27 27 18 9 9 18 134 134 134 1798 1819 3 3 229 230 230 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 /* $OpenBSD: uipc_mbuf2.c,v 1.45 2020/12/12 11:48:54 jan Exp $ */ /* $KAME: uipc_mbuf2.c,v 1.29 2001/02/14 13:42:10 itojun Exp $ */ /* $NetBSD: uipc_mbuf.c,v 1.40 1999/04/01 00:23:25 thorpej Exp $ */ /* * Copyright (C) 1999 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 1982, 1986, 1988, 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)uipc_mbuf.c 8.4 (Berkeley) 2/14/95 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/pool.h> #include <sys/mbuf.h> extern struct pool mtagpool; /* can't call it m_dup(), as freebsd[34] uses m_dup() with different arg */ static struct mbuf *m_dup1(struct mbuf *, int, int, int); /* * ensure that [off, off + len] is contiguous on the mbuf chain "m". * packet chain before "off" is kept untouched. * if offp == NULL, the target will start at <retval, 0> on resulting chain. * if offp != NULL, the target will start at <retval, *offp> on resulting chain. * * on error return (NULL return value), original "m" will be freed. * * XXX m_trailingspace/m_leadingspace on shared cluster (sharedcluster) */ struct mbuf * m_pulldown(struct mbuf *m, int off, int len, int *offp) { struct mbuf *n, *o; int hlen, tlen, olen; int sharedcluster; /* check invalid arguments. */ if (m == NULL) panic("m == NULL in m_pulldown()"); if ((n = m_getptr(m, off, &off)) == NULL) { m_freem(m); return (NULL); /* mbuf chain too short */ } sharedcluster = M_READONLY(n); /* * the target data is on <n, off>. * if we got enough data on the mbuf "n", we're done. */ if ((off == 0 || offp) && len <= n->m_len - off && !sharedcluster) goto ok; /* * when len <= n->m_len - off and off != 0, it is a special case. * len bytes from <n, off> sits in single mbuf, but the caller does * not like the starting position (off). * chop the current mbuf into two pieces, set off to 0. */ if (len <= n->m_len - off) { struct mbuf *mlast; o = m_dup1(n, off, n->m_len - off, M_DONTWAIT); if (o == NULL) { m_freem(m); return (NULL); /* ENOBUFS */ } for (mlast = o; mlast->m_next != NULL; mlast = mlast->m_next) ; n->m_len = off; mlast->m_next = n->m_next; n->m_next = o; n = o; off = 0; goto ok; } /* * we need to take hlen from <n, off> and tlen from <n->m_next, 0>, * and construct contiguous mbuf with m_len == len. * note that hlen + tlen == len, and tlen > 0. */ hlen = n->m_len - off; tlen = len - hlen; /* * ensure that we have enough trailing data on mbuf chain. * if not, we can do nothing about the chain. */ olen = 0; for (o = n->m_next; o != NULL; o = o->m_next) olen += o->m_len; if (hlen + olen < len) { m_freem(m); return (NULL); /* mbuf chain too short */ } /* * easy cases first. * we need to use m_copydata() to get data from <n->m_next, 0>. */ if ((off == 0 || offp) && m_trailingspace(n) >= tlen && !sharedcluster) { m_copydata(n->m_next, 0, tlen, mtod(n, caddr_t) + n->m_len); n->m_len += tlen; m_adj(n->m_next, tlen); goto ok; } if ((off == 0 || offp) && m_leadingspace(n->m_next) >= hlen && !sharedcluster && n->m_next->m_len >= tlen) { n->m_next->m_data -= hlen; n->m_next->m_len += hlen; memmove(mtod(n->m_next, caddr_t), mtod(n, caddr_t) + off, hlen); n->m_len -= hlen; n = n->m_next; off = 0; goto ok; } /* * now, we need to do the hard way. don't m_copym as there's no room * on both ends. */ if (len > MAXMCLBYTES) { m_freem(m); return (NULL); } MGET(o, M_DONTWAIT, m->m_type); if (o && len > MLEN) { MCLGETL(o, M_DONTWAIT, len); if ((o->m_flags & M_EXT) == 0) { m_free(o); o = NULL; } } if (!o) { m_freem(m); return (NULL); /* ENOBUFS */ } /* get hlen from <n, off> into <o, 0> */ o->m_len = hlen; memmove(mtod(o, caddr_t), mtod(n, caddr_t) + off, hlen); n->m_len -= hlen; /* get tlen from <n->m_next, 0> into <o, hlen> */ m_copydata(n->m_next, 0, tlen, mtod(o, caddr_t) + o->m_len); o->m_len += tlen; m_adj(n->m_next, tlen); o->m_next = n->m_next; n->m_next = o; n = o; off = 0; ok: if (offp) *offp = off; return (n); } static struct mbuf * m_dup1(struct mbuf *m, int off, int len, int wait) { struct mbuf *n; int l; if (len > MAXMCLBYTES) return (NULL); if (off == 0 && (m->m_flags & M_PKTHDR) != 0) { MGETHDR(n, wait, m->m_type); if (n == NULL) return (NULL); if (m_dup_pkthdr(n, m, wait)) { m_free(n); return (NULL); } l = MHLEN; } else { MGET(n, wait, m->m_type); l = MLEN; } if (n && len > l) { MCLGETL(n, wait, len); if ((n->m_flags & M_EXT) == 0) { m_free(n); n = NULL; } } if (!n) return (NULL); m_copydata(m, off, len, mtod(n, caddr_t)); n->m_len = len; return (n); } /* Get a packet tag structure along with specified data following. */ struct m_tag * m_tag_get(int type, int len, int wait) { struct m_tag *t; if (len < 0) return (NULL); if (len > PACKET_TAG_MAXSIZE) panic("requested tag size for pool %#x is too big", type); t = pool_get(&mtagpool, wait == M_WAITOK ? PR_WAITOK : PR_NOWAIT); if (t == NULL) return (NULL); t->m_tag_id = type; t->m_tag_len = len; return (t); } /* Prepend a packet tag. */ void m_tag_prepend(struct mbuf *m, struct m_tag *t) { SLIST_INSERT_HEAD(&m->m_pkthdr.ph_tags, t, m_tag_link); m->m_pkthdr.ph_tagsset |= t->m_tag_id; } /* Unlink and free a packet tag. */ void m_tag_delete(struct mbuf *m, struct m_tag *t) { u_int32_t ph_tagsset = 0; struct m_tag *p; SLIST_REMOVE(&m->m_pkthdr.ph_tags, t, m_tag, m_tag_link); pool_put(&mtagpool, t); SLIST_FOREACH(p, &m->m_pkthdr.ph_tags, m_tag_link) ph_tagsset |= p->m_tag_id; m->m_pkthdr.ph_tagsset = ph_tagsset; } /* Unlink and free a packet tag chain. */ void m_tag_delete_chain(struct mbuf *m) { struct m_tag *p; while ((p = SLIST_FIRST(&m->m_pkthdr.ph_tags)) != NULL) { SLIST_REMOVE_HEAD(&m->m_pkthdr.ph_tags, m_tag_link); pool_put(&mtagpool, p); } m->m_pkthdr.ph_tagsset = 0; } /* Find a tag, starting from a given position. */ struct m_tag * m_tag_find(struct mbuf *m, int type, struct m_tag *t) { struct m_tag *p; if (!(m->m_pkthdr.ph_tagsset & type)) return (NULL); if (t == NULL) p = SLIST_FIRST(&m->m_pkthdr.ph_tags); else p = SLIST_NEXT(t, m_tag_link); while (p != NULL) { if (p->m_tag_id == type) return (p); p = SLIST_NEXT(p, m_tag_link); } return (NULL); } /* Copy a single tag. */ struct m_tag * m_tag_copy(struct m_tag *t, int wait) { struct m_tag *p; p = m_tag_get(t->m_tag_id, t->m_tag_len, wait); if (p == NULL) return (NULL); memcpy(p + 1, t + 1, t->m_tag_len); /* Copy the data */ return (p); } /* * Copy two tag chains. The destination mbuf (to) loses any attached * tags even if the operation fails. This should not be a problem, as * m_tag_copy_chain() is typically called with a newly-allocated * destination mbuf. */ int m_tag_copy_chain(struct mbuf *to, struct mbuf *from, int wait) { struct m_tag *p, *t, *tprev = NULL; m_tag_delete_chain(to); SLIST_FOREACH(p, &from->m_pkthdr.ph_tags, m_tag_link) { t = m_tag_copy(p, wait); if (t == NULL) { m_tag_delete_chain(to); return (ENOBUFS); } if (tprev == NULL) SLIST_INSERT_HEAD(&to->m_pkthdr.ph_tags, t, m_tag_link); else SLIST_INSERT_AFTER(tprev, t, m_tag_link); tprev = t; to->m_pkthdr.ph_tagsset |= t->m_tag_id; } return (0); } /* Initialize tags on an mbuf. */ void m_tag_init(struct mbuf *m) { SLIST_INIT(&m->m_pkthdr.ph_tags); } /* Get first tag in chain. */ struct m_tag * m_tag_first(struct mbuf *m) { return (SLIST_FIRST(&m->m_pkthdr.ph_tags)); } /* Get next tag in chain. */ struct m_tag * m_tag_next(struct mbuf *m, struct m_tag *t) { return (SLIST_NEXT(t, m_tag_link)); }
35 22 21 22 33 34 34 34 34 34 22 22 22 16 16 16 16 21 21 15 15 7 7 7 7 17 17 22 22 83 83 84 81 57 57 56 1 1 34 34 34 34 34 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 /* $OpenBSD: pf_if.c,v 1.111 2023/06/30 09:58:30 mvs Exp $ */ /* * Copyright 2005 Henning Brauer <henning@openbsd.org> * Copyright 2005 Ryan McBride <mcbride@openbsd.org> * Copyright (c) 2001 Daniel Hartmeier * Copyright (c) 2003 Cedric Berger * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/filio.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/kernel.h> #include <sys/device.h> #include <sys/time.h> #include <sys/pool.h> #include <sys/syslog.h> #include <net/if.h> #include <net/if_var.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_var.h> #include <net/pfvar.h> #include <netinet/ip_icmp.h> #include <netinet/tcp.h> #include <netinet/udp.h> #ifdef INET6 #include <netinet/ip6.h> #include <netinet/icmp6.h> #endif /* INET6 */ #include <net/pfvar_priv.h> #define isupper(c) ((c) >= 'A' && (c) <= 'Z') #define islower(c) ((c) >= 'a' && (c) <= 'z') #define isalpha(c) (isupper(c)||islower(c)) struct pfi_kif *pfi_all = NULL; struct pool pfi_addr_pl; struct pfi_ifhead pfi_ifs; long pfi_update = 1; struct pfr_addr *pfi_buffer; int pfi_buffer_cnt; int pfi_buffer_max; void pfi_kif_update(struct pfi_kif *); void pfi_dynaddr_update(struct pfi_dynaddr *dyn); void pfi_table_update(struct pfr_ktable *, struct pfi_kif *, u_int8_t, int); void pfi_kifaddr_update(void *); void pfi_instance_add(struct ifnet *, u_int8_t, int); void pfi_address_add(struct sockaddr *, sa_family_t, u_int8_t); int pfi_if_compare(struct pfi_kif *, struct pfi_kif *); int pfi_skip_if(const char *, struct pfi_kif *); int pfi_unmask(void *); void pfi_group_change(const char *); RB_PROTOTYPE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare); RB_GENERATE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare); #define PFI_BUFFER_MAX 0x10000 #define PFI_MTYPE M_PF struct pfi_kif * pfi_kif_alloc(const char *kif_name, int mflags) { struct pfi_kif *kif; kif = malloc(sizeof(*pfi_all), PFI_MTYPE, mflags|M_ZERO); if (kif == NULL) return (NULL); strlcpy(kif->pfik_name, kif_name, sizeof(kif->pfik_name)); kif->pfik_tzero = gettime(); TAILQ_INIT(&kif->pfik_dynaddrs); if (!strcmp(kif->pfik_name, "any")) { /* both so it works in the ioctl and the regular case */ kif->pfik_flags |= PFI_IFLAG_ANY; kif->pfik_flags_new |= PFI_IFLAG_ANY; } return (kif); } void pfi_kif_free(struct pfi_kif *kif) { if (kif == NULL) return; if (kif->pfik_rules || kif->pfik_states || kif->pfik_routes || kif->pfik_srcnodes || kif->pfik_flagrefs) panic("kif is still alive"); free(kif, PFI_MTYPE, sizeof(*kif)); } void pfi_initialize(void) { /* * The first time we arrive here is during kernel boot, * when if_attachsetup() for the first time. No locking * is needed in this case, because it's granted there * is a single thread, which sets pfi_all global var. */ if (pfi_all != NULL) /* already initialized */ return; pool_init(&pfi_addr_pl, sizeof(struct pfi_dynaddr), 0, IPL_SOFTNET, 0, "pfiaddrpl", NULL); pfi_buffer_max = 64; pfi_buffer = mallocarray(pfi_buffer_max, sizeof(*pfi_buffer), PFI_MTYPE, M_WAITOK); pfi_all = pfi_kif_alloc(IFG_ALL, M_WAITOK); if (RB_INSERT(pfi_ifhead, &pfi_ifs, pfi_all) != NULL) panic("IFG_ALL kif found already"); } struct pfi_kif * pfi_kif_find(const char *kif_name) { struct pfi_kif_cmp s; PF_ASSERT_LOCKED(); memset(&s, 0, sizeof(s)); strlcpy(s.pfik_name, kif_name, sizeof(s.pfik_name)); return (RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&s)); } struct pfi_kif * pfi_kif_get(const char *kif_name, struct pfi_kif **prealloc) { struct pfi_kif *kif; PF_ASSERT_LOCKED(); if ((kif = pfi_kif_find(kif_name))) return (kif); /* create new one */ if ((prealloc == NULL) || (*prealloc == NULL)) { kif = pfi_kif_alloc(kif_name, M_NOWAIT); if (kif == NULL) return (NULL); } else { kif = *prealloc; *prealloc = NULL; } RB_INSERT(pfi_ifhead, &pfi_ifs, kif); return (kif); } void pfi_kif_ref(struct pfi_kif *kif, enum pfi_kif_refs what) { PF_ASSERT_LOCKED(); switch (what) { case PFI_KIF_REF_RULE: kif->pfik_rules++; break; case PFI_KIF_REF_STATE: kif->pfik_states++; break; case PFI_KIF_REF_ROUTE: kif->pfik_routes++; break; case PFI_KIF_REF_SRCNODE: kif->pfik_srcnodes++; break; case PFI_KIF_REF_FLAG: kif->pfik_flagrefs++; break; default: panic("pfi_kif_ref with unknown type"); } } void pfi_kif_unref(struct pfi_kif *kif, enum pfi_kif_refs what) { if (kif == NULL) return; PF_ASSERT_LOCKED(); switch (what) { case PFI_KIF_REF_NONE: break; case PFI_KIF_REF_RULE: if (kif->pfik_rules <= 0) { DPFPRINTF(LOG_ERR, "pfi_kif_unref (%s): rules refcount <= 0", kif->pfik_name); return; } kif->pfik_rules--; break; case PFI_KIF_REF_STATE: if (kif->pfik_states <= 0) { DPFPRINTF(LOG_ERR, "pfi_kif_unref (%s): state refcount <= 0", kif->pfik_name); return; } kif->pfik_states--; break; case PFI_KIF_REF_ROUTE: if (kif->pfik_routes <= 0) { DPFPRINTF(LOG_ERR, "pfi_kif_unref (%s): route refcount <= 0", kif->pfik_name); return; } kif->pfik_routes--; break; case PFI_KIF_REF_SRCNODE: if (kif->pfik_srcnodes <= 0) { DPFPRINTF(LOG_ERR, "pfi_kif_unref (%s): src-node refcount <= 0", kif->pfik_name); return; } kif->pfik_srcnodes--; break; case PFI_KIF_REF_FLAG: if (kif->pfik_flagrefs <= 0) { DPFPRINTF(LOG_ERR, "pfi_kif_unref (%s): flags refcount <= 0", kif->pfik_name); return; } kif->pfik_flagrefs--; break; default: panic("pfi_kif_unref (%s) with unknown type", kif->pfik_name); } if (kif->pfik_ifp != NULL || kif->pfik_group != NULL || kif == pfi_all) return; if (kif->pfik_rules || kif->pfik_states || kif->pfik_routes || kif->pfik_srcnodes || kif->pfik_flagrefs) return; RB_REMOVE(pfi_ifhead, &pfi_ifs, kif); free(kif, PFI_MTYPE, sizeof(*kif)); } int pfi_kif_match(struct pfi_kif *rule_kif, struct pfi_kif *packet_kif) { struct ifg_list *p; if (rule_kif == NULL || rule_kif == packet_kif) return (1); if (rule_kif->pfik_group != NULL) TAILQ_FOREACH(p, &packet_kif->pfik_ifp->if_groups, ifgl_next) if (p->ifgl_group == rule_kif->pfik_group) return (1); if (rule_kif->pfik_flags & PFI_IFLAG_ANY && packet_kif->pfik_ifp && !(packet_kif->pfik_ifp->if_flags & IFF_LOOPBACK)) return (1); return (0); } void pfi_attach_ifnet(struct ifnet *ifp) { struct pfi_kif *kif; struct task *t; PF_LOCK(); pfi_initialize(); pfi_update++; if ((kif = pfi_kif_get(ifp->if_xname, NULL)) == NULL) panic("%s: pfi_kif_get failed", __func__); kif->pfik_ifp = ifp; ifp->if_pf_kif = (caddr_t)kif; t = malloc(sizeof(*t), PFI_MTYPE, M_WAITOK); task_set(t, pfi_kifaddr_update, kif); if_addrhook_add(ifp, t); kif->pfik_ah_cookie = t; pfi_kif_update(kif); PF_UNLOCK(); } void pfi_detach_ifnet(struct ifnet *ifp) { struct pfi_kif *kif; struct task *t; if ((kif = (struct pfi_kif *)ifp->if_pf_kif) == NULL) return; PF_LOCK(); pfi_update++; t = kif->pfik_ah_cookie; kif->pfik_ah_cookie = NULL; if_addrhook_del(ifp, t); free(t, PFI_MTYPE, sizeof(*t)); pfi_kif_update(kif); kif->pfik_ifp = NULL; ifp->if_pf_kif = NULL; pfi_kif_unref(kif, PFI_KIF_REF_NONE); PF_UNLOCK(); } void pfi_attach_ifgroup(struct ifg_group *ifg) { struct pfi_kif *kif; PF_LOCK(); pfi_initialize(); pfi_update++; if ((kif = pfi_kif_get(ifg->ifg_group, NULL)) == NULL) panic("%s: pfi_kif_get failed", __func__); kif->pfik_group = ifg; ifg->ifg_pf_kif = (caddr_t)kif; PF_UNLOCK(); } void pfi_detach_ifgroup(struct ifg_group *ifg) { struct pfi_kif *kif; if ((kif = (struct pfi_kif *)ifg->ifg_pf_kif) == NULL) return; PF_LOCK(); pfi_update++; kif->pfik_group = NULL; ifg->ifg_pf_kif = NULL; pfi_kif_unref(kif, PFI_KIF_REF_NONE); PF_UNLOCK(); } void pfi_group_change(const char *group) { struct pfi_kif *kif; pfi_update++; if ((kif = pfi_kif_get(group, NULL)) == NULL) panic("%s: pfi_kif_get failed", __func__); pfi_kif_update(kif); } void pfi_group_delmember(const char *group) { PF_LOCK(); pfi_group_change(group); pfi_xcommit(); PF_UNLOCK(); } void pfi_group_addmember(const char *group) { PF_LOCK(); pfi_group_change(group); pfi_xcommit(); PF_UNLOCK(); } int pfi_match_addr(struct pfi_dynaddr *dyn, struct pf_addr *a, sa_family_t af) { switch (af) { case AF_INET: switch (dyn->pfid_acnt4) { case 0: return (0); case 1: return (pf_match_addr(0, &dyn->pfid_addr4, &dyn->pfid_mask4, a, AF_INET)); default: return (pfr_match_addr(dyn->pfid_kt, a, AF_INET)); } break; #ifdef INET6 case AF_INET6: switch (dyn->pfid_acnt6) { case 0: return (0); case 1: return (pf_match_addr(0, &dyn->pfid_addr6, &dyn->pfid_mask6, a, AF_INET6)); default: return (pfr_match_addr(dyn->pfid_kt, a, AF_INET6)); } break; #endif /* INET6 */ default: return (0); } } int pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af, int wait) { struct pfi_dynaddr *dyn; char tblname[PF_TABLE_NAME_SIZE]; struct pf_ruleset *ruleset = NULL; int rv = 0; if (aw->type != PF_ADDR_DYNIFTL) return (0); if ((dyn = pool_get(&pfi_addr_pl, wait|PR_LIMITFAIL|PR_ZERO)) == NULL) return (1); if (!strcmp(aw->v.ifname, "self")) dyn->pfid_kif = pfi_kif_get(IFG_ALL, NULL); else dyn->pfid_kif = pfi_kif_get(aw->v.ifname, NULL); if (dyn->pfid_kif == NULL) { rv = 1; goto _bad; } pfi_kif_ref(dyn->pfid_kif, PFI_KIF_REF_RULE); dyn->pfid_net = pfi_unmask(&aw->v.a.mask); if (af == AF_INET && dyn->pfid_net == 32) dyn->pfid_net = 128; strlcpy(tblname, aw->v.ifname, sizeof(tblname)); if (aw->iflags & PFI_AFLAG_NETWORK) strlcat(tblname, ":network", sizeof(tblname)); if (aw->iflags & PFI_AFLAG_BROADCAST) strlcat(tblname, ":broadcast", sizeof(tblname)); if (aw->iflags & PFI_AFLAG_PEER) strlcat(tblname, ":peer", sizeof(tblname)); if (aw->iflags & PFI_AFLAG_NOALIAS) strlcat(tblname, ":0", sizeof(tblname)); if (dyn->pfid_net != 128) snprintf(tblname + strlen(tblname), sizeof(tblname) - strlen(tblname), "/%d", dyn->pfid_net); if ((ruleset = pf_find_or_create_ruleset(PF_RESERVED_ANCHOR)) == NULL) { rv = 1; goto _bad; } if ((dyn->pfid_kt = pfr_attach_table(ruleset, tblname, wait)) == NULL) { rv = 1; goto _bad; } dyn->pfid_kt->pfrkt_flags |= PFR_TFLAG_ACTIVE; dyn->pfid_iflags = aw->iflags; dyn->pfid_af = af; TAILQ_INSERT_TAIL(&dyn->pfid_kif->pfik_dynaddrs, dyn, entry); aw->p.dyn = dyn; pfi_kif_update(dyn->pfid_kif); return (0); _bad: if (dyn->pfid_kt != NULL) pfr_detach_table(dyn->pfid_kt); if (ruleset != NULL) pf_remove_if_empty_ruleset(ruleset); if (dyn->pfid_kif != NULL) pfi_kif_unref(dyn->pfid_kif, PFI_KIF_REF_RULE); pool_put(&pfi_addr_pl, dyn); return (rv); } void pfi_kif_update(struct pfi_kif *kif) { struct ifg_list *ifgl; struct pfi_dynaddr *p; /* update all dynaddr */ TAILQ_FOREACH(p, &kif->pfik_dynaddrs, entry) pfi_dynaddr_update(p); /* again for all groups kif is member of */ if (kif->pfik_ifp != NULL) TAILQ_FOREACH(ifgl, &kif->pfik_ifp->if_groups, ifgl_next) pfi_kif_update((struct pfi_kif *) ifgl->ifgl_group->ifg_pf_kif); } void pfi_dynaddr_update(struct pfi_dynaddr *dyn) { struct pfi_kif *kif; struct pfr_ktable *kt; if (dyn == NULL || dyn->pfid_kif == NULL || dyn->pfid_kt == NULL) panic("pfi_dynaddr_update"); kif = dyn->pfid_kif; kt = dyn->pfid_kt; if (kt->pfrkt_larg != pfi_update) { /* this table needs to be brought up-to-date */ pfi_table_update(kt, kif, dyn->pfid_net, dyn->pfid_iflags); kt->pfrkt_larg = pfi_update; } pfr_dynaddr_update(kt, dyn); } void pfi_table_update(struct pfr_ktable *kt, struct pfi_kif *kif, u_int8_t net, int flags) { int e, size2 = 0; struct ifg_member *ifgm; pfi_buffer_cnt = 0; if (kif->pfik_ifp != NULL) pfi_instance_add(kif->pfik_ifp, net, flags); else if (kif->pfik_group != NULL) TAILQ_FOREACH(ifgm, &kif->pfik_group->ifg_members, ifgm_next) pfi_instance_add(ifgm->ifgm_ifp, net, flags); if ((e = pfr_set_addrs(&kt->pfrkt_t, pfi_buffer, pfi_buffer_cnt, &size2, NULL, NULL, NULL, 0, PFR_TFLAG_ALLMASK))) DPFPRINTF(LOG_ERR, "pfi_table_update: cannot set %d new addresses " "into table %s: %d", pfi_buffer_cnt, kt->pfrkt_name, e); } void pfi_instance_add(struct ifnet *ifp, u_int8_t net, int flags) { struct ifaddr *ifa; int got4 = 0, got6 = 0; int net2, af; if (ifp == NULL) return; TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr == NULL) continue; af = ifa->ifa_addr->sa_family; if (af != AF_INET && af != AF_INET6) continue; if ((flags & PFI_AFLAG_BROADCAST) && af == AF_INET6) continue; if ((flags & PFI_AFLAG_BROADCAST) && !(ifp->if_flags & IFF_BROADCAST)) continue; if ((flags & PFI_AFLAG_PEER) && !(ifp->if_flags & IFF_POINTOPOINT)) continue; if ((flags & PFI_AFLAG_NETWORK) && af == AF_INET6 && IN6_IS_ADDR_LINKLOCAL( &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) continue; if (flags & PFI_AFLAG_NOALIAS) { if (af == AF_INET && got4) continue; if (af == AF_INET6 && got6) continue; } if (af == AF_INET) got4 = 1; else if (af == AF_INET6) got6 = 1; net2 = net; if (net2 == 128 && (flags & PFI_AFLAG_NETWORK)) { if (af == AF_INET) net2 = pfi_unmask(&((struct sockaddr_in *) ifa->ifa_netmask)->sin_addr); else if (af == AF_INET6) net2 = pfi_unmask(&((struct sockaddr_in6 *) ifa->ifa_netmask)->sin6_addr); } if (af == AF_INET && net2 > 32) net2 = 32; if (flags & PFI_AFLAG_BROADCAST) pfi_address_add(ifa->ifa_broadaddr, af, net2); else if (flags & PFI_AFLAG_PEER) pfi_address_add(ifa->ifa_dstaddr, af, net2); else pfi_address_add(ifa->ifa_addr, af, net2); } } void pfi_address_add(struct sockaddr *sa, sa_family_t af, u_int8_t net) { struct pfr_addr *p; int i; if (pfi_buffer_cnt >= pfi_buffer_max) { int new_max = pfi_buffer_max * 2; if (new_max > PFI_BUFFER_MAX) { DPFPRINTF(LOG_ERR, "pfi_address_add: address buffer full (%d/%d)", pfi_buffer_cnt, PFI_BUFFER_MAX); return; } p = mallocarray(new_max, sizeof(*pfi_buffer), PFI_MTYPE, M_DONTWAIT); if (p == NULL) { DPFPRINTF(LOG_ERR, "pfi_address_add: no memory to grow buffer " "(%d/%d)", pfi_buffer_cnt, PFI_BUFFER_MAX); return; } memcpy(p, pfi_buffer, pfi_buffer_max * sizeof(*pfi_buffer)); /* no need to zero buffer */ free(pfi_buffer, PFI_MTYPE, pfi_buffer_max * sizeof(*pfi_buffer)); pfi_buffer = p; pfi_buffer_max = new_max; } if (af == AF_INET && net > 32) net = 128; p = pfi_buffer + pfi_buffer_cnt++; memset(p, 0, sizeof(*p)); p->pfra_af = af; p->pfra_net = net; if (af == AF_INET) p->pfra_ip4addr = ((struct sockaddr_in *)sa)->sin_addr; else if (af == AF_INET6) { p->pfra_ip6addr = ((struct sockaddr_in6 *)sa)->sin6_addr; if (IN6_IS_SCOPE_EMBED(&p->pfra_ip6addr)) p->pfra_ip6addr.s6_addr16[1] = 0; } /* mask network address bits */ if (net < 128) ((caddr_t)p)[p->pfra_net/8] &= ~(0xFF >> (p->pfra_net%8)); for (i = (p->pfra_net+7)/8; i < sizeof(p->pfra_u); i++) ((caddr_t)p)[i] = 0; } void pfi_dynaddr_remove(struct pf_addr_wrap *aw) { if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL || aw->p.dyn->pfid_kif == NULL || aw->p.dyn->pfid_kt == NULL) return; TAILQ_REMOVE(&aw->p.dyn->pfid_kif->pfik_dynaddrs, aw->p.dyn, entry); pfi_kif_unref(aw->p.dyn->pfid_kif, PFI_KIF_REF_RULE); aw->p.dyn->pfid_kif = NULL; pfr_detach_table(aw->p.dyn->pfid_kt); aw->p.dyn->pfid_kt = NULL; pool_put(&pfi_addr_pl, aw->p.dyn); aw->p.dyn = NULL; } void pfi_dynaddr_copyout(struct pf_addr_wrap *aw) { if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL || aw->p.dyn->pfid_kif == NULL) return; aw->p.dyncnt = aw->p.dyn->pfid_acnt4 + aw->p.dyn->pfid_acnt6; } void pfi_kifaddr_update(void *v) { struct pfi_kif *kif = (struct pfi_kif *)v; NET_ASSERT_LOCKED(); PF_LOCK(); pfi_update++; pfi_kif_update(kif); PF_UNLOCK(); } int pfi_if_compare(struct pfi_kif *p, struct pfi_kif *q) { return (strncmp(p->pfik_name, q->pfik_name, IFNAMSIZ)); } void pfi_update_status(const char *name, struct pf_status *pfs) { struct pfi_kif *p; struct pfi_kif_cmp key; struct ifg_member p_member, *ifgm; TAILQ_HEAD(, ifg_member) ifg_members; int i, j, k; if (*name == '\0' && pfs == NULL) { RB_FOREACH(p, pfi_ifhead, &pfi_ifs) { memset(p->pfik_packets, 0, sizeof(p->pfik_packets)); memset(p->pfik_bytes, 0, sizeof(p->pfik_bytes)); p->pfik_tzero = gettime(); } return; } strlcpy(key.pfik_name, name, sizeof(key.pfik_name)); p = RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&key); if (p == NULL) { return; } if (p->pfik_group != NULL) { memcpy(&ifg_members, &p->pfik_group->ifg_members, sizeof(ifg_members)); } else { /* build a temporary list for p only */ memset(&p_member, 0, sizeof(p_member)); p_member.ifgm_ifp = p->pfik_ifp; TAILQ_INIT(&ifg_members); TAILQ_INSERT_TAIL(&ifg_members, &p_member, ifgm_next); } if (pfs) { memset(pfs->pcounters, 0, sizeof(pfs->pcounters)); memset(pfs->bcounters, 0, sizeof(pfs->bcounters)); } TAILQ_FOREACH(ifgm, &ifg_members, ifgm_next) { if (ifgm->ifgm_ifp == NULL) continue; p = (struct pfi_kif *)ifgm->ifgm_ifp->if_pf_kif; /* just clear statistics */ if (pfs == NULL) { memset(p->pfik_packets, 0, sizeof(p->pfik_packets)); memset(p->pfik_bytes, 0, sizeof(p->pfik_bytes)); p->pfik_tzero = gettime(); continue; } for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) for (k = 0; k < 2; k++) { pfs->pcounters[i][j][k] += p->pfik_packets[i][j][k]; pfs->bcounters[i][j] += p->pfik_bytes[i][j][k]; } } } void pfi_get_ifaces(const char *name, struct pfi_kif *buf, int *size) { struct pfi_kif *p; int n = 0; RB_FOREACH(p, pfi_ifhead, &pfi_ifs) { if (pfi_skip_if(name, p)) continue; if (*size <= ++n) break; if (!p->pfik_tzero) p->pfik_tzero = gettime(); memcpy(buf++, p, sizeof(*buf)); } *size = n; } int pfi_skip_if(const char *filter, struct pfi_kif *p) { struct ifg_list *i; int n; PF_ASSERT_LOCKED(); if (filter == NULL || !*filter) return (0); if (!strcmp(p->pfik_name, filter)) return (0); /* exact match */ n = strlen(filter); if (n < 1 || n >= IFNAMSIZ) return (1); /* sanity check */ if (filter[n-1] >= '0' && filter[n-1] <= '9') return (1); /* group names may not end in a digit */ if (p->pfik_ifp != NULL) TAILQ_FOREACH(i, &p->pfik_ifp->if_groups, ifgl_next) if (!strncmp(i->ifgl_group->ifg_group, filter, IFNAMSIZ)) return (0); /* iface is in group "filter" */ return (1); } int pfi_set_flags(const char *name, int flags) { struct pfi_kif *p; size_t n; PF_ASSERT_LOCKED(); if (name != NULL && name[0] != '\0') { p = pfi_kif_find(name); if (p == NULL) { n = strlen(name); if (n < 1 || n >= IFNAMSIZ) return (EINVAL); if (!isalpha(name[0])) return (EINVAL); p = pfi_kif_get(name, NULL); if (p != NULL) { p->pfik_flags_new = p->pfik_flags | flags; /* * We use pfik_flagrefs counter as an * indication whether the kif has been created * on behalf of 'pfi_set_flags()' or not. */ KASSERT(p->pfik_flagrefs == 0); if (ISSET(p->pfik_flags_new, PFI_IFLAG_SKIP)) pfi_kif_ref(p, PFI_KIF_REF_FLAG); } else panic("%s pfi_kif_get() returned NULL\n", __func__); } else p->pfik_flags_new = p->pfik_flags | flags; } else { RB_FOREACH(p, pfi_ifhead, &pfi_ifs) p->pfik_flags_new = p->pfik_flags | flags; } return (0); } int pfi_clear_flags(const char *name, int flags) { struct pfi_kif *p, *w; PF_ASSERT_LOCKED(); if (name != NULL && name[0] != '\0') { p = pfi_kif_find(name); if (p != NULL) { p->pfik_flags_new = p->pfik_flags & ~flags; KASSERT((p->pfik_flagrefs == 0) || (p->pfik_flagrefs == 1)); if (!ISSET(p->pfik_flags_new, PFI_IFLAG_SKIP) && (p->pfik_flagrefs == 1)) pfi_kif_unref(p, PFI_KIF_REF_FLAG); } else return (ESRCH); } else RB_FOREACH_SAFE(p, pfi_ifhead, &pfi_ifs, w) { p->pfik_flags_new = p->pfik_flags & ~flags; KASSERT((p->pfik_flagrefs == 0) || (p->pfik_flagrefs == 1)); if (!ISSET(p->pfik_flags_new, PFI_IFLAG_SKIP) && (p->pfik_flagrefs == 1)) pfi_kif_unref(p, PFI_KIF_REF_FLAG); } return (0); } void pfi_xcommit(void) { struct pfi_kif *p, *gkif; struct ifg_list *g; struct ifnet *ifp; size_t n; PF_ASSERT_LOCKED(); RB_FOREACH(p, pfi_ifhead, &pfi_ifs) { p->pfik_flags = p->pfik_flags_new; n = strlen(p->pfik_name); ifp = p->pfik_ifp; /* * if kif is backed by existing interface, then we must use * skip flags found in groups. We use pfik_flags_new, otherwise * we would need to do two RB_FOREACH() passes: the first to * commit group changes the second to commit flag changes for * interfaces. */ if (ifp != NULL) TAILQ_FOREACH(g, &ifp->if_groups, ifgl_next) { gkif = (struct pfi_kif *)g->ifgl_group->ifg_pf_kif; KASSERT(gkif != NULL); p->pfik_flags |= gkif->pfik_flags_new; } } } /* from pf_print_state.c */ int pfi_unmask(void *addr) { struct pf_addr *m = addr; int i = 31, j = 0, b = 0; u_int32_t tmp; while (j < 4 && m->addr32[j] == 0xffffffff) { b += 32; j++; } if (j < 4) { tmp = ntohl(m->addr32[j]); for (i = 31; tmp & (1 << i); --i) b++; } return (b); }
13 33 13 7 35 35 33 2 4 5 5 2 3 4 5 5 46 33 13 53 40 9 5 5 1 4 8 8 1 7 4 4 2 4 2 23 3 2 23 20 23 23 34 35 5 1 1 4 4 5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 /* $OpenBSD: uvm_aobj.c,v 1.110 2024/04/13 23:44:11 jsg Exp $ */ /* $NetBSD: uvm_aobj.c,v 1.39 2001/02/18 21:19:08 chs Exp $ */ /* * Copyright (c) 1998 Chuck Silvers, Charles D. Cranor and * Washington University. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * from: Id: uvm_aobj.c,v 1.1.2.5 1998/02/06 05:14:38 chs Exp */ /* * uvm_aobj.c: anonymous memory uvm_object pager * * author: Chuck Silvers <chuq@chuq.com> * started: Jan-1998 * * - design mostly from Chuck Cranor */ #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/kernel.h> #include <sys/pool.h> #include <sys/stdint.h> #include <sys/atomic.h> #include <uvm/uvm.h> /* * An anonymous UVM object (aobj) manages anonymous-memory. In addition to * keeping the list of resident pages, it may also keep a list of allocated * swap blocks. Depending on the size of the object, this list is either * stored in an array (small objects) or in a hash table (large objects). */ /* * Note: for hash tables, we break the address space of the aobj into blocks * of UAO_SWHASH_CLUSTER_SIZE pages, which shall be a power of two. */ #define UAO_SWHASH_CLUSTER_SHIFT 4 #define UAO_SWHASH_CLUSTER_SIZE (1 << UAO_SWHASH_CLUSTER_SHIFT) /* Get the "tag" for this page index. */ #define UAO_SWHASH_ELT_TAG(idx) ((idx) >> UAO_SWHASH_CLUSTER_SHIFT) #define UAO_SWHASH_ELT_PAGESLOT_IDX(idx) \ ((idx) & (UAO_SWHASH_CLUSTER_SIZE - 1)) /* Given an ELT and a page index, find the swap slot. */ #define UAO_SWHASH_ELT_PAGESLOT(elt, idx) \ ((elt)->slots[UAO_SWHASH_ELT_PAGESLOT_IDX(idx)]) /* Given an ELT, return its pageidx base. */ #define UAO_SWHASH_ELT_PAGEIDX_BASE(elt) \ ((elt)->tag << UAO_SWHASH_CLUSTER_SHIFT) /* The hash function. */ #define UAO_SWHASH_HASH(aobj, idx) \ (&(aobj)->u_swhash[(((idx) >> UAO_SWHASH_CLUSTER_SHIFT) \ & (aobj)->u_swhashmask)]) /* * The threshold which determines whether we will use an array or a * hash table to store the list of allocated swap blocks. */ #define UAO_SWHASH_THRESHOLD (UAO_SWHASH_CLUSTER_SIZE * 4) #define UAO_USES_SWHASH(aobj) \ ((aobj)->u_pages > UAO_SWHASH_THRESHOLD) /* The number of buckets in a hash, with an upper bound. */ #define UAO_SWHASH_MAXBUCKETS 256 #define UAO_SWHASH_BUCKETS(pages) \ (min((pages) >> UAO_SWHASH_CLUSTER_SHIFT, UAO_SWHASH_MAXBUCKETS)) /* * uao_swhash_elt: when a hash table is being used, this structure defines * the format of an entry in the bucket list. */ struct uao_swhash_elt { LIST_ENTRY(uao_swhash_elt) list; /* the hash list */ voff_t tag; /* our 'tag' */ int count; /* our number of active slots */ int slots[UAO_SWHASH_CLUSTER_SIZE]; /* the slots */ }; /* * uao_swhash: the swap hash table structure */ LIST_HEAD(uao_swhash, uao_swhash_elt); /* * uao_swhash_elt_pool: pool of uao_swhash_elt structures */ struct pool uao_swhash_elt_pool; /* * uvm_aobj: the actual anon-backed uvm_object * * => the uvm_object is at the top of the structure, this allows * (struct uvm_aobj *) == (struct uvm_object *) * => only one of u_swslots and u_swhash is used in any given aobj */ struct uvm_aobj { struct uvm_object u_obj; /* has: pgops, memt, #pages, #refs */ int u_pages; /* number of pages in entire object */ int u_flags; /* the flags (see uvm_aobj.h) */ /* * Either an array or hashtable (array of bucket heads) of * offset -> swapslot mappings for the aobj. */ #define u_swslots u_swap.slot_array #define u_swhash u_swap.slot_hash union swslots { int *slot_array; struct uao_swhash *slot_hash; } u_swap; u_long u_swhashmask; /* mask for hashtable */ LIST_ENTRY(uvm_aobj) u_list; /* global list of aobjs */ }; struct pool uvm_aobj_pool; static struct uao_swhash_elt *uao_find_swhash_elt(struct uvm_aobj *, int, boolean_t); static boolean_t uao_flush(struct uvm_object *, voff_t, voff_t, int); static void uao_free(struct uvm_aobj *); static int uao_get(struct uvm_object *, voff_t, vm_page_t *, int *, int, vm_prot_t, int, int); static boolean_t uao_pagein(struct uvm_aobj *, int, int); static boolean_t uao_pagein_page(struct uvm_aobj *, int); void uao_dropswap_range(struct uvm_object *, voff_t, voff_t); void uao_shrink_flush(struct uvm_object *, int, int); int uao_shrink_hash(struct uvm_object *, int); int uao_shrink_array(struct uvm_object *, int); int uao_shrink_convert(struct uvm_object *, int); int uao_grow_hash(struct uvm_object *, int); int uao_grow_array(struct uvm_object *, int); int uao_grow_convert(struct uvm_object *, int); /* * aobj_pager * * note that some functions (e.g. put) are handled elsewhere */ const struct uvm_pagerops aobj_pager = { .pgo_reference = uao_reference, .pgo_detach = uao_detach, .pgo_flush = uao_flush, .pgo_get = uao_get, }; /* * uao_list: global list of active aobjs, locked by uao_list_lock * * Lock ordering: generally the locking order is object lock, then list lock. * in the case of swap off we have to iterate over the list, and thus the * ordering is reversed. In that case we must use trylocking to prevent * deadlock. */ static LIST_HEAD(aobjlist, uvm_aobj) uao_list = LIST_HEAD_INITIALIZER(uao_list); static struct mutex uao_list_lock = MUTEX_INITIALIZER(IPL_MPFLOOR); /* * functions */ /* * hash table/array related functions */ /* * uao_find_swhash_elt: find (or create) a hash table entry for a page * offset. */ static struct uao_swhash_elt * uao_find_swhash_elt(struct uvm_aobj *aobj, int pageidx, boolean_t create) { struct uao_swhash *swhash; struct uao_swhash_elt *elt; voff_t page_tag; swhash = UAO_SWHASH_HASH(aobj, pageidx); /* first hash to get bucket */ page_tag = UAO_SWHASH_ELT_TAG(pageidx); /* tag to search for */ /* * now search the bucket for the requested tag */ LIST_FOREACH(elt, swhash, list) { if (elt->tag == page_tag) return elt; } if (!create) return NULL; /* * allocate a new entry for the bucket and init/insert it in */ elt = pool_get(&uao_swhash_elt_pool, PR_NOWAIT | PR_ZERO); /* * XXX We cannot sleep here as the hash table might disappear * from under our feet. And we run the risk of deadlocking * the pagedeamon. In fact this code will only be called by * the pagedaemon and allocation will only fail if we * exhausted the pagedeamon reserve. In that case we're * doomed anyway, so panic. */ if (elt == NULL) panic("%s: can't allocate entry", __func__); LIST_INSERT_HEAD(swhash, elt, list); elt->tag = page_tag; return elt; } /* * uao_find_swslot: find the swap slot number for an aobj/pageidx */ int uao_find_swslot(struct uvm_object *uobj, int pageidx) { struct uvm_aobj *aobj = (struct uvm_aobj *)uobj; KASSERT(UVM_OBJ_IS_AOBJ(uobj)); /* * if noswap flag is set, then we never return a slot */ if (aobj->u_flags & UAO_FLAG_NOSWAP) return 0; /* * if hashing, look in hash table. */ if (UAO_USES_SWHASH(aobj)) { struct uao_swhash_elt *elt = uao_find_swhash_elt(aobj, pageidx, FALSE); if (elt) return UAO_SWHASH_ELT_PAGESLOT(elt, pageidx); else return 0; } /* * otherwise, look in the array */ return aobj->u_swslots[pageidx]; } /* * uao_set_swslot: set the swap slot for a page in an aobj. * * => setting a slot to zero frees the slot * => object must be locked by caller * => we return the old slot number, or -1 if we failed to allocate * memory to record the new slot number */ int uao_set_swslot(struct uvm_object *uobj, int pageidx, int slot) { struct uvm_aobj *aobj = (struct uvm_aobj *)uobj; int oldslot; KASSERT(rw_write_held(uobj->vmobjlock) || uobj->uo_refs == 0); KASSERT(UVM_OBJ_IS_AOBJ(uobj)); /* * if noswap flag is set, then we can't set a slot */ if (aobj->u_flags & UAO_FLAG_NOSWAP) { if (slot == 0) return 0; /* a clear is ok */ /* but a set is not */ printf("uao_set_swslot: uobj = %p\n", uobj); panic("uao_set_swslot: attempt to set a slot on a NOSWAP object"); } /* * are we using a hash table? if so, add it in the hash. */ if (UAO_USES_SWHASH(aobj)) { /* * Avoid allocating an entry just to free it again if * the page had not swap slot in the first place, and * we are freeing. */ struct uao_swhash_elt *elt = uao_find_swhash_elt(aobj, pageidx, slot ? TRUE : FALSE); if (elt == NULL) { KASSERT(slot == 0); return 0; } oldslot = UAO_SWHASH_ELT_PAGESLOT(elt, pageidx); UAO_SWHASH_ELT_PAGESLOT(elt, pageidx) = slot; /* * now adjust the elt's reference counter and free it if we've * dropped it to zero. */ if (slot) { if (oldslot == 0) elt->count++; } else { if (oldslot) elt->count--; if (elt->count == 0) { LIST_REMOVE(elt, list); pool_put(&uao_swhash_elt_pool, elt); } } } else { /* we are using an array */ oldslot = aobj->u_swslots[pageidx]; aobj->u_swslots[pageidx] = slot; } return oldslot; } /* * end of hash/array functions */ /* * uao_free: free all resources held by an aobj, and then free the aobj * * => the aobj should be dead */ static void uao_free(struct uvm_aobj *aobj) { struct uvm_object *uobj = &aobj->u_obj; KASSERT(UVM_OBJ_IS_AOBJ(uobj)); KASSERT(rw_write_held(uobj->vmobjlock)); uao_dropswap_range(uobj, 0, 0); rw_exit(uobj->vmobjlock); if (UAO_USES_SWHASH(aobj)) { /* * free the hash table itself. */ hashfree(aobj->u_swhash, UAO_SWHASH_BUCKETS(aobj->u_pages), M_UVMAOBJ); } else { free(aobj->u_swslots, M_UVMAOBJ, aobj->u_pages * sizeof(int)); } /* * finally free the aobj itself */ uvm_obj_destroy(uobj); pool_put(&uvm_aobj_pool, aobj); } /* * pager functions */ #ifdef TMPFS /* * Shrink an aobj to a given number of pages. The procedure is always the same: * assess the necessity of data structure conversion (hash to array), secure * resources, flush pages and drop swap slots. * */ void uao_shrink_flush(struct uvm_object *uobj, int startpg, int endpg) { KASSERT(startpg < endpg); KASSERT(uobj->uo_refs == 1); uao_flush(uobj, (voff_t)startpg << PAGE_SHIFT, (voff_t)endpg << PAGE_SHIFT, PGO_FREE); uao_dropswap_range(uobj, startpg, endpg); } int uao_shrink_hash(struct uvm_object *uobj, int pages) { struct uvm_aobj *aobj = (struct uvm_aobj *)uobj; struct uao_swhash *new_swhash; struct uao_swhash_elt *elt; unsigned long new_hashmask; int i; KASSERT(UAO_USES_SWHASH(aobj)); /* * If the size of the hash table doesn't change, all we need to do is * to adjust the page count. */ if (UAO_SWHASH_BUCKETS(aobj->u_pages) == UAO_SWHASH_BUCKETS(pages)) { uao_shrink_flush(uobj, pages, aobj->u_pages); aobj->u_pages = pages; return 0; } new_swhash = hashinit(UAO_SWHASH_BUCKETS(pages), M_UVMAOBJ, M_WAITOK | M_CANFAIL, &new_hashmask); if (new_swhash == NULL) return ENOMEM; uao_shrink_flush(uobj, pages, aobj->u_pages); /* * Even though the hash table size is changing, the hash of the buckets * we are interested in copying should not change. */ for (i = 0; i < UAO_SWHASH_BUCKETS(aobj->u_pages); i++) { while (LIST_EMPTY(&aobj->u_swhash[i]) == 0) { elt = LIST_FIRST(&aobj->u_swhash[i]); LIST_REMOVE(elt, list); LIST_INSERT_HEAD(&new_swhash[i], elt, list); } } hashfree(aobj->u_swhash, UAO_SWHASH_BUCKETS(aobj->u_pages), M_UVMAOBJ); aobj->u_swhash = new_swhash; aobj->u_pages = pages; aobj->u_swhashmask = new_hashmask; return 0; } int uao_shrink_convert(struct uvm_object *uobj, int pages) { struct uvm_aobj *aobj = (struct uvm_aobj *)uobj; struct uao_swhash_elt *elt; int i, *new_swslots; new_swslots = mallocarray(pages, sizeof(int), M_UVMAOBJ, M_WAITOK | M_CANFAIL | M_ZERO); if (new_swslots == NULL) return ENOMEM; uao_shrink_flush(uobj, pages, aobj->u_pages); /* Convert swap slots from hash to array. */ for (i = 0; i < pages; i++) { elt = uao_find_swhash_elt(aobj, i, FALSE); if (elt != NULL) { new_swslots[i] = UAO_SWHASH_ELT_PAGESLOT(elt, i); if (new_swslots[i] != 0) elt->count--; if (elt->count == 0) { LIST_REMOVE(elt, list); pool_put(&uao_swhash_elt_pool, elt); } } } hashfree(aobj->u_swhash, UAO_SWHASH_BUCKETS(aobj->u_pages), M_UVMAOBJ); aobj->u_swslots = new_swslots; aobj->u_pages = pages; return 0; } int uao_shrink_array(struct uvm_object *uobj, int pages) { struct uvm_aobj *aobj = (struct uvm_aobj *)uobj; int i, *new_swslots; new_swslots = mallocarray(pages, sizeof(int), M_UVMAOBJ, M_WAITOK | M_CANFAIL | M_ZERO); if (new_swslots == NULL) return ENOMEM; uao_shrink_flush(uobj, pages, aobj->u_pages); for (i = 0; i < pages; i++) new_swslots[i] = aobj->u_swslots[i]; free(aobj->u_swslots, M_UVMAOBJ, aobj->u_pages * sizeof(int)); aobj->u_swslots = new_swslots; aobj->u_pages = pages; return 0; } int uao_shrink(struct uvm_object *uobj, int pages) { struct uvm_aobj *aobj = (struct uvm_aobj *)uobj; KASSERT(pages < aobj->u_pages); /* * Distinguish between three possible cases: * 1. aobj uses hash and must be converted to array. * 2. aobj uses array and array size needs to be adjusted. * 3. aobj uses hash and hash size needs to be adjusted. */ if (pages > UAO_SWHASH_THRESHOLD) return uao_shrink_hash(uobj, pages); /* case 3 */ else if (aobj->u_pages > UAO_SWHASH_THRESHOLD) return uao_shrink_convert(uobj, pages); /* case 1 */ else return uao_shrink_array(uobj, pages); /* case 2 */ } /* * Grow an aobj to a given number of pages. Right now we only adjust the swap * slots. We could additionally handle page allocation directly, so that they * don't happen through uvm_fault(). That would allow us to use another * mechanism for the swap slots other than malloc(). It is thus mandatory that * the caller of these functions does not allow faults to happen in case of * growth error. */ int uao_grow_array(struct uvm_object *uobj, int pages) { struct uvm_aobj *aobj = (struct uvm_aobj *)uobj; int i, *new_swslots; KASSERT(aobj->u_pages <= UAO_SWHASH_THRESHOLD); new_swslots = mallocarray(pages, sizeof(int), M_UVMAOBJ, M_WAITOK | M_CANFAIL | M_ZERO); if (new_swslots == NULL) return ENOMEM; for (i = 0; i < aobj->u_pages; i++) new_swslots[i] = aobj->u_swslots[i]; free(aobj->u_swslots, M_UVMAOBJ, aobj->u_pages * sizeof(int)); aobj->u_swslots = new_swslots; aobj->u_pages = pages; return 0; } int uao_grow_hash(struct uvm_object *uobj, int pages) { struct uvm_aobj *aobj = (struct uvm_aobj *)uobj; struct uao_swhash *new_swhash; struct uao_swhash_elt *elt; unsigned long new_hashmask; int i; KASSERT(pages > UAO_SWHASH_THRESHOLD); /* * If the size of the hash table doesn't change, all we need to do is * to adjust the page count. */ if (UAO_SWHASH_BUCKETS(aobj->u_pages) == UAO_SWHASH_BUCKETS(pages)) { aobj->u_pages = pages; return 0; } KASSERT(UAO_SWHASH_BUCKETS(aobj->u_pages) < UAO_SWHASH_BUCKETS(pages)); new_swhash = hashinit(UAO_SWHASH_BUCKETS(pages), M_UVMAOBJ, M_WAITOK | M_CANFAIL, &new_hashmask); if (new_swhash == NULL) return ENOMEM; for (i = 0; i < UAO_SWHASH_BUCKETS(aobj->u_pages); i++) { while (LIST_EMPTY(&aobj->u_swhash[i]) == 0) { elt = LIST_FIRST(&aobj->u_swhash[i]); LIST_REMOVE(elt, list); LIST_INSERT_HEAD(&new_swhash[i], elt, list); } } hashfree(aobj->u_swhash, UAO_SWHASH_BUCKETS(aobj->u_pages), M_UVMAOBJ); aobj->u_swhash = new_swhash; aobj->u_pages = pages; aobj->u_swhashmask = new_hashmask; return 0; } int uao_grow_convert(struct uvm_object *uobj, int pages) { struct uvm_aobj *aobj = (struct uvm_aobj *)uobj; struct uao_swhash *new_swhash; struct uao_swhash_elt *elt; unsigned long new_hashmask; int i, *old_swslots; new_swhash = hashinit(UAO_SWHASH_BUCKETS(pages), M_UVMAOBJ, M_WAITOK | M_CANFAIL, &new_hashmask); if (new_swhash == NULL) return ENOMEM; /* Set these now, so we can use uao_find_swhash_elt(). */ old_swslots = aobj->u_swslots; aobj->u_swhash = new_swhash; aobj->u_swhashmask = new_hashmask; for (i = 0; i < aobj->u_pages; i++) { if (old_swslots[i] != 0) { elt = uao_find_swhash_elt(aobj, i, TRUE); elt->count++; UAO_SWHASH_ELT_PAGESLOT(elt, i) = old_swslots[i]; } } free(old_swslots, M_UVMAOBJ, aobj->u_pages * sizeof(int)); aobj->u_pages = pages; return 0; } int uao_grow(struct uvm_object *uobj, int pages) { struct uvm_aobj *aobj = (struct uvm_aobj *)uobj; KASSERT(pages > aobj->u_pages); /* * Distinguish between three possible cases: * 1. aobj uses hash and hash size needs to be adjusted. * 2. aobj uses array and array size needs to be adjusted. * 3. aobj uses array and must be converted to hash. */ if (pages <= UAO_SWHASH_THRESHOLD) return uao_grow_array(uobj, pages); /* case 2 */ else if (aobj->u_pages > UAO_SWHASH_THRESHOLD) return uao_grow_hash(uobj, pages); /* case 1 */ else return uao_grow_convert(uobj, pages); } #endif /* TMPFS */ /* * uao_create: create an aobj of the given size and return its uvm_object. * * => for normal use, flags are zero or UAO_FLAG_CANFAIL. * => for the kernel object, the flags are: * UAO_FLAG_KERNOBJ - allocate the kernel object (can only happen once) * UAO_FLAG_KERNSWAP - enable swapping of kernel object (" ") */ struct uvm_object * uao_create(vsize_t size, int flags) { static struct uvm_aobj kernel_object_store; static struct rwlock bootstrap_kernel_object_lock; static int kobj_alloced = 0; int pages = round_page(size) >> PAGE_SHIFT; struct uvm_aobj *aobj; int refs; /* * Allocate a new aobj, unless kernel object is requested. */ if (flags & UAO_FLAG_KERNOBJ) { KASSERT(!kobj_alloced); aobj = &kernel_object_store; aobj->u_pages = pages; aobj->u_flags = UAO_FLAG_NOSWAP; refs = UVM_OBJ_KERN; kobj_alloced = UAO_FLAG_KERNOBJ; } else if (flags & UAO_FLAG_KERNSWAP) { KASSERT(kobj_alloced == UAO_FLAG_KERNOBJ); aobj = &kernel_object_store; kobj_alloced = UAO_FLAG_KERNSWAP; } else { aobj = pool_get(&uvm_aobj_pool, PR_WAITOK); aobj->u_pages = pages; aobj->u_flags = 0; refs = 1; } /* * allocate hash/array if necessary */ if (flags == 0 || (flags & (UAO_FLAG_KERNSWAP | UAO_FLAG_CANFAIL))) { int mflags; if (flags) mflags = M_NOWAIT; else mflags = M_WAITOK; /* allocate hash table or array depending on object size */ if (UAO_USES_SWHASH(aobj)) { aobj->u_swhash = hashinit(UAO_SWHASH_BUCKETS(pages), M_UVMAOBJ, mflags, &aobj->u_swhashmask); if (aobj->u_swhash == NULL) { if (flags & UAO_FLAG_CANFAIL) { pool_put(&uvm_aobj_pool, aobj); return NULL; } panic("uao_create: hashinit swhash failed"); } } else { aobj->u_swslots = mallocarray(pages, sizeof(int), M_UVMAOBJ, mflags|M_ZERO); if (aobj->u_swslots == NULL) { if (flags & UAO_FLAG_CANFAIL) { pool_put(&uvm_aobj_pool, aobj); return NULL; } panic("uao_create: malloc swslots failed"); } } if (flags & UAO_FLAG_KERNSWAP) { aobj->u_flags &= ~UAO_FLAG_NOSWAP; /* clear noswap */ return &aobj->u_obj; /* done! */ } } /* * Initialise UVM object. */ uvm_obj_init(&aobj->u_obj, &aobj_pager, refs); if (flags & UAO_FLAG_KERNOBJ) { /* Use a temporary static lock for kernel_object. */ rw_init(&bootstrap_kernel_object_lock, "kobjlk"); uvm_obj_setlock(&aobj->u_obj, &bootstrap_kernel_object_lock); } /* * now that aobj is ready, add it to the global list */ mtx_enter(&uao_list_lock); LIST_INSERT_HEAD(&uao_list, aobj, u_list); mtx_leave(&uao_list_lock); return &aobj->u_obj; } /* * uao_init: set up aobj pager subsystem * * => called at boot time from uvm_pager_init() */ void uao_init(void) { /* * NOTE: Pages for this pool must not come from a pageable * kernel map! */ pool_init(&uao_swhash_elt_pool, sizeof(struct uao_swhash_elt), 0, IPL_NONE, PR_WAITOK, "uaoeltpl", NULL); pool_init(&uvm_aobj_pool, sizeof(struct uvm_aobj), 0, IPL_NONE, PR_WAITOK, "aobjpl", NULL); } /* * uao_reference: hold a reference to an anonymous UVM object. */ void uao_reference(struct uvm_object *uobj) { /* Kernel object is persistent. */ if (UVM_OBJ_IS_KERN_OBJECT(uobj)) return; atomic_inc_int(&uobj->uo_refs); } /* * uao_detach: drop a reference to an anonymous UVM object. */ void uao_detach(struct uvm_object *uobj) { struct uvm_aobj *aobj = (struct uvm_aobj *)uobj; struct vm_page *pg; /* * Detaching from kernel_object is a NOP. */ if (UVM_OBJ_IS_KERN_OBJECT(uobj)) return; /* * Drop the reference. If it was the last one, destroy the object. */ if (atomic_dec_int_nv(&uobj->uo_refs) > 0) { return; } /* * Remove the aobj from the global list. */ mtx_enter(&uao_list_lock); LIST_REMOVE(aobj, u_list); mtx_leave(&uao_list_lock); /* * Free all the pages left in the aobj. For each page, when the * page is no longer busy (and thus after any disk I/O that it is * involved in is complete), release any swap resources and free * the page itself. */ rw_enter(uobj->vmobjlock, RW_WRITE); while ((pg = RBT_ROOT(uvm_objtree, &uobj->memt)) != NULL) { pmap_page_protect(pg, PROT_NONE); if (pg->pg_flags & PG_BUSY) { uvm_pagewait(pg, uobj->vmobjlock, "uao_det"); rw_enter(uobj->vmobjlock, RW_WRITE); continue; } uao_dropswap(&aobj->u_obj, pg->offset >> PAGE_SHIFT); uvm_lock_pageq(); uvm_pagefree(pg); uvm_unlock_pageq(); } /* * Finally, free the anonymous UVM object itself. */ uao_free(aobj); } /* * uao_flush: flush pages out of a uvm object * * => if PGO_CLEANIT is not set, then we will not block. * => if PGO_ALLPAGE is set, then all pages in the object are valid targets * for flushing. * => NOTE: we are allowed to lock the page queues, so the caller * must not be holding the lock on them [e.g. pagedaemon had * better not call us with the queues locked] * => we return TRUE unless we encountered some sort of I/O error * XXXJRT currently never happens, as we never directly initiate * XXXJRT I/O */ boolean_t uao_flush(struct uvm_object *uobj, voff_t start, voff_t stop, int flags) { struct uvm_aobj *aobj = (struct uvm_aobj *) uobj; struct vm_page *pg; voff_t curoff; KASSERT(UVM_OBJ_IS_AOBJ(uobj)); KASSERT(rw_write_held(uobj->vmobjlock)); if (flags & PGO_ALLPAGES) { start = 0; stop = (voff_t)aobj->u_pages << PAGE_SHIFT; } else { start = trunc_page(start); stop = round_page(stop); if (stop > ((voff_t)aobj->u_pages << PAGE_SHIFT)) { printf("uao_flush: strange, got an out of range " "flush (fixed)\n"); stop = (voff_t)aobj->u_pages << PAGE_SHIFT; } } /* * Don't need to do any work here if we're not freeing * or deactivating pages. */ if ((flags & (PGO_DEACTIVATE|PGO_FREE)) == 0) { return TRUE; } curoff = start; for (;;) { if (curoff < stop) { pg = uvm_pagelookup(uobj, curoff); curoff += PAGE_SIZE; if (pg == NULL) continue; } else { break; } /* Make sure page is unbusy, else wait for it. */ if (pg->pg_flags & PG_BUSY) { uvm_pagewait(pg, uobj->vmobjlock, "uaoflsh"); rw_enter(uobj->vmobjlock, RW_WRITE); curoff -= PAGE_SIZE; continue; } switch (flags & (PGO_CLEANIT|PGO_FREE|PGO_DEACTIVATE)) { /* * XXX In these first 3 cases, we always just * XXX deactivate the page. We may want to * XXX handle the different cases more specifically * XXX in the future. */ case PGO_CLEANIT|PGO_FREE: /* FALLTHROUGH */ case PGO_CLEANIT|PGO_DEACTIVATE: /* FALLTHROUGH */ case PGO_DEACTIVATE: deactivate_it: if (pg->wire_count != 0) continue; uvm_lock_pageq(); pmap_page_protect(pg, PROT_NONE); uvm_pagedeactivate(pg); uvm_unlock_pageq(); continue; case PGO_FREE: /* * If there are multiple references to * the object, just deactivate the page. */ if (uobj->uo_refs > 1) goto deactivate_it; /* XXX skip the page if it's wired */ if (pg->wire_count != 0) continue; /* * free the swap slot and the page. */ pmap_page_protect(pg, PROT_NONE); /* * freeing swapslot here is not strictly necessary. * however, leaving it here doesn't save much * because we need to update swap accounting anyway. */ uao_dropswap(uobj, pg->offset >> PAGE_SHIFT); uvm_lock_pageq(); uvm_pagefree(pg); uvm_unlock_pageq(); continue; default: panic("uao_flush: weird flags"); } } return TRUE; } /* * uao_get: fetch me a page * * we have three cases: * 1: page is resident -> just return the page. * 2: page is zero-fill -> allocate a new page and zero it. * 3: page is swapped out -> fetch the page from swap. * * cases 1 can be handled with PGO_LOCKED, cases 2 and 3 cannot. * so, if the "center" page hits case 3 (or any page, with PGO_ALLPAGES), * then we will need to return VM_PAGER_UNLOCK. * * => flags: PGO_ALLPAGES: get all of the pages * PGO_LOCKED: fault data structures are locked * => NOTE: offset is the offset of pps[0], _NOT_ pps[centeridx] * => NOTE: caller must check for released pages!! */ static int uao_get(struct uvm_object *uobj, voff_t offset, struct vm_page **pps, int *npagesp, int centeridx, vm_prot_t access_type, int advice, int flags) { struct uvm_aobj *aobj = (struct uvm_aobj *)uobj; voff_t current_offset; vm_page_t ptmp; int lcv, gotpages, maxpages, swslot, rv, pageidx; boolean_t done; KASSERT(UVM_OBJ_IS_AOBJ(uobj)); KASSERT(rw_write_held(uobj->vmobjlock)); /* * get number of pages */ maxpages = *npagesp; if (flags & PGO_LOCKED) { /* * step 1a: get pages that are already resident. only do * this if the data structures are locked (i.e. the first * time through). */ done = TRUE; /* be optimistic */ gotpages = 0; /* # of pages we got so far */ for (lcv = 0, current_offset = offset ; lcv < maxpages ; lcv++, current_offset += PAGE_SIZE) { /* do we care about this page? if not, skip it */ if (pps[lcv] == PGO_DONTCARE) continue; ptmp = uvm_pagelookup(uobj, current_offset); /* * if page is new, attempt to allocate the page, * zero-fill'd. */ if (ptmp == NULL && uao_find_swslot(uobj, current_offset >> PAGE_SHIFT) == 0) { ptmp = uvm_pagealloc(uobj, current_offset, NULL, UVM_PGA_ZERO); if (ptmp) { /* new page */ atomic_clearbits_int(&ptmp->pg_flags, PG_BUSY|PG_FAKE); atomic_setbits_int(&ptmp->pg_flags, PQ_AOBJ); UVM_PAGE_OWN(ptmp, NULL); } } /* * to be useful must get a non-busy page */ if (ptmp == NULL || (ptmp->pg_flags & PG_BUSY) != 0) { if (lcv == centeridx || (flags & PGO_ALLPAGES) != 0) /* need to do a wait or I/O! */ done = FALSE; continue; } /* * useful page: plug it in our result array */ atomic_setbits_int(&ptmp->pg_flags, PG_BUSY); UVM_PAGE_OWN(ptmp, "uao_get1"); pps[lcv] = ptmp; gotpages++; } /* * step 1b: now we've either done everything needed or we * to unlock and do some waiting or I/O. */ *npagesp = gotpages; if (done) /* bingo! */ return VM_PAGER_OK; else /* EEK! Need to unlock and I/O */ return VM_PAGER_UNLOCK; } /* * step 2: get non-resident or busy pages. * data structures are unlocked. */ for (lcv = 0, current_offset = offset ; lcv < maxpages ; lcv++, current_offset += PAGE_SIZE) { /* * - skip over pages we've already gotten or don't want * - skip over pages we don't _have_ to get */ if (pps[lcv] != NULL || (lcv != centeridx && (flags & PGO_ALLPAGES) == 0)) continue; pageidx = current_offset >> PAGE_SHIFT; /* * we have yet to locate the current page (pps[lcv]). we * first look for a page that is already at the current offset. * if we find a page, we check to see if it is busy or * released. if that is the case, then we sleep on the page * until it is no longer busy or released and repeat the lookup. * if the page we found is neither busy nor released, then we * busy it (so we own it) and plug it into pps[lcv]. this * 'break's the following while loop and indicates we are * ready to move on to the next page in the "lcv" loop above. * * if we exit the while loop with pps[lcv] still set to NULL, * then it means that we allocated a new busy/fake/clean page * ptmp in the object and we need to do I/O to fill in the data. */ /* top of "pps" while loop */ while (pps[lcv] == NULL) { /* look for a resident page */ ptmp = uvm_pagelookup(uobj, current_offset); /* not resident? allocate one now (if we can) */ if (ptmp == NULL) { ptmp = uvm_pagealloc(uobj, current_offset, NULL, 0); /* out of RAM? */ if (ptmp == NULL) { rw_exit(uobj->vmobjlock); uvm_wait("uao_getpage"); rw_enter(uobj->vmobjlock, RW_WRITE); /* goto top of pps while loop */ continue; } /* * safe with PQ's unlocked: because we just * alloc'd the page */ atomic_setbits_int(&ptmp->pg_flags, PQ_AOBJ); /* * got new page ready for I/O. break pps while * loop. pps[lcv] is still NULL. */ break; } /* page is there, see if we need to wait on it */ if ((ptmp->pg_flags & PG_BUSY) != 0) { uvm_pagewait(ptmp, uobj->vmobjlock, "uao_get"); rw_enter(uobj->vmobjlock, RW_WRITE); continue; /* goto top of pps while loop */ } /* * if we get here then the page is resident and * unbusy. we busy it now (so we own it). */ /* we own it, caller must un-busy */ atomic_setbits_int(&ptmp->pg_flags, PG_BUSY); UVM_PAGE_OWN(ptmp, "uao_get2"); pps[lcv] = ptmp; } /* * if we own the valid page at the correct offset, pps[lcv] will * point to it. nothing more to do except go to the next page. */ if (pps[lcv]) continue; /* next lcv */ /* * we have a "fake/busy/clean" page that we just allocated. * do the needed "i/o", either reading from swap or zeroing. */ swslot = uao_find_swslot(uobj, pageidx); /* just zero the page if there's nothing in swap. */ if (swslot == 0) { /* page hasn't existed before, just zero it. */ uvm_pagezero(ptmp); } else { /* * page in the swapped-out page. * unlock object for i/o, relock when done. */ rw_exit(uobj->vmobjlock); rv = uvm_swap_get(ptmp, swslot, PGO_SYNCIO); rw_enter(uobj->vmobjlock, RW_WRITE); /* * I/O done. check for errors. */ if (rv != VM_PAGER_OK) { /* * remove the swap slot from the aobj * and mark the aobj as having no real slot. * don't free the swap slot, thus preventing * it from being used again. */ swslot = uao_set_swslot(&aobj->u_obj, pageidx, SWSLOT_BAD); uvm_swap_markbad(swslot, 1); if (ptmp->pg_flags & PG_WANTED) wakeup(ptmp); atomic_clearbits_int(&ptmp->pg_flags, PG_WANTED|PG_BUSY); UVM_PAGE_OWN(ptmp, NULL); uvm_lock_pageq(); uvm_pagefree(ptmp); uvm_unlock_pageq(); rw_exit(uobj->vmobjlock); return rv; } } /* * we got the page! clear the fake flag (indicates valid * data now in page) and plug into our result array. note * that page is still busy. * * it is the callers job to: * => check if the page is released * => unbusy the page * => activate the page */ atomic_clearbits_int(&ptmp->pg_flags, PG_FAKE); pmap_clear_modify(ptmp); /* ... and clean */ pps[lcv] = ptmp; } /* lcv loop */ rw_exit(uobj->vmobjlock); return VM_PAGER_OK; } /* * uao_dropswap: release any swap resources from this aobj page. * * => aobj must be locked or have a reference count of 0. */ int uao_dropswap(struct uvm_object *uobj, int pageidx) { int slot; KASSERT(UVM_OBJ_IS_AOBJ(uobj)); slot = uao_set_swslot(uobj, pageidx, 0); if (slot) { uvm_swap_free(slot, 1); } return slot; } /* * page in every page in every aobj that is paged-out to a range of swslots. * * => aobj must be locked and is returned locked. * => returns TRUE if pagein was aborted due to lack of memory. */ boolean_t uao_swap_off(int startslot, int endslot) { struct uvm_aobj *aobj; /* * Walk the list of all anonymous UVM objects. Grab the first. */ mtx_enter(&uao_list_lock); if ((aobj = LIST_FIRST(&uao_list)) == NULL) { mtx_leave(&uao_list_lock); return FALSE; } uao_reference(&aobj->u_obj); do { struct uvm_aobj *nextaobj; boolean_t rv; /* * Prefetch the next object and immediately hold a reference * on it, so neither the current nor the next entry could * disappear while we are iterating. */ if ((nextaobj = LIST_NEXT(aobj, u_list)) != NULL) { uao_reference(&nextaobj->u_obj); } mtx_leave(&uao_list_lock); /* * Page in all pages in the swap slot range. */ rw_enter(aobj->u_obj.vmobjlock, RW_WRITE); rv = uao_pagein(aobj, startslot, endslot); rw_exit(aobj->u_obj.vmobjlock); /* Drop the reference of the current object. */ uao_detach(&aobj->u_obj); if (rv) { if (nextaobj) { uao_detach(&nextaobj->u_obj); } return rv; } aobj = nextaobj; mtx_enter(&uao_list_lock); } while (aobj); /* * done with traversal, unlock the list */ mtx_leave(&uao_list_lock); return FALSE; } /* * page in any pages from aobj in the given range. * * => returns TRUE if pagein was aborted due to lack of memory. */ static boolean_t uao_pagein(struct uvm_aobj *aobj, int startslot, int endslot) { boolean_t rv; if (UAO_USES_SWHASH(aobj)) { struct uao_swhash_elt *elt; int bucket; restart: for (bucket = aobj->u_swhashmask; bucket >= 0; bucket--) { for (elt = LIST_FIRST(&aobj->u_swhash[bucket]); elt != NULL; elt = LIST_NEXT(elt, list)) { int i; for (i = 0; i < UAO_SWHASH_CLUSTER_SIZE; i++) { int slot = elt->slots[i]; /* * if the slot isn't in range, skip it. */ if (slot < startslot || slot >= endslot) { continue; } /* * process the page, * the start over on this object * since the swhash elt * may have been freed. */ rv = uao_pagein_page(aobj, UAO_SWHASH_ELT_PAGEIDX_BASE(elt) + i); if (rv) { return rv; } goto restart; } } } } else { int i; for (i = 0; i < aobj->u_pages; i++) { int slot = aobj->u_swslots[i]; /* * if the slot isn't in range, skip it */ if (slot < startslot || slot >= endslot) { continue; } /* * process the page. */ rv = uao_pagein_page(aobj, i); if (rv) { return rv; } } } return FALSE; } /* * uao_pagein_page: page in a single page from an anonymous UVM object. * * => Returns TRUE if pagein was aborted due to lack of memory. */ static boolean_t uao_pagein_page(struct uvm_aobj *aobj, int pageidx) { struct uvm_object *uobj = &aobj->u_obj; struct vm_page *pg; int rv, npages; pg = NULL; npages = 1; KASSERT(rw_write_held(uobj->vmobjlock)); rv = uao_get(&aobj->u_obj, (voff_t)pageidx << PAGE_SHIFT, &pg, &npages, 0, PROT_READ | PROT_WRITE, 0, 0); /* * relock and finish up. */ rw_enter(uobj->vmobjlock, RW_WRITE); switch (rv) { case VM_PAGER_OK: break; case VM_PAGER_ERROR: case VM_PAGER_REFAULT: /* * nothing more to do on errors. * VM_PAGER_REFAULT can only mean that the anon was freed, * so again there's nothing to do. */ return FALSE; } /* * ok, we've got the page now. * mark it as dirty, clear its swslot and un-busy it. */ uao_dropswap(&aobj->u_obj, pageidx); atomic_clearbits_int(&pg->pg_flags, PG_BUSY|PG_CLEAN|PG_FAKE); UVM_PAGE_OWN(pg, NULL); /* * deactivate the page (to put it on a page queue). */ pmap_clear_reference(pg); uvm_lock_pageq(); uvm_pagedeactivate(pg); uvm_unlock_pageq(); return FALSE; } /* * uao_dropswap_range: drop swapslots in the range. * * => aobj must be locked and is returned locked. * => start is inclusive. end is exclusive. */ void uao_dropswap_range(struct uvm_object *uobj, voff_t start, voff_t end) { struct uvm_aobj *aobj = (struct uvm_aobj *)uobj; int swpgonlydelta = 0; KASSERT(UVM_OBJ_IS_AOBJ(uobj)); KASSERT(rw_write_held(uobj->vmobjlock)); if (end == 0) { end = INT64_MAX; } if (UAO_USES_SWHASH(aobj)) { int i, hashbuckets = aobj->u_swhashmask + 1; voff_t taghi; voff_t taglo; taglo = UAO_SWHASH_ELT_TAG(start); taghi = UAO_SWHASH_ELT_TAG(end); for (i = 0; i < hashbuckets; i++) { struct uao_swhash_elt *elt, *next; for (elt = LIST_FIRST(&aobj->u_swhash[i]); elt != NULL; elt = next) { int startidx, endidx; int j; next = LIST_NEXT(elt, list); if (elt->tag < taglo || taghi < elt->tag) { continue; } if (elt->tag == taglo) { startidx = UAO_SWHASH_ELT_PAGESLOT_IDX(start); } else { startidx = 0; } if (elt->tag == taghi) { endidx = UAO_SWHASH_ELT_PAGESLOT_IDX(end); } else { endidx = UAO_SWHASH_CLUSTER_SIZE; } for (j = startidx; j < endidx; j++) { int slot = elt->slots[j]; KASSERT(uvm_pagelookup(&aobj->u_obj, (voff_t)(UAO_SWHASH_ELT_PAGEIDX_BASE(elt) + j) << PAGE_SHIFT) == NULL); if (slot > 0) { uvm_swap_free(slot, 1); swpgonlydelta++; KASSERT(elt->count > 0); elt->slots[j] = 0; elt->count--; } } if (elt->count == 0) { LIST_REMOVE(elt, list); pool_put(&uao_swhash_elt_pool, elt); } } } } else { int i; if (aobj->u_pages < end) { end = aobj->u_pages; } for (i = start; i < end; i++) { int slot = aobj->u_swslots[i]; if (slot > 0) { uvm_swap_free(slot, 1); swpgonlydelta++; } } } /* * adjust the counter of pages only in swap for all * the swap slots we've freed. */ if (swpgonlydelta > 0) { KASSERT(uvmexp.swpgonly >= swpgonlydelta); atomic_add_int(&uvmexp.swpgonly, -swpgonlydelta); } }
1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 /* $OpenBSD: video.c,v 1.57 2022/07/02 08:50:41 visa Exp $ */ /* * Copyright (c) 2008 Robert Nagy <robert@openbsd.org> * Copyright (c) 2008 Marcus Glocker <mglocker@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/errno.h> #include <sys/ioctl.h> #include <sys/fcntl.h> #include <sys/device.h> #include <sys/vnode.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/conf.h> #include <sys/proc.h> #include <sys/videoio.h> #include <dev/video_if.h> #include <uvm/uvm_extern.h> #ifdef VIDEO_DEBUG int video_debug = 1; #define DPRINTF(l, x...) do { if ((l) <= video_debug) printf(x); } while (0) #else #define DPRINTF(l, x...) #endif struct video_softc { struct device dev; void *hw_hdl; /* hardware driver handle */ struct device *sc_dev; /* hardware device struct */ const struct video_hw_if *hw_if; /* hardware interface */ char sc_dying; /* device detached */ struct process *sc_owner; /* owner process */ uint8_t sc_open; /* device opened */ int sc_fsize; uint8_t *sc_fbuffer; caddr_t sc_fbuffer_mmap; size_t sc_fbufferlen; int sc_vidmode; /* access mode */ #define VIDMODE_NONE 0 #define VIDMODE_MMAP 1 #define VIDMODE_READ 2 int sc_frames_ready; struct selinfo sc_rsel; /* read selector */ }; int videoprobe(struct device *, void *, void *); void videoattach(struct device *, struct device *, void *); int videodetach(struct device *, int); int videoactivate(struct device *, int); int videoprint(void *, const char *); void video_intr(void *); int video_stop(struct video_softc *); int video_claim(struct video_softc *, struct process *); const struct cfattach video_ca = { sizeof(struct video_softc), videoprobe, videoattach, videodetach, videoactivate }; struct cfdriver video_cd = { NULL, "video", DV_DULL }; /* * Global flag to control if video recording is enabled by kern.video.record. */ int video_record_enable = 0; int videoprobe(struct device *parent, void *match, void *aux) { return (1); } void videoattach(struct device *parent, struct device *self, void *aux) { struct video_softc *sc = (void *)self; struct video_attach_args *sa = aux; printf("\n"); sc->hw_if = sa->hwif; sc->hw_hdl = sa->hdl; sc->sc_dev = parent; sc->sc_fbufferlen = 0; sc->sc_owner = NULL; if (sc->hw_if->get_bufsize) sc->sc_fbufferlen = (sc->hw_if->get_bufsize)(sc->hw_hdl); if (sc->sc_fbufferlen == 0) { printf("video: could not request frame buffer size\n"); return; } sc->sc_fbuffer = malloc(sc->sc_fbufferlen, M_DEVBUF, M_NOWAIT); if (sc->sc_fbuffer == NULL) { printf("video: could not allocate frame buffer\n"); return; } } int videoopen(dev_t dev, int flags, int fmt, struct proc *p) { int unit = VIDEOUNIT(dev); struct video_softc *sc; int error = 0; KERNEL_ASSERT_LOCKED(); if (unit >= video_cd.cd_ndevs || (sc = video_cd.cd_devs[unit]) == NULL || sc->hw_if == NULL) return (ENXIO); if (sc->sc_open) { DPRINTF(1, "%s: device already open\n", __func__); return (0); } sc->sc_vidmode = VIDMODE_NONE; sc->sc_frames_ready = 0; if (sc->hw_if->open != NULL) { error = sc->hw_if->open(sc->hw_hdl, flags, &sc->sc_fsize, sc->sc_fbuffer, video_intr, sc); } if (error == 0) { sc->sc_open = 1; DPRINTF(1, "%s: set device to open\n", __func__); } return (error); } int videoclose(dev_t dev, int flags, int fmt, struct proc *p) { struct video_softc *sc; int error = 0; KERNEL_ASSERT_LOCKED(); DPRINTF(1, "%s: last close\n", __func__); sc = video_cd.cd_devs[VIDEOUNIT(dev)]; error = video_stop(sc); sc->sc_open = 0; return (error); } int videoread(dev_t dev, struct uio *uio, int ioflag) { int unit = VIDEOUNIT(dev); struct video_softc *sc; int error; size_t size; KERNEL_ASSERT_LOCKED(); if (unit >= video_cd.cd_ndevs || (sc = video_cd.cd_devs[unit]) == NULL) return (ENXIO); if (sc->sc_dying) return (EIO); if (sc->sc_vidmode == VIDMODE_MMAP) return (EBUSY); if ((error = video_claim(sc, curproc->p_p))) return (error); /* start the stream if not already started */ if (sc->sc_vidmode == VIDMODE_NONE && sc->hw_if->start_read) { error = sc->hw_if->start_read(sc->hw_hdl); if (error) return (error); sc->sc_vidmode = VIDMODE_READ; } DPRINTF(1, "resid=%zu\n", uio->uio_resid); if (sc->sc_frames_ready < 1) { /* block userland read until a frame is ready */ error = tsleep_nsec(sc, PWAIT | PCATCH, "vid_rd", INFSLP); if (sc->sc_dying) error = EIO; if (error) return (error); } /* move no more than 1 frame to userland, as per specification */ size = ulmin(uio->uio_resid, sc->sc_fsize); if (!video_record_enable) bzero(sc->sc_fbuffer, size); error = uiomove(sc->sc_fbuffer, size, uio); sc->sc_frames_ready--; if (error) return (error); DPRINTF(1, "uiomove successfully done (%zu bytes)\n", size); return (0); } int videoioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) { int unit = VIDEOUNIT(dev); struct video_softc *sc; struct v4l2_buffer *vb = (struct v4l2_buffer *)data; int error; KERNEL_ASSERT_LOCKED(); if (unit >= video_cd.cd_ndevs || (sc = video_cd.cd_devs[unit]) == NULL || sc->hw_if == NULL) return (ENXIO); DPRINTF(3, "video_ioctl(%zu, '%c', %zu)\n", IOCPARM_LEN(cmd), (int) IOCGROUP(cmd), cmd & 0xff); error = EOPNOTSUPP; switch (cmd) { case VIDIOC_G_CTRL: if (sc->hw_if->g_ctrl) error = (sc->hw_if->g_ctrl)(sc->hw_hdl, (struct v4l2_control *)data); break; case VIDIOC_S_CTRL: if (sc->hw_if->s_ctrl) error = (sc->hw_if->s_ctrl)(sc->hw_hdl, (struct v4l2_control *)data); break; default: error = (ENOTTY); } if (error != ENOTTY) return (error); if ((error = video_claim(sc, p->p_p))) return (error); /* * The following IOCTLs can only be called by the device owner. * For further shared IOCTLs please move it up. */ error = EOPNOTSUPP; switch (cmd) { case VIDIOC_QUERYCAP: if (sc->hw_if->querycap) error = (sc->hw_if->querycap)(sc->hw_hdl, (struct v4l2_capability *)data); break; case VIDIOC_ENUM_FMT: if (sc->hw_if->enum_fmt) error = (sc->hw_if->enum_fmt)(sc->hw_hdl, (struct v4l2_fmtdesc *)data); break; case VIDIOC_ENUM_FRAMESIZES: if (sc->hw_if->enum_fsizes) error = (sc->hw_if->enum_fsizes)(sc->hw_hdl, (struct v4l2_frmsizeenum *)data); break; case VIDIOC_ENUM_FRAMEINTERVALS: if (sc->hw_if->enum_fivals) error = (sc->hw_if->enum_fivals)(sc->hw_hdl, (struct v4l2_frmivalenum *)data); break; case VIDIOC_S_FMT: if (!(flags & FWRITE)) return (EACCES); if (sc->hw_if->s_fmt) error = (sc->hw_if->s_fmt)(sc->hw_hdl, (struct v4l2_format *)data); break; case VIDIOC_G_FMT: if (sc->hw_if->g_fmt) error = (sc->hw_if->g_fmt)(sc->hw_hdl, (struct v4l2_format *)data); break; case VIDIOC_S_PARM: if (sc->hw_if->s_parm) error = (sc->hw_if->s_parm)(sc->hw_hdl, (struct v4l2_streamparm *)data); break; case VIDIOC_G_PARM: if (sc->hw_if->g_parm) error = (sc->hw_if->g_parm)(sc->hw_hdl, (struct v4l2_streamparm *)data); break; case VIDIOC_ENUMINPUT: if (sc->hw_if->enum_input) error = (sc->hw_if->enum_input)(sc->hw_hdl, (struct v4l2_input *)data); break; case VIDIOC_S_INPUT: if (sc->hw_if->s_input) error = (sc->hw_if->s_input)(sc->hw_hdl, (int)*data); break; case VIDIOC_G_INPUT: if (sc->hw_if->g_input) error = (sc->hw_if->g_input)(sc->hw_hdl, (int *)data); break; case VIDIOC_REQBUFS: if (sc->hw_if->reqbufs) error = (sc->hw_if->reqbufs)(sc->hw_hdl, (struct v4l2_requestbuffers *)data); break; case VIDIOC_QUERYBUF: if (sc->hw_if->querybuf) error = (sc->hw_if->querybuf)(sc->hw_hdl, (struct v4l2_buffer *)data); break; case VIDIOC_QBUF: if (sc->hw_if->qbuf) error = (sc->hw_if->qbuf)(sc->hw_hdl, (struct v4l2_buffer *)data); break; case VIDIOC_DQBUF: if (!sc->hw_if->dqbuf) break; /* should have called mmap() before now */ if (sc->sc_vidmode != VIDMODE_MMAP) { error = EINVAL; break; } error = (sc->hw_if->dqbuf)(sc->hw_hdl, (struct v4l2_buffer *)data); if (!video_record_enable) bzero(sc->sc_fbuffer_mmap + vb->m.offset, vb->length); sc->sc_frames_ready--; break; case VIDIOC_STREAMON: if (sc->hw_if->streamon) error = (sc->hw_if->streamon)(sc->hw_hdl, (int)*data); break; case VIDIOC_STREAMOFF: if (sc->hw_if->streamoff) error = (sc->hw_if->streamoff)(sc->hw_hdl, (int)*data); if (!error) { /* Release device ownership and streaming buffers. */ error = video_stop(sc); } break; case VIDIOC_TRY_FMT: if (sc->hw_if->try_fmt) error = (sc->hw_if->try_fmt)(sc->hw_hdl, (struct v4l2_format *)data); break; case VIDIOC_QUERYCTRL: if (sc->hw_if->queryctrl) error = (sc->hw_if->queryctrl)(sc->hw_hdl, (struct v4l2_queryctrl *)data); break; default: error = (ENOTTY); } return (error); } paddr_t videommap(dev_t dev, off_t off, int prot) { int unit = VIDEOUNIT(dev); struct video_softc *sc; caddr_t p; paddr_t pa; KERNEL_ASSERT_LOCKED(); DPRINTF(2, "%s: off=%lld, prot=%d\n", __func__, off, prot); if (unit >= video_cd.cd_ndevs || (sc = video_cd.cd_devs[unit]) == NULL) return (-1); if (sc->sc_dying) return (-1); if (sc->hw_if->mappage == NULL) return (-1); p = sc->hw_if->mappage(sc->hw_hdl, off, prot); if (p == NULL) return (-1); if (pmap_extract(pmap_kernel(), (vaddr_t)p, &pa) == FALSE) panic("videommap: invalid page"); sc->sc_vidmode = VIDMODE_MMAP; /* store frame buffer base address for later blanking */ if (off == 0) sc->sc_fbuffer_mmap = p; return (pa); } void filt_videodetach(struct knote *kn) { struct video_softc *sc = kn->kn_hook; int s; s = splhigh(); klist_remove_locked(&sc->sc_rsel.si_note, kn); splx(s); } int filt_videoread(struct knote *kn, long hint) { struct video_softc *sc = kn->kn_hook; if (sc->sc_frames_ready > 0) return (1); return (0); } const struct filterops video_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, .f_detach = filt_videodetach, .f_event = filt_videoread, }; int videokqfilter(dev_t dev, struct knote *kn) { int unit = VIDEOUNIT(dev); struct video_softc *sc; int s, error; KERNEL_ASSERT_LOCKED(); if (unit >= video_cd.cd_ndevs || (sc = video_cd.cd_devs[unit]) == NULL) return (ENXIO); if (sc->sc_dying) return (ENXIO); switch (kn->kn_filter) { case EVFILT_READ: kn->kn_fop = &video_filtops; kn->kn_hook = sc; break; default: return (EINVAL); } if ((error = video_claim(sc, curproc->p_p))) return (error); /* * Start the stream in read() mode if not already started. If * the user wanted mmap() mode, he should have called mmap() * before now. */ if (sc->sc_vidmode == VIDMODE_NONE && sc->hw_if->start_read) { if (sc->hw_if->start_read(sc->hw_hdl)) return (ENXIO); sc->sc_vidmode = VIDMODE_READ; } s = splhigh(); klist_insert_locked(&sc->sc_rsel.si_note, kn); splx(s); return (0); } int video_submatch(struct device *parent, void *match, void *aux) { struct cfdata *cf = match; return (cf->cf_driver == &video_cd); } /* * Called from hardware driver. This is where the MI video driver gets * probed/attached to the hardware driver */ struct device * video_attach_mi(const struct video_hw_if *rhwp, void *hdlp, struct device *dev) { struct video_attach_args arg; arg.hwif = rhwp; arg.hdl = hdlp; return (config_found_sm(dev, &arg, videoprint, video_submatch)); } void video_intr(void *addr) { struct video_softc *sc = (struct video_softc *)addr; DPRINTF(3, "video_intr sc=%p\n", sc); if (sc->sc_vidmode != VIDMODE_NONE) sc->sc_frames_ready++; else printf("%s: interrupt but no streams!\n", __func__); if (sc->sc_vidmode == VIDMODE_READ) wakeup(sc); selwakeup(&sc->sc_rsel); } int video_stop(struct video_softc *sc) { int error = 0; DPRINTF(1, "%s: stream close\n", __func__); if (sc->hw_if->close != NULL) error = sc->hw_if->close(sc->hw_hdl); sc->sc_vidmode = VIDMODE_NONE; sc->sc_frames_ready = 0; sc->sc_owner = NULL; return (error); } int video_claim(struct video_softc *sc, struct process *pr) { if (sc->sc_owner != NULL && sc->sc_owner != pr) { DPRINTF(1, "%s: already owned=%p\n", __func__, sc->sc_owner); return (EBUSY); } if (sc->sc_owner == NULL) { sc->sc_owner = pr; DPRINTF(1, "%s: new owner=%p\n", __func__, sc->sc_owner); } return (0); } int videoprint(void *aux, const char *pnp) { if (pnp != NULL) printf("video at %s", pnp); return (UNCONF); } int videodetach(struct device *self, int flags) { struct video_softc *sc = (struct video_softc *)self; int s, maj, mn; /* locate the major number */ for (maj = 0; maj < nchrdev; maj++) if (cdevsw[maj].d_open == videoopen) break; /* Nuke the vnodes for any open instances (calls close). */ mn = self->dv_unit; vdevgone(maj, mn, mn, VCHR); s = splhigh(); klist_invalidate(&sc->sc_rsel.si_note); splx(s); free(sc->sc_fbuffer, M_DEVBUF, sc->sc_fbufferlen); return (0); } int videoactivate(struct device *self, int act) { struct video_softc *sc = (struct video_softc *)self; switch (act) { case DVACT_DEACTIVATE: sc->sc_dying = 1; break; } return (0); }
2 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 /* * Copyright © 2008 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. * * Authors: * Eric Anholt <eric@anholt.net> * */ #include <linux/dma-buf.h> #include <linux/file.h> #include <linux/fs.h> #include <linux/iosys-map.h> #include <linux/mem_encrypt.h> #include <linux/mm.h> #include <linux/mman.h> #include <linux/module.h> #include <linux/pagemap.h> #include <linux/pagevec.h> #include <linux/shmem_fs.h> #include <linux/slab.h> #include <linux/string_helpers.h> #include <linux/types.h> #include <linux/uaccess.h> #include <drm/drm.h> #include <drm/drm_device.h> #include <drm/drm_drv.h> #include <drm/drm_file.h> #include <drm/drm_gem.h> #include <drm/drm_managed.h> #include <drm/drm_print.h> #include <drm/drm_vma_manager.h> #include "drm_internal.h" #include <sys/conf.h> #include <uvm/uvm.h> void drm_unref(struct uvm_object *); void drm_ref(struct uvm_object *); boolean_t drm_flush(struct uvm_object *, voff_t, voff_t, int); int drm_fault(struct uvm_faultinfo *, vaddr_t, vm_page_t *, int, int, vm_fault_t, vm_prot_t, int); const struct uvm_pagerops drm_pgops = { .pgo_reference = drm_ref, .pgo_detach = drm_unref, .pgo_fault = drm_fault, .pgo_flush = drm_flush, }; void drm_ref(struct uvm_object *uobj) { struct drm_gem_object *obj = container_of(uobj, struct drm_gem_object, uobj); drm_gem_object_get(obj); } void drm_unref(struct uvm_object *uobj) { struct drm_gem_object *obj = container_of(uobj, struct drm_gem_object, uobj); drm_gem_object_put(obj); } int drm_fault(struct uvm_faultinfo *ufi, vaddr_t vaddr, vm_page_t *pps, int npages, int centeridx, vm_fault_t fault_type, vm_prot_t access_type, int flags) { struct vm_map_entry *entry = ufi->entry; struct uvm_object *uobj = entry->object.uvm_obj; struct drm_gem_object *obj = container_of(uobj, struct drm_gem_object, uobj); struct drm_device *dev = obj->dev; int ret; /* * we do not allow device mappings to be mapped copy-on-write * so we kill any attempt to do so here. */ if (UVM_ET_ISCOPYONWRITE(entry)) { uvmfault_unlockall(ufi, ufi->entry->aref.ar_amap, uobj); return(VM_PAGER_ERROR); } /* * We could end up here as the result of a copyin(9) or * copyout(9) while handling an ioctl. So we must be careful * not to deadlock. Therefore we only block if the quiesce * count is zero, which guarantees we didn't enter from within * an ioctl code path. */ mtx_enter(&dev->quiesce_mtx); if (dev->quiesce && dev->quiesce_count == 0) { mtx_leave(&dev->quiesce_mtx); uvmfault_unlockall(ufi, ufi->entry->aref.ar_amap, uobj); mtx_enter(&dev->quiesce_mtx); while (dev->quiesce) { msleep_nsec(&dev->quiesce, &dev->quiesce_mtx, PZERO, "drmflt", INFSLP); } mtx_leave(&dev->quiesce_mtx); return(VM_PAGER_REFAULT); } dev->quiesce_count++; mtx_leave(&dev->quiesce_mtx); /* Call down into driver to do the magic */ ret = dev->driver->gem_fault(obj, ufi, entry->offset + (vaddr - entry->start), vaddr, pps, npages, centeridx, access_type, flags); mtx_enter(&dev->quiesce_mtx); dev->quiesce_count--; if (dev->quiesce) wakeup(&dev->quiesce_count); mtx_leave(&dev->quiesce_mtx); return (ret); } boolean_t drm_flush(struct uvm_object *uobj, voff_t start, voff_t stop, int flags) { return (TRUE); } struct uvm_object * udv_attach_drm(dev_t device, vm_prot_t accessprot, voff_t off, vsize_t size) { struct drm_device *dev = drm_get_device_from_kdev(device); struct drm_gem_object *obj = NULL; struct drm_vma_offset_node *node; struct drm_file *priv; struct file *filp; if (cdevsw[major(device)].d_mmap != drmmmap) return NULL; if (dev == NULL) return NULL; mutex_lock(&dev->filelist_mutex); priv = drm_find_file_by_minor(dev, minor(device)); if (priv == NULL) { mutex_unlock(&dev->filelist_mutex); return NULL; } filp = priv->filp; mutex_unlock(&dev->filelist_mutex); if (dev->driver->mmap) return dev->driver->mmap(filp, accessprot, off, size); drm_vma_offset_lock_lookup(dev->vma_offset_manager); node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager, off >> PAGE_SHIFT, atop(round_page(size))); if (likely(node)) { obj = container_of(node, struct drm_gem_object, vma_node); /* * When the object is being freed, after it hits 0-refcnt it * proceeds to tear down the object. In the process it will * attempt to remove the VMA offset and so acquire this * mgr->vm_lock. Therefore if we find an object with a 0-refcnt * that matches our range, we know it is in the process of being * destroyed and will be freed as soon as we release the lock - * so we have to check for the 0-refcnted object and treat it as * invalid. */ if (!kref_get_unless_zero(&obj->refcount)) obj = NULL; } drm_vma_offset_unlock_lookup(dev->vma_offset_manager); if (!obj) return NULL; if (!drm_vma_node_is_allowed(node, priv)) { drm_gem_object_put(obj); return NULL; } return &obj->uobj; } /** @file drm_gem.c * * This file provides some of the base ioctls and library routines for * the graphics memory manager implemented by each device driver. * * Because various devices have different requirements in terms of * synchronization and migration strategies, implementing that is left up to * the driver, and all that the general API provides should be generic -- * allocating objects, reading/writing data with the cpu, freeing objects. * Even there, platform-dependent optimizations for reading/writing data with * the CPU mean we'll likely hook those out to driver-specific calls. However, * the DRI2 implementation wants to have at least allocate/mmap be generic. * * The goal was to have swap-backed object allocation managed through * struct file. However, file descriptors as handles to a struct file have * two major failings: * - Process limits prevent more than 1024 or so being used at a time by * default. * - Inability to allocate high fds will aggravate the X Server's select() * handling, and likely that of many GL client applications as well. * * This led to a plan of using our own integer IDs (called handles, following * DRM terminology) to mimic fds, and implement the fd syscalls we need as * ioctls. The objects themselves will still include the struct file so * that we can transition to fds if the required kernel infrastructure shows * up at a later date, and as our interface with shmfs for memory allocation. */ static void drm_gem_init_release(struct drm_device *dev, void *ptr) { drm_vma_offset_manager_destroy(dev->vma_offset_manager); } /** * drm_gem_init - Initialize the GEM device fields * @dev: drm_devic structure to initialize */ int drm_gem_init(struct drm_device *dev) { struct drm_vma_offset_manager *vma_offset_manager; rw_init(&dev->object_name_lock, "drmonl"); idr_init_base(&dev->object_name_idr, 1); vma_offset_manager = drmm_kzalloc(dev, sizeof(*vma_offset_manager), GFP_KERNEL); if (!vma_offset_manager) { DRM_ERROR("out of memory\n"); return -ENOMEM; } dev->vma_offset_manager = vma_offset_manager; drm_vma_offset_manager_init(vma_offset_manager, DRM_FILE_PAGE_OFFSET_START, DRM_FILE_PAGE_OFFSET_SIZE); return drmm_add_action(dev, drm_gem_init_release, NULL); } #ifdef __linux__ /** * drm_gem_object_init - initialize an allocated shmem-backed GEM object * @dev: drm_device the object should be initialized for * @obj: drm_gem_object to initialize * @size: object size * * Initialize an already allocated GEM object of the specified size with * shmfs backing store. */ int drm_gem_object_init(struct drm_device *dev, struct drm_gem_object *obj, size_t size) { struct file *filp; drm_gem_private_object_init(dev, obj, size); filp = shmem_file_setup("drm mm object", size, VM_NORESERVE); if (IS_ERR(filp)) return PTR_ERR(filp); obj->filp = filp; return 0; } EXPORT_SYMBOL(drm_gem_object_init); #else int drm_gem_object_init(struct drm_device *dev, struct drm_gem_object *obj, size_t size) { drm_gem_private_object_init(dev, obj, size); if (size > (512 * 1024 * 1024)) { printf("%s size too big %lu\n", __func__, size); return -ENOMEM; } obj->uao = uao_create(size, 0); uvm_obj_init(&obj->uobj, &drm_pgops, 1); return 0; } #endif /** * drm_gem_private_object_init - initialize an allocated private GEM object * @dev: drm_device the object should be initialized for * @obj: drm_gem_object to initialize * @size: object size * * Initialize an already allocated GEM object of the specified size with * no GEM provided backing store. Instead the caller is responsible for * backing the object and handling it. */ void drm_gem_private_object_init(struct drm_device *dev, struct drm_gem_object *obj, size_t size) { BUG_ON((size & (PAGE_SIZE - 1)) != 0); obj->dev = dev; #ifdef __linux__ obj->filp = NULL; #else obj->uao = NULL; obj->uobj.pgops = NULL; #endif kref_init(&obj->refcount); obj->handle_count = 0; obj->size = size; dma_resv_init(&obj->_resv); if (!obj->resv) obj->resv = &obj->_resv; if (drm_core_check_feature(dev, DRIVER_GEM_GPUVA)) drm_gem_gpuva_init(obj); drm_vma_node_reset(&obj->vma_node); INIT_LIST_HEAD(&obj->lru_node); } EXPORT_SYMBOL(drm_gem_private_object_init); /** * drm_gem_private_object_fini - Finalize a failed drm_gem_object * @obj: drm_gem_object * * Uninitialize an already allocated GEM object when it initialized failed */ void drm_gem_private_object_fini(struct drm_gem_object *obj) { WARN_ON(obj->dma_buf); dma_resv_fini(&obj->_resv); } EXPORT_SYMBOL(drm_gem_private_object_fini); /** * drm_gem_object_handle_free - release resources bound to userspace handles * @obj: GEM object to clean up. * * Called after the last handle to the object has been closed * * Removes any name for the object. Note that this must be * called before drm_gem_object_free or we'll be touching * freed memory */ static void drm_gem_object_handle_free(struct drm_gem_object *obj) { struct drm_device *dev = obj->dev; /* Remove any name for this object */ if (obj->name) { idr_remove(&dev->object_name_idr, obj->name); obj->name = 0; } } static void drm_gem_object_exported_dma_buf_free(struct drm_gem_object *obj) { /* Unbreak the reference cycle if we have an exported dma_buf. */ if (obj->dma_buf) { dma_buf_put(obj->dma_buf); obj->dma_buf = NULL; } } static void drm_gem_object_handle_put_unlocked(struct drm_gem_object *obj) { struct drm_device *dev = obj->dev; bool final = false; if (WARN_ON(READ_ONCE(obj->handle_count) == 0)) return; /* * Must bump handle count first as this may be the last * ref, in which case the object would disappear before we * checked for a name */ mutex_lock(&dev->object_name_lock); if (--obj->handle_count == 0) { drm_gem_object_handle_free(obj); drm_gem_object_exported_dma_buf_free(obj); final = true; } mutex_unlock(&dev->object_name_lock); if (final) drm_gem_object_put(obj); } /* * Called at device or object close to release the file's * handle references on objects. */ static int drm_gem_object_release_handle(int id, void *ptr, void *data) { struct drm_file *file_priv = data; struct drm_gem_object *obj = ptr; if (obj->funcs->close) obj->funcs->close(obj, file_priv); drm_prime_remove_buf_handle(&file_priv->prime, id); drm_vma_node_revoke(&obj->vma_node, file_priv); drm_gem_object_handle_put_unlocked(obj); return 0; } /** * drm_gem_handle_delete - deletes the given file-private handle * @filp: drm file-private structure to use for the handle look up * @handle: userspace handle to delete * * Removes the GEM handle from the @filp lookup table which has been added with * drm_gem_handle_create(). If this is the last handle also cleans up linked * resources like GEM names. */ int drm_gem_handle_delete(struct drm_file *filp, u32 handle) { struct drm_gem_object *obj; spin_lock(&filp->table_lock); /* Check if we currently have a reference on the object */ obj = idr_replace(&filp->object_idr, NULL, handle); spin_unlock(&filp->table_lock); if (IS_ERR_OR_NULL(obj)) return -EINVAL; /* Release driver's reference and decrement refcount. */ drm_gem_object_release_handle(handle, obj, filp); /* And finally make the handle available for future allocations. */ spin_lock(&filp->table_lock); idr_remove(&filp->object_idr, handle); spin_unlock(&filp->table_lock); return 0; } EXPORT_SYMBOL(drm_gem_handle_delete); /** * drm_gem_dumb_map_offset - return the fake mmap offset for a gem object * @file: drm file-private structure containing the gem object * @dev: corresponding drm_device * @handle: gem object handle * @offset: return location for the fake mmap offset * * This implements the &drm_driver.dumb_map_offset kms driver callback for * drivers which use gem to manage their backing storage. * * Returns: * 0 on success or a negative error code on failure. */ int drm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev, u32 handle, u64 *offset) { struct drm_gem_object *obj; int ret; obj = drm_gem_object_lookup(file, handle); if (!obj) return -ENOENT; /* Don't allow imported objects to be mapped */ if (obj->import_attach) { ret = -EINVAL; goto out; } ret = drm_gem_create_mmap_offset(obj); if (ret) goto out; *offset = drm_vma_node_offset_addr(&obj->vma_node); out: drm_gem_object_put(obj); return ret; } EXPORT_SYMBOL_GPL(drm_gem_dumb_map_offset); /** * drm_gem_handle_create_tail - internal functions to create a handle * @file_priv: drm file-private structure to register the handle for * @obj: object to register * @handlep: pointer to return the created handle to the caller * * This expects the &drm_device.object_name_lock to be held already and will * drop it before returning. Used to avoid races in establishing new handles * when importing an object from either an flink name or a dma-buf. * * Handles must be release again through drm_gem_handle_delete(). This is done * when userspace closes @file_priv for all attached handles, or through the * GEM_CLOSE ioctl for individual handles. */ int drm_gem_handle_create_tail(struct drm_file *file_priv, struct drm_gem_object *obj, u32 *handlep) { struct drm_device *dev = obj->dev; u32 handle; int ret; WARN_ON(!mutex_is_locked(&dev->object_name_lock)); if (obj->handle_count++ == 0) drm_gem_object_get(obj); /* * Get the user-visible handle using idr. Preload and perform * allocation under our spinlock. */ idr_preload(GFP_KERNEL); spin_lock(&file_priv->table_lock); ret = idr_alloc(&file_priv->object_idr, obj, 1, 0, GFP_NOWAIT); spin_unlock(&file_priv->table_lock); idr_preload_end(); mutex_unlock(&dev->object_name_lock); if (ret < 0) goto err_unref; handle = ret; ret = drm_vma_node_allow(&obj->vma_node, file_priv); if (ret) goto err_remove; if (obj->funcs->open) { ret = obj->funcs->open(obj, file_priv); if (ret) goto err_revoke; } *handlep = handle; return 0; err_revoke: drm_vma_node_revoke(&obj->vma_node, file_priv); err_remove: spin_lock(&file_priv->table_lock); idr_remove(&file_priv->object_idr, handle); spin_unlock(&file_priv->table_lock); err_unref: drm_gem_object_handle_put_unlocked(obj); return ret; } /** * drm_gem_handle_create - create a gem handle for an object * @file_priv: drm file-private structure to register the handle for * @obj: object to register * @handlep: pointer to return the created handle to the caller * * Create a handle for this object. This adds a handle reference to the object, * which includes a regular reference count. Callers will likely want to * dereference the object afterwards. * * Since this publishes @obj to userspace it must be fully set up by this point, * drivers must call this last in their buffer object creation callbacks. */ int drm_gem_handle_create(struct drm_file *file_priv, struct drm_gem_object *obj, u32 *handlep) { mutex_lock(&obj->dev->object_name_lock); return drm_gem_handle_create_tail(file_priv, obj, handlep); } EXPORT_SYMBOL(drm_gem_handle_create); /** * drm_gem_free_mmap_offset - release a fake mmap offset for an object * @obj: obj in question * * This routine frees fake offsets allocated by drm_gem_create_mmap_offset(). * * Note that drm_gem_object_release() already calls this function, so drivers * don't have to take care of releasing the mmap offset themselves when freeing * the GEM object. */ void drm_gem_free_mmap_offset(struct drm_gem_object *obj) { struct drm_device *dev = obj->dev; drm_vma_offset_remove(dev->vma_offset_manager, &obj->vma_node); } EXPORT_SYMBOL(drm_gem_free_mmap_offset); /** * drm_gem_create_mmap_offset_size - create a fake mmap offset for an object * @obj: obj in question * @size: the virtual size * * GEM memory mapping works by handing back to userspace a fake mmap offset * it can use in a subsequent mmap(2) call. The DRM core code then looks * up the object based on the offset and sets up the various memory mapping * structures. * * This routine allocates and attaches a fake offset for @obj, in cases where * the virtual size differs from the physical size (ie. &drm_gem_object.size). * Otherwise just use drm_gem_create_mmap_offset(). * * This function is idempotent and handles an already allocated mmap offset * transparently. Drivers do not need to check for this case. */ int drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size) { struct drm_device *dev = obj->dev; return drm_vma_offset_add(dev->vma_offset_manager, &obj->vma_node, size / PAGE_SIZE); } EXPORT_SYMBOL(drm_gem_create_mmap_offset_size); /** * drm_gem_create_mmap_offset - create a fake mmap offset for an object * @obj: obj in question * * GEM memory mapping works by handing back to userspace a fake mmap offset * it can use in a subsequent mmap(2) call. The DRM core code then looks * up the object based on the offset and sets up the various memory mapping * structures. * * This routine allocates and attaches a fake offset for @obj. * * Drivers can call drm_gem_free_mmap_offset() before freeing @obj to release * the fake offset again. */ int drm_gem_create_mmap_offset(struct drm_gem_object *obj) { return drm_gem_create_mmap_offset_size(obj, obj->size); } EXPORT_SYMBOL(drm_gem_create_mmap_offset); #ifdef notyet /* * Move folios to appropriate lru and release the folios, decrementing the * ref count of those folios. */ static void drm_gem_check_release_batch(struct folio_batch *fbatch) { check_move_unevictable_folios(fbatch); __folio_batch_release(fbatch); cond_resched(); } #endif /** * drm_gem_get_pages - helper to allocate backing pages for a GEM object * from shmem * @obj: obj in question * * This reads the page-array of the shmem-backing storage of the given gem * object. An array of pages is returned. If a page is not allocated or * swapped-out, this will allocate/swap-in the required pages. Note that the * whole object is covered by the page-array and pinned in memory. * * Use drm_gem_put_pages() to release the array and unpin all pages. * * This uses the GFP-mask set on the shmem-mapping (see mapping_set_gfp_mask()). * If you require other GFP-masks, you have to do those allocations yourself. * * Note that you are not allowed to change gfp-zones during runtime. That is, * shmem_read_mapping_page_gfp() must be called with the same gfp_zone(gfp) as * set during initialization. If you have special zone constraints, set them * after drm_gem_object_init() via mapping_set_gfp_mask(). shmem-core takes care * to keep pages in the required zone during swap-in. * * This function is only valid on objects initialized with * drm_gem_object_init(), but not for those initialized with * drm_gem_private_object_init() only. */ struct vm_page **drm_gem_get_pages(struct drm_gem_object *obj) { STUB(); return ERR_PTR(-ENOSYS); #ifdef notyet struct address_space *mapping; struct vm_page **pages; struct folio *folio; struct folio_batch fbatch; long i, j, npages; if (WARN_ON(!obj->filp)) return ERR_PTR(-EINVAL); /* This is the shared memory object that backs the GEM resource */ mapping = obj->filp->f_mapping; /* We already BUG_ON() for non-page-aligned sizes in * drm_gem_object_init(), so we should never hit this unless * driver author is doing something really wrong: */ WARN_ON((obj->size & (PAGE_SIZE - 1)) != 0); npages = obj->size >> PAGE_SHIFT; pages = kvmalloc_array(npages, sizeof(struct vm_page *), GFP_KERNEL); if (pages == NULL) return ERR_PTR(-ENOMEM); mapping_set_unevictable(mapping); i = 0; while (i < npages) { long nr; folio = shmem_read_folio_gfp(mapping, i, mapping_gfp_mask(mapping)); if (IS_ERR(folio)) goto fail; nr = min(npages - i, folio_nr_pages(folio)); for (j = 0; j < nr; j++, i++) pages[i] = folio_file_page(folio, i); /* Make sure shmem keeps __GFP_DMA32 allocated pages in the * correct region during swapin. Note that this requires * __GFP_DMA32 to be set in mapping_gfp_mask(inode->i_mapping) * so shmem can relocate pages during swapin if required. */ BUG_ON(mapping_gfp_constraint(mapping, __GFP_DMA32) && (folio_pfn(folio) >= 0x00100000UL)); } return pages; fail: mapping_clear_unevictable(mapping); folio_batch_init(&fbatch); j = 0; while (j < i) { struct folio *f = page_folio(pages[j]); if (!folio_batch_add(&fbatch, f)) drm_gem_check_release_batch(&fbatch); j += folio_nr_pages(f); } if (fbatch.nr) drm_gem_check_release_batch(&fbatch); kvfree(pages); return ERR_CAST(folio); #endif } EXPORT_SYMBOL(drm_gem_get_pages); /** * drm_gem_put_pages - helper to free backing pages for a GEM object * @obj: obj in question * @pages: pages to free * @dirty: if true, pages will be marked as dirty * @accessed: if true, the pages will be marked as accessed */ void drm_gem_put_pages(struct drm_gem_object *obj, struct vm_page **pages, bool dirty, bool accessed) { STUB(); #ifdef notyet int i, npages; struct address_space *mapping; struct folio_batch fbatch; mapping = file_inode(obj->filp)->i_mapping; mapping_clear_unevictable(mapping); /* We already BUG_ON() for non-page-aligned sizes in * drm_gem_object_init(), so we should never hit this unless * driver author is doing something really wrong: */ WARN_ON((obj->size & (PAGE_SIZE - 1)) != 0); npages = obj->size >> PAGE_SHIFT; folio_batch_init(&fbatch); for (i = 0; i < npages; i++) { struct folio *folio; if (!pages[i]) continue; folio = page_folio(pages[i]); if (dirty) folio_mark_dirty(folio); if (accessed) folio_mark_accessed(folio); /* Undo the reference we took when populating the table */ if (!folio_batch_add(&fbatch, folio)) drm_gem_check_release_batch(&fbatch); i += folio_nr_pages(folio) - 1; } if (folio_batch_count(&fbatch)) drm_gem_check_release_batch(&fbatch); kvfree(pages); #endif } EXPORT_SYMBOL(drm_gem_put_pages); static int objects_lookup(struct drm_file *filp, u32 *handle, int count, struct drm_gem_object **objs) { int i, ret = 0; struct drm_gem_object *obj; spin_lock(&filp->table_lock); for (i = 0; i < count; i++) { /* Check if we currently have a reference on the object */ obj = idr_find(&filp->object_idr, handle[i]); if (!obj) { ret = -ENOENT; break; } drm_gem_object_get(obj); objs[i] = obj; } spin_unlock(&filp->table_lock); return ret; } /** * drm_gem_objects_lookup - look up GEM objects from an array of handles * @filp: DRM file private date * @bo_handles: user pointer to array of userspace handle * @count: size of handle array * @objs_out: returned pointer to array of drm_gem_object pointers * * Takes an array of userspace handles and returns a newly allocated array of * GEM objects. * * For a single handle lookup, use drm_gem_object_lookup(). * * Returns: * * @objs filled in with GEM object pointers. Returned GEM objects need to be * released with drm_gem_object_put(). -ENOENT is returned on a lookup * failure. 0 is returned on success. * */ int drm_gem_objects_lookup(struct drm_file *filp, void __user *bo_handles, int count, struct drm_gem_object ***objs_out) { int ret; u32 *handles; struct drm_gem_object **objs; if (!count) return 0; objs = kvmalloc_array(count, sizeof(struct drm_gem_object *), GFP_KERNEL | __GFP_ZERO); if (!objs) return -ENOMEM; *objs_out = objs; handles = kvmalloc_array(count, sizeof(u32), GFP_KERNEL); if (!handles) { ret = -ENOMEM; goto out; } if (copy_from_user(handles, bo_handles, count * sizeof(u32))) { ret = -EFAULT; DRM_DEBUG("Failed to copy in GEM handles\n"); goto out; } ret = objects_lookup(filp, handles, count, objs); out: kvfree(handles); return ret; } EXPORT_SYMBOL(drm_gem_objects_lookup); /** * drm_gem_object_lookup - look up a GEM object from its handle * @filp: DRM file private date * @handle: userspace handle * * Returns: * * A reference to the object named by the handle if such exists on @filp, NULL * otherwise. * * If looking up an array of handles, use drm_gem_objects_lookup(). */ struct drm_gem_object * drm_gem_object_lookup(struct drm_file *filp, u32 handle) { struct drm_gem_object *obj = NULL; objects_lookup(filp, &handle, 1, &obj); return obj; } EXPORT_SYMBOL(drm_gem_object_lookup); /** * drm_gem_dma_resv_wait - Wait on GEM object's reservation's objects * shared and/or exclusive fences. * @filep: DRM file private date * @handle: userspace handle * @wait_all: if true, wait on all fences, else wait on just exclusive fence * @timeout: timeout value in jiffies or zero to return immediately * * Returns: * * Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or * greater than 0 on success. */ long drm_gem_dma_resv_wait(struct drm_file *filep, u32 handle, bool wait_all, unsigned long timeout) { long ret; struct drm_gem_object *obj; obj = drm_gem_object_lookup(filep, handle); if (!obj) { DRM_DEBUG("Failed to look up GEM BO %d\n", handle); return -EINVAL; } ret = dma_resv_wait_timeout(obj->resv, dma_resv_usage_rw(wait_all), true, timeout); if (ret == 0) ret = -ETIME; else if (ret > 0) ret = 0; drm_gem_object_put(obj); return ret; } EXPORT_SYMBOL(drm_gem_dma_resv_wait); /** * drm_gem_close_ioctl - implementation of the GEM_CLOSE ioctl * @dev: drm_device * @data: ioctl data * @file_priv: drm file-private structure * * Releases the handle to an mm object. */ int drm_gem_close_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_gem_close *args = data; int ret; if (!drm_core_check_feature(dev, DRIVER_GEM)) return -EOPNOTSUPP; ret = drm_gem_handle_delete(file_priv, args->handle); return ret; } /** * drm_gem_flink_ioctl - implementation of the GEM_FLINK ioctl * @dev: drm_device * @data: ioctl data * @file_priv: drm file-private structure * * Create a global name for an object, returning the name. * * Note that the name does not hold a reference; when the object * is freed, the name goes away. */ int drm_gem_flink_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_gem_flink *args = data; struct drm_gem_object *obj; int ret; if (!drm_core_check_feature(dev, DRIVER_GEM)) return -EOPNOTSUPP; obj = drm_gem_object_lookup(file_priv, args->handle); if (obj == NULL) return -ENOENT; mutex_lock(&dev->object_name_lock); /* prevent races with concurrent gem_close. */ if (obj->handle_count == 0) { ret = -ENOENT; goto err; } if (!obj->name) { ret = idr_alloc(&dev->object_name_idr, obj, 1, 0, GFP_KERNEL); if (ret < 0) goto err; obj->name = ret; } args->name = (uint64_t) obj->name; ret = 0; err: mutex_unlock(&dev->object_name_lock); drm_gem_object_put(obj); return ret; } /** * drm_gem_open_ioctl - implementation of the GEM_OPEN ioctl * @dev: drm_device * @data: ioctl data * @file_priv: drm file-private structure * * Open an object using the global name, returning a handle and the size. * * This handle (of course) holds a reference to the object, so the object * will not go away until the handle is deleted. */ int drm_gem_open_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_gem_open *args = data; struct drm_gem_object *obj; int ret; u32 handle; if (!drm_core_check_feature(dev, DRIVER_GEM)) return -EOPNOTSUPP; mutex_lock(&dev->object_name_lock); obj = idr_find(&dev->object_name_idr, (int) args->name); if (obj) { drm_gem_object_get(obj); } else { mutex_unlock(&dev->object_name_lock); return -ENOENT; } /* drm_gem_handle_create_tail unlocks dev->object_name_lock. */ ret = drm_gem_handle_create_tail(file_priv, obj, &handle); if (ret) goto err; args->handle = handle; args->size = obj->size; err: drm_gem_object_put(obj); return ret; } /** * drm_gem_open - initializes GEM file-private structures at devnode open time * @dev: drm_device which is being opened by userspace * @file_private: drm file-private structure to set up * * Called at device open time, sets up the structure for handling refcounting * of mm objects. */ void drm_gem_open(struct drm_device *dev, struct drm_file *file_private) { idr_init_base(&file_private->object_idr, 1); mtx_init(&file_private->table_lock, IPL_NONE); } /** * drm_gem_release - release file-private GEM resources * @dev: drm_device which is being closed by userspace * @file_private: drm file-private structure to clean up * * Called at close time when the filp is going away. * * Releases any remaining references on objects by this filp. */ void drm_gem_release(struct drm_device *dev, struct drm_file *file_private) { idr_for_each(&file_private->object_idr, &drm_gem_object_release_handle, file_private); idr_destroy(&file_private->object_idr); } /** * drm_gem_object_release - release GEM buffer object resources * @obj: GEM buffer object * * This releases any structures and resources used by @obj and is the inverse of * drm_gem_object_init(). */ void drm_gem_object_release(struct drm_gem_object *obj) { #ifdef __linux__ if (obj->filp) fput(obj->filp); #else if (obj->uao) uao_detach(obj->uao); if (obj->uobj.pgops) uvm_obj_destroy(&obj->uobj); #endif drm_gem_private_object_fini(obj); drm_gem_free_mmap_offset(obj); drm_gem_lru_remove(obj); } EXPORT_SYMBOL(drm_gem_object_release); /** * drm_gem_object_free - free a GEM object * @kref: kref of the object to free * * Called after the last reference to the object has been lost. * * Frees the object */ void drm_gem_object_free(struct kref *kref) { struct drm_gem_object *obj = container_of(kref, struct drm_gem_object, refcount); if (WARN_ON(!obj->funcs->free)) return; obj->funcs->free(obj); } EXPORT_SYMBOL(drm_gem_object_free); #ifdef __linux__ /** * drm_gem_vm_open - vma->ops->open implementation for GEM * @vma: VM area structure * * This function implements the #vm_operations_struct open() callback for GEM * drivers. This must be used together with drm_gem_vm_close(). */ void drm_gem_vm_open(struct vm_area_struct *vma) { struct drm_gem_object *obj = vma->vm_private_data; drm_gem_object_get(obj); } EXPORT_SYMBOL(drm_gem_vm_open); /** * drm_gem_vm_close - vma->ops->close implementation for GEM * @vma: VM area structure * * This function implements the #vm_operations_struct close() callback for GEM * drivers. This must be used together with drm_gem_vm_open(). */ void drm_gem_vm_close(struct vm_area_struct *vma) { struct drm_gem_object *obj = vma->vm_private_data; drm_gem_object_put(obj); } EXPORT_SYMBOL(drm_gem_vm_close); /** * drm_gem_mmap_obj - memory map a GEM object * @obj: the GEM object to map * @obj_size: the object size to be mapped, in bytes * @vma: VMA for the area to be mapped * * Set up the VMA to prepare mapping of the GEM object using the GEM object's * vm_ops. Depending on their requirements, GEM objects can either * provide a fault handler in their vm_ops (in which case any accesses to * the object will be trapped, to perform migration, GTT binding, surface * register allocation, or performance monitoring), or mmap the buffer memory * synchronously after calling drm_gem_mmap_obj. * * This function is mainly intended to implement the DMABUF mmap operation, when * the GEM object is not looked up based on its fake offset. To implement the * DRM mmap operation, drivers should use the drm_gem_mmap() function. * * drm_gem_mmap_obj() assumes the user is granted access to the buffer while * drm_gem_mmap() prevents unprivileged users from mapping random objects. So * callers must verify access restrictions before calling this helper. * * Return 0 or success or -EINVAL if the object size is smaller than the VMA * size, or if no vm_ops are provided. */ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size, struct vm_area_struct *vma) { int ret; /* Check for valid size. */ if (obj_size < vma->vm_end - vma->vm_start) return -EINVAL; /* Take a ref for this mapping of the object, so that the fault * handler can dereference the mmap offset's pointer to the object. * This reference is cleaned up by the corresponding vm_close * (which should happen whether the vma was created by this call, or * by a vm_open due to mremap or partial unmap or whatever). */ drm_gem_object_get(obj); vma->vm_private_data = obj; vma->vm_ops = obj->funcs->vm_ops; if (obj->funcs->mmap) { ret = obj->funcs->mmap(obj, vma); if (ret) goto err_drm_gem_object_put; WARN_ON(!(vma->vm_flags & VM_DONTEXPAND)); } else { if (!vma->vm_ops) { ret = -EINVAL; goto err_drm_gem_object_put; } vm_flags_set(vma, VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP); vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); } return 0; err_drm_gem_object_put: drm_gem_object_put(obj); return ret; } EXPORT_SYMBOL(drm_gem_mmap_obj); /** * drm_gem_mmap - memory map routine for GEM objects * @filp: DRM file pointer * @vma: VMA for the area to be mapped * * If a driver supports GEM object mapping, mmap calls on the DRM file * descriptor will end up here. * * Look up the GEM object based on the offset passed in (vma->vm_pgoff will * contain the fake offset we created when the GTT map ioctl was called on * the object) and map it with a call to drm_gem_mmap_obj(). * * If the caller is not granted access to the buffer object, the mmap will fail * with EACCES. Please see the vma manager for more information. */ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) { struct drm_file *priv = filp->private_data; struct drm_device *dev = priv->minor->dev; struct drm_gem_object *obj = NULL; struct drm_vma_offset_node *node; int ret; if (drm_dev_is_unplugged(dev)) return -ENODEV; drm_vma_offset_lock_lookup(dev->vma_offset_manager); node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager, vma->vm_pgoff, vma_pages(vma)); if (likely(node)) { obj = container_of(node, struct drm_gem_object, vma_node); /* * When the object is being freed, after it hits 0-refcnt it * proceeds to tear down the object. In the process it will * attempt to remove the VMA offset and so acquire this * mgr->vm_lock. Therefore if we find an object with a 0-refcnt * that matches our range, we know it is in the process of being * destroyed and will be freed as soon as we release the lock - * so we have to check for the 0-refcnted object and treat it as * invalid. */ if (!kref_get_unless_zero(&obj->refcount)) obj = NULL; } drm_vma_offset_unlock_lookup(dev->vma_offset_manager); if (!obj) return -EINVAL; if (!drm_vma_node_is_allowed(node, priv)) { drm_gem_object_put(obj); return -EACCES; } ret = drm_gem_mmap_obj(obj, drm_vma_node_size(node) << PAGE_SHIFT, vma); drm_gem_object_put(obj); return ret; } EXPORT_SYMBOL(drm_gem_mmap); #else /* ! __linux__ */ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size, vm_prot_t accessprot, voff_t off, vsize_t size) { int ret; /* Check for valid size. */ if (obj_size < size) return -EINVAL; /* Take a ref for this mapping of the object, so that the fault * handler can dereference the mmap offset's pointer to the object. * This reference is cleaned up by the corresponding vm_close * (which should happen whether the vma was created by this call, or * by a vm_open due to mremap or partial unmap or whatever). */ drm_gem_object_get(obj); #ifdef __linux__ vma->vm_private_data = obj; vma->vm_ops = obj->funcs->vm_ops; #else if (obj->uobj.pgops == NULL) uvm_obj_init(&obj->uobj, obj->funcs->vm_ops, 1); #endif if (obj->funcs->mmap) { ret = obj->funcs->mmap(obj, accessprot, off, size); if (ret) goto err_drm_gem_object_put; #ifdef notyet WARN_ON(!(vma->vm_flags & VM_DONTEXPAND)); #endif } else { #ifdef notyet if (!vma->vm_ops) { ret = -EINVAL; goto err_drm_gem_object_put; } vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP; vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); #else ret = -EINVAL; goto err_drm_gem_object_put; #endif } return 0; err_drm_gem_object_put: drm_gem_object_put(obj); return ret; } struct uvm_object * drm_gem_mmap(struct file *filp, vm_prot_t accessprot, voff_t off, vsize_t size) { struct drm_file *priv = (void *)filp; struct drm_device *dev = priv->minor->dev; struct drm_gem_object *obj = NULL; struct drm_vma_offset_node *node; int ret; if (drm_dev_is_unplugged(dev)) return NULL; drm_vma_offset_lock_lookup(dev->vma_offset_manager); node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager, off >> PAGE_SHIFT, atop(round_page(size))); if (likely(node)) { obj = container_of(node, struct drm_gem_object, vma_node); /* * When the object is being freed, after it hits 0-refcnt it * proceeds to tear down the object. In the process it will * attempt to remove the VMA offset and so acquire this * mgr->vm_lock. Therefore if we find an object with a 0-refcnt * that matches our range, we know it is in the process of being * destroyed and will be freed as soon as we release the lock - * so we have to check for the 0-refcnted object and treat it as * invalid. */ if (!kref_get_unless_zero(&obj->refcount)) obj = NULL; } drm_vma_offset_unlock_lookup(dev->vma_offset_manager); if (!obj) return NULL; if (!drm_vma_node_is_allowed(node, priv)) { drm_gem_object_put(obj); return NULL; } ret = drm_gem_mmap_obj(obj, drm_vma_node_size(node) << PAGE_SHIFT, accessprot, off, size); drm_gem_object_put(obj); return &obj->uobj; } #endif /* __linux__ */ void drm_gem_print_info(struct drm_printer *p, unsigned int indent, const struct drm_gem_object *obj) { drm_printf_indent(p, indent, "name=%d\n", obj->name); drm_printf_indent(p, indent, "refcount=%u\n", kref_read(&obj->refcount)); drm_printf_indent(p, indent, "start=%08lx\n", drm_vma_node_start(&obj->vma_node)); drm_printf_indent(p, indent, "size=%zu\n", obj->size); drm_printf_indent(p, indent, "imported=%s\n", str_yes_no(obj->import_attach)); if (obj->funcs->print_info) obj->funcs->print_info(p, indent, obj); } int drm_gem_pin(struct drm_gem_object *obj) { if (obj->funcs->pin) return obj->funcs->pin(obj); return 0; } void drm_gem_unpin(struct drm_gem_object *obj) { if (obj->funcs->unpin) obj->funcs->unpin(obj); } int drm_gem_vmap(struct drm_gem_object *obj, struct iosys_map *map) { int ret; dma_resv_assert_held(obj->resv); if (!obj->funcs->vmap) return -EOPNOTSUPP; ret = obj->funcs->vmap(obj, map); if (ret) return ret; else if (iosys_map_is_null(map)) return -ENOMEM; return 0; } EXPORT_SYMBOL(drm_gem_vmap); void drm_gem_vunmap(struct drm_gem_object *obj, struct iosys_map *map) { dma_resv_assert_held(obj->resv); if (iosys_map_is_null(map)) return; if (obj->funcs->vunmap) obj->funcs->vunmap(obj, map); /* Always set the mapping to NULL. Callers may rely on this. */ iosys_map_clear(map); } EXPORT_SYMBOL(drm_gem_vunmap); int drm_gem_vmap_unlocked(struct drm_gem_object *obj, struct iosys_map *map) { int ret; dma_resv_lock(obj->resv, NULL); ret = drm_gem_vmap(obj, map); dma_resv_unlock(obj->resv); return ret; } EXPORT_SYMBOL(drm_gem_vmap_unlocked); void drm_gem_vunmap_unlocked(struct drm_gem_object *obj, struct iosys_map *map) { dma_resv_lock(obj->resv, NULL); drm_gem_vunmap(obj, map); dma_resv_unlock(obj->resv); } EXPORT_SYMBOL(drm_gem_vunmap_unlocked); /** * drm_gem_lock_reservations - Sets up the ww context and acquires * the lock on an array of GEM objects. * * Once you've locked your reservations, you'll want to set up space * for your shared fences (if applicable), submit your job, then * drm_gem_unlock_reservations(). * * @objs: drm_gem_objects to lock * @count: Number of objects in @objs * @acquire_ctx: struct ww_acquire_ctx that will be initialized as * part of tracking this set of locked reservations. */ int drm_gem_lock_reservations(struct drm_gem_object **objs, int count, struct ww_acquire_ctx *acquire_ctx) { int contended = -1; int i, ret; ww_acquire_init(acquire_ctx, &reservation_ww_class); retry: if (contended != -1) { struct drm_gem_object *obj = objs[contended]; ret = dma_resv_lock_slow_interruptible(obj->resv, acquire_ctx); if (ret) { ww_acquire_fini(acquire_ctx); return ret; } } for (i = 0; i < count; i++) { if (i == contended) continue; ret = dma_resv_lock_interruptible(objs[i]->resv, acquire_ctx); if (ret) { int j; for (j = 0; j < i; j++) dma_resv_unlock(objs[j]->resv); if (contended != -1 && contended >= i) dma_resv_unlock(objs[contended]->resv); if (ret == -EDEADLK) { contended = i; goto retry; } ww_acquire_fini(acquire_ctx); return ret; } } ww_acquire_done(acquire_ctx); return 0; } EXPORT_SYMBOL(drm_gem_lock_reservations); void drm_gem_unlock_reservations(struct drm_gem_object **objs, int count, struct ww_acquire_ctx *acquire_ctx) { int i; for (i = 0; i < count; i++) dma_resv_unlock(objs[i]->resv); ww_acquire_fini(acquire_ctx); } EXPORT_SYMBOL(drm_gem_unlock_reservations); /** * drm_gem_lru_init - initialize a LRU * * @lru: The LRU to initialize * @lock: The lock protecting the LRU */ void drm_gem_lru_init(struct drm_gem_lru *lru, struct rwlock *lock) { lru->lock = lock; lru->count = 0; INIT_LIST_HEAD(&lru->list); } EXPORT_SYMBOL(drm_gem_lru_init); static void drm_gem_lru_remove_locked(struct drm_gem_object *obj) { obj->lru->count -= obj->size >> PAGE_SHIFT; WARN_ON(obj->lru->count < 0); list_del(&obj->lru_node); obj->lru = NULL; } /** * drm_gem_lru_remove - remove object from whatever LRU it is in * * If the object is currently in any LRU, remove it. * * @obj: The GEM object to remove from current LRU */ void drm_gem_lru_remove(struct drm_gem_object *obj) { struct drm_gem_lru *lru = obj->lru; if (!lru) return; mutex_lock(lru->lock); drm_gem_lru_remove_locked(obj); mutex_unlock(lru->lock); } EXPORT_SYMBOL(drm_gem_lru_remove); /** * drm_gem_lru_move_tail_locked - move the object to the tail of the LRU * * Like &drm_gem_lru_move_tail but lru lock must be held * * @lru: The LRU to move the object into. * @obj: The GEM object to move into this LRU */ void drm_gem_lru_move_tail_locked(struct drm_gem_lru *lru, struct drm_gem_object *obj) { lockdep_assert_held_once(lru->lock); if (obj->lru) drm_gem_lru_remove_locked(obj); lru->count += obj->size >> PAGE_SHIFT; list_add_tail(&obj->lru_node, &lru->list); obj->lru = lru; } EXPORT_SYMBOL(drm_gem_lru_move_tail_locked); /** * drm_gem_lru_move_tail - move the object to the tail of the LRU * * If the object is already in this LRU it will be moved to the * tail. Otherwise it will be removed from whichever other LRU * it is in (if any) and moved into this LRU. * * @lru: The LRU to move the object into. * @obj: The GEM object to move into this LRU */ void drm_gem_lru_move_tail(struct drm_gem_lru *lru, struct drm_gem_object *obj) { mutex_lock(lru->lock); drm_gem_lru_move_tail_locked(lru, obj); mutex_unlock(lru->lock); } EXPORT_SYMBOL(drm_gem_lru_move_tail); /** * drm_gem_lru_scan - helper to implement shrinker.scan_objects * * If the shrink callback succeeds, it is expected that the driver * move the object out of this LRU. * * If the LRU possibly contain active buffers, it is the responsibility * of the shrink callback to check for this (ie. dma_resv_test_signaled()) * or if necessary block until the buffer becomes idle. * * @lru: The LRU to scan * @nr_to_scan: The number of pages to try to reclaim * @remaining: The number of pages left to reclaim, should be initialized by caller * @shrink: Callback to try to shrink/reclaim the object. */ unsigned long drm_gem_lru_scan(struct drm_gem_lru *lru, unsigned int nr_to_scan, unsigned long *remaining, bool (*shrink)(struct drm_gem_object *obj)) { struct drm_gem_lru still_in_lru; struct drm_gem_object *obj; unsigned freed = 0; drm_gem_lru_init(&still_in_lru, lru->lock); mutex_lock(lru->lock); while (freed < nr_to_scan) { obj = list_first_entry_or_null(&lru->list, typeof(*obj), lru_node); if (!obj) break; drm_gem_lru_move_tail_locked(&still_in_lru, obj); /* * If it's in the process of being freed, gem_object->free() * may be blocked on lock waiting to remove it. So just * skip it. */ if (!kref_get_unless_zero(&obj->refcount)) continue; /* * Now that we own a reference, we can drop the lock for the * rest of the loop body, to reduce contention with other * code paths that need the LRU lock */ mutex_unlock(lru->lock); /* * Note that this still needs to be trylock, since we can * hit shrinker in response to trying to get backing pages * for this obj (ie. while it's lock is already held) */ if (!dma_resv_trylock(obj->resv)) { *remaining += obj->size >> PAGE_SHIFT; goto tail; } if (shrink(obj)) { freed += obj->size >> PAGE_SHIFT; /* * If we succeeded in releasing the object's backing * pages, we expect the driver to have moved the object * out of this LRU */ WARN_ON(obj->lru == &still_in_lru); WARN_ON(obj->lru == lru); } dma_resv_unlock(obj->resv); tail: drm_gem_object_put(obj); mutex_lock(lru->lock); } /* * Move objects we've skipped over out of the temporary still_in_lru * back into this LRU */ list_for_each_entry (obj, &still_in_lru.list, lru_node) obj->lru = lru; list_splice_tail(&still_in_lru.list, &lru->list); lru->count += still_in_lru.count; mutex_unlock(lru->lock); return freed; } EXPORT_SYMBOL(drm_gem_lru_scan); /** * drm_gem_evict - helper to evict backing pages for a GEM object * @obj: obj in question */ int drm_gem_evict(struct drm_gem_object *obj) { dma_resv_assert_held(obj->resv); if (!dma_resv_test_signaled(obj->resv, DMA_RESV_USAGE_READ)) return -EBUSY; if (obj->funcs->evict) return obj->funcs->evict(obj); return 0; } EXPORT_SYMBOL(drm_gem_evict);
3 409 401 5 404 395 14 398 318 92 365 2 367 14 14 14 14 14 2131 93 125 2251 10 3129 31 3129 2 230 230 5 2 3 2 1 100 100 2 1 2 95 95 161 5 159 1 6 6 2 1 1 2 1 3 11 5 2 3 65 8 39 26 6 5 3 27 3 18 18 37 1 1 2 14 3 2 3 6 9 1 148 100 99 90 1 10 98 1 85 15 1 190 188 3 189 367 367 161 161 147 148 412 412 406 13 398 2 397 397 389 12 378 4 382 2 435 1 416 18 435 478 216 276 198 292 16 2 1 1 6 7 2 9 14 4 4 3 1 1 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 /* $OpenBSD: kern_descrip.c,v 1.207 2022/12/05 23:18:37 deraadt Exp $ */ /* $NetBSD: kern_descrip.c,v 1.42 1996/03/30 22:24:38 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_descrip.c 8.6 (Berkeley) 4/19/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/filedesc.h> #include <sys/vnode.h> #include <sys/proc.h> #include <sys/file.h> #include <sys/socket.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <sys/fcntl.h> #include <sys/lock.h> #include <sys/malloc.h> #include <sys/ucred.h> #include <sys/unistd.h> #include <sys/resourcevar.h> #include <sys/mount.h> #include <sys/syscallargs.h> #include <sys/event.h> #include <sys/pool.h> #include <sys/ktrace.h> #include <sys/pledge.h> /* * Descriptor management. * * We need to block interrupts as long as `fhdlk' is being taken * with and without the KERNEL_LOCK(). */ struct mutex fhdlk = MUTEX_INITIALIZER(IPL_MPFLOOR); struct filelist filehead; /* head of list of open files */ int numfiles; /* actual number of open files */ static __inline void fd_used(struct filedesc *, int); static __inline void fd_unused(struct filedesc *, int); static __inline int find_next_zero(u_int *, int, u_int); static __inline int fd_inuse(struct filedesc *, int); int finishdup(struct proc *, struct file *, int, int, register_t *, int); int find_last_set(struct filedesc *, int); int dodup3(struct proc *, int, int, int, register_t *); #define DUPF_CLOEXEC 0x01 #define DUPF_DUP2 0x02 struct pool file_pool; struct pool fdesc_pool; void filedesc_init(void) { pool_init(&file_pool, sizeof(struct file), 0, IPL_MPFLOOR, PR_WAITOK, "filepl", NULL); pool_init(&fdesc_pool, sizeof(struct filedesc0), 0, IPL_NONE, PR_WAITOK, "fdescpl", NULL); LIST_INIT(&filehead); } static __inline int find_next_zero (u_int *bitmap, int want, u_int bits) { int i, off, maxoff; u_int sub; if (want > bits) return -1; off = want >> NDENTRYSHIFT; i = want & NDENTRYMASK; if (i) { sub = bitmap[off] | ((u_int)~0 >> (NDENTRIES - i)); if (sub != ~0) goto found; off++; } maxoff = NDLOSLOTS(bits); while (off < maxoff) { if ((sub = bitmap[off]) != ~0) goto found; off++; } return -1; found: return (off << NDENTRYSHIFT) + ffs(~sub) - 1; } int find_last_set(struct filedesc *fd, int last) { int off, i; u_int *bitmap = fd->fd_lomap; off = (last - 1) >> NDENTRYSHIFT; while (off >= 0 && !bitmap[off]) off--; if (off < 0) return 0; i = ((off + 1) << NDENTRYSHIFT) - 1; if (i >= last) i = last - 1; while (i > 0 && !fd_inuse(fd, i)) i--; return i; } static __inline int fd_inuse(struct filedesc *fdp, int fd) { u_int off = fd >> NDENTRYSHIFT; if (fdp->fd_lomap[off] & (1U << (fd & NDENTRYMASK))) return 1; return 0; } static __inline void fd_used(struct filedesc *fdp, int fd) { u_int off = fd >> NDENTRYSHIFT; fdp->fd_lomap[off] |= 1U << (fd & NDENTRYMASK); if (fdp->fd_lomap[off] == ~0) fdp->fd_himap[off >> NDENTRYSHIFT] |= 1U << (off & NDENTRYMASK); if (fd > fdp->fd_lastfile) fdp->fd_lastfile = fd; fdp->fd_openfd++; } static __inline void fd_unused(struct filedesc *fdp, int fd) { u_int off = fd >> NDENTRYSHIFT; if (fd < fdp->fd_freefile) fdp->fd_freefile = fd; if (fdp->fd_lomap[off] == ~0) fdp->fd_himap[off >> NDENTRYSHIFT] &= ~(1U << (off & NDENTRYMASK)); fdp->fd_lomap[off] &= ~(1U << (fd & NDENTRYMASK)); #ifdef DIAGNOSTIC if (fd > fdp->fd_lastfile) panic("fd_unused: fd_lastfile inconsistent"); #endif if (fd == fdp->fd_lastfile) fdp->fd_lastfile = find_last_set(fdp, fd); fdp->fd_openfd--; } struct file * fd_iterfile(struct file *fp, struct proc *p) { struct file *nfp; unsigned int count; mtx_enter(&fhdlk); if (fp == NULL) nfp = LIST_FIRST(&filehead); else nfp = LIST_NEXT(fp, f_list); /* don't refcount when f_count == 0 to avoid race in fdrop() */ while (nfp != NULL) { count = nfp->f_count; if (count == 0) { nfp = LIST_NEXT(nfp, f_list); continue; } if (atomic_cas_uint(&nfp->f_count, count, count + 1) == count) break; } mtx_leave(&fhdlk); if (fp != NULL) FRELE(fp, p); return nfp; } struct file * fd_getfile(struct filedesc *fdp, int fd) { struct file *fp; vfs_stall_barrier(); if ((u_int)fd >= fdp->fd_nfiles) return (NULL); mtx_enter(&fdp->fd_fplock); fp = fdp->fd_ofiles[fd]; if (fp != NULL) atomic_inc_int(&fp->f_count); mtx_leave(&fdp->fd_fplock); return (fp); } struct file * fd_getfile_mode(struct filedesc *fdp, int fd, int mode) { struct file *fp; KASSERT(mode != 0); fp = fd_getfile(fdp, fd); if (fp == NULL) return (NULL); if ((fp->f_flag & mode) == 0) { FRELE(fp, curproc); return (NULL); } return (fp); } int fd_checkclosed(struct filedesc *fdp, int fd, struct file *fp) { int closed; mtx_enter(&fdp->fd_fplock); KASSERT(fd < fdp->fd_nfiles); closed = (fdp->fd_ofiles[fd] != fp); mtx_leave(&fdp->fd_fplock); return (closed); } /* * System calls on descriptors. */ /* * Duplicate a file descriptor. */ int sys_dup(struct proc *p, void *v, register_t *retval) { struct sys_dup_args /* { syscallarg(int) fd; } */ *uap = v; struct filedesc *fdp = p->p_fd; int old = SCARG(uap, fd); struct file *fp; int new; int error; restart: if ((fp = fd_getfile(fdp, old)) == NULL) return (EBADF); fdplock(fdp); if ((error = fdalloc(p, 0, &new)) != 0) { if (error == ENOSPC) { fdexpand(p); fdpunlock(fdp); FRELE(fp, p); goto restart; } fdpunlock(fdp); FRELE(fp, p); return (error); } /* No need for FRELE(), finishdup() uses current ref. */ return (finishdup(p, fp, old, new, retval, 0)); } /* * Duplicate a file descriptor to a particular value. */ int sys_dup2(struct proc *p, void *v, register_t *retval) { struct sys_dup2_args /* { syscallarg(int) from; syscallarg(int) to; } */ *uap = v; return (dodup3(p, SCARG(uap, from), SCARG(uap, to), 0, retval)); } int sys_dup3(struct proc *p, void *v, register_t *retval) { struct sys_dup3_args /* { syscallarg(int) from; syscallarg(int) to; syscallarg(int) flags; } */ *uap = v; if (SCARG(uap, from) == SCARG(uap, to)) return (EINVAL); if (SCARG(uap, flags) & ~O_CLOEXEC) return (EINVAL); return (dodup3(p, SCARG(uap, from), SCARG(uap, to), SCARG(uap, flags), retval)); } int dodup3(struct proc *p, int old, int new, int flags, register_t *retval) { struct filedesc *fdp = p->p_fd; struct file *fp; int dupflags, error, i; restart: if ((fp = fd_getfile(fdp, old)) == NULL) return (EBADF); if (old == new) { /* * NOTE! This doesn't clear the close-on-exec flag. This might * or might not be the intended behavior from the start, but * this is what everyone else does. */ *retval = new; FRELE(fp, p); return (0); } if ((u_int)new >= lim_cur(RLIMIT_NOFILE) || (u_int)new >= maxfiles) { FRELE(fp, p); return (EBADF); } fdplock(fdp); if (new >= fdp->fd_nfiles) { if ((error = fdalloc(p, new, &i)) != 0) { if (error == ENOSPC) { fdexpand(p); fdpunlock(fdp); FRELE(fp, p); goto restart; } fdpunlock(fdp); FRELE(fp, p); return (error); } if (new != i) panic("dup2: fdalloc"); fd_unused(fdp, new); } dupflags = DUPF_DUP2; if (flags & O_CLOEXEC) dupflags |= DUPF_CLOEXEC; /* No need for FRELE(), finishdup() uses current ref. */ return (finishdup(p, fp, old, new, retval, dupflags)); } /* * The file control system call. */ int sys_fcntl(struct proc *p, void *v, register_t *retval) { struct sys_fcntl_args /* { syscallarg(int) fd; syscallarg(int) cmd; syscallarg(void *) arg; } */ *uap = v; int fd = SCARG(uap, fd); struct filedesc *fdp = p->p_fd; struct file *fp; struct vnode *vp; int i, prev, tmp, newmin, flg = F_POSIX; struct flock fl; int error = 0; error = pledge_fcntl(p, SCARG(uap, cmd)); if (error) return (error); restart: if ((fp = fd_getfile(fdp, fd)) == NULL) return (EBADF); switch (SCARG(uap, cmd)) { case F_DUPFD: case F_DUPFD_CLOEXEC: newmin = (long)SCARG(uap, arg); if ((u_int)newmin >= lim_cur(RLIMIT_NOFILE) || (u_int)newmin >= maxfiles) { error = EINVAL; break; } fdplock(fdp); if ((error = fdalloc(p, newmin, &i)) != 0) { if (error == ENOSPC) { fdexpand(p); fdpunlock(fdp); FRELE(fp, p); goto restart; } fdpunlock(fdp); FRELE(fp, p); } else { int dupflags = 0; if (SCARG(uap, cmd) == F_DUPFD_CLOEXEC) dupflags |= DUPF_CLOEXEC; /* No need for FRELE(), finishdup() uses current ref. */ error = finishdup(p, fp, fd, i, retval, dupflags); } return (error); case F_GETFD: fdplock(fdp); *retval = fdp->fd_ofileflags[fd] & UF_EXCLOSE ? 1 : 0; fdpunlock(fdp); break; case F_SETFD: fdplock(fdp); if ((long)SCARG(uap, arg) & 1) fdp->fd_ofileflags[fd] |= UF_EXCLOSE; else fdp->fd_ofileflags[fd] &= ~UF_EXCLOSE; fdpunlock(fdp); break; case F_GETFL: *retval = OFLAGS(fp->f_flag); break; case F_ISATTY: vp = fp->f_data; if (fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY)) *retval = 1; else { *retval = 0; error = ENOTTY; } break; case F_SETFL: do { tmp = prev = fp->f_flag; tmp &= ~FCNTLFLAGS; tmp |= FFLAGS((long)SCARG(uap, arg)) & FCNTLFLAGS; } while (atomic_cas_uint(&fp->f_flag, prev, tmp) != prev); tmp = fp->f_flag & FNONBLOCK; error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); if (error) break; tmp = fp->f_flag & FASYNC; error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p); if (!error) break; atomic_clearbits_int(&fp->f_flag, FNONBLOCK); tmp = 0; (void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); break; case F_GETOWN: tmp = 0; error = (*fp->f_ops->fo_ioctl) (fp, FIOGETOWN, (caddr_t)&tmp, p); *retval = tmp; break; case F_SETOWN: tmp = (long)SCARG(uap, arg); error = ((*fp->f_ops->fo_ioctl) (fp, FIOSETOWN, (caddr_t)&tmp, p)); break; case F_SETLKW: flg |= F_WAIT; /* FALLTHROUGH */ case F_SETLK: error = pledge_flock(p); if (error != 0) break; if (fp->f_type != DTYPE_VNODE) { error = EINVAL; break; } vp = fp->f_data; /* Copy in the lock structure */ error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&fl, sizeof (fl)); if (error) break; #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrflock(p, &fl); #endif if (fl.l_whence == SEEK_CUR) { off_t offset = foffset(fp); if (fl.l_start == 0 && fl.l_len < 0) { /* lockf(3) compliance hack */ fl.l_len = -fl.l_len; fl.l_start = offset - fl.l_len; } else fl.l_start += offset; } switch (fl.l_type) { case F_RDLCK: if ((fp->f_flag & FREAD) == 0) { error = EBADF; goto out; } atomic_setbits_int(&fdp->fd_flags, FD_ADVLOCK); error = VOP_ADVLOCK(vp, fdp, F_SETLK, &fl, flg); break; case F_WRLCK: if ((fp->f_flag & FWRITE) == 0) { error = EBADF; goto out; } atomic_setbits_int(&fdp->fd_flags, FD_ADVLOCK); error = VOP_ADVLOCK(vp, fdp, F_SETLK, &fl, flg); break; case F_UNLCK: error = VOP_ADVLOCK(vp, fdp, F_UNLCK, &fl, F_POSIX); goto out; default: error = EINVAL; goto out; } if (fd_checkclosed(fdp, fd, fp)) { /* * We have lost the race with close() or dup2(); * unlock, pretend that we've won the race and that * lock had been removed by close() */ fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; VOP_ADVLOCK(vp, fdp, F_UNLCK, &fl, F_POSIX); fl.l_type = F_UNLCK; } goto out; case F_GETLK: error = pledge_flock(p); if (error != 0) break; if (fp->f_type != DTYPE_VNODE) { error = EINVAL; break; } vp = fp->f_data; /* Copy in the lock structure */ error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&fl, sizeof (fl)); if (error) break; if (fl.l_whence == SEEK_CUR) { off_t offset = foffset(fp); if (fl.l_start == 0 && fl.l_len < 0) { /* lockf(3) compliance hack */ fl.l_len = -fl.l_len; fl.l_start = offset - fl.l_len; } else fl.l_start += offset; } if (fl.l_type != F_RDLCK && fl.l_type != F_WRLCK && fl.l_type != F_UNLCK && fl.l_type != 0) { error = EINVAL; break; } error = VOP_ADVLOCK(vp, fdp, F_GETLK, &fl, F_POSIX); if (error) break; #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrflock(p, &fl); #endif error = (copyout((caddr_t)&fl, (caddr_t)SCARG(uap, arg), sizeof (fl))); break; default: error = EINVAL; break; } out: FRELE(fp, p); return (error); } /* * Common code for dup, dup2, and fcntl(F_DUPFD). */ int finishdup(struct proc *p, struct file *fp, int old, int new, register_t *retval, int dupflags) { struct file *oldfp; struct filedesc *fdp = p->p_fd; int error; fdpassertlocked(fdp); KASSERT(fp->f_iflags & FIF_INSERTED); if (fp->f_count >= FDUP_MAX_COUNT) { error = EDEADLK; goto fail; } oldfp = fd_getfile(fdp, new); if ((dupflags & DUPF_DUP2) && oldfp == NULL) { if (fd_inuse(fdp, new)) { error = EBUSY; goto fail; } fd_used(fdp, new); } /* * Use `fd_fplock' to synchronize with fd_getfile() so that * the function no longer creates a new reference to the old file. */ mtx_enter(&fdp->fd_fplock); fdp->fd_ofiles[new] = fp; mtx_leave(&fdp->fd_fplock); fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] & ~UF_EXCLOSE; if (dupflags & DUPF_CLOEXEC) fdp->fd_ofileflags[new] |= UF_EXCLOSE; *retval = new; if (oldfp != NULL) { knote_fdclose(p, new); fdpunlock(fdp); closef(oldfp, p); } else { fdpunlock(fdp); } return (0); fail: fdpunlock(fdp); FRELE(fp, p); return (error); } void fdinsert(struct filedesc *fdp, int fd, int flags, struct file *fp) { struct file *fq; fdpassertlocked(fdp); mtx_enter(&fhdlk); if ((fp->f_iflags & FIF_INSERTED) == 0) { atomic_setbits_int(&fp->f_iflags, FIF_INSERTED); if ((fq = fdp->fd_ofiles[0]) != NULL) { LIST_INSERT_AFTER(fq, fp, f_list); } else { LIST_INSERT_HEAD(&filehead, fp, f_list); } } mtx_leave(&fhdlk); mtx_enter(&fdp->fd_fplock); KASSERT(fdp->fd_ofiles[fd] == NULL); fdp->fd_ofiles[fd] = fp; mtx_leave(&fdp->fd_fplock); fdp->fd_ofileflags[fd] |= (flags & UF_EXCLOSE); } void fdremove(struct filedesc *fdp, int fd) { fdpassertlocked(fdp); /* * Use `fd_fplock' to synchronize with fd_getfile() so that * the function no longer creates a new reference to the file. */ mtx_enter(&fdp->fd_fplock); fdp->fd_ofiles[fd] = NULL; mtx_leave(&fdp->fd_fplock); fdp->fd_ofileflags[fd] = 0; fd_unused(fdp, fd); } int fdrelease(struct proc *p, int fd) { struct filedesc *fdp = p->p_fd; struct file *fp; fdpassertlocked(fdp); fp = fd_getfile(fdp, fd); if (fp == NULL) { fdpunlock(fdp); return (EBADF); } fdremove(fdp, fd); knote_fdclose(p, fd); fdpunlock(fdp); return (closef(fp, p)); } /* * Close a file descriptor. */ int sys_close(struct proc *p, void *v, register_t *retval) { struct sys_close_args /* { syscallarg(int) fd; } */ *uap = v; int fd = SCARG(uap, fd), error; struct filedesc *fdp = p->p_fd; fdplock(fdp); /* fdrelease unlocks fdp. */ error = fdrelease(p, fd); return (error); } /* * Return status information about a file descriptor. */ int sys_fstat(struct proc *p, void *v, register_t *retval) { struct sys_fstat_args /* { syscallarg(int) fd; syscallarg(struct stat *) sb; } */ *uap = v; int fd = SCARG(uap, fd); struct filedesc *fdp = p->p_fd; struct file *fp; struct stat ub; int error; if ((fp = fd_getfile(fdp, fd)) == NULL) return (EBADF); error = (*fp->f_ops->fo_stat)(fp, &ub, p); FRELE(fp, p); if (error == 0) { /* * Don't let non-root see generation numbers * (for NFS security) */ if (suser(p)) ub.st_gen = 0; error = copyout((caddr_t)&ub, (caddr_t)SCARG(uap, sb), sizeof (ub)); } #ifdef KTRACE if (error == 0 && KTRPOINT(p, KTR_STRUCT)) ktrstat(p, &ub); #endif return (error); } /* * Return pathconf information about a file descriptor. */ int sys_fpathconf(struct proc *p, void *v, register_t *retval) { struct sys_fpathconf_args /* { syscallarg(int) fd; syscallarg(int) name; } */ *uap = v; int fd = SCARG(uap, fd); struct filedesc *fdp = p->p_fd; struct file *fp; struct vnode *vp; int error; if ((fp = fd_getfile(fdp, fd)) == NULL) return (EBADF); switch (fp->f_type) { case DTYPE_PIPE: case DTYPE_SOCKET: if (SCARG(uap, name) != _PC_PIPE_BUF) { error = EINVAL; break; } *retval = PIPE_BUF; error = 0; break; case DTYPE_VNODE: vp = fp->f_data; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); error = VOP_PATHCONF(vp, SCARG(uap, name), retval); VOP_UNLOCK(vp); break; default: error = EOPNOTSUPP; break; } FRELE(fp, p); return (error); } /* * Allocate a file descriptor for the process. */ int fdalloc(struct proc *p, int want, int *result) { struct filedesc *fdp = p->p_fd; int lim, last, i; u_int new, off; fdpassertlocked(fdp); /* * Search for a free descriptor starting at the higher * of want or fd_freefile. If that fails, consider * expanding the ofile array. */ restart: lim = min((int)lim_cur(RLIMIT_NOFILE), maxfiles); last = min(fdp->fd_nfiles, lim); if ((i = want) < fdp->fd_freefile) i = fdp->fd_freefile; off = i >> NDENTRYSHIFT; new = find_next_zero(fdp->fd_himap, off, (last + NDENTRIES - 1) >> NDENTRYSHIFT); if (new != -1) { i = find_next_zero(&fdp->fd_lomap[new], new > off ? 0 : i & NDENTRYMASK, NDENTRIES); if (i == -1) { /* * Free file descriptor in this block was * below want, try again with higher want. */ want = (new + 1) << NDENTRYSHIFT; goto restart; } i += (new << NDENTRYSHIFT); if (i < last) { fd_used(fdp, i); if (want <= fdp->fd_freefile) fdp->fd_freefile = i; *result = i; fdp->fd_ofileflags[i] = 0; if (ISSET(p->p_p->ps_flags, PS_PLEDGE)) fdp->fd_ofileflags[i] |= UF_PLEDGED; return (0); } } if (fdp->fd_nfiles >= lim) return (EMFILE); return (ENOSPC); } void fdexpand(struct proc *p) { struct filedesc *fdp = p->p_fd; int nfiles, oldnfiles; size_t copylen; struct file **newofile, **oldofile; char *newofileflags; u_int *newhimap, *newlomap; fdpassertlocked(fdp); oldnfiles = fdp->fd_nfiles; oldofile = fdp->fd_ofiles; /* * No space in current array. */ if (fdp->fd_nfiles < NDEXTENT) nfiles = NDEXTENT; else nfiles = 2 * fdp->fd_nfiles; newofile = mallocarray(nfiles, OFILESIZE, M_FILEDESC, M_WAITOK); /* * Allocate all required chunks before calling free(9) to make * sure that ``fd_ofiles'' stays valid if we go to sleep. */ if (NDHISLOTS(nfiles) > NDHISLOTS(fdp->fd_nfiles)) { newhimap = mallocarray(NDHISLOTS(nfiles), sizeof(u_int), M_FILEDESC, M_WAITOK); newlomap = mallocarray(NDLOSLOTS(nfiles), sizeof(u_int), M_FILEDESC, M_WAITOK); } newofileflags = (char *) &newofile[nfiles]; /* * Copy the existing ofile and ofileflags arrays * and zero the new portion of each array. */ copylen = sizeof(struct file *) * fdp->fd_nfiles; memcpy(newofile, fdp->fd_ofiles, copylen); memset((char *)newofile + copylen, 0, nfiles * sizeof(struct file *) - copylen); copylen = sizeof(char) * fdp->fd_nfiles; memcpy(newofileflags, fdp->fd_ofileflags, copylen); memset(newofileflags + copylen, 0, nfiles * sizeof(char) - copylen); if (NDHISLOTS(nfiles) > NDHISLOTS(fdp->fd_nfiles)) { copylen = NDHISLOTS(fdp->fd_nfiles) * sizeof(u_int); memcpy(newhimap, fdp->fd_himap, copylen); memset((char *)newhimap + copylen, 0, NDHISLOTS(nfiles) * sizeof(u_int) - copylen); copylen = NDLOSLOTS(fdp->fd_nfiles) * sizeof(u_int); memcpy(newlomap, fdp->fd_lomap, copylen); memset((char *)newlomap + copylen, 0, NDLOSLOTS(nfiles) * sizeof(u_int) - copylen); if (NDHISLOTS(fdp->fd_nfiles) > NDHISLOTS(NDFILE)) { free(fdp->fd_himap, M_FILEDESC, NDHISLOTS(fdp->fd_nfiles) * sizeof(u_int)); free(fdp->fd_lomap, M_FILEDESC, NDLOSLOTS(fdp->fd_nfiles) * sizeof(u_int)); } fdp->fd_himap = newhimap; fdp->fd_lomap = newlomap; } mtx_enter(&fdp->fd_fplock); fdp->fd_ofiles = newofile; mtx_leave(&fdp->fd_fplock); fdp->fd_ofileflags = newofileflags; fdp->fd_nfiles = nfiles; if (oldnfiles > NDFILE) free(oldofile, M_FILEDESC, oldnfiles * OFILESIZE); } /* * Create a new open file structure and allocate * a file descriptor for the process that refers to it. */ int falloc(struct proc *p, struct file **resultfp, int *resultfd) { struct file *fp; int error, i; KASSERT(resultfp != NULL); KASSERT(resultfd != NULL); fdpassertlocked(p->p_fd); restart: if ((error = fdalloc(p, 0, &i)) != 0) { if (error == ENOSPC) { fdexpand(p); goto restart; } return (error); } fp = fnew(p); if (fp == NULL) { fd_unused(p->p_fd, i); return (ENFILE); } FREF(fp); *resultfp = fp; *resultfd = i; return (0); } struct file * fnew(struct proc *p) { struct file *fp; int nfiles; nfiles = atomic_inc_int_nv(&numfiles); if (nfiles > maxfiles) { atomic_dec_int(&numfiles); tablefull("file"); return (NULL); } fp = pool_get(&file_pool, PR_WAITOK|PR_ZERO); /* * We need to block interrupts as long as `f_mtx' is being taken * with and without the KERNEL_LOCK(). */ mtx_init(&fp->f_mtx, IPL_MPFLOOR); fp->f_count = 1; fp->f_cred = p->p_ucred; crhold(fp->f_cred); return (fp); } /* * Build a new filedesc structure. */ struct filedesc * fdinit(void) { struct filedesc0 *newfdp; newfdp = pool_get(&fdesc_pool, PR_WAITOK|PR_ZERO); rw_init(&newfdp->fd_fd.fd_lock, "fdlock"); mtx_init(&newfdp->fd_fd.fd_fplock, IPL_MPFLOOR); LIST_INIT(&newfdp->fd_fd.fd_kqlist); /* Create the file descriptor table. */ newfdp->fd_fd.fd_refcnt = 1; newfdp->fd_fd.fd_cmask = S_IWGRP|S_IWOTH; newfdp->fd_fd.fd_ofiles = newfdp->fd_dfiles; newfdp->fd_fd.fd_ofileflags = newfdp->fd_dfileflags; newfdp->fd_fd.fd_nfiles = NDFILE; newfdp->fd_fd.fd_himap = newfdp->fd_dhimap; newfdp->fd_fd.fd_lomap = newfdp->fd_dlomap; newfdp->fd_fd.fd_freefile = 0; newfdp->fd_fd.fd_lastfile = 0; return (&newfdp->fd_fd); } /* * Share a filedesc structure. */ struct filedesc * fdshare(struct process *pr) { pr->ps_fd->fd_refcnt++; return (pr->ps_fd); } /* * Copy a filedesc structure. */ struct filedesc * fdcopy(struct process *pr) { struct filedesc *newfdp, *fdp = pr->ps_fd; int i; newfdp = fdinit(); fdplock(fdp); if (fdp->fd_cdir) { vref(fdp->fd_cdir); newfdp->fd_cdir = fdp->fd_cdir; } if (fdp->fd_rdir) { vref(fdp->fd_rdir); newfdp->fd_rdir = fdp->fd_rdir; } /* * If the number of open files fits in the internal arrays * of the open file structure, use them, otherwise allocate * additional memory for the number of descriptors currently * in use. */ if (fdp->fd_lastfile >= NDFILE) { /* * Compute the smallest multiple of NDEXTENT needed * for the file descriptors currently in use, * allowing the table to shrink. */ i = fdp->fd_nfiles; while (i >= 2 * NDEXTENT && i > fdp->fd_lastfile * 2) i /= 2; newfdp->fd_ofiles = mallocarray(i, OFILESIZE, M_FILEDESC, M_WAITOK | M_ZERO); newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i]; newfdp->fd_nfiles = i; } if (NDHISLOTS(newfdp->fd_nfiles) > NDHISLOTS(NDFILE)) { newfdp->fd_himap = mallocarray(NDHISLOTS(newfdp->fd_nfiles), sizeof(u_int), M_FILEDESC, M_WAITOK | M_ZERO); newfdp->fd_lomap = mallocarray(NDLOSLOTS(newfdp->fd_nfiles), sizeof(u_int), M_FILEDESC, M_WAITOK | M_ZERO); } newfdp->fd_freefile = fdp->fd_freefile; newfdp->fd_flags = fdp->fd_flags; newfdp->fd_cmask = fdp->fd_cmask; for (i = 0; i <= fdp->fd_lastfile; i++) { struct file *fp = fdp->fd_ofiles[i]; if (fp != NULL) { /* * XXX Gruesome hack. If count gets too high, fail * to copy an fd, since fdcopy()'s callers do not * permit it to indicate failure yet. * Meanwhile, kqueue files have to be * tied to the process that opened them to enforce * their internal consistency, so close them here. */ if (fp->f_count >= FDUP_MAX_COUNT || fp->f_type == DTYPE_KQUEUE) { if (i < newfdp->fd_freefile) newfdp->fd_freefile = i; continue; } FREF(fp); newfdp->fd_ofiles[i] = fp; newfdp->fd_ofileflags[i] = fdp->fd_ofileflags[i]; fd_used(newfdp, i); } } fdpunlock(fdp); return (newfdp); } /* * Release a filedesc structure. */ void fdfree(struct proc *p) { struct filedesc *fdp = p->p_fd; struct file *fp; int fd; if (--fdp->fd_refcnt > 0) return; for (fd = 0; fd <= fdp->fd_lastfile; fd++) { fp = fdp->fd_ofiles[fd]; if (fp != NULL) { fdp->fd_ofiles[fd] = NULL; knote_fdclose(p, fd); /* closef() expects a refcount of 2 */ FREF(fp); (void) closef(fp, p); } } p->p_fd = NULL; if (fdp->fd_nfiles > NDFILE) free(fdp->fd_ofiles, M_FILEDESC, fdp->fd_nfiles * OFILESIZE); if (NDHISLOTS(fdp->fd_nfiles) > NDHISLOTS(NDFILE)) { free(fdp->fd_himap, M_FILEDESC, NDHISLOTS(fdp->fd_nfiles) * sizeof(u_int)); free(fdp->fd_lomap, M_FILEDESC, NDLOSLOTS(fdp->fd_nfiles) * sizeof(u_int)); } if (fdp->fd_cdir) vrele(fdp->fd_cdir); if (fdp->fd_rdir) vrele(fdp->fd_rdir); pool_put(&fdesc_pool, fdp); } /* * Internal form of close. * Decrement reference count on file structure. * Note: p may be NULL when closing a file * that was being passed in a message. * * The fp must have its usecount bumped and will be FRELEd here. */ int closef(struct file *fp, struct proc *p) { struct filedesc *fdp; if (fp == NULL) return (0); KASSERTMSG(fp->f_count >= 2, "count (%u) < 2", fp->f_count); atomic_dec_int(&fp->f_count); /* * POSIX record locking dictates that any close releases ALL * locks owned by this process. This is handled by setting * a flag in the unlock to free ONLY locks obeying POSIX * semantics, and not to free BSD-style file locks. * If the descriptor was in a message, POSIX-style locks * aren't passed with the descriptor. */ if (p && ((fdp = p->p_fd) != NULL) && (fdp->fd_flags & FD_ADVLOCK) && fp->f_type == DTYPE_VNODE) { struct vnode *vp = fp->f_data; struct flock lf; lf.l_whence = SEEK_SET; lf.l_start = 0; lf.l_len = 0; lf.l_type = F_UNLCK; (void) VOP_ADVLOCK(vp, fdp, F_UNLCK, &lf, F_POSIX); } return (FRELE(fp, p)); } int fdrop(struct file *fp, struct proc *p) { int error; KASSERTMSG(fp->f_count == 0, "count (%u) != 0", fp->f_count); mtx_enter(&fhdlk); if (fp->f_iflags & FIF_INSERTED) LIST_REMOVE(fp, f_list); mtx_leave(&fhdlk); if (fp->f_ops) error = (*fp->f_ops->fo_close)(fp, p); else error = 0; crfree(fp->f_cred); atomic_dec_int(&numfiles); pool_put(&file_pool, fp); return (error); } /* * Apply an advisory lock on a file descriptor. * * Just attempt to get a record lock of the requested type on * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0). */ int sys_flock(struct proc *p, void *v, register_t *retval) { struct sys_flock_args /* { syscallarg(int) fd; syscallarg(int) how; } */ *uap = v; int fd = SCARG(uap, fd); int how = SCARG(uap, how); struct filedesc *fdp = p->p_fd; struct file *fp; struct vnode *vp; struct flock lf; int error; if ((fp = fd_getfile(fdp, fd)) == NULL) return (EBADF); if (fp->f_type != DTYPE_VNODE) { error = EOPNOTSUPP; goto out; } vp = fp->f_data; lf.l_whence = SEEK_SET; lf.l_start = 0; lf.l_len = 0; if (how & LOCK_UN) { lf.l_type = F_UNLCK; atomic_clearbits_int(&fp->f_iflags, FIF_HASLOCK); error = VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK); goto out; } if (how & LOCK_EX) lf.l_type = F_WRLCK; else if (how & LOCK_SH) lf.l_type = F_RDLCK; else { error = EINVAL; goto out; } atomic_setbits_int(&fp->f_iflags, FIF_HASLOCK); if (how & LOCK_NB) error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK); else error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT); out: FRELE(fp, p); return (error); } /* * File Descriptor pseudo-device driver (/dev/fd/). * * Opening minor device N dup()s the file (if any) connected to file * descriptor N belonging to the calling process. Note that this driver * consists of only the ``open()'' routine, because all subsequent * references to this file will be direct to the other driver. */ int filedescopen(dev_t dev, int mode, int type, struct proc *p) { /* * XXX Kludge: set curproc->p_dupfd to contain the value of the * the file descriptor being sought for duplication. The error * return ensures that the vnode for this device will be released * by vn_open. Open will detect this special error and take the * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN * will simply report the error. */ p->p_dupfd = minor(dev); return (ENODEV); } /* * Duplicate the specified descriptor to a free descriptor. */ int dupfdopen(struct proc *p, int indx, int mode) { struct filedesc *fdp = p->p_fd; int dupfd = p->p_dupfd; struct file *wfp; fdpassertlocked(fdp); /* * Assume that the filename was user-specified; applications do * not tend to open /dev/fd/# when they can just call dup() */ if ((p->p_p->ps_flags & (PS_SUGIDEXEC | PS_SUGID))) { if (p->p_descfd == 255) return (EPERM); if (p->p_descfd != dupfd) return (EPERM); } /* * If the to-be-dup'd fd number is greater than the allowed number * of file descriptors, or the fd to be dup'd has already been * closed, reject. Note, there is no need to check for new == old * because fd_getfile will return NULL if the file at indx is * newly created by falloc. */ if ((wfp = fd_getfile(fdp, dupfd)) == NULL) return (EBADF); /* * Check that the mode the file is being opened for is a * subset of the mode of the existing descriptor. */ if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) { FRELE(wfp, p); return (EACCES); } if (wfp->f_count >= FDUP_MAX_COUNT) { FRELE(wfp, p); return (EDEADLK); } KASSERT(wfp->f_iflags & FIF_INSERTED); mtx_enter(&fdp->fd_fplock); KASSERT(fdp->fd_ofiles[indx] == NULL); fdp->fd_ofiles[indx] = wfp; mtx_leave(&fdp->fd_fplock); fdp->fd_ofileflags[indx] = (fdp->fd_ofileflags[indx] & UF_EXCLOSE) | (fdp->fd_ofileflags[dupfd] & ~UF_EXCLOSE); return (0); } /* * Close any files on exec? */ void fdcloseexec(struct proc *p) { struct filedesc *fdp = p->p_fd; int fd; fdplock(fdp); for (fd = 0; fd <= fdp->fd_lastfile; fd++) { fdp->fd_ofileflags[fd] &= ~UF_PLEDGED; if (fdp->fd_ofileflags[fd] & UF_EXCLOSE) { /* fdrelease() unlocks fdp. */ (void) fdrelease(p, fd); fdplock(fdp); } } fdpunlock(fdp); } int sys_closefrom(struct proc *p, void *v, register_t *retval) { struct sys_closefrom_args *uap = v; struct filedesc *fdp = p->p_fd; u_int startfd, i; startfd = SCARG(uap, fd); fdplock(fdp); if (startfd > fdp->fd_lastfile) { fdpunlock(fdp); return (EBADF); } for (i = startfd; i <= fdp->fd_lastfile; i++) { /* fdrelease() unlocks fdp. */ fdrelease(p, i); fdplock(fdp); } fdpunlock(fdp); return (0); } int sys_getdtablecount(struct proc *p, void *v, register_t *retval) { *retval = p->p_fd->fd_openfd; return (0); }
459 459 734 734 12 12 12 13 13 13 377 377 263 262 262 263 746 745 748 131 130 102 102 102 369 368 367 2150 2151 2145 859 863 141 144 18 18 17 17 17 14 14 14 1 13 6 6 6 65 65 65 19 19 19 6 6 6 6 8 8 8 10 10 10 18 18 18 96 95 509 508 508 154 154 3064 3068 3063 3067 23 23 23 112 111 216 216 216 155 155 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 /* $OpenBSD: vfs_vops.c,v 1.36 2024/05/13 11:17:40 semarie Exp $ */ /* * Copyright (c) 2010 Thordur I. Bjornsson <thib@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <sys/param.h> #include <sys/vnode.h> #include <sys/unistd.h> #include <sys/systm.h> #ifdef VFSLCKDEBUG #define ASSERT_VP_ISLOCKED(vp) do { \ if (((vp)->v_flag & VLOCKSWORK) && !VOP_ISLOCKED(vp)) { \ VOP_PRINT(vp); \ panic("vp not locked"); \ } \ } while (0) #else #define ASSERT_VP_ISLOCKED(vp) /* nothing */ #endif int VOP_ISLOCKED(struct vnode *vp) { struct vop_islocked_args a; a.a_vp = vp; if (vp->v_op->vop_islocked == NULL) return (EOPNOTSUPP); return ((vp->v_op->vop_islocked)(&a)); } int VOP_LOOKUP(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp) { struct vop_lookup_args a; a.a_dvp = dvp; a.a_vpp = vpp; a.a_cnp = cnp; if (dvp->v_op->vop_lookup == NULL) return (EOPNOTSUPP); return ((dvp->v_op->vop_lookup)(&a)); } int VOP_CREATE(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, struct vattr *vap) { struct vop_create_args a; a.a_dvp = dvp; a.a_vpp = vpp; a.a_cnp = cnp; a.a_vap = vap; ASSERT_VP_ISLOCKED(dvp); if (dvp->v_op->vop_create == NULL) return (EOPNOTSUPP); return ((dvp->v_op->vop_create)(&a)); } int VOP_MKNOD(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, struct vattr *vap) { struct vop_mknod_args a; a.a_dvp = dvp; a.a_vpp = vpp; a.a_cnp = cnp; a.a_vap = vap; ASSERT_VP_ISLOCKED(dvp); if (dvp->v_op->vop_mknod == NULL) return (EOPNOTSUPP); return ((dvp->v_op->vop_mknod)(&a)); } int VOP_OPEN(struct vnode *vp, int mode, struct ucred *cred, struct proc *p) { struct vop_open_args a; a.a_vp = vp; a.a_mode = mode; a.a_cred = cred; a.a_p = p; KASSERT(p == curproc); if (vp->v_op->vop_open == NULL) return (EOPNOTSUPP); return ((vp->v_op->vop_open)(&a)); } int VOP_CLOSE(struct vnode *vp, int fflag, struct ucred *cred, struct proc *p) { struct vop_close_args a; a.a_vp = vp; a.a_fflag = fflag; a.a_cred = cred; a.a_p = p; KASSERT(p == NULL || p == curproc); ASSERT_VP_ISLOCKED(vp); if (vp->v_op->vop_close == NULL) return (EOPNOTSUPP); return ((vp->v_op->vop_close)(&a)); } int VOP_ACCESS(struct vnode *vp, int mode, struct ucred *cred, struct proc *p) { struct vop_access_args a; a.a_vp = vp; a.a_mode = mode; a.a_cred = cred; a.a_p = p; KASSERT(p == curproc); ASSERT_VP_ISLOCKED(vp); if (vp->v_op->vop_access == NULL) return (EOPNOTSUPP); return ((vp->v_op->vop_access)(&a)); } int VOP_GETATTR(struct vnode *vp, struct vattr *vap, struct ucred *cred, struct proc *p) { struct vop_getattr_args a; a.a_vp = vp; a.a_vap = vap; a.a_cred = cred; a.a_p = p; KASSERT(p == curproc); if (vp->v_op->vop_getattr == NULL) return (EOPNOTSUPP); return ((vp->v_op->vop_getattr)(&a)); } int VOP_SETATTR(struct vnode *vp, struct vattr *vap, struct ucred *cred, struct proc *p) { struct vop_setattr_args a; a.a_vp = vp; a.a_vap = vap; a.a_cred = cred; a.a_p = p; KASSERT(p == curproc); ASSERT_VP_ISLOCKED(vp); if (vp->v_op->vop_setattr == NULL) return (EOPNOTSUPP); return ((vp->v_op->vop_setattr)(&a)); } int VOP_READ(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred) { struct vop_read_args a; a.a_vp = vp; a.a_uio = uio; a.a_ioflag = ioflag; a.a_cred = cred; ASSERT_VP_ISLOCKED(vp); if (vp->v_op->vop_read == NULL) return (EOPNOTSUPP); return ((vp->v_op->vop_read)(&a)); } int VOP_WRITE(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred) { struct vop_write_args a; a.a_vp = vp; a.a_uio = uio; a.a_ioflag = ioflag; a.a_cred = cred; ASSERT_VP_ISLOCKED(vp); if (vp->v_op->vop_write == NULL) return (EOPNOTSUPP); return ((vp->v_op->vop_write)(&a)); } int VOP_IOCTL(struct vnode *vp, u_long command, void *data, int fflag, struct ucred *cred, struct proc *p) { struct vop_ioctl_args a; a.a_vp = vp; a.a_command = command; a.a_data = data; a.a_fflag = fflag; a.a_cred = cred; a.a_p = p; KASSERT(p == curproc); if (vp->v_op->vop_ioctl == NULL) return (EOPNOTSUPP); return ((vp->v_op->vop_ioctl)(&a)); } int VOP_KQFILTER(struct vnode *vp, int fflag, struct knote *kn) { struct vop_kqfilter_args a; a.a_vp = vp; a.a_fflag = fflag; a.a_kn = kn; if (vp->v_op->vop_kqfilter == NULL) return (EOPNOTSUPP); return ((vp->v_op->vop_kqfilter)(&a)); } int VOP_REVOKE(struct vnode *vp, int flags) { struct vop_revoke_args a; a.a_vp = vp; a.a_flags = flags; if (vp->v_op->vop_revoke == NULL) return (EOPNOTSUPP); return ((vp->v_op->vop_revoke)(&a)); } int VOP_FSYNC(struct vnode *vp, struct ucred *cred, int waitfor, struct proc *p) { int r, s; struct vop_fsync_args a; a.a_vp = vp; a.a_cred = cred; a.a_waitfor = waitfor; a.a_p = p; KASSERT(p == curproc); ASSERT_VP_ISLOCKED(vp); if (vp->v_op->vop_fsync == NULL) return (EOPNOTSUPP); r = (vp->v_op->vop_fsync)(&a); s = splbio(); if (r == 0 && vp->v_bioflag & VBIOERROR) r = EIO; splx(s); return r; } int VOP_REMOVE(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) { int error; struct vop_remove_args a; a.a_dvp = dvp; a.a_vp = vp; a.a_cnp = cnp; ASSERT_VP_ISLOCKED(dvp); ASSERT_VP_ISLOCKED(vp); error = dvp->v_op->vop_remove(&a); if (dvp == vp) vrele(vp); else vput(vp); vput(dvp); return error; } int VOP_LINK(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) { struct vop_link_args a; a.a_dvp = dvp; a.a_vp = vp; a.a_cnp = cnp; ASSERT_VP_ISLOCKED(dvp); if (dvp->v_op->vop_link == NULL) return (EOPNOTSUPP); return ((dvp->v_op->vop_link)(&a)); } int VOP_RENAME(struct vnode *fdvp, struct vnode *fvp, struct componentname *fcnp, struct vnode *tdvp, struct vnode *tvp, struct componentname *tcnp) { struct vop_rename_args a; a.a_fdvp = fdvp; a.a_fvp = fvp; a.a_fcnp = fcnp; a.a_tdvp = tdvp; a.a_tvp = tvp; a.a_tcnp = tcnp; ASSERT_VP_ISLOCKED(tdvp); if (fdvp->v_op->vop_rename == NULL) return (EOPNOTSUPP); return ((fdvp->v_op->vop_rename)(&a)); } int VOP_MKDIR(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, struct vattr *vap) { struct vop_mkdir_args a; a.a_dvp = dvp; a.a_vpp = vpp; a.a_cnp = cnp; a.a_vap = vap; ASSERT_VP_ISLOCKED(dvp); if (dvp->v_op->vop_mkdir == NULL) return (EOPNOTSUPP); return ((dvp->v_op->vop_mkdir)(&a)); } int VOP_RMDIR(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) { struct vop_rmdir_args a; a.a_dvp = dvp; a.a_vp = vp; a.a_cnp = cnp; ASSERT_VP_ISLOCKED(dvp); ASSERT_VP_ISLOCKED(vp); KASSERT(dvp != vp); if (dvp->v_op->vop_rmdir == NULL) return (EOPNOTSUPP); return ((dvp->v_op->vop_rmdir)(&a)); } int VOP_SYMLINK(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, struct vattr *vap, char *target) { struct vop_symlink_args a; a.a_dvp = dvp; a.a_vpp = vpp; a.a_cnp = cnp; a.a_vap = vap; a.a_target = target; ASSERT_VP_ISLOCKED(dvp); if (dvp->v_op->vop_symlink == NULL) return (EOPNOTSUPP); return ((dvp->v_op->vop_symlink)(&a)); } int VOP_READDIR(struct vnode *vp, struct uio *uio, struct ucred *cred, int *eofflag) { struct vop_readdir_args a; a.a_vp = vp; a.a_uio = uio; a.a_cred = cred; a.a_eofflag = eofflag; ASSERT_VP_ISLOCKED(vp); if (vp->v_op->vop_readdir == NULL) return (EOPNOTSUPP); return ((vp->v_op->vop_readdir)(&a)); } int VOP_READLINK(struct vnode *vp, struct uio *uio, struct ucred *cred) { struct vop_readlink_args a; a.a_vp = vp; a.a_uio = uio; a.a_cred = cred; ASSERT_VP_ISLOCKED(vp); if (vp->v_op->vop_readlink == NULL) return (EOPNOTSUPP); return ((vp->v_op->vop_readlink)(&a)); } int VOP_ABORTOP(struct vnode *dvp, struct componentname *cnp) { struct vop_abortop_args a; a.a_dvp = dvp; a.a_cnp = cnp; if (dvp->v_op->vop_abortop == NULL) return (EOPNOTSUPP); return ((dvp->v_op->vop_abortop)(&a)); } int VOP_INACTIVE(struct vnode *vp, struct proc *p) { struct vop_inactive_args a; a.a_vp = vp; a.a_p = p; KASSERT(p == curproc); ASSERT_VP_ISLOCKED(vp); if (vp->v_op->vop_inactive == NULL) return (EOPNOTSUPP); return ((vp->v_op->vop_inactive)(&a)); } int VOP_RECLAIM(struct vnode *vp, struct proc *p) { struct vop_reclaim_args a; a.a_vp = vp; a.a_p = p; KASSERT(p == curproc); if (vp->v_op->vop_reclaim == NULL) return (EOPNOTSUPP); return ((vp->v_op->vop_reclaim)(&a)); } int VOP_LOCK(struct vnode *vp, int flags) { struct vop_lock_args a; a.a_vp = vp; a.a_flags = flags; MUTEX_ASSERT_UNLOCKED(&vnode_mtx); if (vp->v_op->vop_lock == NULL) return (EOPNOTSUPP); return ((vp->v_op->vop_lock)(&a)); } int VOP_UNLOCK(struct vnode *vp) { struct vop_unlock_args a; a.a_vp = vp; if (vp->v_op->vop_unlock == NULL) return (EOPNOTSUPP); return ((vp->v_op->vop_unlock)(&a)); } int VOP_BMAP(struct vnode *vp, daddr_t bn, struct vnode **vpp, daddr_t *bnp, int *runp) { struct vop_bmap_args a; a.a_vp = vp; a.a_bn = bn; a.a_vpp = vpp; a.a_bnp = bnp; a.a_runp = runp; ASSERT_VP_ISLOCKED(vp); if (vp->v_op->vop_bmap == NULL) return (EOPNOTSUPP); return ((vp->v_op->vop_bmap)(&a)); } int VOP_PRINT(struct vnode *vp) { struct vop_print_args a; a.a_vp = vp; if (vp->v_op->vop_print == NULL) return (EOPNOTSUPP); return ((vp->v_op->vop_print)(&a)); } int VOP_PATHCONF(struct vnode *vp, int name, register_t *retval) { struct vop_pathconf_args a; /* * Handle names that are constant across filesystem */ switch (name) { case _PC_PATH_MAX: *retval = PATH_MAX; return (0); case _PC_PIPE_BUF: *retval = PIPE_BUF; return (0); case _PC_ASYNC_IO: case _PC_PRIO_IO: case _PC_SYNC_IO: *retval = 0; return (0); } a.a_vp = vp; a.a_name = name; a.a_retval = retval; ASSERT_VP_ISLOCKED(vp); if (vp->v_op->vop_pathconf == NULL) return (EOPNOTSUPP); return ((vp->v_op->vop_pathconf)(&a)); } int VOP_ADVLOCK(struct vnode *vp, void *id, int op, struct flock *fl, int flags) { struct vop_advlock_args a; a.a_vp = vp; a.a_id = id; a.a_op = op; a.a_fl = fl; a.a_flags = flags; if (vp->v_op->vop_advlock == NULL) return (EOPNOTSUPP); return (vp->v_op->vop_advlock)(&a); } int VOP_STRATEGY(struct vnode *vp, struct buf *bp) { struct vop_strategy_args a; a.a_vp = vp; a.a_bp = bp; if ((ISSET(bp->b_flags, B_BC)) && (!ISSET(bp->b_flags, B_DMA))) panic("Non dma reachable buffer passed to VOP_STRATEGY"); if (vp->v_op->vop_strategy == NULL) return (EOPNOTSUPP); return ((vp->v_op->vop_strategy)(&a)); } int VOP_BWRITE(struct buf *bp) { struct vop_bwrite_args a; a.a_bp = bp; if (bp->b_vp->v_op->vop_bwrite == NULL) return (EOPNOTSUPP); return ((bp->b_vp->v_op->vop_bwrite)(&a)); }
5 5 4 4 2 2 2 4 1 4 4 1 1 142 142 1 139 1 3 23 3 1 2 1 2 3 2 1 1 2 1 1 1 1 1 1 7 3 4 209 209 209 209 4 209 3 89 63 130 129 6 162 162 163 160 8 8 8 7 1 8 8 8 138 140 1 1 1 1 133 55 76 1 130 128 1 6 5 26 74 24 19 35 2 1 66 32 65 2 9 2 5 2 2 8 86 7 79 79 1 32 32 8 24 7 1 1 8 1 5 2 30 31 3 5 23 6 1 1 23 31 9 32 32 32 30 2 32 31 31 26 6 8 122 120 118 2 2 115 117 115 104 93 2 4 5 1 6 3 2 92 3 125 125 126 99 98 75 126 126 99 124 10 18 18 18 8 10 8 10 79 78 39 5 73 79 24 79 47 48 55 55 31 31 5 2 1 1 1 1 4 4 1 4 4 6 6 6 6 6 3 5 4 4 4 4 2 30 1 2 11 17 8 6 1 6 6 2 2 1 4 2 2 1 2 8 3 9 2 16 2 9 1 2 2 9 1 1 7 1 1 7 7 2 1 1 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 /* $OpenBSD: rtsock.c,v 1.373 2023/12/03 10:51:17 mvs Exp $ */ /* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 1988, 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)rtsock.c 8.6 (Berkeley) 2/11/95 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/sysctl.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/domain.h> #include <sys/pool.h> #include <sys/protosw.h> #include <sys/srp.h> #include <net/if.h> #include <net/if_dl.h> #include <net/if_var.h> #include <net/route.h> #include <netinet/in.h> #ifdef MPLS #include <netmpls/mpls.h> #endif #ifdef IPSEC #include <netinet/ip_ipsp.h> #include <net/if_enc.h> #endif #ifdef BFD #include <net/bfd.h> #endif #include <sys/stdarg.h> #include <sys/kernel.h> #include <sys/timeout.h> #define ROUTESNDQ 8192 #define ROUTERCVQ 8192 const struct sockaddr route_src = { 2, PF_ROUTE, }; struct walkarg { int w_op, w_arg, w_tmemsize; size_t w_given, w_needed; caddr_t w_where, w_tmem; }; void route_prinit(void); void rcb_ref(void *, void *); void rcb_unref(void *, void *); int route_output(struct mbuf *, struct socket *); int route_ctloutput(int, struct socket *, int, int, struct mbuf *); int route_attach(struct socket *, int, int); int route_detach(struct socket *); int route_disconnect(struct socket *); int route_shutdown(struct socket *); void route_rcvd(struct socket *); int route_send(struct socket *, struct mbuf *, struct mbuf *, struct mbuf *); int route_sockaddr(struct socket *, struct mbuf *); int route_peeraddr(struct socket *, struct mbuf *); void route_input(struct mbuf *m0, struct socket *, sa_family_t); int route_arp_conflict(struct rtentry *, struct rt_addrinfo *); int route_cleargateway(struct rtentry *, void *, unsigned int); void rtm_senddesync_timer(void *); void rtm_senddesync(struct socket *); int rtm_sendup(struct socket *, struct mbuf *); int rtm_getifa(struct rt_addrinfo *, unsigned int); int rtm_output(struct rt_msghdr *, struct rtentry **, struct rt_addrinfo *, uint8_t, unsigned int); struct rt_msghdr *rtm_report(struct rtentry *, u_char, int, int); struct mbuf *rtm_msg1(int, struct rt_addrinfo *); int rtm_msg2(int, int, struct rt_addrinfo *, caddr_t, struct walkarg *); int rtm_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *); int rtm_validate_proposal(struct rt_addrinfo *); void rtm_setmetrics(u_long, const struct rt_metrics *, struct rt_kmetrics *); void rtm_getmetrics(const struct rtentry *, struct rt_metrics *); int sysctl_iflist(int, struct walkarg *); int sysctl_ifnames(struct walkarg *); int sysctl_rtable_rtstat(void *, size_t *, void *); int rt_setsource(unsigned int, const struct sockaddr *); /* * Locks used to protect struct members * I immutable after creation * s solock */ struct rtpcb { struct socket *rop_socket; /* [I] */ SRPL_ENTRY(rtpcb) rop_list; struct refcnt rop_refcnt; struct timeout rop_timeout; unsigned int rop_msgfilter; /* [s] */ unsigned int rop_flagfilter; /* [s] */ unsigned int rop_flags; /* [s] */ u_int rop_rtableid; /* [s] */ unsigned short rop_proto; /* [I] */ u_char rop_priority; /* [s] */ }; #define sotortpcb(so) ((struct rtpcb *)(so)->so_pcb) struct rtptable { SRPL_HEAD(, rtpcb) rtp_list; struct srpl_rc rtp_rc; struct rwlock rtp_lk; unsigned int rtp_count; }; struct pool rtpcb_pool; struct rtptable rtptable; /* * These flags and timeout are used for indicating to userland (via a * RTM_DESYNC msg) when the route socket has overflowed and messages * have been lost. */ #define ROUTECB_FLAG_DESYNC 0x1 /* Route socket out of memory */ #define ROUTECB_FLAG_FLUSH 0x2 /* Wait until socket is empty before queueing more packets */ #define ROUTE_DESYNC_RESEND_TIMEOUT 200 /* In ms */ void route_prinit(void) { srpl_rc_init(&rtptable.rtp_rc, rcb_ref, rcb_unref, NULL); rw_init(&rtptable.rtp_lk, "rtsock"); SRPL_INIT(&rtptable.rtp_list); pool_init(&rtpcb_pool, sizeof(struct rtpcb), 0, IPL_SOFTNET, PR_WAITOK, "rtpcb", NULL); } void rcb_ref(void *null, void *v) { struct rtpcb *rop = v; refcnt_take(&rop->rop_refcnt); } void rcb_unref(void *null, void *v) { struct rtpcb *rop = v; refcnt_rele_wake(&rop->rop_refcnt); } int route_attach(struct socket *so, int proto, int wait) { struct rtpcb *rop; int error; error = soreserve(so, ROUTESNDQ, ROUTERCVQ); if (error) return (error); /* * use the rawcb but allocate a rtpcb, this * code does not care about the additional fields * and works directly on the raw socket. */ rop = pool_get(&rtpcb_pool, (wait == M_WAIT ? PR_WAITOK : PR_NOWAIT) | PR_ZERO); if (rop == NULL) return (ENOBUFS); so->so_pcb = rop; /* Init the timeout structure */ timeout_set_flags(&rop->rop_timeout, rtm_senddesync_timer, so, KCLOCK_NONE, TIMEOUT_PROC | TIMEOUT_MPSAFE); refcnt_init(&rop->rop_refcnt); rop->rop_socket = so; rop->rop_proto = proto; rop->rop_rtableid = curproc->p_p->ps_rtableid; soisconnected(so); so->so_options |= SO_USELOOPBACK; rw_enter(&rtptable.rtp_lk, RW_WRITE); SRPL_INSERT_HEAD_LOCKED(&rtptable.rtp_rc, &rtptable.rtp_list, rop, rop_list); rtptable.rtp_count++; rw_exit(&rtptable.rtp_lk); return (0); } int route_detach(struct socket *so) { struct rtpcb *rop; soassertlocked(so); rop = sotortpcb(so); if (rop == NULL) return (EINVAL); rw_enter(&rtptable.rtp_lk, RW_WRITE); rtptable.rtp_count--; SRPL_REMOVE_LOCKED(&rtptable.rtp_rc, &rtptable.rtp_list, rop, rtpcb, rop_list); rw_exit(&rtptable.rtp_lk); sounlock(so); /* wait for all references to drop */ refcnt_finalize(&rop->rop_refcnt, "rtsockrefs"); timeout_del_barrier(&rop->rop_timeout); solock(so); so->so_pcb = NULL; KASSERT((so->so_state & SS_NOFDREF) == 0); pool_put(&rtpcb_pool, rop); return (0); } int route_disconnect(struct socket *so) { soisdisconnected(so); return (0); } int route_shutdown(struct socket *so) { socantsendmore(so); return (0); } void route_rcvd(struct socket *so) { struct rtpcb *rop = sotortpcb(so); soassertlocked(so); /* * If we are in a FLUSH state, check if the buffer is * empty so that we can clear the flag. */ if (((rop->rop_flags & ROUTECB_FLAG_FLUSH) != 0) && ((sbspace(rop->rop_socket, &rop->rop_socket->so_rcv) == rop->rop_socket->so_rcv.sb_hiwat))) rop->rop_flags &= ~ROUTECB_FLAG_FLUSH; } int route_send(struct socket *so, struct mbuf *m, struct mbuf *nam, struct mbuf *control) { int error; soassertlocked(so); if (control && control->m_len) { error = EOPNOTSUPP; goto out; } if (nam) { error = EISCONN; goto out; } error = route_output(m, so); m = NULL; out: m_freem(control); m_freem(m); return (error); } int route_sockaddr(struct socket *so, struct mbuf *nam) { return (EINVAL); } int route_peeraddr(struct socket *so, struct mbuf *nam) { /* minimal support, just implement a fake peer address */ bcopy(&route_src, mtod(nam, caddr_t), route_src.sa_len); nam->m_len = route_src.sa_len; return (0); } int route_ctloutput(int op, struct socket *so, int level, int optname, struct mbuf *m) { struct rtpcb *rop = sotortpcb(so); int error = 0; unsigned int tid, prio; if (level != AF_ROUTE) return (EINVAL); switch (op) { case PRCO_SETOPT: switch (optname) { case ROUTE_MSGFILTER: if (m == NULL || m->m_len != sizeof(unsigned int)) error = EINVAL; else rop->rop_msgfilter = *mtod(m, unsigned int *); break; case ROUTE_TABLEFILTER: if (m == NULL || m->m_len != sizeof(unsigned int)) { error = EINVAL; break; } tid = *mtod(m, unsigned int *); if (tid != RTABLE_ANY && !rtable_exists(tid)) error = ENOENT; else rop->rop_rtableid = tid; break; case ROUTE_PRIOFILTER: if (m == NULL || m->m_len != sizeof(unsigned int)) { error = EINVAL; break; } prio = *mtod(m, unsigned int *); if (prio > RTP_MAX) error = EINVAL; else rop->rop_priority = prio; break; case ROUTE_FLAGFILTER: if (m == NULL || m->m_len != sizeof(unsigned int)) error = EINVAL; else rop->rop_flagfilter = *mtod(m, unsigned int *); break; default: error = ENOPROTOOPT; break; } break; case PRCO_GETOPT: switch (optname) { case ROUTE_MSGFILTER: m->m_len = sizeof(unsigned int); *mtod(m, unsigned int *) = rop->rop_msgfilter; break; case ROUTE_TABLEFILTER: m->m_len = sizeof(unsigned int); *mtod(m, unsigned int *) = rop->rop_rtableid; break; case ROUTE_PRIOFILTER: m->m_len = sizeof(unsigned int); *mtod(m, unsigned int *) = rop->rop_priority; break; case ROUTE_FLAGFILTER: m->m_len = sizeof(unsigned int); *mtod(m, unsigned int *) = rop->rop_flagfilter; break; default: error = ENOPROTOOPT; break; } } return (error); } void rtm_senddesync_timer(void *xso) { struct socket *so = xso; solock(so); rtm_senddesync(so); sounlock(so); } void rtm_senddesync(struct socket *so) { struct rtpcb *rop = sotortpcb(so); struct mbuf *desync_mbuf; soassertlocked(so); /* * Dying socket is disconnected by upper layer and there is * no reason to send packet. Also we shouldn't reschedule * timeout(9), otherwise timeout_del_barrier(9) can't help us. */ if ((so->so_state & SS_ISCONNECTED) == 0 || (so->so_rcv.sb_state & SS_CANTRCVMORE)) return; /* If we are in a DESYNC state, try to send a RTM_DESYNC packet */ if ((rop->rop_flags & ROUTECB_FLAG_DESYNC) == 0) return; /* * If we fail to alloc memory or if sbappendaddr() * fails, re-add timeout and try again. */ desync_mbuf = rtm_msg1(RTM_DESYNC, NULL); if (desync_mbuf != NULL) { if (sbappendaddr(so, &so->so_rcv, &route_src, desync_mbuf, NULL) != 0) { rop->rop_flags &= ~ROUTECB_FLAG_DESYNC; sorwakeup(rop->rop_socket); return; } m_freem(desync_mbuf); } /* Re-add timeout to try sending msg again */ timeout_add_msec(&rop->rop_timeout, ROUTE_DESYNC_RESEND_TIMEOUT); } void route_input(struct mbuf *m0, struct socket *so0, sa_family_t sa_family) { struct socket *so; struct rtpcb *rop; struct rt_msghdr *rtm; struct mbuf *m = m0; struct srp_ref sr; /* ensure that we can access the rtm_type via mtod() */ if (m->m_len < offsetof(struct rt_msghdr, rtm_type) + 1) { m_freem(m); return; } SRPL_FOREACH(rop, &sr, &rtptable.rtp_list, rop_list) { /* * If route socket is bound to an address family only send * messages that match the address family. Address family * agnostic messages are always sent. */ if (sa_family != AF_UNSPEC && rop->rop_proto != AF_UNSPEC && rop->rop_proto != sa_family) continue; so = rop->rop_socket; solock(so); /* * Check to see if we don't want our own messages and * if we can receive anything. */ if ((so0 == so && !(so0->so_options & SO_USELOOPBACK)) || !(so->so_state & SS_ISCONNECTED) || (so->so_rcv.sb_state & SS_CANTRCVMORE)) goto next; /* filter messages that the process does not want */ rtm = mtod(m, struct rt_msghdr *); /* but RTM_DESYNC can't be filtered */ if (rtm->rtm_type != RTM_DESYNC) { if (rop->rop_msgfilter != 0 && !(rop->rop_msgfilter & (1U << rtm->rtm_type))) goto next; if (ISSET(rop->rop_flagfilter, rtm->rtm_flags)) goto next; } switch (rtm->rtm_type) { case RTM_IFANNOUNCE: case RTM_DESYNC: /* no tableid */ break; case RTM_RESOLVE: case RTM_NEWADDR: case RTM_DELADDR: case RTM_IFINFO: case RTM_80211INFO: case RTM_BFD: /* check against rdomain id */ if (rop->rop_rtableid != RTABLE_ANY && rtable_l2(rop->rop_rtableid) != rtm->rtm_tableid) goto next; break; default: if (rop->rop_priority != 0 && rop->rop_priority < rtm->rtm_priority) goto next; /* check against rtable id */ if (rop->rop_rtableid != RTABLE_ANY && rop->rop_rtableid != rtm->rtm_tableid) goto next; break; } /* * Check to see if the flush flag is set. If so, don't queue * any more messages until the flag is cleared. */ if ((rop->rop_flags & ROUTECB_FLAG_FLUSH) != 0) goto next; rtm_sendup(so, m); next: sounlock(so); } SRPL_LEAVE(&sr); m_freem(m); } int rtm_sendup(struct socket *so, struct mbuf *m0) { struct rtpcb *rop = sotortpcb(so); struct mbuf *m; soassertlocked(so); m = m_copym(m0, 0, M_COPYALL, M_NOWAIT); if (m == NULL) return (ENOMEM); if (sbspace(so, &so->so_rcv) < (2 * MSIZE) || sbappendaddr(so, &so->so_rcv, &route_src, m, NULL) == 0) { /* Flag socket as desync'ed and flush required */ rop->rop_flags |= ROUTECB_FLAG_DESYNC | ROUTECB_FLAG_FLUSH; rtm_senddesync(so); m_freem(m); return (ENOBUFS); } sorwakeup(so); return (0); } struct rt_msghdr * rtm_report(struct rtentry *rt, u_char type, int seq, int tableid) { struct rt_msghdr *rtm; struct rt_addrinfo info; struct sockaddr_rtlabel sa_rl; struct sockaddr_in6 sa_mask; #ifdef BFD struct sockaddr_bfd sa_bfd; #endif struct ifnet *ifp = NULL; int len; bzero(&info, sizeof(info)); info.rti_info[RTAX_DST] = rt_key(rt); info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; info.rti_info[RTAX_NETMASK] = rt_plen2mask(rt, &sa_mask); info.rti_info[RTAX_LABEL] = rtlabel_id2sa(rt->rt_labelid, &sa_rl); #ifdef BFD if (rt->rt_flags & RTF_BFD) { KERNEL_LOCK(); info.rti_info[RTAX_BFD] = bfd2sa(rt, &sa_bfd); KERNEL_UNLOCK(); } #endif #ifdef MPLS if (rt->rt_flags & RTF_MPLS) { struct sockaddr_mpls sa_mpls; bzero(&sa_mpls, sizeof(sa_mpls)); sa_mpls.smpls_family = AF_MPLS; sa_mpls.smpls_len = sizeof(sa_mpls); sa_mpls.smpls_label = ((struct rt_mpls *) rt->rt_llinfo)->mpls_label; info.rti_info[RTAX_SRC] = (struct sockaddr *)&sa_mpls; info.rti_mpls = ((struct rt_mpls *) rt->rt_llinfo)->mpls_operation; } #endif ifp = if_get(rt->rt_ifidx); if (ifp != NULL) { info.rti_info[RTAX_IFP] = sdltosa(ifp->if_sadl); info.rti_info[RTAX_IFA] = rtable_getsource(tableid, info.rti_info[RTAX_DST]->sa_family); if (info.rti_info[RTAX_IFA] == NULL) info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; if (ifp->if_flags & IFF_POINTOPOINT) info.rti_info[RTAX_BRD] = rt->rt_ifa->ifa_dstaddr; } if_put(ifp); /* RTAX_GENMASK, RTAX_AUTHOR, RTAX_SRCMASK ignored */ /* build new route message */ len = rtm_msg2(type, RTM_VERSION, &info, NULL, NULL); rtm = malloc(len, M_RTABLE, M_WAITOK | M_ZERO); rtm_msg2(type, RTM_VERSION, &info, (caddr_t)rtm, NULL); rtm->rtm_type = type; rtm->rtm_index = rt->rt_ifidx; rtm->rtm_tableid = tableid; rtm->rtm_priority = rt->rt_priority & RTP_MASK; rtm->rtm_flags = rt->rt_flags; rtm->rtm_pid = curproc->p_p->ps_pid; rtm->rtm_seq = seq; rtm_getmetrics(rt, &rtm->rtm_rmx); rtm->rtm_addrs = info.rti_addrs; #ifdef MPLS rtm->rtm_mpls = info.rti_mpls; #endif return rtm; } int route_output(struct mbuf *m, struct socket *so) { struct rt_msghdr *rtm = NULL; struct rtentry *rt = NULL; struct rt_addrinfo info; struct ifnet *ifp; int len, seq, useloopback, error = 0; u_int tableid; u_int8_t prio; u_char vers, type; if (m == NULL || ((m->m_len < sizeof(int32_t)) && (m = m_pullup(m, sizeof(int32_t))) == NULL)) return (ENOBUFS); if ((m->m_flags & M_PKTHDR) == 0) panic("route_output"); useloopback = so->so_options & SO_USELOOPBACK; /* * The socket can't be closed concurrently because the file * descriptor reference is still held. */ sounlock(so); len = m->m_pkthdr.len; if (len < offsetof(struct rt_msghdr, rtm_hdrlen) + sizeof(rtm->rtm_hdrlen) || len != mtod(m, struct rt_msghdr *)->rtm_msglen) { error = EINVAL; goto fail; } vers = mtod(m, struct rt_msghdr *)->rtm_version; switch (vers) { case RTM_VERSION: if (len < sizeof(struct rt_msghdr)) { error = EINVAL; goto fail; } if (len > RTM_MAXSIZE) { error = EMSGSIZE; goto fail; } rtm = malloc(len, M_RTABLE, M_WAITOK); m_copydata(m, 0, len, rtm); break; default: error = EPROTONOSUPPORT; goto fail; } /* Verify that the caller is sending an appropriate message early */ switch (rtm->rtm_type) { case RTM_ADD: case RTM_DELETE: case RTM_GET: case RTM_CHANGE: case RTM_PROPOSAL: case RTM_SOURCE: break; default: error = EOPNOTSUPP; goto fail; } /* * Verify that the header length is valid. * All messages from userland start with a struct rt_msghdr. */ if (rtm->rtm_hdrlen == 0) /* old client */ rtm->rtm_hdrlen = sizeof(struct rt_msghdr); if (rtm->rtm_hdrlen < sizeof(struct rt_msghdr) || len < rtm->rtm_hdrlen) { error = EINVAL; goto fail; } rtm->rtm_pid = curproc->p_p->ps_pid; /* * Verify that the caller has the appropriate privilege; RTM_GET * is the only operation the non-superuser is allowed. */ if (rtm->rtm_type != RTM_GET && suser(curproc) != 0) { error = EACCES; goto fail; } tableid = rtm->rtm_tableid; if (!rtable_exists(tableid)) { if (rtm->rtm_type == RTM_ADD) { if ((error = rtable_add(tableid)) != 0) goto fail; } else { error = EINVAL; goto fail; } } /* Do not let userland play with kernel-only flags. */ if ((rtm->rtm_flags & (RTF_LOCAL|RTF_BROADCAST)) != 0) { error = EINVAL; goto fail; } /* make sure that kernel-only bits are not set */ rtm->rtm_priority &= RTP_MASK; rtm->rtm_flags &= ~(RTF_DONE|RTF_CLONED|RTF_CACHED); rtm->rtm_fmask &= RTF_FMASK; if (rtm->rtm_priority != 0) { if (rtm->rtm_priority > RTP_MAX || rtm->rtm_priority == RTP_LOCAL) { error = EINVAL; goto fail; } prio = rtm->rtm_priority; } else if (rtm->rtm_type != RTM_ADD) prio = RTP_ANY; else if (rtm->rtm_flags & RTF_STATIC) prio = 0; else prio = RTP_DEFAULT; bzero(&info, sizeof(info)); info.rti_addrs = rtm->rtm_addrs; if ((error = rtm_xaddrs(rtm->rtm_hdrlen + (caddr_t)rtm, len + (caddr_t)rtm, &info)) != 0) goto fail; info.rti_flags = rtm->rtm_flags; if (rtm->rtm_type != RTM_SOURCE && rtm->rtm_type != RTM_PROPOSAL && (info.rti_info[RTAX_DST] == NULL || info.rti_info[RTAX_DST]->sa_family >= AF_MAX || (info.rti_info[RTAX_GATEWAY] != NULL && info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX) || info.rti_info[RTAX_GENMASK] != NULL)) { error = EINVAL; goto fail; } #ifdef MPLS info.rti_mpls = rtm->rtm_mpls; #endif if (info.rti_info[RTAX_GATEWAY] != NULL && info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK && (info.rti_flags & RTF_CLONING) == 0) { info.rti_flags |= RTF_LLINFO; } /* * Validate RTM_PROPOSAL and pass it along or error out. */ if (rtm->rtm_type == RTM_PROPOSAL) { if (rtm_validate_proposal(&info) == -1) { error = EINVAL; goto fail; } /* * If this is a solicitation proposal forward request to * all interfaces. Most handlers will ignore it but at least * umb(4) will send a response to this event. */ if (rtm->rtm_priority == RTP_PROPOSAL_SOLICIT) { NET_LOCK(); TAILQ_FOREACH(ifp, &ifnetlist, if_list) { ifp->if_rtrequest(ifp, RTM_PROPOSAL, NULL); } NET_UNLOCK(); } } else if (rtm->rtm_type == RTM_SOURCE) { if (info.rti_info[RTAX_IFA] == NULL) { error = EINVAL; goto fail; } NET_LOCK(); error = rt_setsource(tableid, info.rti_info[RTAX_IFA]); NET_UNLOCK(); if (error) goto fail; } else { error = rtm_output(rtm, &rt, &info, prio, tableid); if (!error) { type = rtm->rtm_type; seq = rtm->rtm_seq; free(rtm, M_RTABLE, len); NET_LOCK_SHARED(); rtm = rtm_report(rt, type, seq, tableid); NET_UNLOCK_SHARED(); len = rtm->rtm_msglen; } } rtfree(rt); if (error) { rtm->rtm_errno = error; } else { rtm->rtm_flags |= RTF_DONE; } /* * Check to see if we don't want our own messages. */ if (!useloopback) { if (rtptable.rtp_count == 0) { /* no other listener and no loopback of messages */ goto fail; } } if (m_copyback(m, 0, len, rtm, M_NOWAIT)) { m_freem(m); m = NULL; } else if (m->m_pkthdr.len > len) m_adj(m, len - m->m_pkthdr.len); free(rtm, M_RTABLE, len); if (m) route_input(m, so, info.rti_info[RTAX_DST] ? info.rti_info[RTAX_DST]->sa_family : AF_UNSPEC); solock(so); return (error); fail: free(rtm, M_RTABLE, len); m_freem(m); solock(so); return (error); } int rtm_output(struct rt_msghdr *rtm, struct rtentry **prt, struct rt_addrinfo *info, uint8_t prio, unsigned int tableid) { struct rtentry *rt = *prt; struct ifnet *ifp = NULL; int plen, newgate = 0, error = 0; switch (rtm->rtm_type) { case RTM_ADD: if (info->rti_info[RTAX_GATEWAY] == NULL) { error = EINVAL; break; } rt = rtable_match(tableid, info->rti_info[RTAX_DST], NULL); if ((error = route_arp_conflict(rt, info))) { rtfree(rt); rt = NULL; break; } /* * We cannot go through a delete/create/insert cycle for * cached route because this can lead to races in the * receive path. Instead we update the L2 cache. */ if ((rt != NULL) && ISSET(rt->rt_flags, RTF_CACHED)) { ifp = if_get(rt->rt_ifidx); if (ifp == NULL) { rtfree(rt); rt = NULL; error = ESRCH; break; } goto change; } rtfree(rt); rt = NULL; NET_LOCK(); if ((error = rtm_getifa(info, tableid)) != 0) { NET_UNLOCK(); break; } error = rtrequest(RTM_ADD, info, prio, &rt, tableid); NET_UNLOCK(); if (error == 0) rtm_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, &rt->rt_rmx); break; case RTM_DELETE: rt = rtable_lookup(tableid, info->rti_info[RTAX_DST], info->rti_info[RTAX_NETMASK], info->rti_info[RTAX_GATEWAY], prio); if (rt == NULL) { error = ESRCH; break; } /* * If we got multipath routes, we require users to specify * a matching gateway. */ if (ISSET(rt->rt_flags, RTF_MPATH) && info->rti_info[RTAX_GATEWAY] == NULL) { error = ESRCH; break; } ifp = if_get(rt->rt_ifidx); if (ifp == NULL) { rtfree(rt); rt = NULL; error = ESRCH; break; } /* * Invalidate the cache of automagically created and * referenced L2 entries to make sure that ``rt_gwroute'' * pointer stays valid for other CPUs. */ if ((ISSET(rt->rt_flags, RTF_CACHED))) { NET_LOCK(); ifp->if_rtrequest(ifp, RTM_INVALIDATE, rt); /* Reset the MTU of the gateway route. */ rtable_walk(tableid, rt_key(rt)->sa_family, NULL, route_cleargateway, rt); NET_UNLOCK(); break; } /* * Make sure that local routes are only modified by the * kernel. */ if (ISSET(rt->rt_flags, RTF_LOCAL|RTF_BROADCAST)) { error = EINVAL; break; } rtfree(rt); rt = NULL; NET_LOCK(); error = rtrequest_delete(info, prio, ifp, &rt, tableid); NET_UNLOCK(); break; case RTM_CHANGE: rt = rtable_lookup(tableid, info->rti_info[RTAX_DST], info->rti_info[RTAX_NETMASK], info->rti_info[RTAX_GATEWAY], prio); /* * If we got multipath routes, we require users to specify * a matching gateway. */ if ((rt != NULL) && ISSET(rt->rt_flags, RTF_MPATH) && (info->rti_info[RTAX_GATEWAY] == NULL)) { rtfree(rt); rt = NULL; } /* * If RTAX_GATEWAY is the argument we're trying to * change, try to find a compatible route. */ if ((rt == NULL) && (info->rti_info[RTAX_GATEWAY] != NULL)) { rt = rtable_lookup(tableid, info->rti_info[RTAX_DST], info->rti_info[RTAX_NETMASK], NULL, prio); /* Ensure we don't pick a multipath one. */ if ((rt != NULL) && ISSET(rt->rt_flags, RTF_MPATH)) { rtfree(rt); rt = NULL; } } if (rt == NULL) { error = ESRCH; break; } /* * Make sure that local routes are only modified by the * kernel. */ if (ISSET(rt->rt_flags, RTF_LOCAL|RTF_BROADCAST)) { error = EINVAL; break; } ifp = if_get(rt->rt_ifidx); if (ifp == NULL) { rtfree(rt); rt = NULL; error = ESRCH; break; } /* * RTM_CHANGE needs a perfect match. */ plen = rtable_satoplen(info->rti_info[RTAX_DST]->sa_family, info->rti_info[RTAX_NETMASK]); if (rt_plen(rt) != plen) { error = ESRCH; break; } if (info->rti_info[RTAX_GATEWAY] != NULL) if (rt->rt_gateway == NULL || bcmp(rt->rt_gateway, info->rti_info[RTAX_GATEWAY], info->rti_info[RTAX_GATEWAY]->sa_len)) { newgate = 1; } /* * Check reachable gateway before changing the route. * New gateway could require new ifaddr, ifp; * flags may also be different; ifp may be specified * by ll sockaddr when protocol address is ambiguous. */ if (newgate || info->rti_info[RTAX_IFP] != NULL || info->rti_info[RTAX_IFA] != NULL) { struct ifaddr *ifa = NULL; NET_LOCK(); if ((error = rtm_getifa(info, tableid)) != 0) { NET_UNLOCK(); break; } ifa = info->rti_ifa; if (rt->rt_ifa != ifa) { ifp->if_rtrequest(ifp, RTM_DELETE, rt); ifafree(rt->rt_ifa); rt->rt_ifa = ifaref(ifa); rt->rt_ifidx = ifa->ifa_ifp->if_index; /* recheck link state after ifp change */ rt_if_linkstate_change(rt, ifa->ifa_ifp, tableid); } NET_UNLOCK(); } change: if (info->rti_info[RTAX_GATEWAY] != NULL) { /* When updating the gateway, make sure it is valid. */ if (!newgate && rt->rt_gateway->sa_family != info->rti_info[RTAX_GATEWAY]->sa_family) { error = EINVAL; break; } NET_LOCK(); error = rt_setgate(rt, info->rti_info[RTAX_GATEWAY], tableid); NET_UNLOCK(); if (error) break; } #ifdef MPLS if (rtm->rtm_flags & RTF_MPLS) { NET_LOCK(); error = rt_mpls_set(rt, info->rti_info[RTAX_SRC], info->rti_mpls); NET_UNLOCK(); if (error) break; } else if (newgate || (rtm->rtm_fmask & RTF_MPLS)) { NET_LOCK(); /* if gateway changed remove MPLS information */ rt_mpls_clear(rt); NET_UNLOCK(); } #endif #ifdef BFD if (ISSET(rtm->rtm_flags, RTF_BFD)) { KERNEL_LOCK(); error = bfdset(rt); KERNEL_UNLOCK(); if (error) break; } else if (!ISSET(rtm->rtm_flags, RTF_BFD) && ISSET(rtm->rtm_fmask, RTF_BFD)) { KERNEL_LOCK(); bfdclear(rt); KERNEL_UNLOCK(); } #endif NET_LOCK(); /* Hack to allow some flags to be toggled */ if (rtm->rtm_fmask) { /* MPLS flag it is set by rt_mpls_set() */ rtm->rtm_fmask &= ~RTF_MPLS; rtm->rtm_flags &= ~RTF_MPLS; rt->rt_flags = (rt->rt_flags & ~rtm->rtm_fmask) | (rtm->rtm_flags & rtm->rtm_fmask); } rtm_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, &rt->rt_rmx); ifp->if_rtrequest(ifp, RTM_ADD, rt); if (info->rti_info[RTAX_LABEL] != NULL) { const char *rtlabel = ((const struct sockaddr_rtlabel *) info->rti_info[RTAX_LABEL])->sr_label; rtlabel_unref(rt->rt_labelid); rt->rt_labelid = rtlabel_name2id(rtlabel); } if_group_routechange(info->rti_info[RTAX_DST], info->rti_info[RTAX_NETMASK]); rt->rt_locks &= ~(rtm->rtm_inits); rt->rt_locks |= (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); NET_UNLOCK(); break; case RTM_GET: rt = rtable_lookup(tableid, info->rti_info[RTAX_DST], info->rti_info[RTAX_NETMASK], info->rti_info[RTAX_GATEWAY], prio); if (rt == NULL) error = ESRCH; break; } if_put(ifp); *prt = rt; return (error); } struct ifaddr * ifa_ifwithroute(int flags, const struct sockaddr *dst, const struct sockaddr *gateway, unsigned int rtableid) { struct ifaddr *ifa; if ((flags & RTF_GATEWAY) == 0) { /* * If we are adding a route to an interface, * and the interface is a pt to pt link * we should search for the destination * as our clue to the interface. Otherwise * we can use the local address. */ ifa = NULL; if (flags & RTF_HOST) ifa = ifa_ifwithdstaddr(dst, rtableid); if (ifa == NULL) ifa = ifa_ifwithaddr(gateway, rtableid); } else { /* * If we are adding a route to a remote net * or host, the gateway may still be on the * other end of a pt to pt link. */ ifa = ifa_ifwithdstaddr(gateway, rtableid); } if (ifa == NULL) { if (gateway->sa_family == AF_LINK) { const struct sockaddr_dl *sdl; struct ifnet *ifp; sdl = satosdl_const(gateway); ifp = if_get(sdl->sdl_index); if (ifp != NULL) ifa = ifaof_ifpforaddr(dst, ifp); if_put(ifp); } else { struct rtentry *rt; rt = rtalloc(gateway, RT_RESOLVE, rtable_l2(rtableid)); if (rt != NULL) ifa = rt->rt_ifa; rtfree(rt); } } if (ifa == NULL) return (NULL); if (ifa->ifa_addr->sa_family != dst->sa_family) { struct ifaddr *oifa = ifa; ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp); if (ifa == NULL) ifa = oifa; } return (ifa); } int rtm_getifa(struct rt_addrinfo *info, unsigned int rtid) { struct ifnet *ifp = NULL; /* * The "returned" `ifa' is guaranteed to be alive only if * the NET_LOCK() is held. */ NET_ASSERT_LOCKED(); /* * ifp may be specified by sockaddr_dl when protocol address * is ambiguous */ if (info->rti_info[RTAX_IFP] != NULL) { const struct sockaddr_dl *sdl; sdl = satosdl_const(info->rti_info[RTAX_IFP]); ifp = if_get(sdl->sdl_index); } #ifdef IPSEC /* * If the destination is a PF_KEY address, we'll look * for the existence of a encap interface number or address * in the options list of the gateway. By default, we'll return * enc0. */ if (info->rti_info[RTAX_DST] && info->rti_info[RTAX_DST]->sa_family == PF_KEY) info->rti_ifa = enc_getifa(rtid, 0); #endif if (info->rti_ifa == NULL && info->rti_info[RTAX_IFA] != NULL) info->rti_ifa = ifa_ifwithaddr(info->rti_info[RTAX_IFA], rtid); if (info->rti_ifa == NULL) { const struct sockaddr *sa; if ((sa = info->rti_info[RTAX_IFA]) == NULL) if ((sa = info->rti_info[RTAX_GATEWAY]) == NULL) sa = info->rti_info[RTAX_DST]; if (sa != NULL && ifp != NULL) info->rti_ifa = ifaof_ifpforaddr(sa, ifp); else if (info->rti_info[RTAX_DST] != NULL && info->rti_info[RTAX_GATEWAY] != NULL) info->rti_ifa = ifa_ifwithroute(info->rti_flags, info->rti_info[RTAX_DST], info->rti_info[RTAX_GATEWAY], rtid); else if (sa != NULL) info->rti_ifa = ifa_ifwithroute(info->rti_flags, sa, sa, rtid); } if_put(ifp); if (info->rti_ifa == NULL) return (ENETUNREACH); return (0); } int route_cleargateway(struct rtentry *rt, void *arg, unsigned int rtableid) { struct rtentry *nhrt = arg; if (ISSET(rt->rt_flags, RTF_GATEWAY) && rt->rt_gwroute == nhrt && !ISSET(rt->rt_locks, RTV_MTU)) rt->rt_mtu = 0; return (0); } /* * Check if the user request to insert an ARP entry does not conflict * with existing ones. * * Only two entries are allowed for a given IP address: a private one * (priv) and a public one (pub). */ int route_arp_conflict(struct rtentry *rt, struct rt_addrinfo *info) { int proxy = (info->rti_flags & RTF_ANNOUNCE); if ((info->rti_flags & RTF_LLINFO) == 0 || (info->rti_info[RTAX_DST]->sa_family != AF_INET)) return (0); if (rt == NULL || !ISSET(rt->rt_flags, RTF_LLINFO)) return (0); /* If the entry is cached, it can be updated. */ if (ISSET(rt->rt_flags, RTF_CACHED)) return (0); /* * Same destination, not cached and both "priv" or "pub" conflict. * If a second entry exists, it always conflict. */ if ((ISSET(rt->rt_flags, RTF_ANNOUNCE) == proxy) || ISSET(rt->rt_flags, RTF_MPATH)) return (EEXIST); /* No conflict but an entry exist so we need to force mpath. */ info->rti_flags |= RTF_MPATH; return (0); } void rtm_setmetrics(u_long which, const struct rt_metrics *in, struct rt_kmetrics *out) { int64_t expire; if (which & RTV_MTU) out->rmx_mtu = in->rmx_mtu; if (which & RTV_EXPIRE) { expire = in->rmx_expire; if (expire != 0) { expire -= gettime(); expire += getuptime(); } out->rmx_expire = expire; } } void rtm_getmetrics(const struct rtentry *rt, struct rt_metrics *out) { const struct rt_kmetrics *in = &rt->rt_rmx; int64_t expire; expire = in->rmx_expire; if (expire == 0) expire = rt_timer_get_expire(rt); if (expire != 0) { expire -= getuptime(); expire += gettime(); } bzero(out, sizeof(*out)); out->rmx_locks = in->rmx_locks; out->rmx_mtu = in->rmx_mtu; out->rmx_expire = expire; out->rmx_pksent = in->rmx_pksent; } #define ROUNDUP(a) \ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) int rtm_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo) { int i; /* * Parse address bits, split address storage in chunks, and * set info pointers. Use sa_len for traversing the memory * and check that we stay within in the limit. */ bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info)); for (i = 0; i < sizeof(rtinfo->rti_addrs) * 8; i++) { struct sockaddr *sa; if ((rtinfo->rti_addrs & (1U << i)) == 0) continue; if (i >= RTAX_MAX || cp + sizeof(socklen_t) > cplim) return (EINVAL); sa = (struct sockaddr *)cp; if (cp + sa->sa_len > cplim) return (EINVAL); rtinfo->rti_info[i] = sa; ADVANCE(cp, sa); } /* * Check that the address family is suitable for the route address * type. Check that each address has a size that fits its family * and its length is within the size. Strings within addresses must * be NUL terminated. */ for (i = 0; i < RTAX_MAX; i++) { const struct sockaddr *sa; size_t len, maxlen, size; sa = rtinfo->rti_info[i]; if (sa == NULL) continue; maxlen = size = 0; switch (i) { case RTAX_DST: case RTAX_GATEWAY: case RTAX_SRC: switch (sa->sa_family) { case AF_INET: size = sizeof(struct sockaddr_in); break; case AF_LINK: size = sizeof(struct sockaddr_dl); break; #ifdef INET6 case AF_INET6: size = sizeof(struct sockaddr_in6); break; #endif #ifdef MPLS case AF_MPLS: size = sizeof(struct sockaddr_mpls); break; #endif } break; case RTAX_IFP: if (sa->sa_family != AF_LINK) return (EAFNOSUPPORT); /* * XXX Should be sizeof(struct sockaddr_dl), but * route(8) has a bug and provides less memory. * arp(8) has another bug and uses sizeof pointer. */ size = 4; break; case RTAX_IFA: switch (sa->sa_family) { case AF_INET: size = sizeof(struct sockaddr_in); break; #ifdef INET6 case AF_INET6: size = sizeof(struct sockaddr_in6); break; #endif default: return (EAFNOSUPPORT); } break; case RTAX_LABEL: if (sa->sa_family != AF_UNSPEC) return (EAFNOSUPPORT); maxlen = RTLABEL_LEN; size = sizeof(struct sockaddr_rtlabel); break; #ifdef BFD case RTAX_BFD: if (sa->sa_family != AF_UNSPEC) return (EAFNOSUPPORT); size = sizeof(struct sockaddr_bfd); break; #endif case RTAX_DNS: /* more validation in rtm_validate_proposal */ if (sa->sa_len > sizeof(struct sockaddr_rtdns)) return (EINVAL); if (sa->sa_len < offsetof(struct sockaddr_rtdns, sr_dns)) return (EINVAL); switch (sa->sa_family) { case AF_INET: #ifdef INET6 case AF_INET6: #endif break; default: return (EAFNOSUPPORT); } break; case RTAX_STATIC: switch (sa->sa_family) { case AF_INET: #ifdef INET6 case AF_INET6: #endif break; default: return (EAFNOSUPPORT); } maxlen = RTSTATIC_LEN; size = sizeof(struct sockaddr_rtstatic); break; case RTAX_SEARCH: if (sa->sa_family != AF_UNSPEC) return (EAFNOSUPPORT); maxlen = RTSEARCH_LEN; size = sizeof(struct sockaddr_rtsearch); break; } if (size) { /* memory for the full struct must be provided */ if (sa->sa_len < size) return (EINVAL); } if (maxlen) { /* this should not happen */ if (2 + maxlen > size) return (EINVAL); /* strings must be NUL terminated within the struct */ len = strnlen(sa->sa_data, maxlen); if (len >= maxlen || 2 + len >= sa->sa_len) return (EINVAL); break; } } return (0); } struct mbuf * rtm_msg1(int type, struct rt_addrinfo *rtinfo) { struct rt_msghdr *rtm; struct mbuf *m; int i; const struct sockaddr *sa; int len, dlen, hlen; switch (type) { case RTM_DELADDR: case RTM_NEWADDR: hlen = sizeof(struct ifa_msghdr); break; case RTM_IFINFO: hlen = sizeof(struct if_msghdr); break; case RTM_IFANNOUNCE: hlen = sizeof(struct if_announcemsghdr); break; #ifdef BFD case RTM_BFD: hlen = sizeof(struct bfd_msghdr); break; #endif case RTM_80211INFO: hlen = sizeof(struct if_ieee80211_msghdr); break; default: hlen = sizeof(struct rt_msghdr); break; } len = hlen; for (i = 0; i < RTAX_MAX; i++) { if (rtinfo == NULL || (sa = rtinfo->rti_info[i]) == NULL) continue; len += ROUNDUP(sa->sa_len); } if (len > MCLBYTES) panic("rtm_msg1"); m = m_gethdr(M_DONTWAIT, MT_DATA); if (m && len > MHLEN) { MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { m_free(m); m = NULL; } } if (m == NULL) return (m); m->m_pkthdr.len = m->m_len = len; m->m_pkthdr.ph_ifidx = 0; rtm = mtod(m, struct rt_msghdr *); bzero(rtm, len); len = hlen; for (i = 0; i < RTAX_MAX; i++) { if (rtinfo == NULL || (sa = rtinfo->rti_info[i]) == NULL) continue; rtinfo->rti_addrs |= (1U << i); dlen = ROUNDUP(sa->sa_len); if (m_copyback(m, len, sa->sa_len, sa, M_NOWAIT)) { m_freem(m); return (NULL); } len += dlen; } rtm->rtm_msglen = len; rtm->rtm_hdrlen = hlen; rtm->rtm_version = RTM_VERSION; rtm->rtm_type = type; return (m); } int rtm_msg2(int type, int vers, struct rt_addrinfo *rtinfo, caddr_t cp, struct walkarg *w) { int i; int len, dlen, hlen, second_time = 0; caddr_t cp0; rtinfo->rti_addrs = 0; again: switch (type) { case RTM_DELADDR: case RTM_NEWADDR: len = sizeof(struct ifa_msghdr); break; case RTM_IFINFO: len = sizeof(struct if_msghdr); break; default: len = sizeof(struct rt_msghdr); break; } hlen = len; if ((cp0 = cp) != NULL) cp += len; for (i = 0; i < RTAX_MAX; i++) { const struct sockaddr *sa; if ((sa = rtinfo->rti_info[i]) == NULL) continue; rtinfo->rti_addrs |= (1U << i); dlen = ROUNDUP(sa->sa_len); if (cp) { bcopy(sa, cp, sa->sa_len); bzero(cp + sa->sa_len, dlen - sa->sa_len); cp += dlen; } len += dlen; } /* align message length to the next natural boundary */ len = ALIGN(len); if (cp == 0 && w != NULL && !second_time) { w->w_needed += len; if (w->w_needed <= w->w_given && w->w_where) { if (w->w_tmemsize < len) { free(w->w_tmem, M_RTABLE, w->w_tmemsize); w->w_tmem = malloc(len, M_RTABLE, M_NOWAIT | M_ZERO); if (w->w_tmem) w->w_tmemsize = len; } if (w->w_tmem) { cp = w->w_tmem; second_time = 1; goto again; } else w->w_where = 0; } } if (cp && w) /* clear the message header */ bzero(cp0, hlen); if (cp) { struct rt_msghdr *rtm = (struct rt_msghdr *)cp0; rtm->rtm_version = RTM_VERSION; rtm->rtm_type = type; rtm->rtm_msglen = len; rtm->rtm_hdrlen = hlen; } return (len); } void rtm_send(struct rtentry *rt, int cmd, int error, unsigned int rtableid) { struct rt_addrinfo info; struct ifnet *ifp; struct sockaddr_rtlabel sa_rl; struct sockaddr_in6 sa_mask; memset(&info, 0, sizeof(info)); info.rti_info[RTAX_DST] = rt_key(rt); info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; if (!ISSET(rt->rt_flags, RTF_HOST)) info.rti_info[RTAX_NETMASK] = rt_plen2mask(rt, &sa_mask); info.rti_info[RTAX_LABEL] = rtlabel_id2sa(rt->rt_labelid, &sa_rl); ifp = if_get(rt->rt_ifidx); if (ifp != NULL) { info.rti_info[RTAX_IFP] = sdltosa(ifp->if_sadl); info.rti_info[RTAX_IFA] = rtable_getsource(rtableid, info.rti_info[RTAX_DST]->sa_family); if (info.rti_info[RTAX_IFA] == NULL) info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; } rtm_miss(cmd, &info, rt->rt_flags, rt->rt_priority, rt->rt_ifidx, error, rtableid); if_put(ifp); } /* * This routine is called to generate a message from the routing * socket indicating that a redirect has occurred, a routing lookup * has failed, or that a protocol has detected timeouts to a particular * destination. */ void rtm_miss(int type, struct rt_addrinfo *rtinfo, int flags, uint8_t prio, u_int ifidx, int error, u_int tableid) { struct rt_msghdr *rtm; struct mbuf *m; const struct sockaddr *sa = rtinfo->rti_info[RTAX_DST]; if (rtptable.rtp_count == 0) return; m = rtm_msg1(type, rtinfo); if (m == NULL) return; rtm = mtod(m, struct rt_msghdr *); rtm->rtm_flags = RTF_DONE | flags; rtm->rtm_priority = prio; rtm->rtm_errno = error; rtm->rtm_tableid = tableid; rtm->rtm_addrs = rtinfo->rti_addrs; rtm->rtm_index = ifidx; route_input(m, NULL, sa ? sa->sa_family : AF_UNSPEC); } /* * This routine is called to generate a message from the routing * socket indicating that the status of a network interface has changed. */ void rtm_ifchg(struct ifnet *ifp) { struct rt_addrinfo info; struct if_msghdr *ifm; struct mbuf *m; if (rtptable.rtp_count == 0) return; memset(&info, 0, sizeof(info)); info.rti_info[RTAX_IFP] = sdltosa(ifp->if_sadl); m = rtm_msg1(RTM_IFINFO, &info); if (m == NULL) return; ifm = mtod(m, struct if_msghdr *); ifm->ifm_index = ifp->if_index; ifm->ifm_tableid = ifp->if_rdomain; ifm->ifm_flags = ifp->if_flags; ifm->ifm_xflags = ifp->if_xflags; if_getdata(ifp, &ifm->ifm_data); ifm->ifm_addrs = info.rti_addrs; route_input(m, NULL, AF_UNSPEC); } /* * This is called to generate messages from the routing socket * indicating a network interface has had addresses associated with it. * if we ever reverse the logic and replace messages TO the routing * socket indicate a request to configure interfaces, then it will * be unnecessary as the routing socket will automatically generate * copies of it. */ void rtm_addr(int cmd, struct ifaddr *ifa) { struct ifnet *ifp = ifa->ifa_ifp; struct mbuf *m; struct rt_addrinfo info; struct ifa_msghdr *ifam; if (rtptable.rtp_count == 0) return; memset(&info, 0, sizeof(info)); info.rti_info[RTAX_IFA] = ifa->ifa_addr; info.rti_info[RTAX_IFP] = sdltosa(ifp->if_sadl); info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr; if ((m = rtm_msg1(cmd, &info)) == NULL) return; ifam = mtod(m, struct ifa_msghdr *); ifam->ifam_index = ifp->if_index; ifam->ifam_metric = ifa->ifa_metric; ifam->ifam_flags = ifa->ifa_flags; ifam->ifam_addrs = info.rti_addrs; ifam->ifam_tableid = ifp->if_rdomain; route_input(m, NULL, ifa->ifa_addr ? ifa->ifa_addr->sa_family : AF_UNSPEC); } /* * This is called to generate routing socket messages indicating * network interface arrival and departure. */ void rtm_ifannounce(struct ifnet *ifp, int what) { struct if_announcemsghdr *ifan; struct mbuf *m; if (rtptable.rtp_count == 0) return; m = rtm_msg1(RTM_IFANNOUNCE, NULL); if (m == NULL) return; ifan = mtod(m, struct if_announcemsghdr *); ifan->ifan_index = ifp->if_index; strlcpy(ifan->ifan_name, ifp->if_xname, sizeof(ifan->ifan_name)); ifan->ifan_what = what; route_input(m, NULL, AF_UNSPEC); } #ifdef BFD /* * This is used to generate routing socket messages indicating * the state of a BFD session. */ void rtm_bfd(struct bfd_config *bfd) { struct bfd_msghdr *bfdm; struct sockaddr_bfd sa_bfd; struct mbuf *m; struct rt_addrinfo info; if (rtptable.rtp_count == 0) return; memset(&info, 0, sizeof(info)); info.rti_info[RTAX_DST] = rt_key(bfd->bc_rt); info.rti_info[RTAX_IFA] = bfd->bc_rt->rt_ifa->ifa_addr; m = rtm_msg1(RTM_BFD, &info); if (m == NULL) return; bfdm = mtod(m, struct bfd_msghdr *); bfdm->bm_addrs = info.rti_addrs; KERNEL_ASSERT_LOCKED(); bfd2sa(bfd->bc_rt, &sa_bfd); memcpy(&bfdm->bm_sa, &sa_bfd, sizeof(sa_bfd)); route_input(m, NULL, info.rti_info[RTAX_DST]->sa_family); } #endif /* BFD */ /* * This is used to generate routing socket messages indicating * the state of an ieee80211 interface. */ void rtm_80211info(struct ifnet *ifp, struct if_ieee80211_data *ifie) { struct if_ieee80211_msghdr *ifim; struct mbuf *m; if (rtptable.rtp_count == 0) return; m = rtm_msg1(RTM_80211INFO, NULL); if (m == NULL) return; ifim = mtod(m, struct if_ieee80211_msghdr *); ifim->ifim_index = ifp->if_index; ifim->ifim_tableid = ifp->if_rdomain; memcpy(&ifim->ifim_ifie, ifie, sizeof(ifim->ifim_ifie)); route_input(m, NULL, AF_UNSPEC); } /* * This is used to generate routing socket messages indicating * the address selection proposal from an interface. */ void rtm_proposal(struct ifnet *ifp, struct rt_addrinfo *rtinfo, int flags, uint8_t prio) { struct rt_msghdr *rtm; struct mbuf *m; m = rtm_msg1(RTM_PROPOSAL, rtinfo); if (m == NULL) return; rtm = mtod(m, struct rt_msghdr *); rtm->rtm_flags = RTF_DONE | flags; rtm->rtm_priority = prio; rtm->rtm_tableid = ifp->if_rdomain; rtm->rtm_index = ifp->if_index; rtm->rtm_addrs = rtinfo->rti_addrs; route_input(m, NULL, rtinfo->rti_info[RTAX_DNS]->sa_family); } /* * This is used in dumping the kernel table via sysctl(). */ int sysctl_dumpentry(struct rtentry *rt, void *v, unsigned int id) { struct walkarg *w = v; int error = 0, size; struct rt_addrinfo info; struct ifnet *ifp; #ifdef BFD struct sockaddr_bfd sa_bfd; #endif struct sockaddr_rtlabel sa_rl; struct sockaddr_in6 sa_mask; if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) return 0; if (w->w_op == NET_RT_DUMP && w->w_arg) { u_int8_t prio = w->w_arg & RTP_MASK; if (w->w_arg < 0) { prio = (-w->w_arg) & RTP_MASK; /* Show all routes that are not this priority */ if (prio == (rt->rt_priority & RTP_MASK)) return 0; } else { if (prio != (rt->rt_priority & RTP_MASK) && prio != RTP_ANY) return 0; } } bzero(&info, sizeof(info)); info.rti_info[RTAX_DST] = rt_key(rt); info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; info.rti_info[RTAX_NETMASK] = rt_plen2mask(rt, &sa_mask); ifp = if_get(rt->rt_ifidx); if (ifp != NULL) { info.rti_info[RTAX_IFP] = sdltosa(ifp->if_sadl); info.rti_info[RTAX_IFA] = rtable_getsource(id, info.rti_info[RTAX_DST]->sa_family); if (info.rti_info[RTAX_IFA] == NULL) info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; if (ifp->if_flags & IFF_POINTOPOINT) info.rti_info[RTAX_BRD] = rt->rt_ifa->ifa_dstaddr; } if_put(ifp); info.rti_info[RTAX_LABEL] = rtlabel_id2sa(rt->rt_labelid, &sa_rl); #ifdef BFD if (rt->rt_flags & RTF_BFD) { KERNEL_ASSERT_LOCKED(); info.rti_info[RTAX_BFD] = bfd2sa(rt, &sa_bfd); } #endif #ifdef MPLS if (rt->rt_flags & RTF_MPLS) { struct sockaddr_mpls sa_mpls; bzero(&sa_mpls, sizeof(sa_mpls)); sa_mpls.smpls_family = AF_MPLS; sa_mpls.smpls_len = sizeof(sa_mpls); sa_mpls.smpls_label = ((struct rt_mpls *) rt->rt_llinfo)->mpls_label; info.rti_info[RTAX_SRC] = (struct sockaddr *)&sa_mpls; info.rti_mpls = ((struct rt_mpls *) rt->rt_llinfo)->mpls_operation; } #endif size = rtm_msg2(RTM_GET, RTM_VERSION, &info, NULL, w); if (w->w_where && w->w_tmem && w->w_needed <= w->w_given) { struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem; rtm->rtm_pid = curproc->p_p->ps_pid; rtm->rtm_flags = RTF_DONE | rt->rt_flags; rtm->rtm_priority = rt->rt_priority & RTP_MASK; rtm_getmetrics(rt, &rtm->rtm_rmx); /* Do not account the routing table's reference. */ rtm->rtm_rmx.rmx_refcnt = refcnt_read(&rt->rt_refcnt) - 1; rtm->rtm_index = rt->rt_ifidx; rtm->rtm_addrs = info.rti_addrs; rtm->rtm_tableid = id; #ifdef MPLS rtm->rtm_mpls = info.rti_mpls; #endif if ((error = copyout(rtm, w->w_where, size)) != 0) w->w_where = NULL; else w->w_where += size; } return (error); } int sysctl_iflist(int af, struct walkarg *w) { struct ifnet *ifp; struct ifaddr *ifa; struct rt_addrinfo info; int len, error = 0; bzero(&info, sizeof(info)); TAILQ_FOREACH(ifp, &ifnetlist, if_list) { if (w->w_arg && w->w_arg != ifp->if_index) continue; /* Copy the link-layer address first */ info.rti_info[RTAX_IFP] = sdltosa(ifp->if_sadl); len = rtm_msg2(RTM_IFINFO, RTM_VERSION, &info, 0, w); if (w->w_where && w->w_tmem && w->w_needed <= w->w_given) { struct if_msghdr *ifm; ifm = (struct if_msghdr *)w->w_tmem; ifm->ifm_index = ifp->if_index; ifm->ifm_tableid = ifp->if_rdomain; ifm->ifm_flags = ifp->if_flags; if_getdata(ifp, &ifm->ifm_data); ifm->ifm_addrs = info.rti_addrs; error = copyout(ifm, w->w_where, len); if (error) return (error); w->w_where += len; } info.rti_info[RTAX_IFP] = NULL; TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { KASSERT(ifa->ifa_addr->sa_family != AF_LINK); if (af && af != ifa->ifa_addr->sa_family) continue; info.rti_info[RTAX_IFA] = ifa->ifa_addr; info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr; len = rtm_msg2(RTM_NEWADDR, RTM_VERSION, &info, 0, w); if (w->w_where && w->w_tmem && w->w_needed <= w->w_given) { struct ifa_msghdr *ifam; ifam = (struct ifa_msghdr *)w->w_tmem; ifam->ifam_index = ifa->ifa_ifp->if_index; ifam->ifam_flags = ifa->ifa_flags; ifam->ifam_metric = ifa->ifa_metric; ifam->ifam_addrs = info.rti_addrs; error = copyout(w->w_tmem, w->w_where, len); if (error) return (error); w->w_where += len; } } info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] = info.rti_info[RTAX_BRD] = NULL; } return (0); } int sysctl_ifnames(struct walkarg *w) { struct if_nameindex_msg ifn; struct ifnet *ifp; int error = 0; /* XXX ignore tableid for now */ TAILQ_FOREACH(ifp, &ifnetlist, if_list) { if (w->w_arg && w->w_arg != ifp->if_index) continue; w->w_needed += sizeof(ifn); if (w->w_where && w->w_needed <= w->w_given) { memset(&ifn, 0, sizeof(ifn)); ifn.if_index = ifp->if_index; strlcpy(ifn.if_name, ifp->if_xname, sizeof(ifn.if_name)); error = copyout(&ifn, w->w_where, sizeof(ifn)); if (error) return (error); w->w_where += sizeof(ifn); } } return (0); } int sysctl_source(int af, u_int tableid, struct walkarg *w) { struct sockaddr *sa; int size, error = 0; sa = rtable_getsource(tableid, af); if (sa) { switch (sa->sa_family) { case AF_INET: size = sizeof(struct sockaddr_in); break; #ifdef INET6 case AF_INET6: size = sizeof(struct sockaddr_in6); break; #endif default: return (0); } w->w_needed += size; if (w->w_where && w->w_needed <= w->w_given) { if ((error = copyout(sa, w->w_where, size))) return (error); w->w_where += size; } } return (0); } int sysctl_rtable(int *name, u_int namelen, void *where, size_t *given, void *new, size_t newlen) { int i, error = EINVAL; u_char af; struct walkarg w; struct rt_tableinfo tableinfo; u_int tableid = 0; if (new) return (EPERM); if (namelen < 3 || namelen > 4) return (EINVAL); af = name[0]; bzero(&w, sizeof(w)); w.w_where = where; w.w_given = *given; w.w_op = name[1]; w.w_arg = name[2]; if (namelen == 4) { tableid = name[3]; if (!rtable_exists(tableid)) return (ENOENT); } else tableid = curproc->p_p->ps_rtableid; switch (w.w_op) { case NET_RT_DUMP: case NET_RT_FLAGS: NET_LOCK_SHARED(); for (i = 1; i <= AF_MAX; i++) { if (af != 0 && af != i) continue; error = rtable_walk(tableid, i, NULL, sysctl_dumpentry, &w); if (error == EAFNOSUPPORT) error = 0; if (error) break; } NET_UNLOCK_SHARED(); break; case NET_RT_IFLIST: NET_LOCK_SHARED(); error = sysctl_iflist(af, &w); NET_UNLOCK_SHARED(); break; case NET_RT_STATS: return (sysctl_rtable_rtstat(where, given, new)); case NET_RT_TABLE: tableid = w.w_arg; if (!rtable_exists(tableid)) return (ENOENT); memset(&tableinfo, 0, sizeof tableinfo); tableinfo.rti_tableid = tableid; tableinfo.rti_domainid = rtable_l2(tableid); error = sysctl_rdstruct(where, given, new, &tableinfo, sizeof(tableinfo)); return (error); case NET_RT_IFNAMES: NET_LOCK_SHARED(); error = sysctl_ifnames(&w); NET_UNLOCK_SHARED(); break; case NET_RT_SOURCE: tableid = w.w_arg; if (!rtable_exists(tableid)) return (ENOENT); NET_LOCK_SHARED(); for (i = 1; i <= AF_MAX; i++) { if (af != 0 && af != i) continue; error = sysctl_source(i, tableid, &w); if (error == EAFNOSUPPORT) error = 0; if (error) break; } NET_UNLOCK_SHARED(); break; } free(w.w_tmem, M_RTABLE, w.w_tmemsize); if (where) { *given = w.w_where - (caddr_t)where; if (w.w_needed > w.w_given) return (ENOMEM); } else if (w.w_needed == 0) { *given = 0; } else { *given = roundup(w.w_needed + MAX(w.w_needed / 10, 1024), PAGE_SIZE); } return (error); } int sysctl_rtable_rtstat(void *oldp, size_t *oldlenp, void *newp) { extern struct cpumem *rtcounters; uint64_t counters[rts_ncounters]; struct rtstat rtstat; uint32_t *words = (uint32_t *)&rtstat; int i; CTASSERT(sizeof(rtstat) == (nitems(counters) * sizeof(uint32_t))); memset(&rtstat, 0, sizeof rtstat); counters_read(rtcounters, counters, nitems(counters), NULL); for (i = 0; i < nitems(counters); i++) words[i] = (uint32_t)counters[i]; return (sysctl_rdstruct(oldp, oldlenp, newp, &rtstat, sizeof(rtstat))); } int rtm_validate_proposal(struct rt_addrinfo *info) { if (info->rti_addrs & ~(RTA_NETMASK | RTA_IFA | RTA_DNS | RTA_STATIC | RTA_SEARCH)) { return -1; } if (ISSET(info->rti_addrs, RTA_NETMASK)) { const struct sockaddr *sa = info->rti_info[RTAX_NETMASK]; if (sa == NULL) return -1; switch (sa->sa_family) { case AF_INET: if (sa->sa_len != sizeof(struct sockaddr_in)) return -1; break; case AF_INET6: if (sa->sa_len != sizeof(struct sockaddr_in6)) return -1; break; default: return -1; } } if (ISSET(info->rti_addrs, RTA_IFA)) { const struct sockaddr *sa = info->rti_info[RTAX_IFA]; if (sa == NULL) return -1; switch (sa->sa_family) { case AF_INET: if (sa->sa_len != sizeof(struct sockaddr_in)) return -1; break; case AF_INET6: if (sa->sa_len != sizeof(struct sockaddr_in6)) return -1; break; default: return -1; } } if (ISSET(info->rti_addrs, RTA_DNS)) { const struct sockaddr_rtdns *rtdns = (const struct sockaddr_rtdns *)info->rti_info[RTAX_DNS]; if (rtdns == NULL) return -1; if (rtdns->sr_len > sizeof(*rtdns)) return -1; if (rtdns->sr_len < offsetof(struct sockaddr_rtdns, sr_dns)) return -1; switch (rtdns->sr_family) { case AF_INET: if ((rtdns->sr_len - offsetof(struct sockaddr_rtdns, sr_dns)) % sizeof(struct in_addr) != 0) return -1; break; #ifdef INET6 case AF_INET6: if ((rtdns->sr_len - offsetof(struct sockaddr_rtdns, sr_dns)) % sizeof(struct in6_addr) != 0) return -1; break; #endif default: return -1; } } if (ISSET(info->rti_addrs, RTA_STATIC)) { const struct sockaddr_rtstatic *rtstatic = (const struct sockaddr_rtstatic *)info->rti_info[RTAX_STATIC]; if (rtstatic == NULL) return -1; if (rtstatic->sr_len > sizeof(*rtstatic)) return -1; if (rtstatic->sr_len <= offsetof(struct sockaddr_rtstatic, sr_static)) return -1; } if (ISSET(info->rti_addrs, RTA_SEARCH)) { const struct sockaddr_rtsearch *rtsearch = (const struct sockaddr_rtsearch *)info->rti_info[RTAX_SEARCH]; if (rtsearch == NULL) return -1; if (rtsearch->sr_len > sizeof(*rtsearch)) return -1; if (rtsearch->sr_len <= offsetof(struct sockaddr_rtsearch, sr_search)) return -1; } return 0; } int rt_setsource(unsigned int rtableid, const struct sockaddr *src) { struct ifaddr *ifa; /* * If source address is 0.0.0.0 or :: * use automatic source selection */ switch(src->sa_family) { case AF_INET: if(satosin_const(src)->sin_addr.s_addr == INADDR_ANY) { rtable_setsource(rtableid, AF_INET, NULL); return (0); } break; #ifdef INET6 case AF_INET6: if (IN6_IS_ADDR_UNSPECIFIED(&satosin6_const(src)->sin6_addr)) { rtable_setsource(rtableid, AF_INET6, NULL); return (0); } break; #endif default: return (EAFNOSUPPORT); } /* * Check if source address is assigned to an interface in the * same rdomain */ if ((ifa = ifa_ifwithaddr(src, rtableid)) == NULL) return (EINVAL); return rtable_setsource(rtableid, src->sa_family, ifa->ifa_addr); } /* * Definitions of protocols supported in the ROUTE domain. */ const struct pr_usrreqs route_usrreqs = { .pru_attach = route_attach, .pru_detach = route_detach, .pru_disconnect = route_disconnect, .pru_shutdown = route_shutdown, .pru_rcvd = route_rcvd, .pru_send = route_send, .pru_sockaddr = route_sockaddr, .pru_peeraddr = route_peeraddr, }; const struct protosw routesw[] = { { .pr_type = SOCK_RAW, .pr_domain = &routedomain, .pr_flags = PR_ATOMIC|PR_ADDR|PR_WANTRCVD, .pr_ctloutput = route_ctloutput, .pr_usrreqs = &route_usrreqs, .pr_init = route_prinit, .pr_sysctl = sysctl_rtable } }; const struct domain routedomain = { .dom_family = PF_ROUTE, .dom_name = "route", .dom_init = route_init, .dom_protosw = routesw, .dom_protoswNPROTOSW = &routesw[nitems(routesw)] };
141 137 3 1 3 132 47 13 19 134 1 47 1 135 641 2 2 42 606 634 2 633 636 638 636 7 637 8 48 620 10 633 4 6 634 10 626 6 16 13 16 15 15 16 16 133 134 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 /* $OpenBSD: ffs_vnops.c,v 1.102 2024/02/03 18:51:58 beck Exp $ */ /* $NetBSD: ffs_vnops.c,v 1.7 1996/05/11 18:27:24 mycroft Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ffs_vnops.c 8.10 (Berkeley) 8/10/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/resourcevar.h> #include <sys/kernel.h> #include <sys/stat.h> #include <sys/buf.h> #include <sys/mount.h> #include <sys/vnode.h> #include <sys/malloc.h> #include <sys/signalvar.h> #include <sys/pool.h> #include <sys/event.h> #include <sys/specdev.h> #include <miscfs/fifofs/fifo.h> #include <ufs/ufs/quota.h> #include <ufs/ufs/inode.h> #include <ufs/ufs/dir.h> #include <ufs/ufs/ufs_extern.h> #include <ufs/ufs/ufsmount.h> #include <ufs/ffs/fs.h> #include <ufs/ffs/ffs_extern.h> const struct vops ffs_vops = { .vop_lookup = ufs_lookup, .vop_create = ufs_create, .vop_mknod = ufs_mknod, .vop_open = ufs_open, .vop_close = ufs_close, .vop_access = ufs_access, .vop_getattr = ufs_getattr, .vop_setattr = ufs_setattr, .vop_read = ffs_read, .vop_write = ffs_write, .vop_ioctl = ufs_ioctl, .vop_kqfilter = ufs_kqfilter, .vop_revoke = vop_generic_revoke, .vop_fsync = ffs_fsync, .vop_remove = ufs_remove, .vop_link = ufs_link, .vop_rename = ufs_rename, .vop_mkdir = ufs_mkdir, .vop_rmdir = ufs_rmdir, .vop_symlink = ufs_symlink, .vop_readdir = ufs_readdir, .vop_readlink = ufs_readlink, .vop_abortop = vop_generic_abortop, .vop_inactive = ufs_inactive, .vop_reclaim = ffs_reclaim, .vop_lock = ufs_lock, .vop_unlock = ufs_unlock, .vop_bmap = ufs_bmap, .vop_strategy = ufs_strategy, .vop_print = ufs_print, .vop_islocked = ufs_islocked, .vop_pathconf = ufs_pathconf, .vop_advlock = ufs_advlock, .vop_bwrite = vop_generic_bwrite }; const struct vops ffs_specvops = { .vop_close = ufsspec_close, .vop_access = ufs_access, .vop_getattr = ufs_getattr, .vop_setattr = ufs_setattr, .vop_read = ufsspec_read, .vop_write = ufsspec_write, .vop_fsync = ffs_fsync, .vop_inactive = ufs_inactive, .vop_reclaim = ffs_reclaim, .vop_lock = ufs_lock, .vop_unlock = ufs_unlock, .vop_print = ufs_print, .vop_islocked = ufs_islocked, /* XXX: Keep in sync with spec_vops */ .vop_lookup = vop_generic_lookup, .vop_create = vop_generic_badop, .vop_mknod = vop_generic_badop, .vop_open = spec_open, .vop_ioctl = spec_ioctl, .vop_kqfilter = spec_kqfilter, .vop_revoke = vop_generic_revoke, .vop_remove = vop_generic_badop, .vop_link = vop_generic_badop, .vop_rename = vop_generic_badop, .vop_mkdir = vop_generic_badop, .vop_rmdir = vop_generic_badop, .vop_symlink = vop_generic_badop, .vop_readdir = vop_generic_badop, .vop_readlink = vop_generic_badop, .vop_abortop = vop_generic_badop, .vop_bmap = vop_generic_bmap, .vop_strategy = spec_strategy, .vop_pathconf = spec_pathconf, .vop_advlock = spec_advlock, .vop_bwrite = vop_generic_bwrite, }; #ifdef FIFO const struct vops ffs_fifovops = { .vop_close = ufsfifo_close, .vop_access = ufs_access, .vop_getattr = ufs_getattr, .vop_setattr = ufs_setattr, .vop_read = ufsfifo_read, .vop_write = ufsfifo_write, .vop_fsync = ffs_fsync, .vop_inactive = ufs_inactive, .vop_reclaim = ffsfifo_reclaim, .vop_lock = ufs_lock, .vop_unlock = ufs_unlock, .vop_print = ufs_print, .vop_islocked = ufs_islocked, .vop_bwrite = vop_generic_bwrite, /* XXX: Keep in sync with fifo_vops */ .vop_lookup = vop_generic_lookup, .vop_create = vop_generic_badop, .vop_mknod = vop_generic_badop, .vop_open = fifo_open, .vop_ioctl = fifo_ioctl, .vop_kqfilter = fifo_kqfilter, .vop_revoke = vop_generic_revoke, .vop_remove = vop_generic_badop, .vop_link = vop_generic_badop, .vop_rename = vop_generic_badop, .vop_mkdir = vop_generic_badop, .vop_rmdir = vop_generic_badop, .vop_symlink = vop_generic_badop, .vop_readdir = vop_generic_badop, .vop_readlink = vop_generic_badop, .vop_abortop = vop_generic_badop, .vop_bmap = vop_generic_bmap, .vop_strategy = vop_generic_badop, .vop_pathconf = fifo_pathconf, .vop_advlock = fifo_advlock }; #endif /* FIFO */ /* * Vnode op for reading. */ int ffs_read(void *v) { struct vop_read_args *ap = v; struct vnode *vp; struct inode *ip; struct uio *uio; struct fs *fs; struct buf *bp; daddr_t lbn, nextlbn; off_t bytesinfile; int size, xfersize, blkoffset; mode_t mode; int error; vp = ap->a_vp; ip = VTOI(vp); mode = DIP(ip, mode); uio = ap->a_uio; #ifdef DIAGNOSTIC if (uio->uio_rw != UIO_READ) panic("ffs_read: mode"); if (vp->v_type == VLNK) { if (DIP(ip, size) < ip->i_ump->um_maxsymlinklen) panic("ffs_read: short symlink"); } else if (vp->v_type != VREG && vp->v_type != VDIR) panic("ffs_read: type %d", vp->v_type); #endif fs = ip->i_fs; if (uio->uio_offset < 0) return (EINVAL); if (uio->uio_resid == 0) return (0); for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) { if ((bytesinfile = DIP(ip, size) - uio->uio_offset) <= 0) break; lbn = lblkno(fs, uio->uio_offset); nextlbn = lbn + 1; size = fs->fs_bsize; /* WAS blksize(fs, ip, lbn); */ blkoffset = blkoff(fs, uio->uio_offset); xfersize = fs->fs_bsize - blkoffset; if (uio->uio_resid < xfersize) xfersize = uio->uio_resid; if (bytesinfile < xfersize) xfersize = bytesinfile; if (lblktosize(fs, nextlbn) >= DIP(ip, size)) error = bread(vp, lbn, size, &bp); else if (lbn - 1 == ip->i_ci.ci_lastr || uio->uio_resid > xfersize) { error = bread_cluster(vp, lbn, size, &bp); } else error = bread(vp, lbn, size, &bp); if (error) break; ip->i_ci.ci_lastr = lbn; /* * We should only get non-zero b_resid when an I/O error * has occurred, which should cause us to break above. * However, if the short read did not cause an error, * then we want to ensure that we do not uiomove bad * or uninitialized data. */ size -= bp->b_resid; if (size < xfersize) { if (size == 0) break; xfersize = size; } error = uiomove(bp->b_data + blkoffset, xfersize, uio); if (error) break; brelse(bp); } if (bp != NULL) brelse(bp); if (!(vp->v_mount->mnt_flag & MNT_NOATIME) || (ip->i_flag & (IN_CHANGE | IN_UPDATE))) { ip->i_flag |= IN_ACCESS; } return (error); } /* * Vnode op for writing. */ int ffs_write(void *v) { struct vop_write_args *ap = v; struct vnode *vp; struct uio *uio; struct inode *ip; struct fs *fs; struct buf *bp; daddr_t lbn; off_t osize; int blkoffset, error, extended, flags, ioflag, size, xfersize; size_t resid; ssize_t overrun; extended = 0; ioflag = ap->a_ioflag; uio = ap->a_uio; vp = ap->a_vp; ip = VTOI(vp); #ifdef DIAGNOSTIC if (uio->uio_rw != UIO_WRITE) panic("ffs_write: mode"); #endif /* * If writing 0 bytes, succeed and do not change * update time or file offset (standards compliance) */ if (uio->uio_resid == 0) return (0); switch (vp->v_type) { case VREG: if (ioflag & IO_APPEND) uio->uio_offset = DIP(ip, size); if ((DIP(ip, flags) & APPEND) && uio->uio_offset != DIP(ip, size)) return (EPERM); /* FALLTHROUGH */ case VLNK: break; case VDIR: if ((ioflag & IO_SYNC) == 0) panic("ffs_write: nonsync dir write"); break; default: panic("ffs_write: type %d", vp->v_type); } fs = ip->i_fs; if (uio->uio_offset < 0 || (u_int64_t)uio->uio_offset + uio->uio_resid > fs->fs_maxfilesize) return (EFBIG); /* do the filesize rlimit check */ if ((error = vn_fsizechk(vp, uio, ioflag, &overrun))) return (error); resid = uio->uio_resid; osize = DIP(ip, size); flags = ioflag & IO_SYNC ? B_SYNC : 0; for (error = 0; uio->uio_resid > 0;) { lbn = lblkno(fs, uio->uio_offset); blkoffset = blkoff(fs, uio->uio_offset); xfersize = fs->fs_bsize - blkoffset; if (uio->uio_resid < xfersize) xfersize = uio->uio_resid; if (fs->fs_bsize > xfersize) flags |= B_CLRBUF; else flags &= ~B_CLRBUF; if ((error = UFS_BUF_ALLOC(ip, uio->uio_offset, xfersize, ap->a_cred, flags, &bp)) != 0) break; if (uio->uio_offset + xfersize > DIP(ip, size)) { DIP_ASSIGN(ip, size, uio->uio_offset + xfersize); uvm_vnp_setsize(vp, DIP(ip, size)); extended = 1; } (void)uvm_vnp_uncache(vp); size = blksize(fs, ip, lbn) - bp->b_resid; if (size < xfersize) xfersize = size; error = uiomove(bp->b_data + blkoffset, xfersize, uio); /* * If the buffer is not already filled and we encounter an * error while trying to fill it, we have to clear out any * garbage data from the pages instantiated for the buffer. * If we do not, a failed uiomove() during a write can leave * the prior contents of the pages exposed to a userland mmap. * * Note that we don't need to clear buffers that were * allocated with the B_CLRBUF flag set. */ if (error != 0 && !(flags & B_CLRBUF)) memset(bp->b_data + blkoffset, 0, xfersize); if (ioflag & IO_NOCACHE) bp->b_flags |= B_NOCACHE; if (ioflag & IO_SYNC) (void)bwrite(bp); else if (xfersize + blkoffset == fs->fs_bsize) { bawrite(bp); } else bdwrite(bp); if (error || xfersize == 0) break; ip->i_flag |= IN_CHANGE | IN_UPDATE; } /* * If we successfully wrote any data, and we are not the superuser * we clear the setuid and setgid bits as a precaution against * tampering. */ if (resid > uio->uio_resid && ap->a_cred && ap->a_cred->cr_uid != 0 && !vnoperm(vp)) DIP_ASSIGN(ip, mode, DIP(ip, mode) & ~(ISUID | ISGID)); if (resid > uio->uio_resid) VN_KNOTE(vp, NOTE_WRITE | (extended ? NOTE_EXTEND : 0)); if (error) { if (ioflag & IO_UNIT) { (void)UFS_TRUNCATE(ip, osize, ioflag & IO_SYNC, ap->a_cred); uio->uio_offset -= resid - uio->uio_resid; uio->uio_resid = resid; } } else if (resid > uio->uio_resid && (ioflag & IO_SYNC)) { error = UFS_UPDATE(ip, 1); } /* correct the result for writes clamped by vn_fsizechk() */ uio->uio_resid += overrun; return (error); } /* * Synch an open file. */ int ffs_fsync(void *v) { struct vop_fsync_args *ap = v; struct vnode *vp = ap->a_vp; struct buf *bp, *nbp; int s, error, passes, skipmeta; /* * Flush all dirty buffers associated with a vnode. */ passes = NIADDR + 1; skipmeta = 0; if (ap->a_waitfor == MNT_WAIT) skipmeta = 1; s = splbio(); loop: LIST_FOREACH(bp, &vp->v_dirtyblkhd, b_vnbufs) { bp->b_flags &= ~B_SCANNED; } LIST_FOREACH_SAFE(bp, &vp->v_dirtyblkhd, b_vnbufs, nbp) { /* * Reasons to skip this buffer: it has already been considered * on this pass, this pass is the first time through on a * synchronous flush request and the buffer being considered * is metadata, the buffer has dependencies that will cause * it to be redirtied and it has not already been deferred, * or it is already being written. */ if (bp->b_flags & (B_BUSY | B_SCANNED)) continue; if ((bp->b_flags & B_DELWRI) == 0) panic("ffs_fsync: not dirty"); if (skipmeta && bp->b_lblkno < 0) continue; bremfree(bp); buf_acquire(bp); bp->b_flags |= B_SCANNED; splx(s); /* * On our final pass through, do all I/O synchronously * so that we can find out if our flush is failing * because of write errors. */ if (passes > 0 || ap->a_waitfor != MNT_WAIT) (void) bawrite(bp); else if ((error = bwrite(bp)) != 0) return (error); s = splbio(); /* * Since we may have slept during the I/O, we need * to start from a known point. */ nbp = LIST_FIRST(&vp->v_dirtyblkhd); } if (skipmeta) { skipmeta = 0; goto loop; } if (ap->a_waitfor == MNT_WAIT) { vwaitforio(vp, 0, "ffs_fsync", INFSLP); /* * Ensure that any filesystem metadata associated * with the vnode has been written. */ splx(s); /* XXX softdep was here. reconsider this locking dance */ s = splbio(); if (!LIST_EMPTY(&vp->v_dirtyblkhd)) { /* * Block devices associated with filesystems may * have new I/O requests posted for them even if * the vnode is locked, so no amount of trying will * get them clean. Thus we give block devices a * good effort, then just give up. For all other file * types, go around and try again until it is clean. */ if (passes > 0) { passes -= 1; goto loop; } #ifdef DIAGNOSTIC if (vp->v_type != VBLK) vprint("ffs_fsync: dirty", vp); #endif } } splx(s); return (UFS_UPDATE(VTOI(vp), ap->a_waitfor == MNT_WAIT)); } /* * Reclaim an inode so that it can be used for other purposes. */ int ffs_reclaim(void *v) { struct vop_reclaim_args *ap = v; struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); int error; if ((error = ufs_reclaim(vp)) != 0) return (error); if (ip->i_din1 != NULL) { #ifdef FFS2 if (ip->i_ump->um_fstype == UM_UFS2) pool_put(&ffs_dinode2_pool, ip->i_din2); else #endif pool_put(&ffs_dinode1_pool, ip->i_din1); } pool_put(&ffs_ino_pool, ip); vp->v_data = NULL; return (0); } #ifdef FIFO int ffsfifo_reclaim(void *v) { fifo_reclaim(v); return (ffs_reclaim(v)); } #endif
7 7 7 7 7 7 4 1 3 10 9 7 7 1 7 7 7 7 8 7 7 7 7 7 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 /* $OpenBSD: wskbdutil.c,v 1.19 2021/12/30 06:55:11 anton Exp $ */ /* $NetBSD: wskbdutil.c,v 1.7 1999/12/21 11:59:13 drochner Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Juergen Hannken-Illjes. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/errno.h> #include <sys/systm.h> #include <sys/malloc.h> #include <dev/wscons/wsksymdef.h> #include <dev/wscons/wsksymvar.h> static struct compose_tab_s { keysym_t elem[2]; keysym_t result; } compose_tab[] = { { { KS_plus, KS_plus }, KS_numbersign }, { { KS_a, KS_a }, KS_at }, { { KS_parenleft, KS_parenleft }, KS_bracketleft }, { { KS_slash, KS_slash }, KS_backslash }, { { KS_parenright, KS_parenright }, KS_bracketright }, { { KS_parenleft, KS_minus }, KS_braceleft }, { { KS_slash, KS_minus }, KS_bar }, { { KS_parenright, KS_minus }, KS_braceright }, { { KS_exclam, KS_exclam }, KS_exclamdown }, { { KS_c, KS_slash }, KS_cent }, { { KS_l, KS_minus }, KS_sterling }, { { KS_y, KS_minus }, KS_yen }, { { KS_s, KS_o }, KS_section }, { { KS_x, KS_o }, KS_currency }, { { KS_c, KS_o }, KS_copyright }, { { KS_less, KS_less }, KS_guillemotleft }, { { KS_greater, KS_greater }, KS_guillemotright }, { { KS_question, KS_question }, KS_questiondown }, { { KS_dead_acute, KS_space }, KS_apostrophe }, { { KS_dead_grave, KS_space }, KS_grave }, { { KS_dead_tilde, KS_space }, KS_asciitilde }, { { KS_dead_circumflex, KS_space }, KS_asciicircum }, { { KS_dead_diaeresis, KS_space }, KS_quotedbl }, { { KS_dead_cedilla, KS_space }, KS_comma }, { { KS_dead_circumflex, KS_A }, KS_Acircumflex }, { { KS_dead_diaeresis, KS_A }, KS_Adiaeresis }, { { KS_dead_grave, KS_A }, KS_Agrave }, { { KS_dead_abovering, KS_A }, KS_Aring }, { { KS_dead_tilde, KS_A }, KS_Atilde }, { { KS_dead_cedilla, KS_C }, KS_Ccedilla }, { { KS_dead_acute, KS_E }, KS_Eacute }, { { KS_dead_circumflex, KS_E }, KS_Ecircumflex }, { { KS_dead_diaeresis, KS_E }, KS_Ediaeresis }, { { KS_dead_grave, KS_E }, KS_Egrave }, { { KS_dead_acute, KS_I }, KS_Iacute }, { { KS_dead_circumflex, KS_I }, KS_Icircumflex }, { { KS_dead_diaeresis, KS_I }, KS_Idiaeresis }, { { KS_dead_grave, KS_I }, KS_Igrave }, { { KS_dead_tilde, KS_N }, KS_Ntilde }, { { KS_dead_acute, KS_O }, KS_Oacute }, { { KS_dead_circumflex, KS_O }, KS_Ocircumflex }, { { KS_dead_diaeresis, KS_O }, KS_Odiaeresis }, { { KS_dead_grave, KS_O }, KS_Ograve }, { { KS_dead_tilde, KS_O }, KS_Otilde }, { { KS_dead_acute, KS_U }, KS_Uacute }, { { KS_dead_circumflex, KS_U }, KS_Ucircumflex }, { { KS_dead_diaeresis, KS_U }, KS_Udiaeresis }, { { KS_dead_grave, KS_U }, KS_Ugrave }, { { KS_dead_acute, KS_Y }, KS_Yacute }, { { KS_dead_acute, KS_a }, KS_aacute }, { { KS_dead_circumflex, KS_a }, KS_acircumflex }, { { KS_dead_diaeresis, KS_a }, KS_adiaeresis }, { { KS_dead_grave, KS_a }, KS_agrave }, { { KS_dead_abovering, KS_a }, KS_aring }, { { KS_dead_tilde, KS_a }, KS_atilde }, { { KS_dead_cedilla, KS_c }, KS_ccedilla }, { { KS_dead_acute, KS_e }, KS_eacute }, { { KS_dead_circumflex, KS_e }, KS_ecircumflex }, { { KS_dead_diaeresis, KS_e }, KS_ediaeresis }, { { KS_dead_grave, KS_e }, KS_egrave }, { { KS_dead_acute, KS_i }, KS_iacute }, { { KS_dead_circumflex, KS_i }, KS_icircumflex }, { { KS_dead_diaeresis, KS_i }, KS_idiaeresis }, { { KS_dead_grave, KS_i }, KS_igrave }, { { KS_dead_tilde, KS_n }, KS_ntilde }, { { KS_dead_acute, KS_o }, KS_oacute }, { { KS_dead_circumflex, KS_o }, KS_ocircumflex }, { { KS_dead_diaeresis, KS_o }, KS_odiaeresis }, { { KS_dead_grave, KS_o }, KS_ograve }, { { KS_dead_tilde, KS_o }, KS_otilde }, { { KS_dead_acute, KS_u }, KS_uacute }, { { KS_dead_circumflex, KS_u }, KS_ucircumflex }, { { KS_dead_diaeresis, KS_u }, KS_udiaeresis }, { { KS_dead_grave, KS_u }, KS_ugrave }, { { KS_dead_acute, KS_y }, KS_yacute }, { { KS_dead_diaeresis, KS_y }, KS_ydiaeresis }, { { KS_quotedbl, KS_A }, KS_Adiaeresis }, { { KS_quotedbl, KS_E }, KS_Ediaeresis }, { { KS_quotedbl, KS_I }, KS_Idiaeresis }, { { KS_quotedbl, KS_O }, KS_Odiaeresis }, { { KS_quotedbl, KS_U }, KS_Udiaeresis }, { { KS_quotedbl, KS_a }, KS_adiaeresis }, { { KS_quotedbl, KS_e }, KS_ediaeresis }, { { KS_quotedbl, KS_i }, KS_idiaeresis }, { { KS_quotedbl, KS_o }, KS_odiaeresis }, { { KS_quotedbl, KS_u }, KS_udiaeresis }, { { KS_quotedbl, KS_y }, KS_ydiaeresis }, { { KS_acute, KS_A }, KS_Aacute }, { { KS_asciicircum, KS_A }, KS_Acircumflex }, { { KS_grave, KS_A }, KS_Agrave }, { { KS_asterisk, KS_A }, KS_Aring }, { { KS_asciitilde, KS_A }, KS_Atilde }, { { KS_cedilla, KS_C }, KS_Ccedilla }, { { KS_acute, KS_E }, KS_Eacute }, { { KS_asciicircum, KS_E }, KS_Ecircumflex }, { { KS_grave, KS_E }, KS_Egrave }, { { KS_acute, KS_I }, KS_Iacute }, { { KS_asciicircum, KS_I }, KS_Icircumflex }, { { KS_grave, KS_I }, KS_Igrave }, { { KS_asciitilde, KS_N }, KS_Ntilde }, { { KS_acute, KS_O }, KS_Oacute }, { { KS_asciicircum, KS_O }, KS_Ocircumflex }, { { KS_grave, KS_O }, KS_Ograve }, { { KS_asciitilde, KS_O }, KS_Otilde }, { { KS_acute, KS_U }, KS_Uacute }, { { KS_asciicircum, KS_U }, KS_Ucircumflex }, { { KS_grave, KS_U }, KS_Ugrave }, { { KS_acute, KS_Y }, KS_Yacute }, { { KS_acute, KS_a }, KS_aacute }, { { KS_asciicircum, KS_a }, KS_acircumflex }, { { KS_grave, KS_a }, KS_agrave }, { { KS_asterisk, KS_a }, KS_aring }, { { KS_asciitilde, KS_a }, KS_atilde }, { { KS_cedilla, KS_c }, KS_ccedilla }, { { KS_acute, KS_e }, KS_eacute }, { { KS_asciicircum, KS_e }, KS_ecircumflex }, { { KS_grave, KS_e }, KS_egrave }, { { KS_acute, KS_i }, KS_iacute }, { { KS_asciicircum, KS_i }, KS_icircumflex }, { { KS_grave, KS_i }, KS_igrave }, { { KS_asciitilde, KS_n }, KS_ntilde }, { { KS_acute, KS_o }, KS_oacute }, { { KS_asciicircum, KS_o }, KS_ocircumflex }, { { KS_grave, KS_o }, KS_ograve }, { { KS_asciitilde, KS_o }, KS_otilde }, { { KS_acute, KS_u }, KS_uacute }, { { KS_asciicircum, KS_u }, KS_ucircumflex }, { { KS_grave, KS_u }, KS_ugrave }, { { KS_acute, KS_y }, KS_yacute }, { { KS_dead_caron, KS_space }, KS_L2_caron }, { { KS_dead_caron, KS_S }, KS_L2_Scaron }, { { KS_dead_caron, KS_Z }, KS_L2_Zcaron }, { { KS_dead_caron, KS_s }, KS_L2_scaron }, { { KS_dead_caron, KS_z }, KS_L2_zcaron } }; #define COMPOSE_SIZE nitems(compose_tab) static int compose_tab_inorder = 0; keysym_t ksym_upcase(keysym_t); void fillmapentry(const keysym_t *, int, struct wscons_keymap *); static inline int compose_tab_cmp(struct compose_tab_s *i, struct compose_tab_s *j) { if (i->elem[0] == j->elem[0]) return(i->elem[1] - j->elem[1]); else return(i->elem[0] - j->elem[0]); } keysym_t wskbd_compose_value(keysym_t *compose_buf) { int i, j, r; struct compose_tab_s v; if (!compose_tab_inorder) { /* Insertion sort. */ for (i = 1; i < COMPOSE_SIZE; i++) { v = compose_tab[i]; /* find correct slot, moving others up */ for (j = i; --j >= 0 && compose_tab_cmp(&v, &compose_tab[j]) < 0;) compose_tab[j + 1] = compose_tab[j]; compose_tab[j + 1] = v; } compose_tab_inorder = 1; } for (j = 0, i = COMPOSE_SIZE; i != 0; i /= 2) { if (compose_tab[j + i/2].elem[0] == compose_buf[0]) { if (compose_tab[j + i/2].elem[1] == compose_buf[1]) return(compose_tab[j + i/2].result); r = compose_tab[j + i/2].elem[1] < compose_buf[1]; } else r = compose_tab[j + i/2].elem[0] < compose_buf[0]; if (r) { j += i/2 + 1; i--; } } return(KS_voidSymbol); } static const u_char latin1_to_upper[256] = { /* 0 8 1 9 2 a 3 b 4 c 5 d 6 e 7 f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 4 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 4 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5 */ 0x00, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 6 */ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* 6 */ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 7 */ 'X', 'Y', 'Z', 0x00, 0x00, 0x00, 0x00, 0x00, /* 7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d */ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* e */ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* e */ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0x00, /* f */ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x00, /* f */ }; keysym_t ksym_upcase(keysym_t ksym) { if (ksym >= KS_f1 && ksym <= KS_f20) return(KS_F1 - KS_f1 + ksym); if (KS_GROUP(ksym) == KS_GROUP_Ascii && ksym <= 0xff && latin1_to_upper[ksym] != 0x00) return(latin1_to_upper[ksym]); return(ksym); } void fillmapentry(const keysym_t *kp, int len, struct wscons_keymap *mapentry) { switch (len) { case 0: mapentry->group1[0] = KS_voidSymbol; mapentry->group1[1] = KS_voidSymbol; mapentry->group2[0] = KS_voidSymbol; mapentry->group2[1] = KS_voidSymbol; break; case 1: mapentry->group1[0] = kp[0]; mapentry->group1[1] = ksym_upcase(kp[0]); mapentry->group2[0] = mapentry->group1[0]; mapentry->group2[1] = mapentry->group1[1]; break; case 2: mapentry->group1[0] = kp[0]; mapentry->group1[1] = kp[1]; mapentry->group2[0] = mapentry->group1[0]; mapentry->group2[1] = mapentry->group1[1]; break; case 3: mapentry->group1[0] = kp[0]; mapentry->group1[1] = kp[1]; mapentry->group2[0] = kp[2]; mapentry->group2[1] = ksym_upcase(kp[2]); break; case 4: mapentry->group1[0] = kp[0]; mapentry->group1[1] = kp[1]; mapentry->group2[0] = kp[2]; mapentry->group2[1] = kp[3]; break; } } void wskbd_get_mapentry(const struct wskbd_mapdata *mapdata, int kc, struct wscons_keymap *mapentry) { kbd_t cur; const keysym_t *kp; const struct wscons_keydesc *mp; int l; keysym_t ksg; mapentry->command = KS_voidSymbol; mapentry->group1[0] = KS_voidSymbol; mapentry->group1[1] = KS_voidSymbol; mapentry->group2[0] = KS_voidSymbol; mapentry->group2[1] = KS_voidSymbol; for (cur = mapdata->layout & ~KB_HANDLEDBYWSKBD; cur != 0; ) { mp = mapdata->keydesc; while (mp->map_size > 0) { if (mp->name == cur) break; mp++; } /* If map not found, return */ if (mp->map_size <= 0) return; for (kp = mp->map; kp < mp->map + mp->map_size; kp++) { ksg = KS_GROUP(*kp); if (ksg == KS_GROUP_Keycode && KS_VALUE(*kp) == kc) { /* First skip keycode and possible command */ kp++; if (KS_GROUP(*kp) == KS_GROUP_Command || *kp == KS_Cmd || *kp == KS_Cmd1 || *kp == KS_Cmd2) mapentry->command = *kp++; for (l = 0; kp + l < mp->map + mp->map_size; l++) { ksg = KS_GROUP(kp[l]); if (ksg == KS_GROUP_Keycode) break; } if (l > 4) panic("wskbd_get_mapentry: %d(%d): bad entry", mp->name, *kp); fillmapentry(kp, l, mapentry); return; } } cur = mp->base; } } struct wscons_keymap * wskbd_init_keymap(int maplen) { struct wscons_keymap *map; int i; map = mallocarray(maplen, sizeof(*map), M_DEVBUF, M_WAITOK); for (i = 0; i < maplen; i++) { map[i].command = KS_voidSymbol; map[i].group1[0] = KS_voidSymbol; map[i].group1[1] = KS_voidSymbol; map[i].group2[0] = KS_voidSymbol; map[i].group2[1] = KS_voidSymbol; } return map; } int wskbd_load_keymap(const struct wskbd_mapdata *mapdata, kbd_t layout, struct wscons_keymap **map, int *maplen) { int i, s, kc, stack_ptr; const keysym_t *kp; const struct wscons_keydesc *mp, *stack[10]; kbd_t cur; keysym_t ksg; for (cur = layout & ~KB_HANDLEDBYWSKBD, stack_ptr = 0; cur != 0; stack_ptr++) { mp = mapdata->keydesc; while (mp->map_size > 0) { if (cur == 0 || mp->name == cur) { break; } mp++; } if (stack_ptr == nitems(stack)) panic("wskbd_load_keymap: %d: recursion too deep", mapdata->layout); if (mp->map_size <= 0) return(EINVAL); stack[stack_ptr] = mp; cur = mp->base; } for (i = 0, s = stack_ptr - 1; s >= 0; s--) { mp = stack[s]; for (kp = mp->map; kp < mp->map + mp->map_size; kp++) { ksg = KS_GROUP(*kp); if (ksg == KS_GROUP_Keycode && KS_VALUE(*kp) > i) i = KS_VALUE(*kp); } } *map = wskbd_init_keymap(i + 1); *maplen = i + 1; for (s = stack_ptr - 1; s >= 0; s--) { mp = stack[s]; for (kp = mp->map; kp < mp->map + mp->map_size; ) { ksg = KS_GROUP(*kp); if (ksg != KS_GROUP_Keycode) panic("wskbd_load_keymap: %d(%d): bad entry", mp->name, *kp); kc = KS_VALUE(*kp); kp++; if (KS_GROUP(*kp) == KS_GROUP_Command || *kp == KS_Cmd || *kp == KS_Cmd1 || *kp == KS_Cmd2) { (*map)[kc].command = *kp; kp++; } for (i = 0; kp + i < mp->map + mp->map_size; i++) { ksg = KS_GROUP(kp[i]); if (ksg == KS_GROUP_Keycode) break; } if (i > 4) panic("wskbd_load_keymap: %d(%d): bad entry", mp->name, *kp); fillmapentry(kp, i, &(*map)[kc]); kp += i; } } return(0); }
1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 /* $OpenBSD: midi.c,v 1.57 2024/05/13 01:15:50 jsg Exp $ */ /* * Copyright (c) 2003, 2004 Alexandre Ratchov * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/fcntl.h> #include <sys/systm.h> #include <sys/ioctl.h> #include <sys/conf.h> #include <sys/kernel.h> #include <sys/timeout.h> #include <sys/vnode.h> #include <sys/signalvar.h> #include <sys/device.h> #include <dev/midi_if.h> #include <dev/audio_if.h> #include <dev/midivar.h> #define DEVNAME(sc) ((sc)->dev.dv_xname) int midiopen(dev_t, int, int, struct proc *); int midiclose(dev_t, int, int, struct proc *); int midiread(dev_t, struct uio *, int); int midiwrite(dev_t, struct uio *, int); int midikqfilter(dev_t, struct knote *); int midiioctl(dev_t, u_long, caddr_t, int, struct proc *); int midiprobe(struct device *, void *, void *); void midiattach(struct device *, struct device *, void *); int mididetach(struct device *, int); int midiprint(void *, const char *); void midi_iintr(void *, int); void midi_ointr(void *); void midi_timeout(void *); void midi_out_start(struct midi_softc *); void midi_out_stop(struct midi_softc *); void midi_out_do(struct midi_softc *); const struct cfattach midi_ca = { sizeof(struct midi_softc), midiprobe, midiattach, mididetach }; struct cfdriver midi_cd = { NULL, "midi", DV_DULL }; void filt_midiwdetach(struct knote *); int filt_midiwrite(struct knote *, long); int filt_midimodify(struct kevent *, struct knote *); int filt_midiprocess(struct knote *, struct kevent *); const struct filterops midiwrite_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_midiwdetach, .f_event = filt_midiwrite, .f_modify = filt_midimodify, .f_process = filt_midiprocess, }; void filt_midirdetach(struct knote *); int filt_midiread(struct knote *, long); const struct filterops midiread_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_midirdetach, .f_event = filt_midiread, .f_modify = filt_midimodify, .f_process = filt_midiprocess, }; void midi_buf_wakeup(struct midi_buffer *buf) { if (buf->blocking) { wakeup(&buf->blocking); buf->blocking = 0; } knote_locked(&buf->klist, 0); } void midi_iintr(void *addr, int data) { struct midi_softc *sc = (struct midi_softc *)addr; struct midi_buffer *mb = &sc->inbuf; MUTEX_ASSERT_LOCKED(&audio_lock); if (!(sc->dev.dv_flags & DVF_ACTIVE) || !(sc->flags & FREAD)) return; if (MIDIBUF_ISFULL(mb)) return; /* discard data */ MIDIBUF_WRITE(mb, data); midi_buf_wakeup(mb); } int midiread(dev_t dev, struct uio *uio, int ioflag) { struct midi_softc *sc; struct midi_buffer *mb; size_t count; int error; sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)); if (sc == NULL) return ENXIO; if (!(sc->flags & FREAD)) { error = ENXIO; goto done; } mb = &sc->inbuf; /* if there is no data then sleep (unless IO_NDELAY flag is set) */ error = 0; mtx_enter(&audio_lock); while (MIDIBUF_ISEMPTY(mb)) { if (ioflag & IO_NDELAY) { error = EWOULDBLOCK; goto done_mtx; } sc->inbuf.blocking = 1; error = msleep_nsec(&sc->inbuf.blocking, &audio_lock, PWAIT | PCATCH, "mid_rd", INFSLP); if (!(sc->dev.dv_flags & DVF_ACTIVE)) error = EIO; if (error) goto done_mtx; } /* at this stage, there is at least 1 byte */ while (uio->uio_resid > 0 && mb->used > 0) { count = MIDIBUF_SIZE - mb->start; if (count > mb->used) count = mb->used; if (count > uio->uio_resid) count = uio->uio_resid; mtx_leave(&audio_lock); error = uiomove(mb->data + mb->start, count, uio); if (error) goto done; mtx_enter(&audio_lock); MIDIBUF_REMOVE(mb, count); } done_mtx: mtx_leave(&audio_lock); done: device_unref(&sc->dev); return error; } void midi_ointr(void *addr) { struct midi_softc *sc = (struct midi_softc *)addr; struct midi_buffer *mb; MUTEX_ASSERT_LOCKED(&audio_lock); if (!(sc->dev.dv_flags & DVF_ACTIVE) || !(sc->flags & FWRITE)) return; mb = &sc->outbuf; if (mb->used > 0) { #ifdef MIDI_DEBUG if (!sc->isbusy) { printf("midi_ointr: output must be busy\n"); } #endif midi_out_do(sc); } else if (sc->isbusy) midi_out_stop(sc); } void midi_timeout(void *addr) { mtx_enter(&audio_lock); midi_ointr(addr); mtx_leave(&audio_lock); } void midi_out_start(struct midi_softc *sc) { if (!sc->isbusy) { sc->isbusy = 1; midi_out_do(sc); } } void midi_out_stop(struct midi_softc *sc) { sc->isbusy = 0; midi_buf_wakeup(&sc->outbuf); } void midi_out_do(struct midi_softc *sc) { struct midi_buffer *mb = &sc->outbuf; while (mb->used > 0) { if (!sc->hw_if->output(sc->hw_hdl, mb->data[mb->start])) break; MIDIBUF_REMOVE(mb, 1); if (MIDIBUF_ISEMPTY(mb)) { if (sc->hw_if->flush != NULL) sc->hw_if->flush(sc->hw_hdl); midi_out_stop(sc); return; } } if (!(sc->props & MIDI_PROP_OUT_INTR)) { if (MIDIBUF_ISEMPTY(mb)) midi_out_stop(sc); else timeout_add(&sc->timeo, 1); } } int midiwrite(dev_t dev, struct uio *uio, int ioflag) { struct midi_softc *sc; struct midi_buffer *mb; size_t count; int error; sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)); if (sc == NULL) return ENXIO; if (!(sc->flags & FWRITE)) { error = ENXIO; goto done; } mb = &sc->outbuf; /* * If IO_NDELAY flag is set then check if there is enough room * in the buffer to store at least one byte. If not then dont * start the write process. */ error = 0; mtx_enter(&audio_lock); if ((ioflag & IO_NDELAY) && MIDIBUF_ISFULL(mb) && (uio->uio_resid > 0)) { error = EWOULDBLOCK; goto done_mtx; } while (uio->uio_resid > 0) { while (MIDIBUF_ISFULL(mb)) { if (ioflag & IO_NDELAY) { /* * At this stage at least one byte is already * moved so we do not return EWOULDBLOCK */ goto done_mtx; } sc->outbuf.blocking = 1; error = msleep_nsec(&sc->outbuf.blocking, &audio_lock, PWAIT | PCATCH, "mid_wr", INFSLP); if (!(sc->dev.dv_flags & DVF_ACTIVE)) error = EIO; if (error) goto done_mtx; } count = MIDIBUF_SIZE - MIDIBUF_END(mb); if (count > MIDIBUF_AVAIL(mb)) count = MIDIBUF_AVAIL(mb); if (count > uio->uio_resid) count = uio->uio_resid; mtx_leave(&audio_lock); error = uiomove(mb->data + MIDIBUF_END(mb), count, uio); if (error) goto done; mtx_enter(&audio_lock); mb->used += count; midi_out_start(sc); } done_mtx: mtx_leave(&audio_lock); done: device_unref(&sc->dev); return error; } int midikqfilter(dev_t dev, struct knote *kn) { struct midi_softc *sc; struct klist *klist; int error; sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)); if (sc == NULL) return ENXIO; error = 0; switch (kn->kn_filter) { case EVFILT_READ: klist = &sc->inbuf.klist; kn->kn_fop = &midiread_filtops; break; case EVFILT_WRITE: klist = &sc->outbuf.klist; kn->kn_fop = &midiwrite_filtops; break; default: error = EINVAL; goto done; } kn->kn_hook = (void *)sc; klist_insert(klist, kn); done: device_unref(&sc->dev); return error; } void filt_midirdetach(struct knote *kn) { struct midi_softc *sc = (struct midi_softc *)kn->kn_hook; klist_remove(&sc->inbuf.klist, kn); } int filt_midiread(struct knote *kn, long hint) { struct midi_softc *sc = (struct midi_softc *)kn->kn_hook; return (!MIDIBUF_ISEMPTY(&sc->inbuf)); } void filt_midiwdetach(struct knote *kn) { struct midi_softc *sc = (struct midi_softc *)kn->kn_hook; klist_remove(&sc->outbuf.klist, kn); } int filt_midiwrite(struct knote *kn, long hint) { struct midi_softc *sc = (struct midi_softc *)kn->kn_hook; return (!MIDIBUF_ISFULL(&sc->outbuf)); } int filt_midimodify(struct kevent *kev, struct knote *kn) { int active; mtx_enter(&audio_lock); active = knote_modify(kev, kn); mtx_leave(&audio_lock); return active; } int filt_midiprocess(struct knote *kn, struct kevent *kev) { int active; mtx_enter(&audio_lock); active = knote_process(kn, kev); mtx_leave(&audio_lock); return active; } int midiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { struct midi_softc *sc; int error; sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)); if (sc == NULL) return ENXIO; error = 0; switch(cmd) { case FIONBIO: /* All handled in the upper FS layer */ break; default: error = ENOTTY; } device_unref(&sc->dev); return error; } int midiopen(dev_t dev, int flags, int mode, struct proc *p) { struct midi_softc *sc; int error; sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)); if (sc == NULL) return ENXIO; error = 0; if (sc->flags) { error = EBUSY; goto done; } MIDIBUF_INIT(&sc->inbuf); MIDIBUF_INIT(&sc->outbuf); sc->isbusy = 0; sc->inbuf.blocking = sc->outbuf.blocking = 0; sc->flags = flags; error = sc->hw_if->open(sc->hw_hdl, flags, midi_iintr, midi_ointr, sc); if (error) sc->flags = 0; done: device_unref(&sc->dev); return error; } int midiclose(dev_t dev, int fflag, int devtype, struct proc *p) { struct midi_softc *sc; struct midi_buffer *mb; int error; sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)); if (sc == NULL) return ENXIO; /* start draining output buffer */ error = 0; mb = &sc->outbuf; mtx_enter(&audio_lock); if (!MIDIBUF_ISEMPTY(mb)) midi_out_start(sc); while (sc->isbusy) { sc->outbuf.blocking = 1; error = msleep_nsec(&sc->outbuf.blocking, &audio_lock, PWAIT, "mid_dr", SEC_TO_NSEC(5)); if (!(sc->dev.dv_flags & DVF_ACTIVE)) error = EIO; if (error) break; } mtx_leave(&audio_lock); /* * some hw_if->close() reset immediately the midi uart * which flushes the internal buffer of the uart device, * so we may lose some (important) data. To avoid this, * sleep 20ms (around 64 bytes) to give the time to the * uart to drain its internal buffers. */ tsleep_nsec(&sc->outbuf.blocking, PWAIT, "mid_cl", MSEC_TO_NSEC(20)); sc->hw_if->close(sc->hw_hdl); sc->flags = 0; device_unref(&sc->dev); return 0; } int midiprobe(struct device *parent, void *match, void *aux) { struct audio_attach_args *sa = aux; return (sa != NULL && (sa->type == AUDIODEV_TYPE_MIDI) ? 1 : 0); } void midiattach(struct device *parent, struct device *self, void *aux) { struct midi_info mi; struct midi_softc *sc = (struct midi_softc *)self; struct audio_attach_args *sa = (struct audio_attach_args *)aux; const struct midi_hw_if *hwif = sa->hwif; void *hdl = sa->hdl; #ifdef DIAGNOSTIC if (hwif == 0 || hwif->open == 0 || hwif->close == 0 || hwif->output == 0 || hwif->getinfo == 0) { printf("%s: missing method\n", DEVNAME(sc)); return; } #endif klist_init_mutex(&sc->inbuf.klist, &audio_lock); klist_init_mutex(&sc->outbuf.klist, &audio_lock); sc->hw_if = hwif; sc->hw_hdl = hdl; sc->hw_if->getinfo(sc->hw_hdl, &mi); sc->props = mi.props; sc->flags = 0; timeout_set(&sc->timeo, midi_timeout, sc); printf(": <%s>\n", mi.name); } int mididetach(struct device *self, int flags) { struct midi_softc *sc = (struct midi_softc *)self; int maj, mn; /* locate the major number */ for (maj = 0; maj < nchrdev; maj++) { if (cdevsw[maj].d_open == midiopen) { /* Nuke the vnodes for any open instances (calls close). */ mn = self->dv_unit; vdevgone(maj, mn, mn, VCHR); } } /* * The close() method did nothing (device_lookup() returns * NULL), so quickly halt transfers (normally parent is already * gone, and code below is no-op), and wake-up user-land blocked * in read/write/ioctl, which return EIO. */ if (sc->flags) { KERNEL_ASSERT_LOCKED(); if (sc->flags & FREAD) wakeup(&sc->inbuf.blocking); if (sc->flags & FWRITE) wakeup(&sc->outbuf.blocking); sc->hw_if->close(sc->hw_hdl); sc->flags = 0; } klist_invalidate(&sc->inbuf.klist); klist_invalidate(&sc->outbuf.klist); klist_free(&sc->inbuf.klist); klist_free(&sc->outbuf.klist); return 0; } int midiprint(void *aux, const char *pnp) { if (pnp) printf("midi at %s", pnp); return (UNCONF); } struct device * midi_attach_mi(const struct midi_hw_if *hwif, void *hdl, struct device *dev) { struct audio_attach_args arg; arg.type = AUDIODEV_TYPE_MIDI; arg.hwif = hwif; arg.hdl = hdl; return config_found(dev, &arg, midiprint); }
13 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 /* $OpenBSD: route.h,v 1.210 2024/03/31 15:53:12 bluhm Exp $ */ /* $NetBSD: route.h,v 1.9 1996/02/13 22:00:49 christos Exp $ */ /* * Copyright (c) 1980, 1986, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)route.h 8.3 (Berkeley) 4/19/94 */ #ifndef _NET_ROUTE_H_ #define _NET_ROUTE_H_ /* * Locks used to protect struct members in this file: * I immutable after creation * N net lock * X exclusive net lock, or shared net lock + kernel lock * R art (rtable) lock * L arp/nd6/etc lock for updates, net lock for reads * T rttimer_mtx route timer lists */ /* * Kernel resident routing tables. * * The routing tables are initialized when interface addresses * are set by making entries for all directly connected interfaces. */ #ifdef _KERNEL /* * These numbers are used by reliable protocols for determining * retransmission behavior and are included in the routing structure. */ struct rt_kmetrics { u_int64_t rmx_pksent; /* packets sent using this route */ int64_t rmx_expire; /* lifetime for route, e.g. redirect */ u_int rmx_locks; /* Kernel must leave these values */ u_int rmx_mtu; /* MTU for this path */ }; #endif /* * Huge version for userland compatibility. */ struct rt_metrics { u_int64_t rmx_pksent; /* packets sent using this route */ int64_t rmx_expire; /* lifetime for route, e.g. redirect */ u_int rmx_locks; /* Kernel must leave these values */ u_int rmx_mtu; /* MTU for this path */ u_int rmx_refcnt; /* # references hold */ /* some apps may still need these no longer used metrics */ u_int rmx_hopcount; /* max hops expected */ u_int rmx_recvpipe; /* inbound delay-bandwidth product */ u_int rmx_sendpipe; /* outbound delay-bandwidth product */ u_int rmx_ssthresh; /* outbound gateway buffer limit */ u_int rmx_rtt; /* estimated round trip time */ u_int rmx_rttvar; /* estimated rtt variance */ u_int rmx_pad; }; #ifdef _KERNEL /* * rmx_rtt and rmx_rttvar are stored as microseconds; * RTTTOPRHZ(rtt) converts to a value suitable for use * by a protocol slowtimo counter. */ #define RTM_RTTUNIT 1000000 /* units for rtt, rttvar, as units per sec */ #define RTTTOPRHZ(r) ((r) / (RTM_RTTUNIT / PR_SLOWHZ)) #include <sys/queue.h> #include <net/rtable.h> struct rttimer; /* * We distinguish between routes to hosts and routes to networks, * preferring the former if available. For each route we infer * the interface to use from the gateway address supplied when * the route was entered. Routes that forward packets through * gateways are marked with RTF_GATEWAY so that the output routines * know to address the gateway rather than the ultimate destination. * * How the RT_gw union is used also depends on RTF_GATEWAY. With * RTF_GATEWAY set, rt_gwroute points at the rtentry for the rt_gateway * address. If RTF_GATEWAY is not set, rt_cachecnt contains the * number of RTF_GATEWAY rtentry structs with their rt_gwroute pointing * at this rtentry. */ struct rtentry { struct sockaddr *rt_dest; /* [I] destination */ SRPL_ENTRY(rtentry) rt_next; /* [R] next mpath entry to our dst */ struct sockaddr *rt_gateway; /* [X] gateway address */ struct ifaddr *rt_ifa; /* [N] interface addr to use */ caddr_t rt_llinfo; /* [L] pointer to link level info or an MPLS structure */ union { struct rtentry *_nh; /* [X] rtentry for rt_gateway */ unsigned int _ref; /* [X] # gateway rtentry refs */ } RT_gw; #define rt_gwroute RT_gw._nh #define rt_cachecnt RT_gw._ref struct rtentry *rt_parent; /* [N] if cloned, parent rtentry */ LIST_HEAD(, rttimer) rt_timer; /* queue of timeouts for misc funcs */ struct rt_kmetrics rt_rmx; /* metrics used by rx'ing protocols */ unsigned int rt_ifidx; /* [N] interface to use */ unsigned int rt_flags; /* [X] up/down?, host/net */ struct refcnt rt_refcnt; /* # held references */ int rt_plen; /* [I] prefix length */ uint16_t rt_labelid; /* [N] route label ID */ uint8_t rt_priority; /* [N] routing priority to use */ }; #define rt_use rt_rmx.rmx_pksent #define rt_expire rt_rmx.rmx_expire #define rt_locks rt_rmx.rmx_locks #define rt_mtu rt_rmx.rmx_mtu #endif /* _KERNEL */ /* bitmask values for rtm_flags */ #define RTF_UP 0x1 /* route usable */ #define RTF_GATEWAY 0x2 /* destination is a gateway */ #define RTF_HOST 0x4 /* host entry (net otherwise) */ #define RTF_REJECT 0x8 /* host or net unreachable */ #define RTF_DYNAMIC 0x10 /* created dynamically (by redirect) */ #define RTF_MODIFIED 0x20 /* modified dynamically (by redirect) */ #define RTF_DONE 0x40 /* message confirmed */ #define RTF_CLONING 0x100 /* generate new routes on use */ #define RTF_MULTICAST 0x200 /* route associated to a mcast addr. */ #define RTF_LLINFO 0x400 /* generated by ARP or ND */ #define RTF_STATIC 0x800 /* manually added */ #define RTF_BLACKHOLE 0x1000 /* just discard pkts (during updates) */ #define RTF_PROTO3 0x2000 /* protocol specific routing flag */ #define RTF_PROTO2 0x4000 /* protocol specific routing flag */ #define RTF_ANNOUNCE RTF_PROTO2 /* announce L2 entry */ #define RTF_PROTO1 0x8000 /* protocol specific routing flag */ #define RTF_CLONED 0x10000 /* this is a cloned route */ #define RTF_CACHED 0x20000 /* cached by a RTF_GATEWAY entry */ #define RTF_MPATH 0x40000 /* multipath route or operation */ #define RTF_MPLS 0x100000 /* MPLS additional infos */ #define RTF_LOCAL 0x200000 /* route to a local address */ #define RTF_BROADCAST 0x400000 /* route associated to a bcast addr. */ #define RTF_CONNECTED 0x800000 /* interface route */ #define RTF_BFD 0x1000000 /* Link state controlled by BFD */ /* mask of RTF flags that are allowed to be modified by RTM_CHANGE */ #define RTF_FMASK \ (RTF_LLINFO | RTF_PROTO1 | RTF_PROTO2 | RTF_PROTO3 | RTF_BLACKHOLE | \ RTF_REJECT | RTF_STATIC | RTF_MPLS | RTF_BFD) /* Routing priorities used by the different routing protocols */ #define RTP_NONE 0 /* unset priority use sane default */ #define RTP_LOCAL 1 /* local address routes (must be the highest) */ #define RTP_CONNECTED 4 /* directly connected routes */ #define RTP_STATIC 8 /* static routes base priority */ #define RTP_EIGRP 28 /* EIGRP routes */ #define RTP_OSPF 32 /* OSPF routes */ #define RTP_ISIS 36 /* IS-IS routes */ #define RTP_RIP 40 /* RIP routes */ #define RTP_BGP 48 /* BGP routes */ #define RTP_DEFAULT 56 /* routes that have nothing set */ #define RTP_PROPOSAL_STATIC 57 #define RTP_PROPOSAL_DHCLIENT 58 #define RTP_PROPOSAL_SLAAC 59 #define RTP_PROPOSAL_UMB 60 #define RTP_PROPOSAL_PPP 61 #define RTP_PROPOSAL_SOLICIT 62 /* request reply of all RTM_PROPOSAL */ #define RTP_MAX 63 /* maximum priority */ #define RTP_ANY 64 /* any of the above */ #define RTP_MASK 0x7f #define RTP_DOWN 0x80 /* route/link is down */ /* * Routing statistics. */ struct rtstat { u_int32_t rts_badredirect; /* bogus redirect calls */ u_int32_t rts_dynamic; /* routes created by redirects */ u_int32_t rts_newgateway; /* routes modified by redirects */ u_int32_t rts_unreach; /* lookups which failed */ u_int32_t rts_wildcard; /* lookups satisfied by a wildcard */ }; /* * Routing Table Info. */ struct rt_tableinfo { u_short rti_tableid; /* routing table id */ u_short rti_domainid; /* routing domain id */ }; /* * Structures for routing messages. */ struct rt_msghdr { u_short rtm_msglen; /* to skip over non-understood messages */ u_char rtm_version; /* future binary compatibility */ u_char rtm_type; /* message type */ u_short rtm_hdrlen; /* sizeof(rt_msghdr) to skip over the header */ u_short rtm_index; /* index for associated ifp */ u_short rtm_tableid; /* routing table id */ u_char rtm_priority; /* routing priority */ u_char rtm_mpls; /* MPLS additional infos */ int rtm_addrs; /* bitmask identifying sockaddrs in msg */ int rtm_flags; /* flags, incl. kern & message, e.g. DONE */ int rtm_fmask; /* bitmask used in RTM_CHANGE message */ pid_t rtm_pid; /* identify sender */ int rtm_seq; /* for sender to identify action */ int rtm_errno; /* why failed */ u_int rtm_inits; /* which metrics we are initializing */ struct rt_metrics rtm_rmx; /* metrics themselves */ }; /* overload no longer used field */ #define rtm_use rtm_rmx.rmx_pksent #define RTM_VERSION 5 /* Up the ante and ignore older versions */ #define RTM_MAXSIZE 2048 /* Maximum size of an accepted route msg */ /* values for rtm_type */ #define RTM_ADD 0x1 /* Add Route */ #define RTM_DELETE 0x2 /* Delete Route */ #define RTM_CHANGE 0x3 /* Change Metrics or flags */ #define RTM_GET 0x4 /* Report Metrics */ #define RTM_LOSING 0x5 /* Kernel Suspects Partitioning */ #define RTM_REDIRECT 0x6 /* Told to use different route */ #define RTM_MISS 0x7 /* Lookup failed on this address */ #define RTM_RESOLVE 0xb /* req to resolve dst to LL addr */ #define RTM_NEWADDR 0xc /* address being added to iface */ #define RTM_DELADDR 0xd /* address being removed from iface */ #define RTM_IFINFO 0xe /* iface going up/down etc. */ #define RTM_IFANNOUNCE 0xf /* iface arrival/departure */ #define RTM_DESYNC 0x10 /* route socket buffer overflow */ #define RTM_INVALIDATE 0x11 /* Invalidate cache of L2 route */ #define RTM_BFD 0x12 /* bidirectional forwarding detection */ #define RTM_PROPOSAL 0x13 /* proposal for resolvd(8) */ #define RTM_CHGADDRATTR 0x14 /* address attribute change */ #define RTM_80211INFO 0x15 /* 80211 iface change */ #define RTM_SOURCE 0x16 /* set source address */ #define RTV_MTU 0x1 /* init or lock _mtu */ #define RTV_HOPCOUNT 0x2 /* init or lock _hopcount */ #define RTV_EXPIRE 0x4 /* init or lock _expire */ #define RTV_RPIPE 0x8 /* init or lock _recvpipe */ #define RTV_SPIPE 0x10 /* init or lock _sendpipe */ #define RTV_SSTHRESH 0x20 /* init or lock _ssthresh */ #define RTV_RTT 0x40 /* init or lock _rtt */ #define RTV_RTTVAR 0x80 /* init or lock _rttvar */ /* * Bitmask values for rtm_addrs. */ #define RTA_DST 0x1 /* destination sockaddr present */ #define RTA_GATEWAY 0x2 /* gateway sockaddr present */ #define RTA_NETMASK 0x4 /* netmask sockaddr present */ #define RTA_GENMASK 0x8 /* cloning mask sockaddr present */ #define RTA_IFP 0x10 /* interface name sockaddr present */ #define RTA_IFA 0x20 /* interface addr sockaddr present */ #define RTA_AUTHOR 0x40 /* sockaddr for author of redirect */ #define RTA_BRD 0x80 /* for NEWADDR, broadcast or p-p dest addr */ #define RTA_SRC 0x100 /* source sockaddr present */ #define RTA_SRCMASK 0x200 /* source netmask present */ #define RTA_LABEL 0x400 /* route label present */ #define RTA_BFD 0x800 /* bfd present */ #define RTA_DNS 0x1000 /* DNS Servers sockaddr present */ #define RTA_STATIC 0x2000 /* RFC 3442 encoded static routes present */ #define RTA_SEARCH 0x4000 /* RFC 3397 encoded search path present */ /* * Index offsets for sockaddr array for alternate internal encoding. */ #define RTAX_DST 0 /* destination sockaddr present */ #define RTAX_GATEWAY 1 /* gateway sockaddr present */ #define RTAX_NETMASK 2 /* netmask sockaddr present */ #define RTAX_GENMASK 3 /* cloning mask sockaddr present */ #define RTAX_IFP 4 /* interface name sockaddr present */ #define RTAX_IFA 5 /* interface addr sockaddr present */ #define RTAX_AUTHOR 6 /* sockaddr for author of redirect */ #define RTAX_BRD 7 /* for NEWADDR, broadcast or p-p dest addr */ #define RTAX_SRC 8 /* source sockaddr present */ #define RTAX_SRCMASK 9 /* source netmask present */ #define RTAX_LABEL 10 /* route label present */ #define RTAX_BFD 11 /* bfd present */ #define RTAX_DNS 12 /* DNS Server(s) sockaddr present */ #define RTAX_STATIC 13 /* RFC 3442 encoded static routes present */ #define RTAX_SEARCH 14 /* RFC 3397 encoded search path present */ #define RTAX_MAX 15 /* size of array to allocate */ /* * setsockopt defines used for the filtering. */ #define ROUTE_MSGFILTER 1 /* bitmask to specify which types should be sent to the client. */ #define ROUTE_TABLEFILTER 2 /* change routing table the socket is listening on, RTABLE_ANY listens on all tables. */ #define ROUTE_PRIOFILTER 3 /* only pass updates with a priority higher or equal (actual value lower) to the specified priority. */ #define ROUTE_FLAGFILTER 4 /* do not pass updates for routes with flags in this bitmask. */ #define ROUTE_FILTER(m) (1 << (m)) #define RTABLE_ANY 0xffffffff #define RTLABEL_LEN 32 struct sockaddr_rtlabel { u_int8_t sr_len; /* total length */ sa_family_t sr_family; /* address family */ char sr_label[RTLABEL_LEN]; }; #define RTDNS_LEN 128 struct sockaddr_rtdns { u_int8_t sr_len; /* total length */ sa_family_t sr_family; /* address family */ char sr_dns[RTDNS_LEN]; }; #ifdef _KERNEL static inline struct sockaddr * srtdnstosa(struct sockaddr_rtdns *sdns) { return ((struct sockaddr *)(sdns)); } #endif #define RTSTATIC_LEN 128 struct sockaddr_rtstatic { u_int8_t sr_len; /* total length */ sa_family_t sr_family; /* address family */ char sr_static[RTSTATIC_LEN]; }; #define RTSEARCH_LEN 128 struct sockaddr_rtsearch { u_int8_t sr_len; /* total length */ sa_family_t sr_family; /* address family */ char sr_search[RTSEARCH_LEN]; }; struct rt_addrinfo { int rti_addrs; const struct sockaddr *rti_info[RTAX_MAX]; int rti_flags; struct ifaddr *rti_ifa; struct rt_msghdr *rti_rtm; u_char rti_mpls; }; #ifdef __BSD_VISIBLE #include <netinet/in.h> /* * A route consists of a destination address and a reference * to a routing entry. These are often held by protocols * in their control blocks, e.g. inpcb. */ struct route { struct rtentry *ro_rt; u_long ro_generation; u_long ro_tableid; /* u_long because of alignment */ union { struct sockaddr ro_dstsa; struct sockaddr_in ro_dstsin; struct sockaddr_in6 ro_dstsin6; }; union { struct in_addr ro_srcin; struct in6_addr ro_srcin6; }; }; #endif /* __BSD_VISIBLE */ #ifdef _KERNEL #include <sys/percpu.h> enum rtstat_counters { rts_badredirect, /* bogus redirect calls */ rts_dynamic, /* routes created by redirects */ rts_newgateway, /* routes modified by redirects */ rts_unreach, /* lookups which failed */ rts_wildcard, /* lookups satisfied by a wildcard */ rts_ncounters }; static inline void rtstat_inc(enum rtstat_counters c) { extern struct cpumem *rtcounters; counters_inc(rtcounters, c); } /* * This structure, and the prototypes for the rt_timer_{init,remove_all, * add,timer} functions all used with the kind permission of BSDI. * These allow functions to be called for routes at specific times. */ struct rttimer_queue { TAILQ_HEAD(, rttimer) rtq_head; /* [T] */ LIST_ENTRY(rttimer_queue) rtq_link; /* [T] */ void (*rtq_func) /* [I] callback */ (struct rtentry *, u_int); unsigned long rtq_count; /* [T] */ int rtq_timeout; /* [T] */ }; const char *rtlabel_id2name_locked(u_int16_t); const char *rtlabel_id2name(u_int16_t, char *, size_t); u_int16_t rtlabel_name2id(const char *); struct sockaddr *rtlabel_id2sa(u_int16_t, struct sockaddr_rtlabel *); void rtlabel_unref(u_int16_t); /* * Values for additional argument to rtalloc() */ #define RT_RESOLVE 1 extern struct rtstat rtstat; extern u_long rtgeneration; struct mbuf; struct socket; struct ifnet; struct sockaddr_in6; struct if_ieee80211_data; struct bfd_config; void route_init(void); int route_cache(struct route *, const struct in_addr *, const struct in_addr *, u_int); struct rtentry *route_mpath(struct route *, const struct in_addr *, const struct in_addr *, u_int); int route6_cache(struct route *, const struct in6_addr *, const struct in6_addr *, u_int); struct rtentry *route6_mpath(struct route *, const struct in6_addr *, const struct in6_addr *, u_int); void rtm_ifchg(struct ifnet *); void rtm_ifannounce(struct ifnet *, int); void rtm_bfd(struct bfd_config *); void rtm_80211info(struct ifnet *, struct if_ieee80211_data *); void rt_maskedcopy(struct sockaddr *, struct sockaddr *, struct sockaddr *); struct sockaddr *rt_plen2mask(struct rtentry *, struct sockaddr_in6 *); void rtm_send(struct rtentry *, int, int, unsigned int); void rtm_addr(int, struct ifaddr *); void rtm_miss(int, struct rt_addrinfo *, int, uint8_t, u_int, int, u_int); void rtm_proposal(struct ifnet *, struct rt_addrinfo *, int, uint8_t); int rt_setgate(struct rtentry *, const struct sockaddr *, u_int); struct rtentry *rt_getll(struct rtentry *); void rt_timer_init(void); int rt_timer_add(struct rtentry *, struct rttimer_queue *, u_int); void rt_timer_remove_all(struct rtentry *); time_t rt_timer_get_expire(const struct rtentry *); void rt_timer_queue_init(struct rttimer_queue *, int, void(*)(struct rtentry *, u_int)); void rt_timer_queue_change(struct rttimer_queue *, int); void rt_timer_queue_flush(struct rttimer_queue *); unsigned long rt_timer_queue_count(struct rttimer_queue *); void rt_timer_timer(void *); int rt_mpls_set(struct rtentry *, const struct sockaddr *, uint8_t); void rt_mpls_clear(struct rtentry *); int rtisvalid(struct rtentry *); int rt_hash(struct rtentry *, const struct sockaddr *, uint32_t *); struct rtentry *rtalloc_mpath(const struct sockaddr *, uint32_t *, u_int); struct rtentry *rtalloc(const struct sockaddr *, int, unsigned int); void rtref(struct rtentry *); void rtfree(struct rtentry *); int rt_ifa_add(struct ifaddr *, int, struct sockaddr *, unsigned int); int rt_ifa_del(struct ifaddr *, int, struct sockaddr *, unsigned int); void rt_ifa_purge(struct ifaddr *); int rt_ifa_addlocal(struct ifaddr *); int rt_ifa_dellocal(struct ifaddr *); void rtredirect(struct sockaddr *, struct sockaddr *, struct sockaddr *, struct rtentry **, unsigned int); int rtrequest(int, struct rt_addrinfo *, u_int8_t, struct rtentry **, u_int); int rtrequest_delete(struct rt_addrinfo *, u_int8_t, struct ifnet *, struct rtentry **, u_int); int rt_if_track(struct ifnet *); int rt_if_linkstate_change(struct rtentry *, void *, u_int); int rtdeletemsg(struct rtentry *, struct ifnet *, u_int); #endif /* _KERNEL */ #endif /* _NET_ROUTE_H_ */
1942 329 330 61 42 91 1304 330 1123 1264 1119 330 220 301 120 122 122 122 1195 1195 1191 219 1122 1167 125 61 61 61 223 215 44 78 194 161 194 43 223 223 4 214 46 160 3 3 1912 1951 270 1919 570 571 30 570 564 569 31 565 23 23 5 23 5 23 2 1837 1842 1842 118 1801 1655 1005 1950 21 185 51 1122 749 1444 4 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 /* $OpenBSD: uvm_page.c,v 1.177 2024/05/01 12:54:27 mpi Exp $ */ /* $NetBSD: uvm_page.c,v 1.44 2000/11/27 08:40:04 chs Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. * Copyright (c) 1991, 1993, The Regents of the University of California. * * All rights reserved. * * This code is derived from software contributed to Berkeley by * The Mach Operating System project at Carnegie-Mellon University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)vm_page.c 8.3 (Berkeley) 3/21/94 * from: Id: uvm_page.c,v 1.1.2.18 1998/02/06 05:24:42 chs Exp * * * Copyright (c) 1987, 1990 Carnegie-Mellon University. * All rights reserved. * * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ /* * uvm_page.c: page ops. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/sched.h> #include <sys/vnode.h> #include <sys/mount.h> #include <sys/proc.h> #include <sys/smr.h> #include <uvm/uvm.h> /* * for object trees */ RBT_GENERATE(uvm_objtree, vm_page, objt, uvm_pagecmp); int uvm_pagecmp(const struct vm_page *a, const struct vm_page *b) { return a->offset < b->offset ? -1 : a->offset > b->offset; } /* * global vars... XXXCDC: move to uvm. structure. */ /* * physical memory config is stored in vm_physmem. */ struct vm_physseg vm_physmem[VM_PHYSSEG_MAX]; /* XXXCDC: uvm.physmem */ int vm_nphysseg = 0; /* XXXCDC: uvm.nphysseg */ /* * Some supported CPUs in a given architecture don't support all * of the things necessary to do idle page zero'ing efficiently. * We therefore provide a way to disable it from machdep code here. */ /* * local variables */ /* * these variables record the values returned by vm_page_bootstrap, * for debugging purposes. The implementation of uvm_pageboot_alloc * and pmap_startup here also uses them internally. */ static vaddr_t virtual_space_start; static vaddr_t virtual_space_end; /* * local prototypes */ static void uvm_pageinsert(struct vm_page *); static void uvm_pageremove(struct vm_page *); int uvm_page_owner_locked_p(struct vm_page *); /* * inline functions */ /* * uvm_pageinsert: insert a page in the object * * => caller must lock object * => call should have already set pg's object and offset pointers * and bumped the version counter */ static inline void uvm_pageinsert(struct vm_page *pg) { struct vm_page *dupe; KASSERT(UVM_OBJ_IS_DUMMY(pg->uobject) || rw_write_held(pg->uobject->vmobjlock)); KASSERT((pg->pg_flags & PG_TABLED) == 0); dupe = RBT_INSERT(uvm_objtree, &pg->uobject->memt, pg); /* not allowed to insert over another page */ KASSERT(dupe == NULL); atomic_setbits_int(&pg->pg_flags, PG_TABLED); pg->uobject->uo_npages++; } /* * uvm_page_remove: remove page from object * * => caller must lock object */ static inline void uvm_pageremove(struct vm_page *pg) { KASSERT(UVM_OBJ_IS_DUMMY(pg->uobject) || rw_write_held(pg->uobject->vmobjlock)); KASSERT(pg->pg_flags & PG_TABLED); RBT_REMOVE(uvm_objtree, &pg->uobject->memt, pg); atomic_clearbits_int(&pg->pg_flags, PG_TABLED); pg->uobject->uo_npages--; pg->uobject = NULL; pg->pg_version++; } /* * uvm_page_init: init the page system. called from uvm_init(). * * => we return the range of kernel virtual memory in kvm_startp/kvm_endp */ void uvm_page_init(vaddr_t *kvm_startp, vaddr_t *kvm_endp) { vsize_t freepages, pagecount, n; vm_page_t pagearray, curpg; int lcv, i; paddr_t paddr, pgno; struct vm_physseg *seg; /* * init the page queues and page queue locks */ TAILQ_INIT(&uvm.page_active); TAILQ_INIT(&uvm.page_inactive); mtx_init(&uvm.pageqlock, IPL_VM); mtx_init(&uvm.fpageqlock, IPL_VM); uvm_pmr_init(); /* * allocate vm_page structures. */ /* * sanity check: * before calling this function the MD code is expected to register * some free RAM with the uvm_page_physload() function. our job * now is to allocate vm_page structures for this memory. */ if (vm_nphysseg == 0) panic("uvm_page_bootstrap: no memory pre-allocated"); /* * first calculate the number of free pages... * * note that we use start/end rather than avail_start/avail_end. * this allows us to allocate extra vm_page structures in case we * want to return some memory to the pool after booting. */ freepages = 0; for (lcv = 0, seg = vm_physmem; lcv < vm_nphysseg ; lcv++, seg++) freepages += (seg->end - seg->start); /* * we now know we have (PAGE_SIZE * freepages) bytes of memory we can * use. for each page of memory we use we need a vm_page structure. * thus, the total number of pages we can use is the total size of * the memory divided by the PAGE_SIZE plus the size of the vm_page * structure. we add one to freepages as a fudge factor to avoid * truncation errors (since we can only allocate in terms of whole * pages). */ pagecount = (((paddr_t)freepages + 1) << PAGE_SHIFT) / (PAGE_SIZE + sizeof(struct vm_page)); pagearray = (vm_page_t)uvm_pageboot_alloc(pagecount * sizeof(struct vm_page)); memset(pagearray, 0, pagecount * sizeof(struct vm_page)); /* init the vm_page structures and put them in the correct place. */ for (lcv = 0, seg = vm_physmem; lcv < vm_nphysseg ; lcv++, seg++) { n = seg->end - seg->start; if (n > pagecount) { panic("uvm_page_init: lost %ld page(s) in init", (long)(n - pagecount)); /* XXXCDC: shouldn't happen? */ /* n = pagecount; */ } /* set up page array pointers */ seg->pgs = pagearray; pagearray += n; pagecount -= n; seg->lastpg = seg->pgs + (n - 1); /* init and free vm_pages (we've already zeroed them) */ pgno = seg->start; paddr = ptoa(pgno); for (i = 0, curpg = seg->pgs; i < n; i++, curpg++, pgno++, paddr += PAGE_SIZE) { curpg->phys_addr = paddr; VM_MDPAGE_INIT(curpg); if (pgno >= seg->avail_start && pgno < seg->avail_end) { uvmexp.npages++; } } /* Add pages to free pool. */ uvm_pmr_freepages(&seg->pgs[seg->avail_start - seg->start], seg->avail_end - seg->avail_start); } /* * pass up the values of virtual_space_start and * virtual_space_end (obtained by uvm_pageboot_alloc) to the upper * layers of the VM. */ *kvm_startp = round_page(virtual_space_start); *kvm_endp = trunc_page(virtual_space_end); /* init locks for kernel threads */ mtx_init(&uvm.aiodoned_lock, IPL_BIO); /* * init reserve thresholds * XXXCDC - values may need adjusting */ uvmexp.reserve_pagedaemon = 4; uvmexp.reserve_kernel = 8; uvmexp.anonminpct = 10; uvmexp.vnodeminpct = 10; uvmexp.vtextminpct = 5; uvmexp.anonmin = uvmexp.anonminpct * 256 / 100; uvmexp.vnodemin = uvmexp.vnodeminpct * 256 / 100; uvmexp.vtextmin = uvmexp.vtextminpct * 256 / 100; uvm.page_init_done = TRUE; } /* * uvm_setpagesize: set the page size * * => sets page_shift and page_mask from uvmexp.pagesize. */ void uvm_setpagesize(void) { if (uvmexp.pagesize == 0) uvmexp.pagesize = DEFAULT_PAGE_SIZE; uvmexp.pagemask = uvmexp.pagesize - 1; if ((uvmexp.pagemask & uvmexp.pagesize) != 0) panic("uvm_setpagesize: page size not a power of two"); for (uvmexp.pageshift = 0; ; uvmexp.pageshift++) if ((1 << uvmexp.pageshift) == uvmexp.pagesize) break; } /* * uvm_pageboot_alloc: steal memory from physmem for bootstrapping */ vaddr_t uvm_pageboot_alloc(vsize_t size) { #if defined(PMAP_STEAL_MEMORY) vaddr_t addr; /* * defer bootstrap allocation to MD code (it may want to allocate * from a direct-mapped segment). pmap_steal_memory should round * off virtual_space_start/virtual_space_end. */ addr = pmap_steal_memory(size, &virtual_space_start, &virtual_space_end); return addr; #else /* !PMAP_STEAL_MEMORY */ static boolean_t initialized = FALSE; vaddr_t addr, vaddr; paddr_t paddr; /* round to page size */ size = round_page(size); /* on first call to this function, initialize ourselves. */ if (initialized == FALSE) { pmap_virtual_space(&virtual_space_start, &virtual_space_end); /* round it the way we like it */ virtual_space_start = round_page(virtual_space_start); virtual_space_end = trunc_page(virtual_space_end); initialized = TRUE; } /* allocate virtual memory for this request */ if (virtual_space_start == virtual_space_end || (virtual_space_end - virtual_space_start) < size) panic("uvm_pageboot_alloc: out of virtual space"); addr = virtual_space_start; #ifdef PMAP_GROWKERNEL /* * If the kernel pmap can't map the requested space, * then allocate more resources for it. */ if (uvm_maxkaddr < (addr + size)) { uvm_maxkaddr = pmap_growkernel(addr + size); if (uvm_maxkaddr < (addr + size)) panic("uvm_pageboot_alloc: pmap_growkernel() failed"); } #endif virtual_space_start += size; /* allocate and mapin physical pages to back new virtual pages */ for (vaddr = round_page(addr) ; vaddr < addr + size ; vaddr += PAGE_SIZE) { if (!uvm_page_physget(&paddr)) panic("uvm_pageboot_alloc: out of memory"); /* * Note this memory is no longer managed, so using * pmap_kenter is safe. */ pmap_kenter_pa(vaddr, paddr, PROT_READ | PROT_WRITE); } pmap_update(pmap_kernel()); return addr; #endif /* PMAP_STEAL_MEMORY */ } #if !defined(PMAP_STEAL_MEMORY) /* * uvm_page_physget: "steal" one page from the vm_physmem structure. * * => attempt to allocate it off the end of a segment in which the "avail" * values match the start/end values. if we can't do that, then we * will advance both values (making them equal, and removing some * vm_page structures from the non-avail area). * => return false if out of memory. */ boolean_t uvm_page_physget(paddr_t *paddrp) { int lcv; struct vm_physseg *seg; /* pass 1: try allocating from a matching end */ #if (VM_PHYSSEG_STRAT == VM_PSTRAT_BIGFIRST) || \ (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH) for (lcv = vm_nphysseg - 1, seg = vm_physmem + lcv; lcv >= 0; lcv--, seg--) #else for (lcv = 0, seg = vm_physmem; lcv < vm_nphysseg ; lcv++, seg++) #endif { if (uvm.page_init_done == TRUE) panic("uvm_page_physget: called _after_ bootstrap"); /* try from front */ if (seg->avail_start == seg->start && seg->avail_start < seg->avail_end) { *paddrp = ptoa(seg->avail_start); seg->avail_start++; seg->start++; /* nothing left? nuke it */ if (seg->avail_start == seg->end) { if (vm_nphysseg == 1) panic("uvm_page_physget: out of memory!"); vm_nphysseg--; for (; lcv < vm_nphysseg; lcv++, seg++) /* structure copy */ seg[0] = seg[1]; } return TRUE; } /* try from rear */ if (seg->avail_end == seg->end && seg->avail_start < seg->avail_end) { *paddrp = ptoa(seg->avail_end - 1); seg->avail_end--; seg->end--; /* nothing left? nuke it */ if (seg->avail_end == seg->start) { if (vm_nphysseg == 1) panic("uvm_page_physget: out of memory!"); vm_nphysseg--; for (; lcv < vm_nphysseg ; lcv++, seg++) /* structure copy */ seg[0] = seg[1]; } return TRUE; } } /* pass2: forget about matching ends, just allocate something */ #if (VM_PHYSSEG_STRAT == VM_PSTRAT_BIGFIRST) || \ (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH) for (lcv = vm_nphysseg - 1, seg = vm_physmem + lcv; lcv >= 0; lcv--, seg--) #else for (lcv = 0, seg = vm_physmem; lcv < vm_nphysseg ; lcv++, seg++) #endif { /* any room in this bank? */ if (seg->avail_start >= seg->avail_end) continue; /* nope */ *paddrp = ptoa(seg->avail_start); seg->avail_start++; /* truncate! */ seg->start = seg->avail_start; /* nothing left? nuke it */ if (seg->avail_start == seg->end) { if (vm_nphysseg == 1) panic("uvm_page_physget: out of memory!"); vm_nphysseg--; for (; lcv < vm_nphysseg ; lcv++, seg++) /* structure copy */ seg[0] = seg[1]; } return TRUE; } return FALSE; /* whoops! */ } #endif /* PMAP_STEAL_MEMORY */ /* * uvm_page_physload: load physical memory into VM system * * => all args are PFs * => all pages in start/end get vm_page structures * => areas marked by avail_start/avail_end get added to the free page pool * => we are limited to VM_PHYSSEG_MAX physical memory segments */ void uvm_page_physload(paddr_t start, paddr_t end, paddr_t avail_start, paddr_t avail_end, int flags) { int preload, lcv; psize_t npages; struct vm_page *pgs; struct vm_physseg *ps, *seg; #ifdef DIAGNOSTIC if (uvmexp.pagesize == 0) panic("uvm_page_physload: page size not set!"); if (start >= end) panic("uvm_page_physload: start >= end"); #endif /* do we have room? */ if (vm_nphysseg == VM_PHYSSEG_MAX) { printf("uvm_page_physload: unable to load physical memory " "segment\n"); printf("\t%d segments allocated, ignoring 0x%llx -> 0x%llx\n", VM_PHYSSEG_MAX, (long long)start, (long long)end); printf("\tincrease VM_PHYSSEG_MAX\n"); return; } /* * check to see if this is a "preload" (i.e. uvm_mem_init hasn't been * called yet, so malloc is not available). */ for (lcv = 0, seg = vm_physmem; lcv < vm_nphysseg; lcv++, seg++) { if (seg->pgs) break; } preload = (lcv == vm_nphysseg); /* if VM is already running, attempt to malloc() vm_page structures */ if (!preload) { /* * XXXCDC: need some sort of lockout for this case * right now it is only used by devices so it should be alright. */ paddr_t paddr; npages = end - start; /* # of pages */ pgs = km_alloc(round_page(npages * sizeof(*pgs)), &kv_any, &kp_zero, &kd_waitok); if (pgs == NULL) { printf("uvm_page_physload: can not malloc vm_page " "structs for segment\n"); printf("\tignoring 0x%lx -> 0x%lx\n", start, end); return; } /* init phys_addr and free pages, XXX uvmexp.npages */ for (lcv = 0, paddr = ptoa(start); lcv < npages; lcv++, paddr += PAGE_SIZE) { pgs[lcv].phys_addr = paddr; VM_MDPAGE_INIT(&pgs[lcv]); if (atop(paddr) >= avail_start && atop(paddr) < avail_end) { if (flags & PHYSLOAD_DEVICE) { atomic_setbits_int(&pgs[lcv].pg_flags, PG_DEV); pgs[lcv].wire_count = 1; } else { #if defined(VM_PHYSSEG_NOADD) panic("uvm_page_physload: tried to add RAM after vm_mem_init"); #endif } } } /* Add pages to free pool. */ if ((flags & PHYSLOAD_DEVICE) == 0) { uvm_pmr_freepages(&pgs[avail_start - start], avail_end - avail_start); } /* XXXCDC: need hook to tell pmap to rebuild pv_list, etc... */ } else { /* gcc complains if these don't get init'd */ pgs = NULL; npages = 0; } /* now insert us in the proper place in vm_physmem[] */ #if (VM_PHYSSEG_STRAT == VM_PSTRAT_RANDOM) /* random: put it at the end (easy!) */ ps = &vm_physmem[vm_nphysseg]; #elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH) { int x; /* sort by address for binary search */ for (lcv = 0, seg = vm_physmem; lcv < vm_nphysseg; lcv++, seg++) if (start < seg->start) break; ps = seg; /* move back other entries, if necessary ... */ for (x = vm_nphysseg, seg = vm_physmem + x - 1; x > lcv; x--, seg--) /* structure copy */ seg[1] = seg[0]; } #elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BIGFIRST) { int x; /* sort by largest segment first */ for (lcv = 0, seg = vm_physmem; lcv < vm_nphysseg; lcv++, seg++) if ((end - start) > (seg->end - seg->start)) break; ps = &vm_physmem[lcv]; /* move back other entries, if necessary ... */ for (x = vm_nphysseg, seg = vm_physmem + x - 1; x > lcv; x--, seg--) /* structure copy */ seg[1] = seg[0]; } #else panic("uvm_page_physload: unknown physseg strategy selected!"); #endif ps->start = start; ps->end = end; ps->avail_start = avail_start; ps->avail_end = avail_end; if (preload) { ps->pgs = NULL; } else { ps->pgs = pgs; ps->lastpg = pgs + npages - 1; } vm_nphysseg++; return; } #ifdef DDB /* XXXCDC: TMP TMP TMP DEBUG DEBUG DEBUG */ void uvm_page_physdump(void); /* SHUT UP GCC */ /* call from DDB */ void uvm_page_physdump(void) { int lcv; struct vm_physseg *seg; printf("uvm_page_physdump: physical memory config [segs=%d of %d]:\n", vm_nphysseg, VM_PHYSSEG_MAX); for (lcv = 0, seg = vm_physmem; lcv < vm_nphysseg ; lcv++, seg++) printf("0x%llx->0x%llx [0x%llx->0x%llx]\n", (long long)seg->start, (long long)seg->end, (long long)seg->avail_start, (long long)seg->avail_end); printf("STRATEGY = "); switch (VM_PHYSSEG_STRAT) { case VM_PSTRAT_RANDOM: printf("RANDOM\n"); break; case VM_PSTRAT_BSEARCH: printf("BSEARCH\n"); break; case VM_PSTRAT_BIGFIRST: printf("BIGFIRST\n"); break; default: printf("<<UNKNOWN>>!!!!\n"); } } #endif void uvm_shutdown(void) { #ifdef UVM_SWAP_ENCRYPT uvm_swap_finicrypt_all(); #endif smr_flush(); } /* * Perform insert of a given page in the specified anon of obj. * This is basically, uvm_pagealloc, but with the page already given. */ void uvm_pagealloc_pg(struct vm_page *pg, struct uvm_object *obj, voff_t off, struct vm_anon *anon) { int flags; KASSERT(obj == NULL || anon == NULL); KASSERT(anon == NULL || off == 0); KASSERT(off == trunc_page(off)); KASSERT(obj == NULL || UVM_OBJ_IS_DUMMY(obj) || rw_write_held(obj->vmobjlock)); KASSERT(anon == NULL || anon->an_lock == NULL || rw_write_held(anon->an_lock)); flags = PG_BUSY | PG_FAKE; pg->offset = off; pg->uobject = obj; pg->uanon = anon; KASSERT(uvm_page_owner_locked_p(pg)); if (anon) { anon->an_page = pg; flags |= PQ_ANON; } else if (obj) uvm_pageinsert(pg); atomic_setbits_int(&pg->pg_flags, flags); #if defined(UVM_PAGE_TRKOWN) pg->owner_tag = NULL; #endif UVM_PAGE_OWN(pg, "new alloc"); } /* * uvm_pglistalloc: allocate a list of pages * * => allocated pages are placed at the tail of rlist. rlist is * assumed to be properly initialized by caller. * => returns 0 on success or errno on failure * => doesn't take into account clean non-busy pages on inactive list * that could be used(?) * => params: * size the size of the allocation, rounded to page size. * low the low address of the allowed allocation range. * high the high address of the allowed allocation range. * alignment memory must be aligned to this power-of-two boundary. * boundary no segment in the allocation may cross this * power-of-two boundary (relative to zero). * => flags: * UVM_PLA_NOWAIT fail if allocation fails * UVM_PLA_WAITOK wait for memory to become avail * UVM_PLA_ZERO return zeroed memory */ int uvm_pglistalloc(psize_t size, paddr_t low, paddr_t high, paddr_t alignment, paddr_t boundary, struct pglist *rlist, int nsegs, int flags) { KASSERT((alignment & (alignment - 1)) == 0); KASSERT((boundary & (boundary - 1)) == 0); KASSERT(!(flags & UVM_PLA_WAITOK) ^ !(flags & UVM_PLA_NOWAIT)); if (size == 0) return EINVAL; size = atop(round_page(size)); /* * XXX uvm_pglistalloc is currently only used for kernel * objects. Unlike the checks in uvm_pagealloc, below, here * we are always allowed to use the kernel reserve. */ flags |= UVM_PLA_USERESERVE; if ((high & PAGE_MASK) != PAGE_MASK) { printf("uvm_pglistalloc: Upper boundary 0x%lx " "not on pagemask.\n", (unsigned long)high); } /* * Our allocations are always page granularity, so our alignment * must be, too. */ if (alignment < PAGE_SIZE) alignment = PAGE_SIZE; low = atop(roundup(low, alignment)); /* * high + 1 may result in overflow, in which case high becomes 0x0, * which is the 'don't care' value. * The only requirement in that case is that low is also 0x0, or the * low<high assert will fail. */ high = atop(high + 1); alignment = atop(alignment); if (boundary < PAGE_SIZE && boundary != 0) boundary = PAGE_SIZE; boundary = atop(boundary); return uvm_pmr_getpages(size, low, high, alignment, boundary, nsegs, flags, rlist); } /* * uvm_pglistfree: free a list of pages * * => pages should already be unmapped */ void uvm_pglistfree(struct pglist *list) { uvm_pmr_freepageq(list); } /* * interface used by the buffer cache to allocate a buffer at a time. * The pages are allocated wired in DMA accessible memory */ int uvm_pagealloc_multi(struct uvm_object *obj, voff_t off, vsize_t size, int flags) { struct pglist plist; struct vm_page *pg; int i, r; KASSERT(UVM_OBJ_IS_BUFCACHE(obj)); KERNEL_ASSERT_LOCKED(); TAILQ_INIT(&plist); r = uvm_pglistalloc(size, dma_constraint.ucr_low, dma_constraint.ucr_high, 0, 0, &plist, atop(round_page(size)), flags); if (r == 0) { i = 0; while ((pg = TAILQ_FIRST(&plist)) != NULL) { pg->wire_count = 1; atomic_setbits_int(&pg->pg_flags, PG_CLEAN | PG_FAKE); KASSERT((pg->pg_flags & PG_DEV) == 0); TAILQ_REMOVE(&plist, pg, pageq); uvm_pagealloc_pg(pg, obj, off + ptoa(i++), NULL); } } return r; } /* * interface used by the buffer cache to reallocate a buffer at a time. * The pages are reallocated wired outside the DMA accessible region. * */ int uvm_pagerealloc_multi(struct uvm_object *obj, voff_t off, vsize_t size, int flags, struct uvm_constraint_range *where) { struct pglist plist; struct vm_page *pg, *tpg; int i, r; voff_t offset; KASSERT(UVM_OBJ_IS_BUFCACHE(obj)); KERNEL_ASSERT_LOCKED(); TAILQ_INIT(&plist); if (size == 0) panic("size 0 uvm_pagerealloc"); r = uvm_pglistalloc(size, where->ucr_low, where->ucr_high, 0, 0, &plist, atop(round_page(size)), flags); if (r == 0) { i = 0; while((pg = TAILQ_FIRST(&plist)) != NULL) { offset = off + ptoa(i++); tpg = uvm_pagelookup(obj, offset); KASSERT(tpg != NULL); pg->wire_count = 1; atomic_setbits_int(&pg->pg_flags, PG_CLEAN | PG_FAKE); KASSERT((pg->pg_flags & PG_DEV) == 0); TAILQ_REMOVE(&plist, pg, pageq); uvm_pagecopy(tpg, pg); KASSERT(tpg->wire_count == 1); tpg->wire_count = 0; uvm_lock_pageq(); uvm_pagefree(tpg); uvm_unlock_pageq(); uvm_pagealloc_pg(pg, obj, offset, NULL); } } return r; } /* * uvm_pagealloc: allocate vm_page from a particular free list. * * => return null if no pages free * => wake up pagedaemon if number of free pages drops below low water mark * => only one of obj or anon can be non-null * => caller must activate/deactivate page if it is not wired. */ struct vm_page * uvm_pagealloc(struct uvm_object *obj, voff_t off, struct vm_anon *anon, int flags) { struct vm_page *pg = NULL; int pmr_flags; KASSERT(obj == NULL || anon == NULL); KASSERT(anon == NULL || off == 0); KASSERT(off == trunc_page(off)); KASSERT(obj == NULL || UVM_OBJ_IS_DUMMY(obj) || rw_write_held(obj->vmobjlock)); KASSERT(anon == NULL || anon->an_lock == NULL || rw_write_held(anon->an_lock)); pmr_flags = UVM_PLA_NOWAIT; /* * We're allowed to use the kernel reserve if the page is * being allocated to a kernel object. */ if ((flags & UVM_PGA_USERESERVE) || (obj != NULL && UVM_OBJ_IS_KERN_OBJECT(obj))) pmr_flags |= UVM_PLA_USERESERVE; if (flags & UVM_PGA_ZERO) pmr_flags |= UVM_PLA_ZERO; pg = uvm_pmr_cache_get(pmr_flags); if (pg == NULL) return NULL; uvm_pagealloc_pg(pg, obj, off, anon); KASSERT((pg->pg_flags & PG_DEV) == 0); if (flags & UVM_PGA_ZERO) atomic_clearbits_int(&pg->pg_flags, PG_CLEAN); else atomic_setbits_int(&pg->pg_flags, PG_CLEAN); return pg; } /* * uvm_pagerealloc: reallocate a page from one object to another */ void uvm_pagerealloc(struct vm_page *pg, struct uvm_object *newobj, voff_t newoff) { /* remove it from the old object */ if (pg->uobject) { uvm_pageremove(pg); } /* put it in the new object */ if (newobj) { pg->uobject = newobj; pg->offset = newoff; pg->pg_version++; uvm_pageinsert(pg); } } /* * uvm_pageclean: clean page * * => erase page's identity (i.e. remove from object) * => caller must lock page queues if `pg' is managed * => assumes all valid mappings of pg are gone */ void uvm_pageclean(struct vm_page *pg) { u_int flags_to_clear = 0; if ((pg->pg_flags & (PG_TABLED|PQ_ACTIVE|PQ_INACTIVE)) && (pg->uobject == NULL || !UVM_OBJ_IS_PMAP(pg->uobject))) MUTEX_ASSERT_LOCKED(&uvm.pageqlock); #ifdef DEBUG if (pg->uobject == (void *)0xdeadbeef && pg->uanon == (void *)0xdeadbeef) { panic("uvm_pagefree: freeing free page %p", pg); } #endif KASSERT((pg->pg_flags & PG_DEV) == 0); KASSERT(pg->uobject == NULL || UVM_OBJ_IS_DUMMY(pg->uobject) || rw_write_held(pg->uobject->vmobjlock)); KASSERT(pg->uobject != NULL || pg->uanon == NULL || rw_write_held(pg->uanon->an_lock)); /* * if the page was an object page (and thus "TABLED"), remove it * from the object. */ if (pg->pg_flags & PG_TABLED) uvm_pageremove(pg); /* * now remove the page from the queues */ uvm_pagedequeue(pg); /* * if the page was wired, unwire it now. */ if (pg->wire_count) { pg->wire_count = 0; uvmexp.wired--; } if (pg->uanon) { pg->uanon->an_page = NULL; pg->uanon = NULL; } /* Clean page state bits. */ flags_to_clear |= PQ_ANON|PQ_AOBJ|PQ_ENCRYPT|PG_ZERO|PG_FAKE|PG_BUSY| PG_RELEASED|PG_CLEAN|PG_CLEANCHK; atomic_clearbits_int(&pg->pg_flags, flags_to_clear); #ifdef DEBUG pg->uobject = (void *)0xdeadbeef; pg->offset = 0xdeadbeef; pg->uanon = (void *)0xdeadbeef; #endif } /* * uvm_pagefree: free page * * => erase page's identity (i.e. remove from object) * => put page on free list * => caller must lock page queues if `pg' is managed * => assumes all valid mappings of pg are gone */ void uvm_pagefree(struct vm_page *pg) { uvm_pageclean(pg); uvm_pmr_cache_put(pg); } /* * uvm_page_unbusy: unbusy an array of pages. * * => pages must either all belong to the same object, or all belong to anons. * => if pages are object-owned, object must be locked. * => if pages are anon-owned, anons must have 0 refcount. * => caller must make sure that anon-owned pages are not PG_RELEASED. */ void uvm_page_unbusy(struct vm_page **pgs, int npgs) { struct vm_page *pg; int i; for (i = 0; i < npgs; i++) { pg = pgs[i]; if (pg == NULL || pg == PGO_DONTCARE) { continue; } KASSERT(uvm_page_owner_locked_p(pg)); KASSERT(pg->pg_flags & PG_BUSY); if (pg->pg_flags & PG_WANTED) { wakeup(pg); } if (pg->pg_flags & PG_RELEASED) { KASSERT(pg->uobject != NULL || (pg->uanon != NULL && pg->uanon->an_ref > 0)); atomic_clearbits_int(&pg->pg_flags, PG_RELEASED); pmap_page_protect(pg, PROT_NONE); uvm_pagefree(pg); } else { KASSERT((pg->pg_flags & PG_FAKE) == 0); atomic_clearbits_int(&pg->pg_flags, PG_WANTED|PG_BUSY); UVM_PAGE_OWN(pg, NULL); } } } /* * uvm_pagewait: wait for a busy page * * => page must be known PG_BUSY * => object must be locked * => object will be unlocked on return */ void uvm_pagewait(struct vm_page *pg, struct rwlock *lock, const char *wmesg) { KASSERT(rw_lock_held(lock)); KASSERT((pg->pg_flags & PG_BUSY) != 0); atomic_setbits_int(&pg->pg_flags, PG_WANTED); rwsleep_nsec(pg, lock, PVM | PNORELOCK, wmesg, INFSLP); } #if defined(UVM_PAGE_TRKOWN) /* * uvm_page_own: set or release page ownership * * => this is a debugging function that keeps track of who sets PG_BUSY * and where they do it. it can be used to track down problems * such a thread setting "PG_BUSY" and never releasing it. * => if "tag" is NULL then we are releasing page ownership */ void uvm_page_own(struct vm_page *pg, char *tag) { /* gain ownership? */ if (tag) { if (pg->owner_tag) { printf("uvm_page_own: page %p already owned " "by thread %d [%s]\n", pg, pg->owner, pg->owner_tag); panic("uvm_page_own"); } pg->owner = (curproc) ? curproc->p_tid : (pid_t) -1; pg->owner_tag = tag; return; } /* drop ownership */ if (pg->owner_tag == NULL) { printf("uvm_page_own: dropping ownership of an non-owned " "page (%p)\n", pg); panic("uvm_page_own"); } pg->owner_tag = NULL; return; } #endif /* * when VM_PHYSSEG_MAX is 1, we can simplify these functions */ #if VM_PHYSSEG_MAX > 1 /* * vm_physseg_find: find vm_physseg structure that belongs to a PA */ int vm_physseg_find(paddr_t pframe, int *offp) { struct vm_physseg *seg; #if (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH) /* binary search for it */ int start, len, try; /* * if try is too large (thus target is less than try) we reduce * the length to trunc(len/2) [i.e. everything smaller than "try"] * * if the try is too small (thus target is greater than try) then * we set the new start to be (try + 1). this means we need to * reduce the length to (round(len/2) - 1). * * note "adjust" below which takes advantage of the fact that * (round(len/2) - 1) == trunc((len - 1) / 2) * for any value of len we may have */ for (start = 0, len = vm_nphysseg ; len != 0 ; len = len / 2) { try = start + (len / 2); /* try in the middle */ seg = vm_physmem + try; /* start past our try? */ if (pframe >= seg->start) { /* was try correct? */ if (pframe < seg->end) { if (offp) *offp = pframe - seg->start; return try; /* got it */ } start = try + 1; /* next time, start here */ len--; /* "adjust" */ } else { /* * pframe before try, just reduce length of * region, done in "for" loop */ } } return -1; #else /* linear search for it */ int lcv; for (lcv = 0, seg = vm_physmem; lcv < vm_nphysseg ; lcv++, seg++) { if (pframe >= seg->start && pframe < seg->end) { if (offp) *offp = pframe - seg->start; return lcv; /* got it */ } } return -1; #endif } /* * PHYS_TO_VM_PAGE: find vm_page for a PA. used by MI code to get vm_pages * back from an I/O mapping (ugh!). used in some MD code as well. */ struct vm_page * PHYS_TO_VM_PAGE(paddr_t pa) { paddr_t pf = atop(pa); int off; int psi; psi = vm_physseg_find(pf, &off); return (psi == -1) ? NULL : &vm_physmem[psi].pgs[off]; } #endif /* VM_PHYSSEG_MAX > 1 */ /* * uvm_pagelookup: look up a page */ struct vm_page * uvm_pagelookup(struct uvm_object *obj, voff_t off) { /* XXX if stack is too much, handroll */ struct vm_page p, *pg; p.offset = off; pg = RBT_FIND(uvm_objtree, &obj->memt, &p); KASSERT(pg == NULL || obj->uo_npages != 0); KASSERT(pg == NULL || (pg->pg_flags & PG_RELEASED) == 0 || (pg->pg_flags & PG_BUSY) != 0); return (pg); } /* * uvm_pagewire: wire the page, thus removing it from the daemon's grasp * * => caller must lock page queues */ void uvm_pagewire(struct vm_page *pg) { KASSERT(uvm_page_owner_locked_p(pg)); MUTEX_ASSERT_LOCKED(&uvm.pageqlock); if (pg->wire_count == 0) { uvm_pagedequeue(pg); uvmexp.wired++; } pg->wire_count++; } /* * uvm_pageunwire: unwire the page. * * => activate if wire count goes to zero. * => caller must lock page queues */ void uvm_pageunwire(struct vm_page *pg) { KASSERT(uvm_page_owner_locked_p(pg)); MUTEX_ASSERT_LOCKED(&uvm.pageqlock); pg->wire_count--; if (pg->wire_count == 0) { uvm_pageactivate(pg); uvmexp.wired--; } } /* * uvm_pagedeactivate: deactivate page -- no pmaps have access to page * * => caller must lock page queues * => caller must check to make sure page is not wired * => object that page belongs to must be locked (so we can adjust pg->flags) */ void uvm_pagedeactivate(struct vm_page *pg) { KASSERT(uvm_page_owner_locked_p(pg)); MUTEX_ASSERT_LOCKED(&uvm.pageqlock); if (pg->pg_flags & PQ_ACTIVE) { TAILQ_REMOVE(&uvm.page_active, pg, pageq); atomic_clearbits_int(&pg->pg_flags, PQ_ACTIVE); uvmexp.active--; } if ((pg->pg_flags & PQ_INACTIVE) == 0) { KASSERT(pg->wire_count == 0); TAILQ_INSERT_TAIL(&uvm.page_inactive, pg, pageq); atomic_setbits_int(&pg->pg_flags, PQ_INACTIVE); uvmexp.inactive++; pmap_clear_reference(pg); /* * update the "clean" bit. this isn't 100% * accurate, and doesn't have to be. we'll * re-sync it after we zap all mappings when * scanning the inactive list. */ if ((pg->pg_flags & PG_CLEAN) != 0 && pmap_is_modified(pg)) atomic_clearbits_int(&pg->pg_flags, PG_CLEAN); } } /* * uvm_pageactivate: activate page * * => caller must lock page queues */ void uvm_pageactivate(struct vm_page *pg) { KASSERT(uvm_page_owner_locked_p(pg)); MUTEX_ASSERT_LOCKED(&uvm.pageqlock); uvm_pagedequeue(pg); if (pg->wire_count == 0) { TAILQ_INSERT_TAIL(&uvm.page_active, pg, pageq); atomic_setbits_int(&pg->pg_flags, PQ_ACTIVE); uvmexp.active++; } } /* * uvm_pagedequeue: remove a page from any paging queue */ void uvm_pagedequeue(struct vm_page *pg) { if (pg->pg_flags & PQ_ACTIVE) { TAILQ_REMOVE(&uvm.page_active, pg, pageq); atomic_clearbits_int(&pg->pg_flags, PQ_ACTIVE); uvmexp.active--; } if (pg->pg_flags & PQ_INACTIVE) { TAILQ_REMOVE(&uvm.page_inactive, pg, pageq); atomic_clearbits_int(&pg->pg_flags, PQ_INACTIVE); uvmexp.inactive--; } } /* * uvm_pagezero: zero fill a page */ void uvm_pagezero(struct vm_page *pg) { atomic_clearbits_int(&pg->pg_flags, PG_CLEAN); pmap_zero_page(pg); } /* * uvm_pagecopy: copy a page */ void uvm_pagecopy(struct vm_page *src, struct vm_page *dst) { atomic_clearbits_int(&dst->pg_flags, PG_CLEAN); pmap_copy_page(src, dst); } /* * uvm_page_owner_locked_p: return true if object associated with page is * locked. this is a weak check for runtime assertions only. */ int uvm_page_owner_locked_p(struct vm_page *pg) { if (pg->uobject != NULL) { if (UVM_OBJ_IS_DUMMY(pg->uobject)) return 1; return rw_write_held(pg->uobject->vmobjlock); } if (pg->uanon != NULL) { return rw_write_held(pg->uanon->an_lock); } return 1; } /* * uvm_pagecount: count the number of physical pages in the address range. */ psize_t uvm_pagecount(struct uvm_constraint_range* constraint) { int lcv; psize_t sz; paddr_t low, high; paddr_t ps_low, ps_high; /* Algorithm uses page numbers. */ low = atop(constraint->ucr_low); high = atop(constraint->ucr_high); sz = 0; for (lcv = 0; lcv < vm_nphysseg; lcv++) { ps_low = MAX(low, vm_physmem[lcv].avail_start); ps_high = MIN(high, vm_physmem[lcv].avail_end); if (ps_low < ps_high) sz += ps_high - ps_low; } return sz; }
5 2 1 2 1 1 3 2 1 4 3 1 2 2 4 4 4 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 /* $OpenBSD: vscsi.c,v 1.63 2024/05/13 01:15:50 jsg Exp $ */ /* * Copyright (c) 2008 David Gwynne <dlg@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/device.h> #include <sys/conf.h> #include <sys/queue.h> #include <sys/rwlock.h> #include <sys/pool.h> #include <sys/task.h> #include <sys/ioctl.h> #include <sys/event.h> #include <scsi/scsi_all.h> #include <scsi/scsiconf.h> #include <dev/vscsivar.h> /* * Locks used to protect struct members and global data * s sc_state_mtx */ int vscsi_match(struct device *, void *, void *); void vscsi_attach(struct device *, struct device *, void *); struct vscsi_ccb { TAILQ_ENTRY(vscsi_ccb) ccb_entry; int ccb_tag; struct scsi_xfer *ccb_xs; size_t ccb_datalen; }; TAILQ_HEAD(vscsi_ccb_list, vscsi_ccb); enum vscsi_state { VSCSI_S_CLOSED, VSCSI_S_CONFIG, VSCSI_S_RUNNING }; struct vscsi_softc { struct device sc_dev; struct scsibus_softc *sc_scsibus; struct mutex sc_state_mtx; enum vscsi_state sc_state; u_int sc_ref_count; struct pool sc_ccb_pool; struct scsi_iopool sc_iopool; struct vscsi_ccb_list sc_ccb_i2t; /* [s] */ struct vscsi_ccb_list sc_ccb_t2i; int sc_ccb_tag; struct mutex sc_poll_mtx; struct rwlock sc_ioc_lock; struct klist sc_klist; /* [s] */ }; #define DEVNAME(_s) ((_s)->sc_dev.dv_xname) #define DEV2SC(_d) ((struct vscsi_softc *)device_lookup(&vscsi_cd, minor(_d))) const struct cfattach vscsi_ca = { sizeof(struct vscsi_softc), vscsi_match, vscsi_attach }; struct cfdriver vscsi_cd = { NULL, "vscsi", DV_DULL }; void vscsi_cmd(struct scsi_xfer *); int vscsi_probe(struct scsi_link *); void vscsi_free(struct scsi_link *); const struct scsi_adapter vscsi_switch = { vscsi_cmd, NULL, vscsi_probe, vscsi_free, NULL }; int vscsi_i2t(struct vscsi_softc *, struct vscsi_ioc_i2t *); int vscsi_data(struct vscsi_softc *, struct vscsi_ioc_data *, int); int vscsi_t2i(struct vscsi_softc *, struct vscsi_ioc_t2i *); int vscsi_devevent(struct vscsi_softc *, u_long, struct vscsi_ioc_devevent *); void vscsi_devevent_task(void *); void vscsi_done(struct vscsi_softc *, struct vscsi_ccb *); void * vscsi_ccb_get(void *); void vscsi_ccb_put(void *, void *); void filt_vscsidetach(struct knote *); int filt_vscsiread(struct knote *, long); int filt_vscsimodify(struct kevent *, struct knote *); int filt_vscsiprocess(struct knote *, struct kevent *); const struct filterops vscsi_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_vscsidetach, .f_event = filt_vscsiread, .f_modify = filt_vscsimodify, .f_process = filt_vscsiprocess, }; int vscsi_match(struct device *parent, void *match, void *aux) { return (1); } void vscsi_attach(struct device *parent, struct device *self, void *aux) { struct vscsi_softc *sc = (struct vscsi_softc *)self; struct scsibus_attach_args saa; printf("\n"); mtx_init(&sc->sc_state_mtx, IPL_MPFLOOR); sc->sc_state = VSCSI_S_CLOSED; TAILQ_INIT(&sc->sc_ccb_i2t); TAILQ_INIT(&sc->sc_ccb_t2i); mtx_init(&sc->sc_poll_mtx, IPL_BIO); rw_init(&sc->sc_ioc_lock, "vscsiioc"); scsi_iopool_init(&sc->sc_iopool, sc, vscsi_ccb_get, vscsi_ccb_put); klist_init_mutex(&sc->sc_klist, &sc->sc_state_mtx); saa.saa_adapter = &vscsi_switch; saa.saa_adapter_softc = sc; saa.saa_adapter_target = SDEV_NO_ADAPTER_TARGET; saa.saa_adapter_buswidth = 256; saa.saa_luns = 8; saa.saa_openings = 16; saa.saa_pool = &sc->sc_iopool; saa.saa_quirks = saa.saa_flags = 0; saa.saa_wwpn = saa.saa_wwnn = 0; sc->sc_scsibus = (struct scsibus_softc *)config_found(&sc->sc_dev, &saa, scsiprint); } void vscsi_cmd(struct scsi_xfer *xs) { struct scsi_link *link = xs->sc_link; struct vscsi_softc *sc = link->bus->sb_adapter_softc; struct vscsi_ccb *ccb = xs->io; int polled = ISSET(xs->flags, SCSI_POLL); int running = 0; if (ISSET(xs->flags, SCSI_POLL) && ISSET(xs->flags, SCSI_NOSLEEP)) { printf("%s: POLL && NOSLEEP for 0x%02x\n", DEVNAME(sc), xs->cmd.opcode); xs->error = XS_DRIVER_STUFFUP; scsi_done(xs); return; } ccb->ccb_xs = xs; mtx_enter(&sc->sc_state_mtx); if (sc->sc_state == VSCSI_S_RUNNING) { running = 1; TAILQ_INSERT_TAIL(&sc->sc_ccb_i2t, ccb, ccb_entry); } knote_locked(&sc->sc_klist, 0); mtx_leave(&sc->sc_state_mtx); if (!running) { xs->error = XS_DRIVER_STUFFUP; scsi_done(xs); return; } if (polled) { mtx_enter(&sc->sc_poll_mtx); while (ccb->ccb_xs != NULL) msleep_nsec(ccb, &sc->sc_poll_mtx, PRIBIO, "vscsipoll", INFSLP); mtx_leave(&sc->sc_poll_mtx); scsi_done(xs); } } void vscsi_done(struct vscsi_softc *sc, struct vscsi_ccb *ccb) { struct scsi_xfer *xs = ccb->ccb_xs; if (ISSET(xs->flags, SCSI_POLL)) { mtx_enter(&sc->sc_poll_mtx); ccb->ccb_xs = NULL; wakeup(ccb); mtx_leave(&sc->sc_poll_mtx); } else scsi_done(xs); } int vscsi_probe(struct scsi_link *link) { struct vscsi_softc *sc = link->bus->sb_adapter_softc; int rv = 0; mtx_enter(&sc->sc_state_mtx); if (sc->sc_state == VSCSI_S_RUNNING) sc->sc_ref_count++; else rv = ENXIO; mtx_leave(&sc->sc_state_mtx); return (rv); } void vscsi_free(struct scsi_link *link) { struct vscsi_softc *sc = link->bus->sb_adapter_softc; mtx_enter(&sc->sc_state_mtx); sc->sc_ref_count--; if (sc->sc_state != VSCSI_S_RUNNING && sc->sc_ref_count == 0) wakeup(&sc->sc_ref_count); mtx_leave(&sc->sc_state_mtx); } int vscsiopen(dev_t dev, int flags, int mode, struct proc *p) { struct vscsi_softc *sc = DEV2SC(dev); enum vscsi_state state = VSCSI_S_RUNNING; int rv = 0; if (sc == NULL) return (ENXIO); mtx_enter(&sc->sc_state_mtx); if (sc->sc_state != VSCSI_S_CLOSED) rv = EBUSY; else sc->sc_state = VSCSI_S_CONFIG; mtx_leave(&sc->sc_state_mtx); if (rv != 0) { device_unref(&sc->sc_dev); return (rv); } pool_init(&sc->sc_ccb_pool, sizeof(struct vscsi_ccb), 0, IPL_BIO, 0, "vscsiccb", NULL); /* we need to guarantee some ccbs will be available for the iopool */ rv = pool_prime(&sc->sc_ccb_pool, 8); if (rv != 0) { pool_destroy(&sc->sc_ccb_pool); state = VSCSI_S_CLOSED; } /* commit changes */ mtx_enter(&sc->sc_state_mtx); sc->sc_state = state; mtx_leave(&sc->sc_state_mtx); device_unref(&sc->sc_dev); return (rv); } int vscsiioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) { struct vscsi_softc *sc = DEV2SC(dev); int read = 0; int err = 0; if (sc == NULL) return (ENXIO); rw_enter_write(&sc->sc_ioc_lock); switch (cmd) { case VSCSI_I2T: err = vscsi_i2t(sc, (struct vscsi_ioc_i2t *)addr); break; case VSCSI_DATA_READ: read = 1; case VSCSI_DATA_WRITE: err = vscsi_data(sc, (struct vscsi_ioc_data *)addr, read); break; case VSCSI_T2I: err = vscsi_t2i(sc, (struct vscsi_ioc_t2i *)addr); break; case VSCSI_REQPROBE: case VSCSI_REQDETACH: err = vscsi_devevent(sc, cmd, (struct vscsi_ioc_devevent *)addr); break; default: err = ENOTTY; break; } rw_exit_write(&sc->sc_ioc_lock); device_unref(&sc->sc_dev); return (err); } int vscsi_i2t(struct vscsi_softc *sc, struct vscsi_ioc_i2t *i2t) { struct vscsi_ccb *ccb; struct scsi_xfer *xs; struct scsi_link *link; mtx_enter(&sc->sc_state_mtx); ccb = TAILQ_FIRST(&sc->sc_ccb_i2t); if (ccb != NULL) TAILQ_REMOVE(&sc->sc_ccb_i2t, ccb, ccb_entry); mtx_leave(&sc->sc_state_mtx); if (ccb == NULL) return (EAGAIN); xs = ccb->ccb_xs; link = xs->sc_link; i2t->tag = ccb->ccb_tag; i2t->target = link->target; i2t->lun = link->lun; memcpy(&i2t->cmd, &xs->cmd, xs->cmdlen); i2t->cmdlen = xs->cmdlen; i2t->datalen = xs->datalen; switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) { case SCSI_DATA_IN: i2t->direction = VSCSI_DIR_READ; break; case SCSI_DATA_OUT: i2t->direction = VSCSI_DIR_WRITE; break; default: i2t->direction = VSCSI_DIR_NONE; break; } TAILQ_INSERT_TAIL(&sc->sc_ccb_t2i, ccb, ccb_entry); return (0); } int vscsi_data(struct vscsi_softc *sc, struct vscsi_ioc_data *data, int read) { struct vscsi_ccb *ccb; struct scsi_xfer *xs; int xsread; u_int8_t *buf; int rv = EINVAL; TAILQ_FOREACH(ccb, &sc->sc_ccb_t2i, ccb_entry) { if (ccb->ccb_tag == data->tag) break; } if (ccb == NULL) return (EFAULT); xs = ccb->ccb_xs; if (data->datalen > xs->datalen - ccb->ccb_datalen) return (ENOMEM); switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) { case SCSI_DATA_IN: xsread = 1; break; case SCSI_DATA_OUT: xsread = 0; break; default: return (EINVAL); } if (read != xsread) return (EINVAL); buf = xs->data; buf += ccb->ccb_datalen; if (read) rv = copyin(data->data, buf, data->datalen); else rv = copyout(buf, data->data, data->datalen); if (rv == 0) ccb->ccb_datalen += data->datalen; return (rv); } int vscsi_t2i(struct vscsi_softc *sc, struct vscsi_ioc_t2i *t2i) { struct vscsi_ccb *ccb; struct scsi_xfer *xs; int rv = 0; TAILQ_FOREACH(ccb, &sc->sc_ccb_t2i, ccb_entry) { if (ccb->ccb_tag == t2i->tag) break; } if (ccb == NULL) return (EFAULT); TAILQ_REMOVE(&sc->sc_ccb_t2i, ccb, ccb_entry); xs = ccb->ccb_xs; xs->resid = xs->datalen - ccb->ccb_datalen; xs->status = SCSI_OK; switch (t2i->status) { case VSCSI_STAT_DONE: xs->error = XS_NOERROR; break; case VSCSI_STAT_SENSE: xs->error = XS_SENSE; memcpy(&xs->sense, &t2i->sense, sizeof(xs->sense)); break; case VSCSI_STAT_RESET: xs->error = XS_RESET; break; case VSCSI_STAT_ERR: default: xs->error = XS_DRIVER_STUFFUP; break; } vscsi_done(sc, ccb); return (rv); } struct vscsi_devevent_task { struct vscsi_softc *sc; struct task t; struct vscsi_ioc_devevent de; u_long cmd; }; int vscsi_devevent(struct vscsi_softc *sc, u_long cmd, struct vscsi_ioc_devevent *de) { struct vscsi_devevent_task *dt; dt = malloc(sizeof(*dt), M_TEMP, M_WAITOK | M_CANFAIL); if (dt == NULL) return (ENOMEM); task_set(&dt->t, vscsi_devevent_task, dt); dt->sc = sc; dt->de = *de; dt->cmd = cmd; device_ref(&sc->sc_dev); task_add(systq, &dt->t); return (0); } void vscsi_devevent_task(void *xdt) { struct vscsi_devevent_task *dt = xdt; struct vscsi_softc *sc = dt->sc; int state; mtx_enter(&sc->sc_state_mtx); state = sc->sc_state; mtx_leave(&sc->sc_state_mtx); if (state != VSCSI_S_RUNNING) goto gone; switch (dt->cmd) { case VSCSI_REQPROBE: scsi_probe(sc->sc_scsibus, dt->de.target, dt->de.lun); break; case VSCSI_REQDETACH: scsi_detach(sc->sc_scsibus, dt->de.target, dt->de.lun, DETACH_FORCE); break; #ifdef DIAGNOSTIC default: panic("unexpected vscsi_devevent cmd"); /* NOTREACHED */ #endif } gone: device_unref(&sc->sc_dev); free(dt, M_TEMP, sizeof(*dt)); } int vscsikqfilter(dev_t dev, struct knote *kn) { struct vscsi_softc *sc = DEV2SC(dev); if (sc == NULL) return (ENXIO); switch (kn->kn_filter) { case EVFILT_READ: kn->kn_fop = &vscsi_filtops; break; default: device_unref(&sc->sc_dev); return (EINVAL); } kn->kn_hook = sc; klist_insert(&sc->sc_klist, kn); /* device ref is given to the knote in the klist */ return (0); } void filt_vscsidetach(struct knote *kn) { struct vscsi_softc *sc = kn->kn_hook; klist_remove(&sc->sc_klist, kn); device_unref(&sc->sc_dev); } int filt_vscsiread(struct knote *kn, long hint) { struct vscsi_softc *sc = kn->kn_hook; return (!TAILQ_EMPTY(&sc->sc_ccb_i2t)); } int filt_vscsimodify(struct kevent *kev, struct knote *kn) { struct vscsi_softc *sc = kn->kn_hook; int active; mtx_enter(&sc->sc_state_mtx); active = knote_modify(kev, kn); mtx_leave(&sc->sc_state_mtx); return (active); } int filt_vscsiprocess(struct knote *kn, struct kevent *kev) { struct vscsi_softc *sc = kn->kn_hook; int active; mtx_enter(&sc->sc_state_mtx); active = knote_process(kn, kev); mtx_leave(&sc->sc_state_mtx); return (active); } int vscsiclose(dev_t dev, int flags, int mode, struct proc *p) { struct vscsi_softc *sc = DEV2SC(dev); struct vscsi_ccb *ccb; if (sc == NULL) return (ENXIO); mtx_enter(&sc->sc_state_mtx); KASSERT(sc->sc_state == VSCSI_S_RUNNING); sc->sc_state = VSCSI_S_CONFIG; mtx_leave(&sc->sc_state_mtx); scsi_activate(sc->sc_scsibus, -1, -1, DVACT_DEACTIVATE); while ((ccb = TAILQ_FIRST(&sc->sc_ccb_t2i)) != NULL) { TAILQ_REMOVE(&sc->sc_ccb_t2i, ccb, ccb_entry); ccb->ccb_xs->error = XS_RESET; vscsi_done(sc, ccb); } while ((ccb = TAILQ_FIRST(&sc->sc_ccb_i2t)) != NULL) { TAILQ_REMOVE(&sc->sc_ccb_i2t, ccb, ccb_entry); ccb->ccb_xs->error = XS_RESET; vscsi_done(sc, ccb); } scsi_req_detach(sc->sc_scsibus, -1, -1, DETACH_FORCE); mtx_enter(&sc->sc_state_mtx); while (sc->sc_ref_count > 0) { msleep_nsec(&sc->sc_ref_count, &sc->sc_state_mtx, PRIBIO, "vscsiref", INFSLP); } mtx_leave(&sc->sc_state_mtx); pool_destroy(&sc->sc_ccb_pool); mtx_enter(&sc->sc_state_mtx); sc->sc_state = VSCSI_S_CLOSED; mtx_leave(&sc->sc_state_mtx); device_unref(&sc->sc_dev); return (0); } void * vscsi_ccb_get(void *cookie) { struct vscsi_softc *sc = cookie; struct vscsi_ccb *ccb = NULL; ccb = pool_get(&sc->sc_ccb_pool, PR_NOWAIT); if (ccb != NULL) { ccb->ccb_tag = sc->sc_ccb_tag++; ccb->ccb_datalen = 0; } return (ccb); } void vscsi_ccb_put(void *cookie, void *io) { struct vscsi_softc *sc = cookie; struct vscsi_ccb *ccb = io; pool_put(&sc->sc_ccb_pool, ccb); }
609 4 57 4 557 578 70 160 5 593 89 524 15 100 1 99 115 4 112 110 263 10 203 3 52 246 19 184 77 236 5 15 248 1348 1 1344 416 5 411 389 1795 9 1744 3 52 1771 106 1537 165 85 1739 16 90 1760 1248 13 846 1 1118 126 1105 112 1 64 6 5 5 6 1228 1060 211 1236 116 97 2 9 7 2 15 112 1 91 22 110 109 106 95 16 16 16 105 69 4 9 2 24 18 28 28 27 27 26 6 6 6 20 91 105 66 68 100 91 18 87 39 69 21 1 11 7 2 20 350 91 103 2 1 103 1 79 25 2 100 1 6 9 2 79 51 85 6 9 85 94 10 77 24 88 88 18 83 13 2 1 100 99 33 89 62 68 55 51 86 15 98 50 50 14 9 21 6 22 11 1 49 50 50 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 /* $OpenBSD: sys_generic.c,v 1.157 2024/04/10 10:05:26 claudio Exp $ */ /* $NetBSD: sys_generic.c,v 1.24 1996/03/29 00:25:32 cgd Exp $ */ /* * Copyright (c) 1996 Theo de Raadt * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)sys_generic.c 8.5 (Berkeley) 1/21/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/filedesc.h> #include <sys/ioctl.h> #include <sys/fcntl.h> #include <sys/vnode.h> #include <sys/file.h> #include <sys/proc.h> #include <sys/resourcevar.h> #include <sys/socketvar.h> #include <sys/signalvar.h> #include <sys/uio.h> #include <sys/time.h> #include <sys/malloc.h> #include <sys/poll.h> #include <sys/eventvar.h> #ifdef KTRACE #include <sys/ktrace.h> #endif #include <sys/pledge.h> #include <sys/mount.h> #include <sys/syscallargs.h> /* * Debug values: * 1 - print implementation errors, things that should not happen. * 2 - print ppoll(2) information, somewhat verbose * 3 - print pselect(2) and ppoll(2) information, very verbose */ int kqpoll_debug = 0; #define DPRINTFN(v, x...) if (kqpoll_debug > v) { \ printf("%s(%d): ", curproc->p_p->ps_comm, curproc->p_tid); \ printf(x); \ } int pselregister(struct proc *, fd_set **, fd_set **, int, int *, int *); int pselcollect(struct proc *, struct kevent *, fd_set **, int *); void ppollregister(struct proc *, struct pollfd *, int, int *, int *); int ppollcollect(struct proc *, struct kevent *, struct pollfd *, u_int); int pollout(struct pollfd *, struct pollfd *, u_int); int dopselect(struct proc *, int, fd_set *, fd_set *, fd_set *, struct timespec *, const sigset_t *, register_t *); int doppoll(struct proc *, struct pollfd *, u_int, struct timespec *, const sigset_t *, register_t *); int iovec_copyin(const struct iovec *uiov, struct iovec **iovp, struct iovec *aiov, unsigned int iovcnt, size_t *residp) { #ifdef KTRACE struct proc *p = curproc; #endif struct iovec *iov; int error, i; size_t resid = 0; if (iovcnt > UIO_SMALLIOV) { if (iovcnt > IOV_MAX) return (EINVAL); iov = mallocarray(iovcnt, sizeof(*iov), M_IOV, M_WAITOK); } else if (iovcnt > 0) { iov = aiov; } else { return (EINVAL); } *iovp = iov; if ((error = copyin(uiov, iov, iovcnt * sizeof(*iov)))) return (error); #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktriovec(p, iov, iovcnt); #endif for (i = 0; i < iovcnt; i++) { resid += iov->iov_len; /* * Writes return ssize_t because -1 is returned on error. * Therefore we must restrict the length to SSIZE_MAX to * avoid garbage return values. Note that the addition is * guaranteed to not wrap because SSIZE_MAX * 2 < SIZE_MAX. */ if (iov->iov_len > SSIZE_MAX || resid > SSIZE_MAX) return (EINVAL); iov++; } if (residp != NULL) *residp = resid; return (0); } void iovec_free(struct iovec *iov, unsigned int iovcnt) { if (iovcnt > UIO_SMALLIOV) free(iov, M_IOV, iovcnt * sizeof(*iov)); } /* * Read system call. */ int sys_read(struct proc *p, void *v, register_t *retval) { struct sys_read_args /* { syscallarg(int) fd; syscallarg(void *) buf; syscallarg(size_t) nbyte; } */ *uap = v; struct iovec iov; struct uio auio; iov.iov_base = SCARG(uap, buf); iov.iov_len = SCARG(uap, nbyte); if (iov.iov_len > SSIZE_MAX) return (EINVAL); auio.uio_iov = &iov; auio.uio_iovcnt = 1; auio.uio_resid = iov.iov_len; return (dofilereadv(p, SCARG(uap, fd), &auio, 0, retval)); } /* * Scatter read system call. */ int sys_readv(struct proc *p, void *v, register_t *retval) { struct sys_readv_args /* { syscallarg(int) fd; syscallarg(const struct iovec *) iovp; syscallarg(int) iovcnt; } */ *uap = v; struct iovec aiov[UIO_SMALLIOV], *iov = NULL; int error, iovcnt = SCARG(uap, iovcnt); struct uio auio; size_t resid; error = iovec_copyin(SCARG(uap, iovp), &iov, aiov, iovcnt, &resid); if (error) goto done; auio.uio_iov = iov; auio.uio_iovcnt = iovcnt; auio.uio_resid = resid; error = dofilereadv(p, SCARG(uap, fd), &auio, 0, retval); done: iovec_free(iov, iovcnt); return (error); } int dofilereadv(struct proc *p, int fd, struct uio *uio, int flags, register_t *retval) { struct filedesc *fdp = p->p_fd; struct file *fp; long cnt, error = 0; u_int iovlen; #ifdef KTRACE struct iovec *ktriov = NULL; #endif KASSERT(uio->uio_iov != NULL && uio->uio_iovcnt > 0); iovlen = uio->uio_iovcnt * sizeof(struct iovec); if ((fp = fd_getfile_mode(fdp, fd, FREAD)) == NULL) return (EBADF); /* Checks for positioned read. */ if (flags & FO_POSITION) { struct vnode *vp = fp->f_data; if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO || (vp->v_flag & VISTTY)) { error = ESPIPE; goto done; } if (uio->uio_offset < 0 && vp->v_type != VCHR) { error = EINVAL; goto done; } } uio->uio_rw = UIO_READ; uio->uio_segflg = UIO_USERSPACE; uio->uio_procp = p; #ifdef KTRACE /* * if tracing, save a copy of iovec */ if (KTRPOINT(p, KTR_GENIO)) { ktriov = malloc(iovlen, M_TEMP, M_WAITOK); memcpy(ktriov, uio->uio_iov, iovlen); } #endif cnt = uio->uio_resid; error = (*fp->f_ops->fo_read)(fp, uio, flags); if (error) { if (uio->uio_resid != cnt && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; } cnt -= uio->uio_resid; mtx_enter(&fp->f_mtx); fp->f_rxfer++; fp->f_rbytes += cnt; mtx_leave(&fp->f_mtx); #ifdef KTRACE if (ktriov != NULL) { if (error == 0) ktrgenio(p, fd, UIO_READ, ktriov, cnt); free(ktriov, M_TEMP, iovlen); } #endif *retval = cnt; done: FRELE(fp, p); return (error); } /* * Write system call */ int sys_write(struct proc *p, void *v, register_t *retval) { struct sys_write_args /* { syscallarg(int) fd; syscallarg(const void *) buf; syscallarg(size_t) nbyte; } */ *uap = v; struct iovec iov; struct uio auio; iov.iov_base = (void *)SCARG(uap, buf); iov.iov_len = SCARG(uap, nbyte); if (iov.iov_len > SSIZE_MAX) return (EINVAL); auio.uio_iov = &iov; auio.uio_iovcnt = 1; auio.uio_resid = iov.iov_len; return (dofilewritev(p, SCARG(uap, fd), &auio, 0, retval)); } /* * Gather write system call */ int sys_writev(struct proc *p, void *v, register_t *retval) { struct sys_writev_args /* { syscallarg(int) fd; syscallarg(const struct iovec *) iovp; syscallarg(int) iovcnt; } */ *uap = v; struct iovec aiov[UIO_SMALLIOV], *iov = NULL; int error, iovcnt = SCARG(uap, iovcnt); struct uio auio; size_t resid; error = iovec_copyin(SCARG(uap, iovp), &iov, aiov, iovcnt, &resid); if (error) goto done; auio.uio_iov = iov; auio.uio_iovcnt = iovcnt; auio.uio_resid = resid; error = dofilewritev(p, SCARG(uap, fd), &auio, 0, retval); done: iovec_free(iov, iovcnt); return (error); } int dofilewritev(struct proc *p, int fd, struct uio *uio, int flags, register_t *retval) { struct filedesc *fdp = p->p_fd; struct file *fp; long cnt, error = 0; u_int iovlen; #ifdef KTRACE struct iovec *ktriov = NULL; #endif KASSERT(uio->uio_iov != NULL && uio->uio_iovcnt > 0); iovlen = uio->uio_iovcnt * sizeof(struct iovec); if ((fp = fd_getfile_mode(fdp, fd, FWRITE)) == NULL) return (EBADF); /* Checks for positioned write. */ if (flags & FO_POSITION) { struct vnode *vp = fp->f_data; if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO || (vp->v_flag & VISTTY)) { error = ESPIPE; goto done; } if (uio->uio_offset < 0 && vp->v_type != VCHR) { error = EINVAL; goto done; } } uio->uio_rw = UIO_WRITE; uio->uio_segflg = UIO_USERSPACE; uio->uio_procp = p; #ifdef KTRACE /* * if tracing, save a copy of iovec */ if (KTRPOINT(p, KTR_GENIO)) { ktriov = malloc(iovlen, M_TEMP, M_WAITOK); memcpy(ktriov, uio->uio_iov, iovlen); } #endif cnt = uio->uio_resid; error = (*fp->f_ops->fo_write)(fp, uio, flags); if (error) { if (uio->uio_resid != cnt && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; if (error == EPIPE) { KERNEL_LOCK(); ptsignal(p, SIGPIPE, STHREAD); KERNEL_UNLOCK(); } } cnt -= uio->uio_resid; mtx_enter(&fp->f_mtx); fp->f_wxfer++; fp->f_wbytes += cnt; mtx_leave(&fp->f_mtx); #ifdef KTRACE if (ktriov != NULL) { if (error == 0) ktrgenio(p, fd, UIO_WRITE, ktriov, cnt); free(ktriov, M_TEMP, iovlen); } #endif *retval = cnt; done: FRELE(fp, p); return (error); } /* * Ioctl system call */ int sys_ioctl(struct proc *p, void *v, register_t *retval) { struct sys_ioctl_args /* { syscallarg(int) fd; syscallarg(u_long) com; syscallarg(void *) data; } */ *uap = v; struct file *fp; struct filedesc *fdp = p->p_fd; u_long com = SCARG(uap, com); int error = 0; u_int size = 0; caddr_t data, memp = NULL; int tmp; #define STK_PARAMS 128 long long stkbuf[STK_PARAMS / sizeof(long long)]; if ((fp = fd_getfile_mode(fdp, SCARG(uap, fd), FREAD|FWRITE)) == NULL) return (EBADF); if (fp->f_type == DTYPE_SOCKET) { struct socket *so = fp->f_data; if (so->so_state & SS_DNS) { error = EINVAL; goto out; } } error = pledge_ioctl(p, com, fp); if (error) goto out; switch (com) { case FIONCLEX: case FIOCLEX: fdplock(fdp); if (com == FIONCLEX) fdp->fd_ofileflags[SCARG(uap, fd)] &= ~UF_EXCLOSE; else fdp->fd_ofileflags[SCARG(uap, fd)] |= UF_EXCLOSE; fdpunlock(fdp); goto out; } /* * Interpret high order word to find amount of data to be * copied to/from the user's address space. */ size = IOCPARM_LEN(com); if (size > IOCPARM_MAX) { error = ENOTTY; goto out; } if (size > sizeof (stkbuf)) { memp = malloc(size, M_IOCTLOPS, M_WAITOK); data = memp; } else data = (caddr_t)stkbuf; if (com&IOC_IN) { if (size) { error = copyin(SCARG(uap, data), data, size); if (error) { goto out; } } else *(caddr_t *)data = SCARG(uap, data); } else if ((com&IOC_OUT) && size) /* * Zero the buffer so the user always * gets back something deterministic. */ memset(data, 0, size); else if (com&IOC_VOID) *(caddr_t *)data = SCARG(uap, data); switch (com) { case FIONBIO: if ((tmp = *(int *)data) != 0) atomic_setbits_int(&fp->f_flag, FNONBLOCK); else atomic_clearbits_int(&fp->f_flag, FNONBLOCK); error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); break; case FIOASYNC: if ((tmp = *(int *)data) != 0) atomic_setbits_int(&fp->f_flag, FASYNC); else atomic_clearbits_int(&fp->f_flag, FASYNC); error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p); break; default: error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); break; } /* * Copy any data to user, size was * already set and checked above. */ if (error == 0 && (com&IOC_OUT) && size) error = copyout(data, SCARG(uap, data), size); out: FRELE(fp, p); free(memp, M_IOCTLOPS, size); return (error); } /* * Select system call. */ int sys_select(struct proc *p, void *v, register_t *retval) { struct sys_select_args /* { syscallarg(int) nd; syscallarg(fd_set *) in; syscallarg(fd_set *) ou; syscallarg(fd_set *) ex; syscallarg(struct timeval *) tv; } */ *uap = v; struct timespec ts, *tsp = NULL; int error; if (SCARG(uap, tv) != NULL) { struct timeval tv; if ((error = copyin(SCARG(uap, tv), &tv, sizeof tv)) != 0) return (error); #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrreltimeval(p, &tv); #endif if (tv.tv_sec < 0 || !timerisvalid(&tv)) return (EINVAL); TIMEVAL_TO_TIMESPEC(&tv, &ts); tsp = &ts; } return (dopselect(p, SCARG(uap, nd), SCARG(uap, in), SCARG(uap, ou), SCARG(uap, ex), tsp, NULL, retval)); } int sys_pselect(struct proc *p, void *v, register_t *retval) { struct sys_pselect_args /* { syscallarg(int) nd; syscallarg(fd_set *) in; syscallarg(fd_set *) ou; syscallarg(fd_set *) ex; syscallarg(const struct timespec *) ts; syscallarg(const sigset_t *) mask; } */ *uap = v; struct timespec ts, *tsp = NULL; sigset_t ss, *ssp = NULL; int error; if (SCARG(uap, ts) != NULL) { if ((error = copyin(SCARG(uap, ts), &ts, sizeof ts)) != 0) return (error); #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrreltimespec(p, &ts); #endif if (ts.tv_sec < 0 || !timespecisvalid(&ts)) return (EINVAL); tsp = &ts; } if (SCARG(uap, mask) != NULL) { if ((error = copyin(SCARG(uap, mask), &ss, sizeof ss)) != 0) return (error); ssp = &ss; } return (dopselect(p, SCARG(uap, nd), SCARG(uap, in), SCARG(uap, ou), SCARG(uap, ex), tsp, ssp, retval)); } int dopselect(struct proc *p, int nd, fd_set *in, fd_set *ou, fd_set *ex, struct timespec *timeout, const sigset_t *sigmask, register_t *retval) { struct kqueue_scan_state scan; struct timespec zerots = {}; fd_mask bits[6]; fd_set *pibits[3], *pobits[3]; int error, nfiles, ncollected = 0, nevents = 0; u_int ni; if (nd < 0) return (EINVAL); nfiles = READ_ONCE(p->p_fd->fd_nfiles); if (nd > nfiles) nd = nfiles; ni = howmany(nd, NFDBITS) * sizeof(fd_mask); if (ni > sizeof(bits[0])) { caddr_t mbits; mbits = mallocarray(6, ni, M_TEMP, M_WAITOK|M_ZERO); pibits[0] = (fd_set *)&mbits[ni * 0]; pibits[1] = (fd_set *)&mbits[ni * 1]; pibits[2] = (fd_set *)&mbits[ni * 2]; pobits[0] = (fd_set *)&mbits[ni * 3]; pobits[1] = (fd_set *)&mbits[ni * 4]; pobits[2] = (fd_set *)&mbits[ni * 5]; } else { memset(bits, 0, sizeof(bits)); pibits[0] = (fd_set *)&bits[0]; pibits[1] = (fd_set *)&bits[1]; pibits[2] = (fd_set *)&bits[2]; pobits[0] = (fd_set *)&bits[3]; pobits[1] = (fd_set *)&bits[4]; pobits[2] = (fd_set *)&bits[5]; } kqpoll_init(nd); #define getbits(name, x) \ if (name && (error = copyin(name, pibits[x], ni))) \ goto done; getbits(in, 0); getbits(ou, 1); getbits(ex, 2); #undef getbits #ifdef KTRACE if (ni > 0 && KTRPOINT(p, KTR_STRUCT)) { if (in) ktrfdset(p, pibits[0], ni); if (ou) ktrfdset(p, pibits[1], ni); if (ex) ktrfdset(p, pibits[2], ni); } #endif if (sigmask) dosigsuspend(p, *sigmask &~ sigcantmask); /* Register kqueue events */ error = pselregister(p, pibits, pobits, nd, &nevents, &ncollected); if (error != 0) goto done; /* * The poll/select family of syscalls has been designed to * block when file descriptors are not available, even if * there's nothing to wait for. */ if (nevents == 0 && ncollected == 0) { uint64_t nsecs = INFSLP; if (timeout != NULL) { if (!timespecisset(timeout)) goto done; nsecs = MAX(1, MIN(TIMESPEC_TO_NSEC(timeout), MAXTSLP)); } error = tsleep_nsec(&nowake, PSOCK | PCATCH, "kqsel", nsecs); /* select is not restarted after signals... */ if (error == ERESTART) error = EINTR; if (error == EWOULDBLOCK) error = 0; goto done; } /* Do not block if registering found pending events. */ if (ncollected > 0) timeout = &zerots; /* Collect at most `nevents' possibly waiting in kqueue_scan() */ kqueue_scan_setup(&scan, p->p_kq); while (nevents > 0) { struct kevent kev[KQ_NEVENTS]; int i, ready, count; /* Maximum number of events per iteration */ count = MIN(nitems(kev), nevents); ready = kqueue_scan(&scan, count, kev, timeout, p, &error); /* Convert back events that are ready. */ for (i = 0; i < ready && error == 0; i++) error = pselcollect(p, &kev[i], pobits, &ncollected); /* * Stop if there was an error or if we had enough * space to collect all events that were ready. */ if (error || ready < count) break; nevents -= ready; } kqueue_scan_finish(&scan); *retval = ncollected; done: #define putbits(name, x) \ if (name && (error2 = copyout(pobits[x], name, ni))) \ error = error2; if (error == 0) { int error2; putbits(in, 0); putbits(ou, 1); putbits(ex, 2); #undef putbits #ifdef KTRACE if (ni > 0 && KTRPOINT(p, KTR_STRUCT)) { if (in) ktrfdset(p, pobits[0], ni); if (ou) ktrfdset(p, pobits[1], ni); if (ex) ktrfdset(p, pobits[2], ni); } #endif } if (pibits[0] != (fd_set *)&bits[0]) free(pibits[0], M_TEMP, 6 * ni); kqpoll_done(nd); return (error); } /* * Convert fd_set into kqueue events and register them on the * per-thread queue. */ int pselregister(struct proc *p, fd_set *pibits[3], fd_set *pobits[3], int nfd, int *nregistered, int *ncollected) { static const int evf[] = { EVFILT_READ, EVFILT_WRITE, EVFILT_EXCEPT }; static const int evff[] = { 0, 0, NOTE_OOB }; int msk, i, j, fd, nevents = 0, error = 0; struct kevent kev; fd_mask bits; for (msk = 0; msk < 3; msk++) { for (i = 0; i < nfd; i += NFDBITS) { bits = pibits[msk]->fds_bits[i / NFDBITS]; while ((j = ffs(bits)) && (fd = i + --j) < nfd) { bits &= ~(1 << j); DPRINTFN(2, "select fd %d mask %d serial %lu\n", fd, msk, p->p_kq_serial); EV_SET(&kev, fd, evf[msk], EV_ADD|EV_ENABLE|__EV_SELECT, evff[msk], 0, (void *)(p->p_kq_serial)); error = kqueue_register(p->p_kq, &kev, 0, p); switch (error) { case 0: nevents++; /* FALLTHROUGH */ case EOPNOTSUPP:/* No underlying kqfilter */ case EINVAL: /* Unimplemented filter */ case EPERM: /* Specific to FIFO and * __EV_SELECT */ error = 0; break; case ENXIO: /* Device has been detached */ default: goto bad; } } } } *nregistered = nevents; return (0); bad: DPRINTFN(0, "select fd %u filt %d error %d\n", (int)kev.ident, kev.filter, error); return (error); } /* * Convert given kqueue event into corresponding select(2) bit. */ int pselcollect(struct proc *p, struct kevent *kevp, fd_set *pobits[3], int *ncollected) { if ((unsigned long)kevp->udata != p->p_kq_serial) { panic("%s: spurious kevp %p fd %d udata 0x%lx serial 0x%lx", __func__, kevp, (int)kevp->ident, (unsigned long)kevp->udata, p->p_kq_serial); } if (kevp->flags & EV_ERROR) { DPRINTFN(2, "select fd %d filt %d error %d\n", (int)kevp->ident, kevp->filter, (int)kevp->data); return (kevp->data); } switch (kevp->filter) { case EVFILT_READ: FD_SET(kevp->ident, pobits[0]); break; case EVFILT_WRITE: FD_SET(kevp->ident, pobits[1]); break; case EVFILT_EXCEPT: FD_SET(kevp->ident, pobits[2]); break; default: KASSERT(0); } (*ncollected)++; DPRINTFN(2, "select fd %d filt %d\n", (int)kevp->ident, kevp->filter); return (0); } /* * Do a wakeup when a selectable event occurs. */ void selwakeup(struct selinfo *sip) { KERNEL_LOCK(); knote_locked(&sip->si_note, NOTE_SUBMIT); KERNEL_UNLOCK(); } /* * Only copyout the revents field. */ int pollout(struct pollfd *pl, struct pollfd *upl, u_int nfds) { int error = 0; u_int i = 0; while (!error && i++ < nfds) { error = copyout(&pl->revents, &upl->revents, sizeof(upl->revents)); pl++; upl++; } return (error); } /* * We are using the same mechanism as select only we encode/decode args * differently. */ int sys_poll(struct proc *p, void *v, register_t *retval) { struct sys_poll_args /* { syscallarg(struct pollfd *) fds; syscallarg(u_int) nfds; syscallarg(int) timeout; } */ *uap = v; struct timespec ts, *tsp = NULL; int msec = SCARG(uap, timeout); if (msec != INFTIM) { if (msec < 0) return (EINVAL); ts.tv_sec = msec / 1000; ts.tv_nsec = (msec - (ts.tv_sec * 1000)) * 1000000; tsp = &ts; } return (doppoll(p, SCARG(uap, fds), SCARG(uap, nfds), tsp, NULL, retval)); } int sys_ppoll(struct proc *p, void *v, register_t *retval) { struct sys_ppoll_args /* { syscallarg(struct pollfd *) fds; syscallarg(u_int) nfds; syscallarg(const struct timespec *) ts; syscallarg(const sigset_t *) mask; } */ *uap = v; int error; struct timespec ts, *tsp = NULL; sigset_t ss, *ssp = NULL; if (SCARG(uap, ts) != NULL) { if ((error = copyin(SCARG(uap, ts), &ts, sizeof ts)) != 0) return (error); #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrreltimespec(p, &ts); #endif if (ts.tv_sec < 0 || !timespecisvalid(&ts)) return (EINVAL); tsp = &ts; } if (SCARG(uap, mask) != NULL) { if ((error = copyin(SCARG(uap, mask), &ss, sizeof ss)) != 0) return (error); ssp = &ss; } return (doppoll(p, SCARG(uap, fds), SCARG(uap, nfds), tsp, ssp, retval)); } int doppoll(struct proc *p, struct pollfd *fds, u_int nfds, struct timespec *timeout, const sigset_t *sigmask, register_t *retval) { struct kqueue_scan_state scan; struct timespec zerots = {}; struct pollfd pfds[4], *pl = pfds; int error, ncollected = 0, nevents = 0; size_t sz; /* Standards say no more than MAX_OPEN; this is possibly better. */ if (nfds > min((int)lim_cur(RLIMIT_NOFILE), maxfiles)) return (EINVAL); /* optimize for the default case, of a small nfds value */ if (nfds > nitems(pfds)) { pl = mallocarray(nfds, sizeof(*pl), M_TEMP, M_WAITOK | M_CANFAIL); if (pl == NULL) return (EINVAL); } kqpoll_init(nfds); sz = nfds * sizeof(*pl); if ((error = copyin(fds, pl, sz)) != 0) goto bad; if (sigmask) dosigsuspend(p, *sigmask &~ sigcantmask); /* Register kqueue events */ ppollregister(p, pl, nfds, &nevents, &ncollected); /* * The poll/select family of syscalls has been designed to * block when file descriptors are not available, even if * there's nothing to wait for. */ if (nevents == 0 && ncollected == 0) { uint64_t nsecs = INFSLP; if (timeout != NULL) { if (!timespecisset(timeout)) goto done; nsecs = MAX(1, MIN(TIMESPEC_TO_NSEC(timeout), MAXTSLP)); } error = tsleep_nsec(&nowake, PSOCK | PCATCH, "kqpoll", nsecs); if (error == ERESTART) error = EINTR; if (error == EWOULDBLOCK) error = 0; goto done; } /* Do not block if registering found pending events. */ if (ncollected > 0) timeout = &zerots; /* Collect at most `nevents' possibly waiting in kqueue_scan() */ kqueue_scan_setup(&scan, p->p_kq); while (nevents > 0) { struct kevent kev[KQ_NEVENTS]; int i, ready, count; /* Maximum number of events per iteration */ count = MIN(nitems(kev), nevents); ready = kqueue_scan(&scan, count, kev, timeout, p, &error); /* Convert back events that are ready. */ for (i = 0; i < ready; i++) ncollected += ppollcollect(p, &kev[i], pl, nfds); /* * Stop if there was an error or if we had enough * place to collect all events that were ready. */ if (error || ready < count) break; nevents -= ready; } kqueue_scan_finish(&scan); *retval = ncollected; done: /* * NOTE: poll(2) is not restarted after a signal and EWOULDBLOCK is * ignored (since the whole point is to see what would block). */ switch (error) { case EINTR: error = pollout(pl, fds, nfds); if (error == 0) error = EINTR; break; case EWOULDBLOCK: case 0: error = pollout(pl, fds, nfds); break; } #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrpollfd(p, pl, nfds); #endif /* KTRACE */ bad: if (pl != pfds) free(pl, M_TEMP, sz); kqpoll_done(nfds); return (error); } int ppollregister_evts(struct proc *p, struct kevent *kevp, int nkev, struct pollfd *pl, unsigned int pollid) { int i, error, nevents = 0; KASSERT(pl->revents == 0); for (i = 0; i < nkev; i++, kevp++) { again: error = kqueue_register(p->p_kq, kevp, pollid, p); switch (error) { case 0: nevents++; break; case EOPNOTSUPP:/* No underlying kqfilter */ case EINVAL: /* Unimplemented filter */ break; case EBADF: /* Bad file descriptor */ pl->revents |= POLLNVAL; break; case EPERM: /* Specific to FIFO */ KASSERT(kevp->filter == EVFILT_WRITE); if (nkev == 1) { /* * If this is the only filter make sure * POLLHUP is passed to userland. */ kevp->filter = EVFILT_EXCEPT; goto again; } break; default: DPRINTFN(0, "poll err %lu fd %d revents %02x serial" " %lu filt %d ERROR=%d\n", ((unsigned long)kevp->udata - p->p_kq_serial), pl->fd, pl->revents, p->p_kq_serial, kevp->filter, error); /* FALLTHROUGH */ case ENXIO: /* Device has been detached */ pl->revents |= POLLERR; break; } } return (nevents); } /* * Convert pollfd into kqueue events and register them on the * per-thread queue. * * At most 3 events can correspond to a single pollfd. */ void ppollregister(struct proc *p, struct pollfd *pl, int nfds, int *nregistered, int *ncollected) { int i, nkev, nevt, forcehup; struct kevent kev[3], *kevp; for (i = 0; i < nfds; i++) { pl[i].events &= ~POLL_NOHUP; pl[i].revents = 0; if (pl[i].fd < 0) continue; /* * POLLHUP checking is implicit in the event filters. * However, the checking must be even if no events are * requested. */ forcehup = ((pl[i].events & ~POLLHUP) == 0); DPRINTFN(1, "poll set %d/%d fd %d events %02x serial %lu\n", i+1, nfds, pl[i].fd, pl[i].events, p->p_kq_serial); nevt = 0; nkev = 0; kevp = kev; if (pl[i].events & (POLLIN | POLLRDNORM)) { EV_SET(kevp, pl[i].fd, EVFILT_READ, EV_ADD|EV_ENABLE|__EV_POLL, 0, 0, (void *)(p->p_kq_serial + i)); nkev++; kevp++; } if (pl[i].events & (POLLOUT | POLLWRNORM)) { EV_SET(kevp, pl[i].fd, EVFILT_WRITE, EV_ADD|EV_ENABLE|__EV_POLL, 0, 0, (void *)(p->p_kq_serial + i)); nkev++; kevp++; } if ((pl[i].events & (POLLPRI | POLLRDBAND)) || forcehup) { int evff = forcehup ? 0 : NOTE_OOB; EV_SET(kevp, pl[i].fd, EVFILT_EXCEPT, EV_ADD|EV_ENABLE|__EV_POLL, evff, 0, (void *)(p->p_kq_serial + i)); nkev++; kevp++; } if (nkev == 0) continue; *nregistered += ppollregister_evts(p, kev, nkev, &pl[i], i); if (pl[i].revents != 0) (*ncollected)++; } DPRINTFN(1, "poll registered = %d, collected = %d\n", *nregistered, *ncollected); } /* * Convert given kqueue event into corresponding poll(2) revents bit. */ int ppollcollect(struct proc *p, struct kevent *kevp, struct pollfd *pl, u_int nfds) { static struct timeval poll_errintvl = { 5, 0 }; static struct timeval poll_lasterr; int already_seen; unsigned long i; /* Extract poll array index */ i = (unsigned long)kevp->udata - p->p_kq_serial; if (i >= nfds) { panic("%s: spurious kevp %p nfds %u udata 0x%lx serial 0x%lx", __func__, kevp, nfds, (unsigned long)kevp->udata, p->p_kq_serial); } if ((int)kevp->ident != pl[i].fd) { panic("%s: kevp %p %lu/%d mismatch fd %d!=%d serial 0x%lx", __func__, kevp, i + 1, nfds, (int)kevp->ident, pl[i].fd, p->p_kq_serial); } /* * A given descriptor may already have generated an error * against another filter during kqueue_register(). * * Make sure to set the appropriate flags but do not * increment `*retval' more than once. */ already_seen = (pl[i].revents != 0); /* POLLNVAL preempts other events. */ if ((kevp->flags & EV_ERROR) && kevp->data == EBADF) { pl[i].revents = POLLNVAL; goto done; } else if (pl[i].revents & POLLNVAL) { goto done; } switch (kevp->filter) { case EVFILT_READ: if (kevp->flags & __EV_HUP) pl[i].revents |= POLLHUP; if (pl[i].events & (POLLIN | POLLRDNORM)) pl[i].revents |= pl[i].events & (POLLIN | POLLRDNORM); break; case EVFILT_WRITE: /* POLLHUP and POLLOUT/POLLWRNORM are mutually exclusive */ if (kevp->flags & __EV_HUP) { pl[i].revents |= POLLHUP; } else if (pl[i].events & (POLLOUT | POLLWRNORM)) { pl[i].revents |= pl[i].events & (POLLOUT | POLLWRNORM); } break; case EVFILT_EXCEPT: if (kevp->flags & __EV_HUP) { if (pl[i].events != 0 && pl[i].events != POLLOUT) DPRINTFN(0, "weird events %x\n", pl[i].events); pl[i].revents |= POLLHUP; break; } if (pl[i].events & (POLLPRI | POLLRDBAND)) pl[i].revents |= pl[i].events & (POLLPRI | POLLRDBAND); break; default: KASSERT(0); } done: DPRINTFN(1, "poll get %lu/%d fd %d revents %02x serial %lu filt %d\n", i+1, nfds, pl[i].fd, pl[i].revents, (unsigned long)kevp->udata, kevp->filter); /* * Make noise about unclaimed events as they might indicate a bug * and can result in spurious-looking wakeups of poll(2). * * Live-locking within the system call should not happen because * the scan loop in doppoll() has an upper limit for the number * of events to process. */ if (pl[i].revents == 0 && ratecheck(&poll_lasterr, &poll_errintvl)) { printf("%s[%d]: poll index %lu fd %d events 0x%x " "filter %d/0x%x unclaimed\n", p->p_p->ps_comm, p->p_tid, i, pl[i].fd, pl[i].events, kevp->filter, kevp->flags); } if (!already_seen && (pl[i].revents != 0)) return (1); return (0); } /* * utrace system call */ int sys_utrace(struct proc *curp, void *v, register_t *retval) { #ifdef KTRACE struct sys_utrace_args /* { syscallarg(const char *) label; syscallarg(const void *) addr; syscallarg(size_t) len; } */ *uap = v; return (ktruser(curp, SCARG(uap, label), SCARG(uap, addr), SCARG(uap, len))); #else return (0); #endif }
7 2 5 1 1 5 2 3 11 7 3 6 14 4 10 13 1 3 9 2 9 6 2 4 6 13 12 2 8 6 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 /* $OpenBSD: vfs_getcwd.c,v 1.38 2022/12/05 23:18:37 deraadt Exp $ */ /* $NetBSD: vfs_getcwd.c,v 1.3.2.3 1999/07/11 10:24:09 sommerfeld Exp $ */ /* * Copyright (c) 1999 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Bill Sommerfeld. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/namei.h> #include <sys/filedesc.h> #include <sys/stat.h> #include <sys/lock.h> #include <sys/vnode.h> #include <sys/mount.h> #include <sys/ktrace.h> #include <sys/proc.h> #include <sys/uio.h> #include <sys/malloc.h> #include <sys/dirent.h> #include <ufs/ufs/dir.h> /* only for DIRBLKSIZ */ #include <sys/syscallargs.h> /* Find parent vnode of *lvpp, return in *uvpp */ int vfs_getcwd_scandir(struct vnode **lvpp, struct vnode **uvpp, char **bpp, char *bufp, struct proc *p) { int eofflag, tries, dirbuflen = 0, len, reclen, error = 0; off_t off; struct uio uio; struct iovec iov; char *dirbuf = NULL; ino_t fileno; struct vattr va; struct vnode *uvp = NULL; struct vnode *lvp = *lvpp; struct componentname cn; tries = 0; /* * If we want the filename, get some info we need while the * current directory is still locked. */ if (bufp != NULL) { error = VOP_GETATTR(lvp, &va, p->p_ucred, p); if (error) { vput(lvp); *lvpp = NULL; *uvpp = NULL; return (error); } } cn.cn_nameiop = LOOKUP; cn.cn_flags = ISLASTCN | ISDOTDOT | RDONLY; cn.cn_proc = p; cn.cn_cred = p->p_ucred; cn.cn_pnbuf = NULL; cn.cn_nameptr = ".."; cn.cn_namelen = 2; cn.cn_consume = 0; /* Get parent vnode using lookup of '..' */ error = VOP_LOOKUP(lvp, uvpp, &cn); if (error) { vput(lvp); *lvpp = NULL; *uvpp = NULL; return (error); } uvp = *uvpp; /* If we don't care about the pathname, we're done */ if (bufp == NULL) { error = 0; goto out; } fileno = va.va_fileid; dirbuflen = DIRBLKSIZ; if (dirbuflen < va.va_blocksize) dirbuflen = va.va_blocksize; /* XXX we need some limit for fuse, 1 MB should be enough */ if (dirbuflen > 0xfffff) { error = EINVAL; goto out; } dirbuf = malloc(dirbuflen, M_TEMP, M_WAITOK); off = 0; do { char *cpos; struct dirent *dp; iov.iov_base = dirbuf; iov.iov_len = dirbuflen; uio.uio_iov = &iov; uio.uio_iovcnt = 1; uio.uio_offset = off; uio.uio_resid = dirbuflen; uio.uio_segflg = UIO_SYSSPACE; uio.uio_rw = UIO_READ; uio.uio_procp = p; eofflag = 0; /* Call VOP_READDIR of parent */ error = VOP_READDIR(uvp, &uio, p->p_ucred, &eofflag); off = uio.uio_offset; /* Try again if NFS tosses its cookies */ if (error == EINVAL && tries < 3) { tries++; off = 0; continue; } else if (error) { goto out; /* Old userland getcwd() behaviour */ } cpos = dirbuf; tries = 0; /* Scan directory page looking for matching vnode */ for (len = (dirbuflen - uio.uio_resid); len > 0; len -= reclen) { dp = (struct dirent *)cpos; reclen = dp->d_reclen; /* Check for malformed directory */ if (reclen < DIRENT_RECSIZE(1) || reclen > len) { error = EINVAL; goto out; } if (dp->d_fileno == fileno) { char *bp = *bpp; if (offsetof(struct dirent, d_name) + dp->d_namlen > reclen) { error = EINVAL; goto out; } bp -= dp->d_namlen; if (bp <= bufp) { error = ERANGE; goto out; } memmove(bp, dp->d_name, dp->d_namlen); error = 0; *bpp = bp; goto out; } cpos += reclen; } } while (!eofflag); error = ENOENT; out: vrele(lvp); *lvpp = NULL; free(dirbuf, M_TEMP, dirbuflen); return (error); } /* Do a lookup in the vnode-to-name reverse */ int vfs_getcwd_getcache(struct vnode **lvpp, struct vnode **uvpp, char **bpp, char *bufp) { struct vnode *lvp, *uvp = NULL; char *obp; int error, vpid; lvp = *lvpp; obp = *bpp; /* Save original position to restore to on error */ error = cache_revlookup(lvp, uvpp, bpp, bufp); if (error) { if (error != -1) { vput(lvp); *lvpp = NULL; *uvpp = NULL; } return (error); } uvp = *uvpp; vpid = uvp->v_id; /* Release current lock before acquiring the parent lock */ VOP_UNLOCK(lvp); error = vget(uvp, LK_EXCLUSIVE | LK_RETRY); if (error) *uvpp = NULL; /* * Verify that vget() succeeded, and check that vnode capability * didn't change while we were waiting for the lock. */ if (error || (vpid != uvp->v_id)) { /* * Try to get our lock back. If that works, tell the caller to * try things the hard way, otherwise give up. */ if (!error) vput(uvp); *uvpp = NULL; error = vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY); if (!error) { *bpp = obp; /* restore the buffer */ return (-1); } } vrele(lvp); *lvpp = NULL; return (error); } /* Common routine shared by sys___getcwd() and vn_isunder() and sys___realpath() */ int vfs_getcwd_common(struct vnode *lvp, struct vnode *rvp, char **bpp, char *bufp, int limit, int flags, struct proc *p) { struct filedesc *fdp = p->p_fd; struct vnode *uvp = NULL; char *bp = NULL; int error, perms = VEXEC; if (rvp == NULL) { rvp = fdp->fd_rdir; if (rvp == NULL) rvp = rootvnode; } vref(rvp); vref(lvp); error = vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY); if (error) { vrele(lvp); lvp = NULL; goto out; } if (bufp) bp = *bpp; if (lvp == rvp) { if (bp) *(--bp) = '/'; goto out; } /* * This loop will terminate when we hit the root, VOP_READDIR() or * VOP_LOOKUP() fails, or we run out of space in the user buffer. */ do { if (lvp->v_type != VDIR) { error = ENOTDIR; goto out; } /* Check for access if caller cares */ if (flags & GETCWD_CHECK_ACCESS) { error = VOP_ACCESS(lvp, perms, p->p_ucred, p); if (error) goto out; perms = VEXEC|VREAD; } /* Step up if we're a covered vnode */ while (lvp->v_flag & VROOT) { struct vnode *tvp; if (lvp == rvp) goto out; tvp = lvp; lvp = lvp->v_mount->mnt_vnodecovered; vput(tvp); if (lvp == NULL) { error = ENOENT; goto out; } vref(lvp); error = vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY); if (error) { vrele(lvp); lvp = NULL; goto out; } } /* Look in the name cache */ error = vfs_getcwd_getcache(&lvp, &uvp, &bp, bufp); if (error == -1) { /* If that fails, look in the directory */ error = vfs_getcwd_scandir(&lvp, &uvp, &bp, bufp, p); } if (error) goto out; #ifdef DIAGNOSTIC if (lvp != NULL) panic("getcwd: oops, forgot to null lvp"); if (bufp && (bp <= bufp)) { panic("getcwd: oops, went back too far"); } #endif if (bp) *(--bp) = '/'; lvp = uvp; uvp = NULL; limit--; } while ((lvp != rvp) && (limit > 0)); out: if (bpp) *bpp = bp; if (uvp) vput(uvp); if (lvp) vput(lvp); vrele(rvp); return (error); } /* Find pathname of a process's current directory */ int sys___getcwd(struct proc *p, void *v, register_t *retval) { struct sys___getcwd_args *uap = v; int error, len = SCARG(uap, len); char *path, *bp; if (len > MAXPATHLEN * 4) len = MAXPATHLEN * 4; else if (len < 2) return (ERANGE); path = malloc(len, M_TEMP, M_WAITOK); bp = &path[len - 1]; *bp = '\0'; /* * 5th argument here is "max number of vnodes to traverse". * Since each entry takes up at least 2 bytes in the output * buffer, limit it to N/2 vnodes for an N byte buffer. */ error = vfs_getcwd_common(p->p_fd->fd_cdir, NULL, &bp, path, len/2, GETCWD_CHECK_ACCESS, p); if (error) goto out; /* Put the result into user buffer */ error = copyoutstr(bp, SCARG(uap, buf), MAXPATHLEN, NULL); #ifdef KTRACE if (KTRPOINT(p, KTR_NAMEI)) ktrnamei(p, bp); #endif out: free(path, M_TEMP, len); return (error); }
2 69 68 41 21 3 13 4 4 4 5 5 5 5 3 2 5 21 22 11 11 11 19 3 3 3 1 2 2 2 1 2 3 3 3 477 480 5 3 2 1 2 4 2 2 2 6435 6384 176 6441 6432 6442 6440 532 524 175 168 173 9 175 480 47 47 47 47 47 1 15 47 47 47 47 47 47 47 33 31 10 31 31 181 165 18 18 3 1 2 2 2 42 16 19 7 5 3 1 1 1 13 5 16 16 17 16 1 3 2 1 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 /* $OpenBSD: kern_sig.c,v 1.329 2024/05/22 09:22:55 claudio Exp $ */ /* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */ /* * Copyright (c) 1997 Theo de Raadt. All rights reserved. * Copyright (c) 1982, 1986, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_sig.c 8.7 (Berkeley) 4/18/94 */ #include <sys/param.h> #include <sys/signalvar.h> #include <sys/queue.h> #include <sys/namei.h> #include <sys/vnode.h> #include <sys/event.h> #include <sys/proc.h> #include <sys/systm.h> #include <sys/acct.h> #include <sys/fcntl.h> #include <sys/filedesc.h> #include <sys/wait.h> #include <sys/ktrace.h> #include <sys/stat.h> #include <sys/malloc.h> #include <sys/pool.h> #include <sys/sched.h> #include <sys/user.h> #include <sys/syslog.h> #include <sys/ttycom.h> #include <sys/pledge.h> #include <sys/witness.h> #include <sys/exec_elf.h> #include <sys/mount.h> #include <sys/syscallargs.h> #include <uvm/uvm_extern.h> #include <machine/tcb.h> int nosuidcoredump = 1; int filt_sigattach(struct knote *kn); void filt_sigdetach(struct knote *kn); int filt_signal(struct knote *kn, long hint); const struct filterops sig_filtops = { .f_flags = 0, .f_attach = filt_sigattach, .f_detach = filt_sigdetach, .f_event = filt_signal, }; /* * The array below categorizes the signals and their default actions. */ const int sigprop[NSIG] = { 0, /* unused */ SA_KILL, /* SIGHUP */ SA_KILL, /* SIGINT */ SA_KILL|SA_CORE, /* SIGQUIT */ SA_KILL|SA_CORE, /* SIGILL */ SA_KILL|SA_CORE, /* SIGTRAP */ SA_KILL|SA_CORE, /* SIGABRT */ SA_KILL|SA_CORE, /* SIGEMT */ SA_KILL|SA_CORE, /* SIGFPE */ SA_KILL, /* SIGKILL */ SA_KILL|SA_CORE, /* SIGBUS */ SA_KILL|SA_CORE, /* SIGSEGV */ SA_KILL|SA_CORE, /* SIGSYS */ SA_KILL, /* SIGPIPE */ SA_KILL, /* SIGALRM */ SA_KILL, /* SIGTERM */ SA_IGNORE, /* SIGURG */ SA_STOP, /* SIGSTOP */ SA_STOP|SA_TTYSTOP, /* SIGTSTP */ SA_IGNORE|SA_CONT, /* SIGCONT */ SA_IGNORE, /* SIGCHLD */ SA_STOP|SA_TTYSTOP, /* SIGTTIN */ SA_STOP|SA_TTYSTOP, /* SIGTTOU */ SA_IGNORE, /* SIGIO */ SA_KILL, /* SIGXCPU */ SA_KILL, /* SIGXFSZ */ SA_KILL, /* SIGVTALRM */ SA_KILL, /* SIGPROF */ SA_IGNORE, /* SIGWINCH */ SA_IGNORE, /* SIGINFO */ SA_KILL, /* SIGUSR1 */ SA_KILL, /* SIGUSR2 */ SA_IGNORE, /* SIGTHR */ }; #define CONTSIGMASK (sigmask(SIGCONT)) #define STOPSIGMASK (sigmask(SIGSTOP) | sigmask(SIGTSTP) | \ sigmask(SIGTTIN) | sigmask(SIGTTOU)) void setsigvec(struct proc *, int, struct sigaction *); void proc_stop(struct proc *p, int); void proc_stop_sweep(void *); void *proc_stop_si; void setsigctx(struct proc *, int, struct sigctx *); void postsig_done(struct proc *, int, sigset_t, int); void postsig(struct proc *, int, struct sigctx *); int cansignal(struct proc *, struct process *, int); struct pool sigacts_pool; /* memory pool for sigacts structures */ void sigio_del(struct sigiolst *); void sigio_unlink(struct sigio_ref *, struct sigiolst *); struct mutex sigio_lock = MUTEX_INITIALIZER(IPL_HIGH); /* * Can thread p, send the signal signum to process qr? */ int cansignal(struct proc *p, struct process *qr, int signum) { struct process *pr = p->p_p; struct ucred *uc = p->p_ucred; struct ucred *quc = qr->ps_ucred; if (uc->cr_uid == 0) return (1); /* root can always signal */ if (pr == qr) return (1); /* process can always signal itself */ /* optimization: if the same creds then the tests below will pass */ if (uc == quc) return (1); if (signum == SIGCONT && qr->ps_session == pr->ps_session) return (1); /* SIGCONT in session */ /* * Using kill(), only certain signals can be sent to setugid * child processes */ if (qr->ps_flags & PS_SUGID) { switch (signum) { case 0: case SIGKILL: case SIGINT: case SIGTERM: case SIGALRM: case SIGSTOP: case SIGTTIN: case SIGTTOU: case SIGTSTP: case SIGHUP: case SIGUSR1: case SIGUSR2: if (uc->cr_ruid == quc->cr_ruid || uc->cr_uid == quc->cr_ruid) return (1); } return (0); } if (uc->cr_ruid == quc->cr_ruid || uc->cr_ruid == quc->cr_svuid || uc->cr_uid == quc->cr_ruid || uc->cr_uid == quc->cr_svuid) return (1); return (0); } /* * Initialize signal-related data structures. */ void signal_init(void) { proc_stop_si = softintr_establish(IPL_SOFTCLOCK, proc_stop_sweep, NULL); if (proc_stop_si == NULL) panic("signal_init failed to register softintr"); pool_init(&sigacts_pool, sizeof(struct sigacts), 0, IPL_NONE, PR_WAITOK, "sigapl", NULL); } /* * Initialize a new sigaltstack structure. */ void sigstkinit(struct sigaltstack *ss) { ss->ss_flags = SS_DISABLE; ss->ss_size = 0; ss->ss_sp = NULL; } /* * Create an initial sigacts structure, using the same signal state * as pr. */ struct sigacts * sigactsinit(struct process *pr) { struct sigacts *ps; ps = pool_get(&sigacts_pool, PR_WAITOK); memcpy(ps, pr->ps_sigacts, sizeof(struct sigacts)); return (ps); } /* * Release a sigacts structure. */ void sigactsfree(struct sigacts *ps) { pool_put(&sigacts_pool, ps); } int sys_sigaction(struct proc *p, void *v, register_t *retval) { struct sys_sigaction_args /* { syscallarg(int) signum; syscallarg(const struct sigaction *) nsa; syscallarg(struct sigaction *) osa; } */ *uap = v; struct sigaction vec; #ifdef KTRACE struct sigaction ovec; #endif struct sigaction *sa; const struct sigaction *nsa; struct sigaction *osa; struct sigacts *ps = p->p_p->ps_sigacts; int signum; int bit, error; signum = SCARG(uap, signum); nsa = SCARG(uap, nsa); osa = SCARG(uap, osa); if (signum <= 0 || signum >= NSIG || (nsa && (signum == SIGKILL || signum == SIGSTOP))) return (EINVAL); sa = &vec; if (osa) { mtx_enter(&p->p_p->ps_mtx); sa->sa_handler = ps->ps_sigact[signum]; sa->sa_mask = ps->ps_catchmask[signum]; bit = sigmask(signum); sa->sa_flags = 0; if ((ps->ps_sigonstack & bit) != 0) sa->sa_flags |= SA_ONSTACK; if ((ps->ps_sigintr & bit) == 0) sa->sa_flags |= SA_RESTART; if ((ps->ps_sigreset & bit) != 0) sa->sa_flags |= SA_RESETHAND; if ((ps->ps_siginfo & bit) != 0) sa->sa_flags |= SA_SIGINFO; if (signum == SIGCHLD) { if ((ps->ps_sigflags & SAS_NOCLDSTOP) != 0) sa->sa_flags |= SA_NOCLDSTOP; if ((ps->ps_sigflags & SAS_NOCLDWAIT) != 0) sa->sa_flags |= SA_NOCLDWAIT; } mtx_leave(&p->p_p->ps_mtx); if ((sa->sa_mask & bit) == 0) sa->sa_flags |= SA_NODEFER; sa->sa_mask &= ~bit; error = copyout(sa, osa, sizeof (vec)); if (error) return (error); #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ovec = vec; #endif } if (nsa) { error = copyin(nsa, sa, sizeof (vec)); if (error) return (error); #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrsigaction(p, sa); #endif setsigvec(p, signum, sa); } #ifdef KTRACE if (osa && KTRPOINT(p, KTR_STRUCT)) ktrsigaction(p, &ovec); #endif return (0); } void setsigvec(struct proc *p, int signum, struct sigaction *sa) { struct sigacts *ps = p->p_p->ps_sigacts; int bit; bit = sigmask(signum); mtx_enter(&p->p_p->ps_mtx); ps->ps_sigact[signum] = sa->sa_handler; if ((sa->sa_flags & SA_NODEFER) == 0) sa->sa_mask |= sigmask(signum); ps->ps_catchmask[signum] = sa->sa_mask &~ sigcantmask; if (signum == SIGCHLD) { if (sa->sa_flags & SA_NOCLDSTOP) atomic_setbits_int(&ps->ps_sigflags, SAS_NOCLDSTOP); else atomic_clearbits_int(&ps->ps_sigflags, SAS_NOCLDSTOP); /* * If the SA_NOCLDWAIT flag is set or the handler * is SIG_IGN we reparent the dying child to PID 1 * (init) which will reap the zombie. Because we use * init to do our dirty work we never set SAS_NOCLDWAIT * for PID 1. * XXX exit1 rework means this is unnecessary? */ if (initprocess->ps_sigacts != ps && ((sa->sa_flags & SA_NOCLDWAIT) || sa->sa_handler == SIG_IGN)) atomic_setbits_int(&ps->ps_sigflags, SAS_NOCLDWAIT); else atomic_clearbits_int(&ps->ps_sigflags, SAS_NOCLDWAIT); } if ((sa->sa_flags & SA_RESETHAND) != 0) ps->ps_sigreset |= bit; else ps->ps_sigreset &= ~bit; if ((sa->sa_flags & SA_SIGINFO) != 0) ps->ps_siginfo |= bit; else ps->ps_siginfo &= ~bit; if ((sa->sa_flags & SA_RESTART) == 0) ps->ps_sigintr |= bit; else ps->ps_sigintr &= ~bit; if ((sa->sa_flags & SA_ONSTACK) != 0) ps->ps_sigonstack |= bit; else ps->ps_sigonstack &= ~bit; /* * Set bit in ps_sigignore for signals that are set to SIG_IGN, * and for signals set to SIG_DFL where the default is to ignore. * However, don't put SIGCONT in ps_sigignore, * as we have to restart the process. */ if (sa->sa_handler == SIG_IGN || (sigprop[signum] & SA_IGNORE && sa->sa_handler == SIG_DFL)) { atomic_clearbits_int(&p->p_siglist, bit); atomic_clearbits_int(&p->p_p->ps_siglist, bit); if (signum != SIGCONT) ps->ps_sigignore |= bit; /* easier in psignal */ ps->ps_sigcatch &= ~bit; } else { ps->ps_sigignore &= ~bit; if (sa->sa_handler == SIG_DFL) ps->ps_sigcatch &= ~bit; else ps->ps_sigcatch |= bit; } mtx_leave(&p->p_p->ps_mtx); } /* * Initialize signal state for process 0; * set to ignore signals that are ignored by default. */ void siginit(struct sigacts *ps) { int i; for (i = 0; i < NSIG; i++) if (sigprop[i] & SA_IGNORE && i != SIGCONT) ps->ps_sigignore |= sigmask(i); ps->ps_sigflags = SAS_NOCLDWAIT | SAS_NOCLDSTOP; } /* * Reset signals for an exec by the specified thread. */ void execsigs(struct proc *p) { struct sigacts *ps; int nc, mask; ps = p->p_p->ps_sigacts; mtx_enter(&p->p_p->ps_mtx); /* * Reset caught signals. Held signals remain held * through p_sigmask (unless they were caught, * and are now ignored by default). */ while (ps->ps_sigcatch) { nc = ffs((long)ps->ps_sigcatch); mask = sigmask(nc); ps->ps_sigcatch &= ~mask; if (sigprop[nc] & SA_IGNORE) { if (nc != SIGCONT) ps->ps_sigignore |= mask; atomic_clearbits_int(&p->p_siglist, mask); atomic_clearbits_int(&p->p_p->ps_siglist, mask); } ps->ps_sigact[nc] = SIG_DFL; } /* * Reset stack state to the user stack. * Clear set of signals caught on the signal stack. */ sigstkinit(&p->p_sigstk); atomic_clearbits_int(&ps->ps_sigflags, SAS_NOCLDWAIT); if (ps->ps_sigact[SIGCHLD] == SIG_IGN) ps->ps_sigact[SIGCHLD] = SIG_DFL; mtx_leave(&p->p_p->ps_mtx); } /* * Manipulate signal mask. * Note that we receive new mask, not pointer, * and return old mask as return value; * the library stub does the rest. */ int sys_sigprocmask(struct proc *p, void *v, register_t *retval) { struct sys_sigprocmask_args /* { syscallarg(int) how; syscallarg(sigset_t) mask; } */ *uap = v; int error = 0; sigset_t mask; KASSERT(p == curproc); *retval = p->p_sigmask; mask = SCARG(uap, mask) &~ sigcantmask; switch (SCARG(uap, how)) { case SIG_BLOCK: SET(p->p_sigmask, mask); break; case SIG_UNBLOCK: CLR(p->p_sigmask, mask); break; case SIG_SETMASK: p->p_sigmask = mask; break; default: error = EINVAL; break; } return (error); } int sys_sigpending(struct proc *p, void *v, register_t *retval) { *retval = p->p_siglist | p->p_p->ps_siglist; return (0); } /* * Temporarily replace calling proc's signal mask for the duration of a * system call. Original signal mask will be restored by userret(). */ void dosigsuspend(struct proc *p, sigset_t newmask) { KASSERT(p == curproc); p->p_oldmask = p->p_sigmask; p->p_sigmask = newmask; atomic_setbits_int(&p->p_flag, P_SIGSUSPEND); } /* * Suspend thread until signal, providing mask to be set * in the meantime. Note nonstandard calling convention: * libc stub passes mask, not pointer, to save a copyin. */ int sys_sigsuspend(struct proc *p, void *v, register_t *retval) { struct sys_sigsuspend_args /* { syscallarg(int) mask; } */ *uap = v; dosigsuspend(p, SCARG(uap, mask) &~ sigcantmask); while (tsleep_nsec(&nowake, PPAUSE|PCATCH, "sigsusp", INFSLP) == 0) continue; /* always return EINTR rather than ERESTART... */ return (EINTR); } int sigonstack(size_t stack) { const struct sigaltstack *ss = &curproc->p_sigstk; return (ss->ss_flags & SS_DISABLE ? 0 : (stack - (size_t)ss->ss_sp < ss->ss_size)); } int sys_sigaltstack(struct proc *p, void *v, register_t *retval) { struct sys_sigaltstack_args /* { syscallarg(const struct sigaltstack *) nss; syscallarg(struct sigaltstack *) oss; } */ *uap = v; struct sigaltstack ss; const struct sigaltstack *nss; struct sigaltstack *oss; int onstack = sigonstack(PROC_STACK(p)); int error; nss = SCARG(uap, nss); oss = SCARG(uap, oss); if (oss != NULL) { ss = p->p_sigstk; if (onstack) ss.ss_flags |= SS_ONSTACK; if ((error = copyout(&ss, oss, sizeof(ss)))) return (error); } if (nss == NULL) return (0); error = copyin(nss, &ss, sizeof(ss)); if (error) return (error); if (onstack) return (EPERM); if (ss.ss_flags & ~SS_DISABLE) return (EINVAL); if (ss.ss_flags & SS_DISABLE) { p->p_sigstk.ss_flags = ss.ss_flags; return (0); } if (ss.ss_size < MINSIGSTKSZ) return (ENOMEM); error = uvm_map_remap_as_stack(p, (vaddr_t)ss.ss_sp, ss.ss_size); if (error) return (error); p->p_sigstk = ss; return (0); } int sys_kill(struct proc *cp, void *v, register_t *retval) { struct sys_kill_args /* { syscallarg(int) pid; syscallarg(int) signum; } */ *uap = v; struct process *pr; int pid = SCARG(uap, pid); int signum = SCARG(uap, signum); int error; int zombie = 0; if ((error = pledge_kill(cp, pid)) != 0) return (error); if (((u_int)signum) >= NSIG) return (EINVAL); if (pid > 0) { if ((pr = prfind(pid)) == NULL) { if ((pr = zombiefind(pid)) == NULL) return (ESRCH); else zombie = 1; } if (!cansignal(cp, pr, signum)) return (EPERM); /* kill single process */ if (signum && !zombie) prsignal(pr, signum); return (0); } switch (pid) { case -1: /* broadcast signal */ return (killpg1(cp, signum, 0, 1)); case 0: /* signal own process group */ return (killpg1(cp, signum, 0, 0)); default: /* negative explicit process group */ return (killpg1(cp, signum, -pid, 0)); } } int sys_thrkill(struct proc *cp, void *v, register_t *retval) { struct sys_thrkill_args /* { syscallarg(pid_t) tid; syscallarg(int) signum; syscallarg(void *) tcb; } */ *uap = v; struct proc *p; int tid = SCARG(uap, tid); int signum = SCARG(uap, signum); void *tcb; if (((u_int)signum) >= NSIG) return (EINVAL); p = tid ? tfind_user(tid, cp->p_p) : cp; if (p == NULL) return (ESRCH); /* optionally require the target thread to have the given tcb addr */ tcb = SCARG(uap, tcb); if (tcb != NULL && tcb != TCB_GET(p)) return (ESRCH); if (signum) ptsignal(p, signum, STHREAD); return (0); } /* * Common code for kill process group/broadcast kill. * cp is calling process. */ int killpg1(struct proc *cp, int signum, int pgid, int all) { struct process *pr; struct pgrp *pgrp; int nfound = 0; if (all) { /* * broadcast */ LIST_FOREACH(pr, &allprocess, ps_list) { if (pr->ps_pid <= 1 || pr->ps_flags & (PS_SYSTEM | PS_NOBROADCASTKILL) || pr == cp->p_p || !cansignal(cp, pr, signum)) continue; nfound++; if (signum) prsignal(pr, signum); } } else { if (pgid == 0) /* * zero pgid means send to my process group. */ pgrp = cp->p_p->ps_pgrp; else { pgrp = pgfind(pgid); if (pgrp == NULL) return (ESRCH); } LIST_FOREACH(pr, &pgrp->pg_members, ps_pglist) { if (pr->ps_pid <= 1 || pr->ps_flags & PS_SYSTEM || !cansignal(cp, pr, signum)) continue; nfound++; if (signum) prsignal(pr, signum); } } return (nfound ? 0 : ESRCH); } #define CANDELIVER(uid, euid, pr) \ (euid == 0 || \ (uid) == (pr)->ps_ucred->cr_ruid || \ (uid) == (pr)->ps_ucred->cr_svuid || \ (uid) == (pr)->ps_ucred->cr_uid || \ (euid) == (pr)->ps_ucred->cr_ruid || \ (euid) == (pr)->ps_ucred->cr_svuid || \ (euid) == (pr)->ps_ucred->cr_uid) #define CANSIGIO(cr, pr) \ CANDELIVER((cr)->cr_ruid, (cr)->cr_uid, (pr)) /* * Send a signal to a process group. If checktty is 1, * limit to members which have a controlling terminal. */ void pgsignal(struct pgrp *pgrp, int signum, int checkctty) { struct process *pr; if (pgrp) LIST_FOREACH(pr, &pgrp->pg_members, ps_pglist) if (checkctty == 0 || pr->ps_flags & PS_CONTROLT) prsignal(pr, signum); } /* * Send a SIGIO or SIGURG signal to a process or process group using stored * credentials rather than those of the current process. */ void pgsigio(struct sigio_ref *sir, int sig, int checkctty) { struct process *pr; struct sigio *sigio; if (sir->sir_sigio == NULL) return; KERNEL_LOCK(); mtx_enter(&sigio_lock); sigio = sir->sir_sigio; if (sigio == NULL) goto out; if (sigio->sio_pgid > 0) { if (CANSIGIO(sigio->sio_ucred, sigio->sio_proc)) prsignal(sigio->sio_proc, sig); } else if (sigio->sio_pgid < 0) { LIST_FOREACH(pr, &sigio->sio_pgrp->pg_members, ps_pglist) { if (CANSIGIO(sigio->sio_ucred, pr) && (checkctty == 0 || (pr->ps_flags & PS_CONTROLT))) prsignal(pr, sig); } } out: mtx_leave(&sigio_lock); KERNEL_UNLOCK(); } /* * Recalculate the signal mask and reset the signal disposition after * usermode frame for delivery is formed. */ void postsig_done(struct proc *p, int signum, sigset_t catchmask, int reset) { p->p_ru.ru_nsignals++; SET(p->p_sigmask, catchmask); if (reset != 0) { sigset_t mask = sigmask(signum); struct sigacts *ps = p->p_p->ps_sigacts; mtx_enter(&p->p_p->ps_mtx); ps->ps_sigcatch &= ~mask; if (signum != SIGCONT && sigprop[signum] & SA_IGNORE) ps->ps_sigignore |= mask; ps->ps_sigact[signum] = SIG_DFL; mtx_leave(&p->p_p->ps_mtx); } } /* * Send a signal caused by a trap to the current thread * If it will be caught immediately, deliver it with correct code. * Otherwise, post it normally. */ void trapsignal(struct proc *p, int signum, u_long trapno, int code, union sigval sigval) { struct process *pr = p->p_p; struct sigctx ctx; int mask; switch (signum) { case SIGILL: if (code == ILL_BTCFI) { pr->ps_acflag |= ABTCFI; break; } /* FALLTHROUGH */ case SIGBUS: case SIGSEGV: pr->ps_acflag |= ATRAP; break; } mask = sigmask(signum); setsigctx(p, signum, &ctx); if ((pr->ps_flags & PS_TRACED) == 0 && ctx.sig_catch != 0 && (p->p_sigmask & mask) == 0) { siginfo_t si; initsiginfo(&si, signum, trapno, code, sigval); #ifdef KTRACE if (KTRPOINT(p, KTR_PSIG)) { ktrpsig(p, signum, ctx.sig_action, p->p_sigmask, code, &si); } #endif if (sendsig(ctx.sig_action, signum, p->p_sigmask, &si, ctx.sig_info, ctx.sig_onstack)) { KERNEL_LOCK(); sigexit(p, SIGILL); /* NOTREACHED */ } postsig_done(p, signum, ctx.sig_catchmask, ctx.sig_reset); } else { p->p_sisig = signum; p->p_sitrapno = trapno; /* XXX for core dump/debugger */ p->p_sicode = code; p->p_sigval = sigval; /* * If traced, stop if signal is masked, and stay stopped * until released by the debugger. If our parent process * is waiting for us, don't hang as we could deadlock. */ if (((pr->ps_flags & (PS_TRACED | PS_PPWAIT)) == PS_TRACED) && signum != SIGKILL && (p->p_sigmask & mask) != 0) { int s; single_thread_set(p, SINGLE_SUSPEND | SINGLE_NOWAIT); pr->ps_xsig = signum; SCHED_LOCK(s); proc_stop(p, 1); SCHED_UNLOCK(s); signum = pr->ps_xsig; single_thread_clear(p, 0); /* * If we are no longer being traced, or the parent * didn't give us a signal, skip sending the signal. */ if ((pr->ps_flags & PS_TRACED) == 0 || signum == 0) return; /* update signal info */ p->p_sisig = signum; mask = sigmask(signum); } /* * Signals like SIGBUS and SIGSEGV should not, when * generated by the kernel, be ignorable or blockable. * If it is and we're not being traced, then just kill * the process. * After vfs_shutdown(9), init(8) cannot receive signals * because new code pages of the signal handler cannot be * mapped from halted storage. init(8) may not die or the * kernel panics. Better loop between signal handler and * page fault trap until the machine is halted. */ if ((pr->ps_flags & PS_TRACED) == 0 && (sigprop[signum] & SA_KILL) && ((p->p_sigmask & mask) || ctx.sig_ignore) && pr->ps_pid != 1) { KERNEL_LOCK(); sigexit(p, signum); /* NOTREACHED */ } KERNEL_LOCK(); ptsignal(p, signum, STHREAD); KERNEL_UNLOCK(); } } /* * Send the signal to the process. If the signal has an action, the action * is usually performed by the target process rather than the caller; we add * the signal to the set of pending signals for the process. * * Exceptions: * o When a stop signal is sent to a sleeping process that takes the * default action, the process is stopped without awakening it. * o SIGCONT restarts stopped processes (or puts them back to sleep) * regardless of the signal action (eg, blocked or ignored). * * Other ignored signals are discarded immediately. */ void psignal(struct proc *p, int signum) { ptsignal(p, signum, SPROCESS); } /* * type = SPROCESS process signal, can be diverted (sigwait()) * type = STHREAD thread signal, but should be propagated if unhandled * type = SPROPAGATED propagated to this thread, so don't propagate again */ void ptsignal(struct proc *p, int signum, enum signal_type type) { int s, prop; sig_t action, altaction = SIG_DFL; sigset_t mask, sigmask; int *siglist; struct process *pr = p->p_p; struct proc *q; int wakeparent = 0; KERNEL_ASSERT_LOCKED(); #ifdef DIAGNOSTIC if ((u_int)signum >= NSIG || signum == 0) panic("psignal signal number"); #endif /* Ignore signal if the target process is exiting */ if (pr->ps_flags & PS_EXITING) return; mask = sigmask(signum); sigmask = READ_ONCE(p->p_sigmask); if (type == SPROCESS) { sigset_t tmpmask; /* Accept SIGKILL to coredumping processes */ if (pr->ps_flags & PS_COREDUMP && signum == SIGKILL) { atomic_setbits_int(&pr->ps_siglist, mask); return; } /* * If the current thread can process the signal * immediately (it's unblocked) then have it take it. */ q = curproc; tmpmask = READ_ONCE(q->p_sigmask); if (q->p_p == pr && (q->p_flag & P_WEXIT) == 0 && (tmpmask & mask) == 0) { p = q; sigmask = tmpmask; } else { /* * A process-wide signal can be diverted to a * different thread that's in sigwait() for this * signal. If there isn't such a thread, then * pick a thread that doesn't have it blocked so * that the stop/kill consideration isn't * delayed. Otherwise, mark it pending on the * main thread. */ TAILQ_FOREACH(q, &pr->ps_threads, p_thr_link) { /* ignore exiting threads */ if (q->p_flag & P_WEXIT) continue; /* skip threads that have the signal blocked */ tmpmask = READ_ONCE(q->p_sigmask); if ((tmpmask & mask) != 0) continue; /* okay, could send to this thread */ p = q; sigmask = tmpmask; /* * sigsuspend, sigwait, ppoll/pselect, etc? * Definitely go to this thread, as it's * already blocked in the kernel. */ if (q->p_flag & P_SIGSUSPEND) break; } } } if (type != SPROPAGATED) knote_locked(&pr->ps_klist, NOTE_SIGNAL | signum); prop = sigprop[signum]; /* * If proc is traced, always give parent a chance. */ if (pr->ps_flags & PS_TRACED) { action = SIG_DFL; } else { sigset_t sigcatch, sigignore; /* * If the signal is being ignored, * then we forget about it immediately. * (Note: we don't set SIGCONT in ps_sigignore, * and if it is set to SIG_IGN, * action will be SIG_DFL here.) */ mtx_enter(&pr->ps_mtx); sigignore = pr->ps_sigacts->ps_sigignore; sigcatch = pr->ps_sigacts->ps_sigcatch; mtx_leave(&pr->ps_mtx); if (sigignore & mask) return; if (sigmask & mask) { action = SIG_HOLD; if (sigcatch & mask) altaction = SIG_CATCH; } else if (sigcatch & mask) { action = SIG_CATCH; } else { action = SIG_DFL; if (prop & SA_KILL && pr->ps_nice > NZERO) pr->ps_nice = NZERO; /* * If sending a tty stop signal to a member of an * orphaned process group, discard the signal here if * the action is default; don't stop the process below * if sleeping, and don't clear any pending SIGCONT. */ if (prop & SA_TTYSTOP && pr->ps_pgrp->pg_jobc == 0) return; } } /* * If delivered to process, mark as pending there. Continue and stop * signals will be propagated to all threads. So they are always * marked at thread level. */ siglist = (type == SPROCESS) ? &pr->ps_siglist : &p->p_siglist; if (prop & (SA_CONT | SA_STOP)) siglist = &p->p_siglist; /* * XXX delay processing of SA_STOP signals unless action == SIG_DFL? */ if (prop & (SA_CONT | SA_STOP) && type != SPROPAGATED) TAILQ_FOREACH(q, &pr->ps_threads, p_thr_link) if (q != p) ptsignal(q, signum, SPROPAGATED); SCHED_LOCK(s); switch (p->p_stat) { case SSLEEP: /* * If process is sleeping uninterruptibly * we can't interrupt the sleep... the signal will * be noticed when the process returns through * trap() or syscall(). */ if ((p->p_flag & P_SINTR) == 0) goto out; /* * Process is sleeping and traced... make it runnable * so it can discover the signal in cursig() and stop * for the parent. */ if (pr->ps_flags & PS_TRACED) goto run; /* * Recheck sigmask before waking up the process, * there is a chance that while sending the signal * the process changed sigmask and went to sleep. */ sigmask = READ_ONCE(p->p_sigmask); if (sigmask & mask) goto out; else if (action == SIG_HOLD) { /* signal got unmasked, get proper action */ action = altaction; if (action == SIG_DFL) { if (prop & SA_KILL && pr->ps_nice > NZERO) pr->ps_nice = NZERO; /* * Discard tty stop signals sent to an * orphaned process group, see above. */ if (prop & SA_TTYSTOP && pr->ps_pgrp->pg_jobc == 0) { mask = 0; prop = 0; goto out; } } } /* * If SIGCONT is default (or ignored) and process is * asleep, we are finished; the process should not * be awakened. */ if ((prop & SA_CONT) && action == SIG_DFL) { mask = 0; goto out; } /* * When a sleeping process receives a stop * signal, process immediately if possible. */ if ((prop & SA_STOP) && action == SIG_DFL) { /* * If a child holding parent blocked, * stopping could cause deadlock. */ if (pr->ps_flags & PS_PPWAIT) goto out; mask = 0; pr->ps_xsig = signum; proc_stop(p, 0); goto out; } /* * All other (caught or default) signals * cause the process to run. */ goto runfast; /* NOTREACHED */ case SSTOP: /* * If traced process is already stopped, * then no further action is necessary. */ if (pr->ps_flags & PS_TRACED) goto out; /* * Kill signal always sets processes running. */ if (signum == SIGKILL) { atomic_clearbits_int(&p->p_flag, P_SUSPSIG); goto runfast; } if (prop & SA_CONT) { /* * If SIGCONT is default (or ignored), we continue the * process but don't leave the signal in p_siglist, as * it has no further action. If SIGCONT is held, we * continue the process and leave the signal in * p_siglist. If the process catches SIGCONT, let it * handle the signal itself. If it isn't waiting on * an event, then it goes back to run state. * Otherwise, process goes back to sleep state. */ atomic_setbits_int(&p->p_flag, P_CONTINUED); atomic_clearbits_int(&p->p_flag, P_SUSPSIG); wakeparent = 1; if (action == SIG_DFL) mask = 0; if (action == SIG_CATCH) goto runfast; if (p->p_wchan == NULL) goto run; atomic_clearbits_int(&p->p_flag, P_WSLEEP); p->p_stat = SSLEEP; goto out; } /* * Defer further processing for signals which are held, * except that stopped processes must be continued by SIGCONT. */ if (action == SIG_HOLD) goto out; if (prop & SA_STOP) { /* * Already stopped, don't need to stop again. * (If we did the shell could get confused.) */ mask = 0; goto out; } /* * If process is sleeping interruptibly, then simulate a * wakeup so that when it is continued, it will be made * runnable and can look at the signal. But don't make * the process runnable, leave it stopped. */ if (p->p_flag & P_SINTR) unsleep(p); goto out; case SONPROC: if (action == SIG_HOLD) goto out; /* set siglist before issuing the ast */ atomic_setbits_int(siglist, mask); mask = 0; signotify(p); /* FALLTHROUGH */ default: /* * SRUN, SIDL, SDEAD do nothing with the signal, * other than kicking ourselves if we are running. * It will either never be noticed, or noticed very soon. */ goto out; } /* NOTREACHED */ runfast: /* * Raise priority to at least PUSER. */ if (p->p_usrpri > PUSER) p->p_usrpri = PUSER; run: unsleep(p); setrunnable(p); out: /* finally adjust siglist */ if (mask) atomic_setbits_int(siglist, mask); if (prop & SA_CONT) { atomic_clearbits_int(siglist, STOPSIGMASK); } if (prop & SA_STOP) { atomic_clearbits_int(siglist, CONTSIGMASK); atomic_clearbits_int(&p->p_flag, P_CONTINUED); } SCHED_UNLOCK(s); if (wakeparent) wakeup(pr->ps_pptr); } /* fill the signal context which should be used by postsig() and issignal() */ void setsigctx(struct proc *p, int signum, struct sigctx *sctx) { struct sigacts *ps = p->p_p->ps_sigacts; sigset_t mask; mtx_enter(&p->p_p->ps_mtx); mask = sigmask(signum); sctx->sig_action = ps->ps_sigact[signum]; sctx->sig_catchmask = ps->ps_catchmask[signum]; sctx->sig_reset = (ps->ps_sigreset & mask) != 0; sctx->sig_info = (ps->ps_siginfo & mask) != 0; sctx->sig_intr = (ps->ps_sigintr & mask) != 0; sctx->sig_onstack = (ps->ps_sigonstack & mask) != 0; sctx->sig_ignore = (ps->ps_sigignore & mask) != 0; sctx->sig_catch = (ps->ps_sigcatch & mask) != 0; mtx_leave(&p->p_p->ps_mtx); } /* * Determine signal that should be delivered to process p, the current * process, 0 if none. * * If the current process has received a signal (should be caught or cause * termination, should interrupt current syscall), return the signal number. * Stop signals with default action are processed immediately, then cleared; * they aren't returned. This is checked after each entry to the system for * a syscall or trap. The normal call sequence is * * while (signum = cursig(curproc, &ctx)) * postsig(signum, &ctx); * * Assumes that if the P_SINTR flag is set, we're holding both the * kernel and scheduler locks. */ int cursig(struct proc *p, struct sigctx *sctx) { struct process *pr = p->p_p; int signum, mask, prop; sigset_t ps_siglist; int s; KASSERT(p == curproc); for (;;) { ps_siglist = READ_ONCE(pr->ps_siglist); membar_consumer(); mask = SIGPENDING(p); if (pr->ps_flags & PS_PPWAIT) mask &= ~STOPSIGMASK; if (mask == 0) /* no signal to send */ return (0); signum = ffs((long)mask); mask = sigmask(signum); /* take the signal! */ if (atomic_cas_uint(&pr->ps_siglist, ps_siglist, ps_siglist & ~mask) != ps_siglist) { /* lost race taking the process signal, restart */ continue; } atomic_clearbits_int(&p->p_siglist, mask); setsigctx(p, signum, sctx); /* * We should see pending but ignored signals * only if PS_TRACED was on when they were posted. */ if (sctx->sig_ignore && (pr->ps_flags & PS_TRACED) == 0) continue; /* * If traced, always stop, and stay stopped until released * by the debugger. If our parent process is waiting for * us, don't hang as we could deadlock. */ if (((pr->ps_flags & (PS_TRACED | PS_PPWAIT)) == PS_TRACED) && signum != SIGKILL) { single_thread_set(p, SINGLE_SUSPEND | SINGLE_NOWAIT); pr->ps_xsig = signum; SCHED_LOCK(s); proc_stop(p, 1); SCHED_UNLOCK(s); /* * re-take the signal before releasing * the other threads. Must check the continue * conditions below and only take the signal if * those are not true. */ signum = pr->ps_xsig; mask = sigmask(signum); setsigctx(p, signum, sctx); if (!((pr->ps_flags & PS_TRACED) == 0 || signum == 0 || (p->p_sigmask & mask) != 0)) { atomic_clearbits_int(&p->p_siglist, mask); atomic_clearbits_int(&pr->ps_siglist, mask); } single_thread_clear(p, 0); /* * If we are no longer being traced, or the parent * didn't give us a signal, look for more signals. */ if ((pr->ps_flags & PS_TRACED) == 0 || signum == 0) continue; /* * If the new signal is being masked, look for other * signals. */ if ((p->p_sigmask & mask) != 0) continue; } prop = sigprop[signum]; /* * Decide whether the signal should be returned. * Return the signal's number, or fall through * to clear it from the pending mask. */ switch ((long)sctx->sig_action) { case (long)SIG_DFL: /* * Don't take default actions on system processes. */ if (pr->ps_pid <= 1) { #ifdef DIAGNOSTIC /* * Are you sure you want to ignore SIGSEGV * in init? XXX */ printf("Process (pid %d) got signal" " %d\n", pr->ps_pid, signum); #endif break; /* == ignore */ } /* * If there is a pending stop signal to process * with default action, stop here, * then clear the signal. However, * if process is member of an orphaned * process group, ignore tty stop signals. */ if (prop & SA_STOP) { if (pr->ps_flags & PS_TRACED || (pr->ps_pgrp->pg_jobc == 0 && prop & SA_TTYSTOP)) break; /* == ignore */ pr->ps_xsig = signum; SCHED_LOCK(s); proc_stop(p, 1); SCHED_UNLOCK(s); break; } else if (prop & SA_IGNORE) { /* * Except for SIGCONT, shouldn't get here. * Default action is to ignore; drop it. */ break; /* == ignore */ } else goto keep; /* NOTREACHED */ case (long)SIG_IGN: /* * Masking above should prevent us ever trying * to take action on an ignored signal other * than SIGCONT, unless process is traced. */ if ((prop & SA_CONT) == 0 && (pr->ps_flags & PS_TRACED) == 0) printf("%s\n", __func__); break; /* == ignore */ default: /* * This signal has an action, let * postsig() process it. */ goto keep; } } /* NOTREACHED */ keep: atomic_setbits_int(&p->p_siglist, mask); /*leave the signal for later */ return (signum); } /* * Put the argument process into the stopped state and notify the parent * via wakeup. Signals are handled elsewhere. The process must not be * on the run queue. */ void proc_stop(struct proc *p, int sw) { struct process *pr = p->p_p; #ifdef MULTIPROCESSOR SCHED_ASSERT_LOCKED(); #endif /* do not stop exiting procs */ if (ISSET(p->p_flag, P_WEXIT)) return; p->p_stat = SSTOP; atomic_clearbits_int(&pr->ps_flags, PS_WAITED); atomic_setbits_int(&pr->ps_flags, PS_STOPPED); atomic_setbits_int(&p->p_flag, P_SUSPSIG); /* * We need this soft interrupt to be handled fast. * Extra calls to softclock don't hurt. */ softintr_schedule(proc_stop_si); if (sw) mi_switch(); } /* * Called from a soft interrupt to send signals to the parents of stopped * processes. * We can't do this in proc_stop because it's called with nasty locks held * and we would need recursive scheduler lock to deal with that. */ void proc_stop_sweep(void *v) { struct process *pr; LIST_FOREACH(pr, &allprocess, ps_list) { if ((pr->ps_flags & PS_STOPPED) == 0) continue; atomic_clearbits_int(&pr->ps_flags, PS_STOPPED); if ((pr->ps_pptr->ps_sigacts->ps_sigflags & SAS_NOCLDSTOP) == 0) prsignal(pr->ps_pptr, SIGCHLD); wakeup(pr->ps_pptr); } } /* * Take the action for the specified signal * from the current set of pending signals. */ void postsig(struct proc *p, int signum, struct sigctx *sctx) { u_long trapno; int mask, returnmask; siginfo_t si; union sigval sigval; int code; KASSERT(signum != 0); mask = sigmask(signum); atomic_clearbits_int(&p->p_siglist, mask); sigval.sival_ptr = NULL; if (p->p_sisig != signum) { trapno = 0; code = SI_USER; sigval.sival_ptr = NULL; } else { trapno = p->p_sitrapno; code = p->p_sicode; sigval = p->p_sigval; } initsiginfo(&si, signum, trapno, code, sigval); #ifdef KTRACE if (KTRPOINT(p, KTR_PSIG)) { ktrpsig(p, signum, sctx->sig_action, p->p_flag & P_SIGSUSPEND ? p->p_oldmask : p->p_sigmask, code, &si); } #endif if (sctx->sig_action == SIG_DFL) { /* * Default action, where the default is to kill * the process. (Other cases were ignored above.) */ KERNEL_LOCK(); sigexit(p, signum); /* NOTREACHED */ } else { /* * If we get here, the signal must be caught. */ #ifdef DIAGNOSTIC if (sctx->sig_action == SIG_IGN || (p->p_sigmask & mask)) panic("postsig action"); #endif /* * Set the new mask value and also defer further * occurrences of this signal. * * Special case: user has done a sigpause. Here the * current mask is not of interest, but rather the * mask from before the sigpause is what we want * restored after the signal processing is completed. */ if (p->p_flag & P_SIGSUSPEND) { atomic_clearbits_int(&p->p_flag, P_SIGSUSPEND); returnmask = p->p_oldmask; } else { returnmask = p->p_sigmask; } if (p->p_sisig == signum) { p->p_sisig = 0; p->p_sitrapno = 0; p->p_sicode = SI_USER; p->p_sigval.sival_ptr = NULL; } if (sendsig(sctx->sig_action, signum, returnmask, &si, sctx->sig_info, sctx->sig_onstack)) { KERNEL_LOCK(); sigexit(p, SIGILL); /* NOTREACHED */ } postsig_done(p, signum, sctx->sig_catchmask, sctx->sig_reset); } } /* * Force the current process to exit with the specified signal, dumping core * if appropriate. We bypass the normal tests for masked and caught signals, * allowing unrecoverable failures to terminate the process without changing * signal state. Mark the accounting record with the signal termination. * If dumping core, save the signal number for the debugger. Calls exit and * does not return. */ void sigexit(struct proc *p, int signum) { /* Mark process as going away */ atomic_setbits_int(&p->p_flag, P_WEXIT); p->p_p->ps_acflag |= AXSIG; if (sigprop[signum] & SA_CORE) { p->p_sisig = signum; /* if there are other threads, pause them */ if (P_HASSIBLING(p)) single_thread_set(p, SINGLE_UNWIND); if (coredump(p) == 0) signum |= WCOREFLAG; } exit1(p, 0, signum, EXIT_NORMAL); /* NOTREACHED */ } /* * Send uncatchable SIGABRT for coredump. */ void sigabort(struct proc *p) { struct sigaction sa; KASSERT(p == curproc || panicstr || db_active); memset(&sa, 0, sizeof sa); sa.sa_handler = SIG_DFL; setsigvec(p, SIGABRT, &sa); CLR(p->p_sigmask, sigmask(SIGABRT)); psignal(p, SIGABRT); } /* * Return 1 if `sig', a given signal, is ignored or masked for `p', a given * thread, and 0 otherwise. */ int sigismasked(struct proc *p, int sig) { struct process *pr = p->p_p; int rv; KASSERT(p == curproc); mtx_enter(&pr->ps_mtx); rv = (pr->ps_sigacts->ps_sigignore & sigmask(sig)) || (p->p_sigmask & sigmask(sig)); mtx_leave(&pr->ps_mtx); return !!rv; } struct coredump_iostate { struct proc *io_proc; struct vnode *io_vp; struct ucred *io_cred; off_t io_offset; }; /* * Dump core, into a file named "progname.core", unless the process was * setuid/setgid. */ int coredump(struct proc *p) { #ifdef SMALL_KERNEL return EPERM; #else struct process *pr = p->p_p; struct vnode *vp; struct ucred *cred = p->p_ucred; struct vmspace *vm = p->p_vmspace; struct nameidata nd; struct vattr vattr; struct coredump_iostate io; int error, len, incrash = 0; char *name; const char *dir = "/var/crash"; atomic_setbits_int(&pr->ps_flags, PS_COREDUMP); #ifdef PMAP_CHECK_COPYIN /* disable copyin checks, so we can write out text sections if needed */ p->p_vmspace->vm_map.check_copyin_count = 0; #endif /* Don't dump if will exceed file size limit. */ if (USPACE + ptoa(vm->vm_dsize + vm->vm_ssize) >= lim_cur(RLIMIT_CORE)) return (EFBIG); name = pool_get(&namei_pool, PR_WAITOK); /* * If the process has inconsistent uids, nosuidcoredump * determines coredump placement policy. */ if (((pr->ps_flags & PS_SUGID) && (error = suser(p))) || ((pr->ps_flags & PS_SUGID) && nosuidcoredump)) { if (nosuidcoredump == 3) { /* * If the program directory does not exist, dumps of * that core will silently fail. */ len = snprintf(name, MAXPATHLEN, "%s/%s/%u.core", dir, pr->ps_comm, pr->ps_pid); incrash = KERNELPATH; } else if (nosuidcoredump == 2) { len = snprintf(name, MAXPATHLEN, "%s/%s.core", dir, pr->ps_comm); incrash = KERNELPATH; } else { pool_put(&namei_pool, name); return (EPERM); } } else len = snprintf(name, MAXPATHLEN, "%s.core", pr->ps_comm); if (len >= MAXPATHLEN) { pool_put(&namei_pool, name); return (EACCES); } /* * Control the UID used to write out. The normal case uses * the real UID. If the sugid case is going to write into the * controlled directory, we do so as root. */ if (incrash == 0) { cred = crdup(cred); cred->cr_uid = cred->cr_ruid; cred->cr_gid = cred->cr_rgid; } else { if (p->p_fd->fd_rdir) { vrele(p->p_fd->fd_rdir); p->p_fd->fd_rdir = NULL; } p->p_ucred = crdup(p->p_ucred); crfree(cred); cred = p->p_ucred; crhold(cred); cred->cr_uid = 0; cred->cr_gid = 0; } /* incrash should be 0 or KERNELPATH only */ NDINIT(&nd, 0, BYPASSUNVEIL | incrash, UIO_SYSSPACE, name, p); error = vn_open(&nd, O_CREAT | FWRITE | O_NOFOLLOW | O_NONBLOCK, S_IRUSR | S_IWUSR); if (error) goto out; /* * Don't dump to non-regular files, files with links, or files * owned by someone else. */ vp = nd.ni_vp; if ((error = VOP_GETATTR(vp, &vattr, cred, p)) != 0) { VOP_UNLOCK(vp); vn_close(vp, FWRITE, cred, p); goto out; } if (vp->v_type != VREG || vattr.va_nlink != 1 || vattr.va_mode & ((VREAD | VWRITE) >> 3 | (VREAD | VWRITE) >> 6) || vattr.va_uid != cred->cr_uid) { error = EACCES; VOP_UNLOCK(vp); vn_close(vp, FWRITE, cred, p); goto out; } VATTR_NULL(&vattr); vattr.va_size = 0; VOP_SETATTR(vp, &vattr, cred, p); pr->ps_acflag |= ACORE; io.io_proc = p; io.io_vp = vp; io.io_cred = cred; io.io_offset = 0; VOP_UNLOCK(vp); vref(vp); error = vn_close(vp, FWRITE, cred, p); if (error == 0) error = coredump_elf(p, &io); vrele(vp); out: crfree(cred); pool_put(&namei_pool, name); return (error); #endif } #ifndef SMALL_KERNEL int coredump_write(void *cookie, enum uio_seg segflg, const void *data, size_t len, int isvnode) { struct coredump_iostate *io = cookie; off_t coffset = 0; size_t csize; int chunk, error; csize = len; do { if (sigmask(SIGKILL) & (io->io_proc->p_siglist | io->io_proc->p_p->ps_siglist)) return (EINTR); /* Rest of the loop sleeps with lock held, so... */ yield(); chunk = MIN(csize, MAXPHYS); error = vn_rdwr(UIO_WRITE, io->io_vp, (caddr_t)data + coffset, chunk, io->io_offset + coffset, segflg, IO_UNIT, io->io_cred, NULL, io->io_proc); if (error && (error != EFAULT || !isvnode)) { struct process *pr = io->io_proc->p_p; if (error == ENOSPC) log(LOG_ERR, "coredump of %s(%d) failed, filesystem full\n", pr->ps_comm, pr->ps_pid); else log(LOG_ERR, "coredump of %s(%d), write failed: errno %d\n", pr->ps_comm, pr->ps_pid, error); return (error); } coffset += chunk; csize -= chunk; } while (csize > 0); io->io_offset += len; return (0); } void coredump_unmap(void *cookie, vaddr_t start, vaddr_t end) { struct coredump_iostate *io = cookie; uvm_unmap(&io->io_proc->p_vmspace->vm_map, start, end); } #endif /* !SMALL_KERNEL */ /* * Nonexistent system call-- signal process (may want to handle it). * Flag error in case process won't see signal immediately (blocked or ignored). */ int sys_nosys(struct proc *p, void *v, register_t *retval) { ptsignal(p, SIGSYS, STHREAD); return (ENOSYS); } int sys___thrsigdivert(struct proc *p, void *v, register_t *retval) { struct sys___thrsigdivert_args /* { syscallarg(sigset_t) sigmask; syscallarg(siginfo_t *) info; syscallarg(const struct timespec *) timeout; } */ *uap = v; struct sigctx ctx; sigset_t mask = SCARG(uap, sigmask) &~ sigcantmask; siginfo_t si; uint64_t nsecs = INFSLP; int timeinvalid = 0; int error = 0; memset(&si, 0, sizeof(si)); if (SCARG(uap, timeout) != NULL) { struct timespec ts; if ((error = copyin(SCARG(uap, timeout), &ts, sizeof(ts))) != 0) return (error); #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrreltimespec(p, &ts); #endif if (!timespecisvalid(&ts)) timeinvalid = 1; else nsecs = TIMESPEC_TO_NSEC(&ts); } dosigsuspend(p, p->p_sigmask &~ mask); for (;;) { si.si_signo = cursig(p, &ctx); if (si.si_signo != 0) { sigset_t smask = sigmask(si.si_signo); if (smask & mask) { atomic_clearbits_int(&p->p_siglist, smask); error = 0; break; } } /* per-POSIX, delay this error until after the above */ if (timeinvalid) error = EINVAL; /* per-POSIX, return immediately if timeout is zero-valued */ if (nsecs == 0) error = EAGAIN; if (error != 0) break; error = tsleep_nsec(&nowake, PPAUSE|PCATCH, "sigwait", nsecs); } if (error == 0) { *retval = si.si_signo; if (SCARG(uap, info) != NULL) { error = copyout(&si, SCARG(uap, info), sizeof(si)); #ifdef KTRACE if (error == 0 && KTRPOINT(p, KTR_STRUCT)) ktrsiginfo(p, &si); #endif } } else if (error == ERESTART && SCARG(uap, timeout) != NULL) { /* * Restarting is wrong if there's a timeout, as it'll be * for the same interval again */ error = EINTR; } return (error); } void initsiginfo(siginfo_t *si, int sig, u_long trapno, int code, union sigval val) { memset(si, 0, sizeof(*si)); si->si_signo = sig; si->si_code = code; if (code == SI_USER) { si->si_value = val; } else { switch (sig) { case SIGSEGV: case SIGILL: case SIGBUS: case SIGFPE: si->si_addr = val.sival_ptr; si->si_trapno = trapno; break; case SIGXFSZ: break; } } } int filt_sigattach(struct knote *kn) { struct process *pr = curproc->p_p; int s; if (kn->kn_id >= NSIG) return EINVAL; kn->kn_ptr.p_process = pr; kn->kn_flags |= EV_CLEAR; /* automatically set */ s = splhigh(); klist_insert_locked(&pr->ps_klist, kn); splx(s); return (0); } void filt_sigdetach(struct knote *kn) { struct process *pr = kn->kn_ptr.p_process; int s; s = splhigh(); klist_remove_locked(&pr->ps_klist, kn); splx(s); } /* * signal knotes are shared with proc knotes, so we apply a mask to * the hint in order to differentiate them from process hints. This * could be avoided by using a signal-specific knote list, but probably * isn't worth the trouble. */ int filt_signal(struct knote *kn, long hint) { if (hint & NOTE_SIGNAL) { hint &= ~NOTE_SIGNAL; if (kn->kn_id == hint) kn->kn_data++; } return (kn->kn_data != 0); } void userret(struct proc *p) { struct sigctx ctx; int signum; if (p->p_flag & P_SUSPSINGLE) single_thread_check(p, 0); /* send SIGPROF or SIGVTALRM if their timers interrupted this thread */ if (p->p_flag & P_PROFPEND) { atomic_clearbits_int(&p->p_flag, P_PROFPEND); KERNEL_LOCK(); psignal(p, SIGPROF); KERNEL_UNLOCK(); } if (p->p_flag & P_ALRMPEND) { atomic_clearbits_int(&p->p_flag, P_ALRMPEND); KERNEL_LOCK(); psignal(p, SIGVTALRM); KERNEL_UNLOCK(); } if (SIGPENDING(p) != 0) { while ((signum = cursig(p, &ctx)) != 0) postsig(p, signum, &ctx); } /* * If P_SIGSUSPEND is still set here, then we still need to restore * the original sigmask before returning to userspace. Also, this * might unmask some pending signals, so we need to check a second * time for signals to post. */ if (p->p_flag & P_SIGSUSPEND) { p->p_sigmask = p->p_oldmask; atomic_clearbits_int(&p->p_flag, P_SIGSUSPEND); while ((signum = cursig(p, &ctx)) != 0) postsig(p, signum, &ctx); } WITNESS_WARN(WARN_PANIC, NULL, "userret: returning"); p->p_cpu->ci_schedstate.spc_curpriority = p->p_usrpri; } int single_thread_check_locked(struct proc *p, int deep) { struct process *pr = p->p_p; int s; MUTEX_ASSERT_LOCKED(&pr->ps_mtx); if (pr->ps_single == NULL || pr->ps_single == p) return (0); do { /* if we're in deep, we need to unwind to the edge */ if (deep) { if (pr->ps_flags & PS_SINGLEUNWIND) return (ERESTART); if (pr->ps_flags & PS_SINGLEEXIT) return (EINTR); } if (pr->ps_flags & PS_SINGLEEXIT) { mtx_leave(&pr->ps_mtx); KERNEL_LOCK(); exit1(p, 0, 0, EXIT_THREAD_NOCHECK); /* NOTREACHED */ } if (--pr->ps_singlecnt == 0) wakeup(&pr->ps_singlecnt); /* not exiting and don't need to unwind, so suspend */ mtx_leave(&pr->ps_mtx); SCHED_LOCK(s); p->p_stat = SSTOP; mi_switch(); SCHED_UNLOCK(s); mtx_enter(&pr->ps_mtx); } while (pr->ps_single != NULL); return (0); } int single_thread_check(struct proc *p, int deep) { int error; mtx_enter(&p->p_p->ps_mtx); error = single_thread_check_locked(p, deep); mtx_leave(&p->p_p->ps_mtx); return error; } /* * Stop other threads in the process. The mode controls how and * where the other threads should stop: * - SINGLE_SUSPEND: stop wherever they are, will later be released (via * single_thread_clear()) * - SINGLE_UNWIND: just unwind to kernel boundary, will be told to exit * (by setting to SINGLE_EXIT) or released as with SINGLE_SUSPEND * - SINGLE_EXIT: unwind to kernel boundary and exit */ int single_thread_set(struct proc *p, int flags) { struct process *pr = p->p_p; struct proc *q; int error, s, mode = flags & SINGLE_MASK; KASSERT(curproc == p); mtx_enter(&pr->ps_mtx); error = single_thread_check_locked(p, flags & SINGLE_DEEP); if (error) { mtx_leave(&pr->ps_mtx); return error; } switch (mode) { case SINGLE_SUSPEND: break; case SINGLE_UNWIND: atomic_setbits_int(&pr->ps_flags, PS_SINGLEUNWIND); break; case SINGLE_EXIT: atomic_setbits_int(&pr->ps_flags, PS_SINGLEEXIT); atomic_clearbits_int(&pr->ps_flags, PS_SINGLEUNWIND); break; #ifdef DIAGNOSTIC default: panic("single_thread_mode = %d", mode); #endif } pr->ps_single = p; pr->ps_singlecnt = pr->ps_threadcnt; TAILQ_FOREACH(q, &pr->ps_threads, p_thr_link) { if (q == p) continue; SCHED_LOCK(s); atomic_setbits_int(&q->p_flag, P_SUSPSINGLE); switch (q->p_stat) { case SIDL: case SDEAD: break; case SSLEEP: /* if it's not interruptible, then just have to wait */ if (q->p_flag & P_SINTR) { /* merely need to suspend? just stop it */ if (mode == SINGLE_SUSPEND) { q->p_stat = SSTOP; --pr->ps_singlecnt; break; } /* need to unwind or exit, so wake it */ unsleep(q); setrunnable(q); } break; case SSTOP: if (mode == SINGLE_EXIT) { unsleep(q); setrunnable(q); } else --pr->ps_singlecnt; break; case SONPROC: signotify(q); /* FALLTHROUGH */ case SRUN: break; } SCHED_UNLOCK(s); } /* count ourselfs out */ --pr->ps_singlecnt; mtx_leave(&pr->ps_mtx); if ((flags & SINGLE_NOWAIT) == 0) single_thread_wait(pr, 1); return 0; } /* * Wait for other threads to stop. If recheck is false then the function * returns non-zero if the caller needs to restart the check else 0 is * returned. If recheck is true the return value is always 0. */ int single_thread_wait(struct process *pr, int recheck) { int wait; /* wait until they're all suspended */ mtx_enter(&pr->ps_mtx); while ((wait = pr->ps_singlecnt > 0)) { msleep_nsec(&pr->ps_singlecnt, &pr->ps_mtx, PWAIT, "suspend", INFSLP); if (!recheck) break; } mtx_leave(&pr->ps_mtx); return wait; } void single_thread_clear(struct proc *p, int flag) { struct process *pr = p->p_p; struct proc *q; int s; KASSERT(pr->ps_single == p); KASSERT(curproc == p); mtx_enter(&pr->ps_mtx); pr->ps_single = NULL; atomic_clearbits_int(&pr->ps_flags, PS_SINGLEUNWIND | PS_SINGLEEXIT); TAILQ_FOREACH(q, &pr->ps_threads, p_thr_link) { if (q == p || (q->p_flag & P_SUSPSINGLE) == 0) continue; atomic_clearbits_int(&q->p_flag, P_SUSPSINGLE); /* * if the thread was only stopped for single threading * then clearing that either makes it runnable or puts * it back into some sleep queue */ SCHED_LOCK(s); if (q->p_stat == SSTOP && (q->p_flag & flag) == 0) { if (q->p_wchan == NULL) setrunnable(q); else { atomic_clearbits_int(&q->p_flag, P_WSLEEP); q->p_stat = SSLEEP; } } SCHED_UNLOCK(s); } mtx_leave(&pr->ps_mtx); } void sigio_del(struct sigiolst *rmlist) { struct sigio *sigio; while ((sigio = LIST_FIRST(rmlist)) != NULL) { LIST_REMOVE(sigio, sio_pgsigio); crfree(sigio->sio_ucred); free(sigio, M_SIGIO, sizeof(*sigio)); } } void sigio_unlink(struct sigio_ref *sir, struct sigiolst *rmlist) { struct sigio *sigio; MUTEX_ASSERT_LOCKED(&sigio_lock); sigio = sir->sir_sigio; if (sigio != NULL) { KASSERT(sigio->sio_myref == sir); sir->sir_sigio = NULL; if (sigio->sio_pgid > 0) sigio->sio_proc = NULL; else sigio->sio_pgrp = NULL; LIST_REMOVE(sigio, sio_pgsigio); LIST_INSERT_HEAD(rmlist, sigio, sio_pgsigio); } } void sigio_free(struct sigio_ref *sir) { struct sigiolst rmlist; if (sir->sir_sigio == NULL) return; LIST_INIT(&rmlist); mtx_enter(&sigio_lock); sigio_unlink(sir, &rmlist); mtx_leave(&sigio_lock); sigio_del(&rmlist); } void sigio_freelist(struct sigiolst *sigiolst) { struct sigiolst rmlist; struct sigio *sigio; if (LIST_EMPTY(sigiolst)) return; LIST_INIT(&rmlist); mtx_enter(&sigio_lock); while ((sigio = LIST_FIRST(sigiolst)) != NULL) sigio_unlink(sigio->sio_myref, &rmlist); mtx_leave(&sigio_lock); sigio_del(&rmlist); } int sigio_setown(struct sigio_ref *sir, u_long cmd, caddr_t data) { struct sigiolst rmlist; struct proc *p = curproc; struct pgrp *pgrp = NULL; struct process *pr = NULL; struct sigio *sigio; int error; pid_t pgid = *(int *)data; if (pgid == 0) { sigio_free(sir); return (0); } if (cmd == TIOCSPGRP) { if (pgid < 0) return (EINVAL); pgid = -pgid; } sigio = malloc(sizeof(*sigio), M_SIGIO, M_WAITOK); sigio->sio_pgid = pgid; sigio->sio_ucred = crhold(p->p_ucred); sigio->sio_myref = sir; LIST_INIT(&rmlist); /* * The kernel lock, and not sleeping between prfind()/pgfind() and * linking of the sigio ensure that the process or process group does * not disappear unexpectedly. */ KERNEL_LOCK(); mtx_enter(&sigio_lock); if (pgid > 0) { pr = prfind(pgid); if (pr == NULL) { error = ESRCH; goto fail; } /* * Policy - Don't allow a process to FSETOWN a process * in another session. * * Remove this test to allow maximum flexibility or * restrict FSETOWN to the current process or process * group for maximum safety. */ if (pr->ps_session != p->p_p->ps_session) { error = EPERM; goto fail; } if ((pr->ps_flags & PS_EXITING) != 0) { error = ESRCH; goto fail; } } else /* if (pgid < 0) */ { pgrp = pgfind(-pgid); if (pgrp == NULL) { error = ESRCH; goto fail; } /* * Policy - Don't allow a process to FSETOWN a process * in another session. * * Remove this test to allow maximum flexibility or * restrict FSETOWN to the current process or process * group for maximum safety. */ if (pgrp->pg_session != p->p_p->ps_session) { error = EPERM; goto fail; } } if (pgid > 0) { sigio->sio_proc = pr; LIST_INSERT_HEAD(&pr->ps_sigiolst, sigio, sio_pgsigio); } else { sigio->sio_pgrp = pgrp; LIST_INSERT_HEAD(&pgrp->pg_sigiolst, sigio, sio_pgsigio); } sigio_unlink(sir, &rmlist); sir->sir_sigio = sigio; mtx_leave(&sigio_lock); KERNEL_UNLOCK(); sigio_del(&rmlist); return (0); fail: mtx_leave(&sigio_lock); KERNEL_UNLOCK(); crfree(sigio->sio_ucred); free(sigio, M_SIGIO, sizeof(*sigio)); return (error); } void sigio_getown(struct sigio_ref *sir, u_long cmd, caddr_t data) { struct sigio *sigio; pid_t pgid = 0; mtx_enter(&sigio_lock); sigio = sir->sir_sigio; if (sigio != NULL) pgid = sigio->sio_pgid; mtx_leave(&sigio_lock); if (cmd == TIOCGPGRP) pgid = -pgid; *(int *)data = pgid; } void sigio_copy(struct sigio_ref *dst, struct sigio_ref *src) { struct sigiolst rmlist; struct sigio *newsigio, *sigio; sigio_free(dst); if (src->sir_sigio == NULL) return; newsigio = malloc(sizeof(*newsigio), M_SIGIO, M_WAITOK); LIST_INIT(&rmlist); mtx_enter(&sigio_lock); sigio = src->sir_sigio; if (sigio == NULL) { mtx_leave(&sigio_lock); free(newsigio, M_SIGIO, sizeof(*newsigio)); return; } newsigio->sio_pgid = sigio->sio_pgid; newsigio->sio_ucred = crhold(sigio->sio_ucred); newsigio->sio_myref = dst; if (newsigio->sio_pgid > 0) { newsigio->sio_proc = sigio->sio_proc; LIST_INSERT_HEAD(&newsigio->sio_proc->ps_sigiolst, newsigio, sio_pgsigio); } else { newsigio->sio_pgrp = sigio->sio_pgrp; LIST_INSERT_HEAD(&newsigio->sio_pgrp->pg_sigiolst, newsigio, sio_pgsigio); } sigio_unlink(dst, &rmlist); dst->sir_sigio = newsigio; mtx_leave(&sigio_lock); sigio_del(&rmlist); }
1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 /* $OpenBSD: _endian.h,v 1.8 2018/01/11 23:13:37 dlg Exp $ */ /*- * Copyright (c) 1997 Niklas Hallqvist. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Internal endianness macros. This pulls in <machine/endian.h> to * get the correct setting direction for the platform and sets internal * ('__' prefix) macros appropriately. */ #ifndef _SYS__ENDIAN_H_ #define _SYS__ENDIAN_H_ #include <sys/_types.h> #define __FROM_SYS__ENDIAN #include <machine/endian.h> #undef __FROM_SYS__ENDIAN #define _LITTLE_ENDIAN 1234 #define _BIG_ENDIAN 4321 #define _PDP_ENDIAN 3412 /* Note that these macros evaluate their arguments several times. */ #define __swap16gen(x) \ (__uint16_t)(((__uint16_t)(x) & 0xffU) << 8 | ((__uint16_t)(x) & 0xff00U) >> 8) #define __swap32gen(x) \ (__uint32_t)(((__uint32_t)(x) & 0xff) << 24 | \ ((__uint32_t)(x) & 0xff00) << 8 | ((__uint32_t)(x) & 0xff0000) >> 8 |\ ((__uint32_t)(x) & 0xff000000) >> 24) #define __swap64gen(x) \ (__uint64_t)((((__uint64_t)(x) & 0xff) << 56) | \ ((__uint64_t)(x) & 0xff00ULL) << 40 | \ ((__uint64_t)(x) & 0xff0000ULL) << 24 | \ ((__uint64_t)(x) & 0xff000000ULL) << 8 | \ ((__uint64_t)(x) & 0xff00000000ULL) >> 8 | \ ((__uint64_t)(x) & 0xff0000000000ULL) >> 24 | \ ((__uint64_t)(x) & 0xff000000000000ULL) >> 40 | \ ((__uint64_t)(x) & 0xff00000000000000ULL) >> 56) #ifndef __HAVE_MD_SWAP static __inline __uint16_t __swap16md(__uint16_t x) { return (__swap16gen(x)); } static __inline __uint32_t __swap32md(__uint32_t x) { return (__swap32gen(x)); } static __inline __uint64_t __swap64md(__uint64_t x) { return (__swap64gen(x)); } #endif #define __swap16(x) \ (__uint16_t)(__builtin_constant_p(x) ? __swap16gen(x) : __swap16md(x)) #define __swap32(x) \ (__uint32_t)(__builtin_constant_p(x) ? __swap32gen(x) : __swap32md(x)) #define __swap64(x) \ (__uint64_t)(__builtin_constant_p(x) ? __swap64gen(x) : __swap64md(x)) #if _BYTE_ORDER == _LITTLE_ENDIAN #define _QUAD_HIGHWORD 1 #define _QUAD_LOWWORD 0 #define __htobe16 __swap16 #define __htobe32 __swap32 #define __htobe64 __swap64 #define __htole16(x) ((__uint16_t)(x)) #define __htole32(x) ((__uint32_t)(x)) #define __htole64(x) ((__uint64_t)(x)) #ifdef _KERNEL #ifdef __HAVE_MD_SWAPIO #define __bemtoh16(_x) __mswap16(_x) #define __bemtoh32(_x) __mswap32(_x) #define __bemtoh64(_x) __mswap64(_x) #define __htobem16(_x, _v) __swapm16((_x), (_v)) #define __htobem32(_x, _v) __swapm32((_x), (_v)) #define __htobem64(_x, _v) __swapm64((_x), (_v)) #endif /* __HAVE_MD_SWAPIO */ #endif /* _KERNEL */ #endif /* _BYTE_ORDER == _LITTLE_ENDIAN */ #if _BYTE_ORDER == _BIG_ENDIAN #define _QUAD_HIGHWORD 0 #define _QUAD_LOWWORD 1 #define __htobe16(x) ((__uint16_t)(x)) #define __htobe32(x) ((__uint32_t)(x)) #define __htobe64(x) ((__uint64_t)(x)) #define __htole16 __swap16 #define __htole32 __swap32 #define __htole64 __swap64 #ifdef _KERNEL #ifdef __HAVE_MD_SWAPIO #define __lemtoh16(_x) __mswap16(_x) #define __lemtoh32(_x) __mswap32(_x) #define __lemtoh64(_x) __mswap64(_x) #define __htolem16(_x, _v) __swapm16((_x), (_v)) #define __htolem32(_x, _v) __swapm32((_x), (_v)) #define __htolem64(_x, _v) __swapm64((_x), (_v)) #endif /* __HAVE_MD_SWAPIO */ #endif /* _KERNEL */ #endif /* _BYTE_ORDER == _BIG_ENDIAN */ #ifdef _KERNEL /* * Fill in the __hto[bl]em{16,32,64} and __[bl]emtoh{16,32,64} macros * that haven't been defined yet */ #ifndef __bemtoh16 #define __bemtoh16(_x) __htobe16(*(__uint16_t *)(_x)) #define __bemtoh32(_x) __htobe32(*(__uint32_t *)(_x)) #define __bemtoh64(_x) __htobe64(*(__uint64_t *)(_x)) #endif #ifndef __htobem16 #define __htobem16(_x, _v) (*(__uint16_t *)(_x) = __htobe16(_v)) #define __htobem32(_x, _v) (*(__uint32_t *)(_x) = __htobe32(_v)) #define __htobem64(_x, _v) (*(__uint64_t *)(_x) = __htobe64(_v)) #endif #ifndef __lemtoh16 #define __lemtoh16(_x) __htole16(*(__uint16_t *)(_x)) #define __lemtoh32(_x) __htole32(*(__uint32_t *)(_x)) #define __lemtoh64(_x) __htole64(*(__uint64_t *)(_x)) #endif #ifndef __htolem16 #define __htolem16(_x, _v) (*(__uint16_t *)(_x) = __htole16(_v)) #define __htolem32(_x, _v) (*(__uint32_t *)(_x) = __htole32(_v)) #define __htolem64(_x, _v) (*(__uint64_t *)(_x) = __htole64(_v)) #endif #endif /* _KERNEL */ #endif /* _SYS__ENDIAN_H_ */
4 1 2 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 /* $OpenBSD: if_pfsync.c,v 1.326 2024/05/24 06:38:41 sashan Exp $ */ /* * Copyright (c) 2002 Michael Shalayeff * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, 2022, 2023 David Gwynne <dlg@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "bpfilter.h" #include "pfsync.h" #include "kstat.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/time.h> #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <sys/timeout.h> #include <sys/kernel.h> #include <sys/sysctl.h> #include <sys/pool.h> #include <sys/syslog.h> #include <sys/tree.h> #include <sys/smr.h> #include <sys/percpu.h> #include <sys/refcnt.h> #include <sys/kstat.h> #include <sys/stdarg.h> #include <net/if.h> #include <net/if_types.h> #include <net/bpf.h> #include <net/netisr.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/if_ether.h> #include <netinet/ip.h> #include <netinet/in_var.h> #include <netinet/ip_var.h> #include <netinet/ip_ipsp.h> #include <netinet/ip_icmp.h> #include <netinet/icmp6.h> #include <netinet/tcp.h> #include <netinet/tcp_seq.h> #include <netinet/tcp_fsm.h> #include <netinet/udp.h> #ifdef INET6 #include <netinet6/in6_var.h> #include <netinet/ip6.h> #include <netinet6/ip6_var.h> #include <netinet6/nd6.h> #endif /* INET6 */ #include "carp.h" #if NCARP > 0 #include <netinet/ip_carp.h> #endif #include <net/pfvar.h> #include <net/pfvar_priv.h> #include <net/if_pfsync.h> #define PFSYNC_MINPKT ( \ sizeof(struct ip) + \ sizeof(struct pfsync_header)) struct pfsync_softc; struct pfsync_deferral { TAILQ_ENTRY(pfsync_deferral) pd_entry; struct pf_state *pd_st; struct mbuf *pd_m; uint64_t pd_deadline; }; TAILQ_HEAD(pfsync_deferrals, pfsync_deferral); #define PFSYNC_DEFER_NSEC 20000000ULL #define PFSYNC_DEFER_LIMIT 128 #define PFSYNC_BULK_SND_IVAL_MS 20 static struct pool pfsync_deferrals_pool; enum pfsync_bulk_req_state { PFSYNC_BREQ_S_NONE, PFSYNC_BREQ_S_START, PFSYNC_BREQ_S_SENT, PFSYNC_BREQ_S_BULK, PFSYNC_BREQ_S_DONE, }; static const char *pfsync_bulk_req_state_names[] = { [PFSYNC_BREQ_S_NONE] = "none", [PFSYNC_BREQ_S_START] = "start", [PFSYNC_BREQ_S_SENT] = "sent", [PFSYNC_BREQ_S_BULK] = "bulk", [PFSYNC_BREQ_S_DONE] = "done", }; enum pfsync_bulk_req_event { PFSYNC_BREQ_EVT_UP, PFSYNC_BREQ_EVT_DOWN, PFSYNC_BREQ_EVT_TMO, PFSYNC_BREQ_EVT_LINK, PFSYNC_BREQ_EVT_BUS_START, PFSYNC_BREQ_EVT_BUS_END, }; static const char *pfsync_bulk_req_event_names[] = { [PFSYNC_BREQ_EVT_UP] = "up", [PFSYNC_BREQ_EVT_DOWN] = "down", [PFSYNC_BREQ_EVT_TMO] = "timeout", [PFSYNC_BREQ_EVT_LINK] = "link", [PFSYNC_BREQ_EVT_BUS_START] = "bus-start", [PFSYNC_BREQ_EVT_BUS_END] = "bus-end", }; struct pfsync_slice { struct pfsync_softc *s_pfsync; struct mutex s_mtx; struct pf_state_queue s_qs[PFSYNC_S_COUNT]; TAILQ_HEAD(, tdb) s_tdb_q; size_t s_len; struct mbuf_list s_ml; struct taskq *s_softnet; struct task s_task; struct timeout s_tmo; struct mbuf_queue s_sendq; struct task s_send; struct pfsync_deferrals s_deferrals; unsigned int s_deferred; struct task s_deferrals_task; struct timeout s_deferrals_tmo; uint64_t s_stat_locks; uint64_t s_stat_contended; uint64_t s_stat_write_nop; uint64_t s_stat_task_add; uint64_t s_stat_task_run; uint64_t s_stat_enqueue; uint64_t s_stat_dequeue; uint64_t s_stat_defer_add; uint64_t s_stat_defer_ack; uint64_t s_stat_defer_run; uint64_t s_stat_defer_overlimit; struct kstat *s_kstat; } __aligned(CACHELINESIZE); #define PFSYNC_SLICE_BITS 1 #define PFSYNC_NSLICES (1 << PFSYNC_SLICE_BITS) struct pfsync_softc { struct ifnet sc_if; unsigned int sc_dead; unsigned int sc_up; struct refcnt sc_refs; /* config */ struct in_addr sc_syncpeer; unsigned int sc_maxupdates; unsigned int sc_defer; /* operation */ unsigned int sc_sync_ifidx; unsigned int sc_sync_if_down; void *sc_inm; struct task sc_ltask; struct task sc_dtask; struct ip sc_template; struct pfsync_slice sc_slices[PFSYNC_NSLICES]; struct { struct rwlock req_lock; struct timeout req_tmo; enum pfsync_bulk_req_state req_state; unsigned int req_tries; unsigned int req_demoted; } sc_bulk_req; struct { struct rwlock snd_lock; struct timeout snd_tmo; time_t snd_requested; struct pf_state *snd_next; struct pf_state *snd_tail; unsigned int snd_again; } sc_bulk_snd; }; static struct pfsync_softc *pfsyncif = NULL; static struct cpumem *pfsynccounters; static inline void pfsyncstat_inc(enum pfsync_counters c) { counters_inc(pfsynccounters, c); } static int pfsync_clone_create(struct if_clone *, int); static int pfsync_clone_destroy(struct ifnet *); static int pfsync_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); static void pfsync_start(struct ifqueue *); static int pfsync_ioctl(struct ifnet *, u_long, caddr_t); static int pfsync_up(struct pfsync_softc *); static int pfsync_down(struct pfsync_softc *); static int pfsync_set_mtu(struct pfsync_softc *, unsigned int); static int pfsync_set_parent(struct pfsync_softc *, const struct if_parent *); static int pfsync_get_parent(struct pfsync_softc *, struct if_parent *); static int pfsync_del_parent(struct pfsync_softc *); static int pfsync_get_ioc(struct pfsync_softc *, struct ifreq *); static int pfsync_set_ioc(struct pfsync_softc *, struct ifreq *); static void pfsync_syncif_link(void *); static void pfsync_syncif_detach(void *); static void pfsync_sendout(struct pfsync_softc *, struct mbuf *); static void pfsync_slice_drop(struct pfsync_softc *, struct pfsync_slice *); static void pfsync_slice_tmo(void *); static void pfsync_slice_task(void *); static void pfsync_slice_sendq(void *); static void pfsync_deferrals_tmo(void *); static void pfsync_deferrals_task(void *); static void pfsync_defer_output(struct pfsync_deferral *); static void pfsync_bulk_req_evt(struct pfsync_softc *, enum pfsync_bulk_req_event); static void pfsync_bulk_req_tmo(void *); static void pfsync_bulk_snd_tmo(void *); #if NKSTAT > 0 struct pfsync_kstat_data { struct kstat_kv pd_locks; struct kstat_kv pd_contended; struct kstat_kv pd_write_nop; struct kstat_kv pd_task_add; struct kstat_kv pd_task_run; struct kstat_kv pd_enqueue; struct kstat_kv pd_dequeue; struct kstat_kv pd_qdrop; struct kstat_kv pd_defer_len; struct kstat_kv pd_defer_add; struct kstat_kv pd_defer_ack; struct kstat_kv pd_defer_run; struct kstat_kv pd_defer_overlimit; }; static const struct pfsync_kstat_data pfsync_kstat_tpl = { KSTAT_KV_INITIALIZER("locks", KSTAT_KV_T_COUNTER64), KSTAT_KV_INITIALIZER("contended", KSTAT_KV_T_COUNTER64), KSTAT_KV_INITIALIZER("write-nops", KSTAT_KV_T_COUNTER64), KSTAT_KV_INITIALIZER("send-sched", KSTAT_KV_T_COUNTER64), KSTAT_KV_INITIALIZER("send-run", KSTAT_KV_T_COUNTER64), KSTAT_KV_INITIALIZER("enqueues", KSTAT_KV_T_COUNTER64), KSTAT_KV_INITIALIZER("dequeues", KSTAT_KV_T_COUNTER64), KSTAT_KV_UNIT_INITIALIZER("qdrops", KSTAT_KV_T_COUNTER32, KSTAT_KV_U_PACKETS), KSTAT_KV_UNIT_INITIALIZER("defer-len", KSTAT_KV_T_COUNTER32, KSTAT_KV_U_PACKETS), KSTAT_KV_INITIALIZER("defer-add", KSTAT_KV_T_COUNTER64), KSTAT_KV_INITIALIZER("defer-ack", KSTAT_KV_T_COUNTER64), KSTAT_KV_INITIALIZER("defer-run", KSTAT_KV_T_COUNTER64), KSTAT_KV_INITIALIZER("defer-over", KSTAT_KV_T_COUNTER64), }; static int pfsync_kstat_copy(struct kstat *ks, void *dst) { struct pfsync_slice *s = ks->ks_softc; struct pfsync_kstat_data *pd = dst; *pd = pfsync_kstat_tpl; kstat_kv_u64(&pd->pd_locks) = s->s_stat_locks; kstat_kv_u64(&pd->pd_contended) = s->s_stat_contended; kstat_kv_u64(&pd->pd_write_nop) = s->s_stat_write_nop; kstat_kv_u64(&pd->pd_task_add) = s->s_stat_task_add; kstat_kv_u64(&pd->pd_task_run) = s->s_stat_task_run; kstat_kv_u64(&pd->pd_enqueue) = s->s_stat_enqueue; kstat_kv_u64(&pd->pd_dequeue) = s->s_stat_dequeue; kstat_kv_u32(&pd->pd_qdrop) = mq_drops(&s->s_sendq); kstat_kv_u32(&pd->pd_defer_len) = s->s_deferred; kstat_kv_u64(&pd->pd_defer_add) = s->s_stat_defer_add; kstat_kv_u64(&pd->pd_defer_ack) = s->s_stat_defer_ack; kstat_kv_u64(&pd->pd_defer_run) = s->s_stat_defer_run; kstat_kv_u64(&pd->pd_defer_overlimit) = s->s_stat_defer_overlimit; return (0); } #endif /* NKSTAT > 0 */ #define PFSYNC_MAX_BULKTRIES 12 struct if_clone pfsync_cloner = IF_CLONE_INITIALIZER("pfsync", pfsync_clone_create, pfsync_clone_destroy); void pfsyncattach(int npfsync) { pfsynccounters = counters_alloc(pfsyncs_ncounters); if_clone_attach(&pfsync_cloner); } static int pfsync_clone_create(struct if_clone *ifc, int unit) { struct pfsync_softc *sc; struct ifnet *ifp; size_t i, q; if (unit != 0) return (ENXIO); if (pfsync_deferrals_pool.pr_size == 0) { pool_init(&pfsync_deferrals_pool, sizeof(struct pfsync_deferral), 0, IPL_MPFLOOR, 0, "pfdefer", NULL); /* pool_cache_init(&pfsync_deferrals_pool); */ } sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO|M_CANFAIL); if (sc == NULL) return (ENOMEM); /* sc_refs is "owned" by IFF_RUNNING */ sc->sc_syncpeer.s_addr = INADDR_PFSYNC_GROUP; sc->sc_maxupdates = 128; sc->sc_defer = 0; task_set(&sc->sc_ltask, pfsync_syncif_link, sc); task_set(&sc->sc_dtask, pfsync_syncif_detach, sc); rw_init(&sc->sc_bulk_req.req_lock, "pfsyncbreq"); /* need process context to take net lock to call ip_output */ timeout_set_proc(&sc->sc_bulk_req.req_tmo, pfsync_bulk_req_tmo, sc); rw_init(&sc->sc_bulk_snd.snd_lock, "pfsyncbsnd"); /* need process context to take net lock to call ip_output */ timeout_set_proc(&sc->sc_bulk_snd.snd_tmo, pfsync_bulk_snd_tmo, sc); ifp = &sc->sc_if; snprintf(ifp->if_xname, sizeof ifp->if_xname, "%s%d", ifc->ifc_name, unit); ifp->if_softc = sc; ifp->if_ioctl = pfsync_ioctl; ifp->if_output = pfsync_output; ifp->if_qstart = pfsync_start; ifp->if_type = IFT_PFSYNC; ifp->if_hdrlen = sizeof(struct pfsync_header); ifp->if_mtu = ETHERMTU; ifp->if_xflags = IFXF_CLONED | IFXF_MPSAFE; for (i = 0; i < nitems(sc->sc_slices); i++) { struct pfsync_slice *s = &sc->sc_slices[i]; s->s_pfsync = sc; mtx_init_flags(&s->s_mtx, IPL_SOFTNET, "pfslice", 0); s->s_softnet = net_tq(i); timeout_set(&s->s_tmo, pfsync_slice_tmo, s); task_set(&s->s_task, pfsync_slice_task, s); mq_init(&s->s_sendq, 16, IPL_SOFTNET); task_set(&s->s_send, pfsync_slice_sendq, s); s->s_len = PFSYNC_MINPKT; ml_init(&s->s_ml); for (q = 0; q < nitems(s->s_qs); q++) TAILQ_INIT(&s->s_qs[q]); TAILQ_INIT(&s->s_tdb_q); /* stupid NET_LOCK */ timeout_set(&s->s_deferrals_tmo, pfsync_deferrals_tmo, s); task_set(&s->s_deferrals_task, pfsync_deferrals_task, s); TAILQ_INIT(&s->s_deferrals); #if NKSTAT > 0 s->s_kstat = kstat_create(ifp->if_xname, 0, "pfsync-slice", i, KSTAT_T_KV, 0); kstat_set_mutex(s->s_kstat, &s->s_mtx); s->s_kstat->ks_softc = s; s->s_kstat->ks_datalen = sizeof(pfsync_kstat_tpl); s->s_kstat->ks_copy = pfsync_kstat_copy; kstat_install(s->s_kstat); #endif } if_counters_alloc(ifp); if_attach(ifp); if_alloc_sadl(ifp); #if NCARP > 0 if_addgroup(ifp, "carp"); #endif #if NBPFILTER > 0 bpfattach(&sc->sc_if.if_bpf, ifp, DLT_PFSYNC, PFSYNC_HDRLEN); #endif return (0); } static int pfsync_clone_destroy(struct ifnet *ifp) { struct pfsync_softc *sc = ifp->if_softc; #if NKSTAT > 0 size_t i; #endif NET_LOCK(); sc->sc_dead = 1; if (ISSET(ifp->if_flags, IFF_RUNNING)) pfsync_down(sc); NET_UNLOCK(); if_detach(ifp); #if NKSTAT > 0 for (i = 0; i < nitems(sc->sc_slices); i++) { struct pfsync_slice *s = &sc->sc_slices[i]; kstat_destroy(s->s_kstat); } #endif free(sc, M_DEVBUF, sizeof(*sc)); return (0); } static void pfsync_dprintf(struct pfsync_softc *sc, const char *fmt, ...) { struct ifnet *ifp = &sc->sc_if; va_list ap; if (!ISSET(ifp->if_flags, IFF_DEBUG)) return; printf("%s: ", ifp->if_xname); va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); printf("\n"); } static void pfsync_syncif_link(void *arg) { struct pfsync_softc *sc = arg; struct ifnet *ifp0; unsigned int sync_if_down = 1; ifp0 = if_get(sc->sc_sync_ifidx); if (ifp0 != NULL && LINK_STATE_IS_UP(ifp0->if_link_state)) { pfsync_bulk_req_evt(sc, PFSYNC_BREQ_EVT_LINK); sync_if_down = 0; } if_put(ifp0); #if NCARP > 0 if (sc->sc_sync_if_down != sync_if_down) { carp_group_demote_adj(&sc->sc_if, sync_if_down ? 1 : -1, "pfsync link"); } #endif sc->sc_sync_if_down = sync_if_down; } static void pfsync_syncif_detach(void *arg) { struct pfsync_softc *sc = arg; struct ifnet *ifp = &sc->sc_if; if (ISSET(ifp->if_flags, IFF_RUNNING)) { pfsync_down(sc); if_down(ifp); } sc->sc_sync_ifidx = 0; } static int pfsync_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) { m_freem(m); /* drop packet */ return (EAFNOSUPPORT); } static int pfsync_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct pfsync_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *)data; int error = ENOTTY; switch (cmd) { case SIOCSIFADDR: error = EOPNOTSUPP; break; case SIOCSIFFLAGS: if (ISSET(ifp->if_flags, IFF_UP)) { if (!ISSET(ifp->if_flags, IFF_RUNNING)) error = pfsync_up(sc); else error = ENETRESET; } else { if (ISSET(ifp->if_flags, IFF_RUNNING)) error = pfsync_down(sc); } break; case SIOCSIFMTU: error = pfsync_set_mtu(sc, ifr->ifr_mtu); break; case SIOCSIFPARENT: error = pfsync_set_parent(sc, (struct if_parent *)data); break; case SIOCGIFPARENT: error = pfsync_get_parent(sc, (struct if_parent *)data); break; case SIOCDIFPARENT: error = pfsync_del_parent(sc); break; case SIOCSETPFSYNC: error = pfsync_set_ioc(sc, ifr); break; case SIOCGETPFSYNC: error = pfsync_get_ioc(sc, ifr); break; default: break; } if (error == ENETRESET) error = 0; return (error); } static int pfsync_set_mtu(struct pfsync_softc *sc, unsigned int mtu) { struct ifnet *ifp = &sc->sc_if; struct ifnet *ifp0; int error = 0; ifp0 = if_get(sc->sc_sync_ifidx); if (ifp0 == NULL) return (EINVAL); if (mtu <= PFSYNC_MINPKT || mtu > ifp0->if_mtu) { error = EINVAL; goto put; } /* commit */ ifp->if_mtu = mtu; put: if_put(ifp0); return (error); } static int pfsync_set_parent(struct pfsync_softc *sc, const struct if_parent *p) { struct ifnet *ifp = &sc->sc_if; struct ifnet *ifp0; int error = 0; ifp0 = if_unit(p->ifp_parent); if (ifp0 == NULL) return (ENXIO); if (ifp0->if_index == sc->sc_sync_ifidx) goto put; if (ISSET(ifp->if_flags, IFF_RUNNING)) { error = EBUSY; goto put; } /* commit */ sc->sc_sync_ifidx = ifp0->if_index; put: if_put(ifp0); return (error); } static int pfsync_get_parent(struct pfsync_softc *sc, struct if_parent *p) { struct ifnet *ifp0; int error = 0; ifp0 = if_get(sc->sc_sync_ifidx); if (ifp0 == NULL) error = EADDRNOTAVAIL; else strlcpy(p->ifp_parent, ifp0->if_xname, sizeof(p->ifp_parent)); if_put(ifp0); return (error); } static int pfsync_del_parent(struct pfsync_softc *sc) { struct ifnet *ifp = &sc->sc_if; if (ISSET(ifp->if_flags, IFF_RUNNING)) return (EBUSY); /* commit */ sc->sc_sync_ifidx = 0; return (0); } static int pfsync_get_ioc(struct pfsync_softc *sc, struct ifreq *ifr) { struct pfsyncreq pfsyncr; struct ifnet *ifp0; memset(&pfsyncr, 0, sizeof(pfsyncr)); ifp0 = if_get(sc->sc_sync_ifidx); if (ifp0 != NULL) { strlcpy(pfsyncr.pfsyncr_syncdev, ifp0->if_xname, sizeof(pfsyncr.pfsyncr_syncdev)); } if_put(ifp0); pfsyncr.pfsyncr_syncpeer = sc->sc_syncpeer; pfsyncr.pfsyncr_maxupdates = sc->sc_maxupdates; pfsyncr.pfsyncr_defer = sc->sc_defer; return (copyout(&pfsyncr, ifr->ifr_data, sizeof(pfsyncr))); } static int pfsync_set_ioc(struct pfsync_softc *sc, struct ifreq *ifr) { struct ifnet *ifp = &sc->sc_if; struct pfsyncreq pfsyncr; unsigned int sync_ifidx = sc->sc_sync_ifidx; int wantdown = 0; int error; error = suser(curproc); if (error != 0) return (error); error = copyin(ifr->ifr_data, &pfsyncr, sizeof(pfsyncr)); if (error != 0) return (error); if (pfsyncr.pfsyncr_maxupdates > 255) return (EINVAL); if (pfsyncr.pfsyncr_syncdev[0] != '\0') { /* set */ struct ifnet *ifp0 = if_unit(pfsyncr.pfsyncr_syncdev); if (ifp0 == NULL) return (ENXIO); if (ifp0->if_index != sync_ifidx) wantdown = 1; sync_ifidx = ifp0->if_index; if_put(ifp0); } else { /* del */ wantdown = 1; sync_ifidx = 0; } if (pfsyncr.pfsyncr_syncpeer.s_addr == INADDR_ANY) pfsyncr.pfsyncr_syncpeer.s_addr = INADDR_PFSYNC_GROUP; if (pfsyncr.pfsyncr_syncpeer.s_addr != sc->sc_syncpeer.s_addr) wantdown = 1; if (wantdown && ISSET(ifp->if_flags, IFF_RUNNING)) return (EBUSY); /* commit */ sc->sc_sync_ifidx = sync_ifidx; sc->sc_syncpeer = pfsyncr.pfsyncr_syncpeer; sc->sc_maxupdates = pfsyncr.pfsyncr_maxupdates; sc->sc_defer = pfsyncr.pfsyncr_defer; return (0); } static int pfsync_up(struct pfsync_softc *sc) { struct ifnet *ifp = &sc->sc_if; struct ifnet *ifp0; void *inm = NULL; int error = 0; struct ip *ip; NET_ASSERT_LOCKED(); KASSERT(!ISSET(ifp->if_flags, IFF_RUNNING)); if (sc->sc_dead) return (ENXIO); /* * coordinate with pfsync_down(). if sc_up is still up and * we're here then something else is tearing pfsync down. */ if (sc->sc_up) return (EBUSY); if (sc->sc_syncpeer.s_addr == INADDR_ANY || sc->sc_syncpeer.s_addr == INADDR_BROADCAST) return (EDESTADDRREQ); ifp0 = if_get(sc->sc_sync_ifidx); if (ifp0 == NULL) return (ENXIO); if (IN_MULTICAST(sc->sc_syncpeer.s_addr)) { if (!ISSET(ifp0->if_flags, IFF_MULTICAST)) { error = ENODEV; goto put; } inm = in_addmulti(&sc->sc_syncpeer, ifp0); if (inm == NULL) { error = ECONNABORTED; goto put; } } sc->sc_up = 1; ip = &sc->sc_template; memset(ip, 0, sizeof(*ip)); ip->ip_v = IPVERSION; ip->ip_hl = sizeof(*ip) >> 2; ip->ip_tos = IPTOS_LOWDELAY; /* len and id are set later */ ip->ip_off = htons(IP_DF); ip->ip_ttl = PFSYNC_DFLTTL; ip->ip_p = IPPROTO_PFSYNC; ip->ip_src.s_addr = INADDR_ANY; ip->ip_dst.s_addr = sc->sc_syncpeer.s_addr; /* commit */ refcnt_init(&sc->sc_refs); /* IFF_RUNNING kind of owns this */ #if NCARP > 0 sc->sc_sync_if_down = 1; carp_group_demote_adj(&sc->sc_if, 1, "pfsync up"); #endif if_linkstatehook_add(ifp0, &sc->sc_ltask); if_detachhook_add(ifp0, &sc->sc_dtask); sc->sc_inm = inm; SET(ifp->if_flags, IFF_RUNNING); pfsync_bulk_req_evt(sc, PFSYNC_BREQ_EVT_UP); refcnt_take(&sc->sc_refs); /* give one to SMR */ SMR_PTR_SET_LOCKED(&pfsyncif, sc); pfsync_syncif_link(sc); /* try and push the bulk req state forward */ put: if_put(ifp0); return (error); } static struct mbuf * pfsync_encap(struct pfsync_softc *sc, struct mbuf *m) { struct { struct ip ip; struct pfsync_header ph; } __packed __aligned(4) *h; unsigned int mlen = m->m_pkthdr.len; m = m_prepend(m, sizeof(*h), M_DONTWAIT); if (m == NULL) return (NULL); h = mtod(m, void *); memset(h, 0, sizeof(*h)); mlen += sizeof(h->ph); h->ph.version = PFSYNC_VERSION; h->ph.len = htons(mlen); /* h->ph.pfcksum */ mlen += sizeof(h->ip); h->ip = sc->sc_template; h->ip.ip_len = htons(mlen); h->ip.ip_id = htons(ip_randomid()); return (m); } static void pfsync_bulk_req_send(struct pfsync_softc *sc) { struct { struct pfsync_subheader subh; struct pfsync_upd_req ur; } __packed __aligned(4) *h; unsigned mlen = max_linkhdr + sizeof(struct ip) + sizeof(struct pfsync_header) + sizeof(*h); struct mbuf *m; m = m_gethdr(M_DONTWAIT, MT_DATA); if (m == NULL) goto fail; if (mlen > MHLEN) { MCLGETL(m, M_DONTWAIT, mlen); if (!ISSET(m->m_flags, M_EXT)) goto drop; } m_align(m, sizeof(*h)); m->m_len = m->m_pkthdr.len = sizeof(*h); h = mtod(m, void *); memset(h, 0, sizeof(*h)); h->subh.action = PFSYNC_ACT_UPD_REQ; h->subh.len = sizeof(h->ur) >> 2; h->subh.count = htons(1); h->ur.id = htobe64(0); h->ur.creatorid = htobe32(0); m = pfsync_encap(sc, m); if (m == NULL) goto fail; pfsync_sendout(sc, m); return; drop: m_freem(m); fail: printf("%s: unable to request bulk update\n", sc->sc_if.if_xname); } static void pfsync_bulk_req_nstate(struct pfsync_softc *sc, enum pfsync_bulk_req_state nstate, int seconds) { sc->sc_bulk_req.req_state = nstate; if (seconds > 0) timeout_add_sec(&sc->sc_bulk_req.req_tmo, seconds); else timeout_del(&sc->sc_bulk_req.req_tmo); } static void pfsync_bulk_req_invstate(struct pfsync_softc *sc, enum pfsync_bulk_req_event evt) { panic("%s: unexpected event %s in state %s", sc->sc_if.if_xname, pfsync_bulk_req_event_names[evt], pfsync_bulk_req_state_names[sc->sc_bulk_req.req_state]); } static void pfsync_bulk_req_nstate_bulk(struct pfsync_softc *sc) { /* calculate the number of packets we expect */ int t = pf_pool_limits[PF_LIMIT_STATES].limit / ((sc->sc_if.if_mtu - PFSYNC_MINPKT) / sizeof(struct pfsync_state)); /* turn it into seconds */ t /= 1000 / PFSYNC_BULK_SND_IVAL_MS; if (t == 0) t = 1; pfsync_bulk_req_nstate(sc, PFSYNC_BREQ_S_BULK, t * 4); } static inline void pfsync_bulk_req_nstate_done(struct pfsync_softc *sc) { pfsync_bulk_req_nstate(sc, PFSYNC_BREQ_S_DONE, 0); KASSERT(sc->sc_bulk_req.req_demoted == 1); sc->sc_bulk_req.req_demoted = 0; #if NCARP > 0 carp_group_demote_adj(&sc->sc_if, -32, "pfsync done"); #endif } static void pfsync_bulk_req_evt(struct pfsync_softc *sc, enum pfsync_bulk_req_event evt) { struct ifnet *ifp = &sc->sc_if; rw_enter_write(&sc->sc_bulk_req.req_lock); pfsync_dprintf(sc, "%s state %s evt %s", __func__, pfsync_bulk_req_state_names[sc->sc_bulk_req.req_state], pfsync_bulk_req_event_names[evt]); if (evt == PFSYNC_BREQ_EVT_DOWN) { /* unconditionally move down */ sc->sc_bulk_req.req_tries = 0; pfsync_bulk_req_nstate(sc, PFSYNC_BREQ_S_NONE, 0); if (sc->sc_bulk_req.req_demoted) { sc->sc_bulk_req.req_demoted = 0; #if NCARP > 0 carp_group_demote_adj(&sc->sc_if, -32, "pfsync down"); #endif } } else switch (sc->sc_bulk_req.req_state) { case PFSYNC_BREQ_S_NONE: switch (evt) { case PFSYNC_BREQ_EVT_UP: KASSERT(sc->sc_bulk_req.req_demoted == 0); sc->sc_bulk_req.req_demoted = 1; #if NCARP > 0 carp_group_demote_adj(&sc->sc_if, 32, "pfsync start"); #endif pfsync_bulk_req_nstate(sc, PFSYNC_BREQ_S_START, 30); break; default: pfsync_bulk_req_invstate(sc, evt); } break; case PFSYNC_BREQ_S_START: switch (evt) { case PFSYNC_BREQ_EVT_LINK: pfsync_bulk_req_send(sc); pfsync_bulk_req_nstate(sc, PFSYNC_BREQ_S_SENT, 2); break; case PFSYNC_BREQ_EVT_TMO: pfsync_dprintf(sc, "timeout waiting for link"); pfsync_bulk_req_nstate_done(sc); break; case PFSYNC_BREQ_EVT_BUS_START: pfsync_bulk_req_nstate_bulk(sc); break; case PFSYNC_BREQ_EVT_BUS_END: /* ignore this */ break; default: pfsync_bulk_req_invstate(sc, evt); } break; case PFSYNC_BREQ_S_SENT: switch (evt) { case PFSYNC_BREQ_EVT_BUS_START: pfsync_bulk_req_nstate_bulk(sc); break; case PFSYNC_BREQ_EVT_BUS_END: case PFSYNC_BREQ_EVT_LINK: /* ignore this */ break; case PFSYNC_BREQ_EVT_TMO: if (++sc->sc_bulk_req.req_tries < PFSYNC_MAX_BULKTRIES) { pfsync_bulk_req_send(sc); pfsync_bulk_req_nstate(sc, PFSYNC_BREQ_S_SENT, 2); break; } pfsync_dprintf(sc, "timeout waiting for bulk transfer start"); pfsync_bulk_req_nstate_done(sc); break; default: pfsync_bulk_req_invstate(sc, evt); } break; case PFSYNC_BREQ_S_BULK: switch (evt) { case PFSYNC_BREQ_EVT_BUS_START: case PFSYNC_BREQ_EVT_LINK: /* ignore this */ break; case PFSYNC_BREQ_EVT_BUS_END: pfsync_bulk_req_nstate_done(sc); break; case PFSYNC_BREQ_EVT_TMO: if (++sc->sc_bulk_req.req_tries < PFSYNC_MAX_BULKTRIES) { pfsync_bulk_req_send(sc); pfsync_bulk_req_nstate(sc, PFSYNC_BREQ_S_SENT, 2); } pfsync_dprintf(sc, "timeout waiting for bulk transfer end"); pfsync_bulk_req_nstate_done(sc); break; default: pfsync_bulk_req_invstate(sc, evt); } break; case PFSYNC_BREQ_S_DONE: /* pfsync is up and running */ switch (evt) { case PFSYNC_BREQ_EVT_BUS_START: case PFSYNC_BREQ_EVT_BUS_END: case PFSYNC_BREQ_EVT_LINK: /* nops */ break; default: pfsync_bulk_req_invstate(sc, evt); } break; default: panic("%s: unknown event %d", ifp->if_xname, evt); /* NOTREACHED */ } rw_exit_write(&sc->sc_bulk_req.req_lock); } static void pfsync_bulk_req_tmo(void *arg) { struct pfsync_softc *sc = arg; NET_LOCK(); pfsync_bulk_req_evt(sc, PFSYNC_BREQ_EVT_TMO); NET_UNLOCK(); } static int pfsync_down(struct pfsync_softc *sc) { struct ifnet *ifp = &sc->sc_if; struct ifnet *ifp0; struct smr_entry smr; size_t i; void *inm = NULL; unsigned int sndbar = 0; struct pfsync_deferrals pds = TAILQ_HEAD_INITIALIZER(pds); struct pfsync_deferral *pd; NET_ASSERT_LOCKED(); KASSERT(ISSET(ifp->if_flags, IFF_RUNNING)); /* * tearing down pfsync involves waiting for pfsync to stop * running in various contexts including softnet taskqs. * this thread cannot hold netlock while waiting for a * barrier in softnet because softnet might be waiting for * the netlock. sc->sc_up is used to coordinate with * pfsync_up. */ CLR(ifp->if_flags, IFF_RUNNING); ifp0 = if_get(sc->sc_sync_ifidx); if (ifp0 != NULL) { if_linkstatehook_del(ifp0, &sc->sc_ltask); if_detachhook_del(ifp0, &sc->sc_dtask); } if_put(ifp0); #if NCARP > 0 if (sc->sc_sync_if_down) carp_group_demote_adj(&sc->sc_if, -1, "pfsync down"); #endif NET_UNLOCK(); KASSERTMSG(SMR_PTR_GET_LOCKED(&pfsyncif) == sc, "pfsyncif %p != sc %p", pfsyncif, sc); SMR_PTR_SET_LOCKED(&pfsyncif, NULL); smr_init(&smr); smr_call(&smr, (void (*)(void *))refcnt_rele_wake, &sc->sc_refs); /* stop pf producing work before cleaning up the timeouts and tasks */ refcnt_finalize(&sc->sc_refs, "pfsyncfini"); pfsync_bulk_req_evt(sc, PFSYNC_BREQ_EVT_DOWN); rw_enter_read(&pf_state_list.pfs_rwl); rw_enter_write(&sc->sc_bulk_snd.snd_lock); if (sc->sc_bulk_snd.snd_tail != NULL) { sndbar = !timeout_del(&sc->sc_bulk_snd.snd_tmo); sc->sc_bulk_snd.snd_again = 0; sc->sc_bulk_snd.snd_next = NULL; sc->sc_bulk_snd.snd_tail = NULL; } rw_exit_write(&sc->sc_bulk_snd.snd_lock); rw_exit_read(&pf_state_list.pfs_rwl); /* * do a single barrier for all the timeouts. because the * timeouts in each slice are configured the same way, the * barrier for one will work for all of them. */ for (i = 0; i < nitems(sc->sc_slices); i++) { struct pfsync_slice *s = &sc->sc_slices[i]; timeout_del(&s->s_tmo); task_del(s->s_softnet, &s->s_task); task_del(s->s_softnet, &s->s_send); timeout_del(&s->s_deferrals_tmo); task_del(s->s_softnet, &s->s_deferrals_task); } timeout_barrier(&sc->sc_slices[0].s_tmo); timeout_barrier(&sc->sc_bulk_req.req_tmo); /* XXX proc */ if (sndbar) { /* technically the preceding barrier does the same job */ timeout_barrier(&sc->sc_bulk_snd.snd_tmo); } net_tq_barriers("pfsyncbar"); /* pfsync is no longer running */ if (sc->sc_inm != NULL) { inm = sc->sc_inm; sc->sc_inm = NULL; } for (i = 0; i < nitems(sc->sc_slices); i++) { struct pfsync_slice *s = &sc->sc_slices[i]; struct pf_state *st; pfsync_slice_drop(sc, s); mq_purge(&s->s_sendq); while ((pd = TAILQ_FIRST(&s->s_deferrals)) != NULL) { TAILQ_REMOVE(&s->s_deferrals, pd, pd_entry); st = pd->pd_st; st->sync_defer = NULL; TAILQ_INSERT_TAIL(&pds, pd, pd_entry); } s->s_deferred = 0; } NET_LOCK(); sc->sc_up = 0; if (inm != NULL) in_delmulti(inm); while ((pd = TAILQ_FIRST(&pds)) != NULL) { TAILQ_REMOVE(&pds, pd, pd_entry); pfsync_defer_output(pd); } return (0); } int pfsync_is_up(void) { int rv; smr_read_enter(); rv = SMR_PTR_GET(&pfsyncif) != NULL; smr_read_leave(); return (rv); } static void pfsync_start(struct ifqueue *ifq) { ifq_purge(ifq); } struct pfsync_q { void (*write)(struct pf_state *, void *); size_t len; u_int8_t action; }; static struct pfsync_slice * pfsync_slice_enter(struct pfsync_softc *sc, const struct pf_state *st) { unsigned int idx = st->key[0]->hash % nitems(sc->sc_slices); struct pfsync_slice *s = &sc->sc_slices[idx]; if (!mtx_enter_try(&s->s_mtx)) { mtx_enter(&s->s_mtx); s->s_stat_contended++; } s->s_stat_locks++; return (s); } static void pfsync_slice_leave(struct pfsync_softc *sc, struct pfsync_slice *s) { mtx_leave(&s->s_mtx); } /* we have one of these for every PFSYNC_S_ */ static void pfsync_out_state(struct pf_state *, void *); static void pfsync_out_iack(struct pf_state *, void *); static void pfsync_out_upd_c(struct pf_state *, void *); static void pfsync_out_del(struct pf_state *, void *); #if defined(IPSEC) static void pfsync_out_tdb(struct tdb *, void *); #endif static const struct pfsync_q pfsync_qs[] = { { pfsync_out_iack, sizeof(struct pfsync_ins_ack), PFSYNC_ACT_INS_ACK }, { pfsync_out_upd_c, sizeof(struct pfsync_upd_c), PFSYNC_ACT_UPD_C }, { pfsync_out_del, sizeof(struct pfsync_del_c), PFSYNC_ACT_DEL_C }, { pfsync_out_state, sizeof(struct pfsync_state), PFSYNC_ACT_INS }, { pfsync_out_state, sizeof(struct pfsync_state), PFSYNC_ACT_UPD } }; static void pfsync_out_state(struct pf_state *st, void *buf) { struct pfsync_state *sp = buf; mtx_enter(&st->mtx); pf_state_export(sp, st); mtx_leave(&st->mtx); } static void pfsync_out_iack(struct pf_state *st, void *buf) { struct pfsync_ins_ack *iack = buf; iack->id = st->id; iack->creatorid = st->creatorid; } static void pfsync_out_upd_c(struct pf_state *st, void *buf) { struct pfsync_upd_c *up = buf; memset(up, 0, sizeof(*up)); up->id = st->id; up->creatorid = st->creatorid; mtx_enter(&st->mtx); pf_state_peer_hton(&st->src, &up->src); pf_state_peer_hton(&st->dst, &up->dst); up->timeout = st->timeout; mtx_leave(&st->mtx); } static void pfsync_out_del(struct pf_state *st, void *buf) { struct pfsync_del_c *dp = buf; dp->id = st->id; dp->creatorid = st->creatorid; st->sync_state = PFSYNC_S_DEAD; } #if defined(IPSEC) static inline void pfsync_tdb_enter(struct tdb *tdb) { mtx_enter(&tdb->tdb_mtx); } static inline void pfsync_tdb_leave(struct tdb *tdb) { unsigned int snapped = ISSET(tdb->tdb_flags, TDBF_PFSYNC_SNAPPED); mtx_leave(&tdb->tdb_mtx); if (snapped) wakeup_one(&tdb->tdb_updates); } #endif /* defined(IPSEC) */ static void pfsync_slice_drop(struct pfsync_softc *sc, struct pfsync_slice *s) { struct pf_state *st; int q; #if defined(IPSEC) struct tdb *tdb; #endif for (q = 0; q < nitems(s->s_qs); q++) { if (TAILQ_EMPTY(&s->s_qs[q])) continue; while ((st = TAILQ_FIRST(&s->s_qs[q])) != NULL) { TAILQ_REMOVE(&s->s_qs[q], st, sync_list); #ifdef PFSYNC_DEBUG KASSERT(st->sync_state == q); #endif st->sync_state = PFSYNC_S_NONE; pf_state_unref(st); } } #if defined(IPSEC) while ((tdb = TAILQ_FIRST(&s->s_tdb_q)) != NULL) { TAILQ_REMOVE(&s->s_tdb_q, tdb, tdb_sync_entry); pfsync_tdb_enter(tdb); KASSERT(ISSET(tdb->tdb_flags, TDBF_PFSYNC)); CLR(tdb->tdb_flags, TDBF_PFSYNC); pfsync_tdb_leave(tdb); } #endif /* defined(IPSEC) */ timeout_del(&s->s_tmo); s->s_len = PFSYNC_MINPKT; } static struct mbuf * pfsync_slice_write(struct pfsync_slice *s) { struct pfsync_softc *sc = s->s_pfsync; struct mbuf *m; struct ip *ip; struct pfsync_header *ph; struct pfsync_subheader *subh; unsigned int mlen = max_linkhdr + s->s_len; unsigned int q, count; caddr_t ptr; size_t off; MUTEX_ASSERT_LOCKED(&s->s_mtx); if (s->s_len == PFSYNC_MINPKT) { s->s_stat_write_nop++; return (NULL); } task_del(s->s_softnet, &s->s_task); m = m_gethdr(M_DONTWAIT, MT_DATA); if (m == NULL) goto drop; if (mlen > MHLEN) { MCLGETL(m, M_DONTWAIT, mlen); if (!ISSET(m->m_flags, M_EXT)) goto drop; } m_align(m, s->s_len); m->m_len = m->m_pkthdr.len = s->s_len; ptr = mtod(m, caddr_t); off = 0; ip = (struct ip *)(ptr + off); off += sizeof(*ip); *ip = sc->sc_template; ip->ip_len = htons(m->m_pkthdr.len); ip->ip_id = htons(ip_randomid()); ph = (struct pfsync_header *)(ptr + off); off += sizeof(*ph); memset(ph, 0, sizeof(*ph)); ph->version = PFSYNC_VERSION; ph->len = htons(m->m_pkthdr.len - sizeof(*ip)); for (q = 0; q < nitems(s->s_qs); q++) { struct pf_state_queue *psq = &s->s_qs[q]; struct pf_state *st; if (TAILQ_EMPTY(psq)) continue; subh = (struct pfsync_subheader *)(ptr + off); off += sizeof(*subh); count = 0; while ((st = TAILQ_FIRST(psq)) != NULL) { TAILQ_REMOVE(psq, st, sync_list); count++; KASSERT(st->sync_state == q); /* the write handler below may override this */ st->sync_state = PFSYNC_S_NONE; pfsync_qs[q].write(st, ptr + off); off += pfsync_qs[q].len; pf_state_unref(st); } subh->action = pfsync_qs[q].action; subh->len = pfsync_qs[q].len >> 2; subh->count = htons(count); } #if defined(IPSEC) if (!TAILQ_EMPTY(&s->s_tdb_q)) { struct tdb *tdb; subh = (struct pfsync_subheader *)(ptr + off); off += sizeof(*subh); count = 0; while ((tdb = TAILQ_FIRST(&s->s_tdb_q)) != NULL) { TAILQ_REMOVE(&s->s_tdb_q, tdb, tdb_sync_entry); count++; pfsync_tdb_enter(tdb); KASSERT(ISSET(tdb->tdb_flags, TDBF_PFSYNC)); /* get a consistent view of the counters */ pfsync_out_tdb(tdb, ptr + off); CLR(tdb->tdb_flags, TDBF_PFSYNC); pfsync_tdb_leave(tdb); off += sizeof(struct pfsync_tdb); } subh->action = PFSYNC_ACT_TDB; subh->len = sizeof(struct pfsync_tdb) >> 2; subh->count = htons(count); } #endif timeout_del(&s->s_tmo); s->s_len = PFSYNC_MINPKT; return (m); drop: m_freem(m); pfsyncstat_inc(pfsyncs_onomem); pfsync_slice_drop(sc, s); return (NULL); } static void pfsync_sendout(struct pfsync_softc *sc, struct mbuf *m) { struct ip_moptions imo; unsigned int len = m->m_pkthdr.len; #if NBPFILTER > 0 caddr_t if_bpf = sc->sc_if.if_bpf; if (if_bpf) bpf_mtap(if_bpf, m, BPF_DIRECTION_OUT); #endif imo.imo_ifidx = sc->sc_sync_ifidx; imo.imo_ttl = PFSYNC_DFLTTL; imo.imo_loop = 0; m->m_pkthdr.ph_rtableid = sc->sc_if.if_rdomain; if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &imo, NULL, 0) == 0) { counters_pkt(sc->sc_if.if_counters, ifc_opackets, ifc_obytes, len); pfsyncstat_inc(pfsyncs_opackets); } else { counters_inc(sc->sc_if.if_counters, ifc_oerrors); pfsyncstat_inc(pfsyncs_oerrors); } } static void pfsync_slice_tmo(void *arg) { struct pfsync_slice *s = arg; task_add(s->s_softnet, &s->s_task); } static void pfsync_slice_sched(struct pfsync_slice *s) { s->s_stat_task_add++; task_add(s->s_softnet, &s->s_task); } static void pfsync_slice_task(void *arg) { struct pfsync_slice *s = arg; struct mbuf *m; mtx_enter(&s->s_mtx); s->s_stat_task_run++; m = pfsync_slice_write(s); mtx_leave(&s->s_mtx); if (m != NULL) { NET_LOCK(); pfsync_sendout(s->s_pfsync, m); NET_UNLOCK(); } } static void pfsync_slice_sendq(void *arg) { struct pfsync_slice *s = arg; struct mbuf_list ml; struct mbuf *m; mq_delist(&s->s_sendq, &ml); if (ml_empty(&ml)) return; mtx_enter(&s->s_mtx); s->s_stat_dequeue++; mtx_leave(&s->s_mtx); NET_LOCK(); while ((m = ml_dequeue(&ml)) != NULL) pfsync_sendout(s->s_pfsync, m); NET_UNLOCK(); } static void pfsync_q_ins(struct pfsync_slice *s, struct pf_state *st, unsigned int q) { size_t nlen = pfsync_qs[q].len; struct mbuf *m = NULL; MUTEX_ASSERT_LOCKED(&s->s_mtx); KASSERT(st->sync_state == PFSYNC_S_NONE); KASSERT(s->s_len >= PFSYNC_MINPKT); if (TAILQ_EMPTY(&s->s_qs[q])) nlen += sizeof(struct pfsync_subheader); if (s->s_len + nlen > s->s_pfsync->sc_if.if_mtu) { m = pfsync_slice_write(s); if (m != NULL) { s->s_stat_enqueue++; if (mq_enqueue(&s->s_sendq, m) == 0) task_add(s->s_softnet, &s->s_send); } nlen = sizeof(struct pfsync_subheader) + pfsync_qs[q].len; } s->s_len += nlen; pf_state_ref(st); TAILQ_INSERT_TAIL(&s->s_qs[q], st, sync_list); st->sync_state = q; if (!timeout_pending(&s->s_tmo)) timeout_add_sec(&s->s_tmo, 1); } static void pfsync_q_del(struct pfsync_slice *s, struct pf_state *st) { unsigned int q = st->sync_state; MUTEX_ASSERT_LOCKED(&s->s_mtx); KASSERT(st->sync_state < PFSYNC_S_NONE); st->sync_state = PFSYNC_S_NONE; TAILQ_REMOVE(&s->s_qs[q], st, sync_list); pf_state_unref(st); s->s_len -= pfsync_qs[q].len; if (TAILQ_EMPTY(&s->s_qs[q])) s->s_len -= sizeof(struct pfsync_subheader); } /* * the pfsync hooks that pf calls */ void pfsync_init_state(struct pf_state *st, const struct pf_state_key *skw, const struct pf_state_key *sks, int flags) { /* this is called before pf_state_insert */ if (skw->proto == IPPROTO_PFSYNC) SET(st->state_flags, PFSTATE_NOSYNC); if (ISSET(st->state_flags, PFSTATE_NOSYNC)) { st->sync_state = PFSYNC_S_DEAD; return; } if (ISSET(flags, PFSYNC_SI_IOCTL)) { /* all good */ return; } /* state came off the wire */ if (ISSET(flags, PFSYNC_SI_PFSYNC)) { if (ISSET(st->state_flags, PFSTATE_ACK)) { CLR(st->state_flags, PFSTATE_ACK); /* peer wants an iack, not an insert */ st->sync_state = PFSYNC_S_SYNC; } else st->sync_state = PFSYNC_S_PFSYNC; } } void pfsync_insert_state(struct pf_state *st) { struct pfsync_softc *sc; MUTEX_ASSERT_UNLOCKED(&st->mtx); if (ISSET(st->state_flags, PFSTATE_NOSYNC) || st->sync_state == PFSYNC_S_DEAD) return; smr_read_enter(); sc = SMR_PTR_GET(&pfsyncif); if (sc != NULL) { struct pfsync_slice *s = pfsync_slice_enter(sc, st); switch (st->sync_state) { case PFSYNC_S_UPD_C: /* we must have lost a race after insert */ pfsync_q_del(s, st); /* FALLTHROUGH */ case PFSYNC_S_NONE: pfsync_q_ins(s, st, PFSYNC_S_INS); break; case PFSYNC_S_SYNC: st->sync_state = PFSYNC_S_NONE; /* gross */ pfsync_q_ins(s, st, PFSYNC_S_IACK); pfsync_slice_sched(s); /* the peer is waiting */ break; case PFSYNC_S_PFSYNC: /* state was just inserted by pfsync */ st->sync_state = PFSYNC_S_NONE; break; default: panic("%s: state %p unexpected sync_state %d", __func__, st, st->sync_state); /* NOTREACHED */ } pfsync_slice_leave(sc, s); } smr_read_leave(); } void pfsync_update_state(struct pf_state *st) { struct pfsync_softc *sc; MUTEX_ASSERT_UNLOCKED(&st->mtx); if (ISSET(st->state_flags, PFSTATE_NOSYNC) || st->sync_state == PFSYNC_S_DEAD) return; smr_read_enter(); sc = SMR_PTR_GET(&pfsyncif); if (sc != NULL) { struct pfsync_slice *s = pfsync_slice_enter(sc, st); int sync = 0; switch (st->sync_state) { case PFSYNC_S_UPD_C: case PFSYNC_S_UPD: /* we're already handling it */ if (st->key[PF_SK_WIRE]->proto == IPPROTO_TCP) { st->sync_updates++; if (st->sync_updates >= sc->sc_maxupdates) sync = 1; } /* FALLTHROUGH */ case PFSYNC_S_INS: case PFSYNC_S_DEL: case PFSYNC_S_DEAD: break; case PFSYNC_S_IACK: pfsync_q_del(s, st); /* FALLTHROUGH */ case PFSYNC_S_NONE: pfsync_q_ins(s, st, PFSYNC_S_UPD_C); st->sync_updates = 0; break; default: panic("%s: state %p unexpected sync_state %d", __func__, st, st->sync_state); /* NOTREACHED */ } if (!sync && (getuptime() - st->pfsync_time) < 2) sync = 1; if (sync) pfsync_slice_sched(s); pfsync_slice_leave(sc, s); } smr_read_leave(); } void pfsync_delete_state(struct pf_state *st) { struct pfsync_softc *sc; MUTEX_ASSERT_UNLOCKED(&st->mtx); if (ISSET(st->state_flags, PFSTATE_NOSYNC) || st->sync_state == PFSYNC_S_DEAD) return; smr_read_enter(); sc = SMR_PTR_GET(&pfsyncif); if (sc != NULL) { struct pfsync_slice *s = pfsync_slice_enter(sc, st); switch (st->sync_state) { case PFSYNC_S_INS: /* let's pretend this never happened */ pfsync_q_del(s, st); break; case PFSYNC_S_UPD_C: case PFSYNC_S_UPD: case PFSYNC_S_IACK: pfsync_q_del(s, st); /* FALLTHROUGH */ case PFSYNC_S_NONE: pfsync_q_ins(s, st, PFSYNC_S_DEL); st->sync_updates = 0; break; case PFSYNC_S_DEL: case PFSYNC_S_DEAD: /* XXX we should count this */ break; default: panic("%s: state %p unexpected sync_state %d", __func__, st, st->sync_state); /* NOTREACHED */ } pfsync_slice_leave(sc, s); } smr_read_leave(); } struct pfsync_subh_clr { struct pfsync_subheader subh; struct pfsync_clr clr; } __packed __aligned(4); void pfsync_clear_states(u_int32_t creatorid, const char *ifname) { struct pfsync_softc *sc; struct pfsync_subh_clr *h; struct mbuf *m; unsigned int hlen, mlen; smr_read_enter(); sc = SMR_PTR_GET(&pfsyncif); if (sc != NULL) refcnt_take(&sc->sc_refs); smr_read_leave(); if (sc == NULL) return; hlen = sizeof(sc->sc_template) + sizeof(struct pfsync_header) + sizeof(*h); mlen = max_linkhdr + hlen; m = m_gethdr(M_DONTWAIT, MT_DATA); if (m == NULL) { /* count error */ goto leave; } if (mlen > MHLEN) { MCLGETL(m, M_DONTWAIT, mlen); if (!ISSET(m->m_flags, M_EXT)) { m_freem(m); goto leave; } } m_align(m, sizeof(*h)); h = mtod(m, struct pfsync_subh_clr *); h->subh.action = PFSYNC_ACT_CLR; h->subh.len = sizeof(h->clr) >> 2; h->subh.count = htons(1); strlcpy(h->clr.ifname, ifname, sizeof(h->clr.ifname)); h->clr.creatorid = creatorid; m->m_pkthdr.len = m->m_len = sizeof(*h); m = pfsync_encap(sc, m); if (m == NULL) goto leave; pfsync_sendout(sc, m); leave: refcnt_rele_wake(&sc->sc_refs); } int pfsync_state_in_use(struct pf_state *st) { struct pfsync_softc *sc; int rv = 0; smr_read_enter(); sc = SMR_PTR_GET(&pfsyncif); if (sc != NULL) { /* * pfsync bulk sends run inside * rw_enter_read(&pf_state_list.pfs_rwl), and this * code (pfsync_state_in_use) is only called from the * purge code inside * rw_enter_write(&pf_state_list.pfs_rwl). therefore, * those two sections are exclusive so we can safely * look at the bulk send pointers. */ /* rw_assert_wrlock(&pf_state_list.pfs_rwl); */ if (sc->sc_bulk_snd.snd_next == st || sc->sc_bulk_snd.snd_tail == st) rv = 1; } smr_read_leave(); return (rv); } int pfsync_defer(struct pf_state *st, struct mbuf *m) { struct pfsync_softc *sc; struct pfsync_slice *s; struct pfsync_deferral *pd; int sched = 0; int rv = 0; if (ISSET(st->state_flags, PFSTATE_NOSYNC) || ISSET(m->m_flags, M_BCAST|M_MCAST)) return (0); smr_read_enter(); sc = SMR_PTR_GET(&pfsyncif); if (sc == NULL || !sc->sc_defer) goto leave; pd = pool_get(&pfsync_deferrals_pool, M_NOWAIT); if (pd == NULL) { goto leave; } s = pfsync_slice_enter(sc, st); s->s_stat_defer_add++; pd->pd_st = pf_state_ref(st); pd->pd_m = m; pd->pd_deadline = getnsecuptime() + PFSYNC_DEFER_NSEC; m->m_pkthdr.pf.flags |= PF_TAG_GENERATED; st->sync_defer = pd; sched = s->s_deferred++; TAILQ_INSERT_TAIL(&s->s_deferrals, pd, pd_entry); if (sched == 0) timeout_add_nsec(&s->s_deferrals_tmo, PFSYNC_DEFER_NSEC); else if (sched >= PFSYNC_DEFER_LIMIT) { s->s_stat_defer_overlimit++; timeout_del(&s->s_deferrals_tmo); task_add(s->s_softnet, &s->s_deferrals_task); } pfsync_slice_sched(s); pfsync_slice_leave(sc, s); rv = 1; leave: smr_read_leave(); return (rv); } static void pfsync_deferred(struct pfsync_softc *sc, struct pf_state *st) { struct pfsync_slice *s; struct pfsync_deferral *pd; s = pfsync_slice_enter(sc, st); pd = st->sync_defer; if (pd != NULL) { s->s_stat_defer_ack++; TAILQ_REMOVE(&s->s_deferrals, pd, pd_entry); s->s_deferred--; st = pd->pd_st; st->sync_defer = NULL; } pfsync_slice_leave(sc, s); if (pd != NULL) pfsync_defer_output(pd); } static void pfsync_deferrals_tmo(void *arg) { struct pfsync_slice *s = arg; if (READ_ONCE(s->s_deferred) > 0) task_add(s->s_softnet, &s->s_deferrals_task); } static void pfsync_deferrals_task(void *arg) { struct pfsync_slice *s = arg; struct pfsync_deferral *pd; struct pf_state *st; uint64_t now, nsec = 0; struct pfsync_deferrals pds = TAILQ_HEAD_INITIALIZER(pds); now = getnsecuptime(); mtx_enter(&s->s_mtx); s->s_stat_defer_run++; /* maybe move this into the loop */ for (;;) { pd = TAILQ_FIRST(&s->s_deferrals); if (pd == NULL) break; if (s->s_deferred < PFSYNC_DEFER_LIMIT && now < pd->pd_deadline) { nsec = pd->pd_deadline - now; break; } TAILQ_REMOVE(&s->s_deferrals, pd, pd_entry); s->s_deferred--; /* * detach the pd from the state. the pd still refers * to the state though. */ st = pd->pd_st; st->sync_defer = NULL; TAILQ_INSERT_TAIL(&pds, pd, pd_entry); } mtx_leave(&s->s_mtx); if (nsec > 0) { /* we were looking at a pd, but it wasn't old enough */ timeout_add_nsec(&s->s_deferrals_tmo, nsec); } if (TAILQ_EMPTY(&pds)) return; NET_LOCK(); while ((pd = TAILQ_FIRST(&pds)) != NULL) { TAILQ_REMOVE(&pds, pd, pd_entry); pfsync_defer_output(pd); } NET_UNLOCK(); } static void pfsync_defer_output(struct pfsync_deferral *pd) { struct pf_pdesc pdesc; struct pf_state *st = pd->pd_st; if (st->rt == PF_ROUTETO) { if (pf_setup_pdesc(&pdesc, st->key[PF_SK_WIRE]->af, st->direction, NULL, pd->pd_m, NULL) != PF_PASS) return; switch (st->key[PF_SK_WIRE]->af) { case AF_INET: pf_route(&pdesc, st); break; #ifdef INET6 case AF_INET6: pf_route6(&pdesc, st); break; #endif /* INET6 */ default: unhandled_af(st->key[PF_SK_WIRE]->af); } pd->pd_m = pdesc.m; } else { switch (st->key[PF_SK_WIRE]->af) { case AF_INET: ip_output(pd->pd_m, NULL, NULL, 0, NULL, NULL, 0); break; #ifdef INET6 case AF_INET6: ip6_output(pd->pd_m, NULL, NULL, 0, NULL, NULL); break; #endif /* INET6 */ default: unhandled_af(st->key[PF_SK_WIRE]->af); } pd->pd_m = NULL; } pf_state_unref(st); m_freem(pd->pd_m); pool_put(&pfsync_deferrals_pool, pd); } struct pfsync_subh_bus { struct pfsync_subheader subh; struct pfsync_bus bus; } __packed __aligned(4); static unsigned int pfsync_bulk_snd_bus(struct pfsync_softc *sc, struct mbuf *m, const unsigned int space, uint32_t endtime, uint8_t status) { struct pfsync_subh_bus *h; unsigned int nlen; nlen = m->m_len + sizeof(*h); if (space < nlen) return (0); h = (struct pfsync_subh_bus *)(mtod(m, caddr_t) + m->m_len); memset(h, 0, sizeof(*h)); h->subh.action = PFSYNC_ACT_BUS; h->subh.len = sizeof(h->bus) >> 2; h->subh.count = htons(1); h->bus.creatorid = pf_status.hostid; h->bus.endtime = htonl(endtime); h->bus.status = status; m->m_len = nlen; return (1); } static unsigned int pfsync_bulk_snd_states(struct pfsync_softc *sc, struct mbuf *m, const unsigned int space, unsigned int len) { struct pf_state *st; struct pfsync_state *sp; unsigned int nlen; unsigned int count = 0; st = sc->sc_bulk_snd.snd_next; for (;;) { nlen = len + sizeof(*sp); sp = (struct pfsync_state *)(mtod(m, caddr_t) + len); if (space < nlen) break; mtx_enter(&st->mtx); pf_state_export(sp, st); mtx_leave(&st->mtx); /* commit */ count++; m->m_len = len = nlen; if (st == sc->sc_bulk_snd.snd_tail) { if (pfsync_bulk_snd_bus(sc, m, space, 0, PFSYNC_BUS_END) == 0) { /* couldn't fit the BUS */ st = NULL; break; } /* this BUS is done */ pfsync_dprintf(sc, "bulk send done (%s)", __func__); sc->sc_bulk_snd.snd_again = 0; /* XXX */ sc->sc_bulk_snd.snd_next = NULL; sc->sc_bulk_snd.snd_tail = NULL; return (count); } st = TAILQ_NEXT(st, entry_list); } /* there's still work to do */ sc->sc_bulk_snd.snd_next = st; timeout_add_msec(&sc->sc_bulk_snd.snd_tmo, PFSYNC_BULK_SND_IVAL_MS); return (count); } static unsigned int pfsync_bulk_snd_sub(struct pfsync_softc *sc, struct mbuf *m, const unsigned int space) { struct pfsync_subheader *subh; unsigned int count; unsigned int len, nlen; len = m->m_len; nlen = len + sizeof(*subh); if (nlen > space) return (0); subh = (struct pfsync_subheader *)(mtod(m, caddr_t) + len); /* * pfsync_bulk_snd_states only updates m->m_len after * filling in a state after the offset we gave it. */ count = pfsync_bulk_snd_states(sc, m, space, nlen); if (count == 0) return (0); subh->action = PFSYNC_ACT_UPD; subh->len = sizeof(struct pfsync_state) >> 2; subh->count = htons(count); return (count); } static void pfsync_bulk_snd_start(struct pfsync_softc *sc) { const unsigned int space = sc->sc_if.if_mtu - (sizeof(struct ip) + sizeof(struct pfsync_header)); struct mbuf *m; rw_enter_read(&pf_state_list.pfs_rwl); rw_enter_write(&sc->sc_bulk_snd.snd_lock); if (sc->sc_bulk_snd.snd_next != NULL) { sc->sc_bulk_snd.snd_again = 1; goto leave; } mtx_enter(&pf_state_list.pfs_mtx); sc->sc_bulk_snd.snd_next = TAILQ_FIRST(&pf_state_list.pfs_list); sc->sc_bulk_snd.snd_tail = TAILQ_LAST(&pf_state_list.pfs_list, pf_state_queue); mtx_leave(&pf_state_list.pfs_mtx); m = m_gethdr(M_DONTWAIT, MT_DATA); if (m == NULL) goto leave; MCLGETL(m, M_DONTWAIT, max_linkhdr + sc->sc_if.if_mtu); if (!ISSET(m->m_flags, M_EXT)) { /* some error++ */ m_freem(m); /* drop */ goto leave; } m_align(m, space); m->m_len = 0; if (sc->sc_bulk_snd.snd_tail == NULL) { pfsync_dprintf(sc, "bulk send empty (%s)", __func__); /* list is empty */ if (pfsync_bulk_snd_bus(sc, m, space, 0, PFSYNC_BUS_END) == 0) panic("%s: mtu is too low", __func__); goto encap; } pfsync_dprintf(sc, "bulk send start (%s)", __func__); /* start a bulk update. */ if (pfsync_bulk_snd_bus(sc, m, space, 0, PFSYNC_BUS_START) == 0) panic("%s: mtu is too low", __func__); /* fill it up with state updates. */ pfsync_bulk_snd_sub(sc, m, space); encap: m->m_pkthdr.len = m->m_len; m = pfsync_encap(sc, m); if (m == NULL) goto leave; pfsync_sendout(sc, m); leave: rw_exit_write(&sc->sc_bulk_snd.snd_lock); rw_exit_read(&pf_state_list.pfs_rwl); } static void pfsync_bulk_snd_tmo(void *arg) { struct pfsync_softc *sc = arg; const unsigned int space = sc->sc_if.if_mtu - (sizeof(struct ip) + sizeof(struct pfsync_header)); struct mbuf *m; m = m_gethdr(M_DONTWAIT, MT_DATA); if (m == NULL) { /* some error++ */ /* retry later */ timeout_add_msec(&sc->sc_bulk_snd.snd_tmo, PFSYNC_BULK_SND_IVAL_MS); return; } MCLGETL(m, M_DONTWAIT, max_linkhdr + sc->sc_if.if_mtu); if (!ISSET(m->m_flags, M_EXT)) { /* some error++ */ m_freem(m); /* retry later */ timeout_add_msec(&sc->sc_bulk_snd.snd_tmo, PFSYNC_BULK_SND_IVAL_MS); return; } m_align(m, space); m->m_len = 0; rw_enter_read(&pf_state_list.pfs_rwl); rw_enter_write(&sc->sc_bulk_snd.snd_lock); if (sc->sc_bulk_snd.snd_next == NULL) { /* there was no space in the previous packet for a BUS END */ if (pfsync_bulk_snd_bus(sc, m, space, 0, PFSYNC_BUS_END) == 0) panic("%s: mtu is too low", __func__); /* this bulk is done */ pfsync_dprintf(sc, "bulk send done (%s)", __func__); sc->sc_bulk_snd.snd_again = 0; /* XXX */ sc->sc_bulk_snd.snd_tail = NULL; } else { pfsync_dprintf(sc, "bulk send again (%s)", __func__); /* fill it up with state updates. */ pfsync_bulk_snd_sub(sc, m, space); } m->m_pkthdr.len = m->m_len; m = pfsync_encap(sc, m); rw_exit_write(&sc->sc_bulk_snd.snd_lock); rw_exit_read(&pf_state_list.pfs_rwl); if (m != NULL) { NET_LOCK(); pfsync_sendout(sc, m); NET_UNLOCK(); } } static void pfsync_update_state_req(struct pfsync_softc *sc, struct pf_state *st) { struct pfsync_slice *s = pfsync_slice_enter(sc, st); switch (st->sync_state) { case PFSYNC_S_UPD_C: case PFSYNC_S_IACK: pfsync_q_del(s, st); /* FALLTHROUGH */ case PFSYNC_S_NONE: pfsync_q_ins(s, st, PFSYNC_S_UPD); break; case PFSYNC_S_INS: case PFSYNC_S_UPD: case PFSYNC_S_DEL: /* we're already handling it */ break; default: panic("%s: state %p unexpected sync_state %d", __func__, st, st->sync_state); } pfsync_slice_sched(s); pfsync_slice_leave(sc, s); } #if defined(IPSEC) static void pfsync_out_tdb(struct tdb *tdb, void *buf) { struct pfsync_tdb *ut = buf; memset(ut, 0, sizeof(*ut)); ut->spi = tdb->tdb_spi; memcpy(&ut->dst, &tdb->tdb_dst, sizeof(ut->dst)); /* * When a failover happens, the master's rpl is probably above * what we see here (we may be up to a second late), so * increase it a bit for outbound tdbs to manage most such * situations. * * For now, just add an offset that is likely to be larger * than the number of packets we can see in one second. The RFC * just says the next packet must have a higher seq value. * * XXX What is a good algorithm for this? We could use * a rate-determined increase, but to know it, we would have * to extend struct tdb. * XXX pt->rpl can wrap over MAXINT, but if so the real tdb * will soon be replaced anyway. For now, just don't handle * this edge case. */ #define RPL_INCR 16384 ut->rpl = htobe64(tdb->tdb_rpl + (ISSET(tdb->tdb_flags, TDBF_PFSYNC_RPL) ? RPL_INCR : 0)); ut->cur_bytes = htobe64(tdb->tdb_cur_bytes); ut->sproto = tdb->tdb_sproto; ut->rdomain = htons(tdb->tdb_rdomain); } static struct pfsync_slice * pfsync_slice_enter_tdb(struct pfsync_softc *sc, const struct tdb *t) { /* * just use the first slice for all ipsec (for now) until * it's more obvious what property (eg, spi) we can distribute * tdbs over slices with. */ struct pfsync_slice *s = &sc->sc_slices[0]; if (!mtx_enter_try(&s->s_mtx)) { mtx_enter(&s->s_mtx); s->s_stat_contended++; } s->s_stat_locks++; return (s); } static void pfsync_tdb_ins(struct pfsync_slice *s, struct tdb *tdb) { size_t nlen = sizeof(struct pfsync_tdb); struct mbuf *m = NULL; KASSERT(s->s_len >= PFSYNC_MINPKT); MUTEX_ASSERT_LOCKED(&s->s_mtx); MUTEX_ASSERT_UNLOCKED(&tdb->tdb_mtx); if (TAILQ_EMPTY(&s->s_tdb_q)) nlen += sizeof(struct pfsync_subheader); if (s->s_len + nlen > s->s_pfsync->sc_if.if_mtu) { m = pfsync_slice_write(s); if (m != NULL) { s->s_stat_enqueue++; if (mq_enqueue(&s->s_sendq, m) == 0) task_add(s->s_softnet, &s->s_send); } nlen = sizeof(struct pfsync_subheader) + sizeof(struct pfsync_tdb); } s->s_len += nlen; TAILQ_INSERT_TAIL(&s->s_tdb_q, tdb, tdb_sync_entry); tdb->tdb_updates = 0; if (!timeout_pending(&s->s_tmo)) timeout_add_sec(&s->s_tmo, 1); } static void pfsync_tdb_del(struct pfsync_slice *s, struct tdb *tdb) { MUTEX_ASSERT_LOCKED(&s->s_mtx); MUTEX_ASSERT_UNLOCKED(&tdb->tdb_mtx); TAILQ_REMOVE(&s->s_tdb_q, tdb, tdb_sync_entry); s->s_len -= sizeof(struct pfsync_tdb); if (TAILQ_EMPTY(&s->s_tdb_q)) s->s_len -= sizeof(struct pfsync_subheader); } /* * the reference that pfsync has to a tdb is accounted for by the * TDBF_PFSYNC flag, not by tdb_ref/tdb_unref. tdb_delete_tdb() is * called after all other references to a tdb are dropped (with * tdb_unref) as part of the tdb_free(). * * tdb_free() needs to wait for pfsync to let go of the tdb though, * which would be best handled by a reference count, but tdb_free * needs the NET_LOCK which pfsync is already fighting with. instead * use the TDBF_PFSYNC_SNAPPED flag to coordinate the pfsync write/drop * with tdb_free. */ void pfsync_update_tdb(struct tdb *tdb, int output) { struct pfsync_softc *sc; MUTEX_ASSERT_UNLOCKED(&tdb->tdb_mtx); smr_read_enter(); sc = SMR_PTR_GET(&pfsyncif); if (sc != NULL) { struct pfsync_slice *s = pfsync_slice_enter_tdb(sc, tdb); /* TDBF_PFSYNC is only changed while the slice mtx is held */ if (!ISSET(tdb->tdb_flags, TDBF_PFSYNC)) { mtx_enter(&tdb->tdb_mtx); SET(tdb->tdb_flags, TDBF_PFSYNC); mtx_leave(&tdb->tdb_mtx); pfsync_tdb_ins(s, tdb); } else if (++tdb->tdb_updates >= sc->sc_maxupdates) pfsync_slice_sched(s); /* XXX no sync timestamp on tdbs to check */ pfsync_slice_leave(sc, s); } smr_read_leave(); } void pfsync_delete_tdb(struct tdb *tdb) { struct pfsync_softc *sc; MUTEX_ASSERT_UNLOCKED(&tdb->tdb_mtx); smr_read_enter(); sc = SMR_PTR_GET(&pfsyncif); if (sc != NULL) { struct pfsync_slice *s = pfsync_slice_enter_tdb(sc, tdb); /* TDBF_PFSYNC is only changed while the slice mtx is held */ if (ISSET(tdb->tdb_flags, TDBF_PFSYNC)) { pfsync_tdb_del(s, tdb); mtx_enter(&tdb->tdb_mtx); CLR(tdb->tdb_flags, TDBF_PFSYNC); mtx_leave(&tdb->tdb_mtx); } pfsync_slice_leave(sc, s); } smr_read_leave(); /* * handle pfsync_slice_drop being called from pfsync_down * and the smr/slice access above won't work. */ mtx_enter(&tdb->tdb_mtx); SET(tdb->tdb_flags, TDBF_PFSYNC_SNAPPED); /* like a thanos snap */ while (ISSET(tdb->tdb_flags, TDBF_PFSYNC)) { msleep_nsec(&tdb->tdb_updates, &tdb->tdb_mtx, PWAIT, "tdbfree", INFSLP); } mtx_leave(&tdb->tdb_mtx); } #endif /* defined(IPSEC) */ struct pfsync_act { void (*in)(struct pfsync_softc *, const caddr_t, unsigned int, unsigned int); size_t len; }; static void pfsync_in_clr(struct pfsync_softc *, const caddr_t, unsigned int, unsigned int); static void pfsync_in_iack(struct pfsync_softc *, const caddr_t, unsigned int, unsigned int); static void pfsync_in_upd_c(struct pfsync_softc *, const caddr_t, unsigned int, unsigned int); static void pfsync_in_ureq(struct pfsync_softc *, const caddr_t, unsigned int, unsigned int); static void pfsync_in_del(struct pfsync_softc *, const caddr_t, unsigned int, unsigned int); static void pfsync_in_del_c(struct pfsync_softc *, const caddr_t, unsigned int, unsigned int); static void pfsync_in_bus(struct pfsync_softc *, const caddr_t, unsigned int, unsigned int); static void pfsync_in_tdb(struct pfsync_softc *, const caddr_t, unsigned int, unsigned int); static void pfsync_in_ins(struct pfsync_softc *, const caddr_t, unsigned int, unsigned int); static void pfsync_in_upd(struct pfsync_softc *, const caddr_t, unsigned int, unsigned int); static const struct pfsync_act pfsync_acts[] = { [PFSYNC_ACT_CLR] = { pfsync_in_clr, sizeof(struct pfsync_clr) }, [PFSYNC_ACT_INS_ACK] = { pfsync_in_iack, sizeof(struct pfsync_ins_ack) }, [PFSYNC_ACT_UPD_C] = { pfsync_in_upd_c, sizeof(struct pfsync_upd_c) }, [PFSYNC_ACT_UPD_REQ] = { pfsync_in_ureq, sizeof(struct pfsync_upd_req) }, [PFSYNC_ACT_DEL] = { pfsync_in_del, sizeof(struct pfsync_state) }, [PFSYNC_ACT_DEL_C] = { pfsync_in_del_c, sizeof(struct pfsync_del_c) }, [PFSYNC_ACT_BUS] = { pfsync_in_bus, sizeof(struct pfsync_bus) }, [PFSYNC_ACT_INS] = { pfsync_in_ins, sizeof(struct pfsync_state) }, [PFSYNC_ACT_UPD] = { pfsync_in_upd, sizeof(struct pfsync_state) }, [PFSYNC_ACT_TDB] = { pfsync_in_tdb, sizeof(struct pfsync_tdb) }, }; static void pfsync_in_skip(struct pfsync_softc *sc, const caddr_t buf, unsigned int mlen, unsigned int count) { /* nop */ } static struct mbuf * pfsync_input(struct mbuf *m, uint8_t ttl, unsigned int hlen) { struct pfsync_softc *sc; struct pfsync_header *ph; struct pfsync_subheader *subh; unsigned int len; void (*in)(struct pfsync_softc *, const caddr_t, unsigned int, unsigned int); pfsyncstat_inc(pfsyncs_ipackets); if (!pf_status.running) return (m); /* * pfsyncif is only set if it is up and running correctly. */ smr_read_enter(); sc = SMR_PTR_GET(&pfsyncif); if (sc == NULL) goto leave; if (sc->sc_sync_ifidx != m->m_pkthdr.ph_ifidx) { pfsyncstat_inc(pfsyncs_badif); goto leave; } /* verify that the IP TTL is 255. */ if (ttl != PFSYNC_DFLTTL) { pfsyncstat_inc(pfsyncs_badttl); goto leave; } m_adj(m, hlen); if (m->m_pkthdr.len < sizeof(*ph)) { pfsyncstat_inc(pfsyncs_hdrops); goto leave; } if (m->m_len < sizeof(*ph)) { m = m_pullup(m, sizeof(*ph)); if (m == NULL) goto leave; } ph = mtod(m, struct pfsync_header *); if (ph->version != PFSYNC_VERSION) { pfsyncstat_inc(pfsyncs_badver); goto leave; } len = ntohs(ph->len); if (m->m_pkthdr.len < len) { pfsyncstat_inc(pfsyncs_badlen); goto leave; } if (m->m_pkthdr.len > len) m->m_pkthdr.len = len; /* ok, it's serious now */ refcnt_take(&sc->sc_refs); smr_read_leave(); counters_pkt(sc->sc_if.if_counters, ifc_ipackets, ifc_ibytes, len); m_adj(m, sizeof(*ph)); while (m->m_pkthdr.len >= sizeof(*subh)) { unsigned int action, mlen, count; if (m->m_len < sizeof(*subh)) { m = m_pullup(m, sizeof(*subh)); if (m == NULL) goto rele; } subh = mtod(m, struct pfsync_subheader *); action = subh->action; mlen = subh->len << 2; count = ntohs(subh->count); if (action >= PFSYNC_ACT_MAX || action >= nitems(pfsync_acts) || mlen < pfsync_acts[subh->action].len) { /* * subheaders are always followed by at least one * message, so if the peer is new * enough to tell us how big its messages are then we * know enough to skip them. */ if (count == 0 || mlen == 0) { pfsyncstat_inc(pfsyncs_badact); goto rele; } in = pfsync_in_skip; } else { in = pfsync_acts[action].in; if (in == NULL) in = pfsync_in_skip; } m_adj(m, sizeof(*subh)); len = mlen * count; if (len > m->m_pkthdr.len) { pfsyncstat_inc(pfsyncs_badlen); goto rele; } if (m->m_len < len) { m = m_pullup(m, len); if (m == NULL) goto rele; } (*in)(sc, mtod(m, caddr_t), mlen, count); m_adj(m, len); } rele: refcnt_rele_wake(&sc->sc_refs); return (m); leave: smr_read_leave(); return (m); } static void pfsync_in_clr(struct pfsync_softc *sc, const caddr_t buf, unsigned int mlen, unsigned int count) { const struct pfsync_clr *clr; struct pf_state *head, *tail, *st, *next; struct pfi_kif *kif; uint32_t creatorid; unsigned int i; rw_enter_read(&pf_state_list.pfs_rwl); /* get a view of the state list */ mtx_enter(&pf_state_list.pfs_mtx); head = TAILQ_FIRST(&pf_state_list.pfs_list); tail = TAILQ_LAST(&pf_state_list.pfs_list, pf_state_queue); mtx_leave(&pf_state_list.pfs_mtx); PF_LOCK(); for (i = 0; i < count; i++) { clr = (struct pfsync_clr *)(buf + i * mlen); creatorid = clr->creatorid; if (clr->ifname[0] == '\0') kif = NULL; else { kif = pfi_kif_find(clr->ifname); if (kif == NULL) continue; } st = NULL; next = head; PF_STATE_ENTER_WRITE(); while (st != tail) { st = next; next = TAILQ_NEXT(st, entry_list); if (creatorid != st->creatorid) continue; if (kif != NULL && kif != st->kif) continue; mtx_enter(&st->mtx); SET(st->state_flags, PFSTATE_NOSYNC); mtx_leave(&st->mtx); pf_remove_state(st); } PF_STATE_EXIT_WRITE(); } PF_UNLOCK(); rw_exit_read(&pf_state_list.pfs_rwl); } static void pfsync_in_ins(struct pfsync_softc *sc, const caddr_t buf, unsigned int mlen, unsigned int count) { const struct pfsync_state *sp; sa_family_t af1, af2; unsigned int i; PF_LOCK(); for (i = 0; i < count; i++) { sp = (struct pfsync_state *)(buf + mlen * i); af1 = sp->key[0].af; af2 = sp->key[1].af; /* check for invalid values */ if (sp->timeout >= PFTM_MAX || sp->src.state > PF_TCPS_PROXY_DST || sp->dst.state > PF_TCPS_PROXY_DST || sp->direction > PF_OUT || (((af1 || af2) && ((af1 != AF_INET && af1 != AF_INET6) || (af2 != AF_INET && af2 != AF_INET6))) || (sp->af != AF_INET && sp->af != AF_INET6))) { pfsyncstat_inc(pfsyncs_badval); continue; } if (pf_state_import(sp, PFSYNC_SI_PFSYNC) == ENOMEM) { /* drop out, but process the rest of the actions */ break; } } PF_UNLOCK(); } static void pfsync_in_iack(struct pfsync_softc *sc, const caddr_t buf, unsigned int mlen, unsigned int count) { const struct pfsync_ins_ack *ia; struct pf_state_cmp id_key; struct pf_state *st; unsigned int i; for (i = 0; i < count; i++) { ia = (struct pfsync_ins_ack *)(buf + mlen * i); id_key.id = ia->id; id_key.creatorid = ia->creatorid; PF_STATE_ENTER_READ(); st = pf_find_state_byid(&id_key); pf_state_ref(st); PF_STATE_EXIT_READ(); if (st == NULL) continue; if (READ_ONCE(st->sync_defer) != NULL) pfsync_deferred(sc, st); pf_state_unref(st); } } static int pfsync_upd_tcp(struct pf_state *st, const struct pfsync_state_peer *src, const struct pfsync_state_peer *dst) { int sync = 0; /* * The state should never go backwards except * for syn-proxy states. Neither should the * sequence window slide backwards. */ if ((st->src.state > src->state && (st->src.state < PF_TCPS_PROXY_SRC || src->state >= PF_TCPS_PROXY_SRC)) || (st->src.state == src->state && SEQ_GT(st->src.seqlo, ntohl(src->seqlo)))) sync++; else pf_state_peer_ntoh(src, &st->src); if ((st->dst.state > dst->state) || (st->dst.state == dst->state && SEQ_GT(st->dst.seqlo, ntohl(dst->seqlo)))) sync++; else pf_state_peer_ntoh(dst, &st->dst); return (sync); } static void pfsync_in_updates(struct pfsync_softc *sc, struct pf_state *st, const struct pfsync_state_peer *src, const struct pfsync_state_peer *dst, uint8_t timeout) { struct pf_state_scrub *sscrub = NULL; struct pf_state_scrub *dscrub = NULL; int sync; if (src->scrub.scrub_flag && st->src.scrub == NULL) { sscrub = pf_state_scrub_get(); if (sscrub == NULL) { /* inc error? */ goto out; } } if (dst->scrub.scrub_flag && st->dst.scrub == NULL) { dscrub = pf_state_scrub_get(); if (dscrub == NULL) { /* inc error? */ goto out; } } if (READ_ONCE(st->sync_defer) != NULL) pfsync_deferred(sc, st); mtx_enter(&st->mtx); /* attach the scrub memory if needed */ if (sscrub != NULL && st->src.scrub == NULL) { st->src.scrub = sscrub; sscrub = NULL; } if (dscrub != NULL && st->dst.scrub == NULL) { st->dst.scrub = dscrub; dscrub = NULL; } if (st->key[PF_SK_WIRE]->proto == IPPROTO_TCP) sync = pfsync_upd_tcp(st, src, dst); else { sync = 0; /* * Non-TCP protocol state machine always go * forwards */ if (st->src.state > src->state) sync++; else pf_state_peer_ntoh(src, &st->src); if (st->dst.state > dst->state) sync++; else pf_state_peer_ntoh(dst, &st->dst); } st->pfsync_time = getuptime(); if (sync < 2) { st->expire = st->pfsync_time; st->timeout = timeout; } mtx_leave(&st->mtx); if (sync) { pfsyncstat_inc(pfsyncs_stale); pfsync_update_state(st); } out: if (sscrub != NULL) pf_state_scrub_put(sscrub); if (dscrub != NULL) pf_state_scrub_put(dscrub); } static void pfsync_in_upd(struct pfsync_softc *sc, const caddr_t buf, unsigned int mlen, unsigned int count) { const struct pfsync_state *sp; struct pf_state_cmp id_key; struct pf_state *st; int error; unsigned int i; for (i = 0; i < count; i++) { sp = (struct pfsync_state *)(buf + mlen * i); /* check for invalid values */ if (sp->timeout >= PFTM_MAX || sp->src.state > PF_TCPS_PROXY_DST || sp->dst.state > PF_TCPS_PROXY_DST) { pfsyncstat_inc(pfsyncs_badval); continue; } id_key.id = sp->id; id_key.creatorid = sp->creatorid; PF_STATE_ENTER_READ(); st = pf_find_state_byid(&id_key); pf_state_ref(st); PF_STATE_EXIT_READ(); if (st == NULL) { /* insert the update */ PF_LOCK(); error = pf_state_import(sp, PFSYNC_SI_PFSYNC); if (error) pfsyncstat_inc(pfsyncs_badstate); PF_UNLOCK(); continue; } pfsync_in_updates(sc, st, &sp->src, &sp->dst, sp->timeout); pf_state_unref(st); } } static struct mbuf * pfsync_upd_req_init(struct pfsync_softc *sc, unsigned int count) { struct mbuf *m; unsigned int mlen; m = m_gethdr(M_DONTWAIT, MT_DATA); if (m == NULL) { pfsyncstat_inc(pfsyncs_onomem); return (NULL); } mlen = max_linkhdr + sizeof(sc->sc_template) + sizeof(struct pfsync_header) + sizeof(struct pfsync_subheader) + sizeof(struct pfsync_upd_req) * count; if (mlen > MHLEN) { MCLGETL(m, M_DONTWAIT, mlen); if (!ISSET(m->m_flags, M_EXT)) { m_freem(m); return (NULL); } } m_align(m, 0); m->m_len = 0; return (m); } static void pfsync_in_upd_c(struct pfsync_softc *sc, const caddr_t buf, unsigned int mlen, unsigned int count) { const struct pfsync_upd_c *up; struct pf_state_cmp id_key; struct pf_state *st; unsigned int i; struct mbuf *m = NULL; unsigned int rcount = 0; for (i = 0; i < count; i++) { up = (struct pfsync_upd_c *)(buf + mlen * i); /* check for invalid values */ if (up->timeout >= PFTM_MAX || up->src.state > PF_TCPS_PROXY_DST || up->dst.state > PF_TCPS_PROXY_DST) { pfsyncstat_inc(pfsyncs_badval); continue; } id_key.id = up->id; id_key.creatorid = up->creatorid; PF_STATE_ENTER_READ(); st = pf_find_state_byid(&id_key); pf_state_ref(st); PF_STATE_EXIT_READ(); if (st == NULL) { /* We don't have this state. Ask for it. */ struct pfsync_upd_req *ur; if (m == NULL) { m = pfsync_upd_req_init(sc, count); if (m == NULL) { pfsyncstat_inc(pfsyncs_onomem); continue; } } m = m_prepend(m, sizeof(*ur), M_DONTWAIT); if (m == NULL) { pfsyncstat_inc(pfsyncs_onomem); continue; } ur = mtod(m, struct pfsync_upd_req *); ur->id = up->id; ur->creatorid = up->creatorid; rcount++; continue; } pfsync_in_updates(sc, st, &up->src, &up->dst, up->timeout); pf_state_unref(st); } if (m != NULL) { struct pfsync_subheader *subh; m = m_prepend(m, sizeof(*subh), M_DONTWAIT); if (m == NULL) { pfsyncstat_inc(pfsyncs_onomem); return; } subh = mtod(m, struct pfsync_subheader *); subh->action = PFSYNC_ACT_UPD_REQ; subh->len = sizeof(struct pfsync_upd_req) >> 2; subh->count = htons(rcount); m = pfsync_encap(sc, m); if (m == NULL) { pfsyncstat_inc(pfsyncs_onomem); return; } pfsync_sendout(sc, m); } } static void pfsync_in_ureq(struct pfsync_softc *sc, const caddr_t buf, unsigned int mlen, unsigned int count) { const struct pfsync_upd_req *ur; struct pf_state_cmp id_key; struct pf_state *st; unsigned int i; for (i = 0; i < count; i++) { ur = (struct pfsync_upd_req *)(buf + mlen * i); id_key.id = ur->id; id_key.creatorid = ur->creatorid; if (id_key.id == 0 && id_key.creatorid == 0) { pfsync_bulk_snd_start(sc); continue; } PF_STATE_ENTER_READ(); st = pf_find_state_byid(&id_key); if (st != NULL && st->timeout < PFTM_MAX && !ISSET(st->state_flags, PFSTATE_NOSYNC)) pf_state_ref(st); else st = NULL; PF_STATE_EXIT_READ(); if (st == NULL) { pfsyncstat_inc(pfsyncs_badstate); continue; } pfsync_update_state_req(sc, st); pf_state_unref(st); } } static void pfsync_in_del(struct pfsync_softc *sc, const caddr_t buf, unsigned int mlen, unsigned int count) { const struct pfsync_state *sp; struct pf_state_cmp id_key; struct pf_state *st; unsigned int i; PF_LOCK(); PF_STATE_ENTER_WRITE(); for (i = 0; i < count; i++) { sp = (struct pfsync_state *)(buf + mlen * i); id_key.id = sp->id; id_key.creatorid = sp->creatorid; st = pf_find_state_byid(&id_key); if (st == NULL) { pfsyncstat_inc(pfsyncs_badstate); continue; } mtx_enter(&st->mtx); SET(st->state_flags, PFSTATE_NOSYNC); mtx_leave(&st->mtx); pf_remove_state(st); } PF_STATE_EXIT_WRITE(); PF_UNLOCK(); } static void pfsync_in_del_c(struct pfsync_softc *sc, const caddr_t buf, unsigned int mlen, unsigned int count) { const struct pfsync_del_c *sp; struct pf_state_cmp id_key; struct pf_state *st; unsigned int i; PF_LOCK(); PF_STATE_ENTER_WRITE(); for (i = 0; i < count; i++) { sp = (struct pfsync_del_c *)(buf + mlen * i); id_key.id = sp->id; id_key.creatorid = sp->creatorid; st = pf_find_state_byid(&id_key); if (st == NULL) { pfsyncstat_inc(pfsyncs_badstate); continue; } mtx_enter(&st->mtx); SET(st->state_flags, PFSTATE_NOSYNC); mtx_leave(&st->mtx); pf_remove_state(st); } PF_STATE_EXIT_WRITE(); PF_UNLOCK(); } static void pfsync_in_bus(struct pfsync_softc *sc, const caddr_t buf, unsigned int len, unsigned int count) { const struct pfsync_bus *bus = (struct pfsync_bus *)buf; switch (bus->status) { case PFSYNC_BUS_START: pfsync_bulk_req_evt(sc, PFSYNC_BREQ_EVT_BUS_START); break; case PFSYNC_BUS_END: pfsync_bulk_req_evt(sc, PFSYNC_BREQ_EVT_BUS_END); break; } } #if defined(IPSEC) /* Update an in-kernel tdb. Silently fail if no tdb is found. */ static void pfsync_update_net_tdb(const struct pfsync_tdb *pt) { struct tdb *tdb; NET_ASSERT_LOCKED(); /* check for invalid values */ if (ntohl(pt->spi) <= SPI_RESERVED_MAX || (pt->dst.sa.sa_family != AF_INET && pt->dst.sa.sa_family != AF_INET6)) goto bad; tdb = gettdb(ntohs(pt->rdomain), pt->spi, (union sockaddr_union *)&pt->dst, pt->sproto); if (tdb) { uint64_t rpl = betoh64(pt->rpl); uint64_t cur_bytes = betoh64(pt->cur_bytes); /* Neither replay nor byte counter should ever decrease. */ mtx_enter(&tdb->tdb_mtx); if (rpl >= tdb->tdb_rpl && cur_bytes >= tdb->tdb_cur_bytes) { tdb->tdb_rpl = rpl; tdb->tdb_cur_bytes = cur_bytes; } mtx_leave(&tdb->tdb_mtx); tdb_unref(tdb); } return; bad: DPFPRINTF(LOG_WARNING, "pfsync_insert: PFSYNC_ACT_TDB_UPD: " "invalid value"); pfsyncstat_inc(pfsyncs_badstate); return; } #endif static void pfsync_in_tdb(struct pfsync_softc *sc, const caddr_t buf, unsigned int len, unsigned int count) { #if defined(IPSEC) const struct pfsync_tdb *tp; unsigned int i; for (i = 0; i < count; i++) { tp = (const struct pfsync_tdb *)(buf + len * i); pfsync_update_net_tdb(tp); } #endif } int pfsync_input4(struct mbuf **mp, int *offp, int proto, int af) { struct mbuf *m = *mp; struct ip *ip; ip = mtod(m, struct ip *); m = pfsync_input(m, ip->ip_ttl, ip->ip_hl << 2); m_freem(m); *mp = NULL; return (IPPROTO_DONE); } int pfsync_sysctl_pfsyncstat(void *oldp, size_t *oldlenp, void *newp) { struct pfsyncstats pfsyncstat; CTASSERT(sizeof(pfsyncstat) == (pfsyncs_ncounters * sizeof(uint64_t))); memset(&pfsyncstat, 0, sizeof pfsyncstat); counters_read(pfsynccounters, (uint64_t *)&pfsyncstat, pfsyncs_ncounters, NULL); return (sysctl_rdstruct(oldp, oldlenp, newp, &pfsyncstat, sizeof(pfsyncstat))); } int pfsync_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { /* All sysctl names at this level are terminal. */ if (namelen != 1) return (ENOTDIR); switch (name[0]) { case PFSYNCCTL_STATS: return (pfsync_sysctl_pfsyncstat(oldp, oldlenp, newp)); default: return (ENOPROTOOPT); } }
241 2 2 222 15 1 5 231 107 2 127 5 19 9 11 7 7 8 3 3 7 1 6 6 14 14 14 14 16 16 1 1 7 7 5 3 2 4 4 7 2 4 11 15 20 18 1 18 2 243 243 8 9 1 112 1 127 1 242 42 41 41 1 146 146 131 16 8 2 1 2 1 1 2 54 30 2 1 1 5 1 6 1 3 2 1 7 2 1 2 1 2 1 2 1 1 1 2 1 2 1 1 2 145 83 3 1 44 34 30 7 36 1 7 7 7 6 1 2 4 1 5 18 12 4 14 9 9 6 18 5 3 3 15 15 72 83 918 52 918 2 55 897 876 2 6 73 835 835 73 1 4 4 72 69 1 2 70 4 4 403 13 21 21 17 17 17 17 17 16 17 17 11 15 7 7 11 1 3 1 7 2 5 184 406 6 6 6 1 1 4 3 1 2 2 2 11 261 3 100 100 187 187 111 5 4 107 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 /* $OpenBSD: bpf.c,v 1.222 2024/01/26 21:14:08 jan Exp $ */ /* $NetBSD: bpf.c,v 1.33 1997/02/21 23:59:35 thorpej Exp $ */ /* * Copyright (c) 1990, 1991, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 2010, 2014 Henning Brauer <henning@openbsd.org> * * This code is derived from the Stanford/CMU enet packet filter, * (net/enet.c) distributed as part of 4.3BSD, and code contributed * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence * Berkeley Laboratory. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)bpf.c 8.2 (Berkeley) 3/28/94 */ #include "bpfilter.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/proc.h> #include <sys/signalvar.h> #include <sys/ioctl.h> #include <sys/conf.h> #include <sys/vnode.h> #include <sys/fcntl.h> #include <sys/socket.h> #include <sys/kernel.h> #include <sys/sysctl.h> #include <sys/rwlock.h> #include <sys/atomic.h> #include <sys/event.h> #include <sys/mutex.h> #include <sys/refcnt.h> #include <sys/smr.h> #include <sys/specdev.h> #include <sys/sigio.h> #include <sys/task.h> #include <sys/time.h> #include <net/if.h> #include <net/bpf.h> #include <net/bpfdesc.h> #include <netinet/in.h> #include <netinet/if_ether.h> #include "vlan.h" #if NVLAN > 0 #include <net/if_vlan_var.h> #endif #define BPF_BUFSIZE 32768 #define BPF_S_IDLE 0 #define BPF_S_WAIT 1 #define BPF_S_DONE 2 #define PRINET 26 /* interruptible */ /* * The default read buffer size is patchable. */ int bpf_bufsize = BPF_BUFSIZE; int bpf_maxbufsize = BPF_MAXBUFSIZE; /* * bpf_iflist is the list of interfaces; each corresponds to an ifnet * bpf_d_list is the list of descriptors */ struct bpf_if *bpf_iflist; LIST_HEAD(, bpf_d) bpf_d_list; int bpf_allocbufs(struct bpf_d *); void bpf_ifname(struct bpf_if*, struct ifreq *); void bpf_mcopy(const void *, void *, size_t); int bpf_movein(struct uio *, struct bpf_d *, struct mbuf **, struct sockaddr *); int bpf_setif(struct bpf_d *, struct ifreq *); int bpfkqfilter(dev_t, struct knote *); void bpf_wakeup(struct bpf_d *); void bpf_wakeup_cb(void *); void bpf_wait_cb(void *); int _bpf_mtap(caddr_t, const struct mbuf *, const struct mbuf *, u_int); void bpf_catchpacket(struct bpf_d *, u_char *, size_t, size_t, const struct bpf_hdr *); int bpf_getdltlist(struct bpf_d *, struct bpf_dltlist *); int bpf_setdlt(struct bpf_d *, u_int); void filt_bpfrdetach(struct knote *); int filt_bpfread(struct knote *, long); int filt_bpfreadmodify(struct kevent *, struct knote *); int filt_bpfreadprocess(struct knote *, struct kevent *); int bpf_sysctl_locked(int *, u_int, void *, size_t *, void *, size_t); struct bpf_d *bpfilter_lookup(int); /* * Called holding ``bd_mtx''. */ void bpf_attachd(struct bpf_d *, struct bpf_if *); void bpf_detachd(struct bpf_d *); void bpf_resetd(struct bpf_d *); void bpf_prog_smr(void *); void bpf_d_smr(void *); /* * Reference count access to descriptor buffers */ void bpf_get(struct bpf_d *); void bpf_put(struct bpf_d *); struct rwlock bpf_sysctl_lk = RWLOCK_INITIALIZER("bpfsz"); int bpf_movein(struct uio *uio, struct bpf_d *d, struct mbuf **mp, struct sockaddr *sockp) { struct bpf_program_smr *bps; struct bpf_insn *fcode = NULL; struct mbuf *m; struct m_tag *mtag; int error; u_int hlen, alen, mlen; u_int len; u_int linktype; u_int slen; /* * Build a sockaddr based on the data link layer type. * We do this at this level because the ethernet header * is copied directly into the data field of the sockaddr. * In the case of SLIP, there is no header and the packet * is forwarded as is. * Also, we are careful to leave room at the front of the mbuf * for the link level header. */ linktype = d->bd_bif->bif_dlt; switch (linktype) { case DLT_SLIP: sockp->sa_family = AF_INET; hlen = 0; break; case DLT_PPP: sockp->sa_family = AF_UNSPEC; hlen = 0; break; case DLT_EN10MB: sockp->sa_family = AF_UNSPEC; /* XXX Would MAXLINKHDR be better? */ hlen = ETHER_HDR_LEN; break; case DLT_IEEE802_11: case DLT_IEEE802_11_RADIO: sockp->sa_family = AF_UNSPEC; hlen = 0; break; case DLT_RAW: case DLT_NULL: sockp->sa_family = AF_UNSPEC; hlen = 0; break; case DLT_LOOP: sockp->sa_family = AF_UNSPEC; hlen = sizeof(u_int32_t); break; default: return (EIO); } if (uio->uio_resid > MAXMCLBYTES) return (EMSGSIZE); len = uio->uio_resid; if (len < hlen) return (EINVAL); /* * Get the length of the payload so we can align it properly. */ alen = len - hlen; /* * Allocate enough space for headers and the aligned payload. */ mlen = max(max_linkhdr, hlen) + roundup(alen, sizeof(long)); if (mlen > MAXMCLBYTES) return (EMSGSIZE); MGETHDR(m, M_WAIT, MT_DATA); if (mlen > MHLEN) { MCLGETL(m, M_WAIT, mlen); if ((m->m_flags & M_EXT) == 0) { error = ENOBUFS; goto bad; } } m_align(m, alen); /* Align the payload. */ m->m_data -= hlen; m->m_pkthdr.ph_ifidx = 0; m->m_pkthdr.len = len; m->m_len = len; error = uiomove(mtod(m, caddr_t), len, uio); if (error) goto bad; smr_read_enter(); bps = SMR_PTR_GET(&d->bd_wfilter); if (bps != NULL) fcode = bps->bps_bf.bf_insns; slen = bpf_filter(fcode, mtod(m, u_char *), len, len); smr_read_leave(); if (slen < len) { error = EPERM; goto bad; } /* * Make room for link header, and copy it to sockaddr */ if (hlen != 0) { if (linktype == DLT_LOOP) { u_int32_t af; /* the link header indicates the address family */ KASSERT(hlen == sizeof(u_int32_t)); memcpy(&af, m->m_data, hlen); sockp->sa_family = ntohl(af); } else memcpy(sockp->sa_data, m->m_data, hlen); m->m_pkthdr.len -= hlen; m->m_len -= hlen; m->m_data += hlen; } /* * Prepend the data link type as a mbuf tag */ mtag = m_tag_get(PACKET_TAG_DLT, sizeof(u_int), M_WAIT); *(u_int *)(mtag + 1) = linktype; m_tag_prepend(m, mtag); *mp = m; return (0); bad: m_freem(m); return (error); } /* * Attach file to the bpf interface, i.e. make d listen on bp. */ void bpf_attachd(struct bpf_d *d, struct bpf_if *bp) { MUTEX_ASSERT_LOCKED(&d->bd_mtx); /* * Point d at bp, and add d to the interface's list of listeners. * Finally, point the driver's bpf cookie at the interface so * it will divert packets to bpf. */ d->bd_bif = bp; KERNEL_ASSERT_LOCKED(); SMR_SLIST_INSERT_HEAD_LOCKED(&bp->bif_dlist, d, bd_next); *bp->bif_driverp = bp; } /* * Detach a file from its interface. */ void bpf_detachd(struct bpf_d *d) { struct bpf_if *bp; MUTEX_ASSERT_LOCKED(&d->bd_mtx); bp = d->bd_bif; /* Not attached. */ if (bp == NULL) return; /* Remove ``d'' from the interface's descriptor list. */ KERNEL_ASSERT_LOCKED(); SMR_SLIST_REMOVE_LOCKED(&bp->bif_dlist, d, bpf_d, bd_next); if (SMR_SLIST_EMPTY_LOCKED(&bp->bif_dlist)) { /* * Let the driver know that there are no more listeners. */ *bp->bif_driverp = NULL; } d->bd_bif = NULL; /* * Check if this descriptor had requested promiscuous mode. * If so, turn it off. */ if (d->bd_promisc) { int error; KASSERT(bp->bif_ifp != NULL); d->bd_promisc = 0; bpf_get(d); mtx_leave(&d->bd_mtx); NET_LOCK(); error = ifpromisc(bp->bif_ifp, 0); NET_UNLOCK(); mtx_enter(&d->bd_mtx); bpf_put(d); if (error && !(error == EINVAL || error == ENODEV || error == ENXIO)) /* * Something is really wrong if we were able to put * the driver into promiscuous mode, but can't * take it out. */ panic("bpf: ifpromisc failed"); } } void bpfilterattach(int n) { LIST_INIT(&bpf_d_list); } /* * Open ethernet device. Returns ENXIO for illegal minor device number, * EBUSY if file is open by another process. */ int bpfopen(dev_t dev, int flag, int mode, struct proc *p) { struct bpf_d *bd; int unit = minor(dev); if (unit & ((1 << CLONE_SHIFT) - 1)) return (ENXIO); KASSERT(bpfilter_lookup(unit) == NULL); /* create on demand */ if ((bd = malloc(sizeof(*bd), M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL) return (EBUSY); /* Mark "free" and do most initialization. */ bd->bd_unit = unit; bd->bd_bufsize = bpf_bufsize; bd->bd_sig = SIGIO; mtx_init(&bd->bd_mtx, IPL_NET); task_set(&bd->bd_wake_task, bpf_wakeup_cb, bd); timeout_set(&bd->bd_wait_tmo, bpf_wait_cb, bd); smr_init(&bd->bd_smr); sigio_init(&bd->bd_sigio); klist_init_mutex(&bd->bd_klist, &bd->bd_mtx); bd->bd_rtout = 0; /* no timeout by default */ bd->bd_wtout = INFSLP; /* wait for the buffer to fill by default */ refcnt_init(&bd->bd_refcnt); LIST_INSERT_HEAD(&bpf_d_list, bd, bd_list); return (0); } /* * Close the descriptor by detaching it from its interface, * deallocating its buffers, and marking it free. */ int bpfclose(dev_t dev, int flag, int mode, struct proc *p) { struct bpf_d *d; d = bpfilter_lookup(minor(dev)); mtx_enter(&d->bd_mtx); bpf_detachd(d); bpf_wakeup(d); LIST_REMOVE(d, bd_list); mtx_leave(&d->bd_mtx); bpf_put(d); return (0); } /* * Rotate the packet buffers in descriptor d. Move the store buffer * into the hold slot, and the free buffer into the store slot. * Zero the length of the new store buffer. */ #define ROTATE_BUFFERS(d) \ KASSERT(d->bd_in_uiomove == 0); \ MUTEX_ASSERT_LOCKED(&d->bd_mtx); \ (d)->bd_hbuf = (d)->bd_sbuf; \ (d)->bd_hlen = (d)->bd_slen; \ (d)->bd_sbuf = (d)->bd_fbuf; \ (d)->bd_state = BPF_S_IDLE; \ (d)->bd_slen = 0; \ (d)->bd_fbuf = NULL; /* * bpfread - read next chunk of packets from buffers */ int bpfread(dev_t dev, struct uio *uio, int ioflag) { uint64_t end, now; struct bpf_d *d; caddr_t hbuf; int error, hlen; KERNEL_ASSERT_LOCKED(); d = bpfilter_lookup(minor(dev)); if (d->bd_bif == NULL) return (ENXIO); bpf_get(d); mtx_enter(&d->bd_mtx); /* * Restrict application to use a buffer the same size as * as kernel buffers. */ if (uio->uio_resid != d->bd_bufsize) { error = EINVAL; goto out; } /* * If there's a timeout, mark when the read should end. */ if (d->bd_rtout != 0) { now = nsecuptime(); end = now + d->bd_rtout; if (end < now) end = UINT64_MAX; } /* * If the hold buffer is empty, then do a timed sleep, which * ends when the timeout expires or when enough packets * have arrived to fill the store buffer. */ while (d->bd_hbuf == NULL) { if (d->bd_bif == NULL) { /* interface is gone */ if (d->bd_slen == 0) { error = EIO; goto out; } ROTATE_BUFFERS(d); break; } if (d->bd_state == BPF_S_DONE) { /* * A packet(s) either arrived since the previous * read or arrived while we were asleep. * Rotate the buffers and return what's here. */ ROTATE_BUFFERS(d); break; } if (ISSET(ioflag, IO_NDELAY)) { /* User requested non-blocking I/O */ error = EWOULDBLOCK; } else if (d->bd_rtout == 0) { /* No read timeout set. */ d->bd_nreaders++; error = msleep_nsec(d, &d->bd_mtx, PRINET|PCATCH, "bpf", INFSLP); d->bd_nreaders--; } else if ((now = nsecuptime()) < end) { /* Read timeout has not expired yet. */ d->bd_nreaders++; error = msleep_nsec(d, &d->bd_mtx, PRINET|PCATCH, "bpf", end - now); d->bd_nreaders--; } else { /* Read timeout has expired. */ error = EWOULDBLOCK; } if (error == EINTR || error == ERESTART) goto out; if (error == EWOULDBLOCK) { /* * On a timeout, return what's in the buffer, * which may be nothing. If there is something * in the store buffer, we can rotate the buffers. */ if (d->bd_hbuf != NULL) /* * We filled up the buffer in between * getting the timeout and arriving * here, so we don't need to rotate. */ break; if (d->bd_slen == 0) { error = 0; goto out; } ROTATE_BUFFERS(d); break; } } /* * At this point, we know we have something in the hold slot. */ hbuf = d->bd_hbuf; hlen = d->bd_hlen; d->bd_hbuf = NULL; d->bd_hlen = 0; d->bd_fbuf = NULL; d->bd_in_uiomove = 1; /* * Move data from hold buffer into user space. * We know the entire buffer is transferred since * we checked above that the read buffer is bpf_bufsize bytes. */ mtx_leave(&d->bd_mtx); error = uiomove(hbuf, hlen, uio); mtx_enter(&d->bd_mtx); /* Ensure that bpf_resetd() or ROTATE_BUFFERS() haven't been called. */ KASSERT(d->bd_fbuf == NULL); KASSERT(d->bd_hbuf == NULL); d->bd_fbuf = hbuf; d->bd_in_uiomove = 0; out: mtx_leave(&d->bd_mtx); bpf_put(d); return (error); } /* * If there are processes sleeping on this descriptor, wake them up. */ void bpf_wakeup(struct bpf_d *d) { MUTEX_ASSERT_LOCKED(&d->bd_mtx); if (d->bd_nreaders) wakeup(d); knote_locked(&d->bd_klist, 0); /* * As long as pgsigio() needs to be protected * by the KERNEL_LOCK() we have to delay the wakeup to * another context to keep the hot path KERNEL_LOCK()-free. */ if (d->bd_async && d->bd_sig) { bpf_get(d); if (!task_add(systq, &d->bd_wake_task)) bpf_put(d); } } void bpf_wakeup_cb(void *xd) { struct bpf_d *d = xd; if (d->bd_async && d->bd_sig) pgsigio(&d->bd_sigio, d->bd_sig, 0); bpf_put(d); } void bpf_wait_cb(void *xd) { struct bpf_d *d = xd; mtx_enter(&d->bd_mtx); if (d->bd_state == BPF_S_WAIT) { d->bd_state = BPF_S_DONE; bpf_wakeup(d); } mtx_leave(&d->bd_mtx); bpf_put(d); } int bpfwrite(dev_t dev, struct uio *uio, int ioflag) { struct bpf_d *d; struct ifnet *ifp; struct mbuf *m; int error; struct sockaddr_storage dst; KERNEL_ASSERT_LOCKED(); d = bpfilter_lookup(minor(dev)); if (d->bd_bif == NULL) return (ENXIO); bpf_get(d); ifp = d->bd_bif->bif_ifp; if (ifp == NULL || (ifp->if_flags & IFF_UP) == 0) { error = ENETDOWN; goto out; } if (uio->uio_resid == 0) { error = 0; goto out; } error = bpf_movein(uio, d, &m, sstosa(&dst)); if (error) goto out; if (m->m_pkthdr.len > ifp->if_mtu) { m_freem(m); error = EMSGSIZE; goto out; } m->m_pkthdr.ph_rtableid = ifp->if_rdomain; m->m_pkthdr.pf.prio = ifp->if_llprio; if (d->bd_hdrcmplt && dst.ss_family == AF_UNSPEC) dst.ss_family = pseudo_AF_HDRCMPLT; NET_LOCK(); error = ifp->if_output(ifp, m, sstosa(&dst), NULL); NET_UNLOCK(); out: bpf_put(d); return (error); } /* * Reset a descriptor by flushing its packet buffer and clearing the * receive and drop counts. */ void bpf_resetd(struct bpf_d *d) { MUTEX_ASSERT_LOCKED(&d->bd_mtx); KASSERT(d->bd_in_uiomove == 0); if (timeout_del(&d->bd_wait_tmo)) bpf_put(d); if (d->bd_hbuf != NULL) { /* Free the hold buffer. */ d->bd_fbuf = d->bd_hbuf; d->bd_hbuf = NULL; } d->bd_state = BPF_S_IDLE; d->bd_slen = 0; d->bd_hlen = 0; d->bd_rcount = 0; d->bd_dcount = 0; } static int bpf_set_wtout(struct bpf_d *d, uint64_t wtout) { mtx_enter(&d->bd_mtx); d->bd_wtout = wtout; mtx_leave(&d->bd_mtx); return (0); } static int bpf_set_wtimeout(struct bpf_d *d, const struct timeval *tv) { uint64_t nsec; if (tv->tv_sec < 0 || !timerisvalid(tv)) return (EINVAL); nsec = TIMEVAL_TO_NSEC(tv); if (nsec > MAXTSLP) return (EOVERFLOW); return (bpf_set_wtout(d, nsec)); } static int bpf_get_wtimeout(struct bpf_d *d, struct timeval *tv) { uint64_t nsec; mtx_enter(&d->bd_mtx); nsec = d->bd_wtout; mtx_leave(&d->bd_mtx); if (nsec == INFSLP) return (ENXIO); memset(tv, 0, sizeof(*tv)); NSEC_TO_TIMEVAL(nsec, tv); return (0); } /* * FIONREAD Check for read packet available. * BIOCGBLEN Get buffer len [for read()]. * BIOCSETF Set ethernet read filter. * BIOCFLUSH Flush read packet buffer. * BIOCPROMISC Put interface into promiscuous mode. * BIOCGDLTLIST Get supported link layer types. * BIOCGDLT Get link layer type. * BIOCSDLT Set link layer type. * BIOCGETIF Get interface name. * BIOCSETIF Set interface. * BIOCSRTIMEOUT Set read timeout. * BIOCGRTIMEOUT Get read timeout. * BIOCSWTIMEOUT Set wait timeout. * BIOCGWTIMEOUT Get wait timeout. * BIOCDWTIMEOUT Del wait timeout. * BIOCGSTATS Get packet stats. * BIOCIMMEDIATE Set immediate mode. * BIOCVERSION Get filter language version. * BIOCGHDRCMPLT Get "header already complete" flag * BIOCSHDRCMPLT Set "header already complete" flag */ int bpfioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { struct bpf_d *d; int error = 0; d = bpfilter_lookup(minor(dev)); if (d->bd_locked && suser(p) != 0) { /* list of allowed ioctls when locked and not root */ switch (cmd) { case BIOCGBLEN: case BIOCFLUSH: case BIOCGDLT: case BIOCGDLTLIST: case BIOCGETIF: case BIOCGRTIMEOUT: case BIOCGWTIMEOUT: case BIOCGSTATS: case BIOCVERSION: case BIOCGRSIG: case BIOCGHDRCMPLT: case FIONREAD: case BIOCLOCK: case BIOCSRTIMEOUT: case BIOCSWTIMEOUT: case BIOCDWTIMEOUT: case BIOCIMMEDIATE: case TIOCGPGRP: case BIOCGDIRFILT: break; default: return (EPERM); } } bpf_get(d); switch (cmd) { default: error = EINVAL; break; /* * Check for read packet available. */ case FIONREAD: { int n; mtx_enter(&d->bd_mtx); n = d->bd_slen; if (d->bd_hbuf != NULL) n += d->bd_hlen; mtx_leave(&d->bd_mtx); *(int *)addr = n; break; } /* * Get buffer len [for read()]. */ case BIOCGBLEN: *(u_int *)addr = d->bd_bufsize; break; /* * Set buffer length. */ case BIOCSBLEN: if (d->bd_bif != NULL) error = EINVAL; else { u_int size = *(u_int *)addr; if (size > bpf_maxbufsize) *(u_int *)addr = size = bpf_maxbufsize; else if (size < BPF_MINBUFSIZE) *(u_int *)addr = size = BPF_MINBUFSIZE; mtx_enter(&d->bd_mtx); d->bd_bufsize = size; mtx_leave(&d->bd_mtx); } break; /* * Set link layer read filter. */ case BIOCSETF: error = bpf_setf(d, (struct bpf_program *)addr, 0); break; /* * Set link layer write filter. */ case BIOCSETWF: error = bpf_setf(d, (struct bpf_program *)addr, 1); break; /* * Flush read packet buffer. */ case BIOCFLUSH: mtx_enter(&d->bd_mtx); bpf_resetd(d); mtx_leave(&d->bd_mtx); break; /* * Put interface into promiscuous mode. */ case BIOCPROMISC: if (d->bd_bif == NULL) { /* * No interface attached yet. */ error = EINVAL; } else if (d->bd_bif->bif_ifp != NULL) { if (d->bd_promisc == 0) { MUTEX_ASSERT_UNLOCKED(&d->bd_mtx); NET_LOCK(); error = ifpromisc(d->bd_bif->bif_ifp, 1); NET_UNLOCK(); if (error == 0) d->bd_promisc = 1; } } break; /* * Get a list of supported device parameters. */ case BIOCGDLTLIST: if (d->bd_bif == NULL) error = EINVAL; else error = bpf_getdltlist(d, (struct bpf_dltlist *)addr); break; /* * Get device parameters. */ case BIOCGDLT: if (d->bd_bif == NULL) error = EINVAL; else *(u_int *)addr = d->bd_bif->bif_dlt; break; /* * Set device parameters. */ case BIOCSDLT: if (d->bd_bif == NULL) error = EINVAL; else { mtx_enter(&d->bd_mtx); error = bpf_setdlt(d, *(u_int *)addr); mtx_leave(&d->bd_mtx); } break; /* * Set interface name. */ case BIOCGETIF: if (d->bd_bif == NULL) error = EINVAL; else bpf_ifname(d->bd_bif, (struct ifreq *)addr); break; /* * Set interface. */ case BIOCSETIF: error = bpf_setif(d, (struct ifreq *)addr); break; /* * Set read timeout. */ case BIOCSRTIMEOUT: { struct timeval *tv = (struct timeval *)addr; uint64_t rtout; if (tv->tv_sec < 0 || !timerisvalid(tv)) { error = EINVAL; break; } rtout = TIMEVAL_TO_NSEC(tv); if (rtout > MAXTSLP) { error = EOVERFLOW; break; } mtx_enter(&d->bd_mtx); d->bd_rtout = rtout; mtx_leave(&d->bd_mtx); break; } /* * Get read timeout. */ case BIOCGRTIMEOUT: { struct timeval *tv = (struct timeval *)addr; memset(tv, 0, sizeof(*tv)); mtx_enter(&d->bd_mtx); NSEC_TO_TIMEVAL(d->bd_rtout, tv); mtx_leave(&d->bd_mtx); break; } /* * Get packet stats. */ case BIOCGSTATS: { struct bpf_stat *bs = (struct bpf_stat *)addr; bs->bs_recv = d->bd_rcount; bs->bs_drop = d->bd_dcount; break; } /* * Set immediate mode. */ case BIOCIMMEDIATE: error = bpf_set_wtout(d, *(int *)addr ? 0 : INFSLP); break; /* * Wait timeout. */ case BIOCSWTIMEOUT: error = bpf_set_wtimeout(d, (const struct timeval *)addr); break; case BIOCGWTIMEOUT: error = bpf_get_wtimeout(d, (struct timeval *)addr); break; case BIOCDWTIMEOUT: error = bpf_set_wtout(d, INFSLP); break; case BIOCVERSION: { struct bpf_version *bv = (struct bpf_version *)addr; bv->bv_major = BPF_MAJOR_VERSION; bv->bv_minor = BPF_MINOR_VERSION; break; } case BIOCGHDRCMPLT: /* get "header already complete" flag */ *(u_int *)addr = d->bd_hdrcmplt; break; case BIOCSHDRCMPLT: /* set "header already complete" flag */ d->bd_hdrcmplt = *(u_int *)addr ? 1 : 0; break; case BIOCLOCK: /* set "locked" flag (no reset) */ d->bd_locked = 1; break; case BIOCGFILDROP: /* get "filter-drop" flag */ *(u_int *)addr = d->bd_fildrop; break; case BIOCSFILDROP: { /* set "filter-drop" flag */ unsigned int fildrop = *(u_int *)addr; switch (fildrop) { case BPF_FILDROP_PASS: case BPF_FILDROP_CAPTURE: case BPF_FILDROP_DROP: d->bd_fildrop = fildrop; break; default: error = EINVAL; break; } break; } case BIOCGDIRFILT: /* get direction filter */ *(u_int *)addr = d->bd_dirfilt; break; case BIOCSDIRFILT: /* set direction filter */ d->bd_dirfilt = (*(u_int *)addr) & (BPF_DIRECTION_IN|BPF_DIRECTION_OUT); break; case FIONBIO: /* Non-blocking I/O */ /* let vfs to keep track of this */ break; case FIOASYNC: /* Send signal on receive packets */ d->bd_async = *(int *)addr; break; case FIOSETOWN: /* Process or group to send signals to */ case TIOCSPGRP: error = sigio_setown(&d->bd_sigio, cmd, addr); break; case FIOGETOWN: case TIOCGPGRP: sigio_getown(&d->bd_sigio, cmd, addr); break; case BIOCSRSIG: /* Set receive signal */ { u_int sig; sig = *(u_int *)addr; if (sig >= NSIG) error = EINVAL; else d->bd_sig = sig; break; } case BIOCGRSIG: *(u_int *)addr = d->bd_sig; break; } bpf_put(d); return (error); } /* * Set d's packet filter program to fp. If this file already has a filter, * free it and replace it. Returns EINVAL for bogus requests. */ int bpf_setf(struct bpf_d *d, struct bpf_program *fp, int wf) { struct bpf_program_smr *bps, *old_bps; struct bpf_insn *fcode; u_int flen, size; KERNEL_ASSERT_LOCKED(); if (fp->bf_insns == 0) { if (fp->bf_len != 0) return (EINVAL); bps = NULL; } else { flen = fp->bf_len; if (flen > BPF_MAXINSNS) return (EINVAL); fcode = mallocarray(flen, sizeof(*fp->bf_insns), M_DEVBUF, M_WAITOK | M_CANFAIL); if (fcode == NULL) return (ENOMEM); size = flen * sizeof(*fp->bf_insns); if (copyin(fp->bf_insns, fcode, size) != 0 || bpf_validate(fcode, (int)flen) == 0) { free(fcode, M_DEVBUF, size); return (EINVAL); } bps = malloc(sizeof(*bps), M_DEVBUF, M_WAITOK); smr_init(&bps->bps_smr); bps->bps_bf.bf_len = flen; bps->bps_bf.bf_insns = fcode; } if (wf == 0) { old_bps = SMR_PTR_GET_LOCKED(&d->bd_rfilter); SMR_PTR_SET_LOCKED(&d->bd_rfilter, bps); } else { old_bps = SMR_PTR_GET_LOCKED(&d->bd_wfilter); SMR_PTR_SET_LOCKED(&d->bd_wfilter, bps); } mtx_enter(&d->bd_mtx); bpf_resetd(d); mtx_leave(&d->bd_mtx); if (old_bps != NULL) smr_call(&old_bps->bps_smr, bpf_prog_smr, old_bps); return (0); } /* * Detach a file from its current interface (if attached at all) and attach * to the interface indicated by the name stored in ifr. * Return an errno or 0. */ int bpf_setif(struct bpf_d *d, struct ifreq *ifr) { struct bpf_if *bp, *candidate = NULL; int error = 0; /* * Look through attached interfaces for the named one. */ for (bp = bpf_iflist; bp != NULL; bp = bp->bif_next) { if (strcmp(bp->bif_name, ifr->ifr_name) != 0) continue; if (candidate == NULL || candidate->bif_dlt > bp->bif_dlt) candidate = bp; } /* Not found. */ if (candidate == NULL) return (ENXIO); /* * Allocate the packet buffers if we need to. * If we're already attached to requested interface, * just flush the buffer. */ mtx_enter(&d->bd_mtx); if (d->bd_sbuf == NULL) { if ((error = bpf_allocbufs(d))) goto out; } if (candidate != d->bd_bif) { /* * Detach if attached to something else. */ bpf_detachd(d); bpf_attachd(d, candidate); } bpf_resetd(d); out: mtx_leave(&d->bd_mtx); return (error); } /* * Copy the interface name to the ifreq. */ void bpf_ifname(struct bpf_if *bif, struct ifreq *ifr) { bcopy(bif->bif_name, ifr->ifr_name, sizeof(ifr->ifr_name)); } const struct filterops bpfread_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_bpfrdetach, .f_event = filt_bpfread, .f_modify = filt_bpfreadmodify, .f_process = filt_bpfreadprocess, }; int bpfkqfilter(dev_t dev, struct knote *kn) { struct bpf_d *d; struct klist *klist; KERNEL_ASSERT_LOCKED(); d = bpfilter_lookup(minor(dev)); if (d == NULL) return (ENXIO); switch (kn->kn_filter) { case EVFILT_READ: klist = &d->bd_klist; kn->kn_fop = &bpfread_filtops; break; default: return (EINVAL); } bpf_get(d); kn->kn_hook = d; klist_insert(klist, kn); return (0); } void filt_bpfrdetach(struct knote *kn) { struct bpf_d *d = kn->kn_hook; klist_remove(&d->bd_klist, kn); bpf_put(d); } int filt_bpfread(struct knote *kn, long hint) { struct bpf_d *d = kn->kn_hook; MUTEX_ASSERT_LOCKED(&d->bd_mtx); kn->kn_data = d->bd_hlen; if (d->bd_wtout == 0) kn->kn_data += d->bd_slen; return (kn->kn_data > 0); } int filt_bpfreadmodify(struct kevent *kev, struct knote *kn) { struct bpf_d *d = kn->kn_hook; int active; mtx_enter(&d->bd_mtx); active = knote_modify_fn(kev, kn, filt_bpfread); mtx_leave(&d->bd_mtx); return (active); } int filt_bpfreadprocess(struct knote *kn, struct kevent *kev) { struct bpf_d *d = kn->kn_hook; int active; mtx_enter(&d->bd_mtx); active = knote_process_fn(kn, kev, filt_bpfread); mtx_leave(&d->bd_mtx); return (active); } /* * Copy data from an mbuf chain into a buffer. This code is derived * from m_copydata in sys/uipc_mbuf.c. */ void bpf_mcopy(const void *src_arg, void *dst_arg, size_t len) { const struct mbuf *m; u_int count; u_char *dst; m = src_arg; dst = dst_arg; while (len > 0) { if (m == NULL) panic("bpf_mcopy"); count = min(m->m_len, len); bcopy(mtod(m, caddr_t), (caddr_t)dst, count); m = m->m_next; dst += count; len -= count; } } int bpf_mtap(caddr_t arg, const struct mbuf *m, u_int direction) { return _bpf_mtap(arg, m, m, direction); } int _bpf_mtap(caddr_t arg, const struct mbuf *mp, const struct mbuf *m, u_int direction) { struct bpf_if *bp = (struct bpf_if *)arg; struct bpf_d *d; size_t pktlen, slen; const struct mbuf *m0; struct bpf_hdr tbh; int gothdr = 0; int drop = 0; if (m == NULL) return (0); if (bp == NULL) return (0); pktlen = 0; for (m0 = m; m0 != NULL; m0 = m0->m_next) pktlen += m0->m_len; smr_read_enter(); SMR_SLIST_FOREACH(d, &bp->bif_dlist, bd_next) { struct bpf_program_smr *bps; struct bpf_insn *fcode = NULL; atomic_inc_long(&d->bd_rcount); if (ISSET(d->bd_dirfilt, direction)) continue; bps = SMR_PTR_GET(&d->bd_rfilter); if (bps != NULL) fcode = bps->bps_bf.bf_insns; slen = bpf_mfilter(fcode, m, pktlen); if (slen == 0) continue; if (d->bd_fildrop != BPF_FILDROP_PASS) drop = 1; if (d->bd_fildrop != BPF_FILDROP_DROP) { if (!gothdr) { struct timeval tv; memset(&tbh, 0, sizeof(tbh)); if (ISSET(mp->m_flags, M_PKTHDR)) { tbh.bh_ifidx = mp->m_pkthdr.ph_ifidx; tbh.bh_flowid = mp->m_pkthdr.ph_flowid; tbh.bh_flags = mp->m_pkthdr.pf.prio; if (ISSET(mp->m_pkthdr.csum_flags, M_FLOWID)) SET(tbh.bh_flags, BPF_F_FLOWID); tbh.bh_csumflags = mp->m_pkthdr.csum_flags; m_microtime(mp, &tv); } else microtime(&tv); tbh.bh_tstamp.tv_sec = tv.tv_sec; tbh.bh_tstamp.tv_usec = tv.tv_usec; SET(tbh.bh_flags, direction << BPF_F_DIR_SHIFT); gothdr = 1; } mtx_enter(&d->bd_mtx); bpf_catchpacket(d, (u_char *)m, pktlen, slen, &tbh); mtx_leave(&d->bd_mtx); } } smr_read_leave(); return (drop); } /* * Incoming linkage from device drivers, where a data buffer should be * prepended by an arbitrary header. In this situation we already have a * way of representing a chain of memory buffers, ie, mbufs, so reuse * the existing functionality by attaching the buffers to mbufs. * * Con up a minimal mbuf chain to pacify bpf by allocating (only) a * struct m_hdr each for the header and data on the stack. */ int bpf_tap_hdr(caddr_t arg, const void *hdr, unsigned int hdrlen, const void *buf, unsigned int buflen, u_int direction) { struct m_hdr mh, md; struct mbuf *m0 = NULL; struct mbuf **mp = &m0; if (hdr != NULL) { mh.mh_flags = 0; mh.mh_next = NULL; mh.mh_len = hdrlen; mh.mh_data = (void *)hdr; *mp = (struct mbuf *)&mh; mp = &mh.mh_next; } if (buf != NULL) { md.mh_flags = 0; md.mh_next = NULL; md.mh_len = buflen; md.mh_data = (void *)buf; *mp = (struct mbuf *)&md; } return bpf_mtap(arg, m0, direction); } /* * Incoming linkage from device drivers, where we have a mbuf chain * but need to prepend some arbitrary header from a linear buffer. * * Con up a minimal dummy header to pacify bpf. Allocate (only) a * struct m_hdr on the stack. This is safe as bpf only reads from the * fields in this header that we initialize, and will not try to free * it or keep a pointer to it. */ int bpf_mtap_hdr(caddr_t arg, const void *data, u_int dlen, const struct mbuf *m, u_int direction) { struct m_hdr mh; const struct mbuf *m0; if (dlen > 0) { mh.mh_flags = 0; mh.mh_next = (struct mbuf *)m; mh.mh_len = dlen; mh.mh_data = (void *)data; m0 = (struct mbuf *)&mh; } else m0 = m; return _bpf_mtap(arg, m, m0, direction); } /* * Incoming linkage from device drivers, where we have a mbuf chain * but need to prepend the address family. * * Con up a minimal dummy header to pacify bpf. We allocate (only) a * struct m_hdr on the stack. This is safe as bpf only reads from the * fields in this header that we initialize, and will not try to free * it or keep a pointer to it. */ int bpf_mtap_af(caddr_t arg, u_int32_t af, const struct mbuf *m, u_int direction) { u_int32_t afh; afh = htonl(af); return bpf_mtap_hdr(arg, &afh, sizeof(afh), m, direction); } /* * Incoming linkage from device drivers, where we have a mbuf chain * but need to prepend a VLAN encapsulation header. * * Con up a minimal dummy header to pacify bpf. Allocate (only) a * struct m_hdr on the stack. This is safe as bpf only reads from the * fields in this header that we initialize, and will not try to free * it or keep a pointer to it. */ int bpf_mtap_ether(caddr_t arg, const struct mbuf *m, u_int direction) { #if NVLAN > 0 struct ether_vlan_header evh; struct m_hdr mh, md; if ((m->m_flags & M_VLANTAG) == 0) #endif { return _bpf_mtap(arg, m, m, direction); } #if NVLAN > 0 KASSERT(m->m_len >= ETHER_HDR_LEN); memcpy(&evh, mtod(m, char *), ETHER_HDR_LEN); evh.evl_proto = evh.evl_encap_proto; evh.evl_encap_proto = htons(ETHERTYPE_VLAN); evh.evl_tag = htons(m->m_pkthdr.ether_vtag); mh.mh_flags = 0; mh.mh_data = (caddr_t)&evh; mh.mh_len = sizeof(evh); mh.mh_next = (struct mbuf *)&md; md.mh_flags = 0; md.mh_data = m->m_data + ETHER_HDR_LEN; md.mh_len = m->m_len - ETHER_HDR_LEN; md.mh_next = m->m_next; return _bpf_mtap(arg, m, (struct mbuf *)&mh, direction); #endif } /* * Move the packet data from interface memory (pkt) into the * store buffer. Wake up listeners if needed. * "copy" is the routine called to do the actual data * transfer. bcopy is passed in to copy contiguous chunks, while * bpf_mcopy is passed in to copy mbuf chains. In the latter case, * pkt is really an mbuf. */ void bpf_catchpacket(struct bpf_d *d, u_char *pkt, size_t pktlen, size_t snaplen, const struct bpf_hdr *tbh) { struct bpf_hdr *bh; int totlen, curlen; int hdrlen, do_wakeup = 0; MUTEX_ASSERT_LOCKED(&d->bd_mtx); if (d->bd_bif == NULL) return; hdrlen = d->bd_bif->bif_hdrlen; /* * Figure out how many bytes to move. If the packet is * greater or equal to the snapshot length, transfer that * much. Otherwise, transfer the whole packet (unless * we hit the buffer size limit). */ totlen = hdrlen + min(snaplen, pktlen); if (totlen > d->bd_bufsize) totlen = d->bd_bufsize; /* * Round up the end of the previous packet to the next longword. */ curlen = BPF_WORDALIGN(d->bd_slen); if (curlen + totlen > d->bd_bufsize) { /* * This packet will overflow the storage buffer. * Rotate the buffers if we can, then wakeup any * pending reads. */ if (d->bd_fbuf == NULL) { /* * We haven't completed the previous read yet, * so drop the packet. */ ++d->bd_dcount; return; } /* cancel pending wtime */ if (timeout_del(&d->bd_wait_tmo)) bpf_put(d); ROTATE_BUFFERS(d); do_wakeup = 1; curlen = 0; } /* * Append the bpf header. */ bh = (struct bpf_hdr *)(d->bd_sbuf + curlen); *bh = *tbh; bh->bh_datalen = pktlen; bh->bh_hdrlen = hdrlen; bh->bh_caplen = totlen - hdrlen; /* * Copy the packet data into the store buffer and update its length. */ bpf_mcopy(pkt, (u_char *)bh + hdrlen, bh->bh_caplen); d->bd_slen = curlen + totlen; switch (d->bd_wtout) { case 0: /* * Immediate mode is set. A packet arrived so any * reads should be woken up. */ if (d->bd_state == BPF_S_IDLE) d->bd_state = BPF_S_DONE; do_wakeup = 1; break; case INFSLP: break; default: if (d->bd_state == BPF_S_IDLE) { d->bd_state = BPF_S_WAIT; bpf_get(d); if (!timeout_add_nsec(&d->bd_wait_tmo, d->bd_wtout)) bpf_put(d); } break; } if (do_wakeup) bpf_wakeup(d); } /* * Initialize all nonzero fields of a descriptor. */ int bpf_allocbufs(struct bpf_d *d) { MUTEX_ASSERT_LOCKED(&d->bd_mtx); d->bd_fbuf = malloc(d->bd_bufsize, M_DEVBUF, M_NOWAIT); if (d->bd_fbuf == NULL) return (ENOMEM); d->bd_sbuf = malloc(d->bd_bufsize, M_DEVBUF, M_NOWAIT); if (d->bd_sbuf == NULL) { free(d->bd_fbuf, M_DEVBUF, d->bd_bufsize); d->bd_fbuf = NULL; return (ENOMEM); } d->bd_slen = 0; d->bd_hlen = 0; return (0); } void bpf_prog_smr(void *bps_arg) { struct bpf_program_smr *bps = bps_arg; free(bps->bps_bf.bf_insns, M_DEVBUF, bps->bps_bf.bf_len * sizeof(struct bpf_insn)); free(bps, M_DEVBUF, sizeof(struct bpf_program_smr)); } void bpf_d_smr(void *smr) { struct bpf_d *bd = smr; sigio_free(&bd->bd_sigio); free(bd->bd_sbuf, M_DEVBUF, bd->bd_bufsize); free(bd->bd_hbuf, M_DEVBUF, bd->bd_bufsize); free(bd->bd_fbuf, M_DEVBUF, bd->bd_bufsize); if (bd->bd_rfilter != NULL) bpf_prog_smr(bd->bd_rfilter); if (bd->bd_wfilter != NULL) bpf_prog_smr(bd->bd_wfilter); klist_free(&bd->bd_klist); free(bd, M_DEVBUF, sizeof(*bd)); } void bpf_get(struct bpf_d *bd) { refcnt_take(&bd->bd_refcnt); } /* * Free buffers currently in use by a descriptor * when the reference count drops to zero. */ void bpf_put(struct bpf_d *bd) { if (refcnt_rele(&bd->bd_refcnt) == 0) return; smr_call(&bd->bd_smr, bpf_d_smr, bd); } void * bpfsattach(caddr_t *bpfp, const char *name, u_int dlt, u_int hdrlen) { struct bpf_if *bp; if ((bp = malloc(sizeof(*bp), M_DEVBUF, M_NOWAIT)) == NULL) panic("bpfattach"); SMR_SLIST_INIT(&bp->bif_dlist); bp->bif_driverp = (struct bpf_if **)bpfp; bp->bif_name = name; bp->bif_ifp = NULL; bp->bif_dlt = dlt; bp->bif_next = bpf_iflist; bpf_iflist = bp; *bp->bif_driverp = NULL; /* * Compute the length of the bpf header. This is not necessarily * equal to SIZEOF_BPF_HDR because we want to insert spacing such * that the network layer header begins on a longword boundary (for * performance reasons and to alleviate alignment restrictions). */ bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + SIZEOF_BPF_HDR) - hdrlen; return (bp); } void bpfattach(caddr_t *driverp, struct ifnet *ifp, u_int dlt, u_int hdrlen) { struct bpf_if *bp; bp = bpfsattach(driverp, ifp->if_xname, dlt, hdrlen); bp->bif_ifp = ifp; } /* Detach an interface from its attached bpf device. */ void bpfdetach(struct ifnet *ifp) { struct bpf_if *bp, *nbp; KERNEL_ASSERT_LOCKED(); for (bp = bpf_iflist; bp; bp = nbp) { nbp = bp->bif_next; if (bp->bif_ifp == ifp) bpfsdetach(bp); } ifp->if_bpf = NULL; } void bpfsdetach(void *p) { struct bpf_if *bp = p, *tbp; struct bpf_d *bd; int maj; KERNEL_ASSERT_LOCKED(); /* Locate the major number. */ for (maj = 0; maj < nchrdev; maj++) if (cdevsw[maj].d_open == bpfopen) break; while ((bd = SMR_SLIST_FIRST_LOCKED(&bp->bif_dlist))) { vdevgone(maj, bd->bd_unit, bd->bd_unit, VCHR); klist_invalidate(&bd->bd_klist); } for (tbp = bpf_iflist; tbp; tbp = tbp->bif_next) { if (tbp->bif_next == bp) { tbp->bif_next = bp->bif_next; break; } } if (bpf_iflist == bp) bpf_iflist = bp->bif_next; free(bp, M_DEVBUF, sizeof(*bp)); } int bpf_sysctl_locked(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { switch (name[0]) { case NET_BPF_BUFSIZE: return sysctl_int_bounded(oldp, oldlenp, newp, newlen, &bpf_bufsize, BPF_MINBUFSIZE, bpf_maxbufsize); case NET_BPF_MAXBUFSIZE: return sysctl_int_bounded(oldp, oldlenp, newp, newlen, &bpf_maxbufsize, BPF_MINBUFSIZE, INT_MAX); default: return (EOPNOTSUPP); } } int bpf_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int flags = RW_INTR; int error; if (namelen != 1) return (ENOTDIR); flags |= (newp == NULL) ? RW_READ : RW_WRITE; error = rw_enter(&bpf_sysctl_lk, flags); if (error != 0) return (error); error = bpf_sysctl_locked(name, namelen, oldp, oldlenp, newp, newlen); rw_exit(&bpf_sysctl_lk); return (error); } struct bpf_d * bpfilter_lookup(int unit) { struct bpf_d *bd; KERNEL_ASSERT_LOCKED(); LIST_FOREACH(bd, &bpf_d_list, bd_list) if (bd->bd_unit == unit) return (bd); return (NULL); } /* * Get a list of available data link type of the interface. */ int bpf_getdltlist(struct bpf_d *d, struct bpf_dltlist *bfl) { int n, error; struct bpf_if *bp; const char *name; name = d->bd_bif->bif_name; n = 0; error = 0; for (bp = bpf_iflist; bp != NULL; bp = bp->bif_next) { if (strcmp(name, bp->bif_name) != 0) continue; if (bfl->bfl_list != NULL) { if (n >= bfl->bfl_len) return (ENOMEM); error = copyout(&bp->bif_dlt, bfl->bfl_list + n, sizeof(u_int)); if (error) break; } n++; } bfl->bfl_len = n; return (error); } /* * Set the data link type of a BPF instance. */ int bpf_setdlt(struct bpf_d *d, u_int dlt) { const char *name; struct bpf_if *bp; MUTEX_ASSERT_LOCKED(&d->bd_mtx); if (d->bd_bif->bif_dlt == dlt) return (0); name = d->bd_bif->bif_name; for (bp = bpf_iflist; bp != NULL; bp = bp->bif_next) { if (strcmp(name, bp->bif_name) != 0) continue; if (bp->bif_dlt == dlt) break; } if (bp == NULL) return (EINVAL); bpf_detachd(d); bpf_attachd(d, bp); bpf_resetd(d); return (0); } u_int32_t bpf_mbuf_ldw(const void *, u_int32_t, int *); u_int32_t bpf_mbuf_ldh(const void *, u_int32_t, int *); u_int32_t bpf_mbuf_ldb(const void *, u_int32_t, int *); int bpf_mbuf_copy(const struct mbuf *, u_int32_t, void *, u_int32_t); const struct bpf_ops bpf_mbuf_ops = { bpf_mbuf_ldw, bpf_mbuf_ldh, bpf_mbuf_ldb, }; int bpf_mbuf_copy(const struct mbuf *m, u_int32_t off, void *buf, u_int32_t len) { u_int8_t *cp = buf; u_int32_t count; while (off >= m->m_len) { off -= m->m_len; m = m->m_next; if (m == NULL) return (-1); } for (;;) { count = min(m->m_len - off, len); memcpy(cp, m->m_data + off, count); len -= count; if (len == 0) return (0); m = m->m_next; if (m == NULL) break; cp += count; off = 0; } return (-1); } u_int32_t bpf_mbuf_ldw(const void *m0, u_int32_t k, int *err) { u_int32_t v; if (bpf_mbuf_copy(m0, k, &v, sizeof(v)) != 0) { *err = 1; return (0); } *err = 0; return ntohl(v); } u_int32_t bpf_mbuf_ldh(const void *m0, u_int32_t k, int *err) { u_int16_t v; if (bpf_mbuf_copy(m0, k, &v, sizeof(v)) != 0) { *err = 1; return (0); } *err = 0; return ntohs(v); } u_int32_t bpf_mbuf_ldb(const void *m0, u_int32_t k, int *err) { const struct mbuf *m = m0; u_int8_t v; while (k >= m->m_len) { k -= m->m_len; m = m->m_next; if (m == NULL) { *err = 1; return (0); } } v = m->m_data[k]; *err = 0; return v; } u_int bpf_mfilter(const struct bpf_insn *pc, const struct mbuf *m, u_int wirelen) { return _bpf_filter(pc, &bpf_mbuf_ops, m, wirelen); }
8 8 2 2 9 8 3 9 22 22 13 22 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 /* $OpenBSD: dead_vnops.c,v 1.42 2023/03/08 04:43:08 guenther Exp $ */ /* $NetBSD: dead_vnops.c,v 1.16 1996/02/13 13:12:48 mycroft Exp $ */ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)dead_vnops.c 8.2 (Berkeley) 11/21/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/event.h> #include <sys/time.h> #include <sys/vnode.h> #include <sys/lock.h> #include <sys/errno.h> #include <sys/buf.h> /* * Prototypes for dead operations on vnodes. */ int dead_ebadf(void *); int dead_open(void *); int dead_read(void *); int dead_write(void *); int dead_ioctl(void *); int dead_kqfilter(void *v); int dead_inactive(void *); int dead_lock(void *); int dead_bmap(void *); int dead_strategy(void *); int dead_print(void *); int chkvnlock(struct vnode *); const struct vops dead_vops = { .vop_lookup = vop_generic_lookup, .vop_create = vop_generic_badop, .vop_mknod = vop_generic_badop, .vop_open = dead_open, .vop_close = nullop, .vop_access = dead_ebadf, .vop_getattr = dead_ebadf, .vop_setattr = dead_ebadf, .vop_read = dead_read, .vop_write = dead_write, .vop_ioctl = dead_ioctl, .vop_kqfilter = dead_kqfilter, .vop_revoke = NULL, .vop_fsync = nullop, .vop_remove = vop_generic_badop, .vop_link = vop_generic_badop, .vop_rename = vop_generic_badop, .vop_mkdir = vop_generic_badop, .vop_rmdir = vop_generic_badop, .vop_symlink = vop_generic_badop, .vop_readdir = dead_ebadf, .vop_readlink = dead_ebadf, .vop_abortop = vop_generic_badop, .vop_inactive = dead_inactive, .vop_reclaim = nullop, .vop_lock = dead_lock, .vop_unlock = nullop, .vop_islocked = nullop, .vop_bmap = dead_bmap, .vop_strategy = dead_strategy, .vop_print = dead_print, .vop_pathconf = dead_ebadf, .vop_advlock = dead_ebadf, .vop_bwrite = nullop, }; /* * Open always fails as if device did not exist. */ int dead_open(void *v) { return (ENXIO); } /* * Vnode op for read */ int dead_read(void *v) { struct vop_read_args *ap = v; if (chkvnlock(ap->a_vp)) panic("dead_read: lock"); /* * Return EOF for tty devices, EIO for others */ if ((ap->a_vp->v_flag & VISTTY) == 0) return (EIO); return (0); } /* * Vnode op for write */ int dead_write(void *v) { struct vop_write_args *ap = v; if (chkvnlock(ap->a_vp)) panic("dead_write: lock"); return (EIO); } /* * Device ioctl operation. */ int dead_ioctl(void *v) { struct vop_ioctl_args *ap = v; if (!chkvnlock(ap->a_vp)) return (EBADF); return ((ap->a_vp->v_op->vop_ioctl)(ap)); } int dead_kqfilter(void *v) { struct vop_kqfilter_args *ap = v; switch (ap->a_kn->kn_filter) { case EVFILT_READ: case EVFILT_WRITE: ap->a_kn->kn_fop = &dead_filtops; break; case EVFILT_EXCEPT: if ((ap->a_kn->kn_flags & __EV_POLL) == 0) return (EINVAL); ap->a_kn->kn_fop = &dead_filtops; break; default: return (EINVAL); } return (0); } /* * Just call the device strategy routine */ int dead_strategy(void *v) { struct vop_strategy_args *ap = v; int s; if (ap->a_bp->b_vp == NULL || !chkvnlock(ap->a_bp->b_vp)) { ap->a_bp->b_flags |= B_ERROR; s = splbio(); biodone(ap->a_bp); splx(s); return (EIO); } return (VOP_STRATEGY(ap->a_bp->b_vp, ap->a_bp)); } int dead_inactive(void *v) { struct vop_inactive_args *ap = v; VOP_UNLOCK(ap->a_vp); return (0); } /* * Wait until the vnode has finished changing state. */ int dead_lock(void *v) { struct vop_lock_args *ap = v; struct vnode *vp = ap->a_vp; if (ap->a_flags & LK_DRAIN || !chkvnlock(vp)) return (0); return VOP_LOCK(vp, ap->a_flags); } /* * Wait until the vnode has finished changing state. */ int dead_bmap(void *v) { struct vop_bmap_args *ap = v; if (!chkvnlock(ap->a_vp)) return (EIO); return (VOP_BMAP(ap->a_vp, ap->a_bn, ap->a_vpp, ap->a_bnp, ap->a_runp)); } /* * Print out the contents of a dead vnode. */ int dead_print(void *v) { printf("tag VT_NON, dead vnode\n"); return 0; } /* * Empty vnode failed operation */ int dead_ebadf(void *v) { return (EBADF); } /* * We have to wait during times when the vnode is * in a state of change. */ int chkvnlock(struct vnode *vp) { int locked = 0; mtx_enter(&vnode_mtx); while (vp->v_lflag & VXLOCK) { vp->v_lflag |= VXWANT; msleep_nsec(vp, &vnode_mtx, PINOD, "chkvnlock", INFSLP); locked = 1; } mtx_leave(&vnode_mtx); return (locked); }
4 7 6 1 5 6 4 4 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 /* $OpenBSD: if_vlan.c,v 1.218 2023/12/23 10:52:54 bluhm Exp $ */ /* * Copyright 1998 Massachusetts Institute of Technology * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that both the above copyright notice and this * permission notice appear in all copies, that both the above * copyright notice and this permission notice appear in all * supporting documentation, and that the name of M.I.T. not be used * in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. M.I.T. makes * no representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied * warranty. * * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD: src/sys/net/if_vlan.c,v 1.16 2000/03/26 15:21:40 charnier Exp $ */ /* * if_vlan.c - pseudo-device driver for IEEE 802.1Q virtual LANs. * This is sort of sneaky in the implementation, since * we need to pretend to be enough of an Ethernet implementation * to make arp work. The way we do this is by telling everyone * that we are an Ethernet, and then catch the packets that * ether_output() left on our output queue when it calls * if_start(), rewrite them for use by the real outgoing interface, * and ask it to send them. * * Some devices support 802.1Q tag insertion in firmware. The * vlan interface behavior changes when the IFCAP_VLAN_HWTAGGING * capability is set on the parent. In this case, vlan_start() * will not modify the ethernet header. */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/queue.h> #include <sys/socket.h> #include <sys/sockio.h> #include <sys/systm.h> #include <sys/rwlock.h> #include <sys/percpu.h> #include <sys/refcnt.h> #include <sys/smr.h> #include <net/if.h> #include <net/if_dl.h> #include <net/if_types.h> #include <netinet/in.h> #include <netinet/if_ether.h> #include <net/if_vlan_var.h> #include "bpfilter.h" #if NBPFILTER > 0 #include <net/bpf.h> #endif struct vlan_mc_entry { LIST_ENTRY(vlan_mc_entry) mc_entries; union { struct ether_multi *mcu_enm; } mc_u; #define mc_enm mc_u.mcu_enm struct sockaddr_storage mc_addr; }; struct vlan_softc { struct arpcom sc_ac; #define sc_if sc_ac.ac_if unsigned int sc_dead; unsigned int sc_ifidx0; /* parent interface */ int sc_txprio; int sc_rxprio; uint16_t sc_proto; /* encapsulation ethertype */ uint16_t sc_tag; uint16_t sc_type; /* non-standard ethertype or 0x8100 */ LIST_HEAD(__vlan_mchead, vlan_mc_entry) sc_mc_listhead; SMR_SLIST_ENTRY(vlan_softc) sc_list; int sc_flags; struct refcnt sc_refcnt; struct task sc_ltask; struct task sc_dtask; }; SMR_SLIST_HEAD(vlan_list, vlan_softc); #define IFVF_PROMISC 0x01 /* the parent should be made promisc */ #define IFVF_LLADDR 0x02 /* don't inherit the parents mac */ #define TAG_HASH_BITS 5 #define TAG_HASH_SIZE (1 << TAG_HASH_BITS) #define TAG_HASH_MASK (TAG_HASH_SIZE - 1) #define TAG_HASH(tag) (tag & TAG_HASH_MASK) struct vlan_list *vlan_tagh, *svlan_tagh; struct rwlock vlan_tagh_lk = RWLOCK_INITIALIZER("vlantag"); void vlanattach(int count); int vlan_clone_create(struct if_clone *, int); int vlan_clone_destroy(struct ifnet *); int vlan_enqueue(struct ifnet *, struct mbuf *); void vlan_start(struct ifqueue *ifq); int vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr); int vlan_up(struct vlan_softc *); int vlan_down(struct vlan_softc *); void vlan_ifdetach(void *); void vlan_link_hook(void *); void vlan_link_state(struct vlan_softc *, u_char, uint64_t); int vlan_set_vnetid(struct vlan_softc *, uint16_t); int vlan_set_parent(struct vlan_softc *, const char *); int vlan_del_parent(struct vlan_softc *); int vlan_inuse(uint16_t, unsigned int, uint16_t); int vlan_inuse_locked(uint16_t, unsigned int, uint16_t); int vlan_multi_add(struct vlan_softc *, struct ifreq *); int vlan_multi_del(struct vlan_softc *, struct ifreq *); void vlan_multi_apply(struct vlan_softc *, struct ifnet *, u_long); void vlan_multi_free(struct vlan_softc *); int vlan_media_get(struct vlan_softc *, struct ifreq *); int vlan_iff(struct vlan_softc *); int vlan_setlladdr(struct vlan_softc *, struct ifreq *); int vlan_set_compat(struct ifnet *, struct ifreq *); int vlan_get_compat(struct ifnet *, struct ifreq *); struct if_clone vlan_cloner = IF_CLONE_INITIALIZER("vlan", vlan_clone_create, vlan_clone_destroy); struct if_clone svlan_cloner = IF_CLONE_INITIALIZER("svlan", vlan_clone_create, vlan_clone_destroy); void vlanattach(int count) { unsigned int i; /* Normal VLAN */ vlan_tagh = mallocarray(TAG_HASH_SIZE, sizeof(*vlan_tagh), M_DEVBUF, M_NOWAIT); if (vlan_tagh == NULL) panic("vlanattach: hashinit"); /* Service-VLAN for QinQ/802.1ad provider bridges */ svlan_tagh = mallocarray(TAG_HASH_SIZE, sizeof(*svlan_tagh), M_DEVBUF, M_NOWAIT); if (svlan_tagh == NULL) panic("vlanattach: hashinit"); for (i = 0; i < TAG_HASH_SIZE; i++) { SMR_SLIST_INIT(&vlan_tagh[i]); SMR_SLIST_INIT(&svlan_tagh[i]); } if_clone_attach(&vlan_cloner); if_clone_attach(&svlan_cloner); } int vlan_clone_create(struct if_clone *ifc, int unit) { struct vlan_softc *sc; struct ifnet *ifp; sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); sc->sc_dead = 0; LIST_INIT(&sc->sc_mc_listhead); task_set(&sc->sc_ltask, vlan_link_hook, sc); task_set(&sc->sc_dtask, vlan_ifdetach, sc); ifp = &sc->sc_if; ifp->if_softc = sc; snprintf(ifp->if_xname, sizeof ifp->if_xname, "%s%d", ifc->ifc_name, unit); /* NB: flags are not set here */ /* NB: mtu is not set here */ /* Special handling for the IEEE 802.1ad QinQ variant */ if (strcmp("svlan", ifc->ifc_name) == 0) sc->sc_type = ETHERTYPE_QINQ; else sc->sc_type = ETHERTYPE_VLAN; refcnt_init(&sc->sc_refcnt); sc->sc_txprio = IF_HDRPRIO_PACKET; sc->sc_rxprio = IF_HDRPRIO_OUTER; ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST; ifp->if_xflags = IFXF_CLONED|IFXF_MPSAFE; ifp->if_qstart = vlan_start; ifp->if_enqueue = vlan_enqueue; ifp->if_ioctl = vlan_ioctl; ifp->if_hardmtu = 0xffff; ifp->if_link_state = LINK_STATE_DOWN; if_counters_alloc(ifp); if_attach(ifp); ether_ifattach(ifp); ifp->if_hdrlen = EVL_ENCAPLEN; return (0); } int vlan_clone_destroy(struct ifnet *ifp) { struct vlan_softc *sc = ifp->if_softc; NET_LOCK(); sc->sc_dead = 1; if (ISSET(ifp->if_flags, IFF_RUNNING)) vlan_down(sc); NET_UNLOCK(); ether_ifdetach(ifp); if_detach(ifp); smr_barrier(); refcnt_finalize(&sc->sc_refcnt, "vlanrefs"); vlan_multi_free(sc); free(sc, M_DEVBUF, sizeof(*sc)); return (0); } void vlan_transmit(struct vlan_softc *sc, struct ifnet *ifp0, struct mbuf *m) { struct ifnet *ifp = &sc->sc_if; int txprio = sc->sc_txprio; uint8_t prio; #if NBPFILTER > 0 if (ifp->if_bpf) bpf_mtap_ether(ifp->if_bpf, m, BPF_DIRECTION_OUT); #endif /* NBPFILTER > 0 */ prio = (txprio == IF_HDRPRIO_PACKET) ? m->m_pkthdr.pf.prio : txprio; /* IEEE 802.1p has prio 0 and 1 swapped */ if (prio <= 1) prio = !prio; /* * If the underlying interface cannot do VLAN tag insertion * itself, create an encapsulation header. */ if ((ifp0->if_capabilities & IFCAP_VLAN_HWTAGGING) && (sc->sc_type == ETHERTYPE_VLAN)) { m->m_pkthdr.ether_vtag = sc->sc_tag | (prio << EVL_PRIO_BITS); m->m_flags |= M_VLANTAG; } else { m = vlan_inject(m, sc->sc_type, sc->sc_tag | (prio << EVL_PRIO_BITS)); if (m == NULL) { counters_inc(ifp->if_counters, ifc_oerrors); return; } } if (if_enqueue(ifp0, m)) counters_inc(ifp->if_counters, ifc_oerrors); } int vlan_enqueue(struct ifnet *ifp, struct mbuf *m) { struct ifnet *ifp0; struct vlan_softc *sc; int error = 0; if (!ifq_is_priq(&ifp->if_snd)) return (if_enqueue_ifq(ifp, m)); sc = ifp->if_softc; ifp0 = if_get(sc->sc_ifidx0); if (ifp0 == NULL || !ISSET(ifp0->if_flags, IFF_RUNNING)) { m_freem(m); error = ENETDOWN; } else { counters_pkt(ifp->if_counters, ifc_opackets, ifc_obytes, m->m_pkthdr.len); vlan_transmit(sc, ifp0, m); } if_put(ifp0); return (error); } void vlan_start(struct ifqueue *ifq) { struct ifnet *ifp = ifq->ifq_if; struct vlan_softc *sc = ifp->if_softc; struct ifnet *ifp0; struct mbuf *m; ifp0 = if_get(sc->sc_ifidx0); if (ifp0 == NULL || !ISSET(ifp0->if_flags, IFF_RUNNING)) { ifq_purge(ifq); goto leave; } while ((m = ifq_dequeue(ifq)) != NULL) vlan_transmit(sc, ifp0, m); leave: if_put(ifp0); } struct mbuf * vlan_strip(struct mbuf *m) { if (ISSET(m->m_flags, M_VLANTAG)) { CLR(m->m_flags, M_VLANTAG); } else { struct ether_vlan_header *evl; evl = mtod(m, struct ether_vlan_header *); memmove((caddr_t)evl + EVL_ENCAPLEN, evl, offsetof(struct ether_vlan_header, evl_encap_proto)); m_adj(m, EVL_ENCAPLEN); } return (m); } struct mbuf * vlan_inject(struct mbuf *m, uint16_t type, uint16_t tag) { struct ether_vlan_header evh; m_copydata(m, 0, ETHER_HDR_LEN, &evh); evh.evl_proto = evh.evl_encap_proto; evh.evl_encap_proto = htons(type); evh.evl_tag = htons(tag); m_adj(m, ETHER_HDR_LEN); M_PREPEND(m, sizeof(evh) + ETHER_ALIGN, M_DONTWAIT); if (m == NULL) return (NULL); m_adj(m, ETHER_ALIGN); m_copyback(m, 0, sizeof(evh), &evh, M_NOWAIT); CLR(m->m_flags, M_VLANTAG); return (m); } struct mbuf * vlan_input(struct ifnet *ifp0, struct mbuf *m, unsigned int *sdelim) { struct vlan_softc *sc; struct ifnet *ifp; struct ether_vlan_header *evl; struct vlan_list *tagh, *list; uint16_t vtag, tag; uint16_t etype; int rxprio; if (m->m_flags & M_VLANTAG) { vtag = m->m_pkthdr.ether_vtag; etype = ETHERTYPE_VLAN; tagh = vlan_tagh; } else { if (m->m_len < sizeof(*evl)) { m = m_pullup(m, sizeof(*evl)); if (m == NULL) return (NULL); } evl = mtod(m, struct ether_vlan_header *); vtag = bemtoh16(&evl->evl_tag); etype = bemtoh16(&evl->evl_encap_proto); switch (etype) { case ETHERTYPE_VLAN: tagh = vlan_tagh; break; case ETHERTYPE_QINQ: tagh = svlan_tagh; break; default: panic("%s: unexpected etype 0x%04x", __func__, etype); /* NOTREACHED */ } } tag = EVL_VLANOFTAG(vtag); list = &tagh[TAG_HASH(tag)]; smr_read_enter(); SMR_SLIST_FOREACH(sc, list, sc_list) { if (ifp0->if_index == sc->sc_ifidx0 && tag == sc->sc_tag && etype == sc->sc_type) { refcnt_take(&sc->sc_refcnt); break; } } smr_read_leave(); if (sc == NULL) { /* VLAN 0 Priority Tagging */ if (tag == 0 && etype == ETHERTYPE_VLAN) { struct ether_header *eh; /* XXX we should actually use the prio value? */ m = vlan_strip(m); eh = mtod(m, struct ether_header *); if (eh->ether_type == htons(ETHERTYPE_VLAN) || eh->ether_type == htons(ETHERTYPE_QINQ)) { m_freem(m); return (NULL); } } else *sdelim = 1; return (m); /* decline */ } ifp = &sc->sc_if; if (!ISSET(ifp->if_flags, IFF_RUNNING)) { m_freem(m); goto leave; } /* * Having found a valid vlan interface corresponding to * the given source interface and vlan tag, remove the * encapsulation. */ m = vlan_strip(m); rxprio = sc->sc_rxprio; switch (rxprio) { case IF_HDRPRIO_PACKET: break; case IF_HDRPRIO_OUTER: m->m_pkthdr.pf.prio = EVL_PRIOFTAG(m->m_pkthdr.ether_vtag); /* IEEE 802.1p has prio 0 and 1 swapped */ if (m->m_pkthdr.pf.prio <= 1) m->m_pkthdr.pf.prio = !m->m_pkthdr.pf.prio; break; default: m->m_pkthdr.pf.prio = rxprio; break; } if_vinput(ifp, m); leave: refcnt_rele_wake(&sc->sc_refcnt); return (NULL); } int vlan_up(struct vlan_softc *sc) { struct vlan_list *tagh, *list; struct ifnet *ifp = &sc->sc_if; struct ifnet *ifp0; int error = 0; unsigned int hardmtu; KASSERT(!ISSET(ifp->if_flags, IFF_RUNNING)); tagh = sc->sc_type == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh; list = &tagh[TAG_HASH(sc->sc_tag)]; ifp0 = if_get(sc->sc_ifidx0); if (ifp0 == NULL) return (ENXIO); /* check vlan will work on top of the parent */ if (ifp0->if_type != IFT_ETHER) { error = EPROTONOSUPPORT; goto put; } hardmtu = ifp0->if_hardmtu; if (!ISSET(ifp0->if_capabilities, IFCAP_VLAN_MTU)) hardmtu -= EVL_ENCAPLEN; if (ifp->if_mtu > hardmtu) { error = ENOBUFS; goto put; } /* parent is fine, let's prepare the sc to handle packets */ ifp->if_hardmtu = hardmtu; SET(ifp->if_flags, ifp0->if_flags & IFF_SIMPLEX); if (ISSET(sc->sc_flags, IFVF_PROMISC)) { error = ifpromisc(ifp0, 1); if (error != 0) goto scrub; } /* * Note: In cases like vio(4) and em(4) where the offsets of the * csum can be freely defined, we could actually do csum offload * for VLAN and QINQ packets. */ if (sc->sc_type != ETHERTYPE_VLAN) { /* * Hardware offload only works with the default VLAN * ethernet type (0x8100). */ ifp->if_capabilities = 0; } else if (ISSET(ifp0->if_capabilities, IFCAP_VLAN_HWTAGGING)) { /* * Chips that can do hardware-assisted VLAN encapsulation, can * calculate the correct checksum for VLAN tagged packets. */ ifp->if_capabilities = ifp0->if_capabilities & (IFCAP_CSUM_MASK | IFCAP_TSOv4 | IFCAP_TSOv6); } /* commit the sc */ error = rw_enter(&vlan_tagh_lk, RW_WRITE | RW_INTR); if (error != 0) goto unpromisc; error = vlan_inuse_locked(sc->sc_type, sc->sc_ifidx0, sc->sc_tag); if (error != 0) goto leave; SMR_SLIST_INSERT_HEAD_LOCKED(list, sc, sc_list); rw_exit(&vlan_tagh_lk); /* Register callback for physical link state changes */ if_linkstatehook_add(ifp0, &sc->sc_ltask); /* Register callback if parent wants to unregister */ if_detachhook_add(ifp0, &sc->sc_dtask); /* configure the parent to handle packets for this vlan */ vlan_multi_apply(sc, ifp0, SIOCADDMULTI); /* we're running now */ SET(ifp->if_flags, IFF_RUNNING); vlan_link_state(sc, ifp0->if_link_state, ifp0->if_baudrate); if_put(ifp0); return (ENETRESET); leave: rw_exit(&vlan_tagh_lk); unpromisc: if (ISSET(sc->sc_flags, IFVF_PROMISC)) (void)ifpromisc(ifp0, 0); /* XXX */ scrub: ifp->if_capabilities = 0; CLR(ifp->if_flags, IFF_SIMPLEX); ifp->if_hardmtu = 0xffff; put: if_put(ifp0); return (error); } int vlan_down(struct vlan_softc *sc) { struct vlan_list *tagh, *list; struct ifnet *ifp = &sc->sc_if; struct ifnet *ifp0; tagh = sc->sc_type == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh; list = &tagh[TAG_HASH(sc->sc_tag)]; KASSERT(ISSET(ifp->if_flags, IFF_RUNNING)); vlan_link_state(sc, LINK_STATE_DOWN, 0); CLR(ifp->if_flags, IFF_RUNNING); ifq_barrier(&ifp->if_snd); ifp0 = if_get(sc->sc_ifidx0); if (ifp0 != NULL) { if (ISSET(sc->sc_flags, IFVF_PROMISC)) ifpromisc(ifp0, 0); vlan_multi_apply(sc, ifp0, SIOCDELMULTI); if_detachhook_del(ifp0, &sc->sc_dtask); if_linkstatehook_del(ifp0, &sc->sc_ltask); } if_put(ifp0); rw_enter_write(&vlan_tagh_lk); SMR_SLIST_REMOVE_LOCKED(list, sc, vlan_softc, sc_list); rw_exit_write(&vlan_tagh_lk); ifp->if_capabilities = 0; CLR(ifp->if_flags, IFF_SIMPLEX); ifp->if_hardmtu = 0xffff; return (0); } void vlan_ifdetach(void *v) { struct vlan_softc *sc = v; struct ifnet *ifp = &sc->sc_if; if (ISSET(ifp->if_flags, IFF_RUNNING)) { vlan_down(sc); CLR(ifp->if_flags, IFF_UP); } sc->sc_ifidx0 = 0; } void vlan_link_hook(void *v) { struct vlan_softc *sc = v; struct ifnet *ifp0; u_char link = LINK_STATE_DOWN; uint64_t baud = 0; ifp0 = if_get(sc->sc_ifidx0); if (ifp0 != NULL) { link = ifp0->if_link_state; baud = ifp0->if_baudrate; } if_put(ifp0); vlan_link_state(sc, link, baud); } void vlan_link_state(struct vlan_softc *sc, u_char link, uint64_t baud) { if (sc->sc_if.if_link_state == link) return; sc->sc_if.if_link_state = link; sc->sc_if.if_baudrate = baud; if_link_state_change(&sc->sc_if); } int vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct vlan_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *)data; struct if_parent *parent = (struct if_parent *)data; struct ifnet *ifp0; uint16_t tag; int error = 0; if (sc->sc_dead) return (ENXIO); switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; /* FALLTHROUGH */ case SIOCSIFFLAGS: if (ISSET(ifp->if_flags, IFF_UP)) { if (!ISSET(ifp->if_flags, IFF_RUNNING)) error = vlan_up(sc); else error = ENETRESET; } else { if (ISSET(ifp->if_flags, IFF_RUNNING)) error = vlan_down(sc); } break; case SIOCSVNETID: if (ifr->ifr_vnetid < EVL_VLID_MIN || ifr->ifr_vnetid > EVL_VLID_MAX) { error = EINVAL; break; } tag = ifr->ifr_vnetid; if (tag == sc->sc_tag) break; error = vlan_set_vnetid(sc, tag); break; case SIOCGVNETID: if (sc->sc_tag == EVL_VLID_NULL) error = EADDRNOTAVAIL; else ifr->ifr_vnetid = (int64_t)sc->sc_tag; break; case SIOCDVNETID: error = vlan_set_vnetid(sc, 0); break; case SIOCSIFPARENT: error = vlan_set_parent(sc, parent->ifp_parent); break; case SIOCGIFPARENT: ifp0 = if_get(sc->sc_ifidx0); if (ifp0 == NULL) error = EADDRNOTAVAIL; else { memcpy(parent->ifp_parent, ifp0->if_xname, sizeof(parent->ifp_parent)); } if_put(ifp0); break; case SIOCDIFPARENT: error = vlan_del_parent(sc); break; case SIOCADDMULTI: error = vlan_multi_add(sc, ifr); break; case SIOCDELMULTI: error = vlan_multi_del(sc, ifr); break; case SIOCGIFMEDIA: error = vlan_media_get(sc, ifr); break; case SIOCSIFMEDIA: error = ENOTTY; break; case SIOCSIFLLADDR: error = vlan_setlladdr(sc, ifr); break; case SIOCSETVLAN: error = vlan_set_compat(ifp, ifr); break; case SIOCGETVLAN: error = vlan_get_compat(ifp, ifr); break; case SIOCSTXHPRIO: error = if_txhprio_l2_check(ifr->ifr_hdrprio); if (error != 0) break; sc->sc_txprio = ifr->ifr_hdrprio; break; case SIOCGTXHPRIO: ifr->ifr_hdrprio = sc->sc_txprio; break; case SIOCSRXHPRIO: error = if_rxhprio_l2_check(ifr->ifr_hdrprio); if (error != 0) break; sc->sc_rxprio = ifr->ifr_hdrprio; break; case SIOCGRXHPRIO: ifr->ifr_hdrprio = sc->sc_rxprio; break; default: error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); break; } if (error == ENETRESET) error = vlan_iff(sc); return error; } int vlan_iff(struct vlan_softc *sc) { struct ifnet *ifp0; int promisc = 0; int error = 0; if (ISSET(sc->sc_if.if_flags, IFF_PROMISC) || ISSET(sc->sc_flags, IFVF_LLADDR)) promisc = IFVF_PROMISC; if (ISSET(sc->sc_flags, IFVF_PROMISC) == promisc) return (0); if (ISSET(sc->sc_if.if_flags, IFF_RUNNING)) { ifp0 = if_get(sc->sc_ifidx0); if (ifp0 != NULL) error = ifpromisc(ifp0, promisc); if_put(ifp0); } if (error == 0) { CLR(sc->sc_flags, IFVF_PROMISC); SET(sc->sc_flags, promisc); } return (error); } int vlan_setlladdr(struct vlan_softc *sc, struct ifreq *ifr) { struct ifnet *ifp = &sc->sc_if; struct ifnet *ifp0; uint8_t lladdr[ETHER_ADDR_LEN]; int flag; memcpy(lladdr, ifr->ifr_addr.sa_data, sizeof(lladdr)); /* setting the mac addr to 00:00:00:00:00:00 means reset lladdr */ if (memcmp(lladdr, etheranyaddr, sizeof(lladdr)) == 0) { ifp0 = if_get(sc->sc_ifidx0); if (ifp0 != NULL) memcpy(lladdr, LLADDR(ifp0->if_sadl), sizeof(lladdr)); if_put(ifp0); flag = 0; } else flag = IFVF_LLADDR; if (memcmp(lladdr, LLADDR(ifp->if_sadl), sizeof(lladdr)) == 0 && ISSET(sc->sc_flags, IFVF_LLADDR) == flag) { /* nop */ return (0); } /* commit */ if_setlladdr(ifp, lladdr); CLR(sc->sc_flags, IFVF_LLADDR); SET(sc->sc_flags, flag); return (ENETRESET); } int vlan_set_vnetid(struct vlan_softc *sc, uint16_t tag) { struct ifnet *ifp = &sc->sc_if; struct vlan_list *tagh, *list; u_char link = ifp->if_link_state; uint64_t baud = ifp->if_baudrate; int error; tagh = sc->sc_type == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh; if (ISSET(ifp->if_flags, IFF_RUNNING) && LINK_STATE_IS_UP(link)) vlan_link_state(sc, LINK_STATE_DOWN, 0); error = rw_enter(&vlan_tagh_lk, RW_WRITE); if (error != 0) return (error); error = vlan_inuse_locked(sc->sc_type, sc->sc_ifidx0, tag); if (error != 0) goto unlock; if (ISSET(ifp->if_flags, IFF_RUNNING)) { list = &tagh[TAG_HASH(sc->sc_tag)]; SMR_SLIST_REMOVE_LOCKED(list, sc, vlan_softc, sc_list); sc->sc_tag = tag; list = &tagh[TAG_HASH(sc->sc_tag)]; SMR_SLIST_INSERT_HEAD_LOCKED(list, sc, sc_list); } else sc->sc_tag = tag; unlock: rw_exit(&vlan_tagh_lk); if (ISSET(ifp->if_flags, IFF_RUNNING) && LINK_STATE_IS_UP(link)) vlan_link_state(sc, link, baud); return (error); } int vlan_set_parent(struct vlan_softc *sc, const char *parent) { struct ifnet *ifp = &sc->sc_if; struct ifnet *ifp0; int error = 0; ifp0 = if_unit(parent); if (ifp0 == NULL) return (EINVAL); if (ifp0->if_type != IFT_ETHER) { error = EPROTONOSUPPORT; goto put; } if (sc->sc_ifidx0 == ifp0->if_index) { /* nop */ goto put; } if (ISSET(ifp->if_flags, IFF_RUNNING)) { error = EBUSY; goto put; } error = vlan_inuse(sc->sc_type, ifp0->if_index, sc->sc_tag); if (error != 0) goto put; if (ether_brport_isset(ifp)) ifsetlro(ifp0, 0); /* commit */ sc->sc_ifidx0 = ifp0->if_index; if (!ISSET(sc->sc_flags, IFVF_LLADDR)) if_setlladdr(ifp, LLADDR(ifp0->if_sadl)); put: if_put(ifp0); return (error); } int vlan_del_parent(struct vlan_softc *sc) { struct ifnet *ifp = &sc->sc_if; if (ISSET(ifp->if_flags, IFF_RUNNING)) return (EBUSY); /* commit */ sc->sc_ifidx0 = 0; if (!ISSET(sc->sc_flags, IFVF_LLADDR)) if_setlladdr(ifp, etheranyaddr); return (0); } int vlan_set_compat(struct ifnet *ifp, struct ifreq *ifr) { struct vlanreq vlr; struct ifreq req; struct if_parent parent; int error; error = suser(curproc); if (error != 0) return (error); error = copyin(ifr->ifr_data, &vlr, sizeof(vlr)); if (error != 0) return (error); if (vlr.vlr_parent[0] == '\0') return (vlan_ioctl(ifp, SIOCDIFPARENT, (caddr_t)ifr)); memset(&req, 0, sizeof(req)); memcpy(req.ifr_name, ifp->if_xname, sizeof(req.ifr_name)); req.ifr_vnetid = vlr.vlr_tag; error = vlan_ioctl(ifp, SIOCSVNETID, (caddr_t)&req); if (error != 0) return (error); memset(&parent, 0, sizeof(parent)); memcpy(parent.ifp_name, ifp->if_xname, sizeof(parent.ifp_name)); memcpy(parent.ifp_parent, vlr.vlr_parent, sizeof(parent.ifp_parent)); error = vlan_ioctl(ifp, SIOCSIFPARENT, (caddr_t)&parent); if (error != 0) return (error); memset(&req, 0, sizeof(req)); memcpy(req.ifr_name, ifp->if_xname, sizeof(req.ifr_name)); SET(ifp->if_flags, IFF_UP); return (vlan_ioctl(ifp, SIOCSIFFLAGS, (caddr_t)&req)); } int vlan_get_compat(struct ifnet *ifp, struct ifreq *ifr) { struct vlan_softc *sc = ifp->if_softc; struct vlanreq vlr; struct ifnet *p; memset(&vlr, 0, sizeof(vlr)); p = if_get(sc->sc_ifidx0); if (p != NULL) memcpy(vlr.vlr_parent, p->if_xname, sizeof(vlr.vlr_parent)); if_put(p); vlr.vlr_tag = sc->sc_tag; return (copyout(&vlr, ifr->ifr_data, sizeof(vlr))); } /* * do a quick check of up and running vlans for existing configurations. * * NOTE: this does allow the same config on down vlans, but vlan_up() * will catch them. */ int vlan_inuse(uint16_t type, unsigned int ifidx, uint16_t tag) { int error = 0; error = rw_enter(&vlan_tagh_lk, RW_READ | RW_INTR); if (error != 0) return (error); error = vlan_inuse_locked(type, ifidx, tag); rw_exit(&vlan_tagh_lk); return (error); } int vlan_inuse_locked(uint16_t type, unsigned int ifidx, uint16_t tag) { struct vlan_list *tagh, *list; struct vlan_softc *sc; tagh = type == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh; list = &tagh[TAG_HASH(tag)]; SMR_SLIST_FOREACH_LOCKED(sc, list, sc_list) { if (sc->sc_tag == tag && sc->sc_type == type && /* wat */ sc->sc_ifidx0 == ifidx) return (EADDRINUSE); } return (0); } int vlan_multi_add(struct vlan_softc *sc, struct ifreq *ifr) { struct ifnet *ifp0; struct vlan_mc_entry *mc; uint8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN]; int error; error = ether_addmulti(ifr, &sc->sc_ac); if (error != ENETRESET) return (error); /* * This is new multicast address. We have to tell parent * about it. Also, remember this multicast address so that * we can delete them on unconfigure. */ if ((mc = malloc(sizeof(*mc), M_DEVBUF, M_NOWAIT)) == NULL) { error = ENOMEM; goto alloc_failed; } /* * As ether_addmulti() returns ENETRESET, following two * statement shouldn't fail. */ (void)ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi); ETHER_LOOKUP_MULTI(addrlo, addrhi, &sc->sc_ac, mc->mc_enm); memcpy(&mc->mc_addr, &ifr->ifr_addr, ifr->ifr_addr.sa_len); LIST_INSERT_HEAD(&sc->sc_mc_listhead, mc, mc_entries); ifp0 = if_get(sc->sc_ifidx0); error = (ifp0 == NULL) ? 0 : (*ifp0->if_ioctl)(ifp0, SIOCADDMULTI, (caddr_t)ifr); if_put(ifp0); if (error != 0) goto ioctl_failed; return (error); ioctl_failed: LIST_REMOVE(mc, mc_entries); free(mc, M_DEVBUF, sizeof(*mc)); alloc_failed: (void)ether_delmulti(ifr, &sc->sc_ac); return (error); } int vlan_multi_del(struct vlan_softc *sc, struct ifreq *ifr) { struct ifnet *ifp0; struct ether_multi *enm; struct vlan_mc_entry *mc; uint8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN]; int error; /* * Find a key to lookup vlan_mc_entry. We have to do this * before calling ether_delmulti for obvious reason. */ if ((error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi)) != 0) return (error); ETHER_LOOKUP_MULTI(addrlo, addrhi, &sc->sc_ac, enm); if (enm == NULL) return (EINVAL); LIST_FOREACH(mc, &sc->sc_mc_listhead, mc_entries) { if (mc->mc_enm == enm) break; } /* We won't delete entries we didn't add */ if (mc == NULL) return (EINVAL); error = ether_delmulti(ifr, &sc->sc_ac); if (error != ENETRESET) return (error); if (!ISSET(sc->sc_if.if_flags, IFF_RUNNING)) goto forget; ifp0 = if_get(sc->sc_ifidx0); error = (ifp0 == NULL) ? 0 : (*ifp0->if_ioctl)(ifp0, SIOCDELMULTI, (caddr_t)ifr); if_put(ifp0); if (error != 0) { (void)ether_addmulti(ifr, &sc->sc_ac); return (error); } forget: /* forget about this address */ LIST_REMOVE(mc, mc_entries); free(mc, M_DEVBUF, sizeof(*mc)); return (0); } int vlan_media_get(struct vlan_softc *sc, struct ifreq *ifr) { struct ifnet *ifp0; int error; ifp0 = if_get(sc->sc_ifidx0); error = (ifp0 == NULL) ? ENOTTY : (*ifp0->if_ioctl)(ifp0, SIOCGIFMEDIA, (caddr_t)ifr); if_put(ifp0); return (error); } void vlan_multi_apply(struct vlan_softc *sc, struct ifnet *ifp0, u_long cmd) { struct vlan_mc_entry *mc; union { struct ifreq ifreq; struct { char ifr_name[IFNAMSIZ]; struct sockaddr_storage ifr_ss; } ifreq_storage; } ifreq; struct ifreq *ifr = &ifreq.ifreq; memcpy(ifr->ifr_name, ifp0->if_xname, IFNAMSIZ); LIST_FOREACH(mc, &sc->sc_mc_listhead, mc_entries) { memcpy(&ifr->ifr_addr, &mc->mc_addr, mc->mc_addr.ss_len); (void)(*ifp0->if_ioctl)(ifp0, cmd, (caddr_t)ifr); } } void vlan_multi_free(struct vlan_softc *sc) { struct vlan_mc_entry *mc; while ((mc = LIST_FIRST(&sc->sc_mc_listhead)) != NULL) { LIST_REMOVE(mc, mc_entries); free(mc, M_DEVBUF, sizeof(*mc)); } }
1 1 1 3 1 3 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 /* $OpenBSD: uhid.c,v 1.91 2024/05/23 03:21:09 jsg Exp $ */ /* $NetBSD: uhid.c,v 1.57 2003/03/11 16:44:00 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Lennart Augustsson (lennart@augustsson.net) at * Carlstedt Research & Technology. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * HID spec: https://www.usb.org/sites/default/files/hid1_11.pdf */ #include "fido.h" #include "ujoy.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/device.h> #include <sys/conf.h> #include <sys/tty.h> #include <sys/selinfo.h> #include <sys/vnode.h> #include <dev/usb/usb.h> #include <dev/usb/usbhid.h> #include <dev/usb/usbdi.h> #include <dev/usb/usbdi_util.h> #include <dev/usb/uhidev.h> #include <dev/usb/uhid.h> #ifdef UHID_DEBUG #define DPRINTF(x) do { if (uhiddebug) printf x; } while (0) #define DPRINTFN(n,x) do { if (uhiddebug>(n)) printf x; } while (0) int uhiddebug = 0; #else #define DPRINTF(x) #define DPRINTFN(n,x) #endif int uhid_match(struct device *, void *, void *); struct cfdriver uhid_cd = { NULL, "uhid", DV_DULL }; const struct cfattach uhid_ca = { sizeof(struct uhid_softc), uhid_match, uhid_attach, uhid_detach, }; struct uhid_softc * uhid_lookup(dev_t dev) { struct uhid_softc *sc = NULL; struct cdevsw *cdev; struct cfdriver *cd; cdev = &cdevsw[major(dev)]; if (cdev->d_open == uhidopen) cd = &uhid_cd; #if NFIDO > 0 else if (cdev->d_open == fidoopen) cd = &fido_cd; #endif #if NUJOY > 0 else if (cdev->d_open == ujoyopen) cd = &ujoy_cd; #endif else return (NULL); if (UHIDUNIT(dev) < cd->cd_ndevs) sc = cd->cd_devs[UHIDUNIT(dev)]; return (sc); } int uhid_match(struct device *parent, void *match, void *aux) { struct uhidev_attach_arg *uha = aux; if (UHIDEV_CLAIM_MULTIPLE_REPORTID(uha)) return (UMATCH_NONE); return (UMATCH_IFACECLASS_GENERIC); } void uhid_attach(struct device *parent, struct device *self, void *aux) { struct uhid_softc *sc = (struct uhid_softc *)self; struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux; int size, repid; void *desc; sc->sc_hdev.sc_intr = uhid_intr; sc->sc_hdev.sc_parent = uha->parent; sc->sc_hdev.sc_udev = uha->uaa->device; sc->sc_hdev.sc_report_id = uha->reportid; uhidev_get_report_desc(uha->parent, &desc, &size); repid = uha->reportid; sc->sc_hdev.sc_isize = hid_report_size(desc, size, hid_input, repid); sc->sc_hdev.sc_osize = hid_report_size(desc, size, hid_output, repid); sc->sc_hdev.sc_fsize = hid_report_size(desc, size, hid_feature, repid); printf(": input=%d, output=%d, feature=%d\n", sc->sc_hdev.sc_isize, sc->sc_hdev.sc_osize, sc->sc_hdev.sc_fsize); } int uhid_detach(struct device *self, int flags) { struct uhid_softc *sc = (struct uhid_softc *)self; int s; int maj, mn; DPRINTF(("uhid_detach: sc=%p flags=%d\n", sc, flags)); if (sc->sc_hdev.sc_state & UHIDEV_OPEN) { s = splusb(); if (--sc->sc_refcnt >= 0) { /* Wake everyone */ wakeup(&sc->sc_q); /* Wait for processes to go away. */ usb_detach_wait(&sc->sc_hdev.sc_dev); } splx(s); } /* locate the major number */ for (maj = 0; maj < nchrdev; maj++) if (cdevsw[maj].d_open == uhidopen) break; /* Nuke the vnodes for any open instances (calls close). */ mn = self->dv_unit; vdevgone(maj, mn, mn, VCHR); s = splusb(); klist_invalidate(&sc->sc_rsel.si_note); splx(s); return (0); } void uhid_intr(struct uhidev *addr, void *data, u_int len) { struct uhid_softc *sc = (struct uhid_softc *)addr; #ifdef UHID_DEBUG if (uhiddebug > 5) { u_int32_t i; DPRINTF(("uhid_intr: data =")); for (i = 0; i < len; i++) DPRINTF((" %02x", ((u_char *)data)[i])); DPRINTF(("\n")); } #endif (void)b_to_q(data, len, &sc->sc_q); if (sc->sc_state & UHID_ASLP) { sc->sc_state &= ~UHID_ASLP; DPRINTFN(5, ("uhid_intr: waking %p\n", &sc->sc_q)); wakeup(&sc->sc_q); } selwakeup(&sc->sc_rsel); } int uhidopen(dev_t dev, int flag, int mode, struct proc *p) { return (uhid_do_open(dev, flag, mode, p)); } int uhid_do_open(dev_t dev, int flag, int mode, struct proc *p) { struct uhid_softc *sc; int error; if ((sc = uhid_lookup(dev)) == NULL) return (ENXIO); DPRINTF(("uhidopen: sc=%p\n", sc)); if (usbd_is_dying(sc->sc_hdev.sc_udev)) return (ENXIO); if (sc->sc_hdev.sc_state & UHIDEV_OPEN) return (EBUSY); clalloc(&sc->sc_q, UHID_BSIZE, 0); error = uhidev_open(&sc->sc_hdev); if (error) { clfree(&sc->sc_q); return (error); } sc->sc_obuf = malloc(sc->sc_hdev.sc_osize, M_USBDEV, M_WAITOK); return (0); } int uhidclose(dev_t dev, int flag, int mode, struct proc *p) { struct uhid_softc *sc; if ((sc = uhid_lookup(dev)) == NULL) return (ENXIO); DPRINTF(("uhidclose: sc=%p\n", sc)); clfree(&sc->sc_q); free(sc->sc_obuf, M_USBDEV, sc->sc_hdev.sc_osize); uhidev_close(&sc->sc_hdev); return (0); } int uhid_do_read(struct uhid_softc *sc, struct uio *uio, int flag) { int s; int error = 0; size_t length; u_char buffer[UHID_CHUNK]; DPRINTFN(1, ("uhidread\n")); s = splusb(); while (sc->sc_q.c_cc == 0) { if (flag & IO_NDELAY) { splx(s); return (EWOULDBLOCK); } sc->sc_state |= UHID_ASLP; DPRINTFN(5, ("uhidread: sleep on %p\n", &sc->sc_q)); error = tsleep_nsec(&sc->sc_q, PZERO|PCATCH, "uhidrea", INFSLP); DPRINTFN(5, ("uhidread: woke, error=%d\n", error)); if (usbd_is_dying(sc->sc_hdev.sc_udev)) error = EIO; if (error) { sc->sc_state &= ~UHID_ASLP; break; } } splx(s); /* Transfer as many chunks as possible. */ while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0 && !error) { length = ulmin(sc->sc_q.c_cc, uio->uio_resid); if (length > sizeof(buffer)) length = sizeof(buffer); /* Remove a small chunk from the input queue. */ (void) q_to_b(&sc->sc_q, buffer, length); DPRINTFN(5, ("uhidread: got %zu chars\n", length)); /* Copy the data to the user process. */ if ((error = uiomove(buffer, length, uio)) != 0) break; } return (error); } int uhidread(dev_t dev, struct uio *uio, int flag) { struct uhid_softc *sc; int error; if ((sc = uhid_lookup(dev)) == NULL) return (ENXIO); sc->sc_refcnt++; error = uhid_do_read(sc, uio, flag); if (--sc->sc_refcnt < 0) usb_detach_wakeup(&sc->sc_hdev.sc_dev); return (error); } int uhid_do_write(struct uhid_softc *sc, struct uio *uio, int flag) { int error; int size; DPRINTFN(1, ("uhidwrite\n")); if (usbd_is_dying(sc->sc_hdev.sc_udev)) return (EIO); size = sc->sc_hdev.sc_osize; error = 0; if (uio->uio_resid > size) return (EMSGSIZE); else if (uio->uio_resid < size) { /* don't leak kernel memory to the USB device */ memset(sc->sc_obuf + uio->uio_resid, 0, size - uio->uio_resid); } error = uiomove(sc->sc_obuf, uio->uio_resid, uio); if (!error) { if (uhidev_set_report(sc->sc_hdev.sc_parent, UHID_OUTPUT_REPORT, sc->sc_hdev.sc_report_id, sc->sc_obuf, size) != size) error = EIO; } return (error); } int uhidwrite(dev_t dev, struct uio *uio, int flag) { struct uhid_softc *sc; int error; if ((sc = uhid_lookup(dev)) == NULL) return (ENXIO); sc->sc_refcnt++; error = uhid_do_write(sc, uio, flag); if (--sc->sc_refcnt < 0) usb_detach_wakeup(&sc->sc_hdev.sc_dev); return (error); } int uhid_do_ioctl(struct uhid_softc *sc, u_long cmd, caddr_t addr, int flag, struct proc *p) { int rc; DPRINTFN(2, ("uhidioctl: cmd=%lx\n", cmd)); if (usbd_is_dying(sc->sc_hdev.sc_udev)) return (EIO); switch (cmd) { case FIONBIO: case FIOASYNC: /* All handled in the upper FS layer. */ break; case USB_GET_DEVICEINFO: usbd_fill_deviceinfo(sc->sc_hdev.sc_udev, (struct usb_device_info *)addr); break; case USB_GET_REPORT_DESC: case USB_GET_REPORT: case USB_SET_REPORT: case USB_GET_REPORT_ID: default: rc = uhidev_ioctl(&sc->sc_hdev, cmd, addr, flag, p); if (rc == -1) rc = ENOTTY; return rc; } return (0); } int uhidioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { struct uhid_softc *sc; int error; if ((sc = uhid_lookup(dev)) == NULL) return (ENXIO); sc->sc_refcnt++; error = uhid_do_ioctl(sc, cmd, addr, flag, p); if (--sc->sc_refcnt < 0) usb_detach_wakeup(&sc->sc_hdev.sc_dev); return (error); } void filt_uhidrdetach(struct knote *); int filt_uhidread(struct knote *, long); int uhidkqfilter(dev_t, struct knote *); void filt_uhidrdetach(struct knote *kn) { struct uhid_softc *sc = (void *)kn->kn_hook; int s; s = splusb(); klist_remove_locked(&sc->sc_rsel.si_note, kn); splx(s); } int filt_uhidread(struct knote *kn, long hint) { struct uhid_softc *sc = (void *)kn->kn_hook; kn->kn_data = sc->sc_q.c_cc; return (kn->kn_data > 0); } const struct filterops uhidread_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, .f_detach = filt_uhidrdetach, .f_event = filt_uhidread, }; int uhidkqfilter(dev_t dev, struct knote *kn) { struct uhid_softc *sc; struct klist *klist; int s; if ((sc = uhid_lookup(dev)) == NULL) return (ENXIO); if (usbd_is_dying(sc->sc_hdev.sc_udev)) return (ENXIO); switch (kn->kn_filter) { case EVFILT_READ: klist = &sc->sc_rsel.si_note; kn->kn_fop = &uhidread_filtops; break; case EVFILT_WRITE: return (seltrue_kqfilter(dev, kn)); default: return (EINVAL); } kn->kn_hook = (void *)sc; s = splusb(); klist_insert_locked(klist, kn); splx(s); return (0); }
2 2 2 2 12 12 12 12 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 /* $OpenBSD: vm_machdep.c,v 1.47 2023/04/11 00:45:07 jsg Exp $ */ /* $NetBSD: vm_machdep.c,v 1.1 2003/04/26 18:39:33 fvdl Exp $ */ /*- * Copyright (c) 1995 Charles M. Hannum. All rights reserved. * Copyright (c) 1982, 1986 The Regents of the University of California. * Copyright (c) 1989, 1990 William Jolitz * All rights reserved. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department, and William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91 */ /* * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$ */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/buf.h> #include <sys/user.h> #include <uvm/uvm_extern.h> #include <machine/cpu.h> #include <machine/fpu.h> void setguardpage(struct proc *); /* * Finish a fork operation, with process p2 nearly set up. * Copy and update the kernel stack and pcb, making the child * ready to run, and marking it so that it can return differently * than the parent. */ void cpu_fork(struct proc *p1, struct proc *p2, void *stack, void *tcb, void (*func)(void *), void *arg) { struct cpu_info *ci = curcpu(); struct pcb *pcb = &p2->p_addr->u_pcb; struct pcb *pcb1 = &p1->p_addr->u_pcb; struct trapframe *tf; struct switchframe *sf; /* Save the fpu h/w state to p1's pcb so that we can copy it. */ if (p1 != &proc0 && (ci->ci_pflags & CPUPF_USERXSTATE)) fpusave(&pcb1->pcb_savefpu); p2->p_md.md_flags = p1->p_md.md_flags; #ifdef DIAGNOSTIC if (p1 != curproc && p1 != &proc0) panic("cpu_fork: curproc"); #endif *pcb = *pcb1; /* * Activate the address space. */ pmap_activate(p2); /* Record where this process's kernel stack is */ pcb->pcb_kstack = (u_int64_t)p2->p_addr + USPACE - 16 - (arc4random() & PAGE_MASK & ~_STACKALIGNBYTES); /* * Copy the trapframe. */ p2->p_md.md_regs = tf = (struct trapframe *)pcb->pcb_kstack - 1; *tf = *p1->p_md.md_regs; setguardpage(p2); /* * If specified, give the child a different stack and/or TCB */ if (stack != NULL) tf->tf_rsp = (u_int64_t)stack; if (tcb != NULL) pcb->pcb_fsbase = (u_int64_t)tcb; sf = (struct switchframe *)tf - 1; sf->sf_r12 = (u_int64_t)func; sf->sf_r13 = (u_int64_t)arg; sf->sf_rip = (u_int64_t)proc_trampoline; pcb->pcb_rsp = (u_int64_t)sf; pcb->pcb_rbp = 0; } /* * cpu_exit is called as the last action during exit. * * We clean up a little and then call sched_exit() with the old proc as an * argument. */ void cpu_exit(struct proc *p) { pmap_deactivate(p); sched_exit(p); } /* * Set a red zone in the kernel stack after the u. area. */ void setguardpage(struct proc *p) { pmap_remove(pmap_kernel(), (vaddr_t)p->p_addr + PAGE_SIZE, (vaddr_t)p->p_addr + 2 * PAGE_SIZE); pmap_update(pmap_kernel()); } struct kmem_va_mode kv_physwait = { .kv_map = &phys_map, .kv_wait = 1, }; /* * Map a user I/O request into kernel virtual address space. * Note: the pages are already locked by uvm_vslock(), so we * do not need to pass an access_type to pmap_enter(). */ void vmapbuf(struct buf *bp, vsize_t len) { vaddr_t faddr, taddr, off; paddr_t fpa; if ((bp->b_flags & B_PHYS) == 0) panic("vmapbuf"); faddr = trunc_page((vaddr_t)(bp->b_saveaddr = bp->b_data)); off = (vaddr_t)bp->b_data - faddr; len = round_page(off + len); taddr = (vaddr_t)km_alloc(len, &kv_physwait, &kp_none, &kd_waitok); bp->b_data = (caddr_t)(taddr + off); /* * The region is locked, so we expect that pmap_pte() will return * non-NULL. * XXX: unwise to expect this in a multithreaded environment. * anything can happen to a pmap between the time we lock a * region, release the pmap lock, and then relock it for * the pmap_extract(). * * no need to flush TLB since we expect nothing to be mapped * where we just allocated (TLB will be flushed when our * mapping is removed). */ while (len) { (void) pmap_extract(vm_map_pmap(&bp->b_proc->p_vmspace->vm_map), faddr, &fpa); pmap_kenter_pa(taddr, fpa, PROT_READ | PROT_WRITE); faddr += PAGE_SIZE; taddr += PAGE_SIZE; len -= PAGE_SIZE; } pmap_update(pmap_kernel()); } /* * Unmap a previously-mapped user I/O request. */ void vunmapbuf(struct buf *bp, vsize_t len) { vaddr_t addr, off; if ((bp->b_flags & B_PHYS) == 0) panic("vunmapbuf"); addr = trunc_page((vaddr_t)bp->b_data); off = (vaddr_t)bp->b_data - addr; len = round_page(off + len); pmap_kremove(addr, len); pmap_update(pmap_kernel()); km_free((void *)addr, len, &kv_physwait, &kp_none); bp->b_data = bp->b_saveaddr; bp->b_saveaddr = NULL; } void * tcb_get(struct proc *p) { return ((void *)p->p_addr->u_pcb.pcb_fsbase); } void tcb_set(struct proc *p, void *tcb) { KASSERT(p == curproc); reset_segs(); p->p_addr->u_pcb.pcb_fsbase = (u_int64_t)tcb; }
9 4 4 4 4 5 5 4 4 4 4 4 6 2 2 2 7 4 5 4 4 4 5 5 4 5 6 6 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 /* $OpenBSD: pms.c,v 1.98 2023/08/16 20:53:47 bru Exp $ */ /* $NetBSD: psm.c,v 1.11 2000/06/05 22:20:57 sommerfeld Exp $ */ /*- * Copyright (c) 1994 Charles M. Hannum. * Copyright (c) 1992, 1993 Erik Forsberg. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/rwlock.h> #include <sys/device.h> #include <sys/ioctl.h> #include <sys/malloc.h> #include <sys/task.h> #include <sys/timeout.h> #include <machine/bus.h> #include <dev/ic/pckbcvar.h> #include <dev/pckbc/pmsreg.h> #include <dev/wscons/wsconsio.h> #include <dev/wscons/wsmousevar.h> #if defined(__i386__) || defined(__amd64__) #include "acpi.h" #endif #if !defined(SMALL_KERNEL) && NACPI > 0 extern int mouse_has_softbtn; #else int mouse_has_softbtn; #endif #ifdef DEBUG #define DPRINTF(x...) do { printf(x); } while (0); #else #define DPRINTF(x...) #endif #define DEVNAME(sc) ((sc)->sc_dev.dv_xname) #define WSMOUSE_BUTTON(x) (1 << ((x) - 1)) struct pms_softc; struct pms_protocol { int type; #define PMS_STANDARD 0 #define PMS_INTELLI 1 #define PMS_SYNAPTICS 2 #define PMS_ALPS 3 #define PMS_ELANTECH_V1 4 #define PMS_ELANTECH_V2 5 #define PMS_ELANTECH_V3 6 #define PMS_ELANTECH_V4 7 u_int packetsize; int (*enable)(struct pms_softc *); int (*ioctl)(struct pms_softc *, u_long, caddr_t, int, struct proc *); int (*sync)(struct pms_softc *, int); void (*proc)(struct pms_softc *); void (*disable)(struct pms_softc *); }; struct synaptics_softc { int identify; int capabilities, ext_capabilities, ext2_capabilities; int model, ext_model; int modes; int mode; int mask; #define SYNAPTICS_MASK_NEWABS_STRICT 0xc8 #define SYNAPTICS_MASK_NEWABS_RELAXED 0xc0 #define SYNAPTICS_VALID_NEWABS_FIRST 0x80 #define SYNAPTICS_VALID_NEWABS_NEXT 0xc0 u_int sec_buttons; #define SYNAPTICS_PRESSURE_HI 30 #define SYNAPTICS_PRESSURE_LO 25 #define SYNAPTICS_PRESSURE SYNAPTICS_PRESSURE_HI #define SYNAPTICS_SCALE 4 #define SYNAPTICS_MAX_FINGERS 3 }; struct alps_softc { int model; #define ALPS_GLIDEPOINT (1 << 1) #define ALPS_DUALPOINT (1 << 2) #define ALPS_PASSTHROUGH (1 << 3) #define ALPS_INTERLEAVED (1 << 4) int mask; int version; u_int gesture; u_int sec_buttons; /* trackpoint */ int old_x, old_y; #define ALPS_PRESSURE 40 }; struct elantech_softc { int flags; #define ELANTECH_F_REPORTS_PRESSURE 0x01 #define ELANTECH_F_HAS_ROCKER 0x02 #define ELANTECH_F_2FINGER_PACKET 0x04 #define ELANTECH_F_HW_V1_OLD 0x08 #define ELANTECH_F_CRC_ENABLED 0x10 #define ELANTECH_F_TRACKPOINT 0x20 int fw_version; u_int mt_slots; int width; u_char parity[256]; u_char p1, p2, p3; int max_x, max_y; int old_x, old_y; int initial_pkt; }; #define ELANTECH_IS_CLICKPAD(sc) (((sc)->elantech->fw_version & 0x1000) != 0) struct pms_softc { /* driver status information */ struct device sc_dev; pckbc_tag_t sc_kbctag; int sc_state; #define PMS_STATE_DISABLED 0 #define PMS_STATE_ENABLED 1 #define PMS_STATE_SUSPENDED 2 struct rwlock sc_state_lock; int sc_dev_enable; #define PMS_DEV_IGNORE 0x00 #define PMS_DEV_PRIMARY 0x01 #define PMS_DEV_SECONDARY 0x02 struct task sc_rsttask; struct timeout sc_rsttimo; int sc_rststate; #define PMS_RST_COMMENCE 0x01 #define PMS_RST_ANNOUNCED 0x02 int poll; int inputstate; const struct pms_protocol *protocol; struct synaptics_softc *synaptics; struct alps_softc *alps; struct elantech_softc *elantech; u_char packet[8]; struct device *sc_wsmousedev; struct device *sc_sec_wsmousedev; }; static const u_int butmap[8] = { 0, WSMOUSE_BUTTON(1), WSMOUSE_BUTTON(3), WSMOUSE_BUTTON(1) | WSMOUSE_BUTTON(3), WSMOUSE_BUTTON(2), WSMOUSE_BUTTON(1) | WSMOUSE_BUTTON(2), WSMOUSE_BUTTON(2) | WSMOUSE_BUTTON(3), WSMOUSE_BUTTON(1) | WSMOUSE_BUTTON(2) | WSMOUSE_BUTTON(3) }; static const struct alps_model { int version; int mask; int model; } alps_models[] = { { 0x2021, 0xf8, ALPS_DUALPOINT | ALPS_PASSTHROUGH }, { 0x2221, 0xf8, ALPS_DUALPOINT | ALPS_PASSTHROUGH }, { 0x2222, 0xff, ALPS_DUALPOINT | ALPS_PASSTHROUGH }, { 0x3222, 0xf8, ALPS_DUALPOINT | ALPS_PASSTHROUGH }, { 0x5212, 0xff, ALPS_DUALPOINT | ALPS_PASSTHROUGH | ALPS_INTERLEAVED }, { 0x5321, 0xf8, ALPS_GLIDEPOINT }, { 0x5322, 0xf8, ALPS_GLIDEPOINT }, { 0x603b, 0xf8, ALPS_GLIDEPOINT }, { 0x6222, 0xcf, ALPS_DUALPOINT | ALPS_PASSTHROUGH | ALPS_INTERLEAVED }, { 0x6321, 0xf8, ALPS_GLIDEPOINT }, { 0x6322, 0xf8, ALPS_GLIDEPOINT }, { 0x6323, 0xf8, ALPS_GLIDEPOINT }, { 0x6324, 0x8f, ALPS_GLIDEPOINT }, { 0x6325, 0xef, ALPS_GLIDEPOINT }, { 0x6326, 0xf8, ALPS_GLIDEPOINT }, { 0x7301, 0xf8, ALPS_DUALPOINT }, { 0x7321, 0xf8, ALPS_GLIDEPOINT }, { 0x7322, 0xf8, ALPS_GLIDEPOINT }, { 0x7325, 0xcf, ALPS_GLIDEPOINT }, #if 0 /* * This model has a clitpad sending almost compatible PS2 * packets but not compatible enough to be used with the * ALPS protocol. */ { 0x633b, 0xf8, ALPS_DUALPOINT | ALPS_PASSTHROUGH }, { 0x7326, 0, 0 }, /* XXX Uses unknown v3 protocol */ { 0x7331, 0x8f, ALPS_DUALPOINT }, /* not supported */ #endif }; static struct wsmouse_param synaptics_params[] = { { WSMOUSECFG_PRESSURE_LO, SYNAPTICS_PRESSURE_LO }, { WSMOUSECFG_PRESSURE_HI, SYNAPTICS_PRESSURE_HI } }; static struct wsmouse_param alps_params[] = { { WSMOUSECFG_SMOOTHING, 3 } }; int pmsprobe(struct device *, void *, void *); void pmsattach(struct device *, struct device *, void *); int pmsactivate(struct device *, int); void pmsinput(void *, int); int pms_change_state(struct pms_softc *, int, int); int pms_ioctl(void *, u_long, caddr_t, int, struct proc *); int pms_enable(void *); void pms_disable(void *); int pms_sec_ioctl(void *, u_long, caddr_t, int, struct proc *); int pms_sec_enable(void *); void pms_sec_disable(void *); int pms_cmd(struct pms_softc *, u_char *, int, u_char *, int); int pms_spec_cmd(struct pms_softc *, int); int pms_get_devid(struct pms_softc *, u_char *); int pms_get_status(struct pms_softc *, u_char *); int pms_set_rate(struct pms_softc *, int); int pms_set_resolution(struct pms_softc *, int); int pms_set_scaling(struct pms_softc *, int); int pms_reset(struct pms_softc *); int pms_dev_enable(struct pms_softc *); int pms_dev_disable(struct pms_softc *); void pms_protocol_lookup(struct pms_softc *); void pms_reset_detect(struct pms_softc *, int); void pms_reset_task(void *); void pms_reset_timo(void *); int pms_enable_intelli(struct pms_softc *); int pms_ioctl_mouse(struct pms_softc *, u_long, caddr_t, int, struct proc *); int pms_sync_mouse(struct pms_softc *, int); void pms_proc_mouse(struct pms_softc *); int pms_enable_synaptics(struct pms_softc *); int pms_ioctl_synaptics(struct pms_softc *, u_long, caddr_t, int, struct proc *); int pms_sync_synaptics(struct pms_softc *, int); void pms_proc_synaptics(struct pms_softc *); void pms_disable_synaptics(struct pms_softc *); int pms_enable_alps(struct pms_softc *); int pms_ioctl_alps(struct pms_softc *, u_long, caddr_t, int, struct proc *); int pms_sync_alps(struct pms_softc *, int); void pms_proc_alps(struct pms_softc *); int pms_enable_elantech_v1(struct pms_softc *); int pms_enable_elantech_v2(struct pms_softc *); int pms_enable_elantech_v3(struct pms_softc *); int pms_enable_elantech_v4(struct pms_softc *); int pms_ioctl_elantech(struct pms_softc *, u_long, caddr_t, int, struct proc *); int pms_sync_elantech_v1(struct pms_softc *, int); int pms_sync_elantech_v2(struct pms_softc *, int); int pms_sync_elantech_v3(struct pms_softc *, int); int pms_sync_elantech_v4(struct pms_softc *, int); void pms_proc_elantech_v1(struct pms_softc *); void pms_proc_elantech_v2(struct pms_softc *); void pms_proc_elantech_v3(struct pms_softc *); void pms_proc_elantech_v4(struct pms_softc *); int synaptics_knock(struct pms_softc *); int synaptics_set_mode(struct pms_softc *, int, int); int synaptics_query(struct pms_softc *, int, int *); int synaptics_get_hwinfo(struct pms_softc *); void synaptics_sec_proc(struct pms_softc *); int alps_sec_proc(struct pms_softc *); int alps_get_hwinfo(struct pms_softc *); int elantech_knock(struct pms_softc *); int elantech_get_hwinfo_v1(struct pms_softc *); int elantech_get_hwinfo_v2(struct pms_softc *); int elantech_get_hwinfo_v3(struct pms_softc *); int elantech_get_hwinfo_v4(struct pms_softc *); int elantech_ps2_cmd(struct pms_softc *, u_char); int elantech_set_absolute_mode_v1(struct pms_softc *); int elantech_set_absolute_mode_v2(struct pms_softc *); int elantech_set_absolute_mode_v3(struct pms_softc *); int elantech_set_absolute_mode_v4(struct pms_softc *); const struct cfattach pms_ca = { sizeof(struct pms_softc), pmsprobe, pmsattach, NULL, pmsactivate }; struct cfdriver pms_cd = { NULL, "pms", DV_DULL }; const struct wsmouse_accessops pms_accessops = { pms_enable, pms_ioctl, pms_disable, }; const struct wsmouse_accessops pms_sec_accessops = { pms_sec_enable, pms_sec_ioctl, pms_sec_disable, }; const struct pms_protocol pms_protocols[] = { /* Generic PS/2 mouse */ { PMS_STANDARD, 3, NULL, pms_ioctl_mouse, pms_sync_mouse, pms_proc_mouse, NULL }, /* Synaptics touchpad */ { PMS_SYNAPTICS, 6, pms_enable_synaptics, pms_ioctl_synaptics, pms_sync_synaptics, pms_proc_synaptics, pms_disable_synaptics }, /* ALPS touchpad */ { PMS_ALPS, 6, pms_enable_alps, pms_ioctl_alps, pms_sync_alps, pms_proc_alps, NULL }, /* Elantech touchpad (hardware version 1) */ { PMS_ELANTECH_V1, 4, pms_enable_elantech_v1, pms_ioctl_elantech, pms_sync_elantech_v1, pms_proc_elantech_v1, NULL }, /* Elantech touchpad (hardware version 2) */ { PMS_ELANTECH_V2, 6, pms_enable_elantech_v2, pms_ioctl_elantech, pms_sync_elantech_v2, pms_proc_elantech_v2, NULL }, /* Elantech touchpad (hardware version 3) */ { PMS_ELANTECH_V3, 6, pms_enable_elantech_v3, pms_ioctl_elantech, pms_sync_elantech_v3, pms_proc_elantech_v3, NULL }, /* Elantech touchpad (hardware version 4) */ { PMS_ELANTECH_V4, 6, pms_enable_elantech_v4, pms_ioctl_elantech, pms_sync_elantech_v4, pms_proc_elantech_v4, NULL }, /* Microsoft IntelliMouse */ { PMS_INTELLI, 4, pms_enable_intelli, pms_ioctl_mouse, pms_sync_mouse, pms_proc_mouse, NULL }, }; int pms_cmd(struct pms_softc *sc, u_char *cmd, int len, u_char *resp, int resplen) { if (sc->poll) { return pckbc_poll_cmd(sc->sc_kbctag, PCKBC_AUX_SLOT, cmd, len, resplen, resp, 1); } else { return pckbc_enqueue_cmd(sc->sc_kbctag, PCKBC_AUX_SLOT, cmd, len, resplen, 1, resp); } } int pms_spec_cmd(struct pms_softc *sc, int cmd) { if (pms_set_scaling(sc, 1) || pms_set_resolution(sc, (cmd >> 6) & 0x03) || pms_set_resolution(sc, (cmd >> 4) & 0x03) || pms_set_resolution(sc, (cmd >> 2) & 0x03) || pms_set_resolution(sc, (cmd >> 0) & 0x03)) return (-1); return (0); } int pms_get_devid(struct pms_softc *sc, u_char *resp) { u_char cmd[1]; cmd[0] = PMS_SEND_DEV_ID; return (pms_cmd(sc, cmd, 1, resp, 1)); } int pms_get_status(struct pms_softc *sc, u_char *resp) { u_char cmd[1]; cmd[0] = PMS_SEND_DEV_STATUS; return (pms_cmd(sc, cmd, 1, resp, 3)); } int pms_set_rate(struct pms_softc *sc, int value) { u_char cmd[2]; cmd[0] = PMS_SET_SAMPLE; cmd[1] = value; return (pms_cmd(sc, cmd, 2, NULL, 0)); } int pms_set_resolution(struct pms_softc *sc, int value) { u_char cmd[2]; cmd[0] = PMS_SET_RES; cmd[1] = value; return (pms_cmd(sc, cmd, 2, NULL, 0)); } int pms_set_scaling(struct pms_softc *sc, int scale) { u_char cmd[1]; switch (scale) { case 1: default: cmd[0] = PMS_SET_SCALE11; break; case 2: cmd[0] = PMS_SET_SCALE21; break; } return (pms_cmd(sc, cmd, 1, NULL, 0)); } int pms_reset(struct pms_softc *sc) { u_char cmd[1], resp[2]; int res; cmd[0] = PMS_RESET; res = pms_cmd(sc, cmd, 1, resp, 2); #ifdef DEBUG if (res || resp[0] != PMS_RSTDONE || resp[1] != 0) printf("%s: reset error %d (response 0x%02x, type 0x%02x)\n", DEVNAME(sc), res, resp[0], resp[1]); #endif return (res); } int pms_dev_enable(struct pms_softc *sc) { u_char cmd[1]; int res; cmd[0] = PMS_DEV_ENABLE; res = pms_cmd(sc, cmd, 1, NULL, 0); if (res) printf("%s: enable error\n", DEVNAME(sc)); return (res); } int pms_dev_disable(struct pms_softc *sc) { u_char cmd[1]; int res; cmd[0] = PMS_DEV_DISABLE; res = pms_cmd(sc, cmd, 1, NULL, 0); if (res) printf("%s: disable error\n", DEVNAME(sc)); return (res); } void pms_protocol_lookup(struct pms_softc *sc) { int i; sc->protocol = &pms_protocols[0]; for (i = 1; i < nitems(pms_protocols); i++) { pms_reset(sc); if (pms_protocols[i].enable(sc)) { sc->protocol = &pms_protocols[i]; break; } } DPRINTF("%s: protocol type %d\n", DEVNAME(sc), sc->protocol->type); } /* * Detect reset announcement ([0xaa, 0x0]). * The sequence will be sent as input on rare occasions when the touchpad was * reset due to a power failure. */ void pms_reset_detect(struct pms_softc *sc, int data) { switch (sc->sc_rststate) { case PMS_RST_COMMENCE: if (data == 0x0) { sc->sc_rststate = PMS_RST_ANNOUNCED; timeout_add_msec(&sc->sc_rsttimo, 100); } else if (data != PMS_RSTDONE) { sc->sc_rststate = 0; } break; default: if (data == PMS_RSTDONE) sc->sc_rststate = PMS_RST_COMMENCE; else sc->sc_rststate = 0; } } void pms_reset_timo(void *v) { struct pms_softc *sc = v; int s = spltty(); /* * Do nothing if the reset was a false positive or if the device already * is disabled. */ if (sc->sc_rststate == PMS_RST_ANNOUNCED && sc->sc_state != PMS_STATE_DISABLED) task_add(systq, &sc->sc_rsttask); splx(s); } void pms_reset_task(void *v) { struct pms_softc *sc = v; int s = spltty(); #ifdef DIAGNOSTIC printf("%s: device reset (state = %d)\n", DEVNAME(sc), sc->sc_rststate); #endif rw_enter_write(&sc->sc_state_lock); if (sc->sc_sec_wsmousedev != NULL) pms_change_state(sc, PMS_STATE_DISABLED, PMS_DEV_SECONDARY); pms_change_state(sc, PMS_STATE_DISABLED, PMS_DEV_PRIMARY); pms_change_state(sc, PMS_STATE_ENABLED, PMS_DEV_PRIMARY); if (sc->sc_sec_wsmousedev != NULL) pms_change_state(sc, PMS_STATE_ENABLED, PMS_DEV_SECONDARY); rw_exit_write(&sc->sc_state_lock); splx(s); } int pms_enable_intelli(struct pms_softc *sc) { u_char resp; /* the special sequence to enable the third button and the roller */ if (pms_set_rate(sc, PMS_INTELLI_MAGIC1) || pms_set_rate(sc, PMS_INTELLI_MAGIC2) || pms_set_rate(sc, PMS_INTELLI_MAGIC3) || pms_get_devid(sc, &resp) || resp != PMS_INTELLI_ID) return (0); return (1); } int pms_ioctl_mouse(struct pms_softc *sc, u_long cmd, caddr_t data, int flag, struct proc *p) { int i; switch (cmd) { case WSMOUSEIO_GTYPE: *(u_int *)data = WSMOUSE_TYPE_PS2; break; case WSMOUSEIO_SRES: i = ((int) *(u_int *)data - 12) / 25; /* valid values are {0,1,2,3} */ if (i < 0) i = 0; if (i > 3) i = 3; if (pms_set_resolution(sc, i)) printf("%s: SET_RES command error\n", DEVNAME(sc)); break; default: return (-1); } return (0); } int pms_sync_mouse(struct pms_softc *sc, int data) { if (sc->inputstate != 0) return (0); switch (sc->protocol->type) { case PMS_STANDARD: if ((data & 0xc0) != 0) return (-1); break; case PMS_INTELLI: if ((data & 0x08) != 0x08) return (-1); break; } return (0); } void pms_proc_mouse(struct pms_softc *sc) { u_int buttons; int dx, dy, dz; buttons = butmap[sc->packet[0] & PMS_PS2_BUTTONSMASK]; dx = (sc->packet[0] & PMS_PS2_XNEG) ? (int)sc->packet[1] - 256 : sc->packet[1]; dy = (sc->packet[0] & PMS_PS2_YNEG) ? (int)sc->packet[2] - 256 : sc->packet[2]; if (sc->protocol->type == PMS_INTELLI) dz = (signed char)sc->packet[3]; else dz = 0; WSMOUSE_INPUT(sc->sc_wsmousedev, buttons, dx, dy, dz, 0); } int pmsprobe(struct device *parent, void *match, void *aux) { struct pckbc_attach_args *pa = aux; u_char cmd[1], resp[2]; int res; if (pa->pa_slot != PCKBC_AUX_SLOT) return (0); /* Flush any garbage. */ pckbc_flush(pa->pa_tag, pa->pa_slot); /* reset the device */ cmd[0] = PMS_RESET; res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 1); if (res || resp[0] != PMS_RSTDONE || resp[1] != 0) { #ifdef DEBUG printf("pms: reset error %d (response 0x%02x, type 0x%02x)\n", res, resp[0], resp[1]); #endif return (0); } return (1); } void pmsattach(struct device *parent, struct device *self, void *aux) { struct pms_softc *sc = (void *)self; struct pckbc_attach_args *pa = aux; struct wsmousedev_attach_args a; sc->sc_kbctag = pa->pa_tag; pckbc_set_inputhandler(sc->sc_kbctag, PCKBC_AUX_SLOT, pmsinput, sc, DEVNAME(sc)); printf("\n"); a.accessops = &pms_accessops; a.accesscookie = sc; rw_init(&sc->sc_state_lock, "pmsst"); /* * Attach the wsmouse, saving a handle to it. * Note that we don't need to check this pointer against NULL * here or in pmsintr, because if this fails pms_enable() will * never be called, so pmsinput() will never be called. */ sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint); task_set(&sc->sc_rsttask, pms_reset_task, sc); timeout_set(&sc->sc_rsttimo, pms_reset_timo, sc); sc->poll = 1; sc->sc_dev_enable = 0; /* See if the device understands an extended (touchpad) protocol. */ pms_protocol_lookup(sc); /* no interrupts until enabled */ pms_change_state(sc, PMS_STATE_DISABLED, PMS_DEV_IGNORE); } int pmsactivate(struct device *self, int act) { struct pms_softc *sc = (struct pms_softc *)self; switch (act) { case DVACT_SUSPEND: if (sc->sc_state == PMS_STATE_ENABLED) pms_change_state(sc, PMS_STATE_SUSPENDED, PMS_DEV_IGNORE); break; case DVACT_RESUME: if (sc->sc_state == PMS_STATE_SUSPENDED) pms_change_state(sc, PMS_STATE_ENABLED, PMS_DEV_IGNORE); break; } return (0); } int pms_change_state(struct pms_softc *sc, int newstate, int dev) { if (dev != PMS_DEV_IGNORE) { switch (newstate) { case PMS_STATE_ENABLED: if (sc->sc_dev_enable & dev) return (EBUSY); sc->sc_dev_enable |= dev; if (sc->sc_state == PMS_STATE_ENABLED) return (0); break; case PMS_STATE_DISABLED: sc->sc_dev_enable &= ~dev; if (sc->sc_dev_enable) return (0); break; } } switch (newstate) { case PMS_STATE_ENABLED: sc->inputstate = 0; sc->sc_rststate = 0; pckbc_slot_enable(sc->sc_kbctag, PCKBC_AUX_SLOT, 1); if (sc->poll) pckbc_flush(sc->sc_kbctag, PCKBC_AUX_SLOT); pms_reset(sc); if (sc->protocol->enable != NULL && sc->protocol->enable(sc) == 0) pms_protocol_lookup(sc); pms_dev_enable(sc); break; case PMS_STATE_DISABLED: case PMS_STATE_SUSPENDED: pms_dev_disable(sc); if (sc->protocol->disable) sc->protocol->disable(sc); pckbc_slot_enable(sc->sc_kbctag, PCKBC_AUX_SLOT, 0); break; } sc->sc_state = newstate; sc->poll = (newstate == PMS_STATE_SUSPENDED) ? 1 : 0; return (0); } int pms_enable(void *v) { struct pms_softc *sc = v; int rv; rw_enter_write(&sc->sc_state_lock); rv = pms_change_state(sc, PMS_STATE_ENABLED, PMS_DEV_PRIMARY); rw_exit_write(&sc->sc_state_lock); return (rv); } void pms_disable(void *v) { struct pms_softc *sc = v; rw_enter_write(&sc->sc_state_lock); pms_change_state(sc, PMS_STATE_DISABLED, PMS_DEV_PRIMARY); rw_exit_write(&sc->sc_state_lock); } int pms_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) { struct pms_softc *sc = v; if (sc->protocol->ioctl) return (sc->protocol->ioctl(sc, cmd, data, flag, p)); else return (-1); } int pms_sec_enable(void *v) { struct pms_softc *sc = v; int rv; rw_enter_write(&sc->sc_state_lock); rv = pms_change_state(sc, PMS_STATE_ENABLED, PMS_DEV_SECONDARY); rw_exit_write(&sc->sc_state_lock); return (rv); } void pms_sec_disable(void *v) { struct pms_softc *sc = v; rw_enter_write(&sc->sc_state_lock); pms_change_state(sc, PMS_STATE_DISABLED, PMS_DEV_SECONDARY); rw_exit_write(&sc->sc_state_lock); } int pms_sec_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) { switch (cmd) { case WSMOUSEIO_GTYPE: *(u_int *)data = WSMOUSE_TYPE_PS2; break; default: return (-1); } return (0); } #ifdef DIAGNOSTIC static inline void pms_print_packet(struct pms_softc *sc) { int i, state, size; state = sc->inputstate; size = sc->protocol->packetsize; for (i = 0; i < size; i++) printf(i == state ? " %02x |" : " %02x", sc->packet[i]); } #endif void pmsinput(void *vsc, int data) { struct pms_softc *sc = vsc; if (sc->sc_state != PMS_STATE_ENABLED) { /* Interrupts are not expected. Discard the byte. */ return; } sc->packet[sc->inputstate] = data; pms_reset_detect(sc, data); if (sc->protocol->sync(sc, data)) { #ifdef DIAGNOSTIC printf("%s: not in sync yet, discard input " "(state = %d,", DEVNAME(sc), sc->inputstate); pms_print_packet(sc); printf(")\n"); #endif sc->inputstate = 0; return; } sc->inputstate++; if (sc->inputstate != sc->protocol->packetsize) return; sc->inputstate = 0; sc->protocol->proc(sc); } int synaptics_set_mode(struct pms_softc *sc, int mode, int rate) { struct synaptics_softc *syn = sc->synaptics; if (pms_spec_cmd(sc, mode) || pms_set_rate(sc, rate == 0 ? SYNAPTICS_CMD_SET_MODE : rate)) return (-1); /* * Make sure that the set mode command has finished. * Otherwise enabling the device before that will make it fail. */ delay(10000); if (rate == 0) syn->mode = mode; return (0); } int synaptics_query(struct pms_softc *sc, int query, int *val) { u_char resp[3]; if (pms_spec_cmd(sc, query) || pms_get_status(sc, resp)) return (-1); if (val) *val = (resp[0] << 16) | (resp[1] << 8) | resp[2]; return (0); } int synaptics_get_hwinfo(struct pms_softc *sc) { struct synaptics_softc *syn = sc->synaptics; struct wsmousehw *hw; int resolution = 0, max_coords = 0, min_coords = 0; hw = wsmouse_get_hw(sc->sc_wsmousedev); if (synaptics_query(sc, SYNAPTICS_QUE_IDENTIFY, &syn->identify)) return (-1); if (synaptics_query(sc, SYNAPTICS_QUE_CAPABILITIES, &syn->capabilities)) return (-1); if (synaptics_query(sc, SYNAPTICS_QUE_MODEL, &syn->model)) return (-1); if ((SYNAPTICS_CAP_EXTENDED_QUERIES(syn->capabilities) >= 1) && synaptics_query(sc, SYNAPTICS_QUE_EXT_MODEL, &syn->ext_model)) return (-1); if ((SYNAPTICS_CAP_EXTENDED_QUERIES(syn->capabilities) >= 4) && synaptics_query(sc, SYNAPTICS_QUE_EXT_CAPABILITIES, &syn->ext_capabilities)) return (-1); if ((SYNAPTICS_ID_MAJOR(syn->identify) >= 4) && synaptics_query(sc, SYNAPTICS_QUE_RESOLUTION, &resolution)) return (-1); if ((SYNAPTICS_CAP_EXTENDED_QUERIES(syn->capabilities) >= 5) && (syn->ext_capabilities & SYNAPTICS_EXT_CAP_MAX_COORDS) && synaptics_query(sc, SYNAPTICS_QUE_EXT_MAX_COORDS, &max_coords)) return (-1); if ((SYNAPTICS_CAP_EXTENDED_QUERIES(syn->capabilities) >= 7 || SYNAPTICS_ID_FULL(syn->identify) == 0x801) && (syn->ext_capabilities & SYNAPTICS_EXT_CAP_MIN_COORDS) && synaptics_query(sc, SYNAPTICS_QUE_EXT_MIN_COORDS, &min_coords)) return (-1); if (SYNAPTICS_ID_FULL(syn->identify) >= 0x705) { if (synaptics_query(sc, SYNAPTICS_QUE_MODES, &syn->modes)) return (-1); if ((syn->modes & SYNAPTICS_EXT2_CAP) && synaptics_query(sc, SYNAPTICS_QUE_EXT2_CAPABILITIES, &syn->ext2_capabilities)) return (-1); } if ((syn->ext_capabilities & SYNAPTICS_EXT_CAP_CLICKPAD) && !(syn->ext2_capabilities & SYNAPTICS_EXT2_CAP_BUTTONS_STICK) && mouse_has_softbtn) hw->type = WSMOUSE_TYPE_SYNAP_SBTN; else hw->type = WSMOUSE_TYPE_SYNAPTICS; hw->hw_type = (syn->ext_capabilities & SYNAPTICS_EXT_CAP_CLICKPAD) ? WSMOUSEHW_CLICKPAD : WSMOUSEHW_TOUCHPAD; if (resolution & SYNAPTICS_RESOLUTION_VALID) { hw->h_res = SYNAPTICS_RESOLUTION_X(resolution); hw->v_res = SYNAPTICS_RESOLUTION_Y(resolution); } hw->x_min = (min_coords ? SYNAPTICS_X_LIMIT(min_coords) : SYNAPTICS_XMIN_BEZEL); hw->y_min = (min_coords ? SYNAPTICS_Y_LIMIT(min_coords) : SYNAPTICS_YMIN_BEZEL); hw->x_max = (max_coords ? SYNAPTICS_X_LIMIT(max_coords) : SYNAPTICS_XMAX_BEZEL); hw->y_max = (max_coords ? SYNAPTICS_Y_LIMIT(max_coords) : SYNAPTICS_YMAX_BEZEL); if ((syn->capabilities & SYNAPTICS_CAP_MULTIFINGER) || SYNAPTICS_SUPPORTS_AGM(syn->ext_capabilities)) hw->contacts_max = SYNAPTICS_MAX_FINGERS; else hw->contacts_max = 1; syn->sec_buttons = 0; if (SYNAPTICS_EXT_MODEL_BUTTONS(syn->ext_model) > 8) syn->ext_model &= ~0xf000; if ((syn->model & SYNAPTICS_MODEL_NEWABS) == 0) { printf("%s: don't support Synaptics OLDABS\n", DEVNAME(sc)); return (-1); } if ((SYNAPTICS_ID_MAJOR(syn->identify) == 5) && (SYNAPTICS_ID_MINOR(syn->identify) == 9)) syn->mask = SYNAPTICS_MASK_NEWABS_RELAXED; else syn->mask = SYNAPTICS_MASK_NEWABS_STRICT; return (0); } void synaptics_sec_proc(struct pms_softc *sc) { struct synaptics_softc *syn = sc->synaptics; u_int buttons; int dx, dy; if ((sc->sc_dev_enable & PMS_DEV_SECONDARY) == 0) return; buttons = butmap[sc->packet[1] & PMS_PS2_BUTTONSMASK]; buttons |= syn->sec_buttons; dx = (sc->packet[1] & PMS_PS2_XNEG) ? (int)sc->packet[4] - 256 : sc->packet[4]; dy = (sc->packet[1] & PMS_PS2_YNEG) ? (int)sc->packet[5] - 256 : sc->packet[5]; WSMOUSE_INPUT(sc->sc_sec_wsmousedev, buttons, dx, dy, 0, 0); } int synaptics_knock(struct pms_softc *sc) { u_char resp[3]; if (pms_set_resolution(sc, 0) || pms_set_resolution(sc, 0) || pms_set_resolution(sc, 0) || pms_set_resolution(sc, 0) || pms_get_status(sc, resp) || resp[1] != SYNAPTICS_ID_MAGIC) return (-1); return (0); } int pms_enable_synaptics(struct pms_softc *sc) { struct synaptics_softc *syn = sc->synaptics; struct wsmousedev_attach_args a; int mode, i; if (synaptics_knock(sc)) { if (sc->synaptics == NULL) goto err; /* * Some synaptics touchpads don't resume quickly. * Retry a few times. */ for (i = 10; i > 0; --i) { printf("%s: device not resuming, retrying\n", DEVNAME(sc)); pms_reset(sc); if (synaptics_knock(sc) == 0) break; delay(100000); } if (i == 0) { printf("%s: lost device\n", DEVNAME(sc)); goto err; } } if (sc->synaptics == NULL) { sc->synaptics = syn = malloc(sizeof(struct synaptics_softc), M_DEVBUF, M_WAITOK | M_ZERO); if (syn == NULL) { printf("%s: synaptics: not enough memory\n", DEVNAME(sc)); goto err; } if (synaptics_get_hwinfo(sc)) { free(sc->synaptics, M_DEVBUF, sizeof(struct synaptics_softc)); sc->synaptics = NULL; goto err; } /* enable pass-through PS/2 port if supported */ if (syn->capabilities & SYNAPTICS_CAP_PASSTHROUGH) { a.accessops = &pms_sec_accessops; a.accesscookie = sc; sc->sc_sec_wsmousedev = config_found((void *)sc, &a, wsmousedevprint); } if (wsmouse_configure(sc->sc_wsmousedev, synaptics_params, nitems(synaptics_params))) goto err; printf("%s: Synaptics %s, firmware %d.%d, " "0x%x 0x%x 0x%x 0x%x 0x%x\n", DEVNAME(sc), (syn->ext_capabilities & SYNAPTICS_EXT_CAP_CLICKPAD ? "clickpad" : "touchpad"), SYNAPTICS_ID_MAJOR(syn->identify), SYNAPTICS_ID_MINOR(syn->identify), syn->model, syn->ext_model, syn->modes, syn->capabilities, syn->ext_capabilities); } /* * Enable absolute mode, plain W-mode and "advanced gesture mode" * (AGM), if possible. AGM, which seems to be a prerequisite for the * extended W-mode, might not always be necessary here, but at least * some older Synaptics models do not report finger counts without it. */ mode = SYNAPTICS_ABSOLUTE_MODE | SYNAPTICS_HIGH_RATE; if (syn->capabilities & SYNAPTICS_CAP_EXTENDED) mode |= SYNAPTICS_W_MODE; else if (SYNAPTICS_ID_MAJOR(syn->identify) >= 4) mode |= SYNAPTICS_DISABLE_GESTURE; if (synaptics_set_mode(sc, mode, 0)) goto err; if (SYNAPTICS_SUPPORTS_AGM(syn->ext_capabilities) && synaptics_set_mode(sc, SYNAPTICS_QUE_MODEL, SYNAPTICS_CMD_SET_ADV_GESTURE_MODE)) goto err; return (1); err: pms_reset(sc); return (0); } int pms_ioctl_synaptics(struct pms_softc *sc, u_long cmd, caddr_t data, int flag, struct proc *p) { struct wsmouse_calibcoords *wsmc = (struct wsmouse_calibcoords *)data; struct wsmousehw *hw; int wsmode; hw = wsmouse_get_hw(sc->sc_wsmousedev); switch (cmd) { case WSMOUSEIO_GTYPE: *(u_int *)data = hw->type; break; case WSMOUSEIO_GCALIBCOORDS: wsmc->minx = hw->x_min; wsmc->maxx = hw->x_max; wsmc->miny = hw->y_min; wsmc->maxy = hw->y_max; wsmc->swapxy = 0; wsmc->resx = hw->h_res; wsmc->resy = hw->v_res; break; case WSMOUSEIO_SETMODE: wsmode = *(u_int *)data; if (wsmode != WSMOUSE_COMPAT && wsmode != WSMOUSE_NATIVE) return (EINVAL); wsmouse_set_mode(sc->sc_wsmousedev, wsmode); break; default: return (-1); } return (0); } int pms_sync_synaptics(struct pms_softc *sc, int data) { struct synaptics_softc *syn = sc->synaptics; switch (sc->inputstate) { case 0: if ((data & syn->mask) != SYNAPTICS_VALID_NEWABS_FIRST) return (-1); break; case 3: if ((data & syn->mask) != SYNAPTICS_VALID_NEWABS_NEXT) return (-1); break; } return (0); } void pms_proc_synaptics(struct pms_softc *sc) { struct synaptics_softc *syn = sc->synaptics; u_int buttons; int x, y, z, w, fingerwidth; w = ((sc->packet[0] & 0x30) >> 2) | ((sc->packet[0] & 0x04) >> 1) | ((sc->packet[3] & 0x04) >> 2); z = sc->packet[2]; if ((syn->capabilities & SYNAPTICS_CAP_EXTENDED) == 0) { /* * Emulate W mode for models that don't provide it. Bit 3 * of the w-input signals a touch ("finger"), Bit 2 and * the "gesture" bits 1-0 can be ignored. */ if (w & 8) w = 4; else z = w = 0; } if (w == 3) { if (syn->capabilities & SYNAPTICS_CAP_PASSTHROUGH) synaptics_sec_proc(sc); return; } if ((sc->sc_dev_enable & PMS_DEV_PRIMARY) == 0) return; if (w == 2) return; /* EW-mode packets are not expected here. */ x = ((sc->packet[3] & 0x10) << 8) | ((sc->packet[1] & 0x0f) << 8) | sc->packet[4]; y = ((sc->packet[3] & 0x20) << 7) | ((sc->packet[1] & 0xf0) << 4) | sc->packet[5]; buttons = ((sc->packet[0] & sc->packet[3]) & 0x01) ? WSMOUSE_BUTTON(1) : 0; buttons |= ((sc->packet[0] & sc->packet[3]) & 0x02) ? WSMOUSE_BUTTON(3) : 0; if (syn->ext_capabilities & SYNAPTICS_EXT_CAP_CLICKPAD) { buttons |= ((sc->packet[0] ^ sc->packet[3]) & 0x01) ? WSMOUSE_BUTTON(1) : 0; } else if (syn->capabilities & SYNAPTICS_CAP_MIDDLE_BUTTON) { buttons |= ((sc->packet[0] ^ sc->packet[3]) & 0x01) ? WSMOUSE_BUTTON(2) : 0; } if (syn->capabilities & SYNAPTICS_CAP_FOUR_BUTTON) { buttons |= ((sc->packet[0] ^ sc->packet[3]) & 0x01) ? WSMOUSE_BUTTON(4) : 0; buttons |= ((sc->packet[0] ^ sc->packet[3]) & 0x02) ? WSMOUSE_BUTTON(5) : 0; } else if (SYNAPTICS_EXT_MODEL_BUTTONS(syn->ext_model) && ((sc->packet[0] ^ sc->packet[3]) & 0x02)) { if (syn->ext2_capabilities & SYNAPTICS_EXT2_CAP_BUTTONS_STICK) { /* * Trackstick buttons on this machine are wired to the * trackpad as extra buttons, so route the event * through the trackstick interface as normal buttons */ syn->sec_buttons = (sc->packet[4] & 0x01) ? WSMOUSE_BUTTON(1) : 0; syn->sec_buttons |= (sc->packet[5] & 0x01) ? WSMOUSE_BUTTON(3) : 0; syn->sec_buttons |= (sc->packet[4] & 0x02) ? WSMOUSE_BUTTON(2) : 0; wsmouse_buttons( sc->sc_sec_wsmousedev, syn->sec_buttons); wsmouse_input_sync(sc->sc_sec_wsmousedev); return; } buttons |= (sc->packet[4] & 0x01) ? WSMOUSE_BUTTON(6) : 0; buttons |= (sc->packet[5] & 0x01) ? WSMOUSE_BUTTON(7) : 0; buttons |= (sc->packet[4] & 0x02) ? WSMOUSE_BUTTON(8) : 0; buttons |= (sc->packet[5] & 0x02) ? WSMOUSE_BUTTON(9) : 0; buttons |= (sc->packet[4] & 0x04) ? WSMOUSE_BUTTON(10) : 0; buttons |= (sc->packet[5] & 0x04) ? WSMOUSE_BUTTON(11) : 0; buttons |= (sc->packet[4] & 0x08) ? WSMOUSE_BUTTON(12) : 0; buttons |= (sc->packet[5] & 0x08) ? WSMOUSE_BUTTON(13) : 0; x &= ~0x0f; y &= ~0x0f; } if (z) { fingerwidth = max(w, 4); w = (w < 2 ? w + 2 : 1); } else { fingerwidth = 0; w = 0; } wsmouse_set(sc->sc_wsmousedev, WSMOUSE_TOUCH_WIDTH, fingerwidth, 0); WSMOUSE_TOUCH(sc->sc_wsmousedev, buttons, x, y, z, w); } void pms_disable_synaptics(struct pms_softc *sc) { struct synaptics_softc *syn = sc->synaptics; if (syn->capabilities & SYNAPTICS_CAP_SLEEP) synaptics_set_mode(sc, SYNAPTICS_SLEEP_MODE | SYNAPTICS_DISABLE_GESTURE, 0); } int alps_sec_proc(struct pms_softc *sc) { struct alps_softc *alps = sc->alps; int dx, dy, pos = 0; if ((sc->packet[0] & PMS_ALPS_PS2_MASK) == PMS_ALPS_PS2_VALID) { /* * We need to keep buttons states because interleaved * packets only signalize x/y movements. */ alps->sec_buttons = butmap[sc->packet[0] & PMS_PS2_BUTTONSMASK]; } else if ((sc->packet[3] & PMS_ALPS_INTERLEAVED_MASK) == PMS_ALPS_INTERLEAVED_VALID) { sc->inputstate = 3; pos = 3; } else { return (0); } if ((sc->sc_dev_enable & PMS_DEV_SECONDARY) == 0) return (1); dx = (sc->packet[pos] & PMS_PS2_XNEG) ? (int)sc->packet[pos + 1] - 256 : sc->packet[pos + 1]; dy = (sc->packet[pos] & PMS_PS2_YNEG) ? (int)sc->packet[pos + 2] - 256 : sc->packet[pos + 2]; WSMOUSE_INPUT(sc->sc_sec_wsmousedev, alps->sec_buttons, dx, dy, 0, 0); return (1); } int alps_get_hwinfo(struct pms_softc *sc) { struct alps_softc *alps = sc->alps; u_char resp[3]; int i; struct wsmousehw *hw; if (pms_set_resolution(sc, 0) || pms_set_scaling(sc, 2) || pms_set_scaling(sc, 2) || pms_set_scaling(sc, 2) || pms_get_status(sc, resp)) { DPRINTF("%s: alps: model query error\n", DEVNAME(sc)); return (-1); } alps->version = (resp[0] << 8) | (resp[1] << 4) | (resp[2] / 20 + 1); for (i = 0; i < nitems(alps_models); i++) if (alps->version == alps_models[i].version) { alps->model = alps_models[i].model; alps->mask = alps_models[i].mask; hw = wsmouse_get_hw(sc->sc_wsmousedev); hw->type = WSMOUSE_TYPE_ALPS; hw->hw_type = WSMOUSEHW_TOUCHPAD; hw->x_min = ALPS_XMIN_BEZEL; hw->y_min = ALPS_YMIN_BEZEL; hw->x_max = ALPS_XMAX_BEZEL; hw->y_max = ALPS_YMAX_BEZEL; hw->contacts_max = 1; return (0); } return (-1); } int pms_enable_alps(struct pms_softc *sc) { struct alps_softc *alps = sc->alps; struct wsmousedev_attach_args a; u_char resp[3]; if (pms_set_resolution(sc, 0) || pms_set_scaling(sc, 1) || pms_set_scaling(sc, 1) || pms_set_scaling(sc, 1) || pms_get_status(sc, resp) || resp[0] != PMS_ALPS_MAGIC1 || resp[1] != PMS_ALPS_MAGIC2 || (resp[2] != PMS_ALPS_MAGIC3_1 && resp[2] != PMS_ALPS_MAGIC3_2 && resp[2] != PMS_ALPS_MAGIC3_3)) goto err; if (sc->alps == NULL) { sc->alps = alps = malloc(sizeof(struct alps_softc), M_DEVBUF, M_WAITOK | M_ZERO); if (alps == NULL) { printf("%s: alps: not enough memory\n", DEVNAME(sc)); goto err; } if (alps_get_hwinfo(sc)) { free(sc->alps, M_DEVBUF, sizeof(struct alps_softc)); sc->alps = NULL; goto err; } if (wsmouse_configure(sc->sc_wsmousedev, alps_params, nitems(alps_params))) { free(sc->alps, M_DEVBUF, sizeof(struct alps_softc)); sc->alps = NULL; printf("%s: setup failed\n", DEVNAME(sc)); goto err; } printf("%s: ALPS %s, version 0x%04x\n", DEVNAME(sc), (alps->model & ALPS_DUALPOINT ? "Dualpoint" : "Glidepoint"), alps->version); if (alps->model & ALPS_DUALPOINT) { a.accessops = &pms_sec_accessops; a.accesscookie = sc; sc->sc_sec_wsmousedev = config_found((void *)sc, &a, wsmousedevprint); } } if (alps->model == 0) goto err; if ((alps->model & ALPS_PASSTHROUGH) && (pms_set_scaling(sc, 2) || pms_set_scaling(sc, 2) || pms_set_scaling(sc, 2) || pms_dev_disable(sc))) { DPRINTF("%s: alps: passthrough on error\n", DEVNAME(sc)); goto err; } if (pms_dev_disable(sc) || pms_dev_disable(sc) || pms_set_rate(sc, 0x0a)) { DPRINTF("%s: alps: tapping error\n", DEVNAME(sc)); goto err; } if (pms_dev_disable(sc) || pms_dev_disable(sc) || pms_dev_disable(sc) || pms_dev_disable(sc) || pms_dev_enable(sc)) { DPRINTF("%s: alps: absolute mode error\n", DEVNAME(sc)); goto err; } if ((alps->model & ALPS_PASSTHROUGH) && (pms_set_scaling(sc, 1) || pms_set_scaling(sc, 1) || pms_set_scaling(sc, 1) || pms_dev_disable(sc))) { DPRINTF("%s: alps: passthrough off error\n", DEVNAME(sc)); goto err; } alps->sec_buttons = 0; return (1); err: pms_reset(sc); return (0); } int pms_ioctl_alps(struct pms_softc *sc, u_long cmd, caddr_t data, int flag, struct proc *p) { struct wsmouse_calibcoords *wsmc = (struct wsmouse_calibcoords *)data; int wsmode; struct wsmousehw *hw; switch (cmd) { case WSMOUSEIO_GTYPE: *(u_int *)data = WSMOUSE_TYPE_ALPS; break; case WSMOUSEIO_GCALIBCOORDS: hw = wsmouse_get_hw(sc->sc_wsmousedev); wsmc->minx = hw->x_min; wsmc->maxx = hw->x_max; wsmc->miny = hw->y_min; wsmc->maxy = hw->y_max; wsmc->swapxy = 0; break; case WSMOUSEIO_SETMODE: wsmode = *(u_int *)data; if (wsmode != WSMOUSE_COMPAT && wsmode != WSMOUSE_NATIVE) return (EINVAL); wsmouse_set_mode(sc->sc_wsmousedev, wsmode); break; default: return (-1); } return (0); } int pms_sync_alps(struct pms_softc *sc, int data) { struct alps_softc *alps = sc->alps; if ((alps->model & ALPS_DUALPOINT) && (sc->packet[0] & PMS_ALPS_PS2_MASK) == PMS_ALPS_PS2_VALID) { if (sc->inputstate == 2) sc->inputstate += 3; return (0); } switch (sc->inputstate) { case 0: if ((data & alps->mask) != alps->mask) return (-1); break; case 1: case 2: case 3: if ((data & PMS_ALPS_MASK) != PMS_ALPS_VALID) return (-1); break; case 4: case 5: if ((alps->model & ALPS_INTERLEAVED) == 0 && (data & PMS_ALPS_MASK) != PMS_ALPS_VALID) return (-1); break; } return (0); } void pms_proc_alps(struct pms_softc *sc) { struct alps_softc *alps = sc->alps; int x, y, z, dx, dy; u_int buttons, gesture; if ((alps->model & ALPS_DUALPOINT) && alps_sec_proc(sc)) return; x = sc->packet[1] | ((sc->packet[2] & 0x78) << 4); y = sc->packet[4] | ((sc->packet[3] & 0x70) << 3); z = sc->packet[5]; buttons = ((sc->packet[3] & 1) ? WSMOUSE_BUTTON(1) : 0) | ((sc->packet[3] & 2) ? WSMOUSE_BUTTON(3) : 0) | ((sc->packet[3] & 4) ? WSMOUSE_BUTTON(2) : 0); if ((sc->sc_dev_enable & PMS_DEV_SECONDARY) && z == ALPS_Z_MAGIC) { dx = (x > ALPS_XSEC_BEZEL / 2) ? (x - ALPS_XSEC_BEZEL) : x; dy = (y > ALPS_YSEC_BEZEL / 2) ? (y - ALPS_YSEC_BEZEL) : y; WSMOUSE_INPUT(sc->sc_sec_wsmousedev, buttons, dx, dy, 0, 0); return; } if ((sc->sc_dev_enable & PMS_DEV_PRIMARY) == 0) return; /* * XXX The Y-axis is in the oposit direction compared to * Synaptics touchpads and PS/2 mouses. * It's why we need to translate the y value here for both * NATIVE and COMPAT modes. */ y = ALPS_YMAX_BEZEL - y + ALPS_YMIN_BEZEL; if (alps->gesture == ALPS_TAP) { /* Report a touch with the tap coordinates. */ WSMOUSE_TOUCH(sc->sc_wsmousedev, buttons, alps->old_x, alps->old_y, ALPS_PRESSURE, 0); if (z > 0) { /* * The hardware doesn't send a null pressure * event when dragging starts. */ WSMOUSE_TOUCH(sc->sc_wsmousedev, buttons, alps->old_x, alps->old_y, 0, 0); } } gesture = sc->packet[2] & 0x03; if (gesture != ALPS_TAP) WSMOUSE_TOUCH(sc->sc_wsmousedev, buttons, x, y, z, 0); if (alps->gesture != ALPS_DRAG || gesture != ALPS_TAP) alps->gesture = gesture; alps->old_x = x; alps->old_y = y; } int elantech_set_absolute_mode_v1(struct pms_softc *sc) { int i; u_char resp[3]; /* Enable absolute mode. Magic numbers from Linux driver. */ if (pms_spec_cmd(sc, ELANTECH_CMD_WRITE_REG) || pms_spec_cmd(sc, 0x10) || pms_spec_cmd(sc, 0x16) || pms_set_scaling(sc, 1) || pms_spec_cmd(sc, ELANTECH_CMD_WRITE_REG) || pms_spec_cmd(sc, 0x11) || pms_spec_cmd(sc, 0x8f) || pms_set_scaling(sc, 1)) return (-1); /* Read back reg 0x10 to ensure hardware is ready. */ for (i = 0; i < 5; i++) { if (pms_spec_cmd(sc, ELANTECH_CMD_READ_REG) || pms_spec_cmd(sc, 0x10) || pms_get_status(sc, resp) == 0) break; delay(2000); } if (i == 5) return (-1); if ((resp[0] & ELANTECH_ABSOLUTE_MODE) == 0) return (-1); return (0); } int elantech_set_absolute_mode_v2(struct pms_softc *sc) { int i; u_char resp[3]; u_char reg10 = (sc->elantech->fw_version == 0x20030 ? 0x54 : 0xc4); /* Enable absolute mode. Magic numbers from Linux driver. */ if (elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) || elantech_ps2_cmd(sc, ELANTECH_CMD_WRITE_REG) || elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) || elantech_ps2_cmd(sc, 0x10) || elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) || elantech_ps2_cmd(sc, reg10) || pms_set_scaling(sc, 1) || elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) || elantech_ps2_cmd(sc, ELANTECH_CMD_WRITE_REG) || elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) || elantech_ps2_cmd(sc, 0x11) || elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) || elantech_ps2_cmd(sc, 0x88) || pms_set_scaling(sc, 1)) return (-1); /* Read back reg 0x10 to ensure hardware is ready. */ for (i = 0; i < 5; i++) { if (elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) || elantech_ps2_cmd(sc, ELANTECH_CMD_READ_REG) || elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) || elantech_ps2_cmd(sc, 0x10) || pms_get_status(sc, resp) == 0) break; delay(2000); } if (i == 5) return (-1); return (0); } int elantech_set_absolute_mode_v3(struct pms_softc *sc) { int i; u_char resp[3]; /* Enable absolute mode. Magic numbers from Linux driver. */ if (elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) || elantech_ps2_cmd(sc, ELANTECH_CMD_READ_WRITE_REG) || elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) || elantech_ps2_cmd(sc, 0x10) || elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) || elantech_ps2_cmd(sc, 0x0b) || pms_set_scaling(sc, 1)) return (-1); /* Read back reg 0x10 to ensure hardware is ready. */ for (i = 0; i < 5; i++) { if (elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) || elantech_ps2_cmd(sc, ELANTECH_CMD_READ_WRITE_REG) || elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) || elantech_ps2_cmd(sc, 0x10) || pms_get_status(sc, resp) == 0) break; delay(2000); } if (i == 5) return (-1); return (0); } int elantech_set_absolute_mode_v4(struct pms_softc *sc) { /* Enable absolute mode. Magic numbers from Linux driver. */ if (elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) || elantech_ps2_cmd(sc, ELANTECH_CMD_READ_WRITE_REG) || elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) || elantech_ps2_cmd(sc, 0x07) || elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) || elantech_ps2_cmd(sc, ELANTECH_CMD_READ_WRITE_REG) || elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) || elantech_ps2_cmd(sc, 0x01) || pms_set_scaling(sc, 1)) return (-1); /* v4 has no register 0x10 to read response from */ return (0); } int elantech_get_hwinfo_v1(struct pms_softc *sc) { struct elantech_softc *elantech = sc->elantech; struct wsmousehw *hw; int fw_version; u_char capabilities[3]; if (synaptics_query(sc, ELANTECH_QUE_FW_VER, &fw_version)) return (-1); if (fw_version < 0x20030 || fw_version == 0x20600) { if (fw_version < 0x20000) elantech->flags |= ELANTECH_F_HW_V1_OLD; } else return (-1); elantech->fw_version = fw_version; if (pms_spec_cmd(sc, ELANTECH_QUE_CAPABILITIES) || pms_get_status(sc, capabilities)) return (-1); if (capabilities[0] & ELANTECH_CAP_HAS_ROCKER) elantech->flags |= ELANTECH_F_HAS_ROCKER; if (elantech_set_absolute_mode_v1(sc)) return (-1); hw = wsmouse_get_hw(sc->sc_wsmousedev); hw->type = WSMOUSE_TYPE_ELANTECH; hw->hw_type = WSMOUSEHW_TOUCHPAD; hw->x_min = ELANTECH_V1_X_MIN; hw->x_max = ELANTECH_V1_X_MAX; hw->y_min = ELANTECH_V1_Y_MIN; hw->y_max = ELANTECH_V1_Y_MAX; return (0); } int elantech_get_hwinfo_v2(struct pms_softc *sc) { struct elantech_softc *elantech = sc->elantech; struct wsmousehw *hw; int fw_version, ic_ver; u_char capabilities[3]; int i, fixed_dpi; u_char resp[3]; if (synaptics_query(sc, ELANTECH_QUE_FW_VER, &fw_version)) return (-1); ic_ver = (fw_version & 0x0f0000) >> 16; if (ic_ver != 2 && ic_ver != 4) return (-1); elantech->fw_version = fw_version; if (fw_version >= 0x20800) elantech->flags |= ELANTECH_F_REPORTS_PRESSURE; if (pms_spec_cmd(sc, ELANTECH_QUE_CAPABILITIES) || pms_get_status(sc, capabilities)) return (-1); if (elantech_set_absolute_mode_v2(sc)) return (-1); hw = wsmouse_get_hw(sc->sc_wsmousedev); hw->type = WSMOUSE_TYPE_ELANTECH; hw->hw_type = WSMOUSEHW_TOUCHPAD; if (fw_version == 0x20800 || fw_version == 0x20b00 || fw_version == 0x20030) { hw->x_max = ELANTECH_V2_X_MAX; hw->y_max = ELANTECH_V2_Y_MAX; } else { if (pms_spec_cmd(sc, ELANTECH_QUE_FW_ID) || pms_get_status(sc, resp)) return (-1); fixed_dpi = resp[1] & 0x10; i = (fw_version > 0x20800 && fw_version < 0x20900) ? 1 : 2; if ((fw_version >> 16) == 0x14 && fixed_dpi) { if (pms_spec_cmd(sc, ELANTECH_QUE_SAMPLE) || pms_get_status(sc, resp)) return (-1); hw->x_max = (capabilities[1] - i) * resp[1] / 2; hw->y_max = (capabilities[2] - i) * resp[2] / 2; } else if (fw_version == 0x040216) { hw->x_max = 819; hw->y_max = 405; } else if (fw_version == 0x040219 || fw_version == 0x040215) { hw->x_max = 900; hw->y_max = 500; } else { hw->x_max = (capabilities[1] - i) * 64; hw->y_max = (capabilities[2] - i) * 64; } } return (0); } int elantech_get_hwinfo_v3(struct pms_softc *sc) { struct elantech_softc *elantech = sc->elantech; struct wsmousehw *hw; int fw_version; u_char resp[3]; if (synaptics_query(sc, ELANTECH_QUE_FW_VER, &fw_version)) return (-1); if (((fw_version & 0x0f0000) >> 16) != 5) return (-1); elantech->fw_version = fw_version; elantech->flags |= ELANTECH_F_REPORTS_PRESSURE; if ((fw_version & 0x4000) == 0x4000) elantech->flags |= ELANTECH_F_CRC_ENABLED; if (elantech_set_absolute_mode_v3(sc)) return (-1); if (pms_spec_cmd(sc, ELANTECH_QUE_FW_ID) || pms_get_status(sc, resp)) return (-1); hw = wsmouse_get_hw(sc->sc_wsmousedev); hw->x_max = elantech->max_x = (resp[0] & 0x0f) << 8 | resp[1]; hw->y_max = elantech->max_y = (resp[0] & 0xf0) << 4 | resp[2]; hw->type = WSMOUSE_TYPE_ELANTECH; hw->hw_type = WSMOUSEHW_TOUCHPAD; return (0); } int elantech_get_hwinfo_v4(struct pms_softc *sc) { struct elantech_softc *elantech = sc->elantech; struct wsmousehw *hw; int fw_version; u_char capabilities[3]; u_char resp[3]; if (synaptics_query(sc, ELANTECH_QUE_FW_VER, &fw_version)) return (-1); if ((fw_version & 0x0f0000) >> 16 < 6) return (-1); elantech->fw_version = fw_version; elantech->flags |= ELANTECH_F_REPORTS_PRESSURE; if ((fw_version & 0x4000) == 0x4000) elantech->flags |= ELANTECH_F_CRC_ENABLED; if (elantech_set_absolute_mode_v4(sc)) return (-1); if (pms_spec_cmd(sc, ELANTECH_QUE_CAPABILITIES) || pms_get_status(sc, capabilities)) return (-1); if (pms_spec_cmd(sc, ELANTECH_QUE_FW_ID) || pms_get_status(sc, resp)) return (-1); hw = wsmouse_get_hw(sc->sc_wsmousedev); hw->x_max = (resp[0] & 0x0f) << 8 | resp[1]; hw->y_max = (resp[0] & 0xf0) << 4 | resp[2]; if ((capabilities[1] < 2) || (capabilities[1] > hw->x_max)) return (-1); if (capabilities[0] & ELANTECH_CAP_TRACKPOINT) elantech->flags |= ELANTECH_F_TRACKPOINT; hw->type = WSMOUSE_TYPE_ELANTECH; hw->hw_type = (ELANTECH_IS_CLICKPAD(sc) ? WSMOUSEHW_CLICKPAD : WSMOUSEHW_TOUCHPAD); hw->mt_slots = ELANTECH_MAX_FINGERS; elantech->width = hw->x_max / (capabilities[1] - 1); return (0); } int elantech_ps2_cmd(struct pms_softc *sc, u_char command) { u_char cmd[1]; cmd[0] = command; return (pms_cmd(sc, cmd, 1, NULL, 0)); } int elantech_knock(struct pms_softc *sc) { u_char resp[3]; if (pms_dev_disable(sc) || pms_set_scaling(sc, 1) || pms_set_scaling(sc, 1) || pms_set_scaling(sc, 1) || pms_get_status(sc, resp) || resp[0] != PMS_ELANTECH_MAGIC1 || resp[1] != PMS_ELANTECH_MAGIC2 || (resp[2] != PMS_ELANTECH_MAGIC3_1 && resp[2] != PMS_ELANTECH_MAGIC3_2)) return (-1); return (0); } int pms_enable_elantech_v1(struct pms_softc *sc) { struct elantech_softc *elantech = sc->elantech; int i; if (elantech_knock(sc)) goto err; if (sc->elantech == NULL) { sc->elantech = elantech = malloc(sizeof(struct elantech_softc), M_DEVBUF, M_WAITOK | M_ZERO); if (elantech == NULL) { printf("%s: elantech: not enough memory\n", DEVNAME(sc)); goto err; } if (elantech_get_hwinfo_v1(sc)) { free(sc->elantech, M_DEVBUF, sizeof(struct elantech_softc)); sc->elantech = NULL; goto err; } if (wsmouse_configure(sc->sc_wsmousedev, NULL, 0)) { free(sc->elantech, M_DEVBUF, sizeof(struct elantech_softc)); sc->elantech = NULL; printf("%s: elantech: setup failed\n", DEVNAME(sc)); goto err; } printf("%s: Elantech Touchpad, version %d, firmware 0x%x\n", DEVNAME(sc), 1, sc->elantech->fw_version); } else if (elantech_set_absolute_mode_v1(sc)) goto err; for (i = 0; i < nitems(sc->elantech->parity); i++) sc->elantech->parity[i] = sc->elantech->parity[i & (i - 1)] ^ 1; return (1); err: pms_reset(sc); return (0); } int pms_enable_elantech_v2(struct pms_softc *sc) { struct elantech_softc *elantech = sc->elantech; if (elantech_knock(sc)) goto err; if (sc->elantech == NULL) { sc->elantech = elantech = malloc(sizeof(struct elantech_softc), M_DEVBUF, M_WAITOK | M_ZERO); if (elantech == NULL) { printf("%s: elantech: not enough memory\n", DEVNAME(sc)); goto err; } if (elantech_get_hwinfo_v2(sc)) { free(sc->elantech, M_DEVBUF, sizeof(struct elantech_softc)); sc->elantech = NULL; goto err; } if (wsmouse_configure(sc->sc_wsmousedev, NULL, 0)) { free(sc->elantech, M_DEVBUF, sizeof(struct elantech_softc)); sc->elantech = NULL; printf("%s: elantech: setup failed\n", DEVNAME(sc)); goto err; } printf("%s: Elantech Touchpad, version %d, firmware 0x%x\n", DEVNAME(sc), 2, sc->elantech->fw_version); } else if (elantech_set_absolute_mode_v2(sc)) goto err; return (1); err: pms_reset(sc); return (0); } int pms_enable_elantech_v3(struct pms_softc *sc) { struct elantech_softc *elantech = sc->elantech; if (elantech_knock(sc)) goto err; if (sc->elantech == NULL) { sc->elantech = elantech = malloc(sizeof(struct elantech_softc), M_DEVBUF, M_WAITOK | M_ZERO); if (elantech == NULL) { printf("%s: elantech: not enough memory\n", DEVNAME(sc)); goto err; } if (elantech_get_hwinfo_v3(sc)) { free(sc->elantech, M_DEVBUF, sizeof(struct elantech_softc)); sc->elantech = NULL; goto err; } if (wsmouse_configure(sc->sc_wsmousedev, NULL, 0)) { free(sc->elantech, M_DEVBUF, sizeof(struct elantech_softc)); sc->elantech = NULL; printf("%s: elantech: setup failed\n", DEVNAME(sc)); goto err; } printf("%s: Elantech Touchpad, version %d, firmware 0x%x\n", DEVNAME(sc), 3, sc->elantech->fw_version); } else if (elantech_set_absolute_mode_v3(sc)) goto err; return (1); err: pms_reset(sc); return (0); } int pms_enable_elantech_v4(struct pms_softc *sc) { struct elantech_softc *elantech = sc->elantech; struct wsmousedev_attach_args a; if (elantech_knock(sc)) goto err; if (sc->elantech == NULL) { sc->elantech = elantech = malloc(sizeof(struct elantech_softc), M_DEVBUF, M_WAITOK | M_ZERO); if (elantech == NULL) { printf("%s: elantech: not enough memory\n", DEVNAME(sc)); goto err; } if (elantech_get_hwinfo_v4(sc)) { free(sc->elantech, M_DEVBUF, sizeof(struct elantech_softc)); sc->elantech = NULL; goto err; } if (wsmouse_configure(sc->sc_wsmousedev, NULL, 0)) { free(sc->elantech, M_DEVBUF, sizeof(struct elantech_softc)); sc->elantech = NULL; printf("%s: elantech: setup failed\n", DEVNAME(sc)); goto err; } printf("%s: Elantech %s, version 4, firmware 0x%x\n", DEVNAME(sc), (ELANTECH_IS_CLICKPAD(sc) ? "Clickpad" : "Touchpad"), sc->elantech->fw_version); if (sc->elantech->flags & ELANTECH_F_TRACKPOINT) { a.accessops = &pms_sec_accessops; a.accesscookie = sc; sc->sc_sec_wsmousedev = config_found((void *) sc, &a, wsmousedevprint); } } else if (elantech_set_absolute_mode_v4(sc)) goto err; return (1); err: pms_reset(sc); return (0); } int pms_ioctl_elantech(struct pms_softc *sc, u_long cmd, caddr_t data, int flag, struct proc *p) { struct wsmouse_calibcoords *wsmc = (struct wsmouse_calibcoords *)data; struct wsmousehw *hw; int wsmode; switch (cmd) { case WSMOUSEIO_GTYPE: *(u_int *)data = WSMOUSE_TYPE_ELANTECH; break; case WSMOUSEIO_GCALIBCOORDS: hw = wsmouse_get_hw(sc->sc_wsmousedev); wsmc->minx = hw->x_min; wsmc->maxx = hw->x_max; wsmc->miny = hw->y_min; wsmc->maxy = hw->y_max; wsmc->swapxy = 0; wsmc->resx = hw->h_res; wsmc->resy = hw->v_res; break; case WSMOUSEIO_SETMODE: wsmode = *(u_int *)data; if (wsmode != WSMOUSE_COMPAT && wsmode != WSMOUSE_NATIVE) return (EINVAL); wsmouse_set_mode(sc->sc_wsmousedev, wsmode); break; default: return (-1); } return (0); } int pms_sync_elantech_v1(struct pms_softc *sc, int data) { struct elantech_softc *elantech = sc->elantech; u_char p; switch (sc->inputstate) { case 0: if (elantech->flags & ELANTECH_F_HW_V1_OLD) { elantech->p1 = (data & 0x20) >> 5; elantech->p2 = (data & 0x10) >> 4; } else { elantech->p1 = (data & 0x10) >> 4; elantech->p2 = (data & 0x20) >> 5; } elantech->p3 = (data & 0x04) >> 2; return (0); case 1: p = elantech->p1; break; case 2: p = elantech->p2; break; case 3: p = elantech->p3; break; default: return (-1); } if (data < 0 || data >= nitems(elantech->parity) || /* * FW 0x20022 sends inverted parity bits on cold boot, returning * to normal after suspend & resume, so the parity check is * disabled for this one. */ (elantech->fw_version != 0x20022 && elantech->parity[data] != p)) return (-1); return (0); } int pms_sync_elantech_v2(struct pms_softc *sc, int data) { struct elantech_softc *elantech = sc->elantech; /* Variants reporting pressure always have the same constant bits. */ if (elantech->flags & ELANTECH_F_REPORTS_PRESSURE) { if (sc->inputstate == 0 && (data & 0x0c) != 0x04) return (-1); if (sc->inputstate == 3 && (data & 0x0f) != 0x02) return (-1); return (0); } /* For variants not reporting pressure, 1 and 3 finger touch packets * have different constant bits than 2 finger touch packets. */ switch (sc->inputstate) { case 0: if ((data & 0xc0) == 0x80) { if ((data & 0x0c) != 0x0c) return (-1); elantech->flags |= ELANTECH_F_2FINGER_PACKET; } else { if ((data & 0x3c) != 0x3c) return (-1); elantech->flags &= ~ELANTECH_F_2FINGER_PACKET; } break; case 1: case 4: if (elantech->flags & ELANTECH_F_2FINGER_PACKET) break; if ((data & 0xf0) != 0x00) return (-1); break; case 3: if (elantech->flags & ELANTECH_F_2FINGER_PACKET) { if ((data & 0x0e) != 0x08) return (-1); } else { if ((data & 0x3e) != 0x38) return (-1); } break; default: break; } return (0); } int pms_sync_elantech_v3(struct pms_softc *sc, int data) { struct elantech_softc *elantech = sc->elantech; switch (sc->inputstate) { case 0: if (elantech->flags & ELANTECH_F_CRC_ENABLED) break; if ((data & 0x0c) != 0x04 && (data & 0x0c) != 0x0c) return (-1); break; case 3: if (elantech->flags & ELANTECH_F_CRC_ENABLED) { if ((data & 0x09) != 0x08 && (data & 0x09) != 0x09) return (-1); } else { if ((data & 0xcf) != 0x02 && (data & 0xce) != 0x0c) return (-1); } break; } return (0); } /* Extract the type bits from packet[3]. */ static inline int elantech_packet_type(struct elantech_softc *elantech, u_char b) { /* * This looks dubious, but in the "crc-enabled" format bit 2 may * be set even in MOTION packets. */ if ((elantech->flags & ELANTECH_F_TRACKPOINT) && ((b & 0x0f) == 0x06)) return (ELANTECH_PKT_TRACKPOINT); else return (b & 0x03); } int pms_sync_elantech_v4(struct pms_softc *sc, int data) { if (sc->inputstate == 0) return ((data & 0x08) == 0 ? 0 : -1); if (sc->inputstate == 3) { switch (elantech_packet_type(sc->elantech, data)) { case ELANTECH_V4_PKT_STATUS: case ELANTECH_V4_PKT_HEAD: case ELANTECH_V4_PKT_MOTION: if (sc->elantech->flags & ELANTECH_F_CRC_ENABLED) return ((data & 0x08) == 0 ? 0 : -1); else return ((data & 0x1c) == 0x10 ? 0 : -1); case ELANTECH_PKT_TRACKPOINT: return ((sc->packet[0] & 0xc8) == 0 && sc->packet[1] == ((data & 0x10) << 3) && sc->packet[2] == ((data & 0x20) << 2) && (data ^ (sc->packet[0] & 0x30)) == 0x36 ? 0 : -1); } return (-1); } return (0); } void pms_proc_elantech_v1(struct pms_softc *sc) { struct elantech_softc *elantech = sc->elantech; int x, y, w, z; u_int buttons; buttons = butmap[sc->packet[0] & 3]; if (elantech->flags & ELANTECH_F_HAS_ROCKER) { if (sc->packet[0] & 0x40) /* up */ buttons |= WSMOUSE_BUTTON(4); if (sc->packet[0] & 0x80) /* down */ buttons |= WSMOUSE_BUTTON(5); } if (elantech->flags & ELANTECH_F_HW_V1_OLD) w = ((sc->packet[1] & 0x80) >> 7) + ((sc->packet[1] & 0x30) >> 4); else w = (sc->packet[0] & 0xc0) >> 6; /* * Firmwares 0x20022 and 0x20600 have a bug, position data in the * first two reports for single-touch contacts may be corrupt. */ if (elantech->fw_version == 0x20022 || elantech->fw_version == 0x20600) { if (w == 1) { if (elantech->initial_pkt < 2) { elantech->initial_pkt++; return; } } else if (elantech->initial_pkt) { elantech->initial_pkt = 0; } } /* Hardware version 1 doesn't report pressure. */ if (w) { x = ((sc->packet[1] & 0x0c) << 6) | sc->packet[2]; y = ((sc->packet[1] & 0x03) << 8) | sc->packet[3]; z = SYNAPTICS_PRESSURE; } else { x = y = z = 0; } WSMOUSE_TOUCH(sc->sc_wsmousedev, buttons, x, y, z, w); } void pms_proc_elantech_v2(struct pms_softc *sc) { const u_char debounce_pkt[] = { 0x84, 0xff, 0xff, 0x02, 0xff, 0xff }; struct elantech_softc *elantech = sc->elantech; int x, y, w, z; u_int buttons; /* * The hardware sends this packet when in debounce state. * The packet should be ignored. */ if (!memcmp(sc->packet, debounce_pkt, sizeof(debounce_pkt))) return; buttons = butmap[sc->packet[0] & 3]; w = (sc->packet[0] & 0xc0) >> 6; if (w == 1 || w == 3) { x = ((sc->packet[1] & 0x0f) << 8) | sc->packet[2]; y = ((sc->packet[4] & 0x0f) << 8) | sc->packet[5]; if (elantech->flags & ELANTECH_F_REPORTS_PRESSURE) z = ((sc->packet[1] & 0xf0) | (sc->packet[4] & 0xf0) >> 4); else z = SYNAPTICS_PRESSURE; } else if (w == 2) { x = (((sc->packet[0] & 0x10) << 4) | sc->packet[1]) << 2; y = (((sc->packet[0] & 0x20) << 3) | sc->packet[2]) << 2; z = SYNAPTICS_PRESSURE; } else { x = y = z = 0; } WSMOUSE_TOUCH(sc->sc_wsmousedev, buttons, x, y, z, w); } void pms_proc_elantech_v3(struct pms_softc *sc) { const u_char debounce_pkt[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff }; struct elantech_softc *elantech = sc->elantech; int x, y, w, z; u_int buttons; buttons = butmap[sc->packet[0] & 3]; x = ((sc->packet[1] & 0x0f) << 8 | sc->packet[2]); y = ((sc->packet[4] & 0x0f) << 8 | sc->packet[5]); z = 0; w = (sc->packet[0] & 0xc0) >> 6; if (w == 2) { /* * Two-finger touch causes two packets -- a head packet * and a tail packet. We report a single event and ignore * the tail packet. */ if (elantech->flags & ELANTECH_F_CRC_ENABLED) { if ((sc->packet[3] & 0x09) != 0x08) return; } else { /* The hardware sends this packet when in debounce state. * The packet should be ignored. */ if (!memcmp(sc->packet, debounce_pkt, sizeof(debounce_pkt))) return; if ((sc->packet[0] & 0x0c) != 0x04 && (sc->packet[3] & 0xcf) != 0x02) { /* not the head packet -- ignore */ return; } } } /* Prevent jumping cursor if pad isn't touched or reports garbage. */ if (w == 0 || ((x == 0 || y == 0 || x == elantech->max_x || y == elantech->max_y) && (x != elantech->old_x || y != elantech->old_y))) { x = elantech->old_x; y = elantech->old_y; } if (elantech->flags & ELANTECH_F_REPORTS_PRESSURE) z = (sc->packet[1] & 0xf0) | ((sc->packet[4] & 0xf0) >> 4); else if (w) z = SYNAPTICS_PRESSURE; WSMOUSE_TOUCH(sc->sc_wsmousedev, buttons, x, y, z, w); elantech->old_x = x; elantech->old_y = y; } void pms_proc_elantech_v4(struct pms_softc *sc) { struct elantech_softc *elantech = sc->elantech; struct device *sc_wsmousedev = sc->sc_wsmousedev; int id, weight, n, x, y, z; u_int buttons, slots; switch (elantech_packet_type(elantech, sc->packet[3])) { case ELANTECH_V4_PKT_STATUS: slots = elantech->mt_slots; elantech->mt_slots = sc->packet[1] & 0x1f; slots &= ~elantech->mt_slots; for (id = 0; slots; id++, slots >>= 1) { if (slots & 1) wsmouse_mtstate(sc_wsmousedev, id, 0, 0, 0); } break; case ELANTECH_V4_PKT_HEAD: id = ((sc->packet[3] & 0xe0) >> 5) - 1; if (id > -1 && id < ELANTECH_MAX_FINGERS) { x = ((sc->packet[1] & 0x0f) << 8) | sc->packet[2]; y = ((sc->packet[4] & 0x0f) << 8) | sc->packet[5]; z = (sc->packet[1] & 0xf0) | ((sc->packet[4] & 0xf0) >> 4); wsmouse_mtstate(sc_wsmousedev, id, x, y, z); } break; case ELANTECH_V4_PKT_MOTION: weight = (sc->packet[0] & 0x10) ? ELANTECH_V4_WEIGHT_VALUE : 1; for (n = 0; n < 6; n += 3) { id = ((sc->packet[n] & 0xe0) >> 5) - 1; if (id < 0 || id >= ELANTECH_MAX_FINGERS) continue; x = weight * (signed char)sc->packet[n + 1]; y = weight * (signed char)sc->packet[n + 2]; z = WSMOUSE_DEFAULT_PRESSURE; wsmouse_set(sc_wsmousedev, WSMOUSE_MT_REL_X, x, id); wsmouse_set(sc_wsmousedev, WSMOUSE_MT_REL_Y, y, id); wsmouse_set(sc_wsmousedev, WSMOUSE_MT_PRESSURE, z, id); } break; case ELANTECH_PKT_TRACKPOINT: if (sc->sc_dev_enable & PMS_DEV_SECONDARY) { /* * This firmware misreport coordinates for trackpoint * occasionally. Discard packets outside of [-127, 127] range * to prevent cursor jumps. */ if (sc->packet[4] == 0x80 || sc->packet[5] == 0x80 || sc->packet[1] >> 7 == sc->packet[4] >> 7 || sc->packet[2] >> 7 == sc->packet[5] >> 7) return; x = sc->packet[4] - 0x100 + (sc->packet[1] << 1); y = sc->packet[5] - 0x100 + (sc->packet[2] << 1); buttons = butmap[sc->packet[0] & 7]; WSMOUSE_INPUT(sc->sc_sec_wsmousedev, buttons, x, y, 0, 0); } return; default: printf("%s: unknown packet type 0x%x\n", DEVNAME(sc), sc->packet[3] & 0x1f); return; } buttons = butmap[sc->packet[0] & 3]; wsmouse_buttons(sc_wsmousedev, buttons); wsmouse_input_sync(sc_wsmousedev); }
1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 /* $OpenBSD: tty_tty.c,v 1.32 2022/08/14 01:58:28 jsg Exp $ */ /* $NetBSD: tty_tty.c,v 1.13 1996/03/30 22:24:46 christos Exp $ */ /*- * Copyright (c) 1982, 1986, 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)tty_tty.c 8.2 (Berkeley) 9/23/93 */ /* * Indirect driver for controlling tty. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/tty.h> #include <sys/vnode.h> #include <sys/lock.h> #include <sys/fcntl.h> #define cttyvp(p) \ ((p)->p_p->ps_flags & PS_CONTROLT ? \ (p)->p_p->ps_session->s_ttyvp : NULL) int cttyopen(dev_t dev, int flag, int mode, struct proc *p) { struct vnode *ttyvp = cttyvp(p); int error; if (ttyvp == NULL) return (ENXIO); vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY); error = VOP_OPEN(ttyvp, flag, NOCRED, p); VOP_UNLOCK(ttyvp); return (error); } int cttyread(dev_t dev, struct uio *uio, int flag) { struct vnode *ttyvp = cttyvp(uio->uio_procp); int error; if (ttyvp == NULL) return (EIO); vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY); error = VOP_READ(ttyvp, uio, flag, NOCRED); VOP_UNLOCK(ttyvp); return (error); } int cttywrite(dev_t dev, struct uio *uio, int flag) { struct vnode *ttyvp = cttyvp(uio->uio_procp); int error; if (ttyvp == NULL) return (EIO); vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY); error = VOP_WRITE(ttyvp, uio, flag, NOCRED); VOP_UNLOCK(ttyvp); return (error); } int cttyioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { struct vnode *ttyvp = cttyvp(p); struct session *sess; int error, secs; if (ttyvp == NULL) return (EIO); if (cmd == TIOCSCTTY) /* XXX */ return (EINVAL); if (cmd == TIOCNOTTY) { if (!SESS_LEADER(p->p_p)) { atomic_clearbits_int(&p->p_p->ps_flags, PS_CONTROLT); return (0); } else return (EINVAL); } switch (cmd) { case TIOCSETVERAUTH: if ((error = suser(p))) return error; secs = *(int *)addr; if (secs < 1 || secs > 3600) return EINVAL; sess = p->p_p->ps_pgrp->pg_session; sess->s_verauthuid = p->p_ucred->cr_ruid; sess->s_verauthppid = p->p_p->ps_pptr->ps_pid; timeout_add_sec(&sess->s_verauthto, secs); return 0; case TIOCCLRVERAUTH: sess = p->p_p->ps_pgrp->pg_session; timeout_del(&sess->s_verauthto); zapverauth(sess); return 0; case TIOCCHKVERAUTH: /* * It's not clear when or what these checks are for. * How can we reach this code with a different ruid? * The ppid check is also more porous than desired. * Nevertheless, the checks reflect the original intention; * namely, that it be the same user using the same shell. */ sess = p->p_p->ps_pgrp->pg_session; if (sess->s_verauthuid == p->p_ucred->cr_ruid && sess->s_verauthppid == p->p_p->ps_pptr->ps_pid) return 0; return EPERM; } return (VOP_IOCTL(ttyvp, cmd, addr, flag, NOCRED, p)); } int cttykqfilter(dev_t dev, struct knote *kn) { struct vnode *ttyvp = cttyvp(curproc); if (ttyvp == NULL) { if (kn->kn_flags & (__EV_POLL | __EV_SELECT)) return (seltrue_kqfilter(dev, kn)); return (ENXIO); } return (VOP_KQFILTER(ttyvp, FREAD|FWRITE, kn)); }
open /syzkaller/managers/main/kernel/machine/pmap.h: no such file or directory
5 2 1 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 /* $OpenBSD: if_pflow.c,v 1.109 2023/12/23 10:52:54 bluhm Exp $ */ /* * Copyright (c) 2011 Florian Obser <florian@narrans.de> * Copyright (c) 2011 Sebastian Benoit <benoit-lists@fb12.de> * Copyright (c) 2008 Henning Brauer <henning@openbsd.org> * Copyright (c) 2008 Joerg Goltermann <jg@osn.de> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/malloc.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/timeout.h> #include <sys/ioctl.h> #include <sys/kernel.h> #include <sys/socketvar.h> #include <sys/sysctl.h> #include <sys/mutex.h> #include <net/if.h> #include <net/if_types.h> #include <net/bpf.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/if_ether.h> #include <netinet/tcp.h> #include <netinet/ip.h> #include <netinet/ip_icmp.h> #include <netinet/ip_var.h> #include <netinet/udp.h> #include <netinet/udp_var.h> #include <netinet/in_pcb.h> #include <net/pfvar.h> #include <net/pfvar_priv.h> #include <net/if_pflow.h> #include "bpfilter.h" #include "pflow.h" #define PFLOW_MINMTU \ (sizeof(struct pflow_header) + sizeof(struct pflow_flow)) #ifdef PFLOWDEBUG #define DPRINTF(x) do { printf x ; } while (0) #else #define DPRINTF(x) #endif SMR_SLIST_HEAD(, pflow_softc) pflowif_list; enum pflowstat_counters { pflow_flows, pflow_packets, pflow_onomem, pflow_oerrors, pflow_ncounters, }; struct cpumem *pflow_counters; static inline void pflowstat_inc(enum pflowstat_counters c) { counters_inc(pflow_counters, c); } void pflowattach(int); int pflow_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt); void pflow_output_process(void *); int pflow_clone_create(struct if_clone *, int); int pflow_clone_destroy(struct ifnet *); int pflow_set(struct pflow_softc *, struct pflowreq *); int pflow_calc_mtu(struct pflow_softc *, int, int); void pflow_setmtu(struct pflow_softc *, int); int pflowvalidsockaddr(const struct sockaddr *, int); int pflowioctl(struct ifnet *, u_long, caddr_t); struct mbuf *pflow_get_mbuf(struct pflow_softc *, u_int16_t); void pflow_flush(struct pflow_softc *); int pflow_sendout_v5(struct pflow_softc *); int pflow_sendout_ipfix(struct pflow_softc *, sa_family_t); int pflow_sendout_ipfix_tmpl(struct pflow_softc *); int pflow_sendout_mbuf(struct pflow_softc *, struct mbuf *); void pflow_timeout(void *); void pflow_timeout6(void *); void pflow_timeout_tmpl(void *); void copy_flow_data(struct pflow_flow *, struct pflow_flow *, struct pf_state *, struct pf_state_key *, int, int); void copy_flow_ipfix_4_data(struct pflow_ipfix_flow4 *, struct pflow_ipfix_flow4 *, struct pf_state *, struct pf_state_key *, struct pflow_softc *, int, int); void copy_flow_ipfix_6_data(struct pflow_ipfix_flow6 *, struct pflow_ipfix_flow6 *, struct pf_state *, struct pf_state_key *, struct pflow_softc *, int, int); int pflow_pack_flow(struct pf_state *, struct pf_state_key *, struct pflow_softc *); int pflow_pack_flow_ipfix(struct pf_state *, struct pf_state_key *, struct pflow_softc *); int export_pflow_if(struct pf_state*, struct pf_state_key *, struct pflow_softc *); int copy_flow_to_m(struct pflow_flow *flow, struct pflow_softc *sc); int copy_flow_ipfix_4_to_m(struct pflow_ipfix_flow4 *flow, struct pflow_softc *sc); int copy_flow_ipfix_6_to_m(struct pflow_ipfix_flow6 *flow, struct pflow_softc *sc); struct if_clone pflow_cloner = IF_CLONE_INITIALIZER("pflow", pflow_clone_create, pflow_clone_destroy); void pflowattach(int npflow) { SMR_SLIST_INIT(&pflowif_list); pflow_counters = counters_alloc(pflow_ncounters); if_clone_attach(&pflow_cloner); } int pflow_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) { m_freem(m); /* drop packet */ return (EAFNOSUPPORT); } void pflow_output_process(void *arg) { struct mbuf_list ml; struct pflow_softc *sc = arg; struct mbuf *m; mq_delist(&sc->sc_outputqueue, &ml); rw_enter_read(&sc->sc_lock); while ((m = ml_dequeue(&ml)) != NULL) { pflow_sendout_mbuf(sc, m); } rw_exit_read(&sc->sc_lock); } int pflow_clone_create(struct if_clone *ifc, int unit) { struct ifnet *ifp; struct pflow_softc *pflowif; pflowif = malloc(sizeof(*pflowif), M_DEVBUF, M_WAITOK|M_ZERO); rw_init(&pflowif->sc_lock, "pflowlk"); mtx_init(&pflowif->sc_mtx, IPL_MPFLOOR); MGET(pflowif->send_nam, M_WAIT, MT_SONAME); pflowif->sc_version = PFLOW_PROTO_DEFAULT; /* ipfix template init */ bzero(&pflowif->sc_tmpl_ipfix,sizeof(pflowif->sc_tmpl_ipfix)); pflowif->sc_tmpl_ipfix.set_header.set_id = htons(PFLOW_IPFIX_TMPL_SET_ID); pflowif->sc_tmpl_ipfix.set_header.set_length = htons(sizeof(struct pflow_ipfix_tmpl)); /* ipfix IPv4 template */ pflowif->sc_tmpl_ipfix.ipv4_tmpl.h.tmpl_id = htons(PFLOW_IPFIX_TMPL_IPV4_ID); pflowif->sc_tmpl_ipfix.ipv4_tmpl.h.field_count = htons(PFLOW_IPFIX_TMPL_IPV4_FIELD_COUNT); pflowif->sc_tmpl_ipfix.ipv4_tmpl.src_ip.field_id = htons(PFIX_IE_sourceIPv4Address); pflowif->sc_tmpl_ipfix.ipv4_tmpl.src_ip.len = htons(4); pflowif->sc_tmpl_ipfix.ipv4_tmpl.dest_ip.field_id = htons(PFIX_IE_destinationIPv4Address); pflowif->sc_tmpl_ipfix.ipv4_tmpl.dest_ip.len = htons(4); pflowif->sc_tmpl_ipfix.ipv4_tmpl.if_index_in.field_id = htons(PFIX_IE_ingressInterface); pflowif->sc_tmpl_ipfix.ipv4_tmpl.if_index_in.len = htons(4); pflowif->sc_tmpl_ipfix.ipv4_tmpl.if_index_out.field_id = htons(PFIX_IE_egressInterface); pflowif->sc_tmpl_ipfix.ipv4_tmpl.if_index_out.len = htons(4); pflowif->sc_tmpl_ipfix.ipv4_tmpl.packets.field_id = htons(PFIX_IE_packetDeltaCount); pflowif->sc_tmpl_ipfix.ipv4_tmpl.packets.len = htons(8); pflowif->sc_tmpl_ipfix.ipv4_tmpl.octets.field_id = htons(PFIX_IE_octetDeltaCount); pflowif->sc_tmpl_ipfix.ipv4_tmpl.octets.len = htons(8); pflowif->sc_tmpl_ipfix.ipv4_tmpl.start.field_id = htons(PFIX_IE_flowStartMilliseconds); pflowif->sc_tmpl_ipfix.ipv4_tmpl.start.len = htons(8); pflowif->sc_tmpl_ipfix.ipv4_tmpl.finish.field_id = htons(PFIX_IE_flowEndMilliseconds); pflowif->sc_tmpl_ipfix.ipv4_tmpl.finish.len = htons(8); pflowif->sc_tmpl_ipfix.ipv4_tmpl.src_port.field_id = htons(PFIX_IE_sourceTransportPort); pflowif->sc_tmpl_ipfix.ipv4_tmpl.src_port.len = htons(2); pflowif->sc_tmpl_ipfix.ipv4_tmpl.dest_port.field_id = htons(PFIX_IE_destinationTransportPort); pflowif->sc_tmpl_ipfix.ipv4_tmpl.dest_port.len = htons(2); pflowif->sc_tmpl_ipfix.ipv4_tmpl.tos.field_id = htons(PFIX_IE_ipClassOfService); pflowif->sc_tmpl_ipfix.ipv4_tmpl.tos.len = htons(1); pflowif->sc_tmpl_ipfix.ipv4_tmpl.protocol.field_id = htons(PFIX_IE_protocolIdentifier); pflowif->sc_tmpl_ipfix.ipv4_tmpl.protocol.len = htons(1); /* ipfix IPv6 template */ pflowif->sc_tmpl_ipfix.ipv6_tmpl.h.tmpl_id = htons(PFLOW_IPFIX_TMPL_IPV6_ID); pflowif->sc_tmpl_ipfix.ipv6_tmpl.h.field_count = htons(PFLOW_IPFIX_TMPL_IPV6_FIELD_COUNT); pflowif->sc_tmpl_ipfix.ipv6_tmpl.src_ip.field_id = htons(PFIX_IE_sourceIPv6Address); pflowif->sc_tmpl_ipfix.ipv6_tmpl.src_ip.len = htons(16); pflowif->sc_tmpl_ipfix.ipv6_tmpl.dest_ip.field_id = htons(PFIX_IE_destinationIPv6Address); pflowif->sc_tmpl_ipfix.ipv6_tmpl.dest_ip.len = htons(16); pflowif->sc_tmpl_ipfix.ipv6_tmpl.if_index_in.field_id = htons(PFIX_IE_ingressInterface); pflowif->sc_tmpl_ipfix.ipv6_tmpl.if_index_in.len = htons(4); pflowif->sc_tmpl_ipfix.ipv6_tmpl.if_index_out.field_id = htons(PFIX_IE_egressInterface); pflowif->sc_tmpl_ipfix.ipv6_tmpl.if_index_out.len = htons(4); pflowif->sc_tmpl_ipfix.ipv6_tmpl.packets.field_id = htons(PFIX_IE_packetDeltaCount); pflowif->sc_tmpl_ipfix.ipv6_tmpl.packets.len = htons(8); pflowif->sc_tmpl_ipfix.ipv6_tmpl.octets.field_id = htons(PFIX_IE_octetDeltaCount); pflowif->sc_tmpl_ipfix.ipv6_tmpl.octets.len = htons(8); pflowif->sc_tmpl_ipfix.ipv6_tmpl.start.field_id = htons(PFIX_IE_flowStartMilliseconds); pflowif->sc_tmpl_ipfix.ipv6_tmpl.start.len = htons(8); pflowif->sc_tmpl_ipfix.ipv6_tmpl.finish.field_id = htons(PFIX_IE_flowEndMilliseconds); pflowif->sc_tmpl_ipfix.ipv6_tmpl.finish.len = htons(8); pflowif->sc_tmpl_ipfix.ipv6_tmpl.src_port.field_id = htons(PFIX_IE_sourceTransportPort); pflowif->sc_tmpl_ipfix.ipv6_tmpl.src_port.len = htons(2); pflowif->sc_tmpl_ipfix.ipv6_tmpl.dest_port.field_id = htons(PFIX_IE_destinationTransportPort); pflowif->sc_tmpl_ipfix.ipv6_tmpl.dest_port.len = htons(2); pflowif->sc_tmpl_ipfix.ipv6_tmpl.tos.field_id = htons(PFIX_IE_ipClassOfService); pflowif->sc_tmpl_ipfix.ipv6_tmpl.tos.len = htons(1); pflowif->sc_tmpl_ipfix.ipv6_tmpl.protocol.field_id = htons(PFIX_IE_protocolIdentifier); pflowif->sc_tmpl_ipfix.ipv6_tmpl.protocol.len = htons(1); ifp = &pflowif->sc_if; snprintf(ifp->if_xname, sizeof ifp->if_xname, "pflow%d", unit); ifp->if_softc = pflowif; ifp->if_ioctl = pflowioctl; ifp->if_output = pflow_output; ifp->if_start = NULL; ifp->if_xflags = IFXF_CLONED; ifp->if_type = IFT_PFLOW; ifp->if_hdrlen = PFLOW_HDRLEN; ifp->if_flags = IFF_UP; ifp->if_flags &= ~IFF_RUNNING; /* not running, need receiver */ mq_init(&pflowif->sc_outputqueue, 8192, IPL_SOFTNET); pflow_setmtu(pflowif, ETHERMTU); timeout_set_proc(&pflowif->sc_tmo, pflow_timeout, pflowif); timeout_set_proc(&pflowif->sc_tmo6, pflow_timeout6, pflowif); timeout_set_proc(&pflowif->sc_tmo_tmpl, pflow_timeout_tmpl, pflowif); task_set(&pflowif->sc_outputtask, pflow_output_process, pflowif); if_counters_alloc(ifp); if_attach(ifp); if_alloc_sadl(ifp); /* Insert into list of pflows */ KERNEL_ASSERT_LOCKED(); SMR_SLIST_INSERT_HEAD_LOCKED(&pflowif_list, pflowif, sc_next); return (0); } int pflow_clone_destroy(struct ifnet *ifp) { struct pflow_softc *sc = ifp->if_softc; int error; error = 0; rw_enter_write(&sc->sc_lock); sc->sc_dying = 1; rw_exit_write(&sc->sc_lock); KERNEL_ASSERT_LOCKED(); SMR_SLIST_REMOVE_LOCKED(&pflowif_list, sc, pflow_softc, sc_next); smr_barrier(); timeout_del(&sc->sc_tmo); timeout_del(&sc->sc_tmo6); timeout_del(&sc->sc_tmo_tmpl); pflow_flush(sc); task_del(net_tq(ifp->if_index), &sc->sc_outputtask); taskq_barrier(net_tq(ifp->if_index)); mq_purge(&sc->sc_outputqueue); m_freem(sc->send_nam); if (sc->so != NULL) { error = soclose(sc->so, MSG_DONTWAIT); sc->so = NULL; } if (sc->sc_flowdst != NULL) free(sc->sc_flowdst, M_DEVBUF, sc->sc_flowdst->sa_len); if (sc->sc_flowsrc != NULL) free(sc->sc_flowsrc, M_DEVBUF, sc->sc_flowsrc->sa_len); if_detach(ifp); free(sc, M_DEVBUF, sizeof(*sc)); return (error); } int pflowvalidsockaddr(const struct sockaddr *sa, int ignore_port) { struct sockaddr_in6 *sin6; struct sockaddr_in *sin; if (sa == NULL) return (0); switch(sa->sa_family) { case AF_INET: sin = (struct sockaddr_in*) sa; return (sin->sin_addr.s_addr != INADDR_ANY && (ignore_port || sin->sin_port != 0)); case AF_INET6: sin6 = (struct sockaddr_in6*) sa; return (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) && (ignore_port || sin6->sin6_port != 0)); default: return (0); } } int pflow_set(struct pflow_softc *sc, struct pflowreq *pflowr) { struct proc *p = curproc; struct socket *so; struct sockaddr *sa; int error = 0; if (pflowr->addrmask & PFLOW_MASK_VERSION) { switch(pflowr->version) { case PFLOW_PROTO_5: case PFLOW_PROTO_10: break; default: return(EINVAL); } } rw_assert_wrlock(&sc->sc_lock); pflow_flush(sc); if (pflowr->addrmask & PFLOW_MASK_DSTIP) { if (sc->sc_flowdst != NULL && sc->sc_flowdst->sa_family != pflowr->flowdst.ss_family) { free(sc->sc_flowdst, M_DEVBUF, sc->sc_flowdst->sa_len); sc->sc_flowdst = NULL; if (sc->so != NULL) { soclose(sc->so, MSG_DONTWAIT); sc->so = NULL; } } switch (pflowr->flowdst.ss_family) { case AF_INET: if (sc->sc_flowdst == NULL) { if ((sc->sc_flowdst = malloc( sizeof(struct sockaddr_in), M_DEVBUF, M_NOWAIT)) == NULL) return (ENOMEM); } memcpy(sc->sc_flowdst, &pflowr->flowdst, sizeof(struct sockaddr_in)); sc->sc_flowdst->sa_len = sizeof(struct sockaddr_in); break; case AF_INET6: if (sc->sc_flowdst == NULL) { if ((sc->sc_flowdst = malloc( sizeof(struct sockaddr_in6), M_DEVBUF, M_NOWAIT)) == NULL) return (ENOMEM); } memcpy(sc->sc_flowdst, &pflowr->flowdst, sizeof(struct sockaddr_in6)); sc->sc_flowdst->sa_len = sizeof(struct sockaddr_in6); break; default: break; } if (sc->sc_flowdst != NULL) { sc->send_nam->m_len = sc->sc_flowdst->sa_len; sa = mtod(sc->send_nam, struct sockaddr *); memcpy(sa, sc->sc_flowdst, sc->sc_flowdst->sa_len); } } if (pflowr->addrmask & PFLOW_MASK_SRCIP) { if (sc->sc_flowsrc != NULL) free(sc->sc_flowsrc, M_DEVBUF, sc->sc_flowsrc->sa_len); sc->sc_flowsrc = NULL; if (sc->so != NULL) { soclose(sc->so, MSG_DONTWAIT); sc->so = NULL; } switch(pflowr->flowsrc.ss_family) { case AF_INET: if ((sc->sc_flowsrc = malloc( sizeof(struct sockaddr_in), M_DEVBUF, M_NOWAIT)) == NULL) return (ENOMEM); memcpy(sc->sc_flowsrc, &pflowr->flowsrc, sizeof(struct sockaddr_in)); sc->sc_flowsrc->sa_len = sizeof(struct sockaddr_in); break; case AF_INET6: if ((sc->sc_flowsrc = malloc( sizeof(struct sockaddr_in6), M_DEVBUF, M_NOWAIT)) == NULL) return (ENOMEM); memcpy(sc->sc_flowsrc, &pflowr->flowsrc, sizeof(struct sockaddr_in6)); sc->sc_flowsrc->sa_len = sizeof(struct sockaddr_in6); break; default: break; } } if (sc->so == NULL) { if (pflowvalidsockaddr(sc->sc_flowdst, 0)) { error = socreate(sc->sc_flowdst->sa_family, &so, SOCK_DGRAM, 0); if (error) return (error); if (pflowvalidsockaddr(sc->sc_flowsrc, 1)) { struct mbuf *m; MGET(m, M_WAIT, MT_SONAME); m->m_len = sc->sc_flowsrc->sa_len; sa = mtod(m, struct sockaddr *); memcpy(sa, sc->sc_flowsrc, sc->sc_flowsrc->sa_len); solock(so); error = sobind(so, m, p); sounlock(so); m_freem(m); if (error) { soclose(so, MSG_DONTWAIT); return (error); } } sc->so = so; } } else if (!pflowvalidsockaddr(sc->sc_flowdst, 0)) { soclose(sc->so, MSG_DONTWAIT); sc->so = NULL; } NET_LOCK(); mtx_enter(&sc->sc_mtx); /* error check is above */ if (pflowr->addrmask & PFLOW_MASK_VERSION) sc->sc_version = pflowr->version; pflow_setmtu(sc, ETHERMTU); switch (sc->sc_version) { case PFLOW_PROTO_5: timeout_del(&sc->sc_tmo6); timeout_del(&sc->sc_tmo_tmpl); break; case PFLOW_PROTO_10: timeout_add_sec(&sc->sc_tmo_tmpl, PFLOW_TMPL_TIMEOUT); break; default: /* NOTREACHED */ break; } mtx_leave(&sc->sc_mtx); NET_UNLOCK(); return (0); } int pflowioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct proc *p = curproc; struct pflow_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *)data; struct pflowreq pflowr; int error = 0; switch (cmd) { case SIOCSIFADDR: case SIOCSIFDSTADDR: case SIOCSIFFLAGS: case SIOCSIFMTU: case SIOCGETPFLOW: case SIOCSETPFLOW: break; default: return (ENOTTY); } /* XXXSMP: enforce lock order */ NET_UNLOCK(); rw_enter_write(&sc->sc_lock); if (sc->sc_dying) { error = ENXIO; goto out; } switch (cmd) { case SIOCSIFADDR: case SIOCSIFDSTADDR: case SIOCSIFFLAGS: NET_LOCK(); if ((ifp->if_flags & IFF_UP) && sc->so != NULL) { ifp->if_flags |= IFF_RUNNING; mtx_enter(&sc->sc_mtx); /* send templates on startup */ if (sc->sc_version == PFLOW_PROTO_10) pflow_sendout_ipfix_tmpl(sc); mtx_leave(&sc->sc_mtx); } else ifp->if_flags &= ~IFF_RUNNING; NET_UNLOCK(); break; case SIOCSIFMTU: if (ifr->ifr_mtu < PFLOW_MINMTU) { error = EINVAL; goto out; } if (ifr->ifr_mtu > MCLBYTES) ifr->ifr_mtu = MCLBYTES; NET_LOCK(); if (ifr->ifr_mtu < ifp->if_mtu) pflow_flush(sc); mtx_enter(&sc->sc_mtx); pflow_setmtu(sc, ifr->ifr_mtu); mtx_leave(&sc->sc_mtx); NET_UNLOCK(); break; case SIOCGETPFLOW: bzero(&pflowr, sizeof(pflowr)); if (sc->sc_flowsrc != NULL) memcpy(&pflowr.flowsrc, sc->sc_flowsrc, sc->sc_flowsrc->sa_len); if (sc->sc_flowdst != NULL) memcpy(&pflowr.flowdst, sc->sc_flowdst, sc->sc_flowdst->sa_len); mtx_enter(&sc->sc_mtx); pflowr.version = sc->sc_version; mtx_leave(&sc->sc_mtx); if ((error = copyout(&pflowr, ifr->ifr_data, sizeof(pflowr)))) goto out; break; case SIOCSETPFLOW: if ((error = suser(p)) != 0) goto out; if ((error = copyin(ifr->ifr_data, &pflowr, sizeof(pflowr)))) goto out; error = pflow_set(sc, &pflowr); if (error != 0) goto out; NET_LOCK(); if ((ifp->if_flags & IFF_UP) && sc->so != NULL) { ifp->if_flags |= IFF_RUNNING; mtx_enter(&sc->sc_mtx); if (sc->sc_version == PFLOW_PROTO_10) pflow_sendout_ipfix_tmpl(sc); mtx_leave(&sc->sc_mtx); } else ifp->if_flags &= ~IFF_RUNNING; NET_UNLOCK(); break; } out: rw_exit_write(&sc->sc_lock); NET_LOCK(); return (error); } int pflow_calc_mtu(struct pflow_softc *sc, int mtu, int hdrsz) { sc->sc_maxcount4 = (mtu - hdrsz - sizeof(struct udpiphdr)) / sizeof(struct pflow_ipfix_flow4); sc->sc_maxcount6 = (mtu - hdrsz - sizeof(struct udpiphdr)) / sizeof(struct pflow_ipfix_flow6); if (sc->sc_maxcount4 > PFLOW_MAXFLOWS) sc->sc_maxcount4 = PFLOW_MAXFLOWS; if (sc->sc_maxcount6 > PFLOW_MAXFLOWS) sc->sc_maxcount6 = PFLOW_MAXFLOWS; return (hdrsz + sizeof(struct udpiphdr) + MIN(sc->sc_maxcount4 * sizeof(struct pflow_ipfix_flow4), sc->sc_maxcount6 * sizeof(struct pflow_ipfix_flow6))); } void pflow_setmtu(struct pflow_softc *sc, int mtu_req) { int mtu; mtu = mtu_req; switch (sc->sc_version) { case PFLOW_PROTO_5: sc->sc_maxcount = (mtu - sizeof(struct pflow_header) - sizeof(struct udpiphdr)) / sizeof(struct pflow_flow); if (sc->sc_maxcount > PFLOW_MAXFLOWS) sc->sc_maxcount = PFLOW_MAXFLOWS; sc->sc_if.if_mtu = sizeof(struct pflow_header) + sizeof(struct udpiphdr) + sc->sc_maxcount * sizeof(struct pflow_flow); break; case PFLOW_PROTO_10: sc->sc_if.if_mtu = pflow_calc_mtu(sc, mtu, sizeof(struct pflow_v10_header)); break; default: /* NOTREACHED */ break; } } struct mbuf * pflow_get_mbuf(struct pflow_softc *sc, u_int16_t set_id) { struct pflow_set_header set_hdr; struct pflow_header h; struct mbuf *m; MUTEX_ASSERT_LOCKED(&sc->sc_mtx); MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == NULL) { pflowstat_inc(pflow_onomem); return (NULL); } MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { m_free(m); pflowstat_inc(pflow_onomem); return (NULL); } m->m_len = m->m_pkthdr.len = 0; m->m_pkthdr.ph_ifidx = 0; if (sc == NULL) /* get only a new empty mbuf */ return (m); switch (sc->sc_version) { case PFLOW_PROTO_5: /* populate pflow_header */ h.reserved1 = 0; h.reserved2 = 0; h.count = 0; h.version = htons(PFLOW_PROTO_5); h.flow_sequence = htonl(sc->sc_gcounter); h.engine_type = PFLOW_ENGINE_TYPE; h.engine_id = PFLOW_ENGINE_ID; m_copyback(m, 0, PFLOW_HDRLEN, &h, M_NOWAIT); sc->sc_count = 0; timeout_add_sec(&sc->sc_tmo, PFLOW_TIMEOUT); break; case PFLOW_PROTO_10: /* populate pflow_set_header */ set_hdr.set_length = 0; set_hdr.set_id = htons(set_id); m_copyback(m, 0, PFLOW_SET_HDRLEN, &set_hdr, M_NOWAIT); break; default: /* NOTREACHED */ break; } return (m); } void copy_flow_data(struct pflow_flow *flow1, struct pflow_flow *flow2, struct pf_state *st, struct pf_state_key *sk, int src, int dst) { flow1->src_ip = flow2->dest_ip = sk->addr[src].v4.s_addr; flow1->src_port = flow2->dest_port = sk->port[src]; flow1->dest_ip = flow2->src_ip = sk->addr[dst].v4.s_addr; flow1->dest_port = flow2->src_port = sk->port[dst]; flow1->dest_as = flow2->src_as = flow1->src_as = flow2->dest_as = 0; flow1->if_index_in = htons(st->if_index_in); flow1->if_index_out = htons(st->if_index_out); flow2->if_index_in = htons(st->if_index_out); flow2->if_index_out = htons(st->if_index_in); flow1->dest_mask = flow2->src_mask = flow1->src_mask = flow2->dest_mask = 0; flow1->flow_packets = htonl(st->packets[0]); flow2->flow_packets = htonl(st->packets[1]); flow1->flow_octets = htonl(st->bytes[0]); flow2->flow_octets = htonl(st->bytes[1]); /* * Pretend the flow was created or expired when the machine came up * when creation is in the future of the last time a package was seen * or was created / expired before this machine came up due to pfsync. */ flow1->flow_start = flow2->flow_start = st->creation < 0 || st->creation > st->expire ? htonl(0) : htonl(st->creation * 1000); flow1->flow_finish = flow2->flow_finish = st->expire < 0 ? htonl(0) : htonl(st->expire * 1000); flow1->tcp_flags = flow2->tcp_flags = 0; flow1->protocol = flow2->protocol = sk->proto; flow1->tos = flow2->tos = st->rule.ptr->tos; } void copy_flow_ipfix_4_data(struct pflow_ipfix_flow4 *flow1, struct pflow_ipfix_flow4 *flow2, struct pf_state *st, struct pf_state_key *sk, struct pflow_softc *sc, int src, int dst) { flow1->src_ip = flow2->dest_ip = sk->addr[src].v4.s_addr; flow1->src_port = flow2->dest_port = sk->port[src]; flow1->dest_ip = flow2->src_ip = sk->addr[dst].v4.s_addr; flow1->dest_port = flow2->src_port = sk->port[dst]; flow1->if_index_in = htonl(st->if_index_in); flow1->if_index_out = htonl(st->if_index_out); flow2->if_index_in = htonl(st->if_index_out); flow2->if_index_out = htonl(st->if_index_in); flow1->flow_packets = htobe64(st->packets[0]); flow2->flow_packets = htobe64(st->packets[1]); flow1->flow_octets = htobe64(st->bytes[0]); flow2->flow_octets = htobe64(st->bytes[1]); /* * Pretend the flow was created when the machine came up when creation * is in the future of the last time a package was seen due to pfsync. */ if (st->creation > st->expire) flow1->flow_start = flow2->flow_start = htobe64((gettime() - getuptime())*1000); else flow1->flow_start = flow2->flow_start = htobe64((gettime() - (getuptime() - st->creation))*1000); flow1->flow_finish = flow2->flow_finish = htobe64((gettime() - (getuptime() - st->expire))*1000); flow1->protocol = flow2->protocol = sk->proto; flow1->tos = flow2->tos = st->rule.ptr->tos; } void copy_flow_ipfix_6_data(struct pflow_ipfix_flow6 *flow1, struct pflow_ipfix_flow6 *flow2, struct pf_state *st, struct pf_state_key *sk, struct pflow_softc *sc, int src, int dst) { bcopy(&sk->addr[src].v6, &flow1->src_ip, sizeof(flow1->src_ip)); bcopy(&sk->addr[src].v6, &flow2->dest_ip, sizeof(flow2->dest_ip)); flow1->src_port = flow2->dest_port = sk->port[src]; bcopy(&sk->addr[dst].v6, &flow1->dest_ip, sizeof(flow1->dest_ip)); bcopy(&sk->addr[dst].v6, &flow2->src_ip, sizeof(flow2->src_ip)); flow1->dest_port = flow2->src_port = sk->port[dst]; flow1->if_index_in = htonl(st->if_index_in); flow1->if_index_out = htonl(st->if_index_out); flow2->if_index_in = htonl(st->if_index_out); flow2->if_index_out = htonl(st->if_index_in); flow1->flow_packets = htobe64(st->packets[0]); flow2->flow_packets = htobe64(st->packets[1]); flow1->flow_octets = htobe64(st->bytes[0]); flow2->flow_octets = htobe64(st->bytes[1]); /* * Pretend the flow was created when the machine came up when creation * is in the future of the last time a package was seen due to pfsync. */ if (st->creation > st->expire) flow1->flow_start = flow2->flow_start = htobe64((gettime() - getuptime())*1000); else flow1->flow_start = flow2->flow_start = htobe64((gettime() - (getuptime() - st->creation))*1000); flow1->flow_finish = flow2->flow_finish = htobe64((gettime() - (getuptime() - st->expire))*1000); flow1->protocol = flow2->protocol = sk->proto; flow1->tos = flow2->tos = st->rule.ptr->tos; } int export_pflow(struct pf_state *st) { struct pflow_softc *sc = NULL; struct pf_state_key *sk; sk = st->key[st->direction == PF_IN ? PF_SK_WIRE : PF_SK_STACK]; SMR_SLIST_FOREACH(sc, &pflowif_list, sc_next) { mtx_enter(&sc->sc_mtx); switch (sc->sc_version) { case PFLOW_PROTO_5: if (sk->af == AF_INET) export_pflow_if(st, sk, sc); break; case PFLOW_PROTO_10: if (sk->af == AF_INET || sk->af == AF_INET6) export_pflow_if(st, sk, sc); break; default: /* NOTREACHED */ break; } mtx_leave(&sc->sc_mtx); } return (0); } int export_pflow_if(struct pf_state *st, struct pf_state_key *sk, struct pflow_softc *sc) { struct pf_state pfs_copy; struct ifnet *ifp = &sc->sc_if; u_int64_t bytes[2]; int ret = 0; if (!(ifp->if_flags & IFF_RUNNING)) return (0); if (sc->sc_version == PFLOW_PROTO_10) return (pflow_pack_flow_ipfix(st, sk, sc)); /* PFLOW_PROTO_5 */ if ((st->bytes[0] < (u_int64_t)PFLOW_MAXBYTES) && (st->bytes[1] < (u_int64_t)PFLOW_MAXBYTES)) return (pflow_pack_flow(st, sk, sc)); /* flow > PFLOW_MAXBYTES need special handling */ bcopy(st, &pfs_copy, sizeof(pfs_copy)); bytes[0] = pfs_copy.bytes[0]; bytes[1] = pfs_copy.bytes[1]; while (bytes[0] > PFLOW_MAXBYTES) { pfs_copy.bytes[0] = PFLOW_MAXBYTES; pfs_copy.bytes[1] = 0; if ((ret = pflow_pack_flow(&pfs_copy, sk, sc)) != 0) return (ret); if ((bytes[0] - PFLOW_MAXBYTES) > 0) bytes[0] -= PFLOW_MAXBYTES; } while (bytes[1] > (u_int64_t)PFLOW_MAXBYTES) { pfs_copy.bytes[1] = PFLOW_MAXBYTES; pfs_copy.bytes[0] = 0; if ((ret = pflow_pack_flow(&pfs_copy, sk, sc)) != 0) return (ret); if ((bytes[1] - PFLOW_MAXBYTES) > 0) bytes[1] -= PFLOW_MAXBYTES; } pfs_copy.bytes[0] = bytes[0]; pfs_copy.bytes[1] = bytes[1]; return (pflow_pack_flow(&pfs_copy, sk, sc)); } int copy_flow_to_m(struct pflow_flow *flow, struct pflow_softc *sc) { int ret = 0; MUTEX_ASSERT_LOCKED(&sc->sc_mtx); if (sc->sc_mbuf == NULL) { if ((sc->sc_mbuf = pflow_get_mbuf(sc, 0)) == NULL) return (ENOBUFS); } m_copyback(sc->sc_mbuf, PFLOW_HDRLEN + (sc->sc_count * sizeof(struct pflow_flow)), sizeof(struct pflow_flow), flow, M_NOWAIT); pflowstat_inc(pflow_flows); sc->sc_gcounter++; sc->sc_count++; if (sc->sc_count >= sc->sc_maxcount) ret = pflow_sendout_v5(sc); return(ret); } int copy_flow_ipfix_4_to_m(struct pflow_ipfix_flow4 *flow, struct pflow_softc *sc) { int ret = 0; MUTEX_ASSERT_LOCKED(&sc->sc_mtx); if (sc->sc_mbuf == NULL) { if ((sc->sc_mbuf = pflow_get_mbuf(sc, PFLOW_IPFIX_TMPL_IPV4_ID)) == NULL) { return (ENOBUFS); } sc->sc_count4 = 0; timeout_add_sec(&sc->sc_tmo, PFLOW_TIMEOUT); } m_copyback(sc->sc_mbuf, PFLOW_SET_HDRLEN + (sc->sc_count4 * sizeof(struct pflow_ipfix_flow4)), sizeof(struct pflow_ipfix_flow4), flow, M_NOWAIT); pflowstat_inc(pflow_flows); sc->sc_gcounter++; sc->sc_count4++; if (sc->sc_count4 >= sc->sc_maxcount4) ret = pflow_sendout_ipfix(sc, AF_INET); return(ret); } int copy_flow_ipfix_6_to_m(struct pflow_ipfix_flow6 *flow, struct pflow_softc *sc) { int ret = 0; MUTEX_ASSERT_LOCKED(&sc->sc_mtx); if (sc->sc_mbuf6 == NULL) { if ((sc->sc_mbuf6 = pflow_get_mbuf(sc, PFLOW_IPFIX_TMPL_IPV6_ID)) == NULL) { return (ENOBUFS); } sc->sc_count6 = 0; timeout_add_sec(&sc->sc_tmo6, PFLOW_TIMEOUT); } m_copyback(sc->sc_mbuf6, PFLOW_SET_HDRLEN + (sc->sc_count6 * sizeof(struct pflow_ipfix_flow6)), sizeof(struct pflow_ipfix_flow6), flow, M_NOWAIT); pflowstat_inc(pflow_flows); sc->sc_gcounter++; sc->sc_count6++; if (sc->sc_count6 >= sc->sc_maxcount6) ret = pflow_sendout_ipfix(sc, AF_INET6); return(ret); } int pflow_pack_flow(struct pf_state *st, struct pf_state_key *sk, struct pflow_softc *sc) { struct pflow_flow flow1; struct pflow_flow flow2; int ret = 0; bzero(&flow1, sizeof(flow1)); bzero(&flow2, sizeof(flow2)); if (st->direction == PF_OUT) copy_flow_data(&flow1, &flow2, st, sk, 1, 0); else copy_flow_data(&flow1, &flow2, st, sk, 0, 1); if (st->bytes[0] != 0) /* first flow from state */ ret = copy_flow_to_m(&flow1, sc); if (st->bytes[1] != 0) /* second flow from state */ ret = copy_flow_to_m(&flow2, sc); return (ret); } int pflow_pack_flow_ipfix(struct pf_state *st, struct pf_state_key *sk, struct pflow_softc *sc) { struct pflow_ipfix_flow4 flow4_1, flow4_2; struct pflow_ipfix_flow6 flow6_1, flow6_2; int ret = 0; if (sk->af == AF_INET) { bzero(&flow4_1, sizeof(flow4_1)); bzero(&flow4_2, sizeof(flow4_2)); if (st->direction == PF_OUT) copy_flow_ipfix_4_data(&flow4_1, &flow4_2, st, sk, sc, 1, 0); else copy_flow_ipfix_4_data(&flow4_1, &flow4_2, st, sk, sc, 0, 1); if (st->bytes[0] != 0) /* first flow from state */ ret = copy_flow_ipfix_4_to_m(&flow4_1, sc); if (st->bytes[1] != 0) /* second flow from state */ ret = copy_flow_ipfix_4_to_m(&flow4_2, sc); } else if (sk->af == AF_INET6) { bzero(&flow6_1, sizeof(flow6_1)); bzero(&flow6_2, sizeof(flow6_2)); if (st->direction == PF_OUT) copy_flow_ipfix_6_data(&flow6_1, &flow6_2, st, sk, sc, 1, 0); else copy_flow_ipfix_6_data(&flow6_1, &flow6_2, st, sk, sc, 0, 1); if (st->bytes[0] != 0) /* first flow from state */ ret = copy_flow_ipfix_6_to_m(&flow6_1, sc); if (st->bytes[1] != 0) /* second flow from state */ ret = copy_flow_ipfix_6_to_m(&flow6_2, sc); } return (ret); } void pflow_timeout(void *v) { struct pflow_softc *sc = v; mtx_enter(&sc->sc_mtx); switch (sc->sc_version) { case PFLOW_PROTO_5: pflow_sendout_v5(sc); break; case PFLOW_PROTO_10: pflow_sendout_ipfix(sc, AF_INET); break; default: /* NOTREACHED */ break; } mtx_leave(&sc->sc_mtx); } void pflow_timeout6(void *v) { struct pflow_softc *sc = v; mtx_enter(&sc->sc_mtx); pflow_sendout_ipfix(sc, AF_INET6); mtx_leave(&sc->sc_mtx); } void pflow_timeout_tmpl(void *v) { struct pflow_softc *sc = v; mtx_enter(&sc->sc_mtx); pflow_sendout_ipfix_tmpl(sc); mtx_leave(&sc->sc_mtx); } void pflow_flush(struct pflow_softc *sc) { mtx_enter(&sc->sc_mtx); switch (sc->sc_version) { case PFLOW_PROTO_5: pflow_sendout_v5(sc); break; case PFLOW_PROTO_10: pflow_sendout_ipfix(sc, AF_INET); pflow_sendout_ipfix(sc, AF_INET6); break; default: /* NOTREACHED */ break; } mtx_leave(&sc->sc_mtx); } int pflow_sendout_v5(struct pflow_softc *sc) { struct mbuf *m = sc->sc_mbuf; struct pflow_header *h; struct ifnet *ifp = &sc->sc_if; struct timespec tv; MUTEX_ASSERT_LOCKED(&sc->sc_mtx); timeout_del(&sc->sc_tmo); if (m == NULL) return (0); sc->sc_mbuf = NULL; if (!(ifp->if_flags & IFF_RUNNING)) { m_freem(m); return (0); } pflowstat_inc(pflow_packets); h = mtod(m, struct pflow_header *); h->count = htons(sc->sc_count); /* populate pflow_header */ h->uptime_ms = htonl(getuptime() * 1000); getnanotime(&tv); h->time_sec = htonl(tv.tv_sec); /* XXX 2038 */ h->time_nanosec = htonl(tv.tv_nsec); if (mq_enqueue(&sc->sc_outputqueue, m) == 0) task_add(net_tq(ifp->if_index), &sc->sc_outputtask); return (0); } int pflow_sendout_ipfix(struct pflow_softc *sc, sa_family_t af) { struct mbuf *m; struct pflow_v10_header *h10; struct pflow_set_header *set_hdr; struct ifnet *ifp = &sc->sc_if; u_int32_t count; int set_length; MUTEX_ASSERT_LOCKED(&sc->sc_mtx); switch (af) { case AF_INET: m = sc->sc_mbuf; timeout_del(&sc->sc_tmo); if (m == NULL) return (0); sc->sc_mbuf = NULL; count = sc->sc_count4; set_length = sizeof(struct pflow_set_header) + sc->sc_count4 * sizeof(struct pflow_ipfix_flow4); break; case AF_INET6: m = sc->sc_mbuf6; timeout_del(&sc->sc_tmo6); if (m == NULL) return (0); sc->sc_mbuf6 = NULL; count = sc->sc_count6; set_length = sizeof(struct pflow_set_header) + sc->sc_count6 * sizeof(struct pflow_ipfix_flow6); break; default: unhandled_af(af); } if (!(ifp->if_flags & IFF_RUNNING)) { m_freem(m); return (0); } pflowstat_inc(pflow_packets); set_hdr = mtod(m, struct pflow_set_header *); set_hdr->set_length = htons(set_length); /* populate pflow_header */ M_PREPEND(m, sizeof(struct pflow_v10_header), M_DONTWAIT); if (m == NULL) { pflowstat_inc(pflow_onomem); return (ENOBUFS); } h10 = mtod(m, struct pflow_v10_header *); h10->version = htons(PFLOW_PROTO_10); h10->length = htons(PFLOW_IPFIX_HDRLEN + set_length); h10->time_sec = htonl(gettime()); /* XXX 2038 */ h10->flow_sequence = htonl(sc->sc_sequence); sc->sc_sequence += count; h10->observation_dom = htonl(PFLOW_ENGINE_TYPE); if (mq_enqueue(&sc->sc_outputqueue, m) == 0) task_add(net_tq(ifp->if_index), &sc->sc_outputtask); return (0); } int pflow_sendout_ipfix_tmpl(struct pflow_softc *sc) { struct mbuf *m; struct pflow_v10_header *h10; struct ifnet *ifp = &sc->sc_if; MUTEX_ASSERT_LOCKED(&sc->sc_mtx); timeout_del(&sc->sc_tmo_tmpl); if (!(ifp->if_flags & IFF_RUNNING)) { return (0); } m = pflow_get_mbuf(sc, 0); if (m == NULL) return (0); if (m_copyback(m, 0, sizeof(struct pflow_ipfix_tmpl), &sc->sc_tmpl_ipfix, M_NOWAIT)) { m_freem(m); return (0); } pflowstat_inc(pflow_packets); /* populate pflow_header */ M_PREPEND(m, sizeof(struct pflow_v10_header), M_DONTWAIT); if (m == NULL) { pflowstat_inc(pflow_onomem); return (ENOBUFS); } h10 = mtod(m, struct pflow_v10_header *); h10->version = htons(PFLOW_PROTO_10); h10->length = htons(PFLOW_IPFIX_HDRLEN + sizeof(struct pflow_ipfix_tmpl)); h10->time_sec = htonl(gettime()); /* XXX 2038 */ h10->flow_sequence = htonl(sc->sc_sequence); h10->observation_dom = htonl(PFLOW_ENGINE_TYPE); timeout_add_sec(&sc->sc_tmo_tmpl, PFLOW_TMPL_TIMEOUT); if (mq_enqueue(&sc->sc_outputqueue, m) == 0) task_add(net_tq(ifp->if_index), &sc->sc_outputtask); return (0); } int pflow_sendout_mbuf(struct pflow_softc *sc, struct mbuf *m) { rw_assert_anylock(&sc->sc_lock); counters_pkt(sc->sc_if.if_counters, ifc_opackets, ifc_obytes, m->m_pkthdr.len); if (sc->so == NULL) { m_freem(m); return (EINVAL); } return (sosend(sc->so, sc->send_nam, NULL, m, NULL, 0)); } int pflow_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { if (namelen != 1) return (ENOTDIR); switch (name[0]) { case NET_PFLOW_STATS: { uint64_t counters[pflow_ncounters]; struct pflowstats pflowstats; if (newp != NULL) return (EPERM); counters_read(pflow_counters, counters, pflow_ncounters, NULL); pflowstats.pflow_flows = counters[pflow_flows]; pflowstats.pflow_packets = counters[pflow_packets]; pflowstats.pflow_onomem = counters[pflow_onomem]; pflowstats.pflow_oerrors = counters[pflow_oerrors]; return (sysctl_struct(oldp, oldlenp, newp, newlen, &pflowstats, sizeof(pflowstats))); } default: return (EOPNOTSUPP); } return (0); }
9 4 1 3 12 12 1 5 1 4 10 10 1 21 22 22 12 110 5 32 15 15 9 5 45 15 18 13 1 3 4 3 9 1 3 1 7 16 2 14 18 15 1 1 17 18 9 2 10 14 14 2 6 9 13 9 2 2 9 6 1 11 15 12 1 2 13 6 13 24 19 3 1 26 12 33 2 27 1 27 27 7 27 27 27 7 30 2 104 104 51 30 12 25 10 61 1 59 37 4 27 29 26 8 23 94 94 12 12 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 /* $OpenBSD: sys_pipe.c,v 1.146 2023/05/09 14:22:17 visa Exp $ */ /* * Copyright (c) 1996 John S. Dyson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice immediately at the beginning of the file, without modification, * this list of conditions, and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Absolutely no warranty of function or purpose is made by the author * John S. Dyson. * 4. Modifications may be freely made to this file if the above conditions * are met. */ /* * This file contains a high-performance replacement for the socket-based * pipes scheme originally used in FreeBSD/4.4Lite. It does not support * all features of sockets, but does do everything that pipes normally * do. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/fcntl.h> #include <sys/file.h> #include <sys/filedesc.h> #include <sys/pool.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/signalvar.h> #include <sys/mount.h> #include <sys/syscallargs.h> #include <sys/event.h> #ifdef KTRACE #include <sys/ktrace.h> #endif #include <uvm/uvm_extern.h> #include <sys/pipe.h> struct pipe_pair { struct pipe pp_wpipe; struct pipe pp_rpipe; struct rwlock pp_lock; }; /* * interfaces to the outside world */ int pipe_read(struct file *, struct uio *, int); int pipe_write(struct file *, struct uio *, int); int pipe_close(struct file *, struct proc *); int pipe_kqfilter(struct file *fp, struct knote *kn); int pipe_ioctl(struct file *, u_long, caddr_t, struct proc *); int pipe_stat(struct file *fp, struct stat *ub, struct proc *p); static const struct fileops pipeops = { .fo_read = pipe_read, .fo_write = pipe_write, .fo_ioctl = pipe_ioctl, .fo_kqfilter = pipe_kqfilter, .fo_stat = pipe_stat, .fo_close = pipe_close }; void filt_pipedetach(struct knote *kn); int filt_piperead(struct knote *kn, long hint); int filt_pipewrite(struct knote *kn, long hint); int filt_pipeexcept(struct knote *kn, long hint); int filt_pipemodify(struct kevent *kev, struct knote *kn); int filt_pipeprocess(struct knote *kn, struct kevent *kev); const struct filterops pipe_rfiltops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_pipedetach, .f_event = filt_piperead, .f_modify = filt_pipemodify, .f_process = filt_pipeprocess, }; const struct filterops pipe_wfiltops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_pipedetach, .f_event = filt_pipewrite, .f_modify = filt_pipemodify, .f_process = filt_pipeprocess, }; const struct filterops pipe_efiltops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_pipedetach, .f_event = filt_pipeexcept, .f_modify = filt_pipemodify, .f_process = filt_pipeprocess, }; /* * Default pipe buffer size(s), this can be kind-of large now because pipe * space is pageable. The pipe code will try to maintain locality of * reference for performance reasons, so small amounts of outstanding I/O * will not wipe the cache. */ #define MINPIPESIZE (PIPE_SIZE/3) /* * Limit the number of "big" pipes */ #define LIMITBIGPIPES 32 unsigned int nbigpipe; static unsigned int amountpipekva; struct pool pipe_pair_pool; int dopipe(struct proc *, int *, int); void pipe_wakeup(struct pipe *); int pipe_create(struct pipe *); void pipe_destroy(struct pipe *); int pipe_rundown(struct pipe *); struct pipe *pipe_peer(struct pipe *); int pipe_buffer_realloc(struct pipe *, u_int); void pipe_buffer_free(struct pipe *); int pipe_iolock(struct pipe *); void pipe_iounlock(struct pipe *); int pipe_iosleep(struct pipe *, const char *); struct pipe_pair *pipe_pair_create(void); void pipe_pair_destroy(struct pipe_pair *); /* * The pipe system call for the DTYPE_PIPE type of pipes */ int sys_pipe(struct proc *p, void *v, register_t *retval) { struct sys_pipe_args /* { syscallarg(int *) fdp; } */ *uap = v; return (dopipe(p, SCARG(uap, fdp), 0)); } int sys_pipe2(struct proc *p, void *v, register_t *retval) { struct sys_pipe2_args /* { syscallarg(int *) fdp; syscallarg(int) flags; } */ *uap = v; if (SCARG(uap, flags) & ~(O_CLOEXEC | FNONBLOCK)) return (EINVAL); return (dopipe(p, SCARG(uap, fdp), SCARG(uap, flags))); } int dopipe(struct proc *p, int *ufds, int flags) { struct filedesc *fdp = p->p_fd; struct file *rf, *wf; struct pipe_pair *pp; struct pipe *rpipe, *wpipe = NULL; int fds[2], cloexec, error; cloexec = (flags & O_CLOEXEC) ? UF_EXCLOSE : 0; pp = pipe_pair_create(); if (pp == NULL) return (ENOMEM); wpipe = &pp->pp_wpipe; rpipe = &pp->pp_rpipe; fdplock(fdp); error = falloc(p, &rf, &fds[0]); if (error != 0) goto free2; rf->f_flag = FREAD | FWRITE | (flags & FNONBLOCK); rf->f_type = DTYPE_PIPE; rf->f_data = rpipe; rf->f_ops = &pipeops; error = falloc(p, &wf, &fds[1]); if (error != 0) goto free3; wf->f_flag = FREAD | FWRITE | (flags & FNONBLOCK); wf->f_type = DTYPE_PIPE; wf->f_data = wpipe; wf->f_ops = &pipeops; fdinsert(fdp, fds[0], cloexec, rf); fdinsert(fdp, fds[1], cloexec, wf); error = copyout(fds, ufds, sizeof(fds)); if (error == 0) { fdpunlock(fdp); #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrfds(p, fds, 2); #endif } else { /* fdrelease() unlocks fdp. */ fdrelease(p, fds[0]); fdplock(fdp); fdrelease(p, fds[1]); } FRELE(rf, p); FRELE(wf, p); return (error); free3: fdremove(fdp, fds[0]); closef(rf, p); rpipe = NULL; free2: fdpunlock(fdp); pipe_destroy(wpipe); pipe_destroy(rpipe); return (error); } /* * Allocate kva for pipe circular buffer, the space is pageable. * This routine will 'realloc' the size of a pipe safely, if it fails * it will retain the old buffer. * If it fails it will return ENOMEM. */ int pipe_buffer_realloc(struct pipe *cpipe, u_int size) { caddr_t buffer; /* buffer uninitialized or pipe locked */ KASSERT((cpipe->pipe_buffer.buffer == NULL) || (cpipe->pipe_state & PIPE_LOCK)); /* buffer should be empty */ KASSERT(cpipe->pipe_buffer.cnt == 0); KERNEL_LOCK(); buffer = km_alloc(size, &kv_any, &kp_pageable, &kd_waitok); KERNEL_UNLOCK(); if (buffer == NULL) return (ENOMEM); /* free old resources if we are resizing */ pipe_buffer_free(cpipe); cpipe->pipe_buffer.buffer = buffer; cpipe->pipe_buffer.size = size; cpipe->pipe_buffer.in = 0; cpipe->pipe_buffer.out = 0; atomic_add_int(&amountpipekva, cpipe->pipe_buffer.size); return (0); } /* * initialize and allocate VM and memory for pipe */ int pipe_create(struct pipe *cpipe) { int error; error = pipe_buffer_realloc(cpipe, PIPE_SIZE); if (error != 0) return (error); sigio_init(&cpipe->pipe_sigio); getnanotime(&cpipe->pipe_ctime); cpipe->pipe_atime = cpipe->pipe_ctime; cpipe->pipe_mtime = cpipe->pipe_ctime; return (0); } struct pipe * pipe_peer(struct pipe *cpipe) { struct pipe *peer; rw_assert_anylock(cpipe->pipe_lock); peer = cpipe->pipe_peer; if (peer == NULL || (peer->pipe_state & PIPE_EOF)) return (NULL); return (peer); } /* * Lock a pipe for exclusive I/O access. */ int pipe_iolock(struct pipe *cpipe) { int error; rw_assert_wrlock(cpipe->pipe_lock); while (cpipe->pipe_state & PIPE_LOCK) { cpipe->pipe_state |= PIPE_LWANT; error = rwsleep_nsec(cpipe, cpipe->pipe_lock, PRIBIO | PCATCH, "pipeiolk", INFSLP); if (error) return (error); } cpipe->pipe_state |= PIPE_LOCK; return (0); } /* * Unlock a pipe I/O lock. */ void pipe_iounlock(struct pipe *cpipe) { rw_assert_wrlock(cpipe->pipe_lock); KASSERT(cpipe->pipe_state & PIPE_LOCK); cpipe->pipe_state &= ~PIPE_LOCK; if (cpipe->pipe_state & PIPE_LWANT) { cpipe->pipe_state &= ~PIPE_LWANT; wakeup(cpipe); } } /* * Unlock the pipe I/O lock and go to sleep. Returns 0 on success and the I/O * lock is relocked. Otherwise if a signal was caught, non-zero is returned and * the I/O lock is not locked. * * Any caller must obtain a reference to the pipe by incrementing `pipe_busy' * before calling this function in order ensure that the same pipe is not * destroyed while sleeping. */ int pipe_iosleep(struct pipe *cpipe, const char *wmesg) { int error; pipe_iounlock(cpipe); error = rwsleep_nsec(cpipe, cpipe->pipe_lock, PRIBIO | PCATCH, wmesg, INFSLP); if (error) return (error); return (pipe_iolock(cpipe)); } void pipe_wakeup(struct pipe *cpipe) { rw_assert_wrlock(cpipe->pipe_lock); knote_locked(&cpipe->pipe_klist, 0); if (cpipe->pipe_state & PIPE_ASYNC) pgsigio(&cpipe->pipe_sigio, SIGIO, 0); } int pipe_read(struct file *fp, struct uio *uio, int fflags) { struct pipe *rpipe = fp->f_data; size_t nread = 0, size; int error; rw_enter_write(rpipe->pipe_lock); ++rpipe->pipe_busy; error = pipe_iolock(rpipe); if (error) { --rpipe->pipe_busy; pipe_rundown(rpipe); rw_exit_write(rpipe->pipe_lock); return (error); } while (uio->uio_resid) { /* Normal pipe buffer receive. */ if (rpipe->pipe_buffer.cnt > 0) { size = rpipe->pipe_buffer.size - rpipe->pipe_buffer.out; if (size > rpipe->pipe_buffer.cnt) size = rpipe->pipe_buffer.cnt; if (size > uio->uio_resid) size = uio->uio_resid; rw_exit_write(rpipe->pipe_lock); error = uiomove(&rpipe->pipe_buffer.buffer[rpipe->pipe_buffer.out], size, uio); rw_enter_write(rpipe->pipe_lock); if (error) { break; } rpipe->pipe_buffer.out += size; if (rpipe->pipe_buffer.out >= rpipe->pipe_buffer.size) rpipe->pipe_buffer.out = 0; rpipe->pipe_buffer.cnt -= size; /* * If there is no more to read in the pipe, reset * its pointers to the beginning. This improves * cache hit stats. */ if (rpipe->pipe_buffer.cnt == 0) { rpipe->pipe_buffer.in = 0; rpipe->pipe_buffer.out = 0; } nread += size; } else { /* * detect EOF condition * read returns 0 on EOF, no need to set error */ if (rpipe->pipe_state & PIPE_EOF) break; /* If the "write-side" has been blocked, wake it up. */ if (rpipe->pipe_state & PIPE_WANTW) { rpipe->pipe_state &= ~PIPE_WANTW; wakeup(rpipe); } /* Break if some data was read. */ if (nread > 0) break; /* Handle non-blocking mode operation. */ if (fp->f_flag & FNONBLOCK) { error = EAGAIN; break; } /* Wait for more data. */ rpipe->pipe_state |= PIPE_WANTR; error = pipe_iosleep(rpipe, "piperd"); if (error) goto unlocked_error; } } pipe_iounlock(rpipe); if (error == 0) getnanotime(&rpipe->pipe_atime); unlocked_error: --rpipe->pipe_busy; if (pipe_rundown(rpipe) == 0 && rpipe->pipe_buffer.cnt < MINPIPESIZE) { /* Handle write blocking hysteresis. */ if (rpipe->pipe_state & PIPE_WANTW) { rpipe->pipe_state &= ~PIPE_WANTW; wakeup(rpipe); } } if (rpipe->pipe_buffer.size - rpipe->pipe_buffer.cnt >= PIPE_BUF) pipe_wakeup(rpipe); rw_exit_write(rpipe->pipe_lock); return (error); } int pipe_write(struct file *fp, struct uio *uio, int fflags) { struct pipe *rpipe = fp->f_data, *wpipe; struct rwlock *lock = rpipe->pipe_lock; size_t orig_resid; int error; rw_enter_write(lock); wpipe = pipe_peer(rpipe); /* Detect loss of pipe read side, issue SIGPIPE if lost. */ if (wpipe == NULL) { rw_exit_write(lock); return (EPIPE); } ++wpipe->pipe_busy; error = pipe_iolock(wpipe); if (error) { --wpipe->pipe_busy; pipe_rundown(wpipe); rw_exit_write(lock); return (error); } /* If it is advantageous to resize the pipe buffer, do so. */ if (uio->uio_resid > PIPE_SIZE && wpipe->pipe_buffer.size <= PIPE_SIZE && wpipe->pipe_buffer.cnt == 0) { unsigned int npipe; npipe = atomic_inc_int_nv(&nbigpipe); if (npipe > LIMITBIGPIPES || pipe_buffer_realloc(wpipe, BIG_PIPE_SIZE) != 0) atomic_dec_int(&nbigpipe); } orig_resid = uio->uio_resid; while (uio->uio_resid) { size_t space; if (wpipe->pipe_state & PIPE_EOF) { error = EPIPE; break; } space = wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt; /* Writes of size <= PIPE_BUF must be atomic. */ if (space < uio->uio_resid && orig_resid <= PIPE_BUF) space = 0; if (space > 0) { size_t size; /* Transfer size */ size_t segsize; /* first segment to transfer */ /* * Transfer size is minimum of uio transfer * and free space in pipe buffer. */ if (space > uio->uio_resid) size = uio->uio_resid; else size = space; /* * First segment to transfer is minimum of * transfer size and contiguous space in * pipe buffer. If first segment to transfer * is less than the transfer size, we've got * a wraparound in the buffer. */ segsize = wpipe->pipe_buffer.size - wpipe->pipe_buffer.in; if (segsize > size) segsize = size; /* Transfer first segment */ rw_exit_write(lock); error = uiomove(&wpipe->pipe_buffer.buffer[wpipe->pipe_buffer.in], segsize, uio); rw_enter_write(lock); if (error == 0 && segsize < size) { /* * Transfer remaining part now, to * support atomic writes. Wraparound * happened. */ #ifdef DIAGNOSTIC if (wpipe->pipe_buffer.in + segsize != wpipe->pipe_buffer.size) panic("Expected pipe buffer wraparound disappeared"); #endif rw_exit_write(lock); error = uiomove(&wpipe->pipe_buffer.buffer[0], size - segsize, uio); rw_enter_write(lock); } if (error == 0) { wpipe->pipe_buffer.in += size; if (wpipe->pipe_buffer.in >= wpipe->pipe_buffer.size) { #ifdef DIAGNOSTIC if (wpipe->pipe_buffer.in != size - segsize + wpipe->pipe_buffer.size) panic("Expected wraparound bad"); #endif wpipe->pipe_buffer.in = size - segsize; } wpipe->pipe_buffer.cnt += size; #ifdef DIAGNOSTIC if (wpipe->pipe_buffer.cnt > wpipe->pipe_buffer.size) panic("Pipe buffer overflow"); #endif } if (error) break; } else { /* If the "read-side" has been blocked, wake it up. */ if (wpipe->pipe_state & PIPE_WANTR) { wpipe->pipe_state &= ~PIPE_WANTR; wakeup(wpipe); } /* Don't block on non-blocking I/O. */ if (fp->f_flag & FNONBLOCK) { error = EAGAIN; break; } /* * We have no more space and have something to offer, * wake up select/poll. */ pipe_wakeup(wpipe); wpipe->pipe_state |= PIPE_WANTW; error = pipe_iosleep(wpipe, "pipewr"); if (error) goto unlocked_error; /* * If read side wants to go away, we just issue a * signal to ourselves. */ if (wpipe->pipe_state & PIPE_EOF) { error = EPIPE; break; } } } pipe_iounlock(wpipe); unlocked_error: --wpipe->pipe_busy; if (pipe_rundown(wpipe) == 0 && wpipe->pipe_buffer.cnt > 0) { /* * If we have put any characters in the buffer, we wake up * the reader. */ if (wpipe->pipe_state & PIPE_WANTR) { wpipe->pipe_state &= ~PIPE_WANTR; wakeup(wpipe); } } /* Don't return EPIPE if I/O was successful. */ if (wpipe->pipe_buffer.cnt == 0 && uio->uio_resid == 0 && error == EPIPE) { error = 0; } if (error == 0) getnanotime(&wpipe->pipe_mtime); /* We have something to offer, wake up select/poll. */ if (wpipe->pipe_buffer.cnt) pipe_wakeup(wpipe); rw_exit_write(lock); return (error); } /* * we implement a very minimal set of ioctls for compatibility with sockets. */ int pipe_ioctl(struct file *fp, u_long cmd, caddr_t data, struct proc *p) { struct pipe *mpipe = fp->f_data; int error = 0; switch (cmd) { case FIONBIO: break; case FIOASYNC: rw_enter_write(mpipe->pipe_lock); if (*(int *)data) { mpipe->pipe_state |= PIPE_ASYNC; } else { mpipe->pipe_state &= ~PIPE_ASYNC; } rw_exit_write(mpipe->pipe_lock); break; case FIONREAD: rw_enter_read(mpipe->pipe_lock); *(int *)data = mpipe->pipe_buffer.cnt; rw_exit_read(mpipe->pipe_lock); break; case FIOSETOWN: case SIOCSPGRP: case TIOCSPGRP: error = sigio_setown(&mpipe->pipe_sigio, cmd, data); break; case FIOGETOWN: case SIOCGPGRP: case TIOCGPGRP: sigio_getown(&mpipe->pipe_sigio, cmd, data); break; default: error = ENOTTY; } return (error); } int pipe_stat(struct file *fp, struct stat *ub, struct proc *p) { struct pipe *pipe = fp->f_data; memset(ub, 0, sizeof(*ub)); rw_enter_read(pipe->pipe_lock); ub->st_mode = S_IFIFO; ub->st_blksize = pipe->pipe_buffer.size; ub->st_size = pipe->pipe_buffer.cnt; ub->st_blocks = (ub->st_size + ub->st_blksize - 1) / ub->st_blksize; ub->st_atim.tv_sec = pipe->pipe_atime.tv_sec; ub->st_atim.tv_nsec = pipe->pipe_atime.tv_nsec; ub->st_mtim.tv_sec = pipe->pipe_mtime.tv_sec; ub->st_mtim.tv_nsec = pipe->pipe_mtime.tv_nsec; ub->st_ctim.tv_sec = pipe->pipe_ctime.tv_sec; ub->st_ctim.tv_nsec = pipe->pipe_ctime.tv_nsec; ub->st_uid = fp->f_cred->cr_uid; ub->st_gid = fp->f_cred->cr_gid; rw_exit_read(pipe->pipe_lock); /* * Left as 0: st_dev, st_ino, st_nlink, st_rdev, st_flags, st_gen. * XXX (st_dev, st_ino) should be unique. */ return (0); } int pipe_close(struct file *fp, struct proc *p) { struct pipe *cpipe = fp->f_data; fp->f_ops = NULL; fp->f_data = NULL; pipe_destroy(cpipe); return (0); } /* * Free kva for pipe circular buffer. * No pipe lock check as only called from pipe_buffer_realloc() and pipeclose() */ void pipe_buffer_free(struct pipe *cpipe) { u_int size; if (cpipe->pipe_buffer.buffer == NULL) return; size = cpipe->pipe_buffer.size; KERNEL_LOCK(); km_free(cpipe->pipe_buffer.buffer, size, &kv_any, &kp_pageable); KERNEL_UNLOCK(); cpipe->pipe_buffer.buffer = NULL; atomic_sub_int(&amountpipekva, size); if (size > PIPE_SIZE) atomic_dec_int(&nbigpipe); } /* * shutdown the pipe, and free resources. */ void pipe_destroy(struct pipe *cpipe) { struct pipe *ppipe; if (cpipe == NULL) return; rw_enter_write(cpipe->pipe_lock); pipe_wakeup(cpipe); sigio_free(&cpipe->pipe_sigio); /* * If the other side is blocked, wake it up saying that * we want to close it down. */ cpipe->pipe_state |= PIPE_EOF; while (cpipe->pipe_busy) { wakeup(cpipe); cpipe->pipe_state |= PIPE_WANTD; rwsleep_nsec(cpipe, cpipe->pipe_lock, PRIBIO, "pipecl", INFSLP); } /* Disconnect from peer. */ if ((ppipe = cpipe->pipe_peer) != NULL) { pipe_wakeup(ppipe); ppipe->pipe_state |= PIPE_EOF; wakeup(ppipe); ppipe->pipe_peer = NULL; } pipe_buffer_free(cpipe); rw_exit_write(cpipe->pipe_lock); if (ppipe == NULL) pipe_pair_destroy(cpipe->pipe_pair); } /* * Returns non-zero if a rundown is currently ongoing. */ int pipe_rundown(struct pipe *cpipe) { rw_assert_wrlock(cpipe->pipe_lock); if (cpipe->pipe_busy > 0 || (cpipe->pipe_state & PIPE_WANTD) == 0) return (0); /* Only wakeup pipe_destroy() once the pipe is no longer busy. */ cpipe->pipe_state &= ~(PIPE_WANTD | PIPE_WANTR | PIPE_WANTW); wakeup(cpipe); return (1); } int pipe_kqfilter(struct file *fp, struct knote *kn) { struct pipe *rpipe = kn->kn_fp->f_data, *wpipe; struct rwlock *lock = rpipe->pipe_lock; int error = 0; rw_enter_write(lock); wpipe = pipe_peer(rpipe); switch (kn->kn_filter) { case EVFILT_READ: kn->kn_fop = &pipe_rfiltops; kn->kn_hook = rpipe; klist_insert_locked(&rpipe->pipe_klist, kn); break; case EVFILT_WRITE: if (wpipe == NULL) { /* * The other end of the pipe has been closed. * Since the filter now always indicates a pending * event, attach the knote to the current side * to proceed with the registration. */ wpipe = rpipe; } kn->kn_fop = &pipe_wfiltops; kn->kn_hook = wpipe; klist_insert_locked(&wpipe->pipe_klist, kn); break; case EVFILT_EXCEPT: if (kn->kn_flags & __EV_SELECT) { /* Prevent triggering exceptfds. */ error = EPERM; break; } if ((kn->kn_flags & __EV_POLL) == 0) { /* Disallow usage through kevent(2). */ error = EINVAL; break; } kn->kn_fop = &pipe_efiltops; kn->kn_hook = rpipe; klist_insert_locked(&rpipe->pipe_klist, kn); break; default: error = EINVAL; } rw_exit_write(lock); return (error); } void filt_pipedetach(struct knote *kn) { struct pipe *cpipe = kn->kn_hook; klist_remove(&cpipe->pipe_klist, kn); } int filt_piperead(struct knote *kn, long hint) { struct pipe *rpipe = kn->kn_fp->f_data, *wpipe; rw_assert_wrlock(rpipe->pipe_lock); wpipe = pipe_peer(rpipe); kn->kn_data = rpipe->pipe_buffer.cnt; if ((rpipe->pipe_state & PIPE_EOF) || wpipe == NULL) { kn->kn_flags |= EV_EOF; if (kn->kn_flags & __EV_POLL) kn->kn_flags |= __EV_HUP; return (1); } return (kn->kn_data > 0); } int filt_pipewrite(struct knote *kn, long hint) { struct pipe *rpipe = kn->kn_fp->f_data, *wpipe; rw_assert_wrlock(rpipe->pipe_lock); wpipe = pipe_peer(rpipe); if (wpipe == NULL) { kn->kn_data = 0; kn->kn_flags |= EV_EOF; if (kn->kn_flags & __EV_POLL) kn->kn_flags |= __EV_HUP; return (1); } kn->kn_data = wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt; return (kn->kn_data >= PIPE_BUF); } int filt_pipeexcept(struct knote *kn, long hint) { struct pipe *rpipe = kn->kn_fp->f_data, *wpipe; int active = 0; rw_assert_wrlock(rpipe->pipe_lock); wpipe = pipe_peer(rpipe); if (kn->kn_flags & __EV_POLL) { if ((rpipe->pipe_state & PIPE_EOF) || wpipe == NULL) { kn->kn_flags |= __EV_HUP; active = 1; } } return (active); } int filt_pipemodify(struct kevent *kev, struct knote *kn) { struct pipe *rpipe = kn->kn_fp->f_data; int active; rw_enter_write(rpipe->pipe_lock); active = knote_modify(kev, kn); rw_exit_write(rpipe->pipe_lock); return (active); } int filt_pipeprocess(struct knote *kn, struct kevent *kev) { struct pipe *rpipe = kn->kn_fp->f_data; int active; rw_enter_write(rpipe->pipe_lock); active = knote_process(kn, kev); rw_exit_write(rpipe->pipe_lock); return (active); } void pipe_init(void) { pool_init(&pipe_pair_pool, sizeof(struct pipe_pair), 0, IPL_MPFLOOR, PR_WAITOK, "pipepl", NULL); } struct pipe_pair * pipe_pair_create(void) { struct pipe_pair *pp; pp = pool_get(&pipe_pair_pool, PR_WAITOK | PR_ZERO); pp->pp_wpipe.pipe_pair = pp; pp->pp_rpipe.pipe_pair = pp; pp->pp_wpipe.pipe_peer = &pp->pp_rpipe; pp->pp_rpipe.pipe_peer = &pp->pp_wpipe; /* * One lock is used per pipe pair in order to obtain exclusive access to * the pipe pair. */ rw_init(&pp->pp_lock, "pipelk"); pp->pp_wpipe.pipe_lock = &pp->pp_lock; pp->pp_rpipe.pipe_lock = &pp->pp_lock; klist_init_rwlock(&pp->pp_wpipe.pipe_klist, &pp->pp_lock); klist_init_rwlock(&pp->pp_rpipe.pipe_klist, &pp->pp_lock); if (pipe_create(&pp->pp_wpipe) || pipe_create(&pp->pp_rpipe)) goto err; return (pp); err: pipe_destroy(&pp->pp_wpipe); pipe_destroy(&pp->pp_rpipe); return (NULL); } void pipe_pair_destroy(struct pipe_pair *pp) { klist_free(&pp->pp_wpipe.pipe_klist); klist_free(&pp->pp_rpipe.pipe_klist); pool_put(&pipe_pair_pool, pp); }
735 24 735 673 522 491 44 2 6 18 46 20 490 13 480 479 489 12 489 490 451 5 160 160 4 5 26 26 8 477 143 23 141 158 4 9 14 105 112 11 32 450 1 479 350 4 8 81 3 3 64 69 98 2 4 33 60 2 45 33 323 72 372 8 490 489 75 75 75 13 1 68 67 65 3 3 6 3 66 68 51 18 63 4 5 3 6 4 5 60 43 8 12 15 49 43 17 60 60 19 19 14 14 2 14 14 10 1 7 2 7 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 /* $OpenBSD: ufs_lookup.c,v 1.61 2024/02/03 18:51:58 beck Exp $ */ /* $NetBSD: ufs_lookup.c,v 1.7 1996/02/09 22:36:06 christos Exp $ */ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ufs_lookup.c 8.9 (Berkeley) 8/11/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/namei.h> #include <sys/buf.h> #include <sys/stat.h> #include <sys/mount.h> #include <sys/proc.h> #include <sys/vnode.h> #include <ufs/ufs/quota.h> #include <ufs/ufs/inode.h> #include <ufs/ufs/dir.h> #ifdef UFS_DIRHASH #include <ufs/ufs/dirhash.h> #endif #include <ufs/ufs/ufsmount.h> #include <ufs/ufs/ufs_extern.h> extern struct nchstats nchstats; #ifdef DIAGNOSTIC int dirchk = 1; #else int dirchk = 0; #endif /* * Convert a component of a pathname into a pointer to a locked inode. * This is a very central and rather complicated routine. * If the file system is not maintained in a strict tree hierarchy, * this can result in a deadlock situation (see comments in code below). * * The cnp->cn_nameiop argument is LOOKUP, CREATE, RENAME, or DELETE depending * on whether the name is to be looked up, created, renamed, or deleted. * When CREATE, RENAME, or DELETE is specified, information usable in * creating, renaming, or deleting a directory entry may be calculated. * If flag has LOCKPARENT or'ed into it and the target of the pathname * exists, lookup returns both the target and its parent directory locked. * When creating or renaming and LOCKPARENT is specified, the target may * not be ".". When deleting and LOCKPARENT is specified, the target may * be "."., but the caller must check to ensure it does an vrele and vput * instead of two vputs. * * Overall outline of ufs_lookup: * * check accessibility of directory * look for name in cache, if found, then if at end of path * and deleting or creating, drop it, else return name * search for name in directory, to found or notfound * notfound: * if creating, return locked directory, leaving info on available slots * else return error * found: * if at end of path and deleting, return information to allow delete * if at end of path and rewriting (RENAME and LOCKPARENT), lock target * inode and return info to allow rewrite * if not at end, add name to cache; if at end and neither creating * nor deleting, add name to cache */ int ufs_lookup(void *v) { struct vop_lookup_args *ap = v; struct vnode *vdp; /* vnode for directory being searched */ struct inode *dp; /* inode for directory being searched */ struct buf *bp; /* a buffer of directory entries */ struct direct *ep; /* the current directory entry */ int entryoffsetinblock; /* offset of ep in bp's buffer */ enum {NONE, COMPACT, FOUND} slotstatus; doff_t slotoffset; /* offset of area with free space */ int slotsize; /* size of area at slotoffset */ int slotfreespace; /* amount of space free in slot */ int slotneeded; /* size of the entry we're seeking */ int numdirpasses; /* strategy for directory search */ doff_t endsearch; /* offset to end directory search */ doff_t prevoff; /* prev entry dp->i_offset */ struct vnode *pdp; /* saved dp during symlink work */ struct vnode *tdp; /* returned by VFS_VGET */ doff_t enduseful; /* pointer past last used dir slot */ u_long bmask; /* block offset mask */ int lockparent; /* 1 => lockparent flag is set */ int wantparent; /* 1 => wantparent or lockparent flag */ int namlen, error; struct vnode **vpp = ap->a_vpp; struct componentname *cnp = ap->a_cnp; struct ucred *cred = cnp->cn_cred; int flags; int nameiop = cnp->cn_nameiop; cnp->cn_flags &= ~PDIRUNLOCK; flags = cnp->cn_flags; bp = NULL; slotoffset = -1; *vpp = NULL; vdp = ap->a_dvp; dp = VTOI(vdp); lockparent = flags & LOCKPARENT; wantparent = flags & (LOCKPARENT|WANTPARENT); /* * Check accessibility of directory. */ if ((DIP(dp, mode) & IFMT) != IFDIR) return (ENOTDIR); if ((error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc)) != 0) return (error); if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) && (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) return (EROFS); /* * We now have a segment name to search for, and a directory to search. * * Before tediously performing a linear scan of the directory, * check the name cache to see if the directory/name pair * we are looking for is known already. */ if ((error = cache_lookup(vdp, vpp, cnp)) >= 0) return (error); /* * Suppress search for slots unless creating * file and at end of pathname, in which case * we watch for a place to put the new file in * case it doesn't already exist. */ slotstatus = FOUND; slotfreespace = slotsize = slotneeded = 0; if ((nameiop == CREATE || nameiop == RENAME) && (flags & ISLASTCN)) { slotstatus = NONE; slotneeded = (sizeof(struct direct) - MAXNAMLEN + cnp->cn_namelen + 3) &~ 3; } /* * If there is cached information on a previous search of * this directory, pick up where we last left off. * We cache only lookups as these are the most common * and have the greatest payoff. Caching CREATE has little * benefit as it usually must search the entire directory * to determine that the entry does not exist. Caching the * location of the last DELETE or RENAME has not reduced * profiling time and hence has been removed in the interest * of simplicity. */ bmask = VFSTOUFS(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1; #ifdef UFS_DIRHASH /* * Use dirhash for fast operations on large directories. The logic * to determine whether to hash the directory is contained within * ufsdirhash_build(); a zero return means that it decided to hash * this directory and it successfully built up the hash table. */ if (ufsdirhash_build(dp) == 0) { /* Look for a free slot if needed. */ enduseful = DIP(dp, size); if (slotstatus != FOUND) { slotoffset = ufsdirhash_findfree(dp, slotneeded, &slotsize); if (slotoffset >= 0) { slotstatus = COMPACT; enduseful = ufsdirhash_enduseful(dp); if (enduseful < 0) enduseful = DIP(dp, size); } } /* Look up the component. */ numdirpasses = 1; entryoffsetinblock = 0; /* silence compiler warning */ switch (ufsdirhash_lookup(dp, cnp->cn_nameptr, cnp->cn_namelen, &dp->i_offset, &bp, nameiop == DELETE ? &prevoff : NULL)) { case 0: ep = (struct direct *)((char *)bp->b_data + (dp->i_offset & bmask)); goto foundentry; case ENOENT: #define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */ dp->i_offset = roundup2(DIP(dp, size), DIRBLKSIZ); goto notfound; default: /* Something failed; just do a linear search. */ break; } } #endif /* UFS_DIRHASH */ if (nameiop != LOOKUP || dp->i_diroff == 0 || dp->i_diroff >= DIP(dp, size)) { entryoffsetinblock = 0; dp->i_offset = 0; numdirpasses = 1; } else { dp->i_offset = dp->i_diroff; if ((entryoffsetinblock = dp->i_offset & bmask) && (error = UFS_BUFATOFF(dp, (off_t)dp->i_offset, NULL, &bp))) return (error); numdirpasses = 2; nchstats.ncs_2passes++; } prevoff = dp->i_offset; endsearch = roundup(DIP(dp, size), DIRBLKSIZ); enduseful = 0; searchloop: while (dp->i_offset < endsearch) { /* * If necessary, get the next directory block. */ if ((dp->i_offset & bmask) == 0) { if (bp != NULL) brelse(bp); error = UFS_BUFATOFF(dp, (off_t)dp->i_offset, NULL, &bp); if (error) return (error); entryoffsetinblock = 0; } /* * If still looking for a slot, and at a DIRBLKSIZE * boundary, have to start looking for free space again. */ if (slotstatus == NONE && (entryoffsetinblock & (DIRBLKSIZ - 1)) == 0) { slotoffset = -1; slotfreespace = 0; } /* * Get pointer to next entry. * Full validation checks are slow, so we only check * enough to insure forward progress through the * directory. Complete checks can be run by patching * "dirchk" to be true. */ ep = (struct direct *)((char *)bp->b_data + entryoffsetinblock); if (ep->d_reclen == 0 || (dirchk && ufs_dirbadentry(vdp, ep, entryoffsetinblock))) { int i; ufs_dirbad(dp, dp->i_offset, "mangled entry"); i = DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)); dp->i_offset += i; entryoffsetinblock += i; continue; } /* * If an appropriate sized slot has not yet been found, * check to see if one is available. Also accumulate space * in the current block so that we can determine if * compaction is viable. */ if (slotstatus != FOUND) { int size = ep->d_reclen; if (ep->d_ino != 0) size -= DIRSIZ(ep); if (size > 0) { if (size >= slotneeded) { slotstatus = FOUND; slotoffset = dp->i_offset; slotsize = ep->d_reclen; } else if (slotstatus == NONE) { slotfreespace += size; if (slotoffset == -1) slotoffset = dp->i_offset; if (slotfreespace >= slotneeded) { slotstatus = COMPACT; slotsize = dp->i_offset + ep->d_reclen - slotoffset; } } } } /* * Check for a name match. */ if (ep->d_ino) { namlen = ep->d_namlen; if (namlen == cnp->cn_namelen && !memcmp(cnp->cn_nameptr, ep->d_name, namlen)) { #ifdef UFS_DIRHASH foundentry: #endif /* * Save directory entry's inode number and * reclen in ndp->ni_ufs area, and release * directory buffer. */ dp->i_ino = ep->d_ino; dp->i_reclen = ep->d_reclen; goto found; } } prevoff = dp->i_offset; dp->i_offset += ep->d_reclen; entryoffsetinblock += ep->d_reclen; if (ep->d_ino) enduseful = dp->i_offset; } #ifdef UFS_DIRHASH notfound: #endif /* * If we started in the middle of the directory and failed * to find our target, we must check the beginning as well. */ if (numdirpasses == 2) { numdirpasses--; dp->i_offset = 0; endsearch = dp->i_diroff; goto searchloop; } if (bp != NULL) brelse(bp); /* * If creating, and at end of pathname and current * directory has not been removed, then can consider * allowing file to be created. */ if ((nameiop == CREATE || nameiop == RENAME) && (flags & ISLASTCN) && dp->i_effnlink != 0) { /* * Access for write is interpreted as allowing * creation of files in the directory. */ error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_proc); if (error) return (error); /* * Return an indication of where the new directory * entry should be put. If we didn't find a slot, * then set dp->i_count to 0 indicating * that the new slot belongs at the end of the * directory. If we found a slot, then the new entry * can be put in the range from dp->i_offset to * dp->i_offset + dp->i_count. */ if (slotstatus == NONE) { dp->i_offset = roundup(DIP(dp, size), DIRBLKSIZ); dp->i_count = 0; enduseful = dp->i_offset; } else if (nameiop == DELETE) { dp->i_offset = slotoffset; if ((dp->i_offset & (DIRBLKSIZ - 1)) == 0) dp->i_count = 0; else dp->i_count = dp->i_offset - prevoff; } else { dp->i_offset = slotoffset; dp->i_count = slotsize; if (enduseful < slotoffset + slotsize) enduseful = slotoffset + slotsize; } dp->i_endoff = roundup(enduseful, DIRBLKSIZ); /* * We return with the directory locked, so that * the parameters we set up above will still be * valid if we actually decide to do a direnter(). * We return ni_vp == NULL to indicate that the entry * does not currently exist; we leave a pointer to * the (locked) directory inode in ndp->ni_dvp. * The pathname buffer is saved so that the name * can be obtained later. * * NB - if the directory is unlocked, then this * information cannot be used. */ cnp->cn_flags |= SAVENAME; if (!lockparent) { VOP_UNLOCK(vdp); cnp->cn_flags |= PDIRUNLOCK; } return (EJUSTRETURN); } /* * Insert name into cache (as non-existent) if appropriate. */ if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) cache_enter(vdp, *vpp, cnp); return (ENOENT); found: if (numdirpasses == 2) nchstats.ncs_pass2++; /* * Check that directory length properly reflects presence * of this entry. */ if (dp->i_offset + DIRSIZ(ep) > DIP(dp, size)) { ufs_dirbad(dp, dp->i_offset, "i_ffs_size too small"); DIP_ASSIGN(dp, size, dp->i_offset + DIRSIZ(ep)); dp->i_flag |= IN_CHANGE | IN_UPDATE; } brelse(bp); /* * Found component in pathname. * If the final component of path name, save information * in the cache as to where the entry was found. */ if ((flags & ISLASTCN) && nameiop == LOOKUP) dp->i_diroff = dp->i_offset &~ (DIRBLKSIZ - 1); /* * If deleting, and at end of pathname, return * parameters which can be used to remove file. * If the wantparent flag isn't set, we return only * the directory (in ndp->ni_dvp), otherwise we go * on and lock the inode, being careful with ".". */ if (nameiop == DELETE && (flags & ISLASTCN)) { /* * Write access to directory required to delete files. */ error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_proc); if (error) return (error); /* * Return pointer to current entry in dp->i_offset, * and distance past previous entry (if there * is a previous entry in this block) in dp->i_count. * Save directory inode pointer in ndp->ni_dvp for dirremove(). */ if ((dp->i_offset & (DIRBLKSIZ - 1)) == 0) dp->i_count = 0; else dp->i_count = dp->i_offset - prevoff; if (dp->i_number == dp->i_ino) { vref(vdp); *vpp = vdp; return (0); } error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp); if (error) return (error); /* * If directory is "sticky", then user must own * the directory, or the file in it, else she * may not delete it (unless she's root). This * implements append-only directories. */ if ((DIP(dp, mode) & ISVTX) && cred->cr_uid != 0 && cred->cr_uid != DIP(dp, uid) && !vnoperm(vdp) && DIP(VTOI(tdp), uid) != cred->cr_uid) { vput(tdp); return (EPERM); } *vpp = tdp; if (!lockparent) { VOP_UNLOCK(vdp); cnp->cn_flags |= PDIRUNLOCK; } return (0); } /* * If rewriting (RENAME), return the inode and the * information required to rewrite the present directory * Must get inode of directory entry to verify it's a * regular file, or empty directory. */ if (nameiop == RENAME && wantparent && (flags & ISLASTCN)) { error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_proc); if (error) return (error); /* * Careful about locking second inode. * This can only occur if the target is ".". */ if (dp->i_number == dp->i_ino) return (EISDIR); error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp); if (error) return (error); *vpp = tdp; cnp->cn_flags |= SAVENAME; if (!lockparent) { VOP_UNLOCK(vdp); cnp->cn_flags |= PDIRUNLOCK; } return (0); } /* * Step through the translation in the name. We do not `vput' the * directory because we may need it again if a symbolic link * is relative to the current directory. Instead we save it * unlocked as "pdp". We must get the target inode before unlocking * the directory to insure that the inode will not be removed * before we get it. We prevent deadlock by always fetching * inodes from the root, moving down the directory tree. Thus * when following backward pointers ".." we must unlock the * parent directory before getting the requested directory. * There is a potential race condition here if both the current * and parent directories are removed before the VFS_VGET for the * inode associated with ".." returns. We hope that this occurs * infrequently since we cannot avoid this race condition without * implementing a sophisticated deadlock detection algorithm. * Note also that this simple deadlock detection scheme will not * work if the file system has any hard links other than ".." * that point backwards in the directory structure. */ pdp = vdp; if (flags & ISDOTDOT) { VOP_UNLOCK(pdp); /* race to get the inode */ cnp->cn_flags |= PDIRUNLOCK; error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp); if (error) { if (vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY) == 0) cnp->cn_flags &= ~PDIRUNLOCK; return (error); } if (lockparent && (flags & ISLASTCN)) { if ((error = vn_lock(pdp, LK_EXCLUSIVE))) { vput(tdp); return (error); } cnp->cn_flags &= ~PDIRUNLOCK; } *vpp = tdp; } else if (dp->i_number == dp->i_ino) { vref(vdp); /* we want ourself, ie "." */ *vpp = vdp; } else { error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp); if (error) return (error); if (!lockparent || !(flags & ISLASTCN)) { VOP_UNLOCK(pdp); cnp->cn_flags |= PDIRUNLOCK; } *vpp = tdp; } /* * Insert name into cache if appropriate. */ if (cnp->cn_flags & MAKEENTRY) cache_enter(vdp, *vpp, cnp); return (0); } void ufs_dirbad(struct inode *ip, doff_t offset, char *how) { struct mount *mp; mp = ITOV(ip)->v_mount; (void)printf("%s: bad dir ino %u at offset %d: %s\n", mp->mnt_stat.f_mntonname, ip->i_number, offset, how); if ((mp->mnt_stat.f_flags & MNT_RDONLY) == 0) panic("bad dir"); } /* * Do consistency checking on a directory entry: * record length must be multiple of 4 * entry must fit in rest of its DIRBLKSIZ block * record must be large enough to contain entry * name is not longer than MAXNAMLEN * name must be as long as advertised, and null terminated */ int ufs_dirbadentry(struct vnode *vdp, struct direct *ep, int entryoffsetinblock) { struct inode *dp; int i; int namlen; dp = VTOI(vdp); namlen = ep->d_namlen; if ((ep->d_reclen & 0x3) != 0 || ep->d_reclen > DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)) || ep->d_reclen < DIRSIZ(ep) || namlen > MAXNAMLEN) { /*return (1); */ printf("First bad\n"); goto bad; } if (ep->d_ino == 0) return (0); for (i = 0; i < namlen; i++) if (ep->d_name[i] == '\0') { /*return (1); */ printf("Second bad\n"); goto bad; } if (ep->d_name[i]) goto bad; return (0); bad: return (1); } /* * Construct a new directory entry after a call to namei, using the * parameters that it left in the componentname argument cnp. The * argument ip is the inode to which the new directory entry will refer. */ void ufs_makedirentry(struct inode *ip, struct componentname *cnp, struct direct *newdirp) { #ifdef DIAGNOSTIC if ((cnp->cn_flags & SAVENAME) == 0) panic("ufs_makedirentry: missing name"); #endif newdirp->d_ino = ip->i_number; newdirp->d_namlen = cnp->cn_namelen; memset(newdirp->d_name + (cnp->cn_namelen & ~(DIR_ROUNDUP-1)), 0, DIR_ROUNDUP); memcpy(newdirp->d_name, cnp->cn_nameptr, cnp->cn_namelen); newdirp->d_type = IFTODT(DIP(ip, mode)); } /* * Write a directory entry after a call to namei, using the parameters * that it left in nameidata. The argument dirp is the new directory * entry contents. Dvp is a pointer to the directory to be written, * which was left locked by namei. Remaining parameters (dp->i_offset, * dp->i_count) indicate how the space for the new entry is to be obtained. * Non-null bp indicates that a directory is being created (for the * soft dependency code). */ int ufs_direnter(struct vnode *dvp, struct vnode *tvp, struct direct *dirp, struct componentname *cnp, struct buf *newdirbp) { struct ucred *cr; struct proc *p; int newentrysize; struct inode *dp; struct buf *bp; u_int dsize; struct direct *ep, *nep; int error, ret, blkoff, loc, spacefree, flags; char *dirbuf; error = 0; cr = cnp->cn_cred; p = cnp->cn_proc; dp = VTOI(dvp); newentrysize = DIRSIZ(dirp); if (dp->i_count == 0) { /* * If dp->i_count is 0, then namei could find no * space in the directory. Here, dp->i_offset will * be on a directory block boundary and we will write the * new entry into a fresh block. */ if (dp->i_offset & (DIRBLKSIZ - 1)) panic("ufs_direnter: newblk"); flags = B_CLRBUF; flags |= B_SYNC; if ((error = UFS_BUF_ALLOC(dp, (off_t)dp->i_offset, DIRBLKSIZ, cr, flags, &bp)) != 0) { return (error); } DIP_ASSIGN(dp, size, dp->i_offset + DIRBLKSIZ); dp->i_flag |= IN_CHANGE | IN_UPDATE; uvm_vnp_setsize(dvp, DIP(dp, size)); dirp->d_reclen = DIRBLKSIZ; blkoff = dp->i_offset & (VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_iosize - 1); memcpy(bp->b_data + blkoff, dirp, newentrysize); #ifdef UFS_DIRHASH if (dp->i_dirhash != NULL) { ufsdirhash_newblk(dp, dp->i_offset); ufsdirhash_add(dp, dirp, dp->i_offset); ufsdirhash_checkblock(dp, (char *)bp->b_data + blkoff, dp->i_offset); } #endif error = VOP_BWRITE(bp); ret = UFS_UPDATE(dp, 1); if (error == 0) return (ret); return (error); } /* * If dp->i_count is non-zero, then namei found space for the new * entry in the range dp->i_offset to dp->i_offset + dp->i_count * in the directory. To use this space, we may have to compact * the entries located there, by copying them together towards the * beginning of the block, leaving the free space in one usable * chunk at the end. */ /* * Increase size of directory if entry eats into new space. * This should never push the size past a new multiple of * DIRBLKSIZE. * * N.B. - THIS IS AN ARTIFACT OF 4.2 AND SHOULD NEVER HAPPEN. */ if (dp->i_offset + dp->i_count > DIP(dp, size)) DIP_ASSIGN(dp, size, dp->i_offset + dp->i_count); /* * Get the block containing the space for the new directory entry. */ if ((error = UFS_BUFATOFF(dp, (off_t)dp->i_offset, &dirbuf, &bp)) != 0) { return (error); } /* * Find space for the new entry. In the simple case, the entry at * offset base will have the space. If it does not, then namei * arranged that compacting the region dp->i_offset to * dp->i_offset + dp->i_count would yield the space. */ ep = (struct direct *)dirbuf; dsize = ep->d_ino ? DIRSIZ(ep) : 0; spacefree = ep->d_reclen - dsize; for (loc = ep->d_reclen; loc < dp->i_count; ) { nep = (struct direct *)(dirbuf + loc); /* Trim the existing slot (NB: dsize may be zero). */ ep->d_reclen = dsize; ep = (struct direct *)((char *)ep + dsize); /* Read nep->d_reclen now as the memmove() may clobber it. */ loc += nep->d_reclen; if (nep->d_ino == 0) { /* * A mid-block unused entry. Such entries are * never created by the kernel, but fsck_ffs * can create them (and it doesn't fix them). * * Add up the free space, and initialise the * relocated entry since we don't memmove it. */ spacefree += nep->d_reclen; ep->d_ino = 0; dsize = 0; continue; } dsize = DIRSIZ(nep); spacefree += nep->d_reclen - dsize; #ifdef UFS_DIRHASH if (dp->i_dirhash != NULL) ufsdirhash_move(dp, nep, dp->i_offset + ((char *)nep - dirbuf), dp->i_offset + ((char *)ep - dirbuf)); #endif memmove(ep, nep, dsize); } /* * Here, `ep' points to a directory entry containing `dsize' in-use * bytes followed by `spacefree' unused bytes. If ep->d_ino == 0, * then the entry is completely unused (dsize == 0). The value * of ep->d_reclen is always indeterminate. * * Update the pointer fields in the previous entry (if any), * copy in the new entry, and write out the block. */ if (ep->d_ino == 0) { if (spacefree + dsize < newentrysize) panic("ufs_direnter: compact1"); dirp->d_reclen = spacefree + dsize; } else { if (spacefree < newentrysize) panic("ufs_direnter: compact2"); dirp->d_reclen = spacefree; ep->d_reclen = dsize; ep = (struct direct *)((char *)ep + dsize); } #ifdef UFS_DIRHASH if (dp->i_dirhash != NULL && (ep->d_ino == 0 || dirp->d_reclen == spacefree)) ufsdirhash_add(dp, dirp, dp->i_offset + ((char *)ep - dirbuf)); #endif memcpy(ep, dirp, newentrysize); #ifdef UFS_DIRHASH if (dp->i_dirhash != NULL) ufsdirhash_checkblock(dp, dirbuf - (dp->i_offset & (DIRBLKSIZ - 1)), dp->i_offset & ~(DIRBLKSIZ - 1)); #endif error = VOP_BWRITE(bp); dp->i_flag |= IN_CHANGE | IN_UPDATE; /* * If all went well, and the directory can be shortened, proceed * with the truncation. Note that we have to unlock the inode for * the entry that we just entered, as the truncation may need to * lock other inodes which can lead to deadlock if we also hold a * lock on the newly entered node. */ if (error == 0 && dp->i_endoff && dp->i_endoff < DIP(dp, size)) { if (tvp != NULL) VOP_UNLOCK(tvp); error = UFS_TRUNCATE(dp, (off_t)dp->i_endoff, IO_SYNC, cr); #ifdef UFS_DIRHASH if (error == 0 && dp->i_dirhash != NULL) ufsdirhash_dirtrunc(dp, dp->i_endoff); #endif if (tvp != NULL) vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY); } return (error); } /* * Remove a directory entry after a call to namei, using * the parameters which it left in nameidata. The entry * dp->i_offset contains the offset into the directory of the * entry to be eliminated. The dp->i_count field contains the * size of the previous record in the directory. If this * is 0, the first entry is being deleted, so we need only * zero the inode number to mark the entry as free. If the * entry is not the first in the directory, we must reclaim * the space of the now empty record by adding the record size * to the size of the previous entry. */ int ufs_dirremove(struct vnode *dvp, struct inode *ip, int flags, int isrmdir) { struct inode *dp; struct direct *ep; struct buf *bp; int error; dp = VTOI(dvp); if ((error = UFS_BUFATOFF(dp, (off_t)(dp->i_offset - dp->i_count), (char **)&ep, &bp)) != 0) return (error); #ifdef UFS_DIRHASH /* * Remove the dirhash entry. This is complicated by the fact * that `ep' is the previous entry when dp->i_count != 0. */ if (dp->i_dirhash != NULL) ufsdirhash_remove(dp, (dp->i_count == 0) ? ep : (struct direct *)((char *)ep + ep->d_reclen), dp->i_offset); #endif if (dp->i_count == 0) { /* * First entry in block: set d_ino to zero. */ ep->d_ino = 0; } else { /* * Collapse new free space into previous entry. */ ep->d_reclen += dp->i_reclen; } #ifdef UFS_DIRHASH if (dp->i_dirhash != NULL) ufsdirhash_checkblock(dp, (char *)ep - ((dp->i_offset - dp->i_count) & (DIRBLKSIZ - 1)), dp->i_offset & ~(DIRBLKSIZ - 1)); #endif if (ip) { ip->i_effnlink--; DIP_ADD(ip, nlink, -1); ip->i_flag |= IN_CHANGE; } if (DOINGASYNC(dvp) && dp->i_count != 0) { bdwrite(bp); error = 0; } else error = bwrite(bp); dp->i_flag |= IN_CHANGE | IN_UPDATE; return (error); } /* * Rewrite an existing directory entry to point at the inode * supplied. The parameters describing the directory entry are * set up by a call to namei. */ int ufs_dirrewrite(struct inode *dp, struct inode *oip, ufsino_t newinum, int newtype, int isrmdir) { struct buf *bp; struct direct *ep; struct vnode *vdp = ITOV(dp); int error; error = UFS_BUFATOFF(dp, (off_t)dp->i_offset, (char **)&ep, &bp); if (error) return (error); ep->d_ino = newinum; ep->d_type = newtype; oip->i_effnlink--; DIP_ADD(oip, nlink, -1); oip->i_flag |= IN_CHANGE; if (DOINGASYNC(vdp)) { bdwrite(bp); error = 0; } else { error = VOP_BWRITE(bp); } dp->i_flag |= IN_CHANGE | IN_UPDATE; return (error); } /* * Check if a directory is empty or not. * Inode supplied must be locked. * * Using a struct dirtemplate here is not precisely * what we want, but better than using a struct direct. * * NB: does not handle corrupted directories. */ int ufs_dirempty(struct inode *ip, ufsino_t parentino, struct ucred *cred) { off_t off, m; struct dirtemplate dbuf; struct direct *dp = (struct direct *)&dbuf; int error, namlen; size_t count; #define MINDIRSIZ (sizeof (struct dirtemplate) / 2) m = DIP(ip, size); for (off = 0; off < m; off += dp->d_reclen) { error = vn_rdwr(UIO_READ, ITOV(ip), (caddr_t)dp, MINDIRSIZ, off, UIO_SYSSPACE, IO_NODELOCKED, cred, &count, curproc); /* * Since we read MINDIRSIZ, residual must * be 0 unless we're at end of file. */ if (error || count != 0) return (0); /* avoid infinite loops */ if (dp->d_reclen == 0) return (0); /* skip empty entries */ if (dp->d_ino == 0) continue; /* accept only "." and ".." */ namlen = dp->d_namlen; if (namlen > 2) return (0); if (dp->d_name[0] != '.') return (0); /* * At this point namlen must be 1 or 2. * 1 implies ".", 2 implies ".." if second * char is also "." */ if (namlen == 1 && dp->d_ino == ip->i_number) continue; if (dp->d_name[1] == '.' && dp->d_ino == parentino) continue; return (0); } return (1); } /* * Check if source directory is in the path of the target directory. * Target is supplied locked, source is unlocked. * The target is always vput before returning. */ int ufs_checkpath(struct inode *source, struct inode *target, struct ucred *cred) { struct vnode *nextvp, *vp; int error, rootino, namlen; struct dirtemplate dirbuf; vp = ITOV(target); if (target->i_number == source->i_number) { error = EEXIST; goto out; } rootino = ROOTINO; error = 0; if (target->i_number == rootino) goto out; for (;;) { if (vp->v_type != VDIR) { error = ENOTDIR; break; } error = vn_rdwr(UIO_READ, vp, (caddr_t)&dirbuf, sizeof (struct dirtemplate), (off_t)0, UIO_SYSSPACE, IO_NODELOCKED, cred, NULL, curproc); if (error != 0) break; namlen = dirbuf.dotdot_namlen; if (namlen != 2 || dirbuf.dotdot_name[0] != '.' || dirbuf.dotdot_name[1] != '.') { error = ENOTDIR; break; } if (dirbuf.dotdot_ino == source->i_number) { error = EINVAL; break; } if (dirbuf.dotdot_ino == rootino) break; VOP_UNLOCK(vp); error = VFS_VGET(vp->v_mount, dirbuf.dotdot_ino, &nextvp); vrele(vp); if (error) { vp = NULL; break; } vp = nextvp; } out: if (error == ENOTDIR) printf("checkpath: .. not a directory\n"); if (vp != NULL) vput(vp); return (error); }
12 2 2 3 19 13 6 19 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 /* $OpenBSD: kern_clock.c,v 1.123 2024/02/12 22:07:33 cheloha Exp $ */ /* $NetBSD: kern_clock.c,v 1.34 1996/06/09 04:51:03 briggs Exp $ */ /*- * Copyright (c) 1982, 1986, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_clock.c 8.5 (Berkeley) 1/21/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/clockintr.h> #include <sys/timeout.h> #include <sys/kernel.h> #include <sys/limits.h> #include <sys/proc.h> #include <sys/user.h> #include <sys/resourcevar.h> #include <sys/sysctl.h> #include <sys/sched.h> #include <sys/timetc.h> /* * Clock handling routines. * * This code is written to operate with two timers that run independently of * each other. The main clock, running hz times per second, is used to keep * track of real time. The second timer handles kernel and user profiling, * and does resource use estimation. If the second timer is programmable, * it is randomized to avoid aliasing between the two clocks. For example, * the randomization prevents an adversary from always giving up the cpu * just before its quantum expires. Otherwise, it would never accumulate * cpu ticks. The mean frequency of the second timer is stathz. * * If no second timer exists, stathz will be zero; in this case we drive * profiling and statistics off the main clock. This WILL NOT be accurate; * do not do it unless absolutely necessary. * * The statistics clock may (or may not) be run at a higher rate while * profiling. This profile clock runs at profhz. We require that profhz * be an integral multiple of stathz. * * If the statistics clock is running fast, it must be divided by the ratio * profhz/stathz for statistics. (For profiling, every tick counts.) */ int stathz; int profhz; int profprocs; int ticks = INT_MAX - (15 * 60 * HZ); /* Don't force early wrap around, triggers bug in inteldrm */ volatile unsigned long jiffies; uint64_t hardclock_period; /* [I] hardclock period (ns) */ uint64_t statclock_avg; /* [I] average statclock period (ns) */ uint64_t statclock_min; /* [I] minimum statclock period (ns) */ uint32_t statclock_mask; /* [I] set of allowed offsets */ int statclock_is_randomized; /* [I] fixed or pseudorandom period? */ /* * Initialize clock frequencies and start both clocks running. */ void initclocks(void) { uint64_t half_avg; uint32_t var; /* * Let the machine-specific code do its bit. */ cpu_initclocks(); KASSERT(hz > 0 && hz <= 1000000000); hardclock_period = 1000000000 / hz; roundrobin_period = hardclock_period * 10; KASSERT(stathz >= 1 && stathz <= 1000000000); /* * Compute the average statclock() period. Then find var, the * largest 32-bit power of two such that var <= statclock_avg / 2. */ statclock_avg = 1000000000 / stathz; half_avg = statclock_avg / 2; for (var = 1U << 31; var > half_avg; var /= 2) continue; /* * Set a lower bound for the range using statclock_avg and var. * The mask for that range is just (var - 1). */ statclock_min = statclock_avg - (var / 2); statclock_mask = var - 1; KASSERT(profhz >= stathz && profhz <= 1000000000); KASSERT(profhz % stathz == 0); profclock_period = 1000000000 / profhz; inittimecounter(); /* Start dispatching clock interrupts on the primary CPU. */ cpu_startclock(); } /* * The real-time timer, interrupting hz times per second. */ void hardclock(struct clockframe *frame) { tc_ticktock(); ticks++; jiffies++; /* * Update the timeout wheel. */ timeout_hardclock_update(); } /* * Compute number of hz in the specified amount of time. */ int tvtohz(const struct timeval *tv) { unsigned long nticks; time_t sec; long usec; /* * If the number of usecs in the whole seconds part of the time * fits in a long, then the total number of usecs will * fit in an unsigned long. Compute the total and convert it to * ticks, rounding up and adding 1 to allow for the current tick * to expire. Rounding also depends on unsigned long arithmetic * to avoid overflow. * * Otherwise, if the number of ticks in the whole seconds part of * the time fits in a long, then convert the parts to * ticks separately and add, using similar rounding methods and * overflow avoidance. This method would work in the previous * case but it is slightly slower and assumes that hz is integral. * * Otherwise, round the time down to the maximum * representable value. * * If ints have 32 bits, then the maximum value for any timeout in * 10ms ticks is 248 days. */ sec = tv->tv_sec; usec = tv->tv_usec; if (sec < 0 || (sec == 0 && usec <= 0)) nticks = 0; else if (sec <= LONG_MAX / 1000000) nticks = (sec * 1000000 + (unsigned long)usec + (tick - 1)) / tick + 1; else if (sec <= LONG_MAX / hz) nticks = sec * hz + ((unsigned long)usec + (tick - 1)) / tick + 1; else nticks = LONG_MAX; if (nticks > INT_MAX) nticks = INT_MAX; return ((int)nticks); } int tstohz(const struct timespec *ts) { struct timeval tv; TIMESPEC_TO_TIMEVAL(&tv, ts); /* Round up. */ if ((ts->tv_nsec % 1000) != 0) { tv.tv_usec += 1; if (tv.tv_usec >= 1000000) { tv.tv_usec -= 1000000; tv.tv_sec += 1; } } return (tvtohz(&tv)); } /* * Start profiling on a process. * * Kernel profiling passes proc0 which never exits and hence * keeps the profile clock running constantly. */ void startprofclock(struct process *pr) { int s; if ((pr->ps_flags & PS_PROFIL) == 0) { atomic_setbits_int(&pr->ps_flags, PS_PROFIL); if (++profprocs == 1) { s = splstatclock(); setstatclockrate(profhz); splx(s); } } } /* * Stop profiling on a process. */ void stopprofclock(struct process *pr) { int s; if (pr->ps_flags & PS_PROFIL) { atomic_clearbits_int(&pr->ps_flags, PS_PROFIL); if (--profprocs == 0) { s = splstatclock(); setstatclockrate(stathz); splx(s); } } } /* * Statistics clock. Grab profile sample, and if divider reaches 0, * do process and kernel statistics. */ void statclock(struct clockrequest *cr, void *cf, void *arg) { uint64_t count, i; struct clockframe *frame = cf; struct cpu_info *ci = curcpu(); struct schedstate_percpu *spc = &ci->ci_schedstate; struct proc *p = curproc; struct process *pr; if (statclock_is_randomized) { count = clockrequest_advance_random(cr, statclock_min, statclock_mask); } else { count = clockrequest_advance(cr, statclock_avg); } if (CLKF_USERMODE(frame)) { pr = p->p_p; /* * Came from user mode; CPU was in user state. * If this process is being profiled record the tick. */ p->p_uticks += count; if (pr->ps_nice > NZERO) spc->spc_cp_time[CP_NICE] += count; else spc->spc_cp_time[CP_USER] += count; } else { /* * Came from kernel mode, so we were: * - spinning on a lock * - handling an interrupt, * - doing syscall or trap work on behalf of the current * user process, or * - spinning in the idle loop. * Whichever it is, charge the time as appropriate. * Note that we charge interrupts to the current process, * regardless of whether they are ``for'' that process, * so that we know how much of its real time was spent * in ``non-process'' (i.e., interrupt) work. */ if (CLKF_INTR(frame)) { if (p != NULL) p->p_iticks += count; spc->spc_cp_time[spc->spc_spinning ? CP_SPIN : CP_INTR] += count; } else if (p != NULL && p != spc->spc_idleproc) { p->p_sticks += count; spc->spc_cp_time[spc->spc_spinning ? CP_SPIN : CP_SYS] += count; } else spc->spc_cp_time[spc->spc_spinning ? CP_SPIN : CP_IDLE] += count; } if (p != NULL) { p->p_cpticks += count; /* * schedclock() runs every fourth statclock(). */ for (i = 0; i < count; i++) { if ((++spc->spc_schedticks & 3) == 0) schedclock(p); } } } /* * Return information about system clocks. */ int sysctl_clockrate(char *where, size_t *sizep, void *newp) { struct clockinfo clkinfo; /* * Construct clockinfo structure. */ memset(&clkinfo, 0, sizeof clkinfo); clkinfo.tick = tick; clkinfo.hz = hz; clkinfo.profhz = profhz; clkinfo.stathz = stathz; return (sysctl_rdstruct(where, sizep, newp, &clkinfo, sizeof(clkinfo))); }
9 5 1 4 3 1 2 4 1 3 1 1 3 4 3 3 2 3 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 /* $OpenBSD: tty_msts.c,v 1.21 2018/02/19 08:59:52 mpi Exp $ */ /* * Copyright (c) 2008 Marc Balmer <mbalmer@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * A tty line discipline to decode the Meinberg Standard Time String * to get the time (http://www.meinberg.de/english/specs/timestr.htm). */ #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/sensors.h> #include <sys/tty.h> #include <sys/conf.h> #include <sys/time.h> #ifdef MSTS_DEBUG #define DPRINTFN(n, x) do { if (mstsdebug > (n)) printf x; } while (0) int mstsdebug = 0; #else #define DPRINTFN(n, x) #endif #define DPRINTF(x) DPRINTFN(0, x) void mstsattach(int); #define MSTSMAX 32 #define MAXFLDS 4 #ifdef MSTS_DEBUG #define TRUSTTIME 30 #else #define TRUSTTIME (10 * 60) /* 10 minutes */ #endif int msts_count, msts_nxid; struct msts { char cbuf[MSTSMAX]; /* receive buffer */ struct ksensor time; /* the timedelta sensor */ struct ksensor signal; /* signal status */ struct ksensordev timedev; struct timespec ts; /* current timestamp */ struct timespec lts; /* timestamp of last <STX> */ struct timeout msts_tout; /* invalidate sensor */ int64_t gap; /* gap between two sentences */ int64_t last; /* last time rcvd */ int sync; /* if 1, waiting for <STX> */ int pos; /* position in rcv buffer */ int no_pps; /* no PPS although requested */ }; /* MSTS decoding */ void msts_scan(struct msts *, struct tty *); void msts_decode(struct msts *, struct tty *, char *fld[], int fldcnt); /* date and time conversion */ int msts_date_to_nano(char *s, int64_t *nano); int msts_time_to_nano(char *s, int64_t *nano); /* degrade the timedelta sensor */ void msts_timeout(void *); void mstsattach(int dummy) { } int mstsopen(dev_t dev, struct tty *tp, struct proc *p) { struct msts *np; int error; DPRINTF(("mstsopen\n")); if (tp->t_line == MSTSDISC) return ENODEV; if ((error = suser(p)) != 0) return error; np = malloc(sizeof(struct msts), M_DEVBUF, M_WAITOK|M_ZERO); snprintf(np->timedev.xname, sizeof(np->timedev.xname), "msts%d", msts_nxid++); msts_count++; np->time.status = SENSOR_S_UNKNOWN; np->time.type = SENSOR_TIMEDELTA; #ifndef MSTS_DEBUG np->time.flags = SENSOR_FINVALID; #endif sensor_attach(&np->timedev, &np->time); np->signal.type = SENSOR_PERCENT; np->signal.status = SENSOR_S_UNKNOWN; np->signal.value = 100000LL; strlcpy(np->signal.desc, "Signal", sizeof(np->signal.desc)); sensor_attach(&np->timedev, &np->signal); np->sync = 1; tp->t_sc = (caddr_t)np; error = linesw[TTYDISC].l_open(dev, tp, p); if (error) { free(np, M_DEVBUF, sizeof(*np)); tp->t_sc = NULL; } else { sensordev_install(&np->timedev); timeout_set(&np->msts_tout, msts_timeout, np); } return error; } int mstsclose(struct tty *tp, int flags, struct proc *p) { struct msts *np = (struct msts *)tp->t_sc; tp->t_line = TTYDISC; /* switch back to termios */ timeout_del(&np->msts_tout); sensordev_deinstall(&np->timedev); free(np, M_DEVBUF, sizeof(*np)); tp->t_sc = NULL; msts_count--; if (msts_count == 0) msts_nxid = 0; return linesw[TTYDISC].l_close(tp, flags, p); } /* collect MSTS sentence from tty */ int mstsinput(int c, struct tty *tp) { struct msts *np = (struct msts *)tp->t_sc; struct timespec ts; int64_t gap; long tmin, tmax; switch (c) { case 2: /* ASCII <STX> */ nanotime(&ts); np->pos = np->sync = 0; gap = (ts.tv_sec * 1000000000LL + ts.tv_nsec) - (np->lts.tv_sec * 1000000000LL + np->lts.tv_nsec); np->lts.tv_sec = ts.tv_sec; np->lts.tv_nsec = ts.tv_nsec; if (gap <= np->gap) break; np->ts.tv_sec = ts.tv_sec; np->ts.tv_nsec = ts.tv_nsec; np->gap = gap; /* * If a tty timestamp is available, make sure its value is * reasonable by comparing against the timestamp just taken. * If they differ by more than 2 seconds, assume no PPS signal * is present, note the fact, and keep using the timestamp * value. When this happens, the sensor state is set to * CRITICAL later when the MSTS sentence is decoded. */ if (tp->t_flags & (TS_TSTAMPDCDSET | TS_TSTAMPDCDCLR | TS_TSTAMPCTSSET | TS_TSTAMPCTSCLR)) { tmax = lmax(np->ts.tv_sec, tp->t_tv.tv_sec); tmin = lmin(np->ts.tv_sec, tp->t_tv.tv_sec); if (tmax - tmin > 1) np->no_pps = 1; else { np->ts.tv_sec = tp->t_tv.tv_sec; np->ts.tv_nsec = tp->t_tv.tv_usec * 1000L; np->no_pps = 0; } } break; case 3: /* ASCII <ETX> */ if (!np->sync) { np->cbuf[np->pos] = '\0'; msts_scan(np, tp); np->sync = 1; } break; default: if (!np->sync && np->pos < (MSTSMAX - 1)) np->cbuf[np->pos++] = c; break; } /* pass data to termios */ return linesw[TTYDISC].l_rint(c, tp); } /* Scan the MSTS sentence just received */ void msts_scan(struct msts *np, struct tty *tp) { int fldcnt = 0, n; char *fld[MAXFLDS], *cs; /* split into fields */ fld[fldcnt++] = &np->cbuf[0]; for (cs = NULL, n = 0; n < np->pos && cs == NULL; n++) { switch (np->cbuf[n]) { case 3: /* ASCII <ETX> */ np->cbuf[n] = '\0'; cs = &np->cbuf[n + 1]; break; case ';': if (fldcnt < MAXFLDS) { np->cbuf[n] = '\0'; fld[fldcnt++] = &np->cbuf[n + 1]; } else { DPRINTF(("nr of fields in sentence exceeds " "maximum of %d\n", MAXFLDS)); return; } break; } } msts_decode(np, tp, fld, fldcnt); } /* Decode the time string */ void msts_decode(struct msts *np, struct tty *tp, char *fld[], int fldcnt) { int64_t date_nano, time_nano, msts_now; int jumped = 0; if (fldcnt != MAXFLDS) { DPRINTF(("msts: field count mismatch, %d\n", fldcnt)); return; } if (msts_time_to_nano(fld[2], &time_nano)) { DPRINTF(("msts: illegal time, %s\n", fld[2])); return; } if (msts_date_to_nano(fld[0], &date_nano)) { DPRINTF(("msts: illegal date, %s\n", fld[0])); return; } msts_now = date_nano + time_nano; if ( fld[3][2] == ' ' ) /* received time in CET */ msts_now = msts_now - 3600 * 1000000000LL; if ( fld[3][2] == 'S' ) /* received time in CEST */ msts_now = msts_now - 2 * 3600 * 1000000000LL; if (msts_now <= np->last) { DPRINTF(("msts: time not monotonically increasing\n")); jumped = 1; } np->last = msts_now; np->gap = 0LL; #ifdef MSTS_DEBUG if (np->time.status == SENSOR_S_UNKNOWN) { np->time.status = SENSOR_S_OK; timeout_add_sec(&np->msts_tout, TRUSTTIME); } #endif np->time.value = np->ts.tv_sec * 1000000000LL + np->ts.tv_nsec - msts_now; np->time.tv.tv_sec = np->ts.tv_sec; np->time.tv.tv_usec = np->ts.tv_nsec / 1000L; if (np->time.status == SENSOR_S_UNKNOWN) { np->time.status = SENSOR_S_OK; np->time.flags &= ~SENSOR_FINVALID; strlcpy(np->time.desc, "MSTS", sizeof(np->time.desc)); } /* * only update the timeout if the clock reports the time a valid, * the status is reported in fld[3][0] and fld[3][1] as follows: * fld[3][0] == '#' critical * fld[3][0] == ' ' && fld[3][1] == '*' warning * fld[3][0] == ' ' && fld[3][1] == ' ' ok */ if (fld[3][0] == ' ' && fld[3][1] == ' ') { np->time.status = SENSOR_S_OK; np->signal.status = SENSOR_S_OK; } else np->signal.status = SENSOR_S_WARN; if (jumped) np->time.status = SENSOR_S_WARN; if (np->time.status == SENSOR_S_OK) timeout_add_sec(&np->msts_tout, TRUSTTIME); /* * If tty timestamping is requested, but no PPS signal is present, set * the sensor state to CRITICAL. */ if (np->no_pps) np->time.status = SENSOR_S_CRIT; } /* * Convert date field from MSTS to nanoseconds since the epoch. * The string must be of the form D:DD.MM.YY . * Return 0 on success, -1 if illegal characters are encountered. */ int msts_date_to_nano(char *s, int64_t *nano) { struct clock_ymdhms ymd; time_t secs; char *p; int n; if (s[0] != 'D' || s[1] != ':' || s[4] != '.' || s[7] != '.') return -1; /* shift numbers to DDMMYY */ s[0]=s[2]; s[1]=s[3]; s[2]=s[5]; s[3]=s[6]; s[4]=s[8]; s[5]=s[9]; s[6]='\0'; /* make sure the input contains only numbers and is six digits long */ for (n = 0, p = s; n < 6 && *p && *p >= '0' && *p <= '9'; n++, p++) ; if (n != 6 || (*p != '\0')) return -1; ymd.dt_year = 2000 + (s[4] - '0') * 10 + (s[5] - '0'); ymd.dt_mon = (s[2] - '0') * 10 + (s[3] - '0'); ymd.dt_day = (s[0] - '0') * 10 + (s[1] - '0'); ymd.dt_hour = ymd.dt_min = ymd.dt_sec = 0; secs = clock_ymdhms_to_secs(&ymd); *nano = secs * 1000000000LL; return 0; } /* * Convert time field from MSTS to nanoseconds since midnight. * The string must be of the form U:HH.MM.SS . * Return 0 on success, -1 if illegal characters are encountered. */ int msts_time_to_nano(char *s, int64_t *nano) { long fac = 36000L, div = 6L, secs = 0L; char ul = '2'; int n; if (s[0] != 'U' || s[1] != ':' || s[4] != '.' || s[7] != '.') return -1; /* shift numbers to HHMMSS */ s[0]=s[2]; s[1]=s[3]; s[2]=s[5]; s[3]=s[6]; s[4]=s[8]; s[5]=s[9]; s[6]='\0'; for (n = 0, secs = 0; fac && *s && *s >= '0' && *s <= ul; s++, n++) { secs += (*s - '0') * fac; div = 16 - div; fac /= div; switch (n) { case 0: if (*s <= '1') ul = '9'; else ul = '3'; break; case 1: case 3: ul = '5'; break; case 2: case 4: ul = '9'; break; } } if (fac) return -1; if (*s != '\0') return -1; *nano = secs * 1000000000LL; return 0; } /* * Degrade the sensor state if we received no MSTS string for more than * TRUSTTIME seconds. */ void msts_timeout(void *xnp) { struct msts *np = xnp; if (np->time.status == SENSOR_S_OK) { np->time.status = SENSOR_S_WARN; /* * further degrade in TRUSTTIME seconds if no new valid MSTS * strings are received. */ timeout_add_sec(&np->msts_tout, TRUSTTIME); } else np->time.status = SENSOR_S_CRIT; }
12 6 1 5 5 4 3 4 4 2 1 2 2 1 1 1 4 2 2 1 1 4 2 2 4 2 1 5 1 4 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 /* $OpenBSD: fuse_device.c,v 1.40 2023/12/16 22:17:08 mvs Exp $ */ /* * Copyright (c) 2012-2013 Sylvestre Gallon <ccna.syl@gmail.com> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/fcntl.h> #include <sys/ioctl.h> #include <sys/event.h> #include <sys/malloc.h> #include <sys/mount.h> #include <sys/rwlock.h> #include <sys/stat.h> #include <sys/statvfs.h> #include <sys/vnode.h> #include <sys/fusebuf.h> #include "fusefs_node.h" #include "fusefs.h" #ifdef FUSE_DEBUG #define DPRINTF(fmt, arg...) printf("%s: " fmt, "fuse", ##arg) #else #define DPRINTF(fmt, arg...) #endif /* * Locks used to protect struct members and global data * l fd_lock */ SIMPLEQ_HEAD(fusebuf_head, fusebuf); struct fuse_d { struct rwlock fd_lock; struct fusefs_mnt *fd_fmp; int fd_unit; /*fusebufs queues*/ struct fusebuf_head fd_fbufs_in; /* [l] */ struct fusebuf_head fd_fbufs_wait; /* kq fields */ struct klist fd_rklist; /* [l] */ LIST_ENTRY(fuse_d) fd_list; }; int stat_fbufs_in = 0; int stat_fbufs_wait = 0; int stat_opened_fusedev = 0; LIST_HEAD(, fuse_d) fuse_d_list; struct fuse_d *fuse_lookup(int); void fuseattach(int); int fuseopen(dev_t, int, int, struct proc *); int fuseclose(dev_t, int, int, struct proc *); int fuseioctl(dev_t, u_long, caddr_t, int, struct proc *); int fuseread(dev_t, struct uio *, int); int fusewrite(dev_t, struct uio *, int); int fusekqfilter(dev_t dev, struct knote *kn); int filt_fuse_read(struct knote *, long); void filt_fuse_rdetach(struct knote *); int filt_fuse_modify(struct kevent *, struct knote *); int filt_fuse_process(struct knote *, struct kevent *); static const struct filterops fuse_rd_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_fuse_rdetach, .f_event = filt_fuse_read, .f_modify = filt_fuse_modify, .f_process = filt_fuse_process, }; #ifdef FUSE_DEBUG static void fuse_dump_buff(char *buff, int len) { char text[17]; int i; if (len < 0) { printf("invalid len: %d", len); return; } if (buff == NULL) { printf("invalid buff"); return; } memset(text, 0, 17); for (i = 0; i < len; i++) { if (i != 0 && (i % 16) == 0) { printf(": %s\n", text); memset(text, 0, 17); } printf("%.2x ", buff[i] & 0xff); if (buff[i] > ' ' && buff[i] < '~') text[i%16] = buff[i] & 0xff; else text[i%16] = '.'; } if ((i % 16) != 0) while ((i % 16) != 0) { printf(" "); i++; } printf(": %s\n", text); } #endif struct fuse_d * fuse_lookup(int unit) { struct fuse_d *fd; LIST_FOREACH(fd, &fuse_d_list, fd_list) if (fd->fd_unit == unit) return (fd); return (NULL); } /* * Cleanup all msgs from sc_fbufs_in and sc_fbufs_wait. */ void fuse_device_cleanup(dev_t dev) { struct fuse_d *fd; struct fusebuf *f, *ftmp, *lprev; fd = fuse_lookup(minor(dev)); if (fd == NULL) return; /* clear FIFO IN */ lprev = NULL; rw_enter_write(&fd->fd_lock); SIMPLEQ_FOREACH_SAFE(f, &fd->fd_fbufs_in, fb_next, ftmp) { DPRINTF("cleanup unprocessed msg in sc_fbufs_in\n"); if (lprev == NULL) SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_in, fb_next); else SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_in, lprev, fb_next); stat_fbufs_in--; f->fb_err = ENXIO; wakeup(f); lprev = f; } rw_exit_write(&fd->fd_lock); /* clear FIFO WAIT*/ lprev = NULL; SIMPLEQ_FOREACH_SAFE(f, &fd->fd_fbufs_wait, fb_next, ftmp) { DPRINTF("umount unprocessed msg in sc_fbufs_wait\n"); if (lprev == NULL) SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_wait, fb_next); else SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_wait, lprev, fb_next); stat_fbufs_wait--; f->fb_err = ENXIO; wakeup(f); lprev = f; } } void fuse_device_queue_fbuf(dev_t dev, struct fusebuf *fbuf) { struct fuse_d *fd; fd = fuse_lookup(minor(dev)); if (fd == NULL) return; rw_enter_write(&fd->fd_lock); SIMPLEQ_INSERT_TAIL(&fd->fd_fbufs_in, fbuf, fb_next); knote_locked(&fd->fd_rklist, 0); rw_exit_write(&fd->fd_lock); stat_fbufs_in++; } void fuse_device_set_fmp(struct fusefs_mnt *fmp, int set) { struct fuse_d *fd; fd = fuse_lookup(minor(fmp->dev)); if (fd == NULL) return; fd->fd_fmp = set ? fmp : NULL; } void fuseattach(int num) { LIST_INIT(&fuse_d_list); } int fuseopen(dev_t dev, int flags, int fmt, struct proc * p) { struct fuse_d *fd; int unit = minor(dev); if (flags & O_EXCL) return (EBUSY); /* No exclusive opens */ if ((fd = fuse_lookup(unit)) != NULL) return (EBUSY); fd = malloc(sizeof(*fd), M_DEVBUF, M_WAITOK | M_ZERO); fd->fd_unit = unit; SIMPLEQ_INIT(&fd->fd_fbufs_in); SIMPLEQ_INIT(&fd->fd_fbufs_wait); rw_init(&fd->fd_lock, "fusedlk"); klist_init_rwlock(&fd->fd_rklist, &fd->fd_lock); LIST_INSERT_HEAD(&fuse_d_list, fd, fd_list); stat_opened_fusedev++; return (0); } int fuseclose(dev_t dev, int flags, int fmt, struct proc *p) { struct fuse_d *fd; int error; fd = fuse_lookup(minor(dev)); if (fd == NULL) return (EINVAL); if (fd->fd_fmp) { printf("fuse: device close without umount\n"); fd->fd_fmp->sess_init = 0; fuse_device_cleanup(dev); if ((vfs_busy(fd->fd_fmp->mp, VB_WRITE | VB_NOWAIT)) != 0) goto end; error = dounmount(fd->fd_fmp->mp, MNT_FORCE, p); if (error) printf("fuse: unmount failed with error %d\n", error); fd->fd_fmp = NULL; } end: LIST_REMOVE(fd, fd_list); free(fd, M_DEVBUF, sizeof(*fd)); stat_opened_fusedev--; return (0); } /* * FIOCGETFBDAT Get fusebuf data from kernel to user * FIOCSETFBDAT Set fusebuf data from user to kernel */ int fuseioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) { struct fb_ioctl_xch *ioexch; struct fusebuf *lastfbuf; struct fusebuf *fbuf; struct fuse_d *fd; int error = 0; fd = fuse_lookup(minor(dev)); if (fd == NULL) return (ENXIO); switch (cmd) { case FIOCGETFBDAT: ioexch = (struct fb_ioctl_xch *)addr; /* Looking for uuid in fd_fbufs_in */ rw_enter_write(&fd->fd_lock); SIMPLEQ_FOREACH(fbuf, &fd->fd_fbufs_in, fb_next) { if (fbuf->fb_uuid == ioexch->fbxch_uuid) break; lastfbuf = fbuf; } if (fbuf == NULL) { rw_exit_write(&fd->fd_lock); printf("fuse: Cannot find fusebuf\n"); return (EINVAL); } /* Remove the fbuf from fd_fbufs_in */ if (fbuf == SIMPLEQ_FIRST(&fd->fd_fbufs_in)) SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_in, fb_next); else SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_in, lastfbuf, fb_next); rw_exit_write(&fd->fd_lock); stat_fbufs_in--; /* Do not handle fbufs with bad len */ if (fbuf->fb_len != ioexch->fbxch_len) { printf("fuse: Bad fusebuf len\n"); return (EINVAL); } /* Update the userland fbuf */ error = copyout(fbuf->fb_dat, ioexch->fbxch_data, ioexch->fbxch_len); if (error) { printf("fuse: cannot copyout\n"); return (error); } #ifdef FUSE_DEBUG fuse_dump_buff(fbuf->fb_dat, fbuf->fb_len); #endif /* Adding fbuf in fd_fbufs_wait */ free(fbuf->fb_dat, M_FUSEFS, fbuf->fb_len); fbuf->fb_dat = NULL; SIMPLEQ_INSERT_TAIL(&fd->fd_fbufs_wait, fbuf, fb_next); stat_fbufs_wait++; break; case FIOCSETFBDAT: DPRINTF("SET BUFFER\n"); ioexch = (struct fb_ioctl_xch *)addr; /* looking for uuid in fd_fbufs_wait */ SIMPLEQ_FOREACH(fbuf, &fd->fd_fbufs_wait, fb_next) { if (fbuf->fb_uuid == ioexch->fbxch_uuid) break; lastfbuf = fbuf; } if (fbuf == NULL) { printf("fuse: Cannot find fusebuf\n"); return (EINVAL); } /* Do not handle fbufs with bad len */ if (fbuf->fb_len != ioexch->fbxch_len) { printf("fuse: Bad fusebuf size\n"); return (EINVAL); } /* fetching data from userland */ fbuf->fb_dat = malloc(ioexch->fbxch_len, M_FUSEFS, M_WAITOK | M_ZERO); error = copyin(ioexch->fbxch_data, fbuf->fb_dat, ioexch->fbxch_len); if (error) { printf("fuse: Cannot copyin\n"); free(fbuf->fb_dat, M_FUSEFS, fbuf->fb_len); fbuf->fb_dat = NULL; return (error); } #ifdef FUSE_DEBUG fuse_dump_buff(fbuf->fb_dat, fbuf->fb_len); #endif /* Remove fbuf from fd_fbufs_wait */ if (fbuf == SIMPLEQ_FIRST(&fd->fd_fbufs_wait)) SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_wait, fb_next); else SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_wait, lastfbuf, fb_next); stat_fbufs_wait--; wakeup(fbuf); break; default: error = EINVAL; } return (error); } int fuseread(dev_t dev, struct uio *uio, int ioflag) { struct fuse_d *fd; struct fusebuf *fbuf; struct fb_hdr hdr; void *tmpaddr; int error = 0; /* We get the whole fusebuf or nothing */ if (uio->uio_resid != FUSEBUFSIZE) return (EINVAL); fd = fuse_lookup(minor(dev)); if (fd == NULL) return (ENXIO); rw_enter_write(&fd->fd_lock); if (SIMPLEQ_EMPTY(&fd->fd_fbufs_in)) { if (ioflag & O_NONBLOCK) error = EAGAIN; goto end; } fbuf = SIMPLEQ_FIRST(&fd->fd_fbufs_in); /* Do not send kernel pointers */ memcpy(&hdr.fh_next, &fbuf->fb_next, sizeof(fbuf->fb_next)); memset(&fbuf->fb_next, 0, sizeof(fbuf->fb_next)); tmpaddr = fbuf->fb_dat; fbuf->fb_dat = NULL; error = uiomove(fbuf, FUSEBUFSIZE, uio); if (error) goto end; #ifdef FUSE_DEBUG fuse_dump_buff((char *)fbuf, FUSEBUFSIZE); #endif /* Restore kernel pointers */ memcpy(&fbuf->fb_next, &hdr.fh_next, sizeof(fbuf->fb_next)); fbuf->fb_dat = tmpaddr; /* Remove the fbuf if it does not contains data */ if (fbuf->fb_len == 0) { SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_in, fb_next); stat_fbufs_in--; SIMPLEQ_INSERT_TAIL(&fd->fd_fbufs_wait, fbuf, fb_next); stat_fbufs_wait++; } end: rw_exit_write(&fd->fd_lock); return (error); } int fusewrite(dev_t dev, struct uio *uio, int ioflag) { struct fusebuf *lastfbuf; struct fuse_d *fd; struct fusebuf *fbuf; struct fb_hdr hdr; int error = 0; fd = fuse_lookup(minor(dev)); if (fd == NULL) return (ENXIO); /* We get the whole fusebuf or nothing */ if (uio->uio_resid != FUSEBUFSIZE) return (EINVAL); if ((error = uiomove(&hdr, sizeof(hdr), uio)) != 0) return (error); /* looking for uuid in fd_fbufs_wait */ SIMPLEQ_FOREACH(fbuf, &fd->fd_fbufs_wait, fb_next) { if (fbuf->fb_uuid == hdr.fh_uuid) break; lastfbuf = fbuf; } if (fbuf == NULL) return (EINVAL); /* Update fb_hdr */ fbuf->fb_len = hdr.fh_len; fbuf->fb_err = hdr.fh_err; fbuf->fb_ino = hdr.fh_ino; /* Check for corrupted fbufs */ if ((fbuf->fb_len && fbuf->fb_err) || SIMPLEQ_EMPTY(&fd->fd_fbufs_wait)) { printf("fuse: dropping corrupted fusebuf\n"); error = EINVAL; goto end; } /* Get the missing data from the fbuf */ error = uiomove(&fbuf->FD, uio->uio_resid, uio); if (error) return error; fbuf->fb_dat = NULL; #ifdef FUSE_DEBUG fuse_dump_buff((char *)fbuf, FUSEBUFSIZE); #endif switch (fbuf->fb_type) { case FBT_INIT: fd->fd_fmp->sess_init = 1; break ; case FBT_DESTROY: fd->fd_fmp = NULL; break ; } end: /* Remove the fbuf if it does not contains data */ if (fbuf->fb_len == 0) { if (fbuf == SIMPLEQ_FIRST(&fd->fd_fbufs_wait)) SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_wait, fb_next); else SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_wait, lastfbuf, fb_next); stat_fbufs_wait--; if (fbuf->fb_type == FBT_INIT) fb_delete(fbuf); else wakeup(fbuf); } return (error); } int fusekqfilter(dev_t dev, struct knote *kn) { struct fuse_d *fd; struct klist *klist; fd = fuse_lookup(minor(dev)); if (fd == NULL) return (EINVAL); switch (kn->kn_filter) { case EVFILT_READ: klist = &fd->fd_rklist; kn->kn_fop = &fuse_rd_filtops; break; case EVFILT_WRITE: return (seltrue_kqfilter(dev, kn)); default: return (EINVAL); } kn->kn_hook = fd; klist_insert(klist, kn); return (0); } void filt_fuse_rdetach(struct knote *kn) { struct fuse_d *fd = kn->kn_hook; struct klist *klist = &fd->fd_rklist; klist_remove(klist, kn); } int filt_fuse_read(struct knote *kn, long hint) { struct fuse_d *fd = kn->kn_hook; int event = 0; rw_assert_wrlock(&fd->fd_lock); if (!SIMPLEQ_EMPTY(&fd->fd_fbufs_in)) event = 1; return (event); } int filt_fuse_modify(struct kevent *kev, struct knote *kn) { struct fuse_d *fd = kn->kn_hook; int active; rw_enter_write(&fd->fd_lock); active = knote_modify(kev, kn); rw_exit_write(&fd->fd_lock); return (active); } int filt_fuse_process(struct knote *kn, struct kevent *kev) { struct fuse_d *fd = kn->kn_hook; int active; rw_enter_write(&fd->fd_lock); active = knote_process(kn, kev); rw_exit_write(&fd->fd_lock); return (active); }
5 3 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 /* $OpenBSD: uvm_device.c,v 1.66 2021/12/15 12:53:53 mpi Exp $ */ /* $NetBSD: uvm_device.c,v 1.30 2000/11/25 06:27:59 chs Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * from: Id: uvm_device.c,v 1.1.2.9 1998/02/06 05:11:47 chs Exp */ /* * uvm_device.c: the device pager. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/conf.h> #include <sys/malloc.h> #include <sys/mutex.h> #include <uvm/uvm.h> #include <uvm/uvm_device.h> #include "drm.h" /* * private global data structure * * we keep a list of active device objects in the system. */ LIST_HEAD(, uvm_device) udv_list = LIST_HEAD_INITIALIZER(udv_list); struct mutex udv_lock = MUTEX_INITIALIZER(IPL_NONE); /* * functions */ static void udv_reference(struct uvm_object *); static void udv_detach(struct uvm_object *); static int udv_fault(struct uvm_faultinfo *, vaddr_t, vm_page_t *, int, int, vm_fault_t, vm_prot_t, int); static boolean_t udv_flush(struct uvm_object *, voff_t, voff_t, int); /* * master pager structure */ const struct uvm_pagerops uvm_deviceops = { .pgo_reference = udv_reference, .pgo_detach = udv_detach, .pgo_fault = udv_fault, .pgo_flush = udv_flush, }; /* * the ops! */ /* * udv_attach * * get a VM object that is associated with a device. allocate a new * one if needed. * * => nothing should be locked so that we can sleep here. * * The last two arguments (off and size) are only used for access checking. */ struct uvm_object * udv_attach(dev_t device, vm_prot_t accessprot, voff_t off, vsize_t size) { struct uvm_device *udv, *lcv; paddr_t (*mapfn)(dev_t, off_t, int); #if NDRM > 0 struct uvm_object *obj; #endif /* * before we do anything, ensure this device supports mmap */ mapfn = cdevsw[major(device)].d_mmap; if (mapfn == NULL || mapfn == (paddr_t (*)(dev_t, off_t, int)) enodev || mapfn == (paddr_t (*)(dev_t, off_t, int)) nullop) return(NULL); /* * Negative offsets on the object are not allowed. */ if (off < 0) return(NULL); #if NDRM > 0 obj = udv_attach_drm(device, accessprot, off, size); if (obj) return(obj); #endif /* * Check that the specified range of the device allows the * desired protection. * * XXX clobbers off and size, but nothing else here needs them. */ while (size != 0) { if ((*mapfn)(device, off, accessprot) == -1) return (NULL); off += PAGE_SIZE; size -= PAGE_SIZE; } /* * keep looping until we get it */ for (;;) { /* * first, attempt to find it on the main list */ mtx_enter(&udv_lock); LIST_FOREACH(lcv, &udv_list, u_list) { if (device == lcv->u_device) break; } /* * got it on main list. put a hold on it and unlock udv_lock. */ if (lcv) { /* * if someone else has a hold on it, sleep and start * over again. Else, we need take HOLD flag so we * don't have to re-order locking here. */ if (lcv->u_flags & UVM_DEVICE_HOLD) { lcv->u_flags |= UVM_DEVICE_WANTED; msleep_nsec(lcv, &udv_lock, PVM | PNORELOCK, "udv_attach", INFSLP); continue; } /* we are now holding it */ lcv->u_flags |= UVM_DEVICE_HOLD; mtx_leave(&udv_lock); /* * bump reference count, unhold, return. */ rw_enter(lcv->u_obj.vmobjlock, RW_WRITE); lcv->u_obj.uo_refs++; rw_exit(lcv->u_obj.vmobjlock); mtx_enter(&udv_lock); if (lcv->u_flags & UVM_DEVICE_WANTED) wakeup(lcv); lcv->u_flags &= ~(UVM_DEVICE_WANTED|UVM_DEVICE_HOLD); mtx_leave(&udv_lock); return(&lcv->u_obj); } /* * Did not find it on main list. Need to allocate a new one. */ mtx_leave(&udv_lock); /* NOTE: we could sleep in the following malloc() */ udv = malloc(sizeof(*udv), M_TEMP, M_WAITOK); uvm_obj_init(&udv->u_obj, &uvm_deviceops, 1); mtx_enter(&udv_lock); /* * now we have to double check to make sure no one added it * to the list while we were sleeping... */ LIST_FOREACH(lcv, &udv_list, u_list) { if (device == lcv->u_device) break; } /* * did we lose a race to someone else? * free our memory and retry. */ if (lcv) { mtx_leave(&udv_lock); uvm_obj_destroy(&udv->u_obj); free(udv, M_TEMP, sizeof(*udv)); continue; } /* * we have it! init the data structures, add to list * and return. */ udv->u_flags = 0; udv->u_device = device; LIST_INSERT_HEAD(&udv_list, udv, u_list); mtx_leave(&udv_lock); return(&udv->u_obj); } /*NOTREACHED*/ } /* * udv_reference * * add a reference to a VM object. Note that the reference count must * already be one (the passed in reference) so there is no chance of the * udv being released or locked out here. */ static void udv_reference(struct uvm_object *uobj) { rw_enter(uobj->vmobjlock, RW_WRITE); uobj->uo_refs++; rw_exit(uobj->vmobjlock); } /* * udv_detach * * remove a reference to a VM object. */ static void udv_detach(struct uvm_object *uobj) { struct uvm_device *udv = (struct uvm_device *)uobj; KERNEL_ASSERT_LOCKED(); /* * loop until done */ again: rw_enter(uobj->vmobjlock, RW_WRITE); if (uobj->uo_refs > 1) { uobj->uo_refs--; rw_exit(uobj->vmobjlock); return; } KASSERT(uobj->uo_npages == 0 && RBT_EMPTY(uvm_objtree, &uobj->memt)); /* * is it being held? if so, wait until others are done. */ mtx_enter(&udv_lock); if (udv->u_flags & UVM_DEVICE_HOLD) { udv->u_flags |= UVM_DEVICE_WANTED; rw_exit(uobj->vmobjlock); msleep_nsec(udv, &udv_lock, PVM | PNORELOCK, "udv_detach", INFSLP); goto again; } /* * got it! nuke it now. */ LIST_REMOVE(udv, u_list); if (udv->u_flags & UVM_DEVICE_WANTED) wakeup(udv); mtx_leave(&udv_lock); rw_exit(uobj->vmobjlock); uvm_obj_destroy(uobj); free(udv, M_TEMP, sizeof(*udv)); } /* * udv_flush * * flush pages out of a uvm object. a no-op for devices. */ static boolean_t udv_flush(struct uvm_object *uobj, voff_t start, voff_t stop, int flags) { return(TRUE); } /* * udv_fault: non-standard fault routine for device "pages" * * => rather than having a "get" function, we have a fault routine * since we don't return vm_pages we need full control over the * pmap_enter map in * => on return, we unlock all fault data structures * => flags: PGO_ALLPAGES: get all of the pages * PGO_LOCKED: fault data structures are locked * XXX: currently PGO_LOCKED is always required ... consider removing * it as a flag * => NOTE: vaddr is the VA of pps[0] in ufi->entry, _NOT_ pps[centeridx] */ static int udv_fault(struct uvm_faultinfo *ufi, vaddr_t vaddr, vm_page_t *pps, int npages, int centeridx, vm_fault_t fault_type, vm_prot_t access_type, int flags) { struct vm_map_entry *entry = ufi->entry; struct uvm_object *uobj = entry->object.uvm_obj; struct uvm_device *udv = (struct uvm_device *)uobj; vaddr_t curr_va; off_t curr_offset; paddr_t paddr; int lcv, retval; dev_t device; paddr_t (*mapfn)(dev_t, off_t, int); vm_prot_t mapprot; KERNEL_ASSERT_LOCKED(); /* * we do not allow device mappings to be mapped copy-on-write * so we kill any attempt to do so here. */ if (UVM_ET_ISCOPYONWRITE(entry)) { uvmfault_unlockall(ufi, ufi->entry->aref.ar_amap, uobj); return(VM_PAGER_ERROR); } /* * get device map function. */ device = udv->u_device; mapfn = cdevsw[major(device)].d_mmap; /* * now we must determine the offset in udv to use and the VA to * use for pmap_enter. note that we always use orig_map's pmap * for pmap_enter (even if we have a submap). since virtual * addresses in a submap must match the main map, this is ok. */ /* udv offset = (offset from start of entry) + entry's offset */ curr_offset = entry->offset + (vaddr - entry->start); /* pmap va = vaddr (virtual address of pps[0]) */ curr_va = vaddr; /* * loop over the page range entering in as needed */ retval = VM_PAGER_OK; for (lcv = 0 ; lcv < npages ; lcv++, curr_offset += PAGE_SIZE, curr_va += PAGE_SIZE) { if ((flags & PGO_ALLPAGES) == 0 && lcv != centeridx) continue; if (pps[lcv] == PGO_DONTCARE) continue; paddr = (*mapfn)(device, curr_offset, access_type); if (paddr == -1) { retval = VM_PAGER_ERROR; break; } mapprot = ufi->entry->protection; if (pmap_enter(ufi->orig_map->pmap, curr_va, paddr, mapprot, PMAP_CANFAIL | mapprot) != 0) { /* * pmap_enter() didn't have the resource to * enter this mapping. Unlock everything, * wait for the pagedaemon to free up some * pages, and then tell uvm_fault() to start * the fault again. * * XXX Needs some rethinking for the PGO_ALLPAGES * XXX case. */ uvmfault_unlockall(ufi, ufi->entry->aref.ar_amap, uobj); /* sync what we have so far */ pmap_update(ufi->orig_map->pmap); uvm_wait("udv_fault"); return (VM_PAGER_REFAULT); } } uvmfault_unlockall(ufi, ufi->entry->aref.ar_amap, uobj); pmap_update(ufi->orig_map->pmap); return (retval); }
351 314 351 312 255 515 23 11 9 13 9 4 226 285 246 142 59 73 78 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 /* $OpenBSD: socketvar.h,v 1.131 2024/05/17 19:11:14 mvs Exp $ */ /* $NetBSD: socketvar.h,v 1.18 1996/02/09 18:25:38 christos Exp $ */ /*- * Copyright (c) 1982, 1986, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)socketvar.h 8.1 (Berkeley) 6/2/93 */ #ifndef _SYS_SOCKETVAR_H_ #define _SYS_SOCKETVAR_H_ #include <sys/event.h> #include <sys/queue.h> #include <sys/sigio.h> /* for struct sigio_ref */ #include <sys/task.h> #include <sys/timeout.h> #include <sys/mutex.h> #include <sys/rwlock.h> #include <sys/refcnt.h> #ifndef _SOCKLEN_T_DEFINED_ #define _SOCKLEN_T_DEFINED_ typedef __socklen_t socklen_t; /* length type for network syscalls */ #endif TAILQ_HEAD(soqhead, socket); /* * Kernel structure per socket. * Contains send and receive buffer queues, * handle on protocol and pointer to protocol * private data and error information. */ struct socket { const struct protosw *so_proto; /* protocol handle */ struct rwlock so_lock; /* this socket lock */ struct refcnt so_refcnt; /* references to this socket */ void *so_pcb; /* protocol control block */ u_int so_state; /* internal state flags SS_*, below */ short so_type; /* generic type, see socket.h */ short so_options; /* from socket call, see socket.h */ short so_linger; /* time to linger while closing */ /* * Variables for connection queueing. * Socket where accepts occur is so_head in all subsidiary sockets. * If so_head is 0, socket is not related to an accept. * For head socket so_q0 queues partially completed connections, * while so_q is a queue of connections ready to be accepted. * If a connection is aborted and it has so_head set, then * it has to be pulled out of either so_q0 or so_q. * We allow connections to queue up based on current queue lengths * and limit on number of queued connections for this socket. */ struct socket *so_head; /* back pointer to accept socket */ struct soqhead *so_onq; /* queue (q or q0) that we're on */ struct soqhead so_q0; /* queue of partial connections */ struct soqhead so_q; /* queue of incoming connections */ struct sigio_ref so_sigio; /* async I/O registration */ TAILQ_ENTRY(socket) so_qe; /* our queue entry (q or q0) */ short so_q0len; /* partials on so_q0 */ short so_qlen; /* number of connections on so_q */ short so_qlimit; /* max number queued connections */ short so_timeo; /* connection timeout */ u_long so_oobmark; /* chars to oob mark */ u_int so_error; /* error affecting connection */ /* * Variables for socket splicing, allocated only when needed. */ struct sosplice { struct socket *ssp_socket; /* send data to drain socket */ struct socket *ssp_soback; /* back ref to source socket */ off_t ssp_len; /* number of bytes spliced */ off_t ssp_max; /* maximum number of bytes */ struct timeval ssp_idletv; /* idle timeout */ struct timeout ssp_idleto; struct task ssp_task; /* task for somove */ } *so_sp; /* * Variables for socket buffering. */ struct sockbuf { struct rwlock sb_lock; struct mutex sb_mtx; /* The following fields are all zeroed on flush. */ #define sb_startzero sb_cc u_long sb_cc; /* actual chars in buffer */ u_long sb_datacc; /* data only chars in buffer */ u_long sb_hiwat; /* max actual char count */ u_long sb_wat; /* default watermark */ u_long sb_mbcnt; /* chars of mbufs used */ u_long sb_mbmax; /* max chars of mbufs to use */ long sb_lowat; /* low water mark */ struct mbuf *sb_mb; /* the mbuf chain */ struct mbuf *sb_mbtail; /* the last mbuf in the chain */ struct mbuf *sb_lastrecord;/* first mbuf of last record in socket buffer */ short sb_flags; /* flags, see below */ /* End area that is zeroed on flush. */ #define sb_endzero sb_flags short sb_state; /* socket state on sockbuf */ uint64_t sb_timeo_nsecs;/* timeout for read/write */ struct klist sb_klist; /* process selecting read/write */ } so_rcv, so_snd; #define SB_MAX (2*1024*1024) /* default for max chars in sockbuf */ #define SB_WAIT 0x0001 /* someone is waiting for data/space */ #define SB_ASYNC 0x0002 /* ASYNC I/O, need signals */ #define SB_SPLICE 0x0004 /* buffer is splice source or drain */ #define SB_NOINTR 0x0008 /* operations not interruptible */ #define SB_MTXLOCK 0x0010 /* sblock() doesn't need solock() */ void (*so_upcall)(struct socket *so, caddr_t arg, int waitf); caddr_t so_upcallarg; /* Arg for above */ uid_t so_euid, so_ruid; /* who opened the socket */ gid_t so_egid, so_rgid; pid_t so_cpid; /* pid of process that opened socket */ }; /* * Socket state bits. * * NOTE: The following states should be used with corresponding socket's * buffer `sb_state' only: * * SS_CANTSENDMORE with `so_snd' * SS_ISSENDING with `so_snd' * SS_CANTRCVMORE with `so_rcv' * SS_RCVATMARK with `so_rcv' */ #define SS_NOFDREF 0x001 /* no file table ref any more */ #define SS_ISCONNECTED 0x002 /* socket connected to a peer */ #define SS_ISCONNECTING 0x004 /* in process of connecting to peer */ #define SS_ISDISCONNECTING 0x008 /* in process of disconnecting */ #define SS_CANTSENDMORE 0x010 /* can't send more data to peer */ #define SS_CANTRCVMORE 0x020 /* can't receive more data from peer */ #define SS_RCVATMARK 0x040 /* at mark on input */ #define SS_ISDISCONNECTED 0x800 /* socket disconnected from peer */ #define SS_PRIV 0x080 /* privileged for broadcast, raw... */ #define SS_CONNECTOUT 0x1000 /* connect, not accept, at this end */ #define SS_ISSENDING 0x2000 /* hint for lower layer */ #define SS_DNS 0x4000 /* created using SOCK_DNS socket(2) */ #define SS_YP 0x8000 /* created using ypconnect(2) */ #ifdef _KERNEL #include <sys/protosw.h> #include <lib/libkern/libkern.h> void soassertlocked(struct socket *); void soassertlocked_readonly(struct socket *); static inline void soref(struct socket *so) { refcnt_take(&so->so_refcnt); } static inline void sorele(struct socket *so) { refcnt_rele_wake(&so->so_refcnt); } /* * Macros for sockets and socket buffering. */ #define isspliced(so) ((so)->so_sp && (so)->so_sp->ssp_socket) #define issplicedback(so) ((so)->so_sp && (so)->so_sp->ssp_soback) static inline void sb_mtx_lock(struct sockbuf *sb) { if (sb->sb_flags & SB_MTXLOCK) mtx_enter(&sb->sb_mtx); } static inline void sb_mtx_unlock(struct sockbuf *sb) { if (sb->sb_flags & SB_MTXLOCK) mtx_leave(&sb->sb_mtx); } void sbmtxassertlocked(struct socket *so, struct sockbuf *); /* * Do we need to notify the other side when I/O is possible? */ static inline int sb_notify(struct socket *so, struct sockbuf *sb) { int rv; soassertlocked(so); mtx_enter(&sb->sb_mtx); rv = ((sb->sb_flags & (SB_WAIT|SB_ASYNC|SB_SPLICE)) != 0 || !klist_empty(&sb->sb_klist)); mtx_leave(&sb->sb_mtx); return rv; } /* * How much space is there in a socket buffer (so->so_snd or so->so_rcv)? * This is problematical if the fields are unsigned, as the space might * still be negative (cc > hiwat or mbcnt > mbmax). Should detect * overflow and return 0. */ static inline long sbspace(struct socket *so, struct sockbuf *sb) { if (sb->sb_flags & SB_MTXLOCK) sbmtxassertlocked(so, sb); else soassertlocked_readonly(so); return lmin(sb->sb_hiwat - sb->sb_cc, sb->sb_mbmax - sb->sb_mbcnt); } /* do we have to send all at once on a socket? */ #define sosendallatonce(so) \ ((so)->so_proto->pr_flags & PR_ATOMIC) /* are we sending on this socket? */ #define soissending(so) \ ((so)->so_snd.sb_state & SS_ISSENDING) /* can we read something from so? */ static inline int soreadable(struct socket *so) { soassertlocked_readonly(so); if (isspliced(so)) return 0; return (so->so_rcv.sb_state & SS_CANTRCVMORE) || so->so_qlen || so->so_error || so->so_rcv.sb_cc >= so->so_rcv.sb_lowat; } /* can we write something to so? */ static inline int sowriteable(struct socket *so) { soassertlocked_readonly(so); return ((sbspace(so, &so->so_snd) >= so->so_snd.sb_lowat && ((so->so_state & SS_ISCONNECTED) || (so->so_proto->pr_flags & PR_CONNREQUIRED)==0)) || (so->so_snd.sb_state & SS_CANTSENDMORE) || so->so_error); } /* adjust counters in sb reflecting allocation of m */ static inline void sballoc(struct socket *so, struct sockbuf *sb, struct mbuf *m) { sb->sb_cc += m->m_len; if (m->m_type != MT_CONTROL && m->m_type != MT_SONAME) sb->sb_datacc += m->m_len; sb->sb_mbcnt += MSIZE; if (m->m_flags & M_EXT) sb->sb_mbcnt += m->m_ext.ext_size; } /* adjust counters in sb reflecting freeing of m */ static inline void sbfree(struct socket *so, struct sockbuf *sb, struct mbuf *m) { sb->sb_cc -= m->m_len; if (m->m_type != MT_CONTROL && m->m_type != MT_SONAME) sb->sb_datacc -= m->m_len; sb->sb_mbcnt -= MSIZE; if (m->m_flags & M_EXT) sb->sb_mbcnt -= m->m_ext.ext_size; } /* * Flags to sblock() */ #define SBL_WAIT 0x01 /* Wait if lock not immediately available. */ #define SBL_NOINTR 0x02 /* Enforce non-interruptible sleep. */ /* * Set lock on sockbuf sb; sleep if lock is already held. * Unless SB_NOINTR is set on sockbuf or SBL_NOINTR passed, * sleep is interruptible. Returns error without lock if * sleep is interrupted. */ int sblock(struct sockbuf *, int); /* release lock on sockbuf sb */ void sbunlock(struct sockbuf *); #define SB_EMPTY_FIXUP(sb) do { \ if ((sb)->sb_mb == NULL) { \ (sb)->sb_mbtail = NULL; \ (sb)->sb_lastrecord = NULL; \ } \ } while (/*CONSTCOND*/0) extern u_long sb_max; extern struct pool socket_pool; struct mbuf; struct sockaddr; struct proc; struct msghdr; struct stat; struct knote; /* * File operations on sockets. */ int soo_read(struct file *, struct uio *, int); int soo_write(struct file *, struct uio *, int); int soo_ioctl(struct file *, u_long, caddr_t, struct proc *); int soo_kqfilter(struct file *, struct knote *); int soo_close(struct file *, struct proc *); int soo_stat(struct file *, struct stat *, struct proc *); void sbappend(struct socket *, struct sockbuf *, struct mbuf *); void sbappendstream(struct socket *, struct sockbuf *, struct mbuf *); int sbappendaddr(struct socket *, struct sockbuf *, const struct sockaddr *, struct mbuf *, struct mbuf *); int sbappendcontrol(struct socket *, struct sockbuf *, struct mbuf *, struct mbuf *); void sbappendrecord(struct socket *, struct sockbuf *, struct mbuf *); void sbcompress(struct socket *, struct sockbuf *, struct mbuf *, struct mbuf *); struct mbuf * sbcreatecontrol(const void *, size_t, int, int); void sbdrop(struct socket *, struct sockbuf *, int); void sbdroprecord(struct socket *, struct sockbuf *); void sbflush(struct socket *, struct sockbuf *); void sbrelease(struct socket *, struct sockbuf *); int sbcheckreserve(u_long, u_long); int sbchecklowmem(void); int sbreserve(struct socket *, struct sockbuf *, u_long); int sbwait(struct socket *, struct sockbuf *); void soinit(void); void soabort(struct socket *); int soaccept(struct socket *, struct mbuf *); int sobind(struct socket *, struct mbuf *, struct proc *); void socantrcvmore(struct socket *); void socantsendmore(struct socket *); int soclose(struct socket *, int); int soconnect(struct socket *, struct mbuf *); int soconnect2(struct socket *, struct socket *); int socreate(int, struct socket **, int, int); int sodisconnect(struct socket *); struct socket *soalloc(const struct protosw *, int); void sofree(struct socket *, int); int sogetopt(struct socket *, int, int, struct mbuf *); void sohasoutofband(struct socket *); void soisconnected(struct socket *); void soisconnecting(struct socket *); void soisdisconnected(struct socket *); void soisdisconnecting(struct socket *); int solisten(struct socket *, int); struct socket *sonewconn(struct socket *, int, int); void soqinsque(struct socket *, struct socket *, int); int soqremque(struct socket *, int); int soreceive(struct socket *, struct mbuf **, struct uio *, struct mbuf **, struct mbuf **, int *, socklen_t); int soreserve(struct socket *, u_long, u_long); int sosend(struct socket *, struct mbuf *, struct uio *, struct mbuf *, struct mbuf *, int); int sosetopt(struct socket *, int, int, struct mbuf *); int soshutdown(struct socket *, int); void sowakeup(struct socket *, struct sockbuf *); void sorwakeup(struct socket *); void sowwakeup(struct socket *); int sockargs(struct mbuf **, const void *, size_t, int); int sosleep_nsec(struct socket *, void *, int, const char *, uint64_t); void solock(struct socket *); void solock_shared(struct socket *); int solock_persocket(struct socket *); void solock_pair(struct socket *, struct socket *); void sounlock(struct socket *); void sounlock_shared(struct socket *); int sendit(struct proc *, int, struct msghdr *, int, register_t *); int recvit(struct proc *, int, struct msghdr *, caddr_t, register_t *); int doaccept(struct proc *, int, struct sockaddr *, socklen_t *, int, register_t *); #ifdef SOCKBUF_DEBUG void sblastrecordchk(struct sockbuf *, const char *); #define SBLASTRECORDCHK(sb, where) sblastrecordchk((sb), (where)) void sblastmbufchk(struct sockbuf *, const char *); #define SBLASTMBUFCHK(sb, where) sblastmbufchk((sb), (where)) void sbcheck(struct socket *, struct sockbuf *); #define SBCHECK(so, sb) sbcheck((so), (sb)) #else #define SBLASTRECORDCHK(sb, where) /* nothing */ #define SBLASTMBUFCHK(sb, where) /* nothing */ #define SBCHECK(so, sb) /* nothing */ #endif /* SOCKBUF_DEBUG */ #endif /* _KERNEL */ #endif /* _SYS_SOCKETVAR_H_ */
4 4 4 4 2 2 4 2 1 1 1 1 1 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 5 4 1 220 7 1 1 1 210 1 1 1 1 1 1 1 1 14 14 1 10 2 7 3 4 210 194 162 21 7 25 1 1 1 1 15 13 2 1 1 234 7 227 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 /* $OpenBSD: subr_disk.c,v 1.272 2023/11/15 20:23:19 kn Exp $ */ /* $NetBSD: subr_disk.c,v 1.17 1996/03/16 23:17:08 christos Exp $ */ /* * Copyright (c) 1995 Jason R. Thorpe. All rights reserved. * Copyright (c) 1982, 1986, 1988, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ufs_disksubr.c 8.5 (Berkeley) 1/21/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/fcntl.h> #include <sys/buf.h> #include <sys/stat.h> #include <sys/syslog.h> #include <sys/device.h> #include <sys/time.h> #include <sys/disklabel.h> #include <sys/conf.h> #include <sys/disk.h> #include <sys/reboot.h> #include <sys/dkio.h> #include <sys/vnode.h> #include <sys/task.h> #include <sys/stdint.h> #include <sys/socket.h> #include <net/if.h> #include <dev/cons.h> #include <lib/libz/zlib.h> #include "softraid.h" #ifdef DEBUG #define DPRINTF(x...) printf(x) #else #define DPRINTF(x...) #endif /* * A global list of all disks attached to the system. May grow or * shrink over time. */ struct disklist_head disklist; /* TAILQ_HEAD */ int disk_count; /* number of drives in global disklist */ int disk_change; /* set if a disk has been attached/detached * since last we looked at this variable. This * is reset by hw_sysctl() */ #define DUID_SIZE 8 u_char bootduid[DUID_SIZE]; /* DUID of boot disk. */ u_char rootduid[DUID_SIZE]; /* DUID of root disk. */ struct device *rootdv; /* softraid callback, do not use! */ void (*softraid_disk_attach)(struct disk *, int); void sr_map_root(void); struct disk_attach_task { struct task task; struct disk *dk; }; void disk_attach_callback(void *); int spoofgpt(struct buf *, void (*)(struct buf *), const uint8_t *, struct disklabel *, daddr_t *); void spoofmbr(struct buf *, void (*)(struct buf *), const uint8_t *, struct disklabel *, daddr_t *); void spooffat(const uint8_t *, struct disklabel *, daddr_t *); int gpt_chk_mbr(struct dos_partition *, uint64_t); int gpt_get_hdr(struct buf *, void (*)(struct buf *), struct disklabel *, uint64_t, struct gpt_header *); int gpt_get_parts(struct buf *, void (*)(struct buf *), struct disklabel *, const struct gpt_header *, struct gpt_partition **); int gpt_get_fstype(const struct uuid *); int mbr_get_fstype(const uint8_t); int duid_equal(u_char *, u_char *); /* * Compute checksum for disk label. */ u_int dkcksum(struct disklabel *lp) { u_int16_t *start, *end; u_int16_t sum = 0; start = (u_int16_t *)lp; end = (u_int16_t *)&lp->d_partitions[lp->d_npartitions]; while (start < end) sum ^= *start++; return (sum); } int initdisklabel(struct disklabel *lp) { int i; /* minimal requirements for archetypal disk label */ if (lp->d_secsize < DEV_BSIZE) lp->d_secsize = DEV_BSIZE; if (DL_GETDSIZE(lp) == 0) DL_SETDSIZE(lp, MAXDISKSIZE); if (lp->d_secpercyl == 0) return (ERANGE); lp->d_npartitions = MAXPARTITIONS; for (i = 0; i < RAW_PART; i++) { DL_SETPSIZE(&lp->d_partitions[i], 0); DL_SETPOFFSET(&lp->d_partitions[i], 0); } if (DL_GETPSIZE(&lp->d_partitions[RAW_PART]) == 0) DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp)); DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0); DL_SETBSTART(lp, 0); DL_SETBEND(lp, DL_GETDSIZE(lp)); lp->d_version = 1; return (0); } /* * Check an incoming block to make sure it is a disklabel, convert it to * a newer version if needed, etc etc. */ int checkdisklabel(dev_t dev, void *rlp, struct disklabel *lp, u_int64_t boundstart, u_int64_t boundend) { struct disklabel *dlp = rlp; struct __partitionv0 *v0pp; struct partition *pp; const char *blkname; u_int64_t disksize; int error = 0; int i; if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) error = ENOENT; /* no disk label */ else if (dlp->d_npartitions > MAXPARTITIONS) error = E2BIG; /* too many partitions */ else if (dlp->d_secpercyl == 0) error = EINVAL; /* invalid label */ else if (dlp->d_secsize == 0) error = ENOSPC; /* disk too small */ else if (dkcksum(dlp) != 0) error = EINVAL; /* incorrect checksum */ if (error) { u_int16_t *start, *end, sum = 0; /* If it is byte-swapped, attempt to convert it */ if (swap32(dlp->d_magic) != DISKMAGIC || swap32(dlp->d_magic2) != DISKMAGIC || swap16(dlp->d_npartitions) > MAXPARTITIONS) return (error); /* * Need a byte-swap aware dkcksum variant * inlined, because dkcksum uses a sub-field */ start = (u_int16_t *)dlp; end = (u_int16_t *)&dlp->d_partitions[ swap16(dlp->d_npartitions)]; while (start < end) sum ^= *start++; if (sum != 0) return (error); dlp->d_magic = swap32(dlp->d_magic); dlp->d_type = swap16(dlp->d_type); /* d_typename and d_packname are strings */ dlp->d_secsize = swap32(dlp->d_secsize); dlp->d_nsectors = swap32(dlp->d_nsectors); dlp->d_ntracks = swap32(dlp->d_ntracks); dlp->d_ncylinders = swap32(dlp->d_ncylinders); dlp->d_secpercyl = swap32(dlp->d_secpercyl); dlp->d_secperunit = swap32(dlp->d_secperunit); /* d_uid is a string */ dlp->d_acylinders = swap32(dlp->d_acylinders); dlp->d_flags = swap32(dlp->d_flags); dlp->d_secperunith = swap16(dlp->d_secperunith); dlp->d_version = swap16(dlp->d_version); for (i = 0; i < NSPARE; i++) dlp->d_spare[i] = swap32(dlp->d_spare[i]); dlp->d_magic2 = swap32(dlp->d_magic2); dlp->d_npartitions = swap16(dlp->d_npartitions); for (i = 0; i < MAXPARTITIONS; i++) { pp = &dlp->d_partitions[i]; pp->p_size = swap32(pp->p_size); pp->p_offset = swap32(pp->p_offset); if (dlp->d_version == 0) { v0pp = (struct __partitionv0 *)pp; v0pp->p_fsize = swap32(v0pp->p_fsize); } else { pp->p_offseth = swap16(pp->p_offseth); pp->p_sizeh = swap16(pp->p_sizeh); } pp->p_cpg = swap16(pp->p_cpg); } dlp->d_checksum = 0; dlp->d_checksum = dkcksum(dlp); error = 0; } /* XXX should verify lots of other fields and whine a lot */ /* Initial passed in lp contains the real disk size. */ disksize = DL_GETDSIZE(lp); if (lp != dlp) *lp = *dlp; if (lp->d_version == 0) { blkname = findblkname(major(dev)); if (blkname == NULL) blkname = findblkname(major(chrtoblk(dev))); printf("%s%d has legacy label, please rewrite using " "disklabel(8)\n", blkname, DISKUNIT(dev)); lp->d_version = 1; lp->d_secperunith = 0; v0pp = (struct __partitionv0 *)lp->d_partitions; pp = lp->d_partitions; for (i = 0; i < lp->d_npartitions; i++, pp++, v0pp++) { pp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(v0pp-> p_fsize, v0pp->p_frag); pp->p_offseth = 0; pp->p_sizeh = 0; } } #ifdef DEBUG if (DL_GETDSIZE(lp) != disksize) printf("on-disk disklabel has incorrect disksize (%llu)\n", DL_GETDSIZE(lp)); if (DL_GETPSIZE(&lp->d_partitions[RAW_PART]) != disksize) printf("on-disk disklabel RAW_PART has incorrect size (%llu)\n", DL_GETPSIZE(&lp->d_partitions[RAW_PART])); if (DL_GETPOFFSET(&lp->d_partitions[RAW_PART]) != 0) printf("on-disk disklabel RAW_PART offset != 0 (%llu)\n", DL_GETPOFFSET(&lp->d_partitions[RAW_PART])); #endif DL_SETDSIZE(lp, disksize); DL_SETPSIZE(&lp->d_partitions[RAW_PART], disksize); DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0); DL_SETBSTART(lp, boundstart); DL_SETBEND(lp, boundend < DL_GETDSIZE(lp) ? boundend : DL_GETDSIZE(lp)); lp->d_checksum = 0; lp->d_checksum = dkcksum(lp); return (0); } /* * Read a disk sector. */ int readdisksector(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp, u_int64_t sector) { bp->b_blkno = DL_SECTOBLK(lp, sector); bp->b_bcount = lp->d_secsize; bp->b_error = 0; CLR(bp->b_flags, B_READ | B_WRITE | B_DONE | B_ERROR); SET(bp->b_flags, B_BUSY | B_READ | B_RAW); (*strat)(bp); return (biowait(bp)); } int readdoslabel(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp, daddr_t *partoffp, int spoofonly) { uint8_t dosbb[DEV_BSIZE]; struct disklabel nlp; struct disklabel *rlp; daddr_t partoff; int error; #ifdef DEBUG char devname[32]; const char *blkname; blkname = findblkname(major(bp->b_dev)); if (blkname == NULL) blkname = findblkname(major(chrtoblk(bp->b_dev))); if (blkname == NULL) snprintf(devname, sizeof(devname), "<%d, %d>", major(bp->b_dev), minor(bp->b_dev)); else snprintf(devname, sizeof(devname), "%s%d", blkname, DISKUNIT(bp->b_dev)); printf("readdoslabel enter: %s, spoofonly %d, partoffp %sNULL\n", devname, spoofonly, (partoffp == NULL) ? "" : "not "); #endif /* DEBUG */ error = readdisksector(bp, strat, lp, DOSBBSECTOR); if (error) { DPRINTF("readdoslabel return: %s, %d -- lp unchanged, " "DOSBBSECTOR read error\n", devname, error); return error; } memcpy(dosbb, bp->b_data, sizeof(dosbb)); nlp = *lp; memset(nlp.d_partitions, 0, sizeof(nlp.d_partitions)); nlp.d_partitions[RAW_PART] = lp->d_partitions[RAW_PART]; nlp.d_magic = 0; error = spoofgpt(bp, strat, dosbb, &nlp, &partoff); if (error) return error; if (nlp.d_magic != DISKMAGIC) spoofmbr(bp, strat, dosbb, &nlp, &partoff); if (nlp.d_magic != DISKMAGIC) spooffat(dosbb, &nlp, &partoff); if (nlp.d_magic != DISKMAGIC) { DPRINTF("readdoslabel: N/A -- label partition @ " "daddr_t 0 (default)\n"); partoff = 0; } if (partoffp != NULL) { /* * If a non-zero value is returned writedisklabel() exits with * EIO. If 0 is returned the label sector is read from disk and * lp is copied into it. So leave lp alone! */ if (partoff == -1) { DPRINTF("readdoslabel return: %s, ENXIO, lp " "unchanged, *partoffp unchanged\n", devname); return ENXIO; } *partoffp = partoff; DPRINTF("readdoslabel return: %s, 0, lp unchanged, " "*partoffp set to %lld\n", devname, *partoffp); return 0; } nlp.d_magic = lp->d_magic; *lp = nlp; lp->d_checksum = 0; lp->d_checksum = dkcksum(lp); if (spoofonly || partoff == -1) { DPRINTF("readdoslabel return: %s, 0, lp spoofed\n", devname); return 0; } partoff += DOS_LABELSECTOR; error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp, partoff)); if (error) { DPRINTF("readdoslabel return: %s, %d, lp read failed\n", devname, error); return bp->b_error; } rlp = (struct disklabel *)(bp->b_data + DL_BLKOFFSET(lp, partoff)); error = checkdisklabel(bp->b_dev, rlp, lp, DL_GETBSTART(rlp), DL_GETBEND(rlp)); DPRINTF("readdoslabel return: %s, %d, checkdisklabel() of daddr_t " "%lld %s\n", devname, error, partoff, error ? "failed" : "ok"); return error; } /* * Return the index into dp[] of the EFI GPT (0xEE) partition, or -1 if no such * partition exists. * * Copied into sbin/fdisk/mbr.c. */ int gpt_chk_mbr(struct dos_partition *dp, uint64_t dsize) { struct dos_partition *dp2; int efi, eficnt, found, i; uint32_t psize; found = efi = eficnt = 0; for (dp2 = dp, i = 0; i < NDOSPART; i++, dp2++) { if (dp2->dp_typ == DOSPTYP_UNUSED) continue; found++; if (dp2->dp_typ != DOSPTYP_EFI) continue; if (letoh32(dp2->dp_start) != GPTSECTOR) continue; psize = letoh32(dp2->dp_size); if (psize <= (dsize - GPTSECTOR) || psize == UINT32_MAX) { efi = i; eficnt++; } } if (found == 1 && eficnt == 1) return (efi); return (-1); } int gpt_get_hdr(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp, uint64_t sector, struct gpt_header *gh) { struct gpt_header ngh; int error; uint64_t lbaend, lbastart; uint32_t csum; uint32_t size, partsize; error = readdisksector(bp, strat, lp, sector); if (error) return error; memcpy(&ngh, bp->b_data, sizeof(ngh)); size = letoh32(ngh.gh_size); partsize = letoh32(ngh.gh_part_size); lbaend = letoh64(ngh.gh_lba_end); lbastart = letoh64(ngh.gh_lba_start); csum = ngh.gh_csum; ngh.gh_csum = 0; ngh.gh_csum = htole32(crc32(0, (unsigned char *)&ngh, GPTMINHDRSIZE)); if (letoh64(ngh.gh_sig) == GPTSIGNATURE && letoh32(ngh.gh_rev) == GPTREVISION && size == GPTMINHDRSIZE && lbastart <= lbaend && partsize == GPTMINPARTSIZE && lp->d_secsize % partsize == 0 && csum == ngh.gh_csum) *gh = ngh; else memset(gh, 0, sizeof(*gh)); return 0; } int gpt_get_parts(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp, const struct gpt_header *gh, struct gpt_partition **gp) { uint8_t *ngp; int error, i; uint64_t bytes, partlba, sectors; uint32_t partnum, partsize, partcsum; partlba = letoh64(gh->gh_part_lba); partnum = letoh32(gh->gh_part_num); partsize = letoh32(gh->gh_part_size); sectors = ((uint64_t)partnum * partsize + lp->d_secsize - 1) / lp->d_secsize; ngp = mallocarray(sectors, lp->d_secsize, M_DEVBUF, M_NOWAIT | M_ZERO); if (ngp == NULL) { *gp = NULL; return ENOMEM; } bytes = sectors * lp->d_secsize; for (i = 0; i < sectors; i++) { error = readdisksector(bp, strat, lp, partlba + i); if (error) { free(ngp, M_DEVBUF, bytes); *gp = NULL; return error; } memcpy(ngp + i * lp->d_secsize, bp->b_data, lp->d_secsize); } partcsum = htole32(crc32(0, ngp, partnum * partsize)); if (partcsum != gh->gh_part_csum) { DPRINTF("invalid %s GPT partition array @ %llu\n", (letoh64(gh->gh_lba_self) == GPTSECTOR) ? "Primary" : "Secondary", partlba); free(ngp, M_DEVBUF, bytes); *gp = NULL; } else { *gp = (struct gpt_partition *)ngp; } return 0; } int gpt_get_fstype(const struct uuid *uuid_part) { static int init = 0; static struct uuid uuid_openbsd, uuid_msdos, uuid_chromefs, uuid_linux, uuid_hfs, uuid_unused, uuid_efi_system, uuid_bios_boot; static const uint8_t gpt_uuid_openbsd[] = GPT_UUID_OPENBSD; static const uint8_t gpt_uuid_msdos[] = GPT_UUID_MSDOS; static const uint8_t gpt_uuid_chromerootfs[] = GPT_UUID_CHROMEROOTFS; static const uint8_t gpt_uuid_linux[] = GPT_UUID_LINUX; static const uint8_t gpt_uuid_hfs[] = GPT_UUID_APPLE_HFS; static const uint8_t gpt_uuid_unused[] = GPT_UUID_UNUSED; static const uint8_t gpt_uuid_efi_system[] = GPT_UUID_EFI_SYSTEM; static const uint8_t gpt_uuid_bios_boot[] = GPT_UUID_BIOS_BOOT; if (init == 0) { uuid_dec_be(gpt_uuid_openbsd, &uuid_openbsd); uuid_dec_be(gpt_uuid_msdos, &uuid_msdos); uuid_dec_be(gpt_uuid_chromerootfs, &uuid_chromefs); uuid_dec_be(gpt_uuid_linux, &uuid_linux); uuid_dec_be(gpt_uuid_hfs, &uuid_hfs); uuid_dec_be(gpt_uuid_unused, &uuid_unused); uuid_dec_be(gpt_uuid_efi_system, &uuid_efi_system); uuid_dec_be(gpt_uuid_bios_boot, &uuid_bios_boot); init = 1; } if (!memcmp(uuid_part, &uuid_unused, sizeof(struct uuid))) return FS_UNUSED; else if (!memcmp(uuid_part, &uuid_openbsd, sizeof(struct uuid))) return FS_BSDFFS; else if (!memcmp(uuid_part, &uuid_msdos, sizeof(struct uuid))) return FS_MSDOS; else if (!memcmp(uuid_part, &uuid_chromefs, sizeof(struct uuid))) return FS_EXT2FS; else if (!memcmp(uuid_part, &uuid_linux, sizeof(struct uuid))) return FS_EXT2FS; else if (!memcmp(uuid_part, &uuid_hfs, sizeof(struct uuid))) return FS_HFS; else if (!memcmp(uuid_part, &uuid_efi_system, sizeof(struct uuid))) return FS_MSDOS; else if (!memcmp(uuid_part, &uuid_bios_boot, sizeof(struct uuid))) return FS_BOOT; else return FS_OTHER; } int spoofgpt(struct buf *bp, void (*strat)(struct buf *), const uint8_t *dosbb, struct disklabel *lp, daddr_t *partoffp) { struct dos_partition dp[NDOSPART]; struct gpt_header gh; struct uuid gptype; struct gpt_partition *gp; struct partition *pp; uint64_t lbaend, lbastart, labelsec; uint64_t gpbytes, end, start; daddr_t partoff; unsigned int i, n; int error, fstype, obsdfound; uint32_t partnum; uint16_t sig; gp = NULL; gpbytes = 0; memcpy(dp, dosbb + DOSPARTOFF, sizeof(dp)); memcpy(&sig, dosbb + DOSMBR_SIGNATURE_OFF, sizeof(sig)); if (letoh16(sig) != DOSMBR_SIGNATURE || gpt_chk_mbr(dp, DL_GETDSIZE(lp)) == -1) return 0; error = gpt_get_hdr(bp, strat, lp, GPTSECTOR, &gh); if (error == 0 && letoh64(gh.gh_sig) == GPTSIGNATURE) error = gpt_get_parts(bp, strat, lp, &gh, &gp); if (error || letoh64(gh.gh_sig) != GPTSIGNATURE || gp == NULL) { error = gpt_get_hdr(bp, strat, lp, DL_GETDSIZE(lp) - 1, &gh); if (error == 0 && letoh64(gh.gh_sig) == GPTSIGNATURE) error = gpt_get_parts(bp, strat, lp, &gh, &gp); } if (error) return error; if (gp == NULL) return ENXIO; lbastart = letoh64(gh.gh_lba_start); lbaend = letoh64(gh.gh_lba_end); partnum = letoh32(gh.gh_part_num); n = 'i' - 'a'; /* Start spoofing at 'i', a.k.a. 8. */ DL_SETBSTART(lp, lbastart); DL_SETBEND(lp, lbaend + 1); partoff = DL_SECTOBLK(lp, lbastart); obsdfound = 0; for (i = 0; i < partnum; i++) { if (letoh64(gp[i].gp_attrs) & GPTPARTATTR_REQUIRED) { DPRINTF("spoofgpt: Skipping partition %u (REQUIRED)\n", i); continue; } start = letoh64(gp[i].gp_lba_start); if (start > lbaend || start < lbastart) continue; end = letoh64(gp[i].gp_lba_end); if (start > end) continue; uuid_dec_le(&gp[i].gp_type, &gptype); fstype = gpt_get_fstype(&gptype); if (obsdfound && fstype == FS_BSDFFS) continue; if (fstype == FS_BSDFFS) { obsdfound = 1; partoff = DL_SECTOBLK(lp, start); labelsec = DL_BLKTOSEC(lp, partoff + DOS_LABELSECTOR); if (labelsec > ((end < lbaend) ? end : lbaend)) partoff = -1; DL_SETBSTART(lp, start); DL_SETBEND(lp, end + 1); continue; } if (partoff != -1) { labelsec = DL_BLKTOSEC(lp, partoff + DOS_LABELSECTOR); if (labelsec >= start && labelsec <= end) partoff = -1; } if (n < MAXPARTITIONS && end <= lbaend) { pp = &lp->d_partitions[n]; n++; pp->p_fstype = fstype; DL_SETPOFFSET(pp, start); DL_SETPSIZE(pp, end - start + 1); } } lp->d_magic = DISKMAGIC; *partoffp = partoff; free(gp, M_DEVBUF, gpbytes); #ifdef DEBUG printf("readdoslabel: GPT -- "); if (partoff == -1) printf("no label partition\n"); else if (obsdfound == 0) printf("label partition @ daddr_t %lld (free space)\n", partoff); else printf("label partition @ daddr_t %lld (A6)\n", partoff); #endif /* DEBUG */ return 0; } int mbr_get_fstype(const uint8_t dp_typ) { switch (dp_typ) { case DOSPTYP_OPENBSD: return FS_BSDFFS; case DOSPTYP_UNUSED: return FS_UNUSED; case DOSPTYP_LINUX: return FS_EXT2FS; case DOSPTYP_NTFS: return FS_NTFS; case DOSPTYP_EFISYS: case DOSPTYP_FAT12: case DOSPTYP_FAT16S: case DOSPTYP_FAT16B: case DOSPTYP_FAT16L: case DOSPTYP_FAT32: case DOSPTYP_FAT32L: return FS_MSDOS; case DOSPTYP_EFI: case DOSPTYP_EXTEND: case DOSPTYP_EXTENDL: default: return FS_OTHER; } } void spoofmbr(struct buf *bp, void (*strat)(struct buf *), const uint8_t *dosbb, struct disklabel *lp, daddr_t *partoffp) { struct dos_partition dp[NDOSPART]; struct partition *pp; uint64_t sector = DOSBBSECTOR; uint64_t start, end; daddr_t labeloff, partoff; unsigned int i, n, parts; int wander = 1, ebr = 0; int error, obsdfound; uint32_t extoff = 0; uint16_t sig; uint8_t fstype; memcpy(&sig, dosbb + DOSMBR_SIGNATURE_OFF, sizeof(sig)); if (letoh16(sig) != DOSMBR_SIGNATURE) return; memcpy(dp, dosbb + DOSPARTOFF, sizeof(dp)); obsdfound = 0; partoff = 0; parts = 0; n = 'i' - 'a'; while (wander && ebr < DOS_MAXEBR) { ebr++; wander = 0; if (sector < extoff) sector = extoff; error = 0; if (sector != DOSBBSECTOR) { error = readdisksector(bp, strat, lp, sector); if (error) break; memcpy(&sig, bp->b_data + DOSMBR_SIGNATURE_OFF, sizeof(sig)); if (letoh16(sig) != DOSMBR_SIGNATURE) break; memcpy(dp, bp->b_data + DOSPARTOFF, sizeof(dp)); } for (i = 0; i < NDOSPART; i++) { if (letoh32(dp[i].dp_size) == 0) continue; if (obsdfound && dp[i].dp_typ == DOSPTYP_OPENBSD) continue; if (dp[i].dp_typ != DOSPTYP_OPENBSD) { if (letoh32(dp[i].dp_start) > DL_GETDSIZE(lp)) continue; if (letoh32(dp[i].dp_size) > DL_GETDSIZE(lp)) continue; } start = sector + letoh32(dp[i].dp_start); end = start + letoh32(dp[i].dp_size); parts++; if (obsdfound == 0) { labeloff = partoff + DOS_LABELSECTOR; if (labeloff >= DL_SECTOBLK(lp, start) && labeloff < DL_SECTOBLK(lp, end)) partoff = -1; } switch (dp[i].dp_typ) { case DOSPTYP_OPENBSD: obsdfound = 1; partoff = DL_SECTOBLK(lp, start); labeloff = partoff + DOS_LABELSECTOR; if (labeloff >= DL_SECTOBLK(lp, end)) partoff = -1; DL_SETBSTART(lp, start); DL_SETBEND(lp, end); continue; case DOSPTYP_EFI: continue; case DOSPTYP_EXTEND: case DOSPTYP_EXTENDL: sector = start + extoff; if (extoff == 0) { extoff = start; sector = 0; } wander = 1; continue; default: break; } fstype = mbr_get_fstype(dp[i].dp_typ); if (n < MAXPARTITIONS) { pp = &lp->d_partitions[n++]; pp->p_fstype = fstype; if (start) DL_SETPOFFSET(pp, start); DL_SETPSIZE(pp, end - start); } } } if (parts > 0) { lp->d_magic = DISKMAGIC; *partoffp = partoff; #ifdef DEBUG printf("readdoslabel: MBR -- "); if (partoff == -1) printf("no label partition\n"); else if (obsdfound == 0) printf("label partition @ daddr_t %lld (free space)\n", partoff); else printf("label partition @ daddr_t %lld (A6)\n", partoff); #endif /* DEBUG */ } } void spooffat(const uint8_t *dosbb, struct disklabel *lp, daddr_t *partoffp) { uint16_t secsize; #define VALID_JMP(_p) (((_p)[0] == 0xeb && (_p)[2] == 0x90) || (_p)[0] == 0xe9) #define VALID_FAT(_p) ((_p)[16] == 1 || (_p)[16] == 2) #define VALID_SEC(_s) ((_s) >= DEV_BSIZE && (_s) <= 4096 && ((_s) % 512 == 0)) memcpy(&secsize, dosbb + 11, sizeof(secsize)); secsize = letoh16(secsize); if (VALID_JMP(dosbb) && VALID_SEC(secsize) && VALID_FAT(dosbb)) { lp->d_partitions['i' - 'a'] = lp->d_partitions[RAW_PART]; lp->d_partitions['i' - 'a'].p_fstype = FS_MSDOS; *partoffp = -1; lp->d_magic = DISKMAGIC; DPRINTF("readdoslabel: FAT -- no label partition\n"); } } /* * Check new disk label for sensibility before setting it. */ int setdisklabel(struct disklabel *olp, struct disklabel *nlp, u_int openmask) { struct partition *opp, *npp; struct disk *dk; int i; /* sanity clause */ if (nlp->d_secpercyl == 0 || nlp->d_secsize == 0 || (nlp->d_secsize % DEV_BSIZE) != 0) return (EINVAL); /* special case to allow disklabel to be invalidated */ if (nlp->d_magic == 0xffffffff) { *olp = *nlp; return (0); } if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC || dkcksum(nlp) != 0) return (EINVAL); /* XXX missing check if other dos partitions will be overwritten */ for (i = 0; i < MAXPARTITIONS; i++) { opp = &olp->d_partitions[i]; npp = &nlp->d_partitions[i]; if ((openmask & (1 << i)) && (DL_GETPOFFSET(npp) != DL_GETPOFFSET(opp) || DL_GETPSIZE(npp) < DL_GETPSIZE(opp))) return (EBUSY); /* * Copy internally-set partition information * if new label doesn't include it. XXX */ if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) { npp->p_fragblock = opp->p_fragblock; npp->p_cpg = opp->p_cpg; } } /* Generate a UID if the disklabel does not already have one. */ if (duid_iszero(nlp->d_uid)) { do { arc4random_buf(nlp->d_uid, sizeof(nlp->d_uid)); TAILQ_FOREACH(dk, &disklist, dk_link) if (dk->dk_label && duid_equal(dk->dk_label->d_uid, nlp->d_uid)) break; } while (dk != NULL || duid_iszero(nlp->d_uid)); } /* Preserve the disk size and RAW_PART values. */ DL_SETDSIZE(nlp, DL_GETDSIZE(olp)); npp = &nlp->d_partitions[RAW_PART]; DL_SETPOFFSET(npp, 0); DL_SETPSIZE(npp, DL_GETDSIZE(nlp)); nlp->d_checksum = 0; nlp->d_checksum = dkcksum(nlp); *olp = *nlp; disk_change = 1; return (0); } /* * Determine the size of the transfer, and make sure it is within the * boundaries of the partition. Adjust transfer if needed, and signal errors or * early completion. */ int bounds_check_with_label(struct buf *bp, struct disklabel *lp) { struct partition *p = &lp->d_partitions[DISKPART(bp->b_dev)]; daddr_t partblocks, sz; /* Avoid division by zero, negative offsets, and negative sizes. */ if (lp->d_secpercyl == 0 || bp->b_blkno < 0 || bp->b_bcount < 0) goto bad; /* Ensure transfer is a whole number of aligned sectors. */ if ((bp->b_blkno % DL_BLKSPERSEC(lp)) != 0 || (bp->b_bcount % lp->d_secsize) != 0) goto bad; /* Ensure transfer starts within partition boundary. */ partblocks = DL_SECTOBLK(lp, DL_GETPSIZE(p)); if (bp->b_blkno > partblocks) goto bad; /* If exactly at end of partition or null transfer, return EOF. */ if (bp->b_blkno == partblocks || bp->b_bcount == 0) goto done; /* Truncate request if it extends past the end of the partition. */ sz = bp->b_bcount >> DEV_BSHIFT; if (sz > partblocks - bp->b_blkno) { sz = partblocks - bp->b_blkno; bp->b_bcount = sz << DEV_BSHIFT; } return (0); bad: bp->b_error = EINVAL; bp->b_flags |= B_ERROR; done: bp->b_resid = bp->b_bcount; return (-1); } /* * Disk error is the preface to plaintive error messages * about failing disk transfers. It prints messages of the form hp0g: hard error reading fsbn 12345 of 12344-12347 (hp0 bn %d cn %d tn %d sn %d) * if the offset of the error in the transfer and a disk label * are both available. blkdone should be -1 if the position of the error * is unknown; the disklabel pointer may be null from drivers that have not * been converted to use them. The message is printed with printf * if pri is LOG_PRINTF, otherwise it uses log at the specified priority. * The message should be completed (with at least a newline) with printf * or addlog, respectively. There is no trailing space. */ void diskerr(struct buf *bp, char *dname, char *what, int pri, int blkdone, struct disklabel *lp) { int unit = DISKUNIT(bp->b_dev), part = DISKPART(bp->b_dev); int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2))); char partname = 'a' + part; daddr_t sn; if (pri != LOG_PRINTF) { log(pri, "%s", ""); pr = addlog; } else pr = printf; (*pr)("%s%d%c: %s %sing fsbn ", dname, unit, partname, what, bp->b_flags & B_READ ? "read" : "writ"); sn = bp->b_blkno; if (bp->b_bcount <= DEV_BSIZE) (*pr)("%lld", (long long)sn); else { if (blkdone >= 0) { sn += blkdone; (*pr)("%lld of ", (long long)sn); } (*pr)("%lld-%lld", (long long)bp->b_blkno, (long long)(bp->b_blkno + (bp->b_bcount - 1) / DEV_BSIZE)); } if (lp && (blkdone >= 0 || bp->b_bcount <= lp->d_secsize)) { sn += DL_SECTOBLK(lp, DL_GETPOFFSET(&lp->d_partitions[part])); (*pr)(" (%s%d bn %lld; cn %lld", dname, unit, (long long)sn, (long long)(sn / DL_SECTOBLK(lp, lp->d_secpercyl))); sn %= DL_SECTOBLK(lp, lp->d_secpercyl); (*pr)(" tn %lld sn %lld)", (long long)(sn / DL_SECTOBLK(lp, lp->d_nsectors)), (long long)(sn % DL_SECTOBLK(lp, lp->d_nsectors))); } } /* * Initialize the disklist. Called by main() before autoconfiguration. */ void disk_init(void) { TAILQ_INIT(&disklist); disk_count = disk_change = 0; } int disk_construct(struct disk *diskp) { rw_init_flags(&diskp->dk_lock, "dklk", RWL_IS_VNODE); mtx_init(&diskp->dk_mtx, IPL_BIO); diskp->dk_flags |= DKF_CONSTRUCTED; return (0); } /* * Attach a disk. */ void disk_attach(struct device *dv, struct disk *diskp) { int majdev; KERNEL_ASSERT_LOCKED(); if (!ISSET(diskp->dk_flags, DKF_CONSTRUCTED)) disk_construct(diskp); /* * Allocate and initialize the disklabel structures. Note that * it's not safe to sleep here, since we're probably going to be * called during autoconfiguration. */ diskp->dk_label = malloc(sizeof(struct disklabel), M_DEVBUF, M_NOWAIT|M_ZERO); if (diskp->dk_label == NULL) panic("disk_attach: can't allocate storage for disklabel"); /* * Set the attached timestamp. */ microuptime(&diskp->dk_attachtime); /* * Link into the disklist. */ TAILQ_INSERT_TAIL(&disklist, diskp, dk_link); ++disk_count; disk_change = 1; /* * Store device structure and number for later use. */ diskp->dk_device = dv; diskp->dk_devno = NODEV; if (dv != NULL) { majdev = findblkmajor(dv); if (majdev >= 0) diskp->dk_devno = MAKEDISKDEV(majdev, dv->dv_unit, RAW_PART); if (diskp->dk_devno != NODEV) { struct disk_attach_task *dat; dat = malloc(sizeof(*dat), M_TEMP, M_WAITOK); /* XXX: Assumes dk is part of the device softc. */ device_ref(dv); dat->dk = diskp; task_set(&dat->task, disk_attach_callback, dat); task_add(systq, &dat->task); } } if (softraid_disk_attach) softraid_disk_attach(diskp, 1); } void disk_attach_callback(void *xdat) { struct disk_attach_task *dat = xdat; struct disk *dk = dat->dk; struct disklabel dl; char errbuf[100]; free(dat, M_TEMP, sizeof(*dat)); if (dk->dk_flags & (DKF_OPENED | DKF_NOLABELREAD)) goto done; /* Read disklabel. */ if (disk_readlabel(&dl, dk->dk_devno, errbuf, sizeof(errbuf)) == NULL) { enqueue_randomness(dl.d_checksum); } done: dk->dk_flags |= DKF_OPENED; device_unref(dk->dk_device); wakeup(dk); } /* * Detach a disk. */ void disk_detach(struct disk *diskp) { KERNEL_ASSERT_LOCKED(); if (softraid_disk_attach) softraid_disk_attach(diskp, -1); /* * Free the space used by the disklabel structures. */ free(diskp->dk_label, M_DEVBUF, sizeof(*diskp->dk_label)); /* * Remove from the disklist. */ TAILQ_REMOVE(&disklist, diskp, dk_link); disk_change = 1; if (--disk_count < 0) panic("disk_detach: disk_count < 0"); } int disk_openpart(struct disk *dk, int part, int fmt, int haslabel) { KASSERT(part >= 0 && part < MAXPARTITIONS); /* Unless opening the raw partition, check that the partition exists. */ if (part != RAW_PART && (!haslabel || part >= dk->dk_label->d_npartitions || dk->dk_label->d_partitions[part].p_fstype == FS_UNUSED)) return (ENXIO); /* Ensure the partition doesn't get changed under our feet. */ switch (fmt) { case S_IFCHR: dk->dk_copenmask |= (1 << part); break; case S_IFBLK: dk->dk_bopenmask |= (1 << part); break; } dk->dk_openmask = dk->dk_copenmask | dk->dk_bopenmask; return (0); } void disk_closepart(struct disk *dk, int part, int fmt) { KASSERT(part >= 0 && part < MAXPARTITIONS); switch (fmt) { case S_IFCHR: dk->dk_copenmask &= ~(1 << part); break; case S_IFBLK: dk->dk_bopenmask &= ~(1 << part); break; } dk->dk_openmask = dk->dk_copenmask | dk->dk_bopenmask; } void disk_gone(int (*open)(dev_t, int, int, struct proc *), int unit) { int bmaj, cmaj, mn; /* Locate the lowest minor number to be detached. */ mn = DISKMINOR(unit, 0); for (bmaj = 0; bmaj < nblkdev; bmaj++) if (bdevsw[bmaj].d_open == open) vdevgone(bmaj, mn, mn + MAXPARTITIONS - 1, VBLK); for (cmaj = 0; cmaj < nchrdev; cmaj++) if (cdevsw[cmaj].d_open == open) vdevgone(cmaj, mn, mn + MAXPARTITIONS - 1, VCHR); } /* * Increment a disk's busy counter. If the counter is going from * 0 to 1, set the timestamp. */ void disk_busy(struct disk *diskp) { /* * XXX We'd like to use something as accurate as microtime(), * but that doesn't depend on the system TOD clock. */ mtx_enter(&diskp->dk_mtx); if (diskp->dk_busy++ == 0) microuptime(&diskp->dk_timestamp); mtx_leave(&diskp->dk_mtx); } /* * Decrement a disk's busy counter, increment the byte count, total busy * time, and reset the timestamp. */ void disk_unbusy(struct disk *diskp, long bcount, daddr_t blkno, int read) { struct timeval dv_time, diff_time; mtx_enter(&diskp->dk_mtx); if (diskp->dk_busy-- == 0) printf("disk_unbusy: %s: dk_busy < 0\n", diskp->dk_name); microuptime(&dv_time); timersub(&dv_time, &diskp->dk_timestamp, &diff_time); timeradd(&diskp->dk_time, &diff_time, &diskp->dk_time); diskp->dk_timestamp = dv_time; if (bcount > 0) { if (read) { diskp->dk_rbytes += bcount; diskp->dk_rxfer++; } else { diskp->dk_wbytes += bcount; diskp->dk_wxfer++; } } else diskp->dk_seek++; mtx_leave(&diskp->dk_mtx); enqueue_randomness(bcount ^ diff_time.tv_usec ^ (blkno >> 32) ^ (blkno & 0xffffffff)); } int disk_lock(struct disk *dk) { return (rw_enter(&dk->dk_lock, RW_WRITE|RW_INTR)); } void disk_lock_nointr(struct disk *dk) { rw_enter_write(&dk->dk_lock); } void disk_unlock(struct disk *dk) { rw_exit_write(&dk->dk_lock); } int dk_mountroot(void) { char errbuf[100]; int part = DISKPART(rootdev); int (*mountrootfn)(void); struct disklabel dl; char *error; error = disk_readlabel(&dl, rootdev, errbuf, sizeof(errbuf)); if (error) panic("%s", error); if (DL_GETPSIZE(&dl.d_partitions[part]) == 0) panic("root filesystem has size 0"); switch (dl.d_partitions[part].p_fstype) { #ifdef EXT2FS case FS_EXT2FS: { extern int ext2fs_mountroot(void); mountrootfn = ext2fs_mountroot; } break; #endif #ifdef FFS case FS_BSDFFS: { extern int ffs_mountroot(void); mountrootfn = ffs_mountroot; } break; #endif #ifdef CD9660 case FS_ISO9660: { extern int cd9660_mountroot(void); mountrootfn = cd9660_mountroot; } break; #endif default: #ifdef FFS { extern int ffs_mountroot(void); printf("filesystem type %d not known.. assuming ffs\n", dl.d_partitions[part].p_fstype); mountrootfn = ffs_mountroot; } #else panic("disk 0x%x filesystem type %d not known", rootdev, dl.d_partitions[part].p_fstype); #endif } return (*mountrootfn)(); } struct device * getdisk(char *str, int len, int defpart, dev_t *devp) { struct device *dv; if ((dv = parsedisk(str, len, defpart, devp)) == NULL) { printf("use one of: exit"); TAILQ_FOREACH(dv, &alldevs, dv_list) { if (dv->dv_class == DV_DISK) printf(" %s[a-p]", dv->dv_xname); #if defined(NFSCLIENT) if (dv->dv_class == DV_IFNET) printf(" %s", dv->dv_xname); #endif } printf("\n"); } return (dv); } struct device * parsedisk(char *str, int len, int defpart, dev_t *devp) { struct device *dv; int majdev, part = defpart; char c; if (len == 0) return (NULL); c = str[len-1]; if (c >= 'a' && (c - 'a') < MAXPARTITIONS) { part = c - 'a'; len -= 1; } TAILQ_FOREACH(dv, &alldevs, dv_list) { if (dv->dv_class == DV_DISK && strncmp(str, dv->dv_xname, len) == 0 && dv->dv_xname[len] == '\0') { majdev = findblkmajor(dv); if (majdev < 0) return NULL; *devp = MAKEDISKDEV(majdev, dv->dv_unit, part); break; } #if defined(NFSCLIENT) if (dv->dv_class == DV_IFNET && strncmp(str, dv->dv_xname, len) == 0 && dv->dv_xname[len] == '\0') { *devp = NODEV; break; } #endif } return (dv); } void setroot(struct device *bootdv, int part, int exitflags) { int majdev, unit, len, s, slept = 0; struct swdevt *swp; struct device *dv; dev_t nrootdev, nswapdev = NODEV, temp = NODEV; struct ifnet *ifp = NULL; struct disk *dk; char buf[128]; #if defined(NFSCLIENT) extern char *nfsbootdevname; #endif /* Ensure that all disk attach callbacks have completed. */ do { TAILQ_FOREACH(dk, &disklist, dk_link) { if (dk->dk_devno != NODEV && (dk->dk_flags & DKF_OPENED) == 0) { tsleep_nsec(dk, 0, "dkopen", SEC_TO_NSEC(1)); slept++; break; } } } while (dk != NULL && slept < 5); if (slept == 5) { printf("disklabels not read:"); TAILQ_FOREACH(dk, &disklist, dk_link) if (dk->dk_devno != NODEV && (dk->dk_flags & DKF_OPENED) == 0) printf(" %s", dk->dk_name); printf("\n"); } if (duid_iszero(bootduid)) { /* Locate DUID for boot disk since it was not provided. */ TAILQ_FOREACH(dk, &disklist, dk_link) if (dk->dk_device == bootdv) break; if (dk) bcopy(dk->dk_label->d_uid, bootduid, sizeof(bootduid)); } else if (bootdv == NULL) { /* Locate boot disk based on the provided DUID. */ TAILQ_FOREACH(dk, &disklist, dk_link) if (duid_equal(dk->dk_label->d_uid, bootduid)) break; if (dk) bootdv = dk->dk_device; } bcopy(bootduid, rootduid, sizeof(rootduid)); #if NSOFTRAID > 0 sr_map_root(); #endif /* * If `swap generic' and we couldn't determine boot device, * ask the user. */ dk = NULL; if (mountroot == NULL && bootdv == NULL) boothowto |= RB_ASKNAME; if (boothowto & RB_ASKNAME) { while (1) { printf("root device"); if (bootdv != NULL) { printf(" (default %s", bootdv->dv_xname); if (bootdv->dv_class == DV_DISK) printf("%c", 'a' + part); printf(")"); } printf(": "); s = splhigh(); cnpollc(1); len = getsn(buf, sizeof(buf)); cnpollc(0); splx(s); if (strcmp(buf, "exit") == 0) reboot(exitflags); if (len == 0 && bootdv != NULL) { strlcpy(buf, bootdv->dv_xname, sizeof buf); len = strlen(buf); } if (len > 0 && buf[len - 1] == '*') { buf[--len] = '\0'; dv = getdisk(buf, len, part, &nrootdev); if (dv != NULL) { rootdv = dv; nswapdev = nrootdev; goto gotswap; } } dv = getdisk(buf, len, part, &nrootdev); if (dv != NULL) { rootdv = dv; break; } } if (rootdv->dv_class == DV_IFNET) goto gotswap; /* try to build swap device out of new root device */ while (1) { printf("swap device"); if (rootdv != NULL) printf(" (default %s%s)", rootdv->dv_xname, rootdv->dv_class == DV_DISK ? "b" : ""); printf(": "); s = splhigh(); cnpollc(1); len = getsn(buf, sizeof(buf)); cnpollc(0); splx(s); if (strcmp(buf, "exit") == 0) reboot(exitflags); if (len == 0 && rootdv != NULL) { switch (rootdv->dv_class) { case DV_IFNET: nswapdev = NODEV; break; case DV_DISK: nswapdev = MAKEDISKDEV(major(nrootdev), DISKUNIT(nrootdev), 1); if (nswapdev == nrootdev) continue; break; default: break; } break; } dv = getdisk(buf, len, 1, &nswapdev); if (dv) { if (dv->dv_class == DV_IFNET) nswapdev = NODEV; if (nswapdev == nrootdev) continue; break; } } gotswap: rootdev = nrootdev; dumpdev = nswapdev; swdevt[0].sw_dev = nswapdev; swdevt[1].sw_dev = NODEV; #if defined(NFSCLIENT) } else if (mountroot == nfs_mountroot) { rootdv = bootdv; rootdev = dumpdev = swapdev = NODEV; #endif } else if (mountroot == NULL && rootdev == NODEV) { /* * `swap generic' */ rootdv = bootdv; if (bootdv->dv_class == DV_DISK) { if (!duid_iszero(rootduid)) { TAILQ_FOREACH(dk, &disklist, dk_link) if (dk->dk_label && duid_equal( dk->dk_label->d_uid, rootduid)) break; if (dk == NULL) panic("root device (%s) not found", duid_format(rootduid)); rootdv = dk->dk_device; } } majdev = findblkmajor(rootdv); if (majdev >= 0) { /* * Root and swap are on the disk. * Assume swap is on partition b. */ rootdev = MAKEDISKDEV(majdev, rootdv->dv_unit, part); nswapdev = MAKEDISKDEV(majdev, rootdv->dv_unit, 1); } else { /* * Root and swap are on a net. */ nswapdev = NODEV; } dumpdev = nswapdev; swdevt[0].sw_dev = nswapdev; /* swdevt[1].sw_dev = NODEV; */ } else { /* Completely pre-configured, but we want rootdv .. */ majdev = major(rootdev); if (findblkname(majdev) == NULL) return; unit = DISKUNIT(rootdev); part = DISKPART(rootdev); snprintf(buf, sizeof buf, "%s%d%c", findblkname(majdev), unit, 'a' + part); rootdv = parsedisk(buf, strlen(buf), 0, &nrootdev); if (rootdv == NULL) panic("root device (%s) not found", buf); } if (bootdv != NULL && bootdv->dv_class == DV_IFNET) ifp = if_unit(bootdv->dv_xname); if (ifp) { if_addgroup(ifp, "netboot"); if_put(ifp); } switch (rootdv->dv_class) { #if defined(NFSCLIENT) case DV_IFNET: mountroot = nfs_mountroot; nfsbootdevname = rootdv->dv_xname; return; #endif case DV_DISK: mountroot = dk_mountroot; part = DISKPART(rootdev); break; default: printf("can't figure root, hope your kernel is right\n"); return; } printf("root on %s%c", rootdv->dv_xname, 'a' + part); if (dk && dk->dk_device == rootdv) printf(" (%s.%c)", duid_format(rootduid), 'a' + part); /* * Make the swap partition on the root drive the primary swap. */ for (swp = swdevt; swp->sw_dev != NODEV; swp++) { if (major(rootdev) == major(swp->sw_dev) && DISKUNIT(rootdev) == DISKUNIT(swp->sw_dev)) { temp = swdevt[0].sw_dev; swdevt[0].sw_dev = swp->sw_dev; swp->sw_dev = temp; break; } } if (swp->sw_dev != NODEV) { /* * If dumpdev was the same as the old primary swap device, * move it to the new primary swap device. */ if (temp == dumpdev) dumpdev = swdevt[0].sw_dev; } if (swdevt[0].sw_dev != NODEV) printf(" swap on %s%d%c", findblkname(major(swdevt[0].sw_dev)), DISKUNIT(swdevt[0].sw_dev), 'a' + DISKPART(swdevt[0].sw_dev)); if (dumpdev != NODEV) printf(" dump on %s%d%c", findblkname(major(dumpdev)), DISKUNIT(dumpdev), 'a' + DISKPART(dumpdev)); printf("\n"); } extern const struct nam2blk nam2blk[]; int findblkmajor(struct device *dv) { char buf[16], *p; int i; if (strlcpy(buf, dv->dv_xname, sizeof buf) >= sizeof buf) return (-1); for (p = buf; *p; p++) if (*p >= '0' && *p <= '9') *p = '\0'; for (i = 0; nam2blk[i].name; i++) if (!strcmp(buf, nam2blk[i].name)) return (nam2blk[i].maj); return (-1); } char * findblkname(int maj) { int i; for (i = 0; nam2blk[i].name; i++) if (nam2blk[i].maj == maj) return (nam2blk[i].name); return (NULL); } char * disk_readlabel(struct disklabel *dl, dev_t dev, char *errbuf, size_t errsize) { struct vnode *vn; dev_t chrdev, rawdev; int error; chrdev = blktochr(dev); rawdev = MAKEDISKDEV(major(chrdev), DISKUNIT(chrdev), RAW_PART); #ifdef DEBUG printf("dev=0x%x chrdev=0x%x rawdev=0x%x\n", dev, chrdev, rawdev); #endif if (cdevvp(rawdev, &vn)) { snprintf(errbuf, errsize, "cannot obtain vnode for 0x%x/0x%x", dev, rawdev); return (errbuf); } error = VOP_OPEN(vn, FREAD, NOCRED, curproc); if (error) { snprintf(errbuf, errsize, "cannot open disk, 0x%x/0x%x, error %d", dev, rawdev, error); goto done; } error = VOP_IOCTL(vn, DIOCGDINFO, (caddr_t)dl, FREAD, NOCRED, curproc); if (error) { snprintf(errbuf, errsize, "cannot read disk label, 0x%x/0x%x, error %d", dev, rawdev, error); } done: VOP_CLOSE(vn, FREAD, NOCRED, curproc); vput(vn); if (error) return (errbuf); return (NULL); } int disk_map(const char *path, char *mappath, int size, int flags) { struct disk *dk, *mdk; u_char uid[8]; char c, part; int i; /* * Attempt to map a request for a disklabel UID to the correct device. * We should be supplied with a disklabel UID which has the following * format: * * [disklabel uid] . [partition] * * Alternatively, if the DM_OPENPART flag is set the disklabel UID can * based passed on its own. */ if (strchr(path, '/') != NULL) return -1; /* Verify that the device name is properly formed. */ if (!((strlen(path) == 16 && (flags & DM_OPENPART)) || (strlen(path) == 18 && path[16] == '.'))) return -1; /* Get partition. */ if (flags & DM_OPENPART) part = 'a' + RAW_PART; else part = path[17]; if (part < 'a' || part >= 'a' + MAXPARTITIONS) return -1; /* Derive label UID. */ memset(uid, 0, sizeof(uid)); for (i = 0; i < 16; i++) { c = path[i]; if (c >= '0' && c <= '9') c -= '0'; else if (c >= 'a' && c <= 'f') c -= ('a' - 10); else return -1; uid[i / 2] <<= 4; uid[i / 2] |= c & 0xf; } mdk = NULL; TAILQ_FOREACH(dk, &disklist, dk_link) { if (dk->dk_label && memcmp(dk->dk_label->d_uid, uid, sizeof(dk->dk_label->d_uid)) == 0) { /* Fail if there are duplicate UIDs! */ if (mdk != NULL) return -1; mdk = dk; } } if (mdk == NULL || mdk->dk_name == NULL) return -1; snprintf(mappath, size, "/dev/%s%s%c", (flags & DM_OPENBLCK) ? "" : "r", mdk->dk_name, part); return 0; } /* * Lookup a disk device and verify that it has completed attaching. */ struct device * disk_lookup(struct cfdriver *cd, int unit) { struct device *dv; struct disk *dk; dv = device_lookup(cd, unit); if (dv == NULL) return (NULL); TAILQ_FOREACH(dk, &disklist, dk_link) if (dk->dk_device == dv) break; if (dk == NULL) { device_unref(dv); return (NULL); } return (dv); } int duid_equal(u_char *duid1, u_char *duid2) { return (memcmp(duid1, duid2, DUID_SIZE) == 0); } int duid_iszero(u_char *duid) { u_char zeroduid[DUID_SIZE]; memset(zeroduid, 0, sizeof(zeroduid)); return (duid_equal(duid, zeroduid)); } const char * duid_format(u_char *duid) { static char duid_str[17]; KERNEL_ASSERT_LOCKED(); snprintf(duid_str, sizeof(duid_str), "%02x%02x%02x%02x%02x%02x%02x%02x", duid[0], duid[1], duid[2], duid[3], duid[4], duid[5], duid[6], duid[7]); return (duid_str); }
11 11 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 /* $OpenBSD: uvm_io.c,v 1.30 2022/10/07 14:59:39 deraadt Exp $ */ /* $NetBSD: uvm_io.c,v 1.12 2000/06/27 17:29:23 mrg Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * from: Id: uvm_io.c,v 1.1.2.2 1997/12/30 12:02:00 mrg Exp */ /* * uvm_io.c: uvm i/o ops */ #include <sys/param.h> #include <sys/systm.h> #include <sys/mman.h> #include <sys/uio.h> #include <uvm/uvm.h> /* * functions */ /* * uvm_io: perform I/O on a map * * => caller must have a reference to "map" so that it doesn't go away * while we are working. */ int uvm_io(vm_map_t map, struct uio *uio, int flags) { vaddr_t baseva, endva, pageoffset, kva; vsize_t chunksz, togo, sz; struct uvm_map_deadq dead_entries; int error, extractflags; /* * step 0: sanity checks and set up for copy loop. start with a * large chunk size. if we have trouble finding vm space we will * reduce it. */ if (uio->uio_resid == 0) return(0); togo = uio->uio_resid; baseva = (vaddr_t) uio->uio_offset; endva = baseva + (togo - 1); if (endva < baseva) /* wrap around? */ return(EIO); if (baseva >= VM_MAXUSER_ADDRESS) return(0); if (endva >= VM_MAXUSER_ADDRESS) /* EOF truncate */ togo = togo - (endva - VM_MAXUSER_ADDRESS + 1); pageoffset = baseva & PAGE_MASK; baseva = trunc_page(baseva); chunksz = min(round_page(togo + pageoffset), MAXBSIZE); error = 0; extractflags = 0; if (flags & UVM_IO_FIXPROT) extractflags |= UVM_EXTRACT_FIXPROT; /* * step 1: main loop... while we've got data to move */ for (/*null*/; togo > 0 ; pageoffset = 0) { /* * step 2: extract mappings from the map into kernel_map */ error = uvm_map_extract(map, baseva, chunksz, &kva, extractflags); if (error) { /* retry with a smaller chunk... */ if (error == ENOMEM && chunksz > PAGE_SIZE) { chunksz = trunc_page(chunksz / 2); if (chunksz < PAGE_SIZE) chunksz = PAGE_SIZE; continue; } break; } /* * step 3: move a chunk of data */ sz = chunksz - pageoffset; if (sz > togo) sz = togo; error = uiomove((caddr_t) (kva + pageoffset), sz, uio); togo -= sz; baseva += chunksz; /* * step 4: unmap the area of kernel memory */ vm_map_lock(kernel_map); TAILQ_INIT(&dead_entries); uvm_unmap_remove(kernel_map, kva, kva+chunksz, &dead_entries, FALSE, TRUE, FALSE); vm_map_unlock(kernel_map); uvm_unmap_detach(&dead_entries, AMAP_REFALL); if (error) break; } return (error); }
71 35 38 29 28 2 29 179 7 173 36 144 29 173 8 8 172 85 11 162 51 35 3 26 23 120 4 13 42 66 47 18 29 90 14 27 63 49 25 94 155 18 57 85 34 30 43 48 85 14 57 31 34 42 17 49 66 10 9 41 22 34 47 132 22 18 21 19 5 2 1 28 135 132 127 135 14 134 55 168 169 167 64 2 25 1 20 102 18 46 46 29 105 15 15 8 105 104 66 66 79 39 165 165 102 70 1 3 1 2 9 2 2 3 2 2 3 2 2 1 5 3 5 3 1 1 2 25 2 7 12 9 6 26 4 20 2 5 25 3 9 11 6 13 2 2 11 13 2 3 1 3 2 2 3 11 3 2 3 2 3 2 3 2 3 2 43 2 21 11 3 2 4 9 25 24 5 5 16 1 15 1 9 9 2 29 28 25 14 22 7 60 47 20 17 16 16 36 127 49 98 98 98 66 97 38 85 84 2 6 12 4 35 50 12 200 50 14 36 31 30 2 1 2 3 16 27 57 57 41 35 7 40 7 3 4 2 1 1 5 9 31 26 13 1 21 21 1 20 11 2 1 1 1 2 2 2 16 3 16 26 9 113 113 109 4 2 8 12 2 35 34 1 1 1 1 34 31 2 10 5 2 9 21 29 9 24 24 4 30 28 7 20 1 1 8 12 91 15 1 1 38 43 11 27 1 17 17 11 14 17 43 43 71 72 72 72 166 16 166 128 38 70 58 34 12 25 1 145 216 3 61 4 4 30 3 27 4 3 4 4 4 4 4 33 6 27 30 30 30 13 33 29 33 4 4 2 2 2 2 2 1 8 1 1 1 1 1 2 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 /* $OpenBSD: tty.c,v 1.176 2022/08/14 01:58:28 jsg Exp $ */ /* $NetBSD: tty.c,v 1.68.4.2 1996/06/06 16:04:52 thorpej Exp $ */ /*- * Copyright (c) 1982, 1986, 1990, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)tty.c 8.8 (Berkeley) 1/21/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/ioctl.h> #include <sys/proc.h> #define TTYDEFCHARS #include <sys/tty.h> #undef TTYDEFCHARS #include <sys/fcntl.h> #include <sys/conf.h> #include <sys/uio.h> #include <sys/kernel.h> #include <sys/vnode.h> #include <sys/lock.h> #include <sys/malloc.h> #include <sys/msgbuf.h> #include <sys/signalvar.h> #include <sys/resourcevar.h> #include <sys/sysctl.h> #include <sys/pool.h> #include <sys/unistd.h> #include <sys/pledge.h> #include <sys/namei.h> #include <uvm/uvm_extern.h> #include <dev/cons.h> #include "pty.h" static int ttnread(struct tty *); static void ttyblock(struct tty *); void ttyunblock(struct tty *); static void ttyecho(int, struct tty *); static void ttyrubo(struct tty *, int); int filt_ttyread(struct knote *kn, long hint); void filt_ttyrdetach(struct knote *kn); int filt_ttywrite(struct knote *kn, long hint); void filt_ttywdetach(struct knote *kn); int filt_ttyexcept(struct knote *kn, long hint); void ttystats_init(struct itty **, int *, size_t *); int ttywait_nsec(struct tty *, uint64_t); int ttysleep_nsec(struct tty *, void *, int, char *, uint64_t); /* Symbolic sleep message strings. */ char ttclos[] = "ttycls"; char ttopen[] = "ttyopn"; char ttybg[] = "ttybg"; char ttyin[] = "ttyin"; char ttyout[] = "ttyout"; /* * Table with character classes and parity. The 8th bit indicates parity, * the 7th bit indicates the character is an alphameric or underscore (for * ALTWERASE), and the low 6 bits indicate delay type. If the low 6 bits * are 0 then the character needs no special processing on output; classes * other than 0 might be translated or (not currently) require delays. */ #define E 0x00 /* Even parity. */ #define O 0x80 /* Odd parity. */ #define PARITY(c) (char_type[c] & O) #define ALPHA 0x40 /* Alpha or underscore. */ #define ISALPHA(c) (char_type[(c) & TTY_CHARMASK] & ALPHA) #define CCLASSMASK 0x3f #define CCLASS(c) (char_type[c] & CCLASSMASK) #define BS BACKSPACE #define CC CONTROL #define CR RETURN #define NA ORDINARY | ALPHA #define NL NEWLINE #define NO ORDINARY #define TB TAB #define VT VTAB u_char const char_type[] = { E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* nul - bel */ O|BS, E|TB, E|NL, O|CC, E|VT, O|CR, O|CC, E|CC, /* bs - si */ O|CC, E|CC, E|CC, O|CC, E|CC, O|CC, O|CC, E|CC, /* dle - etb */ E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* can - us */ O|NO, E|NO, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* sp - ' */ E|NO, O|NO, O|NO, E|NO, O|NO, E|NO, E|NO, O|NO, /* ( - / */ E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* 0 - 7 */ O|NA, E|NA, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* 8 - ? */ O|NO, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* @ - G */ E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* H - O */ E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* P - W */ O|NA, E|NA, E|NA, O|NO, E|NO, O|NO, O|NO, O|NA, /* X - _ */ E|NO, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* ` - g */ O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* h - o */ O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* p - w */ E|NA, O|NA, O|NA, E|NO, O|NO, E|NO, E|NO, O|CC, /* x - del */ /* * Meta chars; should be settable per character set; * for now, treat them all as normal characters. */ NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, }; #undef BS #undef CC #undef CR #undef NA #undef NL #undef NO #undef TB #undef VT #define islower(c) ((c) >= 'a' && (c) <= 'z') #define isupper(c) ((c) >= 'A' && (c) <= 'Z') #define tolower(c) ((c) - 'A' + 'a') #define toupper(c) ((c) - 'a' + 'A') struct ttylist_head ttylist; /* TAILQ_HEAD */ int tty_count; struct rwlock ttylist_lock = RWLOCK_INITIALIZER("ttylist"); int64_t tk_cancc, tk_nin, tk_nout, tk_rawcc; /* * Initial open of tty, or (re)entry to standard tty line discipline. */ int ttyopen(dev_t device, struct tty *tp, struct proc *p) { int s; s = spltty(); tp->t_dev = device; if (!ISSET(tp->t_state, TS_ISOPEN)) { SET(tp->t_state, TS_ISOPEN); memset(&tp->t_winsize, 0, sizeof(tp->t_winsize)); tp->t_column = 0; } CLR(tp->t_state, TS_WOPEN); splx(s); return (0); } /* * Handle close() on a tty line: flush and set to initial state, * bumping generation number so that pending read/write calls * can detect recycling of the tty. */ int ttyclose(struct tty *tp) { if (constty == tp) constty = NULL; ttyflush(tp, FREAD | FWRITE); tp->t_gen++; tp->t_pgrp = NULL; if (tp->t_session) SESSRELE(tp->t_session); tp->t_session = NULL; tp->t_state = 0; return (0); } #define FLUSHQ(q) { \ if ((q)->c_cc) \ ndflush(q, (q)->c_cc); \ } /* Is 'c' a line delimiter ("break" character)? */ #define TTBREAKC(c, lflag) \ ((c) == '\n' || (((c) == cc[VEOF] || (c) == cc[VEOL] || \ ((c) == cc[VEOL2] && (lflag & IEXTEN))) && (c) != _POSIX_VDISABLE)) /* * Process input of a single character received on a tty. Returns 0 normally, * 1 if a costly operation was reached. */ int ttyinput(int c, struct tty *tp) { int iflag, lflag; u_char *cc; int i, error, ret = 0; int s; enqueue_randomness(tp->t_dev << 8 | c); /* * If receiver is not enabled, drop it. */ if (!ISSET(tp->t_cflag, CREAD)) return (0); /* * If input is pending take it first. */ lflag = tp->t_lflag; s = spltty(); if (ISSET(lflag, PENDIN)) ttypend(tp); splx(s); /* * Gather stats. */ if (ISSET(lflag, ICANON)) { ++tk_cancc; ++tp->t_cancc; } else { ++tk_rawcc; ++tp->t_rawcc; } ++tk_nin; /* Handle exceptional conditions (break, parity, framing). */ cc = tp->t_cc; iflag = tp->t_iflag; if ((error = (ISSET(c, TTY_ERRORMASK))) != 0) { CLR(c, TTY_ERRORMASK); if (ISSET(error, TTY_FE) && !c) { /* Break. */ if (ISSET(iflag, IGNBRK)) return (0); ttyflush(tp, FREAD | FWRITE); if (ISSET(iflag, BRKINT)) { pgsignal(tp->t_pgrp, SIGINT, 1); goto endcase; } else if (ISSET(iflag, PARMRK)) goto parmrk; } else if ((ISSET(error, TTY_PE) && ISSET(iflag, INPCK)) || ISSET(error, TTY_FE)) { if (ISSET(iflag, IGNPAR)) goto endcase; else if (ISSET(iflag, PARMRK)) { parmrk: (void)putc(0377 | TTY_QUOTE, &tp->t_rawq); if (ISSET(iflag, ISTRIP) || c != 0377) (void)putc(0 | TTY_QUOTE, &tp->t_rawq); (void)putc(c | TTY_QUOTE, &tp->t_rawq); goto endcase; } else c = 0; } } if (c == 0377 && !ISSET(iflag, ISTRIP) && ISSET(iflag, PARMRK)) goto parmrk; /* * In tandem mode, check high water mark. */ if (ISSET(iflag, IXOFF) || ISSET(tp->t_cflag, CHWFLOW)) ttyblock(tp); if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP)) CLR(c, 0x80); if (!ISSET(lflag, EXTPROC)) { /* * Check for literal nexting very first */ if (ISSET(tp->t_state, TS_LNCH)) { SET(c, TTY_QUOTE); CLR(tp->t_state, TS_LNCH); } /* * Scan for special characters. This code * is really just a big case statement with * non-constant cases. The bottom of the * case statement is labeled ``endcase'', so goto * it after a case match, or similar. */ /* * Control chars which aren't controlled * by ICANON, ISIG, or IXON. */ if (ISSET(lflag, IEXTEN)) { if (CCEQ(cc[VLNEXT], c)) { if (ISSET(lflag, ECHO)) { if (ISSET(lflag, ECHOE)) { (void)ttyoutput('^', tp); (void)ttyoutput('\b', tp); } else ttyecho(c, tp); } SET(tp->t_state, TS_LNCH); goto endcase; } if (CCEQ(cc[VDISCARD], c)) { if (ISSET(lflag, FLUSHO)) CLR(tp->t_lflag, FLUSHO); else { ttyflush(tp, FWRITE); ttyecho(c, tp); if (tp->t_rawq.c_cc + tp->t_canq.c_cc) ret = ttyretype(tp); SET(tp->t_lflag, FLUSHO); } goto startoutput; } } /* * Signals. */ if (ISSET(lflag, ISIG)) { if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) { if (!ISSET(lflag, NOFLSH)) ttyflush(tp, FREAD | FWRITE); ttyecho(c, tp); pgsignal(tp->t_pgrp, CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1); goto endcase; } if (CCEQ(cc[VSUSP], c)) { if (!ISSET(lflag, NOFLSH)) ttyflush(tp, FREAD); ttyecho(c, tp); pgsignal(tp->t_pgrp, SIGTSTP, 1); goto endcase; } } /* * Handle start/stop characters. */ if (ISSET(iflag, IXON)) { if (CCEQ(cc[VSTOP], c)) { if (!ISSET(tp->t_state, TS_TTSTOP)) { SET(tp->t_state, TS_TTSTOP); (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); return (0); } if (!CCEQ(cc[VSTART], c)) return (0); /* * if VSTART == VSTOP then toggle */ goto endcase; } if (CCEQ(cc[VSTART], c)) goto restartoutput; } /* * IGNCR, ICRNL, & INLCR */ if (c == '\r') { if (ISSET(iflag, IGNCR)) goto endcase; else if (ISSET(iflag, ICRNL)) c = '\n'; } else if (c == '\n' && ISSET(iflag, INLCR)) c = '\r'; } if (!ISSET(tp->t_lflag, EXTPROC) && ISSET(lflag, ICANON)) { /* * From here on down canonical mode character * processing takes place. */ /* * upper case or specials with IUCLC and XCASE */ if (ISSET(lflag, XCASE) && ISSET(iflag, IUCLC)) { if (ISSET(tp->t_state, TS_BKSL)) { CLR(tp->t_state, TS_BKSL); switch (c) { case '\'': c = '`'; break; case '!': c = '|'; break; case '^': c = '~'; break; case '(': c = '{'; break; case ')': c = '}'; break; } } else if (c == '\\') { SET(tp->t_state, TS_BKSL); goto endcase; } else if (isupper(c)) c = tolower(c); } else if (ISSET(iflag, IUCLC) && isupper(c)) c = tolower(c); /* * erase (^H / ^?) */ if (CCEQ(cc[VERASE], c)) { if (tp->t_rawq.c_cc) ret = ttyrub(unputc(&tp->t_rawq), tp); goto endcase; } /* * kill (^U) */ if (CCEQ(cc[VKILL], c)) { if (ISSET(lflag, ECHOKE) && tp->t_rawq.c_cc == tp->t_rocount && !ISSET(lflag, ECHOPRT)) { while (tp->t_rawq.c_cc) if (ttyrub(unputc(&tp->t_rawq), tp)) ret = 1; } else { ttyecho(c, tp); if (ISSET(lflag, ECHOK) || ISSET(lflag, ECHOKE)) ttyecho('\n', tp); FLUSHQ(&tp->t_rawq); tp->t_rocount = 0; } CLR(tp->t_state, TS_LOCAL); goto endcase; } /* * word erase (^W) */ if (CCEQ(cc[VWERASE], c) && ISSET(lflag, IEXTEN)) { int alt = ISSET(lflag, ALTWERASE); int ctype; /* * erase whitespace */ while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t') if (ttyrub(c, tp)) ret = 1; if (c == -1) goto endcase; /* * erase last char of word and remember the * next chars type (for ALTWERASE) */ if (ttyrub(c, tp)) ret = 1; c = unputc(&tp->t_rawq); if (c == -1) goto endcase; if (c == ' ' || c == '\t') { (void)putc(c, &tp->t_rawq); goto endcase; } ctype = ISALPHA(c); /* * erase rest of word */ do { if (ttyrub(c, tp)) ret = 1; c = unputc(&tp->t_rawq); if (c == -1) goto endcase; } while (c != ' ' && c != '\t' && (alt == 0 || ISALPHA(c) == ctype)); (void)putc(c, &tp->t_rawq); goto endcase; } /* * reprint line (^R) */ if (CCEQ(cc[VREPRINT], c) && ISSET(lflag, IEXTEN)) { ret = ttyretype(tp); goto endcase; } /* * ^T - kernel info and generate SIGINFO */ if (CCEQ(cc[VSTATUS], c) && ISSET(lflag, IEXTEN)) { if (ISSET(lflag, ISIG)) pgsignal(tp->t_pgrp, SIGINFO, 1); if (!ISSET(lflag, NOKERNINFO)) ttyinfo(tp); goto endcase; } } /* * Check for input buffer overflow */ if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= TTYHOG(tp)) { if (ISSET(iflag, IMAXBEL)) { if (tp->t_outq.c_cc < tp->t_hiwat) (void)ttyoutput(CTRL('g'), tp); } else ttyflush(tp, FREAD | FWRITE); goto endcase; } /* * Put data char in q for user and * wakeup on seeing a line delimiter. */ if (putc(c, &tp->t_rawq) >= 0) { if (!ISSET(lflag, ICANON)) { ttwakeup(tp); ttyecho(c, tp); goto endcase; } if (TTBREAKC(c, lflag)) { tp->t_rocount = 0; catq(&tp->t_rawq, &tp->t_canq); ttwakeup(tp); } else if (tp->t_rocount++ == 0) tp->t_rocol = tp->t_column; if (ISSET(tp->t_state, TS_ERASE)) { /* * end of prterase \.../ */ CLR(tp->t_state, TS_ERASE); (void)ttyoutput('/', tp); } i = tp->t_column; ttyecho(c, tp); if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) { /* * Place the cursor over the '^' of the ^D. */ i = min(2, tp->t_column - i); while (i > 0) { (void)ttyoutput('\b', tp); i--; } } } endcase: /* * IXANY means allow any character to restart output. */ if (ISSET(tp->t_state, TS_TTSTOP) && !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP]) return (ret); restartoutput: CLR(tp->t_lflag, FLUSHO); CLR(tp->t_state, TS_TTSTOP); startoutput: ttstart(tp); return (ret); } /* * Output a single character on a tty, doing output processing * as needed (expanding tabs, newline processing, etc.). * Returns < 0 if succeeds, otherwise returns char to resend. * Must be recursive. */ int ttyoutput(int c, struct tty *tp) { long oflag; int col, notout, s, c2; oflag = tp->t_oflag; if (!ISSET(oflag, OPOST)) { tk_nout++; tp->t_outcc++; if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq)) return (c); return (-1); } /* * Do tab expansion if OXTABS is set. Special case if we external * processing, we don't do the tab expansion because we'll probably * get it wrong. If tab expansion needs to be done, let it happen * externally. */ CLR(c, ~TTY_CHARMASK); if (c == '\t' && ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) { c = 8 - (tp->t_column & 7); if (ISSET(tp->t_lflag, FLUSHO)) { notout = 0; } else { s = spltty(); /* Don't interrupt tabs. */ notout = b_to_q(" ", c, &tp->t_outq); c -= notout; tk_nout += c; tp->t_outcc += c; splx(s); } tp->t_column += c; return (notout ? '\t' : -1); } if (c == CEOT && ISSET(oflag, ONOEOT)) return (-1); /* * Newline translation: if ONLCR is set, * translate newline into "\r\n". If OCRNL * is set, translate '\r' into '\n'. */ if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) { tk_nout++; tp->t_outcc++; if (!ISSET(tp->t_lflag, FLUSHO) && putc('\r', &tp->t_outq)) return (c); tp->t_column = 0; } else if (c == '\r' && ISSET(tp->t_oflag, OCRNL)) c = '\n'; if (ISSET(tp->t_oflag, OLCUC) && islower(c)) c = toupper(c); else if (ISSET(tp->t_oflag, OLCUC) && ISSET(tp->t_lflag, XCASE)) { c2 = c; switch (c) { case '`': c2 = '\''; break; case '|': c2 = '!'; break; case '~': c2 = '^'; break; case '{': c2 = '('; break; case '}': c2 = ')'; break; } if (c == '\\' || isupper(c) || c != c2) { tk_nout++; tp->t_outcc++; if (putc('\\', &tp->t_outq)) return (c); c = c2; } } if (ISSET(tp->t_oflag, ONOCR) && c == '\r' && tp->t_column == 0) return (-1); tk_nout++; tp->t_outcc++; if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq)) return (c); col = tp->t_column; switch (CCLASS(c)) { case BACKSPACE: if (col > 0) --col; break; case CONTROL: break; case NEWLINE: if (ISSET(tp->t_oflag, ONLRET) || ISSET(tp->t_oflag, OCRNL)) col = 0; break; case RETURN: col = 0; break; case ORDINARY: ++col; break; case TAB: col = (col + 8) & ~7; break; } tp->t_column = col; return (-1); } /* * Ioctls for all tty devices. Called after line-discipline specific ioctl * has been called to do discipline-specific functions and/or reject any * of these ioctl commands. */ int ttioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p) { extern int nlinesw; struct process *pr = p->p_p; int s, error; /* If the ioctl involves modification, hang if in the background. */ switch (cmd) { case FIOSETOWN: case TIOCFLUSH: case TIOCDRAIN: case TIOCSBRK: case TIOCCBRK: case TIOCSETA: case TIOCSETD: case TIOCSETAF: case TIOCSETAW: case TIOCSPGRP: case TIOCSTAT: case TIOCSWINSZ: while (isbackground(pr, tp) && (pr->ps_flags & PS_PPWAIT) == 0 && !sigismasked(p, SIGTTOU)) { if (pr->ps_pgrp->pg_jobc == 0) return (EIO); pgsignal(pr->ps_pgrp, SIGTTOU, 1); error = ttysleep(tp, &lbolt, TTOPRI | PCATCH, ttybg); if (error) return (error); } break; } switch (cmd) { /* Process the ioctl. */ case FIOASYNC: /* set/clear async i/o */ s = spltty(); if (*(int *)data) SET(tp->t_state, TS_ASYNC); else CLR(tp->t_state, TS_ASYNC); splx(s); break; case FIONBIO: /* set/clear non-blocking i/o */ break; /* XXX: delete. */ case FIONREAD: /* get # bytes to read */ s = spltty(); *(int *)data = ttnread(tp); splx(s); break; case TIOCEXCL: /* set exclusive use of tty */ s = spltty(); SET(tp->t_state, TS_XCLUDE); splx(s); break; case TIOCFLUSH: { /* flush buffers */ int flags = *(int *)data; if (flags == 0) flags = FREAD | FWRITE; else flags &= FREAD | FWRITE; ttyflush(tp, flags); break; } case TIOCCONS: { /* become virtual console */ if (*(int *)data) { struct nameidata nid; if (constty != NULL && constty != tp && ISSET(constty->t_state, TS_CARR_ON | TS_ISOPEN) == (TS_CARR_ON | TS_ISOPEN)) return (EBUSY); /* ensure user can open the real console */ NDINIT(&nid, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/console", p); nid.ni_pledge = PLEDGE_RPATH | PLEDGE_WPATH; nid.ni_unveil = UNVEIL_READ | UNVEIL_WRITE; error = namei(&nid); if (error) return (error); vn_lock(nid.ni_vp, LK_EXCLUSIVE | LK_RETRY); error = VOP_ACCESS(nid.ni_vp, VREAD, p->p_ucred, p); VOP_UNLOCK(nid.ni_vp); vrele(nid.ni_vp); if (error) return (error); constty = tp; } else if (tp == constty) constty = NULL; break; } case TIOCDRAIN: /* wait till output drained */ if ((error = ttywait(tp)) != 0) return (error); break; case TIOCGETA: { /* get termios struct */ struct termios *t = (struct termios *)data; memcpy(t, &tp->t_termios, sizeof(struct termios)); break; } case TIOCGETD: /* get line discipline */ *(int *)data = tp->t_line; break; case TIOCGWINSZ: /* get window size */ *(struct winsize *)data = tp->t_winsize; break; case TIOCGTSTAMP: s = spltty(); *(struct timeval *)data = tp->t_tv; splx(s); break; case FIOGETOWN: /* get pgrp of tty */ if (!isctty(pr, tp) && suser(p)) return (ENOTTY); *(int *)data = tp->t_pgrp ? -tp->t_pgrp->pg_id : 0; break; case TIOCGPGRP: /* get pgrp of tty */ if (!isctty(pr, tp) && suser(p)) return (ENOTTY); *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; break; case TIOCGSID: /* get sid of tty */ if (!isctty(pr, tp)) return (ENOTTY); *(int *)data = tp->t_session->s_leader->ps_pid; break; case TIOCNXCL: /* reset exclusive use of tty */ s = spltty(); CLR(tp->t_state, TS_XCLUDE); splx(s); break; case TIOCOUTQ: /* output queue size */ *(int *)data = tp->t_outq.c_cc; break; case TIOCSETA: /* set termios struct */ case TIOCSETAW: /* drain output, set */ case TIOCSETAF: { /* drn out, fls in, set */ struct termios *t = (struct termios *)data; s = spltty(); if (cmd == TIOCSETAW || cmd == TIOCSETAF) { if ((error = ttywait(tp)) != 0) { splx(s); return (error); } if (cmd == TIOCSETAF) ttyflush(tp, FREAD); } if (!ISSET(t->c_cflag, CIGNORE)) { /* * Some minor validation is necessary. */ if (t->c_ispeed < 0 || t->c_ospeed < 0) { splx(s); return (EINVAL); } /* * Set device hardware. */ if (tp->t_param && (error = (*tp->t_param)(tp, t))) { splx(s); return (error); } else { if (!ISSET(tp->t_state, TS_CARR_ON) && ISSET(tp->t_cflag, CLOCAL) && !ISSET(t->c_cflag, CLOCAL)) { CLR(tp->t_state, TS_ISOPEN); SET(tp->t_state, TS_WOPEN); ttwakeup(tp); } tp->t_cflag = t->c_cflag; tp->t_ispeed = t->c_ispeed; tp->t_ospeed = t->c_ospeed; if (t->c_ospeed == 0 && tp->t_session && tp->t_session->s_leader) prsignal(tp->t_session->s_leader, SIGHUP); } ttsetwater(tp); } if (cmd != TIOCSETAF) { if (ISSET(t->c_lflag, ICANON) != ISSET(tp->t_lflag, ICANON)) { if (ISSET(t->c_lflag, ICANON)) { SET(tp->t_lflag, PENDIN); ttwakeup(tp); } else { struct clist tq; catq(&tp->t_rawq, &tp->t_canq); tq = tp->t_rawq; tp->t_rawq = tp->t_canq; tp->t_canq = tq; CLR(tp->t_lflag, PENDIN); } } } tp->t_iflag = t->c_iflag; tp->t_oflag = t->c_oflag; /* * Make the EXTPROC bit read only. */ if (ISSET(tp->t_lflag, EXTPROC)) SET(t->c_lflag, EXTPROC); else CLR(t->c_lflag, EXTPROC); tp->t_lflag = t->c_lflag | ISSET(tp->t_lflag, PENDIN); memcpy(tp->t_cc, t->c_cc, sizeof(t->c_cc)); splx(s); break; } case TIOCSETD: { /* set line discipline */ int t = *(int *)data; dev_t device = tp->t_dev; if ((u_int)t >= nlinesw) return (ENXIO); if (t != tp->t_line) { s = spltty(); (*linesw[tp->t_line].l_close)(tp, flag, p); error = (*linesw[t].l_open)(device, tp, p); if (error) { (*linesw[tp->t_line].l_open)(device, tp, p); splx(s); return (error); } tp->t_line = t; splx(s); } break; } case TIOCSTART: /* start output, like ^Q */ s = spltty(); if (ISSET(tp->t_state, TS_TTSTOP) || ISSET(tp->t_lflag, FLUSHO)) { CLR(tp->t_lflag, FLUSHO); CLR(tp->t_state, TS_TTSTOP); ttstart(tp); } splx(s); break; case TIOCSTOP: /* stop output, like ^S */ s = spltty(); if (!ISSET(tp->t_state, TS_TTSTOP)) { SET(tp->t_state, TS_TTSTOP); (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); } splx(s); break; case TIOCSCTTY: /* become controlling tty */ /* Session ctty vnode pointer set in vnode layer. */ if (!SESS_LEADER(pr) || ((pr->ps_session->s_ttyvp || tp->t_session) && (tp->t_session != pr->ps_session))) return (EPERM); if (tp->t_session) SESSRELE(tp->t_session); SESSHOLD(pr->ps_session); tp->t_session = pr->ps_session; tp->t_pgrp = pr->ps_pgrp; pr->ps_session->s_ttyp = tp; atomic_setbits_int(&pr->ps_flags, PS_CONTROLT); break; case FIOSETOWN: { /* set pgrp of tty */ struct pgrp *pgrp; struct process *pr1; pid_t pgid = *(int *)data; if (!isctty(pr, tp)) return (ENOTTY); if (pgid < 0) { pgrp = pgfind(-pgid); } else { pr1 = prfind(pgid); if (pr1 == NULL) return (ESRCH); pgrp = pr1->ps_pgrp; } if (pgrp == NULL) return (EINVAL); else if (pgrp->pg_session != pr->ps_session) return (EPERM); tp->t_pgrp = pgrp; break; } case TIOCSPGRP: { /* set pgrp of tty */ struct pgrp *pgrp = pgfind(*(int *)data); if (!isctty(pr, tp)) return (ENOTTY); else if (pgrp == NULL) return (EINVAL); else if (pgrp->pg_session != pr->ps_session) return (EPERM); tp->t_pgrp = pgrp; break; } case TIOCSTAT: /* get load avg stats */ ttyinfo(tp); break; case TIOCSWINSZ: /* set window size */ if (bcmp((caddr_t)&tp->t_winsize, data, sizeof (struct winsize))) { tp->t_winsize = *(struct winsize *)data; pgsignal(tp->t_pgrp, SIGWINCH, 1); } break; case TIOCSTSTAMP: { struct tstamps *ts = (struct tstamps *)data; s = spltty(); CLR(tp->t_flags, TS_TSTAMPDCDSET); CLR(tp->t_flags, TS_TSTAMPCTSSET); CLR(tp->t_flags, TS_TSTAMPDCDCLR); CLR(tp->t_flags, TS_TSTAMPCTSCLR); if (ISSET(ts->ts_set, TIOCM_CAR)) SET(tp->t_flags, TS_TSTAMPDCDSET); if (ISSET(ts->ts_set, TIOCM_CTS)) SET(tp->t_flags, TS_TSTAMPCTSSET); if (ISSET(ts->ts_clr, TIOCM_CAR)) SET(tp->t_flags, TS_TSTAMPDCDCLR); if (ISSET(ts->ts_clr, TIOCM_CTS)) SET(tp->t_flags, TS_TSTAMPCTSCLR); splx(s); break; } default: return (-1); } return (0); } const struct filterops ttyread_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, .f_detach = filt_ttyrdetach, .f_event = filt_ttyread, }; const struct filterops ttywrite_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, .f_detach = filt_ttywdetach, .f_event = filt_ttywrite, }; const struct filterops ttyexcept_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, .f_detach = filt_ttyrdetach, .f_event = filt_ttyexcept, }; int ttkqfilter(dev_t dev, struct knote *kn) { struct tty *tp = (*cdevsw[major(dev)].d_tty)(dev); struct klist *klist; int s; switch (kn->kn_filter) { case EVFILT_READ: klist = &tp->t_rsel.si_note; kn->kn_fop = &ttyread_filtops; break; case EVFILT_WRITE: klist = &tp->t_wsel.si_note; kn->kn_fop = &ttywrite_filtops; break; case EVFILT_EXCEPT: if (kn->kn_flags & __EV_SELECT) { /* Prevent triggering exceptfds. */ return (EPERM); } if ((kn->kn_flags & __EV_POLL) == 0) { /* Disallow usage through kevent(2). */ return (EINVAL); } klist = &tp->t_rsel.si_note; kn->kn_fop = &ttyexcept_filtops; break; default: return (EINVAL); } kn->kn_hook = tp; s = spltty(); klist_insert_locked(klist, kn); splx(s); return (0); } void filt_ttyrdetach(struct knote *kn) { struct tty *tp = kn->kn_hook; int s; s = spltty(); klist_remove_locked(&tp->t_rsel.si_note, kn); splx(s); } int filt_ttyread(struct knote *kn, long hint) { struct tty *tp = kn->kn_hook; int active, s; s = spltty(); kn->kn_data = ttnread(tp); active = (kn->kn_data > 0); if (!ISSET(tp->t_cflag, CLOCAL) && !ISSET(tp->t_state, TS_CARR_ON)) { kn->kn_flags |= EV_EOF; if (kn->kn_flags & __EV_POLL) kn->kn_flags |= __EV_HUP; active = 1; } else { kn->kn_flags &= ~(EV_EOF | __EV_HUP); } splx(s); return (active); } void filt_ttywdetach(struct knote *kn) { struct tty *tp = kn->kn_hook; int s; s = spltty(); klist_remove_locked(&tp->t_wsel.si_note, kn); splx(s); } int filt_ttywrite(struct knote *kn, long hint) { struct tty *tp = kn->kn_hook; int active, s; s = spltty(); kn->kn_data = tp->t_outq.c_cn - tp->t_outq.c_cc; active = (tp->t_outq.c_cc <= tp->t_lowat); /* Write-side HUP condition is only for poll(2) and select(2). */ if (kn->kn_flags & (__EV_POLL | __EV_SELECT)) { if (!ISSET(tp->t_cflag, CLOCAL) && !ISSET(tp->t_state, TS_CARR_ON)) { kn->kn_flags |= __EV_HUP; active = 1; } else { kn->kn_flags &= ~__EV_HUP; } } splx(s); return (active); } int filt_ttyexcept(struct knote *kn, long hint) { struct tty *tp = kn->kn_hook; int active = 0; int s; s = spltty(); if (kn->kn_flags & __EV_POLL) { if (!ISSET(tp->t_cflag, CLOCAL) && !ISSET(tp->t_state, TS_CARR_ON)) { kn->kn_flags |= __EV_HUP; active = 1; } else { kn->kn_flags &= ~__EV_HUP; } } splx(s); return (active); } static int ttnread(struct tty *tp) { int nread; splassert(IPL_TTY); if (ISSET(tp->t_lflag, PENDIN)) ttypend(tp); nread = tp->t_canq.c_cc; if (!ISSET(tp->t_lflag, ICANON)) { nread += tp->t_rawq.c_cc; if (nread < tp->t_cc[VMIN] && !tp->t_cc[VTIME]) nread = 0; } return (nread); } /* * Wait for output to drain, or if this times out, flush it. */ int ttywait_nsec(struct tty *tp, uint64_t nsecs) { int error, s; error = 0; s = spltty(); while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) && (ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL)) && tp->t_oproc) { (*tp->t_oproc)(tp); if ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) && (ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL)) && tp->t_oproc) { SET(tp->t_state, TS_ASLEEP); error = ttysleep_nsec(tp, &tp->t_outq, TTOPRI | PCATCH, ttyout, nsecs); if (error == EWOULDBLOCK) ttyflush(tp, FWRITE); if (error) break; } else break; } splx(s); return (error); } int ttywait(struct tty *tp) { return (ttywait_nsec(tp, INFSLP)); } /* * Flush if successfully wait. */ int ttywflush(struct tty *tp) { int error; error = ttywait_nsec(tp, SEC_TO_NSEC(5)); if (error == 0 || error == EWOULDBLOCK) ttyflush(tp, FREAD); return (error); } /* * Flush tty read and/or write queues, notifying anyone waiting. */ void ttyflush(struct tty *tp, int rw) { int s; s = spltty(); if (rw & FREAD) { FLUSHQ(&tp->t_canq); FLUSHQ(&tp->t_rawq); tp->t_rocount = 0; tp->t_rocol = 0; CLR(tp->t_state, TS_LOCAL); ttyunblock(tp); ttwakeup(tp); } if (rw & FWRITE) { CLR(tp->t_state, TS_TTSTOP); (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw); FLUSHQ(&tp->t_outq); wakeup((caddr_t)&tp->t_outq); selwakeup(&tp->t_wsel); } splx(s); } /* * Copy in the default termios characters. */ void ttychars(struct tty *tp) { memcpy(tp->t_cc, ttydefchars, sizeof(ttydefchars)); } /* * Send stop character on input overflow. */ static void ttyblock(struct tty *tp) { int total; total = tp->t_rawq.c_cc + tp->t_canq.c_cc; if (tp->t_rawq.c_cc > TTYHOG(tp)) { ttyflush(tp, FREAD | FWRITE); CLR(tp->t_state, TS_TBLOCK); } /* * Block further input iff: current input > threshold * AND input is available to user program. */ if ((total >= TTYHOG(tp) / 2 && !ISSET(tp->t_state, TS_TBLOCK) && !ISSET(tp->t_lflag, ICANON)) || tp->t_canq.c_cc > 0) { if (ISSET(tp->t_iflag, IXOFF) && tp->t_cc[VSTOP] != _POSIX_VDISABLE && putc(tp->t_cc[VSTOP], &tp->t_outq) == 0) { SET(tp->t_state, TS_TBLOCK); ttstart(tp); } /* Try to block remote output via hardware flow control. */ if (ISSET(tp->t_cflag, CHWFLOW) && tp->t_hwiflow && (*tp->t_hwiflow)(tp, 1) != 0) SET(tp->t_state, TS_TBLOCK); } } void ttrstrt(void *arg) { struct tty *tp = (struct tty *)arg; int s; #ifdef DIAGNOSTIC if (tp == NULL) panic("ttrstrt"); #endif s = spltty(); CLR(tp->t_state, TS_TIMEOUT); ttstart(tp); splx(s); } int ttstart(struct tty *tp) { if (tp->t_oproc != NULL) /* XXX: Kludge for pty. */ (*tp->t_oproc)(tp); return (0); } /* * "close" a line discipline */ int ttylclose(struct tty *tp, int flag, struct proc *p) { if (flag & FNONBLOCK) ttyflush(tp, FREAD | FWRITE); else ttywflush(tp); return (0); } /* * Handle modem control transition on a tty. * Flag indicates new state of carrier. * Returns 0 if the line should be turned off, otherwise 1. */ int ttymodem(struct tty *tp, int flag) { if (!ISSET(tp->t_state, TS_WOPEN) && ISSET(tp->t_cflag, MDMBUF)) { /* * MDMBUF: do flow control according to carrier flag */ if (flag) { CLR(tp->t_state, TS_TTSTOP); ttstart(tp); } else if (!ISSET(tp->t_state, TS_TTSTOP)) { SET(tp->t_state, TS_TTSTOP); (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); } } else if (flag == 0) { /* * Lost carrier. */ CLR(tp->t_state, TS_CARR_ON); if (ISSET(tp->t_state, TS_ISOPEN) && !ISSET(tp->t_cflag, CLOCAL)) { if (tp->t_session && tp->t_session->s_leader) prsignal(tp->t_session->s_leader, SIGHUP); ttyflush(tp, FREAD | FWRITE); return (0); } } else { /* * Carrier now on. */ SET(tp->t_state, TS_CARR_ON); ttwakeup(tp); } return (1); } /* * Default modem control routine (for other line disciplines). * Return argument flag, to turn off device on carrier drop. */ int nullmodem(struct tty *tp, int flag) { if (flag) SET(tp->t_state, TS_CARR_ON); else { CLR(tp->t_state, TS_CARR_ON); if (ISSET(tp->t_state, TS_ISOPEN) && !ISSET(tp->t_cflag, CLOCAL)) { if (tp->t_session && tp->t_session->s_leader) prsignal(tp->t_session->s_leader, SIGHUP); ttyflush(tp, FREAD | FWRITE); return (0); } } return (1); } /* * Reinput pending characters after state switch * call at spltty(). */ void ttypend(struct tty *tp) { struct clist tq; int c; splassert(IPL_TTY); CLR(tp->t_lflag, PENDIN); SET(tp->t_state, TS_TYPEN); tq = tp->t_rawq; tp->t_rawq.c_cc = 0; tp->t_rawq.c_cf = tp->t_rawq.c_cl = NULL; while ((c = getc(&tq)) >= 0) ttyinput(c, tp); CLR(tp->t_state, TS_TYPEN); } void ttvtimeout(void *); void ttvtimeout(void *arg) { struct tty *tp = (struct tty *)arg; wakeup(&tp->t_rawq); } /* * Process a read call on a tty device. */ int ttread(struct tty *tp, struct uio *uio, int flag) { struct timeout *stime = NULL; struct proc *p = curproc; struct process *pr = p->p_p; int s, first, error = 0; u_char *cc = tp->t_cc; struct clist *qp; int last_cc = 0; long lflag; int c; loop: lflag = tp->t_lflag; s = spltty(); /* * take pending input first */ if (ISSET(lflag, PENDIN)) ttypend(tp); splx(s); /* * Hang process if it's in the background. */ if (isbackground(pr, tp)) { if (sigismasked(p, SIGTTIN) || pr->ps_flags & PS_PPWAIT || pr->ps_pgrp->pg_jobc == 0) { error = EIO; goto out; } pgsignal(pr->ps_pgrp, SIGTTIN, 1); error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg); if (error) goto out; goto loop; } s = spltty(); if (!ISSET(lflag, ICANON)) { int min = cc[VMIN]; int time = cc[VTIME] * 100; /* tenths of a second (ms) */ qp = &tp->t_rawq; /* * Check each of the four combinations. * (min > 0 && time == 0) is the normal read case. * It should be fairly efficient, so we check that and its * companion case (min == 0 && time == 0) first. */ if (time == 0) { if (qp->c_cc < min) goto sleep; goto read; } if (min > 0) { if (qp->c_cc <= 0) goto sleep; if (qp->c_cc >= min) goto read; if (stime == NULL) { alloc_timer: stime = malloc(sizeof(*stime), M_TEMP, M_WAITOK); timeout_set(stime, ttvtimeout, tp); timeout_add_msec(stime, time); } else if (qp->c_cc > last_cc) { /* got a character, restart timer */ timeout_add_msec(stime, time); } } else { /* min == 0 */ if (qp->c_cc > 0) goto read; if (stime == NULL) { goto alloc_timer; } } last_cc = qp->c_cc; if (stime && !timeout_triggered(stime)) { goto sleep; } } else if ((qp = &tp->t_canq)->c_cc <= 0) { int carrier; sleep: /* * If there is no input, sleep on rawq * awaiting hardware receipt and notification. * If we have data, we don't need to check for carrier. */ carrier = ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL); if (!carrier && ISSET(tp->t_state, TS_ISOPEN)) { splx(s); error = 0; goto out; } if (flag & IO_NDELAY) { splx(s); error = EWOULDBLOCK; goto out; } error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, carrier ? ttyin : ttopen); splx(s); if (stime && timeout_triggered(stime)) error = EWOULDBLOCK; if (cc[VMIN] == 0 && error == EWOULDBLOCK) { error = 0; goto out; } if (error && error != EWOULDBLOCK) goto out; error = 0; goto loop; } read: splx(s); /* * Input present, check for input mapping and processing. */ first = 1; while ((c = getc(qp)) >= 0) { /* * delayed suspend (^Y) */ if (CCEQ(cc[VDSUSP], c) && ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG)) { pgsignal(tp->t_pgrp, SIGTSTP, 1); if (first) { error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg); if (error) break; goto loop; } break; } /* * Interpret EOF only in canonical mode. */ if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON)) break; /* * Give user character. */ error = ureadc(c, uio); if (error) break; if (uio->uio_resid == 0) break; /* * In canonical mode check for a "break character" * marking the end of a "line of input". */ if (ISSET(lflag, ICANON) && TTBREAKC(c, lflag)) break; first = 0; } /* * Look to unblock output now that (presumably) * the input queue has gone down. */ s = spltty(); if (tp->t_rawq.c_cc < TTYHOG(tp)/5) ttyunblock(tp); splx(s); out: if (stime) { timeout_del(stime); free(stime, M_TEMP, sizeof(*stime)); } return (error); } /* Call at spltty */ void ttyunblock(struct tty *tp) { u_char *cc = tp->t_cc; splassert(IPL_TTY); if (ISSET(tp->t_state, TS_TBLOCK)) { if (ISSET(tp->t_iflag, IXOFF) && cc[VSTART] != _POSIX_VDISABLE && putc(cc[VSTART], &tp->t_outq) == 0) { CLR(tp->t_state, TS_TBLOCK); ttstart(tp); } /* Try to unblock remote output via hardware flow control. */ if (ISSET(tp->t_cflag, CHWFLOW) && tp->t_hwiflow && (*tp->t_hwiflow)(tp, 0) != 0) CLR(tp->t_state, TS_TBLOCK); } } /* * Check the output queue on tp for space for a kernel message (from uprintf * or tprintf). Allow some space over the normal hiwater mark so we don't * lose messages due to normal flow control, but don't let the tty run amok. * Sleeps here are not interruptible, but we return prematurely if new signals * arrive. */ int ttycheckoutq(struct tty *tp, int wait) { int hiwat, s, oldsig; hiwat = tp->t_hiwat; s = spltty(); oldsig = wait ? SIGPENDING(curproc) : 0; if (tp->t_outq.c_cc > hiwat + TTHIWATMINSPACE) while (tp->t_outq.c_cc > hiwat) { ttstart(tp); if (wait == 0 || SIGPENDING(curproc) != oldsig) { splx(s); return (0); } SET(tp->t_state, TS_ASLEEP); tsleep_nsec(&tp->t_outq, PZERO - 1, "ttckoutq", SEC_TO_NSEC(1)); } splx(s); return (1); } /* * Process a write call on a tty device. */ int ttwrite(struct tty *tp, struct uio *uio, int flag) { u_char *cp = NULL; int cc, ce, obufcc = 0; struct proc *p; struct process *pr; int hiwat, error, s; size_t cnt; u_char obuf[OBUFSIZ]; hiwat = tp->t_hiwat; cnt = uio->uio_resid; error = 0; cc = 0; loop: s = spltty(); if (!ISSET(tp->t_state, TS_CARR_ON) && !ISSET(tp->t_cflag, CLOCAL)) { if (ISSET(tp->t_state, TS_ISOPEN)) { splx(s); error = EIO; goto done; } else if (flag & IO_NDELAY) { splx(s); error = EWOULDBLOCK; goto out; } else { /* Sleep awaiting carrier. */ error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, ttopen); splx(s); if (error) goto out; goto loop; } } splx(s); /* * Hang the process if it's in the background. */ p = curproc; pr = p->p_p; if (isbackground(pr, tp) && ISSET(tp->t_lflag, TOSTOP) && (pr->ps_flags & PS_PPWAIT) == 0 && !sigismasked(p, SIGTTOU)) { if (pr->ps_pgrp->pg_jobc == 0) { error = EIO; goto out; } pgsignal(pr->ps_pgrp, SIGTTOU, 1); error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg); if (error) goto out; goto loop; } /* * Process the user's data in at most OBUFSIZ chunks. Perform any * output translation. Keep track of high water mark, sleep on * overflow awaiting device aid in acquiring new space. */ while (uio->uio_resid > 0 || cc > 0) { if (ISSET(tp->t_lflag, FLUSHO)) { uio->uio_resid = 0; goto done; } if (tp->t_outq.c_cc > hiwat) goto ovhiwat; /* * Grab a hunk of data from the user, unless we have some * leftover from last time. */ if (cc == 0) { cc = MIN(uio->uio_resid, OBUFSIZ); cp = obuf; error = uiomove(cp, cc, uio); if (error) { cc = 0; break; } if (cc > obufcc) obufcc = cc; /* duplicate /dev/console output into console buffer */ if (consbufp && cn_tab && cn_tab->cn_dev == tp->t_dev && tp->t_gen == 0) { int i; for (i = 0; i < cc; i++) { char c = cp[i]; if (c != '\0' && c != '\r' && c != 0177) msgbuf_putchar(consbufp, c); } } } /* * If nothing fancy need be done, grab those characters we * can handle without any of ttyoutput's processing and * just transfer them to the output q. For those chars * which require special processing (as indicated by the * bits in char_type), call ttyoutput. After processing * a hunk of data, look for FLUSHO so ^O's will take effect * immediately. */ while (cc > 0) { int i; if (!ISSET(tp->t_oflag, OPOST)) ce = cc; else { ce = cc - scanc((u_int)cc, cp, char_type, CCLASSMASK); /* * If ce is zero, then we're processing * a special character through ttyoutput. */ if (ce == 0) { tp->t_rocount = 0; if (ttyoutput(*cp, tp) >= 0) { /* out of space */ goto ovhiwat; } cp++; cc--; if (ISSET(tp->t_lflag, FLUSHO) || tp->t_outq.c_cc > hiwat) goto ovhiwat; continue; } } /* * A bunch of normal characters have been found. * Transfer them en masse to the output queue and * continue processing at the top of the loop. * If there are any further characters in this * <= OBUFSIZ chunk, the first should be a character * requiring special handling by ttyoutput. */ tp->t_rocount = 0; i = b_to_q(cp, ce, &tp->t_outq); ce -= i; tp->t_column += ce; cp += ce, cc -= ce, tk_nout += ce; tp->t_outcc += ce; if (i > 0) { /* out of space */ goto ovhiwat; } if (ISSET(tp->t_lflag, FLUSHO) || tp->t_outq.c_cc > hiwat) break; } ttstart(tp); } out: /* * If cc is nonzero, we leave the uio structure inconsistent, as the * offset and iov pointers have moved forward, but it doesn't matter * (the call will either return short or restart with a new uio). */ uio->uio_resid += cc; done: if (obufcc) explicit_bzero(obuf, obufcc); return (error); ovhiwat: ttstart(tp); s = spltty(); /* * This can only occur if FLUSHO is set in t_lflag, * or if ttstart/oproc is synchronous (or very fast). */ if (tp->t_outq.c_cc <= hiwat) { splx(s); goto loop; } if (flag & IO_NDELAY) { splx(s); uio->uio_resid += cc; if (obufcc) explicit_bzero(obuf, obufcc); return (uio->uio_resid == cnt ? EWOULDBLOCK : 0); } SET(tp->t_state, TS_ASLEEP); error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, ttyout); splx(s); if (error) goto out; goto loop; } /* * Rubout one character from the rawq of tp * as cleanly as possible. */ int ttyrub(int c, struct tty *tp) { u_char *cp; int savecol; int tabc, s, cc; if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC)) return 0; CLR(tp->t_lflag, FLUSHO); if (ISSET(tp->t_lflag, ECHOE)) { if (tp->t_rocount == 0) { /* * Screwed by ttwrite; retype */ return ttyretype(tp); } if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE)) ttyrubo(tp, 2); else { CLR(c, ~TTY_CHARMASK); switch (CCLASS(c)) { case ORDINARY: ttyrubo(tp, 1); break; case BACKSPACE: case CONTROL: case NEWLINE: case RETURN: case VTAB: if (ISSET(tp->t_lflag, ECHOCTL)) ttyrubo(tp, 2); break; case TAB: if (tp->t_rocount < tp->t_rawq.c_cc) return ttyretype(tp); s = spltty(); savecol = tp->t_column; SET(tp->t_state, TS_CNTTB); SET(tp->t_lflag, FLUSHO); tp->t_column = tp->t_rocol; for (cp = firstc(&tp->t_rawq, &tabc, &cc); cp; cp = nextc(&tp->t_rawq, cp, &tabc, &cc)) ttyecho(tabc, tp); CLR(tp->t_lflag, FLUSHO); CLR(tp->t_state, TS_CNTTB); splx(s); /* savecol will now be length of the tab. */ savecol -= tp->t_column; tp->t_column += savecol; if (savecol > 8) savecol = 8; /* overflow screw */ while (--savecol >= 0) (void)ttyoutput('\b', tp); break; default: /* XXX */ #define PANICSTR "ttyrub: would panic c = %d, val = %d" (void)printf(PANICSTR "\n", c, CCLASS(c)); #ifdef notdef panic(PANICSTR, c, CCLASS(c)); #endif } } } else if (ISSET(tp->t_lflag, ECHOPRT)) { if (!ISSET(tp->t_state, TS_ERASE)) { SET(tp->t_state, TS_ERASE); (void)ttyoutput('\\', tp); } ttyecho(c, tp); } else ttyecho(tp->t_cc[VERASE], tp); --tp->t_rocount; return 0; } /* * Back over cnt characters, erasing them. */ static void ttyrubo(struct tty *tp, int cnt) { while (cnt-- > 0) { (void)ttyoutput('\b', tp); (void)ttyoutput(' ', tp); (void)ttyoutput('\b', tp); } } /* * ttyretype -- * Reprint the rawq line. Note, it is assumed that c_cc has already * been checked. */ int ttyretype(struct tty *tp) { u_char *cp; int s, c, cc; /* Echo the reprint character. */ if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE) ttyecho(tp->t_cc[VREPRINT], tp); (void)ttyoutput('\n', tp); s = spltty(); for (cp = firstc(&tp->t_canq, &c, &cc); cp; cp = nextc(&tp->t_canq, cp, &c, &cc)) ttyecho(c, tp); for (cp = firstc(&tp->t_rawq, &c, &cc); cp; cp = nextc(&tp->t_rawq, cp, &c, &cc)) ttyecho(c, tp); CLR(tp->t_state, TS_ERASE); splx(s); tp->t_rocount = tp->t_rawq.c_cc; tp->t_rocol = 0; return (1); } /* * Echo a typed character to the terminal. */ static void ttyecho(int c, struct tty *tp) { if (!ISSET(tp->t_state, TS_CNTTB)) CLR(tp->t_lflag, FLUSHO); if ((!ISSET(tp->t_lflag, ECHO) && (!ISSET(tp->t_lflag, ECHONL) || c != '\n')) || ISSET(tp->t_lflag, EXTPROC)) return; if (((ISSET(tp->t_lflag, ECHOCTL) && (ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n')) || ISSET(c, TTY_CHARMASK) == 0177)) { (void)ttyoutput('^', tp); CLR(c, ~TTY_CHARMASK); if (c == 0177) c = '?'; else c += 'A' - 1; } (void)ttyoutput(c, tp); } /* * Wakeup any writers if necessary. */ void ttwakeupwr(struct tty *tp) { if (tp->t_outq.c_cc <= tp->t_lowat) { if (ISSET(tp->t_state, TS_ASLEEP)) { CLR(tp->t_state, TS_ASLEEP); wakeup(&tp->t_outq); } selwakeup(&tp->t_wsel); } } /* * Wake up any readers on a tty. */ void ttwakeup(struct tty *tp) { selwakeup(&tp->t_rsel); if (ISSET(tp->t_state, TS_ASYNC)) pgsignal(tp->t_pgrp, SIGIO, 1); wakeup((caddr_t)&tp->t_rawq); } /* * Look up a code for a specified speed in a conversion table; * used by drivers to map software speed values to hardware parameters. */ int ttspeedtab(int speed, const struct speedtab *table) { for ( ; table->sp_speed != -1; table++) if (table->sp_speed == speed) return (table->sp_code); return (-1); } /* * Set tty hi and low water marks. * * Try to arrange the dynamics so there's about one second * from hi to low water. */ void ttsetwater(struct tty *tp) { int cps, x; #define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x)) cps = tp->t_ospeed / 10; tp->t_lowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT); x += cps; tp->t_hiwat = CLAMP(x, tp->t_outq.c_cn - TTHIWATMINSPACE, TTMINHIWAT); #undef CLAMP } /* * Get the total estcpu for a process, summing across threads. * Returns true if at least one thread is runnable/running. */ static int process_sum(struct process *pr, fixpt_t *estcpup) { struct proc *p; fixpt_t estcpu; int ret; ret = 0; estcpu = 0; TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) { if (p->p_stat == SRUN || p->p_stat == SONPROC) ret = 1; estcpu += p->p_pctcpu; } *estcpup = estcpu; return (ret); } /* * Report on state of foreground process group. */ void ttyinfo(struct tty *tp) { struct process *pr, *pickpr; struct proc *p, *pick; struct timespec utime, stime; int tmp; if (ttycheckoutq(tp,0) == 0) return; /* Print load average. */ tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT; ttyprintf(tp, "load: %d.%02d ", tmp / 100, tmp % 100); if (tp->t_session == NULL) ttyprintf(tp, "not a controlling terminal\n"); else if (tp->t_pgrp == NULL) ttyprintf(tp, "no foreground process group\n"); else if ((pr = LIST_FIRST(&tp->t_pgrp->pg_members)) == NULL) empty: ttyprintf(tp, "empty foreground process group\n"); else { const char *state; fixpt_t pctcpu, pctcpu2; int run, run2; int calc_pctcpu; long rss = 0; /* * Pick the most active process: * - prefer at least one running/runnable thread * - prefer higher total pctcpu * - prefer non-zombie * Otherwise take the most recently added to this process group */ pickpr = pr; run = process_sum(pickpr, &pctcpu); while ((pr = LIST_NEXT(pr, ps_pglist)) != NULL) { run2 = process_sum(pr, &pctcpu2); if (run) { /* * pick is running; is p running w/same or * more cpu? */ if (run2 && pctcpu2 >= pctcpu) goto update_pickpr; continue; } /* pick isn't running; is p running *or* w/more cpu? */ if (run2 || pctcpu2 > pctcpu) goto update_pickpr; /* if p has less cpu or is zombie, then it's worse */ if (pctcpu2 < pctcpu || (pr->ps_flags & PS_ZOMBIE)) continue; update_pickpr: pickpr = pr; run = run2; pctcpu = pctcpu2; } /* Calculate percentage cpu, resident set size. */ calc_pctcpu = (pctcpu * 10000 + FSCALE / 2) >> FSHIFT; if ((pickpr->ps_flags & (PS_EMBRYO | PS_ZOMBIE)) == 0 && pickpr->ps_vmspace != NULL) rss = vm_resident_count(pickpr->ps_vmspace); calctsru(&pickpr->ps_tu, &utime, &stime, NULL); /* Round up and print user time. */ utime.tv_nsec += 5000000; if (utime.tv_nsec >= 1000000000) { utime.tv_sec += 1; utime.tv_nsec -= 1000000000; } /* Round up and print system time. */ stime.tv_nsec += 5000000; if (stime.tv_nsec >= 1000000000) { stime.tv_sec += 1; stime.tv_nsec -= 1000000000; } /* * Find the most active thread: * - prefer runnable * - prefer higher pctcpu * - prefer living * Otherwise take the newest thread */ pick = p = TAILQ_FIRST(&pickpr->ps_threads); if (p == NULL) goto empty; run = p->p_stat == SRUN || p->p_stat == SONPROC; pctcpu = p->p_pctcpu; while ((p = TAILQ_NEXT(p, p_thr_link)) != NULL) { run2 = p->p_stat == SRUN || p->p_stat == SONPROC; pctcpu2 = p->p_pctcpu; if (run) { /* * pick is running; is p running w/same or * more cpu? */ if (run2 && pctcpu2 >= pctcpu) goto update_pick; continue; } /* pick isn't running; is p running *or* w/more cpu? */ if (run2 || pctcpu2 > pctcpu) goto update_pick; /* if p has less cpu or is exiting, then it's worse */ if (pctcpu2 < pctcpu || p->p_flag & P_WEXIT) continue; update_pick: pick = p; run = run2; pctcpu = p->p_pctcpu; } state = pick->p_stat == SONPROC ? "running" : pick->p_stat == SRUN ? "runnable" : pick->p_wmesg ? pick->p_wmesg : "iowait"; ttyprintf(tp, " cmd: %s %d [%s] %lld.%02ldu %lld.%02lds %d%% %ldk\n", pickpr->ps_comm, pickpr->ps_pid, state, (long long)utime.tv_sec, utime.tv_nsec / 10000000, (long long)stime.tv_sec, stime.tv_nsec / 10000000, calc_pctcpu / 100, rss); } tp->t_rocount = 0; /* so pending input will be retyped if BS */ } /* * Output char to tty; console putchar style. */ int tputchar(int c, struct tty *tp) { int s; s = spltty(); if (ISSET(tp->t_state, TS_ISOPEN) == 0 || !(ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL))) { splx(s); return (-1); } if (c == '\n') (void)ttyoutput('\r', tp); (void)ttyoutput(c, tp); ttstart(tp); splx(s); return (0); } /* * Sleep on chan, returning ERESTART if tty changed while we napped and * returning any errors (e.g. EINTR/ETIMEDOUT) reported by tsleep. If * the tty is revoked, restarting a pending call will redo validation done * at the start of the call. */ int ttysleep(struct tty *tp, void *chan, int pri, char *wmesg) { return (ttysleep_nsec(tp, chan, pri, wmesg, INFSLP)); } int ttysleep_nsec(struct tty *tp, void *chan, int pri, char *wmesg, uint64_t nsecs) { int error; short gen; gen = tp->t_gen; if ((error = tsleep_nsec(chan, pri, wmesg, nsecs)) != 0) return (error); return (tp->t_gen == gen ? 0 : ERESTART); } /* * Initialise the global tty list. */ void tty_init(void) { TAILQ_INIT(&ttylist); tty_count = 0; } /* * Allocate a tty structure and its associated buffers, and attach it to the * tty list. */ struct tty * ttymalloc(int baud) { struct tty *tp; tp = malloc(sizeof(struct tty), M_TTYS, M_WAITOK|M_ZERO); if (baud == 0) baud = 115200; if (baud <= 9600) tp->t_qlen = 1024; else if (baud <= 115200) tp->t_qlen = 4096; else tp->t_qlen = 8192; clalloc(&tp->t_rawq, tp->t_qlen, 1); clalloc(&tp->t_canq, tp->t_qlen, 1); /* output queue doesn't need quoting */ clalloc(&tp->t_outq, tp->t_qlen, 0); rw_enter_write(&ttylist_lock); TAILQ_INSERT_TAIL(&ttylist, tp, tty_link); ++tty_count; rw_exit_write(&ttylist_lock); timeout_set(&tp->t_rstrt_to, ttrstrt, tp); return(tp); } /* * Free a tty structure and its buffers, after removing it from the tty list. */ void ttyfree(struct tty *tp) { int s; rw_enter_write(&ttylist_lock); --tty_count; #ifdef DIAGNOSTIC if (tty_count < 0) panic("ttyfree: tty_count < 0"); #endif TAILQ_REMOVE(&ttylist, tp, tty_link); rw_exit_write(&ttylist_lock); s = spltty(); klist_invalidate(&tp->t_rsel.si_note); klist_invalidate(&tp->t_wsel.si_note); splx(s); clfree(&tp->t_rawq); clfree(&tp->t_canq); clfree(&tp->t_outq); free(tp, M_TTYS, sizeof(*tp)); } void ttystats_init(struct itty **ttystats, int *ttycp, size_t *ttystatssiz) { int ntty = 0, ttyc; struct itty *itp; struct tty *tp; ttyc = tty_count; *ttystatssiz = ttyc * sizeof(struct itty); *ttystats = mallocarray(ttyc, sizeof(struct itty), M_SYSCTL, M_WAITOK|M_ZERO); rw_enter_write(&ttylist_lock); for (tp = TAILQ_FIRST(&ttylist), itp = *ttystats; tp && ntty++ < ttyc; tp = TAILQ_NEXT(tp, tty_link), itp++) { itp->t_dev = tp->t_dev; itp->t_rawq_c_cc = tp->t_rawq.c_cc; itp->t_canq_c_cc = tp->t_canq.c_cc; itp->t_outq_c_cc = tp->t_outq.c_cc; itp->t_hiwat = tp->t_hiwat; itp->t_lowat = tp->t_lowat; if (ISSET(tp->t_oflag, OPOST)) itp->t_column = tp->t_column; itp->t_state = tp->t_state; itp->t_session = tp->t_session; if (tp->t_pgrp) itp->t_pgrp_pg_id = tp->t_pgrp->pg_id; else itp->t_pgrp_pg_id = 0; itp->t_line = tp->t_line; } rw_exit_write(&ttylist_lock); *ttycp = ntty; } /* * Return tty-related information. */ int sysctl_tty(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int err; if (namelen != 1) return (ENOTDIR); switch (name[0]) { case KERN_TTY_TKNIN: return (sysctl_rdquad(oldp, oldlenp, newp, tk_nin)); case KERN_TTY_TKNOUT: return (sysctl_rdquad(oldp, oldlenp, newp, tk_nout)); case KERN_TTY_TKRAWCC: return (sysctl_rdquad(oldp, oldlenp, newp, tk_rawcc)); case KERN_TTY_TKCANCC: return (sysctl_rdquad(oldp, oldlenp, newp, tk_cancc)); case KERN_TTY_INFO: { struct itty *ttystats; size_t ttystatssiz; int ttyc; ttystats_init(&ttystats, &ttyc, &ttystatssiz); err = sysctl_rdstruct(oldp, oldlenp, newp, ttystats, ttyc * sizeof(struct itty)); free(ttystats, M_SYSCTL, ttystatssiz); return (err); } default: #if NPTY > 0 return (sysctl_pty(name, namelen, oldp, oldlenp, newp, newlen)); #else return (EOPNOTSUPP); #endif } /* NOTREACHED */ } void ttytstamp(struct tty *tp, int octs, int ncts, int odcd, int ndcd) { int doit = 0; if (ncts ^ octs) doit |= ncts ? ISSET(tp->t_flags, TS_TSTAMPCTSSET) : ISSET(tp->t_flags, TS_TSTAMPCTSCLR); if (ndcd ^ odcd) doit |= ndcd ? ISSET(tp->t_flags, TS_TSTAMPDCDSET) : ISSET(tp->t_flags, TS_TSTAMPDCDCLR); if (doit) microtime(&tp->t_tv); }
6 2 1 3 2 3 2 2 1 1 2 4 4 1 1 91 92 5 97 80 2 2 42 2 33 96 98 1 6 1 2 2 2 1 5 3 2 2 2 2 4 4 2 2 35 34 2 27 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 42 40 2 1 2 1 2 2 4 35 2 2 2 2 2 2 2 3 2 2 2 2 2 2 2 39 4 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 /* $OpenBSD: wsmouse.c,v 1.72 2024/05/17 20:11:58 miod Exp $ */ /* $NetBSD: wsmouse.c,v 1.35 2005/02/27 00:27:52 perry Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Christopher G. Demetriou * for the NetBSD Project. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Lawrence Berkeley Laboratory. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ms.c 8.1 (Berkeley) 6/11/93 */ /* * Copyright (c) 2015, 2016 Ulf Brosziewski * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * Mouse driver. */ #include <sys/param.h> #include <sys/conf.h> #include <sys/ioctl.h> #include <sys/fcntl.h> #include <sys/kernel.h> #include <sys/proc.h> #include <sys/syslog.h> #include <sys/systm.h> #include <sys/tty.h> #include <sys/signalvar.h> #include <sys/device.h> #include <sys/vnode.h> #include <sys/malloc.h> #include <dev/wscons/wscons_features.h> #include <dev/wscons/wsconsio.h> #include <dev/wscons/wsmousevar.h> #include <dev/wscons/wseventvar.h> #include <dev/wscons/wsmouseinput.h> #include "wsmux.h" #include "wsdisplay.h" #include "wskbd.h" #include <dev/wscons/wsmuxvar.h> #if defined(WSMUX_DEBUG) && NWSMUX > 0 #define DPRINTF(x) if (wsmuxdebug) printf x extern int wsmuxdebug; #else #define DPRINTF(x) #endif struct wsmouse_softc { struct wsevsrc sc_base; const struct wsmouse_accessops *sc_accessops; void *sc_accesscookie; struct wsmouseinput sc_input; int sc_refcnt; u_char sc_dying; /* device is being detached */ }; int wsmouse_match(struct device *, void *, void *); void wsmouse_attach(struct device *, struct device *, void *); int wsmouse_detach(struct device *, int); int wsmouse_activate(struct device *, int); int wsmouse_do_ioctl(struct wsmouse_softc *, u_long, caddr_t, int, struct proc *); #if NWSMUX > 0 int wsmouse_mux_open(struct wsevsrc *, struct wseventvar *); int wsmouse_mux_close(struct wsevsrc *); #endif int wsmousedoioctl(struct device *, u_long, caddr_t, int, struct proc *); int wsmousedoopen(struct wsmouse_softc *, struct wseventvar *); struct cfdriver wsmouse_cd = { NULL, "wsmouse", DV_TTY }; const struct cfattach wsmouse_ca = { sizeof (struct wsmouse_softc), wsmouse_match, wsmouse_attach, wsmouse_detach, wsmouse_activate }; #if NWSMUX > 0 struct wssrcops wsmouse_srcops = { .type = WSMUX_MOUSE, .dopen = wsmouse_mux_open, .dclose = wsmouse_mux_close, .dioctl = wsmousedoioctl, .ddispioctl = NULL, .dsetdisplay = NULL, }; #endif /* * Print function (for parent devices). */ int wsmousedevprint(void *aux, const char *pnp) { if (pnp) printf("wsmouse at %s", pnp); return (UNCONF); } int wsmouse_match(struct device *parent, void *match, void *aux) { return (1); } void wsmouse_attach(struct device *parent, struct device *self, void *aux) { struct wsmouse_softc *sc = (struct wsmouse_softc *)self; struct wsmousedev_attach_args *ap = aux; #if NWSMUX > 0 int mux, error; #endif sc->sc_accessops = ap->accessops; sc->sc_accesscookie = ap->accesscookie; sc->sc_input.evar = &sc->sc_base.me_evp; #if NWSMUX > 0 sc->sc_base.me_ops = &wsmouse_srcops; mux = sc->sc_base.me_dv.dv_cfdata->wsmousedevcf_mux; if (mux >= 0) { error = wsmux_attach_sc(wsmux_getmux(mux), &sc->sc_base); if (error) printf(" attach error=%d", error); else printf(" mux %d", mux); } #else #if 0 /* not worth keeping, especially since the default value is not -1... */ if (sc->sc_base.me_dv.dv_cfdata->wsmousedevcf_mux >= 0) printf(" (mux ignored)"); #endif #endif /* NWSMUX > 0 */ printf("\n"); } int wsmouse_activate(struct device *self, int act) { struct wsmouse_softc *sc = (struct wsmouse_softc *)self; if (act == DVACT_DEACTIVATE) sc->sc_dying = 1; return (0); } /* * Detach a mouse. To keep track of users of the softc we keep * a reference count that's incremented while inside, e.g., read. * If the mouse is active and the reference count is > 0 (0 is the * normal state) we post an event and then wait for the process * that had the reference to wake us up again. Then we blow away the * vnode and return (which will deallocate the softc). */ int wsmouse_detach(struct device *self, int flags) { struct wsmouse_softc *sc = (struct wsmouse_softc *)self; struct wseventvar *evar; int maj, mn; int s; #if NWSMUX > 0 /* Tell parent mux we're leaving. */ if (sc->sc_base.me_parent != NULL) { DPRINTF(("%s\n", __func__)); wsmux_detach_sc(&sc->sc_base); } #endif /* If we're open ... */ evar = sc->sc_base.me_evp; if (evar != NULL) { s = spltty(); if (--sc->sc_refcnt >= 0) { /* Wake everyone by generating a dummy event. */ if (++evar->ws_put >= WSEVENT_QSIZE) evar->ws_put = 0; WSEVENT_WAKEUP(evar); /* Wait for processes to go away. */ if (tsleep_nsec(sc, PZERO, "wsmdet", SEC_TO_NSEC(60))) printf("wsmouse_detach: %s didn't detach\n", sc->sc_base.me_dv.dv_xname); } splx(s); } /* locate the major number */ for (maj = 0; maj < nchrdev; maj++) if (cdevsw[maj].d_open == wsmouseopen) break; /* Nuke the vnodes for any open instances (calls close). */ mn = self->dv_unit; vdevgone(maj, mn, mn, VCHR); wsmouse_input_cleanup(&sc->sc_input); return (0); } int wsmouseopen(dev_t dev, int flags, int mode, struct proc *p) { struct wsmouse_softc *sc; struct wseventvar *evar; int error, unit; unit = minor(dev); if (unit >= wsmouse_cd.cd_ndevs || /* make sure it was attached */ (sc = wsmouse_cd.cd_devs[unit]) == NULL) return (ENXIO); #if NWSMUX > 0 DPRINTF(("%s: %s mux=%p\n", __func__, sc->sc_base.me_dv.dv_xname, sc->sc_base.me_parent)); #endif if (sc->sc_dying) return (EIO); if ((flags & (FREAD | FWRITE)) == FWRITE) return (0); /* always allow open for write so ioctl() is possible. */ #if NWSMUX > 0 if (sc->sc_base.me_parent != NULL) { /* Grab the mouse out of the greedy hands of the mux. */ DPRINTF(("%s: detach\n", __func__)); wsmux_detach_sc(&sc->sc_base); } #endif if (sc->sc_base.me_evp != NULL) return (EBUSY); evar = &sc->sc_base.me_evar; if (wsevent_init(evar)) return (EBUSY); error = wsmousedoopen(sc, evar); if (error) wsevent_fini(evar); return (error); } int wsmouseclose(dev_t dev, int flags, int mode, struct proc *p) { struct wsmouse_softc *sc = (struct wsmouse_softc *)wsmouse_cd.cd_devs[minor(dev)]; struct wseventvar *evar = sc->sc_base.me_evp; if ((flags & (FREAD | FWRITE)) == FWRITE) /* Not open for read */ return (0); sc->sc_base.me_evp = NULL; (*sc->sc_accessops->disable)(sc->sc_accesscookie); wsevent_fini(evar); #if NWSMUX > 0 if (sc->sc_base.me_parent == NULL) { int mux, error; DPRINTF(("%s: attach\n", __func__)); mux = sc->sc_base.me_dv.dv_cfdata->wsmousedevcf_mux; if (mux >= 0) { error = wsmux_attach_sc(wsmux_getmux(mux), &sc->sc_base); if (error) printf("%s: can't attach mux (error=%d)\n", sc->sc_base.me_dv.dv_xname, error); } } #endif return (0); } int wsmousedoopen(struct wsmouse_softc *sc, struct wseventvar *evp) { int error; /* The device could already be attached to a mux. */ if (sc->sc_base.me_evp != NULL) return (EBUSY); sc->sc_base.me_evp = evp; wsmouse_input_reset(&sc->sc_input); /* enable the device, and punt if that's not possible */ error = (*sc->sc_accessops->enable)(sc->sc_accesscookie); if (error) sc->sc_base.me_evp = NULL; return (error); } int wsmouseread(dev_t dev, struct uio *uio, int flags) { struct wsmouse_softc *sc = wsmouse_cd.cd_devs[minor(dev)]; int error; if (sc->sc_dying) return (EIO); #ifdef DIAGNOSTIC if (sc->sc_base.me_evp == NULL) { printf("wsmouseread: evp == NULL\n"); return (EINVAL); } #endif sc->sc_refcnt++; error = wsevent_read(sc->sc_base.me_evp, uio, flags); if (--sc->sc_refcnt < 0) { wakeup(sc); error = EIO; } return (error); } int wsmouseioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { return (wsmousedoioctl(wsmouse_cd.cd_devs[minor(dev)], cmd, data, flag, p)); } /* A wrapper around the ioctl() workhorse to make reference counting easy. */ int wsmousedoioctl(struct device *dv, u_long cmd, caddr_t data, int flag, struct proc *p) { struct wsmouse_softc *sc = (struct wsmouse_softc *)dv; int error; sc->sc_refcnt++; error = wsmouse_do_ioctl(sc, cmd, data, flag, p); if (--sc->sc_refcnt < 0) wakeup(sc); return (error); } int wsmouse_param_ioctl(struct wsmouse_softc *sc, u_long cmd, struct wsmouse_param *params, u_int nparams) { struct wsmouse_param *buf; int error, s, size; if (params == NULL || nparams > WSMOUSECFG_MAX) return (EINVAL); size = nparams * sizeof(struct wsmouse_param); buf = malloc(size, M_DEVBUF, M_WAITOK); if (buf == NULL) return (ENOMEM); if ((error = copyin(params, buf, size))) { free(buf, M_DEVBUF, size); return (error); } s = spltty(); if (cmd == WSMOUSEIO_SETPARAMS) { if (wsmouse_set_params((struct device *) sc, buf, nparams)) error = EINVAL; } else { if (wsmouse_get_params((struct device *) sc, buf, nparams)) error = EINVAL; else error = copyout(buf, params, size); } splx(s); free(buf, M_DEVBUF, size); return (error); } int wsmouse_do_ioctl(struct wsmouse_softc *sc, u_long cmd, caddr_t data, int flag, struct proc *p) { struct wseventvar *evar; int error; if (sc->sc_dying) return (EIO); /* * Try the generic ioctls that the wsmouse interface supports. */ switch (cmd) { case FIOASYNC: case FIOSETOWN: case TIOCSPGRP: if ((flag & FWRITE) == 0) return (EACCES); } switch (cmd) { case FIONBIO: /* we will remove this someday (soon???) */ return (0); case FIOASYNC: if (sc->sc_base.me_evp == NULL) return (EINVAL); sc->sc_base.me_evp->ws_async = *(int *)data != 0; return (0); case FIOGETOWN: case TIOCGPGRP: evar = sc->sc_base.me_evp; if (evar == NULL) return (EINVAL); sigio_getown(&evar->ws_sigio, cmd, data); return (0); case FIOSETOWN: case TIOCSPGRP: evar = sc->sc_base.me_evp; if (evar == NULL) return (EINVAL); return (sigio_setown(&evar->ws_sigio, cmd, data)); case WSMOUSEIO_GETPARAMS: case WSMOUSEIO_SETPARAMS: return (wsmouse_param_ioctl(sc, cmd, ((struct wsmouse_parameters *) data)->params, ((struct wsmouse_parameters *) data)->nparams)); } /* * Try the mouse driver for WSMOUSEIO ioctls. It returns -1 * if it didn't recognize the request. */ error = (*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd, data, flag, p); return (error != -1 ? error : ENOTTY); } int wsmousekqfilter(dev_t dev, struct knote *kn) { struct wsmouse_softc *sc = wsmouse_cd.cd_devs[minor(dev)]; if (sc->sc_base.me_evp == NULL) return (ENXIO); return (wsevent_kqfilter(sc->sc_base.me_evp, kn)); } #if NWSMUX > 0 int wsmouse_mux_open(struct wsevsrc *me, struct wseventvar *evp) { struct wsmouse_softc *sc = (struct wsmouse_softc *)me; return (wsmousedoopen(sc, evp)); } int wsmouse_mux_close(struct wsevsrc *me) { struct wsmouse_softc *sc = (struct wsmouse_softc *)me; (*sc->sc_accessops->disable)(sc->sc_accesscookie); sc->sc_base.me_evp = NULL; return (0); } int wsmouse_add_mux(int unit, struct wsmux_softc *muxsc) { struct wsmouse_softc *sc; if (unit < 0 || unit >= wsmouse_cd.cd_ndevs || (sc = wsmouse_cd.cd_devs[unit]) == NULL) return (ENXIO); if (sc->sc_base.me_parent != NULL || sc->sc_base.me_evp != NULL) return (EBUSY); return (wsmux_attach_sc(muxsc, &sc->sc_base)); } #endif /* NWSMUX > 0 */ void wsmouse_buttons(struct device *sc, u_int buttons) { struct btn_state *btn = &((struct wsmouse_softc *) sc)->sc_input.btn; if (btn->sync) /* Restore the old state. */ btn->buttons ^= btn->sync; btn->sync = btn->buttons ^ buttons; btn->buttons = buttons; } void wsmouse_motion(struct device *sc, int dx, int dy, int dz, int dw) { struct motion_state *motion = &((struct wsmouse_softc *) sc)->sc_input.motion; motion->dx = dx; motion->dy = dy; motion->dz = dz; motion->dw = dw; if (dx || dy || dz || dw) motion->sync |= SYNC_DELTAS; } static inline void set_x(struct position *pos, int x, u_int *sync, u_int mask) { if (*sync & mask) { if (x == pos->x) return; pos->x -= pos->dx; pos->acc_dx -= pos->dx; } if ((pos->dx = x - pos->x)) { pos->x = x; if ((pos->dx > 0) == (pos->acc_dx > 0)) pos->acc_dx += pos->dx; else pos->acc_dx = pos->dx; *sync |= mask; } } static inline void set_y(struct position *pos, int y, u_int *sync, u_int mask) { if (*sync & mask) { if (y == pos->y) return; pos->y -= pos->dy; pos->acc_dy -= pos->dy; } if ((pos->dy = y - pos->y)) { pos->y = y; if ((pos->dy > 0) == (pos->acc_dy > 0)) pos->acc_dy += pos->dy; else pos->acc_dy = pos->dy; *sync |= mask; } } static inline void cleardeltas(struct position *pos) { pos->dx = pos->acc_dx = 0; pos->dy = pos->acc_dy = 0; } void wsmouse_position(struct device *sc, int x, int y) { struct motion_state *motion = &((struct wsmouse_softc *) sc)->sc_input.motion; set_x(&motion->pos, x, &motion->sync, SYNC_X); set_y(&motion->pos, y, &motion->sync, SYNC_Y); } static inline int normalized_pressure(struct wsmouseinput *input, int pressure) { int limit = imax(input->touch.min_pressure, 1); if (pressure >= limit) return pressure; else return (pressure < 0 ? limit : 0); } void wsmouse_touch(struct device *sc, int pressure, int contacts) { struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input; struct touch_state *touch = &input->touch; pressure = normalized_pressure(input, pressure); contacts = (pressure ? imax(contacts, 1) : 0); if (pressure == 0 || pressure != touch->pressure) { /* * pressure == 0: Drivers may report possibly arbitrary * coordinates in this case; touch_update will correct them. */ touch->pressure = pressure; touch->sync |= SYNC_PRESSURE; } if (contacts != touch->contacts) { touch->contacts = contacts; touch->sync |= SYNC_CONTACTS; } } void wsmouse_mtstate(struct device *sc, int slot, int x, int y, int pressure) { struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input; struct mt_state *mt = &input->mt; struct mt_slot *mts; u_int bit; if (slot < 0 || slot >= mt->num_slots) return; bit = (1 << slot); mt->frame |= bit; mts = &mt->slots[slot]; set_x(&mts->pos, x, mt->sync + MTS_X, bit); set_y(&mts->pos, y, mt->sync + MTS_Y, bit); /* Is this a new touch? */ if ((mt->touches & bit) == (mt->sync[MTS_TOUCH] & bit)) cleardeltas(&mts->pos); pressure = normalized_pressure(input, pressure); if (pressure != mts->pressure) { mts->pressure = pressure; mt->sync[MTS_PRESSURE] |= bit; if (pressure) { if ((mt->touches & bit) == 0) { mt->num_touches++; mt->touches |= bit; mt->sync[MTS_TOUCH] |= bit; mt->sync[MTS_X] |= bit; mt->sync[MTS_Y] |= bit; } } else if (mt->touches & bit) { mt->num_touches--; mt->touches ^= bit; mt->sync[MTS_TOUCH] |= bit; mt->ptr_mask &= mt->touches; } } } void wsmouse_set(struct device *sc, enum wsmouseval type, int value, int aux) { struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input; struct mt_slot *mts; if (WSMOUSE_IS_MT_CODE(type)) { if (aux < 0 || aux >= input->mt.num_slots) return; mts = &input->mt.slots[aux]; } switch (type) { case WSMOUSE_REL_X: value += input->motion.pos.x; /* fall through */ case WSMOUSE_ABS_X: wsmouse_position(sc, value, input->motion.pos.y); return; case WSMOUSE_REL_Y: value += input->motion.pos.y; /* fall through */ case WSMOUSE_ABS_Y: wsmouse_position(sc, input->motion.pos.x, value); return; case WSMOUSE_PRESSURE: wsmouse_touch(sc, value, input->touch.contacts); return; case WSMOUSE_CONTACTS: /* Contact counts can be overridden by wsmouse_touch. */ if (value != input->touch.contacts) { input->touch.contacts = value; input->touch.sync |= SYNC_CONTACTS; } return; case WSMOUSE_TOUCH_WIDTH: if (value != input->touch.width) { input->touch.width = value; input->touch.sync |= SYNC_TOUCH_WIDTH; } return; case WSMOUSE_MT_REL_X: value += mts->pos.x; /* fall through */ case WSMOUSE_MT_ABS_X: wsmouse_mtstate(sc, aux, value, mts->pos.y, mts->pressure); return; case WSMOUSE_MT_REL_Y: value += mts->pos.y; /* fall through */ case WSMOUSE_MT_ABS_Y: wsmouse_mtstate(sc, aux, mts->pos.x, value, mts->pressure); return; case WSMOUSE_MT_PRESSURE: wsmouse_mtstate(sc, aux, mts->pos.x, mts->pos.y, value); return; } } /* Make touch and motion state consistent. */ void wsmouse_touch_update(struct wsmouseinput *input) { struct motion_state *motion = &input->motion; struct touch_state *touch = &input->touch; if (touch->pressure == 0) { /* * There may be zero coordinates, or coordinates of * touches with pressure values below min_pressure. */ if (motion->sync & SYNC_POSITION) { /* Restore valid coordinates. */ motion->pos.x -= motion->pos.dx; motion->pos.y -= motion->pos.dy; motion->sync &= ~SYNC_POSITION; } if (touch->prev_contacts == 0) touch->sync &= ~SYNC_PRESSURE; } if (touch->sync & SYNC_CONTACTS) /* Suppress pointer movement. */ cleardeltas(&motion->pos); if ((touch->sync & SYNC_PRESSURE) && touch->min_pressure) { if (touch->pressure >= input->filter.pressure_hi) touch->min_pressure = input->filter.pressure_lo; else if (touch->pressure < input->filter.pressure_lo) touch->min_pressure = input->filter.pressure_hi; } } /* Normalize multitouch state. */ void wsmouse_mt_update(struct wsmouseinput *input) { int i; /* * The same as above: There may be arbitrary coordinates if * (pressure == 0). Clear the sync flags for touches that have * been released. */ if (input->mt.frame & ~input->mt.touches) { for (i = MTS_X; i < MTS_SIZE; i++) input->mt.sync[i] &= input->mt.touches; } } /* Return TRUE if a coordinate update may be noise. */ int wsmouse_hysteresis(struct wsmouseinput *input, struct position *pos) { return (abs(pos->acc_dx) < input->filter.h.hysteresis && abs(pos->acc_dy) < input->filter.v.hysteresis); } /* * Select the pointer-controlling MT slot. * * Pointer-control is assigned to slots with non-zero motion deltas if * at least one such slot exists. This function doesn't impose any * restrictions on the way drivers use wsmouse_mtstate(), it covers * partial, unordered, and "delta-filtered" input. * * The "cycle" is the set of slots with X/Y updates in previous sync * operations; it will be cleared and rebuilt whenever a slot that is * being updated is already a member. If a cycle ends that doesn't * contain the pointer-controlling slot, a new slot will be selected. */ void wsmouse_ptr_ctrl(struct wsmouseinput *input) { struct mt_state *mt = &input->mt; u_int updates; int select, slot; mt->prev_ptr = mt->ptr; if (mt->num_touches <= 1) { mt->ptr = mt->touches; mt->ptr_cycle = mt->ptr; return; } updates = (mt->sync[MTS_X] | mt->sync[MTS_Y]) & ~mt->sync[MTS_TOUCH]; FOREACHBIT(updates, slot) { /* * Touches that just produce noise are no problem if the * frequency of zero deltas is high enough, but there might * be no guarantee for that. */ if (wsmouse_hysteresis(input, &mt->slots[slot].pos)) updates ^= (1 << slot); } /* * If there is no pointer-controlling slot, or if it should be * masked, select a new one. */ select = ((mt->ptr & mt->touches & ~mt->ptr_mask) == 0); /* Remove slots without coordinate deltas from the cycle. */ mt->ptr_cycle &= ~(mt->frame ^ updates); if (mt->ptr_cycle & updates) { select |= ((mt->ptr_cycle & mt->ptr) == 0); mt->ptr_cycle = updates; } else { mt->ptr_cycle |= updates; } if (select) { if (mt->ptr_cycle & ~mt->ptr_mask) slot = ffs(mt->ptr_cycle & ~mt->ptr_mask) - 1; else if (mt->touches & ~mt->ptr_mask) slot = ffs(mt->touches & ~mt->ptr_mask) - 1; else slot = ffs(mt->touches) - 1; mt->ptr = (1 << slot); } } /* Derive touch and motion state from MT state. */ void wsmouse_mt_convert(struct device *sc) { struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input; struct mt_state *mt = &input->mt; struct mt_slot *mts; int slot, pressure; wsmouse_ptr_ctrl(input); if (mt->ptr) { slot = ffs(mt->ptr) - 1; mts = &mt->slots[slot]; if (mts->pos.x != input->motion.pos.x) input->motion.sync |= SYNC_X; if (mts->pos.y != input->motion.pos.y) input->motion.sync |= SYNC_Y; if (mt->ptr != mt->prev_ptr) /* Suppress pointer movement. */ mts->pos.dx = mts->pos.dy = 0; memcpy(&input->motion.pos, &mts->pos, sizeof(struct position)); pressure = mts->pressure; } else { pressure = 0; } wsmouse_touch(sc, pressure, mt->num_touches); } void wsmouse_evq_put(struct evq_access *evq, int ev_type, int ev_value) { struct wscons_event *ev; int space; space = evq->evar->ws_get - evq->put; if (space != 1 && space != 1 - WSEVENT_QSIZE) { ev = &evq->evar->ws_q[evq->put++]; evq->put %= WSEVENT_QSIZE; ev->type = ev_type; ev->value = ev_value; memcpy(&ev->time, &evq->ts, sizeof(struct timespec)); evq->result |= EVQ_RESULT_SUCCESS; } else { evq->result = EVQ_RESULT_OVERFLOW; } } void wsmouse_btn_sync(struct btn_state *btn, struct evq_access *evq) { int button, ev_type; u_int bit, sync; for (sync = btn->sync; sync; sync ^= bit) { button = ffs(sync) - 1; bit = (1 << button); ev_type = (btn->buttons & bit) ? BTN_DOWN_EV : BTN_UP_EV; wsmouse_evq_put(evq, ev_type, button); } } /* * Scale with a [*.12] fixed-point factor and a remainder: */ static inline int scale(int val, int factor, int *rmdr) { val = val * factor + *rmdr; if (val >= 0) { *rmdr = val & 0xfff; return (val >> 12); } else { *rmdr = -(-val & 0xfff); return -(-val >> 12); } } void wsmouse_motion_sync(struct wsmouseinput *input, struct evq_access *evq) { struct motion_state *motion = &input->motion; struct axis_filter *h = &input->filter.h; struct axis_filter *v = &input->filter.v; int x, y, dx, dy, dz, dw; if (motion->sync & SYNC_DELTAS) { dx = h->inv ? -motion->dx : motion->dx; dy = v->inv ? -motion->dy : motion->dy; if (h->scale) dx = scale(dx, h->scale, &h->rmdr); if (v->scale) dy = scale(dy, v->scale, &v->rmdr); if (dx) wsmouse_evq_put(evq, DELTA_X_EV(input), dx); if (dy) wsmouse_evq_put(evq, DELTA_Y_EV(input), dy); if (motion->dz) { dz = (input->flags & REVERSE_SCROLLING) ? -motion->dz : motion->dz; if (IS_TOUCHPAD(input)) wsmouse_evq_put(evq, VSCROLL_EV, dz); else wsmouse_evq_put(evq, DELTA_Z_EV, dz); } if (motion->dw) { dw = (input->flags & REVERSE_SCROLLING) ? -motion->dw : motion->dw; if (IS_TOUCHPAD(input)) wsmouse_evq_put(evq, HSCROLL_EV, dw); else wsmouse_evq_put(evq, DELTA_W_EV, dw); } } if (motion->sync & SYNC_POSITION) { if (motion->sync & SYNC_X) { x = (h->inv ? h->inv - motion->pos.x : motion->pos.x); wsmouse_evq_put(evq, ABS_X_EV(input), x); } if (motion->sync & SYNC_Y) { y = (v->inv ? v->inv - motion->pos.y : motion->pos.y); wsmouse_evq_put(evq, ABS_Y_EV(input), y); } if (motion->pos.dx == 0 && motion->pos.dy == 0 && (input->flags & TPAD_NATIVE_MODE )) /* Suppress pointer motion. */ wsmouse_evq_put(evq, WSCONS_EVENT_TOUCH_RESET, 0); } } void wsmouse_touch_sync(struct wsmouseinput *input, struct evq_access *evq) { struct touch_state *touch = &input->touch; if (touch->sync & SYNC_PRESSURE) wsmouse_evq_put(evq, ABS_Z_EV, touch->pressure); if (touch->sync & SYNC_CONTACTS) wsmouse_evq_put(evq, ABS_W_EV, touch->contacts); if ((touch->sync & SYNC_TOUCH_WIDTH) && (input->flags & TPAD_NATIVE_MODE)) wsmouse_evq_put(evq, WSCONS_EVENT_TOUCH_WIDTH, touch->width); } void wsmouse_log_input(struct wsmouseinput *input, struct timespec *ts) { struct motion_state *motion = &input->motion; int t_sync, mt_sync; t_sync = (input->touch.sync & SYNC_CONTACTS); mt_sync = (input->mt.frame && (input->mt.sync[MTS_TOUCH] || input->mt.ptr != input->mt.prev_ptr)); if (motion->sync || mt_sync || t_sync || input->btn.sync) printf("[%s-in][%04d]", DEVNAME(input), LOGTIME(ts)); else return; if (motion->sync & SYNC_POSITION) printf(" abs:%d,%d", motion->pos.x, motion->pos.y); if (motion->sync & SYNC_DELTAS) printf(" rel:%d,%d,%d,%d", motion->dx, motion->dy, motion->dz, motion->dw); if (mt_sync) printf(" mt:0x%02x:%d", input->mt.touches, ffs(input->mt.ptr) - 1); else if (t_sync) printf(" t:%d", input->touch.contacts); if (input->btn.sync) printf(" btn:0x%02x", input->btn.buttons); printf("\n"); } void wsmouse_log_events(struct wsmouseinput *input, struct evq_access *evq) { struct wscons_event *ev; int n = evq->evar->ws_put; if (n != evq->put) { printf("[%s-ev][%04d]", DEVNAME(input), LOGTIME(&evq->ts)); while (n != evq->put) { ev = &evq->evar->ws_q[n++]; n %= WSEVENT_QSIZE; printf(" %d:%d", ev->type, ev->value); } printf("\n"); } } static inline void clear_sync_flags(struct wsmouseinput *input) { int i; input->btn.sync = 0; input->sbtn.sync = 0; input->motion.sync = 0; input->touch.sync = 0; input->touch.prev_contacts = input->touch.contacts; if (input->mt.frame) { input->mt.frame = 0; for (i = 0; i < MTS_SIZE; i++) input->mt.sync[i] = 0; } } void wsmouse_input_sync(struct device *sc) { struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input; struct evq_access evq; evq.evar = *input->evar; if (evq.evar == NULL) return; evq.put = evq.evar->ws_put; evq.result = EVQ_RESULT_NONE; getnanotime(&evq.ts); enqueue_randomness(input->btn.buttons ^ input->motion.dx ^ input->motion.dy ^ input->motion.pos.x ^ input->motion.pos.y ^ input->motion.dz ^ input->motion.dw); if (input->mt.frame) { wsmouse_mt_update(input); wsmouse_mt_convert(sc); } if (input->touch.sync) wsmouse_touch_update(input); if (input->flags & LOG_INPUT) wsmouse_log_input(input, &evq.ts); if (input->flags & TPAD_COMPAT_MODE) wstpad_compat_convert(input, &evq); if (input->flags & RESYNC) { input->flags &= ~RESYNC; input->motion.sync &= SYNC_POSITION; } if (input->btn.sync) wsmouse_btn_sync(&input->btn, &evq); if (input->sbtn.sync) wsmouse_btn_sync(&input->sbtn, &evq); if (input->motion.sync) wsmouse_motion_sync(input, &evq); if (input->touch.sync) wsmouse_touch_sync(input, &evq); /* No MT events are generated yet. */ if (evq.result == EVQ_RESULT_SUCCESS) { wsmouse_evq_put(&evq, WSCONS_EVENT_SYNC, 0); if (evq.result == EVQ_RESULT_SUCCESS) { if (input->flags & LOG_EVENTS) { wsmouse_log_events(input, &evq); } evq.evar->ws_put = evq.put; WSEVENT_WAKEUP(evq.evar); } } if (evq.result != EVQ_RESULT_OVERFLOW) clear_sync_flags(input); else input->flags |= RESYNC; } int wsmouse_id_to_slot(struct device *sc, int id) { struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input; struct mt_state *mt = &input->mt; int slot; if (mt->num_slots == 0) return (-1); FOREACHBIT(mt->touches, slot) { if (mt->slots[slot].id == id) return slot; } slot = ffs(~(mt->touches | mt->frame)) - 1; if (slot >= 0 && slot < mt->num_slots) { mt->frame |= 1 << slot; mt->slots[slot].id = id; return (slot); } else { return (-1); } } /* * Find a minimum-weight matching for an m-by-n matrix. * * m must be greater than or equal to n. The size of the buffer must be * at least 3m + 3n. * * On return, the first m elements of the buffer contain the row-to- * column mappings, i.e., buffer[i] is the column index for row i, or -1 * if there is no assignment for that row (which may happen if n < m). * * Wrong results because of overflows will not occur with input values * in the range of 0 to INT_MAX / 2 inclusive. * * The function applies the Dinic-Kronrod algorithm. It is not modern or * popular, but it seems to be a good choice for small matrices at least. * The original form of the algorithm is modified as follows: There is no * initial search for row minima, the initial assignments are in a * "virtual" column with the index -1 and zero values. This permits inputs * with n < m, and it simplifies the reassignments. */ void wsmouse_matching(int *matrix, int m, int n, int *buffer) { int i, j, k, d, e, row, col, delta; int *p; int *r2c = buffer; /* row-to-column assignments */ int *red = r2c + m; /* reduced values of the assignments */ int *mc = red + m; /* row-wise minimal elements of cs */ int *cs = mc + m; /* the column set */ int *c2r = cs + n; /* column-to-row assignments in cs */ int *cd = c2r + n; /* column deltas (reduction) */ for (p = r2c; p < red; *p++ = -1) {} for (; p < mc; *p++ = 0) {} for (col = 0; col < n; col++) { delta = INT_MAX; row = 0; for (i = 0, p = matrix + col; i < m; i++, p += n) { d = *p - red[i]; if (d < delta || (d == delta && r2c[i] < 0)) { delta = d; row = i; } } cd[col] = delta; if (r2c[row] < 0) { r2c[row] = col; continue; } for (p = mc; p < cs; *p++ = col) {} for (k = 0; (j = r2c[row]) >= 0;) { cs[k++] = j; c2r[j] = row; mc[row] -= n; delta = INT_MAX; for (i = 0, p = matrix; i < m; i++, p += n) if (mc[i] >= 0) { d = p[mc[i]] - cd[mc[i]]; e = p[j] - cd[j]; if (e < d) { d = e; mc[i] = j; } d -= red[i]; if (d < delta || (d == delta && r2c[i] < 0)) { delta = d; row = i; } } cd[col] += delta; for (i = 0; i < k; i++) { cd[cs[i]] += delta; red[c2r[cs[i]]] -= delta; } } for (j = mc[row]; (r2c[row] = j) != col;) { row = c2r[j]; j = mc[row] + n; } } } /* * Assign slot numbers to the points in the pt array, and update all slots by * calling wsmouse_mtstate internally. The slot numbers are passed to the * caller in the pt->slot fields. * * The slot assignment pairs the points with points of the previous frame in * such a way that the sum of the squared distances is minimal. Using * squares instead of simple distances favours assignments with more uniform * distances, and it is faster. */ void wsmouse_mtframe(struct device *sc, struct mtpoint *pt, int size) { struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input; struct mt_state *mt = &input->mt; int i, j, m, n, dx, dy, slot, maxdist; int *p, *r2c, *c2r; u_int touches; if (mt->num_slots == 0 || mt->matrix == NULL) return; size = imax(0, imin(size, mt->num_slots)); p = mt->matrix; touches = mt->touches; if (mt->num_touches >= size) { FOREACHBIT(touches, slot) for (i = 0; i < size; i++) { dx = pt[i].x - mt->slots[slot].pos.x; dy = pt[i].y - mt->slots[slot].pos.y; *p++ = dx * dx + dy * dy; } m = mt->num_touches; n = size; } else { for (i = 0; i < size; i++) FOREACHBIT(touches, slot) { dx = pt[i].x - mt->slots[slot].pos.x; dy = pt[i].y - mt->slots[slot].pos.y; *p++ = dx * dx + dy * dy; } m = size; n = mt->num_touches; } wsmouse_matching(mt->matrix, m, n, p); r2c = p; c2r = p + m; maxdist = input->filter.tracking_maxdist; maxdist = (maxdist ? maxdist * maxdist : INT_MAX); for (i = 0, p = mt->matrix; i < m; i++, p += n) if ((j = r2c[i]) >= 0) { if (p[j] <= maxdist) c2r[j] = i; else c2r[j] = r2c[i] = -1; } p = (n == size ? c2r : r2c); for (i = 0; i < size; i++) if (*p++ < 0) { slot = ffs(~(mt->touches | mt->frame)) - 1; if (slot < 0 || slot >= mt->num_slots) break; wsmouse_mtstate(sc, slot, pt[i].x, pt[i].y, pt[i].pressure); pt[i].slot = slot; } p = (n == size ? r2c : c2r); FOREACHBIT(touches, slot) if ((i = *p++) >= 0) { wsmouse_mtstate(sc, slot, pt[i].x, pt[i].y, pt[i].pressure); pt[i].slot = slot; } else { wsmouse_mtstate(sc, slot, 0, 0, 0); } } static inline void free_mt_slots(struct wsmouseinput *input) { int n, size; if ((n = input->mt.num_slots)) { size = n * sizeof(struct mt_slot); if (input->flags & MT_TRACKING) size += MATRIX_SIZE(n); input->mt.num_slots = 0; free(input->mt.slots, M_DEVBUF, size); input->mt.slots = NULL; input->mt.matrix = NULL; } } /* Allocate the MT slots and, if necessary, the buffers for MT tracking. */ int wsmouse_mt_init(struct device *sc, int num_slots, int tracking) { struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input; int n, size; if (num_slots == input->mt.num_slots && (!tracking == ((input->flags & MT_TRACKING) == 0))) return (0); free_mt_slots(input); if (tracking) input->flags |= MT_TRACKING; else input->flags &= ~MT_TRACKING; n = imin(imax(num_slots, 0), WSMOUSE_MT_SLOTS_MAX); if (n) { size = n * sizeof(struct mt_slot); if (input->flags & MT_TRACKING) size += MATRIX_SIZE(n); input->mt.slots = malloc(size, M_DEVBUF, M_WAITOK | M_ZERO); if (input->mt.slots != NULL) { if (input->flags & MT_TRACKING) input->mt.matrix = (int *) (input->mt.slots + n); input->mt.num_slots = n; return (0); } } return (-1); } int wsmouse_get_params(struct device *sc, struct wsmouse_param *params, u_int nparams) { struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input; int i, key, error = 0; for (i = 0; i < nparams; i++) { key = params[i].key; switch (key) { case WSMOUSECFG_DX_SCALE: params[i].value = input->filter.h.scale; break; case WSMOUSECFG_DY_SCALE: params[i].value = input->filter.v.scale; break; case WSMOUSECFG_PRESSURE_LO: params[i].value = input->filter.pressure_lo; break; case WSMOUSECFG_PRESSURE_HI: params[i].value = input->filter.pressure_hi; break; case WSMOUSECFG_TRKMAXDIST: params[i].value = input->filter.tracking_maxdist; break; case WSMOUSECFG_SWAPXY: params[i].value = input->filter.swapxy; break; case WSMOUSECFG_X_INV: params[i].value = input->filter.h.inv; break; case WSMOUSECFG_Y_INV: params[i].value = input->filter.v.inv; break; case WSMOUSECFG_REVERSE_SCROLLING: params[i].value = !!(input->flags & REVERSE_SCROLLING); break; case WSMOUSECFG_DX_MAX: params[i].value = input->filter.h.dmax; break; case WSMOUSECFG_DY_MAX: params[i].value = input->filter.v.dmax; break; case WSMOUSECFG_X_HYSTERESIS: params[i].value = input->filter.h.hysteresis; break; case WSMOUSECFG_Y_HYSTERESIS: params[i].value = input->filter.v.hysteresis; break; case WSMOUSECFG_DECELERATION: params[i].value = input->filter.dclr; break; case WSMOUSECFG_STRONG_HYSTERESIS: params[i].value = 0; /* The feature has been removed. */ break; case WSMOUSECFG_SMOOTHING: params[i].value = input->filter.mode & SMOOTHING_MASK; break; case WSMOUSECFG_LOG_INPUT: params[i].value = !!(input->flags & LOG_INPUT); break; case WSMOUSECFG_LOG_EVENTS: params[i].value = !!(input->flags & LOG_EVENTS); break; default: error = wstpad_get_param(input, key, &params[i].value); if (error != 0) return (error); break; } } return (0); } int wsmouse_set_params(struct device *sc, const struct wsmouse_param *params, u_int nparams) { struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input; int i, val, key, needreset = 0, error = 0; for (i = 0; i < nparams; i++) { key = params[i].key; val = params[i].value; switch (params[i].key) { case WSMOUSECFG_PRESSURE_LO: input->filter.pressure_lo = val; if (val > input->filter.pressure_hi) input->filter.pressure_hi = val; input->touch.min_pressure = input->filter.pressure_hi; break; case WSMOUSECFG_PRESSURE_HI: input->filter.pressure_hi = val; if (val < input->filter.pressure_lo) input->filter.pressure_lo = val; input->touch.min_pressure = val; break; case WSMOUSECFG_X_HYSTERESIS: input->filter.h.hysteresis = val; break; case WSMOUSECFG_Y_HYSTERESIS: input->filter.v.hysteresis = val; break; case WSMOUSECFG_DECELERATION: input->filter.dclr = val; wstpad_init_deceleration(input); break; case WSMOUSECFG_DX_SCALE: input->filter.h.scale = val; break; case WSMOUSECFG_DY_SCALE: input->filter.v.scale = val; break; case WSMOUSECFG_TRKMAXDIST: input->filter.tracking_maxdist = val; break; case WSMOUSECFG_SWAPXY: input->filter.swapxy = val; break; case WSMOUSECFG_X_INV: input->filter.h.inv = val; break; case WSMOUSECFG_Y_INV: input->filter.v.inv = val; break; case WSMOUSECFG_REVERSE_SCROLLING: if (val) input->flags |= REVERSE_SCROLLING; else input->flags &= ~REVERSE_SCROLLING; break; case WSMOUSECFG_DX_MAX: input->filter.h.dmax = val; break; case WSMOUSECFG_DY_MAX: input->filter.v.dmax = val; break; case WSMOUSECFG_SMOOTHING: input->filter.mode &= ~SMOOTHING_MASK; input->filter.mode |= (val & SMOOTHING_MASK); break; case WSMOUSECFG_LOG_INPUT: if (val) input->flags |= LOG_INPUT; else input->flags &= ~LOG_INPUT; break; case WSMOUSECFG_LOG_EVENTS: if (val) input->flags |= LOG_EVENTS; else input->flags &= ~LOG_EVENTS; break; default: needreset = 1; error = wstpad_set_param(input, key, val); if (error != 0) return (error); break; } } /* Reset soft-states if touchpad parameters changed */ if (needreset) { wstpad_reset(input); return (wstpad_configure(input)); } return (0); } int wsmouse_set_mode(struct device *sc, int mode) { struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input; if (mode == WSMOUSE_COMPAT) { input->flags &= ~TPAD_NATIVE_MODE; input->flags |= TPAD_COMPAT_MODE; return (0); } else if (mode == WSMOUSE_NATIVE) { input->flags &= ~TPAD_COMPAT_MODE; input->flags |= TPAD_NATIVE_MODE; return (0); } return (-1); } struct wsmousehw *wsmouse_get_hw(struct device *sc) { return &((struct wsmouse_softc *) sc)->sc_input.hw; } /* * Create a default configuration based on the hardware infos in the 'hw' * fields. The 'params' argument is optional, hardware drivers can use it * to modify the generic defaults. Up to now this function is only useful * for touchpads. */ int wsmouse_configure(struct device *sc, struct wsmouse_param *params, u_int nparams) { struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input; int error; if (!(input->flags & CONFIGURED)) { if (input->hw.x_max && input->hw.y_max) { if (input->hw.flags & WSMOUSEHW_LR_DOWN) { input->filter.v.inv = input->hw.y_max + input->hw.y_min; } } input->filter.ratio = 1 << 12; if (input->hw.h_res > 0 && input->hw.v_res > 0) { input->filter.ratio *= input->hw.h_res; input->filter.ratio /= input->hw.v_res; } if (wsmouse_mt_init(sc, input->hw.mt_slots, (input->hw.flags & WSMOUSEHW_MT_TRACKING))) { printf("wsmouse_configure: " "MT initialization failed.\n"); return (-1); } if (IS_TOUCHPAD(input) && wstpad_configure(input)) { printf("wstpad_configure: " "Initialization failed.\n"); return (-1); } input->flags |= CONFIGURED; if (params != NULL) { if ((error = wsmouse_set_params(sc, params, nparams))) return (error); } } if (IS_TOUCHPAD(input)) wsmouse_set_mode(sc, WSMOUSE_COMPAT); return (0); } void wsmouse_input_reset(struct wsmouseinput *input) { int num_slots, *matrix; struct mt_slot *slots; memset(&input->btn, 0, sizeof(struct btn_state)); memset(&input->motion, 0, sizeof(struct motion_state)); memset(&input->touch, 0, sizeof(struct touch_state)); input->touch.min_pressure = input->filter.pressure_hi; if ((num_slots = input->mt.num_slots)) { slots = input->mt.slots; matrix = input->mt.matrix; memset(&input->mt, 0, sizeof(struct mt_state)); memset(slots, 0, num_slots * sizeof(struct mt_slot)); input->mt.num_slots = num_slots; input->mt.slots = slots; input->mt.matrix = matrix; } if (input->tp != NULL) wstpad_reset(input); } void wsmouse_input_cleanup(struct wsmouseinput *input) { if (input->tp != NULL) wstpad_cleanup(input); free_mt_slots(input); }
21 15 22 22 21 12 16 16 13 5 13 3 4 19 19 19 19 3 2 43 21 43 21 7 2 7 2 7 21 28 21 7 21 18 18 5 1 4 4 46 45 12 12 10 10 12 11 4 10 10 55 56 34 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 /* $OpenBSD: nd6.c,v 1.280 2023/05/13 16:27:59 bluhm Exp $ */ /* $KAME: nd6.c,v 1.280 2002/06/08 19:52:07 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/timeout.h> #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/sockio.h> #include <sys/time.h> #include <sys/kernel.h> #include <sys/pool.h> #include <sys/errno.h> #include <sys/ioctl.h> #include <sys/syslog.h> #include <sys/queue.h> #include <sys/stdint.h> #include <sys/task.h> #include <net/if.h> #include <net/if_dl.h> #include <net/if_types.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/if_ether.h> #include <netinet/ip_ipsp.h> #include <netinet6/in6_var.h> #include <netinet/ip6.h> #include <netinet6/ip6_var.h> #include <netinet6/nd6.h> #include <netinet/icmp6.h> /* * Locks used to protect struct members in this file: * a atomic operations * I immutable after creation * K kernel lock * m nd6 mutex, needed when net lock is shared * N net lock */ #define ND6_SLOWTIMER_INTERVAL (60 * 60) /* 1 hour */ #define ND6_RECALC_REACHTM_INTERVAL (60 * 120) /* 2 hours */ /* timer values */ int nd6_timer_next = -1; /* at which uptime nd6_timer runs */ time_t nd6_expire_next = -1; /* at which uptime nd6_expire runs */ int nd6_delay = 5; /* delay first probe time 5 second */ int nd6_umaxtries = 3; /* maximum unicast query */ int nd6_mmaxtries = 3; /* maximum multicast query */ int nd6_gctimer = (60 * 60 * 24); /* 1 day: garbage collection timer */ /* preventing too many loops in ND option parsing */ int nd6_maxndopt = 10; /* max # of ND options allowed */ int nd6_maxnudhint = 0; /* max # of subsequent upper layer hints */ #ifdef ND6_DEBUG int nd6_debug = 1; #else int nd6_debug = 0; #endif /* llinfo_nd6 live time, rt_llinfo and RTF_LLINFO are protected by nd6_mtx */ struct mutex nd6_mtx = MUTEX_INITIALIZER(IPL_SOFTNET); TAILQ_HEAD(llinfo_nd6_head, llinfo_nd6) nd6_list = TAILQ_HEAD_INITIALIZER(nd6_list); /* [mN] list of llinfo_nd6 structures */ struct pool nd6_pool; /* [I] pool for llinfo_nd6 structures */ int nd6_inuse; /* [m] limit neigbor discovery routes */ unsigned int ln_hold_total; /* [a] packets currently in the nd6 queue */ void nd6_timer(void *); void nd6_slowtimo(void *); void nd6_expire(void *); void nd6_expire_timer(void *); void nd6_invalidate(struct rtentry *); void nd6_free(struct rtentry *); int nd6_llinfo_timer(struct rtentry *); struct timeout nd6_timer_to; struct timeout nd6_slowtimo_ch; struct timeout nd6_expire_timeout; struct task nd6_expire_task; void nd6_init(void) { pool_init(&nd6_pool, sizeof(struct llinfo_nd6), 0, IPL_SOFTNET, 0, "nd6", NULL); task_set(&nd6_expire_task, nd6_expire, NULL); /* start timer */ timeout_set_proc(&nd6_timer_to, nd6_timer, NULL); timeout_set_proc(&nd6_slowtimo_ch, nd6_slowtimo, NULL); timeout_add_sec(&nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL); timeout_set(&nd6_expire_timeout, nd6_expire_timer, NULL); } void nd6_ifattach(struct ifnet *ifp) { struct nd_ifinfo *nd; nd = malloc(sizeof(*nd), M_IP6NDP, M_WAITOK | M_ZERO); nd->reachable = ND_COMPUTE_RTIME(REACHABLE_TIME); ifp->if_nd = nd; } void nd6_ifdetach(struct ifnet *ifp) { struct nd_ifinfo *nd = ifp->if_nd; free(nd, M_IP6NDP, sizeof(*nd)); } /* * Parse multiple ND options. * This function is much easier to use, for ND routines that do not need * multiple options of the same type. */ int nd6_options(void *opt, int icmp6len, struct nd_opts *ndopts) { struct nd_opt_hdr *nd_opt, *next_opt, *last_opt; int i = 0; bzero(ndopts, sizeof(*ndopts)); if (icmp6len == 0) return 0; next_opt = opt; last_opt = (struct nd_opt_hdr *)((u_char *)opt + icmp6len); while (next_opt != NULL) { int olen; nd_opt = next_opt; /* make sure nd_opt_len is inside the buffer */ if ((caddr_t)&nd_opt->nd_opt_len >= (caddr_t)last_opt) goto invalid; /* every option must have a length greater than zero */ olen = nd_opt->nd_opt_len << 3; if (olen == 0) goto invalid; next_opt = (struct nd_opt_hdr *)((caddr_t)nd_opt + olen); if (next_opt > last_opt) { /* option overruns the end of buffer */ goto invalid; } else if (next_opt == last_opt) { /* reached the end of options chain */ next_opt = NULL; } switch (nd_opt->nd_opt_type) { case ND_OPT_SOURCE_LINKADDR: if (ndopts->nd_opts_src_lladdr != NULL) nd6log((LOG_INFO, "duplicated ND6 option found " "(type=%d)\n", nd_opt->nd_opt_type)); else ndopts->nd_opts_src_lladdr = nd_opt; break; case ND_OPT_TARGET_LINKADDR: if (ndopts->nd_opts_tgt_lladdr != NULL) nd6log((LOG_INFO, "duplicated ND6 option found " "(type=%d)\n", nd_opt->nd_opt_type)); else ndopts->nd_opts_tgt_lladdr = nd_opt; break; case ND_OPT_MTU: case ND_OPT_REDIRECTED_HEADER: case ND_OPT_PREFIX_INFORMATION: case ND_OPT_DNSSL: case ND_OPT_RDNSS: /* Don't warn, not used by kernel */ break; default: /* * Unknown options must be silently ignored, * to accommodate future extension to the protocol. */ nd6log((LOG_DEBUG, "nd6_options: unsupported option %d - " "option ignored\n", nd_opt->nd_opt_type)); break; } i++; if (i > nd6_maxndopt) { icmp6stat_inc(icp6s_nd_toomanyopt); nd6log((LOG_INFO, "too many loop in nd opt\n")); break; } } return 0; invalid: bzero(ndopts, sizeof(*ndopts)); icmp6stat_inc(icp6s_nd_badopt); return -1; } /* * ND6 timer routine to handle ND6 entries */ void nd6_llinfo_settimer(const struct llinfo_nd6 *ln, unsigned int secs) { time_t expire = getuptime() + secs; NET_ASSERT_LOCKED(); KASSERT(!ISSET(ln->ln_rt->rt_flags, RTF_LOCAL)); ln->ln_rt->rt_expire = expire; if (!timeout_pending(&nd6_timer_to) || expire < nd6_timer_next) { nd6_timer_next = expire; timeout_add_sec(&nd6_timer_to, secs); } } void nd6_timer(void *unused) { struct llinfo_nd6 *ln, *nln; time_t uptime, expire; int secs; NET_LOCK(); uptime = getuptime(); expire = uptime + nd6_gctimer; /* Net lock is exclusive, no nd6 mutex needed for nd6_list here. */ TAILQ_FOREACH_SAFE(ln, &nd6_list, ln_list, nln) { struct rtentry *rt = ln->ln_rt; if (rt->rt_expire && rt->rt_expire <= uptime) if (nd6_llinfo_timer(rt)) continue; if (rt->rt_expire && rt->rt_expire < expire) expire = rt->rt_expire; } secs = expire - uptime; if (secs < 0) secs = 0; if (!TAILQ_EMPTY(&nd6_list)) { nd6_timer_next = uptime + secs; timeout_add_sec(&nd6_timer_to, secs); } NET_UNLOCK(); } /* * ND timer state handling. * * Returns 1 if `rt' should no longer be used, 0 otherwise. */ int nd6_llinfo_timer(struct rtentry *rt) { struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo; struct sockaddr_in6 *dst = satosin6(rt_key(rt)); struct ifnet *ifp; NET_ASSERT_LOCKED_EXCLUSIVE(); if ((ifp = if_get(rt->rt_ifidx)) == NULL) return 1; switch (ln->ln_state) { case ND6_LLINFO_INCOMPLETE: if (ln->ln_asked < nd6_mmaxtries) { ln->ln_asked++; nd6_llinfo_settimer(ln, RETRANS_TIMER / 1000); nd6_ns_output(ifp, NULL, &dst->sin6_addr, &ln->ln_saddr6, 0); } else { struct mbuf_list ml; struct mbuf *m; unsigned int len; mq_delist(&ln->ln_mq, &ml); len = ml_len(&ml); while ((m = ml_dequeue(&ml)) != NULL) { /* * Fake rcvif to make the ICMP error * more helpful in diagnosing for the * receiver. * XXX: should we consider older rcvif? */ m->m_pkthdr.ph_ifidx = rt->rt_ifidx; icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR, 0); } /* XXXSMP we also discard if other CPU enqueues */ if (mq_len(&ln->ln_mq) > 0) { /* mbuf is back in queue. Discard. */ atomic_sub_int(&ln_hold_total, len + mq_purge(&ln->ln_mq)); } else atomic_sub_int(&ln_hold_total, len); nd6_free(rt); ln = NULL; } break; case ND6_LLINFO_REACHABLE: if (!ND6_LLINFO_PERMANENT(ln)) { ln->ln_state = ND6_LLINFO_STALE; nd6_llinfo_settimer(ln, nd6_gctimer); } break; case ND6_LLINFO_STALE: case ND6_LLINFO_PURGE: /* Garbage Collection(RFC 2461 5.3) */ if (!ND6_LLINFO_PERMANENT(ln)) { nd6_free(rt); ln = NULL; } break; case ND6_LLINFO_DELAY: /* We need NUD */ ln->ln_asked = 1; ln->ln_state = ND6_LLINFO_PROBE; nd6_llinfo_settimer(ln, RETRANS_TIMER / 1000); nd6_ns_output(ifp, &dst->sin6_addr, &dst->sin6_addr, &ln->ln_saddr6, 0); break; case ND6_LLINFO_PROBE: if (ln->ln_asked < nd6_umaxtries) { ln->ln_asked++; nd6_llinfo_settimer(ln, RETRANS_TIMER / 1000); nd6_ns_output(ifp, &dst->sin6_addr, &dst->sin6_addr, &ln->ln_saddr6, 0); } else { nd6_free(rt); ln = NULL; } break; } if_put(ifp); return (ln == NULL); } void nd6_expire_timer_update(struct in6_ifaddr *ia6) { time_t expire_time = INT64_MAX; if (ia6->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) expire_time = ia6->ia6_lifetime.ia6t_expire; if (!(ia6->ia6_flags & IN6_IFF_DEPRECATED) && ia6->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME && expire_time > ia6->ia6_lifetime.ia6t_preferred) expire_time = ia6->ia6_lifetime.ia6t_preferred; if (expire_time == INT64_MAX) return; /* * IFA6_IS_INVALID() and IFA6_IS_DEPRECATED() check for uptime * greater than ia6t_expire or ia6t_preferred, not greater or equal. * Schedule timeout one second later so that either IFA6_IS_INVALID() * or IFA6_IS_DEPRECATED() is true. */ expire_time++; if (!timeout_pending(&nd6_expire_timeout) || nd6_expire_next > expire_time) { int secs; secs = expire_time - getuptime(); if (secs < 0) secs = 0; timeout_add_sec(&nd6_expire_timeout, secs); nd6_expire_next = expire_time; } } /* * Expire interface addresses. */ void nd6_expire(void *unused) { struct ifnet *ifp; NET_LOCK(); TAILQ_FOREACH(ifp, &ifnetlist, if_list) { struct ifaddr *ifa, *nifa; struct in6_ifaddr *ia6; TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrlist, ifa_list, nifa) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; ia6 = ifatoia6(ifa); /* check address lifetime */ if (IFA6_IS_INVALID(ia6)) { in6_purgeaddr(&ia6->ia_ifa); } else { if (IFA6_IS_DEPRECATED(ia6)) ia6->ia6_flags |= IN6_IFF_DEPRECATED; nd6_expire_timer_update(ia6); } } } NET_UNLOCK(); } void nd6_expire_timer(void *unused) { task_add(net_tq(0), &nd6_expire_task); } /* * Nuke neighbor cache/prefix/default router management table, right before * ifp goes away. */ void nd6_purge(struct ifnet *ifp) { struct llinfo_nd6 *ln, *nln; NET_ASSERT_LOCKED_EXCLUSIVE(); /* * Nuke neighbor cache entries for the ifp. */ TAILQ_FOREACH_SAFE(ln, &nd6_list, ln_list, nln) { struct rtentry *rt; struct sockaddr_dl *sdl; rt = ln->ln_rt; if (rt != NULL && rt->rt_gateway != NULL && rt->rt_gateway->sa_family == AF_LINK) { sdl = satosdl(rt->rt_gateway); if (sdl->sdl_index == ifp->if_index) nd6_free(rt); } } } struct rtentry * nd6_lookup(const struct in6_addr *addr6, int create, struct ifnet *ifp, u_int rtableid) { struct rtentry *rt; struct sockaddr_in6 sin6; int flags; bzero(&sin6, sizeof(sin6)); sin6.sin6_len = sizeof(struct sockaddr_in6); sin6.sin6_family = AF_INET6; sin6.sin6_addr = *addr6; flags = (create) ? RT_RESOLVE : 0; rt = rtalloc(sin6tosa(&sin6), flags, rtableid); if (rt != NULL && (rt->rt_flags & RTF_LLINFO) == 0) { /* * This is the case for the default route. * If we want to create a neighbor cache for the address, we * should free the route for the destination and allocate an * interface route. */ if (create) { rtfree(rt); rt = NULL; } } if (rt == NULL) { if (create && ifp) { struct rt_addrinfo info; struct llinfo_nd6 *ln; struct ifaddr *ifa; int error; /* * If no route is available and create is set, * we allocate a host route for the destination * and treat it like an interface route. * This hack is necessary for a neighbor which can't * be covered by our own prefix. */ ifa = ifaof_ifpforaddr(sin6tosa(&sin6), ifp); if (ifa == NULL) return (NULL); /* * Create a new route. RTF_LLINFO is necessary * to create a Neighbor Cache entry for the * destination in nd6_rtrequest which will be * called in rtrequest. */ bzero(&info, sizeof(info)); info.rti_ifa = ifa; info.rti_flags = RTF_HOST | RTF_LLINFO; info.rti_info[RTAX_DST] = sin6tosa(&sin6); info.rti_info[RTAX_GATEWAY] = sdltosa(ifp->if_sadl); error = rtrequest(RTM_ADD, &info, RTP_CONNECTED, &rt, rtableid); if (error) return (NULL); mtx_enter(&nd6_mtx); ln = (struct llinfo_nd6 *)rt->rt_llinfo; if (ln != NULL) ln->ln_state = ND6_LLINFO_NOSTATE; mtx_leave(&nd6_mtx); } else return (NULL); } /* * Validation for the entry. * Note that the check for rt_llinfo is necessary because a cloned * route from a parent route that has the L flag (e.g. the default * route to a p2p interface) may have the flag, too, while the * destination is not actually a neighbor. */ if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 || rt->rt_gateway->sa_family != AF_LINK || rt->rt_llinfo == NULL || (ifp != NULL && rt->rt_ifidx != ifp->if_index)) { if (create) { char addr[INET6_ADDRSTRLEN]; nd6log((LOG_DEBUG, "%s: failed to lookup %s (if=%s)\n", __func__, inet_ntop(AF_INET6, addr6, addr, sizeof(addr)), ifp ? ifp->if_xname : "unspec")); } rtfree(rt); return (NULL); } return (rt); } /* * Detect if a given IPv6 address identifies a neighbor on a given link. * XXX: should take care of the destination of a p2p link? */ int nd6_is_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp) { struct in6_ifaddr *ia6; struct ifaddr *ifa; struct rtentry *rt; /* * A link-local address is always a neighbor. * XXX: we should use the sin6_scope_id field rather than the embedded * interface index. * XXX: a link does not necessarily specify a single interface. */ if (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr) && ntohs(*(u_int16_t *)&addr->sin6_addr.s6_addr[2]) == ifp->if_index) return (1); TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; ia6 = ifatoia6(ifa); /* Prefix check down below. */ if (ia6->ia6_flags & IN6_IFF_AUTOCONF) continue; if (IN6_ARE_MASKED_ADDR_EQUAL(&addr->sin6_addr, &ia6->ia_addr.sin6_addr, &ia6->ia_prefixmask.sin6_addr)) return (1); } /* * Even if the address matches none of our addresses, it might be * in the neighbor cache. */ rt = nd6_lookup(&addr->sin6_addr, 0, ifp, ifp->if_rdomain); if (rt != NULL) { rtfree(rt); return (1); } return (0); } void nd6_invalidate(struct rtentry *rt) { struct llinfo_nd6 *ln; struct sockaddr_dl *sdl = satosdl(rt->rt_gateway); mtx_enter(&nd6_mtx); ln = (struct llinfo_nd6 *)rt->rt_llinfo; if (ln == NULL) { mtx_leave(&nd6_mtx); return; } atomic_sub_int(&ln_hold_total, mq_purge(&ln->ln_mq)); sdl->sdl_alen = 0; ln->ln_state = ND6_LLINFO_INCOMPLETE; ln->ln_asked = 0; mtx_leave(&nd6_mtx); } /* * Free an nd6 llinfo entry. */ void nd6_free(struct rtentry *rt) { struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo; struct in6_addr in6 = satosin6(rt_key(rt))->sin6_addr; struct ifnet *ifp; NET_ASSERT_LOCKED_EXCLUSIVE(); ifp = if_get(rt->rt_ifidx); if (!ip6_forwarding) { if (ln->ln_router) { /* * rt6_flush must be called whether or not the neighbor * is in the Default Router List. * See a corresponding comment in nd6_na_input(). */ rt6_flush(&in6, ifp); } } KASSERT(!ISSET(rt->rt_flags, RTF_LOCAL)); nd6_invalidate(rt); /* * Detach the route from the routing tree and the list of neighbor * caches, and disable the route entry not to be used in already * cached routes. */ if (!ISSET(rt->rt_flags, RTF_STATIC|RTF_CACHED)) rtdeletemsg(rt, ifp, ifp->if_rdomain); if_put(ifp); } /* * Upper-layer reachability hint for Neighbor Unreachability Detection. * * XXX cost-effective methods? */ void nd6_nud_hint(struct rtentry *rt) { struct llinfo_nd6 *ln; struct ifnet *ifp; NET_ASSERT_LOCKED_EXCLUSIVE(); ifp = if_get(rt->rt_ifidx); if (ifp == NULL) return; if ((rt->rt_flags & RTF_GATEWAY) != 0 || (rt->rt_flags & RTF_LLINFO) == 0 || rt->rt_llinfo == NULL || rt->rt_gateway == NULL || rt->rt_gateway->sa_family != AF_LINK) { /* This is not a host route. */ goto out; } ln = (struct llinfo_nd6 *)rt->rt_llinfo; if (ln->ln_state < ND6_LLINFO_REACHABLE) goto out; /* * if we get upper-layer reachability confirmation many times, * it is possible we have false information. */ ln->ln_byhint++; if (ln->ln_byhint > nd6_maxnudhint) goto out; ln->ln_state = ND6_LLINFO_REACHABLE; if (!ND6_LLINFO_PERMANENT(ln)) nd6_llinfo_settimer(ln, ifp->if_nd->reachable); out: if_put(ifp); } void nd6_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt) { struct sockaddr *gate = rt->rt_gateway; struct llinfo_nd6 *ln; struct ifaddr *ifa; struct in6_ifaddr *ifa6; if (ISSET(rt->rt_flags, RTF_GATEWAY|RTF_MULTICAST|RTF_MPLS)) return; if (nd6_need_cache(ifp) == 0 && (rt->rt_flags & RTF_HOST) == 0) { /* * This is probably an interface direct route for a link * which does not need neighbor caches (e.g. fe80::%lo0/64). * We do not need special treatment below for such a route. * Moreover, the RTF_LLINFO flag which would be set below * would annoy the ndp(8) command. */ return; } if (req == RTM_RESOLVE && nd6_need_cache(ifp) == 0) { /* * For routing daemons like ospf6d we allow neighbor discovery * based on the cloning route only. This allows us to send * packets directly into a network without having an address * with matching prefix on the interface. If the cloning * route is used for an 6to4 interface, we would mistakenly * make a neighbor cache for the host route, and would see * strange neighbor solicitation for the corresponding * destination. In order to avoid confusion, we check if the * interface is suitable for neighbor discovery, and stop the * process if not. Additionally, we remove the LLINFO flag * so that ndp(8) will not try to get the neighbor information * of the destination. */ rt->rt_flags &= ~RTF_LLINFO; return; } switch (req) { case RTM_ADD: if (rt->rt_flags & RTF_CLONING) { rt->rt_expire = 0; break; } if ((rt->rt_flags & RTF_LOCAL) && rt->rt_llinfo == NULL) rt->rt_expire = 0; /* FALLTHROUGH */ case RTM_RESOLVE: if (gate->sa_family != AF_LINK || gate->sa_len < sizeof(struct sockaddr_dl)) { log(LOG_DEBUG, "%s: bad gateway value: %s\n", __func__, ifp->if_xname); break; } satosdl(gate)->sdl_type = ifp->if_type; satosdl(gate)->sdl_index = ifp->if_index; /* * Case 2: This route may come from cloning, or a manual route * add with a LL address. */ ln = pool_get(&nd6_pool, PR_NOWAIT | PR_ZERO); if (ln == NULL) { log(LOG_DEBUG, "%s: pool get failed\n", __func__); break; } mtx_enter(&nd6_mtx); if (rt->rt_llinfo != NULL) { /* we lost the race, another thread has entered it */ mtx_leave(&nd6_mtx); pool_put(&nd6_pool, ln); break; } nd6_inuse++; mq_init(&ln->ln_mq, LN_HOLD_QUEUE, IPL_SOFTNET); rt->rt_llinfo = (caddr_t)ln; ln->ln_rt = rt; rt->rt_flags |= RTF_LLINFO; TAILQ_INSERT_HEAD(&nd6_list, ln, ln_list); /* this is required for "ndp" command. - shin */ if (req == RTM_ADD) { /* * gate should have some valid AF_LINK entry, * and ln expire should have some lifetime * which is specified by ndp command. */ ln->ln_state = ND6_LLINFO_REACHABLE; ln->ln_byhint = 0; } else { /* * When req == RTM_RESOLVE, rt is created and * initialized in rtrequest(), so rt_expire is 0. */ ln->ln_state = ND6_LLINFO_NOSTATE; nd6_llinfo_settimer(ln, 0); } /* * If we have too many cache entries, initiate immediate * purging for some "less recently used" entries. Note that * we cannot directly call nd6_free() here because it would * cause re-entering rtable related routines triggering * lock-order-reversal problems. */ if (ip6_neighborgcthresh >= 0 && nd6_inuse >= ip6_neighborgcthresh) { int i; for (i = 0; i < 10; i++) { struct llinfo_nd6 *ln_end; ln_end = TAILQ_LAST(&nd6_list, llinfo_nd6_head); if (ln_end == ln) break; /* Move this entry to the head */ TAILQ_REMOVE(&nd6_list, ln_end, ln_list); TAILQ_INSERT_HEAD(&nd6_list, ln_end, ln_list); if (ND6_LLINFO_PERMANENT(ln_end)) continue; if (ln_end->ln_state > ND6_LLINFO_INCOMPLETE) ln_end->ln_state = ND6_LLINFO_STALE; else ln_end->ln_state = ND6_LLINFO_PURGE; nd6_llinfo_settimer(ln_end, 0); } } /* * check if rt_key(rt) is one of my address assigned * to the interface. */ ifa6 = in6ifa_ifpwithaddr(ifp, &satosin6(rt_key(rt))->sin6_addr); ifa = ifa6 ? &ifa6->ia_ifa : NULL; if (ifa != NULL || (rt->rt_flags & RTF_ANNOUNCE)) { ln->ln_state = ND6_LLINFO_REACHABLE; ln->ln_byhint = 0; rt->rt_expire = 0; } mtx_leave(&nd6_mtx); /* join solicited node multicast for proxy ND */ if (ifa == NULL && (rt->rt_flags & RTF_ANNOUNCE) && (ifp->if_flags & IFF_MULTICAST)) { struct in6_addr llsol; int error; llsol = satosin6(rt_key(rt))->sin6_addr; llsol.s6_addr16[0] = htons(0xff02); llsol.s6_addr16[1] = htons(ifp->if_index); llsol.s6_addr32[1] = 0; llsol.s6_addr32[2] = htonl(1); llsol.s6_addr8[12] = 0xff; KERNEL_LOCK(); if (in6_addmulti(&llsol, ifp, &error)) { char addr[INET6_ADDRSTRLEN]; nd6log((LOG_ERR, "%s: failed to join " "%s (errno=%d)\n", ifp->if_xname, inet_ntop(AF_INET6, &llsol, addr, sizeof(addr)), error)); } KERNEL_UNLOCK(); } break; case RTM_DELETE: mtx_enter(&nd6_mtx); ln = (struct llinfo_nd6 *)rt->rt_llinfo; if (ln == NULL) { /* we lost the race, another thread has removed it */ mtx_leave(&nd6_mtx); break; } nd6_inuse--; TAILQ_REMOVE(&nd6_list, ln, ln_list); rt->rt_expire = 0; rt->rt_llinfo = NULL; rt->rt_flags &= ~RTF_LLINFO; atomic_sub_int(&ln_hold_total, mq_purge(&ln->ln_mq)); mtx_leave(&nd6_mtx); pool_put(&nd6_pool, ln); /* leave from solicited node multicast for proxy ND */ if ((rt->rt_flags & RTF_ANNOUNCE) != 0 && (ifp->if_flags & IFF_MULTICAST) != 0) { struct in6_addr llsol; struct in6_multi *in6m; llsol = satosin6(rt_key(rt))->sin6_addr; llsol.s6_addr16[0] = htons(0xff02); llsol.s6_addr16[1] = htons(ifp->if_index); llsol.s6_addr32[1] = 0; llsol.s6_addr32[2] = htonl(1); llsol.s6_addr8[12] = 0xff; KERNEL_LOCK(); IN6_LOOKUP_MULTI(llsol, ifp, in6m); if (in6m) in6_delmulti(in6m); KERNEL_UNLOCK(); } break; case RTM_INVALIDATE: if (!ISSET(rt->rt_flags, RTF_LOCAL)) nd6_invalidate(rt); break; } } int nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp) { struct in6_ndireq *ndi = (struct in6_ndireq *)data; struct in6_nbrinfo *nbi = (struct in6_nbrinfo *)data; struct rtentry *rt; switch (cmd) { case SIOCGIFINFO_IN6: NET_LOCK_SHARED(); ndi->ndi = *ifp->if_nd; NET_UNLOCK_SHARED(); return (0); case SIOCGNBRINFO_IN6: { struct llinfo_nd6 *ln; struct in6_addr nb_addr = nbi->addr; /* make local for safety */ time_t expire; NET_LOCK_SHARED(); /* * XXX: KAME specific hack for scoped addresses * XXXX: for other scopes than link-local? */ if (IN6_IS_ADDR_LINKLOCAL(&nb_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&nb_addr)) { u_int16_t *idp = (u_int16_t *)&nb_addr.s6_addr[2]; if (*idp == 0) *idp = htons(ifp->if_index); } rt = nd6_lookup(&nb_addr, 0, ifp, ifp->if_rdomain); mtx_enter(&nd6_mtx); if (rt == NULL || (ln = (struct llinfo_nd6 *)rt->rt_llinfo) == NULL) { mtx_leave(&nd6_mtx); rtfree(rt); NET_UNLOCK_SHARED(); return (EINVAL); } expire = ln->ln_rt->rt_expire; if (expire != 0) { expire -= getuptime(); expire += gettime(); } nbi->state = ln->ln_state; nbi->asked = ln->ln_asked; nbi->isrouter = ln->ln_router; nbi->expire = expire; mtx_leave(&nd6_mtx); rtfree(rt); NET_UNLOCK_SHARED(); return (0); } } return (0); } /* * Create neighbor cache entry and cache link-layer address, * on reception of inbound ND6 packets. (RS/RA/NS/redirect) * * type - ICMP6 type * code - type dependent information */ void nd6_cache_lladdr(struct ifnet *ifp, const struct in6_addr *from, char *lladdr, int lladdrlen, int type, int code) { struct rtentry *rt; struct llinfo_nd6 *ln; int is_newentry; struct sockaddr_dl *sdl; int do_update; int olladdr; int llchange; int newstate = 0; NET_ASSERT_LOCKED_EXCLUSIVE(); if (!ifp) panic("%s: ifp == NULL", __func__); if (!from) panic("%s: from == NULL", __func__); /* nothing must be updated for unspecified address */ if (IN6_IS_ADDR_UNSPECIFIED(from)) return; /* * Validation about ifp->if_addrlen and lladdrlen must be done in * the caller. * * XXX If the link does not have link-layer address, what should * we do? (ifp->if_addrlen == 0) * Spec says nothing in sections for RA, RS and NA. There's small * description on it in NS section (RFC 2461 7.2.3). */ rt = nd6_lookup(from, 0, ifp, ifp->if_rdomain); if (rt == NULL) { rt = nd6_lookup(from, 1, ifp, ifp->if_rdomain); is_newentry = 1; } else { /* do not overwrite local or static entry */ if (ISSET(rt->rt_flags, RTF_STATIC|RTF_LOCAL)) { rtfree(rt); return; } is_newentry = 0; } if (!rt) return; if ((rt->rt_flags & (RTF_GATEWAY | RTF_LLINFO)) != RTF_LLINFO) { fail: nd6_free(rt); rtfree(rt); return; } ln = (struct llinfo_nd6 *)rt->rt_llinfo; if (ln == NULL) goto fail; if (rt->rt_gateway == NULL) goto fail; if (rt->rt_gateway->sa_family != AF_LINK) goto fail; sdl = satosdl(rt->rt_gateway); olladdr = (sdl->sdl_alen) ? 1 : 0; if (olladdr && lladdr) { if (bcmp(lladdr, LLADDR(sdl), ifp->if_addrlen)) llchange = 1; else llchange = 0; } else llchange = 0; /* * newentry olladdr lladdr llchange (*=record) * 0 n n -- (1) * 0 y n -- (2) * 0 n y -- (3) * STALE * 0 y y n (4) * * 0 y y y (5) * STALE * 1 -- n -- (6) NOSTATE(= PASSIVE) * 1 -- y -- (7) * STALE */ if (llchange) { char addr[INET6_ADDRSTRLEN]; log(LOG_INFO, "ndp info overwritten for %s by %s on %s\n", inet_ntop(AF_INET6, from, addr, sizeof(addr)), ether_sprintf(lladdr), ifp->if_xname); } if (lladdr) { /* (3-5) and (7) */ /* * Record source link-layer address * XXX is it dependent to ifp->if_type? */ sdl->sdl_alen = ifp->if_addrlen; bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen); } if (!is_newentry) { if ((!olladdr && lladdr) || /* (3) */ (olladdr && lladdr && llchange)) { /* (5) */ do_update = 1; newstate = ND6_LLINFO_STALE; } else /* (1-2,4) */ do_update = 0; } else { do_update = 1; if (!lladdr) /* (6) */ newstate = ND6_LLINFO_NOSTATE; else /* (7) */ newstate = ND6_LLINFO_STALE; } if (do_update) { /* * Update the state of the neighbor cache. */ ln->ln_state = newstate; if (ln->ln_state == ND6_LLINFO_STALE) { /* * Since nd6_resolve() in ifp->if_output() will cause * state transition to DELAY and reset the timer, * we must set the timer now, although it is actually * meaningless. */ nd6_llinfo_settimer(ln, nd6_gctimer); if_output_mq(ifp, &ln->ln_mq, &ln_hold_total, rt_key(rt), rt); } else if (ln->ln_state == ND6_LLINFO_INCOMPLETE) { /* probe right away */ nd6_llinfo_settimer(ln, 0); } } /* * ICMP6 type dependent behavior. * * NS: clear IsRouter if new entry * RS: clear IsRouter * RA: set IsRouter if there's lladdr * redir: clear IsRouter if new entry * * RA case, (1): * The spec says that we must set IsRouter in the following cases: * - If lladdr exist, set IsRouter. This means (1-5). * - If it is old entry (!newentry), set IsRouter. This means (7). * So, based on the spec, in (1-5) and (7) cases we must set IsRouter. * A question arises for (1) case. (1) case has no lladdr in the * neighbor cache, this is similar to (6). * This case is rare but we figured that we MUST NOT set IsRouter. * * newentry olladdr lladdr llchange NS RS RA redir * D R * 0 n n -- (1) c ? s * 0 y n -- (2) c s s * 0 n y -- (3) c s s * 0 y y n (4) c s s * 0 y y y (5) c s s * 1 -- n -- (6) c c c s * 1 -- y -- (7) c c s c s * * (c=clear s=set) */ switch (type & 0xff) { case ND_NEIGHBOR_SOLICIT: /* * New entry must have is_router flag cleared. */ if (is_newentry) /* (6-7) */ ln->ln_router = 0; break; case ND_REDIRECT: /* * If the icmp is a redirect to a better router, always set the * is_router flag. Otherwise, if the entry is newly created, * clear the flag. [RFC 2461, sec 8.3] */ if (code == ND_REDIRECT_ROUTER) ln->ln_router = 1; else if (is_newentry) /* (6-7) */ ln->ln_router = 0; break; case ND_ROUTER_SOLICIT: /* * is_router flag must always be cleared. */ ln->ln_router = 0; break; case ND_ROUTER_ADVERT: /* * Mark an entry with lladdr as a router. */ if ((!is_newentry && (olladdr || lladdr)) || /* (2-5) */ (is_newentry && lladdr)) { /* (7) */ ln->ln_router = 1; } break; } rtfree(rt); } void nd6_slowtimo(void *ignored_arg) { struct nd_ifinfo *nd6if; struct ifnet *ifp; NET_LOCK(); timeout_add_sec(&nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL); TAILQ_FOREACH(ifp, &ifnetlist, if_list) { nd6if = ifp->if_nd; if ((nd6if->recalctm -= ND6_SLOWTIMER_INTERVAL) <= 0) { /* * Since reachable time rarely changes by router * advertisements, we SHOULD insure that a new random * value gets recomputed at least once every few hours. * (RFC 2461, 6.3.4) */ nd6if->recalctm = ND6_RECALC_REACHTM_INTERVAL; nd6if->reachable = ND_COMPUTE_RTIME(REACHABLE_TIME); } } NET_UNLOCK(); } int nd6_resolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, struct sockaddr *dst, u_char *desten) { struct sockaddr_dl *sdl; struct rtentry *rt; struct llinfo_nd6 *ln; struct in6_addr saddr6; time_t uptime; int solicit = 0; if (m->m_flags & M_MCAST) { ETHER_MAP_IPV6_MULTICAST(&satosin6(dst)->sin6_addr, desten); return (0); } uptime = getuptime(); rt = rt_getll(rt0); if (ISSET(rt->rt_flags, RTF_REJECT) && (rt->rt_expire == 0 || rt->rt_expire > uptime)) { m_freem(m); return (rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); } /* * Address resolution or Neighbor Unreachability Detection * for the next hop. * At this point, the destination of the packet must be a unicast * or an anycast address(i.e. not a multicast). */ if (!ISSET(rt->rt_flags, RTF_LLINFO)) { char addr[INET6_ADDRSTRLEN]; log(LOG_DEBUG, "%s: %s: route contains no ND information\n", __func__, inet_ntop(AF_INET6, &satosin6(rt_key(rt))->sin6_addr, addr, sizeof(addr))); goto bad; } if (rt->rt_gateway->sa_family != AF_LINK) { printf("%s: something odd happens\n", __func__); goto bad; } mtx_enter(&nd6_mtx); ln = (struct llinfo_nd6 *)rt->rt_llinfo; if (ln == NULL) { mtx_leave(&nd6_mtx); goto bad; } /* * Move this entry to the head of the queue so that it is less likely * for this entry to be a target of forced garbage collection (see * nd6_rtrequest()). */ TAILQ_REMOVE(&nd6_list, ln, ln_list); TAILQ_INSERT_HEAD(&nd6_list, ln, ln_list); /* * The first time we send a packet to a neighbor whose entry is * STALE, we have to change the state to DELAY and set a timer to * expire in DELAY_FIRST_PROBE_TIME seconds to ensure we do * neighbor unreachability detection on expiration. * (RFC 2461 7.3.3) */ if (ln->ln_state == ND6_LLINFO_STALE) { ln->ln_asked = 0; ln->ln_state = ND6_LLINFO_DELAY; nd6_llinfo_settimer(ln, nd6_delay); } /* * If the neighbor cache entry has a state other than INCOMPLETE * (i.e. its link-layer address is already resolved), just * send the packet. */ if (ln->ln_state > ND6_LLINFO_INCOMPLETE) { mtx_leave(&nd6_mtx); sdl = satosdl(rt->rt_gateway); if (sdl->sdl_alen != ETHER_ADDR_LEN) { char addr[INET6_ADDRSTRLEN]; log(LOG_DEBUG, "%s: %s: incorrect nd6 information\n", __func__, inet_ntop(AF_INET6, &satosin6(dst)->sin6_addr, addr, sizeof(addr))); goto bad; } bcopy(LLADDR(sdl), desten, sdl->sdl_alen); return (0); } /* * There is a neighbor cache entry, but no ethernet address * response yet. Insert mbuf in hold queue if below limit. * If above the limit free the queue without queuing the new packet. */ if (ln->ln_state == ND6_LLINFO_NOSTATE) ln->ln_state = ND6_LLINFO_INCOMPLETE; /* source address of prompting packet is needed by nd6_ns_output() */ if (m->m_len >= sizeof(struct ip6_hdr)) { memcpy(&ln->ln_saddr6, &mtod(m, struct ip6_hdr *)->ip6_src, sizeof(ln->ln_saddr6)); } if (atomic_inc_int_nv(&ln_hold_total) <= LN_HOLD_TOTAL) { if (mq_push(&ln->ln_mq, m) != 0) atomic_dec_int(&ln_hold_total); } else { atomic_sub_int(&ln_hold_total, mq_purge(&ln->ln_mq) + 1); m_freem(m); } /* * If there has been no NS for the neighbor after entering the * INCOMPLETE state, send the first solicitation. */ if (!ND6_LLINFO_PERMANENT(ln) && ln->ln_asked == 0) { ln->ln_asked++; nd6_llinfo_settimer(ln, RETRANS_TIMER / 1000); saddr6 = ln->ln_saddr6; solicit = 1; } mtx_leave(&nd6_mtx); if (solicit) nd6_ns_output(ifp, NULL, &satosin6(dst)->sin6_addr, &saddr6, 0); return (EAGAIN); bad: m_freem(m); return (EINVAL); } int nd6_need_cache(struct ifnet *ifp) { /* * RFC2893 says: * - unidirectional tunnels needs no ND */ switch (ifp->if_type) { case IFT_ETHER: case IFT_IEEE80211: case IFT_CARP: return (1); default: return (0); } }
121 70 146 209 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 /* $OpenBSD: bus_space.c,v 1.28 2022/11/29 21:41:39 guenther Exp $ */ /* $NetBSD: bus_space.c,v 1.2 2003/03/14 18:47:53 christos Exp $ */ /*- * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace * Simulation Facility, NASA Ames Research Center. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/extent.h> #include <uvm/uvm_extern.h> #include <machine/bus.h> #include <dev/isa/isareg.h> #include <machine/isa_machdep.h> extern int pmap_initialized; /* kernel address of "hole" (location of start of iomem in virtual) */ u_long atdevbase = 0; /* * Extent maps to manage I/O and memory space. Allocate * storage for 16 regions in each, initially. Later, ioport_malloc_safe * will indicate that it's safe to use malloc() to dynamically allocate * region descriptors. * * N.B. At least two regions are _always_ allocated from the iomem * extent map; (0 -> ISA hole) and (end of ISA hole -> end of RAM). * * The extent maps are not static! Machine-dependent ISA and EISA * routines need access to them for bus address space allocation. */ static long ioport_ex_storage[EXTENT_FIXED_STORAGE_SIZE(16) / sizeof(long)]; static long iomem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(16) / sizeof(long)]; struct extent *ioport_ex; struct extent *iomem_ex; static int ioport_malloc_safe; int x86_mem_add_mapping(bus_addr_t, bus_size_t, int, bus_space_handle_t *); u_int8_t x86_bus_space_io_read_1(bus_space_handle_t, bus_size_t); u_int16_t x86_bus_space_io_read_2(bus_space_handle_t, bus_size_t); u_int32_t x86_bus_space_io_read_4(bus_space_handle_t, bus_size_t); u_int64_t x86_bus_space_io_read_8(bus_space_handle_t, bus_size_t); void x86_bus_space_io_read_multi_1(bus_space_handle_t, bus_size_t, u_int8_t *, bus_size_t); void x86_bus_space_io_read_multi_2(bus_space_handle_t, bus_size_t, u_int16_t *, bus_size_t); void x86_bus_space_io_read_multi_4(bus_space_handle_t, bus_size_t, u_int32_t *, bus_size_t); void x86_bus_space_io_read_multi_8(bus_space_handle_t, bus_size_t, u_int64_t *, bus_size_t); void x86_bus_space_io_read_region_1(bus_space_handle_t, bus_size_t, u_int8_t *, bus_size_t); void x86_bus_space_io_read_region_2(bus_space_handle_t, bus_size_t, u_int16_t *, bus_size_t); void x86_bus_space_io_read_region_4(bus_space_handle_t, bus_size_t, u_int32_t *, bus_size_t); void x86_bus_space_io_read_region_8(bus_space_handle_t, bus_size_t, u_int64_t *, bus_size_t); void x86_bus_space_io_write_1(bus_space_handle_t, bus_size_t, u_int8_t); void x86_bus_space_io_write_2(bus_space_handle_t, bus_size_t, u_int16_t); void x86_bus_space_io_write_4(bus_space_handle_t, bus_size_t, u_int32_t); void x86_bus_space_io_write_8(bus_space_handle_t, bus_size_t, u_int64_t); void x86_bus_space_io_write_multi_1(bus_space_handle_t, bus_size_t, const u_int8_t *, bus_size_t); void x86_bus_space_io_write_multi_2(bus_space_handle_t, bus_size_t, const u_int16_t *, bus_size_t); void x86_bus_space_io_write_multi_4(bus_space_handle_t, bus_size_t, const u_int32_t *, bus_size_t); void x86_bus_space_io_write_multi_8(bus_space_handle_t, bus_size_t, const u_int64_t *, bus_size_t); void x86_bus_space_io_write_region_1(bus_space_handle_t, bus_size_t, const u_int8_t *, bus_size_t); void x86_bus_space_io_write_region_2(bus_space_handle_t, bus_size_t, const u_int16_t *, bus_size_t); void x86_bus_space_io_write_region_4(bus_space_handle_t, bus_size_t, const u_int32_t *, bus_size_t); void x86_bus_space_io_write_region_8(bus_space_handle_t, bus_size_t, const u_int64_t *, bus_size_t); void x86_bus_space_io_set_multi_1(bus_space_handle_t, bus_size_t, u_int8_t, size_t); void x86_bus_space_io_set_multi_2(bus_space_handle_t, bus_size_t, u_int16_t, size_t); void x86_bus_space_io_set_multi_4(bus_space_handle_t, bus_size_t, u_int32_t, size_t); void x86_bus_space_io_set_multi_8(bus_space_handle_t, bus_size_t, u_int64_t, size_t); void x86_bus_space_io_set_region_1(bus_space_handle_t, bus_size_t, u_int8_t, size_t); void x86_bus_space_io_set_region_2(bus_space_handle_t, bus_size_t, u_int16_t, size_t); void x86_bus_space_io_set_region_4(bus_space_handle_t, bus_size_t, u_int32_t, size_t); void x86_bus_space_io_set_region_8(bus_space_handle_t, bus_size_t, u_int64_t, size_t); void x86_bus_space_io_copy_1(bus_space_handle_t, bus_size_t, bus_space_handle_t, bus_size_t, size_t); void x86_bus_space_io_copy_2(bus_space_handle_t, bus_size_t, bus_space_handle_t, bus_size_t, size_t); void x86_bus_space_io_copy_4(bus_space_handle_t, bus_size_t, bus_space_handle_t, bus_size_t, size_t); void x86_bus_space_io_copy_8(bus_space_handle_t, bus_size_t, bus_space_handle_t, bus_size_t, size_t); void * x86_bus_space_io_vaddr(bus_space_handle_t); paddr_t x86_bus_space_io_mmap(bus_addr_t, off_t, int, int); const struct x86_bus_space_ops x86_bus_space_io_ops = { x86_bus_space_io_read_1, x86_bus_space_io_read_2, x86_bus_space_io_read_4, x86_bus_space_io_read_8, x86_bus_space_io_read_multi_1, x86_bus_space_io_read_multi_2, x86_bus_space_io_read_multi_4, x86_bus_space_io_read_multi_8, x86_bus_space_io_read_region_1, x86_bus_space_io_read_region_2, x86_bus_space_io_read_region_4, x86_bus_space_io_read_region_8, x86_bus_space_io_write_1, x86_bus_space_io_write_2, x86_bus_space_io_write_4, x86_bus_space_io_write_8, x86_bus_space_io_write_multi_1, x86_bus_space_io_write_multi_2, x86_bus_space_io_write_multi_4, x86_bus_space_io_write_multi_8, x86_bus_space_io_write_region_1, x86_bus_space_io_write_region_2, x86_bus_space_io_write_region_4, x86_bus_space_io_write_region_8, x86_bus_space_io_set_multi_1, x86_bus_space_io_set_multi_2, x86_bus_space_io_set_multi_4, x86_bus_space_io_set_multi_8, x86_bus_space_io_set_region_1, x86_bus_space_io_set_region_2, x86_bus_space_io_set_region_4, x86_bus_space_io_set_region_8, x86_bus_space_io_copy_1, x86_bus_space_io_copy_2, x86_bus_space_io_copy_4, x86_bus_space_io_copy_8, x86_bus_space_io_vaddr, x86_bus_space_io_mmap }; u_int8_t x86_bus_space_mem_read_1(bus_space_handle_t, bus_size_t); u_int16_t x86_bus_space_mem_read_2(bus_space_handle_t, bus_size_t); u_int32_t x86_bus_space_mem_read_4(bus_space_handle_t, bus_size_t); u_int64_t x86_bus_space_mem_read_8(bus_space_handle_t, bus_size_t); void x86_bus_space_mem_read_multi_1(bus_space_handle_t, bus_size_t, u_int8_t *, bus_size_t); void x86_bus_space_mem_read_multi_2(bus_space_handle_t, bus_size_t, u_int16_t *, bus_size_t); void x86_bus_space_mem_read_multi_4(bus_space_handle_t, bus_size_t, u_int32_t *, bus_size_t); void x86_bus_space_mem_read_multi_8(bus_space_handle_t, bus_size_t, u_int64_t *, bus_size_t); void x86_bus_space_mem_read_region_1(bus_space_handle_t, bus_size_t, u_int8_t *, bus_size_t); void x86_bus_space_mem_read_region_2(bus_space_handle_t, bus_size_t, u_int16_t *, bus_size_t); void x86_bus_space_mem_read_region_4(bus_space_handle_t, bus_size_t, u_int32_t *, bus_size_t); void x86_bus_space_mem_read_region_8(bus_space_handle_t, bus_size_t, u_int64_t *, bus_size_t); void x86_bus_space_mem_write_1(bus_space_handle_t, bus_size_t, u_int8_t); void x86_bus_space_mem_write_2(bus_space_handle_t, bus_size_t, u_int16_t); void x86_bus_space_mem_write_4(bus_space_handle_t, bus_size_t, u_int32_t); void x86_bus_space_mem_write_8(bus_space_handle_t, bus_size_t, u_int64_t); void x86_bus_space_mem_write_multi_1(bus_space_handle_t, bus_size_t, const u_int8_t *, bus_size_t); void x86_bus_space_mem_write_multi_2(bus_space_handle_t, bus_size_t, const u_int16_t *, bus_size_t); void x86_bus_space_mem_write_multi_4(bus_space_handle_t, bus_size_t, const u_int32_t *, bus_size_t); void x86_bus_space_mem_write_multi_8(bus_space_handle_t, bus_size_t, const u_int64_t *, bus_size_t); void x86_bus_space_mem_write_region_1(bus_space_handle_t, bus_size_t, const u_int8_t *, bus_size_t); void x86_bus_space_mem_write_region_2(bus_space_handle_t, bus_size_t, const u_int16_t *, bus_size_t); void x86_bus_space_mem_write_region_4(bus_space_handle_t, bus_size_t, const u_int32_t *, bus_size_t); void x86_bus_space_mem_write_region_8(bus_space_handle_t, bus_size_t, const u_int64_t *, bus_size_t); void x86_bus_space_mem_set_multi_1(bus_space_handle_t, bus_size_t, u_int8_t, size_t); void x86_bus_space_mem_set_multi_2(bus_space_handle_t, bus_size_t, u_int16_t, size_t); void x86_bus_space_mem_set_multi_4(bus_space_handle_t, bus_size_t, u_int32_t, size_t); void x86_bus_space_mem_set_multi_8(bus_space_handle_t, bus_size_t, u_int64_t, size_t); void x86_bus_space_mem_set_region_1(bus_space_handle_t, bus_size_t, u_int8_t, size_t); void x86_bus_space_mem_set_region_2(bus_space_handle_t, bus_size_t, u_int16_t, size_t); void x86_bus_space_mem_set_region_4(bus_space_handle_t, bus_size_t, u_int32_t, size_t); void x86_bus_space_mem_set_region_8(bus_space_handle_t, bus_size_t, u_int64_t, size_t); void x86_bus_space_mem_copy_1(bus_space_handle_t, bus_size_t, bus_space_handle_t, bus_size_t, size_t); void x86_bus_space_mem_copy_2(bus_space_handle_t, bus_size_t, bus_space_handle_t, bus_size_t, size_t); void x86_bus_space_mem_copy_4(bus_space_handle_t, bus_size_t, bus_space_handle_t, bus_size_t, size_t); void x86_bus_space_mem_copy_8(bus_space_handle_t, bus_size_t, bus_space_handle_t, bus_size_t, size_t); void * x86_bus_space_mem_vaddr(bus_space_handle_t); paddr_t x86_bus_space_mem_mmap(bus_addr_t, off_t, int, int); const struct x86_bus_space_ops x86_bus_space_mem_ops = { x86_bus_space_mem_read_1, x86_bus_space_mem_read_2, x86_bus_space_mem_read_4, x86_bus_space_mem_read_8, x86_bus_space_mem_read_multi_1, x86_bus_space_mem_read_multi_2, x86_bus_space_mem_read_multi_4, x86_bus_space_mem_read_multi_8, x86_bus_space_mem_read_region_1, x86_bus_space_mem_read_region_2, x86_bus_space_mem_read_region_4, x86_bus_space_mem_read_region_8, x86_bus_space_mem_write_1, x86_bus_space_mem_write_2, x86_bus_space_mem_write_4, x86_bus_space_mem_write_8, x86_bus_space_mem_write_multi_1, x86_bus_space_mem_write_multi_2, x86_bus_space_mem_write_multi_4, x86_bus_space_mem_write_multi_8, x86_bus_space_mem_write_region_1, x86_bus_space_mem_write_region_2, x86_bus_space_mem_write_region_4, x86_bus_space_mem_write_region_8, x86_bus_space_mem_set_multi_1, x86_bus_space_mem_set_multi_2, x86_bus_space_mem_set_multi_4, x86_bus_space_mem_set_multi_8, x86_bus_space_mem_set_region_1, x86_bus_space_mem_set_region_2, x86_bus_space_mem_set_region_4, x86_bus_space_mem_set_region_8, x86_bus_space_mem_copy_1, x86_bus_space_mem_copy_2, x86_bus_space_mem_copy_4, x86_bus_space_mem_copy_8, x86_bus_space_mem_vaddr, x86_bus_space_mem_mmap }; void x86_bus_space_init(void) { /* * Initialize the I/O port and I/O mem extent maps. * Note: we don't have to check the return value since * creation of a fixed extent map will never fail (since * descriptor storage has already been allocated). * * N.B. The iomem extent manages _all_ physical addresses * on the machine. When the amount of RAM is found, the two * extents of RAM are allocated from the map (0 -> ISA hole * and end of ISA hole -> end of RAM). */ ioport_ex = extent_create("ioport", 0x0, 0xffff, M_DEVBUF, (caddr_t)ioport_ex_storage, sizeof(ioport_ex_storage), EX_NOCOALESCE|EX_NOWAIT); iomem_ex = extent_create("iomem", 0x0, 0xffffffffffff, M_DEVBUF, (caddr_t)iomem_ex_storage, sizeof(iomem_ex_storage), EX_NOCOALESCE|EX_NOWAIT); } void x86_bus_space_mallocok(void) { ioport_malloc_safe = 1; } int bus_space_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, int flags, bus_space_handle_t *bshp) { int error; struct extent *ex; /* * Pick the appropriate extent map. */ if (t == X86_BUS_SPACE_IO) { ex = ioport_ex; if (flags & BUS_SPACE_MAP_LINEAR) return (EINVAL); } else if (t == X86_BUS_SPACE_MEM) ex = iomem_ex; else panic("bus_space_map: bad bus space tag"); /* * Before we go any further, let's make sure that this * region is available. */ error = extent_alloc_region(ex, bpa, size, EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0)); if (error) return (error); /* * For I/O space, that's all she wrote. */ if (t == X86_BUS_SPACE_IO) { *bshp = bpa; return (0); } if (bpa >= IOM_BEGIN && (bpa + size) <= IOM_END) { *bshp = (bus_space_handle_t)ISA_HOLE_VADDR(bpa); return(0); } if (!pmap_initialized && bpa < 0x100000000) { *bshp = (bus_space_handle_t)PMAP_DIRECT_MAP(bpa); return(0); } /* * For memory space, map the bus physical address to * a kernel virtual address. */ error = x86_mem_add_mapping(bpa, size, flags, bshp); if (error) { if (extent_free(ex, bpa, size, EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0))) { printf("bus_space_map: pa 0x%lx, size 0x%lx\n", bpa, size); printf("bus_space_map: can't free region\n"); } } return (error); } int _bus_space_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, int flags, bus_space_handle_t *bshp) { /* * For I/O space, just fill in the handle. */ if (t == X86_BUS_SPACE_IO) { *bshp = bpa; return (0); } /* * For memory space, map the bus physical address to * a kernel virtual address. */ return (x86_mem_add_mapping(bpa, size, flags, bshp)); } int bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart, bus_addr_t rend, bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags, bus_addr_t *bpap, bus_space_handle_t *bshp) { struct extent *ex; u_long bpa; int error; /* * Pick the appropriate extent map. */ if (t == X86_BUS_SPACE_IO) { ex = ioport_ex; } else if (t == X86_BUS_SPACE_MEM) ex = iomem_ex; else panic("bus_space_alloc: bad bus space tag"); /* * Sanity check the allocation against the extent's boundaries. */ if (rstart < ex->ex_start || rend > ex->ex_end) panic("bus_space_alloc: bad region start/end"); /* * Do the requested allocation. */ error = extent_alloc_subregion(ex, rstart, rend, size, alignment, 0, boundary, EX_FAST | EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0), &bpa); if (error) return (error); /* * For I/O space, that's all she wrote. */ if (t == X86_BUS_SPACE_IO) { *bshp = *bpap = bpa; return (0); } /* * For memory space, map the bus physical address to * a kernel virtual address. */ error = x86_mem_add_mapping(bpa, size, flags, bshp); if (error) { if (extent_free(iomem_ex, bpa, size, EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0))) { printf("bus_space_alloc: pa 0x%lx, size 0x%lx\n", bpa, size); printf("bus_space_alloc: can't free region\n"); } } *bpap = bpa; return (error); } int x86_mem_add_mapping(bus_addr_t bpa, bus_size_t size, int flags, bus_space_handle_t *bshp) { paddr_t pa, endpa; vaddr_t va; bus_size_t map_size; int pmap_flags = PMAP_NOCACHE; pa = trunc_page(bpa); endpa = round_page(bpa + size); #ifdef DIAGNOSTIC if (endpa <= pa && endpa != 0) panic("bus_mem_add_mapping: overflow"); #endif map_size = endpa - pa; va = (vaddr_t)km_alloc(map_size, &kv_any, &kp_none, &kd_nowait); if (va == 0) return (ENOMEM); *bshp = (bus_space_handle_t)(va + (bpa & PGOFSET)); if (flags & BUS_SPACE_MAP_CACHEABLE) pmap_flags = 0; else if (flags & BUS_SPACE_MAP_PREFETCHABLE) pmap_flags = PMAP_WC; for (; map_size > 0; pa += PAGE_SIZE, va += PAGE_SIZE, map_size -= PAGE_SIZE) pmap_kenter_pa(va, pa | pmap_flags, PROT_READ | PROT_WRITE); pmap_update(pmap_kernel()); return 0; } /* * void _bus_space_unmap(bus_space_tag bst, bus_space_handle bsh, * bus_size_t size, bus_addr_t *adrp) * * This function unmaps memory- or io-space mapped by the function * _bus_space_map(). This function works nearly as same as * bus_space_unmap(), but this function does not ask kernel * built-in extents and returns physical address of the bus space, * for the convenience of the extra extent manager. */ void _bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size, bus_addr_t *adrp) { u_long va, endva; bus_addr_t bpa; /* * Find the correct bus physical address. */ if (t == X86_BUS_SPACE_IO) { bpa = bsh; } else if (t == X86_BUS_SPACE_MEM) { bpa = (bus_addr_t)ISA_PHYSADDR(bsh); if (IOM_BEGIN <= bpa && bpa <= IOM_END) goto ok; va = trunc_page(bsh); endva = round_page(bsh + size); #ifdef DIAGNOSTIC if (endva <= va) panic("_bus_space_unmap: overflow"); #endif (void) pmap_extract(pmap_kernel(), va, &bpa); bpa += (bsh & PGOFSET); pmap_kremove(va, endva - va); pmap_update(pmap_kernel()); /* * Free the kernel virtual mapping. */ km_free((void *)va, endva - va, &kv_any, &kp_none); } else panic("bus_space_unmap: bad bus space tag"); ok: if (adrp != NULL) *adrp = bpa; } void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) { struct extent *ex; u_long va, endva; bus_addr_t bpa; /* * Find the correct extent and bus physical address. */ if (t == X86_BUS_SPACE_IO) { ex = ioport_ex; bpa = bsh; } else if (t == X86_BUS_SPACE_MEM) { ex = iomem_ex; bpa = (bus_addr_t)ISA_PHYSADDR(bsh); if (IOM_BEGIN <= bpa && bpa <= IOM_END) goto ok; if (bsh >= PMAP_DIRECT_BASE && bsh < PMAP_DIRECT_END) { bpa = PMAP_DIRECT_UNMAP(bsh); goto ok; } va = trunc_page(bsh); endva = round_page(bsh + size); #ifdef DIAGNOSTIC if (endva <= va) panic("bus_space_unmap: overflow"); #endif (void)pmap_extract(pmap_kernel(), va, &bpa); bpa += (bsh & PGOFSET); pmap_kremove(va, endva - va); pmap_update(pmap_kernel()); /* * Free the kernel virtual mapping. */ km_free((void *)va, endva - va, &kv_any, &kp_none); } else panic("bus_space_unmap: bad bus space tag"); ok: if (extent_free(ex, bpa, size, EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0))) { printf("bus_space_unmap: %s 0x%lx, size 0x%lx\n", (t == X86_BUS_SPACE_IO) ? "port" : "pa", bpa, size); printf("bus_space_unmap: can't free region\n"); } } void bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) { /* bus_space_unmap() does all that we need to do. */ bus_space_unmap(t, bsh, size); } int bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp) { *nbshp = bsh + offset; return (0); } u_int8_t x86_bus_space_io_read_1(bus_space_handle_t h, bus_size_t o) { return (inb(h + o)); } u_int16_t x86_bus_space_io_read_2(bus_space_handle_t h, bus_size_t o) { return (inw(h + o)); } u_int32_t x86_bus_space_io_read_4(bus_space_handle_t h, bus_size_t o) { return (inl(h + o)); } u_int64_t x86_bus_space_io_read_8(bus_space_handle_t h, bus_size_t o) { panic("bus_space_read_8: invalid bus space tag"); } void x86_bus_space_io_read_multi_1(bus_space_handle_t h, bus_size_t o, u_int8_t *ptr, bus_size_t cnt) { insb(h + o, ptr, cnt); } void x86_bus_space_io_read_multi_2(bus_space_handle_t h, bus_size_t o, u_int16_t *ptr, bus_size_t cnt) { insw(h + o, ptr, cnt); } void x86_bus_space_io_read_multi_4(bus_space_handle_t h, bus_size_t o, u_int32_t *ptr, bus_size_t cnt) { insl(h + o, ptr, cnt); } void x86_bus_space_io_read_multi_8(bus_space_handle_t h, bus_size_t o, u_int64_t *ptr, bus_size_t cnt) { panic("bus_space_multi_8: invalid bus space tag"); } void x86_bus_space_io_read_region_1(bus_space_handle_t h, bus_size_t o, u_int8_t *ptr, bus_size_t cnt) { int dummy1; void *dummy2; int dummy3; int __x; u_int32_t port = h + o; __asm volatile( "1: inb %w1,%%al ;" " stosb ;" " incl %1 ;" " loop 1b" : "=&a" (__x), "=d" (dummy1), "=D" (dummy2), "=c" (dummy3) : "1" (port), "2" (ptr), "3" (cnt) : "memory"); } void x86_bus_space_io_read_region_2(bus_space_handle_t h, bus_size_t o, u_int16_t *ptr, bus_size_t cnt) { int dummy1; void *dummy2; int dummy3; int __x; u_int32_t port = h + o; __asm volatile( "1: inw %w1,%%ax ;" " stosw ;" " addl $2,%1 ;" " loop 1b" : "=&a" (__x), "=d" (dummy1), "=D" (dummy2), "=c" (dummy3) : "1" ((port)), "2" ((ptr)), "3" ((cnt)) : "memory"); } void x86_bus_space_io_read_region_4(bus_space_handle_t h, bus_size_t o, u_int32_t *ptr, bus_size_t cnt) { int dummy1; void *dummy2; int dummy3; int __x; u_int32_t port = h + o; __asm volatile( "1: inl %w1,%%eax ;" " stosl ;" " addl $4,%1 ;" " loop 1b" : "=&a" (__x), "=d" (dummy1), "=D" (dummy2), "=c" (dummy3) : "1" (port), "2" (ptr), "3" (cnt) : "memory"); } void x86_bus_space_io_read_region_8(bus_space_handle_t h, bus_size_t o, u_int64_t *ptr, bus_size_t cnt) { panic("bus_space_read_region_8: invalid bus space tag"); } void x86_bus_space_io_write_1(bus_space_handle_t h, bus_size_t o, u_int8_t v) { outb(h + o, v); } void x86_bus_space_io_write_2(bus_space_handle_t h, bus_size_t o, u_int16_t v) { outw(h + o, v); } void x86_bus_space_io_write_4(bus_space_handle_t h, bus_size_t o, u_int32_t v) { outl(h + o, v); } void x86_bus_space_io_write_8(bus_space_handle_t h, bus_size_t o, u_int64_t v) { panic("bus_space_write_8: invalid bus space tag"); } void x86_bus_space_io_write_multi_1(bus_space_handle_t h, bus_size_t o, const u_int8_t *ptr, bus_size_t cnt) { outsb(h + o, ptr, cnt); } void x86_bus_space_io_write_multi_2(bus_space_handle_t h, bus_size_t o, const u_int16_t *ptr, bus_size_t cnt) { outsw(h + o, ptr, cnt); } void x86_bus_space_io_write_multi_4(bus_space_handle_t h, bus_size_t o, const u_int32_t *ptr, bus_size_t cnt) { outsl(h + o, ptr, cnt); } void x86_bus_space_io_write_multi_8(bus_space_handle_t h, bus_size_t o, const u_int64_t *ptr, bus_size_t cnt) { panic("bus_space_write_multi_8: invalid bus space tag"); } void x86_bus_space_io_write_region_1(bus_space_handle_t h, bus_size_t o, const u_int8_t *ptr, bus_size_t cnt) { int dummy1; void *dummy2; int dummy3; int __x; u_int32_t port = h + o; __asm volatile( "1: lodsb ;" " outb %%al,%w1 ;" " incl %1 ;" " loop 1b" : "=&a" (__x), "=d" (dummy1), "=S" (dummy2), "=c" (dummy3) : "1" (port), "2" (ptr), "3" (cnt) : "memory"); } void x86_bus_space_io_write_region_2(bus_space_handle_t h, bus_size_t o, const u_int16_t *ptr, bus_size_t cnt) { int dummy1; void *dummy2; int dummy3; int __x; u_int32_t port = h + o; __asm volatile( "1: lodsw ;" " outw %%ax,%w1 ;" " addl $2,%1 ;" " loop 1b" : "=&a" (__x), "=d" (dummy1), "=S" (dummy2), "=c" (dummy3) : "1" (port), "2" (ptr), "3" (cnt) : "memory"); } void x86_bus_space_io_write_region_4(bus_space_handle_t h, bus_size_t o, const u_int32_t *ptr, bus_size_t cnt) { int dummy1; void *dummy2; int dummy3; int __x; u_int32_t port = h + o; __asm volatile( "1: lodsl ;" " outl %%eax,%w1 ;" " addl $4,%1 ;" " loop 1b" : "=&a" (__x), "=d" (dummy1), "=S" (dummy2), "=c" (dummy3) : "1" (port), "2" (ptr), "3" (cnt) : "memory"); } void x86_bus_space_io_write_region_8(bus_space_handle_t h, bus_size_t o, const u_int64_t *ptr, bus_size_t cnt) { panic("bus_space_write_region_8: invalid bus space tag"); } void x86_bus_space_io_set_multi_1(bus_space_handle_t h, bus_size_t o, u_int8_t v, size_t c) { bus_addr_t addr = h + o; while (c--) outb(addr, v); } void x86_bus_space_io_set_multi_2(bus_space_handle_t h, bus_size_t o, u_int16_t v, size_t c) { bus_addr_t addr = h + o; while (c--) outw(addr, v); } void x86_bus_space_io_set_multi_4(bus_space_handle_t h, bus_size_t o, u_int32_t v, size_t c) { bus_addr_t addr = h + o; while (c--) outl(addr, v); } void x86_bus_space_io_set_multi_8(bus_space_handle_t h, bus_size_t o, u_int64_t v, size_t c) { panic("bus_space_set_multi_8: invalid bus space tag"); } void x86_bus_space_io_set_region_1(bus_space_handle_t h, bus_size_t o, u_int8_t v, size_t c) { bus_addr_t addr = h + o; for (; c != 0; c--, addr++) outb(addr, v); } void x86_bus_space_io_set_region_2(bus_space_handle_t h, bus_size_t o, u_int16_t v, size_t c) { bus_addr_t addr = h + o; for (; c != 0; c--, addr += sizeof(v)) outw(addr, v); } void x86_bus_space_io_set_region_4(bus_space_handle_t h, bus_size_t o, u_int32_t v, size_t c) { bus_addr_t addr = h + o; for (; c != 0; c--, addr += sizeof(v)) outl(addr, v); } void x86_bus_space_io_set_region_8(bus_space_handle_t h, bus_size_t o, u_int64_t v, size_t c) { panic("bus_space_set_region_8: invalid bus space tag"); } void x86_bus_space_io_copy_1(bus_space_handle_t h1, bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, size_t c) { bus_addr_t addr1 = h1 + o1; bus_addr_t addr2 = h2 + o2; if (addr1 >= addr2) { /* src after dest: copy forward */ for (; c != 0; c--, addr1++, addr2++) outb(addr2, inb(addr1)); } else { /* dest after src: copy backwards */ for (addr1 += (c - 1), addr2 += (c - 1); c != 0; c--, addr1--, addr2--) outb(addr2, inb(addr1)); } } void x86_bus_space_io_copy_2(bus_space_handle_t h1, bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, size_t c) { bus_addr_t addr1 = h1 + o1; bus_addr_t addr2 = h2 + o2; if (addr1 >= addr2) { /* src after dest: copy forward */ for (; c != 0; c--, addr1 += 2, addr2 += 2) outw(addr2, inw(addr1)); } else { /* dest after src: copy backwards */ for (addr1 += 2 * (c - 1), addr2 += 2 * (c - 1); c != 0; c--, addr1 -= 2, addr2 -= 2) outw(addr2, inw(addr1)); } } void x86_bus_space_io_copy_4(bus_space_handle_t h1, bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, size_t c) { bus_addr_t addr1 = h1 + o1; bus_addr_t addr2 = h2 + o2; if (addr1 >= addr2) { /* src after dest: copy forward */ for (; c != 0; c--, addr1 += 4, addr2 += 4) outl(addr2, inl(addr1)); } else { /* dest after src: copy backwards */ for (addr1 += 4 * (c - 1), addr2 += 4 * (c - 1); c != 0; c--, addr1 -= 4, addr2 -= 4) outl(addr2, inl(addr1)); } } void x86_bus_space_io_copy_8(bus_space_handle_t h1, bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, size_t c) { panic("bus_space_set_region_8: invalid bus space tag"); } void * x86_bus_space_io_vaddr(bus_space_handle_t h) { return (NULL); } paddr_t x86_bus_space_io_mmap(bus_addr_t addr, off_t off, int prot, int flags) { /* Can't mmap I/O space. */ return (-1); } void x86_bus_space_mem_write_1(bus_space_handle_t h, bus_size_t o, u_int8_t v) { *(volatile u_int8_t *)(h + o) = v; } void x86_bus_space_mem_write_2(bus_space_handle_t h, bus_size_t o, u_int16_t v) { *(volatile u_int16_t *)(h + o) = v; } u_int8_t x86_bus_space_mem_read_1(bus_space_handle_t h, bus_size_t o) { return (*(volatile u_int8_t *)(h + o)); } u_int16_t x86_bus_space_mem_read_2(bus_space_handle_t h, bus_size_t o) { return (*(volatile u_int16_t *)(h + o)); } u_int32_t x86_bus_space_mem_read_4(bus_space_handle_t h, bus_size_t o) { return (*(volatile u_int32_t *)(h + o)); } u_int64_t x86_bus_space_mem_read_8(bus_space_handle_t h, bus_size_t o) { return (*(volatile u_int64_t *)(h + o)); } void x86_bus_space_mem_read_multi_1(bus_space_handle_t h, bus_size_t o, u_int8_t *ptr, bus_size_t cnt) { void *dummy1; int dummy2; void *dummy3; int __x; __asm volatile( "1: movb (%2),%%al ;" " stosb ;" " loop 1b" : "=D" (dummy1), "=c" (dummy2), "=r" (dummy3), "=&a" (__x) : "0" ((ptr)), "1" ((cnt)), "2" (h + o) : "memory"); } void x86_bus_space_mem_read_multi_2(bus_space_handle_t h, bus_size_t o, u_int16_t *ptr, bus_size_t cnt) { void *dummy1; int dummy2; void *dummy3; int __x; __asm volatile( "1: movw (%2),%%ax ;" " stosw ;" " loop 1b" : "=D" (dummy1), "=c" (dummy2), "=r" (dummy3), "=&a" (__x) : "0" ((ptr)), "1" ((cnt)), "2" (h + o) : "memory"); } void x86_bus_space_mem_read_multi_4(bus_space_handle_t h, bus_size_t o, u_int32_t *ptr, bus_size_t cnt) { void *dummy1; int dummy2; void *dummy3; int __x; __asm volatile( "1: movl (%2),%%eax ;" " stosl ;" " loop 1b" : "=D" (dummy1), "=c" (dummy2), "=r" (dummy3), "=&a" (__x) : "0" ((ptr)), "1" ((cnt)), "2" (h + o) : "memory"); } void x86_bus_space_mem_read_multi_8(bus_space_handle_t h, bus_size_t o, u_int64_t *ptr, bus_size_t cnt) { void *dummy1; int dummy2; void *dummy3; int __x; __asm volatile( "1: movq (%2),%%rax ;" " stosq ;" " loop 1b" : "=D" (dummy1), "=c" (dummy2), "=r" (dummy3), "=&a" (__x) : "0" ((ptr)), "1" ((cnt)), "2" (h + o) : "memory"); } void x86_bus_space_mem_read_region_1(bus_space_handle_t h, bus_size_t o, u_int8_t *ptr, bus_size_t cnt) { int dummy1; void *dummy2; int dummy3; __asm volatile( " repne ;" " movsb" : "=S" (dummy1), "=D" (dummy2), "=c" (dummy3) : "0" (h + o), "1" (ptr), "2" (cnt) : "memory"); } void x86_bus_space_mem_read_region_2(bus_space_handle_t h, bus_size_t o, u_int16_t *ptr, bus_size_t cnt) { int dummy1; void *dummy2; int dummy3; __asm volatile( " repne ;" " movsw" : "=S" (dummy1), "=D" (dummy2), "=c" (dummy3) : "0" (h + o), "1" (ptr), "2" (cnt) : "memory"); } void x86_bus_space_mem_read_region_4(bus_space_handle_t h, bus_size_t o, u_int32_t *ptr, bus_size_t cnt) { int dummy1; void *dummy2; int dummy3; __asm volatile( " repne ;" " movsl" : "=S" (dummy1), "=D" (dummy2), "=c" (dummy3) : "0" (h + o), "1" (ptr), "2" (cnt) : "memory"); } void x86_bus_space_mem_read_region_8(bus_space_handle_t h, bus_size_t o, u_int64_t *ptr, bus_size_t cnt) { int dummy1; void *dummy2; int dummy3; __asm volatile( " repne ;" " movsq" : "=S" (dummy1), "=D" (dummy2), "=c" (dummy3) : "0" (h + o), "1" (ptr), "2" (cnt) : "memory"); } void x86_bus_space_mem_write_4(bus_space_handle_t h, bus_size_t o, u_int32_t v) { *(volatile u_int32_t *)(h + o) = v; } void x86_bus_space_mem_write_8(bus_space_handle_t h, bus_size_t o, u_int64_t v) { *(volatile u_int64_t *)(h + o) = v; } void x86_bus_space_mem_write_multi_1(bus_space_handle_t h, bus_size_t o, const u_int8_t *ptr, bus_size_t cnt) { void *dummy1; int dummy2; void *dummy3; int __x; __asm volatile( "1: lodsb ;" " movb %%al,(%2) ;" " loop 1b" : "=S" (dummy1), "=c" (dummy2), "=r" (dummy3), "=&a" (__x) : "0" (ptr), "1" (cnt), "2" (h + o)); } void x86_bus_space_mem_write_multi_2(bus_space_handle_t h, bus_size_t o, const u_int16_t *ptr, bus_size_t cnt) { void *dummy1; int dummy2; void *dummy3; int __x; __asm volatile( "1: lodsw ;" " movw %%ax,(%2) ;" " loop 1b" : "=S" (dummy1), "=c" (dummy2), "=r" (dummy3), "=&a" (__x) : "0" (ptr), "1" (cnt), "2" (h + o)); } void x86_bus_space_mem_write_multi_4(bus_space_handle_t h, bus_size_t o, const u_int32_t *ptr, bus_size_t cnt) { void *dummy1; int dummy2; void *dummy3; int __x; __asm volatile( "1: lodsl ;" " movl %%eax,(%2) ;" " loop 1b" : "=S" (dummy1), "=c" (dummy2), "=r" (dummy3), "=&a" (__x) : "0" (ptr), "1" (cnt), "2" (h + o)); } void x86_bus_space_mem_write_multi_8(bus_space_handle_t h, bus_size_t o, const u_int64_t *ptr, bus_size_t cnt) { void *dummy1; int dummy2; void *dummy3; int __x; __asm volatile( "1: lodsq ;" " movq %%rax,(%2) ;" " loop 1b" : "=S" (dummy1), "=c" (dummy2), "=r" (dummy3), "=&a" (__x) : "0" (ptr), "1" (cnt), "2" (h + o)); } void x86_bus_space_mem_write_region_1(bus_space_handle_t h, bus_size_t o, const u_int8_t *ptr, bus_size_t cnt) { int dummy1; void *dummy2; int dummy3; __asm volatile( " repne ;" " movsb" : "=D" (dummy1), "=S" (dummy2), "=c" (dummy3) : "0" (h + o), "1" (ptr), "2" (cnt) : "memory"); } void x86_bus_space_mem_write_region_2(bus_space_handle_t h, bus_size_t o, const u_int16_t *ptr, bus_size_t cnt) { int dummy1; void *dummy2; int dummy3; __asm volatile( " repne ;" " movsw" : "=D" (dummy1), "=S" (dummy2), "=c" (dummy3) : "0" (h + o), "1" (ptr), "2" (cnt) : "memory"); } void x86_bus_space_mem_write_region_4(bus_space_handle_t h, bus_size_t o, const u_int32_t *ptr, bus_size_t cnt) { int dummy1; void *dummy2; int dummy3; __asm volatile( " repne ;" " movsl" : "=D" (dummy1), "=S" (dummy2), "=c" (dummy3) : "0" (h + o), "1" (ptr), "2" (cnt) : "memory"); } void x86_bus_space_mem_write_region_8(bus_space_handle_t h, bus_size_t o, const u_int64_t *ptr, bus_size_t cnt) { int dummy1; void *dummy2; int dummy3; __asm volatile( " repne ;" " movsq" : "=D" (dummy1), "=S" (dummy2), "=c" (dummy3) : "0" (h + o), "1" (ptr), "2" (cnt) : "memory"); } void x86_bus_space_mem_set_multi_1(bus_space_handle_t h, bus_size_t o, u_int8_t v, size_t c) { bus_addr_t addr = h + o; while (c--) *(volatile u_int8_t *)(addr) = v; } void x86_bus_space_mem_set_multi_2(bus_space_handle_t h, bus_size_t o, u_int16_t v, size_t c) { bus_addr_t addr = h + o; while (c--) *(volatile u_int16_t *)(addr) = v; } void x86_bus_space_mem_set_multi_4(bus_space_handle_t h, bus_size_t o, u_int32_t v, size_t c) { bus_addr_t addr = h + o; while (c--) *(volatile u_int32_t *)(addr) = v; } void x86_bus_space_mem_set_multi_8(bus_space_handle_t h, bus_size_t o, u_int64_t v, size_t c) { bus_addr_t addr = h + o; while (c--) *(volatile u_int64_t *)(addr) = v; } void x86_bus_space_mem_set_region_1(bus_space_handle_t h, bus_size_t o, u_int8_t v, size_t c) { bus_addr_t addr = h + o; for (; c != 0; c--, addr++) *(volatile u_int8_t *)(addr) = v; } void x86_bus_space_mem_set_region_2(bus_space_handle_t h, bus_size_t o, u_int16_t v, size_t c) { bus_addr_t addr = h + o; for (; c != 0; c--, addr += sizeof(v)) *(volatile u_int16_t *)(addr) = v; } void x86_bus_space_mem_set_region_4(bus_space_handle_t h, bus_size_t o, u_int32_t v, size_t c) { bus_addr_t addr = h + o; for (; c != 0; c--, addr += sizeof(v)) *(volatile u_int32_t *)(addr) = v; } void x86_bus_space_mem_set_region_8(bus_space_handle_t h, bus_size_t o, u_int64_t v, size_t c) { bus_addr_t addr = h + o; for (; c != 0; c--, addr += sizeof(v)) *(volatile u_int64_t *)(addr) = v; } void x86_bus_space_mem_copy_1( bus_space_handle_t h1, bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, size_t c) { bus_addr_t addr1 = h1 + o1; bus_addr_t addr2 = h2 + o2; if (addr1 >= addr2) { /* src after dest: copy forward */ for (; c != 0; c--, addr1++, addr2++) *(volatile u_int8_t *)(addr2) = *(volatile u_int8_t *)(addr1); } else { /* dest after src: copy backwards */ for (addr1 += (c - 1), addr2 += (c - 1); c != 0; c--, addr1--, addr2--) *(volatile u_int8_t *)(addr2) = *(volatile u_int8_t *)(addr1); } } void x86_bus_space_mem_copy_2(bus_space_handle_t h1, bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, size_t c) { bus_addr_t addr1 = h1 + o1; bus_addr_t addr2 = h2 + o2; if (addr1 >= addr2) { /* src after dest: copy forward */ for (; c != 0; c--, addr1 += 2, addr2 += 2) *(volatile u_int16_t *)(addr2) = *(volatile u_int16_t *)(addr1); } else { /* dest after src: copy backwards */ for (addr1 += 2 * (c - 1), addr2 += 2 * (c - 1); c != 0; c--, addr1 -= 2, addr2 -= 2) *(volatile u_int16_t *)(addr2) = *(volatile u_int16_t *)(addr1); } } void x86_bus_space_mem_copy_4(bus_space_handle_t h1, bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, size_t c) { bus_addr_t addr1 = h1 + o1; bus_addr_t addr2 = h2 + o2; if (addr1 >= addr2) { /* src after dest: copy forward */ for (; c != 0; c--, addr1 += 4, addr2 += 4) *(volatile u_int32_t *)(addr2) = *(volatile u_int32_t *)(addr1); } else { /* dest after src: copy backwards */ for (addr1 += 4 * (c - 1), addr2 += 4 * (c - 1); c != 0; c--, addr1 -= 4, addr2 -= 4) *(volatile u_int32_t *)(addr2) = *(volatile u_int32_t *)(addr1); } } void x86_bus_space_mem_copy_8(bus_space_handle_t h1, bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, size_t c) { bus_addr_t addr1 = h1 + o1; bus_addr_t addr2 = h2 + o2; if (addr1 >= addr2) { /* src after dest: copy forward */ for (; c != 0; c--, addr1 += 8, addr2 += 8) *(volatile u_int64_t *)(addr2) = *(volatile u_int64_t *)(addr1); } else { /* dest after src: copy backwards */ for (addr1 += 8 * (c - 1), addr2 += 8 * (c - 1); c != 0; c--, addr1 -= 8, addr2 -= 8) *(volatile u_int64_t *)(addr2) = *(volatile u_int64_t *)(addr1); } } void * x86_bus_space_mem_vaddr(bus_space_handle_t h) { return ((void *)h); } paddr_t x86_bus_space_mem_mmap(bus_addr_t addr, off_t off, int prot, int flags) { /* * "addr" is the base address of the device we're mapping. * "off" is the offset into that device. * * Note we are called for each "page" in the device that * the upper layers want to map. */ return (addr + off); }
51 52 51 52 26 26 27 34 29 2 2 26 4 30 30 30 52 22 11 21 30 30 22 11 13 1 4 1 1 1 1 9 2 4 1 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 /* $OpenBSD: icmp6.c,v 1.252 2024/04/21 17:32:10 florian Exp $ */ /* $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 1982, 1986, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94 */ #include "carp.h" #include "pf.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/sysctl.h> #include <sys/protosw.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/time.h> #include <sys/kernel.h> #include <sys/syslog.h> #include <net/if.h> #include <net/if_var.h> #include <net/route.h> #include <net/if_dl.h> #include <net/if_types.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet6/in6_var.h> #include <netinet/ip6.h> #include <netinet6/ip6_var.h> #include <netinet/icmp6.h> #include <netinet6/mld6_var.h> #include <netinet/in_pcb.h> #include <netinet6/nd6.h> #include <netinet6/ip6protosw.h> #if NCARP > 0 #include <netinet/ip_carp.h> #endif #if NPF > 0 #include <net/pfvar.h> #endif struct cpumem *icmp6counters; extern int icmp6errppslim; static int icmp6errpps_count = 0; static struct timeval icmp6errppslim_last; /* * List of callbacks to notify when Path MTU changes are made. */ struct icmp6_mtudisc_callback { LIST_ENTRY(icmp6_mtudisc_callback) mc_list; void (*mc_func)(struct sockaddr_in6 *, u_int); }; LIST_HEAD(, icmp6_mtudisc_callback) icmp6_mtudisc_callbacks = LIST_HEAD_INITIALIZER(icmp6_mtudisc_callbacks); struct rttimer_queue icmp6_mtudisc_timeout_q; /* XXX do these values make any sense? */ static int icmp6_mtudisc_hiwat = 1280; static int icmp6_mtudisc_lowat = 256; /* * keep track of # of redirect routes. */ struct rttimer_queue icmp6_redirect_timeout_q; void icmp6_errcount(int, int); int icmp6_ratelimit(const struct in6_addr *, const int, const int); const char *icmp6_redirect_diag(struct in6_addr *, struct in6_addr *, struct in6_addr *); int icmp6_notify_error(struct mbuf *, int, int, int); void icmp6_mtudisc_timeout(struct rtentry *, u_int); void icmp6_init(void) { mld6_init(); rt_timer_queue_init(&icmp6_mtudisc_timeout_q, ip6_mtudisc_timeout, &icmp6_mtudisc_timeout); rt_timer_queue_init(&icmp6_redirect_timeout_q, icmp6_redirtimeout, NULL); icmp6counters = counters_alloc(icp6s_ncounters); } void icmp6_errcount(int type, int code) { enum icmp6stat_counters c = icp6s_ounknown; switch (type) { case ICMP6_DST_UNREACH: switch (code) { case ICMP6_DST_UNREACH_NOROUTE: c = icp6s_odst_unreach_noroute; break; case ICMP6_DST_UNREACH_ADMIN: c = icp6s_odst_unreach_admin; break; case ICMP6_DST_UNREACH_BEYONDSCOPE: c = icp6s_odst_unreach_beyondscope; break; case ICMP6_DST_UNREACH_ADDR: c = icp6s_odst_unreach_addr; break; case ICMP6_DST_UNREACH_NOPORT: c = icp6s_odst_unreach_noport; break; } break; case ICMP6_PACKET_TOO_BIG: c = icp6s_opacket_too_big; break; case ICMP6_TIME_EXCEEDED: switch (code) { case ICMP6_TIME_EXCEED_TRANSIT: c = icp6s_otime_exceed_transit; break; case ICMP6_TIME_EXCEED_REASSEMBLY: c = icp6s_otime_exceed_reassembly; break; } break; case ICMP6_PARAM_PROB: switch (code) { case ICMP6_PARAMPROB_HEADER: c = icp6s_oparamprob_header; break; case ICMP6_PARAMPROB_NEXTHEADER: c = icp6s_oparamprob_nextheader; break; case ICMP6_PARAMPROB_OPTION: c = icp6s_oparamprob_option; break; } break; case ND_REDIRECT: c = icp6s_oredirect; break; } icmp6stat_inc(c); } /* * Register a Path MTU Discovery callback. */ void icmp6_mtudisc_callback_register(void (*func)(struct sockaddr_in6 *, u_int)) { struct icmp6_mtudisc_callback *mc; LIST_FOREACH(mc, &icmp6_mtudisc_callbacks, mc_list) { if (mc->mc_func == func) return; } mc = malloc(sizeof(*mc), M_PCB, M_NOWAIT); if (mc == NULL) panic("%s", __func__); mc->mc_func = func; LIST_INSERT_HEAD(&icmp6_mtudisc_callbacks, mc, mc_list); } struct mbuf * icmp6_do_error(struct mbuf *m, int type, int code, int param) { struct ip6_hdr *oip6, *nip6; struct icmp6_hdr *icmp6; u_int preplen; int off; int nxt; icmp6stat_inc(icp6s_error); /* count per-type-code statistics */ icmp6_errcount(type, code); if (m->m_len < sizeof(struct ip6_hdr)) { m = m_pullup(m, sizeof(struct ip6_hdr)); if (m == NULL) return (NULL); } oip6 = mtod(m, struct ip6_hdr *); /* * If the destination address of the erroneous packet is a multicast * address, or the packet was sent using link-layer multicast, * we should basically suppress sending an error (RFC 2463, Section * 2.4). * We have two exceptions (the item e.2 in that section): * - the Packet Too Big message can be sent for path MTU discovery. * - the Parameter Problem Message that can be allowed an icmp6 error * in the option type field. This check has been done in * ip6_unknown_opt(), so we can just check the type and code. */ if ((m->m_flags & (M_BCAST|M_MCAST) || IN6_IS_ADDR_MULTICAST(&oip6->ip6_dst)) && (type != ICMP6_PACKET_TOO_BIG && (type != ICMP6_PARAM_PROB || code != ICMP6_PARAMPROB_OPTION))) goto freeit; /* * RFC 2463, 2.4 (e.5): source address check. * XXX: the case of anycast source? */ if (IN6_IS_ADDR_UNSPECIFIED(&oip6->ip6_src) || IN6_IS_ADDR_MULTICAST(&oip6->ip6_src)) goto freeit; /* * If we are about to send ICMPv6 against ICMPv6 error/redirect, * don't do it. */ nxt = -1; off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt); if (off >= 0 && nxt == IPPROTO_ICMPV6) { struct icmp6_hdr *icp; IP6_EXTHDR_GET(icp, struct icmp6_hdr *, m, off, sizeof(*icp)); if (icp == NULL) { icmp6stat_inc(icp6s_tooshort); return (NULL); } if (icp->icmp6_type < ICMP6_ECHO_REQUEST || icp->icmp6_type == ND_REDIRECT) { /* * ICMPv6 error * Special case: for redirect (which is * informational) we must not send icmp6 error. */ icmp6stat_inc(icp6s_canterror); goto freeit; } else { /* ICMPv6 informational - send the error */ } } else { /* non-ICMPv6 - send the error */ } oip6 = mtod(m, struct ip6_hdr *); /* adjust pointer */ /* Finally, do rate limitation check. */ if (icmp6_ratelimit(&oip6->ip6_src, type, code)) { icmp6stat_inc(icp6s_toofreq); goto freeit; } /* * OK, ICMP6 can be generated. */ if (m->m_pkthdr.len >= ICMPV6_PLD_MAXLEN) m_adj(m, ICMPV6_PLD_MAXLEN - m->m_pkthdr.len); preplen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr); M_PREPEND(m, preplen, M_DONTWAIT); if (m && m->m_len < preplen) m = m_pullup(m, preplen); if (m == NULL) { nd6log((LOG_DEBUG, "ENOBUFS in icmp6_error %d\n", __LINE__)); return (NULL); } nip6 = mtod(m, struct ip6_hdr *); nip6->ip6_src = oip6->ip6_src; nip6->ip6_dst = oip6->ip6_dst; if (IN6_IS_SCOPE_EMBED(&oip6->ip6_src)) oip6->ip6_src.s6_addr16[1] = 0; if (IN6_IS_SCOPE_EMBED(&oip6->ip6_dst)) oip6->ip6_dst.s6_addr16[1] = 0; icmp6 = (struct icmp6_hdr *)(nip6 + 1); icmp6->icmp6_type = type; icmp6->icmp6_code = code; icmp6->icmp6_pptr = htonl((u_int32_t)param); /* * icmp6_reflect() is designed to be in the input path. * icmp6_error() can be called from both input and output path, * and if we are in output path rcvif could contain bogus value. * clear m->m_pkthdr.ph_ifidx for safety, we should have enough * scope information in ip header (nip6). */ m->m_pkthdr.ph_ifidx = 0; icmp6stat_inc(icp6s_outhist + type); return (m); freeit: /* * If we can't tell whether or not we can generate ICMP6, free it. */ return (m_freem(m)); } /* * Generate an error packet of type error in response to bad IP6 packet. */ void icmp6_error(struct mbuf *m, int type, int code, int param) { struct mbuf *n; n = icmp6_do_error(m, type, code, param); if (n != NULL) { /* header order: IPv6 - ICMPv6 */ if (!icmp6_reflect(&n, sizeof(struct ip6_hdr), NULL)) ip6_send(n); } } /* * Process a received ICMP6 message. */ int icmp6_input(struct mbuf **mp, int *offp, int proto, int af) { #if NCARP > 0 struct ifnet *ifp; #endif struct mbuf *m = *mp, *n; struct ip6_hdr *ip6, *nip6; struct icmp6_hdr *icmp6, *nicmp6; int off = *offp; int icmp6len = m->m_pkthdr.len - off; int code, sum, noff; char src[INET6_ADDRSTRLEN], dst[INET6_ADDRSTRLEN]; /* * Locate icmp6 structure in mbuf, and check * that not corrupted and of at least minimum length */ ip6 = mtod(m, struct ip6_hdr *); if (icmp6len < sizeof(struct icmp6_hdr)) { icmp6stat_inc(icp6s_tooshort); goto freeit; } /* * calculate the checksum */ IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6)); if (icmp6 == NULL) { icmp6stat_inc(icp6s_tooshort); return IPPROTO_DONE; } code = icmp6->icmp6_code; if ((sum = in6_cksum(m, IPPROTO_ICMPV6, off, icmp6len)) != 0) { nd6log((LOG_ERR, "ICMP6 checksum error(%d|%x) %s\n", icmp6->icmp6_type, sum, inet_ntop(AF_INET6, &ip6->ip6_src, src, sizeof(src)))); icmp6stat_inc(icp6s_checksum); goto freeit; } #if NPF > 0 if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { switch (icmp6->icmp6_type) { /* * These ICMP6 types map to other connections. They must be * delivered to pr_ctlinput() also for diverted connections. */ case ICMP6_DST_UNREACH: case ICMP6_PACKET_TOO_BIG: case ICMP6_TIME_EXCEEDED: case ICMP6_PARAM_PROB: /* * Do not use the divert-to property of the TCP or UDP * rule when doing the PCB lookup for the raw socket. */ m->m_pkthdr.pf.flags &=~ PF_TAG_DIVERTED; break; default: goto raw; } } #endif /* NPF */ #if NCARP > 0 ifp = if_get(m->m_pkthdr.ph_ifidx); if (ifp == NULL) goto freeit; if (icmp6->icmp6_type == ICMP6_ECHO_REQUEST && carp_lsdrop(ifp, m, AF_INET6, ip6->ip6_src.s6_addr32, ip6->ip6_dst.s6_addr32, 1)) { if_put(ifp); goto freeit; } if_put(ifp); #endif icmp6stat_inc(icp6s_inhist + icmp6->icmp6_type); switch (icmp6->icmp6_type) { case ICMP6_DST_UNREACH: switch (code) { case ICMP6_DST_UNREACH_NOROUTE: code = PRC_UNREACH_NET; break; case ICMP6_DST_UNREACH_ADMIN: code = PRC_UNREACH_PROTOCOL; /* is this a good code? */ break; case ICMP6_DST_UNREACH_ADDR: code = PRC_HOSTDEAD; break; case ICMP6_DST_UNREACH_BEYONDSCOPE: /* I mean "source address was incorrect." */ code = PRC_PARAMPROB; break; case ICMP6_DST_UNREACH_NOPORT: code = PRC_UNREACH_PORT; break; default: goto badcode; } goto deliver; case ICMP6_PACKET_TOO_BIG: /* MTU is checked in icmp6_mtudisc_update. */ code = PRC_MSGSIZE; /* * Updating the path MTU will be done after examining * intermediate extension headers. */ goto deliver; case ICMP6_TIME_EXCEEDED: switch (code) { case ICMP6_TIME_EXCEED_TRANSIT: code = PRC_TIMXCEED_INTRANS; break; case ICMP6_TIME_EXCEED_REASSEMBLY: code = PRC_TIMXCEED_REASS; break; default: goto badcode; } goto deliver; case ICMP6_PARAM_PROB: switch (code) { case ICMP6_PARAMPROB_NEXTHEADER: code = PRC_UNREACH_PROTOCOL; break; case ICMP6_PARAMPROB_HEADER: case ICMP6_PARAMPROB_OPTION: code = PRC_PARAMPROB; break; default: goto badcode; } goto deliver; case ICMP6_ECHO_REQUEST: if (code != 0) goto badcode; /* * Copy mbuf to send to two data paths: userland socket(s), * and to the querier (echo reply). * m: a copy for socket, n: a copy for querier */ if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { /* Give up local */ n = m; m = *mp = NULL; goto deliverecho; } /* * If the first mbuf is shared, or the first mbuf is too short, * copy the first part of the data into a fresh mbuf. * Otherwise, we will wrongly overwrite both copies. */ if ((n->m_flags & M_EXT) != 0 || n->m_len < off + sizeof(struct icmp6_hdr)) { struct mbuf *n0 = n; const int maxlen = sizeof(*nip6) + sizeof(*nicmp6); /* * Prepare an internal mbuf. m_pullup() doesn't * always copy the length we specified. */ if (maxlen >= MCLBYTES) { /* Give up remote */ m_freem(n0); break; } MGETHDR(n, M_DONTWAIT, n0->m_type); if (n && maxlen >= MHLEN) { MCLGET(n, M_DONTWAIT); if ((n->m_flags & M_EXT) == 0) { m_free(n); n = NULL; } } if (n == NULL) { /* Give up local */ m_freem(n0); n = m; m = *mp = NULL; goto deliverecho; } M_MOVE_PKTHDR(n, n0); /* * Copy IPv6 and ICMPv6 only. */ nip6 = mtod(n, struct ip6_hdr *); bcopy(ip6, nip6, sizeof(struct ip6_hdr)); nicmp6 = (struct icmp6_hdr *)(nip6 + 1); bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr)); noff = sizeof(struct ip6_hdr); n->m_len = noff + sizeof(struct icmp6_hdr); /* * Adjust mbuf. ip6_plen will be adjusted in * ip6_output(). * n->m_pkthdr.len == n0->m_pkthdr.len at this point. */ n->m_pkthdr.len += noff + sizeof(struct icmp6_hdr); n->m_pkthdr.len -= (off + sizeof(struct icmp6_hdr)); m_adj(n0, off + sizeof(struct icmp6_hdr)); n->m_next = n0; } else { deliverecho: IP6_EXTHDR_GET(nicmp6, struct icmp6_hdr *, n, off, sizeof(*nicmp6)); noff = off; } if (n) { nicmp6->icmp6_type = ICMP6_ECHO_REPLY; nicmp6->icmp6_code = 0; icmp6stat_inc(icp6s_reflect); icmp6stat_inc(icp6s_outhist + ICMP6_ECHO_REPLY); if (!icmp6_reflect(&n, noff, NULL)) ip6_send(n); } if (!m) goto freeit; break; case ICMP6_ECHO_REPLY: if (code != 0) goto badcode; break; case MLD_LISTENER_QUERY: case MLD_LISTENER_REPORT: if (icmp6len < sizeof(struct mld_hdr)) goto badlen; if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { /* give up local */ mld6_input(m, off); m = NULL; goto freeit; } mld6_input(n, off); /* m stays. */ break; case MLD_LISTENER_DONE: if (icmp6len < sizeof(struct mld_hdr)) /* necessary? */ goto badlen; break; /* nothing to be done in kernel */ case MLD_MTRACE_RESP: case MLD_MTRACE: /* XXX: these two are experimental. not officially defined. */ /* XXX: per-interface statistics? */ break; /* just pass it to applications */ case ICMP6_WRUREQUEST: /* ICMP6_FQDN_QUERY */ /* IPv6 Node Information Queries are not supported */ break; case ICMP6_WRUREPLY: break; case ND_ROUTER_SOLICIT: case ND_ROUTER_ADVERT: if (code != 0) goto badcode; if ((icmp6->icmp6_type == ND_ROUTER_SOLICIT && icmp6len < sizeof(struct nd_router_solicit)) || (icmp6->icmp6_type == ND_ROUTER_ADVERT && icmp6len < sizeof(struct nd_router_advert))) goto badlen; if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { /* give up local */ nd6_rtr_cache(m, off, icmp6len, icmp6->icmp6_type); m = NULL; goto freeit; } nd6_rtr_cache(n, off, icmp6len, icmp6->icmp6_type); /* m stays. */ break; case ND_NEIGHBOR_SOLICIT: if (code != 0) goto badcode; if (icmp6len < sizeof(struct nd_neighbor_solicit)) goto badlen; if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { /* give up local */ nd6_ns_input(m, off, icmp6len); m = NULL; goto freeit; } nd6_ns_input(n, off, icmp6len); /* m stays. */ break; case ND_NEIGHBOR_ADVERT: if (code != 0) goto badcode; if (icmp6len < sizeof(struct nd_neighbor_advert)) goto badlen; if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { /* give up local */ nd6_na_input(m, off, icmp6len); m = NULL; goto freeit; } nd6_na_input(n, off, icmp6len); /* m stays. */ break; case ND_REDIRECT: if (code != 0) goto badcode; if (icmp6len < sizeof(struct nd_redirect)) goto badlen; if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { /* give up local */ icmp6_redirect_input(m, off); m = NULL; goto freeit; } icmp6_redirect_input(n, off); /* m stays. */ break; case ICMP6_ROUTER_RENUMBERING: if (code != ICMP6_ROUTER_RENUMBERING_COMMAND && code != ICMP6_ROUTER_RENUMBERING_RESULT) goto badcode; if (icmp6len < sizeof(struct icmp6_router_renum)) goto badlen; break; default: nd6log((LOG_DEBUG, "icmp6_input: unknown type %d(src=%s, dst=%s, ifid=%u)\n", icmp6->icmp6_type, inet_ntop(AF_INET6, &ip6->ip6_src, src, sizeof(src)), inet_ntop(AF_INET6, &ip6->ip6_dst, dst, sizeof(dst)), m->m_pkthdr.ph_ifidx)); if (icmp6->icmp6_type < ICMP6_ECHO_REQUEST) { /* ICMPv6 error: MUST deliver it by spec... */ code = PRC_NCMDS; /* deliver */ } else { /* ICMPv6 informational: MUST not deliver */ break; } deliver: if (icmp6_notify_error(m, off, icmp6len, code)) { /* In this case, m should've been freed. */ return (IPPROTO_DONE); } break; badcode: icmp6stat_inc(icp6s_badcode); break; badlen: icmp6stat_inc(icp6s_badlen); break; } #if NPF > 0 raw: #endif /* deliver the packet to appropriate sockets */ return rip6_input(mp, offp, proto, af); freeit: m_freem(m); return IPPROTO_DONE; } int icmp6_notify_error(struct mbuf *m, int off, int icmp6len, int code) { struct icmp6_hdr *icmp6; struct ip6_hdr *eip6; u_int32_t notifymtu; struct sockaddr_in6 icmp6src, icmp6dst; if (icmp6len < sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr)) { icmp6stat_inc(icp6s_tooshort); goto freeit; } IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6) + sizeof(struct ip6_hdr)); if (icmp6 == NULL) { icmp6stat_inc(icp6s_tooshort); return (-1); } eip6 = (struct ip6_hdr *)(icmp6 + 1); /* Detect the upper level protocol */ { void (*ctlfunc)(int, struct sockaddr *, u_int, void *); u_int8_t nxt = eip6->ip6_nxt; int eoff = off + sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr); struct ip6ctlparam ip6cp; struct in6_addr *finaldst = NULL; int icmp6type = icmp6->icmp6_type; struct ip6_frag *fh; struct ip6_rthdr *rth; struct ip6_rthdr0 *rth0; int rthlen; while (1) { /* XXX: should avoid infinite loop explicitly? */ struct ip6_ext *eh; switch (nxt) { case IPPROTO_HOPOPTS: case IPPROTO_DSTOPTS: case IPPROTO_AH: IP6_EXTHDR_GET(eh, struct ip6_ext *, m, eoff, sizeof(*eh)); if (eh == NULL) { icmp6stat_inc(icp6s_tooshort); return (-1); } if (nxt == IPPROTO_AH) eoff += (eh->ip6e_len + 2) << 2; else eoff += (eh->ip6e_len + 1) << 3; nxt = eh->ip6e_nxt; break; case IPPROTO_ROUTING: /* * When the erroneous packet contains a * routing header, we should examine the * header to determine the final destination. * Otherwise, we can't properly update * information that depends on the final * destination (e.g. path MTU). */ IP6_EXTHDR_GET(rth, struct ip6_rthdr *, m, eoff, sizeof(*rth)); if (rth == NULL) { icmp6stat_inc(icp6s_tooshort); return (-1); } rthlen = (rth->ip6r_len + 1) << 3; /* * XXX: currently there is no * officially defined type other * than type-0. * Note that if the segment left field * is 0, all intermediate hops must * have been passed. */ if (rth->ip6r_segleft && rth->ip6r_type == IPV6_RTHDR_TYPE_0) { int hops; IP6_EXTHDR_GET(rth0, struct ip6_rthdr0 *, m, eoff, rthlen); if (rth0 == NULL) { icmp6stat_inc(icp6s_tooshort); return (-1); } /* just ignore a bogus header */ if ((rth0->ip6r0_len % 2) == 0 && (hops = rth0->ip6r0_len/2)) finaldst = (struct in6_addr *)(rth0 + 1) + (hops - 1); } eoff += rthlen; nxt = rth->ip6r_nxt; break; case IPPROTO_FRAGMENT: IP6_EXTHDR_GET(fh, struct ip6_frag *, m, eoff, sizeof(*fh)); if (fh == NULL) { icmp6stat_inc(icp6s_tooshort); return (-1); } /* * Data after a fragment header is meaningless * unless it is the first fragment, but * we'll go to the notify label for path MTU * discovery. */ if (fh->ip6f_offlg & IP6F_OFF_MASK) goto notify; eoff += sizeof(struct ip6_frag); nxt = fh->ip6f_nxt; break; default: /* * This case includes ESP and the No Next * Header. In such cases going to the notify * label does not have any meaning * (i.e. ctlfunc will be NULL), but we go * anyway since we might have to update * path MTU information. */ goto notify; } } notify: IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6) + sizeof(struct ip6_hdr)); if (icmp6 == NULL) { icmp6stat_inc(icp6s_tooshort); return (-1); } eip6 = (struct ip6_hdr *)(icmp6 + 1); bzero(&icmp6dst, sizeof(icmp6dst)); icmp6dst.sin6_len = sizeof(struct sockaddr_in6); icmp6dst.sin6_family = AF_INET6; if (finaldst == NULL) icmp6dst.sin6_addr = eip6->ip6_dst; else icmp6dst.sin6_addr = *finaldst; icmp6dst.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.ph_ifidx, &icmp6dst.sin6_addr); if (in6_embedscope(&icmp6dst.sin6_addr, &icmp6dst, NULL, NULL)) { /* should be impossible */ nd6log((LOG_DEBUG, "icmp6_notify_error: in6_embedscope failed\n")); goto freeit; } /* * retrieve parameters from the inner IPv6 header, and convert * them into sockaddr structures. */ bzero(&icmp6src, sizeof(icmp6src)); icmp6src.sin6_len = sizeof(struct sockaddr_in6); icmp6src.sin6_family = AF_INET6; icmp6src.sin6_addr = eip6->ip6_src; icmp6src.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.ph_ifidx, &icmp6src.sin6_addr); if (in6_embedscope(&icmp6src.sin6_addr, &icmp6src, NULL, NULL)) { /* should be impossible */ nd6log((LOG_DEBUG, "icmp6_notify_error: in6_embedscope failed\n")); goto freeit; } icmp6src.sin6_flowinfo = (eip6->ip6_flow & IPV6_FLOWLABEL_MASK); if (finaldst == NULL) finaldst = &eip6->ip6_dst; ip6cp.ip6c_m = m; ip6cp.ip6c_icmp6 = icmp6; ip6cp.ip6c_ip6 = (struct ip6_hdr *)(icmp6 + 1); ip6cp.ip6c_off = eoff; ip6cp.ip6c_finaldst = finaldst; ip6cp.ip6c_src = &icmp6src; ip6cp.ip6c_nxt = nxt; #if NPF > 0 pf_pkt_addr_changed(m); #endif if (icmp6type == ICMP6_PACKET_TOO_BIG) { notifymtu = ntohl(icmp6->icmp6_mtu); ip6cp.ip6c_cmdarg = (void *)&notifymtu; } ctlfunc = inet6sw[ip6_protox[nxt]].pr_ctlinput; if (ctlfunc) (*ctlfunc)(code, sin6tosa(&icmp6dst), m->m_pkthdr.ph_rtableid, &ip6cp); } return (0); freeit: m_freem(m); return (-1); } void icmp6_mtudisc_update(struct ip6ctlparam *ip6cp, int validated) { unsigned long rtcount; struct icmp6_mtudisc_callback *mc; struct in6_addr *dst = ip6cp->ip6c_finaldst; struct icmp6_hdr *icmp6 = ip6cp->ip6c_icmp6; struct mbuf *m = ip6cp->ip6c_m; /* will be necessary for scope issue */ u_int mtu = ntohl(icmp6->icmp6_mtu); struct rtentry *rt = NULL; struct sockaddr_in6 sin6; if (mtu < IPV6_MMTU) return; /* * allow non-validated cases if memory is plenty, to make traffic * from non-connected pcb happy. */ rtcount = rt_timer_queue_count(&icmp6_mtudisc_timeout_q); if (validated) { if (0 <= icmp6_mtudisc_hiwat && rtcount > icmp6_mtudisc_hiwat) return; else if (0 <= icmp6_mtudisc_lowat && rtcount > icmp6_mtudisc_lowat) { /* * XXX nuke a victim, install the new one. */ } } else { if (0 <= icmp6_mtudisc_lowat && rtcount > icmp6_mtudisc_lowat) return; } bzero(&sin6, sizeof(sin6)); sin6.sin6_family = PF_INET6; sin6.sin6_len = sizeof(struct sockaddr_in6); sin6.sin6_addr = *dst; /* XXX normally, this won't happen */ if (IN6_IS_ADDR_LINKLOCAL(dst)) { sin6.sin6_addr.s6_addr16[1] = htons(m->m_pkthdr.ph_ifidx); } sin6.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.ph_ifidx, &sin6.sin6_addr); rt = icmp6_mtudisc_clone(&sin6, m->m_pkthdr.ph_rtableid, 0); if (rt != NULL && ISSET(rt->rt_flags, RTF_HOST) && !(rt->rt_locks & RTV_MTU) && (rt->rt_mtu > mtu || rt->rt_mtu == 0)) { struct ifnet *ifp; ifp = if_get(rt->rt_ifidx); if (ifp != NULL && mtu < ifp->if_mtu) { icmp6stat_inc(icp6s_pmtuchg); rt->rt_mtu = mtu; } if_put(ifp); } rtfree(rt); /* * Notify protocols that the MTU for this destination * has changed. */ LIST_FOREACH(mc, &icmp6_mtudisc_callbacks, mc_list) (*mc->mc_func)(&sin6, m->m_pkthdr.ph_rtableid); } /* * Reflect the ip6 packet back to the source. * OFF points to the icmp6 header, counted from the top of the mbuf. */ int icmp6_reflect(struct mbuf **mp, size_t off, struct sockaddr *sa) { struct mbuf *m = *mp; struct rtentry *rt = NULL; struct ip6_hdr *ip6; struct icmp6_hdr *icmp6; struct in6_addr t, *src = NULL; struct sockaddr_in6 sa6_src, sa6_dst; u_int rtableid; u_int8_t pfflags; CTASSERT(sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) <= MHLEN); /* too short to reflect */ if (off < sizeof(struct ip6_hdr)) { nd6log((LOG_DEBUG, "sanity fail: off=%lx, sizeof(ip6)=%lx in %s:%d\n", (u_long)off, (u_long)sizeof(struct ip6_hdr), __FILE__, __LINE__)); goto bad; } if (m->m_pkthdr.ph_loopcnt++ >= M_MAXLOOP) { m_freemp(mp); return (ELOOP); } rtableid = m->m_pkthdr.ph_rtableid; pfflags = m->m_pkthdr.pf.flags; m_resethdr(m); m->m_pkthdr.ph_rtableid = rtableid; m->m_pkthdr.pf.flags = pfflags & PF_TAG_GENERATED; /* * If there are extra headers between IPv6 and ICMPv6, strip * off that header first. */ if (off > sizeof(struct ip6_hdr)) { size_t l; struct ip6_hdr nip6; l = off - sizeof(struct ip6_hdr); m_copydata(m, 0, sizeof(nip6), (caddr_t)&nip6); m_adj(m, l); l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr); if (m->m_len < l) { if ((m = *mp = m_pullup(m, l)) == NULL) return (EMSGSIZE); } memcpy(mtod(m, caddr_t), &nip6, sizeof(nip6)); } else /* off == sizeof(struct ip6_hdr) */ { size_t l; l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr); if (m->m_len < l) { if ((m = *mp = m_pullup(m, l)) == NULL) return (EMSGSIZE); } } ip6 = mtod(m, struct ip6_hdr *); ip6->ip6_nxt = IPPROTO_ICMPV6; icmp6 = (struct icmp6_hdr *)(ip6 + 1); t = ip6->ip6_dst; /* * ip6_input() drops a packet if its src is multicast. * So, the src is never multicast. */ ip6->ip6_dst = ip6->ip6_src; /* * XXX: make sure to embed scope zone information, using * already embedded IDs or the received interface (if any). * Note that rcvif may be NULL. * TODO: scoped routing case (XXX). */ bzero(&sa6_src, sizeof(sa6_src)); sa6_src.sin6_family = AF_INET6; sa6_src.sin6_len = sizeof(sa6_src); sa6_src.sin6_addr = ip6->ip6_dst; bzero(&sa6_dst, sizeof(sa6_dst)); sa6_dst.sin6_family = AF_INET6; sa6_dst.sin6_len = sizeof(sa6_dst); sa6_dst.sin6_addr = t; if (sa == NULL) { /* * If the incoming packet was addressed directly to us (i.e. * unicast), use dst as the src for the reply. The * IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED case would be VERY rare, * but is possible (for example) when we encounter an error * while forwarding procedure destined to a duplicated address * of ours. */ rt = rtalloc(sin6tosa(&sa6_dst), 0, rtableid); if (rtisvalid(rt) && ISSET(rt->rt_flags, RTF_LOCAL) && !ISSET(ifatoia6(rt->rt_ifa)->ia6_flags, IN6_IFF_ANYCAST|IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED)) { src = &t; } rtfree(rt); rt = NULL; sa = sin6tosa(&sa6_src); } if (src == NULL) { struct in6_ifaddr *ia6; /* * This case matches to multicasts, our anycast, or unicasts * that we do not own. Select a source address based on the * source address of the erroneous packet. */ rt = rtalloc(sa, RT_RESOLVE, rtableid); if (!rtisvalid(rt)) { char addr[INET6_ADDRSTRLEN]; nd6log((LOG_DEBUG, "%s: source can't be determined: dst=%s\n", __func__, inet_ntop(AF_INET6, &sa6_src.sin6_addr, addr, sizeof(addr)))); rtfree(rt); goto bad; } ia6 = in6_ifawithscope(rt->rt_ifa->ifa_ifp, &t, rtableid, rt); if (ia6 != NULL) src = &ia6->ia_addr.sin6_addr; if (src == NULL) src = &ifatoia6(rt->rt_ifa)->ia_addr.sin6_addr; } ip6->ip6_src = *src; rtfree(rt); ip6->ip6_flow = 0; ip6->ip6_vfc &= ~IPV6_VERSION_MASK; ip6->ip6_vfc |= IPV6_VERSION; ip6->ip6_nxt = IPPROTO_ICMPV6; ip6->ip6_hlim = ip6_defhlim; icmp6->icmp6_cksum = 0; m->m_pkthdr.csum_flags = M_ICMP_CSUM_OUT; /* * XXX option handling */ m->m_flags &= ~(M_BCAST|M_MCAST); return (0); bad: m_freemp(mp); return (EHOSTUNREACH); } void icmp6_fasttimo(void) { mld6_fasttimeo(); } const char * icmp6_redirect_diag(struct in6_addr *src6, struct in6_addr *dst6, struct in6_addr *tgt6) { static char buf[1024]; /* XXX */ char src[INET6_ADDRSTRLEN]; char dst[INET6_ADDRSTRLEN]; char tgt[INET6_ADDRSTRLEN]; snprintf(buf, sizeof(buf), "(src=%s dst=%s tgt=%s)", inet_ntop(AF_INET6, src6, src, sizeof(src)), inet_ntop(AF_INET6, dst6, dst, sizeof(dst)), inet_ntop(AF_INET6, tgt6, tgt, sizeof(tgt))); return buf; } void icmp6_redirect_input(struct mbuf *m, int off) { struct ifnet *ifp; struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); struct nd_redirect *nd_rd; int icmp6len = ntohs(ip6->ip6_plen); char *lladdr = NULL; int lladdrlen = 0; struct rtentry *rt = NULL; int is_router; int is_onlink; struct in6_addr src6 = ip6->ip6_src; struct in6_addr redtgt6; struct in6_addr reddst6; struct nd_opts ndopts; char addr[INET6_ADDRSTRLEN]; ifp = if_get(m->m_pkthdr.ph_ifidx); if (ifp == NULL) return; /* XXX if we are router, we don't update route by icmp6 redirect */ if (ip6_forwarding) goto freeit; if (!(ifp->if_xflags & IFXF_AUTOCONF6)) goto freeit; IP6_EXTHDR_GET(nd_rd, struct nd_redirect *, m, off, icmp6len); if (nd_rd == NULL) { icmp6stat_inc(icp6s_tooshort); if_put(ifp); return; } redtgt6 = nd_rd->nd_rd_target; reddst6 = nd_rd->nd_rd_dst; if (IN6_IS_ADDR_LINKLOCAL(&redtgt6)) redtgt6.s6_addr16[1] = htons(ifp->if_index); if (IN6_IS_ADDR_LINKLOCAL(&reddst6)) reddst6.s6_addr16[1] = htons(ifp->if_index); /* validation */ if (!IN6_IS_ADDR_LINKLOCAL(&src6)) { nd6log((LOG_ERR, "ICMP6 redirect sent from %s rejected; " "must be from linklocal\n", inet_ntop(AF_INET6, &src6, addr, sizeof(addr)))); goto bad; } if (ip6->ip6_hlim != 255) { nd6log((LOG_ERR, "ICMP6 redirect sent from %s rejected; " "hlim=%d (must be 255)\n", inet_ntop(AF_INET6, &src6, addr, sizeof(addr)), ip6->ip6_hlim)); goto bad; } if (IN6_IS_ADDR_MULTICAST(&reddst6)) { nd6log((LOG_ERR, "ICMP6 redirect rejected; " "redirect dst must be unicast: %s\n", icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); goto bad; } { /* ip6->ip6_src must be equal to gw for icmp6->icmp6_reddst */ struct sockaddr_in6 sin6; struct in6_addr *gw6; bzero(&sin6, sizeof(sin6)); sin6.sin6_family = AF_INET6; sin6.sin6_len = sizeof(struct sockaddr_in6); memcpy(&sin6.sin6_addr, &reddst6, sizeof(reddst6)); rt = rtalloc(sin6tosa(&sin6), 0, m->m_pkthdr.ph_rtableid); if (rt) { if (rt->rt_gateway == NULL || rt->rt_gateway->sa_family != AF_INET6) { nd6log((LOG_ERR, "ICMP6 redirect rejected; no route " "with inet6 gateway found for redirect dst: %s\n", icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); rtfree(rt); goto bad; } gw6 = &(satosin6(rt->rt_gateway)->sin6_addr); if (bcmp(&src6, gw6, sizeof(struct in6_addr)) != 0) { nd6log((LOG_ERR, "ICMP6 redirect rejected; " "not equal to gw-for-src=%s (must be same): " "%s\n", inet_ntop(AF_INET6, gw6, addr, sizeof(addr)), icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); rtfree(rt); goto bad; } } else { nd6log((LOG_ERR, "ICMP6 redirect rejected; " "no route found for redirect dst: %s\n", icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); goto bad; } rtfree(rt); rt = NULL; } is_router = is_onlink = 0; if (IN6_IS_ADDR_LINKLOCAL(&redtgt6)) is_router = 1; /* router case */ if (bcmp(&redtgt6, &reddst6, sizeof(redtgt6)) == 0) is_onlink = 1; /* on-link destination case */ if (!is_router && !is_onlink) { nd6log((LOG_ERR, "ICMP6 redirect rejected; " "neither router case nor onlink case: %s\n", icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); goto bad; } /* validation passed */ icmp6len -= sizeof(*nd_rd); if (nd6_options(nd_rd + 1, icmp6len, &ndopts) < 0) { nd6log((LOG_INFO, "icmp6_redirect_input: " "invalid ND option, rejected: %s\n", icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); /* nd6_options have incremented stats */ goto freeit; } if (ndopts.nd_opts_tgt_lladdr) { lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1); lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3; } if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) { nd6log((LOG_INFO, "icmp6_redirect_input: lladdrlen mismatch for %s " "(if %d, icmp6 packet %d): %s\n", inet_ntop(AF_INET6, &redtgt6, addr, sizeof(addr)), ifp->if_addrlen, lladdrlen - 2, icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); goto bad; } /* RFC 2461 8.3 */ nd6_cache_lladdr(ifp, &redtgt6, lladdr, lladdrlen, ND_REDIRECT, is_onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER); if (!is_onlink) { /* better router case. perform rtredirect. */ /* perform rtredirect */ struct sockaddr_in6 sdst; struct sockaddr_in6 sgw; struct sockaddr_in6 ssrc; unsigned long rtcount; struct rtentry *newrt = NULL; /* * do not install redirect route, if the number of entries * is too much (> hiwat). note that, the node (= host) will * work just fine even if we do not install redirect route * (there will be additional hops, though). */ rtcount = rt_timer_queue_count(&icmp6_redirect_timeout_q); if (0 <= ip6_maxdynroutes && rtcount >= ip6_maxdynroutes) goto freeit; bzero(&sdst, sizeof(sdst)); bzero(&sgw, sizeof(sgw)); bzero(&ssrc, sizeof(ssrc)); sdst.sin6_family = sgw.sin6_family = ssrc.sin6_family = AF_INET6; sdst.sin6_len = sgw.sin6_len = ssrc.sin6_len = sizeof(struct sockaddr_in6); memcpy(&sgw.sin6_addr, &redtgt6, sizeof(struct in6_addr)); memcpy(&sdst.sin6_addr, &reddst6, sizeof(struct in6_addr)); memcpy(&ssrc.sin6_addr, &src6, sizeof(struct in6_addr)); rtredirect(sin6tosa(&sdst), sin6tosa(&sgw), sin6tosa(&ssrc), &newrt, m->m_pkthdr.ph_rtableid); if (newrt != NULL && icmp6_redirtimeout > 0) { rt_timer_add(newrt, &icmp6_redirect_timeout_q, m->m_pkthdr.ph_rtableid); } rtfree(newrt); } /* finally update cached route in each socket via pfctlinput */ { struct sockaddr_in6 sdst; bzero(&sdst, sizeof(sdst)); sdst.sin6_family = AF_INET6; sdst.sin6_len = sizeof(struct sockaddr_in6); memcpy(&sdst.sin6_addr, &reddst6, sizeof(struct in6_addr)); pfctlinput(PRC_REDIRECT_HOST, sin6tosa(&sdst)); } freeit: if_put(ifp); m_freem(m); return; bad: if_put(ifp); icmp6stat_inc(icp6s_badredirect); m_freem(m); } void icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt) { struct ifnet *ifp = NULL; struct in6_addr *ifp_ll6; struct in6_addr *nexthop; struct ip6_hdr *sip6; /* m0 as struct ip6_hdr */ struct mbuf *m = NULL; /* newly allocated one */ struct ip6_hdr *ip6; /* m as struct ip6_hdr */ struct nd_redirect *nd_rd; size_t maxlen; u_char *p; struct sockaddr_in6 src_sa; icmp6_errcount(ND_REDIRECT, 0); /* if we are not router, we don't send icmp6 redirect */ if (!ip6_forwarding) goto fail; /* sanity check */ if (m0 == NULL || !rtisvalid(rt)) goto fail; ifp = if_get(rt->rt_ifidx); if (ifp == NULL) goto fail; /* * Address check: * the source address must identify a neighbor, and * the destination address must not be a multicast address * [RFC 2461, sec 8.2] */ sip6 = mtod(m0, struct ip6_hdr *); bzero(&src_sa, sizeof(src_sa)); src_sa.sin6_family = AF_INET6; src_sa.sin6_len = sizeof(src_sa); src_sa.sin6_addr = sip6->ip6_src; /* we don't currently use sin6_scope_id, but eventually use it */ src_sa.sin6_scope_id = in6_addr2scopeid(ifp->if_index, &sip6->ip6_src); if (nd6_is_addr_neighbor(&src_sa, ifp) == 0) goto fail; if (IN6_IS_ADDR_MULTICAST(&sip6->ip6_dst)) goto fail; /* what should we do here? */ /* rate limit */ if (icmp6_ratelimit(&sip6->ip6_src, ND_REDIRECT, 0)) goto fail; /* * Since we are going to append up to 1280 bytes (= IPV6_MMTU), * we almost always ask for an mbuf cluster for simplicity. * (MHLEN < IPV6_MMTU is almost always true) */ #if IPV6_MMTU >= MCLBYTES # error assumption failed about IPV6_MMTU and MCLBYTES #endif MGETHDR(m, M_DONTWAIT, MT_HEADER); if (m && IPV6_MMTU >= MHLEN) MCLGET(m, M_DONTWAIT); if (!m) goto fail; m->m_pkthdr.ph_ifidx = 0; m->m_len = 0; maxlen = m_trailingspace(m); maxlen = min(IPV6_MMTU, maxlen); /* just for safety */ if (maxlen < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) + ((sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7)) { goto fail; } { /* get ip6 linklocal address for ifp(my outgoing interface). */ struct in6_ifaddr *ia6; if ((ia6 = in6ifa_ifpforlinklocal(ifp, IN6_IFF_TENTATIVE| IN6_IFF_DUPLICATED|IN6_IFF_ANYCAST)) == NULL) goto fail; ifp_ll6 = &ia6->ia_addr.sin6_addr; } /* get ip6 linklocal address for the router. */ if (rt->rt_gateway && (rt->rt_flags & RTF_GATEWAY)) { struct sockaddr_in6 *sin6; sin6 = satosin6(rt->rt_gateway); nexthop = &sin6->sin6_addr; if (!IN6_IS_ADDR_LINKLOCAL(nexthop)) nexthop = NULL; } else nexthop = NULL; /* ip6 */ ip6 = mtod(m, struct ip6_hdr *); ip6->ip6_flow = 0; ip6->ip6_vfc &= ~IPV6_VERSION_MASK; ip6->ip6_vfc |= IPV6_VERSION; /* ip6->ip6_plen will be set later */ ip6->ip6_nxt = IPPROTO_ICMPV6; ip6->ip6_hlim = 255; /* ip6->ip6_src must be linklocal addr for my outgoing if. */ bcopy(ifp_ll6, &ip6->ip6_src, sizeof(struct in6_addr)); bcopy(&sip6->ip6_src, &ip6->ip6_dst, sizeof(struct in6_addr)); /* ND Redirect */ nd_rd = (struct nd_redirect *)(ip6 + 1); nd_rd->nd_rd_type = ND_REDIRECT; nd_rd->nd_rd_code = 0; nd_rd->nd_rd_reserved = 0; if (rt->rt_flags & RTF_GATEWAY) { /* * nd_rd->nd_rd_target must be a link-local address in * better router cases. */ if (!nexthop) goto fail; bcopy(nexthop, &nd_rd->nd_rd_target, sizeof(nd_rd->nd_rd_target)); bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst, sizeof(nd_rd->nd_rd_dst)); } else { /* make sure redtgt == reddst */ nexthop = &sip6->ip6_dst; bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_target, sizeof(nd_rd->nd_rd_target)); bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst, sizeof(nd_rd->nd_rd_dst)); } p = (u_char *)(nd_rd + 1); { /* target lladdr option */ struct rtentry *nrt; int len; struct sockaddr_dl *sdl; struct nd_opt_hdr *nd_opt; char *lladdr; len = sizeof(*nd_opt) + ifp->if_addrlen; len = (len + 7) & ~7; /* round by 8 */ /* safety check */ if (len + (p - (u_char *)ip6) > maxlen) goto nolladdropt; nrt = nd6_lookup(nexthop, 0, ifp, ifp->if_rdomain); if ((nrt != NULL) && (nrt->rt_flags & (RTF_GATEWAY|RTF_LLINFO)) == RTF_LLINFO && (nrt->rt_gateway->sa_family == AF_LINK) && (sdl = satosdl(nrt->rt_gateway)) && sdl->sdl_alen) { nd_opt = (struct nd_opt_hdr *)p; nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR; nd_opt->nd_opt_len = len >> 3; lladdr = (char *)(nd_opt + 1); bcopy(LLADDR(sdl), lladdr, ifp->if_addrlen); p += len; } rtfree(nrt); } nolladdropt:; m->m_pkthdr.len = m->m_len = p - (u_char *)ip6; /* just to be safe */ if (p - (u_char *)ip6 > maxlen) goto noredhdropt; { /* redirected header option */ int len; struct nd_opt_rd_hdr *nd_opt_rh; /* * compute the maximum size for icmp6 redirect header option. * XXX room for auth header? */ len = maxlen - (p - (u_char *)ip6); len &= ~7; /* * Redirected header option spec (RFC2461 4.6.3) talks nothing * about padding/truncate rule for the original IP packet. * From the discussion on IPv6imp in Feb 1999, * the consensus was: * - "attach as much as possible" is the goal * - pad if not aligned (original size can be guessed by * original ip6 header) * Following code adds the padding if it is simple enough, * and truncates if not. */ if (len - sizeof(*nd_opt_rh) < m0->m_pkthdr.len) { /* not enough room, truncate */ m_adj(m0, (len - sizeof(*nd_opt_rh)) - m0->m_pkthdr.len); } else { /* * enough room, truncate if not aligned. * we don't pad here for simplicity. */ size_t extra; extra = m0->m_pkthdr.len % 8; if (extra) { /* truncate */ m_adj(m0, -extra); } len = m0->m_pkthdr.len + sizeof(*nd_opt_rh); } nd_opt_rh = (struct nd_opt_rd_hdr *)p; bzero(nd_opt_rh, sizeof(*nd_opt_rh)); nd_opt_rh->nd_opt_rh_type = ND_OPT_REDIRECTED_HEADER; nd_opt_rh->nd_opt_rh_len = len >> 3; p += sizeof(*nd_opt_rh); m->m_pkthdr.len = m->m_len = p - (u_char *)ip6; /* connect m0 to m */ m->m_pkthdr.len += m0->m_pkthdr.len; m_cat(m, m0); m0 = NULL; } noredhdropt: m_freem(m0); m0 = NULL; sip6 = mtod(m, struct ip6_hdr *); if (IN6_IS_ADDR_LINKLOCAL(&sip6->ip6_src)) sip6->ip6_src.s6_addr16[1] = 0; if (IN6_IS_ADDR_LINKLOCAL(&sip6->ip6_dst)) sip6->ip6_dst.s6_addr16[1] = 0; #if 0 if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src)) ip6->ip6_src.s6_addr16[1] = 0; if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) ip6->ip6_dst.s6_addr16[1] = 0; #endif if (IN6_IS_ADDR_LINKLOCAL(&nd_rd->nd_rd_target)) nd_rd->nd_rd_target.s6_addr16[1] = 0; if (IN6_IS_ADDR_LINKLOCAL(&nd_rd->nd_rd_dst)) nd_rd->nd_rd_dst.s6_addr16[1] = 0; ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); nd_rd->nd_rd_cksum = 0; m->m_pkthdr.csum_flags = M_ICMP_CSUM_OUT; /* send the packet to outside... */ ip6_output(m, NULL, NULL, 0, NULL, NULL); icmp6stat_inc(icp6s_outhist + ND_REDIRECT); if_put(ifp); return; fail: if_put(ifp); m_freem(m); m_freem(m0); } /* * ICMPv6 socket option processing. */ int icmp6_ctloutput(int op, struct socket *so, int level, int optname, struct mbuf *m) { int error = 0; struct inpcb *inp = sotoinpcb(so); if (level != IPPROTO_ICMPV6) return EINVAL; switch (op) { case PRCO_SETOPT: switch (optname) { case ICMP6_FILTER: { struct icmp6_filter *p; if (m == NULL || m->m_len != sizeof(*p)) { error = EMSGSIZE; break; } p = mtod(m, struct icmp6_filter *); if (!p || !inp->inp_icmp6filt) { error = EINVAL; break; } bcopy(p, inp->inp_icmp6filt, sizeof(struct icmp6_filter)); error = 0; break; } default: error = ENOPROTOOPT; break; } break; case PRCO_GETOPT: switch (optname) { case ICMP6_FILTER: { struct icmp6_filter *p; if (!inp->inp_icmp6filt) { error = EINVAL; break; } m->m_len = sizeof(struct icmp6_filter); p = mtod(m, struct icmp6_filter *); bcopy(inp->inp_icmp6filt, p, sizeof(struct icmp6_filter)); error = 0; break; } default: error = ENOPROTOOPT; break; } break; } return (error); } /* * Perform rate limit check. * Returns 0 if it is okay to send the icmp6 packet. * Returns 1 if the router SHOULD NOT send this icmp6 packet due to rate * limitation. * * XXX per-destination/type check necessary? * * dst - not used at this moment * type - not used at this moment * code - not used at this moment */ int icmp6_ratelimit(const struct in6_addr *dst, const int type, const int code) { /* PPS limit */ if (!ppsratecheck(&icmp6errppslim_last, &icmp6errpps_count, icmp6errppslim)) return 1; /* The packet is subject to rate limit */ return 0; /* okay to send */ } struct rtentry * icmp6_mtudisc_clone(struct sockaddr_in6 *dst, u_int rtableid, int ipsec) { struct rtentry *rt; int error; rt = rtalloc(sin6tosa(dst), RT_RESOLVE, rtableid); /* Check if the route is actually usable */ if (!rtisvalid(rt)) goto bad; /* IPsec needs the route only for PMTU, it can use reject for that */ if (!ipsec && (rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE))) goto bad; /* * No PMTU for local routes and permanent neighbors, * ARP and NDP use the same expire timer as the route. */ if (ISSET(rt->rt_flags, RTF_LOCAL) || (ISSET(rt->rt_flags, RTF_LLINFO) && rt->rt_expire == 0)) goto bad; /* If we didn't get a host route, allocate one */ if ((rt->rt_flags & RTF_HOST) == 0) { struct rtentry *nrt; struct rt_addrinfo info; struct sockaddr_rtlabel sa_rl; memset(&info, 0, sizeof(info)); info.rti_ifa = rt->rt_ifa; info.rti_flags = RTF_GATEWAY | RTF_HOST | RTF_DYNAMIC; info.rti_info[RTAX_DST] = sin6tosa(dst); info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; info.rti_info[RTAX_LABEL] = rtlabel_id2sa(rt->rt_labelid, &sa_rl); error = rtrequest(RTM_ADD, &info, rt->rt_priority, &nrt, rtableid); if (error) goto bad; nrt->rt_rmx = rt->rt_rmx; rtfree(rt); rt = nrt; rtm_send(rt, RTM_ADD, 0, rtableid); } error = rt_timer_add(rt, &icmp6_mtudisc_timeout_q, rtableid); if (error) goto bad; return (rt); bad: rtfree(rt); return (NULL); } void icmp6_mtudisc_timeout(struct rtentry *rt, u_int rtableid) { struct ifnet *ifp; NET_ASSERT_LOCKED(); ifp = if_get(rt->rt_ifidx); if (ifp == NULL) return; if ((rt->rt_flags & (RTF_DYNAMIC|RTF_HOST)) == (RTF_DYNAMIC|RTF_HOST)) { rtdeletemsg(rt, ifp, rtableid); } else { if (!(rt->rt_locks & RTV_MTU)) rt->rt_mtu = 0; } if_put(ifp); } const struct sysctl_bounded_args icmpv6ctl_vars[] = { { ICMPV6CTL_ND6_DELAY, &nd6_delay, 0, INT_MAX }, { ICMPV6CTL_ND6_UMAXTRIES, &nd6_umaxtries, 0, INT_MAX }, { ICMPV6CTL_ND6_MMAXTRIES, &nd6_mmaxtries, 0, INT_MAX }, { ICMPV6CTL_ERRPPSLIMIT, &icmp6errppslim, -1, 1000 }, { ICMPV6CTL_ND6_MAXNUDHINT, &nd6_maxnudhint, 0, INT_MAX }, { ICMPV6CTL_MTUDISC_HIWAT, &icmp6_mtudisc_hiwat, -1, INT_MAX }, { ICMPV6CTL_MTUDISC_LOWAT, &icmp6_mtudisc_lowat, -1, INT_MAX }, { ICMPV6CTL_ND6_DEBUG, &nd6_debug, 0, 1 }, }; int icmp6_sysctl_icmp6stat(void *oldp, size_t *oldlenp, void *newp) { struct icmp6stat *icmp6stat; int ret; CTASSERT(sizeof(*icmp6stat) == icp6s_ncounters * sizeof(uint64_t)); icmp6stat = malloc(sizeof(*icmp6stat), M_TEMP, M_WAITOK|M_ZERO); counters_read(icmp6counters, (uint64_t *)icmp6stat, icp6s_ncounters, NULL); ret = sysctl_rdstruct(oldp, oldlenp, newp, icmp6stat, sizeof(*icmp6stat)); free(icmp6stat, M_TEMP, sizeof(*icmp6stat)); return (ret); } int icmp6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int error; /* All sysctl names at this level are terminal. */ if (namelen != 1) return (ENOTDIR); switch (name[0]) { case ICMPV6CTL_REDIRTIMEOUT: NET_LOCK(); error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &icmp6_redirtimeout, 0, INT_MAX); rt_timer_queue_change(&icmp6_redirect_timeout_q, icmp6_redirtimeout); NET_UNLOCK(); break; case ICMPV6CTL_STATS: error = icmp6_sysctl_icmp6stat(oldp, oldlenp, newp); break; case ICMPV6CTL_ND6_QUEUED: error = sysctl_rdint(oldp, oldlenp, newp, atomic_load_int(&ln_hold_total)); break; default: NET_LOCK(); error = sysctl_bounded_arr(icmpv6ctl_vars, nitems(icmpv6ctl_vars), name, namelen, oldp, oldlenp, newp, newlen); NET_UNLOCK(); break; } return (error); }
353 239 140 5 5 74 75 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 /* $OpenBSD: uvm_object.c,v 1.25 2022/02/21 16:08:36 kn Exp $ */ /* * Copyright (c) 2006, 2010, 2019 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Mindaugas Rasiukevicius. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * uvm_object.c: operate with memory objects * */ #include <sys/param.h> #include <sys/systm.h> #include <sys/mman.h> #include <sys/atomic.h> #include <sys/rwlock.h> #include <uvm/uvm.h> /* Dummy object used by some pmaps for sanity checks. */ const struct uvm_pagerops pmap_pager = { /* nothing */ }; /* Dummy object used by the buffer cache for sanity checks. */ const struct uvm_pagerops bufcache_pager = { /* nothing */ }; /* Page count to fetch per single step. */ #define FETCH_PAGECOUNT 16 /* * uvm_obj_init: initialize UVM memory object. */ void uvm_obj_init(struct uvm_object *uobj, const struct uvm_pagerops *pgops, int refs) { int alock; alock = ((pgops != NULL) && (pgops != &pmap_pager) && (pgops != &bufcache_pager) && (refs != UVM_OBJ_KERN)); if (alock) { /* Allocate and assign a lock. */ rw_obj_alloc(&uobj->vmobjlock, "uobjlk"); } else { /* The lock will need to be set via uvm_obj_setlock(). */ uobj->vmobjlock = NULL; } uobj->pgops = pgops; RBT_INIT(uvm_objtree, &uobj->memt); uobj->uo_npages = 0; uobj->uo_refs = refs; } /* * uvm_obj_destroy: destroy UVM memory object. */ void uvm_obj_destroy(struct uvm_object *uo) { KASSERT(RBT_EMPTY(uvm_objtree, &uo->memt)); rw_obj_free(uo->vmobjlock); } /* * uvm_obj_setlock: assign a vmobjlock to the UVM object. * * => Caller is responsible to ensure that UVM objects is not use. * => Only dynamic lock may be previously set. We drop the reference then. */ void uvm_obj_setlock(struct uvm_object *uo, struct rwlock *lockptr) { struct rwlock *olockptr = uo->vmobjlock; if (olockptr) { /* Drop the reference on the old lock. */ rw_obj_free(olockptr); } if (lockptr == NULL) { /* If new lock is not passed - allocate default one. */ rw_obj_alloc(&lockptr, "uobjlk"); } uo->vmobjlock = lockptr; } #ifndef SMALL_KERNEL /* * uvm_obj_wire: wire the pages of entire UVM object. * * => NOTE: this function should only be used for types of objects * where PG_RELEASED flag is never set (aobj objects) * => caller must pass page-aligned start and end values * => if the caller passes in a pageq pointer, we'll return a list of * wired pages. */ int uvm_obj_wire(struct uvm_object *uobj, voff_t start, voff_t end, struct pglist *pageq) { int i, npages, left, error; struct vm_page *pgs[FETCH_PAGECOUNT]; voff_t offset = start; left = (end - start) >> PAGE_SHIFT; rw_enter(uobj->vmobjlock, RW_WRITE | RW_DUPOK); while (left) { npages = MIN(FETCH_PAGECOUNT, left); /* Get the pages */ memset(pgs, 0, sizeof(pgs)); error = (*uobj->pgops->pgo_get)(uobj, offset, pgs, &npages, 0, PROT_READ | PROT_WRITE, MADV_SEQUENTIAL, PGO_ALLPAGES | PGO_SYNCIO); if (error) goto error; rw_enter(uobj->vmobjlock, RW_WRITE | RW_DUPOK); for (i = 0; i < npages; i++) { KASSERT(pgs[i] != NULL); KASSERT(!(pgs[i]->pg_flags & PG_RELEASED)); if (pgs[i]->pg_flags & PQ_AOBJ) { atomic_clearbits_int(&pgs[i]->pg_flags, PG_CLEAN); uao_dropswap(uobj, i); } } /* Wire the pages */ uvm_lock_pageq(); for (i = 0; i < npages; i++) { uvm_pagewire(pgs[i]); if (pageq != NULL) TAILQ_INSERT_TAIL(pageq, pgs[i], pageq); } uvm_unlock_pageq(); /* Unbusy the pages */ uvm_page_unbusy(pgs, npages); left -= npages; offset += (voff_t)npages << PAGE_SHIFT; } rw_exit(uobj->vmobjlock); return 0; error: /* Unwire the pages which have been wired */ uvm_obj_unwire(uobj, start, offset); return error; } /* * uvm_obj_unwire: unwire the pages of entire UVM object. * * => caller must pass page-aligned start and end values */ void uvm_obj_unwire(struct uvm_object *uobj, voff_t start, voff_t end) { struct vm_page *pg; off_t offset; rw_enter(uobj->vmobjlock, RW_WRITE | RW_DUPOK); uvm_lock_pageq(); for (offset = start; offset < end; offset += PAGE_SIZE) { pg = uvm_pagelookup(uobj, offset); KASSERT(pg != NULL); KASSERT(!(pg->pg_flags & PG_RELEASED)); uvm_pageunwire(pg); } uvm_unlock_pageq(); rw_exit(uobj->vmobjlock); } #endif /* !SMALL_KERNEL */ /* * uvm_obj_free: free all pages in a uvm object, used by the buffer * cache to free all pages attached to a buffer. */ void uvm_obj_free(struct uvm_object *uobj) { struct vm_page *pg; struct pglist pgl; KASSERT(UVM_OBJ_IS_BUFCACHE(uobj)); KERNEL_ASSERT_LOCKED(); TAILQ_INIT(&pgl); /* * Extract from rb tree in offset order. The phys addresses * usually increase in that order, which is better for * uvm_pglistfree(). */ RBT_FOREACH(pg, uvm_objtree, &uobj->memt) { /* * clear PG_TABLED so we don't do work to remove * this pg from the uobj we are throwing away */ atomic_clearbits_int(&pg->pg_flags, PG_TABLED); uvm_lock_pageq(); uvm_pageclean(pg); uvm_unlock_pageq(); TAILQ_INSERT_TAIL(&pgl, pg, pageq); } uvm_pglistfree(&pgl); }
1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 /* $OpenBSD: wsdisplay.c,v 1.152 2023/01/10 16:33:18 tobhe Exp $ */ /* $NetBSD: wsdisplay.c,v 1.82 2005/02/27 00:27:52 perry Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Christopher G. Demetriou * for the NetBSD Project. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/conf.h> #include <sys/device.h> #include <sys/ioctl.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/syslog.h> #include <sys/systm.h> #include <sys/task.h> #include <sys/tty.h> #include <sys/signalvar.h> #include <sys/errno.h> #include <sys/fcntl.h> #include <sys/vnode.h> #include <sys/timeout.h> #include <dev/wscons/wscons_features.h> #include <dev/wscons/wsconsio.h> #include <dev/wscons/wsdisplayvar.h> #include <dev/wscons/wsksymvar.h> #include <dev/wscons/wsksymdef.h> #include <dev/wscons/wsemulvar.h> #include <dev/wscons/wscons_callbacks.h> #include <dev/cons.h> #include "wsdisplay.h" #include "wskbd.h" #include "wsmux.h" #if NWSKBD > 0 #include <dev/wscons/wseventvar.h> #include <dev/wscons/wsmuxvar.h> #endif #ifdef DDB #include <ddb/db_output.h> #endif #include "wsmoused.h" struct wsscreen_internal { const struct wsdisplay_emulops *emulops; void *emulcookie; const struct wsscreen_descr *scrdata; const struct wsemul_ops *wsemul; void *wsemulcookie; }; struct wsscreen { struct wsscreen_internal *scr_dconf; struct task scr_emulbell_task; struct tty *scr_tty; int scr_hold_screen; /* hold tty output */ int scr_flags; #define SCR_OPEN 1 /* is it open? */ #define SCR_WAITACTIVE 2 /* someone waiting on activation */ #define SCR_GRAPHICS 4 /* graphics mode, no text (emulation) output */ #define SCR_DUMBFB 8 /* in use as dumb fb (iff SCR_GRAPHICS) */ #ifdef WSDISPLAY_COMPAT_USL const struct wscons_syncops *scr_syncops; void *scr_synccookie; #endif #ifdef WSDISPLAY_COMPAT_RAWKBD int scr_rawkbd; #endif struct wsdisplay_softc *sc; #ifdef HAVE_WSMOUSED_SUPPORT /* mouse console support via wsmoused(8) */ u_int mouse; /* mouse cursor position */ u_int cursor; /* selection cursor position (if different from mouse cursor pos) */ u_int cpy_start; /* position of the copy start mark*/ u_int cpy_end; /* position of the copy end mark */ u_int orig_start; /* position of the original sel. start*/ u_int orig_end; /* position of the original sel. end */ u_int mouse_flags; /* flags, status of the mouse */ #define MOUSE_VISIBLE 0x01 /* flag, the mouse cursor is visible */ #define SEL_EXISTS 0x02 /* flag, a selection exists */ #define SEL_IN_PROGRESS 0x04 /* flag, a selection is in progress */ #define SEL_EXT_AFTER 0x08 /* flag, selection is extended after */ #define BLANK_TO_EOL 0x10 /* flag, there are only blanks characters to eol */ #define SEL_BY_CHAR 0x20 /* flag, select character by character*/ #define SEL_BY_WORD 0x40 /* flag, select word by word */ #define SEL_BY_LINE 0x80 /* flag, select line by line */ #define IS_MOUSE_VISIBLE(scr) ((scr)->mouse_flags & MOUSE_VISIBLE) #define IS_SEL_EXISTS(scr) ((scr)->mouse_flags & SEL_EXISTS) #define IS_SEL_IN_PROGRESS(scr) ((scr)->mouse_flags & SEL_IN_PROGRESS) #define IS_SEL_EXT_AFTER(scr) ((scr)->mouse_flags & SEL_EXT_AFTER) #define IS_BLANK_TO_EOL(scr) ((scr)->mouse_flags & BLANK_TO_EOL) #define IS_SEL_BY_CHAR(scr) ((scr)->mouse_flags & SEL_BY_CHAR) #define IS_SEL_BY_WORD(scr) ((scr)->mouse_flags & SEL_BY_WORD) #define IS_SEL_BY_LINE(scr) ((scr)->mouse_flags & SEL_BY_LINE) #endif /* HAVE_WSMOUSED_SUPPORT */ }; struct wsscreen *wsscreen_attach(struct wsdisplay_softc *, int, const char *, const struct wsscreen_descr *, void *, int, int, uint32_t); void wsscreen_detach(struct wsscreen *); int wsdisplay_addscreen(struct wsdisplay_softc *, int, const char *, const char *); int wsdisplay_getscreen(struct wsdisplay_softc *, struct wsdisplay_addscreendata *); void wsdisplay_resume_device(struct device *); void wsdisplay_suspend_device(struct device *); void wsdisplay_addscreen_print(struct wsdisplay_softc *, int, int); void wsdisplay_closescreen(struct wsdisplay_softc *, struct wsscreen *); int wsdisplay_delscreen(struct wsdisplay_softc *, int, int); int wsdisplay_driver_ioctl(struct wsdisplay_softc *, u_long, caddr_t, int, struct proc *); void wsdisplay_burner_setup(struct wsdisplay_softc *, struct wsscreen *); void wsdisplay_burner(void *v); struct wsdisplay_softc { struct device sc_dv; const struct wsdisplay_accessops *sc_accessops; void *sc_accesscookie; const struct wsscreen_list *sc_scrdata; struct wsscreen *sc_scr[WSDISPLAY_MAXSCREEN]; int sc_focusidx; /* available only if sc_focus isn't null */ struct wsscreen *sc_focus; struct taskq *sc_taskq; #ifdef HAVE_BURNER_SUPPORT struct timeout sc_burner; int sc_burnoutintvl; /* delay before blanking (ms) */ int sc_burninintvl; /* delay before unblanking (ms) */ int sc_burnout; /* current sc_burner delay (ms) */ int sc_burnman; /* nonzero if screen blanked */ int sc_burnflags; #endif int sc_isconsole; int sc_flags; #define SC_SWITCHPENDING 0x01 #define SC_PASTE_AVAIL 0x02 int sc_screenwanted, sc_oldscreen; /* valid with SC_SWITCHPENDING */ int sc_resumescreen; /* if set, can't switch until resume. */ #if NWSKBD > 0 struct wsevsrc *sc_input; #ifdef WSDISPLAY_COMPAT_RAWKBD int sc_rawkbd; #endif #endif /* NWSKBD > 0 */ #ifdef HAVE_WSMOUSED_SUPPORT char *sc_copybuffer; u_int sc_copybuffer_size; #endif }; extern struct cfdriver wsdisplay_cd; /* Autoconfiguration definitions. */ int wsdisplay_emul_match(struct device *, void *, void *); void wsdisplay_emul_attach(struct device *, struct device *, void *); int wsdisplay_emul_detach(struct device *, int); int wsdisplay_activate(struct device *, int); void wsdisplay_emulbell_task(void *); struct cfdriver wsdisplay_cd = { NULL, "wsdisplay", DV_TTY }; const struct cfattach wsdisplay_emul_ca = { sizeof(struct wsdisplay_softc), wsdisplay_emul_match, wsdisplay_emul_attach, wsdisplay_emul_detach, wsdisplay_activate }; void wsdisplaystart(struct tty *); int wsdisplayparam(struct tty *, struct termios *); /* Internal macros, functions, and variables. */ #define WSDISPLAYUNIT(dev) (minor(dev) >> 8) #define WSDISPLAYSCREEN(dev) (minor(dev) & 0xff) #define ISWSDISPLAYCTL(dev) (WSDISPLAYSCREEN(dev) == 255) #define WSDISPLAYMINOR(unit, screen) (((unit) << 8) | (screen)) #define WSSCREEN_HAS_TTY(scr) ((scr)->scr_tty != NULL) void wsdisplay_common_attach(struct wsdisplay_softc *sc, int console, int mux, const struct wsscreen_list *, const struct wsdisplay_accessops *accessops, void *accesscookie, u_int defaultscreens); int wsdisplay_common_detach(struct wsdisplay_softc *, int); void wsdisplay_kbdholdscr(struct wsscreen *, int); #ifdef WSDISPLAY_COMPAT_RAWKBD int wsdisplay_update_rawkbd(struct wsdisplay_softc *, struct wsscreen *); #endif int wsdisplay_console_initted; struct wsdisplay_softc *wsdisplay_console_device; struct wsscreen_internal wsdisplay_console_conf; int wsdisplay_getc_dummy(dev_t); void wsdisplay_pollc(dev_t, int); int wsdisplay_cons_pollmode; void (*wsdisplay_cons_kbd_pollc)(dev_t, int); struct consdev wsdisplay_cons = { NULL, NULL, wsdisplay_getc_dummy, wsdisplay_cnputc, wsdisplay_pollc, NULL, NODEV, CN_LOWPRI }; /* * Function pointers for wsconsctl parameter handling. * These are used for firmware-provided display brightness control. */ int (*ws_get_param)(struct wsdisplay_param *); int (*ws_set_param)(struct wsdisplay_param *); #ifndef WSDISPLAY_DEFAULTSCREENS #define WSDISPLAY_DEFAULTSCREENS 1 #endif int wsdisplay_defaultscreens = WSDISPLAY_DEFAULTSCREENS; int wsdisplay_switch1(void *, int, int); int wsdisplay_switch2(void *, int, int); int wsdisplay_switch3(void *, int, int); int wsdisplay_clearonclose; struct wsscreen * wsscreen_attach(struct wsdisplay_softc *sc, int console, const char *emul, const struct wsscreen_descr *type, void *cookie, int ccol, int crow, uint32_t defattr) { struct wsscreen_internal *dconf; struct wsscreen *scr; scr = malloc(sizeof(*scr), M_DEVBUF, M_ZERO | M_NOWAIT); if (!scr) return (NULL); if (console) { dconf = &wsdisplay_console_conf; /* * Tell the emulation about the callback argument. * The other stuff is already there. */ (void)(*dconf->wsemul->attach)(1, 0, 0, 0, 0, scr, 0); } else { /* not console */ dconf = malloc(sizeof(*dconf), M_DEVBUF, M_NOWAIT); if (dconf == NULL) goto fail; dconf->emulops = type->textops; dconf->emulcookie = cookie; if (dconf->emulops == NULL || (dconf->wsemul = wsemul_pick(emul)) == NULL) goto fail; dconf->wsemulcookie = (*dconf->wsemul->attach)(0, type, cookie, ccol, crow, scr, defattr); if (dconf->wsemulcookie == NULL) goto fail; dconf->scrdata = type; } task_set(&scr->scr_emulbell_task, wsdisplay_emulbell_task, scr); scr->scr_dconf = dconf; scr->scr_tty = ttymalloc(0); scr->sc = sc; return (scr); fail: if (dconf != NULL) free(dconf, M_DEVBUF, sizeof(*dconf)); free(scr, M_DEVBUF, sizeof(*scr)); return (NULL); } void wsscreen_detach(struct wsscreen *scr) { int ccol, crow; /* XXX */ if (WSSCREEN_HAS_TTY(scr)) { timeout_del(&scr->scr_tty->t_rstrt_to); ttyfree(scr->scr_tty); } (*scr->scr_dconf->wsemul->detach)(scr->scr_dconf->wsemulcookie, &ccol, &crow); taskq_del_barrier(scr->sc->sc_taskq, &scr->scr_emulbell_task); free(scr->scr_dconf, M_DEVBUF, sizeof(*scr->scr_dconf)); free(scr, M_DEVBUF, sizeof(*scr)); } const struct wsscreen_descr * wsdisplay_screentype_pick(const struct wsscreen_list *scrdata, const char *name) { int i; const struct wsscreen_descr *scr; KASSERT(scrdata->nscreens > 0); if (name == NULL || *name == '\0') return (scrdata->screens[0]); for (i = 0; i < scrdata->nscreens; i++) { scr = scrdata->screens[i]; if (!strncmp(name, scr->name, WSSCREEN_NAME_SIZE)) return (scr); } return (0); } /* * print info about attached screen */ void wsdisplay_addscreen_print(struct wsdisplay_softc *sc, int idx, int count) { printf("%s: screen %d", sc->sc_dv.dv_xname, idx); if (count > 1) printf("-%d", idx + (count-1)); printf(" added (%s, %s emulation)\n", sc->sc_scr[idx]->scr_dconf->scrdata->name, sc->sc_scr[idx]->scr_dconf->wsemul->name); } int wsdisplay_addscreen(struct wsdisplay_softc *sc, int idx, const char *screentype, const char *emul) { const struct wsscreen_descr *scrdesc; int error; void *cookie; int ccol, crow; uint32_t defattr; struct wsscreen *scr; int s; if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN) return (EINVAL); if (sc->sc_scr[idx] != NULL) return (EBUSY); scrdesc = wsdisplay_screentype_pick(sc->sc_scrdata, screentype); if (!scrdesc) return (ENXIO); error = (*sc->sc_accessops->alloc_screen)(sc->sc_accesscookie, scrdesc, &cookie, &ccol, &crow, &defattr); if (error) return (error); scr = wsscreen_attach(sc, 0, emul, scrdesc, cookie, ccol, crow, defattr); if (scr == NULL) { (*sc->sc_accessops->free_screen)(sc->sc_accesscookie, cookie); return (ENXIO); } sc->sc_scr[idx] = scr; /* if no screen has focus yet, activate the first we get */ s = spltty(); if (!sc->sc_focus) { (*sc->sc_accessops->show_screen)(sc->sc_accesscookie, scr->scr_dconf->emulcookie, 0, 0, 0); sc->sc_focusidx = idx; sc->sc_focus = scr; } splx(s); #ifdef HAVE_WSMOUSED_SUPPORT allocate_copybuffer(sc); /* enlarge the copy buffer if necessary */ #endif return (0); } int wsdisplay_getscreen(struct wsdisplay_softc *sc, struct wsdisplay_addscreendata *sd) { struct wsscreen *scr; if (sd->idx < 0 && sc->sc_focus) sd->idx = sc->sc_focusidx; if (sd->idx < 0 || sd->idx >= WSDISPLAY_MAXSCREEN) return (EINVAL); scr = sc->sc_scr[sd->idx]; if (scr == NULL) return (ENXIO); strlcpy(sd->screentype, scr->scr_dconf->scrdata->name, WSSCREEN_NAME_SIZE); strlcpy(sd->emul, scr->scr_dconf->wsemul->name, WSEMUL_NAME_SIZE); return (0); } void wsdisplay_closescreen(struct wsdisplay_softc *sc, struct wsscreen *scr) { int maj, mn, idx; /* hangup */ if (WSSCREEN_HAS_TTY(scr)) { struct tty *tp = scr->scr_tty; (*linesw[tp->t_line].l_modem)(tp, 0); } /* locate the major number */ for (maj = 0; maj < nchrdev; maj++) if (cdevsw[maj].d_open == wsdisplayopen) break; /* locate the screen index */ for (idx = 0; idx < WSDISPLAY_MAXSCREEN; idx++) if (scr == sc->sc_scr[idx]) break; #ifdef DIAGNOSTIC if (idx == WSDISPLAY_MAXSCREEN) panic("wsdisplay_forceclose: bad screen"); #endif /* nuke the vnodes */ mn = WSDISPLAYMINOR(sc->sc_dv.dv_unit, idx); vdevgone(maj, mn, mn, VCHR); } int wsdisplay_delscreen(struct wsdisplay_softc *sc, int idx, int flags) { struct wsscreen *scr; int s; void *cookie; if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN) return (EINVAL); if ((scr = sc->sc_scr[idx]) == NULL) return (ENXIO); if (scr->scr_dconf == &wsdisplay_console_conf || #ifdef WSDISPLAY_COMPAT_USL scr->scr_syncops || #endif ((scr->scr_flags & SCR_OPEN) && !(flags & WSDISPLAY_DELSCR_FORCE))) return (EBUSY); wsdisplay_closescreen(sc, scr); /* * delete pointers, so neither device entries * nor keyboard input can reference it anymore */ s = spltty(); if (sc->sc_focus == scr) { sc->sc_focus = NULL; #ifdef WSDISPLAY_COMPAT_RAWKBD wsdisplay_update_rawkbd(sc, 0); #endif } sc->sc_scr[idx] = NULL; splx(s); /* * Wake up processes waiting for the screen to * be activated. Sleepers must check whether * the screen still exists. */ if (scr->scr_flags & SCR_WAITACTIVE) wakeup(scr); /* save a reference to the graphics screen */ cookie = scr->scr_dconf->emulcookie; wsscreen_detach(scr); (*sc->sc_accessops->free_screen)(sc->sc_accesscookie, cookie); if ((flags & WSDISPLAY_DELSCR_QUIET) == 0) printf("%s: screen %d deleted\n", sc->sc_dv.dv_xname, idx); return (0); } /* * Autoconfiguration functions. */ int wsdisplay_emul_match(struct device *parent, void *match, void *aux) { struct cfdata *cf = match; struct wsemuldisplaydev_attach_args *ap = aux; if (cf->wsemuldisplaydevcf_console != WSEMULDISPLAYDEVCF_CONSOLE_UNK) { /* * If console-ness of device specified, either match * exactly (at high priority), or fail. */ if (cf->wsemuldisplaydevcf_console != 0 && ap->console != 0) return (10); else return (0); } if (cf->wsemuldisplaydevcf_primary != WSEMULDISPLAYDEVCF_PRIMARY_UNK) { /* * If primary-ness of device specified, either match * exactly (at high priority), or fail. */ if (cf->wsemuldisplaydevcf_primary != 0 && ap->primary != 0) return (10); else return (0); } /* If console-ness and primary-ness unspecified, it wins. */ return (1); } void wsdisplay_emul_attach(struct device *parent, struct device *self, void *aux) { struct wsdisplay_softc *sc = (struct wsdisplay_softc *)self; struct wsemuldisplaydev_attach_args *ap = aux; wsdisplay_common_attach(sc, ap->console, sc->sc_dv.dv_cfdata->wsemuldisplaydevcf_mux, ap->scrdata, ap->accessops, ap->accesscookie, ap->defaultscreens); if (ap->console && cn_tab == &wsdisplay_cons) { int maj; /* locate the major number */ for (maj = 0; maj < nchrdev; maj++) if (cdevsw[maj].d_open == wsdisplayopen) break; cn_tab->cn_dev = makedev(maj, WSDISPLAYMINOR(self->dv_unit, 0)); } } /* * Detach a display. */ int wsdisplay_emul_detach(struct device *self, int flags) { struct wsdisplay_softc *sc = (struct wsdisplay_softc *)self; return (wsdisplay_common_detach(sc, flags)); } int wsdisplay_activate(struct device *self, int act) { int ret = 0; switch (act) { case DVACT_POWERDOWN: wsdisplay_switchtoconsole(); break; } return (ret); } int wsdisplay_common_detach(struct wsdisplay_softc *sc, int flags) { int i; int rc; /* We don't support detaching the console display yet. */ if (sc->sc_isconsole) return (EBUSY); /* Delete all screens managed by this display */ for (i = 0; i < WSDISPLAY_MAXSCREEN; i++) if (sc->sc_scr[i] != NULL) { if ((rc = wsdisplay_delscreen(sc, i, WSDISPLAY_DELSCR_QUIET | (flags & DETACH_FORCE ? WSDISPLAY_DELSCR_FORCE : 0))) != 0) return (rc); } #ifdef HAVE_BURNER_SUPPORT timeout_del(&sc->sc_burner); #endif #if NWSKBD > 0 if (sc->sc_input != NULL) { #if NWSMUX > 0 /* * If we are the display of the mux we are attached to, * disconnect all input devices from us. */ if (sc->sc_input->me_dispdv == &sc->sc_dv) { if ((rc = wsmux_set_display((struct wsmux_softc *) sc->sc_input, NULL)) != 0) return (rc); } /* * XXX * If we created a standalone mux (dmux), we should destroy it * there, but there is currently no support for this in wsmux. */ #else if ((rc = wskbd_set_display((struct device *)sc->sc_input, NULL)) != 0) return (rc); #endif } #endif taskq_destroy(sc->sc_taskq); return (0); } /* Print function (for parent devices). */ int wsemuldisplaydevprint(void *aux, const char *pnp) { #if 0 /* -Wunused */ struct wsemuldisplaydev_attach_args *ap = aux; #endif if (pnp) printf("wsdisplay at %s", pnp); #if 0 /* don't bother; it's ugly */ printf(" console %d", ap->console); #endif return (UNCONF); } /* Submatch function (for parent devices). */ int wsemuldisplaydevsubmatch(struct device *parent, void *match, void *aux) { extern struct cfdriver wsdisplay_cd; struct cfdata *cf = match; /* only allow wsdisplay to attach */ if (cf->cf_driver == &wsdisplay_cd) return ((*cf->cf_attach->ca_match)(parent, match, aux)); return (0); } void wsdisplay_common_attach(struct wsdisplay_softc *sc, int console, int kbdmux, const struct wsscreen_list *scrdata, const struct wsdisplay_accessops *accessops, void *accesscookie, u_int defaultscreens) { int i, start = 0; #if NWSKBD > 0 struct wsevsrc *kme; #if NWSMUX > 0 struct wsmux_softc *mux; if (kbdmux >= 0) mux = wsmux_getmux(kbdmux); else mux = wsmux_create("dmux", sc->sc_dv.dv_unit); /* XXX panic()ing isn't nice, but attach cannot fail */ if (mux == NULL) panic("wsdisplay_common_attach: no memory"); sc->sc_input = &mux->sc_base; if (kbdmux >= 0) printf(" mux %d", kbdmux); #else #if 0 /* not worth keeping, especially since the default value is not -1... */ if (kbdmux >= 0) printf(" (mux ignored)"); #endif #endif /* NWSMUX > 0 */ #endif /* NWSKBD > 0 */ sc->sc_isconsole = console; sc->sc_resumescreen = WSDISPLAY_NULLSCREEN; sc->sc_taskq = taskq_create(sc->sc_dv.dv_xname, 1, IPL_TTY, 0); if (console) { KASSERT(wsdisplay_console_initted); KASSERT(wsdisplay_console_device == NULL); sc->sc_scr[0] = wsscreen_attach(sc, 1, 0, 0, 0, 0, 0, 0); if (sc->sc_scr[0] == NULL) return; wsdisplay_console_device = sc; printf(": console (%s, %s emulation)", wsdisplay_console_conf.scrdata->name, wsdisplay_console_conf.wsemul->name); #if NWSKBD > 0 kme = wskbd_set_console_display(&sc->sc_dv, sc->sc_input); if (kme != NULL) printf(", using %s", kme->me_dv.dv_xname); #if NWSMUX == 0 sc->sc_input = kme; #endif #endif sc->sc_focusidx = 0; sc->sc_focus = sc->sc_scr[0]; start = 1; } printf("\n"); #if NWSKBD > 0 && NWSMUX > 0 /* * If this mux did not have a display device yet, volunteer for * the job. */ if (mux->sc_displaydv == NULL) wsmux_set_display(mux, &sc->sc_dv); #endif sc->sc_accessops = accessops; sc->sc_accesscookie = accesscookie; sc->sc_scrdata = scrdata; /* * Set up a number of virtual screens if wanted. The * WSDISPLAYIO_ADDSCREEN ioctl is more flexible, so this code * is for special cases like installation kernels, as well as * sane multihead defaults. */ if (defaultscreens == 0) defaultscreens = wsdisplay_defaultscreens; for (i = start; i < defaultscreens; i++) { if (wsdisplay_addscreen(sc, i, 0, 0)) break; } if (i > start) wsdisplay_addscreen_print(sc, start, i-start); #ifdef HAVE_BURNER_SUPPORT sc->sc_burnoutintvl = WSDISPLAY_DEFBURNOUT_MSEC; sc->sc_burninintvl = WSDISPLAY_DEFBURNIN_MSEC; sc->sc_burnflags = WSDISPLAY_BURN_OUTPUT | WSDISPLAY_BURN_KBD | WSDISPLAY_BURN_MOUSE; timeout_set(&sc->sc_burner, wsdisplay_burner, sc); sc->sc_burnout = sc->sc_burnoutintvl; wsdisplay_burn(sc, sc->sc_burnflags); #endif #if NWSKBD > 0 && NWSMUX == 0 if (console == 0) { /* * In the non-wsmux world, always connect wskbd0 and wsdisplay0 * together. */ extern struct cfdriver wskbd_cd; if (wskbd_cd.cd_ndevs != 0 && sc->sc_dv.dv_unit == 0) { if (wsdisplay_set_kbd(&sc->sc_dv, (struct wsevsrc *)wskbd_cd.cd_devs[0]) == 0) wskbd_set_display(wskbd_cd.cd_devs[0], &sc->sc_dv); } } #endif } void wsdisplay_cnattach(const struct wsscreen_descr *type, void *cookie, int ccol, int crow, uint32_t defattr) { const struct wsemul_ops *wsemul; const struct wsdisplay_emulops *emulops; KASSERT(type->nrows > 0); KASSERT(type->ncols > 0); KASSERT(crow < type->nrows); KASSERT(ccol < type->ncols); wsdisplay_console_conf.emulops = emulops = type->textops; wsdisplay_console_conf.emulcookie = cookie; wsdisplay_console_conf.scrdata = type; #ifdef WSEMUL_DUMB /* * If the emulops structure is crippled, force a dumb emulation. */ if (emulops->cursor == NULL || emulops->copycols == NULL || emulops->copyrows == NULL || emulops->erasecols == NULL || emulops->eraserows == NULL) wsemul = wsemul_pick("dumb"); else #endif wsemul = wsemul_pick(""); wsdisplay_console_conf.wsemul = wsemul; wsdisplay_console_conf.wsemulcookie = (*wsemul->cnattach)(type, cookie, ccol, crow, defattr); if (!wsdisplay_console_initted) cn_tab = &wsdisplay_cons; wsdisplay_console_initted = 1; #ifdef DDB db_resize(type->ncols, type->nrows); #endif } /* * Tty and cdevsw functions. */ int wsdisplayopen(dev_t dev, int flag, int mode, struct proc *p) { struct wsdisplay_softc *sc; struct tty *tp; int unit, newopen, error; struct wsscreen *scr; unit = WSDISPLAYUNIT(dev); if (unit >= wsdisplay_cd.cd_ndevs || /* make sure it was attached */ (sc = wsdisplay_cd.cd_devs[unit]) == NULL) return (ENXIO); if (ISWSDISPLAYCTL(dev)) return (0); if (WSDISPLAYSCREEN(dev) >= WSDISPLAY_MAXSCREEN) return (ENXIO); if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) return (ENXIO); if (WSSCREEN_HAS_TTY(scr)) { tp = scr->scr_tty; tp->t_oproc = wsdisplaystart; tp->t_param = wsdisplayparam; tp->t_dev = dev; newopen = (tp->t_state & TS_ISOPEN) == 0; if (newopen) { ttychars(tp); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_cflag = TTYDEF_CFLAG; tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; wsdisplayparam(tp, &tp->t_termios); ttsetwater(tp); } else if ((tp->t_state & TS_XCLUDE) != 0 && suser(p) != 0) return (EBUSY); tp->t_state |= TS_CARR_ON; error = ((*linesw[tp->t_line].l_open)(dev, tp, p)); if (error) return (error); if (newopen) { /* set window sizes as appropriate, and reset the emulation */ tp->t_winsize.ws_row = scr->scr_dconf->scrdata->nrows; tp->t_winsize.ws_col = scr->scr_dconf->scrdata->ncols; } } scr->scr_flags |= SCR_OPEN; return (0); } int wsdisplayclose(dev_t dev, int flag, int mode, struct proc *p) { struct wsdisplay_softc *sc; struct tty *tp; int unit; struct wsscreen *scr; unit = WSDISPLAYUNIT(dev); sc = wsdisplay_cd.cd_devs[unit]; if (ISWSDISPLAYCTL(dev)) return (0); if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) return (ENXIO); if (WSSCREEN_HAS_TTY(scr)) { if (scr->scr_hold_screen) { int s; /* XXX RESET KEYBOARD LEDS, etc. */ s = spltty(); /* avoid conflict with keyboard */ wsdisplay_kbdholdscr(scr, 0); splx(s); } tp = scr->scr_tty; (*linesw[tp->t_line].l_close)(tp, flag, p); ttyclose(tp); } #ifdef WSDISPLAY_COMPAT_USL if (scr->scr_syncops) (*scr->scr_syncops->destroy)(scr->scr_synccookie); #endif scr->scr_flags &= ~SCR_GRAPHICS; (*scr->scr_dconf->wsemul->reset)(scr->scr_dconf->wsemulcookie, WSEMUL_RESET); if (wsdisplay_clearonclose) (*scr->scr_dconf->wsemul->reset) (scr->scr_dconf->wsemulcookie, WSEMUL_CLEARSCREEN); #ifdef WSDISPLAY_COMPAT_RAWKBD if (scr->scr_rawkbd) { int kbmode = WSKBD_TRANSLATED; (void) wsdisplay_internal_ioctl(sc, scr, WSKBDIO_SETMODE, (caddr_t)&kbmode, FWRITE, p); } #endif scr->scr_flags &= ~SCR_OPEN; #ifdef HAVE_WSMOUSED_SUPPORT /* remove the selection at logout */ if (sc->sc_copybuffer != NULL) explicit_bzero(sc->sc_copybuffer, sc->sc_copybuffer_size); CLR(sc->sc_flags, SC_PASTE_AVAIL); #endif return (0); } int wsdisplayread(dev_t dev, struct uio *uio, int flag) { struct wsdisplay_softc *sc; struct tty *tp; int unit; struct wsscreen *scr; unit = WSDISPLAYUNIT(dev); sc = wsdisplay_cd.cd_devs[unit]; if (ISWSDISPLAYCTL(dev)) return (0); if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) return (ENXIO); if (!WSSCREEN_HAS_TTY(scr)) return (ENODEV); tp = scr->scr_tty; return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); } int wsdisplaywrite(dev_t dev, struct uio *uio, int flag) { struct wsdisplay_softc *sc; struct tty *tp; int unit; struct wsscreen *scr; unit = WSDISPLAYUNIT(dev); sc = wsdisplay_cd.cd_devs[unit]; if (ISWSDISPLAYCTL(dev)) return (0); if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) return (ENXIO); if (!WSSCREEN_HAS_TTY(scr)) return (ENODEV); tp = scr->scr_tty; return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); } struct tty * wsdisplaytty(dev_t dev) { struct wsdisplay_softc *sc; int unit; struct wsscreen *scr; unit = WSDISPLAYUNIT(dev); sc = wsdisplay_cd.cd_devs[unit]; if (ISWSDISPLAYCTL(dev)) panic("wsdisplaytty() on ctl device"); if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) return (NULL); return (scr->scr_tty); } int wsdisplayioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { struct wsdisplay_softc *sc; struct tty *tp; int unit, error; struct wsscreen *scr; unit = WSDISPLAYUNIT(dev); sc = wsdisplay_cd.cd_devs[unit]; #ifdef WSDISPLAY_COMPAT_USL error = wsdisplay_usl_ioctl1(sc, cmd, data, flag, p); if (error >= 0) return (error); #endif if (ISWSDISPLAYCTL(dev)) { switch (cmd) { case WSDISPLAYIO_GTYPE: case WSDISPLAYIO_GETSCREENTYPE: /* pass to the first screen */ dev = makedev(major(dev), WSDISPLAYMINOR(unit, 0)); break; default: return (wsdisplay_cfg_ioctl(sc, cmd, data, flag, p)); } } if (WSDISPLAYSCREEN(dev) >= WSDISPLAY_MAXSCREEN) return (ENODEV); if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) return (ENXIO); if (WSSCREEN_HAS_TTY(scr)) { tp = scr->scr_tty; /* printf("disc\n"); */ /* do the line discipline ioctls first */ error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); if (error >= 0) return (error); /* printf("tty\n"); */ /* then the tty ioctls */ error = ttioctl(tp, cmd, data, flag, p); if (error >= 0) return (error); } #ifdef WSDISPLAY_COMPAT_USL error = wsdisplay_usl_ioctl2(sc, scr, cmd, data, flag, p); if (error >= 0) return (error); #endif error = wsdisplay_internal_ioctl(sc, scr, cmd, data, flag, p); return (error != -1 ? error : ENOTTY); } int wsdisplay_param(struct device *dev, u_long cmd, struct wsdisplay_param *dp) { struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; return wsdisplay_driver_ioctl(sc, cmd, (caddr_t)dp, 0, NULL); } int wsdisplay_internal_ioctl(struct wsdisplay_softc *sc, struct wsscreen *scr, u_long cmd, caddr_t data, int flag, struct proc *p) { int error; #if NWSKBD > 0 struct wsevsrc *inp; #ifdef WSDISPLAY_COMPAT_RAWKBD switch (cmd) { case WSKBDIO_SETMODE: if ((flag & FWRITE) == 0) return (EACCES); scr->scr_rawkbd = (*(int *)data == WSKBD_RAW); return (wsdisplay_update_rawkbd(sc, scr)); case WSKBDIO_GETMODE: *(int *)data = (scr->scr_rawkbd ? WSKBD_RAW : WSKBD_TRANSLATED); return (0); } #endif inp = sc->sc_input; if (inp != NULL) { error = wsevsrc_display_ioctl(inp, cmd, data, flag, p); if (error >= 0) return (error); } #endif /* NWSKBD > 0 */ switch (cmd) { case WSDISPLAYIO_SMODE: case WSDISPLAYIO_USEFONT: #ifdef HAVE_BURNER_SUPPORT case WSDISPLAYIO_SVIDEO: case WSDISPLAYIO_SBURNER: #endif case WSDISPLAYIO_SETSCREEN: if ((flag & FWRITE) == 0) return (EACCES); } switch (cmd) { case WSDISPLAYIO_GMODE: if (scr->scr_flags & SCR_GRAPHICS) { if (scr->scr_flags & SCR_DUMBFB) *(u_int *)data = WSDISPLAYIO_MODE_DUMBFB; else *(u_int *)data = WSDISPLAYIO_MODE_MAPPED; } else *(u_int *)data = WSDISPLAYIO_MODE_EMUL; return (0); case WSDISPLAYIO_SMODE: #define d (*(int *)data) if (d != WSDISPLAYIO_MODE_EMUL && d != WSDISPLAYIO_MODE_MAPPED && d != WSDISPLAYIO_MODE_DUMBFB) return (EINVAL); scr->scr_flags &= ~SCR_GRAPHICS; if (d == WSDISPLAYIO_MODE_MAPPED || d == WSDISPLAYIO_MODE_DUMBFB) { scr->scr_flags |= SCR_GRAPHICS | ((d == WSDISPLAYIO_MODE_DUMBFB) ? SCR_DUMBFB : 0); /* clear cursor */ (*scr->scr_dconf->wsemul->reset) (scr->scr_dconf->wsemulcookie, WSEMUL_CLEARCURSOR); } #ifdef HAVE_BURNER_SUPPORT wsdisplay_burner_setup(sc, scr); #endif (void)(*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd, data, flag, p); return (0); #undef d case WSDISPLAYIO_USEFONT: #define d ((struct wsdisplay_font *)data) if (!sc->sc_accessops->load_font) return (EINVAL); d->data = NULL; error = (*sc->sc_accessops->load_font)(sc->sc_accesscookie, scr->scr_dconf->emulcookie, d); if (!error) (*scr->scr_dconf->wsemul->reset) (scr->scr_dconf->wsemulcookie, WSEMUL_SYNCFONT); return (error); #undef d #ifdef HAVE_BURNER_SUPPORT case WSDISPLAYIO_GVIDEO: *(u_int *)data = !sc->sc_burnman; break; case WSDISPLAYIO_SVIDEO: if (*(u_int *)data != WSDISPLAYIO_VIDEO_OFF && *(u_int *)data != WSDISPLAYIO_VIDEO_ON) return (EINVAL); if (sc->sc_accessops->burn_screen == NULL) return (EOPNOTSUPP); (*sc->sc_accessops->burn_screen)(sc->sc_accesscookie, *(u_int *)data, sc->sc_burnflags); sc->sc_burnman = *(u_int *)data == WSDISPLAYIO_VIDEO_OFF; break; case WSDISPLAYIO_GBURNER: #define d ((struct wsdisplay_burner *)data) d->on = sc->sc_burninintvl; d->off = sc->sc_burnoutintvl; d->flags = sc->sc_burnflags; return (0); case WSDISPLAYIO_SBURNER: { struct wsscreen *active; if (d->flags & ~(WSDISPLAY_BURN_VBLANK | WSDISPLAY_BURN_KBD | WSDISPLAY_BURN_MOUSE | WSDISPLAY_BURN_OUTPUT)) return EINVAL; error = 0; sc->sc_burnflags = d->flags; /* disable timeout if necessary */ if (d->off==0 || (sc->sc_burnflags & (WSDISPLAY_BURN_OUTPUT | WSDISPLAY_BURN_KBD | WSDISPLAY_BURN_MOUSE)) == 0) { if (sc->sc_burnout) timeout_del(&sc->sc_burner); } active = sc->sc_focus; if (active == NULL) active = scr; if (d->on) { sc->sc_burninintvl = d->on; if (sc->sc_burnman) { sc->sc_burnout = sc->sc_burninintvl; /* reinit timeout if changed */ if ((active->scr_flags & SCR_GRAPHICS) == 0) wsdisplay_burn(sc, sc->sc_burnflags); } } sc->sc_burnoutintvl = d->off; if (!sc->sc_burnman) { sc->sc_burnout = sc->sc_burnoutintvl; /* reinit timeout if changed */ if ((active->scr_flags & SCR_GRAPHICS) == 0) wsdisplay_burn(sc, sc->sc_burnflags); } return (error); } #undef d #endif /* HAVE_BURNER_SUPPORT */ case WSDISPLAYIO_GETSCREEN: return (wsdisplay_getscreen(sc, (struct wsdisplay_addscreendata *)data)); case WSDISPLAYIO_SETSCREEN: return (wsdisplay_switch((void *)sc, *(int *)data, 1)); case WSDISPLAYIO_GETSCREENTYPE: #define d ((struct wsdisplay_screentype *)data) if (d->idx < 0 || d->idx >= sc->sc_scrdata->nscreens) return(EINVAL); d->nidx = sc->sc_scrdata->nscreens; strlcpy(d->name, sc->sc_scrdata->screens[d->idx]->name, WSSCREEN_NAME_SIZE); d->ncols = sc->sc_scrdata->screens[d->idx]->ncols; d->nrows = sc->sc_scrdata->screens[d->idx]->nrows; d->fontwidth = sc->sc_scrdata->screens[d->idx]->fontwidth; d->fontheight = sc->sc_scrdata->screens[d->idx]->fontheight; return (0); #undef d case WSDISPLAYIO_GETEMULTYPE: #define d ((struct wsdisplay_emultype *)data) if (wsemul_getname(d->idx) == NULL) return(EINVAL); strlcpy(d->name, wsemul_getname(d->idx), WSEMUL_NAME_SIZE); return (0); #undef d } /* check ioctls for display */ return wsdisplay_driver_ioctl(sc, cmd, data, flag, p); } int wsdisplay_driver_ioctl(struct wsdisplay_softc *sc, u_long cmd, caddr_t data, int flag, struct proc *p) { int error; #if defined(OpenBSD7_1) || defined(OpenBSD7_2) || defined(OpenBSD7_3) if (cmd == WSDISPLAYIO_OGINFO) { struct wsdisplay_ofbinfo *oinfo = (struct wsdisplay_ofbinfo *)data; struct wsdisplay_fbinfo info; error = (*sc->sc_accessops->ioctl)(sc->sc_accesscookie, WSDISPLAYIO_GINFO, (caddr_t)&info, flag, p); if (error) return error; oinfo->height = info.height; oinfo->width = info.width; oinfo->depth = info.depth; oinfo->cmsize = info.cmsize; return (0); } #endif error = ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd, data, flag, p)); /* Do not report parameters with empty ranges to userland. */ if (error == 0 && cmd == WSDISPLAYIO_GETPARAM) { struct wsdisplay_param *dp = (struct wsdisplay_param *)data; switch (dp->param) { case WSDISPLAYIO_PARAM_BACKLIGHT: case WSDISPLAYIO_PARAM_BRIGHTNESS: case WSDISPLAYIO_PARAM_CONTRAST: if (dp->min == dp->max) error = ENOTTY; break; } } return error; } int wsdisplay_cfg_ioctl(struct wsdisplay_softc *sc, u_long cmd, caddr_t data, int flag, struct proc *p) { int error; void *buf; size_t fontsz; #if NWSKBD > 0 struct wsevsrc *inp; #endif switch (cmd) { #ifdef HAVE_WSMOUSED_SUPPORT case WSDISPLAYIO_WSMOUSED: error = wsmoused(sc, data, flag, p); return (error); #endif case WSDISPLAYIO_ADDSCREEN: #define d ((struct wsdisplay_addscreendata *)data) if ((error = wsdisplay_addscreen(sc, d->idx, d->screentype, d->emul)) == 0) wsdisplay_addscreen_print(sc, d->idx, 0); return (error); #undef d case WSDISPLAYIO_DELSCREEN: #define d ((struct wsdisplay_delscreendata *)data) return (wsdisplay_delscreen(sc, d->idx, d->flags)); #undef d case WSDISPLAYIO_GETSCREEN: return (wsdisplay_getscreen(sc, (struct wsdisplay_addscreendata *)data)); case WSDISPLAYIO_SETSCREEN: return (wsdisplay_switch((void *)sc, *(int *)data, 1)); case WSDISPLAYIO_LDFONT: #define d ((struct wsdisplay_font *)data) if (!sc->sc_accessops->load_font) return (EINVAL); if (d->fontheight > 64 || d->stride > 8) /* 64x64 pixels */ return (EINVAL); if (d->numchars > 65536) /* unicode plane */ return (EINVAL); fontsz = d->fontheight * d->stride * d->numchars; if (fontsz > WSDISPLAY_MAXFONTSZ) return (EINVAL); buf = malloc(fontsz, M_DEVBUF, M_WAITOK); error = copyin(d->data, buf, fontsz); if (error) { free(buf, M_DEVBUF, fontsz); return (error); } d->data = buf; error = (*sc->sc_accessops->load_font)(sc->sc_accesscookie, 0, d); if (error) free(buf, M_DEVBUF, fontsz); return (error); case WSDISPLAYIO_LSFONT: if (!sc->sc_accessops->list_font) return (EINVAL); error = (*sc->sc_accessops->list_font)(sc->sc_accesscookie, d); return (error); case WSDISPLAYIO_DELFONT: return (EINVAL); #undef d #if NWSKBD > 0 case WSMUXIO_ADD_DEVICE: #define d ((struct wsmux_device *)data) if (d->idx == -1 && d->type == WSMUX_KBD) d->idx = wskbd_pickfree(); #undef d /* FALLTHROUGH */ case WSMUXIO_INJECTEVENT: case WSMUXIO_REMOVE_DEVICE: case WSMUXIO_LIST_DEVICES: inp = sc->sc_input; if (inp == NULL) return (ENXIO); return (wsevsrc_ioctl(inp, cmd, data, flag,p)); #endif /* NWSKBD > 0 */ } return (EINVAL); } paddr_t wsdisplaymmap(dev_t dev, off_t offset, int prot) { struct wsdisplay_softc *sc = wsdisplay_cd.cd_devs[WSDISPLAYUNIT(dev)]; struct wsscreen *scr; if (ISWSDISPLAYCTL(dev)) return (-1); if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) return (-1); if (!(scr->scr_flags & SCR_GRAPHICS)) return (-1); /* pass mmap to display */ return ((*sc->sc_accessops->mmap)(sc->sc_accesscookie, offset, prot)); } int wsdisplaykqfilter(dev_t dev, struct knote *kn) { struct wsdisplay_softc *sc = wsdisplay_cd.cd_devs[WSDISPLAYUNIT(dev)]; struct wsscreen *scr; if (ISWSDISPLAYCTL(dev)) return (ENXIO); if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) return (ENXIO); if (!WSSCREEN_HAS_TTY(scr)) return (ENXIO); return (ttkqfilter(dev, kn)); } void wsdisplaystart(struct tty *tp) { struct wsdisplay_softc *sc; struct wsscreen *scr; int s, n, done, unit; u_char *buf; unit = WSDISPLAYUNIT(tp->t_dev); if (unit >= wsdisplay_cd.cd_ndevs || (sc = wsdisplay_cd.cd_devs[unit]) == NULL) return; s = spltty(); if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) { splx(s); return; } if (tp->t_outq.c_cc == 0) goto low; if ((scr = sc->sc_scr[WSDISPLAYSCREEN(tp->t_dev)]) == NULL) { splx(s); return; } if (scr->scr_hold_screen) { tp->t_state |= TS_TIMEOUT; splx(s); return; } tp->t_state |= TS_BUSY; splx(s); /* * Drain output from ring buffer. * The output will normally be in one contiguous chunk, but when the * ring wraps, it will be in two pieces.. one at the end of the ring, * the other at the start. For performance, rather than loop here, * we output one chunk, see if there's another one, and if so, output * it too. */ n = ndqb(&tp->t_outq, 0); buf = tp->t_outq.c_cf; if (!(scr->scr_flags & SCR_GRAPHICS)) { #ifdef HAVE_BURNER_SUPPORT wsdisplay_burn(sc, WSDISPLAY_BURN_OUTPUT); #endif #ifdef HAVE_WSMOUSED_SUPPORT if (scr == sc->sc_focus) mouse_remove(scr); #endif done = (*scr->scr_dconf->wsemul->output) (scr->scr_dconf->wsemulcookie, buf, n, 0); } else done = n; ndflush(&tp->t_outq, done); if (done == n) { if ((n = ndqb(&tp->t_outq, 0)) > 0) { buf = tp->t_outq.c_cf; if (!(scr->scr_flags & SCR_GRAPHICS)) { done = (*scr->scr_dconf->wsemul->output) (scr->scr_dconf->wsemulcookie, buf, n, 0); } else done = n; ndflush(&tp->t_outq, done); } } s = spltty(); tp->t_state &= ~TS_BUSY; /* Come back if there's more to do */ if (tp->t_outq.c_cc) { tp->t_state |= TS_TIMEOUT; timeout_add(&tp->t_rstrt_to, (hz > 128) ? (hz / 128) : 1); } low: ttwakeupwr(tp); splx(s); } int wsdisplaystop(struct tty *tp, int flag) { int s; s = spltty(); if (ISSET(tp->t_state, TS_BUSY)) if (!ISSET(tp->t_state, TS_TTSTOP)) SET(tp->t_state, TS_FLUSH); splx(s); return (0); } /* Set line parameters. */ int wsdisplayparam(struct tty *tp, struct termios *t) { tp->t_ispeed = t->c_ispeed; tp->t_ospeed = t->c_ospeed; tp->t_cflag = t->c_cflag; return (0); } /* * Callbacks for the emulation code. */ void wsdisplay_emulbell(void *v) { struct wsscreen *scr = v; if (scr == NULL) /* console, before real attach */ return; if (scr->scr_flags & SCR_GRAPHICS) /* can this happen? */ return; task_add(scr->sc->sc_taskq, &scr->scr_emulbell_task); } void wsdisplay_emulbell_task(void *v) { struct wsscreen *scr = v; (void)wsdisplay_internal_ioctl(scr->sc, scr, WSKBDIO_BELL, NULL, FWRITE, NULL); } #if !defined(WSEMUL_NO_VT100) void wsdisplay_emulinput(void *v, const u_char *data, u_int count) { struct wsscreen *scr = v; struct tty *tp; if (v == NULL) /* console, before real attach */ return; if (scr->scr_flags & SCR_GRAPHICS) /* XXX can't happen */ return; if (!WSSCREEN_HAS_TTY(scr)) return; tp = scr->scr_tty; while (count-- > 0) (*linesw[tp->t_line].l_rint)(*data++, tp); } #endif /* * Calls from the keyboard interface. */ void wsdisplay_kbdinput(struct device *dev, kbd_t layout, keysym_t *ks, int num) { struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; struct wsscreen *scr; const u_char *dp; int count; struct tty *tp; scr = sc->sc_focus; if (!scr || !WSSCREEN_HAS_TTY(scr)) return; tp = scr->scr_tty; for (; num > 0; num--) { count = (*scr->scr_dconf->wsemul->translate) (scr->scr_dconf->wsemulcookie, layout, *ks++, &dp); while (count-- > 0) (*linesw[tp->t_line].l_rint)(*dp++, tp); } } #ifdef WSDISPLAY_COMPAT_RAWKBD void wsdisplay_rawkbdinput(struct device *dev, u_char *buf, int num) { struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; struct wsscreen *scr; struct tty *tp; scr = sc->sc_focus; if (!scr || !WSSCREEN_HAS_TTY(scr)) return; tp = scr->scr_tty; while (num-- > 0) (*linesw[tp->t_line].l_rint)(*buf++, tp); } int wsdisplay_update_rawkbd(struct wsdisplay_softc *sc, struct wsscreen *scr) { #if NWSKBD > 0 int s, raw, data, error; struct wsevsrc *inp; s = spltty(); raw = (scr ? scr->scr_rawkbd : 0); if (scr != sc->sc_focus || sc->sc_rawkbd == raw) { splx(s); return (0); } data = raw ? WSKBD_RAW : WSKBD_TRANSLATED; inp = sc->sc_input; if (inp == NULL) { splx(s); return (ENXIO); } error = wsevsrc_display_ioctl(inp, WSKBDIO_SETMODE, &data, FWRITE, 0); if (!error) sc->sc_rawkbd = raw; splx(s); return (error); #else return (0); #endif } #endif int wsdisplay_switch3(void *arg, int error, int waitok) { struct wsdisplay_softc *sc = arg; int no; struct wsscreen *scr; #ifdef WSDISPLAY_COMPAT_USL if (!ISSET(sc->sc_flags, SC_SWITCHPENDING)) { printf("wsdisplay_switch3: not switching\n"); return (EINVAL); } no = sc->sc_screenwanted; if (no < 0 || no >= WSDISPLAY_MAXSCREEN) panic("wsdisplay_switch3: invalid screen %d", no); scr = sc->sc_scr[no]; if (!scr) { printf("wsdisplay_switch3: screen %d disappeared\n", no); error = ENXIO; } if (error) { /* try to recover, avoid recursion */ if (sc->sc_oldscreen == WSDISPLAY_NULLSCREEN) { printf("wsdisplay_switch3: giving up\n"); sc->sc_focus = NULL; #ifdef WSDISPLAY_COMPAT_RAWKBD wsdisplay_update_rawkbd(sc, 0); #endif CLR(sc->sc_flags, SC_SWITCHPENDING); return (error); } sc->sc_screenwanted = sc->sc_oldscreen; sc->sc_oldscreen = WSDISPLAY_NULLSCREEN; return (wsdisplay_switch1(arg, 0, waitok)); } #else /* * If we do not have syncops support, we come straight from * wsdisplay_switch2 which has already validated our arguments * and did not sleep. */ no = sc->sc_screenwanted; scr = sc->sc_scr[no]; #endif CLR(sc->sc_flags, SC_SWITCHPENDING); #ifdef HAVE_BURNER_SUPPORT if (!error) wsdisplay_burner_setup(sc, scr); #endif if (!error && (scr->scr_flags & SCR_WAITACTIVE)) wakeup(scr); return (error); } int wsdisplay_switch2(void *arg, int error, int waitok) { struct wsdisplay_softc *sc = arg; int no; struct wsscreen *scr; if (!ISSET(sc->sc_flags, SC_SWITCHPENDING)) { printf("wsdisplay_switch2: not switching\n"); return (EINVAL); } no = sc->sc_screenwanted; if (no < 0 || no >= WSDISPLAY_MAXSCREEN) panic("wsdisplay_switch2: invalid screen %d", no); scr = sc->sc_scr[no]; if (!scr) { printf("wsdisplay_switch2: screen %d disappeared\n", no); error = ENXIO; } if (error) { /* try to recover, avoid recursion */ if (sc->sc_oldscreen == WSDISPLAY_NULLSCREEN) { printf("wsdisplay_switch2: giving up\n"); sc->sc_focus = NULL; CLR(sc->sc_flags, SC_SWITCHPENDING); return (error); } sc->sc_screenwanted = sc->sc_oldscreen; sc->sc_oldscreen = WSDISPLAY_NULLSCREEN; return (wsdisplay_switch1(arg, 0, waitok)); } sc->sc_focusidx = no; sc->sc_focus = scr; #ifdef WSDISPLAY_COMPAT_RAWKBD (void) wsdisplay_update_rawkbd(sc, scr); #endif /* keyboard map??? */ #ifdef WSDISPLAY_COMPAT_USL #define wsswitch_cb3 ((void (*)(void *, int, int))wsdisplay_switch3) if (scr->scr_syncops) { error = (*scr->scr_syncops->attach)(scr->scr_synccookie, waitok, sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb3, sc); if (error == EAGAIN) { /* switch will be done asynchronously */ return (0); } } #endif return (wsdisplay_switch3(sc, error, waitok)); } int wsdisplay_switch1(void *arg, int error, int waitok) { struct wsdisplay_softc *sc = arg; int no; struct wsscreen *scr; if (!ISSET(sc->sc_flags, SC_SWITCHPENDING)) { printf("wsdisplay_switch1: not switching\n"); return (EINVAL); } no = sc->sc_screenwanted; if (no == WSDISPLAY_NULLSCREEN) { CLR(sc->sc_flags, SC_SWITCHPENDING); if (!error) { sc->sc_focus = NULL; } wakeup(sc); return (error); } if (no < 0 || no >= WSDISPLAY_MAXSCREEN) panic("wsdisplay_switch1: invalid screen %d", no); scr = sc->sc_scr[no]; if (!scr) { printf("wsdisplay_switch1: screen %d disappeared\n", no); error = ENXIO; } if (error) { CLR(sc->sc_flags, SC_SWITCHPENDING); return (error); } #define wsswitch_cb2 ((void (*)(void *, int, int))wsdisplay_switch2) error = (*sc->sc_accessops->show_screen)(sc->sc_accesscookie, scr->scr_dconf->emulcookie, waitok, sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb2, sc); if (error == EAGAIN) { /* switch will be done asynchronously */ return (0); } return (wsdisplay_switch2(sc, error, waitok)); } int wsdisplay_switch(struct device *dev, int no, int waitok) { struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; int s, res = 0; struct wsscreen *scr; if (no != WSDISPLAY_NULLSCREEN) { if (no < 0 || no >= WSDISPLAY_MAXSCREEN) return (EINVAL); if (sc->sc_scr[no] == NULL) return (ENXIO); } s = spltty(); while (sc->sc_resumescreen != WSDISPLAY_NULLSCREEN && res == 0) res = tsleep_nsec(&sc->sc_resumescreen, PCATCH, "wsrestore", INFSLP); if (res) { splx(s); return (res); } if ((sc->sc_focus && no == sc->sc_focusidx) || (sc->sc_focus == NULL && no == WSDISPLAY_NULLSCREEN)) { splx(s); return (0); } if (ISSET(sc->sc_flags, SC_SWITCHPENDING)) { splx(s); return (EBUSY); } SET(sc->sc_flags, SC_SWITCHPENDING); sc->sc_screenwanted = no; splx(s); scr = sc->sc_focus; if (!scr) { sc->sc_oldscreen = WSDISPLAY_NULLSCREEN; return (wsdisplay_switch1(sc, 0, waitok)); } else sc->sc_oldscreen = sc->sc_focusidx; #ifdef WSDISPLAY_COMPAT_USL #define wsswitch_cb1 ((void (*)(void *, int, int))wsdisplay_switch1) if (scr->scr_syncops) { res = (*scr->scr_syncops->detach)(scr->scr_synccookie, waitok, sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb1, sc); if (res == EAGAIN) { /* switch will be done asynchronously */ return (0); } } else if (scr->scr_flags & SCR_GRAPHICS) { /* no way to save state */ res = EBUSY; } #endif #ifdef HAVE_WSMOUSED_SUPPORT mouse_remove(scr); #endif return (wsdisplay_switch1(sc, res, waitok)); } void wsdisplay_reset(struct device *dev, enum wsdisplay_resetops op) { struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; struct wsscreen *scr; scr = sc->sc_focus; if (!scr) return; switch (op) { case WSDISPLAY_RESETEMUL: (*scr->scr_dconf->wsemul->reset)(scr->scr_dconf->wsemulcookie, WSEMUL_RESET); break; case WSDISPLAY_RESETCLOSE: wsdisplay_closescreen(sc, scr); break; } } #ifdef WSDISPLAY_COMPAT_USL /* * Interface for (external) VT switch / process synchronization code */ int wsscreen_attach_sync(struct wsscreen *scr, const struct wscons_syncops *ops, void *cookie) { if (scr->scr_syncops) { /* * The screen is already claimed. * Check if the owner is still alive. */ if ((*scr->scr_syncops->check)(scr->scr_synccookie)) return (EBUSY); } scr->scr_syncops = ops; scr->scr_synccookie = cookie; return (0); } int wsscreen_detach_sync(struct wsscreen *scr) { if (!scr->scr_syncops) return (EINVAL); scr->scr_syncops = NULL; return (0); } int wsscreen_lookup_sync(struct wsscreen *scr, const struct wscons_syncops *ops, /* used as ID */ void **cookiep) { if (!scr->scr_syncops || ops != scr->scr_syncops) return (EINVAL); *cookiep = scr->scr_synccookie; return (0); } #endif /* * Interface to virtual screen stuff */ int wsdisplay_maxscreenidx(struct wsdisplay_softc *sc) { return (WSDISPLAY_MAXSCREEN - 1); } int wsdisplay_screenstate(struct wsdisplay_softc *sc, int idx) { if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN) return (EINVAL); if (!sc->sc_scr[idx]) return (ENXIO); return ((sc->sc_scr[idx]->scr_flags & SCR_OPEN) ? EBUSY : 0); } int wsdisplay_getactivescreen(struct wsdisplay_softc *sc) { return (sc->sc_focus ? sc->sc_focusidx : WSDISPLAY_NULLSCREEN); } int wsscreen_switchwait(struct wsdisplay_softc *sc, int no) { struct wsscreen *scr; int s, res = 0; if (no == WSDISPLAY_NULLSCREEN) { s = spltty(); while (sc->sc_focus && res == 0) { res = tsleep_nsec(sc, PCATCH, "wswait", INFSLP); } splx(s); return (res); } if (no < 0 || no >= WSDISPLAY_MAXSCREEN) return (ENXIO); scr = sc->sc_scr[no]; if (!scr) return (ENXIO); s = spltty(); if (scr != sc->sc_focus) { scr->scr_flags |= SCR_WAITACTIVE; res = tsleep_nsec(scr, PCATCH, "wswait2", INFSLP); if (scr != sc->sc_scr[no]) res = ENXIO; /* disappeared in the meantime */ else scr->scr_flags &= ~SCR_WAITACTIVE; } splx(s); return (res); } void wsdisplay_kbdholdscr(struct wsscreen *scr, int hold) { if (hold) scr->scr_hold_screen = 1; else { scr->scr_hold_screen = 0; timeout_add(&scr->scr_tty->t_rstrt_to, 0); /* "immediate" */ } } void wsdisplay_kbdholdscreen(struct device *dev, int hold) { struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; struct wsscreen *scr; scr = sc->sc_focus; if (scr != NULL && WSSCREEN_HAS_TTY(scr)) wsdisplay_kbdholdscr(scr, hold); } #if NWSKBD > 0 void wsdisplay_set_console_kbd(struct wsevsrc *src) { if (wsdisplay_console_device == NULL) { src->me_dispdv = NULL; return; } #if NWSMUX > 0 if (wsmux_attach_sc((struct wsmux_softc *) wsdisplay_console_device->sc_input, src)) { src->me_dispdv = NULL; return; } #else wsdisplay_console_device->sc_input = src; #endif src->me_dispdv = &wsdisplay_console_device->sc_dv; } #if NWSMUX == 0 int wsdisplay_set_kbd(struct device *disp, struct wsevsrc *kbd) { struct wsdisplay_softc *sc = (struct wsdisplay_softc *)disp; if (sc->sc_input != NULL) return (EBUSY); sc->sc_input = kbd; return (0); } #endif #endif /* NWSKBD > 0 */ /* * Console interface. */ void wsdisplay_cnputc(dev_t dev, int i) { struct wsscreen_internal *dc; char c = i; if (!wsdisplay_console_initted) return; if (wsdisplay_console_device != NULL && (wsdisplay_console_device->sc_scr[0] != NULL) && (wsdisplay_console_device->sc_scr[0]->scr_flags & SCR_GRAPHICS)) return; dc = &wsdisplay_console_conf; #ifdef HAVE_BURNER_SUPPORT /*wsdisplay_burn(wsdisplay_console_device, WSDISPLAY_BURN_OUTPUT);*/ #endif (void)(*dc->wsemul->output)(dc->wsemulcookie, &c, 1, 1); } int wsdisplay_getc_dummy(dev_t dev) { /* panic? */ return (0); } void wsdisplay_pollc(dev_t dev, int on) { wsdisplay_cons_pollmode = on; /* notify to fb drivers */ if (wsdisplay_console_device != NULL && wsdisplay_console_device->sc_accessops->pollc != NULL) (*wsdisplay_console_device->sc_accessops->pollc) (wsdisplay_console_device->sc_accesscookie, on); /* notify to kbd drivers */ if (wsdisplay_cons_kbd_pollc) (*wsdisplay_cons_kbd_pollc)(dev, on); } void wsdisplay_set_cons_kbd(int (*get)(dev_t), void (*poll)(dev_t, int), void (*bell)(dev_t, u_int, u_int, u_int)) { wsdisplay_cons.cn_getc = get; wsdisplay_cons.cn_bell = bell; wsdisplay_cons_kbd_pollc = poll; } void wsdisplay_unset_cons_kbd(void) { wsdisplay_cons.cn_getc = wsdisplay_getc_dummy; wsdisplay_cons.cn_bell = NULL; wsdisplay_cons_kbd_pollc = NULL; } /* * Switch the console display to its first screen. */ void wsdisplay_switchtoconsole(void) { struct wsdisplay_softc *sc; struct wsscreen *scr; if (wsdisplay_console_device != NULL && cn_tab == &wsdisplay_cons) { sc = wsdisplay_console_device; if ((scr = sc->sc_scr[0]) == NULL) return; (*sc->sc_accessops->show_screen)(sc->sc_accesscookie, scr->scr_dconf->emulcookie, 0, NULL, NULL); } } /* * Switch the console display to its ddb screen, avoiding locking * where we can. */ void wsdisplay_enter_ddb(void) { struct wsdisplay_softc *sc; struct wsscreen *scr; if (wsdisplay_console_device != NULL && cn_tab == &wsdisplay_cons) { sc = wsdisplay_console_device; if ((scr = sc->sc_scr[0]) == NULL) return; if (sc->sc_accessops->enter_ddb) { (*sc->sc_accessops->enter_ddb)(sc->sc_accesscookie, scr->scr_dconf->emulcookie); } else { (*sc->sc_accessops->show_screen)(sc->sc_accesscookie, scr->scr_dconf->emulcookie, 0, NULL, NULL); } } } /* * Deal with the xserver doing driver in userland and thus screwing up suspend * and resume by switching away from it at suspend/resume time. * * these functions must be called from the MD suspend callback, since we may * need to sleep if we have a user (probably an X server) on a vt. therefore * this can't be a config_suspend() hook. */ void wsdisplay_suspend(void) { int i; for (i = 0; i < wsdisplay_cd.cd_ndevs; i++) if (wsdisplay_cd.cd_devs[i] != NULL) wsdisplay_suspend_device(wsdisplay_cd.cd_devs[i]); } void wsdisplay_suspend_device(struct device *dev) { struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; struct wsscreen *scr; int active, idx, ret = 0, s; if ((active = wsdisplay_getactivescreen(sc)) == WSDISPLAY_NULLSCREEN) return; scr = sc->sc_scr[active]; /* * We want to switch out of graphics mode for the suspend */ retry: idx = WSDISPLAY_MAXSCREEN; if (scr->scr_flags & SCR_GRAPHICS) { for (idx = 0; idx < WSDISPLAY_MAXSCREEN; idx++) { if (sc->sc_scr[idx] == NULL || sc->sc_scr[idx] == scr) continue; if ((sc->sc_scr[idx]->scr_flags & SCR_GRAPHICS) == 0) break; } } /* if we don't have anything to switch to, we can't do anything */ if (idx == WSDISPLAY_MAXSCREEN) return; /* * we do a lot of magic here because we need to know that the * switch has completed before we return */ ret = wsdisplay_switch((struct device *)sc, idx, 1); if (ret == EBUSY) { /* XXX sleep on what's going on */ goto retry; } else if (ret) return; s = spltty(); sc->sc_resumescreen = active; /* block other vt switches until resume */ splx(s); /* * This will either return ENXIO (invalid (shouldn't happen) or * wsdisplay disappeared (problem solved)), or EINTR/ERESTART. * Not much we can do about the latter since we can't return to * userland. */ (void)wsscreen_switchwait(sc, idx); } void wsdisplay_resume(void) { int i; for (i = 0; i < wsdisplay_cd.cd_ndevs; i++) if (wsdisplay_cd.cd_devs[i] != NULL) wsdisplay_resume_device(wsdisplay_cd.cd_devs[i]); } void wsdisplay_resume_device(struct device *dev) { struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; int idx, s; if (sc->sc_resumescreen != WSDISPLAY_NULLSCREEN) { s = spltty(); idx = sc->sc_resumescreen; sc->sc_resumescreen = WSDISPLAY_NULLSCREEN; wakeup(&sc->sc_resumescreen); splx(s); (void)wsdisplay_switch((struct device *)sc, idx, 1); } } #ifdef HAVE_SCROLLBACK_SUPPORT void wsscrollback(void *arg, int op) { struct wsdisplay_softc *sc = arg; int lines; if (sc->sc_focus == NULL) return; if (op == WSDISPLAY_SCROLL_RESET) lines = 0; else { lines = sc->sc_focus->scr_dconf->scrdata->nrows - 1; if (op == WSDISPLAY_SCROLL_BACKWARD) lines = -lines; } if (sc->sc_accessops->scrollback) { (*sc->sc_accessops->scrollback)(sc->sc_accesscookie, sc->sc_focus->scr_dconf->emulcookie, lines); } } #endif #ifdef HAVE_BURNER_SUPPORT /* * Update screen burner behaviour after either a screen focus change or * a screen mode change. * This is needed to allow X11 to manage screen blanking without any * interference from the kernel. */ void wsdisplay_burner_setup(struct wsdisplay_softc *sc, struct wsscreen *scr) { if (scr->scr_flags & SCR_GRAPHICS) { /* enable video _immediately_ if it needs to be... */ if (sc->sc_burnman) wsdisplay_burner(sc); /* ...and disable the burner while X is running */ if (sc->sc_burnout) { timeout_del(&sc->sc_burner); sc->sc_burnout = 0; } } else { /* reenable the burner after exiting from X */ if (!sc->sc_burnman) { sc->sc_burnout = sc->sc_burnoutintvl; wsdisplay_burn(sc, sc->sc_burnflags); } } } void wsdisplay_burn(void *v, u_int flags) { struct wsdisplay_softc *sc = v; if ((flags & sc->sc_burnflags & (WSDISPLAY_BURN_OUTPUT | WSDISPLAY_BURN_KBD | WSDISPLAY_BURN_MOUSE)) && sc->sc_accessops->burn_screen) { if (sc->sc_burnout) timeout_add_msec(&sc->sc_burner, sc->sc_burnout); if (sc->sc_burnman) sc->sc_burnout = 0; } } void wsdisplay_burner(void *v) { struct wsdisplay_softc *sc = v; int s; if (sc->sc_accessops->burn_screen) { (*sc->sc_accessops->burn_screen)(sc->sc_accesscookie, sc->sc_burnman, sc->sc_burnflags); s = spltty(); if (sc->sc_burnman) { sc->sc_burnout = sc->sc_burnoutintvl; timeout_add_msec(&sc->sc_burner, sc->sc_burnout); } else sc->sc_burnout = sc->sc_burninintvl; sc->sc_burnman = !sc->sc_burnman; splx(s); } } #endif int wsdisplay_get_param(struct wsdisplay_softc *sc, struct wsdisplay_param *dp) { int error = ENXIO; int i; if (sc != NULL) return wsdisplay_param(&sc->sc_dv, WSDISPLAYIO_GETPARAM, dp); for (i = 0; i < wsdisplay_cd.cd_ndevs; i++) { sc = wsdisplay_cd.cd_devs[i]; if (sc == NULL) continue; error = wsdisplay_param(&sc->sc_dv, WSDISPLAYIO_GETPARAM, dp); if (error == 0) break; } if (error && ws_get_param) error = ws_get_param(dp); return error; } int wsdisplay_set_param(struct wsdisplay_softc *sc, struct wsdisplay_param *dp) { int error = ENXIO; int i; if (sc != NULL) return wsdisplay_param(&sc->sc_dv, WSDISPLAYIO_SETPARAM, dp); for (i = 0; i < wsdisplay_cd.cd_ndevs; i++) { sc = wsdisplay_cd.cd_devs[i]; if (sc == NULL) continue; error = wsdisplay_param(&sc->sc_dv, WSDISPLAYIO_SETPARAM, dp); if (error == 0) break; } if (error && ws_set_param) error = ws_set_param(dp); return error; } void wsdisplay_brightness_step(struct device *dev, int dir) { struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; struct wsdisplay_param dp; int delta, new; dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS; if (wsdisplay_get_param(sc, &dp)) return; /* Use a step size of approximately 5%. */ delta = max(1, ((dp.max - dp.min) * 5) / 100); new = dp.curval; if (dir > 0) { if (delta > dp.max - dp.curval) new = dp.max; else new += delta; } else if (dir < 0) { if (delta > dp.curval - dp.min) new = dp.min; else new -= delta; } if (dp.curval == new) return; dp.curval = new; wsdisplay_set_param(sc, &dp); } void wsdisplay_brightness_zero(struct device *dev) { struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; struct wsdisplay_param dp; dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS; if (wsdisplay_get_param(sc, &dp)) return; dp.curval = dp.min; wsdisplay_set_param(sc, &dp); } void wsdisplay_brightness_cycle(struct device *dev) { struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; struct wsdisplay_param dp; dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS; if (wsdisplay_get_param(sc, &dp)) return; if (dp.curval == dp.max) wsdisplay_brightness_zero(dev); else wsdisplay_brightness_step(dev, 1); } #ifdef HAVE_WSMOUSED_SUPPORT /* * wsmoused(8) support functions */ /* * Main function, called from wsdisplay_cfg_ioctl. */ int wsmoused(struct wsdisplay_softc *sc, caddr_t data, int flag, struct proc *p) { struct wscons_event mouse_event = *(struct wscons_event *)data; if (IS_MOTION_EVENT(mouse_event.type)) { if (sc->sc_focus != NULL) motion_event(sc->sc_focus, mouse_event.type, mouse_event.value); return 0; } if (IS_BUTTON_EVENT(mouse_event.type)) { if (sc->sc_focus != NULL) { /* XXX tv_sec contains the number of clicks */ if (mouse_event.type == WSCONS_EVENT_MOUSE_DOWN) { button_event(sc->sc_focus, mouse_event.value, mouse_event.time.tv_sec); } else button_event(sc->sc_focus, mouse_event.value, 0); } return (0); } if (IS_CTRL_EVENT(mouse_event.type)) { return ctrl_event(sc, mouse_event.type, mouse_event.value, p); } return -1; } /* * Mouse motion events */ void motion_event(struct wsscreen *scr, u_int type, int value) { switch (type) { case WSCONS_EVENT_MOUSE_DELTA_X: mouse_moverel(scr, value, 0); break; case WSCONS_EVENT_MOUSE_DELTA_Y: mouse_moverel(scr, 0, -value); break; #ifdef HAVE_SCROLLBACK_SUPPORT case WSCONS_EVENT_MOUSE_DELTA_Z: mouse_zaxis(scr, value); break; #endif default: break; } } /* * Button clicks events */ void button_event(struct wsscreen *scr, int button, int clicks) { switch (button) { case MOUSE_COPY_BUTTON: switch (clicks % 4) { case 0: /* button is up */ mouse_copy_end(scr); mouse_copy_selection(scr); break; case 1: /* single click */ mouse_copy_start(scr); mouse_copy_selection(scr); break; case 2: /* double click */ mouse_copy_word(scr); mouse_copy_selection(scr); break; case 3: /* triple click */ mouse_copy_line(scr); mouse_copy_selection(scr); break; } break; case MOUSE_PASTE_BUTTON: if (clicks != 0) mouse_paste(scr); break; case MOUSE_EXTEND_BUTTON: if (clicks != 0) mouse_copy_extend_after(scr); break; default: break; } } /* * Control events */ int ctrl_event(struct wsdisplay_softc *sc, u_int type, int value, struct proc *p) { struct wsscreen *scr; int i; switch (type) { case WSCONS_EVENT_WSMOUSED_OFF: CLR(sc->sc_flags, SC_PASTE_AVAIL); return (0); case WSCONS_EVENT_WSMOUSED_ON: if (!sc->sc_accessops->getchar) /* no wsmoused(8) support in the display driver */ return (1); allocate_copybuffer(sc); CLR(sc->sc_flags, SC_PASTE_AVAIL); for (i = 0 ; i < WSDISPLAY_DEFAULTSCREENS ; i++) if ((scr = sc->sc_scr[i]) != NULL) { scr->mouse = (WS_NCOLS(scr) * WS_NROWS(scr)) / 2; scr->cursor = scr->mouse; scr->cpy_start = 0; scr->cpy_end = 0; scr->orig_start = 0; scr->orig_end = 0; scr->mouse_flags = 0; } return (0); default: /* can't happen, really */ return 0; } } void mouse_moverel(struct wsscreen *scr, int dx, int dy) { struct wsscreen_internal *dconf = scr->scr_dconf; u_int old_mouse = scr->mouse; int mouse_col = scr->mouse % N_COLS(dconf); int mouse_row = scr->mouse / N_COLS(dconf); /* update position */ if (mouse_col + dx >= MAXCOL(dconf)) mouse_col = MAXCOL(dconf); else { if (mouse_col + dx <= 0) mouse_col = 0; else mouse_col += dx; } if (mouse_row + dy >= MAXROW(dconf)) mouse_row = MAXROW(dconf); else { if (mouse_row + dy <= 0) mouse_row = 0; else mouse_row += dy; } scr->mouse = mouse_row * N_COLS(dconf) + mouse_col; /* if we have moved */ if (old_mouse != scr->mouse) { /* XXX unblank screen if display.ms_act */ if (ISSET(scr->mouse_flags, SEL_IN_PROGRESS)) { /* selection in progress */ mouse_copy_extend(scr); } else { inverse_char(scr, scr->mouse); if (ISSET(scr->mouse_flags, MOUSE_VISIBLE)) inverse_char(scr, old_mouse); else SET(scr->mouse_flags, MOUSE_VISIBLE); } } } void inverse_char(struct wsscreen *scr, u_int pos) { struct wsscreen_internal *dconf = scr->scr_dconf; struct wsdisplay_charcell cell; int fg, bg, ul; int flags; int tmp; uint32_t attr; GETCHAR(scr, pos, &cell); (*dconf->emulops->unpack_attr)(dconf->emulcookie, cell.attr, &fg, &bg, &ul); /* * Display the mouse cursor as a color inverted cell whenever * possible. If this is not possible, ask for the video reverse * attribute. */ flags = 0; if (dconf->scrdata->capabilities & WSSCREEN_WSCOLORS) { flags |= WSATTR_WSCOLORS; tmp = fg; fg = bg; bg = tmp; } else if (dconf->scrdata->capabilities & WSSCREEN_REVERSE) { flags |= WSATTR_REVERSE; } if ((*dconf->emulops->pack_attr)(dconf->emulcookie, fg, bg, flags | (ul ? WSATTR_UNDERLINE : 0), &attr) == 0) { cell.attr = attr; PUTCHAR(dconf, pos, cell.uc, cell.attr); } } void inverse_region(struct wsscreen *scr, u_int start, u_int end) { struct wsscreen_internal *dconf = scr->scr_dconf; u_int current_pos; u_int abs_end; /* sanity check, useful because 'end' can be (u_int)-1 */ abs_end = N_COLS(dconf) * N_ROWS(dconf); if (end > abs_end) return; current_pos = start; while (current_pos <= end) inverse_char(scr, current_pos++); } /* * Return the number of contiguous blank characters between the right margin * if border == 1 or between the next non-blank character and the current mouse * cursor if border == 0 */ u_int skip_spc_right(struct wsscreen *scr, int border) { struct wsscreen_internal *dconf = scr->scr_dconf; struct wsdisplay_charcell cell; u_int current = scr->cpy_end; u_int mouse_col = scr->cpy_end % N_COLS(dconf); u_int limit = current + (N_COLS(dconf) - mouse_col - 1); u_int res = 0; while (GETCHAR(scr, current, &cell) == 0 && cell.uc == ' ' && current <= limit) { current++; res++; } if (border == BORDER) { if (current > limit) return (res - 1); else return (0); } else { if (res != 0) return (res - 1); else return (res); } } /* * Return the number of contiguous blank characters between the first of the * contiguous blank characters and the current mouse cursor */ u_int skip_spc_left(struct wsscreen *scr) { struct wsscreen_internal *dconf = scr->scr_dconf; struct wsdisplay_charcell cell; u_int current = scr->cpy_start; u_int mouse_col = scr->mouse % N_COLS(dconf); u_int limit = current - mouse_col; u_int res = 0; while (GETCHAR(scr, current, &cell) == 0 && cell.uc == ' ' && current >= limit) { current--; res++; } if (res != 0) res--; return (res); } /* * Class of characters * Stolen from xterm sources of the Xfree project (see cvs tag below) * $TOG: button.c /main/76 1997/07/30 16:56:19 kaleb $ */ static const int charClass[256] = { /* NUL SOH STX ETX EOT ENQ ACK BEL */ 32, 1, 1, 1, 1, 1, 1, 1, /* BS HT NL VT NP CR SO SI */ 1, 32, 1, 1, 1, 1, 1, 1, /* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */ 1, 1, 1, 1, 1, 1, 1, 1, /* CAN EM SUB ESC FS GS RS US */ 1, 1, 1, 1, 1, 1, 1, 1, /* SP ! " # $ % & ' */ 32, 33, 34, 35, 36, 37, 38, 39, /* ( ) * + , - . / */ 40, 41, 42, 43, 44, 45, 46, 47, /* 0 1 2 3 4 5 6 7 */ 48, 48, 48, 48, 48, 48, 48, 48, /* 8 9 : ; < = > ? */ 48, 48, 58, 59, 60, 61, 62, 63, /* @ A B C D E F G */ 64, 48, 48, 48, 48, 48, 48, 48, /* H I J K L M N O */ 48, 48, 48, 48, 48, 48, 48, 48, /* P Q R S T U V W */ 48, 48, 48, 48, 48, 48, 48, 48, /* X Y Z [ \ ] ^ _ */ 48, 48, 48, 91, 92, 93, 94, 48, /* ` a b c d e f g */ 96, 48, 48, 48, 48, 48, 48, 48, /* h i j k l m n o */ 48, 48, 48, 48, 48, 48, 48, 48, /* p q r s t u v w */ 48, 48, 48, 48, 48, 48, 48, 48, /* x y z { | } ~ DEL */ 48, 48, 48, 123, 124, 125, 126, 1, /* x80 x81 x82 x83 IND NEL SSA ESA */ 1, 1, 1, 1, 1, 1, 1, 1, /* HTS HTJ VTS PLD PLU RI SS2 SS3 */ 1, 1, 1, 1, 1, 1, 1, 1, /* DCS PU1 PU2 STS CCH MW SPA EPA */ 1, 1, 1, 1, 1, 1, 1, 1, /* x98 x99 x9A CSI ST OSC PM APC */ 1, 1, 1, 1, 1, 1, 1, 1, /* - i c/ L ox Y- | So */ 160, 161, 162, 163, 164, 165, 166, 167, /* .. c0 ip << _ R0 - */ 168, 169, 170, 171, 172, 173, 174, 175, /* o +- 2 3 ' u q| . */ 176, 177, 178, 179, 180, 181, 182, 183, /* , 1 2 >> 1/4 1/2 3/4 ? */ 184, 185, 186, 187, 188, 189, 190, 191, /* A` A' A^ A~ A: Ao AE C, */ 48, 48, 48, 48, 48, 48, 48, 48, /* E` E' E^ E: I` I' I^ I: */ 48, 48, 48, 48, 48, 48, 48, 48, /* D- N~ O` O' O^ O~ O: X */ 48, 48, 48, 48, 48, 48, 48, 216, /* O/ U` U' U^ U: Y' P B */ 48, 48, 48, 48, 48, 48, 48, 48, /* a` a' a^ a~ a: ao ae c, */ 48, 48, 48, 48, 48, 48, 48, 48, /* e` e' e^ e: i` i' i^ i: */ 48, 48, 48, 48, 48, 48, 48, 48, /* d n~ o` o' o^ o~ o: -: */ 48, 48, 48, 48, 48, 48, 48, 248, /* o/ u` u' u^ u: y' P y: */ 48, 48, 48, 48, 48, 48, 48, 48 }; /* * Find the first blank beginning after the current cursor position */ u_int skip_char_right(struct wsscreen *scr, u_int offset) { struct wsscreen_internal *dconf = scr->scr_dconf; struct wsdisplay_charcell cell; u_int current = offset; u_int limit = current + (N_COLS(dconf) - (scr->mouse % N_COLS(dconf)) - 1); u_int class; u_int res = 0; GETCHAR(scr, current, &cell); class = charClass[cell.uc & 0xff]; while (GETCHAR(scr, current, &cell) == 0 && charClass[cell.uc & 0xff] == class && current <= limit) { current++; res++; } if (res != 0) res--; return (res); } /* * Find the first non-blank character before the cursor position */ u_int skip_char_left(struct wsscreen *scr, u_int offset) { struct wsscreen_internal *dconf = scr->scr_dconf; struct wsdisplay_charcell cell; u_int current = offset; u_int limit = current - (scr->mouse % N_COLS(dconf)); u_int class; u_int res = 0; GETCHAR(scr, current, &cell); class = charClass[cell.uc & 0xff]; while (GETCHAR(scr, current, &cell) == 0 && charClass[cell.uc & 0xff] == class && current >= limit) { current--; res++; } if (res != 0) res--; return (res); } /* * Compare character classes */ u_int class_cmp(struct wsscreen *scr, u_int first, u_int second) { struct wsdisplay_charcell cell; u_int first_class; u_int second_class; if (GETCHAR(scr, first, &cell) != 0) return (1); first_class = charClass[cell.uc & 0xff]; if (GETCHAR(scr, second, &cell) != 0) return (1); second_class = charClass[cell.uc & 0xff]; if (first_class != second_class) return (1); else return (0); } /* * Beginning of a copy operation */ void mouse_copy_start(struct wsscreen *scr) { u_int right; /* if no selection, then that's the first one */ SET(scr->sc->sc_flags, SC_PASTE_AVAIL); /* remove the previous selection */ if (ISSET(scr->mouse_flags, SEL_EXISTS)) remove_selection(scr); /* initial show of the cursor */ if (!ISSET(scr->mouse_flags, MOUSE_VISIBLE)) inverse_char(scr, scr->mouse); scr->cpy_start = scr->cpy_end = scr->mouse; scr->orig_start = scr->cpy_start; scr->orig_end = scr->cpy_end; scr->cursor = scr->cpy_end + 1; /* init value */ /* useful later, in mouse_copy_extend */ right = skip_spc_right(scr, BORDER); if (right) SET(scr->mouse_flags, BLANK_TO_EOL); SET(scr->mouse_flags, SEL_IN_PROGRESS | SEL_EXISTS | SEL_BY_CHAR); CLR(scr->mouse_flags, SEL_BY_WORD | SEL_BY_LINE); CLR(scr->mouse_flags, MOUSE_VISIBLE); /* cursor hidden in selection */ } /* * Copy of the word under the cursor */ void mouse_copy_word(struct wsscreen *scr) { struct wsdisplay_charcell cell; u_int right; u_int left; if (ISSET(scr->mouse_flags, SEL_EXISTS)) remove_selection(scr); if (ISSET(scr->mouse_flags, MOUSE_VISIBLE)) inverse_char(scr, scr->mouse); scr->cpy_start = scr->cpy_end = scr->mouse; if (GETCHAR(scr, scr->mouse, &cell) == 0 && IS_ALPHANUM(cell.uc)) { right = skip_char_right(scr, scr->cpy_end); left = skip_char_left(scr, scr->cpy_start); } else { right = skip_spc_right(scr, NO_BORDER); left = skip_spc_left(scr); } scr->cpy_start -= left; scr->cpy_end += right; scr->orig_start = scr->cpy_start; scr->orig_end = scr->cpy_end; scr->cursor = scr->cpy_end + 1; /* init value, never happen */ inverse_region(scr, scr->cpy_start, scr->cpy_end); SET(scr->mouse_flags, SEL_IN_PROGRESS | SEL_EXISTS | SEL_BY_WORD); CLR(scr->mouse_flags, SEL_BY_CHAR | SEL_BY_LINE); /* mouse cursor hidden in the selection */ CLR(scr->mouse_flags, BLANK_TO_EOL | MOUSE_VISIBLE); } /* * Copy of the current line */ void mouse_copy_line(struct wsscreen *scr) { struct wsscreen_internal *dconf = scr->scr_dconf; u_int row = scr->mouse / N_COLS(dconf); if (ISSET(scr->mouse_flags, SEL_EXISTS)) remove_selection(scr); if (ISSET(scr->mouse_flags, MOUSE_VISIBLE)) inverse_char(scr, scr->mouse); scr->cpy_start = row * N_COLS(dconf); scr->cpy_end = scr->cpy_start + (N_COLS(dconf) - 1); scr->orig_start = scr->cpy_start; scr->orig_end = scr->cpy_end; scr->cursor = scr->cpy_end + 1; inverse_region(scr, scr->cpy_start, scr->cpy_end); SET(scr->mouse_flags, SEL_IN_PROGRESS | SEL_EXISTS | SEL_BY_LINE); CLR(scr->mouse_flags, SEL_BY_CHAR | SEL_BY_WORD); /* mouse cursor hidden in the selection */ CLR(scr->mouse_flags, BLANK_TO_EOL | MOUSE_VISIBLE); } /* * End of a copy operation */ void mouse_copy_end(struct wsscreen *scr) { CLR(scr->mouse_flags, SEL_IN_PROGRESS); if (ISSET(scr->mouse_flags, SEL_BY_WORD) || ISSET(scr->mouse_flags, SEL_BY_LINE)) { if (scr->cursor != scr->cpy_end + 1) inverse_char(scr, scr->cursor); scr->cursor = scr->cpy_end + 1; } } /* * Generic selection extend function */ void mouse_copy_extend(struct wsscreen *scr) { if (ISSET(scr->mouse_flags, SEL_BY_CHAR)) mouse_copy_extend_char(scr); if (ISSET(scr->mouse_flags, SEL_BY_WORD)) mouse_copy_extend_word(scr); if (ISSET(scr->mouse_flags, SEL_BY_LINE)) mouse_copy_extend_line(scr); } /* * Extend a selected region, character by character */ void mouse_copy_extend_char(struct wsscreen *scr) { u_int right; if (!ISSET(scr->mouse_flags, SEL_EXT_AFTER)) { if (ISSET(scr->mouse_flags, BLANK_TO_EOL)) { /* * First extension of selection. We handle special * cases of blank characters to eol */ right = skip_spc_right(scr, BORDER); if (scr->mouse > scr->orig_start) { /* the selection goes to the lower part of the screen */ /* remove the previous cursor, start of selection is now next line */ inverse_char(scr, scr->cpy_start); scr->cpy_start += (right + 1); scr->cpy_end = scr->cpy_start; scr->orig_start = scr->cpy_start; /* simulate the initial mark */ inverse_char(scr, scr->cpy_start); } else { /* the selection goes to the upper part of the screen */ /* remove the previous cursor, start of selection is now at the eol */ inverse_char(scr, scr->cpy_start); scr->orig_start += (right + 1); scr->cpy_start = scr->orig_start - 1; scr->cpy_end = scr->orig_start - 1; /* simulate the initial mark */ inverse_char(scr, scr->cpy_start); } CLR(scr->mouse_flags, BLANK_TO_EOL); } if (scr->mouse < scr->orig_start && scr->cpy_end >= scr->orig_start) { /* we go to the upper part of the screen */ /* reverse the old selection region */ remove_selection(scr); scr->cpy_end = scr->orig_start - 1; scr->cpy_start = scr->orig_start; } if (scr->cpy_start < scr->orig_start && scr->mouse >= scr->orig_start) { /* we go to the lower part of the screen */ /* reverse the old selection region */ remove_selection(scr); scr->cpy_start = scr->orig_start; scr->cpy_end = scr->orig_start - 1; } /* restore flags cleared in remove_selection() */ SET(scr->mouse_flags, SEL_IN_PROGRESS | SEL_EXISTS); } if (scr->mouse >= scr->orig_start) { /* lower part of the screen */ if (scr->mouse > scr->cpy_end) { /* extending selection */ inverse_region(scr, scr->cpy_end + 1, scr->mouse); } else { /* reducing selection */ inverse_region(scr, scr->mouse + 1, scr->cpy_end); } scr->cpy_end = scr->mouse; } else { /* upper part of the screen */ if (scr->mouse < scr->cpy_start) { /* extending selection */ inverse_region(scr, scr->mouse, scr->cpy_start - 1); } else { /* reducing selection */ inverse_region(scr, scr->cpy_start, scr->mouse - 1); } scr->cpy_start = scr->mouse; } } /* * Extend a selected region, word by word */ void mouse_copy_extend_word(struct wsscreen *scr) { u_int old_cpy_end; u_int old_cpy_start; if (!ISSET(scr->mouse_flags, SEL_EXT_AFTER)) { /* remove cursor in selection (black one) */ if (scr->cursor != scr->cpy_end + 1) inverse_char(scr, scr->cursor); /* now, switch between lower and upper part of the screen */ if (scr->mouse < scr->orig_start && scr->cpy_end >= scr->orig_start) { /* going to the upper part of the screen */ inverse_region(scr, scr->orig_end + 1, scr->cpy_end); scr->cpy_end = scr->orig_end; } if (scr->mouse > scr->orig_end && scr->cpy_start <= scr->orig_start) { /* going to the lower part of the screen */ inverse_region(scr, scr->cpy_start, scr->orig_start - 1); scr->cpy_start = scr->orig_start; } } if (scr->mouse >= scr->orig_start) { /* lower part of the screen */ if (scr->mouse > scr->cpy_end) { /* extending selection */ old_cpy_end = scr->cpy_end; scr->cpy_end = scr->mouse + skip_char_right(scr, scr->mouse); inverse_region(scr, old_cpy_end + 1, scr->cpy_end); } else { if (class_cmp(scr, scr->mouse, scr->mouse + 1)) { /* reducing selection (remove last word) */ old_cpy_end = scr->cpy_end; scr->cpy_end = scr->mouse; inverse_region(scr, scr->cpy_end + 1, old_cpy_end); } else { old_cpy_end = scr->cpy_end; scr->cpy_end = scr->mouse + skip_char_right(scr, scr->mouse); if (scr->cpy_end != old_cpy_end) { /* reducing selection, from the end of * next word */ inverse_region(scr, scr->cpy_end + 1, old_cpy_end); } } } } else { /* upper part of the screen */ if (scr->mouse < scr->cpy_start) { /* extending selection */ old_cpy_start = scr->cpy_start; scr->cpy_start = scr->mouse - skip_char_left(scr, scr->mouse); inverse_region(scr, scr->cpy_start, old_cpy_start - 1); } else { if (class_cmp(scr, scr->mouse - 1, scr->mouse)) { /* reducing selection (remove last word) */ old_cpy_start = scr->cpy_start; scr->cpy_start = scr->mouse; inverse_region(scr, old_cpy_start, scr->cpy_start - 1); } else { old_cpy_start = scr->cpy_start; scr->cpy_start = scr->mouse - skip_char_left(scr, scr->mouse); if (scr->cpy_start != old_cpy_start) { inverse_region(scr, old_cpy_start, scr->cpy_start - 1); } } } } if (!ISSET(scr->mouse_flags, SEL_EXT_AFTER)) { /* display new cursor */ scr->cursor = scr->mouse; inverse_char(scr, scr->cursor); } } /* * Extend a selected region, line by line */ void mouse_copy_extend_line(struct wsscreen *scr) { struct wsscreen_internal *dconf = scr->scr_dconf; u_int old_row; u_int new_row; u_int old_cpy_start; u_int old_cpy_end; if (!ISSET(scr->mouse_flags, SEL_EXT_AFTER)) { /* remove cursor in selection (black one) */ if (scr->cursor != scr->cpy_end + 1) inverse_char(scr, scr->cursor); /* now, switch between lower and upper part of the screen */ if (scr->mouse < scr->orig_start && scr->cpy_end >= scr->orig_start) { /* going to the upper part of the screen */ inverse_region(scr, scr->orig_end + 1, scr->cpy_end); scr->cpy_end = scr->orig_end; } if (scr->mouse > scr->orig_end && scr->cpy_start <= scr->orig_start) { /* going to the lower part of the screen */ inverse_region(scr, scr->cpy_start, scr->orig_start - 1); scr->cpy_start = scr->orig_start; } } if (scr->mouse >= scr->orig_start) { /* lower part of the screen */ if (scr->cursor == scr->cpy_end + 1) scr->cursor = scr->cpy_end; old_row = scr->cursor / N_COLS(dconf); new_row = scr->mouse / N_COLS(dconf); old_cpy_end = scr->cpy_end; scr->cpy_end = new_row * N_COLS(dconf) + MAXCOL(dconf); if (new_row > old_row) inverse_region(scr, old_cpy_end + 1, scr->cpy_end); else if (new_row < old_row) inverse_region(scr, scr->cpy_end + 1, old_cpy_end); } else { /* upper part of the screen */ old_row = scr->cursor / N_COLS(dconf); new_row = scr->mouse / N_COLS(dconf); old_cpy_start = scr->cpy_start; scr->cpy_start = new_row * N_COLS(dconf); if (new_row < old_row) inverse_region(scr, scr->cpy_start, old_cpy_start - 1); else if (new_row > old_row) inverse_region(scr, old_cpy_start, scr->cpy_start - 1); } if (!ISSET(scr->mouse_flags, SEL_EXT_AFTER)) { /* display new cursor */ scr->cursor = scr->mouse; inverse_char(scr, scr->cursor); } } /* * Add an extension to a selected region, word by word */ void mouse_copy_extend_after(struct wsscreen *scr) { u_int start_dist; u_int end_dist; if (ISSET(scr->mouse_flags, SEL_EXISTS)) { SET(scr->mouse_flags, SEL_EXT_AFTER); mouse_hide(scr); /* hide current cursor */ if (scr->cpy_start > scr->mouse) start_dist = scr->cpy_start - scr->mouse; else start_dist = scr->mouse - scr->cpy_start; if (scr->mouse > scr->cpy_end) end_dist = scr->mouse - scr->cpy_end; else end_dist = scr->cpy_end - scr->mouse; if (start_dist < end_dist) { /* upper part of the screen*/ scr->orig_start = scr->mouse + 1; /* only used in mouse_copy_extend_line() */ scr->cursor = scr->cpy_start; } else { /* lower part of the screen */ scr->orig_start = scr->mouse; /* only used in mouse_copy_extend_line() */ scr->cursor = scr->cpy_end; } if (ISSET(scr->mouse_flags, SEL_BY_CHAR)) mouse_copy_extend_char(scr); if (ISSET(scr->mouse_flags, SEL_BY_WORD)) mouse_copy_extend_word(scr); if (ISSET(scr->mouse_flags, SEL_BY_LINE)) mouse_copy_extend_line(scr); mouse_copy_selection(scr); } } void mouse_hide(struct wsscreen *scr) { if (ISSET(scr->mouse_flags, MOUSE_VISIBLE)) { inverse_char(scr, scr->mouse); CLR(scr->mouse_flags, MOUSE_VISIBLE); } } /* * Remove a previously selected region */ void remove_selection(struct wsscreen *scr) { if (ISSET(scr->mouse_flags, SEL_EXT_AFTER)) { /* reset the flag indicating an extension of selection */ CLR(scr->mouse_flags, SEL_EXT_AFTER); } inverse_region(scr, scr->cpy_start, scr->cpy_end); CLR(scr->mouse_flags, SEL_IN_PROGRESS | SEL_EXISTS); } /* * Put the current visual selection in the selection buffer */ void mouse_copy_selection(struct wsscreen *scr) { struct wsscreen_internal *dconf = scr->scr_dconf; struct wsdisplay_charcell cell; u_int current = 0; u_int blank = current; u_int buf_end = (N_COLS(dconf) + 1) * N_ROWS(dconf); u_int sel_cur; u_int sel_end; sel_cur = scr->cpy_start; sel_end = scr->cpy_end; while (sel_cur <= sel_end && current < buf_end - 1) { if (GETCHAR(scr, sel_cur, &cell) != 0) break; scr->sc->sc_copybuffer[current] = cell.uc; if (!IS_SPACE(cell.uc)) blank = current + 1; /* first blank after non-blank */ current++; if (sel_cur % N_COLS(dconf) == MAXCOL(dconf)) { /* * If we are on the last column of the screen, * insert a carriage return. */ scr->sc->sc_copybuffer[blank] = '\r'; current = ++blank; } sel_cur++; } scr->sc->sc_copybuffer[current] = '\0'; } /* * Paste the current selection */ void mouse_paste(struct wsscreen *scr) { char *current = scr->sc->sc_copybuffer; struct tty *tp; u_int len; if (ISSET(scr->sc->sc_flags, SC_PASTE_AVAIL)) { if (!WSSCREEN_HAS_TTY(scr)) return; tp = scr->scr_tty; for (len = strlen(scr->sc->sc_copybuffer); len != 0; len--) (*linesw[tp->t_line].l_rint)(*current++, tp); } } #ifdef HAVE_SCROLLBACK_SUPPORT /* * Handle the z axis. * The z axis (roller or wheel) is mapped by default to scrollback. */ void mouse_zaxis(struct wsscreen *scr, int z) { if (z < 0) wsscrollback(scr->sc, WSDISPLAY_SCROLL_BACKWARD); else wsscrollback(scr->sc, WSDISPLAY_SCROLL_FORWARD); } #endif /* * Allocate the copy buffer. The size is: * (cols + 1) * (rows) * (+1 for '\n' at the end of lines), * where cols and rows are the maximum of column and rows of all screens. */ void allocate_copybuffer(struct wsdisplay_softc *sc) { int nscreens = sc->sc_scrdata->nscreens; int i, s; const struct wsscreen_descr **screens_list = sc->sc_scrdata->screens; const struct wsscreen_descr *current; u_int size = sc->sc_copybuffer_size; s = spltty(); for (i = 0; i < nscreens; i++) { current = *screens_list; if ((current->ncols + 1) * current->nrows > size) size = (current->ncols + 1) * current->nrows; screens_list++; } if (size != sc->sc_copybuffer_size && sc->sc_copybuffer_size != 0) { bzero(sc->sc_copybuffer, sc->sc_copybuffer_size); free(sc->sc_copybuffer, M_DEVBUF, sc->sc_copybuffer_size); } if ((sc->sc_copybuffer = (char *)malloc(size, M_DEVBUF, M_NOWAIT)) == NULL) { printf("%s: couldn't allocate copy buffer\n", sc->sc_dv.dv_xname); size = 0; } sc->sc_copybuffer_size = size; splx(s); } /* Remove selection and cursor on current screen */ void mouse_remove(struct wsscreen *scr) { if (ISSET(scr->mouse_flags, SEL_EXISTS)) remove_selection(scr); mouse_hide(scr); } #endif /* HAVE_WSMOUSED_SUPPORT */
5 3 1 2 1 1 1 1 1 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 /* $OpenBSD: mpls_input.c,v 1.79 2023/05/13 13:35:18 bluhm Exp $ */ /* * Copyright (c) 2008 Claudio Jeker <claudio@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/mbuf.h> #include <sys/systm.h> #include <sys/socket.h> #include <net/if.h> #include <net/if_var.h> #include <net/if_types.h> #include <net/netisr.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_var.h> #include <netinet/ip_icmp.h> #ifdef INET6 #include <netinet/ip6.h> #endif /* INET6 */ #include <netmpls/mpls.h> #ifdef MPLS_DEBUG #define MPLS_LABEL_GET(l) ((ntohl((l) & MPLS_LABEL_MASK)) >> MPLS_LABEL_OFFSET) #define MPLS_TTL_GET(l) (ntohl((l) & MPLS_TTL_MASK)) #endif struct mbuf *mpls_do_error(struct mbuf *, int, int, int); void mpls_input_local(struct rtentry *, struct mbuf *); void mpls_input(struct ifnet *ifp, struct mbuf *m) { struct sockaddr_mpls *smpls; struct sockaddr_mpls sa_mpls; struct shim_hdr *shim; struct rtentry *rt; struct rt_mpls *rt_mpls; uint8_t ttl; int hasbos; if (!ISSET(ifp->if_xflags, IFXF_MPLS)) { m_freem(m); return; } /* drop all broadcast and multicast packets */ if (m->m_flags & (M_BCAST | M_MCAST)) { m_freem(m); return; } if (m->m_len < sizeof(*shim)) { m = m_pullup(m, sizeof(*shim)); if (m == NULL) return; } shim = mtod(m, struct shim_hdr *); #ifdef MPLS_DEBUG printf("mpls_input: iface %s label=%d, ttl=%d BoS %d\n", ifp->if_xname, MPLS_LABEL_GET(shim->shim_label), MPLS_TTL_GET(shim->shim_label), MPLS_BOS_ISSET(shim->shim_label)); #endif /* check and decrement TTL */ ttl = ntohl(shim->shim_label & MPLS_TTL_MASK); if (ttl <= 1) { /* TTL exceeded */ m = mpls_do_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, 0); if (m == NULL) return; shim = mtod(m, struct shim_hdr *); ttl = ntohl(shim->shim_label & MPLS_TTL_MASK); } else ttl--; hasbos = MPLS_BOS_ISSET(shim->shim_label); bzero(&sa_mpls, sizeof(sa_mpls)); smpls = &sa_mpls; smpls->smpls_family = AF_MPLS; smpls->smpls_len = sizeof(*smpls); smpls->smpls_label = shim->shim_label & MPLS_LABEL_MASK; if (ntohl(smpls->smpls_label) < MPLS_LABEL_RESERVED_MAX) { m = mpls_shim_pop(m); if (m == NULL) return; if (!hasbos) { /* * RFC 4182 relaxes the position of the * explicit NULL labels. They no longer need * to be at the beginning of the stack. * In this case the label is ignored and the decision * is made based on the lower one. */ shim = mtod(m, struct shim_hdr *); smpls->smpls_label = shim->shim_label & MPLS_LABEL_MASK; hasbos = MPLS_BOS_ISSET(shim->shim_label); } else { switch (ntohl(smpls->smpls_label)) { case MPLS_LABEL_IPV4NULL: do_v4: if (mpls_mapttl_ip) { m = mpls_ip_adjttl(m, ttl); if (m == NULL) return; } ipv4_input(ifp, m); return; #ifdef INET6 case MPLS_LABEL_IPV6NULL: do_v6: if (mpls_mapttl_ip6) { m = mpls_ip6_adjttl(m, ttl); if (m == NULL) return; } ipv6_input(ifp, m); return; #endif /* INET6 */ case MPLS_LABEL_IMPLNULL: if (m->m_len < sizeof(u_char) && (m = m_pullup(m, sizeof(u_char))) == NULL) return; switch (*mtod(m, u_char *) >> 4) { case IPVERSION: goto do_v4; #ifdef INET6 case IPV6_VERSION >> 4: goto do_v6; #endif default: m_freem(m); return; } default: /* Other cases are not handled for now */ m_freem(m); return; } } } ifp = NULL; rt = rtalloc(smplstosa(smpls), RT_RESOLVE, m->m_pkthdr.ph_rtableid); if (!rtisvalid(rt)) { /* no entry for this label */ #ifdef MPLS_DEBUG printf("MPLS_DEBUG: label not found\n"); #endif m_freem(m); goto done; } rt_mpls = (struct rt_mpls *)rt->rt_llinfo; if (rt_mpls == NULL || (rt->rt_flags & RTF_MPLS) == 0) { #ifdef MPLS_DEBUG printf("MPLS_DEBUG: no MPLS information attached\n"); #endif m_freem(m); goto done; } switch (rt_mpls->mpls_operation) { case MPLS_OP_POP: if (ISSET(rt->rt_flags, RTF_LOCAL)) { mpls_input_local(rt, m); goto done; } m = mpls_shim_pop(m); if (m == NULL) goto done; if (!hasbos) /* just forward to gw */ break; /* last label popped so decide where to push it to */ ifp = if_get(rt->rt_ifidx); if (ifp == NULL) { m_freem(m); goto done; } KASSERT(rt->rt_gateway); switch(rt->rt_gateway->sa_family) { case AF_INET: if ((m = mpls_ip_adjttl(m, ttl)) == NULL) goto done; break; #ifdef INET6 case AF_INET6: if ((m = mpls_ip6_adjttl(m, ttl)) == NULL) goto done; break; #endif case AF_LINK: break; default: m_freem(m); goto done; } /* shortcut sending out the packet */ if (!ISSET(ifp->if_xflags, IFXF_MPLS)) (*ifp->if_output)(ifp, m, rt->rt_gateway, rt); else (*ifp->if_ll_output)(ifp, m, rt->rt_gateway, rt); goto done; case MPLS_OP_PUSH: /* this does not make much sense but it does not hurt */ m = mpls_shim_push(m, rt_mpls); break; case MPLS_OP_SWAP: m = mpls_shim_swap(m, rt_mpls); break; default: m_freem(m); goto done; } if (m == NULL) goto done; /* refetch label and write back TTL */ shim = mtod(m, struct shim_hdr *); shim->shim_label = (shim->shim_label & ~MPLS_TTL_MASK) | htonl(ttl); ifp = if_get(rt->rt_ifidx); if (ifp == NULL) { m_freem(m); goto done; } #ifdef MPLS_DEBUG printf("MPLS: sending on %s outlabel %x dst af %d in %d out %d\n", ifp->if_xname, ntohl(shim->shim_label), smpls->smpls_family, MPLS_LABEL_GET(smpls->smpls_label), MPLS_LABEL_GET(rt_mpls->mpls_label)); #endif /* Output iface is not MPLS-enabled */ if (!ISSET(ifp->if_xflags, IFXF_MPLS)) { #ifdef MPLS_DEBUG printf("MPLS_DEBUG: interface %s not mpls enabled\n", ifp->if_xname); #endif m_freem(m); goto done; } (*ifp->if_ll_output)(ifp, m, smplstosa(smpls), rt); done: if_put(ifp); rtfree(rt); } void mpls_input_local(struct rtentry *rt, struct mbuf *m) { struct ifnet *ifp; ifp = if_get(rt->rt_ifidx); if (ifp == NULL) { m_freem(m); return; } /* shortcut sending out the packet */ if (!ISSET(ifp->if_xflags, IFXF_MPLS)) (*ifp->if_output)(ifp, m, rt->rt_gateway, rt); else (*ifp->if_ll_output)(ifp, m, rt->rt_gateway, rt); if_put(ifp); } struct mbuf * mpls_ip_adjttl(struct mbuf *m, u_int8_t ttl) { struct ip *ip; uint16_t old, new; uint32_t x; if (m->m_len < sizeof(*ip)) { m = m_pullup(m, sizeof(*ip)); if (m == NULL) return (NULL); } ip = mtod(m, struct ip *); old = htons(ip->ip_ttl << 8); new = htons(ttl << 8); x = ip->ip_sum + old - new; ip->ip_ttl = ttl; /* see pf_cksum_fixup() */ ip->ip_sum = (x) + (x >> 16); return (m); } #ifdef INET6 struct mbuf * mpls_ip6_adjttl(struct mbuf *m, u_int8_t ttl) { struct ip6_hdr *ip6; if (m->m_len < sizeof(*ip6)) { m = m_pullup(m, sizeof(*ip6)); if (m == NULL) return (NULL); } ip6 = mtod(m, struct ip6_hdr *); ip6->ip6_hlim = ttl; return (m); } #endif /* INET6 */ struct mbuf * mpls_do_error(struct mbuf *m, int type, int code, int destmtu) { struct shim_hdr stack[MPLS_INKERNEL_LOOP_MAX]; struct sockaddr_mpls sa_mpls; struct sockaddr_mpls *smpls; struct rtentry *rt = NULL; struct shim_hdr *shim; struct in_ifaddr *ia; struct icmp *icp; struct ip *ip; int nstk, error; for (nstk = 0; nstk < MPLS_INKERNEL_LOOP_MAX; nstk++) { if (m->m_len < sizeof(*shim) && (m = m_pullup(m, sizeof(*shim))) == NULL) return (NULL); stack[nstk] = *mtod(m, struct shim_hdr *); m_adj(m, sizeof(*shim)); if (MPLS_BOS_ISSET(stack[nstk].shim_label)) break; } shim = &stack[0]; if (m->m_len < sizeof(u_char) && (m = m_pullup(m, sizeof(u_char))) == NULL) return (NULL); switch (*mtod(m, u_char *) >> 4) { case IPVERSION: if (m->m_len < sizeof(*ip) && (m = m_pullup(m, sizeof(*ip))) == NULL) return (NULL); m = icmp_do_error(m, type, code, 0, destmtu); if (m == NULL) return (NULL); if (icmp_do_exthdr(m, ICMP_EXT_MPLS, 1, stack, (nstk + 1) * sizeof(*shim))) return (NULL); /* set ip_src to something usable, based on the MPLS label */ bzero(&sa_mpls, sizeof(sa_mpls)); smpls = &sa_mpls; smpls->smpls_family = AF_MPLS; smpls->smpls_len = sizeof(*smpls); smpls->smpls_label = shim->shim_label & MPLS_LABEL_MASK; rt = rtalloc(smplstosa(smpls), RT_RESOLVE, 0); if (!rtisvalid(rt)) { rtfree(rt); /* no entry for this label */ m_freem(m); return (NULL); } if (rt->rt_ifa->ifa_addr->sa_family == AF_INET) ia = ifatoia(rt->rt_ifa); else { /* XXX this needs fixing, if the MPLS is on an IP * less interface we need to find some other IP to * use as source. */ rtfree(rt); m_freem(m); return (NULL); } /* It is safe to dereference ``ia'' iff ``rt'' is valid. */ error = icmp_reflect(m, NULL, ia); rtfree(rt); if (error) return (NULL); ip = mtod(m, struct ip *); /* stuff to fix up which is normally done in ip_output */ ip->ip_v = IPVERSION; ip->ip_id = htons(ip_randomid()); in_hdr_cksum_out(m, NULL); /* stolen from icmp_send() */ icp = (struct icmp *)(mtod(m, caddr_t) + sizeof(*ip)); icp->icmp_cksum = 0; icp->icmp_cksum = in4_cksum(m, 0, sizeof(*ip), ntohs(ip->ip_len) - sizeof(*ip)); break; #ifdef INET6 case IPV6_VERSION >> 4: #endif default: m_freem(m); return (NULL); } /* add mpls stack back to new packet */ M_PREPEND(m, (nstk + 1) * sizeof(*shim), M_NOWAIT); if (m == NULL) return (NULL); m_copyback(m, 0, (nstk + 1) * sizeof(*shim), stack, M_NOWAIT); /* change TTL to default */ shim = mtod(m, struct shim_hdr *); shim->shim_label = (shim->shim_label & ~MPLS_TTL_MASK) | htonl(mpls_defttl); return (m); }
1169 3 144 260 235 51 51 51 261 261 30 248 30 30 30 19 11 202 200 199 82 43 22 180 1 7 201 1067 1 978 148 148 7 1058 776 780 503 502 476 1250 1019 441 777 775 1 183 71 183 22 84 153 136 18 154 135 18 135 18 154 43 43 13 154 35 134 46 36 84 3 112 91 30 29 29 28 61 100 26 10 10 24 5 5 5 147 146 15 13 15 43 2 1 24 2 1 2 2 9 1 17 1 12 5 5 5 827 673 117 41 755 108 749 5278 5284 2 2 1 7 2 5 16 184 184 18 1 1 1 195 194 40 181 169 13 180 58 20 63 64 64 194 120 120 120 111 9 120 74 74 73 30 67 20 74 234 234 78 217 129 51 131 70 1 235 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 /* $OpenBSD: vfs_subr.c,v 1.319 2024/02/03 18:51:58 beck Exp $ */ /* $NetBSD: vfs_subr.c,v 1.53 1996/04/22 01:39:13 christos Exp $ */ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)vfs_subr.c 8.13 (Berkeley) 4/18/94 */ /* * External virtual filesystem routines */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/sysctl.h> #include <sys/mount.h> #include <sys/fcntl.h> #include <sys/conf.h> #include <sys/vnode.h> #include <sys/lock.h> #include <sys/lockf.h> #include <sys/stat.h> #include <sys/acct.h> #include <sys/namei.h> #include <sys/ucred.h> #include <sys/buf.h> #include <sys/errno.h> #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/syscallargs.h> #include <sys/pool.h> #include <sys/tree.h> #include <sys/specdev.h> #include <sys/atomic.h> #include <netinet/in.h> #include <uvm/uvm_extern.h> #include <uvm/uvm_vnode.h> #include "softraid.h" void sr_quiesce(void); enum vtype iftovt_tab[16] = { VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON, VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD, }; int vttoif_tab[9] = { 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, S_IFSOCK, S_IFIFO, S_IFMT, }; int prtactive = 0; /* 1 => print out reclaim of active vnodes */ int suid_clear = 1; /* 1 => clear SUID / SGID on owner change */ /* * Insq/Remq for the vnode usage lists. */ #define bufinsvn(bp, dp) LIST_INSERT_HEAD(dp, bp, b_vnbufs) #define bufremvn(bp) { \ LIST_REMOVE(bp, b_vnbufs); \ LIST_NEXT(bp, b_vnbufs) = NOLIST; \ } TAILQ_HEAD(freelst, vnode); struct freelst vnode_hold_list; /* list of vnodes referencing buffers */ struct freelst vnode_free_list; /* vnode free list */ struct mntlist mountlist; /* mounted filesystem list */ void vclean(struct vnode *, int, struct proc *); void insmntque(struct vnode *, struct mount *); int getdevvp(dev_t, struct vnode **, enum vtype); int vfs_hang_addrlist(struct mount *, struct netexport *, struct export_args *); int vfs_free_netcred(struct radix_node *, void *, u_int); void vfs_free_addrlist(struct netexport *); void vputonfreelist(struct vnode *); int vflush_vnode(struct vnode *, void *); int maxvnodes; struct mutex vnode_mtx = MUTEX_INITIALIZER(IPL_BIO); void vfs_unmountall(void); #ifdef DEBUG void printlockedvnodes(void); #endif struct pool vnode_pool; struct pool uvm_vnode_pool; static inline int rb_buf_compare(const struct buf *b1, const struct buf *b2); RBT_GENERATE(buf_rb_bufs, buf, b_rbbufs, rb_buf_compare); static inline int rb_buf_compare(const struct buf *b1, const struct buf *b2) { if (b1->b_lblkno < b2->b_lblkno) return(-1); if (b1->b_lblkno > b2->b_lblkno) return(1); return(0); } /* * Initialize the vnode management data structures. */ void vntblinit(void) { /* buffer cache may need a vnode for each buffer */ maxvnodes = 2 * initialvnodes; pool_init(&vnode_pool, sizeof(struct vnode), 0, IPL_NONE, PR_WAITOK, "vnodes", NULL); pool_init(&uvm_vnode_pool, sizeof(struct uvm_vnode), 0, IPL_NONE, PR_WAITOK, "uvmvnodes", NULL); TAILQ_INIT(&vnode_hold_list); TAILQ_INIT(&vnode_free_list); TAILQ_INIT(&mountlist); /* * Initialize the filesystem syncer. */ vn_initialize_syncerd(); #ifdef NFSSERVER rn_init(sizeof(struct sockaddr_in)); #endif /* NFSSERVER */ } /* * Allocate a mount point. * * The returned mount point is marked as busy. */ struct mount * vfs_mount_alloc(struct vnode *vp, struct vfsconf *vfsp) { struct mount *mp; mp = malloc(sizeof(*mp), M_MOUNT, M_WAITOK|M_ZERO); rw_init_flags(&mp->mnt_lock, "vfslock", RWL_IS_VNODE); (void)vfs_busy(mp, VB_READ|VB_NOWAIT); TAILQ_INIT(&mp->mnt_vnodelist); mp->mnt_vnodecovered = vp; atomic_inc_int(&vfsp->vfc_refcount); mp->mnt_vfc = vfsp; mp->mnt_op = vfsp->vfc_vfsops; mp->mnt_flag = vfsp->vfc_flags; strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN); return (mp); } /* * Release a mount point. */ void vfs_mount_free(struct mount *mp) { atomic_dec_int(&mp->mnt_vfc->vfc_refcount); free(mp, M_MOUNT, sizeof(*mp)); } /* * Mark a mount point as busy. Used to synchronize access and to delay * unmounting. * * Default behaviour is to attempt getting a READ lock and in case of an * ongoing unmount, to wait for it to finish and then return failure. */ int vfs_busy(struct mount *mp, int flags) { int rwflags = 0; if (flags & VB_WRITE) rwflags |= RW_WRITE; else rwflags |= RW_READ; if (flags & VB_WAIT) rwflags |= RW_SLEEPFAIL; else rwflags |= RW_NOSLEEP; #ifdef WITNESS if (flags & VB_DUPOK) rwflags |= RW_DUPOK; #endif if (rw_enter(&mp->mnt_lock, rwflags)) return (EBUSY); return (0); } /* * Free a busy file system */ void vfs_unbusy(struct mount *mp) { rw_exit(&mp->mnt_lock); } int vfs_isbusy(struct mount *mp) { if (RWLOCK_OWNER(&mp->mnt_lock) > 0) return (1); else return (0); } /* * Lookup a filesystem type, and if found allocate and initialize * a mount structure for it. * * Devname is usually updated by mount(8) after booting. */ int vfs_rootmountalloc(char *fstypename, char *devname, struct mount **mpp) { struct vfsconf *vfsp; struct mount *mp; vfsp = vfs_byname(fstypename); if (vfsp == NULL) return (ENODEV); mp = vfs_mount_alloc(NULLVP, vfsp); mp->mnt_flag |= MNT_RDONLY; mp->mnt_stat.f_mntonname[0] = '/'; strlcpy(mp->mnt_stat.f_mntfromname, devname, MNAMELEN); strlcpy(mp->mnt_stat.f_mntfromspec, devname, MNAMELEN); *mpp = mp; return (0); } /* * Lookup a mount point by filesystem identifier. */ struct mount * vfs_getvfs(fsid_t *fsid) { struct mount *mp; TAILQ_FOREACH(mp, &mountlist, mnt_list) { if (mp->mnt_stat.f_fsid.val[0] == fsid->val[0] && mp->mnt_stat.f_fsid.val[1] == fsid->val[1]) { return (mp); } } return (NULL); } /* * Get a new unique fsid */ void vfs_getnewfsid(struct mount *mp) { static u_short xxxfs_mntid; fsid_t tfsid; int mtype; mtype = mp->mnt_vfc->vfc_typenum; mp->mnt_stat.f_fsid.val[0] = makedev(nblkdev + mtype, 0); mp->mnt_stat.f_fsid.val[1] = mtype; if (xxxfs_mntid == 0) ++xxxfs_mntid; tfsid.val[0] = makedev(nblkdev + mtype, xxxfs_mntid); tfsid.val[1] = mtype; if (!TAILQ_EMPTY(&mountlist)) { while (vfs_getvfs(&tfsid)) { tfsid.val[0]++; xxxfs_mntid++; } } mp->mnt_stat.f_fsid.val[0] = tfsid.val[0]; } /* * Set vnode attributes to VNOVAL */ void vattr_null(struct vattr *vap) { vap->va_type = VNON; /* * Don't get fancy: u_quad_t = u_int = VNOVAL leaves the u_quad_t * with 2^31-1 instead of 2^64-1. Just write'm out and let * the compiler do its job. */ vap->va_mode = VNOVAL; vap->va_nlink = VNOVAL; vap->va_uid = VNOVAL; vap->va_gid = VNOVAL; vap->va_fsid = VNOVAL; vap->va_fileid = VNOVAL; vap->va_size = VNOVAL; vap->va_blocksize = VNOVAL; vap->va_atime.tv_sec = VNOVAL; vap->va_atime.tv_nsec = VNOVAL; vap->va_mtime.tv_sec = VNOVAL; vap->va_mtime.tv_nsec = VNOVAL; vap->va_ctime.tv_sec = VNOVAL; vap->va_ctime.tv_nsec = VNOVAL; vap->va_gen = VNOVAL; vap->va_flags = VNOVAL; vap->va_rdev = VNOVAL; vap->va_bytes = VNOVAL; vap->va_filerev = VNOVAL; vap->va_vaflags = 0; } /* * Routines having to do with the management of the vnode table. */ long numvnodes; /* * Return the next vnode from the free list. */ int getnewvnode(enum vtagtype tag, struct mount *mp, const struct vops *vops, struct vnode **vpp) { struct proc *p = curproc; struct freelst *listhd; static int toggle; struct vnode *vp; int s; /* * allow maxvnodes to increase if the buffer cache itself * is big enough to justify it. (we don't shrink it ever) */ maxvnodes = maxvnodes < bcstats.numbufs ? bcstats.numbufs : maxvnodes; /* * We must choose whether to allocate a new vnode or recycle an * existing one. The criterion for allocating a new one is that * the total number of vnodes is less than the number desired or * there are no vnodes on either free list. Generally we only * want to recycle vnodes that have no buffers associated with * them, so we look first on the vnode_free_list. If it is empty, * we next consider vnodes with referencing buffers on the * vnode_hold_list. The toggle ensures that half the time we * will use a buffer from the vnode_hold_list, and half the time * we will allocate a new one unless the list has grown to twice * the desired size. We are reticent to recycle vnodes from the * vnode_hold_list because we will lose the identity of all its * referencing buffers. */ toggle ^= 1; if (numvnodes / 2 > maxvnodes) toggle = 0; s = splbio(); if ((numvnodes < maxvnodes) || ((TAILQ_FIRST(listhd = &vnode_free_list) == NULL) && ((TAILQ_FIRST(listhd = &vnode_hold_list) == NULL) || toggle))) { splx(s); vp = pool_get(&vnode_pool, PR_WAITOK | PR_ZERO); vp->v_uvm = pool_get(&uvm_vnode_pool, PR_WAITOK | PR_ZERO); vp->v_uvm->u_vnode = vp; uvm_obj_init(&vp->v_uvm->u_obj, &uvm_vnodeops, 0); RBT_INIT(buf_rb_bufs, &vp->v_bufs_tree); cache_tree_init(&vp->v_nc_tree); TAILQ_INIT(&vp->v_cache_dst); numvnodes++; } else { TAILQ_FOREACH(vp, listhd, v_freelist) { if (VOP_ISLOCKED(vp) == 0) break; } /* * Unless this is a bad time of the month, at most * the first NCPUS items on the free list are * locked, so this is close enough to being empty. */ if (vp == NULL) { splx(s); tablefull("vnode"); *vpp = NULL; return (ENFILE); } #ifdef DIAGNOSTIC if (vp->v_usecount) { vprint("free vnode", vp); panic("free vnode isn't"); } #endif TAILQ_REMOVE(listhd, vp, v_freelist); vp->v_bioflag &= ~VBIOONFREELIST; splx(s); if (vp->v_type != VBAD) vgonel(vp, p); #ifdef DIAGNOSTIC if (vp->v_data) { vprint("cleaned vnode", vp); panic("cleaned vnode isn't"); } s = splbio(); if (vp->v_numoutput) panic("Clean vnode has pending I/O's"); splx(s); #endif vp->v_flag = 0; vp->v_socket = NULL; } cache_purge(vp); vp->v_type = VNON; vp->v_tag = tag; vp->v_op = vops; insmntque(vp, mp); *vpp = vp; vp->v_usecount = 1; vp->v_data = NULL; return (0); } /* * Move a vnode from one mount queue to another. */ void insmntque(struct vnode *vp, struct mount *mp) { /* * Delete from old mount point vnode list, if on one. */ if (vp->v_mount != NULL) TAILQ_REMOVE(&vp->v_mount->mnt_vnodelist, vp, v_mntvnodes); /* * Insert into list of vnodes for the new mount point, if available. */ if ((vp->v_mount = mp) != NULL) TAILQ_INSERT_TAIL(&mp->mnt_vnodelist, vp, v_mntvnodes); } /* * Create a vnode for a block device. * Used for root filesystem, argdev, and swap areas. * Also used for memory file system special devices. */ int bdevvp(dev_t dev, struct vnode **vpp) { return (getdevvp(dev, vpp, VBLK)); } /* * Create a vnode for a character device. * Used for console handling. */ int cdevvp(dev_t dev, struct vnode **vpp) { return (getdevvp(dev, vpp, VCHR)); } /* * Create a vnode for a device. * Used by bdevvp (block device) for root file system etc., * and by cdevvp (character device) for console. */ int getdevvp(dev_t dev, struct vnode **vpp, enum vtype type) { struct vnode *vp; struct vnode *nvp; int error; if (dev == NODEV) { *vpp = NULLVP; return (0); } error = getnewvnode(VT_NON, NULL, &spec_vops, &nvp); if (error) { *vpp = NULLVP; return (error); } vp = nvp; vp->v_type = type; if ((nvp = checkalias(vp, dev, NULL)) != NULL) { vput(vp); vp = nvp; } if (vp->v_type == VCHR && cdevsw[major(vp->v_rdev)].d_type == D_TTY) vp->v_flag |= VISTTY; *vpp = vp; return (0); } /* * Check to see if the new vnode represents a special device * for which we already have a vnode (either because of * bdevvp() or because of a different vnode representing * the same block device). If such an alias exists, deallocate * the existing contents and return the aliased vnode. The * caller is responsible for filling it with its new contents. */ struct vnode * checkalias(struct vnode *nvp, dev_t nvp_rdev, struct mount *mp) { struct proc *p = curproc; struct vnode *vp; struct vnodechain *vchain; if (nvp->v_type != VBLK && nvp->v_type != VCHR) return (NULLVP); vchain = &speclisth[SPECHASH(nvp_rdev)]; loop: SLIST_FOREACH(vp, vchain, v_specnext) { if (nvp_rdev != vp->v_rdev || nvp->v_type != vp->v_type) { continue; } /* * Alias, but not in use, so flush it out. */ if (vp->v_usecount == 0) { vgonel(vp, p); goto loop; } if (vget(vp, LK_EXCLUSIVE)) { goto loop; } break; } /* * Common case is actually in the if statement */ if (vp == NULL || !(vp->v_tag == VT_NON && vp->v_type == VBLK)) { nvp->v_specinfo = malloc(sizeof(struct specinfo), M_VNODE, M_WAITOK); nvp->v_rdev = nvp_rdev; nvp->v_hashchain = vchain; nvp->v_specmountpoint = NULL; nvp->v_speclockf = NULL; nvp->v_specbitmap = NULL; if (nvp->v_type == VCHR && (cdevsw[major(nvp_rdev)].d_flags & D_CLONE) && (minor(nvp_rdev) >> CLONE_SHIFT == 0)) { if (vp != NULLVP) nvp->v_specbitmap = vp->v_specbitmap; else nvp->v_specbitmap = malloc(CLONE_MAPSZ, M_VNODE, M_WAITOK | M_ZERO); } SLIST_INSERT_HEAD(vchain, nvp, v_specnext); if (vp != NULLVP) { nvp->v_flag |= VALIASED; vp->v_flag |= VALIASED; vput(vp); } return (NULLVP); } /* * This code is the uncommon case. It is called in case * we found an alias that was VT_NON && vtype of VBLK * This means we found a block device that was created * using bdevvp. * An example of such a vnode is the root partition device vnode * created in ffs_mountroot. * * The vnodes created by bdevvp should not be aliased (why?). */ VOP_UNLOCK(vp); vclean(vp, 0, p); vp->v_op = nvp->v_op; vp->v_tag = nvp->v_tag; nvp->v_type = VNON; insmntque(vp, mp); return (vp); } /* * Grab a particular vnode from the free list, increment its * reference count and lock it. If the vnode lock bit is set, * the vnode is being eliminated in vgone. In that case, we * cannot grab it, so the process is awakened when the * transition is completed, and an error code is returned to * indicate that the vnode is no longer usable, possibly * having been changed to a new file system type. */ int vget(struct vnode *vp, int flags) { int error, s, onfreelist; /* * If the vnode is in the process of being cleaned out for * another use, we wait for the cleaning to finish and then * return failure. Cleaning is determined by checking that * the VXLOCK flag is set. */ mtx_enter(&vnode_mtx); if (vp->v_lflag & VXLOCK) { if (flags & LK_NOWAIT) { mtx_leave(&vnode_mtx); return (EBUSY); } vp->v_lflag |= VXWANT; msleep_nsec(vp, &vnode_mtx, PINOD, "vget", INFSLP); mtx_leave(&vnode_mtx); return (ENOENT); } mtx_leave(&vnode_mtx); s = splbio(); onfreelist = vp->v_bioflag & VBIOONFREELIST; if (vp->v_usecount == 0 && onfreelist) { if (vp->v_holdcnt > 0) TAILQ_REMOVE(&vnode_hold_list, vp, v_freelist); else TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); vp->v_bioflag &= ~VBIOONFREELIST; } splx(s); vp->v_usecount++; if (flags & LK_TYPE_MASK) { if ((error = vn_lock(vp, flags)) != 0) { vp->v_usecount--; if (vp->v_usecount == 0 && onfreelist) vputonfreelist(vp); } return (error); } return (0); } /* Vnode reference. */ void vref(struct vnode *vp) { KERNEL_ASSERT_LOCKED(); #ifdef DIAGNOSTIC if (vp->v_usecount == 0) panic("vref used where vget required"); if (vp->v_type == VNON) panic("vref on a VNON vnode"); #endif vp->v_usecount++; } void vputonfreelist(struct vnode *vp) { int s; struct freelst *lst; s = splbio(); #ifdef DIAGNOSTIC if (vp->v_usecount != 0) panic("Use count is not zero!"); /* * If the hold count is still positive, one or many threads could still * be waiting on the vnode lock inside uvn_io(). */ if (vp->v_holdcnt == 0 && vp->v_lockcount != 0) panic("%s: lock count is not zero", __func__); if (vp->v_bioflag & VBIOONFREELIST) { vprint("vnode already on free list: ", vp); panic("vnode already on free list"); } #endif vp->v_bioflag |= VBIOONFREELIST; vp->v_bioflag &= ~VBIOERROR; if (vp->v_holdcnt > 0) lst = &vnode_hold_list; else lst = &vnode_free_list; if (vp->v_type == VBAD) TAILQ_INSERT_HEAD(lst, vp, v_freelist); else TAILQ_INSERT_TAIL(lst, vp, v_freelist); splx(s); } /* * vput(), just unlock and vrele() */ void vput(struct vnode *vp) { struct proc *p = curproc; int s; #ifdef DIAGNOSTIC if (vp == NULL) panic("vput: null vp"); #endif #ifdef DIAGNOSTIC if (vp->v_usecount == 0) { vprint("vput: bad ref count", vp); panic("vput: ref cnt"); } #endif vp->v_usecount--; KASSERT(vp->v_usecount > 0 || vp->v_uvcount == 0); if (vp->v_usecount > 0) { VOP_UNLOCK(vp); return; } #ifdef DIAGNOSTIC if (vp->v_writecount != 0) { vprint("vput: bad writecount", vp); panic("vput: v_writecount != 0"); } #endif VOP_INACTIVE(vp, p); s = splbio(); if (vp->v_usecount == 0 && !(vp->v_bioflag & VBIOONFREELIST)) vputonfreelist(vp); splx(s); } /* * Vnode release - use for active VNODES. * If count drops to zero, call inactive routine and return to freelist. * Returns 0 if it did not sleep. */ int vrele(struct vnode *vp) { struct proc *p = curproc; int s; #ifdef DIAGNOSTIC if (vp == NULL) panic("vrele: null vp"); #endif #ifdef DIAGNOSTIC if (vp->v_usecount == 0) { vprint("vrele: bad ref count", vp); panic("vrele: ref cnt"); } #endif vp->v_usecount--; if (vp->v_usecount > 0) { return (0); } #ifdef DIAGNOSTIC if (vp->v_writecount != 0) { vprint("vrele: bad writecount", vp); panic("vrele: v_writecount != 0"); } #endif if (vn_lock(vp, LK_EXCLUSIVE)) { #ifdef DIAGNOSTIC vprint("vrele: cannot lock", vp); #endif return (1); } VOP_INACTIVE(vp, p); s = splbio(); if (vp->v_usecount == 0 && !(vp->v_bioflag & VBIOONFREELIST)) vputonfreelist(vp); splx(s); return (1); } /* Page or buffer structure gets a reference. */ void vhold(struct vnode *vp) { int s; s = splbio(); /* * If it is on the freelist and the hold count is currently * zero, move it to the hold list. */ if ((vp->v_bioflag & VBIOONFREELIST) && vp->v_holdcnt == 0 && vp->v_usecount == 0) { TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); TAILQ_INSERT_TAIL(&vnode_hold_list, vp, v_freelist); } vp->v_holdcnt++; splx(s); } /* Lose interest in a vnode. */ void vdrop(struct vnode *vp) { int s; s = splbio(); #ifdef DIAGNOSTIC if (vp->v_holdcnt == 0) panic("vdrop: zero holdcnt"); #endif vp->v_holdcnt--; /* * If it is on the holdlist and the hold count drops to * zero, move it to the free list. */ if ((vp->v_bioflag & VBIOONFREELIST) && vp->v_holdcnt == 0 && vp->v_usecount == 0) { TAILQ_REMOVE(&vnode_hold_list, vp, v_freelist); TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist); } splx(s); } /* * Remove any vnodes in the vnode table belonging to mount point mp. * * If MNT_NOFORCE is specified, there should not be any active ones, * return error if any are found (nb: this is a user error, not a * system error). If MNT_FORCE is specified, detach any active vnodes * that are found. */ #ifdef DEBUG_SYSCTL int busyprt = 0; /* print out busy vnodes */ struct ctldebug debug_vfs_busyprt = { "vfs_busyprt", &busyprt }; #endif int vfs_mount_foreach_vnode(struct mount *mp, int (*func)(struct vnode *, void *), void *arg) { struct vnode *vp, *nvp; int error = 0; loop: TAILQ_FOREACH_SAFE(vp , &mp->mnt_vnodelist, v_mntvnodes, nvp) { if (vp->v_mount != mp) goto loop; error = func(vp, arg); if (error != 0) break; } return (error); } struct vflush_args { struct vnode *skipvp; int busy; int flags; }; int vflush_vnode(struct vnode *vp, void *arg) { struct vflush_args *va = arg; struct proc *p = curproc; int empty, s; if (vp == va->skipvp) { return (0); } if ((va->flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM)) { return (0); } /* * If WRITECLOSE is set, only flush out regular file * vnodes open for writing. */ if ((va->flags & WRITECLOSE) && (vp->v_writecount == 0 || vp->v_type != VREG)) { return (0); } /* * With v_usecount == 0, all we need to do is clear * out the vnode data structures and we are done. */ if (vp->v_usecount == 0) { vgonel(vp, p); return (0); } /* * If FORCECLOSE is set, forcibly close the vnode. * For block or character devices, revert to an * anonymous device. For all other files, just kill them. */ if (va->flags & FORCECLOSE) { if (vp->v_type != VBLK && vp->v_type != VCHR) { vgonel(vp, p); } else { vclean(vp, 0, p); vp->v_op = &spec_vops; insmntque(vp, NULL); } return (0); } /* * If set, this is allowed to ignore vnodes which don't * have changes pending to disk. * XXX Might be nice to check per-fs "inode" flags, but * generally the filesystem is sync'd already, right? */ s = splbio(); empty = (va->flags & IGNORECLEAN) && LIST_EMPTY(&vp->v_dirtyblkhd); splx(s); if (empty) return (0); #ifdef DEBUG_SYSCTL if (busyprt) vprint("vflush: busy vnode", vp); #endif va->busy++; return (0); } int vflush(struct mount *mp, struct vnode *skipvp, int flags) { struct vflush_args va; va.skipvp = skipvp; va.busy = 0; va.flags = flags; vfs_mount_foreach_vnode(mp, vflush_vnode, &va); if (va.busy) return (EBUSY); return (0); } /* * Disassociate the underlying file system from a vnode. */ void vclean(struct vnode *vp, int flags, struct proc *p) { int active, do_wakeup = 0; int s; /* * Check to see if the vnode is in use. * If so we have to reference it before we clean it out * so that its count cannot fall to zero and generate a * race against ourselves to recycle it. */ if ((active = vp->v_usecount) != 0) vp->v_usecount++; /* * Prevent the vnode from being recycled or * brought into use while we clean it out. */ mtx_enter(&vnode_mtx); if (vp->v_lflag & VXLOCK) panic("vclean: deadlock"); vp->v_lflag |= VXLOCK; if (vp->v_lockcount > 0) { /* * Ensure that any thread currently waiting on the same lock has * observed that the vnode is about to be exclusively locked * before continuing. */ msleep_nsec(&vp->v_lockcount, &vnode_mtx, PINOD, "vop_lock", INFSLP); KASSERT(vp->v_lockcount == 0); } mtx_leave(&vnode_mtx); /* * Even if the count is zero, the VOP_INACTIVE routine may still * have the object locked while it cleans it out. The VOP_LOCK * ensures that the VOP_INACTIVE routine is done with its work. * For active vnodes, it ensures that no other activity can * occur while the underlying object is being cleaned out. */ VOP_LOCK(vp, LK_EXCLUSIVE | LK_DRAIN); /* * Clean out any VM data associated with the vnode. */ uvm_vnp_terminate(vp); /* * Clean out any buffers associated with the vnode. */ if (flags & DOCLOSE) vinvalbuf(vp, V_SAVE, NOCRED, p, 0, INFSLP); /* * If purging an active vnode, it must be closed and * deactivated before being reclaimed. Note that the * VOP_INACTIVE will unlock the vnode */ if (active) { if (flags & DOCLOSE) VOP_CLOSE(vp, FNONBLOCK, NOCRED, p); VOP_INACTIVE(vp, p); } else { /* * Any other processes trying to obtain this lock must first * wait for VXLOCK to clear, then call the new lock operation. */ VOP_UNLOCK(vp); } /* * Reclaim the vnode. */ if (VOP_RECLAIM(vp, p)) panic("vclean: cannot reclaim"); if (active) { vp->v_usecount--; if (vp->v_usecount == 0) { s = splbio(); if (vp->v_holdcnt > 0) panic("vclean: not clean"); vputonfreelist(vp); splx(s); } } cache_purge(vp); /* * Done with purge, notify sleepers of the grim news. */ vp->v_op = &dead_vops; VN_KNOTE(vp, NOTE_REVOKE); vp->v_tag = VT_NON; #ifdef VFSLCKDEBUG vp->v_flag &= ~VLOCKSWORK; #endif mtx_enter(&vnode_mtx); vp->v_lflag &= ~VXLOCK; if (vp->v_lflag & VXWANT) { vp->v_lflag &= ~VXWANT; do_wakeup = 1; } mtx_leave(&vnode_mtx); if (do_wakeup) wakeup(vp); } /* * Recycle an unused vnode to the front of the free list. */ int vrecycle(struct vnode *vp, struct proc *p) { if (vp->v_usecount == 0) { vgonel(vp, p); return (1); } return (0); } /* * Eliminate all activity associated with a vnode * in preparation for reuse. */ void vgone(struct vnode *vp) { struct proc *p = curproc; vgonel(vp, p); } /* * vgone, with struct proc. */ void vgonel(struct vnode *vp, struct proc *p) { struct vnode *vq; struct vnode *vx; int s; KASSERT(vp->v_uvcount == 0); /* * If a vgone (or vclean) is already in progress, * wait until it is done and return. */ mtx_enter(&vnode_mtx); if (vp->v_lflag & VXLOCK) { vp->v_lflag |= VXWANT; msleep_nsec(vp, &vnode_mtx, PINOD, "vgone", INFSLP); mtx_leave(&vnode_mtx); return; } mtx_leave(&vnode_mtx); /* * Clean out the filesystem specific data. */ vclean(vp, DOCLOSE, p); /* * Delete from old mount point vnode list, if on one. */ if (vp->v_mount != NULL) insmntque(vp, NULL); /* * If special device, remove it from special device alias list * if it is on one. */ if ((vp->v_type == VBLK || vp->v_type == VCHR) && vp->v_specinfo != NULL) { if ((vp->v_flag & VALIASED) == 0 && vp->v_type == VCHR && (cdevsw[major(vp->v_rdev)].d_flags & D_CLONE) && (minor(vp->v_rdev) >> CLONE_SHIFT == 0)) { free(vp->v_specbitmap, M_VNODE, CLONE_MAPSZ); } SLIST_REMOVE(vp->v_hashchain, vp, vnode, v_specnext); if (vp->v_flag & VALIASED) { vx = NULL; SLIST_FOREACH(vq, vp->v_hashchain, v_specnext) { if (vq->v_rdev != vp->v_rdev || vq->v_type != vp->v_type) continue; if (vx) break; vx = vq; } if (vx == NULL) panic("missing alias"); if (vq == NULL) vx->v_flag &= ~VALIASED; vp->v_flag &= ~VALIASED; } lf_purgelocks(&vp->v_speclockf); free(vp->v_specinfo, M_VNODE, sizeof(struct specinfo)); vp->v_specinfo = NULL; } /* * If it is on the freelist and not already at the head, * move it to the head of the list. */ vp->v_type = VBAD; /* * Move onto the free list, unless we were called from * getnewvnode and we're not on any free list */ s = splbio(); if (vp->v_usecount == 0 && (vp->v_bioflag & VBIOONFREELIST)) { if (vp->v_holdcnt > 0) panic("vgonel: not clean"); if (TAILQ_FIRST(&vnode_free_list) != vp) { TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist); } } splx(s); } /* * Lookup a vnode by device number. */ int vfinddev(dev_t dev, enum vtype type, struct vnode **vpp) { struct vnode *vp; int rc =0; SLIST_FOREACH(vp, &speclisth[SPECHASH(dev)], v_specnext) { if (dev != vp->v_rdev || type != vp->v_type) continue; *vpp = vp; rc = 1; break; } return (rc); } /* * Revoke all the vnodes corresponding to the specified minor number * range (endpoints inclusive) of the specified major. */ void vdevgone(int maj, int minl, int minh, enum vtype type) { struct vnode *vp; int mn; for (mn = minl; mn <= minh; mn++) if (vfinddev(makedev(maj, mn), type, &vp)) VOP_REVOKE(vp, REVOKEALL); } /* * Calculate the total number of references to a special device. */ int vcount(struct vnode *vp) { struct vnode *vq; int count; loop: if ((vp->v_flag & VALIASED) == 0) return (vp->v_usecount); count = 0; SLIST_FOREACH(vq, vp->v_hashchain, v_specnext) { if (vq->v_rdev != vp->v_rdev || vq->v_type != vp->v_type) continue; /* * Alias, but not in use, so flush it out. */ if (vq->v_usecount == 0 && vq != vp) { vgone(vq); goto loop; } count += vq->v_usecount; } return (count); } #if defined(DEBUG) || defined(DIAGNOSTIC) /* * Print out a description of a vnode. */ static char *typename[] = { "VNON", "VREG", "VDIR", "VBLK", "VCHR", "VLNK", "VSOCK", "VFIFO", "VBAD" }; void vprint(char *label, struct vnode *vp) { char buf[64]; if (label != NULL) printf("%s: ", label); printf("%p, type %s, use %u, write %u, hold %u,", vp, typename[vp->v_type], vp->v_usecount, vp->v_writecount, vp->v_holdcnt); buf[0] = '\0'; if (vp->v_flag & VROOT) strlcat(buf, "|VROOT", sizeof buf); if (vp->v_flag & VTEXT) strlcat(buf, "|VTEXT", sizeof buf); if (vp->v_flag & VSYSTEM) strlcat(buf, "|VSYSTEM", sizeof buf); if (vp->v_lflag & VXLOCK) strlcat(buf, "|VXLOCK", sizeof buf); if (vp->v_lflag & VXWANT) strlcat(buf, "|VXWANT", sizeof buf); if (vp->v_bioflag & VBIOWAIT) strlcat(buf, "|VBIOWAIT", sizeof buf); if (vp->v_bioflag & VBIOONFREELIST) strlcat(buf, "|VBIOONFREELIST", sizeof buf); if (vp->v_bioflag & VBIOONSYNCLIST) strlcat(buf, "|VBIOONSYNCLIST", sizeof buf); if (vp->v_flag & VALIASED) strlcat(buf, "|VALIASED", sizeof buf); if (buf[0] != '\0') printf(" flags (%s)", &buf[1]); if (vp->v_data == NULL) { printf("\n"); } else { printf("\n\t"); VOP_PRINT(vp); } } #endif /* DEBUG || DIAGNOSTIC */ #ifdef DEBUG /* * List all of the locked vnodes in the system. * Called when debugging the kernel. */ void printlockedvnodes(void) { struct mount *mp; struct vnode *vp; printf("Locked vnodes\n"); TAILQ_FOREACH(mp, &mountlist, mnt_list) { if (vfs_busy(mp, VB_READ|VB_NOWAIT)) continue; TAILQ_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) { if (VOP_ISLOCKED(vp)) vprint(NULL, vp); } vfs_unbusy(mp); } } #endif /* * Top level filesystem related information gathering. */ int vfs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { struct vfsconf *vfsp, *tmpvfsp; int ret; /* all sysctl names at this level are at least name and field */ if (namelen < 2) return (ENOTDIR); /* overloaded */ if (name[0] != VFS_GENERIC) { vfsp = vfs_bytypenum(name[0]); if (vfsp == NULL || vfsp->vfc_vfsops->vfs_sysctl == NULL) return (EOPNOTSUPP); return ((*vfsp->vfc_vfsops->vfs_sysctl)(&name[1], namelen - 1, oldp, oldlenp, newp, newlen, p)); } switch (name[1]) { case VFS_MAXTYPENUM: return (sysctl_rdint(oldp, oldlenp, newp, maxvfsconf)); case VFS_CONF: if (namelen < 3) return (ENOTDIR); /* overloaded */ vfsp = vfs_bytypenum(name[2]); if (vfsp == NULL) return (EOPNOTSUPP); /* Make a copy, clear out kernel pointers */ tmpvfsp = malloc(sizeof(*tmpvfsp), M_TEMP, M_WAITOK|M_ZERO); memcpy(tmpvfsp, vfsp, sizeof(*tmpvfsp)); tmpvfsp->vfc_vfsops = NULL; ret = sysctl_rdstruct(oldp, oldlenp, newp, tmpvfsp, sizeof(struct vfsconf)); free(tmpvfsp, M_TEMP, sizeof(*tmpvfsp)); return (ret); case VFS_BCACHESTAT: /* buffer cache statistics */ ret = sysctl_rdstruct(oldp, oldlenp, newp, &bcstats, sizeof(struct bcachestats)); return(ret); } return (EOPNOTSUPP); } /* * Check to see if a filesystem is mounted on a block device. */ int vfs_mountedon(struct vnode *vp) { struct vnode *vq; int error = 0; if (vp->v_specmountpoint != NULL) return (EBUSY); if (vp->v_flag & VALIASED) { SLIST_FOREACH(vq, vp->v_hashchain, v_specnext) { if (vq->v_rdev != vp->v_rdev || vq->v_type != vp->v_type) continue; if (vq->v_specmountpoint != NULL) { error = EBUSY; break; } } } return (error); } #ifdef NFSSERVER /* * Build hash lists of net addresses and hang them off the mount point. * Called by vfs_export() to set up the lists of export addresses. */ int vfs_hang_addrlist(struct mount *mp, struct netexport *nep, struct export_args *argp) { struct netcred *np; struct radix_node_head *rnh; int nplen, i; struct radix_node *rn; struct sockaddr *saddr, *smask = NULL; int error; if (argp->ex_addrlen == 0) { if (mp->mnt_flag & MNT_DEFEXPORTED) return (EPERM); np = &nep->ne_defexported; /* fill in the kernel's ucred from userspace's xucred */ if ((error = crfromxucred(&np->netc_anon, &argp->ex_anon))) return (error); mp->mnt_flag |= MNT_DEFEXPORTED; goto finish; } if (argp->ex_addrlen > MLEN || argp->ex_masklen > MLEN || argp->ex_addrlen < 0 || argp->ex_masklen < 0) return (EINVAL); nplen = sizeof(struct netcred) + argp->ex_addrlen + argp->ex_masklen; np = (struct netcred *)malloc(nplen, M_NETADDR, M_WAITOK|M_ZERO); np->netc_len = nplen; saddr = (struct sockaddr *)(np + 1); error = copyin(argp->ex_addr, saddr, argp->ex_addrlen); if (error) goto out; if (saddr->sa_len > argp->ex_addrlen) saddr->sa_len = argp->ex_addrlen; if (argp->ex_masklen) { smask = (struct sockaddr *)((caddr_t)saddr + argp->ex_addrlen); error = copyin(argp->ex_mask, smask, argp->ex_masklen); if (error) goto out; if (smask->sa_len > argp->ex_masklen) smask->sa_len = argp->ex_masklen; } /* fill in the kernel's ucred from userspace's xucred */ if ((error = crfromxucred(&np->netc_anon, &argp->ex_anon))) goto out; i = saddr->sa_family; switch (i) { case AF_INET: if ((rnh = nep->ne_rtable_inet) == NULL) { if (!rn_inithead((void **)&nep->ne_rtable_inet, offsetof(struct sockaddr_in, sin_addr))) { error = ENOBUFS; goto out; } rnh = nep->ne_rtable_inet; } break; default: error = EINVAL; goto out; } rn = rn_addroute(saddr, smask, rnh, np->netc_rnodes, 0); if (rn == NULL || np != (struct netcred *)rn) { /* already exists */ error = EPERM; goto out; } finish: np->netc_exflags = argp->ex_flags; return (0); out: free(np, M_NETADDR, np->netc_len); return (error); } int vfs_free_netcred(struct radix_node *rn, void *w, u_int id) { struct radix_node_head *rnh = (struct radix_node_head *)w; struct netcred * np = (struct netcred *)rn; rn_delete(rn->rn_key, rn->rn_mask, rnh, NULL); free(np, M_NETADDR, np->netc_len); return (0); } /* * Free the net address hash lists that are hanging off the mount points. */ void vfs_free_addrlist(struct netexport *nep) { struct radix_node_head *rnh; if ((rnh = nep->ne_rtable_inet) != NULL) { rn_walktree(rnh, vfs_free_netcred, rnh); free(rnh, M_RTABLE, sizeof(*rnh)); nep->ne_rtable_inet = NULL; } } #endif /* NFSSERVER */ int vfs_export(struct mount *mp, struct netexport *nep, struct export_args *argp) { #ifdef NFSSERVER int error; if (argp->ex_flags & MNT_DELEXPORT) { vfs_free_addrlist(nep); mp->mnt_flag &= ~(MNT_EXPORTED | MNT_DEFEXPORTED); } if (argp->ex_flags & MNT_EXPORTED) { if ((error = vfs_hang_addrlist(mp, nep, argp)) != 0) return (error); mp->mnt_flag |= MNT_EXPORTED; } return (0); #else return (ENOTSUP); #endif /* NFSSERVER */ } struct netcred * vfs_export_lookup(struct mount *mp, struct netexport *nep, struct mbuf *nam) { #ifdef NFSSERVER struct netcred *np; struct radix_node_head *rnh; struct sockaddr *saddr; np = NULL; if (mp->mnt_flag & MNT_EXPORTED) { /* * Lookup in the export list first. */ if (nam != NULL) { saddr = mtod(nam, struct sockaddr *); switch(saddr->sa_family) { case AF_INET: rnh = nep->ne_rtable_inet; break; default: rnh = NULL; break; } if (rnh != NULL) np = (struct netcred *)rn_match(saddr, rnh); } /* * If no address match, use the default if it exists. */ if (np == NULL && mp->mnt_flag & MNT_DEFEXPORTED) np = &nep->ne_defexported; } return (np); #else return (NULL); #endif /* NFSSERVER */ } /* * Do the usual access checking. * file_mode, uid and gid are from the vnode in question, * while acc_mode and cred are from the VOP_ACCESS parameter list */ int vaccess(enum vtype type, mode_t file_mode, uid_t uid, gid_t gid, mode_t acc_mode, struct ucred *cred) { mode_t mask; /* User id 0 always gets read/write access. */ if (cred->cr_uid == 0) { /* For VEXEC, at least one of the execute bits must be set. */ if ((acc_mode & VEXEC) && type != VDIR && (file_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0) return EACCES; return 0; } mask = 0; /* Otherwise, check the owner. */ if (cred->cr_uid == uid) { if (acc_mode & VEXEC) mask |= S_IXUSR; if (acc_mode & VREAD) mask |= S_IRUSR; if (acc_mode & VWRITE) mask |= S_IWUSR; return (file_mode & mask) == mask ? 0 : EACCES; } /* Otherwise, check the groups. */ if (groupmember(gid, cred)) { if (acc_mode & VEXEC) mask |= S_IXGRP; if (acc_mode & VREAD) mask |= S_IRGRP; if (acc_mode & VWRITE) mask |= S_IWGRP; return (file_mode & mask) == mask ? 0 : EACCES; } /* Otherwise, check everyone else. */ if (acc_mode & VEXEC) mask |= S_IXOTH; if (acc_mode & VREAD) mask |= S_IROTH; if (acc_mode & VWRITE) mask |= S_IWOTH; return (file_mode & mask) == mask ? 0 : EACCES; } int vnoperm(struct vnode *vp) { if (vp->v_flag & VROOT || vp->v_mount == NULL) return 0; return (vp->v_mount->mnt_flag & MNT_NOPERM); } struct rwlock vfs_stall_lock = RWLOCK_INITIALIZER("vfs_stall"); unsigned int vfs_stalling = 0; int vfs_stall(struct proc *p, int stall) { struct mount *mp; int allerror = 0, error; if (stall) { atomic_inc_int(&vfs_stalling); rw_enter_write(&vfs_stall_lock); } /* * The loop variable mp is protected by vfs_busy() so that it cannot * be unmounted while VFS_SYNC() sleeps. Traverse forward to keep the * lock order consistent with dounmount(). */ TAILQ_FOREACH(mp, &mountlist, mnt_list) { if (stall) { error = vfs_busy(mp, VB_WRITE|VB_WAIT|VB_DUPOK); if (error) { printf("%s: busy\n", mp->mnt_stat.f_mntonname); allerror = error; continue; } uvm_vnp_sync(mp); error = VFS_SYNC(mp, MNT_WAIT, stall, p->p_ucred, p); if (error) { printf("%s: failed to sync\n", mp->mnt_stat.f_mntonname); vfs_unbusy(mp); allerror = error; continue; } mp->mnt_flag |= MNT_STALLED; } else { if (mp->mnt_flag & MNT_STALLED) { vfs_unbusy(mp); mp->mnt_flag &= ~MNT_STALLED; } } } if (!stall) { rw_exit_write(&vfs_stall_lock); atomic_dec_int(&vfs_stalling); } return (allerror); } void vfs_stall_barrier(void) { if (__predict_false(vfs_stalling)) { rw_enter_read(&vfs_stall_lock); rw_exit_read(&vfs_stall_lock); } } /* * Unmount all file systems. * We traverse the list in reverse order under the assumption that doing so * will avoid needing to worry about dependencies. */ void vfs_unmountall(void) { struct mount *mp, *nmp; int allerror, error, again = 1; retry: allerror = 0; TAILQ_FOREACH_REVERSE_SAFE(mp, &mountlist, mntlist, mnt_list, nmp) { if (vfs_busy(mp, VB_WRITE|VB_NOWAIT)) continue; /* XXX Here is a race, the next pointer is not locked. */ if ((error = dounmount(mp, MNT_FORCE, curproc)) != 0) { printf("unmount of %s failed with error %d\n", mp->mnt_stat.f_mntonname, error); allerror = 1; } } if (allerror) { printf("WARNING: some file systems would not unmount\n"); if (again) { printf("retrying\n"); again = 0; goto retry; } } } /* * Sync and unmount file systems before shutting down. */ void vfs_shutdown(struct proc *p) { #ifdef ACCOUNTING acct_shutdown(); #endif printf("syncing disks..."); if (panicstr == NULL) { /* Sync before unmount, in case we hang on something. */ sys_sync(p, NULL, NULL); vfs_unmountall(); } #if NSOFTRAID > 0 sr_quiesce(); #endif if (vfs_syncwait(p, 1)) printf(" giving up\n"); else printf(" done\n"); } /* * perform sync() operation and wait for buffers to flush. */ int vfs_syncwait(struct proc *p, int verbose) { struct buf *bp; int iter, nbusy, dcount, s; #ifdef MULTIPROCESSOR int hold_count; #endif sys_sync(p, NULL, NULL); /* Wait for sync to finish. */ dcount = 10000; for (iter = 0; iter < 20; iter++) { nbusy = 0; LIST_FOREACH(bp, &bufhead, b_list) { if ((bp->b_flags & (B_BUSY|B_INVAL|B_READ)) == B_BUSY) nbusy++; /* * With soft updates, some buffers that are * written will be remarked as dirty until other * buffers are written. * * XXX here be dragons. this should really go away * but should be carefully made to go away on it's * own with testing.. XXX */ if (bp->b_flags & B_DELWRI) { s = splbio(); bremfree(bp); buf_acquire(bp); splx(s); nbusy++; bawrite(bp); if (dcount-- <= 0) { if (verbose) printf("softdep "); return 1; } } } if (nbusy == 0) break; if (verbose) printf("%d ", nbusy); #ifdef MULTIPROCESSOR if (_kernel_lock_held()) hold_count = __mp_release_all(&kernel_lock); else hold_count = 0; #endif DELAY(40000 * iter); #ifdef MULTIPROCESSOR if (hold_count) __mp_acquire_count(&kernel_lock, hold_count); #endif } return nbusy; } /* * posix file system related system variables. */ int fs_posix_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { /* all sysctl names at this level are terminal */ if (namelen != 1) return (ENOTDIR); switch (name[0]) { case FS_POSIX_SETUID: return (sysctl_securelevel_int(oldp, oldlenp, newp, newlen, &suid_clear)); default: return (EOPNOTSUPP); } /* NOTREACHED */ } /* * file system related system variables. */ int fs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { sysctlfn *fn; switch (name[0]) { case FS_POSIX: fn = fs_posix_sysctl; break; default: return (EOPNOTSUPP); } return (*fn)(name + 1, namelen - 1, oldp, oldlenp, newp, newlen, p); } /* * Routines dealing with vnodes and buffers */ /* * Wait for all outstanding I/Os to complete * * Manipulates v_numoutput. Must be called at splbio() */ int vwaitforio(struct vnode *vp, int slpflag, char *wmesg, uint64_t timeo) { int error = 0; splassert(IPL_BIO); while (vp->v_numoutput) { vp->v_bioflag |= VBIOWAIT; error = tsleep_nsec(&vp->v_numoutput, slpflag | (PRIBIO + 1), wmesg, timeo); if (error) break; } return (error); } /* * Update outstanding I/O count and do wakeup if requested. * * Manipulates v_numoutput. Must be called at splbio() */ void vwakeup(struct vnode *vp) { splassert(IPL_BIO); if (vp != NULL) { if (vp->v_numoutput-- == 0) panic("vwakeup: neg numoutput"); if ((vp->v_bioflag & VBIOWAIT) && vp->v_numoutput == 0) { vp->v_bioflag &= ~VBIOWAIT; wakeup(&vp->v_numoutput); } } } /* * Flush out and invalidate all buffers associated with a vnode. * Called with the underlying object locked. */ int vinvalbuf(struct vnode *vp, int flags, struct ucred *cred, struct proc *p, int slpflag, uint64_t slptimeo) { struct buf *bp; struct buf *nbp, *blist; int s, error; #ifdef VFSLCKDEBUG if ((vp->v_flag & VLOCKSWORK) && !VOP_ISLOCKED(vp)) panic("%s: vp isn't locked, vp %p", __func__, vp); #endif if (flags & V_SAVE) { s = splbio(); vwaitforio(vp, 0, "vinvalbuf", INFSLP); if (!LIST_EMPTY(&vp->v_dirtyblkhd)) { splx(s); if ((error = VOP_FSYNC(vp, cred, MNT_WAIT, p)) != 0) return (error); s = splbio(); if (vp->v_numoutput > 0 || !LIST_EMPTY(&vp->v_dirtyblkhd)) panic("%s: dirty bufs, vp %p", __func__, vp); } splx(s); } loop: s = splbio(); for (;;) { int count = 0; if ((blist = LIST_FIRST(&vp->v_cleanblkhd)) && (flags & V_SAVEMETA)) while (blist && blist->b_lblkno < 0) blist = LIST_NEXT(blist, b_vnbufs); if (blist == NULL && (blist = LIST_FIRST(&vp->v_dirtyblkhd)) && (flags & V_SAVEMETA)) while (blist && blist->b_lblkno < 0) blist = LIST_NEXT(blist, b_vnbufs); if (!blist) break; for (bp = blist; bp; bp = nbp) { nbp = LIST_NEXT(bp, b_vnbufs); if (flags & V_SAVEMETA && bp->b_lblkno < 0) continue; if (bp->b_flags & B_BUSY) { bp->b_flags |= B_WANTED; error = tsleep_nsec(bp, slpflag | (PRIBIO + 1), "vinvalbuf", slptimeo); if (error) { splx(s); return (error); } break; } bremfree(bp); /* * XXX Since there are no node locks for NFS, I believe * there is a slight chance that a delayed write will * occur while sleeping just above, so check for it. */ if ((bp->b_flags & B_DELWRI) && (flags & V_SAVE)) { buf_acquire(bp); splx(s); (void) VOP_BWRITE(bp); goto loop; } buf_acquire_nomap(bp); bp->b_flags |= B_INVAL; brelse(bp); count++; /* * XXX Temporary workaround XXX * * If this is a gigantisch vnode and we are * trashing a ton of buffers, drop the lock * and yield every so often. The longer term * fix is to add a separate list for these * invalid buffers so we don't have to do the * work to free these here. */ if (count > 100) { splx(s); sched_pause(yield); goto loop; } } } if (!(flags & V_SAVEMETA) && (!LIST_EMPTY(&vp->v_dirtyblkhd) || !LIST_EMPTY(&vp->v_cleanblkhd))) panic("%s: flush failed, vp %p", __func__, vp); splx(s); return (0); } void vflushbuf(struct vnode *vp, int sync) { struct buf *bp, *nbp; int s; loop: s = splbio(); LIST_FOREACH_SAFE(bp, &vp->v_dirtyblkhd, b_vnbufs, nbp) { if ((bp->b_flags & B_BUSY)) continue; if ((bp->b_flags & B_DELWRI) == 0) panic("vflushbuf: not dirty"); bremfree(bp); buf_acquire(bp); splx(s); /* * Wait for I/O associated with indirect blocks to complete, * since there is no way to quickly wait for them below. */ if (bp->b_vp == vp || sync == 0) (void) bawrite(bp); else (void) bwrite(bp); goto loop; } if (sync == 0) { splx(s); return; } vwaitforio(vp, 0, "vflushbuf", INFSLP); if (!LIST_EMPTY(&vp->v_dirtyblkhd)) { splx(s); #ifdef DIAGNOSTIC vprint("vflushbuf: dirty", vp); #endif goto loop; } splx(s); } /* * Associate a buffer with a vnode. * * Manipulates buffer vnode queues. Must be called at splbio(). */ void bgetvp(struct vnode *vp, struct buf *bp) { splassert(IPL_BIO); if (bp->b_vp) panic("bgetvp: not free"); vhold(vp); bp->b_vp = vp; if (vp->v_type == VBLK || vp->v_type == VCHR) bp->b_dev = vp->v_rdev; else bp->b_dev = NODEV; /* * Insert onto list for new vnode. */ bufinsvn(bp, &vp->v_cleanblkhd); } /* * Disassociate a buffer from a vnode. * * Manipulates vnode buffer queues. Must be called at splbio(). */ void brelvp(struct buf *bp) { struct vnode *vp; splassert(IPL_BIO); if ((vp = bp->b_vp) == (struct vnode *) 0) panic("brelvp: NULL"); /* * Delete from old vnode list, if on one. */ if (LIST_NEXT(bp, b_vnbufs) != NOLIST) bufremvn(bp); if ((vp->v_bioflag & VBIOONSYNCLIST) && LIST_EMPTY(&vp->v_dirtyblkhd)) { vp->v_bioflag &= ~VBIOONSYNCLIST; LIST_REMOVE(vp, v_synclist); } bp->b_vp = NULL; vdrop(vp); } /* * Replaces the current vnode associated with the buffer, if any, * with a new vnode. * * If an output I/O is pending on the buffer, the old vnode * I/O count is adjusted. * * Ignores vnode buffer queues. Must be called at splbio(). */ void buf_replacevnode(struct buf *bp, struct vnode *newvp) { struct vnode *oldvp = bp->b_vp; splassert(IPL_BIO); if (oldvp) brelvp(bp); if ((bp->b_flags & (B_READ | B_DONE)) == 0) { newvp->v_numoutput++; /* put it on swapdev */ vwakeup(oldvp); } bgetvp(newvp, bp); bufremvn(bp); } /* * Used to assign buffers to the appropriate clean or dirty list on * the vnode and to add newly dirty vnodes to the appropriate * filesystem syncer list. * * Manipulates vnode buffer queues. Must be called at splbio(). */ void reassignbuf(struct buf *bp) { struct buflists *listheadp; int delay; struct vnode *vp = bp->b_vp; splassert(IPL_BIO); /* * Delete from old vnode list, if on one. */ if (LIST_NEXT(bp, b_vnbufs) != NOLIST) bufremvn(bp); /* * If dirty, put on list of dirty buffers; * otherwise insert onto list of clean buffers. */ if ((bp->b_flags & B_DELWRI) == 0) { listheadp = &vp->v_cleanblkhd; if ((vp->v_bioflag & VBIOONSYNCLIST) && LIST_EMPTY(&vp->v_dirtyblkhd)) { vp->v_bioflag &= ~VBIOONSYNCLIST; LIST_REMOVE(vp, v_synclist); } } else { listheadp = &vp->v_dirtyblkhd; if ((vp->v_bioflag & VBIOONSYNCLIST) == 0) { switch (vp->v_type) { case VDIR: delay = syncdelay / 2; break; case VBLK: if (vp->v_specmountpoint != NULL) { delay = syncdelay / 3; break; } /* FALLTHROUGH */ default: delay = syncdelay; } vn_syncer_add_to_worklist(vp, delay); } } bufinsvn(bp, listheadp); } /* * Check if vnode represents a disk device */ int vn_isdisk(struct vnode *vp, int *errp) { if (vp->v_type != VBLK && vp->v_type != VCHR) return (0); return (1); } #ifdef DDB #include <machine/db_machdep.h> #include <ddb/db_interface.h> void vfs_buf_print(void *b, int full, int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2)))) { struct buf *bp = b; (*pr)(" vp %p lblkno 0x%llx blkno 0x%llx dev 0x%x\n" " proc %p error %d flags %lb\n", bp->b_vp, (int64_t)bp->b_lblkno, (int64_t)bp->b_blkno, bp->b_dev, bp->b_proc, bp->b_error, bp->b_flags, B_BITS); (*pr)(" bufsize 0x%lx bcount 0x%lx resid 0x%lx\n" " data %p saveaddr %p iodone %p\n", bp->b_bufsize, bp->b_bcount, (long)bp->b_resid, bp->b_data, bp->b_saveaddr, bp->b_iodone); (*pr)(" dirty {off 0x%x end 0x%x} valid {off 0x%x end 0x%x}\n", bp->b_dirtyoff, bp->b_dirtyend, bp->b_validoff, bp->b_validend); } const char *vtypes[] = { VTYPE_NAMES }; const char *vtags[] = { VTAG_NAMES }; void vfs_vnode_print(void *v, int full, int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2)))) { struct vnode *vp = v; (*pr)("tag %s(%d) type %s(%d) mount %p typedata %p\n", (u_int)vp->v_tag >= nitems(vtags)? "<unk>":vtags[vp->v_tag], vp->v_tag, (u_int)vp->v_type >= nitems(vtypes)? "<unk>":vtypes[vp->v_type], vp->v_type, vp->v_mount, vp->v_mountedhere); (*pr)("data %p usecount %d writecount %d holdcnt %d numoutput %d\n", vp->v_data, vp->v_usecount, vp->v_writecount, vp->v_holdcnt, vp->v_numoutput); /* uvm_object_printit(&vp->v_uobj, full, pr); */ if (full) { struct buf *bp; (*pr)("clean bufs:\n"); LIST_FOREACH(bp, &vp->v_cleanblkhd, b_vnbufs) { (*pr)(" bp %p\n", bp); vfs_buf_print(bp, full, pr); } (*pr)("dirty bufs:\n"); LIST_FOREACH(bp, &vp->v_dirtyblkhd, b_vnbufs) { (*pr)(" bp %p\n", bp); vfs_buf_print(bp, full, pr); } } } void vfs_mount_print(struct mount *mp, int full, int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2)))) { struct vfsconf *vfc = mp->mnt_vfc; struct vnode *vp; int cnt; (*pr)("flags %b\nvnodecovered %p syncer %p data %p\n", mp->mnt_flag, MNT_BITS, mp->mnt_vnodecovered, mp->mnt_syncer, mp->mnt_data); (*pr)("vfsconf: ops %p name \"%s\" num %d ref %u flags 0x%x\n", vfc->vfc_vfsops, vfc->vfc_name, vfc->vfc_typenum, vfc->vfc_refcount, vfc->vfc_flags); (*pr)("statvfs cache: bsize %x iosize %x\n" "blocks %llu free %llu avail %lld\n", mp->mnt_stat.f_bsize, mp->mnt_stat.f_iosize, mp->mnt_stat.f_blocks, mp->mnt_stat.f_bfree, mp->mnt_stat.f_bavail); (*pr)(" files %llu ffiles %llu favail %lld\n", mp->mnt_stat.f_files, mp->mnt_stat.f_ffree, mp->mnt_stat.f_favail); (*pr)(" f_fsidx {0x%x, 0x%x} owner %u ctime 0x%llx\n", mp->mnt_stat.f_fsid.val[0], mp->mnt_stat.f_fsid.val[1], mp->mnt_stat.f_owner, mp->mnt_stat.f_ctime); (*pr)(" syncwrites %llu asyncwrites = %llu\n", mp->mnt_stat.f_syncwrites, mp->mnt_stat.f_asyncwrites); (*pr)(" syncreads %llu asyncreads = %llu\n", mp->mnt_stat.f_syncreads, mp->mnt_stat.f_asyncreads); (*pr)(" fstype \"%s\" mnton \"%s\" mntfrom \"%s\" mntspec \"%s\"\n", mp->mnt_stat.f_fstypename, mp->mnt_stat.f_mntonname, mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntfromspec); (*pr)("locked vnodes:"); /* XXX would take mountlist lock, except ddb has no context */ cnt = 0; TAILQ_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) { if (VOP_ISLOCKED(vp)) { if (cnt == 0) (*pr)("\n %p", vp); else if ((cnt % (72 / (sizeof(void *) * 2 + 4))) == 0) (*pr)(",\n %p", vp); else (*pr)(", %p", vp); cnt++; } } (*pr)("\n"); if (full) { (*pr)("all vnodes:"); /* XXX would take mountlist lock, except ddb has no context */ cnt = 0; TAILQ_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) { if (cnt == 0) (*pr)("\n %p", vp); else if ((cnt % (72 / (sizeof(void *) * 2 + 4))) == 0) (*pr)(",\n %p", vp); else (*pr)(", %p", vp); cnt++; } (*pr)("\n"); } } #endif /* DDB */ void copy_statfs_info(struct statfs *sbp, const struct mount *mp) { const struct statfs *mbp; strncpy(sbp->f_fstypename, mp->mnt_vfc->vfc_name, MFSNAMELEN); if (sbp == (mbp = &mp->mnt_stat)) return; sbp->f_fsid = mbp->f_fsid; sbp->f_owner = mbp->f_owner; sbp->f_flags = mbp->f_flags; sbp->f_syncwrites = mbp->f_syncwrites; sbp->f_asyncwrites = mbp->f_asyncwrites; sbp->f_syncreads = mbp->f_syncreads; sbp->f_asyncreads = mbp->f_asyncreads; sbp->f_namemax = mbp->f_namemax; memcpy(sbp->f_mntonname, mp->mnt_stat.f_mntonname, MNAMELEN); memcpy(sbp->f_mntfromname, mp->mnt_stat.f_mntfromname, MNAMELEN); memcpy(sbp->f_mntfromspec, mp->mnt_stat.f_mntfromspec, MNAMELEN); memcpy(&sbp->mount_info, &mp->mnt_stat.mount_info, sizeof(union mount_info)); }
61 48 15 15 20 39 30 63 63 63 49 16 11 5 63 12 12 12 12 6 8 2 6 63 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 /* $OpenBSD: in6_cksum.c,v 1.18 2019/04/22 22:47:49 bluhm Exp $ */ /* $KAME: in6_cksum.c,v 1.10 2000/12/03 00:53:59 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 1988, 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93 */ #include <sys/param.h> #include <sys/mbuf.h> #include <sys/systm.h> #include <netinet/in.h> #include <netinet/ip6.h> /* * Checksum routine for Internet Protocol family headers (Portable Version). * * This routine is very heavily used in the network * code and should be modified for each CPU to be as fast as possible. */ #define ADDCARRY(x) (x > 65535 ? x -= 65535 : x) #define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);} /* * m MUST contain a continuous IP6 header. * off is a offset where TCP/UDP/ICMP6 header starts. * len is a total length of a transport segment. * (e.g. TCP header + TCP payload) */ int in6_cksum(struct mbuf *m, uint8_t nxt, uint32_t off, uint32_t len) { uint16_t *w; int sum = 0; int mlen = 0; int byte_swapped = 0; struct ip6_hdr *ip6; union { uint16_t phs[4]; struct { uint32_t ph_len; uint8_t ph_zero[3]; uint8_t ph_nxt; } ph __packed; } uph; union { uint8_t c[2]; uint16_t s; } s_util; union { uint16_t s[2]; uint32_t l; } l_util; /* sanity check */ if (m->m_pkthdr.len < off + len) { panic("%s: mbuf len (%d) < off+len (%d+%d)", __func__, m->m_pkthdr.len, off, len); } /* Skip pseudo-header if nxt == 0. */ if (nxt == 0) goto skip_phdr; bzero(&uph, sizeof(uph)); /* * First create IP6 pseudo header and calculate a summary. */ ip6 = mtod(m, struct ip6_hdr *); w = (uint16_t *)&ip6->ip6_src; uph.ph.ph_len = htonl(len); uph.ph.ph_nxt = nxt; /* IPv6 source address */ sum += w[0]; if (!IN6_IS_SCOPE_EMBED(&ip6->ip6_src)) sum += w[1]; sum += w[2]; sum += w[3]; sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; /* IPv6 destination address */ sum += w[8]; if (!IN6_IS_SCOPE_EMBED(&ip6->ip6_dst)) sum += w[9]; sum += w[10]; sum += w[11]; sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15]; /* Payload length and upper layer identifier */ sum += uph.phs[0]; sum += uph.phs[1]; sum += uph.phs[2]; sum += uph.phs[3]; skip_phdr: /* * Secondly calculate a summary of the first mbuf excluding offset. */ while (m != NULL && off > 0) { if (m->m_len <= off) off -= m->m_len; else break; m = m->m_next; } if (m == NULL) { if (off) panic("%s: out of header, off %u", __func__, off); goto end; } w = (uint16_t *)(mtod(m, uint8_t *) + off); mlen = m->m_len - off; if (len < mlen) mlen = len; len -= mlen; /* * Force to even boundary. */ if ((1 & (long) w) && (mlen > 0)) { REDUCE; sum <<= 8; s_util.c[0] = *(uint8_t *)w; w = (uint16_t *)((uint8_t *)w + 1); mlen--; byte_swapped = 1; } /* * Unroll the loop to make overhead from * branches &c small. */ while ((mlen -= 32) >= 0) { sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11]; sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15]; w += 16; } mlen += 32; while ((mlen -= 8) >= 0) { sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; w += 4; } mlen += 8; if (mlen == 0 && byte_swapped == 0) goto next; REDUCE; while ((mlen -= 2) >= 0) { sum += *w++; } if (byte_swapped) { REDUCE; sum <<= 8; byte_swapped = 0; if (mlen == -1) { s_util.c[1] = *(uint8_t *)w; sum += s_util.s; mlen = 0; } else mlen = -1; } else if (mlen == -1) s_util.c[0] = *(uint8_t *)w; next: m = m->m_next; /* * Lastly calculate a summary of the rest of mbufs. */ for (;m && len; m = m->m_next) { if (m->m_len == 0) continue; w = mtod(m, uint16_t *); if (mlen == -1) { /* * The first byte of this mbuf is the continuation * of a word spanning between this mbuf and the * last mbuf. * * s_util.c[0] is already saved when scanning previous * mbuf. */ s_util.c[1] = *(uint8_t *)w; sum += s_util.s; w = (uint16_t *)((uint8_t *)w + 1); mlen = m->m_len - 1; len--; } else mlen = m->m_len; if (len < mlen) mlen = len; len -= mlen; /* * Force to even boundary. */ if ((1 & (long) w) && (mlen > 0)) { REDUCE; sum <<= 8; s_util.c[0] = *(uint8_t *)w; w = (uint16_t *)((uint8_t *)w + 1); mlen--; byte_swapped = 1; } /* * Unroll the loop to make overhead from * branches &c small. */ while ((mlen -= 32) >= 0) { sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11]; sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15]; w += 16; } mlen += 32; while ((mlen -= 8) >= 0) { sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; w += 4; } mlen += 8; if (mlen == 0 && byte_swapped == 0) continue; REDUCE; while ((mlen -= 2) >= 0) { sum += *w++; } if (byte_swapped) { REDUCE; sum <<= 8; byte_swapped = 0; if (mlen == -1) { s_util.c[1] = *(uint8_t *)w; sum += s_util.s; mlen = 0; } else mlen = -1; } else if (mlen == -1) s_util.c[0] = *(uint8_t *)w; } end: if (len) panic("%s: out of data, len %u", __func__, len); if (mlen == -1) { /* The last mbuf has odd # of bytes. Follow the standard (the odd byte may be shifted left by 8 bits or not as determined by endian-ness of the machine) */ s_util.c[1] = 0; sum += s_util.s; } REDUCE; return (~sum & 0xffff); }
4 41 39 4 2 37 1 30 8 8 28 28 4 3 23 43 6 1 2 4 3 3 1 36 26 1 25 196 26 194 38 120 121 52 88 85 59 30 1 1 28 21 16 3 13 1 1 1 11 1 1 10 3 9 3 4 4 1 186 3 6 15 2 13 8 2 2 165 165 166 2 165 164 2 7 161 3 11 6 3 8 10 7 9 6 3 15 6 2 2 11 2 8 7 9 2 7 3 4 6 28 1 10 12 6 34 115 1 1 2 1 85 19 1 1 1 1 1 1 1 2 1 97 6 8 3 99 3 38 62 22 1 62 21 1 26 21 26 26 26 1 28 27 29 1 28 1 1 26 26 26 1 26 26 26 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 /* $OpenBSD: tty_pty.c,v 1.114 2022/09/02 07:37:57 deraadt Exp $ */ /* $NetBSD: tty_pty.c,v 1.33.4.1 1996/06/02 09:08:11 mrg Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)tty_pty.c 8.4 (Berkeley) 2/20/95 */ /* * Pseudo-teletype Driver * (Actually two drivers, requiring two entries in 'cdevsw') */ #include <sys/param.h> #include <sys/systm.h> #include <sys/namei.h> #include <sys/mount.h> #include <sys/ioctl.h> #include <sys/proc.h> #include <sys/tty.h> #include <sys/fcntl.h> #include <sys/file.h> #include <sys/filedesc.h> #include <sys/uio.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/vnode.h> #include <sys/signalvar.h> #include <sys/conf.h> #include <sys/stat.h> #include <sys/sysctl.h> #include <sys/pledge.h> #include <sys/rwlock.h> #define BUFSIZ 100 /* Chunk size iomoved to/from user */ /* * pts == /dev/tty[p-zP-T][0-9a-zA-Z] * ptc == /dev/pty[p-zP-T][0-9a-zA-Z] */ /* XXX this needs to come from somewhere sane, and work with MAKEDEV */ #define TTY_LETTERS "pqrstuvwxyzPQRST" #define TTY_SUFFIX "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" static int pts_major; struct pt_softc { struct tty *pt_tty; int pt_flags; struct selinfo pt_selr, pt_selw; u_char pt_send; u_char pt_ucntl; char pty_pn[11]; char pty_sn[11]; }; #define NPTY_MIN 8 /* number of initial ptys */ #define NPTY_MAX 992 /* maximum number of ptys supported */ static struct pt_softc **pt_softc = NULL; /* pty array */ static int npty = 0; /* size of pty array */ static int maxptys = NPTY_MAX; /* maximum number of ptys */ /* for pty array */ struct rwlock pt_softc_lock = RWLOCK_INITIALIZER("ptarrlk"); #define PF_PKT 0x08 /* packet mode */ #define PF_STOPPED 0x10 /* user told stopped */ #define PF_REMOTE 0x20 /* remote and flow controlled input */ #define PF_NOSTOP 0x40 #define PF_UCNTL 0x80 /* user control mode */ void ptyattach(int); void ptcwakeup(struct tty *, int); struct tty *ptytty(dev_t); void ptsstart(struct tty *); int sysctl_pty(int *, u_int, void *, size_t *, void *, size_t); void filt_ptcrdetach(struct knote *); int filt_ptcread(struct knote *, long); void filt_ptcwdetach(struct knote *); int filt_ptcwrite(struct knote *, long); int filt_ptcexcept(struct knote *, long); static struct pt_softc **ptyarralloc(int); static int check_pty(int); static gid_t tty_gid = TTY_GID; void ptydevname(int, struct pt_softc *); dev_t pty_getfree(void); void ptmattach(int); int ptmopen(dev_t, int, int, struct proc *); int ptmclose(dev_t, int, int, struct proc *); int ptmioctl(dev_t, u_long, caddr_t, int, struct proc *p); static int ptm_vn_open(struct nameidata *); void ptydevname(int minor, struct pt_softc *pti) { char buf[11] = "/dev/XtyXX"; int i, j; i = minor / (sizeof(TTY_SUFFIX) - 1); j = minor % (sizeof(TTY_SUFFIX) - 1); if (i >= sizeof(TTY_LETTERS) - 1) { pti->pty_pn[0] = '\0'; pti->pty_sn[0] = '\0'; return; } buf[5] = 'p'; buf[8] = TTY_LETTERS[i]; buf[9] = TTY_SUFFIX[j]; memcpy(pti->pty_pn, buf, sizeof(buf)); buf[5] = 't'; memcpy(pti->pty_sn, buf, sizeof(buf)); } /* * Allocate and zero array of nelem elements. */ struct pt_softc ** ptyarralloc(int nelem) { struct pt_softc **pt; pt = mallocarray(nelem, sizeof(struct pt_softc *), M_DEVBUF, M_WAITOK|M_ZERO); return pt; } /* * Check if the minor is correct and ensure necessary structures * are properly allocated. */ int check_pty(int dev) { struct pt_softc *pti; int minor = minor(dev); rw_enter_write(&pt_softc_lock); if (minor >= npty) { struct pt_softc **newpt; int newnpty; /* check if the requested pty can be granted */ if (minor >= maxptys) goto limit_reached; /* grow pty array by powers of two, up to maxptys */ for (newnpty = npty; newnpty <= minor; newnpty *= 2) ; if (newnpty > maxptys) newnpty = maxptys; newpt = ptyarralloc(newnpty); memcpy(newpt, pt_softc, npty * sizeof(struct pt_softc *)); free(pt_softc, M_DEVBUF, npty * sizeof(struct pt_softc *)); pt_softc = newpt; npty = newnpty; } /* * If the entry is not yet allocated, allocate one. */ if (!pt_softc[minor]) { pti = malloc(sizeof(struct pt_softc), M_DEVBUF, M_WAITOK|M_ZERO); pti->pt_tty = ttymalloc(1000000); pti->pt_tty->t_dev = dev; ptydevname(minor, pti); pt_softc[minor] = pti; } rw_exit_write(&pt_softc_lock); return (0); limit_reached: rw_exit_write(&pt_softc_lock); tablefull("pty"); return (ENXIO); } /* * Establish n (or default if n is 1) ptys in the system. */ void ptyattach(int n) { /* maybe should allow 0 => none? */ if (n <= 1) n = NPTY_MIN; pt_softc = ptyarralloc(n); npty = n; /* * If we have pty, we need ptm too. */ ptmattach(1); } int ptsopen(dev_t dev, int flag, int devtype, struct proc *p) { struct pt_softc *pti; struct tty *tp; int error; if ((error = check_pty(dev))) return (error); pti = pt_softc[minor(dev)]; tp = pti->pt_tty; if ((tp->t_state & TS_ISOPEN) == 0) { tp->t_state |= TS_WOPEN; ttychars(tp); /* Set up default chars */ tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_lflag = TTYDEF_LFLAG; tp->t_cflag = TTYDEF_CFLAG; tp->t_ispeed = tp->t_ospeed = B115200; ttsetwater(tp); /* would be done in xxparam() */ } else if (tp->t_state & TS_XCLUDE && suser(p) != 0) return (EBUSY); if (tp->t_oproc) /* Ctrlr still around. */ tp->t_state |= TS_CARR_ON; while ((tp->t_state & TS_CARR_ON) == 0) { tp->t_state |= TS_WOPEN; if (flag & FNONBLOCK) break; error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, ttopen); if (error) return (error); } error = (*linesw[tp->t_line].l_open)(dev, tp, p); ptcwakeup(tp, FREAD|FWRITE); return (error); } int ptsclose(dev_t dev, int flag, int mode, struct proc *p) { struct pt_softc *pti = pt_softc[minor(dev)]; struct tty *tp = pti->pt_tty; int error; error = (*linesw[tp->t_line].l_close)(tp, flag, p); error |= ttyclose(tp); ptcwakeup(tp, FREAD|FWRITE); return (error); } int ptsread(dev_t dev, struct uio *uio, int flag) { struct proc *p = curproc; struct process *pr = p->p_p; struct pt_softc *pti = pt_softc[minor(dev)]; struct tty *tp = pti->pt_tty; int error = 0; again: if (pti->pt_flags & PF_REMOTE) { while (isbackground(pr, tp)) { if (sigismasked(p, SIGTTIN) || pr->ps_pgrp->pg_jobc == 0 || pr->ps_flags & PS_PPWAIT) return (EIO); pgsignal(pr->ps_pgrp, SIGTTIN, 1); error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg); if (error) return (error); } if (tp->t_canq.c_cc == 0) { if (flag & IO_NDELAY) return (EWOULDBLOCK); error = ttysleep(tp, &tp->t_canq, TTIPRI | PCATCH, ttyin); if (error) return (error); goto again; } while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) if (ureadc(getc(&tp->t_canq), uio) < 0) { error = EFAULT; break; } if (tp->t_canq.c_cc == 1) (void) getc(&tp->t_canq); if (tp->t_canq.c_cc) return (error); } else if (tp->t_oproc) error = (*linesw[tp->t_line].l_read)(tp, uio, flag); ptcwakeup(tp, FWRITE); return (error); } /* * Write to pseudo-tty. * Wakeups of controlling tty will happen * indirectly, when tty driver calls ptsstart. */ int ptswrite(dev_t dev, struct uio *uio, int flag) { struct pt_softc *pti = pt_softc[minor(dev)]; struct tty *tp = pti->pt_tty; if (tp->t_oproc == NULL) return (EIO); return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); } /* * Start output on pseudo-tty. * Wake up process polling or sleeping for input from controlling tty. */ void ptsstart(struct tty *tp) { struct pt_softc *pti = pt_softc[minor(tp->t_dev)]; if (tp->t_state & TS_TTSTOP) return; if (pti->pt_flags & PF_STOPPED) { pti->pt_flags &= ~PF_STOPPED; pti->pt_send = TIOCPKT_START; } ptcwakeup(tp, FREAD); } int ptsstop(struct tty *tp, int flush) { struct pt_softc *pti = pt_softc[minor(tp->t_dev)]; int flag; /* note: FLUSHREAD and FLUSHWRITE already ok */ if (flush == 0) { flush = TIOCPKT_STOP; pti->pt_flags |= PF_STOPPED; } else pti->pt_flags &= ~PF_STOPPED; pti->pt_send |= flush; /* change of perspective */ flag = 0; if (flush & FREAD) flag |= FWRITE; if (flush & FWRITE) flag |= FREAD; ptcwakeup(tp, flag); return 0; } void ptcwakeup(struct tty *tp, int flag) { struct pt_softc *pti = pt_softc[minor(tp->t_dev)]; if (flag & FREAD) { selwakeup(&pti->pt_selr); wakeup(&tp->t_outq.c_cf); } if (flag & FWRITE) { selwakeup(&pti->pt_selw); wakeup(&tp->t_rawq.c_cf); } } int ptcopen(dev_t, int, int, struct proc *); int ptcopen(dev_t dev, int flag, int devtype, struct proc *p) { struct pt_softc *pti; struct tty *tp; int error; if ((error = check_pty(dev))) return (error); pti = pt_softc[minor(dev)]; tp = pti->pt_tty; if (tp->t_oproc) return (EIO); tp->t_oproc = ptsstart; (void)(*linesw[tp->t_line].l_modem)(tp, 1); tp->t_lflag &= ~EXTPROC; pti->pt_flags = 0; pti->pt_send = 0; pti->pt_ucntl = 0; return (0); } int ptcclose(dev_t dev, int flag, int devtype, struct proc *p) { struct pt_softc *pti = pt_softc[minor(dev)]; struct tty *tp = pti->pt_tty; (void)(*linesw[tp->t_line].l_modem)(tp, 0); tp->t_state &= ~TS_CARR_ON; tp->t_oproc = NULL; /* mark closed */ return (0); } int ptcread(dev_t dev, struct uio *uio, int flag) { struct pt_softc *pti = pt_softc[minor(dev)]; struct tty *tp = pti->pt_tty; char buf[BUFSIZ]; int error = 0, cc, bufcc = 0; /* * We want to block until the slave * is open, and there's something to read; * but if we lost the slave or we're NBIO, * then return the appropriate error instead. */ for (;;) { if (tp->t_state & TS_ISOPEN) { if (pti->pt_flags & PF_PKT && pti->pt_send) { error = ureadc((int)pti->pt_send, uio); if (error) return (error); if (pti->pt_send & TIOCPKT_IOCTL) { cc = MIN(uio->uio_resid, sizeof(tp->t_termios)); error = uiomove(&tp->t_termios, cc, uio); if (error) return (error); } pti->pt_send = 0; return (0); } if (pti->pt_flags & PF_UCNTL && pti->pt_ucntl) { error = ureadc((int)pti->pt_ucntl, uio); if (error) return (error); pti->pt_ucntl = 0; return (0); } if (tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) break; } if ((tp->t_state & TS_CARR_ON) == 0) return (0); /* EOF */ if (flag & IO_NDELAY) return (EWOULDBLOCK); error = tsleep_nsec(&tp->t_outq.c_cf, TTIPRI | PCATCH, ttyin, INFSLP); if (error) return (error); } if (pti->pt_flags & (PF_PKT|PF_UCNTL)) error = ureadc(0, uio); while (uio->uio_resid > 0 && error == 0) { cc = MIN(uio->uio_resid, BUFSIZ); cc = q_to_b(&tp->t_outq, buf, cc); if (cc > bufcc) bufcc = cc; if (cc <= 0) break; error = uiomove(buf, cc, uio); } ttwakeupwr(tp); if (bufcc) explicit_bzero(buf, bufcc); return (error); } int ptcwrite(dev_t dev, struct uio *uio, int flag) { struct pt_softc *pti = pt_softc[minor(dev)]; struct tty *tp = pti->pt_tty; u_char *cp = NULL; int cc = 0, bufcc = 0; u_char buf[BUFSIZ]; size_t cnt = 0; int error = 0; again: if ((tp->t_state & TS_ISOPEN) == 0) goto block; if (pti->pt_flags & PF_REMOTE) { if (tp->t_canq.c_cc) goto block; while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG(tp) - 1) { if (cc == 0) { cc = MIN(uio->uio_resid, BUFSIZ); cc = min(cc, TTYHOG(tp) - 1 - tp->t_canq.c_cc); if (cc > bufcc) bufcc = cc; cp = buf; error = uiomove(cp, cc, uio); if (error) goto done; /* check again for safety */ if ((tp->t_state & TS_ISOPEN) == 0) { error = EIO; goto done; } } if (cc) (void) b_to_q((char *)cp, cc, &tp->t_canq); cc = 0; } (void) putc(0, &tp->t_canq); ttwakeup(tp); wakeup(&tp->t_canq); goto done; } do { if (cc == 0) { cc = MIN(uio->uio_resid, BUFSIZ); if (cc > bufcc) bufcc = cc; cp = buf; error = uiomove(cp, cc, uio); if (error) goto done; /* check again for safety */ if ((tp->t_state & TS_ISOPEN) == 0) { error = EIO; goto done; } } bufcc = cc; while (cc > 0) { if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG(tp) - 2 && (tp->t_canq.c_cc > 0 || !ISSET(tp->t_lflag, ICANON))) { wakeup(&tp->t_rawq); goto block; } if ((*linesw[tp->t_line].l_rint)(*cp++, tp) == 1 && tsleep(tp, TTIPRI | PCATCH, "ttyretype", 1) == EINTR) goto interrupt; cnt++; cc--; } cc = 0; } while (uio->uio_resid > 0); goto done; block: /* * Come here to wait for slave to open, for space * in outq, or space in rawq. */ if ((tp->t_state & TS_CARR_ON) == 0) { error = EIO; goto done; } if (flag & IO_NDELAY) { /* adjust for data copied in but not written */ uio->uio_resid += cc; if (cnt == 0) error = EWOULDBLOCK; goto done; } error = tsleep_nsec(&tp->t_rawq.c_cf, TTOPRI | PCATCH, ttyout, INFSLP); if (error == 0) goto again; interrupt: /* adjust for data copied in but not written */ uio->uio_resid += cc; done: if (bufcc) explicit_bzero(buf, bufcc); return (error); } void filt_ptcrdetach(struct knote *kn) { struct pt_softc *pti = (struct pt_softc *)kn->kn_hook; int s; s = spltty(); klist_remove_locked(&pti->pt_selr.si_note, kn); splx(s); } int filt_ptcread(struct knote *kn, long hint) { struct pt_softc *pti = (struct pt_softc *)kn->kn_hook; struct tty *tp; int active; tp = pti->pt_tty; kn->kn_data = 0; if (ISSET(tp->t_state, TS_ISOPEN)) { if (!ISSET(tp->t_state, TS_TTSTOP)) kn->kn_data = tp->t_outq.c_cc; if (((pti->pt_flags & PF_PKT) && pti->pt_send) || ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)) kn->kn_data++; } active = (kn->kn_data > 0); if (!ISSET(tp->t_state, TS_CARR_ON)) { kn->kn_flags |= EV_EOF; if (kn->kn_flags & __EV_POLL) kn->kn_flags |= __EV_HUP; active = 1; } else { kn->kn_flags &= ~(EV_EOF | __EV_HUP); } return (active); } void filt_ptcwdetach(struct knote *kn) { struct pt_softc *pti = (struct pt_softc *)kn->kn_hook; int s; s = spltty(); klist_remove_locked(&pti->pt_selw.si_note, kn); splx(s); } int filt_ptcwrite(struct knote *kn, long hint) { struct pt_softc *pti = (struct pt_softc *)kn->kn_hook; struct tty *tp; int active; tp = pti->pt_tty; kn->kn_data = 0; if (ISSET(tp->t_state, TS_ISOPEN)) { if (ISSET(pti->pt_flags, PF_REMOTE)) { if (tp->t_canq.c_cc == 0) kn->kn_data = tp->t_canq.c_cn; } else if ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG(tp)-2) || (tp->t_canq.c_cc == 0 && ISSET(tp->t_lflag, ICANON))) kn->kn_data = tp->t_canq.c_cn - (tp->t_rawq.c_cc + tp->t_canq.c_cc); } active = (kn->kn_data > 0); /* Write-side HUP condition is only for poll(2) and select(2). */ if (kn->kn_flags & (__EV_POLL | __EV_SELECT)) { if (!ISSET(tp->t_state, TS_CARR_ON)) { kn->kn_flags |= __EV_HUP; active = 1; } else { kn->kn_flags &= ~__EV_HUP; } } return (active); } int filt_ptcexcept(struct knote *kn, long hint) { struct pt_softc *pti = (struct pt_softc *)kn->kn_hook; struct tty *tp; int active = 0; tp = pti->pt_tty; if (kn->kn_sfflags & NOTE_OOB) { /* If in packet or user control mode, check for data. */ if (((pti->pt_flags & PF_PKT) && pti->pt_send) || ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)) { kn->kn_fflags |= NOTE_OOB; kn->kn_data = 1; active = 1; } } if (kn->kn_flags & __EV_POLL) { if (!ISSET(tp->t_state, TS_CARR_ON)) { kn->kn_flags |= __EV_HUP; active = 1; } else { kn->kn_flags &= ~__EV_HUP; } } return (active); } const struct filterops ptcread_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, .f_detach = filt_ptcrdetach, .f_event = filt_ptcread, }; const struct filterops ptcwrite_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, .f_detach = filt_ptcwdetach, .f_event = filt_ptcwrite, }; const struct filterops ptcexcept_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, .f_detach = filt_ptcrdetach, .f_event = filt_ptcexcept, }; int ptckqfilter(dev_t dev, struct knote *kn) { struct pt_softc *pti = pt_softc[minor(dev)]; struct klist *klist; int s; switch (kn->kn_filter) { case EVFILT_READ: klist = &pti->pt_selr.si_note; kn->kn_fop = &ptcread_filtops; break; case EVFILT_WRITE: klist = &pti->pt_selw.si_note; kn->kn_fop = &ptcwrite_filtops; break; case EVFILT_EXCEPT: klist = &pti->pt_selr.si_note; kn->kn_fop = &ptcexcept_filtops; break; default: return (EINVAL); } kn->kn_hook = (caddr_t)pti; s = spltty(); klist_insert_locked(klist, kn); splx(s); return (0); } struct tty * ptytty(dev_t dev) { struct pt_softc *pti = pt_softc[minor(dev)]; struct tty *tp = pti->pt_tty; return (tp); } int ptyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { struct pt_softc *pti = pt_softc[minor(dev)]; struct tty *tp = pti->pt_tty; u_char *cc = tp->t_cc; int stop, error; /* * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. * ttywflush(tp) will hang if there are characters in the outq. */ if (cmd == TIOCEXT) { /* * When the EXTPROC bit is being toggled, we need * to send an TIOCPKT_IOCTL if the packet driver * is turned on. */ if (*(int *)data) { if (pti->pt_flags & PF_PKT) { pti->pt_send |= TIOCPKT_IOCTL; ptcwakeup(tp, FREAD); } tp->t_lflag |= EXTPROC; } else { if ((tp->t_lflag & EXTPROC) && (pti->pt_flags & PF_PKT)) { pti->pt_send |= TIOCPKT_IOCTL; ptcwakeup(tp, FREAD); } tp->t_lflag &= ~EXTPROC; } return(0); } else if (cdevsw[major(dev)].d_open == ptcopen) switch (cmd) { case TIOCGPGRP: /* * We avoid calling ttioctl on the controller since, * in that case, tp must be the controlling terminal. */ *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; return (0); case TIOCPKT: if (*(int *)data) { if (pti->pt_flags & PF_UCNTL) return (EINVAL); pti->pt_flags |= PF_PKT; } else pti->pt_flags &= ~PF_PKT; return (0); case TIOCUCNTL: if (*(int *)data) { if (pti->pt_flags & PF_PKT) return (EINVAL); pti->pt_flags |= PF_UCNTL; } else pti->pt_flags &= ~PF_UCNTL; return (0); case TIOCREMOTE: if (*(int *)data) pti->pt_flags |= PF_REMOTE; else pti->pt_flags &= ~PF_REMOTE; ttyflush(tp, FREAD|FWRITE); return (0); case TIOCSETD: case TIOCSETA: case TIOCSETAW: case TIOCSETAF: ndflush(&tp->t_outq, tp->t_outq.c_cc); break; case TIOCSIG: if (*(unsigned int *)data >= NSIG || *(unsigned int *)data == 0) return(EINVAL); if ((tp->t_lflag & NOFLSH) == 0) ttyflush(tp, FREAD|FWRITE); pgsignal(tp->t_pgrp, *(unsigned int *)data, 1); if ((*(unsigned int *)data == SIGINFO) && ((tp->t_lflag & NOKERNINFO) == 0)) ttyinfo(tp); return (0); case FIONREAD: /* * FIONREAD on the master side must return the amount * in the output queue rather than the input. */ *(int *)data = tp->t_outq.c_cc; return (0); } error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); if (error < 0) error = ttioctl(tp, cmd, data, flag, p); if (error < 0) { /* * Translate TIOCSBRK/TIOCCBRK to user mode ioctls to * let the master interpret BREAK conditions. */ switch (cmd) { case TIOCSBRK: cmd = UIOCCMD(TIOCUCNTL_SBRK); break; case TIOCCBRK: cmd = UIOCCMD(TIOCUCNTL_CBRK); break; default: break; } if (pti->pt_flags & PF_UCNTL && (cmd & ~0xff) == UIOCCMD(0)) { if (cmd & 0xff) { pti->pt_ucntl = (u_char)cmd; ptcwakeup(tp, FREAD); } return (0); } error = ENOTTY; } /* * If external processing and packet mode send ioctl packet. */ if ((tp->t_lflag & EXTPROC) && (pti->pt_flags & PF_PKT)) { switch (cmd) { case TIOCSETA: case TIOCSETAW: case TIOCSETAF: pti->pt_send |= TIOCPKT_IOCTL; ptcwakeup(tp, FREAD); default: break; } } stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) && CCEQ(cc[VSTART], CTRL('q')); if (pti->pt_flags & PF_NOSTOP) { if (stop) { pti->pt_send &= ~TIOCPKT_NOSTOP; pti->pt_send |= TIOCPKT_DOSTOP; pti->pt_flags &= ~PF_NOSTOP; ptcwakeup(tp, FREAD); } } else { if (!stop) { pti->pt_send &= ~TIOCPKT_DOSTOP; pti->pt_send |= TIOCPKT_NOSTOP; pti->pt_flags |= PF_NOSTOP; ptcwakeup(tp, FREAD); } } return (error); } /* * Return pty-related information. */ int sysctl_pty(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { if (namelen != 1) return (ENOTDIR); switch (name[0]) { default: return (EOPNOTSUPP); } /* NOTREACHED */ } /* * Check if a pty is free to use. */ static int pty_isfree_locked(int minor) { struct pt_softc *pt = pt_softc[minor]; return (pt == NULL || pt->pt_tty == NULL || pt->pt_tty->t_oproc == NULL); } static int pty_isfree(int minor) { int isfree; rw_enter_read(&pt_softc_lock); isfree = pty_isfree_locked(minor); rw_exit_read(&pt_softc_lock); return(isfree); } dev_t pty_getfree(void) { int i; rw_enter_read(&pt_softc_lock); for (i = 0; i < npty; i++) { if (pty_isfree_locked(i)) break; } rw_exit_read(&pt_softc_lock); return (makedev(pts_major, i)); } /* * Hacked up version of vn_open. We _only_ handle ptys and only open * them with FREAD|FWRITE and never deal with creat or stuff like that. * * We need it because we have to fake up root credentials to open the pty. */ static int ptm_vn_open(struct nameidata *ndp) { struct proc *p = ndp->ni_cnd.cn_proc; struct ucred *cred; struct vattr vattr; struct vnode *vp; int error; if ((error = namei(ndp)) != 0) return (error); vp = ndp->ni_vp; if (vp->v_type != VCHR) { error = EINVAL; goto bad; } /* * Get us a fresh cred with root privileges. */ cred = crget(); error = VOP_OPEN(vp, FREAD|FWRITE, cred, p); if (!error) { /* update atime/mtime */ VATTR_NULL(&vattr); getnanotime(&vattr.va_atime); vattr.va_mtime = vattr.va_atime; vattr.va_vaflags |= VA_UTIMES_NULL; (void)VOP_SETATTR(vp, &vattr, p->p_ucred, p); } crfree(cred); if (error) goto bad; vp->v_writecount++; return (0); bad: vput(vp); return (error); } void ptmattach(int n) { /* find the major and minor of the pty devices */ int i; for (i = 0; i < nchrdev; i++) if (cdevsw[i].d_open == ptsopen) break; if (i == nchrdev) panic("ptmattach: Can't find pty slave in cdevsw"); pts_major = i; } int ptmopen(dev_t dev, int flag, int mode, struct proc *p) { return(0); } int ptmclose(dev_t dev, int flag, int mode, struct proc *p) { return (0); } int ptmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { dev_t newdev; struct pt_softc * pti; struct nameidata cnd, snd; struct filedesc *fdp = p->p_fd; struct file *cfp = NULL, *sfp = NULL; int cindx, sindx, error; uid_t uid; gid_t gid; struct vattr vattr; struct ucred *cred; struct ptmget *ptm = (struct ptmget *)data; switch (cmd) { case PTMGET: fdplock(fdp); /* Grab two filedescriptors. */ if ((error = falloc(p, &cfp, &cindx)) != 0) { fdpunlock(fdp); break; } if ((error = falloc(p, &sfp, &sindx)) != 0) { fdremove(fdp, cindx); fdpunlock(fdp); closef(cfp, p); break; } fdpunlock(fdp); retry: /* Find and open a free master pty. */ newdev = pty_getfree(); if ((error = check_pty(newdev))) goto bad; pti = pt_softc[minor(newdev)]; NDINIT(&cnd, LOOKUP, NOFOLLOW|LOCKLEAF|KERNELPATH, UIO_SYSSPACE, pti->pty_pn, p); cnd.ni_pledge = PLEDGE_RPATH | PLEDGE_WPATH; if ((error = ptm_vn_open(&cnd)) != 0) { /* * Check if the master open failed because we lost * the race to grab it. */ if (error == EIO && !pty_isfree(minor(newdev))) goto retry; goto bad; } cfp->f_flag = FREAD|FWRITE; cfp->f_type = DTYPE_VNODE; cfp->f_ops = &vnops; cfp->f_data = (caddr_t) cnd.ni_vp; VOP_UNLOCK(cnd.ni_vp); /* * Open the slave. * namei -> setattr -> unlock -> revoke -> vrele -> * namei -> open -> unlock * Three stage rocket: * 1. Change the owner and permissions on the slave. * 2. Revoke all the users of the slave. * 3. open the slave. */ NDINIT(&snd, LOOKUP, NOFOLLOW|LOCKLEAF|KERNELPATH, UIO_SYSSPACE, pti->pty_sn, p); snd.ni_pledge = PLEDGE_RPATH | PLEDGE_WPATH; if ((error = namei(&snd)) != 0) goto bad; if ((snd.ni_vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { gid = tty_gid; /* get real uid */ uid = p->p_ucred->cr_ruid; VATTR_NULL(&vattr); vattr.va_uid = uid; vattr.va_gid = gid; vattr.va_mode = (S_IRUSR|S_IWUSR|S_IWGRP) & ALLPERMS; /* Get a fake cred to pretend we're root. */ cred = crget(); error = VOP_SETATTR(snd.ni_vp, &vattr, cred, p); crfree(cred); if (error) { vput(snd.ni_vp); goto bad; } } VOP_UNLOCK(snd.ni_vp); if (snd.ni_vp->v_usecount > 1 || (snd.ni_vp->v_flag & (VALIASED))) VOP_REVOKE(snd.ni_vp, REVOKEALL); /* * The vnode is useless after the revoke, we need to * namei again. */ vrele(snd.ni_vp); NDINIT(&snd, LOOKUP, NOFOLLOW|LOCKLEAF|KERNELPATH, UIO_SYSSPACE, pti->pty_sn, p); snd.ni_pledge = PLEDGE_RPATH | PLEDGE_WPATH; /* now open it */ if ((error = ptm_vn_open(&snd)) != 0) goto bad; sfp->f_flag = FREAD|FWRITE; sfp->f_type = DTYPE_VNODE; sfp->f_ops = &vnops; sfp->f_data = (caddr_t) snd.ni_vp; VOP_UNLOCK(snd.ni_vp); /* now, put the indexen and names into struct ptmget */ ptm->cfd = cindx; ptm->sfd = sindx; memcpy(ptm->cn, pti->pty_pn, sizeof(pti->pty_pn)); memcpy(ptm->sn, pti->pty_sn, sizeof(pti->pty_sn)); /* insert files now that we've passed all errors */ fdplock(fdp); fdinsert(fdp, cindx, 0, cfp); fdinsert(fdp, sindx, 0, sfp); fdpunlock(fdp); FRELE(cfp, p); FRELE(sfp, p); break; default: error = EINVAL; break; } return (error); bad: fdplock(fdp); fdremove(fdp, cindx); fdremove(fdp, sindx); fdpunlock(fdp); closef(cfp, p); closef(sfp, p); return (error); }
48 7 1 22 1 15 1 11 12 39 47 47 1 3 1 47 22 22 22 22 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 /* $OpenBSD: tcp_input.c,v 1.405 2024/04/17 20:48:51 bluhm Exp $ */ /* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 * * NRL grants permission for redistribution and use in source and binary * forms, with or without modification, of the software and documentation * created at NRL provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgements: * This product includes software developed by the University of * California, Berkeley and its contributors. * This product includes software developed at the Information * Technology Division, US Naval Research Laboratory. * 4. Neither the name of the NRL nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the US Naval * Research Laboratory (NRL). */ #include "pf.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/protosw.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/timeout.h> #include <sys/kernel.h> #include <sys/pool.h> #include <net/if.h> #include <net/if_var.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/in_pcb.h> #include <netinet/ip_var.h> #include <netinet6/ip6_var.h> #include <netinet/tcp.h> #include <netinet/tcp_fsm.h> #include <netinet/tcp_seq.h> #include <netinet/tcp_timer.h> #include <netinet/tcp_var.h> #include <netinet/tcp_debug.h> #if NPF > 0 #include <net/pfvar.h> #endif int tcp_mss_adv(struct mbuf *, int); int tcp_flush_queue(struct tcpcb *); #ifdef INET6 #include <netinet6/in6_var.h> #include <netinet6/nd6.h> /* for the packet header length in the mbuf */ #define M_PH_LEN(m) (((struct mbuf *)(m))->m_pkthdr.len) #define M_V6_LEN(m) (M_PH_LEN(m) - sizeof(struct ip6_hdr)) #define M_V4_LEN(m) (M_PH_LEN(m) - sizeof(struct ip)) #endif /* INET6 */ int tcprexmtthresh = 3; int tcptv_keep_init = TCPTV_KEEP_INIT; int tcp_rst_ppslim = 100; /* 100pps */ int tcp_rst_ppslim_count = 0; struct timeval tcp_rst_ppslim_last; int tcp_ackdrop_ppslim = 100; /* 100pps */ int tcp_ackdrop_ppslim_count = 0; struct timeval tcp_ackdrop_ppslim_last; #define TCP_PAWS_IDLE TCP_TIME(24 * 24 * 60 * 60) /* for modulo comparisons of timestamps */ #define TSTMP_LT(a,b) ((int32_t)((a)-(b)) < 0) #define TSTMP_GEQ(a,b) ((int32_t)((a)-(b)) >= 0) /* for TCP SACK comparisons */ #define SEQ_MIN(a,b) (SEQ_LT(a,b) ? (a) : (b)) #define SEQ_MAX(a,b) (SEQ_GT(a,b) ? (a) : (b)) /* * Neighbor Discovery, Neighbor Unreachability Detection Upper layer hint. */ #ifdef INET6 #define ND6_HINT(tp) \ do { \ if (tp && tp->t_inpcb && \ ISSET(tp->t_inpcb->inp_flags, INP_IPV6) && \ rtisvalid(tp->t_inpcb->inp_route.ro_rt)) { \ nd6_nud_hint(tp->t_inpcb->inp_route.ro_rt); \ } \ } while (0) #else #define ND6_HINT(tp) #endif #ifdef TCP_ECN /* * ECN (Explicit Congestion Notification) support based on RFC3168 * implementation note: * snd_last is used to track a recovery phase. * when cwnd is reduced, snd_last is set to snd_max. * while snd_last > snd_una, the sender is in a recovery phase and * its cwnd should not be reduced again. * snd_last follows snd_una when not in a recovery phase. */ #endif /* * Macro to compute ACK transmission behavior. Delay the ACK unless * we have already delayed an ACK (must send an ACK every two segments). * We also ACK immediately if we received a PUSH and the ACK-on-PUSH * option is enabled or when the packet is coming from a loopback * interface. */ #define TCP_SETUP_ACK(tp, tiflags, m) \ do { \ struct ifnet *ifp = NULL; \ if (m && (m->m_flags & M_PKTHDR)) \ ifp = if_get(m->m_pkthdr.ph_ifidx); \ if (TCP_TIMER_ISARMED(tp, TCPT_DELACK) || \ (tcp_ack_on_push && (tiflags) & TH_PUSH) || \ (ifp && (ifp->if_flags & IFF_LOOPBACK))) \ tp->t_flags |= TF_ACKNOW; \ else \ TCP_TIMER_ARM(tp, TCPT_DELACK, tcp_delack_msecs); \ if_put(ifp); \ } while (0) void tcp_sack_partialack(struct tcpcb *, struct tcphdr *); void tcp_newreno_partialack(struct tcpcb *, struct tcphdr *); void syn_cache_put(struct syn_cache *); void syn_cache_rm(struct syn_cache *); int syn_cache_respond(struct syn_cache *, struct mbuf *, uint64_t); void syn_cache_timer(void *); void syn_cache_insert(struct syn_cache *, struct tcpcb *); void syn_cache_reset(struct sockaddr *, struct sockaddr *, struct tcphdr *, u_int); int syn_cache_add(struct sockaddr *, struct sockaddr *, struct tcphdr *, unsigned int, struct socket *, struct mbuf *, u_char *, int, struct tcp_opt_info *, tcp_seq *, uint64_t); struct socket *syn_cache_get(struct sockaddr *, struct sockaddr *, struct tcphdr *, unsigned int, unsigned int, struct socket *, struct mbuf *, uint64_t); struct syn_cache *syn_cache_lookup(const struct sockaddr *, const struct sockaddr *, struct syn_cache_head **, u_int); /* * Insert segment ti into reassembly queue of tcp with * control block tp. Return TH_FIN if reassembly now includes * a segment with FIN. The macro form does the common case inline * (segment is the next to be received on an established connection, * and the queue is empty), avoiding linkage into and removal * from the queue and repetition of various conversions. * Set DELACK for segments received in order, but ack immediately * when segments are out of order (so fast retransmit can work). */ int tcp_reass(struct tcpcb *tp, struct tcphdr *th, struct mbuf *m, int *tlen) { struct tcpqent *p, *q, *nq, *tiqe; /* * Allocate a new queue entry, before we throw away any data. * If we can't, just drop the packet. XXX */ tiqe = pool_get(&tcpqe_pool, PR_NOWAIT); if (tiqe == NULL) { tiqe = TAILQ_LAST(&tp->t_segq, tcpqehead); if (tiqe != NULL && th->th_seq == tp->rcv_nxt) { /* Reuse last entry since new segment fills a hole */ m_freem(tiqe->tcpqe_m); TAILQ_REMOVE(&tp->t_segq, tiqe, tcpqe_q); } if (tiqe == NULL || th->th_seq != tp->rcv_nxt) { /* Flush segment queue for this connection */ tcp_freeq(tp); tcpstat_inc(tcps_rcvmemdrop); m_freem(m); return (0); } } /* * Find a segment which begins after this one does. */ for (p = NULL, q = TAILQ_FIRST(&tp->t_segq); q != NULL; p = q, q = TAILQ_NEXT(q, tcpqe_q)) if (SEQ_GT(q->tcpqe_tcp->th_seq, th->th_seq)) break; /* * If there is a preceding segment, it may provide some of * our data already. If so, drop the data from the incoming * segment. If it provides all of our data, drop us. */ if (p != NULL) { struct tcphdr *phdr = p->tcpqe_tcp; int i; /* conversion to int (in i) handles seq wraparound */ i = phdr->th_seq + phdr->th_reseqlen - th->th_seq; if (i > 0) { if (i >= *tlen) { tcpstat_pkt(tcps_rcvduppack, tcps_rcvdupbyte, *tlen); m_freem(m); pool_put(&tcpqe_pool, tiqe); return (0); } m_adj(m, i); *tlen -= i; th->th_seq += i; } } tcpstat_pkt(tcps_rcvoopack, tcps_rcvoobyte, *tlen); tp->t_rcvoopack++; /* * While we overlap succeeding segments trim them or, * if they are completely covered, dequeue them. */ for (; q != NULL; q = nq) { struct tcphdr *qhdr = q->tcpqe_tcp; int i = (th->th_seq + *tlen) - qhdr->th_seq; if (i <= 0) break; if (i < qhdr->th_reseqlen) { qhdr->th_seq += i; qhdr->th_reseqlen -= i; m_adj(q->tcpqe_m, i); break; } nq = TAILQ_NEXT(q, tcpqe_q); m_freem(q->tcpqe_m); TAILQ_REMOVE(&tp->t_segq, q, tcpqe_q); pool_put(&tcpqe_pool, q); } /* Insert the new segment queue entry into place. */ tiqe->tcpqe_m = m; th->th_reseqlen = *tlen; tiqe->tcpqe_tcp = th; if (p == NULL) { TAILQ_INSERT_HEAD(&tp->t_segq, tiqe, tcpqe_q); } else { TAILQ_INSERT_AFTER(&tp->t_segq, p, tiqe, tcpqe_q); } if (th->th_seq != tp->rcv_nxt) return (0); return (tcp_flush_queue(tp)); } int tcp_flush_queue(struct tcpcb *tp) { struct socket *so = tp->t_inpcb->inp_socket; struct tcpqent *q, *nq; int flags; /* * Present data to user, advancing rcv_nxt through * completed sequence space. */ if (TCPS_HAVEESTABLISHED(tp->t_state) == 0) return (0); q = TAILQ_FIRST(&tp->t_segq); if (q == NULL || q->tcpqe_tcp->th_seq != tp->rcv_nxt) return (0); if (tp->t_state == TCPS_SYN_RECEIVED && q->tcpqe_tcp->th_reseqlen) return (0); do { tp->rcv_nxt += q->tcpqe_tcp->th_reseqlen; flags = q->tcpqe_tcp->th_flags & TH_FIN; nq = TAILQ_NEXT(q, tcpqe_q); TAILQ_REMOVE(&tp->t_segq, q, tcpqe_q); ND6_HINT(tp); if (so->so_rcv.sb_state & SS_CANTRCVMORE) m_freem(q->tcpqe_m); else sbappendstream(so, &so->so_rcv, q->tcpqe_m); pool_put(&tcpqe_pool, q); q = nq; } while (q != NULL && q->tcpqe_tcp->th_seq == tp->rcv_nxt); tp->t_flags |= TF_BLOCKOUTPUT; sorwakeup(so); tp->t_flags &= ~TF_BLOCKOUTPUT; return (flags); } /* * TCP input routine, follows pages 65-76 of the * protocol specification dated September, 1981 very closely. */ int tcp_input(struct mbuf **mp, int *offp, int proto, int af) { struct mbuf *m = *mp; int iphlen = *offp; struct ip *ip = NULL; struct inpcb *inp = NULL; u_int8_t *optp = NULL; int optlen = 0; int tlen, off; struct tcpcb *otp = NULL, *tp = NULL; int tiflags; struct socket *so = NULL; int todrop, acked, ourfinisacked; int hdroptlen = 0; short ostate; union { struct tcpiphdr tcpip; #ifdef INET6 struct tcpipv6hdr tcpip6; #endif char caddr; } saveti; tcp_seq iss, *reuse = NULL; uint64_t now; u_long tiwin; struct tcp_opt_info opti; struct tcphdr *th; #ifdef INET6 struct ip6_hdr *ip6 = NULL; #endif /* INET6 */ #ifdef TCP_ECN u_char iptos; #endif tcpstat_inc(tcps_rcvtotal); opti.ts_present = 0; opti.maxseg = 0; now = tcp_now(); /* * RFC1122 4.2.3.10, p. 104: discard bcast/mcast SYN */ if (m->m_flags & (M_BCAST|M_MCAST)) goto drop; /* * Get IP and TCP header together in first mbuf. * Note: IP leaves IP header in first mbuf. */ IP6_EXTHDR_GET(th, struct tcphdr *, m, iphlen, sizeof(*th)); if (!th) { tcpstat_inc(tcps_rcvshort); return IPPROTO_DONE; } tlen = m->m_pkthdr.len - iphlen; switch (af) { case AF_INET: ip = mtod(m, struct ip *); #ifdef TCP_ECN /* save ip_tos before clearing it for checksum */ iptos = ip->ip_tos; #endif break; #ifdef INET6 case AF_INET6: ip6 = mtod(m, struct ip6_hdr *); #ifdef TCP_ECN iptos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; #endif /* * Be proactive about unspecified IPv6 address in source. * As we use all-zero to indicate unbounded/unconnected pcb, * unspecified IPv6 address can be used to confuse us. * * Note that packets with unspecified IPv6 destination is * already dropped in ip6_input. */ if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) { /* XXX stat */ goto drop; } /* Discard packets to multicast */ if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { /* XXX stat */ goto drop; } break; #endif default: unhandled_af(af); } /* * Checksum extended TCP header and data. */ if ((m->m_pkthdr.csum_flags & M_TCP_CSUM_IN_OK) == 0) { int sum; if (m->m_pkthdr.csum_flags & M_TCP_CSUM_IN_BAD) { tcpstat_inc(tcps_rcvbadsum); goto drop; } tcpstat_inc(tcps_inswcsum); switch (af) { case AF_INET: sum = in4_cksum(m, IPPROTO_TCP, iphlen, tlen); break; #ifdef INET6 case AF_INET6: sum = in6_cksum(m, IPPROTO_TCP, sizeof(struct ip6_hdr), tlen); break; #endif } if (sum != 0) { tcpstat_inc(tcps_rcvbadsum); goto drop; } } /* * Check that TCP offset makes sense, * pull out TCP options and adjust length. XXX */ off = th->th_off << 2; if (off < sizeof(struct tcphdr) || off > tlen) { tcpstat_inc(tcps_rcvbadoff); goto drop; } tlen -= off; if (off > sizeof(struct tcphdr)) { IP6_EXTHDR_GET(th, struct tcphdr *, m, iphlen, off); if (!th) { tcpstat_inc(tcps_rcvshort); return IPPROTO_DONE; } optlen = off - sizeof(struct tcphdr); optp = (u_int8_t *)(th + 1); /* * Do quick retrieval of timestamp options ("options * prediction?"). If timestamp is the only option and it's * formatted as recommended in RFC 1323 appendix A, we * quickly get the values now and not bother calling * tcp_dooptions(), etc. */ if ((optlen == TCPOLEN_TSTAMP_APPA || (optlen > TCPOLEN_TSTAMP_APPA && optp[TCPOLEN_TSTAMP_APPA] == TCPOPT_EOL)) && *(u_int32_t *)optp == htonl(TCPOPT_TSTAMP_HDR) && (th->th_flags & TH_SYN) == 0) { opti.ts_present = 1; opti.ts_val = ntohl(*(u_int32_t *)(optp + 4)); opti.ts_ecr = ntohl(*(u_int32_t *)(optp + 8)); optp = NULL; /* we've parsed the options */ } } tiflags = th->th_flags; /* * Convert TCP protocol specific fields to host format. */ th->th_seq = ntohl(th->th_seq); th->th_ack = ntohl(th->th_ack); th->th_win = ntohs(th->th_win); th->th_urp = ntohs(th->th_urp); if (th->th_dport == 0) { tcpstat_inc(tcps_noport); goto dropwithreset_ratelim; } /* * Locate pcb for segment. */ #if NPF > 0 inp = pf_inp_lookup(m); #endif findpcb: if (inp == NULL) { switch (af) { #ifdef INET6 case AF_INET6: inp = in6_pcblookup(&tcb6table, &ip6->ip6_src, th->th_sport, &ip6->ip6_dst, th->th_dport, m->m_pkthdr.ph_rtableid); break; #endif case AF_INET: inp = in_pcblookup(&tcbtable, ip->ip_src, th->th_sport, ip->ip_dst, th->th_dport, m->m_pkthdr.ph_rtableid); break; } } if (inp == NULL) { tcpstat_inc(tcps_pcbhashmiss); switch (af) { #ifdef INET6 case AF_INET6: inp = in6_pcblookup_listen(&tcb6table, &ip6->ip6_dst, th->th_dport, m, m->m_pkthdr.ph_rtableid); break; #endif case AF_INET: inp = in_pcblookup_listen(&tcbtable, ip->ip_dst, th->th_dport, m, m->m_pkthdr.ph_rtableid); break; } /* * If the state is CLOSED (i.e., TCB does not exist) then * all data in the incoming segment is discarded. * If the TCB exists but is in CLOSED state, it is embryonic, * but should either do a listen or a connect soon. */ } #ifdef IPSEC if (ipsec_in_use) { struct m_tag *mtag; struct tdb *tdb = NULL; int error; /* Find most recent IPsec tag */ mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); if (mtag != NULL) { struct tdb_ident *tdbi; tdbi = (struct tdb_ident *)(mtag + 1); tdb = gettdb(tdbi->rdomain, tdbi->spi, &tdbi->dst, tdbi->proto); } error = ipsp_spd_lookup(m, af, iphlen, IPSP_DIRECTION_IN, tdb, inp ? &inp->inp_seclevel : NULL, NULL, NULL); tdb_unref(tdb); if (error) { tcpstat_inc(tcps_rcvnosec); goto drop; } } #endif /* IPSEC */ if (inp == NULL) { tcpstat_inc(tcps_noport); goto dropwithreset_ratelim; } KASSERT(sotoinpcb(inp->inp_socket) == inp); KASSERT(intotcpcb(inp) == NULL || intotcpcb(inp)->t_inpcb == inp); soassertlocked(inp->inp_socket); /* Check the minimum TTL for socket. */ switch (af) { case AF_INET: if (inp->inp_ip_minttl && inp->inp_ip_minttl > ip->ip_ttl) goto drop; break; #ifdef INET6 case AF_INET6: if (inp->inp_ip6_minhlim && inp->inp_ip6_minhlim > ip6->ip6_hlim) goto drop; break; #endif } tp = intotcpcb(inp); if (tp == NULL) goto dropwithreset_ratelim; if (tp->t_state == TCPS_CLOSED) goto drop; /* Unscale the window into a 32-bit value. */ if ((tiflags & TH_SYN) == 0) tiwin = th->th_win << tp->snd_scale; else tiwin = th->th_win; so = inp->inp_socket; if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) { union syn_cache_sa src; union syn_cache_sa dst; bzero(&src, sizeof(src)); bzero(&dst, sizeof(dst)); switch (af) { case AF_INET: src.sin.sin_len = sizeof(struct sockaddr_in); src.sin.sin_family = AF_INET; src.sin.sin_addr = ip->ip_src; src.sin.sin_port = th->th_sport; dst.sin.sin_len = sizeof(struct sockaddr_in); dst.sin.sin_family = AF_INET; dst.sin.sin_addr = ip->ip_dst; dst.sin.sin_port = th->th_dport; break; #ifdef INET6 case AF_INET6: src.sin6.sin6_len = sizeof(struct sockaddr_in6); src.sin6.sin6_family = AF_INET6; src.sin6.sin6_addr = ip6->ip6_src; src.sin6.sin6_port = th->th_sport; dst.sin6.sin6_len = sizeof(struct sockaddr_in6); dst.sin6.sin6_family = AF_INET6; dst.sin6.sin6_addr = ip6->ip6_dst; dst.sin6.sin6_port = th->th_dport; break; #endif /* INET6 */ } if (so->so_options & SO_DEBUG) { otp = tp; ostate = tp->t_state; switch (af) { #ifdef INET6 case AF_INET6: saveti.tcpip6.ti6_i = *ip6; saveti.tcpip6.ti6_t = *th; break; #endif case AF_INET: memcpy(&saveti.tcpip.ti_i, ip, sizeof(*ip)); saveti.tcpip.ti_t = *th; break; } } if (so->so_options & SO_ACCEPTCONN) { switch (tiflags & (TH_RST|TH_SYN|TH_ACK)) { case TH_SYN|TH_ACK|TH_RST: case TH_SYN|TH_RST: case TH_ACK|TH_RST: case TH_RST: syn_cache_reset(&src.sa, &dst.sa, th, inp->inp_rtableid); goto drop; case TH_SYN|TH_ACK: /* * Received a SYN,ACK. This should * never happen while we are in * LISTEN. Send an RST. */ goto badsyn; case TH_ACK: so = syn_cache_get(&src.sa, &dst.sa, th, iphlen, tlen, so, m, now); if (so == NULL) { /* * We don't have a SYN for * this ACK; send an RST. */ goto badsyn; } else if (so == (struct socket *)(-1)) { /* * We were unable to create * the connection. If the * 3-way handshake was * completed, and RST has * been sent to the peer. * Since the mbuf might be * in use for the reply, * do not free it. */ m = *mp = NULL; goto drop; } else { /* * We have created a * full-blown connection. */ tp = NULL; in_pcbunref(inp); inp = in_pcbref(sotoinpcb(so)); tp = intotcpcb(inp); if (tp == NULL) goto badsyn; /*XXX*/ } break; default: /* * None of RST, SYN or ACK was set. * This is an invalid packet for a * TCB in LISTEN state. Send a RST. */ goto badsyn; case TH_SYN: /* * Received a SYN. */ #ifdef INET6 /* * If deprecated address is forbidden, we do * not accept SYN to deprecated interface * address to prevent any new inbound * connection from getting established. * When we do not accept SYN, we send a TCP * RST, with deprecated source address (instead * of dropping it). We compromise it as it is * much better for peer to send a RST, and * RST will be the final packet for the * exchange. * * If we do not forbid deprecated addresses, we * accept the SYN packet. RFC2462 does not * suggest dropping SYN in this case. * If we decipher RFC2462 5.5.4, it says like * this: * 1. use of deprecated addr with existing * communication is okay - "SHOULD continue * to be used" * 2. use of it with new communication: * (2a) "SHOULD NOT be used if alternate * address with sufficient scope is * available" * (2b) nothing mentioned otherwise. * Here we fall into (2b) case as we have no * choice in our source address selection - we * must obey the peer. * * The wording in RFC2462 is confusing, and * there are multiple description text for * deprecated address handling - worse, they * are not exactly the same. I believe 5.5.4 * is the best one, so we follow 5.5.4. */ if (ip6 && !ip6_use_deprecated) { struct in6_ifaddr *ia6; struct ifnet *ifp = if_get(m->m_pkthdr.ph_ifidx); if (ifp && (ia6 = in6ifa_ifpwithaddr(ifp, &ip6->ip6_dst)) && (ia6->ia6_flags & IN6_IFF_DEPRECATED)) { tp = NULL; if_put(ifp); goto dropwithreset; } if_put(ifp); } #endif /* * LISTEN socket received a SYN * from itself? This can't possibly * be valid; drop the packet. */ if (th->th_dport == th->th_sport) { switch (af) { #ifdef INET6 case AF_INET6: if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &ip6->ip6_dst)) { tcpstat_inc(tcps_badsyn); goto drop; } break; #endif /* INET6 */ case AF_INET: if (ip->ip_dst.s_addr == ip->ip_src.s_addr) { tcpstat_inc(tcps_badsyn); goto drop; } break; } } /* * SYN looks ok; create compressed TCP * state for it. */ if (so->so_qlen > so->so_qlimit || syn_cache_add(&src.sa, &dst.sa, th, iphlen, so, m, optp, optlen, &opti, reuse, now) == -1) { tcpstat_inc(tcps_dropsyn); goto drop; } in_pcbunref(inp); return IPPROTO_DONE; } } } #ifdef DIAGNOSTIC /* * Should not happen now that all embryonic connections * are handled with compressed state. */ if (tp->t_state == TCPS_LISTEN) panic("tcp_input: TCPS_LISTEN"); #endif #if NPF > 0 pf_inp_link(m, inp); #endif /* * Segment received on connection. * Reset idle time and keep-alive timer. */ tp->t_rcvtime = now; if (TCPS_HAVEESTABLISHED(tp->t_state)) TCP_TIMER_ARM(tp, TCPT_KEEP, tcp_keepidle); if (tp->sack_enable) tcp_del_sackholes(tp, th); /* Delete stale SACK holes */ /* * Process options. */ #ifdef TCP_SIGNATURE if (optp || (tp->t_flags & TF_SIGNATURE)) #else if (optp) #endif if (tcp_dooptions(tp, optp, optlen, th, m, iphlen, &opti, m->m_pkthdr.ph_rtableid, now)) goto drop; if (opti.ts_present && opti.ts_ecr) { int32_t rtt_test; /* subtract out the tcp timestamp modulator */ opti.ts_ecr -= tp->ts_modulate; /* make sure ts_ecr is sensible */ rtt_test = now - opti.ts_ecr; if (rtt_test < 0 || rtt_test > TCP_RTT_MAX) opti.ts_ecr = 0; } #ifdef TCP_ECN /* if congestion experienced, set ECE bit in subsequent packets. */ if ((iptos & IPTOS_ECN_MASK) == IPTOS_ECN_CE) { tp->t_flags |= TF_RCVD_CE; tcpstat_inc(tcps_ecn_rcvce); } #endif /* * Header prediction: check for the two common cases * of a uni-directional data xfer. If the packet has * no control flags, is in-sequence, the window didn't * change and we're not retransmitting, it's a * candidate. If the length is zero and the ack moved * forward, we're the sender side of the xfer. Just * free the data acked & wake any higher level process * that was blocked waiting for space. If the length * is non-zero and the ack didn't move, we're the * receiver side. If we're getting packets in-order * (the reassembly queue is empty), add the data to * the socket buffer and note that we need a delayed ack. */ if (tp->t_state == TCPS_ESTABLISHED && #ifdef TCP_ECN (tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ECE|TH_CWR|TH_ACK)) == TH_ACK && #else (tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK && #endif (!opti.ts_present || TSTMP_GEQ(opti.ts_val, tp->ts_recent)) && th->th_seq == tp->rcv_nxt && tiwin && tiwin == tp->snd_wnd && tp->snd_nxt == tp->snd_max) { /* * If last ACK falls within this segment's sequence numbers, * record the timestamp. * Fix from Braden, see Stevens p. 870 */ if (opti.ts_present && SEQ_LEQ(th->th_seq, tp->last_ack_sent)) { tp->ts_recent_age = now; tp->ts_recent = opti.ts_val; } if (tlen == 0) { if (SEQ_GT(th->th_ack, tp->snd_una) && SEQ_LEQ(th->th_ack, tp->snd_max) && tp->snd_cwnd >= tp->snd_wnd && tp->t_dupacks == 0) { /* * this is a pure ack for outstanding data. */ tcpstat_inc(tcps_predack); if (opti.ts_present && opti.ts_ecr) tcp_xmit_timer(tp, now - opti.ts_ecr); else if (tp->t_rtttime && SEQ_GT(th->th_ack, tp->t_rtseq)) tcp_xmit_timer(tp, now - tp->t_rtttime); acked = th->th_ack - tp->snd_una; tcpstat_pkt(tcps_rcvackpack, tcps_rcvackbyte, acked); tp->t_rcvacktime = now; ND6_HINT(tp); sbdrop(so, &so->so_snd, acked); /* * If we had a pending ICMP message that * refers to data that have just been * acknowledged, disregard the recorded ICMP * message. */ if ((tp->t_flags & TF_PMTUD_PEND) && SEQ_GT(th->th_ack, tp->t_pmtud_th_seq)) tp->t_flags &= ~TF_PMTUD_PEND; /* * Keep track of the largest chunk of data * acknowledged since last PMTU update */ if (tp->t_pmtud_mss_acked < acked) tp->t_pmtud_mss_acked = acked; tp->snd_una = th->th_ack; /* Pull snd_wl2 up to prevent seq wrap. */ tp->snd_wl2 = th->th_ack; /* * We want snd_last to track snd_una so * as to avoid sequence wraparound problems * for very large transfers. */ #ifdef TCP_ECN if (SEQ_GT(tp->snd_una, tp->snd_last)) #endif tp->snd_last = tp->snd_una; m_freem(m); /* * If all outstanding data are acked, stop * retransmit timer, otherwise restart timer * using current (possibly backed-off) value. * If process is waiting for space, * wakeup/selwakeup/signal. If data * are ready to send, let tcp_output * decide between more output or persist. */ if (tp->snd_una == tp->snd_max) TCP_TIMER_DISARM(tp, TCPT_REXMT); else if (TCP_TIMER_ISARMED(tp, TCPT_PERSIST) == 0) TCP_TIMER_ARM(tp, TCPT_REXMT, tp->t_rxtcur); tcp_update_sndspace(tp); if (sb_notify(so, &so->so_snd)) { tp->t_flags |= TF_BLOCKOUTPUT; sowwakeup(so); tp->t_flags &= ~TF_BLOCKOUTPUT; } if (so->so_snd.sb_cc || tp->t_flags & TF_NEEDOUTPUT) (void) tcp_output(tp); in_pcbunref(inp); return IPPROTO_DONE; } } else if (th->th_ack == tp->snd_una && TAILQ_EMPTY(&tp->t_segq) && tlen <= sbspace(so, &so->so_rcv)) { /* * This is a pure, in-sequence data packet * with nothing on the reassembly queue and * we have enough buffer space to take it. */ /* Clean receiver SACK report if present */ if (tp->sack_enable && tp->rcv_numsacks) tcp_clean_sackreport(tp); tcpstat_inc(tcps_preddat); tp->rcv_nxt += tlen; /* Pull snd_wl1 and rcv_up up to prevent seq wrap. */ tp->snd_wl1 = th->th_seq; /* Packet has most recent segment, no urgent exists. */ tp->rcv_up = tp->rcv_nxt; tcpstat_pkt(tcps_rcvpack, tcps_rcvbyte, tlen); ND6_HINT(tp); TCP_SETUP_ACK(tp, tiflags, m); /* * Drop TCP, IP headers and TCP options then add data * to socket buffer. */ if (so->so_rcv.sb_state & SS_CANTRCVMORE) m_freem(m); else { if (tp->t_srtt != 0 && tp->rfbuf_ts != 0 && now - tp->rfbuf_ts > (tp->t_srtt >> (TCP_RTT_SHIFT + TCP_RTT_BASE_SHIFT))) { tcp_update_rcvspace(tp); /* Start over with next RTT. */ tp->rfbuf_cnt = 0; tp->rfbuf_ts = 0; } else tp->rfbuf_cnt += tlen; m_adj(m, iphlen + off); sbappendstream(so, &so->so_rcv, m); } tp->t_flags |= TF_BLOCKOUTPUT; sorwakeup(so); tp->t_flags &= ~TF_BLOCKOUTPUT; if (tp->t_flags & (TF_ACKNOW|TF_NEEDOUTPUT)) (void) tcp_output(tp); in_pcbunref(inp); return IPPROTO_DONE; } } /* * Compute mbuf offset to TCP data segment. */ hdroptlen = iphlen + off; /* * Calculate amount of space in receive window, * and then do TCP input processing. * Receive window is amount of space in rcv queue, * but not less than advertised window. */ { int win; win = sbspace(so, &so->so_rcv); if (win < 0) win = 0; tp->rcv_wnd = imax(win, (int)(tp->rcv_adv - tp->rcv_nxt)); } switch (tp->t_state) { /* * If the state is SYN_RECEIVED: * if seg contains SYN/ACK, send an RST. * if seg contains an ACK, but not for our SYN/ACK, send an RST */ case TCPS_SYN_RECEIVED: if (tiflags & TH_ACK) { if (tiflags & TH_SYN) { tcpstat_inc(tcps_badsyn); goto dropwithreset; } if (SEQ_LEQ(th->th_ack, tp->snd_una) || SEQ_GT(th->th_ack, tp->snd_max)) goto dropwithreset; } break; /* * If the state is SYN_SENT: * if seg contains an ACK, but not for our SYN, drop the input. * if seg contains a RST, then drop the connection. * if seg does not contain SYN, then drop it. * Otherwise this is an acceptable SYN segment * initialize tp->rcv_nxt and tp->irs * if seg contains ack then advance tp->snd_una * if SYN has been acked change to ESTABLISHED else SYN_RCVD state * arrange for segment to be acked (eventually) * continue processing rest of data/controls, beginning with URG */ case TCPS_SYN_SENT: if ((tiflags & TH_ACK) && (SEQ_LEQ(th->th_ack, tp->iss) || SEQ_GT(th->th_ack, tp->snd_max))) goto dropwithreset; if (tiflags & TH_RST) { #ifdef TCP_ECN /* if ECN is enabled, fall back to non-ecn at rexmit */ if (tcp_do_ecn && !(tp->t_flags & TF_DISABLE_ECN)) goto drop; #endif if (tiflags & TH_ACK) tp = tcp_drop(tp, ECONNREFUSED); goto drop; } if ((tiflags & TH_SYN) == 0) goto drop; if (tiflags & TH_ACK) { tp->snd_una = th->th_ack; if (SEQ_LT(tp->snd_nxt, tp->snd_una)) tp->snd_nxt = tp->snd_una; } TCP_TIMER_DISARM(tp, TCPT_REXMT); tp->irs = th->th_seq; tcp_mss(tp, opti.maxseg); /* Reset initial window to 1 segment for retransmit */ if (tp->t_rxtshift > 0) tp->snd_cwnd = tp->t_maxseg; tcp_rcvseqinit(tp); tp->t_flags |= TF_ACKNOW; /* * If we've sent a SACK_PERMITTED option, and the peer * also replied with one, then TF_SACK_PERMIT should have * been set in tcp_dooptions(). If it was not, disable SACKs. */ if (tp->sack_enable) tp->sack_enable = tp->t_flags & TF_SACK_PERMIT; #ifdef TCP_ECN /* * if ECE is set but CWR is not set for SYN-ACK, or * both ECE and CWR are set for simultaneous open, * peer is ECN capable. */ if (tcp_do_ecn) { switch (tiflags & (TH_ACK|TH_ECE|TH_CWR)) { case TH_ACK|TH_ECE: case TH_ECE|TH_CWR: tp->t_flags |= TF_ECN_PERMIT; tiflags &= ~(TH_ECE|TH_CWR); tcpstat_inc(tcps_ecn_accepts); } } #endif if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) { tcpstat_inc(tcps_connects); tp->t_flags |= TF_BLOCKOUTPUT; soisconnected(so); tp->t_flags &= ~TF_BLOCKOUTPUT; tp->t_state = TCPS_ESTABLISHED; TCP_TIMER_ARM(tp, TCPT_KEEP, tcp_keepidle); /* Do window scaling on this connection? */ if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == (TF_RCVD_SCALE|TF_REQ_SCALE)) { tp->snd_scale = tp->requested_s_scale; tp->rcv_scale = tp->request_r_scale; } tcp_flush_queue(tp); /* * if we didn't have to retransmit the SYN, * use its rtt as our initial srtt & rtt var. */ if (tp->t_rtttime) tcp_xmit_timer(tp, now - tp->t_rtttime); /* * Since new data was acked (the SYN), open the * congestion window by one MSS. We do this * here, because we won't go through the normal * ACK processing below. And since this is the * start of the connection, we know we are in * the exponential phase of slow-start. */ tp->snd_cwnd += tp->t_maxseg; } else tp->t_state = TCPS_SYN_RECEIVED; #if 0 trimthenstep6: #endif /* * Advance th->th_seq to correspond to first data byte. * If data, trim to stay within window, * dropping FIN if necessary. */ th->th_seq++; if (tlen > tp->rcv_wnd) { todrop = tlen - tp->rcv_wnd; m_adj(m, -todrop); tlen = tp->rcv_wnd; tiflags &= ~TH_FIN; tcpstat_pkt(tcps_rcvpackafterwin, tcps_rcvbyteafterwin, todrop); } tp->snd_wl1 = th->th_seq - 1; tp->rcv_up = th->th_seq; goto step6; /* * If a new connection request is received while in TIME_WAIT, * drop the old connection and start over if the if the * timestamp or the sequence numbers are above the previous * ones. */ case TCPS_TIME_WAIT: if (((tiflags & (TH_SYN|TH_ACK)) == TH_SYN) && ((opti.ts_present && TSTMP_LT(tp->ts_recent, opti.ts_val)) || SEQ_GT(th->th_seq, tp->rcv_nxt))) { #if NPF > 0 /* * The socket will be recreated but the new state * has already been linked to the socket. Remove the * link between old socket and new state. */ pf_inp_unlink(inp); #endif /* * Advance the iss by at least 32768, but * clear the msb in order to make sure * that SEG_LT(snd_nxt, iss). */ iss = tp->snd_nxt + ((arc4random() & 0x7fffffff) | 0x8000); reuse = &iss; tp = tcp_close(tp); in_pcbunref(inp); inp = NULL; goto findpcb; } } /* * States other than LISTEN or SYN_SENT. * First check timestamp, if present. * Then check that at least some bytes of segment are within * receive window. If segment begins before rcv_nxt, * drop leading data (and SYN); if nothing left, just ack. * * RFC 1323 PAWS: If we have a timestamp reply on this segment * and it's less than opti.ts_recent, drop it. */ if (opti.ts_present && (tiflags & TH_RST) == 0 && tp->ts_recent && TSTMP_LT(opti.ts_val, tp->ts_recent)) { /* Check to see if ts_recent is over 24 days old. */ if (now - tp->ts_recent_age > TCP_PAWS_IDLE) { /* * Invalidate ts_recent. If this segment updates * ts_recent, the age will be reset later and ts_recent * will get a valid value. If it does not, setting * ts_recent to zero will at least satisfy the * requirement that zero be placed in the timestamp * echo reply when ts_recent isn't valid. The * age isn't reset until we get a valid ts_recent * because we don't want out-of-order segments to be * dropped when ts_recent is old. */ tp->ts_recent = 0; } else { tcpstat_pkt(tcps_rcvduppack, tcps_rcvdupbyte, tlen); tcpstat_inc(tcps_pawsdrop); if (tlen) goto dropafterack; goto drop; } } todrop = tp->rcv_nxt - th->th_seq; if (todrop > 0) { if (tiflags & TH_SYN) { tiflags &= ~TH_SYN; th->th_seq++; if (th->th_urp > 1) th->th_urp--; else tiflags &= ~TH_URG; todrop--; } if (todrop > tlen || (todrop == tlen && (tiflags & TH_FIN) == 0)) { /* * Any valid FIN must be to the left of the * window. At this point, FIN must be a * duplicate or out-of-sequence, so drop it. */ tiflags &= ~TH_FIN; /* * Send ACK to resynchronize, and drop any data, * but keep on processing for RST or ACK. */ tp->t_flags |= TF_ACKNOW; todrop = tlen; tcpstat_pkt(tcps_rcvduppack, tcps_rcvdupbyte, todrop); } else { tcpstat_pkt(tcps_rcvpartduppack, tcps_rcvpartdupbyte, todrop); } hdroptlen += todrop; /* drop from head afterwards */ th->th_seq += todrop; tlen -= todrop; if (th->th_urp > todrop) th->th_urp -= todrop; else { tiflags &= ~TH_URG; th->th_urp = 0; } } /* * If new data are received on a connection after the * user processes are gone, then RST the other end. */ if ((so->so_state & SS_NOFDREF) && tp->t_state > TCPS_CLOSE_WAIT && tlen) { tp = tcp_close(tp); tcpstat_inc(tcps_rcvafterclose); goto dropwithreset; } /* * If segment ends after window, drop trailing data * (and PUSH and FIN); if nothing left, just ACK. */ todrop = (th->th_seq + tlen) - (tp->rcv_nxt+tp->rcv_wnd); if (todrop > 0) { tcpstat_inc(tcps_rcvpackafterwin); if (todrop >= tlen) { tcpstat_add(tcps_rcvbyteafterwin, tlen); /* * If window is closed can only take segments at * window edge, and have to drop data and PUSH from * incoming segments. Continue processing, but * remember to ack. Otherwise, drop segment * and ack. */ if (tp->rcv_wnd == 0 && th->th_seq == tp->rcv_nxt) { tp->t_flags |= TF_ACKNOW; tcpstat_inc(tcps_rcvwinprobe); } else goto dropafterack; } else tcpstat_add(tcps_rcvbyteafterwin, todrop); m_adj(m, -todrop); tlen -= todrop; tiflags &= ~(TH_PUSH|TH_FIN); } /* * If last ACK falls within this segment's sequence numbers, * record its timestamp if it's more recent. * NOTE that the test is modified according to the latest * proposal of the tcplw@cray.com list (Braden 1993/04/26). */ if (opti.ts_present && TSTMP_GEQ(opti.ts_val, tp->ts_recent) && SEQ_LEQ(th->th_seq, tp->last_ack_sent)) { tp->ts_recent_age = now; tp->ts_recent = opti.ts_val; } /* * If the RST bit is set examine the state: * SYN_RECEIVED STATE: * If passive open, return to LISTEN state. * If active open, inform user that connection was refused. * ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES: * Inform user that connection was reset, and close tcb. * CLOSING, LAST_ACK, TIME_WAIT STATES * Close the tcb. */ if (tiflags & TH_RST) { if (th->th_seq != tp->last_ack_sent && th->th_seq != tp->rcv_nxt && th->th_seq != (tp->rcv_nxt + 1)) goto drop; switch (tp->t_state) { case TCPS_SYN_RECEIVED: #ifdef TCP_ECN /* if ECN is enabled, fall back to non-ecn at rexmit */ if (tcp_do_ecn && !(tp->t_flags & TF_DISABLE_ECN)) goto drop; #endif so->so_error = ECONNREFUSED; goto close; case TCPS_ESTABLISHED: case TCPS_FIN_WAIT_1: case TCPS_FIN_WAIT_2: case TCPS_CLOSE_WAIT: so->so_error = ECONNRESET; close: tp->t_state = TCPS_CLOSED; tcpstat_inc(tcps_drops); tp = tcp_close(tp); goto drop; case TCPS_CLOSING: case TCPS_LAST_ACK: case TCPS_TIME_WAIT: tp = tcp_close(tp); goto drop; } } /* * If a SYN is in the window, then this is an * error and we ACK and drop the packet. */ if (tiflags & TH_SYN) goto dropafterack_ratelim; /* * If the ACK bit is off we drop the segment and return. */ if ((tiflags & TH_ACK) == 0) { if (tp->t_flags & TF_ACKNOW) goto dropafterack; else goto drop; } /* * Ack processing. */ switch (tp->t_state) { /* * In SYN_RECEIVED state, the ack ACKs our SYN, so enter * ESTABLISHED state and continue processing. * The ACK was checked above. */ case TCPS_SYN_RECEIVED: tcpstat_inc(tcps_connects); tp->t_flags |= TF_BLOCKOUTPUT; soisconnected(so); tp->t_flags &= ~TF_BLOCKOUTPUT; tp->t_state = TCPS_ESTABLISHED; TCP_TIMER_ARM(tp, TCPT_KEEP, tcp_keepidle); /* Do window scaling? */ if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == (TF_RCVD_SCALE|TF_REQ_SCALE)) { tp->snd_scale = tp->requested_s_scale; tp->rcv_scale = tp->request_r_scale; tiwin = th->th_win << tp->snd_scale; } tcp_flush_queue(tp); tp->snd_wl1 = th->th_seq - 1; /* fall into ... */ /* * In ESTABLISHED state: drop duplicate ACKs; ACK out of range * ACKs. If the ack is in the range * tp->snd_una < th->th_ack <= tp->snd_max * then advance tp->snd_una to th->th_ack and drop * data from the retransmission queue. If this ACK reflects * more up to date window information we update our window information. */ case TCPS_ESTABLISHED: case TCPS_FIN_WAIT_1: case TCPS_FIN_WAIT_2: case TCPS_CLOSE_WAIT: case TCPS_CLOSING: case TCPS_LAST_ACK: case TCPS_TIME_WAIT: #ifdef TCP_ECN /* * if we receive ECE and are not already in recovery phase, * reduce cwnd by half but don't slow-start. * advance snd_last to snd_max not to reduce cwnd again * until all outstanding packets are acked. */ if (tcp_do_ecn && (tiflags & TH_ECE)) { if ((tp->t_flags & TF_ECN_PERMIT) && SEQ_GEQ(tp->snd_una, tp->snd_last)) { u_int win; win = min(tp->snd_wnd, tp->snd_cwnd) / tp->t_maxseg; if (win > 1) { tp->snd_ssthresh = win / 2 * tp->t_maxseg; tp->snd_cwnd = tp->snd_ssthresh; tp->snd_last = tp->snd_max; tp->t_flags |= TF_SEND_CWR; tcpstat_inc(tcps_cwr_ecn); } } tcpstat_inc(tcps_ecn_rcvece); } /* * if we receive CWR, we know that the peer has reduced * its congestion window. stop sending ecn-echo. */ if ((tiflags & TH_CWR)) { tp->t_flags &= ~TF_RCVD_CE; tcpstat_inc(tcps_ecn_rcvcwr); } #endif /* TCP_ECN */ if (SEQ_LEQ(th->th_ack, tp->snd_una)) { /* * Duplicate/old ACK processing. * Increments t_dupacks: * Pure duplicate (same seq/ack/window, no data) * Doesn't affect t_dupacks: * Data packets. * Normal window updates (window opens) * Resets t_dupacks: * New data ACKed. * Window shrinks * Old ACK */ if (tlen) { /* Drop very old ACKs unless th_seq matches */ if (th->th_seq != tp->rcv_nxt && SEQ_LT(th->th_ack, tp->snd_una - tp->max_sndwnd)) { tcpstat_inc(tcps_rcvacktooold); goto drop; } break; } /* * If we get an old ACK, there is probably packet * reordering going on. Be conservative and reset * t_dupacks so that we are less aggressive in * doing a fast retransmit. */ if (th->th_ack != tp->snd_una) { tp->t_dupacks = 0; break; } if (tiwin == tp->snd_wnd) { tcpstat_inc(tcps_rcvdupack); /* * If we have outstanding data (other than * a window probe), this is a completely * duplicate ack (ie, window info didn't * change), the ack is the biggest we've * seen and we've seen exactly our rexmt * threshold of them, assume a packet * has been dropped and retransmit it. * Kludge snd_nxt & the congestion * window so we send only this one * packet. * * We know we're losing at the current * window size so do congestion avoidance * (set ssthresh to half the current window * and pull our congestion window back to * the new ssthresh). * * Dup acks mean that packets have left the * network (they're now cached at the receiver) * so bump cwnd by the amount in the receiver * to keep a constant cwnd packets in the * network. */ if (TCP_TIMER_ISARMED(tp, TCPT_REXMT) == 0) tp->t_dupacks = 0; else if (++tp->t_dupacks == tcprexmtthresh) { tcp_seq onxt = tp->snd_nxt; u_long win = ulmin(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg; if (SEQ_LT(th->th_ack, tp->snd_last)){ /* * False fast retx after * timeout. Do not cut window. */ tp->t_dupacks = 0; goto drop; } if (win < 2) win = 2; tp->snd_ssthresh = win * tp->t_maxseg; tp->snd_last = tp->snd_max; if (tp->sack_enable) { TCP_TIMER_DISARM(tp, TCPT_REXMT); tp->t_rtttime = 0; #ifdef TCP_ECN tp->t_flags |= TF_SEND_CWR; #endif tcpstat_inc(tcps_cwr_frecovery); tcpstat_inc(tcps_sack_recovery_episode); /* * tcp_output() will send * oldest SACK-eligible rtx. */ (void) tcp_output(tp); tp->snd_cwnd = tp->snd_ssthresh+ tp->t_maxseg * tp->t_dupacks; goto drop; } TCP_TIMER_DISARM(tp, TCPT_REXMT); tp->t_rtttime = 0; tp->snd_nxt = th->th_ack; tp->snd_cwnd = tp->t_maxseg; #ifdef TCP_ECN tp->t_flags |= TF_SEND_CWR; #endif tcpstat_inc(tcps_cwr_frecovery); tcpstat_inc(tcps_sndrexmitfast); (void) tcp_output(tp); tp->snd_cwnd = tp->snd_ssthresh + tp->t_maxseg * tp->t_dupacks; if (SEQ_GT(onxt, tp->snd_nxt)) tp->snd_nxt = onxt; goto drop; } else if (tp->t_dupacks > tcprexmtthresh) { tp->snd_cwnd += tp->t_maxseg; (void) tcp_output(tp); goto drop; } } else if (tiwin < tp->snd_wnd) { /* * The window was retracted! Previous dup * ACKs may have been due to packets arriving * after the shrunken window, not a missing * packet, so play it safe and reset t_dupacks */ tp->t_dupacks = 0; } break; } /* * If the congestion window was inflated to account * for the other side's cached packets, retract it. */ if (tp->t_dupacks >= tcprexmtthresh) { /* Check for a partial ACK */ if (SEQ_LT(th->th_ack, tp->snd_last)) { if (tp->sack_enable) tcp_sack_partialack(tp, th); else tcp_newreno_partialack(tp, th); } else { /* Out of fast recovery */ tp->snd_cwnd = tp->snd_ssthresh; if (tcp_seq_subtract(tp->snd_max, th->th_ack) < tp->snd_ssthresh) tp->snd_cwnd = tcp_seq_subtract(tp->snd_max, th->th_ack); tp->t_dupacks = 0; } } else { /* * Reset the duplicate ACK counter if we * were not in fast recovery. */ tp->t_dupacks = 0; } if (SEQ_GT(th->th_ack, tp->snd_max)) { tcpstat_inc(tcps_rcvacktoomuch); goto dropafterack_ratelim; } acked = th->th_ack - tp->snd_una; tcpstat_pkt(tcps_rcvackpack, tcps_rcvackbyte, acked); tp->t_rcvacktime = now; /* * If we have a timestamp reply, update smoothed * round trip time. If no timestamp is present but * transmit timer is running and timed sequence * number was acked, update smoothed round trip time. * Since we now have an rtt measurement, cancel the * timer backoff (cf., Phil Karn's retransmit alg.). * Recompute the initial retransmit timer. */ if (opti.ts_present && opti.ts_ecr) tcp_xmit_timer(tp, now - opti.ts_ecr); else if (tp->t_rtttime && SEQ_GT(th->th_ack, tp->t_rtseq)) tcp_xmit_timer(tp, now - tp->t_rtttime); /* * If all outstanding data is acked, stop retransmit * timer and remember to restart (more output or persist). * If there is more data to be acked, restart retransmit * timer, using current (possibly backed-off) value. */ if (th->th_ack == tp->snd_max) { TCP_TIMER_DISARM(tp, TCPT_REXMT); tp->t_flags |= TF_NEEDOUTPUT; } else if (TCP_TIMER_ISARMED(tp, TCPT_PERSIST) == 0) TCP_TIMER_ARM(tp, TCPT_REXMT, tp->t_rxtcur); /* * When new data is acked, open the congestion window. * If the window gives us less than ssthresh packets * in flight, open exponentially (maxseg per packet). * Otherwise open linearly: maxseg per window * (maxseg^2 / cwnd per packet). */ { u_int cw = tp->snd_cwnd; u_int incr = tp->t_maxseg; if (cw > tp->snd_ssthresh) incr = max(incr * incr / cw, 1); if (tp->t_dupacks < tcprexmtthresh) tp->snd_cwnd = ulmin(cw + incr, TCP_MAXWIN << tp->snd_scale); } ND6_HINT(tp); if (acked > so->so_snd.sb_cc) { if (tp->snd_wnd > so->so_snd.sb_cc) tp->snd_wnd -= so->so_snd.sb_cc; else tp->snd_wnd = 0; sbdrop(so, &so->so_snd, (int)so->so_snd.sb_cc); ourfinisacked = 1; } else { sbdrop(so, &so->so_snd, acked); if (tp->snd_wnd > acked) tp->snd_wnd -= acked; else tp->snd_wnd = 0; ourfinisacked = 0; } tcp_update_sndspace(tp); if (sb_notify(so, &so->so_snd)) { tp->t_flags |= TF_BLOCKOUTPUT; sowwakeup(so); tp->t_flags &= ~TF_BLOCKOUTPUT; } /* * If we had a pending ICMP message that referred to data * that have just been acknowledged, disregard the recorded * ICMP message. */ if ((tp->t_flags & TF_PMTUD_PEND) && SEQ_GT(th->th_ack, tp->t_pmtud_th_seq)) tp->t_flags &= ~TF_PMTUD_PEND; /* * Keep track of the largest chunk of data acknowledged * since last PMTU update */ if (tp->t_pmtud_mss_acked < acked) tp->t_pmtud_mss_acked = acked; tp->snd_una = th->th_ack; #ifdef TCP_ECN /* sync snd_last with snd_una */ if (SEQ_GT(tp->snd_una, tp->snd_last)) tp->snd_last = tp->snd_una; #endif if (SEQ_LT(tp->snd_nxt, tp->snd_una)) tp->snd_nxt = tp->snd_una; switch (tp->t_state) { /* * In FIN_WAIT_1 STATE in addition to the processing * for the ESTABLISHED state if our FIN is now acknowledged * then enter FIN_WAIT_2. */ case TCPS_FIN_WAIT_1: if (ourfinisacked) { /* * If we can't receive any more * data, then closing user can proceed. * Starting the timer is contrary to the * specification, but if we don't get a FIN * we'll hang forever. */ if (so->so_rcv.sb_state & SS_CANTRCVMORE) { tp->t_flags |= TF_BLOCKOUTPUT; soisdisconnected(so); tp->t_flags &= ~TF_BLOCKOUTPUT; TCP_TIMER_ARM(tp, TCPT_2MSL, tcp_maxidle); } tp->t_state = TCPS_FIN_WAIT_2; } break; /* * In CLOSING STATE in addition to the processing for * the ESTABLISHED state if the ACK acknowledges our FIN * then enter the TIME-WAIT state, otherwise ignore * the segment. */ case TCPS_CLOSING: if (ourfinisacked) { tp->t_state = TCPS_TIME_WAIT; tcp_canceltimers(tp); TCP_TIMER_ARM(tp, TCPT_2MSL, 2 * TCPTV_MSL); tp->t_flags |= TF_BLOCKOUTPUT; soisdisconnected(so); tp->t_flags &= ~TF_BLOCKOUTPUT; } break; /* * In LAST_ACK, we may still be waiting for data to drain * and/or to be acked, as well as for the ack of our FIN. * If our FIN is now acknowledged, delete the TCB, * enter the closed state and return. */ case TCPS_LAST_ACK: if (ourfinisacked) { tp = tcp_close(tp); goto drop; } break; /* * In TIME_WAIT state the only thing that should arrive * is a retransmission of the remote FIN. Acknowledge * it and restart the finack timer. */ case TCPS_TIME_WAIT: TCP_TIMER_ARM(tp, TCPT_2MSL, 2 * TCPTV_MSL); goto dropafterack; } } step6: /* * Update window information. * Don't look at window if no ACK: TAC's send garbage on first SYN. */ if ((tiflags & TH_ACK) && (SEQ_LT(tp->snd_wl1, th->th_seq) || (tp->snd_wl1 == th->th_seq && (SEQ_LT(tp->snd_wl2, th->th_ack) || (tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd))))) { /* keep track of pure window updates */ if (tlen == 0 && tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd) tcpstat_inc(tcps_rcvwinupd); tp->snd_wnd = tiwin; tp->snd_wl1 = th->th_seq; tp->snd_wl2 = th->th_ack; if (tp->snd_wnd > tp->max_sndwnd) tp->max_sndwnd = tp->snd_wnd; tp->t_flags |= TF_NEEDOUTPUT; } /* * Process segments with URG. */ if ((tiflags & TH_URG) && th->th_urp && TCPS_HAVERCVDFIN(tp->t_state) == 0) { /* * This is a kludge, but if we receive and accept * random urgent pointers, we'll crash in * soreceive. It's hard to imagine someone * actually wanting to send this much urgent data. */ if (th->th_urp + so->so_rcv.sb_cc > sb_max) { th->th_urp = 0; /* XXX */ tiflags &= ~TH_URG; /* XXX */ goto dodata; /* XXX */ } /* * If this segment advances the known urgent pointer, * then mark the data stream. This should not happen * in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since * a FIN has been received from the remote side. * In these states we ignore the URG. * * According to RFC961 (Assigned Protocols), * the urgent pointer points to the last octet * of urgent data. We continue, however, * to consider it to indicate the first octet * of data past the urgent section as the original * spec states (in one of two places). */ if (SEQ_GT(th->th_seq+th->th_urp, tp->rcv_up)) { tp->rcv_up = th->th_seq + th->th_urp; so->so_oobmark = so->so_rcv.sb_cc + (tp->rcv_up - tp->rcv_nxt) - 1; if (so->so_oobmark == 0) so->so_rcv.sb_state |= SS_RCVATMARK; sohasoutofband(so); tp->t_oobflags &= ~(TCPOOB_HAVEDATA | TCPOOB_HADDATA); } /* * Remove out of band data so doesn't get presented to user. * This can happen independent of advancing the URG pointer, * but if two URG's are pending at once, some out-of-band * data may creep in... ick. */ if (th->th_urp <= (u_int16_t) tlen && (so->so_options & SO_OOBINLINE) == 0) tcp_pulloutofband(so, th->th_urp, m, hdroptlen); } else /* * If no out of band data is expected, * pull receive urgent pointer along * with the receive window. */ if (SEQ_GT(tp->rcv_nxt, tp->rcv_up)) tp->rcv_up = tp->rcv_nxt; dodata: /* XXX */ /* * Process the segment text, merging it into the TCP sequencing queue, * and arranging for acknowledgment of receipt if necessary. * This process logically involves adjusting tp->rcv_wnd as data * is presented to the user (this happens in tcp_usrreq.c, * case PRU_RCVD). If a FIN has already been received on this * connection then we just ignore the text. */ if ((tlen || (tiflags & TH_FIN)) && TCPS_HAVERCVDFIN(tp->t_state) == 0) { tcp_seq laststart = th->th_seq; tcp_seq lastend = th->th_seq + tlen; if (th->th_seq == tp->rcv_nxt && TAILQ_EMPTY(&tp->t_segq) && tp->t_state == TCPS_ESTABLISHED) { TCP_SETUP_ACK(tp, tiflags, m); tp->rcv_nxt += tlen; tiflags = th->th_flags & TH_FIN; tcpstat_pkt(tcps_rcvpack, tcps_rcvbyte, tlen); ND6_HINT(tp); if (so->so_rcv.sb_state & SS_CANTRCVMORE) m_freem(m); else { m_adj(m, hdroptlen); sbappendstream(so, &so->so_rcv, m); } tp->t_flags |= TF_BLOCKOUTPUT; sorwakeup(so); tp->t_flags &= ~TF_BLOCKOUTPUT; } else { m_adj(m, hdroptlen); tiflags = tcp_reass(tp, th, m, &tlen); tp->t_flags |= TF_ACKNOW; } if (tp->sack_enable) tcp_update_sack_list(tp, laststart, lastend); /* * variable len never referenced again in modern BSD, * so why bother computing it ?? */ #if 0 /* * Note the amount of data that peer has sent into * our window, in order to estimate the sender's * buffer size. */ len = so->so_rcv.sb_hiwat - (tp->rcv_adv - tp->rcv_nxt); #endif /* 0 */ } else { m_freem(m); tiflags &= ~TH_FIN; } /* * If FIN is received ACK the FIN and let the user know * that the connection is closing. Ignore a FIN received before * the connection is fully established. */ if ((tiflags & TH_FIN) && TCPS_HAVEESTABLISHED(tp->t_state)) { if (TCPS_HAVERCVDFIN(tp->t_state) == 0) { tp->t_flags |= TF_BLOCKOUTPUT; socantrcvmore(so); tp->t_flags &= ~TF_BLOCKOUTPUT; tp->t_flags |= TF_ACKNOW; tp->rcv_nxt++; } switch (tp->t_state) { /* * In ESTABLISHED STATE enter the CLOSE_WAIT state. */ case TCPS_ESTABLISHED: tp->t_state = TCPS_CLOSE_WAIT; break; /* * If still in FIN_WAIT_1 STATE FIN has not been acked so * enter the CLOSING state. */ case TCPS_FIN_WAIT_1: tp->t_state = TCPS_CLOSING; break; /* * In FIN_WAIT_2 state enter the TIME_WAIT state, * starting the time-wait timer, turning off the other * standard timers. */ case TCPS_FIN_WAIT_2: tp->t_state = TCPS_TIME_WAIT; tcp_canceltimers(tp); TCP_TIMER_ARM(tp, TCPT_2MSL, 2 * TCPTV_MSL); tp->t_flags |= TF_BLOCKOUTPUT; soisdisconnected(so); tp->t_flags &= ~TF_BLOCKOUTPUT; break; /* * In TIME_WAIT state restart the 2 MSL time_wait timer. */ case TCPS_TIME_WAIT: TCP_TIMER_ARM(tp, TCPT_2MSL, 2 * TCPTV_MSL); break; } } if (otp) tcp_trace(TA_INPUT, ostate, tp, otp, &saveti.caddr, 0, tlen); /* * Return any desired output. */ if (tp->t_flags & (TF_ACKNOW|TF_NEEDOUTPUT)) (void) tcp_output(tp); in_pcbunref(inp); return IPPROTO_DONE; badsyn: /* * Received a bad SYN. Increment counters and dropwithreset. */ tcpstat_inc(tcps_badsyn); tp = NULL; goto dropwithreset; dropafterack_ratelim: if (ppsratecheck(&tcp_ackdrop_ppslim_last, &tcp_ackdrop_ppslim_count, tcp_ackdrop_ppslim) == 0) { /* XXX stat */ goto drop; } /* ...fall into dropafterack... */ dropafterack: /* * Generate an ACK dropping incoming segment if it occupies * sequence space, where the ACK reflects our state. */ if (tiflags & TH_RST) goto drop; m_freem(m); tp->t_flags |= TF_ACKNOW; (void) tcp_output(tp); in_pcbunref(inp); return IPPROTO_DONE; dropwithreset_ratelim: /* * We may want to rate-limit RSTs in certain situations, * particularly if we are sending an RST in response to * an attempt to connect to or otherwise communicate with * a port for which we have no socket. */ if (ppsratecheck(&tcp_rst_ppslim_last, &tcp_rst_ppslim_count, tcp_rst_ppslim) == 0) { /* XXX stat */ goto drop; } /* ...fall into dropwithreset... */ dropwithreset: /* * Generate a RST, dropping incoming segment. * Make ACK acceptable to originator of segment. * Don't bother to respond to RST. */ if (tiflags & TH_RST) goto drop; if (tiflags & TH_ACK) { tcp_respond(tp, mtod(m, caddr_t), th, (tcp_seq)0, th->th_ack, TH_RST, m->m_pkthdr.ph_rtableid, now); } else { if (tiflags & TH_SYN) tlen++; tcp_respond(tp, mtod(m, caddr_t), th, th->th_seq + tlen, (tcp_seq)0, TH_RST|TH_ACK, m->m_pkthdr.ph_rtableid, now); } m_freem(m); in_pcbunref(inp); return IPPROTO_DONE; drop: /* * Drop space held by incoming segment and return. */ if (otp) tcp_trace(TA_DROP, ostate, tp, otp, &saveti.caddr, 0, tlen); m_freem(m); in_pcbunref(inp); return IPPROTO_DONE; } int tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, struct tcphdr *th, struct mbuf *m, int iphlen, struct tcp_opt_info *oi, u_int rtableid, uint64_t now) { u_int16_t mss = 0; int opt, optlen; #ifdef TCP_SIGNATURE caddr_t sigp = NULL; struct tdb *tdb = NULL; #endif /* TCP_SIGNATURE */ for (; cp && cnt > 0; cnt -= optlen, cp += optlen) { opt = cp[0]; if (opt == TCPOPT_EOL) break; if (opt == TCPOPT_NOP) optlen = 1; else { if (cnt < 2) break; optlen = cp[1]; if (optlen < 2 || optlen > cnt) break; } switch (opt) { default: continue; case TCPOPT_MAXSEG: if (optlen != TCPOLEN_MAXSEG) continue; if (!(th->th_flags & TH_SYN)) continue; if (TCPS_HAVERCVDSYN(tp->t_state)) continue; memcpy(&mss, cp + 2, sizeof(mss)); mss = ntohs(mss); oi->maxseg = mss; break; case TCPOPT_WINDOW: if (optlen != TCPOLEN_WINDOW) continue; if (!(th->th_flags & TH_SYN)) continue; if (TCPS_HAVERCVDSYN(tp->t_state)) continue; tp->t_flags |= TF_RCVD_SCALE; tp->requested_s_scale = min(cp[2], TCP_MAX_WINSHIFT); break; case TCPOPT_TIMESTAMP: if (optlen != TCPOLEN_TIMESTAMP) continue; oi->ts_present = 1; memcpy(&oi->ts_val, cp + 2, sizeof(oi->ts_val)); oi->ts_val = ntohl(oi->ts_val); memcpy(&oi->ts_ecr, cp + 6, sizeof(oi->ts_ecr)); oi->ts_ecr = ntohl(oi->ts_ecr); if (!(th->th_flags & TH_SYN)) continue; if (TCPS_HAVERCVDSYN(tp->t_state)) continue; /* * A timestamp received in a SYN makes * it ok to send timestamp requests and replies. */ tp->t_flags |= TF_RCVD_TSTMP; tp->ts_recent = oi->ts_val; tp->ts_recent_age = now; break; case TCPOPT_SACK_PERMITTED: if (!tp->sack_enable || optlen!=TCPOLEN_SACK_PERMITTED) continue; if (!(th->th_flags & TH_SYN)) continue; if (TCPS_HAVERCVDSYN(tp->t_state)) continue; /* MUST only be set on SYN */ tp->t_flags |= TF_SACK_PERMIT; break; case TCPOPT_SACK: tcp_sack_option(tp, th, cp, optlen); break; #ifdef TCP_SIGNATURE case TCPOPT_SIGNATURE: if (optlen != TCPOLEN_SIGNATURE) continue; if (sigp && timingsafe_bcmp(sigp, cp + 2, 16)) goto bad; sigp = cp + 2; break; #endif /* TCP_SIGNATURE */ } } #ifdef TCP_SIGNATURE if (tp->t_flags & TF_SIGNATURE) { union sockaddr_union src, dst; memset(&src, 0, sizeof(union sockaddr_union)); memset(&dst, 0, sizeof(union sockaddr_union)); switch (tp->pf) { case 0: case AF_INET: src.sa.sa_len = sizeof(struct sockaddr_in); src.sa.sa_family = AF_INET; src.sin.sin_addr = mtod(m, struct ip *)->ip_src; dst.sa.sa_len = sizeof(struct sockaddr_in); dst.sa.sa_family = AF_INET; dst.sin.sin_addr = mtod(m, struct ip *)->ip_dst; break; #ifdef INET6 case AF_INET6: src.sa.sa_len = sizeof(struct sockaddr_in6); src.sa.sa_family = AF_INET6; src.sin6.sin6_addr = mtod(m, struct ip6_hdr *)->ip6_src; dst.sa.sa_len = sizeof(struct sockaddr_in6); dst.sa.sa_family = AF_INET6; dst.sin6.sin6_addr = mtod(m, struct ip6_hdr *)->ip6_dst; break; #endif /* INET6 */ } tdb = gettdbbysrcdst(rtable_l2(rtableid), 0, &src, &dst, IPPROTO_TCP); /* * We don't have an SA for this peer, so we turn off * TF_SIGNATURE on the listen socket */ if (tdb == NULL && tp->t_state == TCPS_LISTEN) tp->t_flags &= ~TF_SIGNATURE; } if ((sigp ? TF_SIGNATURE : 0) ^ (tp->t_flags & TF_SIGNATURE)) { tcpstat_inc(tcps_rcvbadsig); goto bad; } if (sigp) { char sig[16]; if (tdb == NULL) { tcpstat_inc(tcps_rcvbadsig); goto bad; } if (tcp_signature(tdb, tp->pf, m, th, iphlen, 1, sig) < 0) goto bad; if (timingsafe_bcmp(sig, sigp, 16)) { tcpstat_inc(tcps_rcvbadsig); goto bad; } tcpstat_inc(tcps_rcvgoodsig); } tdb_unref(tdb); #endif /* TCP_SIGNATURE */ return (0); #ifdef TCP_SIGNATURE bad: tdb_unref(tdb); #endif /* TCP_SIGNATURE */ return (-1); } u_long tcp_seq_subtract(u_long a, u_long b) { return ((long)(a - b)); } /* * This function is called upon receipt of new valid data (while not in header * prediction mode), and it updates the ordered list of sacks. */ void tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_laststart, tcp_seq rcv_lastend) { /* * First reported block MUST be the most recent one. Subsequent * blocks SHOULD be in the order in which they arrived at the * receiver. These two conditions make the implementation fully * compliant with RFC 2018. */ int i, j = 0, count = 0, lastpos = -1; struct sackblk sack, firstsack, temp[MAX_SACK_BLKS]; /* First clean up current list of sacks */ for (i = 0; i < tp->rcv_numsacks; i++) { sack = tp->sackblks[i]; if (sack.start == 0 && sack.end == 0) { count++; /* count = number of blocks to be discarded */ continue; } if (SEQ_LEQ(sack.end, tp->rcv_nxt)) { tp->sackblks[i].start = tp->sackblks[i].end = 0; count++; } else { temp[j].start = tp->sackblks[i].start; temp[j++].end = tp->sackblks[i].end; } } tp->rcv_numsacks -= count; if (tp->rcv_numsacks == 0) { /* no sack blocks currently (fast path) */ tcp_clean_sackreport(tp); if (SEQ_LT(tp->rcv_nxt, rcv_laststart)) { /* ==> need first sack block */ tp->sackblks[0].start = rcv_laststart; tp->sackblks[0].end = rcv_lastend; tp->rcv_numsacks = 1; } return; } /* Otherwise, sack blocks are already present. */ for (i = 0; i < tp->rcv_numsacks; i++) tp->sackblks[i] = temp[i]; /* first copy back sack list */ if (SEQ_GEQ(tp->rcv_nxt, rcv_lastend)) return; /* sack list remains unchanged */ /* * From here, segment just received should be (part of) the 1st sack. * Go through list, possibly coalescing sack block entries. */ firstsack.start = rcv_laststart; firstsack.end = rcv_lastend; for (i = 0; i < tp->rcv_numsacks; i++) { sack = tp->sackblks[i]; if (SEQ_LT(sack.end, firstsack.start) || SEQ_GT(sack.start, firstsack.end)) continue; /* no overlap */ if (sack.start == firstsack.start && sack.end == firstsack.end){ /* * identical block; delete it here since we will * move it to the front of the list. */ tp->sackblks[i].start = tp->sackblks[i].end = 0; lastpos = i; /* last posn with a zero entry */ continue; } if (SEQ_LEQ(sack.start, firstsack.start)) firstsack.start = sack.start; /* merge blocks */ if (SEQ_GEQ(sack.end, firstsack.end)) firstsack.end = sack.end; /* merge blocks */ tp->sackblks[i].start = tp->sackblks[i].end = 0; lastpos = i; /* last posn with a zero entry */ } if (lastpos != -1) { /* at least one merge */ for (i = 0, j = 1; i < tp->rcv_numsacks; i++) { sack = tp->sackblks[i]; if (sack.start == 0 && sack.end == 0) continue; temp[j++] = sack; } tp->rcv_numsacks = j; /* including first blk (added later) */ for (i = 1; i < tp->rcv_numsacks; i++) /* now copy back */ tp->sackblks[i] = temp[i]; } else { /* no merges -- shift sacks by 1 */ if (tp->rcv_numsacks < MAX_SACK_BLKS) tp->rcv_numsacks++; for (i = tp->rcv_numsacks-1; i > 0; i--) tp->sackblks[i] = tp->sackblks[i-1]; } tp->sackblks[0] = firstsack; return; } /* * Process the TCP SACK option. tp->snd_holes is an ordered list * of holes (oldest to newest, in terms of the sequence space). */ void tcp_sack_option(struct tcpcb *tp, struct tcphdr *th, u_char *cp, int optlen) { int tmp_olen; u_char *tmp_cp; struct sackhole *cur, *p, *temp; if (!tp->sack_enable) return; /* SACK without ACK doesn't make sense. */ if ((th->th_flags & TH_ACK) == 0) return; /* Make sure the ACK on this segment is in [snd_una, snd_max]. */ if (SEQ_LT(th->th_ack, tp->snd_una) || SEQ_GT(th->th_ack, tp->snd_max)) return; /* Note: TCPOLEN_SACK must be 2*sizeof(tcp_seq) */ if (optlen <= 2 || (optlen - 2) % TCPOLEN_SACK != 0) return; /* Note: TCPOLEN_SACK must be 2*sizeof(tcp_seq) */ tmp_cp = cp + 2; tmp_olen = optlen - 2; tcpstat_inc(tcps_sack_rcv_opts); if (tp->snd_numholes < 0) tp->snd_numholes = 0; if (tp->t_maxseg == 0) panic("tcp_sack_option"); /* Should never happen */ while (tmp_olen > 0) { struct sackblk sack; memcpy(&sack.start, tmp_cp, sizeof(tcp_seq)); sack.start = ntohl(sack.start); memcpy(&sack.end, tmp_cp + sizeof(tcp_seq), sizeof(tcp_seq)); sack.end = ntohl(sack.end); tmp_olen -= TCPOLEN_SACK; tmp_cp += TCPOLEN_SACK; if (SEQ_LEQ(sack.end, sack.start)) continue; /* bad SACK fields */ if (SEQ_LEQ(sack.end, tp->snd_una)) continue; /* old block */ if (SEQ_GT(th->th_ack, tp->snd_una)) { if (SEQ_LT(sack.start, th->th_ack)) continue; } if (SEQ_GT(sack.end, tp->snd_max)) continue; if (tp->snd_holes == NULL) { /* first hole */ tp->snd_holes = (struct sackhole *) pool_get(&sackhl_pool, PR_NOWAIT); if (tp->snd_holes == NULL) { /* ENOBUFS, so ignore SACKed block for now */ goto dropped; } cur = tp->snd_holes; cur->start = th->th_ack; cur->end = sack.start; cur->rxmit = cur->start; cur->next = NULL; tp->snd_numholes = 1; tp->rcv_lastsack = sack.end; /* * dups is at least one. If more data has been * SACKed, it can be greater than one. */ cur->dups = min(tcprexmtthresh, ((sack.end - cur->end)/tp->t_maxseg)); if (cur->dups < 1) cur->dups = 1; continue; /* with next sack block */ } /* Go thru list of holes: p = previous, cur = current */ p = cur = tp->snd_holes; while (cur) { if (SEQ_LEQ(sack.end, cur->start)) /* SACKs data before the current hole */ break; /* no use going through more holes */ if (SEQ_GEQ(sack.start, cur->end)) { /* SACKs data beyond the current hole */ cur->dups++; if (((sack.end - cur->end)/tp->t_maxseg) >= tcprexmtthresh) cur->dups = tcprexmtthresh; p = cur; cur = cur->next; continue; } if (SEQ_LEQ(sack.start, cur->start)) { /* Data acks at least the beginning of hole */ if (SEQ_GEQ(sack.end, cur->end)) { /* Acks entire hole, so delete hole */ if (p != cur) { p->next = cur->next; pool_put(&sackhl_pool, cur); cur = p->next; } else { cur = cur->next; pool_put(&sackhl_pool, p); p = cur; tp->snd_holes = p; } tp->snd_numholes--; continue; } /* otherwise, move start of hole forward */ cur->start = sack.end; cur->rxmit = SEQ_MAX(cur->rxmit, cur->start); p = cur; cur = cur->next; continue; } /* move end of hole backward */ if (SEQ_GEQ(sack.end, cur->end)) { cur->end = sack.start; cur->rxmit = SEQ_MIN(cur->rxmit, cur->end); cur->dups++; if (((sack.end - cur->end)/tp->t_maxseg) >= tcprexmtthresh) cur->dups = tcprexmtthresh; p = cur; cur = cur->next; continue; } if (SEQ_LT(cur->start, sack.start) && SEQ_GT(cur->end, sack.end)) { /* * ACKs some data in middle of a hole; need to * split current hole */ if (tp->snd_numholes >= TCP_SACKHOLE_LIMIT) goto dropped; temp = (struct sackhole *) pool_get(&sackhl_pool, PR_NOWAIT); if (temp == NULL) goto dropped; /* ENOBUFS */ temp->next = cur->next; temp->start = sack.end; temp->end = cur->end; temp->dups = cur->dups; temp->rxmit = SEQ_MAX(cur->rxmit, temp->start); cur->end = sack.start; cur->rxmit = SEQ_MIN(cur->rxmit, cur->end); cur->dups++; if (((sack.end - cur->end)/tp->t_maxseg) >= tcprexmtthresh) cur->dups = tcprexmtthresh; cur->next = temp; p = temp; cur = p->next; tp->snd_numholes++; } } /* At this point, p points to the last hole on the list */ if (SEQ_LT(tp->rcv_lastsack, sack.start)) { /* * Need to append new hole at end. * Last hole is p (and it's not NULL). */ if (tp->snd_numholes >= TCP_SACKHOLE_LIMIT) goto dropped; temp = (struct sackhole *) pool_get(&sackhl_pool, PR_NOWAIT); if (temp == NULL) goto dropped; /* ENOBUFS */ temp->start = tp->rcv_lastsack; temp->end = sack.start; temp->dups = min(tcprexmtthresh, ((sack.end - sack.start)/tp->t_maxseg)); if (temp->dups < 1) temp->dups = 1; temp->rxmit = temp->start; temp->next = 0; p->next = temp; tp->rcv_lastsack = sack.end; tp->snd_numholes++; } } return; dropped: tcpstat_inc(tcps_sack_drop_opts); } /* * Delete stale (i.e, cumulatively ack'd) holes. Hole is deleted only if * it is completely acked; otherwise, tcp_sack_option(), called from * tcp_dooptions(), will fix up the hole. */ void tcp_del_sackholes(struct tcpcb *tp, struct tcphdr *th) { if (tp->sack_enable && tp->t_state != TCPS_LISTEN) { /* max because this could be an older ack just arrived */ tcp_seq lastack = SEQ_GT(th->th_ack, tp->snd_una) ? th->th_ack : tp->snd_una; struct sackhole *cur = tp->snd_holes; struct sackhole *prev; while (cur) if (SEQ_LEQ(cur->end, lastack)) { prev = cur; cur = cur->next; pool_put(&sackhl_pool, prev); tp->snd_numholes--; } else if (SEQ_LT(cur->start, lastack)) { cur->start = lastack; if (SEQ_LT(cur->rxmit, cur->start)) cur->rxmit = cur->start; break; } else break; tp->snd_holes = cur; } } /* * Delete all receiver-side SACK information. */ void tcp_clean_sackreport(struct tcpcb *tp) { int i; tp->rcv_numsacks = 0; for (i = 0; i < MAX_SACK_BLKS; i++) tp->sackblks[i].start = tp->sackblks[i].end=0; } /* * Partial ack handling within a sack recovery episode. When a partial ack * arrives, turn off retransmission timer, deflate the window, do not clear * tp->t_dupacks. */ void tcp_sack_partialack(struct tcpcb *tp, struct tcphdr *th) { /* Turn off retx. timer (will start again next segment) */ TCP_TIMER_DISARM(tp, TCPT_REXMT); tp->t_rtttime = 0; /* * Partial window deflation. This statement relies on the * fact that tp->snd_una has not been updated yet. */ if (tp->snd_cwnd > (th->th_ack - tp->snd_una)) { tp->snd_cwnd -= th->th_ack - tp->snd_una; tp->snd_cwnd += tp->t_maxseg; } else tp->snd_cwnd = tp->t_maxseg; tp->snd_cwnd += tp->t_maxseg; tp->t_flags |= TF_NEEDOUTPUT; } /* * Pull out of band byte out of a segment so * it doesn't appear in the user's data queue. * It is still reflected in the segment length for * sequencing purposes. */ void tcp_pulloutofband(struct socket *so, u_int urgent, struct mbuf *m, int off) { int cnt = off + urgent - 1; while (cnt >= 0) { if (m->m_len > cnt) { char *cp = mtod(m, caddr_t) + cnt; struct tcpcb *tp = sototcpcb(so); tp->t_iobc = *cp; tp->t_oobflags |= TCPOOB_HAVEDATA; memmove(cp, cp + 1, m->m_len - cnt - 1); m->m_len--; return; } cnt -= m->m_len; m = m->m_next; if (m == NULL) break; } panic("tcp_pulloutofband"); } /* * Collect new round-trip time estimate * and update averages and current timeout. */ void tcp_xmit_timer(struct tcpcb *tp, int32_t rtt) { int delta, rttmin; if (rtt < 0) rtt = 0; else if (rtt > TCP_RTT_MAX) rtt = TCP_RTT_MAX; tcpstat_inc(tcps_rttupdated); if (tp->t_srtt != 0) { /* * delta is fixed point with 2 (TCP_RTT_BASE_SHIFT) bits * after the binary point (scaled by 4), whereas * srtt is stored as fixed point with 5 bits after the * binary point (i.e., scaled by 32). The following magic * is equivalent to the smoothing algorithm in rfc793 with * an alpha of .875 (srtt = rtt/8 + srtt*7/8 in fixed * point). */ delta = (rtt << TCP_RTT_BASE_SHIFT) - (tp->t_srtt >> TCP_RTT_SHIFT); if ((tp->t_srtt += delta) <= 0) tp->t_srtt = 1 << TCP_RTT_BASE_SHIFT; /* * We accumulate a smoothed rtt variance (actually, a * smoothed mean difference), then set the retransmit * timer to smoothed rtt + 4 times the smoothed variance. * rttvar is stored as fixed point with 4 bits after the * binary point (scaled by 16). The following is * equivalent to rfc793 smoothing with an alpha of .75 * (rttvar = rttvar*3/4 + |delta| / 4). This replaces * rfc793's wired-in beta. */ if (delta < 0) delta = -delta; delta -= (tp->t_rttvar >> TCP_RTTVAR_SHIFT); if ((tp->t_rttvar += delta) <= 0) tp->t_rttvar = 1 << TCP_RTT_BASE_SHIFT; } else { /* * No rtt measurement yet - use the unsmoothed rtt. * Set the variance to half the rtt (so our first * retransmit happens at 3*rtt). */ tp->t_srtt = (rtt + 1) << (TCP_RTT_SHIFT + TCP_RTT_BASE_SHIFT); tp->t_rttvar = (rtt + 1) << (TCP_RTTVAR_SHIFT + TCP_RTT_BASE_SHIFT - 1); } tp->t_rtttime = 0; tp->t_rxtshift = 0; /* * the retransmit should happen at rtt + 4 * rttvar. * Because of the way we do the smoothing, srtt and rttvar * will each average +1/2 tick of bias. When we compute * the retransmit timer, we want 1/2 tick of rounding and * 1 extra tick because of +-1/2 tick uncertainty in the * firing of the timer. The bias will give us exactly the * 1.5 tick we need. But, because the bias is * statistical, we have to test that we don't drop below * the minimum feasible timer (which is 2 ticks). */ rttmin = min(max(tp->t_rttmin, rtt + 2 * (TCP_TIME(1) / hz)), TCPTV_REXMTMAX); TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp), rttmin, TCPTV_REXMTMAX); /* * We received an ack for a packet that wasn't retransmitted; * it is probably safe to discard any error indications we've * received recently. This isn't quite right, but close enough * for now (a route might have failed after we sent a segment, * and the return path might not be symmetrical). */ tp->t_softerror = 0; } /* * Determine a reasonable value for maxseg size. * If the route is known, check route for mtu. * If none, use an mss that can be handled on the outgoing * interface without forcing IP to fragment; if bigger than * an mbuf cluster (MCLBYTES), round down to nearest multiple of MCLBYTES * to utilize large mbufs. If no route is found, route has no mtu, * or the destination isn't local, use a default, hopefully conservative * size (usually 512 or the default IP max size, but no more than the mtu * of the interface), as we can't discover anything about intervening * gateways or networks. We also initialize the congestion/slow start * window to be a single segment if the destination isn't local. * While looking at the routing entry, we also initialize other path-dependent * parameters from pre-set or cached values in the routing entry. * * Also take into account the space needed for options that we * send regularly. Make maxseg shorter by that amount to assure * that we can send maxseg amount of data even when the options * are present. Store the upper limit of the length of options plus * data in maxopd. * * NOTE: offer == -1 indicates that the maxseg size changed due to * Path MTU discovery. */ int tcp_mss(struct tcpcb *tp, int offer) { struct rtentry *rt; struct ifnet *ifp = NULL; int mss, mssopt; int iphlen; struct inpcb *inp; inp = tp->t_inpcb; mssopt = mss = tcp_mssdflt; rt = in_pcbrtentry(inp); if (rt == NULL) goto out; ifp = if_get(rt->rt_ifidx); if (ifp == NULL) goto out; switch (tp->pf) { #ifdef INET6 case AF_INET6: iphlen = sizeof(struct ip6_hdr); break; #endif case AF_INET: iphlen = sizeof(struct ip); break; default: /* the family does not support path MTU discovery */ goto out; } /* * if there's an mtu associated with the route and we support * path MTU discovery for the underlying protocol family, use it. */ if (rt->rt_mtu) { /* * One may wish to lower MSS to take into account options, * especially security-related options. */ if (tp->pf == AF_INET6 && rt->rt_mtu < IPV6_MMTU) { /* * RFC2460 section 5, last paragraph: if path MTU is * smaller than 1280, use 1280 as packet size and * attach fragment header. */ mss = IPV6_MMTU - iphlen - sizeof(struct ip6_frag) - sizeof(struct tcphdr); } else { mss = rt->rt_mtu - iphlen - sizeof(struct tcphdr); } } else if (ifp->if_flags & IFF_LOOPBACK) { mss = ifp->if_mtu - iphlen - sizeof(struct tcphdr); } else if (tp->pf == AF_INET) { if (ip_mtudisc) mss = ifp->if_mtu - iphlen - sizeof(struct tcphdr); } #ifdef INET6 else if (tp->pf == AF_INET6) { /* * for IPv6, path MTU discovery is always turned on, * or the node must use packet size <= 1280. */ mss = ifp->if_mtu - iphlen - sizeof(struct tcphdr); } #endif /* INET6 */ /* Calculate the value that we offer in TCPOPT_MAXSEG */ if (offer != -1) { mssopt = ifp->if_mtu - iphlen - sizeof(struct tcphdr); mssopt = max(tcp_mssdflt, mssopt); } out: if_put(ifp); /* * The current mss, t_maxseg, is initialized to the default value. * If we compute a smaller value, reduce the current mss. * If we compute a larger value, return it for use in sending * a max seg size option, but don't store it for use * unless we received an offer at least that large from peer. * * However, do not accept offers lower than the minimum of * the interface MTU and 216. */ if (offer > 0) tp->t_peermss = offer; if (tp->t_peermss) mss = min(mss, max(tp->t_peermss, 216)); /* sanity - at least max opt. space */ mss = max(mss, 64); /* * maxopd stores the maximum length of data AND options * in a segment; maxseg is the amount of data in a normal * segment. We need to store this value (maxopd) apart * from maxseg, because now every segment carries options * and thus we normally have somewhat less data in segments. */ tp->t_maxopd = mss; if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP && (tp->t_flags & TF_RCVD_TSTMP) == TF_RCVD_TSTMP) mss -= TCPOLEN_TSTAMP_APPA; #ifdef TCP_SIGNATURE if (tp->t_flags & TF_SIGNATURE) mss -= TCPOLEN_SIGLEN; #endif if (offer == -1) { /* mss changed due to Path MTU discovery */ tp->t_flags &= ~TF_PMTUD_PEND; tp->t_pmtud_mtu_sent = 0; tp->t_pmtud_mss_acked = 0; if (mss < tp->t_maxseg) { /* * Follow suggestion in RFC 2414 to reduce the * congestion window by the ratio of the old * segment size to the new segment size. */ tp->snd_cwnd = ulmax((tp->snd_cwnd / tp->t_maxseg) * mss, mss); } } else if (tcp_do_rfc3390 == 2) { /* increase initial window */ tp->snd_cwnd = ulmin(10 * mss, ulmax(2 * mss, 14600)); } else if (tcp_do_rfc3390) { /* increase initial window */ tp->snd_cwnd = ulmin(4 * mss, ulmax(2 * mss, 4380)); } else tp->snd_cwnd = mss; tp->t_maxseg = mss; return (offer != -1 ? mssopt : mss); } u_int tcp_hdrsz(struct tcpcb *tp) { u_int hlen; switch (tp->pf) { #ifdef INET6 case AF_INET6: hlen = sizeof(struct ip6_hdr); break; #endif case AF_INET: hlen = sizeof(struct ip); break; default: hlen = 0; break; } hlen += sizeof(struct tcphdr); if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP && (tp->t_flags & TF_RCVD_TSTMP) == TF_RCVD_TSTMP) hlen += TCPOLEN_TSTAMP_APPA; #ifdef TCP_SIGNATURE if (tp->t_flags & TF_SIGNATURE) hlen += TCPOLEN_SIGLEN; #endif return (hlen); } /* * Set connection variables based on the effective MSS. * We are passed the TCPCB for the actual connection. If we * are the server, we are called by the compressed state engine * when the 3-way handshake is complete. If we are the client, * we are called when we receive the SYN,ACK from the server. * * NOTE: The t_maxseg value must be initialized in the TCPCB * before this routine is called! */ void tcp_mss_update(struct tcpcb *tp) { int mss; u_long bufsize; struct rtentry *rt; struct socket *so; so = tp->t_inpcb->inp_socket; mss = tp->t_maxseg; rt = in_pcbrtentry(tp->t_inpcb); if (rt == NULL) return; bufsize = so->so_snd.sb_hiwat; if (bufsize < mss) { mss = bufsize; /* Update t_maxseg and t_maxopd */ tcp_mss(tp, mss); } else { bufsize = roundup(bufsize, mss); if (bufsize > sb_max) bufsize = sb_max; (void)sbreserve(so, &so->so_snd, bufsize); } bufsize = so->so_rcv.sb_hiwat; if (bufsize > mss) { bufsize = roundup(bufsize, mss); if (bufsize > sb_max) bufsize = sb_max; (void)sbreserve(so, &so->so_rcv, bufsize); } } /* * When a partial ack arrives, force the retransmission of the * next unacknowledged segment. Do not clear tp->t_dupacks. * By setting snd_nxt to ti_ack, this forces retransmission timer * to be started again. */ void tcp_newreno_partialack(struct tcpcb *tp, struct tcphdr *th) { /* * snd_una has not been updated and the socket send buffer * not yet drained of the acked data, so we have to leave * snd_una as it was to get the correct data offset in * tcp_output(). */ tcp_seq onxt = tp->snd_nxt; u_long ocwnd = tp->snd_cwnd; TCP_TIMER_DISARM(tp, TCPT_REXMT); tp->t_rtttime = 0; tp->snd_nxt = th->th_ack; /* * Set snd_cwnd to one segment beyond acknowledged offset * (tp->snd_una not yet updated when this function is called) */ tp->snd_cwnd = tp->t_maxseg + (th->th_ack - tp->snd_una); (void)tcp_output(tp); tp->snd_cwnd = ocwnd; if (SEQ_GT(onxt, tp->snd_nxt)) tp->snd_nxt = onxt; /* * Partial window deflation. Relies on fact that tp->snd_una * not updated yet. */ if (tp->snd_cwnd > th->th_ack - tp->snd_una) tp->snd_cwnd -= th->th_ack - tp->snd_una; else tp->snd_cwnd = 0; tp->snd_cwnd += tp->t_maxseg; } int tcp_mss_adv(struct mbuf *m, int af) { int mss = 0; int iphlen; struct ifnet *ifp = NULL; if (m && (m->m_flags & M_PKTHDR)) ifp = if_get(m->m_pkthdr.ph_ifidx); switch (af) { case AF_INET: if (ifp != NULL) mss = ifp->if_mtu; iphlen = sizeof(struct ip); break; #ifdef INET6 case AF_INET6: if (ifp != NULL) mss = ifp->if_mtu; iphlen = sizeof(struct ip6_hdr); break; #endif default: unhandled_af(af); } if_put(ifp); mss = mss - iphlen - sizeof(struct tcphdr); return (max(mss, tcp_mssdflt)); } /* * TCP compressed state engine. Currently used to hold compressed * state for SYN_RECEIVED. */ /* * Locks used to protect global data and struct members: * N net lock * S syn_cache_mtx tcp syn cache global mutex */ /* syn hash parameters */ int tcp_syn_hash_size = TCP_SYN_HASH_SIZE; /* [N] size of hash table */ int tcp_syn_cache_limit = /* [N] global entry limit */ TCP_SYN_HASH_SIZE * TCP_SYN_BUCKET_SIZE; int tcp_syn_bucket_limit = /* [N] per bucket limit */ 3 * TCP_SYN_BUCKET_SIZE; int tcp_syn_use_limit = 100000; /* [N] reseed after uses */ struct pool syn_cache_pool; struct syn_cache_set tcp_syn_cache[2]; int tcp_syn_cache_active; struct mutex syn_cache_mtx = MUTEX_INITIALIZER(IPL_SOFTNET); #define SYN_HASH(sa, sp, dp, rand) \ (((sa)->s_addr ^ (rand)[0]) * \ (((((u_int32_t)(dp))<<16) + ((u_int32_t)(sp))) ^ (rand)[4])) #ifndef INET6 #define SYN_HASHALL(hash, src, dst, rand) \ do { \ hash = SYN_HASH(&satosin_const(src)->sin_addr, \ satosin_const(src)->sin_port, \ satosin_const(dst)->sin_port, (rand)); \ } while (/*CONSTCOND*/ 0) #else #define SYN_HASH6(sa, sp, dp, rand) \ (((sa)->s6_addr32[0] ^ (rand)[0]) * \ ((sa)->s6_addr32[1] ^ (rand)[1]) * \ ((sa)->s6_addr32[2] ^ (rand)[2]) * \ ((sa)->s6_addr32[3] ^ (rand)[3]) * \ (((((u_int32_t)(dp))<<16) + ((u_int32_t)(sp))) ^ (rand)[4])) #define SYN_HASHALL(hash, src, dst, rand) \ do { \ switch ((src)->sa_family) { \ case AF_INET: \ hash = SYN_HASH(&satosin_const(src)->sin_addr, \ satosin_const(src)->sin_port, \ satosin_const(dst)->sin_port, (rand)); \ break; \ case AF_INET6: \ hash = SYN_HASH6(&satosin6_const(src)->sin6_addr, \ satosin6_const(src)->sin6_port, \ satosin6_const(dst)->sin6_port, (rand)); \ break; \ default: \ hash = 0; \ } \ } while (/*CONSTCOND*/0) #endif /* INET6 */ void syn_cache_rm(struct syn_cache *sc) { MUTEX_ASSERT_LOCKED(&syn_cache_mtx); KASSERT(!ISSET(sc->sc_dynflags, SCF_DEAD)); SET(sc->sc_dynflags, SCF_DEAD); TAILQ_REMOVE(&sc->sc_buckethead->sch_bucket, sc, sc_bucketq); sc->sc_tp = NULL; LIST_REMOVE(sc, sc_tpq); refcnt_rele(&sc->sc_refcnt); sc->sc_buckethead->sch_length--; if (timeout_del(&sc->sc_timer)) refcnt_rele(&sc->sc_refcnt); sc->sc_set->scs_count--; } void syn_cache_put(struct syn_cache *sc) { if (refcnt_rele(&sc->sc_refcnt) == 0) return; /* Dealing with last reference, no lock needed. */ m_free(sc->sc_ipopts); rtfree(sc->sc_route.ro_rt); pool_put(&syn_cache_pool, sc); } void syn_cache_init(void) { int i; /* Initialize the hash buckets. */ tcp_syn_cache[0].scs_buckethead = mallocarray(tcp_syn_hash_size, sizeof(struct syn_cache_head), M_SYNCACHE, M_WAITOK|M_ZERO); tcp_syn_cache[1].scs_buckethead = mallocarray(tcp_syn_hash_size, sizeof(struct syn_cache_head), M_SYNCACHE, M_WAITOK|M_ZERO); tcp_syn_cache[0].scs_size = tcp_syn_hash_size; tcp_syn_cache[1].scs_size = tcp_syn_hash_size; for (i = 0; i < tcp_syn_hash_size; i++) { TAILQ_INIT(&tcp_syn_cache[0].scs_buckethead[i].sch_bucket); TAILQ_INIT(&tcp_syn_cache[1].scs_buckethead[i].sch_bucket); } /* Initialize the syn cache pool. */ pool_init(&syn_cache_pool, sizeof(struct syn_cache), 0, IPL_SOFTNET, 0, "syncache", NULL); } void syn_cache_insert(struct syn_cache *sc, struct tcpcb *tp) { struct syn_cache_set *set = &tcp_syn_cache[tcp_syn_cache_active]; struct syn_cache_head *scp; struct syn_cache *sc2; int i; NET_ASSERT_LOCKED(); MUTEX_ASSERT_LOCKED(&syn_cache_mtx); /* * If there are no entries in the hash table, reinitialize * the hash secrets. To avoid useless cache swaps and * reinitialization, use it until the limit is reached. * An empty cache is also the opportunity to resize the hash. */ if (set->scs_count == 0 && set->scs_use <= 0) { set->scs_use = tcp_syn_use_limit; if (set->scs_size != tcp_syn_hash_size) { scp = mallocarray(tcp_syn_hash_size, sizeof(struct syn_cache_head), M_SYNCACHE, M_NOWAIT|M_ZERO); if (scp == NULL) { /* Try again next time. */ set->scs_use = 0; } else { free(set->scs_buckethead, M_SYNCACHE, set->scs_size * sizeof(struct syn_cache_head)); set->scs_buckethead = scp; set->scs_size = tcp_syn_hash_size; for (i = 0; i < tcp_syn_hash_size; i++) TAILQ_INIT(&scp[i].sch_bucket); } } arc4random_buf(set->scs_random, sizeof(set->scs_random)); tcpstat_inc(tcps_sc_seedrandom); } SYN_HASHALL(sc->sc_hash, &sc->sc_src.sa, &sc->sc_dst.sa, set->scs_random); scp = &set->scs_buckethead[sc->sc_hash % set->scs_size]; sc->sc_buckethead = scp; /* * Make sure that we don't overflow the per-bucket * limit or the total cache size limit. */ if (scp->sch_length >= tcp_syn_bucket_limit) { tcpstat_inc(tcps_sc_bucketoverflow); /* * Someone might attack our bucket hash function. Reseed * with random as soon as the passive syn cache gets empty. */ set->scs_use = 0; /* * The bucket is full. Toss the oldest element in the * bucket. This will be the first entry in the bucket. */ sc2 = TAILQ_FIRST(&scp->sch_bucket); #ifdef DIAGNOSTIC /* * This should never happen; we should always find an * entry in our bucket. */ if (sc2 == NULL) panic("%s: bucketoverflow: impossible", __func__); #endif syn_cache_rm(sc2); syn_cache_put(sc2); } else if (set->scs_count >= tcp_syn_cache_limit) { struct syn_cache_head *scp2, *sce; tcpstat_inc(tcps_sc_overflowed); /* * The cache is full. Toss the oldest entry in the * first non-empty bucket we can find. * * XXX We would really like to toss the oldest * entry in the cache, but we hope that this * condition doesn't happen very often. */ scp2 = scp; if (TAILQ_EMPTY(&scp2->sch_bucket)) { sce = &set->scs_buckethead[set->scs_size]; for (++scp2; scp2 != scp; scp2++) { if (scp2 >= sce) scp2 = &set->scs_buckethead[0]; if (! TAILQ_EMPTY(&scp2->sch_bucket)) break; } #ifdef DIAGNOSTIC /* * This should never happen; we should always find a * non-empty bucket. */ if (scp2 == scp) panic("%s: cacheoverflow: impossible", __func__); #endif } sc2 = TAILQ_FIRST(&scp2->sch_bucket); syn_cache_rm(sc2); syn_cache_put(sc2); } /* * Initialize the entry's timer. We don't estimate RTT * with SYNs, so each packet starts with the default RTT * and each timer step has a fixed timeout value. */ sc->sc_rxttot = 0; sc->sc_rxtshift = 0; TCPT_RANGESET(sc->sc_rxtcur, TCPTV_SRTTDFLT * tcp_backoff[sc->sc_rxtshift], TCPTV_MIN, TCPTV_REXMTMAX); if (timeout_add_msec(&sc->sc_timer, sc->sc_rxtcur)) refcnt_take(&sc->sc_refcnt); /* Link it from tcpcb entry */ refcnt_take(&sc->sc_refcnt); LIST_INSERT_HEAD(&tp->t_sc, sc, sc_tpq); /* Put it into the bucket. */ TAILQ_INSERT_TAIL(&scp->sch_bucket, sc, sc_bucketq); scp->sch_length++; sc->sc_set = set; set->scs_count++; set->scs_use--; tcpstat_inc(tcps_sc_added); /* * If the active cache has exceeded its use limit and * the passive syn cache is empty, exchange their roles. */ if (set->scs_use <= 0 && tcp_syn_cache[!tcp_syn_cache_active].scs_count == 0) tcp_syn_cache_active = !tcp_syn_cache_active; } /* * Walk the timer queues, looking for SYN,ACKs that need to be retransmitted. * If we have retransmitted an entry the maximum number of times, expire * that entry. */ void syn_cache_timer(void *arg) { struct syn_cache *sc = arg; uint64_t now; int lastref; mtx_enter(&syn_cache_mtx); if (ISSET(sc->sc_dynflags, SCF_DEAD)) goto freeit; if (__predict_false(sc->sc_rxtshift == TCP_MAXRXTSHIFT)) { /* Drop it -- too many retransmissions. */ goto dropit; } /* * Compute the total amount of time this entry has * been on a queue. If this entry has been on longer * than the keep alive timer would allow, expire it. */ sc->sc_rxttot += sc->sc_rxtcur; if (sc->sc_rxttot >= READ_ONCE(tcptv_keep_init)) goto dropit; /* Advance the timer back-off. */ sc->sc_rxtshift++; TCPT_RANGESET(sc->sc_rxtcur, TCPTV_SRTTDFLT * tcp_backoff[sc->sc_rxtshift], TCPTV_MIN, TCPTV_REXMTMAX); if (timeout_add_msec(&sc->sc_timer, sc->sc_rxtcur)) refcnt_take(&sc->sc_refcnt); mtx_leave(&syn_cache_mtx); NET_LOCK(); now = tcp_now(); (void) syn_cache_respond(sc, NULL, now); tcpstat_inc(tcps_sc_retransmitted); NET_UNLOCK(); syn_cache_put(sc); return; dropit: tcpstat_inc(tcps_sc_timed_out); syn_cache_rm(sc); /* Decrement reference of the timer and free object after remove. */ lastref = refcnt_rele(&sc->sc_refcnt); KASSERT(lastref == 0); (void)lastref; freeit: mtx_leave(&syn_cache_mtx); syn_cache_put(sc); } /* * Remove syn cache created by the specified tcb entry, * because this does not make sense to keep them * (if there's no tcb entry, syn cache entry will never be used) */ void syn_cache_cleanup(struct tcpcb *tp) { struct syn_cache *sc, *nsc; NET_ASSERT_LOCKED(); mtx_enter(&syn_cache_mtx); LIST_FOREACH_SAFE(sc, &tp->t_sc, sc_tpq, nsc) { #ifdef DIAGNOSTIC if (sc->sc_tp != tp) panic("invalid sc_tp in syn_cache_cleanup"); #endif syn_cache_rm(sc); syn_cache_put(sc); } mtx_leave(&syn_cache_mtx); KASSERT(LIST_EMPTY(&tp->t_sc)); } /* * Find an entry in the syn cache. */ struct syn_cache * syn_cache_lookup(const struct sockaddr *src, const struct sockaddr *dst, struct syn_cache_head **headp, u_int rtableid) { struct syn_cache_set *sets[2]; struct syn_cache *sc; struct syn_cache_head *scp; u_int32_t hash; int i; NET_ASSERT_LOCKED(); MUTEX_ASSERT_LOCKED(&syn_cache_mtx); /* Check the active cache first, the passive cache is likely empty. */ sets[0] = &tcp_syn_cache[tcp_syn_cache_active]; sets[1] = &tcp_syn_cache[!tcp_syn_cache_active]; for (i = 0; i < 2; i++) { if (sets[i]->scs_count == 0) continue; SYN_HASHALL(hash, src, dst, sets[i]->scs_random); scp = &sets[i]->scs_buckethead[hash % sets[i]->scs_size]; *headp = scp; TAILQ_FOREACH(sc, &scp->sch_bucket, sc_bucketq) { if (sc->sc_hash != hash) continue; if (!bcmp(&sc->sc_src, src, src->sa_len) && !bcmp(&sc->sc_dst, dst, dst->sa_len) && rtable_l2(rtableid) == rtable_l2(sc->sc_rtableid)) return (sc); } } return (NULL); } /* * This function gets called when we receive an ACK for a * socket in the LISTEN state. We look up the connection * in the syn cache, and if its there, we pull it out of * the cache and turn it into a full-blown connection in * the SYN-RECEIVED state. * * The return values may not be immediately obvious, and their effects * can be subtle, so here they are: * * NULL SYN was not found in cache; caller should drop the * packet and send an RST. * * -1 We were unable to create the new connection, and are * aborting it. An ACK,RST is being sent to the peer * (unless we got screwy sequence numbers; see below), * because the 3-way handshake has been completed. Caller * should not free the mbuf, since we may be using it. If * we are not, we will free it. * * Otherwise, the return value is a pointer to the new socket * associated with the connection. */ struct socket * syn_cache_get(struct sockaddr *src, struct sockaddr *dst, struct tcphdr *th, u_int hlen, u_int tlen, struct socket *so, struct mbuf *m, uint64_t now) { struct syn_cache *sc; struct syn_cache_head *scp; struct inpcb *inp, *oldinp; struct tcpcb *tp = NULL; struct mbuf *am; struct socket *oso; u_int rtableid; NET_ASSERT_LOCKED(); mtx_enter(&syn_cache_mtx); sc = syn_cache_lookup(src, dst, &scp, sotoinpcb(so)->inp_rtableid); if (sc == NULL) { mtx_leave(&syn_cache_mtx); return (NULL); } /* * Verify the sequence and ack numbers. Try getting the correct * response again. */ if ((th->th_ack != sc->sc_iss + 1) || SEQ_LEQ(th->th_seq, sc->sc_irs) || SEQ_GT(th->th_seq, sc->sc_irs + 1 + sc->sc_win)) { refcnt_take(&sc->sc_refcnt); mtx_leave(&syn_cache_mtx); (void) syn_cache_respond(sc, m, now); syn_cache_put(sc); return ((struct socket *)(-1)); } /* Remove this cache entry */ syn_cache_rm(sc); mtx_leave(&syn_cache_mtx); /* * Ok, create the full blown connection, and set things up * as they would have been set up if we had created the * connection when the SYN arrived. If we can't create * the connection, abort it. */ oso = so; so = sonewconn(so, SS_ISCONNECTED, M_DONTWAIT); if (so == NULL) goto resetandabort; oldinp = sotoinpcb(oso); inp = sotoinpcb(so); #ifdef IPSEC /* * We need to copy the required security levels * from the old pcb. Ditto for any other * IPsec-related information. */ inp->inp_seclevel = oldinp->inp_seclevel; #endif /* IPSEC */ #ifdef INET6 if (ISSET(inp->inp_flags, INP_IPV6)) { KASSERT(ISSET(oldinp->inp_flags, INP_IPV6)); inp->inp_ipv6.ip6_hlim = oldinp->inp_ipv6.ip6_hlim; inp->inp_hops = oldinp->inp_hops; } else #endif { KASSERT(!ISSET(oldinp->inp_flags, INP_IPV6)); inp->inp_ip.ip_ttl = oldinp->inp_ip.ip_ttl; inp->inp_options = ip_srcroute(m); if (inp->inp_options == NULL) { inp->inp_options = sc->sc_ipopts; sc->sc_ipopts = NULL; } } /* inherit rtable from listening socket */ rtableid = sc->sc_rtableid; #if NPF > 0 if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { struct pf_divert *divert; divert = pf_find_divert(m); KASSERT(divert != NULL); rtableid = divert->rdomain; } #endif in_pcbset_laddr(inp, dst, rtableid); /* * Give the new socket our cached route reference. */ inp->inp_route = sc->sc_route; /* struct assignment */ sc->sc_route.ro_rt = NULL; am = m_get(M_DONTWAIT, MT_SONAME); /* XXX */ if (am == NULL) goto resetandabort; am->m_len = src->sa_len; memcpy(mtod(am, caddr_t), src, src->sa_len); if (in_pcbconnect(inp, am)) { (void) m_free(am); goto resetandabort; } (void) m_free(am); tp = intotcpcb(inp); tp->t_flags = sototcpcb(oso)->t_flags & (TF_NOPUSH|TF_NODELAY); if (sc->sc_request_r_scale != 15) { tp->requested_s_scale = sc->sc_requested_s_scale; tp->request_r_scale = sc->sc_request_r_scale; tp->t_flags |= TF_REQ_SCALE|TF_RCVD_SCALE; } if (ISSET(sc->sc_fixflags, SCF_TIMESTAMP)) tp->t_flags |= TF_REQ_TSTMP|TF_RCVD_TSTMP; tp->t_template = tcp_template(tp); if (tp->t_template == 0) { tp = tcp_drop(tp, ENOBUFS); /* destroys socket */ so = NULL; goto abort; } tp->sack_enable = ISSET(sc->sc_fixflags, SCF_SACK_PERMIT); tp->ts_modulate = sc->sc_modulate; tp->ts_recent = sc->sc_timestamp; tp->iss = sc->sc_iss; tp->irs = sc->sc_irs; tcp_sendseqinit(tp); tp->snd_last = tp->snd_una; #ifdef TCP_ECN if (ISSET(sc->sc_fixflags, SCF_ECN_PERMIT)) { tp->t_flags |= TF_ECN_PERMIT; tcpstat_inc(tcps_ecn_accepts); } #endif if (ISSET(sc->sc_fixflags, SCF_SACK_PERMIT)) tp->t_flags |= TF_SACK_PERMIT; #ifdef TCP_SIGNATURE if (ISSET(sc->sc_fixflags, SCF_SIGNATURE)) tp->t_flags |= TF_SIGNATURE; #endif tcp_rcvseqinit(tp); tp->t_state = TCPS_SYN_RECEIVED; tp->t_rcvtime = now; tp->t_sndtime = now; tp->t_rcvacktime = now; tp->t_sndacktime = now; TCP_TIMER_ARM(tp, TCPT_KEEP, tcptv_keep_init); tcpstat_inc(tcps_accepts); tcp_mss(tp, sc->sc_peermaxseg); /* sets t_maxseg */ if (sc->sc_peermaxseg) tcp_mss_update(tp); /* Reset initial window to 1 segment for retransmit */ if (READ_ONCE(sc->sc_rxtshift) > 0) tp->snd_cwnd = tp->t_maxseg; tp->snd_wl1 = sc->sc_irs; tp->rcv_up = sc->sc_irs + 1; /* * This is what would have happened in tcp_output() when * the SYN,ACK was sent. */ tp->snd_up = tp->snd_una; tp->snd_max = tp->snd_nxt = tp->iss+1; TCP_TIMER_ARM(tp, TCPT_REXMT, tp->t_rxtcur); if (sc->sc_win > 0 && SEQ_GT(tp->rcv_nxt + sc->sc_win, tp->rcv_adv)) tp->rcv_adv = tp->rcv_nxt + sc->sc_win; tp->last_ack_sent = tp->rcv_nxt; tcpstat_inc(tcps_sc_completed); syn_cache_put(sc); return (so); resetandabort: tcp_respond(NULL, mtod(m, caddr_t), th, (tcp_seq)0, th->th_ack, TH_RST, m->m_pkthdr.ph_rtableid, now); abort: m_freem(m); if (so != NULL) soabort(so); syn_cache_put(sc); tcpstat_inc(tcps_sc_aborted); return ((struct socket *)(-1)); } /* * This function is called when we get a RST for a * non-existent connection, so that we can see if the * connection is in the syn cache. If it is, zap it. */ void syn_cache_reset(struct sockaddr *src, struct sockaddr *dst, struct tcphdr *th, u_int rtableid) { struct syn_cache *sc; struct syn_cache_head *scp; NET_ASSERT_LOCKED(); mtx_enter(&syn_cache_mtx); sc = syn_cache_lookup(src, dst, &scp, rtableid); if (sc == NULL) { mtx_leave(&syn_cache_mtx); return; } if (SEQ_LT(th->th_seq, sc->sc_irs) || SEQ_GT(th->th_seq, sc->sc_irs + 1)) { mtx_leave(&syn_cache_mtx); return; } syn_cache_rm(sc); mtx_leave(&syn_cache_mtx); tcpstat_inc(tcps_sc_reset); syn_cache_put(sc); } void syn_cache_unreach(const struct sockaddr *src, const struct sockaddr *dst, struct tcphdr *th, u_int rtableid) { struct syn_cache *sc; struct syn_cache_head *scp; NET_ASSERT_LOCKED(); mtx_enter(&syn_cache_mtx); sc = syn_cache_lookup(src, dst, &scp, rtableid); if (sc == NULL) { mtx_leave(&syn_cache_mtx); return; } /* If the sequence number != sc_iss, then it's a bogus ICMP msg */ if (ntohl (th->th_seq) != sc->sc_iss) { mtx_leave(&syn_cache_mtx); return; } /* * If we've retransmitted 3 times and this is our second error, * we remove the entry. Otherwise, we allow it to continue on. * This prevents us from incorrectly nuking an entry during a * spurious network outage. * * See tcp_notify(). */ if (!ISSET(sc->sc_dynflags, SCF_UNREACH) || sc->sc_rxtshift < 3) { SET(sc->sc_dynflags, SCF_UNREACH); mtx_leave(&syn_cache_mtx); return; } syn_cache_rm(sc); mtx_leave(&syn_cache_mtx); tcpstat_inc(tcps_sc_unreach); syn_cache_put(sc); } /* * Given a LISTEN socket and an inbound SYN request, add * this to the syn cache, and send back a segment: * <SEQ=ISS><ACK=RCV_NXT><CTL=SYN,ACK> * to the source. * * IMPORTANT NOTE: We do _NOT_ ACK data that might accompany the SYN. * Doing so would require that we hold onto the data and deliver it * to the application. However, if we are the target of a SYN-flood * DoS attack, an attacker could send data which would eventually * consume all available buffer space if it were ACKed. By not ACKing * the data, we avoid this DoS scenario. */ int syn_cache_add(struct sockaddr *src, struct sockaddr *dst, struct tcphdr *th, u_int iphlen, struct socket *so, struct mbuf *m, u_char *optp, int optlen, struct tcp_opt_info *oi, tcp_seq *issp, uint64_t now) { struct tcpcb tb, *tp; long win; struct syn_cache *sc; struct syn_cache_head *scp; struct mbuf *ipopts; NET_ASSERT_LOCKED(); tp = sototcpcb(so); /* * RFC1122 4.2.3.10, p. 104: discard bcast/mcast SYN * * Note this check is performed in tcp_input() very early on. */ /* * Initialize some local state. */ win = sbspace(so, &so->so_rcv); if (win > TCP_MAXWIN) win = TCP_MAXWIN; bzero(&tb, sizeof(tb)); #ifdef TCP_SIGNATURE if (optp || (tp->t_flags & TF_SIGNATURE)) { #else if (optp) { #endif tb.pf = tp->pf; tb.sack_enable = tp->sack_enable; tb.t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0; #ifdef TCP_SIGNATURE if (tp->t_flags & TF_SIGNATURE) tb.t_flags |= TF_SIGNATURE; #endif tb.t_state = TCPS_LISTEN; if (tcp_dooptions(&tb, optp, optlen, th, m, iphlen, oi, sotoinpcb(so)->inp_rtableid, now)) return (-1); } switch (src->sa_family) { case AF_INET: /* * Remember the IP options, if any. */ ipopts = ip_srcroute(m); break; default: ipopts = NULL; } /* * See if we already have an entry for this connection. * If we do, resend the SYN,ACK. We do not count this * as a retransmission (XXX though maybe we should). */ mtx_enter(&syn_cache_mtx); sc = syn_cache_lookup(src, dst, &scp, sotoinpcb(so)->inp_rtableid); if (sc != NULL) { refcnt_take(&sc->sc_refcnt); mtx_leave(&syn_cache_mtx); tcpstat_inc(tcps_sc_dupesyn); if (ipopts) { /* * If we were remembering a previous source route, * forget it and use the new one we've been given. */ m_free(sc->sc_ipopts); sc->sc_ipopts = ipopts; } sc->sc_timestamp = tb.ts_recent; if (syn_cache_respond(sc, m, now) == 0) { tcpstat_inc(tcps_sndacks); tcpstat_inc(tcps_sndtotal); } syn_cache_put(sc); return (0); } mtx_leave(&syn_cache_mtx); sc = pool_get(&syn_cache_pool, PR_NOWAIT|PR_ZERO); if (sc == NULL) { m_free(ipopts); return (-1); } refcnt_init_trace(&sc->sc_refcnt, DT_REFCNT_IDX_SYNCACHE); timeout_set_flags(&sc->sc_timer, syn_cache_timer, sc, KCLOCK_NONE, TIMEOUT_PROC | TIMEOUT_MPSAFE); /* * Fill in the cache, and put the necessary IP and TCP * options into the reply. */ memcpy(&sc->sc_src, src, src->sa_len); memcpy(&sc->sc_dst, dst, dst->sa_len); sc->sc_rtableid = sotoinpcb(so)->inp_rtableid; sc->sc_ipopts = ipopts; sc->sc_irs = th->th_seq; sc->sc_iss = issp ? *issp : arc4random(); sc->sc_peermaxseg = oi->maxseg; sc->sc_ourmaxseg = tcp_mss_adv(m, sc->sc_src.sa.sa_family); sc->sc_win = win; sc->sc_timestamp = tb.ts_recent; if ((tb.t_flags & (TF_REQ_TSTMP|TF_RCVD_TSTMP)) == (TF_REQ_TSTMP|TF_RCVD_TSTMP)) { SET(sc->sc_fixflags, SCF_TIMESTAMP); sc->sc_modulate = arc4random(); } if ((tb.t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == (TF_RCVD_SCALE|TF_REQ_SCALE)) { sc->sc_requested_s_scale = tb.requested_s_scale; sc->sc_request_r_scale = 0; /* * Pick the smallest possible scaling factor that * will still allow us to scale up to sb_max. * * We do this because there are broken firewalls that * will corrupt the window scale option, leading to * the other endpoint believing that our advertised * window is unscaled. At scale factors larger than * 5 the unscaled window will drop below 1500 bytes, * leading to serious problems when traversing these * broken firewalls. * * With the default sbmax of 256K, a scale factor * of 3 will be chosen by this algorithm. Those who * choose a larger sbmax should watch out * for the compatibility problems mentioned above. * * RFC1323: The Window field in a SYN (i.e., a <SYN> * or <SYN,ACK>) segment itself is never scaled. */ while (sc->sc_request_r_scale < TCP_MAX_WINSHIFT && (TCP_MAXWIN << sc->sc_request_r_scale) < sb_max) sc->sc_request_r_scale++; } else { sc->sc_requested_s_scale = 15; sc->sc_request_r_scale = 15; } #ifdef TCP_ECN /* * if both ECE and CWR flag bits are set, peer is ECN capable. */ if (tcp_do_ecn && (th->th_flags & (TH_ECE|TH_CWR)) == (TH_ECE|TH_CWR)) SET(sc->sc_fixflags, SCF_ECN_PERMIT); #endif /* * Set SCF_SACK_PERMIT if peer did send a SACK_PERMITTED option * (i.e., if tcp_dooptions() did set TF_SACK_PERMIT). */ if (tb.sack_enable && (tb.t_flags & TF_SACK_PERMIT)) SET(sc->sc_fixflags, SCF_SACK_PERMIT); #ifdef TCP_SIGNATURE if (tb.t_flags & TF_SIGNATURE) SET(sc->sc_fixflags, SCF_SIGNATURE); #endif sc->sc_tp = tp; if (syn_cache_respond(sc, m, now) == 0) { mtx_enter(&syn_cache_mtx); /* * XXXSMP Currently exclusive netlock prevents another insert * after our syn_cache_lookup() and before syn_cache_insert(). * Double insert should be handled and not rely on netlock. */ syn_cache_insert(sc, tp); mtx_leave(&syn_cache_mtx); tcpstat_inc(tcps_sndacks); tcpstat_inc(tcps_sndtotal); } else { syn_cache_put(sc); tcpstat_inc(tcps_sc_dropped); } return (0); } int syn_cache_respond(struct syn_cache *sc, struct mbuf *m, uint64_t now) { u_int8_t *optp; int optlen, error; u_int16_t tlen; struct ip *ip = NULL; #ifdef INET6 struct ip6_hdr *ip6 = NULL; #endif struct tcphdr *th; u_int hlen; struct inpcb *inp; NET_ASSERT_LOCKED(); switch (sc->sc_src.sa.sa_family) { case AF_INET: hlen = sizeof(struct ip); break; #ifdef INET6 case AF_INET6: hlen = sizeof(struct ip6_hdr); break; #endif default: m_freem(m); return (EAFNOSUPPORT); } /* Compute the size of the TCP options. */ optlen = 4 + (sc->sc_request_r_scale != 15 ? 4 : 0) + (ISSET(sc->sc_fixflags, SCF_SACK_PERMIT) ? 4 : 0) + #ifdef TCP_SIGNATURE (ISSET(sc->sc_fixflags, SCF_SIGNATURE) ? TCPOLEN_SIGLEN : 0) + #endif (ISSET(sc->sc_fixflags, SCF_TIMESTAMP) ? TCPOLEN_TSTAMP_APPA : 0); tlen = hlen + sizeof(struct tcphdr) + optlen; /* * Create the IP+TCP header from scratch. */ m_freem(m); #ifdef DIAGNOSTIC if (max_linkhdr + tlen > MCLBYTES) return (ENOBUFS); #endif MGETHDR(m, M_DONTWAIT, MT_DATA); if (m && max_linkhdr + tlen > MHLEN) { MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { m_freem(m); m = NULL; } } if (m == NULL) return (ENOBUFS); /* Fixup the mbuf. */ m->m_data += max_linkhdr; m->m_len = m->m_pkthdr.len = tlen; m->m_pkthdr.ph_ifidx = 0; m->m_pkthdr.ph_rtableid = sc->sc_rtableid; memset(mtod(m, u_char *), 0, tlen); switch (sc->sc_src.sa.sa_family) { case AF_INET: ip = mtod(m, struct ip *); ip->ip_dst = sc->sc_src.sin.sin_addr; ip->ip_src = sc->sc_dst.sin.sin_addr; ip->ip_p = IPPROTO_TCP; th = (struct tcphdr *)(ip + 1); th->th_dport = sc->sc_src.sin.sin_port; th->th_sport = sc->sc_dst.sin.sin_port; break; #ifdef INET6 case AF_INET6: ip6 = mtod(m, struct ip6_hdr *); ip6->ip6_dst = sc->sc_src.sin6.sin6_addr; ip6->ip6_src = sc->sc_dst.sin6.sin6_addr; ip6->ip6_nxt = IPPROTO_TCP; th = (struct tcphdr *)(ip6 + 1); th->th_dport = sc->sc_src.sin6.sin6_port; th->th_sport = sc->sc_dst.sin6.sin6_port; break; #endif } th->th_seq = htonl(sc->sc_iss); th->th_ack = htonl(sc->sc_irs + 1); th->th_off = (sizeof(struct tcphdr) + optlen) >> 2; th->th_flags = TH_SYN|TH_ACK; #ifdef TCP_ECN /* Set ECE for SYN-ACK if peer supports ECN. */ if (tcp_do_ecn && ISSET(sc->sc_fixflags, SCF_ECN_PERMIT)) th->th_flags |= TH_ECE; #endif th->th_win = htons(sc->sc_win); /* th_sum already 0 */ /* th_urp already 0 */ /* Tack on the TCP options. */ optp = (u_int8_t *)(th + 1); *optp++ = TCPOPT_MAXSEG; *optp++ = 4; *optp++ = (sc->sc_ourmaxseg >> 8) & 0xff; *optp++ = sc->sc_ourmaxseg & 0xff; /* Include SACK_PERMIT_HDR option if peer has already done so. */ if (ISSET(sc->sc_fixflags, SCF_SACK_PERMIT)) { *((u_int32_t *)optp) = htonl(TCPOPT_SACK_PERMIT_HDR); optp += 4; } if (sc->sc_request_r_scale != 15) { *((u_int32_t *)optp) = htonl(TCPOPT_NOP << 24 | TCPOPT_WINDOW << 16 | TCPOLEN_WINDOW << 8 | sc->sc_request_r_scale); optp += 4; } if (ISSET(sc->sc_fixflags, SCF_TIMESTAMP)) { u_int32_t *lp = (u_int32_t *)(optp); /* Form timestamp option as shown in appendix A of RFC 1323. */ *lp++ = htonl(TCPOPT_TSTAMP_HDR); *lp++ = htonl(now + sc->sc_modulate); *lp = htonl(sc->sc_timestamp); optp += TCPOLEN_TSTAMP_APPA; } #ifdef TCP_SIGNATURE if (ISSET(sc->sc_fixflags, SCF_SIGNATURE)) { union sockaddr_union src, dst; struct tdb *tdb; bzero(&src, sizeof(union sockaddr_union)); bzero(&dst, sizeof(union sockaddr_union)); src.sa.sa_len = sc->sc_src.sa.sa_len; src.sa.sa_family = sc->sc_src.sa.sa_family; dst.sa.sa_len = sc->sc_dst.sa.sa_len; dst.sa.sa_family = sc->sc_dst.sa.sa_family; switch (sc->sc_src.sa.sa_family) { case 0: /*default to PF_INET*/ case AF_INET: src.sin.sin_addr = mtod(m, struct ip *)->ip_src; dst.sin.sin_addr = mtod(m, struct ip *)->ip_dst; break; #ifdef INET6 case AF_INET6: src.sin6.sin6_addr = mtod(m, struct ip6_hdr *)->ip6_src; dst.sin6.sin6_addr = mtod(m, struct ip6_hdr *)->ip6_dst; break; #endif /* INET6 */ } tdb = gettdbbysrcdst(rtable_l2(sc->sc_rtableid), 0, &src, &dst, IPPROTO_TCP); if (tdb == NULL) { m_freem(m); return (EPERM); } /* Send signature option */ *(optp++) = TCPOPT_SIGNATURE; *(optp++) = TCPOLEN_SIGNATURE; if (tcp_signature(tdb, sc->sc_src.sa.sa_family, m, th, hlen, 0, optp) < 0) { m_freem(m); tdb_unref(tdb); return (EINVAL); } tdb_unref(tdb); optp += 16; /* Pad options list to the next 32 bit boundary and * terminate it. */ *optp++ = TCPOPT_NOP; *optp++ = TCPOPT_EOL; } #endif /* TCP_SIGNATURE */ SET(m->m_pkthdr.csum_flags, M_TCP_CSUM_OUT); /* use IPsec policy and ttl from listening socket, on SYN ACK */ mtx_enter(&syn_cache_mtx); inp = sc->sc_tp ? sc->sc_tp->t_inpcb : NULL; mtx_leave(&syn_cache_mtx); /* * Fill in some straggling IP bits. Note the stack expects * ip_len to be in host order, for convenience. */ switch (sc->sc_src.sa.sa_family) { case AF_INET: ip->ip_len = htons(tlen); ip->ip_ttl = inp ? inp->inp_ip.ip_ttl : ip_defttl; if (inp != NULL) ip->ip_tos = inp->inp_ip.ip_tos; error = ip_output(m, sc->sc_ipopts, &sc->sc_route, (ip_mtudisc ? IP_MTUDISC : 0), NULL, inp ? &inp->inp_seclevel : NULL, 0); break; #ifdef INET6 case AF_INET6: ip6->ip6_vfc &= ~IPV6_VERSION_MASK; ip6->ip6_vfc |= IPV6_VERSION; /* ip6_plen will be updated in ip6_output() */ ip6->ip6_hlim = in6_selecthlim(inp); /* leave flowlabel = 0, it is legal and require no state mgmt */ error = ip6_output(m, NULL /*XXX*/, &sc->sc_route, 0, NULL, inp ? &inp->inp_seclevel : NULL); break; #endif } return (error); }
16 1 15 12 13 5 5 4 4 1 3 13 4 6 3 21 1 2 2 16 20 17 1 2 5 8 4 16 2 11 4 2 12 5 7 7 5 2 7 4 35 12 24 20 14 14 22 9 4 11 12 23 6 4 5 10 1 8 46 1 2 40 26 14 13 4 36 4 4 8 13 2 7 2 2 4 4 3 51 51 45 45 12 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 /* $OpenBSD: kern_time.c,v 1.167 2023/10/17 00:04:02 cheloha Exp $ */ /* $NetBSD: kern_time.c,v 1.20 1996/02/18 11:57:06 fvdl Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_time.c 8.4 (Berkeley) 5/26/95 */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/systm.h> #include <sys/clockintr.h> #include <sys/mutex.h> #include <sys/rwlock.h> #include <sys/proc.h> #include <sys/ktrace.h> #include <sys/signalvar.h> #include <sys/stdint.h> #include <sys/pledge.h> #include <sys/task.h> #include <sys/time.h> #include <sys/timeout.h> #include <sys/timetc.h> #include <sys/mount.h> #include <sys/syscallargs.h> #include <dev/clock_subr.h> int itimerfix(struct itimerval *); void process_reset_itimer_flag(struct process *); /* * Time of day and interval timer support. * * These routines provide the kernel entry points to get and set * the time-of-day and per-process interval timers. Subroutines * here provide support for adding and subtracting timeval structures * and decrementing interval timers, optionally reloading the interval * timers when they expire. */ /* This function is used by clock_settime and settimeofday */ int settime(const struct timespec *ts) { struct timespec now; /* * Don't allow the time to be set forward so far it will wrap * and become negative, thus allowing an attacker to bypass * the next check below. The cutoff is 1 year before rollover * occurs, so even if the attacker uses adjtime(2) to move * the time past the cutoff, it will take a very long time * to get to the wrap point. * * XXX: we check against UINT_MAX until we can figure out * how to deal with the hardware RTCs. */ if (ts->tv_sec > UINT_MAX - 365*24*60*60) { printf("denied attempt to set clock forward to %lld\n", (long long)ts->tv_sec); return (EPERM); } /* * If the system is secure, we do not allow the time to be * set to an earlier value (it may be slowed using adjtime, * but not set back). This feature prevent interlopers from * setting arbitrary time stamps on files. */ nanotime(&now); if (securelevel > 1 && timespeccmp(ts, &now, <=)) { printf("denied attempt to set clock back %lld seconds\n", (long long)now.tv_sec - ts->tv_sec); return (EPERM); } tc_setrealtimeclock(ts); KERNEL_LOCK(); resettodr(); KERNEL_UNLOCK(); return (0); } int clock_gettime(struct proc *p, clockid_t clock_id, struct timespec *tp) { struct proc *q; int error = 0; switch (clock_id) { case CLOCK_REALTIME: nanotime(tp); break; case CLOCK_UPTIME: nanoruntime(tp); break; case CLOCK_MONOTONIC: case CLOCK_BOOTTIME: nanouptime(tp); break; case CLOCK_PROCESS_CPUTIME_ID: nanouptime(tp); timespecsub(tp, &curcpu()->ci_schedstate.spc_runtime, tp); timespecadd(tp, &p->p_p->ps_tu.tu_runtime, tp); break; case CLOCK_THREAD_CPUTIME_ID: nanouptime(tp); timespecsub(tp, &curcpu()->ci_schedstate.spc_runtime, tp); timespecadd(tp, &p->p_tu.tu_runtime, tp); break; default: /* check for clock from pthread_getcpuclockid() */ if (__CLOCK_TYPE(clock_id) == CLOCK_THREAD_CPUTIME_ID) { KERNEL_LOCK(); q = tfind_user(__CLOCK_PTID(clock_id), p->p_p); if (q == NULL) error = ESRCH; else *tp = q->p_tu.tu_runtime; KERNEL_UNLOCK(); } else error = EINVAL; break; } return (error); } int sys_clock_gettime(struct proc *p, void *v, register_t *retval) { struct sys_clock_gettime_args /* { syscallarg(clockid_t) clock_id; syscallarg(struct timespec *) tp; } */ *uap = v; struct timespec ats; int error; memset(&ats, 0, sizeof(ats)); if ((error = clock_gettime(p, SCARG(uap, clock_id), &ats)) != 0) return (error); error = copyout(&ats, SCARG(uap, tp), sizeof(ats)); #ifdef KTRACE if (error == 0 && KTRPOINT(p, KTR_STRUCT)) ktrabstimespec(p, &ats); #endif return (error); } int sys_clock_settime(struct proc *p, void *v, register_t *retval) { struct sys_clock_settime_args /* { syscallarg(clockid_t) clock_id; syscallarg(const struct timespec *) tp; } */ *uap = v; struct timespec ats; clockid_t clock_id; int error; if ((error = suser(p)) != 0) return (error); if ((error = copyin(SCARG(uap, tp), &ats, sizeof(ats))) != 0) return (error); clock_id = SCARG(uap, clock_id); switch (clock_id) { case CLOCK_REALTIME: if (!timespecisvalid(&ats)) return (EINVAL); if ((error = settime(&ats)) != 0) return (error); break; default: /* Other clocks are read-only */ return (EINVAL); } return (0); } int sys_clock_getres(struct proc *p, void *v, register_t *retval) { struct sys_clock_getres_args /* { syscallarg(clockid_t) clock_id; syscallarg(struct timespec *) tp; } */ *uap = v; clockid_t clock_id; struct bintime bt; struct timespec ts; struct proc *q; u_int64_t scale; int error = 0; memset(&ts, 0, sizeof(ts)); clock_id = SCARG(uap, clock_id); switch (clock_id) { case CLOCK_REALTIME: case CLOCK_MONOTONIC: case CLOCK_BOOTTIME: case CLOCK_UPTIME: memset(&bt, 0, sizeof(bt)); rw_enter_read(&tc_lock); scale = ((1ULL << 63) / tc_getfrequency()) * 2; bt.frac = tc_getprecision() * scale; rw_exit_read(&tc_lock); BINTIME_TO_TIMESPEC(&bt, &ts); break; case CLOCK_PROCESS_CPUTIME_ID: case CLOCK_THREAD_CPUTIME_ID: ts.tv_nsec = 1000000000 / stathz; break; default: /* check for clock from pthread_getcpuclockid() */ if (__CLOCK_TYPE(clock_id) == CLOCK_THREAD_CPUTIME_ID) { KERNEL_LOCK(); q = tfind_user(__CLOCK_PTID(clock_id), p->p_p); if (q == NULL) error = ESRCH; else ts.tv_nsec = 1000000000 / stathz; KERNEL_UNLOCK(); } else error = EINVAL; break; } if (error == 0 && SCARG(uap, tp)) { ts.tv_nsec = MAX(ts.tv_nsec, 1); error = copyout(&ts, SCARG(uap, tp), sizeof(ts)); #ifdef KTRACE if (error == 0 && KTRPOINT(p, KTR_STRUCT)) ktrreltimespec(p, &ts); #endif } return error; } int sys_nanosleep(struct proc *p, void *v, register_t *retval) { struct sys_nanosleep_args/* { syscallarg(const struct timespec *) rqtp; syscallarg(struct timespec *) rmtp; } */ *uap = v; struct timespec elapsed, remainder, request, start, stop; uint64_t nsecs; struct timespec *rmtp; int copyout_error, error; rmtp = SCARG(uap, rmtp); error = copyin(SCARG(uap, rqtp), &request, sizeof(request)); if (error) return (error); #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrreltimespec(p, &request); #endif if (request.tv_sec < 0 || !timespecisvalid(&request)) return (EINVAL); do { getnanouptime(&start); nsecs = MAX(1, MIN(TIMESPEC_TO_NSEC(&request), MAXTSLP)); error = tsleep_nsec(&nowake, PWAIT | PCATCH, "nanoslp", nsecs); getnanouptime(&stop); timespecsub(&stop, &start, &elapsed); timespecsub(&request, &elapsed, &request); if (request.tv_sec < 0) timespecclear(&request); if (error != EWOULDBLOCK) break; } while (timespecisset(&request)); if (error == ERESTART) error = EINTR; if (error == EWOULDBLOCK) error = 0; if (rmtp) { memset(&remainder, 0, sizeof(remainder)); remainder = request; copyout_error = copyout(&remainder, rmtp, sizeof(remainder)); if (copyout_error) error = copyout_error; #ifdef KTRACE if (copyout_error == 0 && KTRPOINT(p, KTR_STRUCT)) ktrreltimespec(p, &remainder); #endif } return error; } int sys_gettimeofday(struct proc *p, void *v, register_t *retval) { struct sys_gettimeofday_args /* { syscallarg(struct timeval *) tp; syscallarg(struct timezone *) tzp; } */ *uap = v; struct timeval atv; static const struct timezone zerotz = { 0, 0 }; struct timeval *tp; struct timezone *tzp; int error = 0; tp = SCARG(uap, tp); tzp = SCARG(uap, tzp); if (tp) { memset(&atv, 0, sizeof(atv)); microtime(&atv); if ((error = copyout(&atv, tp, sizeof (atv)))) return (error); #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrabstimeval(p, &atv); #endif } if (tzp) error = copyout(&zerotz, tzp, sizeof(zerotz)); return (error); } int sys_settimeofday(struct proc *p, void *v, register_t *retval) { struct sys_settimeofday_args /* { syscallarg(const struct timeval *) tv; syscallarg(const struct timezone *) tzp; } */ *uap = v; struct timezone atz; struct timeval atv; const struct timeval *tv; const struct timezone *tzp; int error; tv = SCARG(uap, tv); tzp = SCARG(uap, tzp); if ((error = suser(p))) return (error); /* Verify all parameters before changing time. */ if (tv && (error = copyin(tv, &atv, sizeof(atv)))) return (error); if (tzp && (error = copyin(tzp, &atz, sizeof(atz)))) return (error); if (tv) { struct timespec ts; #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrabstimeval(p, &atv); #endif if (!timerisvalid(&atv)) return (EINVAL); TIMEVAL_TO_TIMESPEC(&atv, &ts); if ((error = settime(&ts)) != 0) return (error); } return (0); } #define ADJFREQ_MAX (500000000LL << 32) #define ADJFREQ_MIN (-ADJFREQ_MAX) int sys_adjfreq(struct proc *p, void *v, register_t *retval) { struct sys_adjfreq_args /* { syscallarg(const int64_t *) freq; syscallarg(int64_t *) oldfreq; } */ *uap = v; int error = 0; int64_t f, oldf; const int64_t *freq = SCARG(uap, freq); int64_t *oldfreq = SCARG(uap, oldfreq); if (freq) { if ((error = suser(p))) return (error); if ((error = copyin(freq, &f, sizeof(f)))) return (error); if (f < ADJFREQ_MIN || f > ADJFREQ_MAX) return (EINVAL); } rw_enter(&tc_lock, (freq == NULL) ? RW_READ : RW_WRITE); if (oldfreq) { tc_adjfreq(&oldf, NULL); if ((error = copyout(&oldf, oldfreq, sizeof(oldf)))) goto out; } if (freq) tc_adjfreq(NULL, &f); out: rw_exit(&tc_lock); return (error); } int sys_adjtime(struct proc *p, void *v, register_t *retval) { struct sys_adjtime_args /* { syscallarg(const struct timeval *) delta; syscallarg(struct timeval *) olddelta; } */ *uap = v; struct timeval atv; const struct timeval *delta = SCARG(uap, delta); struct timeval *olddelta = SCARG(uap, olddelta); int64_t adjustment, remaining; int error; error = pledge_adjtime(p, delta); if (error) return error; if (delta) { if ((error = suser(p))) return (error); if ((error = copyin(delta, &atv, sizeof(struct timeval)))) return (error); #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrreltimeval(p, &atv); #endif if (!timerisvalid(&atv)) return (EINVAL); if (atv.tv_sec > INT64_MAX / 1000000) return EINVAL; if (atv.tv_sec < INT64_MIN / 1000000) return EINVAL; adjustment = atv.tv_sec * 1000000; if (adjustment > INT64_MAX - atv.tv_usec) return EINVAL; adjustment += atv.tv_usec; rw_enter_write(&tc_lock); } if (olddelta) { tc_adjtime(&remaining, NULL); memset(&atv, 0, sizeof(atv)); atv.tv_sec = remaining / 1000000; atv.tv_usec = remaining % 1000000; if (atv.tv_usec < 0) { atv.tv_usec += 1000000; atv.tv_sec--; } if ((error = copyout(&atv, olddelta, sizeof(struct timeval)))) goto out; } if (delta) tc_adjtime(NULL, &adjustment); out: if (delta) rw_exit_write(&tc_lock); return (error); } struct mutex itimer_mtx = MUTEX_INITIALIZER(IPL_CLOCK); /* * Get or set value of an interval timer. The process virtual and * profiling virtual time timers are kept internally in the * way they are specified externally: in time until they expire. * * The real time interval timer's it_value, in contrast, is kept as an * absolute time rather than as a delta, so that it is easy to keep * periodic real-time signals from drifting. * * Virtual time timers are processed in the hardclock() routine of * kern_clock.c. The real time timer is processed by a timeout * routine, called from the softclock() routine. Since a callout * may be delayed in real time due to interrupt processing in the system, * it is possible for the real time timeout routine (realitexpire, given below), * to be delayed in real time past when it is supposed to occur. It * does not suffice, therefore, to reload the real timer .it_value from the * real time timers .it_interval. Rather, we compute the next time in * absolute time the timer should go off. */ void setitimer(int which, const struct itimerval *itv, struct itimerval *olditv) { struct itimerspec its, oldits; struct timespec now; struct itimerspec *itimer; struct process *pr; KASSERT(which >= ITIMER_REAL && which <= ITIMER_PROF); pr = curproc->p_p; itimer = &pr->ps_timer[which]; if (itv != NULL) { TIMEVAL_TO_TIMESPEC(&itv->it_value, &its.it_value); TIMEVAL_TO_TIMESPEC(&itv->it_interval, &its.it_interval); } if (which == ITIMER_REAL) { mtx_enter(&pr->ps_mtx); nanouptime(&now); } else mtx_enter(&itimer_mtx); if (olditv != NULL) oldits = *itimer; if (itv != NULL) { if (which == ITIMER_REAL) { if (timespecisset(&its.it_value)) { timespecadd(&its.it_value, &now, &its.it_value); timeout_abs_ts(&pr->ps_realit_to,&its.it_value); } else timeout_del(&pr->ps_realit_to); } *itimer = its; if (which == ITIMER_VIRTUAL || which == ITIMER_PROF) { process_reset_itimer_flag(pr); need_resched(curcpu()); } } if (which == ITIMER_REAL) mtx_leave(&pr->ps_mtx); else mtx_leave(&itimer_mtx); if (olditv != NULL) { if (which == ITIMER_REAL && timespecisset(&oldits.it_value)) { if (timespeccmp(&oldits.it_value, &now, <)) timespecclear(&oldits.it_value); else { timespecsub(&oldits.it_value, &now, &oldits.it_value); } } TIMESPEC_TO_TIMEVAL(&olditv->it_value, &oldits.it_value); TIMESPEC_TO_TIMEVAL(&olditv->it_interval, &oldits.it_interval); } } void cancel_all_itimers(void) { struct itimerval itv; int i; timerclear(&itv.it_value); timerclear(&itv.it_interval); for (i = 0; i < nitems(curproc->p_p->ps_timer); i++) setitimer(i, &itv, NULL); } int sys_getitimer(struct proc *p, void *v, register_t *retval) { struct sys_getitimer_args /* { syscallarg(int) which; syscallarg(struct itimerval *) itv; } */ *uap = v; struct itimerval aitv; int which; which = SCARG(uap, which); if (which < ITIMER_REAL || which > ITIMER_PROF) return EINVAL; memset(&aitv, 0, sizeof(aitv)); setitimer(which, NULL, &aitv); return copyout(&aitv, SCARG(uap, itv), sizeof(aitv)); } int sys_setitimer(struct proc *p, void *v, register_t *retval) { struct sys_setitimer_args /* { syscallarg(int) which; syscallarg(const struct itimerval *) itv; syscallarg(struct itimerval *) oitv; } */ *uap = v; struct itimerval aitv, olditv; struct itimerval *newitvp, *olditvp; int error, which; which = SCARG(uap, which); if (which < ITIMER_REAL || which > ITIMER_PROF) return EINVAL; newitvp = olditvp = NULL; if (SCARG(uap, itv) != NULL) { error = copyin(SCARG(uap, itv), &aitv, sizeof(aitv)); if (error) return error; error = itimerfix(&aitv); if (error) return error; newitvp = &aitv; } if (SCARG(uap, oitv) != NULL) { memset(&olditv, 0, sizeof(olditv)); olditvp = &olditv; } if (newitvp == NULL && olditvp == NULL) return 0; setitimer(which, newitvp, olditvp); if (SCARG(uap, oitv) != NULL) return copyout(&olditv, SCARG(uap, oitv), sizeof(olditv)); return 0; } /* * Real interval timer expired: * send process whose timer expired an alarm signal. * If time is not set up to reload, then just return. * Else compute next time timer should go off which is > current time. * This is where delay in processing this timeout causes multiple * SIGALRM calls to be compressed into one. */ void realitexpire(void *arg) { struct timespec cts; struct process *pr = arg; struct itimerspec *tp = &pr->ps_timer[ITIMER_REAL]; int need_signal = 0; mtx_enter(&pr->ps_mtx); /* * Do nothing if the timer was cancelled or rescheduled while we * were entering the mutex. */ if (!timespecisset(&tp->it_value) || timeout_pending(&pr->ps_realit_to)) goto out; /* The timer expired. We need to send the signal. */ need_signal = 1; /* One-shot timers are not reloaded. */ if (!timespecisset(&tp->it_interval)) { timespecclear(&tp->it_value); goto out; } /* * Find the nearest future expiration point and restart * the timeout. */ nanouptime(&cts); while (timespeccmp(&tp->it_value, &cts, <=)) timespecadd(&tp->it_value, &tp->it_interval, &tp->it_value); if ((pr->ps_flags & PS_EXITING) == 0) timeout_abs_ts(&pr->ps_realit_to, &tp->it_value); out: mtx_leave(&pr->ps_mtx); if (need_signal) prsignal(pr, SIGALRM); } /* * Check if the given setitimer(2) input is valid. Clear it_interval * if it_value is unset. Round it_interval up to the minimum interval * if necessary. */ int itimerfix(struct itimerval *itv) { static const struct timeval max = { .tv_sec = UINT_MAX, .tv_usec = 0 }; struct timeval min_interval = { .tv_sec = 0, .tv_usec = tick }; if (itv->it_value.tv_sec < 0 || !timerisvalid(&itv->it_value)) return EINVAL; if (timercmp(&itv->it_value, &max, >)) return EINVAL; if (itv->it_interval.tv_sec < 0 || !timerisvalid(&itv->it_interval)) return EINVAL; if (timercmp(&itv->it_interval, &max, >)) return EINVAL; if (!timerisset(&itv->it_value)) timerclear(&itv->it_interval); if (timerisset(&itv->it_interval)) { if (timercmp(&itv->it_interval, &min_interval, <)) itv->it_interval = min_interval; } return 0; } /* * Decrement an interval timer by the given duration. * If the timer expires and it is periodic then reload it. When reloading * the timer we subtract any overrun from the next period so that the timer * does not drift. */ int itimerdecr(struct itimerspec *itp, const struct timespec *decrement) { timespecsub(&itp->it_value, decrement, &itp->it_value); if (itp->it_value.tv_sec >= 0 && timespecisset(&itp->it_value)) return (1); if (!timespecisset(&itp->it_interval)) { timespecclear(&itp->it_value); return (0); } while (itp->it_value.tv_sec < 0 || !timespecisset(&itp->it_value)) timespecadd(&itp->it_value, &itp->it_interval, &itp->it_value); return (0); } void itimer_update(struct clockrequest *cr, void *cf, void *arg) { struct timespec elapsed; uint64_t nsecs; struct clockframe *frame = cf; struct proc *p = curproc; struct process *pr; if (p == NULL || ISSET(p->p_flag, P_SYSTEM | P_WEXIT)) return; pr = p->p_p; if (!ISSET(pr->ps_flags, PS_ITIMER)) return; nsecs = clockrequest_advance(cr, hardclock_period) * hardclock_period; NSEC_TO_TIMESPEC(nsecs, &elapsed); mtx_enter(&itimer_mtx); if (CLKF_USERMODE(frame) && timespecisset(&pr->ps_timer[ITIMER_VIRTUAL].it_value) && itimerdecr(&pr->ps_timer[ITIMER_VIRTUAL], &elapsed) == 0) { process_reset_itimer_flag(pr); atomic_setbits_int(&p->p_flag, P_ALRMPEND); need_proftick(p); } if (timespecisset(&pr->ps_timer[ITIMER_PROF].it_value) && itimerdecr(&pr->ps_timer[ITIMER_PROF], &elapsed) == 0) { process_reset_itimer_flag(pr); atomic_setbits_int(&p->p_flag, P_PROFPEND); need_proftick(p); } mtx_leave(&itimer_mtx); } void process_reset_itimer_flag(struct process *ps) { if (timespecisset(&ps->ps_timer[ITIMER_VIRTUAL].it_value) || timespecisset(&ps->ps_timer[ITIMER_PROF].it_value)) atomic_setbits_int(&ps->ps_flags, PS_ITIMER); else atomic_clearbits_int(&ps->ps_flags, PS_ITIMER); } struct mutex ratecheck_mtx = MUTEX_INITIALIZER(IPL_HIGH); /* * ratecheck(): simple time-based rate-limit checking. see ratecheck(9) * for usage and rationale. */ int ratecheck(struct timeval *lasttime, const struct timeval *mininterval) { struct timeval tv, delta; int rv = 0; getmicrouptime(&tv); mtx_enter(&ratecheck_mtx); timersub(&tv, lasttime, &delta); /* * check for 0,0 is so that the message will be seen at least once, * even if interval is huge. */ if (timercmp(&delta, mininterval, >=) || (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) { *lasttime = tv; rv = 1; } mtx_leave(&ratecheck_mtx); return (rv); } struct mutex ppsratecheck_mtx = MUTEX_INITIALIZER(IPL_HIGH); /* * ppsratecheck(): packets (or events) per second limitation. */ int ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps) { struct timeval tv, delta; int rv; microuptime(&tv); mtx_enter(&ppsratecheck_mtx); timersub(&tv, lasttime, &delta); /* * check for 0,0 is so that the message will be seen at least once. * if more than one second have passed since the last update of * lasttime, reset the counter. * * we do increment *curpps even in *curpps < maxpps case, as some may * try to use *curpps for stat purposes as well. */ if (maxpps == 0) rv = 0; else if ((lasttime->tv_sec == 0 && lasttime->tv_usec == 0) || delta.tv_sec >= 1) { *lasttime = tv; *curpps = 0; rv = 1; } else if (maxpps < 0) rv = 1; else if (*curpps < maxpps) rv = 1; else rv = 0; /* be careful about wrap-around */ if (*curpps + 1 > *curpps) *curpps = *curpps + 1; mtx_leave(&ppsratecheck_mtx); return (rv); } todr_chip_handle_t todr_handle; int inittodr_done; #define MINYEAR ((OpenBSD / 100) - 1) /* minimum plausible year */ /* * inittodr: * * Initialize time from the time-of-day register. */ void inittodr(time_t base) { time_t deltat; struct timeval rtctime; struct timespec ts; int badbase; inittodr_done = 1; if (base < (MINYEAR - 1970) * SECYR) { printf("WARNING: preposterous time in file system\n"); /* read the system clock anyway */ base = (MINYEAR - 1970) * SECYR; badbase = 1; } else badbase = 0; rtctime.tv_sec = base; rtctime.tv_usec = 0; if (todr_handle == NULL || todr_gettime(todr_handle, &rtctime) != 0 || rtctime.tv_sec < (MINYEAR - 1970) * SECYR) { /* * Believe the time in the file system for lack of * anything better, resetting the TODR. */ rtctime.tv_sec = base; rtctime.tv_usec = 0; if (todr_handle != NULL && !badbase) printf("WARNING: bad clock chip time\n"); ts.tv_sec = rtctime.tv_sec; ts.tv_nsec = rtctime.tv_usec * 1000; tc_setclock(&ts); goto bad; } else { ts.tv_sec = rtctime.tv_sec; ts.tv_nsec = rtctime.tv_usec * 1000; tc_setclock(&ts); } if (!badbase) { /* * See if we gained/lost two or more days; if * so, assume something is amiss. */ deltat = rtctime.tv_sec - base; if (deltat < 0) deltat = -deltat; if (deltat < 2 * SECDAY) return; /* all is well */ #ifndef SMALL_KERNEL printf("WARNING: clock %s %lld days\n", rtctime.tv_sec < base ? "lost" : "gained", (long long)(deltat / SECDAY)); #endif } bad: printf("WARNING: CHECK AND RESET THE DATE!\n"); } /* * resettodr: * * Reset the time-of-day register with the current time. */ void resettodr(void) { struct timeval rtctime; /* * Skip writing the RTC if inittodr(9) never ran. We don't * want to overwrite a reasonable value with a nonsense value. */ if (!inittodr_done) return; microtime(&rtctime); if (todr_handle != NULL && todr_settime(todr_handle, &rtctime) != 0) printf("WARNING: can't update clock chip time\n"); } void todr_attach(struct todr_chip_handle *todr) { if (todr_handle == NULL || todr->todr_quality > todr_handle->todr_quality) todr_handle = todr; } #define RESETTODR_PERIOD 1800 void periodic_resettodr(void *); void perform_resettodr(void *); struct timeout resettodr_to = TIMEOUT_INITIALIZER(periodic_resettodr, NULL); struct task resettodr_task = TASK_INITIALIZER(perform_resettodr, NULL); void periodic_resettodr(void *arg __unused) { task_add(systq, &resettodr_task); } void perform_resettodr(void *arg __unused) { resettodr(); timeout_add_sec(&resettodr_to, RESETTODR_PERIOD); } void start_periodic_resettodr(void) { timeout_add_sec(&resettodr_to, RESETTODR_PERIOD); } void stop_periodic_resettodr(void) { timeout_del(&resettodr_to); task_del(systq, &resettodr_task); }
9 9 9 15 2 13 10 10 8 6 10 6 8 45 24 241 22 22 17 234 8 8 7 8 650 9 648 94 95 5 5 154 160 1 155 43 43 43 89 5 56 15 45 26 55 41 40 438 4 144 360 60 55 19 20 10 5 60 55 18 18 8 12 39 1 28 35 28 5 26 36 74 74 29 73 42 47 74 3 3 92 16 15 16 14 33 33 33 7 63 82 52 132 109 108 109 83 10 2 39 47 4 7 6 5 6 6 7 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 /* $OpenBSD: rtable.c,v 1.87 2024/04/09 12:53:08 claudio Exp $ */ /* * Copyright (c) 2014-2016 Martin Pieuchot * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _KERNEL #include "kern_compat.h" #else #include <sys/param.h> #include <sys/systm.h> #include <sys/socket.h> #include <sys/malloc.h> #include <sys/queue.h> #include <sys/domain.h> #include <sys/srp.h> #endif #include <net/rtable.h> #include <net/route.h> #include <net/art.h> /* * Structures used by rtable_get() to retrieve the corresponding * routing table for a given pair of ``af'' and ``rtableid''. * * Note that once allocated routing table heads are never freed. * This way we do not need to reference count them. * * afmap rtmap/dommp * ----------- --------- ----- * | 0 |--------> | 0 | 0 | ... | 0 | Array mapping rtableid (=index) * ----------- --------- ----- to rdomain/loopback (=value). * | AF_INET |. * ----------- `. .---------. .---------. * ... `----> | rtable0 | ... | rtableN | Array of pointers for * ----------- '---------' '---------' IPv4 routing tables * | AF_MPLS | indexed by ``rtableid''. * ----------- */ struct srp *afmap; uint8_t af2idx[AF_MAX+1]; /* To only allocate supported AF */ uint8_t af2idx_max; /* Array of routing table pointers. */ struct rtmap { unsigned int limit; void **tbl; }; /* * Array of rtableid -> rdomain mapping. * * Only used for the first index as described above. */ struct dommp { unsigned int limit; /* * Array to get the routing domain and loopback interface related to * a routing table. Format: * * 8 unused bits | 16 bits for loopback index | 8 bits for rdomain */ unsigned int *value; }; unsigned int rtmap_limit = 0; void rtmap_init(void); void rtmap_grow(unsigned int, sa_family_t); void rtmap_dtor(void *, void *); struct srp_gc rtmap_gc = SRP_GC_INITIALIZER(rtmap_dtor, NULL); void rtable_init_backend(void); void *rtable_alloc(unsigned int, unsigned int, unsigned int); void *rtable_get(unsigned int, sa_family_t); void rtmap_init(void) { const struct domain *dp; int i; /* Start with a single table for every domain that requires it. */ for (i = 0; (dp = domains[i]) != NULL; i++) { if (dp->dom_rtoffset == 0) continue; rtmap_grow(1, dp->dom_family); } /* Initialize the rtableid->rdomain mapping table. */ rtmap_grow(1, 0); rtmap_limit = 1; } /* * Grow the size of the array of routing table for AF ``af'' to ``nlimit''. */ void rtmap_grow(unsigned int nlimit, sa_family_t af) { struct rtmap *map, *nmap; int i; KERNEL_ASSERT_LOCKED(); KASSERT(nlimit > rtmap_limit); nmap = malloc(sizeof(*nmap), M_RTABLE, M_WAITOK); nmap->limit = nlimit; nmap->tbl = mallocarray(nlimit, sizeof(*nmap[0].tbl), M_RTABLE, M_WAITOK|M_ZERO); map = srp_get_locked(&afmap[af2idx[af]]); if (map != NULL) { KASSERT(map->limit == rtmap_limit); for (i = 0; i < map->limit; i++) nmap->tbl[i] = map->tbl[i]; } srp_update_locked(&rtmap_gc, &afmap[af2idx[af]], nmap); } void rtmap_dtor(void *null, void *xmap) { struct rtmap *map = xmap; /* * doesn't need to be serialized since this is the last reference * to this map. there's nothing to race against. */ free(map->tbl, M_RTABLE, map->limit * sizeof(*map[0].tbl)); free(map, M_RTABLE, sizeof(*map)); } void rtable_init(void) { const struct domain *dp; int i; KASSERT(sizeof(struct rtmap) == sizeof(struct dommp)); /* We use index 0 for the rtable/rdomain map. */ af2idx_max = 1; memset(af2idx, 0, sizeof(af2idx)); /* * Compute the maximum supported key length in case the routing * table backend needs it. */ for (i = 0; (dp = domains[i]) != NULL; i++) { if (dp->dom_rtoffset == 0) continue; af2idx[dp->dom_family] = af2idx_max++; } rtable_init_backend(); /* * Allocate AF-to-id table now that we now how many AFs this * kernel supports. */ afmap = mallocarray(af2idx_max + 1, sizeof(*afmap), M_RTABLE, M_WAITOK|M_ZERO); rtmap_init(); if (rtable_add(0) != 0) panic("unable to create default routing table"); rt_timer_init(); } int rtable_add(unsigned int id) { const struct domain *dp; void *tbl; struct rtmap *map; struct dommp *dmm; sa_family_t af; unsigned int off, alen; int i, error = 0; if (id > RT_TABLEID_MAX) return (EINVAL); KERNEL_LOCK(); if (rtable_exists(id)) goto out; for (i = 0; (dp = domains[i]) != NULL; i++) { if (dp->dom_rtoffset == 0) continue; af = dp->dom_family; off = dp->dom_rtoffset; alen = dp->dom_maxplen; if (id >= rtmap_limit) rtmap_grow(id + 1, af); tbl = rtable_alloc(id, alen, off); if (tbl == NULL) { error = ENOMEM; goto out; } map = srp_get_locked(&afmap[af2idx[af]]); map->tbl[id] = tbl; } /* Reflect possible growth. */ if (id >= rtmap_limit) { rtmap_grow(id + 1, 0); rtmap_limit = id + 1; } /* Use main rtable/rdomain by default. */ dmm = srp_get_locked(&afmap[0]); dmm->value[id] = 0; out: KERNEL_UNLOCK(); return (error); } void * rtable_get(unsigned int rtableid, sa_family_t af) { struct rtmap *map; void *tbl = NULL; struct srp_ref sr; if (af >= nitems(af2idx) || af2idx[af] == 0) return (NULL); map = srp_enter(&sr, &afmap[af2idx[af]]); if (rtableid < map->limit) tbl = map->tbl[rtableid]; srp_leave(&sr); return (tbl); } int rtable_exists(unsigned int rtableid) { const struct domain *dp; void *tbl; int i; for (i = 0; (dp = domains[i]) != NULL; i++) { if (dp->dom_rtoffset == 0) continue; tbl = rtable_get(rtableid, dp->dom_family); if (tbl != NULL) return (1); } return (0); } int rtable_empty(unsigned int rtableid) { const struct domain *dp; int i; struct art_root *tbl; for (i = 0; (dp = domains[i]) != NULL; i++) { if (dp->dom_rtoffset == 0) continue; tbl = rtable_get(rtableid, dp->dom_family); if (tbl == NULL) continue; if (tbl->ar_root.ref != NULL) return (0); } return (1); } unsigned int rtable_l2(unsigned int rtableid) { struct dommp *dmm; unsigned int rdomain = 0; struct srp_ref sr; dmm = srp_enter(&sr, &afmap[0]); if (rtableid < dmm->limit) rdomain = (dmm->value[rtableid] & RT_TABLEID_MASK); srp_leave(&sr); return (rdomain); } unsigned int rtable_loindex(unsigned int rtableid) { struct dommp *dmm; unsigned int loifidx = 0; struct srp_ref sr; dmm = srp_enter(&sr, &afmap[0]); if (rtableid < dmm->limit) loifidx = (dmm->value[rtableid] >> RT_TABLEID_BITS); srp_leave(&sr); return (loifidx); } void rtable_l2set(unsigned int rtableid, unsigned int rdomain, unsigned int loifidx) { struct dommp *dmm; unsigned int value; KERNEL_ASSERT_LOCKED(); if (!rtable_exists(rtableid) || !rtable_exists(rdomain)) return; value = (rdomain & RT_TABLEID_MASK) | (loifidx << RT_TABLEID_BITS); dmm = srp_get_locked(&afmap[0]); dmm->value[rtableid] = value; } static inline const uint8_t *satoaddr(struct art_root *, const struct sockaddr *); int an_match(struct art_node *, const struct sockaddr *, int); void rtentry_ref(void *, void *); void rtentry_unref(void *, void *); void rtable_mpath_insert(struct art_node *, struct rtentry *); struct srpl_rc rt_rc = SRPL_RC_INITIALIZER(rtentry_ref, rtentry_unref, NULL); void rtable_init_backend(void) { art_init(); } void * rtable_alloc(unsigned int rtableid, unsigned int alen, unsigned int off) { return (art_alloc(rtableid, alen, off)); } int rtable_setsource(unsigned int rtableid, int af, struct sockaddr *src) { struct art_root *ar; NET_ASSERT_LOCKED_EXCLUSIVE(); if ((ar = rtable_get(rtableid, af)) == NULL) return (EAFNOSUPPORT); ar->ar_source = src; return (0); } struct sockaddr * rtable_getsource(unsigned int rtableid, int af) { struct art_root *ar; NET_ASSERT_LOCKED(); ar = rtable_get(rtableid, af); if (ar == NULL) return (NULL); return (ar->ar_source); } void rtable_clearsource(unsigned int rtableid, struct sockaddr *src) { struct sockaddr *addr; addr = rtable_getsource(rtableid, src->sa_family); if (addr && (addr->sa_len == src->sa_len)) { if (memcmp(src, addr, addr->sa_len) == 0) { rtable_setsource(rtableid, src->sa_family, NULL); } } } struct rtentry * rtable_lookup(unsigned int rtableid, const struct sockaddr *dst, const struct sockaddr *mask, const struct sockaddr *gateway, uint8_t prio) { struct art_root *ar; struct art_node *an; struct rtentry *rt = NULL; struct srp_ref sr, nsr; const uint8_t *addr; int plen; ar = rtable_get(rtableid, dst->sa_family); if (ar == NULL) return (NULL); addr = satoaddr(ar, dst); /* No need for a perfect match. */ if (mask == NULL) { an = art_match(ar, addr, &nsr); if (an == NULL) goto out; } else { plen = rtable_satoplen(dst->sa_family, mask); if (plen == -1) return (NULL); an = art_lookup(ar, addr, plen, &nsr); /* Make sure we've got a perfect match. */ if (!an_match(an, dst, plen)) goto out; } SRPL_FOREACH(rt, &sr, &an->an_rtlist, rt_next) { if (prio != RTP_ANY && (rt->rt_priority & RTP_MASK) != (prio & RTP_MASK)) continue; if (gateway == NULL) break; if (rt->rt_gateway->sa_len == gateway->sa_len && memcmp(rt->rt_gateway, gateway, gateway->sa_len) == 0) break; } if (rt != NULL) rtref(rt); SRPL_LEAVE(&sr); out: srp_leave(&nsr); return (rt); } struct rtentry * rtable_match(unsigned int rtableid, const struct sockaddr *dst, uint32_t *src) { struct art_root *ar; struct art_node *an; struct rtentry *rt = NULL; struct srp_ref sr, nsr; const uint8_t *addr; int hash; ar = rtable_get(rtableid, dst->sa_family); if (ar == NULL) return (NULL); addr = satoaddr(ar, dst); an = art_match(ar, addr, &nsr); if (an == NULL) goto out; rt = SRPL_FIRST(&sr, &an->an_rtlist); if (rt == NULL) { SRPL_LEAVE(&sr); goto out; } rtref(rt); SRPL_LEAVE(&sr); /* Gateway selection by Hash-Threshold (RFC 2992) */ if ((hash = rt_hash(rt, dst, src)) != -1) { struct rtentry *mrt; int threshold, npaths = 0; KASSERT(hash <= 0xffff); SRPL_FOREACH(mrt, &sr, &an->an_rtlist, rt_next) { /* Only count nexthops with the same priority. */ if (mrt->rt_priority == rt->rt_priority) npaths++; } SRPL_LEAVE(&sr); threshold = (0xffff / npaths) + 1; /* * we have no protection against concurrent modification of the * route list attached to the node, so we won't necessarily * have the same number of routes. for most modifications, * we'll pick a route that we wouldn't have if we only saw the * list before or after the change. if we were going to use * the last available route, but it got removed, we'll hit * the end of the list and then pick the first route. */ mrt = SRPL_FIRST(&sr, &an->an_rtlist); while (hash > threshold && mrt != NULL) { if (mrt->rt_priority == rt->rt_priority) hash -= threshold; mrt = SRPL_FOLLOW(&sr, mrt, rt_next); } if (mrt != NULL) { rtref(mrt); rtfree(rt); rt = mrt; } SRPL_LEAVE(&sr); } out: srp_leave(&nsr); return (rt); } int rtable_insert(unsigned int rtableid, struct sockaddr *dst, const struct sockaddr *mask, const struct sockaddr *gateway, uint8_t prio, struct rtentry *rt) { struct rtentry *mrt; struct srp_ref sr; struct art_root *ar; struct art_node *an, *prev; const uint8_t *addr; int plen; unsigned int rt_flags; int error = 0; ar = rtable_get(rtableid, dst->sa_family); if (ar == NULL) return (EAFNOSUPPORT); addr = satoaddr(ar, dst); plen = rtable_satoplen(dst->sa_family, mask); if (plen == -1) return (EINVAL); rtref(rt); /* guarantee rtfree won't do anything during insert */ rw_enter_write(&ar->ar_lock); /* Do not permit exactly the same dst/mask/gw pair. */ an = art_lookup(ar, addr, plen, &sr); srp_leave(&sr); /* an can't go away while we have the lock */ if (an_match(an, dst, plen)) { struct rtentry *mrt; int mpathok = ISSET(rt->rt_flags, RTF_MPATH); SRPL_FOREACH_LOCKED(mrt, &an->an_rtlist, rt_next) { if (prio != RTP_ANY && (mrt->rt_priority & RTP_MASK) != (prio & RTP_MASK)) continue; if (!mpathok || (mrt->rt_gateway->sa_len == gateway->sa_len && memcmp(mrt->rt_gateway, gateway, gateway->sa_len) == 0)) { error = EEXIST; goto leave; } } } an = art_get(plen); if (an == NULL) { error = ENOBUFS; goto leave; } /* prepare for immediate operation if insert succeeds */ rt_flags = rt->rt_flags; rt->rt_flags &= ~RTF_MPATH; rt->rt_dest = dst; rt->rt_plen = plen; SRPL_INSERT_HEAD_LOCKED(&rt_rc, &an->an_rtlist, rt, rt_next); prev = art_insert(ar, an, addr, plen); if (prev != an) { SRPL_REMOVE_LOCKED(&rt_rc, &an->an_rtlist, rt, rtentry, rt_next); rt->rt_flags = rt_flags; art_put(an); if (prev == NULL) { error = ESRCH; goto leave; } an = prev; mrt = SRPL_FIRST_LOCKED(&an->an_rtlist); KASSERT(mrt != NULL); KASSERT((rt->rt_flags & RTF_MPATH) || mrt->rt_priority != prio); /* * An ART node with the same destination/netmask already * exists, MPATH conflict must have been already checked. */ if (rt->rt_flags & RTF_MPATH) { /* * Only keep the RTF_MPATH flag if two routes have * the same gateway. */ rt->rt_flags &= ~RTF_MPATH; SRPL_FOREACH_LOCKED(mrt, &an->an_rtlist, rt_next) { if (mrt->rt_priority == prio) { mrt->rt_flags |= RTF_MPATH; rt->rt_flags |= RTF_MPATH; } } } /* Put newly inserted entry at the right place. */ rtable_mpath_insert(an, rt); } leave: rw_exit_write(&ar->ar_lock); rtfree(rt); return (error); } int rtable_delete(unsigned int rtableid, const struct sockaddr *dst, const struct sockaddr *mask, struct rtentry *rt) { struct art_root *ar; struct art_node *an; struct srp_ref sr; const uint8_t *addr; int plen; struct rtentry *mrt; int npaths = 0; int error = 0; ar = rtable_get(rtableid, dst->sa_family); if (ar == NULL) return (EAFNOSUPPORT); addr = satoaddr(ar, dst); plen = rtable_satoplen(dst->sa_family, mask); if (plen == -1) return (EINVAL); rtref(rt); /* guarantee rtfree won't do anything under ar_lock */ rw_enter_write(&ar->ar_lock); an = art_lookup(ar, addr, plen, &sr); srp_leave(&sr); /* an can't go away while we have the lock */ /* Make sure we've got a perfect match. */ if (!an_match(an, dst, plen)) { error = ESRCH; goto leave; } /* * If other multipath route entries are still attached to * this ART node we only have to unlink it. */ SRPL_FOREACH_LOCKED(mrt, &an->an_rtlist, rt_next) npaths++; if (npaths > 1) { KASSERT(refcnt_read(&rt->rt_refcnt) >= 1); SRPL_REMOVE_LOCKED(&rt_rc, &an->an_rtlist, rt, rtentry, rt_next); mrt = SRPL_FIRST_LOCKED(&an->an_rtlist); if (npaths == 2) mrt->rt_flags &= ~RTF_MPATH; goto leave; } if (art_delete(ar, an, addr, plen) == NULL) panic("art_delete failed to find node %p", an); KASSERT(refcnt_read(&rt->rt_refcnt) >= 1); SRPL_REMOVE_LOCKED(&rt_rc, &an->an_rtlist, rt, rtentry, rt_next); art_put(an); leave: rw_exit_write(&ar->ar_lock); rtfree(rt); return (error); } struct rtable_walk_cookie { int (*rwc_func)(struct rtentry *, void *, unsigned int); void *rwc_arg; struct rtentry **rwc_prt; unsigned int rwc_rid; }; /* * Helper for rtable_walk to keep the ART code free from any "struct rtentry". */ int rtable_walk_helper(struct art_node *an, void *xrwc) { struct srp_ref sr; struct rtable_walk_cookie *rwc = xrwc; struct rtentry *rt; int error = 0; SRPL_FOREACH(rt, &sr, &an->an_rtlist, rt_next) { error = (*rwc->rwc_func)(rt, rwc->rwc_arg, rwc->rwc_rid); if (error != 0) break; } if (rwc->rwc_prt != NULL && rt != NULL) { rtref(rt); *rwc->rwc_prt = rt; } SRPL_LEAVE(&sr); return (error); } int rtable_walk(unsigned int rtableid, sa_family_t af, struct rtentry **prt, int (*func)(struct rtentry *, void *, unsigned int), void *arg) { struct art_root *ar; struct rtable_walk_cookie rwc; int error; ar = rtable_get(rtableid, af); if (ar == NULL) return (EAFNOSUPPORT); rwc.rwc_func = func; rwc.rwc_arg = arg; rwc.rwc_prt = prt; rwc.rwc_rid = rtableid; error = art_walk(ar, rtable_walk_helper, &rwc); return (error); } struct rtentry * rtable_iterate(struct rtentry *rt0) { struct rtentry *rt = NULL; struct srp_ref sr; rt = SRPL_NEXT(&sr, rt0, rt_next); if (rt != NULL) rtref(rt); SRPL_LEAVE(&sr); rtfree(rt0); return (rt); } int rtable_mpath_capable(unsigned int rtableid, sa_family_t af) { return (1); } int rtable_mpath_reprio(unsigned int rtableid, struct sockaddr *dst, int plen, uint8_t prio, struct rtentry *rt) { struct art_root *ar; struct art_node *an; struct srp_ref sr; const uint8_t *addr; int error = 0; ar = rtable_get(rtableid, dst->sa_family); if (ar == NULL) return (EAFNOSUPPORT); addr = satoaddr(ar, dst); rw_enter_write(&ar->ar_lock); an = art_lookup(ar, addr, plen, &sr); srp_leave(&sr); /* an can't go away while we have the lock */ /* Make sure we've got a perfect match. */ if (!an_match(an, dst, plen)) { error = ESRCH; } else if (SRPL_FIRST_LOCKED(&an->an_rtlist) == rt && SRPL_NEXT_LOCKED(rt, rt_next) == NULL) { /* * If there's only one entry on the list do not go * through an insert/remove cycle. This is done to * guarantee that ``an->an_rtlist'' is never empty * when a node is in the tree. */ rt->rt_priority = prio; } else { rtref(rt); /* keep rt alive in between remove and insert */ SRPL_REMOVE_LOCKED(&rt_rc, &an->an_rtlist, rt, rtentry, rt_next); rt->rt_priority = prio; rtable_mpath_insert(an, rt); rtfree(rt); error = EAGAIN; } rw_exit_write(&ar->ar_lock); return (error); } void rtable_mpath_insert(struct art_node *an, struct rtentry *rt) { struct rtentry *mrt, *prt = NULL; uint8_t prio = rt->rt_priority; if ((mrt = SRPL_FIRST_LOCKED(&an->an_rtlist)) == NULL) { SRPL_INSERT_HEAD_LOCKED(&rt_rc, &an->an_rtlist, rt, rt_next); return; } /* Iterate until we find the route to be placed after ``rt''. */ while (mrt->rt_priority <= prio && SRPL_NEXT_LOCKED(mrt, rt_next)) { prt = mrt; mrt = SRPL_NEXT_LOCKED(mrt, rt_next); } if (mrt->rt_priority <= prio) { SRPL_INSERT_AFTER_LOCKED(&rt_rc, mrt, rt, rt_next); } else if (prt != NULL) { SRPL_INSERT_AFTER_LOCKED(&rt_rc, prt, rt, rt_next); } else { SRPL_INSERT_HEAD_LOCKED(&rt_rc, &an->an_rtlist, rt, rt_next); } } /* * Returns 1 if ``an'' perfectly matches (``dst'', ``plen''), 0 otherwise. */ int an_match(struct art_node *an, const struct sockaddr *dst, int plen) { struct rtentry *rt; struct srp_ref sr; int match; if (an == NULL || an->an_plen != plen) return (0); rt = SRPL_FIRST(&sr, &an->an_rtlist); match = (rt != NULL && memcmp(rt->rt_dest, dst, dst->sa_len) == 0); SRPL_LEAVE(&sr); return (match); } void rtentry_ref(void *null, void *xrt) { struct rtentry *rt = xrt; rtref(rt); } void rtentry_unref(void *null, void *xrt) { struct rtentry *rt = xrt; rtfree(rt); } /* * Return a pointer to the address (key). This is an heritage from the * BSD radix tree needed to skip the non-address fields from the flavor * of "struct sockaddr" used by this routing table. */ static inline const uint8_t * satoaddr(struct art_root *at, const struct sockaddr *sa) { return (((const uint8_t *)sa) + at->ar_off); } /* * Return the prefix length of a mask. */ int rtable_satoplen(sa_family_t af, const struct sockaddr *mask) { const struct domain *dp; uint8_t *ap, *ep; int mlen, plen = 0; int i; for (i = 0; (dp = domains[i]) != NULL; i++) { if (dp->dom_rtoffset == 0) continue; if (af == dp->dom_family) break; } if (dp == NULL) return (-1); /* Host route */ if (mask == NULL) return (dp->dom_maxplen); mlen = mask->sa_len; /* Default route */ if (mlen == 0) return (0); ap = (uint8_t *)((uint8_t *)mask) + dp->dom_rtoffset; ep = (uint8_t *)((uint8_t *)mask) + mlen; if (ap > ep) return (-1); /* Trim trailing zeroes. */ while (ap < ep && ep[-1] == 0) ep--; if (ap == ep) return (0); /* "Beauty" adapted from sbin/route/show.c ... */ while (ap < ep) { switch (*ap++) { case 0xff: plen += 8; break; case 0xfe: plen += 7; goto out; case 0xfc: plen += 6; goto out; case 0xf8: plen += 5; goto out; case 0xf0: plen += 4; goto out; case 0xe0: plen += 3; goto out; case 0xc0: plen += 2; goto out; case 0x80: plen += 1; goto out; default: /* Non contiguous mask. */ return (-1); } } out: if (plen > dp->dom_maxplen || ap != ep) return -1; return (plen); }
566 567 568 568 501 504 187 187 186 29 152 187 184 68 68 3 48 68 68 826 824 384 478 829 695 222 383 479 82 81 793 661 122 108 442 438 170 303 479 2 2 1 2 2 2 17 100 100 1965 1969 1021 464 1969 464 464 1832 345 123 123 3221 3215 1903 3274 3251 195 1993 2001 86 86 84 86 38 38 8 25 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 /* $OpenBSD: kern_synch.c,v 1.204 2024/05/22 09:24:11 claudio Exp $ */ /* $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1990, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_synch.c 8.6 (Berkeley) 1/21/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/kernel.h> #include <sys/signalvar.h> #include <sys/sched.h> #include <sys/timeout.h> #include <sys/mount.h> #include <sys/syscallargs.h> #include <sys/refcnt.h> #include <sys/atomic.h> #include <sys/tracepoint.h> #include <ddb/db_output.h> #include <machine/spinlock.h> #ifdef DIAGNOSTIC #include <sys/syslog.h> #endif #ifdef KTRACE #include <sys/ktrace.h> #endif int sleep_signal_check(void); int thrsleep(struct proc *, struct sys___thrsleep_args *); int thrsleep_unlock(void *); /* * We're only looking at 7 bits of the address; everything is * aligned to 4, lots of things are aligned to greater powers * of 2. Shift right by 8, i.e. drop the bottom 256 worth. */ #define TABLESIZE 128 #define LOOKUP(x) (((long)(x) >> 8) & (TABLESIZE - 1)) TAILQ_HEAD(slpque,proc) slpque[TABLESIZE]; void sleep_queue_init(void) { int i; for (i = 0; i < TABLESIZE; i++) TAILQ_INIT(&slpque[i]); } /* * Global sleep channel for threads that do not want to * receive wakeup(9) broadcasts. */ int nowake; /* * During autoconfiguration or after a panic, a sleep will simply * lower the priority briefly to allow interrupts, then return. * The priority to be used (safepri) is machine-dependent, thus this * value is initialized and maintained in the machine-dependent layers. * This priority will typically be 0, or the lowest priority * that is safe for use on the interrupt stack; it can be made * higher to block network software interrupts after panics. */ extern int safepri; /* * General sleep call. Suspends the current process until a wakeup is * performed on the specified identifier. The process will then be made * runnable with the specified priority. Sleeps at most timo/hz seconds * (0 means no timeout). If pri includes PCATCH flag, signals are checked * before and after sleeping, else signals are not checked. Returns 0 if * awakened, EWOULDBLOCK if the timeout expires. If PCATCH is set and a * signal needs to be delivered, ERESTART is returned if the current system * call should be restarted if possible, and EINTR is returned if the system * call should be interrupted by the signal (return EINTR). */ int tsleep(const volatile void *ident, int priority, const char *wmesg, int timo) { #ifdef MULTIPROCESSOR int hold_count; #endif KASSERT((priority & ~(PRIMASK | PCATCH)) == 0); KASSERT(ident != &nowake || ISSET(priority, PCATCH) || timo != 0); #ifdef MULTIPROCESSOR KASSERT(ident == &nowake || timo || _kernel_lock_held()); #endif #ifdef DDB if (cold == 2) db_stack_dump(); #endif if (cold || panicstr) { int s; /* * After a panic, or during autoconfiguration, * just give interrupts a chance, then just return; * don't run any other procs or panic below, * in case this is the idle process and already asleep. */ s = splhigh(); splx(safepri); #ifdef MULTIPROCESSOR if (_kernel_lock_held()) { hold_count = __mp_release_all(&kernel_lock); __mp_acquire_count(&kernel_lock, hold_count); } #endif splx(s); return (0); } sleep_setup(ident, priority, wmesg); return sleep_finish(timo, 1); } int tsleep_nsec(const volatile void *ident, int priority, const char *wmesg, uint64_t nsecs) { uint64_t to_ticks; if (nsecs == INFSLP) return tsleep(ident, priority, wmesg, 0); #ifdef DIAGNOSTIC if (nsecs == 0) { log(LOG_WARNING, "%s: %s[%d]: %s: trying to sleep zero nanoseconds\n", __func__, curproc->p_p->ps_comm, curproc->p_p->ps_pid, wmesg); } #endif /* * We want to sleep at least nsecs nanoseconds worth of ticks. * * - Clamp nsecs to prevent arithmetic overflow. * * - Round nsecs up to account for any nanoseconds that do not * divide evenly into tick_nsec, otherwise we'll lose them to * integer division in the next step. We add (tick_nsec - 1) * to keep from introducing a spurious tick if there are no * such nanoseconds, i.e. nsecs % tick_nsec == 0. * * - Divide the rounded value to a count of ticks. We divide * by (tick_nsec + 1) to discard the extra tick introduced if, * before rounding, nsecs % tick_nsec == 1. * * - Finally, add a tick to the result. We need to wait out * the current tick before we can begin counting our interval, * as we do not know how much time has elapsed since the * current tick began. */ nsecs = MIN(nsecs, UINT64_MAX - tick_nsec); to_ticks = (nsecs + tick_nsec - 1) / (tick_nsec + 1) + 1; if (to_ticks > INT_MAX) to_ticks = INT_MAX; return tsleep(ident, priority, wmesg, (int)to_ticks); } /* * Same as tsleep, but if we have a mutex provided, then once we've * entered the sleep queue we drop the mutex. After sleeping we re-lock. */ int msleep(const volatile void *ident, struct mutex *mtx, int priority, const char *wmesg, int timo) { int error, spl; #ifdef MULTIPROCESSOR int hold_count; #endif KASSERT((priority & ~(PRIMASK | PCATCH | PNORELOCK)) == 0); KASSERT(ident != &nowake || ISSET(priority, PCATCH) || timo != 0); KASSERT(mtx != NULL); #ifdef DDB if (cold == 2) db_stack_dump(); #endif if (cold || panicstr) { /* * After a panic, or during autoconfiguration, * just give interrupts a chance, then just return; * don't run any other procs or panic below, * in case this is the idle process and already asleep. */ spl = MUTEX_OLDIPL(mtx); MUTEX_OLDIPL(mtx) = safepri; mtx_leave(mtx); #ifdef MULTIPROCESSOR if (_kernel_lock_held()) { hold_count = __mp_release_all(&kernel_lock); __mp_acquire_count(&kernel_lock, hold_count); } #endif if ((priority & PNORELOCK) == 0) { mtx_enter(mtx); MUTEX_OLDIPL(mtx) = spl; } else splx(spl); return (0); } sleep_setup(ident, priority, wmesg); mtx_leave(mtx); /* signal may stop the process, release mutex before that */ error = sleep_finish(timo, 1); if ((priority & PNORELOCK) == 0) mtx_enter(mtx); return error; } int msleep_nsec(const volatile void *ident, struct mutex *mtx, int priority, const char *wmesg, uint64_t nsecs) { uint64_t to_ticks; if (nsecs == INFSLP) return msleep(ident, mtx, priority, wmesg, 0); #ifdef DIAGNOSTIC if (nsecs == 0) { log(LOG_WARNING, "%s: %s[%d]: %s: trying to sleep zero nanoseconds\n", __func__, curproc->p_p->ps_comm, curproc->p_p->ps_pid, wmesg); } #endif nsecs = MIN(nsecs, UINT64_MAX - tick_nsec); to_ticks = (nsecs + tick_nsec - 1) / (tick_nsec + 1) + 1; if (to_ticks > INT_MAX) to_ticks = INT_MAX; return msleep(ident, mtx, priority, wmesg, (int)to_ticks); } /* * Same as tsleep, but if we have a rwlock provided, then once we've * entered the sleep queue we drop the it. After sleeping we re-lock. */ int rwsleep(const volatile void *ident, struct rwlock *rwl, int priority, const char *wmesg, int timo) { int error, status; KASSERT((priority & ~(PRIMASK | PCATCH | PNORELOCK)) == 0); KASSERT(ident != &nowake || ISSET(priority, PCATCH) || timo != 0); KASSERT(ident != rwl); rw_assert_anylock(rwl); status = rw_status(rwl); sleep_setup(ident, priority, wmesg); rw_exit(rwl); /* signal may stop the process, release rwlock before that */ error = sleep_finish(timo, 1); if ((priority & PNORELOCK) == 0) rw_enter(rwl, status); return error; } int rwsleep_nsec(const volatile void *ident, struct rwlock *rwl, int priority, const char *wmesg, uint64_t nsecs) { uint64_t to_ticks; if (nsecs == INFSLP) return rwsleep(ident, rwl, priority, wmesg, 0); #ifdef DIAGNOSTIC if (nsecs == 0) { log(LOG_WARNING, "%s: %s[%d]: %s: trying to sleep zero nanoseconds\n", __func__, curproc->p_p->ps_comm, curproc->p_p->ps_pid, wmesg); } #endif nsecs = MIN(nsecs, UINT64_MAX - tick_nsec); to_ticks = (nsecs + tick_nsec - 1) / (tick_nsec + 1) + 1; if (to_ticks > INT_MAX) to_ticks = INT_MAX; return rwsleep(ident, rwl, priority, wmesg, (int)to_ticks); } void sleep_setup(const volatile void *ident, int prio, const char *wmesg) { struct proc *p = curproc; int s; #ifdef DIAGNOSTIC if (p->p_flag & P_CANTSLEEP) panic("sleep: %s failed insomnia", p->p_p->ps_comm); if (ident == NULL) panic("tsleep: no ident"); if (p->p_stat != SONPROC) panic("tsleep: not SONPROC"); #endif /* exiting processes are not allowed to catch signals */ if (p->p_flag & P_WEXIT) CLR(prio, PCATCH); SCHED_LOCK(s); TRACEPOINT(sched, sleep, NULL); p->p_wchan = ident; p->p_wmesg = wmesg; p->p_slptime = 0; p->p_slppri = prio & PRIMASK; atomic_setbits_int(&p->p_flag, P_WSLEEP); TAILQ_INSERT_TAIL(&slpque[LOOKUP(ident)], p, p_runq); if (prio & PCATCH) atomic_setbits_int(&p->p_flag, P_SINTR); p->p_stat = SSLEEP; SCHED_UNLOCK(s); } int sleep_finish(int timo, int do_sleep) { struct proc *p = curproc; int s, catch, error = 0, error1 = 0; catch = p->p_flag & P_SINTR; if (timo != 0) { KASSERT((p->p_flag & P_TIMEOUT) == 0); timeout_add(&p->p_sleep_to, timo); } if (catch != 0) { /* * We put ourselves on the sleep queue and start our * timeout before calling sleep_signal_check(), as we could * stop there, and a wakeup or a SIGCONT (or both) could * occur while we were stopped. A SIGCONT would cause * us to be marked as SSLEEP without resuming us, thus * we must be ready for sleep when sleep_signal_check() is * called. */ if ((error = sleep_signal_check()) != 0) { catch = 0; do_sleep = 0; } } SCHED_LOCK(s); /* * If the wakeup happens while going to sleep, p->p_wchan * will be NULL. In that case unwind immediately but still * check for possible signals and timeouts. */ if (p->p_wchan == NULL) do_sleep = 0; atomic_clearbits_int(&p->p_flag, P_WSLEEP); if (do_sleep) { KASSERT(p->p_stat == SSLEEP || p->p_stat == SSTOP); p->p_ru.ru_nvcsw++; mi_switch(); } else { KASSERT(p->p_stat == SONPROC || p->p_stat == SSLEEP || p->p_stat == SSTOP); unsleep(p); p->p_stat = SONPROC; } #ifdef DIAGNOSTIC if (p->p_stat != SONPROC) panic("sleep_finish !SONPROC"); #endif p->p_cpu->ci_schedstate.spc_curpriority = p->p_usrpri; SCHED_UNLOCK(s); /* * Even though this belongs to the signal handling part of sleep, * we need to clear it before the ktrace. */ atomic_clearbits_int(&p->p_flag, P_SINTR); if (timo != 0) { if (p->p_flag & P_TIMEOUT) { error1 = EWOULDBLOCK; } else { /* This can sleep. It must not use timeouts. */ timeout_del_barrier(&p->p_sleep_to); } atomic_clearbits_int(&p->p_flag, P_TIMEOUT); } /* Check if thread was woken up because of a unwind or signal */ if (catch != 0) error = sleep_signal_check(); /* Signal errors are higher priority than timeouts. */ if (error == 0 && error1 != 0) error = error1; return error; } /* * Check and handle signals and suspensions around a sleep cycle. */ int sleep_signal_check(void) { struct proc *p = curproc; struct sigctx ctx; int err, sig; if ((err = single_thread_check(p, 1)) != 0) return err; if ((sig = cursig(p, &ctx)) != 0) { if (ctx.sig_intr) return EINTR; else return ERESTART; } return 0; } int wakeup_proc(struct proc *p, int flags) { int awakened = 0; SCHED_ASSERT_LOCKED(); if (p->p_wchan != NULL) { awakened = 1; if (flags) atomic_setbits_int(&p->p_flag, flags); #ifdef DIAGNOSTIC if (p->p_stat != SSLEEP && p->p_stat != SSTOP) panic("thread %d p_stat is %d", p->p_tid, p->p_stat); #endif unsleep(p); if (p->p_stat == SSLEEP) setrunnable(p); } return awakened; } /* * Implement timeout for tsleep. * If process hasn't been awakened (wchan non-zero), * set timeout flag and undo the sleep. If proc * is stopped, just unsleep so it will remain stopped. */ void endtsleep(void *arg) { struct proc *p = arg; int s; SCHED_LOCK(s); wakeup_proc(p, P_TIMEOUT); SCHED_UNLOCK(s); } /* * Remove a process from its wait queue */ void unsleep(struct proc *p) { SCHED_ASSERT_LOCKED(); if (p->p_wchan != NULL) { TAILQ_REMOVE(&slpque[LOOKUP(p->p_wchan)], p, p_runq); p->p_wchan = NULL; p->p_wmesg = NULL; TRACEPOINT(sched, unsleep, p->p_tid + THREAD_PID_OFFSET, p->p_p->ps_pid); } } /* * Make a number of processes sleeping on the specified identifier runnable. */ void wakeup_n(const volatile void *ident, int n) { struct slpque *qp, wakeq; struct proc *p; struct proc *pnext; int s; TAILQ_INIT(&wakeq); SCHED_LOCK(s); qp = &slpque[LOOKUP(ident)]; for (p = TAILQ_FIRST(qp); p != NULL && n != 0; p = pnext) { pnext = TAILQ_NEXT(p, p_runq); #ifdef DIAGNOSTIC if (p->p_stat != SSLEEP && p->p_stat != SSTOP) panic("thread %d p_stat is %d", p->p_tid, p->p_stat); #endif KASSERT(p->p_wchan != NULL); if (p->p_wchan == ident) { TAILQ_REMOVE(qp, p, p_runq); p->p_wchan = NULL; p->p_wmesg = NULL; TAILQ_INSERT_TAIL(&wakeq, p, p_runq); --n; } } while ((p = TAILQ_FIRST(&wakeq))) { TAILQ_REMOVE(&wakeq, p, p_runq); TRACEPOINT(sched, unsleep, p->p_tid + THREAD_PID_OFFSET, p->p_p->ps_pid); if (p->p_stat == SSLEEP) setrunnable(p); } SCHED_UNLOCK(s); } /* * Make all processes sleeping on the specified identifier runnable. */ void wakeup(const volatile void *chan) { wakeup_n(chan, -1); } int sys_sched_yield(struct proc *p, void *v, register_t *retval) { struct proc *q; uint8_t newprio; int s; /* * If one of the threads of a multi-threaded process called * sched_yield(2), drop its priority to ensure its siblings * can make some progress. */ mtx_enter(&p->p_p->ps_mtx); newprio = p->p_usrpri; TAILQ_FOREACH(q, &p->p_p->ps_threads, p_thr_link) newprio = max(newprio, q->p_runpri); mtx_leave(&p->p_p->ps_mtx); SCHED_LOCK(s); setrunqueue(p->p_cpu, p, newprio); p->p_ru.ru_nvcsw++; mi_switch(); SCHED_UNLOCK(s); return (0); } int thrsleep_unlock(void *lock) { static _atomic_lock_t unlocked = _ATOMIC_LOCK_UNLOCKED; _atomic_lock_t *atomiclock = lock; if (!lock) return 0; return copyout(&unlocked, atomiclock, sizeof(unlocked)); } struct tslpentry { TAILQ_ENTRY(tslpentry) tslp_link; long tslp_ident; }; /* thrsleep queue shared between processes */ static struct tslpqueue thrsleep_queue = TAILQ_HEAD_INITIALIZER(thrsleep_queue); static struct rwlock thrsleep_lock = RWLOCK_INITIALIZER("thrsleeplk"); int thrsleep(struct proc *p, struct sys___thrsleep_args *v) { struct sys___thrsleep_args /* { syscallarg(const volatile void *) ident; syscallarg(clockid_t) clock_id; syscallarg(const struct timespec *) tp; syscallarg(void *) lock; syscallarg(const int *) abort; } */ *uap = v; long ident = (long)SCARG(uap, ident); struct tslpentry entry; struct tslpqueue *queue; struct rwlock *qlock; struct timespec *tsp = (struct timespec *)SCARG(uap, tp); void *lock = SCARG(uap, lock); uint64_t nsecs = INFSLP; int abort = 0, error; clockid_t clock_id = SCARG(uap, clock_id); if (ident == 0) return (EINVAL); if (tsp != NULL) { struct timespec now; if ((error = clock_gettime(p, clock_id, &now))) return (error); #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrabstimespec(p, tsp); #endif if (timespeccmp(tsp, &now, <=)) { /* already passed: still do the unlock */ if ((error = thrsleep_unlock(lock))) return (error); return (EWOULDBLOCK); } timespecsub(tsp, &now, tsp); nsecs = MIN(TIMESPEC_TO_NSEC(tsp), MAXTSLP); } if (ident == -1) { queue = &thrsleep_queue; qlock = &thrsleep_lock; } else { queue = &p->p_p->ps_tslpqueue; qlock = &p->p_p->ps_lock; } /* Interlock with wakeup. */ entry.tslp_ident = ident; rw_enter_write(qlock); TAILQ_INSERT_TAIL(queue, &entry, tslp_link); rw_exit_write(qlock); error = thrsleep_unlock(lock); if (error == 0 && SCARG(uap, abort) != NULL) error = copyin(SCARG(uap, abort), &abort, sizeof(abort)); rw_enter_write(qlock); if (error != 0) goto out; if (abort != 0) { error = EINTR; goto out; } if (entry.tslp_ident != 0) { error = rwsleep_nsec(&entry, qlock, PWAIT|PCATCH, "thrsleep", nsecs); } out: if (entry.tslp_ident != 0) TAILQ_REMOVE(queue, &entry, tslp_link); rw_exit_write(qlock); if (error == ERESTART) error = ECANCELED; return (error); } int sys___thrsleep(struct proc *p, void *v, register_t *retval) { struct sys___thrsleep_args /* { syscallarg(const volatile void *) ident; syscallarg(clockid_t) clock_id; syscallarg(struct timespec *) tp; syscallarg(void *) lock; syscallarg(const int *) abort; } */ *uap = v; struct timespec ts; int error; if (SCARG(uap, tp) != NULL) { if ((error = copyin(SCARG(uap, tp), &ts, sizeof(ts)))) { *retval = error; return 0; } if (!timespecisvalid(&ts)) { *retval = EINVAL; return 0; } SCARG(uap, tp) = &ts; } *retval = thrsleep(p, uap); return 0; } int sys___thrwakeup(struct proc *p, void *v, register_t *retval) { struct sys___thrwakeup_args /* { syscallarg(const volatile void *) ident; syscallarg(int) n; } */ *uap = v; struct tslpentry *entry, *tmp; struct tslpqueue *queue; struct rwlock *qlock; long ident = (long)SCARG(uap, ident); int n = SCARG(uap, n); int found = 0; if (ident == 0) *retval = EINVAL; else { if (ident == -1) { queue = &thrsleep_queue; qlock = &thrsleep_lock; /* * Wake up all waiters with ident -1. This is needed * because ident -1 can be shared by multiple userspace * lock state machines concurrently. The implementation * has no way to direct the wakeup to a particular * state machine. */ n = 0; } else { queue = &p->p_p->ps_tslpqueue; qlock = &p->p_p->ps_lock; } rw_enter_write(qlock); TAILQ_FOREACH_SAFE(entry, queue, tslp_link, tmp) { if (entry->tslp_ident == ident) { TAILQ_REMOVE(queue, entry, tslp_link); entry->tslp_ident = 0; wakeup_one(entry); if (++found == n) break; } } rw_exit_write(qlock); if (ident == -1) *retval = 0; else *retval = found ? 0 : ESRCH; } return (0); } void refcnt_init(struct refcnt *r) { refcnt_init_trace(r, 0); } void refcnt_init_trace(struct refcnt *r, int idx) { r->r_traceidx = idx; atomic_store_int(&r->r_refs, 1); TRACEINDEX(refcnt, r->r_traceidx, r, 0, +1); } void refcnt_take(struct refcnt *r) { u_int refs; refs = atomic_inc_int_nv(&r->r_refs); KASSERT(refs != 0); TRACEINDEX(refcnt, r->r_traceidx, r, refs - 1, +1); (void)refs; } int refcnt_rele(struct refcnt *r) { u_int refs; membar_exit_before_atomic(); refs = atomic_dec_int_nv(&r->r_refs); KASSERT(refs != ~0); TRACEINDEX(refcnt, r->r_traceidx, r, refs + 1, -1); if (refs == 0) { membar_enter_after_atomic(); return (1); } return (0); } void refcnt_rele_wake(struct refcnt *r) { if (refcnt_rele(r)) wakeup_one(r); } void refcnt_finalize(struct refcnt *r, const char *wmesg) { u_int refs; membar_exit_before_atomic(); refs = atomic_dec_int_nv(&r->r_refs); KASSERT(refs != ~0); TRACEINDEX(refcnt, r->r_traceidx, r, refs + 1, -1); while (refs) { sleep_setup(r, PWAIT, wmesg); refs = atomic_load_int(&r->r_refs); sleep_finish(0, refs); } TRACEINDEX(refcnt, r->r_traceidx, r, refs, 0); /* Order subsequent loads and stores after refs == 0 load. */ membar_sync(); } int refcnt_shared(struct refcnt *r) { u_int refs; refs = atomic_load_int(&r->r_refs); TRACEINDEX(refcnt, r->r_traceidx, r, refs, 0); return (refs > 1); } unsigned int refcnt_read(struct refcnt *r) { u_int refs; refs = atomic_load_int(&r->r_refs); TRACEINDEX(refcnt, r->r_traceidx, r, refs, 0); return (refs); } void cond_init(struct cond *c) { atomic_store_int(&c->c_wait, 1); } void cond_signal(struct cond *c) { atomic_store_int(&c->c_wait, 0); wakeup_one(c); } void cond_wait(struct cond *c, const char *wmesg) { unsigned int wait; wait = atomic_load_int(&c->c_wait); while (wait) { sleep_setup(c, PWAIT, wmesg); wait = atomic_load_int(&c->c_wait); sleep_finish(0, wait); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 /* $OpenBSD: kref.h,v 1.6 2023/03/21 09:44:35 jsg Exp $ */ /* * Copyright (c) 2015 Mark Kettenis * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _LINUX_KREF_H #define _LINUX_KREF_H #include <sys/types.h> #include <sys/rwlock.h> #include <linux/refcount.h> #include <linux/spinlock.h> struct kref { uint32_t refcount; }; static inline void kref_init(struct kref *ref) { atomic_set(&ref->refcount, 1); } static inline unsigned int kref_read(const struct kref *ref) { return atomic_read(&ref->refcount); } static inline void kref_get(struct kref *ref) { atomic_inc_int(&ref->refcount); } static inline int kref_get_unless_zero(struct kref *ref) { if (ref->refcount != 0) { atomic_inc_int(&ref->refcount); return (1); } else { return (0); } } static inline int kref_put(struct kref *ref, void (*release)(struct kref *ref)) { if (atomic_dec_int_nv(&ref->refcount) == 0) { release(ref); return 1; } return 0; } static inline int kref_put_mutex(struct kref *kref, void (*release)(struct kref *kref), struct rwlock *lock) { if (!atomic_add_unless(&kref->refcount, -1, 1)) { rw_enter_write(lock); if (likely(atomic_dec_and_test(&kref->refcount))) { release(kref); return 1; } rw_exit_write(lock); return 0; } return 0; } static inline int kref_put_lock(struct kref *kref, void (*release)(struct kref *kref), struct mutex *lock) { if (!atomic_add_unless(&kref->refcount, -1, 1)) { mtx_enter(lock); if (likely(atomic_dec_and_test(&kref->refcount))) { release(kref); return 1; } mtx_leave(lock); return 0; } return 0; } #endif
47 29 3 35 34 5 11 23 11 47 47 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 /* $OpenBSD: kern_exec.c,v 1.255 2024/04/02 08:39:16 deraadt Exp $ */ /* $NetBSD: kern_exec.c,v 1.75 1996/02/09 18:59:28 christos Exp $ */ /*- * Copyright (C) 1993, 1994 Christopher G. Demetriou * Copyright (C) 1992 Wolfgang Solfrank. * Copyright (C) 1992 TooLs GmbH. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by TooLs GmbH. * 4. The name of TooLs GmbH may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/filedesc.h> #include <sys/proc.h> #include <sys/user.h> #include <sys/mount.h> #include <sys/malloc.h> #include <sys/pool.h> #include <sys/namei.h> #include <sys/vnode.h> #include <sys/fcntl.h> #include <sys/file.h> #include <sys/acct.h> #include <sys/exec.h> #include <sys/exec_elf.h> #include <sys/ktrace.h> #include <sys/resourcevar.h> #include <sys/mman.h> #include <sys/signalvar.h> #include <sys/stat.h> #include <sys/conf.h> #include <sys/pledge.h> #ifdef SYSVSHM #include <sys/shm.h> #endif #include <sys/syscallargs.h> #include <uvm/uvm_extern.h> #include <machine/tcb.h> #include <sys/timetc.h> struct uvm_object *sigobject; /* shared sigcode object */ vaddr_t sigcode_va; vsize_t sigcode_sz; struct uvm_object *timekeep_object; struct timekeep *timekeep; void unveil_destroy(struct process *ps); const struct kmem_va_mode kv_exec = { .kv_wait = 1, .kv_map = &exec_map }; /* * Map the shared signal code. */ int exec_sigcode_map(struct process *); /* * Map the shared timekeep page. */ int exec_timekeep_map(struct process *); /* * If non-zero, stackgap_random specifies the upper limit of the random gap size * added to the fixed stack position. Must be n^2. */ int stackgap_random = STACKGAP_RANDOM; /* * check exec: * given an "executable" described in the exec package's namei info, * see what we can do with it. * * ON ENTRY: * exec package with appropriate namei info * proc pointer of exec'ing proc * NO SELF-LOCKED VNODES * * ON EXIT: * error: nothing held, etc. exec header still allocated. * ok: filled exec package, one locked vnode. * * EXEC SWITCH ENTRY: * Locked vnode to check, exec package, proc. * * EXEC SWITCH EXIT: * ok: return 0, filled exec package, one locked vnode. * error: destructive: * everything deallocated except exec header. * non-destructive: * error code, locked vnode, exec header unmodified */ int check_exec(struct proc *p, struct exec_package *epp) { int error, i; struct vnode *vp; struct nameidata *ndp; size_t resid; ndp = epp->ep_ndp; ndp->ni_cnd.cn_nameiop = LOOKUP; ndp->ni_cnd.cn_flags = FOLLOW | LOCKLEAF | SAVENAME; if (epp->ep_flags & EXEC_INDIR) ndp->ni_cnd.cn_flags |= BYPASSUNVEIL; /* first get the vnode */ if ((error = namei(ndp)) != 0) return (error); epp->ep_vp = vp = ndp->ni_vp; /* check for regular file */ if (vp->v_type != VREG) { error = EACCES; goto bad1; } /* get attributes */ if ((error = VOP_GETATTR(vp, epp->ep_vap, p->p_ucred, p)) != 0) goto bad1; /* Check mount point */ if (vp->v_mount->mnt_flag & MNT_NOEXEC) { error = EACCES; goto bad1; } /* SUID programs may not be started with execpromises */ if ((epp->ep_vap->va_mode & (VSUID | VSGID)) && (p->p_p->ps_flags & PS_EXECPLEDGE)) { error = EACCES; goto bad1; } if ((vp->v_mount->mnt_flag & MNT_NOSUID)) epp->ep_vap->va_mode &= ~(VSUID | VSGID); /* check access. for root we have to see if any exec bit on */ if ((error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p)) != 0) goto bad1; if ((epp->ep_vap->va_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0) { error = EACCES; goto bad1; } /* try to open it */ if ((error = VOP_OPEN(vp, FREAD, p->p_ucred, p)) != 0) goto bad1; /* unlock vp, we need it unlocked from here */ VOP_UNLOCK(vp); /* now we have the file, get the exec header */ error = vn_rdwr(UIO_READ, vp, epp->ep_hdr, epp->ep_hdrlen, 0, UIO_SYSSPACE, 0, p->p_ucred, &resid, p); if (error) goto bad2; epp->ep_hdrvalid = epp->ep_hdrlen - resid; /* * set up the vmcmds for creation of the process * address space */ error = ENOEXEC; for (i = 0; i < nexecs && error != 0; i++) { int newerror; if (execsw[i].es_check == NULL) continue; newerror = (*execsw[i].es_check)(p, epp); /* make sure the first "interesting" error code is saved. */ if (!newerror || error == ENOEXEC) error = newerror; if (epp->ep_flags & EXEC_DESTR && error != 0) return (error); } if (!error) { /* check that entry point is sane */ if (epp->ep_entry > VM_MAXUSER_ADDRESS) { error = ENOEXEC; } /* check limits */ if ((epp->ep_tsize > MAXTSIZ) || (epp->ep_dsize > lim_cur(RLIMIT_DATA))) error = ENOMEM; if (!error) return (0); } /* * free any vmspace-creation commands, * and release their references */ kill_vmcmds(&epp->ep_vmcmds); bad2: /* * close the vnode, free the pathname buf, and punt. */ vn_close(vp, FREAD, p->p_ucred, p); pool_put(&namei_pool, ndp->ni_cnd.cn_pnbuf); return (error); bad1: /* * free the namei pathname buffer, and put the vnode * (which we don't yet have open). */ pool_put(&namei_pool, ndp->ni_cnd.cn_pnbuf); vput(vp); return (error); } /* * exec system call */ int sys_execve(struct proc *p, void *v, register_t *retval) { struct sys_execve_args /* { syscallarg(const char *) path; syscallarg(char *const *) argp; syscallarg(char *const *) envp; } */ *uap = v; int error; struct exec_package pack; struct nameidata nid; struct vattr attr; struct ucred *cred = p->p_ucred; char *argp; char * const *cpp, *dp, *sp; #ifdef KTRACE char *env_start; #endif struct process *pr = p->p_p; long argc, envc; size_t len, sgap, dstsize; #ifdef MACHINE_STACK_GROWS_UP size_t slen; #endif char *stack; struct ps_strings arginfo; struct vmspace *vm = p->p_vmspace; struct vnode *otvp; /* * Get other threads to stop, if contested return ERESTART, * so the syscall is restarted after halting in userret. */ if (single_thread_set(p, SINGLE_UNWIND | SINGLE_DEEP)) return (ERESTART); /* * Cheap solution to complicated problems. * Mark this process as "leave me alone, I'm execing". */ atomic_setbits_int(&pr->ps_flags, PS_INEXEC); NDINIT(&nid, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p); nid.ni_pledge = PLEDGE_EXEC; nid.ni_unveil = UNVEIL_EXEC; /* * initialize the fields of the exec package. */ pack.ep_name = (char *)SCARG(uap, path); pack.ep_hdr = malloc(exec_maxhdrsz, M_EXEC, M_WAITOK); pack.ep_hdrlen = exec_maxhdrsz; pack.ep_hdrvalid = 0; pack.ep_ndp = &nid; pack.ep_interp = NULL; pack.ep_args = NULL; pack.ep_auxinfo = NULL; VMCMDSET_INIT(&pack.ep_vmcmds); pack.ep_vap = &attr; pack.ep_flags = 0; pack.ep_pins = NULL; pack.ep_npins = 0; /* see if we can run it. */ if ((error = check_exec(p, &pack)) != 0) { goto freehdr; } /* XXX -- THE FOLLOWING SECTION NEEDS MAJOR CLEANUP */ /* allocate an argument buffer */ argp = km_alloc(NCARGS, &kv_exec, &kp_pageable, &kd_waitok); #ifdef DIAGNOSTIC if (argp == NULL) panic("execve: argp == NULL"); #endif dp = argp; argc = 0; /* * Copy the fake args list, if there's one, freeing it as we go. * exec_script_makecmds() allocates either 2 or 3 fake args bounded * by MAXINTERP + MAXPATHLEN < NCARGS so no overflow can happen. */ if (pack.ep_flags & EXEC_HASARGL) { dstsize = NCARGS; for(; pack.ep_fa[argc] != NULL; argc++) { len = strlcpy(dp, pack.ep_fa[argc], dstsize); len++; dp += len; dstsize -= len; if (pack.ep_fa[argc+1] != NULL) free(pack.ep_fa[argc], M_EXEC, len); else free(pack.ep_fa[argc], M_EXEC, MAXPATHLEN); } free(pack.ep_fa, M_EXEC, 4 * sizeof(char *)); pack.ep_flags &= ~EXEC_HASARGL; } /* Now get argv & environment */ if (!(cpp = SCARG(uap, argp))) { error = EFAULT; goto bad; } if (pack.ep_flags & EXEC_SKIPARG) cpp++; while (1) { len = argp + ARG_MAX - dp; if ((error = copyin(cpp, &sp, sizeof(sp))) != 0) goto bad; if (!sp) break; if ((error = copyinstr(sp, dp, len, &len)) != 0) { if (error == ENAMETOOLONG) error = E2BIG; goto bad; } dp += len; cpp++; argc++; } /* must have at least one argument */ if (argc == 0) { error = EINVAL; goto bad; } #ifdef KTRACE if (KTRPOINT(p, KTR_EXECARGS)) ktrexec(p, KTR_EXECARGS, argp, dp - argp); #endif envc = 0; /* environment does not need to be there */ if ((cpp = SCARG(uap, envp)) != NULL ) { #ifdef KTRACE env_start = dp; #endif while (1) { len = argp + ARG_MAX - dp; if ((error = copyin(cpp, &sp, sizeof(sp))) != 0) goto bad; if (!sp) break; if ((error = copyinstr(sp, dp, len, &len)) != 0) { if (error == ENAMETOOLONG) error = E2BIG; goto bad; } dp += len; cpp++; envc++; } #ifdef KTRACE if (KTRPOINT(p, KTR_EXECENV)) ktrexec(p, KTR_EXECENV, env_start, dp - env_start); #endif } dp = (char *)(((long)dp + _STACKALIGNBYTES) & ~_STACKALIGNBYTES); /* * If we have enabled random stackgap, the stack itself has already * been moved from a random location, but is still aligned to a page * boundary. Provide the lower bits of random placement now. */ if (stackgap_random == 0) { sgap = 0; } else { sgap = arc4random() & PAGE_MASK; sgap = (sgap + _STACKALIGNBYTES) & ~_STACKALIGNBYTES; } /* Now check if args & environ fit into new stack */ len = ((argc + envc + 2 + ELF_AUX_WORDS) * sizeof(char *) + sizeof(long) + dp + sgap + sizeof(struct ps_strings)) - argp; len = (len + _STACKALIGNBYTES) &~ _STACKALIGNBYTES; if (len > pack.ep_ssize) { /* in effect, compare to initial limit */ error = ENOMEM; goto bad; } /* adjust "active stack depth" for process VSZ */ pack.ep_ssize = len; /* maybe should go elsewhere, but... */ /* * we're committed: any further errors will kill the process, so * kill the other threads now. */ single_thread_set(p, SINGLE_EXIT); /* * Prepare vmspace for remapping. Note that uvmspace_exec can replace * ps_vmspace! */ uvmspace_exec(p, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS); vm = pr->ps_vmspace; /* Now map address space */ vm->vm_taddr = (char *)trunc_page(pack.ep_taddr); vm->vm_tsize = atop(round_page(pack.ep_taddr + pack.ep_tsize) - trunc_page(pack.ep_taddr)); vm->vm_daddr = (char *)trunc_page(pack.ep_daddr); vm->vm_dsize = atop(round_page(pack.ep_daddr + pack.ep_dsize) - trunc_page(pack.ep_daddr)); vm->vm_dused = 0; vm->vm_ssize = atop(round_page(pack.ep_ssize)); vm->vm_maxsaddr = (char *)pack.ep_maxsaddr; vm->vm_minsaddr = (char *)pack.ep_minsaddr; /* create the new process's VM space by running the vmcmds */ #ifdef DIAGNOSTIC if (pack.ep_vmcmds.evs_used == 0) panic("execve: no vmcmds"); #endif error = exec_process_vmcmds(p, &pack); /* if an error happened, deallocate and punt */ if (error) goto exec_abort; #ifdef MACHINE_STACK_GROWS_UP pr->ps_strings = (vaddr_t)vm->vm_maxsaddr + sgap; if (uvm_map_protect(&vm->vm_map, (vaddr_t)vm->vm_maxsaddr, trunc_page(pr->ps_strings), PROT_NONE, 0, TRUE, FALSE)) goto exec_abort; #else pr->ps_strings = (vaddr_t)vm->vm_minsaddr - sizeof(arginfo) - sgap; if (uvm_map_protect(&vm->vm_map, round_page(pr->ps_strings + sizeof(arginfo)), (vaddr_t)vm->vm_minsaddr, PROT_NONE, 0, TRUE, FALSE)) goto exec_abort; #endif memset(&arginfo, 0, sizeof(arginfo)); /* remember information about the process */ arginfo.ps_nargvstr = argc; arginfo.ps_nenvstr = envc; #ifdef MACHINE_STACK_GROWS_UP stack = (char *)vm->vm_maxsaddr + sizeof(arginfo) + sgap; slen = len - sizeof(arginfo) - sgap; #else stack = (char *)(vm->vm_minsaddr - len); #endif /* Now copy argc, args & environ to new stack */ if (!copyargs(&pack, &arginfo, stack, argp)) goto exec_abort; pr->ps_auxinfo = (vaddr_t)pack.ep_auxinfo; /* copy out the process's ps_strings structure */ if (copyout(&arginfo, (char *)pr->ps_strings, sizeof(arginfo))) goto exec_abort; free(pr->ps_pin.pn_pins, M_PINSYSCALL, pr->ps_pin.pn_npins * sizeof(u_int)); if (pack.ep_npins) { pr->ps_pin.pn_start = pack.ep_pinstart; pr->ps_pin.pn_end = pack.ep_pinend; pr->ps_pin.pn_pins = pack.ep_pins; pack.ep_pins = NULL; pr->ps_pin.pn_npins = pack.ep_npins; pr->ps_flags |= PS_PIN; } else { pr->ps_pin.pn_start = pr->ps_pin.pn_end = 0; pr->ps_pin.pn_pins = NULL; pr->ps_pin.pn_npins = 0; pr->ps_flags &= ~PS_PIN; } if (pr->ps_libcpin.pn_pins) { free(pr->ps_libcpin.pn_pins, M_PINSYSCALL, pr->ps_libcpin.pn_npins * sizeof(u_int)); pr->ps_libcpin.pn_start = pr->ps_libcpin.pn_end = 0; pr->ps_libcpin.pn_pins = NULL; pr->ps_libcpin.pn_npins = 0; pr->ps_flags &= ~PS_LIBCPIN; } stopprofclock(pr); /* stop profiling */ fdcloseexec(p); /* handle close on exec */ execsigs(p); /* reset caught signals */ TCB_SET(p, NULL); /* reset the TCB address */ pr->ps_kbind_addr = 0; /* reset the kbind bits */ pr->ps_kbind_cookie = 0; arc4random_buf(&pr->ps_sigcookie, sizeof pr->ps_sigcookie); /* set command name & other accounting info */ memset(pr->ps_comm, 0, sizeof(pr->ps_comm)); strlcpy(pr->ps_comm, nid.ni_cnd.cn_nameptr, sizeof(pr->ps_comm)); pr->ps_acflag &= ~AFORK; /* record proc's vnode, for use by sysctl */ otvp = pr->ps_textvp; vref(pack.ep_vp); pr->ps_textvp = pack.ep_vp; if (otvp) vrele(otvp); if (pack.ep_flags & EXEC_NOBTCFI) atomic_setbits_int(&p->p_p->ps_flags, PS_NOBTCFI); else atomic_clearbits_int(&p->p_p->ps_flags, PS_NOBTCFI); atomic_setbits_int(&pr->ps_flags, PS_EXEC); if (pr->ps_flags & PS_PPWAIT) { atomic_clearbits_int(&pr->ps_flags, PS_PPWAIT); atomic_clearbits_int(&pr->ps_pptr->ps_flags, PS_ISPWAIT); wakeup(pr->ps_pptr); } /* * If process does execve() while it has a mismatched real, * effective, or saved uid/gid, we set PS_SUGIDEXEC. */ if (cred->cr_uid != cred->cr_ruid || cred->cr_uid != cred->cr_svuid || cred->cr_gid != cred->cr_rgid || cred->cr_gid != cred->cr_svgid) atomic_setbits_int(&pr->ps_flags, PS_SUGIDEXEC); else atomic_clearbits_int(&pr->ps_flags, PS_SUGIDEXEC); if (pr->ps_flags & PS_EXECPLEDGE) { pr->ps_pledge = pr->ps_execpledge; atomic_setbits_int(&pr->ps_flags, PS_PLEDGE); } else { atomic_clearbits_int(&pr->ps_flags, PS_PLEDGE); pr->ps_pledge = 0; /* XXX XXX XXX XXX */ /* Clear our unveil paths out so the child * starts afresh */ unveil_destroy(pr); pr->ps_uvdone = 0; } /* * deal with set[ug]id. * MNT_NOEXEC has already been used to disable s[ug]id. */ if ((attr.va_mode & (VSUID | VSGID)) && proc_cansugid(p)) { int i; atomic_setbits_int(&pr->ps_flags, PS_SUGID|PS_SUGIDEXEC); #ifdef KTRACE /* * If process is being ktraced, turn off - unless * root set it. */ if (pr->ps_tracevp && !(pr->ps_traceflag & KTRFAC_ROOT)) ktrcleartrace(pr); #endif p->p_ucred = cred = crcopy(cred); if (attr.va_mode & VSUID) cred->cr_uid = attr.va_uid; if (attr.va_mode & VSGID) cred->cr_gid = attr.va_gid; /* * For set[ug]id processes, a few caveats apply to * stdin, stdout, and stderr. */ error = 0; fdplock(p->p_fd); for (i = 0; i < 3; i++) { struct file *fp = NULL; /* * NOTE - This will never return NULL because of * immature fds. The file descriptor table is not * shared because we're suid. */ fp = fd_getfile(p->p_fd, i); /* * Ensure that stdin, stdout, and stderr are already * allocated. We do not want userland to accidentally * allocate descriptors in this range which has implied * meaning to libc. */ if (fp == NULL) { short flags = FREAD | (i == 0 ? 0 : FWRITE); struct vnode *vp; int indx; if ((error = falloc(p, &fp, &indx)) != 0) break; #ifdef DIAGNOSTIC if (indx != i) panic("sys_execve: falloc indx != i"); #endif if ((error = cdevvp(getnulldev(), &vp)) != 0) { fdremove(p->p_fd, indx); closef(fp, p); break; } if ((error = VOP_OPEN(vp, flags, cred, p)) != 0) { fdremove(p->p_fd, indx); closef(fp, p); vrele(vp); break; } if (flags & FWRITE) vp->v_writecount++; fp->f_flag = flags; fp->f_type = DTYPE_VNODE; fp->f_ops = &vnops; fp->f_data = (caddr_t)vp; fdinsert(p->p_fd, indx, 0, fp); } FRELE(fp, p); } fdpunlock(p->p_fd); if (error) goto exec_abort; } else atomic_clearbits_int(&pr->ps_flags, PS_SUGID); /* * Reset the saved ugids and update the process's copy of the * creds if the creds have been changed */ if (cred->cr_uid != cred->cr_svuid || cred->cr_gid != cred->cr_svgid) { /* make sure we have unshared ucreds */ p->p_ucred = cred = crcopy(cred); cred->cr_svuid = cred->cr_uid; cred->cr_svgid = cred->cr_gid; } if (pr->ps_ucred != cred) { struct ucred *ocred; ocred = pr->ps_ucred; crhold(cred); pr->ps_ucred = cred; crfree(ocred); } if (pr->ps_flags & PS_SUGIDEXEC) { cancel_all_itimers(); } /* reset CPU time usage for the thread, but not the process */ timespecclear(&p->p_tu.tu_runtime); p->p_tu.tu_uticks = p->p_tu.tu_sticks = p->p_tu.tu_iticks = 0; memset(p->p_name, 0, sizeof p->p_name); km_free(argp, NCARGS, &kv_exec, &kp_pageable); pool_put(&namei_pool, nid.ni_cnd.cn_pnbuf); vn_close(pack.ep_vp, FREAD, cred, p); /* * notify others that we exec'd */ knote_locked(&pr->ps_klist, NOTE_EXEC); /* map the process's timekeep page, needs to be before exec_elf_fixup */ if (exec_timekeep_map(pr)) goto free_pack_abort; /* setup new registers and do misc. setup. */ if (exec_elf_fixup(p, &pack) != 0) goto free_pack_abort; #ifdef MACHINE_STACK_GROWS_UP setregs(p, &pack, (u_long)stack + slen, &arginfo); #else setregs(p, &pack, (u_long)stack, &arginfo); #endif /* map the process's signal trampoline code */ if (exec_sigcode_map(pr)) goto free_pack_abort; #ifdef __HAVE_EXEC_MD_MAP /* perform md specific mappings that process might need */ if (exec_md_map(p, &pack)) goto free_pack_abort; #endif if (pr->ps_flags & PS_TRACED) psignal(p, SIGTRAP); free(pack.ep_hdr, M_EXEC, pack.ep_hdrlen); p->p_descfd = 255; if ((pack.ep_flags & EXEC_HASFD) && pack.ep_fd < 255) p->p_descfd = pack.ep_fd; if (pack.ep_flags & EXEC_WXNEEDED) atomic_setbits_int(&p->p_p->ps_flags, PS_WXNEEDED); else atomic_clearbits_int(&p->p_p->ps_flags, PS_WXNEEDED); atomic_clearbits_int(&pr->ps_flags, PS_INEXEC); single_thread_clear(p, P_SUSPSIG); /* setregs() sets up all the registers, so just 'return' */ return EJUSTRETURN; bad: /* free the vmspace-creation commands, and release their references */ kill_vmcmds(&pack.ep_vmcmds); /* kill any opened file descriptor, if necessary */ if (pack.ep_flags & EXEC_HASFD) { pack.ep_flags &= ~EXEC_HASFD; fdplock(p->p_fd); /* fdrelease unlocks p->p_fd. */ (void) fdrelease(p, pack.ep_fd); } if (pack.ep_interp != NULL) pool_put(&namei_pool, pack.ep_interp); free(pack.ep_args, M_TEMP, sizeof *pack.ep_args); free(pack.ep_pins, M_PINSYSCALL, pack.ep_npins * sizeof(u_int)); /* close and put the exec'd file */ vn_close(pack.ep_vp, FREAD, cred, p); pool_put(&namei_pool, nid.ni_cnd.cn_pnbuf); km_free(argp, NCARGS, &kv_exec, &kp_pageable); freehdr: free(pack.ep_hdr, M_EXEC, pack.ep_hdrlen); atomic_clearbits_int(&pr->ps_flags, PS_INEXEC); single_thread_clear(p, P_SUSPSIG); return (error); exec_abort: /* * the old process doesn't exist anymore. exit gracefully. * get rid of the (new) address space we have created, if any, get rid * of our namei data and vnode, and exit noting failure */ uvm_unmap(&vm->vm_map, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS); if (pack.ep_interp != NULL) pool_put(&namei_pool, pack.ep_interp); free(pack.ep_args, M_TEMP, sizeof *pack.ep_args); pool_put(&namei_pool, nid.ni_cnd.cn_pnbuf); vn_close(pack.ep_vp, FREAD, cred, p); km_free(argp, NCARGS, &kv_exec, &kp_pageable); free_pack_abort: free(pack.ep_hdr, M_EXEC, pack.ep_hdrlen); exit1(p, 0, SIGABRT, EXIT_NORMAL); /* NOTREACHED */ atomic_clearbits_int(&pr->ps_flags, PS_INEXEC); return (0); } int copyargs(struct exec_package *pack, struct ps_strings *arginfo, void *stack, void *argp) { char **cpp = stack; char *dp, *sp; size_t len; void *nullp = NULL; long argc = arginfo->ps_nargvstr; int envc = arginfo->ps_nenvstr; if (copyout(&argc, cpp++, sizeof(argc))) return (0); dp = (char *) (cpp + argc + envc + 2 + ELF_AUX_WORDS); sp = argp; /* XXX don't copy them out, remap them! */ arginfo->ps_argvstr = cpp; /* remember location of argv for later */ for (; --argc >= 0; sp += len, dp += len) if (copyout(&dp, cpp++, sizeof(dp)) || copyoutstr(sp, dp, ARG_MAX, &len)) return (0); if (copyout(&nullp, cpp++, sizeof(nullp))) return (0); arginfo->ps_envstr = cpp; /* remember location of envp for later */ for (; --envc >= 0; sp += len, dp += len) if (copyout(&dp, cpp++, sizeof(dp)) || copyoutstr(sp, dp, ARG_MAX, &len)) return (0); if (copyout(&nullp, cpp++, sizeof(nullp))) return (0); /* if this process needs auxinfo, note where to place it */ if (pack->ep_args != NULL) pack->ep_auxinfo = cpp; return (1); } int exec_sigcode_map(struct process *pr) { extern char sigcode[], esigcode[], sigcoderet[]; vsize_t sz; sz = (vaddr_t)esigcode - (vaddr_t)sigcode; /* * If we don't have a sigobject yet, create one. * * sigobject is an anonymous memory object (just like SYSV shared * memory) that we keep a permanent reference to and that we map * in all processes that need this sigcode. The creation is simple, * we create an object, add a permanent reference to it, map it in * kernel space, copy out the sigcode to it and unmap it. Then we map * it with PROT_EXEC into the process just the way sys_mmap would map it. */ if (sigobject == NULL) { extern int sigfillsiz; extern u_char sigfill[]; size_t off, left; vaddr_t va; int r; sigobject = uao_create(sz, 0); uao_reference(sigobject); /* permanent reference */ if ((r = uvm_map(kernel_map, &va, round_page(sz), sigobject, 0, 0, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE, MAP_INHERIT_SHARE, MADV_RANDOM, 0)))) { uao_detach(sigobject); return (ENOMEM); } for (off = 0, left = round_page(sz); left != 0; off += sigfillsiz) { size_t chunk = ulmin(left, sigfillsiz); memcpy((caddr_t)va + off, sigfill, chunk); left -= chunk; } memcpy((caddr_t)va, sigcode, sz); (void) uvm_map_protect(kernel_map, va, round_page(sz), PROT_READ, 0, FALSE, FALSE); sigcode_va = va; sigcode_sz = round_page(sz); } pr->ps_sigcode = 0; /* no hint */ uao_reference(sigobject); if (uvm_map(&pr->ps_vmspace->vm_map, &pr->ps_sigcode, round_page(sz), sigobject, 0, 0, UVM_MAPFLAG(PROT_EXEC, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_INHERIT_COPY, MADV_RANDOM, UVM_FLAG_COPYONW))) { uao_detach(sigobject); return (ENOMEM); } uvm_map_immutable(&pr->ps_vmspace->vm_map, pr->ps_sigcode, pr->ps_sigcode + round_page(sz), 1); /* Calculate PC at point of sigreturn entry */ pr->ps_sigcoderet = pr->ps_sigcode + (sigcoderet - sigcode); return (0); } int exec_timekeep_map(struct process *pr) { size_t timekeep_sz = round_page(sizeof(struct timekeep)); /* * Similar to the sigcode object */ if (timekeep_object == NULL) { vaddr_t va = 0; timekeep_object = uao_create(timekeep_sz, 0); uao_reference(timekeep_object); if (uvm_map(kernel_map, &va, timekeep_sz, timekeep_object, 0, 0, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE, MAP_INHERIT_SHARE, MADV_RANDOM, 0))) { uao_detach(timekeep_object); timekeep_object = NULL; return (ENOMEM); } if (uvm_fault_wire(kernel_map, va, va + timekeep_sz, PROT_READ | PROT_WRITE)) { uvm_unmap(kernel_map, va, va + timekeep_sz); uao_detach(timekeep_object); timekeep_object = NULL; return (ENOMEM); } timekeep = (struct timekeep *)va; timekeep->tk_version = TK_VERSION; } pr->ps_timekeep = 0; /* no hint */ uao_reference(timekeep_object); if (uvm_map(&pr->ps_vmspace->vm_map, &pr->ps_timekeep, timekeep_sz, timekeep_object, 0, 0, UVM_MAPFLAG(PROT_READ, PROT_READ, MAP_INHERIT_COPY, MADV_RANDOM, 0))) { uao_detach(timekeep_object); return (ENOMEM); } uvm_map_immutable(&pr->ps_vmspace->vm_map, pr->ps_timekeep, pr->ps_timekeep + timekeep_sz, 1); return (0); }
28 25 44 12 32 13 31 36 227 12 8 208 2 101 93 9 93 1 74 2 44 18 45 40 4 2 42 19 42 2 1 1 2 31 6 1 33 1 3 2 5 18 17 7 6 2 2 2 2 2 1 3 44 2 27 25 1 43 42 35 35 11 3 2 29 9 15 12 9 2 6 6 3 5 16 2 16 7 16 14 4 13 5 16 2 3 13 8 6 13 8 6 13 3 19 19 19 19 19 19 19 19 1 18 16 16 13 16 9 16 16 5 13 33 33 32 26 28 28 19 5 22 87 88 33 33 9 28 72 56 28 26 67 63 57 48 77 5 91 30 17 33 66 96 13 90 90 86 35 35 34 4 96 96 43 56 96 75 96 96 96 96 89 90 28 90 54 9 67 23 8 51 1 52 8 9 28 14 36 36 90 10 89 1 8 3 7 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 /* $OpenBSD: in6.c,v 1.266 2024/05/21 15:12:25 florian Exp $ */ /* $KAME: in6.c,v 1.372 2004/06/14 08:14:21 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 1982, 1986, 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)in.c 8.2 (Berkeley) 11/15/93 */ #include "carp.h" #include <sys/param.h> #include <sys/ioctl.h> #include <sys/errno.h> #include <sys/malloc.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/sockio.h> #include <sys/mbuf.h> #include <sys/systm.h> #include <sys/time.h> #include <sys/kernel.h> #include <sys/syslog.h> #include <net/if.h> #include <net/if_dl.h> #include <net/if_types.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/if_ether.h> #include <netinet6/in6_var.h> #include <netinet/ip6.h> #include <netinet6/ip6_var.h> #include <netinet6/nd6.h> #include <netinet6/mld6_var.h> #ifdef MROUTING #include <netinet6/ip6_mroute.h> #endif #include <netinet6/in6_ifattach.h> #if NCARP > 0 #include <netinet/ip_carp.h> #endif /* * Definitions of some constant IP6 addresses. */ const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; const struct in6_addr in6addr_intfacelocal_allnodes = IN6ADDR_INTFACELOCAL_ALLNODES_INIT; const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT; const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT; const struct in6_addr in6mask0 = IN6MASK0; const struct in6_addr in6mask32 = IN6MASK32; const struct in6_addr in6mask64 = IN6MASK64; const struct in6_addr in6mask96 = IN6MASK96; const struct in6_addr in6mask128 = IN6MASK128; int in6_ioctl(u_long, caddr_t, struct ifnet *, int); int in6_ioctl_change_ifaddr(u_long, caddr_t, struct ifnet *); int in6_ioctl_get(u_long, caddr_t, struct ifnet *); int in6_check_embed_scope(struct sockaddr_in6 *, unsigned int); int in6_clear_scope_id(struct sockaddr_in6 *, unsigned int); int in6_ifinit(struct ifnet *, struct in6_ifaddr *, int); void in6_unlink_ifa(struct in6_ifaddr *, struct ifnet *); const struct sockaddr_in6 sa6_any = { sizeof(sa6_any), AF_INET6, 0, 0, IN6ADDR_ANY_INIT, 0 }; int in6_mask2len(struct in6_addr *mask, u_char *lim0) { int x = 0, y; u_char *lim = lim0, *p; /* ignore the scope_id part */ if (lim0 == NULL || lim0 - (u_char *)mask > sizeof(*mask)) lim = (u_char *)mask + sizeof(*mask); for (p = (u_char *)mask; p < lim; x++, p++) { if (*p != 0xff) break; } y = 0; if (p < lim) { for (y = 0; y < 8; y++) { if ((*p & (0x80 >> y)) == 0) break; } } /* * when the limit pointer is given, do a stricter check on the * remaining bits. */ if (p < lim) { if (y != 0 && (*p & (0x00ff >> y)) != 0) return (-1); for (p = p + 1; p < lim; p++) if (*p != 0) return (-1); } return x * 8 + y; } int in6_nam2sin6(const struct mbuf *nam, struct sockaddr_in6 **sin6) { struct sockaddr *sa = mtod(nam, struct sockaddr *); if (nam->m_len < offsetof(struct sockaddr, sa_data)) return EINVAL; if (sa->sa_family != AF_INET6) return EAFNOSUPPORT; if (sa->sa_len != nam->m_len) return EINVAL; if (sa->sa_len != sizeof(struct sockaddr_in6)) return EINVAL; *sin6 = satosin6(sa); return 0; } int in6_sa2sin6(struct sockaddr *sa, struct sockaddr_in6 **sin6) { if (sa->sa_family != AF_INET6) return EAFNOSUPPORT; if (sa->sa_len != sizeof(struct sockaddr_in6)) return EINVAL; *sin6 = satosin6(sa); return 0; } int in6_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp) { int privileged; privileged = 0; if ((so->so_state & SS_PRIV) != 0) privileged++; switch (cmd) { #ifdef MROUTING case SIOCGETSGCNT_IN6: case SIOCGETMIFCNT_IN6: return mrt6_ioctl(so, cmd, data); #endif /* MROUTING */ default: return in6_ioctl(cmd, data, ifp, privileged); } } int in6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, int privileged) { if (ifp == NULL) return (ENXIO); switch (cmd) { case SIOCGIFINFO_IN6: case SIOCGNBRINFO_IN6: return (nd6_ioctl(cmd, data, ifp)); case SIOCGIFDSTADDR_IN6: case SIOCGIFNETMASK_IN6: case SIOCGIFAFLAG_IN6: case SIOCGIFALIFETIME_IN6: return (in6_ioctl_get(cmd, data, ifp)); case SIOCAIFADDR_IN6: case SIOCDIFADDR_IN6: if (!privileged) return (EPERM); return (in6_ioctl_change_ifaddr(cmd, data, ifp)); case SIOCSIFADDR: case SIOCSIFDSTADDR: case SIOCSIFBRDADDR: case SIOCSIFNETMASK: /* * Do not pass those ioctl to driver handler since they are not * properly set up. Instead just error out. */ return (EINVAL); default: return (EOPNOTSUPP); } } int in6_ioctl_change_ifaddr(u_long cmd, caddr_t data, struct ifnet *ifp) { struct in6_ifaddr *ia6 = NULL; struct in6_aliasreq *ifra = (struct in6_aliasreq *)data; struct sockaddr *sa; struct sockaddr_in6 *sa6 = NULL; int error = 0, newifaddr = 0, plen; /* * Find address for this interface, if it exists. * * In netinet code, we have checked ifra_addr in SIOCSIF*ADDR operation * only, and used the first interface address as the target of other * operations (without checking ifra_addr). This was because netinet * code/API assumed at most 1 interface address per interface. * Since IPv6 allows a node to assign multiple addresses * on a single interface, we almost always look and check the * presence of ifra_addr, and reject invalid ones here. * It also decreases duplicated code among SIOC*_IN6 operations. * * We always require users to specify a valid IPv6 address for * the corresponding operation. */ switch (cmd) { case SIOCAIFADDR_IN6: sa = sin6tosa(&ifra->ifra_addr); break; case SIOCDIFADDR_IN6: sa = sin6tosa(&((struct in6_ifreq *)data)->ifr_addr); break; default: panic("%s: invalid ioctl %lu", __func__, cmd); } if (sa->sa_family == AF_INET6) { error = in6_sa2sin6(sa, &sa6); if (error) return (error); } KERNEL_LOCK(); NET_LOCK(); if (sa6 != NULL) { error = in6_check_embed_scope(sa6, ifp->if_index); if (error) goto err; error = in6_clear_scope_id(sa6, ifp->if_index); if (error) goto err; ia6 = in6ifa_ifpwithaddr(ifp, &sa6->sin6_addr); } switch (cmd) { case SIOCDIFADDR_IN6: /* * for IPv4, we look for existing in_ifaddr here to allow * "ifconfig if0 delete" to remove the first IPv4 address on * the interface. For IPv6, as the spec allows multiple * interface address from the day one, we consider "remove the * first one" semantics to be not preferable. */ if (ia6 == NULL) { error = EADDRNOTAVAIL; break; } in6_purgeaddr(&ia6->ia_ifa); if_addrhooks_run(ifp); break; case SIOCAIFADDR_IN6: if (ifra->ifra_addr.sin6_family != AF_INET6 || ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6)) { error = EAFNOSUPPORT; break; } /* reject read-only flags */ if ((ifra->ifra_flags & IN6_IFF_DUPLICATED) != 0 || (ifra->ifra_flags & IN6_IFF_DETACHED) != 0 || (ifra->ifra_flags & IN6_IFF_DEPRECATED) != 0) { error = EINVAL; break; } if (ia6 == NULL) newifaddr = 1; /* * Make the address tentative before joining multicast * addresses, so that corresponding MLD responses would * not have a tentative source address. */ if (newifaddr && in6if_do_dad(ifp)) ifra->ifra_flags |= IN6_IFF_TENTATIVE; /* * first, make or update the interface address structure, * and link it to the list. try to enable inet6 if there * is no link-local yet. */ error = in6_ifattach(ifp); if (error) break; error = in6_update_ifa(ifp, ifra, ia6); if (error) break; ia6 = NULL; if (sa6 != NULL) ia6 = in6ifa_ifpwithaddr(ifp, &sa6->sin6_addr); if (ia6 == NULL) { /* * this can happen when the user specify the 0 valid * lifetime. */ break; } /* Perform DAD, if needed. */ if (ia6->ia6_flags & IN6_IFF_TENTATIVE) nd6_dad_start(&ia6->ia_ifa); if (!newifaddr) { if_addrhooks_run(ifp); break; } plen = in6_mask2len(&ia6->ia_prefixmask.sin6_addr, NULL); if ((ifp->if_flags & IFF_LOOPBACK) || plen == 128) { if_addrhooks_run(ifp); break; /* No need to install a connected route. */ } error = rt_ifa_add(&ia6->ia_ifa, RTF_CLONING | RTF_CONNECTED | RTF_MPATH, ia6->ia_ifa.ifa_addr, ifp->if_rdomain); if (error) { in6_purgeaddr(&ia6->ia_ifa); break; } if_addrhooks_run(ifp); break; } err: NET_UNLOCK(); KERNEL_UNLOCK(); return (error); } int in6_ioctl_get(u_long cmd, caddr_t data, struct ifnet *ifp) { struct in6_ifreq *ifr = (struct in6_ifreq *)data; struct in6_ifaddr *ia6 = NULL; struct sockaddr *sa; struct sockaddr_in6 *sa6 = NULL; int error = 0; sa = sin6tosa(&ifr->ifr_addr); if (sa->sa_family == AF_INET6) { sa->sa_len = sizeof(struct sockaddr_in6); error = in6_sa2sin6(sa, &sa6); if (error) return (error); } NET_LOCK_SHARED(); if (sa6 != NULL) { error = in6_check_embed_scope(sa6, ifp->if_index); if (error) goto err; error = in6_clear_scope_id(sa6, ifp->if_index); if (error) goto err; ia6 = in6ifa_ifpwithaddr(ifp, &sa6->sin6_addr); } /* must think again about its semantics */ if (ia6 == NULL) { error = EADDRNOTAVAIL; goto err; } switch (cmd) { case SIOCGIFDSTADDR_IN6: if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { error = EINVAL; break; } /* * XXX: should we check if ifa_dstaddr is NULL and return * an error? */ ifr->ifr_dstaddr = ia6->ia_dstaddr; break; case SIOCGIFNETMASK_IN6: ifr->ifr_addr = ia6->ia_prefixmask; break; case SIOCGIFAFLAG_IN6: ifr->ifr_ifru.ifru_flags6 = ia6->ia6_flags; break; case SIOCGIFALIFETIME_IN6: ifr->ifr_ifru.ifru_lifetime = ia6->ia6_lifetime; if (ia6->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) { time_t expire, maxexpire; struct in6_addrlifetime *retlt = &ifr->ifr_ifru.ifru_lifetime; /* * XXX: adjust expiration time assuming time_t is * signed. */ maxexpire = (time_t)~(1ULL << ((sizeof(maxexpire) * 8) - 1)); if (ia6->ia6_lifetime.ia6t_vltime < maxexpire - ia6->ia6_updatetime) { expire = ia6->ia6_updatetime + ia6->ia6_lifetime.ia6t_vltime; if (expire != 0) { expire -= getuptime(); expire += gettime(); } retlt->ia6t_expire = expire; } else retlt->ia6t_expire = maxexpire; } if (ia6->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) { time_t expire, maxexpire; struct in6_addrlifetime *retlt = &ifr->ifr_ifru.ifru_lifetime; /* * XXX: adjust expiration time assuming time_t is * signed. */ maxexpire = (time_t)~(1ULL << ((sizeof(maxexpire) * 8) - 1)); if (ia6->ia6_lifetime.ia6t_pltime < maxexpire - ia6->ia6_updatetime) { expire = ia6->ia6_updatetime + ia6->ia6_lifetime.ia6t_pltime; if (expire != 0) { expire -= getuptime(); expire += gettime(); } retlt->ia6t_preferred = expire; } else retlt->ia6t_preferred = maxexpire; } break; default: panic("%s: invalid ioctl %lu", __func__, cmd); } err: NET_UNLOCK_SHARED(); return (error); } int in6_check_embed_scope(struct sockaddr_in6 *sa6, unsigned int ifidx) { if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) { if (sa6->sin6_addr.s6_addr16[1] == 0) { /* link ID is not embedded by the user */ sa6->sin6_addr.s6_addr16[1] = htons(ifidx); } else if (sa6->sin6_addr.s6_addr16[1] != htons(ifidx)) return EINVAL; /* link ID contradicts */ } return 0; } int in6_clear_scope_id(struct sockaddr_in6 *sa6, unsigned int ifidx) { if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) { if (sa6->sin6_scope_id) { if (sa6->sin6_scope_id != (u_int32_t)ifidx) return EINVAL; sa6->sin6_scope_id = 0; /* XXX: good way? */ } } return 0; } /* * Update parameters of an IPv6 interface address. * If necessary, a new entry is created and linked into address chains. * This function is separated from in6_control(). */ int in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra, struct in6_ifaddr *ia6) { int error = 0, hostIsNew = 0, plen = -1; struct sockaddr_in6 dst6; struct in6_addrlifetime *lt; struct in6_multi_mship *imm; struct rtentry *rt; char addr[INET6_ADDRSTRLEN]; NET_ASSERT_LOCKED(); /* Validate parameters */ if (ifp == NULL || ifra == NULL) /* this maybe redundant */ return (EINVAL); /* * The destination address for a p2p link or the address of the * announcing router for an autoconf address must have a family of * AF_UNSPEC or AF_INET6. */ if ((ifp->if_flags & IFF_POINTOPOINT) || (ifp->if_flags & IFF_LOOPBACK) || (ifra->ifra_flags & IN6_IFF_AUTOCONF)) { if (ifra->ifra_dstaddr.sin6_family != AF_INET6 && ifra->ifra_dstaddr.sin6_family != AF_UNSPEC) return (EAFNOSUPPORT); } else if (ifra->ifra_dstaddr.sin6_family != AF_UNSPEC) return (EINVAL); /* * validate ifra_prefixmask. don't check sin6_family, netmask * does not carry fields other than sin6_len. */ if (ifra->ifra_prefixmask.sin6_len > sizeof(struct sockaddr_in6)) return (EINVAL); /* * Because the IPv6 address architecture is classless, we require * users to specify a (non 0) prefix length (mask) for a new address. * We also require the prefix (when specified) mask is valid, and thus * reject a non-consecutive mask. */ if (ia6 == NULL && ifra->ifra_prefixmask.sin6_len == 0) return (EINVAL); if (ifra->ifra_prefixmask.sin6_len != 0) { plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr, (u_char *)&ifra->ifra_prefixmask + ifra->ifra_prefixmask.sin6_len); if (plen <= 0) return (EINVAL); } else { /* * In this case, ia6 must not be NULL. We just use its prefix * length. */ plen = in6_mask2len(&ia6->ia_prefixmask.sin6_addr, NULL); } dst6 = ifra->ifra_dstaddr; if (dst6.sin6_family == AF_INET6) { error = in6_check_embed_scope(&dst6, ifp->if_index); if (error) return error; if (((ifp->if_flags & IFF_POINTOPOINT) || (ifp->if_flags & IFF_LOOPBACK)) && plen != 128) return (EINVAL); } /* lifetime consistency check */ lt = &ifra->ifra_lifetime; if (lt->ia6t_pltime > lt->ia6t_vltime) return (EINVAL); if (lt->ia6t_vltime == 0) { /* * the following log might be noisy, but this is a typical * configuration mistake or a tool's bug. */ nd6log((LOG_INFO, "%s: valid lifetime is 0 for %s\n", __func__, inet_ntop(AF_INET6, &ifra->ifra_addr.sin6_addr, addr, sizeof(addr)))); if (ia6 == NULL) return (0); /* there's nothing to do */ } /* * If this is a new address, allocate a new ifaddr and link it * into chains. */ if (ia6 == NULL) { hostIsNew = 1; ia6 = malloc(sizeof(*ia6), M_IFADDR, M_WAITOK | M_ZERO); refcnt_init_trace(&ia6->ia_ifa.ifa_refcnt, DT_REFCNT_IDX_IFADDR); LIST_INIT(&ia6->ia6_memberships); /* Initialize the address and masks, and put time stamp */ ia6->ia_ifa.ifa_addr = sin6tosa(&ia6->ia_addr); ia6->ia_addr.sin6_family = AF_INET6; ia6->ia_addr.sin6_len = sizeof(ia6->ia_addr); ia6->ia6_updatetime = getuptime(); if ((ifp->if_flags & IFF_POINTOPOINT) || (ifp->if_flags & IFF_LOOPBACK)) { /* * XXX: some functions expect that ifa_dstaddr is not * NULL for p2p interfaces. */ ia6->ia_ifa.ifa_dstaddr = sin6tosa(&ia6->ia_dstaddr); } else { ia6->ia_ifa.ifa_dstaddr = NULL; } ia6->ia_ifa.ifa_netmask = sin6tosa(&ia6->ia_prefixmask); ia6->ia_ifp = ifp; ia6->ia_addr = ifra->ifra_addr; ifa_add(ifp, &ia6->ia_ifa); } /* set prefix mask */ if (ifra->ifra_prefixmask.sin6_len) { /* * We prohibit changing the prefix length of an existing * address, because * + such an operation should be rare in IPv6, and * + the operation would confuse prefix management. */ if (ia6->ia_prefixmask.sin6_len && in6_mask2len(&ia6->ia_prefixmask.sin6_addr, NULL) != plen) { error = EINVAL; goto unlink; } ia6->ia_prefixmask = ifra->ifra_prefixmask; } /* * If a new destination address is specified, scrub the old one and * install the new destination. */ if (((ifp->if_flags & IFF_POINTOPOINT) || (ifp->if_flags & IFF_LOOPBACK)) && dst6.sin6_family == AF_INET6 && !IN6_ARE_ADDR_EQUAL(&dst6.sin6_addr, &ia6->ia_dstaddr.sin6_addr)) { struct ifaddr *ifa = &ia6->ia_ifa; if ((ia6->ia_flags & IFA_ROUTE) != 0 && rt_ifa_del(ifa, RTF_HOST, ifa->ifa_dstaddr, ifp->if_rdomain) != 0) { nd6log((LOG_ERR, "%s: failed to remove a route " "to the old destination: %s\n", __func__, inet_ntop(AF_INET6, &ia6->ia_addr.sin6_addr, addr, sizeof(addr)))); /* proceed anyway... */ } else ia6->ia_flags &= ~IFA_ROUTE; ia6->ia_dstaddr = dst6; } if ((ifra->ifra_flags & IN6_IFF_AUTOCONF) && dst6.sin6_family == AF_INET6 && !IN6_ARE_ADDR_EQUAL(&dst6.sin6_addr, &ia6->ia_gwaddr.sin6_addr)) { /* Set or update announcing router */ ia6->ia_gwaddr = dst6; } /* * Set lifetimes. We do not refer to ia6t_expire and ia6t_preferred * to see if the address is deprecated or invalidated, but initialize * these members for applications. */ ia6->ia6_updatetime = getuptime(); ia6->ia6_lifetime = ifra->ifra_lifetime; if (ia6->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) { ia6->ia6_lifetime.ia6t_expire = getuptime() + ia6->ia6_lifetime.ia6t_vltime; } else ia6->ia6_lifetime.ia6t_expire = 0; if (ia6->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) { ia6->ia6_lifetime.ia6t_preferred = getuptime() + ia6->ia6_lifetime.ia6t_pltime; } else ia6->ia6_lifetime.ia6t_preferred = 0; /* reset the interface and routing table appropriately. */ if ((error = in6_ifinit(ifp, ia6, hostIsNew)) != 0) goto unlink; /* re-run DAD */ if (ia6->ia6_flags & (IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED)) ifra->ifra_flags |= IN6_IFF_TENTATIVE; /* * configure address flags. */ ia6->ia6_flags = ifra->ifra_flags; nd6_expire_timer_update(ia6); /* * We are done if we have simply modified an existing address. */ if (!hostIsNew) { /* DAD sends RTM_CHGADDRATTR when done. */ if (!(ia6->ia6_flags & IN6_IFF_TENTATIVE)) rtm_addr(RTM_CHGADDRATTR, &ia6->ia_ifa); return (error); } /* * Beyond this point, we should call in6_purgeaddr upon an error, * not just go to unlink. */ /* join necessary multiast groups */ if ((ifp->if_flags & IFF_MULTICAST) != 0) { struct sockaddr_in6 mltaddr, mltmask; /* join solicited multicast addr for new host id */ struct sockaddr_in6 llsol; bzero(&llsol, sizeof(llsol)); llsol.sin6_family = AF_INET6; llsol.sin6_len = sizeof(llsol); llsol.sin6_addr.s6_addr16[0] = htons(0xff02); llsol.sin6_addr.s6_addr16[1] = htons(ifp->if_index); llsol.sin6_addr.s6_addr32[1] = 0; llsol.sin6_addr.s6_addr32[2] = htonl(1); llsol.sin6_addr.s6_addr32[3] = ifra->ifra_addr.sin6_addr.s6_addr32[3]; llsol.sin6_addr.s6_addr8[12] = 0xff; imm = in6_joingroup(ifp, &llsol.sin6_addr, &error); if (!imm) goto cleanup; LIST_INSERT_HEAD(&ia6->ia6_memberships, imm, i6mm_chain); bzero(&mltmask, sizeof(mltmask)); mltmask.sin6_len = sizeof(struct sockaddr_in6); mltmask.sin6_family = AF_INET6; mltmask.sin6_addr = in6mask32; /* * join link-local all-nodes address */ bzero(&mltaddr, sizeof(mltaddr)); mltaddr.sin6_len = sizeof(struct sockaddr_in6); mltaddr.sin6_family = AF_INET6; mltaddr.sin6_addr = in6addr_linklocal_allnodes; mltaddr.sin6_addr.s6_addr16[1] = htons(ifp->if_index); mltaddr.sin6_scope_id = 0; /* * XXX: do we really need this automatic routes? * We should probably reconsider this stuff. Most applications * actually do not need the routes, since they usually specify * the outgoing interface. */ rt = rtalloc(sin6tosa(&mltaddr), 0, ifp->if_rdomain); if (rt) { /* 32bit came from "mltmask" */ if (memcmp(&mltaddr.sin6_addr, &satosin6(rt_key(rt))->sin6_addr, 32 / 8)) { rtfree(rt); rt = NULL; } } if (!rt) { struct rt_addrinfo info; bzero(&info, sizeof(info)); info.rti_ifa = &ia6->ia_ifa; info.rti_info[RTAX_DST] = sin6tosa(&mltaddr); info.rti_info[RTAX_GATEWAY] = sin6tosa(&ia6->ia_addr); info.rti_info[RTAX_NETMASK] = sin6tosa(&mltmask); info.rti_info[RTAX_IFA] = sin6tosa(&ia6->ia_addr); info.rti_flags = RTF_MULTICAST; error = rtrequest(RTM_ADD, &info, RTP_CONNECTED, NULL, ifp->if_rdomain); if (error) goto cleanup; } else { rtfree(rt); } imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error); if (!imm) goto cleanup; LIST_INSERT_HEAD(&ia6->ia6_memberships, imm, i6mm_chain); /* * join interface-local all-nodes address. * (ff01::1%ifN, and ff01::%ifN/32) */ bzero(&mltaddr, sizeof(mltaddr)); mltaddr.sin6_len = sizeof(struct sockaddr_in6); mltaddr.sin6_family = AF_INET6; mltaddr.sin6_addr = in6addr_intfacelocal_allnodes; mltaddr.sin6_addr.s6_addr16[1] = htons(ifp->if_index); mltaddr.sin6_scope_id = 0; /* XXX: again, do we really need the route? */ rt = rtalloc(sin6tosa(&mltaddr), 0, ifp->if_rdomain); if (rt) { /* 32bit came from "mltmask" */ if (memcmp(&mltaddr.sin6_addr, &satosin6(rt_key(rt))->sin6_addr, 32 / 8)) { rtfree(rt); rt = NULL; } } if (!rt) { struct rt_addrinfo info; bzero(&info, sizeof(info)); info.rti_ifa = &ia6->ia_ifa; info.rti_info[RTAX_DST] = sin6tosa(&mltaddr); info.rti_info[RTAX_GATEWAY] = sin6tosa(&ia6->ia_addr); info.rti_info[RTAX_NETMASK] = sin6tosa(&mltmask); info.rti_info[RTAX_IFA] = sin6tosa(&ia6->ia_addr); info.rti_flags = RTF_MULTICAST; error = rtrequest(RTM_ADD, &info, RTP_CONNECTED, NULL, ifp->if_rdomain); if (error) goto cleanup; } else { rtfree(rt); } imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error); if (!imm) goto cleanup; LIST_INSERT_HEAD(&ia6->ia6_memberships, imm, i6mm_chain); } return (error); unlink: /* * XXX: if a change of an existing address failed, keep the entry * anyway. */ if (hostIsNew) in6_unlink_ifa(ia6, ifp); return (error); cleanup: in6_purgeaddr(&ia6->ia_ifa); return error; } void in6_purgeaddr(struct ifaddr *ifa) { struct ifnet *ifp = ifa->ifa_ifp; struct in6_ifaddr *ia6 = ifatoia6(ifa); struct in6_multi_mship *imm; /* stop DAD processing */ nd6_dad_stop(ifa); /* * delete route to the destination of the address being purged. * The interface must be p2p or loopback in this case. */ if ((ifp->if_flags & IFF_POINTOPOINT) && (ia6->ia_flags & IFA_ROUTE) && ia6->ia_dstaddr.sin6_len != 0) { int e; e = rt_ifa_del(ifa, RTF_HOST, ifa->ifa_dstaddr, ifp->if_rdomain); if (e != 0) { char addr[INET6_ADDRSTRLEN]; log(LOG_ERR, "in6_purgeaddr: failed to remove " "a route to the p2p destination: %s on %s, " "errno=%d\n", inet_ntop(AF_INET6, &ia6->ia_addr.sin6_addr, addr, sizeof(addr)), ifp->if_xname, e); /* proceed anyway... */ } else ia6->ia_flags &= ~IFA_ROUTE; } /* Remove ownaddr's loopback rtentry, if it exists. */ rt_ifa_dellocal(&(ia6->ia_ifa)); /* * leave from multicast groups we have joined for the interface */ while (!LIST_EMPTY(&ia6->ia6_memberships)) { imm = LIST_FIRST(&ia6->ia6_memberships); LIST_REMOVE(imm, i6mm_chain); in6_leavegroup(imm); } in6_unlink_ifa(ia6, ifp); } void in6_unlink_ifa(struct in6_ifaddr *ia6, struct ifnet *ifp) { struct ifaddr *ifa = &ia6->ia_ifa; int plen; NET_ASSERT_LOCKED(); /* Release the reference to the base prefix. */ plen = in6_mask2len(&ia6->ia_prefixmask.sin6_addr, NULL); if ((ifp->if_flags & IFF_LOOPBACK) == 0 && plen != 128) { rt_ifa_del(ifa, RTF_CLONING | RTF_CONNECTED, ifa->ifa_addr, ifp->if_rdomain); } rt_ifa_purge(ifa); ifa_del(ifp, ifa); ia6->ia_ifp = NULL; ifafree(ifa); } /* * Initialize an interface's inet6 address * and routing table entry. */ int in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia6, int newhost) { int error = 0, plen, ifacount = 0; struct ifaddr *ifa; NET_ASSERT_LOCKED(); /* * Give the interface a chance to initialize * if this is its first address (or it is a CARP interface) * and to validate the address if necessary. */ TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; ifacount++; } if ((ifacount <= 1 || ifp->if_type == IFT_CARP || (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))) && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia6))) { return (error); } ia6->ia_ifa.ifa_metric = ifp->if_metric; /* we could do in(6)_socktrim here, but just omit it at this moment. */ /* * Special case: * If the destination address is specified for a point-to-point * interface, install a route to the destination as an interface * direct route. */ plen = in6_mask2len(&ia6->ia_prefixmask.sin6_addr, NULL); /* XXX */ if ((ifp->if_flags & IFF_POINTOPOINT) && plen == 128 && ia6->ia_dstaddr.sin6_family == AF_INET6) { ifa = &ia6->ia_ifa; error = rt_ifa_add(ifa, RTF_HOST | RTF_MPATH, ifa->ifa_dstaddr, ifp->if_rdomain); if (error != 0) return (error); ia6->ia_flags |= IFA_ROUTE; } if (newhost) error = rt_ifa_addlocal(&(ia6->ia_ifa)); return (error); } /* * Add an address to the list of IP6 multicast addresses for a * given interface. */ struct in6_multi * in6_addmulti(struct in6_addr *maddr6, struct ifnet *ifp, int *errorp) { struct in6_ifreq ifr; struct in6_multi *in6m; NET_ASSERT_LOCKED(); *errorp = 0; /* * See if address already in list. */ IN6_LOOKUP_MULTI(*maddr6, ifp, in6m); if (in6m != NULL) { /* * Found it; just increment the reference count. */ refcnt_take(&in6m->in6m_refcnt); } else { /* * New address; allocate a new multicast record * and link it into the interface's multicast list. */ in6m = malloc(sizeof(*in6m), M_IPMADDR, M_NOWAIT | M_ZERO); if (in6m == NULL) { *errorp = ENOBUFS; return (NULL); } in6m->in6m_sin.sin6_len = sizeof(struct sockaddr_in6); in6m->in6m_sin.sin6_family = AF_INET6; in6m->in6m_sin.sin6_addr = *maddr6; refcnt_init_trace(&in6m->in6m_refcnt, DT_REFCNT_IDX_IFMADDR); in6m->in6m_ifidx = ifp->if_index; in6m->in6m_ifma.ifma_addr = sin6tosa(&in6m->in6m_sin); /* * Ask the network driver to update its multicast reception * filter appropriately for the new address. */ memcpy(&ifr.ifr_addr, &in6m->in6m_sin, sizeof(in6m->in6m_sin)); KERNEL_LOCK(); *errorp = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr); KERNEL_UNLOCK(); if (*errorp) { free(in6m, M_IPMADDR, sizeof(*in6m)); return (NULL); } TAILQ_INSERT_HEAD(&ifp->if_maddrlist, &in6m->in6m_ifma, ifma_list); /* * Let MLD6 know that we have joined a new IP6 multicast * group. */ mld6_start_listening(in6m); } return (in6m); } /* * Delete a multicast address record. */ void in6_delmulti(struct in6_multi *in6m) { struct in6_ifreq ifr; struct ifnet *ifp; NET_ASSERT_LOCKED(); if (refcnt_rele(&in6m->in6m_refcnt) != 0) { /* * No remaining claims to this record; let MLD6 know * that we are leaving the multicast group. */ mld6_stop_listening(in6m); ifp = if_get(in6m->in6m_ifidx); /* * Notify the network driver to update its multicast * reception filter. */ if (ifp != NULL) { bzero(&ifr.ifr_addr, sizeof(struct sockaddr_in6)); ifr.ifr_addr.sin6_len = sizeof(struct sockaddr_in6); ifr.ifr_addr.sin6_family = AF_INET6; ifr.ifr_addr.sin6_addr = in6m->in6m_addr; KERNEL_LOCK(); (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr); KERNEL_UNLOCK(); TAILQ_REMOVE(&ifp->if_maddrlist, &in6m->in6m_ifma, ifma_list); } if_put(ifp); free(in6m, M_IPMADDR, sizeof(*in6m)); } } /* * Return 1 if the multicast group represented by ``maddr6'' has been * joined by interface ``ifp'', 0 otherwise. */ int in6_hasmulti(struct in6_addr *maddr6, struct ifnet *ifp) { struct in6_multi *in6m; int joined; IN6_LOOKUP_MULTI(*maddr6, ifp, in6m); joined = (in6m != NULL); return (joined); } struct in6_multi_mship * in6_joingroup(struct ifnet *ifp, struct in6_addr *addr, int *errorp) { struct in6_multi_mship *imm; imm = malloc(sizeof(*imm), M_IPMADDR, M_NOWAIT); if (!imm) { *errorp = ENOBUFS; return NULL; } imm->i6mm_maddr = in6_addmulti(addr, ifp, errorp); if (!imm->i6mm_maddr) { /* *errorp is already set */ free(imm, M_IPMADDR, sizeof(*imm)); return NULL; } return imm; } void in6_leavegroup(struct in6_multi_mship *imm) { if (imm->i6mm_maddr) in6_delmulti(imm->i6mm_maddr); free(imm, M_IPMADDR, sizeof(*imm)); } /* * Find an IPv6 interface link-local address specific to an interface. */ struct in6_ifaddr * in6ifa_ifpforlinklocal(struct ifnet *ifp, int ignoreflags) { struct ifaddr *ifa; TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa))) { if ((ifatoia6(ifa)->ia6_flags & ignoreflags) != 0) continue; break; } } return (ifatoia6(ifa)); } /* * find the internet address corresponding to a given interface and address. */ struct in6_ifaddr * in6ifa_ifpwithaddr(struct ifnet *ifp, struct in6_addr *addr) { struct ifaddr *ifa; TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa))) break; } return (ifatoia6(ifa)); } /* * Get a scope of the address. Node-local, link-local, site-local or global. */ int in6_addrscope(struct in6_addr *addr) { int scope; if (addr->s6_addr8[0] == 0xfe) { scope = addr->s6_addr8[1] & 0xc0; switch (scope) { case 0x80: return __IPV6_ADDR_SCOPE_LINKLOCAL; break; case 0xc0: return __IPV6_ADDR_SCOPE_SITELOCAL; break; default: return __IPV6_ADDR_SCOPE_GLOBAL; /* just in case */ break; } } if (addr->s6_addr8[0] == 0xff) { scope = addr->s6_addr8[1] & 0x0f; /* * due to other scope such as reserved, * return scope doesn't work. */ switch (scope) { case __IPV6_ADDR_SCOPE_INTFACELOCAL: return __IPV6_ADDR_SCOPE_INTFACELOCAL; break; case __IPV6_ADDR_SCOPE_LINKLOCAL: return __IPV6_ADDR_SCOPE_LINKLOCAL; break; case __IPV6_ADDR_SCOPE_SITELOCAL: return __IPV6_ADDR_SCOPE_SITELOCAL; break; default: return __IPV6_ADDR_SCOPE_GLOBAL; break; } } if (bcmp(&in6addr_loopback, addr, sizeof(*addr) - 1) == 0) { if (addr->s6_addr8[15] == 1) /* loopback */ return __IPV6_ADDR_SCOPE_INTFACELOCAL; if (addr->s6_addr8[15] == 0) /* unspecified */ return __IPV6_ADDR_SCOPE_LINKLOCAL; } return __IPV6_ADDR_SCOPE_GLOBAL; } int in6_addr2scopeid(unsigned int ifidx, struct in6_addr *addr) { int scope = in6_addrscope(addr); switch(scope) { case __IPV6_ADDR_SCOPE_INTFACELOCAL: case __IPV6_ADDR_SCOPE_LINKLOCAL: /* XXX: we do not distinguish between a link and an I/F. */ return (ifidx); case __IPV6_ADDR_SCOPE_SITELOCAL: return (0); /* XXX: invalid. */ default: return (0); /* XXX: treat as global. */ } } /* * return length of part which dst and src are equal * hard coding... */ int in6_matchlen(struct in6_addr *src, struct in6_addr *dst) { int match = 0; u_char *s = (u_char *)src, *d = (u_char *)dst; u_char *lim = s + 16, r; while (s < lim) if ((r = (*d++ ^ *s++)) != 0) { while (r < 128) { match++; r <<= 1; } break; } else match += 8; return match; } void in6_prefixlen2mask(struct in6_addr *maskp, int len) { u_char maskarray[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; int bytelen, bitlen, i; /* sanity check */ if (0 > len || len > 128) { log(LOG_ERR, "in6_prefixlen2mask: invalid prefix length(%d)\n", len); return; } bzero(maskp, sizeof(*maskp)); bytelen = len / 8; bitlen = len % 8; for (i = 0; i < bytelen; i++) maskp->s6_addr[i] = 0xff; /* len == 128 is ok because bitlen == 0 then */ if (bitlen) maskp->s6_addr[bytelen] = maskarray[bitlen - 1]; } /* * return the best address out of the same scope */ struct in6_ifaddr * in6_ifawithscope(struct ifnet *oifp, struct in6_addr *dst, u_int rdomain, struct rtentry *rt) { int dst_scope = in6_addrscope(dst), src_scope, best_scope = 0; int blen = -1; struct ifaddr *ifa; struct ifnet *ifp; struct in6_ifaddr *ia6_best = NULL; struct in6_addr *gw6 = NULL; if (rt) { if (rt->rt_gateway != NULL && rt->rt_gateway->sa_family == AF_INET6) gw6 = &(satosin6(rt->rt_gateway)->sin6_addr); } if (oifp == NULL) { printf("%s: output interface is not specified\n", __func__); return (NULL); } /* We search for all addresses on all interfaces from the beginning. */ TAILQ_FOREACH(ifp, &ifnetlist, if_list) { if (ifp->if_rdomain != rdomain) continue; #if NCARP > 0 /* * Never use a carp address of an interface which is not * the master. */ if (ifp->if_type == IFT_CARP && !carp_iamatch(ifp)) continue; #endif /* * We can never take an address that breaks the scope zone * of the destination. */ if (in6_addr2scopeid(ifp->if_index, dst) != in6_addr2scopeid(oifp->if_index, dst)) continue; TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { int tlen = -1; if (ifa->ifa_addr->sa_family != AF_INET6) continue; src_scope = in6_addrscope(IFA_IN6(ifa)); /* * Don't use an address before completing DAD * nor a duplicated address. */ if (ifatoia6(ifa)->ia6_flags & (IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED)) continue; /* * RFC 6724 allows anycast addresses as source address * because the restriction was removed in RFC 4291. * However RFC 4443 states that ICMPv6 responses * MUST use a unicast source address. * * XXX Skip anycast addresses for now since * icmp6_reflect() uses this function for source * address selection. */ if (ifatoia6(ifa)->ia6_flags & IN6_IFF_ANYCAST) continue; if (ifatoia6(ifa)->ia6_flags & IN6_IFF_DETACHED) continue; /* * If this is the first address we find, * keep it anyway. */ if (ia6_best == NULL) goto replace; /* * ia6_best is never NULL beyond this line except * within the block labeled "replace". */ /* * Rule 2: Prefer appropriate scope. * Find the address with the smallest scope that is * bigger (or equal) to the scope of the destination * address. * Accept an address with smaller scope than the * destination if non exists with bigger scope. */ if (best_scope < src_scope) { if (best_scope < dst_scope) goto replace; else continue; } else if (src_scope < best_scope) { if (src_scope < dst_scope) continue; else goto replace; } /* Rule 3: Avoid deprecated addresses. */ if (ifatoia6(ifa)->ia6_flags & IN6_IFF_DEPRECATED) { /* * Ignore any deprecated addresses if * specified by configuration. */ if (!ip6_use_deprecated) continue; /* * If we have already found a non-deprecated * candidate, just ignore deprecated addresses. */ if ((ia6_best->ia6_flags & IN6_IFF_DEPRECATED) == 0) continue; } else if ((ia6_best->ia6_flags & IN6_IFF_DEPRECATED)) goto replace; /* * Rule 4: Prefer home addresses. * We do not support home addresses. */ /* Rule 5: Prefer outgoing interface */ if (ia6_best->ia_ifp == oifp && ifp != oifp) continue; if (ia6_best->ia_ifp != oifp && ifp == oifp) goto replace; /* * Rule 5.5: Prefer addresses in a prefix advertised * by the next-hop. */ if (gw6) { struct in6_addr *in6_bestgw, *in6_newgw; in6_bestgw = &ia6_best->ia_gwaddr.sin6_addr; in6_newgw = &ifatoia6(ifa)->ia_gwaddr.sin6_addr; if (!IN6_ARE_ADDR_EQUAL(in6_bestgw, gw6) && IN6_ARE_ADDR_EQUAL(in6_newgw, gw6)) goto replace; } /* * Rule 6: Prefer matching label. * We do not implement policy tables. */ /* Rule 7: Prefer temporary addresses. */ if ((ia6_best->ia6_flags & IN6_IFF_TEMPORARY) && !(ifatoia6(ifa)->ia6_flags & IN6_IFF_TEMPORARY)) continue; if (!(ia6_best->ia6_flags & IN6_IFF_TEMPORARY) && (ifatoia6(ifa)->ia6_flags & IN6_IFF_TEMPORARY)) goto replace; /* Rule 8: Use longest matching prefix. */ tlen = in6_matchlen(IFA_IN6(ifa), dst); if (tlen > blen) { #if NCARP > 0 /* * Don't let carp interfaces win a tie against * the output interface based on matchlen. * We should only use a carp address if no * other interface has a usable address. * Otherwise, when communicating from a carp * master to a carp backup, the backup system * won't respond since the carp address is also * configured as a local address on the backup. * Note that carp interfaces in backup state * were already skipped above. */ if (ifp->if_type == IFT_CARP && oifp->if_type != IFT_CARP) continue; #endif goto replace; } else if (tlen < blen) continue; /* * If the eight rules fail to choose a single address, * the tiebreaker is implementation-specific. */ /* Prefer address with highest pltime. */ if (ia6_best->ia6_updatetime + ia6_best->ia6_lifetime.ia6t_pltime < ifatoia6(ifa)->ia6_updatetime + ifatoia6(ifa)->ia6_lifetime.ia6t_pltime) goto replace; else if (ia6_best->ia6_updatetime + ia6_best->ia6_lifetime.ia6t_pltime > ifatoia6(ifa)->ia6_updatetime + ifatoia6(ifa)->ia6_lifetime.ia6t_pltime) continue; /* Prefer address with highest vltime. */ if (ia6_best->ia6_updatetime + ia6_best->ia6_lifetime.ia6t_vltime < ifatoia6(ifa)->ia6_updatetime + ifatoia6(ifa)->ia6_lifetime.ia6t_vltime) goto replace; else if (ia6_best->ia6_updatetime + ia6_best->ia6_lifetime.ia6t_vltime > ifatoia6(ifa)->ia6_updatetime + ifatoia6(ifa)->ia6_lifetime.ia6t_vltime) continue; continue; replace: ia6_best = ifatoia6(ifa); blen = tlen >= 0 ? tlen : in6_matchlen(IFA_IN6(ifa), dst); best_scope = in6_addrscope(&ia6_best->ia_addr.sin6_addr); } } /* count statistics for future improvements */ if (ia6_best == NULL) ip6stat_inc(ip6s_sources_none); else { if (oifp == ia6_best->ia_ifp) ip6stat_inc(ip6s_sources_sameif + best_scope); else ip6stat_inc(ip6s_sources_otherif + best_scope); if (best_scope == dst_scope) ip6stat_inc(ip6s_sources_samescope + best_scope); else ip6stat_inc(ip6s_sources_otherscope + best_scope); if ((ia6_best->ia6_flags & IN6_IFF_DEPRECATED) != 0) ip6stat_inc(ip6s_sources_deprecated + best_scope); } return (ia6_best); } int in6if_do_dad(struct ifnet *ifp) { if ((ifp->if_flags & IFF_LOOPBACK) != 0) return (0); switch (ifp->if_type) { #if NCARP > 0 case IFT_CARP: /* * XXX: DAD does not work currently on carp(4) * so disable it for now. */ return (0); #endif default: /* * Our DAD routine requires the interface up and running. * However, some interfaces can be up before the RUNNING * status. Additionally, users may try to assign addresses * before the interface becomes up (or running). * We simply skip DAD in such a case as a work around. * XXX: we should rather mark "tentative" on such addresses, * and do DAD after the interface becomes ready. */ if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) return (0); return (1); } }
1164 1162 156 156 123 64 1173 1174 94 123 1164 1164 1167 1166 76 76 2 75 1 75 2 75 94 94 93 23 90 122 121 122 75 75 75 75 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 /* $OpenBSD: vfs_biomem.c,v 1.51 2021/10/24 00:02:25 jsg Exp $ */ /* * Copyright (c) 2007 Artur Grabowski <art@openbsd.org> * Copyright (c) 2012-2016,2019 Bob Beck <beck@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/buf.h> #include <sys/pool.h> #include <sys/proc.h> /* XXX for atomic */ #include <sys/mount.h> #include <uvm/uvm_extern.h> vaddr_t buf_kva_start, buf_kva_end; int buf_needva; TAILQ_HEAD(,buf) buf_valist; extern struct bcachestats bcstats; vaddr_t buf_unmap(struct buf *); void buf_mem_init(vsize_t size) { TAILQ_INIT(&buf_valist); buf_kva_start = vm_map_min(kernel_map); if (uvm_map(kernel_map, &buf_kva_start, size, NULL, UVM_UNKNOWN_OFFSET, PAGE_SIZE, UVM_MAPFLAG(PROT_NONE, PROT_NONE, MAP_INHERIT_NONE, MADV_NORMAL, 0))) panic("%s: can't reserve VM for buffers", __func__); buf_kva_end = buf_kva_start + size; /* Contiguous mapping */ bcstats.kvaslots = bcstats.kvaslots_avail = size / MAXPHYS; } /* * buf_acquire and buf_release manage the kvm mappings of buffers. */ void buf_acquire(struct buf *bp) { KASSERT((bp->b_flags & B_BUSY) == 0); splassert(IPL_BIO); /* * Busy before waiting for kvm. */ SET(bp->b_flags, B_BUSY); buf_map(bp); } /* * Acquire a buf but do not map it. Preserve any mapping it did have. */ void buf_acquire_nomap(struct buf *bp) { splassert(IPL_BIO); SET(bp->b_flags, B_BUSY); if (bp->b_data != NULL) { TAILQ_REMOVE(&buf_valist, bp, b_valist); bcstats.kvaslots_avail--; bcstats.busymapped++; } } void buf_map(struct buf *bp) { vaddr_t va; splassert(IPL_BIO); if (bp->b_data == NULL) { unsigned long i; /* * First, just use the pre-allocated space until we run out. */ if (buf_kva_start < buf_kva_end) { va = buf_kva_start; buf_kva_start += MAXPHYS; bcstats.kvaslots_avail--; } else { struct buf *vbp; /* * Find some buffer we can steal the space from. */ vbp = TAILQ_FIRST(&buf_valist); while ((curproc != syncerproc && curproc != cleanerproc && bcstats.kvaslots_avail <= RESERVE_SLOTS) || vbp == NULL) { buf_needva++; tsleep_nsec(&buf_needva, PRIBIO, "buf_needva", INFSLP); vbp = TAILQ_FIRST(&buf_valist); } va = buf_unmap(vbp); } for (i = 0; i < atop(bp->b_bufsize); i++) { struct vm_page *pg = uvm_pagelookup(bp->b_pobj, bp->b_poffs + ptoa(i)); KASSERT(pg != NULL); pmap_kenter_pa(va + ptoa(i), VM_PAGE_TO_PHYS(pg), PROT_READ | PROT_WRITE); } pmap_update(pmap_kernel()); bp->b_data = (caddr_t)va; } else { TAILQ_REMOVE(&buf_valist, bp, b_valist); bcstats.kvaslots_avail--; } bcstats.busymapped++; } void buf_release(struct buf *bp) { KASSERT(bp->b_flags & B_BUSY); splassert(IPL_BIO); if (bp->b_data) { bcstats.busymapped--; TAILQ_INSERT_TAIL(&buf_valist, bp, b_valist); bcstats.kvaslots_avail++; if (buf_needva) { buf_needva=0; wakeup(&buf_needva); } } CLR(bp->b_flags, B_BUSY); } /* * Deallocate all memory resources for this buffer. We need to be careful * to not drop kvm since we have no way to reclaim it. So, if the buffer * has kvm, we need to free it later. We put it on the front of the * freelist just so it gets picked up faster. * * Also, lots of assertions count on bp->b_data being NULL, so we * set it temporarily to NULL. * * Return non-zero if we take care of the freeing later. */ int buf_dealloc_mem(struct buf *bp) { caddr_t data; splassert(IPL_BIO); data = bp->b_data; bp->b_data = NULL; if (data) { if (bp->b_flags & B_BUSY) bcstats.busymapped--; pmap_kremove((vaddr_t)data, bp->b_bufsize); pmap_update(pmap_kernel()); } if (bp->b_pobj) buf_free_pages(bp); if (data == NULL) return (0); bp->b_data = data; if (!(bp->b_flags & B_BUSY)) { /* XXX - need better test */ TAILQ_REMOVE(&buf_valist, bp, b_valist); bcstats.kvaslots_avail--; } else { CLR(bp->b_flags, B_BUSY); if (buf_needva) { buf_needva = 0; wakeup(&buf_needva); } } SET(bp->b_flags, B_RELEASED); TAILQ_INSERT_HEAD(&buf_valist, bp, b_valist); bcstats.kvaslots_avail++; return (1); } /* * Only used by bread_cluster. */ void buf_fix_mapping(struct buf *bp, vsize_t newsize) { vaddr_t va = (vaddr_t)bp->b_data; if (newsize < bp->b_bufsize) { pmap_kremove(va + newsize, bp->b_bufsize - newsize); pmap_update(pmap_kernel()); /* * Note: the size we lost is actually with the other * buffers read in by bread_cluster */ bp->b_bufsize = newsize; } } vaddr_t buf_unmap(struct buf *bp) { vaddr_t va; KASSERT((bp->b_flags & B_BUSY) == 0); KASSERT(bp->b_data != NULL); splassert(IPL_BIO); TAILQ_REMOVE(&buf_valist, bp, b_valist); bcstats.kvaslots_avail--; va = (vaddr_t)bp->b_data; bp->b_data = NULL; pmap_kremove(va, bp->b_bufsize); pmap_update(pmap_kernel()); if (bp->b_flags & B_RELEASED) pool_put(&bufpool, bp); return (va); } /* Always allocates in dma-reachable memory */ void buf_alloc_pages(struct buf *bp, vsize_t size) { int i; KASSERT(size == round_page(size)); KASSERT(bp->b_pobj == NULL); KASSERT(bp->b_data == NULL); splassert(IPL_BIO); uvm_obj_init(&bp->b_uobj, &bufcache_pager, 1); /* * Attempt to allocate with NOWAIT. if we can't, then throw * away some clean pages and try again. Finally, if that * fails, do a WAITOK allocation so the page daemon can find * memory for us. */ do { i = uvm_pagealloc_multi(&bp->b_uobj, 0, size, UVM_PLA_NOWAIT | UVM_PLA_NOWAKE); if (i == 0) break; } while (bufbackoff(&dma_constraint, size) == 0); if (i != 0) i = uvm_pagealloc_multi(&bp->b_uobj, 0, size, UVM_PLA_WAITOK); /* should not happen */ if (i != 0) panic("uvm_pagealloc_multi unable to allocate an buf_object " "of size %lu", size); bcstats.numbufpages += atop(size); bcstats.dmapages += atop(size); SET(bp->b_flags, B_DMA); bp->b_pobj = &bp->b_uobj; bp->b_poffs = 0; bp->b_bufsize = size; } void buf_free_pages(struct buf *bp) { struct uvm_object *uobj = bp->b_pobj; struct vm_page *pg; voff_t off, i; KASSERT(bp->b_data == NULL); KASSERT(uobj != NULL); splassert(IPL_BIO); off = bp->b_poffs; bp->b_pobj = NULL; bp->b_poffs = 0; for (i = 0; i < atop(bp->b_bufsize); i++) { pg = uvm_pagelookup(uobj, off + ptoa(i)); KASSERT(pg != NULL); KASSERT(pg->wire_count == 1); pg->wire_count = 0; bcstats.numbufpages--; if (ISSET(bp->b_flags, B_DMA)) bcstats.dmapages--; } CLR(bp->b_flags, B_DMA); /* XXX refactor to do this without splbio later */ uvm_obj_free(uobj); } /* Reallocate a buf into a particular pmem range specified by "where". */ int buf_realloc_pages(struct buf *bp, struct uvm_constraint_range *where, int flags) { vaddr_t va; int dma; int i, r; KASSERT(!(flags & UVM_PLA_WAITOK) ^ !(flags & UVM_PLA_NOWAIT)); splassert(IPL_BIO); KASSERT(ISSET(bp->b_flags, B_BUSY)); dma = ISSET(bp->b_flags, B_DMA); /* if the original buf is mapped, unmap it */ if (bp->b_data != NULL) { va = (vaddr_t)bp->b_data; pmap_kremove(va, bp->b_bufsize); pmap_update(pmap_kernel()); } do { r = uvm_pagerealloc_multi(bp->b_pobj, bp->b_poffs, bp->b_bufsize, UVM_PLA_NOWAIT | UVM_PLA_NOWAKE, where); if (r == 0) break; } while ((bufbackoff(where, atop(bp->b_bufsize)) == 0)); /* * bufbackoff() failed, so there's no more we can do without * waiting. If allowed do, make that attempt. */ if (r != 0 && (flags & UVM_PLA_WAITOK)) r = uvm_pagerealloc_multi(bp->b_pobj, bp->b_poffs, bp->b_bufsize, flags, where); /* * If the allocation has succeeded, we may be somewhere different. * If the allocation has failed, we are in the same place. * * We still have to re-map the buffer before returning. */ /* take it out of dma stats until we know where we are */ if (dma) bcstats.dmapages -= atop(bp->b_bufsize); dma = 1; /* if the original buf was mapped, re-map it */ for (i = 0; i < atop(bp->b_bufsize); i++) { struct vm_page *pg = uvm_pagelookup(bp->b_pobj, bp->b_poffs + ptoa(i)); KASSERT(pg != NULL); if (!PADDR_IS_DMA_REACHABLE(VM_PAGE_TO_PHYS(pg))) dma = 0; if (bp->b_data != NULL) { pmap_kenter_pa(va + ptoa(i), VM_PAGE_TO_PHYS(pg), PROT_READ|PROT_WRITE); pmap_update(pmap_kernel()); } } if (dma) { SET(bp->b_flags, B_DMA); bcstats.dmapages += atop(bp->b_bufsize); } else CLR(bp->b_flags, B_DMA); return(r); }
82 73 99 55 94 94 63 1050 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 /* $OpenBSD: kern_srp.c,v 1.13 2020/12/06 19:18:30 cheloha Exp $ */ /* * Copyright (c) 2014 Jonathan Matthew <jmatthew@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/timeout.h> #include <sys/srp.h> #include <sys/atomic.h> void srp_v_gc_start(struct srp_gc *, struct srp *, void *); void srpl_rc_init(struct srpl_rc *rc, void (*ref)(void *, void *), void (*unref)(void *, void *), void *cookie) { rc->srpl_ref = ref; srp_gc_init(&rc->srpl_gc, unref, cookie); } void srp_gc_init(struct srp_gc *srp_gc, void (*dtor)(void *, void *), void *cookie) { srp_gc->srp_gc_dtor = dtor; srp_gc->srp_gc_cookie = cookie; refcnt_init(&srp_gc->srp_gc_refcnt); } void srp_init(struct srp *srp) { srp->ref = NULL; } void * srp_swap_locked(struct srp *srp, void *nv) { void *ov; /* * this doesn't have to be as careful as the caller has already * prevented concurrent updates, eg. by holding the kernel lock. * can't be mixed with non-locked updates though. */ ov = srp->ref; srp->ref = nv; return (ov); } void srp_update_locked(struct srp_gc *srp_gc, struct srp *srp, void *v) { if (v != NULL) refcnt_take(&srp_gc->srp_gc_refcnt); v = srp_swap_locked(srp, v); if (v != NULL) srp_v_gc_start(srp_gc, srp, v); } void * srp_get_locked(struct srp *srp) { return (srp->ref); } void srp_gc_finalize(struct srp_gc *srp_gc) { refcnt_finalize(&srp_gc->srp_gc_refcnt, "srpfini"); } #ifdef MULTIPROCESSOR #include <machine/cpu.h> #include <sys/pool.h> struct srp_gc_ctx { struct srp_gc *srp_gc; struct timeout tick; struct srp_hazard hzrd; }; int srp_v_referenced(struct srp *, void *); void srp_v_gc(void *); struct pool srp_gc_ctx_pool; void srp_startup(void) { pool_init(&srp_gc_ctx_pool, sizeof(struct srp_gc_ctx), 0, IPL_SOFTCLOCK, PR_WAITOK, "srpgc", NULL); } int srp_v_referenced(struct srp *srp, void *v) { struct cpu_info *ci; CPU_INFO_ITERATOR cii; u_int i; struct srp_hazard *hzrd; CPU_INFO_FOREACH(cii, ci) { for (i = 0; i < nitems(ci->ci_srp_hazards); i++) { hzrd = &ci->ci_srp_hazards[i]; if (hzrd->sh_p != srp) continue; membar_consumer(); if (hzrd->sh_v != v) continue; return (1); } } return (0); } void srp_v_dtor(struct srp_gc *srp_gc, void *v) { (*srp_gc->srp_gc_dtor)(srp_gc->srp_gc_cookie, v); refcnt_rele_wake(&srp_gc->srp_gc_refcnt); } void srp_v_gc_start(struct srp_gc *srp_gc, struct srp *srp, void *v) { struct srp_gc_ctx *ctx; if (!srp_v_referenced(srp, v)) { /* we win */ srp_v_dtor(srp_gc, v); return; } /* in use, try later */ ctx = pool_get(&srp_gc_ctx_pool, PR_WAITOK); ctx->srp_gc = srp_gc; ctx->hzrd.sh_p = srp; ctx->hzrd.sh_v = v; timeout_set(&ctx->tick, srp_v_gc, ctx); timeout_add(&ctx->tick, 1); } void srp_v_gc(void *x) { struct srp_gc_ctx *ctx = x; if (srp_v_referenced(ctx->hzrd.sh_p, ctx->hzrd.sh_v)) { /* oh well, try again later */ timeout_add(&ctx->tick, 1); return; } srp_v_dtor(ctx->srp_gc, ctx->hzrd.sh_v); pool_put(&srp_gc_ctx_pool, ctx); } void * srp_swap(struct srp *srp, void *v) { return (atomic_swap_ptr(&srp->ref, v)); } void srp_update(struct srp_gc *srp_gc, struct srp *srp, void *v) { if (v != NULL) refcnt_take(&srp_gc->srp_gc_refcnt); v = srp_swap(srp, v); if (v != NULL) srp_v_gc_start(srp_gc, srp, v); } static inline void * srp_v(struct srp_hazard *hzrd, struct srp *srp) { void *v; hzrd->sh_p = srp; /* * ensure we update this cpu's hazard pointer to a value that's still * current after the store finishes, otherwise the gc task may already * be destroying it */ do { v = srp->ref; hzrd->sh_v = v; membar_consumer(); } while (__predict_false(v != srp->ref)); return (v); } void * srp_enter(struct srp_ref *sr, struct srp *srp) { struct cpu_info *ci = curcpu(); struct srp_hazard *hzrd; u_int i; for (i = 0; i < nitems(ci->ci_srp_hazards); i++) { hzrd = &ci->ci_srp_hazards[i]; if (hzrd->sh_p == NULL) { sr->hz = hzrd; return (srp_v(hzrd, srp)); } } panic("%s: not enough srp hazard records", __func__); /* NOTREACHED */ return (NULL); } void * srp_follow(struct srp_ref *sr, struct srp *srp) { return (srp_v(sr->hz, srp)); } void srp_leave(struct srp_ref *sr) { sr->hz->sh_p = NULL; } static inline int srp_referenced(void *v) { struct cpu_info *ci; CPU_INFO_ITERATOR cii; u_int i; struct srp_hazard *hzrd; CPU_INFO_FOREACH(cii, ci) { for (i = 0; i < nitems(ci->ci_srp_hazards); i++) { hzrd = &ci->ci_srp_hazards[i]; if (hzrd->sh_p != NULL && hzrd->sh_v == v) return (1); } } return (0); } void srp_finalize(void *v, const char *wmesg) { while (srp_referenced(v)) tsleep_nsec(v, PWAIT, wmesg, MSEC_TO_NSEC(1)); } #else /* MULTIPROCESSOR */ void srp_startup(void) { } void srp_v_gc_start(struct srp_gc *srp_gc, struct srp *srp, void *v) { (*srp_gc->srp_gc_dtor)(srp_gc->srp_gc_cookie, v); refcnt_rele_wake(&srp_gc->srp_gc_refcnt); } #endif /* MULTIPROCESSOR */
14 31 31 22 25 417 376 56 417 416 1 415 113 113 53 53 135 134 105 2 105 2 2 254 254 89 1 14 5 5 5 35 2 34 2 25 16 10 2 21 18 102 29 61 29 61 63 64 29 16 15 31 37 15 422 602 34 583 602 27 3 50 42 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 /* $OpenBSD: kern_ktrace.c,v 1.114 2023/12/15 15:12:08 deraadt Exp $ */ /* $NetBSD: kern_ktrace.c,v 1.23 1996/02/09 18:59:36 christos Exp $ */ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_ktrace.c 8.2 (Berkeley) 9/23/93 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/sched.h> #include <sys/fcntl.h> #include <sys/namei.h> #include <sys/vnode.h> #include <sys/lock.h> #include <sys/ktrace.h> #include <sys/malloc.h> #include <sys/syslog.h> #include <sys/sysctl.h> #include <sys/pledge.h> #include <sys/mount.h> #include <sys/syscall.h> #include <sys/syscallargs.h> void ktrinitheaderraw(struct ktr_header *, uint, pid_t, pid_t); void ktrinitheader(struct ktr_header *, struct proc *, int); int ktrstart(struct proc *, struct vnode *, struct ucred *); int ktrops(struct proc *, struct process *, int, int, struct vnode *, struct ucred *); int ktrsetchildren(struct proc *, struct process *, int, int, struct vnode *, struct ucred *); int ktrwrite(struct proc *, struct ktr_header *, const void *, size_t); int ktrwrite2(struct proc *, struct ktr_header *, const void *, size_t, const void *, size_t); int ktrwriteraw(struct proc *, struct vnode *, struct ucred *, struct ktr_header *, struct iovec *); int ktrcanset(struct proc *, struct process *); /* * Clear the trace settings in a correct way (to avoid races). */ void ktrcleartrace(struct process *pr) { struct vnode *vp; struct ucred *cred; if (pr->ps_tracevp != NULL) { vp = pr->ps_tracevp; cred = pr->ps_tracecred; pr->ps_traceflag = 0; pr->ps_tracevp = NULL; pr->ps_tracecred = NULL; vp->v_writecount--; vrele(vp); crfree(cred); } } /* * Change the trace setting in a correct way (to avoid races). */ void ktrsettrace(struct process *pr, int facs, struct vnode *newvp, struct ucred *newcred) { struct vnode *oldvp; struct ucred *oldcred; KASSERT(newvp != NULL); KASSERT(newcred != NULL); pr->ps_traceflag |= facs; /* nothing to change about where the trace goes? */ if (pr->ps_tracevp == newvp && pr->ps_tracecred == newcred) return; vref(newvp); crhold(newcred); newvp->v_writecount++; oldvp = pr->ps_tracevp; oldcred = pr->ps_tracecred; pr->ps_tracevp = newvp; pr->ps_tracecred = newcred; if (oldvp != NULL) { oldvp->v_writecount--; vrele(oldvp); crfree(oldcred); } } void ktrinitheaderraw(struct ktr_header *kth, uint type, pid_t pid, pid_t tid) { memset(kth, 0, sizeof(struct ktr_header)); kth->ktr_type = type; kth->ktr_pid = pid; kth->ktr_tid = tid; } void ktrinitheader(struct ktr_header *kth, struct proc *p, int type) { struct process *pr = p->p_p; ktrinitheaderraw(kth, type, pr->ps_pid, p->p_tid + THREAD_PID_OFFSET); memcpy(kth->ktr_comm, pr->ps_comm, sizeof(kth->ktr_comm)); } int ktrstart(struct proc *p, struct vnode *vp, struct ucred *cred) { struct ktr_header kth; ktrinitheaderraw(&kth, htobe32(KTR_START), -1, -1); return (ktrwriteraw(p, vp, cred, &kth, NULL)); } void ktrsyscall(struct proc *p, register_t code, size_t argsize, register_t args[]) { struct ktr_header kth; struct ktr_syscall *ktp; size_t len = sizeof(struct ktr_syscall) + argsize; register_t *argp; u_int nargs = 0; int i; if (code == SYS_sysctl) { /* * The sysctl encoding stores the mib[] * array because it is interesting. */ if (args[1] > 0) nargs = lmin(args[1], CTL_MAXNAME); len += nargs * sizeof(int); } atomic_setbits_int(&p->p_flag, P_INKTR); ktrinitheader(&kth, p, KTR_SYSCALL); ktp = malloc(len, M_TEMP, M_WAITOK); ktp->ktr_code = code; ktp->ktr_argsize = argsize; argp = (register_t *)((char *)ktp + sizeof(struct ktr_syscall)); for (i = 0; i < (argsize / sizeof *argp); i++) *argp++ = args[i]; if (nargs && copyin((void *)args[0], argp, nargs * sizeof(int))) memset(argp, 0, nargs * sizeof(int)); ktrwrite(p, &kth, ktp, len); free(ktp, M_TEMP, len); atomic_clearbits_int(&p->p_flag, P_INKTR); } void ktrsysret(struct proc *p, register_t code, int error, const register_t retval[2]) { struct ktr_header kth; struct ktr_sysret ktp; int len; atomic_setbits_int(&p->p_flag, P_INKTR); ktrinitheader(&kth, p, KTR_SYSRET); ktp.ktr_code = code; ktp.ktr_error = error; if (error) len = 0; else if (code == SYS_lseek) /* the one exception: lseek on ILP32 needs more */ len = sizeof(long long); else len = sizeof(register_t); ktrwrite2(p, &kth, &ktp, sizeof(ktp), retval, len); atomic_clearbits_int(&p->p_flag, P_INKTR); } void ktrnamei(struct proc *p, char *path) { struct ktr_header kth; atomic_setbits_int(&p->p_flag, P_INKTR); ktrinitheader(&kth, p, KTR_NAMEI); ktrwrite(p, &kth, path, strlen(path)); atomic_clearbits_int(&p->p_flag, P_INKTR); } void ktrgenio(struct proc *p, int fd, enum uio_rw rw, struct iovec *iov, ssize_t len) { struct ktr_header kth; struct ktr_genio ktp; caddr_t cp; int count, error; int buflen; atomic_setbits_int(&p->p_flag, P_INKTR); /* beware overflow */ if (len > PAGE_SIZE) buflen = PAGE_SIZE; else buflen = len + sizeof(struct ktr_genio); ktrinitheader(&kth, p, KTR_GENIO); ktp.ktr_fd = fd; ktp.ktr_rw = rw; cp = malloc(buflen, M_TEMP, M_WAITOK); while (len > 0) { /* * Don't allow this process to hog the cpu when doing * huge I/O. */ sched_pause(preempt); count = lmin(iov->iov_len, buflen); if (count > len) count = len; if (copyin(iov->iov_base, cp, count)) break; KERNEL_LOCK(); error = ktrwrite2(p, &kth, &ktp, sizeof(ktp), cp, count); KERNEL_UNLOCK(); if (error != 0) break; iov->iov_len -= count; iov->iov_base = (caddr_t)iov->iov_base + count; if (iov->iov_len == 0) iov++; len -= count; } free(cp, M_TEMP, buflen); atomic_clearbits_int(&p->p_flag, P_INKTR); } void ktrpsig(struct proc *p, int sig, sig_t action, int mask, int code, siginfo_t *si) { struct ktr_header kth; struct ktr_psig kp; atomic_setbits_int(&p->p_flag, P_INKTR); ktrinitheader(&kth, p, KTR_PSIG); kp.signo = (char)sig; kp.action = action; kp.mask = mask; kp.code = code; kp.si = *si; KERNEL_LOCK(); ktrwrite(p, &kth, &kp, sizeof(kp)); KERNEL_UNLOCK(); atomic_clearbits_int(&p->p_flag, P_INKTR); } void ktrstruct(struct proc *p, const char *name, const void *data, size_t datalen) { struct ktr_header kth; atomic_setbits_int(&p->p_flag, P_INKTR); ktrinitheader(&kth, p, KTR_STRUCT); if (data == NULL) datalen = 0; KERNEL_LOCK(); ktrwrite2(p, &kth, name, strlen(name) + 1, data, datalen); KERNEL_UNLOCK(); atomic_clearbits_int(&p->p_flag, P_INKTR); } int ktruser(struct proc *p, const char *id, const void *addr, size_t len) { struct ktr_header kth; struct ktr_user ktp; int error; void *memp; #define STK_PARAMS 128 long long stkbuf[STK_PARAMS / sizeof(long long)]; if (!KTRPOINT(p, KTR_USER)) return (0); if (len > KTR_USER_MAXLEN) return (EINVAL); atomic_setbits_int(&p->p_flag, P_INKTR); ktrinitheader(&kth, p, KTR_USER); memset(ktp.ktr_id, 0, KTR_USER_MAXIDLEN); error = copyinstr(id, ktp.ktr_id, KTR_USER_MAXIDLEN, NULL); if (error == 0) { if (len > sizeof(stkbuf)) memp = malloc(len, M_TEMP, M_WAITOK); else memp = stkbuf; error = copyin(addr, memp, len); if (error == 0) { KERNEL_LOCK(); ktrwrite2(p, &kth, &ktp, sizeof(ktp), memp, len); KERNEL_UNLOCK(); } if (memp != stkbuf) free(memp, M_TEMP, len); } atomic_clearbits_int(&p->p_flag, P_INKTR); return (error); } void ktrexec(struct proc *p, int type, const char *data, ssize_t len) { struct ktr_header kth; int count; int buflen; assert(type == KTR_EXECARGS || type == KTR_EXECENV); atomic_setbits_int(&p->p_flag, P_INKTR); /* beware overflow */ if (len > PAGE_SIZE) buflen = PAGE_SIZE; else buflen = len; ktrinitheader(&kth, p, type); while (len > 0) { /* * Don't allow this process to hog the cpu when doing * huge I/O. */ sched_pause(preempt); count = lmin(len, buflen); if (ktrwrite(p, &kth, data, count) != 0) break; len -= count; data += count; } atomic_clearbits_int(&p->p_flag, P_INKTR); } void ktrpledge(struct proc *p, int error, uint64_t code, int syscall) { struct ktr_header kth; struct ktr_pledge kp; atomic_setbits_int(&p->p_flag, P_INKTR); ktrinitheader(&kth, p, KTR_PLEDGE); kp.error = error; kp.code = code; kp.syscall = syscall; KERNEL_LOCK(); ktrwrite(p, &kth, &kp, sizeof(kp)); KERNEL_UNLOCK(); atomic_clearbits_int(&p->p_flag, P_INKTR); } void ktrpinsyscall(struct proc *p, int error, int syscall, vaddr_t addr) { struct ktr_header kth; struct ktr_pinsyscall kp; atomic_setbits_int(&p->p_flag, P_INKTR); ktrinitheader(&kth, p, KTR_PINSYSCALL); kp.error = error; kp.syscall = syscall; kp.addr = addr; KERNEL_LOCK(); ktrwrite(p, &kth, &kp, sizeof(kp)); KERNEL_UNLOCK(); atomic_clearbits_int(&p->p_flag, P_INKTR); } /* Interface and common routines */ int doktrace(struct vnode *vp, int ops, int facs, pid_t pid, struct proc *p) { struct process *pr = NULL; struct ucred *cred = NULL; struct pgrp *pg; int descend = ops & KTRFLAG_DESCEND; int ret = 0; int error = 0; facs = facs & ~((unsigned)KTRFAC_ROOT); ops = KTROP(ops); if (ops != KTROP_CLEAR) { /* * an operation which requires a file argument. */ cred = p->p_ucred; if (!vp) { error = EINVAL; goto done; } if (vp->v_type != VREG) { error = EACCES; goto done; } } /* * Clear all uses of the tracefile */ if (ops == KTROP_CLEARFILE) { LIST_FOREACH(pr, &allprocess, ps_list) { if (pr->ps_tracevp == vp) { if (ktrcanset(p, pr)) ktrcleartrace(pr); else error = EPERM; } } goto done; } /* * need something to (un)trace (XXX - why is this here?) */ if (!facs) { error = EINVAL; goto done; } if (ops == KTROP_SET) { if (suser(p) == 0) facs |= KTRFAC_ROOT; error = ktrstart(p, vp, cred); if (error != 0) goto done; } /* * do it */ if (pid < 0) { /* * by process group */ pg = pgfind(-pid); if (pg == NULL) { error = ESRCH; goto done; } LIST_FOREACH(pr, &pg->pg_members, ps_pglist) { if (descend) ret |= ktrsetchildren(p, pr, ops, facs, vp, cred); else ret |= ktrops(p, pr, ops, facs, vp, cred); } } else { /* * by pid */ pr = prfind(pid); if (pr == NULL) { error = ESRCH; goto done; } if (descend) ret |= ktrsetchildren(p, pr, ops, facs, vp, cred); else ret |= ktrops(p, pr, ops, facs, vp, cred); } if (!ret) error = EPERM; done: return (error); } /* * ktrace system call */ int sys_ktrace(struct proc *p, void *v, register_t *retval) { struct sys_ktrace_args /* { syscallarg(const char *) fname; syscallarg(int) ops; syscallarg(int) facs; syscallarg(pid_t) pid; } */ *uap = v; struct vnode *vp = NULL; const char *fname = SCARG(uap, fname); struct ucred *cred = NULL; int error; if (fname) { struct nameidata nd; cred = p->p_ucred; NDINIT(&nd, 0, 0, UIO_USERSPACE, fname, p); nd.ni_pledge = PLEDGE_CPATH | PLEDGE_WPATH; nd.ni_unveil = UNVEIL_CREATE | UNVEIL_WRITE; if ((error = vn_open(&nd, FWRITE|O_NOFOLLOW, 0)) != 0) return error; vp = nd.ni_vp; VOP_UNLOCK(vp); } error = doktrace(vp, SCARG(uap, ops), SCARG(uap, facs), SCARG(uap, pid), p); if (vp != NULL) (void)vn_close(vp, FWRITE, cred, p); return error; } int ktrops(struct proc *curp, struct process *pr, int ops, int facs, struct vnode *vp, struct ucred *cred) { if (!ktrcanset(curp, pr)) return (0); if (ops == KTROP_SET) ktrsettrace(pr, facs, vp, cred); else { /* KTROP_CLEAR */ pr->ps_traceflag &= ~facs; if ((pr->ps_traceflag & KTRFAC_MASK) == 0) { /* cleared all the facility bits, so stop completely */ ktrcleartrace(pr); } } return (1); } int ktrsetchildren(struct proc *curp, struct process *top, int ops, int facs, struct vnode *vp, struct ucred *cred) { struct process *pr; int ret = 0; pr = top; for (;;) { ret |= ktrops(curp, pr, ops, facs, vp, cred); /* * If this process has children, descend to them next, * otherwise do any siblings, and if done with this level, * follow back up the tree (but not past top). */ if (!LIST_EMPTY(&pr->ps_children)) pr = LIST_FIRST(&pr->ps_children); else for (;;) { if (pr == top) return (ret); if (LIST_NEXT(pr, ps_sibling) != NULL) { pr = LIST_NEXT(pr, ps_sibling); break; } pr = pr->ps_pptr; } } /*NOTREACHED*/ } int ktrwrite(struct proc *p, struct ktr_header *kth, const void *aux, size_t len) { struct vnode *vp = p->p_p->ps_tracevp; struct ucred *cred = p->p_p->ps_tracecred; struct iovec data[2]; int error; if (vp == NULL) return 0; crhold(cred); data[0].iov_base = (void *)aux; data[0].iov_len = len; data[1].iov_len = 0; kth->ktr_len = len; error = ktrwriteraw(p, vp, cred, kth, data); crfree(cred); return (error); } int ktrwrite2(struct proc *p, struct ktr_header *kth, const void *aux1, size_t len1, const void *aux2, size_t len2) { struct vnode *vp = p->p_p->ps_tracevp; struct ucred *cred = p->p_p->ps_tracecred; struct iovec data[2]; int error; if (vp == NULL) return 0; crhold(cred); data[0].iov_base = (void *)aux1; data[0].iov_len = len1; data[1].iov_base = (void *)aux2; data[1].iov_len = len2; kth->ktr_len = len1 + len2; error = ktrwriteraw(p, vp, cred, kth, data); crfree(cred); return (error); } int ktrwriteraw(struct proc *curp, struct vnode *vp, struct ucred *cred, struct ktr_header *kth, struct iovec *data) { struct uio auio; struct iovec aiov[3]; struct process *pr; int error; nanotime(&kth->ktr_time); KERNEL_ASSERT_LOCKED(); auio.uio_iov = &aiov[0]; auio.uio_offset = 0; auio.uio_segflg = UIO_SYSSPACE; auio.uio_rw = UIO_WRITE; aiov[0].iov_base = (caddr_t)kth; aiov[0].iov_len = sizeof(struct ktr_header); auio.uio_resid = sizeof(struct ktr_header); auio.uio_iovcnt = 1; auio.uio_procp = curp; if (kth->ktr_len > 0) { aiov[1] = data[0]; aiov[2] = data[1]; auio.uio_iovcnt++; if (aiov[2].iov_len > 0) auio.uio_iovcnt++; auio.uio_resid += kth->ktr_len; } error = vget(vp, LK_EXCLUSIVE | LK_RETRY); if (error) goto bad; error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, cred); vput(vp); if (error) goto bad; return (0); bad: /* * If error encountered, give up tracing on this vnode. */ log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n", error); LIST_FOREACH(pr, &allprocess, ps_list) { if (pr == curp->p_p) continue; if (pr->ps_tracevp == vp && pr->ps_tracecred == cred) ktrcleartrace(pr); } ktrcleartrace(curp->p_p); return (error); } /* * Return true if caller has permission to set the ktracing state * of target. Essentially, the target can't possess any * more permissions than the caller. KTRFAC_ROOT signifies that * root previously set the tracing status on the target process, and * so, only root may further change it. * * TODO: check groups. use caller effective gid. */ int ktrcanset(struct proc *callp, struct process *targetpr) { struct ucred *caller = callp->p_ucred; struct ucred *target = targetpr->ps_ucred; if ((caller->cr_uid == target->cr_ruid && target->cr_ruid == target->cr_svuid && caller->cr_rgid == target->cr_rgid && /* XXX */ target->cr_rgid == target->cr_svgid && (targetpr->ps_traceflag & KTRFAC_ROOT) == 0 && !ISSET(targetpr->ps_flags, PS_SUGID)) || caller->cr_uid == 0) return (1); return (0); }
24 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 /* $OpenBSD: raw_ip6.h,v 1.4 2017/02/09 15:23:35 jca Exp $ */ /* $KAME: raw_ip6.h,v 1.2 2001/05/27 13:28:35 itojun Exp $ */ /* * Copyright (C) 2001 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef _NETINET6_RAW_IP6_H_ #define _NETINET6_RAW_IP6_H_ /* * ICMPv6 stat is counted separately. see netinet/icmp6.h */ struct rip6stat { u_int64_t rip6s_ipackets; /* total input packets */ u_int64_t rip6s_isum; /* input checksum computations */ u_int64_t rip6s_badsum; /* of above, checksum error */ u_int64_t rip6s_nosock; /* no matching socket */ u_int64_t rip6s_nosockmcast; /* of above, arrived as multicast */ u_int64_t rip6s_fullsock; /* not delivered, input socket full */ u_int64_t rip6s_opackets; /* total output packets */ }; /* * Names for RIP6 sysctl objects */ #define RIPV6CTL_STATS 1 /* RIP6 stats */ #define RIPV6CTL_MAXID 2 #define RIPM6CTL_NAMES { \ { 0, 0 }, \ { "stats", CTLTYPE_NODE }, \ } #ifdef _KERNEL #include <sys/percpu.h> enum rip6stat_counters { rip6s_ipackets, rip6s_isum, rip6s_badsum, rip6s_nosock, rip6s_nosockmcast, rip6s_fullsock, rip6s_opackets, rip6s_ncounters, }; extern struct cpumem *rip6counters; static inline void rip6stat_inc(enum rip6stat_counters c) { counters_inc(rip6counters, c); } #endif #endif
2 1 1 4 2 2 2 1 1 1 37 35 1 11 6 6 1 1 27 28 2 1 2 1 1 2 1 2 4 4 2 2 1 1 1 1 1 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 /* $OpenBSD: pci.c,v 1.128 2024/03/18 21:20:46 kettenis Exp $ */ /* $NetBSD: pci.c,v 1.31 1997/06/06 23:48:04 thorpej Exp $ */ /* * Copyright (c) 1995, 1996 Christopher G. Demetriou. All rights reserved. * Copyright (c) 1994 Charles Hannum. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Charles Hannum. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * PCI bus autoconfiguration. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> #include <sys/malloc.h> #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcidevs.h> #include <dev/pci/ppbreg.h> int pcimatch(struct device *, void *, void *); void pciattach(struct device *, struct device *, void *); int pcidetach(struct device *, int); int pciactivate(struct device *, int); void pci_suspend(struct pci_softc *); void pci_powerdown(struct pci_softc *); void pci_resume(struct pci_softc *); struct msix_vector { uint32_t mv_ma; uint32_t mv_mau32; uint32_t mv_md; uint32_t mv_vc; }; #define NMAPREG ((PCI_MAPREG_END - PCI_MAPREG_START) / \ sizeof(pcireg_t)) struct pci_dev { struct device *pd_dev; LIST_ENTRY(pci_dev) pd_next; pcitag_t pd_tag; /* pci register tag */ pcireg_t pd_csr; pcireg_t pd_bhlc; pcireg_t pd_int; pcireg_t pd_map[NMAPREG]; pcireg_t pd_mask[NMAPREG]; pcireg_t pd_msi_mc; pcireg_t pd_msi_ma; pcireg_t pd_msi_mau32; pcireg_t pd_msi_md; pcireg_t pd_msix_mc; struct msix_vector *pd_msix_table; int pd_pmcsr_state; int pd_vga_decode; }; #ifdef APERTURE extern int allowaperture; #endif const struct cfattach pci_ca = { sizeof(struct pci_softc), pcimatch, pciattach, pcidetach, pciactivate }; struct cfdriver pci_cd = { NULL, "pci", DV_DULL }; int pci_ndomains; struct proc *pci_vga_proc; struct pci_softc *pci_vga_pci; pcitag_t pci_vga_tag; int pci_dopm; int pciprint(void *, const char *); int pcisubmatch(struct device *, void *, void *); #ifdef PCI_MACHDEP_ENUMERATE_BUS #define pci_enumerate_bus PCI_MACHDEP_ENUMERATE_BUS #else int pci_enumerate_bus(struct pci_softc *, int (*)(struct pci_attach_args *), struct pci_attach_args *); #endif int pci_reserve_resources(struct pci_attach_args *); int pci_primary_vga(struct pci_attach_args *); /* * Important note about PCI-ISA bridges: * * Callbacks are used to configure these devices so that ISA/EISA bridges * can attach their child busses after PCI configuration is done. * * This works because: * (1) there can be at most one ISA/EISA bridge per PCI bus, and * (2) any ISA/EISA bridges must be attached to primary PCI * busses (i.e. bus zero). * * That boils down to: there can only be one of these outstanding * at a time, it is cleared when configuring PCI bus 0 before any * subdevices have been found, and it is run after all subdevices * of PCI bus 0 have been found. * * This is needed because there are some (legacy) PCI devices which * can show up as ISA/EISA devices as well (the prime example of which * are VGA controllers). If you attach ISA from a PCI-ISA/EISA bridge, * and the bridge is seen before the video board is, the board can show * up as an ISA device, and that can (bogusly) complicate the PCI device's * attach code, or make the PCI device not be properly attached at all. * * We use the generic config_defer() facility to achieve this. */ int pcimatch(struct device *parent, void *match, void *aux) { struct cfdata *cf = match; struct pcibus_attach_args *pba = aux; if (strcmp(pba->pba_busname, cf->cf_driver->cd_name)) return (0); /* Check the locators */ if (cf->pcibuscf_bus != PCIBUS_UNK_BUS && cf->pcibuscf_bus != pba->pba_bus) return (0); /* sanity */ if (pba->pba_bus < 0 || pba->pba_bus > 255) return (0); /* * XXX check other (hardware?) indicators */ return (1); } void pciattach(struct device *parent, struct device *self, void *aux) { struct pcibus_attach_args *pba = aux; struct pci_softc *sc = (struct pci_softc *)self; pci_attach_hook(parent, self, pba); printf("\n"); LIST_INIT(&sc->sc_devs); sc->sc_iot = pba->pba_iot; sc->sc_memt = pba->pba_memt; sc->sc_dmat = pba->pba_dmat; sc->sc_pc = pba->pba_pc; sc->sc_flags = pba->pba_flags; sc->sc_ioex = pba->pba_ioex; sc->sc_memex = pba->pba_memex; sc->sc_pmemex = pba->pba_pmemex; sc->sc_busex = pba->pba_busex; sc->sc_domain = pba->pba_domain; sc->sc_bus = pba->pba_bus; sc->sc_bridgetag = pba->pba_bridgetag; sc->sc_bridgeih = pba->pba_bridgeih; sc->sc_maxndevs = pci_bus_maxdevs(pba->pba_pc, pba->pba_bus); sc->sc_intrswiz = pba->pba_intrswiz; sc->sc_intrtag = pba->pba_intrtag; /* Reserve our own bus number. */ if (sc->sc_busex) extent_alloc_region(sc->sc_busex, sc->sc_bus, 1, EX_NOWAIT); pci_enumerate_bus(sc, pci_reserve_resources, NULL); /* Find the VGA device that's currently active. */ if (pci_enumerate_bus(sc, pci_primary_vga, NULL)) pci_vga_pci = sc; pci_enumerate_bus(sc, NULL, NULL); } int pcidetach(struct device *self, int flags) { return pci_detach_devices((struct pci_softc *)self, flags); } int pciactivate(struct device *self, int act) { int rv = 0; switch (act) { case DVACT_SUSPEND: rv = config_activate_children(self, act); pci_suspend((struct pci_softc *)self); break; case DVACT_RESUME: pci_resume((struct pci_softc *)self); rv = config_activate_children(self, act); break; case DVACT_POWERDOWN: rv = config_activate_children(self, act); pci_powerdown((struct pci_softc *)self); break; default: rv = config_activate_children(self, act); break; } return (rv); } void pci_suspend(struct pci_softc *sc) { struct pci_dev *pd; pcireg_t bhlc, reg; int off, i; LIST_FOREACH(pd, &sc->sc_devs, pd_next) { /* * Only handle header type 0 here; PCI-PCI bridges and * CardBus bridges need special handling, which will * be done in their specific drivers. */ bhlc = pci_conf_read(sc->sc_pc, pd->pd_tag, PCI_BHLC_REG); if (PCI_HDRTYPE_TYPE(bhlc) != 0) continue; /* Save registers that may get lost. */ for (i = 0; i < NMAPREG; i++) pd->pd_map[i] = pci_conf_read(sc->sc_pc, pd->pd_tag, PCI_MAPREG_START + (i * 4)); pd->pd_csr = pci_conf_read(sc->sc_pc, pd->pd_tag, PCI_COMMAND_STATUS_REG); pd->pd_bhlc = pci_conf_read(sc->sc_pc, pd->pd_tag, PCI_BHLC_REG); pd->pd_int = pci_conf_read(sc->sc_pc, pd->pd_tag, PCI_INTERRUPT_REG); if (pci_get_capability(sc->sc_pc, pd->pd_tag, PCI_CAP_MSI, &off, &reg)) { pd->pd_msi_ma = pci_conf_read(sc->sc_pc, pd->pd_tag, off + PCI_MSI_MA); if (reg & PCI_MSI_MC_C64) { pd->pd_msi_mau32 = pci_conf_read(sc->sc_pc, pd->pd_tag, off + PCI_MSI_MAU32); pd->pd_msi_md = pci_conf_read(sc->sc_pc, pd->pd_tag, off + PCI_MSI_MD64); } else { pd->pd_msi_md = pci_conf_read(sc->sc_pc, pd->pd_tag, off + PCI_MSI_MD32); } pd->pd_msi_mc = reg; } pci_suspend_msix(sc->sc_pc, pd->pd_tag, sc->sc_memt, &pd->pd_msix_mc, pd->pd_msix_table); } } void pci_powerdown(struct pci_softc *sc) { struct pci_dev *pd; pcireg_t bhlc; LIST_FOREACH(pd, &sc->sc_devs, pd_next) { /* * Only handle header type 0 here; PCI-PCI bridges and * CardBus bridges need special handling, which will * be done in their specific drivers. */ bhlc = pci_conf_read(sc->sc_pc, pd->pd_tag, PCI_BHLC_REG); if (PCI_HDRTYPE_TYPE(bhlc) != 0) continue; if (pci_dopm) { /* * Place the device into the lowest possible * power state. */ pd->pd_pmcsr_state = pci_get_powerstate(sc->sc_pc, pd->pd_tag); pci_set_powerstate(sc->sc_pc, pd->pd_tag, pci_min_powerstate(sc->sc_pc, pd->pd_tag)); } } } void pci_resume(struct pci_softc *sc) { struct pci_dev *pd; pcireg_t bhlc, reg; int off, i; LIST_FOREACH(pd, &sc->sc_devs, pd_next) { /* * Only handle header type 0 here; PCI-PCI bridges and * CardBus bridges need special handling, which will * be done in their specific drivers. */ bhlc = pci_conf_read(sc->sc_pc, pd->pd_tag, PCI_BHLC_REG); if (PCI_HDRTYPE_TYPE(bhlc) != 0) continue; /* Restore power. */ if (pci_dopm) pci_set_powerstate(sc->sc_pc, pd->pd_tag, pd->pd_pmcsr_state); /* Restore the registers saved above. */ for (i = 0; i < NMAPREG; i++) pci_conf_write(sc->sc_pc, pd->pd_tag, PCI_MAPREG_START + (i * 4), pd->pd_map[i]); reg = pci_conf_read(sc->sc_pc, pd->pd_tag, PCI_COMMAND_STATUS_REG); pci_conf_write(sc->sc_pc, pd->pd_tag, PCI_COMMAND_STATUS_REG, (reg & 0xffff0000) | (pd->pd_csr & 0x0000ffff)); pci_conf_write(sc->sc_pc, pd->pd_tag, PCI_BHLC_REG, pd->pd_bhlc); pci_conf_write(sc->sc_pc, pd->pd_tag, PCI_INTERRUPT_REG, pd->pd_int); if (pci_get_capability(sc->sc_pc, pd->pd_tag, PCI_CAP_MSI, &off, &reg)) { pci_conf_write(sc->sc_pc, pd->pd_tag, off + PCI_MSI_MA, pd->pd_msi_ma); if (reg & PCI_MSI_MC_C64) { pci_conf_write(sc->sc_pc, pd->pd_tag, off + PCI_MSI_MAU32, pd->pd_msi_mau32); pci_conf_write(sc->sc_pc, pd->pd_tag, off + PCI_MSI_MD64, pd->pd_msi_md); } else { pci_conf_write(sc->sc_pc, pd->pd_tag, off + PCI_MSI_MD32, pd->pd_msi_md); } pci_conf_write(sc->sc_pc, pd->pd_tag, off + PCI_MSI_MC, pd->pd_msi_mc); } pci_resume_msix(sc->sc_pc, pd->pd_tag, sc->sc_memt, pd->pd_msix_mc, pd->pd_msix_table); } } int pciprint(void *aux, const char *pnp) { struct pci_attach_args *pa = aux; char devinfo[256]; if (pnp) { pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo, sizeof devinfo); printf("%s at %s", devinfo, pnp); } printf(" dev %d function %d", pa->pa_device, pa->pa_function); if (!pnp) { pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof devinfo); printf(" %s", devinfo); } return (UNCONF); } int pcisubmatch(struct device *parent, void *match, void *aux) { struct cfdata *cf = match; struct pci_attach_args *pa = aux; if (cf->pcicf_dev != PCI_UNK_DEV && cf->pcicf_dev != pa->pa_device) return (0); if (cf->pcicf_function != PCI_UNK_FUNCTION && cf->pcicf_function != pa->pa_function) return (0); return ((*cf->cf_attach->ca_match)(parent, match, aux)); } int pci_probe_device(struct pci_softc *sc, pcitag_t tag, int (*match)(struct pci_attach_args *), struct pci_attach_args *pap) { pci_chipset_tag_t pc = sc->sc_pc; struct pci_attach_args pa; struct pci_dev *pd; pcireg_t id, class, intr, bhlcr, cap; int pin, bus, device, function; int off, ret = 0; uint64_t addr; pci_decompose_tag(pc, tag, &bus, &device, &function); bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG); if (PCI_HDRTYPE_TYPE(bhlcr) > 2) return (0); id = pci_conf_read(pc, tag, PCI_ID_REG); class = pci_conf_read(pc, tag, PCI_CLASS_REG); /* Invalid vendor ID value? */ if (PCI_VENDOR(id) == PCI_VENDOR_INVALID) return (0); /* XXX Not invalid, but we've done this ~forever. */ if (PCI_VENDOR(id) == 0) return (0); pa.pa_iot = sc->sc_iot; pa.pa_memt = sc->sc_memt; pa.pa_dmat = sc->sc_dmat; pa.pa_pc = pc; pa.pa_ioex = sc->sc_ioex; pa.pa_memex = sc->sc_memex; pa.pa_pmemex = sc->sc_pmemex; pa.pa_busex = sc->sc_busex; pa.pa_domain = sc->sc_domain; pa.pa_bus = bus; pa.pa_device = device; pa.pa_function = function; pa.pa_tag = tag; pa.pa_id = id; pa.pa_class = class; pa.pa_bridgetag = sc->sc_bridgetag; pa.pa_bridgeih = sc->sc_bridgeih; /* This is a simplification of the NetBSD code. We don't support turning off I/O or memory on broken hardware. <csapuntz@stanford.edu> */ pa.pa_flags = sc->sc_flags; pa.pa_flags |= PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED; if (sc->sc_bridgetag == NULL) { pa.pa_intrswiz = 0; pa.pa_intrtag = tag; } else { pa.pa_intrswiz = sc->sc_intrswiz + device; pa.pa_intrtag = sc->sc_intrtag; } intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG); pin = PCI_INTERRUPT_PIN(intr); pa.pa_rawintrpin = pin; if (pin == PCI_INTERRUPT_PIN_NONE) { /* no interrupt */ pa.pa_intrpin = 0; } else { /* * swizzle it based on the number of busses we're * behind and our device number. */ pa.pa_intrpin = /* XXX */ ((pin + pa.pa_intrswiz - 1) % 4) + 1; } pa.pa_intrline = PCI_INTERRUPT_LINE(intr); if (pci_get_ht_capability(pc, tag, PCI_HT_CAP_MSI, &off, &cap)) { /* * XXX Should we enable MSI mapping ourselves on * systems that have it disabled? */ if (cap & PCI_HT_MSI_ENABLED) { if ((cap & PCI_HT_MSI_FIXED) == 0) { addr = pci_conf_read(pc, tag, off + PCI_HT_MSI_ADDR); addr |= (uint64_t)pci_conf_read(pc, tag, off + PCI_HT_MSI_ADDR_HI32) << 32; } else addr = PCI_HT_MSI_FIXED_ADDR; /* * XXX This will fail to enable MSI on systems * that don't use the canonical address. */ if (addr == PCI_HT_MSI_FIXED_ADDR) pa.pa_flags |= PCI_FLAGS_MSI_ENABLED; } } /* * Give the MD code a chance to alter pci_attach_args and/or * skip devices. */ if (pci_probe_device_hook(pc, &pa) != 0) return (0); if (match != NULL) { ret = (*match)(&pa); if (ret != 0 && pap != NULL) *pap = pa; } else { pcireg_t address, csr; int i, reg, reg_start, reg_end; int s; pd = malloc(sizeof *pd, M_DEVBUF, M_ZERO | M_WAITOK); pd->pd_tag = tag; LIST_INSERT_HEAD(&sc->sc_devs, pd, pd_next); switch (PCI_HDRTYPE_TYPE(bhlcr)) { case 0: reg_start = PCI_MAPREG_START; reg_end = PCI_MAPREG_END; break; case 1: /* PCI-PCI bridge */ reg_start = PCI_MAPREG_START; reg_end = PCI_MAPREG_PPB_END; break; case 2: /* PCI-CardBus bridge */ reg_start = PCI_MAPREG_START; reg_end = PCI_MAPREG_PCB_END; break; default: return (0); } pd->pd_msix_table = pci_alloc_msix_table(sc->sc_pc, pd->pd_tag); s = splhigh(); csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); if (csr & (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE)) pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr & ~(PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE)); for (reg = reg_start, i = 0; reg < reg_end; reg += 4, i++) { address = pci_conf_read(pc, tag, reg); pci_conf_write(pc, tag, reg, 0xffffffff); pd->pd_mask[i] = pci_conf_read(pc, tag, reg); pci_conf_write(pc, tag, reg, address); } if (csr & (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE)) pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr); splx(s); if ((PCI_CLASS(class) == PCI_CLASS_DISPLAY && PCI_SUBCLASS(class) == PCI_SUBCLASS_DISPLAY_VGA) || (PCI_CLASS(class) == PCI_CLASS_PREHISTORIC && PCI_SUBCLASS(class) == PCI_SUBCLASS_PREHISTORIC_VGA)) pd->pd_vga_decode = 1; pd->pd_dev = config_found_sm(&sc->sc_dev, &pa, pciprint, pcisubmatch); if (pd->pd_dev) pci_dev_postattach(pd->pd_dev, &pa); } return (ret); } int pci_detach_devices(struct pci_softc *sc, int flags) { struct pci_dev *pd, *next; int ret; ret = config_detach_children(&sc->sc_dev, flags); if (ret != 0) return (ret); for (pd = LIST_FIRST(&sc->sc_devs); pd != NULL; pd = next) { pci_free_msix_table(sc->sc_pc, pd->pd_tag, pd->pd_msix_table); next = LIST_NEXT(pd, pd_next); free(pd, M_DEVBUF, sizeof *pd); } LIST_INIT(&sc->sc_devs); return (0); } int pci_get_capability(pci_chipset_tag_t pc, pcitag_t tag, int capid, int *offset, pcireg_t *value) { pcireg_t reg; unsigned int ofs; reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); if (!(reg & PCI_STATUS_CAPLIST_SUPPORT)) return (0); /* Determine the Capability List Pointer register to start with. */ reg = pci_conf_read(pc, tag, PCI_BHLC_REG); switch (PCI_HDRTYPE_TYPE(reg)) { case 0: /* standard device header */ case 1: /* PCI-PCI bridge header */ ofs = PCI_CAPLISTPTR_REG; break; case 2: /* PCI-CardBus bridge header */ ofs = PCI_CARDBUS_CAPLISTPTR_REG; break; default: return (0); } ofs = PCI_CAPLIST_PTR(pci_conf_read(pc, tag, ofs)); while (ofs != 0) { /* * Some devices, like parts of the NVIDIA C51 chipset, * have a broken Capabilities List. So we need to do * a sanity check here. */ if ((ofs & 3) || (ofs < 0x40)) return (0); reg = pci_conf_read(pc, tag, ofs); if (PCI_CAPLIST_CAP(reg) == capid) { if (offset) *offset = ofs; if (value) *value = reg; return (1); } ofs = PCI_CAPLIST_NEXT(reg); } return (0); } int pci_get_ht_capability(pci_chipset_tag_t pc, pcitag_t tag, int capid, int *offset, pcireg_t *value) { pcireg_t reg; unsigned int ofs; if (pci_get_capability(pc, tag, PCI_CAP_HT, &ofs, NULL) == 0) return (0); while (ofs != 0) { #ifdef DIAGNOSTIC if ((ofs & 3) || (ofs < 0x40)) panic("pci_get_ht_capability"); #endif reg = pci_conf_read(pc, tag, ofs); if (PCI_HT_CAP(reg) == capid) { if (offset) *offset = ofs; if (value) *value = reg; return (1); } ofs = PCI_CAPLIST_NEXT(reg); } return (0); } int pci_get_ext_capability(pci_chipset_tag_t pc, pcitag_t tag, int capid, int *offset, pcireg_t *value) { pcireg_t reg; unsigned int ofs; /* Make sure this is a PCI Express device. */ if (pci_get_capability(pc, tag, PCI_CAP_PCIEXPRESS, NULL, NULL) == 0) return (0); /* Scan PCI Express extended capabilities. */ ofs = PCI_PCIE_ECAP; while (ofs != 0) { #ifdef DIAGNOSTIC if ((ofs & 3) || (ofs < PCI_PCIE_ECAP)) panic("pci_get_ext_capability"); #endif reg = pci_conf_read(pc, tag, ofs); if (PCI_PCIE_ECAP_ID(reg) == capid) { if (offset) *offset = ofs; if (value) *value = reg; return (1); } ofs = PCI_PCIE_ECAP_NEXT(reg); } return (0); } uint16_t pci_requester_id(pci_chipset_tag_t pc, pcitag_t tag) { int bus, dev, func; pci_decompose_tag(pc, tag, &bus, &dev, &func); return ((bus << 8) | (dev << 3) | func); } int pci_find_device(struct pci_attach_args *pa, int (*match)(struct pci_attach_args *)) { extern struct cfdriver pci_cd; struct device *pcidev; int i; for (i = 0; i < pci_cd.cd_ndevs; i++) { pcidev = pci_cd.cd_devs[i]; if (pcidev != NULL && pci_enumerate_bus((struct pci_softc *)pcidev, match, pa) != 0) return (1); } return (0); } int pci_get_powerstate(pci_chipset_tag_t pc, pcitag_t tag) { pcireg_t reg; int offset; if (pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &offset, 0)) { reg = pci_conf_read(pc, tag, offset + PCI_PMCSR); return (reg & PCI_PMCSR_STATE_MASK); } return (PCI_PMCSR_STATE_D0); } int pci_set_powerstate(pci_chipset_tag_t pc, pcitag_t tag, int state) { pcireg_t reg; int offset, ostate = state; /* * Warn the firmware that we are going to put the device * into the given state. */ pci_set_powerstate_md(pc, tag, state, 1); if (pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &offset, 0)) { if (state == PCI_PMCSR_STATE_D3) { /* * The PCI Power Management spec says we * should disable I/O and memory space as well * as bus mastering before we place the device * into D3. */ reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); reg &= ~PCI_COMMAND_IO_ENABLE; reg &= ~PCI_COMMAND_MEM_ENABLE; reg &= ~PCI_COMMAND_MASTER_ENABLE; pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, reg); } reg = pci_conf_read(pc, tag, offset + PCI_PMCSR); if ((reg & PCI_PMCSR_STATE_MASK) != state) { ostate = reg & PCI_PMCSR_STATE_MASK; pci_conf_write(pc, tag, offset + PCI_PMCSR, (reg & ~PCI_PMCSR_STATE_MASK) | state); if (state == PCI_PMCSR_STATE_D3 || ostate == PCI_PMCSR_STATE_D3) delay(10 * 1000); } } /* * Warn the firmware that the device is now in the given * state. */ pci_set_powerstate_md(pc, tag, state, 0); return (ostate); } #ifndef PCI_MACHDEP_ENUMERATE_BUS /* * Generic PCI bus enumeration routine. Used unless machine-dependent * code needs to provide something else. */ int pci_enumerate_bus(struct pci_softc *sc, int (*match)(struct pci_attach_args *), struct pci_attach_args *pap) { pci_chipset_tag_t pc = sc->sc_pc; int device, function, nfunctions, ret; int maxndevs = sc->sc_maxndevs; const struct pci_quirkdata *qd; pcireg_t id, bhlcr, cap; pcitag_t tag; /* * PCIe downstream ports and root ports should only forward * configuration requests for device number 0. However, not * all hardware implements this correctly, and some devices * will respond to other device numbers making the device show * up 32 times. Prevent this by only scanning a single * device. */ if (sc->sc_bridgetag && pci_get_capability(pc, *sc->sc_bridgetag, PCI_CAP_PCIEXPRESS, NULL, &cap)) { switch (PCI_PCIE_XCAP_TYPE(cap)) { case PCI_PCIE_XCAP_TYPE_RP: case PCI_PCIE_XCAP_TYPE_DOWN: case PCI_PCIE_XCAP_TYPE_PCI2PCIE: maxndevs = 1; break; } } for (device = 0; device < maxndevs; device++) { tag = pci_make_tag(pc, sc->sc_bus, device, 0); bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG); if (PCI_HDRTYPE_TYPE(bhlcr) > 2) continue; id = pci_conf_read(pc, tag, PCI_ID_REG); /* Invalid vendor ID value? */ if (PCI_VENDOR(id) == PCI_VENDOR_INVALID) continue; /* XXX Not invalid, but we've done this ~forever. */ if (PCI_VENDOR(id) == 0) continue; qd = pci_lookup_quirkdata(PCI_VENDOR(id), PCI_PRODUCT(id)); if (qd != NULL && (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0) nfunctions = 8; else if (qd != NULL && (qd->quirks & PCI_QUIRK_MONOFUNCTION) != 0) nfunctions = 1; else nfunctions = PCI_HDRTYPE_MULTIFN(bhlcr) ? 8 : 1; for (function = 0; function < nfunctions; function++) { tag = pci_make_tag(pc, sc->sc_bus, device, function); ret = pci_probe_device(sc, tag, match, pap); if (match != NULL && ret != 0) return (ret); } } return (0); } #endif /* PCI_MACHDEP_ENUMERATE_BUS */ int pci_reserve_resources(struct pci_attach_args *pa) { pci_chipset_tag_t pc = pa->pa_pc; pcitag_t tag = pa->pa_tag; pcireg_t bhlc, blr, bir, csr; pcireg_t addr, mask, type; bus_addr_t base, limit; bus_size_t size; int reg, reg_start, reg_end, reg_rom; int bus, dev, func; int sec, sub; int flags; int s; pci_decompose_tag(pc, tag, &bus, &dev, &func); bhlc = pci_conf_read(pc, tag, PCI_BHLC_REG); switch (PCI_HDRTYPE_TYPE(bhlc)) { case 0: reg_start = PCI_MAPREG_START; reg_end = PCI_MAPREG_END; reg_rom = PCI_ROM_REG; break; case 1: /* PCI-PCI bridge */ reg_start = PCI_MAPREG_START; reg_end = PCI_MAPREG_PPB_END; reg_rom = 0; /* 0x38 */ break; case 2: /* PCI-CardBus bridge */ reg_start = PCI_MAPREG_START; reg_end = PCI_MAPREG_PCB_END; reg_rom = 0; break; default: return (0); } csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); for (reg = reg_start; reg < reg_end; reg += 4) { if (!pci_mapreg_probe(pc, tag, reg, &type)) continue; if (pci_mapreg_info(pc, tag, reg, type, &base, &size, &flags)) continue; if (base == 0) continue; switch (type) { case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT: case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT: if (ISSET(flags, BUS_SPACE_MAP_PREFETCHABLE) && pa->pa_pmemex && extent_alloc_region(pa->pa_pmemex, base, size, EX_NOWAIT) == 0) { break; } #ifdef __sparc64__ /* * Certain SPARC T5 systems assign * non-prefetchable 64-bit BARs of their onboard * mpii(4) controllers addresses in the * prefetchable memory range. This is * (probably) safe, as reads from the device * registers mapped by these BARs are * side-effect free. So assume the firmware * knows what it is doing. */ if (base >= 0x100000000 && pa->pa_pmemex && extent_alloc_region(pa->pa_pmemex, base, size, EX_NOWAIT) == 0) { break; } #endif if (pa->pa_memex && extent_alloc_region(pa->pa_memex, base, size, EX_NOWAIT)) { if (csr & PCI_COMMAND_MEM_ENABLE) { printf("%d:%d:%d: mem address conflict" " 0x%lx/0x%lx\n", bus, dev, func, base, size); } pci_conf_write(pc, tag, reg, 0); if (type & PCI_MAPREG_MEM_TYPE_64BIT) pci_conf_write(pc, tag, reg + 4, 0); } break; case PCI_MAPREG_TYPE_IO: if (pa->pa_ioex && extent_alloc_region(pa->pa_ioex, base, size, EX_NOWAIT)) { if (csr & PCI_COMMAND_IO_ENABLE) { printf("%d:%d:%d: io address conflict" " 0x%lx/0x%lx\n", bus, dev, func, base, size); } pci_conf_write(pc, tag, reg, 0); } break; } if (type & PCI_MAPREG_MEM_TYPE_64BIT) reg += 4; } if (reg_rom != 0) { s = splhigh(); addr = pci_conf_read(pc, tag, PCI_ROM_REG); pci_conf_write(pc, tag, PCI_ROM_REG, ~PCI_ROM_ENABLE); mask = pci_conf_read(pc, tag, PCI_ROM_REG); pci_conf_write(pc, tag, PCI_ROM_REG, addr); splx(s); base = PCI_ROM_ADDR(addr); size = PCI_ROM_SIZE(mask); if (base != 0 && size != 0) { if (pa->pa_pmemex && extent_alloc_region(pa->pa_pmemex, base, size, EX_NOWAIT) && pa->pa_memex && extent_alloc_region(pa->pa_memex, base, size, EX_NOWAIT)) { if (addr & PCI_ROM_ENABLE) { printf("%d:%d:%d: rom address conflict" " 0x%lx/0x%lx\n", bus, dev, func, base, size); } pci_conf_write(pc, tag, PCI_ROM_REG, 0); } } } if (PCI_HDRTYPE_TYPE(bhlc) != 1) return (0); /* Figure out the I/O address range of the bridge. */ blr = pci_conf_read(pc, tag, PPB_REG_IOSTATUS); base = (blr & 0x000000f0) << 8; limit = (blr & 0x000f000) | 0x00000fff; blr = pci_conf_read(pc, tag, PPB_REG_IO_HI); base |= (blr & 0x0000ffff) << 16; limit |= (blr & 0xffff0000); if (limit > base) size = (limit - base + 1); else size = 0; if (pa->pa_ioex && base > 0 && size > 0) { if (extent_alloc_region(pa->pa_ioex, base, size, EX_NOWAIT)) { printf("%d:%d:%d: bridge io address conflict 0x%lx/0x%lx\n", bus, dev, func, base, size); blr &= 0xffff0000; blr |= 0x000000f0; pci_conf_write(pc, tag, PPB_REG_IOSTATUS, blr); } } /* Figure out the memory mapped I/O address range of the bridge. */ blr = pci_conf_read(pc, tag, PPB_REG_MEM); base = (blr & 0x0000fff0) << 16; limit = (blr & 0xfff00000) | 0x000fffff; if (limit > base) size = (limit - base + 1); else size = 0; if (pa->pa_memex && base > 0 && size > 0) { if (extent_alloc_region(pa->pa_memex, base, size, EX_NOWAIT)) { printf("%d:%d:%d: bridge mem address conflict 0x%lx/0x%lx\n", bus, dev, func, base, size); pci_conf_write(pc, tag, PPB_REG_MEM, 0x0000fff0); } } /* Figure out the prefetchable memory address range of the bridge. */ blr = pci_conf_read(pc, tag, PPB_REG_PREFMEM); base = (blr & 0x0000fff0) << 16; limit = (blr & 0xfff00000) | 0x000fffff; #ifdef __LP64__ blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_PREFBASE_HI32); base |= ((uint64_t)blr) << 32; blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_PREFLIM_HI32); limit |= ((uint64_t)blr) << 32; #endif if (limit > base) size = (limit - base + 1); else size = 0; if (pa->pa_pmemex && base > 0 && size > 0) { if (extent_alloc_region(pa->pa_pmemex, base, size, EX_NOWAIT)) { printf("%d:%d:%d: bridge mem address conflict 0x%lx/0x%lx\n", bus, dev, func, base, size); pci_conf_write(pc, tag, PPB_REG_PREFMEM, 0x0000fff0); } } else if (pa->pa_memex && base > 0 && size > 0) { if (extent_alloc_region(pa->pa_memex, base, size, EX_NOWAIT)) { printf("%d:%d:%d: bridge mem address conflict 0x%lx/0x%lx\n", bus, dev, func, base, size); pci_conf_write(pc, tag, PPB_REG_PREFMEM, 0x0000fff0); } } /* Figure out the bus range handled by the bridge. */ bir = pci_conf_read(pc, tag, PPB_REG_BUSINFO); sec = PPB_BUSINFO_SECONDARY(bir); sub = PPB_BUSINFO_SUBORDINATE(bir); if (pa->pa_busex && sub >= sec && sub > 0) { if (extent_alloc_region(pa->pa_busex, sec, sub - sec + 1, EX_NOWAIT)) { printf("%d:%d:%d: bridge bus conflict %d-%d\n", bus, dev, func, sec, sub); } } return (0); } /* * Vital Product Data (PCI 2.2) */ int pci_vpd_read(pci_chipset_tag_t pc, pcitag_t tag, int offset, int count, pcireg_t *data) { uint32_t reg; int ofs, i, j; KASSERT(data != NULL); if ((offset + count) >= PCI_VPD_ADDRESS_MASK) return (EINVAL); if (pci_get_capability(pc, tag, PCI_CAP_VPD, &ofs, &reg) == 0) return (ENXIO); for (i = 0; i < count; offset += sizeof(*data), i++) { reg &= 0x0000ffff; reg &= ~PCI_VPD_OPFLAG; reg |= PCI_VPD_ADDRESS(offset); pci_conf_write(pc, tag, ofs, reg); /* * PCI 2.2 does not specify how long we should poll * for completion nor whether the operation can fail. */ j = 0; do { if (j++ == 20) return (EIO); delay(4); reg = pci_conf_read(pc, tag, ofs); } while ((reg & PCI_VPD_OPFLAG) == 0); data[i] = pci_conf_read(pc, tag, PCI_VPD_DATAREG(ofs)); } return (0); } int pci_vpd_write(pci_chipset_tag_t pc, pcitag_t tag, int offset, int count, pcireg_t *data) { pcireg_t reg; int ofs, i, j; KASSERT(data != NULL); KASSERT((offset + count) < 0x7fff); if (pci_get_capability(pc, tag, PCI_CAP_VPD, &ofs, &reg) == 0) return (1); for (i = 0; i < count; offset += sizeof(*data), i++) { pci_conf_write(pc, tag, PCI_VPD_DATAREG(ofs), data[i]); reg &= 0x0000ffff; reg |= PCI_VPD_OPFLAG; reg |= PCI_VPD_ADDRESS(offset); pci_conf_write(pc, tag, ofs, reg); /* * PCI 2.2 does not specify how long we should poll * for completion nor whether the operation can fail. */ j = 0; do { if (j++ == 20) return (1); delay(1); reg = pci_conf_read(pc, tag, ofs); } while (reg & PCI_VPD_OPFLAG); } return (0); } int pci_matchbyid(struct pci_attach_args *pa, const struct pci_matchid *ids, int nent) { const struct pci_matchid *pm; int i; for (i = 0, pm = ids; i < nent; i++, pm++) if (PCI_VENDOR(pa->pa_id) == pm->pm_vid && PCI_PRODUCT(pa->pa_id) == pm->pm_pid) return (1); return (0); } void pci_disable_legacy_vga(struct device *dev) { struct pci_softc *pci; struct pci_dev *pd; /* XXX Until we attach the drm drivers directly to pci. */ while (dev->dv_parent->dv_cfdata->cf_driver != &pci_cd) dev = dev->dv_parent; pci = (struct pci_softc *)dev->dv_parent; LIST_FOREACH(pd, &pci->sc_devs, pd_next) { if (pd->pd_dev == dev) { pd->pd_vga_decode = 0; break; } } } #ifdef USER_PCICONF /* * This is the user interface to PCI configuration space. */ #include <sys/pciio.h> #include <sys/fcntl.h> #ifdef DEBUG #define PCIDEBUG(x) printf x #else #define PCIDEBUG(x) #endif void pci_disable_vga(pci_chipset_tag_t, pcitag_t); void pci_enable_vga(pci_chipset_tag_t, pcitag_t); void pci_route_vga(struct pci_softc *); void pci_unroute_vga(struct pci_softc *); int pciopen(dev_t dev, int oflags, int devtype, struct proc *p); int pciclose(dev_t dev, int flag, int devtype, struct proc *p); int pciioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p); int pciopen(dev_t dev, int oflags, int devtype, struct proc *p) { PCIDEBUG(("pciopen ndevs: %d\n" , pci_cd.cd_ndevs)); if (minor(dev) >= pci_ndomains) { return ENXIO; } #ifndef APERTURE if ((oflags & FWRITE) && securelevel > 0) { return EPERM; } #else if ((oflags & FWRITE) && securelevel > 0 && allowaperture == 0) { return EPERM; } #endif return (0); } int pciclose(dev_t dev, int flag, int devtype, struct proc *p) { PCIDEBUG(("pciclose\n")); pci_vga_proc = NULL; return (0); } int pciioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { struct pcisel *sel = (struct pcisel *)data; struct pci_io *io; struct pci_dev *pd; struct pci_rom *rom; int i, error; pcitag_t tag; struct pci_softc *pci; pci_chipset_tag_t pc; switch (cmd) { case PCIOCREAD: case PCIOCREADMASK: break; case PCIOCWRITE: if (!(flag & FWRITE)) return EPERM; break; case PCIOCGETROMLEN: case PCIOCGETROM: case PCIOCGETVPD: break; case PCIOCGETVGA: case PCIOCSETVGA: if (pci_vga_pci == NULL) return EINVAL; break; default: return ENOTTY; } for (i = 0; i < pci_cd.cd_ndevs; i++) { pci = pci_cd.cd_devs[i]; if (pci != NULL && pci->sc_domain == minor(dev) && pci->sc_bus == sel->pc_bus) break; } if (i >= pci_cd.cd_ndevs) return ENXIO; /* Check bounds */ if (pci->sc_bus >= 256 || sel->pc_dev >= pci_bus_maxdevs(pci->sc_pc, pci->sc_bus) || sel->pc_func >= 8) return EINVAL; pc = pci->sc_pc; LIST_FOREACH(pd, &pci->sc_devs, pd_next) { int bus, dev, func; pci_decompose_tag(pc, pd->pd_tag, &bus, &dev, &func); if (bus == sel->pc_bus && dev == sel->pc_dev && func == sel->pc_func) break; } if (pd == NULL) return ENXIO; tag = pci_make_tag(pc, sel->pc_bus, sel->pc_dev, sel->pc_func); switch (cmd) { case PCIOCREAD: io = (struct pci_io *)data; switch (io->pi_width) { case 4: /* Configuration space bounds check */ if (io->pi_reg < 0 || io->pi_reg >= pci_conf_size(pc, tag)) return EINVAL; /* Make sure the register is properly aligned */ if (io->pi_reg & 0x3) return EINVAL; io->pi_data = pci_conf_read(pc, tag, io->pi_reg); error = 0; break; default: error = EINVAL; break; } break; case PCIOCWRITE: io = (struct pci_io *)data; switch (io->pi_width) { case 4: /* Configuration space bounds check */ if (io->pi_reg < 0 || io->pi_reg >= pci_conf_size(pc, tag)) return EINVAL; /* Make sure the register is properly aligned */ if (io->pi_reg & 0x3) return EINVAL; pci_conf_write(pc, tag, io->pi_reg, io->pi_data); error = 0; break; default: error = EINVAL; break; } break; case PCIOCREADMASK: io = (struct pci_io *)data; if (io->pi_width != 4 || io->pi_reg & 0x3 || io->pi_reg < PCI_MAPREG_START || io->pi_reg >= PCI_MAPREG_END) return (EINVAL); i = (io->pi_reg - PCI_MAPREG_START) / 4; io->pi_data = pd->pd_mask[i]; error = 0; break; case PCIOCGETROMLEN: case PCIOCGETROM: { pcireg_t addr, mask, bhlc; bus_space_handle_t h; bus_size_t len, off; char buf[256]; int s; rom = (struct pci_rom *)data; bhlc = pci_conf_read(pc, tag, PCI_BHLC_REG); if (PCI_HDRTYPE_TYPE(bhlc) != 0) return (ENODEV); s = splhigh(); addr = pci_conf_read(pc, tag, PCI_ROM_REG); pci_conf_write(pc, tag, PCI_ROM_REG, ~PCI_ROM_ENABLE); mask = pci_conf_read(pc, tag, PCI_ROM_REG); pci_conf_write(pc, tag, PCI_ROM_REG, addr); splx(s); /* * Section 6.2.5.2 `Expansion ROM Base Address Register', * * tells us that only the upper 21 bits are writable. * This means that the size of a ROM must be a * multiple of 2 KB. So reading the ROM in chunks of * 256 bytes should work just fine. */ if ((PCI_ROM_ADDR(addr) == 0 || PCI_ROM_SIZE(mask) % sizeof(buf)) != 0) return (ENODEV); /* If we're just after the size, skip reading the ROM. */ if (cmd == PCIOCGETROMLEN) { error = 0; goto fail; } if (rom->pr_romlen < PCI_ROM_SIZE(mask)) { error = ENOMEM; goto fail; } error = bus_space_map(pci->sc_memt, PCI_ROM_ADDR(addr), PCI_ROM_SIZE(mask), 0, &h); if (error) goto fail; off = 0; len = PCI_ROM_SIZE(mask); while (len > 0 && error == 0) { s = splhigh(); pci_conf_write(pc, tag, PCI_ROM_REG, addr | PCI_ROM_ENABLE); bus_space_read_region_1(pci->sc_memt, h, off, buf, sizeof(buf)); pci_conf_write(pc, tag, PCI_ROM_REG, addr); splx(s); error = copyout(buf, rom->pr_rom + off, sizeof(buf)); off += sizeof(buf); len -= sizeof(buf); } bus_space_unmap(pci->sc_memt, h, PCI_ROM_SIZE(mask)); fail: rom->pr_romlen = PCI_ROM_SIZE(mask); break; } case PCIOCGETVPD: { struct pci_vpd_req *pv = (struct pci_vpd_req *)data; pcireg_t *data; size_t len; unsigned int i; int s; CTASSERT(sizeof(*data) == sizeof(*pv->pv_data)); data = mallocarray(pv->pv_count, sizeof(*data), M_TEMP, M_WAITOK|M_CANFAIL); if (data == NULL) { error = ENOMEM; break; } s = splhigh(); error = pci_vpd_read(pc, tag, pv->pv_offset, pv->pv_count, data); splx(s); len = pv->pv_count * sizeof(*pv->pv_data); if (error == 0) { for (i = 0; i < pv->pv_count; i++) data[i] = letoh32(data[i]); error = copyout(data, pv->pv_data, len); } free(data, M_TEMP, len); break; } case PCIOCGETVGA: { struct pci_vga *vga = (struct pci_vga *)data; struct pci_dev *pd; int bus, dev, func; vga->pv_decode = 0; LIST_FOREACH(pd, &pci->sc_devs, pd_next) { pci_decompose_tag(pc, pd->pd_tag, NULL, &dev, &func); if (dev == sel->pc_dev && func == sel->pc_func) { if (pd->pd_vga_decode) vga->pv_decode = PCI_VGA_IO_ENABLE | PCI_VGA_MEM_ENABLE; break; } } pci_decompose_tag(pci_vga_pci->sc_pc, pci_vga_tag, &bus, &dev, &func); vga->pv_sel.pc_bus = bus; vga->pv_sel.pc_dev = dev; vga->pv_sel.pc_func = func; error = 0; break; } case PCIOCSETVGA: { struct pci_vga *vga = (struct pci_vga *)data; int bus, dev, func; switch (vga->pv_lock) { case PCI_VGA_UNLOCK: case PCI_VGA_LOCK: case PCI_VGA_TRYLOCK: break; default: return (EINVAL); } if (vga->pv_lock == PCI_VGA_UNLOCK) { if (pci_vga_proc != p) return (EINVAL); pci_vga_proc = NULL; wakeup(&pci_vga_proc); return (0); } while (pci_vga_proc != p && pci_vga_proc != NULL) { if (vga->pv_lock == PCI_VGA_TRYLOCK) return (EBUSY); error = tsleep_nsec(&pci_vga_proc, PLOCK | PCATCH, "vgalk", INFSLP); if (error) return (error); } pci_vga_proc = p; pci_decompose_tag(pci_vga_pci->sc_pc, pci_vga_tag, &bus, &dev, &func); if (bus != vga->pv_sel.pc_bus || dev != vga->pv_sel.pc_dev || func != vga->pv_sel.pc_func) { pci_disable_vga(pci_vga_pci->sc_pc, pci_vga_tag); if (pci != pci_vga_pci) { pci_unroute_vga(pci_vga_pci); pci_route_vga(pci); pci_vga_pci = pci; } pci_enable_vga(pc, tag); pci_vga_tag = tag; } error = 0; break; } default: error = ENOTTY; break; } return (error); } void pci_disable_vga(pci_chipset_tag_t pc, pcitag_t tag) { pcireg_t csr; csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); csr &= ~(PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE); pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr); } void pci_enable_vga(pci_chipset_tag_t pc, pcitag_t tag) { pcireg_t csr; csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); csr |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE; pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr); } void pci_route_vga(struct pci_softc *sc) { pci_chipset_tag_t pc = sc->sc_pc; pcireg_t bc; if (sc->sc_bridgetag == NULL) return; bc = pci_conf_read(pc, *sc->sc_bridgetag, PPB_REG_BRIDGECONTROL); bc |= PPB_BC_VGA_ENABLE; pci_conf_write(pc, *sc->sc_bridgetag, PPB_REG_BRIDGECONTROL, bc); pci_route_vga((struct pci_softc *)sc->sc_dev.dv_parent->dv_parent); } void pci_unroute_vga(struct pci_softc *sc) { pci_chipset_tag_t pc = sc->sc_pc; pcireg_t bc; if (sc->sc_bridgetag == NULL) return; bc = pci_conf_read(pc, *sc->sc_bridgetag, PPB_REG_BRIDGECONTROL); bc &= ~PPB_BC_VGA_ENABLE; pci_conf_write(pc, *sc->sc_bridgetag, PPB_REG_BRIDGECONTROL, bc); pci_unroute_vga((struct pci_softc *)sc->sc_dev.dv_parent->dv_parent); } #endif /* USER_PCICONF */ int pci_primary_vga(struct pci_attach_args *pa) { /* XXX For now, only handle the first PCI domain. */ if (pa->pa_domain != 0) return (0); if ((PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY || PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_DISPLAY_VGA) && (PCI_CLASS(pa->pa_class) != PCI_CLASS_PREHISTORIC || PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_PREHISTORIC_VGA)) return (0); if ((pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) & (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE)) != (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE)) return (0); pci_vga_tag = pa->pa_tag; return (1); } #ifdef __HAVE_PCI_MSIX struct msix_vector * pci_alloc_msix_table(pci_chipset_tag_t pc, pcitag_t tag) { struct msix_vector *table; pcireg_t reg; int tblsz; if (pci_get_capability(pc, tag, PCI_CAP_MSIX, NULL, &reg) == 0) return NULL; tblsz = PCI_MSIX_MC_TBLSZ(reg) + 1; table = mallocarray(tblsz, sizeof(*table), M_DEVBUF, M_WAITOK); return table; } void pci_free_msix_table(pci_chipset_tag_t pc, pcitag_t tag, struct msix_vector *table) { pcireg_t reg; int tblsz; if (pci_get_capability(pc, tag, PCI_CAP_MSIX, NULL, &reg) == 0) return; tblsz = PCI_MSIX_MC_TBLSZ(reg) + 1; free(table, M_DEVBUF, tblsz * sizeof(*table)); } void pci_suspend_msix(pci_chipset_tag_t pc, pcitag_t tag, bus_space_tag_t memt, pcireg_t *mc, struct msix_vector *table) { bus_space_handle_t memh; pcireg_t reg; int tblsz, i; if (pci_get_capability(pc, tag, PCI_CAP_MSIX, NULL, &reg) == 0) return; KASSERT(table != NULL); if (pci_msix_table_map(pc, tag, memt, &memh)) return; tblsz = PCI_MSIX_MC_TBLSZ(reg) + 1; for (i = 0; i < tblsz; i++) { table[i].mv_ma = bus_space_read_4(memt, memh, PCI_MSIX_MA(i)); table[i].mv_mau32 = bus_space_read_4(memt, memh, PCI_MSIX_MAU32(i)); table[i].mv_md = bus_space_read_4(memt, memh, PCI_MSIX_MD(i)); table[i].mv_vc = bus_space_read_4(memt, memh, PCI_MSIX_VC(i)); } pci_msix_table_unmap(pc, tag, memt, memh); *mc = reg; } void pci_resume_msix(pci_chipset_tag_t pc, pcitag_t tag, bus_space_tag_t memt, pcireg_t mc, struct msix_vector *table) { bus_space_handle_t memh; pcireg_t reg; int tblsz, i; int off; if (pci_get_capability(pc, tag, PCI_CAP_MSIX, &off, &reg) == 0) return; KASSERT(table != NULL); if (pci_msix_table_map(pc, tag, memt, &memh)) return; tblsz = PCI_MSIX_MC_TBLSZ(reg) + 1; for (i = 0; i < tblsz; i++) { bus_space_write_4(memt, memh, PCI_MSIX_MA(i), table[i].mv_ma); bus_space_write_4(memt, memh, PCI_MSIX_MAU32(i), table[i].mv_mau32); bus_space_write_4(memt, memh, PCI_MSIX_MD(i), table[i].mv_md); bus_space_barrier(memt, memh, PCI_MSIX_MA(i), 16, BUS_SPACE_BARRIER_WRITE); bus_space_write_4(memt, memh, PCI_MSIX_VC(i), table[i].mv_vc); bus_space_barrier(memt, memh, PCI_MSIX_VC(i), 4, BUS_SPACE_BARRIER_WRITE); } pci_msix_table_unmap(pc, tag, memt, memh); pci_conf_write(pc, tag, off, mc); } int pci_intr_msix_count(struct pci_attach_args *pa) { pcireg_t reg; if ((pa->pa_flags & PCI_FLAGS_MSI_ENABLED) == 0) return (0); if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_MSIX, NULL, &reg) == 0) return (0); return (PCI_MSIX_MC_TBLSZ(reg) + 1); } #else /* __HAVE_PCI_MSIX */ struct msix_vector * pci_alloc_msix_table(pci_chipset_tag_t pc, pcitag_t tag) { return NULL; } void pci_free_msix_table(pci_chipset_tag_t pc, pcitag_t tag, struct msix_vector *table) { } void pci_suspend_msix(pci_chipset_tag_t pc, pcitag_t tag, bus_space_tag_t memt, pcireg_t *mc, struct msix_vector *table) { } void pci_resume_msix(pci_chipset_tag_t pc, pcitag_t tag, bus_space_tag_t memt, pcireg_t mc, struct msix_vector *table) { } int pci_intr_msix_count(struct pci_attach_args *pa) { return (0); } #endif /* __HAVE_PCI_MSIX */
36 36 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 /* $OpenBSD: vfs_init.c,v 1.44 2024/05/20 09:11:21 mvs Exp $ */ /* $NetBSD: vfs_init.c,v 1.6 1996/02/09 19:00:58 christos Exp $ */ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed * to Berkeley by John Heidemann of the UCLA Ficus project. * * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)vfs_init.c 8.3 (Berkeley) 1/4/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/mount.h> #include <sys/namei.h> #include <sys/vnode.h> #include <sys/pool.h> struct pool namei_pool; /* This defines the root filesystem. */ struct vnode *rootvnode; /* Set up the filesystem operations for vnodes. */ static struct vfsconf vfsconflist[] = { #ifdef FFS { &ffs_vfsops, MOUNT_FFS, 1, 0, MNT_LOCAL | MNT_SWAPPABLE, sizeof(struct ufs_args) }, #endif #ifdef MFS { &mfs_vfsops, MOUNT_MFS, 3, 0, MNT_LOCAL, sizeof(struct mfs_args) }, #endif #ifdef EXT2FS { &ext2fs_vfsops, MOUNT_EXT2FS, 17, 0, MNT_LOCAL | MNT_SWAPPABLE, sizeof(struct ufs_args) }, #endif #ifdef CD9660 { &cd9660_vfsops, MOUNT_CD9660, 14, 0, MNT_LOCAL, sizeof(struct iso_args) }, #endif #ifdef MSDOSFS { &msdosfs_vfsops, MOUNT_MSDOS, 4, 0, MNT_LOCAL | MNT_SWAPPABLE, sizeof(struct msdosfs_args) }, #endif #ifdef NFSCLIENT { &nfs_vfsops, MOUNT_NFS, 2, 0, MNT_SWAPPABLE, sizeof(struct nfs_args) }, #endif #ifdef NTFS { &ntfs_vfsops, MOUNT_NTFS, 6, 0, MNT_LOCAL, sizeof(struct ntfs_args) }, #endif #ifdef UDF { &udf_vfsops, MOUNT_UDF, 13, 0, MNT_LOCAL, sizeof(struct iso_args) }, #endif #ifdef FUSE { &fusefs_vfsops, MOUNT_FUSEFS, 18, 0, 0, sizeof(struct fusefs_args) }, #endif #ifdef TMPFS { &tmpfs_vfsops, MOUNT_TMPFS, 19, 0, MNT_LOCAL, sizeof(struct tmpfs_args) }, #endif }; /* * Initially the size of the list, vfsinit will set maxvfsconf * to the highest defined type number. */ int maxvfsconf = sizeof(vfsconflist) / sizeof(struct vfsconf); /* Initialize the vnode structures and initialize each file system type. */ void vfsinit(void) { struct vfsconf *vfsp; int i; pool_init(&namei_pool, MAXPATHLEN, 0, IPL_NONE, PR_WAITOK, "namei", NULL); /* Initialize the vnode table. */ vntblinit(); /* Initialize the vnode name cache. */ nchinit(); maxvfsconf = 0; for (i = 0; i < nitems(vfsconflist); i++) { vfsp = &vfsconflist[i]; if (vfsp->vfc_typenum > maxvfsconf) maxvfsconf = vfsp->vfc_typenum; if (vfsp->vfc_vfsops->vfs_init != NULL) (*vfsp->vfc_vfsops->vfs_init)(vfsp); } } struct vfsconf * vfs_byname(const char *name) { int i; for (i = 0; i < nitems(vfsconflist); i++) { if (strcmp(vfsconflist[i].vfc_name, name) == 0) return &vfsconflist[i]; } return NULL; } struct vfsconf * vfs_bytypenum(int typenum) { int i; for (i = 0; i < nitems(vfsconflist); i++) { if (vfsconflist[i].vfc_typenum == typenum) return &vfsconflist[i]; } return NULL; }
4 2 2 2 2 2 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 /* $OpenBSD: wstpad.c,v 1.34 2024/03/25 13:01:49 mvs Exp $ */ /* * Copyright (c) 2015, 2016 Ulf Brosziewski * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * touchpad input processing */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/proc.h> #include <sys/systm.h> #include <sys/signalvar.h> #include <sys/timeout.h> #include <dev/wscons/wsconsio.h> #include <dev/wscons/wsmousevar.h> #include <dev/wscons/wseventvar.h> #include <dev/wscons/wsmouseinput.h> #define BTNMASK(n) ((n) > 0 && (n) <= 32 ? 1 << ((n) - 1) : 0) #define LEFTBTN BTNMASK(1) #define MIDDLEBTN BTNMASK(2) #define RIGHTBTN BTNMASK(3) #define PRIMARYBTN LEFTBTN #define PRIMARYBTN_CLICKED(tp) ((tp)->btns_sync & PRIMARYBTN & (tp)->btns) #define PRIMARYBTN_RELEASED(tp) ((tp)->btns_sync & PRIMARYBTN & ~(tp)->btns) #define IS_MT(tp) ((tp)->features & WSTPAD_MT) #define DISABLE(tp) ((tp)->features & WSTPAD_DISABLE) /* * Ratios to the height or width of the touchpad surface, in * [*.12] fixed-point format: */ #define V_EDGE_RATIO_DEFAULT 205 #define B_EDGE_RATIO_DEFAULT 410 #define T_EDGE_RATIO_DEFAULT 512 #define CENTER_RATIO_DEFAULT 512 #define TAP_MAXTIME_DEFAULT 180 #define TAP_CLICKTIME_DEFAULT 180 #define TAP_LOCKTIME_DEFAULT 0 #define TAP_BTNMAP_SIZE 3 #define CLICKDELAY_MS 20 #define FREEZE_MS 100 #define MATCHINTERVAL_MS 45 #define STOPINTERVAL_MS 55 #define MAG_LOW (10 << 12) #define MAG_MEDIUM (18 << 12) enum tpad_handlers { SOFTBUTTON_HDLR, TOPBUTTON_HDLR, TAP_HDLR, F2SCROLL_HDLR, EDGESCROLL_HDLR, CLICK_HDLR, }; enum tap_state { TAP_DETECT, TAP_IGNORE, TAP_LIFTED, TAP_LOCKED, TAP_LOCKED_DRAG, }; enum tpad_cmd { CLEAR_MOTION_DELTAS, SOFTBUTTON_DOWN, SOFTBUTTON_UP, TAPBUTTON_SYNC, TAPBUTTON_DOWN, TAPBUTTON_UP, VSCROLL, HSCROLL, }; /* * tpad_touch.flags: */ #define L_EDGE (1 << 0) #define R_EDGE (1 << 1) #define T_EDGE (1 << 2) #define B_EDGE (1 << 3) #define THUMB (1 << 4) #define EDGES (L_EDGE | R_EDGE | T_EDGE | B_EDGE) /* * A touch is "centered" if it does not start and remain at the top * edge or one of the vertical edges. Two-finger scrolling and tapping * require that at least one touch is centered. */ #define CENTERED(t) (((t)->flags & (L_EDGE | R_EDGE | T_EDGE)) == 0) enum touchstates { TOUCH_NONE, TOUCH_BEGIN, TOUCH_UPDATE, TOUCH_END, }; struct tpad_touch { u_int flags; enum touchstates state; int x; int y; int dir; struct timespec start; struct timespec match; struct position *pos; struct { int x; int y; struct timespec time; } orig; }; /* * wstpad.features */ #define WSTPAD_SOFTBUTTONS (1 << 0) #define WSTPAD_SOFTMBTN (1 << 1) #define WSTPAD_TOPBUTTONS (1 << 2) #define WSTPAD_TWOFINGERSCROLL (1 << 3) #define WSTPAD_EDGESCROLL (1 << 4) #define WSTPAD_HORIZSCROLL (1 << 5) #define WSTPAD_SWAPSIDES (1 << 6) #define WSTPAD_DISABLE (1 << 7) #define WSTPAD_MTBUTTONS (1 << 8) #define WSTPAD_MT (1U << 31) struct wstpad { u_int features; u_int handlers; /* * t always points into the tpad_touches array, which has at * least one element. If there is more than one, t selects * the pointer-controlling touch. */ struct tpad_touch *t; struct tpad_touch *tpad_touches; u_int mtcycle; u_int ignore; int contacts; int prev_contacts; u_int btns; u_int btns_sync; int ratio; struct timespec time; u_int freeze; struct timespec freeze_ts; /* edge coordinates */ struct { int left; int right; int top; int bottom; int center; int center_left; int center_right; int low; } edge; struct { /* ratios to the surface width or height */ int left_edge; int right_edge; int top_edge; int bottom_edge; int center_width; /* two-finger contacts */ int f2pressure; int f2width; /* MTBUTTONS: distance limit for two-finger clicks */ int mtbtn_maxdist; } params; /* handler state and configuration: */ u_int softbutton; u_int sbtnswap; struct { enum tap_state state; int contacts; int valid; u_int pending; u_int button; int masked; int maxdist; struct timeout to; /* parameters: */ struct timespec maxtime; int clicktime; int locktime; u_int btnmap[TAP_BTNMAP_SIZE]; } tap; struct { int dz; int dw; int hdist; int vdist; int mag; } scroll; }; static const struct timespec match_interval = { .tv_sec = 0, .tv_nsec = MATCHINTERVAL_MS * 1000000 }; static const struct timespec stop_interval = { .tv_sec = 0, .tv_nsec = STOPINTERVAL_MS * 1000000 }; /* * Coordinates in the wstpad struct are "normalized" device coordinates, * the orientation is left-to-right and upward. */ static inline int normalize_abs(struct axis_filter *filter, int val) { return (filter->inv ? filter->inv - val : val); } static inline int normalize_rel(struct axis_filter *filter, int val) { return (filter->inv ? -val : val); } /* * Directions of motion are represented by numbers in the range 0 - 11, * corresponding to clockwise counted circle sectors: * * 11 | 0 * 10 | 1 * 9 | 2 * -------+------- * 8 | 3 * 7 | 4 * 6 | 5 * */ /* Tangent constants in [*.12] fixed-point format: */ #define TAN_DEG_60 7094 #define TAN_DEG_30 2365 #define NORTH(d) ((d) == 0 || (d) == 11) #define SOUTH(d) ((d) == 5 || (d) == 6) #define EAST(d) ((d) == 2 || (d) == 3) #define WEST(d) ((d) == 8 || (d) == 9) static inline int direction(int dx, int dy, int ratio) { int rdy, dir = -1; if (dx || dy) { rdy = abs(dy) * ratio; if (abs(dx) * TAN_DEG_60 < rdy) dir = 0; else if (abs(dx) * TAN_DEG_30 < rdy) dir = 1; else dir = 2; if ((dx < 0) != (dy < 0)) dir = 5 - dir; if (dx < 0) dir += 6; } return dir; } static inline int dircmp(int dir1, int dir2) { int diff = abs(dir1 - dir2); return (diff <= 6 ? diff : 12 - diff); } /* * Update direction and timespec attributes for a touch. They are used to * determine whether it is moving - or resting - stably. * * The callers pass touches from the current frame and the touches that are * no longer present in the update cycle to this function. Even though this * ensures that pairs of zero deltas do not result from stale coordinates, * zero deltas do not reset the state immediately. A short time span - the * "stop interval" - must pass before the state is cleared, which is * necessary because some touchpads report intermediate stops when a touch * is moving very slowly. */ void wstpad_set_direction(struct wstpad *tp, struct tpad_touch *t, int dx, int dy) { int dir; struct timespec ts; if (t->state != TOUCH_UPDATE) { t->dir = -1; memcpy(&t->start, &tp->time, sizeof(struct timespec)); return; } dir = direction(dx, dy, tp->ratio); if (dir >= 0) { if (t->dir < 0 || dircmp(dir, t->dir) > 1) { memcpy(&t->start, &tp->time, sizeof(struct timespec)); } t->dir = dir; memcpy(&t->match, &tp->time, sizeof(struct timespec)); } else if (t->dir >= 0) { timespecsub(&tp->time, &t->match, &ts); if (timespeccmp(&ts, &stop_interval, >=)) { t->dir = -1; memcpy(&t->start, &t->match, sizeof(struct timespec)); } } } /* * Make a rough, but quick estimation of the speed of a touch. Its * distance to the previous position is scaled by factors derived * from the average update rate and the deceleration parameter * (filter.dclr). The unit of the result is: * (filter.dclr / 100) device units per millisecond * * Magnitudes are returned in [*.12] fixed-point format. For purposes * of filtering, they are divided into medium and high speeds * (> MAG_MEDIUM), low speeds, and very low speeds (< MAG_LOW). * * The scale factors are not affected if deceleration is turned off. */ static inline int magnitude(struct wsmouseinput *input, int dx, int dy) { int h, v; h = abs(dx) * input->filter.h.mag_scale; v = abs(dy) * input->filter.v.mag_scale; /* Return an "alpha-max-plus-beta-min" approximation: */ return (h >= v ? h + 3 * v / 8 : v + 3 * h / 8); } /* * Treat a touch as stable if it is moving at a medium or high speed, * if it is moving continuously, or if it has stopped for a certain * time span. */ int wstpad_is_stable(struct wsmouseinput *input, struct tpad_touch *t) { struct timespec ts; if (t->dir >= 0) { if (magnitude(input, t->pos->dx, t->pos->dy) > MAG_MEDIUM) return (1); timespecsub(&t->match, &t->start, &ts); } else { timespecsub(&input->tp->time, &t->start, &ts); } return (timespeccmp(&ts, &match_interval, >=)); } /* * If a touch starts in an edge area, pointer movement will be * suppressed as long as it stays in that area. */ static inline u_int edge_flags(struct wstpad *tp, int x, int y) { u_int flags = 0; if (x < tp->edge.left) flags |= L_EDGE; else if (x >= tp->edge.right) flags |= R_EDGE; if (y < tp->edge.bottom) flags |= B_EDGE; else if (y >= tp->edge.top) flags |= T_EDGE; return (flags); } static inline struct tpad_touch * get_2nd_touch(struct wsmouseinput *input) { struct wstpad *tp = input->tp; int slot; if (IS_MT(tp)) { slot = ffs(input->mt.touches & ~(input->mt.ptr | tp->ignore)); if (slot) return &tp->tpad_touches[--slot]; } return NULL; } /* Suppress pointer motion for a short period of time. */ static inline void set_freeze_ts(struct wstpad *tp, int sec, int ms) { tp->freeze_ts.tv_sec = sec; tp->freeze_ts.tv_nsec = ms * 1000000; timespecadd(&tp->time, &tp->freeze_ts, &tp->freeze_ts); } /* Return TRUE if two-finger- or edge-scrolling would be valid. */ int wstpad_scroll_coords(struct wsmouseinput *input, int *dx, int *dy) { struct wstpad *tp = input->tp; if (tp->contacts != tp->prev_contacts || tp->btns || tp->btns_sync) { tp->scroll.dz = 0; tp->scroll.dw = 0; return (0); } if ((input->motion.sync & SYNC_POSITION) == 0) return (0); /* * Try to exclude accidental scroll events by checking whether the * pointer-controlling touch is stable. The check, which may cause * a short delay, is only applied initially, a touch that stops and * resumes scrolling is not affected. */ if (tp->scroll.dz || tp->scroll.dw || wstpad_is_stable(input, tp->t)) { *dx = normalize_rel(&input->filter.h, input->motion.pos.dx); *dy = normalize_rel(&input->filter.v, input->motion.pos.dy); return (*dx || *dy); } return (0); } void wstpad_scroll(struct wstpad *tp, int dx, int dy, int mag, u_int *cmds) { int dz, dw, n = 1; /* * The function applies strong deceleration, but only to input with * very low speeds. A higher threshold might make applications * without support for precision scrolling appear unresponsive. */ mag = tp->scroll.mag = imin(MAG_MEDIUM, (mag + 3 * tp->scroll.mag) / 4); if (mag < MAG_LOW) n = (MAG_LOW - mag) / 4096 + 1; if (dy && tp->scroll.vdist) { if (tp->scroll.dw) { /* * Before switching the axis, wstpad_scroll_coords() * should check again whether the movement is stable. */ tp->scroll.dw = 0; return; } dz = -dy * 4096 / (tp->scroll.vdist * n); if (tp->scroll.dz) { if ((dy < 0) != (tp->scroll.dz > 0)) tp->scroll.dz = -tp->scroll.dz; dz = (dz + 3 * tp->scroll.dz) / 4; } if (dz) { tp->scroll.dz = dz; *cmds |= 1 << VSCROLL; } } else if (dx && tp->scroll.hdist) { if (tp->scroll.dz) { tp->scroll.dz = 0; return; } dw = dx * 4096 / (tp->scroll.hdist * n); if (tp->scroll.dw) { if ((dx > 0) != (tp->scroll.dw > 0)) tp->scroll.dw = -tp->scroll.dw; dw = (dw + 3 * tp->scroll.dw) / 4; } if (dw) { tp->scroll.dw = dw; *cmds |= 1 << HSCROLL; } } } void wstpad_f2scroll(struct wsmouseinput *input, u_int *cmds) { struct wstpad *tp = input->tp; struct tpad_touch *t2; int dir, dx, dy, centered; if (tp->ignore == 0) { if (tp->contacts != 2) return; } else if (tp->contacts != 3 || (tp->ignore == input->mt.ptr)) { return; } if (!wstpad_scroll_coords(input, &dx, &dy)) return; dir = tp->t->dir; if (!(NORTH(dir) || SOUTH(dir))) dy = 0; if (!(EAST(dir) || WEST(dir))) dx = 0; if (dx || dy) { centered = CENTERED(tp->t); if (IS_MT(tp)) { t2 = get_2nd_touch(input); if (t2 == NULL) return; dir = t2->dir; if ((dy > 0 && !NORTH(dir)) || (dy < 0 && !SOUTH(dir))) return; if ((dx > 0 && !EAST(dir)) || (dx < 0 && !WEST(dir))) return; if (!wstpad_is_stable(input, t2) && !(tp->scroll.dz || tp->scroll.dw)) return; centered |= CENTERED(t2); } if (centered) { wstpad_scroll(tp, dx, dy, magnitude(input, dx, dy), cmds); set_freeze_ts(tp, 0, FREEZE_MS); } } } void wstpad_edgescroll(struct wsmouseinput *input, u_int *cmds) { struct wstpad *tp = input->tp; struct tpad_touch *t = tp->t; u_int v_edge, b_edge; int dx, dy; if (!wstpad_scroll_coords(input, &dx, &dy) || tp->contacts != 1) return; v_edge = (tp->features & WSTPAD_SWAPSIDES) ? L_EDGE : R_EDGE; b_edge = (tp->features & WSTPAD_HORIZSCROLL) ? B_EDGE : 0; if ((t->flags & v_edge) == 0) dy = 0; if ((t->flags & b_edge) == 0) dx = 0; if (dx || dy) wstpad_scroll(tp, dx, dy, magnitude(input, dx, dy), cmds); } static inline u_int sbtn(struct wstpad *tp, int x, int y) { if (y >= tp->edge.bottom) return (0); if ((tp->features & WSTPAD_SOFTMBTN) && x >= tp->edge.center_left && x < tp->edge.center_right) return (MIDDLEBTN); return ((x < tp->edge.center ? LEFTBTN : RIGHTBTN) ^ tp->sbtnswap); } static inline u_int top_sbtn(struct wstpad *tp, int x, int y) { if (y < tp->edge.top) return (0); if (x < tp->edge.center_left) return (LEFTBTN ^ tp->sbtnswap); return (x > tp->edge.center_right ? (RIGHTBTN ^ tp->sbtnswap) : MIDDLEBTN); } u_int wstpad_get_sbtn(struct wsmouseinput *input, int top) { struct wstpad *tp = input->tp; struct tpad_touch *t = tp->t; u_int btn; btn = 0; if (tp->contacts) { btn = top ? top_sbtn(tp, t->x, t->y) : sbtn(tp, t->x, t->y); /* * If there is no middle-button area, but contacts in both * halves of the edge zone, generate a middle-button event: */ if (btn && IS_MT(tp) && tp->contacts == 2 && !top && !(tp->features & WSTPAD_SOFTMBTN)) { if ((t = get_2nd_touch(input)) != NULL) btn |= sbtn(tp, t->x, t->y); if (btn == (LEFTBTN | RIGHTBTN)) btn = MIDDLEBTN; } } return (btn != PRIMARYBTN ? btn : 0); } int wstpad_mtbtn_contacts(struct wsmouseinput *input) { struct wstpad *tp = input->tp; struct tpad_touch *t; int dx, dy, dist, limit; if (tp->ignore != 0) return (tp->contacts - 1); if (tp->contacts == 2 && (t = get_2nd_touch(input)) != NULL) { dx = abs(t->x - tp->t->x) << 12; dy = abs(t->y - tp->t->y) * tp->ratio; dist = (dx >= dy ? dx + 3 * dy / 8 : dy + 3 * dx / 8); limit = tp->params.mtbtn_maxdist << 12; if (input->mt.ptr_mask != 0) limit = limit * 2 / 3; if (dist > limit) return (1); } return (tp->contacts); } u_int wstpad_get_mtbtn(struct wsmouseinput *input) { int contacts = wstpad_mtbtn_contacts(input); return (contacts == 2 ? RIGHTBTN : (contacts == 3 ? MIDDLEBTN : 0)); } void wstpad_softbuttons(struct wsmouseinput *input, u_int *cmds, int hdlr) { struct wstpad *tp = input->tp; int top = (hdlr == TOPBUTTON_HDLR); if (tp->softbutton && PRIMARYBTN_RELEASED(tp)) { *cmds |= 1 << SOFTBUTTON_UP; return; } if (tp->softbutton == 0 && PRIMARYBTN_CLICKED(tp)) { tp->softbutton = ((tp->features & WSTPAD_MTBUTTONS) ? wstpad_get_mtbtn(input) : wstpad_get_sbtn(input, top)); if (tp->softbutton) *cmds |= 1 << SOFTBUTTON_DOWN; } } /* Check whether the duration of t is within the tap limit. */ int wstpad_is_tap(struct wstpad *tp, struct tpad_touch *t) { struct timespec ts; timespecsub(&tp->time, &t->orig.time, &ts); return (timespeccmp(&ts, &tp->tap.maxtime, <)); } /* * At least one MT touch must remain close to its origin and end * in the main area. The same conditions apply to one-finger taps * on single-touch devices. */ void wstpad_tap_filter(struct wstpad *tp, struct tpad_touch *t) { int dx, dy, dist = 0; if (IS_MT(tp) || tp->tap.contacts == 1) { dx = abs(t->x - t->orig.x) << 12; dy = abs(t->y - t->orig.y) * tp->ratio; dist = (dx >= dy ? dx + 3 * dy / 8 : dy + 3 * dx / 8); } tp->tap.valid = (CENTERED(t) && dist <= (tp->tap.maxdist << 12)); } /* * Return the oldest touch in the TOUCH_END state, or NULL. */ struct tpad_touch * wstpad_tap_touch(struct wsmouseinput *input) { struct wstpad *tp = input->tp; struct tpad_touch *s, *t = NULL; u_int lifted; int slot; if (IS_MT(tp)) { lifted = (input->mt.sync[MTS_TOUCH] & ~input->mt.touches); FOREACHBIT(lifted, slot) { s = &tp->tpad_touches[slot]; if (tp->tap.state == TAP_DETECT && !tp->tap.valid) wstpad_tap_filter(tp, s); if (t == NULL || timespeccmp(&t->orig.time, &s->orig.time, >)) t = s; } } else { if (tp->t->state == TOUCH_END) { t = tp->t; if (tp->tap.state == TAP_DETECT && !tp->tap.valid) wstpad_tap_filter(tp, t); } } return (t); } /* Determine the "tap button", keep track of whether a touch is masked. */ u_int wstpad_tap_button(struct wstpad *tp) { int n = tp->tap.contacts - tp->contacts - 1; tp->tap.masked = tp->contacts; return (n >= 0 && n < TAP_BTNMAP_SIZE ? tp->tap.btnmap[n] : 0); } /* * In the hold/drag state, do not mask touches if no masking was involved * in the preceding tap gesture. */ static inline int tap_unmask(struct wstpad *tp) { return ((tp->tap.button || tp->tap.pending) && tp->tap.masked == 0); } /* * In the default configuration, this handler maps one-, two-, and * three-finger taps to left-button, right-button, and middle-button * events, respectively. Setting the LOCKTIME parameter enables * "locked drags", which are finished by a timeout or a tap-to-end * gesture. */ void wstpad_tap(struct wsmouseinput *input, u_int *cmds) { struct wstpad *tp = input->tp; struct tpad_touch *t; int contacts, is_tap, slot, err = 0; /* Synchronize the button states, if necessary. */ if (input->btn.sync) *cmds |= 1 << TAPBUTTON_SYNC; /* * It is possible to produce a click within the tap timeout. * Wait for a new touch before generating new button events. */ if (PRIMARYBTN_RELEASED(tp)) tp->tap.contacts = 0; /* Reset the detection state whenever a new touch starts. */ if (tp->contacts > tp->prev_contacts || (IS_MT(tp) && (input->mt.touches & input->mt.sync[MTS_TOUCH]))) { tp->tap.contacts = tp->contacts; tp->tap.valid = 0; } /* * The filtered number of active touches excludes a masked * touch if its duration exceeds the tap limit. */ contacts = tp->contacts; if ((slot = ffs(input->mt.ptr_mask) - 1) >= 0 && !wstpad_is_tap(tp, &tp->tpad_touches[slot]) && !tap_unmask(tp)) { contacts--; } switch (tp->tap.state) { case TAP_DETECT: /* Find the oldest touch in the TOUCH_END state. */ t = wstpad_tap_touch(input); if (t) { is_tap = wstpad_is_tap(tp, t); if (is_tap && contacts == 0) { if (tp->tap.button) *cmds |= 1 << TAPBUTTON_UP; tp->tap.pending = (tp->tap.valid ? wstpad_tap_button(tp) : 0); if (tp->tap.pending) { tp->tap.state = TAP_LIFTED; err = !timeout_add_msec(&tp->tap.to, CLICKDELAY_MS); } } else if (!is_tap && tp->tap.locktime == 0) { if (contacts == 0 && tp->tap.button) *cmds |= 1 << TAPBUTTON_UP; else if (contacts) tp->tap.state = TAP_IGNORE; } else if (!is_tap && tp->tap.button) { if (contacts == 0) { tp->tap.state = TAP_LOCKED; err = !timeout_add_msec(&tp->tap.to, tp->tap.locktime); } else { tp->tap.state = TAP_LOCKED_DRAG; } } } break; case TAP_IGNORE: if (contacts == 0) { tp->tap.state = TAP_DETECT; if (tp->tap.button) *cmds |= 1 << TAPBUTTON_UP; } break; case TAP_LIFTED: if (contacts) { timeout_del(&tp->tap.to); tp->tap.state = TAP_DETECT; if (tp->tap.pending) *cmds |= 1 << TAPBUTTON_DOWN; } break; case TAP_LOCKED: if (contacts) { timeout_del(&tp->tap.to); tp->tap.state = TAP_LOCKED_DRAG; } break; case TAP_LOCKED_DRAG: if (contacts == 0) { t = wstpad_tap_touch(input); if (t && wstpad_is_tap(tp, t)) { /* "tap-to-end" */ *cmds |= 1 << TAPBUTTON_UP; tp->tap.state = TAP_DETECT; } else { tp->tap.state = TAP_LOCKED; err = !timeout_add_msec(&tp->tap.to, tp->tap.locktime); } } break; } if (err) { /* Did timeout_add fail? */ input->sbtn.buttons &= ~tp->tap.button; input->sbtn.sync |= tp->tap.button; tp->tap.pending = 0; tp->tap.button = 0; tp->tap.state = TAP_DETECT; } } int wstpad_tap_sync(struct wsmouseinput *input) { struct wstpad *tp = input->tp; return ((tp->tap.button & (input->btn.buttons | tp->softbutton)) == 0 || (tp->tap.button == PRIMARYBTN && tp->softbutton)); } void wstpad_tap_timeout(void *p) { struct wsmouseinput *input = p; struct wstpad *tp = input->tp; struct evq_access evq; u_int btn; int s, ev; s = spltty(); evq.evar = *input->evar; if (evq.evar != NULL && tp != NULL) { ev = 0; if (tp->tap.pending) { tp->tap.button = tp->tap.pending; tp->tap.pending = 0; input->sbtn.buttons |= tp->tap.button; timeout_add_msec(&tp->tap.to, tp->tap.clicktime); if (wstpad_tap_sync(input)) { ev = BTN_DOWN_EV; btn = ffs(tp->tap.button) - 1; } } else { if (wstpad_tap_sync(input)) { ev = BTN_UP_EV; btn = ffs(tp->tap.button) - 1; } if (tp->tap.button != tp->softbutton) input->sbtn.buttons &= ~tp->tap.button; tp->tap.button = 0; tp->tap.state = TAP_DETECT; } if (ev) { evq.put = evq.evar->ws_put; evq.result = EVQ_RESULT_NONE; getnanotime(&evq.ts); wsmouse_evq_put(&evq, ev, btn); wsmouse_evq_put(&evq, SYNC_EV, 0); if (evq.result == EVQ_RESULT_SUCCESS) { if (input->flags & LOG_EVENTS) { wsmouse_log_events(input, &evq); } evq.evar->ws_put = evq.put; WSEVENT_WAKEUP(evq.evar); } else { input->sbtn.sync |= tp->tap.button; } } } splx(s); } /* * Suppress accidental pointer movements after a click on a clickpad. */ void wstpad_click(struct wsmouseinput *input) { struct wstpad *tp = input->tp; if (tp->contacts == 1 && (PRIMARYBTN_CLICKED(tp) || PRIMARYBTN_RELEASED(tp))) set_freeze_ts(tp, 0, FREEZE_MS); } /* Translate the "command" bits into the sync-state of wsmouse. */ void wstpad_cmds(struct wsmouseinput *input, u_int cmds) { struct wstpad *tp = input->tp; int n; FOREACHBIT(cmds, n) { switch (n) { case CLEAR_MOTION_DELTAS: input->motion.dx = input->motion.dy = 0; if (input->motion.dz == 0 && input->motion.dw == 0) input->motion.sync &= ~SYNC_DELTAS; continue; case SOFTBUTTON_DOWN: input->btn.sync &= ~PRIMARYBTN; input->sbtn.buttons |= tp->softbutton; if (tp->softbutton != tp->tap.button) input->sbtn.sync |= tp->softbutton; continue; case SOFTBUTTON_UP: input->btn.sync &= ~PRIMARYBTN; if (tp->softbutton != tp->tap.button) { input->sbtn.buttons &= ~tp->softbutton; input->sbtn.sync |= tp->softbutton; } tp->softbutton = 0; continue; case TAPBUTTON_SYNC: if (tp->tap.button) input->btn.sync &= ~tp->tap.button; continue; case TAPBUTTON_DOWN: tp->tap.button = tp->tap.pending; tp->tap.pending = 0; input->sbtn.buttons |= tp->tap.button; if (wstpad_tap_sync(input)) input->sbtn.sync |= tp->tap.button; continue; case TAPBUTTON_UP: if (tp->tap.button != tp->softbutton) input->sbtn.buttons &= ~tp->tap.button; if (wstpad_tap_sync(input)) input->sbtn.sync |= tp->tap.button; tp->tap.button = 0; continue; case HSCROLL: input->motion.dw = tp->scroll.dw; input->motion.sync |= SYNC_DELTAS; continue; case VSCROLL: input->motion.dz = tp->scroll.dz; input->motion.sync |= SYNC_DELTAS; continue; default: printf("[wstpad] invalid cmd %d\n", n); break; } } } /* * Set the state of touches that have ended. TOUCH_END is a transitional * state and will be changed to TOUCH_NONE before process_input() returns. */ static inline void clear_touchstates(struct wsmouseinput *input, enum touchstates state) { u_int touches; int slot; touches = input->mt.sync[MTS_TOUCH] & ~input->mt.touches; FOREACHBIT(touches, slot) input->tp->tpad_touches[slot].state = state; } void wstpad_mt_inputs(struct wsmouseinput *input) { struct wstpad *tp = input->tp; struct tpad_touch *t; int slot, dx, dy; u_int touches, inactive; /* TOUCH_BEGIN */ touches = input->mt.touches & input->mt.sync[MTS_TOUCH]; FOREACHBIT(touches, slot) { t = &tp->tpad_touches[slot]; t->state = TOUCH_BEGIN; t->x = normalize_abs(&input->filter.h, t->pos->x); t->y = normalize_abs(&input->filter.v, t->pos->y); t->orig.x = t->x; t->orig.y = t->y; memcpy(&t->orig.time, &tp->time, sizeof(struct timespec)); t->flags = edge_flags(tp, t->x, t->y); wstpad_set_direction(tp, t, 0, 0); } /* TOUCH_UPDATE */ touches = input->mt.touches & input->mt.frame; if (touches & tp->mtcycle) { /* * Slot data may be synchronized separately, in any order, * or not at all if there is no delta. Identify the touches * without deltas. */ inactive = input->mt.touches & ~tp->mtcycle; tp->mtcycle = touches; } else { inactive = 0; tp->mtcycle |= touches; } touches = input->mt.touches & ~input->mt.sync[MTS_TOUCH]; FOREACHBIT(touches, slot) { t = &tp->tpad_touches[slot]; t->state = TOUCH_UPDATE; if ((1 << slot) & input->mt.frame) { dx = normalize_abs(&input->filter.h, t->pos->x) - t->x; t->x += dx; dy = normalize_abs(&input->filter.v, t->pos->y) - t->y; t->y += dy; t->flags &= (~EDGES | edge_flags(tp, t->x, t->y)); if (wsmouse_hysteresis(input, t->pos)) dx = dy = 0; wstpad_set_direction(tp, t, dx, dy); } else if ((1 << slot) & inactive) { wstpad_set_direction(tp, t, 0, 0); } } clear_touchstates(input, TOUCH_END); } /* * Identify "thumb" contacts in the bottom area. The identification * has three stages: * 1. If exactly one of two or more touches is in the bottom area, it * is masked, which means it does not receive pointer control as long * as there are alternatives. Once set, the mask will only be cleared * when the touch is released. * Tap detection ignores a masked touch if it does not participate in * a tap gesture. * 2. If the pointer-controlling touch is moving stably while a masked * touch in the bottom area is resting, or only moving minimally, the * pointer mask is copied to tp->ignore. In this stage, the masked * touch does not block pointer movement, and it is ignored by * wstpad_f2scroll(). * Decisions are made more or less immediately, there may be errors * in edge cases. If a fast or long upward movement is detected, * tp->ignore is cleared. There is no other transition from stage 2 * to scrolling, or vice versa, for a pair of touches. * 3. If tp->ignore is set and the touch is resting, it is marked as * thumb, and it will be ignored until it ends. */ void wstpad_mt_masks(struct wsmouseinput *input) { struct wstpad *tp = input->tp; struct tpad_touch *t; struct position *pos; u_int mask; int slot; tp->ignore &= input->mt.touches; if (tp->contacts < 2) return; if (tp->ignore) { slot = ffs(tp->ignore) - 1; t = &tp->tpad_touches[slot]; if (t->flags & THUMB) return; if (t->dir < 0 && wstpad_is_stable(input, t)) { t->flags |= THUMB; return; } /* The edge.low area is a bit larger than the bottom area. */ if (t->y >= tp->edge.low || (NORTH(t->dir) && magnitude(input, t->pos->dx, t->pos->dy) >= MAG_MEDIUM)) tp->ignore = 0; return; } if (input->mt.ptr_mask == 0) { mask = ~0; FOREACHBIT(input->mt.touches, slot) { t = &tp->tpad_touches[slot]; if (t->flags & B_EDGE) { mask &= (1 << slot); input->mt.ptr_mask = mask; } } } if ((input->mt.ptr_mask & ~input->mt.ptr) && !(tp->scroll.dz || tp->scroll.dw) && tp->t->dir >= 0 && wstpad_is_stable(input, tp->t)) { slot = ffs(input->mt.ptr_mask) - 1; t = &tp->tpad_touches[slot]; if (t->y >= tp->edge.low) return; if (!wstpad_is_stable(input, t)) return; /* Default hysteresis limits are low. Make a strict check. */ pos = tp->t->pos; if (abs(pos->acc_dx) < 3 * input->filter.h.hysteresis && abs(pos->acc_dy) < 3 * input->filter.v.hysteresis) return; if (t->dir >= 0) { /* Treat t as thumb if it is slow while tp->t is fast. */ if (magnitude(input, t->pos->dx, t->pos->dy) > MAG_LOW || magnitude(input, pos->dx, pos->dy) < MAG_MEDIUM) return; } tp->ignore = input->mt.ptr_mask; } } void wstpad_touch_inputs(struct wsmouseinput *input) { struct wstpad *tp = input->tp; struct tpad_touch *t; int slot, x, y, dx, dy; tp->btns = input->btn.buttons; tp->btns_sync = input->btn.sync; tp->prev_contacts = tp->contacts; tp->contacts = input->touch.contacts; if (tp->contacts == 1 && ((tp->params.f2width && input->touch.width >= tp->params.f2width) || (tp->params.f2pressure && input->touch.pressure >= tp->params.f2pressure))) tp->contacts = 2; if (IS_MT(tp)) { wstpad_mt_inputs(input); if (input->mt.ptr) { slot = ffs(input->mt.ptr) - 1; tp->t = &tp->tpad_touches[slot]; } wstpad_mt_masks(input); } else { t = tp->t; if (tp->contacts) t->state = (tp->prev_contacts ? TOUCH_UPDATE : TOUCH_BEGIN); else t->state = (tp->prev_contacts ? TOUCH_END : TOUCH_NONE); dx = dy = 0; x = normalize_abs(&input->filter.h, t->pos->x); y = normalize_abs(&input->filter.v, t->pos->y); if (t->state == TOUCH_BEGIN) { t->x = t->orig.x = x; t->y = t->orig.y = y; memcpy(&t->orig.time, &tp->time, sizeof(struct timespec)); t->flags = edge_flags(tp, x, y); } else if (input->motion.sync & SYNC_POSITION) { if (!wsmouse_hysteresis(input, t->pos)) { dx = x - t->x; dy = y - t->y; } t->x = x; t->y = y; t->flags &= (~EDGES | edge_flags(tp, x, y)); } wstpad_set_direction(tp, t, dx, dy); } } static inline int t2_ignore(struct wsmouseinput *input) { /* * If there are two touches, do not block pointer movement if they * perform a click-and-drag action, or if the second touch is * resting in the bottom area. */ return (input->tp->contacts == 2 && ((input->tp->btns & PRIMARYBTN) || (input->tp->ignore & ~input->mt.ptr))); } void wstpad_process_input(struct wsmouseinput *input, struct evq_access *evq) { struct wstpad *tp = input->tp; u_int handlers, hdlr, cmds; memcpy(&tp->time, &evq->ts, sizeof(struct timespec)); wstpad_touch_inputs(input); cmds = 0; handlers = tp->handlers; if (DISABLE(tp)) handlers &= ((1 << TOPBUTTON_HDLR) | (1 << SOFTBUTTON_HDLR)); FOREACHBIT(handlers, hdlr) { switch (hdlr) { case SOFTBUTTON_HDLR: case TOPBUTTON_HDLR: wstpad_softbuttons(input, &cmds, hdlr); continue; case TAP_HDLR: wstpad_tap(input, &cmds); continue; case F2SCROLL_HDLR: wstpad_f2scroll(input, &cmds); continue; case EDGESCROLL_HDLR: wstpad_edgescroll(input, &cmds); continue; case CLICK_HDLR: wstpad_click(input); continue; } } /* Check whether pointer movement should be blocked. */ if (input->motion.dx || input->motion.dy) { if (DISABLE(tp) || (tp->t->flags & tp->freeze) || timespeccmp(&tp->time, &tp->freeze_ts, <) || (tp->contacts > 1 && !t2_ignore(input))) { cmds |= 1 << CLEAR_MOTION_DELTAS; } } wstpad_cmds(input, cmds); if (IS_MT(tp)) clear_touchstates(input, TOUCH_NONE); } /* * Try to determine the average interval between two updates. Various * conditions are checked in order to ensure that only valid samples enter * into the calculation. Above all, it is restricted to motion events * occurring when there is only one contact. MT devices may need more than * one packet to transmit their state if there are multiple touches, and * the update frequency may be higher in this case. */ void wstpad_track_interval(struct wsmouseinput *input, struct timespec *time) { static const struct timespec limit = { 0, 30 * 1000000L }; struct timespec ts; int samples; if (input->motion.sync == 0 || (input->touch.sync & SYNC_CONTACTS) || (input->touch.contacts > 1)) { input->intv.track = 0; return; } if (input->intv.track) { timespecsub(time, &input->intv.ts, &ts); if (timespeccmp(&ts, &limit, <)) { /* The unit of the sum is 4096 nanoseconds. */ input->intv.sum += ts.tv_nsec >> 12; samples = ++input->intv.samples; /* * Make the first calculation quickly and later * a more reliable one: */ if (samples == 8) { input->intv.avg = input->intv.sum << 9; wstpad_init_deceleration(input); } else if (samples == 128) { input->intv.avg = input->intv.sum << 5; wstpad_init_deceleration(input); input->intv.samples = 0; input->intv.sum = 0; input->flags &= ~TRACK_INTERVAL; } } } memcpy(&input->intv.ts, time, sizeof(struct timespec)); input->intv.track = 1; } /* * The default acceleration options of X don't work convincingly with * touchpads (the synaptics driver installs its own "acceleration * profile" and callback function). As a preliminary workaround, this * filter applies a simple deceleration scheme to small deltas, based * on the "magnitude" of the delta pair. A magnitude of 8 corresponds, * roughly, to a speed of (filter.dclr / 12.5) device units per milli- * second. If its magnitude is smaller than 7 a delta will be downscaled * by the factor 2/8, deltas with magnitudes from 7 to 11 by factors * ranging from 3/8 to 7/8. */ int wstpad_decelerate(struct wsmouseinput *input, int *dx, int *dy) { int mag, n, h, v; mag = magnitude(input, *dx, *dy); /* Don't change deceleration levels abruptly. */ mag = (mag + 7 * input->filter.mag) / 8; /* Don't use arbitrarily high values. */ input->filter.mag = imin(mag, 24 << 12); n = imax((mag >> 12) - 4, 2); if (n < 8) { /* Scale by (n / 8). */ h = *dx * n + input->filter.h.dclr_rmdr; v = *dy * n + input->filter.v.dclr_rmdr; input->filter.h.dclr_rmdr = (h >= 0 ? h & 7 : -(-h & 7)); input->filter.v.dclr_rmdr = (v >= 0 ? v & 7 : -(-v & 7)); *dx = h / 8; *dy = v / 8; return (1); } return (0); } void wstpad_filter(struct wsmouseinput *input) { struct axis_filter *h = &input->filter.h; struct axis_filter *v = &input->filter.v; struct position *pos = &input->motion.pos; int strength = input->filter.mode & 7; int dx, dy; if (!(input->motion.sync & SYNC_POSITION) || (h->dmax && (abs(pos->dx) > h->dmax)) || (v->dmax && (abs(pos->dy) > v->dmax))) { dx = dy = 0; } else { dx = pos->dx; dy = pos->dy; } if (wsmouse_hysteresis(input, pos)) dx = dy = 0; if (input->filter.dclr && wstpad_decelerate(input, &dx, &dy)) /* Strong smoothing may hamper the precision at low speeds. */ strength = imin(strength, 2); if (strength) { if ((input->touch.sync & SYNC_CONTACTS) || input->mt.ptr != input->mt.prev_ptr) { h->avg = v->avg = 0; } /* Use a weighted decaying average for smoothing. */ dx = dx * (8 - strength) + h->avg * strength + h->avg_rmdr; dy = dy * (8 - strength) + v->avg * strength + v->avg_rmdr; h->avg_rmdr = (dx >= 0 ? dx & 7 : -(-dx & 7)); v->avg_rmdr = (dy >= 0 ? dy & 7 : -(-dy & 7)); dx = h->avg = dx / 8; dy = v->avg = dy / 8; } input->motion.dx = dx; input->motion.dy = dy; } /* * Compatibility-mode conversions. wstpad_filter transforms and filters * the coordinate inputs, extended functionality is provided by * wstpad_process_input. */ void wstpad_compat_convert(struct wsmouseinput *input, struct evq_access *evq) { if (input->flags & TRACK_INTERVAL) wstpad_track_interval(input, &evq->ts); wstpad_filter(input); if ((input->motion.dx || input->motion.dy) && !(input->motion.sync & SYNC_DELTAS)) { input->motion.dz = input->motion.dw = 0; input->motion.sync |= SYNC_DELTAS; } if (input->tp != NULL) wstpad_process_input(input, evq); input->motion.sync &= ~SYNC_POSITION; input->touch.sync = 0; } int wstpad_init(struct wsmouseinput *input) { struct wstpad *tp = input->tp; int i, slots; if (tp != NULL) return (0); input->tp = tp = malloc(sizeof(struct wstpad), M_DEVBUF, M_WAITOK | M_ZERO); if (tp == NULL) return (-1); slots = imax(input->mt.num_slots, 1); tp->tpad_touches = malloc(slots * sizeof(struct tpad_touch), M_DEVBUF, M_WAITOK | M_ZERO); if (tp->tpad_touches == NULL) { free(tp, M_DEVBUF, sizeof(struct wstpad)); return (-1); } tp->t = &tp->tpad_touches[0]; if (input->mt.num_slots) { tp->features |= WSTPAD_MT; for (i = 0; i < input->mt.num_slots; i++) tp->tpad_touches[i].pos = &input->mt.slots[i].pos; } else { tp->t->pos = &input->motion.pos; } timeout_set(&tp->tap.to, wstpad_tap_timeout, input); tp->ratio = input->filter.ratio; return (0); } /* * Integer square root (Halleck's method) * * An adaption of code from John B. Halleck (from * http://www.cc.utah.edu/~nahaj/factoring/code.html). This version is * used and published under the OpenBSD license terms with his permission. * * Cf. also Martin Guy's "Square root by abacus" method. */ static inline u_int isqrt(u_int n) { u_int root, sqbit; root = 0; sqbit = 1 << (sizeof(u_int) * 8 - 2); while (sqbit) { if (n >= (sqbit | root)) { n -= (sqbit | root); root = (root >> 1) | sqbit; } else { root >>= 1; } sqbit >>= 2; } return (root); } void wstpad_init_deceleration(struct wsmouseinput *input) { int n, dclr; if ((dclr = input->filter.dclr) == 0) return; dclr = imax(dclr, 4); /* * For a standard update rate of about 80Hz, (dclr) units * will be mapped to a magnitude of 8. If the average rate * is significantly higher or lower, adjust the coefficient * accordingly: */ if (input->intv.avg == 0) { n = 8; } else { n = 8 * 13000000 / input->intv.avg; n = imax(imin(n, 32), 4); } input->filter.h.mag_scale = (n << 12) / dclr; input->filter.v.mag_scale = (input->filter.ratio ? n * input->filter.ratio : n << 12) / dclr; input->filter.h.dclr_rmdr = 0; input->filter.v.dclr_rmdr = 0; input->flags |= TRACK_INTERVAL; } int wstpad_configure(struct wsmouseinput *input) { struct wstpad *tp; int width, height, diag, offset, h_res, v_res, h_unit, v_unit, i; width = abs(input->hw.x_max - input->hw.x_min); height = abs(input->hw.y_max - input->hw.y_min); if (width == 0 || height == 0) return (-1); /* We can't do anything. */ if (input->tp == NULL && wstpad_init(input)) return (-1); tp = input->tp; if (!(input->flags & CONFIGURED)) { /* * The filter parameters are derived from the length of the * diagonal in device units, with some magic constants which * are partly adapted from libinput or synaptics code, or are * based on tests and guess work. The absolute resolution * values might not be reliable, but if they are present the * settings are adapted to the ratio. */ h_res = input->hw.h_res; v_res = input->hw.v_res; if (h_res == 0 || v_res == 0) h_res = v_res = 1; diag = isqrt(width * width + height * height); input->filter.h.scale = (imin(920, diag) << 12) / diag; input->filter.v.scale = input->filter.h.scale * h_res / v_res; h_unit = imax(diag / 280, 3); v_unit = imax((h_unit * v_res + h_res / 2) / h_res, 3); input->filter.h.hysteresis = h_unit; input->filter.v.hysteresis = v_unit; input->filter.mode = FILTER_MODE_DEFAULT; input->filter.dclr = h_unit - h_unit / 5; wstpad_init_deceleration(input); tp->features &= (WSTPAD_MT | WSTPAD_DISABLE); if (input->hw.contacts_max != 1) tp->features |= WSTPAD_TWOFINGERSCROLL; else tp->features |= WSTPAD_EDGESCROLL; if (input->hw.hw_type == WSMOUSEHW_CLICKPAD) { if (input->hw.type == WSMOUSE_TYPE_SYNAP_SBTN) { tp->features |= WSTPAD_TOPBUTTONS; } else { tp->features |= WSTPAD_SOFTBUTTONS; tp->features |= WSTPAD_SOFTMBTN; } } tp->params.left_edge = V_EDGE_RATIO_DEFAULT; tp->params.right_edge = V_EDGE_RATIO_DEFAULT; tp->params.bottom_edge = ((tp->features & WSTPAD_SOFTBUTTONS) ? B_EDGE_RATIO_DEFAULT : 0); tp->params.top_edge = ((tp->features & WSTPAD_TOPBUTTONS) ? T_EDGE_RATIO_DEFAULT : 0); tp->params.center_width = CENTER_RATIO_DEFAULT; tp->tap.maxtime.tv_nsec = TAP_MAXTIME_DEFAULT * 1000000; tp->tap.clicktime = TAP_CLICKTIME_DEFAULT; tp->tap.locktime = TAP_LOCKTIME_DEFAULT; tp->scroll.hdist = 4 * h_unit; tp->scroll.vdist = 4 * v_unit; tp->tap.maxdist = 4 * h_unit; if (IS_MT(tp) && h_res > 1 && v_res > 1 && input->hw.hw_type == WSMOUSEHW_CLICKPAD && (width + h_res / 2) / h_res > 100 && (height + v_res / 2) / v_res > 60) { tp->params.mtbtn_maxdist = h_res * 35; } else { tp->params.mtbtn_maxdist = -1; /* not available */ } } /* A touch with a flag set in this mask does not move the pointer. */ tp->freeze = EDGES; offset = width * tp->params.left_edge / 4096; tp->edge.left = (offset ? input->hw.x_min + offset : INT_MIN); offset = width * tp->params.right_edge / 4096; tp->edge.right = (offset ? input->hw.x_max - offset : INT_MAX); offset = height * tp->params.bottom_edge / 4096; tp->edge.bottom = (offset ? input->hw.y_min + offset : INT_MIN); tp->edge.low = tp->edge.bottom + offset / 2; offset = height * tp->params.top_edge / 4096; tp->edge.top = (offset ? input->hw.y_max - offset : INT_MAX); offset = width * abs(tp->params.center_width) / 8192; tp->edge.center = input->hw.x_min + width / 2; tp->edge.center_left = tp->edge.center - offset; tp->edge.center_right = tp->edge.center + offset; /* * Make the MTBUTTONS configuration consistent. A non-negative 'maxdist' * value makes the feature visible in wsconsctl. 0-values are replaced * by a default (one fourth of the length of the touchpad diagonal). */ if (tp->params.mtbtn_maxdist < 0) { tp->features &= ~WSTPAD_MTBUTTONS; } else if (tp->params.mtbtn_maxdist == 0) { diag = isqrt(width * width + height * height); tp->params.mtbtn_maxdist = diag / 4; } tp->handlers = 0; if (tp->features & (WSTPAD_SOFTBUTTONS | WSTPAD_MTBUTTONS)) tp->handlers |= 1 << SOFTBUTTON_HDLR; if (tp->features & WSTPAD_TOPBUTTONS) tp->handlers |= 1 << TOPBUTTON_HDLR; if (tp->features & WSTPAD_TWOFINGERSCROLL) tp->handlers |= 1 << F2SCROLL_HDLR; else if (tp->features & WSTPAD_EDGESCROLL) tp->handlers |= 1 << EDGESCROLL_HDLR; for (i = 0; i < TAP_BTNMAP_SIZE; i++) { if (tp->tap.btnmap[i] == 0) continue; tp->tap.clicktime = imin(imax(tp->tap.clicktime, 80), 350); if (tp->tap.locktime) tp->tap.locktime = imin(imax(tp->tap.locktime, 150), 5000); tp->handlers |= 1 << TAP_HDLR; break; } if (input->hw.hw_type == WSMOUSEHW_CLICKPAD) tp->handlers |= 1 << CLICK_HDLR; tp->sbtnswap = ((tp->features & WSTPAD_SWAPSIDES) ? (LEFTBTN | RIGHTBTN) : 0); return (0); } void wstpad_reset(struct wsmouseinput *input) { struct wstpad *tp = input->tp; if (tp != NULL) { timeout_del(&tp->tap.to); tp->tap.state = TAP_DETECT; } if (input->sbtn.buttons) { input->sbtn.sync = input->sbtn.buttons; input->sbtn.buttons = 0; } } void wstpad_cleanup(struct wsmouseinput *input) { struct wstpad *tp = input->tp; int slots; timeout_del(&tp->tap.to); slots = imax(input->mt.num_slots, 1); free(tp->tpad_touches, M_DEVBUF, slots * sizeof(struct tpad_touch)); free(tp, M_DEVBUF, sizeof(struct wstpad)); input->tp = NULL; } int wstpad_set_param(struct wsmouseinput *input, int key, int val) { struct wstpad *tp = input->tp; u_int flag; if (tp == NULL) return (EINVAL); switch (key) { case WSMOUSECFG_SOFTBUTTONS ... WSMOUSECFG_MTBUTTONS: switch (key) { case WSMOUSECFG_SOFTBUTTONS: flag = WSTPAD_SOFTBUTTONS; break; case WSMOUSECFG_SOFTMBTN: flag = WSTPAD_SOFTMBTN; break; case WSMOUSECFG_TOPBUTTONS: flag = WSTPAD_TOPBUTTONS; break; case WSMOUSECFG_TWOFINGERSCROLL: flag = WSTPAD_TWOFINGERSCROLL; break; case WSMOUSECFG_EDGESCROLL: flag = WSTPAD_EDGESCROLL; break; case WSMOUSECFG_HORIZSCROLL: flag = WSTPAD_HORIZSCROLL; break; case WSMOUSECFG_SWAPSIDES: flag = WSTPAD_SWAPSIDES; break; case WSMOUSECFG_DISABLE: flag = WSTPAD_DISABLE; break; case WSMOUSECFG_MTBUTTONS: flag = WSTPAD_MTBUTTONS; break; } if (val) tp->features |= flag; else tp->features &= ~flag; break; case WSMOUSECFG_LEFT_EDGE: tp->params.left_edge = val; break; case WSMOUSECFG_RIGHT_EDGE: tp->params.right_edge = val; break; case WSMOUSECFG_TOP_EDGE: tp->params.top_edge = val; break; case WSMOUSECFG_BOTTOM_EDGE: tp->params.bottom_edge = val; break; case WSMOUSECFG_CENTERWIDTH: tp->params.center_width = val; break; case WSMOUSECFG_HORIZSCROLLDIST: tp->scroll.hdist = val; break; case WSMOUSECFG_VERTSCROLLDIST: tp->scroll.vdist = val; break; case WSMOUSECFG_F2WIDTH: tp->params.f2width = val; break; case WSMOUSECFG_F2PRESSURE: tp->params.f2pressure = val; break; case WSMOUSECFG_TAP_MAXTIME: tp->tap.maxtime.tv_nsec = imin(val, 999) * 1000000; break; case WSMOUSECFG_TAP_CLICKTIME: tp->tap.clicktime = val; break; case WSMOUSECFG_TAP_LOCKTIME: tp->tap.locktime = val; break; case WSMOUSECFG_TAP_ONE_BTNMAP: tp->tap.btnmap[0] = BTNMASK(val); break; case WSMOUSECFG_TAP_TWO_BTNMAP: tp->tap.btnmap[1] = BTNMASK(val); break; case WSMOUSECFG_TAP_THREE_BTNMAP: tp->tap.btnmap[2] = BTNMASK(val); break; case WSMOUSECFG_MTBTN_MAXDIST: if (IS_MT(tp)) tp->params.mtbtn_maxdist = val; break; default: return (ENOTSUP); } return (0); } int wstpad_get_param(struct wsmouseinput *input, int key, int *pval) { struct wstpad *tp = input->tp; u_int flag; if (tp == NULL) return (EINVAL); switch (key) { case WSMOUSECFG_SOFTBUTTONS ... WSMOUSECFG_MTBUTTONS: switch (key) { case WSMOUSECFG_SOFTBUTTONS: flag = WSTPAD_SOFTBUTTONS; break; case WSMOUSECFG_SOFTMBTN: flag = WSTPAD_SOFTMBTN; break; case WSMOUSECFG_TOPBUTTONS: flag = WSTPAD_TOPBUTTONS; break; case WSMOUSECFG_TWOFINGERSCROLL: flag = WSTPAD_TWOFINGERSCROLL; break; case WSMOUSECFG_EDGESCROLL: flag = WSTPAD_EDGESCROLL; break; case WSMOUSECFG_HORIZSCROLL: flag = WSTPAD_HORIZSCROLL; break; case WSMOUSECFG_SWAPSIDES: flag = WSTPAD_SWAPSIDES; break; case WSMOUSECFG_DISABLE: flag = WSTPAD_DISABLE; break; case WSMOUSECFG_MTBUTTONS: flag = WSTPAD_MTBUTTONS; break; } *pval = !!(tp->features & flag); break; case WSMOUSECFG_LEFT_EDGE: *pval = tp->params.left_edge; break; case WSMOUSECFG_RIGHT_EDGE: *pval = tp->params.right_edge; break; case WSMOUSECFG_TOP_EDGE: *pval = tp->params.top_edge; break; case WSMOUSECFG_BOTTOM_EDGE: *pval = tp->params.bottom_edge; break; case WSMOUSECFG_CENTERWIDTH: *pval = tp->params.center_width; break; case WSMOUSECFG_HORIZSCROLLDIST: *pval = tp->scroll.hdist; break; case WSMOUSECFG_VERTSCROLLDIST: *pval = tp->scroll.vdist; break; case WSMOUSECFG_F2WIDTH: *pval = tp->params.f2width; break; case WSMOUSECFG_F2PRESSURE: *pval = tp->params.f2pressure; break; case WSMOUSECFG_TAP_MAXTIME: *pval = tp->tap.maxtime.tv_nsec / 1000000; break; case WSMOUSECFG_TAP_CLICKTIME: *pval = tp->tap.clicktime; break; case WSMOUSECFG_TAP_LOCKTIME: *pval = tp->tap.locktime; break; case WSMOUSECFG_TAP_ONE_BTNMAP: *pval = ffs(tp->tap.btnmap[0]); break; case WSMOUSECFG_TAP_TWO_BTNMAP: *pval = ffs(tp->tap.btnmap[1]); break; case WSMOUSECFG_TAP_THREE_BTNMAP: *pval = ffs(tp->tap.btnmap[2]); break; case WSMOUSECFG_MTBTN_MAXDIST: *pval = tp->params.mtbtn_maxdist; break; default: return (ENOTSUP); } return (0); }
1 1 1 1 1 1 1 1 1 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 /* $OpenBSD: sys_futex.c,v 1.22 2023/08/14 07:42:34 miod Exp $ */ /* * Copyright (c) 2016-2017 Martin Pieuchot * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/mount.h> #include <sys/syscallargs.h> #include <sys/pool.h> #include <sys/time.h> #include <sys/rwlock.h> #include <sys/futex.h> #ifdef KTRACE #include <sys/ktrace.h> #endif #include <uvm/uvm.h> /* * Kernel representation of a futex. */ struct futex { LIST_ENTRY(futex) ft_list; /* list of all futexes */ TAILQ_HEAD(, proc) ft_threads; /* sleeping queue */ struct uvm_object *ft_obj; /* UVM object */ struct vm_amap *ft_amap; /* UVM amap */ voff_t ft_off; /* UVM offset */ unsigned int ft_refcnt; /* # of references */ }; /* Syscall helpers. */ int futex_wait(uint32_t *, uint32_t, const struct timespec *, int); int futex_wake(uint32_t *, uint32_t, int); int futex_requeue(uint32_t *, uint32_t, uint32_t *, uint32_t, int); /* Flags for futex_get(). */ #define FT_CREATE 0x1 /* Create a futex if it doesn't exist. */ #define FT_PRIVATE 0x2 /* Futex is process-private. */ struct futex *futex_get(uint32_t *, int); void futex_put(struct futex *); /* * The global futex lock serializes futex(2) calls so that no wakeup * event is lost, and protects all futex lists and futex states. */ struct rwlock ftlock = RWLOCK_INITIALIZER("futex"); static struct futex_list ftlist_shared = LIST_HEAD_INITIALIZER(ftlist_shared); struct pool ftpool; void futex_init(void) { pool_init(&ftpool, sizeof(struct futex), 0, IPL_NONE, PR_WAITOK | PR_RWLOCK, "futexpl", NULL); } int sys_futex(struct proc *p, void *v, register_t *retval) { struct sys_futex_args /* { syscallarg(uint32_t *) f; syscallarg(int) op; syscallarg(inr) val; syscallarg(const struct timespec *) timeout; syscallarg(uint32_t *) g; } */ *uap = v; uint32_t *uaddr = SCARG(uap, f); int op = SCARG(uap, op); uint32_t val = SCARG(uap, val); const struct timespec *timeout = SCARG(uap, timeout); void *g = SCARG(uap, g); int flags = 0; int error = 0; if (op & FUTEX_PRIVATE_FLAG) flags |= FT_PRIVATE; rw_enter_write(&ftlock); switch (op) { case FUTEX_WAIT: case FUTEX_WAIT_PRIVATE: error = futex_wait(uaddr, val, timeout, flags); break; case FUTEX_WAKE: case FUTEX_WAKE_PRIVATE: *retval = futex_wake(uaddr, val, flags); break; case FUTEX_REQUEUE: case FUTEX_REQUEUE_PRIVATE: *retval = futex_requeue(uaddr, val, g, (u_long)timeout, flags); break; default: error = ENOSYS; break; } rw_exit_write(&ftlock); return error; } /* * Return an existing futex matching userspace address ``uaddr''. * * If such futex does not exist and FT_CREATE is given, create it. */ struct futex * futex_get(uint32_t *uaddr, int flags) { struct proc *p = curproc; vm_map_t map = &p->p_vmspace->vm_map; vm_map_entry_t entry; struct uvm_object *obj = NULL; struct vm_amap *amap = NULL; voff_t off = (vaddr_t)uaddr; struct futex *f; struct futex_list *ftlist = &p->p_p->ps_ftlist; rw_assert_wrlock(&ftlock); if (!(flags & FT_PRIVATE)) { vm_map_lock_read(map); if (uvm_map_lookup_entry(map, (vaddr_t)uaddr, &entry) && entry->inheritance == MAP_INHERIT_SHARE) { if (UVM_ET_ISOBJ(entry)) { ftlist = &ftlist_shared; obj = entry->object.uvm_obj; off = entry->offset + ((vaddr_t)uaddr - entry->start); } else if (entry->aref.ar_amap) { ftlist = &ftlist_shared; amap = entry->aref.ar_amap; off = ptoa(entry->aref.ar_pageoff) + ((vaddr_t)uaddr - entry->start); } } vm_map_unlock_read(map); } LIST_FOREACH(f, ftlist, ft_list) { if (f->ft_obj == obj && f->ft_amap == amap && f->ft_off == off) { f->ft_refcnt++; break; } } if ((f == NULL) && (flags & FT_CREATE)) { /* * We rely on the rwlock to ensure that no other thread * create the same futex. */ f = pool_get(&ftpool, PR_WAITOK); TAILQ_INIT(&f->ft_threads); f->ft_obj = obj; f->ft_amap = amap; f->ft_off = off; f->ft_refcnt = 1; LIST_INSERT_HEAD(ftlist, f, ft_list); } return f; } /* * Release a given futex. */ void futex_put(struct futex *f) { rw_assert_wrlock(&ftlock); KASSERT(f->ft_refcnt > 0); --f->ft_refcnt; if (f->ft_refcnt == 0) { KASSERT(TAILQ_EMPTY(&f->ft_threads)); LIST_REMOVE(f, ft_list); pool_put(&ftpool, f); } } /* * Put the current thread on the sleep queue of the futex at address * ``uaddr''. Let it sleep for the specified ``timeout'' time, or * indefinitely if the argument is NULL. */ int futex_wait(uint32_t *uaddr, uint32_t val, const struct timespec *timeout, int flags) { struct proc *p = curproc; struct futex *f; uint64_t nsecs = INFSLP; uint32_t cval; int error; /* * After reading the value a race is still possible but * we deal with it by serializing all futex syscalls. */ rw_assert_wrlock(&ftlock); /* * Read user space futex value */ if ((error = copyin32(uaddr, &cval))) return error; /* If the value changed, stop here. */ if (cval != val) return EAGAIN; if (timeout != NULL) { struct timespec ts; if ((error = copyin(timeout, &ts, sizeof(ts)))) return error; #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrreltimespec(p, &ts); #endif if (ts.tv_sec < 0 || !timespecisvalid(&ts)) return EINVAL; nsecs = MAX(1, MIN(TIMESPEC_TO_NSEC(&ts), MAXTSLP)); } f = futex_get(uaddr, flags | FT_CREATE); TAILQ_INSERT_TAIL(&f->ft_threads, p, p_fut_link); p->p_futex = f; error = rwsleep_nsec(p, &ftlock, PWAIT|PCATCH, "fsleep", nsecs); if (error == ERESTART) error = ECANCELED; else if (error == EWOULDBLOCK) { /* A race occurred between a wakeup and a timeout. */ if (p->p_futex == NULL) error = 0; else error = ETIMEDOUT; } /* Remove ourself if we haven't been awaken. */ if ((f = p->p_futex) != NULL) { p->p_futex = NULL; TAILQ_REMOVE(&f->ft_threads, p, p_fut_link); futex_put(f); } return error; } /* * Wakeup at most ``n'' sibling threads sleeping on a futex at address * ``uaddr'' and requeue at most ``m'' sibling threads on a futex at * address ``uaddr2''. */ int futex_requeue(uint32_t *uaddr, uint32_t n, uint32_t *uaddr2, uint32_t m, int flags) { struct futex *f, *g; struct proc *p; uint32_t count = 0; rw_assert_wrlock(&ftlock); f = futex_get(uaddr, flags); if (f == NULL) return 0; while ((p = TAILQ_FIRST(&f->ft_threads)) != NULL && (count < (n + m))) { p->p_futex = NULL; TAILQ_REMOVE(&f->ft_threads, p, p_fut_link); futex_put(f); if (count < n) { wakeup_one(p); } else if (uaddr2 != NULL) { g = futex_get(uaddr2, FT_CREATE); TAILQ_INSERT_TAIL(&g->ft_threads, p, p_fut_link); p->p_futex = g; } count++; } futex_put(f); return count; } /* * Wakeup at most ``n'' sibling threads sleeping on a futex at address * ``uaddr''. */ int futex_wake(uint32_t *uaddr, uint32_t n, int flags) { return futex_requeue(uaddr, n, NULL, 0, flags); }
1 4 17 1 1 15 4 4 8 4 4 5 8 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 /* $OpenBSD: diskmap.c,v 1.27 2023/04/13 02:19:05 jsg Exp $ */ /* * Copyright (c) 2009, 2010 Joel Sing <jsing@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * Disk mapper. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> #include <sys/errno.h> #include <sys/conf.h> #include <sys/dkio.h> #include <sys/disk.h> #include <sys/disklabel.h> #include <sys/fcntl.h> #include <sys/file.h> #include <sys/filedesc.h> #include <sys/lock.h> #include <sys/malloc.h> #include <sys/namei.h> #include <sys/proc.h> #include <sys/vnode.h> #include <sys/pledge.h> int diskmapopen(dev_t dev, int flag, int fmt, struct proc *p) { return 0; } int diskmapclose(dev_t dev, int flag, int fmt, struct proc *p) { return 0; } int diskmapioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { struct dk_diskmap *dm; struct nameidata ndp; struct filedesc *fdp = p->p_fd; struct file *fp0 = NULL, *fp = NULL; struct vnode *vp = NULL; char *devname, flags; int error, fd; if (cmd != DIOCMAP) return ENOTTY; /* * Map a request for a disk to the correct device. We should be * supplied with either a diskname or a disklabel UID. */ dm = (struct dk_diskmap *)addr; fd = dm->fd; devname = malloc(PATH_MAX, M_DEVBUF, M_WAITOK); if ((error = copyinstr(dm->device, devname, PATH_MAX, NULL)) != 0) goto invalid; if (disk_map(devname, devname, PATH_MAX, dm->flags) == 0) { error = copyoutstr(devname, dm->device, PATH_MAX, NULL); if (error != 0) goto invalid; } /* Attempt to open actual device. */ if ((error = getvnode(p, fd, &fp0)) != 0) goto invalid; NDINIT(&ndp, 0, 0, UIO_SYSSPACE, devname, p); ndp.ni_pledge = PLEDGE_RPATH; ndp.ni_unveil = UNVEIL_READ; if ((error = vn_open(&ndp, fp0->f_flag, 0)) != 0) goto invalid; vp = ndp.ni_vp; VOP_UNLOCK(vp); fdplock(fdp); /* * Stop here if the 'struct file *' has been replaced, * for example by another thread calling dup2(2), while * this thread was sleeping in vn_open(). * * Note that this would not happen for correct usages of * "/dev/diskmap". */ if (fdp->fd_ofiles[fd] != fp0) { error = EAGAIN; goto bad; } fp = fnew(p); if (fp == NULL) { error = ENFILE; goto bad; } /* Zap old file. */ mtx_enter(&fdp->fd_fplock); KASSERT(fdp->fd_ofiles[fd] == fp0); flags = fdp->fd_ofileflags[fd]; fdp->fd_ofiles[fd] = NULL; fdp->fd_ofileflags[fd] = 0; mtx_leave(&fdp->fd_fplock); /* Insert new file. */ fp->f_flag = fp0->f_flag; fp->f_type = DTYPE_VNODE; fp->f_ops = &vnops; fp->f_data = (caddr_t)vp; fdinsert(fdp, fd, flags, fp); fdpunlock(fdp); closef(fp0, p); free(devname, M_DEVBUF, PATH_MAX); return 0; bad: fdpunlock(fdp); (void)vn_close(vp, fp0->f_flag, p->p_ucred, p); invalid: if (fp0) FRELE(fp0, p); free(devname, M_DEVBUF, PATH_MAX); return error; } int diskmapread(dev_t dev, struct uio *uio, int flag) { return ENXIO; } int diskmapwrite(dev_t dev, struct uio *uio, int flag) { return ENXIO; }
4 10 4 1 1 1 2 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 /* $OpenBSD: pckbd.c,v 1.51 2023/08/13 21:54:02 miod Exp $ */ /* $NetBSD: pckbd.c,v 1.24 2000/06/05 22:20:57 sommerfeld Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Charles M. Hannum. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz and Don Ahn. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)pccons.c 5.11 (Berkeley) 5/21/91 */ /* * code to work keyboard for PC-style console */ #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> #include <sys/malloc.h> #include <sys/ioctl.h> #include <machine/bus.h> #include <dev/ic/pckbcvar.h> #include <dev/pckbc/pckbdreg.h> #include <dev/pckbc/pmsreg.h> #include <dev/wscons/wsconsio.h> #include <dev/wscons/wskbdraw.h> #include <dev/wscons/wskbdvar.h> #include <dev/wscons/wsksymdef.h> #include <dev/wscons/wsksymvar.h> #include <dev/pckbc/wskbdmap_mfii.h> struct pckbd_internal { int t_isconsole; pckbc_tag_t t_kbctag; pckbc_slot_t t_kbcslot; int t_translating; /* nonzero if hardware performs translation */ int t_table; /* scan code set in use */ int t_lastchar; int t_extended; int t_extended1; int t_releasing; struct pckbd_softc *t_sc; /* back pointer */ }; struct pckbd_softc { struct device sc_dev; struct pckbd_internal *id; int sc_enabled; int sc_ledstate; struct device *sc_wskbddev; #ifdef WSDISPLAY_COMPAT_RAWKBD int rawkbd; u_int sc_rawcnt; char sc_rawbuf[3]; #endif }; static int pckbd_is_console(pckbc_tag_t, pckbc_slot_t); int pckbdprobe(struct device *, void *, void *); void pckbdattach(struct device *, struct device *, void *); int pckbdactivate(struct device *, int); const struct cfattach pckbd_ca = { sizeof(struct pckbd_softc), pckbdprobe, pckbdattach, NULL, pckbdactivate }; int pckbd_enable(void *, int); void pckbd_set_leds(void *, int); int pckbd_ioctl(void *, u_long, caddr_t, int, struct proc *); const struct wskbd_accessops pckbd_accessops = { pckbd_enable, pckbd_set_leds, pckbd_ioctl, }; void pckbd_cngetc(void *, u_int *, int *); void pckbd_cnpollc(void *, int); void pckbd_cnbell(void *, u_int, u_int, u_int); const struct wskbd_consops pckbd_consops = { pckbd_cngetc, pckbd_cnpollc, pckbd_cnbell, }; const struct wskbd_mapdata pckbd_keymapdata = { pckbd_keydesctab, #ifdef PCKBD_LAYOUT PCKBD_LAYOUT, #else KB_US | KB_DEFAULT, #endif }; /* * Hackish support for a bell on the PC Keyboard; when a suitable beeper * is found, it attaches itself into the pckbd driver here. */ void (*pckbd_bell_fn)(void *, u_int, u_int, u_int, int); void *pckbd_bell_fn_arg; void pckbd_bell(u_int, u_int, u_int, int); int pckbd_scancode_translate(struct pckbd_internal *, int); int pckbd_set_xtscancode(pckbc_tag_t, pckbc_slot_t, struct pckbd_internal *); void pckbd_init(struct pckbd_internal *, pckbc_tag_t, pckbc_slot_t, int); void pckbd_input(void *, int); static int pckbd_decode(struct pckbd_internal *, int, u_int *, int *); static int pckbd_led_encode(int); struct pckbd_internal pckbd_consdata; int pckbdactivate(struct device *self, int act) { struct pckbd_softc *sc = (struct pckbd_softc *)self; int rv = 0; u_char cmd[1]; switch(act) { case DVACT_RESUME: if (sc->sc_enabled) { /* * Some keyboards are not enabled after a reset, * so make sure it is enabled now. */ cmd[0] = KBC_ENABLE; (void) pckbc_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot, cmd, 1, 0, NULL, 0); /* XXX - also invoke pckbd_set_xtscancode() too? */ } break; } rv = config_activate_children(self, act); return (rv); } int pckbd_set_xtscancode(pckbc_tag_t kbctag, pckbc_slot_t kbcslot, struct pckbd_internal *id) { int table = 0; if (pckbc_xt_translation(kbctag, &table)) { #ifdef DEBUG printf("pckbd: enabling of translation failed\n"); #endif #ifdef __sparc64__ /* only pckbc@ebus on sparc64 uses this */ /* * If hardware lacks translation capability, stick to the * table it is using. */ if (table != 0) { id->t_translating = 0; id->t_table = table; return 0; } #endif /* * Since the keyboard controller can not translate scan * codes to the XT set (#1), we would like to request * this exact set. However it is likely that the * controller does not support it either. * * So try scan code set #2 as well, which this driver * knows how to translate. */ table = 2; if (id != NULL) id->t_translating = 0; } else { table = 3; if (id != NULL) { id->t_translating = 1; if (id->t_table == 0) { /* * Don't bother explicitly setting into set 2, * it's the default. */ id->t_table = 2; return (0); } } } /* keep falling back until we hit a table that looks usable. */ for (; table >= 1; table--) { u_char cmd[2]; #ifdef DEBUG printf("pckbd: trying table %d\n", table); #endif cmd[0] = KBC_SETTABLE; cmd[1] = table; if (pckbc_poll_cmd(kbctag, kbcslot, cmd, 2, 0, NULL, 0)) { #ifdef DEBUG printf("pckbd: table set of %d failed\n", table); #endif if (table > 1) { cmd[0] = KBC_RESET; (void)pckbc_poll_cmd(kbctag, kbcslot, cmd, 1, 1, NULL, 1); pckbc_flush(kbctag, kbcslot); continue; } } /* * the 8042 took the table set request, however, not all that * report they can work with table 3 actually work, so ask what * table it reports it's in. */ if (table == 3) { u_char resp[1]; cmd[0] = KBC_SETTABLE; cmd[1] = 0; if (pckbc_poll_cmd(kbctag, kbcslot, cmd, 2, 1, resp, 0)) { /* * query failed, step down to table 2 to be * safe. */ #ifdef DEBUG printf("pckbd: table 3 verification failed\n"); #endif continue; } else if (resp[0] == 3) { #ifdef DEBUG printf("pckbd: settling on table 3\n"); #endif break; } #ifdef DEBUG else printf("pckbd: table \"%x\" != 3, trying 2\n", resp[0]); #endif } else { #ifdef DEBUG printf("pckbd: settling on table %d\n", table); #endif break; } } if (table == 0) return (1); if (id != NULL) id->t_table = table; return (0); } static int pckbd_is_console(pckbc_tag_t tag, pckbc_slot_t slot) { return (pckbd_consdata.t_isconsole && (tag == pckbd_consdata.t_kbctag) && (slot == pckbd_consdata.t_kbcslot)); } /* * these are both bad jokes */ int pckbdprobe(struct device *parent, void *match, void *aux) { struct cfdata *cf = match; struct pckbc_attach_args *pa = aux; u_char cmd[1], resp[2]; int res; /* * XXX There are rumours that a keyboard can be connected * to the aux port as well. For me, this didn't work. * For further experiments, allow it if explicitly * wired in the config file. */ if ((pa->pa_slot != PCKBC_KBD_SLOT) && (cf->cf_loc[PCKBCCF_SLOT] == PCKBCCF_SLOT_DEFAULT)) return (0); /* Flush any garbage. */ pckbc_flush(pa->pa_tag, pa->pa_slot); /* Reset the keyboard. */ cmd[0] = KBC_RESET; res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 1, resp, 1); if (res != 0) { #ifdef DEBUG printf("pckbdprobe: reset error %d\n", res); #endif } else if (resp[0] != KBR_RSTDONE) { #ifdef DEBUG printf("pckbdprobe: reset response 0x%x\n", resp[0]); #endif res = EINVAL; } #if defined(__i386__) || defined(__amd64__) if (res) { /* * The 8042 emulation on Chromebooks fails the reset * command but otherwise appears to work correctly. * Try a "get ID" command to give it a second chance. */ cmd[0] = KBC_GETID; res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 0); if (res != 0) { #ifdef DEBUG printf("pckbdprobe: getid error %d\n", res); #endif } else if (resp[0] != 0xab || resp[1] != 0x83) { #ifdef DEBUG printf("pckbdprobe: unexpected id 0x%x/0x%x\n", resp[0], resp[1]); #endif res = EINVAL; } } #endif if (res) { /* * There is probably no keyboard connected. * Let the probe succeed if the keyboard is used * as console input - it can be connected later. */ #if defined(__i386__) || defined(__amd64__) /* * However, on legacy-free PCs, there might really * be no PS/2 connector at all; in that case, do not * even try to attach; ukbd will take over as console. */ if (res == ENXIO) { /* check cf_flags from parent */ struct cfdata *cf = parent->dv_cfdata; if (!ISSET(cf->cf_flags, PCKBCF_FORCE_KEYBOARD_PRESENT)) return 0; } #endif return (pckbd_is_console(pa->pa_tag, pa->pa_slot) ? 1 : 0); } /* * Some keyboards seem to leave a second ack byte after the reset. * This is kind of stupid, but we account for them anyway by just * flushing the buffer. */ pckbc_flush(pa->pa_tag, pa->pa_slot); return (2); } void pckbdattach(struct device *parent, struct device *self, void *aux) { struct pckbd_softc *sc = (void *)self; struct pckbc_attach_args *pa = aux; int isconsole; struct wskbddev_attach_args a; u_char cmd[1]; isconsole = pckbd_is_console(pa->pa_tag, pa->pa_slot); if (isconsole) { sc->id = &pckbd_consdata; if (sc->id->t_table == 0) pckbd_set_xtscancode(pa->pa_tag, pa->pa_slot, sc->id); /* * Some keyboards are not enabled after a reset, * so make sure it is enabled now. */ cmd[0] = KBC_ENABLE; (void) pckbc_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot, cmd, 1, 0, NULL, 0); sc->sc_enabled = 1; } else { sc->id = malloc(sizeof(struct pckbd_internal), M_DEVBUF, M_WAITOK); pckbd_init(sc->id, pa->pa_tag, pa->pa_slot, 0); pckbd_set_xtscancode(pa->pa_tag, pa->pa_slot, sc->id); /* no interrupts until enabled */ cmd[0] = KBC_DISABLE; (void) pckbc_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot, cmd, 1, 0, NULL, 0); sc->sc_enabled = 0; } sc->id->t_sc = sc; pckbc_set_inputhandler(sc->id->t_kbctag, sc->id->t_kbcslot, pckbd_input, sc, sc->sc_dev.dv_xname); a.console = isconsole; a.keymap = &pckbd_keymapdata; a.accessops = &pckbd_accessops; a.accesscookie = sc; printf("\n"); /* * Attach the wskbd, saving a handle to it. */ sc->sc_wskbddev = config_found(self, &a, wskbddevprint); } int pckbd_enable(void *v, int on) { struct pckbd_softc *sc = v; u_char cmd[1]; int res; if (on) { if (sc->sc_enabled) return (EBUSY); pckbc_slot_enable(sc->id->t_kbctag, sc->id->t_kbcslot, 1); cmd[0] = KBC_ENABLE; res = pckbc_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot, cmd, 1, 0, NULL, 0); if (res) { printf("pckbd_enable: command error\n"); return (res); } res = pckbd_set_xtscancode(sc->id->t_kbctag, sc->id->t_kbcslot, sc->id); if (res) return (res); sc->sc_enabled = 1; } else { if (sc->id->t_isconsole) return (EBUSY); cmd[0] = KBC_DISABLE; res = pckbc_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot, cmd, 1, 0, 1, 0); if (res) { printf("pckbd_disable: command error\n"); return (res); } pckbc_slot_enable(sc->id->t_kbctag, sc->id->t_kbcslot, 0); sc->sc_enabled = 0; } return (0); } /* * Scan code set #2 translation tables */ const u_int8_t pckbd_xtbl2[] = { /* 0x00 */ 0, RAWKEY_f9, 0, RAWKEY_f5, RAWKEY_f3, RAWKEY_f1, RAWKEY_f2, RAWKEY_f12, RAWKEY_f6, /* F6 according to documentation */ RAWKEY_f10, RAWKEY_f8, RAWKEY_f6, /* F6 according to experimentation */ RAWKEY_f4, RAWKEY_Tab, RAWKEY_grave, 0, /* 0x10 */ 0, RAWKEY_Alt_L, RAWKEY_Shift_L, 0, RAWKEY_Control_L, RAWKEY_q, RAWKEY_1, 0, 0, 0, RAWKEY_z, RAWKEY_s, RAWKEY_a, RAWKEY_w, RAWKEY_2, RAWKEY_Meta_L, /* 0x20 */ 0, RAWKEY_c, RAWKEY_x, RAWKEY_d, RAWKEY_e, RAWKEY_4, RAWKEY_3, 0, RAWKEY_Meta_R, RAWKEY_space, RAWKEY_v, RAWKEY_f, RAWKEY_t, RAWKEY_r, RAWKEY_5, 0, /* 0x30 */ 0, RAWKEY_n, RAWKEY_b, RAWKEY_h, RAWKEY_g, RAWKEY_y, RAWKEY_6, 0, 0, 0, RAWKEY_m, RAWKEY_j, RAWKEY_u, RAWKEY_7, RAWKEY_8, 0, /* 0x40 */ 0, RAWKEY_comma, RAWKEY_k, RAWKEY_i, RAWKEY_o, RAWKEY_0, RAWKEY_9, 0, 0, RAWKEY_period, RAWKEY_slash, RAWKEY_l, RAWKEY_semicolon, RAWKEY_p, RAWKEY_minus, 0, /* 0x50 */ 0, 0, RAWKEY_apostrophe, 0, RAWKEY_bracketleft, RAWKEY_equal, 0, 0, RAWKEY_Caps_Lock, RAWKEY_Shift_R, RAWKEY_Return, RAWKEY_bracketright, 0, RAWKEY_backslash, 0, 0, /* 0x60 */ 0, 0, 0, 0, 0, 0, RAWKEY_BackSpace, 0, 0, RAWKEY_KP_End, 0, RAWKEY_KP_Left, RAWKEY_KP_Home, 0, 0, 0, /* 0x70 */ RAWKEY_KP_Insert, RAWKEY_KP_Delete, RAWKEY_KP_Down, RAWKEY_KP_Begin, RAWKEY_KP_Right, RAWKEY_KP_Up, RAWKEY_Escape, RAWKEY_Num_Lock, RAWKEY_f11, RAWKEY_KP_Add, RAWKEY_KP_Next, RAWKEY_KP_Subtract, RAWKEY_KP_Multiply, RAWKEY_KP_Prior, RAWKEY_Hold_Screen, 0, /* 0x80 */ 0, 0, 0, RAWKEY_f7, 0 /* Alt-Print Screen */ }; const u_int8_t pckbd_xtbl2_ext[] = { /* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */ 0, RAWKEY_Alt_R, 0, /* E0 12, to be ignored */ 0, RAWKEY_Control_R, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RAWKEY_KP_Divide, 0, 0, 0, 0, 0, /* 0x50 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RAWKEY_KP_Enter, 0, 0, 0, 0, 0, /* 0x60 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, RAWKEY_End, 0, RAWKEY_Left, RAWKEY_Home, 0, 0, 0, /* 0x70 */ RAWKEY_Insert, RAWKEY_Delete, RAWKEY_Down, 0, RAWKEY_Right, RAWKEY_Up, 0, 0, 0, 0, RAWKEY_Next, 0, RAWKEY_Print_Screen, RAWKEY_Prior, 0xc6, /* Ctrl-Break */ 0 }; #ifdef __sparc64__ /* only pckbc@ebus on sparc64 uses this */ /* * Scan code set #3 translation table */ const u_int8_t pckbd_xtbl3[] = { /* 0x00 */ 0, RAWKEY_L5, /* Front */ RAWKEY_L1, /* Stop */ RAWKEY_L3, /* Props */ 0, RAWKEY_L7, /* Open */ RAWKEY_L9, /* Find */ RAWKEY_f1, RAWKEY_Escape, RAWKEY_L10, /* Cut */ 0, 0, 0, RAWKEY_Tab, RAWKEY_grave, RAWKEY_f2, /* 0x10 */ RAWKEY_Help, RAWKEY_Control_L, RAWKEY_Shift_L, 0, RAWKEY_Caps_Lock, RAWKEY_q, RAWKEY_1, RAWKEY_f3, 0, RAWKEY_Alt_L, RAWKEY_z, RAWKEY_s, RAWKEY_a, RAWKEY_w, RAWKEY_2, RAWKEY_f4, /* 0x20 */ 0, RAWKEY_c, RAWKEY_x, RAWKEY_d, RAWKEY_e, RAWKEY_4, RAWKEY_3, RAWKEY_f5, RAWKEY_L4, /* Undo */ RAWKEY_space, RAWKEY_v, RAWKEY_f, RAWKEY_t, RAWKEY_r, RAWKEY_5, RAWKEY_f6, /* 0x30 */ RAWKEY_L2, /* Again */ RAWKEY_n, RAWKEY_b, RAWKEY_h, RAWKEY_g, RAWKEY_y, RAWKEY_6, RAWKEY_f7, 0, RAWKEY_Alt_R, RAWKEY_m, RAWKEY_j, RAWKEY_u, RAWKEY_7, RAWKEY_8, RAWKEY_f8, /* 0x40 */ 0, RAWKEY_comma, RAWKEY_k, RAWKEY_i, RAWKEY_o, RAWKEY_0, RAWKEY_9, RAWKEY_f9, RAWKEY_L6, /* Copy */ RAWKEY_period, RAWKEY_slash, RAWKEY_l, RAWKEY_semicolon, RAWKEY_p, RAWKEY_minus, RAWKEY_f10, /* 0x50 */ 0, 0, RAWKEY_apostrophe, 0, RAWKEY_bracketleft, RAWKEY_equal, RAWKEY_f11, RAWKEY_Print_Screen, RAWKEY_Control_R, RAWKEY_Shift_R, RAWKEY_Return, RAWKEY_bracketright, RAWKEY_backslash, 0, RAWKEY_f12, RAWKEY_Hold_Screen, /* 0x60 */ RAWKEY_Down, RAWKEY_Left, RAWKEY_Pause, RAWKEY_Up, RAWKEY_Delete, RAWKEY_End, RAWKEY_BackSpace, RAWKEY_Insert, RAWKEY_L8, /* Paste */ RAWKEY_KP_End, RAWKEY_Right, RAWKEY_KP_Left, RAWKEY_KP_Home, RAWKEY_Next, RAWKEY_Home, RAWKEY_Prior, /* 0x70 */ RAWKEY_KP_Insert, RAWKEY_KP_Delete, RAWKEY_KP_Down, RAWKEY_KP_Begin, RAWKEY_KP_Right, RAWKEY_KP_Up, RAWKEY_Num_Lock, RAWKEY_KP_Divide, 0, RAWKEY_KP_Enter, RAWKEY_KP_Next, 0, RAWKEY_KP_Add, RAWKEY_KP_Prior, RAWKEY_KP_Multiply, 0, /* 0x80 */ 0, 0, 0, 0, RAWKEY_KP_Subtract, 0, 0, 0, 0, 0, 0, RAWKEY_Meta_L, RAWKEY_Meta_R }; #endif /* * Translate scan codes from set 2 or 3 to set 1 */ int pckbd_scancode_translate(struct pckbd_internal *id, int datain) { if (id->t_translating != 0 || id->t_table == 1) return datain; if (datain == KBR_BREAK) { id->t_releasing = 0x80; /* next keycode is a release */ return 0; /* consume scancode */ } switch (id->t_table) { case 2: /* * Convert BREAK sequence (14 77 -> 1D 45) */ if (id->t_extended1 == 2 && datain == 0x14) return 0x1d | id->t_releasing; else if (id->t_extended1 == 1 && datain == 0x77) return 0x45 | id->t_releasing; if (id->t_extended != 0) { if (datain >= sizeof pckbd_xtbl2_ext) datain = 0; else datain = pckbd_xtbl2_ext[datain]; /* xtbl2_ext already has the upper bit set */ id->t_extended = 0; } else { if (datain >= sizeof pckbd_xtbl2) datain = 0; else datain = pckbd_xtbl2[datain] & ~0x80; } break; #ifdef __sparc64__ /* only pckbc@ebus on sparc64 uses this */ case 3: if (datain >= sizeof pckbd_xtbl3) datain = 0; else datain = pckbd_xtbl3[datain] & ~0x80; break; #endif } if (datain == 0) { /* * We don't know how to translate this scan code, but * we can't silently eat it either (because there might * have been an extended byte transmitted already). * Hopefully this value will be harmless to the upper * layers. */ return 0xff; } return datain | id->t_releasing; } static int pckbd_decode(struct pckbd_internal *id, int datain, u_int *type, int *dataout) { int key; int releasing; if (datain == KBR_EXTENDED0) { id->t_extended = 0x80; return 0; } else if (datain == KBR_EXTENDED1) { id->t_extended1 = 2; return 0; } releasing = datain & 0x80; datain &= 0x7f; /* * process BREAK key sequence (EXT1 1D 45 / EXT1 9D C5): * map to (unused) code 7F */ if (id->t_extended1 == 2 && datain == 0x1d) { id->t_extended1 = 1; return 0; } else if (id->t_extended1 == 1 && datain == 0x45) { id->t_extended1 = 0; datain = 0x7f; } else id->t_extended1 = 0; if (id->t_translating != 0 || id->t_table == 1) { id->t_releasing = releasing; } else { /* id->t_releasing computed in pckbd_scancode_translate() */ } /* map extended keys to (unused) codes 128-254 */ key = datain | id->t_extended; id->t_extended = 0; if (id->t_releasing) { id->t_releasing = 0; id->t_lastchar = 0; *type = WSCONS_EVENT_KEY_UP; } else { /* Always ignore typematic keys */ if (key == id->t_lastchar) return 0; id->t_lastchar = key; *type = WSCONS_EVENT_KEY_DOWN; } *dataout = key; return 1; } void pckbd_init(struct pckbd_internal *t, pckbc_tag_t kbctag, pckbc_slot_t kbcslot, int console) { bzero(t, sizeof(struct pckbd_internal)); t->t_isconsole = console; t->t_kbctag = kbctag; t->t_kbcslot = kbcslot; } static int pckbd_led_encode(int led) { int res; res = 0; if (led & WSKBD_LED_SCROLL) res |= 0x01; if (led & WSKBD_LED_NUM) res |= 0x02; if (led & WSKBD_LED_CAPS) res |= 0x04; return(res); } void pckbd_set_leds(void *v, int leds) { struct pckbd_softc *sc = v; u_char cmd[2]; cmd[0] = KBC_MODEIND; cmd[1] = pckbd_led_encode(leds); sc->sc_ledstate = leds; (void) pckbc_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot, cmd, 2, 0, 0, 0); } /* * Got a console receive interrupt - * the console processor wants to give us a character. */ void pckbd_input(void *vsc, int data) { struct pckbd_softc *sc = vsc; int rc, type, key; data = pckbd_scancode_translate(sc->id, data); if (data == 0) return; rc = pckbd_decode(sc->id, data, &type, &key); #ifdef WSDISPLAY_COMPAT_RAWKBD if (sc->rawkbd) { sc->sc_rawbuf[sc->sc_rawcnt++] = (char)data; if (rc != 0 || sc->sc_rawcnt == sizeof(sc->sc_rawbuf)) { wskbd_rawinput(sc->sc_wskbddev, sc->sc_rawbuf, sc->sc_rawcnt); sc->sc_rawcnt = 0; } /* * Pass audio keys to wskbd_input anyway. */ if (rc == 0 || (key != 160 && key != 174 && key != 176)) return; } #endif if (rc != 0) wskbd_input(sc->sc_wskbddev, type, key); } int pckbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) { struct pckbd_softc *sc = v; switch (cmd) { case WSKBDIO_GTYPE: *(int *)data = WSKBD_TYPE_PC_XT; return 0; case WSKBDIO_SETLEDS: { char cmd[2]; int res; cmd[0] = KBC_MODEIND; cmd[1] = pckbd_led_encode(*(int *)data); sc->sc_ledstate = *(int *)data & (WSKBD_LED_SCROLL | WSKBD_LED_NUM | WSKBD_LED_CAPS); res = pckbc_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot, cmd, 2, 0, 1, 0); return (res); } case WSKBDIO_GETLEDS: *(int *)data = sc->sc_ledstate; return (0); case WSKBDIO_COMPLEXBELL: #define d ((struct wskbd_bell_data *)data) /* * Keyboard can't beep directly; we have an * externally-provided global hook to do this. */ pckbd_bell(d->pitch, d->period, d->volume, 0); #undef d return (0); #ifdef WSDISPLAY_COMPAT_RAWKBD case WSKBDIO_SETMODE: sc->rawkbd = (*(int *)data == WSKBD_RAW); return (0); #endif } return -1; } void pckbd_bell(u_int pitch, u_int period, u_int volume, int poll) { if (pckbd_bell_fn != NULL) (*pckbd_bell_fn)(pckbd_bell_fn_arg, pitch, period, volume, poll); } void pckbd_hookup_bell(void (*fn)(void *, u_int, u_int, u_int, int), void *arg) { if (pckbd_bell_fn == NULL) { pckbd_bell_fn = fn; pckbd_bell_fn_arg = arg; } } int pckbd_cnattach(pckbc_tag_t kbctag) { pckbd_init(&pckbd_consdata, kbctag, PCKBC_KBD_SLOT, 1); wskbd_cnattach(&pckbd_consops, &pckbd_consdata, &pckbd_keymapdata); return (0); } void pckbd_cngetc(void *v, u_int *type, int *data) { struct pckbd_internal *t = v; int val; for (;;) { val = pckbc_poll_data(t->t_kbctag, t->t_kbcslot); if (val == -1) continue; val = pckbd_scancode_translate(t, val); if (val == 0) continue; if (pckbd_decode(t, val, type, data)) return; } } void pckbd_cnpollc(void *v, int on) { struct pckbd_internal *t = v; pckbc_set_poll(t->t_kbctag, t->t_kbcslot, on); /* * If we enter ukc or ddb before having attached the console * keyboard we need to probe its scan code set. */ if (t->t_table == 0) { char cmd[1]; pckbc_flush(t->t_kbctag, t->t_kbcslot); pckbd_set_xtscancode(t->t_kbctag, t->t_kbcslot, t); /* Just to be sure. */ cmd[0] = KBC_ENABLE; pckbc_poll_cmd(t->t_kbctag, PCKBC_KBD_SLOT, cmd, 1, 0, NULL, 0); } } void pckbd_cnbell(void *v, u_int pitch, u_int period, u_int volume) { pckbd_bell(pitch, period, volume, 1); } struct cfdriver pckbd_cd = { NULL, "pckbd", DV_DULL };
11 9 2 2 2 11 11 11 1 11 11 11 32 32 11 22 11 11 11 11 22 22 22 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 /* $OpenBSD: if_vio.c,v 1.35 2024/05/24 10:05:55 jsg Exp $ */ /* * Copyright (c) 2012 Stefan Fritsch, Alexander Fiveg. * Copyright (c) 2010 Minoura Makoto. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "bpfilter.h" #include "vlan.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> #include <sys/mbuf.h> #include <sys/sockio.h> #include <sys/timeout.h> #include <dev/pv/virtioreg.h> #include <dev/pv/virtiovar.h> #include <net/if.h> #include <net/if_media.h> #include <net/route.h> #include <netinet/if_ether.h> #include <netinet/tcp.h> #include <netinet/tcp_timer.h> #include <netinet/tcp_var.h> #include <netinet/udp.h> #if NBPFILTER > 0 #include <net/bpf.h> #endif #if VIRTIO_DEBUG #define DPRINTF(x...) printf(x) #else #define DPRINTF(x...) #endif /* * if_vioreg.h: */ /* Configuration registers */ #define VIRTIO_NET_CONFIG_MAC 0 /* 8bit x 6byte */ #define VIRTIO_NET_CONFIG_STATUS 6 /* 16bit */ /* Feature bits */ #define VIRTIO_NET_F_CSUM (1ULL<<0) #define VIRTIO_NET_F_GUEST_CSUM (1ULL<<1) #define VIRTIO_NET_F_CTRL_GUEST_OFFLOADS (1ULL<<2) #define VIRTIO_NET_F_MTU (1ULL<<3) #define VIRTIO_NET_F_MAC (1ULL<<5) #define VIRTIO_NET_F_GSO (1ULL<<6) #define VIRTIO_NET_F_GUEST_TSO4 (1ULL<<7) #define VIRTIO_NET_F_GUEST_TSO6 (1ULL<<8) #define VIRTIO_NET_F_GUEST_ECN (1ULL<<9) #define VIRTIO_NET_F_GUEST_UFO (1ULL<<10) #define VIRTIO_NET_F_HOST_TSO4 (1ULL<<11) #define VIRTIO_NET_F_HOST_TSO6 (1ULL<<12) #define VIRTIO_NET_F_HOST_ECN (1ULL<<13) #define VIRTIO_NET_F_HOST_UFO (1ULL<<14) #define VIRTIO_NET_F_MRG_RXBUF (1ULL<<15) #define VIRTIO_NET_F_STATUS (1ULL<<16) #define VIRTIO_NET_F_CTRL_VQ (1ULL<<17) #define VIRTIO_NET_F_CTRL_RX (1ULL<<18) #define VIRTIO_NET_F_CTRL_VLAN (1ULL<<19) #define VIRTIO_NET_F_CTRL_RX_EXTRA (1ULL<<20) #define VIRTIO_NET_F_GUEST_ANNOUNCE (1ULL<<21) #define VIRTIO_NET_F_MQ (1ULL<<22) #define VIRTIO_NET_F_CTRL_MAC_ADDR (1ULL<<23) /* * Config(8) flags. The lowest byte is reserved for generic virtio stuff. */ /* Workaround for vlan related bug in qemu < version 2.0 */ #define CONFFLAG_QEMU_VLAN_BUG (1<<8) static const struct virtio_feature_name virtio_net_feature_names[] = { #if VIRTIO_DEBUG { VIRTIO_NET_F_CSUM, "CSum" }, { VIRTIO_NET_F_GUEST_CSUM, "GuestCSum" }, { VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, "CtrlGuestOffl" }, { VIRTIO_NET_F_MTU, "MTU", }, { VIRTIO_NET_F_MAC, "MAC" }, { VIRTIO_NET_F_GSO, "GSO" }, { VIRTIO_NET_F_GUEST_TSO4, "GuestTSO4" }, { VIRTIO_NET_F_GUEST_TSO6, "GuestTSO6" }, { VIRTIO_NET_F_GUEST_ECN, "GuestECN" }, { VIRTIO_NET_F_GUEST_UFO, "GuestUFO" }, { VIRTIO_NET_F_HOST_TSO4, "HostTSO4" }, { VIRTIO_NET_F_HOST_TSO6, "HostTSO6" }, { VIRTIO_NET_F_HOST_ECN, "HostECN" }, { VIRTIO_NET_F_HOST_UFO, "HostUFO" }, { VIRTIO_NET_F_MRG_RXBUF, "MrgRXBuf" }, { VIRTIO_NET_F_STATUS, "Status" }, { VIRTIO_NET_F_CTRL_VQ, "CtrlVQ" }, { VIRTIO_NET_F_CTRL_RX, "CtrlRX" }, { VIRTIO_NET_F_CTRL_VLAN, "CtrlVLAN" }, { VIRTIO_NET_F_CTRL_RX_EXTRA, "CtrlRXExtra" }, { VIRTIO_NET_F_GUEST_ANNOUNCE, "GuestAnnounce" }, { VIRTIO_NET_F_MQ, "MQ" }, { VIRTIO_NET_F_CTRL_MAC_ADDR, "CtrlMAC" }, #endif { 0, NULL } }; /* Status */ #define VIRTIO_NET_S_LINK_UP 1 /* Packet header structure */ struct virtio_net_hdr { uint8_t flags; uint8_t gso_type; uint16_t hdr_len; uint16_t gso_size; uint16_t csum_start; uint16_t csum_offset; /* only present if VIRTIO_NET_F_MRG_RXBUF is negotiated */ uint16_t num_buffers; } __packed; #define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 /* flags */ #define VIRTIO_NET_HDR_F_DATA_VALID 2 /* flags */ #define VIRTIO_NET_HDR_GSO_NONE 0 /* gso_type */ #define VIRTIO_NET_HDR_GSO_TCPV4 1 /* gso_type */ #define VIRTIO_NET_HDR_GSO_UDP 3 /* gso_type */ #define VIRTIO_NET_HDR_GSO_TCPV6 4 /* gso_type */ #define VIRTIO_NET_HDR_GSO_ECN 0x80 /* gso_type, |'ed */ #define VIRTIO_NET_MAX_GSO_LEN (65536+ETHER_HDR_LEN) /* Control virtqueue */ struct virtio_net_ctrl_cmd { uint8_t class; uint8_t command; } __packed; #define VIRTIO_NET_CTRL_RX 0 # define VIRTIO_NET_CTRL_RX_PROMISC 0 # define VIRTIO_NET_CTRL_RX_ALLMULTI 1 #define VIRTIO_NET_CTRL_MAC 1 # define VIRTIO_NET_CTRL_MAC_TABLE_SET 0 #define VIRTIO_NET_CTRL_VLAN 2 # define VIRTIO_NET_CTRL_VLAN_ADD 0 # define VIRTIO_NET_CTRL_VLAN_DEL 1 struct virtio_net_ctrl_status { uint8_t ack; } __packed; #define VIRTIO_NET_OK 0 #define VIRTIO_NET_ERR 1 struct virtio_net_ctrl_rx { uint8_t onoff; } __packed; struct virtio_net_ctrl_mac_tbl { uint32_t nentries; uint8_t macs[][ETHER_ADDR_LEN]; } __packed; struct virtio_net_ctrl_vlan { uint16_t id; } __packed; /* * if_viovar.h: */ enum vio_ctrl_state { FREE, INUSE, DONE, RESET }; struct vio_softc { struct device sc_dev; struct virtio_softc *sc_virtio; #define VQRX 0 #define VQTX 1 #define VQCTL 2 struct virtqueue sc_vq[3]; struct arpcom sc_ac; struct ifmedia sc_media; short sc_ifflags; /* bus_dmamem */ bus_dma_segment_t sc_dma_seg; bus_dmamap_t sc_dma_map; size_t sc_dma_size; caddr_t sc_dma_kva; int sc_hdr_size; struct virtio_net_hdr *sc_tx_hdrs; struct virtio_net_ctrl_cmd *sc_ctrl_cmd; struct virtio_net_ctrl_status *sc_ctrl_status; struct virtio_net_ctrl_rx *sc_ctrl_rx; struct virtio_net_ctrl_mac_tbl *sc_ctrl_mac_tbl_uc; #define sc_ctrl_mac_info sc_ctrl_mac_tbl_uc struct virtio_net_ctrl_mac_tbl *sc_ctrl_mac_tbl_mc; /* kmem */ bus_dmamap_t *sc_arrays; #define sc_rx_dmamaps sc_arrays bus_dmamap_t *sc_tx_dmamaps; struct mbuf **sc_rx_mbufs; struct mbuf **sc_tx_mbufs; struct if_rxring sc_rx_ring; enum vio_ctrl_state sc_ctrl_inuse; struct timeout sc_txtick, sc_rxtick; }; #define VIO_DMAMEM_OFFSET(sc, p) ((caddr_t)(p) - (sc)->sc_dma_kva) #define VIO_DMAMEM_SYNC(vsc, sc, p, size, flags) \ bus_dmamap_sync((vsc)->sc_dmat, (sc)->sc_dma_map, \ VIO_DMAMEM_OFFSET((sc), (p)), (size), (flags)) #define VIO_DMAMEM_ENQUEUE(sc, vq, slot, p, size, write) \ virtio_enqueue_p((vq), (slot), (sc)->sc_dma_map, \ VIO_DMAMEM_OFFSET((sc), (p)), (size), (write)) #define VIO_HAVE_MRG_RXBUF(sc) \ ((sc)->sc_hdr_size == sizeof(struct virtio_net_hdr)) #define VIRTIO_NET_TX_MAXNSEGS 16 /* for larger chains, defrag */ #define VIRTIO_NET_CTRL_MAC_MC_ENTRIES 64 /* for more entries, use ALLMULTI */ #define VIRTIO_NET_CTRL_MAC_UC_ENTRIES 1 /* one entry for own unicast addr */ #define VIRTIO_NET_CTRL_TIMEOUT (5*1000*1000*1000ULL) /* 5 seconds */ #define VIO_CTRL_MAC_INFO_SIZE \ (2*sizeof(struct virtio_net_ctrl_mac_tbl) + \ (VIRTIO_NET_CTRL_MAC_MC_ENTRIES + \ VIRTIO_NET_CTRL_MAC_UC_ENTRIES) * ETHER_ADDR_LEN) /* cfattach interface functions */ int vio_match(struct device *, void *, void *); void vio_attach(struct device *, struct device *, void *); /* ifnet interface functions */ int vio_init(struct ifnet *); void vio_stop(struct ifnet *, int); void vio_start(struct ifnet *); int vio_ioctl(struct ifnet *, u_long, caddr_t); void vio_get_lladdr(struct arpcom *ac, struct virtio_softc *vsc); void vio_put_lladdr(struct arpcom *ac, struct virtio_softc *vsc); /* rx */ int vio_add_rx_mbuf(struct vio_softc *, int); void vio_free_rx_mbuf(struct vio_softc *, int); void vio_populate_rx_mbufs(struct vio_softc *); int vio_rxeof(struct vio_softc *); int vio_rx_intr(struct virtqueue *); void vio_rx_drain(struct vio_softc *); void vio_rxtick(void *); /* tx */ int vio_tx_intr(struct virtqueue *); int vio_txeof(struct virtqueue *); void vio_tx_drain(struct vio_softc *); int vio_encap(struct vio_softc *, int, struct mbuf *); void vio_txtick(void *); /* other control */ void vio_link_state(struct ifnet *); int vio_config_change(struct virtio_softc *); int vio_ctrl_rx(struct vio_softc *, int, int); int vio_set_rx_filter(struct vio_softc *); void vio_iff(struct vio_softc *); int vio_media_change(struct ifnet *); void vio_media_status(struct ifnet *, struct ifmediareq *); int vio_ctrleof(struct virtqueue *); int vio_wait_ctrl(struct vio_softc *sc); int vio_wait_ctrl_done(struct vio_softc *sc); void vio_ctrl_wakeup(struct vio_softc *, enum vio_ctrl_state); int vio_alloc_mem(struct vio_softc *); int vio_alloc_dmamem(struct vio_softc *); void vio_free_dmamem(struct vio_softc *); #if VIRTIO_DEBUG void vio_dump(struct vio_softc *); #endif int vio_match(struct device *parent, void *match, void *aux) { struct virtio_softc *va = aux; if (va->sc_childdevid == PCI_PRODUCT_VIRTIO_NETWORK) return 1; return 0; } const struct cfattach vio_ca = { sizeof(struct vio_softc), vio_match, vio_attach, NULL }; struct cfdriver vio_cd = { NULL, "vio", DV_IFNET }; int vio_alloc_dmamem(struct vio_softc *sc) { struct virtio_softc *vsc = sc->sc_virtio; int nsegs; if (bus_dmamap_create(vsc->sc_dmat, sc->sc_dma_size, 1, sc->sc_dma_size, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->sc_dma_map) != 0) goto err; if (bus_dmamem_alloc(vsc->sc_dmat, sc->sc_dma_size, 16, 0, &sc->sc_dma_seg, 1, &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO) != 0) goto destroy; if (bus_dmamem_map(vsc->sc_dmat, &sc->sc_dma_seg, nsegs, sc->sc_dma_size, &sc->sc_dma_kva, BUS_DMA_NOWAIT) != 0) goto free; if (bus_dmamap_load(vsc->sc_dmat, sc->sc_dma_map, sc->sc_dma_kva, sc->sc_dma_size, NULL, BUS_DMA_NOWAIT) != 0) goto unmap; return (0); unmap: bus_dmamem_unmap(vsc->sc_dmat, sc->sc_dma_kva, sc->sc_dma_size); free: bus_dmamem_free(vsc->sc_dmat, &sc->sc_dma_seg, 1); destroy: bus_dmamap_destroy(vsc->sc_dmat, sc->sc_dma_map); err: return (1); } void vio_free_dmamem(struct vio_softc *sc) { struct virtio_softc *vsc = sc->sc_virtio; bus_dmamap_unload(vsc->sc_dmat, sc->sc_dma_map); bus_dmamem_unmap(vsc->sc_dmat, sc->sc_dma_kva, sc->sc_dma_size); bus_dmamem_free(vsc->sc_dmat, &sc->sc_dma_seg, 1); bus_dmamap_destroy(vsc->sc_dmat, sc->sc_dma_map); } /* allocate memory */ /* * dma memory is used for: * sc_tx_hdrs[slot]: metadata array for frames to be sent (WRITE) * sc_ctrl_cmd: command to be sent via ctrl vq (WRITE) * sc_ctrl_status: return value for a command via ctrl vq (READ) * sc_ctrl_rx: parameter for a VIRTIO_NET_CTRL_RX class command * (WRITE) * sc_ctrl_mac_tbl_uc: unicast MAC address filter for a VIRTIO_NET_CTRL_MAC * class command (WRITE) * sc_ctrl_mac_tbl_mc: multicast MAC address filter for a VIRTIO_NET_CTRL_MAC * class command (WRITE) * sc_ctrl_* structures are allocated only one each; they are protected by * sc_ctrl_inuse, which must only be accessed at splnet * * metadata headers for received frames are stored at the start of the * rx mbufs. */ /* * dynamically allocated memory is used for: * sc_rx_dmamaps[slot]: bus_dmamap_t array for received payload * sc_tx_dmamaps[slot]: bus_dmamap_t array for sent payload * sc_rx_mbufs[slot]: mbuf pointer array for received frames * sc_tx_mbufs[slot]: mbuf pointer array for sent frames */ int vio_alloc_mem(struct vio_softc *sc) { struct virtio_softc *vsc = sc->sc_virtio; struct ifnet *ifp = &sc->sc_ac.ac_if; int allocsize, r, i, txsize; unsigned int offset = 0; int rxqsize, txqsize; caddr_t kva; rxqsize = vsc->sc_vqs[0].vq_num; txqsize = vsc->sc_vqs[1].vq_num; /* * For simplicity, we always allocate the full virtio_net_hdr size * even if VIRTIO_NET_F_MRG_RXBUF is not negotiated and * only a part of the memory is ever used. */ allocsize = sizeof(struct virtio_net_hdr) * txqsize; if (vsc->sc_nvqs == 3) { allocsize += sizeof(struct virtio_net_ctrl_cmd) * 1; allocsize += sizeof(struct virtio_net_ctrl_status) * 1; allocsize += sizeof(struct virtio_net_ctrl_rx) * 1; allocsize += VIO_CTRL_MAC_INFO_SIZE; } sc->sc_dma_size = allocsize; if (vio_alloc_dmamem(sc) != 0) { printf("unable to allocate dma region\n"); return -1; } kva = sc->sc_dma_kva; sc->sc_tx_hdrs = (struct virtio_net_hdr*)(kva + offset); offset += sizeof(struct virtio_net_hdr) * txqsize; if (vsc->sc_nvqs == 3) { sc->sc_ctrl_cmd = (void*)(kva + offset); offset += sizeof(*sc->sc_ctrl_cmd); sc->sc_ctrl_status = (void*)(kva + offset); offset += sizeof(*sc->sc_ctrl_status); sc->sc_ctrl_rx = (void*)(kva + offset); offset += sizeof(*sc->sc_ctrl_rx); sc->sc_ctrl_mac_tbl_uc = (void*)(kva + offset); offset += sizeof(*sc->sc_ctrl_mac_tbl_uc) + ETHER_ADDR_LEN * VIRTIO_NET_CTRL_MAC_UC_ENTRIES; sc->sc_ctrl_mac_tbl_mc = (void*)(kva + offset); } sc->sc_arrays = mallocarray(rxqsize + txqsize, 2 * sizeof(bus_dmamap_t) + sizeof(struct mbuf *), M_DEVBUF, M_WAITOK | M_CANFAIL | M_ZERO); if (sc->sc_arrays == NULL) { printf("unable to allocate mem for dmamaps\n"); goto err_hdr; } allocsize = (rxqsize + txqsize) * (2 * sizeof(bus_dmamap_t) + sizeof(struct mbuf *)); sc->sc_tx_dmamaps = sc->sc_arrays + rxqsize; sc->sc_rx_mbufs = (void*) (sc->sc_tx_dmamaps + txqsize); sc->sc_tx_mbufs = sc->sc_rx_mbufs + rxqsize; for (i = 0; i < rxqsize; i++) { r = bus_dmamap_create(vsc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &sc->sc_rx_dmamaps[i]); if (r != 0) goto err_reqs; } txsize = ifp->if_hardmtu + sc->sc_hdr_size + ETHER_HDR_LEN; for (i = 0; i < txqsize; i++) { r = bus_dmamap_create(vsc->sc_dmat, txsize, VIRTIO_NET_TX_MAXNSEGS, txsize, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &sc->sc_tx_dmamaps[i]); if (r != 0) goto err_reqs; } return 0; err_reqs: printf("dmamap creation failed, error %d\n", r); for (i = 0; i < txqsize; i++) { if (sc->sc_tx_dmamaps[i]) bus_dmamap_destroy(vsc->sc_dmat, sc->sc_tx_dmamaps[i]); } for (i = 0; i < rxqsize; i++) { if (sc->sc_rx_dmamaps[i]) bus_dmamap_destroy(vsc->sc_dmat, sc->sc_rx_dmamaps[i]); } if (sc->sc_arrays) { free(sc->sc_arrays, M_DEVBUF, allocsize); sc->sc_arrays = 0; } err_hdr: vio_free_dmamem(sc); return -1; } void vio_get_lladdr(struct arpcom *ac, struct virtio_softc *vsc) { int i; for (i = 0; i < ETHER_ADDR_LEN; i++) { ac->ac_enaddr[i] = virtio_read_device_config_1(vsc, VIRTIO_NET_CONFIG_MAC + i); } } void vio_put_lladdr(struct arpcom *ac, struct virtio_softc *vsc) { int i; for (i = 0; i < ETHER_ADDR_LEN; i++) { virtio_write_device_config_1(vsc, VIRTIO_NET_CONFIG_MAC + i, ac->ac_enaddr[i]); } } static int vio_needs_reset(struct vio_softc *sc) { if (virtio_get_status(sc->sc_virtio) & VIRTIO_CONFIG_DEVICE_STATUS_DEVICE_NEEDS_RESET) { printf("%s: device needs reset", sc->sc_dev.dv_xname); vio_ctrl_wakeup(sc, RESET); return 1; } return 0; } void vio_attach(struct device *parent, struct device *self, void *aux) { struct vio_softc *sc = (struct vio_softc *)self; struct virtio_softc *vsc = (struct virtio_softc *)parent; int i; struct ifnet *ifp = &sc->sc_ac.ac_if; if (vsc->sc_child != NULL) { printf(": child already attached for %s; something wrong...\n", parent->dv_xname); return; } sc->sc_virtio = vsc; vsc->sc_child = self; vsc->sc_ipl = IPL_NET; vsc->sc_vqs = &sc->sc_vq[0]; vsc->sc_config_change = NULL; vsc->sc_driver_features = VIRTIO_NET_F_MAC | VIRTIO_NET_F_STATUS | VIRTIO_NET_F_CTRL_VQ | VIRTIO_NET_F_CTRL_RX | VIRTIO_NET_F_MRG_RXBUF | VIRTIO_NET_F_CSUM | VIRTIO_F_RING_EVENT_IDX | VIRTIO_NET_F_GUEST_CSUM; vsc->sc_driver_features |= VIRTIO_NET_F_HOST_TSO4; vsc->sc_driver_features |= VIRTIO_NET_F_HOST_TSO6; virtio_negotiate_features(vsc, virtio_net_feature_names); if (virtio_has_feature(vsc, VIRTIO_NET_F_MAC)) { vio_get_lladdr(&sc->sc_ac, vsc); } else { ether_fakeaddr(ifp); vio_put_lladdr(&sc->sc_ac, vsc); } printf(": address %s\n", ether_sprintf(sc->sc_ac.ac_enaddr)); if (virtio_has_feature(vsc, VIRTIO_NET_F_MRG_RXBUF) || vsc->sc_version_1) { sc->sc_hdr_size = sizeof(struct virtio_net_hdr); } else { sc->sc_hdr_size = offsetof(struct virtio_net_hdr, num_buffers); } if (virtio_has_feature(vsc, VIRTIO_NET_F_MRG_RXBUF)) ifp->if_hardmtu = MAXMCLBYTES; else ifp->if_hardmtu = MAXMCLBYTES - sc->sc_hdr_size - ETHER_HDR_LEN; if (virtio_alloc_vq(vsc, &sc->sc_vq[VQRX], 0, MCLBYTES, 2, "rx") != 0) goto err; vsc->sc_nvqs = 1; sc->sc_vq[VQRX].vq_done = vio_rx_intr; if (virtio_alloc_vq(vsc, &sc->sc_vq[VQTX], 1, sc->sc_hdr_size + ifp->if_hardmtu + ETHER_HDR_LEN, VIRTIO_NET_TX_MAXNSEGS + 1, "tx") != 0) { goto err; } vsc->sc_nvqs = 2; sc->sc_vq[VQTX].vq_done = vio_tx_intr; virtio_start_vq_intr(vsc, &sc->sc_vq[VQRX]); if (virtio_has_feature(vsc, VIRTIO_F_RING_EVENT_IDX)) virtio_postpone_intr_far(&sc->sc_vq[VQTX]); else virtio_stop_vq_intr(vsc, &sc->sc_vq[VQTX]); if (virtio_has_feature(vsc, VIRTIO_NET_F_CTRL_VQ) && virtio_has_feature(vsc, VIRTIO_NET_F_CTRL_RX)) { if (virtio_alloc_vq(vsc, &sc->sc_vq[VQCTL], 2, NBPG, 1, "control") == 0) { sc->sc_vq[VQCTL].vq_done = vio_ctrleof; virtio_start_vq_intr(vsc, &sc->sc_vq[VQCTL]); vsc->sc_nvqs = 3; } } if (vio_alloc_mem(sc) < 0) goto err; strlcpy(ifp->if_xname, self->dv_xname, IFNAMSIZ); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_start = vio_start; ifp->if_ioctl = vio_ioctl; ifp->if_capabilities = IFCAP_VLAN_MTU; if (virtio_has_feature(vsc, VIRTIO_NET_F_CSUM)) ifp->if_capabilities |= IFCAP_CSUM_TCPv4|IFCAP_CSUM_UDPv4| IFCAP_CSUM_TCPv6|IFCAP_CSUM_UDPv6; if (virtio_has_feature(vsc, VIRTIO_NET_F_HOST_TSO4)) ifp->if_capabilities |= IFCAP_TSOv4; if (virtio_has_feature(vsc, VIRTIO_NET_F_HOST_TSO6)) ifp->if_capabilities |= IFCAP_TSOv6; ifq_init_maxlen(&ifp->if_snd, vsc->sc_vqs[1].vq_num - 1); ifmedia_init(&sc->sc_media, 0, vio_media_change, vio_media_status); ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL); ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO); vsc->sc_config_change = vio_config_change; timeout_set(&sc->sc_txtick, vio_txtick, &sc->sc_vq[VQTX]); timeout_set(&sc->sc_rxtick, vio_rxtick, &sc->sc_vq[VQRX]); virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK); if_attach(ifp); ether_ifattach(ifp); return; err: for (i = 0; i < vsc->sc_nvqs; i++) virtio_free_vq(vsc, &sc->sc_vq[i]); vsc->sc_nvqs = 0; vsc->sc_child = VIRTIO_CHILD_ERROR; return; } /* check link status */ void vio_link_state(struct ifnet *ifp) { struct vio_softc *sc = ifp->if_softc; struct virtio_softc *vsc = sc->sc_virtio; int link_state = LINK_STATE_FULL_DUPLEX; if (virtio_has_feature(vsc, VIRTIO_NET_F_STATUS)) { int status = virtio_read_device_config_2(vsc, VIRTIO_NET_CONFIG_STATUS); if (!(status & VIRTIO_NET_S_LINK_UP)) link_state = LINK_STATE_DOWN; } if (ifp->if_link_state != link_state) { ifp->if_link_state = link_state; if_link_state_change(ifp); } } int vio_config_change(struct virtio_softc *vsc) { struct vio_softc *sc = (struct vio_softc *)vsc->sc_child; vio_link_state(&sc->sc_ac.ac_if); vio_needs_reset(sc); return 1; } int vio_media_change(struct ifnet *ifp) { /* Ignore */ return (0); } void vio_media_status(struct ifnet *ifp, struct ifmediareq *imr) { imr->ifm_active = IFM_ETHER | IFM_AUTO; imr->ifm_status = IFM_AVALID; vio_link_state(ifp); if (LINK_STATE_IS_UP(ifp->if_link_state) && ifp->if_flags & IFF_UP) imr->ifm_status |= IFM_ACTIVE|IFM_FDX; } /* * Interface functions for ifnet */ int vio_init(struct ifnet *ifp) { struct vio_softc *sc = ifp->if_softc; vio_stop(ifp, 0); if_rxr_init(&sc->sc_rx_ring, 2 * ((ifp->if_hardmtu / MCLBYTES) + 1), sc->sc_vq[VQRX].vq_num); vio_populate_rx_mbufs(sc); ifp->if_flags |= IFF_RUNNING; ifq_clr_oactive(&ifp->if_snd); vio_iff(sc); vio_link_state(ifp); return 0; } void vio_stop(struct ifnet *ifp, int disable) { struct vio_softc *sc = ifp->if_softc; struct virtio_softc *vsc = sc->sc_virtio; timeout_del(&sc->sc_txtick); timeout_del(&sc->sc_rxtick); ifp->if_flags &= ~IFF_RUNNING; ifq_clr_oactive(&ifp->if_snd); /* only way to stop I/O and DMA is resetting... */ virtio_reset(vsc); vio_rxeof(sc); if (vsc->sc_nvqs >= 3) vio_ctrl_wakeup(sc, RESET); vio_tx_drain(sc); if (disable) vio_rx_drain(sc); virtio_reinit_start(vsc); virtio_start_vq_intr(vsc, &sc->sc_vq[VQRX]); virtio_stop_vq_intr(vsc, &sc->sc_vq[VQTX]); if (vsc->sc_nvqs >= 3) virtio_start_vq_intr(vsc, &sc->sc_vq[VQCTL]); virtio_reinit_end(vsc); if (vsc->sc_nvqs >= 3) vio_ctrl_wakeup(sc, FREE); } static inline uint16_t vio_cksum_update(uint32_t cksum, uint16_t paylen) { /* Add payload length */ cksum += paylen; /* Fold back to 16 bit */ cksum += cksum >> 16; return (uint16_t)(cksum); } void vio_tx_offload(struct virtio_net_hdr *hdr, struct mbuf *m) { struct ether_extracted ext; /* * Checksum Offload */ if (!ISSET(m->m_pkthdr.csum_flags, M_TCP_CSUM_OUT) && !ISSET(m->m_pkthdr.csum_flags, M_UDP_CSUM_OUT)) return; ether_extract_headers(m, &ext); /* Consistency Checks */ if ((!ext.ip4 && !ext.ip6) || (!ext.tcp && !ext.udp)) return; if ((ext.tcp && !ISSET(m->m_pkthdr.csum_flags, M_TCP_CSUM_OUT)) || (ext.udp && !ISSET(m->m_pkthdr.csum_flags, M_UDP_CSUM_OUT))) return; hdr->csum_start = sizeof(*ext.eh); #if NVLAN > 0 if (ext.evh) hdr->csum_start = sizeof(*ext.evh); #endif hdr->csum_start += ext.iphlen; if (ext.tcp) hdr->csum_offset = offsetof(struct tcphdr, th_sum); else if (ext.udp) hdr->csum_offset = offsetof(struct udphdr, uh_sum); hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; /* * TCP Segmentation Offload */ if (!ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO)) return; if (!ext.tcp || m->m_pkthdr.ph_mss == 0) { tcpstat_inc(tcps_outbadtso); return; } hdr->hdr_len = hdr->csum_start + ext.tcphlen; hdr->gso_size = m->m_pkthdr.ph_mss; if (ext.ip4) hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4; #ifdef INET6 else if (ext.ip6) hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6; #endif /* VirtIO-Net need pseudo header cksum with IP-payload length for TSO */ ext.tcp->th_sum = vio_cksum_update(ext.tcp->th_sum, htons(ext.iplen - ext.iphlen)); tcpstat_add(tcps_outpkttso, (ext.paylen + m->m_pkthdr.ph_mss - 1) / m->m_pkthdr.ph_mss); } void vio_start(struct ifnet *ifp) { struct vio_softc *sc = ifp->if_softc; struct virtio_softc *vsc = sc->sc_virtio; struct virtqueue *vq = &sc->sc_vq[VQTX]; struct mbuf *m; int queued = 0; vio_txeof(vq); if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd)) return; if (ifq_empty(&ifp->if_snd)) return; again: for (;;) { int slot, r; struct virtio_net_hdr *hdr; m = ifq_deq_begin(&ifp->if_snd); if (m == NULL) break; r = virtio_enqueue_prep(vq, &slot); if (r == EAGAIN) { ifq_deq_rollback(&ifp->if_snd, m); ifq_set_oactive(&ifp->if_snd); break; } if (r != 0) panic("enqueue_prep for a tx buffer: %d", r); hdr = &sc->sc_tx_hdrs[slot]; memset(hdr, 0, sc->sc_hdr_size); vio_tx_offload(hdr, m); r = vio_encap(sc, slot, m); if (r != 0) { virtio_enqueue_abort(vq, slot); ifq_deq_commit(&ifp->if_snd, m); m_freem(m); ifp->if_oerrors++; continue; } r = virtio_enqueue_reserve(vq, slot, sc->sc_tx_dmamaps[slot]->dm_nsegs + 1); if (r != 0) { bus_dmamap_unload(vsc->sc_dmat, sc->sc_tx_dmamaps[slot]); ifq_deq_rollback(&ifp->if_snd, m); sc->sc_tx_mbufs[slot] = NULL; ifq_set_oactive(&ifp->if_snd); break; } ifq_deq_commit(&ifp->if_snd, m); bus_dmamap_sync(vsc->sc_dmat, sc->sc_tx_dmamaps[slot], 0, sc->sc_tx_dmamaps[slot]->dm_mapsize, BUS_DMASYNC_PREWRITE); VIO_DMAMEM_SYNC(vsc, sc, hdr, sc->sc_hdr_size, BUS_DMASYNC_PREWRITE); VIO_DMAMEM_ENQUEUE(sc, vq, slot, hdr, sc->sc_hdr_size, 1); virtio_enqueue(vq, slot, sc->sc_tx_dmamaps[slot], 1); virtio_enqueue_commit(vsc, vq, slot, 0); queued++; #if NBPFILTER > 0 if (ifp->if_bpf) bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); #endif } if (ifq_is_oactive(&ifp->if_snd)) { int r; if (virtio_has_feature(vsc, VIRTIO_F_RING_EVENT_IDX)) r = virtio_postpone_intr_smart(&sc->sc_vq[VQTX]); else r = virtio_start_vq_intr(vsc, &sc->sc_vq[VQTX]); if (r) { vio_txeof(vq); goto again; } } if (queued > 0) { virtio_notify(vsc, vq); timeout_add_sec(&sc->sc_txtick, 1); } } #if VIRTIO_DEBUG void vio_dump(struct vio_softc *sc) { struct ifnet *ifp = &sc->sc_ac.ac_if; struct virtio_softc *vsc = sc->sc_virtio; printf("%s status dump:\n", ifp->if_xname); printf("TX virtqueue:\n"); virtio_vq_dump(&vsc->sc_vqs[VQTX]); printf("tx tick active: %d\n", !timeout_triggered(&sc->sc_txtick)); printf("rx tick active: %d\n", !timeout_triggered(&sc->sc_rxtick)); printf("RX virtqueue:\n"); virtio_vq_dump(&vsc->sc_vqs[VQRX]); if (vsc->sc_nvqs == 3) { printf("CTL virtqueue:\n"); virtio_vq_dump(&vsc->sc_vqs[VQCTL]); printf("ctrl_inuse: %d\n", sc->sc_ctrl_inuse); } } #endif int vio_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct vio_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *)data; int s, r = 0; s = splnet(); switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; if (!(ifp->if_flags & IFF_RUNNING)) vio_init(ifp); break; case SIOCSIFFLAGS: if (ifp->if_flags & IFF_UP) { #if VIRTIO_DEBUG if (ifp->if_flags & IFF_DEBUG) vio_dump(sc); #endif if (ifp->if_flags & IFF_RUNNING) r = ENETRESET; else vio_init(ifp); } else { if (ifp->if_flags & IFF_RUNNING) vio_stop(ifp, 1); } break; case SIOCGIFMEDIA: case SIOCSIFMEDIA: r = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); break; case SIOCGIFRXR: r = if_rxr_ioctl((struct if_rxrinfo *)ifr->ifr_data, NULL, MCLBYTES, &sc->sc_rx_ring); break; default: r = ether_ioctl(ifp, &sc->sc_ac, cmd, data); } if (r == ENETRESET) { if (ifp->if_flags & IFF_RUNNING) vio_iff(sc); r = 0; } splx(s); return r; } /* * Receive implementation */ /* allocate and initialize a mbuf for receive */ int vio_add_rx_mbuf(struct vio_softc *sc, int i) { struct mbuf *m; int r; m = MCLGETL(NULL, M_DONTWAIT, MCLBYTES); if (m == NULL) return ENOBUFS; sc->sc_rx_mbufs[i] = m; m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; r = bus_dmamap_load_mbuf(sc->sc_virtio->sc_dmat, sc->sc_rx_dmamaps[i], m, BUS_DMA_READ|BUS_DMA_NOWAIT); if (r) { m_freem(m); sc->sc_rx_mbufs[i] = NULL; return r; } return 0; } /* free a mbuf for receive */ void vio_free_rx_mbuf(struct vio_softc *sc, int i) { bus_dmamap_unload(sc->sc_virtio->sc_dmat, sc->sc_rx_dmamaps[i]); m_freem(sc->sc_rx_mbufs[i]); sc->sc_rx_mbufs[i] = NULL; } /* add mbufs for all the empty receive slots */ void vio_populate_rx_mbufs(struct vio_softc *sc) { struct virtio_softc *vsc = sc->sc_virtio; int r, done = 0; u_int slots; struct virtqueue *vq = &sc->sc_vq[VQRX]; int mrg_rxbuf = VIO_HAVE_MRG_RXBUF(sc); for (slots = if_rxr_get(&sc->sc_rx_ring, vq->vq_num); slots > 0; slots--) { int slot; r = virtio_enqueue_prep(vq, &slot); if (r == EAGAIN) break; if (r != 0) panic("enqueue_prep for rx buffers: %d", r); if (sc->sc_rx_mbufs[slot] == NULL) { r = vio_add_rx_mbuf(sc, slot); if (r != 0) { virtio_enqueue_abort(vq, slot); break; } } r = virtio_enqueue_reserve(vq, slot, sc->sc_rx_dmamaps[slot]->dm_nsegs + (mrg_rxbuf ? 0 : 1)); if (r != 0) { vio_free_rx_mbuf(sc, slot); break; } bus_dmamap_sync(vsc->sc_dmat, sc->sc_rx_dmamaps[slot], 0, MCLBYTES, BUS_DMASYNC_PREREAD); if (mrg_rxbuf) { virtio_enqueue(vq, slot, sc->sc_rx_dmamaps[slot], 0); } else { /* * Buggy kvm wants a buffer of exactly the size of * the header in this case, so we have to split in * two. */ virtio_enqueue_p(vq, slot, sc->sc_rx_dmamaps[slot], 0, sc->sc_hdr_size, 0); virtio_enqueue_p(vq, slot, sc->sc_rx_dmamaps[slot], sc->sc_hdr_size, MCLBYTES - sc->sc_hdr_size, 0); } virtio_enqueue_commit(vsc, vq, slot, 0); done = 1; } if_rxr_put(&sc->sc_rx_ring, slots); if (done) virtio_notify(vsc, vq); timeout_add_sec(&sc->sc_rxtick, 1); } void vio_rx_offload(struct mbuf *m, struct virtio_net_hdr *hdr) { struct ether_extracted ext; if (!ISSET(hdr->flags, VIRTIO_NET_HDR_F_DATA_VALID) && !ISSET(hdr->flags, VIRTIO_NET_HDR_F_NEEDS_CSUM)) return; ether_extract_headers(m, &ext); if (ext.ip4) SET(m->m_pkthdr.csum_flags, M_IPV4_CSUM_IN_OK); if (ext.tcp) { SET(m->m_pkthdr.csum_flags, M_TCP_CSUM_IN_OK); if (ISSET(hdr->flags, VIRTIO_NET_HDR_F_NEEDS_CSUM)) SET(m->m_pkthdr.csum_flags, M_TCP_CSUM_OUT); } else if (ext.udp) { SET(m->m_pkthdr.csum_flags, M_UDP_CSUM_IN_OK); if (ISSET(hdr->flags, VIRTIO_NET_HDR_F_NEEDS_CSUM)) SET(m->m_pkthdr.csum_flags, M_UDP_CSUM_OUT); } } /* dequeue received packets */ int vio_rxeof(struct vio_softc *sc) { struct virtio_softc *vsc = sc->sc_virtio; struct virtqueue *vq = &sc->sc_vq[VQRX]; struct ifnet *ifp = &sc->sc_ac.ac_if; struct mbuf_list ml = MBUF_LIST_INITIALIZER(); struct mbuf *m, *m0 = NULL, *mlast; int r = 0; int slot, len, bufs_left; struct virtio_net_hdr *hdr; while (virtio_dequeue(vsc, vq, &slot, &len) == 0) { r = 1; bus_dmamap_sync(vsc->sc_dmat, sc->sc_rx_dmamaps[slot], 0, MCLBYTES, BUS_DMASYNC_POSTREAD); m = sc->sc_rx_mbufs[slot]; KASSERT(m != NULL); bus_dmamap_unload(vsc->sc_dmat, sc->sc_rx_dmamaps[slot]); sc->sc_rx_mbufs[slot] = NULL; virtio_dequeue_commit(vq, slot); if_rxr_put(&sc->sc_rx_ring, 1); m->m_len = m->m_pkthdr.len = len; m->m_pkthdr.csum_flags = 0; if (m0 == NULL) { hdr = mtod(m, struct virtio_net_hdr *); m_adj(m, sc->sc_hdr_size); m0 = mlast = m; if (VIO_HAVE_MRG_RXBUF(sc)) bufs_left = hdr->num_buffers - 1; else bufs_left = 0; if (virtio_has_feature(vsc, VIRTIO_NET_F_GUEST_CSUM)) vio_rx_offload(m, hdr); } else { m->m_flags &= ~M_PKTHDR; m0->m_pkthdr.len += m->m_len; mlast->m_next = m; mlast = m; bufs_left--; } if (bufs_left == 0) { ml_enqueue(&ml, m0); m0 = NULL; } } if (m0 != NULL) { DPRINTF("%s: expected %d buffers, got %d\n", __func__, (int)hdr->num_buffers, (int)hdr->num_buffers - bufs_left); ifp->if_ierrors++; m_freem(m0); } if (ifiq_input(&ifp->if_rcv, &ml)) if_rxr_livelocked(&sc->sc_rx_ring); return r; } int vio_rx_intr(struct virtqueue *vq) { struct virtio_softc *vsc = vq->vq_owner; struct vio_softc *sc = (struct vio_softc *)vsc->sc_child; int r, sum = 0; again: r = vio_rxeof(sc); sum += r; if (r) { vio_populate_rx_mbufs(sc); /* set used event index to the next slot */ if (virtio_has_feature(vsc, VIRTIO_F_RING_EVENT_IDX)) { if (virtio_start_vq_intr(vq->vq_owner, vq)) goto again; } } return sum; } void vio_rxtick(void *arg) { struct virtqueue *vq = arg; struct virtio_softc *vsc = vq->vq_owner; struct vio_softc *sc = (struct vio_softc *)vsc->sc_child; int s; s = splnet(); vio_populate_rx_mbufs(sc); splx(s); } /* free all the mbufs; called from if_stop(disable) */ void vio_rx_drain(struct vio_softc *sc) { struct virtqueue *vq = &sc->sc_vq[VQRX]; int i; for (i = 0; i < vq->vq_num; i++) { if (sc->sc_rx_mbufs[i] == NULL) continue; vio_free_rx_mbuf(sc, i); } } /* * Transmission implementation */ /* actual transmission is done in if_start */ /* tx interrupt; dequeue and free mbufs */ /* * tx interrupt is actually disabled unless the tx queue is full, i.e. * IFF_OACTIVE is set. vio_txtick is used to make sure that mbufs * are dequeued and freed even if no further transfer happens. */ int vio_tx_intr(struct virtqueue *vq) { struct virtio_softc *vsc = vq->vq_owner; struct vio_softc *sc = (struct vio_softc *)vsc->sc_child; struct ifnet *ifp = &sc->sc_ac.ac_if; int r; r = vio_txeof(vq); vio_start(ifp); return r; } void vio_txtick(void *arg) { struct virtqueue *vq = arg; int s = splnet(); vio_tx_intr(vq); splx(s); } int vio_txeof(struct virtqueue *vq) { struct virtio_softc *vsc = vq->vq_owner; struct vio_softc *sc = (struct vio_softc *)vsc->sc_child; struct ifnet *ifp = &sc->sc_ac.ac_if; struct mbuf *m; int r = 0; int slot, len; if (!ISSET(ifp->if_flags, IFF_RUNNING)) return 0; while (virtio_dequeue(vsc, vq, &slot, &len) == 0) { struct virtio_net_hdr *hdr = &sc->sc_tx_hdrs[slot]; r++; VIO_DMAMEM_SYNC(vsc, sc, hdr, sc->sc_hdr_size, BUS_DMASYNC_POSTWRITE); bus_dmamap_sync(vsc->sc_dmat, sc->sc_tx_dmamaps[slot], 0, sc->sc_tx_dmamaps[slot]->dm_mapsize, BUS_DMASYNC_POSTWRITE); m = sc->sc_tx_mbufs[slot]; bus_dmamap_unload(vsc->sc_dmat, sc->sc_tx_dmamaps[slot]); sc->sc_tx_mbufs[slot] = NULL; virtio_dequeue_commit(vq, slot); m_freem(m); } if (r) { ifq_clr_oactive(&ifp->if_snd); virtio_stop_vq_intr(vsc, &sc->sc_vq[VQTX]); } if (vq->vq_used_idx == vq->vq_avail_idx) timeout_del(&sc->sc_txtick); else if (r) timeout_add_sec(&sc->sc_txtick, 1); return r; } int vio_encap(struct vio_softc *sc, int slot, struct mbuf *m) { struct virtio_softc *vsc = sc->sc_virtio; bus_dmamap_t dmap= sc->sc_tx_dmamaps[slot]; int r; r = bus_dmamap_load_mbuf(vsc->sc_dmat, dmap, m, BUS_DMA_WRITE|BUS_DMA_NOWAIT); switch (r) { case 0: break; case EFBIG: if (m_defrag(m, M_DONTWAIT) == 0 && bus_dmamap_load_mbuf(vsc->sc_dmat, dmap, m, BUS_DMA_WRITE|BUS_DMA_NOWAIT) == 0) break; /* FALLTHROUGH */ default: return ENOBUFS; } sc->sc_tx_mbufs[slot] = m; return 0; } /* free all the mbufs already put on vq; called from if_stop(disable) */ void vio_tx_drain(struct vio_softc *sc) { struct virtio_softc *vsc = sc->sc_virtio; struct virtqueue *vq = &sc->sc_vq[VQTX]; int i; for (i = 0; i < vq->vq_num; i++) { if (sc->sc_tx_mbufs[i] == NULL) continue; bus_dmamap_unload(vsc->sc_dmat, sc->sc_tx_dmamaps[i]); m_freem(sc->sc_tx_mbufs[i]); sc->sc_tx_mbufs[i] = NULL; } } /* * Control vq */ /* issue a VIRTIO_NET_CTRL_RX class command and wait for completion */ int vio_ctrl_rx(struct vio_softc *sc, int cmd, int onoff) { struct virtio_softc *vsc = sc->sc_virtio; struct virtqueue *vq = &sc->sc_vq[VQCTL]; int r, slot; splassert(IPL_NET); if ((r = vio_wait_ctrl(sc)) != 0) return r; sc->sc_ctrl_cmd->class = VIRTIO_NET_CTRL_RX; sc->sc_ctrl_cmd->command = cmd; sc->sc_ctrl_rx->onoff = onoff; VIO_DMAMEM_SYNC(vsc, sc, sc->sc_ctrl_cmd, sizeof(*sc->sc_ctrl_cmd), BUS_DMASYNC_PREWRITE); VIO_DMAMEM_SYNC(vsc, sc, sc->sc_ctrl_rx, sizeof(*sc->sc_ctrl_rx), BUS_DMASYNC_PREWRITE); VIO_DMAMEM_SYNC(vsc, sc, sc->sc_ctrl_status, sizeof(*sc->sc_ctrl_status), BUS_DMASYNC_PREREAD); r = virtio_enqueue_prep(vq, &slot); if (r != 0) panic("%s: control vq busy!?", sc->sc_dev.dv_xname); r = virtio_enqueue_reserve(vq, slot, 3); if (r != 0) panic("%s: control vq busy!?", sc->sc_dev.dv_xname); VIO_DMAMEM_ENQUEUE(sc, vq, slot, sc->sc_ctrl_cmd, sizeof(*sc->sc_ctrl_cmd), 1); VIO_DMAMEM_ENQUEUE(sc, vq, slot, sc->sc_ctrl_rx, sizeof(*sc->sc_ctrl_rx), 1); VIO_DMAMEM_ENQUEUE(sc, vq, slot, sc->sc_ctrl_status, sizeof(*sc->sc_ctrl_status), 0); virtio_enqueue_commit(vsc, vq, slot, 1); if ((r = vio_wait_ctrl_done(sc)) != 0) goto out; VIO_DMAMEM_SYNC(vsc, sc, sc->sc_ctrl_cmd, sizeof(*sc->sc_ctrl_cmd), BUS_DMASYNC_POSTWRITE); VIO_DMAMEM_SYNC(vsc, sc, sc->sc_ctrl_rx, sizeof(*sc->sc_ctrl_rx), BUS_DMASYNC_POSTWRITE); VIO_DMAMEM_SYNC(vsc, sc, sc->sc_ctrl_status, sizeof(*sc->sc_ctrl_status), BUS_DMASYNC_POSTREAD); if (sc->sc_ctrl_status->ack == VIRTIO_NET_OK) { r = 0; } else { printf("%s: ctrl cmd %d failed\n", sc->sc_dev.dv_xname, cmd); r = EIO; } DPRINTF("%s: cmd %d %d: %d\n", __func__, cmd, (int)onoff, r); out: vio_ctrl_wakeup(sc, FREE); return r; } int vio_wait_ctrl(struct vio_softc *sc) { int r = 0; while (sc->sc_ctrl_inuse != FREE) { if (sc->sc_ctrl_inuse == RESET || vio_needs_reset(sc)) return ENXIO; r = tsleep_nsec(&sc->sc_ctrl_inuse, PRIBIO, "viowait", INFSLP); } sc->sc_ctrl_inuse = INUSE; return r; } int vio_wait_ctrl_done(struct vio_softc *sc) { int r = 0; while (sc->sc_ctrl_inuse != DONE) { if (sc->sc_ctrl_inuse == RESET || vio_needs_reset(sc)) return ENXIO; r = tsleep_nsec(&sc->sc_ctrl_inuse, PRIBIO, "viodone", VIRTIO_NET_CTRL_TIMEOUT); if (r == EWOULDBLOCK) { printf("%s: ctrl queue timeout", sc->sc_dev.dv_xname); vio_ctrl_wakeup(sc, RESET); return ENXIO; } } return r; } void vio_ctrl_wakeup(struct vio_softc *sc, enum vio_ctrl_state new) { sc->sc_ctrl_inuse = new; wakeup(&sc->sc_ctrl_inuse); } int vio_ctrleof(struct virtqueue *vq) { struct virtio_softc *vsc = vq->vq_owner; struct vio_softc *sc = (struct vio_softc *)vsc->sc_child; int r = 0, ret, slot; again: ret = virtio_dequeue(vsc, vq, &slot, NULL); if (ret == ENOENT) return r; virtio_dequeue_commit(vq, slot); r++; vio_ctrl_wakeup(sc, DONE); if (virtio_start_vq_intr(vsc, vq)) goto again; return r; } /* issue VIRTIO_NET_CTRL_MAC_TABLE_SET command and wait for completion */ int vio_set_rx_filter(struct vio_softc *sc) { /* filter already set in sc_ctrl_mac_tbl */ struct virtio_softc *vsc = sc->sc_virtio; struct virtqueue *vq = &sc->sc_vq[VQCTL]; int r, slot; splassert(IPL_NET); if ((r = vio_wait_ctrl(sc)) != 0) return r; sc->sc_ctrl_cmd->class = VIRTIO_NET_CTRL_MAC; sc->sc_ctrl_cmd->command = VIRTIO_NET_CTRL_MAC_TABLE_SET; VIO_DMAMEM_SYNC(vsc, sc, sc->sc_ctrl_cmd, sizeof(*sc->sc_ctrl_cmd), BUS_DMASYNC_PREWRITE); VIO_DMAMEM_SYNC(vsc, sc, sc->sc_ctrl_mac_info, VIO_CTRL_MAC_INFO_SIZE, BUS_DMASYNC_PREWRITE); VIO_DMAMEM_SYNC(vsc, sc, sc->sc_ctrl_status, sizeof(*sc->sc_ctrl_status), BUS_DMASYNC_PREREAD); r = virtio_enqueue_prep(vq, &slot); if (r != 0) panic("%s: control vq busy!?", sc->sc_dev.dv_xname); r = virtio_enqueue_reserve(vq, slot, 4); if (r != 0) panic("%s: control vq busy!?", sc->sc_dev.dv_xname); VIO_DMAMEM_ENQUEUE(sc, vq, slot, sc->sc_ctrl_cmd, sizeof(*sc->sc_ctrl_cmd), 1); VIO_DMAMEM_ENQUEUE(sc, vq, slot, sc->sc_ctrl_mac_tbl_uc, sizeof(*sc->sc_ctrl_mac_tbl_uc) + sc->sc_ctrl_mac_tbl_uc->nentries * ETHER_ADDR_LEN, 1); VIO_DMAMEM_ENQUEUE(sc, vq, slot, sc->sc_ctrl_mac_tbl_mc, sizeof(*sc->sc_ctrl_mac_tbl_mc) + sc->sc_ctrl_mac_tbl_mc->nentries * ETHER_ADDR_LEN, 1); VIO_DMAMEM_ENQUEUE(sc, vq, slot, sc->sc_ctrl_status, sizeof(*sc->sc_ctrl_status), 0); virtio_enqueue_commit(vsc, vq, slot, 1); if ((r = vio_wait_ctrl_done(sc)) != 0) goto out; VIO_DMAMEM_SYNC(vsc, sc, sc->sc_ctrl_cmd, sizeof(*sc->sc_ctrl_cmd), BUS_DMASYNC_POSTWRITE); VIO_DMAMEM_SYNC(vsc, sc, sc->sc_ctrl_mac_info, VIO_CTRL_MAC_INFO_SIZE, BUS_DMASYNC_POSTWRITE); VIO_DMAMEM_SYNC(vsc, sc, sc->sc_ctrl_status, sizeof(*sc->sc_ctrl_status), BUS_DMASYNC_POSTREAD); if (sc->sc_ctrl_status->ack == VIRTIO_NET_OK) { r = 0; } else { /* The host's filter table is not large enough */ printf("%s: failed setting rx filter\n", sc->sc_dev.dv_xname); r = EIO; } out: vio_ctrl_wakeup(sc, FREE); return r; } void vio_iff(struct vio_softc *sc) { struct virtio_softc *vsc = sc->sc_virtio; struct ifnet *ifp = &sc->sc_ac.ac_if; struct arpcom *ac = &sc->sc_ac; struct ether_multi *enm; struct ether_multistep step; int nentries = 0; int promisc = 0, allmulti = 0, rxfilter = 0; int r; splassert(IPL_NET); ifp->if_flags &= ~IFF_ALLMULTI; if (vsc->sc_nvqs < 3) { /* no ctrl vq; always promisc */ ifp->if_flags |= IFF_ALLMULTI | IFF_PROMISC; return; } if (sc->sc_dev.dv_cfdata->cf_flags & CONFFLAG_QEMU_VLAN_BUG) ifp->if_flags |= IFF_PROMISC; if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0 || ac->ac_multicnt >= VIRTIO_NET_CTRL_MAC_MC_ENTRIES) { ifp->if_flags |= IFF_ALLMULTI; if (ifp->if_flags & IFF_PROMISC) promisc = 1; else allmulti = 1; } else { rxfilter = 1; ETHER_FIRST_MULTI(step, ac, enm); while (enm != NULL) { memcpy(sc->sc_ctrl_mac_tbl_mc->macs[nentries++], enm->enm_addrlo, ETHER_ADDR_LEN); ETHER_NEXT_MULTI(step, enm); } } /* set unicast address, VirtualBox wants that */ memcpy(sc->sc_ctrl_mac_tbl_uc->macs[0], ac->ac_enaddr, ETHER_ADDR_LEN); sc->sc_ctrl_mac_tbl_uc->nentries = 1; sc->sc_ctrl_mac_tbl_mc->nentries = rxfilter ? nentries : 0; if (vsc->sc_nvqs < 3) return; r = vio_set_rx_filter(sc); if (r == EIO) allmulti = 1; /* fallback */ else if (r != 0) return; r = vio_ctrl_rx(sc, VIRTIO_NET_CTRL_RX_ALLMULTI, allmulti); if (r == EIO) promisc = 1; /* fallback */ else if (r != 0) return; vio_ctrl_rx(sc, VIRTIO_NET_CTRL_RX_PROMISC, promisc); }
8 4 1 3 3 1 2 6 6 5 4 3 1 4 5 6 5 5 5 3 5 5 5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 /* $OpenBSD: tty_nmea.c,v 1.51 2022/04/02 22:45:18 mlarkin Exp $ */ /* * Copyright (c) 2006, 2007, 2008 Marc Balmer <mbalmer@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * A tty line discipline to decode NMEA 0183 data to get the time * and GPS position data */ #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/sensors.h> #include <sys/tty.h> #include <sys/conf.h> #include <sys/time.h> #ifdef NMEA_DEBUG #define DPRINTFN(n, x) do { if (nmeadebug > (n)) printf x; } while (0) int nmeadebug = 0; #else #define DPRINTFN(n, x) #endif #define DPRINTF(x) DPRINTFN(0, x) void nmeaattach(int); #define NMEAMAX 82 #define MAXFLDS 32 #define KNOTTOMS (51444 / 100) #ifdef NMEA_DEBUG #define TRUSTTIME 30 #else #define TRUSTTIME (10 * 60) /* 10 minutes */ #endif int nmea_count, nmea_nxid; struct nmea { char cbuf[NMEAMAX]; /* receive buffer */ struct ksensor time; /* the timedelta sensor */ struct ksensor signal; /* signal status */ struct ksensor latitude; struct ksensor longitude; struct ksensor altitude; struct ksensor speed; struct ksensordev timedev; struct timespec ts; /* current timestamp */ struct timespec lts; /* timestamp of last '$' seen */ struct timeout nmea_tout; /* invalidate sensor */ int64_t gap; /* gap between two sentences */ #ifdef NMEA_DEBUG int gapno; #endif int64_t last; /* last time rcvd */ int sync; /* if 1, waiting for '$' */ int pos; /* position in rcv buffer */ int no_pps; /* no PPS although requested */ char mode; /* GPS mode */ }; /* NMEA decoding */ void nmea_scan(struct nmea *, struct tty *); void nmea_gprmc(struct nmea *, struct tty *, char *fld[], int fldcnt); void nmea_decode_gga(struct nmea *, struct tty *, char *fld[], int fldcnt); /* date and time conversion */ int nmea_date_to_nano(char *s, int64_t *nano); int nmea_time_to_nano(char *s, int64_t *nano); /* longitude and latitude conversion */ int nmea_degrees(int64_t *dst, char *src, int neg); int nmea_atoi(int64_t *dst, char *src); /* degrade the timedelta sensor */ void nmea_timeout(void *); void nmeaattach(int dummy) { /* noop */ } int nmeaopen(dev_t dev, struct tty *tp, struct proc *p) { struct nmea *np; int error; if (tp->t_line == NMEADISC) return (ENODEV); if ((error = suser(p)) != 0) return (error); np = malloc(sizeof(struct nmea), M_DEVBUF, M_WAITOK | M_ZERO); snprintf(np->timedev.xname, sizeof(np->timedev.xname), "nmea%d", nmea_nxid++); nmea_count++; np->time.status = SENSOR_S_UNKNOWN; np->time.type = SENSOR_TIMEDELTA; np->time.flags = SENSOR_FINVALID; sensor_attach(&np->timedev, &np->time); np->signal.type = SENSOR_INDICATOR; np->signal.status = SENSOR_S_UNKNOWN; np->signal.value = 0; strlcpy(np->signal.desc, "Signal", sizeof(np->signal.desc)); sensor_attach(&np->timedev, &np->signal); np->latitude.type = SENSOR_ANGLE; np->latitude.status = SENSOR_S_UNKNOWN; np->latitude.flags = SENSOR_FINVALID; np->latitude.value = 0; strlcpy(np->latitude.desc, "Latitude", sizeof(np->latitude.desc)); sensor_attach(&np->timedev, &np->latitude); np->longitude.type = SENSOR_ANGLE; np->longitude.status = SENSOR_S_UNKNOWN; np->longitude.flags = SENSOR_FINVALID; np->longitude.value = 0; strlcpy(np->longitude.desc, "Longitude", sizeof(np->longitude.desc)); sensor_attach(&np->timedev, &np->longitude); np->altitude.type = SENSOR_DISTANCE; np->altitude.status = SENSOR_S_UNKNOWN; np->altitude.flags = SENSOR_FINVALID; np->altitude.value = 0; strlcpy(np->altitude.desc, "Altitude", sizeof(np->altitude.desc)); sensor_attach(&np->timedev, &np->altitude); np->speed.type = SENSOR_VELOCITY; np->speed.status = SENSOR_S_UNKNOWN; np->speed.flags = SENSOR_FINVALID; np->speed.value = 0; strlcpy(np->speed.desc, "Ground speed", sizeof(np->speed.desc)); sensor_attach(&np->timedev, &np->speed); np->sync = 1; tp->t_sc = (caddr_t)np; error = linesw[TTYDISC].l_open(dev, tp, p); if (error) { free(np, M_DEVBUF, sizeof(*np)); tp->t_sc = NULL; } else { sensordev_install(&np->timedev); timeout_set(&np->nmea_tout, nmea_timeout, np); } return (error); } int nmeaclose(struct tty *tp, int flags, struct proc *p) { struct nmea *np = (struct nmea *)tp->t_sc; tp->t_line = TTYDISC; /* switch back to termios */ timeout_del(&np->nmea_tout); sensordev_deinstall(&np->timedev); free(np, M_DEVBUF, sizeof(*np)); tp->t_sc = NULL; nmea_count--; if (nmea_count == 0) nmea_nxid = 0; return (linesw[TTYDISC].l_close(tp, flags, p)); } /* Collect NMEA sentences from the tty. */ int nmeainput(int c, struct tty *tp) { struct nmea *np = (struct nmea *)tp->t_sc; struct timespec ts; int64_t gap; long tmin, tmax; switch (c) { case '$': nanotime(&ts); np->pos = np->sync = 0; gap = (ts.tv_sec * 1000000000LL + ts.tv_nsec) - (np->lts.tv_sec * 1000000000LL + np->lts.tv_nsec); np->lts.tv_sec = ts.tv_sec; np->lts.tv_nsec = ts.tv_nsec; if (gap <= np->gap) break; np->ts.tv_sec = ts.tv_sec; np->ts.tv_nsec = ts.tv_nsec; #ifdef NMEA_DEBUG if (nmeadebug > 0) { linesw[TTYDISC].l_rint('[', tp); linesw[TTYDISC].l_rint('0' + np->gapno++, tp); linesw[TTYDISC].l_rint(']', tp); } #endif np->gap = gap; /* * If a tty timestamp is available, make sure its value is * reasonable by comparing against the timestamp just taken. * If they differ by more than 2 seconds, assume no PPS signal * is present, note the fact, and keep using the timestamp * value. When this happens, the sensor state is set to * CRITICAL later when the GPRMC sentence is decoded. */ if (tp->t_flags & (TS_TSTAMPDCDSET | TS_TSTAMPDCDCLR | TS_TSTAMPCTSSET | TS_TSTAMPCTSCLR)) { tmax = lmax(np->ts.tv_sec, tp->t_tv.tv_sec); tmin = lmin(np->ts.tv_sec, tp->t_tv.tv_sec); if (tmax - tmin > 1) np->no_pps = 1; else { np->ts.tv_sec = tp->t_tv.tv_sec; np->ts.tv_nsec = tp->t_tv.tv_usec * 1000L; np->no_pps = 0; } } break; case '\r': case '\n': if (!np->sync) { np->cbuf[np->pos] = '\0'; nmea_scan(np, tp); np->sync = 1; } break; default: if (!np->sync && np->pos < (NMEAMAX - 1)) np->cbuf[np->pos++] = c; break; } /* pass data to termios */ return (linesw[TTYDISC].l_rint(c, tp)); } /* Scan the NMEA sentence just received. */ void nmea_scan(struct nmea *np, struct tty *tp) { int fldcnt = 0, cksum = 0, msgcksum, n; char *fld[MAXFLDS], *cs; /* split into fields and calculate the checksum */ fld[fldcnt++] = &np->cbuf[0]; /* message type */ for (cs = NULL, n = 0; n < np->pos && cs == NULL; n++) { switch (np->cbuf[n]) { case '*': np->cbuf[n] = '\0'; cs = &np->cbuf[n + 1]; break; case ',': if (fldcnt < MAXFLDS) { cksum ^= np->cbuf[n]; np->cbuf[n] = '\0'; fld[fldcnt++] = &np->cbuf[n + 1]; } else { DPRINTF(("nr of fields in %s sentence exceeds " "maximum of %d\n", fld[0], MAXFLDS)); return; } break; default: cksum ^= np->cbuf[n]; } } /* * we only look at the messages coming from well-known sources or 'talkers', * distinguished by the two-chars prefix, the most common being: * GPS (GP) * Glonass (GL) * BeiDou (BD) * Galileo (GA) * 'Any kind/a mix of GNSS systems' (GN) */ if (strncmp(fld[0], "BD", 2) && strncmp(fld[0], "GA", 2) && strncmp(fld[0], "GL", 2) && strncmp(fld[0], "GN", 2) && strncmp(fld[0], "GP", 2)) return; /* we look for the RMC & GGA messages */ if (strncmp(fld[0] + 2, "RMC", 3) && strncmp(fld[0] + 2, "GGA", 3)) return; /* if we have a checksum, verify it */ if (cs != NULL) { msgcksum = 0; while (*cs) { if ((*cs >= '0' && *cs <= '9') || (*cs >= 'A' && *cs <= 'F')) { if (msgcksum) msgcksum <<= 4; if (*cs >= '0' && *cs<= '9') msgcksum += *cs - '0'; else if (*cs >= 'A' && *cs <= 'F') msgcksum += 10 + *cs - 'A'; cs++; } else { DPRINTF(("bad char %c in checksum\n", *cs)); return; } } if (msgcksum != cksum) { DPRINTF(("checksum mismatch\n")); return; } } if (strncmp(fld[0] + 2, "RMC", 3) == 0) nmea_gprmc(np, tp, fld, fldcnt); if (strncmp(fld[0] + 2, "GGA", 3) == 0) nmea_decode_gga(np, tp, fld, fldcnt); } /* Decode the recommended minimum specific GPS/TRANSIT data. */ void nmea_gprmc(struct nmea *np, struct tty *tp, char *fld[], int fldcnt) { int64_t date_nano, time_nano, nmea_now; int jumped = 0; if (fldcnt < 12 || fldcnt > 14) { DPRINTF(("gprmc: field count mismatch, %d\n", fldcnt)); return; } if (nmea_time_to_nano(fld[1], &time_nano)) { DPRINTF(("gprmc: illegal time, %s\n", fld[1])); return; } if (nmea_date_to_nano(fld[9], &date_nano)) { DPRINTF(("gprmc: illegal date, %s\n", fld[9])); return; } nmea_now = date_nano + time_nano; if (nmea_now <= np->last) { DPRINTF(("gprmc: time not monotonically increasing\n")); jumped = 1; } np->last = nmea_now; np->gap = 0LL; #ifdef NMEA_DEBUG if (np->time.status == SENSOR_S_UNKNOWN) { np->time.status = SENSOR_S_OK; timeout_add_sec(&np->nmea_tout, TRUSTTIME); } np->gapno = 0; if (nmeadebug > 0) { linesw[TTYDISC].l_rint('[', tp); linesw[TTYDISC].l_rint('C', tp); linesw[TTYDISC].l_rint(']', tp); } #endif np->time.value = np->ts.tv_sec * 1000000000LL + np->ts.tv_nsec - nmea_now; np->time.tv.tv_sec = np->ts.tv_sec; np->time.tv.tv_usec = np->ts.tv_nsec / 1000L; if (fldcnt < 13) strlcpy(np->time.desc, "GPS", sizeof(np->time.desc)); else if (*fld[12] != np->mode) { np->mode = *fld[12]; switch (np->mode) { case 'S': strlcpy(np->time.desc, "GPS simulated", sizeof(np->time.desc)); break; case 'E': strlcpy(np->time.desc, "GPS estimated", sizeof(np->time.desc)); break; case 'A': strlcpy(np->time.desc, "GPS autonomous", sizeof(np->time.desc)); break; case 'D': strlcpy(np->time.desc, "GPS differential", sizeof(np->time.desc)); break; case 'N': strlcpy(np->time.desc, "GPS invalid", sizeof(np->time.desc)); break; default: strlcpy(np->time.desc, "GPS unknown", sizeof(np->time.desc)); DPRINTF(("gprmc: unknown mode '%c'\n", np->mode)); } } switch (*fld[2]) { case 'A': /* The GPS has a fix, (re)arm the timeout. */ /* XXX is 'D' also a valid state? */ np->time.status = SENSOR_S_OK; np->signal.value = 1; np->signal.status = SENSOR_S_OK; np->latitude.status = SENSOR_S_OK; np->longitude.status = SENSOR_S_OK; np->speed.status = SENSOR_S_OK; np->time.flags &= ~SENSOR_FINVALID; np->latitude.flags &= ~SENSOR_FINVALID; np->longitude.flags &= ~SENSOR_FINVALID; np->speed.flags &= ~SENSOR_FINVALID; break; case 'V': /* * The GPS indicates a warning status, do not add to * the timeout, if the condition persist, the sensor * will be degraded. Signal the condition through * the signal sensor. */ np->signal.value = 0; np->signal.status = SENSOR_S_CRIT; np->latitude.status = SENSOR_S_WARN; np->longitude.status = SENSOR_S_WARN; np->speed.status = SENSOR_S_WARN; break; } if (nmea_degrees(&np->latitude.value, fld[3], *fld[4] == 'S' ? 1 : 0)) np->latitude.status = SENSOR_S_WARN; if (nmea_degrees(&np->longitude.value,fld[5], *fld[6] == 'W' ? 1 : 0)) np->longitude.status = SENSOR_S_WARN; if (nmea_atoi(&np->speed.value, fld[7])) np->speed.status = SENSOR_S_WARN; /* convert from knot to um/s */ np->speed.value *= KNOTTOMS; if (jumped) np->time.status = SENSOR_S_WARN; if (np->time.status == SENSOR_S_OK) timeout_add_sec(&np->nmea_tout, TRUSTTIME); /* * If tty timestamping is requested, but no PPS signal is present, set * the sensor state to CRITICAL. */ if (np->no_pps) np->time.status = SENSOR_S_CRIT; } /* Decode the GPS fix data for altitude. * - field 9 is the altitude in meters * $GNGGA,085901.00,1234.5678,N,00987.12345,E,1,12,0.84,1040.9,M,47.4,M,,*4B */ void nmea_decode_gga(struct nmea *np, struct tty *tp, char *fld[], int fldcnt) { if (fldcnt != 15) { DPRINTF(("GGA: field count mismatch, %d\n", fldcnt)); return; } #ifdef NMEA_DEBUG if (nmeadebug > 0) { linesw[TTYDISC].l_rint('[', tp); linesw[TTYDISC].l_rint('C', tp); linesw[TTYDISC].l_rint(']', tp); } #endif np->altitude.status = SENSOR_S_OK; if (nmea_atoi(&np->altitude.value, fld[9])) np->altitude.status = SENSOR_S_WARN; /* convert to uMeter */ np->altitude.value *= 1000; np->altitude.flags &= ~SENSOR_FINVALID; } /* * Convert nmea integer/decimal values in the form of XXXX.Y to an integer value * if it's a meter/altitude value, will be returned as mm */ int nmea_atoi(int64_t *dst, char *src) { char *p; int i = 3; /* take 3 digits */ *dst = 0; for (p = src; *p && *p != '.' && *p >= '0' && *p <= '9' ; ) *dst = *dst * 10 + (*p++ - '0'); /* *p should be '.' at that point */ if (*p != '.') return -1; /* no decimal point, or bogus value ? */ p++; /* read digits after decimal point, stop at first non-digit */ for (; *p && i > 0 && *p >= '0' && *p <= '9' ; i--) *dst = *dst * 10 + (*p++ - '0'); for (; i > 0 ; i--) *dst *= 10; DPRINTFN(2,("%s -> %lld\n", src, *dst)); return 0; } /* * Convert a nmea position in the form DDDMM.MMMM to an * angle sensor value (degrees*1000000) */ int nmea_degrees(int64_t *dst, char *src, int neg) { size_t ppos; int i, n; int64_t deg = 0, min = 0; char *p; while (*src == '0') ++src; /* skip leading zeroes */ for (p = src, ppos = 0; *p; ppos++) if (*p++ == '.') break; if (*p == '\0') return (-1); /* no decimal point */ for (n = 0; *src && n + 2 < ppos; n++) deg = deg * 10 + (*src++ - '0'); for (; *src && n < ppos; n++) min = min * 10 + (*src++ - '0'); src++; /* skip decimal point */ for (; *src && n < (ppos + 4); n++) min = min * 10 + (*src++ - '0'); for (i=0; i < 6 + ppos - n; i++) min *= 10; deg = deg * 1000000 + (min/60); *dst = neg ? -deg : deg; return (0); } /* * Convert a NMEA 0183 formatted date string to seconds since the epoch. * The string must be of the form DDMMYY. * Return 0 on success, -1 if illegal characters are encountered. */ int nmea_date_to_nano(char *s, int64_t *nano) { struct clock_ymdhms ymd; time_t secs; char *p; int n; /* make sure the input contains only numbers and is six digits long */ for (n = 0, p = s; n < 6 && *p && *p >= '0' && *p <= '9'; n++, p++) ; if (n != 6 || (*p != '\0')) return (-1); ymd.dt_year = 2000 + (s[4] - '0') * 10 + (s[5] - '0'); ymd.dt_mon = (s[2] - '0') * 10 + (s[3] - '0'); ymd.dt_day = (s[0] - '0') * 10 + (s[1] - '0'); ymd.dt_hour = ymd.dt_min = ymd.dt_sec = 0; secs = clock_ymdhms_to_secs(&ymd); *nano = secs * 1000000000LL; return (0); } /* * Convert NMEA 0183 formatted time string to nanoseconds since midnight. * The string must be of the form HHMMSS[.[sss]] (e.g. 143724 or 143723.615). * Return 0 on success, -1 if illegal characters are encountered. */ int nmea_time_to_nano(char *s, int64_t *nano) { long fac = 36000L, div = 6L, secs = 0L, frac = 0L; char ul = '2'; int n; for (n = 0, secs = 0; fac && *s && *s >= '0' && *s <= ul; s++, n++) { secs += (*s - '0') * fac; div = 16 - div; fac /= div; switch (n) { case 0: if (*s <= '1') ul = '9'; else ul = '3'; break; case 1: case 3: ul = '5'; break; case 2: case 4: ul = '9'; break; } } if (fac) return (-1); /* Handle the fractions of a second, up to a maximum of 6 digits. */ div = 1L; if (*s == '.') { for (++s; div < 1000000 && *s && *s >= '0' && *s <= '9'; s++) { frac *= 10; frac += (*s - '0'); div *= 10; } } if (*s != '\0') return (-1); *nano = secs * 1000000000LL + (int64_t)frac * (1000000000 / div); return (0); } /* * Degrade the sensor state if we received no NMEA sentences for more than * TRUSTTIME seconds. */ void nmea_timeout(void *xnp) { struct nmea *np = xnp; np->signal.value = 0; np->signal.status = SENSOR_S_CRIT; if (np->time.status == SENSOR_S_OK) { np->time.status = SENSOR_S_WARN; np->latitude.status = SENSOR_S_WARN; np->longitude.status = SENSOR_S_WARN; np->altitude.status = SENSOR_S_WARN; np->speed.status = SENSOR_S_WARN; /* * further degrade in TRUSTTIME seconds if no new valid NMEA * sentences are received. */ timeout_add_sec(&np->nmea_tout, TRUSTTIME); } else { np->time.status = SENSOR_S_CRIT; np->latitude.status = SENSOR_S_CRIT; np->longitude.status = SENSOR_S_CRIT; np->altitude.status = SENSOR_S_CRIT; np->speed.status = SENSOR_S_CRIT; } }
1 103 4 203 10 15 16 6 2 2 27 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 /* $OpenBSD: protosw.h,v 1.66 2024/04/14 20:46:27 bluhm Exp $ */ /* $NetBSD: protosw.h,v 1.10 1996/04/09 20:55:32 cgd Exp $ */ /*- * Copyright (c) 1982, 1986, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)protosw.h 8.1 (Berkeley) 6/2/93 */ /* * Protocol switch table. * * Each protocol has a handle initializing one of these structures, * which is used for protocol-protocol and system-protocol communication. * * A protocol is called through the pr_init entry before any other. * Thereafter it is called every 200ms through the pr_fasttimo entry and * every 500ms through the pr_slowtimo for timer based actions. * * Protocols pass data between themselves as chains of mbufs using * the pr_input and pr_send hooks. Pr_input passes data up (towards * UNIX) and pr_send passes it down (towards the imps); control * information passes up and down on pr_ctlinput and pr_ctloutput. * The protocol is responsible for the space occupied by any the * arguments to these entries and must dispose it. * * The userreq routine interfaces protocols to the system and is * described below. */ #ifndef _SYS_PROTOSW_H_ #define _SYS_PROTOSW_H_ struct mbuf; struct sockaddr; struct socket; struct domain; struct proc; struct stat; struct ifnet; struct pr_usrreqs { int (*pru_attach)(struct socket *, int, int); int (*pru_detach)(struct socket *); void (*pru_lock)(struct socket *); void (*pru_unlock)(struct socket *); int (*pru_locked)(struct socket *so); int (*pru_bind)(struct socket *, struct mbuf *, struct proc *); int (*pru_listen)(struct socket *); int (*pru_connect)(struct socket *, struct mbuf *); int (*pru_accept)(struct socket *, struct mbuf *); int (*pru_disconnect)(struct socket *); int (*pru_shutdown)(struct socket *); void (*pru_rcvd)(struct socket *); int (*pru_send)(struct socket *, struct mbuf *, struct mbuf *, struct mbuf *); void (*pru_abort)(struct socket *); int (*pru_control)(struct socket *, u_long, caddr_t, struct ifnet *); int (*pru_sense)(struct socket *, struct stat *); int (*pru_rcvoob)(struct socket *, struct mbuf *, int); int (*pru_sendoob)(struct socket *, struct mbuf *, struct mbuf *, struct mbuf *); int (*pru_sockaddr)(struct socket *, struct mbuf *); int (*pru_peeraddr)(struct socket *, struct mbuf *); int (*pru_connect2)(struct socket *, struct socket *); }; struct protosw { short pr_type; /* socket type used for */ const struct domain *pr_domain; /* domain protocol a member of */ short pr_protocol; /* protocol number */ short pr_flags; /* see below */ /* protocol-protocol hooks */ /* input to protocol (from below) */ int (*pr_input)(struct mbuf **, int *, int, int); /* control input (from below) */ void (*pr_ctlinput)(int, struct sockaddr *, u_int, void *); /* control output (from above) */ int (*pr_ctloutput)(int, struct socket *, int, int, struct mbuf *); /* user-protocol hooks */ const struct pr_usrreqs *pr_usrreqs; /* utility hooks */ void (*pr_init)(void); /* initialization hook */ void (*pr_fasttimo)(void); /* fast timeout (200ms) */ void (*pr_slowtimo)(void); /* slow timeout (500ms) */ /* sysctl for protocol */ int (*pr_sysctl)(int *, u_int, void *, size_t *, void *, size_t); }; #define PR_SLOWHZ 2 /* 2 slow timeouts per second */ #define PR_FASTHZ 5 /* 5 fast timeouts per second */ /* * Values for pr_flags. * PR_ADDR requires PR_ATOMIC; * PR_ADDR and PR_CONNREQUIRED are mutually exclusive. */ #define PR_ATOMIC 0x0001 /* exchange atomic messages only */ #define PR_ADDR 0x0002 /* addresses given with messages */ #define PR_CONNREQUIRED 0x0004 /* connection required by protocol */ #define PR_WANTRCVD 0x0008 /* want PRU_RCVD calls */ #define PR_RIGHTS 0x0010 /* passes capabilities */ #define PR_ABRTACPTDIS 0x0020 /* abort on accept(2) to disconnected socket */ #define PR_SPLICE 0x0040 /* socket splicing is possible */ #define PR_MPINPUT 0x0080 /* input runs with shared netlock */ /* * The arguments to usrreq are: * (*protosw[].pr_usrreq)(up, req, m, nam, opt); * where up is a (struct socket *), req is one of these requests, * m is a optional mbuf chain containing a message, * nam is an optional mbuf chain containing an address, * and opt is a pointer to a socketopt structure or nil. * The protocol is responsible for disposal of the mbuf chain m, * the caller is responsible for any space held by nam and opt. * A non-zero return from usrreq gives an * UNIX error number which should be passed to higher level software. */ #define PRU_ATTACH 0 /* attach protocol to up */ #define PRU_DETACH 1 /* detach protocol from up */ #define PRU_BIND 2 /* bind socket to address */ #define PRU_LISTEN 3 /* listen for connection */ #define PRU_CONNECT 4 /* establish connection to peer */ #define PRU_ACCEPT 5 /* accept connection from peer */ #define PRU_DISCONNECT 6 /* disconnect from peer */ #define PRU_SHUTDOWN 7 /* won't send any more data */ #define PRU_RCVD 8 /* have taken data; more room now */ #define PRU_SEND 9 /* send this data */ #define PRU_ABORT 10 /* abort (fast DISCONNECT, DETACH) */ #define PRU_CONTROL 11 /* control operations on protocol */ #define PRU_SENSE 12 /* return status into m */ #define PRU_RCVOOB 13 /* retrieve out of band data */ #define PRU_SENDOOB 14 /* send out of band data */ #define PRU_SOCKADDR 15 /* fetch socket's address */ #define PRU_PEERADDR 16 /* fetch peer's address */ #define PRU_CONNECT2 17 /* connect two sockets */ /* begin for protocols internal use */ #define PRU_FASTTIMO 18 /* 200ms timeout */ #define PRU_SLOWTIMO 19 /* 500ms timeout */ #define PRU_PROTORCV 20 /* receive from below */ #define PRU_PROTOSEND 21 /* send to below */ #define PRU_NREQ 22 #ifdef PRUREQUESTS const char *prurequests[] = { "ATTACH", "DETACH", "BIND", "LISTEN", "CONNECT", "ACCEPT", "DISCONNECT", "SHUTDOWN", "RCVD", "SEND", "ABORT", "CONTROL", "SENSE", "RCVOOB", "SENDOOB", "SOCKADDR", "PEERADDR", "CONNECT2", "FASTTIMO", "SLOWTIMO", "PROTORCV", "PROTOSEND", }; #endif /* * The arguments to the ctlinput routine are * (*protosw[].pr_ctlinput)(cmd, sa, arg); * where cmd is one of the commands below, sa is a pointer to a sockaddr, * and arg is an optional caddr_t argument used within a protocol family. */ #define PRC_IFDOWN 0 /* interface transition */ #define PRC_ROUTEDEAD 1 /* select new route if possible ??? */ #define PRC_MTUINC 2 /* increase in mtu to host */ #define PRC_QUENCH2 3 /* DEC congestion bit says slow down */ #define PRC_QUENCH 4 /* some one said to slow down */ #define PRC_MSGSIZE 5 /* message size forced drop */ #define PRC_HOSTDEAD 6 /* host appears to be down */ #define PRC_HOSTUNREACH 7 /* deprecated (use PRC_UNREACH_HOST) */ #define PRC_UNREACH_NET 8 /* no route to network */ #define PRC_UNREACH_HOST 9 /* no route to host */ #define PRC_UNREACH_PROTOCOL 10 /* dst says bad protocol */ #define PRC_UNREACH_PORT 11 /* bad port # */ /* was PRC_UNREACH_NEEDFRAG 12 (use PRC_MSGSIZE) */ #define PRC_UNREACH_SRCFAIL 13 /* source route failed */ #define PRC_REDIRECT_NET 14 /* net routing redirect */ #define PRC_REDIRECT_HOST 15 /* host routing redirect */ #define PRC_REDIRECT_TOSNET 16 /* redirect for type of service & net */ #define PRC_REDIRECT_TOSHOST 17 /* redirect for tos & host */ #define PRC_TIMXCEED_INTRANS 18 /* packet lifetime expired in transit */ #define PRC_TIMXCEED_REASS 19 /* lifetime expired on reass q */ #define PRC_PARAMPROB 20 /* header incorrect */ #define PRC_NCMDS 21 #define PRC_IS_REDIRECT(cmd) \ ((cmd) >= PRC_REDIRECT_NET && (cmd) <= PRC_REDIRECT_TOSHOST) #ifdef PRCREQUESTS char *prcrequests[] = { "IFDOWN", "ROUTEDEAD", "MTUINC", "DEC-BIT-QUENCH2", "QUENCH", "MSGSIZE", "HOSTDEAD", "#7", "NET-UNREACH", "HOST-UNREACH", "PROTO-UNREACH", "PORT-UNREACH", "#12", "SRCFAIL-UNREACH", "NET-REDIRECT", "HOST-REDIRECT", "TOSNET-REDIRECT", "TOSHOST-REDIRECT", "TX-INTRANS", "TX-REASS", "PARAMPROB" }; #endif /* * The arguments to ctloutput are: * (*protosw[].pr_ctloutput)(req, so, level, optname, optval); * req is one of the actions listed below, so is a (struct socket *), * level is an indication of which protocol layer the option is intended. * optname is a protocol dependent socket option request, * optval is a pointer to a mbuf-chain pointer, for value-return results. * The protocol is responsible for disposal of the mbuf chain *optval * if supplied, * the caller is responsible for any space held by *optval, when returned. * A non-zero return from usrreq gives an * UNIX error number which should be passed to higher level software. */ #define PRCO_GETOPT 0 #define PRCO_SETOPT 1 #define PRCO_NCMDS 2 #ifdef PRCOREQUESTS char *prcorequests[] = { "GETOPT", "SETOPT", }; #endif #ifdef _KERNEL #include <sys/mbuf.h> #include <sys/socketvar.h> #include <sys/systm.h> struct ifnet; struct sockaddr; const struct protosw *pffindproto(int, int, int); const struct protosw *pffindtype(int, int); const struct domain *pffinddomain(int); void pfctlinput(int, struct sockaddr *); extern u_char ip_protox[]; extern const struct protosw inetsw[]; #ifdef INET6 extern u_char ip6_protox[]; extern const struct protosw inet6sw[]; #endif /* INET6 */ static inline int pru_attach(struct socket *so, int proto, int wait) { return (*so->so_proto->pr_usrreqs->pru_attach)(so, proto, wait); } static inline int pru_detach(struct socket *so) { return (*so->so_proto->pr_usrreqs->pru_detach)(so); } static inline void pru_lock(struct socket *so) { if (so->so_proto->pr_usrreqs->pru_lock) (*so->so_proto->pr_usrreqs->pru_lock)(so); } static inline void pru_unlock(struct socket *so) { if (so->so_proto->pr_usrreqs->pru_unlock) (*so->so_proto->pr_usrreqs->pru_unlock)(so); } static inline int pru_locked(struct socket *so) { if (so->so_proto->pr_usrreqs->pru_locked) return (*so->so_proto->pr_usrreqs->pru_locked)(so); return (0); } static inline int pru_bind(struct socket *so, struct mbuf *nam, struct proc *p) { if (so->so_proto->pr_usrreqs->pru_bind) return (*so->so_proto->pr_usrreqs->pru_bind)(so, nam, p); return (EOPNOTSUPP); } static inline int pru_listen(struct socket *so) { if (so->so_proto->pr_usrreqs->pru_listen) return (*so->so_proto->pr_usrreqs->pru_listen)(so); return (EOPNOTSUPP); } static inline int pru_connect(struct socket *so, struct mbuf *nam) { if (so->so_proto->pr_usrreqs->pru_connect) return (*so->so_proto->pr_usrreqs->pru_connect)(so, nam); return (EOPNOTSUPP); } static inline int pru_accept(struct socket *so, struct mbuf *nam) { if (so->so_proto->pr_usrreqs->pru_accept) return (*so->so_proto->pr_usrreqs->pru_accept)(so, nam); return (EOPNOTSUPP); } static inline int pru_disconnect(struct socket *so) { if (so->so_proto->pr_usrreqs->pru_disconnect) return (*so->so_proto->pr_usrreqs->pru_disconnect)(so); return (EOPNOTSUPP); } static inline int pru_shutdown(struct socket *so) { return (*so->so_proto->pr_usrreqs->pru_shutdown)(so); } static inline void pru_rcvd(struct socket *so) { (*so->so_proto->pr_usrreqs->pru_rcvd)(so); } static inline int pru_send(struct socket *so, struct mbuf *top, struct mbuf *addr, struct mbuf *control) { return (*so->so_proto->pr_usrreqs->pru_send)(so, top, addr, control); } static inline void pru_abort(struct socket *so) { (*so->so_proto->pr_usrreqs->pru_abort)(so); } static inline int pru_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp) { if (so->so_proto->pr_usrreqs->pru_control) return (*so->so_proto->pr_usrreqs->pru_control)(so, cmd, data, ifp); return (EOPNOTSUPP); } static inline int pru_sense(struct socket *so, struct stat *ub) { if (so->so_proto->pr_usrreqs->pru_sense) return (*so->so_proto->pr_usrreqs->pru_sense)(so, ub); return (0); } static inline int pru_rcvoob(struct socket *so, struct mbuf *m, int flags) { if (so->so_proto->pr_usrreqs->pru_rcvoob) return (*so->so_proto->pr_usrreqs->pru_rcvoob)(so, m, flags); return (EOPNOTSUPP); } static inline int pru_sendoob(struct socket *so, struct mbuf *top, struct mbuf *addr, struct mbuf *control) { if (so->so_proto->pr_usrreqs->pru_sendoob) return (*so->so_proto->pr_usrreqs->pru_sendoob)(so, top, addr, control); m_freem(top); m_freem(control); return (EOPNOTSUPP); } static inline int pru_sockaddr(struct socket *so, struct mbuf *addr) { return (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, addr); } static inline int pru_peeraddr(struct socket *so, struct mbuf *addr) { return (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, addr); } static inline int pru_connect2(struct socket *so1, struct socket *so2) { if (so1->so_proto->pr_usrreqs->pru_connect2) return (*so1->so_proto->pr_usrreqs->pru_connect2)(so1, so2); return (EOPNOTSUPP); } #endif #endif /* _SYS_PROTOSW_H_ */
37 37 11 28 37 37 37 37 37 15 30 23 7 36 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 /* $OpenBSD: in4_cksum.c,v 1.11 2022/02/01 15:30:10 miod Exp $ */ /* $KAME: in4_cksum.c,v 1.10 2001/11/30 10:06:15 itojun Exp $ */ /* $NetBSD: in_cksum.c,v 1.13 1996/10/13 02:03:03 christos Exp $ */ /* * Copyright (C) 1999 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 1988, 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93 */ #include <sys/param.h> #include <sys/mbuf.h> #include <sys/systm.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_var.h> /* * Checksum routine for Internet Protocol family headers (Portable Version). * This is only for IPv4 pseudo header checksum. * No need to clear non-pseudo-header fields in IPv4 header. * len is for actual payload size, and does not include IPv4 header and * skipped header chain (off + len should be equal to the whole packet). * * This routine is very heavily used in the network * code and should be modified for each CPU to be as fast as possible. */ #define ADDCARRY(x) (x > 65535 ? x -= 65535 : x) #define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);} int in4_cksum(struct mbuf *m, u_int8_t nxt, int off, int len) { u_int16_t *w; int sum = 0; int mlen = 0; int byte_swapped = 0; union { struct ipovly ipov; u_int16_t w[10]; } u; union { u_int8_t c[2]; u_int16_t s; } s_util; union { u_int16_t s[2]; u_int32_t l; } l_util; if (nxt != 0) { /* pseudo header */ if (off < sizeof(struct ipovly)) panic("in4_cksum: offset too short"); if (m->m_len < sizeof(struct ip)) panic("in4_cksum: bad mbuf chain"); u.ipov.ih_x1[8] = 0; u.ipov.ih_pr = nxt; u.ipov.ih_len = htons(len); u.ipov.ih_src = mtod(m, struct ip *)->ip_src; u.ipov.ih_dst = mtod(m, struct ip *)->ip_dst; w = u.w; /* assumes sizeof(ipov) == 20 and first 8 bytes are zeroes */ sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; sum += w[8]; sum += w[9]; } /* skip unnecessary part */ while (m && off > 0) { if (m->m_len > off) break; off -= m->m_len; m = m->m_next; } for (;m && len; m = m->m_next) { if (m->m_len == 0) continue; w = (u_int16_t *)(mtod(m, caddr_t) + off); if (mlen == -1) { /* * The first byte of this mbuf is the continuation * of a word spanning between this mbuf and the * last mbuf. * * s_util.c[0] is already saved when scanning previous * mbuf. */ s_util.c[1] = *(u_int8_t *)w; sum += s_util.s; w = (u_int16_t *)((u_int8_t *)w + 1); mlen = m->m_len - off - 1; len--; } else mlen = m->m_len - off; off = 0; if (len < mlen) mlen = len; len -= mlen; /* * Force to even boundary. */ if ((1 & (long) w) && (mlen > 0)) { REDUCE; sum <<= 8; s_util.c[0] = *(u_int8_t *)w; w = (u_int16_t *)((int8_t *)w + 1); mlen--; byte_swapped = 1; } /* * Unroll the loop to make overhead from * branches &c small. */ while ((mlen -= 32) >= 0) { sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11]; sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15]; w += 16; } mlen += 32; while ((mlen -= 8) >= 0) { sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; w += 4; } mlen += 8; if (mlen == 0 && byte_swapped == 0) continue; REDUCE; while ((mlen -= 2) >= 0) { sum += *w++; } if (byte_swapped) { REDUCE; sum <<= 8; byte_swapped = 0; if (mlen == -1) { s_util.c[1] = *(u_int8_t *)w; sum += s_util.s; mlen = 0; } else mlen = -1; } else if (mlen == -1) s_util.c[0] = *(u_int8_t *)w; } if (len) printf("cksum4: out of data\n"); if (mlen == -1) { /* The last mbuf has odd # of bytes. Follow the standard (the odd byte may be shifted left by 8 bits or not as determined by endian-ness of the machine) */ s_util.c[1] = 0; sum += s_util.s; } REDUCE; return (~sum & 0xffff); }
42 1 20 23 3 20 108 3 2 102 8 106 21 3 18 26 26 17 11 20 1 1 17 1 3 3 7 3 9 12 3 9 9 3 7 5 9 9 9 10 10 217 3 2 210 21 213 1 113 105 8 203 18 5 2 8 4 12 1 1 7 1 8 8 2 2 2 1 3 2 4 3 3 176 179 2 171 25 1 166 9 148 24 4 167 9 79 57 72 69 12 75 38 2 72 37 3 40 38 419 16 408 3 295 2 140 137 13 4 2 91 14 392 39 140 163 166 396 19 408 22 2 11 9 63 2 2 54 5 32 27 17 38 7 1 53 5 82 66 2 12 4 2 13 32 44 4 66 25 1 67 28 41 41 5 2 6 8 8 52 25 54 2 21 141 13 132 4 118 20 128 3 130 38 116 6 16 51 91 4 6 3 29 82 4 18 4 20 3 1 12 9 126 51 2 49 734 5 1 162 592 3 2 589 725 207 3 63 153 27 13 38 205 29 4 2 3 21 26 17 3 1 2 12 15 491 4 486 11 3 96 439 26 9 41 18 23 38 3 31 5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 /* $OpenBSD: uipc_syscalls.c,v 1.219 2024/04/25 17:32:53 bluhm Exp $ */ /* $NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/filedesc.h> #include <sys/namei.h> #include <sys/pool.h> #include <sys/proc.h> #include <sys/fcntl.h> #include <sys/kernel.h> #include <sys/file.h> #include <sys/vnode.h> #include <sys/malloc.h> #include <sys/event.h> #include <sys/mbuf.h> #include <sys/protosw.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/signalvar.h> #include <sys/pledge.h> #ifdef KTRACE #include <sys/ktrace.h> #endif #include <sys/unistd.h> #include <sys/mount.h> #include <sys/syscallargs.h> #include <sys/domain.h> #include <netinet/in.h> #include <netinet/ip.h> #include <net/route.h> #include <netinet/in_pcb.h> #include <net/rtable.h> int copyaddrout(struct proc *, struct mbuf *, struct sockaddr *, socklen_t, socklen_t *); int sys_socket(struct proc *p, void *v, register_t *retval) { struct sys_socket_args /* { syscallarg(int) domain; syscallarg(int) type; syscallarg(int) protocol; } */ *uap = v; struct filedesc *fdp = p->p_fd; struct socket *so; struct file *fp; int type = SCARG(uap, type); int domain = SCARG(uap, domain); int fd, cloexec, nonblock, fflag, error; unsigned int ss = 0; if ((type & SOCK_DNS) && !(domain == AF_INET || domain == AF_INET6)) return (EINVAL); if (ISSET(type, SOCK_DNS)) ss |= SS_DNS; error = pledge_socket(p, domain, ss); if (error) return (error); type &= ~(SOCK_CLOEXEC | SOCK_NONBLOCK | SOCK_DNS); cloexec = (SCARG(uap, type) & SOCK_CLOEXEC) ? UF_EXCLOSE : 0; nonblock = SCARG(uap, type) & SOCK_NONBLOCK; fflag = FREAD | FWRITE | (nonblock ? FNONBLOCK : 0); error = socreate(SCARG(uap, domain), &so, type, SCARG(uap, protocol)); if (error) return (error); fdplock(fdp); error = falloc(p, &fp, &fd); if (error) { fdpunlock(fdp); soclose(so, MSG_DONTWAIT); } else { fp->f_flag = fflag; fp->f_type = DTYPE_SOCKET; fp->f_ops = &socketops; so->so_state |= ss; fp->f_data = so; fdinsert(fdp, fd, cloexec, fp); fdpunlock(fdp); FRELE(fp, p); *retval = fd; } return (error); } static inline int isdnssocket(struct socket *so) { return (so->so_state & SS_DNS); } /* For SS_DNS sockets, only allow port DNS (port 53) */ static int dns_portcheck(struct proc *p, struct socket *so, void *nam, size_t namelen) { int error = EINVAL; switch (so->so_proto->pr_domain->dom_family) { case AF_INET: if (namelen < sizeof(struct sockaddr_in)) break; if (((struct sockaddr_in *)nam)->sin_port == htons(53)) error = 0; break; #ifdef INET6 case AF_INET6: if (namelen < sizeof(struct sockaddr_in6)) break; if (((struct sockaddr_in6 *)nam)->sin6_port == htons(53)) error = 0; #endif } if (error && p->p_p->ps_flags & PS_PLEDGE) return (pledge_fail(p, EPERM, PLEDGE_DNS)); return error; } int sys_bind(struct proc *p, void *v, register_t *retval) { struct sys_bind_args /* { syscallarg(int) s; syscallarg(const struct sockaddr *) name; syscallarg(socklen_t) namelen; } */ *uap = v; struct file *fp; struct mbuf *nam; struct socket *so; int error; if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) return (error); so = fp->f_data; error = pledge_socket(p, so->so_proto->pr_domain->dom_family, so->so_state); if (error) goto out; if (so->so_state & SS_YP) { error = ENOTSOCK; goto out; } error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), MT_SONAME); if (error) goto out; #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen)); #endif solock_shared(so); error = sobind(so, nam, p); sounlock_shared(so); m_freem(nam); out: FRELE(fp, p); return (error); } int sys_listen(struct proc *p, void *v, register_t *retval) { struct sys_listen_args /* { syscallarg(int) s; syscallarg(int) backlog; } */ *uap = v; struct file *fp; struct socket *so; int error; if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) return (error); so = fp->f_data; if (so->so_state & SS_YP) return ENOTSOCK; solock(so); error = solisten(so, SCARG(uap, backlog)); sounlock(so); FRELE(fp, p); return (error); } int sys_accept(struct proc *p, void *v, register_t *retval) { struct sys_accept_args /* { syscallarg(int) s; syscallarg(struct sockaddr *) name; syscallarg(socklen_t *) anamelen; } */ *uap = v; return (doaccept(p, SCARG(uap, s), SCARG(uap, name), SCARG(uap, anamelen), SOCK_NONBLOCK_INHERIT, retval)); } int sys_accept4(struct proc *p, void *v, register_t *retval) { struct sys_accept4_args /* { syscallarg(int) s; syscallarg(struct sockaddr *) name; syscallarg(socklen_t *) anamelen; syscallarg(socklen_t *) int flags; } */ *uap = v; if (SCARG(uap, flags) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) return (EINVAL); return (doaccept(p, SCARG(uap, s), SCARG(uap, name), SCARG(uap, anamelen), SCARG(uap, flags), retval)); } int doaccept(struct proc *p, int sock, struct sockaddr *name, socklen_t *anamelen, int flags, register_t *retval) { struct filedesc *fdp = p->p_fd; struct file *fp, *headfp; struct mbuf *nam; socklen_t namelen; int error, tmpfd; struct socket *head, *so; int cloexec, nflag, persocket; cloexec = (flags & SOCK_CLOEXEC) ? UF_EXCLOSE : 0; if (name && (error = copyin(anamelen, &namelen, sizeof (namelen)))) return (error); if ((error = getsock(p, sock, &fp)) != 0) return (error); headfp = fp; fdplock(fdp); error = falloc(p, &fp, &tmpfd); fdpunlock(fdp); if (error) { FRELE(headfp, p); return (error); } nam = m_get(M_WAIT, MT_SONAME); head = headfp->f_data; solock(head); persocket = solock_persocket(head); if (isdnssocket(head) || (head->so_options & SO_ACCEPTCONN) == 0) { error = EINVAL; goto out_unlock; } if ((headfp->f_flag & FNONBLOCK) && head->so_qlen == 0) { if (head->so_rcv.sb_state & SS_CANTRCVMORE) error = ECONNABORTED; else error = EWOULDBLOCK; goto out_unlock; } while (head->so_qlen == 0 && head->so_error == 0) { if (head->so_rcv.sb_state & SS_CANTRCVMORE) { head->so_error = ECONNABORTED; break; } error = sosleep_nsec(head, &head->so_timeo, PSOCK | PCATCH, "netacc", INFSLP); if (error) goto out_unlock; } if (head->so_error) { error = head->so_error; head->so_error = 0; goto out_unlock; } /* * Do not sleep after we have taken the socket out of the queue. */ so = TAILQ_FIRST(&head->so_q); if (persocket) solock(so); if (soqremque(so, 1) == 0) panic("accept"); /* Figure out whether the new socket should be non-blocking. */ nflag = flags & SOCK_NONBLOCK_INHERIT ? (headfp->f_flag & FNONBLOCK) : (flags & SOCK_NONBLOCK ? FNONBLOCK : 0); /* connection has been removed from the listen queue */ knote(&head->so_rcv.sb_klist, 0); if (persocket) sounlock(head); fp->f_type = DTYPE_SOCKET; fp->f_flag = FREAD | FWRITE | nflag; fp->f_ops = &socketops; fp->f_data = so; error = soaccept(so, nam); if (persocket) sounlock(so); else sounlock(head); if (error) goto out; if (name != NULL) { error = copyaddrout(p, nam, name, namelen, anamelen); if (error) goto out; } fdplock(fdp); fdinsert(fdp, tmpfd, cloexec, fp); fdpunlock(fdp); FRELE(fp, p); *retval = tmpfd; m_freem(nam); FRELE(headfp, p); return 0; out_unlock: sounlock(head); out: fdplock(fdp); fdremove(fdp, tmpfd); fdpunlock(fdp); closef(fp, p); m_freem(nam); FRELE(headfp, p); return (error); } int sys_connect(struct proc *p, void *v, register_t *retval) { struct sys_connect_args /* { syscallarg(int) s; syscallarg(const struct sockaddr *) name; syscallarg(socklen_t) namelen; } */ *uap = v; struct file *fp; struct socket *so; struct mbuf *nam; int error, interrupted = 0; if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) return (error); so = fp->f_data; error = pledge_socket(p, so->so_proto->pr_domain->dom_family, so->so_state); if (error) goto out; if (so->so_state & SS_YP) { error = ENOTSOCK; goto out; } error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), MT_SONAME); if (error) goto out; #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen)); #endif solock_shared(so); if (isdnssocket(so)) { error = dns_portcheck(p, so, mtod(nam, void *), nam->m_len); if (error) goto unlock; } if (so->so_state & SS_ISCONNECTING) { error = EALREADY; goto unlock; } error = soconnect(so, nam); if (error) goto bad; if ((fp->f_flag & FNONBLOCK) && (so->so_state & SS_ISCONNECTING)) { error = EINPROGRESS; goto unlock; } while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { error = sosleep_nsec(so, &so->so_timeo, PSOCK | PCATCH, "netcon", INFSLP); if (error) { if (error == EINTR || error == ERESTART) interrupted = 1; break; } } if (error == 0) { error = so->so_error; so->so_error = 0; } bad: if (!interrupted) so->so_state &= ~SS_ISCONNECTING; unlock: sounlock_shared(so); m_freem(nam); out: FRELE(fp, p); if (error == ERESTART) error = EINTR; return (error); } int sys_socketpair(struct proc *p, void *v, register_t *retval) { struct sys_socketpair_args /* { syscallarg(int) domain; syscallarg(int) type; syscallarg(int) protocol; syscallarg(int *) rsv; } */ *uap = v; struct filedesc *fdp = p->p_fd; struct file *fp1 = NULL, *fp2 = NULL; struct socket *so1, *so2; int type, cloexec, nonblock, fflag, error, sv[2]; type = SCARG(uap, type) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK); cloexec = (SCARG(uap, type) & SOCK_CLOEXEC) ? UF_EXCLOSE : 0; nonblock = SCARG(uap, type) & SOCK_NONBLOCK; fflag = FREAD | FWRITE | (nonblock ? FNONBLOCK : 0); error = socreate(SCARG(uap, domain), &so1, type, SCARG(uap, protocol)); if (error) return (error); error = socreate(SCARG(uap, domain), &so2, type, SCARG(uap, protocol)); if (error) goto free1; error = soconnect2(so1, so2); if (error != 0) goto free2; if ((SCARG(uap, type) & SOCK_TYPE_MASK) == SOCK_DGRAM) { /* * Datagram socket connection is asymmetric. */ error = soconnect2(so2, so1); if (error != 0) goto free2; } fdplock(fdp); if ((error = falloc(p, &fp1, &sv[0])) != 0) goto free3; fp1->f_flag = fflag; fp1->f_type = DTYPE_SOCKET; fp1->f_ops = &socketops; fp1->f_data = so1; if ((error = falloc(p, &fp2, &sv[1])) != 0) goto free4; fp2->f_flag = fflag; fp2->f_type = DTYPE_SOCKET; fp2->f_ops = &socketops; fp2->f_data = so2; error = copyout(sv, SCARG(uap, rsv), 2 * sizeof (int)); if (error == 0) { fdinsert(fdp, sv[0], cloexec, fp1); fdinsert(fdp, sv[1], cloexec, fp2); fdpunlock(fdp); #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrfds(p, sv, 2); #endif FRELE(fp1, p); FRELE(fp2, p); return (0); } fdremove(fdp, sv[1]); free4: fdremove(fdp, sv[0]); free3: fdpunlock(fdp); if (fp2 != NULL) { closef(fp2, p); so2 = NULL; } if (fp1 != NULL) { closef(fp1, p); so1 = NULL; } free2: if (so2 != NULL) (void)soclose(so2, 0); free1: if (so1 != NULL) (void)soclose(so1, 0); return (error); } int sys_sendto(struct proc *p, void *v, register_t *retval) { struct sys_sendto_args /* { syscallarg(int) s; syscallarg(const void *) buf; syscallarg(size_t) len; syscallarg(int) flags; syscallarg(const struct sockaddr *) to; syscallarg(socklen_t) tolen; } */ *uap = v; struct msghdr msg; struct iovec aiov; msg.msg_name = (caddr_t)SCARG(uap, to); msg.msg_namelen = SCARG(uap, tolen); msg.msg_iov = &aiov; msg.msg_iovlen = 1; msg.msg_control = NULL; msg.msg_flags = 0; aiov.iov_base = (char *)SCARG(uap, buf); aiov.iov_len = SCARG(uap, len); return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval)); } int sys_sendmsg(struct proc *p, void *v, register_t *retval) { struct sys_sendmsg_args /* { syscallarg(int) s; syscallarg(const struct msghdr *) msg; syscallarg(int) flags; } */ *uap = v; struct msghdr msg; struct iovec aiov[UIO_SMALLIOV], *iov; int error; error = copyin(SCARG(uap, msg), &msg, sizeof (msg)); if (error) return (error); #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrmsghdr(p, &msg); #endif if (msg.msg_iovlen > IOV_MAX) return (EMSGSIZE); if (msg.msg_iovlen > UIO_SMALLIOV) iov = mallocarray(msg.msg_iovlen, sizeof(struct iovec), M_IOV, M_WAITOK); else iov = aiov; if (msg.msg_iovlen && (error = copyin(msg.msg_iov, iov, msg.msg_iovlen * sizeof (struct iovec)))) goto done; #ifdef KTRACE if (msg.msg_iovlen && KTRPOINT(p, KTR_STRUCT)) ktriovec(p, iov, msg.msg_iovlen); #endif msg.msg_iov = iov; msg.msg_flags = 0; error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval); done: if (iov != aiov) free(iov, M_IOV, sizeof(struct iovec) * msg.msg_iovlen); return (error); } int sys_sendmmsg(struct proc *p, void *v, register_t *retval) { struct sys_sendmmsg_args /* { syscallarg(int) s; syscallarg(struct mmsghdr *) mmsg; syscallarg(unsigned int) vlen; syscallarg(int) flags; } */ *uap = v; struct mmsghdr mmsg, *mmsgp; struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *uiov; size_t iovlen = UIO_SMALLIOV; register_t retsnd; unsigned int vlen, dgrams; int error = 0, flags, s; s = SCARG(uap, s); flags = SCARG(uap, flags); /* Arbitrarily capped at 1024 datagrams. */ vlen = SCARG(uap, vlen); if (vlen > 1024) vlen = 1024; mmsgp = SCARG(uap, mmsg); for (dgrams = 0; dgrams < vlen; dgrams++) { error = copyin(&mmsgp[dgrams], &mmsg, sizeof(mmsg)); if (error) break; #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrmmsghdr(p, &mmsg); #endif if (mmsg.msg_hdr.msg_iovlen > IOV_MAX) { error = EMSGSIZE; break; } if (mmsg.msg_hdr.msg_iovlen > iovlen) { if (iov != aiov) free(iov, M_IOV, iovlen * sizeof(struct iovec)); iovlen = mmsg.msg_hdr.msg_iovlen; iov = mallocarray(iovlen, sizeof(struct iovec), M_IOV, M_WAITOK); } if (mmsg.msg_hdr.msg_iovlen > 0) { error = copyin(mmsg.msg_hdr.msg_iov, iov, mmsg.msg_hdr.msg_iovlen * sizeof(struct iovec)); if (error) break; } #ifdef KTRACE if (mmsg.msg_hdr.msg_iovlen && KTRPOINT(p, KTR_STRUCT)) ktriovec(p, iov, mmsg.msg_hdr.msg_iovlen); #endif uiov = mmsg.msg_hdr.msg_iov; mmsg.msg_hdr.msg_iov = iov; mmsg.msg_hdr.msg_flags = 0; error = sendit(p, s, &mmsg.msg_hdr, flags, &retsnd); if (error) break; mmsg.msg_hdr.msg_iov = uiov; mmsg.msg_len = retsnd; error = copyout(&mmsg, &mmsgp[dgrams], sizeof(mmsg)); if (error) break; } if (iov != aiov) free(iov, M_IOV, sizeof(struct iovec) * iovlen); *retval = dgrams; if (error && dgrams > 0) error = 0; return (error); } int sendit(struct proc *p, int s, struct msghdr *mp, int flags, register_t *retsize) { struct file *fp; struct uio auio; struct iovec *iov; int i; struct mbuf *to, *control; struct socket *so; size_t len; int error; #ifdef KTRACE struct iovec *ktriov = NULL; int iovlen = 0; #endif to = NULL; if ((error = getsock(p, s, &fp)) != 0) return (error); so = fp->f_data; if (fp->f_flag & FNONBLOCK) flags |= MSG_DONTWAIT; error = pledge_sendit(p, mp->msg_name); if (error) goto bad; auio.uio_iov = mp->msg_iov; auio.uio_iovcnt = mp->msg_iovlen; auio.uio_segflg = UIO_USERSPACE; auio.uio_rw = UIO_WRITE; auio.uio_procp = p; auio.uio_offset = 0; /* XXX */ auio.uio_resid = 0; iov = mp->msg_iov; for (i = 0; i < mp->msg_iovlen; i++, iov++) { /* Don't allow sum > SSIZE_MAX */ if (iov->iov_len > SSIZE_MAX || (auio.uio_resid += iov->iov_len) > SSIZE_MAX) { error = EINVAL; goto bad; } } if (mp->msg_name) { error = sockargs(&to, mp->msg_name, mp->msg_namelen, MT_SONAME); if (error) goto bad; if (isdnssocket(so)) { error = dns_portcheck(p, so, mtod(to, caddr_t), mp->msg_namelen); if (error) goto bad; } #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrsockaddr(p, mtod(to, caddr_t), mp->msg_namelen); #endif } if (mp->msg_control) { if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))) { error = EINVAL; goto bad; } error = sockargs(&control, mp->msg_control, mp->msg_controllen, MT_CONTROL); if (error) goto bad; #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT) && mp->msg_controllen) ktrcmsghdr(p, mtod(control, char *), mp->msg_controllen); #endif } else control = NULL; #ifdef KTRACE if (KTRPOINT(p, KTR_GENIO)) { ktriov = mallocarray(auio.uio_iovcnt, sizeof(struct iovec), M_TEMP, M_WAITOK); iovlen = auio.uio_iovcnt * sizeof (struct iovec); memcpy(ktriov, auio.uio_iov, iovlen); } #endif len = auio.uio_resid; error = sosend(so, to, &auio, NULL, control, flags); if (error) { if (auio.uio_resid != len && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; if (error == EPIPE && (flags & MSG_NOSIGNAL) == 0) { KERNEL_LOCK(); ptsignal(p, SIGPIPE, STHREAD); KERNEL_UNLOCK(); } } if (error == 0) { *retsize = len - auio.uio_resid; mtx_enter(&fp->f_mtx); fp->f_wxfer++; fp->f_wbytes += *retsize; mtx_leave(&fp->f_mtx); } #ifdef KTRACE if (ktriov != NULL) { if (error == 0) ktrgenio(p, s, UIO_WRITE, ktriov, *retsize); free(ktriov, M_TEMP, iovlen); } #endif bad: FRELE(fp, p); m_freem(to); return (error); } int sys_recvfrom(struct proc *p, void *v, register_t *retval) { struct sys_recvfrom_args /* { syscallarg(int) s; syscallarg(void *) buf; syscallarg(size_t) len; syscallarg(int) flags; syscallarg(struct sockaddr *) from; syscallarg(socklen_t *) fromlenaddr; } */ *uap = v; struct msghdr msg; struct iovec aiov; int error; if (SCARG(uap, fromlenaddr)) { error = copyin(SCARG(uap, fromlenaddr), &msg.msg_namelen, sizeof (msg.msg_namelen)); if (error) return (error); } else msg.msg_namelen = 0; msg.msg_name = (caddr_t)SCARG(uap, from); msg.msg_iov = &aiov; msg.msg_iovlen = 1; aiov.iov_base = SCARG(uap, buf); aiov.iov_len = SCARG(uap, len); msg.msg_control = NULL; msg.msg_flags = SCARG(uap, flags); return (recvit(p, SCARG(uap, s), &msg, (caddr_t)SCARG(uap, fromlenaddr), retval)); } int sys_recvmsg(struct proc *p, void *v, register_t *retval) { struct sys_recvmsg_args /* { syscallarg(int) s; syscallarg(struct msghdr *) msg; syscallarg(int) flags; } */ *uap = v; struct msghdr msg; struct iovec aiov[UIO_SMALLIOV], *uiov, *iov; int error; error = copyin(SCARG(uap, msg), &msg, sizeof (msg)); if (error) return (error); if (msg.msg_iovlen > IOV_MAX) return (EMSGSIZE); if (msg.msg_iovlen > UIO_SMALLIOV) iov = mallocarray(msg.msg_iovlen, sizeof(struct iovec), M_IOV, M_WAITOK); else iov = aiov; msg.msg_flags = SCARG(uap, flags); if (msg.msg_iovlen > 0) { error = copyin(msg.msg_iov, iov, msg.msg_iovlen * sizeof(struct iovec)); if (error) goto done; } uiov = msg.msg_iov; msg.msg_iov = iov; if ((error = recvit(p, SCARG(uap, s), &msg, NULL, retval)) == 0) { msg.msg_iov = uiov; #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) { ktrmsghdr(p, &msg); if (msg.msg_iovlen) ktriovec(p, iov, msg.msg_iovlen); } #endif error = copyout(&msg, SCARG(uap, msg), sizeof(msg)); } done: if (iov != aiov) free(iov, M_IOV, sizeof(struct iovec) * msg.msg_iovlen); return (error); } int sys_recvmmsg(struct proc *p, void *v, register_t *retval) { struct sys_recvmmsg_args /* { syscallarg(int) s; syscallarg(struct mmsghdr *) mmsg; syscallarg(unsigned int) vlen; syscallarg(int) flags; syscallarg(struct timespec *) timeout; } */ *uap = v; struct mmsghdr mmsg, *mmsgp; struct timespec ts, now, *timeout; struct iovec aiov[UIO_SMALLIOV], *uiov, *iov = aiov; size_t iovlen = UIO_SMALLIOV; register_t retrec; unsigned int vlen, dgrams; int error = 0, flags, s; timeout = SCARG(uap, timeout); if (timeout != NULL) { error = copyin(timeout, &ts, sizeof(ts)); if (error) return (error); #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrreltimespec(p, &ts); #endif if (!timespecisvalid(&ts)) return (EINVAL); getnanotime(&now); timespecadd(&now, &ts, &ts); } s = SCARG(uap, s); flags = SCARG(uap, flags); /* Arbitrarily capped at 1024 datagrams. */ vlen = SCARG(uap, vlen); if (vlen > 1024) vlen = 1024; mmsgp = SCARG(uap, mmsg); for (dgrams = 0; dgrams < vlen;) { error = copyin(&mmsgp[dgrams], &mmsg, sizeof(mmsg)); if (error) break; if (mmsg.msg_hdr.msg_iovlen > IOV_MAX) { error = EMSGSIZE; break; } if (mmsg.msg_hdr.msg_iovlen > iovlen) { if (iov != aiov) free(iov, M_IOV, iovlen * sizeof(struct iovec)); iovlen = mmsg.msg_hdr.msg_iovlen; iov = mallocarray(iovlen, sizeof(struct iovec), M_IOV, M_WAITOK); } if (mmsg.msg_hdr.msg_iovlen > 0) { error = copyin(mmsg.msg_hdr.msg_iov, iov, mmsg.msg_hdr.msg_iovlen * sizeof(struct iovec)); if (error) break; } uiov = mmsg.msg_hdr.msg_iov; mmsg.msg_hdr.msg_iov = iov; mmsg.msg_hdr.msg_flags = flags & ~MSG_WAITFORONE; error = recvit(p, s, &mmsg.msg_hdr, NULL, &retrec); if (error) { if (error == EAGAIN && dgrams > 0) error = 0; break; } if (flags & MSG_WAITFORONE) flags |= MSG_DONTWAIT; mmsg.msg_hdr.msg_iov = uiov; mmsg.msg_len = retrec; #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) { ktrmmsghdr(p, &mmsg); if (mmsg.msg_hdr.msg_iovlen) ktriovec(p, iov, mmsg.msg_hdr.msg_iovlen); } #endif error = copyout(&mmsg, &mmsgp[dgrams], sizeof(mmsg)); if (error) break; dgrams++; if (mmsg.msg_hdr.msg_flags & MSG_OOB) break; if (timeout != NULL) { getnanotime(&now); timespecsub(&now, &ts, &now); if (now.tv_sec > 0) break; } } if (iov != aiov) free(iov, M_IOV, iovlen * sizeof(struct iovec)); *retval = dgrams; /* * If we succeeded at least once, return 0, hopefully so->so_error * will catch it next time. */ if (error && dgrams > 0) { struct file *fp; struct socket *so; if (getsock(p, s, &fp) == 0) { so = (struct socket *)fp->f_data; so->so_error = error; FRELE(fp, p); } error = 0; } return (error); } int recvit(struct proc *p, int s, struct msghdr *mp, caddr_t namelenp, register_t *retsize) { struct file *fp; struct uio auio; struct iovec *iov; int i; size_t len; int error; struct mbuf *from = NULL, *control = NULL; #ifdef KTRACE struct iovec *ktriov = NULL; int iovlen = 0, kmsgflags; #endif if ((error = getsock(p, s, &fp)) != 0) return (error); auio.uio_iov = mp->msg_iov; auio.uio_iovcnt = mp->msg_iovlen; auio.uio_segflg = UIO_USERSPACE; auio.uio_rw = UIO_READ; auio.uio_procp = p; auio.uio_offset = 0; /* XXX */ auio.uio_resid = 0; iov = mp->msg_iov; for (i = 0; i < mp->msg_iovlen; i++, iov++) { /* Don't allow sum > SSIZE_MAX */ if (iov->iov_len > SSIZE_MAX || (auio.uio_resid += iov->iov_len) > SSIZE_MAX) { error = EINVAL; goto out; } } #ifdef KTRACE if (KTRPOINT(p, KTR_GENIO)) { ktriov = mallocarray(auio.uio_iovcnt, sizeof(struct iovec), M_TEMP, M_WAITOK); iovlen = auio.uio_iovcnt * sizeof (struct iovec); memcpy(ktriov, auio.uio_iov, iovlen); } kmsgflags = mp->msg_flags; #endif len = auio.uio_resid; if (fp->f_flag & FNONBLOCK) mp->msg_flags |= MSG_DONTWAIT; error = soreceive(fp->f_data, &from, &auio, NULL, mp->msg_control ? &control : NULL, &mp->msg_flags, mp->msg_control ? mp->msg_controllen : 0); if (error) { if (auio.uio_resid != len && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; } #ifdef KTRACE if (ktriov != NULL) { if (error == 0) ktrgenio(p, s, UIO_READ, ktriov, len - auio.uio_resid); free(ktriov, M_TEMP, iovlen); } #endif if (error) goto out; *retsize = len - auio.uio_resid; if (mp->msg_name) { socklen_t alen; if (from == NULL) alen = 0; else { alen = from->m_len; error = copyout(mtod(from, caddr_t), mp->msg_name, MIN(alen, mp->msg_namelen)); if (error) goto out; #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrsockaddr(p, mtod(from, caddr_t), alen); #endif } mp->msg_namelen = alen; if (namelenp && (error = copyout(&alen, namelenp, sizeof(alen)))) { goto out; } } if (mp->msg_control) { len = mp->msg_controllen; if (len <= 0 || control == NULL) len = 0; else { struct mbuf *m = control; caddr_t cp = mp->msg_control; do { i = m->m_len; if (len < i) { mp->msg_flags |= MSG_CTRUNC; i = len; } error = copyout(mtod(m, caddr_t), cp, i); #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT) && error == 0 && i) { /* msg_flags potentially incorrect */ int rmsgflags = mp->msg_flags; mp->msg_flags = kmsgflags; ktrcmsghdr(p, mtod(m, char *), i); mp->msg_flags = rmsgflags; } #endif if (m->m_next) i = ALIGN(i); cp += i; len -= i; if (error != 0 || len <= 0) break; } while ((m = m->m_next) != NULL); len = cp - (caddr_t)mp->msg_control; } mp->msg_controllen = len; } if (!error) { mtx_enter(&fp->f_mtx); fp->f_rxfer++; fp->f_rbytes += *retsize; mtx_leave(&fp->f_mtx); } out: FRELE(fp, p); m_freem(from); m_freem(control); return (error); } int sys_shutdown(struct proc *p, void *v, register_t *retval) { struct sys_shutdown_args /* { syscallarg(int) s; syscallarg(int) how; } */ *uap = v; struct file *fp; int error; if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) return (error); error = soshutdown(fp->f_data, SCARG(uap, how)); FRELE(fp, p); return (error); } int sys_setsockopt(struct proc *p, void *v, register_t *retval) { struct sys_setsockopt_args /* { syscallarg(int) s; syscallarg(int) level; syscallarg(int) name; syscallarg(const void *) val; syscallarg(socklen_t) valsize; } */ *uap = v; struct file *fp; struct mbuf *m = NULL; struct socket *so; int error; if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) return (error); error = pledge_sockopt(p, 1, SCARG(uap, level), SCARG(uap, name)); if (error) goto bad; if (SCARG(uap, valsize) > MCLBYTES) { error = EINVAL; goto bad; } if (SCARG(uap, val)) { m = m_get(M_WAIT, MT_SOOPTS); if (SCARG(uap, valsize) > MLEN) { MCLGET(m, M_WAIT); if ((m->m_flags & M_EXT) == 0) { error = ENOBUFS; goto bad; } } error = copyin(SCARG(uap, val), mtod(m, caddr_t), SCARG(uap, valsize)); if (error) { goto bad; } m->m_len = SCARG(uap, valsize); } so = fp->f_data; error = sosetopt(so, SCARG(uap, level), SCARG(uap, name), m); bad: m_freem(m); FRELE(fp, p); return (error); } int sys_getsockopt(struct proc *p, void *v, register_t *retval) { struct sys_getsockopt_args /* { syscallarg(int) s; syscallarg(int) level; syscallarg(int) name; syscallarg(void *) val; syscallarg(socklen_t *) avalsize; } */ *uap = v; struct file *fp; struct mbuf *m = NULL; socklen_t valsize; struct socket *so; int error; if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) return (error); error = pledge_sockopt(p, 0, SCARG(uap, level), SCARG(uap, name)); if (error) goto out; if (SCARG(uap, val)) { error = copyin(SCARG(uap, avalsize), &valsize, sizeof (valsize)); if (error) goto out; } else valsize = 0; m = m_get(M_WAIT, MT_SOOPTS); so = fp->f_data; error = sogetopt(so, SCARG(uap, level), SCARG(uap, name), m); if (error == 0 && SCARG(uap, val) && valsize && m != NULL) { if (valsize > m->m_len) valsize = m->m_len; error = copyout(mtod(m, caddr_t), SCARG(uap, val), valsize); if (error == 0) error = copyout(&valsize, SCARG(uap, avalsize), sizeof (valsize)); } m_free(m); out: FRELE(fp, p); return (error); } /* * Get socket name. */ int sys_getsockname(struct proc *p, void *v, register_t *retval) { struct sys_getsockname_args /* { syscallarg(int) fdes; syscallarg(struct sockaddr *) asa; syscallarg(socklen_t *) alen; } */ *uap = v; struct file *fp; struct socket *so; struct mbuf *m = NULL; socklen_t len; int error; if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0) return (error); error = copyin(SCARG(uap, alen), &len, sizeof (len)); if (error) goto bad; so = fp->f_data; if (so->so_state & SS_YP) { error = ENOTSOCK; goto bad; } error = pledge_socket(p, -1, so->so_state); if (error) goto bad; if (so->so_state & SS_YP) { error = ENOTSOCK; goto bad; } m = m_getclr(M_WAIT, MT_SONAME); solock_shared(so); error = pru_sockaddr(so, m); sounlock_shared(so); if (error) goto bad; error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen)); bad: FRELE(fp, p); m_freem(m); return (error); } /* * Get name of peer for connected socket. */ int sys_getpeername(struct proc *p, void *v, register_t *retval) { struct sys_getpeername_args /* { syscallarg(int) fdes; syscallarg(struct sockaddr *) asa; syscallarg(socklen_t *) alen; } */ *uap = v; struct file *fp; struct socket *so; struct mbuf *m = NULL; socklen_t len; int error; if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0) return (error); so = fp->f_data; error = pledge_socket(p, -1, so->so_state); if (error) goto bad; if (so->so_state & SS_YP) { error = ENOTSOCK; goto bad; } if ((so->so_state & SS_ISCONNECTED) == 0) { error = ENOTCONN; goto bad; } error = copyin(SCARG(uap, alen), &len, sizeof (len)); if (error) goto bad; m = m_getclr(M_WAIT, MT_SONAME); solock_shared(so); error = pru_peeraddr(so, m); sounlock_shared(so); if (error) goto bad; error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen)); bad: FRELE(fp, p); m_freem(m); return (error); } int sockargs(struct mbuf **mp, const void *buf, size_t buflen, int type) { struct sockaddr *sa; struct mbuf *m; int error; /* * We can't allow socket names > UCHAR_MAX in length, since that * will overflow sa_len. Also, control data more than MCLBYTES in * length is just too much. * Memory for sa_len and sa_family must exist. */ if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) || (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data))) return (EINVAL); /* Allocate an mbuf to hold the arguments. */ m = m_get(M_WAIT, type); if (buflen > MLEN) { MCLGET(m, M_WAITOK); if ((m->m_flags & M_EXT) == 0) { m_free(m); return ENOBUFS; } } m->m_len = buflen; error = copyin(buf, mtod(m, caddr_t), buflen); if (error) { (void) m_free(m); return (error); } *mp = m; if (type == MT_SONAME) { sa = mtod(m, struct sockaddr *); sa->sa_len = buflen; } return (0); } int getsock(struct proc *p, int fdes, struct file **fpp) { struct file *fp; fp = fd_getfile(p->p_fd, fdes); if (fp == NULL) return (EBADF); if (fp->f_type != DTYPE_SOCKET) { FRELE(fp, p); return (ENOTSOCK); } *fpp = fp; return (0); } int sys_setrtable(struct proc *p, void *v, register_t *retval) { struct sys_setrtable_args /* { syscallarg(int) rtableid; } */ *uap = v; u_int ps_rtableid = p->p_p->ps_rtableid; int rtableid, error; rtableid = SCARG(uap, rtableid); if (ps_rtableid == rtableid) return (0); if (ps_rtableid != 0 && (error = suser(p)) != 0) return (error); if (rtableid < 0 || !rtable_exists((u_int)rtableid)) return (EINVAL); p->p_p->ps_rtableid = (u_int)rtableid; return (0); } int sys_getrtable(struct proc *p, void *v, register_t *retval) { *retval = (int)p->p_p->ps_rtableid; return (0); } int copyaddrout(struct proc *p, struct mbuf *name, struct sockaddr *sa, socklen_t buflen, socklen_t *outlen) { int error; socklen_t namelen = name->m_len; /* SHOULD COPY OUT A CHAIN HERE */ error = copyout(mtod(name, caddr_t), sa, MIN(buflen, namelen)); if (error == 0) { #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrsockaddr(p, mtod(name, caddr_t), namelen); #endif error = copyout(&namelen, outlen, sizeof(*outlen)); } return (error); } #ifndef SMALL_KERNEL int ypsockargs(struct mbuf **mp, const void *buf, size_t buflen, int type) { struct sockaddr *sa; struct mbuf *m; /* * We can't allow socket names > UCHAR_MAX in length, since that * will overflow sa_len. Also, control data more than MCLBYTES in * length is just too much. * Memory for sa_len and sa_family must exist. */ if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) || (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data))) return (EINVAL); /* Allocate an mbuf to hold the arguments. */ m = m_get(M_WAIT, type); if (buflen > MLEN) { MCLGET(m, M_WAITOK); if ((m->m_flags & M_EXT) == 0) { m_free(m); return ENOBUFS; } } m->m_len = buflen; bcopy(buf, mtod(m, caddr_t), buflen); *mp = m; if (type == MT_SONAME) { sa = mtod(m, struct sockaddr *); sa->sa_len = buflen; } return (0); } #endif /* SMALL_KERNEL */ int sys_ypconnect(struct proc *p, void *v, register_t *retval) { #ifdef SMALL_KERNEL return EAFNOSUPPORT; #else struct sys_ypconnect_args /* { syscallarg(int) type; } */ *uap = v; struct nameidata nid; struct vattr va; struct uio uio; struct iovec iov; struct filedesc *fdp = p->p_fd; struct socket *so; struct file *fp; struct flock fl; char *name; struct mbuf *nam = NULL; int error, fd = -1; struct ypbinding { u_short ypbind_port; int status; in_addr_t in; u_short ypserv_udp_port; u_short garbage; u_short ypserv_tcp_port; } __packed data; struct sockaddr_in ypsin; if (!domainname[0] || strchr(domainname, '/')) return EAFNOSUPPORT; switch (SCARG(uap, type)) { case SOCK_STREAM: case SOCK_DGRAM: break; default: return EAFNOSUPPORT; } if (p->p_p->ps_flags & PS_CHROOT) return EACCES; KERNEL_LOCK(); name = pool_get(&namei_pool, PR_WAITOK); snprintf(name, MAXPATHLEN, "/var/yp/binding/%s.2", domainname); NDINIT(&nid, 0, NOFOLLOW|LOCKLEAF|KERNELPATH, UIO_SYSSPACE, name, p); nid.ni_pledge = PLEDGE_RPATH; error = namei(&nid); pool_put(&namei_pool, name); if (error) goto out; error = VOP_GETATTR(nid.ni_vp, &va, p->p_ucred, p); if (error) goto verror; if (nid.ni_vp->v_type != VREG || va.va_size != sizeof data) { error = EFTYPE; goto verror; } /* * Check that a lock is held on the file (hopefully by ypbind), * otherwise the file might be old */ fl.l_start = 0; fl.l_len = 0; fl.l_pid = 0; fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; error = VOP_ADVLOCK(nid.ni_vp, fdp, F_GETLK, &fl, F_POSIX); if (error) goto verror; if (fl.l_type == F_UNLCK) { error = EOWNERDEAD; goto verror; } iov.iov_base = &data; iov.iov_len = sizeof data; uio.uio_iov = &iov; uio.uio_iovcnt = 1; uio.uio_offset = 0; uio.uio_resid = iov.iov_len; uio.uio_segflg = UIO_SYSSPACE; uio.uio_rw = UIO_READ; uio.uio_procp = p; error = VOP_READ(nid.ni_vp, &uio, 0, p->p_ucred); if (error) { verror: if (nid.ni_vp) vput(nid.ni_vp); out: KERNEL_UNLOCK(); return (error); } vput(nid.ni_vp); KERNEL_UNLOCK(); bzero(&ypsin, sizeof ypsin); ypsin.sin_len = sizeof ypsin; ypsin.sin_family = AF_INET; if (SCARG(uap, type) == SOCK_STREAM) ypsin.sin_port = data.ypserv_tcp_port; else ypsin.sin_port = data.ypserv_udp_port; if (ntohs(ypsin.sin_port) >= IPPORT_RESERVED || ntohs(ypsin.sin_port) == 20) return EPERM; memcpy(&ypsin.sin_addr.s_addr, &data.in, sizeof ypsin.sin_addr.s_addr); error = socreate(AF_INET, &so, SCARG(uap, type), 0); if (error) return (error); error = ypsockargs(&nam, &ypsin, sizeof ypsin, MT_SONAME); if (error) { soclose(so, MSG_DONTWAIT); return (error); } #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrsockaddr(p, mtod(nam, caddr_t), sizeof(struct sockaddr_in)); #endif solock(so); /* Secure YP maps require reserved ports */ if (suser(p) == 0) sotoinpcb(so)->inp_flags |= INP_LOWPORT; error = soconnect(so, nam); while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { error = sosleep_nsec(so, &so->so_timeo, PSOCK | PCATCH, "ypcon", INFSLP); if (error) break; } m_freem(nam); so->so_state |= SS_YP; /* impose some restrictions */ sounlock(so); if (error) { soclose(so, MSG_DONTWAIT); return (error); } fdplock(fdp); error = falloc(p, &fp, &fd); if (error) { fdpunlock(fdp); soclose(so, MSG_DONTWAIT); return (error); } fp->f_flag = FREAD | FWRITE | FNONBLOCK; fp->f_type = DTYPE_SOCKET; fp->f_ops = &socketops; fp->f_data = so; fdinsert(fdp, fd, UF_EXCLOSE, fp); fdpunlock(fdp); FRELE(fp, p); *retval = fd; return (error); #endif /* SMALL_KERNEL */ }
2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 /* $OpenBSD: if_gre.c,v 1.178 2023/12/23 10:52:54 bluhm Exp $ */ /* $NetBSD: if_gre.c,v 1.9 1999/10/25 19:18:11 drochner Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Heiko W.Rupp <hwr@pilhuhn.de> * * IPv6-over-GRE contributed by Gert Doering <gert@greenie.muc.de> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Encapsulate L3 protocols into IP, per RFC 1701 and 1702. * See gre(4) for more details. * Also supported: IP in IP encapsulation (proto 55) per RFC 2004. */ #include "bpfilter.h" #include "pf.h" #include <sys/param.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/sockio.h> #include <sys/kernel.h> #include <sys/systm.h> #include <sys/errno.h> #include <sys/timeout.h> #include <sys/queue.h> #include <sys/tree.h> #include <sys/pool.h> #include <sys/rwlock.h> #include <crypto/siphash.h> #include <net/if.h> #include <net/if_var.h> #include <net/if_types.h> #include <net/if_media.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/in_var.h> #include <netinet/if_ether.h> #include <netinet/ip.h> #include <netinet/ip_var.h> #include <netinet/ip_ecn.h> #ifdef INET6 #include <netinet/ip6.h> #include <netinet6/ip6_var.h> #include <netinet6/in6_var.h> #endif #ifdef PIPEX #include <net/pipex.h> #endif #ifdef MPLS #include <netmpls/mpls.h> #endif /* MPLS */ #if NBPFILTER > 0 #include <net/bpf.h> #endif #if NPF > 0 #include <net/pfvar.h> #endif #include <net/if_gre.h> #include <netinet/ip_gre.h> #include <sys/sysctl.h> /* for nvgre bridge shizz */ #include <net/if_bridge.h> #include <net/if_etherbridge.h> /* * packet formats */ struct gre_header { uint16_t gre_flags; #define GRE_CP 0x8000 /* Checksum Present */ #define GRE_KP 0x2000 /* Key Present */ #define GRE_SP 0x1000 /* Sequence Present */ #define GRE_VERS_MASK 0x0007 #define GRE_VERS_0 0x0000 #define GRE_VERS_1 0x0001 uint16_t gre_proto; } __packed __aligned(4); struct gre_h_cksum { uint16_t gre_cksum; uint16_t gre_reserved1; } __packed __aligned(4); struct gre_h_key { uint32_t gre_key; } __packed __aligned(4); #define GRE_EOIP 0x6400 struct gre_h_key_eoip { uint16_t eoip_len; /* network order */ uint16_t eoip_tunnel_id; /* little endian */ } __packed __aligned(4); #define NVGRE_VSID_RES_MIN 0x000000 /* reserved for future use */ #define NVGRE_VSID_RES_MAX 0x000fff #define NVGRE_VSID_NVE2NVE 0xffffff /* vendor specific NVE-to-NVE comms */ struct gre_h_seq { uint32_t gre_seq; } __packed __aligned(4); struct gre_h_wccp { uint8_t wccp_flags; uint8_t service_id; uint8_t alt_bucket; uint8_t pri_bucket; } __packed __aligned(4); #define GRE_WCCP 0x883e #define GRE_HDRLEN (sizeof(struct ip) + sizeof(struct gre_header)) /* * GRE tunnel metadata */ #define GRE_KA_NONE 0 #define GRE_KA_DOWN 1 #define GRE_KA_HOLD 2 #define GRE_KA_UP 3 union gre_addr { struct in_addr in4; struct in6_addr in6; }; static inline int gre_ip_cmp(int, const union gre_addr *, const union gre_addr *); #define GRE_KEY_MIN 0x00000000U #define GRE_KEY_MAX 0xffffffffU #define GRE_KEY_SHIFT 0 #define GRE_KEY_ENTROPY_MIN 0x00000000U #define GRE_KEY_ENTROPY_MAX 0x00ffffffU #define GRE_KEY_ENTROPY_SHIFT 8 struct gre_tunnel { uint32_t t_key_mask; #define GRE_KEY_NONE htonl(0x00000000U) #define GRE_KEY_ENTROPY htonl(0xffffff00U) #define GRE_KEY_MASK htonl(0xffffffffU) uint32_t t_key; u_int t_rtableid; union gre_addr t_src; #define t_src4 t_src.in4 #define t_src6 t_src.in6 union gre_addr t_dst; #define t_dst4 t_dst.in4 #define t_dst6 t_dst.in6 int t_ttl; int t_txhprio; int t_rxhprio; int t_ecn; uint16_t t_df; sa_family_t t_af; }; static int gre_cmp_src(const struct gre_tunnel *, const struct gre_tunnel *); static int gre_cmp(const struct gre_tunnel *, const struct gre_tunnel *); static int gre_set_tunnel(struct gre_tunnel *, struct if_laddrreq *, int); static int gre_get_tunnel(struct gre_tunnel *, struct if_laddrreq *); static int gre_del_tunnel(struct gre_tunnel *); static int gre_set_vnetid(struct gre_tunnel *, struct ifreq *); static int gre_get_vnetid(struct gre_tunnel *, struct ifreq *); static int gre_del_vnetid(struct gre_tunnel *); static int gre_set_vnetflowid(struct gre_tunnel *, struct ifreq *); static int gre_get_vnetflowid(struct gre_tunnel *, struct ifreq *); static struct mbuf * gre_encap_dst(const struct gre_tunnel *, const union gre_addr *, struct mbuf *, uint16_t, uint8_t, uint8_t); #define gre_encap(_t, _m, _p, _ttl, _tos) \ gre_encap_dst((_t), &(_t)->t_dst, (_m), (_p), (_ttl), (_tos)) static struct mbuf * gre_encap_dst_ip(const struct gre_tunnel *, const union gre_addr *, struct mbuf *, uint8_t, uint8_t); #define gre_encap_ip(_t, _m, _ttl, _tos) \ gre_encap_dst_ip((_t), &(_t)->t_dst, (_m), (_ttl), (_tos)) static int gre_ip_output(const struct gre_tunnel *, struct mbuf *); static int gre_tunnel_ioctl(struct ifnet *, struct gre_tunnel *, u_long, void *); static uint8_t gre_l2_tos(const struct gre_tunnel *, const struct mbuf *); static uint8_t gre_l3_tos(const struct gre_tunnel *, const struct mbuf *, uint8_t); /* * layer 3 GRE tunnels */ struct gre_softc { struct gre_tunnel sc_tunnel; /* must be first */ TAILQ_ENTRY(gre_softc) sc_entry; struct ifnet sc_if; struct timeout sc_ka_send; struct timeout sc_ka_hold; unsigned int sc_ka_state; unsigned int sc_ka_timeo; unsigned int sc_ka_count; unsigned int sc_ka_holdmax; unsigned int sc_ka_holdcnt; SIPHASH_KEY sc_ka_key; uint32_t sc_ka_bias; int sc_ka_recvtm; }; TAILQ_HEAD(gre_list, gre_softc); struct gre_keepalive { uint32_t gk_uptime; uint32_t gk_random; uint8_t gk_digest[SIPHASH_DIGEST_LENGTH]; } __packed __aligned(4); static int gre_clone_create(struct if_clone *, int); static int gre_clone_destroy(struct ifnet *); struct if_clone gre_cloner = IF_CLONE_INITIALIZER("gre", gre_clone_create, gre_clone_destroy); /* protected by NET_LOCK */ struct gre_list gre_list = TAILQ_HEAD_INITIALIZER(gre_list); static int gre_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); static void gre_start(struct ifnet *); static int gre_ioctl(struct ifnet *, u_long, caddr_t); static int gre_up(struct gre_softc *); static int gre_down(struct gre_softc *); static void gre_link_state(struct ifnet *, unsigned int); static int gre_input_key(struct mbuf **, int *, int, int, uint8_t, struct gre_tunnel *); static struct mbuf * gre_ipv4_patch(const struct gre_tunnel *, struct mbuf *, uint8_t *, uint8_t); #ifdef INET6 static struct mbuf * gre_ipv6_patch(const struct gre_tunnel *, struct mbuf *, uint8_t *, uint8_t); #endif #ifdef MPLS static struct mbuf * gre_mpls_patch(const struct gre_tunnel *, struct mbuf *, uint8_t *, uint8_t); #endif static void gre_keepalive_send(void *); static void gre_keepalive_recv(struct ifnet *ifp, struct mbuf *); static void gre_keepalive_hold(void *); static struct mbuf * gre_l3_encap_dst(const struct gre_tunnel *, const void *, struct mbuf *m, sa_family_t); #define gre_l3_encap(_t, _m, _af) \ gre_l3_encap_dst((_t), &(_t)->t_dst, (_m), (_af)) struct mgre_softc { struct gre_tunnel sc_tunnel; /* must be first */ RBT_ENTRY(mgre_softc) sc_entry; struct ifnet sc_if; }; RBT_HEAD(mgre_tree, mgre_softc); static inline int mgre_cmp(const struct mgre_softc *, const struct mgre_softc *); RBT_PROTOTYPE(mgre_tree, mgre_softc, sc_entry, mgre_cmp); static int mgre_clone_create(struct if_clone *, int); static int mgre_clone_destroy(struct ifnet *); struct if_clone mgre_cloner = IF_CLONE_INITIALIZER("mgre", mgre_clone_create, mgre_clone_destroy); static void mgre_rtrequest(struct ifnet *, int, struct rtentry *); static int mgre_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); static void mgre_start(struct ifnet *); static int mgre_ioctl(struct ifnet *, u_long, caddr_t); static int mgre_set_tunnel(struct mgre_softc *, struct if_laddrreq *); static int mgre_get_tunnel(struct mgre_softc *, struct if_laddrreq *); static int mgre_up(struct mgre_softc *); static int mgre_down(struct mgre_softc *); /* protected by NET_LOCK */ struct mgre_tree mgre_tree = RBT_INITIALIZER(); /* * Ethernet GRE tunnels */ static struct mbuf * gre_ether_align(struct mbuf *, int); struct egre_softc { struct gre_tunnel sc_tunnel; /* must be first */ RBT_ENTRY(egre_softc) sc_entry; struct arpcom sc_ac; struct ifmedia sc_media; }; RBT_HEAD(egre_tree, egre_softc); static inline int egre_cmp(const struct egre_softc *, const struct egre_softc *); RBT_PROTOTYPE(egre_tree, egre_softc, sc_entry, egre_cmp); static int egre_clone_create(struct if_clone *, int); static int egre_clone_destroy(struct ifnet *); static void egre_start(struct ifnet *); static int egre_ioctl(struct ifnet *, u_long, caddr_t); static int egre_media_change(struct ifnet *); static void egre_media_status(struct ifnet *, struct ifmediareq *); static int egre_up(struct egre_softc *); static int egre_down(struct egre_softc *); static int egre_input(const struct gre_tunnel *, struct mbuf *, int, uint8_t); struct if_clone egre_cloner = IF_CLONE_INITIALIZER("egre", egre_clone_create, egre_clone_destroy); /* protected by NET_LOCK */ struct egre_tree egre_tree = RBT_INITIALIZER(); /* * Network Virtualisation Using Generic Routing Encapsulation (NVGRE) */ struct nvgre_softc { struct gre_tunnel sc_tunnel; /* must be first */ unsigned int sc_ifp0; RBT_ENTRY(nvgre_softc) sc_uentry; RBT_ENTRY(nvgre_softc) sc_mentry; struct arpcom sc_ac; struct ifmedia sc_media; struct mbuf_queue sc_send_list; struct task sc_send_task; void *sc_inm; struct task sc_ltask; struct task sc_dtask; struct etherbridge sc_eb; }; RBT_HEAD(nvgre_ucast_tree, nvgre_softc); RBT_HEAD(nvgre_mcast_tree, nvgre_softc); static inline int nvgre_cmp_ucast(const struct nvgre_softc *, const struct nvgre_softc *); static int nvgre_cmp_mcast(const struct gre_tunnel *, const union gre_addr *, unsigned int, const struct gre_tunnel *, const union gre_addr *, unsigned int); static inline int nvgre_cmp_mcast_sc(const struct nvgre_softc *, const struct nvgre_softc *); RBT_PROTOTYPE(nvgre_ucast_tree, nvgre_softc, sc_uentry, nvgre_cmp_ucast); RBT_PROTOTYPE(nvgre_mcast_tree, nvgre_softc, sc_mentry, nvgre_cmp_mcast_sc); static int nvgre_clone_create(struct if_clone *, int); static int nvgre_clone_destroy(struct ifnet *); static void nvgre_start(struct ifnet *); static int nvgre_ioctl(struct ifnet *, u_long, caddr_t); static int nvgre_up(struct nvgre_softc *); static int nvgre_down(struct nvgre_softc *); static int nvgre_set_parent(struct nvgre_softc *, const char *); static void nvgre_link_change(void *); static void nvgre_detach(void *); static int nvgre_input(const struct gre_tunnel *, struct mbuf *, int, uint8_t); static void nvgre_send(void *); static int nvgre_add_addr(struct nvgre_softc *, const struct ifbareq *); static int nvgre_del_addr(struct nvgre_softc *, const struct ifbareq *); static int nvgre_eb_port_eq(void *, void *, void *); static void *nvgre_eb_port_take(void *, void *); static void nvgre_eb_port_rele(void *, void *); static size_t nvgre_eb_port_ifname(void *, char *, size_t, void *); static void nvgre_eb_port_sa(void *, struct sockaddr_storage *, void *); static const struct etherbridge_ops nvgre_etherbridge_ops = { nvgre_eb_port_eq, nvgre_eb_port_take, nvgre_eb_port_rele, nvgre_eb_port_ifname, nvgre_eb_port_sa, }; struct if_clone nvgre_cloner = IF_CLONE_INITIALIZER("nvgre", nvgre_clone_create, nvgre_clone_destroy); struct pool nvgre_endpoint_pool; /* protected by NET_LOCK */ struct nvgre_ucast_tree nvgre_ucast_tree = RBT_INITIALIZER(); struct nvgre_mcast_tree nvgre_mcast_tree = RBT_INITIALIZER(); /* * MikroTik Ethernet over IP protocol (eoip) */ struct eoip_softc { struct gre_tunnel sc_tunnel; /* must be first */ uint16_t sc_tunnel_id; RBT_ENTRY(eoip_softc) sc_entry; struct arpcom sc_ac; struct ifmedia sc_media; struct timeout sc_ka_send; struct timeout sc_ka_hold; unsigned int sc_ka_state; unsigned int sc_ka_timeo; unsigned int sc_ka_count; unsigned int sc_ka_holdmax; unsigned int sc_ka_holdcnt; }; RBT_HEAD(eoip_tree, eoip_softc); static inline int eoip_cmp(const struct eoip_softc *, const struct eoip_softc *); RBT_PROTOTYPE(eoip_tree, eoip_softc, sc_entry, eoip_cmp); static int eoip_clone_create(struct if_clone *, int); static int eoip_clone_destroy(struct ifnet *); static void eoip_start(struct ifnet *); static int eoip_ioctl(struct ifnet *, u_long, caddr_t); static void eoip_keepalive_send(void *); static void eoip_keepalive_recv(struct eoip_softc *); static void eoip_keepalive_hold(void *); static int eoip_up(struct eoip_softc *); static int eoip_down(struct eoip_softc *); static struct mbuf * eoip_encap(struct eoip_softc *, struct mbuf *, uint8_t); static struct mbuf * eoip_input(struct gre_tunnel *, struct mbuf *, const struct gre_header *, uint8_t, int); struct if_clone eoip_cloner = IF_CLONE_INITIALIZER("eoip", eoip_clone_create, eoip_clone_destroy); /* protected by NET_LOCK */ struct eoip_tree eoip_tree = RBT_INITIALIZER(); /* * It is not easy to calculate the right value for a GRE MTU. * We leave this task to the admin and use the same default that * other vendors use. */ #define GREMTU 1476 /* * We can control the acceptance of GRE and MobileIP packets by * altering the sysctl net.inet.gre.allow values * respectively. Zero means drop them, all else is acceptance. We can also * control acceptance of WCCPv1-style GRE packets through the * net.inet.gre.wccp value, but be aware it depends upon normal GRE being * allowed as well. * */ int gre_allow = 0; int gre_wccp = 0; void greattach(int n) { if_clone_attach(&gre_cloner); if_clone_attach(&mgre_cloner); if_clone_attach(&egre_cloner); if_clone_attach(&nvgre_cloner); if_clone_attach(&eoip_cloner); } static int gre_clone_create(struct if_clone *ifc, int unit) { struct gre_softc *sc; struct ifnet *ifp; sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); snprintf(sc->sc_if.if_xname, sizeof sc->sc_if.if_xname, "%s%d", ifc->ifc_name, unit); ifp = &sc->sc_if; ifp->if_softc = sc; ifp->if_type = IFT_TUNNEL; ifp->if_hdrlen = GRE_HDRLEN; ifp->if_mtu = GREMTU; ifp->if_flags = IFF_POINTOPOINT|IFF_MULTICAST; ifp->if_xflags = IFXF_CLONED; ifp->if_bpf_mtap = p2p_bpf_mtap; ifp->if_input = p2p_input; ifp->if_output = gre_output; ifp->if_start = gre_start; ifp->if_ioctl = gre_ioctl; ifp->if_rtrequest = p2p_rtrequest; sc->sc_tunnel.t_ttl = ip_defttl; sc->sc_tunnel.t_txhprio = IF_HDRPRIO_PAYLOAD; sc->sc_tunnel.t_rxhprio = IF_HDRPRIO_PACKET; sc->sc_tunnel.t_df = htons(0); sc->sc_tunnel.t_ecn = ECN_ALLOWED; timeout_set(&sc->sc_ka_send, gre_keepalive_send, sc); timeout_set_proc(&sc->sc_ka_hold, gre_keepalive_hold, sc); sc->sc_ka_state = GRE_KA_NONE; if_counters_alloc(ifp); if_attach(ifp); if_alloc_sadl(ifp); #if NBPFILTER > 0 bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(uint32_t)); #endif ifp->if_llprio = IFQ_TOS2PRIO(IPTOS_PREC_INTERNETCONTROL); NET_LOCK(); TAILQ_INSERT_TAIL(&gre_list, sc, sc_entry); NET_UNLOCK(); return (0); } static int gre_clone_destroy(struct ifnet *ifp) { struct gre_softc *sc = ifp->if_softc; NET_LOCK(); if (ISSET(ifp->if_flags, IFF_RUNNING)) gre_down(sc); TAILQ_REMOVE(&gre_list, sc, sc_entry); NET_UNLOCK(); if_detach(ifp); free(sc, M_DEVBUF, sizeof(*sc)); return (0); } static int mgre_clone_create(struct if_clone *ifc, int unit) { struct mgre_softc *sc; struct ifnet *ifp; sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); ifp = &sc->sc_if; snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d", ifc->ifc_name, unit); ifp->if_softc = sc; ifp->if_type = IFT_L3IPVLAN; ifp->if_hdrlen = GRE_HDRLEN; ifp->if_mtu = GREMTU; ifp->if_flags = IFF_MULTICAST|IFF_SIMPLEX; ifp->if_xflags = IFXF_CLONED; ifp->if_bpf_mtap = p2p_bpf_mtap; ifp->if_input = p2p_input; ifp->if_rtrequest = mgre_rtrequest; ifp->if_output = mgre_output; ifp->if_start = mgre_start; ifp->if_ioctl = mgre_ioctl; sc->sc_tunnel.t_ttl = ip_defttl; sc->sc_tunnel.t_txhprio = IF_HDRPRIO_PAYLOAD; sc->sc_tunnel.t_rxhprio = IF_HDRPRIO_PACKET; sc->sc_tunnel.t_df = htons(0); sc->sc_tunnel.t_ecn = ECN_ALLOWED; if_counters_alloc(ifp); if_attach(ifp); if_alloc_sadl(ifp); #if NBPFILTER > 0 bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(uint32_t)); #endif return (0); } static int mgre_clone_destroy(struct ifnet *ifp) { struct mgre_softc *sc = ifp->if_softc; NET_LOCK(); if (ISSET(ifp->if_flags, IFF_RUNNING)) mgre_down(sc); NET_UNLOCK(); if_detach(ifp); free(sc, M_DEVBUF, sizeof(*sc)); return (0); } static int egre_clone_create(struct if_clone *ifc, int unit) { struct egre_softc *sc; struct ifnet *ifp; sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); ifp = &sc->sc_ac.ac_if; snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d", ifc->ifc_name, unit); ifp->if_softc = sc; ifp->if_hardmtu = ETHER_MAX_HARDMTU_LEN; ifp->if_ioctl = egre_ioctl; ifp->if_start = egre_start; ifp->if_xflags = IFXF_CLONED; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ether_fakeaddr(ifp); sc->sc_tunnel.t_ttl = ip_defttl; sc->sc_tunnel.t_txhprio = 0; sc->sc_tunnel.t_rxhprio = IF_HDRPRIO_PACKET; sc->sc_tunnel.t_df = htons(0); ifmedia_init(&sc->sc_media, 0, egre_media_change, egre_media_status); ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL); ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO); if_counters_alloc(ifp); if_attach(ifp); ether_ifattach(ifp); return (0); } static int egre_clone_destroy(struct ifnet *ifp) { struct egre_softc *sc = ifp->if_softc; NET_LOCK(); if (ISSET(ifp->if_flags, IFF_RUNNING)) egre_down(sc); NET_UNLOCK(); ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY); ether_ifdetach(ifp); if_detach(ifp); free(sc, M_DEVBUF, sizeof(*sc)); return (0); } static int nvgre_clone_create(struct if_clone *ifc, int unit) { struct nvgre_softc *sc; struct ifnet *ifp; struct gre_tunnel *tunnel; int error; if (nvgre_endpoint_pool.pr_size == 0) { pool_init(&nvgre_endpoint_pool, sizeof(union gre_addr), 0, IPL_SOFTNET, 0, "nvgreep", NULL); } sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); ifp = &sc->sc_ac.ac_if; snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d", ifc->ifc_name, unit); error = etherbridge_init(&sc->sc_eb, ifp->if_xname, &nvgre_etherbridge_ops, sc); if (error != 0) { free(sc, M_DEVBUF, sizeof(*sc)); return (error); } ifp->if_softc = sc; ifp->if_hardmtu = ETHER_MAX_HARDMTU_LEN; ifp->if_ioctl = nvgre_ioctl; ifp->if_start = nvgre_start; ifp->if_xflags = IFXF_CLONED; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ether_fakeaddr(ifp); tunnel = &sc->sc_tunnel; tunnel->t_ttl = IP_DEFAULT_MULTICAST_TTL; tunnel->t_txhprio = 0; sc->sc_tunnel.t_rxhprio = IF_HDRPRIO_PACKET; tunnel->t_df = htons(IP_DF); tunnel->t_key_mask = GRE_KEY_ENTROPY; tunnel->t_key = htonl((NVGRE_VSID_RES_MAX + 1) << GRE_KEY_ENTROPY_SHIFT); mq_init(&sc->sc_send_list, IFQ_MAXLEN * 2, IPL_SOFTNET); task_set(&sc->sc_send_task, nvgre_send, sc); task_set(&sc->sc_ltask, nvgre_link_change, sc); task_set(&sc->sc_dtask, nvgre_detach, sc); ifmedia_init(&sc->sc_media, 0, egre_media_change, egre_media_status); ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL); ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO); if_counters_alloc(ifp); if_attach(ifp); ether_ifattach(ifp); return (0); } static int nvgre_clone_destroy(struct ifnet *ifp) { struct nvgre_softc *sc = ifp->if_softc; NET_LOCK(); if (ISSET(ifp->if_flags, IFF_RUNNING)) nvgre_down(sc); NET_UNLOCK(); etherbridge_destroy(&sc->sc_eb); ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY); ether_ifdetach(ifp); if_detach(ifp); free(sc, M_DEVBUF, sizeof(*sc)); return (0); } static int eoip_clone_create(struct if_clone *ifc, int unit) { struct eoip_softc *sc; struct ifnet *ifp; sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); ifp = &sc->sc_ac.ac_if; snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d", ifc->ifc_name, unit); ifp->if_softc = sc; ifp->if_hardmtu = ETHER_MAX_HARDMTU_LEN; ifp->if_ioctl = eoip_ioctl; ifp->if_start = eoip_start; ifp->if_xflags = IFXF_CLONED; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ether_fakeaddr(ifp); sc->sc_tunnel.t_ttl = ip_defttl; sc->sc_tunnel.t_txhprio = 0; sc->sc_tunnel.t_rxhprio = IF_HDRPRIO_PACKET; sc->sc_tunnel.t_df = htons(0); sc->sc_ka_timeo = 10; sc->sc_ka_count = 10; timeout_set(&sc->sc_ka_send, eoip_keepalive_send, sc); timeout_set_proc(&sc->sc_ka_hold, eoip_keepalive_hold, sc); sc->sc_ka_state = GRE_KA_DOWN; ifmedia_init(&sc->sc_media, 0, egre_media_change, egre_media_status); ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL); ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO); if_counters_alloc(ifp); if_attach(ifp); ether_ifattach(ifp); return (0); } static int eoip_clone_destroy(struct ifnet *ifp) { struct eoip_softc *sc = ifp->if_softc; NET_LOCK(); if (ISSET(ifp->if_flags, IFF_RUNNING)) eoip_down(sc); NET_UNLOCK(); ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY); ether_ifdetach(ifp); if_detach(ifp); free(sc, M_DEVBUF, sizeof(*sc)); return (0); } int gre_input(struct mbuf **mp, int *offp, int type, int af) { struct mbuf *m = *mp; struct gre_tunnel key; struct ip *ip; ip = mtod(m, struct ip *); /* XXX check if ip_src is sane for nvgre? */ key.t_af = AF_INET; key.t_src4 = ip->ip_dst; key.t_dst4 = ip->ip_src; if (gre_input_key(mp, offp, type, af, ip->ip_tos, &key) == -1) return (rip_input(mp, offp, type, af)); return (IPPROTO_DONE); } #ifdef INET6 int gre_input6(struct mbuf **mp, int *offp, int type, int af) { struct mbuf *m = *mp; struct gre_tunnel key; struct ip6_hdr *ip6; uint32_t flow; ip6 = mtod(m, struct ip6_hdr *); /* XXX check if ip6_src is sane for nvgre? */ key.t_af = AF_INET6; key.t_src6 = ip6->ip6_dst; key.t_dst6 = ip6->ip6_src; flow = bemtoh32(&ip6->ip6_flow); if (gre_input_key(mp, offp, type, af, flow >> 20, &key) == -1) return (rip6_input(mp, offp, type, af)); return (IPPROTO_DONE); } #endif /* INET6 */ static inline struct ifnet * gre_find(const struct gre_tunnel *key) { struct gre_softc *sc; TAILQ_FOREACH(sc, &gre_list, sc_entry) { if (gre_cmp(key, &sc->sc_tunnel) != 0) continue; if (!ISSET(sc->sc_if.if_flags, IFF_RUNNING)) continue; return (&sc->sc_if); } return (NULL); } static inline struct ifnet * mgre_find(const struct gre_tunnel *key) { struct mgre_softc *sc; NET_ASSERT_LOCKED(); sc = RBT_FIND(mgre_tree, &mgre_tree, (const struct mgre_softc *)key); if (sc != NULL) return (&sc->sc_if); return (NULL); } static struct mbuf * gre_input_1(struct gre_tunnel *key, struct mbuf *m, const struct gre_header *gh, uint8_t otos, int iphlen) { switch (gh->gre_proto) { case htons(ETHERTYPE_PPP): #ifdef PIPEX if (pipex_enable) { struct pipex_session *session; session = pipex_pptp_lookup_session(m); if (session != NULL) { struct mbuf *m0; m0 = pipex_pptp_input(m, session); pipex_rele_session(session); if (m0 == NULL) return (NULL); } } #endif break; case htons(GRE_EOIP): return (eoip_input(key, m, gh, otos, iphlen)); break; } return (m); } static int gre_input_key(struct mbuf **mp, int *offp, int type, int af, uint8_t otos, struct gre_tunnel *key) { struct mbuf *m = *mp; int iphlen = *offp, hlen, rxprio; struct ifnet *ifp; const struct gre_tunnel *tunnel; caddr_t buf; struct gre_header *gh; struct gre_h_key *gkh; struct mbuf *(*patch)(const struct gre_tunnel *, struct mbuf *, uint8_t *, uint8_t); int mcast = 0; uint8_t itos; if (!gre_allow) goto decline; key->t_rtableid = m->m_pkthdr.ph_rtableid; hlen = iphlen + sizeof(*gh); if (m->m_pkthdr.len < hlen) goto decline; m = m_pullup(m, hlen); if (m == NULL) return (IPPROTO_DONE); buf = mtod(m, caddr_t); gh = (struct gre_header *)(buf + iphlen); /* check the version */ switch (gh->gre_flags & htons(GRE_VERS_MASK)) { case htons(GRE_VERS_0): break; case htons(GRE_VERS_1): m = gre_input_1(key, m, gh, otos, iphlen); if (m == NULL) return (IPPROTO_DONE); /* FALLTHROUGH */ default: goto decline; } /* the only optional bit in the header is K flag */ if ((gh->gre_flags & htons(~(GRE_KP|GRE_VERS_MASK))) != htons(0)) goto decline; if (gh->gre_flags & htons(GRE_KP)) { hlen += sizeof(*gkh); if (m->m_pkthdr.len < hlen) goto decline; m = m_pullup(m, hlen); if (m == NULL) return (IPPROTO_DONE); buf = mtod(m, caddr_t); gh = (struct gre_header *)(buf + iphlen); gkh = (struct gre_h_key *)(gh + 1); key->t_key_mask = GRE_KEY_MASK; key->t_key = gkh->gre_key; } else key->t_key_mask = GRE_KEY_NONE; if (gh->gre_proto == htons(ETHERTYPE_TRANSETHER)) { if (egre_input(key, m, hlen, otos) == -1 && nvgre_input(key, m, hlen, otos) == -1) goto decline; return (IPPROTO_DONE); } ifp = gre_find(key); if (ifp == NULL) { ifp = mgre_find(key); if (ifp == NULL) goto decline; } switch (gh->gre_proto) { case htons(GRE_WCCP): { struct mbuf *n; int off; /* WCCP/GRE: * So far as I can see (and test) it seems that Cisco's WCCP * GRE tunnel is precisely a IP-in-GRE tunnel that differs * only in its protocol number. At least, it works for me. * * The Internet Drafts can be found if you look for * the following: * draft-forster-wrec-wccp-v1-00.txt * draft-wilson-wrec-wccp-v2-01.txt */ if (!gre_wccp && !ISSET(ifp->if_flags, IFF_LINK0)) goto decline; /* * If the first nibble of the payload does not look like * IPv4, assume it is WCCP v2. */ n = m_getptr(m, hlen, &off); if (n == NULL) goto decline; if (n->m_data[off] >> 4 != IPVERSION) hlen += 4; /* four-octet Redirect header */ /* FALLTHROUGH */ } case htons(ETHERTYPE_IP): m->m_pkthdr.ph_family = AF_INET; patch = gre_ipv4_patch; break; #ifdef INET6 case htons(ETHERTYPE_IPV6): m->m_pkthdr.ph_family = AF_INET6; patch = gre_ipv6_patch; break; #endif #ifdef MPLS case htons(ETHERTYPE_MPLS_MCAST): mcast = M_MCAST|M_BCAST; /* fallthrough */ case htons(ETHERTYPE_MPLS): m->m_pkthdr.ph_family = AF_MPLS; patch = gre_mpls_patch; break; #endif case htons(0): if (ifp->if_type != IFT_TUNNEL) { /* keepalives dont make sense for mgre */ goto decline; } m_adj(m, hlen); gre_keepalive_recv(ifp, m); return (IPPROTO_DONE); default: goto decline; } /* it's ours now */ m_adj(m, hlen); tunnel = ifp->if_softc; /* gre and mgre tunnel info is at the front */ m = (*patch)(tunnel, m, &itos, otos); if (m == NULL) return (IPPROTO_DONE); if (tunnel->t_key_mask == GRE_KEY_ENTROPY) { SET(m->m_pkthdr.csum_flags, M_FLOWID); m->m_pkthdr.ph_flowid = bemtoh32(&key->t_key) & ~GRE_KEY_ENTROPY; } rxprio = tunnel->t_rxhprio; switch (rxprio) { case IF_HDRPRIO_PACKET: /* nop */ break; case IF_HDRPRIO_OUTER: m->m_pkthdr.pf.prio = IFQ_TOS2PRIO(otos); break; case IF_HDRPRIO_PAYLOAD: m->m_pkthdr.pf.prio = IFQ_TOS2PRIO(itos); break; default: m->m_pkthdr.pf.prio = rxprio; break; } m->m_flags &= ~(M_MCAST|M_BCAST); m->m_flags |= mcast; if_vinput(ifp, m); return (IPPROTO_DONE); decline: *mp = m; return (-1); } static struct mbuf * gre_ipv4_patch(const struct gre_tunnel *tunnel, struct mbuf *m, uint8_t *itosp, uint8_t otos) { struct ip *ip; uint8_t itos; m = m_pullup(m, sizeof(*ip)); if (m == NULL) return (NULL); ip = mtod(m, struct ip *); itos = ip->ip_tos; if (ip_ecn_egress(tunnel->t_ecn, &otos, &itos) == 0) { m_freem(m); return (NULL); } if (itos != ip->ip_tos) ip_tos_patch(ip, itos); *itosp = itos; return (m); } #ifdef INET6 static struct mbuf * gre_ipv6_patch(const struct gre_tunnel *tunnel, struct mbuf *m, uint8_t *itosp, uint8_t otos) { struct ip6_hdr *ip6; uint32_t flow; uint8_t itos; m = m_pullup(m, sizeof(*ip6)); if (m == NULL) return (NULL); ip6 = mtod(m, struct ip6_hdr *); flow = bemtoh32(&ip6->ip6_flow); itos = flow >> 20; if (ip_ecn_egress(tunnel->t_ecn, &otos, &itos) == 0) { m_freem(m); return (NULL); } CLR(flow, 0xff << 20); SET(flow, itos << 20); htobem32(&ip6->ip6_flow, flow); *itosp = itos; return (m); } #endif #ifdef MPLS static struct mbuf * gre_mpls_patch(const struct gre_tunnel *tunnel, struct mbuf *m, uint8_t *itosp, uint8_t otos) { uint8_t itos; uint32_t shim; m = m_pullup(m, sizeof(shim)); if (m == NULL) return (NULL); shim = *mtod(m, uint32_t *); itos = (ntohl(shim & MPLS_EXP_MASK) >> MPLS_EXP_OFFSET) << 5; if (ip_ecn_egress(tunnel->t_ecn, &otos, &itos) == 0) { m_freem(m); return (NULL); } *itosp = itos; return (m); } #endif #define gre_l2_prio(_t, _m, _otos) do { \ int rxprio = (_t)->t_rxhprio; \ switch (rxprio) { \ case IF_HDRPRIO_PACKET: \ /* nop */ \ break; \ case IF_HDRPRIO_OUTER: \ (_m)->m_pkthdr.pf.prio = IFQ_TOS2PRIO((_otos)); \ break; \ default: \ (_m)->m_pkthdr.pf.prio = rxprio; \ break; \ } \ } while (0) static int egre_input(const struct gre_tunnel *key, struct mbuf *m, int hlen, uint8_t otos) { struct egre_softc *sc; NET_ASSERT_LOCKED(); sc = RBT_FIND(egre_tree, &egre_tree, (const struct egre_softc *)key); if (sc == NULL) return (-1); /* it's ours now */ m = gre_ether_align(m, hlen); if (m == NULL) return (0); if (sc->sc_tunnel.t_key_mask == GRE_KEY_ENTROPY) { SET(m->m_pkthdr.csum_flags, M_FLOWID); m->m_pkthdr.ph_flowid = bemtoh32(&key->t_key) & ~GRE_KEY_ENTROPY; } m->m_flags &= ~(M_MCAST|M_BCAST); gre_l2_prio(&sc->sc_tunnel, m, otos); if_vinput(&sc->sc_ac.ac_if, m); return (0); } static inline struct nvgre_softc * nvgre_mcast_find(const struct gre_tunnel *key, unsigned int if0idx) { struct nvgre_softc *sc; int rv; /* * building an nvgre_softc to use with RBT_FIND is expensive, and * would need to swap the src and dst addresses in the key. so do the * find by hand. */ NET_ASSERT_LOCKED(); sc = RBT_ROOT(nvgre_mcast_tree, &nvgre_mcast_tree); while (sc != NULL) { rv = nvgre_cmp_mcast(key, &key->t_src, if0idx, &sc->sc_tunnel, &sc->sc_tunnel.t_dst, sc->sc_ifp0); if (rv == 0) return (sc); if (rv < 0) sc = RBT_LEFT(nvgre_mcast_tree, sc); else sc = RBT_RIGHT(nvgre_mcast_tree, sc); } return (NULL); } static inline struct nvgre_softc * nvgre_ucast_find(const struct gre_tunnel *key) { NET_ASSERT_LOCKED(); return (RBT_FIND(nvgre_ucast_tree, &nvgre_ucast_tree, (struct nvgre_softc *)key)); } static int nvgre_input(const struct gre_tunnel *key, struct mbuf *m, int hlen, uint8_t otos) { struct nvgre_softc *sc; struct ether_header *eh; if (ISSET(m->m_flags, M_MCAST|M_BCAST)) sc = nvgre_mcast_find(key, m->m_pkthdr.ph_ifidx); else sc = nvgre_ucast_find(key); if (sc == NULL) return (-1); /* it's ours now */ m = gre_ether_align(m, hlen); if (m == NULL) return (0); eh = mtod(m, struct ether_header *); etherbridge_map_ea(&sc->sc_eb, (void *)&key->t_dst, (struct ether_addr *)eh->ether_shost); SET(m->m_pkthdr.csum_flags, M_FLOWID); m->m_pkthdr.ph_flowid = bemtoh32(&key->t_key) & ~GRE_KEY_ENTROPY; m->m_flags &= ~(M_MCAST|M_BCAST); gre_l2_prio(&sc->sc_tunnel, m, otos); if_vinput(&sc->sc_ac.ac_if, m); return (0); } static struct mbuf * gre_ether_align(struct mbuf *m, int hlen) { struct mbuf *n; int off; m_adj(m, hlen); if (m->m_pkthdr.len < sizeof(struct ether_header)) { m_freem(m); return (NULL); } m = m_pullup(m, sizeof(struct ether_header)); if (m == NULL) return (NULL); n = m_getptr(m, sizeof(struct ether_header), &off); if (n == NULL) { m_freem(m); return (NULL); } if (!ALIGNED_POINTER(mtod(n, caddr_t) + off, uint32_t)) { n = m_dup_pkt(m, ETHER_ALIGN, M_NOWAIT); m_freem(m); if (n == NULL) return (NULL); m = n; } return (m); } static void gre_keepalive_recv(struct ifnet *ifp, struct mbuf *m) { struct gre_softc *sc = ifp->if_softc; struct gre_keepalive *gk; SIPHASH_CTX ctx; uint8_t digest[SIPHASH_DIGEST_LENGTH]; int uptime, delta; int tick = ticks; if (sc->sc_ka_state == GRE_KA_NONE || sc->sc_tunnel.t_rtableid != sc->sc_if.if_rdomain) goto drop; if (m->m_pkthdr.len < sizeof(*gk)) goto drop; m = m_pullup(m, sizeof(*gk)); if (m == NULL) return; gk = mtod(m, struct gre_keepalive *); uptime = bemtoh32(&gk->gk_uptime) - sc->sc_ka_bias; delta = tick - uptime; if (delta < 0) goto drop; if (delta > hz * 10) /* magic */ goto drop; /* avoid too much siphash work */ delta = tick - sc->sc_ka_recvtm; if (delta > 0 && delta < (hz / 10)) goto drop; SipHash24_Init(&ctx, &sc->sc_ka_key); SipHash24_Update(&ctx, &gk->gk_uptime, sizeof(gk->gk_uptime)); SipHash24_Update(&ctx, &gk->gk_random, sizeof(gk->gk_random)); SipHash24_Final(digest, &ctx); if (memcmp(digest, gk->gk_digest, sizeof(digest)) != 0) goto drop; sc->sc_ka_recvtm = tick; switch (sc->sc_ka_state) { case GRE_KA_DOWN: sc->sc_ka_state = GRE_KA_HOLD; sc->sc_ka_holdcnt = sc->sc_ka_holdmax; sc->sc_ka_holdmax = MIN(sc->sc_ka_holdmax * 2, 16 * sc->sc_ka_count); break; case GRE_KA_HOLD: if (--sc->sc_ka_holdcnt > 0) break; sc->sc_ka_state = GRE_KA_UP; gre_link_state(&sc->sc_if, sc->sc_ka_state); break; case GRE_KA_UP: sc->sc_ka_holdmax--; sc->sc_ka_holdmax = MAX(sc->sc_ka_holdmax, sc->sc_ka_count); break; } timeout_add_sec(&sc->sc_ka_hold, sc->sc_ka_timeo * sc->sc_ka_count); drop: m_freem(m); } static int gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) { struct m_tag *mtag; int error = 0; if (!gre_allow) { error = EACCES; goto drop; } if (!ISSET(ifp->if_flags, IFF_RUNNING)) { error = ENETDOWN; goto drop; } switch (dst->sa_family) { case AF_INET: #ifdef INET6 case AF_INET6: #endif #ifdef MPLS case AF_MPLS: #endif break; default: error = EAFNOSUPPORT; goto drop; } /* Try to limit infinite recursion through misconfiguration. */ for (mtag = m_tag_find(m, PACKET_TAG_GRE, NULL); mtag; mtag = m_tag_find(m, PACKET_TAG_GRE, mtag)) { if (memcmp((caddr_t)(mtag + 1), &ifp->if_index, sizeof(ifp->if_index)) == 0) { m_freem(m); error = EIO; goto end; } } mtag = m_tag_get(PACKET_TAG_GRE, sizeof(ifp->if_index), M_NOWAIT); if (mtag == NULL) { m_freem(m); error = ENOBUFS; goto end; } memcpy((caddr_t)(mtag + 1), &ifp->if_index, sizeof(ifp->if_index)); m_tag_prepend(m, mtag); m->m_pkthdr.ph_family = dst->sa_family; error = if_enqueue(ifp, m); end: if (error) ifp->if_oerrors++; return (error); drop: m_freem(m); return (error); } void gre_start(struct ifnet *ifp) { struct gre_softc *sc = ifp->if_softc; struct mbuf *m; int af; #if NBPFILTER > 0 caddr_t if_bpf; #endif while ((m = ifq_dequeue(&ifp->if_snd)) != NULL) { af = m->m_pkthdr.ph_family; #if NBPFILTER > 0 if_bpf = ifp->if_bpf; if (if_bpf) bpf_mtap_af(if_bpf, af, m, BPF_DIRECTION_OUT); #endif m = gre_l3_encap(&sc->sc_tunnel, m, af); if (m == NULL || gre_ip_output(&sc->sc_tunnel, m) != 0) { ifp->if_oerrors++; continue; } } } void mgre_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt) { struct ifnet *lo0ifp; struct ifaddr *ifa, *lo0ifa; switch (req) { case RTM_ADD: if (!ISSET(rt->rt_flags, RTF_LOCAL)) break; TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (memcmp(rt_key(rt), ifa->ifa_addr, rt_key(rt)->sa_len) == 0) break; } if (ifa == NULL) break; KASSERT(ifa == rt->rt_ifa); lo0ifp = if_get(rtable_loindex(ifp->if_rdomain)); KASSERT(lo0ifp != NULL); TAILQ_FOREACH(lo0ifa, &lo0ifp->if_addrlist, ifa_list) { if (lo0ifa->ifa_addr->sa_family == ifa->ifa_addr->sa_family) break; } if_put(lo0ifp); if (lo0ifa == NULL) break; rt->rt_flags &= ~RTF_LLINFO; break; case RTM_DELETE: case RTM_RESOLVE: default: break; } } static int mgre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dest, struct rtentry *rt0) { struct mgre_softc *sc = ifp->if_softc; struct sockaddr *gate; struct rtentry *rt; struct m_tag *mtag; int error = 0; sa_family_t af; const void *addr; if (!gre_allow) { error = EACCES; goto drop; } if (!ISSET(ifp->if_flags, IFF_RUNNING)) { error = ENETDOWN; goto drop; } switch (dest->sa_family) { case AF_INET: #ifdef INET6 case AF_INET6: #endif #ifdef MPLS case AF_MPLS: #endif break; default: error = EAFNOSUPPORT; goto drop; } if (ISSET(m->m_flags, M_MCAST|M_BCAST)) { error = ENETUNREACH; goto drop; } rt = rt_getll(rt0); /* check rt_expire? */ if (ISSET(rt->rt_flags, RTF_REJECT)) { error = (rt == rt0) ? EHOSTDOWN : EHOSTUNREACH; goto drop; } if (!ISSET(rt->rt_flags, RTF_HOST)) { error = EHOSTUNREACH; goto drop; } if (ISSET(rt->rt_flags, RTF_GATEWAY)) { error = EINVAL; goto drop; } gate = rt->rt_gateway; af = gate->sa_family; if (af != sc->sc_tunnel.t_af) { error = EAGAIN; goto drop; } /* Try to limit infinite recursion through misconfiguration. */ for (mtag = m_tag_find(m, PACKET_TAG_GRE, NULL); mtag; mtag = m_tag_find(m, PACKET_TAG_GRE, mtag)) { if (memcmp((caddr_t)(mtag + 1), &ifp->if_index, sizeof(ifp->if_index)) == 0) { error = EIO; goto drop; } } mtag = m_tag_get(PACKET_TAG_GRE, sizeof(ifp->if_index), M_NOWAIT); if (mtag == NULL) { error = ENOBUFS; goto drop; } memcpy((caddr_t)(mtag + 1), &ifp->if_index, sizeof(ifp->if_index)); m_tag_prepend(m, mtag); switch (af) { case AF_INET: { struct sockaddr_in *sin = (struct sockaddr_in *)gate; addr = &sin->sin_addr; break; } #ifdef INET6 case AF_INET6: { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)gate; addr = &sin6->sin6_addr; break; } #endif default: unhandled_af(af); /* NOTREACHED */ } m = gre_l3_encap_dst(&sc->sc_tunnel, addr, m, dest->sa_family); if (m == NULL) { ifp->if_oerrors++; return (ENOBUFS); } m->m_pkthdr.ph_family = dest->sa_family; error = if_enqueue(ifp, m); if (error) ifp->if_oerrors++; return (error); drop: m_freem(m); return (error); } static void mgre_start(struct ifnet *ifp) { struct mgre_softc *sc = ifp->if_softc; struct mbuf *m; #if NBPFILTER > 0 caddr_t if_bpf; #endif while ((m = ifq_dequeue(&ifp->if_snd)) != NULL) { #if NBPFILTER > 0 if_bpf = ifp->if_bpf; if (if_bpf) { struct m_hdr mh; struct mbuf *n; int off; n = m_getptr(m, ifp->if_hdrlen, &off); KASSERT(n != NULL); mh.mh_flags = 0; mh.mh_next = n->m_next; mh.mh_len = n->m_len - off; mh.mh_data = n->m_data + off; bpf_mtap_af(if_bpf, m->m_pkthdr.ph_family, (struct mbuf *)&mh, BPF_DIRECTION_OUT); } #endif if (gre_ip_output(&sc->sc_tunnel, m) != 0) { ifp->if_oerrors++; continue; } } } static void egre_start(struct ifnet *ifp) { struct egre_softc *sc = ifp->if_softc; struct mbuf *m0, *m; #if NBPFILTER > 0 caddr_t if_bpf; #endif if (!gre_allow) { ifq_purge(&ifp->if_snd); return; } while ((m0 = ifq_dequeue(&ifp->if_snd)) != NULL) { #if NBPFILTER > 0 if_bpf = ifp->if_bpf; if (if_bpf) bpf_mtap_ether(if_bpf, m0, BPF_DIRECTION_OUT); #endif /* force prepend mbuf because of alignment problems */ m = m_get(M_DONTWAIT, m0->m_type); if (m == NULL) { m_freem(m0); continue; } M_MOVE_PKTHDR(m, m0); m->m_next = m0; m_align(m, 0); m->m_len = 0; m = gre_encap(&sc->sc_tunnel, m, htons(ETHERTYPE_TRANSETHER), sc->sc_tunnel.t_ttl, gre_l2_tos(&sc->sc_tunnel, m)); if (m == NULL || gre_ip_output(&sc->sc_tunnel, m) != 0) { ifp->if_oerrors++; continue; } } } static struct mbuf * gre_l3_encap_dst(const struct gre_tunnel *tunnel, const void *dst, struct mbuf *m, sa_family_t af) { uint16_t proto; uint8_t ttl, itos, otos; int tttl = tunnel->t_ttl; int ttloff; switch (af) { case AF_INET: { struct ip *ip; m = m_pullup(m, sizeof(*ip)); if (m == NULL) return (NULL); ip = mtod(m, struct ip *); itos = ip->ip_tos; ttloff = offsetof(struct ip, ip_ttl); proto = htons(ETHERTYPE_IP); break; } #ifdef INET6 case AF_INET6: { struct ip6_hdr *ip6; m = m_pullup(m, sizeof(*ip6)); if (m == NULL) return (NULL); ip6 = mtod(m, struct ip6_hdr *); itos = (ntohl(ip6->ip6_flow) & 0x0ff00000) >> 20; ttloff = offsetof(struct ip6_hdr, ip6_hlim); proto = htons(ETHERTYPE_IPV6); break; } #endif #ifdef MPLS case AF_MPLS: { uint32_t shim; m = m_pullup(m, sizeof(shim)); if (m == NULL) return (NULL); shim = bemtoh32(mtod(m, uint32_t *)) & MPLS_EXP_MASK; itos = (shim >> MPLS_EXP_OFFSET) << 5; ttloff = 3; if (m->m_flags & (M_BCAST | M_MCAST)) proto = htons(ETHERTYPE_MPLS_MCAST); else proto = htons(ETHERTYPE_MPLS); break; } #endif default: unhandled_af(af); } if (tttl == -1) { KASSERT(m->m_len > ttloff); /* m_pullup has happened */ ttl = *(m->m_data + ttloff); } else ttl = tttl; itos = gre_l3_tos(tunnel, m, itos); ip_ecn_ingress(tunnel->t_ecn, &otos, &itos); return (gre_encap_dst(tunnel, dst, m, proto, ttl, otos)); } static struct mbuf * gre_encap_dst(const struct gre_tunnel *tunnel, const union gre_addr *dst, struct mbuf *m, uint16_t proto, uint8_t ttl, uint8_t tos) { struct gre_header *gh; struct gre_h_key *gkh; int hlen; hlen = sizeof(*gh); if (tunnel->t_key_mask != GRE_KEY_NONE) hlen += sizeof(*gkh); m = m_prepend(m, hlen, M_DONTWAIT); if (m == NULL) return (NULL); gh = mtod(m, struct gre_header *); gh->gre_flags = GRE_VERS_0; gh->gre_proto = proto; if (tunnel->t_key_mask != GRE_KEY_NONE) { gh->gre_flags |= htons(GRE_KP); gkh = (struct gre_h_key *)(gh + 1); gkh->gre_key = tunnel->t_key; if (tunnel->t_key_mask == GRE_KEY_ENTROPY && ISSET(m->m_pkthdr.csum_flags, M_FLOWID)) { gkh->gre_key |= htonl(~GRE_KEY_ENTROPY & m->m_pkthdr.ph_flowid); } } return (gre_encap_dst_ip(tunnel, dst, m, ttl, tos)); } static struct mbuf * gre_encap_dst_ip(const struct gre_tunnel *tunnel, const union gre_addr *dst, struct mbuf *m, uint8_t ttl, uint8_t tos) { switch (tunnel->t_af) { case AF_UNSPEC: /* packets may arrive before tunnel is set up */ m_freem(m); return (NULL); case AF_INET: { struct ip *ip; m = m_prepend(m, sizeof(*ip), M_DONTWAIT); if (m == NULL) return (NULL); ip = mtod(m, struct ip *); ip->ip_v = IPVERSION; ip->ip_hl = sizeof(*ip) >> 2; ip->ip_off = tunnel->t_df; ip->ip_tos = tos; ip->ip_len = htons(m->m_pkthdr.len); ip->ip_ttl = ttl; ip->ip_p = IPPROTO_GRE; ip->ip_src = tunnel->t_src4; ip->ip_dst = dst->in4; break; } #ifdef INET6 case AF_INET6: { struct ip6_hdr *ip6; int len = m->m_pkthdr.len; m = m_prepend(m, sizeof(*ip6), M_DONTWAIT); if (m == NULL) return (NULL); ip6 = mtod(m, struct ip6_hdr *); ip6->ip6_flow = ISSET(m->m_pkthdr.csum_flags, M_FLOWID) ? htonl(m->m_pkthdr.ph_flowid) : 0; ip6->ip6_vfc |= IPV6_VERSION; ip6->ip6_flow |= htonl((uint32_t)tos << 20); ip6->ip6_plen = htons(len); ip6->ip6_nxt = IPPROTO_GRE; ip6->ip6_hlim = ttl; ip6->ip6_src = tunnel->t_src6; ip6->ip6_dst = dst->in6; if (tunnel->t_df) SET(m->m_pkthdr.csum_flags, M_IPV6_DF_OUT); break; } #endif /* INET6 */ default: unhandled_af(tunnel->t_af); } return (m); } static int gre_ip_output(const struct gre_tunnel *tunnel, struct mbuf *m) { m->m_flags &= ~(M_BCAST|M_MCAST); m->m_pkthdr.ph_rtableid = tunnel->t_rtableid; #if NPF > 0 pf_pkt_addr_changed(m); #endif switch (tunnel->t_af) { case AF_INET: ip_send(m); break; #ifdef INET6 case AF_INET6: ip6_send(m); break; #endif default: unhandled_af(tunnel->t_af); } return (0); } static int gre_tunnel_ioctl(struct ifnet *ifp, struct gre_tunnel *tunnel, u_long cmd, void *data) { struct ifreq *ifr = (struct ifreq *)data; int error = 0; switch(cmd) { case SIOCSIFMTU: if (ifr->ifr_mtu < 576) { error = EINVAL; break; } ifp->if_mtu = ifr->ifr_mtu; break; case SIOCADDMULTI: case SIOCDELMULTI: break; case SIOCSVNETID: error = gre_set_vnetid(tunnel, ifr); break; case SIOCGVNETID: error = gre_get_vnetid(tunnel, ifr); break; case SIOCDVNETID: error = gre_del_vnetid(tunnel); break; case SIOCSVNETFLOWID: error = gre_set_vnetflowid(tunnel, ifr); break; case SIOCGVNETFLOWID: error = gre_get_vnetflowid(tunnel, ifr); break; case SIOCSLIFPHYADDR: error = gre_set_tunnel(tunnel, (struct if_laddrreq *)data, 1); break; case SIOCGLIFPHYADDR: error = gre_get_tunnel(tunnel, (struct if_laddrreq *)data); break; case SIOCDIFPHYADDR: error = gre_del_tunnel(tunnel); break; case SIOCSLIFPHYRTABLE: if (ifr->ifr_rdomainid < 0 || ifr->ifr_rdomainid > RT_TABLEID_MAX || !rtable_exists(ifr->ifr_rdomainid)) { error = EINVAL; break; } tunnel->t_rtableid = ifr->ifr_rdomainid; break; case SIOCGLIFPHYRTABLE: ifr->ifr_rdomainid = tunnel->t_rtableid; break; case SIOCSLIFPHYDF: /* commit */ tunnel->t_df = ifr->ifr_df ? htons(IP_DF) : htons(0); break; case SIOCGLIFPHYDF: ifr->ifr_df = tunnel->t_df ? 1 : 0; break; default: error = ENOTTY; break; } return (error); } static uint8_t gre_l2_tos(const struct gre_tunnel *t, const struct mbuf *m) { uint8_t prio; switch (t->t_txhprio) { case IF_HDRPRIO_PACKET: prio = m->m_pkthdr.pf.prio; break; default: prio = t->t_txhprio; break; } return (IFQ_PRIO2TOS(prio)); } static uint8_t gre_l3_tos(const struct gre_tunnel *t, const struct mbuf *m, uint8_t tos) { uint8_t prio; switch (t->t_txhprio) { case IF_HDRPRIO_PAYLOAD: return (tos); case IF_HDRPRIO_PACKET: prio = m->m_pkthdr.pf.prio; break; default: prio = t->t_txhprio; break; } return (IFQ_PRIO2TOS(prio) | (tos & IPTOS_ECN_MASK)); } static int gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct gre_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *)data; struct ifkalivereq *ikar = (struct ifkalivereq *)data; int error = 0; switch(cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; /* FALLTHROUGH */ case SIOCSIFFLAGS: if (ISSET(ifp->if_flags, IFF_UP)) { if (!ISSET(ifp->if_flags, IFF_RUNNING)) error = gre_up(sc); else error = 0; } else { if (ISSET(ifp->if_flags, IFF_RUNNING)) error = gre_down(sc); } break; case SIOCSIFRDOMAIN: /* let if_rdomain do its thing */ error = ENOTTY; break; case SIOCSETKALIVE: if (ikar->ikar_timeo < 0 || ikar->ikar_timeo > 86400 || ikar->ikar_cnt < 0 || ikar->ikar_cnt > 256 || (ikar->ikar_timeo == 0) != (ikar->ikar_cnt == 0)) return (EINVAL); if (ikar->ikar_timeo == 0 || ikar->ikar_cnt == 0) { sc->sc_ka_count = 0; sc->sc_ka_timeo = 0; sc->sc_ka_state = GRE_KA_NONE; } else { sc->sc_ka_count = ikar->ikar_cnt; sc->sc_ka_timeo = ikar->ikar_timeo; sc->sc_ka_state = GRE_KA_DOWN; arc4random_buf(&sc->sc_ka_key, sizeof(sc->sc_ka_key)); sc->sc_ka_bias = arc4random(); sc->sc_ka_holdmax = sc->sc_ka_count; sc->sc_ka_recvtm = ticks - hz; timeout_add(&sc->sc_ka_send, 1); timeout_add_sec(&sc->sc_ka_hold, sc->sc_ka_timeo * sc->sc_ka_count); } break; case SIOCGETKALIVE: ikar->ikar_cnt = sc->sc_ka_count; ikar->ikar_timeo = sc->sc_ka_timeo; break; case SIOCSLIFPHYTTL: if (ifr->ifr_ttl != -1 && (ifr->ifr_ttl < 1 || ifr->ifr_ttl > 0xff)) { error = EINVAL; break; } /* commit */ sc->sc_tunnel.t_ttl = ifr->ifr_ttl; break; case SIOCGLIFPHYTTL: ifr->ifr_ttl = sc->sc_tunnel.t_ttl; break; case SIOCSLIFPHYECN: sc->sc_tunnel.t_ecn = ifr->ifr_metric ? ECN_ALLOWED : ECN_FORBIDDEN; break; case SIOCGLIFPHYECN: ifr->ifr_metric = (sc->sc_tunnel.t_ecn == ECN_ALLOWED); break; case SIOCSTXHPRIO: error = if_txhprio_l3_check(ifr->ifr_hdrprio); if (error != 0) break; sc->sc_tunnel.t_txhprio = ifr->ifr_hdrprio; break; case SIOCGTXHPRIO: ifr->ifr_hdrprio = sc->sc_tunnel.t_txhprio; break; case SIOCSRXHPRIO: error = if_rxhprio_l3_check(ifr->ifr_hdrprio); if (error != 0) break; sc->sc_tunnel.t_rxhprio = ifr->ifr_hdrprio; break; case SIOCGRXHPRIO: ifr->ifr_hdrprio = sc->sc_tunnel.t_rxhprio; break; default: error = gre_tunnel_ioctl(ifp, &sc->sc_tunnel, cmd, data); break; } return (error); } static int mgre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct mgre_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *)data; int error = 0; switch(cmd) { case SIOCSIFADDR: break; case SIOCSIFFLAGS: if (ISSET(ifp->if_flags, IFF_UP)) { if (!ISSET(ifp->if_flags, IFF_RUNNING)) error = mgre_up(sc); else error = 0; } else { if (ISSET(ifp->if_flags, IFF_RUNNING)) error = mgre_down(sc); } break; case SIOCSLIFPHYTTL: if (ifr->ifr_ttl != -1 && (ifr->ifr_ttl < 1 || ifr->ifr_ttl > 0xff)) { error = EINVAL; break; } /* commit */ sc->sc_tunnel.t_ttl = ifr->ifr_ttl; break; case SIOCGLIFPHYTTL: ifr->ifr_ttl = sc->sc_tunnel.t_ttl; break; case SIOCSLIFPHYECN: sc->sc_tunnel.t_ecn = ifr->ifr_metric ? ECN_ALLOWED : ECN_FORBIDDEN; break; case SIOCGLIFPHYECN: ifr->ifr_metric = (sc->sc_tunnel.t_ecn == ECN_ALLOWED); break; case SIOCSLIFPHYADDR: if (ISSET(ifp->if_flags, IFF_RUNNING)) { error = EBUSY; break; } error = mgre_set_tunnel(sc, (struct if_laddrreq *)data); break; case SIOCGLIFPHYADDR: error = mgre_get_tunnel(sc, (struct if_laddrreq *)data); break; case SIOCSTXHPRIO: error = if_txhprio_l3_check(ifr->ifr_hdrprio); if (error != 0) break; sc->sc_tunnel.t_txhprio = ifr->ifr_hdrprio; break; case SIOCGTXHPRIO: ifr->ifr_hdrprio = sc->sc_tunnel.t_txhprio; break; case SIOCSRXHPRIO: error = if_rxhprio_l3_check(ifr->ifr_hdrprio); if (error != 0) break; sc->sc_tunnel.t_rxhprio = ifr->ifr_hdrprio; break; case SIOCGRXHPRIO: ifr->ifr_hdrprio = sc->sc_tunnel.t_rxhprio; break; case SIOCSVNETID: case SIOCDVNETID: case SIOCDIFPHYADDR: case SIOCSLIFPHYRTABLE: if (ISSET(ifp->if_flags, IFF_RUNNING)) { error = EBUSY; break; } /* FALLTHROUGH */ default: error = gre_tunnel_ioctl(ifp, &sc->sc_tunnel, cmd, data); break; } return (error); } static int mgre_set_tunnel(struct mgre_softc *sc, struct if_laddrreq *req) { struct gre_tunnel *tunnel = &sc->sc_tunnel; struct sockaddr *addr = (struct sockaddr *)&req->addr; struct sockaddr *dstaddr = (struct sockaddr *)&req->dstaddr; struct sockaddr_in *addr4; #ifdef INET6 struct sockaddr_in6 *addr6; int error; #endif if (dstaddr->sa_family != AF_UNSPEC) return (EINVAL); /* validate */ switch (addr->sa_family) { case AF_INET: if (addr->sa_len != sizeof(*addr4)) return (EINVAL); addr4 = (struct sockaddr_in *)addr; if (in_nullhost(addr4->sin_addr) || IN_MULTICAST(addr4->sin_addr.s_addr)) return (EINVAL); tunnel->t_src4 = addr4->sin_addr; tunnel->t_dst4.s_addr = INADDR_ANY; break; #ifdef INET6 case AF_INET6: if (addr->sa_len != sizeof(*addr6)) return (EINVAL); addr6 = (struct sockaddr_in6 *)addr; if (IN6_IS_ADDR_UNSPECIFIED(&addr6->sin6_addr) || IN6_IS_ADDR_MULTICAST(&addr6->sin6_addr)) return (EINVAL); error = in6_embedscope(&tunnel->t_src6, addr6, NULL, NULL); if (error != 0) return (error); memset(&tunnel->t_dst6, 0, sizeof(tunnel->t_dst6)); break; #endif default: return (EAFNOSUPPORT); } /* commit */ tunnel->t_af = addr->sa_family; return (0); } static int mgre_get_tunnel(struct mgre_softc *sc, struct if_laddrreq *req) { struct gre_tunnel *tunnel = &sc->sc_tunnel; struct sockaddr *dstaddr = (struct sockaddr *)&req->dstaddr; struct sockaddr_in *sin; #ifdef INET6 struct sockaddr_in6 *sin6; #endif switch (tunnel->t_af) { case AF_UNSPEC: return (EADDRNOTAVAIL); case AF_INET: sin = (struct sockaddr_in *)&req->addr; memset(sin, 0, sizeof(*sin)); sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); sin->sin_addr = tunnel->t_src4; break; #ifdef INET6 case AF_INET6: sin6 = (struct sockaddr_in6 *)&req->addr; memset(sin6, 0, sizeof(*sin6)); sin6->sin6_family = AF_INET6; sin6->sin6_len = sizeof(*sin6); in6_recoverscope(sin6, &tunnel->t_src6); break; #endif default: unhandled_af(tunnel->t_af); } dstaddr->sa_len = 2; dstaddr->sa_family = AF_UNSPEC; return (0); } static int egre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct egre_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *)data; int error = 0; switch(cmd) { case SIOCSIFADDR: break; case SIOCSIFFLAGS: if (ISSET(ifp->if_flags, IFF_UP)) { if (!ISSET(ifp->if_flags, IFF_RUNNING)) error = egre_up(sc); else error = 0; } else { if (ISSET(ifp->if_flags, IFF_RUNNING)) error = egre_down(sc); } break; case SIOCSLIFPHYTTL: if (ifr->ifr_ttl < 1 || ifr->ifr_ttl > 0xff) { error = EINVAL; break; } /* commit */ sc->sc_tunnel.t_ttl = (uint8_t)ifr->ifr_ttl; break; case SIOCGLIFPHYTTL: ifr->ifr_ttl = (int)sc->sc_tunnel.t_ttl; break; case SIOCSTXHPRIO: error = if_txhprio_l2_check(ifr->ifr_hdrprio); if (error != 0) break; sc->sc_tunnel.t_txhprio = ifr->ifr_hdrprio; break; case SIOCGTXHPRIO: ifr->ifr_hdrprio = sc->sc_tunnel.t_txhprio; break; case SIOCSRXHPRIO: error = if_rxhprio_l2_check(ifr->ifr_hdrprio); if (error != 0) break; sc->sc_tunnel.t_rxhprio = ifr->ifr_hdrprio; break; case SIOCGRXHPRIO: ifr->ifr_hdrprio = sc->sc_tunnel.t_rxhprio; break; case SIOCSVNETID: case SIOCDVNETID: case SIOCSVNETFLOWID: case SIOCSLIFPHYADDR: case SIOCDIFPHYADDR: case SIOCSLIFPHYRTABLE: if (ISSET(ifp->if_flags, IFF_RUNNING)) { error = EBUSY; break; } /* FALLTHROUGH */ default: error = gre_tunnel_ioctl(ifp, &sc->sc_tunnel, cmd, data); if (error == ENOTTY) error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); break; } if (error == ENETRESET) { /* no hardware to program */ error = 0; } return (error); } static int nvgre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct nvgre_softc *sc = ifp->if_softc; struct gre_tunnel *tunnel = &sc->sc_tunnel; struct ifreq *ifr = (struct ifreq *)data; struct if_parent *parent = (struct if_parent *)data; struct ifbrparam *bparam = (struct ifbrparam *)data; struct ifnet *ifp0; int error = 0; switch (cmd) { case SIOCSIFADDR: break; case SIOCSIFFLAGS: if (ISSET(ifp->if_flags, IFF_UP)) { if (!ISSET(ifp->if_flags, IFF_RUNNING)) error = nvgre_up(sc); else error = ENETRESET; } else { if (ISSET(ifp->if_flags, IFF_RUNNING)) error = nvgre_down(sc); } break; case SIOCSLIFPHYADDR: if (ISSET(ifp->if_flags, IFF_RUNNING)) { error = EBUSY; break; } error = gre_set_tunnel(tunnel, (struct if_laddrreq *)data, 0); if (error == 0) etherbridge_flush(&sc->sc_eb, IFBF_FLUSHALL); break; case SIOCGLIFPHYADDR: error = gre_get_tunnel(tunnel, (struct if_laddrreq *)data); break; case SIOCDIFPHYADDR: if (ISSET(ifp->if_flags, IFF_RUNNING)) { error = EBUSY; break; } error = gre_del_tunnel(tunnel); if (error == 0) etherbridge_flush(&sc->sc_eb, IFBF_FLUSHALL); break; case SIOCSIFPARENT: if (ISSET(ifp->if_flags, IFF_RUNNING)) { error = EBUSY; break; } error = nvgre_set_parent(sc, parent->ifp_parent); if (error == 0) etherbridge_flush(&sc->sc_eb, IFBF_FLUSHALL); break; case SIOCGIFPARENT: ifp0 = if_get(sc->sc_ifp0); if (ifp0 == NULL) error = EADDRNOTAVAIL; else { memcpy(parent->ifp_parent, ifp0->if_xname, sizeof(parent->ifp_parent)); } if_put(ifp0); break; case SIOCDIFPARENT: if (ISSET(ifp->if_flags, IFF_RUNNING)) { error = EBUSY; break; } /* commit */ sc->sc_ifp0 = 0; etherbridge_flush(&sc->sc_eb, IFBF_FLUSHALL); break; case SIOCSVNETID: if (ISSET(ifp->if_flags, IFF_RUNNING)) { error = EBUSY; break; } if (ifr->ifr_vnetid < GRE_KEY_ENTROPY_MIN || ifr->ifr_vnetid > GRE_KEY_ENTROPY_MAX) { error = EINVAL; break; } /* commit */ tunnel->t_key = htonl(ifr->ifr_vnetid << GRE_KEY_ENTROPY_SHIFT); etherbridge_flush(&sc->sc_eb, IFBF_FLUSHALL); break; case SIOCGVNETID: error = gre_get_vnetid(tunnel, ifr); break; case SIOCSLIFPHYRTABLE: if (ifr->ifr_rdomainid < 0 || ifr->ifr_rdomainid > RT_TABLEID_MAX || !rtable_exists(ifr->ifr_rdomainid)) { error = EINVAL; break; } tunnel->t_rtableid = ifr->ifr_rdomainid; etherbridge_flush(&sc->sc_eb, IFBF_FLUSHALL); break; case SIOCGLIFPHYRTABLE: ifr->ifr_rdomainid = tunnel->t_rtableid; break; case SIOCSLIFPHYDF: /* commit */ tunnel->t_df = ifr->ifr_df ? htons(IP_DF) : htons(0); break; case SIOCGLIFPHYDF: ifr->ifr_df = tunnel->t_df ? 1 : 0; break; case SIOCSLIFPHYTTL: if (ifr->ifr_ttl < 1 || ifr->ifr_ttl > 0xff) { error = EINVAL; break; } /* commit */ tunnel->t_ttl = ifr->ifr_ttl; break; case SIOCGLIFPHYTTL: ifr->ifr_ttl = tunnel->t_ttl; break; case SIOCSTXHPRIO: error = if_txhprio_l2_check(ifr->ifr_hdrprio); if (error != 0) break; sc->sc_tunnel.t_txhprio = ifr->ifr_hdrprio; break; case SIOCGTXHPRIO: ifr->ifr_hdrprio = sc->sc_tunnel.t_txhprio; break; case SIOCSRXHPRIO: error = if_rxhprio_l2_check(ifr->ifr_hdrprio); if (error != 0) break; sc->sc_tunnel.t_rxhprio = ifr->ifr_hdrprio; break; case SIOCGRXHPRIO: ifr->ifr_hdrprio = sc->sc_tunnel.t_rxhprio; break; case SIOCBRDGSCACHE: error = etherbridge_set_max(&sc->sc_eb, bparam); break; case SIOCBRDGGCACHE: error = etherbridge_get_max(&sc->sc_eb, bparam); break; case SIOCBRDGSTO: error = etherbridge_set_tmo(&sc->sc_eb, bparam); break; case SIOCBRDGGTO: error = etherbridge_get_tmo(&sc->sc_eb, bparam); break; case SIOCBRDGRTS: error = etherbridge_rtfind(&sc->sc_eb, (struct ifbaconf *)data); break; case SIOCBRDGFLUSH: etherbridge_flush(&sc->sc_eb, ((struct ifbreq *)data)->ifbr_ifsflags); break; case SIOCBRDGSADDR: error = nvgre_add_addr(sc, (struct ifbareq *)data); break; case SIOCBRDGDADDR: error = nvgre_del_addr(sc, (struct ifbareq *)data); break; case SIOCADDMULTI: case SIOCDELMULTI: break; default: error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); break; } if (error == ENETRESET) { /* no hardware to program */ error = 0; } return (error); } static int eoip_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct eoip_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *)data; struct ifkalivereq *ikar = (struct ifkalivereq *)data; int error = 0; switch(cmd) { case SIOCSIFADDR: break; case SIOCSIFFLAGS: if (ISSET(ifp->if_flags, IFF_UP)) { if (!ISSET(ifp->if_flags, IFF_RUNNING)) error = eoip_up(sc); else error = 0; } else { if (ISSET(ifp->if_flags, IFF_RUNNING)) error = eoip_down(sc); } break; case SIOCSETKALIVE: if (ISSET(ifp->if_flags, IFF_RUNNING)) { error = EBUSY; break; } if (ikar->ikar_timeo < 0 || ikar->ikar_timeo > 86400 || ikar->ikar_cnt < 0 || ikar->ikar_cnt > 256) return (EINVAL); if (ikar->ikar_timeo == 0 || ikar->ikar_cnt == 0) { sc->sc_ka_count = 0; sc->sc_ka_timeo = 0; sc->sc_ka_state = GRE_KA_NONE; } else { sc->sc_ka_count = ikar->ikar_cnt; sc->sc_ka_timeo = ikar->ikar_timeo; sc->sc_ka_state = GRE_KA_DOWN; } break; case SIOCGETKALIVE: ikar->ikar_cnt = sc->sc_ka_count; ikar->ikar_timeo = sc->sc_ka_timeo; break; case SIOCSVNETID: if (ISSET(ifp->if_flags, IFF_RUNNING)) { error = EBUSY; break; } if (ifr->ifr_vnetid < 0 || ifr->ifr_vnetid > 0xffff) return (EINVAL); sc->sc_tunnel.t_key = htole16(ifr->ifr_vnetid); /* for cmp */ sc->sc_tunnel_id = htole16(ifr->ifr_vnetid); break; case SIOCGVNETID: ifr->ifr_vnetid = letoh16(sc->sc_tunnel_id); break; case SIOCSLIFPHYADDR: if (ISSET(ifp->if_flags, IFF_RUNNING)) { error = EBUSY; break; } error = gre_set_tunnel(&sc->sc_tunnel, (struct if_laddrreq *)data, 1); break; case SIOCGLIFPHYADDR: error = gre_get_tunnel(&sc->sc_tunnel, (struct if_laddrreq *)data); break; case SIOCDIFPHYADDR: if (ISSET(ifp->if_flags, IFF_RUNNING)) { error = EBUSY; break; } error = gre_del_tunnel(&sc->sc_tunnel); break; case SIOCSLIFPHYRTABLE: if (ISSET(ifp->if_flags, IFF_RUNNING)) { error = EBUSY; break; } if (ifr->ifr_rdomainid < 0 || ifr->ifr_rdomainid > RT_TABLEID_MAX || !rtable_exists(ifr->ifr_rdomainid)) { error = EINVAL; break; } sc->sc_tunnel.t_rtableid = ifr->ifr_rdomainid; break; case SIOCGLIFPHYRTABLE: ifr->ifr_rdomainid = sc->sc_tunnel.t_rtableid; break; case SIOCSLIFPHYTTL: if (ifr->ifr_ttl < 1 || ifr->ifr_ttl > 0xff) { error = EINVAL; break; } /* commit */ sc->sc_tunnel.t_ttl = (uint8_t)ifr->ifr_ttl; break; case SIOCGLIFPHYTTL: ifr->ifr_ttl = (int)sc->sc_tunnel.t_ttl; break; case SIOCSLIFPHYDF: /* commit */ sc->sc_tunnel.t_df = ifr->ifr_df ? htons(IP_DF) : htons(0); break; case SIOCGLIFPHYDF: ifr->ifr_df = sc->sc_tunnel.t_df ? 1 : 0; break; case SIOCSTXHPRIO: error = if_txhprio_l2_check(ifr->ifr_hdrprio); if (error != 0) break; sc->sc_tunnel.t_txhprio = ifr->ifr_hdrprio; break; case SIOCGTXHPRIO: ifr->ifr_hdrprio = sc->sc_tunnel.t_txhprio; break; case SIOCSRXHPRIO: error = if_rxhprio_l2_check(ifr->ifr_hdrprio); if (error != 0) break; sc->sc_tunnel.t_rxhprio = ifr->ifr_hdrprio; break; case SIOCGRXHPRIO: ifr->ifr_hdrprio = sc->sc_tunnel.t_rxhprio; break; case SIOCADDMULTI: case SIOCDELMULTI: break; default: error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); break; } if (error == ENETRESET) { /* no hardware to program */ error = 0; } return (error); } static int gre_up(struct gre_softc *sc) { NET_ASSERT_LOCKED(); SET(sc->sc_if.if_flags, IFF_RUNNING); if (sc->sc_ka_state != GRE_KA_NONE) gre_keepalive_send(sc); return (0); } static int gre_down(struct gre_softc *sc) { NET_ASSERT_LOCKED(); CLR(sc->sc_if.if_flags, IFF_RUNNING); if (sc->sc_ka_state != GRE_KA_NONE) { timeout_del_barrier(&sc->sc_ka_hold); timeout_del_barrier(&sc->sc_ka_send); sc->sc_ka_state = GRE_KA_DOWN; gre_link_state(&sc->sc_if, sc->sc_ka_state); } return (0); } static void gre_link_state(struct ifnet *ifp, unsigned int state) { int link_state = LINK_STATE_UNKNOWN; if (ISSET(ifp->if_flags, IFF_RUNNING)) { switch (state) { case GRE_KA_NONE: /* maybe up? or down? it's unknown, really */ break; case GRE_KA_UP: link_state = LINK_STATE_UP; break; default: link_state = LINK_STATE_KALIVE_DOWN; break; } } if (ifp->if_link_state != link_state) { ifp->if_link_state = link_state; if_link_state_change(ifp); } } static void gre_keepalive_send(void *arg) { struct gre_tunnel t; struct gre_softc *sc = arg; struct mbuf *m; struct gre_keepalive *gk; SIPHASH_CTX ctx; int linkhdr, len; uint16_t proto; uint8_t ttl; uint8_t tos; /* * re-schedule immediately, so we deal with incomplete configuration * or temporary errors. */ if (sc->sc_ka_timeo) timeout_add_sec(&sc->sc_ka_send, sc->sc_ka_timeo); if (!ISSET(sc->sc_if.if_flags, IFF_RUNNING) || sc->sc_ka_state == GRE_KA_NONE || sc->sc_tunnel.t_af == AF_UNSPEC || sc->sc_tunnel.t_rtableid != sc->sc_if.if_rdomain) return; /* this is really conservative */ #ifdef INET6 linkhdr = max_linkhdr + MAX(sizeof(struct ip), sizeof(struct ip6_hdr)) + sizeof(struct gre_header) + sizeof(struct gre_h_key); #else linkhdr = max_linkhdr + sizeof(struct ip) + sizeof(struct gre_header) + sizeof(struct gre_h_key); #endif len = linkhdr + sizeof(*gk); MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == NULL) return; if (len > MHLEN) { MCLGETL(m, M_DONTWAIT, len); if (!ISSET(m->m_flags, M_EXT)) { m_freem(m); return; } } m->m_pkthdr.len = m->m_len = len; m_adj(m, linkhdr); /* * build the inside packet */ gk = mtod(m, struct gre_keepalive *); htobem32(&gk->gk_uptime, sc->sc_ka_bias + ticks); htobem32(&gk->gk_random, arc4random()); SipHash24_Init(&ctx, &sc->sc_ka_key); SipHash24_Update(&ctx, &gk->gk_uptime, sizeof(gk->gk_uptime)); SipHash24_Update(&ctx, &gk->gk_random, sizeof(gk->gk_random)); SipHash24_Final(gk->gk_digest, &ctx); ttl = sc->sc_tunnel.t_ttl == -1 ? ip_defttl : sc->sc_tunnel.t_ttl; m->m_pkthdr.pf.prio = sc->sc_if.if_llprio; tos = gre_l3_tos(&sc->sc_tunnel, m, IFQ_PRIO2TOS(m->m_pkthdr.pf.prio)); t.t_af = sc->sc_tunnel.t_af; t.t_df = sc->sc_tunnel.t_df; t.t_src = sc->sc_tunnel.t_dst; t.t_dst = sc->sc_tunnel.t_src; t.t_key = sc->sc_tunnel.t_key; t.t_key_mask = sc->sc_tunnel.t_key_mask; m = gre_encap(&t, m, htons(0), ttl, tos); if (m == NULL) return; switch (sc->sc_tunnel.t_af) { case AF_INET: { struct ip *ip; ip = mtod(m, struct ip *); ip->ip_id = htons(ip_randomid()); in_hdr_cksum_out(m, NULL); proto = htons(ETHERTYPE_IP); break; } #ifdef INET6 case AF_INET6: proto = htons(ETHERTYPE_IPV6); break; #endif default: m_freem(m); return; } /* * put it in the tunnel */ m = gre_encap(&sc->sc_tunnel, m, proto, ttl, tos); if (m == NULL) return; gre_ip_output(&sc->sc_tunnel, m); } static void gre_keepalive_hold(void *arg) { struct gre_softc *sc = arg; struct ifnet *ifp = &sc->sc_if; if (!ISSET(ifp->if_flags, IFF_RUNNING) || sc->sc_ka_state == GRE_KA_NONE) return; NET_LOCK(); sc->sc_ka_state = GRE_KA_DOWN; gre_link_state(ifp, sc->sc_ka_state); NET_UNLOCK(); } static int gre_set_tunnel(struct gre_tunnel *tunnel, struct if_laddrreq *req, int ucast) { struct sockaddr *src = (struct sockaddr *)&req->addr; struct sockaddr *dst = (struct sockaddr *)&req->dstaddr; struct sockaddr_in *src4, *dst4; #ifdef INET6 struct sockaddr_in6 *src6, *dst6; int error; #endif /* sa_family and sa_len must be equal */ if (src->sa_family != dst->sa_family || src->sa_len != dst->sa_len) return (EINVAL); /* validate */ switch (dst->sa_family) { case AF_INET: if (dst->sa_len != sizeof(*dst4)) return (EINVAL); src4 = (struct sockaddr_in *)src; if (in_nullhost(src4->sin_addr) || IN_MULTICAST(src4->sin_addr.s_addr)) return (EINVAL); dst4 = (struct sockaddr_in *)dst; if (in_nullhost(dst4->sin_addr) || (IN_MULTICAST(dst4->sin_addr.s_addr) != !ucast)) return (EINVAL); tunnel->t_src4 = src4->sin_addr; tunnel->t_dst4 = dst4->sin_addr; break; #ifdef INET6 case AF_INET6: if (dst->sa_len != sizeof(*dst6)) return (EINVAL); src6 = (struct sockaddr_in6 *)src; if (IN6_IS_ADDR_UNSPECIFIED(&src6->sin6_addr) || IN6_IS_ADDR_MULTICAST(&src6->sin6_addr)) return (EINVAL); dst6 = (struct sockaddr_in6 *)dst; if (IN6_IS_ADDR_UNSPECIFIED(&dst6->sin6_addr) || IN6_IS_ADDR_MULTICAST(&dst6->sin6_addr) != !ucast) return (EINVAL); if (src6->sin6_scope_id != dst6->sin6_scope_id) return (EINVAL); error = in6_embedscope(&tunnel->t_src6, src6, NULL, NULL); if (error != 0) return (error); error = in6_embedscope(&tunnel->t_dst6, dst6, NULL, NULL); if (error != 0) return (error); break; #endif default: return (EAFNOSUPPORT); } /* commit */ tunnel->t_af = dst->sa_family; return (0); } static int gre_get_tunnel(struct gre_tunnel *tunnel, struct if_laddrreq *req) { struct sockaddr *src = (struct sockaddr *)&req->addr; struct sockaddr *dst = (struct sockaddr *)&req->dstaddr; struct sockaddr_in *sin; #ifdef INET6 /* ifconfig already embeds the scopeid */ struct sockaddr_in6 *sin6; #endif switch (tunnel->t_af) { case AF_UNSPEC: return (EADDRNOTAVAIL); case AF_INET: sin = (struct sockaddr_in *)src; memset(sin, 0, sizeof(*sin)); sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); sin->sin_addr = tunnel->t_src4; sin = (struct sockaddr_in *)dst; memset(sin, 0, sizeof(*sin)); sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); sin->sin_addr = tunnel->t_dst4; break; #ifdef INET6 case AF_INET6: sin6 = (struct sockaddr_in6 *)src; memset(sin6, 0, sizeof(*sin6)); sin6->sin6_family = AF_INET6; sin6->sin6_len = sizeof(*sin6); in6_recoverscope(sin6, &tunnel->t_src6); sin6 = (struct sockaddr_in6 *)dst; memset(sin6, 0, sizeof(*sin6)); sin6->sin6_family = AF_INET6; sin6->sin6_len = sizeof(*sin6); in6_recoverscope(sin6, &tunnel->t_dst6); break; #endif default: return (EAFNOSUPPORT); } return (0); } static int gre_del_tunnel(struct gre_tunnel *tunnel) { /* commit */ tunnel->t_af = AF_UNSPEC; return (0); } static int gre_set_vnetid(struct gre_tunnel *tunnel, struct ifreq *ifr) { uint32_t key; uint32_t min = GRE_KEY_MIN; uint32_t max = GRE_KEY_MAX; unsigned int shift = GRE_KEY_SHIFT; uint32_t mask = GRE_KEY_MASK; if (tunnel->t_key_mask == GRE_KEY_ENTROPY) { min = GRE_KEY_ENTROPY_MIN; max = GRE_KEY_ENTROPY_MAX; shift = GRE_KEY_ENTROPY_SHIFT; mask = GRE_KEY_ENTROPY; } if (ifr->ifr_vnetid < min || ifr->ifr_vnetid > max) return (EINVAL); key = htonl(ifr->ifr_vnetid << shift); /* commit */ tunnel->t_key_mask = mask; tunnel->t_key = key; return (0); } static int gre_get_vnetid(struct gre_tunnel *tunnel, struct ifreq *ifr) { int shift; switch (tunnel->t_key_mask) { case GRE_KEY_NONE: return (EADDRNOTAVAIL); case GRE_KEY_ENTROPY: shift = GRE_KEY_ENTROPY_SHIFT; break; case GRE_KEY_MASK: shift = GRE_KEY_SHIFT; break; } ifr->ifr_vnetid = ntohl(tunnel->t_key) >> shift; return (0); } static int gre_del_vnetid(struct gre_tunnel *tunnel) { tunnel->t_key_mask = GRE_KEY_NONE; return (0); } static int gre_set_vnetflowid(struct gre_tunnel *tunnel, struct ifreq *ifr) { uint32_t mask, key; if (tunnel->t_key_mask == GRE_KEY_NONE) return (EADDRNOTAVAIL); mask = ifr->ifr_vnetid ? GRE_KEY_ENTROPY : GRE_KEY_MASK; if (tunnel->t_key_mask == mask) { /* nop */ return (0); } key = ntohl(tunnel->t_key); if (mask == GRE_KEY_ENTROPY) { if (key > GRE_KEY_ENTROPY_MAX) return (ERANGE); key = htonl(key << GRE_KEY_ENTROPY_SHIFT); } else key = htonl(key >> GRE_KEY_ENTROPY_SHIFT); /* commit */ tunnel->t_key_mask = mask; tunnel->t_key = key; return (0); } static int gre_get_vnetflowid(struct gre_tunnel *tunnel, struct ifreq *ifr) { if (tunnel->t_key_mask == GRE_KEY_NONE) return (EADDRNOTAVAIL); ifr->ifr_vnetid = tunnel->t_key_mask == GRE_KEY_ENTROPY; return (0); } static int mgre_up(struct mgre_softc *sc) { unsigned int hlen; switch (sc->sc_tunnel.t_af) { case AF_UNSPEC: return (EDESTADDRREQ); case AF_INET: hlen = sizeof(struct ip); break; #ifdef INET6 case AF_INET6: hlen = sizeof(struct ip6_hdr); break; #endif /* INET6 */ default: unhandled_af(sc->sc_tunnel.t_af); } hlen += sizeof(struct gre_header); if (sc->sc_tunnel.t_key_mask != GRE_KEY_NONE) hlen += sizeof(struct gre_h_key); NET_ASSERT_LOCKED(); if (RBT_INSERT(mgre_tree, &mgre_tree, sc) != NULL) return (EADDRINUSE); sc->sc_if.if_hdrlen = hlen; SET(sc->sc_if.if_flags, IFF_RUNNING); return (0); } static int mgre_down(struct mgre_softc *sc) { NET_ASSERT_LOCKED(); CLR(sc->sc_if.if_flags, IFF_RUNNING); sc->sc_if.if_hdrlen = GRE_HDRLEN; /* symmetry */ RBT_REMOVE(mgre_tree, &mgre_tree, sc); /* barrier? */ return (0); } static int egre_up(struct egre_softc *sc) { if (sc->sc_tunnel.t_af == AF_UNSPEC) return (EDESTADDRREQ); NET_ASSERT_LOCKED(); if (RBT_INSERT(egre_tree, &egre_tree, sc) != NULL) return (EADDRINUSE); SET(sc->sc_ac.ac_if.if_flags, IFF_RUNNING); return (0); } static int egre_down(struct egre_softc *sc) { NET_ASSERT_LOCKED(); CLR(sc->sc_ac.ac_if.if_flags, IFF_RUNNING); RBT_REMOVE(egre_tree, &egre_tree, sc); /* barrier? */ return (0); } static int egre_media_change(struct ifnet *ifp) { return (ENOTTY); } static void egre_media_status(struct ifnet *ifp, struct ifmediareq *imr) { imr->ifm_active = IFM_ETHER | IFM_AUTO; imr->ifm_status = IFM_AVALID | IFM_ACTIVE; } static int nvgre_up(struct nvgre_softc *sc) { struct gre_tunnel *tunnel = &sc->sc_tunnel; struct ifnet *ifp0; void *inm; int error; if (tunnel->t_af == AF_UNSPEC) return (EDESTADDRREQ); ifp0 = if_get(sc->sc_ifp0); if (ifp0 == NULL) return (ENXIO); if (!ISSET(ifp0->if_flags, IFF_MULTICAST)) { error = ENODEV; goto put; } NET_ASSERT_LOCKED(); if (RBT_INSERT(nvgre_mcast_tree, &nvgre_mcast_tree, sc) != NULL) { error = EADDRINUSE; goto put; } if (RBT_INSERT(nvgre_ucast_tree, &nvgre_ucast_tree, sc) != NULL) { error = EADDRINUSE; goto remove_mcast; } switch (tunnel->t_af) { case AF_INET: inm = in_addmulti(&tunnel->t_dst4, ifp0); if (inm == NULL) { error = ECONNABORTED; goto remove_ucast; } break; #ifdef INET6 case AF_INET6: inm = in6_addmulti(&tunnel->t_dst6, ifp0, &error); if (inm == NULL) { /* error is already set */ goto remove_ucast; } break; #endif /* INET6 */ default: unhandled_af(tunnel->t_af); } if_linkstatehook_add(ifp0, &sc->sc_ltask); if_detachhook_add(ifp0, &sc->sc_dtask); if_put(ifp0); sc->sc_inm = inm; SET(sc->sc_ac.ac_if.if_flags, IFF_RUNNING); return (0); remove_ucast: RBT_REMOVE(nvgre_ucast_tree, &nvgre_ucast_tree, sc); remove_mcast: RBT_REMOVE(nvgre_mcast_tree, &nvgre_mcast_tree, sc); put: if_put(ifp0); return (error); } static int nvgre_down(struct nvgre_softc *sc) { struct gre_tunnel *tunnel = &sc->sc_tunnel; struct ifnet *ifp = &sc->sc_ac.ac_if; struct taskq *softnet = net_tq(ifp->if_index); struct ifnet *ifp0; NET_ASSERT_LOCKED(); CLR(ifp->if_flags, IFF_RUNNING); NET_UNLOCK(); ifq_barrier(&ifp->if_snd); if (!task_del(softnet, &sc->sc_send_task)) taskq_barrier(softnet); NET_LOCK(); mq_purge(&sc->sc_send_list); ifp0 = if_get(sc->sc_ifp0); if (ifp0 != NULL) { if_detachhook_del(ifp0, &sc->sc_dtask); if_linkstatehook_del(ifp0, &sc->sc_ltask); } if_put(ifp0); switch (tunnel->t_af) { case AF_INET: in_delmulti(sc->sc_inm); break; #ifdef INET6 case AF_INET6: in6_delmulti(sc->sc_inm); break; #endif default: unhandled_af(tunnel->t_af); } RBT_REMOVE(nvgre_ucast_tree, &nvgre_ucast_tree, sc); RBT_REMOVE(nvgre_mcast_tree, &nvgre_mcast_tree, sc); return (0); } static void nvgre_link_change(void *arg) { /* nop */ } static void nvgre_detach(void *arg) { struct nvgre_softc *sc = arg; struct ifnet *ifp = &sc->sc_ac.ac_if; if (ISSET(ifp->if_flags, IFF_RUNNING)) { nvgre_down(sc); if_down(ifp); } sc->sc_ifp0 = 0; } static int nvgre_set_parent(struct nvgre_softc *sc, const char *parent) { struct ifnet *ifp0; ifp0 = if_unit(parent); if (ifp0 == NULL) return (EINVAL); if (!ISSET(ifp0->if_flags, IFF_MULTICAST)) { if_put(ifp0); return (EPROTONOSUPPORT); } ifsetlro(ifp0, 0); /* commit */ sc->sc_ifp0 = ifp0->if_index; if_put(ifp0); return (0); } static int nvgre_add_addr(struct nvgre_softc *sc, const struct ifbareq *ifba) { struct sockaddr_in *sin; #ifdef INET6 struct sockaddr_in6 *sin6; struct sockaddr_in6 src6 = { .sin6_len = sizeof(src6), .sin6_family = AF_UNSPEC, }; int error; #endif union gre_addr endpoint; unsigned int type; /* ignore ifba_ifsname */ if (ISSET(ifba->ifba_flags, ~IFBAF_TYPEMASK)) return (EINVAL); switch (ifba->ifba_flags & IFBAF_TYPEMASK) { case IFBAF_DYNAMIC: type = EBE_DYNAMIC; break; case IFBAF_STATIC: type = EBE_STATIC; break; default: return (EINVAL); } memset(&endpoint, 0, sizeof(endpoint)); if (ifba->ifba_dstsa.ss_family != sc->sc_tunnel.t_af) return (EAFNOSUPPORT); switch (ifba->ifba_dstsa.ss_family) { case AF_INET: sin = (struct sockaddr_in *)&ifba->ifba_dstsa; if (in_nullhost(sin->sin_addr) || IN_MULTICAST(sin->sin_addr.s_addr)) return (EADDRNOTAVAIL); endpoint.in4 = sin->sin_addr; break; #ifdef INET6 case AF_INET6: sin6 = (struct sockaddr_in6 *)&ifba->ifba_dstsa; if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) || IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) return (EADDRNOTAVAIL); in6_recoverscope(&src6, &sc->sc_tunnel.t_src6); if (src6.sin6_scope_id != sin6->sin6_scope_id) return (EADDRNOTAVAIL); error = in6_embedscope(&endpoint.in6, sin6, NULL, NULL); if (error != 0) return (error); break; #endif default: /* AF_UNSPEC */ return (EADDRNOTAVAIL); } return (etherbridge_add_addr(&sc->sc_eb, &endpoint, &ifba->ifba_dst, type)); } static int nvgre_del_addr(struct nvgre_softc *sc, const struct ifbareq *ifba) { return (etherbridge_del_addr(&sc->sc_eb, &ifba->ifba_dst)); } static void nvgre_start(struct ifnet *ifp) { struct nvgre_softc *sc = ifp->if_softc; const struct gre_tunnel *tunnel = &sc->sc_tunnel; union gre_addr gateway; struct mbuf_list ml = MBUF_LIST_INITIALIZER(); struct ether_header *eh; struct mbuf *m, *m0; #if NBPFILTER > 0 caddr_t if_bpf; #endif if (!gre_allow) { ifq_purge(&ifp->if_snd); return; } while ((m0 = ifq_dequeue(&ifp->if_snd)) != NULL) { #if NBPFILTER > 0 if_bpf = ifp->if_bpf; if (if_bpf) bpf_mtap_ether(if_bpf, m0, BPF_DIRECTION_OUT); #endif eh = mtod(m0, struct ether_header *); if (ETHER_IS_BROADCAST(eh->ether_dhost)) gateway = tunnel->t_dst; else { const union gre_addr *endpoint; smr_read_enter(); endpoint = etherbridge_resolve_ea(&sc->sc_eb, (struct ether_addr *)eh->ether_dhost); if (endpoint == NULL) { /* "flood" to unknown hosts */ endpoint = &tunnel->t_dst; } gateway = *endpoint; smr_read_leave(); } /* force prepend mbuf because of alignment problems */ m = m_get(M_DONTWAIT, m0->m_type); if (m == NULL) { m_freem(m0); continue; } M_MOVE_PKTHDR(m, m0); m->m_next = m0; m_align(m, 0); m->m_len = 0; m = gre_encap_dst(tunnel, &gateway, m, htons(ETHERTYPE_TRANSETHER), tunnel->t_ttl, gre_l2_tos(tunnel, m)); if (m == NULL) continue; m->m_flags &= ~(M_BCAST|M_MCAST); m->m_pkthdr.ph_rtableid = tunnel->t_rtableid; #if NPF > 0 pf_pkt_addr_changed(m); #endif ml_enqueue(&ml, m); } if (!ml_empty(&ml)) { if (mq_enlist(&sc->sc_send_list, &ml) == 0) task_add(net_tq(ifp->if_index), &sc->sc_send_task); /* else set OACTIVE? */ } } static uint64_t nvgre_send4(struct nvgre_softc *sc, struct mbuf_list *ml) { struct ip_moptions imo; struct mbuf *m; uint64_t oerrors = 0; imo.imo_ifidx = sc->sc_ifp0; imo.imo_ttl = sc->sc_tunnel.t_ttl; imo.imo_loop = 0; NET_LOCK(); while ((m = ml_dequeue(ml)) != NULL) { if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &imo, NULL, 0) != 0) oerrors++; } NET_UNLOCK(); return (oerrors); } #ifdef INET6 static uint64_t nvgre_send6(struct nvgre_softc *sc, struct mbuf_list *ml) { struct ip6_moptions im6o; struct mbuf *m; uint64_t oerrors = 0; im6o.im6o_ifidx = sc->sc_ifp0; im6o.im6o_hlim = sc->sc_tunnel.t_ttl; im6o.im6o_loop = 0; NET_LOCK(); while ((m = ml_dequeue(ml)) != NULL) { if (ip6_output(m, NULL, NULL, 0, &im6o, NULL) != 0) oerrors++; } NET_UNLOCK(); return (oerrors); } #endif /* INET6 */ static void nvgre_send(void *arg) { struct nvgre_softc *sc = arg; struct ifnet *ifp = &sc->sc_ac.ac_if; sa_family_t af = sc->sc_tunnel.t_af; struct mbuf_list ml; uint64_t oerrors; if (!ISSET(ifp->if_flags, IFF_RUNNING)) return; mq_delist(&sc->sc_send_list, &ml); if (ml_empty(&ml)) return; switch (af) { case AF_INET: oerrors = nvgre_send4(sc, &ml); break; #ifdef INET6 case AF_INET6: oerrors = nvgre_send6(sc, &ml); break; #endif default: unhandled_af(af); /* NOTREACHED */ } ifp->if_oerrors += oerrors; /* XXX should be ifq_oerrors */ } static int eoip_up(struct eoip_softc *sc) { if (sc->sc_tunnel.t_af == AF_UNSPEC) return (EDESTADDRREQ); NET_ASSERT_LOCKED(); if (RBT_INSERT(eoip_tree, &eoip_tree, sc) != NULL) return (EADDRINUSE); SET(sc->sc_ac.ac_if.if_flags, IFF_RUNNING); if (sc->sc_ka_state != GRE_KA_NONE) { sc->sc_ka_holdmax = sc->sc_ka_count; eoip_keepalive_send(sc); } return (0); } static int eoip_down(struct eoip_softc *sc) { NET_ASSERT_LOCKED(); CLR(sc->sc_ac.ac_if.if_flags, IFF_RUNNING); if (sc->sc_ka_state != GRE_KA_NONE) { timeout_del_barrier(&sc->sc_ka_hold); timeout_del_barrier(&sc->sc_ka_send); sc->sc_ka_state = GRE_KA_DOWN; gre_link_state(&sc->sc_ac.ac_if, sc->sc_ka_state); } RBT_REMOVE(eoip_tree, &eoip_tree, sc); return (0); } static void eoip_start(struct ifnet *ifp) { struct eoip_softc *sc = ifp->if_softc; struct mbuf *m0, *m; #if NBPFILTER > 0 caddr_t if_bpf; #endif if (!gre_allow) { ifq_purge(&ifp->if_snd); return; } while ((m0 = ifq_dequeue(&ifp->if_snd)) != NULL) { #if NBPFILTER > 0 if_bpf = ifp->if_bpf; if (if_bpf) bpf_mtap_ether(if_bpf, m0, BPF_DIRECTION_OUT); #endif /* force prepend mbuf because of alignment problems */ m = m_get(M_DONTWAIT, m0->m_type); if (m == NULL) { m_freem(m0); continue; } M_MOVE_PKTHDR(m, m0); m->m_next = m0; m_align(m, 0); m->m_len = 0; m = eoip_encap(sc, m, gre_l2_tos(&sc->sc_tunnel, m)); if (m == NULL || gre_ip_output(&sc->sc_tunnel, m) != 0) { ifp->if_oerrors++; continue; } } } static struct mbuf * eoip_encap(struct eoip_softc *sc, struct mbuf *m, uint8_t tos) { struct gre_header *gh; struct gre_h_key_eoip *eoiph; int len = m->m_pkthdr.len; m = m_prepend(m, sizeof(*gh) + sizeof(*eoiph), M_DONTWAIT); if (m == NULL) return (NULL); gh = mtod(m, struct gre_header *); gh->gre_flags = htons(GRE_VERS_1 | GRE_KP); gh->gre_proto = htons(GRE_EOIP); eoiph = (struct gre_h_key_eoip *)(gh + 1); htobem16(&eoiph->eoip_len, len); eoiph->eoip_tunnel_id = sc->sc_tunnel_id; return (gre_encap_ip(&sc->sc_tunnel, m, sc->sc_tunnel.t_ttl, tos)); } static void eoip_keepalive_send(void *arg) { struct eoip_softc *sc = arg; struct ifnet *ifp = &sc->sc_ac.ac_if; struct mbuf *m; int linkhdr; if (!ISSET(ifp->if_flags, IFF_RUNNING)) return; /* this is really conservative */ #ifdef INET6 linkhdr = max_linkhdr + MAX(sizeof(struct ip), sizeof(struct ip6_hdr)) + sizeof(struct gre_header) + sizeof(struct gre_h_key_eoip); #else linkhdr = max_linkhdr + sizeof(struct ip) + sizeof(struct gre_header) + sizeof(struct gre_h_key_eoip); #endif MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == NULL) return; if (linkhdr > MHLEN) { MCLGETL(m, M_DONTWAIT, linkhdr); if (!ISSET(m->m_flags, M_EXT)) { m_freem(m); return; } } m->m_pkthdr.pf.prio = ifp->if_llprio; m->m_pkthdr.len = m->m_len = linkhdr; m_adj(m, linkhdr); m = eoip_encap(sc, m, gre_l2_tos(&sc->sc_tunnel, m)); if (m == NULL) return; gre_ip_output(&sc->sc_tunnel, m); timeout_add_sec(&sc->sc_ka_send, sc->sc_ka_timeo); } static void eoip_keepalive_hold(void *arg) { struct eoip_softc *sc = arg; struct ifnet *ifp = &sc->sc_ac.ac_if; if (!ISSET(ifp->if_flags, IFF_RUNNING)) return; NET_LOCK(); sc->sc_ka_state = GRE_KA_DOWN; gre_link_state(ifp, sc->sc_ka_state); NET_UNLOCK(); } static void eoip_keepalive_recv(struct eoip_softc *sc) { switch (sc->sc_ka_state) { case GRE_KA_NONE: return; case GRE_KA_DOWN: sc->sc_ka_state = GRE_KA_HOLD; sc->sc_ka_holdcnt = sc->sc_ka_holdmax; sc->sc_ka_holdmax = MIN(sc->sc_ka_holdmax * 2, 16 * sc->sc_ka_count); break; case GRE_KA_HOLD: if (--sc->sc_ka_holdcnt > 0) break; sc->sc_ka_state = GRE_KA_UP; gre_link_state(&sc->sc_ac.ac_if, sc->sc_ka_state); break; case GRE_KA_UP: sc->sc_ka_holdmax--; sc->sc_ka_holdmax = MAX(sc->sc_ka_holdmax, sc->sc_ka_count); break; } timeout_add_sec(&sc->sc_ka_hold, sc->sc_ka_timeo * sc->sc_ka_count); } static struct mbuf * eoip_input(struct gre_tunnel *key, struct mbuf *m, const struct gre_header *gh, uint8_t otos, int iphlen) { struct eoip_softc *sc; struct gre_h_key_eoip *eoiph; int hlen, len; caddr_t buf; if (gh->gre_flags != htons(GRE_KP | GRE_VERS_1)) goto decline; hlen = iphlen + sizeof(*gh) + sizeof(*eoiph); if (m->m_pkthdr.len < hlen) goto decline; m = m_pullup(m, hlen); if (m == NULL) return (NULL); buf = mtod(m, caddr_t); gh = (struct gre_header *)(buf + iphlen); eoiph = (struct gre_h_key_eoip *)(gh + 1); key->t_key = eoiph->eoip_tunnel_id; NET_ASSERT_LOCKED(); sc = RBT_FIND(eoip_tree, &eoip_tree, (const struct eoip_softc *)key); if (sc == NULL) goto decline; /* it's ours now */ len = bemtoh16(&eoiph->eoip_len); if (len == 0) { eoip_keepalive_recv(sc); goto drop; } m = gre_ether_align(m, hlen); if (m == NULL) return (NULL); if (m->m_pkthdr.len < len) goto drop; if (m->m_pkthdr.len != len) m_adj(m, len - m->m_pkthdr.len); m->m_flags &= ~(M_MCAST|M_BCAST); gre_l2_prio(&sc->sc_tunnel, m, otos); if_vinput(&sc->sc_ac.ac_if, m); return (NULL); decline: return (m); drop: m_freem(m); return (NULL); } const struct sysctl_bounded_args gre_vars[] = { { GRECTL_ALLOW, &gre_allow, 0, 1 }, { GRECTL_WCCP, &gre_wccp, 0, 1 }, }; int gre_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int error; NET_LOCK(); error = sysctl_bounded_arr(gre_vars, nitems(gre_vars), name, namelen, oldp, oldlenp, newp, newlen); NET_UNLOCK(); return error; } static inline int gre_ip_cmp(int af, const union gre_addr *a, const union gre_addr *b) { switch (af) { #ifdef INET6 case AF_INET6: return (memcmp(&a->in6, &b->in6, sizeof(a->in6))); #endif /* INET6 */ case AF_INET: return (memcmp(&a->in4, &b->in4, sizeof(a->in4))); default: unhandled_af(af); } return (0); } static int gre_cmp_src(const struct gre_tunnel *a, const struct gre_tunnel *b) { uint32_t ka, kb; uint32_t mask; int rv; /* is K set at all? */ ka = a->t_key_mask & GRE_KEY_ENTROPY; kb = b->t_key_mask & GRE_KEY_ENTROPY; /* sort by whether K is set */ if (ka > kb) return (1); if (ka < kb) return (-1); /* is K set on both? */ if (ka != GRE_KEY_NONE) { /* get common prefix */ mask = a->t_key_mask & b->t_key_mask; ka = a->t_key & mask; kb = b->t_key & mask; /* sort by common prefix */ if (ka > kb) return (1); if (ka < kb) return (-1); } /* sort by routing table */ if (a->t_rtableid > b->t_rtableid) return (1); if (a->t_rtableid < b->t_rtableid) return (-1); /* sort by address */ if (a->t_af > b->t_af) return (1); if (a->t_af < b->t_af) return (-1); rv = gre_ip_cmp(a->t_af, &a->t_src, &b->t_src); if (rv != 0) return (rv); return (0); } static int gre_cmp(const struct gre_tunnel *a, const struct gre_tunnel *b) { int rv; rv = gre_cmp_src(a, b); if (rv != 0) return (rv); return (gre_ip_cmp(a->t_af, &a->t_dst, &b->t_dst)); } static inline int mgre_cmp(const struct mgre_softc *a, const struct mgre_softc *b) { return (gre_cmp_src(&a->sc_tunnel, &b->sc_tunnel)); } RBT_GENERATE(mgre_tree, mgre_softc, sc_entry, mgre_cmp); static inline int egre_cmp(const struct egre_softc *a, const struct egre_softc *b) { return (gre_cmp(&a->sc_tunnel, &b->sc_tunnel)); } RBT_GENERATE(egre_tree, egre_softc, sc_entry, egre_cmp); static int nvgre_cmp_tunnel(const struct gre_tunnel *a, const struct gre_tunnel *b) { uint32_t ka, kb; ka = a->t_key & GRE_KEY_ENTROPY; kb = b->t_key & GRE_KEY_ENTROPY; /* sort by common prefix */ if (ka > kb) return (1); if (ka < kb) return (-1); /* sort by routing table */ if (a->t_rtableid > b->t_rtableid) return (1); if (a->t_rtableid < b->t_rtableid) return (-1); /* sort by address */ if (a->t_af > b->t_af) return (1); if (a->t_af < b->t_af) return (-1); return (0); } static inline int nvgre_cmp_ucast(const struct nvgre_softc *na, const struct nvgre_softc *nb) { const struct gre_tunnel *a = &na->sc_tunnel; const struct gre_tunnel *b = &nb->sc_tunnel; int rv; rv = nvgre_cmp_tunnel(a, b); if (rv != 0) return (rv); rv = gre_ip_cmp(a->t_af, &a->t_src, &b->t_src); if (rv != 0) return (rv); return (0); } static int nvgre_cmp_mcast(const struct gre_tunnel *a, const union gre_addr *aa, unsigned int if0idxa, const struct gre_tunnel *b, const union gre_addr *ab,unsigned int if0idxb) { int rv; rv = nvgre_cmp_tunnel(a, b); if (rv != 0) return (rv); rv = gre_ip_cmp(a->t_af, aa, ab); if (rv != 0) return (rv); if (if0idxa > if0idxb) return (1); if (if0idxa < if0idxb) return (-1); return (0); } static inline int nvgre_cmp_mcast_sc(const struct nvgre_softc *na, const struct nvgre_softc *nb) { const struct gre_tunnel *a = &na->sc_tunnel; const struct gre_tunnel *b = &nb->sc_tunnel; return (nvgre_cmp_mcast(a, &a->t_dst, na->sc_ifp0, b, &b->t_dst, nb->sc_ifp0)); } RBT_GENERATE(nvgre_ucast_tree, nvgre_softc, sc_uentry, nvgre_cmp_ucast); RBT_GENERATE(nvgre_mcast_tree, nvgre_softc, sc_mentry, nvgre_cmp_mcast_sc); static inline int eoip_cmp(const struct eoip_softc *ea, const struct eoip_softc *eb) { const struct gre_tunnel *a = &ea->sc_tunnel; const struct gre_tunnel *b = &eb->sc_tunnel; int rv; if (a->t_key > b->t_key) return (1); if (a->t_key < b->t_key) return (-1); /* sort by routing table */ if (a->t_rtableid > b->t_rtableid) return (1); if (a->t_rtableid < b->t_rtableid) return (-1); /* sort by address */ if (a->t_af > b->t_af) return (1); if (a->t_af < b->t_af) return (-1); rv = gre_ip_cmp(a->t_af, &a->t_src, &b->t_src); if (rv != 0) return (rv); rv = gre_ip_cmp(a->t_af, &a->t_dst, &b->t_dst); if (rv != 0) return (rv); return (0); } RBT_GENERATE(eoip_tree, eoip_softc, sc_entry, eoip_cmp); static int nvgre_eb_port_eq(void *arg, void *a, void *b) { struct nvgre_softc *sc = arg; return (gre_ip_cmp(sc->sc_tunnel.t_af, a, b) == 0); } static void * nvgre_eb_port_take(void *arg, void *port) { union gre_addr *ea = port; union gre_addr *endpoint; endpoint = pool_get(&nvgre_endpoint_pool, PR_NOWAIT); if (endpoint == NULL) return (NULL); *endpoint = *ea; return (endpoint); } static void nvgre_eb_port_rele(void *arg, void *port) { union gre_addr *endpoint = port; pool_put(&nvgre_endpoint_pool, endpoint); } static size_t nvgre_eb_port_ifname(void *arg, char *dst, size_t len, void *port) { struct nvgre_softc *sc = arg; return (strlcpy(dst, sc->sc_ac.ac_if.if_xname, len)); } static void nvgre_eb_port_sa(void *arg, struct sockaddr_storage *ss, void *port) { struct nvgre_softc *sc = arg; union gre_addr *endpoint = port; switch (sc->sc_tunnel.t_af) { case AF_INET: { struct sockaddr_in *sin = (struct sockaddr_in *)ss; sin->sin_len = sizeof(*sin); sin->sin_family = AF_INET; sin->sin_addr = endpoint->in4; break; } #ifdef INET6 case AF_INET6: { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ss; sin6->sin6_len = sizeof(*sin6); sin6->sin6_family = AF_INET6; in6_recoverscope(sin6, &endpoint->in6); break; } #endif /* INET6 */ default: unhandled_af(sc->sc_tunnel.t_af); } }
3 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 /* $OpenBSD: wd.c,v 1.130 2022/10/23 14:39:19 krw Exp $ */ /* $NetBSD: wd.c,v 1.193 1999/02/28 17:15:27 explorer Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /*- * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Charles M. Hannum and by Onno van der Linden. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #if 0 #include "rnd.h" #endif #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/conf.h> #include <sys/fcntl.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <sys/mutex.h> #include <sys/buf.h> #include <sys/uio.h> #include <sys/malloc.h> #include <sys/device.h> #include <sys/disklabel.h> #include <sys/disk.h> #include <sys/syslog.h> #include <sys/timeout.h> #include <sys/vnode.h> #include <sys/dkio.h> #include <sys/reboot.h> #include <machine/intr.h> #include <machine/bus.h> #include <dev/ata/atareg.h> #include <dev/ata/atavar.h> #include <dev/ata/wdvar.h> #include <dev/ic/wdcreg.h> #include <dev/ic/wdcvar.h> #if 0 #include "locators.h" #endif #define LBA48_THRESHOLD (0xfffffff) /* 128GB / DEV_BSIZE */ #define WDIORETRIES_SINGLE 4 /* number of retries before single-sector */ #define WDIORETRIES 5 /* number of retries before giving up */ #define RECOVERYTIME_MSEC 500 /* time to wait before retrying a cmd */ #define DEBUG_INTR 0x01 #define DEBUG_XFERS 0x02 #define DEBUG_STATUS 0x04 #define DEBUG_FUNCS 0x08 #define DEBUG_PROBE 0x10 #ifdef WDCDEBUG extern int wdcdebug_wd_mask; /* init'ed in ata_wdc.c */ #define WDCDEBUG_PRINT(args, level) do { \ if ((wdcdebug_wd_mask & (level)) != 0) \ printf args; \ } while (0) #else #define WDCDEBUG_PRINT(args, level) #endif #define sc_drive sc_wdc_bio.drive #define sc_mode sc_wdc_bio.mode #define sc_multi sc_wdc_bio.multi int wdprobe(struct device *, void *, void *); void wdattach(struct device *, struct device *, void *); int wddetach(struct device *, int); int wdactivate(struct device *, int); int wdprint(void *, char *); const struct cfattach wd_ca = { sizeof(struct wd_softc), wdprobe, wdattach, wddetach, wdactivate }; struct cfdriver wd_cd = { NULL, "wd", DV_DISK }; void wdgetdefaultlabel(struct wd_softc *, struct disklabel *); int wdgetdisklabel(dev_t dev, struct wd_softc *, struct disklabel *, int); void wdstrategy(struct buf *); void wdstart(void *); void __wdstart(struct wd_softc*, struct buf *); void wdrestart(void *); int wd_get_params(struct wd_softc *, u_int8_t, struct ataparams *); int wd_flushcache(struct wd_softc *, int); void wd_standby(struct wd_softc *, int); /* XXX: these should go elsewhere */ cdev_decl(wd); bdev_decl(wd); #define wdlookup(unit) (struct wd_softc *)disk_lookup(&wd_cd, (unit)) int wdprobe(struct device *parent, void *match_, void *aux) { struct ata_atapi_attach *aa_link = aux; struct cfdata *match = match_; if (aa_link == NULL) return 0; if (aa_link->aa_type != T_ATA) return 0; if (match->cf_loc[0] != -1 && match->cf_loc[0] != aa_link->aa_channel) return 0; if (match->cf_loc[1] != -1 && match->cf_loc[1] != aa_link->aa_drv_data->drive) return 0; return 1; } void wdattach(struct device *parent, struct device *self, void *aux) { struct wd_softc *wd = (void *)self; struct ata_atapi_attach *aa_link= aux; struct wdc_command wdc_c; int i, blank; char buf[41], c, *p, *q; WDCDEBUG_PRINT(("wdattach\n"), DEBUG_FUNCS | DEBUG_PROBE); wd->openings = aa_link->aa_openings; wd->drvp = aa_link->aa_drv_data; strlcpy(wd->drvp->drive_name, wd->sc_dev.dv_xname, sizeof(wd->drvp->drive_name)); wd->drvp->cf_flags = wd->sc_dev.dv_cfdata->cf_flags; if ((NERRS_MAX - 2) > 0) wd->drvp->n_dmaerrs = NERRS_MAX - 2; else wd->drvp->n_dmaerrs = 0; /* read our drive info */ if (wd_get_params(wd, at_poll, &wd->sc_params) != 0) { printf("%s: IDENTIFY failed\n", wd->sc_dev.dv_xname); return; } for (blank = 0, p = wd->sc_params.atap_model, q = buf, i = 0; i < sizeof(wd->sc_params.atap_model); i++) { c = *p++; if (c == '\0') break; if (c != ' ') { if (blank) { *q++ = ' '; blank = 0; } *q++ = c; } else blank = 1; } *q++ = '\0'; printf(": <%s>\n", buf); wdc_probe_caps(wd->drvp, &wd->sc_params); wdc_print_caps(wd->drvp); if ((wd->sc_params.atap_multi & 0xff) > 1) { wd->sc_multi = wd->sc_params.atap_multi & 0xff; } else { wd->sc_multi = 1; } printf("%s: %d-sector PIO,", wd->sc_dev.dv_xname, wd->sc_multi); /* use 48-bit LBA if enabled */ if ((wd->sc_params.atap_cmd2_en & ATAPI_CMD2_48AD) != 0) wd->sc_flags |= WDF_LBA48; /* Prior to ATA-4, LBA was optional. */ if ((wd->sc_params.atap_capabilities1 & WDC_CAP_LBA) != 0) wd->sc_flags |= WDF_LBA; #if 0 /* ATA-4 requires LBA. */ if (wd->sc_params.atap_ataversion != 0xffff && wd->sc_params.atap_ataversion >= WDC_VER_ATA4) wd->sc_flags |= WDF_LBA; #endif if ((wd->sc_flags & WDF_LBA48) != 0) { wd->sc_capacity = (((u_int64_t)wd->sc_params.atap_max_lba[3] << 48) | ((u_int64_t)wd->sc_params.atap_max_lba[2] << 32) | ((u_int64_t)wd->sc_params.atap_max_lba[1] << 16) | (u_int64_t)wd->sc_params.atap_max_lba[0]); printf(" LBA48, %lluMB, %llu sectors\n", wd->sc_capacity / (1048576 / DEV_BSIZE), wd->sc_capacity); } else if ((wd->sc_flags & WDF_LBA) != 0) { wd->sc_capacity = (wd->sc_params.atap_capacity[1] << 16) | wd->sc_params.atap_capacity[0]; printf(" LBA, %lluMB, %llu sectors\n", wd->sc_capacity / (1048576 / DEV_BSIZE), wd->sc_capacity); } else { wd->sc_capacity = wd->sc_params.atap_cylinders * wd->sc_params.atap_heads * wd->sc_params.atap_sectors; printf(" CHS, %lluMB, %d cyl, %d head, %d sec, %llu sectors\n", wd->sc_capacity / (1048576 / DEV_BSIZE), wd->sc_params.atap_cylinders, wd->sc_params.atap_heads, wd->sc_params.atap_sectors, wd->sc_capacity); } WDCDEBUG_PRINT(("%s: atap_dmatiming_mimi=%d, atap_dmatiming_recom=%d\n", self->dv_xname, wd->sc_params.atap_dmatiming_mimi, wd->sc_params.atap_dmatiming_recom), DEBUG_PROBE); /* use read look ahead if supported */ if (wd->sc_params.atap_cmd_set1 & WDC_CMD1_AHEAD) { bzero(&wdc_c, sizeof(struct wdc_command)); wdc_c.r_command = SET_FEATURES; wdc_c.r_features = WDSF_READAHEAD_EN; wdc_c.timeout = 1000; wdc_c.flags = at_poll; if (wdc_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) { printf("%s: enable look ahead command didn't " "complete\n", wd->sc_dev.dv_xname); } } /* use write cache if supported */ if (wd->sc_params.atap_cmd_set1 & WDC_CMD1_CACHE) { bzero(&wdc_c, sizeof(struct wdc_command)); wdc_c.r_command = SET_FEATURES; wdc_c.r_features = WDSF_EN_WR_CACHE; wdc_c.timeout = 1000; wdc_c.flags = at_poll; if (wdc_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) { printf("%s: enable write cache command didn't " "complete\n", wd->sc_dev.dv_xname); } } /* * FREEZE LOCK the drive so malicious users can't lock it on us. * As there is no harm in issuing this to drives that don't * support the security feature set we just send it, and don't * bother checking if the drive sends a command abort to tell us it * doesn't support it. */ bzero(&wdc_c, sizeof(struct wdc_command)); wdc_c.r_command = WDCC_SEC_FREEZE_LOCK; wdc_c.timeout = 1000; wdc_c.flags = at_poll; if (wdc_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) { printf("%s: freeze lock command didn't complete\n", wd->sc_dev.dv_xname); } /* * Initialize disk structures. */ wd->sc_dk.dk_name = wd->sc_dev.dv_xname; bufq_init(&wd->sc_bufq, BUFQ_DEFAULT); timeout_set(&wd->sc_restart_timeout, wdrestart, wd); /* Attach disk. */ disk_attach(&wd->sc_dev, &wd->sc_dk); wd->sc_wdc_bio.lp = wd->sc_dk.dk_label; } int wdactivate(struct device *self, int act) { struct wd_softc *wd = (void *)self; int rv = 0; switch (act) { case DVACT_SUSPEND: break; case DVACT_POWERDOWN: wd_flushcache(wd, AT_POLL); if (boothowto & RB_POWERDOWN) wd_standby(wd, AT_POLL); break; case DVACT_RESUME: /* * Do two resets separated by a small delay. The * first wakes the controller, the second resets * the channel. */ wdc_disable_intr(wd->drvp->chnl_softc); wdc_reset_channel(wd->drvp, 1); delay(10000); wdc_reset_channel(wd->drvp, 0); wdc_enable_intr(wd->drvp->chnl_softc); wd_get_params(wd, at_poll, &wd->sc_params); break; } return (rv); } int wddetach(struct device *self, int flags) { struct wd_softc *sc = (struct wd_softc *)self; timeout_del(&sc->sc_restart_timeout); bufq_drain(&sc->sc_bufq); disk_gone(wdopen, self->dv_unit); /* Detach disk. */ bufq_destroy(&sc->sc_bufq); disk_detach(&sc->sc_dk); return (0); } /* * Read/write routine for a buffer. Validates the arguments and schedules the * transfer. Does not wait for the transfer to complete. */ void wdstrategy(struct buf *bp) { struct wd_softc *wd; int s; wd = wdlookup(DISKUNIT(bp->b_dev)); if (wd == NULL) { bp->b_error = ENXIO; goto bad; } WDCDEBUG_PRINT(("wdstrategy (%s)\n", wd->sc_dev.dv_xname), DEBUG_XFERS); /* If device invalidated (e.g. media change, door open), error. */ if ((wd->sc_flags & WDF_LOADED) == 0) { bp->b_error = EIO; goto bad; } /* Validate the request. */ if (bounds_check_with_label(bp, wd->sc_dk.dk_label) == -1) goto done; /* Check that the number of sectors can fit in a byte. */ if ((bp->b_bcount / wd->sc_dk.dk_label->d_secsize) >= (1 << NBBY)) { bp->b_error = EINVAL; goto bad; } /* Queue transfer on drive, activate drive and controller if idle. */ bufq_queue(&wd->sc_bufq, bp); s = splbio(); wdstart(wd); splx(s); device_unref(&wd->sc_dev); return; bad: bp->b_flags |= B_ERROR; bp->b_resid = bp->b_bcount; done: s = splbio(); biodone(bp); splx(s); if (wd != NULL) device_unref(&wd->sc_dev); } /* * Queue a drive for I/O. */ void wdstart(void *arg) { struct wd_softc *wd = arg; struct buf *bp = NULL; WDCDEBUG_PRINT(("wdstart %s\n", wd->sc_dev.dv_xname), DEBUG_XFERS); while (wd->openings > 0) { /* Is there a buf for us ? */ if ((bp = bufq_dequeue(&wd->sc_bufq)) == NULL) return; /* * Make the command. First lock the device */ wd->openings--; wd->retries = 0; __wdstart(wd, bp); } } void __wdstart(struct wd_softc *wd, struct buf *bp) { struct disklabel *lp; u_int64_t nsecs; lp = wd->sc_dk.dk_label; wd->sc_wdc_bio.blkno = DL_BLKTOSEC(lp, bp->b_blkno + DL_SECTOBLK(lp, DL_GETPOFFSET(&lp->d_partitions[DISKPART(bp->b_dev)]))); wd->sc_wdc_bio.blkdone =0; wd->sc_bp = bp; /* * If we're retrying, retry in single-sector mode. This will give us * the sector number of the problem, and will eventually allow the * transfer to succeed. */ if (wd->retries >= WDIORETRIES_SINGLE) wd->sc_wdc_bio.flags = ATA_SINGLE; else wd->sc_wdc_bio.flags = 0; nsecs = howmany(bp->b_bcount, lp->d_secsize); if ((wd->sc_flags & WDF_LBA48) && /* use LBA48 only if really need */ ((wd->sc_wdc_bio.blkno + nsecs - 1 >= LBA48_THRESHOLD) || (nsecs > 0xff))) wd->sc_wdc_bio.flags |= ATA_LBA48; if (wd->sc_flags & WDF_LBA) wd->sc_wdc_bio.flags |= ATA_LBA; if (bp->b_flags & B_READ) wd->sc_wdc_bio.flags |= ATA_READ; wd->sc_wdc_bio.bcount = bp->b_bcount; wd->sc_wdc_bio.databuf = bp->b_data; wd->sc_wdc_bio.wd = wd; /* Instrumentation. */ disk_busy(&wd->sc_dk); switch (wdc_ata_bio(wd->drvp, &wd->sc_wdc_bio)) { case WDC_TRY_AGAIN: timeout_add_sec(&wd->sc_restart_timeout, 1); break; case WDC_QUEUED: break; case WDC_COMPLETE: /* * This code is never executed because we never set * the ATA_POLL flag above */ #if 0 if (wd->sc_wdc_bio.flags & ATA_POLL) wddone(wd); #endif break; default: panic("__wdstart: bad return code from wdc_ata_bio()"); } } void wddone(void *v) { struct wd_softc *wd = v; struct buf *bp = wd->sc_bp; char buf[256], *errbuf = buf; WDCDEBUG_PRINT(("wddone %s\n", wd->sc_dev.dv_xname), DEBUG_XFERS); bp->b_resid = wd->sc_wdc_bio.bcount; errbuf[0] = '\0'; switch (wd->sc_wdc_bio.error) { case ERR_NODEV: bp->b_flags |= B_ERROR; bp->b_error = ENXIO; break; case ERR_DMA: errbuf = "DMA error"; goto retry; case ERR_DF: errbuf = "device fault"; goto retry; case TIMEOUT: errbuf = "device timeout"; goto retry; case ERROR: /* Don't care about media change bits */ if (wd->sc_wdc_bio.r_error != 0 && (wd->sc_wdc_bio.r_error & ~(WDCE_MC | WDCE_MCR)) == 0) goto noerror; ata_perror(wd->drvp, wd->sc_wdc_bio.r_error, errbuf, sizeof buf); retry: /* Just reset and retry. Can we do more ? */ wdc_reset_channel(wd->drvp, 0); diskerr(bp, "wd", errbuf, LOG_PRINTF, wd->sc_wdc_bio.blkdone, wd->sc_dk.dk_label); if (wd->retries++ < WDIORETRIES) { printf(", retrying\n"); timeout_add_msec(&wd->sc_restart_timeout, RECOVERYTIME_MSEC); return; } printf("\n"); bp->b_flags |= B_ERROR; bp->b_error = EIO; break; case NOERROR: noerror: if ((wd->sc_wdc_bio.flags & ATA_CORR) || wd->retries > 0) printf("%s: soft error (corrected)\n", wd->sc_dev.dv_xname); } disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid), bp->b_blkno, (bp->b_flags & B_READ)); biodone(bp); wd->openings++; wdstart(wd); } void wdrestart(void *v) { struct wd_softc *wd = v; struct buf *bp = wd->sc_bp; struct channel_softc *chnl; int s; WDCDEBUG_PRINT(("wdrestart %s\n", wd->sc_dev.dv_xname), DEBUG_XFERS); chnl = (struct channel_softc *)(wd->drvp->chnl_softc); if (chnl->dying) return; s = splbio(); disk_unbusy(&wd->sc_dk, 0, 0, (bp->b_flags & B_READ)); __wdstart(v, bp); splx(s); } int wdread(dev_t dev, struct uio *uio, int flags) { WDCDEBUG_PRINT(("wdread\n"), DEBUG_XFERS); return (physio(wdstrategy, dev, B_READ, minphys, uio)); } int wdwrite(dev_t dev, struct uio *uio, int flags) { WDCDEBUG_PRINT(("wdwrite\n"), DEBUG_XFERS); return (physio(wdstrategy, dev, B_WRITE, minphys, uio)); } int wdopen(dev_t dev, int flag, int fmt, struct proc *p) { struct wd_softc *wd; struct channel_softc *chnl; int unit, part; int error; WDCDEBUG_PRINT(("wdopen\n"), DEBUG_FUNCS); unit = DISKUNIT(dev); wd = wdlookup(unit); if (wd == NULL) return ENXIO; chnl = (struct channel_softc *)(wd->drvp->chnl_softc); if (chnl->dying) return (ENXIO); /* * If this is the first open of this device, add a reference * to the adapter. */ if ((error = disk_lock(&wd->sc_dk)) != 0) goto bad4; if (wd->sc_dk.dk_openmask != 0) { /* * If any partition is open, but the disk has been invalidated, * disallow further opens. */ if ((wd->sc_flags & WDF_LOADED) == 0) { error = EIO; goto bad3; } } else { if ((wd->sc_flags & WDF_LOADED) == 0) { wd->sc_flags |= WDF_LOADED; /* Load the physical device parameters. */ wd_get_params(wd, AT_WAIT, &wd->sc_params); /* Load the partition info if not already loaded. */ if (wdgetdisklabel(dev, wd, wd->sc_dk.dk_label, 0) == EIO) { error = EIO; goto bad; } } } part = DISKPART(dev); if ((error = disk_openpart(&wd->sc_dk, part, fmt, 1)) != 0) goto bad; disk_unlock(&wd->sc_dk); device_unref(&wd->sc_dev); return 0; bad: if (wd->sc_dk.dk_openmask == 0) { } bad3: disk_unlock(&wd->sc_dk); bad4: device_unref(&wd->sc_dev); return error; } int wdclose(dev_t dev, int flag, int fmt, struct proc *p) { struct wd_softc *wd; int part = DISKPART(dev); wd = wdlookup(DISKUNIT(dev)); if (wd == NULL) return ENXIO; WDCDEBUG_PRINT(("wdclose\n"), DEBUG_FUNCS); disk_lock_nointr(&wd->sc_dk); disk_closepart(&wd->sc_dk, part, fmt); if (wd->sc_dk.dk_openmask == 0) { wd_flushcache(wd, AT_WAIT); /* XXXX Must wait for I/O to complete! */ } disk_unlock(&wd->sc_dk); device_unref(&wd->sc_dev); return (0); } void wdgetdefaultlabel(struct wd_softc *wd, struct disklabel *lp) { WDCDEBUG_PRINT(("wdgetdefaultlabel\n"), DEBUG_FUNCS); bzero(lp, sizeof(struct disklabel)); lp->d_secsize = DEV_BSIZE; DL_SETDSIZE(lp, wd->sc_capacity); lp->d_ntracks = wd->sc_params.atap_heads; lp->d_nsectors = wd->sc_params.atap_sectors; lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; lp->d_ncylinders = DL_GETDSIZE(lp) / lp->d_secpercyl; if (wd->drvp->ata_vers == -1) { lp->d_type = DTYPE_ST506; strncpy(lp->d_typename, "ST506/MFM/RLL", sizeof lp->d_typename); } else { lp->d_type = DTYPE_ESDI; strncpy(lp->d_typename, "ESDI/IDE disk", sizeof lp->d_typename); } /* XXX - user viscopy() like sd.c */ strncpy(lp->d_packname, wd->sc_params.atap_model, sizeof lp->d_packname); lp->d_version = 1; lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; lp->d_checksum = dkcksum(lp); } /* * Fabricate a default disk label, and try to read the correct one. */ int wdgetdisklabel(dev_t dev, struct wd_softc *wd, struct disklabel *lp, int spoofonly) { int error; WDCDEBUG_PRINT(("wdgetdisklabel\n"), DEBUG_FUNCS); wdgetdefaultlabel(wd, lp); if (wd->drvp->state > RECAL) wd->drvp->drive_flags |= DRIVE_RESET; error = readdisklabel(DISKLABELDEV(dev), wdstrategy, lp, spoofonly); if (wd->drvp->state > RECAL) wd->drvp->drive_flags |= DRIVE_RESET; return (error); } int wdioctl(dev_t dev, u_long xfer, caddr_t addr, int flag, struct proc *p) { struct wd_softc *wd; struct disklabel *lp; int error = 0; WDCDEBUG_PRINT(("wdioctl\n"), DEBUG_FUNCS); wd = wdlookup(DISKUNIT(dev)); if (wd == NULL) return ENXIO; if ((wd->sc_flags & WDF_LOADED) == 0) { error = EIO; goto exit; } switch (xfer) { case DIOCRLDINFO: lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK); wdgetdisklabel(dev, wd, lp, 0); bcopy(lp, wd->sc_dk.dk_label, sizeof(*lp)); free(lp, M_TEMP, sizeof(*lp)); goto exit; case DIOCGPDINFO: wdgetdisklabel(dev, wd, (struct disklabel *)addr, 1); goto exit; case DIOCGDINFO: *(struct disklabel *)addr = *(wd->sc_dk.dk_label); goto exit; case DIOCGPART: ((struct partinfo *)addr)->disklab = wd->sc_dk.dk_label; ((struct partinfo *)addr)->part = &wd->sc_dk.dk_label->d_partitions[DISKPART(dev)]; goto exit; case DIOCWDINFO: case DIOCSDINFO: if ((flag & FWRITE) == 0) { error = EBADF; goto exit; } if ((error = disk_lock(&wd->sc_dk)) != 0) goto exit; error = setdisklabel(wd->sc_dk.dk_label, (struct disklabel *)addr, wd->sc_dk.dk_openmask); if (error == 0) { if (wd->drvp->state > RECAL) wd->drvp->drive_flags |= DRIVE_RESET; if (xfer == DIOCWDINFO) error = writedisklabel(DISKLABELDEV(dev), wdstrategy, wd->sc_dk.dk_label); } disk_unlock(&wd->sc_dk); goto exit; case DIOCCACHESYNC: if ((flag & FWRITE) == 0) { error = EBADF; goto exit; } error = wd_flushcache(wd, AT_WAIT); goto exit; default: error = wdc_ioctl(wd->drvp, xfer, addr, flag, p); goto exit; } #ifdef DIAGNOSTIC panic("wdioctl: impossible"); #endif exit: device_unref(&wd->sc_dev); return (error); } #ifdef B_FORMAT int wdformat(struct buf *bp) { bp->b_flags |= B_FORMAT; return wdstrategy(bp); } #endif daddr_t wdsize(dev_t dev) { struct wd_softc *wd; struct disklabel *lp; int part, omask; daddr_t size; WDCDEBUG_PRINT(("wdsize\n"), DEBUG_FUNCS); wd = wdlookup(DISKUNIT(dev)); if (wd == NULL) return (-1); part = DISKPART(dev); omask = wd->sc_dk.dk_openmask & (1 << part); if (omask == 0 && wdopen(dev, 0, S_IFBLK, NULL) != 0) { size = -1; goto exit; } lp = wd->sc_dk.dk_label; size = DL_SECTOBLK(lp, DL_GETPSIZE(&lp->d_partitions[part])); if (omask == 0 && wdclose(dev, 0, S_IFBLK, NULL) != 0) size = -1; exit: device_unref(&wd->sc_dev); return (size); } /* #define WD_DUMP_NOT_TRUSTED if you just want to watch */ static int wddoingadump = 0; static int wddumprecalibrated = 0; static int wddumpmulti = 1; /* * Dump core after a system crash. */ int wddump(dev_t dev, daddr_t blkno, caddr_t va, size_t size) { struct wd_softc *wd; /* disk unit to do the I/O */ struct disklabel *lp; /* disk's disklabel */ int unit, part; int nblks; /* total number of sectors left to write */ int nwrt; /* sectors to write with current i/o. */ int err; char errbuf[256]; /* Check if recursive dump; if so, punt. */ if (wddoingadump) return EFAULT; wddoingadump = 1; unit = DISKUNIT(dev); wd = wdlookup(unit); if (wd == NULL) return ENXIO; part = DISKPART(dev); /* Make sure it was initialized. */ if (wd->drvp->state < READY) return ENXIO; /* Convert to disk sectors. Request must be a multiple of size. */ lp = wd->sc_dk.dk_label; if ((size % lp->d_secsize) != 0) return EFAULT; nblks = size / lp->d_secsize; blkno = blkno / (lp->d_secsize / DEV_BSIZE); /* Check transfer bounds against partition size. */ if ((blkno < 0) || ((blkno + nblks) > DL_GETPSIZE(&lp->d_partitions[part]))) return EINVAL; /* Offset block number to start of partition. */ blkno += DL_GETPOFFSET(&lp->d_partitions[part]); /* Recalibrate, if first dump transfer. */ if (wddumprecalibrated == 0) { wddumpmulti = wd->sc_multi; wddumprecalibrated = 1; wd->drvp->state = RECAL; } while (nblks > 0) { nwrt = min(nblks, wddumpmulti); wd->sc_wdc_bio.blkno = blkno; wd->sc_wdc_bio.flags = ATA_POLL; if (wd->sc_flags & WDF_LBA48) wd->sc_wdc_bio.flags |= ATA_LBA48; if (wd->sc_flags & WDF_LBA) wd->sc_wdc_bio.flags |= ATA_LBA; wd->sc_wdc_bio.bcount = nwrt * lp->d_secsize; wd->sc_wdc_bio.databuf = va; wd->sc_wdc_bio.wd = wd; #ifndef WD_DUMP_NOT_TRUSTED switch (wdc_ata_bio(wd->drvp, &wd->sc_wdc_bio)) { case WDC_TRY_AGAIN: panic("wddump: try again"); break; case WDC_QUEUED: panic("wddump: polled command has been queued"); break; case WDC_COMPLETE: break; } switch(wd->sc_wdc_bio.error) { case TIMEOUT: printf("wddump: device timed out"); err = EIO; break; case ERR_DF: printf("wddump: drive fault"); err = EIO; break; case ERR_DMA: printf("wddump: DMA error"); err = EIO; break; case ERROR: errbuf[0] = '\0'; ata_perror(wd->drvp, wd->sc_wdc_bio.r_error, errbuf, sizeof errbuf); printf("wddump: %s", errbuf); err = EIO; break; case NOERROR: err = 0; break; default: panic("wddump: unknown error type"); } if (err != 0) { printf("\n"); return err; } #else /* WD_DUMP_NOT_TRUSTED */ /* Let's just talk about this first... */ printf("wd%d: dump addr 0x%x, cylin %d, head %d, sector %d\n", unit, va, cylin, head, sector); delay(500 * 1000); /* half a second */ #endif /* update block count */ nblks -= nwrt; blkno += nwrt; va += nwrt * lp->d_secsize; } wddoingadump = 0; return 0; } int wd_get_params(struct wd_softc *wd, u_int8_t flags, struct ataparams *params) { switch (ata_get_params(wd->drvp, flags, params)) { case CMD_AGAIN: return 1; case CMD_ERR: /* If we already have drive parameters, reuse them. */ if (wd->sc_params.atap_cylinders != 0) { if (params != &wd->sc_params) bcopy(&wd->sc_params, params, sizeof(struct ataparams)); return 0; } /* * We `know' there's a drive here; just assume it's old. * This geometry is only used to read the MBR and print a * (false) attach message. */ bzero(params, sizeof(struct ataparams)); strncpy(params->atap_model, "ST506", sizeof params->atap_model); params->atap_config = ATA_CFG_FIXED; params->atap_cylinders = 1024; params->atap_heads = 8; params->atap_sectors = 17; params->atap_multi = 1; params->atap_capabilities1 = params->atap_capabilities2 = 0; wd->drvp->ata_vers = -1; /* Mark it as pre-ATA */ return 0; case CMD_OK: return 0; default: panic("wd_get_params: bad return code from ata_get_params"); /* NOTREACHED */ } } int wd_flushcache(struct wd_softc *wd, int flags) { struct wdc_command wdc_c; if (wd->drvp->ata_vers < 4) /* WDCC_FLUSHCACHE is here since ATA-4 */ return EIO; bzero(&wdc_c, sizeof(struct wdc_command)); wdc_c.r_command = (wd->sc_flags & WDF_LBA48 ? WDCC_FLUSHCACHE_EXT : WDCC_FLUSHCACHE); wdc_c.r_st_bmask = WDCS_DRDY; wdc_c.r_st_pmask = WDCS_DRDY; wdc_c.flags = flags; wdc_c.timeout = 30000; /* 30s timeout */ if (wdc_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) { printf("%s: flush cache command didn't complete\n", wd->sc_dev.dv_xname); return EIO; } if (wdc_c.flags & ERR_NODEV) return ENODEV; if (wdc_c.flags & AT_TIMEOU) { printf("%s: flush cache command timeout\n", wd->sc_dev.dv_xname); return EIO; } if (wdc_c.flags & AT_ERROR) { if (wdc_c.r_error == WDCE_ABRT) /* command not supported */ return ENODEV; printf("%s: flush cache command: error 0x%x\n", wd->sc_dev.dv_xname, wdc_c.r_error); return EIO; } if (wdc_c.flags & AT_DF) { printf("%s: flush cache command: drive fault\n", wd->sc_dev.dv_xname); return EIO; } return 0; } void wd_standby(struct wd_softc *wd, int flags) { struct wdc_command wdc_c; bzero(&wdc_c, sizeof(struct wdc_command)); wdc_c.r_command = WDCC_STANDBY_IMMED; wdc_c.r_st_bmask = WDCS_DRDY; wdc_c.r_st_pmask = WDCS_DRDY; wdc_c.flags = flags; wdc_c.timeout = 30000; /* 30s timeout */ if (wdc_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) { printf("%s: standby command didn't complete\n", wd->sc_dev.dv_xname); } if (wdc_c.flags & AT_TIMEOU) { printf("%s: standby command timeout\n", wd->sc_dev.dv_xname); } if (wdc_c.flags & AT_DF) { printf("%s: standby command: drive fault\n", wd->sc_dev.dv_xname); } /* * Ignore error register, it shouldn't report anything else * than COMMAND ABORTED, which means the device doesn't support * standby */ }
468 261 248 248 248 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 /* $OpenBSD: ffs_vfsops.c,v 1.198 2024/02/03 18:51:58 beck Exp $ */ /* $NetBSD: ffs_vfsops.c,v 1.19 1996/02/09 22:22:26 christos Exp $ */ /* * Copyright (c) 1989, 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ffs_vfsops.c 8.14 (Berkeley) 11/28/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/namei.h> #include <sys/proc.h> #include <sys/kernel.h> #include <sys/vnode.h> #include <sys/socket.h> #include <sys/mount.h> #include <sys/buf.h> #include <sys/mbuf.h> #include <sys/fcntl.h> #include <sys/ioctl.h> #include <sys/errno.h> #include <sys/malloc.h> #include <sys/sysctl.h> #include <sys/pool.h> #include <sys/dkio.h> #include <sys/disk.h> #include <sys/specdev.h> #include <ufs/ufs/quota.h> #include <ufs/ufs/ufsmount.h> #include <ufs/ufs/inode.h> #include <ufs/ufs/dir.h> #include <ufs/ufs/ufs_extern.h> #include <ufs/ufs/dirhash.h> #include <ufs/ffs/fs.h> #include <ufs/ffs/ffs_extern.h> #include <uvm/uvm_extern.h> int ffs_sbupdate(struct ufsmount *, int); int ffs_reload_vnode(struct vnode *, void *); int ffs_sync_vnode(struct vnode *, void *); int ffs_validate(struct fs *); void ffs1_compat_read(struct fs *, struct ufsmount *, daddr_t); void ffs1_compat_write(struct fs *, struct ufsmount *); const struct vfsops ffs_vfsops = { .vfs_mount = ffs_mount, .vfs_start = ufs_start, .vfs_unmount = ffs_unmount, .vfs_root = ufs_root, .vfs_quotactl = ufs_quotactl, .vfs_statfs = ffs_statfs, .vfs_sync = ffs_sync, .vfs_vget = ffs_vget, .vfs_fhtovp = ffs_fhtovp, .vfs_vptofh = ffs_vptofh, .vfs_init = ffs_init, .vfs_sysctl = ffs_sysctl, .vfs_checkexp = ufs_check_export, }; struct inode_vtbl ffs_vtbl = { .iv_truncate = ffs_truncate, .iv_update = ffs_update, .iv_inode_alloc = ffs_inode_alloc, .iv_inode_free = ffs_inode_free, .iv_buf_alloc = ffs_balloc, .iv_bufatoff = ffs_bufatoff }; int ffs_checkrange(struct mount *mp, uint32_t ino) { struct buf *bp; struct cg *cgp; struct fs *fs; struct ufsmount *ump; int cg, error; fs = VFSTOUFS(mp)->um_fs; if (ino < ROOTINO || ino >= fs->fs_ncg * fs->fs_ipg) return ESTALE; /* * Need to check if inode is initialized because ffsv2 does * lazy initialization and we can get here from nfs_fhtovp */ if (fs->fs_magic != FS_UFS2_MAGIC) return 0; cg = ino_to_cg(fs, ino); ump = VFSTOUFS(mp); error = bread(ump->um_devvp, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, &bp); if (error) return error; cgp = (struct cg *)bp->b_data; if (!cg_chkmagic(cgp)) { brelse(bp); return ESTALE; } brelse(bp); if (cg * fs->fs_ipg + cgp->cg_initediblk < ino) return ESTALE; return 0; } /* * Called by main() when ufs is going to be mounted as root. */ struct pool ffs_ino_pool; struct pool ffs_dinode1_pool; #ifdef FFS2 struct pool ffs_dinode2_pool; #endif int ffs_mountroot(void) { struct fs *fs; struct mount *mp; struct proc *p = curproc; /* XXX */ struct ufsmount *ump; int error; /* * Get vnodes for swapdev and rootdev. */ swapdev_vp = NULL; if ((error = bdevvp(swapdev, &swapdev_vp)) || (error = bdevvp(rootdev, &rootvp))) { printf("ffs_mountroot: can't setup bdevvp's\n"); if (swapdev_vp) vrele(swapdev_vp); return (error); } if ((error = vfs_rootmountalloc("ffs", "root_device", &mp)) != 0) { vrele(swapdev_vp); vrele(rootvp); return (error); } if ((error = ffs_mountfs(rootvp, mp, p)) != 0) { vfs_unbusy(mp); vfs_mount_free(mp); vrele(swapdev_vp); vrele(rootvp); return (error); } TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list); ump = VFSTOUFS(mp); fs = ump->um_fs; strlcpy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname, sizeof(fs->fs_fsmnt)); (void)ffs_statfs(mp, &mp->mnt_stat, p); vfs_unbusy(mp); inittodr(fs->fs_time); return (0); } /* * VFS Operations. * * mount system call */ int ffs_mount(struct mount *mp, const char *path, void *data, struct nameidata *ndp, struct proc *p) { struct vnode *devvp; struct ufs_args *args = data; struct ufsmount *ump = NULL; struct fs *fs; char fname[MNAMELEN]; char fspec[MNAMELEN]; int error = 0, flags; int ronly; /* * If updating, check whether changing from read-only to * read/write; if there is no device name, that's all we do. */ if (mp->mnt_flag & MNT_UPDATE) { ump = VFSTOUFS(mp); fs = ump->um_fs; devvp = ump->um_devvp; error = 0; ronly = fs->fs_ronly; if (ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { /* Flush any dirty data */ VFS_SYNC(mp, MNT_WAIT, 0, p->p_ucred, p); /* * Get rid of files open for writing. */ flags = WRITECLOSE; if (args == NULL) flags |= IGNORECLEAN; if (mp->mnt_flag & MNT_FORCE) flags |= FORCECLOSE; error = ffs_flushfiles(mp, flags, p); mp->mnt_flag |= MNT_RDONLY; ronly = 1; } if (!error && (mp->mnt_flag & MNT_RELOAD)) error = ffs_reload(mp, ndp->ni_cnd.cn_cred, p); if (error) goto error_1; if (ronly && (mp->mnt_flag & MNT_WANTRDWR)) { if (fs->fs_clean == 0) { if (mp->mnt_flag & MNT_FORCE) { printf( "WARNING: %s was not properly unmounted\n", fs->fs_fsmnt); } else { printf( "WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n", fs->fs_fsmnt); error = EROFS; goto error_1; } } fs->fs_contigdirs = malloc((u_long)fs->fs_ncg, M_UFSMNT, M_WAITOK|M_ZERO); ronly = 0; } if (args == NULL) goto success; if (args->fspec == NULL) { /* * Process export requests. */ error = vfs_export(mp, &ump->um_export, &args->export_info); if (error) goto error_1; else goto success; } } /* * Not an update, or updating the name: look up the name * and verify that it refers to a sensible block device. */ error = copyinstr(args->fspec, fspec, sizeof(fspec), NULL); if (error) goto error_1; if (disk_map(fspec, fname, MNAMELEN, DM_OPENBLCK) == -1) memcpy(fname, fspec, sizeof(fname)); NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fname, p); if ((error = namei(ndp)) != 0) goto error_1; devvp = ndp->ni_vp; if (devvp->v_type != VBLK) { error = ENOTBLK; goto error_2; } if (major(devvp->v_rdev) >= nblkdev) { error = ENXIO; goto error_2; } if (mp->mnt_flag & MNT_UPDATE) { /* * UPDATE * If it's not the same vnode, or at least the same device * then it's not correct. */ if (devvp != ump->um_devvp) { if (devvp->v_rdev == ump->um_devvp->v_rdev) { vrele(devvp); } else { error = EINVAL; /* needs translation */ } } else vrele(devvp); /* * Update device name only on success */ if (!error) { /* * Save "mounted from" info for mount point (NULL pad) */ memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN); strlcpy(mp->mnt_stat.f_mntfromname, fname, MNAMELEN); memset(mp->mnt_stat.f_mntfromspec, 0, MNAMELEN); strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN); } } else { /* * Since this is a new mount, we want the names for * the device and the mount point copied in. If an * error occurs, the mountpoint is discarded by the * upper level code. */ memset(mp->mnt_stat.f_mntonname, 0, MNAMELEN); strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN); memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN); strlcpy(mp->mnt_stat.f_mntfromname, fname, MNAMELEN); memset(mp->mnt_stat.f_mntfromspec, 0, MNAMELEN); strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN); error = ffs_mountfs(devvp, mp, p); } if (error) goto error_2; /* * Initialize FS stat information in mount struct; uses both * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname * * This code is common to root and non-root mounts */ if (args) memcpy(&mp->mnt_stat.mount_info.ufs_args, args, sizeof(*args)); VFS_STATFS(mp, &mp->mnt_stat, p); success: if (path && (mp->mnt_flag & MNT_UPDATE)) { /* Update clean flag after changing read-onlyness. */ fs = ump->um_fs; if (ronly != fs->fs_ronly) { fs->fs_ronly = ronly; fs->fs_clean = ronly && (fs->fs_flags & FS_UNCLEAN) == 0 ? 1 : 0; if (ronly) free(fs->fs_contigdirs, M_UFSMNT, fs->fs_ncg); } ffs_sbupdate(ump, MNT_WAIT); #if 0 if (ronly) { int force = 0; /* * Updating mount to readonly. Try a cache flush. * Ignore error because the ioctl may not be supported. */ VOP_IOCTL(ump->um_devvp, DIOCCACHESYNC, &force, FWRITE, FSCRED, p); } #endif } return (0); error_2: /* error with devvp held */ vrele (devvp); error_1: /* no state to back out */ return (error); } struct ffs_reload_args { struct fs *fs; struct proc *p; struct ucred *cred; struct vnode *devvp; }; int ffs_reload_vnode(struct vnode *vp, void *args) { struct ffs_reload_args *fra = args; struct inode *ip; struct buf *bp; int error; /* * Step 4: invalidate all inactive vnodes. */ if (vp->v_usecount == 0) { vgonel(vp, fra->p); return (0); } /* * Step 5: invalidate all cached file data. */ if (vget(vp, LK_EXCLUSIVE)) return (0); if (vinvalbuf(vp, 0, fra->cred, fra->p, 0, INFSLP)) panic("ffs_reload: dirty2"); /* * Step 6: re-read inode data for all active vnodes. */ ip = VTOI(vp); error = bread(fra->devvp, fsbtodb(fra->fs, ino_to_fsba(fra->fs, ip->i_number)), (int)fra->fs->fs_bsize, &bp); if (error) { brelse(bp); vput(vp); return (error); } if (fra->fs->fs_magic == FS_UFS1_MAGIC) *ip->i_din1 = *((struct ufs1_dinode *)bp->b_data + ino_to_fsbo(fra->fs, ip->i_number)); #ifdef FFS2 else *ip->i_din2 = *((struct ufs2_dinode *)bp->b_data + ino_to_fsbo(fra->fs, ip->i_number)); #endif /* FFS2 */ ip->i_effnlink = DIP(ip, nlink); brelse(bp); vput(vp); return (0); } /* * Reload all incore data for a filesystem (used after running fsck on * the root filesystem and finding things to fix). The filesystem must * be mounted read-only. * * Things to do to update the mount: * 1) invalidate all cached meta-data. * 2) re-read superblock from disk. * 3) re-read summary information from disk. * 4) invalidate all inactive vnodes. * 5) invalidate all cached file data. * 6) re-read inode data for all active vnodes. */ int ffs_reload(struct mount *mountp, struct ucred *cred, struct proc *p) { struct vnode *devvp; caddr_t space; struct fs *fs, *newfs; int i, blks, size, error; int32_t *lp; struct buf *bp = NULL; struct ffs_reload_args fra; if ((mountp->mnt_flag & MNT_RDONLY) == 0) return (EINVAL); /* * Step 1: invalidate all cached meta-data. */ devvp = VFSTOUFS(mountp)->um_devvp; vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); error = vinvalbuf(devvp, 0, cred, p, 0, INFSLP); VOP_UNLOCK(devvp); if (error) panic("ffs_reload: dirty1"); /* * Step 2: re-read superblock from disk. */ fs = VFSTOUFS(mountp)->um_fs; error = bread(devvp, fs->fs_sblockloc / DEV_BSIZE, SBSIZE, &bp); if (error) { brelse(bp); return (error); } newfs = (struct fs *)bp->b_data; if (ffs_validate(newfs) == 0) { brelse(bp); return (EINVAL); } /* * Copy pointer fields back into superblock before copying in XXX * new superblock. These should really be in the ufsmount. XXX * Note that important parameters (eg fs_ncg) are unchanged. */ newfs->fs_csp = fs->fs_csp; newfs->fs_maxcluster = fs->fs_maxcluster; newfs->fs_ronly = fs->fs_ronly; memcpy(fs, newfs, fs->fs_sbsize); if (fs->fs_sbsize < SBSIZE) bp->b_flags |= B_INVAL; brelse(bp); VFSTOUFS(mountp)->um_maxsymlinklen = fs->fs_maxsymlinklen; ffs1_compat_read(fs, VFSTOUFS(mountp), fs->fs_sblockloc); ffs_oldfscompat(fs); (void)ffs_statfs(mountp, &mountp->mnt_stat, p); /* * Step 3: re-read summary information from disk. */ blks = howmany(fs->fs_cssize, fs->fs_fsize); space = (caddr_t)fs->fs_csp; for (i = 0; i < blks; i += fs->fs_frag) { size = fs->fs_bsize; if (i + fs->fs_frag > blks) size = (blks - i) * fs->fs_fsize; error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, &bp); if (error) { brelse(bp); return (error); } memcpy(space, bp->b_data, size); space += size; brelse(bp); } /* * We no longer know anything about clusters per cylinder group. */ if (fs->fs_contigsumsize > 0) { lp = fs->fs_maxcluster; for (i = 0; i < fs->fs_ncg; i++) *lp++ = fs->fs_contigsumsize; } fra.p = p; fra.cred = cred; fra.fs = fs; fra.devvp = devvp; error = vfs_mount_foreach_vnode(mountp, ffs_reload_vnode, &fra); return (error); } /* * Checks if a super block is sane enough to be mounted. */ int ffs_validate(struct fs *fsp) { #ifdef FFS2 if (fsp->fs_magic != FS_UFS2_MAGIC && fsp->fs_magic != FS_UFS1_MAGIC) return (0); /* Invalid magic */ #else if (fsp->fs_magic != FS_UFS1_MAGIC) return (0); /* Invalid magic */ #endif /* FFS2 */ if ((u_int)fsp->fs_bsize > MAXBSIZE) return (0); /* Invalid block size */ if ((u_int)fsp->fs_bsize < sizeof(struct fs)) return (0); /* Invalid block size */ if ((u_int)fsp->fs_sbsize > SBSIZE) return (0); /* Invalid super block size */ if ((u_int)fsp->fs_frag > MAXFRAG || fragtbl[fsp->fs_frag] == NULL) return (0); /* Invalid number of fragments */ if (fsp->fs_inodefmt == FS_42INODEFMT) return (0); /* Obsolete format, support broken in 2014 */ if (fsp->fs_maxsymlinklen <= 0) return (0); /* Invalid max size of short symlink */ return (1); /* Super block is okay */ } /* * Possible locations for the super-block. */ const int sbtry[] = SBLOCKSEARCH; /* * Common code for mount and mountroot */ int ffs_mountfs(struct vnode *devvp, struct mount *mp, struct proc *p) { struct ufsmount *ump; struct buf *bp; struct fs *fs; dev_t dev; caddr_t space; daddr_t sbloc; int error, i, blks, size, ronly; int32_t *lp; struct ucred *cred; u_int64_t maxfilesize; /* XXX */ dev = devvp->v_rdev; cred = p ? p->p_ucred : NOCRED; /* * Disallow multiple mounts of the same device. * Disallow mounting of a device that is currently in use * (except for root, which might share swap device for miniroot). * Flush out any old buffers remaining from a previous use. */ if ((error = vfs_mountedon(devvp)) != 0) return (error); if (vcount(devvp) > 1 && devvp != rootvp) return (EBUSY); vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); error = vinvalbuf(devvp, V_SAVE, cred, p, 0, INFSLP); VOP_UNLOCK(devvp); if (error) return (error); ronly = (mp->mnt_flag & MNT_RDONLY) != 0; error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p); if (error) return (error); bp = NULL; ump = NULL; /* * Try reading the super-block in each of its possible locations. */ for (i = 0; sbtry[i] != -1; i++) { if (bp != NULL) { bp->b_flags |= B_NOCACHE; brelse(bp); bp = NULL; } error = bread(devvp, sbtry[i] / DEV_BSIZE, SBSIZE, &bp); if (error) goto out; fs = (struct fs *) bp->b_data; sbloc = sbtry[i]; /* * Do not look for an FFS1 file system at SBLOCK_UFS2. Doing so * will find the wrong super-block for file systems with 64k * block size. */ if (fs->fs_magic == FS_UFS1_MAGIC && sbloc == SBLOCK_UFS2) continue; if (ffs_validate(fs)) break; /* Super block validated */ } if (sbtry[i] == -1) { error = EINVAL; goto out; } fs->fs_fmod = 0; fs->fs_flags &= ~FS_UNCLEAN; if (fs->fs_clean == 0) { if (ronly || (mp->mnt_flag & MNT_FORCE)) { printf( "WARNING: %s was not properly unmounted\n", fs->fs_fsmnt); } else { printf( "WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n", fs->fs_fsmnt); error = EROFS; goto out; } } if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) { #ifndef SMALL_KERNEL printf("ffs_mountfs(): obsolete rotational table format, " "please use fsck_ffs(8) -c 1\n"); #endif error = EROFS; goto out; } ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK|M_ZERO); ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT, M_WAITOK); if (fs->fs_magic == FS_UFS1_MAGIC) ump->um_fstype = UM_UFS1; #ifdef FFS2 else ump->um_fstype = UM_UFS2; #endif memcpy(ump->um_fs, bp->b_data, fs->fs_sbsize); if (fs->fs_sbsize < SBSIZE) bp->b_flags |= B_INVAL; brelse(bp); bp = NULL; fs = ump->um_fs; ffs1_compat_read(fs, ump, sbloc); if (fs->fs_clean == 0) fs->fs_flags |= FS_UNCLEAN; fs->fs_ronly = ronly; size = fs->fs_cssize; blks = howmany(size, fs->fs_fsize); if (fs->fs_contigsumsize > 0) size += fs->fs_ncg * sizeof(int32_t); space = malloc((u_long)size, M_UFSMNT, M_WAITOK); fs->fs_csp = (struct csum *)space; for (i = 0; i < blks; i += fs->fs_frag) { size = fs->fs_bsize; if (i + fs->fs_frag > blks) size = (blks - i) * fs->fs_fsize; error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, &bp); if (error) { free(fs->fs_csp, M_UFSMNT, 0); goto out; } memcpy(space, bp->b_data, size); space += size; brelse(bp); bp = NULL; } if (fs->fs_contigsumsize > 0) { fs->fs_maxcluster = lp = (int32_t *)space; for (i = 0; i < fs->fs_ncg; i++) *lp++ = fs->fs_contigsumsize; } mp->mnt_data = ump; mp->mnt_stat.f_fsid.val[0] = (long)dev; /* Use on-disk fsid if it exists, else fake it */ if (fs->fs_id[0] != 0 && fs->fs_id[1] != 0) mp->mnt_stat.f_fsid.val[1] = fs->fs_id[1]; else mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; mp->mnt_stat.f_namemax = MAXNAMLEN; mp->mnt_flag |= MNT_LOCAL; ump->um_mountp = mp; ump->um_dev = dev; ump->um_devvp = devvp; ump->um_nindir = fs->fs_nindir; ump->um_bptrtodb = fs->fs_fsbtodb; ump->um_seqinc = fs->fs_frag; ump->um_maxsymlinklen = fs->fs_maxsymlinklen; for (i = 0; i < MAXQUOTAS; i++) ump->um_quotas[i] = NULLVP; devvp->v_specmountpoint = mp; ffs_oldfscompat(fs); if (ronly) fs->fs_contigdirs = NULL; else { fs->fs_contigdirs = malloc((u_long)fs->fs_ncg, M_UFSMNT, M_WAITOK|M_ZERO); } /* * Set FS local "last mounted on" information (NULL pad) */ memset(fs->fs_fsmnt, 0, sizeof(fs->fs_fsmnt)); strlcpy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname, sizeof(fs->fs_fsmnt)); #if 0 if (mp->mnt_flag & MNT_ROOTFS) { /* * Root mount; update timestamp in mount structure. * this will be used by the common root mount code * to update the system clock. */ mp->mnt_time = fs->fs_time; } #endif /* * XXX * Limit max file size. Even though ffs can handle files up to 16TB, * we do limit the max file to 2^31 pages to prevent overflow of * a 32-bit unsigned int. The buffer cache has its own checks but * a little added paranoia never hurts. */ ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX */ maxfilesize = FS_KERNMAXFILESIZE(PAGE_SIZE, fs); if (fs->fs_maxfilesize > maxfilesize) /* XXX */ fs->fs_maxfilesize = maxfilesize; /* XXX */ if (ronly == 0) { fs->fs_fmod = 1; fs->fs_clean = 0; error = ffs_sbupdate(ump, MNT_WAIT); if (error == EROFS) goto out; } return (0); out: if (devvp->v_specinfo) devvp->v_specmountpoint = NULL; if (bp) brelse(bp); vn_lock(devvp, LK_EXCLUSIVE|LK_RETRY); (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p); VOP_UNLOCK(devvp); if (ump) { free(ump->um_fs, M_UFSMNT, ump->um_fs->fs_sbsize); free(ump, M_UFSMNT, sizeof(*ump)); mp->mnt_data = NULL; } return (error); } /* * Sanity checks for old file systems. */ int ffs_oldfscompat(struct fs *fs) { int i; fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */ fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */ if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ fs->fs_nrpos = 8; /* XXX */ if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ u_int64_t sizepb = fs->fs_bsize; /* XXX */ /* XXX */ fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */ for (i = 0; i < NIADDR; i++) { /* XXX */ sizepb *= NINDIR(fs); /* XXX */ fs->fs_maxfilesize += sizepb; /* XXX */ } /* XXX */ fs->fs_qbmask = ~fs->fs_bmask; /* XXX */ fs->fs_qfmask = ~fs->fs_fmask; /* XXX */ } /* XXX */ if (fs->fs_avgfilesize <= 0) /* XXX */ fs->fs_avgfilesize = AVFILESIZ; /* XXX */ if (fs->fs_avgfpdir <= 0) /* XXX */ fs->fs_avgfpdir = AFPDIR; /* XXX */ return (0); } /* * Auxiliary function for reading FFS1 super blocks. */ void ffs1_compat_read(struct fs *fs, struct ufsmount *ump, daddr_t sbloc) { if (fs->fs_magic == FS_UFS2_MAGIC) return; /* UFS2 */ #if 0 if (fs->fs_ffs1_flags & FS_FLAGS_UPDATED) return; /* Already updated */ #endif fs->fs_flags = fs->fs_ffs1_flags; fs->fs_sblockloc = sbloc; fs->fs_maxbsize = fs->fs_bsize; fs->fs_time = fs->fs_ffs1_time; fs->fs_size = fs->fs_ffs1_size; fs->fs_dsize = fs->fs_ffs1_dsize; fs->fs_csaddr = fs->fs_ffs1_csaddr; fs->fs_cstotal.cs_ndir = fs->fs_ffs1_cstotal.cs_ndir; fs->fs_cstotal.cs_nbfree = fs->fs_ffs1_cstotal.cs_nbfree; fs->fs_cstotal.cs_nifree = fs->fs_ffs1_cstotal.cs_nifree; fs->fs_cstotal.cs_nffree = fs->fs_ffs1_cstotal.cs_nffree; fs->fs_ffs1_flags |= FS_FLAGS_UPDATED; } /* * Auxiliary function for writing FFS1 super blocks. */ void ffs1_compat_write(struct fs *fs, struct ufsmount *ump) { if (fs->fs_magic != FS_UFS1_MAGIC) return; /* UFS2 */ fs->fs_ffs1_time = fs->fs_time; fs->fs_ffs1_cstotal.cs_ndir = fs->fs_cstotal.cs_ndir; fs->fs_ffs1_cstotal.cs_nbfree = fs->fs_cstotal.cs_nbfree; fs->fs_ffs1_cstotal.cs_nifree = fs->fs_cstotal.cs_nifree; fs->fs_ffs1_cstotal.cs_nffree = fs->fs_cstotal.cs_nffree; } /* * unmount system call */ int ffs_unmount(struct mount *mp, int mntflags, struct proc *p) { struct ufsmount *ump; struct fs *fs; int error, flags; flags = 0; if (mntflags & MNT_FORCE) flags |= FORCECLOSE; ump = VFSTOUFS(mp); fs = ump->um_fs; error = ffs_flushfiles(mp, flags, p); if (error != 0) return (error); if (fs->fs_ronly == 0) { fs->fs_clean = (fs->fs_flags & FS_UNCLEAN) ? 0 : 1; error = ffs_sbupdate(ump, MNT_WAIT); /* ignore write errors if mounted RW on read-only device */ if (error && error != EROFS) { fs->fs_clean = 0; return (error); } free(fs->fs_contigdirs, M_UFSMNT, fs->fs_ncg); } ump->um_devvp->v_specmountpoint = NULL; vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY); vinvalbuf(ump->um_devvp, V_SAVE, NOCRED, p, 0, INFSLP); (void)VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE, NOCRED, p); vput(ump->um_devvp); free(fs->fs_csp, M_UFSMNT, 0); free(fs, M_UFSMNT, fs->fs_sbsize); free(ump, M_UFSMNT, sizeof(*ump)); mp->mnt_data = NULL; mp->mnt_flag &= ~MNT_LOCAL; return (0); } /* * Flush out all the files in a filesystem. */ int ffs_flushfiles(struct mount *mp, int flags, struct proc *p) { struct ufsmount *ump; int error; ump = VFSTOUFS(mp); if (mp->mnt_flag & MNT_QUOTA) { int i; if ((error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) != 0) return (error); for (i = 0; i < MAXQUOTAS; i++) { if (ump->um_quotas[i] == NULLVP) continue; quotaoff(p, mp, i); } /* * Here we fall through to vflush again to ensure * that we have gotten rid of all the system vnodes. */ } /* * Flush all the files. */ if ((error = vflush(mp, NULL, flags)) != 0) return (error); /* * Flush filesystem metadata. */ vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY); error = VOP_FSYNC(ump->um_devvp, p->p_ucred, MNT_WAIT, p); VOP_UNLOCK(ump->um_devvp); return (error); } /* * Get file system statistics. */ int ffs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p) { struct ufsmount *ump; struct fs *fs; ump = VFSTOUFS(mp); fs = ump->um_fs; #ifdef FFS2 if (fs->fs_magic != FS_MAGIC && fs->fs_magic != FS_UFS2_MAGIC) panic("ffs_statfs"); #else if (fs->fs_magic != FS_MAGIC) panic("ffs_statfs"); #endif /* FFS2 */ sbp->f_bsize = fs->fs_fsize; sbp->f_iosize = fs->fs_bsize; sbp->f_blocks = fs->fs_dsize; sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + fs->fs_cstotal.cs_nffree; sbp->f_bavail = sbp->f_bfree - ((int64_t)fs->fs_dsize * fs->fs_minfree / 100); sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO; sbp->f_ffree = fs->fs_cstotal.cs_nifree; sbp->f_favail = sbp->f_ffree; copy_statfs_info(sbp, mp); return (0); } struct ffs_sync_args { int allerror; struct proc *p; int waitfor; int nlink0; int inflight; struct ucred *cred; }; int ffs_sync_vnode(struct vnode *vp, void *arg) { struct ffs_sync_args *fsa = arg; struct inode *ip; int error, nlink0 = 0; int s, skip = 0; if (vp->v_type == VNON) return (0); ip = VTOI(vp); /* * If unmounting or converting rw to ro, then stop deferring * timestamp writes. */ if (fsa->waitfor == MNT_WAIT && (ip->i_flag & IN_LAZYMOD)) { ip->i_flag |= IN_MODIFIED; UFS_UPDATE(ip, 1); } if (ip->i_effnlink == 0) nlink0 = 1; s = splbio(); if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 && LIST_EMPTY(&vp->v_dirtyblkhd)) { skip = 1; } splx(s); if (skip) goto end; if (vget(vp, LK_EXCLUSIVE | LK_NOWAIT)) { fsa->inflight = MIN(fsa->inflight+1, 65536); goto end; } if ((error = VOP_FSYNC(vp, fsa->cred, fsa->waitfor, fsa->p))) fsa->allerror = error; VOP_UNLOCK(vp); vrele(vp); end: fsa->nlink0 = MIN(fsa->nlink0 + nlink0, 65536); return (0); } /* * Go through the disk queues to initiate sandbagged IO; * go through the inodes to write those that have been modified; * initiate the writing of the super block if it has been modified. * * Should always be called with the mount point locked. */ int ffs_sync(struct mount *mp, int waitfor, int stall, struct ucred *cred, struct proc *p) { struct ufsmount *ump = VFSTOUFS(mp); struct fs *fs; int error, allerror = 0, clean, fmod; struct ffs_sync_args fsa; fs = ump->um_fs; /* * Write back modified superblock. * Consistency check that the superblock * is still in the buffer cache. */ if (fs->fs_fmod != 0 && fs->fs_ronly != 0) { printf("fs = %s\n", fs->fs_fsmnt); panic("update: rofs mod"); } /* * Write back each (modified) inode. */ fsa.allerror = 0; fsa.p = p; fsa.cred = cred; fsa.waitfor = waitfor; fsa.nlink0 = 0; fsa.inflight = 0; /* * Don't traverse the vnode list if we want to skip all of them. */ if (waitfor != MNT_LAZY) { vfs_mount_foreach_vnode(mp, ffs_sync_vnode, &fsa); allerror = fsa.allerror; } /* * Force stale file system control information to be flushed. */ if (waitfor != MNT_LAZY) { vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY); if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0) allerror = error; VOP_UNLOCK(ump->um_devvp); } qsync(mp); /* * Write back modified superblock. */ clean = fs->fs_clean; fmod = fs->fs_fmod; if (stall && fs->fs_ronly == 0) { fs->fs_fmod = 1; if (allerror == 0 && fsa.nlink0 == 0 && fsa.inflight == 0) { fs->fs_clean = (fs->fs_flags & FS_UNCLEAN) ? 0 : 1; #if 0 printf("%s force clean (dangling %d inflight %d)\n", mp->mnt_stat.f_mntonname, fsa.nlink0, fsa.inflight); #endif } else { fs->fs_clean = 0; #if 0 printf("%s force dirty (dangling %d inflight %d)\n", mp->mnt_stat.f_mntonname, fsa.nlink0, fsa.inflight); #endif } } if (fs->fs_fmod != 0 && (error = ffs_sbupdate(ump, waitfor)) != 0) allerror = error; fs->fs_clean = clean; fs->fs_fmod = fmod; return (allerror); } /* * Look up a FFS dinode number to find its incore vnode, otherwise read it * in from disk. If it is in core, wait for the lock bit to clear, then * return the inode locked. Detection and handling of mount points must be * done by the calling routine. */ int ffs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) { struct fs *fs; struct inode *ip; struct ufs1_dinode *dp1; #ifdef FFS2 struct ufs2_dinode *dp2; #endif struct ufsmount *ump; struct buf *bp; struct vnode *vp; dev_t dev; int error; if (ino > (ufsino_t)-1) panic("ffs_vget: alien ino_t %llu", (unsigned long long)ino); ump = VFSTOUFS(mp); dev = ump->um_dev; retry: if ((*vpp = ufs_ihashget(dev, ino)) != NULL) return (0); /* Allocate a new vnode/inode. */ if ((error = getnewvnode(VT_UFS, mp, &ffs_vops, &vp)) != 0) { *vpp = NULL; return (error); } #ifdef VFSLCKDEBUG vp->v_flag |= VLOCKSWORK; #endif ip = pool_get(&ffs_ino_pool, PR_WAITOK|PR_ZERO); rrw_init_flags(&ip->i_lock, "inode", RWL_DUPOK | RWL_IS_VNODE); ip->i_ump = ump; vref(ip->i_devvp); vp->v_data = ip; ip->i_vnode = vp; ip->i_fs = fs = ump->um_fs; ip->i_dev = dev; ip->i_number = ino; ip->i_vtbl = &ffs_vtbl; /* * Put it onto its hash chain and lock it so that other requests for * this inode will block if they arrive while we are sleeping waiting * for old data structures to be purged or for the contents of the * disk portion of this inode to be read. */ error = ufs_ihashins(ip); if (error) { /* * VOP_INACTIVE will treat this as a stale file * and recycle it quickly */ vrele(vp); if (error == EEXIST) goto retry; return (error); } /* Read in the disk contents for the inode, copy into the inode. */ error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)), (int)fs->fs_bsize, &bp); if (error) { /* * The inode does not contain anything useful, so it would * be misleading to leave it on its hash chain. With mode * still zero, it will be unlinked and returned to the free * list by vput(). */ vput(vp); brelse(bp); *vpp = NULL; return (error); } #ifdef FFS2 if (ip->i_ump->um_fstype == UM_UFS2) { ip->i_din2 = pool_get(&ffs_dinode2_pool, PR_WAITOK); dp2 = (struct ufs2_dinode *) bp->b_data + ino_to_fsbo(fs, ino); *ip->i_din2 = *dp2; } else #endif { ip->i_din1 = pool_get(&ffs_dinode1_pool, PR_WAITOK); dp1 = (struct ufs1_dinode *) bp->b_data + ino_to_fsbo(fs, ino); *ip->i_din1 = *dp1; } brelse(bp); ip->i_effnlink = DIP(ip, nlink); /* * Initialize the vnode from the inode, check for aliases. * Note that the underlying vnode may have changed. */ if ((error = ffs_vinit(mp, &vp)) != 0) { vput(vp); *vpp = NULL; return (error); } /* * Set up a generation number for this inode if it does not * already have one. This should only happen on old filesystems. */ if (DIP(ip, gen) == 0) { while (DIP(ip, gen) == 0) DIP_ASSIGN(ip, gen, arc4random()); if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) ip->i_flag |= IN_MODIFIED; } /* * Ensure that uid and gid are correct. This is a temporary * fix until fsck has been changed to do the update. */ if (fs->fs_magic == FS_UFS1_MAGIC && fs->fs_inodefmt < FS_44INODEFMT) { ip->i_ffs1_uid = ip->i_din1->di_ouid; ip->i_ffs1_gid = ip->i_din1->di_ogid; } *vpp = vp; return (0); } /* * File handle to vnode * * Have to be really careful about stale file handles. */ int ffs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) { struct ufid *ufhp; int error; ufhp = (struct ufid *)fhp; if (ufhp->ufid_len != sizeof(*ufhp)) return EINVAL; if ((error = ffs_checkrange(mp, ufhp->ufid_ino)) != 0) return error; return (ufs_fhtovp(mp, ufhp, vpp)); } /* * Vnode pointer to File handle */ int ffs_vptofh(struct vnode *vp, struct fid *fhp) { struct inode *ip; struct ufid *ufhp; ip = VTOI(vp); ufhp = (struct ufid *)fhp; ufhp->ufid_len = sizeof(struct ufid); ufhp->ufid_ino = ip->i_number; ufhp->ufid_gen = DIP(ip, gen); return (0); } /* * Write a superblock and associated information back to disk. */ int ffs_sbupdate(struct ufsmount *mp, int waitfor) { struct fs *dfs, *fs = mp->um_fs; struct buf *bp; int blks; caddr_t space; int i, size, error, allerror = 0; /* * First write back the summary information. */ blks = howmany(fs->fs_cssize, fs->fs_fsize); space = (caddr_t)fs->fs_csp; for (i = 0; i < blks; i += fs->fs_frag) { size = fs->fs_bsize; if (i + fs->fs_frag > blks) size = (blks - i) * fs->fs_fsize; bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 0, INFSLP); memcpy(bp->b_data, space, size); space += size; if (waitfor != MNT_WAIT) bawrite(bp); else if ((error = bwrite(bp))) allerror = error; } /* * Now write back the superblock itself. If any errors occurred * up to this point, then fail so that the superblock avoids * being written out as clean. */ if (allerror) { return (allerror); } bp = getblk(mp->um_devvp, fs->fs_sblockloc >> (fs->fs_fshift - fs->fs_fsbtodb), (int)fs->fs_sbsize, 0, INFSLP); fs->fs_fmod = 0; fs->fs_time = gettime(); memcpy(bp->b_data, fs, fs->fs_sbsize); /* Restore compatibility to old file systems. XXX */ dfs = (struct fs *)bp->b_data; /* XXX */ if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ dfs->fs_nrpos = -1; /* XXX */ if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ int32_t *lp, tmp; /* XXX */ /* XXX */ lp = (int32_t *)&dfs->fs_qbmask; /* XXX */ tmp = lp[4]; /* XXX */ for (i = 4; i > 0; i--) /* XXX */ lp[i] = lp[i-1]; /* XXX */ lp[0] = tmp; /* XXX */ } /* XXX */ dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */ ffs1_compat_write(dfs, mp); if (waitfor != MNT_WAIT) bawrite(bp); else if ((error = bwrite(bp))) allerror = error; return (allerror); } int ffs_init(struct vfsconf *vfsp) { static int done; if (done) return (0); done = 1; pool_init(&ffs_ino_pool, sizeof(struct inode), 0, IPL_NONE, PR_WAITOK, "ffsino", NULL); pool_init(&ffs_dinode1_pool, sizeof(struct ufs1_dinode), 0, IPL_NONE, PR_WAITOK, "dino1pl", NULL); #ifdef FFS2 pool_init(&ffs_dinode2_pool, sizeof(struct ufs2_dinode), 0, IPL_NONE, PR_WAITOK, "dino2pl", NULL); #endif return (ufs_init(vfsp)); } const struct sysctl_bounded_args ffs_vars[] = { #ifdef UFS_DIRHASH { FFS_DIRHASH_DIRSIZE, &ufs_mindirhashsize, 0, INT_MAX }, { FFS_DIRHASH_MAXMEM, &ufs_dirhashmaxmem, 0, INT_MAX }, { FFS_DIRHASH_MEM, &ufs_dirhashmem, SYSCTL_INT_READONLY }, #endif }; /* * fast filesystem related variables. */ int ffs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { return sysctl_bounded_arr(ffs_vars, nitems(ffs_vars), name, namelen, oldp, oldlenp, newp, newlen); }
1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 /* $OpenBSD: gpio.c,v 1.17 2022/04/11 14:30:05 visa Exp $ */ /* * Copyright (c) 2008 Marc Balmer <mbalmer@openbsd.org> * Copyright (c) 2004, 2006 Alexander Yurchenko <grange@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * General Purpose Input/Output framework. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/conf.h> #include <sys/device.h> #include <sys/fcntl.h> #include <sys/ioctl.h> #include <sys/gpio.h> #include <sys/vnode.h> #include <sys/malloc.h> #include <sys/queue.h> #include <dev/gpio/gpiovar.h> struct gpio_softc { struct device sc_dev; gpio_chipset_tag_t sc_gc; /* GPIO controller */ gpio_pin_t *sc_pins; /* pins array */ int sc_npins; /* number of pins */ int sc_opened; LIST_HEAD(, gpio_dev) sc_devs; /* devices */ LIST_HEAD(, gpio_name) sc_names; /* named pins */ }; int gpio_match(struct device *, void *, void *); int gpio_submatch(struct device *, void *, void *); void gpio_attach(struct device *, struct device *, void *); int gpio_detach(struct device *, int); int gpio_search(struct device *, void *, void *); int gpio_print(void *, const char *); int gpio_pinbyname(struct gpio_softc *, char *gp_name); int gpio_ioctl(struct gpio_softc *, u_long, caddr_t, int); const struct cfattach gpio_ca = { sizeof (struct gpio_softc), gpio_match, gpio_attach, gpio_detach }; struct cfdriver gpio_cd = { NULL, "gpio", DV_DULL }; int gpio_match(struct device *parent, void *match, void *aux) { struct cfdata *cf = match; struct gpiobus_attach_args *gba = aux; return (strcmp(gba->gba_name, cf->cf_driver->cd_name) == 0); } int gpio_submatch(struct device *parent, void *match, void *aux) { struct cfdata *cf = match; struct gpio_attach_args *ga = aux; if (strcmp(ga->ga_dvname, cf->cf_driver->cd_name) != 0) return (0); return ((*cf->cf_attach->ca_match)(parent, match, aux)); } void gpio_attach(struct device *parent, struct device *self, void *aux) { struct gpio_softc *sc = (struct gpio_softc *)self; struct gpiobus_attach_args *gba = aux; sc->sc_gc = gba->gba_gc; sc->sc_pins = gba->gba_pins; sc->sc_npins = gba->gba_npins; printf(": %d pins\n", sc->sc_npins); /* * Attach all devices that can be connected to the GPIO pins * described in the kernel configuration file. */ config_search(gpio_search, self, sc); } int gpio_detach(struct device *self, int flags) { int maj, mn; /* Locate the major number */ for (maj = 0; maj < nchrdev; maj++) if (cdevsw[maj].d_open == gpioopen) break; /* Nuke the vnodes for any open instances (calls close) */ mn = self->dv_unit; vdevgone(maj, mn, mn, VCHR); return (0); } int gpio_search(struct device *parent, void *arg, void *aux) { struct cfdata *cf = arg; struct gpio_attach_args ga; ga.ga_gpio = aux; ga.ga_offset = cf->cf_loc[0]; ga.ga_mask = cf->cf_loc[1]; ga.ga_flags = cf->cf_loc[2]; if (cf->cf_attach->ca_match(parent, cf, &ga) > 0) config_attach(parent, cf, &ga, gpio_print); return (0); } int gpio_print(void *aux, const char *pnp) { struct gpio_attach_args *ga = aux; int i; printf(" pins"); for (i = 0; i < 32; i++) if (ga->ga_mask & (1 << i)) printf(" %d", ga->ga_offset + i); return (UNCONF); } int gpiobus_print(void *aux, const char *pnp) { struct gpiobus_attach_args *gba = aux; if (pnp != NULL) printf("%s at %s", gba->gba_name, pnp); return (UNCONF); } int gpio_pin_map(void *gpio, int offset, u_int32_t mask, struct gpio_pinmap *map) { struct gpio_softc *sc = gpio; int npins, pin, i; npins = gpio_npins(mask); if (npins > sc->sc_npins) return (1); for (npins = 0, i = 0; i < 32; i++) if (mask & (1 << i)) { pin = offset + i; if (pin < 0 || pin >= sc->sc_npins) return (1); if (sc->sc_pins[pin].pin_mapped) return (1); sc->sc_pins[pin].pin_mapped = 1; map->pm_map[npins++] = pin; } map->pm_size = npins; return (0); } void gpio_pin_unmap(void *gpio, struct gpio_pinmap *map) { struct gpio_softc *sc = gpio; int pin, i; for (i = 0; i < map->pm_size; i++) { pin = map->pm_map[i]; sc->sc_pins[pin].pin_mapped = 0; } } int gpio_pin_read(void *gpio, struct gpio_pinmap *map, int pin) { struct gpio_softc *sc = gpio; return (gpiobus_pin_read(sc->sc_gc, map->pm_map[pin])); } void gpio_pin_write(void *gpio, struct gpio_pinmap *map, int pin, int value) { struct gpio_softc *sc = gpio; return (gpiobus_pin_write(sc->sc_gc, map->pm_map[pin], value)); } void gpio_pin_ctl(void *gpio, struct gpio_pinmap *map, int pin, int flags) { struct gpio_softc *sc = gpio; return (gpiobus_pin_ctl(sc->sc_gc, map->pm_map[pin], flags)); } int gpio_pin_caps(void *gpio, struct gpio_pinmap *map, int pin) { struct gpio_softc *sc = gpio; return (sc->sc_pins[map->pm_map[pin]].pin_caps); } int gpio_npins(u_int32_t mask) { int npins, i; for (npins = 0, i = 0; i < 32; i++) if (mask & (1 << i)) npins++; return (npins); } int gpioopen(dev_t dev, int flag, int mode, struct proc *p) { struct gpio_softc *sc; int error = 0; sc = (struct gpio_softc *)device_lookup(&gpio_cd, minor(dev)); if (sc == NULL) return (ENXIO); if (sc->sc_opened) error = EBUSY; else sc->sc_opened = 1; device_unref(&sc->sc_dev); return (error); } int gpioclose(dev_t dev, int flag, int mode, struct proc *p) { struct gpio_softc *sc; sc = (struct gpio_softc *)device_lookup(&gpio_cd, minor(dev)); if (sc == NULL) return (ENXIO); sc->sc_opened = 0; device_unref(&sc->sc_dev); return (0); } int gpio_pinbyname(struct gpio_softc *sc, char *gp_name) { struct gpio_name *nm; LIST_FOREACH(nm, &sc->sc_names, gp_next) if (!strcmp(nm->gp_name, gp_name)) return (nm->gp_pin); return (-1); } int gpio_ioctl(struct gpio_softc *sc, u_long cmd, caddr_t data, int flag) { gpio_chipset_tag_t gc; struct gpio_info *info; struct gpio_pin_op *op; struct gpio_attach *attach; struct gpio_attach_args ga; struct gpio_dev *gdev; struct gpio_name *nm; struct gpio_pin_set *set; struct device *dv; int pin, value, flags, npins, found; gc = sc->sc_gc; switch (cmd) { case GPIOINFO: info = (struct gpio_info *)data; if (securelevel < 1) info->gpio_npins = sc->sc_npins; else { for (pin = npins = 0; pin < sc->sc_npins; pin++) if (sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) ++npins; info->gpio_npins = npins; } break; case GPIOPINREAD: op = (struct gpio_pin_op *)data; if (op->gp_name[0] != '\0') { pin = gpio_pinbyname(sc, op->gp_name); if (pin == -1) return (EINVAL); } else pin = op->gp_pin; if (pin < 0 || pin >= sc->sc_npins) return (EINVAL); if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) && securelevel > 0) return (EPERM); /* return read value */ op->gp_value = gpiobus_pin_read(gc, pin); break; case GPIOPINWRITE: if ((flag & FWRITE) == 0) return (EBADF); op = (struct gpio_pin_op *)data; if (op->gp_name[0] != '\0') { pin = gpio_pinbyname(sc, op->gp_name); if (pin == -1) return (EINVAL); } else pin = op->gp_pin; if (pin < 0 || pin >= sc->sc_npins) return (EINVAL); if (sc->sc_pins[pin].pin_mapped) return (EBUSY); if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) && securelevel > 0) return (EPERM); value = op->gp_value; if (value != GPIO_PIN_LOW && value != GPIO_PIN_HIGH) return (EINVAL); gpiobus_pin_write(gc, pin, value); /* return old value */ op->gp_value = sc->sc_pins[pin].pin_state; /* update current value */ sc->sc_pins[pin].pin_state = value; break; case GPIOPINTOGGLE: if ((flag & FWRITE) == 0) return (EBADF); op = (struct gpio_pin_op *)data; if (op->gp_name[0] != '\0') { pin = gpio_pinbyname(sc, op->gp_name); if (pin == -1) return (EINVAL); } else pin = op->gp_pin; if (pin < 0 || pin >= sc->sc_npins) return (EINVAL); if (sc->sc_pins[pin].pin_mapped) return (EBUSY); if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) && securelevel > 0) return (EPERM); value = (sc->sc_pins[pin].pin_state == GPIO_PIN_LOW ? GPIO_PIN_HIGH : GPIO_PIN_LOW); gpiobus_pin_write(gc, pin, value); /* return old value */ op->gp_value = sc->sc_pins[pin].pin_state; /* update current value */ sc->sc_pins[pin].pin_state = value; break; case GPIOATTACH: if (securelevel > 0) return (EPERM); attach = (struct gpio_attach *)data; bzero(&ga, sizeof(ga)); ga.ga_gpio = sc; ga.ga_dvname = attach->ga_dvname; ga.ga_offset = attach->ga_offset; ga.ga_mask = attach->ga_mask; ga.ga_flags = attach->ga_flags; dv = config_found_sm((struct device *)sc, &ga, gpiobus_print, gpio_submatch); if (dv != NULL) { gdev = malloc(sizeof(*gdev), M_DEVBUF, M_WAITOK); gdev->sc_dev = dv; LIST_INSERT_HEAD(&sc->sc_devs, gdev, sc_next); } break; case GPIODETACH: if (securelevel > 0) return (EPERM); attach = (struct gpio_attach *)data; LIST_FOREACH(gdev, &sc->sc_devs, sc_next) { if (strcmp(gdev->sc_dev->dv_xname, attach->ga_dvname) == 0) { if (config_detach(gdev->sc_dev, 0) == 0) { LIST_REMOVE(gdev, sc_next); free(gdev, M_DEVBUF, sizeof(*gdev)); } break; } } break; case GPIOPINSET: if (securelevel > 0) return (EPERM); set = (struct gpio_pin_set *)data; if (set->gp_name[0] != '\0') { pin = gpio_pinbyname(sc, set->gp_name); if (pin == -1) return (EINVAL); } else pin = set->gp_pin; if (pin < 0 || pin >= sc->sc_npins) return (EINVAL); flags = set->gp_flags; /* check that the controller supports all requested flags */ if ((flags & sc->sc_pins[pin].pin_caps) != flags) return (ENODEV); flags = set->gp_flags | GPIO_PIN_SET; set->gp_caps = sc->sc_pins[pin].pin_caps; /* return old value */ set->gp_flags = sc->sc_pins[pin].pin_flags; if (flags > 0) { gpiobus_pin_ctl(gc, pin, flags); /* update current value */ sc->sc_pins[pin].pin_flags = flags; } /* rename pin or new pin? */ if (set->gp_name2[0] != '\0') { found = 0; LIST_FOREACH(nm, &sc->sc_names, gp_next) if (nm->gp_pin == pin) { strlcpy(nm->gp_name, set->gp_name2, sizeof(nm->gp_name)); found = 1; break; } if (!found) { nm = malloc(sizeof(*nm), M_DEVBUF, M_WAITOK); strlcpy(nm->gp_name, set->gp_name2, sizeof(nm->gp_name)); nm->gp_pin = set->gp_pin; LIST_INSERT_HEAD(&sc->sc_names, nm, gp_next); } } break; case GPIOPINUNSET: if (securelevel > 0) return (EPERM); set = (struct gpio_pin_set *)data; if (set->gp_name[0] != '\0') { pin = gpio_pinbyname(sc, set->gp_name); if (pin == -1) return (EINVAL); } else pin = set->gp_pin; if (pin < 0 || pin >= sc->sc_npins) return (EINVAL); if (sc->sc_pins[pin].pin_mapped) return (EBUSY); if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET)) return (EINVAL); LIST_FOREACH(nm, &sc->sc_names, gp_next) { if (nm->gp_pin == pin) { LIST_REMOVE(nm, gp_next); free(nm, M_DEVBUF, sizeof(*nm)); break; } } sc->sc_pins[pin].pin_flags &= ~GPIO_PIN_SET; break; default: return (ENOTTY); } return (0); } int gpioioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { struct gpio_softc *sc; int error; sc = (struct gpio_softc *)device_lookup(&gpio_cd, minor(dev)); if (sc == NULL) return (ENXIO); error = gpio_ioctl(sc, cmd, data, flag); device_unref(&sc->sc_dev); return (error); }
3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 /* $OpenBSD: uvm_map.h,v 1.89 2024/04/02 08:39:17 deraadt Exp $ */ /* $NetBSD: uvm_map.h,v 1.24 2001/02/18 21:19:08 chs Exp $ */ /* * Copyright (c) 2011 Ariane van der Steldt <ariane@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * * Copyright (c) 1997 Charles D. Cranor and Washington University. * Copyright (c) 1991, 1993, The Regents of the University of California. * * All rights reserved. * * This code is derived from software contributed to Berkeley by * The Mach Operating System project at Carnegie-Mellon University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)vm_map.h 8.3 (Berkeley) 3/15/94 * from: Id: uvm_map.h,v 1.1.2.3 1998/02/07 01:16:55 chs Exp * * * Copyright (c) 1987, 1990 Carnegie-Mellon University. * All rights reserved. * * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ #ifndef _UVM_UVM_MAP_H_ #define _UVM_UVM_MAP_H_ #include <sys/mutex.h> #include <sys/rwlock.h> #ifdef _KERNEL /* * UVM_MAP_CLIP_START: ensure that the entry begins at or after * the starting address, if it doesn't we split the entry. * * => map must be locked by caller */ #define UVM_MAP_CLIP_START(_map, _entry, _addr) \ do { \ KASSERT((_entry)->end + (_entry)->fspace > (_addr)); \ if ((_entry)->start < (_addr)) \ uvm_map_clip_start((_map), (_entry), (_addr)); \ } while (0) /* * UVM_MAP_CLIP_END: ensure that the entry ends at or before * the ending address, if it doesn't we split the entry. * * => map must be locked by caller */ #define UVM_MAP_CLIP_END(_map, _entry, _addr) \ do { \ KASSERT((_entry)->start < (_addr)); \ if ((_entry)->end > (_addr)) \ uvm_map_clip_end((_map), (_entry), (_addr)); \ } while (0) /* * extract flags */ #define UVM_EXTRACT_FIXPROT 0x8 /* set prot to maxprot as we go */ #endif /* _KERNEL */ #include <uvm/uvm_anon.h> /* * Address map entries consist of start and end addresses, * a VM object (or sharing map) and offset into that object, * and user-exported inheritance and protection information. * Also included is control information for virtual copy operations. */ struct vm_map_entry { union { RBT_ENTRY(vm_map_entry) addr_entry; /* address tree */ SLIST_ENTRY(vm_map_entry) addr_kentry; } daddrs; union { RBT_ENTRY(vm_map_entry) rbtree; /* Link freespace tree. */ TAILQ_ENTRY(vm_map_entry) tailq;/* Link freespace queue. */ TAILQ_ENTRY(vm_map_entry) deadq;/* dead entry queue */ } dfree; #define uvm_map_entry_start_copy start vaddr_t start; /* start address */ vaddr_t end; /* end address */ vsize_t guard; /* bytes in guard */ vsize_t fspace; /* free space */ union { struct uvm_object *uvm_obj; /* uvm object */ struct vm_map *sub_map; /* belongs to another map */ } object; /* object I point to */ voff_t offset; /* offset into object */ struct vm_aref aref; /* anonymous overlay */ int etype; /* entry type */ vm_prot_t protection; /* protection code */ vm_prot_t max_protection; /* maximum protection */ vm_inherit_t inheritance; /* inheritance */ int wired_count; /* can be paged if == 0 */ int advice; /* madvise advice */ #define uvm_map_entry_stop_copy flags u_int8_t flags; /* flags */ #define UVM_MAP_STATIC 0x01 /* static map entry */ #define UVM_MAP_KMEM 0x02 /* from kmem entry pool */ vsize_t fspace_augment; /* max(fspace) in subtree */ }; #define VM_MAPENT_ISWIRED(entry) ((entry)->wired_count != 0) TAILQ_HEAD(uvm_map_deadq, vm_map_entry); /* dead entry queue */ RBT_HEAD(uvm_map_addr, vm_map_entry); #ifdef _KERNEL RBT_PROTOTYPE(uvm_map_addr, vm_map_entry, daddrs.addr_entry, uvm_mapentry_addrcmp); #endif /* * A Map is a rbtree of map entries, kept sorted by address. * In addition, free space entries are also kept in a rbtree, * indexed by free size. * * * * LOCKING PROTOCOL NOTES: * ----------------------- * * VM map locking is a little complicated. There are both shared * and exclusive locks on maps. However, it is sometimes required * to unlock a VM map (to prevent lock ordering issues) without * allowing any other thread to modify it. * * In order to prevent this scenario, we introduce the notion of * a `busy' map. A `busy' map is unlocked, but other threads * attempting to write-lock wait for this flag to clear before * entering the lock manager. A map may only be marked busy * when the map is write-locked and may only be marked unbusy by * the thread which marked it busy. * * Access to the map `flags' member is controlled by the `flags_lock' * simple lock. Note that some flags are static (set once at map * creation time, and never changed), and thus require no locking * to check those flags. All flags which are r/w must be set or * cleared while the `flags_lock' is asserted. Additional locking * requirements are: * * VM_MAP_PAGEABLE r/o static flag; no locking required * * VM_MAP_INTRSAFE r/o static flag; no locking required * * VM_MAP_WIREFUTURE r/w; may only be set or cleared when * map is write-locked. may be tested * without asserting `flags_lock'. * * VM_MAP_BUSY r/w; may only be set when map is * write-locked, may only be cleared by * thread which set it, map read-locked * or write-locked. must be tested * while `flags_lock' is asserted. * * VM_MAP_WANTLOCK r/w; may only be set when the map * is busy, and thread is attempting * to write-lock. must be tested * while `flags_lock' is asserted. * * VM_MAP_GUARDPAGES r/o; must be specified at map * initialization time. * If set, guards will appear between * automatic allocations. * No locking required. * * VM_MAP_ISVMSPACE r/o; set by uvmspace_alloc. * Signifies that this map is a vmspace. * (The implementation treats all maps * without this bit as kernel maps.) * No locking required. * * * All automatic allocations (uvm_map without MAP_FIXED) will allocate * from vm_map.free. * If that allocation fails: * - vmspace maps will spill over into vm_map.bfree, * - all other maps will call uvm_map_kmem_grow() to increase the arena. * * vmspace maps have their data, brk() and stack arenas automatically * updated when uvm_map() is invoked without MAP_FIXED. * The spill over arena (vm_map.bfree) will contain the space in the brk() * and stack ranges. * Kernel maps never have a bfree arena and this tree will always be empty. * * * read_locks and write_locks are used in lock debugging code. * * Locks used to protect struct members in this file: * a atomic operations * I immutable after creation or exec(2) * v `vm_map_lock' (this map `lock' or `mtx') */ struct vm_map { struct pmap *pmap; /* [I] Physical map */ u_long sserial; /* [v] # stack changes */ struct uvm_map_addr addr; /* [v] Entry tree, by addr */ vsize_t size; /* virtual size */ int ref_count; /* [a] Reference count */ int flags; /* flags */ unsigned int timestamp; /* Version number */ struct proc *busy; /* [v] thread holding map busy*/ vaddr_t min_offset; /* [I] First address in map. */ vaddr_t max_offset; /* [I] Last address in map. */ /* * Allocation overflow regions. */ vaddr_t b_start; /* [v] Start for brk() alloc. */ vaddr_t b_end; /* [v] End for brk() alloc. */ vaddr_t s_start; /* [v] Start for stack alloc. */ vaddr_t s_end; /* [v] End for stack alloc. */ /* * Special address selectors. * * The uaddr_exe mapping is used if: * - protX is selected * - the pointer is not NULL * * If uaddr_exe is not used, the other mappings are checked in * order of appearance. * If a hint is given, the selection will only be used if the hint * falls in the range described by the mapping. * * The states are pointers because: * - they may not all be in use * - the struct size for different schemes is variable * * The uaddr_brk_stack selector will select addresses that are in * the brk/stack area of the map. */ struct uvm_addr_state *uaddr_exe; /* Executable selector. */ struct uvm_addr_state *uaddr_any[4]; /* More selectors. */ struct uvm_addr_state *uaddr_brk_stack; /* Brk/stack selector. */ #define UVM_MAP_CHECK_COPYIN_MAX 4 /* main, sigtramp, ld.so, libc.so */ struct uvm_check_copyin { vaddr_t start, end; } check_copyin[UVM_MAP_CHECK_COPYIN_MAX]; int check_copyin_count; /* * XXX struct mutex changes size because of compile options, so * place after fields which are inspected by libkvm / procmap(8) */ struct rwlock lock; /* Non-intrsafe lock */ struct mutex mtx; /* Intrsafe lock */ struct mutex flags_lock; /* flags lock */ }; /* vm_map flags */ #define VM_MAP_PAGEABLE 0x01 /* ro: entries are pageable */ #define VM_MAP_INTRSAFE 0x02 /* ro: interrupt safe map */ #define VM_MAP_WIREFUTURE 0x04 /* rw: wire future mappings */ #define VM_MAP_BUSY 0x08 /* rw: map is busy */ #define VM_MAP_WANTLOCK 0x10 /* rw: want to write-lock */ #define VM_MAP_GUARDPAGES 0x20 /* rw: add guard pgs to map */ #define VM_MAP_ISVMSPACE 0x40 /* ro: map is a vmspace */ #define VM_MAP_PINSYSCALL_ONCE 0x100 /* rw: pinsyscall done */ /* Number of kernel maps and entries to statically allocate */ #define MAX_KMAPENT 1024 /* Sufficient to make it to the scheduler. */ #ifdef _KERNEL /* * globals: */ extern vaddr_t uvm_maxkaddr; /* * protos: the following prototypes define the interface to vm_map */ void uvm_map_deallocate(struct vm_map *); int uvm_map_clean(struct vm_map *, vaddr_t, vaddr_t, int); void uvm_map_clip_start(struct vm_map *, struct vm_map_entry *, vaddr_t); void uvm_map_clip_end(struct vm_map *, struct vm_map_entry *, vaddr_t); int uvm_map_extract(struct vm_map *, vaddr_t, vsize_t, vaddr_t *, int); struct vm_map * uvm_map_create(pmap_t, vaddr_t, vaddr_t, int); vaddr_t uvm_map_pie(vaddr_t); vaddr_t uvm_map_hint(struct vmspace *, vm_prot_t, vaddr_t, vaddr_t); int uvm_map_check_copyin_add(struct vm_map *, vaddr_t, vaddr_t); int uvm_map_immutable(struct vm_map *, vaddr_t, vaddr_t, int); int uvm_map_inherit(struct vm_map *, vaddr_t, vaddr_t, vm_inherit_t); int uvm_map_advice(struct vm_map *, vaddr_t, vaddr_t, int); void uvm_map_init(void); boolean_t uvm_map_lookup_entry(struct vm_map *, vaddr_t, vm_map_entry_t *); boolean_t uvm_map_is_stack_remappable(struct vm_map *, vaddr_t, vsize_t, int); int uvm_map_remap_as_stack(struct proc *, vaddr_t, vsize_t); int uvm_map_replace(struct vm_map *, vaddr_t, vaddr_t, vm_map_entry_t, int); int uvm_map_reserve(struct vm_map *, vsize_t, vaddr_t, vsize_t, vaddr_t *); void uvm_map_setup(struct vm_map *, pmap_t, vaddr_t, vaddr_t, int); int uvm_map_submap(struct vm_map *, vaddr_t, vaddr_t, struct vm_map *); void uvm_unmap(struct vm_map *, vaddr_t, vaddr_t); void uvm_unmap_detach(struct uvm_map_deadq *, int); int uvm_unmap_remove(struct vm_map*, vaddr_t, vaddr_t, struct uvm_map_deadq *, boolean_t, boolean_t, boolean_t); void uvm_map_set_uaddr(struct vm_map*, struct uvm_addr_state**, struct uvm_addr_state*); int uvm_map_mquery(struct vm_map*, vaddr_t*, vsize_t, voff_t, int); struct p_inentry; int uvm_map_inentry_sp(vm_map_entry_t); boolean_t uvm_map_inentry(struct proc *, struct p_inentry *, vaddr_t addr, const char *fmt, int (*fn)(vm_map_entry_t), u_long serial); struct kinfo_vmentry; int uvm_map_fill_vmmap(struct vm_map *, struct kinfo_vmentry *, size_t *); /* * VM map locking operations: * * These operations perform locking on the data portion of the * map. * * vm_map_lock_try: try to lock a map, failing if it is already locked. * * vm_map_lock: acquire an exclusive (write) lock on a map. * * vm_map_lock_read: acquire a shared (read) lock on a map. * * vm_map_unlock: release an exclusive lock on a map. * * vm_map_unlock_read: release a shared lock on a map. * * vm_map_busy: mark a map as busy. * * vm_map_unbusy: clear busy status on a map. * */ boolean_t vm_map_lock_try_ln(struct vm_map*, char*, int); void vm_map_lock_ln(struct vm_map*, char*, int); void vm_map_lock_read_ln(struct vm_map*, char*, int); void vm_map_unlock_ln(struct vm_map*, char*, int); void vm_map_unlock_read_ln(struct vm_map*, char*, int); void vm_map_busy_ln(struct vm_map*, char*, int); void vm_map_unbusy_ln(struct vm_map*, char*, int); void vm_map_assert_anylock_ln(struct vm_map*, char*, int); void vm_map_assert_wrlock_ln(struct vm_map*, char*, int); #ifdef DIAGNOSTIC #define vm_map_lock_try(map) vm_map_lock_try_ln(map, __FILE__, __LINE__) #define vm_map_lock(map) vm_map_lock_ln(map, __FILE__, __LINE__) #define vm_map_lock_read(map) vm_map_lock_read_ln(map, __FILE__, __LINE__) #define vm_map_unlock(map) vm_map_unlock_ln(map, __FILE__, __LINE__) #define vm_map_unlock_read(map) vm_map_unlock_read_ln(map, __FILE__, __LINE__) #define vm_map_busy(map) vm_map_busy_ln(map, __FILE__, __LINE__) #define vm_map_unbusy(map) vm_map_unbusy_ln(map, __FILE__, __LINE__) #define vm_map_assert_anylock(map) \ vm_map_assert_anylock_ln(map, __FILE__, __LINE__) #define vm_map_assert_wrlock(map) \ vm_map_assert_wrlock_ln(map, __FILE__, __LINE__) #else #define vm_map_lock_try(map) vm_map_lock_try_ln(map, NULL, 0) #define vm_map_lock(map) vm_map_lock_ln(map, NULL, 0) #define vm_map_lock_read(map) vm_map_lock_read_ln(map, NULL, 0) #define vm_map_unlock(map) vm_map_unlock_ln(map, NULL, 0) #define vm_map_unlock_read(map) vm_map_unlock_read_ln(map, NULL, 0) #define vm_map_busy(map) vm_map_busy_ln(map, NULL, 0) #define vm_map_unbusy(map) vm_map_unbusy_ln(map, NULL, 0) #define vm_map_assert_anylock(map) vm_map_assert_anylock_ln(map, NULL, 0) #define vm_map_assert_wrlock(map) vm_map_assert_wrlock_ln(map, NULL, 0) #endif void uvm_map_lock_entry(struct vm_map_entry *); void uvm_map_unlock_entry(struct vm_map_entry *); #endif /* _KERNEL */ /* * Functions implemented as macros */ #define vm_map_min(map) ((map)->min_offset) #define vm_map_max(map) ((map)->max_offset) #define vm_map_pmap(map) ((map)->pmap) #endif /* _UVM_UVM_MAP_H_ */
3 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 /* $OpenBSD: if_ppp.c,v 1.118 2024/02/28 16:08:34 denis Exp $ */ /* $NetBSD: if_ppp.c,v 1.39 1997/05/17 21:11:59 christos Exp $ */ /* * if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver. * * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The name "Carnegie Mellon University" must not be used to * endorse or promote products derived from this software without * prior written permission. For permission or any legal * details, please contact * Office of Technology Transfer * Carnegie Mellon University * 5000 Forbes Avenue * Pittsburgh, PA 15213-3890 * (412) 268-4387, fax: (412) 268-7395 * tech-transfer@andrew.cmu.edu * * 4. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by Computing Services * at Carnegie Mellon University (http://www.cmu.edu/computing/)." * * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Based on: * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89 * * Copyright (c) 1987, 1989, 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Serial Line interface * * Rick Adams * Center for Seismic Studies * 1300 N 17th Street, Suite 1450 * Arlington, Virginia 22209 * (703)276-7900 * rick@seismo.ARPA * seismo!rick * * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris). * Converted to 4.3BSD Beta by Chris Torek. * Other changes made at Berkeley, based in part on code by Kirk Smith. * * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com) * Added VJ tcp header compression; more unified ioctls * * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au). * Cleaned up a lot of the mbuf-related code to fix bugs that * caused system crashes and packet corruption. Changed pppstart * so that it doesn't just give up with a collision if the whole * packet doesn't fit in the output ring buffer. * * Added priority queueing for interactive IP packets, following * the model of if_sl.c, plus hooks for bpf. * Paul Mackerras (paulus@cs.anu.edu.au). */ /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */ /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */ #include "ppp.h" #if NPPP > 0 #define VJC #define PPP_COMPRESS #include <sys/param.h> #include <sys/proc.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <sys/kernel.h> #include <sys/systm.h> #include <sys/time.h> #include <sys/malloc.h> #include <net/if.h> #include <net/if_var.h> #include <net/if_types.h> #include <net/netisr.h> #include <net/route.h> #include <net/bpf.h> #include <netinet/in.h> #include <netinet/ip.h> #include "bpfilter.h" #ifdef VJC #include <net/slcompress.h> #endif #include <net/ppp_defs.h> #include <net/if_ppp.h> #include <net/if_pppvar.h> #ifdef PPP_COMPRESS #define PACKETPTR struct mbuf * #include <net/ppp-comp.h> #endif static int pppsioctl(struct ifnet *, u_long, caddr_t); static void ppp_requeue(struct ppp_softc *); static void ppp_ccp(struct ppp_softc *, struct mbuf *m, int rcvd); static void ppp_ccp_closed(struct ppp_softc *); static void ppp_inproc(struct ppp_softc *, struct mbuf *); static void pppdumpm(struct mbuf *m0); static void ppp_ifstart(struct ifnet *ifp); int ppp_clone_create(struct if_clone *, int); int ppp_clone_destroy(struct ifnet *); void ppp_pkt_list_init(struct ppp_pkt_list *, u_int); int ppp_pkt_enqueue(struct ppp_pkt_list *, struct ppp_pkt *); struct ppp_pkt *ppp_pkt_dequeue(struct ppp_pkt_list *); struct mbuf *ppp_pkt_mbuf(struct ppp_pkt *); /* * We steal two bits in the mbuf m_flags, to mark high-priority packets * for output, and received packets following lost/corrupted packets. */ #define M_ERRMARK M_LINK0 /* steal a bit in mbuf m_flags */ #ifdef PPP_COMPRESS /* * List of compressors we know about. */ extern struct compressor ppp_bsd_compress; extern struct compressor ppp_deflate, ppp_deflate_draft; struct compressor *ppp_compressors[] = { #if DO_BSD_COMPRESS && defined(PPP_BSDCOMP) &ppp_bsd_compress, #endif #if DO_DEFLATE && defined(PPP_DEFLATE) &ppp_deflate, &ppp_deflate_draft, #endif NULL }; #endif /* PPP_COMPRESS */ LIST_HEAD(, ppp_softc) ppp_softc_list; struct if_clone ppp_cloner = IF_CLONE_INITIALIZER("ppp", ppp_clone_create, ppp_clone_destroy); /* * Called from boot code to establish ppp interfaces. */ void pppattach(void) { LIST_INIT(&ppp_softc_list); if_clone_attach(&ppp_cloner); } int ppp_clone_create(struct if_clone *ifc, int unit) { struct ppp_softc *sc; struct ifnet *ifp; sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); sc->sc_unit = unit; ifp = &sc->sc_if; snprintf(sc->sc_if.if_xname, sizeof sc->sc_if.if_xname, "%s%d", ifc->ifc_name, unit); sc->sc_if.if_softc = sc; sc->sc_if.if_mtu = PPP_MTU; sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; sc->sc_if.if_type = IFT_PPP; sc->sc_if.if_hdrlen = PPP_HDRLEN; sc->sc_if.if_ioctl = pppsioctl; sc->sc_if.if_output = pppoutput; sc->sc_if.if_start = ppp_ifstart; sc->sc_if.if_rtrequest = p2p_rtrequest; mq_init(&sc->sc_inq, IFQ_MAXLEN, IPL_NET); ppp_pkt_list_init(&sc->sc_rawq, IFQ_MAXLEN); if_attach(&sc->sc_if); if_alloc_sadl(&sc->sc_if); #if NBPFILTER > 0 bpfattach(&ifp->if_bpf, ifp, DLT_PPP, PPP_HDRLEN); #endif NET_LOCK(); LIST_INSERT_HEAD(&ppp_softc_list, sc, sc_list); NET_UNLOCK(); return (0); } int ppp_clone_destroy(struct ifnet *ifp) { struct ppp_softc *sc = ifp->if_softc; if (sc->sc_devp != NULL) return (EBUSY); NET_LOCK(); LIST_REMOVE(sc, sc_list); NET_UNLOCK(); if_detach(ifp); free(sc, M_DEVBUF, 0); return (0); } /* * Allocate a ppp interface unit and initialize it. */ struct ppp_softc * pppalloc(pid_t pid) { int i; struct ppp_softc *sc; NET_LOCK(); LIST_FOREACH(sc, &ppp_softc_list, sc_list) { if (sc->sc_xfer == pid) { sc->sc_xfer = 0; NET_UNLOCK(); return sc; } } LIST_FOREACH(sc, &ppp_softc_list, sc_list) { if (sc->sc_devp == NULL) break; } NET_UNLOCK(); if (sc == NULL) return NULL; sc->sc_flags = 0; sc->sc_mru = PPP_MRU; sc->sc_relinq = NULL; bzero((char *)&sc->sc_stats, sizeof(sc->sc_stats)); #ifdef VJC sc->sc_comp = malloc(sizeof(struct slcompress), M_DEVBUF, M_NOWAIT); if (sc->sc_comp) sl_compress_init(sc->sc_comp); #endif #ifdef PPP_COMPRESS sc->sc_xc_state = NULL; sc->sc_rc_state = NULL; #endif /* PPP_COMPRESS */ for (i = 0; i < NUM_NP; ++i) sc->sc_npmode[i] = NPMODE_ERROR; ml_init(&sc->sc_npqueue); sc->sc_last_sent = sc->sc_last_recv = getuptime(); return sc; } /* * Deallocate a ppp unit. */ void pppdealloc(struct ppp_softc *sc) { struct ppp_pkt *pkt; NET_LOCK(); if_down(&sc->sc_if); sc->sc_if.if_flags &= ~IFF_RUNNING; sc->sc_devp = NULL; sc->sc_xfer = 0; while ((pkt = ppp_pkt_dequeue(&sc->sc_rawq)) != NULL) ppp_pkt_free(pkt); mq_purge(&sc->sc_inq); ml_purge(&sc->sc_npqueue); m_freem(sc->sc_togo); sc->sc_togo = NULL; #ifdef PPP_COMPRESS ppp_ccp_closed(sc); sc->sc_xc_state = NULL; sc->sc_rc_state = NULL; #endif /* PPP_COMPRESS */ #if NBPFILTER > 0 if (sc->sc_pass_filt.bf_insns != 0) { free(sc->sc_pass_filt.bf_insns, M_DEVBUF, 0); sc->sc_pass_filt.bf_insns = 0; sc->sc_pass_filt.bf_len = 0; } if (sc->sc_active_filt.bf_insns != 0) { free(sc->sc_active_filt.bf_insns, M_DEVBUF, 0); sc->sc_active_filt.bf_insns = 0; sc->sc_active_filt.bf_len = 0; } #endif #ifdef VJC if (sc->sc_comp != 0) { free(sc->sc_comp, M_DEVBUF, 0); sc->sc_comp = 0; } #endif NET_UNLOCK(); } /* * Ioctl routine for generic ppp devices. */ int pppioctl(struct ppp_softc *sc, u_long cmd, caddr_t data, int flag, struct proc *p) { int s, error, flags, mru, npx; u_int nb; struct ppp_option_data *odp; struct compressor **cp; struct npioctl *npi; time_t t; #if NBPFILTER > 0 struct bpf_program *bp, *nbp; struct bpf_insn *newcode, *oldcode; int newcodelen; #endif #ifdef PPP_COMPRESS u_char ccp_option[CCP_MAX_OPTION_LENGTH]; #endif switch (cmd) { case FIONREAD: *(int *)data = mq_len(&sc->sc_inq); break; case PPPIOCGUNIT: *(int *)data = sc->sc_unit; /* XXX */ break; case PPPIOCGFLAGS: *(u_int *)data = sc->sc_flags; break; case PPPIOCSFLAGS: if ((error = suser(p)) != 0) return (error); flags = *(int *)data & SC_MASK; #ifdef PPP_COMPRESS if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN)) ppp_ccp_closed(sc); #endif s = splnet(); sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags; splx(s); break; case PPPIOCSMRU: if ((error = suser(p)) != 0) return (error); mru = *(int *)data; if (mru >= PPP_MRU && mru <= PPP_MAXMRU) sc->sc_mru = mru; break; case PPPIOCGMRU: *(int *)data = sc->sc_mru; break; #ifdef VJC case PPPIOCSMAXCID: if ((error = suser(p)) != 0) return (error); if (sc->sc_comp) sl_compress_setup(sc->sc_comp, *(int *)data); break; #endif case PPPIOCXFERUNIT: if ((error = suser(p)) != 0) return (error); sc->sc_xfer = p->p_p->ps_pid; break; #ifdef PPP_COMPRESS case PPPIOCSCOMPRESS: if ((error = suser(p)) != 0) return (error); odp = (struct ppp_option_data *) data; nb = odp->length; if (nb > sizeof(ccp_option)) nb = sizeof(ccp_option); if ((error = copyin(odp->ptr, ccp_option, nb)) != 0) return (error); /* preliminary check on the length byte */ if (ccp_option[1] < 2) return (EINVAL); for (cp = ppp_compressors; *cp != NULL; ++cp) if ((*cp)->compress_proto == ccp_option[0]) { /* * Found a handler for the protocol - try to allocate * a compressor or decompressor. */ error = 0; if (odp->transmit) { if (sc->sc_xc_state != NULL) { (*sc->sc_xcomp->comp_free)( sc->sc_xc_state); } sc->sc_xcomp = *cp; sc->sc_xc_state = (*cp)->comp_alloc(ccp_option, nb); if (sc->sc_xc_state == NULL) { if (sc->sc_flags & SC_DEBUG) printf( "%s: comp_alloc failed\n", sc->sc_if.if_xname); error = ENOBUFS; } s = splnet(); sc->sc_flags &= ~SC_COMP_RUN; splx(s); } else { if (sc->sc_rc_state != NULL) { (*sc->sc_rcomp->decomp_free)( sc->sc_rc_state); } sc->sc_rcomp = *cp; sc->sc_rc_state = (*cp)->decomp_alloc( ccp_option, nb); if (sc->sc_rc_state == NULL) { if (sc->sc_flags & SC_DEBUG) { printf( "%s: decomp_alloc failed\n", sc->sc_if.if_xname); } error = ENOBUFS; } s = splnet(); sc->sc_flags &= ~SC_DECOMP_RUN; splx(s); } return (error); } if (sc->sc_flags & SC_DEBUG) { printf("%s: no compressor for [%x %x %x], %x\n", sc->sc_if.if_xname, ccp_option[0], ccp_option[1], ccp_option[2], nb); } return (EINVAL); /* no handler found */ #endif /* PPP_COMPRESS */ case PPPIOCGNPMODE: case PPPIOCSNPMODE: npi = (struct npioctl *)data; switch (npi->protocol) { case PPP_IP: npx = NP_IP; break; #ifdef INET6 case PPP_IPV6: npx = NP_IPV6; break; #endif default: return EINVAL; } if (cmd == PPPIOCGNPMODE) { npi->mode = sc->sc_npmode[npx]; } else { if ((error = suser(p)) != 0) return (error); if (npi->mode != sc->sc_npmode[npx]) { sc->sc_npmode[npx] = npi->mode; if (npi->mode != NPMODE_QUEUE) { ppp_requeue(sc); (*sc->sc_start)(sc); } } } break; case PPPIOCGIDLE: t = getuptime(); ((struct ppp_idle *)data)->xmit_idle = t - sc->sc_last_sent; ((struct ppp_idle *)data)->recv_idle = t - sc->sc_last_recv; break; #if NBPFILTER > 0 case PPPIOCSPASS: case PPPIOCSACTIVE: nbp = (struct bpf_program *) data; if ((unsigned) nbp->bf_len > BPF_MAXINSNS) return EINVAL; newcodelen = nbp->bf_len * sizeof(struct bpf_insn); if (nbp->bf_len != 0) { newcode = mallocarray(nbp->bf_len, sizeof(struct bpf_insn), M_DEVBUF, M_WAITOK); if ((error = copyin((caddr_t)nbp->bf_insns, (caddr_t)newcode, newcodelen)) != 0) { free(newcode, M_DEVBUF, 0); return error; } if (!bpf_validate(newcode, nbp->bf_len)) { free(newcode, M_DEVBUF, 0); return EINVAL; } } else newcode = 0; bp = (cmd == PPPIOCSPASS) ? &sc->sc_pass_filt : &sc->sc_active_filt; oldcode = bp->bf_insns; s = splnet(); bp->bf_len = nbp->bf_len; bp->bf_insns = newcode; splx(s); if (oldcode != 0) free(oldcode, M_DEVBUF, 0); break; #endif default: return (-1); } return (0); } /* * Process an ioctl request to the ppp network interface. */ static int pppsioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct ppp_softc *sc = ifp->if_softc; struct ifaddr *ifa = (struct ifaddr *)data; struct ifreq *ifr = (struct ifreq *)data; struct ppp_stats *psp; #ifdef PPP_COMPRESS struct ppp_comp_stats *pcp; #endif int s = splnet(), error = 0; switch (cmd) { case SIOCSIFFLAGS: if ((ifp->if_flags & IFF_RUNNING) == 0) ifp->if_flags &= ~IFF_UP; break; case SIOCSIFADDR: case SIOCSIFDSTADDR: switch (ifa->ifa_addr->sa_family) { case AF_INET: break; #ifdef INET6 case AF_INET6: break; #endif default: error = EAFNOSUPPORT; break; } break; case SIOCSIFMTU: sc->sc_if.if_mtu = ifr->ifr_mtu; break; case SIOCADDMULTI: case SIOCDELMULTI: break; case SIOCGPPPSTATS: psp = &((struct ifpppstatsreq *) data)->stats; bzero(psp, sizeof(*psp)); psp->p = sc->sc_stats; #if defined(VJC) && !defined(SL_NO_STATS) if (sc->sc_comp) { psp->vj.vjs_packets = sc->sc_comp->sls_packets; psp->vj.vjs_compressed = sc->sc_comp->sls_compressed; psp->vj.vjs_searches = sc->sc_comp->sls_searches; psp->vj.vjs_misses = sc->sc_comp->sls_misses; psp->vj.vjs_uncompressedin = sc->sc_comp->sls_uncompressedin; psp->vj.vjs_compressedin = sc->sc_comp->sls_compressedin; psp->vj.vjs_errorin = sc->sc_comp->sls_errorin; psp->vj.vjs_tossed = sc->sc_comp->sls_tossed; } #endif /* VJC */ break; #ifdef PPP_COMPRESS case SIOCGPPPCSTATS: pcp = &((struct ifpppcstatsreq *) data)->stats; bzero(pcp, sizeof(*pcp)); if (sc->sc_xc_state != NULL) (*sc->sc_xcomp->comp_stat)(sc->sc_xc_state, &pcp->c); if (sc->sc_rc_state != NULL) (*sc->sc_rcomp->decomp_stat)(sc->sc_rc_state, &pcp->d); break; #endif /* PPP_COMPRESS */ default: error = ENOTTY; } splx(s); return (error); } /* * Queue a packet. Start transmission if not active. * Packet is placed in Information field of PPP frame. */ int pppoutput(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst, struct rtentry *rtp) { struct ppp_softc *sc = ifp->if_softc; int protocol, address, control; u_char *cp; int error; enum NPmode mode; int len; if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0 || ((ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC)) { error = ENETDOWN; /* sort of */ goto bad; } #ifdef DIAGNOSTIC if (ifp->if_rdomain != rtable_l2(m0->m_pkthdr.ph_rtableid)) { printf("%s: trying to send packet on wrong domain. " "if %d vs. mbuf %d, AF %d\n", ifp->if_xname, ifp->if_rdomain, rtable_l2(m0->m_pkthdr.ph_rtableid), dst->sa_family); } #endif /* * Compute PPP header. */ switch (dst->sa_family) { case AF_INET: address = PPP_ALLSTATIONS; control = PPP_UI; protocol = PPP_IP; mode = sc->sc_npmode[NP_IP]; break; #ifdef INET6 case AF_INET6: address = PPP_ALLSTATIONS; control = PPP_UI; protocol = PPP_IPV6; mode = sc->sc_npmode[NP_IPV6]; break; #endif case AF_UNSPEC: address = PPP_ADDRESS(dst->sa_data); control = PPP_CONTROL(dst->sa_data); protocol = PPP_PROTOCOL(dst->sa_data); mode = NPMODE_PASS; break; default: printf("%s: af%d not supported\n", ifp->if_xname, dst->sa_family); error = EAFNOSUPPORT; goto bad; } /* * Drop this packet, or return an error, if necessary. */ if (mode == NPMODE_ERROR) { error = ENETDOWN; goto bad; } if (mode == NPMODE_DROP) { error = 0; goto bad; } /* * Add PPP header. If no space in first mbuf, allocate another. */ M_PREPEND(m0, PPP_HDRLEN, M_DONTWAIT); if (m0 == NULL) { error = ENOBUFS; goto bad; } cp = mtod(m0, u_char *); *cp++ = address; *cp++ = control; *cp++ = protocol >> 8; *cp++ = protocol & 0xff; if ((m0->m_flags & M_PKTHDR) == 0) panic("mbuf packet without packet header!"); len = m0->m_pkthdr.len; if (sc->sc_flags & SC_LOG_OUTPKT) { printf("%s output: ", ifp->if_xname); pppdumpm(m0); } if ((protocol & 0x8000) == 0) { #if NBPFILTER > 0 /* * Apply the pass and active filters to the packet, * but only if it is a data packet. */ *mtod(m0, u_char *) = 1; /* indicates outbound */ if (sc->sc_pass_filt.bf_insns != 0 && bpf_filter(sc->sc_pass_filt.bf_insns, (u_char *)m0, len, 0) == 0) { error = 0; /* drop this packet */ goto bad; } /* * Update the time we sent the most recent packet. */ if (sc->sc_active_filt.bf_insns == 0 || bpf_filter(sc->sc_active_filt.bf_insns, (u_char *)m0, len, 0)) sc->sc_last_sent = getuptime(); *mtod(m0, u_char *) = address; #else /* * Update the time we sent the most recent packet. */ sc->sc_last_sent = getuptime(); #endif } #if NBPFILTER > 0 /* See if bpf wants to look at the packet. */ if (ifp->if_bpf) bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT); #endif /* * Put the packet on the appropriate queue. */ if (mode == NPMODE_QUEUE) { /* XXX we should limit the number of packets on this queue */ ml_enqueue(&sc->sc_npqueue, m0); } else { error = ifq_enqueue(&sc->sc_if.if_snd, m0); if (error) { sc->sc_if.if_oerrors++; sc->sc_stats.ppp_oerrors++; return (error); } (*sc->sc_start)(sc); } ifp->if_opackets++; ifp->if_obytes += len; return (0); bad: m_freem(m0); return (error); } /* * After a change in the NPmode for some NP, move packets from the * npqueue to the send queue or the fast queue as appropriate. */ static void ppp_requeue(struct ppp_softc *sc) { struct mbuf_list ml = MBUF_LIST_INITIALIZER(); struct mbuf *m; enum NPmode mode; int error; while ((m = ml_dequeue(&sc->sc_npqueue)) != NULL) { switch (PPP_PROTOCOL(mtod(m, u_char *))) { case PPP_IP: mode = sc->sc_npmode[NP_IP]; break; #ifdef INET6 case PPP_IPV6: mode = sc->sc_npmode[NP_IPV6]; break; #endif default: mode = NPMODE_PASS; } switch (mode) { case NPMODE_PASS: error = ifq_enqueue(&sc->sc_if.if_snd, m); if (error) { sc->sc_if.if_oerrors++; sc->sc_stats.ppp_oerrors++; } break; case NPMODE_DROP: case NPMODE_ERROR: m_freem(m); break; case NPMODE_QUEUE: ml_enqueue(&ml, m); break; } } sc->sc_npqueue = ml; } /* * Transmitter has finished outputting some stuff; */ void ppp_restart(struct ppp_softc *sc) { int s = splnet(); sc->sc_flags &= ~SC_TBUSY; schednetisr(NETISR_PPP); splx(s); } /* * Get a packet to send. */ struct mbuf * ppp_dequeue(struct ppp_softc *sc) { struct mbuf *m, *mp; u_char *cp; int address, control, protocol; /* * Grab a packet to send: first try the fast queue, then the * normal queue. */ m = ifq_dequeue(&sc->sc_if.if_snd); if (m == NULL) return NULL; ++sc->sc_stats.ppp_opackets; /* * Extract the ppp header of the new packet. * The ppp header will be in one mbuf. */ cp = mtod(m, u_char *); address = PPP_ADDRESS(cp); control = PPP_CONTROL(cp); protocol = PPP_PROTOCOL(cp); switch (protocol) { case PPP_IP: #ifdef VJC /* * If the packet is a TCP/IP packet, see if we can compress it. */ if ((sc->sc_flags & SC_COMP_TCP) && sc->sc_comp != NULL) { struct ip *ip; int type; mp = m; ip = (struct ip *)(cp + PPP_HDRLEN); if (mp->m_len <= PPP_HDRLEN) { mp = mp->m_next; if (mp == NULL) break; ip = mtod(mp, struct ip *); } /* * this code assumes the IP/TCP header is in one * non-shared mbuf. */ if (ip->ip_p == IPPROTO_TCP) { type = sl_compress_tcp(mp, ip, sc->sc_comp, !(sc->sc_flags & SC_NO_TCP_CCID)); switch (type) { case TYPE_UNCOMPRESSED_TCP: protocol = PPP_VJC_UNCOMP; break; case TYPE_COMPRESSED_TCP: protocol = PPP_VJC_COMP; cp = mtod(m, u_char *); cp[0] = address; /* header has moved */ cp[1] = control; cp[2] = 0; break; } /* update protocol in PPP header */ cp[3] = protocol; } } #endif /* VJC */ break; #ifdef PPP_COMPRESS case PPP_CCP: ppp_ccp(sc, m, 0); break; #endif /* PPP_COMPRESS */ } #ifdef PPP_COMPRESS if (protocol != PPP_LCP && protocol != PPP_CCP && sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) { struct mbuf *mcomp = NULL; int slen; slen = 0; for (mp = m; mp != NULL; mp = mp->m_next) slen += mp->m_len; (*sc->sc_xcomp->compress)(sc->sc_xc_state, &mcomp, m, slen, (sc->sc_flags & SC_CCP_UP ? sc->sc_if.if_mtu + PPP_HDRLEN : 0)); if (mcomp != NULL) { if (sc->sc_flags & SC_CCP_UP) { /* Send the compressed packet instead. */ m_freem(m); m = mcomp; cp = mtod(m, u_char *); protocol = cp[3]; } else { /* * Can't transmit compressed packets until * CCP is up. */ m_freem(mcomp); } } } #endif /* PPP_COMPRESS */ /* * Compress the address/control and protocol, if possible. */ if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS && control == PPP_UI && protocol != PPP_ALLSTATIONS && protocol != PPP_LCP) { /* can compress address/control */ m->m_data += 2; m->m_len -= 2; } if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) { /* can compress protocol */ if (mtod(m, u_char *) == cp) { cp[2] = cp[1]; /* move address/control up */ cp[1] = cp[0]; } ++m->m_data; --m->m_len; } return m; } /* * Software interrupt routine. */ void pppintr(void) { struct ppp_softc *sc; int s; struct ppp_pkt *pkt; struct mbuf *m; NET_ASSERT_LOCKED(); LIST_FOREACH(sc, &ppp_softc_list, sc_list) { if (!(sc->sc_flags & SC_TBUSY) && (!ifq_empty(&sc->sc_if.if_snd))) { s = splnet(); sc->sc_flags |= SC_TBUSY; splx(s); (*sc->sc_start)(sc); } while ((pkt = ppp_pkt_dequeue(&sc->sc_rawq)) != NULL) { m = ppp_pkt_mbuf(pkt); if (m == NULL) continue; ppp_inproc(sc, m); } } } #ifdef PPP_COMPRESS /* * Handle a CCP packet. `rcvd' is 1 if the packet was received, * 0 if it is about to be transmitted. */ static void ppp_ccp(struct ppp_softc *sc, struct mbuf *m, int rcvd) { u_char *dp, *ep; struct mbuf *mp; int slen, s; /* * Get a pointer to the data after the PPP header. */ if (m->m_len <= PPP_HDRLEN) { mp = m->m_next; if (mp == NULL) return; dp = mtod(mp, u_char *); } else { mp = m; dp = mtod(mp, u_char *) + PPP_HDRLEN; } ep = mtod(mp, u_char *) + mp->m_len; if (dp + CCP_HDRLEN > ep) return; slen = CCP_LENGTH(dp); if (dp + slen > ep) { if (sc->sc_flags & SC_DEBUG) { printf("if_ppp/ccp: not enough data in mbuf" " (%p+%x > %p+%x)\n", dp, slen, mtod(mp, u_char *), mp->m_len); } return; } switch (CCP_CODE(dp)) { case CCP_CONFREQ: case CCP_TERMREQ: case CCP_TERMACK: /* CCP must be going down - disable compression */ if (sc->sc_flags & SC_CCP_UP) { s = splnet(); sc->sc_flags &= ~(SC_CCP_UP | SC_COMP_RUN | SC_DECOMP_RUN); splx(s); } break; case CCP_CONFACK: if (sc->sc_flags & SC_CCP_OPEN && !(sc->sc_flags & SC_CCP_UP) && slen >= CCP_HDRLEN + CCP_OPT_MINLEN && slen >= CCP_OPT_LENGTH(dp + CCP_HDRLEN) + CCP_HDRLEN) { if (!rcvd) { /* we're agreeing to send compressed packets. */ if (sc->sc_xc_state != NULL && (*sc->sc_xcomp->comp_init)(sc->sc_xc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN, sc->sc_unit, 0, sc->sc_flags & SC_DEBUG)) { s = splnet(); sc->sc_flags |= SC_COMP_RUN; splx(s); } } else { /* peer agrees to send compressed packets */ if (sc->sc_rc_state != NULL && (*sc->sc_rcomp->decomp_init)( sc->sc_rc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN, sc->sc_unit, 0, sc->sc_mru, sc->sc_flags & SC_DEBUG)) { s = splnet(); sc->sc_flags |= SC_DECOMP_RUN; sc->sc_flags &= ~(SC_DC_ERROR | SC_DC_FERROR); splx(s); } } } break; case CCP_RESETACK: if (sc->sc_flags & SC_CCP_UP) { if (!rcvd) { if (sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) { (*sc->sc_xcomp->comp_reset)( sc->sc_xc_state); } } else { if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) { (*sc->sc_rcomp->decomp_reset)( sc->sc_rc_state); s = splnet(); sc->sc_flags &= ~SC_DC_ERROR; splx(s); } } } break; } } /* * CCP is down; free (de)compressor state if necessary. */ static void ppp_ccp_closed(struct ppp_softc *sc) { if (sc->sc_xc_state) { (*sc->sc_xcomp->comp_free)(sc->sc_xc_state); sc->sc_xc_state = NULL; } if (sc->sc_rc_state) { (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state); sc->sc_rc_state = NULL; } } #endif /* PPP_COMPRESS */ /* * PPP packet input routine. * The caller has checked and removed the FCS and has inserted * the address/control bytes and the protocol high byte if they * were omitted. */ void ppppktin(struct ppp_softc *sc, struct ppp_pkt *pkt, int lost) { pkt->p_hdr.ph_errmark = lost; if (ppp_pkt_enqueue(&sc->sc_rawq, pkt) == 0) schednetisr(NETISR_PPP); } /* * Process a received PPP packet, doing decompression as necessary. */ #define COMPTYPE(proto) ((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \ TYPE_UNCOMPRESSED_TCP) static void ppp_inproc(struct ppp_softc *sc, struct mbuf *m) { struct ifnet *ifp = &sc->sc_if; int s, ilen, xlen, proto, rv; u_char *cp, adrs, ctrl; struct mbuf *mp, *dmp = NULL; u_char *iphdr; u_int hlen; sc->sc_stats.ppp_ipackets++; if (sc->sc_flags & SC_LOG_INPKT) { ilen = 0; for (mp = m; mp != NULL; mp = mp->m_next) ilen += mp->m_len; printf("%s: got %d bytes\n", ifp->if_xname, ilen); pppdumpm(m); } cp = mtod(m, u_char *); adrs = PPP_ADDRESS(cp); ctrl = PPP_CONTROL(cp); proto = PPP_PROTOCOL(cp); if (m->m_flags & M_ERRMARK) { m->m_flags &= ~M_ERRMARK; s = splnet(); sc->sc_flags |= SC_VJ_RESET; splx(s); } #ifdef PPP_COMPRESS /* * Decompress this packet if necessary, update the receiver's * dictionary, or take appropriate action on a CCP packet. */ if (proto == PPP_COMP && sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN) && !(sc->sc_flags & SC_DC_ERROR) && !(sc->sc_flags & SC_DC_FERROR)) { /* decompress this packet */ rv = (*sc->sc_rcomp->decompress)(sc->sc_rc_state, m, &dmp); if (rv == DECOMP_OK) { m_freem(m); if (dmp == NULL) { /* * no error, but no decompressed packet * produced */ return; } m = dmp; cp = mtod(m, u_char *); proto = PPP_PROTOCOL(cp); } else { /* * An error has occurred in decompression. * Pass the compressed packet up to pppd, which may * take CCP down or issue a Reset-Req. */ if (sc->sc_flags & SC_DEBUG) { printf("%s: decompress failed %d\n", ifp->if_xname, rv); } s = splnet(); sc->sc_flags |= SC_VJ_RESET; if (rv == DECOMP_ERROR) sc->sc_flags |= SC_DC_ERROR; else sc->sc_flags |= SC_DC_FERROR; splx(s); } } else { if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) { (*sc->sc_rcomp->incomp)(sc->sc_rc_state, m); } if (proto == PPP_CCP) { ppp_ccp(sc, m, 1); } } #endif ilen = 0; for (mp = m; mp != NULL; mp = mp->m_next) ilen += mp->m_len; #ifdef VJC if (sc->sc_flags & SC_VJ_RESET) { /* * If we've missed a packet, we must toss subsequent compressed * packets which don't have an explicit connection ID. */ if (sc->sc_comp) sl_uncompress_tcp(NULL, 0, TYPE_ERROR, sc->sc_comp); s = splnet(); sc->sc_flags &= ~SC_VJ_RESET; splx(s); } /* * See if we have a VJ-compressed packet to uncompress. */ if (proto == PPP_VJC_COMP) { if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0) goto bad; xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN, ilen - PPP_HDRLEN, TYPE_COMPRESSED_TCP, sc->sc_comp, &iphdr, &hlen); if (xlen <= 0) { if (sc->sc_flags & SC_DEBUG) { printf("%s: VJ uncompress failed " "on type comp\n", ifp->if_xname); } goto bad; } /* Copy the PPP and IP headers into a new mbuf. */ MGETHDR(mp, M_DONTWAIT, MT_DATA); if (mp == NULL) goto bad; mp->m_len = 0; mp->m_next = NULL; if (hlen + PPP_HDRLEN > MHLEN) { MCLGET(mp, M_DONTWAIT); if (m_trailingspace(mp) < hlen + PPP_HDRLEN) { m_freem(mp); /* lose if big headers and no clusters */ goto bad; } } if (m->m_flags & M_PKTHDR) M_MOVE_HDR(mp, m); cp = mtod(mp, u_char *); cp[0] = adrs; cp[1] = ctrl; cp[2] = 0; cp[3] = PPP_IP; proto = PPP_IP; bcopy(iphdr, cp + PPP_HDRLEN, hlen); mp->m_len = hlen + PPP_HDRLEN; /* * Trim the PPP and VJ headers off the old mbuf * and stick the new and old mbufs together. */ m->m_data += PPP_HDRLEN + xlen; m->m_len -= PPP_HDRLEN + xlen; if (m->m_len <= m_trailingspace(mp)) { bcopy(mtod(m, u_char *), mtod(mp, u_char *) + mp->m_len, m->m_len); mp->m_len += m->m_len; mp->m_next = m_free(m); } else mp->m_next = m; m = mp; ilen += hlen - xlen; } else if (proto == PPP_VJC_UNCOMP) { if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0) goto bad; xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN, ilen - PPP_HDRLEN, TYPE_UNCOMPRESSED_TCP, sc->sc_comp, &iphdr, &hlen); if (xlen < 0) { if (sc->sc_flags & SC_DEBUG) { printf("%s: VJ uncompress failed " "on type uncomp\n", ifp->if_xname); } goto bad; } proto = PPP_IP; cp[3] = PPP_IP; } #endif /* VJC */ m->m_pkthdr.len = ilen; m->m_pkthdr.ph_ifidx = ifp->if_index; /* mark incoming routing table */ m->m_pkthdr.ph_rtableid = ifp->if_rdomain; if ((proto & 0x8000) == 0) { #if NBPFILTER > 0 /* * See whether we want to pass this packet, and * if it counts as link activity. */ adrs = *mtod(m, u_char *); /* save address field */ *mtod(m, u_char *) = 0; /* indicate inbound */ if (sc->sc_pass_filt.bf_insns != 0 && bpf_filter(sc->sc_pass_filt.bf_insns, (u_char *) m, ilen, 0) == 0) { /* drop this packet */ m_freem(m); return; } if (sc->sc_active_filt.bf_insns == 0 || bpf_filter(sc->sc_active_filt.bf_insns, (u_char *)m, ilen, 0)) sc->sc_last_recv = getuptime(); *mtod(m, u_char *) = adrs; #else /* * Record the time that we received this packet. */ sc->sc_last_recv = getuptime(); #endif } #if NBPFILTER > 0 /* See if bpf wants to look at the packet. */ if (ifp->if_bpf) bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN); #endif rv = 0; switch (proto) { case PPP_IP: /* * IP packet - take off the ppp header and pass it up to IP. */ if ((ifp->if_flags & IFF_UP) == 0 || sc->sc_npmode[NP_IP] != NPMODE_PASS) { /* interface is down - drop the packet. */ m_freem(m); return; } m->m_pkthdr.len -= PPP_HDRLEN; m->m_data += PPP_HDRLEN; m->m_len -= PPP_HDRLEN; ipv4_input(ifp, m); rv = 1; break; #ifdef INET6 case PPP_IPV6: /* * IPv6 packet - take off the ppp header and pass it up to IPv6. */ if ((ifp->if_flags & IFF_UP) == 0 || sc->sc_npmode[NP_IPV6] != NPMODE_PASS) { /* interface is down - drop the packet. */ m_freem(m); return; } m->m_pkthdr.len -= PPP_HDRLEN; m->m_data += PPP_HDRLEN; m->m_len -= PPP_HDRLEN; ipv6_input(ifp, m); rv = 1; break; #endif default: /* * Some other protocol - place on input queue for read(). */ if (mq_enqueue(&sc->sc_inq, m) != 0) { if_congestion(); rv = 0; /* failure */ } else rv = 2; /* input queue */ break; } if (rv == 0) { /* failure */ if (sc->sc_flags & SC_DEBUG) printf("%s: input queue full\n", ifp->if_xname); ifp->if_iqdrops++; goto dropped; } ifp->if_ipackets++; ifp->if_ibytes += ilen; if (rv == 2) (*sc->sc_ctlp)(sc); return; bad: m_freem(m); dropped: sc->sc_if.if_ierrors++; sc->sc_stats.ppp_ierrors++; } #define MAX_DUMP_BYTES 128 static void pppdumpm(struct mbuf *m0) { char buf[3*MAX_DUMP_BYTES+4]; char *bp = buf; struct mbuf *m; static char digits[] = "0123456789abcdef"; for (m = m0; m; m = m->m_next) { int l = m->m_len; u_char *rptr = mtod(m, u_char *); while (l--) { if (bp > buf + sizeof(buf) - 4) goto done; /* convert byte to ascii hex */ *bp++ = digits[*rptr >> 4]; *bp++ = digits[*rptr++ & 0xf]; } if (m->m_next) { if (bp > buf + sizeof(buf) - 3) goto done; *bp++ = '|'; } else *bp++ = ' '; } done: if (m) *bp++ = '>'; *bp = 0; printf("%s\n", buf); } static void ppp_ifstart(struct ifnet *ifp) { struct ppp_softc *sc; sc = ifp->if_softc; (*sc->sc_start)(sc); } void ppp_pkt_list_init(struct ppp_pkt_list *pl, u_int limit) { mtx_init(&pl->pl_mtx, IPL_TTY); pl->pl_head = pl->pl_tail = NULL; pl->pl_count = 0; pl->pl_limit = limit; } int ppp_pkt_enqueue(struct ppp_pkt_list *pl, struct ppp_pkt *pkt) { int drop = 0; mtx_enter(&pl->pl_mtx); if (pl->pl_count < pl->pl_limit) { if (pl->pl_tail == NULL) pl->pl_head = pl->pl_tail = pkt; else { PKT_NEXTPKT(pl->pl_tail) = pkt; pl->pl_tail = pkt; } PKT_NEXTPKT(pkt) = NULL; pl->pl_count++; } else drop = 1; mtx_leave(&pl->pl_mtx); if (drop) ppp_pkt_free(pkt); return (drop); } struct ppp_pkt * ppp_pkt_dequeue(struct ppp_pkt_list *pl) { struct ppp_pkt *pkt; mtx_enter(&pl->pl_mtx); pkt = pl->pl_head; if (pkt != NULL) { pl->pl_head = PKT_NEXTPKT(pkt); if (pl->pl_head == NULL) pl->pl_tail = NULL; pl->pl_count--; } mtx_leave(&pl->pl_mtx); return (pkt); } struct mbuf * ppp_pkt_mbuf(struct ppp_pkt *pkt0) { extern struct pool ppp_pkts; struct mbuf *m0 = NULL, **mp = &m0, *m; struct ppp_pkt *pkt = pkt0; size_t len = 0; do { MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == NULL) goto fail; MEXTADD(m, pkt, sizeof(*pkt), M_EXTWR, MEXTFREE_POOL, &ppp_pkts); m->m_data += sizeof(pkt->p_hdr); m->m_len = PKT_LEN(pkt); len += m->m_len; *mp = m; mp = &m->m_next; pkt = PKT_NEXT(pkt); } while (pkt != NULL); m0->m_pkthdr.len = len; if (pkt0->p_hdr.ph_errmark) m0->m_flags |= M_ERRMARK; return (m0); fail: m_freem(m0); ppp_pkt_free(pkt0); return (NULL); } #endif /* NPPP > 0 */
165 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 /* $OpenBSD: tty_conf.c,v 1.23 2015/12/22 20:31:51 sf Exp $ */ /* $NetBSD: tty_conf.c,v 1.18 1996/05/19 17:17:55 jonathan Exp $ */ /*- * Copyright (c) 1982, 1986, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)tty_conf.c 8.4 (Berkeley) 1/21/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/tty.h> #include <sys/conf.h> #include "ppp.h" #include "nmea.h" #include "msts.h" #include "endrun.h" #define ttynodisc ((int (*)(dev_t, struct tty *, struct proc *))enodev) #define ttyerrclose ((int (*)(struct tty *, int flags, struct proc *))enodev) #define ttyerrio ((int (*)(struct tty *, struct uio *, int))enodev) #define ttyerrinput ((int (*)(int c, struct tty *))enodev) #define ttyerrstart ((int (*)(struct tty *))enodev) struct linesw linesw[] = { { ttyopen, ttylclose, ttread, ttwrite, nullioctl, ttyinput, ttstart, ttymodem }, /* 0- termios */ { ttynodisc, ttyerrclose, ttyerrio, ttyerrio, nullioctl, ttyerrinput, ttyerrstart, nullmodem }, /* 1- defunct */ /* 2- old NTTYDISC (defunct) */ { ttynodisc, ttyerrclose, ttyerrio, ttyerrio, nullioctl, ttyerrinput, ttyerrstart, nullmodem }, /* 3- TABLDISC (defunct) */ { ttynodisc, ttyerrclose, ttyerrio, ttyerrio, nullioctl, ttyerrinput, ttyerrstart, nullmodem }, /* 4- SLIPDISC (defunct) */ { ttynodisc, ttyerrclose, ttyerrio, ttyerrio, nullioctl, ttyerrinput, ttyerrstart, nullmodem }, #if NPPP > 0 { pppopen, pppclose, pppread, pppwrite, ppptioctl, pppinput, pppstart, ttymodem }, /* 5- PPPDISC */ #else { ttynodisc, ttyerrclose, ttyerrio, ttyerrio, nullioctl, ttyerrinput, ttyerrstart, nullmodem }, #endif /* 6- STRIPDISC (defunct) */ { ttynodisc, ttyerrclose, ttyerrio, ttyerrio, nullioctl, ttyerrinput, ttyerrstart, nullmodem }, #if NNMEA > 0 { nmeaopen, nmeaclose, ttread, ttwrite, nullioctl, nmeainput, ttstart, ttymodem }, /* 7- NMEADISC */ #else { ttynodisc, ttyerrclose, ttyerrio, ttyerrio, nullioctl, ttyerrinput, ttyerrstart, nullmodem }, #endif #if NMSTS > 0 { mstsopen, mstsclose, ttread, ttwrite, nullioctl, mstsinput, ttstart, ttymodem }, /* 8- MSTSDISC */ #else { ttynodisc, ttyerrclose, ttyerrio, ttyerrio, nullioctl, ttyerrinput, ttyerrstart, nullmodem }, #endif #if NENDRUN > 0 { endrunopen, endrunclose, ttread, ttwrite, nullioctl, endruninput, ttstart, ttymodem }, /* 9- ENDRUNDISC */ #else { ttynodisc, ttyerrclose, ttyerrio, ttyerrio, nullioctl, ttyerrinput, ttyerrstart, nullmodem }, #endif }; int nlinesw = sizeof (linesw) / sizeof (linesw[0]); /* * Do nothing specific version of line * discipline specific ioctl command. */ int nullioctl(struct tty *tp, u_long cmd, char *data, int flags, struct proc *p) { return (-1); }
2 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 /* $OpenBSD: fd.c,v 1.109 2024/05/13 01:15:50 jsg Exp $ */ /* $NetBSD: fd.c,v 1.90 1996/05/12 23:12:03 mycroft Exp $ */ /*- * Copyright (c) 1993, 1994, 1995, 1996 Charles Hannum. * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Don Ahn. * * Portions Copyright (c) 1993, 1994 by * jc@irbs.UUCP (John Capo) * vak@zebub.msk.su (Serge Vakulenko) * ache@astral.msk.su (Andrew A. Chernov) * joerg_wunsch@uriah.sax.de (Joerg Wunsch) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)fd.c 7.4 (Berkeley) 5/25/91 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/fcntl.h> #include <sys/ioctl.h> #include <sys/device.h> #include <sys/disklabel.h> #include <sys/disk.h> #include <sys/buf.h> #include <sys/malloc.h> #include <sys/uio.h> #include <sys/mtio.h> #include <sys/syslog.h> #include <sys/queue.h> #include <sys/stat.h> #include <sys/timeout.h> #include <sys/dkio.h> #include <machine/cpu.h> #include <machine/bus.h> #include <machine/intr.h> #include <machine/ioctl_fd.h> #include <dev/isa/isavar.h> #include <dev/isa/isadmavar.h> #include <dev/isa/fdreg.h> #if defined(__i386__) || defined(__amd64__) /* XXX */ #include <i386/isa/nvram.h> #endif #include <dev/isa/fdlink.h> /* XXX misuse a flag to identify format operation */ #define B_FORMAT B_XXX /* fd_type struct now in ioctl_fd.h */ /* The order of entries in the following table is important -- BEWARE! */ struct fd_type fd_types[] = { { 18,2,36,2,0xff,0xcf,0x1b,0x6c,80,2880,1,FDC_500KBPS,"1.44MB" }, /* 1.44MB diskette */ { 15,2,30,2,0xff,0xdf,0x1b,0x54,80,2400,1,FDC_500KBPS, "1.2MB" }, /* 1.2 MB AT-diskettes */ { 9,2,18,2,0xff,0xdf,0x23,0x50,40, 720,2,FDC_300KBPS, "360KB/AT" }, /* 360kB in 1.2MB drive */ { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,1,FDC_250KBPS, "360KB/PC" }, /* 360kB PC diskettes */ { 9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_250KBPS, "720KB" }, /* 3.5" 720kB diskette */ { 9,2,18,2,0xff,0xdf,0x23,0x50,80,1440,1,FDC_300KBPS, "720KB/x" }, /* 720kB in 1.2MB drive */ { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,2,FDC_250KBPS, "360KB/x" }, /* 360kB in 720kB drive */ { 36,2,72,2,0xff,0xaf,0x1b,0x54,80,5760,1,FDC_500KBPS,"2.88MB" }, /* 2.88MB diskette */ { 8,2,16,3,0xff,0xdf,0x35,0x74,77,1232,1,FDC_500KBPS,"1.2MB/[1024bytes/sector]" } /* 1.2 MB japanese format */ }; /* software state, per disk (with up to 4 disks per ctlr) */ struct fd_softc { struct device sc_dev; struct disk sc_dk; struct fd_type *sc_deftype; /* default type descriptor */ struct fd_type *sc_type; /* current type descriptor */ daddr_t sc_blkno; /* starting block number */ int sc_bcount; /* byte count left */ int sc_opts; /* user-set options */ int sc_skip; /* bytes already transferred */ int sc_nblks; /* number of blocks currently transferring */ int sc_nbytes; /* number of bytes currently transferring */ int sc_drive; /* physical unit number */ int sc_flags; #define FD_OPEN 0x01 /* it's open */ #define FD_MOTOR 0x02 /* motor should be on */ #define FD_MOTOR_WAIT 0x04 /* motor coming up */ int sc_cylin; /* where we think the head is */ TAILQ_ENTRY(fd_softc) sc_drivechain; int sc_ops; /* I/O ops since last switch */ struct bufq sc_bufq; /* pending I/O */ struct buf *sc_bp; /* the current I/O */ struct timeout fd_motor_on_to; struct timeout fd_motor_off_to; struct timeout fdtimeout_to; }; /* floppy driver configuration */ int fdprobe(struct device *, void *, void *); void fdattach(struct device *, struct device *, void *); int fdactivate(struct device *, int); const struct cfattach fd_ca = { sizeof(struct fd_softc), fdprobe, fdattach, NULL, fdactivate }; struct cfdriver fd_cd = { NULL, "fd", DV_DISK }; int fdgetdisklabel(dev_t, struct fd_softc *, struct disklabel *, int); void fdstrategy(struct buf *); void fdstart(struct fd_softc *); int fdintr(struct fdc_softc *); void fd_set_motor(struct fdc_softc *fdc, int reset); void fd_motor_off(void *arg); void fd_motor_on(void *arg); void fdfinish(struct fd_softc *fd, struct buf *bp); int fdformat(dev_t, struct fd_formb *, struct proc *); static __inline struct fd_type *fd_dev_to_type(struct fd_softc *, dev_t); void fdretry(struct fd_softc *); void fdtimeout(void *); int fdgetdisklabel(dev_t dev, struct fd_softc *fd, struct disklabel *lp, int spoofonly) { bzero(lp, sizeof(struct disklabel)); lp->d_type = DTYPE_FLOPPY; lp->d_secsize = FD_BSIZE(fd); lp->d_secpercyl = fd->sc_type->seccyl; lp->d_nsectors = fd->sc_type->sectrac; lp->d_ncylinders = fd->sc_type->tracks; lp->d_ntracks = fd->sc_type->heads; /* Go figure... */ DL_SETDSIZE(lp, fd->sc_type->size); strncpy(lp->d_typename, "floppy disk", sizeof(lp->d_typename)); strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname)); lp->d_version = 1; lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; lp->d_checksum = dkcksum(lp); /* * Call the generic disklabel extraction routine. If there's * not a label there, fake it. */ return readdisklabel(DISKLABELDEV(dev), fdstrategy, lp, spoofonly); } int fdprobe(struct device *parent, void *match, void *aux) { struct fdc_softc *fdc = (void *)parent; struct cfdata *cf = match; struct fdc_attach_args *fa = aux; int drive = fa->fa_drive; bus_space_tag_t iot = fdc->sc_iot; bus_space_handle_t ioh = fdc->sc_ioh; int n; if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != drive) return 0; /* * XXX * This is to work around some odd interactions between this driver * and SMC Ethernet cards. */ if (cf->cf_loc[0] == -1 && drive >= 2) return 0; /* * We want to keep the flags config gave us. */ fa->fa_flags = cf->cf_flags; /* select drive and turn on motor */ bus_space_write_1(iot, ioh, fdout, drive | FDO_FRST | FDO_MOEN(drive)); /* wait for motor to spin up */ tsleep_nsec(fdc, 0, "fdprobe", MSEC_TO_NSEC(250)); out_fdc(iot, ioh, NE7CMD_RECAL); out_fdc(iot, ioh, drive); /* wait for recalibrate */ tsleep_nsec(fdc, 0, "fdprobe", MSEC_TO_NSEC(2000)); out_fdc(iot, ioh, NE7CMD_SENSEI); n = fdcresult(fdc); #ifdef FD_DEBUG { int i; printf("fdprobe: status"); for (i = 0; i < n; i++) printf(" %x", fdc->sc_status[i]); printf("\n"); } #endif /* turn off motor */ tsleep_nsec(fdc, 0, "fdprobe", MSEC_TO_NSEC(250)); bus_space_write_1(iot, ioh, fdout, FDO_FRST); /* flags & 0x20 forces the drive to be found even if it won't probe */ if (!(fa->fa_flags & 0x20) && (n != 2 || (fdc->sc_status[0] & 0xf8) != 0x20)) return 0; return 1; } /* * Controller is working, and drive responded. Attach it. */ void fdattach(struct device *parent, struct device *self, void *aux) { struct fdc_softc *fdc = (void *)parent; struct fd_softc *fd = (void *)self; struct fdc_attach_args *fa = aux; struct fd_type *type = fa->fa_deftype; int drive = fa->fa_drive; if (!type || (fa->fa_flags & 0x10)) { /* The config has overridden this. */ switch (fa->fa_flags & 0x07) { case 1: /* 2.88MB */ type = &fd_types[7]; break; case 2: /* 1.44MB */ type = &fd_types[0]; break; case 3: /* 1.2MB */ type = &fd_types[1]; break; case 4: /* 720K */ type = &fd_types[4]; break; case 5: /* 360K */ type = &fd_types[3]; break; case 6: /* 1.2 MB japanese format */ type = &fd_types[8]; break; #ifdef __alpha__ default: /* 1.44MB, how to detect others? * idea from NetBSD -- jay@rootaction.net */ type = &fd_types[0]; #endif } } if (type) printf(": %s %d cyl, %d head, %d sec\n", type->name, type->tracks, type->heads, type->sectrac); else printf(": density unknown\n"); fd->sc_cylin = -1; fd->sc_drive = drive; fd->sc_deftype = type; fdc->sc_type[drive] = FDC_TYPE_DISK; fdc->sc_link.fdlink.sc_fd[drive] = fd; /* * Initialize and attach the disk structure. */ fd->sc_dk.dk_flags = DKF_NOLABELREAD; fd->sc_dk.dk_name = fd->sc_dev.dv_xname; bufq_init(&fd->sc_bufq, BUFQ_DEFAULT); disk_attach(&fd->sc_dev, &fd->sc_dk); /* Setup timeout structures */ timeout_set(&fd->fd_motor_on_to, fd_motor_on, fd); timeout_set(&fd->fd_motor_off_to, fd_motor_off, fd); timeout_set(&fd->fdtimeout_to, fdtimeout, fd); } int fdactivate(struct device *self, int act) { struct fd_softc *fd = (void *)self; struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent; int rv = 0; switch (act) { case DVACT_SUSPEND: if (fdc->sc_state != DEVIDLE) { timeout_del(&fd->fd_motor_on_to); timeout_del(&fd->fd_motor_off_to); timeout_del(&fd->fdtimeout_to); fdc->sc_state = IOTIMEDOUT; fdc->sc_errors = 4; } break; case DVACT_POWERDOWN: fd_motor_off(self); break; } return (rv); } /* * Translate nvram type into internal data structure. Return NULL for * none/unknown/unusable. */ struct fd_type * fd_nvtotype(char *fdc, int nvraminfo, int drive) { #ifdef __alpha__ /* Alpha: assume 1.44MB, idea from NetBSD sys/dev/isa/fd.c * -- jay@rootaction.net */ return &fd_types[0]; /* 1.44MB */ #else int type; type = (drive == 0 ? nvraminfo : nvraminfo << 4) & 0xf0; switch (type) { case NVRAM_DISKETTE_NONE: return NULL; case NVRAM_DISKETTE_12M: return &fd_types[1]; case NVRAM_DISKETTE_TYPE5: case NVRAM_DISKETTE_TYPE6: return &fd_types[7]; case NVRAM_DISKETTE_144M: return &fd_types[0]; case NVRAM_DISKETTE_360K: return &fd_types[3]; case NVRAM_DISKETTE_720K: return &fd_types[4]; default: printf("%s: drive %d: unknown device type 0x%x\n", fdc, drive, type); return NULL; } #endif } static __inline struct fd_type * fd_dev_to_type(struct fd_softc *fd, dev_t dev) { int type = FDTYPE(dev); if (type > (sizeof(fd_types) / sizeof(fd_types[0]))) return NULL; return type ? &fd_types[type - 1] : fd->sc_deftype; } void fdstrategy(struct buf *bp) { struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(bp->b_dev)]; int sz; int s; int fd_bsize = FD_BSIZE(fd); int bf = fd_bsize / DEV_BSIZE; /* Valid unit, controller, and request? */ if (bp->b_blkno < 0 || (((bp->b_blkno % bf) != 0 || (bp->b_bcount % fd_bsize) != 0) && (bp->b_flags & B_FORMAT) == 0)) { bp->b_error = EINVAL; goto bad; } /* If it's a null transfer, return immediately. */ if (bp->b_bcount == 0) goto done; sz = howmany(bp->b_bcount, DEV_BSIZE); if (bp->b_blkno + sz > fd->sc_type->size * bf) { sz = fd->sc_type->size * bf - bp->b_blkno; if (sz == 0) /* If exactly at end of disk, return EOF. */ goto done; if (sz < 0) { /* If past end of disk, return EINVAL. */ bp->b_error = EINVAL; goto bad; } /* Otherwise, truncate request. */ bp->b_bcount = sz << DEV_BSHIFT; } bp->b_resid = bp->b_bcount; #ifdef FD_DEBUG printf("fdstrategy: b_blkno %lld b_bcount %d blkno %lld sz %d\n", (long long)bp->b_blkno, bp->b_bcount, (long long)fd->sc_blkno, sz); #endif /* Queue I/O */ bufq_queue(&fd->sc_bufq, bp); /* Queue transfer on drive, activate drive and controller if idle. */ s = splbio(); timeout_del(&fd->fd_motor_off_to); /* a good idea */ if (fd->sc_bp == NULL) fdstart(fd); #ifdef DIAGNOSTIC else { struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent; if (fdc->sc_state == DEVIDLE) { printf("fdstrategy: controller inactive\n"); fdcstart(fdc); } } #endif splx(s); return; bad: bp->b_flags |= B_ERROR; done: /* Toss transfer; we're done early. */ bp->b_resid = bp->b_bcount; s = splbio(); biodone(bp); splx(s); } void fdstart(struct fd_softc *fd) { struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent; int active = !TAILQ_EMPTY(&fdc->sc_link.fdlink.sc_drives); /* Link into controller queue. */ fd->sc_bp = bufq_dequeue(&fd->sc_bufq); TAILQ_INSERT_TAIL(&fdc->sc_link.fdlink.sc_drives, fd, sc_drivechain); /* If controller not already active, start it. */ if (!active) fdcstart(fdc); } void fdfinish(struct fd_softc *fd, struct buf *bp) { struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent; splassert(IPL_BIO); fd->sc_skip = 0; fd->sc_bp = bufq_dequeue(&fd->sc_bufq); /* * Move this drive to the end of the queue to give others a `fair' * chance. We only force a switch if N operations are completed while * another drive is waiting to be serviced, since there is a long motor * startup delay whenever we switch. */ if (TAILQ_NEXT(fd, sc_drivechain) != NULL && ++fd->sc_ops >= 8) { fd->sc_ops = 0; TAILQ_REMOVE(&fdc->sc_link.fdlink.sc_drives, fd, sc_drivechain); if (fd->sc_bp != NULL) { TAILQ_INSERT_TAIL(&fdc->sc_link.fdlink.sc_drives, fd, sc_drivechain); } } biodone(bp); /* turn off motor 5s from now */ timeout_add_sec(&fd->fd_motor_off_to, 5); fdc->sc_state = DEVIDLE; } int fdread(dev_t dev, struct uio *uio, int flags) { return (physio(fdstrategy, dev, B_READ, minphys, uio)); } int fdwrite(dev_t dev, struct uio *uio, int flags) { return (physio(fdstrategy, dev, B_WRITE, minphys, uio)); } void fd_set_motor(struct fdc_softc *fdc, int reset) { struct fd_softc *fd; u_char status; int n; if ((fd = TAILQ_FIRST(&fdc->sc_link.fdlink.sc_drives)) != NULL) status = fd->sc_drive; else status = 0; if (!reset) status |= FDO_FRST | FDO_FDMAEN; for (n = 0; n < 4; n++) if ((fd = fdc->sc_link.fdlink.sc_fd[n]) && (fd->sc_flags & FD_MOTOR)) status |= FDO_MOEN(n); bus_space_write_1(fdc->sc_iot, fdc->sc_ioh, fdout, status); } void fd_motor_off(void *arg) { struct fd_softc *fd = arg; int s; s = splbio(); fd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT); fd_set_motor((struct fdc_softc *)fd->sc_dev.dv_parent, 0); splx(s); } void fd_motor_on(void *arg) { struct fd_softc *fd = arg; struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent; int s; s = splbio(); fd->sc_flags &= ~FD_MOTOR_WAIT; if ((TAILQ_FIRST(&fdc->sc_link.fdlink.sc_drives) == fd) && (fdc->sc_state == MOTORWAIT)) (void) fdintr(fdc); splx(s); } int fdopen(dev_t dev, int flags, int fmt, struct proc *p) { int unit, pmask; struct fd_softc *fd; struct fd_type *type; unit = FDUNIT(dev); if (unit >= fd_cd.cd_ndevs) return ENXIO; fd = fd_cd.cd_devs[unit]; if (fd == 0) return ENXIO; type = fd_dev_to_type(fd, dev); if (type == NULL) return ENXIO; if ((fd->sc_flags & FD_OPEN) != 0 && fd->sc_type != type) return EBUSY; fd->sc_type = type; fd->sc_cylin = -1; fd->sc_flags |= FD_OPEN; /* * Only update the disklabel if we're not open anywhere else. */ if (fd->sc_dk.dk_openmask == 0) fdgetdisklabel(dev, fd, fd->sc_dk.dk_label, 0); pmask = (1 << FDPART(dev)); switch (fmt) { case S_IFCHR: fd->sc_dk.dk_copenmask |= pmask; break; case S_IFBLK: fd->sc_dk.dk_bopenmask |= pmask; break; } fd->sc_dk.dk_openmask = fd->sc_dk.dk_copenmask | fd->sc_dk.dk_bopenmask; return 0; } int fdclose(dev_t dev, int flags, int fmt, struct proc *p) { struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)]; int pmask = (1 << FDPART(dev)); fd->sc_flags &= ~FD_OPEN; fd->sc_opts &= ~FDOPT_NORETRY; switch (fmt) { case S_IFCHR: fd->sc_dk.dk_copenmask &= ~pmask; break; case S_IFBLK: fd->sc_dk.dk_bopenmask &= ~pmask; break; } fd->sc_dk.dk_openmask = fd->sc_dk.dk_copenmask | fd->sc_dk.dk_bopenmask; return (0); } daddr_t fdsize(dev_t dev) { /* Swapping to floppies would not make sense. */ return -1; } int fddump(dev_t dev, daddr_t blkno, caddr_t va, size_t size) { /* Not implemented. */ return ENXIO; } /* * Called from the controller. */ int fdintr(struct fdc_softc *fdc) { #define st0 fdc->sc_status[0] #define cyl fdc->sc_status[1] struct fd_softc *fd; struct buf *bp; bus_space_tag_t iot = fdc->sc_iot; bus_space_handle_t ioh = fdc->sc_ioh; bus_space_handle_t ioh_ctl = fdc->sc_ioh_ctl; int read, head, sec, i, nblks, cylin; struct fd_type *type; struct fd_formb *finfo = NULL; int fd_bsize; loop: /* Is there a transfer to this drive? If not, deactivate drive. */ fd = TAILQ_FIRST(&fdc->sc_link.fdlink.sc_drives); if (fd == NULL) { fdc->sc_state = DEVIDLE; return 1; } fd_bsize = FD_BSIZE(fd); bp = fd->sc_bp; if (bp == NULL) { fd->sc_ops = 0; TAILQ_REMOVE(&fdc->sc_link.fdlink.sc_drives, fd, sc_drivechain); goto loop; } if (bp->b_flags & B_FORMAT) finfo = (struct fd_formb *)bp->b_data; cylin = ((bp->b_blkno * DEV_BSIZE) + (bp->b_bcount - bp->b_resid)) / (fd_bsize * fd->sc_type->seccyl); switch (fdc->sc_state) { case DEVIDLE: fdc->sc_errors = 0; fd->sc_skip = 0; fd->sc_bcount = bp->b_bcount; fd->sc_blkno = bp->b_blkno / (fd_bsize / DEV_BSIZE); timeout_del(&fd->fd_motor_off_to); if ((fd->sc_flags & FD_MOTOR_WAIT) != 0) { fdc->sc_state = MOTORWAIT; return 1; } if ((fd->sc_flags & FD_MOTOR) == 0) { /* Turn on the motor, being careful about pairing. */ struct fd_softc *ofd = fdc->sc_link.fdlink.sc_fd[fd->sc_drive ^ 1]; if (ofd && ofd->sc_flags & FD_MOTOR) { timeout_del(&ofd->fd_motor_off_to); ofd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT); } fd->sc_flags |= FD_MOTOR | FD_MOTOR_WAIT; fd_set_motor(fdc, 0); fdc->sc_state = MOTORWAIT; /* Allow .25s for motor to stabilize. */ timeout_add_msec(&fd->fd_motor_on_to, 250); return 1; } /* Make sure the right drive is selected. */ fd_set_motor(fdc, 0); /* FALLTHROUGH */ case DOSEEK: doseek: if (fd->sc_cylin == cylin) goto doio; out_fdc(iot, ioh, NE7CMD_SPECIFY);/* specify command */ out_fdc(iot, ioh, fd->sc_type->steprate); out_fdc(iot, ioh, 6); /* XXX head load time == 6ms */ out_fdc(iot, ioh, NE7CMD_SEEK); /* seek function */ out_fdc(iot, ioh, fd->sc_drive); /* drive number */ out_fdc(iot, ioh, cylin * fd->sc_type->step); fd->sc_cylin = -1; fdc->sc_state = SEEKWAIT; fd->sc_dk.dk_seek++; disk_busy(&fd->sc_dk); timeout_add_sec(&fd->fdtimeout_to, 4); return 1; case DOIO: doio: type = fd->sc_type; if (finfo) fd->sc_skip = (char *)&(finfo->fd_formb_cylno(0)) - (char *)finfo; sec = fd->sc_blkno % type->seccyl; nblks = type->seccyl - sec; nblks = min(nblks, fd->sc_bcount / fd_bsize); nblks = min(nblks, FDC_MAXIOSIZE / fd_bsize); fd->sc_nblks = nblks; fd->sc_nbytes = finfo ? bp->b_bcount : nblks * fd_bsize; head = sec / type->sectrac; sec -= head * type->sectrac; #ifdef DIAGNOSTIC {int block; block = (fd->sc_cylin * type->heads + head) * type->sectrac + sec; if (block != fd->sc_blkno) { panic("fdintr: block %d != blkno %llu", block, fd->sc_blkno); }} #endif read = bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE; isadma_start(bp->b_data + fd->sc_skip, fd->sc_nbytes, fdc->sc_drq, read); bus_space_write_1(iot, ioh_ctl, fdctl, type->rate); #ifdef FD_DEBUG printf("fdintr: %s drive %d track %d head %d sec %d nblks %d\n", read ? "read" : "write", fd->sc_drive, fd->sc_cylin, head, sec, nblks); #endif if (finfo) { /* formatting */ if (out_fdc(iot, ioh, NE7CMD_FORMAT) < 0) { fdc->sc_errors = 4; fdretry(fd); goto loop; } out_fdc(iot, ioh, (head << 2) | fd->sc_drive); out_fdc(iot, ioh, finfo->fd_formb_secshift); out_fdc(iot, ioh, finfo->fd_formb_nsecs); out_fdc(iot, ioh, finfo->fd_formb_gaplen); out_fdc(iot, ioh, finfo->fd_formb_fillbyte); } else { if (read) out_fdc(iot, ioh, NE7CMD_READ); /* READ */ else out_fdc(iot, ioh, NE7CMD_WRITE);/* WRITE */ out_fdc(iot, ioh, (head << 2) | fd->sc_drive); out_fdc(iot, ioh, fd->sc_cylin); /* track */ out_fdc(iot, ioh, head); out_fdc(iot, ioh, sec + 1); /* sec +1 */ out_fdc(iot, ioh, type->secsize); /* sec size */ out_fdc(iot, ioh, type->sectrac); /* secs/track */ out_fdc(iot, ioh, type->gap1); /* gap1 size */ out_fdc(iot, ioh, type->datalen); /* data len */ } fdc->sc_state = IOCOMPLETE; disk_busy(&fd->sc_dk); /* allow 2 seconds for operation */ timeout_add_sec(&fd->fdtimeout_to, 2); return 1; /* will return later */ case SEEKWAIT: timeout_del(&fd->fdtimeout_to); fdc->sc_state = SEEKCOMPLETE; /* allow 1/50 second for heads to settle */ timeout_add_msec(&fdc->fdcpseudointr_to, 20); return 1; case SEEKCOMPLETE: disk_unbusy(&fd->sc_dk, 0, 0, 0); /* no data on seek */ /* Make sure seek really happened. */ out_fdc(iot, ioh, NE7CMD_SENSEI); if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 || cyl != cylin * fd->sc_type->step) { #ifdef FD_DEBUG fdcstatus(&fd->sc_dev, 2, "seek failed"); #endif fdretry(fd); goto loop; } fd->sc_cylin = cylin; goto doio; case IOTIMEDOUT: isadma_abort(fdc->sc_drq); case SEEKTIMEDOUT: case RECALTIMEDOUT: case RESETTIMEDOUT: fdretry(fd); goto loop; case IOCOMPLETE: /* IO DONE, post-analyze */ timeout_del(&fd->fdtimeout_to); disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid), fd->sc_blkno, (bp->b_flags & B_READ)); if (fdcresult(fdc) != 7 || (st0 & 0xf8) != 0) { isadma_abort(fdc->sc_drq); #ifdef FD_DEBUG fdcstatus(&fd->sc_dev, 7, bp->b_flags & B_READ ? "read failed" : "write failed"); printf("blkno %lld nblks %d\n", (long long)fd->sc_blkno, fd->sc_nblks); #endif fdretry(fd); goto loop; } read = bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE; isadma_done(fdc->sc_drq); if (fdc->sc_errors) { diskerr(bp, "fd", "soft error", LOG_PRINTF, fd->sc_skip / fd_bsize, (struct disklabel *)NULL); printf("\n"); fdc->sc_errors = 0; } fd->sc_blkno += fd->sc_nblks; fd->sc_skip += fd->sc_nbytes; fd->sc_bcount -= fd->sc_nbytes; bp->b_resid -= fd->sc_nbytes; if (!finfo && fd->sc_bcount > 0) { cylin = fd->sc_blkno / fd->sc_type->seccyl; goto doseek; } fdfinish(fd, bp); goto loop; case DORESET: /* try a reset, keep motor on */ fd_set_motor(fdc, 1); delay(100); fd_set_motor(fdc, 0); fdc->sc_state = RESETCOMPLETE; timeout_add_msec(&fd->fdtimeout_to, 500); return 1; /* will return later */ case RESETCOMPLETE: timeout_del(&fd->fdtimeout_to); /* clear the controller output buffer */ for (i = 0; i < 4; i++) { out_fdc(iot, ioh, NE7CMD_SENSEI); (void) fdcresult(fdc); } /* FALLTHROUGH */ case DORECAL: out_fdc(iot, ioh, NE7CMD_RECAL); /* recal function */ out_fdc(iot, ioh, fd->sc_drive); fdc->sc_state = RECALWAIT; timeout_add_sec(&fd->fdtimeout_to, 5); return 1; /* will return later */ case RECALWAIT: timeout_del(&fd->fdtimeout_to); fdc->sc_state = RECALCOMPLETE; /* allow 1/30 second for heads to settle */ timeout_add_msec(&fdc->fdcpseudointr_to, 1000 / 30); return 1; /* will return later */ case RECALCOMPLETE: out_fdc(iot, ioh, NE7CMD_SENSEI); if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 || cyl != 0) { #ifdef FD_DEBUG fdcstatus(&fd->sc_dev, 2, "recalibrate failed"); #endif fdretry(fd); goto loop; } fd->sc_cylin = 0; goto doseek; case MOTORWAIT: if (fd->sc_flags & FD_MOTOR_WAIT) return 1; /* time's not up yet */ goto doseek; default: fdcstatus(&fd->sc_dev, 0, "stray interrupt"); return 1; } #ifdef DIAGNOSTIC panic("fdintr: impossible"); #endif #undef st0 #undef cyl } void fdtimeout(void *arg) { struct fd_softc *fd = arg; struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent; int s; s = splbio(); #ifdef DEBUG log(LOG_ERR,"fdtimeout: state %d\n", fdc->sc_state); #endif fdcstatus(&fd->sc_dev, 0, "timeout"); if (fd->sc_bp != NULL) fdc->sc_state++; else fdc->sc_state = DEVIDLE; (void) fdintr(fdc); splx(s); } void fdretry(struct fd_softc *fd) { struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent; struct buf *bp = fd->sc_bp; if (fd->sc_opts & FDOPT_NORETRY) goto fail; switch (fdc->sc_errors) { case 0: /* try again */ fdc->sc_state = DOSEEK; break; case 1: case 2: case 3: /* didn't work; try recalibrating */ fdc->sc_state = DORECAL; break; case 4: /* still no go; reset the bastard */ fdc->sc_state = DORESET; break; default: fail: diskerr(bp, "fd", "hard error", LOG_PRINTF, fd->sc_skip / FD_BSIZE(fd), (struct disklabel *)NULL); printf(" (st0 %b st1 %b st2 %b cyl %d head %d sec %d)\n", fdc->sc_status[0], NE7_ST0BITS, fdc->sc_status[1], NE7_ST1BITS, fdc->sc_status[2], NE7_ST2BITS, fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]); bp->b_flags |= B_ERROR; bp->b_error = EIO; bp->b_resid = bp->b_bcount; fdfinish(fd, bp); } fdc->sc_errors++; } int fdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)]; struct disklabel *lp; int error; switch (cmd) { case MTIOCTOP: if (((struct mtop *)addr)->mt_op != MTOFFL) return EIO; return (0); case DIOCRLDINFO: lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK); fdgetdisklabel(dev, fd, lp, 0); bcopy(lp, fd->sc_dk.dk_label, sizeof(*lp)); free(lp, M_TEMP, sizeof(*lp)); return 0; case DIOCGPDINFO: fdgetdisklabel(dev, fd, (struct disklabel *)addr, 1); return 0; case DIOCGDINFO: *(struct disklabel *)addr = *(fd->sc_dk.dk_label); return 0; case DIOCGPART: ((struct partinfo *)addr)->disklab = fd->sc_dk.dk_label; ((struct partinfo *)addr)->part = &fd->sc_dk.dk_label->d_partitions[FDPART(dev)]; return 0; case DIOCWDINFO: case DIOCSDINFO: if ((flag & FWRITE) == 0) return EBADF; error = setdisklabel(fd->sc_dk.dk_label, (struct disklabel *)addr, 0); if (error == 0) { if (cmd == DIOCWDINFO) error = writedisklabel(DISKLABELDEV(dev), fdstrategy, fd->sc_dk.dk_label); } return error; case FD_FORM: if((flag & FWRITE) == 0) return EBADF; /* must be opened for writing */ else if(((struct fd_formb *)addr)->format_version != FD_FORMAT_VERSION) return EINVAL; /* wrong version of formatting prog */ else return fdformat(dev, (struct fd_formb *)addr, p); break; case FD_GTYPE: /* get drive type */ *(struct fd_type *)addr = *fd->sc_type; return 0; case FD_GOPTS: /* get drive options */ *(int *)addr = fd->sc_opts; return 0; case FD_SOPTS: /* set drive options */ fd->sc_opts = *(int *)addr; return 0; default: return ENOTTY; } #ifdef DIAGNOSTIC panic("fdioctl: impossible"); #endif } int fdformat(dev_t dev, struct fd_formb *finfo, struct proc *p) { int rv = 0; struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)]; struct fd_type *type = fd->sc_type; struct buf *bp; int fd_bsize = FD_BSIZE(fd); /* set up a buffer header for fdstrategy() */ bp = malloc(sizeof(*bp), M_TEMP, M_NOWAIT | M_ZERO); if (bp == NULL) return ENOBUFS; bp->b_flags = B_BUSY | B_PHYS | B_FORMAT | B_RAW; bp->b_proc = p; bp->b_dev = dev; /* * calculate a fake blkno, so fdstrategy() would initiate a * seek to the requested cylinder */ bp->b_blkno = (finfo->cyl * (type->sectrac * type->heads) + finfo->head * type->sectrac) * fd_bsize / DEV_BSIZE; bp->b_bcount = sizeof(struct fd_idfield_data) * finfo->fd_formb_nsecs; bp->b_data = (caddr_t)finfo; #ifdef DEBUG printf("fdformat: blkno %llx count %lx\n", bp->b_blkno, bp->b_bcount); #endif /* now do the format */ fdstrategy(bp); /* ...and wait for it to complete */ rv = biowait(bp); free(bp, M_TEMP, sizeof(*bp)); return (rv); }
319 319 318 207 30 170 2 8 7 177 102 37 7 66 82 78 2 6 37 59 79 37 54 226 227 319 318 157 157 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 /* $OpenBSD: ufs_quota.c,v 1.47 2020/06/24 22:03:45 cheloha Exp $ */ /* $NetBSD: ufs_quota.c,v 1.8 1996/02/09 22:36:09 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1990, 1993, 1995 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Robert Elz at The University of Melbourne. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ufs_quota.c 8.5 (Berkeley) 8/19/94 */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/systm.h> #include <sys/namei.h> #include <sys/malloc.h> #include <sys/fcntl.h> #include <sys/proc.h> #include <sys/vnode.h> #include <sys/mount.h> #include <sys/ktrace.h> #include <ufs/ufs/quota.h> #include <ufs/ufs/inode.h> #include <ufs/ufs/ufsmount.h> #include <ufs/ufs/ufs_extern.h> #include <sys/queue.h> #include <crypto/siphash.h> /* * The following structure records disk usage for a user or group on a * filesystem. There is one allocated for each quota that exists on any * filesystem for the current user or group. A cache is kept of recently * used entries. */ struct dquot { LIST_ENTRY(dquot) dq_hash; /* hash list */ TAILQ_ENTRY(dquot) dq_freelist; /* free list */ u_int16_t dq_flags; /* flags, see below */ u_int16_t dq_type; /* quota type of this dquot */ u_int32_t dq_cnt; /* count of active references */ u_int32_t dq_id; /* identifier this applies to */ struct vnode *dq_vp; /* file backing this quota */ struct ucred *dq_cred; /* credentials for writing file */ struct dqblk dq_dqb; /* actual usage & quotas */ }; /* * Flag values. */ #define DQ_LOCK 0x01 /* this quota locked (no MODS) */ #define DQ_WANT 0x02 /* wakeup on unlock */ #define DQ_MOD 0x04 /* this quota modified since read */ #define DQ_FAKE 0x08 /* no limits here, just usage */ #define DQ_BLKS 0x10 /* has been warned about blk limit */ #define DQ_INODS 0x20 /* has been warned about inode limit */ /* * Shorthand notation. */ #define dq_bhardlimit dq_dqb.dqb_bhardlimit #define dq_bsoftlimit dq_dqb.dqb_bsoftlimit #define dq_curblocks dq_dqb.dqb_curblocks #define dq_ihardlimit dq_dqb.dqb_ihardlimit #define dq_isoftlimit dq_dqb.dqb_isoftlimit #define dq_curinodes dq_dqb.dqb_curinodes #define dq_btime dq_dqb.dqb_btime #define dq_itime dq_dqb.dqb_itime /* * If the system has never checked for a quota for this file, then it is * set to NODQUOT. Once a write attempt is made the inode pointer is set * to reference a dquot structure. */ #define NODQUOT NULL void dqref(struct dquot *); void dqrele(struct vnode *, struct dquot *); int dqsync(struct vnode *, struct dquot *); #ifdef DIAGNOSTIC void chkdquot(struct inode *); #endif int getquota(struct mount *, u_long, int, caddr_t); int quotaon(struct proc *, struct mount *, int, caddr_t); int setquota(struct mount *, u_long, int, caddr_t); int setuse(struct mount *, u_long, int, caddr_t); int chkdqchg(struct inode *, long, struct ucred *, int); int chkiqchg(struct inode *, long, struct ucred *, int); int dqget(struct vnode *, u_long, struct ufsmount *, int, struct dquot **); int quotaon_vnode(struct vnode *, void *); int quotaoff_vnode(struct vnode *, void *); int qsync_vnode(struct vnode *, void *); /* * Quota name to error message mapping. */ static char *quotatypes[] = INITQFNAMES; /* * Obtain a reference to a dquot. */ void dqref(struct dquot *dq) { dq->dq_cnt++; } /* * Set up the quotas for an inode. * * This routine completely defines the semantics of quotas. * If other criterion want to be used to establish quotas, the * MAXQUOTAS value in quotas.h should be increased, and the * additional dquots set up here. */ int getinoquota(struct inode *ip) { struct ufsmount *ump; struct vnode *vp = ITOV(ip); int error; ump = ip->i_ump; /* * Set up the user quota based on file uid. * EINVAL means that quotas are not enabled. */ if (ip->i_dquot[USRQUOTA] == NODQUOT && (error = dqget(vp, DIP(ip, uid), ump, USRQUOTA, &ip->i_dquot[USRQUOTA])) && error != EINVAL) return (error); /* * Set up the group quota based on file gid. * EINVAL means that quotas are not enabled. */ if (ip->i_dquot[GRPQUOTA] == NODQUOT && (error = dqget(vp, DIP(ip, gid), ump, GRPQUOTA, &ip->i_dquot[GRPQUOTA])) && error != EINVAL) return (error); return (0); } /* * Update disk usage, and take corrective action. */ int ufs_quota_alloc_blocks2(struct inode *ip, daddr_t change, struct ucred *cred, enum ufs_quota_flags flags) { struct dquot *dq; int i; int error; #ifdef DIAGNOSTIC chkdquot(ip); #endif if (change == 0) return (0); if ((flags & UFS_QUOTA_FORCE) == 0 && (cred != NOCRED && cred->cr_uid != 0)) { for (i = 0; i < MAXQUOTAS; i++) { if (flags & (1 << i)) continue; if ((dq = ip->i_dquot[i]) == NODQUOT) continue; if ((error = chkdqchg(ip, change, cred, i)) != 0) return (error); } } for (i = 0; i < MAXQUOTAS; i++) { if (flags & (1 << i)) continue; if ((dq = ip->i_dquot[i]) == NODQUOT) continue; while (dq->dq_flags & DQ_LOCK) { dq->dq_flags |= DQ_WANT; tsleep_nsec(dq, PINOD+1, "chkdq", INFSLP); } dq->dq_curblocks += change; dq->dq_flags |= DQ_MOD; } return (0); } int ufs_quota_free_blocks2(struct inode *ip, daddr_t change, struct ucred *cred, enum ufs_quota_flags flags) { struct dquot *dq; int i; #ifdef DIAGNOSTIC if (!VOP_ISLOCKED(ITOV(ip))) panic ("ufs_quota_free_blocks2: vnode is not locked"); #endif if (change == 0) return (0); for (i = 0; i < MAXQUOTAS; i++) { if (flags & (1 << i)) continue; if ((dq = ip->i_dquot[i]) == NODQUOT) continue; while (dq->dq_flags & DQ_LOCK) { dq->dq_flags |= DQ_WANT; tsleep_nsec(dq, PINOD+1, "chkdq", INFSLP); } if (dq->dq_curblocks >= change) dq->dq_curblocks -= change; else dq->dq_curblocks = 0; dq->dq_flags &= ~DQ_BLKS; dq->dq_flags |= DQ_MOD; } return (0); } /* * Check for a valid change to a users allocation. * Issue an error message if appropriate. */ int chkdqchg(struct inode *ip, long change, struct ucred *cred, int type) { struct dquot *dq = ip->i_dquot[type]; long ncurblocks = dq->dq_curblocks + change; /* * If user would exceed their hard limit, disallow space allocation. */ if (ncurblocks >= dq->dq_bhardlimit && dq->dq_bhardlimit) { if ((dq->dq_flags & DQ_BLKS) == 0 && DIP(ip, uid) == cred->cr_uid) { uprintf("\n%s: write failed, %s disk limit reached\n", ITOV(ip)->v_mount->mnt_stat.f_mntonname, quotatypes[type]); dq->dq_flags |= DQ_BLKS; } return (EDQUOT); } /* * If user is over their soft limit for too long, disallow space * allocation. Reset time limit as they cross their soft limit. */ if (ncurblocks >= dq->dq_bsoftlimit && dq->dq_bsoftlimit) { if (dq->dq_curblocks < dq->dq_bsoftlimit) { dq->dq_btime = gettime() + ip->i_ump->um_btime[type]; if (DIP(ip, uid) == cred->cr_uid) uprintf("\n%s: warning, %s %s\n", ITOV(ip)->v_mount->mnt_stat.f_mntonname, quotatypes[type], "disk quota exceeded"); return (0); } if (gettime() > dq->dq_btime) { if ((dq->dq_flags & DQ_BLKS) == 0 && DIP(ip, uid) == cred->cr_uid) { uprintf("\n%s: write failed, %s %s\n", ITOV(ip)->v_mount->mnt_stat.f_mntonname, quotatypes[type], "disk quota exceeded for too long"); dq->dq_flags |= DQ_BLKS; } return (EDQUOT); } } return (0); } /* * Check the inode limit, applying corrective action. */ int ufs_quota_alloc_inode2(struct inode *ip, struct ucred *cred, enum ufs_quota_flags flags) { struct dquot *dq; int i; int error; #ifdef DIAGNOSTIC chkdquot(ip); #endif if ((flags & UFS_QUOTA_FORCE) == 0 && cred->cr_uid != 0) { for (i = 0; i < MAXQUOTAS; i++) { if (flags & (1 << i)) continue; if ((dq = ip->i_dquot[i]) == NODQUOT) continue; if ((error = chkiqchg(ip, 1, cred, i)) != 0) return (error); } } for (i = 0; i < MAXQUOTAS; i++) { if (flags & (1 << i)) continue; if ((dq = ip->i_dquot[i]) == NODQUOT) continue; while (dq->dq_flags & DQ_LOCK) { dq->dq_flags |= DQ_WANT; tsleep_nsec(dq, PINOD+1, "chkiq", INFSLP); } dq->dq_curinodes++; dq->dq_flags |= DQ_MOD; } return (0); } int ufs_quota_free_inode2(struct inode *ip, struct ucred *cred, enum ufs_quota_flags flags) { struct dquot *dq; int i; #ifdef DIAGNOSTIC if (!VOP_ISLOCKED(ITOV(ip))) panic ("ufs_quota_free_blocks2: vnode is not locked"); #endif for (i = 0; i < MAXQUOTAS; i++) { if (flags & (1 << i)) continue; if ((dq = ip->i_dquot[i]) == NODQUOT) continue; while (dq->dq_flags & DQ_LOCK) { dq->dq_flags |= DQ_WANT; tsleep_nsec(dq, PINOD+1, "chkiq", INFSLP); } if (dq->dq_curinodes > 0) dq->dq_curinodes--; dq->dq_flags &= ~DQ_INODS; dq->dq_flags |= DQ_MOD; } return (0); } /* * Check for a valid change to a users allocation. * Issue an error message if appropriate. */ int chkiqchg(struct inode *ip, long change, struct ucred *cred, int type) { struct dquot *dq = ip->i_dquot[type]; long ncurinodes = dq->dq_curinodes + change; /* * If user would exceed their hard limit, disallow inode allocation. */ if (ncurinodes >= dq->dq_ihardlimit && dq->dq_ihardlimit) { if ((dq->dq_flags & DQ_INODS) == 0 && DIP(ip, uid) == cred->cr_uid) { uprintf("\n%s: write failed, %s inode limit reached\n", ITOV(ip)->v_mount->mnt_stat.f_mntonname, quotatypes[type]); dq->dq_flags |= DQ_INODS; } return (EDQUOT); } /* * If user is over their soft limit for too long, disallow inode * allocation. Reset time limit as they cross their soft limit. */ if (ncurinodes >= dq->dq_isoftlimit && dq->dq_isoftlimit) { if (dq->dq_curinodes < dq->dq_isoftlimit) { dq->dq_itime = gettime() + ip->i_ump->um_itime[type]; if (DIP(ip, uid) == cred->cr_uid) uprintf("\n%s: warning, %s %s\n", ITOV(ip)->v_mount->mnt_stat.f_mntonname, quotatypes[type], "inode quota exceeded"); return (0); } if (gettime() > dq->dq_itime) { if ((dq->dq_flags & DQ_INODS) == 0 && DIP(ip, uid) == cred->cr_uid) { uprintf("\n%s: write failed, %s %s\n", ITOV(ip)->v_mount->mnt_stat.f_mntonname, quotatypes[type], "inode quota exceeded for too long"); dq->dq_flags |= DQ_INODS; } return (EDQUOT); } } return (0); } #ifdef DIAGNOSTIC /* * On filesystems with quotas enabled, it is an error for a file to change * size and not to have a dquot structure associated with it. */ void chkdquot(struct inode *ip) { struct ufsmount *ump = ip->i_ump; int i; struct vnode *vp = ITOV(ip); if (!VOP_ISLOCKED(vp)) panic ("chkdquot: vnode is not locked"); for (i = 0; i < MAXQUOTAS; i++) { if (ump->um_quotas[i] == NULLVP || (ump->um_qflags[i] & (QTF_OPENING|QTF_CLOSING))) continue; if (ip->i_dquot[i] == NODQUOT) { vprint("chkdquot: missing dquot", ITOV(ip)); panic("missing dquot"); } } } #endif /* * Code to process quotactl commands. */ int quotaon_vnode(struct vnode *vp, void *arg) { int error; if (vp->v_type == VNON || vp->v_writecount == 0) return (0); if (vget(vp, LK_EXCLUSIVE)) { return (0); } error = getinoquota(VTOI(vp)); vput(vp); return (error); } /* * Q_QUOTAON - set up a quota file for a particular file system. */ int quotaon(struct proc *p, struct mount *mp, int type, caddr_t fname) { struct ufsmount *ump = VFSTOUFS(mp); struct vnode *vp, **vpp; struct dquot *dq; int error; struct nameidata nd; #ifdef DIAGNOSTIC if (!vfs_isbusy(mp)) panic ("quotaon: mount point not busy"); #endif vpp = &ump->um_quotas[type]; NDINIT(&nd, 0, 0, UIO_USERSPACE, fname, p); if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) return (error); vp = nd.ni_vp; VOP_UNLOCK(vp); if (vp->v_type != VREG) { (void) vn_close(vp, FREAD|FWRITE, p->p_ucred, p); return (EACCES); } /* * Update the vnode and ucred for quota file updates */ if (*vpp != vp) { quotaoff(p, mp, type); *vpp = vp; crhold(p->p_ucred); ump->um_cred[type] = p->p_ucred; } else { struct ucred *ocred = ump->um_cred[type]; (void) vn_close(vp, FREAD|FWRITE, ocred, p); if (ocred != p->p_ucred) { crhold(p->p_ucred); ump->um_cred[type] = p->p_ucred; crfree(ocred); } } ump->um_qflags[type] |= QTF_OPENING; mp->mnt_flag |= MNT_QUOTA; vp->v_flag |= VSYSTEM; /* * Set up the time limits for this quota. */ ump->um_btime[type] = MAX_DQ_TIME; ump->um_itime[type] = MAX_IQ_TIME; if (dqget(NULLVP, 0, ump, type, &dq) == 0) { if (dq->dq_btime > 0) ump->um_btime[type] = dq->dq_btime; if (dq->dq_itime > 0) ump->um_itime[type] = dq->dq_itime; dqrele(NULLVP, dq); } /* * Search vnodes associated with this mount point, * adding references to quota file being opened. * NB: only need to add dquot's for inodes being modified. */ error = vfs_mount_foreach_vnode(mp, quotaon_vnode, NULL); ump->um_qflags[type] &= ~QTF_OPENING; if (error) quotaoff(p, mp, type); return (error); } struct quotaoff_arg { struct proc *p; int type; }; int quotaoff_vnode(struct vnode *vp, void *arg) { struct quotaoff_arg *qa = (struct quotaoff_arg *)arg; struct inode *ip; struct dquot *dq; if (vp->v_type == VNON) return (0); if (vget(vp, LK_EXCLUSIVE)) return (0); ip = VTOI(vp); dq = ip->i_dquot[qa->type]; ip->i_dquot[qa->type] = NODQUOT; dqrele(vp, dq); vput(vp); return (0); } /* * Q_QUOTAOFF - turn off disk quotas for a filesystem. */ int quotaoff(struct proc *p, struct mount *mp, int type) { struct vnode *qvp; struct ufsmount *ump = VFSTOUFS(mp); struct quotaoff_arg qa; int error; #ifdef DIAGNOSTIC if (!vfs_isbusy(mp)) panic ("quotaoff: mount point not busy"); #endif if ((qvp = ump->um_quotas[type]) == NULLVP) return (0); ump->um_qflags[type] |= QTF_CLOSING; /* * Search vnodes associated with this mount point, * deleting any references to quota file being closed. */ qa.p = p; qa.type = type; vfs_mount_foreach_vnode(mp, quotaoff_vnode, &qa); error = vn_close(qvp, FREAD|FWRITE, p->p_ucred, p); ump->um_quotas[type] = NULLVP; crfree(ump->um_cred[type]); ump->um_cred[type] = NOCRED; ump->um_qflags[type] &= ~QTF_CLOSING; for (type = 0; type < MAXQUOTAS; type++) if (ump->um_quotas[type] != NULLVP) break; if (type == MAXQUOTAS) mp->mnt_flag &= ~MNT_QUOTA; return (error); } /* * Q_GETQUOTA - return current values in a dqblk structure. */ int getquota(struct mount *mp, u_long id, int type, caddr_t addr) { struct dquot *dq; int error; if ((error = dqget(NULLVP, id, VFSTOUFS(mp), type, &dq)) != 0) return (error); error = copyout((caddr_t)&dq->dq_dqb, addr, sizeof (struct dqblk)); #ifdef KTRACE if (error == 0) { struct proc *p = curproc; if (KTRPOINT(p, KTR_STRUCT)) ktrquota(p, &dq->dq_dqb); } #endif dqrele(NULLVP, dq); return (error); } /* * Q_SETQUOTA - assign an entire dqblk structure. */ int setquota(struct mount *mp, u_long id, int type, caddr_t addr) { struct dquot *dq; struct dquot *ndq; struct ufsmount *ump = VFSTOUFS(mp); struct dqblk newlim; int error; error = copyin(addr, (caddr_t)&newlim, sizeof (struct dqblk)); if (error) return (error); #ifdef KTRACE { struct proc *p = curproc; if (KTRPOINT(p, KTR_STRUCT)) ktrquota(p, &newlim); } #endif if ((error = dqget(NULLVP, id, ump, type, &ndq)) != 0) return (error); dq = ndq; while (dq->dq_flags & DQ_LOCK) { dq->dq_flags |= DQ_WANT; tsleep_nsec(dq, PINOD+1, "setquota", INFSLP); } /* * Copy all but the current values. * Reset time limit if previously had no soft limit or were * under it, but now have a soft limit and are over it. */ newlim.dqb_curblocks = dq->dq_curblocks; newlim.dqb_curinodes = dq->dq_curinodes; if (dq->dq_id != 0) { newlim.dqb_btime = dq->dq_btime; newlim.dqb_itime = dq->dq_itime; } if (newlim.dqb_bsoftlimit && dq->dq_curblocks >= newlim.dqb_bsoftlimit && (dq->dq_bsoftlimit == 0 || dq->dq_curblocks < dq->dq_bsoftlimit)) newlim.dqb_btime = gettime() + ump->um_btime[type]; if (newlim.dqb_isoftlimit && dq->dq_curinodes >= newlim.dqb_isoftlimit && (dq->dq_isoftlimit == 0 || dq->dq_curinodes < dq->dq_isoftlimit)) newlim.dqb_itime = gettime() + ump->um_itime[type]; dq->dq_dqb = newlim; if (dq->dq_curblocks < dq->dq_bsoftlimit) dq->dq_flags &= ~DQ_BLKS; if (dq->dq_curinodes < dq->dq_isoftlimit) dq->dq_flags &= ~DQ_INODS; if (dq->dq_isoftlimit == 0 && dq->dq_bsoftlimit == 0 && dq->dq_ihardlimit == 0 && dq->dq_bhardlimit == 0) dq->dq_flags |= DQ_FAKE; else dq->dq_flags &= ~DQ_FAKE; dq->dq_flags |= DQ_MOD; dqrele(NULLVP, dq); return (0); } /* * Q_SETUSE - set current inode and block usage. */ int setuse(struct mount *mp, u_long id, int type, caddr_t addr) { struct dquot *dq; struct ufsmount *ump = VFSTOUFS(mp); struct dquot *ndq; struct dqblk usage; int error; error = copyin(addr, (caddr_t)&usage, sizeof (struct dqblk)); if (error) return (error); #ifdef KTRACE { struct proc *p = curproc; if (KTRPOINT(p, KTR_STRUCT)) ktrquota(p, &usage); } #endif if ((error = dqget(NULLVP, id, ump, type, &ndq)) != 0) return (error); dq = ndq; while (dq->dq_flags & DQ_LOCK) { dq->dq_flags |= DQ_WANT; tsleep_nsec(dq, PINOD+1, "setuse", INFSLP); } /* * Reset time limit if have a soft limit and were * previously under it, but are now over it. */ if (dq->dq_bsoftlimit && dq->dq_curblocks < dq->dq_bsoftlimit && usage.dqb_curblocks >= dq->dq_bsoftlimit) dq->dq_btime = gettime() + ump->um_btime[type]; if (dq->dq_isoftlimit && dq->dq_curinodes < dq->dq_isoftlimit && usage.dqb_curinodes >= dq->dq_isoftlimit) dq->dq_itime = gettime() + ump->um_itime[type]; dq->dq_curblocks = usage.dqb_curblocks; dq->dq_curinodes = usage.dqb_curinodes; if (dq->dq_curblocks < dq->dq_bsoftlimit) dq->dq_flags &= ~DQ_BLKS; if (dq->dq_curinodes < dq->dq_isoftlimit) dq->dq_flags &= ~DQ_INODS; dq->dq_flags |= DQ_MOD; dqrele(NULLVP, dq); return (0); } int qsync_vnode(struct vnode *vp, void *arg) { int i; struct dquot *dq; if (vp->v_type == VNON) return (0); if (vget(vp, LK_EXCLUSIVE | LK_NOWAIT)) return (0); for (i = 0; i < MAXQUOTAS; i++) { dq = VTOI(vp)->i_dquot[i]; if (dq != NODQUOT && (dq->dq_flags & DQ_MOD)) dqsync(vp, dq); } vput(vp); return (0); } /* * Q_SYNC - sync quota files to disk. */ int qsync(struct mount *mp) { struct ufsmount *ump = VFSTOUFS(mp); int i; /* * Check if the mount point has any quotas. * If not, simply return. */ for (i = 0; i < MAXQUOTAS; i++) if (ump->um_quotas[i] != NULLVP) break; if (i == MAXQUOTAS) return (0); /* * Search vnodes associated with this mount point, * synchronizing any modified dquot structures. */ vfs_mount_foreach_vnode(mp, qsync_vnode, NULL); return (0); } /* * Code pertaining to management of the in-core dquot data structures. */ LIST_HEAD(dqhash, dquot) *dqhashtbl; SIPHASH_KEY dqhashkey; u_long dqhash; /* * Dquot free list. */ #define DQUOTINC 5 /* minimum free dquots desired */ TAILQ_HEAD(dqfreelist, dquot) dqfreelist; long numdquot, desireddquot = DQUOTINC; /* * Initialize the quota system. */ void ufs_quota_init(void) { dqhashtbl = hashinit(initialvnodes, M_DQUOT, M_WAITOK, &dqhash); arc4random_buf(&dqhashkey, sizeof(dqhashkey)); TAILQ_INIT(&dqfreelist); } /* * Obtain a dquot structure for the specified identifier and quota file * reading the information from the file if necessary. */ int dqget(struct vnode *vp, u_long id, struct ufsmount *ump, int type, struct dquot **dqp) { SIPHASH_CTX ctx; struct dquot *dq; struct dqhash *dqh; struct vnode *dqvp; struct iovec aiov; struct uio auio; int error; dqvp = ump->um_quotas[type]; if (dqvp == NULLVP || (ump->um_qflags[type] & QTF_CLOSING)) { *dqp = NODQUOT; return (EINVAL); } /* * Check the cache first. */ SipHash24_Init(&ctx, &dqhashkey); SipHash24_Update(&ctx, &dqvp, sizeof(dqvp)); SipHash24_Update(&ctx, &id, sizeof(id)); dqh = &dqhashtbl[SipHash24_End(&ctx) & dqhash]; LIST_FOREACH(dq, dqh, dq_hash) { if (dq->dq_id != id || dq->dq_vp != dqvp) continue; /* * Cache hit with no references. Take * the structure off the free list. */ if (dq->dq_cnt == 0) TAILQ_REMOVE(&dqfreelist, dq, dq_freelist); dqref(dq); *dqp = dq; return (0); } /* * Not in cache, allocate a new one. */ if (TAILQ_FIRST(&dqfreelist) == NODQUOT && numdquot < MAXQUOTAS * initialvnodes) desireddquot += DQUOTINC; if (numdquot < desireddquot) { dq = malloc(sizeof *dq, M_DQUOT, M_WAITOK | M_ZERO); numdquot++; } else { if ((dq = TAILQ_FIRST(&dqfreelist)) == NULL) { tablefull("dquot"); *dqp = NODQUOT; return (EUSERS); } if (dq->dq_cnt || (dq->dq_flags & DQ_MOD)) panic("free dquot isn't"); TAILQ_REMOVE(&dqfreelist, dq, dq_freelist); LIST_REMOVE(dq, dq_hash); crfree(dq->dq_cred); dq->dq_cred = NOCRED; } /* * Initialize the contents of the dquot structure. */ if (vp != dqvp) vn_lock(dqvp, LK_EXCLUSIVE | LK_RETRY); LIST_INSERT_HEAD(dqh, dq, dq_hash); dqref(dq); dq->dq_flags = DQ_LOCK; dq->dq_id = id; dq->dq_vp = dqvp; dq->dq_type = type; crhold(ump->um_cred[type]); dq->dq_cred = ump->um_cred[type]; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; aiov.iov_base = (caddr_t)&dq->dq_dqb; aiov.iov_len = sizeof (struct dqblk); auio.uio_resid = sizeof (struct dqblk); auio.uio_offset = (off_t)(id * sizeof (struct dqblk)); auio.uio_segflg = UIO_SYSSPACE; auio.uio_rw = UIO_READ; auio.uio_procp = NULL; error = VOP_READ(dqvp, &auio, 0, dq->dq_cred); if (auio.uio_resid == sizeof(struct dqblk) && error == 0) memset(&dq->dq_dqb, 0, sizeof(struct dqblk)); if (vp != dqvp) VOP_UNLOCK(dqvp); if (dq->dq_flags & DQ_WANT) wakeup(dq); dq->dq_flags = 0; /* * I/O error in reading quota file, release * quota structure and reflect problem to caller. */ if (error) { LIST_REMOVE(dq, dq_hash); dqrele(vp, dq); *dqp = NODQUOT; return (error); } /* * Check for no limit to enforce. * Initialize time values if necessary. */ if (dq->dq_isoftlimit == 0 && dq->dq_bsoftlimit == 0 && dq->dq_ihardlimit == 0 && dq->dq_bhardlimit == 0) dq->dq_flags |= DQ_FAKE; if (dq->dq_id != 0) { if (dq->dq_btime == 0) dq->dq_btime = gettime() + ump->um_btime[type]; if (dq->dq_itime == 0) dq->dq_itime = gettime() + ump->um_itime[type]; } *dqp = dq; return (0); } /* * Release a reference to a dquot. */ void dqrele(struct vnode *vp, struct dquot *dq) { if (dq == NODQUOT) return; if (dq->dq_cnt > 1) { dq->dq_cnt--; return; } if (dq->dq_flags & DQ_MOD) (void) dqsync(vp, dq); if (--dq->dq_cnt > 0) return; TAILQ_INSERT_TAIL(&dqfreelist, dq, dq_freelist); } /* * Update the disk quota in the quota file. */ int dqsync(struct vnode *vp, struct dquot *dq) { struct vnode *dqvp; struct iovec aiov; struct uio auio; int error; if (dq == NODQUOT) panic("dqsync: dquot"); if ((dq->dq_flags & DQ_MOD) == 0) return (0); if ((dqvp = dq->dq_vp) == NULLVP) panic("dqsync: file"); if (vp != dqvp) vn_lock(dqvp, LK_EXCLUSIVE | LK_RETRY); while (dq->dq_flags & DQ_LOCK) { dq->dq_flags |= DQ_WANT; tsleep_nsec(dq, PINOD+2, "dqsync", INFSLP); if ((dq->dq_flags & DQ_MOD) == 0) { if (vp != dqvp) VOP_UNLOCK(dqvp); return (0); } } dq->dq_flags |= DQ_LOCK; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; aiov.iov_base = (caddr_t)&dq->dq_dqb; aiov.iov_len = sizeof (struct dqblk); auio.uio_resid = sizeof (struct dqblk); auio.uio_offset = (off_t)(dq->dq_id * sizeof (struct dqblk)); auio.uio_segflg = UIO_SYSSPACE; auio.uio_rw = UIO_WRITE; auio.uio_procp = NULL; error = VOP_WRITE(dqvp, &auio, 0, dq->dq_cred); if (auio.uio_resid && error == 0) error = EIO; if (dq->dq_flags & DQ_WANT) wakeup(dq); dq->dq_flags &= ~(DQ_MOD|DQ_LOCK|DQ_WANT); if (vp != dqvp) VOP_UNLOCK(dqvp); return (error); } int ufs_quota_delete(struct inode *ip) { struct vnode *vp = ITOV(ip); int i; for (i = 0; i < MAXQUOTAS; i++) { if (ip->i_dquot[i] != NODQUOT) { dqrele(vp, ip->i_dquot[i]); ip->i_dquot[i] = NODQUOT; } } return (0); } /* * Do operations associated with quotas */ int ufs_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg, struct proc *p) { int cmd, type, error; if (uid == -1) uid = p->p_ucred->cr_ruid; cmd = cmds >> SUBCMDSHIFT; switch (cmd) { case Q_SYNC: break; case Q_GETQUOTA: if (uid == p->p_ucred->cr_ruid) break; /* FALLTHROUGH */ default: if ((error = suser(p)) != 0) return (error); } type = cmds & SUBCMDMASK; if ((u_int)type >= MAXQUOTAS) return (EINVAL); if (vfs_busy(mp, VB_READ|VB_NOWAIT)) return (0); switch (cmd) { case Q_QUOTAON: error = quotaon(p, mp, type, arg); break; case Q_QUOTAOFF: error = quotaoff(p, mp, type); break; case Q_SETQUOTA: error = setquota(mp, uid, type, arg) ; break; case Q_SETUSE: error = setuse(mp, uid, type, arg); break; case Q_GETQUOTA: error = getquota(mp, uid, type, arg); break; case Q_SYNC: error = qsync(mp); break; default: error = EINVAL; break; } vfs_unbusy(mp); return (error); }
61 22 37 4 3 127 127 127 127 1 1 1 124 1 124 2 1 121 1 1 117 2 1 126 8 57 43 60 2 7 14 6 2 7 8 8 8 60 39 14 13 20 5 2 16 19 8 1 20 20 5 76 65 44 66 7 3 66 65 65 29 6 24 5 25 9 14 4 3 2 4 5 2 20 8 2 17 10 12 8 5 7 4 11 5 12 3 9 5 8 5 5 5 62 30 18 1 2 28 20 2 3 5 4 14 2 2 4 3 20 65 7 18 4 6 6 3 1 1 1 2 5 1 2 9 2 1 12 8 5 7 6 11 1 10 3 11 1 18 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 /* $OpenBSD: ip_input.c,v 1.394 2024/05/08 13:01:30 bluhm Exp $ */ /* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ip_input.c 8.2 (Berkeley) 1/4/94 */ #include "pf.h" #include "carp.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/domain.h> #include <sys/mutex.h> #include <sys/protosw.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/sysctl.h> #include <sys/pool.h> #include <sys/task.h> #include <net/if.h> #include <net/if_var.h> #include <net/if_dl.h> #include <net/route.h> #include <net/netisr.h> #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/if_ether.h> #include <netinet/ip.h> #include <netinet/in_pcb.h> #include <netinet/in_var.h> #include <netinet/ip_var.h> #include <netinet/ip_icmp.h> #include <net/if_types.h> #ifdef INET6 #include <netinet6/ip6_var.h> #endif #if NPF > 0 #include <net/pfvar.h> #endif #ifdef MROUTING #include <netinet/ip_mroute.h> #endif #ifdef IPSEC #include <netinet/ip_ipsp.h> #endif /* IPSEC */ #if NCARP > 0 #include <netinet/ip_carp.h> #endif /* values controllable via sysctl */ int ipforwarding = 0; int ipmforwarding = 0; int ipmultipath = 0; int ipsendredirects = 1; int ip_dosourceroute = 0; int ip_defttl = IPDEFTTL; int ip_mtudisc = 1; int ip_mtudisc_timeout = IPMTUDISCTIMEOUT; int ip_directedbcast = 0; /* Protects `ipq' and `ip_frags'. */ struct mutex ipq_mutex = MUTEX_INITIALIZER(IPL_SOFTNET); /* IP reassembly queue */ LIST_HEAD(, ipq) ipq; /* Keep track of memory used for reassembly */ int ip_maxqueue = 300; int ip_frags = 0; const struct sysctl_bounded_args ipctl_vars[] = { #ifdef MROUTING { IPCTL_MRTPROTO, &ip_mrtproto, SYSCTL_INT_READONLY }, #endif { IPCTL_FORWARDING, &ipforwarding, 0, 2 }, { IPCTL_SENDREDIRECTS, &ipsendredirects, 0, 1 }, { IPCTL_DEFTTL, &ip_defttl, 0, 255 }, { IPCTL_DIRECTEDBCAST, &ip_directedbcast, 0, 1 }, { IPCTL_IPPORT_FIRSTAUTO, &ipport_firstauto, 0, 65535 }, { IPCTL_IPPORT_LASTAUTO, &ipport_lastauto, 0, 65535 }, { IPCTL_IPPORT_HIFIRSTAUTO, &ipport_hifirstauto, 0, 65535 }, { IPCTL_IPPORT_HILASTAUTO, &ipport_hilastauto, 0, 65535 }, { IPCTL_IPPORT_MAXQUEUE, &ip_maxqueue, 0, 10000 }, { IPCTL_MFORWARDING, &ipmforwarding, 0, 1 }, { IPCTL_ARPTIMEOUT, &arpt_keep, 0, INT_MAX }, { IPCTL_ARPDOWN, &arpt_down, 0, INT_MAX }, }; struct niqueue ipintrq = NIQUEUE_INITIALIZER(IPQ_MAXLEN, NETISR_IP); struct pool ipqent_pool; struct pool ipq_pool; struct cpumem *ipcounters; int ip_sysctl_ipstat(void *, size_t *, void *); static struct mbuf_queue ipsend_mq; static struct mbuf_queue ipsendraw_mq; extern struct niqueue arpinq; int ip_ours(struct mbuf **, int *, int, int); int ip_dooptions(struct mbuf *, struct ifnet *); int in_ouraddr(struct mbuf *, struct ifnet *, struct route *); int ip_fragcheck(struct mbuf **, int *); struct mbuf * ip_reass(struct ipqent *, struct ipq *); void ip_freef(struct ipq *); void ip_flush(void); static void ip_send_dispatch(void *); static void ip_sendraw_dispatch(void *); static struct task ipsend_task = TASK_INITIALIZER(ip_send_dispatch, &ipsend_mq); static struct task ipsendraw_task = TASK_INITIALIZER(ip_sendraw_dispatch, &ipsendraw_mq); /* * Used to save the IP options in case a protocol wants to respond * to an incoming packet over the same route if the packet got here * using IP source routing. This allows connection establishment and * maintenance when the remote end is on a network that is not known * to us. */ struct ip_srcrt { int isr_nhops; /* number of hops */ struct in_addr isr_dst; /* final destination */ char isr_nop; /* one NOP to align */ char isr_hdr[IPOPT_OFFSET + 1]; /* OPTVAL, OLEN & OFFSET */ struct in_addr isr_routes[MAX_IPOPTLEN/sizeof(struct in_addr)]; }; void save_rte(struct mbuf *, u_char *, struct in_addr); /* * IP initialization: fill in IP protocol switch table. * All protocols not implemented in kernel go to raw IP protocol handler. */ void ip_init(void) { const struct protosw *pr; int i; const u_int16_t defbaddynamicports_tcp[] = DEFBADDYNAMICPORTS_TCP; const u_int16_t defbaddynamicports_udp[] = DEFBADDYNAMICPORTS_UDP; const u_int16_t defrootonlyports_tcp[] = DEFROOTONLYPORTS_TCP; const u_int16_t defrootonlyports_udp[] = DEFROOTONLYPORTS_UDP; ipcounters = counters_alloc(ips_ncounters); pool_init(&ipqent_pool, sizeof(struct ipqent), 0, IPL_SOFTNET, 0, "ipqe", NULL); pool_init(&ipq_pool, sizeof(struct ipq), 0, IPL_SOFTNET, 0, "ipq", NULL); pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW); if (pr == NULL) panic("ip_init"); for (i = 0; i < IPPROTO_MAX; i++) ip_protox[i] = pr - inetsw; for (pr = inetdomain.dom_protosw; pr < inetdomain.dom_protoswNPROTOSW; pr++) if (pr->pr_domain->dom_family == PF_INET && pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW && pr->pr_protocol < IPPROTO_MAX) ip_protox[pr->pr_protocol] = pr - inetsw; LIST_INIT(&ipq); /* Fill in list of ports not to allocate dynamically. */ memset(&baddynamicports, 0, sizeof(baddynamicports)); for (i = 0; defbaddynamicports_tcp[i] != 0; i++) DP_SET(baddynamicports.tcp, defbaddynamicports_tcp[i]); for (i = 0; defbaddynamicports_udp[i] != 0; i++) DP_SET(baddynamicports.udp, defbaddynamicports_udp[i]); /* Fill in list of ports only root can bind to. */ memset(&rootonlyports, 0, sizeof(rootonlyports)); for (i = 0; defrootonlyports_tcp[i] != 0; i++) DP_SET(rootonlyports.tcp, defrootonlyports_tcp[i]); for (i = 0; defrootonlyports_udp[i] != 0; i++) DP_SET(rootonlyports.udp, defrootonlyports_udp[i]); mq_init(&ipsend_mq, 64, IPL_SOFTNET); mq_init(&ipsendraw_mq, 64, IPL_SOFTNET); arpinit(); #ifdef IPSEC ipsec_init(); #endif #ifdef MROUTING rt_timer_queue_init(&ip_mrouterq, MCAST_EXPIRE_FREQUENCY, &mfc_expire_route); #endif } /* * Enqueue packet for local delivery. Queuing is used as a boundary * between the network layer (input/forward path) running with * NET_LOCK_SHARED() and the transport layer needing it exclusively. */ int ip_ours(struct mbuf **mp, int *offp, int nxt, int af) { nxt = ip_fragcheck(mp, offp); if (nxt == IPPROTO_DONE) return IPPROTO_DONE; /* We are already in a IPv4/IPv6 local deliver loop. */ if (af != AF_UNSPEC) return nxt; nxt = ip_deliver(mp, offp, nxt, AF_INET, 1); if (nxt == IPPROTO_DONE) return IPPROTO_DONE; /* save values for later, use after dequeue */ if (*offp != sizeof(struct ip)) { struct m_tag *mtag; struct ipoffnxt *ion; /* mbuf tags are expensive, but only used for header options */ mtag = m_tag_get(PACKET_TAG_IP_OFFNXT, sizeof(*ion), M_NOWAIT); if (mtag == NULL) { ipstat_inc(ips_idropped); m_freemp(mp); return IPPROTO_DONE; } ion = (struct ipoffnxt *)(mtag + 1); ion->ion_off = *offp; ion->ion_nxt = nxt; m_tag_prepend(*mp, mtag); } niq_enqueue(&ipintrq, *mp); *mp = NULL; return IPPROTO_DONE; } /* * Dequeue and process locally delivered packets. * This is called with exclusive NET_LOCK(). */ void ipintr(void) { struct mbuf *m; while ((m = niq_dequeue(&ipintrq)) != NULL) { struct m_tag *mtag; int off, nxt; #ifdef DIAGNOSTIC if ((m->m_flags & M_PKTHDR) == 0) panic("ipintr no HDR"); #endif mtag = m_tag_find(m, PACKET_TAG_IP_OFFNXT, NULL); if (mtag != NULL) { struct ipoffnxt *ion; ion = (struct ipoffnxt *)(mtag + 1); off = ion->ion_off; nxt = ion->ion_nxt; m_tag_delete(m, mtag); } else { struct ip *ip; ip = mtod(m, struct ip *); off = ip->ip_hl << 2; nxt = ip->ip_p; } nxt = ip_deliver(&m, &off, nxt, AF_INET, 0); KASSERT(nxt == IPPROTO_DONE); } } /* * IPv4 input routine. * * Checksum and byte swap header. Process options. Forward or deliver. */ void ipv4_input(struct ifnet *ifp, struct mbuf *m) { int off, nxt; off = 0; nxt = ip_input_if(&m, &off, IPPROTO_IPV4, AF_UNSPEC, ifp); KASSERT(nxt == IPPROTO_DONE); } struct mbuf * ipv4_check(struct ifnet *ifp, struct mbuf *m) { struct ip *ip; int hlen, len; if (m->m_len < sizeof(*ip)) { m = m_pullup(m, sizeof(*ip)); if (m == NULL) { ipstat_inc(ips_toosmall); return (NULL); } } ip = mtod(m, struct ip *); if (ip->ip_v != IPVERSION) { ipstat_inc(ips_badvers); goto bad; } hlen = ip->ip_hl << 2; if (hlen < sizeof(*ip)) { /* minimum header length */ ipstat_inc(ips_badhlen); goto bad; } if (hlen > m->m_len) { m = m_pullup(m, hlen); if (m == NULL) { ipstat_inc(ips_badhlen); return (NULL); } ip = mtod(m, struct ip *); } /* 127/8 must not appear on wire - RFC1122 */ if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET || (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) { if ((ifp->if_flags & IFF_LOOPBACK) == 0) { ipstat_inc(ips_badaddr); goto bad; } } if (!ISSET(m->m_pkthdr.csum_flags, M_IPV4_CSUM_IN_OK)) { if (ISSET(m->m_pkthdr.csum_flags, M_IPV4_CSUM_IN_BAD)) { ipstat_inc(ips_badsum); goto bad; } ipstat_inc(ips_inswcsum); if (in_cksum(m, hlen) != 0) { ipstat_inc(ips_badsum); goto bad; } SET(m->m_pkthdr.csum_flags, M_IPV4_CSUM_IN_OK); } /* Retrieve the packet length. */ len = ntohs(ip->ip_len); /* * Convert fields to host representation. */ if (len < hlen) { ipstat_inc(ips_badlen); goto bad; } /* * Check that the amount of data in the buffers * is at least as much as the IP header would have us expect. * Trim mbufs if longer than we expect. * Drop packet if shorter than we expect. */ if (m->m_pkthdr.len < len) { ipstat_inc(ips_tooshort); goto bad; } if (m->m_pkthdr.len > len) { if (m->m_len == m->m_pkthdr.len) { m->m_len = len; m->m_pkthdr.len = len; } else m_adj(m, len - m->m_pkthdr.len); } return (m); bad: m_freem(m); return (NULL); } int ip_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp) { struct route ro; struct mbuf *m; struct ip *ip; int hlen; #if NPF > 0 struct in_addr odst; #endif int pfrdr = 0; KASSERT(*offp == 0); ro.ro_rt = NULL; ipstat_inc(ips_total); m = *mp = ipv4_check(ifp, *mp); if (m == NULL) goto bad; ip = mtod(m, struct ip *); #if NCARP > 0 if (carp_lsdrop(ifp, m, AF_INET, &ip->ip_src.s_addr, &ip->ip_dst.s_addr, (ip->ip_p == IPPROTO_ICMP ? 0 : 1))) goto bad; #endif #if NPF > 0 /* * Packet filter */ odst = ip->ip_dst; if (pf_test(AF_INET, PF_IN, ifp, mp) != PF_PASS) goto bad; m = *mp; if (m == NULL) goto bad; ip = mtod(m, struct ip *); pfrdr = odst.s_addr != ip->ip_dst.s_addr; #endif hlen = ip->ip_hl << 2; /* * Process options and, if not destined for us, * ship it on. ip_dooptions returns 1 when an * error was detected (causing an icmp message * to be sent and the original packet to be freed). */ if (hlen > sizeof (struct ip) && ip_dooptions(m, ifp)) { m = *mp = NULL; goto bad; } if (ip->ip_dst.s_addr == INADDR_BROADCAST || ip->ip_dst.s_addr == INADDR_ANY) { nxt = ip_ours(mp, offp, nxt, af); goto out; } switch(in_ouraddr(m, ifp, &ro)) { case 2: goto bad; case 1: nxt = ip_ours(mp, offp, nxt, af); goto out; } if (IN_MULTICAST(ip->ip_dst.s_addr)) { /* * Make sure M_MCAST is set. It should theoretically * already be there, but let's play safe because upper * layers check for this flag. */ m->m_flags |= M_MCAST; #ifdef MROUTING if (ipmforwarding && ip_mrouter[ifp->if_rdomain]) { int error; if (m->m_flags & M_EXT) { if ((m = *mp = m_pullup(m, hlen)) == NULL) { ipstat_inc(ips_toosmall); goto bad; } ip = mtod(m, struct ip *); } /* * If we are acting as a multicast router, all * incoming multicast packets are passed to the * kernel-level multicast forwarding function. * The packet is returned (relatively) intact; if * ip_mforward() returns a non-zero value, the packet * must be discarded, else it may be accepted below. * * (The IP ident field is put in the same byte order * as expected when ip_mforward() is called from * ip_output().) */ KERNEL_LOCK(); error = ip_mforward(m, ifp); KERNEL_UNLOCK(); if (error) { ipstat_inc(ips_cantforward); goto bad; } /* * The process-level routing daemon needs to receive * all multicast IGMP packets, whether or not this * host belongs to their destination groups. */ if (ip->ip_p == IPPROTO_IGMP) { nxt = ip_ours(mp, offp, nxt, af); goto out; } ipstat_inc(ips_forward); } #endif /* * See if we belong to the destination multicast group on the * arrival interface. */ if (!in_hasmulti(&ip->ip_dst, ifp)) { ipstat_inc(ips_notmember); if (!IN_LOCAL_GROUP(ip->ip_dst.s_addr)) ipstat_inc(ips_cantforward); goto bad; } nxt = ip_ours(mp, offp, nxt, af); goto out; } #if NCARP > 0 if (ip->ip_p == IPPROTO_ICMP && carp_lsdrop(ifp, m, AF_INET, &ip->ip_src.s_addr, &ip->ip_dst.s_addr, 1)) goto bad; #endif /* * Not for us; forward if possible and desirable. */ if (ipforwarding == 0) { ipstat_inc(ips_cantforward); goto bad; } #ifdef IPSEC if (ipsec_in_use) { int rv; rv = ipsec_forward_check(m, hlen, AF_INET); if (rv != 0) { ipstat_inc(ips_cantforward); goto bad; } /* * Fall through, forward packet. Outbound IPsec policy * checking will occur in ip_output(). */ } #endif /* IPSEC */ ip_forward(m, ifp, &ro, pfrdr); *mp = NULL; rtfree(ro.ro_rt); return IPPROTO_DONE; bad: nxt = IPPROTO_DONE; m_freemp(mp); out: rtfree(ro.ro_rt); return nxt; } int ip_fragcheck(struct mbuf **mp, int *offp) { struct ip *ip; struct ipq *fp; struct ipqent *ipqe; int hlen; uint16_t mff; ip = mtod(*mp, struct ip *); hlen = ip->ip_hl << 2; /* * If offset or more fragments are set, must reassemble. * Otherwise, nothing need be done. * (We could look in the reassembly queue to see * if the packet was previously fragmented, * but it's not worth the time; just let them time out.) */ if (ISSET(ip->ip_off, htons(IP_OFFMASK | IP_MF))) { if ((*mp)->m_flags & M_EXT) { /* XXX */ if ((*mp = m_pullup(*mp, hlen)) == NULL) { ipstat_inc(ips_toosmall); return IPPROTO_DONE; } ip = mtod(*mp, struct ip *); } /* * Adjust ip_len to not reflect header, * set ipqe_mff if more fragments are expected, * convert offset of this to bytes. */ ip->ip_len = htons(ntohs(ip->ip_len) - hlen); mff = ISSET(ip->ip_off, htons(IP_MF)); if (mff) { /* * Make sure that fragments have a data length * that's a non-zero multiple of 8 bytes. */ if (ntohs(ip->ip_len) == 0 || (ntohs(ip->ip_len) & 0x7) != 0) { ipstat_inc(ips_badfrags); m_freemp(mp); return IPPROTO_DONE; } } ip->ip_off = htons(ntohs(ip->ip_off) << 3); mtx_enter(&ipq_mutex); /* * Look for queue of fragments * of this datagram. */ LIST_FOREACH(fp, &ipq, ipq_q) { if (ip->ip_id == fp->ipq_id && ip->ip_src.s_addr == fp->ipq_src.s_addr && ip->ip_dst.s_addr == fp->ipq_dst.s_addr && ip->ip_p == fp->ipq_p) break; } /* * If datagram marked as having more fragments * or if this is not the first fragment, * attempt reassembly; if it succeeds, proceed. */ if (mff || ip->ip_off) { ipstat_inc(ips_fragments); if (ip_frags + 1 > ip_maxqueue) { ip_flush(); ipstat_inc(ips_rcvmemdrop); goto bad; } ipqe = pool_get(&ipqent_pool, PR_NOWAIT); if (ipqe == NULL) { ipstat_inc(ips_rcvmemdrop); goto bad; } ip_frags++; ipqe->ipqe_mff = mff; ipqe->ipqe_m = *mp; ipqe->ipqe_ip = ip; *mp = ip_reass(ipqe, fp); if (*mp == NULL) goto bad; ipstat_inc(ips_reassembled); ip = mtod(*mp, struct ip *); hlen = ip->ip_hl << 2; ip->ip_len = htons(ntohs(ip->ip_len) + hlen); } else { if (fp != NULL) ip_freef(fp); } mtx_leave(&ipq_mutex); } *offp = hlen; return ip->ip_p; bad: mtx_leave(&ipq_mutex); m_freemp(mp); return IPPROTO_DONE; } #ifndef INET6 #define IPSTAT_INC(name) ipstat_inc(ips_##name) #else #define IPSTAT_INC(name) (af == AF_INET ? \ ipstat_inc(ips_##name) : ip6stat_inc(ip6s_##name)) #endif int ip_deliver(struct mbuf **mp, int *offp, int nxt, int af, int shared) { #ifdef INET6 int nest = 0; #endif /* * Tell launch routine the next header */ IPSTAT_INC(delivered); while (nxt != IPPROTO_DONE) { const struct protosw *psw; int naf; switch (af) { case AF_INET: psw = &inetsw[ip_protox[nxt]]; break; #ifdef INET6 case AF_INET6: psw = &inet6sw[ip6_protox[nxt]]; break; #endif } if (shared && !ISSET(psw->pr_flags, PR_MPINPUT)) { /* delivery not finished, decrement counter, queue */ switch (af) { case AF_INET: counters_dec(ipcounters, ips_delivered); break; #ifdef INET6 case AF_INET6: counters_dec(ip6counters, ip6s_delivered); break; #endif } break; } #ifdef INET6 if (af == AF_INET6 && ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) { ip6stat_inc(ip6s_toomanyhdr); goto bad; } #endif /* * protection against faulty packet - there should be * more sanity checks in header chain processing. */ if ((*mp)->m_pkthdr.len < *offp) { IPSTAT_INC(tooshort); goto bad; } #ifdef IPSEC if (ipsec_in_use) { if (ipsec_local_check(*mp, *offp, nxt, af) != 0) { IPSTAT_INC(cantforward); goto bad; } } /* Otherwise, just fall through and deliver the packet */ #endif switch (nxt) { case IPPROTO_IPV4: naf = AF_INET; ipstat_inc(ips_delivered); break; #ifdef INET6 case IPPROTO_IPV6: naf = AF_INET6; ip6stat_inc(ip6s_delivered); break; #endif default: naf = af; break; } nxt = (*psw->pr_input)(mp, offp, nxt, af); af = naf; } return nxt; bad: m_freemp(mp); return IPPROTO_DONE; } #undef IPSTAT_INC int in_ouraddr(struct mbuf *m, struct ifnet *ifp, struct route *ro) { struct rtentry *rt; struct ip *ip; int match = 0; #if NPF > 0 switch (pf_ouraddr(m)) { case 0: return (0); case 1: return (1); default: /* pf does not know it */ break; } #endif ip = mtod(m, struct ip *); rt = route_mpath(ro, &ip->ip_dst, &ip->ip_src, m->m_pkthdr.ph_rtableid); if (rt != NULL) { if (ISSET(rt->rt_flags, RTF_LOCAL)) match = 1; /* * If directedbcast is enabled we only consider it local * if it is received on the interface with that address. */ if (ISSET(rt->rt_flags, RTF_BROADCAST) && (!ip_directedbcast || rt->rt_ifidx == ifp->if_index)) { match = 1; /* Make sure M_BCAST is set */ m->m_flags |= M_BCAST; } } if (!match) { struct ifaddr *ifa; /* * No local address or broadcast address found, so check for * ancient classful broadcast addresses. * It must have been broadcast on the link layer, and for an * address on the interface it was received on. */ if (!ISSET(m->m_flags, M_BCAST) || !IN_CLASSFULBROADCAST(ip->ip_dst.s_addr, ip->ip_dst.s_addr)) return (0); if (ifp->if_rdomain != rtable_l2(m->m_pkthdr.ph_rtableid)) return (0); /* * The check in the loop assumes you only rx a packet on an UP * interface, and that M_BCAST will only be set on a BROADCAST * interface. */ NET_ASSERT_LOCKED(); TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET) continue; if (IN_CLASSFULBROADCAST(ip->ip_dst.s_addr, ifatoia(ifa)->ia_addr.sin_addr.s_addr)) { match = 1; break; } } } else if (ipforwarding == 0 && rt->rt_ifidx != ifp->if_index && !((ifp->if_flags & IFF_LOOPBACK) || (ifp->if_type == IFT_ENC) || (m->m_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST))) { /* received on wrong interface. */ #if NCARP > 0 struct ifnet *out_if; /* * Virtual IPs on carp interfaces need to be checked also * against the parent interface and other carp interfaces * sharing the same parent. */ out_if = if_get(rt->rt_ifidx); if (!(out_if && carp_strict_addr_chk(out_if, ifp))) { ipstat_inc(ips_wrongif); match = 2; } if_put(out_if); #else ipstat_inc(ips_wrongif); match = 2; #endif } return (match); } /* * Take incoming datagram fragment and try to * reassemble it into whole datagram. If a chain for * reassembly of this datagram already exists, then it * is given as fp; otherwise have to make a chain. */ struct mbuf * ip_reass(struct ipqent *ipqe, struct ipq *fp) { struct mbuf *m = ipqe->ipqe_m; struct ipqent *nq, *p, *q; struct ip *ip; struct mbuf *t; int hlen = ipqe->ipqe_ip->ip_hl << 2; int i, next; u_int8_t ecn, ecn0; MUTEX_ASSERT_LOCKED(&ipq_mutex); /* * Presence of header sizes in mbufs * would confuse code below. */ m->m_data += hlen; m->m_len -= hlen; /* * If first fragment to arrive, create a reassembly queue. */ if (fp == NULL) { fp = pool_get(&ipq_pool, PR_NOWAIT); if (fp == NULL) goto dropfrag; LIST_INSERT_HEAD(&ipq, fp, ipq_q); fp->ipq_ttl = IPFRAGTTL; fp->ipq_p = ipqe->ipqe_ip->ip_p; fp->ipq_id = ipqe->ipqe_ip->ip_id; LIST_INIT(&fp->ipq_fragq); fp->ipq_src = ipqe->ipqe_ip->ip_src; fp->ipq_dst = ipqe->ipqe_ip->ip_dst; p = NULL; goto insert; } /* * Handle ECN by comparing this segment with the first one; * if CE is set, do not lose CE. * drop if CE and not-ECT are mixed for the same packet. */ ecn = ipqe->ipqe_ip->ip_tos & IPTOS_ECN_MASK; ecn0 = LIST_FIRST(&fp->ipq_fragq)->ipqe_ip->ip_tos & IPTOS_ECN_MASK; if (ecn == IPTOS_ECN_CE) { if (ecn0 == IPTOS_ECN_NOTECT) goto dropfrag; if (ecn0 != IPTOS_ECN_CE) LIST_FIRST(&fp->ipq_fragq)->ipqe_ip->ip_tos |= IPTOS_ECN_CE; } if (ecn == IPTOS_ECN_NOTECT && ecn0 != IPTOS_ECN_NOTECT) goto dropfrag; /* * Find a segment which begins after this one does. */ for (p = NULL, q = LIST_FIRST(&fp->ipq_fragq); q != NULL; p = q, q = LIST_NEXT(q, ipqe_q)) if (ntohs(q->ipqe_ip->ip_off) > ntohs(ipqe->ipqe_ip->ip_off)) break; /* * If there is a preceding segment, it may provide some of * our data already. If so, drop the data from the incoming * segment. If it provides all of our data, drop us. */ if (p != NULL) { i = ntohs(p->ipqe_ip->ip_off) + ntohs(p->ipqe_ip->ip_len) - ntohs(ipqe->ipqe_ip->ip_off); if (i > 0) { if (i >= ntohs(ipqe->ipqe_ip->ip_len)) goto dropfrag; m_adj(ipqe->ipqe_m, i); ipqe->ipqe_ip->ip_off = htons(ntohs(ipqe->ipqe_ip->ip_off) + i); ipqe->ipqe_ip->ip_len = htons(ntohs(ipqe->ipqe_ip->ip_len) - i); } } /* * While we overlap succeeding segments trim them or, * if they are completely covered, dequeue them. */ for (; q != NULL && ntohs(ipqe->ipqe_ip->ip_off) + ntohs(ipqe->ipqe_ip->ip_len) > ntohs(q->ipqe_ip->ip_off); q = nq) { i = (ntohs(ipqe->ipqe_ip->ip_off) + ntohs(ipqe->ipqe_ip->ip_len)) - ntohs(q->ipqe_ip->ip_off); if (i < ntohs(q->ipqe_ip->ip_len)) { q->ipqe_ip->ip_len = htons(ntohs(q->ipqe_ip->ip_len) - i); q->ipqe_ip->ip_off = htons(ntohs(q->ipqe_ip->ip_off) + i); m_adj(q->ipqe_m, i); break; } nq = LIST_NEXT(q, ipqe_q); m_freem(q->ipqe_m); LIST_REMOVE(q, ipqe_q); pool_put(&ipqent_pool, q); ip_frags--; } insert: /* * Stick new segment in its place; * check for complete reassembly. */ if (p == NULL) { LIST_INSERT_HEAD(&fp->ipq_fragq, ipqe, ipqe_q); } else { LIST_INSERT_AFTER(p, ipqe, ipqe_q); } next = 0; for (p = NULL, q = LIST_FIRST(&fp->ipq_fragq); q != NULL; p = q, q = LIST_NEXT(q, ipqe_q)) { if (ntohs(q->ipqe_ip->ip_off) != next) return (0); next += ntohs(q->ipqe_ip->ip_len); } if (p->ipqe_mff) return (0); /* * Reassembly is complete. Check for a bogus message size and * concatenate fragments. */ q = LIST_FIRST(&fp->ipq_fragq); ip = q->ipqe_ip; if ((next + (ip->ip_hl << 2)) > IP_MAXPACKET) { ipstat_inc(ips_toolong); ip_freef(fp); return (0); } m = q->ipqe_m; t = m->m_next; m->m_next = 0; m_cat(m, t); nq = LIST_NEXT(q, ipqe_q); pool_put(&ipqent_pool, q); ip_frags--; for (q = nq; q != NULL; q = nq) { t = q->ipqe_m; nq = LIST_NEXT(q, ipqe_q); pool_put(&ipqent_pool, q); ip_frags--; m_removehdr(t); m_cat(m, t); } /* * Create header for new ip packet by * modifying header of first packet; * dequeue and discard fragment reassembly header. * Make header visible. */ ip->ip_len = htons(next); ip->ip_src = fp->ipq_src; ip->ip_dst = fp->ipq_dst; LIST_REMOVE(fp, ipq_q); pool_put(&ipq_pool, fp); m->m_len += (ip->ip_hl << 2); m->m_data -= (ip->ip_hl << 2); m_calchdrlen(m); return (m); dropfrag: ipstat_inc(ips_fragdropped); m_freem(m); pool_put(&ipqent_pool, ipqe); ip_frags--; return (NULL); } /* * Free a fragment reassembly header and all * associated datagrams. */ void ip_freef(struct ipq *fp) { struct ipqent *q; MUTEX_ASSERT_LOCKED(&ipq_mutex); while ((q = LIST_FIRST(&fp->ipq_fragq)) != NULL) { LIST_REMOVE(q, ipqe_q); m_freem(q->ipqe_m); pool_put(&ipqent_pool, q); ip_frags--; } LIST_REMOVE(fp, ipq_q); pool_put(&ipq_pool, fp); } /* * IP timer processing; * if a timer expires on a reassembly queue, discard it. */ void ip_slowtimo(void) { struct ipq *fp, *nfp; mtx_enter(&ipq_mutex); LIST_FOREACH_SAFE(fp, &ipq, ipq_q, nfp) { if (--fp->ipq_ttl == 0) { ipstat_inc(ips_fragtimeout); ip_freef(fp); } } mtx_leave(&ipq_mutex); } /* * Flush a bunch of datagram fragments, till we are down to 75%. */ void ip_flush(void) { int max = 50; MUTEX_ASSERT_LOCKED(&ipq_mutex); while (!LIST_EMPTY(&ipq) && ip_frags > ip_maxqueue * 3 / 4 && --max) { ipstat_inc(ips_fragdropped); ip_freef(LIST_FIRST(&ipq)); } } /* * Do option processing on a datagram, * possibly discarding it if bad options are encountered, * or forwarding it if source-routed. * Returns 1 if packet has been forwarded/freed, * 0 if the packet should be processed further. */ int ip_dooptions(struct mbuf *m, struct ifnet *ifp) { struct ip *ip = mtod(m, struct ip *); unsigned int rtableid = m->m_pkthdr.ph_rtableid; struct rtentry *rt; struct sockaddr_in ipaddr; u_char *cp; struct ip_timestamp ipt; struct in_ifaddr *ia; int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; struct in_addr sin, dst; u_int32_t ntime; dst = ip->ip_dst; cp = (u_char *)(ip + 1); cnt = (ip->ip_hl << 2) - sizeof (struct ip); KERNEL_LOCK(); for (; cnt > 0; cnt -= optlen, cp += optlen) { opt = cp[IPOPT_OPTVAL]; if (opt == IPOPT_EOL) break; if (opt == IPOPT_NOP) optlen = 1; else { if (cnt < IPOPT_OLEN + sizeof(*cp)) { code = &cp[IPOPT_OLEN] - (u_char *)ip; goto bad; } optlen = cp[IPOPT_OLEN]; if (optlen < IPOPT_OLEN + sizeof(*cp) || optlen > cnt) { code = &cp[IPOPT_OLEN] - (u_char *)ip; goto bad; } } switch (opt) { default: break; /* * Source routing with record. * Find interface with current destination address. * If none on this machine then drop if strictly routed, * or do nothing if loosely routed. * Record interface address and bring up next address * component. If strictly routed make sure next * address is on directly accessible net. */ case IPOPT_LSRR: case IPOPT_SSRR: if (!ip_dosourceroute) { type = ICMP_UNREACH; code = ICMP_UNREACH_SRCFAIL; goto bad; } if (optlen < IPOPT_OFFSET + sizeof(*cp)) { code = &cp[IPOPT_OLEN] - (u_char *)ip; goto bad; } if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { code = &cp[IPOPT_OFFSET] - (u_char *)ip; goto bad; } memset(&ipaddr, 0, sizeof(ipaddr)); ipaddr.sin_family = AF_INET; ipaddr.sin_len = sizeof(ipaddr); ipaddr.sin_addr = ip->ip_dst; ia = ifatoia(ifa_ifwithaddr(sintosa(&ipaddr), m->m_pkthdr.ph_rtableid)); if (ia == NULL) { if (opt == IPOPT_SSRR) { type = ICMP_UNREACH; code = ICMP_UNREACH_SRCFAIL; goto bad; } /* * Loose routing, and not at next destination * yet; nothing to do except forward. */ break; } off--; /* 0 origin */ if ((off + sizeof(struct in_addr)) > optlen) { /* * End of source route. Should be for us. */ save_rte(m, cp, ip->ip_src); break; } /* * locate outgoing interface */ memset(&ipaddr, 0, sizeof(ipaddr)); ipaddr.sin_family = AF_INET; ipaddr.sin_len = sizeof(ipaddr); memcpy(&ipaddr.sin_addr, cp + off, sizeof(ipaddr.sin_addr)); /* keep packet in the virtual instance */ rt = rtalloc(sintosa(&ipaddr), RT_RESOLVE, rtableid); if (!rtisvalid(rt) || ((opt == IPOPT_SSRR) && ISSET(rt->rt_flags, RTF_GATEWAY))) { type = ICMP_UNREACH; code = ICMP_UNREACH_SRCFAIL; rtfree(rt); goto bad; } ia = ifatoia(rt->rt_ifa); memcpy(cp + off, &ia->ia_addr.sin_addr, sizeof(struct in_addr)); rtfree(rt); cp[IPOPT_OFFSET] += sizeof(struct in_addr); ip->ip_dst = ipaddr.sin_addr; /* * Let ip_intr's mcast routing check handle mcast pkts */ forward = !IN_MULTICAST(ip->ip_dst.s_addr); break; case IPOPT_RR: if (optlen < IPOPT_OFFSET + sizeof(*cp)) { code = &cp[IPOPT_OLEN] - (u_char *)ip; goto bad; } if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { code = &cp[IPOPT_OFFSET] - (u_char *)ip; goto bad; } /* * If no space remains, ignore. */ off--; /* 0 origin */ if ((off + sizeof(struct in_addr)) > optlen) break; memset(&ipaddr, 0, sizeof(ipaddr)); ipaddr.sin_family = AF_INET; ipaddr.sin_len = sizeof(ipaddr); ipaddr.sin_addr = ip->ip_dst; /* * locate outgoing interface; if we're the destination, * use the incoming interface (should be same). * Again keep the packet inside the virtual instance. */ rt = rtalloc(sintosa(&ipaddr), RT_RESOLVE, rtableid); if (!rtisvalid(rt)) { type = ICMP_UNREACH; code = ICMP_UNREACH_HOST; rtfree(rt); goto bad; } ia = ifatoia(rt->rt_ifa); memcpy(cp + off, &ia->ia_addr.sin_addr, sizeof(struct in_addr)); rtfree(rt); cp[IPOPT_OFFSET] += sizeof(struct in_addr); break; case IPOPT_TS: code = cp - (u_char *)ip; if (optlen < sizeof(struct ip_timestamp)) goto bad; memcpy(&ipt, cp, sizeof(struct ip_timestamp)); if (ipt.ipt_ptr < 5 || ipt.ipt_len < 5) goto bad; if (ipt.ipt_ptr - 1 + sizeof(u_int32_t) > ipt.ipt_len) { if (++ipt.ipt_oflw == 0) goto bad; break; } memcpy(&sin, cp + ipt.ipt_ptr - 1, sizeof sin); switch (ipt.ipt_flg) { case IPOPT_TS_TSONLY: break; case IPOPT_TS_TSANDADDR: if (ipt.ipt_ptr - 1 + sizeof(u_int32_t) + sizeof(struct in_addr) > ipt.ipt_len) goto bad; memset(&ipaddr, 0, sizeof(ipaddr)); ipaddr.sin_family = AF_INET; ipaddr.sin_len = sizeof(ipaddr); ipaddr.sin_addr = dst; ia = ifatoia(ifaof_ifpforaddr(sintosa(&ipaddr), ifp)); if (ia == NULL) continue; memcpy(&sin, &ia->ia_addr.sin_addr, sizeof(struct in_addr)); ipt.ipt_ptr += sizeof(struct in_addr); break; case IPOPT_TS_PRESPEC: if (ipt.ipt_ptr - 1 + sizeof(u_int32_t) + sizeof(struct in_addr) > ipt.ipt_len) goto bad; memset(&ipaddr, 0, sizeof(ipaddr)); ipaddr.sin_family = AF_INET; ipaddr.sin_len = sizeof(ipaddr); ipaddr.sin_addr = sin; if (ifa_ifwithaddr(sintosa(&ipaddr), m->m_pkthdr.ph_rtableid) == NULL) continue; ipt.ipt_ptr += sizeof(struct in_addr); break; default: /* XXX can't take &ipt->ipt_flg */ code = (u_char *)&ipt.ipt_ptr - (u_char *)ip + 1; goto bad; } ntime = iptime(); memcpy(cp + ipt.ipt_ptr - 1, &ntime, sizeof(u_int32_t)); ipt.ipt_ptr += sizeof(u_int32_t); } } KERNEL_UNLOCK(); if (forward && ipforwarding > 0) { ip_forward(m, ifp, NULL, 1); return (1); } return (0); bad: KERNEL_UNLOCK(); icmp_error(m, type, code, 0, 0); ipstat_inc(ips_badoptions); return (1); } /* * Save incoming source route for use in replies, * to be picked up later by ip_srcroute if the receiver is interested. */ void save_rte(struct mbuf *m, u_char *option, struct in_addr dst) { struct ip_srcrt *isr; struct m_tag *mtag; unsigned olen; olen = option[IPOPT_OLEN]; if (olen > sizeof(isr->isr_hdr) + sizeof(isr->isr_routes)) return; mtag = m_tag_get(PACKET_TAG_SRCROUTE, sizeof(*isr), M_NOWAIT); if (mtag == NULL) { ipstat_inc(ips_idropped); return; } isr = (struct ip_srcrt *)(mtag + 1); memcpy(isr->isr_hdr, option, olen); isr->isr_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr); isr->isr_dst = dst; m_tag_prepend(m, mtag); } /* * Retrieve incoming source route for use in replies, * in the same form used by setsockopt. * The first hop is placed before the options, will be removed later. */ struct mbuf * ip_srcroute(struct mbuf *m0) { struct in_addr *p, *q; struct mbuf *m; struct ip_srcrt *isr; struct m_tag *mtag; if (!ip_dosourceroute) return (NULL); mtag = m_tag_find(m0, PACKET_TAG_SRCROUTE, NULL); if (mtag == NULL) return (NULL); isr = (struct ip_srcrt *)(mtag + 1); if (isr->isr_nhops == 0) return (NULL); m = m_get(M_DONTWAIT, MT_SOOPTS); if (m == NULL) { ipstat_inc(ips_idropped); return (NULL); } #define OPTSIZ (sizeof(isr->isr_nop) + sizeof(isr->isr_hdr)) /* length is (nhops+1)*sizeof(addr) + sizeof(nop + header) */ m->m_len = (isr->isr_nhops + 1) * sizeof(struct in_addr) + OPTSIZ; /* * First save first hop for return route */ p = &(isr->isr_routes[isr->isr_nhops - 1]); *(mtod(m, struct in_addr *)) = *p--; /* * Copy option fields and padding (nop) to mbuf. */ isr->isr_nop = IPOPT_NOP; isr->isr_hdr[IPOPT_OFFSET] = IPOPT_MINOFF; memcpy(mtod(m, caddr_t) + sizeof(struct in_addr), &isr->isr_nop, OPTSIZ); q = (struct in_addr *)(mtod(m, caddr_t) + sizeof(struct in_addr) + OPTSIZ); #undef OPTSIZ /* * Record return path as an IP source route, * reversing the path (pointers are now aligned). */ while (p >= isr->isr_routes) { *q++ = *p--; } /* * Last hop goes to final destination. */ *q = isr->isr_dst; m_tag_delete(m0, (struct m_tag *)isr); return (m); } /* * Strip out IP options, at higher level protocol in the kernel. */ void ip_stripoptions(struct mbuf *m) { int i; struct ip *ip = mtod(m, struct ip *); caddr_t opts; int olen; olen = (ip->ip_hl<<2) - sizeof (struct ip); opts = (caddr_t)(ip + 1); i = m->m_len - (sizeof (struct ip) + olen); memmove(opts, opts + olen, i); m->m_len -= olen; if (m->m_flags & M_PKTHDR) m->m_pkthdr.len -= olen; ip->ip_hl = sizeof(struct ip) >> 2; ip->ip_len = htons(ntohs(ip->ip_len) - olen); } const u_char inetctlerrmap[PRC_NCMDS] = { 0, 0, 0, 0, 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH, EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, EMSGSIZE, EHOSTUNREACH, 0, 0, 0, 0, 0, 0, ENOPROTOOPT }; /* * Forward a packet. If some error occurs return the sender * an icmp packet. Note we can't always generate a meaningful * icmp message because icmp doesn't have a large enough repertoire * of codes and types. * * If not forwarding, just drop the packet. This could be confusing * if ipforwarding was zero but some routing protocol was advancing * us as a gateway to somewhere. However, we must let the routing * protocol deal with that. * * The srcrt parameter indicates whether the packet is being forwarded * via a source route. */ void ip_forward(struct mbuf *m, struct ifnet *ifp, struct route *ro, int srcrt) { struct mbuf mfake, *mcopy; struct ip *ip = mtod(m, struct ip *); struct route iproute; struct rtentry *rt; int error = 0, type = 0, code = 0, destmtu = 0, fake = 0, len; u_int32_t dest; dest = 0; if (m->m_flags & (M_BCAST|M_MCAST) || in_canforward(ip->ip_dst) == 0) { ipstat_inc(ips_cantforward); m_freem(m); goto done; } if (ip->ip_ttl <= IPTTLDEC) { icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest, 0); goto done; } if (ro == NULL) { ro = &iproute; ro->ro_rt = NULL; } rt = route_mpath(ro, &ip->ip_dst, &ip->ip_src, m->m_pkthdr.ph_rtableid); if (rt == NULL) { ipstat_inc(ips_noroute); icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0); goto done; } /* * Save at most 68 bytes of the packet in case * we need to generate an ICMP message to the src. * The data is saved in the mbuf on the stack that * acts as a temporary storage not intended to be * passed down the IP stack or to the mfree. */ memset(&mfake.m_hdr, 0, sizeof(mfake.m_hdr)); mfake.m_type = m->m_type; if (m_dup_pkthdr(&mfake, m, M_DONTWAIT) == 0) { mfake.m_data = mfake.m_pktdat; len = min(ntohs(ip->ip_len), 68); m_copydata(m, 0, len, mfake.m_pktdat); mfake.m_pkthdr.len = mfake.m_len = len; #if NPF > 0 pf_pkt_addr_changed(&mfake); #endif /* NPF > 0 */ fake = 1; } ip->ip_ttl -= IPTTLDEC; /* * If forwarding packet using same interface that it came in on, * perhaps should send a redirect to sender to shortcut a hop. * Only send redirect if source is sending directly to us, * and if packet was not source routed (or has any options). * Also, don't send redirect if forwarding using a default route * or a route modified by a redirect. * Don't send redirect if we advertise destination's arp address * as ours (proxy arp). */ if ((rt->rt_ifidx == ifp->if_index) && (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 && satosin(rt_key(rt))->sin_addr.s_addr != 0 && ipsendredirects && !srcrt && !arpproxy(satosin(rt_key(rt))->sin_addr, m->m_pkthdr.ph_rtableid)) { if ((ip->ip_src.s_addr & ifatoia(rt->rt_ifa)->ia_netmask) == ifatoia(rt->rt_ifa)->ia_net) { if (rt->rt_flags & RTF_GATEWAY) dest = satosin(rt->rt_gateway)->sin_addr.s_addr; else dest = ip->ip_dst.s_addr; /* Router requirements says to only send host redirects */ type = ICMP_REDIRECT; code = ICMP_REDIRECT_HOST; } } error = ip_output(m, NULL, ro, (IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)), NULL, NULL, 0); rt = ro->ro_rt; if (error) ipstat_inc(ips_cantforward); else { ipstat_inc(ips_forward); if (type) ipstat_inc(ips_redirectsent); else goto done; } if (!fake) goto done; switch (error) { case 0: /* forwarded, but need redirect */ /* type, code set above */ break; case EMSGSIZE: type = ICMP_UNREACH; code = ICMP_UNREACH_NEEDFRAG; if (rt != NULL) { if (rt->rt_mtu) { destmtu = rt->rt_mtu; } else { struct ifnet *destifp; destifp = if_get(rt->rt_ifidx); if (destifp != NULL) destmtu = destifp->if_mtu; if_put(destifp); } } ipstat_inc(ips_cantfrag); if (destmtu == 0) goto done; break; case EACCES: /* * pf(4) blocked the packet. There is no need to send an ICMP * packet back since pf(4) takes care of it. */ goto done; case ENOBUFS: /* * a router should not generate ICMP_SOURCEQUENCH as * required in RFC1812 Requirements for IP Version 4 Routers. * source quench could be a big problem under DoS attacks, * or the underlying interface is rate-limited. */ goto done; case ENETUNREACH: /* shouldn't happen, checked above */ case EHOSTUNREACH: case ENETDOWN: case EHOSTDOWN: default: type = ICMP_UNREACH; code = ICMP_UNREACH_HOST; break; } mcopy = m_copym(&mfake, 0, len, M_DONTWAIT); if (mcopy != NULL) icmp_error(mcopy, type, code, dest, destmtu); done: if (ro == &iproute) rtfree(ro->ro_rt); if (fake) m_tag_delete_chain(&mfake); } int ip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { #ifdef MROUTING extern struct mrtstat mrtstat; #endif int oldval, error; /* Almost all sysctl names at this level are terminal. */ if (namelen != 1 && name[0] != IPCTL_IFQUEUE && name[0] != IPCTL_ARPQUEUE) return (ENOTDIR); switch (name[0]) { case IPCTL_SOURCEROUTE: NET_LOCK(); error = sysctl_securelevel_int(oldp, oldlenp, newp, newlen, &ip_dosourceroute); NET_UNLOCK(); return (error); case IPCTL_MTUDISC: NET_LOCK(); error = sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtudisc); if (ip_mtudisc == 0) rt_timer_queue_flush(&ip_mtudisc_timeout_q); NET_UNLOCK(); return error; case IPCTL_MTUDISCTIMEOUT: NET_LOCK(); error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &ip_mtudisc_timeout, 0, INT_MAX); rt_timer_queue_change(&ip_mtudisc_timeout_q, ip_mtudisc_timeout); NET_UNLOCK(); return (error); #ifdef IPSEC case IPCTL_ENCDEBUG: case IPCTL_IPSEC_STATS: case IPCTL_IPSEC_EXPIRE_ACQUIRE: case IPCTL_IPSEC_EMBRYONIC_SA_TIMEOUT: case IPCTL_IPSEC_REQUIRE_PFS: case IPCTL_IPSEC_SOFT_ALLOCATIONS: case IPCTL_IPSEC_ALLOCATIONS: case IPCTL_IPSEC_SOFT_BYTES: case IPCTL_IPSEC_BYTES: case IPCTL_IPSEC_TIMEOUT: case IPCTL_IPSEC_SOFT_TIMEOUT: case IPCTL_IPSEC_SOFT_FIRSTUSE: case IPCTL_IPSEC_FIRSTUSE: case IPCTL_IPSEC_ENC_ALGORITHM: case IPCTL_IPSEC_AUTH_ALGORITHM: case IPCTL_IPSEC_IPCOMP_ALGORITHM: return (ipsec_sysctl(name, namelen, oldp, oldlenp, newp, newlen)); #endif case IPCTL_IFQUEUE: return (sysctl_niq(name + 1, namelen - 1, oldp, oldlenp, newp, newlen, &ipintrq)); case IPCTL_ARPQUEUE: return (sysctl_niq(name + 1, namelen - 1, oldp, oldlenp, newp, newlen, &arpinq)); case IPCTL_ARPQUEUED: return (sysctl_rdint(oldp, oldlenp, newp, atomic_load_int(&la_hold_total))); case IPCTL_STATS: return (ip_sysctl_ipstat(oldp, oldlenp, newp)); #ifdef MROUTING case IPCTL_MRTSTATS: return (sysctl_rdstruct(oldp, oldlenp, newp, &mrtstat, sizeof(mrtstat))); case IPCTL_MRTMFC: if (newp) return (EPERM); NET_LOCK(); error = mrt_sysctl_mfc(oldp, oldlenp); NET_UNLOCK(); return (error); case IPCTL_MRTVIF: if (newp) return (EPERM); NET_LOCK(); error = mrt_sysctl_vif(oldp, oldlenp); NET_UNLOCK(); return (error); #else case IPCTL_MRTPROTO: case IPCTL_MRTSTATS: case IPCTL_MRTMFC: case IPCTL_MRTVIF: return (EOPNOTSUPP); #endif case IPCTL_MULTIPATH: NET_LOCK(); oldval = ipmultipath; error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &ipmultipath, 0, 1); if (oldval != ipmultipath) atomic_inc_long(&rtgeneration); NET_UNLOCK(); return (error); default: NET_LOCK(); error = sysctl_bounded_arr(ipctl_vars, nitems(ipctl_vars), name, namelen, oldp, oldlenp, newp, newlen); NET_UNLOCK(); return (error); } /* NOTREACHED */ } int ip_sysctl_ipstat(void *oldp, size_t *oldlenp, void *newp) { uint64_t counters[ips_ncounters]; struct ipstat ipstat; u_long *words = (u_long *)&ipstat; int i; CTASSERT(sizeof(ipstat) == (nitems(counters) * sizeof(u_long))); memset(&ipstat, 0, sizeof ipstat); counters_read(ipcounters, counters, nitems(counters), NULL); for (i = 0; i < nitems(counters); i++) words[i] = (u_long)counters[i]; return (sysctl_rdstruct(oldp, oldlenp, newp, &ipstat, sizeof(ipstat))); } void ip_savecontrol(struct inpcb *inp, struct mbuf **mp, struct ip *ip, struct mbuf *m) { if (inp->inp_socket->so_options & SO_TIMESTAMP) { struct timeval tv; m_microtime(m, &tv); *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv), SCM_TIMESTAMP, SOL_SOCKET); if (*mp) mp = &(*mp)->m_next; } if (inp->inp_flags & INP_RECVDSTADDR) { *mp = sbcreatecontrol((caddr_t) &ip->ip_dst, sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP); if (*mp) mp = &(*mp)->m_next; } #ifdef notyet /* this code is broken and will probably never be fixed. */ /* options were tossed already */ if (inp->inp_flags & INP_RECVOPTS) { *mp = sbcreatecontrol((caddr_t) opts_deleted_above, sizeof(struct in_addr), IP_RECVOPTS, IPPROTO_IP); if (*mp) mp = &(*mp)->m_next; } /* ip_srcroute doesn't do what we want here, need to fix */ if (inp->inp_flags & INP_RECVRETOPTS) { *mp = sbcreatecontrol((caddr_t) ip_srcroute(m), sizeof(struct in_addr), IP_RECVRETOPTS, IPPROTO_IP); if (*mp) mp = &(*mp)->m_next; } #endif if (inp->inp_flags & INP_RECVIF) { struct sockaddr_dl sdl; struct ifnet *ifp; ifp = if_get(m->m_pkthdr.ph_ifidx); if (ifp == NULL || ifp->if_sadl == NULL) { memset(&sdl, 0, sizeof(sdl)); sdl.sdl_len = offsetof(struct sockaddr_dl, sdl_data[0]); sdl.sdl_family = AF_LINK; sdl.sdl_index = ifp != NULL ? ifp->if_index : 0; sdl.sdl_nlen = sdl.sdl_alen = sdl.sdl_slen = 0; *mp = sbcreatecontrol((caddr_t) &sdl, sdl.sdl_len, IP_RECVIF, IPPROTO_IP); } else { *mp = sbcreatecontrol((caddr_t) ifp->if_sadl, ifp->if_sadl->sdl_len, IP_RECVIF, IPPROTO_IP); } if (*mp) mp = &(*mp)->m_next; if_put(ifp); } if (inp->inp_flags & INP_RECVTTL) { *mp = sbcreatecontrol((caddr_t) &ip->ip_ttl, sizeof(u_int8_t), IP_RECVTTL, IPPROTO_IP); if (*mp) mp = &(*mp)->m_next; } if (inp->inp_flags & INP_RECVRTABLE) { u_int rtableid = inp->inp_rtableid; #if NPF > 0 if (m && m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { struct pf_divert *divert; divert = pf_find_divert(m); KASSERT(divert != NULL); rtableid = divert->rdomain; } #endif *mp = sbcreatecontrol((caddr_t) &rtableid, sizeof(u_int), IP_RECVRTABLE, IPPROTO_IP); if (*mp) mp = &(*mp)->m_next; } } void ip_send_do_dispatch(void *xmq, int flags) { struct mbuf_queue *mq = xmq; struct mbuf *m; struct mbuf_list ml; struct m_tag *mtag; mq_delist(mq, &ml); if (ml_empty(&ml)) return; NET_LOCK_SHARED(); while ((m = ml_dequeue(&ml)) != NULL) { u_int32_t ipsecflowinfo = 0; if ((mtag = m_tag_find(m, PACKET_TAG_IPSEC_FLOWINFO, NULL)) != NULL) { ipsecflowinfo = *(u_int32_t *)(mtag + 1); m_tag_delete(m, mtag); } ip_output(m, NULL, NULL, flags, NULL, NULL, ipsecflowinfo); } NET_UNLOCK_SHARED(); } void ip_sendraw_dispatch(void *xmq) { ip_send_do_dispatch(xmq, IP_RAWOUTPUT); } void ip_send_dispatch(void *xmq) { ip_send_do_dispatch(xmq, 0); } void ip_send(struct mbuf *m) { mq_enqueue(&ipsend_mq, m); task_add(net_tq(0), &ipsend_task); } void ip_send_raw(struct mbuf *m) { mq_enqueue(&ipsendraw_mq, m); task_add(net_tq(0), &ipsendraw_task); }
242 1344 10 1340 309 10 10 10 8 10 238 18 238 183 229 81 236 655 238 235 38 229 144 604 225 95 96 68 59 96 96 96 96 96 92 96 10 9 4 10 4 6 9 1 1373 10 1372 1371 1373 1370 10 10 10 10 10 10 10 10 8 1369 562 1 1111 411 1113 185 1373 185 1368 1192 160 161 160 152 1 160 160 120 120 94 120 95 96 2 120 96 185 185 184 1367 1371 1373 131 1316 608 1371 185 1264 1212 185 593 1370 1371 1369 1366 1318 470 606 237 1194 1192 161 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 /* $OpenBSD: uvm_pmemrange.c,v 1.66 2024/05/01 12:54:27 mpi Exp $ */ /* * Copyright (c) 2024 Martin Pieuchot <mpi@openbsd.org> * Copyright (c) 2009, 2010 Ariane van der Steldt <ariane@stack.nl> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <uvm/uvm.h> #include <sys/malloc.h> #include <sys/kernel.h> #include <sys/proc.h> #include <sys/mount.h> /* * 2 trees: addr tree and size tree. * * The allocator keeps chunks of free pages (called a range). * Two pages are part of the same range if: * - all pages in between are part of that range, * - they are of the same memory type (zeroed or non-zeroed), * - they are part of the same pmemrange. * A pmemrange is a range of memory which is part of the same vm_physseg * and has a use-count. * * addr tree is vm_page[0].objt * size tree is vm_page[1].objt * * The size tree is not used for memory ranges of 1 page, instead, * single queue is vm_page[0].pageq * * vm_page[0].fpgsz describes the length of a free range. Two adjacent ranges * are joined, unless: * - they have pages in between them which are not free * - they belong to different memtypes (zeroed vs dirty memory) * - they are in different pmemrange areas (ISA vs non-ISA memory for instance) * - they are not a continuation of the same array * The latter issue is caused by vm_physseg ordering and splitting from the * MD initialization machinery. The MD code is dependant on freelists and * happens to split ISA memory from non-ISA memory. * (Note: freelists die die die!) * * uvm_page_init guarantees that every vm_physseg contains an array of * struct vm_page. Also, uvm_page_physload allocates an array of struct * vm_page. This code depends on that array. The array may break across * vm_physsegs boundaries. */ /* * Validate the flags of the page. (Used in asserts.) * Any free page must have the PQ_FREE flag set. * Free pages may be zeroed. * Pmap flags are left untouched. * * The PQ_FREE flag is not checked here: by not checking, we can easily use * this check in pages which are freed. */ #define VALID_FLAGS(pg_flags) \ (((pg_flags) & ~(PQ_FREE|PG_ZERO|PG_PMAPMASK)) == 0x0) /* Tree comparators. */ int uvm_pmemrange_addr_cmp(const struct uvm_pmemrange *, const struct uvm_pmemrange *); int uvm_pmemrange_use_cmp(struct uvm_pmemrange *, struct uvm_pmemrange *); int uvm_pmr_pg_to_memtype(struct vm_page *); #ifdef DDB void uvm_pmr_print(void); #endif /* * Memory types. The page flags are used to derive what the current memory * type of a page is. */ int uvm_pmr_pg_to_memtype(struct vm_page *pg) { if (pg->pg_flags & PG_ZERO) return UVM_PMR_MEMTYPE_ZERO; /* Default: dirty memory. */ return UVM_PMR_MEMTYPE_DIRTY; } /* Trees. */ RBT_GENERATE(uvm_pmr_addr, vm_page, objt, uvm_pmr_addr_cmp); RBT_GENERATE(uvm_pmr_size, vm_page, objt, uvm_pmr_size_cmp); RBT_GENERATE(uvm_pmemrange_addr, uvm_pmemrange, pmr_addr, uvm_pmemrange_addr_cmp); /* Validation. */ #ifdef DEBUG void uvm_pmr_assertvalid(struct uvm_pmemrange *pmr); #else #define uvm_pmr_assertvalid(pmr) do {} while (0) #endif psize_t uvm_pmr_get1page(psize_t, int, struct pglist *, paddr_t, paddr_t, int); struct uvm_pmemrange *uvm_pmr_allocpmr(void); struct vm_page *uvm_pmr_nfindsz(struct uvm_pmemrange *, psize_t, int); struct vm_page *uvm_pmr_nextsz(struct uvm_pmemrange *, struct vm_page *, int); void uvm_pmr_pnaddr(struct uvm_pmemrange *pmr, struct vm_page *pg, struct vm_page **pg_prev, struct vm_page **pg_next); struct vm_page *uvm_pmr_findnextsegment(struct uvm_pmemrange *, struct vm_page *, paddr_t); struct vm_page *uvm_pmr_findprevsegment(struct uvm_pmemrange *, struct vm_page *, paddr_t); psize_t uvm_pmr_remove_1strange(struct pglist *, paddr_t, struct vm_page **, int); psize_t uvm_pmr_remove_1strange_reverse(struct pglist *, paddr_t *); void uvm_pmr_split(paddr_t); struct uvm_pmemrange *uvm_pmemrange_find(paddr_t); struct uvm_pmemrange *uvm_pmemrange_use_insert(struct uvm_pmemrange_use *, struct uvm_pmemrange *); psize_t pow2divide(psize_t, psize_t); struct vm_page *uvm_pmr_rootupdate(struct uvm_pmemrange *, struct vm_page *, paddr_t, paddr_t, int); /* * Computes num/denom and rounds it up to the next power-of-2. * * This is a division function which calculates an approximation of * num/denom, with result =~ num/denom. It is meant to be fast and doesn't * have to be accurate. * * Providing too large a value makes the allocator slightly faster, at the * risk of hitting the failure case more often. Providing too small a value * makes the allocator a bit slower, but less likely to hit a failure case. */ psize_t pow2divide(psize_t num, psize_t denom) { int rshift; for (rshift = 0; num > denom; rshift++, denom <<= 1) ; return (paddr_t)1 << rshift; } /* * Predicate: lhs is a subrange or rhs. * * If rhs_low == 0: don't care about lower bound. * If rhs_high == 0: don't care about upper bound. */ #define PMR_IS_SUBRANGE_OF(lhs_low, lhs_high, rhs_low, rhs_high) \ (((rhs_low) == 0 || (lhs_low) >= (rhs_low)) && \ ((rhs_high) == 0 || (lhs_high) <= (rhs_high))) /* * Predicate: lhs intersects with rhs. * * If rhs_low == 0: don't care about lower bound. * If rhs_high == 0: don't care about upper bound. * Ranges don't intersect if they don't have any page in common, array * semantics mean that < instead of <= should be used here. */ #define PMR_INTERSECTS_WITH(lhs_low, lhs_high, rhs_low, rhs_high) \ (((rhs_low) == 0 || (rhs_low) < (lhs_high)) && \ ((rhs_high) == 0 || (lhs_low) < (rhs_high))) /* * Align to power-of-2 alignment. */ #define PMR_ALIGN(pgno, align) \ (((pgno) + ((align) - 1)) & ~((align) - 1)) #define PMR_ALIGN_DOWN(pgno, align) \ ((pgno) & ~((align) - 1)) /* * Comparator: sort by address ascending. */ int uvm_pmemrange_addr_cmp(const struct uvm_pmemrange *lhs, const struct uvm_pmemrange *rhs) { return lhs->low < rhs->low ? -1 : lhs->low > rhs->low; } /* * Comparator: sort by use ascending. * * The higher the use value of a range, the more devices need memory in * this range. Therefore allocate from the range with the lowest use first. */ int uvm_pmemrange_use_cmp(struct uvm_pmemrange *lhs, struct uvm_pmemrange *rhs) { int result; result = lhs->use < rhs->use ? -1 : lhs->use > rhs->use; if (result == 0) result = uvm_pmemrange_addr_cmp(lhs, rhs); return result; } int uvm_pmr_addr_cmp(const struct vm_page *lhs, const struct vm_page *rhs) { paddr_t lhs_addr, rhs_addr; lhs_addr = VM_PAGE_TO_PHYS(lhs); rhs_addr = VM_PAGE_TO_PHYS(rhs); return (lhs_addr < rhs_addr ? -1 : lhs_addr > rhs_addr); } int uvm_pmr_size_cmp(const struct vm_page *lhs, const struct vm_page *rhs) { psize_t lhs_size, rhs_size; int cmp; /* Using second tree, so we receive pg[1] instead of pg[0]. */ lhs_size = (lhs - 1)->fpgsz; rhs_size = (rhs - 1)->fpgsz; cmp = (lhs_size < rhs_size ? -1 : lhs_size > rhs_size); if (cmp == 0) cmp = uvm_pmr_addr_cmp(lhs - 1, rhs - 1); return cmp; } /* * Find the first range of free pages that is at least sz pages long. */ struct vm_page * uvm_pmr_nfindsz(struct uvm_pmemrange *pmr, psize_t sz, int mti) { struct vm_page *node, *best; KASSERT(sz >= 1); if (sz == 1 && !TAILQ_EMPTY(&pmr->single[mti])) return TAILQ_FIRST(&pmr->single[mti]); node = RBT_ROOT(uvm_pmr_size, &pmr->size[mti]); best = NULL; while (node != NULL) { if ((node - 1)->fpgsz >= sz) { best = (node - 1); node = RBT_LEFT(uvm_objtree, node); } else node = RBT_RIGHT(uvm_objtree, node); } return best; } /* * Finds the next range. The next range has a size >= pg->fpgsz. * Returns NULL if no more ranges are available. */ struct vm_page * uvm_pmr_nextsz(struct uvm_pmemrange *pmr, struct vm_page *pg, int mt) { struct vm_page *npg; KASSERT(pmr != NULL && pg != NULL); if (pg->fpgsz == 1) { if (TAILQ_NEXT(pg, pageq) != NULL) return TAILQ_NEXT(pg, pageq); else npg = RBT_MIN(uvm_pmr_size, &pmr->size[mt]); } else npg = RBT_NEXT(uvm_pmr_size, pg + 1); return npg == NULL ? NULL : npg - 1; } /* * Finds the previous and next ranges relative to the (uninserted) pg range. * * *pg_prev == NULL if no previous range is available, that can join with * pg. * *pg_next == NULL if no next range is available, that can join with * pg. */ void uvm_pmr_pnaddr(struct uvm_pmemrange *pmr, struct vm_page *pg, struct vm_page **pg_prev, struct vm_page **pg_next) { KASSERT(pg_prev != NULL && pg_next != NULL); *pg_next = RBT_NFIND(uvm_pmr_addr, &pmr->addr, pg); if (*pg_next == NULL) *pg_prev = RBT_MAX(uvm_pmr_addr, &pmr->addr); else *pg_prev = RBT_PREV(uvm_pmr_addr, *pg_next); KDASSERT(*pg_next == NULL || VM_PAGE_TO_PHYS(*pg_next) > VM_PAGE_TO_PHYS(pg)); KDASSERT(*pg_prev == NULL || VM_PAGE_TO_PHYS(*pg_prev) < VM_PAGE_TO_PHYS(pg)); /* Reset if not contig. */ if (*pg_prev != NULL && (atop(VM_PAGE_TO_PHYS(*pg_prev)) + (*pg_prev)->fpgsz != atop(VM_PAGE_TO_PHYS(pg)) || *pg_prev + (*pg_prev)->fpgsz != pg || /* Array broke. */ uvm_pmr_pg_to_memtype(*pg_prev) != uvm_pmr_pg_to_memtype(pg))) *pg_prev = NULL; if (*pg_next != NULL && (atop(VM_PAGE_TO_PHYS(pg)) + pg->fpgsz != atop(VM_PAGE_TO_PHYS(*pg_next)) || pg + pg->fpgsz != *pg_next || /* Array broke. */ uvm_pmr_pg_to_memtype(*pg_next) != uvm_pmr_pg_to_memtype(pg))) *pg_next = NULL; return; } /* * Remove a range from the address tree. * Address tree maintains pmr counters. */ void uvm_pmr_remove_addr(struct uvm_pmemrange *pmr, struct vm_page *pg) { KDASSERT(RBT_FIND(uvm_pmr_addr, &pmr->addr, pg) == pg); KDASSERT(pg->pg_flags & PQ_FREE); RBT_REMOVE(uvm_pmr_addr, &pmr->addr, pg); pmr->nsegs--; } /* * Remove a range from the size tree. */ void uvm_pmr_remove_size(struct uvm_pmemrange *pmr, struct vm_page *pg) { int memtype; #ifdef DEBUG struct vm_page *i; #endif KDASSERT(pg->fpgsz >= 1); KDASSERT(pg->pg_flags & PQ_FREE); memtype = uvm_pmr_pg_to_memtype(pg); if (pg->fpgsz == 1) { #ifdef DEBUG TAILQ_FOREACH(i, &pmr->single[memtype], pageq) { if (i == pg) break; } KDASSERT(i == pg); #endif TAILQ_REMOVE(&pmr->single[memtype], pg, pageq); } else { KDASSERT(RBT_FIND(uvm_pmr_size, &pmr->size[memtype], pg + 1) == pg + 1); RBT_REMOVE(uvm_pmr_size, &pmr->size[memtype], pg + 1); } } /* Remove from both trees. */ void uvm_pmr_remove(struct uvm_pmemrange *pmr, struct vm_page *pg) { uvm_pmr_assertvalid(pmr); uvm_pmr_remove_size(pmr, pg); uvm_pmr_remove_addr(pmr, pg); uvm_pmr_assertvalid(pmr); } /* * Insert the range described in pg. * Returns the range thus created (which may be joined with the previous and * next ranges). * If no_join, the caller guarantees that the range cannot possibly join * with adjacent ranges. */ struct vm_page * uvm_pmr_insert_addr(struct uvm_pmemrange *pmr, struct vm_page *pg, int no_join) { struct vm_page *prev, *next; #ifdef DEBUG struct vm_page *i; int mt; #endif KDASSERT(pg->pg_flags & PQ_FREE); KDASSERT(pg->fpgsz >= 1); #ifdef DEBUG for (mt = 0; mt < UVM_PMR_MEMTYPE_MAX; mt++) { TAILQ_FOREACH(i, &pmr->single[mt], pageq) KDASSERT(i != pg); if (pg->fpgsz > 1) { KDASSERT(RBT_FIND(uvm_pmr_size, &pmr->size[mt], pg + 1) == NULL); } KDASSERT(RBT_FIND(uvm_pmr_addr, &pmr->addr, pg) == NULL); } #endif if (!no_join) { uvm_pmr_pnaddr(pmr, pg, &prev, &next); if (next != NULL) { uvm_pmr_remove_size(pmr, next); uvm_pmr_remove_addr(pmr, next); pg->fpgsz += next->fpgsz; next->fpgsz = 0; } if (prev != NULL) { uvm_pmr_remove_size(pmr, prev); prev->fpgsz += pg->fpgsz; pg->fpgsz = 0; return prev; } } RBT_INSERT(uvm_pmr_addr, &pmr->addr, pg); pmr->nsegs++; return pg; } /* * Insert the range described in pg. * Returns the range thus created (which may be joined with the previous and * next ranges). * Page must already be in the address tree. */ void uvm_pmr_insert_size(struct uvm_pmemrange *pmr, struct vm_page *pg) { int memtype; #ifdef DEBUG struct vm_page *i; int mti; #endif KDASSERT(pg->fpgsz >= 1); KDASSERT(pg->pg_flags & PQ_FREE); memtype = uvm_pmr_pg_to_memtype(pg); #ifdef DEBUG for (mti = 0; mti < UVM_PMR_MEMTYPE_MAX; mti++) { TAILQ_FOREACH(i, &pmr->single[mti], pageq) KDASSERT(i != pg); if (pg->fpgsz > 1) { KDASSERT(RBT_FIND(uvm_pmr_size, &pmr->size[mti], pg + 1) == NULL); } KDASSERT(RBT_FIND(uvm_pmr_addr, &pmr->addr, pg) == pg); } for (i = pg; i < pg + pg->fpgsz; i++) KASSERT(uvm_pmr_pg_to_memtype(i) == memtype); #endif if (pg->fpgsz == 1) TAILQ_INSERT_TAIL(&pmr->single[memtype], pg, pageq); else RBT_INSERT(uvm_pmr_size, &pmr->size[memtype], pg + 1); } /* Insert in both trees. */ struct vm_page * uvm_pmr_insert(struct uvm_pmemrange *pmr, struct vm_page *pg, int no_join) { uvm_pmr_assertvalid(pmr); pg = uvm_pmr_insert_addr(pmr, pg, no_join); uvm_pmr_insert_size(pmr, pg); uvm_pmr_assertvalid(pmr); return pg; } /* * Find the last page that is part of this segment. * => pg: the range at which to start the search. * => boundary: the page number boundary specification (0 = no boundary). * => pmr: the pmemrange of the page. * * This function returns 1 before the next range, so if you want to have the * next range, you need to run TAILQ_NEXT(result, pageq) after calling. * The reason is that this way, the length of the segment is easily * calculated using: atop(result) - atop(pg) + 1. * Hence this function also never returns NULL. */ struct vm_page * uvm_pmr_findnextsegment(struct uvm_pmemrange *pmr, struct vm_page *pg, paddr_t boundary) { paddr_t first_boundary; struct vm_page *next; struct vm_page *prev; KDASSERT(pmr->low <= atop(VM_PAGE_TO_PHYS(pg)) && pmr->high > atop(VM_PAGE_TO_PHYS(pg))); if (boundary != 0) { first_boundary = PMR_ALIGN(atop(VM_PAGE_TO_PHYS(pg)) + 1, boundary); } else first_boundary = 0; /* * Increase next until it hits the first page of the next segment. * * While loop checks the following: * - next != NULL we have not reached the end of pgl * - boundary == 0 || next < first_boundary * we do not cross a boundary * - atop(prev) + 1 == atop(next) * still in the same segment * - low <= last * - high > last still in the same memory range * - memtype is equal allocator is unable to view different memtypes * as part of the same segment * - prev + 1 == next no array breakage occurs */ prev = pg; next = TAILQ_NEXT(prev, pageq); while (next != NULL && (boundary == 0 || atop(VM_PAGE_TO_PHYS(next)) < first_boundary) && atop(VM_PAGE_TO_PHYS(prev)) + 1 == atop(VM_PAGE_TO_PHYS(next)) && pmr->low <= atop(VM_PAGE_TO_PHYS(next)) && pmr->high > atop(VM_PAGE_TO_PHYS(next)) && uvm_pmr_pg_to_memtype(prev) == uvm_pmr_pg_to_memtype(next) && prev + 1 == next) { prev = next; next = TAILQ_NEXT(prev, pageq); } /* * End of this segment. */ return prev; } /* * Find the first page that is part of this segment. * => pg: the range at which to start the search. * => boundary: the page number boundary specification (0 = no boundary). * => pmr: the pmemrange of the page. * * This function returns 1 after the previous range, so if you want to have the * previous range, you need to run TAILQ_NEXT(result, pageq) after calling. * The reason is that this way, the length of the segment is easily * calculated using: atop(pg) - atop(result) + 1. * Hence this function also never returns NULL. */ struct vm_page * uvm_pmr_findprevsegment(struct uvm_pmemrange *pmr, struct vm_page *pg, paddr_t boundary) { paddr_t first_boundary; struct vm_page *next; struct vm_page *prev; KDASSERT(pmr->low <= atop(VM_PAGE_TO_PHYS(pg)) && pmr->high > atop(VM_PAGE_TO_PHYS(pg))); if (boundary != 0) { first_boundary = PMR_ALIGN_DOWN(atop(VM_PAGE_TO_PHYS(pg)), boundary); } else first_boundary = 0; /* * Increase next until it hits the first page of the previous segment. * * While loop checks the following: * - next != NULL we have not reached the end of pgl * - boundary == 0 || next >= first_boundary * we do not cross a boundary * - atop(prev) - 1 == atop(next) * still in the same segment * - low <= last * - high > last still in the same memory range * - memtype is equal allocator is unable to view different memtypes * as part of the same segment * - prev - 1 == next no array breakage occurs */ prev = pg; next = TAILQ_NEXT(prev, pageq); while (next != NULL && (boundary == 0 || atop(VM_PAGE_TO_PHYS(next)) >= first_boundary) && atop(VM_PAGE_TO_PHYS(prev)) - 1 == atop(VM_PAGE_TO_PHYS(next)) && pmr->low <= atop(VM_PAGE_TO_PHYS(next)) && pmr->high > atop(VM_PAGE_TO_PHYS(next)) && uvm_pmr_pg_to_memtype(prev) == uvm_pmr_pg_to_memtype(next) && prev - 1 == next) { prev = next; next = TAILQ_NEXT(prev, pageq); } /* * Start of this segment. */ return prev; } /* * Remove the first segment of contiguous pages from pgl. * A segment ends if it crosses boundary (unless boundary = 0) or * if it would enter a different uvm_pmemrange. * * Work: the page range that the caller is currently working with. * May be null. * * If is_desperate is non-zero, the smallest segment is erased. Otherwise, * the first segment is erased (which, if called by uvm_pmr_getpages(), * probably is the smallest or very close to it). */ psize_t uvm_pmr_remove_1strange(struct pglist *pgl, paddr_t boundary, struct vm_page **work, int is_desperate) { struct vm_page *start, *end, *iter, *iter_end, *inserted, *lowest; psize_t count; struct uvm_pmemrange *pmr, *pmr_iter; KASSERT(!TAILQ_EMPTY(pgl)); /* * Initialize to first page. * Unless desperate scan finds a better candidate, this is what'll be * erased. */ start = TAILQ_FIRST(pgl); pmr = uvm_pmemrange_find(atop(VM_PAGE_TO_PHYS(start))); end = uvm_pmr_findnextsegment(pmr, start, boundary); /* * If we are desperate, we _really_ want to get rid of the smallest * element (rather than a close match to the smallest element). */ if (is_desperate) { /* Linear search for smallest segment. */ pmr_iter = pmr; for (iter = TAILQ_NEXT(end, pageq); iter != NULL && start != end; iter = TAILQ_NEXT(iter_end, pageq)) { /* * Only update pmr if it doesn't match current * iteration. */ if (pmr->low > atop(VM_PAGE_TO_PHYS(iter)) || pmr->high <= atop(VM_PAGE_TO_PHYS(iter))) { pmr_iter = uvm_pmemrange_find(atop( VM_PAGE_TO_PHYS(iter))); } iter_end = uvm_pmr_findnextsegment(pmr_iter, iter, boundary); /* * Current iteration is smaller than best match so * far; update. */ if (VM_PAGE_TO_PHYS(iter_end) - VM_PAGE_TO_PHYS(iter) < VM_PAGE_TO_PHYS(end) - VM_PAGE_TO_PHYS(start)) { start = iter; end = iter_end; pmr = pmr_iter; } } } /* * Calculate count and end of the list. */ count = atop(VM_PAGE_TO_PHYS(end) - VM_PAGE_TO_PHYS(start)) + 1; lowest = start; end = TAILQ_NEXT(end, pageq); /* * Actually remove the range of pages. * * Sadly, this cannot be done using pointer iteration: * vm_physseg is not guaranteed to be sorted on address, hence * uvm_page_init() may not have initialized its array sorted by * page number. */ for (iter = start; iter != end; iter = iter_end) { iter_end = TAILQ_NEXT(iter, pageq); TAILQ_REMOVE(pgl, iter, pageq); } lowest->fpgsz = count; inserted = uvm_pmr_insert(pmr, lowest, 0); /* * If the caller was working on a range and this function modified * that range, update the pointer. */ if (work != NULL && *work != NULL && atop(VM_PAGE_TO_PHYS(inserted)) <= atop(VM_PAGE_TO_PHYS(*work)) && atop(VM_PAGE_TO_PHYS(inserted)) + inserted->fpgsz > atop(VM_PAGE_TO_PHYS(*work))) *work = inserted; return count; } /* * Remove the first segment of contiguous pages from a pgl * with the list elements in reverse order of physaddr. * * A segment ends if it would enter a different uvm_pmemrange. * * Stores starting physical address of the segment in pstart. */ psize_t uvm_pmr_remove_1strange_reverse(struct pglist *pgl, paddr_t *pstart) { struct vm_page *start, *end, *iter, *iter_end, *lowest; psize_t count; struct uvm_pmemrange *pmr; KASSERT(!TAILQ_EMPTY(pgl)); start = TAILQ_FIRST(pgl); pmr = uvm_pmemrange_find(atop(VM_PAGE_TO_PHYS(start))); end = uvm_pmr_findprevsegment(pmr, start, 0); KASSERT(end <= start); /* * Calculate count and end of the list. */ count = atop(VM_PAGE_TO_PHYS(start) - VM_PAGE_TO_PHYS(end)) + 1; lowest = end; end = TAILQ_NEXT(end, pageq); /* * Actually remove the range of pages. * * Sadly, this cannot be done using pointer iteration: * vm_physseg is not guaranteed to be sorted on address, hence * uvm_page_init() may not have initialized its array sorted by * page number. */ for (iter = start; iter != end; iter = iter_end) { iter_end = TAILQ_NEXT(iter, pageq); TAILQ_REMOVE(pgl, iter, pageq); } lowest->fpgsz = count; (void) uvm_pmr_insert(pmr, lowest, 0); *pstart = VM_PAGE_TO_PHYS(lowest); return count; } /* * Extract a number of pages from a segment of free pages. * Called by uvm_pmr_getpages. * * Returns the segment that was created from pages left over at the tail * of the remove set of pages, or NULL if no pages were left at the tail. */ struct vm_page * uvm_pmr_extract_range(struct uvm_pmemrange *pmr, struct vm_page *pg, paddr_t start, paddr_t end, struct pglist *result) { struct vm_page *after, *pg_i; psize_t before_sz, after_sz; #ifdef DEBUG psize_t i; #endif KDASSERT(end > start); KDASSERT(pmr->low <= atop(VM_PAGE_TO_PHYS(pg))); KDASSERT(pmr->high >= atop(VM_PAGE_TO_PHYS(pg)) + pg->fpgsz); KDASSERT(atop(VM_PAGE_TO_PHYS(pg)) <= start); KDASSERT(atop(VM_PAGE_TO_PHYS(pg)) + pg->fpgsz >= end); before_sz = start - atop(VM_PAGE_TO_PHYS(pg)); after_sz = atop(VM_PAGE_TO_PHYS(pg)) + pg->fpgsz - end; KDASSERT(before_sz + after_sz + (end - start) == pg->fpgsz); uvm_pmr_assertvalid(pmr); uvm_pmr_remove_size(pmr, pg); if (before_sz == 0) uvm_pmr_remove_addr(pmr, pg); after = pg + before_sz + (end - start); /* Add selected pages to result. */ for (pg_i = pg + before_sz; pg_i != after; pg_i++) { KASSERT(pg_i->pg_flags & PQ_FREE); pg_i->fpgsz = 0; TAILQ_INSERT_TAIL(result, pg_i, pageq); } /* Before handling. */ if (before_sz > 0) { pg->fpgsz = before_sz; uvm_pmr_insert_size(pmr, pg); } /* After handling. */ if (after_sz > 0) { #ifdef DEBUG for (i = 0; i < after_sz; i++) { KASSERT(!uvm_pmr_isfree(after + i)); } #endif KDASSERT(atop(VM_PAGE_TO_PHYS(after)) == end); after->fpgsz = after_sz; after = uvm_pmr_insert_addr(pmr, after, 1); uvm_pmr_insert_size(pmr, after); } uvm_pmr_assertvalid(pmr); return (after_sz > 0 ? after : NULL); } /* * Indicate to the page daemon that a nowait call failed and it should * recover at least some memory in the most restricted region (assumed * to be dma_constraint). */ extern volatile int uvm_nowait_failed; /* * Acquire a number of pages. * * count: the number of pages returned * start: lowest page number * end: highest page number +1 * (start = end = 0: no limitation) * align: power-of-2 alignment constraint (align = 1: no alignment) * boundary: power-of-2 boundary (boundary = 0: no boundary) * maxseg: maximum number of segments to return * flags: UVM_PLA_* flags * result: returned pages storage (uses pageq) */ int uvm_pmr_getpages(psize_t count, paddr_t start, paddr_t end, paddr_t align, paddr_t boundary, int maxseg, int flags, struct pglist *result) { struct uvm_pmemrange *pmr; /* Iterate memory ranges. */ struct vm_page *found, *f_next; /* Iterate chunks. */ psize_t fcount; /* Current found pages. */ int fnsegs; /* Current segment counter. */ int try, start_try; psize_t search[3]; paddr_t fstart, fend; /* Pages to be taken from found. */ int memtype; /* Requested memtype. */ int memtype_init; /* Best memtype. */ int desperate; /* True if allocation failed. */ #ifdef DIAGNOSTIC struct vm_page *diag_prev; /* Used during validation. */ #endif /* DIAGNOSTIC */ /* * Validate arguments. */ KASSERT(count > 0); KASSERT(start == 0 || end == 0 || start < end); KASSERT(align >= 1); KASSERT(powerof2(align)); KASSERT(maxseg > 0); KASSERT(boundary == 0 || powerof2(boundary)); KASSERT(boundary == 0 || maxseg * boundary >= count); KASSERT(TAILQ_EMPTY(result)); KASSERT(!(flags & UVM_PLA_WAITOK) ^ !(flags & UVM_PLA_NOWAIT)); /* * TRYCONTIG is a noop if you only want a single segment. * Remove it if that's the case: otherwise it'll deny the fast * allocation. */ if (maxseg == 1 || count == 1) flags &= ~UVM_PLA_TRYCONTIG; /* * Configure search. * * search[0] is one segment, only used in UVM_PLA_TRYCONTIG case. * search[1] is multiple segments, chosen to fulfill the search in * approximately even-sized segments. * This is a good trade-off between slightly reduced allocation speed * and less fragmentation. * search[2] is the worst case, in which all segments are evaluated. * This provides the least fragmentation, but makes the search * possibly longer (although in the case it is selected, that no * longer matters most). * * The exception is when maxseg == 1: since we can only fulfill that * with one segment of size pages, only a single search type has to * be attempted. */ if (maxseg == 1 || count == 1) { start_try = 2; search[2] = count; } else if (maxseg >= count && (flags & UVM_PLA_TRYCONTIG) == 0) { start_try = 2; search[2] = 1; } else { start_try = 0; search[0] = count; search[1] = pow2divide(count, maxseg); search[2] = 1; if ((flags & UVM_PLA_TRYCONTIG) == 0) start_try = 1; if (search[1] >= search[0]) { search[1] = search[0]; start_try = 1; } if (search[2] >= search[start_try]) { start_try = 2; } } /* * Memory type: if zeroed memory is requested, traverse the zero set. * Otherwise, traverse the dirty set. * * The memtype iterator is reinitialized to memtype_init on entrance * of a pmemrange. */ if (flags & UVM_PLA_ZERO) memtype_init = UVM_PMR_MEMTYPE_ZERO; else memtype_init = UVM_PMR_MEMTYPE_DIRTY; /* * Initially, we're not desperate. * * Note that if we return from a sleep, we are still desperate. * Chances are that memory pressure is still high, so resetting * seems over-optimistic to me. */ desperate = 0; again: uvm_lock_fpageq(); /* * check to see if we need to generate some free pages waking * the pagedaemon. */ if ((uvmexp.free - BUFPAGES_DEFICIT) < uvmexp.freemin || ((uvmexp.free - BUFPAGES_DEFICIT) < uvmexp.freetarg && (uvmexp.inactive + BUFPAGES_INACT) < uvmexp.inactarg)) wakeup(&uvm.pagedaemon); /* * fail if any of these conditions is true: * [1] there really are no free pages, or * [2] only kernel "reserved" pages remain and * the UVM_PLA_USERESERVE flag wasn't used. * [3] only pagedaemon "reserved" pages remain and * the requestor isn't the pagedaemon nor the syncer. */ if ((uvmexp.free <= (uvmexp.reserve_kernel + count)) && !(flags & UVM_PLA_USERESERVE)) { uvm_unlock_fpageq(); return ENOMEM; } if ((uvmexp.free <= (uvmexp.reserve_pagedaemon + count)) && (curproc != uvm.pagedaemon_proc) && (curproc != syncerproc)) { uvm_unlock_fpageq(); if (flags & UVM_PLA_WAITOK) { uvm_wait("uvm_pmr_getpages"); goto again; } return ENOMEM; } retry: /* Return point after sleeping. */ fcount = 0; fnsegs = 0; retry_desperate: /* * If we just want any page(s), go for the really fast option. */ if (count <= maxseg && align == 1 && boundary == 0 && (flags & UVM_PLA_TRYCONTIG) == 0) { fcount += uvm_pmr_get1page(count - fcount, memtype_init, result, start, end, 0); /* * If we found sufficient pages, go to the success exit code. * * Otherwise, go immediately to fail, since we collected * all we could anyway. */ if (fcount == count) goto out; else goto fail; } /* * The heart of the contig case. * * The code actually looks like this: * * foreach (struct pmemrange) { * foreach (memtype) { * foreach(try) { * foreach (free range of memtype in pmemrange, * starting at search[try]) { * while (range has space left) * take from range * } * } * } * * if next pmemrange has higher usecount than current: * enter desperate case (which will drain the pmemranges * until empty prior to moving to the next one) * } * * When desperate is activated, try always starts at the highest * value. The memtype loop is using a goto ReScanMemtype. * The try loop is using a goto ReScan. * The 'range has space left' loop uses label DrainFound. * * Writing them all as loops would take up a lot of screen space in * the form of indentation and some parts are easier to express * using the labels. */ TAILQ_FOREACH(pmr, &uvm.pmr_control.use, pmr_use) { /* Empty range. */ if (pmr->nsegs == 0) continue; /* Outside requested range. */ if (!PMR_INTERSECTS_WITH(pmr->low, pmr->high, start, end)) continue; memtype = memtype_init; rescan_memtype: /* Return point at memtype++. */ try = start_try; rescan: /* Return point at try++. */ for (found = uvm_pmr_nfindsz(pmr, search[try], memtype); found != NULL; found = f_next) { f_next = uvm_pmr_nextsz(pmr, found, memtype); fstart = atop(VM_PAGE_TO_PHYS(found)); if (start != 0) fstart = MAX(start, fstart); drain_found: /* * Throw away the first segment if fnsegs == maxseg * * Note that f_next is still valid after this call, * since we only allocated from entries before f_next. * We don't revisit the entries we already extracted * from unless we entered the desperate case. */ if (fnsegs == maxseg) { fnsegs--; fcount -= uvm_pmr_remove_1strange(result, boundary, &found, desperate); } fstart = PMR_ALIGN(fstart, align); fend = atop(VM_PAGE_TO_PHYS(found)) + found->fpgsz; if (end != 0) fend = MIN(end, fend); if (boundary != 0) { fend = MIN(fend, PMR_ALIGN(fstart + 1, boundary)); } if (fstart >= fend) continue; if (fend - fstart > count - fcount) fend = fstart + (count - fcount); fcount += fend - fstart; fnsegs++; found = uvm_pmr_extract_range(pmr, found, fstart, fend, result); if (fcount == count) goto out; /* * If there's still space left in found, try to * fully drain it prior to continuing. */ if (found != NULL) { fstart = fend; goto drain_found; } } /* Try a smaller search now. */ if (++try < nitems(search)) goto rescan; /* * Exhaust all memory types prior to going to the next memory * segment. * This means that zero-vs-dirty are eaten prior to moving * to a pmemrange with a higher use-count. * * Code is basically a difficult way of writing: * memtype = memtype_init; * do { * ...; * memtype += 1; * memtype %= MEMTYPE_MAX; * } while (memtype != memtype_init); */ memtype += 1; if (memtype == UVM_PMR_MEMTYPE_MAX) memtype = 0; if (memtype != memtype_init) goto rescan_memtype; /* * If not desperate, enter desperate case prior to eating all * the good stuff in the next range. */ if (!desperate && TAILQ_NEXT(pmr, pmr_use) != NULL && TAILQ_NEXT(pmr, pmr_use)->use != pmr->use) break; } /* * Not enough memory of the requested type available. Fall back to * less good memory that we'll clean up better later. * * This algorithm is not very smart though, it just starts scanning * a different typed range, but the nicer ranges of the previous * iteration may fall out. Hence there is a small chance of a false * negative. * * When desperate: scan all sizes starting at the smallest * (start_try = 1) and do not consider UVM_PLA_TRYCONTIG (which may * allow us to hit the fast path now). * * Also, because we will revisit entries we scanned before, we need * to reset the page queue, or we may end up releasing entries in * such a way as to invalidate f_next. */ if (!desperate) { desperate = 1; start_try = nitems(search) - 1; flags &= ~UVM_PLA_TRYCONTIG; while (!TAILQ_EMPTY(result)) uvm_pmr_remove_1strange(result, 0, NULL, 0); fnsegs = 0; fcount = 0; goto retry_desperate; } fail: /* Allocation failed. */ /* XXX: claim from memory reserve here */ while (!TAILQ_EMPTY(result)) uvm_pmr_remove_1strange(result, 0, NULL, 0); if (flags & UVM_PLA_WAITOK) { if (uvm_wait_pla(ptoa(start), ptoa(end) - 1, ptoa(count), flags & UVM_PLA_FAILOK) == 0) goto retry; KASSERT(flags & UVM_PLA_FAILOK); } else { if (!(flags & UVM_PLA_NOWAKE)) { uvm_nowait_failed = 1; wakeup(&uvm.pagedaemon); } } uvm_unlock_fpageq(); return ENOMEM; out: /* Allocation successful. */ uvmexp.free -= fcount; uvm_unlock_fpageq(); /* Update statistics and zero pages if UVM_PLA_ZERO. */ #ifdef DIAGNOSTIC fnsegs = 0; fcount = 0; diag_prev = NULL; #endif /* DIAGNOSTIC */ TAILQ_FOREACH(found, result, pageq) { atomic_clearbits_int(&found->pg_flags, PG_PMAPMASK); if (found->pg_flags & PG_ZERO) { uvm_lock_fpageq(); uvmexp.zeropages--; if (uvmexp.zeropages < UVM_PAGEZERO_TARGET) wakeup(&uvmexp.zeropages); uvm_unlock_fpageq(); } if (flags & UVM_PLA_ZERO) { if (found->pg_flags & PG_ZERO) uvmexp.pga_zerohit++; else { uvmexp.pga_zeromiss++; uvm_pagezero(found); } } atomic_clearbits_int(&found->pg_flags, PG_ZERO|PQ_FREE); found->uobject = NULL; found->uanon = NULL; found->pg_version++; /* * Validate that the page matches range criterium. */ KDASSERT(start == 0 || atop(VM_PAGE_TO_PHYS(found)) >= start); KDASSERT(end == 0 || atop(VM_PAGE_TO_PHYS(found)) < end); #ifdef DIAGNOSTIC /* * Update fcount (# found pages) and * fnsegs (# found segments) counters. */ if (diag_prev == NULL || /* new segment if it contains a hole */ atop(VM_PAGE_TO_PHYS(diag_prev)) + 1 != atop(VM_PAGE_TO_PHYS(found)) || /* new segment if it crosses boundary */ (atop(VM_PAGE_TO_PHYS(diag_prev)) & ~(boundary - 1)) != (atop(VM_PAGE_TO_PHYS(found)) & ~(boundary - 1))) fnsegs++; fcount++; diag_prev = found; #endif /* DIAGNOSTIC */ } #ifdef DIAGNOSTIC /* * Panic on algorithm failure. */ if (fcount != count || fnsegs > maxseg) { panic("pmemrange allocation error: " "allocated %ld pages in %d segments, " "but request was %ld pages in %d segments", fcount, fnsegs, count, maxseg); } #endif /* DIAGNOSTIC */ return 0; } /* * Acquire a single page. * * flags: UVM_PLA_* flags * result: returned page. */ struct vm_page * uvm_pmr_getone(int flags) { struct vm_page *pg; struct pglist pgl; TAILQ_INIT(&pgl); if (uvm_pmr_getpages(1, 0, 0, 1, 0, 1, flags, &pgl) != 0) return NULL; pg = TAILQ_FIRST(&pgl); KASSERT(pg != NULL && TAILQ_NEXT(pg, pageq) == NULL); return pg; } /* * Free a number of contig pages (invoked by uvm_page_init). */ void uvm_pmr_freepages(struct vm_page *pg, psize_t count) { struct uvm_pmemrange *pmr; psize_t i, pmr_count; struct vm_page *firstpg = pg; for (i = 0; i < count; i++) { KASSERT(atop(VM_PAGE_TO_PHYS(&pg[i])) == atop(VM_PAGE_TO_PHYS(pg)) + i); if (!((pg[i].pg_flags & PQ_FREE) == 0 && VALID_FLAGS(pg[i].pg_flags))) { printf("Flags: 0x%x, will panic now.\n", pg[i].pg_flags); } KASSERT((pg[i].pg_flags & PQ_FREE) == 0 && VALID_FLAGS(pg[i].pg_flags)); atomic_setbits_int(&pg[i].pg_flags, PQ_FREE); atomic_clearbits_int(&pg[i].pg_flags, PG_ZERO); } uvm_lock_fpageq(); for (i = count; i > 0; i -= pmr_count) { pmr = uvm_pmemrange_find(atop(VM_PAGE_TO_PHYS(pg))); KASSERT(pmr != NULL); pmr_count = MIN(i, pmr->high - atop(VM_PAGE_TO_PHYS(pg))); pg->fpgsz = pmr_count; uvm_pmr_insert(pmr, pg, 0); uvmexp.free += pmr_count; pg += pmr_count; } wakeup(&uvmexp.free); if (uvmexp.zeropages < UVM_PAGEZERO_TARGET) wakeup(&uvmexp.zeropages); uvm_wakeup_pla(VM_PAGE_TO_PHYS(firstpg), ptoa(count)); uvm_unlock_fpageq(); } /* * Free all pages in the queue. */ void uvm_pmr_freepageq(struct pglist *pgl) { struct vm_page *pg; paddr_t pstart; psize_t plen; TAILQ_FOREACH(pg, pgl, pageq) { if (!((pg->pg_flags & PQ_FREE) == 0 && VALID_FLAGS(pg->pg_flags))) { printf("Flags: 0x%x, will panic now.\n", pg->pg_flags); } KASSERT((pg->pg_flags & PQ_FREE) == 0 && VALID_FLAGS(pg->pg_flags)); atomic_setbits_int(&pg->pg_flags, PQ_FREE); atomic_clearbits_int(&pg->pg_flags, PG_ZERO); } uvm_lock_fpageq(); while (!TAILQ_EMPTY(pgl)) { pg = TAILQ_FIRST(pgl); if (pg == TAILQ_NEXT(pg, pageq) + 1) { /* * If pg is one behind the position of the * next page in the list in the page array, * try going backwards instead of forward. */ plen = uvm_pmr_remove_1strange_reverse(pgl, &pstart); } else { pstart = VM_PAGE_TO_PHYS(TAILQ_FIRST(pgl)); plen = uvm_pmr_remove_1strange(pgl, 0, NULL, 0); } uvmexp.free += plen; uvm_wakeup_pla(pstart, ptoa(plen)); } wakeup(&uvmexp.free); if (uvmexp.zeropages < UVM_PAGEZERO_TARGET) wakeup(&uvmexp.zeropages); uvm_unlock_fpageq(); return; } /* * Store a pmemrange in the list. * * The list is sorted by use. */ struct uvm_pmemrange * uvm_pmemrange_use_insert(struct uvm_pmemrange_use *useq, struct uvm_pmemrange *pmr) { struct uvm_pmemrange *iter; int cmp = 1; TAILQ_FOREACH(iter, useq, pmr_use) { cmp = uvm_pmemrange_use_cmp(pmr, iter); if (cmp == 0) return iter; if (cmp == -1) break; } if (iter == NULL) TAILQ_INSERT_TAIL(useq, pmr, pmr_use); else TAILQ_INSERT_BEFORE(iter, pmr, pmr_use); return NULL; } #ifdef DEBUG /* * Validation of the whole pmemrange. * Called with fpageq locked. */ void uvm_pmr_assertvalid(struct uvm_pmemrange *pmr) { struct vm_page *prev, *next, *i, *xref; int lcv, mti; /* Empty range */ if (pmr->nsegs == 0) return; /* Validate address tree. */ RBT_FOREACH(i, uvm_pmr_addr, &pmr->addr) { /* Validate the range. */ KASSERT(i->fpgsz > 0); KASSERT(atop(VM_PAGE_TO_PHYS(i)) >= pmr->low); KASSERT(atop(VM_PAGE_TO_PHYS(i)) + i->fpgsz <= pmr->high); /* Validate each page in this range. */ for (lcv = 0; lcv < i->fpgsz; lcv++) { /* * Only the first page has a size specification. * Rest is size 0. */ KASSERT(lcv == 0 || i[lcv].fpgsz == 0); /* * Flag check. */ KASSERT(VALID_FLAGS(i[lcv].pg_flags) && (i[lcv].pg_flags & PQ_FREE) == PQ_FREE); /* * Free pages are: * - not wired * - have no vm_anon * - have no uvm_object */ KASSERT(i[lcv].wire_count == 0); KASSERT(i[lcv].uanon == (void*)0xdeadbeef || i[lcv].uanon == NULL); KASSERT(i[lcv].uobject == (void*)0xdeadbeef || i[lcv].uobject == NULL); /* * Pages in a single range always have the same * memtype. */ KASSERT(uvm_pmr_pg_to_memtype(&i[0]) == uvm_pmr_pg_to_memtype(&i[lcv])); } /* Check that it shouldn't be joined with its predecessor. */ prev = RBT_PREV(uvm_pmr_addr, i); if (prev != NULL) { KASSERT(uvm_pmr_pg_to_memtype(i) != uvm_pmr_pg_to_memtype(prev) || atop(VM_PAGE_TO_PHYS(i)) > atop(VM_PAGE_TO_PHYS(prev)) + prev->fpgsz || prev + prev->fpgsz != i); } /* Assert i is in the size tree as well. */ if (i->fpgsz == 1) { TAILQ_FOREACH(xref, &pmr->single[uvm_pmr_pg_to_memtype(i)], pageq) { if (xref == i) break; } KASSERT(xref == i); } else { KASSERT(RBT_FIND(uvm_pmr_size, &pmr->size[uvm_pmr_pg_to_memtype(i)], i + 1) == i + 1); } } /* Validate size tree. */ for (mti = 0; mti < UVM_PMR_MEMTYPE_MAX; mti++) { for (i = uvm_pmr_nfindsz(pmr, 1, mti); i != NULL; i = next) { next = uvm_pmr_nextsz(pmr, i, mti); if (next != NULL) { KASSERT(i->fpgsz <= next->fpgsz); } /* Assert i is in the addr tree as well. */ KASSERT(RBT_FIND(uvm_pmr_addr, &pmr->addr, i) == i); /* Assert i is of the correct memory type. */ KASSERT(uvm_pmr_pg_to_memtype(i) == mti); } } /* Validate nsegs statistic. */ lcv = 0; RBT_FOREACH(i, uvm_pmr_addr, &pmr->addr) lcv++; KASSERT(pmr->nsegs == lcv); } #endif /* DEBUG */ /* * Split pmr at split point pageno. * Called with fpageq unlocked. * * Split is only applied if a pmemrange spans pageno. */ void uvm_pmr_split(paddr_t pageno) { struct uvm_pmemrange *pmr, *drain; struct vm_page *rebuild, *prev, *next; psize_t prev_sz; uvm_lock_fpageq(); pmr = uvm_pmemrange_find(pageno); if (pmr == NULL || !(pmr->low < pageno)) { /* No split required. */ uvm_unlock_fpageq(); return; } KASSERT(pmr->low < pageno); KASSERT(pmr->high > pageno); /* * uvm_pmr_allocpmr() calls into malloc() which in turn calls into * uvm_kmemalloc which calls into pmemrange, making the locking * a bit hard, so we just race! */ uvm_unlock_fpageq(); drain = uvm_pmr_allocpmr(); uvm_lock_fpageq(); pmr = uvm_pmemrange_find(pageno); if (pmr == NULL || !(pmr->low < pageno)) { /* * We lost the race since someone else ran this or a related * function, however this should be triggered very rarely so * we just leak the pmr. */ printf("uvm_pmr_split: lost one pmr\n"); uvm_unlock_fpageq(); return; } drain->low = pageno; drain->high = pmr->high; drain->use = pmr->use; uvm_pmr_assertvalid(pmr); uvm_pmr_assertvalid(drain); KASSERT(drain->nsegs == 0); RBT_FOREACH(rebuild, uvm_pmr_addr, &pmr->addr) { if (atop(VM_PAGE_TO_PHYS(rebuild)) >= pageno) break; } if (rebuild == NULL) prev = RBT_MAX(uvm_pmr_addr, &pmr->addr); else prev = RBT_PREV(uvm_pmr_addr, rebuild); KASSERT(prev == NULL || atop(VM_PAGE_TO_PHYS(prev)) < pageno); /* * Handle free chunk that spans the split point. */ if (prev != NULL && atop(VM_PAGE_TO_PHYS(prev)) + prev->fpgsz > pageno) { psize_t before, after; KASSERT(atop(VM_PAGE_TO_PHYS(prev)) < pageno); uvm_pmr_remove(pmr, prev); prev_sz = prev->fpgsz; before = pageno - atop(VM_PAGE_TO_PHYS(prev)); after = atop(VM_PAGE_TO_PHYS(prev)) + prev_sz - pageno; KASSERT(before > 0); KASSERT(after > 0); prev->fpgsz = before; uvm_pmr_insert(pmr, prev, 1); (prev + before)->fpgsz = after; uvm_pmr_insert(drain, prev + before, 1); } /* Move free chunks that no longer fall in the range. */ for (; rebuild != NULL; rebuild = next) { next = RBT_NEXT(uvm_pmr_addr, rebuild); uvm_pmr_remove(pmr, rebuild); uvm_pmr_insert(drain, rebuild, 1); } pmr->high = pageno; uvm_pmr_assertvalid(pmr); uvm_pmr_assertvalid(drain); RBT_INSERT(uvm_pmemrange_addr, &uvm.pmr_control.addr, drain); uvm_pmemrange_use_insert(&uvm.pmr_control.use, drain); uvm_unlock_fpageq(); } /* * Increase the usage counter for the given range of memory. * * The more usage counters a given range of memory has, the more will be * attempted not to allocate from it. * * Addresses here are in paddr_t, not page-numbers. * The lowest and highest allowed address are specified. */ void uvm_pmr_use_inc(paddr_t low, paddr_t high) { struct uvm_pmemrange *pmr; paddr_t sz; /* pmr uses page numbers, translate low and high. */ high++; high = atop(trunc_page(high)); low = atop(round_page(low)); uvm_pmr_split(low); uvm_pmr_split(high); sz = 0; uvm_lock_fpageq(); /* Increase use count on segments in range. */ RBT_FOREACH(pmr, uvm_pmemrange_addr, &uvm.pmr_control.addr) { if (PMR_IS_SUBRANGE_OF(pmr->low, pmr->high, low, high)) { TAILQ_REMOVE(&uvm.pmr_control.use, pmr, pmr_use); pmr->use++; sz += pmr->high - pmr->low; uvm_pmemrange_use_insert(&uvm.pmr_control.use, pmr); } uvm_pmr_assertvalid(pmr); } uvm_unlock_fpageq(); KASSERT(sz >= high - low); } /* * Allocate a pmemrange. * * If called from uvm_page_init, the uvm_pageboot_alloc is used. * If called after uvm_init, malloc is used. * (And if called in between, you're dead.) */ struct uvm_pmemrange * uvm_pmr_allocpmr(void) { struct uvm_pmemrange *nw; int i; /* We're only ever hitting the !uvm.page_init_done case for now. */ if (!uvm.page_init_done) { nw = (struct uvm_pmemrange *) uvm_pageboot_alloc(sizeof(struct uvm_pmemrange)); } else { nw = malloc(sizeof(struct uvm_pmemrange), M_VMMAP, M_NOWAIT); } KASSERT(nw != NULL); memset(nw, 0, sizeof(struct uvm_pmemrange)); RBT_INIT(uvm_pmr_addr, &nw->addr); for (i = 0; i < UVM_PMR_MEMTYPE_MAX; i++) { RBT_INIT(uvm_pmr_size, &nw->size[i]); TAILQ_INIT(&nw->single[i]); } return nw; } /* * Initialization of pmr. * Called by uvm_page_init. * * Sets up pmemranges. */ void uvm_pmr_init(void) { struct uvm_pmemrange *new_pmr; int i; TAILQ_INIT(&uvm.pmr_control.use); RBT_INIT(uvm_pmemrange_addr, &uvm.pmr_control.addr); TAILQ_INIT(&uvm.pmr_control.allocs); /* By default, one range for the entire address space. */ new_pmr = uvm_pmr_allocpmr(); new_pmr->low = 0; new_pmr->high = atop((paddr_t)-1) + 1; RBT_INSERT(uvm_pmemrange_addr, &uvm.pmr_control.addr, new_pmr); uvm_pmemrange_use_insert(&uvm.pmr_control.use, new_pmr); for (i = 0; uvm_md_constraints[i] != NULL; i++) { uvm_pmr_use_inc(uvm_md_constraints[i]->ucr_low, uvm_md_constraints[i]->ucr_high); } } /* * Find the pmemrange that contains the given page number. * * (Manually traverses the binary tree, because that is cheaper on stack * usage.) */ struct uvm_pmemrange * uvm_pmemrange_find(paddr_t pageno) { struct uvm_pmemrange *pmr; pmr = RBT_ROOT(uvm_pmemrange_addr, &uvm.pmr_control.addr); while (pmr != NULL) { if (pmr->low > pageno) pmr = RBT_LEFT(uvm_pmemrange_addr, pmr); else if (pmr->high <= pageno) pmr = RBT_RIGHT(uvm_pmemrange_addr, pmr); else break; } return pmr; } #if defined(DDB) || defined(DEBUG) /* * Return true if the given page is in any of the free lists. * Used by uvm_page_printit. * This function is safe, even if the page is not on the freeq. * Note: does not apply locking, only called from ddb. */ int uvm_pmr_isfree(struct vm_page *pg) { struct vm_page *r; struct uvm_pmemrange *pmr; pmr = uvm_pmemrange_find(atop(VM_PAGE_TO_PHYS(pg))); if (pmr == NULL) return 0; r = RBT_NFIND(uvm_pmr_addr, &pmr->addr, pg); if (r == NULL) r = RBT_MAX(uvm_pmr_addr, &pmr->addr); else if (r != pg) r = RBT_PREV(uvm_pmr_addr, r); if (r == NULL) return 0; /* Empty tree. */ KDASSERT(atop(VM_PAGE_TO_PHYS(r)) <= atop(VM_PAGE_TO_PHYS(pg))); return atop(VM_PAGE_TO_PHYS(r)) + r->fpgsz > atop(VM_PAGE_TO_PHYS(pg)); } #endif /* DEBUG */ /* * Given a root of a tree, find a range which intersects start, end and * is of the same memtype. * * Page must be in the address tree. */ struct vm_page* uvm_pmr_rootupdate(struct uvm_pmemrange *pmr, struct vm_page *init_root, paddr_t start, paddr_t end, int memtype) { int direction; struct vm_page *root; struct vm_page *high, *high_next; struct vm_page *low, *low_next; KDASSERT(pmr != NULL && init_root != NULL); root = init_root; /* Which direction to use for searching. */ if (start != 0 && atop(VM_PAGE_TO_PHYS(root)) + root->fpgsz <= start) direction = 1; else if (end != 0 && atop(VM_PAGE_TO_PHYS(root)) >= end) direction = -1; else /* nothing to do */ return root; /* First, update root to fall within the chosen range. */ while (root && !PMR_INTERSECTS_WITH( atop(VM_PAGE_TO_PHYS(root)), atop(VM_PAGE_TO_PHYS(root)) + root->fpgsz, start, end)) { if (direction == 1) root = RBT_RIGHT(uvm_objtree, root); else root = RBT_LEFT(uvm_objtree, root); } if (root == NULL || uvm_pmr_pg_to_memtype(root) == memtype) return root; /* * Root is valid, but of the wrong memtype. * * Try to find a range that has the given memtype in the subtree * (memtype mismatches are costly, either because the conversion * is expensive, or a later allocation will need to do the opposite * conversion, which will be expensive). * * * First, simply increase address until we hit something we can use. * Cache the upper page, so we can page-walk later. */ high = root; high_next = RBT_RIGHT(uvm_objtree, high); while (high_next != NULL && PMR_INTERSECTS_WITH( atop(VM_PAGE_TO_PHYS(high_next)), atop(VM_PAGE_TO_PHYS(high_next)) + high_next->fpgsz, start, end)) { high = high_next; if (uvm_pmr_pg_to_memtype(high) == memtype) return high; high_next = RBT_RIGHT(uvm_objtree, high); } /* * Second, decrease the address until we hit something we can use. * Cache the lower page, so we can page-walk later. */ low = root; low_next = RBT_LEFT(uvm_objtree, low); while (low_next != NULL && PMR_INTERSECTS_WITH( atop(VM_PAGE_TO_PHYS(low_next)), atop(VM_PAGE_TO_PHYS(low_next)) + low_next->fpgsz, start, end)) { low = low_next; if (uvm_pmr_pg_to_memtype(low) == memtype) return low; low_next = RBT_LEFT(uvm_objtree, low); } if (low == high) return NULL; /* No hits. Walk the address tree until we find something usable. */ for (low = RBT_NEXT(uvm_pmr_addr, low); low != high; low = RBT_NEXT(uvm_pmr_addr, low)) { KDASSERT(PMR_IS_SUBRANGE_OF(atop(VM_PAGE_TO_PHYS(low)), atop(VM_PAGE_TO_PHYS(low)) + low->fpgsz, start, end)); if (uvm_pmr_pg_to_memtype(low) == memtype) return low; } /* Nothing found. */ return NULL; } /* * Allocate any page, the fastest way. Page number constraints only. */ psize_t uvm_pmr_get1page(psize_t count, int memtype_init, struct pglist *result, paddr_t start, paddr_t end, int memtype_only) { struct uvm_pmemrange *pmr; struct vm_page *found, *splitpg; psize_t fcount; int memtype; fcount = 0; TAILQ_FOREACH(pmr, &uvm.pmr_control.use, pmr_use) { /* We're done. */ if (fcount == count) break; /* Outside requested range. */ if (!(start == 0 && end == 0) && !PMR_INTERSECTS_WITH(pmr->low, pmr->high, start, end)) continue; /* Range is empty. */ if (pmr->nsegs == 0) continue; /* Loop over all memtypes, starting at memtype_init. */ memtype = memtype_init; while (fcount != count) { found = TAILQ_FIRST(&pmr->single[memtype]); /* * If found is outside the range, walk the list * until we find something that intersects with * boundaries. */ while (found && !PMR_INTERSECTS_WITH( atop(VM_PAGE_TO_PHYS(found)), atop(VM_PAGE_TO_PHYS(found)) + 1, start, end)) found = TAILQ_NEXT(found, pageq); if (found == NULL) { /* * Check if the size tree contains a range * that intersects with the boundaries. As the * allocation is for any page, try the smallest * range so that large ranges are preserved for * more constrained cases. Only one entry is * checked here, to avoid a brute-force search. * * Note that a size tree gives pg[1] instead of * pg[0]. */ found = RBT_MIN(uvm_pmr_size, &pmr->size[memtype]); if (found != NULL) { found--; if (!PMR_INTERSECTS_WITH( atop(VM_PAGE_TO_PHYS(found)), atop(VM_PAGE_TO_PHYS(found)) + found->fpgsz, start, end)) found = NULL; } } if (found == NULL) { /* * Try address-guided search to meet the page * number constraints. */ found = RBT_ROOT(uvm_pmr_addr, &pmr->addr); if (found != NULL) { found = uvm_pmr_rootupdate(pmr, found, start, end, memtype); } } if (found != NULL) { uvm_pmr_assertvalid(pmr); uvm_pmr_remove_size(pmr, found); /* * If the page intersects the end, then it'll * need splitting. * * Note that we don't need to split if the page * intersects start: the drain function will * simply stop on hitting start. */ if (end != 0 && atop(VM_PAGE_TO_PHYS(found)) + found->fpgsz > end) { psize_t splitsz = atop(VM_PAGE_TO_PHYS(found)) + found->fpgsz - end; uvm_pmr_remove_addr(pmr, found); uvm_pmr_assertvalid(pmr); found->fpgsz -= splitsz; splitpg = found + found->fpgsz; splitpg->fpgsz = splitsz; uvm_pmr_insert(pmr, splitpg, 1); /* * At this point, splitpg and found * actually should be joined. * But we explicitly disable that, * because we will start subtracting * from found. */ KASSERT(start == 0 || atop(VM_PAGE_TO_PHYS(found)) + found->fpgsz > start); uvm_pmr_insert_addr(pmr, found, 1); } /* * Fetch pages from the end. * If the range is larger than the requested * number of pages, this saves us an addr-tree * update. * * Since we take from the end and insert at * the head, any ranges keep preserved. */ while (found->fpgsz > 0 && fcount < count && (start == 0 || atop(VM_PAGE_TO_PHYS(found)) + found->fpgsz > start)) { found->fpgsz--; fcount++; TAILQ_INSERT_HEAD(result, &found[found->fpgsz], pageq); } if (found->fpgsz > 0) { uvm_pmr_insert_size(pmr, found); KDASSERT(fcount == count); uvm_pmr_assertvalid(pmr); return fcount; } /* * Delayed addr-tree removal. */ uvm_pmr_remove_addr(pmr, found); uvm_pmr_assertvalid(pmr); } else { if (memtype_only) break; /* * Skip to the next memtype. */ memtype += 1; if (memtype == UVM_PMR_MEMTYPE_MAX) memtype = 0; if (memtype == memtype_init) break; } } } /* * Search finished. * * Ran out of ranges before enough pages were gathered, or we hit the * case where found->fpgsz == count - fcount, in which case the * above exit condition didn't trigger. * * On failure, caller will free the pages. */ return fcount; } #ifdef DDB /* * Print information about pmemrange. * Does not do locking (so either call it from DDB or acquire fpageq lock * before invoking. */ void uvm_pmr_print(void) { struct uvm_pmemrange *pmr; struct vm_page *pg; psize_t size[UVM_PMR_MEMTYPE_MAX]; psize_t free; int useq_len; int mt; printf("Ranges, use queue:\n"); useq_len = 0; TAILQ_FOREACH(pmr, &uvm.pmr_control.use, pmr_use) { useq_len++; free = 0; for (mt = 0; mt < UVM_PMR_MEMTYPE_MAX; mt++) { pg = RBT_MAX(uvm_pmr_size, &pmr->size[mt]); if (pg != NULL) pg--; else pg = TAILQ_FIRST(&pmr->single[mt]); size[mt] = (pg == NULL ? 0 : pg->fpgsz); RBT_FOREACH(pg, uvm_pmr_addr, &pmr->addr) free += pg->fpgsz; } printf("* [0x%lx-0x%lx] use=%d nsegs=%ld", (unsigned long)pmr->low, (unsigned long)pmr->high, pmr->use, (unsigned long)pmr->nsegs); for (mt = 0; mt < UVM_PMR_MEMTYPE_MAX; mt++) { printf(" maxsegsz[%d]=0x%lx", mt, (unsigned long)size[mt]); } printf(" free=0x%lx\n", (unsigned long)free); } printf("#ranges = %d\n", useq_len); } #endif /* * uvm_wait_pla: wait (sleep) for the page daemon to free some pages * in a specific physmem area. * * Returns ENOMEM if the pagedaemon failed to free any pages. * If not failok, failure will lead to panic. * * Must be called with fpageq locked. */ int uvm_wait_pla(paddr_t low, paddr_t high, paddr_t size, int failok) { struct uvm_pmalloc pma; const char *wmsg = "pmrwait"; if (curproc == uvm.pagedaemon_proc) { /* * This is not that uncommon when the pagedaemon is trying * to flush out a large mmapped file. VOP_WRITE will circle * back through the buffer cache and try to get more memory. * The pagedaemon starts by calling bufbackoff, but we can * easily use up that reserve in a single scan iteration. */ uvm_unlock_fpageq(); if (bufbackoff(NULL, atop(size)) == 0) { uvm_lock_fpageq(); return 0; } uvm_lock_fpageq(); /* * XXX detect pagedaemon deadlock - see comment in * uvm_wait(), as this is exactly the same issue. */ printf("pagedaemon: wait_pla deadlock detected!\n"); msleep_nsec(&uvmexp.free, &uvm.fpageqlock, PVM, wmsg, MSEC_TO_NSEC(125)); #if defined(DEBUG) /* DEBUG: panic so we can debug it */ panic("wait_pla pagedaemon deadlock"); #endif return 0; } for (;;) { pma.pm_constraint.ucr_low = low; pma.pm_constraint.ucr_high = high; pma.pm_size = size; pma.pm_flags = UVM_PMA_LINKED; TAILQ_INSERT_TAIL(&uvm.pmr_control.allocs, &pma, pmq); wakeup(&uvm.pagedaemon); /* wake the daemon! */ while (pma.pm_flags & (UVM_PMA_LINKED | UVM_PMA_BUSY)) msleep_nsec(&pma, &uvm.fpageqlock, PVM, wmsg, INFSLP); if (!(pma.pm_flags & UVM_PMA_FREED) && pma.pm_flags & UVM_PMA_FAIL) { if (failok) return ENOMEM; printf("uvm_wait: failed to free %ld pages between " "0x%lx-0x%lx\n", atop(size), low, high); } else return 0; } /* UNREACHABLE */ } /* * Wake up uvm_pmalloc sleepers. */ void uvm_wakeup_pla(paddr_t low, psize_t len) { struct uvm_pmalloc *pma, *pma_next; paddr_t high; high = low + len; /* Wake specific allocations waiting for this memory. */ for (pma = TAILQ_FIRST(&uvm.pmr_control.allocs); pma != NULL; pma = pma_next) { pma_next = TAILQ_NEXT(pma, pmq); if (low < pma->pm_constraint.ucr_high && high > pma->pm_constraint.ucr_low) { pma->pm_flags |= UVM_PMA_FREED; if (!(pma->pm_flags & UVM_PMA_BUSY)) { pma->pm_flags &= ~UVM_PMA_LINKED; TAILQ_REMOVE(&uvm.pmr_control.allocs, pma, pmq); wakeup(pma); } } } } void uvm_pagezero_thread(void *arg) { struct pglist pgl; struct vm_page *pg; int count; /* Run at the lowest possible priority. */ curproc->p_p->ps_nice = NZERO + PRIO_MAX; KERNEL_UNLOCK(); TAILQ_INIT(&pgl); for (;;) { uvm_lock_fpageq(); while (uvmexp.zeropages >= UVM_PAGEZERO_TARGET || (count = uvm_pmr_get1page(16, UVM_PMR_MEMTYPE_DIRTY, &pgl, 0, 0, 1)) == 0) { msleep_nsec(&uvmexp.zeropages, &uvm.fpageqlock, MAXPRI, "pgzero", INFSLP); } uvm_unlock_fpageq(); TAILQ_FOREACH(pg, &pgl, pageq) { uvm_pagezero(pg); atomic_setbits_int(&pg->pg_flags, PG_ZERO); } uvm_lock_fpageq(); while (!TAILQ_EMPTY(&pgl)) uvm_pmr_remove_1strange(&pgl, 0, NULL, 0); uvmexp.zeropages += count; uvm_unlock_fpageq(); yield(); } } #if defined(MULTIPROCESSOR) && defined(__HAVE_UVM_PERCPU) int uvm_pmr_cache_alloc(struct uvm_pmr_cache_item *upci) { struct vm_page *pg; struct pglist pgl; int flags = UVM_PLA_NOWAIT|UVM_PLA_NOWAKE; int npages = UVM_PMR_CACHEMAGSZ; splassert(IPL_VM); KASSERT(upci->upci_npages == 0); TAILQ_INIT(&pgl); if (uvm_pmr_getpages(npages, 0, 0, 1, 0, npages, flags, &pgl)) return -1; while ((pg = TAILQ_FIRST(&pgl)) != NULL) { TAILQ_REMOVE(&pgl, pg, pageq); upci->upci_pages[upci->upci_npages] = pg; upci->upci_npages++; } atomic_add_int(&uvmexp.percpucaches, npages); return 0; } struct vm_page * uvm_pmr_cache_get(int flags) { struct uvm_pmr_cache *upc = &curcpu()->ci_uvm; struct uvm_pmr_cache_item *upci; struct vm_page *pg; int s; s = splvm(); upci = &upc->upc_magz[upc->upc_actv]; if (upci->upci_npages == 0) { unsigned int prev; prev = (upc->upc_actv == 0) ? 1 : 0; upci = &upc->upc_magz[prev]; if (upci->upci_npages == 0) { atomic_inc_int(&uvmexp.pcpmiss); if (uvm_pmr_cache_alloc(upci)) { splx(s); return uvm_pmr_getone(flags); } } /* Swap magazines */ upc->upc_actv = prev; } else { atomic_inc_int(&uvmexp.pcphit); } atomic_dec_int(&uvmexp.percpucaches); upci->upci_npages--; pg = upci->upci_pages[upci->upci_npages]; splx(s); if (flags & UVM_PLA_ZERO) uvm_pagezero(pg); return pg; } void uvm_pmr_cache_free(struct uvm_pmr_cache_item *upci) { struct pglist pgl; unsigned int i; splassert(IPL_VM); TAILQ_INIT(&pgl); for (i = 0; i < upci->upci_npages; i++) TAILQ_INSERT_TAIL(&pgl, upci->upci_pages[i], pageq); uvm_pmr_freepageq(&pgl); atomic_sub_int(&uvmexp.percpucaches, upci->upci_npages); upci->upci_npages = 0; memset(upci->upci_pages, 0, sizeof(upci->upci_pages)); } void uvm_pmr_cache_put(struct vm_page *pg) { struct uvm_pmr_cache *upc = &curcpu()->ci_uvm; struct uvm_pmr_cache_item *upci; int s; s = splvm(); upci = &upc->upc_magz[upc->upc_actv]; if (upci->upci_npages >= UVM_PMR_CACHEMAGSZ) { unsigned int prev; prev = (upc->upc_actv == 0) ? 1 : 0; upci = &upc->upc_magz[prev]; if (upci->upci_npages > 0) uvm_pmr_cache_free(upci); /* Swap magazines */ upc->upc_actv = prev; KASSERT(upci->upci_npages == 0); } upci->upci_pages[upci->upci_npages] = pg; upci->upci_npages++; atomic_inc_int(&uvmexp.percpucaches); splx(s); } void uvm_pmr_cache_drain(void) { struct uvm_pmr_cache *upc = &curcpu()->ci_uvm; int s; s = splvm(); uvm_pmr_cache_free(&upc->upc_magz[0]); uvm_pmr_cache_free(&upc->upc_magz[1]); splx(s); } #else /* !(MULTIPROCESSOR && __HAVE_UVM_PERCPU) */ struct vm_page * uvm_pmr_cache_get(int flags) { return uvm_pmr_getone(flags); } void uvm_pmr_cache_put(struct vm_page *pg) { uvm_pmr_freepages(pg, 1); } void uvm_pmr_cache_drain(void) { } #endif
4 2 2 5 2 1 2 1 2 4 1 1 53 52 1 1 55 5 1 2 2 50 49 39 1 1 2 1 2 1 3 3 2 2 1 3 8 1 7 4 8 5 3 5 3 1 1 8 1 1 1 3 2 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 /* $OpenBSD: wskbd.c,v 1.119 2024/03/25 13:01:49 mvs Exp $ */ /* $NetBSD: wskbd.c,v 1.80 2005/05/04 01:52:16 augustss Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. * * Keysym translator: * Contributed to The NetBSD Foundation by Juergen Hannken-Illjes. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Christopher G. Demetriou * for the NetBSD Project. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Lawrence Berkeley Laboratory. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kbd.c 8.2 (Berkeley) 10/30/93 */ /* * Keyboard driver (/dev/wskbd*). Translates incoming bytes to ASCII or * to `wscons_events' and passes them up to the appropriate reader. */ #include <sys/param.h> #include <sys/conf.h> #include <sys/device.h> #include <sys/ioctl.h> #include <sys/kernel.h> #include <sys/proc.h> #include <sys/syslog.h> #include <sys/systm.h> #include <sys/timeout.h> #include <sys/malloc.h> #include <sys/tty.h> #include <sys/signalvar.h> #include <sys/errno.h> #include <sys/fcntl.h> #include <sys/vnode.h> #include <sys/task.h> #include <ddb/db_var.h> #include <dev/wscons/wscons_features.h> #include <dev/wscons/wsconsio.h> #include <dev/wscons/wskbdvar.h> #include <dev/wscons/wsksymdef.h> #include <dev/wscons/wsksymvar.h> #include <dev/wscons/wsdisplayvar.h> #include <dev/wscons/wseventvar.h> #include <dev/wscons/wscons_callbacks.h> #include "audio.h" /* NAUDIO (mixer tuning) */ #include "wsdisplay.h" #include "wskbd.h" #include "wsmux.h" #if NWSDISPLAY > 0 #include <sys/atomic.h> #endif #ifdef WSKBD_DEBUG #define DPRINTF(x) if (wskbddebug) printf x int wskbddebug = 0; #else #define DPRINTF(x) #endif #include <dev/wscons/wsmuxvar.h> struct wskbd_internal { const struct wskbd_consops *t_consops; void *t_consaccesscookie; int t_modifiers; int t_composelen; /* remaining entries in t_composebuf */ keysym_t t_composebuf[2]; int t_flags; #define WSKFL_METAESC 1 #define MAXKEYSYMSPERKEY 2 /* ESC <key> at max */ keysym_t t_symbols[MAXKEYSYMSPERKEY]; struct wskbd_softc *t_sc; /* back pointer */ struct wskbd_mapdata t_keymap; /* translation map table and current layout */ }; struct wskbd_softc { struct wsevsrc sc_base; struct wskbd_internal *id; const struct wskbd_accessops *sc_accessops; void *sc_accesscookie; int sc_ledstate; int sc_isconsole; struct wskbd_bell_data sc_bell_data; struct wskbd_keyrepeat_data sc_keyrepeat_data; int sc_repeating; /* we've called timeout() */ int sc_repkey; struct timeout sc_repeat_ch; u_int sc_repeat_type; int sc_repeat_value; int sc_translating; /* xlate to chars for emulation */ int sc_maplen; /* number of entries in sc_map */ struct wscons_keymap *sc_map; /* current translation map */ int sc_refcnt; u_char sc_dying; /* device is being detached */ #if NAUDIO > 0 void *sc_audiocookie; #endif struct task sc_kbd_backlight_task; u_int sc_kbd_backlight_cmd; #if NWSDISPLAY > 0 struct task sc_brightness_task; int sc_brightness_steps; #endif }; enum wskbd_kbd_backlight_cmds { KBD_BACKLIGHT_NONE, KBD_BACKLIGHT_UP, KBD_BACKLIGHT_DOWN, KBD_BACKLIGHT_TOGGLE, }; #define MOD_SHIFT_L (1 << 0) #define MOD_SHIFT_R (1 << 1) #define MOD_SHIFTLOCK (1 << 2) #define MOD_CAPSLOCK (1 << 3) #define MOD_CONTROL_L (1 << 4) #define MOD_CONTROL_R (1 << 5) #define MOD_META_L (1 << 6) #define MOD_META_R (1 << 7) #define MOD_MODESHIFT (1 << 8) #define MOD_NUMLOCK (1 << 9) #define MOD_COMPOSE (1 << 10) #define MOD_HOLDSCREEN (1 << 11) #define MOD_COMMAND (1 << 12) #define MOD_COMMAND1 (1 << 13) #define MOD_COMMAND2 (1 << 14) #define MOD_MODELOCK (1 << 15) #define MOD_ANYSHIFT (MOD_SHIFT_L | MOD_SHIFT_R | MOD_SHIFTLOCK) #define MOD_ANYCONTROL (MOD_CONTROL_L | MOD_CONTROL_R) #define MOD_ANYMETA (MOD_META_L | MOD_META_R) #define MOD_ANYLED (MOD_SHIFTLOCK | MOD_CAPSLOCK | MOD_NUMLOCK | \ MOD_COMPOSE | MOD_HOLDSCREEN) #define MOD_ONESET(id, mask) (((id)->t_modifiers & (mask)) != 0) #define MOD_ALLSET(id, mask) (((id)->t_modifiers & (mask)) == (mask)) keysym_t ksym_upcase(keysym_t); int wskbd_match(struct device *, void *, void *); void wskbd_attach(struct device *, struct device *, void *); int wskbd_detach(struct device *, int); int wskbd_activate(struct device *, int); int wskbd_displayioctl(struct device *, u_long, caddr_t, int, struct proc *); int wskbd_displayioctl_sc(struct wskbd_softc *, u_long, caddr_t, int, struct proc *, int); void update_leds(struct wskbd_internal *); void update_modifier(struct wskbd_internal *, u_int, int, int); int internal_command(struct wskbd_softc *, u_int *, keysym_t, keysym_t); int wskbd_translate(struct wskbd_internal *, u_int, int); int wskbd_enable(struct wskbd_softc *, int); void wskbd_debugger(struct wskbd_softc *); #if NWSDISPLAY > 0 void change_displayparam(struct wskbd_softc *, int, int, int); #endif int wskbd_do_ioctl_sc(struct wskbd_softc *, u_long, caddr_t, int, struct proc *, int); void wskbd_deliver_event(struct wskbd_softc *sc, u_int type, int value); #if NWSMUX > 0 int wskbd_mux_open(struct wsevsrc *, struct wseventvar *); int wskbd_mux_close(struct wsevsrc *); #else #define wskbd_mux_open NULL #define wskbd_mux_close NULL #endif int wskbd_do_open(struct wskbd_softc *, struct wseventvar *); int wskbd_do_ioctl(struct device *, u_long, caddr_t, int, struct proc *); void wskbd_set_keymap(struct wskbd_softc *, struct wscons_keymap *, int); int (*wskbd_get_backlight)(struct wskbd_backlight *); int (*wskbd_set_backlight)(struct wskbd_backlight *); void wskbd_kbd_backlight_task(void *); #if NWSDISPLAY > 0 void wskbd_brightness_task(void *); #endif struct cfdriver wskbd_cd = { NULL, "wskbd", DV_TTY }; const struct cfattach wskbd_ca = { sizeof (struct wskbd_softc), wskbd_match, wskbd_attach, wskbd_detach, wskbd_activate }; #if defined(__i386__) || defined(__amd64__) extern int kbd_reset; #endif #ifndef WSKBD_DEFAULT_BELL_PITCH #define WSKBD_DEFAULT_BELL_PITCH 400 /* 400Hz */ #endif #ifndef WSKBD_DEFAULT_BELL_PERIOD #define WSKBD_DEFAULT_BELL_PERIOD 100 /* 100ms */ #endif #ifndef WSKBD_DEFAULT_BELL_VOLUME #define WSKBD_DEFAULT_BELL_VOLUME 50 /* 50% volume */ #endif struct wskbd_bell_data wskbd_default_bell_data = { WSKBD_BELL_DOALL, WSKBD_DEFAULT_BELL_PITCH, WSKBD_DEFAULT_BELL_PERIOD, WSKBD_DEFAULT_BELL_VOLUME, }; #ifndef WSKBD_DEFAULT_KEYREPEAT_DEL1 #define WSKBD_DEFAULT_KEYREPEAT_DEL1 400 /* 400ms to start repeating */ #endif #ifndef WSKBD_DEFAULT_KEYREPEAT_DELN #define WSKBD_DEFAULT_KEYREPEAT_DELN 100 /* 100ms to between repeats */ #endif struct wskbd_keyrepeat_data wskbd_default_keyrepeat_data = { WSKBD_KEYREPEAT_DOALL, WSKBD_DEFAULT_KEYREPEAT_DEL1, WSKBD_DEFAULT_KEYREPEAT_DELN, }; #if NWSMUX > 0 || NWSDISPLAY > 0 struct wssrcops wskbd_srcops = { .type = WSMUX_KBD, .dopen = wskbd_mux_open, .dclose = wskbd_mux_close, .dioctl = wskbd_do_ioctl, .ddispioctl = wskbd_displayioctl, #if NWSDISPLAY > 0 .dsetdisplay = wskbd_set_display, #else .dsetdisplay = NULL, #endif }; #endif #if NWSDISPLAY > 0 void wskbd_repeat(void *v); #endif static int wskbd_console_initted; static struct wskbd_softc *wskbd_console_device; static struct wskbd_internal wskbd_console_data; void wskbd_update_layout(struct wskbd_internal *, kbd_t); #if NAUDIO > 0 extern int wskbd_set_mixervolume_dev(void *, long, long); #endif void wskbd_update_layout(struct wskbd_internal *id, kbd_t enc) { if (enc & KB_METAESC) id->t_flags |= WSKFL_METAESC; else id->t_flags &= ~WSKFL_METAESC; id->t_keymap.layout = enc; } /* * Print function (for parent devices). */ int wskbddevprint(void *aux, const char *pnp) { #if 0 struct wskbddev_attach_args *ap = aux; #endif if (pnp) printf("wskbd at %s", pnp); #if 0 printf(" console %d", ap->console); #endif return (UNCONF); } int wskbd_match(struct device *parent, void *match, void *aux) { struct cfdata *cf = match; struct wskbddev_attach_args *ap = aux; if (cf->wskbddevcf_console != WSKBDDEVCF_CONSOLE_UNK) { /* * If console-ness of device specified, either match * exactly (at high priority), or fail. */ if (cf->wskbddevcf_console != 0 && ap->console != 0) return (10); else return (0); } /* If console-ness unspecified, it wins. */ return (1); } void wskbd_attach(struct device *parent, struct device *self, void *aux) { struct wskbd_softc *sc = (struct wskbd_softc *)self; struct wskbddev_attach_args *ap = aux; kbd_t layout; #if NWSMUX > 0 struct wsmux_softc *wsmux_sc = NULL; int mux, error; #endif sc->sc_isconsole = ap->console; #if NWSMUX > 0 || NWSDISPLAY > 0 sc->sc_base.me_ops = &wskbd_srcops; #endif #if NWSMUX > 0 mux = sc->sc_base.me_dv.dv_cfdata->wskbddevcf_mux; if (mux >= 0) wsmux_sc = wsmux_getmux(mux); #endif /* NWSMUX > 0 */ if (ap->console) { sc->id = &wskbd_console_data; } else { sc->id = malloc(sizeof(struct wskbd_internal), M_DEVBUF, M_WAITOK | M_ZERO); bcopy(ap->keymap, &sc->id->t_keymap, sizeof(sc->id->t_keymap)); } task_set(&sc->sc_kbd_backlight_task, wskbd_kbd_backlight_task, sc); #if NWSDISPLAY > 0 timeout_set(&sc->sc_repeat_ch, wskbd_repeat, sc); task_set(&sc->sc_brightness_task, wskbd_brightness_task, sc); #endif #if NAUDIO > 0 sc->sc_audiocookie = ap->audiocookie; #endif sc->id->t_sc = sc; sc->sc_accessops = ap->accessops; sc->sc_accesscookie = ap->accesscookie; sc->sc_repeating = 0; sc->sc_translating = 1; sc->sc_ledstate = -1; /* force update */ /* * If this layout is the default choice of the driver (i.e. the * driver doesn't know better), pick the existing layout of the * current mux, if any. */ layout = sc->id->t_keymap.layout; #if NWSMUX > 0 if (layout & KB_DEFAULT) { if (wsmux_sc != NULL && wsmux_get_layout(wsmux_sc) != KB_NONE) layout = wsmux_get_layout(wsmux_sc); } #endif for (;;) { struct wscons_keymap *map; int maplen; if (wskbd_load_keymap(&sc->id->t_keymap, layout, &map, &maplen) == 0) { wskbd_set_keymap(sc, map, maplen); break; } #if NWSMUX > 0 if (layout == sc->id->t_keymap.layout) panic("cannot load keymap"); if (wsmux_sc != NULL && wsmux_get_layout(wsmux_sc) != KB_NONE) { printf("\n%s: cannot load keymap, " "falling back to default\n%s", sc->sc_base.me_dv.dv_xname, sc->sc_base.me_dv.dv_xname); layout = wsmux_get_layout(wsmux_sc); } else #endif panic("cannot load keymap"); } wskbd_update_layout(sc->id, layout); /* set default bell and key repeat data */ sc->sc_bell_data = wskbd_default_bell_data; sc->sc_keyrepeat_data = wskbd_default_keyrepeat_data; if (ap->console) { KASSERT(wskbd_console_initted); KASSERT(wskbd_console_device == NULL); wskbd_console_device = sc; printf(": console keyboard"); #if NWSDISPLAY > 0 wsdisplay_set_console_kbd(&sc->sc_base); /* sets sc_displaydv */ if (sc->sc_displaydv != NULL) printf(", using %s", sc->sc_displaydv->dv_xname); #endif } #if NWSMUX > 0 /* Ignore mux for console; it always goes to the console mux. */ if (wsmux_sc != NULL && ap->console == 0) { printf(" mux %d\n", mux); error = wsmux_attach_sc(wsmux_sc, &sc->sc_base); if (error) printf("%s: attach error=%d\n", sc->sc_base.me_dv.dv_xname, error); /* * Try and set this encoding as the mux default if it * hasn't any yet, and if this is not a driver default * layout (i.e. parent driver pretends to know better). * Note that wsmux_set_layout() rejects layouts with * KB_DEFAULT set. */ if (wsmux_get_layout(wsmux_sc) == KB_NONE) wsmux_set_layout(wsmux_sc, layout); } else #endif printf("\n"); #if NWSDISPLAY > 0 && NWSMUX == 0 if (ap->console == 0) { /* * In the non-wsmux world, always connect wskbd0 and wsdisplay0 * together. */ extern struct cfdriver wsdisplay_cd; if (wsdisplay_cd.cd_ndevs != 0 && self->dv_unit == 0) { if (wskbd_set_display(self, wsdisplay_cd.cd_devs[0]) == 0) wsdisplay_set_kbd(wsdisplay_cd.cd_devs[0], (struct wsevsrc *)sc); } } #endif } void wskbd_cnattach(const struct wskbd_consops *consops, void *conscookie, const struct wskbd_mapdata *mapdata) { KASSERT(!wskbd_console_initted); bcopy(mapdata, &wskbd_console_data.t_keymap, sizeof(*mapdata)); wskbd_update_layout(&wskbd_console_data, mapdata->layout); wskbd_console_data.t_consops = consops; wskbd_console_data.t_consaccesscookie = conscookie; #if NWSDISPLAY > 0 wsdisplay_set_cons_kbd(wskbd_cngetc, wskbd_cnpollc, wskbd_cnbell); #endif wskbd_console_initted = 1; } void wskbd_cndetach(void) { KASSERT(wskbd_console_initted); wskbd_console_data.t_keymap.keydesc = NULL; wskbd_console_data.t_keymap.layout = KB_NONE; wskbd_console_data.t_consops = NULL; wskbd_console_data.t_consaccesscookie = NULL; #if NWSDISPLAY > 0 wsdisplay_unset_cons_kbd(); #endif wskbd_console_device = NULL; wskbd_console_initted = 0; } #if NWSDISPLAY > 0 void wskbd_repeat(void *v) { struct wskbd_softc *sc = (struct wskbd_softc *)v; int s = spltty(); if (sc->sc_repeating == 0) { /* * race condition: a "key up" event came in when wskbd_repeat() * was already called but not yet spltty()'d */ splx(s); return; } if (sc->sc_translating) { /* deliver keys */ if (sc->sc_displaydv != NULL) wsdisplay_kbdinput(sc->sc_displaydv, sc->id->t_keymap.layout, sc->id->t_symbols, sc->sc_repeating); } else { /* queue event */ wskbd_deliver_event(sc, sc->sc_repeat_type, sc->sc_repeat_value); } if (sc->sc_keyrepeat_data.delN != 0) timeout_add_msec(&sc->sc_repeat_ch, sc->sc_keyrepeat_data.delN); splx(s); } #endif int wskbd_activate(struct device *self, int act) { struct wskbd_softc *sc = (struct wskbd_softc *)self; if (act == DVACT_DEACTIVATE) sc->sc_dying = 1; return (0); } /* * Detach a keyboard. To keep track of users of the softc we keep * a reference count that's incremented while inside, e.g., read. * If the keyboard is active and the reference count is > 0 (0 is the * normal state) we post an event and then wait for the process * that had the reference to wake us up again. Then we blow away the * vnode and return (which will deallocate the softc). */ int wskbd_detach(struct device *self, int flags) { struct wskbd_softc *sc = (struct wskbd_softc *)self; struct wseventvar *evar; int maj, mn; int s; #if NWSMUX > 0 /* Tell parent mux we're leaving. */ if (sc->sc_base.me_parent != NULL) wsmux_detach_sc(&sc->sc_base); #endif #if NWSDISPLAY > 0 if (sc->sc_repeating) { sc->sc_repeating = 0; timeout_del(&sc->sc_repeat_ch); } #endif if (sc->sc_isconsole) { KASSERT(wskbd_console_device == sc); wskbd_cndetach(); } evar = sc->sc_base.me_evp; if (evar != NULL) { s = spltty(); if (--sc->sc_refcnt >= 0) { /* Wake everyone by generating a dummy event. */ if (++evar->ws_put >= WSEVENT_QSIZE) evar->ws_put = 0; WSEVENT_WAKEUP(evar); /* Wait for processes to go away. */ if (tsleep_nsec(sc, PZERO, "wskdet", SEC_TO_NSEC(60))) printf("wskbd_detach: %s didn't detach\n", sc->sc_base.me_dv.dv_xname); } splx(s); } free(sc->sc_map, M_DEVBUF, sc->sc_maplen * sizeof(struct wscons_keymap)); /* locate the major number */ for (maj = 0; maj < nchrdev; maj++) if (cdevsw[maj].d_open == wskbdopen) break; /* Nuke the vnodes for any open instances. */ mn = self->dv_unit; vdevgone(maj, mn, mn, VCHR); return (0); } void wskbd_input(struct device *dev, u_int type, int value) { struct wskbd_softc *sc = (struct wskbd_softc *)dev; #if NWSDISPLAY > 0 int num; #endif #if NWSDISPLAY > 0 if (sc->sc_repeating) { sc->sc_repeating = 0; timeout_del(&sc->sc_repeat_ch); } /* * If /dev/wskbdN is not connected in event mode translate and * send upstream. */ if (sc->sc_translating) { #ifdef HAVE_BURNER_SUPPORT if (type == WSCONS_EVENT_KEY_DOWN && sc->sc_displaydv != NULL) wsdisplay_burn(sc->sc_displaydv, WSDISPLAY_BURN_KBD); #endif num = wskbd_translate(sc->id, type, value); if (num > 0) { if (sc->sc_displaydv != NULL) { #ifdef HAVE_SCROLLBACK_SUPPORT /* XXX - Shift_R+PGUP(release) emits PrtSc */ if (sc->id->t_symbols[0] != KS_Print_Screen) { wsscrollback(sc->sc_displaydv, WSDISPLAY_SCROLL_RESET); } #endif wsdisplay_kbdinput(sc->sc_displaydv, sc->id->t_keymap.layout, sc->id->t_symbols, num); } if (sc->sc_keyrepeat_data.del1 != 0) { sc->sc_repeating = num; timeout_add_msec(&sc->sc_repeat_ch, sc->sc_keyrepeat_data.del1); } } return; } #endif wskbd_deliver_event(sc, type, value); #if NWSDISPLAY > 0 /* Repeat key presses if enabled. */ if (type == WSCONS_EVENT_KEY_DOWN && sc->sc_keyrepeat_data.del1 != 0) { sc->sc_repeat_type = type; sc->sc_repeat_value = value; sc->sc_repeating = 1; timeout_add_msec(&sc->sc_repeat_ch, sc->sc_keyrepeat_data.del1); } #endif } /* * Keyboard is generating events. Turn this keystroke into an * event and put it in the queue. If the queue is full, the * keystroke is lost (sorry!). */ void wskbd_deliver_event(struct wskbd_softc *sc, u_int type, int value) { struct wseventvar *evar; struct wscons_event *ev; int put; evar = sc->sc_base.me_evp; if (evar == NULL) { DPRINTF(("%s: not open\n", __func__)); return; } #ifdef DIAGNOSTIC if (evar->ws_q == NULL) { printf("wskbd_input: evar->q=NULL\n"); return; } #endif put = evar->ws_put; ev = &evar->ws_q[put]; put = (put + 1) % WSEVENT_QSIZE; if (put == evar->ws_get) { log(LOG_WARNING, "%s: event queue overflow\n", sc->sc_base.me_dv.dv_xname); return; } ev->type = type; ev->value = value; nanotime(&ev->time); evar->ws_put = put; WSEVENT_WAKEUP(evar); } #ifdef WSDISPLAY_COMPAT_RAWKBD void wskbd_rawinput(struct device *dev, u_char *buf, int len) { #if NWSDISPLAY > 0 struct wskbd_softc *sc = (struct wskbd_softc *)dev; if (sc->sc_displaydv != NULL) wsdisplay_rawkbdinput(sc->sc_displaydv, buf, len); #endif } #endif /* WSDISPLAY_COMPAT_RAWKBD */ int wskbd_enable(struct wskbd_softc *sc, int on) { int error; #if NWSDISPLAY > 0 if (sc->sc_displaydv != NULL) return (0); /* Always cancel auto repeat when fiddling with the kbd. */ if (sc->sc_repeating) { sc->sc_repeating = 0; timeout_del(&sc->sc_repeat_ch); } #endif error = (*sc->sc_accessops->enable)(sc->sc_accesscookie, on); DPRINTF(("%s: sc=%p on=%d res=%d\n", __func__, sc, on, error)); return (error); } #if NWSMUX > 0 int wskbd_mux_open(struct wsevsrc *me, struct wseventvar *evp) { struct wskbd_softc *sc = (struct wskbd_softc *)me; if (sc->sc_dying) return (EIO); return (wskbd_do_open(sc, evp)); } #endif int wskbdopen(dev_t dev, int flags, int mode, struct proc *p) { struct wskbd_softc *sc; struct wseventvar *evar; int unit, error; unit = minor(dev); if (unit >= wskbd_cd.cd_ndevs || /* make sure it was attached */ (sc = wskbd_cd.cd_devs[unit]) == NULL) return (ENXIO); #if NWSMUX > 0 DPRINTF(("%s: %s mux=%p\n", __func__, sc->sc_base.me_dv.dv_xname, sc->sc_base.me_parent)); #endif if (sc->sc_dying) return (EIO); if ((flags & (FREAD | FWRITE)) == FWRITE) { /* Not opening for read, only ioctl is available. */ return (0); } #if NWSMUX > 0 if (sc->sc_base.me_parent != NULL) { /* Grab the keyboard out of the greedy hands of the mux. */ DPRINTF(("%s: detach\n", __func__)); wsmux_detach_sc(&sc->sc_base); } #endif if (sc->sc_base.me_evp != NULL) return (EBUSY); evar = &sc->sc_base.me_evar; if (wsevent_init(evar)) return (EBUSY); error = wskbd_do_open(sc, evar); if (error) wsevent_fini(evar); return (error); } int wskbd_do_open(struct wskbd_softc *sc, struct wseventvar *evp) { int error; /* The device could already be attached to a mux. */ if (sc->sc_base.me_evp != NULL) return (EBUSY); sc->sc_base.me_evp = evp; sc->sc_translating = 0; error = wskbd_enable(sc, 1); if (error) sc->sc_base.me_evp = NULL; return (error); } int wskbdclose(dev_t dev, int flags, int mode, struct proc *p) { struct wskbd_softc *sc = (struct wskbd_softc *)wskbd_cd.cd_devs[minor(dev)]; struct wseventvar *evar = sc->sc_base.me_evp; if ((flags & (FREAD | FWRITE)) == FWRITE) { /* not open for read */ return (0); } sc->sc_base.me_evp = NULL; sc->sc_translating = 1; (void)wskbd_enable(sc, 0); wsevent_fini(evar); #if NWSMUX > 0 if (sc->sc_base.me_parent == NULL) { int mux, error; DPRINTF(("%s: attach\n", __func__)); mux = sc->sc_base.me_dv.dv_cfdata->wskbddevcf_mux; if (mux >= 0) { error = wsmux_attach_sc(wsmux_getmux(mux), &sc->sc_base); if (error) printf("%s: can't attach mux (error=%d)\n", sc->sc_base.me_dv.dv_xname, error); } } #endif return (0); } #if NWSMUX > 0 int wskbd_mux_close(struct wsevsrc *me) { struct wskbd_softc *sc = (struct wskbd_softc *)me; (void)wskbd_enable(sc, 0); sc->sc_translating = 1; sc->sc_base.me_evp = NULL; return (0); } #endif int wskbdread(dev_t dev, struct uio *uio, int flags) { struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)]; int error; if (sc->sc_dying) return (EIO); #ifdef DIAGNOSTIC if (sc->sc_base.me_evp == NULL) { printf("wskbdread: evp == NULL\n"); return (EINVAL); } #endif sc->sc_refcnt++; error = wsevent_read(&sc->sc_base.me_evar, uio, flags); if (--sc->sc_refcnt < 0) { wakeup(sc); error = EIO; } return (error); } int wskbdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)]; int error; sc->sc_refcnt++; error = wskbd_do_ioctl_sc(sc, cmd, data, flag, p, 0); if (--sc->sc_refcnt < 0) wakeup(sc); return (error); } /* A wrapper around the ioctl() workhorse to make reference counting easy. */ int wskbd_do_ioctl(struct device *dv, u_long cmd, caddr_t data, int flag, struct proc *p) { struct wskbd_softc *sc = (struct wskbd_softc *)dv; int error; sc->sc_refcnt++; error = wskbd_do_ioctl_sc(sc, cmd, data, flag, p, 1); if (--sc->sc_refcnt < 0) wakeup(sc); return (error); } int wskbd_do_ioctl_sc(struct wskbd_softc *sc, u_long cmd, caddr_t data, int flag, struct proc *p, int evsrc) { struct wseventvar *evar; int error; /* * Try the generic ioctls that the wskbd interface supports. */ switch (cmd) { case FIONBIO: /* we will remove this someday (soon???) */ return (0); case FIOASYNC: if (sc->sc_base.me_evp == NULL) return (EINVAL); sc->sc_base.me_evp->ws_async = *(int *)data != 0; return (0); case FIOGETOWN: case TIOCGPGRP: evar = sc->sc_base.me_evp; if (evar == NULL) return (EINVAL); sigio_getown(&evar->ws_sigio, cmd, data); return (0); case FIOSETOWN: case TIOCSPGRP: evar = sc->sc_base.me_evp; if (evar == NULL) return (EINVAL); return (sigio_setown(&evar->ws_sigio, cmd, data)); } /* * Try the keyboard driver for WSKBDIO ioctls. It returns -1 * if it didn't recognize the request. */ error = wskbd_displayioctl_sc(sc, cmd, data, flag, p, evsrc); return (error != -1 ? error : ENOTTY); } /* * WSKBDIO ioctls, handled in both emulation mode and in ``raw'' mode. * Some of these have no real effect in raw mode, however. */ int wskbd_displayioctl(struct device *dv, u_long cmd, caddr_t data, int flag, struct proc *p) { struct wskbd_softc *sc = (struct wskbd_softc *)dv; return (wskbd_displayioctl_sc(sc, cmd, data, flag, p, 1)); } int wskbd_displayioctl_sc(struct wskbd_softc *sc, u_long cmd, caddr_t data, int flag, struct proc *p, int evsrc) { struct wskbd_bell_data *ubdp, *kbdp; struct wskbd_keyrepeat_data *ukdp, *kkdp; struct wskbd_map_data *umdp; struct wskbd_encoding_data *uedp; kbd_t enc; void *buf; int len, error; int count, i; switch (cmd) { case WSKBDIO_BELL: case WSKBDIO_COMPLEXBELL: case WSKBDIO_SETBELL: case WSKBDIO_SETKEYREPEAT: case WSKBDIO_SETDEFAULTKEYREPEAT: case WSKBDIO_SETMAP: case WSKBDIO_SETENCODING: case WSKBDIO_SETBACKLIGHT: if ((flag & FWRITE) == 0) return (EACCES); } switch (cmd) { #define SETBELL(dstp, srcp, dfltp) \ do { \ (dstp)->pitch = ((srcp)->which & WSKBD_BELL_DOPITCH) ? \ (srcp)->pitch : (dfltp)->pitch; \ (dstp)->period = ((srcp)->which & WSKBD_BELL_DOPERIOD) ? \ (srcp)->period : (dfltp)->period; \ (dstp)->volume = ((srcp)->which & WSKBD_BELL_DOVOLUME) ? \ (srcp)->volume : (dfltp)->volume; \ (dstp)->which = WSKBD_BELL_DOALL; \ } while (0) case WSKBDIO_BELL: return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie, WSKBDIO_COMPLEXBELL, (caddr_t)&sc->sc_bell_data, flag, p)); case WSKBDIO_COMPLEXBELL: ubdp = (struct wskbd_bell_data *)data; SETBELL(ubdp, ubdp, &sc->sc_bell_data); return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie, WSKBDIO_COMPLEXBELL, (caddr_t)ubdp, flag, p)); case WSKBDIO_SETBELL: kbdp = &sc->sc_bell_data; setbell: ubdp = (struct wskbd_bell_data *)data; SETBELL(kbdp, ubdp, kbdp); return (0); case WSKBDIO_GETBELL: kbdp = &sc->sc_bell_data; getbell: ubdp = (struct wskbd_bell_data *)data; SETBELL(ubdp, kbdp, kbdp); return (0); case WSKBDIO_SETDEFAULTBELL: if ((error = suser(p)) != 0) return (error); kbdp = &wskbd_default_bell_data; goto setbell; case WSKBDIO_GETDEFAULTBELL: kbdp = &wskbd_default_bell_data; goto getbell; #undef SETBELL #define SETKEYREPEAT(dstp, srcp, dfltp) \ do { \ (dstp)->del1 = ((srcp)->which & WSKBD_KEYREPEAT_DODEL1) ? \ (srcp)->del1 : (dfltp)->del1; \ (dstp)->delN = ((srcp)->which & WSKBD_KEYREPEAT_DODELN) ? \ (srcp)->delN : (dfltp)->delN; \ (dstp)->which = WSKBD_KEYREPEAT_DOALL; \ } while (0) case WSKBDIO_SETKEYREPEAT: kkdp = &sc->sc_keyrepeat_data; setkeyrepeat: ukdp = (struct wskbd_keyrepeat_data *)data; SETKEYREPEAT(kkdp, ukdp, kkdp); return (0); case WSKBDIO_GETKEYREPEAT: kkdp = &sc->sc_keyrepeat_data; getkeyrepeat: ukdp = (struct wskbd_keyrepeat_data *)data; SETKEYREPEAT(ukdp, kkdp, kkdp); return (0); case WSKBDIO_SETDEFAULTKEYREPEAT: if ((error = suser(p)) != 0) return (error); kkdp = &wskbd_default_keyrepeat_data; goto setkeyrepeat; case WSKBDIO_GETDEFAULTKEYREPEAT: kkdp = &wskbd_default_keyrepeat_data; goto getkeyrepeat; #undef SETKEYREPEAT case WSKBDIO_SETMAP: umdp = (struct wskbd_map_data *)data; if (umdp->maplen > WSKBDIO_MAXMAPLEN) return (EINVAL); buf = mallocarray(umdp->maplen, sizeof(struct wscons_keymap), M_TEMP, M_WAITOK); len = umdp->maplen * sizeof(struct wscons_keymap); error = copyin(umdp->map, buf, len); if (error == 0) { struct wscons_keymap *map; map = wskbd_init_keymap(umdp->maplen); memcpy(map, buf, len); wskbd_set_keymap(sc, map, umdp->maplen); /* drop the variant bits handled by the map */ enc = KB_USER | (KB_VARIANT(sc->id->t_keymap.layout) & KB_HANDLEDBYWSKBD); wskbd_update_layout(sc->id, enc); } free(buf, M_TEMP, len); return(error); case WSKBDIO_GETMAP: umdp = (struct wskbd_map_data *)data; if (umdp->maplen > sc->sc_maplen) umdp->maplen = sc->sc_maplen; error = copyout(sc->sc_map, umdp->map, umdp->maplen*sizeof(struct wscons_keymap)); return(error); case WSKBDIO_GETENCODING: /* Do not advertise encoding to the parent mux. */ if (evsrc && (sc->id->t_keymap.layout & KB_NOENCODING)) return (ENOTTY); *((kbd_t *)data) = sc->id->t_keymap.layout & ~KB_DEFAULT; return(0); case WSKBDIO_SETENCODING: enc = *((kbd_t *)data); if (KB_ENCODING(enc) == KB_USER) { /* user map must already be loaded */ if (KB_ENCODING(sc->id->t_keymap.layout) != KB_USER) return (EINVAL); /* map variants make no sense */ if (KB_VARIANT(enc) & ~KB_HANDLEDBYWSKBD) return (EINVAL); } else if (sc->id->t_keymap.layout & KB_NOENCODING) { return (0); } else { struct wscons_keymap *map; int maplen; error = wskbd_load_keymap(&sc->id->t_keymap, enc, &map, &maplen); if (error) return (error); wskbd_set_keymap(sc, map, maplen); } wskbd_update_layout(sc->id, enc); #if NWSMUX > 0 /* Update mux default layout */ if (sc->sc_base.me_parent != NULL) wsmux_set_layout(sc->sc_base.me_parent, enc); #endif return (0); case WSKBDIO_GETENCODINGS: uedp = (struct wskbd_encoding_data *)data; count = 0; if (sc->id->t_keymap.keydesc != NULL) { while (sc->id->t_keymap.keydesc[count].name) count++; } if (uedp->nencodings > count) uedp->nencodings = count; for (i = 0; i < uedp->nencodings; i++) { error = copyout(&sc->id->t_keymap.keydesc[i].name, &uedp->encodings[i], sizeof(kbd_t)); if (error) return (error); } return (0); case WSKBDIO_GETBACKLIGHT: if (wskbd_get_backlight != NULL) return (*wskbd_get_backlight)((struct wskbd_backlight *)data); break; case WSKBDIO_SETBACKLIGHT: if (wskbd_set_backlight != NULL) return (*wskbd_set_backlight)((struct wskbd_backlight *)data); break; } /* * Try the keyboard driver for WSKBDIO ioctls. It returns -1 * if it didn't recognize the request, and in turn we return * -1 if we didn't recognize the request. */ /* printf("kbdaccess\n"); */ error = (*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd, data, flag, p); #ifdef WSDISPLAY_COMPAT_RAWKBD if (!error && cmd == WSKBDIO_SETMODE && *(int *)data == WSKBD_RAW) { int s = spltty(); sc->id->t_modifiers &= ~(MOD_SHIFT_L | MOD_SHIFT_R | MOD_CONTROL_L | MOD_CONTROL_R | MOD_META_L | MOD_META_R | MOD_COMMAND | MOD_COMMAND1 | MOD_COMMAND2); #if NWSDISPLAY > 0 if (sc->sc_repeating) { sc->sc_repeating = 0; timeout_del(&sc->sc_repeat_ch); } #endif splx(s); } #endif return (error); } int wskbdkqfilter(dev_t dev, struct knote *kn) { struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)]; if (sc->sc_base.me_evp == NULL) return (ENXIO); return (wsevent_kqfilter(sc->sc_base.me_evp, kn)); } #if NWSDISPLAY > 0 int wskbd_pickfree(void) { int i; struct wskbd_softc *sc; for (i = 0; i < wskbd_cd.cd_ndevs; i++) { if ((sc = wskbd_cd.cd_devs[i]) == NULL) continue; if (sc->sc_displaydv == NULL) return (i); } return (-1); } struct wsevsrc * wskbd_set_console_display(struct device *displaydv, struct wsevsrc *me) { struct wskbd_softc *sc = wskbd_console_device; if (sc == NULL) return (NULL); sc->sc_displaydv = displaydv; #if NWSMUX > 0 (void)wsmux_attach_sc((struct wsmux_softc *)me, &sc->sc_base); #endif return (&sc->sc_base); } int wskbd_set_display(struct device *dv, struct device *displaydv) { struct wskbd_softc *sc = (struct wskbd_softc *)dv; struct device *odisplaydv; int error; DPRINTF(("%s: %s odisp=%p disp=%p cons=%d\n", __func__, dv->dv_xname, sc->sc_displaydv, displaydv, sc->sc_isconsole)); if (sc->sc_isconsole) return (EBUSY); if (displaydv != NULL) { if (sc->sc_displaydv != NULL) return (EBUSY); } else { if (sc->sc_displaydv == NULL) return (ENXIO); } odisplaydv = sc->sc_displaydv; sc->sc_displaydv = NULL; error = wskbd_enable(sc, displaydv != NULL); sc->sc_displaydv = displaydv; if (error) { sc->sc_displaydv = odisplaydv; return (error); } if (displaydv) printf("%s: connecting to %s\n", sc->sc_base.me_dv.dv_xname, displaydv->dv_xname); else printf("%s: disconnecting from %s\n", sc->sc_base.me_dv.dv_xname, odisplaydv->dv_xname); return (0); } #endif /* NWSDISPLAY > 0 */ #if NWSMUX > 0 int wskbd_add_mux(int unit, struct wsmux_softc *muxsc) { struct wskbd_softc *sc; if (unit < 0 || unit >= wskbd_cd.cd_ndevs || (sc = wskbd_cd.cd_devs[unit]) == NULL) return (ENXIO); if (sc->sc_base.me_parent != NULL || sc->sc_base.me_evp != NULL) return (EBUSY); return (wsmux_attach_sc(muxsc, &sc->sc_base)); } #endif /* * Console interface. */ int wskbd_cngetc(dev_t dev) { static int num = 0; static int pos; u_int type; int data; keysym_t ks; if (!wskbd_console_initted) return 0; if (wskbd_console_device != NULL && !wskbd_console_device->sc_translating) return 0; for(;;) { if (num-- > 0) { ks = wskbd_console_data.t_symbols[pos++]; if (KS_GROUP(ks) == KS_GROUP_Ascii) return (KS_VALUE(ks)); } else { (*wskbd_console_data.t_consops->getc) (wskbd_console_data.t_consaccesscookie, &type, &data); num = wskbd_translate(&wskbd_console_data, type, data); pos = 0; } } } void wskbd_cnpollc(dev_t dev, int poll) { if (!wskbd_console_initted) return; if (wskbd_console_device != NULL && !wskbd_console_device->sc_translating) return; (*wskbd_console_data.t_consops->pollc) (wskbd_console_data.t_consaccesscookie, poll); } void wskbd_cnbell(dev_t dev, u_int pitch, u_int period, u_int volume) { if (!wskbd_console_initted) return; if (wskbd_console_data.t_consops->bell != NULL) (*wskbd_console_data.t_consops->bell) (wskbd_console_data.t_consaccesscookie, pitch, period, volume); } void update_leds(struct wskbd_internal *id) { int new_state; new_state = 0; if (id->t_modifiers & (MOD_SHIFTLOCK | MOD_CAPSLOCK)) new_state |= WSKBD_LED_CAPS; if (id->t_modifiers & MOD_NUMLOCK) new_state |= WSKBD_LED_NUM; if (id->t_modifiers & MOD_COMPOSE) new_state |= WSKBD_LED_COMPOSE; if (id->t_modifiers & MOD_HOLDSCREEN) new_state |= WSKBD_LED_SCROLL; if (id->t_sc && new_state != id->t_sc->sc_ledstate) { (*id->t_sc->sc_accessops->set_leds) (id->t_sc->sc_accesscookie, new_state); id->t_sc->sc_ledstate = new_state; } } void update_modifier(struct wskbd_internal *id, u_int type, int toggle, int mask) { if (toggle) { if (type == WSCONS_EVENT_KEY_DOWN) id->t_modifiers ^= mask; } else { if (type == WSCONS_EVENT_KEY_DOWN) id->t_modifiers |= mask; else id->t_modifiers &= ~mask; } if (mask & MOD_ANYLED) update_leds(id); } #if NWSDISPLAY > 0 void change_displayparam(struct wskbd_softc *sc, int param, int updown, int wraparound) { int res; struct wsdisplay_param dp; dp.param = param; res = wsdisplay_param(sc->sc_displaydv, WSDISPLAYIO_GETPARAM, &dp); if (res == EINVAL) return; /* no such parameter */ dp.curval += updown; if (dp.max < dp.curval) dp.curval = wraparound ? dp.min : dp.max; else if (dp.curval < dp.min) dp.curval = wraparound ? dp.max : dp.min; wsdisplay_param(sc->sc_displaydv, WSDISPLAYIO_SETPARAM, &dp); } #endif int internal_command(struct wskbd_softc *sc, u_int *type, keysym_t ksym, keysym_t ksym2) { switch (ksym) { case KS_Cmd: update_modifier(sc->id, *type, 0, MOD_COMMAND); ksym = ksym2; break; case KS_Cmd1: update_modifier(sc->id, *type, 0, MOD_COMMAND1); break; case KS_Cmd2: update_modifier(sc->id, *type, 0, MOD_COMMAND2); break; } if (*type != WSCONS_EVENT_KEY_DOWN) return (0); #ifdef SUSPEND if (ksym == KS_Cmd_Sleep) { request_sleep(SLEEP_SUSPEND); return (1); } #endif #ifdef HAVE_SCROLLBACK_SUPPORT #if NWSDISPLAY > 0 switch (ksym) { case KS_Cmd_ScrollBack: if (MOD_ONESET(sc->id, MOD_ANYSHIFT)) { if (sc->sc_displaydv != NULL) wsscrollback(sc->sc_displaydv, WSDISPLAY_SCROLL_BACKWARD); return (1); } break; case KS_Cmd_ScrollFwd: if (MOD_ONESET(sc->id, MOD_ANYSHIFT)) { if (sc->sc_displaydv != NULL) wsscrollback(sc->sc_displaydv, WSDISPLAY_SCROLL_FORWARD); return (1); } break; } #endif #endif switch (ksym) { case KS_Cmd_KbdBacklightUp: atomic_store_int(&sc->sc_kbd_backlight_cmd, KBD_BACKLIGHT_UP); task_add(systq, &sc->sc_kbd_backlight_task); return (1); case KS_Cmd_KbdBacklightDown: atomic_store_int(&sc->sc_kbd_backlight_cmd, KBD_BACKLIGHT_DOWN); task_add(systq, &sc->sc_kbd_backlight_task); return (1); case KS_Cmd_KbdBacklightToggle: atomic_store_int(&sc->sc_kbd_backlight_cmd, KBD_BACKLIGHT_TOGGLE); task_add(systq, &sc->sc_kbd_backlight_task); return (1); } #if NWSDISPLAY > 0 switch(ksym) { case KS_Cmd_BrightnessUp: atomic_add_int(&sc->sc_brightness_steps, 1); task_add(systq, &sc->sc_brightness_task); return (1); case KS_Cmd_BrightnessDown: atomic_sub_int(&sc->sc_brightness_steps, 1); task_add(systq, &sc->sc_brightness_task); return (1); case KS_Cmd_BrightnessRotate: wsdisplay_brightness_cycle(sc->sc_displaydv); return (1); } #endif if (!MOD_ONESET(sc->id, MOD_COMMAND) && !MOD_ALLSET(sc->id, MOD_COMMAND1 | MOD_COMMAND2)) return (0); #ifdef DDB if (ksym == KS_Cmd_Debugger) { wskbd_debugger(sc); /* discard this key (ddb discarded command modifiers) */ *type = WSCONS_EVENT_KEY_UP; return (1); } #endif #if NWSDISPLAY > 0 if (sc->sc_displaydv == NULL) return (0); switch (ksym) { case KS_Cmd_Screen0: case KS_Cmd_Screen1: case KS_Cmd_Screen2: case KS_Cmd_Screen3: case KS_Cmd_Screen4: case KS_Cmd_Screen5: case KS_Cmd_Screen6: case KS_Cmd_Screen7: case KS_Cmd_Screen8: case KS_Cmd_Screen9: case KS_Cmd_Screen10: case KS_Cmd_Screen11: wsdisplay_switch(sc->sc_displaydv, ksym - KS_Cmd_Screen0, 0); return (1); case KS_Cmd_ResetEmul: wsdisplay_reset(sc->sc_displaydv, WSDISPLAY_RESETEMUL); return (1); case KS_Cmd_ResetClose: wsdisplay_reset(sc->sc_displaydv, WSDISPLAY_RESETCLOSE); return (1); #if defined(__i386__) || defined(__amd64__) case KS_Cmd_KbdReset: switch (kbd_reset) { #ifdef DDB case 2: wskbd_debugger(sc); /* discard this key (ddb discarded command modifiers) */ *type = WSCONS_EVENT_KEY_UP; break; #endif case 1: kbd_reset = 0; prsignal(initprocess, SIGUSR1); break; default: break; } return (1); #endif case KS_Cmd_BacklightOn: case KS_Cmd_BacklightOff: case KS_Cmd_BacklightToggle: change_displayparam(sc, WSDISPLAYIO_PARAM_BACKLIGHT, ksym == KS_Cmd_BacklightOff ? -1 : 1, ksym == KS_Cmd_BacklightToggle ? 1 : 0); return (1); case KS_Cmd_ContrastUp: case KS_Cmd_ContrastDown: case KS_Cmd_ContrastRotate: change_displayparam(sc, WSDISPLAYIO_PARAM_CONTRAST, ksym == KS_Cmd_ContrastDown ? -1 : 1, ksym == KS_Cmd_ContrastRotate ? 1 : 0); return (1); } #endif return (0); } int wskbd_translate(struct wskbd_internal *id, u_int type, int value) { struct wskbd_softc *sc = id->t_sc; keysym_t ksym, res, *group; struct wscons_keymap kpbuf, *kp; int gindex, iscommand = 0; if (type == WSCONS_EVENT_ALL_KEYS_UP) { #if NWSDISPLAY > 0 if (sc != NULL && sc->sc_repeating) { sc->sc_repeating = 0; timeout_del(&sc->sc_repeat_ch); } #endif id->t_modifiers &= ~(MOD_SHIFT_L | MOD_SHIFT_R | MOD_CONTROL_L | MOD_CONTROL_R | MOD_META_L | MOD_META_R | MOD_MODESHIFT | MOD_MODELOCK | MOD_COMMAND | MOD_COMMAND1 | MOD_COMMAND2); return (0); } if (sc != NULL) { if (value < 0 || value >= sc->sc_maplen) { #ifdef DEBUG printf("wskbd_translate: keycode %d out of range\n", value); #endif return (0); } kp = sc->sc_map + value; } else { kp = &kpbuf; wskbd_get_mapentry(&id->t_keymap, value, kp); } /* if this key has a command, process it first */ if (sc != NULL && kp->command != KS_voidSymbol) iscommand = internal_command(sc, &type, kp->command, kp->group1[0]); /* Now update modifiers */ switch (kp->group1[0]) { case KS_Shift_L: update_modifier(id, type, 0, MOD_SHIFT_L); break; case KS_Shift_R: update_modifier(id, type, 0, MOD_SHIFT_R); break; case KS_Shift_Lock: update_modifier(id, type, 1, MOD_SHIFTLOCK); break; case KS_Caps_Lock: update_modifier(id, type, 1, MOD_CAPSLOCK); break; case KS_Control_L: update_modifier(id, type, 0, MOD_CONTROL_L); break; case KS_Control_R: update_modifier(id, type, 0, MOD_CONTROL_R); break; case KS_Alt_L: update_modifier(id, type, 0, MOD_META_L); break; case KS_Alt_R: update_modifier(id, type, 0, MOD_META_R); break; case KS_Mode_switch: update_modifier(id, type, 0, MOD_MODESHIFT); break; case KS_Mode_Lock: update_modifier(id, type, 1, MOD_MODELOCK); break; case KS_Num_Lock: update_modifier(id, type, 1, MOD_NUMLOCK); break; #if NWSDISPLAY > 0 case KS_Hold_Screen: if (sc != NULL) { update_modifier(id, type, 1, MOD_HOLDSCREEN); if (sc->sc_displaydv != NULL) wsdisplay_kbdholdscreen(sc->sc_displaydv, id->t_modifiers & MOD_HOLDSCREEN); } break; default: if (sc != NULL && sc->sc_repeating && ((type == WSCONS_EVENT_KEY_UP && value != sc->sc_repkey) || (type == WSCONS_EVENT_KEY_DOWN && value == sc->sc_repkey))) return (0); break; #endif } #if NWSDISPLAY > 0 if (sc != NULL) { if (sc->sc_repeating) { sc->sc_repeating = 0; timeout_del(&sc->sc_repeat_ch); } sc->sc_repkey = value; } #endif /* If this is a key release or we are in command mode, we are done */ if (type != WSCONS_EVENT_KEY_DOWN || iscommand) return (0); /* Get the keysym */ if (id->t_modifiers & (MOD_MODESHIFT|MOD_MODELOCK) && !MOD_ONESET(id, MOD_ANYCONTROL)) group = & kp->group2[0]; else group = & kp->group1[0]; if ((id->t_modifiers & MOD_NUMLOCK) && KS_GROUP(group[1]) == KS_GROUP_Keypad) { gindex = !MOD_ONESET(id, MOD_ANYSHIFT); ksym = group[gindex]; } else { /* CAPS alone should only affect letter keys */ if ((id->t_modifiers & (MOD_CAPSLOCK | MOD_ANYSHIFT)) == MOD_CAPSLOCK) { gindex = 0; ksym = ksym_upcase(group[0]); } else { gindex = MOD_ONESET(id, MOD_ANYSHIFT); ksym = group[gindex]; } } /* Submit Audio keys for hotkey processing */ if (KS_GROUP(ksym) == KS_GROUP_Function) { switch (ksym) { #if NAUDIO > 0 case KS_AudioMute: wskbd_set_mixervolume_dev(sc->sc_audiocookie, 0, 1); return (0); case KS_AudioLower: wskbd_set_mixervolume_dev(sc->sc_audiocookie, -1, 1); return (0); case KS_AudioRaise: wskbd_set_mixervolume_dev(sc->sc_audiocookie, 1, 1); return (0); #endif default: break; } } /* Process compose sequence and dead accents */ res = KS_voidSymbol; switch (KS_GROUP(ksym)) { case KS_GROUP_Ascii: case KS_GROUP_Keypad: case KS_GROUP_Function: res = ksym; break; case KS_GROUP_Mod: if (ksym == KS_Multi_key) { update_modifier(id, 1, 0, MOD_COMPOSE); id->t_composelen = 2; } break; case KS_GROUP_Dead: if (id->t_composelen == 0) { update_modifier(id, 1, 0, MOD_COMPOSE); id->t_composelen = 1; id->t_composebuf[0] = ksym; } else res = ksym; break; } if (res == KS_voidSymbol) return (0); if (id->t_composelen > 0) { /* * If the compose key also serves as AltGr (i.e. set to both * KS_Multi_key and KS_Mode_switch), and would provide a valid, * distinct combination as AltGr, leave compose mode. */ if (id->t_composelen == 2 && group == &kp->group2[0]) { if (kp->group1[gindex] != kp->group2[gindex]) id->t_composelen = 0; } if (id->t_composelen != 0) { id->t_composebuf[2 - id->t_composelen] = res; if (--id->t_composelen == 0) { res = wskbd_compose_value(id->t_composebuf); update_modifier(id, 0, 0, MOD_COMPOSE); } else { return (0); } } } /* We are done, return the symbol */ if (KS_GROUP(res) == KS_GROUP_Ascii) { if (MOD_ONESET(id, MOD_ANYCONTROL)) { if ((res >= KS_at && res <= KS_z) || res == KS_space) res = res & 0x1f; else if (res == KS_2) res = 0x00; else if (res >= KS_3 && res <= KS_7) res = KS_Escape + (res - KS_3); else if (res == KS_8) res = KS_Delete; } if (MOD_ONESET(id, MOD_ANYMETA)) { if (id->t_flags & WSKFL_METAESC) { id->t_symbols[0] = KS_Escape; id->t_symbols[1] = res; return (2); } else res |= 0x80; } } id->t_symbols[0] = res; return (1); } void wskbd_debugger(struct wskbd_softc *sc) { #ifdef DDB if (sc->sc_isconsole && db_console) { if (sc->id->t_consops->debugger != NULL) { (*sc->id->t_consops->debugger) (sc->id->t_consaccesscookie); } else db_enter(); } #endif } void wskbd_set_keymap(struct wskbd_softc *sc, struct wscons_keymap *map, int maplen) { free(sc->sc_map, M_DEVBUF, sc->sc_maplen * sizeof(*sc->sc_map)); sc->sc_map = map; sc->sc_maplen = maplen; } void wskbd_kbd_backlight_task(void *arg) { struct wskbd_softc *sc = arg; struct wskbd_backlight data; int step, val; u_int cmd; if (wskbd_get_backlight == NULL || wskbd_set_backlight == NULL) return; cmd = atomic_swap_uint(&sc->sc_kbd_backlight_cmd, 0); if (cmd != KBD_BACKLIGHT_UP && cmd != KBD_BACKLIGHT_DOWN && cmd != KBD_BACKLIGHT_TOGGLE) return; (*wskbd_get_backlight)(&data); step = (data.max - data.min + 1) / 8; val = (cmd == KBD_BACKLIGHT_UP) ? data.curval + step : (cmd == KBD_BACKLIGHT_DOWN) ? data.curval - step : (data.curval) ? 0 : (data.max - data.min + 1) / 2; data.curval = (val > 0xff) ? 0xff : (val < 0) ? 0 : val; (*wskbd_set_backlight)(&data); } #if NWSDISPLAY > 0 void wskbd_brightness_task(void *arg) { struct wskbd_softc *sc = arg; int steps = atomic_swap_uint(&sc->sc_brightness_steps, 0); int dir = 1; if (steps < 0) { steps = -steps; dir = -1; } while (steps--) wsdisplay_brightness_step(NULL, dir); } #endif
3 3 3 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 /* $OpenBSD: uvm_swap.c,v 1.170 2024/04/16 10:06:37 claudio Exp $ */ /* $NetBSD: uvm_swap.c,v 1.40 2000/11/17 11:39:39 mrg Exp $ */ /* * Copyright (c) 1995, 1996, 1997 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: NetBSD: vm_swap.c,v 1.52 1997/12/02 13:47:37 pk Exp * from: Id: uvm_swap.c,v 1.1.2.42 1998/02/02 20:38:06 chuck Exp */ #include <sys/param.h> #include <sys/systm.h> #include <sys/buf.h> #include <sys/conf.h> #include <sys/proc.h> #include <sys/namei.h> #include <sys/disklabel.h> #include <sys/errno.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/vnode.h> #include <sys/fcntl.h> #include <sys/extent.h> #include <sys/blist.h> #include <sys/mount.h> #include <sys/mutex.h> #include <sys/pool.h> #include <sys/syscallargs.h> #include <sys/swap.h> #include <sys/disk.h> #include <sys/task.h> #include <sys/pledge.h> #if defined(NFSCLIENT) #include <sys/socket.h> #include <netinet/in.h> #include <nfs/nfsproto.h> #include <nfs/nfsdiskless.h> #endif #include <uvm/uvm.h> #ifdef UVM_SWAP_ENCRYPT #include <uvm/uvm_swap_encrypt.h> #endif #include <sys/specdev.h> #include "vnd.h" /* * uvm_swap.c: manage configuration and i/o to swap space. */ /* * swap space is managed in the following way: * * each swap partition or file is described by a "swapdev" structure. * each "swapdev" structure contains a "swapent" structure which contains * information that is passed up to the user (via system calls). * * each swap partition is assigned a "priority" (int) which controls * swap partition usage. * * the system maintains a global data structure describing all swap * partitions/files. there is a sorted LIST of "swappri" structures * which describe "swapdev"'s at that priority. this LIST is headed * by the "swap_priority" global var. each "swappri" contains a * TAILQ of "swapdev" structures at that priority. * * locking: * - swap_syscall_lock (sleep lock): this lock serializes the swapctl * system call and prevents the swap priority list from changing * while we are in the middle of a system call (e.g. SWAP_STATS). * - uvm_swap_data_lock (mutex): this lock protects all swap data * structures including the priority list, the swapdev structures, * and the swapmap arena. * * each swap device has the following info: * - swap device in use (could be disabled, preventing future use) * - swap enabled (allows new allocations on swap) * - map info in /dev/drum * - vnode pointer * for swap files only: * - block size * - max byte count in buffer * - buffer * - credentials to use when doing i/o to file * * userland controls and configures swap with the swapctl(2) system call. * the sys_swapctl performs the following operations: * [1] SWAP_NSWAP: returns the number of swap devices currently configured * [2] SWAP_STATS: given a pointer to an array of swapent structures * (passed in via "arg") of a size passed in via "misc" ... we load * the current swap config into the array. * [3] SWAP_ON: given a pathname in arg (could be device or file) and a * priority in "misc", start swapping on it. * [4] SWAP_OFF: as SWAP_ON, but stops swapping to a device * [5] SWAP_CTL: changes the priority of a swap device (new priority in * "misc") */ /* * swapdev: describes a single swap partition/file * * note the following should be true: * swd_inuse <= swd_nblks [number of blocks in use is <= total blocks] * swd_nblks <= swd_mapsize [because mapsize includes disklabel] */ struct swapdev { struct swapent swd_se; #define swd_dev swd_se.se_dev /* device id */ #define swd_flags swd_se.se_flags /* flags:inuse/enable/fake */ #define swd_priority swd_se.se_priority /* our priority */ #define swd_inuse swd_se.se_inuse /* blocks used */ #define swd_nblks swd_se.se_nblks /* total blocks */ char *swd_path; /* saved pathname of device */ int swd_pathlen; /* length of pathname */ int swd_npages; /* #pages we can use */ int swd_npginuse; /* #pages in use */ int swd_npgbad; /* #pages bad */ int swd_drumoffset; /* page0 offset in drum */ int swd_drumsize; /* #pages in drum */ blist_t swd_blist; /* blist for this swapdev */ struct vnode *swd_vp; /* backing vnode */ TAILQ_ENTRY(swapdev) swd_next; /* priority tailq */ int swd_bsize; /* blocksize (bytes) */ int swd_maxactive; /* max active i/o reqs */ int swd_active; /* # of active i/o reqs */ struct bufq swd_bufq; struct ucred *swd_cred; /* cred for file access */ #ifdef UVM_SWAP_ENCRYPT #define SWD_KEY_SHIFT 7 /* One key per 0.5 MByte */ #define SWD_KEY(x,y) &((x)->swd_keys[((y) - (x)->swd_drumoffset) >> SWD_KEY_SHIFT]) #define SWD_KEY_SIZE(x) (((x) + (1 << SWD_KEY_SHIFT) - 1) >> SWD_KEY_SHIFT) #define SWD_DCRYPT_SHIFT 5 #define SWD_DCRYPT_BITS 32 #define SWD_DCRYPT_MASK (SWD_DCRYPT_BITS - 1) #define SWD_DCRYPT_OFF(x) ((x) >> SWD_DCRYPT_SHIFT) #define SWD_DCRYPT_BIT(x) ((x) & SWD_DCRYPT_MASK) #define SWD_DCRYPT_SIZE(x) (SWD_DCRYPT_OFF((x) + SWD_DCRYPT_MASK) * sizeof(u_int32_t)) u_int32_t *swd_decrypt; /* bitmap for decryption */ struct swap_key *swd_keys; /* keys for different parts */ #endif }; /* * swap device priority entry; the list is kept sorted on `spi_priority'. */ struct swappri { int spi_priority; /* priority */ TAILQ_HEAD(spi_swapdev, swapdev) spi_swapdev; /* tailq of swapdevs at this priority */ LIST_ENTRY(swappri) spi_swappri; /* global list of pri's */ }; /* * The following two structures are used to keep track of data transfers * on swap devices associated with regular files. * NOTE: this code is more or less a copy of vnd.c; we use the same * structure names here to ease porting.. */ struct vndxfer { struct buf *vx_bp; /* Pointer to parent buffer */ struct swapdev *vx_sdp; int vx_error; int vx_pending; /* # of pending aux buffers */ int vx_flags; #define VX_BUSY 1 #define VX_DEAD 2 }; struct vndbuf { struct buf vb_buf; struct vndxfer *vb_vnx; struct task vb_task; }; /* * We keep a of pool vndbuf's and vndxfer structures. */ struct pool vndxfer_pool; struct pool vndbuf_pool; /* * local variables */ struct extent *swapmap; /* controls the mapping of /dev/drum */ /* list of all active swap devices [by priority] */ LIST_HEAD(swap_priority, swappri); struct swap_priority swap_priority; /* [S] */ /* locks */ struct mutex uvm_swap_data_lock = MUTEX_INITIALIZER(IPL_MPFLOOR); struct rwlock swap_syscall_lock = RWLOCK_INITIALIZER("swplk"); struct mutex oommtx = MUTEX_INITIALIZER(IPL_VM); struct vm_page *oompps[SWCLUSTPAGES]; int oom = 0; /* * prototypes */ void swapdrum_add(struct swapdev *, int); struct swapdev *swapdrum_getsdp(int); struct swapdev *swaplist_find(struct vnode *, int); void swaplist_insert(struct swapdev *, struct swappri *, int); void swaplist_trim(void); int swap_on(struct proc *, struct swapdev *); int swap_off(struct proc *, struct swapdev *); void sw_reg_strategy(struct swapdev *, struct buf *, int); void sw_reg_iodone(struct buf *); void sw_reg_iodone_internal(void *); void sw_reg_start(struct swapdev *); int uvm_swap_io(struct vm_page **, int, int, int); void swapmount(void); int uvm_swap_allocpages(struct vm_page **, int, int); #ifdef UVM_SWAP_ENCRYPT /* for swap encrypt */ void uvm_swap_markdecrypt(struct swapdev *, int, int, int); boolean_t uvm_swap_needdecrypt(struct swapdev *, int); void uvm_swap_initcrypt(struct swapdev *, int); #endif /* * uvm_swap_init: init the swap system data structures and locks * * => called at boot time from init_main.c after the filesystems * are brought up (which happens after uvm_init()) */ void uvm_swap_init(void) { int error; /* * first, init the swap list, its counter, and its lock. * then get a handle on the vnode for /dev/drum by using * the its dev_t number ("swapdev", from MD conf.c). */ LIST_INIT(&swap_priority); uvmexp.nswapdev = 0; if (!swapdev_vp && bdevvp(swapdev, &swapdev_vp)) panic("uvm_swap_init: can't get vnode for swap device"); /* * create swap block extent to map /dev/drum. The extent spans * 1 to INT_MAX allows 2 gigablocks of swap space. Note that * block 0 is reserved (used to indicate an allocation failure, * or no allocation). */ swapmap = extent_create("swapmap", 1, INT_MAX, M_VMSWAP, 0, 0, EX_NOWAIT); if (swapmap == 0) panic("uvm_swap_init: extent_create failed"); /* allocate pools for structures used for swapping to files. */ pool_init(&vndxfer_pool, sizeof(struct vndxfer), 0, IPL_BIO, 0, "swp vnx", NULL); pool_init(&vndbuf_pool, sizeof(struct vndbuf), 0, IPL_BIO, 0, "swp vnd", NULL); /* allocate pages for OOM situations. */ error = uvm_swap_allocpages(oompps, SWCLUSTPAGES, UVM_PLA_NOWAIT); KASSERT(error == 0); /* Setup the initial swap partition */ swapmount(); } #ifdef UVM_SWAP_ENCRYPT void uvm_swap_initcrypt_all(void) { struct swapdev *sdp; struct swappri *spp; int npages; LIST_FOREACH(spp, &swap_priority, spi_swappri) { TAILQ_FOREACH(sdp, &spp->spi_swapdev, swd_next) { if (sdp->swd_decrypt == NULL) { npages = dbtob((uint64_t)sdp->swd_nblks) >> PAGE_SHIFT; uvm_swap_initcrypt(sdp, npages); } } } } void uvm_swap_initcrypt(struct swapdev *sdp, int npages) { /* * keep information if a page needs to be decrypted when we get it * from the swap device. * We cannot chance a malloc later, if we are doing ASYNC puts, * we may not call malloc with M_WAITOK. This consumes only * 8KB memory for a 256MB swap partition. */ sdp->swd_decrypt = malloc(SWD_DCRYPT_SIZE(npages), M_VMSWAP, M_WAITOK|M_ZERO); sdp->swd_keys = mallocarray(SWD_KEY_SIZE(npages), sizeof(struct swap_key), M_VMSWAP, M_WAITOK|M_ZERO); } #endif /* UVM_SWAP_ENCRYPT */ int uvm_swap_allocpages(struct vm_page **pps, int npages, int flags) { struct pglist pgl; int error, i; KASSERT(npages <= SWCLUSTPAGES); TAILQ_INIT(&pgl); again: error = uvm_pglistalloc(npages * PAGE_SIZE, dma_constraint.ucr_low, dma_constraint.ucr_high, 0, 0, &pgl, npages, flags); if (error && (curproc == uvm.pagedaemon_proc)) { mtx_enter(&oommtx); if (oom) { msleep_nsec(&oom, &oommtx, PVM | PNORELOCK, "oom", INFSLP); goto again; } oom = 1; for (i = 0; i < npages; i++) { pps[i] = oompps[i]; atomic_setbits_int(&pps[i]->pg_flags, PG_BUSY); } mtx_leave(&oommtx); return 0; } if (error) return error; for (i = 0; i < npages; i++) { pps[i] = TAILQ_FIRST(&pgl); /* *sigh* */ atomic_setbits_int(&pps[i]->pg_flags, PG_BUSY); TAILQ_REMOVE(&pgl, pps[i], pageq); } return 0; } void uvm_swap_freepages(struct vm_page **pps, int npages) { int i; if (pps[0] == oompps[0]) { for (i = 0; i < npages; i++) uvm_pageclean(pps[i]); mtx_enter(&oommtx); KASSERT(oom == 1); oom = 0; mtx_leave(&oommtx); wakeup(&oom); return; } uvm_lock_pageq(); for (i = 0; i < npages; i++) uvm_pagefree(pps[i]); uvm_unlock_pageq(); } #ifdef UVM_SWAP_ENCRYPT /* * Mark pages on the swap device for later decryption */ void uvm_swap_markdecrypt(struct swapdev *sdp, int startslot, int npages, int decrypt) { int pagestart, i; int off, bit; if (!sdp) return; pagestart = startslot - sdp->swd_drumoffset; for (i = 0; i < npages; i++, pagestart++) { off = SWD_DCRYPT_OFF(pagestart); bit = SWD_DCRYPT_BIT(pagestart); if (decrypt) /* pages read need decryption */ sdp->swd_decrypt[off] |= 1 << bit; else /* pages read do not need decryption */ sdp->swd_decrypt[off] &= ~(1 << bit); } } /* * Check if the page that we got from disk needs to be decrypted */ boolean_t uvm_swap_needdecrypt(struct swapdev *sdp, int off) { if (!sdp) return FALSE; off -= sdp->swd_drumoffset; return sdp->swd_decrypt[SWD_DCRYPT_OFF(off)] & (1 << SWD_DCRYPT_BIT(off)) ? TRUE : FALSE; } void uvm_swap_finicrypt_all(void) { struct swapdev *sdp; struct swappri *spp; struct swap_key *key; unsigned int nkeys; LIST_FOREACH(spp, &swap_priority, spi_swappri) { TAILQ_FOREACH(sdp, &spp->spi_swapdev, swd_next) { if (sdp->swd_decrypt == NULL) continue; nkeys = dbtob((uint64_t)sdp->swd_nblks) >> PAGE_SHIFT; key = sdp->swd_keys + (SWD_KEY_SIZE(nkeys) - 1); do { if (key->refcount != 0) swap_key_delete(key); } while (key-- != sdp->swd_keys); } } } #endif /* UVM_SWAP_ENCRYPT */ /* * swaplist functions: functions that operate on the list of swap * devices on the system. */ /* * swaplist_insert: insert swap device "sdp" into the global list * * => caller must hold both swap_syscall_lock and uvm_swap_data_lock * => caller must provide a newly allocated swappri structure (we will * FREE it if we don't need it... this it to prevent allocation * blocking here while adding swap) */ void swaplist_insert(struct swapdev *sdp, struct swappri *newspp, int priority) { struct swappri *spp, *pspp; KASSERT(rw_write_held(&swap_syscall_lock)); MUTEX_ASSERT_LOCKED(&uvm_swap_data_lock); /* * find entry at or after which to insert the new device. */ pspp = NULL; LIST_FOREACH(spp, &swap_priority, spi_swappri) { if (priority <= spp->spi_priority) break; pspp = spp; } /* * new priority? */ if (spp == NULL || spp->spi_priority != priority) { spp = newspp; /* use newspp! */ spp->spi_priority = priority; TAILQ_INIT(&spp->spi_swapdev); if (pspp) LIST_INSERT_AFTER(pspp, spp, spi_swappri); else LIST_INSERT_HEAD(&swap_priority, spp, spi_swappri); } else { /* we don't need a new priority structure, free it */ free(newspp, M_VMSWAP, sizeof(*newspp)); } /* * priority found (or created). now insert on the priority's * tailq list and bump the total number of swapdevs. */ sdp->swd_priority = priority; TAILQ_INSERT_TAIL(&spp->spi_swapdev, sdp, swd_next); uvmexp.nswapdev++; } /* * swaplist_find: find and optionally remove a swap device from the * global list. * * => caller must hold both swap_syscall_lock and uvm_swap_data_lock * => we return the swapdev we found (and removed) */ struct swapdev * swaplist_find(struct vnode *vp, boolean_t remove) { struct swapdev *sdp; struct swappri *spp; KASSERT(rw_write_held(&swap_syscall_lock)); MUTEX_ASSERT_LOCKED(&uvm_swap_data_lock); /* * search the lists for the requested vp */ LIST_FOREACH(spp, &swap_priority, spi_swappri) { TAILQ_FOREACH(sdp, &spp->spi_swapdev, swd_next) { if (sdp->swd_vp != vp) continue; if (remove) { TAILQ_REMOVE(&spp->spi_swapdev, sdp, swd_next); uvmexp.nswapdev--; } return (sdp); } } return (NULL); } /* * swaplist_trim: scan priority list for empty priority entries and kill * them. * * => caller must hold both swap_syscall_lock and uvm_swap_data_lock */ void swaplist_trim(void) { struct swappri *spp, *nextspp; KASSERT(rw_write_held(&swap_syscall_lock)); MUTEX_ASSERT_LOCKED(&uvm_swap_data_lock); LIST_FOREACH_SAFE(spp, &swap_priority, spi_swappri, nextspp) { if (!TAILQ_EMPTY(&spp->spi_swapdev)) continue; LIST_REMOVE(spp, spi_swappri); free(spp, M_VMSWAP, sizeof(*spp)); } } /* * swapdrum_add: add a "swapdev"'s blocks into /dev/drum's area. * * => caller must hold swap_syscall_lock * => uvm_swap_data_lock should be unlocked (we may sleep) */ void swapdrum_add(struct swapdev *sdp, int npages) { u_long result; if (extent_alloc(swapmap, npages, EX_NOALIGN, 0, EX_NOBOUNDARY, EX_WAITOK, &result)) panic("swapdrum_add"); sdp->swd_drumoffset = result; sdp->swd_drumsize = npages; } /* * swapdrum_getsdp: given a page offset in /dev/drum, convert it back * to the "swapdev" that maps that section of the drum. * * => each swapdev takes one big contig chunk of the drum * => caller must hold uvm_swap_data_lock */ struct swapdev * swapdrum_getsdp(int pgno) { struct swapdev *sdp; struct swappri *spp; MUTEX_ASSERT_LOCKED(&uvm_swap_data_lock); LIST_FOREACH(spp, &swap_priority, spi_swappri) { TAILQ_FOREACH(sdp, &spp->spi_swapdev, swd_next) { if (pgno >= sdp->swd_drumoffset && pgno < (sdp->swd_drumoffset + sdp->swd_drumsize)) { return sdp; } } } return NULL; } /* * sys_swapctl: main entry point for swapctl(2) system call * [with two helper functions: swap_on and swap_off] */ int sys_swapctl(struct proc *p, void *v, register_t *retval) { struct sys_swapctl_args /* { syscallarg(int) cmd; syscallarg(void *) arg; syscallarg(int) misc; } */ *uap = (struct sys_swapctl_args *)v; struct vnode *vp; struct nameidata nd; struct swappri *spp; struct swapdev *sdp; struct swapent *sep; char userpath[MAXPATHLEN]; size_t len; int count, error, misc; int priority; misc = SCARG(uap, misc); if ((error = pledge_swapctl(p, SCARG(uap, cmd)))) return error; /* * ensure serialized syscall access by grabbing the swap_syscall_lock */ rw_enter_write(&swap_syscall_lock); /* * we handle the non-priv NSWAP and STATS request first. * * SWAP_NSWAP: return number of config'd swap devices * [can also be obtained with uvmexp sysctl] */ if (SCARG(uap, cmd) == SWAP_NSWAP) { *retval = uvmexp.nswapdev; error = 0; goto out; } /* * SWAP_STATS: get stats on current # of configured swap devs * * note that the swap_priority list can't change as long * as we are holding the swap_syscall_lock. we don't want * to grab the uvm_swap_data_lock because we may fault&sleep during * copyout() and we don't want to be holding that lock then! */ if (SCARG(uap, cmd) == SWAP_STATS) { sep = (struct swapent *)SCARG(uap, arg); count = 0; LIST_FOREACH(spp, &swap_priority, spi_swappri) { TAILQ_FOREACH(sdp, &spp->spi_swapdev, swd_next) { if (count >= misc) continue; sdp->swd_inuse = btodb((u_int64_t)sdp->swd_npginuse << PAGE_SHIFT); error = copyout(&sdp->swd_se, sep, sizeof(struct swapent)); if (error) goto out; /* now copy out the path if necessary */ error = copyoutstr(sdp->swd_path, sep->se_path, sizeof(sep->se_path), NULL); if (error) goto out; count++; sep++; } } *retval = count; error = 0; goto out; } /* all other requests require superuser privs. verify. */ if ((error = suser(p))) goto out; /* * at this point we expect a path name in arg. we will * use namei() to gain a vnode reference (vref), and lock * the vnode (VOP_LOCK). */ error = copyinstr(SCARG(uap, arg), userpath, sizeof(userpath), &len); if (error) goto out; disk_map(userpath, userpath, sizeof(userpath), DM_OPENBLCK); NDINIT(&nd, LOOKUP, FOLLOW|LOCKLEAF, UIO_SYSSPACE, userpath, p); if ((error = namei(&nd))) goto out; vp = nd.ni_vp; /* note: "vp" is referenced and locked */ error = 0; /* assume no error */ switch(SCARG(uap, cmd)) { case SWAP_DUMPDEV: if (vp->v_type != VBLK) { error = ENOTBLK; break; } dumpdev = vp->v_rdev; break; case SWAP_CTL: /* * get new priority, remove old entry (if any) and then * reinsert it in the correct place. finally, prune out * any empty priority structures. */ priority = SCARG(uap, misc); spp = malloc(sizeof *spp, M_VMSWAP, M_WAITOK); mtx_enter(&uvm_swap_data_lock); if ((sdp = swaplist_find(vp, 1)) == NULL) { error = ENOENT; } else { swaplist_insert(sdp, spp, priority); swaplist_trim(); } mtx_leave(&uvm_swap_data_lock); if (error) free(spp, M_VMSWAP, sizeof(*spp)); break; case SWAP_ON: /* * If the device is a regular file, make sure the filesystem * can be used for swapping. */ if (vp->v_type == VREG && (vp->v_mount->mnt_flag & MNT_SWAPPABLE) == 0) { error = ENOTSUP; break; } /* * check for duplicates. if none found, then insert a * dummy entry on the list to prevent someone else from * trying to enable this device while we are working on * it. */ priority = SCARG(uap, misc); sdp = malloc(sizeof *sdp, M_VMSWAP, M_WAITOK|M_ZERO); spp = malloc(sizeof *spp, M_VMSWAP, M_WAITOK); sdp->swd_flags = SWF_FAKE; /* placeholder only */ sdp->swd_vp = vp; sdp->swd_dev = (vp->v_type == VBLK) ? vp->v_rdev : NODEV; /* * XXX Is NFS elaboration necessary? */ if (vp->v_type == VREG) { sdp->swd_cred = crdup(p->p_ucred); } mtx_enter(&uvm_swap_data_lock); if (swaplist_find(vp, 0) != NULL) { error = EBUSY; mtx_leave(&uvm_swap_data_lock); if (vp->v_type == VREG) { crfree(sdp->swd_cred); } free(sdp, M_VMSWAP, sizeof *sdp); free(spp, M_VMSWAP, sizeof *spp); break; } swaplist_insert(sdp, spp, priority); mtx_leave(&uvm_swap_data_lock); sdp->swd_pathlen = len; sdp->swd_path = malloc(sdp->swd_pathlen, M_VMSWAP, M_WAITOK); strlcpy(sdp->swd_path, userpath, len); /* * we've now got a FAKE placeholder in the swap list. * now attempt to enable swap on it. if we fail, undo * what we've done and kill the fake entry we just inserted. * if swap_on is a success, it will clear the SWF_FAKE flag */ if ((error = swap_on(p, sdp)) != 0) { mtx_enter(&uvm_swap_data_lock); (void) swaplist_find(vp, 1); /* kill fake entry */ swaplist_trim(); mtx_leave(&uvm_swap_data_lock); if (vp->v_type == VREG) { crfree(sdp->swd_cred); } free(sdp->swd_path, M_VMSWAP, sdp->swd_pathlen); free(sdp, M_VMSWAP, sizeof(*sdp)); break; } break; case SWAP_OFF: mtx_enter(&uvm_swap_data_lock); if ((sdp = swaplist_find(vp, 0)) == NULL) { mtx_leave(&uvm_swap_data_lock); error = ENXIO; break; } /* * If a device isn't in use or enabled, we * can't stop swapping from it (again). */ if ((sdp->swd_flags & (SWF_INUSE|SWF_ENABLE)) == 0) { mtx_leave(&uvm_swap_data_lock); error = EBUSY; break; } /* * do the real work. */ error = swap_off(p, sdp); break; default: error = EINVAL; } /* done! release the ref gained by namei() and unlock. */ vput(vp); out: rw_exit_write(&swap_syscall_lock); return (error); } /* * swap_on: attempt to enable a swapdev for swapping. note that the * swapdev is already on the global list, but disabled (marked * SWF_FAKE). * * => we avoid the start of the disk (to protect disk labels) * => caller should leave uvm_swap_data_lock unlocked, we may lock it * if needed. */ int swap_on(struct proc *p, struct swapdev *sdp) { struct vnode *vp; int error, npages, nblocks, size; long addr; struct vattr va; #if defined(NFSCLIENT) extern const struct vops nfs_vops; #endif /* defined(NFSCLIENT) */ dev_t dev; /* * we want to enable swapping on sdp. the swd_vp contains * the vnode we want (locked and ref'd), and the swd_dev * contains the dev_t of the file, if it a block device. */ vp = sdp->swd_vp; dev = sdp->swd_dev; #if NVND > 0 /* no swapping to vnds. */ if (bdevsw[major(dev)].d_strategy == vndstrategy) return (EOPNOTSUPP); #endif /* * open the swap file (mostly useful for block device files to * let device driver know what is up). * * we skip the open/close for root on swap because the root * has already been opened when root was mounted (mountroot). */ if (vp != rootvp) { if ((error = VOP_OPEN(vp, FREAD|FWRITE, p->p_ucred, p))) return (error); } /* XXX this only works for block devices */ /* * we now need to determine the size of the swap area. for * block specials we can call the d_psize function. * for normal files, we must stat [get attrs]. * * we put the result in nblks. * for normal files, we also want the filesystem block size * (which we get with statfs). */ switch (vp->v_type) { case VBLK: if (bdevsw[major(dev)].d_psize == 0 || (nblocks = (*bdevsw[major(dev)].d_psize)(dev)) == -1) { error = ENXIO; goto bad; } break; case VREG: if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p))) goto bad; nblocks = (int)btodb(va.va_size); if ((error = VFS_STATFS(vp->v_mount, &vp->v_mount->mnt_stat, p)) != 0) goto bad; sdp->swd_bsize = vp->v_mount->mnt_stat.f_iosize; /* * limit the max # of outstanding I/O requests we issue * at any one time. take it easy on NFS servers. */ #if defined(NFSCLIENT) if (vp->v_op == &nfs_vops) sdp->swd_maxactive = 2; /* XXX */ else #endif /* defined(NFSCLIENT) */ sdp->swd_maxactive = 8; /* XXX */ bufq_init(&sdp->swd_bufq, BUFQ_FIFO); break; default: error = ENXIO; goto bad; } /* * save nblocks in a safe place and convert to pages. */ sdp->swd_nblks = nblocks; npages = dbtob((u_int64_t)nblocks) >> PAGE_SHIFT; /* * for block special files, we want to make sure that leave * the disklabel and bootblocks alone, so we arrange to skip * over them (arbitrarily choosing to skip PAGE_SIZE bytes). * note that because of this the "size" can be less than the * actual number of blocks on the device. */ if (vp->v_type == VBLK) { /* we use pages 1 to (size - 1) [inclusive] */ size = npages - 1; addr = 1; } else { /* we use pages 0 to (size - 1) [inclusive] */ size = npages; addr = 0; } /* * make sure we have enough blocks for a reasonable sized swap * area. we want at least one page. */ if (size < 1) { error = EINVAL; goto bad; } /* * now we need to allocate a blist to manage this swap device */ sdp->swd_blist = blist_create(npages); /* mark all expect the `saved' region free. */ blist_free(sdp->swd_blist, addr, size); #ifdef HIBERNATE /* * Lock down the last region of primary disk swap, in case * hibernate needs to place a signature there. */ if (dev == swdevt[0].sw_dev && vp->v_type == VBLK && size > 3 ) { if (blist_fill(sdp->swd_blist, npages - 1, 1) != 1) panic("hibernate reserve"); } #endif /* add a ref to vp to reflect usage as a swap device. */ vref(vp); #ifdef UVM_SWAP_ENCRYPT if (uvm_doswapencrypt) uvm_swap_initcrypt(sdp, npages); #endif /* now add the new swapdev to the drum and enable. */ swapdrum_add(sdp, npages); sdp->swd_npages = size; mtx_enter(&uvm_swap_data_lock); sdp->swd_flags &= ~SWF_FAKE; /* going live */ sdp->swd_flags |= (SWF_INUSE|SWF_ENABLE); uvmexp.swpages += size; mtx_leave(&uvm_swap_data_lock); return (0); /* * failure: clean up and return error. */ bad: if (vp != rootvp) (void)VOP_CLOSE(vp, FREAD|FWRITE, p->p_ucred, p); return (error); } /* * swap_off: stop swapping on swapdev * * => swap data should be locked, we will unlock. */ int swap_off(struct proc *p, struct swapdev *sdp) { int npages = sdp->swd_npages; int error = 0; KASSERT(rw_write_held(&swap_syscall_lock)); MUTEX_ASSERT_LOCKED(&uvm_swap_data_lock); /* disable the swap area being removed */ sdp->swd_flags &= ~SWF_ENABLE; mtx_leave(&uvm_swap_data_lock); /* * the idea is to find all the pages that are paged out to this * device, and page them all in. in uvm, swap-backed pageable * memory can take two forms: aobjs and anons. call the * swapoff hook for each subsystem to bring in pages. */ if (uao_swap_off(sdp->swd_drumoffset, sdp->swd_drumoffset + sdp->swd_drumsize) || amap_swap_off(sdp->swd_drumoffset, sdp->swd_drumoffset + sdp->swd_drumsize)) { error = ENOMEM; } else if (sdp->swd_npginuse > sdp->swd_npgbad) { error = EBUSY; } if (error) { mtx_enter(&uvm_swap_data_lock); sdp->swd_flags |= SWF_ENABLE; mtx_leave(&uvm_swap_data_lock); return error; } /* * done with the vnode and saved creds. * drop our ref on the vnode before calling VOP_CLOSE() * so that spec_close() can tell if this is the last close. */ if (sdp->swd_vp->v_type == VREG) { crfree(sdp->swd_cred); bufq_destroy(&sdp->swd_bufq); } vrele(sdp->swd_vp); if (sdp->swd_vp != rootvp) { (void) VOP_CLOSE(sdp->swd_vp, FREAD|FWRITE, p->p_ucred, p); } mtx_enter(&uvm_swap_data_lock); uvmexp.swpages -= npages; if (swaplist_find(sdp->swd_vp, 1) == NULL) panic("swap_off: swapdev not in list"); swaplist_trim(); mtx_leave(&uvm_swap_data_lock); /* * free all resources! */ extent_free(swapmap, sdp->swd_drumoffset, sdp->swd_drumsize, EX_WAITOK); blist_destroy(sdp->swd_blist); /* free sdp->swd_path ? */ free(sdp, M_VMSWAP, sizeof(*sdp)); return (0); } /* * /dev/drum interface and i/o functions */ /* * swstrategy: perform I/O on the drum * * => we must map the i/o request from the drum to the correct swapdev. */ void swstrategy(struct buf *bp) { struct swapdev *sdp; int s, pageno, bn; /* * convert block number to swapdev. note that swapdev can't * be yanked out from under us because we are holding resources * in it (i.e. the blocks we are doing I/O on). */ pageno = dbtob((u_int64_t)bp->b_blkno) >> PAGE_SHIFT; mtx_enter(&uvm_swap_data_lock); sdp = swapdrum_getsdp(pageno); mtx_leave(&uvm_swap_data_lock); if (sdp == NULL) { bp->b_error = EINVAL; bp->b_flags |= B_ERROR; s = splbio(); biodone(bp); splx(s); return; } /* convert drum page number to block number on this swapdev. */ pageno -= sdp->swd_drumoffset; /* page # on swapdev */ bn = btodb((u_int64_t)pageno << PAGE_SHIFT); /* convert to diskblock */ /* * for block devices we finish up here. * for regular files we have to do more work which we delegate * to sw_reg_strategy(). */ switch (sdp->swd_vp->v_type) { default: panic("swstrategy: vnode type 0x%x", sdp->swd_vp->v_type); case VBLK: /* * must convert "bp" from an I/O on /dev/drum to an I/O * on the swapdev (sdp). */ s = splbio(); buf_replacevnode(bp, sdp->swd_vp); bp->b_blkno = bn; splx(s); VOP_STRATEGY(bp->b_vp, bp); return; case VREG: /* delegate to sw_reg_strategy function. */ sw_reg_strategy(sdp, bp, bn); return; } /* NOTREACHED */ } /* * sw_reg_strategy: handle swap i/o to regular files */ void sw_reg_strategy(struct swapdev *sdp, struct buf *bp, int bn) { struct vnode *vp; struct vndxfer *vnx; daddr_t nbn; caddr_t addr; off_t byteoff; int s, off, nra, error, sz, resid; /* * allocate a vndxfer head for this transfer and point it to * our buffer. */ vnx = pool_get(&vndxfer_pool, PR_WAITOK); vnx->vx_flags = VX_BUSY; vnx->vx_error = 0; vnx->vx_pending = 0; vnx->vx_bp = bp; vnx->vx_sdp = sdp; /* * setup for main loop where we read filesystem blocks into * our buffer. */ error = 0; bp->b_resid = bp->b_bcount; /* nothing transferred yet! */ addr = bp->b_data; /* current position in buffer */ byteoff = dbtob((u_int64_t)bn); for (resid = bp->b_resid; resid; resid -= sz) { struct vndbuf *nbp; /* * translate byteoffset into block number. return values: * vp = vnode of underlying device * nbn = new block number (on underlying vnode dev) * nra = num blocks we can read-ahead (excludes requested * block) */ nra = 0; error = VOP_BMAP(sdp->swd_vp, byteoff / sdp->swd_bsize, &vp, &nbn, &nra); if (error == 0 && nbn == -1) { /* * this used to just set error, but that doesn't * do the right thing. Instead, it causes random * memory errors. The panic() should remain until * this condition doesn't destabilize the system. */ #if 1 panic("sw_reg_strategy: swap to sparse file"); #else error = EIO; /* failure */ #endif } /* * punt if there was an error or a hole in the file. * we must wait for any i/o ops we have already started * to finish before returning. * * XXX we could deal with holes here but it would be * a hassle (in the write case). */ if (error) { s = splbio(); vnx->vx_error = error; /* pass error up */ goto out; } /* * compute the size ("sz") of this transfer (in bytes). */ off = byteoff % sdp->swd_bsize; sz = (1 + nra) * sdp->swd_bsize - off; if (sz > resid) sz = resid; /* * now get a buf structure. note that the vb_buf is * at the front of the nbp structure so that you can * cast pointers between the two structure easily. */ nbp = pool_get(&vndbuf_pool, PR_WAITOK); nbp->vb_buf.b_flags = bp->b_flags | B_CALL; nbp->vb_buf.b_bcount = sz; nbp->vb_buf.b_bufsize = sz; nbp->vb_buf.b_error = 0; nbp->vb_buf.b_data = addr; nbp->vb_buf.b_bq = NULL; nbp->vb_buf.b_blkno = nbn + btodb(off); nbp->vb_buf.b_proc = bp->b_proc; nbp->vb_buf.b_iodone = sw_reg_iodone; nbp->vb_buf.b_vp = NULLVP; nbp->vb_buf.b_vnbufs.le_next = NOLIST; /* * set b_dirtyoff/end and b_validoff/end. this is * required by the NFS client code (otherwise it will * just discard our I/O request). */ if (bp->b_dirtyend == 0) { nbp->vb_buf.b_dirtyoff = 0; nbp->vb_buf.b_dirtyend = sz; } else { nbp->vb_buf.b_dirtyoff = max(0, bp->b_dirtyoff - (bp->b_bcount-resid)); nbp->vb_buf.b_dirtyend = min(sz, max(0, bp->b_dirtyend - (bp->b_bcount-resid))); } if (bp->b_validend == 0) { nbp->vb_buf.b_validoff = 0; nbp->vb_buf.b_validend = sz; } else { nbp->vb_buf.b_validoff = max(0, bp->b_validoff - (bp->b_bcount-resid)); nbp->vb_buf.b_validend = min(sz, max(0, bp->b_validend - (bp->b_bcount-resid))); } /* patch it back to the vnx */ nbp->vb_vnx = vnx; task_set(&nbp->vb_task, sw_reg_iodone_internal, nbp); s = splbio(); if (vnx->vx_error != 0) { pool_put(&vndbuf_pool, nbp); goto out; } vnx->vx_pending++; /* assoc new buffer with underlying vnode */ bgetvp(vp, &nbp->vb_buf); /* start I/O if we are not over our limit */ bufq_queue(&sdp->swd_bufq, &nbp->vb_buf); sw_reg_start(sdp); splx(s); /* * advance to the next I/O */ byteoff += sz; addr += sz; } s = splbio(); out: /* Arrive here at splbio */ vnx->vx_flags &= ~VX_BUSY; if (vnx->vx_pending == 0) { if (vnx->vx_error != 0) { bp->b_error = vnx->vx_error; bp->b_flags |= B_ERROR; } pool_put(&vndxfer_pool, vnx); biodone(bp); } splx(s); } /* sw_reg_start: start an I/O request on the requested swapdev. */ void sw_reg_start(struct swapdev *sdp) { struct buf *bp; /* XXX: recursion control */ if ((sdp->swd_flags & SWF_BUSY) != 0) return; sdp->swd_flags |= SWF_BUSY; while (sdp->swd_active < sdp->swd_maxactive) { bp = bufq_dequeue(&sdp->swd_bufq); if (bp == NULL) break; sdp->swd_active++; if ((bp->b_flags & B_READ) == 0) bp->b_vp->v_numoutput++; VOP_STRATEGY(bp->b_vp, bp); } sdp->swd_flags &= ~SWF_BUSY; } /* * sw_reg_iodone: one of our i/o's has completed and needs post-i/o cleanup * * => note that we can recover the vndbuf struct by casting the buf ptr * * XXX: * We only put this onto a taskq here, because of the maxactive game since * it basically requires us to call back into VOP_STRATEGY() (where we must * be able to sleep) via sw_reg_start(). */ void sw_reg_iodone(struct buf *bp) { struct vndbuf *vbp = (struct vndbuf *)bp; task_add(systq, &vbp->vb_task); } void sw_reg_iodone_internal(void *xvbp) { struct vndbuf *vbp = xvbp; struct vndxfer *vnx = vbp->vb_vnx; struct buf *pbp = vnx->vx_bp; /* parent buffer */ struct swapdev *sdp = vnx->vx_sdp; int resid, s; s = splbio(); resid = vbp->vb_buf.b_bcount - vbp->vb_buf.b_resid; pbp->b_resid -= resid; vnx->vx_pending--; /* pass error upward */ if (vbp->vb_buf.b_error) vnx->vx_error = vbp->vb_buf.b_error; /* disassociate this buffer from the vnode (if any). */ if (vbp->vb_buf.b_vp != NULL) { brelvp(&vbp->vb_buf); } /* kill vbp structure */ pool_put(&vndbuf_pool, vbp); /* * wrap up this transaction if it has run to completion or, in * case of an error, when all auxiliary buffers have returned. */ if (vnx->vx_error != 0) { /* pass error upward */ pbp->b_flags |= B_ERROR; pbp->b_error = vnx->vx_error; if ((vnx->vx_flags & VX_BUSY) == 0 && vnx->vx_pending == 0) { pool_put(&vndxfer_pool, vnx); biodone(pbp); } } else if (pbp->b_resid == 0) { KASSERT(vnx->vx_pending == 0); if ((vnx->vx_flags & VX_BUSY) == 0) { pool_put(&vndxfer_pool, vnx); biodone(pbp); } } /* * done! start next swapdev I/O if one is pending */ sdp->swd_active--; sw_reg_start(sdp); splx(s); } /* * uvm_swap_alloc: allocate space on swap * * => allocation is done "round robin" down the priority list, as we * allocate in a priority we "rotate" the tail queue. * => space can be freed with uvm_swap_free * => we return the page slot number in /dev/drum (0 == invalid slot) * => we lock uvm_swap_data_lock * => XXXMRG: "LESSOK" INTERFACE NEEDED TO EXTENT SYSTEM */ int uvm_swap_alloc(int *nslots, boolean_t lessok) { struct swapdev *sdp; struct swappri *spp; /* * no swap devices configured yet? definite failure. */ if (uvmexp.nswapdev < 1) return 0; /* * lock data lock, convert slots into blocks, and enter loop */ KERNEL_ASSERT_LOCKED(); mtx_enter(&uvm_swap_data_lock); ReTry: /* XXXMRG */ LIST_FOREACH(spp, &swap_priority, spi_swappri) { TAILQ_FOREACH(sdp, &spp->spi_swapdev, swd_next) { swblk_t result; /* if it's not enabled, then we can't swap from it */ if ((sdp->swd_flags & SWF_ENABLE) == 0) continue; if (sdp->swd_npginuse + *nslots > sdp->swd_npages) continue; result = blist_alloc(sdp->swd_blist, *nslots); if (result == SWAPBLK_NONE) { continue; } KASSERT(result < sdp->swd_drumsize); /* * successful allocation! now rotate the tailq. */ TAILQ_REMOVE(&spp->spi_swapdev, sdp, swd_next); TAILQ_INSERT_TAIL(&spp->spi_swapdev, sdp, swd_next); sdp->swd_npginuse += *nslots; uvmexp.swpginuse += *nslots; mtx_leave(&uvm_swap_data_lock); /* done! return drum slot number */ return result + sdp->swd_drumoffset; } } /* XXXMRG: BEGIN HACK */ if (*nslots > 1 && lessok) { *nslots = 1; /* XXXMRG: ugh! blist should support this for us */ goto ReTry; } /* XXXMRG: END HACK */ mtx_leave(&uvm_swap_data_lock); return 0; /* failed */ } /* * uvm_swapisfilled: return true if the amount of free space in swap is * smaller than the size of a cluster. * * As long as some swap slots are being used by pages currently in memory, * it is possible to reuse them. Even if the swap space has been completly * filled we do not consider it full. */ int uvm_swapisfilled(void) { int result; mtx_enter(&uvm_swap_data_lock); KASSERT(uvmexp.swpginuse <= uvmexp.swpages); result = (uvmexp.swpginuse + SWCLUSTPAGES) >= uvmexp.swpages; mtx_leave(&uvm_swap_data_lock); return result; } /* * uvm_swapisfull: return true if the amount of pages only in swap * accounts for more than 99% of the total swap space. * */ int uvm_swapisfull(void) { int result; mtx_enter(&uvm_swap_data_lock); KASSERT(uvmexp.swpgonly <= uvmexp.swpages); result = (uvmexp.swpgonly >= ((long)uvmexp.swpages * 99 / 100)); mtx_leave(&uvm_swap_data_lock); return result; } /* * uvm_swap_markbad: keep track of swap ranges where we've had i/o errors * * => we lock uvm_swap_data_lock */ void uvm_swap_markbad(int startslot, int nslots) { struct swapdev *sdp; mtx_enter(&uvm_swap_data_lock); sdp = swapdrum_getsdp(startslot); if (sdp != NULL) { /* * we just keep track of how many pages have been marked bad * in this device, to make everything add up in swap_off(). * we assume here that the range of slots will all be within * one swap device. */ sdp->swd_npgbad += nslots; } mtx_leave(&uvm_swap_data_lock); } /* * uvm_swap_free: free swap slots * * => this can be all or part of an allocation made by uvm_swap_alloc * => we lock uvm_swap_data_lock */ void uvm_swap_free(int startslot, int nslots) { struct swapdev *sdp; /* * ignore attempts to free the "bad" slot. */ if (startslot == SWSLOT_BAD) { return; } /* * convert drum slot offset back to sdp, free the blocks * in the extent, and return. must hold pri lock to do * lookup and access the extent. */ KERNEL_LOCK(); mtx_enter(&uvm_swap_data_lock); sdp = swapdrum_getsdp(startslot); KASSERT(uvmexp.nswapdev >= 1); KASSERT(sdp != NULL); KASSERT(sdp->swd_npginuse >= nslots); blist_free(sdp->swd_blist, startslot - sdp->swd_drumoffset, nslots); sdp->swd_npginuse -= nslots; uvmexp.swpginuse -= nslots; mtx_leave(&uvm_swap_data_lock); #ifdef UVM_SWAP_ENCRYPT { int i; if (swap_encrypt_initialized) { /* Dereference keys */ for (i = 0; i < nslots; i++) if (uvm_swap_needdecrypt(sdp, startslot + i)) { struct swap_key *key; key = SWD_KEY(sdp, startslot + i); if (key->refcount != 0) SWAP_KEY_PUT(sdp, key); } /* Mark range as not decrypt */ uvm_swap_markdecrypt(sdp, startslot, nslots, 0); } } #endif /* UVM_SWAP_ENCRYPT */ KERNEL_UNLOCK(); } /* * uvm_swap_put: put any number of pages into a contig place on swap * * => can be sync or async */ int uvm_swap_put(int swslot, struct vm_page **ppsp, int npages, int flags) { int result; result = uvm_swap_io(ppsp, swslot, npages, B_WRITE | ((flags & PGO_SYNCIO) ? 0 : B_ASYNC)); return (result); } /* * uvm_swap_get: get a single page from swap * * => usually a sync op (from fault) */ int uvm_swap_get(struct vm_page *page, int swslot, int flags) { int result; atomic_inc_int(&uvmexp.nswget); KASSERT(flags & PGO_SYNCIO); if (swslot == SWSLOT_BAD) { return VM_PAGER_ERROR; } KERNEL_LOCK(); result = uvm_swap_io(&page, swslot, 1, B_READ); KERNEL_UNLOCK(); if (result == VM_PAGER_OK || result == VM_PAGER_PEND) { /* * this page is no longer only in swap. */ atomic_dec_int(&uvmexp.swpgonly); } return (result); } /* * uvm_swap_io: do an i/o operation to swap */ int uvm_swap_io(struct vm_page **pps, int startslot, int npages, int flags) { daddr_t startblk; struct buf *bp; vaddr_t kva; int result, s, mapinflags, pflag, bounce = 0, i; boolean_t write, async; vaddr_t bouncekva; struct vm_page *tpps[SWCLUSTPAGES]; int pdaemon = (curproc == uvm.pagedaemon_proc); #ifdef UVM_SWAP_ENCRYPT struct swapdev *sdp; int encrypt = 0; #endif KERNEL_ASSERT_LOCKED(); write = (flags & B_READ) == 0; async = (flags & B_ASYNC) != 0; /* convert starting drum slot to block number */ startblk = btodb((u_int64_t)startslot << PAGE_SHIFT); pflag = (async || pdaemon) ? PR_NOWAIT : PR_WAITOK; bp = pool_get(&bufpool, pflag | PR_ZERO); if (bp == NULL) return (VM_PAGER_AGAIN); /* * map the pages into the kernel (XXX: currently required * by buffer system). */ mapinflags = !write ? UVMPAGER_MAPIN_READ : UVMPAGER_MAPIN_WRITE; if (!async) mapinflags |= UVMPAGER_MAPIN_WAITOK; kva = uvm_pagermapin(pps, npages, mapinflags); if (kva == 0) { pool_put(&bufpool, bp); return (VM_PAGER_AGAIN); } #ifdef UVM_SWAP_ENCRYPT if (write) { /* * Check if we need to do swap encryption on old pages. * Later we need a different scheme, that swap encrypts * all pages of a process that had at least one page swap * encrypted. Then we might not need to copy all pages * in the cluster, and avoid the memory overheard in * swapping. */ if (uvm_doswapencrypt) encrypt = 1; } if (swap_encrypt_initialized || encrypt) { /* * we need to know the swap device that we are swapping to/from * to see if the pages need to be marked for decryption or * actually need to be decrypted. * XXX - does this information stay the same over the whole * execution of this function? */ mtx_enter(&uvm_swap_data_lock); sdp = swapdrum_getsdp(startslot); mtx_leave(&uvm_swap_data_lock); } /* * Check that we are dma capable for read (write always bounces * through the swapencrypt anyway... */ if (write && encrypt) { bounce = 1; /* bounce through swapencrypt always */ } else { #else { #endif for (i = 0; i < npages; i++) { if (VM_PAGE_TO_PHYS(pps[i]) < dma_constraint.ucr_low || VM_PAGE_TO_PHYS(pps[i]) > dma_constraint.ucr_high) { bounce = 1; break; } } } if (bounce) { int swmapflags, plaflags; /* We always need write access. */ swmapflags = UVMPAGER_MAPIN_READ; plaflags = UVM_PLA_NOWAIT; if (!async) { swmapflags |= UVMPAGER_MAPIN_WAITOK; plaflags = UVM_PLA_WAITOK; } if (uvm_swap_allocpages(tpps, npages, plaflags)) { pool_put(&bufpool, bp); uvm_pagermapout(kva, npages); return (VM_PAGER_AGAIN); } bouncekva = uvm_pagermapin(tpps, npages, swmapflags); if (bouncekva == 0) { pool_put(&bufpool, bp); uvm_pagermapout(kva, npages); uvm_swap_freepages(tpps, npages); return (VM_PAGER_AGAIN); } } /* encrypt to swap */ if (write && bounce) { int i, opages; caddr_t src, dst; u_int64_t block; src = (caddr_t) kva; dst = (caddr_t) bouncekva; block = startblk; for (i = 0; i < npages; i++) { #ifdef UVM_SWAP_ENCRYPT struct swap_key *key; if (encrypt) { key = SWD_KEY(sdp, startslot + i); SWAP_KEY_GET(sdp, key); /* add reference */ swap_encrypt(key, src, dst, block, PAGE_SIZE); block += btodb(PAGE_SIZE); } else { #else { #endif /* UVM_SWAP_ENCRYPT */ memcpy(dst, src, PAGE_SIZE); } /* this just tells async callbacks to free */ atomic_setbits_int(&tpps[i]->pg_flags, PQ_ENCRYPT); src += PAGE_SIZE; dst += PAGE_SIZE; } uvm_pagermapout(kva, npages); /* dispose of pages we dont use anymore */ opages = npages; uvm_pager_dropcluster(NULL, NULL, pps, &opages, PGO_PDFREECLUST); kva = bouncekva; } /* * prevent ASYNC reads. * uvm_swap_io is only called from uvm_swap_get, uvm_swap_get * assumes that all gets are SYNCIO. Just make sure here. * XXXARTUBC - might not be true anymore. */ if (!write) { flags &= ~B_ASYNC; async = 0; } /* * fill in the bp. we currently route our i/o through * /dev/drum's vnode [swapdev_vp]. */ bp->b_flags = B_BUSY | B_NOCACHE | B_RAW | (flags & (B_READ|B_ASYNC)); bp->b_proc = &proc0; /* XXX */ bp->b_vnbufs.le_next = NOLIST; if (bounce) bp->b_data = (caddr_t)bouncekva; else bp->b_data = (caddr_t)kva; bp->b_bq = NULL; bp->b_blkno = startblk; s = splbio(); bp->b_vp = NULL; buf_replacevnode(bp, swapdev_vp); splx(s); bp->b_bufsize = bp->b_bcount = (long)npages << PAGE_SHIFT; /* * for pageouts we must set "dirtyoff" [NFS client code needs it]. * and we bump v_numoutput (counter of number of active outputs). */ if (write) { bp->b_dirtyoff = 0; bp->b_dirtyend = npages << PAGE_SHIFT; #ifdef UVM_SWAP_ENCRYPT /* mark the pages in the drum for decryption */ if (swap_encrypt_initialized) uvm_swap_markdecrypt(sdp, startslot, npages, encrypt); #endif s = splbio(); swapdev_vp->v_numoutput++; splx(s); } /* for async ops we must set up the iodone handler. */ if (async) { bp->b_flags |= B_CALL | (pdaemon ? B_PDAEMON : 0); bp->b_iodone = uvm_aio_biodone; } /* now we start the I/O, and if async, return. */ VOP_STRATEGY(bp->b_vp, bp); if (async) return (VM_PAGER_PEND); /* must be sync i/o. wait for it to finish */ (void) biowait(bp); result = (bp->b_flags & B_ERROR) ? VM_PAGER_ERROR : VM_PAGER_OK; /* decrypt swap */ if (!write && !(bp->b_flags & B_ERROR)) { int i; caddr_t data = (caddr_t)kva; caddr_t dst = (caddr_t)kva; u_int64_t block = startblk; if (bounce) data = (caddr_t)bouncekva; for (i = 0; i < npages; i++) { #ifdef UVM_SWAP_ENCRYPT struct swap_key *key; /* Check if we need to decrypt */ if (swap_encrypt_initialized && uvm_swap_needdecrypt(sdp, startslot + i)) { key = SWD_KEY(sdp, startslot + i); if (key->refcount == 0) { result = VM_PAGER_ERROR; break; } swap_decrypt(key, data, dst, block, PAGE_SIZE); } else if (bounce) { #else if (bounce) { #endif memcpy(dst, data, PAGE_SIZE); } data += PAGE_SIZE; dst += PAGE_SIZE; block += btodb(PAGE_SIZE); } if (bounce) uvm_pagermapout(bouncekva, npages); } /* kill the pager mapping */ uvm_pagermapout(kva, npages); /* Not anymore needed, free after encryption/bouncing */ if (!write && bounce) uvm_swap_freepages(tpps, npages); /* now dispose of the buf */ s = splbio(); if (bp->b_vp) brelvp(bp); if (write && bp->b_vp) vwakeup(bp->b_vp); pool_put(&bufpool, bp); splx(s); /* finally return. */ return (result); } void swapmount(void) { struct swapdev *sdp; struct swappri *spp; struct vnode *vp; dev_t swap_dev = swdevt[0].sw_dev; char *nam; char path[MNAMELEN + 1]; if (swap_dev == NODEV) return; rw_enter_write(&swap_syscall_lock); #if defined(NFSCLIENT) if (swap_dev == NETDEV) { extern struct nfs_diskless nfs_diskless; snprintf(path, sizeof(path), "%s", nfs_diskless.nd_swap.ndm_host); vp = nfs_diskless.sw_vp; goto gotit; } else #endif if (bdevvp(swap_dev, &vp)) { rw_exit_write(&swap_syscall_lock); return; } /* Construct a potential path to swap */ if ((nam = findblkname(major(swap_dev)))) snprintf(path, sizeof(path), "/dev/%s%d%c", nam, DISKUNIT(swap_dev), 'a' + DISKPART(swap_dev)); else snprintf(path, sizeof(path), "blkdev0x%x", swap_dev); #if defined(NFSCLIENT) gotit: #endif sdp = malloc(sizeof(*sdp), M_VMSWAP, M_WAITOK|M_ZERO); spp = malloc(sizeof(*spp), M_VMSWAP, M_WAITOK); sdp->swd_flags = SWF_FAKE; sdp->swd_dev = swap_dev; sdp->swd_pathlen = strlen(path) + 1; sdp->swd_path = malloc(sdp->swd_pathlen, M_VMSWAP, M_WAITOK | M_ZERO); strlcpy(sdp->swd_path, path, sdp->swd_pathlen); sdp->swd_vp = vp; mtx_enter(&uvm_swap_data_lock); swaplist_insert(sdp, spp, 0); mtx_leave(&uvm_swap_data_lock); if (swap_on(curproc, sdp)) { mtx_enter(&uvm_swap_data_lock); swaplist_find(vp, 1); swaplist_trim(); vput(sdp->swd_vp); mtx_leave(&uvm_swap_data_lock); rw_exit_write(&swap_syscall_lock); free(sdp->swd_path, M_VMSWAP, sdp->swd_pathlen); free(sdp, M_VMSWAP, sizeof(*sdp)); return; } rw_exit_write(&swap_syscall_lock); } #ifdef HIBERNATE int uvm_hibswap(dev_t dev, u_long *sp, u_long *ep) { struct swapdev *sdp, *swd = NULL; struct swappri *spp; /* no swap devices configured yet? */ if (uvmexp.nswapdev < 1 || dev != swdevt[0].sw_dev) return (1); LIST_FOREACH(spp, &swap_priority, spi_swappri) { TAILQ_FOREACH(sdp, &spp->spi_swapdev, swd_next) { if (sdp->swd_dev == dev) swd = sdp; } } if (swd == NULL || (swd->swd_flags & SWF_ENABLE) == 0) return (1); blist_gapfind(swd->swd_blist, sp, ep); if (*ep - *sp == 0) /* no gap found */ return (1); /* * blist_gapfind returns the gap as [sp,ep[ , * whereas [sp,ep] is expected from uvm_hibswap(). */ *ep -= 1; return (0); } #endif /* HIBERNATE */ #ifdef DDB void swap_print_all(int (*pr)(const char *, ...)) { struct swappri *spp; struct swapdev *sdp; LIST_FOREACH(spp, &swap_priority, spi_swappri) { TAILQ_FOREACH(sdp, &spp->spi_swapdev, swd_next) { #ifdef HIBERNATE u_long bgap = 0, egap = 0; #endif pr("swap %p path \"%s\" flags 0x%x\n", sdp, sdp->swd_path, sdp->swd_flags); blist_print(sdp->swd_blist); #ifdef HIBERNATE if (!uvm_hibswap(sdp->swd_dev, &bgap, &egap)) pr("hibernate gap: [0x%lx, 0x%lx] size=%lu\n", bgap, egap, (egap - bgap + 1)); else pr("hibernate gap: not found\n"); #endif } } } #endif /* DDB */
34 58 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 /* $OpenBSD: toeplitz.c,v 1.10 2021/02/21 02:37:38 dlg Exp $ */ /* * Copyright (c) 2009 The DragonFly Project. All rights reserved. * * This code is derived from software contributed to The DragonFly Project * by Sepherosa Ziehau <sepherosa@gmail.com> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name of The DragonFly Project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific, prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 2019 David Gwynne <dlg@openbsd.org> * Copyright (c) 2020 Theo Buehler <tb@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/sysctl.h> #include <netinet/in.h> #include <net/toeplitz.h> /* * symmetric toeplitz */ static stoeplitz_key stoeplitz_keyseed = STOEPLITZ_KEYSEED; static struct stoeplitz_cache stoeplitz_syskey_cache; const struct stoeplitz_cache *const stoeplitz_cache = &stoeplitz_syskey_cache; /* parity of n16: count (mod 2) of ones in the binary representation. */ int parity(uint16_t n16) { n16 = ((n16 & 0xaaaa) >> 1) ^ (n16 & 0x5555); n16 = ((n16 & 0xcccc) >> 2) ^ (n16 & 0x3333); n16 = ((n16 & 0xf0f0) >> 4) ^ (n16 & 0x0f0f); n16 = ((n16 & 0xff00) >> 8) ^ (n16 & 0x00ff); return (n16); } /* * The Toeplitz matrix obtained from a seed is invertible if and only if the * parity of the seed is 1. Generate such a seed uniformly at random. */ stoeplitz_key stoeplitz_random_seed(void) { stoeplitz_key seed; seed = arc4random() & UINT16_MAX; if (parity(seed) == 0) seed ^= 1; return (seed); } void stoeplitz_init(void) { stoeplitz_keyseed = stoeplitz_random_seed(); stoeplitz_cache_init(&stoeplitz_syskey_cache, stoeplitz_keyseed); } #define NBSK (NBBY * sizeof(stoeplitz_key)) /* * The Toeplitz hash of a 16-bit number considered as a column vector over * the field with two elements is calculated as a matrix multiplication with * a 16x16 circulant Toeplitz matrix T generated by skey. * * The first eight columns H of T generate the remaining eight columns using * the byteswap operation J = swap16: T = [H JH]. Thus, the Toeplitz hash of * n = [hi lo] is computed via the formula T * n = (H * hi) ^ swap16(H * lo). * * Therefore the results H * val for all values of a byte are cached in scache. */ void stoeplitz_cache_init(struct stoeplitz_cache *scache, stoeplitz_key skey) { uint16_t column[NBBY]; unsigned int b, shift, val; bzero(column, sizeof(column)); /* Calculate the first eight columns H of the Toeplitz matrix T. */ for (b = 0; b < NBBY; ++b) column[b] = skey << b | skey >> (NBSK - b); /* Cache the results of H * val for all possible values of a byte. */ for (val = 0; val < 256; ++val) { uint16_t res = 0; for (b = 0; b < NBBY; ++b) { shift = NBBY - b - 1; if (val & (1 << shift)) res ^= column[b]; } scache->bytes[val] = res; } } uint16_t stoeplitz_hash_ip4(const struct stoeplitz_cache *scache, in_addr_t faddr, in_addr_t laddr) { return (stoeplitz_hash_n32(scache, faddr ^ laddr)); } uint16_t stoeplitz_hash_ip4port(const struct stoeplitz_cache *scache, in_addr_t faddr, in_addr_t laddr, in_port_t fport, in_port_t lport) { return (stoeplitz_hash_n32(scache, faddr ^ laddr ^ fport ^ lport)); } #ifdef INET6 uint16_t stoeplitz_hash_ip6(const struct stoeplitz_cache *scache, const struct in6_addr *faddr6, const struct in6_addr *laddr6) { uint32_t n32 = 0; size_t i; for (i = 0; i < nitems(faddr6->s6_addr32); i++) n32 ^= faddr6->s6_addr32[i] ^ laddr6->s6_addr32[i]; return (stoeplitz_hash_n32(scache, n32)); } uint16_t stoeplitz_hash_ip6port(const struct stoeplitz_cache *scache, const struct in6_addr *faddr6, const struct in6_addr *laddr6, in_port_t fport, in_port_t lport) { uint32_t n32 = 0; size_t i; for (i = 0; i < nitems(faddr6->s6_addr32); i++) n32 ^= faddr6->s6_addr32[i] ^ laddr6->s6_addr32[i]; n32 ^= fport ^ lport; return (stoeplitz_hash_n32(scache, n32)); } #endif /* INET6 */ uint16_t stoeplitz_hash_eaddr(const struct stoeplitz_cache *scache, const uint8_t ea[static 6]) { const uint16_t *ea16 = (const uint16_t *)ea; return (stoeplitz_hash_n16(scache, ea16[0] ^ ea16[1] ^ ea16[2])); } void stoeplitz_to_key(void *key, size_t klen) { uint8_t *k = key; uint16_t skey = htons(stoeplitz_keyseed); size_t i; KASSERT((klen % 2) == 0); for (i = 0; i < klen; i += sizeof(skey)) { k[i + 0] = skey >> 8; k[i + 1] = skey; } }
520 522 518 88 88 88 88 88 88 119 119 86 86 32 32 32 32 248 231 189 19 246 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 /* $OpenBSD: ffs_subr.c,v 1.34 2021/10/20 06:35:39 semarie Exp $ */ /* $NetBSD: ffs_subr.c,v 1.6 1996/03/17 02:16:23 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ffs_subr.c 8.2 (Berkeley) 9/21/93 */ #include <sys/param.h> #include <ufs/ffs/fs.h> #ifdef _KERNEL #include <sys/systm.h> #include <sys/vnode.h> #include <sys/mount.h> #include <sys/buf.h> #include <ufs/ufs/quota.h> #include <ufs/ufs/inode.h> #include <ufs/ufs/ufsmount.h> #include <ufs/ufs/ufs_extern.h> #include <ufs/ffs/ffs_extern.h> /* * Return buffer with the contents of block "offset" from the beginning of * directory "ip". If "res" is non-zero, fill it in with a pointer to the * remaining space in the directory. */ int ffs_bufatoff(struct inode *ip, off_t offset, char **res, struct buf **bpp) { struct fs *fs; struct vnode *vp; struct buf *bp; daddr_t lbn; int bsize, error; vp = ITOV(ip); fs = ip->i_fs; lbn = lblkno(fs, offset); bsize = blksize(fs, ip, lbn); *bpp = NULL; if ((error = bread(vp, lbn, fs->fs_bsize, &bp)) != 0) { brelse(bp); return (error); } buf_adjcnt(bp, bsize); if (res) *res = (char *)bp->b_data + blkoff(fs, offset); *bpp = bp; return (0); } #else /* Prototypes for userland */ void ffs_fragacct(struct fs *, int, int32_t[], int); int ffs_isfreeblock(struct fs *, u_char *, daddr_t); int ffs_isblock(struct fs *, u_char *, daddr_t); void ffs_clrblock(struct fs *, u_char *, daddr_t); void ffs_setblock(struct fs *, u_char *, daddr_t); __dead void panic(const char *, ...); #endif /* * Update the frsum fields to reflect addition or deletion * of some frags. */ void ffs_fragacct(struct fs *fs, int fragmap, int32_t fraglist[], int cnt) { int inblk; int field, subfield; int siz, pos; inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; fragmap <<= 1; for (siz = 1; siz < fs->fs_frag; siz++) { if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) continue; field = around[siz]; subfield = inside[siz]; for (pos = siz; pos <= fs->fs_frag; pos++) { if ((fragmap & field) == subfield) { fraglist[siz] += cnt; pos += siz; field <<= siz; subfield <<= siz; } field <<= 1; subfield <<= 1; } } } #if defined(_KERNEL) && defined(DIAGNOSTIC) void ffs_checkoverlap(struct buf *bp, struct inode *ip) { daddr_t start, last; struct vnode *vp; struct buf *ep; start = bp->b_blkno; last = start + btodb(bp->b_bcount) - 1; LIST_FOREACH(ep, &bufhead, b_list) { if (ep == bp || (ep->b_flags & B_INVAL) || ep->b_vp == NULLVP) continue; if (VOP_BMAP(ep->b_vp, 0, &vp, NULL, NULL)) continue; if (vp != ip->i_devvp) continue; /* look for overlap */ if (ep->b_bcount == 0 || ep->b_blkno > last || ep->b_blkno + btodb(ep->b_bcount) <= start) continue; vprint("Disk overlap", vp); (void)printf("\tstart %lld, end %lld overlap start %llu, " "end %llu\n", (long long)start, (long long)last, (long long)ep->b_blkno, (long long)(ep->b_blkno + btodb(ep->b_bcount) - 1)); panic("Disk buffer overlap"); } } #endif /* DIAGNOSTIC */ /* * block operations * * check if a block is available */ int ffs_isblock(struct fs *fs, u_char *cp, daddr_t h) { u_char mask; switch (fs->fs_frag) { default: case 8: return (cp[h] == 0xff); case 4: mask = 0x0f << ((h & 0x1) << 2); return ((cp[h >> 1] & mask) == mask); case 2: mask = 0x03 << ((h & 0x3) << 1); return ((cp[h >> 2] & mask) == mask); case 1: mask = 0x01 << (h & 0x7); return ((cp[h >> 3] & mask) == mask); } } /* * take a block out of the map */ void ffs_clrblock(struct fs *fs, u_char *cp, daddr_t h) { switch (fs->fs_frag) { default: case 8: cp[h] = 0; return; case 4: cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); return; case 2: cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); return; case 1: cp[h >> 3] &= ~(0x01 << (h & 0x7)); return; } } /* * put a block into the map */ void ffs_setblock(struct fs *fs, u_char *cp, daddr_t h) { switch (fs->fs_frag) { default: case 8: cp[h] = 0xff; return; case 4: cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); return; case 2: cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); return; case 1: cp[h >> 3] |= (0x01 << (h & 0x7)); return; } } /* * check if a block is free */ int ffs_isfreeblock(struct fs *fs, u_char *cp, daddr_t h) { switch (fs->fs_frag) { default: case 8: return (cp[h] == 0); case 4: return ((cp[h >> 1] & (0x0f << ((h & 0x1) << 2))) == 0); case 2: return ((cp[h >> 2] & (0x03 << ((h & 0x3) << 1))) == 0); case 1: return ((cp[h >> 3] & (0x01 << (h & 0x7))) == 0); } } #ifdef _KERNEL /* * Initialize the vnode associated with a new inode, handle aliased * vnodes. */ int ffs_vinit(struct mount *mntp, struct vnode **vpp) { struct inode *ip; struct vnode *vp, *nvp; struct timeval mtv; vp = *vpp; ip = VTOI(vp); switch(vp->v_type = IFTOVT(DIP(ip, mode))) { case VCHR: case VBLK: vp->v_op = &ffs_specvops; if ((nvp = checkalias(vp, DIP(ip, rdev), mntp)) != NULL) { /* * Discard unneeded vnode, but save its inode. * Note that the lock is carried over in the inode * to the replacement vnode. */ nvp->v_data = vp->v_data; vp->v_data = NULL; vp->v_op = &spec_vops; #ifdef VFSLCKDEBUG vp->v_flag &= ~VLOCKSWORK; #endif vrele(vp); vgone(vp); /* * Reinitialize aliased inode. */ vp = nvp; ip->i_vnode = vp; } break; case VFIFO: #ifdef FIFO vp->v_op = &ffs_fifovops; break; #else return (EOPNOTSUPP); #endif case VNON: case VBAD: case VSOCK: case VLNK: case VDIR: case VREG: break; } if (ip->i_number == ROOTINO) vp->v_flag |= VROOT; /* * Initialize modrev times */ getmicrouptime(&mtv); ip->i_modrev = (u_quad_t)mtv.tv_sec << 32; ip->i_modrev |= (u_quad_t)mtv.tv_usec * 4294; *vpp = vp; return (0); } #endif /* _KERNEL */
86 1 73 5 76 12 4 32 32 19 29 32 66 66 10 1 1 8 1 1 2 2 4 1 3 33 9 9 1 8 70 6 3 3 2 35 4 32 66 57 14 1 6 1 9 48 43 49 1 34 19 17 20 2 5 20 2 5 20 20 2 24 3 3 2 2 5 5 1 4 27 27 13 3 2 1 2 1 2 1 2 2 66 66 62 7 66 3 65 6 8 9 64 3 38 1 37 2 2 3 4 4 4 3 3 5 5 12 31 39 26 13 75 51 24 4 71 21 4 25 1 22 17 7 21 18 4 4 12 3 14 12 9 21 17 8 30 4 16 11 23 24 22 17 3 15 6 4 8 5 2 6 88 72 18 17 7 7 4 11 5 3 33 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 /* $OpenBSD: uipc_usrreq.c,v 1.206 2024/05/03 17:43:09 mvs Exp $ */ /* $NetBSD: uipc_usrreq.c,v 1.18 1996/02/09 19:00:50 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)uipc_usrreq.c 8.3 (Berkeley) 1/4/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/filedesc.h> #include <sys/domain.h> #include <sys/protosw.h> #include <sys/queue.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/unpcb.h> #include <sys/un.h> #include <sys/namei.h> #include <sys/vnode.h> #include <sys/file.h> #include <sys/stat.h> #include <sys/mbuf.h> #include <sys/task.h> #include <sys/pledge.h> #include <sys/pool.h> #include <sys/rwlock.h> #include <sys/mutex.h> #include <sys/sysctl.h> #include <sys/lock.h> #include <sys/refcnt.h> #include "kcov.h" #if NKCOV > 0 #include <sys/kcov.h> #endif /* * Locks used to protect global data and struct members: * I immutable after creation * D unp_df_lock * G unp_gc_lock * M unp_ino_mtx * R unp_rights_mtx * a atomic * s socket lock */ struct rwlock unp_df_lock = RWLOCK_INITIALIZER("unpdflk"); struct rwlock unp_gc_lock = RWLOCK_INITIALIZER("unpgclk"); struct mutex unp_rights_mtx = MUTEX_INITIALIZER(IPL_SOFTNET); struct mutex unp_ino_mtx = MUTEX_INITIALIZER(IPL_SOFTNET); /* * Stack of sets of files that were passed over a socket but were * not received and need to be closed. */ struct unp_deferral { SLIST_ENTRY(unp_deferral) ud_link; /* [D] */ int ud_n; /* [I] */ /* followed by ud_n struct fdpass */ struct fdpass ud_fp[]; /* [I] */ }; void uipc_setaddr(const struct unpcb *, struct mbuf *); void unp_discard(struct fdpass *, int); void unp_remove_gcrefs(struct fdpass *, int); void unp_restore_gcrefs(struct fdpass *, int); void unp_scan(struct mbuf *, void (*)(struct fdpass *, int)); int unp_nam2sun(struct mbuf *, struct sockaddr_un **, size_t *); static inline void unp_ref(struct unpcb *); static inline void unp_rele(struct unpcb *); struct socket *unp_solock_peer(struct socket *); struct pool unpcb_pool; struct task unp_gc_task = TASK_INITIALIZER(unp_gc, NULL); /* * Unix communications domain. * * TODO: * RDM * rethink name space problems * need a proper out-of-band */ const struct sockaddr sun_noname = { sizeof(sun_noname), AF_UNIX }; /* [G] list of all UNIX domain sockets, for unp_gc() */ LIST_HEAD(unp_head, unpcb) unp_head = LIST_HEAD_INITIALIZER(unp_head); /* [D] list of sets of files that were sent over sockets that are now closed */ SLIST_HEAD(,unp_deferral) unp_deferred = SLIST_HEAD_INITIALIZER(unp_deferred); ino_t unp_ino; /* [U] prototype for fake inode numbers */ int unp_rights; /* [R] file descriptors in flight */ int unp_defer; /* [G] number of deferred fp to close by the GC task */ int unp_gcing; /* [G] GC task currently running */ const struct pr_usrreqs uipc_usrreqs = { .pru_attach = uipc_attach, .pru_detach = uipc_detach, .pru_bind = uipc_bind, .pru_listen = uipc_listen, .pru_connect = uipc_connect, .pru_accept = uipc_accept, .pru_disconnect = uipc_disconnect, .pru_shutdown = uipc_shutdown, .pru_rcvd = uipc_rcvd, .pru_send = uipc_send, .pru_abort = uipc_abort, .pru_sense = uipc_sense, .pru_sockaddr = uipc_sockaddr, .pru_peeraddr = uipc_peeraddr, .pru_connect2 = uipc_connect2, }; const struct pr_usrreqs uipc_dgram_usrreqs = { .pru_attach = uipc_attach, .pru_detach = uipc_detach, .pru_bind = uipc_bind, .pru_listen = uipc_listen, .pru_connect = uipc_connect, .pru_disconnect = uipc_disconnect, .pru_shutdown = uipc_dgram_shutdown, .pru_send = uipc_dgram_send, .pru_sense = uipc_sense, .pru_sockaddr = uipc_sockaddr, .pru_peeraddr = uipc_peeraddr, .pru_connect2 = uipc_connect2, }; void unp_init(void) { pool_init(&unpcb_pool, sizeof(struct unpcb), 0, IPL_SOFTNET, 0, "unpcb", NULL); } static inline void unp_ref(struct unpcb *unp) { refcnt_take(&unp->unp_refcnt); } static inline void unp_rele(struct unpcb *unp) { refcnt_rele_wake(&unp->unp_refcnt); } struct socket * unp_solock_peer(struct socket *so) { struct unpcb *unp, *unp2; struct socket *so2; unp = so->so_pcb; again: if ((unp2 = unp->unp_conn) == NULL) return NULL; so2 = unp2->unp_socket; if (so < so2) solock(so2); else if (so > so2) { unp_ref(unp2); sounlock(so); solock(so2); solock(so); /* Datagram socket could be reconnected due to re-lock. */ if (unp->unp_conn != unp2) { sounlock(so2); unp_rele(unp2); goto again; } unp_rele(unp2); } return so2; } void uipc_setaddr(const struct unpcb *unp, struct mbuf *nam) { if (unp != NULL && unp->unp_addr != NULL) { nam->m_len = unp->unp_addr->m_len; memcpy(mtod(nam, caddr_t), mtod(unp->unp_addr, caddr_t), nam->m_len); } else { nam->m_len = sizeof(sun_noname); memcpy(mtod(nam, struct sockaddr *), &sun_noname, nam->m_len); } } /* * Both send and receive buffers are allocated PIPSIZ bytes of buffering * for stream sockets, although the total for sender and receiver is * actually only PIPSIZ. * Datagram sockets really use the sendspace as the maximum datagram size, * and don't really want to reserve the sendspace. Their recvspace should * be large enough for at least one max-size datagram plus address. */ #define PIPSIZ 8192 u_int unpst_sendspace = PIPSIZ; u_int unpst_recvspace = PIPSIZ; u_int unpsq_sendspace = PIPSIZ; u_int unpsq_recvspace = PIPSIZ; u_int unpdg_sendspace = 2*1024; /* really max datagram size */ u_int unpdg_recvspace = 16*1024; const struct sysctl_bounded_args unpstctl_vars[] = { { UNPCTL_RECVSPACE, &unpst_recvspace, 0, SB_MAX }, { UNPCTL_SENDSPACE, &unpst_sendspace, 0, SB_MAX }, }; const struct sysctl_bounded_args unpsqctl_vars[] = { { UNPCTL_RECVSPACE, &unpsq_recvspace, 0, SB_MAX }, { UNPCTL_SENDSPACE, &unpsq_sendspace, 0, SB_MAX }, }; const struct sysctl_bounded_args unpdgctl_vars[] = { { UNPCTL_RECVSPACE, &unpdg_recvspace, 0, SB_MAX }, { UNPCTL_SENDSPACE, &unpdg_sendspace, 0, SB_MAX }, }; int uipc_attach(struct socket *so, int proto, int wait) { struct unpcb *unp; int error; if (so->so_pcb) return EISCONN; if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { switch (so->so_type) { case SOCK_STREAM: error = soreserve(so, unpst_sendspace, unpst_recvspace); break; case SOCK_SEQPACKET: error = soreserve(so, unpsq_sendspace, unpsq_recvspace); break; case SOCK_DGRAM: error = soreserve(so, unpdg_sendspace, unpdg_recvspace); break; default: panic("unp_attach"); } if (error) return (error); } unp = pool_get(&unpcb_pool, (wait == M_WAIT ? PR_WAITOK : PR_NOWAIT) | PR_ZERO); if (unp == NULL) return (ENOBUFS); refcnt_init(&unp->unp_refcnt); unp->unp_socket = so; so->so_pcb = unp; getnanotime(&unp->unp_ctime); rw_enter_write(&unp_gc_lock); LIST_INSERT_HEAD(&unp_head, unp, unp_link); rw_exit_write(&unp_gc_lock); return (0); } int uipc_detach(struct socket *so) { struct unpcb *unp = sotounpcb(so); if (unp == NULL) return (EINVAL); unp_detach(unp); return (0); } int uipc_bind(struct socket *so, struct mbuf *nam, struct proc *p) { struct unpcb *unp = sotounpcb(so); struct sockaddr_un *soun; struct mbuf *nam2; struct vnode *vp; struct vattr vattr; int error; struct nameidata nd; size_t pathlen; if (unp->unp_flags & (UNP_BINDING | UNP_CONNECTING)) return (EINVAL); if (unp->unp_vnode != NULL) return (EINVAL); if ((error = unp_nam2sun(nam, &soun, &pathlen))) return (error); unp->unp_flags |= UNP_BINDING; /* * Enforce `i_lock' -> `solock' because fifo subsystem * requires it. The socket can't be closed concurrently * because the file descriptor reference is still held. */ sounlock(unp->unp_socket); nam2 = m_getclr(M_WAITOK, MT_SONAME); nam2->m_len = sizeof(struct sockaddr_un); memcpy(mtod(nam2, struct sockaddr_un *), soun, offsetof(struct sockaddr_un, sun_path) + pathlen); /* No need to NUL terminate: m_getclr() returns zero'd mbufs. */ soun = mtod(nam2, struct sockaddr_un *); /* Fixup sun_len to keep it in sync with m_len. */ soun->sun_len = nam2->m_len; NDINIT(&nd, CREATE, NOFOLLOW | LOCKPARENT, UIO_SYSSPACE, soun->sun_path, p); nd.ni_pledge = PLEDGE_UNIX; nd.ni_unveil = UNVEIL_CREATE; KERNEL_LOCK(); /* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */ error = namei(&nd); if (error != 0) { m_freem(nam2); solock(unp->unp_socket); goto out; } vp = nd.ni_vp; if (vp != NULL) { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); if (nd.ni_dvp == vp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); vrele(vp); m_freem(nam2); error = EADDRINUSE; solock(unp->unp_socket); goto out; } VATTR_NULL(&vattr); vattr.va_type = VSOCK; vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask; error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); vput(nd.ni_dvp); if (error) { m_freem(nam2); solock(unp->unp_socket); goto out; } solock(unp->unp_socket); unp->unp_addr = nam2; vp = nd.ni_vp; vp->v_socket = unp->unp_socket; unp->unp_vnode = vp; unp->unp_connid.uid = p->p_ucred->cr_uid; unp->unp_connid.gid = p->p_ucred->cr_gid; unp->unp_connid.pid = p->p_p->ps_pid; unp->unp_flags |= UNP_FEIDSBIND; VOP_UNLOCK(vp); out: KERNEL_UNLOCK(); unp->unp_flags &= ~UNP_BINDING; return (error); } int uipc_listen(struct socket *so) { struct unpcb *unp = sotounpcb(so); if (unp->unp_flags & (UNP_BINDING | UNP_CONNECTING)) return (EINVAL); if (unp->unp_vnode == NULL) return (EINVAL); return (0); } int uipc_connect(struct socket *so, struct mbuf *nam) { return unp_connect(so, nam, curproc); } int uipc_accept(struct socket *so, struct mbuf *nam) { struct socket *so2; struct unpcb *unp = sotounpcb(so); /* * Pass back name of connected socket, if it was bound and * we are still connected (our peer may have closed already!). */ so2 = unp_solock_peer(so); uipc_setaddr(unp->unp_conn, nam); if (so2 != NULL && so2 != so) sounlock(so2); return (0); } int uipc_disconnect(struct socket *so) { struct unpcb *unp = sotounpcb(so); unp_disconnect(unp); return (0); } int uipc_shutdown(struct socket *so) { struct unpcb *unp = sotounpcb(so); struct socket *so2; socantsendmore(so); if (unp->unp_conn != NULL) { so2 = unp->unp_conn->unp_socket; socantrcvmore(so2); } return (0); } int uipc_dgram_shutdown(struct socket *so) { socantsendmore(so); return (0); } void uipc_rcvd(struct socket *so) { struct unpcb *unp = sotounpcb(so); struct socket *so2; if (unp->unp_conn == NULL) return; so2 = unp->unp_conn->unp_socket; /* * Adjust backpressure on sender * and wakeup any waiting to write. */ mtx_enter(&so->so_rcv.sb_mtx); mtx_enter(&so2->so_snd.sb_mtx); so2->so_snd.sb_mbcnt = so->so_rcv.sb_mbcnt; so2->so_snd.sb_cc = so->so_rcv.sb_cc; mtx_leave(&so2->so_snd.sb_mtx); mtx_leave(&so->so_rcv.sb_mtx); sowwakeup(so2); } int uipc_send(struct socket *so, struct mbuf *m, struct mbuf *nam, struct mbuf *control) { struct unpcb *unp = sotounpcb(so); struct socket *so2; int error = 0, dowakeup = 0; if (control) { sounlock(so); error = unp_internalize(control, curproc); solock(so); if (error) goto out; } if (unp->unp_conn == NULL) { error = ENOTCONN; goto dispose; } so2 = unp->unp_conn->unp_socket; /* * Send to paired receive port, and then raise * send buffer counts to maintain backpressure. * Wake up readers. */ /* * sbappend*() should be serialized together * with so_snd modification. */ mtx_enter(&so2->so_rcv.sb_mtx); mtx_enter(&so->so_snd.sb_mtx); if (so->so_snd.sb_state & SS_CANTSENDMORE) { mtx_leave(&so->so_snd.sb_mtx); mtx_leave(&so2->so_rcv.sb_mtx); error = EPIPE; goto dispose; } if (control) { if (sbappendcontrol(so2, &so2->so_rcv, m, control)) { control = NULL; } else { mtx_leave(&so->so_snd.sb_mtx); mtx_leave(&so2->so_rcv.sb_mtx); error = ENOBUFS; goto dispose; } } else if (so->so_type == SOCK_SEQPACKET) sbappendrecord(so2, &so2->so_rcv, m); else sbappend(so2, &so2->so_rcv, m); so->so_snd.sb_mbcnt = so2->so_rcv.sb_mbcnt; so->so_snd.sb_cc = so2->so_rcv.sb_cc; if (so2->so_rcv.sb_cc > 0) dowakeup = 1; mtx_leave(&so->so_snd.sb_mtx); mtx_leave(&so2->so_rcv.sb_mtx); if (dowakeup) sorwakeup(so2); m = NULL; dispose: /* we need to undo unp_internalize in case of errors */ if (control && error) unp_dispose(control); out: m_freem(control); m_freem(m); return (error); } int uipc_dgram_send(struct socket *so, struct mbuf *m, struct mbuf *nam, struct mbuf *control) { struct unpcb *unp = sotounpcb(so); struct socket *so2; const struct sockaddr *from; int error = 0, dowakeup = 0; if (control) { sounlock(so); error = unp_internalize(control, curproc); solock(so); if (error) goto out; } if (nam) { if (unp->unp_conn) { error = EISCONN; goto dispose; } error = unp_connect(so, nam, curproc); if (error) goto dispose; } if (unp->unp_conn == NULL) { if (nam != NULL) error = ECONNREFUSED; else error = ENOTCONN; goto dispose; } so2 = unp->unp_conn->unp_socket; if (unp->unp_addr) from = mtod(unp->unp_addr, struct sockaddr *); else from = &sun_noname; mtx_enter(&so2->so_rcv.sb_mtx); if (sbappendaddr(so2, &so2->so_rcv, from, m, control)) { dowakeup = 1; m = NULL; control = NULL; } else error = ENOBUFS; mtx_leave(&so2->so_rcv.sb_mtx); if (dowakeup) sorwakeup(so2); if (nam) unp_disconnect(unp); dispose: /* we need to undo unp_internalize in case of errors */ if (control && error) unp_dispose(control); out: m_freem(control); m_freem(m); return (error); } void uipc_abort(struct socket *so) { struct unpcb *unp = sotounpcb(so); unp_detach(unp); sofree(so, 0); } int uipc_sense(struct socket *so, struct stat *sb) { struct unpcb *unp = sotounpcb(so); sb->st_blksize = so->so_snd.sb_hiwat; sb->st_dev = NODEV; mtx_enter(&unp_ino_mtx); if (unp->unp_ino == 0) unp->unp_ino = unp_ino++; mtx_leave(&unp_ino_mtx); sb->st_atim.tv_sec = sb->st_mtim.tv_sec = sb->st_ctim.tv_sec = unp->unp_ctime.tv_sec; sb->st_atim.tv_nsec = sb->st_mtim.tv_nsec = sb->st_ctim.tv_nsec = unp->unp_ctime.tv_nsec; sb->st_ino = unp->unp_ino; return (0); } int uipc_sockaddr(struct socket *so, struct mbuf *nam) { struct unpcb *unp = sotounpcb(so); uipc_setaddr(unp, nam); return (0); } int uipc_peeraddr(struct socket *so, struct mbuf *nam) { struct unpcb *unp = sotounpcb(so); struct socket *so2; so2 = unp_solock_peer(so); uipc_setaddr(unp->unp_conn, nam); if (so2 != NULL && so2 != so) sounlock(so2); return (0); } int uipc_connect2(struct socket *so, struct socket *so2) { struct unpcb *unp = sotounpcb(so), *unp2; int error; if ((error = unp_connect2(so, so2))) return (error); unp->unp_connid.uid = curproc->p_ucred->cr_uid; unp->unp_connid.gid = curproc->p_ucred->cr_gid; unp->unp_connid.pid = curproc->p_p->ps_pid; unp->unp_flags |= UNP_FEIDS; unp2 = sotounpcb(so2); unp2->unp_connid.uid = curproc->p_ucred->cr_uid; unp2->unp_connid.gid = curproc->p_ucred->cr_gid; unp2->unp_connid.pid = curproc->p_p->ps_pid; unp2->unp_flags |= UNP_FEIDS; return (0); } int uipc_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int *valp = &unp_defer; /* All sysctl names at this level are terminal. */ switch (name[0]) { case SOCK_STREAM: if (namelen != 2) return (ENOTDIR); return sysctl_bounded_arr(unpstctl_vars, nitems(unpstctl_vars), name + 1, namelen - 1, oldp, oldlenp, newp, newlen); case SOCK_SEQPACKET: if (namelen != 2) return (ENOTDIR); return sysctl_bounded_arr(unpsqctl_vars, nitems(unpsqctl_vars), name + 1, namelen - 1, oldp, oldlenp, newp, newlen); case SOCK_DGRAM: if (namelen != 2) return (ENOTDIR); return sysctl_bounded_arr(unpdgctl_vars, nitems(unpdgctl_vars), name + 1, namelen - 1, oldp, oldlenp, newp, newlen); case NET_UNIX_INFLIGHT: valp = &unp_rights; /* FALLTHROUGH */ case NET_UNIX_DEFERRED: if (namelen != 1) return (ENOTDIR); return sysctl_rdint(oldp, oldlenp, newp, *valp); default: return (ENOPROTOOPT); } } void unp_detach(struct unpcb *unp) { struct socket *so = unp->unp_socket; struct vnode *vp = unp->unp_vnode; struct unpcb *unp2; unp->unp_vnode = NULL; /* * Enforce `i_lock' -> `solock()' lock order. */ sounlock(so); rw_enter_write(&unp_gc_lock); LIST_REMOVE(unp, unp_link); rw_exit_write(&unp_gc_lock); if (vp != NULL) { VOP_LOCK(vp, LK_EXCLUSIVE); vp->v_socket = NULL; KERNEL_LOCK(); vput(vp); KERNEL_UNLOCK(); } solock(so); if (unp->unp_conn != NULL) { /* * Datagram socket could be connected to itself. * Such socket will be disconnected here. */ unp_disconnect(unp); } while ((unp2 = SLIST_FIRST(&unp->unp_refs)) != NULL) { struct socket *so2 = unp2->unp_socket; if (so < so2) solock(so2); else { unp_ref(unp2); sounlock(so); solock(so2); solock(so); if (unp2->unp_conn != unp) { /* `unp2' was disconnected due to re-lock. */ sounlock(so2); unp_rele(unp2); continue; } unp_rele(unp2); } unp2->unp_conn = NULL; SLIST_REMOVE(&unp->unp_refs, unp2, unpcb, unp_nextref); so2->so_error = ECONNRESET; so2->so_state &= ~SS_ISCONNECTED; sounlock(so2); } sounlock(so); refcnt_finalize(&unp->unp_refcnt, "unpfinal"); solock(so); soisdisconnected(so); so->so_pcb = NULL; m_freem(unp->unp_addr); pool_put(&unpcb_pool, unp); if (unp_rights) task_add(systqmp, &unp_gc_task); } int unp_connect(struct socket *so, struct mbuf *nam, struct proc *p) { struct sockaddr_un *soun; struct vnode *vp; struct socket *so2, *so3; struct unpcb *unp, *unp2, *unp3; struct nameidata nd; int error; unp = sotounpcb(so); if (unp->unp_flags & (UNP_BINDING | UNP_CONNECTING)) return (EISCONN); if ((error = unp_nam2sun(nam, &soun, NULL))) return (error); NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, soun->sun_path, p); nd.ni_pledge = PLEDGE_UNIX; nd.ni_unveil = UNVEIL_WRITE; unp->unp_flags |= UNP_CONNECTING; /* * Enforce `i_lock' -> `solock' because fifo subsystem * requires it. The socket can't be closed concurrently * because the file descriptor reference is still held. */ sounlock(so); KERNEL_LOCK(); error = namei(&nd); if (error != 0) goto unlock; vp = nd.ni_vp; if (vp->v_type != VSOCK) { error = ENOTSOCK; goto put; } if ((error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) != 0) goto put; so2 = vp->v_socket; if (so2 == NULL) { error = ECONNREFUSED; goto put; } if (so->so_type != so2->so_type) { error = EPROTOTYPE; goto put; } if (so->so_proto->pr_flags & PR_CONNREQUIRED) { solock(so2); if ((so2->so_options & SO_ACCEPTCONN) == 0 || (so3 = sonewconn(so2, 0, M_WAIT)) == NULL) { error = ECONNREFUSED; } sounlock(so2); if (error != 0) goto put; /* * Since `so2' is protected by vnode(9) lock, `so3' * can't be PRU_ABORT'ed here. */ solock_pair(so, so3); unp2 = sotounpcb(so2); unp3 = sotounpcb(so3); /* * `unp_addr', `unp_connid' and 'UNP_FEIDSBIND' flag * are immutable since we set them in uipc_bind(). */ if (unp2->unp_addr) unp3->unp_addr = m_copym(unp2->unp_addr, 0, M_COPYALL, M_NOWAIT); unp3->unp_connid.uid = p->p_ucred->cr_uid; unp3->unp_connid.gid = p->p_ucred->cr_gid; unp3->unp_connid.pid = p->p_p->ps_pid; unp3->unp_flags |= UNP_FEIDS; if (unp2->unp_flags & UNP_FEIDSBIND) { unp->unp_connid = unp2->unp_connid; unp->unp_flags |= UNP_FEIDS; } so2 = so3; } else { if (so2 != so) solock_pair(so, so2); else solock(so); } error = unp_connect2(so, so2); sounlock(so); /* * `so2' can't be PRU_ABORT'ed concurrently */ if (so2 != so) sounlock(so2); put: vput(vp); unlock: KERNEL_UNLOCK(); solock(so); unp->unp_flags &= ~UNP_CONNECTING; /* * The peer socket could be closed by concurrent thread * when `so' and `vp' are unlocked. */ if (error == 0 && unp->unp_conn == NULL) error = ECONNREFUSED; return (error); } int unp_connect2(struct socket *so, struct socket *so2) { struct unpcb *unp = sotounpcb(so); struct unpcb *unp2; soassertlocked(so); soassertlocked(so2); if (so2->so_type != so->so_type) return (EPROTOTYPE); unp2 = sotounpcb(so2); unp->unp_conn = unp2; switch (so->so_type) { case SOCK_DGRAM: SLIST_INSERT_HEAD(&unp2->unp_refs, unp, unp_nextref); soisconnected(so); break; case SOCK_STREAM: case SOCK_SEQPACKET: unp2->unp_conn = unp; soisconnected(so); soisconnected(so2); break; default: panic("unp_connect2"); } return (0); } void unp_disconnect(struct unpcb *unp) { struct socket *so2; struct unpcb *unp2; if ((so2 = unp_solock_peer(unp->unp_socket)) == NULL) return; unp2 = unp->unp_conn; unp->unp_conn = NULL; switch (unp->unp_socket->so_type) { case SOCK_DGRAM: SLIST_REMOVE(&unp2->unp_refs, unp, unpcb, unp_nextref); unp->unp_socket->so_state &= ~SS_ISCONNECTED; break; case SOCK_STREAM: case SOCK_SEQPACKET: unp->unp_socket->so_snd.sb_mbcnt = 0; unp->unp_socket->so_snd.sb_cc = 0; soisdisconnected(unp->unp_socket); unp2->unp_conn = NULL; unp2->unp_socket->so_snd.sb_mbcnt = 0; unp2->unp_socket->so_snd.sb_cc = 0; soisdisconnected(unp2->unp_socket); break; } if (so2 != unp->unp_socket) sounlock(so2); } static struct unpcb * fptounp(struct file *fp) { struct socket *so; if (fp->f_type != DTYPE_SOCKET) return (NULL); if ((so = fp->f_data) == NULL) return (NULL); if (so->so_proto->pr_domain != &unixdomain) return (NULL); return (sotounpcb(so)); } int unp_externalize(struct mbuf *rights, socklen_t controllen, int flags) { struct proc *p = curproc; /* XXX */ struct cmsghdr *cm = mtod(rights, struct cmsghdr *); struct filedesc *fdp = p->p_fd; int i, *fds = NULL; struct fdpass *rp; struct file *fp; int nfds, error = 0; /* * This code only works because SCM_RIGHTS is the only supported * control message type on unix sockets. Enforce this here. */ if (cm->cmsg_type != SCM_RIGHTS || cm->cmsg_level != SOL_SOCKET) return EINVAL; nfds = (cm->cmsg_len - CMSG_ALIGN(sizeof(*cm))) / sizeof(struct fdpass); if (controllen < CMSG_ALIGN(sizeof(struct cmsghdr))) controllen = 0; else controllen -= CMSG_ALIGN(sizeof(struct cmsghdr)); if (nfds > controllen / sizeof(int)) { error = EMSGSIZE; goto out; } /* Make sure the recipient should be able to see the descriptors.. */ rp = (struct fdpass *)CMSG_DATA(cm); /* fdp->fd_rdir requires KERNEL_LOCK() */ KERNEL_LOCK(); for (i = 0; i < nfds; i++) { fp = rp->fp; rp++; error = pledge_recvfd(p, fp); if (error) break; /* * No to block devices. If passing a directory, * make sure that it is underneath the root. */ if (fdp->fd_rdir != NULL && fp->f_type == DTYPE_VNODE) { struct vnode *vp = (struct vnode *)fp->f_data; if (vp->v_type == VBLK || (vp->v_type == VDIR && !vn_isunder(vp, fdp->fd_rdir, p))) { error = EPERM; break; } } } KERNEL_UNLOCK(); if (error) goto out; fds = mallocarray(nfds, sizeof(int), M_TEMP, M_WAITOK); fdplock(fdp); restart: /* * First loop -- allocate file descriptor table slots for the * new descriptors. */ rp = ((struct fdpass *)CMSG_DATA(cm)); for (i = 0; i < nfds; i++) { if ((error = fdalloc(p, 0, &fds[i])) != 0) { /* * Back out what we've done so far. */ for (--i; i >= 0; i--) fdremove(fdp, fds[i]); if (error == ENOSPC) { fdexpand(p); goto restart; } fdpunlock(fdp); /* * This is the error that has historically * been returned, and some callers may * expect it. */ error = EMSGSIZE; goto out; } /* * Make the slot reference the descriptor so that * fdalloc() works properly.. We finalize it all * in the loop below. */ mtx_enter(&fdp->fd_fplock); KASSERT(fdp->fd_ofiles[fds[i]] == NULL); fdp->fd_ofiles[fds[i]] = rp->fp; mtx_leave(&fdp->fd_fplock); fdp->fd_ofileflags[fds[i]] = (rp->flags & UF_PLEDGED); if (flags & MSG_CMSG_CLOEXEC) fdp->fd_ofileflags[fds[i]] |= UF_EXCLOSE; rp++; } /* * Keep `fdp' locked to prevent concurrent close() of just * inserted descriptors. Such descriptors could have the only * `f_count' reference which is now shared between control * message and `fdp'. */ /* * Now that adding them has succeeded, update all of the * descriptor passing state. */ rp = (struct fdpass *)CMSG_DATA(cm); for (i = 0; i < nfds; i++) { struct unpcb *unp; fp = rp->fp; rp++; if ((unp = fptounp(fp)) != NULL) { rw_enter_write(&unp_gc_lock); unp->unp_msgcount--; rw_exit_write(&unp_gc_lock); } } fdpunlock(fdp); mtx_enter(&unp_rights_mtx); unp_rights -= nfds; mtx_leave(&unp_rights_mtx); /* * Copy temporary array to message and adjust length, in case of * transition from large struct file pointers to ints. */ memcpy(CMSG_DATA(cm), fds, nfds * sizeof(int)); cm->cmsg_len = CMSG_LEN(nfds * sizeof(int)); rights->m_len = CMSG_LEN(nfds * sizeof(int)); out: if (fds != NULL) free(fds, M_TEMP, nfds * sizeof(int)); if (error) { if (nfds > 0) { /* * No lock required. We are the only `cm' holder. */ rp = ((struct fdpass *)CMSG_DATA(cm)); unp_discard(rp, nfds); } } return (error); } int unp_internalize(struct mbuf *control, struct proc *p) { struct filedesc *fdp = p->p_fd; struct cmsghdr *cm = mtod(control, struct cmsghdr *); struct fdpass *rp; struct file *fp; struct unpcb *unp; int i, error; int nfds, *ip, fd, neededspace; /* * Check for two potential msg_controllen values because * IETF stuck their nose in a place it does not belong. */ if (control->m_len < CMSG_LEN(0) || cm->cmsg_len < CMSG_LEN(0)) return (EINVAL); if (cm->cmsg_type != SCM_RIGHTS || cm->cmsg_level != SOL_SOCKET || !(cm->cmsg_len == control->m_len || control->m_len == CMSG_ALIGN(cm->cmsg_len))) return (EINVAL); nfds = (cm->cmsg_len - CMSG_ALIGN(sizeof(*cm))) / sizeof (int); mtx_enter(&unp_rights_mtx); if (unp_rights + nfds > maxfiles / 10) { mtx_leave(&unp_rights_mtx); return (EMFILE); } unp_rights += nfds; mtx_leave(&unp_rights_mtx); /* Make sure we have room for the struct file pointers */ morespace: neededspace = CMSG_SPACE(nfds * sizeof(struct fdpass)) - control->m_len; if (neededspace > m_trailingspace(control)) { char *tmp; /* if we already have a cluster, the message is just too big */ if (control->m_flags & M_EXT) { error = E2BIG; goto nospace; } /* copy cmsg data temporarily out of the mbuf */ tmp = malloc(control->m_len, M_TEMP, M_WAITOK); memcpy(tmp, mtod(control, caddr_t), control->m_len); /* allocate a cluster and try again */ MCLGET(control, M_WAIT); if ((control->m_flags & M_EXT) == 0) { free(tmp, M_TEMP, control->m_len); error = ENOBUFS; /* allocation failed */ goto nospace; } /* copy the data back into the cluster */ cm = mtod(control, struct cmsghdr *); memcpy(cm, tmp, control->m_len); free(tmp, M_TEMP, control->m_len); goto morespace; } /* adjust message & mbuf to note amount of space actually used. */ cm->cmsg_len = CMSG_LEN(nfds * sizeof(struct fdpass)); control->m_len = CMSG_SPACE(nfds * sizeof(struct fdpass)); ip = ((int *)CMSG_DATA(cm)) + nfds - 1; rp = ((struct fdpass *)CMSG_DATA(cm)) + nfds - 1; fdplock(fdp); for (i = 0; i < nfds; i++) { memcpy(&fd, ip, sizeof fd); ip--; if ((fp = fd_getfile(fdp, fd)) == NULL) { error = EBADF; goto fail; } if (fp->f_count >= FDUP_MAX_COUNT) { error = EDEADLK; goto fail; } error = pledge_sendfd(p, fp); if (error) goto fail; /* kqueue descriptors cannot be copied */ if (fp->f_type == DTYPE_KQUEUE) { error = EINVAL; goto fail; } #if NKCOV > 0 /* kcov descriptors cannot be copied */ if (fp->f_type == DTYPE_VNODE && kcov_vnode(fp->f_data)) { error = EINVAL; goto fail; } #endif rp->fp = fp; rp->flags = fdp->fd_ofileflags[fd] & UF_PLEDGED; rp--; if ((unp = fptounp(fp)) != NULL) { rw_enter_write(&unp_gc_lock); unp->unp_msgcount++; unp->unp_file = fp; rw_exit_write(&unp_gc_lock); } } fdpunlock(fdp); return (0); fail: fdpunlock(fdp); if (fp != NULL) FRELE(fp, p); /* Back out what we just did. */ for ( ; i > 0; i--) { rp++; fp = rp->fp; if ((unp = fptounp(fp)) != NULL) { rw_enter_write(&unp_gc_lock); unp->unp_msgcount--; rw_exit_write(&unp_gc_lock); } FRELE(fp, p); } nospace: mtx_enter(&unp_rights_mtx); unp_rights -= nfds; mtx_leave(&unp_rights_mtx); return (error); } void unp_gc(void *arg __unused) { struct unp_deferral *defer; struct file *fp; struct socket *so; struct unpcb *unp; int nunref, i; rw_enter_write(&unp_gc_lock); if (unp_gcing) goto unlock; unp_gcing = 1; rw_exit_write(&unp_gc_lock); rw_enter_write(&unp_df_lock); /* close any fds on the deferred list */ while ((defer = SLIST_FIRST(&unp_deferred)) != NULL) { SLIST_REMOVE_HEAD(&unp_deferred, ud_link); rw_exit_write(&unp_df_lock); for (i = 0; i < defer->ud_n; i++) { fp = defer->ud_fp[i].fp; if (fp == NULL) continue; if ((unp = fptounp(fp)) != NULL) { rw_enter_write(&unp_gc_lock); unp->unp_msgcount--; rw_exit_write(&unp_gc_lock); } mtx_enter(&unp_rights_mtx); unp_rights--; mtx_leave(&unp_rights_mtx); /* closef() expects a refcount of 2 */ FREF(fp); (void) closef(fp, NULL); } free(defer, M_TEMP, sizeof(*defer) + sizeof(struct fdpass) * defer->ud_n); rw_enter_write(&unp_df_lock); } rw_exit_write(&unp_df_lock); nunref = 0; rw_enter_write(&unp_gc_lock); /* * Determine sockets which may be prospectively dead. Such * sockets have their `unp_msgcount' equal to the `f_count'. * If `unp_msgcount' is 0, the socket has not been passed * and can't be unreferenced. */ LIST_FOREACH(unp, &unp_head, unp_link) { unp->unp_gcflags = 0; if (unp->unp_msgcount == 0) continue; if ((fp = unp->unp_file) == NULL) continue; if (fp->f_count == unp->unp_msgcount) { unp->unp_gcflags |= UNP_GCDEAD; unp->unp_gcrefs = unp->unp_msgcount; nunref++; } } /* * Scan all sockets previously marked as dead. Remove * the `unp_gcrefs' reference each socket holds on any * dead socket in its buffer. */ LIST_FOREACH(unp, &unp_head, unp_link) { if ((unp->unp_gcflags & UNP_GCDEAD) == 0) continue; so = unp->unp_socket; mtx_enter(&so->so_rcv.sb_mtx); unp_scan(so->so_rcv.sb_mb, unp_remove_gcrefs); mtx_leave(&so->so_rcv.sb_mtx); } /* * If the dead socket has `unp_gcrefs' reference counter * greater than 0, it can't be unreferenced. Mark it as * alive and increment the `unp_gcrefs' reference for each * dead socket within its buffer. Repeat this until we * have no new alive sockets found. */ do { unp_defer = 0; LIST_FOREACH(unp, &unp_head, unp_link) { if ((unp->unp_gcflags & UNP_GCDEAD) == 0) continue; if (unp->unp_gcrefs == 0) continue; unp->unp_gcflags &= ~UNP_GCDEAD; so = unp->unp_socket; mtx_enter(&so->so_rcv.sb_mtx); unp_scan(so->so_rcv.sb_mb, unp_restore_gcrefs); mtx_leave(&so->so_rcv.sb_mtx); KASSERT(nunref > 0); nunref--; } } while (unp_defer > 0); /* * If there are any unreferenced sockets, then for each dispose * of files in its receive buffer and then close it. */ if (nunref) { LIST_FOREACH(unp, &unp_head, unp_link) { if (unp->unp_gcflags & UNP_GCDEAD) { struct sockbuf *sb = &unp->unp_socket->so_rcv; struct mbuf *m; /* * This socket could still be connected * and if so it's `so_rcv' is still * accessible by concurrent PRU_SEND * thread. */ mtx_enter(&sb->sb_mtx); m = sb->sb_mb; memset(&sb->sb_startzero, 0, (caddr_t)&sb->sb_endzero - (caddr_t)&sb->sb_startzero); sb->sb_timeo_nsecs = INFSLP; mtx_leave(&sb->sb_mtx); unp_scan(m, unp_discard); m_purge(m); } } } unp_gcing = 0; unlock: rw_exit_write(&unp_gc_lock); } void unp_dispose(struct mbuf *m) { if (m) unp_scan(m, unp_discard); } void unp_scan(struct mbuf *m0, void (*op)(struct fdpass *, int)) { struct mbuf *m; struct fdpass *rp; struct cmsghdr *cm; int qfds; while (m0) { for (m = m0; m; m = m->m_next) { if (m->m_type == MT_CONTROL && m->m_len >= sizeof(*cm)) { cm = mtod(m, struct cmsghdr *); if (cm->cmsg_level != SOL_SOCKET || cm->cmsg_type != SCM_RIGHTS) continue; qfds = (cm->cmsg_len - CMSG_ALIGN(sizeof *cm)) / sizeof(struct fdpass); if (qfds > 0) { rp = (struct fdpass *)CMSG_DATA(cm); op(rp, qfds); } break; /* XXX, but saves time */ } } m0 = m0->m_nextpkt; } } void unp_discard(struct fdpass *rp, int nfds) { struct unp_deferral *defer; /* copy the file pointers to a deferral structure */ defer = malloc(sizeof(*defer) + sizeof(*rp) * nfds, M_TEMP, M_WAITOK); defer->ud_n = nfds; memcpy(&defer->ud_fp[0], rp, sizeof(*rp) * nfds); memset(rp, 0, sizeof(*rp) * nfds); rw_enter_write(&unp_df_lock); SLIST_INSERT_HEAD(&unp_deferred, defer, ud_link); rw_exit_write(&unp_df_lock); task_add(systqmp, &unp_gc_task); } void unp_remove_gcrefs(struct fdpass *rp, int nfds) { struct unpcb *unp; int i; rw_assert_wrlock(&unp_gc_lock); for (i = 0; i < nfds; i++) { if (rp[i].fp == NULL) continue; if ((unp = fptounp(rp[i].fp)) == NULL) continue; if (unp->unp_gcflags & UNP_GCDEAD) { KASSERT(unp->unp_gcrefs > 0); unp->unp_gcrefs--; } } } void unp_restore_gcrefs(struct fdpass *rp, int nfds) { struct unpcb *unp; int i; rw_assert_wrlock(&unp_gc_lock); for (i = 0; i < nfds; i++) { if (rp[i].fp == NULL) continue; if ((unp = fptounp(rp[i].fp)) == NULL) continue; if (unp->unp_gcflags & UNP_GCDEAD) { unp->unp_gcrefs++; unp_defer++; } } } int unp_nam2sun(struct mbuf *nam, struct sockaddr_un **sun, size_t *pathlen) { struct sockaddr *sa = mtod(nam, struct sockaddr *); size_t size, len; if (nam->m_len < offsetof(struct sockaddr, sa_data)) return EINVAL; if (sa->sa_family != AF_UNIX) return EAFNOSUPPORT; if (sa->sa_len != nam->m_len) return EINVAL; if (sa->sa_len > sizeof(struct sockaddr_un)) return EINVAL; *sun = (struct sockaddr_un *)sa; /* ensure that sun_path is NUL terminated and fits */ size = (*sun)->sun_len - offsetof(struct sockaddr_un, sun_path); len = strnlen((*sun)->sun_path, size); if (len == sizeof((*sun)->sun_path)) return EINVAL; if (len == size) { if (m_trailingspace(nam) == 0) return EINVAL; nam->m_len++; (*sun)->sun_len++; (*sun)->sun_path[len] = '\0'; } if (pathlen != NULL) *pathlen = len; return 0; }
66 66 1 43 1 21 44 21 20 7 14 21 66 46 6 18 21 19 2 16 3 4 15 18 18 32 4 1 1 1 1 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 /* $OpenBSD: ip_icmp.c,v 1.192 2023/09/16 09:33:27 mpi Exp $ */ /* $NetBSD: ip_icmp.c,v 1.19 1996/02/13 23:42:22 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 * * NRL grants permission for redistribution and use in source and binary * forms, with or without modification, of the software and documentation * created at NRL provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgements: * This product includes software developed by the University of * California, Berkeley and its contributors. * This product includes software developed at the Information * Technology Division, US Naval Research Laboratory. * 4. Neither the name of the NRL nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the US Naval * Research Laboratory (NRL). */ #include "carp.h" #include "pf.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/protosw.h> #include <sys/socket.h> #include <sys/sysctl.h> #include <net/if.h> #include <net/if_var.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/in_var.h> #include <netinet/ip.h> #include <netinet/ip_icmp.h> #include <netinet/ip_var.h> #include <netinet/icmp_var.h> #if NCARP > 0 #include <net/if_types.h> #include <netinet/ip_carp.h> #endif #if NPF > 0 #include <net/pfvar.h> #endif /* * ICMP routines: error generation, receive packet processing, and * routines to turnaround packets back to the originator, and * host table maintenance routines. */ #ifdef ICMPPRINTFS int icmpprintfs = 0; /* Settable from ddb */ #endif /* values controllable via sysctl */ int icmpmaskrepl = 0; int icmpbmcastecho = 0; int icmptstamprepl = 1; int icmperrppslim = 100; int icmp_rediraccept = 0; int icmp_redirtimeout = 10 * 60; static int icmperrpps_count = 0; static struct timeval icmperrppslim_last; struct rttimer_queue ip_mtudisc_timeout_q; struct rttimer_queue icmp_redirect_timeout_q; struct cpumem *icmpcounters; const struct sysctl_bounded_args icmpctl_vars[] = { { ICMPCTL_MASKREPL, &icmpmaskrepl, 0, 1 }, { ICMPCTL_BMCASTECHO, &icmpbmcastecho, 0, 1 }, { ICMPCTL_ERRPPSLIMIT, &icmperrppslim, -1, INT_MAX }, { ICMPCTL_REDIRACCEPT, &icmp_rediraccept, 0, 1 }, { ICMPCTL_TSTAMPREPL, &icmptstamprepl, 0, 1 }, }; void icmp_mtudisc_timeout(struct rtentry *, u_int); int icmp_ratelimit(const struct in_addr *, const int, const int); int icmp_input_if(struct ifnet *, struct mbuf **, int *, int, int); int icmp_sysctl_icmpstat(void *, size_t *, void *); void icmp_init(void) { rt_timer_queue_init(&ip_mtudisc_timeout_q, ip_mtudisc_timeout, &icmp_mtudisc_timeout); rt_timer_queue_init(&icmp_redirect_timeout_q, icmp_redirtimeout, NULL); icmpcounters = counters_alloc(icps_ncounters); } struct mbuf * icmp_do_error(struct mbuf *n, int type, int code, u_int32_t dest, int destmtu) { struct ip *oip = mtod(n, struct ip *), *nip; unsigned oiplen = oip->ip_hl << 2; struct icmp *icp; struct mbuf *m; unsigned icmplen, mblen; #ifdef ICMPPRINTFS if (icmpprintfs) printf("icmp_error(%x, %d, %d)\n", oip, type, code); #endif if (type != ICMP_REDIRECT) icmpstat_inc(icps_error); /* * Don't send error if not the first fragment of message. * Don't error if the old packet protocol was ICMP * error message, only known informational types. */ if (oip->ip_off & htons(IP_OFFMASK)) goto freeit; if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT && n->m_len >= oiplen + ICMP_MINLEN && !ICMP_INFOTYPE(((struct icmp *) ((caddr_t)oip + oiplen))->icmp_type)) { icmpstat_inc(icps_oldicmp); goto freeit; } /* Don't send error in response to a multicast or broadcast packet */ if (n->m_flags & (M_BCAST|M_MCAST)) goto freeit; /* * First, do a rate limitation check. */ if (icmp_ratelimit(&oip->ip_src, type, code)) { icmpstat_inc(icps_toofreq); goto freeit; } /* * Now, formulate icmp message */ icmplen = oiplen + min(8, ntohs(oip->ip_len)); /* * Defend against mbuf chains shorter than oip->ip_len: */ mblen = 0; for (m = n; m && (mblen < icmplen); m = m->m_next) mblen += m->m_len; icmplen = min(mblen, icmplen); /* * As we are not required to return everything we have, * we return whatever we can return at ease. * * Note that ICMP datagrams longer than 576 octets are out of spec * according to RFC1812; */ KASSERT(ICMP_MINLEN + sizeof (struct ip) <= MCLBYTES); if (sizeof (struct ip) + icmplen + ICMP_MINLEN > MCLBYTES) icmplen = MCLBYTES - ICMP_MINLEN - sizeof (struct ip); m = m_gethdr(M_DONTWAIT, MT_HEADER); if (m && ((sizeof (struct ip) + icmplen + ICMP_MINLEN + sizeof(long) - 1) &~ (sizeof(long) - 1)) > MHLEN) { MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { m_freem(m); m = NULL; } } if (m == NULL) goto freeit; /* keep in same rtable and preserve other pkthdr bits */ m->m_pkthdr.ph_rtableid = n->m_pkthdr.ph_rtableid; m->m_pkthdr.ph_ifidx = n->m_pkthdr.ph_ifidx; /* move PF_GENERATED to new packet, if existent XXX preserve more? */ if (n->m_pkthdr.pf.flags & PF_TAG_GENERATED) m->m_pkthdr.pf.flags |= PF_TAG_GENERATED; m->m_pkthdr.len = m->m_len = icmplen + ICMP_MINLEN; m_align(m, m->m_len); icp = mtod(m, struct icmp *); if ((u_int)type > ICMP_MAXTYPE) panic("icmp_error"); icmpstat_inc(icps_outhist + type); icp->icmp_type = type; if (type == ICMP_REDIRECT) icp->icmp_gwaddr.s_addr = dest; else { icp->icmp_void = 0; /* * The following assignments assume an overlay with the * zeroed icmp_void field. */ if (type == ICMP_PARAMPROB) { icp->icmp_pptr = code; code = 0; } else if (type == ICMP_UNREACH && code == ICMP_UNREACH_NEEDFRAG && destmtu) icp->icmp_nextmtu = htons(destmtu); } icp->icmp_code = code; m_copydata(n, 0, icmplen, &icp->icmp_ip); /* * Now, copy old ip header (without options) * in front of icmp message. */ m = m_prepend(m, sizeof(struct ip), M_DONTWAIT); if (m == NULL) goto freeit; nip = mtod(m, struct ip *); /* ip_v set in ip_output */ nip->ip_hl = sizeof(struct ip) >> 2; nip->ip_tos = 0; nip->ip_len = htons(m->m_len); /* ip_id set in ip_output */ nip->ip_off = 0; /* ip_ttl set in icmp_reflect */ nip->ip_p = IPPROTO_ICMP; nip->ip_src = oip->ip_src; nip->ip_dst = oip->ip_dst; m_freem(n); return (m); freeit: m_freem(n); return (NULL); } /* * Generate an error packet of type error * in response to bad packet ip. * * The ip packet inside has ip_off and ip_len in host byte order. */ void icmp_error(struct mbuf *n, int type, int code, u_int32_t dest, int destmtu) { struct mbuf *m; m = icmp_do_error(n, type, code, dest, destmtu); if (m != NULL) if (!icmp_reflect(m, NULL, NULL)) icmp_send(m, NULL); } /* * Process a received ICMP message. */ int icmp_input(struct mbuf **mp, int *offp, int proto, int af) { struct ifnet *ifp; ifp = if_get((*mp)->m_pkthdr.ph_ifidx); if (ifp == NULL) { m_freemp(mp); return IPPROTO_DONE; } proto = icmp_input_if(ifp, mp, offp, proto, af); if_put(ifp); return proto; } int icmp_input_if(struct ifnet *ifp, struct mbuf **mp, int *offp, int proto, int af) { struct mbuf *m = *mp; int hlen = *offp; struct icmp *icp; struct ip *ip = mtod(m, struct ip *); struct sockaddr_in sin; int icmplen, i, code; struct in_ifaddr *ia; void (*ctlfunc)(int, struct sockaddr *, u_int, void *); struct mbuf *opts; /* * Locate icmp structure in mbuf, and check * that not corrupted and of at least minimum length. */ icmplen = ntohs(ip->ip_len) - hlen; #ifdef ICMPPRINTFS if (icmpprintfs) { char dst[INET_ADDRSTRLEN], src[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &ip->ip_dst, dst, sizeof(dst)); inet_ntop(AF_INET, &ip->ip_src, src, sizeof(src)); printf("icmp_input from %s to %s, len %d\n", src, dst, icmplen); } #endif if (icmplen < ICMP_MINLEN) { icmpstat_inc(icps_tooshort); goto freeit; } i = hlen + min(icmplen, ICMP_ADVLENMAX); if ((m = *mp = m_pullup(m, i)) == NULL) { icmpstat_inc(icps_tooshort); return IPPROTO_DONE; } ip = mtod(m, struct ip *); if (in4_cksum(m, 0, hlen, icmplen)) { icmpstat_inc(icps_checksum); goto freeit; } icp = (struct icmp *)(mtod(m, caddr_t) + hlen); #ifdef ICMPPRINTFS /* * Message type specific processing. */ if (icmpprintfs) printf("icmp_input, type %d code %d\n", icp->icmp_type, icp->icmp_code); #endif if (icp->icmp_type > ICMP_MAXTYPE) goto raw; #if NPF > 0 if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { switch (icp->icmp_type) { /* * As pf_icmp_mapping() considers redirects belonging to a * diverted connection, we must include it here. */ case ICMP_REDIRECT: /* FALLTHROUGH */ /* * These ICMP types map to other connections. They must be * delivered to pr_ctlinput() also for diverted connections. */ case ICMP_UNREACH: case ICMP_TIMXCEED: case ICMP_PARAMPROB: case ICMP_SOURCEQUENCH: /* * Do not use the divert-to property of the TCP or UDP * rule when doing the PCB lookup for the raw socket. */ m->m_pkthdr.pf.flags &=~ PF_TAG_DIVERTED; break; default: goto raw; } } #endif /* NPF */ icmpstat_inc(icps_inhist + icp->icmp_type); code = icp->icmp_code; switch (icp->icmp_type) { case ICMP_UNREACH: switch (code) { case ICMP_UNREACH_NET: case ICMP_UNREACH_HOST: case ICMP_UNREACH_PROTOCOL: case ICMP_UNREACH_PORT: case ICMP_UNREACH_SRCFAIL: code += PRC_UNREACH_NET; break; case ICMP_UNREACH_NEEDFRAG: code = PRC_MSGSIZE; break; case ICMP_UNREACH_NET_UNKNOWN: case ICMP_UNREACH_NET_PROHIB: case ICMP_UNREACH_TOSNET: code = PRC_UNREACH_NET; break; case ICMP_UNREACH_HOST_UNKNOWN: case ICMP_UNREACH_ISOLATED: case ICMP_UNREACH_HOST_PROHIB: case ICMP_UNREACH_TOSHOST: case ICMP_UNREACH_FILTER_PROHIB: case ICMP_UNREACH_HOST_PRECEDENCE: case ICMP_UNREACH_PRECEDENCE_CUTOFF: code = PRC_UNREACH_HOST; break; default: goto badcode; } goto deliver; case ICMP_TIMXCEED: if (code > 1) goto badcode; code += PRC_TIMXCEED_INTRANS; goto deliver; case ICMP_PARAMPROB: if (code > 1) goto badcode; code = PRC_PARAMPROB; goto deliver; case ICMP_SOURCEQUENCH: if (code) goto badcode; code = PRC_QUENCH; deliver: /* * Problem with datagram; advise higher level routines. */ if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) || icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) { icmpstat_inc(icps_badlen); goto freeit; } if (IN_MULTICAST(icp->icmp_ip.ip_dst.s_addr)) goto badcode; #ifdef INET6 /* Get more contiguous data for a v6 in v4 ICMP message. */ if (icp->icmp_ip.ip_p == IPPROTO_IPV6) { if (icmplen < ICMP_V6ADVLENMIN || icmplen < ICMP_V6ADVLEN(icp)) { icmpstat_inc(icps_badlen); goto freeit; } } #endif /* INET6 */ #ifdef ICMPPRINTFS if (icmpprintfs) printf("deliver to protocol %d\n", icp->icmp_ip.ip_p); #endif memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_len = sizeof(struct sockaddr_in); sin.sin_addr = icp->icmp_ip.ip_dst; #if NCARP > 0 if (carp_lsdrop(ifp, m, AF_INET, &sin.sin_addr.s_addr, &ip->ip_dst.s_addr, 1)) goto freeit; #endif /* * XXX if the packet contains [IPv4 AH TCP], we can't make a * notification to TCP layer. */ ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput; if (ctlfunc) (*ctlfunc)(code, sintosa(&sin), m->m_pkthdr.ph_rtableid, &icp->icmp_ip); break; badcode: icmpstat_inc(icps_badcode); break; case ICMP_ECHO: if (!icmpbmcastecho && (m->m_flags & (M_MCAST | M_BCAST)) != 0) { icmpstat_inc(icps_bmcastecho); break; } icp->icmp_type = ICMP_ECHOREPLY; goto reflect; case ICMP_TSTAMP: if (icmptstamprepl == 0) break; if (!icmpbmcastecho && (m->m_flags & (M_MCAST | M_BCAST)) != 0) { icmpstat_inc(icps_bmcastecho); break; } if (icmplen < ICMP_TSLEN) { icmpstat_inc(icps_badlen); break; } icp->icmp_type = ICMP_TSTAMPREPLY; icp->icmp_rtime = iptime(); icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */ goto reflect; case ICMP_MASKREQ: if (icmpmaskrepl == 0) break; if (icmplen < ICMP_MASKLEN) { icmpstat_inc(icps_badlen); break; } /* * We are not able to respond with all ones broadcast * unless we receive it over a point-to-point interface. */ memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_len = sizeof(struct sockaddr_in); if (ip->ip_dst.s_addr == INADDR_BROADCAST || ip->ip_dst.s_addr == INADDR_ANY) sin.sin_addr = ip->ip_src; else sin.sin_addr = ip->ip_dst; if (ifp == NULL) break; ia = ifatoia(ifaof_ifpforaddr(sintosa(&sin), ifp)); if (ia == NULL) break; icp->icmp_type = ICMP_MASKREPLY; icp->icmp_mask = ia->ia_sockmask.sin_addr.s_addr; if (ip->ip_src.s_addr == 0) { if (ifp->if_flags & IFF_BROADCAST) { if (ia->ia_broadaddr.sin_addr.s_addr) ip->ip_src = ia->ia_broadaddr.sin_addr; else ip->ip_src.s_addr = INADDR_BROADCAST; } else if (ifp->if_flags & IFF_POINTOPOINT) ip->ip_src = ia->ia_dstaddr.sin_addr; } reflect: #if NCARP > 0 if (carp_lsdrop(ifp, m, AF_INET, &ip->ip_src.s_addr, &ip->ip_dst.s_addr, 1)) goto freeit; #endif icmpstat_inc(icps_reflect); icmpstat_inc(icps_outhist + icp->icmp_type); if (!icmp_reflect(m, &opts, NULL)) { icmp_send(m, opts); m_free(opts); } return IPPROTO_DONE; case ICMP_REDIRECT: { struct sockaddr_in sdst; struct sockaddr_in sgw; struct sockaddr_in ssrc; struct rtentry *newrt = NULL; if (icmp_rediraccept == 0 || ipforwarding == 1) goto freeit; if (code > 3) goto badcode; if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) || icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) { icmpstat_inc(icps_badlen); break; } /* * Short circuit routing redirects to force * immediate change in the kernel's routing * tables. The message is also handed to anyone * listening on a raw socket (e.g. the routing * daemon for use in updating its tables). */ memset(&sdst, 0, sizeof(sdst)); memset(&sgw, 0, sizeof(sgw)); memset(&ssrc, 0, sizeof(ssrc)); sdst.sin_family = sgw.sin_family = ssrc.sin_family = AF_INET; sdst.sin_len = sgw.sin_len = ssrc.sin_len = sizeof(sdst); memcpy(&sdst.sin_addr, &icp->icmp_ip.ip_dst, sizeof(sdst.sin_addr)); memcpy(&sgw.sin_addr, &icp->icmp_gwaddr, sizeof(sgw.sin_addr)); memcpy(&ssrc.sin_addr, &ip->ip_src, sizeof(ssrc.sin_addr)); #ifdef ICMPPRINTFS if (icmpprintfs) { char gw[INET_ADDRSTRLEN], dst[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &icp->icmp_gwaddr, gw, sizeof(gw)); inet_ntop(AF_INET, &icp->icmp_ip.ip_dst, dst, sizeof(dst)); printf("redirect dst %s to %s\n", dst, gw); } #endif #if NCARP > 0 if (carp_lsdrop(ifp, m, AF_INET, &sdst.sin_addr.s_addr, &ip->ip_dst.s_addr, 1)) goto freeit; #endif rtredirect(sintosa(&sdst), sintosa(&sgw), sintosa(&ssrc), &newrt, m->m_pkthdr.ph_rtableid); if (newrt != NULL && icmp_redirtimeout > 0) { rt_timer_add(newrt, &icmp_redirect_timeout_q, m->m_pkthdr.ph_rtableid); } rtfree(newrt); pfctlinput(PRC_REDIRECT_HOST, sintosa(&sdst)); break; } /* * No kernel processing for the following; * just fall through to send to raw listener. */ case ICMP_ECHOREPLY: case ICMP_ROUTERADVERT: case ICMP_ROUTERSOLICIT: case ICMP_TSTAMPREPLY: case ICMP_IREQREPLY: case ICMP_MASKREPLY: case ICMP_TRACEROUTE: case ICMP_DATACONVERR: case ICMP_MOBILE_REDIRECT: case ICMP_IPV6_WHEREAREYOU: case ICMP_IPV6_IAMHERE: case ICMP_MOBILE_REGREQUEST: case ICMP_MOBILE_REGREPLY: case ICMP_PHOTURIS: default: break; } raw: return rip_input(mp, offp, proto, af); freeit: m_freem(m); return IPPROTO_DONE; } /* * Reflect the ip packet back to the source */ int icmp_reflect(struct mbuf *m, struct mbuf **op, struct in_ifaddr *ia) { struct ip *ip = mtod(m, struct ip *); struct mbuf *opts = NULL; struct sockaddr_in sin; struct rtentry *rt = NULL; int optlen = (ip->ip_hl << 2) - sizeof(struct ip); u_int rtableid; u_int8_t pfflags; if (!in_canforward(ip->ip_src) && ((ip->ip_src.s_addr & IN_CLASSA_NET) != htonl(IN_LOOPBACKNET << IN_CLASSA_NSHIFT))) { m_freem(m); /* Bad return address */ return (EHOSTUNREACH); } if (m->m_pkthdr.ph_loopcnt++ >= M_MAXLOOP) { m_freem(m); return (ELOOP); } rtableid = m->m_pkthdr.ph_rtableid; pfflags = m->m_pkthdr.pf.flags; m_resethdr(m); m->m_pkthdr.ph_rtableid = rtableid; m->m_pkthdr.pf.flags = pfflags & PF_TAG_GENERATED; /* * If the incoming packet was addressed directly to us, * use dst as the src for the reply. For broadcast, use * the address which corresponds to the incoming interface. */ if (ia == NULL) { memset(&sin, 0, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_addr = ip->ip_dst; rt = rtalloc(sintosa(&sin), 0, rtableid); if (rtisvalid(rt) && ISSET(rt->rt_flags, RTF_LOCAL|RTF_BROADCAST)) ia = ifatoia(rt->rt_ifa); } /* * The following happens if the packet was not addressed to us. * Use the new source address and do a route lookup. If it fails * drop the packet as there is no path to the host. */ if (ia == NULL) { rtfree(rt); memset(&sin, 0, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_addr = ip->ip_src; /* keep packet in the original virtual instance */ rt = rtalloc(sintosa(&sin), RT_RESOLVE, rtableid); if (rt == NULL) { ipstat_inc(ips_noroute); m_freem(m); return (EHOSTUNREACH); } ia = ifatoia(rt->rt_ifa); } ip->ip_dst = ip->ip_src; ip->ip_ttl = MAXTTL; /* It is safe to dereference ``ia'' iff ``rt'' is valid. */ ip->ip_src = ia->ia_addr.sin_addr; rtfree(rt); if (optlen > 0) { u_char *cp; int opt, cnt; u_int len; /* * Retrieve any source routing from the incoming packet; * add on any record-route or timestamp options. */ cp = (u_char *) (ip + 1); if (op && (opts = ip_srcroute(m)) == NULL && (opts = m_gethdr(M_DONTWAIT, MT_HEADER))) { opts->m_len = sizeof(struct in_addr); mtod(opts, struct in_addr *)->s_addr = 0; } if (op && opts) { #ifdef ICMPPRINTFS if (icmpprintfs) printf("icmp_reflect optlen %d rt %d => ", optlen, opts->m_len); #endif for (cnt = optlen; cnt > 0; cnt -= len, cp += len) { opt = cp[IPOPT_OPTVAL]; if (opt == IPOPT_EOL) break; if (opt == IPOPT_NOP) len = 1; else { if (cnt < IPOPT_OLEN + sizeof(*cp)) break; len = cp[IPOPT_OLEN]; if (len < IPOPT_OLEN + sizeof(*cp) || len > cnt) break; } /* * Should check for overflow, but it * "can't happen" */ if (opt == IPOPT_RR || opt == IPOPT_TS || opt == IPOPT_SECURITY) { memcpy(mtod(opts, caddr_t) + opts->m_len, cp, len); opts->m_len += len; } } /* Terminate & pad, if necessary */ if ((cnt = opts->m_len % 4) != 0) for (; cnt < 4; cnt++) { *(mtod(opts, caddr_t) + opts->m_len) = IPOPT_EOL; opts->m_len++; } #ifdef ICMPPRINTFS if (icmpprintfs) printf("%d\n", opts->m_len); #endif } ip_stripoptions(m); } m->m_flags &= ~(M_BCAST|M_MCAST); if (op) *op = opts; return (0); } /* * Send an icmp packet back to the ip level */ void icmp_send(struct mbuf *m, struct mbuf *opts) { struct ip *ip = mtod(m, struct ip *); int hlen; struct icmp *icp; hlen = ip->ip_hl << 2; icp = (struct icmp *)(mtod(m, caddr_t) + hlen); icp->icmp_cksum = 0; m->m_pkthdr.csum_flags = M_ICMP_CSUM_OUT; #ifdef ICMPPRINTFS if (icmpprintfs) { char dst[INET_ADDRSTRLEN], src[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &ip->ip_dst, dst, sizeof(dst)); inet_ntop(AF_INET, &ip->ip_src, src, sizeof(src)); printf("icmp_send dst %s src %s\n", dst, src); } #endif /* * ip_send() cannot handle IP options properly. So in case we have * options fill out the IP header here and use ip_send_raw() instead. */ if (opts != NULL) { m = ip_insertoptions(m, opts, &hlen); ip = mtod(m, struct ip *); ip->ip_hl = (hlen >> 2); ip->ip_v = IPVERSION; ip->ip_off &= htons(IP_DF); ip->ip_id = htons(ip_randomid()); ipstat_inc(ips_localout); ip_send_raw(m); } else ip_send(m); } u_int32_t iptime(void) { struct timeval atv; u_long t; microtime(&atv); t = (atv.tv_sec % (24*60*60)) * 1000 + atv.tv_usec / 1000; return (htonl(t)); } int icmp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int error; /* All sysctl names at this level are terminal. */ if (namelen != 1) return (ENOTDIR); switch (name[0]) { case ICMPCTL_REDIRTIMEOUT: NET_LOCK(); error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &icmp_redirtimeout, 0, INT_MAX); rt_timer_queue_change(&icmp_redirect_timeout_q, icmp_redirtimeout); NET_UNLOCK(); break; case ICMPCTL_STATS: error = icmp_sysctl_icmpstat(oldp, oldlenp, newp); break; default: NET_LOCK(); error = sysctl_bounded_arr(icmpctl_vars, nitems(icmpctl_vars), name, namelen, oldp, oldlenp, newp, newlen); NET_UNLOCK(); break; } return (error); } int icmp_sysctl_icmpstat(void *oldp, size_t *oldlenp, void *newp) { uint64_t counters[icps_ncounters]; struct icmpstat icmpstat; u_long *words = (u_long *)&icmpstat; int i; CTASSERT(sizeof(icmpstat) == (nitems(counters) * sizeof(u_long))); memset(&icmpstat, 0, sizeof icmpstat); counters_read(icmpcounters, counters, nitems(counters), NULL); for (i = 0; i < nitems(counters); i++) words[i] = (u_long)counters[i]; return (sysctl_rdstruct(oldp, oldlenp, newp, &icmpstat, sizeof(icmpstat))); } struct rtentry * icmp_mtudisc_clone(struct in_addr dst, u_int rtableid, int ipsec) { struct sockaddr_in sin; struct rtentry *rt; int error; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_len = sizeof(sin); sin.sin_addr = dst; rt = rtalloc(sintosa(&sin), RT_RESOLVE, rtableid); /* Check if the route is actually usable */ if (!rtisvalid(rt)) goto bad; /* IPsec needs the route only for PMTU, it can use reject for that */ if (!ipsec && (rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE))) goto bad; /* * No PMTU for local routes and permanent neighbors, * ARP and NDP use the same expire timer as the route. */ if (ISSET(rt->rt_flags, RTF_LOCAL) || (ISSET(rt->rt_flags, RTF_LLINFO) && rt->rt_expire == 0)) goto bad; /* If we didn't get a host route, allocate one */ if ((rt->rt_flags & RTF_HOST) == 0) { struct rtentry *nrt; struct rt_addrinfo info; struct sockaddr_rtlabel sa_rl; memset(&info, 0, sizeof(info)); info.rti_ifa = rt->rt_ifa; info.rti_flags = RTF_GATEWAY | RTF_HOST | RTF_DYNAMIC; info.rti_info[RTAX_DST] = sintosa(&sin); info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; info.rti_info[RTAX_LABEL] = rtlabel_id2sa(rt->rt_labelid, &sa_rl); error = rtrequest(RTM_ADD, &info, rt->rt_priority, &nrt, rtableid); if (error) goto bad; nrt->rt_rmx = rt->rt_rmx; rtfree(rt); rt = nrt; rtm_send(rt, RTM_ADD, 0, rtableid); } error = rt_timer_add(rt, &ip_mtudisc_timeout_q, rtableid); if (error) goto bad; return (rt); bad: rtfree(rt); return (NULL); } /* Table of common MTUs: */ static const u_short mtu_table[] = { 65535, 65280, 32000, 17914, 9180, 8166, 4352, 2002, 1492, 1006, 508, 296, 68, 0 }; void icmp_mtudisc(struct icmp *icp, u_int rtableid) { struct rtentry *rt; struct ifnet *ifp; u_long mtu = ntohs(icp->icmp_nextmtu); /* Why a long? IPv6 */ rt = icmp_mtudisc_clone(icp->icmp_ip.ip_dst, rtableid, 0); if (rt == NULL) return; ifp = if_get(rt->rt_ifidx); if (ifp == NULL) { rtfree(rt); return; } if (mtu == 0) { int i = 0; mtu = ntohs(icp->icmp_ip.ip_len); /* Some 4.2BSD-based routers incorrectly adjust the ip_len */ if (mtu > rt->rt_mtu && rt->rt_mtu != 0) mtu -= (icp->icmp_ip.ip_hl << 2); /* If we still can't guess a value, try the route */ if (mtu == 0) { mtu = rt->rt_mtu; /* If no route mtu, default to the interface mtu */ if (mtu == 0) mtu = ifp->if_mtu; } for (i = 0; i < nitems(mtu_table); i++) if (mtu > mtu_table[i]) { mtu = mtu_table[i]; break; } } /* * XXX: RTV_MTU is overloaded, since the admin can set it * to turn off PMTU for a route, and the kernel can * set it to indicate a serious problem with PMTU * on a route. We should be using a separate flag * for the kernel to indicate this. */ if ((rt->rt_locks & RTV_MTU) == 0) { if (mtu < 296 || mtu > ifp->if_mtu) rt->rt_locks |= RTV_MTU; else if (rt->rt_mtu > mtu || rt->rt_mtu == 0) rt->rt_mtu = mtu; } if_put(ifp); rtfree(rt); } void icmp_mtudisc_timeout(struct rtentry *rt, u_int rtableid) { struct ifnet *ifp; NET_ASSERT_LOCKED(); ifp = if_get(rt->rt_ifidx); if (ifp == NULL) return; if ((rt->rt_flags & (RTF_DYNAMIC|RTF_HOST)) == (RTF_DYNAMIC|RTF_HOST)) { void (*ctlfunc)(int, struct sockaddr *, u_int, void *); struct sockaddr_in sin; sin = *satosin(rt_key(rt)); rtdeletemsg(rt, ifp, rtableid); /* Notify TCP layer of increased Path MTU estimate */ ctlfunc = inetsw[ip_protox[IPPROTO_TCP]].pr_ctlinput; if (ctlfunc) (*ctlfunc)(PRC_MTUINC, sintosa(&sin), rtableid, NULL); } else { if ((rt->rt_locks & RTV_MTU) == 0) rt->rt_mtu = 0; } if_put(ifp); } /* * Perform rate limit check. * Returns 0 if it is okay to send the icmp packet. * Returns 1 if the router SHOULD NOT send this icmp packet due to rate * limitation. * * XXX per-destination/type check necessary? */ int icmp_ratelimit(const struct in_addr *dst, const int type, const int code) { /* PPS limit */ if (!ppsratecheck(&icmperrppslim_last, &icmperrpps_count, icmperrppslim)) return 1; /* The packet is subject to rate limit */ return 0; /* okay to send */ } int icmp_do_exthdr(struct mbuf *m, u_int16_t class, u_int8_t ctype, void *buf, size_t len) { struct ip *ip = mtod(m, struct ip *); int hlen, off; struct mbuf *n; struct icmp *icp; struct icmp_ext_hdr *ieh; struct { struct icmp_ext_hdr ieh; struct icmp_ext_obj_hdr ieo; } hdr; hlen = ip->ip_hl << 2; icp = (struct icmp *)(mtod(m, caddr_t) + hlen); if (icp->icmp_type != ICMP_TIMXCEED && icp->icmp_type != ICMP_UNREACH && icp->icmp_type != ICMP_PARAMPROB) /* exthdr not supported */ return (0); if (icp->icmp_length != 0) /* exthdr already present, giving up */ return (0); /* the actual offset starts after the common ICMP header */ hlen += ICMP_MINLEN; /* exthdr must start on a word boundary */ off = roundup(ntohs(ip->ip_len) - hlen, sizeof(u_int32_t)); /* ... and at an offset of ICMP_EXT_OFFSET or bigger */ off = max(off, ICMP_EXT_OFFSET); icp->icmp_length = off / sizeof(u_int32_t); memset(&hdr, 0, sizeof(hdr)); hdr.ieh.ieh_version = ICMP_EXT_HDR_VERSION; hdr.ieo.ieo_length = htons(sizeof(struct icmp_ext_obj_hdr) + len); hdr.ieo.ieo_cnum = class; hdr.ieo.ieo_ctype = ctype; if (m_copyback(m, hlen + off, sizeof(hdr), &hdr, M_NOWAIT) || m_copyback(m, hlen + off + sizeof(hdr), len, buf, M_NOWAIT)) { m_freem(m); return (ENOBUFS); } /* calculate checksum */ n = m_getptr(m, hlen + off, &off); if (n == NULL) panic("icmp_do_exthdr: m_getptr failure"); ieh = (struct icmp_ext_hdr *)(mtod(n, caddr_t) + off); ieh->ieh_cksum = in4_cksum(n, 0, off, sizeof(hdr) + len); ip->ip_len = htons(m->m_pkthdr.len); return (0); }
1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 /* $OpenBSD: ipmi.c,v 1.119 2024/04/03 18:32:47 gkoehler Exp $ */ /* * Copyright (c) 2015 Masao Uebayashi * Copyright (c) 2005 Jordan Hargrave * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/device.h> #include <sys/ioctl.h> #include <sys/extent.h> #include <sys/sensors.h> #include <sys/malloc.h> #include <sys/kthread.h> #include <sys/task.h> #include <machine/bus.h> #include <machine/smbiosvar.h> #include <dev/ipmivar.h> #include <dev/ipmi.h> struct ipmi_sensor { u_int8_t *i_sdr; int i_num; int stype; int etype; struct ksensor i_sensor; SLIST_ENTRY(ipmi_sensor) list; }; int ipmi_enabled = 0; #define SENSOR_REFRESH_RATE 5 /* seconds */ #define DEVNAME(s) ((s)->sc_dev.dv_xname) #define IPMI_BTMSG_LEN 0 #define IPMI_BTMSG_NFLN 1 #define IPMI_BTMSG_SEQ 2 #define IPMI_BTMSG_CMD 3 #define IPMI_BTMSG_CCODE 4 #define IPMI_BTMSG_DATASND 4 #define IPMI_BTMSG_DATARCV 5 /* IPMI 2.0, Table 42-3: Sensor Type Codes */ #define IPMI_SENSOR_TYPE_TEMP 0x0101 #define IPMI_SENSOR_TYPE_VOLT 0x0102 #define IPMI_SENSOR_TYPE_CURRENT 0x0103 #define IPMI_SENSOR_TYPE_FAN 0x0104 #define IPMI_SENSOR_TYPE_INTRUSION 0x6F05 #define IPMI_SENSOR_TYPE_PWRSUPPLY 0x6F08 /* IPMI 2.0, Table 43-15: Sensor Unit Type Codes */ #define IPMI_UNIT_TYPE_DEGREE_C 1 #define IPMI_UNIT_TYPE_DEGREE_F 2 #define IPMI_UNIT_TYPE_DEGREE_K 3 #define IPMI_UNIT_TYPE_VOLTS 4 #define IPMI_UNIT_TYPE_AMPS 5 #define IPMI_UNIT_TYPE_WATTS 6 #define IPMI_UNIT_TYPE_RPM 18 #define IPMI_NAME_UNICODE 0x00 #define IPMI_NAME_BCDPLUS 0x01 #define IPMI_NAME_ASCII6BIT 0x02 #define IPMI_NAME_ASCII8BIT 0x03 #define IPMI_ENTITY_PWRSUPPLY 0x0A #define IPMI_INVALID_SENSOR (1L << 5) #define IPMI_DISABLED_SENSOR (1L << 6) #define IPMI_SDR_TYPEFULL 1 #define IPMI_SDR_TYPECOMPACT 2 #define byteof(x) ((x) >> 3) #define bitof(x) (1L << ((x) & 0x7)) #define TB(b,m) (data[2+byteof(b)] & bitof(b)) #ifdef IPMI_DEBUG int ipmi_dbg = 0; #define dbg_printf(lvl, fmt...) \ if (ipmi_dbg >= lvl) \ printf(fmt); #define dbg_dump(lvl, msg, len, buf) \ if (len && ipmi_dbg >= lvl) \ dumpb(msg, len, (const u_int8_t *)(buf)); #else #define dbg_printf(lvl, fmt...) #define dbg_dump(lvl, msg, len, buf) #endif long signextend(unsigned long, int); SLIST_HEAD(ipmi_sensors_head, ipmi_sensor); struct ipmi_sensors_head ipmi_sensor_list = SLIST_HEAD_INITIALIZER(ipmi_sensor_list); void dumpb(const char *, int, const u_int8_t *); int read_sensor(struct ipmi_softc *, struct ipmi_sensor *); int add_sdr_sensor(struct ipmi_softc *, u_int8_t *, int); int get_sdr_partial(struct ipmi_softc *, u_int16_t, u_int16_t, u_int8_t, u_int8_t, void *, u_int16_t *); int get_sdr(struct ipmi_softc *, u_int16_t, u_int16_t *); int ipmi_sendcmd(struct ipmi_cmd *); int ipmi_recvcmd(struct ipmi_cmd *); void ipmi_cmd(struct ipmi_cmd *); void ipmi_cmd_poll(struct ipmi_cmd *); void ipmi_cmd_wait(struct ipmi_cmd *); void ipmi_cmd_wait_cb(void *); int ipmi_watchdog(void *, int); void ipmi_watchdog_tickle(void *); void ipmi_watchdog_set(void *); struct ipmi_softc *ipmilookup(dev_t dev); int ipmiopen(dev_t, int, int, struct proc *); int ipmiclose(dev_t, int, int, struct proc *); int ipmiioctl(dev_t, u_long, caddr_t, int, struct proc *); long ipow(long, int); long ipmi_convert(u_int8_t, struct sdrtype1 *, long); int ipmi_sensor_name(char *, int, u_int8_t, u_int8_t *, int); /* BMC Helper Functions */ u_int8_t bmc_read(struct ipmi_softc *, int); void bmc_write(struct ipmi_softc *, int, u_int8_t); int bmc_io_wait(struct ipmi_softc *, struct ipmi_iowait *); void bt_buildmsg(struct ipmi_cmd *); void cmn_buildmsg(struct ipmi_cmd *); int getbits(u_int8_t *, int, int); int ipmi_sensor_type(int, int, int, int); void ipmi_refresh_sensors(struct ipmi_softc *sc); int ipmi_map_regs(struct ipmi_softc *sc, struct ipmi_attach_args *ia); void ipmi_unmap_regs(struct ipmi_softc *); int ipmi_sensor_status(struct ipmi_softc *, struct ipmi_sensor *, u_int8_t *); int add_child_sensors(struct ipmi_softc *, u_int8_t *, int, int, int, int, int, int, const char *); void ipmi_create_thread(void *); void ipmi_poll_thread(void *); int kcs_probe(struct ipmi_softc *); int kcs_reset(struct ipmi_softc *); int kcs_sendmsg(struct ipmi_cmd *); int kcs_recvmsg(struct ipmi_cmd *); int bt_probe(struct ipmi_softc *); int bt_reset(struct ipmi_softc *); int bt_sendmsg(struct ipmi_cmd *); int bt_recvmsg(struct ipmi_cmd *); int smic_probe(struct ipmi_softc *); int smic_reset(struct ipmi_softc *); int smic_sendmsg(struct ipmi_cmd *); int smic_recvmsg(struct ipmi_cmd *); struct ipmi_if kcs_if = { "KCS", IPMI_IF_KCS_NREGS, cmn_buildmsg, kcs_sendmsg, kcs_recvmsg, kcs_reset, kcs_probe, IPMI_MSG_DATASND, IPMI_MSG_DATARCV, }; struct ipmi_if smic_if = { "SMIC", IPMI_IF_SMIC_NREGS, cmn_buildmsg, smic_sendmsg, smic_recvmsg, smic_reset, smic_probe, IPMI_MSG_DATASND, IPMI_MSG_DATARCV, }; struct ipmi_if bt_if = { "BT", IPMI_IF_BT_NREGS, bt_buildmsg, bt_sendmsg, bt_recvmsg, bt_reset, bt_probe, IPMI_BTMSG_DATASND, IPMI_BTMSG_DATARCV, }; struct ipmi_if *ipmi_get_if(int); struct ipmi_if * ipmi_get_if(int iftype) { switch (iftype) { case IPMI_IF_KCS: return (&kcs_if); case IPMI_IF_SMIC: return (&smic_if); case IPMI_IF_BT: return (&bt_if); } return (NULL); } /* * BMC Helper Functions */ u_int8_t bmc_read(struct ipmi_softc *sc, int offset) { if (sc->sc_if_iosize == 4) return (bus_space_read_4(sc->sc_iot, sc->sc_ioh, offset * sc->sc_if_iospacing)); else return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, offset * sc->sc_if_iospacing)); } void bmc_write(struct ipmi_softc *sc, int offset, u_int8_t val) { if (sc->sc_if_iosize == 4) bus_space_write_4(sc->sc_iot, sc->sc_ioh, offset * sc->sc_if_iospacing, val); else bus_space_write_1(sc->sc_iot, sc->sc_ioh, offset * sc->sc_if_iospacing, val); } int bmc_io_wait(struct ipmi_softc *sc, struct ipmi_iowait *a) { volatile u_int8_t v; int count = 5000000; /* == 5s XXX can be shorter */ while (count--) { v = bmc_read(sc, a->offset); if ((v & a->mask) == a->value) return v; delay(1); } dbg_printf(1, "%s: bmc_io_wait fails : *v=%.2x m=%.2x b=%.2x %s\n", DEVNAME(sc), v, a->mask, a->value, a->lbl); return (-1); } #define RSSA_MASK 0xff #define LUN_MASK 0x3 #define NETFN_LUN(nf,ln) (((nf) << 2) | ((ln) & LUN_MASK)) /* * BT interface */ #define _BT_CTRL_REG 0 #define BT_CLR_WR_PTR (1L << 0) #define BT_CLR_RD_PTR (1L << 1) #define BT_HOST2BMC_ATN (1L << 2) #define BT_BMC2HOST_ATN (1L << 3) #define BT_EVT_ATN (1L << 4) #define BT_HOST_BUSY (1L << 6) #define BT_BMC_BUSY (1L << 7) #define BT_READY (BT_HOST_BUSY|BT_HOST2BMC_ATN|BT_BMC2HOST_ATN) #define _BT_DATAIN_REG 1 #define _BT_DATAOUT_REG 1 #define _BT_INTMASK_REG 2 #define BT_IM_HIRQ_PEND (1L << 1) #define BT_IM_SCI_EN (1L << 2) #define BT_IM_SMI_EN (1L << 3) #define BT_IM_NMI2SMI (1L << 4) int bt_read(struct ipmi_softc *, int); int bt_write(struct ipmi_softc *, int, uint8_t); int bt_read(struct ipmi_softc *sc, int reg) { return bmc_read(sc, reg); } int bt_write(struct ipmi_softc *sc, int reg, uint8_t data) { struct ipmi_iowait a; a.offset = _BT_CTRL_REG; a.mask = BT_BMC_BUSY; a.value = 0; a.lbl = "bt_write"; if (bmc_io_wait(sc, &a) < 0) return (-1); bmc_write(sc, reg, data); return (0); } int bt_sendmsg(struct ipmi_cmd *c) { struct ipmi_softc *sc = c->c_sc; struct ipmi_iowait a; int i; bt_write(sc, _BT_CTRL_REG, BT_CLR_WR_PTR); for (i = 0; i < c->c_txlen; i++) bt_write(sc, _BT_DATAOUT_REG, sc->sc_buf[i]); bt_write(sc, _BT_CTRL_REG, BT_HOST2BMC_ATN); a.offset = _BT_CTRL_REG; a.mask = BT_HOST2BMC_ATN | BT_BMC_BUSY; a.value = 0; a.lbl = "bt_sendwait"; if (bmc_io_wait(sc, &a) < 0) return (-1); return (0); } int bt_recvmsg(struct ipmi_cmd *c) { struct ipmi_softc *sc = c->c_sc; struct ipmi_iowait a; u_int8_t len, v, i, j; a.offset = _BT_CTRL_REG; a.mask = BT_BMC2HOST_ATN; a.value = BT_BMC2HOST_ATN; a.lbl = "bt_recvwait"; if (bmc_io_wait(sc, &a) < 0) return (-1); bt_write(sc, _BT_CTRL_REG, BT_HOST_BUSY); bt_write(sc, _BT_CTRL_REG, BT_BMC2HOST_ATN); bt_write(sc, _BT_CTRL_REG, BT_CLR_RD_PTR); len = bt_read(sc, _BT_DATAIN_REG); for (i = IPMI_BTMSG_NFLN, j = 0; i <= len; i++) { v = bt_read(sc, _BT_DATAIN_REG); if (i != IPMI_BTMSG_SEQ) *(sc->sc_buf + j++) = v; } bt_write(sc, _BT_CTRL_REG, BT_HOST_BUSY); c->c_rxlen = len - 1; return (0); } int bt_reset(struct ipmi_softc *sc) { return (-1); } int bt_probe(struct ipmi_softc *sc) { u_int8_t rv; rv = bmc_read(sc, _BT_CTRL_REG); rv &= BT_HOST_BUSY; rv |= BT_CLR_WR_PTR|BT_CLR_RD_PTR|BT_BMC2HOST_ATN|BT_HOST2BMC_ATN; bmc_write(sc, _BT_CTRL_REG, rv); rv = bmc_read(sc, _BT_INTMASK_REG); rv &= BT_IM_SCI_EN|BT_IM_SMI_EN|BT_IM_NMI2SMI; rv |= BT_IM_HIRQ_PEND; bmc_write(sc, _BT_INTMASK_REG, rv); #if 0 printf("bt_probe: %2x\n", v); printf(" WR : %2x\n", v & BT_CLR_WR_PTR); printf(" RD : %2x\n", v & BT_CLR_RD_PTR); printf(" H2B : %2x\n", v & BT_HOST2BMC_ATN); printf(" B2H : %2x\n", v & BT_BMC2HOST_ATN); printf(" EVT : %2x\n", v & BT_EVT_ATN); printf(" HBSY : %2x\n", v & BT_HOST_BUSY); printf(" BBSY : %2x\n", v & BT_BMC_BUSY); #endif return (0); } /* * SMIC interface */ #define _SMIC_DATAIN_REG 0 #define _SMIC_DATAOUT_REG 0 #define _SMIC_CTRL_REG 1 #define SMS_CC_GET_STATUS 0x40 #define SMS_CC_START_TRANSFER 0x41 #define SMS_CC_NEXT_TRANSFER 0x42 #define SMS_CC_END_TRANSFER 0x43 #define SMS_CC_START_RECEIVE 0x44 #define SMS_CC_NEXT_RECEIVE 0x45 #define SMS_CC_END_RECEIVE 0x46 #define SMS_CC_TRANSFER_ABORT 0x47 #define SMS_SC_READY 0xc0 #define SMS_SC_WRITE_START 0xc1 #define SMS_SC_WRITE_NEXT 0xc2 #define SMS_SC_WRITE_END 0xc3 #define SMS_SC_READ_START 0xc4 #define SMS_SC_READ_NEXT 0xc5 #define SMS_SC_READ_END 0xc6 #define _SMIC_FLAG_REG 2 #define SMIC_BUSY (1L << 0) #define SMIC_SMS_ATN (1L << 2) #define SMIC_EVT_ATN (1L << 3) #define SMIC_SMI (1L << 4) #define SMIC_TX_DATA_RDY (1L << 6) #define SMIC_RX_DATA_RDY (1L << 7) int smic_wait(struct ipmi_softc *, u_int8_t, u_int8_t, const char *); int smic_write_cmd_data(struct ipmi_softc *, u_int8_t, const u_int8_t *); int smic_read_data(struct ipmi_softc *, u_int8_t *); int smic_wait(struct ipmi_softc *sc, u_int8_t mask, u_int8_t val, const char *lbl) { struct ipmi_iowait a; int v; /* Wait for expected flag bits */ a.offset = _SMIC_FLAG_REG; a.mask = mask; a.value = val; a.lbl = "smicwait"; v = bmc_io_wait(sc, &a); if (v < 0) return (-1); /* Return current status */ v = bmc_read(sc, _SMIC_CTRL_REG); dbg_printf(99, "smic_wait = %.2x\n", v); return (v); } int smic_write_cmd_data(struct ipmi_softc *sc, u_int8_t cmd, const u_int8_t *data) { int sts, v; dbg_printf(50, "smic_wcd: %.2x %.2x\n", cmd, data ? *data : -1); sts = smic_wait(sc, SMIC_TX_DATA_RDY | SMIC_BUSY, SMIC_TX_DATA_RDY, "smic_write_cmd_data ready"); if (sts < 0) return (sts); bmc_write(sc, _SMIC_CTRL_REG, cmd); if (data) bmc_write(sc, _SMIC_DATAOUT_REG, *data); /* Toggle BUSY bit, then wait for busy bit to clear */ v = bmc_read(sc, _SMIC_FLAG_REG); bmc_write(sc, _SMIC_FLAG_REG, v | SMIC_BUSY); return (smic_wait(sc, SMIC_BUSY, 0, "smic_write_cmd_data busy")); } int smic_read_data(struct ipmi_softc *sc, u_int8_t *data) { int sts; sts = smic_wait(sc, SMIC_RX_DATA_RDY | SMIC_BUSY, SMIC_RX_DATA_RDY, "smic_read_data"); if (sts >= 0) { *data = bmc_read(sc, _SMIC_DATAIN_REG); dbg_printf(50, "smic_readdata: %.2x\n", *data); } return (sts); } #define ErrStat(a,b) if (a) printf(b); int smic_sendmsg(struct ipmi_cmd *c) { struct ipmi_softc *sc = c->c_sc; int sts, idx; sts = smic_write_cmd_data(sc, SMS_CC_START_TRANSFER, &sc->sc_buf[0]); ErrStat(sts != SMS_SC_WRITE_START, "wstart"); for (idx = 1; idx < c->c_txlen - 1; idx++) { sts = smic_write_cmd_data(sc, SMS_CC_NEXT_TRANSFER, &sc->sc_buf[idx]); ErrStat(sts != SMS_SC_WRITE_NEXT, "write"); } sts = smic_write_cmd_data(sc, SMS_CC_END_TRANSFER, &sc->sc_buf[idx]); if (sts != SMS_SC_WRITE_END) { dbg_printf(50, "smic_sendmsg %d/%d = %.2x\n", idx, c->c_txlen, sts); return (-1); } return (0); } int smic_recvmsg(struct ipmi_cmd *c) { struct ipmi_softc *sc = c->c_sc; int sts, idx; c->c_rxlen = 0; sts = smic_wait(sc, SMIC_RX_DATA_RDY, SMIC_RX_DATA_RDY, "smic_recvmsg"); if (sts < 0) return (-1); sts = smic_write_cmd_data(sc, SMS_CC_START_RECEIVE, NULL); ErrStat(sts != SMS_SC_READ_START, "rstart"); for (idx = 0;; ) { sts = smic_read_data(sc, &sc->sc_buf[idx++]); if (sts != SMS_SC_READ_START && sts != SMS_SC_READ_NEXT) break; smic_write_cmd_data(sc, SMS_CC_NEXT_RECEIVE, NULL); } ErrStat(sts != SMS_SC_READ_END, "rend"); c->c_rxlen = idx; sts = smic_write_cmd_data(sc, SMS_CC_END_RECEIVE, NULL); if (sts != SMS_SC_READY) { dbg_printf(50, "smic_recvmsg %d/%d = %.2x\n", idx, c->c_maxrxlen, sts); return (-1); } return (0); } int smic_reset(struct ipmi_softc *sc) { return (-1); } int smic_probe(struct ipmi_softc *sc) { /* Flag register should not be 0xFF on a good system */ if (bmc_read(sc, _SMIC_FLAG_REG) == 0xFF) return (-1); return (0); } /* * KCS interface */ #define _KCS_DATAIN_REGISTER 0 #define _KCS_DATAOUT_REGISTER 0 #define KCS_READ_NEXT 0x68 #define _KCS_COMMAND_REGISTER 1 #define KCS_GET_STATUS 0x60 #define KCS_WRITE_START 0x61 #define KCS_WRITE_END 0x62 #define _KCS_STATUS_REGISTER 1 #define KCS_OBF (1L << 0) #define KCS_IBF (1L << 1) #define KCS_SMS_ATN (1L << 2) #define KCS_CD (1L << 3) #define KCS_OEM1 (1L << 4) #define KCS_OEM2 (1L << 5) #define KCS_STATE_MASK 0xc0 #define KCS_IDLE_STATE 0x00 #define KCS_READ_STATE 0x40 #define KCS_WRITE_STATE 0x80 #define KCS_ERROR_STATE 0xC0 int kcs_wait(struct ipmi_softc *, u_int8_t, u_int8_t, const char *); int kcs_write_cmd(struct ipmi_softc *, u_int8_t); int kcs_write_data(struct ipmi_softc *, u_int8_t); int kcs_read_data(struct ipmi_softc *, u_int8_t *); int kcs_wait(struct ipmi_softc *sc, u_int8_t mask, u_int8_t value, const char *lbl) { struct ipmi_iowait a; int v; a.offset = _KCS_STATUS_REGISTER; a.mask = mask; a.value = value; a.lbl = lbl; v = bmc_io_wait(sc, &a); if (v < 0) return (v); /* Check if output buffer full, read dummy byte */ if ((v & (KCS_OBF | KCS_STATE_MASK)) == (KCS_OBF | KCS_WRITE_STATE)) bmc_read(sc, _KCS_DATAIN_REGISTER); /* Check for error state */ if ((v & KCS_STATE_MASK) == KCS_ERROR_STATE) { bmc_write(sc, _KCS_COMMAND_REGISTER, KCS_GET_STATUS); while (bmc_read(sc, _KCS_STATUS_REGISTER) & KCS_IBF) continue; printf("%s: error code: %x\n", DEVNAME(sc), bmc_read(sc, _KCS_DATAIN_REGISTER)); } return (v & KCS_STATE_MASK); } int kcs_write_cmd(struct ipmi_softc *sc, u_int8_t cmd) { /* ASSERT: IBF and OBF are clear */ dbg_printf(50, "kcswritecmd: %.2x\n", cmd); bmc_write(sc, _KCS_COMMAND_REGISTER, cmd); return (kcs_wait(sc, KCS_IBF, 0, "write_cmd")); } int kcs_write_data(struct ipmi_softc *sc, u_int8_t data) { /* ASSERT: IBF and OBF are clear */ dbg_printf(50, "kcswritedata: %.2x\n", data); bmc_write(sc, _KCS_DATAOUT_REGISTER, data); return (kcs_wait(sc, KCS_IBF, 0, "write_data")); } int kcs_read_data(struct ipmi_softc *sc, u_int8_t * data) { int sts; sts = kcs_wait(sc, KCS_IBF | KCS_OBF, KCS_OBF, "read_data"); if (sts != KCS_READ_STATE) return (sts); /* ASSERT: OBF is set read data, request next byte */ *data = bmc_read(sc, _KCS_DATAIN_REGISTER); bmc_write(sc, _KCS_DATAOUT_REGISTER, KCS_READ_NEXT); dbg_printf(50, "kcsreaddata: %.2x\n", *data); return (sts); } /* Exported KCS functions */ int kcs_sendmsg(struct ipmi_cmd *c) { struct ipmi_softc *sc = c->c_sc; int idx, sts; /* ASSERT: IBF is clear */ dbg_dump(50, "kcs sendmsg", c->c_txlen, sc->sc_buf); sts = kcs_write_cmd(sc, KCS_WRITE_START); for (idx = 0; idx < c->c_txlen; idx++) { if (idx == c->c_txlen - 1) sts = kcs_write_cmd(sc, KCS_WRITE_END); if (sts != KCS_WRITE_STATE) break; sts = kcs_write_data(sc, sc->sc_buf[idx]); } if (sts != KCS_READ_STATE) { dbg_printf(1, "kcs sendmsg = %d/%d <%.2x>\n", idx, c->c_txlen, sts); dbg_dump(1, "kcs_sendmsg", c->c_txlen, sc->sc_buf); return (-1); } return (0); } int kcs_recvmsg(struct ipmi_cmd *c) { struct ipmi_softc *sc = c->c_sc; int idx, sts; for (idx = 0; idx < c->c_maxrxlen; idx++) { sts = kcs_read_data(sc, &sc->sc_buf[idx]); if (sts != KCS_READ_STATE) break; } sts = kcs_wait(sc, KCS_IBF, 0, "recv"); c->c_rxlen = idx; if (sts != KCS_IDLE_STATE) { dbg_printf(1, "kcs recvmsg = %d/%d <%.2x>\n", idx, c->c_maxrxlen, sts); return (-1); } dbg_dump(50, "kcs recvmsg", idx, sc->sc_buf); return (0); } int kcs_reset(struct ipmi_softc *sc) { return (-1); } int kcs_probe(struct ipmi_softc *sc) { u_int8_t v; v = bmc_read(sc, _KCS_STATUS_REGISTER); if ((v & KCS_STATE_MASK) == KCS_ERROR_STATE) return (1); #if 0 printf("kcs_probe: %2x\n", v); printf(" STS: %2x\n", v & KCS_STATE_MASK); printf(" ATN: %2x\n", v & KCS_SMS_ATN); printf(" C/D: %2x\n", v & KCS_CD); printf(" IBF: %2x\n", v & KCS_IBF); printf(" OBF: %2x\n", v & KCS_OBF); #endif return (0); } /* * IPMI code */ #define READ_SMS_BUFFER 0x37 #define WRITE_I2C 0x50 #define GET_MESSAGE_CMD 0x33 #define SEND_MESSAGE_CMD 0x34 #define IPMB_CHANNEL_NUMBER 0 #define PUBLIC_BUS 0 #define MIN_I2C_PACKET_SIZE 3 #define MIN_IMB_PACKET_SIZE 7 /* one byte for cksum */ #define MIN_BTBMC_REQ_SIZE 4 #define MIN_BTBMC_RSP_SIZE 5 #define MIN_BMC_REQ_SIZE 2 #define MIN_BMC_RSP_SIZE 3 #define BMC_SA 0x20 /* BMC/ESM3 */ #define FPC_SA 0x22 /* front panel */ #define BP_SA 0xC0 /* Primary Backplane */ #define BP2_SA 0xC2 /* Secondary Backplane */ #define PBP_SA 0xC4 /* Peripheral Backplane */ #define DRAC_SA 0x28 /* DRAC-III */ #define DRAC3_SA 0x30 /* DRAC-III */ #define BMC_LUN 0 #define SMS_LUN 2 struct ipmi_request { u_int8_t rsSa; u_int8_t rsLun; u_int8_t netFn; u_int8_t cmd; u_int8_t data_len; u_int8_t *data; }; struct ipmi_response { u_int8_t cCode; u_int8_t data_len; u_int8_t *data; }; struct ipmi_bmc_request { u_int8_t bmc_nfLn; u_int8_t bmc_cmd; u_int8_t bmc_data_len; u_int8_t bmc_data[1]; }; struct ipmi_bmc_response { u_int8_t bmc_nfLn; u_int8_t bmc_cmd; u_int8_t bmc_cCode; u_int8_t bmc_data_len; u_int8_t bmc_data[1]; }; struct cfdriver ipmi_cd = { NULL, "ipmi", DV_DULL }; void dumpb(const char *lbl, int len, const u_int8_t *data) { int idx; printf("%s: ", lbl); for (idx = 0; idx < len; idx++) printf("%.2x ", data[idx]); printf("\n"); } /* * bt_buildmsg builds an IPMI message from a nfLun, cmd, and data * This is used by BT protocol */ void bt_buildmsg(struct ipmi_cmd *c) { struct ipmi_softc *sc = c->c_sc; u_int8_t *buf = sc->sc_buf; buf[IPMI_BTMSG_LEN] = c->c_txlen + (IPMI_BTMSG_DATASND - 1); buf[IPMI_BTMSG_NFLN] = NETFN_LUN(c->c_netfn, c->c_rslun); buf[IPMI_BTMSG_SEQ] = sc->sc_btseq++; buf[IPMI_BTMSG_CMD] = c->c_cmd; if (c->c_txlen && c->c_data) memcpy(buf + IPMI_BTMSG_DATASND, c->c_data, c->c_txlen); } /* * cmn_buildmsg builds an IPMI message from a nfLun, cmd, and data * This is used by both SMIC and KCS protocols */ void cmn_buildmsg(struct ipmi_cmd *c) { struct ipmi_softc *sc = c->c_sc; u_int8_t *buf = sc->sc_buf; buf[IPMI_MSG_NFLN] = NETFN_LUN(c->c_netfn, c->c_rslun); buf[IPMI_MSG_CMD] = c->c_cmd; if (c->c_txlen && c->c_data) memcpy(buf + IPMI_MSG_DATASND, c->c_data, c->c_txlen); } /* Send an IPMI command */ int ipmi_sendcmd(struct ipmi_cmd *c) { struct ipmi_softc *sc = c->c_sc; int rc = -1; dbg_printf(50, "ipmi_sendcmd: rssa=%.2x nfln=%.2x cmd=%.2x len=%.2x\n", c->c_rssa, NETFN_LUN(c->c_netfn, c->c_rslun), c->c_cmd, c->c_txlen); dbg_dump(10, " send", c->c_txlen, c->c_data); if (c->c_rssa != BMC_SA) { #if 0 sc->sc_if->buildmsg(c); pI2C->bus = (sc->if_ver == 0x09) ? PUBLIC_BUS : IPMB_CHANNEL_NUMBER; imbreq->rsSa = rssa; imbreq->nfLn = NETFN_LUN(netfn, rslun); imbreq->cSum1 = -(imbreq->rsSa + imbreq->nfLn); imbreq->rqSa = BMC_SA; imbreq->seqLn = NETFN_LUN(sc->imb_seq++, SMS_LUN); imbreq->cmd = cmd; if (txlen) memcpy(imbreq->data, data, txlen); /* Set message checksum */ imbreq->data[txlen] = cksum8(&imbreq->rqSa, txlen + 3); #endif goto done; } else sc->sc_if->buildmsg(c); c->c_txlen += sc->sc_if->datasnd; rc = sc->sc_if->sendmsg(c); done: return (rc); } /* Receive an IPMI command */ int ipmi_recvcmd(struct ipmi_cmd *c) { struct ipmi_softc *sc = c->c_sc; u_int8_t *buf = sc->sc_buf, rc = 0; /* Receive message from interface, copy out result data */ c->c_maxrxlen += sc->sc_if->datarcv; if (sc->sc_if->recvmsg(c) || c->c_rxlen < sc->sc_if->datarcv) { return (-1); } c->c_rxlen -= sc->sc_if->datarcv; if (c->c_rxlen > 0 && c->c_data) memcpy(c->c_data, buf + sc->sc_if->datarcv, c->c_rxlen); rc = buf[IPMI_MSG_CCODE]; #ifdef IPMI_DEBUG if (rc != 0) dbg_printf(1, "ipmi_recvcmd: nfln=%.2x cmd=%.2x err=%.2x\n", buf[IPMI_MSG_NFLN], buf[IPMI_MSG_CMD], buf[IPMI_MSG_CCODE]); #endif dbg_printf(50, "ipmi_recvcmd: nfln=%.2x cmd=%.2x err=%.2x len=%.2x\n", buf[IPMI_MSG_NFLN], buf[IPMI_MSG_CMD], buf[IPMI_MSG_CCODE], c->c_rxlen); dbg_dump(10, " recv", c->c_rxlen, c->c_data); return (rc); } void ipmi_cmd(struct ipmi_cmd *c) { if (cold || panicstr != NULL) ipmi_cmd_poll(c); else ipmi_cmd_wait(c); } void ipmi_cmd_poll(struct ipmi_cmd *c) { if ((c->c_ccode = ipmi_sendcmd(c))) printf("%s: sendcmd fails\n", DEVNAME(c->c_sc)); else c->c_ccode = ipmi_recvcmd(c); } void ipmi_cmd_wait(struct ipmi_cmd *c) { struct task t; int res; task_set(&t, ipmi_cmd_wait_cb, c); res = task_add(c->c_sc->sc_cmd_taskq, &t); KASSERT(res == 1); tsleep_nsec(c, PWAIT, "ipmicmd", INFSLP); res = task_del(c->c_sc->sc_cmd_taskq, &t); KASSERT(res == 0); } void ipmi_cmd_wait_cb(void *arg) { struct ipmi_cmd *c = arg; ipmi_cmd_poll(c); wakeup(c); } /* Read a partial SDR entry */ int get_sdr_partial(struct ipmi_softc *sc, u_int16_t recordId, u_int16_t reserveId, u_int8_t offset, u_int8_t length, void *buffer, u_int16_t *nxtRecordId) { u_int8_t cmd[IPMI_GET_WDOG_MAX + 255]; /* 8 + max of length */ int len; ((u_int16_t *) cmd)[0] = reserveId; ((u_int16_t *) cmd)[1] = recordId; cmd[4] = offset; cmd[5] = length; struct ipmi_cmd c; c.c_sc = sc; c.c_rssa = BMC_SA; c.c_rslun = BMC_LUN; c.c_netfn = STORAGE_NETFN; c.c_cmd = STORAGE_GET_SDR; c.c_txlen = IPMI_SET_WDOG_MAX; c.c_rxlen = 0; c.c_maxrxlen = 8 + length; c.c_data = cmd; ipmi_cmd(&c); len = c.c_rxlen; if (nxtRecordId) *nxtRecordId = *(uint16_t *) cmd; if (len > 2) memcpy(buffer, cmd + 2, len - 2); else return (1); return (0); } int maxsdrlen = 0x10; /* Read an entire SDR; pass to add sensor */ int get_sdr(struct ipmi_softc *sc, u_int16_t recid, u_int16_t *nxtrec) { u_int16_t resid = 0; int len, sdrlen, offset; u_int8_t *psdr; struct sdrhdr shdr; /* Reserve SDR */ struct ipmi_cmd c; c.c_sc = sc; c.c_rssa = BMC_SA; c.c_rslun = BMC_LUN; c.c_netfn = STORAGE_NETFN; c.c_cmd = STORAGE_RESERVE_SDR; c.c_txlen = 0; c.c_maxrxlen = sizeof(resid); c.c_rxlen = 0; c.c_data = &resid; ipmi_cmd(&c); /* Get SDR Header */ if (get_sdr_partial(sc, recid, resid, 0, sizeof shdr, &shdr, nxtrec)) { printf("%s: get header fails\n", DEVNAME(sc)); return (1); } /* Allocate space for entire SDR Length of SDR in header does not * include header length */ sdrlen = sizeof(shdr) + shdr.record_length; psdr = malloc(sdrlen, M_DEVBUF, M_NOWAIT); if (psdr == NULL) return (1); memcpy(psdr, &shdr, sizeof(shdr)); /* Read SDR Data maxsdrlen bytes at a time */ for (offset = sizeof(shdr); offset < sdrlen; offset += maxsdrlen) { len = sdrlen - offset; if (len > maxsdrlen) len = maxsdrlen; if (get_sdr_partial(sc, recid, resid, offset, len, psdr + offset, NULL)) { printf("%s: get chunk: %d,%d fails\n", DEVNAME(sc), offset, len); free(psdr, M_DEVBUF, sdrlen); return (1); } } /* Add SDR to sensor list, if not wanted, free buffer */ if (add_sdr_sensor(sc, psdr, sdrlen) == 0) free(psdr, M_DEVBUF, sdrlen); return (0); } int getbits(u_int8_t *bytes, int bitpos, int bitlen) { int v; int mask; bitpos += bitlen - 1; for (v = 0; bitlen--;) { v <<= 1; mask = 1L << (bitpos & 7); if (bytes[bitpos >> 3] & mask) v |= 1; bitpos--; } return (v); } /* Decode IPMI sensor name */ int ipmi_sensor_name(char *name, int len, u_int8_t typelen, u_int8_t *bits, int bitslen) { int i, slen; char bcdplus[] = "0123456789 -.:,_"; slen = typelen & 0x1F; switch (typelen >> 6) { case IPMI_NAME_UNICODE: //unicode break; case IPMI_NAME_BCDPLUS: /* Characters are encoded in 4-bit BCDPLUS */ if (len < slen * 2 + 1) slen = (len >> 1) - 1; if (slen > bitslen) return (0); for (i = 0; i < slen; i++) { *(name++) = bcdplus[bits[i] >> 4]; *(name++) = bcdplus[bits[i] & 0xF]; } break; case IPMI_NAME_ASCII6BIT: /* Characters are encoded in 6-bit ASCII * 0x00 - 0x3F maps to 0x20 - 0x5F */ /* XXX: need to calculate max len: slen = 3/4 * len */ if (len < slen + 1) slen = len - 1; if (slen * 6 / 8 > bitslen) return (0); for (i = 0; i < slen * 8; i += 6) { *(name++) = getbits(bits, i, 6) + ' '; } break; case IPMI_NAME_ASCII8BIT: /* Characters are 8-bit ascii */ if (len < slen + 1) slen = len - 1; if (slen > bitslen) return (0); while (slen--) *(name++) = *(bits++); break; } *name = 0; return (1); } /* Calculate val * 10^exp */ long ipow(long val, int exp) { while (exp > 0) { val *= 10; exp--; } while (exp < 0) { val /= 10; exp++; } return (val); } /* Sign extend a n-bit value */ long signextend(unsigned long val, int bits) { long msk = (1L << (bits-1))-1; return (-(val & ~msk) | val); } /* Convert IPMI reading from sensor factors */ long ipmi_convert(u_int8_t v, struct sdrtype1 *s1, long adj) { int16_t M, B; int8_t K1, K2; long val; /* Calculate linear reading variables */ M = signextend((((short)(s1->m_tolerance & 0xC0)) << 2) + s1->m, 10); B = signextend((((short)(s1->b_accuracy & 0xC0)) << 2) + s1->b, 10); K1 = signextend(s1->rbexp & 0xF, 4); K2 = signextend(s1->rbexp >> 4, 4); /* Calculate sensor reading: * y = L((M * v + (B * 10^K1)) * 10^(K2+adj) * * This commutes out to: * y = L(M*v * 10^(K2+adj) + B * 10^(K1+K2+adj)); */ val = ipow(M * v, K2 + adj) + ipow(B, K1 + K2 + adj); /* Linearization function: y = f(x) 0 : y = x 1 : y = ln(x) 2 : y = * log10(x) 3 : y = log2(x) 4 : y = e^x 5 : y = 10^x 6 : y = 2^x 7 : y * = 1/x 8 : y = x^2 9 : y = x^3 10 : y = square root(x) 11 : y = cube * root(x) */ return (val); } int ipmi_sensor_status(struct ipmi_softc *sc, struct ipmi_sensor *psensor, u_int8_t *reading) { struct sdrtype1 *s1 = (struct sdrtype1 *)psensor->i_sdr; int etype; /* Get reading of sensor */ switch (psensor->i_sensor.type) { case SENSOR_TEMP: psensor->i_sensor.value = ipmi_convert(reading[0], s1, 6); psensor->i_sensor.value += 273150000; break; case SENSOR_VOLTS_DC: case SENSOR_VOLTS_AC: case SENSOR_AMPS: case SENSOR_WATTS: psensor->i_sensor.value = ipmi_convert(reading[0], s1, 6); break; case SENSOR_FANRPM: psensor->i_sensor.value = ipmi_convert(reading[0], s1, 0); if (((s1->units1>>3)&0x7) == 0x3) psensor->i_sensor.value *= 60; // RPS -> RPM break; default: break; } /* Return Sensor Status */ etype = (psensor->etype << 8) + psensor->stype; switch (etype) { case IPMI_SENSOR_TYPE_TEMP: case IPMI_SENSOR_TYPE_VOLT: case IPMI_SENSOR_TYPE_CURRENT: case IPMI_SENSOR_TYPE_FAN: /* non-recoverable threshold */ if (reading[2] & ((1 << 5) | (1 << 2))) return (SENSOR_S_CRIT); /* critical threshold */ else if (reading[2] & ((1 << 4) | (1 << 1))) return (SENSOR_S_CRIT); /* non-critical threshold */ else if (reading[2] & ((1 << 3) | (1 << 0))) return (SENSOR_S_WARN); break; case IPMI_SENSOR_TYPE_INTRUSION: psensor->i_sensor.value = (reading[2] & 1) ? 1 : 0; if (reading[2] & 0x1) return (SENSOR_S_CRIT); break; case IPMI_SENSOR_TYPE_PWRSUPPLY: /* Reading: 1 = present+powered, 0 = otherwise */ psensor->i_sensor.value = (reading[2] & 1) ? 1 : 0; if (reading[2] & 0x10) { /* XXX: Need sysctl type for Power Supply types * ok: power supply installed && powered * warn: power supply installed && !powered * crit: power supply !installed */ return (SENSOR_S_CRIT); } if (reading[2] & 0x08) { /* Power supply AC lost */ return (SENSOR_S_WARN); } break; } return (SENSOR_S_OK); } int read_sensor(struct ipmi_softc *sc, struct ipmi_sensor *psensor) { struct sdrtype1 *s1 = (struct sdrtype1 *) psensor->i_sdr; u_int8_t data[8]; int rv = -1; memset(data, 0, sizeof(data)); data[0] = psensor->i_num; struct ipmi_cmd c; c.c_sc = sc; c.c_rssa = s1->owner_id; c.c_rslun = s1->owner_lun; c.c_netfn = SE_NETFN; c.c_cmd = SE_GET_SENSOR_READING; c.c_txlen = 1; c.c_maxrxlen = sizeof(data); c.c_rxlen = 0; c.c_data = data; ipmi_cmd(&c); if (c.c_ccode != 0) { dbg_printf(1, "sensor reading command for %s failed: %.2x\n", psensor->i_sensor.desc, c.c_ccode); return (rv); } dbg_printf(10, "values=%.2x %.2x %.2x %.2x %s\n", data[0],data[1],data[2],data[3], psensor->i_sensor.desc); psensor->i_sensor.flags &= ~SENSOR_FINVALID; if ((data[1] & IPMI_INVALID_SENSOR) || ((data[1] & IPMI_DISABLED_SENSOR) == 0 && data[0] == 0)) psensor->i_sensor.flags |= SENSOR_FINVALID; psensor->i_sensor.status = ipmi_sensor_status(sc, psensor, data); rv = 0; return (rv); } int ipmi_sensor_type(int type, int ext_type, int units2, int entity) { switch (units2) { case IPMI_UNIT_TYPE_AMPS: return (SENSOR_AMPS); case IPMI_UNIT_TYPE_RPM: return (SENSOR_FANRPM); /* XXX sensors framework distinguishes AC/DC but ipmi does not */ case IPMI_UNIT_TYPE_VOLTS: return (SENSOR_VOLTS_DC); case IPMI_UNIT_TYPE_WATTS: return (SENSOR_WATTS); } switch (ext_type << 8L | type) { case IPMI_SENSOR_TYPE_TEMP: return (SENSOR_TEMP); case IPMI_SENSOR_TYPE_PWRSUPPLY: if (entity == IPMI_ENTITY_PWRSUPPLY) return (SENSOR_INDICATOR); break; case IPMI_SENSOR_TYPE_INTRUSION: return (SENSOR_INDICATOR); } return (-1); } /* Add Sensor to BSD Sysctl interface */ int add_sdr_sensor(struct ipmi_softc *sc, u_int8_t *psdr, int sdrlen) { int rc; struct sdrtype1 *s1 = (struct sdrtype1 *)psdr; struct sdrtype2 *s2 = (struct sdrtype2 *)psdr; char name[64]; switch (s1->sdrhdr.record_type) { case IPMI_SDR_TYPEFULL: rc = ipmi_sensor_name(name, sizeof(name), s1->typelen, s1->name, sdrlen - (int)offsetof(struct sdrtype1, name)); if (rc == 0) return (0); rc = add_child_sensors(sc, psdr, 1, s1->sensor_num, s1->sensor_type, s1->event_code, 0, s1->entity_id, name); break; case IPMI_SDR_TYPECOMPACT: rc = ipmi_sensor_name(name, sizeof(name), s2->typelen, s2->name, sdrlen - (int)offsetof(struct sdrtype2, name)); if (rc == 0) return (0); rc = add_child_sensors(sc, psdr, s2->share1 & 0xF, s2->sensor_num, s2->sensor_type, s2->event_code, s2->share2 & 0x7F, s2->entity_id, name); break; default: return (0); } return rc; } int add_child_sensors(struct ipmi_softc *sc, u_int8_t *psdr, int count, int sensor_num, int sensor_type, int ext_type, int sensor_base, int entity, const char *name) { int typ, idx, rc = 0; struct ipmi_sensor *psensor; struct sdrtype1 *s1 = (struct sdrtype1 *)psdr; typ = ipmi_sensor_type(sensor_type, ext_type, s1->units2, entity); if (typ == -1) { dbg_printf(5, "Unknown sensor type:%.2x et:%.2x sn:%.2x " "units2:%u name:%s\n", sensor_type, ext_type, sensor_num, s1->units2, name); return 0; } for (idx = 0; idx < count; idx++) { psensor = malloc(sizeof(*psensor), M_DEVBUF, M_NOWAIT | M_ZERO); if (psensor == NULL) break; /* Initialize BSD Sensor info */ psensor->i_sdr = psdr; psensor->i_num = sensor_num + idx; psensor->stype = sensor_type; psensor->etype = ext_type; psensor->i_sensor.type = typ; if (count > 1) snprintf(psensor->i_sensor.desc, sizeof(psensor->i_sensor.desc), "%s - %d", name, sensor_base + idx); else strlcpy(psensor->i_sensor.desc, name, sizeof(psensor->i_sensor.desc)); dbg_printf(5, "add sensor:%.4x %.2x:%d ent:%.2x:%.2x %s\n", s1->sdrhdr.record_id, s1->sensor_type, typ, s1->entity_id, s1->entity_instance, psensor->i_sensor.desc); if (read_sensor(sc, psensor) == 0) { SLIST_INSERT_HEAD(&ipmi_sensor_list, psensor, list); sensor_attach(&sc->sc_sensordev, &psensor->i_sensor); dbg_printf(5, " reading: %lld [%s]\n", psensor->i_sensor.value, psensor->i_sensor.desc); rc = 1; } else free(psensor, M_DEVBUF, sizeof(*psensor)); } return (rc); } /* Handle IPMI Timer - reread sensor values */ void ipmi_refresh_sensors(struct ipmi_softc *sc) { if (SLIST_EMPTY(&ipmi_sensor_list)) return; sc->current_sensor = SLIST_NEXT(sc->current_sensor, list); if (sc->current_sensor == NULL) sc->current_sensor = SLIST_FIRST(&ipmi_sensor_list); if (read_sensor(sc, sc->current_sensor)) { dbg_printf(1, "%s: error reading: %s\n", DEVNAME(sc), sc->current_sensor->i_sensor.desc); return; } } int ipmi_map_regs(struct ipmi_softc *sc, struct ipmi_attach_args *ia) { if (sc->sc_if && sc->sc_if->nregs == 0) return (0); sc->sc_if = ipmi_get_if(ia->iaa_if_type); if (sc->sc_if == NULL) return (-1); if (ia->iaa_if_iotype == 'i') sc->sc_iot = ia->iaa_iot; else sc->sc_iot = ia->iaa_memt; sc->sc_if_rev = ia->iaa_if_rev; sc->sc_if_iosize = ia->iaa_if_iosize; sc->sc_if_iospacing = ia->iaa_if_iospacing; if (bus_space_map(sc->sc_iot, ia->iaa_if_iobase, sc->sc_if->nregs * sc->sc_if_iospacing, 0, &sc->sc_ioh)) { printf("%s: bus_space_map(%lx %lx %x 0 %p) failed\n", DEVNAME(sc), (unsigned long)sc->sc_iot, ia->iaa_if_iobase, sc->sc_if->nregs * sc->sc_if_iospacing, &sc->sc_ioh); return (-1); } return (0); } void ipmi_unmap_regs(struct ipmi_softc *sc) { if (sc->sc_if->nregs > 0) { bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_if->nregs * sc->sc_if_iospacing); } } void ipmi_poll_thread(void *arg) { struct ipmi_thread *thread = arg; struct ipmi_softc *sc = thread->sc; u_int16_t rec; /* Scan SDRs, add sensors */ for (rec = 0; rec != 0xFFFF;) { if (get_sdr(sc, rec, &rec)) { ipmi_unmap_regs(sc); printf("%s: no SDRs IPMI disabled\n", DEVNAME(sc)); goto done; } tsleep_nsec(sc, PWAIT, "ipmirun", MSEC_TO_NSEC(1)); } /* initialize sensor list for thread */ if (SLIST_EMPTY(&ipmi_sensor_list)) goto done; else sc->current_sensor = SLIST_FIRST(&ipmi_sensor_list); strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, sizeof(sc->sc_sensordev.xname)); sensordev_install(&sc->sc_sensordev); while (thread->running) { ipmi_refresh_sensors(sc); tsleep_nsec(thread, PWAIT, "ipmi_poll", SEC_TO_NSEC(SENSOR_REFRESH_RATE)); } done: kthread_exit(0); } void ipmi_create_thread(void *arg) { struct ipmi_softc *sc = arg; if (kthread_create(ipmi_poll_thread, sc->sc_thread, NULL, DEVNAME(sc)) != 0) { printf("%s: unable to create run thread, ipmi disabled\n", DEVNAME(sc)); return; } } void ipmi_attach_common(struct ipmi_softc *sc, struct ipmi_attach_args *ia) { struct ipmi_cmd *c = &sc->sc_ioctl.cmd; /* Map registers */ ipmi_map_regs(sc, ia); sc->sc_thread = malloc(sizeof(struct ipmi_thread), M_DEVBUF, M_NOWAIT); if (sc->sc_thread == NULL) { printf(": unable to allocate thread\n"); return; } sc->sc_thread->sc = sc; sc->sc_thread->running = 1; /* Setup threads */ kthread_create_deferred(ipmi_create_thread, sc); printf(": version %d.%d interface %s", ia->iaa_if_rev >> 4, ia->iaa_if_rev & 0xF, sc->sc_if->name); if (sc->sc_if->nregs > 0) printf(" %sbase 0x%lx/%x spacing %d", ia->iaa_if_iotype == 'i' ? "io" : "mem", ia->iaa_if_iobase, ia->iaa_if_iospacing * sc->sc_if->nregs, ia->iaa_if_iospacing); if (ia->iaa_if_irq != -1) printf(" irq %d", ia->iaa_if_irq); printf("\n"); /* setup flag to exclude iic */ ipmi_enabled = 1; /* Setup Watchdog timer */ sc->sc_wdog_period = 0; task_set(&sc->sc_wdog_tickle_task, ipmi_watchdog_tickle, sc); wdog_register(ipmi_watchdog, sc); rw_init(&sc->sc_ioctl.lock, DEVNAME(sc)); sc->sc_ioctl.req.msgid = -1; c->c_sc = sc; c->c_ccode = -1; sc->sc_cmd_taskq = taskq_create("ipmicmd", 1, IPL_MPFLOOR, TASKQ_MPSAFE); } int ipmi_activate(struct device *self, int act) { switch (act) { case DVACT_POWERDOWN: wdog_shutdown(self); break; } return (0); } struct ipmi_softc * ipmilookup(dev_t dev) { return (struct ipmi_softc *)device_lookup(&ipmi_cd, minor(dev)); } int ipmiopen(dev_t dev, int flags, int mode, struct proc *p) { struct ipmi_softc *sc = ipmilookup(dev); if (sc == NULL) return (ENXIO); return (0); } int ipmiclose(dev_t dev, int flags, int mode, struct proc *p) { struct ipmi_softc *sc = ipmilookup(dev); if (sc == NULL) return (ENXIO); return (0); } int ipmiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *proc) { struct ipmi_softc *sc = ipmilookup(dev); struct ipmi_req *req = (struct ipmi_req *)data; struct ipmi_recv *recv = (struct ipmi_recv *)data; struct ipmi_cmd *c = &sc->sc_ioctl.cmd; int iv; int len; u_char ccode; int rc = 0; if (sc == NULL) return (ENXIO); rw_enter_write(&sc->sc_ioctl.lock); c->c_maxrxlen = sizeof(sc->sc_ioctl.buf); c->c_data = sc->sc_ioctl.buf; switch (cmd) { case IPMICTL_SEND_COMMAND: if (req->msgid == -1) { rc = EINVAL; goto reset; } if (sc->sc_ioctl.req.msgid != -1) { rc = EBUSY; goto reset; } len = req->msg.data_len; if (len < 0) { rc = EINVAL; goto reset; } if (len > c->c_maxrxlen) { rc = E2BIG; goto reset; } sc->sc_ioctl.req = *req; c->c_ccode = -1; rc = copyin(req->msg.data, c->c_data, len); if (rc != 0) goto reset; KASSERT(c->c_ccode == -1); /* Execute a command synchronously. */ c->c_netfn = req->msg.netfn; c->c_cmd = req->msg.cmd; c->c_txlen = req->msg.data_len; c->c_rxlen = 0; ipmi_cmd(c); break; case IPMICTL_RECEIVE_MSG_TRUNC: case IPMICTL_RECEIVE_MSG: if (sc->sc_ioctl.req.msgid == -1) { rc = EINVAL; goto reset; } if (c->c_ccode == -1) { rc = EAGAIN; goto reset; } ccode = c->c_ccode & 0xff; rc = copyout(&ccode, recv->msg.data, 1); if (rc != 0) goto reset; /* Return a command result. */ recv->recv_type = IPMI_RESPONSE_RECV_TYPE; recv->msgid = sc->sc_ioctl.req.msgid; recv->msg.netfn = sc->sc_ioctl.req.msg.netfn; recv->msg.cmd = sc->sc_ioctl.req.msg.cmd; recv->msg.data_len = c->c_rxlen + 1; rc = copyout(c->c_data, recv->msg.data + 1, c->c_rxlen); /* Always reset state after command completion. */ goto reset; case IPMICTL_SET_MY_ADDRESS_CMD: iv = *(int *)data; if (iv < 0 || iv > RSSA_MASK) { rc = EINVAL; goto reset; } c->c_rssa = iv; break; case IPMICTL_GET_MY_ADDRESS_CMD: *(int *)data = c->c_rssa; break; case IPMICTL_SET_MY_LUN_CMD: iv = *(int *)data; if (iv < 0 || iv > LUN_MASK) { rc = EINVAL; goto reset; } c->c_rslun = iv; break; case IPMICTL_GET_MY_LUN_CMD: *(int *)data = c->c_rslun; break; case IPMICTL_SET_GETS_EVENTS_CMD: break; case IPMICTL_REGISTER_FOR_CMD: case IPMICTL_UNREGISTER_FOR_CMD: default: break; } done: rw_exit_write(&sc->sc_ioctl.lock); return (rc); reset: sc->sc_ioctl.req.msgid = -1; c->c_ccode = -1; goto done; } #define MIN_PERIOD 10 int ipmi_watchdog(void *arg, int period) { struct ipmi_softc *sc = arg; if (sc->sc_wdog_period == period) { if (period != 0) { struct task *t; int res; t = &sc->sc_wdog_tickle_task; (void)task_del(systq, t); res = task_add(systq, t); KASSERT(res == 1); } return (period); } if (period < MIN_PERIOD && period > 0) period = MIN_PERIOD; sc->sc_wdog_period = period; ipmi_watchdog_set(sc); printf("%s: watchdog %sabled\n", DEVNAME(sc), (period == 0) ? "dis" : "en"); return (period); } void ipmi_watchdog_tickle(void *arg) { struct ipmi_softc *sc = arg; struct ipmi_cmd c; c.c_sc = sc; c.c_rssa = BMC_SA; c.c_rslun = BMC_LUN; c.c_netfn = APP_NETFN; c.c_cmd = APP_RESET_WATCHDOG; c.c_txlen = 0; c.c_maxrxlen = 0; c.c_rxlen = 0; c.c_data = NULL; ipmi_cmd(&c); } void ipmi_watchdog_set(void *arg) { struct ipmi_softc *sc = arg; uint8_t wdog[IPMI_GET_WDOG_MAX]; struct ipmi_cmd c; c.c_sc = sc; c.c_rssa = BMC_SA; c.c_rslun = BMC_LUN; c.c_netfn = APP_NETFN; c.c_cmd = APP_GET_WATCHDOG_TIMER; c.c_txlen = 0; c.c_maxrxlen = IPMI_GET_WDOG_MAX; c.c_rxlen = 0; c.c_data = wdog; ipmi_cmd(&c); /* Period is 10ths/sec */ uint16_t timo = htole16(sc->sc_wdog_period * 10); memcpy(&wdog[IPMI_SET_WDOG_TIMOL], &timo, 2); wdog[IPMI_SET_WDOG_TIMER] &= ~IPMI_WDOG_DONTSTOP; wdog[IPMI_SET_WDOG_TIMER] |= (sc->sc_wdog_period == 0) ? 0 : IPMI_WDOG_DONTSTOP; wdog[IPMI_SET_WDOG_ACTION] &= ~IPMI_WDOG_MASK; wdog[IPMI_SET_WDOG_ACTION] |= (sc->sc_wdog_period == 0) ? IPMI_WDOG_DISABLED : IPMI_WDOG_REBOOT; c.c_cmd = APP_SET_WATCHDOG_TIMER; c.c_txlen = IPMI_SET_WDOG_MAX; c.c_maxrxlen = 0; c.c_rxlen = 0; c.c_data = wdog; ipmi_cmd(&c); } #if defined(__amd64__) || defined(__i386__) #include <dev/isa/isareg.h> #include <dev/isa/isavar.h> /* * Format of SMBIOS IPMI Flags * * bit0: interrupt trigger mode (1=level, 0=edge) * bit1: interrupt polarity (1=active high, 0=active low) * bit2: reserved * bit3: address LSB (1=odd,0=even) * bit4: interrupt (1=specified, 0=not specified) * bit5: reserved * bit6/7: register spacing (1,4,2,err) */ #define SMIPMI_FLAG_IRQLVL (1L << 0) #define SMIPMI_FLAG_IRQEN (1L << 3) #define SMIPMI_FLAG_ODDOFFSET (1L << 4) #define SMIPMI_FLAG_IFSPACING(x) (((x)>>6)&0x3) #define IPMI_IOSPACING_BYTE 0 #define IPMI_IOSPACING_WORD 2 #define IPMI_IOSPACING_DWORD 1 struct dmd_ipmi { u_int8_t dmd_sig[4]; /* Signature 'IPMI' */ u_int8_t dmd_i2c_address; /* Address of BMC */ u_int8_t dmd_nvram_address; /* Address of NVRAM */ u_int8_t dmd_if_type; /* IPMI Interface Type */ u_int8_t dmd_if_rev; /* IPMI Interface Revision */ } __packed; void *scan_sig(long, long, int, int, const void *); void ipmi_smbios_probe(struct smbios_ipmi *, struct ipmi_attach_args *); int ipmi_match(struct device *, void *, void *); void ipmi_attach(struct device *, struct device *, void *); const struct cfattach ipmi_ca = { sizeof(struct ipmi_softc), ipmi_match, ipmi_attach, NULL, ipmi_activate }; int ipmi_match(struct device *parent, void *match, void *aux) { struct ipmi_softc *sc; struct ipmi_attach_args *ia = aux; struct cfdata *cf = match; u_int8_t cmd[32]; int rv = 0; if (strcmp(ia->iaa_name, cf->cf_driver->cd_name)) return (0); /* XXX local softc is wrong wrong wrong */ sc = malloc(sizeof(*sc), M_TEMP, M_WAITOK | M_ZERO); strlcpy(sc->sc_dev.dv_xname, "ipmi0", sizeof(sc->sc_dev.dv_xname)); /* Map registers */ if (ipmi_map_regs(sc, ia) == 0) { sc->sc_if->probe(sc); /* Identify BMC device early to detect lying bios */ struct ipmi_cmd c; c.c_sc = sc; c.c_rssa = BMC_SA; c.c_rslun = BMC_LUN; c.c_netfn = APP_NETFN; c.c_cmd = APP_GET_DEVICE_ID; c.c_txlen = 0; c.c_maxrxlen = sizeof(cmd); c.c_rxlen = 0; c.c_data = cmd; ipmi_cmd(&c); dbg_dump(1, "bmc data", c.c_rxlen, cmd); rv = 1; /* GETID worked, we got IPMI */ ipmi_unmap_regs(sc); } free(sc, M_TEMP, sizeof(*sc)); return (rv); } void ipmi_attach(struct device *parent, struct device *self, void *aux) { ipmi_attach_common((struct ipmi_softc *)self, aux); } /* Scan memory for signature */ void * scan_sig(long start, long end, int skip, int len, const void *data) { void *va; while (start < end) { va = ISA_HOLE_VADDR(start); if (memcmp(va, data, len) == 0) return (va); start += skip; } return (NULL); } void ipmi_smbios_probe(struct smbios_ipmi *pipmi, struct ipmi_attach_args *ia) { dbg_printf(1, "ipmi_smbios_probe: %02x %02x %02x %02x %08llx %02x " "%02x\n", pipmi->smipmi_if_type, pipmi->smipmi_if_rev, pipmi->smipmi_i2c_address, pipmi->smipmi_nvram_address, pipmi->smipmi_base_address, pipmi->smipmi_base_flags, pipmi->smipmi_irq); ia->iaa_if_type = pipmi->smipmi_if_type; ia->iaa_if_rev = pipmi->smipmi_if_rev; ia->iaa_if_irq = (pipmi->smipmi_base_flags & SMIPMI_FLAG_IRQEN) ? pipmi->smipmi_irq : -1; ia->iaa_if_irqlvl = (pipmi->smipmi_base_flags & SMIPMI_FLAG_IRQLVL) ? IST_LEVEL : IST_EDGE; ia->iaa_if_iosize = 1; switch (SMIPMI_FLAG_IFSPACING(pipmi->smipmi_base_flags)) { case IPMI_IOSPACING_BYTE: ia->iaa_if_iospacing = 1; break; case IPMI_IOSPACING_DWORD: ia->iaa_if_iospacing = 4; break; case IPMI_IOSPACING_WORD: ia->iaa_if_iospacing = 2; break; default: ia->iaa_if_iospacing = 1; printf("ipmi: unknown register spacing\n"); } /* Calculate base address (PCI BAR format) */ if (pipmi->smipmi_base_address & 0x1) { ia->iaa_if_iotype = 'i'; ia->iaa_if_iobase = pipmi->smipmi_base_address & ~0x1; } else { ia->iaa_if_iotype = 'm'; ia->iaa_if_iobase = pipmi->smipmi_base_address & ~0xF; } if (pipmi->smipmi_base_flags & SMIPMI_FLAG_ODDOFFSET) ia->iaa_if_iobase++; if (pipmi->smipmi_base_flags == 0x7f) { /* IBM 325 eServer workaround */ ia->iaa_if_iospacing = 1; ia->iaa_if_iobase = pipmi->smipmi_base_address; ia->iaa_if_iotype = 'i'; return; } } int ipmi_probe(void *aux) { struct ipmi_attach_args *ia = aux; struct dmd_ipmi *pipmi; struct smbtable tbl; tbl.cookie = 0; if (smbios_find_table(SMBIOS_TYPE_IPMIDEV, &tbl)) ipmi_smbios_probe(tbl.tblhdr, ia); else { pipmi = (struct dmd_ipmi *)scan_sig(0xC0000L, 0xFFFFFL, 16, 4, "IPMI"); /* XXX hack to find Dell PowerEdge 8450 */ if (pipmi == NULL) { /* no IPMI found */ return (0); } /* we have an IPMI signature, fill in attach arg structure */ ia->iaa_if_type = pipmi->dmd_if_type; ia->iaa_if_rev = pipmi->dmd_if_rev; } return (1); } #endif
4 4 4 126 111 107 107 1 93 100 18 18 16 2 18 18 1 11 8 121 122 205 32 171 176 167 204 24 2 2 11 9 64 5 53 41 61 49 13 60 5 78 78 75 78 76 75 26 79 47 78 2 92 39 91 1 91 89 59 112 12 76 95 76 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 /* $OpenBSD: tty_subr.c,v 1.36 2022/08/14 01:58:28 jsg Exp $ */ /* $NetBSD: tty_subr.c,v 1.13 1996/02/09 19:00:43 christos Exp $ */ /* * Copyright (c) 1993, 1994 Theo de Raadt * All rights reserved. * * Per Lindqvist <pgd@compuram.bbt.se> supplied an almost fully working * set of true clist functions that this is very loosely based on. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/tty.h> #include <sys/malloc.h> /* * If TTY_QUOTE functionality isn't required by a line discipline, * it can free c_cq and set it to NULL. This speeds things up, * and also does not use any extra memory. This is useful for (say) * a SLIP line discipline that wants a 32K ring buffer for data * but doesn't need quoting. */ #define QMEM(n) ((((n)-1)/NBBY)+1) void clrbits(u_char *, int, int); /* * Initialize a particular clist. Ok, they are really ring buffers, * of the specified length, with/without quoting support. */ void clalloc(struct clist *clp, int size, int quot) { clp->c_cs = malloc(size, M_TTYS, M_WAITOK|M_ZERO); if (quot) clp->c_cq = malloc(QMEM(size), M_TTYS, M_WAITOK|M_ZERO); else clp->c_cq = NULL; clp->c_cf = clp->c_cl = NULL; clp->c_ce = clp->c_cs + size; clp->c_cn = size; clp->c_cc = 0; } void clfree(struct clist *clp) { if (clp->c_cs) { explicit_bzero(clp->c_cs, clp->c_cn); free(clp->c_cs, M_TTYS, clp->c_cn); } if (clp->c_cq) { explicit_bzero(clp->c_cq, QMEM(clp->c_cn)); free(clp->c_cq, M_TTYS, QMEM(clp->c_cn)); } clp->c_cs = clp->c_cq = NULL; } /* * Get a character from a clist. */ int getc(struct clist *clp) { int c = -1; int s; s = spltty(); if (clp->c_cc == 0) goto out; c = *clp->c_cf & 0xff; *clp->c_cf = 0; if (clp->c_cq) { if (isset(clp->c_cq, clp->c_cf - clp->c_cs)) c |= TTY_QUOTE; clrbit(clp->c_cq, clp->c_cf - clp->c_cs); } if (++clp->c_cf == clp->c_ce) clp->c_cf = clp->c_cs; if (--clp->c_cc == 0) clp->c_cf = clp->c_cl = NULL; out: splx(s); return c; } /* * Copy clist to buffer. * Return number of bytes moved. */ int q_to_b(struct clist *clp, u_char *cp, int count) { int cc; u_char *p = cp; int s; s = spltty(); /* optimize this while loop */ while (count > 0 && clp->c_cc > 0) { cc = clp->c_cl - clp->c_cf; if (clp->c_cf >= clp->c_cl) cc = clp->c_ce - clp->c_cf; if (cc > count) cc = count; memcpy(p, clp->c_cf, cc); memset(clp->c_cf, 0, cc); if (clp->c_cq) clrbits(clp->c_cq, clp->c_cf - clp->c_cs, cc); count -= cc; p += cc; clp->c_cc -= cc; clp->c_cf += cc; if (clp->c_cf == clp->c_ce) clp->c_cf = clp->c_cs; } if (clp->c_cc == 0) clp->c_cf = clp->c_cl = NULL; splx(s); return p - cp; } /* * Return count of contiguous characters in clist. * Stop counting if flag&character is non-null. */ int ndqb(struct clist *clp, int flag) { int count = 0; int i; int cc; int s; s = spltty(); if ((cc = clp->c_cc) == 0) goto out; if (flag == 0) { count = clp->c_cl - clp->c_cf; if (count <= 0) count = clp->c_ce - clp->c_cf; goto out; } i = clp->c_cf - clp->c_cs; if (flag & TTY_QUOTE) { while (cc-- > 0 && !(clp->c_cs[i++] & (flag & ~TTY_QUOTE) || isset(clp->c_cq, i))) { count++; if (i == clp->c_cn) break; } } else { while (cc-- > 0 && !(clp->c_cs[i++] & flag)) { count++; if (i == clp->c_cn) break; } } out: splx(s); return count; } /* * Flush count bytes from clist. */ void ndflush(struct clist *clp, int count) { int cc; int s; s = spltty(); if (count == clp->c_cc) { clp->c_cc = 0; clp->c_cf = clp->c_cl = NULL; goto out; } /* optimize this while loop */ while (count > 0 && clp->c_cc > 0) { cc = clp->c_cl - clp->c_cf; if (clp->c_cf >= clp->c_cl) cc = clp->c_ce - clp->c_cf; if (cc > count) cc = count; count -= cc; clp->c_cc -= cc; clp->c_cf += cc; if (clp->c_cf == clp->c_ce) clp->c_cf = clp->c_cs; } if (clp->c_cc == 0) clp->c_cf = clp->c_cl = NULL; out: splx(s); } /* * Put a character into the output queue. */ int putc(int c, struct clist *clp) { int i; int s; s = spltty(); if (clp->c_cc == clp->c_cn) { splx(s); return -1; } if (clp->c_cc == 0) { if (!clp->c_cs) panic("%s: tty has no clist", __func__); clp->c_cf = clp->c_cl = clp->c_cs; } *clp->c_cl = c & 0xff; i = clp->c_cl - clp->c_cs; if (clp->c_cq) { if (c & TTY_QUOTE) setbit(clp->c_cq, i); else clrbit(clp->c_cq, i); } clp->c_cc++; clp->c_cl++; if (clp->c_cl == clp->c_ce) clp->c_cl = clp->c_cs; splx(s); return 0; } /* * optimized version of * * for (i = 0; i < len; i++) * clrbit(cp, off + i); */ void clrbits(u_char *cp, int off, int len) { int sby, sbi, eby, ebi; int i; u_char mask; if (len==1) { clrbit(cp, off); return; } sby = off / NBBY; sbi = off % NBBY; eby = (off+len) / NBBY; ebi = (off+len) % NBBY; if (sby == eby) { mask = ((1 << (ebi - sbi)) - 1) << sbi; cp[sby] &= ~mask; } else { mask = (1<<sbi) - 1; cp[sby++] &= mask; for (i = sby; i < eby; i++) cp[i] = 0x00; mask = (1<<ebi) - 1; if (mask) /* if no mask, eby may be 1 too far */ cp[eby] &= ~mask; } } /* * Copy buffer to clist. * Return number of bytes not transferred. */ int b_to_q(u_char *cp, int count, struct clist *clp) { int cc; u_char *p = cp; int s; if (count <= 0) return 0; s = spltty(); if (clp->c_cc == clp->c_cn) goto out; if (clp->c_cc == 0) { if (!clp->c_cs) panic("%s: tty has no clist", __func__); clp->c_cf = clp->c_cl = clp->c_cs; } /* optimize this while loop */ while (count > 0 && clp->c_cc < clp->c_cn) { cc = clp->c_ce - clp->c_cl; if (clp->c_cf > clp->c_cl) cc = clp->c_cf - clp->c_cl; if (cc > count) cc = count; memcpy(clp->c_cl, p, cc); if (clp->c_cq) clrbits(clp->c_cq, clp->c_cl - clp->c_cs, cc); p += cc; count -= cc; clp->c_cc += cc; clp->c_cl += cc; if (clp->c_cl == clp->c_ce) clp->c_cl = clp->c_cs; } out: splx(s); return count; } /* * Given a non-NULL pointer into the clist return the pointer * to the next character in the list or return NULL if no more chars. * * Callers must not allow getc's to happen between firstc's and nextc's * so that the pointer becomes invalid. Note that interrupts are NOT * masked. */ u_char * nextc(struct clist *clp, u_char *cp, int *c, int *ccp) { if (clp->c_cf == cp) { /* * First time initialization. */ *ccp = clp->c_cc; } if (*ccp == 0 || cp == NULL) return NULL; if (--(*ccp) == 0) return NULL; if (++cp == clp->c_ce) cp = clp->c_cs; *c = *cp & 0xff; if (clp->c_cq) { if (isset(clp->c_cq, cp - clp->c_cs)) *c |= TTY_QUOTE; } return cp; } /* * Given a non-NULL pointer into the clist return the pointer * to the first character in the list or return NULL if no more chars. * * Callers must not allow getc's to happen between firstc's and nextc's * so that the pointer becomes invalid. Note that interrupts are NOT * masked. * * *c is set to the NEXT character */ u_char * firstc(struct clist *clp, int *c, int *ccp) { u_char *cp; *ccp = clp->c_cc; if (*ccp == 0) return NULL; cp = clp->c_cf; *c = *cp & 0xff; if (clp->c_cq) { if (isset(clp->c_cq, cp - clp->c_cs)) *c |= TTY_QUOTE; } return clp->c_cf; } /* * Remove the last character in the clist and return it. */ int unputc(struct clist *clp) { unsigned int c = -1; int s; s = spltty(); if (clp->c_cc == 0) goto out; if (clp->c_cl == clp->c_cs) clp->c_cl = clp->c_ce - 1; else --clp->c_cl; clp->c_cc--; c = *clp->c_cl & 0xff; *clp->c_cl = 0; if (clp->c_cq) { if (isset(clp->c_cq, clp->c_cl - clp->c_cs)) c |= TTY_QUOTE; clrbit(clp->c_cq, clp->c_cl - clp->c_cs); } if (clp->c_cc == 0) clp->c_cf = clp->c_cl = NULL; out: splx(s); return c; } /* * Put the chars in the from queue on the end of the to queue. */ void catq(struct clist *from, struct clist *to) { int c; int s; s = spltty(); if (from->c_cc == 0) { /* nothing to move */ splx(s); return; } /* * if `to' queue is empty and the queues are the same max size, * it is more efficient to just swap the clist structures. */ if (to->c_cc == 0 && from->c_cn == to->c_cn) { struct clist tmp; tmp = *from; *from = *to; *to = tmp; splx(s); return; } splx(s); while ((c = getc(from)) != -1) putc(c, to); }
1813 1814 1813 8 8 3 6 1715 1714 1716 8 1715 28 28 28 17 17 17 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 /* $OpenBSD: kern_smr.c,v 1.16 2022/08/14 01:58:27 jsg Exp $ */ /* * Copyright (c) 2019-2020 Visa Hankala * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/kthread.h> #include <sys/mutex.h> #include <sys/percpu.h> #include <sys/proc.h> #include <sys/smr.h> #include <sys/time.h> #include <sys/tracepoint.h> #include <sys/witness.h> #include <machine/cpu.h> #define SMR_PAUSE 100 /* pause between rounds in msec */ void smr_dispatch(struct schedstate_percpu *); void smr_grace_wait(void); void smr_thread(void *); void smr_wakeup(void *); struct mutex smr_lock = MUTEX_INITIALIZER(IPL_HIGH); struct smr_entry_list smr_deferred; struct timeout smr_wakeup_tmo; unsigned int smr_expedite; unsigned int smr_ndeferred; unsigned char smr_grace_period; #ifdef WITNESS static const char smr_lock_name[] = "smr"; struct lock_object smr_lock_obj = { .lo_name = smr_lock_name, .lo_flags = LO_WITNESS | LO_INITIALIZED | LO_SLEEPABLE | (LO_CLASS_RWLOCK << LO_CLASSSHIFT) }; struct lock_type smr_lock_type = { .lt_name = smr_lock_name }; #endif static inline int smr_cpu_is_idle(struct cpu_info *ci) { return ci->ci_curproc == ci->ci_schedstate.spc_idleproc; } void smr_startup(void) { SIMPLEQ_INIT(&smr_deferred); WITNESS_INIT(&smr_lock_obj, &smr_lock_type); timeout_set(&smr_wakeup_tmo, smr_wakeup, NULL); } void smr_startup_thread(void) { if (kthread_create(smr_thread, NULL, NULL, "smr") != 0) panic("could not create smr thread"); } struct timeval smr_logintvl = { 300, 0 }; void smr_thread(void *arg) { struct timeval elapsed, end, loglast, start; struct smr_entry_list deferred; struct smr_entry *smr; unsigned long count; KERNEL_ASSERT_LOCKED(); KERNEL_UNLOCK(); memset(&loglast, 0, sizeof(loglast)); SIMPLEQ_INIT(&deferred); for (;;) { mtx_enter(&smr_lock); if (smr_ndeferred == 0) { while (smr_ndeferred == 0) msleep_nsec(&smr_ndeferred, &smr_lock, PVM, "bored", INFSLP); } else { if (smr_expedite == 0) msleep_nsec(&smr_ndeferred, &smr_lock, PVM, "pause", MSEC_TO_NSEC(SMR_PAUSE)); } SIMPLEQ_CONCAT(&deferred, &smr_deferred); smr_ndeferred = 0; smr_expedite = 0; mtx_leave(&smr_lock); getmicrouptime(&start); smr_grace_wait(); WITNESS_CHECKORDER(&smr_lock_obj, LOP_NEWORDER, NULL); WITNESS_LOCK(&smr_lock_obj, 0); count = 0; while ((smr = SIMPLEQ_FIRST(&deferred)) != NULL) { SIMPLEQ_REMOVE_HEAD(&deferred, smr_list); TRACEPOINT(smr, called, smr->smr_func, smr->smr_arg); smr->smr_func(smr->smr_arg); count++; } WITNESS_UNLOCK(&smr_lock_obj, 0); getmicrouptime(&end); timersub(&end, &start, &elapsed); if (elapsed.tv_sec >= 2 && ratecheck(&loglast, &smr_logintvl)) { printf("smr: dispatch took %ld.%06lds\n", (long)elapsed.tv_sec, (long)elapsed.tv_usec); } TRACEPOINT(smr, thread, TIMEVAL_TO_NSEC(&elapsed), count); } } /* * Announce next grace period and wait until all CPUs have entered it * by crossing quiescent state. */ void smr_grace_wait(void) { #ifdef MULTIPROCESSOR CPU_INFO_ITERATOR cii; struct cpu_info *ci; unsigned char smrgp; smrgp = READ_ONCE(smr_grace_period) + 1; WRITE_ONCE(smr_grace_period, smrgp); curcpu()->ci_schedstate.spc_smrgp = smrgp; CPU_INFO_FOREACH(cii, ci) { if (!CPU_IS_RUNNING(ci)) continue; if (READ_ONCE(ci->ci_schedstate.spc_smrgp) == smrgp) continue; sched_peg_curproc(ci); KASSERT(ci->ci_schedstate.spc_smrgp == smrgp); } atomic_clearbits_int(&curproc->p_flag, P_CPUPEG); #endif /* MULTIPROCESSOR */ } void smr_wakeup(void *arg) { TRACEPOINT(smr, wakeup, NULL); wakeup(&smr_ndeferred); } void smr_read_enter(void) { #ifdef DIAGNOSTIC struct schedstate_percpu *spc = &curcpu()->ci_schedstate; spc->spc_smrdepth++; #endif } void smr_read_leave(void) { #ifdef DIAGNOSTIC struct schedstate_percpu *spc = &curcpu()->ci_schedstate; KASSERT(spc->spc_smrdepth > 0); spc->spc_smrdepth--; #endif } /* * Move SMR entries from the local queue to the system-wide queue. */ void smr_dispatch(struct schedstate_percpu *spc) { int expedite = 0, wake = 0; mtx_enter(&smr_lock); if (smr_ndeferred == 0) wake = 1; SIMPLEQ_CONCAT(&smr_deferred, &spc->spc_deferred); smr_ndeferred += spc->spc_ndeferred; spc->spc_ndeferred = 0; smr_expedite |= spc->spc_smrexpedite; spc->spc_smrexpedite = 0; expedite = smr_expedite; mtx_leave(&smr_lock); if (expedite) smr_wakeup(NULL); else if (wake) timeout_add_msec(&smr_wakeup_tmo, SMR_PAUSE); } /* * Signal that the current CPU is in quiescent state. */ void smr_idle(void) { struct schedstate_percpu *spc = &curcpu()->ci_schedstate; unsigned char smrgp; SMR_ASSERT_NONCRITICAL(); if (spc->spc_ndeferred > 0) smr_dispatch(spc); /* * Update this CPU's view of the system's grace period. * The update must become visible after any preceding reads * of SMR-protected data. */ smrgp = READ_ONCE(smr_grace_period); if (__predict_false(spc->spc_smrgp != smrgp)) { membar_exit(); WRITE_ONCE(spc->spc_smrgp, smrgp); } } void smr_call_impl(struct smr_entry *smr, void (*func)(void *), void *arg, int expedite) { struct cpu_info *ci = curcpu(); struct schedstate_percpu *spc = &ci->ci_schedstate; int s; KASSERT(smr->smr_func == NULL); smr->smr_func = func; smr->smr_arg = arg; s = splhigh(); SIMPLEQ_INSERT_TAIL(&spc->spc_deferred, smr, smr_list); spc->spc_ndeferred++; spc->spc_smrexpedite |= expedite; splx(s); TRACEPOINT(smr, call, func, arg, expedite); /* * If this call was made from an interrupt context that * preempted idle state, dispatch the local queue to the shared * queue immediately. * The entries would linger in the local queue long if the CPU * went to sleep without calling smr_idle(). */ if (smr_cpu_is_idle(ci)) smr_dispatch(spc); } void smr_barrier_func(void *arg) { struct cond *c = arg; cond_signal(c); } void smr_barrier_impl(int expedite) { struct cond c = COND_INITIALIZER(); struct smr_entry smr; if (panicstr != NULL || db_active) return; WITNESS_CHECKORDER(&smr_lock_obj, LOP_NEWORDER, NULL); TRACEPOINT(smr, barrier_enter, expedite); smr_init(&smr); smr_call_impl(&smr, smr_barrier_func, &c, expedite); cond_wait(&c, "smrbar"); TRACEPOINT(smr, barrier_exit, expedite); }
210 1 210 1 210 26 199 200 25 211 210 211 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 /* $OpenBSD: vioscsi.c,v 1.32 2023/05/29 08:13:35 sf Exp $ */ /* * Copyright (c) 2013 Google Inc. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> #include <sys/mutex.h> #include <machine/bus.h> #include <machine/intr.h> #include <dev/pv/vioscsireg.h> #include <dev/pv/virtiovar.h> #include <scsi/scsi_all.h> #include <scsi/scsiconf.h> enum { vioscsi_debug = 0 }; #define DPRINTF(f...) do { if (vioscsi_debug) printf(f); } while (0) /* Number of DMA segments for buffers that the device must support */ #define SEG_MAX (MAXPHYS/PAGE_SIZE + 1) /* In the virtqueue, we need space for header and footer, too */ #define ALLOC_SEGS (SEG_MAX + 2) struct vioscsi_req { struct virtio_scsi_req_hdr vr_req; struct virtio_scsi_res_hdr vr_res; struct scsi_xfer *vr_xs; bus_dmamap_t vr_control; bus_dmamap_t vr_data; SLIST_ENTRY(vioscsi_req) vr_list; int vr_qe_index; }; struct vioscsi_softc { struct device sc_dev; struct scsi_iopool sc_iopool; struct mutex sc_vr_mtx; struct virtqueue sc_vqs[3]; struct vioscsi_req *sc_reqs; bus_dma_segment_t sc_reqs_segs[1]; SLIST_HEAD(, vioscsi_req) sc_freelist; }; int vioscsi_match(struct device *, void *, void *); void vioscsi_attach(struct device *, struct device *, void *); int vioscsi_alloc_reqs(struct vioscsi_softc *, struct virtio_softc *, int); void vioscsi_scsi_cmd(struct scsi_xfer *); int vioscsi_vq_done(struct virtqueue *); void vioscsi_req_done(struct vioscsi_softc *, struct virtio_softc *, struct vioscsi_req *); void *vioscsi_req_get(void *); void vioscsi_req_put(void *, void *); const struct cfattach vioscsi_ca = { sizeof(struct vioscsi_softc), vioscsi_match, vioscsi_attach, }; struct cfdriver vioscsi_cd = { NULL, "vioscsi", DV_DULL, }; const struct scsi_adapter vioscsi_switch = { vioscsi_scsi_cmd, NULL, NULL, NULL, NULL }; const char *const vioscsi_vq_names[] = { "control", "event", "request", }; int vioscsi_match(struct device *parent, void *self, void *aux) { struct virtio_softc *va = (struct virtio_softc *)aux; if (va->sc_childdevid == PCI_PRODUCT_VIRTIO_SCSI) return (1); return (0); } void vioscsi_attach(struct device *parent, struct device *self, void *aux) { struct virtio_softc *vsc = (struct virtio_softc *)parent; struct vioscsi_softc *sc = (struct vioscsi_softc *)self; struct scsibus_attach_args saa; int i, rv; if (vsc->sc_child != NULL) { printf(": parent already has a child\n"); return; } vsc->sc_child = &sc->sc_dev; vsc->sc_ipl = IPL_BIO; // TODO(matthew): Negotiate hotplug. vsc->sc_vqs = sc->sc_vqs; vsc->sc_nvqs = nitems(sc->sc_vqs); virtio_negotiate_features(vsc, NULL); uint32_t cmd_per_lun = virtio_read_device_config_4(vsc, VIRTIO_SCSI_CONFIG_CMD_PER_LUN); uint32_t seg_max = virtio_read_device_config_4(vsc, VIRTIO_SCSI_CONFIG_SEG_MAX); uint16_t max_target = virtio_read_device_config_2(vsc, VIRTIO_SCSI_CONFIG_MAX_TARGET); if (seg_max < SEG_MAX) { printf("\nMax number of segments %d too small\n", seg_max); goto err; } for (i = 0; i < nitems(sc->sc_vqs); i++) { rv = virtio_alloc_vq(vsc, &sc->sc_vqs[i], i, MAXPHYS, ALLOC_SEGS, vioscsi_vq_names[i]); if (rv) { printf(": failed to allocate virtqueue %d\n", i); goto err; } sc->sc_vqs[i].vq_done = vioscsi_vq_done; } int qsize = sc->sc_vqs[2].vq_num; printf(": qsize %d\n", qsize); SLIST_INIT(&sc->sc_freelist); mtx_init(&sc->sc_vr_mtx, IPL_BIO); scsi_iopool_init(&sc->sc_iopool, sc, vioscsi_req_get, vioscsi_req_put); int nreqs = vioscsi_alloc_reqs(sc, vsc, qsize); if (nreqs == 0) { printf("\nCan't alloc reqs\n"); goto err; } saa.saa_adapter = &vioscsi_switch; saa.saa_adapter_softc = sc; saa.saa_adapter_target = SDEV_NO_ADAPTER_TARGET; saa.saa_adapter_buswidth = max_target; saa.saa_luns = 8; saa.saa_openings = (nreqs > cmd_per_lun) ? cmd_per_lun : nreqs; saa.saa_pool = &sc->sc_iopool; saa.saa_quirks = saa.saa_flags = 0; saa.saa_wwpn = saa.saa_wwnn = 0; virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK); config_found(self, &saa, scsiprint); return; err: vsc->sc_child = VIRTIO_CHILD_ERROR; return; } void vioscsi_scsi_cmd(struct scsi_xfer *xs) { struct vioscsi_softc *sc = xs->sc_link->bus->sb_adapter_softc; struct virtio_softc *vsc = (struct virtio_softc *)sc->sc_dev.dv_parent; struct vioscsi_req *vr = xs->io; struct virtio_scsi_req_hdr *req = &vr->vr_req; struct virtqueue *vq = &sc->sc_vqs[2]; int slot = vr->vr_qe_index; DPRINTF("vioscsi_scsi_cmd: enter\n"); // TODO(matthew): Support bidirectional SCSI commands? if ((xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) == (SCSI_DATA_IN | SCSI_DATA_OUT)) { goto stuffup; } vr->vr_xs = xs; /* * "The only supported format for the LUN field is: first byte set to * 1, second byte set to target, third and fourth byte representing a * single level LUN structure, followed by four zero bytes." */ if (xs->sc_link->target >= 256 || xs->sc_link->lun >= 16384) goto stuffup; req->lun[0] = 1; req->lun[1] = xs->sc_link->target; req->lun[2] = 0x40 | (xs->sc_link->lun >> 8); req->lun[3] = xs->sc_link->lun; memset(req->lun + 4, 0, 4); if ((size_t)xs->cmdlen > sizeof(req->cdb)) goto stuffup; memset(req->cdb, 0, sizeof(req->cdb)); memcpy(req->cdb, &xs->cmd, xs->cmdlen); int isread = !!(xs->flags & SCSI_DATA_IN); int nsegs = 2; if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) { if (bus_dmamap_load(vsc->sc_dmat, vr->vr_data, xs->data, xs->datalen, NULL, ((isread ? BUS_DMA_READ : BUS_DMA_WRITE) | BUS_DMA_NOWAIT))) goto stuffup; nsegs += vr->vr_data->dm_nsegs; } /* * Adjust reservation to the number needed, or virtio gets upset. Note * that it may trim UP if 'xs' is being recycled w/o getting a new * reservation! */ int s = splbio(); virtio_enqueue_trim(vq, slot, nsegs); splx(s); bus_dmamap_sync(vsc->sc_dmat, vr->vr_control, offsetof(struct vioscsi_req, vr_req), sizeof(struct virtio_scsi_req_hdr), BUS_DMASYNC_PREWRITE); bus_dmamap_sync(vsc->sc_dmat, vr->vr_control, offsetof(struct vioscsi_req, vr_res), sizeof(struct virtio_scsi_res_hdr), BUS_DMASYNC_PREREAD); if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) bus_dmamap_sync(vsc->sc_dmat, vr->vr_data, 0, xs->datalen, isread ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); s = splbio(); virtio_enqueue_p(vq, slot, vr->vr_control, offsetof(struct vioscsi_req, vr_req), sizeof(struct virtio_scsi_req_hdr), 1); if (xs->flags & SCSI_DATA_OUT) virtio_enqueue(vq, slot, vr->vr_data, 1); virtio_enqueue_p(vq, slot, vr->vr_control, offsetof(struct vioscsi_req, vr_res), sizeof(struct virtio_scsi_res_hdr), 0); if (xs->flags & SCSI_DATA_IN) virtio_enqueue(vq, slot, vr->vr_data, 0); virtio_enqueue_commit(vsc, vq, slot, 1); if (ISSET(xs->flags, SCSI_POLL)) { DPRINTF("vioscsi_scsi_cmd: polling...\n"); int timeout = 1000; do { virtio_poll_intr(vsc); if (vr->vr_xs != xs) break; delay(1000); } while (--timeout > 0); if (vr->vr_xs == xs) { // TODO(matthew): Abort the request. xs->error = XS_TIMEOUT; xs->resid = xs->datalen; DPRINTF("vioscsi_scsi_cmd: polling timeout\n"); scsi_done(xs); } DPRINTF("vioscsi_scsi_cmd: done (timeout=%d)\n", timeout); } splx(s); return; stuffup: xs->error = XS_DRIVER_STUFFUP; xs->resid = xs->datalen; DPRINTF("vioscsi_scsi_cmd: stuffup\n"); scsi_done(xs); } void vioscsi_req_done(struct vioscsi_softc *sc, struct virtio_softc *vsc, struct vioscsi_req *vr) { struct scsi_xfer *xs = vr->vr_xs; DPRINTF("vioscsi_req_done: enter vr: %p xs: %p\n", vr, xs); int isread = !!(xs->flags & SCSI_DATA_IN); bus_dmamap_sync(vsc->sc_dmat, vr->vr_control, offsetof(struct vioscsi_req, vr_req), sizeof(struct virtio_scsi_req_hdr), BUS_DMASYNC_POSTWRITE); bus_dmamap_sync(vsc->sc_dmat, vr->vr_control, offsetof(struct vioscsi_req, vr_res), sizeof(struct virtio_scsi_res_hdr), BUS_DMASYNC_POSTREAD); if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) { bus_dmamap_sync(vsc->sc_dmat, vr->vr_data, 0, xs->datalen, isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(vsc->sc_dmat, vr->vr_data); } if (vr->vr_res.response != VIRTIO_SCSI_S_OK) { xs->error = XS_DRIVER_STUFFUP; xs->resid = xs->datalen; DPRINTF("vioscsi_req_done: stuffup: %d\n", vr->vr_res.response); goto done; } size_t sense_len = MIN(sizeof(xs->sense), vr->vr_res.sense_len); memcpy(&xs->sense, vr->vr_res.sense, sense_len); xs->error = (sense_len == 0) ? XS_NOERROR : XS_SENSE; xs->status = vr->vr_res.status; xs->resid = vr->vr_res.residual; DPRINTF("vioscsi_req_done: done %d, %d, %zd\n", xs->error, xs->status, xs->resid); done: vr->vr_xs = NULL; scsi_done(xs); } int vioscsi_vq_done(struct virtqueue *vq) { struct virtio_softc *vsc = vq->vq_owner; struct vioscsi_softc *sc = (struct vioscsi_softc *)vsc->sc_child; struct vq_entry *qe; struct vioscsi_req *vr; int ret = 0; DPRINTF("vioscsi_vq_done: enter\n"); for (;;) { int r, s, slot; s = splbio(); r = virtio_dequeue(vsc, vq, &slot, NULL); splx(s); if (r != 0) break; DPRINTF("vioscsi_vq_done: slot=%d\n", slot); qe = &vq->vq_entries[slot]; vr = &sc->sc_reqs[qe->qe_vr_index]; vioscsi_req_done(sc, vsc, vr); ret = 1; } DPRINTF("vioscsi_vq_done: exit %d\n", ret); return (ret); } /* * vioscso_req_get() provides the SCSI layer with all the * resources necessary to start an I/O on the device. * * Since the size of the I/O is unknown at this time the * resources allocated (a.k.a. reserved) must be sufficient * to allow the maximum possible I/O size. * * When the I/O is actually attempted via vioscsi_scsi_cmd() * excess resources will be returned via virtio_enqueue_trim(). */ void * vioscsi_req_get(void *cookie) { struct vioscsi_softc *sc = cookie; struct vioscsi_req *vr = NULL; mtx_enter(&sc->sc_vr_mtx); vr = SLIST_FIRST(&sc->sc_freelist); if (vr != NULL) SLIST_REMOVE_HEAD(&sc->sc_freelist, vr_list); mtx_leave(&sc->sc_vr_mtx); DPRINTF("vioscsi_req_get: %p\n", vr); return (vr); } void vioscsi_req_put(void *cookie, void *io) { struct vioscsi_softc *sc = cookie; struct vioscsi_req *vr = io; DPRINTF("vioscsi_req_put: %p\n", vr); mtx_enter(&sc->sc_vr_mtx); /* * Do *NOT* call virtio_dequeue_commit()! * * Descriptors are permanently associated with the vioscsi_req and * should not be placed on the free list! */ SLIST_INSERT_HEAD(&sc->sc_freelist, vr, vr_list); mtx_leave(&sc->sc_vr_mtx); } int vioscsi_alloc_reqs(struct vioscsi_softc *sc, struct virtio_softc *vsc, int qsize) { struct virtqueue *vq = &sc->sc_vqs[2]; struct vioscsi_req *vr; struct vring_desc *vd; size_t allocsize; int i, r, nreqs, rsegs, slot; void *vaddr; if (vq->vq_indirect != NULL) nreqs = qsize; else nreqs = qsize / ALLOC_SEGS; allocsize = nreqs * sizeof(struct vioscsi_req); r = bus_dmamem_alloc(vsc->sc_dmat, allocsize, 0, 0, &sc->sc_reqs_segs[0], 1, &rsegs, BUS_DMA_NOWAIT); if (r != 0) { printf("bus_dmamem_alloc, size %zd, error %d\n", allocsize, r); return 0; } r = bus_dmamem_map(vsc->sc_dmat, &sc->sc_reqs_segs[0], 1, allocsize, (caddr_t *)&vaddr, BUS_DMA_NOWAIT); if (r != 0) { printf("bus_dmamem_map failed, error %d\n", r); bus_dmamem_free(vsc->sc_dmat, &sc->sc_reqs_segs[0], 1); return 0; } sc->sc_reqs = vaddr; memset(vaddr, 0, allocsize); for (i = 0; i < nreqs; i++) { /* * Assign descriptors and create the DMA maps for each * allocated request. */ vr = &sc->sc_reqs[i]; r = virtio_enqueue_prep(vq, &slot); if (r == 0) r = virtio_enqueue_reserve(vq, slot, ALLOC_SEGS); if (r != 0) return i; if (vq->vq_indirect == NULL) { /* * The reserved slots must be a contiguous block * starting at vq_desc[slot]. */ vd = &vq->vq_desc[slot]; for (r = 0; r < ALLOC_SEGS - 1; r++) { DPRINTF("vd[%d].next = %d should be %d\n", r, vd[r].next, (slot + r + 1)); if (vd[r].next != (slot + r + 1)) return i; } if (r == (ALLOC_SEGS -1) && vd[r].next != 0) return i; DPRINTF("Reserved slots are contiguous as required!\n"); } vr->vr_qe_index = slot; vr->vr_req.id = slot; vr->vr_req.task_attr = VIRTIO_SCSI_S_SIMPLE; vq->vq_entries[slot].qe_vr_index = i; r = bus_dmamap_create(vsc->sc_dmat, offsetof(struct vioscsi_req, vr_xs), 1, offsetof(struct vioscsi_req, vr_xs), 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &vr->vr_control); if (r != 0) { printf("bus_dmamap_create vr_control failed, error %d\n", r); return i; } r = bus_dmamap_create(vsc->sc_dmat, MAXPHYS, SEG_MAX, MAXPHYS, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &vr->vr_data); if (r != 0) { printf("bus_dmamap_create vr_data failed, error %d\n", r ); return i; } r = bus_dmamap_load(vsc->sc_dmat, vr->vr_control, vr, offsetof(struct vioscsi_req, vr_xs), NULL, BUS_DMA_NOWAIT); if (r != 0) { printf("bus_dmamap_load vr_control failed, error %d\n", r ); return i; } SLIST_INSERT_HEAD(&sc->sc_freelist, vr, vr_list); } return nreqs; }
1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 /* $OpenBSD: audio.c,v 1.206 2023/02/10 14:34:16 visa Exp $ */ /* * Copyright (c) 2015 Alexandre Ratchov <alex@caoua.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/fcntl.h> #include <sys/systm.h> #include <sys/ioctl.h> #include <sys/conf.h> #include <sys/kernel.h> #include <sys/event.h> #include <sys/mutex.h> #include <sys/task.h> #include <sys/vnode.h> #include <sys/malloc.h> #include <sys/device.h> #include <sys/audioio.h> #include <dev/audio_if.h> #include <dev/mulaw.h> #include "audio.h" #include "wskbd.h" #ifdef AUDIO_DEBUG #define DPRINTF(...) \ do { \ if (audio_debug) \ printf(__VA_ARGS__); \ } while(0) #define DPRINTFN(n, ...) \ do { \ if (audio_debug > (n)) \ printf(__VA_ARGS__); \ } while(0) #else #define DPRINTF(...) do {} while(0) #define DPRINTFN(n, ...) do {} while(0) #endif #define IPL_SOFTAUDIO IPL_SOFTNET #define DEVNAME(sc) ((sc)->dev.dv_xname) #define AUDIO_UNIT(n) (minor(n) & 0x0f) #define AUDIO_DEV(n) (minor(n) & 0xf0) #define AUDIO_DEV_AUDIO 0 /* minor of /dev/audio0 */ #define AUDIO_DEV_AUDIOCTL 0xc0 /* minor of /dev/audioctl */ #define AUDIO_BUFSZ 65536 /* buffer size in bytes */ /* * mixer entries added by the audio(4) layer */ #define MIXER_RECORD 0 /* record class */ #define MIXER_RECORD_ENABLE 1 /* record.enable control */ #define MIXER_RECORD_ENABLE_OFF 0 /* record.enable=off value */ #define MIXER_RECORD_ENABLE_ON 1 /* record.enable=on value */ #define MIXER_RECORD_ENABLE_SYSCTL 2 /* record.enable=sysctl val */ /* * dma buffer */ struct audio_buf { unsigned char *data; /* DMA memory block */ size_t datalen; /* size of DMA memory block */ size_t len; /* size of DMA FIFO */ size_t start; /* first byte used in the FIFO */ size_t used; /* bytes used in the FIFO */ size_t blksz; /* DMA block size */ unsigned int nblks; /* number of blocks */ struct klist klist; /* list of knotes */ unsigned int pos; /* bytes transferred */ unsigned int xrun; /* bytes lost by xruns */ int blocking; /* read/write blocking */ }; #if NWSKBD > 0 struct wskbd_vol { int val; /* index of the value control */ int mute; /* index of the mute control */ int step; /* increment/decrement step */ int nch; /* channels in the value control */ int val_pending; /* pending change of val */ int mute_pending; /* pending change of mute */ #define WSKBD_MUTE_TOGGLE 1 #define WSKBD_MUTE_DISABLE 2 #define WSKBD_MUTE_ENABLE 3 }; int wskbd_set_mixervolume_unit(int, long, long); #endif /* * event indicating that a control was changed */ struct mixer_ev { struct mixer_ev *next; int pending; }; /* * device structure */ struct audio_softc { struct device dev; const struct audio_hw_if *ops; /* driver funcs */ void *cookie; /* wskbd cookie */ void *arg; /* first arg to driver funcs */ int mode; /* bitmask of AUMODE_* */ int quiesce; /* device suspended */ struct audio_buf play, rec; unsigned int sw_enc; /* user exposed AUDIO_ENCODING_* */ unsigned int hw_enc; /* hardware AUDIO_ENCODING_* */ unsigned int bits; /* bits per sample */ unsigned int bps; /* bytes-per-sample */ unsigned int msb; /* sample are MSB aligned */ unsigned int rate; /* rate in Hz */ unsigned int round; /* block size in frames */ unsigned int pchan, rchan; /* number of channels */ unsigned char silence[4]; /* a sample of silence */ int pause; /* not trying to start DMA */ int active; /* DMA in process */ int offs; /* offset between play & rec dir */ void (*conv_enc)(unsigned char *, int); /* encode to native */ void (*conv_dec)(unsigned char *, int); /* decode to user */ struct mixer_ctrl *mix_ents; /* mixer state for suspend/resume */ int mix_nent; /* size of mixer state */ int mix_isopen; /* mixer open for reading */ int mix_blocking; /* read() blocking */ struct klist mix_klist; /* list of knotes */ struct mixer_ev *mix_evbuf; /* per mixer-control event */ struct mixer_ev *mix_pending; /* list of changed controls */ #if NWSKBD > 0 struct wskbd_vol spkr, mic; struct task wskbd_task; #endif int record_enable; /* mixer record.enable value */ }; int audio_match(struct device *, void *, void *); void audio_attach(struct device *, struct device *, void *); int audio_activate(struct device *, int); int audio_detach(struct device *, int); void audio_pintr(void *); void audio_rintr(void *); void audio_buf_wakeup(struct audio_buf *); void audio_mixer_wakeup(struct audio_softc *); #if NWSKBD > 0 void wskbd_mixer_init(struct audio_softc *); void wskbd_mixer_cb(void *); #endif const struct cfattach audio_ca = { sizeof(struct audio_softc), audio_match, audio_attach, audio_detach, audio_activate }; struct cfdriver audio_cd = { NULL, "audio", DV_DULL }; void filt_audioctlrdetach(struct knote *); int filt_audioctlread(struct knote *, long); int filt_audiomodify(struct kevent *, struct knote *); int filt_audioprocess(struct knote *, struct kevent *); const struct filterops audioctlread_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_audioctlrdetach, .f_event = filt_audioctlread, .f_modify = filt_audiomodify, .f_process = filt_audioprocess, }; void filt_audiowdetach(struct knote *); int filt_audiowrite(struct knote *, long); const struct filterops audiowrite_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_audiowdetach, .f_event = filt_audiowrite, .f_modify = filt_audiomodify, .f_process = filt_audioprocess, }; void filt_audiordetach(struct knote *); int filt_audioread(struct knote *, long); const struct filterops audioread_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_audiordetach, .f_event = filt_audioread, .f_modify = filt_audiomodify, .f_process = filt_audioprocess, }; /* * This mutex protects data structures (including registers on the * sound-card) that are manipulated by both the interrupt handler and * syscall code-paths. * * Note that driver methods may sleep (e.g. in malloc); consequently the * audio layer calls them with the mutex unlocked. Driver methods are * responsible for locking the mutex when they manipulate data used by * the interrupt handler and interrupts may occur. * * Similarly, the driver is responsible for locking the mutex in its * interrupt handler and to call the audio layer call-backs (i.e. * audio_{p,r}int()) with the mutex locked. */ struct mutex audio_lock = MUTEX_INITIALIZER(IPL_AUDIO); /* * Global flag to control if audio recording is enabled when the * mixerctl setting is record.enable=sysctl */ int audio_record_enable = 0; #ifdef AUDIO_DEBUG /* * 0 - nothing, as if AUDIO_DEBUG isn't defined * 1 - initialisations & setup * 2 - blocks & interrupts */ int audio_debug = 1; #endif unsigned int audio_gcd(unsigned int a, unsigned int b) { unsigned int r; while (b > 0) { r = a % b; a = b; b = r; } return a; } /* * Calculate the least block size (in frames) such that both the * corresponding play and/or record block sizes (in bytes) are multiple * of the given number of bytes. */ int audio_blksz_bytes(int mode, struct audio_params *p, struct audio_params *r, int bytes) { unsigned int np, nr; if (mode & AUMODE_PLAY) { np = bytes / audio_gcd(p->bps * p->channels, bytes); if (!(mode & AUMODE_RECORD)) nr = np; } if (mode & AUMODE_RECORD) { nr = bytes / audio_gcd(r->bps * r->channels, bytes); if (!(mode & AUMODE_PLAY)) np = nr; } return nr * np / audio_gcd(nr, np); } void audio_mixer_wakeup(struct audio_softc *sc) { MUTEX_ASSERT_LOCKED(&audio_lock); if (sc->mix_blocking) { wakeup(&sc->mix_blocking); sc->mix_blocking = 0; } knote_locked(&sc->mix_klist, 0); } void audio_buf_wakeup(struct audio_buf *buf) { MUTEX_ASSERT_LOCKED(&audio_lock); if (buf->blocking) { wakeup(&buf->blocking); buf->blocking = 0; } knote_locked(&buf->klist, 0); } int audio_buf_init(struct audio_softc *sc, struct audio_buf *buf, int dir) { klist_init_mutex(&buf->klist, &audio_lock); if (sc->ops->round_buffersize) { buf->datalen = sc->ops->round_buffersize(sc->arg, dir, AUDIO_BUFSZ); } else buf->datalen = AUDIO_BUFSZ; if (sc->ops->allocm) { buf->data = sc->ops->allocm(sc->arg, dir, buf->datalen, M_DEVBUF, M_WAITOK); } else buf->data = malloc(buf->datalen, M_DEVBUF, M_WAITOK); if (buf->data == NULL) { klist_free(&buf->klist); return ENOMEM; } return 0; } void audio_buf_done(struct audio_softc *sc, struct audio_buf *buf) { if (sc->ops->freem) sc->ops->freem(sc->arg, buf->data, M_DEVBUF); else free(buf->data, M_DEVBUF, buf->datalen); klist_free(&buf->klist); } /* * return the reader pointer and the number of bytes available */ unsigned char * audio_buf_rgetblk(struct audio_buf *buf, size_t *rsize) { size_t count; count = buf->len - buf->start; if (count > buf->used) count = buf->used; *rsize = count; return buf->data + buf->start; } /* * discard "count" bytes at the start position. */ void audio_buf_rdiscard(struct audio_buf *buf, size_t count) { #ifdef AUDIO_DEBUG if (count > buf->used) { panic("audio_buf_rdiscard: bad count = %zu, " "start = %zu, used = %zu", count, buf->start, buf->used); } #endif buf->used -= count; buf->start += count; if (buf->start >= buf->len) buf->start -= buf->len; } /* * advance the writer pointer by "count" bytes */ void audio_buf_wcommit(struct audio_buf *buf, size_t count) { #ifdef AUDIO_DEBUG if (count > (buf->len - buf->used)) { panic("audio_buf_wcommit: bad count = %zu, " "start = %zu, used = %zu", count, buf->start, buf->used); } #endif buf->used += count; } /* * get writer pointer and the number of bytes writable */ unsigned char * audio_buf_wgetblk(struct audio_buf *buf, size_t *rsize) { size_t end, avail, count; end = buf->start + buf->used; if (end >= buf->len) end -= buf->len; avail = buf->len - buf->used; count = buf->len - end; if (count > avail) count = avail; *rsize = count; return buf->data + end; } void audio_calc_sil(struct audio_softc *sc) { unsigned char *q; unsigned int s, i; int d, e; e = sc->sw_enc; #ifdef AUDIO_DEBUG switch (e) { case AUDIO_ENCODING_SLINEAR_LE: case AUDIO_ENCODING_ULINEAR_LE: case AUDIO_ENCODING_SLINEAR_BE: case AUDIO_ENCODING_ULINEAR_BE: break; default: printf("%s: unhandled play encoding %d\n", DEVNAME(sc), e); memset(sc->silence, 0, sc->bps); return; } #endif if (e == AUDIO_ENCODING_SLINEAR_BE || e == AUDIO_ENCODING_ULINEAR_BE) { d = -1; q = sc->silence + sc->bps - 1; } else { d = 1; q = sc->silence; } if (e == AUDIO_ENCODING_SLINEAR_LE || e == AUDIO_ENCODING_SLINEAR_BE) { s = 0; } else { s = 0x80000000; if (sc->msb) s >>= 32 - 8 * sc->bps; else s >>= 32 - sc->bits; } for (i = 0; i < sc->bps; i++) { *q = s; q += d; s >>= 8; } if (sc->conv_enc) sc->conv_enc(sc->silence, sc->bps); } void audio_fill_sil(struct audio_softc *sc, unsigned char *ptr, size_t count) { unsigned char *q, *p; size_t i, j; q = ptr; for (j = count / sc->bps; j > 0; j--) { p = sc->silence; for (i = sc->bps; i > 0; i--) *q++ = *p++; } } void audio_clear(struct audio_softc *sc) { if (sc->mode & AUMODE_PLAY) { sc->play.used = sc->play.start = 0; sc->play.pos = sc->play.xrun = 0; audio_fill_sil(sc, sc->play.data, sc->play.len); } if (sc->mode & AUMODE_RECORD) { sc->rec.used = sc->rec.start = 0; sc->rec.pos = sc->rec.xrun = 0; audio_fill_sil(sc, sc->rec.data, sc->rec.len); } } /* * called whenever a block is consumed by the driver */ void audio_pintr(void *addr) { struct audio_softc *sc = addr; unsigned char *ptr; size_t count; int error, nblk, todo; MUTEX_ASSERT_LOCKED(&audio_lock); if (!(sc->mode & AUMODE_PLAY) || !sc->active) { printf("%s: play interrupt but not playing\n", DEVNAME(sc)); return; } if (sc->quiesce) { DPRINTF("%s: quiesced, skipping play intr\n", DEVNAME(sc)); return; } /* * check if record pointer wrapped, see explanation * in audio_rintr() */ if ((sc->mode & AUMODE_RECORD) && sc->ops->underrun == NULL) { sc->offs--; nblk = sc->rec.len / sc->rec.blksz; todo = -sc->offs; if (todo >= nblk) { todo -= todo % nblk; DPRINTFN(1, "%s: rec ptr wrapped, moving %d blocks\n", DEVNAME(sc), todo); while (todo-- > 0) audio_rintr(sc); } } sc->play.pos += sc->play.blksz; if (!sc->ops->underrun) { audio_fill_sil(sc, sc->play.data + sc->play.start, sc->play.blksz); } audio_buf_rdiscard(&sc->play, sc->play.blksz); if (sc->play.used < sc->play.blksz) { DPRINTFN(1, "%s: play underrun\n", DEVNAME(sc)); sc->play.xrun += sc->play.blksz; audio_buf_wcommit(&sc->play, sc->play.blksz); if (sc->ops->underrun) sc->ops->underrun(sc->arg); } DPRINTFN(1, "%s: play intr, used -> %zu, start -> %zu\n", DEVNAME(sc), sc->play.used, sc->play.start); if (!sc->ops->trigger_output) { ptr = audio_buf_rgetblk(&sc->play, &count); error = sc->ops->start_output(sc->arg, ptr, sc->play.blksz, audio_pintr, sc); if (error) { printf("%s: play restart failed: %d\n", DEVNAME(sc), error); } } if (sc->play.used < sc->play.len) { DPRINTFN(1, "%s: play wakeup, chan = %d\n", DEVNAME(sc), sc->play.blocking); audio_buf_wakeup(&sc->play); } } /* * called whenever a block is produced by the driver */ void audio_rintr(void *addr) { struct audio_softc *sc = addr; unsigned char *ptr; size_t count; int error, nblk, todo; MUTEX_ASSERT_LOCKED(&audio_lock); if (!(sc->mode & AUMODE_RECORD) || !sc->active) { printf("%s: rec interrupt but not recording\n", DEVNAME(sc)); return; } if (sc->quiesce) { DPRINTF("%s: quiesced, skipping rec intr\n", DEVNAME(sc)); return; } /* * Interrupts may be masked by other sub-systems during 320ms * and more. During such a delay the hardware doesn't stop * playing and the play buffer pointers may wrap, this can't be * detected and corrected by low level drivers. This makes the * record stream ahead of the play stream; this is detected as a * hardware anomaly by userland and cause programs to misbehave. * * We fix this by advancing play position by an integer count of * full buffers, so it reaches the record position. */ if ((sc->mode & AUMODE_PLAY) && sc->ops->underrun == NULL) { sc->offs++; nblk = sc->play.len / sc->play.blksz; todo = sc->offs; if (todo >= nblk) { todo -= todo % nblk; DPRINTFN(1, "%s: play ptr wrapped, moving %d blocks\n", DEVNAME(sc), todo); while (todo-- > 0) audio_pintr(sc); } } sc->rec.pos += sc->rec.blksz; if ((sc->record_enable == MIXER_RECORD_ENABLE_SYSCTL && !audio_record_enable) || sc->record_enable == MIXER_RECORD_ENABLE_OFF) { ptr = audio_buf_wgetblk(&sc->rec, &count); audio_fill_sil(sc, ptr, sc->rec.blksz); } audio_buf_wcommit(&sc->rec, sc->rec.blksz); if (sc->rec.used > sc->rec.len - sc->rec.blksz) { DPRINTFN(1, "%s: rec overrun\n", DEVNAME(sc)); sc->rec.xrun += sc->rec.blksz; audio_buf_rdiscard(&sc->rec, sc->rec.blksz); } DPRINTFN(1, "%s: rec intr, used -> %zu\n", DEVNAME(sc), sc->rec.used); if (!sc->ops->trigger_input) { ptr = audio_buf_wgetblk(&sc->rec, &count); error = sc->ops->start_input(sc->arg, ptr, sc->rec.blksz, audio_rintr, sc); if (error) { printf("%s: rec restart failed: %d\n", DEVNAME(sc), error); } } if (sc->rec.used > 0) { DPRINTFN(1, "%s: rec wakeup, chan = %d\n", DEVNAME(sc), sc->rec.blocking); audio_buf_wakeup(&sc->rec); } } int audio_start_do(struct audio_softc *sc) { int error; struct audio_params p; unsigned char *ptr; size_t count; DPRINTF("%s: starting\n", DEVNAME(sc)); error = 0; sc->offs = 0; if (sc->mode & AUMODE_PLAY) { if (sc->ops->trigger_output) { p.encoding = sc->hw_enc; p.precision = sc->bits; p.bps = sc->bps; p.msb = sc->msb; p.sample_rate = sc->rate; p.channels = sc->pchan; error = sc->ops->trigger_output(sc->arg, sc->play.data, sc->play.data + sc->play.len, sc->play.blksz, audio_pintr, sc, &p); } else { mtx_enter(&audio_lock); ptr = audio_buf_rgetblk(&sc->play, &count); error = sc->ops->start_output(sc->arg, ptr, sc->play.blksz, audio_pintr, sc); mtx_leave(&audio_lock); } if (error) printf("%s: failed to start playback\n", DEVNAME(sc)); } if (sc->mode & AUMODE_RECORD) { if (sc->ops->trigger_input) { p.encoding = sc->hw_enc; p.precision = sc->bits; p.bps = sc->bps; p.msb = sc->msb; p.sample_rate = sc->rate; p.channels = sc->rchan; error = sc->ops->trigger_input(sc->arg, sc->rec.data, sc->rec.data + sc->rec.len, sc->rec.blksz, audio_rintr, sc, &p); } else { mtx_enter(&audio_lock); ptr = audio_buf_wgetblk(&sc->rec, &count); error = sc->ops->start_input(sc->arg, ptr, sc->rec.blksz, audio_rintr, sc); mtx_leave(&audio_lock); } if (error) printf("%s: failed to start recording\n", DEVNAME(sc)); } return error; } int audio_stop_do(struct audio_softc *sc) { if (sc->mode & AUMODE_PLAY) sc->ops->halt_output(sc->arg); if (sc->mode & AUMODE_RECORD) sc->ops->halt_input(sc->arg); DPRINTF("%s: stopped\n", DEVNAME(sc)); return 0; } int audio_start(struct audio_softc *sc) { sc->active = 1; sc->play.xrun = sc->play.pos = sc->rec.xrun = sc->rec.pos = 0; return audio_start_do(sc); } int audio_stop(struct audio_softc *sc) { int error; error = audio_stop_do(sc); if (error) return error; audio_clear(sc); sc->active = 0; return 0; } int audio_canstart(struct audio_softc *sc) { if (sc->active || sc->pause) return 0; if ((sc->mode & AUMODE_RECORD) && sc->rec.used != 0) return 0; if ((sc->mode & AUMODE_PLAY) && sc->play.used != sc->play.len) return 0; return 1; } int audio_setpar_blksz(struct audio_softc *sc, struct audio_params *p, struct audio_params *r) { unsigned int nr, np, max, min, mult; unsigned int blk_mult, blk_max; if (sc->ops->set_blksz) { /* * Don't allow block size of exceed half the buffer size */ if (sc->mode & AUMODE_PLAY) { max = sc->play.datalen / 2 / (sc->pchan * sc->bps); if (sc->round > max) sc->round = max; } if (sc->mode & AUMODE_RECORD) { max = sc->rec.datalen / 2 / (sc->rchan * sc->bps); if (sc->round > max) sc->round = max; } sc->round = sc->ops->set_blksz(sc->arg, sc->mode, p, r, sc->round); DPRINTF("%s: block size set to: %u\n", DEVNAME(sc), sc->round); return 0; } /* * get least multiplier of the number of frames per block */ if (sc->ops->round_blocksize) { blk_mult = sc->ops->round_blocksize(sc->arg, 1); if (blk_mult == 0) { printf("%s: 0x%x: bad block size multiplier\n", DEVNAME(sc), blk_mult); return ENODEV; } } else blk_mult = 1; DPRINTF("%s: hw block size multiplier: %u\n", DEVNAME(sc), blk_mult); if (sc->mode & AUMODE_PLAY) { np = blk_mult / audio_gcd(sc->pchan * sc->bps, blk_mult); if (!(sc->mode & AUMODE_RECORD)) nr = np; DPRINTF("%s: play number of frames multiplier: %u\n", DEVNAME(sc), np); } if (sc->mode & AUMODE_RECORD) { nr = blk_mult / audio_gcd(sc->rchan * sc->bps, blk_mult); if (!(sc->mode & AUMODE_PLAY)) np = nr; DPRINTF("%s: record number of frames multiplier: %u\n", DEVNAME(sc), nr); } mult = nr * np / audio_gcd(nr, np); DPRINTF("%s: least common number of frames multiplier: %u\n", DEVNAME(sc), mult); /* * get minimum and maximum frames per block */ if (sc->ops->round_blocksize) blk_max = sc->ops->round_blocksize(sc->arg, AUDIO_BUFSZ); else blk_max = AUDIO_BUFSZ; if ((sc->mode & AUMODE_PLAY) && blk_max > sc->play.datalen / 2) blk_max = sc->play.datalen / 2; if ((sc->mode & AUMODE_RECORD) && blk_max > sc->rec.datalen / 2) blk_max = sc->rec.datalen / 2; if (sc->mode & AUMODE_PLAY) { np = blk_max / (sc->pchan * sc->bps); if (!(sc->mode & AUMODE_RECORD)) nr = np; } if (sc->mode & AUMODE_RECORD) { nr = blk_max / (sc->rchan * sc->bps); if (!(sc->mode & AUMODE_PLAY)) np = nr; } max = np < nr ? np : nr; max -= max % mult; min = sc->rate / 1000 + mult - 1; min -= min % mult; DPRINTF("%s: frame number range: %u..%u\n", DEVNAME(sc), min, max); if (max < min) { printf("%s: %u: bad max frame number\n", DEVNAME(sc), max); return EIO; } /* * adjust the frame per block to match our constraints */ sc->round += mult / 2; sc->round -= sc->round % mult; if (sc->round > max) sc->round = max; else if (sc->round < min) sc->round = min; return 0; } int audio_setpar_nblks(struct audio_softc *sc, struct audio_params *p, struct audio_params *r) { unsigned int max; /* * set buffer size (number of blocks) */ if (sc->mode & AUMODE_PLAY) { max = sc->play.datalen / (sc->round * sc->pchan * sc->bps); if (sc->play.nblks > max) sc->play.nblks = max; else if (sc->play.nblks < 2) sc->play.nblks = 2; if (sc->ops->set_nblks) { sc->play.nblks = sc->ops->set_nblks(sc->arg, sc->mode, p, sc->round, sc->play.nblks); DPRINTF("%s: play nblks -> %u\n", DEVNAME(sc), sc->play.nblks); } } if (sc->mode & AUMODE_RECORD) { /* * for recording, buffer size is not the latency (it's * exactly one block), so let's get the maximum buffer * size of maximum reliability during xruns */ max = sc->rec.datalen / (sc->round * sc->rchan * sc->bps); if (sc->ops->set_nblks) { max = sc->ops->set_nblks(sc->arg, sc->mode, r, sc->round, max); DPRINTF("%s: rec nblks -> %u\n", DEVNAME(sc), max); } sc->rec.nblks = max; } return 0; } int audio_setpar(struct audio_softc *sc) { struct audio_params p, r; int error; DPRINTF("%s: setpar: req enc=%d bits=%d, bps=%d, msb=%d " "rate=%d, pchan=%d, rchan=%d, round=%u, nblks=%d\n", DEVNAME(sc), sc->sw_enc, sc->bits, sc->bps, sc->msb, sc->rate, sc->pchan, sc->rchan, sc->round, sc->play.nblks); /* * check if requested parameters are in the allowed ranges */ if (sc->mode & AUMODE_PLAY) { if (sc->pchan < 1) sc->pchan = 1; else if (sc->pchan > 64) sc->pchan = 64; } if (sc->mode & AUMODE_RECORD) { if (sc->rchan < 1) sc->rchan = 1; else if (sc->rchan > 64) sc->rchan = 64; } switch (sc->sw_enc) { case AUDIO_ENCODING_ULAW: case AUDIO_ENCODING_ALAW: case AUDIO_ENCODING_SLINEAR_LE: case AUDIO_ENCODING_SLINEAR_BE: case AUDIO_ENCODING_ULINEAR_LE: case AUDIO_ENCODING_ULINEAR_BE: break; default: sc->sw_enc = AUDIO_ENCODING_SLINEAR_LE; } if (sc->bits < 8) sc->bits = 8; else if (sc->bits > 32) sc->bits = 32; if (sc->bps < 1) sc->bps = 1; else if (sc->bps > 4) sc->bps = 4; if (sc->rate < 4000) sc->rate = 4000; else if (sc->rate > 192000) sc->rate = 192000; /* * copy into struct audio_params, required by drivers */ p.encoding = r.encoding = sc->sw_enc; p.precision = r.precision = sc->bits; p.bps = r.bps = sc->bps; p.msb = r.msb = sc->msb; p.sample_rate = r.sample_rate = sc->rate; p.channels = sc->pchan; r.channels = sc->rchan; /* * set parameters */ error = sc->ops->set_params(sc->arg, sc->mode, sc->mode, &p, &r); if (error) return error; if (sc->mode == (AUMODE_PLAY | AUMODE_RECORD)) { if (p.encoding != r.encoding || p.precision != r.precision || p.bps != r.bps || p.msb != r.msb || p.sample_rate != r.sample_rate) { printf("%s: different play and record parameters " "returned by hardware\n", DEVNAME(sc)); return ENODEV; } } if (sc->mode & AUMODE_PLAY) { sc->hw_enc = p.encoding; sc->bits = p.precision; sc->bps = p.bps; sc->msb = p.msb; sc->rate = p.sample_rate; sc->pchan = p.channels; } if (sc->mode & AUMODE_RECORD) { sc->hw_enc = r.encoding; sc->bits = r.precision; sc->bps = r.bps; sc->msb = r.msb; sc->rate = r.sample_rate; sc->rchan = r.channels; } if (sc->rate == 0 || sc->bps == 0 || sc->bits == 0) { printf("%s: invalid parameters returned by hardware\n", DEVNAME(sc)); return ENODEV; } if (sc->ops->commit_settings) { error = sc->ops->commit_settings(sc->arg); if (error) return error; } /* * conversion from/to exotic/dead encoding, for drivers not supporting * linear */ switch (sc->hw_enc) { case AUDIO_ENCODING_SLINEAR_LE: case AUDIO_ENCODING_SLINEAR_BE: case AUDIO_ENCODING_ULINEAR_LE: case AUDIO_ENCODING_ULINEAR_BE: sc->sw_enc = sc->hw_enc; sc->conv_dec = sc->conv_enc = NULL; break; case AUDIO_ENCODING_ULAW: #if BYTE_ORDER == LITTLE_ENDIAN sc->sw_enc = AUDIO_ENCODING_SLINEAR_LE; #else sc->sw_enc = AUDIO_ENCODING_SLINEAR_BE; #endif if (sc->bits == 8) { sc->conv_enc = slinear8_to_mulaw; sc->conv_dec = mulaw_to_slinear8; } else if (sc->bits == 24) { sc->conv_enc = slinear24_to_mulaw24; sc->conv_dec = mulaw24_to_slinear24; } else { sc->sw_enc = sc->hw_enc; sc->conv_dec = sc->conv_enc = NULL; } break; default: printf("%s: setpar: enc = %d, bits = %d: emulation skipped\n", DEVNAME(sc), sc->hw_enc, sc->bits); sc->sw_enc = sc->hw_enc; sc->conv_dec = sc->conv_enc = NULL; } audio_calc_sil(sc); error = audio_setpar_blksz(sc, &p, &r); if (error) return error; error = audio_setpar_nblks(sc, &p, &r); if (error) return error; /* * set buffer */ if (sc->mode & AUMODE_PLAY) { sc->play.blksz = sc->round * sc->pchan * sc->bps; sc->play.len = sc->play.nblks * sc->play.blksz; } if (sc->mode & AUMODE_RECORD) { sc->rec.blksz = sc->round * sc->rchan * sc->bps; sc->rec.len = sc->rec.nblks * sc->rec.blksz; } DPRINTF("%s: setpar: new enc=%d bits=%d, bps=%d, msb=%d " "rate=%d, pchan=%d, rchan=%d, round=%u, nblks=%d\n", DEVNAME(sc), sc->sw_enc, sc->bits, sc->bps, sc->msb, sc->rate, sc->pchan, sc->rchan, sc->round, sc->play.nblks); return 0; } int audio_ioc_start(struct audio_softc *sc) { if (!sc->pause) { DPRINTF("%s: can't start: already started\n", DEVNAME(sc)); return EBUSY; } if ((sc->mode & AUMODE_PLAY) && sc->play.used != sc->play.len) { DPRINTF("%s: play buffer not ready\n", DEVNAME(sc)); return EBUSY; } if ((sc->mode & AUMODE_RECORD) && sc->rec.used != 0) { DPRINTF("%s: record buffer not ready\n", DEVNAME(sc)); return EBUSY; } sc->pause = 0; return audio_start(sc); } int audio_ioc_stop(struct audio_softc *sc) { if (sc->pause) { DPRINTF("%s: can't stop: not started\n", DEVNAME(sc)); return EBUSY; } sc->pause = 1; if (sc->active) return audio_stop(sc); return 0; } int audio_ioc_getpar(struct audio_softc *sc, struct audio_swpar *p) { p->rate = sc->rate; p->sig = sc->sw_enc == AUDIO_ENCODING_SLINEAR_LE || sc->sw_enc == AUDIO_ENCODING_SLINEAR_BE; p->le = sc->sw_enc == AUDIO_ENCODING_SLINEAR_LE || sc->sw_enc == AUDIO_ENCODING_ULINEAR_LE; p->bits = sc->bits; p->bps = sc->bps; p->msb = sc->msb; p->pchan = sc->pchan; p->rchan = sc->rchan; p->nblks = sc->play.nblks; p->round = sc->round; return 0; } int audio_ioc_setpar(struct audio_softc *sc, struct audio_swpar *p) { int error, le, sig; if (sc->active) { DPRINTF("%s: can't change params during dma\n", DEVNAME(sc)); return EBUSY; } /* * copy desired parameters into the softc structure */ if (p->sig != ~0U || p->le != ~0U || p->bits != ~0U) { sig = 1; le = (BYTE_ORDER == LITTLE_ENDIAN); sc->bits = 16; sc->bps = 2; sc->msb = 1; if (p->sig != ~0U) sig = p->sig; if (p->le != ~0U) le = p->le; if (p->bits != ~0U) { sc->bits = p->bits; sc->bps = sc->bits <= 8 ? 1 : (sc->bits <= 16 ? 2 : 4); if (p->bps != ~0U) sc->bps = p->bps; if (p->msb != ~0U) sc->msb = p->msb ? 1 : 0; } sc->sw_enc = (sig) ? (le ? AUDIO_ENCODING_SLINEAR_LE : AUDIO_ENCODING_SLINEAR_BE) : (le ? AUDIO_ENCODING_ULINEAR_LE : AUDIO_ENCODING_ULINEAR_BE); } if (p->rate != ~0) sc->rate = p->rate; if (p->pchan != ~0) sc->pchan = p->pchan; if (p->rchan != ~0) sc->rchan = p->rchan; if (p->round != ~0) sc->round = p->round; if (p->nblks != ~0) sc->play.nblks = p->nblks; /* * if the device is not opened for playback or recording don't * touch the hardware yet (ex. if this is /dev/audioctlN) */ if (sc->mode == 0) return 0; /* * negotiate parameters with the hardware */ error = audio_setpar(sc); if (error) return error; audio_clear(sc); if ((sc->mode & AUMODE_PLAY) && sc->ops->init_output) { error = sc->ops->init_output(sc->arg, sc->play.data, sc->play.len); if (error) return error; } if ((sc->mode & AUMODE_RECORD) && sc->ops->init_input) { error = sc->ops->init_input(sc->arg, sc->rec.data, sc->rec.len); if (error) return error; } return 0; } int audio_ioc_getstatus(struct audio_softc *sc, struct audio_status *p) { p->mode = sc->mode; p->pause = sc->pause; p->active = sc->active; return 0; } int audio_match(struct device *parent, void *match, void *aux) { struct audio_attach_args *sa = aux; return (sa->type == AUDIODEV_TYPE_AUDIO) ? 1 : 0; } void audio_attach(struct device *parent, struct device *self, void *aux) { struct audio_softc *sc = (void *)self; struct audio_attach_args *sa = aux; const struct audio_hw_if *ops = sa->hwif; struct mixer_devinfo *mi; struct mixer_ctrl *ent; void *arg = sa->hdl; int error; printf("\n"); #ifdef DIAGNOSTIC if (ops == 0 || ops->open == 0 || ops->close == 0 || ops->set_params == 0 || (ops->start_output == 0 && ops->trigger_output == 0) || (ops->start_input == 0 && ops->trigger_input == 0) || ops->halt_output == 0 || ops->halt_input == 0 || ops->set_port == 0 || ops->get_port == 0 || ops->query_devinfo == 0) { printf("%s: missing method\n", DEVNAME(sc)); sc->ops = 0; return; } #endif sc->ops = ops; sc->cookie = sa->cookie; sc->arg = arg; #if NWSKBD > 0 wskbd_mixer_init(sc); #endif /* NWSKBD > 0 */ error = audio_buf_init(sc, &sc->play, AUMODE_PLAY); if (error) { sc->ops = 0; printf("%s: could not allocate play buffer\n", DEVNAME(sc)); return; } error = audio_buf_init(sc, &sc->rec, AUMODE_RECORD); if (error) { audio_buf_done(sc, &sc->play); sc->ops = 0; printf("%s: could not allocate record buffer\n", DEVNAME(sc)); return; } klist_init_mutex(&sc->mix_klist, &audio_lock); /* set defaults */ #if BYTE_ORDER == LITTLE_ENDIAN sc->sw_enc = AUDIO_ENCODING_SLINEAR_LE; #else sc->sw_enc = AUDIO_ENCODING_SLINEAR_BE; #endif sc->bits = 16; sc->bps = 2; sc->msb = 1; sc->rate = 48000; sc->pchan = 2; sc->rchan = 2; sc->round = 960; sc->play.nblks = 2; sc->play.pos = sc->play.xrun = sc->rec.pos = sc->rec.xrun = 0; sc->record_enable = MIXER_RECORD_ENABLE_SYSCTL; /* * allocate an array of mixer_ctrl structures to save the * mixer state and prefill them. */ mi = malloc(sizeof(struct mixer_devinfo), M_TEMP, M_WAITOK); mi->index = 0; while (1) { if (sc->ops->query_devinfo(sc->arg, mi) != 0) break; mi->index++; } sc->mix_nent = mi->index; sc->mix_ents = mallocarray(sc->mix_nent, sizeof(struct mixer_ctrl), M_DEVBUF, M_WAITOK); sc->mix_evbuf = mallocarray(sc->mix_nent, sizeof(struct mixer_ev), M_DEVBUF, M_WAITOK | M_ZERO); ent = sc->mix_ents; mi->index = 0; while (1) { if (sc->ops->query_devinfo(sc->arg, mi) != 0) break; switch (mi->type) { case AUDIO_MIXER_VALUE: ent->un.value.num_channels = mi->un.v.num_channels; /* FALLTHROUGH */ case AUDIO_MIXER_SET: case AUDIO_MIXER_ENUM: ent->dev = mi->index; ent->type = mi->type; } mi->index++; ent++; } free(mi, M_TEMP, sizeof(struct mixer_devinfo)); } int audio_activate(struct device *self, int act) { struct audio_softc *sc = (struct audio_softc *)self; int i; switch (act) { case DVACT_QUIESCE: /* * good drivers run play and rec handlers in a single * interrupt. Grab the lock to ensure we expose the same * sc->quiesce value to both play and rec handlers */ mtx_enter(&audio_lock); sc->quiesce = 1; mtx_leave(&audio_lock); /* * once sc->quiesce is set, interrupts may occur, but * counters are not advanced and consequently processes * keep sleeping. * * XXX: ensure read/write/ioctl don't start/stop * DMA at the same time, this needs a "ready" condvar */ if (sc->mode != 0 && sc->active) audio_stop_do(sc); /* * save mixer state */ for (i = 0; i != sc->mix_nent; i++) sc->ops->get_port(sc->arg, sc->mix_ents + i); DPRINTF("%s: quiesce: active = %d\n", DEVNAME(sc), sc->active); break; case DVACT_WAKEUP: DPRINTF("%s: wakeup: active = %d\n", DEVNAME(sc), sc->active); /* * restore mixer state */ for (i = 0; i != sc->mix_nent; i++) sc->ops->set_port(sc->arg, sc->mix_ents + i); /* * keep buffer usage the same, but set start pointer to * the beginning of the buffer. * * No need to grab the audio_lock as DMA is stopped and * this is the only thread running (caller ensures this) */ sc->quiesce = 0; wakeup(&sc->quiesce); if (sc->mode != 0) { if (audio_setpar(sc) != 0) break; if (sc->mode & AUMODE_PLAY) { sc->play.start = 0; audio_fill_sil(sc, sc->play.data, sc->play.len); } if (sc->mode & AUMODE_RECORD) { sc->rec.start = sc->rec.len - sc->rec.used; audio_fill_sil(sc, sc->rec.data, sc->rec.len); } if (sc->active) audio_start_do(sc); } break; } return 0; } int audio_detach(struct device *self, int flags) { struct audio_softc *sc = (struct audio_softc *)self; int maj, mn; DPRINTF("%s: audio_detach: flags = %d\n", DEVNAME(sc), flags); wakeup(&sc->quiesce); /* locate the major number */ for (maj = 0; maj < nchrdev; maj++) if (cdevsw[maj].d_open == audioopen) break; /* * Nuke the vnodes for any open instances, calls close but as * close uses device_lookup, it returns EXIO and does nothing */ mn = self->dv_unit; vdevgone(maj, mn | AUDIO_DEV_AUDIO, mn | AUDIO_DEV_AUDIO, VCHR); vdevgone(maj, mn | AUDIO_DEV_AUDIOCTL, mn | AUDIO_DEV_AUDIOCTL, VCHR); /* * The close() method did nothing, quickly halt DMA (normally * parent is already gone, and code below is no-op), and wake-up * user-land blocked in read/write/ioctl, which return EIO. */ if (sc->mode != 0) { if (sc->active) { wakeup(&sc->play.blocking); wakeup(&sc->rec.blocking); audio_stop(sc); } sc->ops->close(sc->arg); sc->mode = 0; } if (sc->mix_isopen) wakeup(&sc->mix_blocking); klist_invalidate(&sc->play.klist); klist_invalidate(&sc->rec.klist); klist_invalidate(&sc->mix_klist); /* free resources */ klist_free(&sc->mix_klist); free(sc->mix_evbuf, M_DEVBUF, sc->mix_nent * sizeof(struct mixer_ev)); free(sc->mix_ents, M_DEVBUF, sc->mix_nent * sizeof(struct mixer_ctrl)); audio_buf_done(sc, &sc->play); audio_buf_done(sc, &sc->rec); return 0; } int audio_submatch(struct device *parent, void *match, void *aux) { struct cfdata *cf = match; return (cf->cf_driver == &audio_cd); } struct device * audio_attach_mi(const struct audio_hw_if *ops, void *arg, void *cookie, struct device *dev) { struct audio_attach_args aa; aa.type = AUDIODEV_TYPE_AUDIO; aa.hwif = ops; aa.hdl = arg; aa.cookie = cookie; /* * attach this driver to the caller (hardware driver), this * checks the kernel config and possibly calls audio_attach() */ return config_found_sm(dev, &aa, audioprint, audio_submatch); } int audioprint(void *aux, const char *pnp) { struct audio_attach_args *arg = aux; const char *type; if (pnp != NULL) { switch (arg->type) { case AUDIODEV_TYPE_AUDIO: type = "audio"; break; case AUDIODEV_TYPE_OPL: type = "opl"; break; case AUDIODEV_TYPE_MPU: type = "mpu"; break; default: panic("audioprint: unknown type %d", arg->type); } printf("%s at %s", type, pnp); } return UNCONF; } int audio_open(struct audio_softc *sc, int flags) { int error; if (sc->mode) return EBUSY; error = sc->ops->open(sc->arg, flags); if (error) return error; sc->active = 0; sc->pause = 1; sc->rec.blocking = 0; sc->play.blocking = 0; sc->mode = 0; if (flags & FWRITE) sc->mode |= AUMODE_PLAY; if (flags & FREAD) sc->mode |= AUMODE_RECORD; error = audio_setpar(sc); if (error) goto bad; audio_clear(sc); /* * allow read(2)/write(2) to automatically start DMA, without * the need for ioctl(), to make /dev/audio usable in scripts */ sc->pause = 0; return 0; bad: sc->ops->close(sc->arg); sc->mode = 0; return error; } int audio_drain(struct audio_softc *sc) { int error, xrun; unsigned char *ptr; size_t count, bpf; DPRINTF("%s: drain: mode = %d, pause = %d, active = %d, used = %zu\n", DEVNAME(sc), sc->mode, sc->pause, sc->active, sc->play.used); if (!(sc->mode & AUMODE_PLAY) || sc->pause) return 0; /* discard partial samples, required by audio_fill_sil() */ mtx_enter(&audio_lock); bpf = sc->pchan * sc->bps; sc->play.used -= sc->play.used % bpf; if (sc->play.used == 0) { mtx_leave(&audio_lock); return 0; } if (!sc->active) { /* * dma not started yet because buffer was not full * enough to start automatically. Pad it and start now. */ for (;;) { ptr = audio_buf_wgetblk(&sc->play, &count); if (count == 0) break; audio_fill_sil(sc, ptr, count); audio_buf_wcommit(&sc->play, count); } mtx_leave(&audio_lock); error = audio_start(sc); if (error) return error; mtx_enter(&audio_lock); } xrun = sc->play.xrun; while (sc->play.xrun == xrun) { DPRINTF("%s: drain: used = %zu, xrun = %d\n", DEVNAME(sc), sc->play.used, sc->play.xrun); /* * set a 5 second timeout, in case interrupts don't * work, useful only for debugging drivers */ sc->play.blocking = 1; error = msleep_nsec(&sc->play.blocking, &audio_lock, PWAIT | PCATCH, "au_dr", SEC_TO_NSEC(5)); if (!(sc->dev.dv_flags & DVF_ACTIVE)) error = EIO; if (error) { DPRINTF("%s: drain, err = %d\n", DEVNAME(sc), error); break; } } mtx_leave(&audio_lock); return error; } int audio_close(struct audio_softc *sc) { audio_drain(sc); if (sc->active) audio_stop(sc); sc->ops->close(sc->arg); sc->mode = 0; DPRINTF("%s: close: done\n", DEVNAME(sc)); return 0; } int audio_read(struct audio_softc *sc, struct uio *uio, int ioflag) { unsigned char *ptr; size_t count; int error; DPRINTFN(1, "%s: read: resid = %zd\n", DEVNAME(sc), uio->uio_resid); /* block if quiesced */ while (sc->quiesce) tsleep_nsec(&sc->quiesce, 0, "au_qrd", INFSLP); /* start automatically if audio_ioc_start() was never called */ if (audio_canstart(sc)) { error = audio_start(sc); if (error) return error; } mtx_enter(&audio_lock); /* if there is no data then sleep */ while (sc->rec.used == 0) { if (ioflag & IO_NDELAY) { mtx_leave(&audio_lock); return EWOULDBLOCK; } DPRINTFN(1, "%s: read sleep\n", DEVNAME(sc)); sc->rec.blocking = 1; error = msleep_nsec(&sc->rec.blocking, &audio_lock, PWAIT | PCATCH, "au_rd", INFSLP); if (!(sc->dev.dv_flags & DVF_ACTIVE)) error = EIO; if (error) { DPRINTF("%s: read woke up error = %d\n", DEVNAME(sc), error); mtx_leave(&audio_lock); return error; } } /* at this stage, there is data to transfer */ while (uio->uio_resid > 0 && sc->rec.used > 0) { ptr = audio_buf_rgetblk(&sc->rec, &count); if (count > uio->uio_resid) count = uio->uio_resid; mtx_leave(&audio_lock); DPRINTFN(1, "%s: read: start = %zu, count = %zu\n", DEVNAME(sc), ptr - sc->rec.data, count); if (sc->conv_dec) sc->conv_dec(ptr, count); error = uiomove(ptr, count, uio); if (error) return error; mtx_enter(&audio_lock); audio_buf_rdiscard(&sc->rec, count); } mtx_leave(&audio_lock); return 0; } int audio_write(struct audio_softc *sc, struct uio *uio, int ioflag) { unsigned char *ptr; size_t count; int error; DPRINTFN(1, "%s: write: resid = %zd\n", DEVNAME(sc), uio->uio_resid); /* block if quiesced */ while (sc->quiesce) tsleep_nsec(&sc->quiesce, 0, "au_qwr", INFSLP); /* * if IO_NDELAY flag is set then check if there is enough room * in the buffer to store at least one byte. If not then don't * start the write process. */ mtx_enter(&audio_lock); if (uio->uio_resid > 0 && (ioflag & IO_NDELAY)) { if (sc->play.used == sc->play.len) { mtx_leave(&audio_lock); return EWOULDBLOCK; } } while (uio->uio_resid > 0) { while (1) { ptr = audio_buf_wgetblk(&sc->play, &count); if (count > 0) break; if (ioflag & IO_NDELAY) { /* * At this stage at least one byte is already * moved so we do not return EWOULDBLOCK */ mtx_leave(&audio_lock); return 0; } DPRINTFN(1, "%s: write sleep\n", DEVNAME(sc)); sc->play.blocking = 1; error = msleep_nsec(&sc->play.blocking, &audio_lock, PWAIT | PCATCH, "au_wr", INFSLP); if (!(sc->dev.dv_flags & DVF_ACTIVE)) error = EIO; if (error) { DPRINTF("%s: write woke up error = %d\n", DEVNAME(sc), error); mtx_leave(&audio_lock); return error; } } if (count > uio->uio_resid) count = uio->uio_resid; mtx_leave(&audio_lock); error = uiomove(ptr, count, uio); if (error) return 0; if (sc->conv_enc) { sc->conv_enc(ptr, count); DPRINTFN(1, "audio_write: converted count = %zu\n", count); } if (sc->ops->copy_output) sc->ops->copy_output(sc->arg, count); mtx_enter(&audio_lock); audio_buf_wcommit(&sc->play, count); /* start automatically if audio_ioc_start() was never called */ if (audio_canstart(sc)) { mtx_leave(&audio_lock); error = audio_start(sc); if (error) return error; mtx_enter(&audio_lock); } } mtx_leave(&audio_lock); return 0; } int audio_getdev(struct audio_softc *sc, struct audio_device *adev) { memset(adev, 0, sizeof(struct audio_device)); if (sc->dev.dv_parent == NULL) return EIO; strlcpy(adev->name, sc->dev.dv_parent->dv_xname, MAX_AUDIO_DEV_LEN); return 0; } int audio_ioctl(struct audio_softc *sc, unsigned long cmd, void *addr) { struct audio_pos *ap; int error = 0; /* block if quiesced */ while (sc->quiesce) tsleep_nsec(&sc->quiesce, 0, "au_qio", INFSLP); switch (cmd) { case FIONBIO: /* All handled in the upper FS layer. */ break; case AUDIO_GETPOS: mtx_enter(&audio_lock); ap = (struct audio_pos *)addr; ap->play_pos = sc->play.pos; ap->play_xrun = sc->play.xrun; ap->rec_pos = sc->rec.pos; ap->rec_xrun = sc->rec.xrun; mtx_leave(&audio_lock); break; case AUDIO_START: return audio_ioc_start(sc); case AUDIO_STOP: return audio_ioc_stop(sc); case AUDIO_SETPAR: error = audio_ioc_setpar(sc, (struct audio_swpar *)addr); break; case AUDIO_GETPAR: error = audio_ioc_getpar(sc, (struct audio_swpar *)addr); break; case AUDIO_GETSTATUS: error = audio_ioc_getstatus(sc, (struct audio_status *)addr); break; case AUDIO_GETDEV: error = audio_getdev(sc, (struct audio_device *)addr); break; default: DPRINTF("%s: unknown ioctl 0x%lx\n", DEVNAME(sc), cmd); error = ENOTTY; break; } return error; } void audio_event(struct audio_softc *sc, int addr) { struct mixer_ev *e; mtx_enter(&audio_lock); if (sc->mix_isopen) { e = sc->mix_evbuf + addr; if (!e->pending) { e->pending = 1; e->next = sc->mix_pending; sc->mix_pending = e; } audio_mixer_wakeup(sc); } mtx_leave(&audio_lock); } int audio_mixer_devinfo(struct audio_softc *sc, struct mixer_devinfo *devinfo) { if (devinfo->index < sc->mix_nent) return sc->ops->query_devinfo(sc->arg, devinfo); devinfo->next = -1; devinfo->prev = -1; switch (devinfo->index - sc->mix_nent) { case MIXER_RECORD: strlcpy(devinfo->label.name, AudioCrecord, MAX_AUDIO_DEV_LEN); devinfo->type = AUDIO_MIXER_CLASS; devinfo->mixer_class = -1; break; case MIXER_RECORD_ENABLE: strlcpy(devinfo->label.name, "enable", MAX_AUDIO_DEV_LEN); devinfo->type = AUDIO_MIXER_ENUM; devinfo->mixer_class = MIXER_RECORD + sc->mix_nent; devinfo->un.e.num_mem = 3; devinfo->un.e.member[0].ord = MIXER_RECORD_ENABLE_OFF; strlcpy(devinfo->un.e.member[0].label.name, "off", MAX_AUDIO_DEV_LEN); devinfo->un.e.member[1].ord = MIXER_RECORD_ENABLE_ON; strlcpy(devinfo->un.e.member[1].label.name, "on", MAX_AUDIO_DEV_LEN); devinfo->un.e.member[2].ord = MIXER_RECORD_ENABLE_SYSCTL; strlcpy(devinfo->un.e.member[2].label.name, "sysctl", MAX_AUDIO_DEV_LEN); break; default: return EINVAL; } return 0; } int audio_mixer_get(struct audio_softc *sc, struct mixer_ctrl *c) { if (c->dev < sc->mix_nent) return sc->ops->get_port(sc->arg, c); switch (c->dev - sc->mix_nent) { case MIXER_RECORD: return EBADF; case MIXER_RECORD_ENABLE: c->un.ord = sc->record_enable; break; default: return EINVAL; } return 0; } int audio_mixer_set(struct audio_softc *sc, struct mixer_ctrl *c, struct proc *p) { int error; if (c->dev < sc->mix_nent) { error = sc->ops->set_port(sc->arg, c); if (error) return error; if (sc->ops->commit_settings) return sc->ops->commit_settings(sc->arg); audio_event(sc, c->dev); return 0; } switch (c->dev - sc->mix_nent) { case MIXER_RECORD: return EBADF; case MIXER_RECORD_ENABLE: switch (c->un.ord) { case MIXER_RECORD_ENABLE_OFF: case MIXER_RECORD_ENABLE_ON: case MIXER_RECORD_ENABLE_SYSCTL: break; default: return EINVAL; } if (suser(p) == 0) sc->record_enable = c->un.ord; break; default: return EINVAL; } return 0; } int audio_ioctl_mixer(struct audio_softc *sc, unsigned long cmd, void *addr, struct proc *p) { /* block if quiesced */ while (sc->quiesce) tsleep_nsec(&sc->quiesce, 0, "mix_qio", INFSLP); switch (cmd) { case FIONBIO: /* All handled in the upper FS layer. */ break; case AUDIO_MIXER_DEVINFO: return audio_mixer_devinfo(sc, addr); case AUDIO_MIXER_READ: return audio_mixer_get(sc, addr); case AUDIO_MIXER_WRITE: return audio_mixer_set(sc, addr, p); default: return ENOTTY; } return 0; } int audio_mixer_read(struct audio_softc *sc, struct uio *uio, int ioflag) { struct mixer_ev *e; int data; int error; DPRINTF("%s: mixer read: resid = %zd\n", DEVNAME(sc), uio->uio_resid); /* block if quiesced */ while (sc->quiesce) tsleep_nsec(&sc->quiesce, 0, "mix_qrd", INFSLP); mtx_enter(&audio_lock); /* if there are no events then sleep */ while (!sc->mix_pending) { if (ioflag & IO_NDELAY) { mtx_leave(&audio_lock); return EWOULDBLOCK; } DPRINTF("%s: mixer read sleep\n", DEVNAME(sc)); sc->mix_blocking = 1; error = msleep_nsec(&sc->mix_blocking, &audio_lock, PWAIT | PCATCH, "mix_rd", INFSLP); if (!(sc->dev.dv_flags & DVF_ACTIVE)) error = EIO; if (error) { DPRINTF("%s: mixer read woke up error = %d\n", DEVNAME(sc), error); mtx_leave(&audio_lock); return error; } } /* at this stage, there is an event to transfer */ while (uio->uio_resid >= sizeof(int) && sc->mix_pending) { e = sc->mix_pending; sc->mix_pending = e->next; e->pending = 0; data = e - sc->mix_evbuf; mtx_leave(&audio_lock); DPRINTF("%s: mixer read: %u\n", DEVNAME(sc), data); error = uiomove(&data, sizeof(int), uio); if (error) return error; mtx_enter(&audio_lock); } mtx_leave(&audio_lock); return 0; } int audio_mixer_open(struct audio_softc *sc, int flags) { DPRINTF("%s: flags = 0x%x\n", __func__, flags); if (flags & FREAD) { if (sc->mix_isopen) return EBUSY; sc->mix_isopen = 1; } return 0; } int audio_mixer_close(struct audio_softc *sc, int flags) { int i; DPRINTF("%s: flags = 0x%x\n", __func__, flags); if (flags & FREAD) { sc->mix_isopen = 0; mtx_enter(&audio_lock); sc->mix_pending = NULL; for (i = 0; i < sc->mix_nent; i++) sc->mix_evbuf[i].pending = 0; mtx_leave(&audio_lock); } return 0; } int audioopen(dev_t dev, int flags, int mode, struct proc *p) { struct audio_softc *sc; int error; sc = (struct audio_softc *)device_lookup(&audio_cd, AUDIO_UNIT(dev)); if (sc == NULL) return ENXIO; if (sc->ops == NULL) error = ENXIO; else { switch (AUDIO_DEV(dev)) { case AUDIO_DEV_AUDIO: error = audio_open(sc, flags); break; case AUDIO_DEV_AUDIOCTL: error = audio_mixer_open(sc, flags); break; default: error = ENXIO; } } device_unref(&sc->dev); return error; } int audioclose(dev_t dev, int flags, int ifmt, struct proc *p) { struct audio_softc *sc; int error; sc = (struct audio_softc *)device_lookup(&audio_cd, AUDIO_UNIT(dev)); if (sc == NULL) return ENXIO; switch (AUDIO_DEV(dev)) { case AUDIO_DEV_AUDIO: error = audio_close(sc); break; case AUDIO_DEV_AUDIOCTL: error = audio_mixer_close(sc, flags); break; default: error = ENXIO; } device_unref(&sc->dev); return error; } int audioread(dev_t dev, struct uio *uio, int ioflag) { struct audio_softc *sc; int error; sc = (struct audio_softc *)device_lookup(&audio_cd, AUDIO_UNIT(dev)); if (sc == NULL) return ENXIO; switch (AUDIO_DEV(dev)) { case AUDIO_DEV_AUDIO: error = audio_read(sc, uio, ioflag); break; case AUDIO_DEV_AUDIOCTL: error = audio_mixer_read(sc, uio, ioflag); break; default: error = ENXIO; } device_unref(&sc->dev); return error; } int audiowrite(dev_t dev, struct uio *uio, int ioflag) { struct audio_softc *sc; int error; sc = (struct audio_softc *)device_lookup(&audio_cd, AUDIO_UNIT(dev)); if (sc == NULL) return ENXIO; switch (AUDIO_DEV(dev)) { case AUDIO_DEV_AUDIO: error = audio_write(sc, uio, ioflag); break; case AUDIO_DEV_AUDIOCTL: error = ENODEV; break; default: error = ENXIO; } device_unref(&sc->dev); return error; } int audioioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { struct audio_softc *sc; int error; sc = (struct audio_softc *)device_lookup(&audio_cd, AUDIO_UNIT(dev)); if (sc == NULL) return ENXIO; switch (AUDIO_DEV(dev)) { case AUDIO_DEV_AUDIO: error = audio_ioctl(sc, cmd, addr); break; case AUDIO_DEV_AUDIOCTL: if (cmd == AUDIO_SETPAR && sc->mode != 0) { error = EBUSY; break; } if (cmd == AUDIO_START || cmd == AUDIO_STOP) { error = ENXIO; break; } if (cmd == AUDIO_MIXER_DEVINFO || cmd == AUDIO_MIXER_READ || cmd == AUDIO_MIXER_WRITE) error = audio_ioctl_mixer(sc, cmd, addr, p); else error = audio_ioctl(sc, cmd, addr); break; default: error = ENXIO; } device_unref(&sc->dev); return error; } int audiokqfilter(dev_t dev, struct knote *kn) { struct audio_softc *sc; struct klist *klist; int error; sc = (struct audio_softc *)device_lookup(&audio_cd, AUDIO_UNIT(dev)); if (sc == NULL) return ENXIO; error = 0; switch (AUDIO_DEV(dev)) { case AUDIO_DEV_AUDIO: switch (kn->kn_filter) { case EVFILT_READ: klist = &sc->rec.klist; kn->kn_fop = &audioread_filtops; break; case EVFILT_WRITE: klist = &sc->play.klist; kn->kn_fop = &audiowrite_filtops; break; default: error = EINVAL; goto done; } break; case AUDIO_DEV_AUDIOCTL: switch (kn->kn_filter) { case EVFILT_READ: klist = &sc->mix_klist; kn->kn_fop = &audioctlread_filtops; break; default: error = EINVAL; goto done; } break; } kn->kn_hook = sc; klist_insert(klist, kn); done: device_unref(&sc->dev); return error; } void filt_audiordetach(struct knote *kn) { struct audio_softc *sc = kn->kn_hook; klist_remove(&sc->rec.klist, kn); } int filt_audioread(struct knote *kn, long hint) { struct audio_softc *sc = kn->kn_hook; MUTEX_ASSERT_LOCKED(&audio_lock); return (sc->mode & AUMODE_RECORD) && (sc->rec.used > 0); } void filt_audiowdetach(struct knote *kn) { struct audio_softc *sc = kn->kn_hook; klist_remove(&sc->play.klist, kn); } int filt_audiowrite(struct knote *kn, long hint) { struct audio_softc *sc = kn->kn_hook; MUTEX_ASSERT_LOCKED(&audio_lock); return (sc->mode & AUMODE_PLAY) && (sc->play.used < sc->play.len); } void filt_audioctlrdetach(struct knote *kn) { struct audio_softc *sc = kn->kn_hook; klist_remove(&sc->mix_klist, kn); } int filt_audioctlread(struct knote *kn, long hint) { struct audio_softc *sc = kn->kn_hook; MUTEX_ASSERT_LOCKED(&audio_lock); return (sc->mix_isopen && sc->mix_pending); } int filt_audiomodify(struct kevent *kev, struct knote *kn) { int active; mtx_enter(&audio_lock); active = knote_modify(kev, kn); mtx_leave(&audio_lock); return active; } int filt_audioprocess(struct knote *kn, struct kevent *kev) { int active; mtx_enter(&audio_lock); active = knote_process(kn, kev); mtx_leave(&audio_lock); return active; } #if NWSKBD > 0 int wskbd_initmute(struct audio_softc *sc, struct mixer_devinfo *vol) { struct mixer_devinfo *mi; int index = -1; mi = malloc(sizeof(struct mixer_devinfo), M_TEMP, M_WAITOK); for (mi->index = vol->next; mi->index != -1; mi->index = mi->next) { if (sc->ops->query_devinfo(sc->arg, mi) != 0) break; if (strcmp(mi->label.name, AudioNmute) == 0) { index = mi->index; break; } } free(mi, M_TEMP, sizeof(struct mixer_devinfo)); return index; } int wskbd_initvol(struct audio_softc *sc, struct wskbd_vol *vol, char *cn, char *dn) { struct mixer_devinfo *dev, *cls; vol->val = vol->mute = -1; dev = malloc(sizeof(struct mixer_devinfo), M_TEMP, M_WAITOK); cls = malloc(sizeof(struct mixer_devinfo), M_TEMP, M_WAITOK); for (dev->index = 0; ; dev->index++) { if (sc->ops->query_devinfo(sc->arg, dev) != 0) break; if (dev->type != AUDIO_MIXER_VALUE) continue; cls->index = dev->mixer_class; if (sc->ops->query_devinfo(sc->arg, cls) != 0) continue; if (strcmp(cls->label.name, cn) == 0 && strcmp(dev->label.name, dn) == 0) { vol->val = dev->index; vol->nch = dev->un.v.num_channels; vol->step = dev->un.v.delta > 8 ? dev->un.v.delta : 8; vol->mute = wskbd_initmute(sc, dev); vol->val_pending = vol->mute_pending = 0; DPRINTF("%s: wskbd using %s.%s%s\n", DEVNAME(sc), cn, dn, vol->mute >= 0 ? ", mute control" : ""); break; } } free(cls, M_TEMP, sizeof(struct mixer_devinfo)); free(dev, M_TEMP, sizeof(struct mixer_devinfo)); return (vol->val != -1); } void wskbd_mixer_init(struct audio_softc *sc) { static struct { char *cn, *dn; } spkr_names[] = { {AudioCoutputs, AudioNmaster}, {AudioCinputs, AudioNdac}, {AudioCoutputs, AudioNdac}, {AudioCoutputs, AudioNoutput} }, mic_names[] = { {AudioCrecord, AudioNrecord}, {AudioCrecord, AudioNvolume}, {AudioCinputs, AudioNrecord}, {AudioCinputs, AudioNvolume}, {AudioCinputs, AudioNinput} }; int i; for (i = 0; i < sizeof(spkr_names) / sizeof(spkr_names[0]); i++) { if (wskbd_initvol(sc, &sc->spkr, spkr_names[i].cn, spkr_names[i].dn)) break; } for (i = 0; i < sizeof(mic_names) / sizeof(mic_names[0]); i++) { if (wskbd_initvol(sc, &sc->mic, mic_names[i].cn, mic_names[i].dn)) break; } task_set(&sc->wskbd_task, wskbd_mixer_cb, sc); } void wskbd_mixer_update(struct audio_softc *sc, struct wskbd_vol *vol) { struct mixer_ctrl ctrl; int val_pending, mute_pending, i, gain, error, s; s = spltty(); val_pending = vol->val_pending; vol->val_pending = 0; mute_pending = vol->mute_pending; vol->mute_pending = 0; splx(s); if (sc->ops == NULL) return; if (vol->mute >= 0 && mute_pending) { ctrl.dev = vol->mute; ctrl.type = AUDIO_MIXER_ENUM; error = sc->ops->get_port(sc->arg, &ctrl); if (error) { DPRINTF("%s: get mute err = %d\n", DEVNAME(sc), error); return; } switch (mute_pending) { case WSKBD_MUTE_TOGGLE: ctrl.un.ord = !ctrl.un.ord; break; case WSKBD_MUTE_DISABLE: ctrl.un.ord = 0; break; case WSKBD_MUTE_ENABLE: ctrl.un.ord = 1; break; } DPRINTFN(1, "%s: wskbd mute setting to %d\n", DEVNAME(sc), ctrl.un.ord); error = sc->ops->set_port(sc->arg, &ctrl); if (error) { DPRINTF("%s: set mute err = %d\n", DEVNAME(sc), error); return; } audio_event(sc, vol->mute); } if (vol->val >= 0 && val_pending) { ctrl.dev = vol->val; ctrl.type = AUDIO_MIXER_VALUE; ctrl.un.value.num_channels = vol->nch; error = sc->ops->get_port(sc->arg, &ctrl); if (error) { DPRINTF("%s: get mute err = %d\n", DEVNAME(sc), error); return; } for (i = 0; i < vol->nch; i++) { gain = ctrl.un.value.level[i] + vol->step * val_pending; if (gain > AUDIO_MAX_GAIN) gain = AUDIO_MAX_GAIN; else if (gain < AUDIO_MIN_GAIN) gain = AUDIO_MIN_GAIN; ctrl.un.value.level[i] = gain; DPRINTFN(1, "%s: wskbd level %d set to %d\n", DEVNAME(sc), i, gain); } error = sc->ops->set_port(sc->arg, &ctrl); if (error) { DPRINTF("%s: set vol err = %d\n", DEVNAME(sc), error); return; } audio_event(sc, vol->val); } } void wskbd_mixer_cb(void *arg) { struct audio_softc *sc = arg; wskbd_mixer_update(sc, &sc->spkr); wskbd_mixer_update(sc, &sc->mic); device_unref(&sc->dev); } int wskbd_set_mixermute(long mute, long out) { struct audio_softc *sc; struct wskbd_vol *vol; sc = (struct audio_softc *)device_lookup(&audio_cd, 0); if (sc == NULL) return ENODEV; vol = out ? &sc->spkr : &sc->mic; vol->mute_pending = mute ? WSKBD_MUTE_ENABLE : WSKBD_MUTE_DISABLE; if (!task_add(systq, &sc->wskbd_task)) device_unref(&sc->dev); return 0; } /* * Adjust the volume of the audio device associated with the given cookie. * Otherwise, fallback to audio0. */ int wskbd_set_mixervolume_dev(void *cookie, long dir, long out) { int unit = 0; int i; for (i = 0; i < audio_cd.cd_ndevs; i++) { struct audio_softc *sc; sc = (struct audio_softc *)device_lookup(&audio_cd, i); if (sc == NULL) continue; if (sc->cookie != cookie) { device_unref(&sc->dev); continue; } device_unref(&sc->dev); unit = i; break; } return wskbd_set_mixervolume_unit(unit, dir, out); } int wskbd_set_mixervolume(long dir, long out) { return wskbd_set_mixervolume_unit(0, dir, out); } int wskbd_set_mixervolume_unit(int unit, long dir, long out) { struct audio_softc *sc; struct wskbd_vol *vol; sc = (struct audio_softc *)device_lookup(&audio_cd, unit); if (sc == NULL) return ENODEV; vol = out ? &sc->spkr : &sc->mic; if (dir == 0) vol->mute_pending ^= WSKBD_MUTE_TOGGLE; else vol->val_pending += dir; if (!task_add(systq, &sc->wskbd_task)) device_unref(&sc->dev); return 0; } #endif /* NWSKBD > 0 */
1 1 2 2 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 /* $OpenBSD: bio.c,v 1.19 2023/11/15 23:57:45 dlg Exp $ */ /* * Copyright (c) 2002 Niklas Hallqvist. All rights reserved. * Copyright (c) 2012 Joel Sing <jsing@openbsd.org>. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* A device controller ioctl tunnelling device. */ #include <sys/param.h> #include <sys/device.h> #include <sys/ioctl.h> #include <sys/malloc.h> #include <sys/tree.h> #include <sys/systm.h> #include <dev/biovar.h> struct bio_mapping { RBT_ENTRY(bio_mapping) bm_link; uintptr_t bm_cookie; struct device *bm_dev; int (*bm_ioctl)(struct device *, u_long, caddr_t); }; RBT_HEAD(bio_mappings, bio_mapping); static inline int bio_cookie_cmp(const struct bio_mapping *a, const struct bio_mapping *b) { if (a->bm_cookie < b->bm_cookie) return (1); if (a->bm_cookie > b->bm_cookie) return (-1); return (0); } RBT_PROTOTYPE(bio_mappings, bio_mapping, bm_link, bio_cookie_cmp); struct bio_mappings bios = RBT_INITIALIZER(); void bioattach(int); int bioclose(dev_t, int, int, struct proc *); int bioioctl(dev_t, u_long, caddr_t, int, struct proc *); int bioopen(dev_t, int, int, struct proc *); int bio_delegate_ioctl(struct bio_mapping *, u_long, caddr_t); struct bio_mapping *bio_lookup(char *); struct bio_mapping *bio_validate(void *); void bioattach(int nunits) { } int bioopen(dev_t dev, int flags, int mode, struct proc *p) { return (0); } int bioclose(dev_t dev, int flags, int mode, struct proc *p) { return (0); } int bioioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { struct bio_mapping *bm; struct bio_locate *locate; struct bio *bio; char name[16]; int error; switch (cmd) { case BIOCLOCATE: locate = (struct bio_locate *)addr; error = copyinstr(locate->bl_name, name, sizeof name, NULL); if (error != 0) return (error); bm = bio_lookup(name); if (bm == NULL) return (ENOENT); locate->bl_bio.bio_cookie = (void *)bm->bm_cookie; break; default: bio = (struct bio *)addr; bm = bio_validate(bio->bio_cookie); if (bm == NULL) return (ENOENT); error = bio_delegate_ioctl(bm, cmd, addr); break; } return (0); } int bio_register(struct device *dev, int (*ioctl)(struct device *, u_long, caddr_t)) { struct bio_mapping *bm; bm = malloc(sizeof *bm, M_DEVBUF, M_NOWAIT); if (bm == NULL) return (ENOMEM); bm->bm_dev = dev; bm->bm_ioctl = ioctl; do { bm->bm_cookie = arc4random(); /* lets hope we don't have 4 billion bio_registers */ } while (RBT_INSERT(bio_mappings, &bios, bm) != NULL); return (0); } void bio_unregister(struct device *dev) { struct bio_mapping *bm, *next; RBT_FOREACH_SAFE(bm, bio_mappings, &bios, next) { if (dev == bm->bm_dev) { RBT_REMOVE(bio_mappings, &bios, bm); free(bm, M_DEVBUF, sizeof(*bm)); } } } struct bio_mapping * bio_lookup(char *name) { struct bio_mapping *bm; RBT_FOREACH(bm, bio_mappings, &bios) { if (strcmp(name, bm->bm_dev->dv_xname) == 0) return (bm); } return (NULL); } struct bio_mapping * bio_validate(void *cookie) { struct bio_mapping key = { .bm_cookie = (uintptr_t)cookie }; return (RBT_FIND(bio_mappings, &bios, &key)); } int bio_delegate_ioctl(struct bio_mapping *bm, u_long cmd, caddr_t addr) { return (bm->bm_ioctl(bm->bm_dev, cmd, addr)); } void bio_info(struct bio_status *bs, int print, const char *fmt, ...) { va_list ap; va_start(ap, fmt); bio_status(bs, print, BIO_MSG_INFO, fmt, &ap); va_end(ap); } void bio_warn(struct bio_status *bs, int print, const char *fmt, ...) { va_list ap; va_start(ap, fmt); bio_status(bs, print, BIO_MSG_WARN, fmt, &ap); va_end(ap); } void bio_error(struct bio_status *bs, int print, const char *fmt, ...) { va_list ap; va_start(ap, fmt); bio_status(bs, print, BIO_MSG_ERROR, fmt, &ap); va_end(ap); } void bio_status_init(struct bio_status *bs, struct device *dv) { bzero(bs, sizeof(struct bio_status)); bs->bs_status = BIO_STATUS_UNKNOWN; strlcpy(bs->bs_controller, dv->dv_xname, sizeof(bs->bs_controller)); } void bio_status(struct bio_status *bs, int print, int msg_type, const char *fmt, va_list *ap) { int idx; if (bs->bs_msg_count >= BIO_MSG_COUNT) { printf("%s: insufficient message buffers\n", bs->bs_controller); return; } idx = bs->bs_msg_count++; bs->bs_msgs[idx].bm_type = msg_type; vsnprintf(bs->bs_msgs[idx].bm_msg, BIO_MSG_LEN, fmt, *ap); if (print) printf("%s: %s\n", bs->bs_controller, bs->bs_msgs[idx].bm_msg); } RBT_GENERATE(bio_mappings, bio_mapping, bm_link, bio_cookie_cmp);
2 3 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 /* * Created: Fri Jan 19 10:48:35 2001 by faith@acm.org * * Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Author Rickard E. (Rik) Faith <faith@valinux.com> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include <sys/param.h> #include <sys/fcntl.h> #include <sys/specdev.h> #include <sys/vnode.h> #include <machine/bus.h> #ifdef __HAVE_ACPI #include <dev/acpi/acpidev.h> #include <dev/acpi/acpivar.h> #include <dev/acpi/dsdt.h> #endif #include <linux/debugfs.h> #include <linux/fs.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/mount.h> #include <linux/pseudo_fs.h> #include <linux/slab.h> #include <linux/srcu.h> #include <drm/drm_accel.h> #include <drm/drm_cache.h> #include <drm/drm_client.h> #include <drm/drm_color_mgmt.h> #include <drm/drm_drv.h> #include <drm/drm_file.h> #include <drm/drm_managed.h> #include <drm/drm_mode_object.h> #include <drm/drm_print.h> #include <drm/drm_privacy_screen_machine.h> #include <drm/drm_gem.h> #include "drm_crtc_internal.h" #include "drm_internal.h" #include "drm_legacy.h" MODULE_AUTHOR("Gareth Hughes, Leif Delgass, José Fonseca, Jon Smirl"); MODULE_DESCRIPTION("DRM shared core routines"); MODULE_LICENSE("GPL and additional rights"); static DEFINE_SPINLOCK(drm_minor_lock); static struct idr drm_minors_idr; /* * If the drm core fails to init for whatever reason, * we should prevent any drivers from registering with it. * It's best to check this at drm_dev_init(), as some drivers * prefer to embed struct drm_device into their own device * structure and call drm_dev_init() themselves. */ static bool drm_core_init_complete; static struct dentry *drm_debugfs_root; #ifdef notyet DEFINE_STATIC_SRCU(drm_unplug_srcu); #endif /* * Some functions are only called once on init regardless of how many times * drm attaches. In linux this is handled via module_init()/module_exit() */ int drm_refcnt; struct drm_softc { struct device sc_dev; struct drm_device *sc_drm; int sc_allocated; }; struct drm_attach_args { struct drm_device *drm; const struct drm_driver *driver; char *busid; bus_dma_tag_t dmat; bus_space_tag_t bst; size_t busid_len; int is_agp; struct pci_attach_args *pa; int primary; }; void drm_linux_init(void); void drm_linux_exit(void); int drm_linux_acpi_notify(struct aml_node *, int, void *); int drm_dequeue_event(struct drm_device *, struct drm_file *, size_t, struct drm_pending_event **); int drmprint(void *, const char *); int drmsubmatch(struct device *, void *, void *); const struct pci_device_id * drm_find_description(int, int, const struct pci_device_id *); int drm_file_cmp(struct drm_file *, struct drm_file *); SPLAY_PROTOTYPE(drm_file_tree, drm_file, link, drm_file_cmp); #define DRMDEVCF_PRIMARY 0 #define drmdevcf_primary cf_loc[DRMDEVCF_PRIMARY] /* spec'd as primary? */ #define DRMDEVCF_PRIMARY_UNK -1 /* * DRM Minors * A DRM device can provide several char-dev interfaces on the DRM-Major. Each * of them is represented by a drm_minor object. Depending on the capabilities * of the device-driver, different interfaces are registered. * * Minors can be accessed via dev->$minor_name. This pointer is either * NULL or a valid drm_minor pointer and stays valid as long as the device is * valid. This means, DRM minors have the same life-time as the underlying * device. However, this doesn't mean that the minor is active. Minors are * registered and unregistered dynamically according to device-state. */ static struct drm_minor **drm_minor_get_slot(struct drm_device *dev, enum drm_minor_type type) { switch (type) { case DRM_MINOR_PRIMARY: return &dev->primary; case DRM_MINOR_RENDER: return &dev->render; case DRM_MINOR_ACCEL: return &dev->accel; default: BUG(); } } static void drm_minor_alloc_release(struct drm_device *dev, void *data) { struct drm_minor *minor = data; unsigned long flags; WARN_ON(dev != minor->dev); #ifdef __linux__ put_device(minor->kdev); #endif if (minor->type == DRM_MINOR_ACCEL) { accel_minor_remove(minor->index); } else { spin_lock_irqsave(&drm_minor_lock, flags); idr_remove(&drm_minors_idr, minor->index); spin_unlock_irqrestore(&drm_minor_lock, flags); } } static int drm_minor_alloc(struct drm_device *dev, enum drm_minor_type type) { struct drm_minor *minor; unsigned long flags; int r; minor = drmm_kzalloc(dev, sizeof(*minor), GFP_KERNEL); if (!minor) return -ENOMEM; minor->type = type; minor->dev = dev; idr_preload(GFP_KERNEL); if (type == DRM_MINOR_ACCEL) { r = accel_minor_alloc(); } else { spin_lock_irqsave(&drm_minor_lock, flags); r = idr_alloc(&drm_minors_idr, NULL, 64 * type, 64 * (type + 1), GFP_NOWAIT); spin_unlock_irqrestore(&drm_minor_lock, flags); } idr_preload_end(); if (r < 0) return r; minor->index = r; r = drmm_add_action_or_reset(dev, drm_minor_alloc_release, minor); if (r) return r; #ifdef __linux__ minor->kdev = drm_sysfs_minor_alloc(minor); if (IS_ERR(minor->kdev)) return PTR_ERR(minor->kdev); #endif *drm_minor_get_slot(dev, type) = minor; return 0; } static int drm_minor_register(struct drm_device *dev, enum drm_minor_type type) { struct drm_minor *minor; unsigned long flags; #ifdef __linux__ int ret; #endif DRM_DEBUG("\n"); minor = *drm_minor_get_slot(dev, type); if (!minor) return 0; #ifdef __linux__ if (minor->type == DRM_MINOR_ACCEL) { accel_debugfs_init(minor, minor->index); } else { ret = drm_debugfs_init(minor, minor->index, drm_debugfs_root); if (ret) { DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n"); goto err_debugfs; } } ret = device_add(minor->kdev); if (ret) goto err_debugfs; #else drm_debugfs_root = NULL; #endif /* replace NULL with @minor so lookups will succeed from now on */ if (minor->type == DRM_MINOR_ACCEL) { accel_minor_replace(minor, minor->index); } else { spin_lock_irqsave(&drm_minor_lock, flags); idr_replace(&drm_minors_idr, minor, minor->index); spin_unlock_irqrestore(&drm_minor_lock, flags); } DRM_DEBUG("new minor registered %d\n", minor->index); return 0; #ifdef __linux__ err_debugfs: drm_debugfs_cleanup(minor); return ret; #endif } static void drm_minor_unregister(struct drm_device *dev, enum drm_minor_type type) { struct drm_minor *minor; unsigned long flags; minor = *drm_minor_get_slot(dev, type); #ifdef __linux__ if (!minor || !device_is_registered(minor->kdev)) #else if (!minor) #endif return; /* replace @minor with NULL so lookups will fail from now on */ if (minor->type == DRM_MINOR_ACCEL) { accel_minor_replace(NULL, minor->index); } else { spin_lock_irqsave(&drm_minor_lock, flags); idr_replace(&drm_minors_idr, NULL, minor->index); spin_unlock_irqrestore(&drm_minor_lock, flags); } #ifdef __linux__ device_del(minor->kdev); #endif dev_set_drvdata(minor->kdev, NULL); /* safety belt */ drm_debugfs_cleanup(minor); } /* * Looks up the given minor-ID and returns the respective DRM-minor object. The * refence-count of the underlying device is increased so you must release this * object with drm_minor_release(). * * As long as you hold this minor, it is guaranteed that the object and the * minor->dev pointer will stay valid! However, the device may get unplugged and * unregistered while you hold the minor. */ struct drm_minor *drm_minor_acquire(unsigned int minor_id) { struct drm_minor *minor; unsigned long flags; spin_lock_irqsave(&drm_minor_lock, flags); minor = idr_find(&drm_minors_idr, minor_id); if (minor) drm_dev_get(minor->dev); spin_unlock_irqrestore(&drm_minor_lock, flags); if (!minor) { return ERR_PTR(-ENODEV); } else if (drm_dev_is_unplugged(minor->dev)) { drm_dev_put(minor->dev); return ERR_PTR(-ENODEV); } return minor; } void drm_minor_release(struct drm_minor *minor) { drm_dev_put(minor->dev); } /** * DOC: driver instance overview * * A device instance for a drm driver is represented by &struct drm_device. This * is allocated and initialized with devm_drm_dev_alloc(), usually from * bus-specific ->probe() callbacks implemented by the driver. The driver then * needs to initialize all the various subsystems for the drm device like memory * management, vblank handling, modesetting support and initial output * configuration plus obviously initialize all the corresponding hardware bits. * Finally when everything is up and running and ready for userspace the device * instance can be published using drm_dev_register(). * * There is also deprecated support for initializing device instances using * bus-specific helpers and the &drm_driver.load callback. But due to * backwards-compatibility needs the device instance have to be published too * early, which requires unpretty global locking to make safe and is therefore * only support for existing drivers not yet converted to the new scheme. * * When cleaning up a device instance everything needs to be done in reverse: * First unpublish the device instance with drm_dev_unregister(). Then clean up * any other resources allocated at device initialization and drop the driver's * reference to &drm_device using drm_dev_put(). * * Note that any allocation or resource which is visible to userspace must be * released only when the final drm_dev_put() is called, and not when the * driver is unbound from the underlying physical struct &device. Best to use * &drm_device managed resources with drmm_add_action(), drmm_kmalloc() and * related functions. * * devres managed resources like devm_kmalloc() can only be used for resources * directly related to the underlying hardware device, and only used in code * paths fully protected by drm_dev_enter() and drm_dev_exit(). * * Display driver example * ~~~~~~~~~~~~~~~~~~~~~~ * * The following example shows a typical structure of a DRM display driver. * The example focus on the probe() function and the other functions that is * almost always present and serves as a demonstration of devm_drm_dev_alloc(). * * .. code-block:: c * * struct driver_device { * struct drm_device drm; * void *userspace_facing; * struct clk *pclk; * }; * * static const struct drm_driver driver_drm_driver = { * [...] * }; * * static int driver_probe(struct platform_device *pdev) * { * struct driver_device *priv; * struct drm_device *drm; * int ret; * * priv = devm_drm_dev_alloc(&pdev->dev, &driver_drm_driver, * struct driver_device, drm); * if (IS_ERR(priv)) * return PTR_ERR(priv); * drm = &priv->drm; * * ret = drmm_mode_config_init(drm); * if (ret) * return ret; * * priv->userspace_facing = drmm_kzalloc(..., GFP_KERNEL); * if (!priv->userspace_facing) * return -ENOMEM; * * priv->pclk = devm_clk_get(dev, "PCLK"); * if (IS_ERR(priv->pclk)) * return PTR_ERR(priv->pclk); * * // Further setup, display pipeline etc * * platform_set_drvdata(pdev, drm); * * drm_mode_config_reset(drm); * * ret = drm_dev_register(drm); * if (ret) * return ret; * * drm_fbdev_generic_setup(drm, 32); * * return 0; * } * * // This function is called before the devm_ resources are released * static int driver_remove(struct platform_device *pdev) * { * struct drm_device *drm = platform_get_drvdata(pdev); * * drm_dev_unregister(drm); * drm_atomic_helper_shutdown(drm) * * return 0; * } * * // This function is called on kernel restart and shutdown * static void driver_shutdown(struct platform_device *pdev) * { * drm_atomic_helper_shutdown(platform_get_drvdata(pdev)); * } * * static int __maybe_unused driver_pm_suspend(struct device *dev) * { * return drm_mode_config_helper_suspend(dev_get_drvdata(dev)); * } * * static int __maybe_unused driver_pm_resume(struct device *dev) * { * drm_mode_config_helper_resume(dev_get_drvdata(dev)); * * return 0; * } * * static const struct dev_pm_ops driver_pm_ops = { * SET_SYSTEM_SLEEP_PM_OPS(driver_pm_suspend, driver_pm_resume) * }; * * static struct platform_driver driver_driver = { * .driver = { * [...] * .pm = &driver_pm_ops, * }, * .probe = driver_probe, * .remove = driver_remove, * .shutdown = driver_shutdown, * }; * module_platform_driver(driver_driver); * * Drivers that want to support device unplugging (USB, DT overlay unload) should * use drm_dev_unplug() instead of drm_dev_unregister(). The driver must protect * regions that is accessing device resources to prevent use after they're * released. This is done using drm_dev_enter() and drm_dev_exit(). There is one * shortcoming however, drm_dev_unplug() marks the drm_device as unplugged before * drm_atomic_helper_shutdown() is called. This means that if the disable code * paths are protected, they will not run on regular driver module unload, * possibly leaving the hardware enabled. */ /** * drm_put_dev - Unregister and release a DRM device * @dev: DRM device * * Called at module unload time or when a PCI device is unplugged. * * Cleans up all DRM device, calling drm_lastclose(). * * Note: Use of this function is deprecated. It will eventually go away * completely. Please use drm_dev_unregister() and drm_dev_put() explicitly * instead to make sure that the device isn't userspace accessible any more * while teardown is in progress, ensuring that userspace can't access an * inconsistent state. */ void drm_put_dev(struct drm_device *dev) { DRM_DEBUG("\n"); if (!dev) { DRM_ERROR("cleanup called no dev\n"); return; } drm_dev_unregister(dev); drm_dev_put(dev); } EXPORT_SYMBOL(drm_put_dev); /** * drm_dev_enter - Enter device critical section * @dev: DRM device * @idx: Pointer to index that will be passed to the matching drm_dev_exit() * * This function marks and protects the beginning of a section that should not * be entered after the device has been unplugged. The section end is marked * with drm_dev_exit(). Calls to this function can be nested. * * Returns: * True if it is OK to enter the section, false otherwise. */ bool drm_dev_enter(struct drm_device *dev, int *idx) { #ifdef notyet *idx = srcu_read_lock(&drm_unplug_srcu); if (dev->unplugged) { srcu_read_unlock(&drm_unplug_srcu, *idx); return false; } #endif return true; } EXPORT_SYMBOL(drm_dev_enter); /** * drm_dev_exit - Exit device critical section * @idx: index returned from drm_dev_enter() * * This function marks the end of a section that should not be entered after * the device has been unplugged. */ void drm_dev_exit(int idx) { #ifdef notyet srcu_read_unlock(&drm_unplug_srcu, idx); #endif } EXPORT_SYMBOL(drm_dev_exit); /** * drm_dev_unplug - unplug a DRM device * @dev: DRM device * * This unplugs a hotpluggable DRM device, which makes it inaccessible to * userspace operations. Entry-points can use drm_dev_enter() and * drm_dev_exit() to protect device resources in a race free manner. This * essentially unregisters the device like drm_dev_unregister(), but can be * called while there are still open users of @dev. */ void drm_dev_unplug(struct drm_device *dev) { STUB(); #ifdef notyet /* * After synchronizing any critical read section is guaranteed to see * the new value of ->unplugged, and any critical section which might * still have seen the old value of ->unplugged is guaranteed to have * finished. */ dev->unplugged = true; synchronize_srcu(&drm_unplug_srcu); drm_dev_unregister(dev); /* Clear all CPU mappings pointing to this device */ unmap_mapping_range(dev->anon_inode->i_mapping, 0, 0, 1); #endif } EXPORT_SYMBOL(drm_dev_unplug); #ifdef __linux__ /* * DRM internal mount * We want to be able to allocate our own "struct address_space" to control * memory-mappings in VRAM (or stolen RAM, ...). However, core MM does not allow * stand-alone address_space objects, so we need an underlying inode. As there * is no way to allocate an independent inode easily, we need a fake internal * VFS mount-point. * * The drm_fs_inode_new() function allocates a new inode, drm_fs_inode_free() * frees it again. You are allowed to use iget() and iput() to get references to * the inode. But each drm_fs_inode_new() call must be paired with exactly one * drm_fs_inode_free() call (which does not have to be the last iput()). * We use drm_fs_inode_*() to manage our internal VFS mount-point and share it * between multiple inode-users. You could, technically, call * iget() + drm_fs_inode_free() directly after alloc and sometime later do an * iput(), but this way you'd end up with a new vfsmount for each inode. */ static int drm_fs_cnt; static struct vfsmount *drm_fs_mnt; static int drm_fs_init_fs_context(struct fs_context *fc) { return init_pseudo(fc, 0x010203ff) ? 0 : -ENOMEM; } static struct file_system_type drm_fs_type = { .name = "drm", .owner = THIS_MODULE, .init_fs_context = drm_fs_init_fs_context, .kill_sb = kill_anon_super, }; static struct inode *drm_fs_inode_new(void) { struct inode *inode; int r; r = simple_pin_fs(&drm_fs_type, &drm_fs_mnt, &drm_fs_cnt); if (r < 0) { DRM_ERROR("Cannot mount pseudo fs: %d\n", r); return ERR_PTR(r); } inode = alloc_anon_inode(drm_fs_mnt->mnt_sb); if (IS_ERR(inode)) simple_release_fs(&drm_fs_mnt, &drm_fs_cnt); return inode; } static void drm_fs_inode_free(struct inode *inode) { if (inode) { iput(inode); simple_release_fs(&drm_fs_mnt, &drm_fs_cnt); } } #endif /* __linux__ */ /** * DOC: component helper usage recommendations * * DRM drivers that drive hardware where a logical device consists of a pile of * independent hardware blocks are recommended to use the :ref:`component helper * library<component>`. For consistency and better options for code reuse the * following guidelines apply: * * - The entire device initialization procedure should be run from the * &component_master_ops.master_bind callback, starting with * devm_drm_dev_alloc(), then binding all components with * component_bind_all() and finishing with drm_dev_register(). * * - The opaque pointer passed to all components through component_bind_all() * should point at &struct drm_device of the device instance, not some driver * specific private structure. * * - The component helper fills the niche where further standardization of * interfaces is not practical. When there already is, or will be, a * standardized interface like &drm_bridge or &drm_panel, providing its own * functions to find such components at driver load time, like * drm_of_find_panel_or_bridge(), then the component helper should not be * used. */ static void drm_dev_init_release(struct drm_device *dev, void *res) { drm_legacy_ctxbitmap_cleanup(dev); drm_legacy_remove_map_hash(dev); #ifdef __linux__ drm_fs_inode_free(dev->anon_inode); put_device(dev->dev); #endif /* Prevent use-after-free in drm_managed_release when debugging is * enabled. Slightly awkward, but can't really be helped. */ dev->dev = NULL; mutex_destroy(&dev->master_mutex); mutex_destroy(&dev->clientlist_mutex); mutex_destroy(&dev->filelist_mutex); mutex_destroy(&dev->struct_mutex); mutex_destroy(&dev->debugfs_mutex); drm_legacy_destroy_members(dev); } #ifdef notyet static int drm_dev_init(struct drm_device *dev, const struct drm_driver *driver, struct device *parent) { struct inode *inode; int ret; if (!drm_core_init_complete) { DRM_ERROR("DRM core is not initialized\n"); return -ENODEV; } if (WARN_ON(!parent)) return -EINVAL; kref_init(&dev->ref); dev->dev = get_device(parent); dev->driver = driver; INIT_LIST_HEAD(&dev->managed.resources); spin_lock_init(&dev->managed.lock); /* no per-device feature limits by default */ dev->driver_features = ~0u; if (drm_core_check_feature(dev, DRIVER_COMPUTE_ACCEL) && (drm_core_check_feature(dev, DRIVER_RENDER) || drm_core_check_feature(dev, DRIVER_MODESET))) { DRM_ERROR("DRM driver can't be both a compute acceleration and graphics driver\n"); return -EINVAL; } drm_legacy_init_members(dev); INIT_LIST_HEAD(&dev->filelist); INIT_LIST_HEAD(&dev->filelist_internal); INIT_LIST_HEAD(&dev->clientlist); INIT_LIST_HEAD(&dev->vblank_event_list); INIT_LIST_HEAD(&dev->debugfs_list); spin_lock_init(&dev->event_lock); mutex_init(&dev->struct_mutex); mutex_init(&dev->filelist_mutex); mutex_init(&dev->clientlist_mutex); mutex_init(&dev->master_mutex); mutex_init(&dev->debugfs_mutex); ret = drmm_add_action_or_reset(dev, drm_dev_init_release, NULL); if (ret) return ret; inode = drm_fs_inode_new(); if (IS_ERR(inode)) { ret = PTR_ERR(inode); DRM_ERROR("Cannot allocate anonymous inode: %d\n", ret); goto err; } dev->anon_inode = inode; if (drm_core_check_feature(dev, DRIVER_COMPUTE_ACCEL)) { ret = drm_minor_alloc(dev, DRM_MINOR_ACCEL); if (ret) goto err; } else { if (drm_core_check_feature(dev, DRIVER_RENDER)) { ret = drm_minor_alloc(dev, DRM_MINOR_RENDER); if (ret) goto err; } ret = drm_minor_alloc(dev, DRM_MINOR_PRIMARY); if (ret) goto err; } ret = drm_legacy_create_map_hash(dev); if (ret) goto err; drm_legacy_ctxbitmap_init(dev); if (drm_core_check_feature(dev, DRIVER_GEM)) { ret = drm_gem_init(dev); if (ret) { DRM_ERROR("Cannot initialize graphics execution manager (GEM)\n"); goto err; } } dev->unique = drmm_kstrdup(dev, dev_name(parent), GFP_KERNEL); if (!dev->unique) { ret = -ENOMEM; goto err; } return 0; err: drm_managed_release(dev); return ret; } static void devm_drm_dev_init_release(void *data) { drm_dev_put(data); } static int devm_drm_dev_init(struct device *parent, struct drm_device *dev, const struct drm_driver *driver) { int ret; ret = drm_dev_init(dev, driver, parent); if (ret) return ret; return devm_add_action_or_reset(parent, devm_drm_dev_init_release, dev); } #endif void *__devm_drm_dev_alloc(struct device *parent, const struct drm_driver *driver, size_t size, size_t offset) { void *container; struct drm_device *drm; #ifdef notyet int ret; #endif container = kzalloc(size, GFP_KERNEL); if (!container) return ERR_PTR(-ENOMEM); drm = container + offset; #ifdef notyet ret = devm_drm_dev_init(parent, drm, driver); if (ret) { kfree(container); return ERR_PTR(ret); } drmm_add_final_kfree(drm, container); #endif return container; } EXPORT_SYMBOL(__devm_drm_dev_alloc); #ifdef notyet /** * drm_dev_alloc - Allocate new DRM device * @driver: DRM driver to allocate device for * @parent: Parent device object * * This is the deprecated version of devm_drm_dev_alloc(), which does not support * subclassing through embedding the struct &drm_device in a driver private * structure, and which does not support automatic cleanup through devres. * * RETURNS: * Pointer to new DRM device, or ERR_PTR on failure. */ struct drm_device *drm_dev_alloc(const struct drm_driver *driver, struct device *parent) { struct drm_device *dev; int ret; dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return ERR_PTR(-ENOMEM); ret = drm_dev_init(dev, driver, parent); if (ret) { kfree(dev); return ERR_PTR(ret); } drmm_add_final_kfree(dev, dev); return dev; } EXPORT_SYMBOL(drm_dev_alloc); #endif static void drm_dev_release(struct kref *ref) { struct drm_device *dev = container_of(ref, struct drm_device, ref); if (dev->driver->release) dev->driver->release(dev); drm_managed_release(dev); kfree(dev->managed.final_kfree); } /** * drm_dev_get - Take reference of a DRM device * @dev: device to take reference of or NULL * * This increases the ref-count of @dev by one. You *must* already own a * reference when calling this. Use drm_dev_put() to drop this reference * again. * * This function never fails. However, this function does not provide *any* * guarantee whether the device is alive or running. It only provides a * reference to the object and the memory associated with it. */ void drm_dev_get(struct drm_device *dev) { if (dev) kref_get(&dev->ref); } EXPORT_SYMBOL(drm_dev_get); /** * drm_dev_put - Drop reference of a DRM device * @dev: device to drop reference of or NULL * * This decreases the ref-count of @dev by one. The device is destroyed if the * ref-count drops to zero. */ void drm_dev_put(struct drm_device *dev) { if (dev) kref_put(&dev->ref, drm_dev_release); } EXPORT_SYMBOL(drm_dev_put); static int create_compat_control_link(struct drm_device *dev) { struct drm_minor *minor; char *name; int ret; if (!drm_core_check_feature(dev, DRIVER_MODESET)) return 0; minor = *drm_minor_get_slot(dev, DRM_MINOR_PRIMARY); if (!minor) return 0; /* * Some existing userspace out there uses the existing of the controlD* * sysfs files to figure out whether it's a modeset driver. It only does * readdir, hence a symlink is sufficient (and the least confusing * option). Otherwise controlD* is entirely unused. * * Old controlD chardev have been allocated in the range * 64-127. */ name = kasprintf(GFP_KERNEL, "controlD%d", minor->index + 64); if (!name) return -ENOMEM; ret = sysfs_create_link(minor->kdev->kobj.parent, &minor->kdev->kobj, name); kfree(name); return ret; } static void remove_compat_control_link(struct drm_device *dev) { struct drm_minor *minor; char *name; if (!drm_core_check_feature(dev, DRIVER_MODESET)) return; minor = *drm_minor_get_slot(dev, DRM_MINOR_PRIMARY); if (!minor) return; name = kasprintf(GFP_KERNEL, "controlD%d", minor->index + 64); if (!name) return; sysfs_remove_link(minor->kdev->kobj.parent, name); kfree(name); } /** * drm_dev_register - Register DRM device * @dev: Device to register * @flags: Flags passed to the driver's .load() function * * Register the DRM device @dev with the system, advertise device to user-space * and start normal device operation. @dev must be initialized via drm_dev_init() * previously. * * Never call this twice on any device! * * NOTE: To ensure backward compatibility with existing drivers method this * function calls the &drm_driver.load method after registering the device * nodes, creating race conditions. Usage of the &drm_driver.load methods is * therefore deprecated, drivers must perform all initialization before calling * drm_dev_register(). * * RETURNS: * 0 on success, negative error code on failure. */ int drm_dev_register(struct drm_device *dev, unsigned long flags) { const struct drm_driver *driver = dev->driver; int ret; if (!driver->load) drm_mode_config_validate(dev); WARN_ON(!dev->managed.final_kfree); if (drm_dev_needs_global_mutex(dev)) mutex_lock(&drm_global_mutex); ret = drm_minor_register(dev, DRM_MINOR_RENDER); if (ret) goto err_minors; ret = drm_minor_register(dev, DRM_MINOR_PRIMARY); if (ret) goto err_minors; ret = drm_minor_register(dev, DRM_MINOR_ACCEL); if (ret) goto err_minors; ret = create_compat_control_link(dev); if (ret) goto err_minors; dev->registered = true; if (driver->load) { ret = driver->load(dev, flags); if (ret) goto err_minors; } if (drm_core_check_feature(dev, DRIVER_MODESET)) { ret = drm_modeset_register_all(dev); if (ret) goto err_unload; } DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", driver->name, driver->major, driver->minor, driver->patchlevel, driver->date, dev->dev ? dev_name(dev->dev) : "virtual device", dev->primary ? dev->primary->index : dev->accel->index); goto out_unlock; err_unload: if (dev->driver->unload) dev->driver->unload(dev); err_minors: remove_compat_control_link(dev); drm_minor_unregister(dev, DRM_MINOR_ACCEL); drm_minor_unregister(dev, DRM_MINOR_PRIMARY); drm_minor_unregister(dev, DRM_MINOR_RENDER); out_unlock: if (drm_dev_needs_global_mutex(dev)) mutex_unlock(&drm_global_mutex); return ret; } EXPORT_SYMBOL(drm_dev_register); /** * drm_dev_unregister - Unregister DRM device * @dev: Device to unregister * * Unregister the DRM device from the system. This does the reverse of * drm_dev_register() but does not deallocate the device. The caller must call * drm_dev_put() to drop their final reference, unless it is managed with devres * (as devices allocated with devm_drm_dev_alloc() are), in which case there is * already an unwind action registered. * * A special form of unregistering for hotpluggable devices is drm_dev_unplug(), * which can be called while there are still open users of @dev. * * This should be called first in the device teardown code to make sure * userspace can't access the device instance any more. */ void drm_dev_unregister(struct drm_device *dev) { if (drm_core_check_feature(dev, DRIVER_LEGACY)) drm_lastclose(dev); dev->registered = false; drm_client_dev_unregister(dev); if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_modeset_unregister_all(dev); if (dev->driver->unload) dev->driver->unload(dev); drm_legacy_pci_agp_destroy(dev); drm_legacy_rmmaps(dev); remove_compat_control_link(dev); drm_minor_unregister(dev, DRM_MINOR_ACCEL); drm_minor_unregister(dev, DRM_MINOR_PRIMARY); drm_minor_unregister(dev, DRM_MINOR_RENDER); } EXPORT_SYMBOL(drm_dev_unregister); /* * DRM Core * The DRM core module initializes all global DRM objects and makes them * available to drivers. Once setup, drivers can probe their respective * devices. * Currently, core management includes: * - The "DRM-Global" key/value database * - Global ID management for connectors * - DRM major number allocation * - DRM minor management * - DRM sysfs class * - DRM debugfs root * * Furthermore, the DRM core provides dynamic char-dev lookups. For each * interface registered on a DRM device, you can request minor numbers from DRM * core. DRM core takes care of major-number management and char-dev * registration. A stub ->open() callback forwards any open() requests to the * registered minor. */ #ifdef __linux__ static int drm_stub_open(struct inode *inode, struct file *filp) { const struct file_operations *new_fops; struct drm_minor *minor; int err; DRM_DEBUG("\n"); minor = drm_minor_acquire(iminor(inode)); if (IS_ERR(minor)) return PTR_ERR(minor); new_fops = fops_get(minor->dev->driver->fops); if (!new_fops) { err = -ENODEV; goto out; } replace_fops(filp, new_fops); if (filp->f_op->open) err = filp->f_op->open(inode, filp); else err = 0; out: drm_minor_release(minor); return err; } static const struct file_operations drm_stub_fops = { .owner = THIS_MODULE, .open = drm_stub_open, .llseek = noop_llseek, }; #endif /* __linux__ */ static void drm_core_exit(void) { drm_privacy_screen_lookup_exit(); accel_core_exit(); #ifdef __linux__ unregister_chrdev(DRM_MAJOR, "drm"); debugfs_remove(drm_debugfs_root); drm_sysfs_destroy(); #endif idr_destroy(&drm_minors_idr); drm_connector_ida_destroy(); } static int __init drm_core_init(void) { #ifdef __linux__ int ret; #endif drm_connector_ida_init(); idr_init(&drm_minors_idr); drm_memcpy_init_early(); #ifdef __linux__ ret = drm_sysfs_init(); if (ret < 0) { DRM_ERROR("Cannot create DRM class: %d\n", ret); goto error; } drm_debugfs_root = debugfs_create_dir("dri", NULL); ret = register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops); if (ret < 0) goto error; ret = accel_core_init(); if (ret < 0) goto error; #endif drm_privacy_screen_lookup_init(); drm_core_init_complete = true; DRM_DEBUG("Initialized\n"); return 0; #ifdef __linux__ error: drm_core_exit(); return ret; #endif } #ifdef __linux__ module_init(drm_core_init); module_exit(drm_core_exit); #endif void drm_attach_platform(struct drm_driver *driver, bus_space_tag_t iot, bus_dma_tag_t dmat, struct device *dev, struct drm_device *drm) { struct drm_attach_args arg; memset(&arg, 0, sizeof(arg)); arg.driver = driver; arg.bst = iot; arg.dmat = dmat; arg.drm = drm; arg.busid = dev->dv_xname; arg.busid_len = strlen(dev->dv_xname) + 1; config_found_sm(dev, &arg, drmprint, drmsubmatch); } struct drm_device * drm_attach_pci(const struct drm_driver *driver, struct pci_attach_args *pa, int is_agp, int primary, struct device *dev, struct drm_device *drm) { struct drm_attach_args arg; struct drm_softc *sc; arg.drm = drm; arg.driver = driver; arg.dmat = pa->pa_dmat; arg.bst = pa->pa_memt; arg.is_agp = is_agp; arg.primary = primary; arg.pa = pa; arg.busid_len = 20; arg.busid = malloc(arg.busid_len + 1, M_DRM, M_NOWAIT); if (arg.busid == NULL) { printf("%s: no memory for drm\n", dev->dv_xname); return (NULL); } snprintf(arg.busid, arg.busid_len, "pci:%04x:%02x:%02x.%1x", pa->pa_domain, pa->pa_bus, pa->pa_device, pa->pa_function); sc = (struct drm_softc *)config_found_sm(dev, &arg, drmprint, drmsubmatch); if (sc == NULL) return NULL; return sc->sc_drm; } int drmprint(void *aux, const char *pnp) { if (pnp != NULL) printf("drm at %s", pnp); return (UNCONF); } int drmsubmatch(struct device *parent, void *match, void *aux) { extern struct cfdriver drm_cd; struct cfdata *cf = match; /* only allow drm to attach */ if (cf->cf_driver == &drm_cd) return ((*cf->cf_attach->ca_match)(parent, match, aux)); return (0); } int drm_pciprobe(struct pci_attach_args *pa, const struct pci_device_id *idlist) { const struct pci_device_id *id_entry; id_entry = drm_find_description(PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id), idlist); if (id_entry != NULL) return 1; return 0; } int drm_probe(struct device *parent, void *match, void *aux) { struct cfdata *cf = match; struct drm_attach_args *da = aux; if (cf->drmdevcf_primary != DRMDEVCF_PRIMARY_UNK) { /* * If primary-ness of device specified, either match * exactly (at high priority), or fail. */ if (cf->drmdevcf_primary != 0 && da->primary != 0) return (10); else return (0); } /* If primary-ness unspecified, it wins. */ return (1); } int drm_buddy_module_init(void); void drm_buddy_module_exit(void); void drm_attach(struct device *parent, struct device *self, void *aux) { struct drm_softc *sc = (struct drm_softc *)self; struct drm_attach_args *da = aux; struct drm_device *dev = da->drm; int ret; if (drm_refcnt == 0) { drm_linux_init(); drm_core_init(); drm_buddy_module_init(); } drm_refcnt++; if (dev == NULL) { dev = malloc(sizeof(struct drm_device), M_DRM, M_WAITOK | M_ZERO); sc->sc_allocated = 1; } sc->sc_drm = dev; kref_init(&dev->ref); dev->dev = self; dev->dev_private = parent; dev->driver = da->driver; INIT_LIST_HEAD(&dev->managed.resources); mtx_init(&dev->managed.lock, IPL_TTY); /* no per-device feature limits by default */ dev->driver_features = ~0u; dev->dmat = da->dmat; dev->bst = da->bst; dev->unique = da->busid; if (da->pa) { struct pci_attach_args *pa = da->pa; pcireg_t subsys; subsys = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); dev->pdev = &dev->_pdev; dev->pdev->vendor = PCI_VENDOR(pa->pa_id); dev->pdev->device = PCI_PRODUCT(pa->pa_id); dev->pdev->subsystem_vendor = PCI_VENDOR(subsys); dev->pdev->subsystem_device = PCI_PRODUCT(subsys); dev->pdev->revision = PCI_REVISION(pa->pa_class); dev->pdev->class = (PCI_CLASS(pa->pa_class) << 16) | (PCI_SUBCLASS(pa->pa_class) << 8) | PCI_INTERFACE(pa->pa_class); dev->pdev->devfn = PCI_DEVFN(pa->pa_device, pa->pa_function); dev->pdev->bus = &dev->pdev->_bus; dev->pdev->bus->pc = pa->pa_pc; dev->pdev->bus->number = pa->pa_bus; dev->pdev->bus->domain_nr = pa->pa_domain; dev->pdev->bus->bridgetag = pa->pa_bridgetag; if (pa->pa_bridgetag != NULL) { dev->pdev->bus->self = malloc(sizeof(struct pci_dev), M_DRM, M_WAITOK | M_ZERO); dev->pdev->bus->self->pc = pa->pa_pc; dev->pdev->bus->self->tag = *pa->pa_bridgetag; } dev->pdev->pc = pa->pa_pc; dev->pdev->tag = pa->pa_tag; dev->pdev->pci = (struct pci_softc *)parent->dv_parent; #ifdef CONFIG_ACPI dev->pdev->dev.node = acpi_find_pci(pa->pa_pc, pa->pa_tag); aml_register_notify(dev->pdev->dev.node, NULL, drm_linux_acpi_notify, NULL, ACPIDEV_NOPOLL); #endif } mtx_init(&dev->quiesce_mtx, IPL_NONE); mtx_init(&dev->event_lock, IPL_TTY); rw_init(&dev->struct_mutex, "drmdevlk"); rw_init(&dev->filelist_mutex, "drmflist"); rw_init(&dev->clientlist_mutex, "drmclist"); rw_init(&dev->master_mutex, "drmmast"); ret = drmm_add_action(dev, drm_dev_init_release, NULL); if (ret) goto error; SPLAY_INIT(&dev->files); INIT_LIST_HEAD(&dev->filelist_internal); INIT_LIST_HEAD(&dev->clientlist); INIT_LIST_HEAD(&dev->vblank_event_list); if (drm_core_check_feature(dev, DRIVER_RENDER)) { ret = drm_minor_alloc(dev, DRM_MINOR_RENDER); if (ret) goto error; } ret = drm_minor_alloc(dev, DRM_MINOR_PRIMARY); if (ret) goto error; #ifdef CONFIG_DRM_LEGACY if (drm_core_check_feature(dev, DRIVER_USE_AGP)) { #if IS_ENABLED(CONFIG_AGP) if (da->is_agp) dev->agp = drm_agp_init(); #endif if (dev->agp != NULL) { if (drm_mtrr_add(dev->agp->info.ai_aperture_base, dev->agp->info.ai_aperture_size, DRM_MTRR_WC) == 0) dev->agp->mtrr = 1; } } #endif if (dev->driver->gem_size > 0) { KASSERT(dev->driver->gem_size >= sizeof(struct drm_gem_object)); /* XXX unique name */ pool_init(&dev->objpl, dev->driver->gem_size, 0, IPL_NONE, 0, "drmobjpl", NULL); } if (drm_core_check_feature(dev, DRIVER_GEM)) { ret = drm_gem_init(dev); if (ret) { DRM_ERROR("Cannot initialize graphics execution manager (GEM)\n"); goto error; } } drmm_add_final_kfree(dev, dev); printf("\n"); return; error: drm_managed_release(dev); dev->dev_private = NULL; } int drm_detach(struct device *self, int flags) { struct drm_softc *sc = (struct drm_softc *)self; struct drm_device *dev = sc->sc_drm; drm_refcnt--; if (drm_refcnt == 0) { drm_buddy_module_exit(); drm_core_exit(); drm_linux_exit(); } drm_lastclose(dev); if (drm_core_check_feature(dev, DRIVER_GEM)) { if (dev->driver->gem_size > 0) pool_destroy(&dev->objpl); } #ifdef CONFIG_DRM_LEGACY if (dev->agp && dev->agp->mtrr) { int retcode; retcode = drm_mtrr_del(0, dev->agp->info.ai_aperture_base, dev->agp->info.ai_aperture_size, DRM_MTRR_WC); DRM_DEBUG("mtrr_del = %d", retcode); } free(dev->agp, M_DRM, 0); #endif if (dev->pdev && dev->pdev->bus) free(dev->pdev->bus->self, M_DRM, sizeof(struct pci_dev)); if (sc->sc_allocated) free(dev, M_DRM, sizeof(struct drm_device)); return 0; } void drm_quiesce(struct drm_device *dev) { mtx_enter(&dev->quiesce_mtx); dev->quiesce = 1; while (dev->quiesce_count > 0) { msleep_nsec(&dev->quiesce_count, &dev->quiesce_mtx, PZERO, "drmqui", INFSLP); } mtx_leave(&dev->quiesce_mtx); } void drm_wakeup(struct drm_device *dev) { mtx_enter(&dev->quiesce_mtx); dev->quiesce = 0; wakeup(&dev->quiesce); mtx_leave(&dev->quiesce_mtx); } int drm_activate(struct device *self, int act) { struct drm_softc *sc = (struct drm_softc *)self; struct drm_device *dev = sc->sc_drm; switch (act) { case DVACT_QUIESCE: drm_quiesce(dev); break; case DVACT_WAKEUP: drm_wakeup(dev); break; } return (0); } const struct cfattach drm_ca = { sizeof(struct drm_softc), drm_probe, drm_attach, drm_detach, drm_activate }; struct cfdriver drm_cd = { 0, "drm", DV_DULL }; const struct pci_device_id * drm_find_description(int vendor, int device, const struct pci_device_id *idlist) { int i = 0; for (i = 0; idlist[i].vendor != 0; i++) { if ((idlist[i].vendor == vendor) && (idlist[i].device == device || idlist[i].device == PCI_ANY_ID) && (idlist[i].subvendor == PCI_ANY_ID) && (idlist[i].subdevice == PCI_ANY_ID)) return &idlist[i]; } return NULL; } int drm_file_cmp(struct drm_file *f1, struct drm_file *f2) { return (f1->fminor < f2->fminor ? -1 : f1->fminor > f2->fminor); } SPLAY_GENERATE(drm_file_tree, drm_file, link, drm_file_cmp); struct drm_file * drm_find_file_by_minor(struct drm_device *dev, int minor) { struct drm_file key; key.fminor = minor; return (SPLAY_FIND(drm_file_tree, &dev->files, &key)); } struct drm_device * drm_get_device_from_kdev(dev_t kdev) { int unit = minor(kdev) & ((1 << CLONE_SHIFT) - 1); /* render */ if (unit >= 128) unit -= 128; struct drm_softc *sc; if (unit < drm_cd.cd_ndevs) { sc = (struct drm_softc *)drm_cd.cd_devs[unit]; if (sc) return sc->sc_drm; } return NULL; } void filt_drmdetach(struct knote *kn) { struct drm_device *dev = kn->kn_hook; int s; s = spltty(); klist_remove_locked(&dev->note, kn); splx(s); } int filt_drmkms(struct knote *kn, long hint) { if (kn->kn_sfflags & hint) kn->kn_fflags |= hint; return (kn->kn_fflags != 0); } void filt_drmreaddetach(struct knote *kn) { struct drm_file *file_priv = kn->kn_hook; int s; s = spltty(); klist_remove_locked(&file_priv->rsel.si_note, kn); splx(s); } int filt_drmread(struct knote *kn, long hint) { struct drm_file *file_priv = kn->kn_hook; int val = 0; if ((hint & NOTE_SUBMIT) == 0) mtx_enter(&file_priv->minor->dev->event_lock); val = !list_empty(&file_priv->event_list); if ((hint & NOTE_SUBMIT) == 0) mtx_leave(&file_priv->minor->dev->event_lock); return (val); } const struct filterops drm_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, .f_detach = filt_drmdetach, .f_event = filt_drmkms, }; const struct filterops drmread_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, .f_detach = filt_drmreaddetach, .f_event = filt_drmread, }; int drmkqfilter(dev_t kdev, struct knote *kn) { struct drm_device *dev = NULL; struct drm_file *file_priv = NULL; int s; dev = drm_get_device_from_kdev(kdev); if (dev == NULL || dev->dev_private == NULL) return (ENXIO); switch (kn->kn_filter) { case EVFILT_READ: mutex_lock(&dev->struct_mutex); file_priv = drm_find_file_by_minor(dev, minor(kdev)); mutex_unlock(&dev->struct_mutex); if (file_priv == NULL) return (ENXIO); kn->kn_fop = &drmread_filtops; kn->kn_hook = file_priv; s = spltty(); klist_insert_locked(&file_priv->rsel.si_note, kn); splx(s); break; case EVFILT_DEVICE: kn->kn_fop = &drm_filtops; kn->kn_hook = dev; s = spltty(); klist_insert_locked(&dev->note, kn); splx(s); break; default: return (EINVAL); } return (0); } int drmopen(dev_t kdev, int flags, int fmt, struct proc *p) { struct drm_device *dev = NULL; struct drm_file *file_priv; struct drm_minor *dm; int ret = 0; int dminor, realminor, minor_type; int need_setup = 0; dev = drm_get_device_from_kdev(kdev); if (dev == NULL || dev->dev_private == NULL) return (ENXIO); DRM_DEBUG("open_count = %d\n", atomic_read(&dev->open_count)); if (flags & O_EXCL) return (EBUSY); /* No exclusive opens */ if (drm_dev_needs_global_mutex(dev)) mutex_lock(&drm_global_mutex); if (!atomic_fetch_inc(&dev->open_count)) need_setup = 1; dminor = minor(kdev); realminor = dminor & ((1 << CLONE_SHIFT) - 1); if (realminor < 64) minor_type = DRM_MINOR_PRIMARY; else if (realminor >= 128 && realminor < 192) minor_type = DRM_MINOR_RENDER; else { ret = ENXIO; goto err; } dm = *drm_minor_get_slot(dev, minor_type); if (dm == NULL) { ret = ENXIO; goto err; } dm->index = minor(kdev); file_priv = drm_file_alloc(dm); if (IS_ERR(file_priv)) { ret = ENOMEM; goto err; } /* first opener automatically becomes master */ if (drm_is_primary_client(file_priv)) { ret = drm_master_open(file_priv); if (ret != 0) goto out_file_free; } file_priv->filp = (void *)file_priv; file_priv->fminor = minor(kdev); mutex_lock(&dev->filelist_mutex); SPLAY_INSERT(drm_file_tree, &dev->files, file_priv); mutex_unlock(&dev->filelist_mutex); if (need_setup) { ret = drm_legacy_setup(dev); if (ret) goto out_file_free; } if (drm_dev_needs_global_mutex(dev)) mutex_unlock(&drm_global_mutex); return 0; out_file_free: drm_file_free(file_priv); err: atomic_dec(&dev->open_count); if (drm_dev_needs_global_mutex(dev)) mutex_unlock(&drm_global_mutex); return (ret); } int drmclose(dev_t kdev, int flags, int fmt, struct proc *p) { struct drm_device *dev = drm_get_device_from_kdev(kdev); struct drm_file *file_priv; int retcode = 0; if (dev == NULL) return (ENXIO); if (drm_dev_needs_global_mutex(dev)) mutex_lock(&drm_global_mutex); DRM_DEBUG("open_count = %d\n", atomic_read(&dev->open_count)); mutex_lock(&dev->filelist_mutex); file_priv = drm_find_file_by_minor(dev, minor(kdev)); if (file_priv == NULL) { DRM_ERROR("can't find authenticator\n"); retcode = EINVAL; mutex_unlock(&dev->filelist_mutex); goto done; } SPLAY_REMOVE(drm_file_tree, &dev->files, file_priv); mutex_unlock(&dev->filelist_mutex); drm_file_free(file_priv); done: if (atomic_dec_and_test(&dev->open_count)) drm_lastclose(dev); if (drm_dev_needs_global_mutex(dev)) mutex_unlock(&drm_global_mutex); return (retcode); } int drmread(dev_t kdev, struct uio *uio, int ioflag) { struct drm_device *dev = drm_get_device_from_kdev(kdev); struct drm_file *file_priv; struct drm_pending_event *ev; int error = 0; if (dev == NULL) return (ENXIO); mutex_lock(&dev->filelist_mutex); file_priv = drm_find_file_by_minor(dev, minor(kdev)); mutex_unlock(&dev->filelist_mutex); if (file_priv == NULL) return (ENXIO); /* * The semantics are a little weird here. We will wait until we * have events to process, but as soon as we have events we will * only deliver as many as we have. * Note that events are atomic, if the read buffer will not fit in * a whole event, we won't read any of it out. */ mtx_enter(&dev->event_lock); while (error == 0 && list_empty(&file_priv->event_list)) { if (ioflag & IO_NDELAY) { mtx_leave(&dev->event_lock); return (EAGAIN); } error = msleep_nsec(&file_priv->event_wait, &dev->event_lock, PWAIT | PCATCH, "drmread", INFSLP); } if (error) { mtx_leave(&dev->event_lock); return (error); } while (drm_dequeue_event(dev, file_priv, uio->uio_resid, &ev)) { MUTEX_ASSERT_UNLOCKED(&dev->event_lock); /* XXX we always destroy the event on error. */ error = uiomove(ev->event, ev->event->length, uio); kfree(ev); if (error) break; mtx_enter(&dev->event_lock); } MUTEX_ASSERT_UNLOCKED(&dev->event_lock); return (error); } /* * Deqeue an event from the file priv in question. returning 1 if an * event was found. We take the resid from the read as a parameter because * we will only dequeue and event if the read buffer has space to fit the * entire thing. * * We are called locked, but we will *unlock* the queue on return so that * we may sleep to copyout the event. */ int drm_dequeue_event(struct drm_device *dev, struct drm_file *file_priv, size_t resid, struct drm_pending_event **out) { struct drm_pending_event *e = NULL; int gotone = 0; MUTEX_ASSERT_LOCKED(&dev->event_lock); *out = NULL; if (list_empty(&file_priv->event_list)) goto out; e = list_first_entry(&file_priv->event_list, struct drm_pending_event, link); if (e->event->length > resid) goto out; file_priv->event_space += e->event->length; list_del(&e->link); *out = e; gotone = 1; out: mtx_leave(&dev->event_lock); return (gotone); } paddr_t drmmmap(dev_t kdev, off_t offset, int prot) { return -1; } struct drm_dmamem * drm_dmamem_alloc(bus_dma_tag_t dmat, bus_size_t size, bus_size_t alignment, int nsegments, bus_size_t maxsegsz, int mapflags, int loadflags) { struct drm_dmamem *mem; size_t strsize; /* * segs is the last member of the struct since we modify the size * to allow extra segments if more than one are allowed. */ strsize = sizeof(*mem) + (sizeof(bus_dma_segment_t) * (nsegments - 1)); mem = malloc(strsize, M_DRM, M_NOWAIT | M_ZERO); if (mem == NULL) return (NULL); mem->size = size; if (bus_dmamap_create(dmat, size, nsegments, maxsegsz, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &mem->map) != 0) goto strfree; if (bus_dmamem_alloc(dmat, size, alignment, 0, mem->segs, nsegments, &mem->nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO) != 0) goto destroy; if (bus_dmamem_map(dmat, mem->segs, mem->nsegs, size, &mem->kva, BUS_DMA_NOWAIT | mapflags) != 0) goto free; if (bus_dmamap_load(dmat, mem->map, mem->kva, size, NULL, BUS_DMA_NOWAIT | loadflags) != 0) goto unmap; return (mem); unmap: bus_dmamem_unmap(dmat, mem->kva, size); free: bus_dmamem_free(dmat, mem->segs, mem->nsegs); destroy: bus_dmamap_destroy(dmat, mem->map); strfree: free(mem, M_DRM, 0); return (NULL); } void drm_dmamem_free(bus_dma_tag_t dmat, struct drm_dmamem *mem) { if (mem == NULL) return; bus_dmamap_unload(dmat, mem->map); bus_dmamem_unmap(dmat, mem->kva, mem->size); bus_dmamem_free(dmat, mem->segs, mem->nsegs); bus_dmamap_destroy(dmat, mem->map); free(mem, M_DRM, 0); } struct drm_dma_handle * drm_pci_alloc(struct drm_device *dev, size_t size, size_t align) { struct drm_dma_handle *dmah; dmah = malloc(sizeof(*dmah), M_DRM, M_WAITOK); dmah->mem = drm_dmamem_alloc(dev->dmat, size, align, 1, size, BUS_DMA_NOCACHE, 0); if (dmah->mem == NULL) { free(dmah, M_DRM, sizeof(*dmah)); return NULL; } dmah->busaddr = dmah->mem->segs[0].ds_addr; dmah->size = dmah->mem->size; dmah->vaddr = dmah->mem->kva; return (dmah); } void drm_pci_free(struct drm_device *dev, struct drm_dma_handle *dmah) { if (dmah == NULL) return; drm_dmamem_free(dev->dmat, dmah->mem); free(dmah, M_DRM, sizeof(*dmah)); } /* * Compute order. Can be made faster. */ int drm_order(unsigned long size) { int order; unsigned long tmp; for (order = 0, tmp = size; tmp >>= 1; ++order) ; if (size & ~(1 << order)) ++order; return order; } int drm_getpciinfo(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_pciinfo *info = data; if (dev->pdev == NULL) return -ENOTTY; info->domain = dev->pdev->bus->domain_nr; info->bus = dev->pdev->bus->number; info->dev = PCI_SLOT(dev->pdev->devfn); info->func = PCI_FUNC(dev->pdev->devfn); info->vendor_id = dev->pdev->vendor; info->device_id = dev->pdev->device; info->subvendor_id = dev->pdev->subsystem_vendor; info->subdevice_id = dev->pdev->subsystem_device; info->revision_id = 0; return 0; }
141 60 2 34 18 8 32 6 4 5 41 4 4 4 44 44 5 83 4 2 79 2 20 59 1 58 5 1 48 58 11 4 1 34 34 74 74 73 5 2 6 74 16 59 74 16 15 15 2 13 15 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 /* $OpenBSD: in6_pcb.c,v 1.144 2024/04/12 16:07:09 bluhm Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 * * NRL grants permission for redistribution and use in source and binary * forms, with or without modification, of the software and documentation * created at NRL provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgements: * This product includes software developed by the University of * California, Berkeley and its contributors. * This product includes software developed at the Information * Technology Division, US Naval Research Laboratory. * 4. Neither the name of the NRL nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the US Naval * Research Laboratory (NRL). */ /* * Copyright (c) 1982, 1986, 1990, 1993, 1995 * Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include "pf.h" #include "stoeplitz.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/protosw.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <net/if.h> #include <net/if_var.h> #include <net/pfvar.h> #include <netinet/in.h> #include <netinet6/in6_var.h> #include <netinet/ip.h> #include <netinet/ip_var.h> #include <netinet6/ip6_var.h> #include <netinet/in_pcb.h> #if NSTOEPLITZ > 0 #include <net/toeplitz.h> #endif const struct in6_addr zeroin6_addr; struct inpcb *in6_pcbhash_lookup(struct inpcbtable *, uint64_t, u_int, const struct in6_addr *, u_short, const struct in6_addr *, u_short); struct inpcb * in6_pcblookup_lock(struct inpcbtable *, const struct in6_addr *, u_int, const struct in6_addr *, u_int, u_int, int); uint64_t in6_pcbhash(struct inpcbtable *table, u_int rdomain, const struct in6_addr *faddr, u_short fport, const struct in6_addr *laddr, u_short lport) { SIPHASH_CTX ctx; u_int32_t nrdom = htonl(rdomain); SipHash24_Init(&ctx, &table->inpt_key); SipHash24_Update(&ctx, &nrdom, sizeof(nrdom)); SipHash24_Update(&ctx, faddr, sizeof(*faddr)); SipHash24_Update(&ctx, &fport, sizeof(fport)); SipHash24_Update(&ctx, laddr, sizeof(*laddr)); SipHash24_Update(&ctx, &lport, sizeof(lport)); return SipHash24_End(&ctx); } int in6_pcbaddrisavail_lock(const struct inpcb *inp, struct sockaddr_in6 *sin6, int wild, struct proc *p, int lock) { struct socket *so = inp->inp_socket; struct inpcbtable *table = inp->inp_table; u_short lport = sin6->sin6_port; int reuseport = (so->so_options & SO_REUSEPORT); wild |= INPLOOKUP_IPV6; /* KAME hack: embed scopeid */ if (in6_embedscope(&sin6->sin6_addr, sin6, inp->inp_outputopts6, inp->inp_moptions6) != 0) return (EINVAL); /* this must be cleared for ifa_ifwithaddr() */ sin6->sin6_scope_id = 0; /* reject IPv4 mapped address, we have no support for it */ if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) return (EADDRNOTAVAIL); if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { /* * Treat SO_REUSEADDR as SO_REUSEPORT for multicast; * allow complete duplication of binding if * SO_REUSEPORT is set, or if SO_REUSEADDR is set * and a multicast address is bound on both * new and duplicated sockets. */ if (so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) reuseport = SO_REUSEADDR | SO_REUSEPORT; } else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { struct ifaddr *ifa = NULL; sin6->sin6_port = 0; /* * Yechhhh, because of upcoming * call to ifa_ifwithaddr(), which * does bcmp's over the PORTS as * well. (What about flow?) */ sin6->sin6_flowinfo = 0; if (!(so->so_options & SO_BINDANY) && (ifa = ifa_ifwithaddr(sin6tosa(sin6), inp->inp_rtableid)) == NULL) return (EADDRNOTAVAIL); sin6->sin6_port = lport; /* * bind to an anycast address might accidentally * cause sending a packet with an anycast source * address, so we forbid it. * * We should allow to bind to a deprecated address, * since the application dare to use it. * But, can we assume that they are careful enough * to check if the address is deprecated or not? * Maybe, as a safeguard, we should have a setsockopt * flag to control the bind(2) behavior against * deprecated addresses (default: forbid bind(2)). */ if (ifa && ifatoia6(ifa)->ia6_flags & (IN6_IFF_ANYCAST| IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED|IN6_IFF_DETACHED)) return (EADDRNOTAVAIL); } if (lport) { struct inpcb *t; int error = 0; if (so->so_euid && !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { t = in_pcblookup_local_lock(table, &sin6->sin6_addr, lport, INPLOOKUP_WILDCARD | INPLOOKUP_IPV6, inp->inp_rtableid, lock); if (t && (so->so_euid != t->inp_socket->so_euid)) error = EADDRINUSE; if (lock == IN_PCBLOCK_GRAB) in_pcbunref(t); if (error) return (error); } t = in_pcblookup_local_lock(table, &sin6->sin6_addr, lport, wild, inp->inp_rtableid, lock); if (t && (reuseport & t->inp_socket->so_options) == 0) error = EADDRINUSE; if (lock == IN_PCBLOCK_GRAB) in_pcbunref(t); if (error) return (error); } return (0); } int in6_pcbaddrisavail(const struct inpcb *inp, struct sockaddr_in6 *sin6, int wild, struct proc *p) { return in6_pcbaddrisavail_lock(inp, sin6, wild, p, IN_PCBLOCK_GRAB); } /* * Connect from a socket to a specified address. * Both address and port must be specified in argument sin6. * Eventually, flow labels will have to be dealt with here, as well. * * If don't have a local address for this socket yet, * then pick one. */ int in6_pcbconnect(struct inpcb *inp, struct mbuf *nam) { struct inpcbtable *table = inp->inp_table; const struct in6_addr *in6a; struct sockaddr_in6 *sin6; struct inpcb *t; int error; struct sockaddr_in6 tmp; KASSERT(ISSET(inp->inp_flags, INP_IPV6)); if ((error = in6_nam2sin6(nam, &sin6))) return (error); if (sin6->sin6_port == 0) return (EADDRNOTAVAIL); /* reject IPv4 mapped address, we have no support for it */ if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) return (EADDRNOTAVAIL); /* protect *sin6 from overwrites */ tmp = *sin6; sin6 = &tmp; /* KAME hack: embed scopeid */ if (in6_embedscope(&sin6->sin6_addr, sin6, inp->inp_outputopts6, inp->inp_moptions6) != 0) return (EINVAL); /* this must be cleared for ifa_ifwithaddr() */ sin6->sin6_scope_id = 0; /* Source address selection. */ /* * XXX: in6_selectsrc might replace the bound local address * with the address specified by setsockopt(IPV6_PKTINFO). * Is it the intended behavior? */ error = in6_pcbselsrc(&in6a, sin6, inp, inp->inp_outputopts6); if (error) return (error); inp->inp_ipv6.ip6_hlim = (u_int8_t)in6_selecthlim(inp); /* keep lookup, modification, and rehash in sync */ mtx_enter(&table->inpt_mtx); t = in6_pcblookup_lock(inp->inp_table, &sin6->sin6_addr, sin6->sin6_port, IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6) ? in6a : &inp->inp_laddr6, inp->inp_lport, inp->inp_rtableid, IN_PCBLOCK_HOLD); if (t != NULL) { mtx_leave(&table->inpt_mtx); return (EADDRINUSE); } KASSERT(IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6) || inp->inp_lport); if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) { if (inp->inp_lport == 0) { error = in_pcbbind_locked(inp, NULL, in6a, curproc); if (error) { mtx_leave(&table->inpt_mtx); return (error); } t = in6_pcblookup_lock(inp->inp_table, &sin6->sin6_addr, sin6->sin6_port, in6a, inp->inp_lport, inp->inp_rtableid, IN_PCBLOCK_HOLD); if (t != NULL) { inp->inp_lport = 0; mtx_leave(&table->inpt_mtx); return (EADDRINUSE); } } inp->inp_laddr6 = *in6a; } inp->inp_faddr6 = sin6->sin6_addr; inp->inp_fport = sin6->sin6_port; in_pcbrehash(inp); mtx_leave(&table->inpt_mtx); inp->inp_flowinfo &= ~IPV6_FLOWLABEL_MASK; if (ip6_auto_flowlabel) inp->inp_flowinfo |= (htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK); #if NSTOEPLITZ > 0 inp->inp_flowid = stoeplitz_ip6port(&inp->inp_faddr6, &inp->inp_laddr6, inp->inp_fport, inp->inp_lport); #endif return (0); } /* * Get the local address/port, and put it in a sockaddr_in6. * This services the getsockname(2) call. */ void in6_setsockaddr(struct inpcb *inp, struct mbuf *nam) { struct sockaddr_in6 *sin6; nam->m_len = sizeof(struct sockaddr_in6); sin6 = mtod(nam,struct sockaddr_in6 *); bzero ((caddr_t)sin6,sizeof(struct sockaddr_in6)); sin6->sin6_family = AF_INET6; sin6->sin6_len = sizeof(struct sockaddr_in6); sin6->sin6_port = inp->inp_lport; sin6->sin6_addr = inp->inp_laddr6; /* KAME hack: recover scopeid */ in6_recoverscope(sin6, &inp->inp_laddr6); } /* * Get the foreign address/port, and put it in a sockaddr_in6. * This services the getpeername(2) call. */ void in6_setpeeraddr(struct inpcb *inp, struct mbuf *nam) { struct sockaddr_in6 *sin6; nam->m_len = sizeof(struct sockaddr_in6); sin6 = mtod(nam,struct sockaddr_in6 *); bzero ((caddr_t)sin6,sizeof(struct sockaddr_in6)); sin6->sin6_family = AF_INET6; sin6->sin6_len = sizeof(struct sockaddr_in6); sin6->sin6_port = inp->inp_fport; sin6->sin6_addr = inp->inp_faddr6; /* KAME hack: recover scopeid */ in6_recoverscope(sin6, &inp->inp_faddr6); } int in6_sockaddr(struct socket *so, struct mbuf *nam) { struct inpcb *inp; inp = sotoinpcb(so); in6_setsockaddr(inp, nam); return (0); } int in6_peeraddr(struct socket *so, struct mbuf *nam) { struct inpcb *inp; inp = sotoinpcb(so); in6_setpeeraddr(inp, nam); return (0); } /* * Pass some notification to all connections of a protocol * associated with address dst. The local address and/or port numbers * may be specified to limit the search. The "usual action" will be * taken, depending on the ctlinput cmd. The caller must filter any * cmds that are uninteresting (e.g., no error in the map). * Call the protocol specific routine (if any) to report * any errors for each matching socket. * * Also perform input-side security policy check * once PCB to be notified has been located. */ void in6_pcbnotify(struct inpcbtable *table, const struct sockaddr_in6 *dst, uint fport_arg, const struct sockaddr_in6 *src, uint lport_arg, u_int rtable, int cmd, void *cmdarg, void (*notify)(struct inpcb *, int)) { SIMPLEQ_HEAD(, inpcb) inpcblist; struct inpcb *inp; u_short fport = fport_arg, lport = lport_arg; struct sockaddr_in6 sa6_src; int errno; u_int32_t flowinfo; u_int rdomain; if ((unsigned)cmd >= PRC_NCMDS) return; if (IN6_IS_ADDR_UNSPECIFIED(&dst->sin6_addr)) return; if (IN6_IS_ADDR_V4MAPPED(&dst->sin6_addr)) { #ifdef DIAGNOSTIC printf("%s: Huh? Thought we never got " "called with mapped!\n", __func__); #endif return; } /* * note that src can be NULL when we get notify by local fragmentation. */ sa6_src = (src == NULL) ? sa6_any : *src; flowinfo = sa6_src.sin6_flowinfo; /* * Redirects go to all references to the destination, * and use in_rtchange to invalidate the route cache. * Dead host indications: also use in_rtchange to invalidate * the cache, and deliver the error to all the sockets. * Otherwise, if we have knowledge of the local port and address, * deliver only to that socket. */ if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) { fport = 0; lport = 0; sa6_src.sin6_addr = in6addr_any; if (cmd != PRC_HOSTDEAD) notify = in_rtchange; } errno = inet6ctlerrmap[cmd]; if (notify == NULL) return; SIMPLEQ_INIT(&inpcblist); rdomain = rtable_l2(rtable); rw_enter_write(&table->inpt_notify); mtx_enter(&table->inpt_mtx); TAILQ_FOREACH(inp, &table->inpt_queue, inp_queue) { KASSERT(ISSET(inp->inp_flags, INP_IPV6)); /* * Under the following condition, notify of redirects * to the pcb, without making address matches against inpcb. * - redirect notification is arrived. * - the inpcb is unconnected. * - the inpcb is caching !RTF_HOST routing entry. * - the ICMPv6 notification is from the gateway cached in the * inpcb. i.e. ICMPv6 notification is from nexthop gateway * the inpcb used very recently. * * This is to improve interaction between netbsd/openbsd * redirect handling code, and inpcb route cache code. * without the clause, !RTF_HOST routing entry (which carries * gateway used by inpcb right before the ICMPv6 redirect) * will be cached forever in unconnected inpcb. * * There still is a question regarding to what is TRT: * - On bsdi/freebsd, RTF_HOST (cloned) routing entry will be * generated on packet output. inpcb will always cache * RTF_HOST routing entry so there's no need for the clause * (ICMPv6 redirect will update RTF_HOST routing entry, * and inpcb is caching it already). * However, bsdi/freebsd are vulnerable to local DoS attacks * due to the cloned routing entries. * - Specwise, "destination cache" is mentioned in RFC2461. * Jinmei says that it implies bsdi/freebsd behavior, itojun * is not really convinced. * - Having hiwat/lowat on # of cloned host route (redirect/ * pmtud) may be a good idea. netbsd/openbsd has it. see * icmp6_mtudisc_update(). */ if ((PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) && IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6) && inp->inp_route.ro_rt && !(inp->inp_route.ro_rt->rt_flags & RTF_HOST) && IN6_ARE_ADDR_EQUAL(&inp->inp_route.ro_dstsin6.sin6_addr, &dst->sin6_addr)) { goto do_notify; } /* * Detect if we should notify the error. If no source and * destination ports are specified, but non-zero flowinfo and * local address match, notify the error. This is the case * when the error is delivered with an encrypted buffer * by ESP. Otherwise, just compare addresses and ports * as usual. */ if (lport == 0 && fport == 0 && flowinfo && flowinfo == (inp->inp_flowinfo & IPV6_FLOWLABEL_MASK) && IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, &sa6_src.sin6_addr)) goto do_notify; else if (!IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6, &dst->sin6_addr) || rtable_l2(inp->inp_rtableid) != rdomain || (lport && inp->inp_lport != lport) || (!IN6_IS_ADDR_UNSPECIFIED(&sa6_src.sin6_addr) && !IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, &sa6_src.sin6_addr)) || (fport && inp->inp_fport != fport)) { continue; } do_notify: in_pcbref(inp); SIMPLEQ_INSERT_TAIL(&inpcblist, inp, inp_notify); } mtx_leave(&table->inpt_mtx); while ((inp = SIMPLEQ_FIRST(&inpcblist)) != NULL) { SIMPLEQ_REMOVE_HEAD(&inpcblist, inp_notify); (*notify)(inp, errno); in_pcbunref(inp); } rw_exit_write(&table->inpt_notify); } struct rtentry * in6_pcbrtentry(struct inpcb *inp) { if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) return (NULL); return (route6_mpath(&inp->inp_route, &inp->inp_faddr6, &inp->inp_laddr6, inp->inp_rtableid)); } struct inpcb * in6_pcbhash_lookup(struct inpcbtable *table, uint64_t hash, u_int rdomain, const struct in6_addr *faddr, u_short fport, const struct in6_addr *laddr, u_short lport) { struct inpcbhead *head; struct inpcb *inp; NET_ASSERT_LOCKED(); MUTEX_ASSERT_LOCKED(&table->inpt_mtx); head = &table->inpt_hashtbl[hash & table->inpt_mask]; LIST_FOREACH(inp, head, inp_hash) { KASSERT(ISSET(inp->inp_flags, INP_IPV6)); if (inp->inp_fport == fport && inp->inp_lport == lport && IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6, faddr) && IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, laddr) && rtable_l2(inp->inp_rtableid) == rdomain) { break; } } if (inp != NULL) { /* * Move this PCB to the head of hash chain so that * repeated accesses are quicker. This is analogous to * the historic single-entry PCB cache. */ if (inp != LIST_FIRST(head)) { LIST_REMOVE(inp, inp_hash); LIST_INSERT_HEAD(head, inp, inp_hash); } } return (inp); } struct inpcb * in6_pcblookup_lock(struct inpcbtable *table, const struct in6_addr *faddr, u_int fport, const struct in6_addr *laddr, u_int lport, u_int rtable, int lock) { struct inpcb *inp; uint64_t hash; u_int rdomain; rdomain = rtable_l2(rtable); hash = in6_pcbhash(table, rdomain, faddr, fport, laddr, lport); if (lock == IN_PCBLOCK_GRAB) { mtx_enter(&table->inpt_mtx); } else { KASSERT(lock == IN_PCBLOCK_HOLD); MUTEX_ASSERT_LOCKED(&table->inpt_mtx); } inp = in6_pcbhash_lookup(table, hash, rdomain, faddr, fport, laddr, lport); if (lock == IN_PCBLOCK_GRAB) { in_pcbref(inp); mtx_leave(&table->inpt_mtx); } #ifdef DIAGNOSTIC if (inp == NULL && in_pcbnotifymiss) { printf("%s: faddr= fport=%d laddr= lport=%d rdom=%u\n", __func__, ntohs(fport), ntohs(lport), rdomain); } #endif return (inp); } struct inpcb * in6_pcblookup(struct inpcbtable *table, const struct in6_addr *faddr, u_int fport, const struct in6_addr *laddr, u_int lport, u_int rtable) { return in6_pcblookup_lock(table, faddr, fport, laddr, lport, rtable, IN_PCBLOCK_GRAB); } struct inpcb * in6_pcblookup_listen(struct inpcbtable *table, struct in6_addr *laddr, u_int lport, struct mbuf *m, u_int rtable) { const struct in6_addr *key1, *key2; struct inpcb *inp; uint64_t hash; u_int rdomain; key1 = laddr; key2 = &zeroin6_addr; #if NPF > 0 if (m && m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { struct pf_divert *divert; divert = pf_find_divert(m); KASSERT(divert != NULL); switch (divert->type) { case PF_DIVERT_TO: key1 = key2 = &divert->addr.v6; lport = divert->port; break; case PF_DIVERT_REPLY: return (NULL); default: panic("%s: unknown divert type %d, mbuf %p, divert %p", __func__, divert->type, m, divert); } } else if (m && m->m_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST) { /* * Redirected connections should not be treated the same * as connections directed to ::1 since localhost * can only be accessed from the host itself. */ key1 = &zeroin6_addr; key2 = laddr; } #endif rdomain = rtable_l2(rtable); hash = in6_pcbhash(table, rdomain, &zeroin6_addr, 0, key1, lport); mtx_enter(&table->inpt_mtx); inp = in6_pcbhash_lookup(table, hash, rdomain, &zeroin6_addr, 0, key1, lport); if (inp == NULL && ! IN6_ARE_ADDR_EQUAL(key1, key2)) { hash = in6_pcbhash(table, rdomain, &zeroin6_addr, 0, key2, lport); inp = in6_pcbhash_lookup(table, hash, rdomain, &zeroin6_addr, 0, key2, lport); } in_pcbref(inp); mtx_leave(&table->inpt_mtx); #ifdef DIAGNOSTIC if (inp == NULL && in_pcbnotifymiss) { printf("%s: laddr= lport=%d rdom=%u\n", __func__, ntohs(lport), rdomain); } #endif return (inp); }
1908 234 1804 3 4 1900 1872 73 24 24 1876 1873 65 1872 24 1877 1874 1896 137 1698 471 1902 2430 1338 1568 1547 63 63 1546 2 221 106 1548 12 4 4 2 1 2 1 3 1 1 1 1 1 1 1 1 768 765 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 /* $OpenBSD: kern_malloc.c,v 1.151 2023/12/14 14:04:57 claudio Exp $ */ /* $NetBSD: kern_malloc.c,v 1.15.4.2 1996/06/13 17:10:56 cgd Exp $ */ /* * Copyright (c) 1987, 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_malloc.c 8.3 (Berkeley) 1/4/94 */ #include <sys/param.h> #include <sys/malloc.h> #include <sys/proc.h> #include <sys/stdint.h> #include <sys/systm.h> #include <sys/sysctl.h> #include <sys/time.h> #include <sys/mutex.h> #include <sys/rwlock.h> #include <sys/tracepoint.h> #include <uvm/uvm_extern.h> #if defined(DDB) #include <machine/db_machdep.h> #include <ddb/db_output.h> #endif static #ifndef SMALL_KERNEL __inline__ #endif long BUCKETINDX(size_t sz) { long b, d; /* note that this relies upon MINALLOCSIZE being 1 << MINBUCKET */ b = 7 + MINBUCKET; d = 4; while (d != 0) { if (sz <= (1 << b)) b -= d; else b += d; d >>= 1; } if (sz <= (1 << b)) b += 0; else b += 1; return b; } static struct vm_map kmem_map_store; struct vm_map *kmem_map = NULL; /* * Default number of pages in kmem_map. We attempt to calculate this * at run-time, but allow it to be either patched or set in the kernel * config file. */ #ifndef NKMEMPAGES #define NKMEMPAGES -1 #endif u_int nkmempages = NKMEMPAGES; struct mutex malloc_mtx = MUTEX_INITIALIZER(IPL_VM); struct kmembuckets bucket[MINBUCKET + 16]; #ifdef KMEMSTATS struct kmemstats kmemstats[M_LAST]; #endif struct kmemusage *kmemusage; char *kmembase, *kmemlimit; char buckstring[16 * sizeof("123456,")]; int buckstring_init = 0; #if defined(KMEMSTATS) || defined(DIAGNOSTIC) char *memname[] = INITKMEMNAMES; char *memall = NULL; struct rwlock sysctl_kmemlock = RWLOCK_INITIALIZER("sysctlklk"); #endif /* * Normally the freelist structure is used only to hold the list pointer * for free objects. However, when running with diagnostics, the first * 8 bytes of the structure is unused except for diagnostic information, * and the free list pointer is at offset 8 in the structure. Since the * first 8 bytes is the portion of the structure most often modified, this * helps to detect memory reuse problems and avoid free list corruption. */ struct kmem_freelist { int32_t kf_spare0; int16_t kf_type; int16_t kf_spare1; XSIMPLEQ_ENTRY(kmem_freelist) kf_flist; }; #ifdef DIAGNOSTIC /* * This structure provides a set of masks to catch unaligned frees. */ const long addrmask[] = { 0, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff, }; #endif /* DIAGNOSTIC */ #ifndef SMALL_KERNEL struct timeval malloc_errintvl = { 5, 0 }; struct timeval malloc_lasterr; #endif /* * Allocate a block of memory */ void * malloc(size_t size, int type, int flags) { struct kmembuckets *kbp; struct kmemusage *kup; struct kmem_freelist *freep; long indx, npg, allocsize; caddr_t va, cp; int s; #ifdef DIAGNOSTIC int freshalloc; char *savedtype; #endif #ifdef KMEMSTATS struct kmemstats *ksp = &kmemstats[type]; int wake; if (((unsigned long)type) <= 1 || ((unsigned long)type) >= M_LAST) panic("malloc: bogus type %d", type); #endif KASSERT(flags & (M_WAITOK | M_NOWAIT)); #ifdef DIAGNOSTIC if ((flags & M_NOWAIT) == 0) { extern int pool_debug; assertwaitok(); if (pool_debug == 2) yield(); } #endif if (size > 65535 * PAGE_SIZE) { if (flags & M_CANFAIL) { #ifndef SMALL_KERNEL if (ratecheck(&malloc_lasterr, &malloc_errintvl)) printf("malloc(): allocation too large, " "type = %d, size = %lu\n", type, size); #endif return (NULL); } else panic("malloc: allocation too large, " "type = %d, size = %lu", type, size); } indx = BUCKETINDX(size); if (size > MAXALLOCSAVE) allocsize = round_page(size); else allocsize = 1 << indx; kbp = &bucket[indx]; mtx_enter(&malloc_mtx); #ifdef KMEMSTATS while (ksp->ks_memuse >= ksp->ks_limit) { if (flags & M_NOWAIT) { mtx_leave(&malloc_mtx); return (NULL); } #ifdef DIAGNOSTIC if (ISSET(flags, M_WAITOK) && curproc == &proc0) panic("%s: cannot sleep for memory during boot", __func__); #endif if (ksp->ks_limblocks < 65535) ksp->ks_limblocks++; msleep_nsec(ksp, &malloc_mtx, PSWP+2, memname[type], INFSLP); } ksp->ks_memuse += allocsize; /* account for this early */ ksp->ks_size |= 1 << indx; #endif if (XSIMPLEQ_FIRST(&kbp->kb_freelist) == NULL) { mtx_leave(&malloc_mtx); npg = atop(round_page(allocsize)); s = splvm(); va = (caddr_t)uvm_km_kmemalloc_pla(kmem_map, NULL, (vsize_t)ptoa(npg), 0, ((flags & M_NOWAIT) ? UVM_KMF_NOWAIT : 0) | ((flags & M_CANFAIL) ? UVM_KMF_CANFAIL : 0), no_constraint.ucr_low, no_constraint.ucr_high, 0, 0, 0); splx(s); if (va == NULL) { /* * Kmem_malloc() can return NULL, even if it can * wait, if there is no map space available, because * it can't fix that problem. Neither can we, * right now. (We should release pages which * are completely free and which are in buckets * with too many free elements.) */ if ((flags & (M_NOWAIT|M_CANFAIL)) == 0) panic("malloc: out of space in kmem_map"); #ifdef KMEMSTATS mtx_enter(&malloc_mtx); ksp->ks_memuse -= allocsize; wake = ksp->ks_memuse + allocsize >= ksp->ks_limit && ksp->ks_memuse < ksp->ks_limit; mtx_leave(&malloc_mtx); if (wake) wakeup(ksp); #endif return (NULL); } mtx_enter(&malloc_mtx); #ifdef KMEMSTATS kbp->kb_total += kbp->kb_elmpercl; #endif kup = btokup(va); kup->ku_indx = indx; #ifdef DIAGNOSTIC freshalloc = 1; #endif if (allocsize > MAXALLOCSAVE) { kup->ku_pagecnt = npg; goto out; } #ifdef KMEMSTATS kup->ku_freecnt = kbp->kb_elmpercl; kbp->kb_totalfree += kbp->kb_elmpercl; #endif cp = va + (npg * PAGE_SIZE) - allocsize; for (;;) { freep = (struct kmem_freelist *)cp; #ifdef DIAGNOSTIC /* * Copy in known text to detect modification * after freeing. */ poison_mem(cp, allocsize); freep->kf_type = M_FREE; #endif /* DIAGNOSTIC */ XSIMPLEQ_INSERT_HEAD(&kbp->kb_freelist, freep, kf_flist); if (cp <= va) break; cp -= allocsize; } } else { #ifdef DIAGNOSTIC freshalloc = 0; #endif } freep = XSIMPLEQ_FIRST(&kbp->kb_freelist); XSIMPLEQ_REMOVE_HEAD(&kbp->kb_freelist, kf_flist); va = (caddr_t)freep; #ifdef DIAGNOSTIC savedtype = (unsigned)freep->kf_type < M_LAST ? memname[freep->kf_type] : "???"; if (freshalloc == 0 && XSIMPLEQ_FIRST(&kbp->kb_freelist)) { int rv; vaddr_t addr = (vaddr_t)XSIMPLEQ_FIRST(&kbp->kb_freelist); vm_map_lock(kmem_map); rv = uvm_map_checkprot(kmem_map, addr, addr + sizeof(struct kmem_freelist), PROT_WRITE); vm_map_unlock(kmem_map); if (!rv) { printf("%s %zd of object %p size 0x%lx %s %s" " (invalid addr %p)\n", "Data modified on freelist: word", (int32_t *)&addr - (int32_t *)kbp, va, size, "previous type", savedtype, (void *)addr); } } /* Fill the fields that we've used with poison */ poison_mem(freep, sizeof(*freep)); /* and check that the data hasn't been modified. */ if (freshalloc == 0) { size_t pidx; uint32_t pval; if (poison_check(va, allocsize, &pidx, &pval)) { panic("%s %zd of object %p size 0x%lx %s %s" " (0x%x != 0x%x)\n", "Data modified on freelist: word", pidx, va, size, "previous type", savedtype, ((int32_t*)va)[pidx], pval); } } freep->kf_spare0 = 0; #endif /* DIAGNOSTIC */ #ifdef KMEMSTATS kup = btokup(va); if (kup->ku_indx != indx) panic("malloc: wrong bucket"); if (kup->ku_freecnt == 0) panic("malloc: lost data"); kup->ku_freecnt--; kbp->kb_totalfree--; out: kbp->kb_calls++; ksp->ks_inuse++; ksp->ks_calls++; if (ksp->ks_memuse > ksp->ks_maxused) ksp->ks_maxused = ksp->ks_memuse; #else out: #endif mtx_leave(&malloc_mtx); if ((flags & M_ZERO) && va != NULL) memset(va, 0, size); TRACEPOINT(uvm, malloc, type, va, size, flags); return (va); } /* * Free a block of memory allocated by malloc. */ void free(void *addr, int type, size_t freedsize) { struct kmembuckets *kbp; struct kmemusage *kup; struct kmem_freelist *freep; long size; int s; #ifdef DIAGNOSTIC long alloc; #endif #ifdef KMEMSTATS struct kmemstats *ksp = &kmemstats[type]; int wake; #endif if (addr == NULL) return; #ifdef DIAGNOSTIC if (addr < (void *)kmembase || addr >= (void *)kmemlimit) panic("free: non-malloced addr %p type %s", addr, memname[type]); #endif TRACEPOINT(uvm, free, type, addr, freedsize); mtx_enter(&malloc_mtx); kup = btokup(addr); size = 1 << kup->ku_indx; kbp = &bucket[kup->ku_indx]; if (size > MAXALLOCSAVE) size = kup->ku_pagecnt << PAGE_SHIFT; #ifdef DIAGNOSTIC #if 0 if (freedsize == 0) { static int zerowarnings; if (zerowarnings < 5) { zerowarnings++; printf("free with zero size: (%d)\n", type); #ifdef DDB db_stack_dump(); #endif } #endif if (freedsize != 0 && freedsize > size) panic("free: size too large %zu > %ld (%p) type %s", freedsize, size, addr, memname[type]); if (freedsize != 0 && size > MINALLOCSIZE && freedsize <= size / 2) panic("free: size too small %zu <= %ld / 2 (%p) type %s", freedsize, size, addr, memname[type]); /* * Check for returns of data that do not point to the * beginning of the allocation. */ if (size > PAGE_SIZE) alloc = addrmask[BUCKETINDX(PAGE_SIZE)]; else alloc = addrmask[kup->ku_indx]; if (((u_long)addr & alloc) != 0) panic("free: unaligned addr %p, size %ld, type %s, mask %ld", addr, size, memname[type], alloc); #endif /* DIAGNOSTIC */ if (size > MAXALLOCSAVE) { u_short pagecnt = kup->ku_pagecnt; kup->ku_indx = 0; kup->ku_pagecnt = 0; mtx_leave(&malloc_mtx); s = splvm(); uvm_km_free(kmem_map, (vaddr_t)addr, ptoa(pagecnt)); splx(s); #ifdef KMEMSTATS mtx_enter(&malloc_mtx); ksp->ks_memuse -= size; wake = ksp->ks_memuse + size >= ksp->ks_limit && ksp->ks_memuse < ksp->ks_limit; ksp->ks_inuse--; kbp->kb_total -= 1; mtx_leave(&malloc_mtx); if (wake) wakeup(ksp); #endif return; } freep = (struct kmem_freelist *)addr; #ifdef DIAGNOSTIC /* * Check for multiple frees. Use a quick check to see if * it looks free before laboriously searching the freelist. */ if (freep->kf_spare0 == poison_value(freep)) { struct kmem_freelist *fp; XSIMPLEQ_FOREACH(fp, &kbp->kb_freelist, kf_flist) { if (addr != fp) continue; printf("multiply freed item %p\n", addr); panic("free: duplicated free"); } } /* * Copy in known text to detect modification after freeing * and to make it look free. Also, save the type being freed * so we can list likely culprit if modification is detected * when the object is reallocated. */ poison_mem(addr, size); freep->kf_spare0 = poison_value(freep); freep->kf_type = type; #endif /* DIAGNOSTIC */ #ifdef KMEMSTATS kup->ku_freecnt++; if (kup->ku_freecnt >= kbp->kb_elmpercl) { if (kup->ku_freecnt > kbp->kb_elmpercl) panic("free: multiple frees"); else if (kbp->kb_totalfree > kbp->kb_highwat) kbp->kb_couldfree++; } kbp->kb_totalfree++; ksp->ks_memuse -= size; wake = ksp->ks_memuse + size >= ksp->ks_limit && ksp->ks_memuse < ksp->ks_limit; ksp->ks_inuse--; #endif XSIMPLEQ_INSERT_TAIL(&kbp->kb_freelist, freep, kf_flist); mtx_leave(&malloc_mtx); #ifdef KMEMSTATS if (wake) wakeup(ksp); #endif } /* * Compute the number of pages that kmem_map will map, that is, * the size of the kernel malloc arena. */ void kmeminit_nkmempages(void) { u_int npages; if (nkmempages != -1) { /* * It's already been set (by us being here before, or * by patching or kernel config options), bail out now. */ return; } /* * We use the following (simple) formula: * * Up to 1G physmem use physical memory / 4, * above 1G add an extra 16MB per 1G of memory. * * Clamp it down depending on VM_KERNEL_SPACE_SIZE * - up and including 512M -> 64MB * - between 512M and 1024M -> 128MB * - over 1024M clamping to VM_KERNEL_SPACE_SIZE / 4 */ npages = MIN(physmem, atop(1024 * 1024 * 1024)) / 4; if (physmem > atop(1024 * 1024 * 1024)) npages += (physmem - atop(1024 * 1024 * 1024)) / 64; if (VM_KERNEL_SPACE_SIZE <= 512 * 1024 * 1024) { if (npages > atop(64 * 1024 * 1024)) npages = atop(64 * 1024 * 1024); } else if (VM_KERNEL_SPACE_SIZE <= 1024 * 1024 * 1024) { if (npages > atop(128 * 1024 * 1024)) npages = atop(128 * 1024 * 1024); } else if (npages > atop(VM_KERNEL_SPACE_SIZE) / 4) npages = atop(VM_KERNEL_SPACE_SIZE) / 4; nkmempages = npages; } /* * Initialize the kernel memory allocator */ void kmeminit(void) { vaddr_t base, limit; long indx; #ifdef DIAGNOSTIC if (sizeof(struct kmem_freelist) > (1 << MINBUCKET)) panic("kmeminit: minbucket too small/struct freelist too big"); #endif /* * Compute the number of kmem_map pages, if we have not * done so already. */ kmeminit_nkmempages(); base = vm_map_min(kernel_map); kmem_map = uvm_km_suballoc(kernel_map, &base, &limit, (vsize_t)nkmempages << PAGE_SHIFT, #ifdef KVA_GUARDPAGES VM_MAP_INTRSAFE | VM_MAP_GUARDPAGES, #else VM_MAP_INTRSAFE, #endif FALSE, &kmem_map_store); kmembase = (char *)base; kmemlimit = (char *)limit; kmemusage = km_alloc(round_page(nkmempages * sizeof(struct kmemusage)), &kv_any, &kp_zero, &kd_waitok); for (indx = 0; indx < MINBUCKET + 16; indx++) { XSIMPLEQ_INIT(&bucket[indx].kb_freelist); } #ifdef KMEMSTATS for (indx = 0; indx < MINBUCKET + 16; indx++) { if (1 << indx >= PAGE_SIZE) bucket[indx].kb_elmpercl = 1; else bucket[indx].kb_elmpercl = PAGE_SIZE / (1 << indx); bucket[indx].kb_highwat = 5 * bucket[indx].kb_elmpercl; } for (indx = 0; indx < M_LAST; indx++) kmemstats[indx].ks_limit = (long)nkmempages * PAGE_SIZE * 6 / 10; #endif } /* * Return kernel malloc statistics information. */ int sysctl_malloc(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { struct kmembuckets kb; #ifdef KMEMSTATS struct kmemstats km; #endif #if defined(KMEMSTATS) || defined(DIAGNOSTIC) int error; #endif int i, siz; if (namelen != 2 && name[0] != KERN_MALLOC_BUCKETS && name[0] != KERN_MALLOC_KMEMNAMES) return (ENOTDIR); /* overloaded */ switch (name[0]) { case KERN_MALLOC_BUCKETS: /* Initialize the first time */ if (buckstring_init == 0) { buckstring_init = 1; memset(buckstring, 0, sizeof(buckstring)); for (siz = 0, i = MINBUCKET; i < MINBUCKET + 16; i++) { snprintf(buckstring + siz, sizeof buckstring - siz, "%d,", (u_int)(1<<i)); siz += strlen(buckstring + siz); } /* Remove trailing comma */ if (siz) buckstring[siz - 1] = '\0'; } return (sysctl_rdstring(oldp, oldlenp, newp, buckstring)); case KERN_MALLOC_BUCKET: mtx_enter(&malloc_mtx); memcpy(&kb, &bucket[BUCKETINDX(name[1])], sizeof(kb)); mtx_leave(&malloc_mtx); memset(&kb.kb_freelist, 0, sizeof(kb.kb_freelist)); return (sysctl_rdstruct(oldp, oldlenp, newp, &kb, sizeof(kb))); case KERN_MALLOC_KMEMSTATS: #ifdef KMEMSTATS if ((name[1] < 0) || (name[1] >= M_LAST)) return (EINVAL); mtx_enter(&malloc_mtx); memcpy(&km, &kmemstats[name[1]], sizeof(km)); mtx_leave(&malloc_mtx); return (sysctl_rdstruct(oldp, oldlenp, newp, &km, sizeof(km))); #else return (EOPNOTSUPP); #endif case KERN_MALLOC_KMEMNAMES: #if defined(KMEMSTATS) || defined(DIAGNOSTIC) error = rw_enter(&sysctl_kmemlock, RW_WRITE|RW_INTR); if (error) return (error); if (memall == NULL) { int totlen; /* Figure out how large a buffer we need */ for (totlen = 0, i = 0; i < M_LAST; i++) { if (memname[i]) totlen += strlen(memname[i]); totlen++; } memall = malloc(totlen + M_LAST, M_SYSCTL, M_WAITOK|M_ZERO); for (siz = 0, i = 0; i < M_LAST; i++) { snprintf(memall + siz, totlen + M_LAST - siz, "%s,", memname[i] ? memname[i] : ""); siz += strlen(memall + siz); } /* Remove trailing comma */ if (siz) memall[siz - 1] = '\0'; /* Now, convert all spaces to underscores */ for (i = 0; i < totlen; i++) if (memall[i] == ' ') memall[i] = '_'; } rw_exit_write(&sysctl_kmemlock); return (sysctl_rdstring(oldp, oldlenp, newp, memall)); #else return (EOPNOTSUPP); #endif default: return (EOPNOTSUPP); } /* NOTREACHED */ } #if defined(DDB) void malloc_printit( int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2)))) { #ifdef KMEMSTATS struct kmemstats *km; int i; (*pr)("%15s %5s %6s %7s %6s %9s %8s\n", "Type", "InUse", "MemUse", "HighUse", "Limit", "Requests", "Type Lim"); for (i = 0, km = kmemstats; i < M_LAST; i++, km++) { if (!km->ks_calls || !memname[i]) continue; (*pr)("%15s %5ld %6ldK %7ldK %6ldK %9ld %8d\n", memname[i], km->ks_inuse, km->ks_memuse / 1024, km->ks_maxused / 1024, km->ks_limit / 1024, km->ks_calls, km->ks_limblocks); } #else (*pr)("No KMEMSTATS compiled in\n"); #endif } #endif /* DDB */ /* * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW */ #define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4)) void * mallocarray(size_t nmemb, size_t size, int type, int flags) { if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && nmemb > 0 && SIZE_MAX / nmemb < size) { if (flags & M_CANFAIL) return (NULL); panic("mallocarray: overflow %zu * %zu", nmemb, size); } return (malloc(size * nmemb, type, flags)); }
3 11 1 22 22 21 1 20 10 11 21 17 6 17 6 11 5 2 2 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 /* $OpenBSD: igmp.c,v 1.83 2023/09/16 09:33:27 mpi Exp $ */ /* $NetBSD: igmp.c,v 1.15 1996/02/13 23:41:25 christos Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 1988 Stephen Deering. * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Stephen Deering of Stanford University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)igmp.c 8.2 (Berkeley) 5/3/95 */ /* * Internet Group Management Protocol (IGMP) routines. * * Written by Steve Deering, Stanford, May 1988. * Modified by Rosen Sharma, Stanford, Aug 1994. * Modified by Bill Fenner, Xerox PARC, Feb 1995. * * MULTICAST Revision: 1.3 */ #include <sys/param.h> #include <sys/mbuf.h> #include <sys/systm.h> #include <sys/socket.h> #include <sys/protosw.h> #include <sys/sysctl.h> #include <net/if.h> #include <net/if_var.h> #include <netinet/in.h> #include <netinet/in_var.h> #include <netinet/ip.h> #include <netinet/ip_var.h> #include <netinet/igmp.h> #include <netinet/igmp_var.h> #include <sys/stdarg.h> #define IP_MULTICASTOPTS 0 int igmp_timers_are_running; /* [N] shortcut for fast timer */ static LIST_HEAD(, router_info) rti_head; static struct mbuf *router_alert; struct cpumem *igmpcounters; void igmp_checktimer(struct ifnet *); void igmp_sendpkt(struct ifnet *, struct in_multi *, int, in_addr_t); int rti_fill(struct in_multi *); struct router_info * rti_find(struct ifnet *); int igmp_input_if(struct ifnet *, struct mbuf **, int *, int, int); int igmp_sysctl_igmpstat(void *, size_t *, void *); void igmp_init(void) { struct ipoption *ra; igmp_timers_are_running = 0; LIST_INIT(&rti_head); igmpcounters = counters_alloc(igps_ncounters); router_alert = m_get(M_WAIT, MT_DATA); /* * Construct a Router Alert option (RAO) to use in report * messages as required by RFC2236. This option has the * following format: * * | 10010100 | 00000100 | 2 octet value | * * where a value of "0" indicates that routers shall examine * the packet. */ ra = mtod(router_alert, struct ipoption *); ra->ipopt_dst.s_addr = INADDR_ANY; ra->ipopt_list[0] = IPOPT_RA; ra->ipopt_list[1] = 0x04; ra->ipopt_list[2] = 0x00; ra->ipopt_list[3] = 0x00; router_alert->m_len = sizeof(ra->ipopt_dst) + ra->ipopt_list[1]; } int rti_fill(struct in_multi *inm) { struct router_info *rti; LIST_FOREACH(rti, &rti_head, rti_list) { if (rti->rti_ifidx == inm->inm_ifidx) { inm->inm_rti = rti; if (rti->rti_type == IGMP_v1_ROUTER) return (IGMP_v1_HOST_MEMBERSHIP_REPORT); else return (IGMP_v2_HOST_MEMBERSHIP_REPORT); } } rti = malloc(sizeof(*rti), M_MRTABLE, M_WAITOK); rti->rti_ifidx = inm->inm_ifidx; rti->rti_type = IGMP_v2_ROUTER; LIST_INSERT_HEAD(&rti_head, rti, rti_list); inm->inm_rti = rti; return (IGMP_v2_HOST_MEMBERSHIP_REPORT); } struct router_info * rti_find(struct ifnet *ifp) { struct router_info *rti; KERNEL_ASSERT_LOCKED(); LIST_FOREACH(rti, &rti_head, rti_list) { if (rti->rti_ifidx == ifp->if_index) return (rti); } rti = malloc(sizeof(*rti), M_MRTABLE, M_NOWAIT); if (rti == NULL) return (NULL); rti->rti_ifidx = ifp->if_index; rti->rti_type = IGMP_v2_ROUTER; LIST_INSERT_HEAD(&rti_head, rti, rti_list); return (rti); } void rti_delete(struct ifnet *ifp) { struct router_info *rti, *trti; LIST_FOREACH_SAFE(rti, &rti_head, rti_list, trti) { if (rti->rti_ifidx == ifp->if_index) { LIST_REMOVE(rti, rti_list); free(rti, M_MRTABLE, sizeof(*rti)); break; } } } int igmp_input(struct mbuf **mp, int *offp, int proto, int af) { struct ifnet *ifp; igmpstat_inc(igps_rcv_total); ifp = if_get((*mp)->m_pkthdr.ph_ifidx); if (ifp == NULL) { m_freemp(mp); return IPPROTO_DONE; } KERNEL_LOCK(); proto = igmp_input_if(ifp, mp, offp, proto, af); KERNEL_UNLOCK(); if_put(ifp); return proto; } int igmp_input_if(struct ifnet *ifp, struct mbuf **mp, int *offp, int proto, int af) { struct mbuf *m = *mp; int iphlen = *offp; struct ip *ip = mtod(m, struct ip *); struct igmp *igmp; int igmplen; int minlen; struct ifmaddr *ifma; struct in_multi *inm; struct router_info *rti; struct in_ifaddr *ia; int timer; igmplen = ntohs(ip->ip_len) - iphlen; /* * Validate lengths */ if (igmplen < IGMP_MINLEN) { igmpstat_inc(igps_rcv_tooshort); m_freem(m); return IPPROTO_DONE; } minlen = iphlen + IGMP_MINLEN; if ((m->m_flags & M_EXT || m->m_len < minlen) && (m = *mp = m_pullup(m, minlen)) == NULL) { igmpstat_inc(igps_rcv_tooshort); return IPPROTO_DONE; } /* * Validate checksum */ m->m_data += iphlen; m->m_len -= iphlen; igmp = mtod(m, struct igmp *); if (in_cksum(m, igmplen)) { igmpstat_inc(igps_rcv_badsum); m_freem(m); return IPPROTO_DONE; } m->m_data -= iphlen; m->m_len += iphlen; ip = mtod(m, struct ip *); switch (igmp->igmp_type) { case IGMP_HOST_MEMBERSHIP_QUERY: igmpstat_inc(igps_rcv_queries); if (ifp->if_flags & IFF_LOOPBACK) break; if (igmp->igmp_code == 0) { rti = rti_find(ifp); if (rti == NULL) { m_freem(m); return IPPROTO_DONE; } rti->rti_type = IGMP_v1_ROUTER; rti->rti_age = 0; if (ip->ip_dst.s_addr != INADDR_ALLHOSTS_GROUP) { igmpstat_inc(igps_rcv_badqueries); m_freem(m); return IPPROTO_DONE; } /* * Start the timers in all of our membership records * for the interface on which the query arrived, * except those that are already running and those * that belong to a "local" group (224.0.0.X). */ TAILQ_FOREACH(ifma, &ifp->if_maddrlist, ifma_list) { if (ifma->ifma_addr->sa_family != AF_INET) continue; inm = ifmatoinm(ifma); if (inm->inm_timer == 0 && !IN_LOCAL_GROUP(inm->inm_addr.s_addr)) { inm->inm_state = IGMP_DELAYING_MEMBER; inm->inm_timer = IGMP_RANDOM_DELAY( IGMP_MAX_HOST_REPORT_DELAY * PR_FASTHZ); igmp_timers_are_running = 1; } } } else { if (!IN_MULTICAST(ip->ip_dst.s_addr)) { igmpstat_inc(igps_rcv_badqueries); m_freem(m); return IPPROTO_DONE; } timer = igmp->igmp_code * PR_FASTHZ / IGMP_TIMER_SCALE; if (timer == 0) timer = 1; /* * Start the timers in all of our membership records * for the interface on which the query arrived, * except those that are already running and those * that belong to a "local" group (224.0.0.X). For * timers already running, check if they need to be * reset. */ TAILQ_FOREACH(ifma, &ifp->if_maddrlist, ifma_list) { if (ifma->ifma_addr->sa_family != AF_INET) continue; inm = ifmatoinm(ifma); if (!IN_LOCAL_GROUP(inm->inm_addr.s_addr) && (ip->ip_dst.s_addr == INADDR_ALLHOSTS_GROUP || ip->ip_dst.s_addr == inm->inm_addr.s_addr)) { switch (inm->inm_state) { case IGMP_DELAYING_MEMBER: if (inm->inm_timer <= timer) break; /* FALLTHROUGH */ case IGMP_IDLE_MEMBER: case IGMP_LAZY_MEMBER: case IGMP_AWAKENING_MEMBER: inm->inm_state = IGMP_DELAYING_MEMBER; inm->inm_timer = IGMP_RANDOM_DELAY(timer); igmp_timers_are_running = 1; break; case IGMP_SLEEPING_MEMBER: inm->inm_state = IGMP_AWAKENING_MEMBER; break; } } } } break; case IGMP_v1_HOST_MEMBERSHIP_REPORT: igmpstat_inc(igps_rcv_reports); if (ifp->if_flags & IFF_LOOPBACK) break; if (!IN_MULTICAST(igmp->igmp_group.s_addr) || igmp->igmp_group.s_addr != ip->ip_dst.s_addr) { igmpstat_inc(igps_rcv_badreports); m_freem(m); return IPPROTO_DONE; } /* * KLUDGE: if the IP source address of the report has an * unspecified (i.e., zero) subnet number, as is allowed for * a booting host, replace it with the correct subnet number * so that a process-level multicast routing daemon can * determine which subnet it arrived from. This is necessary * to compensate for the lack of any way for a process to * determine the arrival interface of an incoming packet. */ if ((ip->ip_src.s_addr & IN_CLASSA_NET) == 0) { IFP_TO_IA(ifp, ia); if (ia) ip->ip_src.s_addr = ia->ia_net; } /* * If we belong to the group being reported, stop * our timer for that group. */ IN_LOOKUP_MULTI(igmp->igmp_group, ifp, inm); if (inm != NULL) { inm->inm_timer = 0; igmpstat_inc(igps_rcv_ourreports); switch (inm->inm_state) { case IGMP_IDLE_MEMBER: case IGMP_LAZY_MEMBER: case IGMP_AWAKENING_MEMBER: case IGMP_SLEEPING_MEMBER: inm->inm_state = IGMP_SLEEPING_MEMBER; break; case IGMP_DELAYING_MEMBER: if (inm->inm_rti->rti_type == IGMP_v1_ROUTER) inm->inm_state = IGMP_LAZY_MEMBER; else inm->inm_state = IGMP_SLEEPING_MEMBER; break; } } break; case IGMP_v2_HOST_MEMBERSHIP_REPORT: #ifdef MROUTING /* * Make sure we don't hear our own membership report. Fast * leave requires knowing that we are the only member of a * group. */ IFP_TO_IA(ifp, ia); if (ia && ip->ip_src.s_addr == ia->ia_addr.sin_addr.s_addr) break; #endif igmpstat_inc(igps_rcv_reports); if (ifp->if_flags & IFF_LOOPBACK) break; if (!IN_MULTICAST(igmp->igmp_group.s_addr) || igmp->igmp_group.s_addr != ip->ip_dst.s_addr) { igmpstat_inc(igps_rcv_badreports); m_freem(m); return IPPROTO_DONE; } /* * KLUDGE: if the IP source address of the report has an * unspecified (i.e., zero) subnet number, as is allowed for * a booting host, replace it with the correct subnet number * so that a process-level multicast routing daemon can * determine which subnet it arrived from. This is necessary * to compensate for the lack of any way for a process to * determine the arrival interface of an incoming packet. */ if ((ip->ip_src.s_addr & IN_CLASSA_NET) == 0) { #ifndef MROUTING IFP_TO_IA(ifp, ia); #endif if (ia) ip->ip_src.s_addr = ia->ia_net; } /* * If we belong to the group being reported, stop * our timer for that group. */ IN_LOOKUP_MULTI(igmp->igmp_group, ifp, inm); if (inm != NULL) { inm->inm_timer = 0; igmpstat_inc(igps_rcv_ourreports); switch (inm->inm_state) { case IGMP_DELAYING_MEMBER: case IGMP_IDLE_MEMBER: case IGMP_AWAKENING_MEMBER: inm->inm_state = IGMP_LAZY_MEMBER; break; case IGMP_LAZY_MEMBER: case IGMP_SLEEPING_MEMBER: break; } } break; } /* * Pass all valid IGMP packets up to any process(es) listening * on a raw IGMP socket. */ return rip_input(mp, offp, proto, af); } void igmp_joingroup(struct in_multi *inm, struct ifnet *ifp) { int i; inm->inm_state = IGMP_IDLE_MEMBER; if (!IN_LOCAL_GROUP(inm->inm_addr.s_addr) && (ifp->if_flags & IFF_LOOPBACK) == 0) { i = rti_fill(inm); igmp_sendpkt(ifp, inm, i, 0); inm->inm_state = IGMP_DELAYING_MEMBER; inm->inm_timer = IGMP_RANDOM_DELAY( IGMP_MAX_HOST_REPORT_DELAY * PR_FASTHZ); igmp_timers_are_running = 1; } else inm->inm_timer = 0; } void igmp_leavegroup(struct in_multi *inm, struct ifnet *ifp) { switch (inm->inm_state) { case IGMP_DELAYING_MEMBER: case IGMP_IDLE_MEMBER: if (!IN_LOCAL_GROUP(inm->inm_addr.s_addr) && (ifp->if_flags & IFF_LOOPBACK) == 0) if (inm->inm_rti->rti_type != IGMP_v1_ROUTER) igmp_sendpkt(ifp, inm, IGMP_HOST_LEAVE_MESSAGE, INADDR_ALLROUTERS_GROUP); break; case IGMP_LAZY_MEMBER: case IGMP_AWAKENING_MEMBER: case IGMP_SLEEPING_MEMBER: break; } } void igmp_fasttimo(void) { struct ifnet *ifp; /* * Quick check to see if any work needs to be done, in order * to minimize the overhead of fasttimo processing. * Variable igmp_timers_are_running is read atomically, but without * lock intentionally. In case it is not set due to MP races, we may * miss to check the timers. Then run the loop at next fast timeout. */ if (!igmp_timers_are_running) return; NET_LOCK(); igmp_timers_are_running = 0; TAILQ_FOREACH(ifp, &ifnetlist, if_list) igmp_checktimer(ifp); NET_UNLOCK(); } void igmp_checktimer(struct ifnet *ifp) { struct in_multi *inm; struct ifmaddr *ifma; NET_ASSERT_LOCKED(); TAILQ_FOREACH(ifma, &ifp->if_maddrlist, ifma_list) { if (ifma->ifma_addr->sa_family != AF_INET) continue; inm = ifmatoinm(ifma); if (inm->inm_timer == 0) { /* do nothing */ } else if (--inm->inm_timer == 0) { if (inm->inm_state == IGMP_DELAYING_MEMBER) { if (inm->inm_rti->rti_type == IGMP_v1_ROUTER) igmp_sendpkt(ifp, inm, IGMP_v1_HOST_MEMBERSHIP_REPORT, 0); else igmp_sendpkt(ifp, inm, IGMP_v2_HOST_MEMBERSHIP_REPORT, 0); inm->inm_state = IGMP_IDLE_MEMBER; } } else { igmp_timers_are_running = 1; } } } void igmp_slowtimo(void) { struct router_info *rti; NET_LOCK(); LIST_FOREACH(rti, &rti_head, rti_list) { if (rti->rti_type == IGMP_v1_ROUTER && ++rti->rti_age >= IGMP_AGE_THRESHOLD) { rti->rti_type = IGMP_v2_ROUTER; } } NET_UNLOCK(); } void igmp_sendpkt(struct ifnet *ifp, struct in_multi *inm, int type, in_addr_t addr) { struct mbuf *m; struct igmp *igmp; struct ip *ip; struct ip_moptions imo; MGETHDR(m, M_DONTWAIT, MT_HEADER); if (m == NULL) return; /* * Assume max_linkhdr + sizeof(struct ip) + IGMP_MINLEN * is smaller than mbuf size returned by MGETHDR. */ m->m_data += max_linkhdr; m->m_len = sizeof(struct ip) + IGMP_MINLEN; m->m_pkthdr.len = sizeof(struct ip) + IGMP_MINLEN; ip = mtod(m, struct ip *); ip->ip_tos = 0; ip->ip_len = htons(sizeof(struct ip) + IGMP_MINLEN); ip->ip_off = 0; ip->ip_p = IPPROTO_IGMP; ip->ip_src.s_addr = INADDR_ANY; if (addr) { ip->ip_dst.s_addr = addr; } else { ip->ip_dst = inm->inm_addr; } m->m_data += sizeof(struct ip); m->m_len -= sizeof(struct ip); igmp = mtod(m, struct igmp *); igmp->igmp_type = type; igmp->igmp_code = 0; igmp->igmp_group = inm->inm_addr; igmp->igmp_cksum = 0; igmp->igmp_cksum = in_cksum(m, IGMP_MINLEN); m->m_data -= sizeof(struct ip); m->m_len += sizeof(struct ip); m->m_pkthdr.ph_rtableid = ifp->if_rdomain; imo.imo_ifidx = inm->inm_ifidx; imo.imo_ttl = 1; /* * Request loopback of the report if we are acting as a multicast * router, so that the process-level routing daemon can hear it. */ #ifdef MROUTING imo.imo_loop = (ip_mrouter[ifp->if_rdomain] != NULL); #else imo.imo_loop = 0; #endif /* MROUTING */ ip_output(m, router_alert, NULL, IP_MULTICASTOPTS, &imo, NULL, 0); igmpstat_inc(igps_snd_reports); } /* * Sysctl for igmp variables. */ int igmp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { /* All sysctl names at this level are terminal. */ if (namelen != 1) return (ENOTDIR); switch (name[0]) { case IGMPCTL_STATS: if (newp != NULL) return (EPERM); return (igmp_sysctl_igmpstat(oldp, oldlenp, newp)); default: return (EOPNOTSUPP); } /* NOTREACHED */ } int igmp_sysctl_igmpstat(void *oldp, size_t *oldlenp, void *newp) { uint64_t counters[igps_ncounters]; struct igmpstat igmpstat; u_long *words = (u_long *)&igmpstat; int i; CTASSERT(sizeof(igmpstat) == (nitems(counters) * sizeof(u_long))); memset(&igmpstat, 0, sizeof igmpstat); counters_read(igmpcounters, counters, nitems(counters), NULL); for (i = 0; i < nitems(counters); i++) words[i] = (u_long)counters[i]; return (sysctl_rdstruct(oldp, oldlenp, newp, &igmpstat, sizeof(igmpstat))); }
25 25 25 3 2 3 2 4 1 17 4 16 2 18 11 25 10 5 12 8 4 12 154 153 1 1 1 36 22 20 21 12 11 23 20 11 9 3 9 7 7 1 6 6 6 7 4 10 10 10 4 7 7 4 9 30 10 10 10 10 543 517 469 208 475 545 65 3 3 30 63 94 94 24 76 72 4 76 65 10 75 72 4 6 30 47 76 72 3 3 701 624 84 8 685 617 80 8 3 3 3 3 3 3 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 /* $OpenBSD: uvm_vnode.c,v 1.132 2023/04/10 04:21:20 jsg Exp $ */ /* $NetBSD: uvm_vnode.c,v 1.36 2000/11/24 20:34:01 chs Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. * Copyright (c) 1991, 1993 * The Regents of the University of California. * Copyright (c) 1990 University of Utah. * * All rights reserved. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)vnode_pager.c 8.8 (Berkeley) 2/13/94 * from: Id: uvm_vnode.c,v 1.1.2.26 1998/02/02 20:38:07 chuck Exp */ /* * uvm_vnode.c: the vnode pager. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/malloc.h> #include <sys/vnode.h> #include <sys/lock.h> #include <sys/disklabel.h> #include <sys/fcntl.h> #include <sys/conf.h> #include <sys/rwlock.h> #include <sys/dkio.h> #include <sys/specdev.h> #include <uvm/uvm.h> #include <uvm/uvm_vnode.h> /* * private global data structure * * we keep a list of writeable active vnode-backed VM objects for sync op. * we keep a simpleq of vnodes that are currently being sync'd. */ LIST_HEAD(, uvm_vnode) uvn_wlist; /* [K] writeable uvns */ SIMPLEQ_HEAD(, uvm_vnode) uvn_sync_q; /* [S] sync'ing uvns */ struct rwlock uvn_sync_lock; /* locks sync operation */ extern int rebooting; /* * functions */ void uvn_cluster(struct uvm_object *, voff_t, voff_t *, voff_t *); void uvn_detach(struct uvm_object *); boolean_t uvn_flush(struct uvm_object *, voff_t, voff_t, int); int uvn_get(struct uvm_object *, voff_t, vm_page_t *, int *, int, vm_prot_t, int, int); void uvn_init(void); int uvn_io(struct uvm_vnode *, vm_page_t *, int, int, int); int uvn_put(struct uvm_object *, vm_page_t *, int, boolean_t); void uvn_reference(struct uvm_object *); /* * master pager structure */ const struct uvm_pagerops uvm_vnodeops = { .pgo_init = uvn_init, .pgo_reference = uvn_reference, .pgo_detach = uvn_detach, .pgo_flush = uvn_flush, .pgo_get = uvn_get, .pgo_put = uvn_put, .pgo_cluster = uvn_cluster, /* use generic version of this: see uvm_pager.c */ .pgo_mk_pcluster = uvm_mk_pcluster, }; /* * the ops! */ /* * uvn_init * * init pager private data structures. */ void uvn_init(void) { LIST_INIT(&uvn_wlist); /* note: uvn_sync_q init'd in uvm_vnp_sync() */ rw_init_flags(&uvn_sync_lock, "uvnsync", RWL_IS_VNODE); } /* * uvn_attach * * attach a vnode structure to a VM object. if the vnode is already * attached, then just bump the reference count by one and return the * VM object. if not already attached, attach and return the new VM obj. * the "accessprot" tells the max access the attaching thread wants to * our pages. * * => in fact, nothing should be locked so that we can sleep here. * => note that uvm_object is first thing in vnode structure, so their * pointers are equiv. */ struct uvm_object * uvn_attach(struct vnode *vp, vm_prot_t accessprot) { struct uvm_vnode *uvn = vp->v_uvm; struct vattr vattr; int oldflags, result; struct partinfo pi; u_quad_t used_vnode_size = 0; /* if we're mapping a BLK device, make sure it is a disk. */ if (vp->v_type == VBLK && bdevsw[major(vp->v_rdev)].d_type != D_DISK) { return NULL; } /* first get a lock on the uvn. */ rw_enter(uvn->u_obj.vmobjlock, RW_WRITE); while (uvn->u_flags & UVM_VNODE_BLOCKED) { uvn->u_flags |= UVM_VNODE_WANTED; rwsleep_nsec(uvn, uvn->u_obj.vmobjlock, PVM, "uvn_attach", INFSLP); } /* * now uvn must not be in a blocked state. * first check to see if it is already active, in which case * we can bump the reference count, check to see if we need to * add it to the writeable list, and then return. */ if (uvn->u_flags & UVM_VNODE_VALID) { /* already active? */ /* regain vref if we were persisting */ if (uvn->u_obj.uo_refs == 0) { vref(vp); } uvn->u_obj.uo_refs++; /* bump uvn ref! */ /* check for new writeable uvn */ if ((accessprot & PROT_WRITE) != 0 && (uvn->u_flags & UVM_VNODE_WRITEABLE) == 0) { uvn->u_flags |= UVM_VNODE_WRITEABLE; KERNEL_ASSERT_LOCKED(); LIST_INSERT_HEAD(&uvn_wlist, uvn, u_wlist); } rw_exit(uvn->u_obj.vmobjlock); return (&uvn->u_obj); } /* * need to call VOP_GETATTR() to get the attributes, but that could * block (due to I/O), so we want to unlock the object before calling. * however, we want to keep anyone else from playing with the object * while it is unlocked. to do this we set UVM_VNODE_ALOCK which * prevents anyone from attaching to the vnode until we are done with * it. */ uvn->u_flags = UVM_VNODE_ALOCK; rw_exit(uvn->u_obj.vmobjlock); if (vp->v_type == VBLK) { /* * We could implement this as a specfs getattr call, but: * * (1) VOP_GETATTR() would get the file system * vnode operation, not the specfs operation. * * (2) All we want is the size, anyhow. */ result = (*bdevsw[major(vp->v_rdev)].d_ioctl)(vp->v_rdev, DIOCGPART, (caddr_t)&pi, FREAD, curproc); if (result == 0) { /* XXX should remember blocksize */ used_vnode_size = (u_quad_t)pi.disklab->d_secsize * (u_quad_t)DL_GETPSIZE(pi.part); } } else { result = VOP_GETATTR(vp, &vattr, curproc->p_ucred, curproc); if (result == 0) used_vnode_size = vattr.va_size; } if (result != 0) { rw_enter(uvn->u_obj.vmobjlock, RW_WRITE); if (uvn->u_flags & UVM_VNODE_WANTED) wakeup(uvn); uvn->u_flags = 0; rw_exit(uvn->u_obj.vmobjlock); return NULL; } /* * make sure that the newsize fits within a vaddr_t * XXX: need to revise addressing data types */ #ifdef DEBUG if (vp->v_type == VBLK) printf("used_vnode_size = %llu\n", (long long)used_vnode_size); #endif /* now set up the uvn. */ KASSERT(uvn->u_obj.uo_refs == 0); uvn->u_obj.uo_refs++; oldflags = uvn->u_flags; uvn->u_flags = UVM_VNODE_VALID|UVM_VNODE_CANPERSIST; uvn->u_nio = 0; uvn->u_size = used_vnode_size; /* * add a reference to the vnode. this reference will stay as long * as there is a valid mapping of the vnode. dropped when the * reference count goes to zero [and we either free or persist]. */ vref(vp); /* if write access, we need to add it to the wlist */ if (accessprot & PROT_WRITE) { uvn->u_flags |= UVM_VNODE_WRITEABLE; /* we are on wlist! */ KERNEL_ASSERT_LOCKED(); LIST_INSERT_HEAD(&uvn_wlist, uvn, u_wlist); } if (oldflags & UVM_VNODE_WANTED) wakeup(uvn); return &uvn->u_obj; } /* * uvn_reference * * duplicate a reference to a VM object. Note that the reference * count must already be at least one (the passed in reference) so * there is no chance of the uvn being killed out here. * * => caller must be using the same accessprot as was used at attach time */ void uvn_reference(struct uvm_object *uobj) { #ifdef DEBUG struct uvm_vnode *uvn = (struct uvm_vnode *) uobj; #endif rw_enter(uobj->vmobjlock, RW_WRITE); #ifdef DEBUG if ((uvn->u_flags & UVM_VNODE_VALID) == 0) { printf("uvn_reference: ref=%d, flags=0x%x\n", uobj->uo_refs, uvn->u_flags); panic("uvn_reference: invalid state"); } #endif uobj->uo_refs++; rw_exit(uobj->vmobjlock); } /* * uvn_detach * * remove a reference to a VM object. * * => caller must call with map locked. * => this starts the detach process, but doesn't have to finish it * (async i/o could still be pending). */ void uvn_detach(struct uvm_object *uobj) { struct uvm_vnode *uvn; struct vnode *vp; int oldflags; rw_enter(uobj->vmobjlock, RW_WRITE); uobj->uo_refs--; /* drop ref! */ if (uobj->uo_refs) { /* still more refs */ rw_exit(uobj->vmobjlock); return; } /* get other pointers ... */ uvn = (struct uvm_vnode *) uobj; vp = uvn->u_vnode; /* * clear VTEXT flag now that there are no mappings left (VTEXT is used * to keep an active text file from being overwritten). */ vp->v_flag &= ~VTEXT; /* * we just dropped the last reference to the uvn. see if we can * let it "stick around". */ if (uvn->u_flags & UVM_VNODE_CANPERSIST) { /* won't block */ uvn_flush(uobj, 0, 0, PGO_DEACTIVATE|PGO_ALLPAGES); goto out; } /* its a goner! */ uvn->u_flags |= UVM_VNODE_DYING; /* * even though we may unlock in flush, no one can gain a reference * to us until we clear the "dying" flag [because it blocks * attaches]. we will not do that until after we've disposed of all * the pages with uvn_flush(). note that before the flush the only * pages that could be marked PG_BUSY are ones that are in async * pageout by the daemon. (there can't be any pending "get"'s * because there are no references to the object). */ (void) uvn_flush(uobj, 0, 0, PGO_CLEANIT|PGO_FREE|PGO_ALLPAGES); /* * given the structure of this pager, the above flush request will * create the following state: all the pages that were in the object * have either been free'd or they are marked PG_BUSY and in the * middle of an async io. If we still have pages we set the "relkill" * state, so that in the case the vnode gets terminated we know * to leave it alone. Otherwise we'll kill the vnode when it's empty. */ uvn->u_flags |= UVM_VNODE_RELKILL; /* wait on any outstanding io */ while (uobj->uo_npages && uvn->u_flags & UVM_VNODE_RELKILL) { uvn->u_flags |= UVM_VNODE_IOSYNC; rwsleep_nsec(&uvn->u_nio, uobj->vmobjlock, PVM, "uvn_term", INFSLP); } if ((uvn->u_flags & UVM_VNODE_RELKILL) == 0) { rw_exit(uobj->vmobjlock); return; } /* * kill object now. note that we can't be on the sync q because * all references are gone. */ if (uvn->u_flags & UVM_VNODE_WRITEABLE) { LIST_REMOVE(uvn, u_wlist); } KASSERT(RBT_EMPTY(uvm_objtree, &uobj->memt)); oldflags = uvn->u_flags; uvn->u_flags = 0; /* wake up any sleepers */ if (oldflags & UVM_VNODE_WANTED) wakeup(uvn); out: rw_exit(uobj->vmobjlock); /* drop our reference to the vnode. */ vrele(vp); return; } /* * uvm_vnp_terminate: external hook to clear out a vnode's VM * * called in two cases: * [1] when a persisting vnode vm object (i.e. one with a zero reference * count) needs to be freed so that a vnode can be reused. this * happens under "getnewvnode" in vfs_subr.c. if the vnode from * the free list is still attached (i.e. not VBAD) then vgone is * called. as part of the vgone trace this should get called to * free the vm object. this is the common case. * [2] when a filesystem is being unmounted by force (MNT_FORCE, * "umount -f") the vgone() function is called on active vnodes * on the mounted file systems to kill their data (the vnodes become * "dead" ones [see src/sys/miscfs/deadfs/...]). that results in a * call here (even if the uvn is still in use -- i.e. has a non-zero * reference count). this case happens at "umount -f" and during a * "reboot/halt" operation. * * => the caller must XLOCK and VOP_LOCK the vnode before calling us * [protects us from getting a vnode that is already in the DYING * state...] * => in case [2] the uvn is still alive after this call, but all I/O * ops will fail (due to the backing vnode now being "dead"). this * will prob. kill any process using the uvn due to pgo_get failing. */ void uvm_vnp_terminate(struct vnode *vp) { struct uvm_vnode *uvn = vp->v_uvm; struct uvm_object *uobj = &uvn->u_obj; int oldflags; /* check if it is valid */ rw_enter(uobj->vmobjlock, RW_WRITE); if ((uvn->u_flags & UVM_VNODE_VALID) == 0) { rw_exit(uobj->vmobjlock); return; } /* * must be a valid uvn that is not already dying (because XLOCK * protects us from that). the uvn can't in the ALOCK state * because it is valid, and uvn's that are in the ALOCK state haven't * been marked valid yet. */ #ifdef DEBUG /* * debug check: are we yanking the vnode out from under our uvn? */ if (uvn->u_obj.uo_refs) { printf("uvm_vnp_terminate(%p): terminating active vnode " "(refs=%d)\n", uvn, uvn->u_obj.uo_refs); } #endif /* * it is possible that the uvn was detached and is in the relkill * state [i.e. waiting for async i/o to finish]. * we take over the vnode now and cancel the relkill. * we want to know when the i/o is done so we can recycle right * away. note that a uvn can only be in the RELKILL state if it * has a zero reference count. */ if (uvn->u_flags & UVM_VNODE_RELKILL) uvn->u_flags &= ~UVM_VNODE_RELKILL; /* cancel RELKILL */ /* * block the uvn by setting the dying flag, and then flush the * pages. * * also, note that we tell I/O that we are already VOP_LOCK'd so * that uvn_io doesn't attempt to VOP_LOCK again. * * XXXCDC: setting VNISLOCKED on an active uvn which is being terminated * due to a forceful unmount might not be a good idea. maybe we * need a way to pass in this info to uvn_flush through a * pager-defined PGO_ constant [currently there are none]. */ uvn->u_flags |= UVM_VNODE_DYING|UVM_VNODE_VNISLOCKED; (void) uvn_flush(&uvn->u_obj, 0, 0, PGO_CLEANIT|PGO_FREE|PGO_ALLPAGES); /* * as we just did a flush we expect all the pages to be gone or in * the process of going. sleep to wait for the rest to go [via iosync]. */ while (uvn->u_obj.uo_npages) { #ifdef DEBUG struct vm_page *pp; RBT_FOREACH(pp, uvm_objtree, &uvn->u_obj.memt) { if ((pp->pg_flags & PG_BUSY) == 0) panic("uvm_vnp_terminate: detected unbusy pg"); } if (uvn->u_nio == 0) panic("uvm_vnp_terminate: no I/O to wait for?"); printf("uvm_vnp_terminate: waiting for I/O to fin.\n"); /* * XXXCDC: this is unlikely to happen without async i/o so we * put a printf in just to keep an eye on it. */ #endif uvn->u_flags |= UVM_VNODE_IOSYNC; rwsleep_nsec(&uvn->u_nio, uobj->vmobjlock, PVM, "uvn_term", INFSLP); } /* * done. now we free the uvn if its reference count is zero * (true if we are zapping a persisting uvn). however, if we are * terminating a uvn with active mappings we let it live ... future * calls down to the vnode layer will fail. */ oldflags = uvn->u_flags; if (uvn->u_obj.uo_refs) { /* * uvn must live on it is dead-vnode state until all references * are gone. restore flags. clear CANPERSIST state. */ uvn->u_flags &= ~(UVM_VNODE_DYING|UVM_VNODE_VNISLOCKED| UVM_VNODE_WANTED|UVM_VNODE_CANPERSIST); } else { /* * free the uvn now. note that the vref reference is already * gone [it is dropped when we enter the persist state]. */ if (uvn->u_flags & UVM_VNODE_IOSYNCWANTED) panic("uvm_vnp_terminate: io sync wanted bit set"); if (uvn->u_flags & UVM_VNODE_WRITEABLE) { LIST_REMOVE(uvn, u_wlist); } uvn->u_flags = 0; /* uvn is history, clear all bits */ } if (oldflags & UVM_VNODE_WANTED) wakeup(uvn); rw_exit(uobj->vmobjlock); } /* * NOTE: currently we have to use VOP_READ/VOP_WRITE because they go * through the buffer cache and allow I/O in any size. These VOPs use * synchronous i/o. [vs. VOP_STRATEGY which can be async, but doesn't * go through the buffer cache or allow I/O sizes larger than a * block]. we will eventually want to change this. * * issues to consider: * uvm provides the uvm_aiodesc structure for async i/o management. * there are two tailq's in the uvm. structure... one for pending async * i/o and one for "done" async i/o. to do an async i/o one puts * an aiodesc on the "pending" list (protected by splbio()), starts the * i/o and returns VM_PAGER_PEND. when the i/o is done, we expect * some sort of "i/o done" function to be called (at splbio(), interrupt * time). this function should remove the aiodesc from the pending list * and place it on the "done" list and wakeup the daemon. the daemon * will run at normal spl() and will remove all items from the "done" * list and call the "aiodone" hook for each done request (see uvm_pager.c). * [in the old vm code, this was done by calling the "put" routine with * null arguments which made the code harder to read and understand because * you had one function ("put") doing two things.] * * so the current pager needs: * int uvn_aiodone(struct uvm_aiodesc *) * * => return 0 (aio finished, free it). otherwise requeue for later collection. * => called with pageq's locked by the daemon. * * general outline: * - drop "u_nio" (this req is done!) * - if (object->iosync && u_naio == 0) { wakeup &uvn->u_naio } * - get "page" structures (atop?). * - handle "wanted" pages * dont forget to look at "object" wanted flag in all cases. */ /* * uvn_flush: flush pages out of a uvm object. * * => if PGO_CLEANIT is set, we may block (due to I/O). thus, a caller * might want to unlock higher level resources (e.g. vm_map) * before calling flush. * => if PGO_CLEANIT is not set, then we will not block * => if PGO_ALLPAGE is set, then all pages in the object are valid targets * for flushing. * => NOTE: we are allowed to lock the page queues, so the caller * must not be holding the lock on them [e.g. pagedaemon had * better not call us with the queues locked] * => we return TRUE unless we encountered some sort of I/O error * * comment on "cleaning" object and PG_BUSY pages: * this routine is holding the lock on the object. the only time * that it can run into a PG_BUSY page that it does not own is if * some other process has started I/O on the page (e.g. either * a pagein, or a pageout). if the PG_BUSY page is being paged * in, then it can not be dirty (!PG_CLEAN) because no one has * had a chance to modify it yet. if the PG_BUSY page is being * paged out then it means that someone else has already started * cleaning the page for us (how nice!). in this case, if we * have syncio specified, then after we make our pass through the * object we need to wait for the other PG_BUSY pages to clear * off (i.e. we need to do an iosync). also note that once a * page is PG_BUSY it must stay in its object until it is un-busyed. */ boolean_t uvn_flush(struct uvm_object *uobj, voff_t start, voff_t stop, int flags) { struct uvm_vnode *uvn = (struct uvm_vnode *) uobj; struct vm_page *pp, *ptmp; struct vm_page *pps[MAXBSIZE >> PAGE_SHIFT], **ppsp; struct pglist dead; int npages, result, lcv; boolean_t retval, need_iosync, needs_clean; voff_t curoff; KASSERT(rw_write_held(uobj->vmobjlock)); TAILQ_INIT(&dead); /* get init vals and determine how we are going to traverse object */ need_iosync = FALSE; retval = TRUE; /* return value */ if (flags & PGO_ALLPAGES) { start = 0; stop = round_page(uvn->u_size); } else { start = trunc_page(start); stop = MIN(round_page(stop), round_page(uvn->u_size)); } /* * PG_CLEANCHK: this bit is used by the pgo_mk_pcluster function as * a _hint_ as to how up to date the PG_CLEAN bit is. if the hint * is wrong it will only prevent us from clustering... it won't break * anything. we clear all PG_CLEANCHK bits here, and pgo_mk_pcluster * will set them as it syncs PG_CLEAN. This is only an issue if we * are looking at non-inactive pages (because inactive page's PG_CLEAN * bit is always up to date since there are no mappings). * [borrowed PG_CLEANCHK idea from FreeBSD VM] */ if ((flags & PGO_CLEANIT) != 0) { KASSERT(uobj->pgops->pgo_mk_pcluster != 0); for (curoff = start ; curoff < stop; curoff += PAGE_SIZE) { if ((pp = uvm_pagelookup(uobj, curoff)) != NULL) atomic_clearbits_int(&pp->pg_flags, PG_CLEANCHK); } } ppsp = NULL; /* XXX: shut up gcc */ uvm_lock_pageq(); /* locked: both page queues */ for (curoff = start; curoff < stop; curoff += PAGE_SIZE) { if ((pp = uvm_pagelookup(uobj, curoff)) == NULL) continue; /* * handle case where we do not need to clean page (either * because we are not clean or because page is not dirty or * is busy): * * NOTE: we are allowed to deactivate a non-wired active * PG_BUSY page, but once a PG_BUSY page is on the inactive * queue it must stay put until it is !PG_BUSY (so as not to * confuse pagedaemon). */ if ((flags & PGO_CLEANIT) == 0 || (pp->pg_flags & PG_BUSY) != 0) { needs_clean = FALSE; if ((pp->pg_flags & PG_BUSY) != 0 && (flags & (PGO_CLEANIT|PGO_SYNCIO)) == (PGO_CLEANIT|PGO_SYNCIO)) need_iosync = TRUE; } else { /* * freeing: nuke all mappings so we can sync * PG_CLEAN bit with no race */ if ((pp->pg_flags & PG_CLEAN) != 0 && (flags & PGO_FREE) != 0 && (pp->pg_flags & PQ_ACTIVE) != 0) pmap_page_protect(pp, PROT_NONE); if ((pp->pg_flags & PG_CLEAN) != 0 && pmap_is_modified(pp)) atomic_clearbits_int(&pp->pg_flags, PG_CLEAN); atomic_setbits_int(&pp->pg_flags, PG_CLEANCHK); needs_clean = ((pp->pg_flags & PG_CLEAN) == 0); } /* if we don't need a clean, deactivate/free pages then cont. */ if (!needs_clean) { if (flags & PGO_DEACTIVATE) { if (pp->wire_count == 0) { pmap_page_protect(pp, PROT_NONE); uvm_pagedeactivate(pp); } } else if (flags & PGO_FREE) { if (pp->pg_flags & PG_BUSY) { uvm_unlock_pageq(); uvm_pagewait(pp, uobj->vmobjlock, "uvn_flsh"); rw_enter(uobj->vmobjlock, RW_WRITE); uvm_lock_pageq(); curoff -= PAGE_SIZE; continue; } else { pmap_page_protect(pp, PROT_NONE); /* removed page from object */ uvm_pageclean(pp); TAILQ_INSERT_HEAD(&dead, pp, pageq); } } continue; } /* * pp points to a page in the object that we are * working on. if it is !PG_CLEAN,!PG_BUSY and we asked * for cleaning (PGO_CLEANIT). we clean it now. * * let uvm_pager_put attempted a clustered page out. * note: locked: page queues. */ atomic_setbits_int(&pp->pg_flags, PG_BUSY); UVM_PAGE_OWN(pp, "uvn_flush"); pmap_page_protect(pp, PROT_READ); /* if we're async, free the page in aiodoned */ if ((flags & (PGO_FREE|PGO_SYNCIO)) == PGO_FREE) atomic_setbits_int(&pp->pg_flags, PG_RELEASED); ReTry: ppsp = pps; npages = sizeof(pps) / sizeof(struct vm_page *); result = uvm_pager_put(uobj, pp, &ppsp, &npages, flags | PGO_DOACTCLUST, start, stop); /* * if we did an async I/O it is remotely possible for the * async i/o to complete and the page "pp" be freed or what * not before we get a chance to relock the object. Therefore, * we only touch it when it won't be freed, RELEASED took care * of the rest. */ uvm_lock_pageq(); /* * VM_PAGER_AGAIN: given the structure of this pager, this * can only happen when we are doing async I/O and can't * map the pages into kernel memory (pager_map) due to lack * of vm space. if this happens we drop back to sync I/O. */ if (result == VM_PAGER_AGAIN) { /* * it is unlikely, but page could have been released * we ignore this now and retry the I/O. * we will detect and * handle the released page after the syncio I/O * completes. */ #ifdef DIAGNOSTIC if (flags & PGO_SYNCIO) panic("%s: PGO_SYNCIO return 'try again' error (impossible)", __func__); #endif flags |= PGO_SYNCIO; if (flags & PGO_FREE) atomic_clearbits_int(&pp->pg_flags, PG_RELEASED); goto ReTry; } /* * the cleaning operation is now done. finish up. note that * on error (!OK, !PEND) uvm_pager_put drops the cluster for us. * if success (OK, PEND) then uvm_pager_put returns the cluster * to us in ppsp/npages. */ /* * for pending async i/o if we are not deactivating * we can move on to the next page. aiodoned deals with * the freeing case for us. */ if (result == VM_PAGER_PEND && (flags & PGO_DEACTIVATE) == 0) continue; /* * need to look at each page of the I/O operation, and do what * we gotta do. */ for (lcv = 0 ; lcv < npages; lcv++) { ptmp = ppsp[lcv]; /* * verify the page didn't get moved */ if (result == VM_PAGER_PEND && ptmp->uobject != uobj) continue; /* * unbusy the page if I/O is done. note that for * pending I/O it is possible that the I/O op * finished * (in which case the page is no longer busy). */ if (result != VM_PAGER_PEND) { if (ptmp->pg_flags & PG_WANTED) wakeup(ptmp); atomic_clearbits_int(&ptmp->pg_flags, PG_WANTED|PG_BUSY); UVM_PAGE_OWN(ptmp, NULL); atomic_setbits_int(&ptmp->pg_flags, PG_CLEAN|PG_CLEANCHK); if ((flags & PGO_FREE) == 0) pmap_clear_modify(ptmp); } /* dispose of page */ if (flags & PGO_DEACTIVATE) { if (ptmp->wire_count == 0) { pmap_page_protect(ptmp, PROT_NONE); uvm_pagedeactivate(ptmp); } } else if (flags & PGO_FREE && result != VM_PAGER_PEND) { if (result != VM_PAGER_OK) { static struct timeval lasttime; static const struct timeval interval = { 5, 0 }; if (ratecheck(&lasttime, &interval)) { printf("%s: obj=%p, " "offset=0x%llx. error " "during pageout.\n", __func__, pp->uobject, (long long)pp->offset); printf("%s: WARNING: " "changes to page may be " "lost!\n", __func__); } retval = FALSE; } pmap_page_protect(ptmp, PROT_NONE); uvm_pageclean(ptmp); TAILQ_INSERT_TAIL(&dead, ptmp, pageq); } } /* end of "lcv" for loop */ } /* end of "pp" for loop */ /* done with pagequeues: unlock */ uvm_unlock_pageq(); /* now wait for all I/O if required. */ if (need_iosync) { while (uvn->u_nio != 0) { uvn->u_flags |= UVM_VNODE_IOSYNC; rwsleep_nsec(&uvn->u_nio, uobj->vmobjlock, PVM, "uvn_flush", INFSLP); } if (uvn->u_flags & UVM_VNODE_IOSYNCWANTED) wakeup(&uvn->u_flags); uvn->u_flags &= ~(UVM_VNODE_IOSYNC|UVM_VNODE_IOSYNCWANTED); } uvm_pglistfree(&dead); return retval; } /* * uvn_cluster * * we are about to do I/O in an object at offset. this function is called * to establish a range of offsets around "offset" in which we can cluster * I/O. */ void uvn_cluster(struct uvm_object *uobj, voff_t offset, voff_t *loffset, voff_t *hoffset) { struct uvm_vnode *uvn = (struct uvm_vnode *) uobj; *loffset = offset; KASSERT(rw_write_held(uobj->vmobjlock)); if (*loffset >= uvn->u_size) panic("uvn_cluster: offset out of range"); /* * XXX: old pager claims we could use VOP_BMAP to get maxcontig value. */ *hoffset = *loffset + MAXBSIZE; if (*hoffset > round_page(uvn->u_size)) /* past end? */ *hoffset = round_page(uvn->u_size); } /* * uvn_put: flush page data to backing store. * * => prefer map unlocked (not required) * => flags: PGO_SYNCIO -- use sync. I/O * => note: caller must set PG_CLEAN and pmap_clear_modify (if needed) * => XXX: currently we use VOP_READ/VOP_WRITE which are only sync. * [thus we never do async i/o! see iodone comment] */ int uvn_put(struct uvm_object *uobj, struct vm_page **pps, int npages, int flags) { struct uvm_vnode *uvn = (struct uvm_vnode *)uobj; int dying, retval; KASSERT(rw_write_held(uobj->vmobjlock)); /* * Unless we're recycling this vnode, grab a reference to it * to prevent it from being recycled from under our feet. * This also makes sure we can don't panic if we end up in * uvn_vnp_uncache() as a result of the I/O operation as that * function assumes we hold a reference. * * If the vnode is in the process of being recycled by someone * else, grabbing a reference will fail. In that case the * pages will already be written out by whoever is cleaning * the vnode, so simply return VM_PAGER_AGAIN such that we * skip these pages. */ dying = (uvn->u_flags & UVM_VNODE_DYING); if (!dying) { if (vget(uvn->u_vnode, LK_NOWAIT)) return VM_PAGER_AGAIN; } retval = uvn_io((struct uvm_vnode*)uobj, pps, npages, flags, UIO_WRITE); if (!dying) vrele(uvn->u_vnode); return retval; } /* * uvn_get: get pages (synchronously) from backing store * * => prefer map unlocked (not required) * => flags: PGO_ALLPAGES: get all of the pages * PGO_LOCKED: fault data structures are locked * => NOTE: offset is the offset of pps[0], _NOT_ pps[centeridx] * => NOTE: caller must check for released pages!! */ int uvn_get(struct uvm_object *uobj, voff_t offset, struct vm_page **pps, int *npagesp, int centeridx, vm_prot_t access_type, int advice, int flags) { voff_t current_offset; struct vm_page *ptmp; int lcv, result, gotpages; boolean_t done; KASSERT(((flags & PGO_LOCKED) != 0 && rw_lock_held(uobj->vmobjlock)) || (flags & PGO_LOCKED) == 0); /* step 1: handled the case where fault data structures are locked. */ if (flags & PGO_LOCKED) { /* * gotpages is the current number of pages we've gotten (which * we pass back up to caller via *npagesp. */ gotpages = 0; /* * step 1a: get pages that are already resident. only do this * if the data structures are locked (i.e. the first time * through). */ done = TRUE; /* be optimistic */ for (lcv = 0, current_offset = offset ; lcv < *npagesp ; lcv++, current_offset += PAGE_SIZE) { /* do we care about this page? if not, skip it */ if (pps[lcv] == PGO_DONTCARE) continue; /* lookup page */ ptmp = uvm_pagelookup(uobj, current_offset); /* to be useful must get a non-busy, non-released pg */ if (ptmp == NULL || (ptmp->pg_flags & PG_BUSY) != 0) { if (lcv == centeridx || (flags & PGO_ALLPAGES) != 0) done = FALSE; /* need to do a wait or I/O! */ continue; } /* * useful page: busy it and plug it in our * result array */ atomic_setbits_int(&ptmp->pg_flags, PG_BUSY); UVM_PAGE_OWN(ptmp, "uvn_get1"); pps[lcv] = ptmp; gotpages++; } /* * XXX: given the "advice", should we consider async read-ahead? * XXX: fault current does deactivate of pages behind us. is * this good (other callers might now). */ /* * XXX: read-ahead currently handled by buffer cache (bread) * level. * XXX: no async i/o available. * XXX: so we don't do anything now. */ /* * step 1c: now we've either done everything needed or we to * unlock and do some waiting or I/O. */ *npagesp = gotpages; /* let caller know */ if (done) return VM_PAGER_OK; /* bingo! */ else return VM_PAGER_UNLOCK; } /* * step 2: get non-resident or busy pages. * data structures are unlocked. * * XXX: because we can't do async I/O at this level we get things * page at a time (otherwise we'd chunk). the VOP_READ() will do * async-read-ahead for us at a lower level. */ for (lcv = 0, current_offset = offset; lcv < *npagesp ; lcv++, current_offset += PAGE_SIZE) { /* skip over pages we've already gotten or don't want */ /* skip over pages we don't _have_ to get */ if (pps[lcv] != NULL || (lcv != centeridx && (flags & PGO_ALLPAGES) == 0)) continue; /* * we have yet to locate the current page (pps[lcv]). we first * look for a page that is already at the current offset. if * we fine a page, we check to see if it is busy or released. * if that is the case, then we sleep on the page until it is * no longer busy or released and repeat the lookup. if the * page we found is neither busy nor released, then we busy it * (so we own it) and plug it into pps[lcv]. this breaks the * following while loop and indicates we are ready to move on * to the next page in the "lcv" loop above. * * if we exit the while loop with pps[lcv] still set to NULL, * then it means that we allocated a new busy/fake/clean page * ptmp in the object and we need to do I/O to fill in the data. */ while (pps[lcv] == NULL) { /* top of "pps" while loop */ /* look for a current page */ ptmp = uvm_pagelookup(uobj, current_offset); /* nope? allocate one now (if we can) */ if (ptmp == NULL) { ptmp = uvm_pagealloc(uobj, current_offset, NULL, 0); /* out of RAM? */ if (ptmp == NULL) { uvm_wait("uvn_getpage"); /* goto top of pps while loop */ continue; } /* * got new page ready for I/O. break pps * while loop. pps[lcv] is still NULL. */ break; } /* page is there, see if we need to wait on it */ if ((ptmp->pg_flags & PG_BUSY) != 0) { uvm_pagewait(ptmp, uobj->vmobjlock, "uvn_get"); rw_enter(uobj->vmobjlock, RW_WRITE); continue; /* goto top of pps while loop */ } /* * if we get here then the page has become resident * and unbusy between steps 1 and 2. we busy it * now (so we own it) and set pps[lcv] (so that we * exit the while loop). */ atomic_setbits_int(&ptmp->pg_flags, PG_BUSY); UVM_PAGE_OWN(ptmp, "uvn_get2"); pps[lcv] = ptmp; } /* * if we own the a valid page at the correct offset, pps[lcv] * will point to it. nothing more to do except go to the * next page. */ if (pps[lcv]) continue; /* next lcv */ /* * we have a "fake/busy/clean" page that we just allocated. do * I/O to fill it with valid data. */ result = uvn_io((struct uvm_vnode *) uobj, &ptmp, 1, PGO_SYNCIO|PGO_NOWAIT, UIO_READ); /* * I/O done. because we used syncio the result can not be * PEND or AGAIN. */ if (result != VM_PAGER_OK) { if (ptmp->pg_flags & PG_WANTED) wakeup(ptmp); atomic_clearbits_int(&ptmp->pg_flags, PG_WANTED|PG_BUSY); UVM_PAGE_OWN(ptmp, NULL); uvm_lock_pageq(); uvm_pagefree(ptmp); uvm_unlock_pageq(); rw_exit(uobj->vmobjlock); return result; } /* * we got the page! clear the fake flag (indicates valid * data now in page) and plug into our result array. note * that page is still busy. * * it is the callers job to: * => check if the page is released * => unbusy the page * => activate the page */ /* data is valid ... */ atomic_clearbits_int(&ptmp->pg_flags, PG_FAKE); pmap_clear_modify(ptmp); /* ... and clean */ pps[lcv] = ptmp; } rw_exit(uobj->vmobjlock); return (VM_PAGER_OK); } /* * uvn_io: do I/O to a vnode * * => prefer map unlocked (not required) * => flags: PGO_SYNCIO -- use sync. I/O * => XXX: currently we use VOP_READ/VOP_WRITE which are only sync. * [thus we never do async i/o! see iodone comment] */ int uvn_io(struct uvm_vnode *uvn, vm_page_t *pps, int npages, int flags, int rw) { struct uvm_object *uobj = &uvn->u_obj; struct vnode *vn; struct uio uio; struct iovec iov; vaddr_t kva; off_t file_offset; int waitf, result, mapinflags; size_t got, wanted; int vnlocked, netunlocked = 0; int lkflags = (flags & PGO_NOWAIT) ? LK_NOWAIT : 0; voff_t uvnsize; KASSERT(rw_write_held(uobj->vmobjlock)); /* init values */ waitf = (flags & PGO_SYNCIO) ? M_WAITOK : M_NOWAIT; vn = uvn->u_vnode; file_offset = pps[0]->offset; /* check for sync'ing I/O. */ while (uvn->u_flags & UVM_VNODE_IOSYNC) { if (waitf == M_NOWAIT) { return VM_PAGER_AGAIN; } uvn->u_flags |= UVM_VNODE_IOSYNCWANTED; rwsleep_nsec(&uvn->u_flags, uobj->vmobjlock, PVM, "uvn_iosync", INFSLP); } /* check size */ if (file_offset >= uvn->u_size) { return VM_PAGER_BAD; } /* first try and map the pages in (without waiting) */ mapinflags = (rw == UIO_READ) ? UVMPAGER_MAPIN_READ : UVMPAGER_MAPIN_WRITE; kva = uvm_pagermapin(pps, npages, mapinflags); if (kva == 0 && waitf == M_NOWAIT) { return VM_PAGER_AGAIN; } /* * ok, now bump u_nio up. at this point we are done with uvn * and can unlock it. if we still don't have a kva, try again * (this time with sleep ok). */ uvn->u_nio++; /* we have an I/O in progress! */ vnlocked = (uvn->u_flags & UVM_VNODE_VNISLOCKED); uvnsize = uvn->u_size; rw_exit(uobj->vmobjlock); if (kva == 0) kva = uvm_pagermapin(pps, npages, mapinflags | UVMPAGER_MAPIN_WAITOK); /* * ok, mapped in. our pages are PG_BUSY so they are not going to * get touched (so we can look at "offset" without having to lock * the object). set up for I/O. */ /* fill out uio/iov */ iov.iov_base = (caddr_t) kva; wanted = (size_t)npages << PAGE_SHIFT; if (file_offset + wanted > uvnsize) wanted = uvnsize - file_offset; /* XXX: needed? */ iov.iov_len = wanted; uio.uio_iov = &iov; uio.uio_iovcnt = 1; uio.uio_offset = file_offset; uio.uio_segflg = UIO_SYSSPACE; uio.uio_rw = rw; uio.uio_resid = wanted; uio.uio_procp = curproc; /* * This process may already have the NET_LOCK(), if we * faulted in copyin() or copyout() in the network stack. */ if (rw_status(&netlock) == RW_WRITE) { NET_UNLOCK(); netunlocked = 1; } /* do the I/O! (XXX: curproc?) */ /* * This process may already have this vnode locked, if we faulted in * copyin() or copyout() on a region backed by this vnode * while doing I/O to the vnode. If this is the case, don't * panic.. instead, return the error to the user. * * XXX this is a stopgap to prevent a panic. * Ideally, this kind of operation *should* work. */ result = 0; KERNEL_LOCK(); if (!vnlocked) result = vn_lock(vn, LK_EXCLUSIVE | LK_RECURSEFAIL | lkflags); if (result == 0) { /* NOTE: vnode now locked! */ if (rw == UIO_READ) result = VOP_READ(vn, &uio, 0, curproc->p_ucred); else result = VOP_WRITE(vn, &uio, (flags & PGO_PDFREECLUST) ? IO_NOCACHE : 0, curproc->p_ucred); if (!vnlocked) VOP_UNLOCK(vn); } KERNEL_UNLOCK(); if (netunlocked) NET_LOCK(); /* NOTE: vnode now unlocked (unless vnislocked) */ /* * result == unix style errno (0 == OK!) * * zero out rest of buffer (if needed) */ if (result == 0) { got = wanted - uio.uio_resid; if (wanted && got == 0) { result = EIO; /* XXX: error? */ } else if (got < PAGE_SIZE * npages && rw == UIO_READ) { memset((void *) (kva + got), 0, ((size_t)npages << PAGE_SHIFT) - got); } } /* now remove pager mapping */ uvm_pagermapout(kva, npages); /* now clean up the object (i.e. drop I/O count) */ rw_enter(uobj->vmobjlock, RW_WRITE); uvn->u_nio--; /* I/O DONE! */ if ((uvn->u_flags & UVM_VNODE_IOSYNC) != 0 && uvn->u_nio == 0) { wakeup(&uvn->u_nio); } if (result == 0) { return VM_PAGER_OK; } else if (result == EBUSY) { KASSERT(flags & PGO_NOWAIT); return VM_PAGER_AGAIN; } else { if (rebooting) { KERNEL_LOCK(); while (rebooting) tsleep_nsec(&rebooting, PVM, "uvndead", INFSLP); KERNEL_UNLOCK(); } return VM_PAGER_ERROR; } } /* * uvm_vnp_uncache: disable "persisting" in a vnode... when last reference * is gone we will kill the object (flushing dirty pages back to the vnode * if needed). * * => returns TRUE if there was no uvm_object attached or if there was * one and we killed it [i.e. if there is no active uvn] * => called with the vnode VOP_LOCK'd [we will unlock it for I/O, if * needed] * * => XXX: given that we now kill uvn's when a vnode is recycled (without * having to hold a reference on the vnode) and given a working * uvm_vnp_sync(), how does that effect the need for this function? * [XXXCDC: seems like it can die?] * * => XXX: this function should DIE once we merge the VM and buffer * cache. * * research shows that this is called in the following places: * ext2fs_truncate, ffs_truncate, detrunc[msdosfs]: called when vnode * changes sizes * ext2fs_write, WRITE [ufs_readwrite], msdosfs_write: called when we * are written to * ex2fs_chmod, ufs_chmod: called if VTEXT vnode and the sticky bit * is off * ffs_realloccg: when we can't extend the current block and have * to allocate a new one we call this [XXX: why?] * nfsrv_rename, rename_files: called when the target filename is there * and we want to remove it * nfsrv_remove, sys_unlink: called on file we are removing * nfsrv_access: if VTEXT and we want WRITE access and we don't uncache * then return "text busy" * nfs_open: seems to uncache any file opened with nfs * vn_writechk: if VTEXT vnode and can't uncache return "text busy" * fusefs_open: uncaches any file that is opened * fusefs_write: uncaches on every write */ int uvm_vnp_uncache(struct vnode *vp) { struct uvm_vnode *uvn = vp->v_uvm; struct uvm_object *uobj = &uvn->u_obj; /* lock uvn part of the vnode and check if we need to do anything */ rw_enter(uobj->vmobjlock, RW_WRITE); if ((uvn->u_flags & UVM_VNODE_VALID) == 0 || (uvn->u_flags & UVM_VNODE_BLOCKED) != 0) { rw_exit(uobj->vmobjlock); return TRUE; } /* * we have a valid, non-blocked uvn. clear persist flag. * if uvn is currently active we can return now. */ uvn->u_flags &= ~UVM_VNODE_CANPERSIST; if (uvn->u_obj.uo_refs) { rw_exit(uobj->vmobjlock); return FALSE; } /* * uvn is currently persisting! we have to gain a reference to * it so that we can call uvn_detach to kill the uvn. */ vref(vp); /* seems ok, even with VOP_LOCK */ uvn->u_obj.uo_refs++; /* value is now 1 */ rw_exit(uobj->vmobjlock); #ifdef VFSLCKDEBUG /* * carry over sanity check from old vnode pager: the vnode should * be VOP_LOCK'd, and we confirm it here. */ if ((vp->v_flag & VLOCKSWORK) && !VOP_ISLOCKED(vp)) panic("uvm_vnp_uncache: vnode not locked!"); #endif /* * now drop our reference to the vnode. if we have the sole * reference to the vnode then this will cause it to die [as we * just cleared the persist flag]. we have to unlock the vnode * while we are doing this as it may trigger I/O. * * XXX: it might be possible for uvn to get reclaimed while we are * unlocked causing us to return TRUE when we should not. we ignore * this as a false-positive return value doesn't hurt us. */ VOP_UNLOCK(vp); uvn_detach(&uvn->u_obj); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); return TRUE; } /* * uvm_vnp_setsize: grow or shrink a vnode uvn * * grow => just update size value * shrink => toss un-needed pages * * => we assume that the caller has a reference of some sort to the * vnode in question so that it will not be yanked out from under * us. * * called from: * => truncate fns (ext2fs_truncate, ffs_truncate, detrunc[msdos], * fusefs_setattr) * => "write" fns (ext2fs_write, WRITE [ufs/ufs], msdosfs_write, nfs_write * fusefs_write) * => ffs_balloc [XXX: why? doesn't WRITE handle?] * => NFS: nfs_loadattrcache, nfs_getattrcache, nfs_setattr * => union fs: union_newsize */ void uvm_vnp_setsize(struct vnode *vp, off_t newsize) { struct uvm_vnode *uvn = vp->v_uvm; struct uvm_object *uobj = &uvn->u_obj; KERNEL_ASSERT_LOCKED(); rw_enter(uobj->vmobjlock, RW_WRITE); /* lock uvn and check for valid object, and if valid: do it! */ if (uvn->u_flags & UVM_VNODE_VALID) { /* * now check if the size has changed: if we shrink we had better * toss some pages... */ if (uvn->u_size > newsize) { (void)uvn_flush(&uvn->u_obj, newsize, uvn->u_size, PGO_FREE); } uvn->u_size = newsize; } rw_exit(uobj->vmobjlock); } /* * uvm_vnp_sync: flush all dirty VM pages back to their backing vnodes. * * => called from sys_sync with no VM structures locked * => only one process can do a sync at a time (because the uvn * structure only has one queue for sync'ing). we ensure this * by holding the uvn_sync_lock while the sync is in progress. * other processes attempting a sync will sleep on this lock * until we are done. */ void uvm_vnp_sync(struct mount *mp) { struct uvm_vnode *uvn; struct vnode *vp; /* * step 1: ensure we are only ones using the uvn_sync_q by locking * our lock... */ rw_enter_write(&uvn_sync_lock); /* * step 2: build up a simpleq of uvns of interest based on the * write list. we gain a reference to uvns of interest. */ SIMPLEQ_INIT(&uvn_sync_q); LIST_FOREACH(uvn, &uvn_wlist, u_wlist) { vp = uvn->u_vnode; if (mp && vp->v_mount != mp) continue; /* * If the vnode is "blocked" it means it must be dying, which * in turn means its in the process of being flushed out so * we can safely skip it. * * note that uvn must already be valid because we found it on * the wlist (this also means it can't be ALOCK'd). */ if ((uvn->u_flags & UVM_VNODE_BLOCKED) != 0) continue; /* * gain reference. watch out for persisting uvns (need to * regain vnode REF). */ if (uvn->u_obj.uo_refs == 0) vref(vp); uvn->u_obj.uo_refs++; SIMPLEQ_INSERT_HEAD(&uvn_sync_q, uvn, u_syncq); } /* step 3: we now have a list of uvn's that may need cleaning. */ SIMPLEQ_FOREACH(uvn, &uvn_sync_q, u_syncq) { rw_enter(uvn->u_obj.vmobjlock, RW_WRITE); #ifdef DEBUG if (uvn->u_flags & UVM_VNODE_DYING) { printf("uvm_vnp_sync: dying vnode on sync list\n"); } #endif uvn_flush(&uvn->u_obj, 0, 0, PGO_CLEANIT|PGO_ALLPAGES|PGO_DOACTCLUST); /* * if we have the only reference and we just cleaned the uvn, * then we can pull it out of the UVM_VNODE_WRITEABLE state * thus allowing us to avoid thinking about flushing it again * on later sync ops. */ if (uvn->u_obj.uo_refs == 1 && (uvn->u_flags & UVM_VNODE_WRITEABLE)) { LIST_REMOVE(uvn, u_wlist); uvn->u_flags &= ~UVM_VNODE_WRITEABLE; } rw_exit(uvn->u_obj.vmobjlock); /* now drop our reference to the uvn */ uvn_detach(&uvn->u_obj); } rw_exit_write(&uvn_sync_lock); }
15 2 7 3 1 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 /* $OpenBSD: db_usrreq.c,v 1.22 2021/01/09 20:58:12 gnezdo Exp $ */ /* * Copyright (c) 1996 Michael Shalayeff. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/tty.h> #include <sys/sysctl.h> #include <dev/cons.h> #include <ddb/db_var.h> int db_log = 1; int db_profile; /* Allow dynamic profiling */ const struct sysctl_bounded_args ddb_vars[] = { { DBCTL_RADIX, &db_radix, 8, 16 }, { DBCTL_MAXWIDTH, &db_max_width, 0, INT_MAX }, { DBCTL_TABSTOP, &db_tab_stop_width, 1, 16 }, { DBCTL_MAXLINE, &db_max_line, 0, INT_MAX }, { DBCTL_LOG, &db_log, 0, 1 }, }; int ddb_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { /* All sysctl names at this level are terminal. */ if (namelen != 1) return (ENOTDIR); switch (name[0]) { case DBCTL_PANIC: if (securelevel > 0) return (sysctl_int_lower(oldp, oldlenp, newp, newlen, &db_panic)); else { return (sysctl_int_bounded(oldp, oldlenp, newp, newlen, &db_panic, 0, 1)); } break; case DBCTL_CONSOLE: if (securelevel > 0) return (sysctl_int_lower(oldp, oldlenp, newp, newlen, &db_console)); else { return (sysctl_int_bounded(oldp, oldlenp, newp, newlen, &db_console, 0, 1)); } break; case DBCTL_TRIGGER: if (newp && db_console) { struct process *pr = curproc->p_p; if (securelevel < 1 || (pr->ps_flags & PS_CONTROLT && cn_tab && cn_tab->cn_dev == pr->ps_session->s_ttyp->t_dev)) { db_enter(); newp = NULL; } else return (ENODEV); } return (sysctl_rdint(oldp, oldlenp, newp, 0)); #if defined(DDBPROF) case DBCTL_PROFILE: if (securelevel > 0) return (sysctl_int_lower(oldp, oldlenp, newp, newlen, &db_profile)); else { return (sysctl_int_bounded(oldp, oldlenp, newp, newlen, &db_profile, 0, 1)); } break; #endif /* DDBPROF */ default: return (sysctl_bounded_arr(ddb_vars, nitems(ddb_vars), name, namelen, oldp, oldlenp, newp, newlen)); } /* NOTREACHED */ }
468 276 182 261 246 247 152 248 134 134 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 /* $OpenBSD: ufs_ihash.c,v 1.26 2021/10/19 06:11:45 semarie Exp $ */ /* $NetBSD: ufs_ihash.c,v 1.3 1996/02/09 22:36:04 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ufs_ihash.c 8.4 (Berkeley) 12/30/93 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/vnode.h> #include <sys/malloc.h> #include <ufs/ufs/quota.h> #include <ufs/ufs/inode.h> #include <ufs/ufs/ufs_extern.h> #include <crypto/siphash.h> /* * Structures associated with inode caching. */ LIST_HEAD(ihashhead, inode) *ihashtbl; u_long ihash; /* size of hash table - 1 */ SIPHASH_KEY ihashkey; struct ihashhead *ufs_ihash(dev_t, ufsino_t); #define INOHASH(device, inum) ufs_ihash((device), (inum)) struct ihashhead * ufs_ihash(dev_t dev, ufsino_t inum) { SIPHASH_CTX ctx; SipHash24_Init(&ctx, &ihashkey); SipHash24_Update(&ctx, &dev, sizeof(dev)); SipHash24_Update(&ctx, &inum, sizeof(inum)); return (&ihashtbl[SipHash24_End(&ctx) & ihash]); } /* * Initialize inode hash table. */ void ufs_ihashinit(void) { ihashtbl = hashinit(initialvnodes, M_UFSMNT, M_WAITOK, &ihash); arc4random_buf(&ihashkey, sizeof(ihashkey)); } /* * Use the device/inum pair to find the incore inode, and return a pointer * to it. If it is in core, return it, even if it is locked. */ struct vnode * ufs_ihashlookup(dev_t dev, ufsino_t inum) { struct inode *ip; struct ihashhead *ipp; /* XXXLOCKING lock hash list */ ipp = INOHASH(dev, inum); LIST_FOREACH(ip, ipp, i_hash) { if (inum == ip->i_number && dev == ip->i_dev) break; } /* XXXLOCKING unlock hash list? */ if (ip) return (ITOV(ip)); return (NULLVP); } /* * Use the device/inum pair to find the incore inode, and return a pointer * to it. If it is in core, but locked, wait for it. */ struct vnode * ufs_ihashget(dev_t dev, ufsino_t inum) { struct ihashhead *ipp; struct inode *ip; struct vnode *vp; loop: /* XXXLOCKING lock hash list */ ipp = INOHASH(dev, inum); LIST_FOREACH(ip, ipp, i_hash) { if (inum == ip->i_number && dev == ip->i_dev) { vp = ITOV(ip); /* XXXLOCKING unlock hash list? */ if (vget(vp, LK_EXCLUSIVE)) goto loop; return (vp); } } /* XXXLOCKING unlock hash list? */ return (NULL); } /* * Insert the inode into the hash table, and return it locked. */ int ufs_ihashins(struct inode *ip) { struct inode *curip; struct ihashhead *ipp; dev_t dev = ip->i_dev; ufsino_t inum = ip->i_number; /* lock the inode, then put it on the appropriate hash list */ VOP_LOCK(ITOV(ip), LK_EXCLUSIVE); /* XXXLOCKING lock hash list */ ipp = INOHASH(dev, inum); LIST_FOREACH(curip, ipp, i_hash) { if (inum == curip->i_number && dev == curip->i_dev) { /* XXXLOCKING unlock hash list? */ VOP_UNLOCK(ITOV(ip)); return (EEXIST); } } SET(ip->i_flag, IN_HASHED); LIST_INSERT_HEAD(ipp, ip, i_hash); /* XXXLOCKING unlock hash list? */ return (0); } /* * Remove the inode from the hash table. */ void ufs_ihashrem(struct inode *ip) { /* XXXLOCKING lock hash list */ if (ip->i_hash.le_prev == NULL) return; if (ISSET(ip->i_flag, IN_HASHED)) { LIST_REMOVE(ip, i_hash); CLR(ip->i_flag, IN_HASHED); } #ifdef DIAGNOSTIC ip->i_hash.le_next = NULL; ip->i_hash.le_prev = NULL; #endif /* XXXLOCKING unlock hash list? */ }
2 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 /* $OpenBSD: ip_carp.h,v 1.51 2021/03/07 06:02:32 dlg Exp $ */ /* * Copyright (c) 2002 Michael Shalayeff. All rights reserved. * Copyright (c) 2003 Ryan McBride. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _NETINET_IP_CARP_H_ #define _NETINET_IP_CARP_H_ /* * The CARP header layout is as follows: * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |Version| Type | VirtualHostID | AdvSkew | Auth Len | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Demotion | AdvBase | Checksum | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Counter (1) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Counter (2) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | SHA-1 HMAC (1) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | SHA-1 HMAC (2) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | SHA-1 HMAC (3) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | SHA-1 HMAC (4) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | SHA-1 HMAC (5) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ struct carp_header { #if _BYTE_ORDER == _LITTLE_ENDIAN u_int carp_type:4, carp_version:4; #endif #if _BYTE_ORDER == _BIG_ENDIAN u_int carp_version:4, carp_type:4; #endif u_int8_t carp_vhid; /* virtual host id */ u_int8_t carp_advskew; /* advertisement skew */ u_int8_t carp_authlen; /* size of counter+md, 32bit chunks */ u_int8_t carp_demote; /* demotion indicator */ u_int8_t carp_advbase; /* advertisement interval */ u_int16_t carp_cksum; u_int32_t carp_counter[2]; unsigned char carp_md[20]; /* SHA1 HMAC */ } __packed; #define CARP_DFLTTL 255 /* carp_version */ #define CARP_VERSION 2 /* carp_type */ #define CARP_ADVERTISEMENT 0x01 #define CARP_KEY_LEN 20 /* a sha1 hash of a passphrase */ /* carp_advbase */ #define CARP_DFLTINTV 1 /* * Statistics. */ struct carpstats { u_int64_t carps_ipackets; /* total input packets, IPv4 */ u_int64_t carps_ipackets6; /* total input packets, IPv6 */ u_int64_t carps_badif; /* wrong interface */ u_int64_t carps_badttl; /* TTL is not CARP_DFLTTL */ u_int64_t carps_hdrops; /* packets shorter than hdr */ u_int64_t carps_badsum; /* bad checksum */ u_int64_t carps_badver; /* bad (incl unsupp) version */ u_int64_t carps_badlen; /* data length does not match */ u_int64_t carps_badauth; /* bad authentication */ u_int64_t carps_badvhid; /* bad VHID */ u_int64_t carps_badaddrs; /* bad address list */ u_int64_t carps_opackets; /* total output packets, IPv4 */ u_int64_t carps_opackets6; /* total output packets, IPv6 */ u_int64_t carps_onomem; /* no memory for an mbuf */ u_int64_t carps_ostates; /* total state updates sent */ u_int64_t carps_preempt; /* transitions to master */ }; #define CARPDEVNAMSIZ 16 #ifdef IFNAMSIZ #if CARPDEVNAMSIZ != IFNAMSIZ #error namsiz mismatch #endif #endif /* * Configuration structure for SIOCSVH SIOCGVH */ struct carpreq { int carpr_state; #define CARP_STATES "INIT", "BACKUP", "MASTER" #define CARP_MAXSTATE 2 #define CARP_MAXNODES 32 char carpr_carpdev[CARPDEVNAMSIZ]; u_int8_t carpr_vhids[CARP_MAXNODES]; u_int8_t carpr_advskews[CARP_MAXNODES]; u_int8_t carpr_states[CARP_MAXNODES]; #define CARP_BAL_MODES "none", "ip", "ip-stealth", "ip-unicast" #define CARP_BAL_NONE 0 #define CARP_BAL_IP 1 #define CARP_BAL_IPSTEALTH 2 #define CARP_BAL_IPUNICAST 3 #define CARP_BAL_MAXID 3 u_int8_t carpr_balancing; int carpr_advbase; unsigned char carpr_key[CARP_KEY_LEN]; struct in_addr carpr_peer; }; /* * Names for CARP sysctl objects */ #define CARPCTL_ALLOW 1 /* accept incoming CARP packets */ #define CARPCTL_PREEMPT 2 /* high-pri backup preemption mode */ #define CARPCTL_LOG 3 /* log bad packets */ #define CARPCTL_STATS 4 /* CARP stats */ #define CARPCTL_MAXID 5 #define CARPCTL_NAMES { \ { 0, 0 }, \ { "allow", CTLTYPE_INT }, \ { "preempt", CTLTYPE_INT }, \ { "log", CTLTYPE_INT }, \ { "stats", CTLTYPE_STRUCT }, \ } #ifdef _KERNEL #include <net/if_types.h> #include <sys/percpu.h> enum carpstat_counters { carps_ipackets, carps_ipackets6, carps_badif, carps_badttl, carps_hdrops, carps_badsum, carps_badver, carps_badlen, carps_badauth, carps_badvhid, carps_badaddrs, carps_opackets, carps_opackets6, carps_onomem, carps_ostates, carps_preempt, carps_ncounters, }; extern struct cpumem *carpcounters; static inline void carpstat_inc(enum carpstat_counters c) { counters_inc(carpcounters, c); } /* * If two carp interfaces share same physical interface, then we pretend all IP * addresses belong to single interface. */ static inline int carp_strict_addr_chk(struct ifnet *ifp_a, struct ifnet *ifp_b) { return ((ifp_a->if_type == IFT_CARP && ifp_b->if_index == ifp_a->if_carpdevidx) || (ifp_b->if_type == IFT_CARP && ifp_a->if_index == ifp_b->if_carpdevidx) || (ifp_a->if_type == IFT_CARP && ifp_b->if_type == IFT_CARP && ifp_a->if_carpdevidx == ifp_b->if_carpdevidx)); } struct mbuf *carp_input(struct ifnet *, struct mbuf *, uint64_t); int carp_proto_input(struct mbuf **, int *, int, int); void carp_carpdev_state(void *); void carp_group_demote_adj(struct ifnet *, int, char *); int carp6_proto_input(struct mbuf **, int *, int, int); int carp_iamatch(struct ifnet *); int carp_ourether(struct ifnet *, u_int8_t *); int carp_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); int carp_sysctl(int *, u_int, void *, size_t *, void *, size_t); int carp_lsdrop(struct ifnet *, struct mbuf *, sa_family_t, u_int32_t *, u_int32_t *, int); #endif /* _KERNEL */ #endif /* _NETINET_IP_CARP_H_ */
960 956 2 3 4 951 481 1 3 532 481 534 629 212 313 2 40 21 18 15 13 36 11 8 18 19 12 25 11 2 6 16 8 11 10 9 4 402 312 3 1 1 1 1 1 6 5 2 1 6 3 2 6 2 5 1 1 1 2 1 1 2 1 1 1 5 2 2 3 5 2 4 2 1 5 1 1 5 7 109 1 5 5 5 5 5 2 3 1 17 2 1 5 5 2 5 5 5 5 1 5 9 8 9 1 2 1 8 2 2 1 2 1 12 3 9 2 2 121 38 67 133 34 64 22 31 21 79 15 15 160 70 93 17 19 48 3 41 30 6 8 4 6 8 14 14 5 22 8 6 22 2 8 8 14 20 12 18 25 11 2 7 2 5 2 64 18 14 51 20 4 11 11 4 13 4 12 5 12 10 12 3 10 15 6 14 5 14 4 10 14 2 1 1 11 4 10 13 4 13 11 4 10 14 10 11 14 4 10 14 9 5 14 3 6 6 8 12 20 7 36 4 33 2 1 5 9 9 9 9 9 9 9 8 9 4 9 8 14 14 2 9 14 1 8 8 8 7 7 7 5 7 6 7 7 7 7 8 7 7 7 7 3 5 4 5 7 7 7 7 28 1 27 41 41 7 14 20 32 5 2 3 3 3 5 4 9 11 16 19 7 3 4 32 19 13 14 20 16 4 16 16 9 15 6 16 16 11 3 8 11 16 4 16 12 15 15 21 1 2 2 2 1 1 6 7 2 2 2 5 7 2 2 1 3 18 2 2 1 1 11 1 10 8 2 15 2 2 2 3 6 9 2 2 1 13 2 1 2 2 3 3 3 1 2 5 1 1 1 1 2 3 20 2 7 4 2 2 2 5 3 2 1 3 2 17 1 3 5 6 2 2 1 6 1 2 2 5 2 1 4 2 2 7 5 2 5 3 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 /* $OpenBSD: kern_sysctl.c,v 1.427 2024/04/12 16:07:09 bluhm Exp $ */ /* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */ /*- * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Mike Karels at Berkeley Software Design, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94 */ /* * sysctl system call. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/pool.h> #include <sys/proc.h> #include <sys/resourcevar.h> #include <sys/signalvar.h> #include <sys/fcntl.h> #include <sys/file.h> #include <sys/filedesc.h> #include <sys/vnode.h> #include <sys/unistd.h> #include <sys/buf.h> #include <sys/clockintr.h> #include <sys/tty.h> #include <sys/disklabel.h> #include <sys/disk.h> #include <sys/sysctl.h> #include <sys/msgbuf.h> #include <sys/vmmeter.h> #include <sys/namei.h> #include <sys/exec.h> #include <sys/mbuf.h> #include <sys/percpu.h> #include <sys/sensors.h> #include <sys/pipe.h> #include <sys/eventvar.h> #include <sys/socketvar.h> #include <sys/socket.h> #include <sys/domain.h> #include <sys/protosw.h> #include <sys/pledge.h> #include <sys/timetc.h> #include <sys/evcount.h> #include <sys/un.h> #include <sys/unpcb.h> #include <sys/sched.h> #include <sys/mount.h> #include <sys/syscallargs.h> #include <sys/wait.h> #include <sys/witness.h> #include <uvm/uvm_extern.h> #include <dev/cons.h> #include <dev/usb/ucomvar.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_var.h> #include <netinet/in_pcb.h> #include <netinet/ip6.h> #include <netinet/tcp.h> #include <netinet/tcp_timer.h> #include <netinet/tcp_var.h> #include <netinet/udp.h> #include <netinet/udp_var.h> #include <netinet6/ip6_var.h> #ifdef DDB #include <ddb/db_var.h> #endif #ifdef SYSVMSG #include <sys/msg.h> #endif #ifdef SYSVSEM #include <sys/sem.h> #endif #ifdef SYSVSHM #include <sys/shm.h> #endif #include "audio.h" #include "dt.h" #include "pf.h" #include "ucom.h" #include "video.h" extern struct forkstat forkstat; extern struct nchstats nchstats; extern int fscale; extern fixpt_t ccpu; extern long numvnodes; extern int allowdt; extern int audio_record_enable; extern int video_record_enable; extern int autoconf_serial; int allowkmem; int sysctl_diskinit(int, struct proc *); int sysctl_proc_args(int *, u_int, void *, size_t *, struct proc *); int sysctl_proc_cwd(int *, u_int, void *, size_t *, struct proc *); int sysctl_proc_nobroadcastkill(int *, u_int, void *, size_t, void *, size_t *, struct proc *); int sysctl_proc_vmmap(int *, u_int, void *, size_t *, struct proc *); int sysctl_intrcnt(int *, u_int, void *, size_t *); int sysctl_sensors(int *, u_int, void *, size_t *, void *, size_t); int sysctl_cptime2(int *, u_int, void *, size_t *, void *, size_t); int sysctl_audio(int *, u_int, void *, size_t *, void *, size_t); int sysctl_video(int *, u_int, void *, size_t *, void *, size_t); int sysctl_cpustats(int *, u_int, void *, size_t *, void *, size_t); int sysctl_utc_offset(void *, size_t *, void *, size_t); int sysctl_hwbattery(int *, u_int, void *, size_t *, void *, size_t); void fill_file(struct kinfo_file *, struct file *, struct filedesc *, int, struct vnode *, struct process *, struct proc *, struct socket *, int); void fill_kproc(struct process *, struct kinfo_proc *, struct proc *, int); int (*cpu_cpuspeed)(int *); /* * Lock to avoid too many processes vslocking a large amount of memory * at the same time. */ struct rwlock sysctl_lock = RWLOCK_INITIALIZER("sysctllk"); struct rwlock sysctl_disklock = RWLOCK_INITIALIZER("sysctldlk"); int sys_sysctl(struct proc *p, void *v, register_t *retval) { struct sys_sysctl_args /* { syscallarg(const int *) name; syscallarg(u_int) namelen; syscallarg(void *) old; syscallarg(size_t *) oldlenp; syscallarg(void *) new; syscallarg(size_t) newlen; } */ *uap = v; int error, dolock = 1; size_t savelen = 0, oldlen = 0; sysctlfn *fn; int name[CTL_MAXNAME]; if (SCARG(uap, new) != NULL && (error = suser(p))) return (error); /* * all top-level sysctl names are non-terminal */ if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2) return (EINVAL); error = copyin(SCARG(uap, name), name, SCARG(uap, namelen) * sizeof(int)); if (error) return (error); error = pledge_sysctl(p, SCARG(uap, namelen), name, SCARG(uap, new)); if (error) return (error); switch (name[0]) { case CTL_KERN: fn = kern_sysctl; break; case CTL_HW: fn = hw_sysctl; break; case CTL_VM: fn = uvm_sysctl; break; case CTL_NET: fn = net_sysctl; break; case CTL_FS: fn = fs_sysctl; break; case CTL_VFS: fn = vfs_sysctl; break; case CTL_MACHDEP: fn = cpu_sysctl; break; #ifdef DEBUG_SYSCTL case CTL_DEBUG: fn = debug_sysctl; break; #endif #ifdef DDB case CTL_DDB: fn = ddb_sysctl; break; #endif default: return (EOPNOTSUPP); } if (SCARG(uap, oldlenp) && (error = copyin(SCARG(uap, oldlenp), &oldlen, sizeof(oldlen)))) return (error); if (SCARG(uap, old) != NULL) { if ((error = rw_enter(&sysctl_lock, RW_WRITE|RW_INTR)) != 0) return (error); if (dolock) { if (atop(oldlen) > uvmexp.wiredmax - uvmexp.wired) { rw_exit_write(&sysctl_lock); return (ENOMEM); } error = uvm_vslock(p, SCARG(uap, old), oldlen, PROT_READ | PROT_WRITE); if (error) { rw_exit_write(&sysctl_lock); return (error); } } savelen = oldlen; } error = (*fn)(&name[1], SCARG(uap, namelen) - 1, SCARG(uap, old), &oldlen, SCARG(uap, new), SCARG(uap, newlen), p); if (SCARG(uap, old) != NULL) { if (dolock) uvm_vsunlock(p, SCARG(uap, old), savelen); rw_exit_write(&sysctl_lock); } if (error) return (error); if (SCARG(uap, oldlenp)) error = copyout(&oldlen, SCARG(uap, oldlenp), sizeof(oldlen)); return (error); } /* * Attributes stored in the kernel. */ char hostname[MAXHOSTNAMELEN]; int hostnamelen; char domainname[MAXHOSTNAMELEN]; int domainnamelen; long hostid; char *disknames = NULL; size_t disknameslen; struct diskstats *diskstats = NULL; size_t diskstatslen; int securelevel; /* morally const values reported by sysctl_bounded_arr */ static int arg_max = ARG_MAX; static int openbsd = OpenBSD; static int posix_version = _POSIX_VERSION; static int ngroups_max = NGROUPS_MAX; static int int_zero = 0; static int int_one = 1; static int maxpartitions = MAXPARTITIONS; static int raw_part = RAW_PART; extern int somaxconn, sominconn; extern int nosuidcoredump; extern int maxlocksperuid; extern int uvm_wxabort; extern int global_ptrace; const struct sysctl_bounded_args kern_vars[] = { {KERN_OSREV, &openbsd, SYSCTL_INT_READONLY}, {KERN_MAXVNODES, &maxvnodes, 0, INT_MAX}, {KERN_MAXPROC, &maxprocess, 0, INT_MAX}, {KERN_MAXFILES, &maxfiles, 0, INT_MAX}, {KERN_NFILES, &numfiles, SYSCTL_INT_READONLY}, {KERN_TTYCOUNT, &tty_count, SYSCTL_INT_READONLY}, {KERN_ARGMAX, &arg_max, SYSCTL_INT_READONLY}, {KERN_POSIX1, &posix_version, SYSCTL_INT_READONLY}, {KERN_NGROUPS, &ngroups_max, SYSCTL_INT_READONLY}, {KERN_JOB_CONTROL, &int_one, SYSCTL_INT_READONLY}, {KERN_SAVED_IDS, &int_one, SYSCTL_INT_READONLY}, {KERN_MAXPARTITIONS, &maxpartitions, SYSCTL_INT_READONLY}, {KERN_RAWPARTITION, &raw_part, SYSCTL_INT_READONLY}, {KERN_MAXTHREAD, &maxthread, 0, INT_MAX}, {KERN_NTHREADS, &nthreads, SYSCTL_INT_READONLY}, {KERN_SOMAXCONN, &somaxconn, 0, SHRT_MAX}, {KERN_SOMINCONN, &sominconn, 0, SHRT_MAX}, {KERN_NOSUIDCOREDUMP, &nosuidcoredump, 0, 3}, {KERN_FSYNC, &int_one, SYSCTL_INT_READONLY}, {KERN_SYSVMSG, #ifdef SYSVMSG &int_one, #else &int_zero, #endif SYSCTL_INT_READONLY}, {KERN_SYSVSEM, #ifdef SYSVSEM &int_one, #else &int_zero, #endif SYSCTL_INT_READONLY}, {KERN_SYSVSHM, #ifdef SYSVSHM &int_one, #else &int_zero, #endif SYSCTL_INT_READONLY}, {KERN_FSCALE, &fscale, SYSCTL_INT_READONLY}, {KERN_CCPU, &ccpu, SYSCTL_INT_READONLY}, {KERN_NPROCS, &nprocesses, SYSCTL_INT_READONLY}, {KERN_SPLASSERT, &splassert_ctl, 0, 3}, {KERN_MAXLOCKSPERUID, &maxlocksperuid, 0, INT_MAX}, {KERN_WXABORT, &uvm_wxabort, 0, 1}, {KERN_NETLIVELOCKS, &int_zero, SYSCTL_INT_READONLY}, #ifdef PTRACE {KERN_GLOBAL_PTRACE, &global_ptrace, 0, 1}, #endif {KERN_AUTOCONF_SERIAL, &autoconf_serial, SYSCTL_INT_READONLY}, }; int kern_sysctl_dirs(int top_name, int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { switch (top_name) { #ifndef SMALL_KERNEL case KERN_PROC: return (sysctl_doproc(name, namelen, oldp, oldlenp)); case KERN_PROC_ARGS: return (sysctl_proc_args(name, namelen, oldp, oldlenp, p)); case KERN_PROC_CWD: return (sysctl_proc_cwd(name, namelen, oldp, oldlenp, p)); case KERN_PROC_NOBROADCASTKILL: return (sysctl_proc_nobroadcastkill(name, namelen, newp, newlen, oldp, oldlenp, p)); case KERN_PROC_VMMAP: return (sysctl_proc_vmmap(name, namelen, oldp, oldlenp, p)); case KERN_FILE: return (sysctl_file(name, namelen, oldp, oldlenp, p)); #endif #if defined(GPROF) || defined(DDBPROF) case KERN_PROF: return (sysctl_doprof(name, namelen, oldp, oldlenp, newp, newlen)); #endif case KERN_MALLOCSTATS: return (sysctl_malloc(name, namelen, oldp, oldlenp, newp, newlen, p)); case KERN_TTY: return (sysctl_tty(name, namelen, oldp, oldlenp, newp, newlen)); case KERN_POOL: return (sysctl_dopool(name, namelen, oldp, oldlenp)); #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) case KERN_SYSVIPC_INFO: return (sysctl_sysvipc(name, namelen, oldp, oldlenp)); #endif #ifdef SYSVSEM case KERN_SEMINFO: return (sysctl_sysvsem(name, namelen, oldp, oldlenp, newp, newlen)); #endif #ifdef SYSVSHM case KERN_SHMINFO: return (sysctl_sysvshm(name, namelen, oldp, oldlenp, newp, newlen)); #endif #ifndef SMALL_KERNEL case KERN_INTRCNT: return (sysctl_intrcnt(name, namelen, oldp, oldlenp)); case KERN_WATCHDOG: return (sysctl_wdog(name, namelen, oldp, oldlenp, newp, newlen)); #endif #ifndef SMALL_KERNEL case KERN_EVCOUNT: return (evcount_sysctl(name, namelen, oldp, oldlenp, newp, newlen)); #endif case KERN_TIMECOUNTER: return (sysctl_tc(name, namelen, oldp, oldlenp, newp, newlen)); case KERN_CPTIME2: return (sysctl_cptime2(name, namelen, oldp, oldlenp, newp, newlen)); #ifdef WITNESS case KERN_WITNESSWATCH: return witness_sysctl_watch(oldp, oldlenp, newp, newlen); case KERN_WITNESS: return witness_sysctl(name, namelen, oldp, oldlenp, newp, newlen); #endif #if NAUDIO > 0 case KERN_AUDIO: return (sysctl_audio(name, namelen, oldp, oldlenp, newp, newlen)); #endif #if NVIDEO > 0 case KERN_VIDEO: return (sysctl_video(name, namelen, oldp, oldlenp, newp, newlen)); #endif case KERN_CPUSTATS: return (sysctl_cpustats(name, namelen, oldp, oldlenp, newp, newlen)); case KERN_CLOCKINTR: return sysctl_clockintr(name, namelen, oldp, oldlenp, newp, newlen); default: return (ENOTDIR); /* overloaded */ } } /* * kernel related system variables. */ int kern_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { int error, level, inthostid, stackgap; dev_t dev; extern int pool_debug; /* dispatch the non-terminal nodes first */ if (namelen != 1) { return kern_sysctl_dirs(name[0], name + 1, namelen - 1, oldp, oldlenp, newp, newlen, p); } switch (name[0]) { case KERN_OSTYPE: return (sysctl_rdstring(oldp, oldlenp, newp, ostype)); case KERN_OSRELEASE: return (sysctl_rdstring(oldp, oldlenp, newp, osrelease)); case KERN_OSVERSION: return (sysctl_rdstring(oldp, oldlenp, newp, osversion)); case KERN_VERSION: return (sysctl_rdstring(oldp, oldlenp, newp, version)); case KERN_NUMVNODES: /* XXX numvnodes is a long */ return (sysctl_rdint(oldp, oldlenp, newp, numvnodes)); case KERN_SECURELVL: level = securelevel; if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || newp == NULL) return (error); if ((securelevel > 0 || level < -1) && level < securelevel && p->p_p->ps_pid != 1) return (EPERM); securelevel = level; return (0); #if NDT > 0 case KERN_ALLOWDT: return (sysctl_securelevel_int(oldp, oldlenp, newp, newlen, &allowdt)); #endif case KERN_ALLOWKMEM: return (sysctl_securelevel_int(oldp, oldlenp, newp, newlen, &allowkmem)); case KERN_HOSTNAME: error = sysctl_tstring(oldp, oldlenp, newp, newlen, hostname, sizeof(hostname)); if (newp && !error) hostnamelen = newlen; return (error); case KERN_DOMAINNAME: if (securelevel >= 1 && domainnamelen && newp) error = EPERM; else error = sysctl_tstring(oldp, oldlenp, newp, newlen, domainname, sizeof(domainname)); if (newp && !error) domainnamelen = newlen; return (error); case KERN_HOSTID: inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */ error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid); hostid = inthostid; return (error); case KERN_CLOCKRATE: return (sysctl_clockrate(oldp, oldlenp, newp)); case KERN_BOOTTIME: { struct timeval bt; memset(&bt, 0, sizeof bt); microboottime(&bt); return (sysctl_rdstruct(oldp, oldlenp, newp, &bt, sizeof bt)); } case KERN_MBSTAT: { extern struct cpumem *mbstat; uint64_t counters[MBSTAT_COUNT]; struct mbstat mbs; unsigned int i; memset(&mbs, 0, sizeof(mbs)); counters_read(mbstat, counters, MBSTAT_COUNT, NULL); for (i = 0; i < MBSTAT_TYPES; i++) mbs.m_mtypes[i] = counters[i]; mbs.m_drops = counters[MBSTAT_DROPS]; mbs.m_wait = counters[MBSTAT_WAIT]; mbs.m_drain = counters[MBSTAT_DRAIN]; return (sysctl_rdstruct(oldp, oldlenp, newp, &mbs, sizeof(mbs))); } case KERN_MSGBUFSIZE: case KERN_CONSBUFSIZE: { struct msgbuf *mp; mp = (name[0] == KERN_MSGBUFSIZE) ? msgbufp : consbufp; /* * deal with cases where the message buffer has * become corrupted. */ if (!mp || mp->msg_magic != MSG_MAGIC) return (ENXIO); return (sysctl_rdint(oldp, oldlenp, newp, mp->msg_bufs)); } case KERN_CONSBUF: if ((error = suser(p))) return (error); /* FALLTHROUGH */ case KERN_MSGBUF: { struct msgbuf *mp; mp = (name[0] == KERN_MSGBUF) ? msgbufp : consbufp; /* see note above */ if (!mp || mp->msg_magic != MSG_MAGIC) return (ENXIO); return (sysctl_rdstruct(oldp, oldlenp, newp, mp, mp->msg_bufs + offsetof(struct msgbuf, msg_bufc))); } case KERN_CPTIME: { CPU_INFO_ITERATOR cii; struct cpu_info *ci; long cp_time[CPUSTATES]; int i, n = 0; memset(cp_time, 0, sizeof(cp_time)); CPU_INFO_FOREACH(cii, ci) { if (!cpu_is_online(ci)) continue; n++; for (i = 0; i < CPUSTATES; i++) cp_time[i] += ci->ci_schedstate.spc_cp_time[i]; } for (i = 0; i < CPUSTATES; i++) cp_time[i] /= n; return (sysctl_rdstruct(oldp, oldlenp, newp, &cp_time, sizeof(cp_time))); } case KERN_NCHSTATS: return (sysctl_rdstruct(oldp, oldlenp, newp, &nchstats, sizeof(struct nchstats))); case KERN_FORKSTAT: return (sysctl_rdstruct(oldp, oldlenp, newp, &forkstat, sizeof(struct forkstat))); case KERN_STACKGAPRANDOM: stackgap = stackgap_random; error = sysctl_int(oldp, oldlenp, newp, newlen, &stackgap); if (error) return (error); /* * Safety harness. */ if ((stackgap < ALIGNBYTES && stackgap != 0) || !powerof2(stackgap) || stackgap >= MAXSSIZ) return (EINVAL); stackgap_random = stackgap; return (0); case KERN_MAXCLUSTERS: { int val = nmbclust; error = sysctl_int(oldp, oldlenp, newp, newlen, &val); if (error == 0 && val != nmbclust) error = nmbclust_update(val); return (error); } case KERN_CACHEPCT: { u_int64_t dmapages; int opct, pgs; opct = bufcachepercent; error = sysctl_int(oldp, oldlenp, newp, newlen, &bufcachepercent); if (error) return(error); if (bufcachepercent > 90 || bufcachepercent < 5) { bufcachepercent = opct; return (EINVAL); } dmapages = uvm_pagecount(&dma_constraint); if (bufcachepercent != opct) { pgs = bufcachepercent * dmapages / 100; bufadjust(pgs); /* adjust bufpages */ bufhighpages = bufpages; /* set high water mark */ } return(0); } case KERN_CONSDEV: if (cn_tab != NULL) dev = cn_tab->cn_dev; else dev = NODEV; return sysctl_rdstruct(oldp, oldlenp, newp, &dev, sizeof(dev)); case KERN_POOL_DEBUG: { int old_pool_debug = pool_debug; error = sysctl_int(oldp, oldlenp, newp, newlen, &pool_debug); if (error == 0 && pool_debug != old_pool_debug) pool_reclaim_all(); return (error); } #if NPF > 0 case KERN_PFSTATUS: return (pf_sysctl(oldp, oldlenp, newp, newlen)); #endif case KERN_TIMEOUT_STATS: return (timeout_sysctl(oldp, oldlenp, newp, newlen)); case KERN_UTC_OFFSET: return (sysctl_utc_offset(oldp, oldlenp, newp, newlen)); default: return (sysctl_bounded_arr(kern_vars, nitems(kern_vars), name, namelen, oldp, oldlenp, newp, newlen)); } /* NOTREACHED */ } /* * hardware related system variables. */ char *hw_vendor, *hw_prod, *hw_uuid, *hw_serial, *hw_ver; int allowpowerdown = 1; int hw_power = 1; /* morally const values reported by sysctl_bounded_arr */ static int byte_order = BYTE_ORDER; const struct sysctl_bounded_args hw_vars[] = { {HW_NCPU, &ncpus, SYSCTL_INT_READONLY}, {HW_NCPUFOUND, &ncpusfound, SYSCTL_INT_READONLY}, {HW_BYTEORDER, &byte_order, SYSCTL_INT_READONLY}, {HW_PAGESIZE, &uvmexp.pagesize, SYSCTL_INT_READONLY}, {HW_DISKCOUNT, &disk_count, SYSCTL_INT_READONLY}, {HW_POWER, &hw_power, SYSCTL_INT_READONLY}, }; int hw_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { extern char machine[], cpu_model[]; int err, cpuspeed; /* * all sysctl names at this level except sensors and battery * are terminal */ if (name[0] != HW_SENSORS && name[0] != HW_BATTERY && namelen != 1) return (ENOTDIR); /* overloaded */ switch (name[0]) { case HW_MACHINE: return (sysctl_rdstring(oldp, oldlenp, newp, machine)); case HW_MODEL: return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model)); case HW_NCPUONLINE: return (sysctl_rdint(oldp, oldlenp, newp, sysctl_hwncpuonline())); case HW_PHYSMEM: return (sysctl_rdint(oldp, oldlenp, newp, ptoa(physmem))); case HW_USERMEM: return (sysctl_rdint(oldp, oldlenp, newp, ptoa(physmem - uvmexp.wired))); case HW_DISKNAMES: err = sysctl_diskinit(0, p); if (err) return err; if (disknames) return (sysctl_rdstring(oldp, oldlenp, newp, disknames)); else return (sysctl_rdstring(oldp, oldlenp, newp, "")); case HW_DISKSTATS: err = sysctl_diskinit(1, p); if (err) return err; return (sysctl_rdstruct(oldp, oldlenp, newp, diskstats, disk_count * sizeof(struct diskstats))); case HW_CPUSPEED: if (!cpu_cpuspeed) return (EOPNOTSUPP); err = cpu_cpuspeed(&cpuspeed); if (err) return err; return (sysctl_rdint(oldp, oldlenp, newp, cpuspeed)); #ifndef SMALL_KERNEL case HW_SENSORS: return (sysctl_sensors(name + 1, namelen - 1, oldp, oldlenp, newp, newlen)); case HW_SETPERF: return (sysctl_hwsetperf(oldp, oldlenp, newp, newlen)); case HW_PERFPOLICY: return (sysctl_hwperfpolicy(oldp, oldlenp, newp, newlen)); #endif /* !SMALL_KERNEL */ case HW_VENDOR: if (hw_vendor) return (sysctl_rdstring(oldp, oldlenp, newp, hw_vendor)); else return (EOPNOTSUPP); case HW_PRODUCT: if (hw_prod) return (sysctl_rdstring(oldp, oldlenp, newp, hw_prod)); else return (EOPNOTSUPP); case HW_VERSION: if (hw_ver) return (sysctl_rdstring(oldp, oldlenp, newp, hw_ver)); else return (EOPNOTSUPP); case HW_SERIALNO: if (hw_serial) return (sysctl_rdstring(oldp, oldlenp, newp, hw_serial)); else return (EOPNOTSUPP); case HW_UUID: if (hw_uuid) return (sysctl_rdstring(oldp, oldlenp, newp, hw_uuid)); else return (EOPNOTSUPP); case HW_PHYSMEM64: return (sysctl_rdquad(oldp, oldlenp, newp, ptoa((psize_t)physmem))); case HW_USERMEM64: return (sysctl_rdquad(oldp, oldlenp, newp, ptoa((psize_t)physmem - uvmexp.wired))); case HW_ALLOWPOWERDOWN: return (sysctl_securelevel_int(oldp, oldlenp, newp, newlen, &allowpowerdown)); case HW_UCOMNAMES: { const char *str = ""; #if NUCOM > 0 str = sysctl_ucominit(); #endif /* NUCOM > 0 */ return (sysctl_rdstring(oldp, oldlenp, newp, str)); } #ifdef __HAVE_CPU_TOPOLOGY case HW_SMT: return (sysctl_hwsmt(oldp, oldlenp, newp, newlen)); #endif #ifndef SMALL_KERNEL case HW_BATTERY: return (sysctl_hwbattery(name + 1, namelen - 1, oldp, oldlenp, newp, newlen)); #endif default: return sysctl_bounded_arr(hw_vars, nitems(hw_vars), name, namelen, oldp, oldlenp, newp, newlen); } /* NOTREACHED */ } #ifndef SMALL_KERNEL int hw_battery_chargemode; int hw_battery_chargestart; int hw_battery_chargestop; int (*hw_battery_setchargemode)(int); int (*hw_battery_setchargestart)(int); int (*hw_battery_setchargestop)(int); int sysctl_hwchargemode(void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int mode = hw_battery_chargemode; int error; if (!hw_battery_setchargemode) return EOPNOTSUPP; error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &mode, -1, 1); if (error) return error; if (newp != NULL) error = hw_battery_setchargemode(mode); return error; } int sysctl_hwchargestart(void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int start = hw_battery_chargestart; int error; if (!hw_battery_setchargestart) return EOPNOTSUPP; error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &start, 0, 100); if (error) return error; if (newp != NULL) error = hw_battery_setchargestart(start); return error; } int sysctl_hwchargestop(void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int stop = hw_battery_chargestop; int error; if (!hw_battery_setchargestop) return EOPNOTSUPP; error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &stop, 0, 100); if (error) return error; if (newp != NULL) error = hw_battery_setchargestop(stop); return error; } int sysctl_hwbattery(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { if (namelen != 1) return (ENOTDIR); switch (name[0]) { case HW_BATTERY_CHARGEMODE: return (sysctl_hwchargemode(oldp, oldlenp, newp, newlen)); case HW_BATTERY_CHARGESTART: return (sysctl_hwchargestart(oldp, oldlenp, newp, newlen)); case HW_BATTERY_CHARGESTOP: return (sysctl_hwchargestop(oldp, oldlenp, newp, newlen)); default: return (EOPNOTSUPP); } /* NOTREACHED */ } #endif #ifdef DEBUG_SYSCTL /* * Debugging related system variables. */ extern struct ctldebug debug_vfs_busyprt; struct ctldebug debug1, debug2, debug3, debug4; struct ctldebug debug5, debug6, debug7, debug8, debug9; struct ctldebug debug10, debug11, debug12, debug13, debug14; struct ctldebug debug15, debug16, debug17, debug18, debug19; static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { &debug_vfs_busyprt, &debug1, &debug2, &debug3, &debug4, &debug5, &debug6, &debug7, &debug8, &debug9, &debug10, &debug11, &debug12, &debug13, &debug14, &debug15, &debug16, &debug17, &debug18, &debug19, }; int debug_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { struct ctldebug *cdp; /* all sysctl names at this level are name and field */ if (namelen != 2) return (ENOTDIR); /* overloaded */ if (name[0] < 0 || name[0] >= nitems(debugvars)) return (EOPNOTSUPP); cdp = debugvars[name[0]]; if (cdp->debugname == 0) return (EOPNOTSUPP); switch (name[1]) { case CTL_DEBUG_NAME: return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); case CTL_DEBUG_VALUE: return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); default: return (EOPNOTSUPP); } /* NOTREACHED */ } #endif /* DEBUG_SYSCTL */ /* * Reads, or writes that lower the value */ int sysctl_int_lower(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int *valp) { unsigned int oval = *valp, val = *valp; int error; if (newp == NULL) return (sysctl_rdint(oldp, oldlenp, newp, val)); if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &val))) return (error); if (val > oval) return (EPERM); /* do not allow raising */ *(unsigned int *)valp = val; return (0); } /* * Validate parameters and get old / set new parameters * for an integer-valued sysctl function. */ int sysctl_int(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int *valp) { int error = 0; if (oldp && *oldlenp < sizeof(int)) return (ENOMEM); if (newp && newlen != sizeof(int)) return (EINVAL); *oldlenp = sizeof(int); if (oldp) error = copyout(valp, oldp, sizeof(int)); if (error == 0 && newp) error = copyin(newp, valp, sizeof(int)); return (error); } /* * As above, but read-only. */ int sysctl_rdint(void *oldp, size_t *oldlenp, void *newp, int val) { int error = 0; if (oldp && *oldlenp < sizeof(int)) return (ENOMEM); if (newp) return (EPERM); *oldlenp = sizeof(int); if (oldp) error = copyout((caddr_t)&val, oldp, sizeof(int)); return (error); } /* * Selects between sysctl_rdint and sysctl_int according to securelevel. */ int sysctl_securelevel_int(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int *valp) { if (securelevel > 0) return (sysctl_rdint(oldp, oldlenp, newp, *valp)); return (sysctl_int(oldp, oldlenp, newp, newlen, valp)); } /* * Read-only or bounded integer values. */ int sysctl_int_bounded(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int *valp, int minimum, int maximum) { int val = *valp; int error; /* read only */ if (newp == NULL || minimum > maximum) return (sysctl_rdint(oldp, oldlenp, newp, val)); if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &val))) return (error); /* outside limits */ if (val < minimum || maximum < val) return (EINVAL); *valp = val; return (0); } /* * Array of read-only or bounded integer values. */ int sysctl_bounded_arr(const struct sysctl_bounded_args *valpp, u_int valplen, int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { u_int i; if (namelen != 1) return (ENOTDIR); for (i = 0; i < valplen; ++i) { if (valpp[i].mib == name[0]) { return (sysctl_int_bounded(oldp, oldlenp, newp, newlen, valpp[i].var, valpp[i].minimum, valpp[i].maximum)); } } return (EOPNOTSUPP); } /* * Validate parameters and get old / set new parameters * for an integer-valued sysctl function. */ int sysctl_quad(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int64_t *valp) { int error = 0; if (oldp && *oldlenp < sizeof(int64_t)) return (ENOMEM); if (newp && newlen != sizeof(int64_t)) return (EINVAL); *oldlenp = sizeof(int64_t); if (oldp) error = copyout(valp, oldp, sizeof(int64_t)); if (error == 0 && newp) error = copyin(newp, valp, sizeof(int64_t)); return (error); } /* * As above, but read-only. */ int sysctl_rdquad(void *oldp, size_t *oldlenp, void *newp, int64_t val) { int error = 0; if (oldp && *oldlenp < sizeof(int64_t)) return (ENOMEM); if (newp) return (EPERM); *oldlenp = sizeof(int64_t); if (oldp) error = copyout((caddr_t)&val, oldp, sizeof(int64_t)); return (error); } /* * Validate parameters and get old / set new parameters * for a string-valued sysctl function. */ int sysctl_string(void *oldp, size_t *oldlenp, void *newp, size_t newlen, char *str, size_t maxlen) { return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 0); } int sysctl_tstring(void *oldp, size_t *oldlenp, void *newp, size_t newlen, char *str, size_t maxlen) { return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 1); } int sysctl__string(void *oldp, size_t *oldlenp, void *newp, size_t newlen, char *str, size_t maxlen, int trunc) { size_t len; int error = 0; len = strlen(str) + 1; if (oldp && *oldlenp < len) { if (trunc == 0 || *oldlenp == 0) return (ENOMEM); } if (newp && newlen >= maxlen) return (EINVAL); if (oldp) { if (trunc && *oldlenp < len) { len = *oldlenp; error = copyout(str, oldp, len - 1); if (error == 0) error = copyout("", (char *)oldp + len - 1, 1); } else { error = copyout(str, oldp, len); } } *oldlenp = len; if (error == 0 && newp) { error = copyin(newp, str, newlen); str[newlen] = 0; } return (error); } /* * As above, but read-only. */ int sysctl_rdstring(void *oldp, size_t *oldlenp, void *newp, const char *str) { size_t len; int error = 0; len = strlen(str) + 1; if (oldp && *oldlenp < len) return (ENOMEM); if (newp) return (EPERM); *oldlenp = len; if (oldp) error = copyout(str, oldp, len); return (error); } /* * Validate parameters and get old / set new parameters * for a structure oriented sysctl function. */ int sysctl_struct(void *oldp, size_t *oldlenp, void *newp, size_t newlen, void *sp, size_t len) { int error = 0; if (oldp && *oldlenp < len) return (ENOMEM); if (newp && newlen > len) return (EINVAL); if (oldp) { *oldlenp = len; error = copyout(sp, oldp, len); } if (error == 0 && newp) error = copyin(newp, sp, len); return (error); } /* * Validate parameters and get old parameters * for a structure oriented sysctl function. */ int sysctl_rdstruct(void *oldp, size_t *oldlenp, void *newp, const void *sp, size_t len) { int error = 0; if (oldp && *oldlenp < len) return (ENOMEM); if (newp) return (EPERM); *oldlenp = len; if (oldp) error = copyout(sp, oldp, len); return (error); } #ifndef SMALL_KERNEL void fill_file(struct kinfo_file *kf, struct file *fp, struct filedesc *fdp, int fd, struct vnode *vp, struct process *pr, struct proc *p, struct socket *so, int show_pointers) { struct vattr va; memset(kf, 0, sizeof(*kf)); kf->fd_fd = fd; /* might not really be an fd */ if (fp != NULL) { if (show_pointers) kf->f_fileaddr = PTRTOINT64(fp); kf->f_flag = fp->f_flag; kf->f_iflags = fp->f_iflags; kf->f_type = fp->f_type; kf->f_count = fp->f_count; if (show_pointers) kf->f_ucred = PTRTOINT64(fp->f_cred); kf->f_uid = fp->f_cred->cr_uid; kf->f_gid = fp->f_cred->cr_gid; if (show_pointers) kf->f_ops = PTRTOINT64(fp->f_ops); if (show_pointers) kf->f_data = PTRTOINT64(fp->f_data); kf->f_usecount = 0; if (suser(p) == 0 || p->p_ucred->cr_uid == fp->f_cred->cr_uid) { mtx_enter(&fp->f_mtx); kf->f_offset = fp->f_offset; kf->f_rxfer = fp->f_rxfer; kf->f_rwfer = fp->f_wxfer; kf->f_seek = fp->f_seek; kf->f_rbytes = fp->f_rbytes; kf->f_wbytes = fp->f_wbytes; mtx_leave(&fp->f_mtx); } else kf->f_offset = -1; } else if (vp != NULL) { /* fake it */ kf->f_type = DTYPE_VNODE; kf->f_flag = FREAD; if (fd == KERN_FILE_TRACE) kf->f_flag |= FWRITE; } else if (so != NULL) { /* fake it */ kf->f_type = DTYPE_SOCKET; } /* information about the object associated with this file */ switch (kf->f_type) { case DTYPE_VNODE: if (fp != NULL) vp = (struct vnode *)fp->f_data; if (show_pointers) kf->v_un = PTRTOINT64(vp->v_un.vu_socket); kf->v_type = vp->v_type; kf->v_tag = vp->v_tag; kf->v_flag = vp->v_flag; if (show_pointers) kf->v_data = PTRTOINT64(vp->v_data); if (show_pointers) kf->v_mount = PTRTOINT64(vp->v_mount); if (vp->v_mount) strlcpy(kf->f_mntonname, vp->v_mount->mnt_stat.f_mntonname, sizeof(kf->f_mntonname)); if (VOP_GETATTR(vp, &va, p->p_ucred, p) == 0) { kf->va_fileid = va.va_fileid; kf->va_mode = MAKEIMODE(va.va_type, va.va_mode); kf->va_size = va.va_size; kf->va_rdev = va.va_rdev; kf->va_fsid = va.va_fsid & 0xffffffff; kf->va_nlink = va.va_nlink; } break; case DTYPE_SOCKET: { int locked = 0; if (so == NULL) { so = (struct socket *)fp->f_data; /* if so is passed as parameter it is already locked */ solock(so); locked = 1; } kf->so_type = so->so_type; kf->so_state = so->so_state | so->so_snd.sb_state | so->so_rcv.sb_state; if (show_pointers) kf->so_pcb = PTRTOINT64(so->so_pcb); else kf->so_pcb = -1; kf->so_protocol = so->so_proto->pr_protocol; kf->so_family = so->so_proto->pr_domain->dom_family; kf->so_rcv_cc = so->so_rcv.sb_cc; kf->so_snd_cc = so->so_snd.sb_cc; if (isspliced(so)) { if (show_pointers) kf->so_splice = PTRTOINT64(so->so_sp->ssp_socket); kf->so_splicelen = so->so_sp->ssp_len; } else if (issplicedback(so)) kf->so_splicelen = -1; if (so->so_pcb == NULL) { if (locked) sounlock(so); break; } switch (kf->so_family) { case AF_INET: { struct inpcb *inpcb = so->so_pcb; soassertlocked(so); if (show_pointers) kf->inp_ppcb = PTRTOINT64(inpcb->inp_ppcb); kf->inp_lport = inpcb->inp_lport; kf->inp_laddru[0] = inpcb->inp_laddr.s_addr; kf->inp_fport = inpcb->inp_fport; kf->inp_faddru[0] = inpcb->inp_faddr.s_addr; kf->inp_rtableid = inpcb->inp_rtableid; if (so->so_type == SOCK_RAW) kf->inp_proto = inpcb->inp_ip.ip_p; if (so->so_proto->pr_protocol == IPPROTO_TCP) { struct tcpcb *tcpcb = (void *)inpcb->inp_ppcb; kf->t_rcv_wnd = tcpcb->rcv_wnd; kf->t_snd_wnd = tcpcb->snd_wnd; kf->t_snd_cwnd = tcpcb->snd_cwnd; kf->t_state = tcpcb->t_state; } break; } case AF_INET6: { struct inpcb *inpcb = so->so_pcb; soassertlocked(so); if (show_pointers) kf->inp_ppcb = PTRTOINT64(inpcb->inp_ppcb); kf->inp_lport = inpcb->inp_lport; kf->inp_laddru[0] = inpcb->inp_laddr6.s6_addr32[0]; kf->inp_laddru[1] = inpcb->inp_laddr6.s6_addr32[1]; kf->inp_laddru[2] = inpcb->inp_laddr6.s6_addr32[2]; kf->inp_laddru[3] = inpcb->inp_laddr6.s6_addr32[3]; kf->inp_fport = inpcb->inp_fport; kf->inp_faddru[0] = inpcb->inp_faddr6.s6_addr32[0]; kf->inp_faddru[1] = inpcb->inp_faddr6.s6_addr32[1]; kf->inp_faddru[2] = inpcb->inp_faddr6.s6_addr32[2]; kf->inp_faddru[3] = inpcb->inp_faddr6.s6_addr32[3]; kf->inp_rtableid = inpcb->inp_rtableid; if (so->so_type == SOCK_RAW) kf->inp_proto = inpcb->inp_ipv6.ip6_nxt; if (so->so_proto->pr_protocol == IPPROTO_TCP) { struct tcpcb *tcpcb = (void *)inpcb->inp_ppcb; kf->t_rcv_wnd = tcpcb->rcv_wnd; kf->t_snd_wnd = tcpcb->snd_wnd; kf->t_state = tcpcb->t_state; } break; } case AF_UNIX: { struct unpcb *unpcb = so->so_pcb; kf->f_msgcount = unpcb->unp_msgcount; if (show_pointers) { kf->unp_conn = PTRTOINT64(unpcb->unp_conn); kf->unp_refs = PTRTOINT64( SLIST_FIRST(&unpcb->unp_refs)); kf->unp_nextref = PTRTOINT64( SLIST_NEXT(unpcb, unp_nextref)); kf->v_un = PTRTOINT64(unpcb->unp_vnode); kf->unp_addr = PTRTOINT64(unpcb->unp_addr); } if (unpcb->unp_addr != NULL) { struct sockaddr_un *un = mtod(unpcb->unp_addr, struct sockaddr_un *); memcpy(kf->unp_path, un->sun_path, un->sun_len - offsetof(struct sockaddr_un,sun_path)); } break; } } if (locked) sounlock(so); break; } case DTYPE_PIPE: { struct pipe *pipe = (struct pipe *)fp->f_data; if (show_pointers) kf->pipe_peer = PTRTOINT64(pipe->pipe_peer); kf->pipe_state = pipe->pipe_state; break; } case DTYPE_KQUEUE: { struct kqueue *kqi = (struct kqueue *)fp->f_data; kf->kq_count = kqi->kq_count; kf->kq_state = kqi->kq_state; break; } } /* per-process information for KERN_FILE_BY[PU]ID */ if (pr != NULL) { kf->p_pid = pr->ps_pid; kf->p_uid = pr->ps_ucred->cr_uid; kf->p_gid = pr->ps_ucred->cr_gid; kf->p_tid = -1; strlcpy(kf->p_comm, pr->ps_comm, sizeof(kf->p_comm)); } if (fdp != NULL) { fdplock(fdp); kf->fd_ofileflags = fdp->fd_ofileflags[fd]; fdpunlock(fdp); } } /* * Get file structures. */ int sysctl_file(int *name, u_int namelen, char *where, size_t *sizep, struct proc *p) { struct kinfo_file *kf; struct filedesc *fdp; struct file *fp; struct process *pr; size_t buflen, elem_size, elem_count, outsize; char *dp = where; int arg, i, error = 0, needed = 0, matched; u_int op; int show_pointers; if (namelen > 4) return (ENOTDIR); if (namelen < 4 || name[2] > sizeof(*kf)) return (EINVAL); buflen = where != NULL ? *sizep : 0; op = name[0]; arg = name[1]; elem_size = name[2]; elem_count = name[3]; outsize = MIN(sizeof(*kf), elem_size); if (elem_size < 1) return (EINVAL); show_pointers = suser(curproc) == 0; kf = malloc(sizeof(*kf), M_TEMP, M_WAITOK); #define FILLIT2(fp, fdp, i, vp, pr, so) do { \ if (buflen >= elem_size && elem_count > 0) { \ fill_file(kf, fp, fdp, i, vp, pr, p, so, show_pointers);\ error = copyout(kf, dp, outsize); \ if (error) \ break; \ dp += elem_size; \ buflen -= elem_size; \ elem_count--; \ } \ needed += elem_size; \ } while (0) #define FILLIT(fp, fdp, i, vp, pr) \ FILLIT2(fp, fdp, i, vp, pr, NULL) #define FILLSO(so) \ FILLIT2(NULL, NULL, 0, NULL, NULL, so) switch (op) { case KERN_FILE_BYFILE: /* use the inp-tables to pick up closed connections, too */ if (arg == DTYPE_SOCKET) { struct inpcb *inp; NET_LOCK(); mtx_enter(&tcbtable.inpt_mtx); TAILQ_FOREACH(inp, &tcbtable.inpt_queue, inp_queue) FILLSO(inp->inp_socket); mtx_leave(&tcbtable.inpt_mtx); #ifdef INET6 mtx_enter(&tcb6table.inpt_mtx); TAILQ_FOREACH(inp, &tcb6table.inpt_queue, inp_queue) FILLSO(inp->inp_socket); mtx_leave(&tcb6table.inpt_mtx); #endif mtx_enter(&udbtable.inpt_mtx); TAILQ_FOREACH(inp, &udbtable.inpt_queue, inp_queue) FILLSO(inp->inp_socket); mtx_leave(&udbtable.inpt_mtx); #ifdef INET6 mtx_enter(&udb6table.inpt_mtx); TAILQ_FOREACH(inp, &udb6table.inpt_queue, inp_queue) FILLSO(inp->inp_socket); mtx_leave(&udb6table.inpt_mtx); #endif mtx_enter(&rawcbtable.inpt_mtx); TAILQ_FOREACH(inp, &rawcbtable.inpt_queue, inp_queue) FILLSO(inp->inp_socket); mtx_leave(&rawcbtable.inpt_mtx); #ifdef INET6 mtx_enter(&rawin6pcbtable.inpt_mtx); TAILQ_FOREACH(inp, &rawin6pcbtable.inpt_queue, inp_queue) FILLSO(inp->inp_socket); mtx_leave(&rawin6pcbtable.inpt_mtx); #endif NET_UNLOCK(); } fp = NULL; while ((fp = fd_iterfile(fp, p)) != NULL) { if ((arg == 0 || fp->f_type == arg)) { int af, skip = 0; if (arg == DTYPE_SOCKET && fp->f_type == arg) { af = ((struct socket *)fp->f_data)-> so_proto->pr_domain->dom_family; if (af == AF_INET || af == AF_INET6) skip = 1; } if (!skip) FILLIT(fp, NULL, 0, NULL, NULL); } } break; case KERN_FILE_BYPID: /* A arg of -1 indicates all processes */ if (arg < -1) { error = EINVAL; break; } matched = 0; LIST_FOREACH(pr, &allprocess, ps_list) { /* * skip system, exiting, embryonic and undead * processes */ if (pr->ps_flags & (PS_SYSTEM | PS_EMBRYO | PS_EXITING)) continue; if (arg > 0 && pr->ps_pid != (pid_t)arg) { /* not the pid we are looking for */ continue; } matched = 1; fdp = pr->ps_fd; if (pr->ps_textvp) FILLIT(NULL, NULL, KERN_FILE_TEXT, pr->ps_textvp, pr); if (fdp->fd_cdir) FILLIT(NULL, NULL, KERN_FILE_CDIR, fdp->fd_cdir, pr); if (fdp->fd_rdir) FILLIT(NULL, NULL, KERN_FILE_RDIR, fdp->fd_rdir, pr); if (pr->ps_tracevp) FILLIT(NULL, NULL, KERN_FILE_TRACE, pr->ps_tracevp, pr); for (i = 0; i < fdp->fd_nfiles; i++) { if ((fp = fd_getfile(fdp, i)) == NULL) continue; FILLIT(fp, fdp, i, NULL, pr); FRELE(fp, p); } } if (!matched) error = ESRCH; break; case KERN_FILE_BYUID: LIST_FOREACH(pr, &allprocess, ps_list) { /* * skip system, exiting, embryonic and undead * processes */ if (pr->ps_flags & (PS_SYSTEM | PS_EMBRYO | PS_EXITING)) continue; if (arg >= 0 && pr->ps_ucred->cr_uid != (uid_t)arg) { /* not the uid we are looking for */ continue; } fdp = pr->ps_fd; if (fdp->fd_cdir) FILLIT(NULL, NULL, KERN_FILE_CDIR, fdp->fd_cdir, pr); if (fdp->fd_rdir) FILLIT(NULL, NULL, KERN_FILE_RDIR, fdp->fd_rdir, pr); if (pr->ps_tracevp) FILLIT(NULL, NULL, KERN_FILE_TRACE, pr->ps_tracevp, pr); for (i = 0; i < fdp->fd_nfiles; i++) { if ((fp = fd_getfile(fdp, i)) == NULL) continue; FILLIT(fp, fdp, i, NULL, pr); FRELE(fp, p); } } break; default: error = EINVAL; break; } free(kf, M_TEMP, sizeof(*kf)); if (!error) { if (where == NULL) needed += KERN_FILESLOP * elem_size; else if (*sizep < needed) error = ENOMEM; *sizep = needed; } return (error); } /* * try over estimating by 5 procs */ #define KERN_PROCSLOP 5 int sysctl_doproc(int *name, u_int namelen, char *where, size_t *sizep) { struct kinfo_proc *kproc = NULL; struct proc *p; struct process *pr; char *dp; int arg, buflen, doingzomb, elem_size, elem_count; int error, needed, op; int dothreads = 0; int show_pointers; dp = where; buflen = where != NULL ? *sizep : 0; needed = error = 0; if (namelen != 4 || name[2] <= 0 || name[3] < 0 || name[2] > sizeof(*kproc)) return (EINVAL); op = name[0]; arg = name[1]; elem_size = name[2]; elem_count = name[3]; dothreads = op & KERN_PROC_SHOW_THREADS; op &= ~KERN_PROC_SHOW_THREADS; show_pointers = suser(curproc) == 0; if (where != NULL) kproc = malloc(sizeof(*kproc), M_TEMP, M_WAITOK); pr = LIST_FIRST(&allprocess); doingzomb = 0; again: for (; pr != NULL; pr = LIST_NEXT(pr, ps_list)) { /* XXX skip processes in the middle of being zapped */ if (pr->ps_pgrp == NULL) continue; /* * Skip embryonic processes. */ if (pr->ps_flags & PS_EMBRYO) continue; /* * TODO - make more efficient (see notes below). */ switch (op) { case KERN_PROC_PID: /* could do this with just a lookup */ if (pr->ps_pid != (pid_t)arg) continue; break; case KERN_PROC_PGRP: /* could do this by traversing pgrp */ if (pr->ps_pgrp->pg_id != (pid_t)arg) continue; break; case KERN_PROC_SESSION: if (pr->ps_session->s_leader == NULL || pr->ps_session->s_leader->ps_pid != (pid_t)arg) continue; break; case KERN_PROC_TTY: if ((pr->ps_flags & PS_CONTROLT) == 0 || pr->ps_session->s_ttyp == NULL || pr->ps_session->s_ttyp->t_dev != (dev_t)arg) continue; break; case KERN_PROC_UID: if (pr->ps_ucred->cr_uid != (uid_t)arg) continue; break; case KERN_PROC_RUID: if (pr->ps_ucred->cr_ruid != (uid_t)arg) continue; break; case KERN_PROC_ALL: if (pr->ps_flags & PS_SYSTEM) continue; break; case KERN_PROC_KTHREAD: /* no filtering */ break; default: error = EINVAL; goto err; } if (buflen >= elem_size && elem_count > 0) { fill_kproc(pr, kproc, NULL, show_pointers); error = copyout(kproc, dp, elem_size); if (error) goto err; dp += elem_size; buflen -= elem_size; elem_count--; } needed += elem_size; /* Skip per-thread entries if not required by op */ if (!dothreads) continue; TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) { if (buflen >= elem_size && elem_count > 0) { fill_kproc(pr, kproc, p, show_pointers); error = copyout(kproc, dp, elem_size); if (error) goto err; dp += elem_size; buflen -= elem_size; elem_count--; } needed += elem_size; } } if (doingzomb == 0) { pr = LIST_FIRST(&zombprocess); doingzomb++; goto again; } if (where != NULL) { *sizep = dp - where; if (needed > *sizep) { error = ENOMEM; goto err; } } else { needed += KERN_PROCSLOP * elem_size; *sizep = needed; } err: if (kproc) free(kproc, M_TEMP, sizeof(*kproc)); return (error); } /* * Fill in a kproc structure for the specified process. */ void fill_kproc(struct process *pr, struct kinfo_proc *ki, struct proc *p, int show_pointers) { struct session *s = pr->ps_session; struct tty *tp; struct vmspace *vm = pr->ps_vmspace; struct timespec booted, st, ut, utc; int isthread; isthread = p != NULL; if (!isthread) p = pr->ps_mainproc; /* XXX */ FILL_KPROC(ki, strlcpy, p, pr, pr->ps_ucred, pr->ps_pgrp, p, pr, s, vm, pr->ps_limit, pr->ps_sigacts, isthread, show_pointers); /* stuff that's too painful to generalize into the macros */ if (pr->ps_pptr) ki->p_ppid = pr->ps_ppid; if (s->s_leader) ki->p_sid = s->s_leader->ps_pid; if ((pr->ps_flags & PS_CONTROLT) && (tp = s->s_ttyp)) { ki->p_tdev = tp->t_dev; ki->p_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : -1; if (show_pointers) ki->p_tsess = PTRTOINT64(tp->t_session); } else { ki->p_tdev = NODEV; ki->p_tpgid = -1; } /* fixups that can only be done in the kernel */ if ((pr->ps_flags & PS_ZOMBIE) == 0) { if ((pr->ps_flags & PS_EMBRYO) == 0 && vm != NULL) ki->p_vm_rssize = vm_resident_count(vm); calctsru(isthread ? &p->p_tu : &pr->ps_tu, &ut, &st, NULL); ki->p_uutime_sec = ut.tv_sec; ki->p_uutime_usec = ut.tv_nsec/1000; ki->p_ustime_sec = st.tv_sec; ki->p_ustime_usec = st.tv_nsec/1000; /* Convert starting uptime to a starting UTC time. */ nanoboottime(&booted); timespecadd(&booted, &pr->ps_start, &utc); ki->p_ustart_sec = utc.tv_sec; ki->p_ustart_usec = utc.tv_nsec / 1000; #ifdef MULTIPROCESSOR if (p->p_cpu != NULL) ki->p_cpuid = CPU_INFO_UNIT(p->p_cpu); #endif } /* get %cpu and schedule state: just one thread or sum of all? */ if (isthread) { ki->p_pctcpu = p->p_pctcpu; ki->p_stat = p->p_stat; } else { ki->p_pctcpu = 0; ki->p_stat = (pr->ps_flags & PS_ZOMBIE) ? SDEAD : SIDL; TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) { ki->p_pctcpu += p->p_pctcpu; /* find best state: ONPROC > RUN > STOP > SLEEP > .. */ if (p->p_stat == SONPROC || ki->p_stat == SONPROC) ki->p_stat = SONPROC; else if (p->p_stat == SRUN || ki->p_stat == SRUN) ki->p_stat = SRUN; else if (p->p_stat == SSTOP || ki->p_stat == SSTOP) ki->p_stat = SSTOP; else if (p->p_stat == SSLEEP) ki->p_stat = SSLEEP; } } } int sysctl_proc_args(int *name, u_int namelen, void *oldp, size_t *oldlenp, struct proc *cp) { struct process *vpr; pid_t pid; struct ps_strings pss; struct iovec iov; struct uio uio; int error, cnt, op; size_t limit; char **rargv, **vargv; /* reader vs. victim */ char *rarg, *varg, *buf; struct vmspace *vm; vaddr_t ps_strings; if (namelen > 2) return (ENOTDIR); if (namelen < 2) return (EINVAL); pid = name[0]; op = name[1]; switch (op) { case KERN_PROC_ARGV: case KERN_PROC_NARGV: case KERN_PROC_ENV: case KERN_PROC_NENV: break; default: return (EOPNOTSUPP); } if ((vpr = prfind(pid)) == NULL) return (ESRCH); if (oldp == NULL) { if (op == KERN_PROC_NARGV || op == KERN_PROC_NENV) *oldlenp = sizeof(int); else *oldlenp = ARG_MAX; /* XXX XXX XXX */ return (0); } /* Either system process or exiting/zombie */ if (vpr->ps_flags & (PS_SYSTEM | PS_EXITING)) return (EINVAL); /* Execing - danger. */ if ((vpr->ps_flags & PS_INEXEC)) return (EBUSY); /* Only owner or root can get env */ if ((op == KERN_PROC_NENV || op == KERN_PROC_ENV) && (vpr->ps_ucred->cr_uid != cp->p_ucred->cr_uid && (error = suser(cp)) != 0)) return (error); ps_strings = vpr->ps_strings; vm = vpr->ps_vmspace; uvmspace_addref(vm); vpr = NULL; buf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK); iov.iov_base = &pss; iov.iov_len = sizeof(pss); uio.uio_iov = &iov; uio.uio_iovcnt = 1; uio.uio_offset = (off_t)ps_strings; uio.uio_resid = sizeof(pss); uio.uio_segflg = UIO_SYSSPACE; uio.uio_rw = UIO_READ; uio.uio_procp = cp; if ((error = uvm_io(&vm->vm_map, &uio, 0)) != 0) goto out; if (op == KERN_PROC_NARGV) { error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nargvstr); goto out; } if (op == KERN_PROC_NENV) { error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nenvstr); goto out; } if (op == KERN_PROC_ARGV) { cnt = pss.ps_nargvstr; vargv = pss.ps_argvstr; } else { cnt = pss.ps_nenvstr; vargv = pss.ps_envstr; } /* -1 to have space for a terminating NUL */ limit = *oldlenp - 1; *oldlenp = 0; rargv = oldp; /* * *oldlenp - number of bytes copied out into readers buffer. * limit - maximal number of bytes allowed into readers buffer. * rarg - pointer into readers buffer where next arg will be stored. * rargv - pointer into readers buffer where the next rarg pointer * will be stored. * vargv - pointer into victim address space where the next argument * will be read. */ /* space for cnt pointers and a NULL */ rarg = (char *)(rargv + cnt + 1); *oldlenp += (cnt + 1) * sizeof(char **); while (cnt > 0 && *oldlenp < limit) { size_t len, vstrlen; /* Write to readers argv */ if ((error = copyout(&rarg, rargv, sizeof(rarg))) != 0) goto out; /* read the victim argv */ iov.iov_base = &varg; iov.iov_len = sizeof(varg); uio.uio_iov = &iov; uio.uio_iovcnt = 1; uio.uio_offset = (off_t)(vaddr_t)vargv; uio.uio_resid = sizeof(varg); uio.uio_segflg = UIO_SYSSPACE; uio.uio_rw = UIO_READ; uio.uio_procp = cp; if ((error = uvm_io(&vm->vm_map, &uio, 0)) != 0) goto out; if (varg == NULL) break; /* * read the victim arg. We must jump through hoops to avoid * crossing a page boundary too much and returning an error. */ more: len = PAGE_SIZE - (((vaddr_t)varg) & PAGE_MASK); /* leave space for the terminating NUL */ iov.iov_base = buf; iov.iov_len = len; uio.uio_iov = &iov; uio.uio_iovcnt = 1; uio.uio_offset = (off_t)(vaddr_t)varg; uio.uio_resid = len; uio.uio_segflg = UIO_SYSSPACE; uio.uio_rw = UIO_READ; uio.uio_procp = cp; if ((error = uvm_io(&vm->vm_map, &uio, 0)) != 0) goto out; for (vstrlen = 0; vstrlen < len; vstrlen++) { if (buf[vstrlen] == '\0') break; } /* Don't overflow readers buffer. */ if (*oldlenp + vstrlen + 1 >= limit) { error = ENOMEM; goto out; } if ((error = copyout(buf, rarg, vstrlen)) != 0) goto out; *oldlenp += vstrlen; rarg += vstrlen; /* The string didn't end in this page? */ if (vstrlen == len) { varg += vstrlen; goto more; } /* End of string. Terminate it with a NUL */ buf[0] = '\0'; if ((error = copyout(buf, rarg, 1)) != 0) goto out; *oldlenp += 1; rarg += 1; vargv++; rargv++; cnt--; } if (*oldlenp >= limit) { error = ENOMEM; goto out; } /* Write the terminating null */ rarg = NULL; error = copyout(&rarg, rargv, sizeof(rarg)); out: uvmspace_free(vm); free(buf, M_TEMP, PAGE_SIZE); return (error); } int sysctl_proc_cwd(int *name, u_int namelen, void *oldp, size_t *oldlenp, struct proc *cp) { struct process *findpr; struct vnode *vp; pid_t pid; int error; size_t lenused, len; char *path, *bp, *bend; if (namelen > 1) return (ENOTDIR); if (namelen < 1) return (EINVAL); pid = name[0]; if ((findpr = prfind(pid)) == NULL) return (ESRCH); if (oldp == NULL) { *oldlenp = MAXPATHLEN * 4; return (0); } /* Either system process or exiting/zombie */ if (findpr->ps_flags & (PS_SYSTEM | PS_EXITING)) return (EINVAL); /* Only owner or root can get cwd */ if (findpr->ps_ucred->cr_uid != cp->p_ucred->cr_uid && (error = suser(cp)) != 0) return (error); len = *oldlenp; if (len > MAXPATHLEN * 4) len = MAXPATHLEN * 4; else if (len < 2) return (ERANGE); *oldlenp = 0; /* snag a reference to the vnode before we can sleep */ vp = findpr->ps_fd->fd_cdir; vref(vp); path = malloc(len, M_TEMP, M_WAITOK); bp = &path[len]; bend = bp; *(--bp) = '\0'; /* Same as sys__getcwd */ error = vfs_getcwd_common(vp, NULL, &bp, path, len / 2, GETCWD_CHECK_ACCESS, cp); if (error == 0) { *oldlenp = lenused = bend - bp; error = copyout(bp, oldp, lenused); } vrele(vp); free(path, M_TEMP, len); return (error); } int sysctl_proc_nobroadcastkill(int *name, u_int namelen, void *newp, size_t newlen, void *oldp, size_t *oldlenp, struct proc *cp) { struct process *findpr; pid_t pid; int error, flag; if (namelen > 1) return (ENOTDIR); if (namelen < 1) return (EINVAL); pid = name[0]; if ((findpr = prfind(pid)) == NULL) return (ESRCH); /* Either system process or exiting/zombie */ if (findpr->ps_flags & (PS_SYSTEM | PS_EXITING)) return (EINVAL); /* Only root can change PS_NOBROADCASTKILL */ if (newp != NULL && (error = suser(cp)) != 0) return (error); /* get the PS_NOBROADCASTKILL flag */ flag = findpr->ps_flags & PS_NOBROADCASTKILL ? 1 : 0; error = sysctl_int(oldp, oldlenp, newp, newlen, &flag); if (error == 0 && newp) { if (flag) atomic_setbits_int(&findpr->ps_flags, PS_NOBROADCASTKILL); else atomic_clearbits_int(&findpr->ps_flags, PS_NOBROADCASTKILL); } return (error); } /* Arbitrary but reasonable limit for one iteration. */ #define VMMAP_MAXLEN MAXPHYS int sysctl_proc_vmmap(int *name, u_int namelen, void *oldp, size_t *oldlenp, struct proc *cp) { struct process *findpr; pid_t pid; int error; size_t oldlen, len; struct kinfo_vmentry *kve, *ukve; u_long *ustart, start; if (namelen > 1) return (ENOTDIR); if (namelen < 1) return (EINVAL); /* Provide max buffer length as hint. */ if (oldp == NULL) { if (oldlenp == NULL) return (EINVAL); else { *oldlenp = VMMAP_MAXLEN; return (0); } } pid = name[0]; if (pid == cp->p_p->ps_pid) { /* Self process mapping. */ findpr = cp->p_p; } else if (pid > 0) { if ((findpr = prfind(pid)) == NULL) return (ESRCH); /* Either system process or exiting/zombie */ if (findpr->ps_flags & (PS_SYSTEM | PS_EXITING)) return (EINVAL); #if 1 /* XXX Allow only root for now */ if ((error = suser(cp)) != 0) return (error); #else /* Only owner or root can get vmmap */ if (findpr->ps_ucred->cr_uid != cp->p_ucred->cr_uid && (error = suser(cp)) != 0) return (error); #endif } else { /* Only root can get kernel_map */ if ((error = suser(cp)) != 0) return (error); findpr = NULL; } /* Check the given size. */ oldlen = *oldlenp; if (oldlen == 0 || oldlen % sizeof(*kve) != 0) return (EINVAL); /* Deny huge allocation. */ if (oldlen > VMMAP_MAXLEN) return (EINVAL); /* * Iterate from the given address passed as the first element's * kve_start via oldp. */ ukve = (struct kinfo_vmentry *)oldp; ustart = &ukve->kve_start; error = copyin(ustart, &start, sizeof(start)); if (error != 0) return (error); /* Allocate wired memory to not block. */ kve = malloc(oldlen, M_TEMP, M_WAITOK); /* Set the base address and read entries. */ kve[0].kve_start = start; len = oldlen; error = fill_vmmap(findpr, kve, &len); if (error != 0 && error != ENOMEM) goto done; if (len == 0) goto done; KASSERT(len <= oldlen); KASSERT((len % sizeof(struct kinfo_vmentry)) == 0); error = copyout(kve, oldp, len); done: *oldlenp = len; free(kve, M_TEMP, oldlen); return (error); } #endif /* * Initialize disknames/diskstats for export by sysctl. If update is set, * then we simply update the disk statistics information. */ int sysctl_diskinit(int update, struct proc *p) { struct diskstats *sdk; struct disk *dk; const char *duid; int error, changed = 0; KERNEL_ASSERT_LOCKED(); if ((error = rw_enter(&sysctl_disklock, RW_WRITE|RW_INTR)) != 0) return error; /* Run in a loop, disks may change while malloc sleeps. */ while (disk_change) { int tlen; disk_change = 0; tlen = 0; TAILQ_FOREACH(dk, &disklist, dk_link) { if (dk->dk_name) tlen += strlen(dk->dk_name); tlen += 18; /* label uid + separators */ } tlen++; /* * The sysctl_disklock ensures that no other process can * allocate disknames and diskstats while our malloc sleeps. */ free(disknames, M_SYSCTL, disknameslen); free(diskstats, M_SYSCTL, diskstatslen); diskstats = NULL; disknames = NULL; diskstats = mallocarray(disk_count, sizeof(struct diskstats), M_SYSCTL, M_WAITOK|M_ZERO); diskstatslen = disk_count * sizeof(struct diskstats); disknames = malloc(tlen, M_SYSCTL, M_WAITOK|M_ZERO); disknameslen = tlen; disknames[0] = '\0'; changed = 1; } if (changed) { int l; l = 0; sdk = diskstats; TAILQ_FOREACH(dk, &disklist, dk_link) { duid = NULL; if (dk->dk_label && !duid_iszero(dk->dk_label->d_uid)) duid = duid_format(dk->dk_label->d_uid); snprintf(disknames + l, disknameslen - l, "%s:%s,", dk->dk_name ? dk->dk_name : "", duid ? duid : ""); l += strlen(disknames + l); strlcpy(sdk->ds_name, dk->dk_name, sizeof(sdk->ds_name)); mtx_enter(&dk->dk_mtx); sdk->ds_busy = dk->dk_busy; sdk->ds_rxfer = dk->dk_rxfer; sdk->ds_wxfer = dk->dk_wxfer; sdk->ds_seek = dk->dk_seek; sdk->ds_rbytes = dk->dk_rbytes; sdk->ds_wbytes = dk->dk_wbytes; sdk->ds_attachtime = dk->dk_attachtime; sdk->ds_timestamp = dk->dk_timestamp; sdk->ds_time = dk->dk_time; mtx_leave(&dk->dk_mtx); sdk++; } /* Eliminate trailing comma */ if (l != 0) disknames[l - 1] = '\0'; } else if (update) { /* Just update, number of drives hasn't changed */ sdk = diskstats; TAILQ_FOREACH(dk, &disklist, dk_link) { strlcpy(sdk->ds_name, dk->dk_name, sizeof(sdk->ds_name)); mtx_enter(&dk->dk_mtx); sdk->ds_busy = dk->dk_busy; sdk->ds_rxfer = dk->dk_rxfer; sdk->ds_wxfer = dk->dk_wxfer; sdk->ds_seek = dk->dk_seek; sdk->ds_rbytes = dk->dk_rbytes; sdk->ds_wbytes = dk->dk_wbytes; sdk->ds_attachtime = dk->dk_attachtime; sdk->ds_timestamp = dk->dk_timestamp; sdk->ds_time = dk->dk_time; mtx_leave(&dk->dk_mtx); sdk++; } } rw_exit_write(&sysctl_disklock); return 0; } #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) int sysctl_sysvipc(int *name, u_int namelen, void *where, size_t *sizep) { #ifdef SYSVSEM struct sem_sysctl_info *semsi; #endif #ifdef SYSVSHM struct shm_sysctl_info *shmsi; #endif size_t infosize, dssize, tsize, buflen, bufsiz; int i, nds, error, ret; void *buf; if (namelen != 1) return (EINVAL); buflen = *sizep; switch (*name) { case KERN_SYSVIPC_MSG_INFO: #ifdef SYSVMSG return (sysctl_sysvmsg(name, namelen, where, sizep)); #else return (EOPNOTSUPP); #endif case KERN_SYSVIPC_SEM_INFO: #ifdef SYSVSEM infosize = sizeof(semsi->seminfo); nds = seminfo.semmni; dssize = sizeof(semsi->semids[0]); break; #else return (EOPNOTSUPP); #endif case KERN_SYSVIPC_SHM_INFO: #ifdef SYSVSHM infosize = sizeof(shmsi->shminfo); nds = shminfo.shmmni; dssize = sizeof(shmsi->shmids[0]); break; #else return (EOPNOTSUPP); #endif default: return (EINVAL); } tsize = infosize + (nds * dssize); /* Return just the total size required. */ if (where == NULL) { *sizep = tsize; return (0); } /* Not enough room for even the info struct. */ if (buflen < infosize) { *sizep = 0; return (ENOMEM); } bufsiz = min(tsize, buflen); buf = malloc(bufsiz, M_TEMP, M_WAITOK|M_ZERO); switch (*name) { #ifdef SYSVSEM case KERN_SYSVIPC_SEM_INFO: semsi = (struct sem_sysctl_info *)buf; semsi->seminfo = seminfo; break; #endif #ifdef SYSVSHM case KERN_SYSVIPC_SHM_INFO: shmsi = (struct shm_sysctl_info *)buf; shmsi->shminfo = shminfo; break; #endif } buflen -= infosize; ret = 0; if (buflen > 0) { /* Fill in the IPC data structures. */ for (i = 0; i < nds; i++) { if (buflen < dssize) { ret = ENOMEM; break; } switch (*name) { #ifdef SYSVSEM case KERN_SYSVIPC_SEM_INFO: if (sema[i] != NULL) memcpy(&semsi->semids[i], sema[i], dssize); else memset(&semsi->semids[i], 0, dssize); break; #endif #ifdef SYSVSHM case KERN_SYSVIPC_SHM_INFO: if (shmsegs[i] != NULL) memcpy(&shmsi->shmids[i], shmsegs[i], dssize); else memset(&shmsi->shmids[i], 0, dssize); break; #endif } buflen -= dssize; } } *sizep -= buflen; error = copyout(buf, where, *sizep); free(buf, M_TEMP, bufsiz); /* If copyout succeeded, use return code set earlier. */ return (error ? error : ret); } #endif /* SYSVMSG || SYSVSEM || SYSVSHM */ #ifndef SMALL_KERNEL int sysctl_intrcnt(int *name, u_int namelen, void *oldp, size_t *oldlenp) { return (evcount_sysctl(name, namelen, oldp, oldlenp, NULL, 0)); } int sysctl_sensors(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { struct ksensor *ks; struct sensor *us; struct ksensordev *ksd; struct sensordev *usd; int dev, numt, ret; enum sensor_type type; if (namelen != 1 && namelen != 3) return (ENOTDIR); dev = name[0]; if (namelen == 1) { ret = sensordev_get(dev, &ksd); if (ret) return (ret); /* Grab a copy, to clear the kernel pointers */ usd = malloc(sizeof(*usd), M_TEMP, M_WAITOK|M_ZERO); usd->num = ksd->num; strlcpy(usd->xname, ksd->xname, sizeof(usd->xname)); memcpy(usd->maxnumt, ksd->maxnumt, sizeof(usd->maxnumt)); usd->sensors_count = ksd->sensors_count; ret = sysctl_rdstruct(oldp, oldlenp, newp, usd, sizeof(struct sensordev)); free(usd, M_TEMP, sizeof(*usd)); return (ret); } type = name[1]; numt = name[2]; ret = sensor_find(dev, type, numt, &ks); if (ret) return (ret); /* Grab a copy, to clear the kernel pointers */ us = malloc(sizeof(*us), M_TEMP, M_WAITOK|M_ZERO); memcpy(us->desc, ks->desc, sizeof(us->desc)); us->tv = ks->tv; us->value = ks->value; us->type = ks->type; us->status = ks->status; us->numt = ks->numt; us->flags = ks->flags; ret = sysctl_rdstruct(oldp, oldlenp, newp, us, sizeof(struct sensor)); free(us, M_TEMP, sizeof(*us)); return (ret); } #endif /* SMALL_KERNEL */ int sysctl_cptime2(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { CPU_INFO_ITERATOR cii; struct cpu_info *ci; int found = 0; if (namelen != 1) return (ENOTDIR); CPU_INFO_FOREACH(cii, ci) { if (name[0] == CPU_INFO_UNIT(ci)) { found = 1; break; } } if (!found) return (ENOENT); return (sysctl_rdstruct(oldp, oldlenp, newp, &ci->ci_schedstate.spc_cp_time, sizeof(ci->ci_schedstate.spc_cp_time))); } #if NAUDIO > 0 int sysctl_audio(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { if (namelen != 1) return (ENOTDIR); if (name[0] != KERN_AUDIO_RECORD) return (ENOENT); return (sysctl_int(oldp, oldlenp, newp, newlen, &audio_record_enable)); } #endif #if NVIDEO > 0 int sysctl_video(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { if (namelen != 1) return (ENOTDIR); if (name[0] != KERN_VIDEO_RECORD) return (ENOENT); return (sysctl_int(oldp, oldlenp, newp, newlen, &video_record_enable)); } #endif int sysctl_cpustats(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { CPU_INFO_ITERATOR cii; struct cpustats cs; struct cpu_info *ci; int found = 0; if (namelen != 1) return (ENOTDIR); CPU_INFO_FOREACH(cii, ci) { if (name[0] == CPU_INFO_UNIT(ci)) { found = 1; break; } } if (!found) return (ENOENT); memset(&cs, 0, sizeof cs); memcpy(&cs.cs_time, &ci->ci_schedstate.spc_cp_time, sizeof(cs.cs_time)); cs.cs_flags = 0; if (cpu_is_online(ci)) cs.cs_flags |= CPUSTATS_ONLINE; return (sysctl_rdstruct(oldp, oldlenp, newp, &cs, sizeof(cs))); } int sysctl_utc_offset(void *oldp, size_t *oldlenp, void *newp, size_t newlen) { struct timespec adjusted, now; int adjustment_seconds, error, new_offset_minutes, old_offset_minutes; old_offset_minutes = utc_offset / 60; /* seconds -> minutes */ new_offset_minutes = old_offset_minutes; error = sysctl_securelevel_int(oldp, oldlenp, newp, newlen, &new_offset_minutes); if (error) return error; if (new_offset_minutes < -24 * 60 || new_offset_minutes > 24 * 60) return EINVAL; if (new_offset_minutes == old_offset_minutes) return 0; utc_offset = new_offset_minutes * 60; /* minutes -> seconds */ adjustment_seconds = (new_offset_minutes - old_offset_minutes) * 60; nanotime(&now); adjusted = now; adjusted.tv_sec -= adjustment_seconds; tc_setrealtimeclock(&adjusted); resettodr(); return 0; }
2 2 2 2 217 216 218 2 2 213 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 /* $OpenBSD: ip_spd.c,v 1.120 2024/04/17 20:48:51 bluhm Exp $ */ /* * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) * * Copyright (c) 2000-2001 Angelos D. Keromytis. * * Permission to use, copy, and modify this software with or without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or * modification of this software. * You may use this code under the GNU public license if you so wish. Please * contribute changes back to the authors under this freer than GPL license * so that we may further the use of strong encryption without limitations to * all. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR * PURPOSE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/kernel.h> #include <sys/socketvar.h> #include <sys/pool.h> #include <sys/timeout.h> #include <net/route.h> #include <net/netisr.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_var.h> #include <netinet/in_pcb.h> #include <netinet/ip_ipsp.h> #include <net/pfkeyv2.h> int ipsp_spd_inp(struct mbuf *, const struct ipsec_level *, struct ipsec_policy *, struct tdb **); int ipsp_acquire_sa(struct ipsec_policy *, union sockaddr_union *, union sockaddr_union *, struct sockaddr_encap *, struct mbuf *); int ipsp_pending_acquire(struct ipsec_policy *, union sockaddr_union *); void ipsp_delete_acquire_timer(void *); void ipsp_delete_acquire_locked(struct ipsec_acquire *); void ipsp_delete_acquire(struct ipsec_acquire *); void ipsp_unref_acquire_locked(struct ipsec_acquire *); struct pool ipsec_policy_pool; struct pool ipsec_acquire_pool; /* * For tdb_walk() calling tdb_delete_locked() we need lock order * tdb_sadb_mtx before ipo_tdb_mtx. */ struct mutex ipo_tdb_mtx = MUTEX_INITIALIZER(IPL_SOFTNET); /* Protected by the NET_LOCK(). */ struct radix_node_head **spd_tables; unsigned int spd_table_max; struct mutex ipsec_acquire_mtx = MUTEX_INITIALIZER(IPL_SOFTNET); struct ipsec_acquire_head ipsec_acquire_head = TAILQ_HEAD_INITIALIZER(ipsec_acquire_head); struct radix_node_head * spd_table_get(unsigned int rtableid) { unsigned int rdomain; NET_ASSERT_LOCKED(); if (spd_tables == NULL) return (NULL); rdomain = rtable_l2(rtableid); if (rdomain > spd_table_max) return (NULL); return (spd_tables[rdomain]); } struct radix_node_head * spd_table_add(unsigned int rtableid) { struct radix_node_head *rnh = NULL; unsigned int rdomain; void *p; NET_ASSERT_LOCKED_EXCLUSIVE(); rdomain = rtable_l2(rtableid); if (spd_tables == NULL || rdomain > spd_table_max) { if ((p = mallocarray(rdomain + 1, sizeof(*rnh), M_RTABLE, M_NOWAIT|M_ZERO)) == NULL) return (NULL); if (spd_tables != NULL) { memcpy(p, spd_tables, sizeof(*rnh) * (spd_table_max+1)); free(spd_tables, M_RTABLE, sizeof(*rnh) * (spd_table_max+1)); } spd_tables = p; spd_table_max = rdomain; } if (spd_tables[rdomain] == NULL) { if (rn_inithead((void **)&rnh, offsetof(struct sockaddr_encap, sen_type)) == 0) rnh = NULL; spd_tables[rdomain] = rnh; } return (spd_tables[rdomain]); } int spd_table_walk(unsigned int rtableid, int (*func)(struct ipsec_policy *, void *, unsigned int), void *arg) { struct radix_node_head *rnh; int (*walker)(struct radix_node *, void *, u_int) = (void *)func; int error; rnh = spd_table_get(rtableid); if (rnh == NULL) return (0); /* EGAIN means the tree changed. */ while ((error = rn_walktree(rnh, walker, arg)) == EAGAIN) continue; return (error); } /* * Lookup at the SPD based on the headers contained on the mbuf. The second * argument indicates what protocol family the header at the beginning of * the mbuf is. hlen is the offset of the transport protocol header * in the mbuf. * * Return combinations (of return value and *tdbout): * - -EINVAL -> silently drop the packet * - errno -> drop packet and return error * - 0/NULL -> no IPsec required on packet * - 0/TDB -> do IPsec * * In the case of incoming flows, only the first three combinations are * returned. */ int ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int direction, struct tdb *tdbin, const struct ipsec_level *seclevel, struct tdb **tdbout, struct ipsec_ids *ipsecflowinfo_ids) { struct radix_node_head *rnh; struct radix_node *rn; union sockaddr_union sdst, ssrc; struct sockaddr_encap *ddst, dst; struct ipsec_policy *ipo; struct ipsec_ids *ids = NULL; int error, signore = 0, dignore = 0; u_int rdomain; NET_ASSERT_LOCKED(); /* * If there are no flows in place, there's no point * continuing with the SPD lookup. */ if (!ipsec_in_use) return ipsp_spd_inp(m, seclevel, NULL, tdbout); /* * If an input packet is destined to a BYPASS socket, just accept it. */ if ((seclevel != NULL) && (direction == IPSP_DIRECTION_IN) && (seclevel->sl_esp_trans == IPSEC_LEVEL_BYPASS) && (seclevel->sl_esp_network == IPSEC_LEVEL_BYPASS) && (seclevel->sl_auth == IPSEC_LEVEL_BYPASS)) { if (tdbout != NULL) *tdbout = NULL; return 0; } memset(&dst, 0, sizeof(dst)); memset(&sdst, 0, sizeof(union sockaddr_union)); memset(&ssrc, 0, sizeof(union sockaddr_union)); ddst = (struct sockaddr_encap *)&dst; ddst->sen_family = PF_KEY; ddst->sen_len = SENT_LEN; switch (af) { case AF_INET: if (hlen < sizeof (struct ip) || m->m_pkthdr.len < hlen) return EINVAL; ddst->sen_direction = direction; ddst->sen_type = SENT_IP4; m_copydata(m, offsetof(struct ip, ip_src), sizeof(struct in_addr), (caddr_t) &(ddst->sen_ip_src)); m_copydata(m, offsetof(struct ip, ip_dst), sizeof(struct in_addr), (caddr_t) &(ddst->sen_ip_dst)); m_copydata(m, offsetof(struct ip, ip_p), sizeof(u_int8_t), (caddr_t) &(ddst->sen_proto)); sdst.sin.sin_family = ssrc.sin.sin_family = AF_INET; sdst.sin.sin_len = ssrc.sin.sin_len = sizeof(struct sockaddr_in); ssrc.sin.sin_addr = ddst->sen_ip_src; sdst.sin.sin_addr = ddst->sen_ip_dst; /* * If TCP/UDP, extract the port numbers to use in the lookup. */ switch (ddst->sen_proto) { case IPPROTO_UDP: case IPPROTO_TCP: /* Make sure there's enough data in the packet. */ if (m->m_pkthdr.len < hlen + 2 * sizeof(u_int16_t)) return EINVAL; /* * Luckily, the offset of the src/dst ports in * both the UDP and TCP headers is the same (first * two 16-bit values in the respective headers), * so we can just copy them. */ m_copydata(m, hlen, sizeof(u_int16_t), (caddr_t) &(ddst->sen_sport)); m_copydata(m, hlen + sizeof(u_int16_t), sizeof(u_int16_t), (caddr_t) &(ddst->sen_dport)); break; default: ddst->sen_sport = 0; ddst->sen_dport = 0; } break; #ifdef INET6 case AF_INET6: if (hlen < sizeof (struct ip6_hdr) || m->m_pkthdr.len < hlen) return EINVAL; ddst->sen_type = SENT_IP6; ddst->sen_ip6_direction = direction; m_copydata(m, offsetof(struct ip6_hdr, ip6_src), sizeof(struct in6_addr), (caddr_t) &(ddst->sen_ip6_src)); m_copydata(m, offsetof(struct ip6_hdr, ip6_dst), sizeof(struct in6_addr), (caddr_t) &(ddst->sen_ip6_dst)); m_copydata(m, offsetof(struct ip6_hdr, ip6_nxt), sizeof(u_int8_t), (caddr_t) &(ddst->sen_ip6_proto)); sdst.sin6.sin6_family = ssrc.sin6.sin6_family = AF_INET6; sdst.sin6.sin6_len = ssrc.sin6.sin6_len = sizeof(struct sockaddr_in6); in6_recoverscope(&ssrc.sin6, &ddst->sen_ip6_src); in6_recoverscope(&sdst.sin6, &ddst->sen_ip6_dst); /* * If TCP/UDP, extract the port numbers to use in the lookup. */ switch (ddst->sen_ip6_proto) { case IPPROTO_UDP: case IPPROTO_TCP: /* Make sure there's enough data in the packet. */ if (m->m_pkthdr.len < hlen + 2 * sizeof(u_int16_t)) return EINVAL; /* * Luckily, the offset of the src/dst ports in * both the UDP and TCP headers is the same * (first two 16-bit values in the respective * headers), so we can just copy them. */ m_copydata(m, hlen, sizeof(u_int16_t), (caddr_t) &(ddst->sen_ip6_sport)); m_copydata(m, hlen + sizeof(u_int16_t), sizeof(u_int16_t), (caddr_t) &(ddst->sen_ip6_dport)); break; default: ddst->sen_ip6_sport = 0; ddst->sen_ip6_dport = 0; } break; #endif /* INET6 */ default: return EAFNOSUPPORT; } /* Actual SPD lookup. */ rdomain = rtable_l2(m->m_pkthdr.ph_rtableid); if ((rnh = spd_table_get(rdomain)) == NULL || (rn = rn_match((caddr_t)&dst, rnh)) == NULL) { /* * Return whatever the socket requirements are, there are no * system-wide policies. */ return ipsp_spd_inp(m, seclevel, NULL, tdbout); } ipo = (struct ipsec_policy *)rn; switch (ipo->ipo_type) { case IPSP_PERMIT: return ipsp_spd_inp(m, seclevel, ipo, tdbout); case IPSP_DENY: return EHOSTUNREACH; case IPSP_IPSEC_USE: case IPSP_IPSEC_ACQUIRE: case IPSP_IPSEC_REQUIRE: case IPSP_IPSEC_DONTACQ: /* Nothing more needed here. */ break; default: return EINVAL; } /* Check for non-specific destination in the policy. */ switch (ipo->ipo_dst.sa.sa_family) { case AF_INET: if ((ipo->ipo_dst.sin.sin_addr.s_addr == INADDR_ANY) || (ipo->ipo_dst.sin.sin_addr.s_addr == INADDR_BROADCAST)) dignore = 1; break; #ifdef INET6 case AF_INET6: if ((IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_dst.sin6.sin6_addr)) || (memcmp(&ipo->ipo_dst.sin6.sin6_addr, &in6mask128, sizeof(in6mask128)) == 0)) dignore = 1; break; #endif /* INET6 */ } /* Likewise for source. */ switch (ipo->ipo_src.sa.sa_family) { case AF_INET: if (ipo->ipo_src.sin.sin_addr.s_addr == INADDR_ANY) signore = 1; break; #ifdef INET6 case AF_INET6: if (IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_src.sin6.sin6_addr)) signore = 1; break; #endif /* INET6 */ } /* Do we have a cached entry ? If so, check if it's still valid. */ mtx_enter(&ipo_tdb_mtx); if (ipo->ipo_tdb != NULL && (ipo->ipo_tdb->tdb_flags & TDBF_INVALID)) { TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo, ipo_tdb_next); tdb_unref(ipo->ipo_tdb); ipo->ipo_tdb = NULL; } mtx_leave(&ipo_tdb_mtx); /* Outgoing packet policy check. */ if (direction == IPSP_DIRECTION_OUT) { /* * If the packet is destined for the policy-specified * gateway/endhost, and the socket has the BYPASS * option set, skip IPsec processing. */ if ((seclevel != NULL) && (seclevel->sl_esp_trans == IPSEC_LEVEL_BYPASS) && (seclevel->sl_esp_network == IPSEC_LEVEL_BYPASS) && (seclevel->sl_auth == IPSEC_LEVEL_BYPASS)) { /* Direct match. */ if (dignore || !memcmp(&sdst, &ipo->ipo_dst, sdst.sa.sa_len)) { if (tdbout != NULL) *tdbout = NULL; return 0; } } /* Check that the cached TDB (if present), is appropriate. */ mtx_enter(&ipo_tdb_mtx); if (ipo->ipo_tdb != NULL) { if ((ipo->ipo_last_searched <= ipsec_last_added) || (ipo->ipo_sproto != ipo->ipo_tdb->tdb_sproto) || memcmp(dignore ? &sdst : &ipo->ipo_dst, &ipo->ipo_tdb->tdb_dst, ipo->ipo_tdb->tdb_dst.sa.sa_len)) goto nomatchout; if (!ipsp_aux_match(ipo->ipo_tdb, ipsecflowinfo_ids? ipsecflowinfo_ids: ipo->ipo_ids, &ipo->ipo_addr, &ipo->ipo_mask)) goto nomatchout; /* Cached entry is good. */ error = ipsp_spd_inp(m, seclevel, ipo, tdbout); mtx_leave(&ipo_tdb_mtx); return error; nomatchout: /* Cached TDB was not good. */ TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo, ipo_tdb_next); tdb_unref(ipo->ipo_tdb); ipo->ipo_tdb = NULL; ipo->ipo_last_searched = 0; } /* * If no SA has been added since the last time we did a * lookup, there's no point searching for one. However, if the * destination gateway is left unspecified (or is all-1's), * always lookup since this is a generic-match rule * (otherwise, we can have situations where SAs to some * destinations exist but are not used, possibly leading to an * explosion in the number of acquired SAs). */ if (ipo->ipo_last_searched <= ipsec_last_added) { struct tdb *tdbp_new; /* "Touch" the entry. */ if (dignore == 0) ipo->ipo_last_searched = getuptime(); /* gettdb() takes tdb_sadb_mtx, preserve lock order */ mtx_leave(&ipo_tdb_mtx); /* Find an appropriate SA from the existing ones. */ tdbp_new = gettdbbydst(rdomain, dignore ? &sdst : &ipo->ipo_dst, ipo->ipo_sproto, ipsecflowinfo_ids? ipsecflowinfo_ids: ipo->ipo_ids, &ipo->ipo_addr, &ipo->ipo_mask); ids = NULL; mtx_enter(&ipo_tdb_mtx); if ((tdbp_new != NULL) && (tdbp_new->tdb_flags & TDBF_DELETED)) { /* * After tdb_delete() has released ipo_tdb_mtx * in tdb_unlink(), never add a new one. * tdb_cleanspd() has to catch all of them. */ tdb_unref(tdbp_new); tdbp_new = NULL; } if (ipo->ipo_tdb != NULL) { /* Remove cached TDB from parallel thread. */ TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo, ipo_tdb_next); tdb_unref(ipo->ipo_tdb); } ipo->ipo_tdb = tdbp_new; if (ipo->ipo_tdb != NULL) { /* gettdbbydst() has already refcounted tdb */ TAILQ_INSERT_TAIL( &ipo->ipo_tdb->tdb_policy_head, ipo, ipo_tdb_next); error = ipsp_spd_inp(m, seclevel, ipo, tdbout); mtx_leave(&ipo_tdb_mtx); return error; } } mtx_leave(&ipo_tdb_mtx); /* So, we don't have an SA -- just a policy. */ switch (ipo->ipo_type) { case IPSP_IPSEC_REQUIRE: /* Acquire SA through key management. */ if (ipsp_acquire_sa(ipo, dignore ? &sdst : &ipo->ipo_dst, signore ? NULL : &ipo->ipo_src, ddst, m) != 0) { return EACCES; } /* FALLTHROUGH */ case IPSP_IPSEC_DONTACQ: return -EINVAL; /* Silently drop packet. */ case IPSP_IPSEC_ACQUIRE: /* Acquire SA through key management. */ ipsp_acquire_sa(ipo, dignore ? &sdst : &ipo->ipo_dst, signore ? NULL : &ipo->ipo_src, ddst, NULL); /* FALLTHROUGH */ case IPSP_IPSEC_USE: return ipsp_spd_inp(m, seclevel, ipo, tdbout); } } else { /* IPSP_DIRECTION_IN */ if (tdbin != NULL) { /* * Special case for bundled IPcomp/ESP SAs: * 1) only IPcomp flows are loaded into kernel * 2) input processing processes ESP SA first * 3) then optional IPcomp processing happens * 4) we only update m_tag for ESP * => 'tdbin' is always set to ESP SA * => flow has ipo_proto for IPcomp * So if 'tdbin' points to an ESP SA and this 'tdbin' is * bundled with an IPcomp SA, then we replace 'tdbin' * with the IPcomp SA at tdbin->tdb_inext. */ if (ipo->ipo_sproto == IPPROTO_IPCOMP && tdbin->tdb_sproto == IPPROTO_ESP && tdbin->tdb_inext != NULL && tdbin->tdb_inext->tdb_sproto == IPPROTO_IPCOMP) tdbin = tdbin->tdb_inext; /* Direct match in the cache. */ mtx_enter(&ipo_tdb_mtx); if (ipo->ipo_tdb == tdbin) { error = ipsp_spd_inp(m, seclevel, ipo, tdbout); mtx_leave(&ipo_tdb_mtx); return error; } mtx_leave(&ipo_tdb_mtx); if (memcmp(dignore ? &ssrc : &ipo->ipo_dst, &tdbin->tdb_src, tdbin->tdb_src.sa.sa_len) || (ipo->ipo_sproto != tdbin->tdb_sproto)) goto nomatchin; /* Match source/dest IDs. */ if (ipo->ipo_ids) if (tdbin->tdb_ids == NULL || !ipsp_ids_match(ipo->ipo_ids, tdbin->tdb_ids)) goto nomatchin; /* Add it to the cache. */ mtx_enter(&ipo_tdb_mtx); if (ipo->ipo_tdb != NULL) { TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo, ipo_tdb_next); tdb_unref(ipo->ipo_tdb); } ipo->ipo_tdb = tdb_ref(tdbin); TAILQ_INSERT_TAIL(&tdbin->tdb_policy_head, ipo, ipo_tdb_next); error = ipsp_spd_inp(m, seclevel, ipo, tdbout); mtx_leave(&ipo_tdb_mtx); return error; nomatchin: /* Nothing needed here, falling through */ ; } /* Check whether cached entry applies. */ mtx_enter(&ipo_tdb_mtx); if (ipo->ipo_tdb != NULL) { /* * We only need to check that the correct * security protocol and security gateway are * set; IDs will be the same since the cached * entry is linked on this policy. */ if (ipo->ipo_sproto == ipo->ipo_tdb->tdb_sproto && !memcmp(&ipo->ipo_tdb->tdb_src, dignore ? &ssrc : &ipo->ipo_dst, ipo->ipo_tdb->tdb_src.sa.sa_len)) goto skipinputsearch; /* Not applicable, unlink. */ TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo, ipo_tdb_next); tdb_unref(ipo->ipo_tdb); ipo->ipo_tdb = NULL; ipo->ipo_last_searched = 0; } /* Find whether there exists an appropriate SA. */ if (ipo->ipo_last_searched <= ipsec_last_added) { struct tdb *tdbp_new; if (dignore == 0) ipo->ipo_last_searched = getuptime(); /* gettdb() takes tdb_sadb_mtx, preserve lock order */ mtx_leave(&ipo_tdb_mtx); tdbp_new = gettdbbysrc(rdomain, dignore ? &ssrc : &ipo->ipo_dst, ipo->ipo_sproto, ipo->ipo_ids, &ipo->ipo_addr, &ipo->ipo_mask); mtx_enter(&ipo_tdb_mtx); if ((tdbp_new != NULL) && (tdbp_new->tdb_flags & TDBF_DELETED)) { /* * After tdb_delete() has released ipo_tdb_mtx * in tdb_unlink(), never add a new one. * tdb_cleanspd() has to catch all of them. */ tdb_unref(tdbp_new); tdbp_new = NULL; } if (ipo->ipo_tdb != NULL) { /* Remove cached TDB from parallel thread. */ TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo, ipo_tdb_next); tdb_unref(ipo->ipo_tdb); } ipo->ipo_tdb = tdbp_new; if (ipo->ipo_tdb != NULL) { /* gettdbbysrc() has already refcounted tdb */ TAILQ_INSERT_TAIL( &ipo->ipo_tdb->tdb_policy_head, ipo, ipo_tdb_next); } } skipinputsearch: mtx_leave(&ipo_tdb_mtx); switch (ipo->ipo_type) { case IPSP_IPSEC_REQUIRE: /* If appropriate SA exists, don't acquire another. */ if (ipo->ipo_tdb != NULL) return -EINVAL; /* Silently drop packet. */ /* Acquire SA through key management. */ if ((error = ipsp_acquire_sa(ipo, dignore ? &ssrc : &ipo->ipo_dst, signore ? NULL : &ipo->ipo_src, ddst, m)) != 0) return error; /* FALLTHROUGH */ case IPSP_IPSEC_DONTACQ: return -EINVAL; /* Silently drop packet. */ case IPSP_IPSEC_ACQUIRE: /* If appropriate SA exists, don't acquire another. */ if (ipo->ipo_tdb != NULL) return ipsp_spd_inp(m, seclevel, ipo, tdbout); /* Acquire SA through key management. */ ipsp_acquire_sa(ipo, dignore ? &ssrc : &ipo->ipo_dst, signore ? NULL : &ipo->ipo_src, ddst, NULL); /* FALLTHROUGH */ case IPSP_IPSEC_USE: return ipsp_spd_inp(m, seclevel, ipo, tdbout); } } /* Shouldn't ever get this far. */ return EINVAL; } /* * Delete a policy from the SPD. */ int ipsec_delete_policy(struct ipsec_policy *ipo) { struct ipsec_acquire *ipa; struct radix_node_head *rnh; struct radix_node *rn = (struct radix_node *)ipo; NET_ASSERT_LOCKED_EXCLUSIVE(); if (refcnt_rele(&ipo->ipo_refcnt) == 0) return 0; /* Delete from SPD. */ if ((rnh = spd_table_get(ipo->ipo_rdomain)) == NULL || rn_delete(&ipo->ipo_addr, &ipo->ipo_mask, rnh, rn) == NULL) return (ESRCH); mtx_enter(&ipo_tdb_mtx); if (ipo->ipo_tdb != NULL) { TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo, ipo_tdb_next); tdb_unref(ipo->ipo_tdb); ipo->ipo_tdb = NULL; } mtx_leave(&ipo_tdb_mtx); mtx_enter(&ipsec_acquire_mtx); while ((ipa = TAILQ_FIRST(&ipo->ipo_acquires)) != NULL) ipsp_delete_acquire_locked(ipa); mtx_leave(&ipsec_acquire_mtx); TAILQ_REMOVE(&ipsec_policy_head, ipo, ipo_list); if (ipo->ipo_ids) ipsp_ids_free(ipo->ipo_ids); ipsec_in_use--; pool_put(&ipsec_policy_pool, ipo); return 0; } void ipsp_delete_acquire_timer(void *v) { struct ipsec_acquire *ipa = v; mtx_enter(&ipsec_acquire_mtx); refcnt_rele(&ipa->ipa_refcnt); ipsp_delete_acquire_locked(ipa); mtx_leave(&ipsec_acquire_mtx); } /* * Delete a pending IPsec acquire record. */ void ipsp_delete_acquire(struct ipsec_acquire *ipa) { mtx_enter(&ipsec_acquire_mtx); ipsp_delete_acquire_locked(ipa); mtx_leave(&ipsec_acquire_mtx); } void ipsp_delete_acquire_locked(struct ipsec_acquire *ipa) { if (timeout_del(&ipa->ipa_timeout) == 1) refcnt_rele(&ipa->ipa_refcnt); ipsp_unref_acquire_locked(ipa); } void ipsec_unref_acquire(struct ipsec_acquire *ipa) { mtx_enter(&ipsec_acquire_mtx); ipsp_unref_acquire_locked(ipa); mtx_leave(&ipsec_acquire_mtx); } void ipsp_unref_acquire_locked(struct ipsec_acquire *ipa) { MUTEX_ASSERT_LOCKED(&ipsec_acquire_mtx); if (refcnt_rele(&ipa->ipa_refcnt) == 0) return; TAILQ_REMOVE(&ipsec_acquire_head, ipa, ipa_next); TAILQ_REMOVE(&ipa->ipa_policy->ipo_acquires, ipa, ipa_ipo_next); ipa->ipa_policy = NULL; pool_put(&ipsec_acquire_pool, ipa); } /* * Find out if there's an ACQUIRE pending. * XXX Need a better structure. */ int ipsp_pending_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw) { struct ipsec_acquire *ipa; NET_ASSERT_LOCKED(); mtx_enter(&ipsec_acquire_mtx); TAILQ_FOREACH(ipa, &ipo->ipo_acquires, ipa_ipo_next) { if (!memcmp(gw, &ipa->ipa_addr, gw->sa.sa_len)) break; } mtx_leave(&ipsec_acquire_mtx); return (ipa != NULL); } /* * Signal key management that we need an SA. * XXX For outgoing policies, we could try to hold on to the mbuf. */ int ipsp_acquire_sa(struct ipsec_policy *ipo, union sockaddr_union *gw, union sockaddr_union *laddr, struct sockaddr_encap *ddst, struct mbuf *m) { struct ipsec_acquire *ipa; NET_ASSERT_LOCKED(); /* Check whether request has been made already. */ if (ipsp_pending_acquire(ipo, gw)) return 0; /* Add request in cache and proceed. */ ipa = pool_get(&ipsec_acquire_pool, PR_NOWAIT|PR_ZERO); if (ipa == NULL) return ENOMEM; ipa->ipa_addr = *gw; refcnt_init(&ipa->ipa_refcnt); timeout_set(&ipa->ipa_timeout, ipsp_delete_acquire_timer, ipa); ipa->ipa_info.sen_len = ipa->ipa_mask.sen_len = SENT_LEN; ipa->ipa_info.sen_family = ipa->ipa_mask.sen_family = PF_KEY; /* Just copy the right information. */ switch (ipo->ipo_addr.sen_type) { case SENT_IP4: ipa->ipa_info.sen_type = ipa->ipa_mask.sen_type = SENT_IP4; ipa->ipa_info.sen_direction = ipo->ipo_addr.sen_direction; ipa->ipa_mask.sen_direction = ipo->ipo_mask.sen_direction; if (ipsp_is_unspecified(ipo->ipo_dst)) { ipa->ipa_info.sen_ip_src = ddst->sen_ip_src; ipa->ipa_mask.sen_ip_src.s_addr = INADDR_BROADCAST; ipa->ipa_info.sen_ip_dst = ddst->sen_ip_dst; ipa->ipa_mask.sen_ip_dst.s_addr = INADDR_BROADCAST; } else { ipa->ipa_info.sen_ip_src = ipo->ipo_addr.sen_ip_src; ipa->ipa_mask.sen_ip_src = ipo->ipo_mask.sen_ip_src; ipa->ipa_info.sen_ip_dst = ipo->ipo_addr.sen_ip_dst; ipa->ipa_mask.sen_ip_dst = ipo->ipo_mask.sen_ip_dst; } ipa->ipa_info.sen_proto = ipo->ipo_addr.sen_proto; ipa->ipa_mask.sen_proto = ipo->ipo_mask.sen_proto; if (ipo->ipo_addr.sen_proto) { ipa->ipa_info.sen_sport = ipo->ipo_addr.sen_sport; ipa->ipa_mask.sen_sport = ipo->ipo_mask.sen_sport; ipa->ipa_info.sen_dport = ipo->ipo_addr.sen_dport; ipa->ipa_mask.sen_dport = ipo->ipo_mask.sen_dport; } break; #ifdef INET6 case SENT_IP6: ipa->ipa_info.sen_type = ipa->ipa_mask.sen_type = SENT_IP6; ipa->ipa_info.sen_ip6_direction = ipo->ipo_addr.sen_ip6_direction; ipa->ipa_mask.sen_ip6_direction = ipo->ipo_mask.sen_ip6_direction; if (ipsp_is_unspecified(ipo->ipo_dst)) { ipa->ipa_info.sen_ip6_src = ddst->sen_ip6_src; ipa->ipa_mask.sen_ip6_src = in6mask128; ipa->ipa_info.sen_ip6_dst = ddst->sen_ip6_dst; ipa->ipa_mask.sen_ip6_dst = in6mask128; } else { ipa->ipa_info.sen_ip6_src = ipo->ipo_addr.sen_ip6_src; ipa->ipa_mask.sen_ip6_src = ipo->ipo_mask.sen_ip6_src; ipa->ipa_info.sen_ip6_dst = ipo->ipo_addr.sen_ip6_dst; ipa->ipa_mask.sen_ip6_dst = ipo->ipo_mask.sen_ip6_dst; } ipa->ipa_info.sen_ip6_proto = ipo->ipo_addr.sen_ip6_proto; ipa->ipa_mask.sen_ip6_proto = ipo->ipo_mask.sen_ip6_proto; if (ipo->ipo_mask.sen_ip6_proto) { ipa->ipa_info.sen_ip6_sport = ipo->ipo_addr.sen_ip6_sport; ipa->ipa_mask.sen_ip6_sport = ipo->ipo_mask.sen_ip6_sport; ipa->ipa_info.sen_ip6_dport = ipo->ipo_addr.sen_ip6_dport; ipa->ipa_mask.sen_ip6_dport = ipo->ipo_mask.sen_ip6_dport; } break; #endif /* INET6 */ default: pool_put(&ipsec_acquire_pool, ipa); return 0; } mtx_enter(&ipsec_acquire_mtx); #ifdef IPSEC if (timeout_add_sec(&ipa->ipa_timeout, ipsec_expire_acquire) == 1) refcnt_take(&ipa->ipa_refcnt); #endif TAILQ_INSERT_TAIL(&ipsec_acquire_head, ipa, ipa_next); TAILQ_INSERT_TAIL(&ipo->ipo_acquires, ipa, ipa_ipo_next); ipa->ipa_policy = ipo; mtx_leave(&ipsec_acquire_mtx); /* PF_KEYv2 notification message. */ return pfkeyv2_acquire(ipo, gw, laddr, &ipa->ipa_seq, ddst); } /* * Deal with PCB security requirements. */ int ipsp_spd_inp(struct mbuf *m, const struct ipsec_level *seclevel, struct ipsec_policy *ipo, struct tdb **tdbout) { /* Sanity check. */ if (seclevel == NULL) goto justreturn; /* We only support IPSEC_LEVEL_BYPASS or IPSEC_LEVEL_AVAIL */ if (seclevel->sl_esp_trans == IPSEC_LEVEL_BYPASS && seclevel->sl_esp_network == IPSEC_LEVEL_BYPASS && seclevel->sl_auth == IPSEC_LEVEL_BYPASS) goto justreturn; if (seclevel->sl_esp_trans == IPSEC_LEVEL_AVAIL && seclevel->sl_esp_network == IPSEC_LEVEL_AVAIL && seclevel->sl_auth == IPSEC_LEVEL_AVAIL) goto justreturn; return -EINVAL; /* Silently drop packet. */ justreturn: if (tdbout != NULL) { if (ipo != NULL) *tdbout = tdb_ref(ipo->ipo_tdb); else *tdbout = NULL; } return 0; } /* * Find a pending ACQUIRE record based on its sequence number. * XXX Need to use a better data structure. */ struct ipsec_acquire * ipsec_get_acquire(u_int32_t seq) { struct ipsec_acquire *ipa; NET_ASSERT_LOCKED(); mtx_enter(&ipsec_acquire_mtx); TAILQ_FOREACH(ipa, &ipsec_acquire_head, ipa_next) { if (ipa->ipa_seq == seq) { refcnt_take(&ipa->ipa_refcnt); break; } } mtx_leave(&ipsec_acquire_mtx); return ipa; }
10 10 5 5 5 5 10 10 10 10 10 10 10 10 2 3 4 1 2 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 /* $OpenBSD: kern_clockintr.c,v 1.70 2024/02/25 19:15:50 cheloha Exp $ */ /* * Copyright (c) 2003 Dale Rahn <drahn@openbsd.org> * Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org> * Copyright (c) 2020-2024 Scott Cheloha <cheloha@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/atomic.h> #include <sys/clockintr.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/mutex.h> #include <sys/resourcevar.h> #include <sys/queue.h> #include <sys/sched.h> #include <sys/stdint.h> #include <sys/sysctl.h> #include <sys/time.h> void clockintr_cancel_locked(struct clockintr *); void clockintr_hardclock(struct clockrequest *, void *, void *); void clockintr_schedule_locked(struct clockintr *, uint64_t); void clockqueue_intrclock_install(struct clockqueue *, const struct intrclock *); void clockqueue_intrclock_reprogram(struct clockqueue *); uint64_t clockqueue_next(const struct clockqueue *); void clockqueue_pend_delete(struct clockqueue *, struct clockintr *); void clockqueue_pend_insert(struct clockqueue *, struct clockintr *, uint64_t); void intrclock_rearm(struct intrclock *, uint64_t); void intrclock_trigger(struct intrclock *); uint64_t nsec_advance(uint64_t *, uint64_t, uint64_t); /* * Ready the calling CPU for clockintr_dispatch(). If this is our * first time here, install the intrclock, if any, and set necessary * flags. Advance the schedule as needed. */ void clockintr_cpu_init(const struct intrclock *ic) { uint64_t multiplier = 0; struct cpu_info *ci = curcpu(); struct clockqueue *cq = &ci->ci_queue; struct schedstate_percpu *spc = &ci->ci_schedstate; int reset_cq_intrclock = 0; if (ic != NULL) clockqueue_intrclock_install(cq, ic); /* TODO: Remove this from struct clockqueue. */ if (CPU_IS_PRIMARY(ci) && cq->cq_hardclock.cl_expiration == 0) { clockintr_bind(&cq->cq_hardclock, ci, clockintr_hardclock, NULL); } /* * Mask CQ_INTRCLOCK while we're advancing the internal clock * interrupts. We don't want the intrclock to fire until this * thread reaches clockintr_trigger(). */ if (ISSET(cq->cq_flags, CQ_INTRCLOCK)) { CLR(cq->cq_flags, CQ_INTRCLOCK); reset_cq_intrclock = 1; } /* * Until we understand scheduler lock contention better, stagger * the hardclock and statclock so they don't all happen at once. * If we have no intrclock it doesn't matter, we have no control * anyway. The primary CPU's starting offset is always zero, so * leave the multiplier zero. */ if (!CPU_IS_PRIMARY(ci) && reset_cq_intrclock) multiplier = CPU_INFO_UNIT(ci); /* * The first time we do this, the primary CPU cannot skip any * hardclocks. We can skip hardclocks on subsequent calls because * the global tick value is advanced during inittodr(9) on our * behalf. */ if (CPU_IS_PRIMARY(ci)) { if (cq->cq_hardclock.cl_expiration == 0) clockintr_schedule(&cq->cq_hardclock, 0); else clockintr_advance(&cq->cq_hardclock, hardclock_period); } /* * We can always advance the statclock. There is no reason to * stagger a randomized statclock. */ if (!statclock_is_randomized) { if (spc->spc_statclock.cl_expiration == 0) { clockintr_stagger(&spc->spc_statclock, statclock_avg, multiplier, MAXCPUS); } } clockintr_advance(&spc->spc_statclock, statclock_avg); /* * XXX Need to find a better place to do this. We can't do it in * sched_init_cpu() because initclocks() runs after it. */ if (spc->spc_itimer.cl_expiration == 0) { clockintr_stagger(&spc->spc_itimer, hardclock_period, multiplier, MAXCPUS); } if (spc->spc_profclock.cl_expiration == 0) { clockintr_stagger(&spc->spc_profclock, profclock_period, multiplier, MAXCPUS); } if (spc->spc_roundrobin.cl_expiration == 0) { clockintr_stagger(&spc->spc_roundrobin, hardclock_period, multiplier, MAXCPUS); } clockintr_advance(&spc->spc_roundrobin, roundrobin_period); if (reset_cq_intrclock) SET(cq->cq_flags, CQ_INTRCLOCK); } /* * If we have an intrclock, trigger it to start the dispatch cycle. */ void clockintr_trigger(void) { struct clockqueue *cq = &curcpu()->ci_queue; KASSERT(ISSET(cq->cq_flags, CQ_INIT)); if (ISSET(cq->cq_flags, CQ_INTRCLOCK)) intrclock_trigger(&cq->cq_intrclock); } /* * Run all expired events scheduled on the calling CPU. */ int clockintr_dispatch(void *frame) { uint64_t lateness, run = 0, start; struct cpu_info *ci = curcpu(); struct clockintr *cl; struct clockqueue *cq = &ci->ci_queue; struct clockrequest *request = &cq->cq_request; void *arg; void (*func)(struct clockrequest *, void *, void *); uint32_t ogen; if (cq->cq_dispatch != 0) panic("%s: recursive dispatch", __func__); cq->cq_dispatch = 1; splassert(IPL_CLOCK); KASSERT(ISSET(cq->cq_flags, CQ_INIT)); mtx_enter(&cq->cq_mtx); /* * If nothing is scheduled or we arrived too early, we have * nothing to do. */ start = nsecuptime(); cq->cq_uptime = start; if (TAILQ_EMPTY(&cq->cq_pend)) goto stats; if (cq->cq_uptime < clockqueue_next(cq)) goto rearm; lateness = start - clockqueue_next(cq); /* * Dispatch expired events. */ for (;;) { cl = TAILQ_FIRST(&cq->cq_pend); if (cl == NULL) break; if (cq->cq_uptime < cl->cl_expiration) { /* Double-check the time before giving up. */ cq->cq_uptime = nsecuptime(); if (cq->cq_uptime < cl->cl_expiration) break; } /* * This clockintr has expired. Execute it. */ clockqueue_pend_delete(cq, cl); request->cr_expiration = cl->cl_expiration; arg = cl->cl_arg; func = cl->cl_func; cq->cq_running = cl; mtx_leave(&cq->cq_mtx); func(request, frame, arg); mtx_enter(&cq->cq_mtx); cq->cq_running = NULL; if (ISSET(cq->cq_flags, CQ_IGNORE_REQUEST)) { CLR(cq->cq_flags, CQ_IGNORE_REQUEST); CLR(request->cr_flags, CR_RESCHEDULE); } if (ISSET(request->cr_flags, CR_RESCHEDULE)) { CLR(request->cr_flags, CR_RESCHEDULE); clockqueue_pend_insert(cq, cl, request->cr_expiration); } if (ISSET(cq->cq_flags, CQ_NEED_WAKEUP)) { CLR(cq->cq_flags, CQ_NEED_WAKEUP); mtx_leave(&cq->cq_mtx); wakeup(&cq->cq_running); mtx_enter(&cq->cq_mtx); } run++; } /* * Dispatch complete. */ rearm: /* Rearm the interrupt clock if we have one. */ if (ISSET(cq->cq_flags, CQ_INTRCLOCK)) { if (!TAILQ_EMPTY(&cq->cq_pend)) { intrclock_rearm(&cq->cq_intrclock, clockqueue_next(cq) - cq->cq_uptime); } } stats: /* Update our stats. */ ogen = cq->cq_gen; cq->cq_gen = 0; membar_producer(); cq->cq_stat.cs_dispatched += cq->cq_uptime - start; if (run > 0) { cq->cq_stat.cs_lateness += lateness; cq->cq_stat.cs_prompt++; cq->cq_stat.cs_run += run; } else if (!TAILQ_EMPTY(&cq->cq_pend)) { cq->cq_stat.cs_early++; cq->cq_stat.cs_earliness += clockqueue_next(cq) - cq->cq_uptime; } else cq->cq_stat.cs_spurious++; membar_producer(); cq->cq_gen = MAX(1, ogen + 1); mtx_leave(&cq->cq_mtx); if (cq->cq_dispatch != 1) panic("%s: unexpected value: %u", __func__, cq->cq_dispatch); cq->cq_dispatch = 0; return run > 0; } uint64_t clockintr_advance(struct clockintr *cl, uint64_t period) { uint64_t count, expiration; struct clockqueue *cq = cl->cl_queue; mtx_enter(&cq->cq_mtx); expiration = cl->cl_expiration; count = nsec_advance(&expiration, period, nsecuptime()); clockintr_schedule_locked(cl, expiration); mtx_leave(&cq->cq_mtx); return count; } uint64_t clockrequest_advance(struct clockrequest *cr, uint64_t period) { struct clockqueue *cq = cr->cr_queue; KASSERT(cr == &cq->cq_request); SET(cr->cr_flags, CR_RESCHEDULE); return nsec_advance(&cr->cr_expiration, period, cq->cq_uptime); } uint64_t clockrequest_advance_random(struct clockrequest *cr, uint64_t min, uint32_t mask) { uint64_t count = 0; struct clockqueue *cq = cr->cr_queue; uint32_t off; KASSERT(cr == &cq->cq_request); while (cr->cr_expiration <= cq->cq_uptime) { while ((off = (random() & mask)) == 0) continue; cr->cr_expiration += min + off; count++; } SET(cr->cr_flags, CR_RESCHEDULE); return count; } void clockintr_cancel(struct clockintr *cl) { struct clockqueue *cq = cl->cl_queue; mtx_enter(&cq->cq_mtx); clockintr_cancel_locked(cl); mtx_leave(&cq->cq_mtx); } void clockintr_cancel_locked(struct clockintr *cl) { struct clockqueue *cq = cl->cl_queue; int was_next; MUTEX_ASSERT_LOCKED(&cq->cq_mtx); if (ISSET(cl->cl_flags, CLST_PENDING)) { was_next = cl == TAILQ_FIRST(&cq->cq_pend); clockqueue_pend_delete(cq, cl); if (ISSET(cq->cq_flags, CQ_INTRCLOCK)) { if (was_next && !TAILQ_EMPTY(&cq->cq_pend)) { if (cq == &curcpu()->ci_queue) clockqueue_intrclock_reprogram(cq); } } } if (cl == cq->cq_running) SET(cq->cq_flags, CQ_IGNORE_REQUEST); } void clockintr_bind(struct clockintr *cl, struct cpu_info *ci, void (*func)(struct clockrequest *, void *, void *), void *arg) { struct clockqueue *cq = &ci->ci_queue; splassert(IPL_NONE); KASSERT(cl->cl_queue == NULL); mtx_enter(&cq->cq_mtx); cl->cl_arg = arg; cl->cl_func = func; cl->cl_queue = cq; TAILQ_INSERT_TAIL(&cq->cq_all, cl, cl_alink); mtx_leave(&cq->cq_mtx); } void clockintr_unbind(struct clockintr *cl, uint32_t flags) { struct clockqueue *cq = cl->cl_queue; KASSERT(!ISSET(flags, ~CL_FLAG_MASK)); mtx_enter(&cq->cq_mtx); clockintr_cancel_locked(cl); cl->cl_arg = NULL; cl->cl_func = NULL; cl->cl_queue = NULL; TAILQ_REMOVE(&cq->cq_all, cl, cl_alink); if (ISSET(flags, CL_BARRIER) && cl == cq->cq_running) { SET(cq->cq_flags, CQ_NEED_WAKEUP); msleep_nsec(&cq->cq_running, &cq->cq_mtx, PWAIT | PNORELOCK, "clkbar", INFSLP); } else mtx_leave(&cq->cq_mtx); } void clockintr_schedule(struct clockintr *cl, uint64_t expiration) { struct clockqueue *cq = cl->cl_queue; mtx_enter(&cq->cq_mtx); clockintr_schedule_locked(cl, expiration); mtx_leave(&cq->cq_mtx); } void clockintr_schedule_locked(struct clockintr *cl, uint64_t expiration) { struct clockqueue *cq = cl->cl_queue; MUTEX_ASSERT_LOCKED(&cq->cq_mtx); if (ISSET(cl->cl_flags, CLST_PENDING)) clockqueue_pend_delete(cq, cl); clockqueue_pend_insert(cq, cl, expiration); if (ISSET(cq->cq_flags, CQ_INTRCLOCK)) { if (cl == TAILQ_FIRST(&cq->cq_pend)) { if (cq == &curcpu()->ci_queue) clockqueue_intrclock_reprogram(cq); } } if (cl == cq->cq_running) SET(cq->cq_flags, CQ_IGNORE_REQUEST); } void clockintr_stagger(struct clockintr *cl, uint64_t period, uint32_t numer, uint32_t denom) { struct clockqueue *cq = cl->cl_queue; KASSERT(numer < denom); mtx_enter(&cq->cq_mtx); if (ISSET(cl->cl_flags, CLST_PENDING)) panic("%s: clock interrupt pending", __func__); cl->cl_expiration = period / denom * numer; mtx_leave(&cq->cq_mtx); } void clockintr_hardclock(struct clockrequest *cr, void *frame, void *arg) { uint64_t count, i; count = clockrequest_advance(cr, hardclock_period); for (i = 0; i < count; i++) hardclock(frame); } void clockqueue_init(struct clockqueue *cq) { if (ISSET(cq->cq_flags, CQ_INIT)) return; cq->cq_request.cr_queue = cq; mtx_init(&cq->cq_mtx, IPL_CLOCK); TAILQ_INIT(&cq->cq_all); TAILQ_INIT(&cq->cq_pend); cq->cq_gen = 1; SET(cq->cq_flags, CQ_INIT); } void clockqueue_intrclock_install(struct clockqueue *cq, const struct intrclock *ic) { mtx_enter(&cq->cq_mtx); if (!ISSET(cq->cq_flags, CQ_INTRCLOCK)) { cq->cq_intrclock = *ic; SET(cq->cq_flags, CQ_INTRCLOCK); } mtx_leave(&cq->cq_mtx); } uint64_t clockqueue_next(const struct clockqueue *cq) { MUTEX_ASSERT_LOCKED(&cq->cq_mtx); return TAILQ_FIRST(&cq->cq_pend)->cl_expiration; } void clockqueue_pend_delete(struct clockqueue *cq, struct clockintr *cl) { MUTEX_ASSERT_LOCKED(&cq->cq_mtx); KASSERT(ISSET(cl->cl_flags, CLST_PENDING)); TAILQ_REMOVE(&cq->cq_pend, cl, cl_plink); CLR(cl->cl_flags, CLST_PENDING); } void clockqueue_pend_insert(struct clockqueue *cq, struct clockintr *cl, uint64_t expiration) { struct clockintr *elm; MUTEX_ASSERT_LOCKED(&cq->cq_mtx); KASSERT(!ISSET(cl->cl_flags, CLST_PENDING)); cl->cl_expiration = expiration; TAILQ_FOREACH(elm, &cq->cq_pend, cl_plink) { if (cl->cl_expiration < elm->cl_expiration) break; } if (elm == NULL) TAILQ_INSERT_TAIL(&cq->cq_pend, cl, cl_plink); else TAILQ_INSERT_BEFORE(elm, cl, cl_plink); SET(cl->cl_flags, CLST_PENDING); } void clockqueue_intrclock_reprogram(struct clockqueue *cq) { uint64_t exp, now; MUTEX_ASSERT_LOCKED(&cq->cq_mtx); KASSERT(ISSET(cq->cq_flags, CQ_INTRCLOCK)); exp = clockqueue_next(cq); now = nsecuptime(); if (now < exp) intrclock_rearm(&cq->cq_intrclock, exp - now); else intrclock_trigger(&cq->cq_intrclock); } void intrclock_rearm(struct intrclock *ic, uint64_t nsecs) { ic->ic_rearm(ic->ic_cookie, nsecs); } void intrclock_trigger(struct intrclock *ic) { ic->ic_trigger(ic->ic_cookie); } /* * Advance *next in increments of period until it exceeds now. * Returns the number of increments *next was advanced. * * We check the common cases first to avoid division if possible. * This does no overflow checking. */ uint64_t nsec_advance(uint64_t *next, uint64_t period, uint64_t now) { uint64_t elapsed; if (now < *next) return 0; if (now < *next + period) { *next += period; return 1; } elapsed = (now - *next) / period + 1; *next += period * elapsed; return elapsed; } int sysctl_clockintr(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { struct clockintr_stat sum, tmp; struct clockqueue *cq; struct cpu_info *ci; CPU_INFO_ITERATOR cii; uint32_t gen; if (namelen != 1) return ENOTDIR; switch (name[0]) { case KERN_CLOCKINTR_STATS: memset(&sum, 0, sizeof sum); CPU_INFO_FOREACH(cii, ci) { cq = &ci->ci_queue; if (!ISSET(cq->cq_flags, CQ_INIT)) continue; do { gen = cq->cq_gen; membar_consumer(); tmp = cq->cq_stat; membar_consumer(); } while (gen == 0 || gen != cq->cq_gen); sum.cs_dispatched += tmp.cs_dispatched; sum.cs_early += tmp.cs_early; sum.cs_earliness += tmp.cs_earliness; sum.cs_lateness += tmp.cs_lateness; sum.cs_prompt += tmp.cs_prompt; sum.cs_run += tmp.cs_run; sum.cs_spurious += tmp.cs_spurious; } return sysctl_rdstruct(oldp, oldlenp, newp, &sum, sizeof sum); default: break; } return EINVAL; } #ifdef DDB #include <machine/db_machdep.h> #include <ddb/db_interface.h> #include <ddb/db_output.h> #include <ddb/db_sym.h> void db_show_clockintr(const struct clockintr *, const char *, u_int); void db_show_clockintr_cpu(struct cpu_info *); void db_show_all_clockintr(db_expr_t addr, int haddr, db_expr_t count, char *modif) { struct timespec now; struct cpu_info *ci; CPU_INFO_ITERATOR cii; int width = sizeof(long) * 2 + 2; /* +2 for "0x" prefix */ nanouptime(&now); db_printf("%20s\n", "UPTIME"); db_printf("%10lld.%09ld\n", now.tv_sec, now.tv_nsec); db_printf("\n"); db_printf("%20s %5s %3s %*s %s\n", "EXPIRATION", "STATE", "CPU", width, "ARG", "NAME"); CPU_INFO_FOREACH(cii, ci) { if (ISSET(ci->ci_queue.cq_flags, CQ_INIT)) db_show_clockintr_cpu(ci); } } void db_show_clockintr_cpu(struct cpu_info *ci) { struct clockintr *elm; struct clockqueue *cq = &ci->ci_queue; u_int cpu = CPU_INFO_UNIT(ci); if (cq->cq_running != NULL) db_show_clockintr(cq->cq_running, "run", cpu); TAILQ_FOREACH(elm, &cq->cq_pend, cl_plink) db_show_clockintr(elm, "pend", cpu); TAILQ_FOREACH(elm, &cq->cq_all, cl_alink) { if (!ISSET(elm->cl_flags, CLST_PENDING)) db_show_clockintr(elm, "idle", cpu); } } void db_show_clockintr(const struct clockintr *cl, const char *state, u_int cpu) { struct timespec ts; char *name; db_expr_t offset; int width = sizeof(long) * 2; NSEC_TO_TIMESPEC(cl->cl_expiration, &ts); db_find_sym_and_offset((vaddr_t)cl->cl_func, &name, &offset); if (name == NULL) name = "?"; db_printf("%10lld.%09ld %5s %3u 0x%0*lx %s\n", ts.tv_sec, ts.tv_nsec, state, cpu, width, (unsigned long)cl->cl_arg, name); } #endif /* DDB */
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 #ifndef __DRM_GEM_H__ #define __DRM_GEM_H__ /* * GEM Graphics Execution Manager Driver Interfaces * * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * Copyright (c) 2009-2010, Code Aurora Forum. * All rights reserved. * Copyright © 2014 Intel Corporation * Daniel Vetter <daniel.vetter@ffwll.ch> * * Author: Rickard E. (Rik) Faith <faith@valinux.com> * Author: Gareth Hughes <gareth@valinux.com> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #include <linux/kref.h> #include <linux/dma-resv.h> #include <linux/list.h> #include <linux/mutex.h> #include <drm/drm_vma_manager.h> struct iosys_map; struct drm_gem_object; /** * enum drm_gem_object_status - bitmask of object state for fdinfo reporting * @DRM_GEM_OBJECT_RESIDENT: object is resident in memory (ie. not unpinned) * @DRM_GEM_OBJECT_PURGEABLE: object marked as purgeable by userspace * * Bitmask of status used for fdinfo memory stats, see &drm_gem_object_funcs.status * and drm_show_fdinfo(). Note that an object can DRM_GEM_OBJECT_PURGEABLE if * it still active or not resident, in which case drm_show_fdinfo() will not * account for it as purgeable. So drivers do not need to check if the buffer * is idle and resident to return this bit. (Ie. userspace can mark a buffer * as purgeable even while it is still busy on the GPU.. it does not _actually_ * become puregeable until it becomes idle. The status gem object func does * not need to consider this.) */ enum drm_gem_object_status { DRM_GEM_OBJECT_RESIDENT = BIT(0), DRM_GEM_OBJECT_PURGEABLE = BIT(1), }; /** * struct drm_gem_object_funcs - GEM object functions */ struct drm_gem_object_funcs { /** * @free: * * Deconstructor for drm_gem_objects. * * This callback is mandatory. */ void (*free)(struct drm_gem_object *obj); /** * @open: * * Called upon GEM handle creation. * * This callback is optional. */ int (*open)(struct drm_gem_object *obj, struct drm_file *file); /** * @close: * * Called upon GEM handle release. * * This callback is optional. */ void (*close)(struct drm_gem_object *obj, struct drm_file *file); /** * @print_info: * * If driver subclasses struct &drm_gem_object, it can implement this * optional hook for printing additional driver specific info. * * drm_printf_indent() should be used in the callback passing it the * indent argument. * * This callback is called from drm_gem_print_info(). * * This callback is optional. */ void (*print_info)(struct drm_printer *p, unsigned int indent, const struct drm_gem_object *obj); /** * @export: * * Export backing buffer as a &dma_buf. * If this is not set drm_gem_prime_export() is used. * * This callback is optional. */ struct dma_buf *(*export)(struct drm_gem_object *obj, int flags); /** * @pin: * * Pin backing buffer in memory. Used by the drm_gem_map_attach() helper. * * This callback is optional. */ int (*pin)(struct drm_gem_object *obj); /** * @unpin: * * Unpin backing buffer. Used by the drm_gem_map_detach() helper. * * This callback is optional. */ void (*unpin)(struct drm_gem_object *obj); /** * @get_sg_table: * * Returns a Scatter-Gather table representation of the buffer. * Used when exporting a buffer by the drm_gem_map_dma_buf() helper. * Releasing is done by calling dma_unmap_sg_attrs() and sg_free_table() * in drm_gem_unmap_buf(), therefore these helpers and this callback * here cannot be used for sg tables pointing at driver private memory * ranges. * * See also drm_prime_pages_to_sg(). */ struct sg_table *(*get_sg_table)(struct drm_gem_object *obj); /** * @vmap: * * Returns a virtual address for the buffer. Used by the * drm_gem_dmabuf_vmap() helper. * * This callback is optional. */ int (*vmap)(struct drm_gem_object *obj, struct iosys_map *map); /** * @vunmap: * * Releases the address previously returned by @vmap. Used by the * drm_gem_dmabuf_vunmap() helper. * * This callback is optional. */ void (*vunmap)(struct drm_gem_object *obj, struct iosys_map *map); /** * @mmap: * * Handle mmap() of the gem object, setup vma accordingly. * * This callback is optional. * * The callback is used by both drm_gem_mmap_obj() and * drm_gem_prime_mmap(). When @mmap is present @vm_ops is not * used, the @mmap callback must set vma->vm_ops instead. */ #ifdef __linux__ int (*mmap)(struct drm_gem_object *obj, struct vm_area_struct *vma); #else int (*mmap)(struct drm_gem_object *, vm_prot_t, voff_t, vsize_t); #endif /** * @evict: * * Evicts gem object out from memory. Used by the drm_gem_object_evict() * helper. Returns 0 on success, -errno otherwise. * * This callback is optional. */ int (*evict)(struct drm_gem_object *obj); /** * @status: * * The optional status callback can return additional object state * which determines which stats the object is counted against. The * callback is called under table_lock. Racing against object status * change is "harmless", and the callback can expect to not race * against object destruction. * * Called by drm_show_memory_stats(). */ enum drm_gem_object_status (*status)(struct drm_gem_object *obj); /** * @vm_ops: * * Virtual memory operations used with mmap. * * This is optional but necessary for mmap support. */ #ifdef __linux__ const struct vm_operations_struct *vm_ops; #else const struct uvm_pagerops *vm_ops; #endif }; /** * struct drm_gem_lru - A simple LRU helper * * A helper for tracking GEM objects in a given state, to aid in * driver's shrinker implementation. Tracks the count of pages * for lockless &shrinker.count_objects, and provides * &drm_gem_lru_scan for driver's &shrinker.scan_objects * implementation. */ struct drm_gem_lru { /** * @lock: * * Lock protecting movement of GEM objects between LRUs. All * LRUs that the object can move between should be protected * by the same lock. */ struct rwlock *lock; /** * @count: * * The total number of backing pages of the GEM objects in * this LRU. */ long count; /** * @list: * * The LRU list. */ struct list_head list; }; /** * struct drm_gem_object - GEM buffer object * * This structure defines the generic parts for GEM buffer objects, which are * mostly around handling mmap and userspace handles. * * Buffer objects are often abbreviated to BO. */ struct drm_gem_object { /* * This must be first as uobj is cast to ttm_buffer_object for * radeon_ttm_fault() the first member of that struct is drm_gem_object */ struct uvm_object uobj; /** * @refcount: * * Reference count of this object * * Please use drm_gem_object_get() to acquire and drm_gem_object_put_locked() * or drm_gem_object_put() to release a reference to a GEM * buffer object. */ struct kref refcount; /** * @handle_count: * * This is the GEM file_priv handle count of this object. * * Each handle also holds a reference. Note that when the handle_count * drops to 0 any global names (e.g. the id in the flink namespace) will * be cleared. * * Protected by &drm_device.object_name_lock. */ unsigned handle_count; /** * @dev: DRM dev this object belongs to. */ struct drm_device *dev; /** * @filp: * * SHMEM file node used as backing storage for swappable buffer objects. * GEM also supports driver private objects with driver-specific backing * storage (contiguous DMA memory, special reserved blocks). In this * case @filp is NULL. */ #ifdef __linux__ struct file *filp; #endif /** * @vma_node: * * Mapping info for this object to support mmap. Drivers are supposed to * allocate the mmap offset using drm_gem_create_mmap_offset(). The * offset itself can be retrieved using drm_vma_node_offset_addr(). * * Memory mapping itself is handled by drm_gem_mmap(), which also checks * that userspace is allowed to access the object. */ struct drm_vma_offset_node vma_node; /** * @size: * * Size of the object, in bytes. Immutable over the object's * lifetime. */ size_t size; /** * @name: * * Global name for this object, starts at 1. 0 means unnamed. * Access is covered by &drm_device.object_name_lock. This is used by * the GEM_FLINK and GEM_OPEN ioctls. */ int name; /** * @dma_buf: * * dma-buf associated with this GEM object. * * Pointer to the dma-buf associated with this gem object (either * through importing or exporting). We break the resulting reference * loop when the last gem handle for this object is released. * * Protected by &drm_device.object_name_lock. */ struct dma_buf *dma_buf; /** * @import_attach: * * dma-buf attachment backing this object. * * Any foreign dma_buf imported as a gem object has this set to the * attachment point for the device. This is invariant over the lifetime * of a gem object. * * The &drm_gem_object_funcs.free callback is responsible for * cleaning up the dma_buf attachment and references acquired at import * time. * * Note that the drm gem/prime core does not depend upon drivers setting * this field any more. So for drivers where this doesn't make sense * (e.g. virtual devices or a displaylink behind an usb bus) they can * simply leave it as NULL. */ struct dma_buf_attachment *import_attach; /** * @resv: * * Pointer to reservation object associated with the this GEM object. * * Normally (@resv == &@_resv) except for imported GEM objects. */ struct dma_resv *resv; /** * @_resv: * * A reservation object for this GEM object. * * This is unused for imported GEM objects. */ struct dma_resv _resv; /** * @gpuva: * * Provides the list of GPU VAs attached to this GEM object. * * Drivers should lock list accesses with the GEMs &dma_resv lock * (&drm_gem_object.resv) or a custom lock if one is provided. */ struct { struct list_head list; #ifdef CONFIG_LOCKDEP struct lockdep_map *lock_dep_map; #endif } gpuva; /** * @funcs: * * Optional GEM object functions. If this is set, it will be used instead of the * corresponding &drm_driver GEM callbacks. * * New drivers should use this. * */ const struct drm_gem_object_funcs *funcs; /** * @lru_node: * * List node in a &drm_gem_lru. */ struct list_head lru_node; /** * @lru: * * The current LRU list that the GEM object is on. */ struct drm_gem_lru *lru; SPLAY_ENTRY(drm_gem_object) entry; struct uvm_object *uao; }; /** * DRM_GEM_FOPS - Default drm GEM file operations * * This macro provides a shorthand for setting the GEM file ops in the * &file_operations structure. If all you need are the default ops, use * DEFINE_DRM_GEM_FOPS instead. */ #define DRM_GEM_FOPS \ .open = drm_open,\ .release = drm_release,\ .unlocked_ioctl = drm_ioctl,\ .compat_ioctl = drm_compat_ioctl,\ .poll = drm_poll,\ .read = drm_read,\ .llseek = noop_llseek,\ .mmap = drm_gem_mmap /** * DEFINE_DRM_GEM_FOPS() - macro to generate file operations for GEM drivers * @name: name for the generated structure * * This macro autogenerates a suitable &struct file_operations for GEM based * drivers, which can be assigned to &drm_driver.fops. Note that this structure * cannot be shared between drivers, because it contains a reference to the * current module using THIS_MODULE. * * Note that the declaration is already marked as static - if you need a * non-static version of this you're probably doing it wrong and will break the * THIS_MODULE reference by accident. */ #define DEFINE_DRM_GEM_FOPS(name) \ static const struct file_operations name = {\ .owner = THIS_MODULE,\ DRM_GEM_FOPS,\ } void drm_gem_object_release(struct drm_gem_object *obj); void drm_gem_object_free(struct kref *kref); int drm_gem_object_init(struct drm_device *dev, struct drm_gem_object *obj, size_t size); void drm_gem_private_object_init(struct drm_device *dev, struct drm_gem_object *obj, size_t size); void drm_gem_private_object_fini(struct drm_gem_object *obj); #ifdef __linux__ void drm_gem_vm_open(struct vm_area_struct *vma); void drm_gem_vm_close(struct vm_area_struct *vma); int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size, struct vm_area_struct *vma); int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); #else struct uvm_object *drm_gem_mmap(struct file *, vm_prot_t, voff_t, vsize_t); #endif /** * drm_gem_object_get - acquire a GEM buffer object reference * @obj: GEM buffer object * * This function acquires an additional reference to @obj. It is illegal to * call this without already holding a reference. No locks required. */ static inline void drm_gem_object_get(struct drm_gem_object *obj) { kref_get(&obj->refcount); } __attribute__((nonnull)) static inline void __drm_gem_object_put(struct drm_gem_object *obj) { kref_put(&obj->refcount, drm_gem_object_free); } /** * drm_gem_object_put - drop a GEM buffer object reference * @obj: GEM buffer object * * This releases a reference to @obj. */ static inline void drm_gem_object_put(struct drm_gem_object *obj) { if (obj) __drm_gem_object_put(obj); } int drm_gem_handle_create(struct drm_file *file_priv, struct drm_gem_object *obj, u32 *handlep); int drm_gem_handle_delete(struct drm_file *filp, u32 handle); void drm_gem_free_mmap_offset(struct drm_gem_object *obj); int drm_gem_create_mmap_offset(struct drm_gem_object *obj); int drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size); struct vm_page **drm_gem_get_pages(struct drm_gem_object *obj); void drm_gem_put_pages(struct drm_gem_object *obj, struct vm_page **pages, bool dirty, bool accessed); int drm_gem_vmap_unlocked(struct drm_gem_object *obj, struct iosys_map *map); void drm_gem_vunmap_unlocked(struct drm_gem_object *obj, struct iosys_map *map); int drm_gem_objects_lookup(struct drm_file *filp, void __user *bo_handles, int count, struct drm_gem_object ***objs_out); struct drm_gem_object *drm_gem_object_lookup(struct drm_file *filp, u32 handle); long drm_gem_dma_resv_wait(struct drm_file *filep, u32 handle, bool wait_all, unsigned long timeout); int drm_gem_lock_reservations(struct drm_gem_object **objs, int count, struct ww_acquire_ctx *acquire_ctx); void drm_gem_unlock_reservations(struct drm_gem_object **objs, int count, struct ww_acquire_ctx *acquire_ctx); int drm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev, u32 handle, u64 *offset); void drm_gem_lru_init(struct drm_gem_lru *lru, struct rwlock *lock); void drm_gem_lru_remove(struct drm_gem_object *obj); void drm_gem_lru_move_tail_locked(struct drm_gem_lru *lru, struct drm_gem_object *obj); void drm_gem_lru_move_tail(struct drm_gem_lru *lru, struct drm_gem_object *obj); unsigned long drm_gem_lru_scan(struct drm_gem_lru *lru, unsigned int nr_to_scan, unsigned long *remaining, bool (*shrink)(struct drm_gem_object *obj)); int drm_gem_evict(struct drm_gem_object *obj); /** * drm_gem_object_is_shared_for_memory_stats - helper for shared memory stats * * This helper should only be used for fdinfo shared memory stats to determine * if a GEM object is shared. * * @obj: obj in question */ static inline bool drm_gem_object_is_shared_for_memory_stats(struct drm_gem_object *obj) { return (obj->handle_count > 1) || obj->dma_buf; } #ifdef CONFIG_LOCKDEP /** * drm_gem_gpuva_set_lock() - Set the lock protecting accesses to the gpuva list. * @obj: the &drm_gem_object * @lock: the lock used to protect the gpuva list. The locking primitive * must contain a dep_map field. * * Call this if you're not proctecting access to the gpuva list with the * dma-resv lock, but with a custom lock. */ #define drm_gem_gpuva_set_lock(obj, lock) \ if (!WARN((obj)->gpuva.lock_dep_map, \ "GEM GPUVA lock should be set only once.")) \ (obj)->gpuva.lock_dep_map = &(lock)->dep_map #define drm_gem_gpuva_assert_lock_held(obj) \ lockdep_assert((obj)->gpuva.lock_dep_map ? \ lock_is_held((obj)->gpuva.lock_dep_map) : \ dma_resv_held((obj)->resv)) #else #define drm_gem_gpuva_set_lock(obj, lock) do {} while (0) #define drm_gem_gpuva_assert_lock_held(obj) do {} while (0) #endif /** * drm_gem_gpuva_init() - initialize the gpuva list of a GEM object * @obj: the &drm_gem_object * * This initializes the &drm_gem_object's &drm_gpuva list. * * Calling this function is only necessary for drivers intending to support the * &drm_driver_feature DRIVER_GEM_GPUVA. * * See also drm_gem_gpuva_set_lock(). */ static inline void drm_gem_gpuva_init(struct drm_gem_object *obj) { INIT_LIST_HEAD(&obj->gpuva.list); } /** * drm_gem_for_each_gpuva() - iternator to walk over a list of gpuvas * @entry__: &drm_gpuva structure to assign to in each iteration step * @obj__: the &drm_gem_object the &drm_gpuvas to walk are associated with * * This iterator walks over all &drm_gpuva structures associated with the * &drm_gpuva_manager. */ #define drm_gem_for_each_gpuva(entry__, obj__) \ list_for_each_entry(entry__, &(obj__)->gpuva.list, gem.entry) /** * drm_gem_for_each_gpuva_safe() - iternator to safely walk over a list of * gpuvas * @entry__: &drm_gpuva structure to assign to in each iteration step * @next__: &next &drm_gpuva to store the next step * @obj__: the &drm_gem_object the &drm_gpuvas to walk are associated with * * This iterator walks over all &drm_gpuva structures associated with the * &drm_gem_object. It is implemented with list_for_each_entry_safe(), hence * it is save against removal of elements. */ #define drm_gem_for_each_gpuva_safe(entry__, next__, obj__) \ list_for_each_entry_safe(entry__, next__, &(obj__)->gpuva.list, gem.entry) void drm_ref(struct uvm_object *); void drm_unref(struct uvm_object *); #endif /* __DRM_GEM_H__ */
4 1 3 1 3 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 /* $OpenBSD: ppp_tty.c,v 1.54 2022/01/02 22:36:04 jsg Exp $ */ /* $NetBSD: ppp_tty.c,v 1.12 1997/03/24 21:23:10 christos Exp $ */ /* * ppp_tty.c - Point-to-Point Protocol (PPP) driver for asynchronous * tty devices. * * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The name "Carnegie Mellon University" must not be used to * endorse or promote products derived from this software without * prior written permission. For permission or any legal * details, please contact * Office of Technology Transfer * Carnegie Mellon University * 5000 Forbes Avenue * Pittsburgh, PA 15213-3890 * (412) 268-4387, fax: (412) 268-7395 * tech-transfer@andrew.cmu.edu * * 4. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by Computing Services * at Carnegie Mellon University (http://www.cmu.edu/computing/)." * * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Based on: * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89 * * Copyright (c) 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Serial Line interface * * Rick Adams * Center for Seismic Studies * 1300 N 17th Street, Suite 1450 * Arlington, Virginia 22209 * (703)276-7900 * rick@seismo.ARPA * seismo!rick * * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris). * Converted to 4.3BSD Beta by Chris Torek. * Other changes made at Berkeley, based in part on code by Kirk Smith. * * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com) * Added VJ tcp header compression; more unified ioctls * * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au). * Cleaned up a lot of the mbuf-related code to fix bugs that * caused system crashes and packet corruption. Changed pppstart * so that it doesn't just give up with a collision if the whole * packet doesn't fit in the output ring buffer. * * Added priority queueing for interactive IP packets, following * the model of if_sl.c, plus hooks for bpf. * Paul Mackerras (paulus@cs.anu.edu.au). */ /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */ /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */ #include "ppp.h" #if NPPP > 0 #define VJC #define PPP_COMPRESS #include <sys/param.h> #include <sys/proc.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/timeout.h> #include <sys/ioctl.h> #include <sys/fcntl.h> #include <sys/tty.h> #include <sys/kernel.h> #include <sys/conf.h> #include <sys/vnode.h> #include <sys/systm.h> #include <sys/rwlock.h> #include <sys/pool.h> #include <net/if.h> #include <net/if_var.h> #ifdef VJC #include <netinet/in.h> #include <netinet/ip.h> #include <net/slcompress.h> #endif #include <net/bpf.h> #include <net/ppp_defs.h> #include <net/if_ppp.h> #include <net/if_pppvar.h> int pppstart_internal(struct tty *tp, int); u_int16_t pppfcs(u_int16_t fcs, u_char *cp, int len); void pppasyncstart(struct ppp_softc *); void pppasyncctlp(struct ppp_softc *); void pppasyncrelinq(struct ppp_softc *); void ppp_timeout(void *); void ppppkt(struct ppp_softc *sc); void pppdumpb(u_char *b, int l); void ppplogchar(struct ppp_softc *, int); struct rwlock ppp_pkt_init = RWLOCK_INITIALIZER("ppppktini"); struct pool ppp_pkts; #define PKT_MAXLEN(_sc) ((_sc)->sc_mru + PPP_HDRLEN + PPP_FCSLEN) /* * Does c need to be escaped? */ #define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F))) /* * Procedures for using an async tty interface for PPP. */ /* This is a NetBSD-1.0 or later kernel. */ #define CCOUNT(q) ((q)->c_cc) /* * Line specific open routine for async tty devices. * Attach the given tty to the first available ppp unit. * Called from device open routine or ttioctl. */ int pppopen(dev_t dev, struct tty *tp, struct proc *p) { struct ppp_softc *sc; int error, s; if ((error = suser(p)) != 0) return (error); rw_enter_write(&ppp_pkt_init); if (ppp_pkts.pr_size == 0) { extern const struct kmem_pa_mode kp_dma_contig; pool_init(&ppp_pkts, sizeof(struct ppp_pkt), 0, IPL_TTY, 0, "ppppkts", NULL); /* IPL_SOFTTTY */ pool_set_constraints(&ppp_pkts, &kp_dma_contig); } rw_exit_write(&ppp_pkt_init); s = spltty(); if (tp->t_line == PPPDISC) { sc = (struct ppp_softc *) tp->t_sc; if (sc != NULL && sc->sc_devp == (void *) tp) { splx(s); return (0); } } if ((sc = pppalloc(p->p_p->ps_pid)) == NULL) { splx(s); return ENXIO; } if (sc->sc_relinq) (*sc->sc_relinq)(sc); /* get previous owner to relinquish the unit */ timeout_set(&sc->sc_timo, ppp_timeout, sc); sc->sc_ilen = 0; sc->sc_pkt = NULL; bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap)); sc->sc_asyncmap[0] = 0xffffffff; sc->sc_asyncmap[3] = 0x60000000; sc->sc_rasyncmap = 0; sc->sc_devp = (void *) tp; sc->sc_start = pppasyncstart; sc->sc_ctlp = pppasyncctlp; sc->sc_relinq = pppasyncrelinq; sc->sc_outm = NULL; ppppkt(sc); sc->sc_if.if_flags |= IFF_RUNNING; sc->sc_if.if_baudrate = tp->t_ospeed; tp->t_sc = (caddr_t) sc; ttyflush(tp, FREAD | FWRITE); splx(s); return (0); } /* * Line specific close routine, called from device close routine * and from ttioctl. * Detach the tty from the ppp unit. * Mimics part of ttyclose(). */ int pppclose(struct tty *tp, int flag, struct proc *p) { struct ppp_softc *sc; int s; s = spltty(); ttyflush(tp, FREAD|FWRITE); tp->t_line = 0; sc = (struct ppp_softc *) tp->t_sc; if (sc != NULL) { tp->t_sc = NULL; if (tp == (struct tty *) sc->sc_devp) { pppasyncrelinq(sc); pppdealloc(sc); } } splx(s); return 0; } /* * Relinquish the interface unit to another device. */ void pppasyncrelinq(struct ppp_softc *sc) { int s; KERNEL_LOCK(); s = spltty(); m_freem(sc->sc_outm); sc->sc_outm = NULL; if (sc->sc_pkt != NULL) { ppp_pkt_free(sc->sc_pkt); sc->sc_pkt = sc->sc_pktc = NULL; } if (sc->sc_flags & SC_TIMEOUT) { timeout_del(&sc->sc_timo); sc->sc_flags &= ~SC_TIMEOUT; } splx(s); KERNEL_UNLOCK(); } /* * Line specific (tty) read routine. */ int pppread(struct tty *tp, struct uio *uio, int flag) { struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc; struct mbuf *m, *m0; int s; int error = 0; if (sc == NULL) return 0; /* * Loop waiting for input, checking that nothing disastrous * happens in the meantime. */ s = spltty(); for (;;) { if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) { splx(s); return 0; } /* Get the packet from the input queue */ m0 = mq_dequeue(&sc->sc_inq); if (m0 != NULL) break; if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0 && (tp->t_state & TS_ISOPEN)) { splx(s); return 0; /* end of file */ } if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) { splx(s); return (EWOULDBLOCK); } error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI|PCATCH, ttyin); if (error) { splx(s); return error; } } /* Pull place-holder byte out of canonical queue */ getc(&tp->t_canq); splx(s); for (m = m0; m && uio->uio_resid; m = m->m_next) if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0) break; m_freem(m0); return (error); } /* * Line specific (tty) write routine. */ int pppwrite(struct tty *tp, struct uio *uio, int flag) { struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc; struct mbuf *m, *m0, **mp; struct sockaddr dst; u_int len; int error; if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0) return 0; /* wrote 0 bytes */ if (tp->t_line != PPPDISC) return (EINVAL); if (sc == NULL || tp != (struct tty *) sc->sc_devp) return EIO; if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN || uio->uio_resid < PPP_HDRLEN) return (EMSGSIZE); for (mp = &m0; uio->uio_resid; mp = &m->m_next) { if (mp == &m0) { MGETHDR(m, M_WAIT, MT_DATA); m->m_pkthdr.len = uio->uio_resid - PPP_HDRLEN; m->m_pkthdr.ph_ifidx = 0; } else MGET(m, M_WAIT, MT_DATA); *mp = m; m->m_len = 0; if (uio->uio_resid >= MCLBYTES / 2) MCLGET(m, M_DONTWAIT); len = m_trailingspace(m); if (len > uio->uio_resid) len = uio->uio_resid; if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) { m_freem(m0); return (error); } m->m_len = len; } dst.sa_family = AF_UNSPEC; bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN); m0->m_data += PPP_HDRLEN; m0->m_len -= PPP_HDRLEN; return sc->sc_if.if_output(&sc->sc_if, m0, &dst, NULL); } /* * Line specific (tty) ioctl routine. * This discipline requires that tty device drivers call * the line specific l_ioctl routine from their ioctl routines. */ int ppptioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p) { struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc; int error, s; if (sc == NULL || tp != (struct tty *) sc->sc_devp) return -1; error = 0; switch (cmd) { case PPPIOCSASYNCMAP: if ((error = suser(p)) != 0) break; sc->sc_asyncmap[0] = *(u_int *)data; break; case PPPIOCGASYNCMAP: *(u_int *)data = sc->sc_asyncmap[0]; break; case PPPIOCSRASYNCMAP: if ((error = suser(p)) != 0) break; sc->sc_rasyncmap = *(u_int *)data; break; case PPPIOCGRASYNCMAP: *(u_int *)data = sc->sc_rasyncmap; break; case PPPIOCSXASYNCMAP: if ((error = suser(p)) != 0) break; s = spltty(); bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap)); sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */ sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */ sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */ splx(s); break; case PPPIOCGXASYNCMAP: bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap)); break; default: NET_LOCK(); error = pppioctl(sc, cmd, data, flag, p); NET_UNLOCK(); if (error == 0 && cmd == PPPIOCSMRU) ppppkt(sc); } return error; } /* * FCS lookup table as calculated by genfcstab. */ static u_int16_t fcstab[256] = { 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 }; /* * Calculate a new FCS given the current FCS and the new data. */ u_int16_t pppfcs(u_int16_t fcs, u_char *cp, int len) { while (len--) fcs = PPP_FCS(fcs, *cp++); return (fcs); } /* * This gets called from pppoutput when a new packet is * put on a queue. */ void pppasyncstart(struct ppp_softc *sc) { struct tty *tp = (struct tty *) sc->sc_devp; struct mbuf *m; int len; u_char *start, *stop, *cp; int n, ndone, done, idle; struct mbuf *m2; int s; KERNEL_LOCK(); idle = 0; while (CCOUNT(&tp->t_outq) < tp->t_hiwat) { /* * See if we have an existing packet partly sent. * If not, get a new packet and start sending it. */ m = sc->sc_outm; if (m == NULL) { /* * Get another packet to be sent. */ m = ppp_dequeue(sc); if (m == NULL) { idle = 1; break; } /* * The extra PPP_FLAG will start up a new packet, and thus * will flush any accumulated garbage. We do this whenever * the line may have been idle for some time. */ if (CCOUNT(&tp->t_outq) == 0) { ++sc->sc_stats.ppp_obytes; (void) putc(PPP_FLAG, &tp->t_outq); } /* Calculate the FCS for the first mbuf's worth. */ sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len); } for (;;) { start = mtod(m, u_char *); len = m->m_len; stop = start + len; while (len > 0) { /* * Find out how many bytes in the string we can * handle without doing something special. */ for (cp = start; cp < stop; cp++) if (ESCAPE_P(*cp)) break; n = cp - start; if (n) { /* NetBSD (0.9 or later), 4.3-Reno or similar. */ ndone = n - b_to_q(start, n, &tp->t_outq); len -= ndone; start += ndone; sc->sc_stats.ppp_obytes += ndone; if (ndone < n) break; /* packet doesn't fit */ } /* * If there are characters left in the mbuf, * the first one must be special. * Put it out in a different form. */ if (len) { s = spltty(); if (putc(PPP_ESCAPE, &tp->t_outq)) { splx(s); break; } if (putc(*start ^ PPP_TRANS, &tp->t_outq)) { (void) unputc(&tp->t_outq); splx(s); break; } splx(s); sc->sc_stats.ppp_obytes += 2; start++; len--; } } /* * If we didn't empty this mbuf, remember where we're up to. * If we emptied the last mbuf, try to add the FCS and closing * flag, and if we can't, leave sc_outm pointing to m, but with * m->m_len == 0, to remind us to output the FCS and flag later. */ done = len == 0; if (done && m->m_next == NULL) { u_char *p, *q; int c; u_char endseq[8]; /* * We may have to escape the bytes in the FCS. */ p = endseq; c = ~sc->sc_outfcs & 0xFF; if (ESCAPE_P(c)) { *p++ = PPP_ESCAPE; *p++ = c ^ PPP_TRANS; } else *p++ = c; c = (~sc->sc_outfcs >> 8) & 0xFF; if (ESCAPE_P(c)) { *p++ = PPP_ESCAPE; *p++ = c ^ PPP_TRANS; } else *p++ = c; *p++ = PPP_FLAG; /* * Try to output the FCS and flag. If the bytes * don't all fit, back out. */ s = spltty(); for (q = endseq; q < p; ++q) if (putc(*q, &tp->t_outq)) { done = 0; for (; q > endseq; --q) unputc(&tp->t_outq); break; } splx(s); if (done) sc->sc_stats.ppp_obytes += q - endseq; } if (!done) { /* remember where we got to */ m->m_data = start; m->m_len = len; break; } /* Finished with this mbuf; free it and move on. */ m2 = m_free(m); m = m2; if (m == NULL) { /* Finished a packet */ break; } sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len); } /* * If m == NULL, we have finished a packet. * If m != NULL, we've either done as much work this time * as we need to, or else we've filled up the output queue. */ sc->sc_outm = m; if (m) break; } /* Call pppstart to start output again if necessary. */ s = spltty(); pppstart_internal(tp, 0); /* * This timeout is needed for operation on a pseudo-tty, * because the pty code doesn't call pppstart after it has * drained the t_outq. */ if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) { timeout_add(&sc->sc_timo, 1); sc->sc_flags |= SC_TIMEOUT; } splx(s); KERNEL_UNLOCK(); } /* * This gets called when a received packet is placed on * the inq. */ void pppasyncctlp(struct ppp_softc *sc) { struct tty *tp; int s; KERNEL_LOCK(); /* Put a placeholder byte in canq for ttpoll()/ttnread(). */ s = spltty(); tp = (struct tty *) sc->sc_devp; putc(0, &tp->t_canq); ttwakeup(tp); splx(s); KERNEL_UNLOCK(); } /* * Start output on async tty interface. If the transmit queue * has drained sufficiently, arrange for pppasyncstart to be * called later. */ int pppstart_internal(struct tty *tp, int force) { struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc; /* * If there is stuff in the output queue, send it now. * We are being called in lieu of ttstart and must do what it would. */ if (tp->t_oproc != NULL) (*tp->t_oproc)(tp); /* * If the transmit queue has drained and the tty has not hung up * or been disconnected from the ppp unit, then tell if_ppp.c that * we need more output. */ if ((CCOUNT(&tp->t_outq) < tp->t_lowat || force) && !((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0) && sc != NULL && tp == (struct tty *) sc->sc_devp) { ppp_restart(sc); } return 0; } int pppstart(struct tty *tp) { return pppstart_internal(tp, 0); } /* * Timeout routine - try to start some more output. */ void ppp_timeout(void *x) { struct ppp_softc *sc = (struct ppp_softc *) x; struct tty *tp = (struct tty *) sc->sc_devp; int s; s = spltty(); sc->sc_flags &= ~SC_TIMEOUT; pppstart_internal(tp, 1); splx(s); } /* * Allocate enough mbuf to handle current MRU. */ void ppppkt(struct ppp_softc *sc) { struct ppp_pkt **pktp, *pkt; int len; int s; s = spltty(); pktp = &sc->sc_pkt; for (len = PKT_MAXLEN(sc); len > 0; len -= sizeof(pkt->p_buf)) { pkt = *pktp; if (pkt == NULL) { pkt = pool_get(&ppp_pkts, PR_NOWAIT); if (pkt == NULL) break; PKT_NEXT(pkt) = NULL; PKT_PREV(pkt) = *pktp; PKT_LEN(pkt) = 0; *pktp = pkt; } pktp = &PKT_NEXT(pkt); } splx(s); } void ppp_pkt_free(struct ppp_pkt *pkt) { struct ppp_pkt *next; while (pkt != NULL) { next = PKT_NEXT(pkt); pool_put(&ppp_pkts, pkt); pkt = next; } } /* * tty interface receiver interrupt. */ static unsigned int paritytab[8] = { 0x96696996, 0x69969669, 0x69969669, 0x96696996, 0x69969669, 0x96696996, 0x96696996, 0x69969669 }; int pppinput(int c, struct tty *tp) { struct ppp_softc *sc; struct ppp_pkt *pkt; int ilen, s; sc = (struct ppp_softc *) tp->t_sc; if (sc == NULL || tp != (struct tty *) sc->sc_devp) return 0; ++tk_nin; ++sc->sc_stats.ppp_ibytes; if (c & TTY_FE) { /* framing error or overrun on this char - abort packet */ if (sc->sc_flags & SC_DEBUG) printf("%s: bad char %x\n", sc->sc_if.if_xname, c); goto flush; } c &= 0xff; /* * Handle software flow control of output. */ if (tp->t_iflag & IXON) { if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) { if ((tp->t_state & TS_TTSTOP) == 0) { tp->t_state |= TS_TTSTOP; (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); } return 0; } if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) { tp->t_state &= ~TS_TTSTOP; if (tp->t_oproc != NULL) (*tp->t_oproc)(tp); return 0; } } s = spltty(); if (c & 0x80) sc->sc_flags |= SC_RCV_B7_1; else sc->sc_flags |= SC_RCV_B7_0; if (paritytab[c >> 5] & (1 << (c & 0x1F))) sc->sc_flags |= SC_RCV_ODDP; else sc->sc_flags |= SC_RCV_EVNP; splx(s); if (sc->sc_flags & SC_LOG_RAWIN) ppplogchar(sc, c); if (c == PPP_FLAG) { ilen = sc->sc_ilen; sc->sc_ilen = 0; if (sc->sc_rawin_count > 0) ppplogchar(sc, -1); /* * If SC_ESCAPED is set, then we've seen the packet * abort sequence "}~". */ if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED) || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) { s = spltty(); sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */ if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){ if (sc->sc_flags & SC_DEBUG) printf("%s: bad fcs %x\n", sc->sc_if.if_xname, sc->sc_fcs); sc->sc_if.if_ierrors++; sc->sc_stats.ppp_ierrors++; } else sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED); splx(s); return 0; } if (ilen < PPP_HDRLEN + PPP_FCSLEN) { if (ilen) { if (sc->sc_flags & SC_DEBUG) printf("%s: too short (%d)\n", sc->sc_if.if_xname, ilen); s = spltty(); sc->sc_if.if_ierrors++; sc->sc_stats.ppp_ierrors++; sc->sc_flags |= SC_PKTLOST; splx(s); } return 0; } /* * Remove FCS trailer. */ ilen -= 2; pkt = sc->sc_pktc; if (--PKT_LEN(pkt) == 0) { pkt = PKT_PREV(pkt); sc->sc_pktc = pkt; } PKT_LEN(pkt)--; /* excise this mbuf chain */ pkt = sc->sc_pkt; sc->sc_pkt = sc->sc_pktc = PKT_NEXT(sc->sc_pktc); PKT_NEXT(pkt) = NULL; ppppktin(sc, pkt, sc->sc_flags & SC_PKTLOST); if (sc->sc_flags & SC_PKTLOST) { s = spltty(); sc->sc_flags &= ~SC_PKTLOST; splx(s); } ppppkt(sc); return 0; } if (sc->sc_flags & SC_FLUSH) { if (sc->sc_flags & SC_LOG_FLUSH) ppplogchar(sc, c); return 0; } if (c < 0x20 && (sc->sc_rasyncmap & (1 << c))) return 0; s = spltty(); if (sc->sc_flags & SC_ESCAPED) { sc->sc_flags &= ~SC_ESCAPED; c ^= PPP_TRANS; } else if (c == PPP_ESCAPE) { sc->sc_flags |= SC_ESCAPED; splx(s); return 0; } splx(s); /* * Initialize buffer on first octet received. * First octet could be address or protocol (when compressing * address/control). * Second octet is control. * Third octet is first or second (when compressing protocol) * octet of protocol. * Fourth octet is second octet of protocol. */ if (sc->sc_ilen == 0) { /* reset the first input mbuf */ if (sc->sc_pkt == NULL) { ppppkt(sc); if (sc->sc_pkt == NULL) { if (sc->sc_flags & SC_DEBUG) printf("%s: no input mbufs!\n", sc->sc_if.if_xname); goto flush; } } pkt = sc->sc_pkt; PKT_LEN(pkt) = 0; sc->sc_pktc = pkt; sc->sc_pktp = pkt->p_buf; sc->sc_fcs = PPP_INITFCS; if (c != PPP_ALLSTATIONS) { if (sc->sc_flags & SC_REJ_COMP_AC) { if (sc->sc_flags & SC_DEBUG) printf("%s: garbage received: 0x%x (need 0xFF)\n", sc->sc_if.if_xname, c); goto flush; } *sc->sc_pktp++ = PPP_ALLSTATIONS; *sc->sc_pktp++ = PPP_UI; sc->sc_ilen += 2; PKT_LEN(pkt) += 2; } } if (sc->sc_ilen == 1 && c != PPP_UI) { if (sc->sc_flags & SC_DEBUG) printf("%s: missing UI (0x3), got 0x%x\n", sc->sc_if.if_xname, c); goto flush; } if (sc->sc_ilen == 2 && (c & 1) == 1) { /* a compressed protocol */ *sc->sc_pktp++ = 0; sc->sc_ilen++; PKT_LEN(sc->sc_pktc)++; } if (sc->sc_ilen == 3 && (c & 1) == 0) { if (sc->sc_flags & SC_DEBUG) printf("%s: bad protocol %x\n", sc->sc_if.if_xname, (sc->sc_pktp[-1] << 8) + c); goto flush; } /* packet beyond configured mru? */ if (++sc->sc_ilen > PKT_MAXLEN(sc)) { if (sc->sc_flags & SC_DEBUG) printf("%s: packet too big\n", sc->sc_if.if_xname); goto flush; } /* is this packet full? */ pkt = sc->sc_pktc; if (PKT_LEN(pkt) >= sizeof(pkt->p_buf)) { if (PKT_NEXT(pkt) == NULL) { ppppkt(sc); if (PKT_NEXT(pkt) == NULL) { if (sc->sc_flags & SC_DEBUG) printf("%s: too few input packets!\n", sc->sc_if.if_xname); goto flush; } } sc->sc_pktc = pkt = PKT_NEXT(pkt); PKT_LEN(pkt) = 0; sc->sc_pktp = pkt->p_buf; } ++PKT_LEN(pkt); *sc->sc_pktp++ = c; sc->sc_fcs = PPP_FCS(sc->sc_fcs, c); return 0; flush: if (!(sc->sc_flags & SC_FLUSH)) { s = spltty(); sc->sc_if.if_ierrors++; sc->sc_stats.ppp_ierrors++; sc->sc_flags |= SC_FLUSH; splx(s); if (sc->sc_flags & SC_LOG_FLUSH) ppplogchar(sc, c); } return 0; } #define MAX_DUMP_BYTES 128 void ppplogchar(struct ppp_softc *sc, int c) { if (c >= 0) sc->sc_rawin[sc->sc_rawin_count++] = c; if (sc->sc_rawin_count >= sizeof(sc->sc_rawin) || (c < 0 && sc->sc_rawin_count > 0)) { printf("%s input: ", sc->sc_if.if_xname); pppdumpb(sc->sc_rawin, sc->sc_rawin_count); sc->sc_rawin_count = 0; } } void pppdumpb(u_char *b, int l) { char buf[3*MAX_DUMP_BYTES+4]; char *bp = buf; static char digits[] = "0123456789abcdef"; while (l--) { if (bp >= buf + sizeof(buf) - 3) { *bp++ = '>'; break; } *bp++ = digits[*b >> 4]; /* convert byte to ascii hex */ *bp++ = digits[*b++ & 0xf]; *bp++ = ' '; } *bp = 0; printf("%s\n", buf); } #endif /* NPPP > 0 */
1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 /* $OpenBSD: efi.c,v 1.1 2023/01/14 12:11:11 kettenis Exp $ */ /* * Copyright (c) 2022 3mdeb <contact@3mdeb.com> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <dev/efi/efi.h> #include <dev/efi/efiio.h> #include <machine/efivar.h> struct cfdriver efi_cd = { NULL, "efi", DV_DULL }; int efiioc_get_table(struct efi_softc *sc, void *); int efiioc_var_get(struct efi_softc *sc, void *); int efiioc_var_next(struct efi_softc *sc, void *); int efiioc_var_set(struct efi_softc *sc, void *); int efi_adapt_error(EFI_STATUS); int efiopen(dev_t dev, int flag, int mode, struct proc *p) { return (efi_cd.cd_ndevs > 0 ? 0 : ENXIO); } int eficlose(dev_t dev, int flag, int mode, struct proc *p) { return 0; } int efiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { struct efi_softc *sc = efi_cd.cd_devs[0]; int error; switch (cmd) { case EFIIOC_GET_TABLE: error = efiioc_get_table(sc, data); break; case EFIIOC_VAR_GET: error = efiioc_var_get(sc, data); break; case EFIIOC_VAR_NEXT: error = efiioc_var_next(sc, data); break; case EFIIOC_VAR_SET: error = efiioc_var_set(sc, data); break; default: error = ENOTTY; break; } return error; } int efiioc_get_table(struct efi_softc *sc, void *data) { EFI_GUID esrt_guid = EFI_SYSTEM_RESOURCE_TABLE_GUID; struct efi_get_table_ioc *ioc = data; char *buf = NULL; int error; /* Only ESRT is supported at the moment. */ if (memcmp(&ioc->uuid, &esrt_guid, sizeof(ioc->uuid)) != 0) return EINVAL; /* ESRT might not be present. */ if (sc->sc_esrt == NULL) return ENXIO; if (efi_enter_check(sc)) { free(buf, M_TEMP, ioc->table_len); return ENOSYS; } ioc->table_len = sizeof(*sc->sc_esrt) + sizeof(EFI_SYSTEM_RESOURCE_ENTRY) * sc->sc_esrt->FwResourceCount; /* Return table length to userspace. */ if (ioc->buf == NULL) { efi_leave(sc); return 0; } /* Refuse to copy only part of the table. */ if (ioc->buf_len < ioc->table_len) { efi_leave(sc); return EINVAL; } buf = malloc(ioc->table_len, M_TEMP, M_WAITOK); memcpy(buf, sc->sc_esrt, ioc->table_len); efi_leave(sc); error = copyout(buf, ioc->buf, ioc->table_len); free(buf, M_TEMP, ioc->table_len); return error; } int efiioc_var_get(struct efi_softc *sc, void *data) { struct efi_var_ioc *ioc = data; void *value = NULL; efi_char *name = NULL; size_t valuesize = ioc->datasize; EFI_STATUS status; int error; if (valuesize > 0) value = malloc(valuesize, M_TEMP, M_WAITOK); name = malloc(ioc->namesize, M_TEMP, M_WAITOK); error = copyin(ioc->name, name, ioc->namesize); if (error != 0) goto leave; /* NULL-terminated name must fit into namesize bytes. */ if (name[ioc->namesize / sizeof(*name) - 1] != 0) { error = EINVAL; goto leave; } if (efi_enter_check(sc)) { error = ENOSYS; goto leave; } status = sc->sc_rs->GetVariable(name, (EFI_GUID *)&ioc->vendor, &ioc->attrib, &ioc->datasize, value); efi_leave(sc); if (status == EFI_BUFFER_TOO_SMALL) { /* * Return size of the value, which was set by EFI RT, * reporting no error to match FreeBSD's behaviour. */ ioc->data = NULL; goto leave; } error = efi_adapt_error(status); if (error == 0) error = copyout(value, ioc->data, ioc->datasize); leave: free(value, M_TEMP, valuesize); free(name, M_TEMP, ioc->namesize); return error; } int efiioc_var_next(struct efi_softc *sc, void *data) { struct efi_var_ioc *ioc = data; efi_char *name; size_t namesize = ioc->namesize; EFI_STATUS status; int error; name = malloc(namesize, M_TEMP, M_WAITOK); error = copyin(ioc->name, name, namesize); if (error) goto leave; if (efi_enter_check(sc)) { error = ENOSYS; goto leave; } status = sc->sc_rs->GetNextVariableName(&ioc->namesize, name, (EFI_GUID *)&ioc->vendor); efi_leave(sc); if (status == EFI_BUFFER_TOO_SMALL) { /* * Return size of the name, which was set by EFI RT, * reporting no error to match FreeBSD's behaviour. */ ioc->name = NULL; goto leave; } error = efi_adapt_error(status); if (error == 0) error = copyout(name, ioc->name, ioc->namesize); leave: free(name, M_TEMP, namesize); return error; } int efiioc_var_set(struct efi_softc *sc, void *data) { struct efi_var_ioc *ioc = data; void *value = NULL; efi_char *name = NULL; EFI_STATUS status; int error; /* Zero datasize means variable deletion. */ if (ioc->datasize > 0) { value = malloc(ioc->datasize, M_TEMP, M_WAITOK); error = copyin(ioc->data, value, ioc->datasize); if (error) goto leave; } name = malloc(ioc->namesize, M_TEMP, M_WAITOK); error = copyin(ioc->name, name, ioc->namesize); if (error) goto leave; /* NULL-terminated name must fit into namesize bytes. */ if (name[ioc->namesize / sizeof(*name) - 1] != 0) { error = EINVAL; goto leave; } if (securelevel > 0) { error = EPERM; goto leave; } if (efi_enter_check(sc)) { error = ENOSYS; goto leave; } status = sc->sc_rs->SetVariable(name, (EFI_GUID *)&ioc->vendor, ioc->attrib, ioc->datasize, value); efi_leave(sc); error = efi_adapt_error(status); leave: free(value, M_TEMP, ioc->datasize); free(name, M_TEMP, ioc->namesize); return error; } int efi_adapt_error(EFI_STATUS status) { switch (status) { case EFI_SUCCESS: return 0; case EFI_DEVICE_ERROR: return EIO; case EFI_INVALID_PARAMETER: return EINVAL; case EFI_NOT_FOUND: return ENOENT; case EFI_OUT_OF_RESOURCES: return EAGAIN; case EFI_SECURITY_VIOLATION: return EPERM; case EFI_UNSUPPORTED: return ENOSYS; case EFI_WRITE_PROTECTED: return EROFS; default: return EIO; } }
2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 /* $OpenBSD: udf_vfsops.c,v 1.71 2023/04/13 02:19:05 jsg Exp $ */ /* * Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD: src/sys/fs/udf/udf_vfsops.c,v 1.25 2005/01/25 15:52:03 phk Exp $ */ /* * Ported to OpenBSD by Pedro Martelletto in February 2005. */ /* * Ok, here's how it goes. The UDF specs are pretty clear on how each data * structure is made up, but not very clear on how they relate to each other. * Here is the skinny... This demonstrates a filesystem with one file in the * root directory. Subdirectories are treated just as normal files, but they * have File Id Descriptors of their children as their file data. As for the * Anchor Volume Descriptor Pointer, it can exist in two of the following three * places: sector 256, sector n (the max sector of the disk), or sector * n - 256. It's a pretty good bet that one will exist at sector 256 though. * One caveat is unclosed CD media. For that, sector 256 cannot be written, * so the Anchor Volume Descriptor Pointer can exist at sector 512 until the * media is closed. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/uio.h> #include <sys/buf.h> #include <sys/dirent.h> #include <sys/fcntl.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/mutex.h> #include <sys/mount.h> #include <sys/namei.h> #include <sys/pool.h> #include <sys/proc.h> #include <sys/lock.h> #include <sys/queue.h> #include <sys/vnode.h> #include <sys/endian.h> #include <sys/specdev.h> #include <crypto/siphash.h> #include <isofs/udf/ecma167-udf.h> #include <isofs/udf/udf.h> #include <isofs/udf/udf_extern.h> struct pool udf_trans_pool; struct pool unode_pool; struct pool udf_ds_pool; int udf_find_partmaps(struct umount *, struct logvol_desc *); int udf_get_vpartmap(struct umount *, struct part_map_virt *); int udf_get_spartmap(struct umount *, struct part_map_spare *); int udf_get_mpartmap(struct umount *, struct part_map_meta *); int udf_mountfs(struct vnode *, struct mount *, uint32_t, struct proc *); const struct vfsops udf_vfsops = { .vfs_mount = udf_mount, .vfs_start = udf_start, .vfs_unmount = udf_unmount, .vfs_root = udf_root, .vfs_quotactl = udf_quotactl, .vfs_statfs = udf_statfs, .vfs_sync = udf_sync, .vfs_vget = udf_vget, .vfs_fhtovp = udf_fhtovp, .vfs_vptofh = udf_vptofh, .vfs_init = udf_init, .vfs_sysctl = udf_sysctl, .vfs_checkexp = udf_checkexp, }; int udf_init(struct vfsconf *foo) { pool_init(&udf_trans_pool, MAXNAMLEN * sizeof(unicode_t), 0, IPL_NONE, PR_WAITOK, "udftrpl", NULL); pool_init(&unode_pool, sizeof(struct unode), 0, IPL_NONE, PR_WAITOK, "udfndpl", NULL); pool_init(&udf_ds_pool, sizeof(struct udf_dirstream), 0, IPL_NONE, PR_WAITOK, "udfdspl", NULL); return (0); } int udf_start(struct mount *mp, int flags, struct proc *p) { return (0); } int udf_mount(struct mount *mp, const char *path, void *data, struct nameidata *ndp, struct proc *p) { struct vnode *devvp; /* vnode of the mount device */ struct udf_args *args = data; char fspec[MNAMELEN]; int error; if ((mp->mnt_flag & MNT_RDONLY) == 0) { mp->mnt_flag |= MNT_RDONLY; #ifdef UDF_DEBUG printf("udf_mount: enforcing read-only mode\n"); #endif } /* * No root filesystem support. Probably not a big deal, since the * bootloader doesn't understand UDF. */ if (mp->mnt_flag & MNT_ROOTFS) return (EOPNOTSUPP); /* * If updating, check whether changing from read-only to * read/write; if there is no device name, that's all we do. */ if (mp->mnt_flag & MNT_UPDATE) { return (0); } error = copyinstr(args->fspec, fspec, sizeof(fspec), NULL); if (error) return (error); NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fspec, p); if ((error = namei(ndp))) return (error); devvp = ndp->ni_vp; if (devvp->v_type != VBLK) { vrele(devvp); return (ENOTBLK); } if (major(devvp->v_rdev) >= nblkdev) { vrele(devvp); return (ENXIO); } if ((error = udf_mountfs(devvp, mp, args->lastblock, p))) { vrele(devvp); return (error); } /* * Keep a copy of the mount information. */ bzero(mp->mnt_stat.f_mntonname, MNAMELEN); strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN); bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); strlcpy(mp->mnt_stat.f_mntfromname, fspec, MNAMELEN); bzero(mp->mnt_stat.f_mntfromspec, MNAMELEN); strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN); return (0); }; /* * Check the descriptor tag for both the correct id and correct checksum. * Return zero if all is good, EINVAL if not. */ int udf_checktag(struct desc_tag *tag, uint16_t id) { uint8_t *itag; uint8_t i, cksum = 0; itag = (uint8_t *)tag; if (letoh16(tag->id) != id) return (EINVAL); for (i = 0; i < 15; i++) cksum = cksum + itag[i]; cksum = cksum - itag[4]; if (cksum == tag->cksum) return (0); return (EINVAL); } int udf_mountfs(struct vnode *devvp, struct mount *mp, uint32_t lb, struct proc *p) { struct buf *bp = NULL; struct anchor_vdp avdp; struct umount *ump = NULL; struct part_desc *pd; struct logvol_desc *lvd; struct fileset_desc *fsd; struct extfile_entry *xfentry; struct file_entry *fentry; uint32_t sector, size, mvds_start, mvds_end; uint32_t fsd_offset = 0; uint16_t part_num = 0, fsd_part = 0; int error = EINVAL; int logvol_found = 0, part_found = 0, fsd_found = 0; int bsize; /* * Disallow multiple mounts of the same device. * Disallow mounting of a device that is currently in use * (except for root, which might share swap device for miniroot). * Flush out any old buffers remaining from a previous use. */ if ((error = vfs_mountedon(devvp))) return (error); if (vcount(devvp) > 1 && devvp != rootvp) return (EBUSY); vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, INFSLP); VOP_UNLOCK(devvp); if (error) return (error); error = VOP_OPEN(devvp, FREAD, FSCRED, p); if (error) return (error); ump = malloc(sizeof(*ump), M_UDFMOUNT, M_WAITOK | M_ZERO); mp->mnt_data = ump; mp->mnt_stat.f_fsid.val[0] = devvp->v_rdev; mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; mp->mnt_stat.f_namemax = NAME_MAX; mp->mnt_flag |= MNT_LOCAL; ump->um_mountp = mp; ump->um_dev = devvp->v_rdev; ump->um_devvp = devvp; bsize = 2048; /* Should probe the media for its size. */ /* * Get the Anchor Volume Descriptor Pointer from sector 256. * Should also check sector n - 256, n, and 512. */ sector = 256; if ((error = bread(devvp, sector * btodb(bsize), bsize, &bp)) != 0) goto bail; if ((error = udf_checktag((struct desc_tag *)bp->b_data, TAGID_ANCHOR))) goto bail; bcopy(bp->b_data, &avdp, sizeof(struct anchor_vdp)); brelse(bp); bp = NULL; /* * Extract the Partition Descriptor and Logical Volume Descriptor * from the Volume Descriptor Sequence. * Should we care about the partition type right now? * What about multiple partitions? */ mvds_start = letoh32(avdp.main_vds_ex.loc); mvds_end = mvds_start + (letoh32(avdp.main_vds_ex.len) - 1) / bsize; for (sector = mvds_start; sector < mvds_end; sector++) { if ((error = bread(devvp, sector * btodb(bsize), bsize, &bp)) != 0) { printf("Can't read sector %d of VDS\n", sector); goto bail; } lvd = (struct logvol_desc *)bp->b_data; if (!udf_checktag(&lvd->tag, TAGID_LOGVOL)) { ump->um_bsize = letoh32(lvd->lb_size); ump->um_bmask = ump->um_bsize - 1; ump->um_bshift = ffs(ump->um_bsize) - 1; fsd_part = letoh16(lvd->_lvd_use.fsd_loc.loc.part_num); fsd_offset = letoh32(lvd->_lvd_use.fsd_loc.loc.lb_num); if (udf_find_partmaps(ump, lvd)) break; logvol_found = 1; } pd = (struct part_desc *)bp->b_data; if (!udf_checktag(&pd->tag, TAGID_PARTITION)) { part_found = 1; part_num = letoh16(pd->part_num); ump->um_len = ump->um_reallen = letoh32(pd->part_len); ump->um_start = ump->um_realstart = letoh32(pd->start_loc); } brelse(bp); bp = NULL; if ((part_found) && (logvol_found)) break; } if (!part_found || !logvol_found) { error = EINVAL; goto bail; } if (ISSET(ump->um_flags, UDF_MNT_USES_META)) { /* Read Metadata File 'File Entry' to find Metadata file. */ struct long_ad *la; sector = ump->um_start + ump->um_meta_start; /* Set in udf_get_mpartmap() */ if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) { printf("Cannot read sector %d for Metadata File Entry\n", sector); error = EINVAL; goto bail; } xfentry = (struct extfile_entry *)bp->b_data; fentry = (struct file_entry *)bp->b_data; if (udf_checktag(&xfentry->tag, TAGID_EXTFENTRY) == 0) la = (struct long_ad *)&xfentry->data[letoh32(xfentry->l_ea)]; else if (udf_checktag(&fentry->tag, TAGID_FENTRY) == 0) la = (struct long_ad *)&fentry->data[letoh32(fentry->l_ea)]; else { printf("Invalid Metadata File FE @ sector %d! (tag.id %d)\n", sector, fentry->tag.id); error = EINVAL; goto bail; } ump->um_meta_start = letoh32(la->loc.lb_num); ump->um_meta_len = letoh32(la->len); if (bp != NULL) { brelse(bp); bp = NULL; } } else if (fsd_part != part_num) { printf("FSD does not lie within the partition!\n"); error = EINVAL; goto bail; } mtx_init(&ump->um_hashmtx, IPL_NONE); ump->um_hashtbl = hashinit(UDF_HASHTBLSIZE, M_UDFMOUNT, M_WAITOK, &ump->um_hashsz); arc4random_buf(&ump->um_hashkey, sizeof(ump->um_hashkey)); /* Get the VAT, if needed */ if (ump->um_flags & UDF_MNT_FIND_VAT) { error = udf_vat_get(ump, lb); if (error) goto bail; } /* * Grab the Fileset Descriptor * Thanks to Chuck McCrobie <mccrobie@cablespeed.com> for pointing * me in the right direction here. */ if (ISSET(ump->um_flags, UDF_MNT_USES_META)) sector = ump->um_meta_start; else sector = fsd_offset; udf_vat_map(ump, &sector); if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) { printf("Cannot read sector %d of FSD\n", sector); goto bail; } fsd = (struct fileset_desc *)bp->b_data; if (!udf_checktag(&fsd->tag, TAGID_FSD)) { fsd_found = 1; bcopy(&fsd->rootdir_icb, &ump->um_root_icb, sizeof(struct long_ad)); if (ISSET(ump->um_flags, UDF_MNT_USES_META)) { ump->um_root_icb.loc.lb_num += ump->um_meta_start; ump->um_root_icb.loc.part_num = part_num; } } brelse(bp); bp = NULL; if (!fsd_found) { printf("Couldn't find the fsd\n"); error = EINVAL; goto bail; } /* * Find the file entry for the root directory. */ sector = letoh32(ump->um_root_icb.loc.lb_num); size = letoh32(ump->um_root_icb.len); udf_vat_map(ump, &sector); if ((error = udf_readlblks(ump, sector, size, &bp)) != 0) { printf("Cannot read sector %d\n", sector); goto bail; } xfentry = (struct extfile_entry *)bp->b_data; fentry = (struct file_entry *)bp->b_data; error = udf_checktag(&xfentry->tag, TAGID_EXTFENTRY); if (error) { error = udf_checktag(&fentry->tag, TAGID_FENTRY); if (error) { printf("Invalid root file entry!\n"); goto bail; } } brelse(bp); bp = NULL; devvp->v_specmountpoint = mp; return (0); bail: if (ump != NULL) { hashfree(ump->um_hashtbl, UDF_HASHTBLSIZE, M_UDFMOUNT); free(ump, M_UDFMOUNT, 0); mp->mnt_data = NULL; mp->mnt_flag &= ~MNT_LOCAL; } if (devvp->v_specinfo) devvp->v_specmountpoint = NULL; if (bp != NULL) brelse(bp); vn_lock(devvp, LK_EXCLUSIVE|LK_RETRY); VOP_CLOSE(devvp, FREAD, FSCRED, p); VOP_UNLOCK(devvp); return (error); } int udf_unmount(struct mount *mp, int mntflags, struct proc *p) { struct umount *ump; struct vnode *devvp; int error, flags = 0; ump = VFSTOUDFFS(mp); devvp = ump->um_devvp; if (mntflags & MNT_FORCE) flags |= FORCECLOSE; if ((error = vflush(mp, NULL, flags))) return (error); vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); vinvalbuf(devvp, V_SAVE, NOCRED, p, 0, INFSLP); (void)VOP_CLOSE(devvp, FREAD, NOCRED, p); VOP_UNLOCK(devvp); devvp->v_specmountpoint = NULL; vrele(devvp); if (ump->um_flags & UDF_MNT_USES_VAT) free(ump->um_vat, M_UDFMOUNT, 0); if (ump->um_stbl != NULL) free(ump->um_stbl, M_UDFMOUNT, 0); hashfree(ump->um_hashtbl, UDF_HASHTBLSIZE, M_UDFMOUNT); free(ump, M_UDFMOUNT, 0); mp->mnt_data = NULL; mp->mnt_flag &= ~MNT_LOCAL; return (0); } int udf_root(struct mount *mp, struct vnode **vpp) { struct umount *ump; struct vnode *vp; udfino_t id; int error; ump = VFSTOUDFFS(mp); id = udf_getid(&ump->um_root_icb); error = udf_vget(mp, id, vpp); if (error) return (error); vp = *vpp; vp->v_flag |= VROOT; return (0); } int udf_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg, struct proc *p) { return (EOPNOTSUPP); } int udf_statfs(struct mount *mp, struct statfs *sbp, struct proc *p) { struct umount *ump; ump = VFSTOUDFFS(mp); sbp->f_bsize = ump->um_bsize; sbp->f_iosize = ump->um_bsize; sbp->f_blocks = ump->um_len; sbp->f_bfree = 0; sbp->f_bavail = 0; sbp->f_files = 0; sbp->f_ffree = 0; sbp->f_favail = 0; copy_statfs_info(sbp, mp); return (0); } int udf_sync(struct mount *mp, int waitfor, int stall, struct ucred *cred, struct proc *p) { return (0); } int udf_vget(struct mount *mp, ino_t ino, struct vnode **vpp) { struct buf *bp; struct vnode *devvp; struct umount *ump; struct proc *p; struct vnode *vp, *nvp; struct unode *up; struct extfile_entry *xfe; struct file_entry *fe; uint32_t sector; int error, size; if (ino > (udfino_t)-1) panic("udf_vget: alien ino_t %llu", (unsigned long long)ino); p = curproc; bp = NULL; *vpp = NULL; ump = VFSTOUDFFS(mp); /* See if we already have this in the cache */ if ((error = udf_hashlookup(ump, ino, LK_EXCLUSIVE, vpp)) != 0) return (error); if (*vpp != NULL) return (0); /* * Allocate memory and check the tag id's before grabbing a new * vnode, since it's hard to roll back if there is a problem. */ up = pool_get(&unode_pool, PR_WAITOK | PR_ZERO); /* * Copy in the file entry. Per the spec, the size can only be 1 block. */ sector = ino; devvp = ump->um_devvp; udf_vat_map(ump, &sector); if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) { printf("Cannot read sector %d\n", sector); pool_put(&unode_pool, up); if (bp != NULL) brelse(bp); return (error); } xfe = (struct extfile_entry *)bp->b_data; fe = (struct file_entry *)bp->b_data; error = udf_checktag(&xfe->tag, TAGID_EXTFENTRY); if (error == 0) { size = letoh32(xfe->l_ea) + letoh32(xfe->l_ad); } else { error = udf_checktag(&fe->tag, TAGID_FENTRY); if (error) { printf("Invalid file entry!\n"); pool_put(&unode_pool, up); if (bp != NULL) brelse(bp); return (ENOMEM); } else size = letoh32(fe->l_ea) + letoh32(fe->l_ad); } /* Allocate max size of FE/XFE. */ up->u_fentry = malloc(size + UDF_EXTFENTRY_SIZE, M_UDFFENTRY, M_NOWAIT | M_ZERO); if (up->u_fentry == NULL) { pool_put(&unode_pool, up); if (bp != NULL) brelse(bp); return (ENOMEM); /* Cannot allocate file entry block */ } if (udf_checktag(&xfe->tag, TAGID_EXTFENTRY) == 0) bcopy(bp->b_data, up->u_fentry, size + UDF_EXTFENTRY_SIZE); else bcopy(bp->b_data, up->u_fentry, size + UDF_FENTRY_SIZE); brelse(bp); bp = NULL; if ((error = udf_allocv(mp, &vp, p))) { free(up->u_fentry, M_UDFFENTRY, 0); pool_put(&unode_pool, up); return (error); /* Error from udf_allocv() */ } up->u_vnode = vp; up->u_ino = ino; up->u_devvp = ump->um_devvp; up->u_dev = ump->um_dev; up->u_ump = ump; vp->v_data = up; vref(ump->um_devvp); rrw_init_flags(&up->u_lock, "unode", RWL_DUPOK | RWL_IS_VNODE); /* * udf_hashins() will lock the vnode for us. */ udf_hashins(up); switch (up->u_fentry->icbtag.file_type) { default: printf("Unrecognized file type (%d)\n", vp->v_type); vp->v_type = VREG; break; case UDF_ICB_FILETYPE_DIRECTORY: vp->v_type = VDIR; break; case UDF_ICB_FILETYPE_BLOCKDEVICE: vp->v_type = VBLK; break; case UDF_ICB_FILETYPE_CHARDEVICE: vp->v_type = VCHR; break; case UDF_ICB_FILETYPE_FIFO: vp->v_type = VFIFO; break; case UDF_ICB_FILETYPE_SOCKET: vp->v_type = VSOCK; break; case UDF_ICB_FILETYPE_SYMLINK: vp->v_type = VLNK; break; case UDF_ICB_FILETYPE_RANDOMACCESS: case UDF_ICB_FILETYPE_REALTIME: case UDF_ICB_FILETYPE_UNKNOWN: vp->v_type = VREG; break; } /* check if this is a vnode alias */ if ((nvp = checkalias(vp, up->u_dev, ump->um_mountp)) != NULL) { printf("found a vnode alias\n"); /* * Discard unneeded vnode, but save its udf_node. * Note that the lock is carried over in the udf_node */ nvp->v_data = vp->v_data; vp->v_data = NULL; vp->v_op = &spec_vops; vrele(vp); vgone(vp); /* * Reinitialize aliased inode. */ vp = nvp; ump->um_devvp = vp; } *vpp = vp; return (0); } struct ifid { u_short ifid_len; u_short ifid_pad; int ifid_ino; long ifid_start; }; int udf_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) { struct ifid *ifhp; struct vnode *nvp; int error; ifhp = (struct ifid *)fhp; if ((error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) != 0) { *vpp = NULLVP; return (error); } *vpp = nvp; return (0); } int udf_vptofh(struct vnode *vp, struct fid *fhp) { struct unode *up; struct ifid *ifhp; up = VTOU(vp); ifhp = (struct ifid *)fhp; ifhp->ifid_len = sizeof(struct ifid); ifhp->ifid_ino = up->u_ino; return (0); } int udf_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { return (EINVAL); } int udf_checkexp(struct mount *mp, struct mbuf *nam, int *exflagsp, struct ucred **credanonp) { return (EACCES); /* For the time being */ } /* Handle a virtual partition map */ int udf_get_vpartmap(struct umount *ump, struct part_map_virt *pmv) { ump->um_flags |= UDF_MNT_FIND_VAT; /* Should do more than this */ return (0); } /* Handle a sparable partition map */ int udf_get_spartmap(struct umount *ump, struct part_map_spare *pms) { struct buf *bp; int i, error; ump->um_stbl = malloc(letoh32(pms->st_size), M_UDFMOUNT, M_NOWAIT); if (ump->um_stbl == NULL) return (ENOMEM); bzero(ump->um_stbl, letoh32(pms->st_size)); /* Calculate the number of sectors per packet */ ump->um_psecs = letoh16(pms->packet_len) / ump->um_bsize; error = udf_readlblks(ump, letoh32(pms->st_loc[0]), letoh32(pms->st_size), &bp); if (error) { if (bp != NULL) brelse(bp); free(ump->um_stbl, M_UDFMOUNT, 0); return (error); /* Failed to read sparing table */ } bcopy(bp->b_data, ump->um_stbl, letoh32(pms->st_size)); brelse(bp); bp = NULL; if (udf_checktag(&ump->um_stbl->tag, 0)) { free(ump->um_stbl, M_UDFMOUNT, 0); return (EINVAL); /* Invalid sparing table found */ } /* * See how many valid entries there are here. The list is * supposed to be sorted, 0xfffffff0 and higher are not valid. */ for (i = 0; i < letoh16(ump->um_stbl->rt_l); i++) { ump->um_stbl_len = i; if (letoh32(ump->um_stbl->entries[i].org) >= 0xfffffff0) break; } return (0); } /* Handle a metadata partition map */ int udf_get_mpartmap(struct umount *ump, struct part_map_meta *pmm) { ump->um_flags |= UDF_MNT_USES_META; ump->um_meta_start = pmm->meta_file_lbn; return (0); } /* Scan the partition maps */ int udf_find_partmaps(struct umount *ump, struct logvol_desc *lvd) { struct regid *pmap_id; unsigned char regid_id[UDF_REGID_ID_SIZE + 1]; int i, ptype, psize, error; uint8_t *pmap = (uint8_t *) &lvd->maps[0]; for (i = 0; i < letoh32(lvd->n_pm); i++) { ptype = pmap[0]; psize = pmap[1]; if (ptype != 1 && ptype != 2) return (EINVAL); /* Invalid partition map type */ if (psize != sizeof(struct part_map_1) && psize != sizeof(struct part_map_2)) return (EINVAL); /* Invalid partition map size */ if (ptype == 1) { pmap += sizeof(struct part_map_1); continue; } /* Type 2 map. Find out the details */ pmap_id = (struct regid *) &pmap[4]; regid_id[UDF_REGID_ID_SIZE] = '\0'; bcopy(&pmap_id->id[0], &regid_id[0], UDF_REGID_ID_SIZE); if (!bcmp(&regid_id[0], "*UDF Virtual Partition", UDF_REGID_ID_SIZE)) error = udf_get_vpartmap(ump, (struct part_map_virt *) pmap); else if (!bcmp(&regid_id[0], "*UDF Sparable Partition", UDF_REGID_ID_SIZE)) error = udf_get_spartmap(ump, (struct part_map_spare *) pmap); else if (!bcmp(&regid_id[0], "*UDF Metadata Partition", UDF_REGID_ID_SIZE)) error = udf_get_mpartmap(ump, (struct part_map_meta *) pmap); else return (EINVAL); /* Unsupported partition map */ if (error) return (error); /* Error getting partition */ pmap += sizeof(struct part_map_2); } return (0); }
4648 2462 2461 4642 4641 10 2460 2456 2457 1 4641 4643 4644 7 49 49 49 162 4291 4 45 45 4290 3982 3913 108 3983 3983 38 3059 4516 1202 1402 5475 2476 2154 2153 120 121 248 2813 1 22 3 2811 2810 2814 2787 2797 478 11 11 33 4 29 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 /* $OpenBSD: kern_rwlock.c,v 1.50 2023/07/14 07:07:08 claudio Exp $ */ /* * Copyright (c) 2002, 2003 Artur Grabowski <art@openbsd.org> * Copyright (c) 2011 Thordur Bjornsson <thib@secnorth.net> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/pool.h> #include <sys/proc.h> #include <sys/rwlock.h> #include <sys/limits.h> #include <sys/atomic.h> #include <sys/witness.h> void rw_do_exit(struct rwlock *, unsigned long); /* XXX - temporary measure until proc0 is properly aligned */ #define RW_PROC(p) (((long)p) & ~RWLOCK_MASK) /* * Other OSes implement more sophisticated mechanism to determine how long the * process attempting to acquire the lock should be spinning. We start with * the most simple approach: we do RW_SPINS attempts at most before eventually * giving up and putting the process to sleep queue. */ #define RW_SPINS 1000 #ifdef MULTIPROCESSOR #define rw_cas(p, o, n) (atomic_cas_ulong(p, o, n) != o) #else static inline int rw_cas(volatile unsigned long *p, unsigned long o, unsigned long n) { if (*p != o) return (1); *p = n; return (0); } #endif /* * Magic wand for lock operations. Every operation checks if certain * flags are set and if they aren't, it increments the lock with some * value (that might need some computing in a few cases). If the operation * fails, we need to set certain flags while waiting for the lock. * * RW_WRITE The lock must be completely empty. We increment it with * RWLOCK_WRLOCK and the proc pointer of the holder. * Sets RWLOCK_WAIT|RWLOCK_WRWANT while waiting. * RW_READ RWLOCK_WRLOCK|RWLOCK_WRWANT may not be set. We increment * with RWLOCK_READ_INCR. RWLOCK_WAIT while waiting. */ static const struct rwlock_op { unsigned long inc; unsigned long check; unsigned long wait_set; long proc_mult; int wait_prio; } rw_ops[] = { { /* RW_WRITE */ RWLOCK_WRLOCK, ULONG_MAX, RWLOCK_WAIT | RWLOCK_WRWANT, 1, PLOCK - 4 }, { /* RW_READ */ RWLOCK_READ_INCR, RWLOCK_WRLOCK | RWLOCK_WRWANT, RWLOCK_WAIT, 0, PLOCK }, { /* Sparse Entry. */ 0, }, { /* RW_DOWNGRADE */ RWLOCK_READ_INCR - RWLOCK_WRLOCK, 0, 0, -1, PLOCK }, }; void rw_enter_read(struct rwlock *rwl) { unsigned long owner = rwl->rwl_owner; if (__predict_false((owner & (RWLOCK_WRLOCK | RWLOCK_WRWANT)) || rw_cas(&rwl->rwl_owner, owner, owner + RWLOCK_READ_INCR))) rw_enter(rwl, RW_READ); else { membar_enter_after_atomic(); WITNESS_CHECKORDER(&rwl->rwl_lock_obj, LOP_NEWORDER, NULL); WITNESS_LOCK(&rwl->rwl_lock_obj, 0); } } void rw_enter_write(struct rwlock *rwl) { struct proc *p = curproc; if (__predict_false(rw_cas(&rwl->rwl_owner, 0, RW_PROC(p) | RWLOCK_WRLOCK))) rw_enter(rwl, RW_WRITE); else { membar_enter_after_atomic(); WITNESS_CHECKORDER(&rwl->rwl_lock_obj, LOP_EXCLUSIVE | LOP_NEWORDER, NULL); WITNESS_LOCK(&rwl->rwl_lock_obj, LOP_EXCLUSIVE); } } void rw_exit_read(struct rwlock *rwl) { unsigned long owner; rw_assert_rdlock(rwl); WITNESS_UNLOCK(&rwl->rwl_lock_obj, 0); membar_exit_before_atomic(); owner = rwl->rwl_owner; if (__predict_false((owner & RWLOCK_WAIT) || rw_cas(&rwl->rwl_owner, owner, owner - RWLOCK_READ_INCR))) rw_do_exit(rwl, 0); } void rw_exit_write(struct rwlock *rwl) { unsigned long owner; rw_assert_wrlock(rwl); WITNESS_UNLOCK(&rwl->rwl_lock_obj, LOP_EXCLUSIVE); membar_exit_before_atomic(); owner = rwl->rwl_owner; if (__predict_false((owner & RWLOCK_WAIT) || rw_cas(&rwl->rwl_owner, owner, 0))) rw_do_exit(rwl, RWLOCK_WRLOCK); } #ifdef DIAGNOSTIC /* * Put the diagnostic functions here to keep the main code free * from ifdef clutter. */ static void rw_enter_diag(struct rwlock *rwl, int flags) { switch (flags & RW_OPMASK) { case RW_WRITE: case RW_READ: if (RW_PROC(curproc) == RW_PROC(rwl->rwl_owner)) panic("rw_enter: %s locking against myself", rwl->rwl_name); break; case RW_DOWNGRADE: /* * If we're downgrading, we must hold the write lock. */ if ((rwl->rwl_owner & RWLOCK_WRLOCK) == 0) panic("rw_enter: %s downgrade of non-write lock", rwl->rwl_name); if (RW_PROC(curproc) != RW_PROC(rwl->rwl_owner)) panic("rw_enter: %s downgrade, not holder", rwl->rwl_name); break; default: panic("rw_enter: unknown op 0x%x", flags); } } #else #define rw_enter_diag(r, f) #endif static void _rw_init_flags_witness(struct rwlock *rwl, const char *name, int lo_flags, const struct lock_type *type) { rwl->rwl_owner = 0; rwl->rwl_name = name; #ifdef WITNESS rwl->rwl_lock_obj.lo_flags = lo_flags; rwl->rwl_lock_obj.lo_name = name; rwl->rwl_lock_obj.lo_type = type; WITNESS_INIT(&rwl->rwl_lock_obj, type); #else (void)type; (void)lo_flags; #endif } void _rw_init_flags(struct rwlock *rwl, const char *name, int flags, const struct lock_type *type) { _rw_init_flags_witness(rwl, name, RWLOCK_LO_FLAGS(flags), type); } int rw_enter(struct rwlock *rwl, int flags) { const struct rwlock_op *op; unsigned long inc, o; #ifdef MULTIPROCESSOR /* * If process holds the kernel lock, then we want to give up on CPU * as soon as possible so other processes waiting for the kernel lock * can progress. Hence no spinning if we hold the kernel lock. */ unsigned int spin = (_kernel_lock_held()) ? 0 : RW_SPINS; #endif int error, prio; #ifdef WITNESS int lop_flags; lop_flags = LOP_NEWORDER; if (flags & RW_WRITE) lop_flags |= LOP_EXCLUSIVE; if (flags & RW_DUPOK) lop_flags |= LOP_DUPOK; if ((flags & RW_NOSLEEP) == 0 && (flags & RW_DOWNGRADE) == 0) WITNESS_CHECKORDER(&rwl->rwl_lock_obj, lop_flags, NULL); #endif op = &rw_ops[(flags & RW_OPMASK) - 1]; inc = op->inc + RW_PROC(curproc) * op->proc_mult; retry: while (__predict_false(((o = rwl->rwl_owner) & op->check) != 0)) { unsigned long set = o | op->wait_set; int do_sleep; /* Avoid deadlocks after panic or in DDB */ if (panicstr || db_active) return (0); #ifdef MULTIPROCESSOR /* * It makes sense to try to spin just in case the lock * is acquired by writer. */ if ((o & RWLOCK_WRLOCK) && (spin != 0)) { spin--; CPU_BUSY_CYCLE(); continue; } #endif rw_enter_diag(rwl, flags); if (flags & RW_NOSLEEP) return (EBUSY); prio = op->wait_prio; if (flags & RW_INTR) prio |= PCATCH; sleep_setup(rwl, prio, rwl->rwl_name); do_sleep = !rw_cas(&rwl->rwl_owner, o, set); error = sleep_finish(0, do_sleep); if ((flags & RW_INTR) && (error != 0)) return (error); if (flags & RW_SLEEPFAIL) return (EAGAIN); } if (__predict_false(rw_cas(&rwl->rwl_owner, o, o + inc))) goto retry; membar_enter_after_atomic(); /* * If old lock had RWLOCK_WAIT and RWLOCK_WRLOCK set, it means we * downgraded a write lock and had possible read waiter, wake them * to let them retry the lock. */ if (__predict_false((o & (RWLOCK_WRLOCK|RWLOCK_WAIT)) == (RWLOCK_WRLOCK|RWLOCK_WAIT))) wakeup(rwl); if (flags & RW_DOWNGRADE) WITNESS_DOWNGRADE(&rwl->rwl_lock_obj, lop_flags); else WITNESS_LOCK(&rwl->rwl_lock_obj, lop_flags); return (0); } void rw_exit(struct rwlock *rwl) { unsigned long wrlock; /* Avoid deadlocks after panic or in DDB */ if (panicstr || db_active) return; wrlock = rwl->rwl_owner & RWLOCK_WRLOCK; if (wrlock) rw_assert_wrlock(rwl); else rw_assert_rdlock(rwl); WITNESS_UNLOCK(&rwl->rwl_lock_obj, wrlock ? LOP_EXCLUSIVE : 0); membar_exit_before_atomic(); rw_do_exit(rwl, wrlock); } /* membar_exit_before_atomic() has to precede call of this function. */ void rw_do_exit(struct rwlock *rwl, unsigned long wrlock) { unsigned long owner, set; do { owner = rwl->rwl_owner; if (wrlock) set = 0; else set = (owner - RWLOCK_READ_INCR) & ~(RWLOCK_WAIT|RWLOCK_WRWANT); /* * Potential MP race here. If the owner had WRWANT set, we * cleared it and a reader can sneak in before a writer. */ } while (__predict_false(rw_cas(&rwl->rwl_owner, owner, set))); if (owner & RWLOCK_WAIT) wakeup(rwl); } int rw_status(struct rwlock *rwl) { unsigned long owner = rwl->rwl_owner; if (owner & RWLOCK_WRLOCK) { if (RW_PROC(curproc) == RW_PROC(owner)) return RW_WRITE; else return RW_WRITE_OTHER; } if (owner) return RW_READ; return (0); } #ifdef DIAGNOSTIC void rw_assert_wrlock(struct rwlock *rwl) { if (panicstr || db_active) return; #ifdef WITNESS witness_assert(&rwl->rwl_lock_obj, LA_XLOCKED); #else if (!(rwl->rwl_owner & RWLOCK_WRLOCK)) panic("%s: lock not held", rwl->rwl_name); if (RW_PROC(curproc) != RW_PROC(rwl->rwl_owner)) panic("%s: lock not held by this process", rwl->rwl_name); #endif } void rw_assert_rdlock(struct rwlock *rwl) { if (panicstr || db_active) return; #ifdef WITNESS witness_assert(&rwl->rwl_lock_obj, LA_SLOCKED); #else if (!RW_PROC(rwl->rwl_owner) || (rwl->rwl_owner & RWLOCK_WRLOCK)) panic("%s: lock not shared", rwl->rwl_name); #endif } void rw_assert_anylock(struct rwlock *rwl) { if (panicstr || db_active) return; #ifdef WITNESS witness_assert(&rwl->rwl_lock_obj, LA_LOCKED); #else switch (rw_status(rwl)) { case RW_WRITE_OTHER: panic("%s: lock held by different process", rwl->rwl_name); case 0: panic("%s: lock not held", rwl->rwl_name); } #endif } void rw_assert_unlocked(struct rwlock *rwl) { if (panicstr || db_active) return; #ifdef WITNESS witness_assert(&rwl->rwl_lock_obj, LA_UNLOCKED); #else if (RW_PROC(curproc) == RW_PROC(rwl->rwl_owner)) panic("%s: lock held", rwl->rwl_name); #endif } #endif /* recursive rwlocks; */ void _rrw_init_flags(struct rrwlock *rrwl, const char *name, int flags, const struct lock_type *type) { memset(rrwl, 0, sizeof(struct rrwlock)); _rw_init_flags_witness(&rrwl->rrwl_lock, name, RRWLOCK_LO_FLAGS(flags), type); } int rrw_enter(struct rrwlock *rrwl, int flags) { int rv; if (RW_PROC(rrwl->rrwl_lock.rwl_owner) == RW_PROC(curproc)) { if (flags & RW_RECURSEFAIL) return (EDEADLK); else { rrwl->rrwl_wcnt++; WITNESS_LOCK(&rrwl->rrwl_lock.rwl_lock_obj, LOP_EXCLUSIVE); return (0); } } rv = rw_enter(&rrwl->rrwl_lock, flags); if (rv == 0) rrwl->rrwl_wcnt = 1; return (rv); } void rrw_exit(struct rrwlock *rrwl) { if (RW_PROC(rrwl->rrwl_lock.rwl_owner) == RW_PROC(curproc)) { KASSERT(rrwl->rrwl_wcnt > 0); rrwl->rrwl_wcnt--; if (rrwl->rrwl_wcnt != 0) { WITNESS_UNLOCK(&rrwl->rrwl_lock.rwl_lock_obj, LOP_EXCLUSIVE); return; } } rw_exit(&rrwl->rrwl_lock); } int rrw_status(struct rrwlock *rrwl) { return (rw_status(&rrwl->rrwl_lock)); } /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Andrew Doran. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #define RWLOCK_OBJ_MAGIC 0x5aa3c85d struct rwlock_obj { struct rwlock ro_lock; u_int ro_magic; u_int ro_refcnt; }; struct pool rwlock_obj_pool; /* * rw_obj_init: * * Initialize the mutex object store. */ void rw_obj_init(void) { pool_init(&rwlock_obj_pool, sizeof(struct rwlock_obj), 0, IPL_MPFLOOR, PR_WAITOK, "rwobjpl", NULL); } /* * rw_obj_alloc: * * Allocate a single lock object. */ void _rw_obj_alloc_flags(struct rwlock **lock, const char *name, int flags, struct lock_type *type) { struct rwlock_obj *mo; mo = pool_get(&rwlock_obj_pool, PR_WAITOK); mo->ro_magic = RWLOCK_OBJ_MAGIC; _rw_init_flags(&mo->ro_lock, name, flags, type); mo->ro_refcnt = 1; *lock = &mo->ro_lock; } /* * rw_obj_hold: * * Add a single reference to a lock object. A reference to the object * must already be held, and must be held across this call. */ void rw_obj_hold(struct rwlock *lock) { struct rwlock_obj *mo = (struct rwlock_obj *)lock; KASSERTMSG(mo->ro_magic == RWLOCK_OBJ_MAGIC, "%s: lock %p: mo->ro_magic (%#x) != RWLOCK_OBJ_MAGIC (%#x)", __func__, mo, mo->ro_magic, RWLOCK_OBJ_MAGIC); KASSERTMSG(mo->ro_refcnt > 0, "%s: lock %p: mo->ro_refcnt (%#x) == 0", __func__, mo, mo->ro_refcnt); atomic_inc_int(&mo->ro_refcnt); } /* * rw_obj_free: * * Drop a reference from a lock object. If the last reference is being * dropped, free the object and return true. Otherwise, return false. */ int rw_obj_free(struct rwlock *lock) { struct rwlock_obj *mo = (struct rwlock_obj *)lock; KASSERTMSG(mo->ro_magic == RWLOCK_OBJ_MAGIC, "%s: lock %p: mo->ro_magic (%#x) != RWLOCK_OBJ_MAGIC (%#x)", __func__, mo, mo->ro_magic, RWLOCK_OBJ_MAGIC); KASSERTMSG(mo->ro_refcnt > 0, "%s: lock %p: mo->ro_refcnt (%#x) == 0", __func__, mo, mo->ro_refcnt); if (atomic_dec_int_nv(&mo->ro_refcnt) > 0) { return false; } #if notyet WITNESS_DESTROY(&mo->ro_lock); #endif pool_put(&rwlock_obj_pool, mo); return true; }
6 2 1 1 1 1 1 1 2 1 1 181 1 127 25 1 2 1 1 2 1 1 1 2 2 1 2 1 1 1 2 1 1 1 1 1 1 1 2 1 2 2 2 2 2 2 12 56 1 54 54 12 1 8 4 8 8 69 1 53 2 38 3 5 2 6 47 55 3 3 4 18 1 16 17 16 5 5 5 9 9 7 7 2 2 1 2 1 6 6 5 5 5 5 14 1 7 1 1 12 8 4 4 20 1 17 1 1 34 34 1 1 1 5 1 1 1 24 2 1 1 16 2 15 7 21 1 1 1 102 1 6 3 6 3 5 3 1 2 1 27 8 7 1 9 3 1 8 1 1 9 4 63 4 60 63 61 20 52 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 /* $OpenBSD: tcp_usrreq.c,v 1.231 2024/04/12 16:07:09 bluhm Exp $ */ /* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 * * NRL grants permission for redistribution and use in source and binary * forms, with or without modification, of the software and documentation * created at NRL provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgements: * This product includes software developed by the University of * California, Berkeley and its contributors. * This product includes software developed at the Information * Technology Division, US Naval Research Laboratory. * 4. Neither the name of the NRL nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the US Naval * Research Laboratory (NRL). */ #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/protosw.h> #include <sys/stat.h> #include <sys/sysctl.h> #include <sys/domain.h> #include <sys/kernel.h> #include <sys/pool.h> #include <sys/proc.h> #include <net/if.h> #include <net/if_var.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/in_var.h> #include <netinet/ip.h> #include <netinet/in_pcb.h> #include <netinet/ip_var.h> #include <netinet6/ip6_var.h> #include <netinet/tcp.h> #include <netinet/tcp_fsm.h> #include <netinet/tcp_seq.h> #include <netinet/tcp_timer.h> #include <netinet/tcp_var.h> #include <netinet/tcp_debug.h> #ifdef INET6 #include <netinet6/in6_var.h> #endif #ifndef TCP_SENDSPACE #define TCP_SENDSPACE 1024*16 #endif u_int tcp_sendspace = TCP_SENDSPACE; #ifndef TCP_RECVSPACE #define TCP_RECVSPACE 1024*16 #endif u_int tcp_recvspace = TCP_RECVSPACE; u_int tcp_autorcvbuf_inc = 16 * 1024; const struct pr_usrreqs tcp_usrreqs = { .pru_attach = tcp_attach, .pru_detach = tcp_detach, .pru_bind = tcp_bind, .pru_listen = tcp_listen, .pru_connect = tcp_connect, .pru_accept = tcp_accept, .pru_disconnect = tcp_disconnect, .pru_shutdown = tcp_shutdown, .pru_rcvd = tcp_rcvd, .pru_send = tcp_send, .pru_abort = tcp_abort, .pru_sense = tcp_sense, .pru_rcvoob = tcp_rcvoob, .pru_sendoob = tcp_sendoob, .pru_control = in_control, .pru_sockaddr = tcp_sockaddr, .pru_peeraddr = tcp_peeraddr, }; #ifdef INET6 const struct pr_usrreqs tcp6_usrreqs = { .pru_attach = tcp_attach, .pru_detach = tcp_detach, .pru_bind = tcp_bind, .pru_listen = tcp_listen, .pru_connect = tcp_connect, .pru_accept = tcp_accept, .pru_disconnect = tcp_disconnect, .pru_shutdown = tcp_shutdown, .pru_rcvd = tcp_rcvd, .pru_send = tcp_send, .pru_abort = tcp_abort, .pru_sense = tcp_sense, .pru_rcvoob = tcp_rcvoob, .pru_sendoob = tcp_sendoob, .pru_control = in6_control, .pru_sockaddr = tcp_sockaddr, .pru_peeraddr = tcp_peeraddr, }; #endif const struct sysctl_bounded_args tcpctl_vars[] = { { TCPCTL_RFC1323, &tcp_do_rfc1323, 0, 1 }, { TCPCTL_SACK, &tcp_do_sack, 0, 1 }, { TCPCTL_MSSDFLT, &tcp_mssdflt, TCP_MSS, 65535 }, { TCPCTL_RSTPPSLIMIT, &tcp_rst_ppslim, 1, 1000 * 1000 }, { TCPCTL_ACK_ON_PUSH, &tcp_ack_on_push, 0, 1 }, #ifdef TCP_ECN { TCPCTL_ECN, &tcp_do_ecn, 0, 1 }, #endif { TCPCTL_SYN_CACHE_LIMIT, &tcp_syn_cache_limit, 1, 1000 * 1000 }, { TCPCTL_SYN_BUCKET_LIMIT, &tcp_syn_bucket_limit, 1, INT_MAX }, { TCPCTL_RFC3390, &tcp_do_rfc3390, 0, 2 }, { TCPCTL_ALWAYS_KEEPALIVE, &tcp_always_keepalive, 0, 1 }, { TCPCTL_TSO, &tcp_do_tso, 0, 1 }, }; struct inpcbtable tcbtable; #ifdef INET6 struct inpcbtable tcb6table; #endif int tcp_fill_info(struct tcpcb *, struct socket *, struct mbuf *); int tcp_ident(void *, size_t *, void *, size_t, int); static inline int tcp_sogetpcb(struct socket *, struct inpcb **, struct tcpcb **); static inline int tcp_sogetpcb(struct socket *so, struct inpcb **rinp, struct tcpcb **rtp) { struct inpcb *inp; struct tcpcb *tp; /* * When a TCP is attached to a socket, then there will be * a (struct inpcb) pointed at by the socket, and this * structure will point at a subsidiary (struct tcpcb). */ if ((inp = sotoinpcb(so)) == NULL || (tp = intotcpcb(inp)) == NULL) { if (so->so_error) return so->so_error; return EINVAL; } *rinp = inp; *rtp = tp; return 0; } /* * Export internal TCP state information via a struct tcp_info without * leaking any sensitive information. Sequence numbers are reported * relative to the initial sequence number. */ int tcp_fill_info(struct tcpcb *tp, struct socket *so, struct mbuf *m) { struct proc *p = curproc; struct tcp_info *ti; u_int t = 1000; /* msec => usec */ uint64_t now; if (sizeof(*ti) > MLEN) { MCLGETL(m, M_WAITOK, sizeof(*ti)); if (!ISSET(m->m_flags, M_EXT)) return ENOMEM; } ti = mtod(m, struct tcp_info *); m->m_len = sizeof(*ti); memset(ti, 0, sizeof(*ti)); now = tcp_now(); ti->tcpi_state = tp->t_state; if ((tp->t_flags & TF_REQ_TSTMP) && (tp->t_flags & TF_RCVD_TSTMP)) ti->tcpi_options |= TCPI_OPT_TIMESTAMPS; if (tp->t_flags & TF_SACK_PERMIT) ti->tcpi_options |= TCPI_OPT_SACK; if ((tp->t_flags & TF_REQ_SCALE) && (tp->t_flags & TF_RCVD_SCALE)) { ti->tcpi_options |= TCPI_OPT_WSCALE; ti->tcpi_snd_wscale = tp->snd_scale; ti->tcpi_rcv_wscale = tp->rcv_scale; } #ifdef TCP_ECN if (tp->t_flags & TF_ECN_PERMIT) ti->tcpi_options |= TCPI_OPT_ECN; #endif ti->tcpi_rto = tp->t_rxtcur * t; ti->tcpi_snd_mss = tp->t_maxseg; ti->tcpi_rcv_mss = tp->t_peermss; ti->tcpi_last_data_sent = (now - tp->t_sndtime) * t; ti->tcpi_last_ack_sent = (now - tp->t_sndacktime) * t; ti->tcpi_last_data_recv = (now - tp->t_rcvtime) * t; ti->tcpi_last_ack_recv = (now - tp->t_rcvacktime) * t; ti->tcpi_rtt = ((uint64_t)tp->t_srtt * t) >> (TCP_RTT_SHIFT + TCP_RTT_BASE_SHIFT); ti->tcpi_rttvar = ((uint64_t)tp->t_rttvar * t) >> (TCP_RTTVAR_SHIFT + TCP_RTT_BASE_SHIFT); ti->tcpi_snd_ssthresh = tp->snd_ssthresh; ti->tcpi_snd_cwnd = tp->snd_cwnd; ti->tcpi_rcv_space = tp->rcv_wnd; /* * Provide only minimal information for unprivileged processes. */ if (suser(p) != 0) return 0; /* FreeBSD-specific extension fields for tcp_info. */ ti->tcpi_snd_wnd = tp->snd_wnd; ti->tcpi_snd_nxt = tp->snd_nxt - tp->iss; ti->tcpi_rcv_nxt = tp->rcv_nxt - tp->irs; /* missing tcpi_toe_tid */ ti->tcpi_snd_rexmitpack = tp->t_sndrexmitpack; ti->tcpi_rcv_ooopack = tp->t_rcvoopack; ti->tcpi_snd_zerowin = tp->t_sndzerowin; /* OpenBSD extensions */ ti->tcpi_rttmin = tp->t_rttmin * t; ti->tcpi_max_sndwnd = tp->max_sndwnd; ti->tcpi_rcv_adv = tp->rcv_adv - tp->irs; ti->tcpi_rcv_up = tp->rcv_up - tp->irs; ti->tcpi_snd_una = tp->snd_una - tp->iss; ti->tcpi_snd_up = tp->snd_up - tp->iss; ti->tcpi_snd_wl1 = tp->snd_wl1 - tp->iss; ti->tcpi_snd_wl2 = tp->snd_wl2 - tp->iss; ti->tcpi_snd_max = tp->snd_max - tp->iss; ti->tcpi_ts_recent = tp->ts_recent; /* XXX value from the wire */ ti->tcpi_ts_recent_age = (now - tp->ts_recent_age) * t; ti->tcpi_rfbuf_cnt = tp->rfbuf_cnt; ti->tcpi_rfbuf_ts = (now - tp->rfbuf_ts) * t; ti->tcpi_so_rcv_sb_cc = so->so_rcv.sb_cc; ti->tcpi_so_rcv_sb_hiwat = so->so_rcv.sb_hiwat; ti->tcpi_so_rcv_sb_lowat = so->so_rcv.sb_lowat; ti->tcpi_so_rcv_sb_wat = so->so_rcv.sb_wat; ti->tcpi_so_snd_sb_cc = so->so_snd.sb_cc; ti->tcpi_so_snd_sb_hiwat = so->so_snd.sb_hiwat; ti->tcpi_so_snd_sb_lowat = so->so_snd.sb_lowat; ti->tcpi_so_snd_sb_wat = so->so_snd.sb_wat; return 0; } int tcp_ctloutput(int op, struct socket *so, int level, int optname, struct mbuf *m) { int error = 0; struct inpcb *inp; struct tcpcb *tp; int i; inp = sotoinpcb(so); if (inp == NULL) return (ECONNRESET); if (level != IPPROTO_TCP) { #ifdef INET6 if (ISSET(inp->inp_flags, INP_IPV6)) error = ip6_ctloutput(op, so, level, optname, m); else #endif error = ip_ctloutput(op, so, level, optname, m); return (error); } tp = intotcpcb(inp); switch (op) { case PRCO_SETOPT: switch (optname) { case TCP_NODELAY: if (m == NULL || m->m_len < sizeof (int)) error = EINVAL; else if (*mtod(m, int *)) tp->t_flags |= TF_NODELAY; else tp->t_flags &= ~TF_NODELAY; break; case TCP_NOPUSH: if (m == NULL || m->m_len < sizeof (int)) error = EINVAL; else if (*mtod(m, int *)) tp->t_flags |= TF_NOPUSH; else if (tp->t_flags & TF_NOPUSH) { tp->t_flags &= ~TF_NOPUSH; if (TCPS_HAVEESTABLISHED(tp->t_state)) error = tcp_output(tp); } break; case TCP_MAXSEG: if (m == NULL || m->m_len < sizeof (int)) { error = EINVAL; break; } i = *mtod(m, int *); if (i > 0 && i <= tp->t_maxseg) tp->t_maxseg = i; else error = EINVAL; break; case TCP_SACK_ENABLE: if (m == NULL || m->m_len < sizeof (int)) { error = EINVAL; break; } if (TCPS_HAVEESTABLISHED(tp->t_state)) { error = EPERM; break; } if (tp->t_flags & TF_SIGNATURE) { error = EPERM; break; } if (*mtod(m, int *)) tp->sack_enable = 1; else tp->sack_enable = 0; break; #ifdef TCP_SIGNATURE case TCP_MD5SIG: if (m == NULL || m->m_len < sizeof (int)) { error = EINVAL; break; } if (TCPS_HAVEESTABLISHED(tp->t_state)) { error = EPERM; break; } if (*mtod(m, int *)) { tp->t_flags |= TF_SIGNATURE; tp->sack_enable = 0; } else tp->t_flags &= ~TF_SIGNATURE; break; #endif /* TCP_SIGNATURE */ default: error = ENOPROTOOPT; break; } break; case PRCO_GETOPT: switch (optname) { case TCP_NODELAY: m->m_len = sizeof(int); *mtod(m, int *) = tp->t_flags & TF_NODELAY; break; case TCP_NOPUSH: m->m_len = sizeof(int); *mtod(m, int *) = tp->t_flags & TF_NOPUSH; break; case TCP_MAXSEG: m->m_len = sizeof(int); *mtod(m, int *) = tp->t_maxseg; break; case TCP_SACK_ENABLE: m->m_len = sizeof(int); *mtod(m, int *) = tp->sack_enable; break; case TCP_INFO: error = tcp_fill_info(tp, so, m); break; #ifdef TCP_SIGNATURE case TCP_MD5SIG: m->m_len = sizeof(int); *mtod(m, int *) = tp->t_flags & TF_SIGNATURE; break; #endif default: error = ENOPROTOOPT; break; } break; } return (error); } /* * Attach TCP protocol to socket, allocating * internet protocol control block, tcp control block, * buffer space, and entering LISTEN state to accept connections. */ int tcp_attach(struct socket *so, int proto, int wait) { struct inpcbtable *table; struct tcpcb *tp; struct inpcb *inp; int error; if (so->so_pcb) return EISCONN; if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0 || sbcheckreserve(so->so_snd.sb_wat, tcp_sendspace) || sbcheckreserve(so->so_rcv.sb_wat, tcp_recvspace)) { error = soreserve(so, tcp_sendspace, tcp_recvspace); if (error) return (error); } NET_ASSERT_LOCKED(); #ifdef INET6 if (so->so_proto->pr_domain->dom_family == PF_INET6) table = &tcb6table; else #endif table = &tcbtable; error = in_pcballoc(so, table, wait); if (error) return (error); inp = sotoinpcb(so); tp = tcp_newtcpcb(inp, wait); if (tp == NULL) { unsigned int nofd = so->so_state & SS_NOFDREF; /* XXX */ so->so_state &= ~SS_NOFDREF; /* don't free the socket yet */ in_pcbdetach(inp); so->so_state |= nofd; return (ENOBUFS); } tp->t_state = TCPS_CLOSED; #ifdef INET6 if (ISSET(inp->inp_flags, INP_IPV6)) tp->pf = PF_INET6; else #endif tp->pf = PF_INET; if ((so->so_options & SO_LINGER) && so->so_linger == 0) so->so_linger = TCP_LINGERTIME; if (so->so_options & SO_DEBUG) tcp_trace(TA_USER, TCPS_CLOSED, tp, tp, NULL, PRU_ATTACH, 0); return (0); } int tcp_detach(struct socket *so) { struct inpcb *inp; struct tcpcb *otp = NULL, *tp; int error; short ostate; soassertlocked(so); if ((error = tcp_sogetpcb(so, &inp, &tp))) return (error); if (so->so_options & SO_DEBUG) { otp = tp; ostate = tp->t_state; } /* * Detach the TCP protocol from the socket. * If the protocol state is non-embryonic, then can't * do this directly: have to initiate a PRU_DISCONNECT, * which may finish later; embryonic TCB's can just * be discarded here. */ tp = tcp_dodisconnect(tp); if (otp) tcp_trace(TA_USER, ostate, tp, otp, NULL, PRU_DETACH, 0); return (0); } /* * Give the socket an address. */ int tcp_bind(struct socket *so, struct mbuf *nam, struct proc *p) { struct inpcb *inp; struct tcpcb *tp; int error; short ostate; soassertlocked(so); if ((error = tcp_sogetpcb(so, &inp, &tp))) return (error); if (so->so_options & SO_DEBUG) ostate = tp->t_state; error = in_pcbbind(inp, nam, p); if (so->so_options & SO_DEBUG) tcp_trace(TA_USER, ostate, tp, tp, NULL, PRU_BIND, 0); return (error); } /* * Prepare to accept connections. */ int tcp_listen(struct socket *so) { struct inpcb *inp; struct tcpcb *tp, *otp = NULL; int error; short ostate; soassertlocked(so); if ((error = tcp_sogetpcb(so, &inp, &tp))) return (error); if (so->so_options & SO_DEBUG) { otp = tp; ostate = tp->t_state; } if (inp->inp_lport == 0) if ((error = in_pcbbind(inp, NULL, curproc))) goto out; /* * If the in_pcbbind() above is called, the tp->pf * should still be whatever it was before. */ tp->t_state = TCPS_LISTEN; out: if (otp) tcp_trace(TA_USER, ostate, tp, otp, NULL, PRU_LISTEN, 0); return (error); } /* * Initiate connection to peer. * Create a template for use in transmissions on this connection. * Enter SYN_SENT state, and mark socket as connecting. * Start keep-alive timer, and seed output sequence space. * Send initial segment on connection. */ int tcp_connect(struct socket *so, struct mbuf *nam) { struct inpcb *inp; struct tcpcb *tp, *otp = NULL; int error; short ostate; soassertlocked(so); if ((error = tcp_sogetpcb(so, &inp, &tp))) return (error); if (so->so_options & SO_DEBUG) { otp = tp; ostate = tp->t_state; } #ifdef INET6 if (ISSET(inp->inp_flags, INP_IPV6)) { struct sockaddr_in6 *sin6; if ((error = in6_nam2sin6(nam, &sin6))) goto out; if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) || IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { error = EINVAL; goto out; } } else #endif { struct sockaddr_in *sin; if ((error = in_nam2sin(nam, &sin))) goto out; if ((sin->sin_addr.s_addr == INADDR_ANY) || (sin->sin_addr.s_addr == INADDR_BROADCAST) || IN_MULTICAST(sin->sin_addr.s_addr) || in_broadcast(sin->sin_addr, inp->inp_rtableid)) { error = EINVAL; goto out; } } error = in_pcbconnect(inp, nam); if (error) goto out; tp->t_template = tcp_template(tp); if (tp->t_template == 0) { in_pcbunset_faddr(inp); in_pcbdisconnect(inp); error = ENOBUFS; goto out; } so->so_state |= SS_CONNECTOUT; /* Compute window scaling to request. */ tcp_rscale(tp, sb_max); soisconnecting(so); tcpstat_inc(tcps_connattempt); tp->t_state = TCPS_SYN_SENT; TCP_TIMER_ARM(tp, TCPT_KEEP, tcptv_keep_init); tcp_set_iss_tsm(tp); tcp_sendseqinit(tp); tp->snd_last = tp->snd_una; error = tcp_output(tp); out: if (otp) tcp_trace(TA_USER, ostate, tp, otp, NULL, PRU_CONNECT, 0); return (error); } /* * Accept a connection. Essentially all the work is done at higher * levels; just return the address of the peer, storing through addr. */ int tcp_accept(struct socket *so, struct mbuf *nam) { struct inpcb *inp; struct tcpcb *tp; int error; soassertlocked(so); if ((error = tcp_sogetpcb(so, &inp, &tp))) return (error); in_setpeeraddr(inp, nam); if (so->so_options & SO_DEBUG) tcp_trace(TA_USER, tp->t_state, tp, tp, NULL, PRU_ACCEPT, 0); return (0); } /* * Initiate disconnect from peer. * If connection never passed embryonic stage, just drop; * else if don't need to let data drain, then can just drop anyways, * else have to begin TCP shutdown process: mark socket disconnecting, * drain unread data, state switch to reflect user close, and * send segment (e.g. FIN) to peer. Socket will be really disconnected * when peer sends FIN and acks ours. * * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB. */ int tcp_disconnect(struct socket *so) { struct inpcb *inp; struct tcpcb *tp, *otp = NULL; int error; short ostate; soassertlocked(so); if ((error = tcp_sogetpcb(so, &inp, &tp))) return (error); if (so->so_options & SO_DEBUG) { otp = tp; ostate = tp->t_state; } tp = tcp_dodisconnect(tp); if (otp) tcp_trace(TA_USER, ostate, tp, otp, NULL, PRU_DISCONNECT, 0); return (0); } /* * Mark the connection as being incapable of further output. */ int tcp_shutdown(struct socket *so) { struct inpcb *inp; struct tcpcb *tp, *otp = NULL; int error; short ostate; soassertlocked(so); if ((error = tcp_sogetpcb(so, &inp, &tp))) return (error); if (so->so_options & SO_DEBUG) { otp = tp; ostate = tp->t_state; } if (so->so_snd.sb_state & SS_CANTSENDMORE) goto out; socantsendmore(so); tp = tcp_usrclosed(tp); if (tp) error = tcp_output(tp); out: if (otp) tcp_trace(TA_USER, ostate, tp, otp, NULL, PRU_SHUTDOWN, 0); return (error); } /* * After a receive, possibly send window update to peer. */ void tcp_rcvd(struct socket *so) { struct inpcb *inp; struct tcpcb *tp; short ostate; soassertlocked(so); if (tcp_sogetpcb(so, &inp, &tp)) return; if (so->so_options & SO_DEBUG) ostate = tp->t_state; /* * soreceive() calls this function when a user receives * ancillary data on a listening socket. We don't call * tcp_output in such a case, since there is no header * template for a listening socket and hence the kernel * will panic. */ if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) != 0) (void) tcp_output(tp); if (so->so_options & SO_DEBUG) tcp_trace(TA_USER, ostate, tp, tp, NULL, PRU_RCVD, 0); } /* * Do a send by putting data in output queue and updating urgent * marker if URG set. Possibly send more data. */ int tcp_send(struct socket *so, struct mbuf *m, struct mbuf *nam, struct mbuf *control) { struct inpcb *inp; struct tcpcb *tp; int error; short ostate; soassertlocked(so); if (control && control->m_len) { error = EINVAL; goto out; } if ((error = tcp_sogetpcb(so, &inp, &tp))) goto out; if (so->so_options & SO_DEBUG) ostate = tp->t_state; sbappendstream(so, &so->so_snd, m); m = NULL; error = tcp_output(tp); if (so->so_options & SO_DEBUG) tcp_trace(TA_USER, ostate, tp, tp, NULL, PRU_SEND, 0); out: m_freem(control); m_freem(m); return (error); } /* * Abort the TCP. */ void tcp_abort(struct socket *so) { struct inpcb *inp; struct tcpcb *tp, *otp = NULL; short ostate; soassertlocked(so); if (tcp_sogetpcb(so, &inp, &tp)) return; if (so->so_options & SO_DEBUG) { otp = tp; ostate = tp->t_state; } tp = tcp_drop(tp, ECONNABORTED); if (otp) tcp_trace(TA_USER, ostate, tp, otp, NULL, PRU_ABORT, 0); } int tcp_sense(struct socket *so, struct stat *ub) { struct inpcb *inp; struct tcpcb *tp; int error; soassertlocked(so); if ((error = tcp_sogetpcb(so, &inp, &tp))) return (error); ub->st_blksize = so->so_snd.sb_hiwat; if (so->so_options & SO_DEBUG) tcp_trace(TA_USER, tp->t_state, tp, tp, NULL, PRU_SENSE, 0); return (0); } int tcp_rcvoob(struct socket *so, struct mbuf *m, int flags) { struct inpcb *inp; struct tcpcb *tp; int error; soassertlocked(so); if ((error = tcp_sogetpcb(so, &inp, &tp))) return (error); if ((so->so_oobmark == 0 && (so->so_rcv.sb_state & SS_RCVATMARK) == 0) || so->so_options & SO_OOBINLINE || tp->t_oobflags & TCPOOB_HADDATA) { error = EINVAL; goto out; } if ((tp->t_oobflags & TCPOOB_HAVEDATA) == 0) { error = EWOULDBLOCK; goto out; } m->m_len = 1; *mtod(m, caddr_t) = tp->t_iobc; if ((flags & MSG_PEEK) == 0) tp->t_oobflags ^= (TCPOOB_HAVEDATA | TCPOOB_HADDATA); out: if (so->so_options & SO_DEBUG) tcp_trace(TA_USER, tp->t_state, tp, tp, NULL, PRU_RCVOOB, 0); return (error); } int tcp_sendoob(struct socket *so, struct mbuf *m, struct mbuf *nam, struct mbuf *control) { struct inpcb *inp; struct tcpcb *tp; int error; short ostate; soassertlocked(so); if (control && control->m_len) { error = EINVAL; goto release; } if ((error = tcp_sogetpcb(so, &inp, &tp))) goto release; if (so->so_options & SO_DEBUG) ostate = tp->t_state; if (sbspace(so, &so->so_snd) < -512) { error = ENOBUFS; goto out; } /* * According to RFC961 (Assigned Protocols), * the urgent pointer points to the last octet * of urgent data. We continue, however, * to consider it to indicate the first octet * of data past the urgent section. * Otherwise, snd_up should be one lower. */ sbappendstream(so, &so->so_snd, m); m = NULL; tp->snd_up = tp->snd_una + so->so_snd.sb_cc; tp->t_force = 1; error = tcp_output(tp); tp->t_force = 0; out: if (so->so_options & SO_DEBUG) tcp_trace(TA_USER, ostate, tp, tp, NULL, PRU_SENDOOB, 0); release: m_freem(control); m_freem(m); return (error); } int tcp_sockaddr(struct socket *so, struct mbuf *nam) { struct inpcb *inp; struct tcpcb *tp; int error; soassertlocked(so); if ((error = tcp_sogetpcb(so, &inp, &tp))) return (error); in_setsockaddr(inp, nam); if (so->so_options & SO_DEBUG) tcp_trace(TA_USER, tp->t_state, tp, tp, NULL, PRU_SOCKADDR, 0); return (0); } int tcp_peeraddr(struct socket *so, struct mbuf *nam) { struct inpcb *inp; struct tcpcb *tp; int error; soassertlocked(so); if ((error = tcp_sogetpcb(so, &inp, &tp))) return (error); in_setpeeraddr(inp, nam); if (so->so_options & SO_DEBUG) tcp_trace(TA_USER, tp->t_state, tp, tp, NULL, PRU_PEERADDR, 0); return (0); } /* * Initiate (or continue) disconnect. * If embryonic state, just send reset (once). * If in ``let data drain'' option and linger null, just drop. * Otherwise (hard), mark socket disconnecting and drop * current input data; switch states based on user close, and * send segment to peer (with FIN). */ struct tcpcb * tcp_dodisconnect(struct tcpcb *tp) { struct socket *so = tp->t_inpcb->inp_socket; if (TCPS_HAVEESTABLISHED(tp->t_state) == 0) tp = tcp_close(tp); else if ((so->so_options & SO_LINGER) && so->so_linger == 0) tp = tcp_drop(tp, 0); else { soisdisconnecting(so); sbflush(so, &so->so_rcv); tp = tcp_usrclosed(tp); if (tp) (void) tcp_output(tp); } return (tp); } /* * User issued close, and wish to trail through shutdown states: * if never received SYN, just forget it. If got a SYN from peer, * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN. * If already got a FIN from peer, then almost done; go to LAST_ACK * state. In all other cases, have already sent FIN to peer (e.g. * after PRU_SHUTDOWN), and just have to play tedious game waiting * for peer to send FIN or not respond to keep-alives, etc. * We can let the user exit from the close as soon as the FIN is acked. */ struct tcpcb * tcp_usrclosed(struct tcpcb *tp) { switch (tp->t_state) { case TCPS_CLOSED: case TCPS_LISTEN: case TCPS_SYN_SENT: tp->t_state = TCPS_CLOSED; tp = tcp_close(tp); break; case TCPS_SYN_RECEIVED: case TCPS_ESTABLISHED: tp->t_state = TCPS_FIN_WAIT_1; break; case TCPS_CLOSE_WAIT: tp->t_state = TCPS_LAST_ACK; break; } if (tp && tp->t_state >= TCPS_FIN_WAIT_2) { soisdisconnected(tp->t_inpcb->inp_socket); /* * If we are in FIN_WAIT_2, we arrived here because the * application did a shutdown of the send side. Like the * case of a transition from FIN_WAIT_1 to FIN_WAIT_2 after * a full close, we start a timer to make sure sockets are * not left in FIN_WAIT_2 forever. */ if (tp->t_state == TCPS_FIN_WAIT_2) TCP_TIMER_ARM(tp, TCPT_2MSL, tcp_maxidle); } return (tp); } /* * Look up a socket for ident or tcpdrop, ... */ int tcp_ident(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int dodrop) { int error = 0; struct tcp_ident_mapping tir; struct inpcb *inp; struct tcpcb *tp = NULL; struct sockaddr_in *fin, *lin; #ifdef INET6 struct sockaddr_in6 *fin6, *lin6; struct in6_addr f6, l6; #endif NET_ASSERT_LOCKED(); if (dodrop) { if (oldp != NULL || *oldlenp != 0) return (EINVAL); if (newp == NULL) return (EPERM); if (newlen < sizeof(tir)) return (ENOMEM); if ((error = copyin(newp, &tir, sizeof (tir))) != 0 ) return (error); } else { if (oldp == NULL) return (EINVAL); if (*oldlenp < sizeof(tir)) return (ENOMEM); if (newp != NULL || newlen != 0) return (EINVAL); if ((error = copyin(oldp, &tir, sizeof (tir))) != 0 ) return (error); } switch (tir.faddr.ss_family) { #ifdef INET6 case AF_INET6: fin6 = (struct sockaddr_in6 *)&tir.faddr; error = in6_embedscope(&f6, fin6, NULL, NULL); if (error) return EINVAL; /*?*/ lin6 = (struct sockaddr_in6 *)&tir.laddr; error = in6_embedscope(&l6, lin6, NULL, NULL); if (error) return EINVAL; /*?*/ break; #endif case AF_INET: fin = (struct sockaddr_in *)&tir.faddr; lin = (struct sockaddr_in *)&tir.laddr; break; default: return (EINVAL); } switch (tir.faddr.ss_family) { #ifdef INET6 case AF_INET6: inp = in6_pcblookup(&tcb6table, &f6, fin6->sin6_port, &l6, lin6->sin6_port, tir.rdomain); break; #endif case AF_INET: inp = in_pcblookup(&tcbtable, fin->sin_addr, fin->sin_port, lin->sin_addr, lin->sin_port, tir.rdomain); break; default: unhandled_af(tir.faddr.ss_family); } if (dodrop) { if (inp && (tp = intotcpcb(inp)) && ((inp->inp_socket->so_options & SO_ACCEPTCONN) == 0)) tp = tcp_drop(tp, ECONNABORTED); else error = ESRCH; in_pcbunref(inp); return (error); } if (inp == NULL) { tcpstat_inc(tcps_pcbhashmiss); switch (tir.faddr.ss_family) { #ifdef INET6 case AF_INET6: inp = in6_pcblookup_listen(&tcb6table, &l6, lin6->sin6_port, NULL, tir.rdomain); break; #endif case AF_INET: inp = in_pcblookup_listen(&tcbtable, lin->sin_addr, lin->sin_port, NULL, tir.rdomain); break; } } if (inp != NULL && (inp->inp_socket->so_state & SS_CONNECTOUT)) { tir.ruid = inp->inp_socket->so_ruid; tir.euid = inp->inp_socket->so_euid; } else { tir.ruid = -1; tir.euid = -1; } *oldlenp = sizeof (tir); error = copyout((void *)&tir, oldp, sizeof (tir)); in_pcbunref(inp); return (error); } int tcp_sysctl_tcpstat(void *oldp, size_t *oldlenp, void *newp) { uint64_t counters[tcps_ncounters]; struct tcpstat tcpstat; struct syn_cache_set *set; int i = 0; #define ASSIGN(field) do { tcpstat.field = counters[i++]; } while (0) memset(&tcpstat, 0, sizeof tcpstat); counters_read(tcpcounters, counters, nitems(counters), NULL); ASSIGN(tcps_connattempt); ASSIGN(tcps_accepts); ASSIGN(tcps_connects); ASSIGN(tcps_drops); ASSIGN(tcps_conndrops); ASSIGN(tcps_closed); ASSIGN(tcps_segstimed); ASSIGN(tcps_rttupdated); ASSIGN(tcps_delack); ASSIGN(tcps_timeoutdrop); ASSIGN(tcps_rexmttimeo); ASSIGN(tcps_persisttimeo); ASSIGN(tcps_persistdrop); ASSIGN(tcps_keeptimeo); ASSIGN(tcps_keepprobe); ASSIGN(tcps_keepdrops); ASSIGN(tcps_sndtotal); ASSIGN(tcps_sndpack); ASSIGN(tcps_sndbyte); ASSIGN(tcps_sndrexmitpack); ASSIGN(tcps_sndrexmitbyte); ASSIGN(tcps_sndrexmitfast); ASSIGN(tcps_sndacks); ASSIGN(tcps_sndprobe); ASSIGN(tcps_sndurg); ASSIGN(tcps_sndwinup); ASSIGN(tcps_sndctrl); ASSIGN(tcps_rcvtotal); ASSIGN(tcps_rcvpack); ASSIGN(tcps_rcvbyte); ASSIGN(tcps_rcvbadsum); ASSIGN(tcps_rcvbadoff); ASSIGN(tcps_rcvmemdrop); ASSIGN(tcps_rcvnosec); ASSIGN(tcps_rcvshort); ASSIGN(tcps_rcvduppack); ASSIGN(tcps_rcvdupbyte); ASSIGN(tcps_rcvpartduppack); ASSIGN(tcps_rcvpartdupbyte); ASSIGN(tcps_rcvoopack); ASSIGN(tcps_rcvoobyte); ASSIGN(tcps_rcvpackafterwin); ASSIGN(tcps_rcvbyteafterwin); ASSIGN(tcps_rcvafterclose); ASSIGN(tcps_rcvwinprobe); ASSIGN(tcps_rcvdupack); ASSIGN(tcps_rcvacktoomuch); ASSIGN(tcps_rcvacktooold); ASSIGN(tcps_rcvackpack); ASSIGN(tcps_rcvackbyte); ASSIGN(tcps_rcvwinupd); ASSIGN(tcps_pawsdrop); ASSIGN(tcps_predack); ASSIGN(tcps_preddat); ASSIGN(tcps_pcbhashmiss); ASSIGN(tcps_noport); ASSIGN(tcps_badsyn); ASSIGN(tcps_dropsyn); ASSIGN(tcps_rcvbadsig); ASSIGN(tcps_rcvgoodsig); ASSIGN(tcps_inswcsum); ASSIGN(tcps_outswcsum); ASSIGN(tcps_ecn_accepts); ASSIGN(tcps_ecn_rcvece); ASSIGN(tcps_ecn_rcvcwr); ASSIGN(tcps_ecn_rcvce); ASSIGN(tcps_ecn_sndect); ASSIGN(tcps_ecn_sndece); ASSIGN(tcps_ecn_sndcwr); ASSIGN(tcps_cwr_ecn); ASSIGN(tcps_cwr_frecovery); ASSIGN(tcps_cwr_timeout); ASSIGN(tcps_sc_added); ASSIGN(tcps_sc_completed); ASSIGN(tcps_sc_timed_out); ASSIGN(tcps_sc_overflowed); ASSIGN(tcps_sc_reset); ASSIGN(tcps_sc_unreach); ASSIGN(tcps_sc_bucketoverflow); ASSIGN(tcps_sc_aborted); ASSIGN(tcps_sc_dupesyn); ASSIGN(tcps_sc_dropped); ASSIGN(tcps_sc_collisions); ASSIGN(tcps_sc_retransmitted); ASSIGN(tcps_sc_seedrandom); ASSIGN(tcps_sc_hash_size); ASSIGN(tcps_sc_entry_count); ASSIGN(tcps_sc_entry_limit); ASSIGN(tcps_sc_bucket_maxlen); ASSIGN(tcps_sc_bucket_limit); ASSIGN(tcps_sc_uses_left); ASSIGN(tcps_conndrained); ASSIGN(tcps_sack_recovery_episode); ASSIGN(tcps_sack_rexmits); ASSIGN(tcps_sack_rexmit_bytes); ASSIGN(tcps_sack_rcv_opts); ASSIGN(tcps_sack_snd_opts); ASSIGN(tcps_sack_drop_opts); ASSIGN(tcps_outswtso); ASSIGN(tcps_outhwtso); ASSIGN(tcps_outpkttso); ASSIGN(tcps_outbadtso); ASSIGN(tcps_inswlro); ASSIGN(tcps_inhwlro); ASSIGN(tcps_inpktlro); ASSIGN(tcps_inbadlro); #undef ASSIGN mtx_enter(&syn_cache_mtx); set = &tcp_syn_cache[tcp_syn_cache_active]; tcpstat.tcps_sc_hash_size = set->scs_size; tcpstat.tcps_sc_entry_count = set->scs_count; tcpstat.tcps_sc_entry_limit = tcp_syn_cache_limit; tcpstat.tcps_sc_bucket_maxlen = 0; for (i = 0; i < set->scs_size; i++) { if (tcpstat.tcps_sc_bucket_maxlen < set->scs_buckethead[i].sch_length) tcpstat.tcps_sc_bucket_maxlen = set->scs_buckethead[i].sch_length; } tcpstat.tcps_sc_bucket_limit = tcp_syn_bucket_limit; tcpstat.tcps_sc_uses_left = set->scs_use; mtx_leave(&syn_cache_mtx); return (sysctl_rdstruct(oldp, oldlenp, newp, &tcpstat, sizeof(tcpstat))); } /* * Sysctl for tcp variables. */ int tcp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int error, nval; /* All sysctl names at this level are terminal. */ if (namelen != 1) return (ENOTDIR); switch (name[0]) { case TCPCTL_KEEPINITTIME: NET_LOCK(); nval = tcptv_keep_init / TCP_TIME(1); error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &nval, 1, 3 * (TCPTV_KEEP_INIT / TCP_TIME(1))); if (!error) tcptv_keep_init = TCP_TIME(nval); NET_UNLOCK(); return (error); case TCPCTL_KEEPIDLE: NET_LOCK(); nval = tcp_keepidle / TCP_TIME(1); error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &nval, 1, 5 * (TCPTV_KEEP_IDLE / TCP_TIME(1))); if (!error) tcp_keepidle = TCP_TIME(nval); NET_UNLOCK(); return (error); case TCPCTL_KEEPINTVL: NET_LOCK(); nval = tcp_keepintvl / TCP_TIME(1); error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &nval, 1, 3 * (TCPTV_KEEPINTVL / TCP_TIME(1))); if (!error) tcp_keepintvl = TCP_TIME(nval); NET_UNLOCK(); return (error); case TCPCTL_BADDYNAMIC: NET_LOCK(); error = sysctl_struct(oldp, oldlenp, newp, newlen, baddynamicports.tcp, sizeof(baddynamicports.tcp)); NET_UNLOCK(); return (error); case TCPCTL_ROOTONLY: if (newp && securelevel > 0) return (EPERM); NET_LOCK(); error = sysctl_struct(oldp, oldlenp, newp, newlen, rootonlyports.tcp, sizeof(rootonlyports.tcp)); NET_UNLOCK(); return (error); case TCPCTL_IDENT: NET_LOCK(); error = tcp_ident(oldp, oldlenp, newp, newlen, 0); NET_UNLOCK(); return (error); case TCPCTL_DROP: NET_LOCK(); error = tcp_ident(oldp, oldlenp, newp, newlen, 1); NET_UNLOCK(); return (error); case TCPCTL_REASS_LIMIT: NET_LOCK(); nval = tcp_reass_limit; error = sysctl_int(oldp, oldlenp, newp, newlen, &nval); if (!error && nval != tcp_reass_limit) { error = pool_sethardlimit(&tcpqe_pool, nval, NULL, 0); if (!error) tcp_reass_limit = nval; } NET_UNLOCK(); return (error); case TCPCTL_SACKHOLE_LIMIT: NET_LOCK(); nval = tcp_sackhole_limit; error = sysctl_int(oldp, oldlenp, newp, newlen, &nval); if (!error && nval != tcp_sackhole_limit) { error = pool_sethardlimit(&sackhl_pool, nval, NULL, 0); if (!error) tcp_sackhole_limit = nval; } NET_UNLOCK(); return (error); case TCPCTL_STATS: return (tcp_sysctl_tcpstat(oldp, oldlenp, newp)); case TCPCTL_SYN_USE_LIMIT: NET_LOCK(); error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &tcp_syn_use_limit, 0, INT_MAX); if (!error && newp != NULL) { /* * Global tcp_syn_use_limit is used when reseeding a * new cache. Also update the value in active cache. */ mtx_enter(&syn_cache_mtx); if (tcp_syn_cache[0].scs_use > tcp_syn_use_limit) tcp_syn_cache[0].scs_use = tcp_syn_use_limit; if (tcp_syn_cache[1].scs_use > tcp_syn_use_limit) tcp_syn_cache[1].scs_use = tcp_syn_use_limit; mtx_leave(&syn_cache_mtx); } NET_UNLOCK(); return (error); case TCPCTL_SYN_HASH_SIZE: NET_LOCK(); nval = tcp_syn_hash_size; error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &nval, 1, 100000); if (!error && nval != tcp_syn_hash_size) { /* * If global hash size has been changed, * switch sets as soon as possible. Then * the actual hash array will be reallocated. */ mtx_enter(&syn_cache_mtx); if (tcp_syn_cache[0].scs_size != nval) tcp_syn_cache[0].scs_use = 0; if (tcp_syn_cache[1].scs_size != nval) tcp_syn_cache[1].scs_use = 0; tcp_syn_hash_size = nval; mtx_leave(&syn_cache_mtx); } NET_UNLOCK(); return (error); default: NET_LOCK(); error = sysctl_bounded_arr(tcpctl_vars, nitems(tcpctl_vars), name, namelen, oldp, oldlenp, newp, newlen); NET_UNLOCK(); return (error); } /* NOTREACHED */ } /* * Scale the send buffer so that inflight data is not accounted against * the limit. The buffer will scale with the congestion window, if the * the receiver stops acking data the window will shrink and therefore * the buffer size will shrink as well. * In low memory situation try to shrink the buffer to the initial size * disabling the send buffer scaling as long as the situation persists. */ void tcp_update_sndspace(struct tcpcb *tp) { struct socket *so = tp->t_inpcb->inp_socket; u_long nmax = so->so_snd.sb_hiwat; if (sbchecklowmem()) { /* low on memory try to get rid of some */ if (tcp_sendspace < nmax) nmax = tcp_sendspace; } else if (so->so_snd.sb_wat != tcp_sendspace) /* user requested buffer size, auto-scaling disabled */ nmax = so->so_snd.sb_wat; else /* automatic buffer scaling */ nmax = MIN(sb_max, so->so_snd.sb_wat + tp->snd_max - tp->snd_una); /* a writable socket must be preserved because of poll(2) semantics */ if (sbspace(so, &so->so_snd) >= so->so_snd.sb_lowat) { if (nmax < so->so_snd.sb_cc + so->so_snd.sb_lowat) nmax = so->so_snd.sb_cc + so->so_snd.sb_lowat; /* keep in sync with sbreserve() calculation */ if (nmax * 8 < so->so_snd.sb_mbcnt + so->so_snd.sb_lowat) nmax = (so->so_snd.sb_mbcnt+so->so_snd.sb_lowat+7) / 8; } /* round to MSS boundary */ nmax = roundup(nmax, tp->t_maxseg); if (nmax != so->so_snd.sb_hiwat) sbreserve(so, &so->so_snd, nmax); } /* * Scale the recv buffer by looking at how much data was transferred in * one approximated RTT. If more than a big part of the recv buffer was * transferred during that time we increase the buffer by a constant. * In low memory situation try to shrink the buffer to the initial size. */ void tcp_update_rcvspace(struct tcpcb *tp) { struct socket *so = tp->t_inpcb->inp_socket; u_long nmax = so->so_rcv.sb_hiwat; if (sbchecklowmem()) { /* low on memory try to get rid of some */ if (tcp_recvspace < nmax) nmax = tcp_recvspace; } else if (so->so_rcv.sb_wat != tcp_recvspace) /* user requested buffer size, auto-scaling disabled */ nmax = so->so_rcv.sb_wat; else { /* automatic buffer scaling */ if (tp->rfbuf_cnt > so->so_rcv.sb_hiwat / 8 * 7) nmax = MIN(sb_max, so->so_rcv.sb_hiwat + tcp_autorcvbuf_inc); } /* a readable socket must be preserved because of poll(2) semantics */ if (so->so_rcv.sb_cc >= so->so_rcv.sb_lowat && nmax < so->so_snd.sb_lowat) nmax = so->so_snd.sb_lowat; if (nmax == so->so_rcv.sb_hiwat) return; /* round to MSS boundary */ nmax = roundup(nmax, tp->t_maxseg); sbreserve(so, &so->so_rcv, nmax); }
8 2 6 6 6 2 2 1 2 214 4 210 4 209 209 210 24 199 209 10 10 10 10 1 10 11 5 1 1 1 1 2 3 1 1 2 2 2 2 2 2 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 /* $OpenBSD: sd.c,v 1.336 2024/05/04 16:40:38 kn Exp $ */ /* $NetBSD: sd.c,v 1.111 1997/04/02 02:29:41 mycroft Exp $ */ /*- * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Charles M. Hannum. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Originally written by Julian Elischer (julian@dialix.oz.au) * for TRW Financial Systems for use under the MACH(2.5) operating system. * * TRW Financial Systems, in accordance with their agreement with Carnegie * Mellon University, makes this software available to CMU to distribute * or use in any manner that they see fit as long as this message is kept with * the software. For this reason TFS also grants any other persons or * organisations permission to use or modify this software. * * TFS supplies this software to be publicly redistributed * on the understanding that TFS is not responsible for the correct * functioning of this software in any circumstances. * * Ported to run under 386BSD by Julian Elischer (julian@dialix.oz.au) Sept 1992 */ #include <sys/stdint.h> #include <sys/param.h> #include <sys/systm.h> #include <sys/timeout.h> #include <sys/fcntl.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <sys/mtio.h> #include <sys/mutex.h> #include <sys/buf.h> #include <sys/uio.h> #include <sys/malloc.h> #include <sys/pool.h> #include <sys/errno.h> #include <sys/device.h> #include <sys/disklabel.h> #include <sys/disk.h> #include <sys/conf.h> #include <sys/scsiio.h> #include <sys/dkio.h> #include <sys/reboot.h> #include <scsi/scsi_all.h> #include <scsi/scsi_debug.h> #include <scsi/scsi_disk.h> #include <scsi/scsiconf.h> #include <scsi/sdvar.h> #include <ufs/ffs/fs.h> /* for BBSIZE and SBSIZE */ #include <sys/vnode.h> int sdmatch(struct device *, void *, void *); void sdattach(struct device *, struct device *, void *); int sdactivate(struct device *, int); int sddetach(struct device *, int); void sdminphys(struct buf *); int sdgetdisklabel(dev_t, struct sd_softc *, struct disklabel *, int); void sdstart(struct scsi_xfer *); int sd_interpret_sense(struct scsi_xfer *); int sd_read_cap_10(struct sd_softc *, int); int sd_read_cap_16(struct sd_softc *, int); int sd_read_cap(struct sd_softc *, int); int sd_thin_pages(struct sd_softc *, int); int sd_vpd_block_limits(struct sd_softc *, int); int sd_vpd_thin(struct sd_softc *, int); int sd_thin_params(struct sd_softc *, int); int sd_get_parms(struct sd_softc *, int); int sd_flush(struct sd_softc *, int); void viscpy(u_char *, u_char *, int); int sd_ioctl_inquiry(struct sd_softc *, struct dk_inquiry *); int sd_ioctl_cache(struct sd_softc *, long, struct dk_cache *); int sd_cmd_rw6(struct scsi_generic *, int, u_int64_t, u_int32_t); int sd_cmd_rw10(struct scsi_generic *, int, u_int64_t, u_int32_t); int sd_cmd_rw12(struct scsi_generic *, int, u_int64_t, u_int32_t); int sd_cmd_rw16(struct scsi_generic *, int, u_int64_t, u_int32_t); void sd_buf_done(struct scsi_xfer *); const struct cfattach sd_ca = { sizeof(struct sd_softc), sdmatch, sdattach, sddetach, sdactivate }; struct cfdriver sd_cd = { NULL, "sd", DV_DISK }; const struct scsi_inquiry_pattern sd_patterns[] = { {T_DIRECT, T_FIXED, "", "", ""}, {T_DIRECT, T_REMOV, "", "", ""}, {T_RDIRECT, T_FIXED, "", "", ""}, {T_RDIRECT, T_REMOV, "", "", ""}, {T_OPTICAL, T_FIXED, "", "", ""}, {T_OPTICAL, T_REMOV, "", "", ""}, }; #define sdlookup(unit) (struct sd_softc *)disk_lookup(&sd_cd, (unit)) int sdmatch(struct device *parent, void *match, void *aux) { struct scsi_attach_args *sa = aux; struct scsi_inquiry_data *inq = &sa->sa_sc_link->inqdata; int priority; (void)scsi_inqmatch(inq, sd_patterns, nitems(sd_patterns), sizeof(sd_patterns[0]), &priority); return priority; } /* * The routine called by the low level scsi routine when it discovers * a device suitable for this driver. */ void sdattach(struct device *parent, struct device *self, void *aux) { struct dk_cache dkc; struct sd_softc *sc = (struct sd_softc *)self; struct scsi_attach_args *sa = aux; struct disk_parms *dp = &sc->params; struct scsi_link *link = sa->sa_sc_link; int error, sd_autoconf; int sortby = BUFQ_DEFAULT; SC_DEBUG(link, SDEV_DB2, ("sdattach:\n")); sd_autoconf = scsi_autoconf | SCSI_SILENT | SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE; /* * Store information needed to contact our base driver. */ sc->sc_link = link; link->interpret_sense = sd_interpret_sense; link->device_softc = sc; if (ISSET(link->flags, SDEV_ATAPI) && ISSET(link->flags, SDEV_REMOVABLE)) SET(link->quirks, SDEV_NOSYNCCACHE); /* * Use the subdriver to request information regarding the drive. We * cannot use interrupts yet, so the request must specify this. */ printf("\n"); scsi_xsh_set(&sc->sc_xsh, link, sdstart); /* Spin up non-UMASS devices ready or not. */ if (!ISSET(link->flags, SDEV_UMASS)) scsi_start(link, SSS_START, sd_autoconf); /* * Some devices (e.g. BlackBerry Pearl) won't admit they have * media loaded unless its been locked in. */ if (ISSET(link->flags, SDEV_REMOVABLE)) scsi_prevent(link, PR_PREVENT, sd_autoconf); /* Check that it is still responding and ok. */ error = scsi_test_unit_ready(sc->sc_link, TEST_READY_RETRIES * 3, sd_autoconf); if (error == 0) error = sd_get_parms(sc, sd_autoconf); if (ISSET(link->flags, SDEV_REMOVABLE)) scsi_prevent(link, PR_ALLOW, sd_autoconf); if (error == 0) { printf("%s: %lluMB, %u bytes/sector, %llu sectors", sc->sc_dev.dv_xname, dp->disksize / (1048576 / dp->secsize), dp->secsize, dp->disksize); if (ISSET(sc->flags, SDF_THIN)) { sortby = BUFQ_FIFO; printf(", thin"); } if (ISSET(link->flags, SDEV_READONLY)) printf(", readonly"); printf("\n"); } /* * Initialize disk structures. */ sc->sc_dk.dk_name = sc->sc_dev.dv_xname; bufq_init(&sc->sc_bufq, sortby); /* * Enable write cache by default. */ memset(&dkc, 0, sizeof(dkc)); if (sd_ioctl_cache(sc, DIOCGCACHE, &dkc) == 0 && dkc.wrcache == 0) { dkc.wrcache = 1; sd_ioctl_cache(sc, DIOCSCACHE, &dkc); } /* Attach disk. */ disk_attach(&sc->sc_dev, &sc->sc_dk); } int sdactivate(struct device *self, int act) { struct scsi_link *link; struct sd_softc *sc = (struct sd_softc *)self; if (ISSET(sc->flags, SDF_DYING)) return ENXIO; link = sc->sc_link; switch (act) { case DVACT_SUSPEND: /* * We flush the cache, since we our next step before * DVACT_POWERDOWN might be a hibernate operation. */ if (ISSET(sc->flags, SDF_DIRTY)) sd_flush(sc, SCSI_AUTOCONF); break; case DVACT_POWERDOWN: /* * Stop the disk. Stopping the disk should flush the * cache, but we are paranoid so we flush the cache * first. We're cold at this point, so we poll for * completion. */ if (ISSET(sc->flags, SDF_DIRTY)) sd_flush(sc, SCSI_AUTOCONF); if (ISSET(boothowto, RB_POWERDOWN)) scsi_start(link, SSS_STOP, SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY | SCSI_AUTOCONF); break; case DVACT_RESUME: scsi_start(link, SSS_START, SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_AUTOCONF); break; case DVACT_DEACTIVATE: SET(sc->flags, SDF_DYING); scsi_xsh_del(&sc->sc_xsh); break; } return 0; } int sddetach(struct device *self, int flags) { struct sd_softc *sc = (struct sd_softc *)self; bufq_drain(&sc->sc_bufq); disk_gone(sdopen, self->dv_unit); /* Detach disk. */ bufq_destroy(&sc->sc_bufq); disk_detach(&sc->sc_dk); return 0; } /* * Open the device. Make sure the partition info is as up-to-date as can be. */ int sdopen(dev_t dev, int flag, int fmt, struct proc *p) { struct scsi_link *link; struct sd_softc *sc; int error = 0, part, rawopen, unit; unit = DISKUNIT(dev); part = DISKPART(dev); rawopen = (part == RAW_PART) && (fmt == S_IFCHR); sc = sdlookup(unit); if (sc == NULL) return ENXIO; if (ISSET(sc->flags, SDF_DYING)) { device_unref(&sc->sc_dev); return ENXIO; } link = sc->sc_link; SC_DEBUG(link, SDEV_DB1, ("sdopen: dev=0x%x (unit %d (of %d), partition %d)\n", dev, unit, sd_cd.cd_ndevs, part)); if (ISSET(flag, FWRITE) && ISSET(link->flags, SDEV_READONLY)) { device_unref(&sc->sc_dev); return EACCES; } if ((error = disk_lock(&sc->sc_dk)) != 0) { device_unref(&sc->sc_dev); return error; } if (ISSET(sc->flags, SDF_DYING)) { error = ENXIO; goto die; } if (sc->sc_dk.dk_openmask != 0) { /* * If any partition is open, but the disk has been invalidated, * disallow further opens of non-raw partition. */ if (!ISSET(link->flags, SDEV_MEDIA_LOADED)) { if (rawopen) goto out; error = EIO; goto bad; } } else { /* Spin up non-UMASS devices ready or not. */ if (!ISSET(link->flags, SDEV_UMASS)) scsi_start(link, SSS_START, (rawopen ? SCSI_SILENT : 0) | SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE); /* * Use sd_interpret_sense() for sense errors. * * But only after spinning the disk up! Just in case a broken * device returns "Initialization command required." and causes * a loop of scsi_start() calls. */ if (ISSET(sc->flags, SDF_DYING)) { error = ENXIO; goto die; } SET(link->flags, SDEV_OPEN); /* * Try to prevent the unloading of a removable device while * it's open. But allow the open to proceed if the device can't * be locked in. */ if (ISSET(link->flags, SDEV_REMOVABLE)) { scsi_prevent(link, PR_PREVENT, SCSI_SILENT | SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE); } /* Check that it is still responding and ok. */ if (ISSET(sc->flags, SDF_DYING)) { error = ENXIO; goto die; } error = scsi_test_unit_ready(link, TEST_READY_RETRIES, SCSI_SILENT | SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE); if (error) { if (rawopen) { error = 0; goto out; } else goto bad; } /* Load the physical device parameters. */ if (ISSET(sc->flags, SDF_DYING)) { error = ENXIO; goto die; } SET(link->flags, SDEV_MEDIA_LOADED); if (sd_get_parms(sc, (rawopen ? SCSI_SILENT : 0)) == -1) { if (ISSET(sc->flags, SDF_DYING)) { error = ENXIO; goto die; } CLR(link->flags, SDEV_MEDIA_LOADED); error = ENXIO; goto bad; } SC_DEBUG(link, SDEV_DB3, ("Params loaded\n")); /* Load the partition info if not already loaded. */ error = sdgetdisklabel(dev, sc, sc->sc_dk.dk_label, 0); if (error == EIO || error == ENXIO) goto bad; SC_DEBUG(link, SDEV_DB3, ("Disklabel loaded\n")); } out: if ((error = disk_openpart(&sc->sc_dk, part, fmt, 1)) != 0) goto bad; SC_DEBUG(link, SDEV_DB3, ("open complete\n")); /* It's OK to fall through because dk_openmask is now non-zero. */ bad: if (sc->sc_dk.dk_openmask == 0) { if (ISSET(sc->flags, SDF_DYING)) { error = ENXIO; goto die; } if (ISSET(link->flags, SDEV_REMOVABLE)) scsi_prevent(link, PR_ALLOW, SCSI_SILENT | SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE); if (ISSET(sc->flags, SDF_DYING)) { error = ENXIO; goto die; } CLR(link->flags, SDEV_OPEN | SDEV_MEDIA_LOADED); } die: disk_unlock(&sc->sc_dk); device_unref(&sc->sc_dev); return error; } /* * Close the device. Only called if we are the last occurrence of an open * device. Convenient now but usually a pain. */ int sdclose(dev_t dev, int flag, int fmt, struct proc *p) { struct scsi_link *link; struct sd_softc *sc; int part = DISKPART(dev); int error = 0; sc = sdlookup(DISKUNIT(dev)); if (sc == NULL) return ENXIO; if (ISSET(sc->flags, SDF_DYING)) { device_unref(&sc->sc_dev); return ENXIO; } link = sc->sc_link; disk_lock_nointr(&sc->sc_dk); disk_closepart(&sc->sc_dk, part, fmt); if ((ISSET(flag, FWRITE) || sc->sc_dk.dk_openmask == 0) && ISSET(sc->flags, SDF_DIRTY)) sd_flush(sc, 0); if (sc->sc_dk.dk_openmask == 0) { if (ISSET(sc->flags, SDF_DYING)) { error = ENXIO; goto die; } if (ISSET(link->flags, SDEV_REMOVABLE)) scsi_prevent(link, PR_ALLOW, SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY | SCSI_SILENT); if (ISSET(sc->flags, SDF_DYING)) { error = ENXIO; goto die; } CLR(link->flags, SDEV_OPEN | SDEV_MEDIA_LOADED); if (ISSET(link->flags, SDEV_EJECTING)) { scsi_start(link, SSS_STOP|SSS_LOEJ, 0); if (ISSET(sc->flags, SDF_DYING)) { error = ENXIO; goto die; } CLR(link->flags, SDEV_EJECTING); } scsi_xsh_del(&sc->sc_xsh); } die: disk_unlock(&sc->sc_dk); device_unref(&sc->sc_dev); return error; } /* * Actually translate the requested transfer into one the physical driver * can understand. The transfer is described by a buf and will include * only one physical transfer. */ void sdstrategy(struct buf *bp) { struct scsi_link *link; struct sd_softc *sc; int s; sc = sdlookup(DISKUNIT(bp->b_dev)); if (sc == NULL) { bp->b_error = ENXIO; goto bad; } if (ISSET(sc->flags, SDF_DYING)) { bp->b_error = ENXIO; goto bad; } link = sc->sc_link; SC_DEBUG(link, SDEV_DB2, ("sdstrategy: %ld bytes @ blk %lld\n", bp->b_bcount, (long long)bp->b_blkno)); /* * If the device has been made invalid, error out. */ if (!ISSET(link->flags, SDEV_MEDIA_LOADED)) { if (ISSET(link->flags, SDEV_OPEN)) bp->b_error = EIO; else bp->b_error = ENODEV; goto bad; } /* Validate the request. */ if (bounds_check_with_label(bp, sc->sc_dk.dk_label) == -1) goto done; /* Place it in the queue of disk activities for this disk. */ bufq_queue(&sc->sc_bufq, bp); /* * Tell the device to get going on the transfer if it's * not doing anything, otherwise just wait for completion */ scsi_xsh_add(&sc->sc_xsh); device_unref(&sc->sc_dev); return; bad: SET(bp->b_flags, B_ERROR); bp->b_resid = bp->b_bcount; done: s = splbio(); biodone(bp); splx(s); if (sc != NULL) device_unref(&sc->sc_dev); } int sd_cmd_rw6(struct scsi_generic *generic, int read, u_int64_t secno, u_int32_t nsecs) { struct scsi_rw *cmd = (struct scsi_rw *)generic; cmd->opcode = read ? READ_COMMAND : WRITE_COMMAND; _lto3b(secno, cmd->addr); cmd->length = nsecs; return sizeof(*cmd); } int sd_cmd_rw10(struct scsi_generic *generic, int read, u_int64_t secno, u_int32_t nsecs) { struct scsi_rw_10 *cmd = (struct scsi_rw_10 *)generic; cmd->opcode = read ? READ_10 : WRITE_10; _lto4b(secno, cmd->addr); _lto2b(nsecs, cmd->length); return sizeof(*cmd); } int sd_cmd_rw12(struct scsi_generic *generic, int read, u_int64_t secno, u_int32_t nsecs) { struct scsi_rw_12 *cmd = (struct scsi_rw_12 *)generic; cmd->opcode = read ? READ_12 : WRITE_12; _lto4b(secno, cmd->addr); _lto4b(nsecs, cmd->length); return sizeof(*cmd); } int sd_cmd_rw16(struct scsi_generic *generic, int read, u_int64_t secno, u_int32_t nsecs) { struct scsi_rw_16 *cmd = (struct scsi_rw_16 *)generic; cmd->opcode = read ? READ_16 : WRITE_16; _lto8b(secno, cmd->addr); _lto4b(nsecs, cmd->length); return sizeof(*cmd); } /* * sdstart looks to see if there is a buf waiting for the device * and that the device is not already busy. If both are true, * It dequeues the buf and creates a scsi command to perform the * transfer in the buf. The transfer request will call scsi_done * on completion, which will in turn call this routine again * so that the next queued transfer is performed. * The bufs are queued by the strategy routine (sdstrategy) * * This routine is also called after other non-queued requests * have been made of the scsi driver, to ensure that the queue * continues to be drained. */ void sdstart(struct scsi_xfer *xs) { struct scsi_link *link = xs->sc_link; struct sd_softc *sc = link->device_softc; struct buf *bp; struct partition *p; u_int64_t secno; u_int32_t nsecs; int read; if (ISSET(sc->flags, SDF_DYING)) { scsi_xs_put(xs); return; } if (!ISSET(link->flags, SDEV_MEDIA_LOADED)) { bufq_drain(&sc->sc_bufq); scsi_xs_put(xs); return; } bp = bufq_dequeue(&sc->sc_bufq); if (bp == NULL) { scsi_xs_put(xs); return; } read = ISSET(bp->b_flags, B_READ); SET(xs->flags, (read ? SCSI_DATA_IN : SCSI_DATA_OUT)); xs->timeout = 60000; xs->data = bp->b_data; xs->datalen = bp->b_bcount; xs->done = sd_buf_done; xs->cookie = bp; xs->bp = bp; p = &sc->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)]; secno = DL_GETPOFFSET(p) + DL_BLKTOSEC(sc->sc_dk.dk_label, bp->b_blkno); nsecs = howmany(bp->b_bcount, sc->sc_dk.dk_label->d_secsize); if (!ISSET(link->flags, SDEV_ATAPI | SDEV_UMASS) && (SID_ANSII_REV(&link->inqdata) < SCSI_REV_2) && ((secno & 0x1fffff) == secno) && ((nsecs & 0xff) == nsecs)) xs->cmdlen = sd_cmd_rw6(&xs->cmd, read, secno, nsecs); else if (sc->params.disksize > UINT32_MAX) xs->cmdlen = sd_cmd_rw16(&xs->cmd, read, secno, nsecs); else if (nsecs <= UINT16_MAX) xs->cmdlen = sd_cmd_rw10(&xs->cmd, read, secno, nsecs); else xs->cmdlen = sd_cmd_rw12(&xs->cmd, read, secno, nsecs); disk_busy(&sc->sc_dk); if (!read) SET(sc->flags, SDF_DIRTY); scsi_xs_exec(xs); /* Move onto the next io. */ if (bufq_peek(&sc->sc_bufq)) scsi_xsh_add(&sc->sc_xsh); } void sd_buf_done(struct scsi_xfer *xs) { struct sd_softc *sc = xs->sc_link->device_softc; struct buf *bp = xs->cookie; int error, s; switch (xs->error) { case XS_NOERROR: bp->b_error = 0; CLR(bp->b_flags, B_ERROR); bp->b_resid = xs->resid; break; case XS_SENSE: case XS_SHORTSENSE: SC_DEBUG_SENSE(xs); error = sd_interpret_sense(xs); if (error == 0) { bp->b_error = 0; CLR(bp->b_flags, B_ERROR); bp->b_resid = xs->resid; break; } if (error != ERESTART) { bp->b_error = error; SET(bp->b_flags, B_ERROR); xs->retries = 0; } goto retry; case XS_BUSY: if (xs->retries) { if (scsi_delay(xs, 1) != ERESTART) xs->retries = 0; } goto retry; case XS_TIMEOUT: retry: if (xs->retries--) { scsi_xs_exec(xs); return; } /* FALLTHROUGH */ default: if (bp->b_error == 0) bp->b_error = EIO; SET(bp->b_flags, B_ERROR); bp->b_resid = bp->b_bcount; break; } disk_unbusy(&sc->sc_dk, bp->b_bcount - xs->resid, bp->b_blkno, bp->b_flags & B_READ); s = splbio(); biodone(bp); splx(s); scsi_xs_put(xs); } void sdminphys(struct buf *bp) { struct scsi_link *link; struct sd_softc *sc; long max; sc = sdlookup(DISKUNIT(bp->b_dev)); if (sc == NULL) return; /* XXX - right way to fail this? */ if (ISSET(sc->flags, SDF_DYING)) { device_unref(&sc->sc_dev); return; } link = sc->sc_link; /* * If the device is ancient, we want to make sure that * the transfer fits into a 6-byte cdb. * * XXX Note that the SCSI-I spec says that 256-block transfers * are allowed in a 6-byte read/write, and are specified * by setting the "length" to 0. However, we're conservative * here, allowing only 255-block transfers in case an * ancient device gets confused by length == 0. A length of 0 * in a 10-byte read/write actually means 0 blocks. */ if (!ISSET(link->flags, SDEV_ATAPI | SDEV_UMASS) && SID_ANSII_REV(&link->inqdata) < SCSI_REV_2) { max = sc->sc_dk.dk_label->d_secsize * 0xff; if (bp->b_bcount > max) bp->b_bcount = max; } if (link->bus->sb_adapter->dev_minphys != NULL) (*link->bus->sb_adapter->dev_minphys)(bp, link); else minphys(bp); device_unref(&sc->sc_dev); } int sdread(dev_t dev, struct uio *uio, int ioflag) { return physio(sdstrategy, dev, B_READ, sdminphys, uio); } int sdwrite(dev_t dev, struct uio *uio, int ioflag) { return physio(sdstrategy, dev, B_WRITE, sdminphys, uio); } /* * Perform special action on behalf of the user. Knows about the internals of * this device */ int sdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { struct scsi_link *link; struct sd_softc *sc; struct disklabel *lp; int error = 0; int part = DISKPART(dev); sc = sdlookup(DISKUNIT(dev)); if (sc == NULL) return ENXIO; if (ISSET(sc->flags, SDF_DYING)) { device_unref(&sc->sc_dev); return ENXIO; } link = sc->sc_link; SC_DEBUG(link, SDEV_DB2, ("sdioctl 0x%lx\n", cmd)); /* * If the device is not valid, abandon ship. */ if (!ISSET(link->flags, SDEV_MEDIA_LOADED)) { switch (cmd) { case DIOCLOCK: case DIOCEJECT: case SCIOCIDENTIFY: case SCIOCCOMMAND: case SCIOCDEBUG: if (part == RAW_PART) break; /* FALLTHROUGH */ default: if (!ISSET(link->flags, SDEV_OPEN)) { error = ENODEV; goto exit; } else { error = EIO; goto exit; } } } switch (cmd) { case DIOCRLDINFO: lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK); sdgetdisklabel(dev, sc, lp, 0); memcpy(sc->sc_dk.dk_label, lp, sizeof(*lp)); free(lp, M_TEMP, sizeof(*lp)); goto exit; case DIOCGPDINFO: sdgetdisklabel(dev, sc, (struct disklabel *)addr, 1); goto exit; case DIOCGDINFO: *(struct disklabel *)addr = *(sc->sc_dk.dk_label); goto exit; case DIOCGPART: ((struct partinfo *)addr)->disklab = sc->sc_dk.dk_label; ((struct partinfo *)addr)->part = &sc->sc_dk.dk_label->d_partitions[DISKPART(dev)]; goto exit; case DIOCWDINFO: case DIOCSDINFO: if (!ISSET(flag, FWRITE)) { error = EBADF; goto exit; } if ((error = disk_lock(&sc->sc_dk)) != 0) goto exit; error = setdisklabel(sc->sc_dk.dk_label, (struct disklabel *)addr, sc->sc_dk.dk_openmask); if (error == 0) { if (cmd == DIOCWDINFO) error = writedisklabel(DISKLABELDEV(dev), sdstrategy, sc->sc_dk.dk_label); } disk_unlock(&sc->sc_dk); goto exit; case DIOCLOCK: error = scsi_prevent(link, (*(int *)addr) ? PR_PREVENT : PR_ALLOW, 0); goto exit; case MTIOCTOP: if (((struct mtop *)addr)->mt_op != MTOFFL) { error = EIO; goto exit; } /* FALLTHROUGH */ case DIOCEJECT: if (!ISSET(link->flags, SDEV_REMOVABLE)) { error = ENOTTY; goto exit; } SET(link->flags, SDEV_EJECTING); goto exit; case DIOCINQ: error = scsi_do_ioctl(link, cmd, addr, flag); if (error == ENOTTY) error = sd_ioctl_inquiry(sc, (struct dk_inquiry *)addr); goto exit; case DIOCSCACHE: if (!ISSET(flag, FWRITE)) { error = EBADF; goto exit; } /* FALLTHROUGH */ case DIOCGCACHE: error = sd_ioctl_cache(sc, cmd, (struct dk_cache *)addr); goto exit; case DIOCCACHESYNC: if (!ISSET(flag, FWRITE)) { error = EBADF; goto exit; } if (ISSET(sc->flags, SDF_DIRTY) || *(int *)addr != 0) error = sd_flush(sc, 0); goto exit; default: if (part != RAW_PART) { error = ENOTTY; goto exit; } error = scsi_do_ioctl(link, cmd, addr, flag); } exit: device_unref(&sc->sc_dev); return error; } int sd_ioctl_inquiry(struct sd_softc *sc, struct dk_inquiry *di) { struct scsi_link *link; struct scsi_vpd_serial *vpd; vpd = dma_alloc(sizeof(*vpd), PR_WAITOK | PR_ZERO); if (ISSET(sc->flags, SDF_DYING)) { dma_free(vpd, sizeof(*vpd)); return ENXIO; } link = sc->sc_link; bzero(di, sizeof(struct dk_inquiry)); scsi_strvis(di->vendor, link->inqdata.vendor, sizeof(link->inqdata.vendor)); scsi_strvis(di->product, link->inqdata.product, sizeof(link->inqdata.product)); scsi_strvis(di->revision, link->inqdata.revision, sizeof(link->inqdata.revision)); /* the serial vpd page is optional */ if (scsi_inquire_vpd(link, vpd, sizeof(*vpd), SI_PG_SERIAL, 0) == 0) scsi_strvis(di->serial, vpd->serial, sizeof(vpd->serial)); else strlcpy(di->serial, "(unknown)", sizeof(vpd->serial)); dma_free(vpd, sizeof(*vpd)); return 0; } int sd_ioctl_cache(struct sd_softc *sc, long cmd, struct dk_cache *dkc) { struct scsi_link *link; union scsi_mode_sense_buf *buf; struct page_caching_mode *mode = NULL; u_int wrcache, rdcache; int big, rv; if (ISSET(sc->flags, SDF_DYING)) return ENXIO; link = sc->sc_link; if (ISSET(link->flags, SDEV_UMASS)) return EOPNOTSUPP; /* See if the adapter has special handling. */ rv = scsi_do_ioctl(link, cmd, (caddr_t)dkc, 0); if (rv != ENOTTY) return rv; buf = dma_alloc(sizeof(*buf), PR_WAITOK); if (buf == NULL) return ENOMEM; if (ISSET(sc->flags, SDF_DYING)) { rv = ENXIO; goto done; } rv = scsi_do_mode_sense(link, PAGE_CACHING_MODE, buf, (void **)&mode, sizeof(*mode) - 4, scsi_autoconf | SCSI_SILENT, &big); if (rv == 0 && mode == NULL) rv = EIO; if (rv != 0) goto done; wrcache = (ISSET(mode->flags, PG_CACHE_FL_WCE) ? 1 : 0); rdcache = (ISSET(mode->flags, PG_CACHE_FL_RCD) ? 0 : 1); switch (cmd) { case DIOCGCACHE: dkc->wrcache = wrcache; dkc->rdcache = rdcache; break; case DIOCSCACHE: if (dkc->wrcache == wrcache && dkc->rdcache == rdcache) break; if (dkc->wrcache) SET(mode->flags, PG_CACHE_FL_WCE); else CLR(mode->flags, PG_CACHE_FL_WCE); if (dkc->rdcache) CLR(mode->flags, PG_CACHE_FL_RCD); else SET(mode->flags, PG_CACHE_FL_RCD); if (ISSET(sc->flags, SDF_DYING)) { rv = ENXIO; goto done; } if (big) { rv = scsi_mode_select_big(link, SMS_PF, &buf->hdr_big, scsi_autoconf | SCSI_SILENT, 20000); } else { rv = scsi_mode_select(link, SMS_PF, &buf->hdr, scsi_autoconf | SCSI_SILENT, 20000); } break; } done: dma_free(buf, sizeof(*buf)); return rv; } /* * Load the label information on the named device. */ int sdgetdisklabel(dev_t dev, struct sd_softc *sc, struct disklabel *lp, int spoofonly) { char packname[sizeof(lp->d_packname) + 1]; char product[17], vendor[9]; struct scsi_link *link; size_t len; if (ISSET(sc->flags, SDF_DYING)) return ENXIO; link = sc->sc_link; bzero(lp, sizeof(struct disklabel)); lp->d_secsize = sc->params.secsize; lp->d_ntracks = sc->params.heads; lp->d_nsectors = sc->params.sectors; lp->d_ncylinders = sc->params.cyls; lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; if (lp->d_secpercyl == 0) { lp->d_secpercyl = 100; /* As long as it's not 0 - readdisklabel divides by it. */ } if (ISSET(link->flags, SDEV_UFI)) { lp->d_type = DTYPE_FLOPPY; strncpy(lp->d_typename, "USB floppy disk", sizeof(lp->d_typename)); } else { lp->d_type = DTYPE_SCSI; if ((link->inqdata.device & SID_TYPE) == T_OPTICAL) strncpy(lp->d_typename, "SCSI optical", sizeof(lp->d_typename)); else strncpy(lp->d_typename, "SCSI disk", sizeof(lp->d_typename)); } /* * Try to fit '<vendor> <product>' into d_packname. If that doesn't fit * then leave out '<vendor> ' and use only as much of '<product>' as * does fit. */ viscpy(vendor, link->inqdata.vendor, 8); viscpy(product, link->inqdata.product, 16); len = snprintf(packname, sizeof(packname), "%s %s", vendor, product); if (len > sizeof(lp->d_packname)) { strlcpy(packname, product, sizeof(packname)); len = strlen(packname); } /* * It is safe to use len as the count of characters to copy because * packname is sizeof(lp->d_packname)+1, the string in packname is * always null terminated and len does not count the terminating null. * d_packname is not a null terminated string. */ memcpy(lp->d_packname, packname, len); DL_SETDSIZE(lp, sc->params.disksize); lp->d_version = 1; lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; lp->d_checksum = dkcksum(lp); /* * Call the generic disklabel extraction routine. */ return readdisklabel(DISKLABELDEV(dev), sdstrategy, lp, spoofonly); } /* * Check Errors. */ int sd_interpret_sense(struct scsi_xfer *xs) { struct scsi_sense_data *sense = &xs->sense; struct scsi_link *link = xs->sc_link; int retval; u_int8_t serr = sense->error_code & SSD_ERRCODE; /* * Let the generic code handle everything except a few categories of * LUN not ready errors on open devices. */ if ((!ISSET(link->flags, SDEV_OPEN)) || (serr != SSD_ERRCODE_CURRENT && serr != SSD_ERRCODE_DEFERRED) || ((sense->flags & SSD_KEY) != SKEY_NOT_READY) || (sense->extra_len < 6)) return scsi_interpret_sense(xs); if (ISSET(xs->flags, SCSI_IGNORE_NOT_READY)) return 0; switch (ASC_ASCQ(sense)) { case SENSE_NOT_READY_BECOMING_READY: SC_DEBUG(link, SDEV_DB1, ("becoming ready.\n")); retval = scsi_delay(xs, 5); break; case SENSE_NOT_READY_INIT_REQUIRED: SC_DEBUG(link, SDEV_DB1, ("spinning up\n")); retval = scsi_start(link, SSS_START, SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_NOSLEEP); if (retval == 0) retval = ERESTART; else if (retval == ENOMEM) /* Can't issue the command. Fall back on a delay. */ retval = scsi_delay(xs, 5); else SC_DEBUG(link, SDEV_DB1, ("spin up failed (%#x)\n", retval)); break; default: retval = scsi_interpret_sense(xs); break; } return retval; } daddr_t sdsize(dev_t dev) { struct disklabel *lp; struct sd_softc *sc; daddr_t size; int part, omask; sc = sdlookup(DISKUNIT(dev)); if (sc == NULL) return -1; if (ISSET(sc->flags, SDF_DYING)) { size = -1; goto exit; } part = DISKPART(dev); omask = sc->sc_dk.dk_openmask & (1 << part); if (omask == 0 && sdopen(dev, 0, S_IFBLK, NULL) != 0) { size = -1; goto exit; } lp = sc->sc_dk.dk_label; if (ISSET(sc->flags, SDF_DYING)) { size = -1; goto exit; } if (!ISSET(sc->sc_link->flags, SDEV_MEDIA_LOADED)) size = -1; else if (lp->d_partitions[part].p_fstype != FS_SWAP) size = -1; else size = DL_SECTOBLK(lp, DL_GETPSIZE(&lp->d_partitions[part])); if (omask == 0 && sdclose(dev, 0, S_IFBLK, NULL) != 0) size = -1; exit: device_unref(&sc->sc_dev); return size; } /* #define SD_DUMP_NOT_TRUSTED if you just want to watch. */ static int sddoingadump; /* * Dump all of physical memory into the partition specified, starting * at offset 'dumplo' into the partition. */ int sddump(dev_t dev, daddr_t blkno, caddr_t va, size_t size) { struct sd_softc *sc; struct disklabel *lp; struct scsi_xfer *xs; u_int64_t nsects; /* partition sectors */ u_int64_t sectoff; /* partition offset */ u_int64_t totwrt; /* sectors left */ int part, rv, unit; u_int32_t sectorsize; u_int32_t nwrt; /* sectors to write */ /* Check if recursive dump; if so, punt. */ if (sddoingadump) return EFAULT; if (blkno < 0) return EINVAL; /* Mark as active early. */ sddoingadump = 1; unit = DISKUNIT(dev); /* Decompose unit & partition. */ part = DISKPART(dev); /* Check for acceptable drive number. */ if (unit >= sd_cd.cd_ndevs || (sc = sd_cd.cd_devs[unit]) == NULL) return ENXIO; /* * XXX Can't do this check, since the media might have been * XXX marked `invalid' by successful unmounting of all * XXX filesystems. */ #if 0 /* Make sure it was initialized. */ if (!ISSET(sc->sc_link->flags, SDEV_MEDIA_LOADED)) return ENXIO; #endif /* 0 */ /* Convert to disk sectors. Request must be a multiple of size. */ lp = sc->sc_dk.dk_label; sectorsize = lp->d_secsize; if ((size % sectorsize) != 0) return EFAULT; if ((blkno % DL_BLKSPERSEC(lp)) != 0) return EFAULT; totwrt = size / sectorsize; blkno = DL_BLKTOSEC(lp, blkno); nsects = DL_GETPSIZE(&lp->d_partitions[part]); sectoff = DL_GETPOFFSET(&lp->d_partitions[part]); /* Check transfer bounds against partition size. */ if ((blkno + totwrt) > nsects) return EINVAL; /* Offset block number to start of partition. */ blkno += sectoff; while (totwrt > 0) { if (totwrt > UINT32_MAX) nwrt = UINT32_MAX; else nwrt = totwrt; #ifndef SD_DUMP_NOT_TRUSTED xs = scsi_xs_get(sc->sc_link, SCSI_NOSLEEP | SCSI_DATA_OUT); if (xs == NULL) return ENOMEM; xs->timeout = 10000; xs->data = va; xs->datalen = nwrt * sectorsize; xs->cmdlen = sd_cmd_rw10(&xs->cmd, 0, blkno, nwrt); /* XXX */ rv = scsi_xs_sync(xs); scsi_xs_put(xs); if (rv != 0) return ENXIO; #else /* SD_DUMP_NOT_TRUSTED */ /* Let's just talk about this first. */ printf("sd%d: dump addr 0x%x, blk %lld\n", unit, va, (long long)blkno); delay(500 * 1000); /* 1/2 a second */ #endif /* ~SD_DUMP_NOT_TRUSTED */ /* Update block count. */ totwrt -= nwrt; blkno += nwrt; va += sectorsize * nwrt; } sddoingadump = 0; return 0; } /* * Copy up to len chars from src to dst, ignoring non-printables. * Must be room for len+1 chars in dst so we can write the NUL. * Does not assume src is NUL-terminated. */ void viscpy(u_char *dst, u_char *src, int len) { while (len > 0 && *src != '\0') { if (*src < 0x20 || *src >= 0x80) { src++; continue; } *dst++ = *src++; len--; } *dst = '\0'; } int sd_read_cap_10(struct sd_softc *sc, int flags) { struct scsi_read_cap_data *rdcap; int rv; rdcap = dma_alloc(sizeof(*rdcap), (ISSET(flags, SCSI_NOSLEEP) ? PR_NOWAIT : PR_WAITOK) | PR_ZERO); if (rdcap == NULL) return -1; if (ISSET(sc->flags, SDF_DYING)) { rv = -1; goto done; } rv = scsi_read_cap_10(sc->sc_link, rdcap, flags); if (rv == 0) { if (_4btol(rdcap->addr) == 0) { rv = -1; goto done; } sc->params.disksize = _4btol(rdcap->addr) + 1ll; sc->params.secsize = _4btol(rdcap->length); CLR(sc->flags, SDF_THIN); } done: dma_free(rdcap, sizeof(*rdcap)); return rv; } int sd_read_cap_16(struct sd_softc *sc, int flags) { struct scsi_read_cap_data_16 *rdcap; int rv; rdcap = dma_alloc(sizeof(*rdcap), (ISSET(flags, SCSI_NOSLEEP) ? PR_NOWAIT : PR_WAITOK) | PR_ZERO); if (rdcap == NULL) return -1; if (ISSET(sc->flags, SDF_DYING)) { rv = -1; goto done; } rv = scsi_read_cap_16(sc->sc_link, rdcap, flags); if (rv == 0) { if (_8btol(rdcap->addr) == 0) { rv = -1; goto done; } sc->params.disksize = _8btol(rdcap->addr) + 1ll; sc->params.secsize = _4btol(rdcap->length); if (ISSET(_2btol(rdcap->lowest_aligned), READ_CAP_16_TPE)) SET(sc->flags, SDF_THIN); else CLR(sc->flags, SDF_THIN); } done: dma_free(rdcap, sizeof(*rdcap)); return rv; } int sd_read_cap(struct sd_softc *sc, int flags) { int rv; CLR(flags, SCSI_IGNORE_ILLEGAL_REQUEST); /* * post-SPC2 (i.e. post-SCSI-3) devices can start with 16 byte * read capacity commands. Older devices start with the 10 byte * version and move up to the 16 byte version if the device * says it has more sectors than can be reported via the 10 byte * read capacity. */ if (SID_ANSII_REV(&sc->sc_link->inqdata) > SCSI_REV_SPC2) { rv = sd_read_cap_16(sc, flags); if (rv != 0) rv = sd_read_cap_10(sc, flags); } else { rv = sd_read_cap_10(sc, flags); if (rv == 0 && sc->params.disksize == 0x100000000ll) rv = sd_read_cap_16(sc, flags); } return rv; } int sd_thin_pages(struct sd_softc *sc, int flags) { struct scsi_vpd_hdr *pg; u_int8_t *pages; size_t len = 0; int i, rv, score = 0; pg = dma_alloc(sizeof(*pg), (ISSET(flags, SCSI_NOSLEEP) ? PR_NOWAIT : PR_WAITOK) | PR_ZERO); if (pg == NULL) return ENOMEM; if (ISSET(sc->flags, SDF_DYING)) { rv = ENXIO; goto done; } rv = scsi_inquire_vpd(sc->sc_link, pg, sizeof(*pg), SI_PG_SUPPORTED, flags); if (rv != 0) goto done; len = _2btol(pg->page_length); dma_free(pg, sizeof(*pg)); pg = dma_alloc(sizeof(*pg) + len, (ISSET(flags, SCSI_NOSLEEP) ? PR_NOWAIT : PR_WAITOK) | PR_ZERO); if (pg == NULL) return ENOMEM; if (ISSET(sc->flags, SDF_DYING)) { rv = ENXIO; goto done; } rv = scsi_inquire_vpd(sc->sc_link, pg, sizeof(*pg) + len, SI_PG_SUPPORTED, flags); if (rv != 0) goto done; pages = (u_int8_t *)(pg + 1); if (pages[0] != SI_PG_SUPPORTED) { rv = EIO; goto done; } for (i = 1; i < len; i++) { switch (pages[i]) { case SI_PG_DISK_LIMITS: case SI_PG_DISK_THIN: score++; break; } } if (score < 2) rv = EOPNOTSUPP; done: dma_free(pg, sizeof(*pg) + len); return rv; } int sd_vpd_block_limits(struct sd_softc *sc, int flags) { struct scsi_vpd_disk_limits *pg; int rv; pg = dma_alloc(sizeof(*pg), (ISSET(flags, SCSI_NOSLEEP) ? PR_NOWAIT : PR_WAITOK) | PR_ZERO); if (pg == NULL) return ENOMEM; if (ISSET(sc->flags, SDF_DYING)) { rv = ENXIO; goto done; } rv = scsi_inquire_vpd(sc->sc_link, pg, sizeof(*pg), SI_PG_DISK_LIMITS, flags); if (rv != 0) goto done; if (_2btol(pg->hdr.page_length) == SI_PG_DISK_LIMITS_LEN_THIN) { sc->params.unmap_sectors = _4btol(pg->max_unmap_lba_count); sc->params.unmap_descs = _4btol(pg->max_unmap_desc_count); } else rv = EOPNOTSUPP; done: dma_free(pg, sizeof(*pg)); return rv; } int sd_vpd_thin(struct sd_softc *sc, int flags) { struct scsi_vpd_disk_thin *pg; int rv; pg = dma_alloc(sizeof(*pg), (ISSET(flags, SCSI_NOSLEEP) ? PR_NOWAIT : PR_WAITOK) | PR_ZERO); if (pg == NULL) return ENOMEM; if (ISSET(sc->flags, SDF_DYING)) { rv = ENXIO; goto done; } rv = scsi_inquire_vpd(sc->sc_link, pg, sizeof(*pg), SI_PG_DISK_THIN, flags); if (rv != 0) goto done; #ifdef notyet if (ISSET(pg->flags, VPD_DISK_THIN_TPU)) sc->sc_delete = sd_unmap; else if (ISSET(pg->flags, VPD_DISK_THIN_TPWS)) { sc->sc_delete = sd_write_same_16; sc->params.unmap_descs = 1; /* WRITE SAME 16 only does one */ } else rv = EOPNOTSUPP; #endif /* notyet */ done: dma_free(pg, sizeof(*pg)); return rv; } int sd_thin_params(struct sd_softc *sc, int flags) { int rv; rv = sd_thin_pages(sc, flags); if (rv != 0) return rv; rv = sd_vpd_block_limits(sc, flags); if (rv != 0) return rv; rv = sd_vpd_thin(sc, flags); if (rv != 0) return rv; return 0; } /* * Fill out the disk parameter structure. Return 0 if the structure is correctly * filled in, otherwise return -1. * * The caller is responsible for clearing the SDEV_MEDIA_LOADED flag if the * structure cannot be completed. */ int sd_get_parms(struct sd_softc *sc, int flags) { struct disk_parms dp; struct scsi_link *link = sc->sc_link; union scsi_mode_sense_buf *buf = NULL; struct page_rigid_geometry *rigid = NULL; struct page_flex_geometry *flex = NULL; struct page_reduced_geometry *reduced = NULL; u_char *page0 = NULL; int big, err = 0; if (sd_read_cap(sc, flags) != 0) return -1; if (ISSET(sc->flags, SDF_THIN) && sd_thin_params(sc, flags) != 0) { /* we dont know the unmap limits, so we cant use thin shizz */ CLR(sc->flags, SDF_THIN); } /* * Work on a copy of the values initialized by sd_read_cap() and * sd_thin_params(). */ dp = sc->params; buf = dma_alloc(sizeof(*buf), PR_NOWAIT); if (buf == NULL) goto validate; if (ISSET(sc->flags, SDF_DYING)) goto die; /* * Ask for page 0 (vendor specific) mode sense data to find * READONLY info. The only thing USB devices will ask for. * * page0 == NULL is a valid situation. */ err = scsi_do_mode_sense(link, 0, buf, (void **)&page0, 1, flags | SCSI_SILENT, &big); if (ISSET(sc->flags, SDF_DYING)) goto die; if (err == 0) { if (big && buf->hdr_big.dev_spec & SMH_DSP_WRITE_PROT) SET(link->flags, SDEV_READONLY); else if (!big && buf->hdr.dev_spec & SMH_DSP_WRITE_PROT) SET(link->flags, SDEV_READONLY); else CLR(link->flags, SDEV_READONLY); } /* * Many UMASS devices choke when asked about their geometry. Most * don't have a meaningful geometry anyway, so just fake it if * sd_read_cap() worked. */ if (ISSET(link->flags, SDEV_UMASS) && dp.disksize > 0) goto validate; switch (link->inqdata.device & SID_TYPE) { case T_OPTICAL: /* No more information needed or available. */ break; case T_RDIRECT: /* T_RDIRECT supports only PAGE_REDUCED_GEOMETRY (6). */ err = scsi_do_mode_sense(link, PAGE_REDUCED_GEOMETRY, buf, (void **)&reduced, sizeof(*reduced), flags | SCSI_SILENT, &big); if (err == 0) { scsi_parse_blkdesc(link, buf, big, NULL, NULL, &dp.secsize); if (reduced != NULL) { if (dp.disksize == 0) dp.disksize = _5btol(reduced->sectors); if (dp.secsize == 0) dp.secsize = _2btol(reduced->bytes_s); } } break; default: /* * NOTE: Some devices leave off the last four bytes of * PAGE_RIGID_GEOMETRY and PAGE_FLEX_GEOMETRY mode sense pages. * The only information in those four bytes is RPM information * so accept the page. The extra bytes will be zero and RPM will * end up with the default value of 3600. */ err = 0; if (!ISSET(link->flags, SDEV_ATAPI) || !ISSET(link->flags, SDEV_REMOVABLE)) err = scsi_do_mode_sense(link, PAGE_RIGID_GEOMETRY, buf, (void **)&rigid, sizeof(*rigid) - 4, flags | SCSI_SILENT, &big); if (err == 0) { scsi_parse_blkdesc(link, buf, big, NULL, NULL, &dp.secsize); if (rigid != NULL) { dp.heads = rigid->nheads; dp.cyls = _3btol(rigid->ncyl); if (dp.heads * dp.cyls > 0) dp.sectors = dp.disksize / (dp.heads * dp.cyls); } } else { if (ISSET(sc->flags, SDF_DYING)) goto die; err = scsi_do_mode_sense(link, PAGE_FLEX_GEOMETRY, buf, (void **)&flex, sizeof(*flex) - 4, flags | SCSI_SILENT, &big); if (err == 0) { scsi_parse_blkdesc(link, buf, big, NULL, NULL, &dp.secsize); if (flex != NULL) { dp.sectors = flex->ph_sec_tr; dp.heads = flex->nheads; dp.cyls = _2btol(flex->ncyl); if (dp.secsize == 0) dp.secsize = _2btol(flex->bytes_s); if (dp.disksize == 0) dp.disksize = (u_int64_t)dp.cyls * dp.heads * dp.sectors; } } } break; } validate: if (buf) { dma_free(buf, sizeof(*buf)); buf = NULL; } if (dp.disksize == 0) return -1; /* * Restrict secsize values to powers of two between 512 and 64k. */ switch (dp.secsize) { case 0: dp.secsize = DEV_BSIZE; break; case 0x200: /* == 512, == DEV_BSIZE on all architectures. */ case 0x400: case 0x800: case 0x1000: case 0x2000: case 0x4000: case 0x8000: case 0x10000: break; default: SC_DEBUG(sc->sc_link, SDEV_DB1, ("sd_get_parms: bad secsize: %#x\n", dp.secsize)); return -1; } /* * XXX THINK ABOUT THIS!! Using values such that sectors * heads * * cyls is <= disk_size can lead to wasted space. We need a more * careful calculation/validation to make everything work out * optimally. */ if (dp.disksize > 0xffffffff && (dp.heads * dp.sectors) < 0xffff) { dp.heads = 511; dp.sectors = 255; dp.cyls = 0; } /* * Use standard geometry values for anything we still don't * know. */ if (dp.heads == 0) dp.heads = 255; if (dp.sectors == 0) dp.sectors = 63; if (dp.cyls == 0) { dp.cyls = dp.disksize / (dp.heads * dp.sectors); if (dp.cyls == 0) { /* Put everything into one cylinder. */ dp.heads = dp.cyls = 1; dp.sectors = dp.disksize; } } #ifdef SCSIDEBUG if (dp.disksize != (u_int64_t)dp.cyls * dp.heads * dp.sectors) { sc_print_addr(sc->sc_link); printf("disksize (%llu) != cyls (%u) * heads (%u) * " "sectors/track (%u) (%llu)\n", dp.disksize, dp.cyls, dp.heads, dp.sectors, (u_int64_t)dp.cyls * dp.heads * dp.sectors); } #endif /* SCSIDEBUG */ sc->params = dp; return 0; die: dma_free(buf, sizeof(*buf)); return -1; } int sd_flush(struct sd_softc *sc, int flags) { struct scsi_link *link; struct scsi_xfer *xs; struct scsi_synchronize_cache *cmd; int error; if (ISSET(sc->flags, SDF_DYING)) return ENXIO; link = sc->sc_link; if (ISSET(link->quirks, SDEV_NOSYNCCACHE)) return 0; /* * Issue a SYNCHRONIZE CACHE. Address 0, length 0 means "all remaining * blocks starting at address 0". Ignore ILLEGAL REQUEST in the event * that the command is not supported by the device. */ xs = scsi_xs_get(link, flags | SCSI_IGNORE_ILLEGAL_REQUEST); if (xs == NULL) { SC_DEBUG(link, SDEV_DB1, ("cache sync failed to get xs\n")); return EIO; } cmd = (struct scsi_synchronize_cache *)&xs->cmd; cmd->opcode = SYNCHRONIZE_CACHE; xs->cmdlen = sizeof(*cmd); xs->timeout = 100000; error = scsi_xs_sync(xs); scsi_xs_put(xs); if (error) SC_DEBUG(link, SDEV_DB1, ("cache sync failed\n")); else CLR(sc->flags, SDF_DIRTY); return error; }
28 27 1 2 4 2 2 2 2 9 4 2 3 3 2 3 21 7 1 6 2 5 1 3 18 18 1 2 1 3 1 2 6 5 1 6 15 18 18 3 14 1 4 8 7 4 1 5 14 3 3 3 3 55 1 6 4 4 4 1 6 11 3 2 9 3 2 6 1 2 5 4 1 1 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 /* $OpenBSD: sysv_msg.c,v 1.41 2023/04/11 00:45:09 jsg Exp $ */ /* $NetBSD: sysv_msg.c,v 1.19 1996/02/09 19:00:18 christos Exp $ */ /* * Copyright (c) 2009 Bret S. Lambert <blambert@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * Implementation of SVID messages * * Author: Daniel Boulet * * Copyright 1993 Daniel Boulet and RTMX Inc. * * This system call was implemented by Daniel Boulet under contract from RTMX. * * Redistribution and use in source forms, with and without modification, * are permitted provided that this entire comment appears intact. * * Redistribution in binary form may occur without any restrictions. * Obviously, it would be nice if you gave credit where credit is due * but requiring it would be too onerous. * * This software is provided ``AS IS'' without any warranties of any kind. */ #include <sys/param.h> #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/mount.h> #include <sys/msg.h> #include <sys/pool.h> #include <sys/proc.h> #include <sys/queue.h> #include <sys/syscallargs.h> #include <sys/sysctl.h> #include <sys/systm.h> struct que *que_create(key_t, struct ucred *, int); struct que *que_lookup(int); struct que *que_key_lookup(key_t); void que_wakewriters(void); void que_free(struct que *); struct msg *msg_create(struct que *); void msg_free(struct msg *); void msg_enqueue(struct que *, struct msg *, struct proc *); void msg_dequeue(struct que *, struct msg *, struct proc *); struct msg *msg_lookup(struct que *, int); int msg_copyin(struct msg *, const char *, size_t, struct proc *); int msg_copyout(struct msg *, char *, size_t *, struct proc *); struct pool sysvmsgpl; struct msginfo msginfo; TAILQ_HEAD(, que) msg_queues; int num_ques; int num_msgs; int sequence; int maxmsgs; void msginit(void) { msginfo.msgmax = MSGMAX; msginfo.msgmni = MSGMNI; msginfo.msgmnb = MSGMNB; msginfo.msgtql = MSGTQL; msginfo.msgssz = MSGSSZ; msginfo.msgseg = MSGSEG; pool_init(&sysvmsgpl, sizeof(struct msg), 0, IPL_NONE, PR_WAITOK, "sysvmsgpl", NULL); TAILQ_INIT(&msg_queues); num_ques = 0; num_msgs = 0; sequence = 1; maxmsgs = 0; } int sys_msgctl(struct proc *p, void *v, register_t *retval) { struct sys_msgctl_args /* { syscallarg(int) msqid; syscallarg(int) cmd; syscallarg(struct msqid_ds *) buf; } */ *uap = v; struct msqid_ds tmp, *umsq = SCARG(uap, buf); struct ucred *cred = p->p_ucred; struct que *que; int msqid = SCARG(uap, msqid); int cmd = SCARG(uap, cmd); int error; if ((que = que_lookup(msqid)) == NULL) return (EINVAL); QREF(que); switch (cmd) { case IPC_RMID: if ((error = ipcperm(cred, &que->msqid_ds.msg_perm, IPC_M))) goto out; TAILQ_REMOVE(&msg_queues, que, que_next); que->que_flags |= MSGQ_DYING; /* lose interest in the queue and wait for others to too */ if (--que->que_references > 0) { wakeup(que); tsleep_nsec(&que->que_references, PZERO, "msgqrm", INFSLP); } que_free(que); return (0); case IPC_SET: if ((error = ipcperm(cred, &que->msqid_ds.msg_perm, IPC_M))) goto out; if ((error = copyin(umsq, &tmp, sizeof(struct msqid_ds)))) goto out; /* only superuser can bump max bytes in queue */ if (tmp.msg_qbytes > que->msqid_ds.msg_qbytes && cred->cr_uid != 0) { error = EPERM; goto out; } /* restrict max bytes in queue to system limit */ if (tmp.msg_qbytes > msginfo.msgmnb) tmp.msg_qbytes = msginfo.msgmnb; /* can't reduce msg_bytes to 0 */ if (tmp.msg_qbytes == 0) { error = EINVAL; /* non-standard errno! */ goto out; } que->msqid_ds.msg_perm.uid = tmp.msg_perm.uid; que->msqid_ds.msg_perm.gid = tmp.msg_perm.gid; que->msqid_ds.msg_perm.mode = (que->msqid_ds.msg_perm.mode & ~0777) | (tmp.msg_perm.mode & 0777); que->msqid_ds.msg_qbytes = tmp.msg_qbytes; que->msqid_ds.msg_ctime = gettime(); break; case IPC_STAT: if ((error = ipcperm(cred, &que->msqid_ds.msg_perm, IPC_R))) goto out; error = copyout(&que->msqid_ds, umsq, sizeof(struct msqid_ds)); break; default: error = EINVAL; break; } out: QRELE(que); return (error); } int sys_msgget(struct proc *p, void *v, register_t *retval) { struct sys_msgget_args /* { syscallarg(key_t) key; syscallarg(int) msgflg; } */ *uap = v; struct ucred *cred = p->p_ucred; struct que *que; key_t key = SCARG(uap, key); int msgflg = SCARG(uap, msgflg); int error = 0; again: if (key != IPC_PRIVATE) { que = que_key_lookup(key); if (que) { if ((msgflg & IPC_CREAT) && (msgflg & IPC_EXCL)) return (EEXIST); if ((error = ipcperm(cred, &que->msqid_ds.msg_perm, msgflg & 0700))) return (error); goto found; } } /* don't create a new message queue if the caller doesn't want to */ if (key != IPC_PRIVATE && !(msgflg & IPC_CREAT)) return (ENOENT); /* enforce limits on the maximum number of message queues */ if (num_ques >= msginfo.msgmni) return (ENOSPC); /* * if que_create returns NULL, it means that a que with an identical * key was created while this process was sleeping, so start over */ if ((que = que_create(key, cred, msgflg & 0777)) == NULL) goto again; found: *retval = IXSEQ_TO_IPCID(que->que_ix, que->msqid_ds.msg_perm); return (error); } #define MSGQ_SPACE(q) ((q)->msqid_ds.msg_qbytes - (q)->msqid_ds.msg_cbytes) int sys_msgsnd(struct proc *p, void *v, register_t *retval) { struct sys_msgsnd_args /* { syscallarg(int) msqid; syscallarg(const void *) msgp; syscallarg(size_t) msgsz; syscallarg(int) msgflg; } */ *uap = v; struct ucred *cred = p->p_ucred; struct que *que; struct msg *msg; size_t msgsz = SCARG(uap, msgsz); int error; if ((que = que_lookup(SCARG(uap, msqid))) == NULL) return (EINVAL); if (msgsz > que->msqid_ds.msg_qbytes || msgsz > msginfo.msgmax) return (EINVAL); if ((error = ipcperm(cred, &que->msqid_ds.msg_perm, IPC_W))) return (error); QREF(que); while (MSGQ_SPACE(que) < msgsz || num_msgs >= msginfo.msgtql) { if (SCARG(uap, msgflg) & IPC_NOWAIT) { error = EAGAIN; goto out; } /* notify world that process may wedge here */ if (num_msgs >= msginfo.msgtql) maxmsgs = 1; que->que_flags |= MSGQ_WRITERS; if ((error = tsleep_nsec(que, PZERO|PCATCH, "msgwait", INFSLP))) goto out; if (que->que_flags & MSGQ_DYING) { error = EIDRM; goto out; } } /* if msg_create returns NULL, the queue is being removed */ if ((msg = msg_create(que)) == NULL) { error = EIDRM; goto out; } /* msg_copyin frees msg on error */ if ((error = msg_copyin(msg, (const char *)SCARG(uap, msgp), msgsz, p))) goto out; msg_enqueue(que, msg, p); if (que->que_flags & MSGQ_READERS) { que->que_flags &= ~MSGQ_READERS; wakeup(que); } if (que->que_flags & MSGQ_DYING) { error = EIDRM; wakeup(que); } out: QRELE(que); return (error); } int sys_msgrcv(struct proc *p, void *v, register_t *retval) { struct sys_msgrcv_args /* { syscallarg(int) msqid; syscallarg(void *) msgp; syscallarg(size_t) msgsz; syscallarg(long) msgtyp; syscallarg(int) msgflg; } */ *uap = v; struct ucred *cred = p->p_ucred; char *msgp = SCARG(uap, msgp); struct que *que; struct msg *msg; size_t msgsz = SCARG(uap, msgsz); long msgtyp = SCARG(uap, msgtyp); int error; if ((que = que_lookup(SCARG(uap, msqid))) == NULL) return (EINVAL); if ((error = ipcperm(cred, &que->msqid_ds.msg_perm, IPC_R))) return (error); QREF(que); /* msg_lookup handles matching; sleeping gets handled here */ while ((msg = msg_lookup(que, msgtyp)) == NULL) { if (SCARG(uap, msgflg) & IPC_NOWAIT) { error = ENOMSG; goto out; } que->que_flags |= MSGQ_READERS; if ((error = tsleep_nsec(que, PZERO|PCATCH, "msgwait", INFSLP))) goto out; /* make sure the queue still alive */ if (que->que_flags & MSGQ_DYING) { error = EIDRM; goto out; } } /* if msg_copyout fails, keep the message around so it isn't lost */ if ((error = msg_copyout(msg, msgp, &msgsz, p))) goto out; msg_dequeue(que, msg, p); msg_free(msg); if (que->que_flags & MSGQ_WRITERS) { que->que_flags &= ~MSGQ_WRITERS; wakeup(que); } /* ensure processes waiting on the global limit don't wedge */ if (maxmsgs) { maxmsgs = 0; que_wakewriters(); } *retval = msgsz; out: QRELE(que); return (error); } /* * que management functions */ struct que * que_create(key_t key, struct ucred *cred, int mode) { struct que *que, *que2; int nextix = 1; que = malloc(sizeof(*que), M_TEMP, M_WAIT|M_ZERO); /* if malloc slept, a queue with the same key may have been created */ if (que_key_lookup(key)) { free(que, M_TEMP, sizeof *que); return (NULL); } /* find next available "index" */ TAILQ_FOREACH(que2, &msg_queues, que_next) { if (nextix < que2->que_ix) break; nextix = que2->que_ix + 1; } que->que_ix = nextix; que->msqid_ds.msg_perm.key = key; que->msqid_ds.msg_perm.cuid = cred->cr_uid; que->msqid_ds.msg_perm.uid = cred->cr_uid; que->msqid_ds.msg_perm.cgid = cred->cr_gid; que->msqid_ds.msg_perm.gid = cred->cr_gid; que->msqid_ds.msg_perm.mode = mode & 0777; que->msqid_ds.msg_perm.seq = ++sequence & 0x7fff; que->msqid_ds.msg_qbytes = msginfo.msgmnb; que->msqid_ds.msg_ctime = gettime(); TAILQ_INIT(&que->que_msgs); /* keep queues in "index" order */ if (que2) TAILQ_INSERT_BEFORE(que2, que, que_next); else TAILQ_INSERT_TAIL(&msg_queues, que, que_next); num_ques++; return (que); } struct que * que_lookup(int id) { struct que *que; TAILQ_FOREACH(que, &msg_queues, que_next) if (que->que_ix == IPCID_TO_IX(id)) break; /* don't return queues marked for removal */ if (que && que->que_flags & MSGQ_DYING) return (NULL); return (que); } struct que * que_key_lookup(key_t key) { struct que *que; if (key == IPC_PRIVATE) return (NULL); TAILQ_FOREACH(que, &msg_queues, que_next) if (que->msqid_ds.msg_perm.key == key) break; /* don't return queues marked for removal */ if (que && que->que_flags & MSGQ_DYING) return (NULL); return (que); } void que_wakewriters(void) { struct que *que; TAILQ_FOREACH(que, &msg_queues, que_next) { if (que->que_flags & MSGQ_WRITERS) { que->que_flags &= ~MSGQ_WRITERS; wakeup(que); } } } void que_free(struct que *que) { struct msg *msg; #ifdef DIAGNOSTIC if (que->que_references > 0) panic("freeing message queue with active references"); #endif while ((msg = TAILQ_FIRST(&que->que_msgs))) { TAILQ_REMOVE(&que->que_msgs, msg, msg_next); msg_free(msg); } free(que, M_TEMP, sizeof *que); num_ques--; } /* * msg management functions */ struct msg * msg_create(struct que *que) { struct msg *msg; msg = pool_get(&sysvmsgpl, PR_WAITOK|PR_ZERO); /* if the queue has died during allocation, return NULL */ if (que->que_flags & MSGQ_DYING) { pool_put(&sysvmsgpl, msg); wakeup(que); return(NULL); } num_msgs++; return (msg); } struct msg * msg_lookup(struct que *que, int msgtyp) { struct msg *msg; /* * Three different matches are performed based on the value of msgtyp: * 1) msgtyp > 0 => match exactly * 2) msgtyp = 0 => match any * 3) msgtyp < 0 => match any up to absolute value of msgtyp */ TAILQ_FOREACH(msg, &que->que_msgs, msg_next) if (msgtyp == 0 || msgtyp == msg->msg_type || (msgtyp < 0 && -msgtyp <= msg->msg_type)) break; return (msg); } void msg_free(struct msg *msg) { m_freem(msg->msg_data); pool_put(&sysvmsgpl, msg); num_msgs--; } void msg_enqueue(struct que *que, struct msg *msg, struct proc *p) { que->msqid_ds.msg_cbytes += msg->msg_len; que->msqid_ds.msg_qnum++; que->msqid_ds.msg_lspid = p->p_p->ps_pid; que->msqid_ds.msg_stime = gettime(); TAILQ_INSERT_TAIL(&que->que_msgs, msg, msg_next); } void msg_dequeue(struct que *que, struct msg *msg, struct proc *p) { que->msqid_ds.msg_cbytes -= msg->msg_len; que->msqid_ds.msg_qnum--; que->msqid_ds.msg_lrpid = p->p_p->ps_pid; que->msqid_ds.msg_rtime = gettime(); TAILQ_REMOVE(&que->que_msgs, msg, msg_next); } /* * The actual I/O routines. A note concerning the layout of SysV msg buffers: * * The data to be copied is laid out as a single userspace buffer, with a * long preceding an opaque buffer of len bytes. The long value ends * up being the message type, which needs to be copied separately from * the buffer data, which is stored in mbufs. */ int msg_copyin(struct msg *msg, const char *ubuf, size_t len, struct proc *p) { struct mbuf **mm, *m; size_t xfer; int error; if (msg == NULL) panic ("msg NULL"); if ((error = copyin(ubuf, &msg->msg_type, sizeof(long)))) { msg_free(msg); return (error); } if (msg->msg_type < 1) { msg_free(msg); return (EINVAL); } ubuf += sizeof(long); msg->msg_len = 0; mm = &msg->msg_data; while (msg->msg_len < len) { m = m_get(M_WAIT, MT_DATA); if (len >= MINCLSIZE) { MCLGET(m, M_WAIT); xfer = min(len, MCLBYTES); } else { xfer = min(len, MLEN); } m->m_len = xfer; msg->msg_len += xfer; *mm = m; mm = &m->m_next; } for (m = msg->msg_data; m; m = m->m_next) { if ((error = copyin(ubuf, mtod(m, void *), m->m_len))) { msg_free(msg); return (error); } ubuf += m->m_len; } return (0); } int msg_copyout(struct msg *msg, char *ubuf, size_t *len, struct proc *p) { struct mbuf *m; size_t xfer; int error; #ifdef DIAGNOSTIC if (msg->msg_len > MSGMAX) panic("SysV message longer than MSGMAX"); #endif /* silently truncate messages too large for user buffer */ xfer = min(*len, msg->msg_len); if ((error = copyout(&msg->msg_type, ubuf, sizeof(long)))) return (error); ubuf += sizeof(long); *len = xfer; for (m = msg->msg_data; m; m = m->m_next) { if ((error = copyout(mtod(m, void *), ubuf, m->m_len))) return (error); ubuf += m->m_len; } return (0); } int sysctl_sysvmsg(int *name, u_int namelen, void *where, size_t *sizep) { struct msg_sysctl_info *info; struct que *que; size_t infolen, infolen0; int error; switch (*name) { case KERN_SYSVIPC_MSG_INFO: if (namelen != 1) return (ENOTDIR); /* * The userland ipcs(1) utility expects to be able * to iterate over at least msginfo.msgmni queues, * even if those queues don't exist. This is an * artifact of the previous implementation of * message queues; for now, emulate this behavior * until a more thorough fix can be made. */ infolen0 = sizeof(msginfo) + msginfo.msgmni * sizeof(struct msqid_ds); if (where == NULL) { *sizep = infolen0; return (0); } /* * More special-casing due to previous implementation: * if the caller just wants the msginfo struct, then * sizep will point to the value sizeof(struct msginfo). * In that case, only copy out the msginfo struct to * the caller. */ if (*sizep == sizeof(struct msginfo)) return (copyout(&msginfo, where, sizeof(msginfo))); info = malloc(infolen0, M_TEMP, M_WAIT|M_ZERO); /* if the malloc slept, this may have changed */ infolen = sizeof(msginfo) + msginfo.msgmni * sizeof(struct msqid_ds); if (*sizep < infolen) { free(info, M_TEMP, infolen0); return (ENOMEM); } memcpy(&info->msginfo, &msginfo, sizeof(struct msginfo)); /* * Special case #3: the previous array-based implementation * exported the array indices and userland has come to rely * upon these indices, so keep behavior consistent. */ TAILQ_FOREACH(que, &msg_queues, que_next) memcpy(&info->msgids[que->que_ix], &que->msqid_ds, sizeof(struct msqid_ds)); error = copyout(info, where, infolen); free(info, M_TEMP, infolen0); return (error); default: return (EINVAL); } }
1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 /* $OpenBSD: ugen.c,v 1.118 2024/05/23 03:21:09 jsg Exp $ */ /* $NetBSD: ugen.c,v 1.63 2002/11/26 18:49:48 christos Exp $ */ /* $FreeBSD: src/sys/dev/usb/ugen.c,v 1.26 1999/11/17 22:33:41 n_hibma Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Lennart Augustsson (lennart@augustsson.net) at * Carlstedt Research & Technology. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/device.h> #include <sys/ioctl.h> #include <sys/conf.h> #include <sys/tty.h> #include <sys/fcntl.h> #include <sys/selinfo.h> #include <sys/vnode.h> #include <machine/bus.h> #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> #include <dev/usb/usbdi_util.h> #ifdef UGEN_DEBUG #define DPRINTF(x) do { if (ugendebug) printf x; } while (0) #define DPRINTFN(n,x) do { if (ugendebug>(n)) printf x; } while (0) int ugendebug = 0; #else #define DPRINTF(x) #define DPRINTFN(n,x) #endif #define UGEN_CHUNK 128 /* chunk size for read */ #define UGEN_IBSIZE 1020 /* buffer size */ #define UGEN_BBSIZE 1024 #define UGEN_NISOFRAMES 500 /* 0.5 seconds worth */ #define UGEN_NISOREQS 6 /* number of outstanding xfer requests */ #define UGEN_NISORFRMS 4 /* number of frames (milliseconds) per req */ struct ugen_endpoint { struct ugen_softc *sc; usb_endpoint_descriptor_t *edesc; struct usbd_interface *iface; int state; #define UGEN_ASLP 0x02 /* waiting for data */ #define UGEN_SHORT_OK 0x04 /* short xfers are OK */ struct usbd_pipe *pipeh; struct clist q; struct selinfo rsel; u_char *ibuf; /* start of buffer (circular for isoc) */ size_t ibuflen; u_char *fill; /* location for input (isoc) */ u_char *limit; /* end of circular buffer (isoc) */ u_char *cur; /* current read location (isoc) */ u_int32_t timeout; struct isoreq { struct ugen_endpoint *sce; struct usbd_xfer *xfer; void *dmabuf; u_int16_t sizes[UGEN_NISORFRMS]; } isoreqs[UGEN_NISOREQS]; }; struct ugen_softc { struct device sc_dev; /* base device */ struct usbd_device *sc_udev; char sc_is_open[USB_MAX_ENDPOINTS]; struct ugen_endpoint sc_endpoints[USB_MAX_ENDPOINTS][2]; #define OUT 0 #define IN 1 int sc_refcnt; u_char sc_secondary; }; void ugenintr(struct usbd_xfer *, void *, usbd_status); void ugen_isoc_rintr(struct usbd_xfer *, void *, usbd_status); int ugen_do_read(struct ugen_softc *, int, struct uio *, int); int ugen_do_write(struct ugen_softc *, int, struct uio *, int); int ugen_do_ioctl(struct ugen_softc *, int, u_long, caddr_t, int, struct proc *); int ugen_do_close(struct ugen_softc *, int, int); int ugen_set_config(struct ugen_softc *, int); int ugen_set_interface(struct ugen_softc *, int, int); int ugen_get_alt_index(struct ugen_softc *, int); void ugen_clear_iface_eps(struct ugen_softc *, struct usbd_interface *); #define UGENUNIT(n) ((minor(n) >> 4) & 0xf) #define UGENENDPOINT(n) (minor(n) & 0xf) #define UGENDEV(u, e) (makedev(0, ((u) << 4) | (e))) int ugen_match(struct device *, void *, void *); void ugen_attach(struct device *, struct device *, void *); int ugen_detach(struct device *, int); struct cfdriver ugen_cd = { NULL, "ugen", DV_DULL }; const struct cfattach ugen_ca = { sizeof(struct ugen_softc), ugen_match, ugen_attach, ugen_detach }; int ugen_match(struct device *parent, void *match, void *aux) { struct usb_attach_arg *uaa = aux; if (uaa->usegeneric) { return (UMATCH_GENERIC); } else return (UMATCH_NONE); } void ugen_attach(struct device *parent, struct device *self, void *aux) { struct ugen_softc *sc = (struct ugen_softc *)self; struct usb_attach_arg *uaa = aux; struct usbd_device *udev; usbd_status err; int conf; sc->sc_udev = udev = uaa->device; if (usbd_get_devcnt(udev) > 0) sc->sc_secondary = 1; if (!sc->sc_secondary) { /* First set configuration index 0, the default one for ugen. */ err = usbd_set_config_index(udev, 0, 0); if (err) { printf("%s: setting configuration index 0 failed\n", sc->sc_dev.dv_xname); usbd_deactivate(sc->sc_udev); return; } } conf = usbd_get_config_descriptor(udev)->bConfigurationValue; /* Set up all the local state for this configuration. */ err = ugen_set_config(sc, conf); if (err) { printf("%s: setting configuration %d failed\n", sc->sc_dev.dv_xname, conf); usbd_deactivate(sc->sc_udev); return; } } int ugen_set_config(struct ugen_softc *sc, int configno) { struct usbd_device *dev = sc->sc_udev; usb_config_descriptor_t *cdesc; usb_interface_descriptor_t *id; struct usbd_interface *iface; usb_endpoint_descriptor_t *ed; struct ugen_endpoint *sce; int ifaceno, endptno, endpt; int err, dir; DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n", sc->sc_dev.dv_xname, configno, sc)); /* * We start at 1, not 0, because we don't care whether the * control endpoint is open or not. It is always present. */ for (endptno = 1; endptno < USB_MAX_ENDPOINTS; endptno++) if (sc->sc_is_open[endptno]) { DPRINTFN(1, ("ugen_set_config: %s - endpoint %d is open\n", sc->sc_dev.dv_xname, endptno)); return (USBD_IN_USE); } /* Avoid setting the current value. */ cdesc = usbd_get_config_descriptor(dev); if (cdesc == NULL || cdesc->bConfigurationValue != configno) { if (sc->sc_secondary) { printf("%s: secondary, not changing config to %d\n", __func__, configno); return (USBD_IN_USE); } else { err = usbd_set_config_no(dev, configno, 1); if (err) return (err); cdesc = usbd_get_config_descriptor(dev); if (cdesc == NULL || cdesc->bConfigurationValue != configno) return (USBD_INVAL); } } memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints); for (ifaceno = 0; ifaceno < cdesc->bNumInterfaces; ifaceno++) { DPRINTFN(1,("ugen_set_config: ifaceno %d\n", ifaceno)); if (usbd_iface_claimed(sc->sc_udev, ifaceno)) { DPRINTF(("%s: iface %d not available\n", __func__, ifaceno)); continue; } err = usbd_device2interface_handle(dev, ifaceno, &iface); if (err) return (err); id = usbd_get_interface_descriptor(iface); for (endptno = 0; endptno < id->bNumEndpoints; endptno++) { ed = usbd_interface2endpoint_descriptor(iface,endptno); endpt = ed->bEndpointAddress; dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT; sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir]; DPRINTFN(1,("ugen_set_config: endptno %d, endpt=0x%02x" "(%d,%d), sce=%p\n", endptno, endpt, UE_GET_ADDR(endpt), UE_GET_DIR(endpt), sce)); sce->sc = sc; sce->edesc = ed; sce->iface = iface; } } return (0); } int ugenopen(dev_t dev, int flag, int mode, struct proc *p) { struct ugen_softc *sc; int unit = UGENUNIT(dev); int endpt = UGENENDPOINT(dev); usb_endpoint_descriptor_t *edesc; struct ugen_endpoint *sce; int dir, isize; usbd_status err; struct usbd_xfer *xfer; void *buf; int i, j; if (unit >= ugen_cd.cd_ndevs) return (ENXIO); sc = ugen_cd.cd_devs[unit]; if (sc == NULL) return (ENXIO); DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n", flag, mode, unit, endpt)); if (sc == NULL || usbd_is_dying(sc->sc_udev)) return (ENXIO); if (sc->sc_is_open[endpt]) return (EBUSY); if (endpt == USB_CONTROL_ENDPOINT) { sc->sc_is_open[USB_CONTROL_ENDPOINT] = 1; return (0); } /* Make sure there are pipes for all directions. */ for (dir = OUT; dir <= IN; dir++) { if (flag & (dir == OUT ? FWRITE : FREAD)) { sce = &sc->sc_endpoints[endpt][dir]; if (sce == 0 || sce->edesc == 0) return (ENXIO); } } /* Actually open the pipes. */ /* XXX Should back out properly if it fails. */ for (dir = OUT; dir <= IN; dir++) { if (!(flag & (dir == OUT ? FWRITE : FREAD))) continue; sce = &sc->sc_endpoints[endpt][dir]; sce->state = 0; sce->timeout = USBD_NO_TIMEOUT; DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n", sc, endpt, dir, sce)); edesc = sce->edesc; /* Clear device endpoint toggle. */ ugen_clear_iface_eps(sc, sce->iface); switch (UE_GET_XFERTYPE(edesc->bmAttributes)) { case UE_INTERRUPT: if (dir == OUT) { err = usbd_open_pipe(sce->iface, edesc->bEndpointAddress, 0, &sce->pipeh); if (err) return (EIO); break; } isize = UGETW(edesc->wMaxPacketSize); if (isize == 0) /* shouldn't happen */ return (EINVAL); sce->ibuflen = isize; sce->ibuf = malloc(sce->ibuflen, M_USBDEV, M_WAITOK); DPRINTFN(5, ("ugenopen: intr endpt=%d,isize=%d\n", endpt, isize)); clalloc(&sce->q, UGEN_IBSIZE, 0); err = usbd_open_pipe_intr(sce->iface, edesc->bEndpointAddress, USBD_SHORT_XFER_OK, &sce->pipeh, sce, sce->ibuf, isize, ugenintr, USBD_DEFAULT_INTERVAL); if (err) { free(sce->ibuf, M_USBDEV, sce->ibuflen); clfree(&sce->q); return (EIO); } /* Clear HC endpoint toggle. */ usbd_clear_endpoint_toggle(sce->pipeh); DPRINTFN(5, ("ugenopen: interrupt open done\n")); break; case UE_BULK: err = usbd_open_pipe(sce->iface, edesc->bEndpointAddress, 0, &sce->pipeh); if (err) return (EIO); /* Clear HC endpoint toggle. */ usbd_clear_endpoint_toggle(sce->pipeh); break; case UE_ISOCHRONOUS: if (dir == OUT) return (EINVAL); isize = UGETW(edesc->wMaxPacketSize); if (isize == 0) /* shouldn't happen */ return (EINVAL); sce->ibuflen = isize * UGEN_NISOFRAMES; sce->ibuf = mallocarray(isize, UGEN_NISOFRAMES, M_USBDEV, M_WAITOK); sce->cur = sce->fill = sce->ibuf; sce->limit = sce->ibuf + isize * UGEN_NISOFRAMES; DPRINTFN(5, ("ugenopen: isoc endpt=%d, isize=%d\n", endpt, isize)); err = usbd_open_pipe(sce->iface, edesc->bEndpointAddress, 0, &sce->pipeh); if (err) { free(sce->ibuf, M_USBDEV, sce->ibuflen); return (EIO); } for(i = 0; i < UGEN_NISOREQS; ++i) { sce->isoreqs[i].sce = sce; xfer = usbd_alloc_xfer(sc->sc_udev); if (xfer == 0) goto bad; sce->isoreqs[i].xfer = xfer; buf = usbd_alloc_buffer (xfer, isize * UGEN_NISORFRMS); if (buf == 0) { i++; goto bad; } sce->isoreqs[i].dmabuf = buf; for(j = 0; j < UGEN_NISORFRMS; ++j) sce->isoreqs[i].sizes[j] = isize; usbd_setup_isoc_xfer(xfer, sce->pipeh, &sce->isoreqs[i], sce->isoreqs[i].sizes, UGEN_NISORFRMS, USBD_NO_COPY | USBD_SHORT_XFER_OK, ugen_isoc_rintr); (void)usbd_transfer(xfer); } DPRINTFN(5, ("ugenopen: isoc open done\n")); break; bad: while (--i >= 0) /* implicit buffer free */ usbd_free_xfer(sce->isoreqs[i].xfer); return (ENOMEM); case UE_CONTROL: sce->timeout = USBD_DEFAULT_TIMEOUT; return (EINVAL); } } sc->sc_is_open[endpt] = 1; return (0); } int ugenclose(dev_t dev, int flag, int mode, struct proc *p) { struct ugen_softc *sc = ugen_cd.cd_devs[UGENUNIT(dev)]; int endpt = UGENENDPOINT(dev); int error; if (sc == NULL || usbd_is_dying(sc->sc_udev)) return (EIO); DPRINTFN(5, ("ugenclose: flag=%d, mode=%d, unit=%d, endpt=%d\n", flag, mode, UGENUNIT(dev), endpt)); sc->sc_refcnt++; error = ugen_do_close(sc, endpt, flag); if (--sc->sc_refcnt < 0) usb_detach_wakeup(&sc->sc_dev); return (error); } int ugen_do_close(struct ugen_softc *sc, int endpt, int flag) { struct ugen_endpoint *sce; int dir, i; #ifdef DIAGNOSTIC if (!sc->sc_is_open[endpt]) { printf("ugenclose: not open\n"); return (EINVAL); } #endif if (endpt == USB_CONTROL_ENDPOINT) { DPRINTFN(5, ("ugenclose: close control\n")); sc->sc_is_open[endpt] = 0; return (0); } for (dir = OUT; dir <= IN; dir++) { if (!(flag & (dir == OUT ? FWRITE : FREAD))) continue; sce = &sc->sc_endpoints[endpt][dir]; if (sce == NULL || sce->pipeh == NULL) continue; DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n", endpt, dir, sce)); usbd_close_pipe(sce->pipeh); sce->pipeh = NULL; switch (UE_GET_XFERTYPE(sce->edesc->bmAttributes)) { case UE_INTERRUPT: ndflush(&sce->q, sce->q.c_cc); clfree(&sce->q); break; case UE_ISOCHRONOUS: for (i = 0; i < UGEN_NISOREQS; ++i) usbd_free_xfer(sce->isoreqs[i].xfer); default: break; } if (sce->ibuf != NULL) { free(sce->ibuf, M_USBDEV, sce->ibuflen); sce->ibuf = NULL; } } sc->sc_is_open[endpt] = 0; return (0); } int ugen_do_read(struct ugen_softc *sc, int endpt, struct uio *uio, int flag) { struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][IN]; u_int32_t tn; size_t n; char buf[UGEN_BBSIZE]; struct usbd_xfer *xfer; usbd_status err; int s; int flags, error = 0; u_char buffer[UGEN_CHUNK]; DPRINTFN(5, ("%s: ugenread: %d\n", sc->sc_dev.dv_xname, endpt)); if (usbd_is_dying(sc->sc_udev)) return (EIO); if (endpt == USB_CONTROL_ENDPOINT) return (ENODEV); #ifdef DIAGNOSTIC if (sce->edesc == NULL) { printf("ugenread: no edesc\n"); return (EIO); } if (sce->pipeh == NULL) { printf("ugenread: no pipe\n"); return (EIO); } #endif switch (UE_GET_XFERTYPE(sce->edesc->bmAttributes)) { case UE_INTERRUPT: /* Block until activity occurred. */ s = splusb(); while (sce->q.c_cc == 0) { if (flag & IO_NDELAY) { splx(s); return (EWOULDBLOCK); } sce->state |= UGEN_ASLP; DPRINTFN(5, ("ugenread: sleep on %p\n", sce)); error = tsleep_nsec(sce, PZERO | PCATCH, "ugenrintr", MSEC_TO_NSEC(sce->timeout)); sce->state &= ~UGEN_ASLP; DPRINTFN(5, ("ugenread: woke, error=%d\n", error)); if (usbd_is_dying(sc->sc_udev)) error = EIO; if (error == EWOULDBLOCK) { /* timeout, return 0 */ error = 0; break; } if (error) break; } splx(s); /* Transfer as many chunks as possible. */ while (sce->q.c_cc > 0 && uio->uio_resid > 0 && !error) { n = ulmin(sce->q.c_cc, uio->uio_resid); if (n > sizeof(buffer)) n = sizeof(buffer); /* Remove a small chunk from the input queue. */ q_to_b(&sce->q, buffer, n); DPRINTFN(5, ("ugenread: got %zu chars\n", n)); /* Copy the data to the user process. */ error = uiomove(buffer, n, uio); if (error) break; } break; case UE_BULK: xfer = usbd_alloc_xfer(sc->sc_udev); if (xfer == 0) return (ENOMEM); flags = USBD_SYNCHRONOUS; if (sce->state & UGEN_SHORT_OK) flags |= USBD_SHORT_XFER_OK; if (sce->timeout == 0) flags |= USBD_CATCH; while ((n = ulmin(UGEN_BBSIZE, uio->uio_resid)) != 0) { DPRINTFN(1, ("ugenread: start transfer %zu bytes\n",n)); usbd_setup_xfer(xfer, sce->pipeh, 0, buf, n, flags, sce->timeout, NULL); err = usbd_transfer(xfer); if (err) { usbd_clear_endpoint_stall(sce->pipeh); if (err == USBD_INTERRUPTED) error = EINTR; else if (err == USBD_TIMEOUT) error = ETIMEDOUT; else error = EIO; break; } usbd_get_xfer_status(xfer, NULL, NULL, &tn, NULL); DPRINTFN(1, ("ugenread: got %u bytes\n", tn)); error = uiomove(buf, tn, uio); if (error || tn < n) break; } usbd_free_xfer(xfer); break; case UE_ISOCHRONOUS: s = splusb(); while (sce->cur == sce->fill) { if (flag & IO_NDELAY) { splx(s); return (EWOULDBLOCK); } sce->state |= UGEN_ASLP; DPRINTFN(5, ("ugenread: sleep on %p\n", sce)); error = tsleep_nsec(sce, PZERO | PCATCH, "ugenriso", MSEC_TO_NSEC(sce->timeout)); sce->state &= ~UGEN_ASLP; DPRINTFN(5, ("ugenread: woke, error=%d\n", error)); if (usbd_is_dying(sc->sc_udev)) error = EIO; if (error == EWOULDBLOCK) { /* timeout, return 0 */ error = 0; break; } if (error) break; } while (sce->cur != sce->fill && uio->uio_resid > 0 && !error) { if(sce->fill > sce->cur) n = ulmin(sce->fill - sce->cur, uio->uio_resid); else n = ulmin(sce->limit - sce->cur, uio->uio_resid); DPRINTFN(5, ("ugenread: isoc got %zu chars\n", n)); /* Copy the data to the user process. */ error = uiomove(sce->cur, n, uio); if (error) break; sce->cur += n; if(sce->cur >= sce->limit) sce->cur = sce->ibuf; } splx(s); break; default: return (ENXIO); } return (error); } int ugenread(dev_t dev, struct uio *uio, int flag) { int endpt = UGENENDPOINT(dev); struct ugen_softc *sc; int error; sc = ugen_cd.cd_devs[UGENUNIT(dev)]; sc->sc_refcnt++; error = ugen_do_read(sc, endpt, uio, flag); if (--sc->sc_refcnt < 0) usb_detach_wakeup(&sc->sc_dev); return (error); } int ugen_do_write(struct ugen_softc *sc, int endpt, struct uio *uio, int flag) { struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][OUT]; size_t n; int flags, error = 0; char buf[UGEN_BBSIZE]; struct usbd_xfer *xfer; usbd_status err; DPRINTFN(5, ("%s: ugenwrite: %d\n", sc->sc_dev.dv_xname, endpt)); if (usbd_is_dying(sc->sc_udev)) return (EIO); if (endpt == USB_CONTROL_ENDPOINT) return (ENODEV); #ifdef DIAGNOSTIC if (sce->edesc == NULL) { printf("ugenwrite: no edesc\n"); return (EIO); } if (sce->pipeh == NULL) { printf("ugenwrite: no pipe\n"); return (EIO); } #endif flags = USBD_SYNCHRONOUS; if (sce->timeout == 0) flags |= USBD_CATCH; switch (UE_GET_XFERTYPE(sce->edesc->bmAttributes)) { case UE_BULK: xfer = usbd_alloc_xfer(sc->sc_udev); if (xfer == 0) return (EIO); while ((n = ulmin(UGEN_BBSIZE, uio->uio_resid)) != 0) { error = uiomove(buf, n, uio); if (error) break; DPRINTFN(1, ("ugenwrite: transfer %zu bytes\n", n)); usbd_setup_xfer(xfer, sce->pipeh, 0, buf, n, flags, sce->timeout, NULL); err = usbd_transfer(xfer); if (err) { usbd_clear_endpoint_stall(sce->pipeh); if (err == USBD_INTERRUPTED) error = EINTR; else if (err == USBD_TIMEOUT) error = ETIMEDOUT; else error = EIO; break; } } usbd_free_xfer(xfer); break; case UE_INTERRUPT: xfer = usbd_alloc_xfer(sc->sc_udev); if (xfer == 0) return (EIO); while ((n = ulmin(UGETW(sce->edesc->wMaxPacketSize), uio->uio_resid)) != 0) { error = uiomove(buf, n, uio); if (error) break; DPRINTFN(1, ("ugenwrite: transfer %zu bytes\n", n)); usbd_setup_xfer(xfer, sce->pipeh, 0, buf, n, flags, sce->timeout, NULL); err = usbd_transfer(xfer); if (err) { usbd_clear_endpoint_stall(sce->pipeh); if (err == USBD_INTERRUPTED) error = EINTR; else if (err == USBD_TIMEOUT) error = ETIMEDOUT; else error = EIO; break; } } usbd_free_xfer(xfer); break; default: return (ENXIO); } return (error); } int ugenwrite(dev_t dev, struct uio *uio, int flag) { int endpt = UGENENDPOINT(dev); struct ugen_softc *sc; int error; sc = ugen_cd.cd_devs[UGENUNIT(dev)]; sc->sc_refcnt++; error = ugen_do_write(sc, endpt, uio, flag); if (--sc->sc_refcnt < 0) usb_detach_wakeup(&sc->sc_dev); return (error); } int ugen_detach(struct device *self, int flags) { struct ugen_softc *sc = (struct ugen_softc *)self; struct ugen_endpoint *sce; int i, dir, endptno; int s, maj, mn; DPRINTF(("ugen_detach: sc=%p flags=%d\n", sc, flags)); /* Abort all pipes. Causes processes waiting for transfer to wake. */ for (i = 0; i < USB_MAX_ENDPOINTS; i++) { for (dir = OUT; dir <= IN; dir++) { sce = &sc->sc_endpoints[i][dir]; if (sce && sce->pipeh) usbd_abort_pipe(sce->pipeh); } } s = splusb(); if (--sc->sc_refcnt >= 0) { /* Wake everyone */ for (i = 0; i < USB_MAX_ENDPOINTS; i++) wakeup(&sc->sc_endpoints[i][IN]); /* Wait for processes to go away. */ usb_detach_wait(&sc->sc_dev); } splx(s); /* locate the major number */ for (maj = 0; maj < nchrdev; maj++) if (cdevsw[maj].d_open == ugenopen) break; /* Nuke the vnodes for any open instances (calls close). */ mn = self->dv_unit * USB_MAX_ENDPOINTS; vdevgone(maj, mn, mn + USB_MAX_ENDPOINTS - 1, VCHR); for (endptno = 0; endptno < USB_MAX_ENDPOINTS; endptno++) { if (sc->sc_is_open[endptno]) ugen_do_close(sc, endptno, FREAD|FWRITE); /* ugenkqfilter() always uses IN. */ sce = &sc->sc_endpoints[endptno][IN]; klist_invalidate(&sce->rsel.si_note); } return (0); } void ugenintr(struct usbd_xfer *xfer, void *addr, usbd_status status) { struct ugen_endpoint *sce = addr; /*struct ugen_softc *sc = sce->sc;*/ u_int32_t count; u_char *ibuf; if (status == USBD_CANCELLED) return; if (status != USBD_NORMAL_COMPLETION) { DPRINTF(("ugenintr: status=%d\n", status)); if (status == USBD_STALLED) usbd_clear_endpoint_stall_async(sce->pipeh); return; } usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); ibuf = sce->ibuf; DPRINTFN(5, ("ugenintr: xfer=%p status=%d count=%d\n", xfer, status, count)); DPRINTFN(5, (" data = %02x %02x %02x\n", ibuf[0], ibuf[1], ibuf[2])); (void)b_to_q(ibuf, count, &sce->q); if (sce->state & UGEN_ASLP) { sce->state &= ~UGEN_ASLP; DPRINTFN(5, ("ugen_intr: waking %p\n", sce)); wakeup(sce); } selwakeup(&sce->rsel); } void ugen_isoc_rintr(struct usbd_xfer *xfer, void *addr, usbd_status status) { struct isoreq *req = addr; struct ugen_endpoint *sce = req->sce; u_int32_t count, n; int i, isize; /* Return if we are aborting. */ if (status == USBD_CANCELLED) return; usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); DPRINTFN(5,("%s: xfer %ld, count=%d\n", __func__, req - sce->isoreqs, count)); /* throw away oldest input if the buffer is full */ if(sce->fill < sce->cur && sce->cur <= sce->fill + count) { sce->cur += count; if(sce->cur >= sce->limit) sce->cur = sce->ibuf + (sce->limit - sce->cur); DPRINTFN(5, ("%s: throwing away %d bytes\n", __func__, count)); } isize = UGETW(sce->edesc->wMaxPacketSize); for (i = 0; i < UGEN_NISORFRMS; i++) { u_int32_t actlen = req->sizes[i]; char const *buf = (char const *)req->dmabuf + isize * i; /* copy data to buffer */ while (actlen > 0) { n = min(actlen, sce->limit - sce->fill); memcpy(sce->fill, buf, n); buf += n; actlen -= n; sce->fill += n; if(sce->fill == sce->limit) sce->fill = sce->ibuf; } /* setup size for next transfer */ req->sizes[i] = isize; } usbd_setup_isoc_xfer(xfer, sce->pipeh, req, req->sizes, UGEN_NISORFRMS, USBD_NO_COPY | USBD_SHORT_XFER_OK, ugen_isoc_rintr); (void)usbd_transfer(xfer); if (sce->state & UGEN_ASLP) { sce->state &= ~UGEN_ASLP; DPRINTFN(5, ("ugen_isoc_rintr: waking %p\n", sce)); wakeup(sce); } selwakeup(&sce->rsel); } int ugen_set_interface(struct ugen_softc *sc, int ifaceno, int altno) { struct usbd_interface *iface; usb_config_descriptor_t *cdesc; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; struct ugen_endpoint *sce; uint8_t endptno, endpt; int dir, err; DPRINTFN(15, ("ugen_set_interface %d %d\n", ifaceno, altno)); cdesc = usbd_get_config_descriptor(sc->sc_udev); if (ifaceno < 0 || ifaceno >= cdesc->bNumInterfaces || usbd_iface_claimed(sc->sc_udev, ifaceno)) return (USBD_INVAL); err = usbd_device2interface_handle(sc->sc_udev, ifaceno, &iface); if (err) return (err); id = usbd_get_interface_descriptor(iface); for (endptno = 0; endptno < id->bNumEndpoints; endptno++) { ed = usbd_interface2endpoint_descriptor(iface,endptno); endpt = ed->bEndpointAddress; dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT; sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir]; sce->sc = 0; sce->edesc = 0; sce->iface = 0; } /* Try to change setting, if this fails put back the descriptors. */ err = usbd_set_interface(iface, altno); id = usbd_get_interface_descriptor(iface); for (endptno = 0; endptno < id->bNumEndpoints; endptno++) { ed = usbd_interface2endpoint_descriptor(iface,endptno); endpt = ed->bEndpointAddress; dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT; sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir]; sce->sc = sc; sce->edesc = ed; sce->iface = iface; } return (err); } int ugen_get_alt_index(struct ugen_softc *sc, int ifaceno) { struct usbd_interface *iface; usbd_status err; err = usbd_device2interface_handle(sc->sc_udev, ifaceno, &iface); if (err) return (-1); return (usbd_get_interface_altindex(iface)); } int ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd, caddr_t addr, int flag, struct proc *p) { struct ugen_endpoint *sce; int err, cdesc_len; struct usbd_interface *iface; struct usb_config_desc *cd; usb_config_descriptor_t *cdesc; struct usb_interface_desc *id; usb_interface_descriptor_t *idesc; struct usb_endpoint_desc *ed; usb_endpoint_descriptor_t *edesc; struct usb_alt_interface *ai; u_int8_t conf, alt; DPRINTFN(5, ("ugenioctl: cmd=%08lx\n", cmd)); if (usbd_is_dying(sc->sc_udev)) return (EIO); switch (cmd) { case FIONBIO: /* All handled in the upper FS layer. */ return (0); case USB_SET_SHORT_XFER: if (endpt == USB_CONTROL_ENDPOINT) return (EINVAL); /* This flag only affects read */ sce = &sc->sc_endpoints[endpt][IN]; if (sce == NULL || sce->pipeh == NULL) return (EINVAL); if (*(int *)addr) sce->state |= UGEN_SHORT_OK; else sce->state &= ~UGEN_SHORT_OK; return (0); case USB_SET_TIMEOUT: sce = &sc->sc_endpoints[endpt][IN]; if (sce == NULL) return (EINVAL); sce->timeout = *(int *)addr; sce = &sc->sc_endpoints[endpt][OUT]; if (sce == NULL) return (EINVAL); sce->timeout = *(int *)addr; return (0); default: break; } if (endpt != USB_CONTROL_ENDPOINT) return (EINVAL); switch (cmd) { #ifdef UGEN_DEBUG case USB_SETDEBUG: ugendebug = *(int *)addr; break; #endif case USB_GET_CONFIG: err = usbd_get_config(sc->sc_udev, &conf); if (err) return (EIO); *(int *)addr = conf; break; case USB_SET_CONFIG: if (!(flag & FWRITE)) return (EPERM); err = ugen_set_config(sc, *(int *)addr); switch (err) { case USBD_NORMAL_COMPLETION: break; case USBD_IN_USE: return (EBUSY); default: return (EIO); } break; case USB_GET_ALTINTERFACE: ai = (struct usb_alt_interface *)addr; err = usbd_device2interface_handle(sc->sc_udev, ai->uai_interface_index, &iface); if (err) return (EINVAL); idesc = usbd_get_interface_descriptor(iface); if (idesc == NULL) return (EIO); ai->uai_alt_no = idesc->bAlternateSetting; break; case USB_SET_ALTINTERFACE: if (!(flag & FWRITE)) return (EPERM); ai = (struct usb_alt_interface *)addr; err = usbd_device2interface_handle(sc->sc_udev, ai->uai_interface_index, &iface); if (err) return (EINVAL); err = ugen_set_interface(sc, ai->uai_interface_index, ai->uai_alt_no); if (err) return (EINVAL); break; case USB_GET_NO_ALT: ai = (struct usb_alt_interface *)addr; cdesc = usbd_get_cdesc(sc->sc_udev, ai->uai_config_index, &cdesc_len); if (cdesc == NULL) return (EINVAL); idesc = usbd_find_idesc(cdesc, ai->uai_interface_index, 0); if (idesc == NULL) { free(cdesc, M_TEMP, UGETW(cdesc->wTotalLength)); return (EINVAL); } ai->uai_alt_no = usbd_get_no_alts(cdesc, idesc->bInterfaceNumber); free(cdesc, M_TEMP, cdesc_len); break; case USB_GET_DEVICE_DESC: *(usb_device_descriptor_t *)addr = *usbd_get_device_descriptor(sc->sc_udev); break; case USB_GET_CONFIG_DESC: cd = (struct usb_config_desc *)addr; cdesc = usbd_get_cdesc(sc->sc_udev, cd->ucd_config_index, &cdesc_len); if (cdesc == NULL) return (EINVAL); cd->ucd_desc = *cdesc; free(cdesc, M_TEMP, cdesc_len); break; case USB_GET_INTERFACE_DESC: id = (struct usb_interface_desc *)addr; cdesc = usbd_get_cdesc(sc->sc_udev, id->uid_config_index, &cdesc_len); if (cdesc == NULL) return (EINVAL); if (id->uid_config_index == USB_CURRENT_CONFIG_INDEX && id->uid_alt_index == USB_CURRENT_ALT_INDEX) alt = ugen_get_alt_index(sc, id->uid_interface_index); else alt = id->uid_alt_index; idesc = usbd_find_idesc(cdesc, id->uid_interface_index, alt); if (idesc == NULL) { free(cdesc, M_TEMP, UGETW(cdesc->wTotalLength)); return (EINVAL); } id->uid_desc = *idesc; free(cdesc, M_TEMP, cdesc_len); break; case USB_GET_ENDPOINT_DESC: ed = (struct usb_endpoint_desc *)addr; cdesc = usbd_get_cdesc(sc->sc_udev, ed->ued_config_index, &cdesc_len); if (cdesc == NULL) return (EINVAL); if (ed->ued_config_index == USB_CURRENT_CONFIG_INDEX && ed->ued_alt_index == USB_CURRENT_ALT_INDEX) alt = ugen_get_alt_index(sc, ed->ued_interface_index); else alt = ed->ued_alt_index; edesc = usbd_find_edesc(cdesc, ed->ued_interface_index, alt, ed->ued_endpoint_index); if (edesc == NULL) { free(cdesc, M_TEMP, UGETW(cdesc->wTotalLength)); return (EINVAL); } ed->ued_desc = *edesc; free(cdesc, M_TEMP, cdesc_len); break; case USB_GET_FULL_DESC: { u_int len; struct iovec iov; struct uio uio; struct usb_full_desc *fd = (struct usb_full_desc *)addr; int error; cdesc = usbd_get_cdesc(sc->sc_udev, fd->ufd_config_index, &cdesc_len); if (cdesc == NULL) return (EINVAL); len = cdesc_len; if (len > fd->ufd_size) len = fd->ufd_size; iov.iov_base = (caddr_t)fd->ufd_data; iov.iov_len = len; uio.uio_iov = &iov; uio.uio_iovcnt = 1; uio.uio_resid = len; uio.uio_offset = 0; uio.uio_segflg = UIO_USERSPACE; uio.uio_rw = UIO_READ; uio.uio_procp = p; error = uiomove((void *)cdesc, len, &uio); free(cdesc, M_TEMP, cdesc_len); return (error); } case USB_DO_REQUEST: { struct usb_ctl_request *ur = (void *)addr; size_t len = UGETW(ur->ucr_request.wLength), mlen; struct iovec iov; struct uio uio; void *ptr = NULL; int error = 0; if (!(flag & FWRITE)) return (EPERM); /* Avoid requests that would damage the bus integrity. */ if ((ur->ucr_request.bmRequestType == UT_WRITE_DEVICE && ur->ucr_request.bRequest == UR_SET_ADDRESS) || (ur->ucr_request.bmRequestType == UT_WRITE_DEVICE && ur->ucr_request.bRequest == UR_SET_CONFIG) || (ur->ucr_request.bmRequestType == UT_WRITE_INTERFACE && ur->ucr_request.bRequest == UR_SET_INTERFACE)) return (EINVAL); if (len > 32767) return (EINVAL); if (len != 0) { iov.iov_base = (caddr_t)ur->ucr_data; iov.iov_len = len; uio.uio_iov = &iov; uio.uio_iovcnt = 1; uio.uio_resid = len; uio.uio_offset = 0; uio.uio_segflg = UIO_USERSPACE; uio.uio_rw = ur->ucr_request.bmRequestType & UT_READ ? UIO_READ : UIO_WRITE; uio.uio_procp = p; if ((ptr = malloc(len, M_TEMP, M_NOWAIT)) == NULL) { error = ENOMEM; goto ret; } if (uio.uio_rw == UIO_WRITE) { error = uiomove(ptr, len, &uio); if (error) goto ret; } } sce = &sc->sc_endpoints[endpt][IN]; err = usbd_do_request_flags(sc->sc_udev, &ur->ucr_request, ptr, ur->ucr_flags, &ur->ucr_actlen, sce->timeout); if (err) { error = EIO; goto ret; } /* Only if USBD_SHORT_XFER_OK is set. */ mlen = len; if (mlen > ur->ucr_actlen) mlen = ur->ucr_actlen; if (mlen != 0) { if (uio.uio_rw == UIO_READ) { error = uiomove(ptr, mlen, &uio); if (error) goto ret; } } ret: free(ptr, M_TEMP, len); return (error); } case USB_GET_DEVICEINFO: usbd_fill_deviceinfo(sc->sc_udev, (struct usb_device_info *)addr); break; default: return (EINVAL); } return (0); } int ugenioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { int endpt = UGENENDPOINT(dev); struct ugen_softc *sc; int error; sc = ugen_cd.cd_devs[UGENUNIT(dev)]; sc->sc_refcnt++; error = ugen_do_ioctl(sc, endpt, cmd, addr, flag, p); if (--sc->sc_refcnt < 0) usb_detach_wakeup(&sc->sc_dev); return (error); } void filt_ugenrdetach(struct knote *); int filt_ugenread_intr(struct knote *, long); int filt_ugenread_isoc(struct knote *, long); int ugenkqfilter(dev_t, struct knote *); void filt_ugenrdetach(struct knote *kn) { struct ugen_endpoint *sce = (void *)kn->kn_hook; int s; s = splusb(); klist_remove_locked(&sce->rsel.si_note, kn); splx(s); } int filt_ugenread_intr(struct knote *kn, long hint) { struct ugen_endpoint *sce = (void *)kn->kn_hook; kn->kn_data = sce->q.c_cc; return (kn->kn_data > 0); } int filt_ugenread_isoc(struct knote *kn, long hint) { struct ugen_endpoint *sce = (void *)kn->kn_hook; if (sce->cur == sce->fill) return (0); if (sce->cur < sce->fill) kn->kn_data = sce->fill - sce->cur; else kn->kn_data = (sce->limit - sce->cur) + (sce->fill - sce->ibuf); return (1); } const struct filterops ugenread_intr_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, .f_detach = filt_ugenrdetach, .f_event = filt_ugenread_intr, }; const struct filterops ugenread_isoc_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, .f_detach = filt_ugenrdetach, .f_event = filt_ugenread_isoc, }; int ugenkqfilter(dev_t dev, struct knote *kn) { struct ugen_softc *sc; struct ugen_endpoint *sce; struct klist *klist; int s; sc = ugen_cd.cd_devs[UGENUNIT(dev)]; if (usbd_is_dying(sc->sc_udev)) return (ENXIO); /* XXX always IN */ sce = &sc->sc_endpoints[UGENENDPOINT(dev)][IN]; if (sce == NULL) return (ENXIO); switch (kn->kn_filter) { case EVFILT_READ: klist = &sce->rsel.si_note; switch (UE_GET_XFERTYPE(sce->edesc->bmAttributes)) { case UE_INTERRUPT: kn->kn_fop = &ugenread_intr_filtops; break; case UE_ISOCHRONOUS: kn->kn_fop = &ugenread_isoc_filtops; break; case UE_BULK: /* * We have no easy way of determining if a read will * yield any data or a write will happen. */ return (seltrue_kqfilter(dev, kn)); default: return (EINVAL); } break; case EVFILT_WRITE: klist = &sce->rsel.si_note; switch (UE_GET_XFERTYPE(sce->edesc->bmAttributes)) { case UE_INTERRUPT: case UE_ISOCHRONOUS: /* XXX poll doesn't support this */ return (EINVAL); case UE_BULK: /* * We have no easy way of determining if a read will * yield any data or a write will happen. */ return (seltrue_kqfilter(dev, kn)); default: return (EINVAL); } break; default: return (EINVAL); } kn->kn_hook = (void *)sce; s = splusb(); klist_insert_locked(klist, kn); splx(s); return (0); } void ugen_clear_iface_eps(struct ugen_softc *sc, struct usbd_interface *iface) { usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; uint8_t xfertype; int i; /* Only clear interface endpoints when none are in use. */ for (i = 0; i < USB_MAX_ENDPOINTS; i++) { if (i == USB_CONTROL_ENDPOINT) continue; if (sc->sc_is_open[i] != 0) return; } DPRINTFN(1,("%s: clear interface eps\n", __func__)); id = usbd_get_interface_descriptor(iface); if (id == NULL) goto bad; for (i = 0; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(iface, i); if (ed == NULL) goto bad; xfertype = UE_GET_XFERTYPE(ed->bmAttributes); if (xfertype == UE_BULK || xfertype == UE_INTERRUPT) { if (usbd_clear_endpoint_feature(sc->sc_udev, ed->bEndpointAddress, UF_ENDPOINT_HALT)) goto bad; } } return; bad: printf("%s: clear endpoints failed!\n", __func__); }
238 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 /* $OpenBSD: uvm_pmemrange.h,v 1.17 2024/05/01 12:54:27 mpi Exp $ */ /* * Copyright (c) 2009 Ariane van der Steldt <ariane@stack.nl> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * uvm_pmemrange.h: describe and manage free physical memory. */ #ifndef _UVM_UVM_PMEMRANGE_H_ #define _UVM_UVM_PMEMRANGE_H_ RBT_HEAD(uvm_pmr_addr, vm_page); RBT_HEAD(uvm_pmr_size, vm_page); /* * Page types available: * - DIRTY: this page may contain random data. * - ZERO: this page has been zeroed. */ #define UVM_PMR_MEMTYPE_DIRTY 0 #define UVM_PMR_MEMTYPE_ZERO 1 #define UVM_PMR_MEMTYPE_MAX 2 /* * An address range of memory. */ struct uvm_pmemrange { struct uvm_pmr_addr addr; /* Free page chunks, sorted by addr. */ struct uvm_pmr_size size[UVM_PMR_MEMTYPE_MAX]; /* Free page chunks, sorted by size. */ TAILQ_HEAD(, vm_page) single[UVM_PMR_MEMTYPE_MAX]; /* single page regions (uses pageq) */ paddr_t low; /* Start of address range (pgno). */ paddr_t high; /* End +1 (pgno). */ int use; /* Use counter. */ psize_t nsegs; /* Current range count. */ TAILQ_ENTRY(uvm_pmemrange) pmr_use; /* pmr, sorted by use */ RBT_ENTRY(uvm_pmemrange) pmr_addr; /* pmr, sorted by address */ }; /* * Description of failing memory allocation. * * Two ways new pages can become available: * [1] page daemon drops them (we notice because they are freed) * [2] a process calls free * * The buffer cache and page daemon can decide that they don't have the * ability to make pages available in the requested range. In that case, * the FAIL bit will be set. * XXX There's a possibility that a page is no longer on the queues but * XXX has not yet been freed, or that a page was busy. * XXX Also, wired pages are not considered for paging, so they could * XXX cause a failure that may be recoverable. */ struct uvm_pmalloc { TAILQ_ENTRY(uvm_pmalloc) pmq; /* * Allocation request parameters. */ struct uvm_constraint_range pm_constraint; psize_t pm_size; /* * State flags. */ int pm_flags; }; /* * uvm_pmalloc flags. */ #define UVM_PMA_LINKED 0x01 /* uvm_pmalloc is on list */ #define UVM_PMA_BUSY 0x02 /* entry is busy with fpageq unlocked */ #define UVM_PMA_FAIL 0x10 /* page daemon cannot free pages */ #define UVM_PMA_FREED 0x20 /* at least one page in the range was freed */ RBT_HEAD(uvm_pmemrange_addr, uvm_pmemrange); TAILQ_HEAD(uvm_pmemrange_use, uvm_pmemrange); /* * pmr control structure. Contained in uvm.pmr_control. */ struct uvm_pmr_control { struct uvm_pmemrange_addr addr; struct uvm_pmemrange_use use; /* Only changed while fpageq is locked. */ TAILQ_HEAD(, uvm_pmalloc) allocs; }; void uvm_pmr_freepages(struct vm_page *, psize_t); void uvm_pmr_freepageq(struct pglist *); int uvm_pmr_getpages(psize_t, paddr_t, paddr_t, paddr_t, paddr_t, int, int, struct pglist *); void uvm_pmr_init(void); int uvm_wait_pla(paddr_t, paddr_t, paddr_t, int); void uvm_wakeup_pla(paddr_t, psize_t); #if defined(DDB) || defined(DEBUG) int uvm_pmr_isfree(struct vm_page *pg); #endif /* * Internal tree logic. */ int uvm_pmr_addr_cmp(const struct vm_page *, const struct vm_page *); int uvm_pmr_size_cmp(const struct vm_page *, const struct vm_page *); RBT_PROTOTYPE(uvm_pmr_addr, vm_page, objt, uvm_pmr_addr_cmp); RBT_PROTOTYPE(uvm_pmr_size, vm_page, objt, uvm_pmr_size_cmp); RBT_PROTOTYPE(uvm_pmemrange_addr, uvm_pmemrange, pmr_addr, uvm_pmemrange_addr_cmp); struct vm_page *uvm_pmr_insert_addr(struct uvm_pmemrange *, struct vm_page *, int); void uvm_pmr_insert_size(struct uvm_pmemrange *, struct vm_page *); struct vm_page *uvm_pmr_insert(struct uvm_pmemrange *, struct vm_page *, int); void uvm_pmr_remove_addr(struct uvm_pmemrange *, struct vm_page *); void uvm_pmr_remove_size(struct uvm_pmemrange *, struct vm_page *); void uvm_pmr_remove(struct uvm_pmemrange *, struct vm_page *); struct vm_page *uvm_pmr_extract_range(struct uvm_pmemrange *, struct vm_page *, paddr_t, paddr_t, struct pglist *); struct vm_page *uvm_pmr_cache_get(int); void uvm_pmr_cache_put(struct vm_page *); void uvm_pmr_cache_drain(void); #endif /* _UVM_UVM_PMEMRANGE_H_ */
21 1 18 2 11 23 103 13 8 84 3 35 128 123 5 122 1 114 1 7 2 35 3 8 15 15 15 11 8 5 4 1 1 3 1 1 3 7 2 3 3 1 1 5 5 35 21 16 28 26 33 6 4 20 21 2 20 1 2 5 17 5 4 16 20 19 4 18 2 3 24 9 16 18 18 13 11 7 4 4 4 4 3 4 8 5 21 23 23 9 16 15 8 23 23 10 14 5 4 15 16 7 21 13 13 13 13 5 10 10 19 25 25 17 25 25 25 23 24 20 28 28 6 5 21 38 38 22 23 10 10 23 1 46 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 /* $OpenBSD: in.c,v 1.186 2024/01/06 10:58:45 bluhm Exp $ */ /* $NetBSD: in.c,v 1.26 1996/02/13 23:41:39 christos Exp $ */ /* * Copyright (C) 2001 WIDE Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 1982, 1986, 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)in.c 8.2 (Berkeley) 11/15/93 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/ioctl.h> #include <sys/malloc.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <net/if.h> #include <net/if_var.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/in_var.h> #include <netinet/igmp_var.h> #ifdef MROUTING #include <netinet/ip_mroute.h> #endif #include "ether.h" void in_socktrim(struct sockaddr_in *); int in_ioctl_set_ifaddr(u_long, caddr_t, struct ifnet *); int in_ioctl_change_ifaddr(u_long, caddr_t, struct ifnet *); int in_ioctl_get(u_long, caddr_t, struct ifnet *); void in_purgeaddr(struct ifaddr *); int in_addhost(struct in_ifaddr *, struct sockaddr_in *); int in_scrubhost(struct in_ifaddr *, struct sockaddr_in *); int in_insert_prefix(struct in_ifaddr *); void in_remove_prefix(struct in_ifaddr *); /* * Determine whether an IP address is in a reserved set of addresses * that may not be forwarded, or whether datagrams to that destination * may be forwarded. */ int in_canforward(struct in_addr in) { u_int32_t net; if (IN_MULTICAST(in.s_addr)) return (0); if (IN_CLASSA(in.s_addr)) { net = in.s_addr & IN_CLASSA_NET; if (net == 0 || net == htonl(IN_LOOPBACKNET << IN_CLASSA_NSHIFT)) return (0); } return (1); } /* * Trim a mask in a sockaddr */ void in_socktrim(struct sockaddr_in *ap) { char *cplim = (char *) &ap->sin_addr; char *cp = (char *) (&ap->sin_addr + 1); ap->sin_len = 0; while (--cp >= cplim) if (*cp) { (ap)->sin_len = cp - (char *) (ap) + 1; break; } } int in_mask2len(struct in_addr *mask) { int x, y; u_char *p; p = (u_char *)mask; for (x = 0; x < sizeof(*mask); x++) { if (p[x] != 0xff) break; } y = 0; if (x < sizeof(*mask)) { for (y = 0; y < 8; y++) { if ((p[x] & (0x80 >> y)) == 0) break; } } return x * 8 + y; } void in_len2mask(struct in_addr *mask, int len) { int i; u_char *p; p = (u_char *)mask; bzero(mask, sizeof(*mask)); for (i = 0; i < len / 8; i++) p[i] = 0xff; if (len % 8) p[i] = (0xff00 >> (len % 8)) & 0xff; } int in_nam2sin(const struct mbuf *nam, struct sockaddr_in **sin) { struct sockaddr *sa = mtod(nam, struct sockaddr *); if (nam->m_len < offsetof(struct sockaddr, sa_data)) return EINVAL; if (sa->sa_family != AF_INET) return EAFNOSUPPORT; if (sa->sa_len != nam->m_len) return EINVAL; if (sa->sa_len != sizeof(struct sockaddr_in)) return EINVAL; *sin = satosin(sa); return 0; } int in_sa2sin(struct sockaddr *sa, struct sockaddr_in **sin) { if (sa->sa_family != AF_INET) return EAFNOSUPPORT; if (sa->sa_len != sizeof(struct sockaddr_in)) return EINVAL; *sin = satosin(sa); return 0; } int in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp) { int privileged; privileged = 0; if ((so->so_state & SS_PRIV) != 0) privileged++; switch (cmd) { #ifdef MROUTING case SIOCGETVIFCNT: case SIOCGETSGCNT: return mrt_ioctl(so, cmd, data); #endif /* MROUTING */ default: return in_ioctl(cmd, data, ifp, privileged); } } int in_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, int privileged) { struct ifreq *ifr = (struct ifreq *)data; struct ifaddr *ifa; struct in_ifaddr *ia = NULL; struct sockaddr_in *sin = NULL, oldaddr; int error = 0; if (ifp == NULL) return (ENXIO); switch (cmd) { case SIOCGIFADDR: case SIOCGIFNETMASK: case SIOCGIFDSTADDR: case SIOCGIFBRDADDR: return in_ioctl_get(cmd, data, ifp); case SIOCSIFADDR: if (!privileged) return (EPERM); return in_ioctl_set_ifaddr(cmd, data, ifp); case SIOCAIFADDR: case SIOCDIFADDR: if (!privileged) return (EPERM); return in_ioctl_change_ifaddr(cmd, data, ifp); case SIOCSIFNETMASK: case SIOCSIFDSTADDR: case SIOCSIFBRDADDR: break; default: return (EOPNOTSUPP); } if (!privileged) return (EPERM); if (ifr->ifr_addr.sa_family == AF_INET) { error = in_sa2sin(&ifr->ifr_addr, &sin); if (error) return (error); } NET_LOCK(); KERNEL_LOCK(); TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET) continue; /* find first address or exact match */ if (ia == NULL) ia = ifatoia(ifa); if (sin == NULL || sin->sin_addr.s_addr == INADDR_ANY) break; if (ifatoia(ifa)->ia_addr.sin_addr.s_addr == sin->sin_addr.s_addr) { ia = ifatoia(ifa); break; } } if (ia == NULL) { error = EADDRNOTAVAIL; goto err; } switch (cmd) { case SIOCSIFDSTADDR: if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { error = EINVAL; break; } error = in_sa2sin(&ifr->ifr_dstaddr, &sin); if (error) break; oldaddr = ia->ia_dstaddr; ia->ia_dstaddr = *sin; error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, (caddr_t)ia); if (error) { ia->ia_dstaddr = oldaddr; break; } in_scrubhost(ia, &oldaddr); in_addhost(ia, &ia->ia_dstaddr); break; case SIOCSIFBRDADDR: if ((ifp->if_flags & IFF_BROADCAST) == 0) { error = EINVAL; break; } error = in_sa2sin(&ifr->ifr_broadaddr, &sin); if (error) break; ifa_update_broadaddr(ifp, &ia->ia_ifa, sintosa(sin)); break; case SIOCSIFNETMASK: if (ifr->ifr_addr.sa_len < 8) { error = EINVAL; break; } /* do not check inet family or strict len */ sin = satosin(&ifr->ifr_addr); if (ntohl(sin->sin_addr.s_addr) & (~ntohl(sin->sin_addr.s_addr) >> 1)) { /* non-contiguous netmask */ error = EINVAL; break; } ia->ia_netmask = ia->ia_sockmask.sin_addr.s_addr = sin->sin_addr.s_addr; break; } err: KERNEL_UNLOCK(); NET_UNLOCK(); return (error); } int in_ioctl_set_ifaddr(u_long cmd, caddr_t data, struct ifnet *ifp) { struct ifreq *ifr = (struct ifreq *)data; struct ifaddr *ifa; struct in_ifaddr *ia = NULL; struct sockaddr_in *sin; int error = 0; int newifaddr; if (cmd != SIOCSIFADDR) panic("%s: invalid ioctl %lu", __func__, cmd); error = in_sa2sin(&ifr->ifr_addr, &sin); if (error) return (error); NET_LOCK(); KERNEL_LOCK(); TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET) continue; /* find first address */ ia = ifatoia(ifa); break; } if (ia == NULL) { ia = malloc(sizeof *ia, M_IFADDR, M_WAITOK | M_ZERO); refcnt_init_trace(&ia->ia_ifa.ifa_refcnt, DT_REFCNT_IDX_IFADDR); ia->ia_addr.sin_family = AF_INET; ia->ia_addr.sin_len = sizeof(ia->ia_addr); ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr); ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr); ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask); ia->ia_sockmask.sin_len = 8; if (ifp->if_flags & IFF_BROADCAST) { ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); ia->ia_broadaddr.sin_family = AF_INET; } ia->ia_ifp = ifp; newifaddr = 1; } else newifaddr = 0; in_ifscrub(ifp, ia); error = in_ifinit(ifp, ia, sin, newifaddr); if (!error) if_addrhooks_run(ifp); KERNEL_UNLOCK(); NET_UNLOCK(); return error; } int in_ioctl_change_ifaddr(u_long cmd, caddr_t data, struct ifnet *ifp) { struct ifaddr *ifa; struct in_ifaddr *ia = NULL; struct in_aliasreq *ifra = (struct in_aliasreq *)data; struct sockaddr_in *sin = NULL, *dstsin = NULL, *broadsin = NULL; struct sockaddr_in *masksin = NULL; int error = 0; int newifaddr; if (ifra->ifra_addr.sin_family == AF_INET) { error = in_sa2sin(sintosa(&ifra->ifra_addr), &sin); if (error) return (error); } NET_LOCK(); KERNEL_LOCK(); TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET) continue; /* find first address, if no exact match wanted */ if (sin == NULL || sin->sin_addr.s_addr == ifatoia(ifa)->ia_addr.sin_addr.s_addr) { ia = ifatoia(ifa); break; } } switch (cmd) { case SIOCAIFADDR: { int needinit = 0; if (ifra->ifra_mask.sin_len) { if (ifra->ifra_mask.sin_len < 8) { error = EINVAL; break; } /* do not check inet family or strict len */ masksin = &ifra->ifra_mask; if (ntohl(masksin->sin_addr.s_addr) & (~ntohl(masksin->sin_addr.s_addr) >> 1)) { /* non-contiguous netmask */ error = EINVAL; break; } } if ((ifp->if_flags & IFF_POINTOPOINT) && ifra->ifra_dstaddr.sin_family == AF_INET) { error = in_sa2sin(sintosa(&ifra->ifra_dstaddr), &dstsin); if (error) break; } if ((ifp->if_flags & IFF_BROADCAST) && ifra->ifra_broadaddr.sin_family == AF_INET) { error = in_sa2sin(sintosa(&ifra->ifra_broadaddr), &broadsin); if (error) break; } if (ia == NULL) { ia = malloc(sizeof *ia, M_IFADDR, M_WAITOK | M_ZERO); refcnt_init_trace(&ia->ia_ifa.ifa_refcnt, DT_REFCNT_IDX_IFADDR); ia->ia_addr.sin_family = AF_INET; ia->ia_addr.sin_len = sizeof(ia->ia_addr); ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr); ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr); ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask); ia->ia_sockmask.sin_len = 8; if (ifp->if_flags & IFF_BROADCAST) { ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); ia->ia_broadaddr.sin_family = AF_INET; } ia->ia_ifp = ifp; newifaddr = 1; } else newifaddr = 0; if (sin == NULL) { sin = &ia->ia_addr; } else if (newifaddr || sin->sin_addr.s_addr != ia->ia_addr.sin_addr.s_addr) { needinit = 1; } if (masksin != NULL) { in_ifscrub(ifp, ia); ia->ia_netmask = ia->ia_sockmask.sin_addr.s_addr = masksin->sin_addr.s_addr; needinit = 1; } if (dstsin != NULL) { in_ifscrub(ifp, ia); ia->ia_dstaddr = *dstsin; needinit = 1; } if (broadsin != NULL) { if (newifaddr) ia->ia_broadaddr = *broadsin; else ifa_update_broadaddr(ifp, &ia->ia_ifa, sintosa(broadsin)); } if (needinit) { error = in_ifinit(ifp, ia, sin, newifaddr); if (error) break; } if_addrhooks_run(ifp); break; } case SIOCDIFADDR: if (ia == NULL) { error = EADDRNOTAVAIL; break; } /* * Even if the individual steps were safe, shouldn't * these kinds of changes happen atomically? What * should happen to a packet that was routed after * the scrub but before the other steps? */ in_purgeaddr(&ia->ia_ifa); if_addrhooks_run(ifp); break; default: panic("%s: invalid ioctl %lu", __func__, cmd); } KERNEL_UNLOCK(); NET_UNLOCK(); return (error); } int in_ioctl_get(u_long cmd, caddr_t data, struct ifnet *ifp) { struct ifreq *ifr = (struct ifreq *)data; struct ifaddr *ifa; struct in_ifaddr *ia = NULL; struct sockaddr *sa; struct sockaddr_in *sin = NULL; int error = 0; sa = &ifr->ifr_addr; if (sa->sa_family == AF_INET) { sa->sa_len = sizeof(struct sockaddr_in); error = in_sa2sin(sa, &sin); if (error) return (error); } NET_LOCK_SHARED(); TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET) continue; /* find first address or exact match */ if (ia == NULL) ia = ifatoia(ifa); if (sin == NULL || sin->sin_addr.s_addr == INADDR_ANY) break; if (ifatoia(ifa)->ia_addr.sin_addr.s_addr == sin->sin_addr.s_addr) { ia = ifatoia(ifa); break; } } if (ia == NULL) { error = EADDRNOTAVAIL; goto err; } switch(cmd) { case SIOCGIFADDR: *satosin(&ifr->ifr_addr) = ia->ia_addr; break; case SIOCGIFBRDADDR: if ((ifp->if_flags & IFF_BROADCAST) == 0) { error = EINVAL; break; } *satosin(&ifr->ifr_dstaddr) = ia->ia_broadaddr; break; case SIOCGIFDSTADDR: if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { error = EINVAL; break; } *satosin(&ifr->ifr_dstaddr) = ia->ia_dstaddr; break; case SIOCGIFNETMASK: *satosin(&ifr->ifr_addr) = ia->ia_sockmask; break; default: panic("%s: invalid ioctl %lu", __func__, cmd); } err: NET_UNLOCK_SHARED(); return (error); } /* * Delete any existing route for an interface. */ void in_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia) { if (ISSET(ifp->if_flags, IFF_POINTOPOINT)) in_scrubhost(ia, &ia->ia_dstaddr); else if (!ISSET(ifp->if_flags, IFF_LOOPBACK)) in_remove_prefix(ia); } /* * Initialize an interface's internet address * and routing table entry. */ int in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin, int newaddr) { u_int32_t i = sin->sin_addr.s_addr; struct sockaddr_in oldaddr; int error = 0, rterror; NET_ASSERT_LOCKED(); /* * Always remove the address from the tree to make sure its * position gets updated in case the key changes. */ if (!newaddr) { rt_ifa_dellocal(&ia->ia_ifa); ifa_del(ifp, &ia->ia_ifa); } oldaddr = ia->ia_addr; ia->ia_addr = *sin; if (ia->ia_netmask == 0) { if (IN_CLASSA(i)) ia->ia_netmask = IN_CLASSA_NET; else if (IN_CLASSB(i)) ia->ia_netmask = IN_CLASSB_NET; else ia->ia_netmask = IN_CLASSC_NET; ia->ia_sockmask.sin_addr.s_addr = ia->ia_netmask; } /* * Give the interface a chance to initialize * if this is its first address, * and to validate the address if necessary. */ if ((error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) { ia->ia_addr = oldaddr; } /* * Add the address to the local list and the global tree. If an * error occurred, put back the original address. */ ifa_add(ifp, &ia->ia_ifa); rterror = rt_ifa_addlocal(&ia->ia_ifa); if (rterror) { if (!newaddr) ifa_del(ifp, &ia->ia_ifa); if (!error) error = rterror; goto out; } if (error) goto out; ia->ia_net = i & ia->ia_netmask; in_socktrim(&ia->ia_sockmask); /* * Add route for the network. */ ia->ia_ifa.ifa_metric = ifp->if_metric; if (ISSET(ifp->if_flags, IFF_BROADCAST)) { if (IN_RFC3021_SUBNET(ia->ia_netmask)) ia->ia_broadaddr.sin_addr.s_addr = 0; else { ia->ia_broadaddr.sin_addr.s_addr = ia->ia_net | ~ia->ia_netmask; } } if (ISSET(ifp->if_flags, IFF_POINTOPOINT)) { /* XXX We should not even call in_ifinit() in this case. */ if (ia->ia_dstaddr.sin_family != AF_INET) goto out; error = in_addhost(ia, &ia->ia_dstaddr); } else if (!ISSET(ifp->if_flags, IFF_LOOPBACK)) { error = in_insert_prefix(ia); } /* * If the interface supports multicast, join the "all hosts" * multicast group on that interface. */ if ((ifp->if_flags & IFF_MULTICAST) && ia->ia_allhosts == NULL) { struct in_addr addr; addr.s_addr = INADDR_ALLHOSTS_GROUP; ia->ia_allhosts = in_addmulti(&addr, ifp); } out: if (error && newaddr) in_purgeaddr(&ia->ia_ifa); return (error); } void in_purgeaddr(struct ifaddr *ifa) { struct ifnet *ifp = ifa->ifa_ifp; struct in_ifaddr *ia = ifatoia(ifa); NET_ASSERT_LOCKED(); in_ifscrub(ifp, ia); rt_ifa_dellocal(&ia->ia_ifa); rt_ifa_purge(&ia->ia_ifa); ifa_del(ifp, &ia->ia_ifa); if (ia->ia_allhosts != NULL) { in_delmulti(ia->ia_allhosts); ia->ia_allhosts = NULL; } ia->ia_ifp = NULL; ifafree(&ia->ia_ifa); } int in_addhost(struct in_ifaddr *ia, struct sockaddr_in *dst) { return rt_ifa_add(&ia->ia_ifa, RTF_HOST | RTF_MPATH, sintosa(dst), ia->ia_ifa.ifa_ifp->if_rdomain); } int in_scrubhost(struct in_ifaddr *ia, struct sockaddr_in *dst) { return rt_ifa_del(&ia->ia_ifa, RTF_HOST, sintosa(dst), ia->ia_ifa.ifa_ifp->if_rdomain); } /* * Insert the cloning and broadcast routes for this subnet. */ int in_insert_prefix(struct in_ifaddr *ia) { struct ifaddr *ifa = &ia->ia_ifa; int error; error = rt_ifa_add(ifa, RTF_CLONING | RTF_CONNECTED | RTF_MPATH, ifa->ifa_addr, ifa->ifa_ifp->if_rdomain); if (error) return (error); if (ia->ia_broadaddr.sin_addr.s_addr != 0) { error = rt_ifa_add(ifa, RTF_HOST | RTF_BROADCAST | RTF_MPATH, ifa->ifa_broadaddr, ifa->ifa_ifp->if_rdomain); } return (error); } void in_remove_prefix(struct in_ifaddr *ia) { struct ifaddr *ifa = &ia->ia_ifa; rt_ifa_del(ifa, RTF_CLONING | RTF_CONNECTED, ifa->ifa_addr, ifa->ifa_ifp->if_rdomain); if (ia->ia_broadaddr.sin_addr.s_addr != 0) { rt_ifa_del(ifa, RTF_HOST | RTF_BROADCAST, ifa->ifa_broadaddr, ifa->ifa_ifp->if_rdomain); } } /* * Return 1 if the address is a local broadcast address. */ int in_broadcast(struct in_addr in, u_int rtableid) { struct ifnet *ifn; struct ifaddr *ifa; u_int rdomain; rdomain = rtable_l2(rtableid); #define ia (ifatoia(ifa)) TAILQ_FOREACH(ifn, &ifnetlist, if_list) { if (ifn->if_rdomain != rdomain) continue; if ((ifn->if_flags & IFF_BROADCAST) == 0) continue; TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) if (ifa->ifa_addr->sa_family == AF_INET && in.s_addr != ia->ia_addr.sin_addr.s_addr && in.s_addr == ia->ia_broadaddr.sin_addr.s_addr) return 1; } return (0); #undef ia } /* * Add an address to the list of IP multicast addresses for a given interface. */ struct in_multi * in_addmulti(struct in_addr *ap, struct ifnet *ifp) { struct in_multi *inm; struct ifreq ifr; /* * See if address already in list. */ IN_LOOKUP_MULTI(*ap, ifp, inm); if (inm != NULL) { /* * Found it; just increment the reference count. */ refcnt_take(&inm->inm_refcnt); } else { /* * New address; allocate a new multicast record * and link it into the interface's multicast list. */ inm = malloc(sizeof(*inm), M_IPMADDR, M_WAITOK | M_ZERO); inm->inm_sin.sin_len = sizeof(struct sockaddr_in); inm->inm_sin.sin_family = AF_INET; inm->inm_sin.sin_addr = *ap; refcnt_init_trace(&inm->inm_refcnt, DT_REFCNT_IDX_IFMADDR); inm->inm_ifidx = ifp->if_index; inm->inm_ifma.ifma_addr = sintosa(&inm->inm_sin); /* * Ask the network driver to update its multicast reception * filter appropriately for the new address. */ memset(&ifr, 0, sizeof(ifr)); memcpy(&ifr.ifr_addr, &inm->inm_sin, sizeof(inm->inm_sin)); KERNEL_LOCK(); if ((*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) { KERNEL_UNLOCK(); free(inm, M_IPMADDR, sizeof(*inm)); return (NULL); } KERNEL_UNLOCK(); TAILQ_INSERT_HEAD(&ifp->if_maddrlist, &inm->inm_ifma, ifma_list); /* * Let IGMP know that we have joined a new IP multicast group. */ igmp_joingroup(inm, ifp); } return (inm); } /* * Delete a multicast address record. */ void in_delmulti(struct in_multi *inm) { struct ifreq ifr; struct ifnet *ifp; NET_ASSERT_LOCKED(); if (refcnt_rele(&inm->inm_refcnt) == 0) return; ifp = if_get(inm->inm_ifidx); if (ifp != NULL) { /* * No remaining claims to this record; let IGMP know that * we are leaving the multicast group. */ igmp_leavegroup(inm, ifp); /* * Notify the network driver to update its multicast * reception filter. */ memset(&ifr, 0, sizeof(ifr)); satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in); satosin(&ifr.ifr_addr)->sin_family = AF_INET; satosin(&ifr.ifr_addr)->sin_addr = inm->inm_addr; KERNEL_LOCK(); (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr); KERNEL_UNLOCK(); TAILQ_REMOVE(&ifp->if_maddrlist, &inm->inm_ifma, ifma_list); } if_put(ifp); free(inm, M_IPMADDR, sizeof(*inm)); } /* * Return 1 if the multicast group represented by ``ap'' has been * joined by interface ``ifp'', 0 otherwise. */ int in_hasmulti(struct in_addr *ap, struct ifnet *ifp) { struct in_multi *inm; int joined; IN_LOOKUP_MULTI(*ap, ifp, inm); joined = (inm != NULL); return (joined); } void in_ifdetach(struct ifnet *ifp) { struct ifaddr *ifa, *next; /* nuke any of IPv4 addresses we have */ TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrlist, ifa_list, next) { if (ifa->ifa_addr->sa_family != AF_INET) continue; in_purgeaddr(ifa); if_addrhooks_run(ifp); } if (ifp->if_xflags & IFXF_AUTOCONF4) ifp->if_xflags &= ~IFXF_AUTOCONF4; } void in_prefixlen2mask(struct in_addr *maskp, int plen) { if (plen == 0) maskp->s_addr = 0; else maskp->s_addr = htonl(0xffffffff << (32 - plen)); }
61 60 22 71 27 43 16 7 49 8 49 105 104 18 18 1 16 5 2 9 133 57 51 5 118 115 3 53 66 2 117 5 113 113 53 76 72 1 5 111 104 8 8 3 2 2 3 113 12 12 10 211 2 208 1 207 29 28 1 29 1 28 522 1 520 455 70 28 207 335 520 2 3 420 5 116 512 105 3 428 39 494 1 4 33 30 3 33 503 329 501 4 488 11 497 494 4 498 325 195 8 493 328 194 499 320 215 517 201 334 503 502 152 447 91 55 37 217 256 152 61 3 3 61 142 15 130 113 40 139 3 139 3 119 17 137 136 8 65 8 25 3 81 6 2 3 83 5 84 40 50 48 3 50 93 47 5 42 40 1 42 94 4 1 1 36 36 4 25 25 25 1 6 6 40 10 30 79 1 46 4 46 4 42 46 46 11 31 31 2 4 29 3 4 45 1 6 28 3 5 3 3 3 1 22 4 40 93 21 8 38 41 35 6 41 93 2 93 134 117 17 49 12 14 23 37 22 15 37 1 1 35 1 8 5 3 26 4 1 2 19 2 2 16 15 2 2 4 12 5 10 23 15 15 15 10 18 1 2 16 2 13 1 14 1 13 10 3 3 3 3 3 3 3 3 2 1 3 3 3 15 18 12 7 1 11 464 269 197 457 2 4 456 461 245 163 89 250 3 253 728 1 624 57 2 1 1 4 19 10 2 1 8 6 7 13 2 2 6 6 7 4 2 2 2 1 9 1 22 8 202 1 123 42 2 3 3 1 3 3 3 3 3 3 5 3 1 1 1 3 1 52 43 52 43 70 1 31 24 19 8 130 36 104 10 4 3 2 11 124 5 3 3 4 4 113 8 31 19 15 31 5 3 4 3 20 3 16 26 16 11 26 14 10 9 16 4 6 6 6 27 27 27 27 14 14 14 51 51 51 51 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 /* $OpenBSD: uipc_socket.c,v 1.335 2024/05/17 19:11:14 mvs Exp $ */ /* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)uipc_socket.c 8.3 (Berkeley) 4/15/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/file.h> #include <sys/filedesc.h> #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/domain.h> #include <sys/event.h> #include <sys/protosw.h> #include <sys/socket.h> #include <sys/unpcb.h> #include <sys/socketvar.h> #include <sys/signalvar.h> #include <sys/pool.h> #include <sys/atomic.h> #include <sys/rwlock.h> #include <sys/time.h> #include <sys/refcnt.h> #ifdef DDB #include <machine/db_machdep.h> #endif void sbsync(struct sockbuf *, struct mbuf *); int sosplice(struct socket *, int, off_t, struct timeval *); void sounsplice(struct socket *, struct socket *, int); void soidle(void *); void sotask(void *); void soreaper(void *); void soput(void *); int somove(struct socket *, int); void sorflush(struct socket *); void filt_sordetach(struct knote *kn); int filt_soread(struct knote *kn, long hint); void filt_sowdetach(struct knote *kn); int filt_sowrite(struct knote *kn, long hint); int filt_soexcept(struct knote *kn, long hint); int filt_sowmodify(struct kevent *kev, struct knote *kn); int filt_sowprocess(struct knote *kn, struct kevent *kev); int filt_sormodify(struct kevent *kev, struct knote *kn); int filt_sorprocess(struct knote *kn, struct kevent *kev); const struct filterops soread_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_sordetach, .f_event = filt_soread, .f_modify = filt_sormodify, .f_process = filt_sorprocess, }; const struct filterops sowrite_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_sowdetach, .f_event = filt_sowrite, .f_modify = filt_sowmodify, .f_process = filt_sowprocess, }; const struct filterops soexcept_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_sordetach, .f_event = filt_soexcept, .f_modify = filt_sormodify, .f_process = filt_sorprocess, }; #ifndef SOMINCONN #define SOMINCONN 80 #endif /* SOMINCONN */ int somaxconn = SOMAXCONN; int sominconn = SOMINCONN; struct pool socket_pool; #ifdef SOCKET_SPLICE struct pool sosplice_pool; struct taskq *sosplice_taskq; struct rwlock sosplice_lock = RWLOCK_INITIALIZER("sosplicelk"); #endif void soinit(void) { pool_init(&socket_pool, sizeof(struct socket), 0, IPL_SOFTNET, 0, "sockpl", NULL); #ifdef SOCKET_SPLICE pool_init(&sosplice_pool, sizeof(struct sosplice), 0, IPL_SOFTNET, 0, "sosppl", NULL); #endif } struct socket * soalloc(const struct protosw *prp, int wait) { const struct domain *dp = prp->pr_domain; struct socket *so; so = pool_get(&socket_pool, (wait == M_WAIT ? PR_WAITOK : PR_NOWAIT) | PR_ZERO); if (so == NULL) return (NULL); rw_init_flags(&so->so_lock, dp->dom_name, RWL_DUPOK); refcnt_init(&so->so_refcnt); rw_init(&so->so_rcv.sb_lock, "sbufrcv"); rw_init(&so->so_snd.sb_lock, "sbufsnd"); mtx_init_flags(&so->so_rcv.sb_mtx, IPL_MPFLOOR, "sbrcv", 0); mtx_init_flags(&so->so_snd.sb_mtx, IPL_MPFLOOR, "sbsnd", 0); klist_init_mutex(&so->so_rcv.sb_klist, &so->so_rcv.sb_mtx); klist_init_mutex(&so->so_snd.sb_klist, &so->so_snd.sb_mtx); sigio_init(&so->so_sigio); TAILQ_INIT(&so->so_q0); TAILQ_INIT(&so->so_q); switch (dp->dom_family) { case AF_INET: case AF_INET6: switch (prp->pr_type) { case SOCK_RAW: so->so_snd.sb_flags |= SB_MTXLOCK; /* FALLTHROUGH */ case SOCK_DGRAM: so->so_rcv.sb_flags |= SB_MTXLOCK; break; } break; case AF_KEY: case AF_UNIX: so->so_snd.sb_flags |= SB_MTXLOCK; so->so_rcv.sb_flags |= SB_MTXLOCK; break; } return (so); } /* * Socket operation routines. * These routines are called by the routines in * sys_socket.c or from a system process, and * implement the semantics of socket operations by * switching out to the protocol specific routines. */ int socreate(int dom, struct socket **aso, int type, int proto) { struct proc *p = curproc; /* XXX */ const struct protosw *prp; struct socket *so; int error; if (proto) prp = pffindproto(dom, proto, type); else prp = pffindtype(dom, type); if (prp == NULL || prp->pr_usrreqs == NULL) return (EPROTONOSUPPORT); if (prp->pr_type != type) return (EPROTOTYPE); so = soalloc(prp, M_WAIT); so->so_type = type; if (suser(p) == 0) so->so_state = SS_PRIV; so->so_ruid = p->p_ucred->cr_ruid; so->so_euid = p->p_ucred->cr_uid; so->so_rgid = p->p_ucred->cr_rgid; so->so_egid = p->p_ucred->cr_gid; so->so_cpid = p->p_p->ps_pid; so->so_proto = prp; so->so_snd.sb_timeo_nsecs = INFSLP; so->so_rcv.sb_timeo_nsecs = INFSLP; solock(so); error = pru_attach(so, proto, M_WAIT); if (error) { so->so_state |= SS_NOFDREF; /* sofree() calls sounlock(). */ sofree(so, 0); return (error); } sounlock(so); *aso = so; return (0); } int sobind(struct socket *so, struct mbuf *nam, struct proc *p) { soassertlocked(so); return pru_bind(so, nam, p); } int solisten(struct socket *so, int backlog) { int somaxconn_local = READ_ONCE(somaxconn); int sominconn_local = READ_ONCE(sominconn); int error; switch (so->so_type) { case SOCK_STREAM: case SOCK_SEQPACKET: break; default: return (EOPNOTSUPP); } soassertlocked(so); if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING|SS_ISDISCONNECTING)) return (EINVAL); #ifdef SOCKET_SPLICE if (isspliced(so) || issplicedback(so)) return (EOPNOTSUPP); #endif /* SOCKET_SPLICE */ error = pru_listen(so); if (error) return (error); if (TAILQ_FIRST(&so->so_q) == NULL) so->so_options |= SO_ACCEPTCONN; if (backlog < 0 || backlog > somaxconn_local) backlog = somaxconn_local; if (backlog < sominconn_local) backlog = sominconn_local; so->so_qlimit = backlog; return (0); } #define SOSP_FREEING_READ 1 #define SOSP_FREEING_WRITE 2 void sofree(struct socket *so, int keep_lock) { int persocket = solock_persocket(so); soassertlocked(so); if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) { if (!keep_lock) sounlock(so); return; } if (so->so_head) { struct socket *head = so->so_head; /* * We must not decommission a socket that's on the accept(2) * queue. If we do, then accept(2) may hang after select(2) * indicated that the listening socket was ready. */ if (so->so_onq == &head->so_q) { if (!keep_lock) sounlock(so); return; } if (persocket) { /* * Concurrent close of `head' could * abort `so' due to re-lock. */ soref(so); soref(head); sounlock(so); solock(head); solock(so); if (so->so_onq != &head->so_q0) { sounlock(head); sounlock(so); sorele(head); sorele(so); return; } sorele(head); sorele(so); } soqremque(so, 0); if (persocket) sounlock(head); } if (persocket) { sounlock(so); refcnt_finalize(&so->so_refcnt, "sofinal"); solock(so); } sigio_free(&so->so_sigio); klist_free(&so->so_rcv.sb_klist); klist_free(&so->so_snd.sb_klist); #ifdef SOCKET_SPLICE if (issplicedback(so)) { int freeing = SOSP_FREEING_WRITE; if (so->so_sp->ssp_soback == so) freeing |= SOSP_FREEING_READ; sounsplice(so->so_sp->ssp_soback, so, freeing); } if (isspliced(so)) { int freeing = SOSP_FREEING_READ; if (so == so->so_sp->ssp_socket) freeing |= SOSP_FREEING_WRITE; sounsplice(so, so->so_sp->ssp_socket, freeing); } #endif /* SOCKET_SPLICE */ mtx_enter(&so->so_snd.sb_mtx); sbrelease(so, &so->so_snd); mtx_leave(&so->so_snd.sb_mtx); /* * Unlocked dispose and cleanup is safe. Socket is unlinked * from everywhere. Even concurrent sotask() thread will not * call somove(). */ if (so->so_proto->pr_flags & PR_RIGHTS && so->so_proto->pr_domain->dom_dispose) (*so->so_proto->pr_domain->dom_dispose)(so->so_rcv.sb_mb); m_purge(so->so_rcv.sb_mb); if (!keep_lock) sounlock(so); #ifdef SOCKET_SPLICE if (so->so_sp) { /* Reuse splice idle, sounsplice() has been called before. */ timeout_set_proc(&so->so_sp->ssp_idleto, soreaper, so); timeout_add(&so->so_sp->ssp_idleto, 0); } else #endif /* SOCKET_SPLICE */ { pool_put(&socket_pool, so); } } static inline uint64_t solinger_nsec(struct socket *so) { if (so->so_linger == 0) return INFSLP; return SEC_TO_NSEC(so->so_linger); } /* * Close a socket on last file table reference removal. * Initiate disconnect if connected. * Free socket when disconnect complete. */ int soclose(struct socket *so, int flags) { struct socket *so2; int error = 0; solock(so); /* Revoke async IO early. There is a final revocation in sofree(). */ sigio_free(&so->so_sigio); if (so->so_state & SS_ISCONNECTED) { if (so->so_pcb == NULL) goto discard; if ((so->so_state & SS_ISDISCONNECTING) == 0) { error = sodisconnect(so); if (error) goto drop; } if (so->so_options & SO_LINGER) { if ((so->so_state & SS_ISDISCONNECTING) && (flags & MSG_DONTWAIT)) goto drop; while (so->so_state & SS_ISCONNECTED) { error = sosleep_nsec(so, &so->so_timeo, PSOCK | PCATCH, "netcls", solinger_nsec(so)); if (error) break; } } } drop: if (so->so_pcb) { int error2; error2 = pru_detach(so); if (error == 0) error = error2; } if (so->so_options & SO_ACCEPTCONN) { int persocket = solock_persocket(so); while ((so2 = TAILQ_FIRST(&so->so_q0)) != NULL) { if (persocket) solock(so2); (void) soqremque(so2, 0); if (persocket) sounlock(so); soabort(so2); if (persocket) solock(so); } while ((so2 = TAILQ_FIRST(&so->so_q)) != NULL) { if (persocket) solock(so2); (void) soqremque(so2, 1); if (persocket) sounlock(so); soabort(so2); if (persocket) solock(so); } } discard: if (so->so_state & SS_NOFDREF) panic("soclose NOFDREF: so %p, so_type %d", so, so->so_type); so->so_state |= SS_NOFDREF; /* sofree() calls sounlock(). */ sofree(so, 0); return (error); } void soabort(struct socket *so) { soassertlocked(so); pru_abort(so); } int soaccept(struct socket *so, struct mbuf *nam) { int error = 0; soassertlocked(so); if ((so->so_state & SS_NOFDREF) == 0) panic("soaccept !NOFDREF: so %p, so_type %d", so, so->so_type); so->so_state &= ~SS_NOFDREF; if ((so->so_state & SS_ISDISCONNECTED) == 0 || (so->so_proto->pr_flags & PR_ABRTACPTDIS) == 0) error = pru_accept(so, nam); else error = ECONNABORTED; return (error); } int soconnect(struct socket *so, struct mbuf *nam) { int error; soassertlocked(so); if (so->so_options & SO_ACCEPTCONN) return (EOPNOTSUPP); /* * If protocol is connection-based, can only connect once. * Otherwise, if connected, try to disconnect first. * This allows user to disconnect by connecting to, e.g., * a null address. */ if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) && ((so->so_proto->pr_flags & PR_CONNREQUIRED) || (error = sodisconnect(so)))) error = EISCONN; else error = pru_connect(so, nam); return (error); } int soconnect2(struct socket *so1, struct socket *so2) { int persocket, error; if ((persocket = solock_persocket(so1))) solock_pair(so1, so2); else solock(so1); error = pru_connect2(so1, so2); if (persocket) sounlock(so2); sounlock(so1); return (error); } int sodisconnect(struct socket *so) { int error; soassertlocked(so); if ((so->so_state & SS_ISCONNECTED) == 0) return (ENOTCONN); if (so->so_state & SS_ISDISCONNECTING) return (EALREADY); error = pru_disconnect(so); return (error); } int m_getuio(struct mbuf **, int, long, struct uio *); #define SBLOCKWAIT(f) (((f) & MSG_DONTWAIT) ? 0 : SBL_WAIT) /* * Send on a socket. * If send must go all at once and message is larger than * send buffering, then hard error. * Lock against other senders. * If must go all at once and not enough room now, then * inform user that this would block and do nothing. * Otherwise, if nonblocking, send as much as possible. * The data to be sent is described by "uio" if nonzero, * otherwise by the mbuf chain "top" (which must be null * if uio is not). Data provided in mbuf chain must be small * enough to send all at once. * * Returns nonzero on error, timeout or signal; callers * must check for short counts if EINTR/ERESTART are returned. * Data and control buffers are freed on return. */ int sosend(struct socket *so, struct mbuf *addr, struct uio *uio, struct mbuf *top, struct mbuf *control, int flags) { long space, clen = 0; size_t resid; int error; int atomic = sosendallatonce(so) || top; int dosolock = ((so->so_snd.sb_flags & SB_MTXLOCK) == 0); if (uio) resid = uio->uio_resid; else resid = top->m_pkthdr.len; /* MSG_EOR on a SOCK_STREAM socket is invalid. */ if (so->so_type == SOCK_STREAM && (flags & MSG_EOR)) { m_freem(top); m_freem(control); return (EINVAL); } if (uio && uio->uio_procp) uio->uio_procp->p_ru.ru_msgsnd++; if (control) { /* * In theory clen should be unsigned (since control->m_len is). * However, space must be signed, as it might be less than 0 * if we over-committed, and we must use a signed comparison * of space and clen. */ clen = control->m_len; /* reserve extra space for AF_UNIX's internalize */ if (so->so_proto->pr_domain->dom_family == AF_UNIX && clen >= CMSG_ALIGN(sizeof(struct cmsghdr)) && mtod(control, struct cmsghdr *)->cmsg_type == SCM_RIGHTS) clen = CMSG_SPACE( (clen - CMSG_ALIGN(sizeof(struct cmsghdr))) * (sizeof(struct fdpass) / sizeof(int))); } #define snderr(errno) { error = errno; goto release; } restart: if ((error = sblock(&so->so_snd, SBLOCKWAIT(flags))) != 0) goto out; if (dosolock) solock_shared(so); sb_mtx_lock(&so->so_snd); so->so_snd.sb_state |= SS_ISSENDING; do { if (so->so_snd.sb_state & SS_CANTSENDMORE) snderr(EPIPE); if ((error = READ_ONCE(so->so_error))) { so->so_error = 0; snderr(error); } if ((so->so_state & SS_ISCONNECTED) == 0) { if (so->so_proto->pr_flags & PR_CONNREQUIRED) { if (!(resid == 0 && clen != 0)) snderr(ENOTCONN); } else if (addr == NULL) snderr(EDESTADDRREQ); } space = sbspace(so, &so->so_snd); if (flags & MSG_OOB) space += 1024; if (so->so_proto->pr_domain->dom_family == AF_UNIX) { if (atomic && resid > so->so_snd.sb_hiwat) snderr(EMSGSIZE); } else { if (clen > so->so_snd.sb_hiwat || (atomic && resid > so->so_snd.sb_hiwat - clen)) snderr(EMSGSIZE); } if (space < clen || (space - clen < resid && (atomic || space < so->so_snd.sb_lowat))) { if (flags & MSG_DONTWAIT) snderr(EWOULDBLOCK); sbunlock(&so->so_snd); error = sbwait(so, &so->so_snd); so->so_snd.sb_state &= ~SS_ISSENDING; sb_mtx_unlock(&so->so_snd); if (dosolock) sounlock_shared(so); if (error) goto out; goto restart; } space -= clen; do { if (uio == NULL) { /* * Data is prepackaged in "top". */ resid = 0; if (flags & MSG_EOR) top->m_flags |= M_EOR; } else { sb_mtx_unlock(&so->so_snd); if (dosolock) sounlock_shared(so); error = m_getuio(&top, atomic, space, uio); if (dosolock) solock_shared(so); sb_mtx_lock(&so->so_snd); if (error) goto release; space -= top->m_pkthdr.len; resid = uio->uio_resid; if (flags & MSG_EOR) top->m_flags |= M_EOR; } if (resid == 0) so->so_snd.sb_state &= ~SS_ISSENDING; if (top && so->so_options & SO_ZEROIZE) top->m_flags |= M_ZEROIZE; sb_mtx_unlock(&so->so_snd); if (!dosolock) solock_shared(so); if (flags & MSG_OOB) error = pru_sendoob(so, top, addr, control); else error = pru_send(so, top, addr, control); if (!dosolock) sounlock_shared(so); sb_mtx_lock(&so->so_snd); clen = 0; control = NULL; top = NULL; if (error) goto release; } while (resid && space > 0); } while (resid); release: so->so_snd.sb_state &= ~SS_ISSENDING; sb_mtx_unlock(&so->so_snd); if (dosolock) sounlock_shared(so); sbunlock(&so->so_snd); out: m_freem(top); m_freem(control); return (error); } int m_getuio(struct mbuf **mp, int atomic, long space, struct uio *uio) { struct mbuf *m, *top = NULL; struct mbuf **nextp = &top; u_long len, mlen; size_t resid = uio->uio_resid; int error; do { if (top == NULL) { MGETHDR(m, M_WAIT, MT_DATA); mlen = MHLEN; m->m_pkthdr.len = 0; m->m_pkthdr.ph_ifidx = 0; } else { MGET(m, M_WAIT, MT_DATA); mlen = MLEN; } /* chain mbuf together */ *nextp = m; nextp = &m->m_next; resid = ulmin(resid, space); if (resid >= MINCLSIZE) { MCLGETL(m, M_NOWAIT, ulmin(resid, MAXMCLBYTES)); if ((m->m_flags & M_EXT) == 0) MCLGETL(m, M_NOWAIT, MCLBYTES); if ((m->m_flags & M_EXT) == 0) goto nopages; mlen = m->m_ext.ext_size; len = ulmin(mlen, resid); /* * For datagram protocols, leave room * for protocol headers in first mbuf. */ if (atomic && m == top && len < mlen - max_hdr) m->m_data += max_hdr; } else { nopages: len = ulmin(mlen, resid); /* * For datagram protocols, leave room * for protocol headers in first mbuf. */ if (atomic && m == top && len < mlen - max_hdr) m_align(m, len); } error = uiomove(mtod(m, caddr_t), len, uio); if (error) { m_freem(top); return (error); } /* adjust counters */ resid = uio->uio_resid; space -= len; m->m_len = len; top->m_pkthdr.len += len; /* Is there more space and more data? */ } while (space > 0 && resid > 0); *mp = top; return 0; } /* * Following replacement or removal of the first mbuf on the first * mbuf chain of a socket buffer, push necessary state changes back * into the socket buffer so that other consumers see the values * consistently. 'nextrecord' is the callers locally stored value of * the original value of sb->sb_mb->m_nextpkt which must be restored * when the lead mbuf changes. NOTE: 'nextrecord' may be NULL. */ void sbsync(struct sockbuf *sb, struct mbuf *nextrecord) { /* * First, update for the new value of nextrecord. If necessary, * make it the first record. */ if (sb->sb_mb != NULL) sb->sb_mb->m_nextpkt = nextrecord; else sb->sb_mb = nextrecord; /* * Now update any dependent socket buffer fields to reflect * the new state. This is an inline of SB_EMPTY_FIXUP, with * the addition of a second clause that takes care of the * case where sb_mb has been updated, but remains the last * record. */ if (sb->sb_mb == NULL) { sb->sb_mbtail = NULL; sb->sb_lastrecord = NULL; } else if (sb->sb_mb->m_nextpkt == NULL) sb->sb_lastrecord = sb->sb_mb; } /* * Implement receive operations on a socket. * We depend on the way that records are added to the sockbuf * by sbappend*. In particular, each record (mbufs linked through m_next) * must begin with an address if the protocol so specifies, * followed by an optional mbuf or mbufs containing ancillary data, * and then zero or more mbufs of data. * In order to avoid blocking network for the entire time here, we release * the solock() while doing the actual copy to user space. * Although the sockbuf is locked, new data may still be appended, * and thus we must maintain consistency of the sockbuf during that time. * * The caller may receive the data as a single mbuf chain by supplying * an mbuf **mp0 for use in returning the chain. The uio is then used * only for the count in uio_resid. */ int soreceive(struct socket *so, struct mbuf **paddr, struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, int *flagsp, socklen_t controllen) { struct mbuf *m, **mp; struct mbuf *cm; u_long len, offset, moff; int flags, error, error2, type, uio_error = 0; const struct protosw *pr = so->so_proto; struct mbuf *nextrecord; size_t resid, orig_resid = uio->uio_resid; int dosolock = ((so->so_rcv.sb_flags & SB_MTXLOCK) == 0); mp = mp0; if (paddr) *paddr = NULL; if (controlp) *controlp = NULL; if (flagsp) flags = *flagsp &~ MSG_EOR; else flags = 0; if (flags & MSG_OOB) { m = m_get(M_WAIT, MT_DATA); solock(so); error = pru_rcvoob(so, m, flags & MSG_PEEK); sounlock(so); if (error) goto bad; do { error = uiomove(mtod(m, caddr_t), ulmin(uio->uio_resid, m->m_len), uio); m = m_free(m); } while (uio->uio_resid && error == 0 && m); bad: m_freem(m); return (error); } if (mp) *mp = NULL; restart: if ((error = sblock(&so->so_rcv, SBLOCKWAIT(flags))) != 0) return (error); if (dosolock) solock_shared(so); sb_mtx_lock(&so->so_rcv); m = so->so_rcv.sb_mb; #ifdef SOCKET_SPLICE if (isspliced(so)) m = NULL; #endif /* SOCKET_SPLICE */ /* * If we have less data than requested, block awaiting more * (subject to any timeout) if: * 1. the current count is less than the low water mark, * 2. MSG_WAITALL is set, and it is possible to do the entire * receive operation at once if we block (resid <= hiwat), or * 3. MSG_DONTWAIT is not set. * If MSG_WAITALL is set but resid is larger than the receive buffer, * we have to do the receive in sections, and thus risk returning * a short count if a timeout or signal occurs after we start. */ if (m == NULL || (((flags & MSG_DONTWAIT) == 0 && so->so_rcv.sb_cc < uio->uio_resid) && (so->so_rcv.sb_cc < so->so_rcv.sb_lowat || ((flags & MSG_WAITALL) && uio->uio_resid <= so->so_rcv.sb_hiwat)) && m->m_nextpkt == NULL && (pr->pr_flags & PR_ATOMIC) == 0)) { #ifdef DIAGNOSTIC if (m == NULL && so->so_rcv.sb_cc) #ifdef SOCKET_SPLICE if (!isspliced(so)) #endif /* SOCKET_SPLICE */ panic("receive 1: so %p, so_type %d, sb_cc %lu", so, so->so_type, so->so_rcv.sb_cc); #endif if ((error2 = READ_ONCE(so->so_error))) { if (m) goto dontblock; error = error2; if ((flags & MSG_PEEK) == 0) so->so_error = 0; goto release; } if (so->so_rcv.sb_state & SS_CANTRCVMORE) { if (m) goto dontblock; else if (so->so_rcv.sb_cc == 0) goto release; } for (; m; m = m->m_next) if (m->m_type == MT_OOBDATA || (m->m_flags & M_EOR)) { m = so->so_rcv.sb_mb; goto dontblock; } if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 && (so->so_proto->pr_flags & PR_CONNREQUIRED)) { error = ENOTCONN; goto release; } if (uio->uio_resid == 0 && controlp == NULL) goto release; if (flags & MSG_DONTWAIT) { error = EWOULDBLOCK; goto release; } SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 1"); SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 1"); sbunlock(&so->so_rcv); error = sbwait(so, &so->so_rcv); sb_mtx_unlock(&so->so_rcv); if (dosolock) sounlock_shared(so); if (error) return (error); goto restart; } dontblock: /* * On entry here, m points to the first record of the socket buffer. * From this point onward, we maintain 'nextrecord' as a cache of the * pointer to the next record in the socket buffer. We must keep the * various socket buffer pointers and local stack versions of the * pointers in sync, pushing out modifications before operations that * may sleep, and re-reading them afterwards. * * Otherwise, we will race with the network stack appending new data * or records onto the socket buffer by using inconsistent/stale * versions of the field, possibly resulting in socket buffer * corruption. */ if (uio->uio_procp) uio->uio_procp->p_ru.ru_msgrcv++; KASSERT(m == so->so_rcv.sb_mb); SBLASTRECORDCHK(&so->so_rcv, "soreceive 1"); SBLASTMBUFCHK(&so->so_rcv, "soreceive 1"); nextrecord = m->m_nextpkt; if (pr->pr_flags & PR_ADDR) { #ifdef DIAGNOSTIC if (m->m_type != MT_SONAME) panic("receive 1a: so %p, so_type %d, m %p, m_type %d", so, so->so_type, m, m->m_type); #endif orig_resid = 0; if (flags & MSG_PEEK) { if (paddr) *paddr = m_copym(m, 0, m->m_len, M_NOWAIT); m = m->m_next; } else { sbfree(so, &so->so_rcv, m); if (paddr) { *paddr = m; so->so_rcv.sb_mb = m->m_next; m->m_next = NULL; m = so->so_rcv.sb_mb; } else { so->so_rcv.sb_mb = m_free(m); m = so->so_rcv.sb_mb; } sbsync(&so->so_rcv, nextrecord); } } while (m && m->m_type == MT_CONTROL && error == 0) { int skip = 0; if (flags & MSG_PEEK) { if (mtod(m, struct cmsghdr *)->cmsg_type == SCM_RIGHTS) { /* don't leak internalized SCM_RIGHTS msgs */ skip = 1; } else if (controlp) *controlp = m_copym(m, 0, m->m_len, M_NOWAIT); m = m->m_next; } else { sbfree(so, &so->so_rcv, m); so->so_rcv.sb_mb = m->m_next; m->m_nextpkt = m->m_next = NULL; cm = m; m = so->so_rcv.sb_mb; sbsync(&so->so_rcv, nextrecord); if (controlp) { if (pr->pr_domain->dom_externalize) { sb_mtx_unlock(&so->so_rcv); if (dosolock) sounlock_shared(so); error = (*pr->pr_domain->dom_externalize) (cm, controllen, flags); if (dosolock) solock_shared(so); sb_mtx_lock(&so->so_rcv); } *controlp = cm; } else { /* * Dispose of any SCM_RIGHTS message that went * through the read path rather than recv. */ if (pr->pr_domain->dom_dispose) { sb_mtx_unlock(&so->so_rcv); pr->pr_domain->dom_dispose(cm); sb_mtx_lock(&so->so_rcv); } m_free(cm); } } if (m != NULL) nextrecord = so->so_rcv.sb_mb->m_nextpkt; else nextrecord = so->so_rcv.sb_mb; if (controlp && !skip) controlp = &(*controlp)->m_next; orig_resid = 0; } /* If m is non-NULL, we have some data to read. */ if (m) { type = m->m_type; if (type == MT_OOBDATA) flags |= MSG_OOB; if (m->m_flags & M_BCAST) flags |= MSG_BCAST; if (m->m_flags & M_MCAST) flags |= MSG_MCAST; } SBLASTRECORDCHK(&so->so_rcv, "soreceive 2"); SBLASTMBUFCHK(&so->so_rcv, "soreceive 2"); moff = 0; offset = 0; while (m && uio->uio_resid > 0 && error == 0) { if (m->m_type == MT_OOBDATA) { if (type != MT_OOBDATA) break; } else if (type == MT_OOBDATA) { break; } else if (m->m_type == MT_CONTROL) { /* * If there is more than one control message in the * stream, we do a short read. Next can be received * or disposed by another system call. */ break; #ifdef DIAGNOSTIC } else if (m->m_type != MT_DATA && m->m_type != MT_HEADER) { panic("receive 3: so %p, so_type %d, m %p, m_type %d", so, so->so_type, m, m->m_type); #endif } so->so_rcv.sb_state &= ~SS_RCVATMARK; len = uio->uio_resid; if (so->so_oobmark && len > so->so_oobmark - offset) len = so->so_oobmark - offset; if (len > m->m_len - moff) len = m->m_len - moff; /* * If mp is set, just pass back the mbufs. * Otherwise copy them out via the uio, then free. * Sockbuf must be consistent here (points to current mbuf, * it points to next record) when we drop priority; * we must note any additions to the sockbuf when we * block interrupts again. */ if (mp == NULL && uio_error == 0) { SBLASTRECORDCHK(&so->so_rcv, "soreceive uiomove"); SBLASTMBUFCHK(&so->so_rcv, "soreceive uiomove"); resid = uio->uio_resid; sb_mtx_unlock(&so->so_rcv); if (dosolock) sounlock_shared(so); uio_error = uiomove(mtod(m, caddr_t) + moff, len, uio); if (dosolock) solock_shared(so); sb_mtx_lock(&so->so_rcv); if (uio_error) uio->uio_resid = resid - len; } else uio->uio_resid -= len; if (len == m->m_len - moff) { if (m->m_flags & M_EOR) flags |= MSG_EOR; if (flags & MSG_PEEK) { m = m->m_next; moff = 0; orig_resid = 0; } else { nextrecord = m->m_nextpkt; sbfree(so, &so->so_rcv, m); if (mp) { *mp = m; mp = &m->m_next; so->so_rcv.sb_mb = m = m->m_next; *mp = NULL; } else { so->so_rcv.sb_mb = m_free(m); m = so->so_rcv.sb_mb; } /* * If m != NULL, we also know that * so->so_rcv.sb_mb != NULL. */ KASSERT(so->so_rcv.sb_mb == m); if (m) { m->m_nextpkt = nextrecord; if (nextrecord == NULL) so->so_rcv.sb_lastrecord = m; } else { so->so_rcv.sb_mb = nextrecord; SB_EMPTY_FIXUP(&so->so_rcv); } SBLASTRECORDCHK(&so->so_rcv, "soreceive 3"); SBLASTMBUFCHK(&so->so_rcv, "soreceive 3"); } } else { if (flags & MSG_PEEK) { moff += len; orig_resid = 0; } else { if (mp) *mp = m_copym(m, 0, len, M_WAIT); m->m_data += len; m->m_len -= len; so->so_rcv.sb_cc -= len; so->so_rcv.sb_datacc -= len; } } if (so->so_oobmark) { if ((flags & MSG_PEEK) == 0) { so->so_oobmark -= len; if (so->so_oobmark == 0) { so->so_rcv.sb_state |= SS_RCVATMARK; break; } } else { offset += len; if (offset == so->so_oobmark) break; } } if (flags & MSG_EOR) break; /* * If the MSG_WAITALL flag is set (for non-atomic socket), * we must not quit until "uio->uio_resid == 0" or an error * termination. If a signal/timeout occurs, return * with a short count but without error. * Keep sockbuf locked against other readers. */ while (flags & MSG_WAITALL && m == NULL && uio->uio_resid > 0 && !sosendallatonce(so) && !nextrecord) { if (so->so_rcv.sb_state & SS_CANTRCVMORE || so->so_error) break; SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 2"); SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 2"); if (sbwait(so, &so->so_rcv)) { sb_mtx_unlock(&so->so_rcv); if (dosolock) sounlock_shared(so); sbunlock(&so->so_rcv); return (0); } if ((m = so->so_rcv.sb_mb) != NULL) nextrecord = m->m_nextpkt; } } if (m && pr->pr_flags & PR_ATOMIC) { flags |= MSG_TRUNC; if ((flags & MSG_PEEK) == 0) (void) sbdroprecord(so, &so->so_rcv); } if ((flags & MSG_PEEK) == 0) { if (m == NULL) { /* * First part is an inline SB_EMPTY_FIXUP(). Second * part makes sure sb_lastrecord is up-to-date if * there is still data in the socket buffer. */ so->so_rcv.sb_mb = nextrecord; if (so->so_rcv.sb_mb == NULL) { so->so_rcv.sb_mbtail = NULL; so->so_rcv.sb_lastrecord = NULL; } else if (nextrecord->m_nextpkt == NULL) so->so_rcv.sb_lastrecord = nextrecord; } SBLASTRECORDCHK(&so->so_rcv, "soreceive 4"); SBLASTMBUFCHK(&so->so_rcv, "soreceive 4"); if (pr->pr_flags & PR_WANTRCVD) { sb_mtx_unlock(&so->so_rcv); if (!dosolock) solock_shared(so); pru_rcvd(so); if (!dosolock) sounlock_shared(so); sb_mtx_lock(&so->so_rcv); } } if (orig_resid == uio->uio_resid && orig_resid && (flags & MSG_EOR) == 0 && (so->so_rcv.sb_state & SS_CANTRCVMORE) == 0) { sb_mtx_unlock(&so->so_rcv); sbunlock(&so->so_rcv); goto restart; } if (uio_error) error = uio_error; if (flagsp) *flagsp |= flags; release: sb_mtx_unlock(&so->so_rcv); if (dosolock) sounlock_shared(so); sbunlock(&so->so_rcv); return (error); } int soshutdown(struct socket *so, int how) { int error = 0; switch (how) { case SHUT_RD: sorflush(so); break; case SHUT_RDWR: sorflush(so); /* FALLTHROUGH */ case SHUT_WR: solock(so); error = pru_shutdown(so); sounlock(so); break; default: error = EINVAL; break; } return (error); } void sorflush(struct socket *so) { struct sockbuf *sb = &so->so_rcv; struct mbuf *m; const struct protosw *pr = so->so_proto; int error; error = sblock(sb, SBL_WAIT | SBL_NOINTR); /* with SBL_WAIT and SLB_NOINTR sblock() must not fail */ KASSERT(error == 0); solock_shared(so); socantrcvmore(so); mtx_enter(&sb->sb_mtx); m = sb->sb_mb; memset(&sb->sb_startzero, 0, (caddr_t)&sb->sb_endzero - (caddr_t)&sb->sb_startzero); sb->sb_timeo_nsecs = INFSLP; mtx_leave(&sb->sb_mtx); sounlock_shared(so); sbunlock(sb); if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose) (*pr->pr_domain->dom_dispose)(m); m_purge(m); } #ifdef SOCKET_SPLICE #define so_splicelen so_sp->ssp_len #define so_splicemax so_sp->ssp_max #define so_idletv so_sp->ssp_idletv #define so_idleto so_sp->ssp_idleto #define so_splicetask so_sp->ssp_task int sosplice(struct socket *so, int fd, off_t max, struct timeval *tv) { struct file *fp; struct socket *sosp; struct taskq *tq; int error = 0; if ((so->so_proto->pr_flags & PR_SPLICE) == 0) return (EPROTONOSUPPORT); if (max && max < 0) return (EINVAL); if (tv && (tv->tv_sec < 0 || !timerisvalid(tv))) return (EINVAL); /* If no fd is given, unsplice by removing existing link. */ if (fd < 0) { if ((error = sblock(&so->so_rcv, SBL_WAIT)) != 0) return (error); solock(so); if (so->so_options & SO_ACCEPTCONN) { error = EOPNOTSUPP; goto out; } if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 && (so->so_proto->pr_flags & PR_CONNREQUIRED)) { error = ENOTCONN; goto out; } if (so->so_sp && so->so_sp->ssp_socket) sounsplice(so, so->so_sp->ssp_socket, 0); out: sounlock(so); sbunlock(&so->so_rcv); return (error); } if (sosplice_taskq == NULL) { rw_enter_write(&sosplice_lock); if (sosplice_taskq == NULL) { tq = taskq_create("sosplice", 1, IPL_SOFTNET, TASKQ_MPSAFE); if (tq == NULL) { rw_exit_write(&sosplice_lock); return (ENOMEM); } /* Ensure the taskq is fully visible to other CPUs. */ membar_producer(); sosplice_taskq = tq; } rw_exit_write(&sosplice_lock); } else { /* Ensure the taskq is fully visible on this CPU. */ membar_consumer(); } /* Find sosp, the drain socket where data will be spliced into. */ if ((error = getsock(curproc, fd, &fp)) != 0) return (error); sosp = fp->f_data; if (sosp->so_proto->pr_usrreqs->pru_send != so->so_proto->pr_usrreqs->pru_send) { error = EPROTONOSUPPORT; goto frele; } if ((error = sblock(&so->so_rcv, SBL_WAIT)) != 0) goto frele; if ((error = sblock(&sosp->so_snd, SBL_WAIT)) != 0) { sbunlock(&so->so_rcv); goto frele; } solock(so); if ((so->so_options & SO_ACCEPTCONN) || (sosp->so_options & SO_ACCEPTCONN)) { error = EOPNOTSUPP; goto release; } if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 && (so->so_proto->pr_flags & PR_CONNREQUIRED)) { error = ENOTCONN; goto release; } if ((sosp->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0) { error = ENOTCONN; goto release; } if (so->so_sp == NULL) so->so_sp = pool_get(&sosplice_pool, PR_WAITOK | PR_ZERO); if (sosp->so_sp == NULL) sosp->so_sp = pool_get(&sosplice_pool, PR_WAITOK | PR_ZERO); if (so->so_sp->ssp_socket || sosp->so_sp->ssp_soback) { error = EBUSY; goto release; } /* Splice so and sosp together. */ mtx_enter(&so->so_rcv.sb_mtx); so->so_sp->ssp_socket = sosp; sosp->so_sp->ssp_soback = so; mtx_leave(&so->so_rcv.sb_mtx); so->so_splicelen = 0; so->so_splicemax = max; if (tv) so->so_idletv = *tv; else timerclear(&so->so_idletv); timeout_set_proc(&so->so_idleto, soidle, so); task_set(&so->so_splicetask, sotask, so); /* * To prevent softnet interrupt from calling somove() while * we sleep, the socket buffers are not marked as spliced yet. */ if (somove(so, M_WAIT)) { mtx_enter(&so->so_rcv.sb_mtx); so->so_rcv.sb_flags |= SB_SPLICE; mtx_leave(&so->so_rcv.sb_mtx); sosp->so_snd.sb_flags |= SB_SPLICE; } release: sounlock(so); sbunlock(&sosp->so_snd); sbunlock(&so->so_rcv); frele: FRELE(fp, curproc); return (error); } void sounsplice(struct socket *so, struct socket *sosp, int freeing) { soassertlocked(so); task_del(sosplice_taskq, &so->so_splicetask); timeout_del(&so->so_idleto); sosp->so_snd.sb_flags &= ~SB_SPLICE; mtx_enter(&so->so_rcv.sb_mtx); so->so_rcv.sb_flags &= ~SB_SPLICE; so->so_sp->ssp_socket = sosp->so_sp->ssp_soback = NULL; mtx_leave(&so->so_rcv.sb_mtx); /* Do not wakeup a socket that is about to be freed. */ if ((freeing & SOSP_FREEING_READ) == 0 && soreadable(so)) sorwakeup(so); if ((freeing & SOSP_FREEING_WRITE) == 0 && sowriteable(sosp)) sowwakeup(sosp); } void soidle(void *arg) { struct socket *so = arg; solock(so); if (so->so_rcv.sb_flags & SB_SPLICE) { so->so_error = ETIMEDOUT; sounsplice(so, so->so_sp->ssp_socket, 0); } sounlock(so); } void sotask(void *arg) { struct socket *so = arg; solock(so); if (so->so_rcv.sb_flags & SB_SPLICE) { /* * We may not sleep here as sofree() and unsplice() may be * called from softnet interrupt context. This would remove * the socket during somove(). */ somove(so, M_DONTWAIT); } sounlock(so); /* Avoid user land starvation. */ yield(); } /* * The socket splicing task or idle timeout may sleep while grabbing the net * lock. As sofree() can be called anytime, sotask() or soidle() could access * the socket memory of a freed socket after wakeup. So delay the pool_put() * after all pending socket splicing tasks or timeouts have finished. Do this * by scheduling it on the same threads. */ void soreaper(void *arg) { struct socket *so = arg; /* Reuse splice task, sounsplice() has been called before. */ task_set(&so->so_sp->ssp_task, soput, so); task_add(sosplice_taskq, &so->so_sp->ssp_task); } void soput(void *arg) { struct socket *so = arg; pool_put(&sosplice_pool, so->so_sp); pool_put(&socket_pool, so); } /* * Move data from receive buffer of spliced source socket to send * buffer of drain socket. Try to move as much as possible in one * big chunk. It is a TCP only implementation. * Return value 0 means splicing has been finished, 1 continue. */ int somove(struct socket *so, int wait) { struct socket *sosp = so->so_sp->ssp_socket; struct mbuf *m, **mp, *nextrecord; u_long len, off, oobmark; long space; int error = 0, maxreached = 0; unsigned int rcvstate; soassertlocked(so); nextpkt: if (so->so_error) { error = so->so_error; goto release; } if (sosp->so_snd.sb_state & SS_CANTSENDMORE) { error = EPIPE; goto release; } if (sosp->so_error && sosp->so_error != ETIMEDOUT && sosp->so_error != EFBIG && sosp->so_error != ELOOP) { error = sosp->so_error; goto release; } if ((sosp->so_state & SS_ISCONNECTED) == 0) goto release; /* Calculate how many bytes can be copied now. */ len = so->so_rcv.sb_datacc; if (so->so_splicemax) { KASSERT(so->so_splicelen < so->so_splicemax); if (so->so_splicemax <= so->so_splicelen + len) { len = so->so_splicemax - so->so_splicelen; maxreached = 1; } } space = sbspace(sosp, &sosp->so_snd); if (so->so_oobmark && so->so_oobmark < len && so->so_oobmark < space + 1024) space += 1024; if (space <= 0) { maxreached = 0; goto release; } if (space < len) { maxreached = 0; if (space < sosp->so_snd.sb_lowat) goto release; len = space; } sosp->so_snd.sb_state |= SS_ISSENDING; SBLASTRECORDCHK(&so->so_rcv, "somove 1"); SBLASTMBUFCHK(&so->so_rcv, "somove 1"); m = so->so_rcv.sb_mb; if (m == NULL) goto release; nextrecord = m->m_nextpkt; /* Drop address and control information not used with splicing. */ if (so->so_proto->pr_flags & PR_ADDR) { #ifdef DIAGNOSTIC if (m->m_type != MT_SONAME) panic("somove soname: so %p, so_type %d, m %p, " "m_type %d", so, so->so_type, m, m->m_type); #endif m = m->m_next; } while (m && m->m_type == MT_CONTROL) m = m->m_next; if (m == NULL) { sbdroprecord(so, &so->so_rcv); if (so->so_proto->pr_flags & PR_WANTRCVD) pru_rcvd(so); goto nextpkt; } /* * By splicing sockets connected to localhost, userland might create a * loop. Dissolve splicing with error if loop is detected by counter. * * If we deal with looped broadcast/multicast packet we bail out with * no error to suppress splice termination. */ if ((m->m_flags & M_PKTHDR) && ((m->m_pkthdr.ph_loopcnt++ >= M_MAXLOOP) || ((m->m_flags & M_LOOP) && (m->m_flags & (M_BCAST|M_MCAST))))) { error = ELOOP; goto release; } if (so->so_proto->pr_flags & PR_ATOMIC) { if ((m->m_flags & M_PKTHDR) == 0) panic("somove !PKTHDR: so %p, so_type %d, m %p, " "m_type %d", so, so->so_type, m, m->m_type); if (sosp->so_snd.sb_hiwat < m->m_pkthdr.len) { error = EMSGSIZE; goto release; } if (len < m->m_pkthdr.len) goto release; if (m->m_pkthdr.len < len) { maxreached = 0; len = m->m_pkthdr.len; } /* * Throw away the name mbuf after it has been assured * that the whole first record can be processed. */ m = so->so_rcv.sb_mb; sbfree(so, &so->so_rcv, m); so->so_rcv.sb_mb = m_free(m); sbsync(&so->so_rcv, nextrecord); } /* * Throw away the control mbufs after it has been assured * that the whole first record can be processed. */ m = so->so_rcv.sb_mb; while (m && m->m_type == MT_CONTROL) { sbfree(so, &so->so_rcv, m); so->so_rcv.sb_mb = m_free(m); m = so->so_rcv.sb_mb; sbsync(&so->so_rcv, nextrecord); } SBLASTRECORDCHK(&so->so_rcv, "somove 2"); SBLASTMBUFCHK(&so->so_rcv, "somove 2"); /* Take at most len mbufs out of receive buffer. */ for (off = 0, mp = &m; off <= len && *mp; off += (*mp)->m_len, mp = &(*mp)->m_next) { u_long size = len - off; #ifdef DIAGNOSTIC if ((*mp)->m_type != MT_DATA && (*mp)->m_type != MT_HEADER) panic("somove type: so %p, so_type %d, m %p, " "m_type %d", so, so->so_type, *mp, (*mp)->m_type); #endif if ((*mp)->m_len > size) { /* * Move only a partial mbuf at maximum splice length or * if the drain buffer is too small for this large mbuf. */ if (!maxreached && so->so_snd.sb_datacc > 0) { len -= size; break; } *mp = m_copym(so->so_rcv.sb_mb, 0, size, wait); if (*mp == NULL) { len -= size; break; } so->so_rcv.sb_mb->m_data += size; so->so_rcv.sb_mb->m_len -= size; so->so_rcv.sb_cc -= size; so->so_rcv.sb_datacc -= size; } else { *mp = so->so_rcv.sb_mb; sbfree(so, &so->so_rcv, *mp); so->so_rcv.sb_mb = (*mp)->m_next; sbsync(&so->so_rcv, nextrecord); } } *mp = NULL; SBLASTRECORDCHK(&so->so_rcv, "somove 3"); SBLASTMBUFCHK(&so->so_rcv, "somove 3"); SBCHECK(so, &so->so_rcv); if (m == NULL) goto release; m->m_nextpkt = NULL; if (m->m_flags & M_PKTHDR) { m_resethdr(m); m->m_pkthdr.len = len; } /* Send window update to source peer as receive buffer has changed. */ if (so->so_proto->pr_flags & PR_WANTRCVD) pru_rcvd(so); /* Receive buffer did shrink by len bytes, adjust oob. */ mtx_enter(&so->so_rcv.sb_mtx); rcvstate = so->so_rcv.sb_state; so->so_rcv.sb_state &= ~SS_RCVATMARK; oobmark = so->so_oobmark; so->so_oobmark = oobmark > len ? oobmark - len : 0; if (oobmark) { if (oobmark == len) so->so_rcv.sb_state |= SS_RCVATMARK; if (oobmark >= len) oobmark = 0; } mtx_leave(&so->so_rcv.sb_mtx); /* * Handle oob data. If any malloc fails, ignore error. * TCP urgent data is not very reliable anyway. */ while (((rcvstate & SS_RCVATMARK) || oobmark) && (so->so_options & SO_OOBINLINE)) { struct mbuf *o = NULL; if (rcvstate & SS_RCVATMARK) { o = m_get(wait, MT_DATA); rcvstate &= ~SS_RCVATMARK; } else if (oobmark) { o = m_split(m, oobmark, wait); if (o) { error = pru_send(sosp, m, NULL, NULL); if (error) { if (sosp->so_snd.sb_state & SS_CANTSENDMORE) error = EPIPE; m_freem(o); goto release; } len -= oobmark; so->so_splicelen += oobmark; m = o; o = m_get(wait, MT_DATA); } oobmark = 0; } if (o) { o->m_len = 1; *mtod(o, caddr_t) = *mtod(m, caddr_t); error = pru_sendoob(sosp, o, NULL, NULL); if (error) { if (sosp->so_snd.sb_state & SS_CANTSENDMORE) error = EPIPE; m_freem(m); goto release; } len -= 1; so->so_splicelen += 1; if (oobmark) { oobmark -= 1; if (oobmark == 0) rcvstate |= SS_RCVATMARK; } m_adj(m, 1); } } /* Append all remaining data to drain socket. */ if (so->so_rcv.sb_cc == 0 || maxreached) sosp->so_snd.sb_state &= ~SS_ISSENDING; error = pru_send(sosp, m, NULL, NULL); if (error) { if (sosp->so_snd.sb_state & SS_CANTSENDMORE) error = EPIPE; goto release; } so->so_splicelen += len; /* Move several packets if possible. */ if (!maxreached && nextrecord) goto nextpkt; release: sosp->so_snd.sb_state &= ~SS_ISSENDING; if (!error && maxreached && so->so_splicemax == so->so_splicelen) error = EFBIG; if (error) so->so_error = error; if (((so->so_rcv.sb_state & SS_CANTRCVMORE) && so->so_rcv.sb_cc == 0) || (sosp->so_snd.sb_state & SS_CANTSENDMORE) || maxreached || error) { sounsplice(so, sosp, 0); return (0); } if (timerisset(&so->so_idletv)) timeout_add_tv(&so->so_idleto, &so->so_idletv); return (1); } #endif /* SOCKET_SPLICE */ void sorwakeup(struct socket *so) { if ((so->so_rcv.sb_flags & SB_MTXLOCK) == 0) soassertlocked_readonly(so); #ifdef SOCKET_SPLICE if (so->so_rcv.sb_flags & SB_SPLICE) { /* * TCP has a sendbuffer that can handle multiple packets * at once. So queue the stream a bit to accumulate data. * The sosplice thread will call somove() later and send * the packets calling tcp_output() only once. * In the UDP case, send out the packets immediately. * Using a thread would make things slower. */ if (so->so_proto->pr_flags & PR_WANTRCVD) task_add(sosplice_taskq, &so->so_splicetask); else somove(so, M_DONTWAIT); } if (isspliced(so)) return; #endif sowakeup(so, &so->so_rcv); if (so->so_upcall) (*(so->so_upcall))(so, so->so_upcallarg, M_DONTWAIT); } void sowwakeup(struct socket *so) { if ((so->so_snd.sb_flags & SB_MTXLOCK) == 0) soassertlocked_readonly(so); #ifdef SOCKET_SPLICE if (so->so_snd.sb_flags & SB_SPLICE) task_add(sosplice_taskq, &so->so_sp->ssp_soback->so_splicetask); if (issplicedback(so)) return; #endif sowakeup(so, &so->so_snd); } int sosetopt(struct socket *so, int level, int optname, struct mbuf *m) { int error = 0; if (level != SOL_SOCKET) { if (so->so_proto->pr_ctloutput) { solock(so); error = (*so->so_proto->pr_ctloutput)(PRCO_SETOPT, so, level, optname, m); sounlock(so); return (error); } error = ENOPROTOOPT; } else { switch (optname) { case SO_LINGER: if (m == NULL || m->m_len != sizeof (struct linger) || mtod(m, struct linger *)->l_linger < 0 || mtod(m, struct linger *)->l_linger > SHRT_MAX) return (EINVAL); solock(so); so->so_linger = mtod(m, struct linger *)->l_linger; if (*mtod(m, int *)) so->so_options |= optname; else so->so_options &= ~optname; sounlock(so); break; case SO_BINDANY: if ((error = suser(curproc)) != 0) /* XXX */ return (error); /* FALLTHROUGH */ case SO_DEBUG: case SO_KEEPALIVE: case SO_USELOOPBACK: case SO_BROADCAST: case SO_REUSEADDR: case SO_REUSEPORT: case SO_OOBINLINE: case SO_TIMESTAMP: case SO_ZEROIZE: if (m == NULL || m->m_len < sizeof (int)) return (EINVAL); solock(so); if (*mtod(m, int *)) so->so_options |= optname; else so->so_options &= ~optname; sounlock(so); break; case SO_DONTROUTE: if (m == NULL || m->m_len < sizeof (int)) return (EINVAL); if (*mtod(m, int *)) error = EOPNOTSUPP; break; case SO_SNDBUF: case SO_RCVBUF: case SO_SNDLOWAT: case SO_RCVLOWAT: { struct sockbuf *sb = (optname == SO_SNDBUF || optname == SO_SNDLOWAT ? &so->so_snd : &so->so_rcv); u_long cnt; if (m == NULL || m->m_len < sizeof (int)) return (EINVAL); cnt = *mtod(m, int *); if ((long)cnt <= 0) cnt = 1; if (((sb->sb_flags & SB_MTXLOCK) == 0)) solock(so); mtx_enter(&sb->sb_mtx); switch (optname) { case SO_SNDBUF: case SO_RCVBUF: if (sb->sb_state & (SS_CANTSENDMORE | SS_CANTRCVMORE)) { error = EINVAL; break; } if (sbcheckreserve(cnt, sb->sb_wat) || sbreserve(so, sb, cnt)) { error = ENOBUFS; break; } sb->sb_wat = cnt; break; case SO_SNDLOWAT: case SO_RCVLOWAT: sb->sb_lowat = (cnt > sb->sb_hiwat) ? sb->sb_hiwat : cnt; break; } mtx_leave(&sb->sb_mtx); if (((sb->sb_flags & SB_MTXLOCK) == 0)) sounlock(so); break; } case SO_SNDTIMEO: case SO_RCVTIMEO: { struct sockbuf *sb = (optname == SO_SNDTIMEO ? &so->so_snd : &so->so_rcv); struct timeval tv; uint64_t nsecs; if (m == NULL || m->m_len < sizeof (tv)) return (EINVAL); memcpy(&tv, mtod(m, struct timeval *), sizeof tv); if (!timerisvalid(&tv)) return (EINVAL); nsecs = TIMEVAL_TO_NSEC(&tv); if (nsecs == UINT64_MAX) return (EDOM); if (nsecs == 0) nsecs = INFSLP; mtx_enter(&sb->sb_mtx); sb->sb_timeo_nsecs = nsecs; mtx_leave(&sb->sb_mtx); break; } case SO_RTABLE: if (so->so_proto->pr_domain && so->so_proto->pr_domain->dom_protosw && so->so_proto->pr_ctloutput) { const struct domain *dom = so->so_proto->pr_domain; level = dom->dom_protosw->pr_protocol; solock(so); error = (*so->so_proto->pr_ctloutput) (PRCO_SETOPT, so, level, optname, m); sounlock(so); } else error = ENOPROTOOPT; break; #ifdef SOCKET_SPLICE case SO_SPLICE: if (m == NULL) { error = sosplice(so, -1, 0, NULL); } else if (m->m_len < sizeof(int)) { error = EINVAL; } else if (m->m_len < sizeof(struct splice)) { error = sosplice(so, *mtod(m, int *), 0, NULL); } else { error = sosplice(so, mtod(m, struct splice *)->sp_fd, mtod(m, struct splice *)->sp_max, &mtod(m, struct splice *)->sp_idle); } break; #endif /* SOCKET_SPLICE */ default: error = ENOPROTOOPT; break; } } return (error); } int sogetopt(struct socket *so, int level, int optname, struct mbuf *m) { int error = 0; if (level != SOL_SOCKET) { if (so->so_proto->pr_ctloutput) { m->m_len = 0; solock(so); error = (*so->so_proto->pr_ctloutput)(PRCO_GETOPT, so, level, optname, m); sounlock(so); return (error); } else return (ENOPROTOOPT); } else { m->m_len = sizeof (int); switch (optname) { case SO_LINGER: m->m_len = sizeof (struct linger); solock_shared(so); mtod(m, struct linger *)->l_onoff = so->so_options & SO_LINGER; mtod(m, struct linger *)->l_linger = so->so_linger; sounlock_shared(so); break; case SO_BINDANY: case SO_USELOOPBACK: case SO_DEBUG: case SO_KEEPALIVE: case SO_REUSEADDR: case SO_REUSEPORT: case SO_BROADCAST: case SO_OOBINLINE: case SO_ACCEPTCONN: case SO_TIMESTAMP: case SO_ZEROIZE: *mtod(m, int *) = so->so_options & optname; break; case SO_DONTROUTE: *mtod(m, int *) = 0; break; case SO_TYPE: *mtod(m, int *) = so->so_type; break; case SO_ERROR: solock(so); *mtod(m, int *) = so->so_error; so->so_error = 0; sounlock(so); break; case SO_DOMAIN: *mtod(m, int *) = so->so_proto->pr_domain->dom_family; break; case SO_PROTOCOL: *mtod(m, int *) = so->so_proto->pr_protocol; break; case SO_SNDBUF: *mtod(m, int *) = so->so_snd.sb_hiwat; break; case SO_RCVBUF: *mtod(m, int *) = so->so_rcv.sb_hiwat; break; case SO_SNDLOWAT: *mtod(m, int *) = so->so_snd.sb_lowat; break; case SO_RCVLOWAT: *mtod(m, int *) = so->so_rcv.sb_lowat; break; case SO_SNDTIMEO: case SO_RCVTIMEO: { struct sockbuf *sb = (optname == SO_SNDTIMEO ? &so->so_snd : &so->so_rcv); struct timeval tv; uint64_t nsecs; mtx_enter(&sb->sb_mtx); nsecs = sb->sb_timeo_nsecs; mtx_leave(&sb->sb_mtx); m->m_len = sizeof(struct timeval); memset(&tv, 0, sizeof(tv)); if (nsecs != INFSLP) NSEC_TO_TIMEVAL(nsecs, &tv); memcpy(mtod(m, struct timeval *), &tv, sizeof tv); break; } case SO_RTABLE: if (so->so_proto->pr_domain && so->so_proto->pr_domain->dom_protosw && so->so_proto->pr_ctloutput) { const struct domain *dom = so->so_proto->pr_domain; level = dom->dom_protosw->pr_protocol; solock(so); error = (*so->so_proto->pr_ctloutput) (PRCO_GETOPT, so, level, optname, m); sounlock(so); if (error) return (error); break; } return (ENOPROTOOPT); #ifdef SOCKET_SPLICE case SO_SPLICE: { off_t len; m->m_len = sizeof(off_t); solock_shared(so); len = so->so_sp ? so->so_sp->ssp_len : 0; sounlock_shared(so); memcpy(mtod(m, off_t *), &len, sizeof(off_t)); break; } #endif /* SOCKET_SPLICE */ case SO_PEERCRED: if (so->so_proto->pr_protocol == AF_UNIX) { struct unpcb *unp = sotounpcb(so); solock(so); if (unp->unp_flags & UNP_FEIDS) { m->m_len = sizeof(unp->unp_connid); memcpy(mtod(m, caddr_t), &(unp->unp_connid), m->m_len); sounlock(so); break; } sounlock(so); return (ENOTCONN); } return (EOPNOTSUPP); default: return (ENOPROTOOPT); } return (0); } } void sohasoutofband(struct socket *so) { pgsigio(&so->so_sigio, SIGURG, 0); knote(&so->so_rcv.sb_klist, 0); } void sofilt_lock(struct socket *so, struct sockbuf *sb) { switch (so->so_proto->pr_domain->dom_family) { case PF_INET: case PF_INET6: NET_LOCK_SHARED(); break; default: rw_enter_write(&so->so_lock); break; } mtx_enter(&sb->sb_mtx); } void sofilt_unlock(struct socket *so, struct sockbuf *sb) { mtx_leave(&sb->sb_mtx); switch (so->so_proto->pr_domain->dom_family) { case PF_INET: case PF_INET6: NET_UNLOCK_SHARED(); break; default: rw_exit_write(&so->so_lock); break; } } int soo_kqfilter(struct file *fp, struct knote *kn) { struct socket *so = kn->kn_fp->f_data; struct sockbuf *sb; switch (kn->kn_filter) { case EVFILT_READ: kn->kn_fop = &soread_filtops; sb = &so->so_rcv; break; case EVFILT_WRITE: kn->kn_fop = &sowrite_filtops; sb = &so->so_snd; break; case EVFILT_EXCEPT: kn->kn_fop = &soexcept_filtops; sb = &so->so_rcv; break; default: return (EINVAL); } klist_insert(&sb->sb_klist, kn); return (0); } void filt_sordetach(struct knote *kn) { struct socket *so = kn->kn_fp->f_data; klist_remove(&so->so_rcv.sb_klist, kn); } int filt_soread(struct knote *kn, long hint) { struct socket *so = kn->kn_fp->f_data; int rv = 0; MUTEX_ASSERT_LOCKED(&so->so_rcv.sb_mtx); if ((so->so_rcv.sb_flags & SB_MTXLOCK) == 0) soassertlocked_readonly(so); if (so->so_options & SO_ACCEPTCONN) { if (so->so_rcv.sb_flags & SB_MTXLOCK) soassertlocked_readonly(so); kn->kn_data = so->so_qlen; rv = (kn->kn_data != 0); if (kn->kn_flags & (__EV_POLL | __EV_SELECT)) { if (so->so_state & SS_ISDISCONNECTED) { kn->kn_flags |= __EV_HUP; rv = 1; } else { rv = soreadable(so); } } return rv; } kn->kn_data = so->so_rcv.sb_cc; #ifdef SOCKET_SPLICE if (isspliced(so)) { rv = 0; } else #endif /* SOCKET_SPLICE */ if (so->so_rcv.sb_state & SS_CANTRCVMORE) { kn->kn_flags |= EV_EOF; if (kn->kn_flags & __EV_POLL) { if (so->so_state & SS_ISDISCONNECTED) kn->kn_flags |= __EV_HUP; } kn->kn_fflags = so->so_error; rv = 1; } else if (so->so_error) { rv = 1; } else if (kn->kn_sfflags & NOTE_LOWAT) { rv = (kn->kn_data >= kn->kn_sdata); } else { rv = (kn->kn_data >= so->so_rcv.sb_lowat); } return rv; } void filt_sowdetach(struct knote *kn) { struct socket *so = kn->kn_fp->f_data; klist_remove(&so->so_snd.sb_klist, kn); } int filt_sowrite(struct knote *kn, long hint) { struct socket *so = kn->kn_fp->f_data; int rv; MUTEX_ASSERT_LOCKED(&so->so_snd.sb_mtx); if ((so->so_snd.sb_flags & SB_MTXLOCK) == 0) soassertlocked_readonly(so); kn->kn_data = sbspace(so, &so->so_snd); if (so->so_snd.sb_state & SS_CANTSENDMORE) { kn->kn_flags |= EV_EOF; if (kn->kn_flags & __EV_POLL) { if (so->so_state & SS_ISDISCONNECTED) kn->kn_flags |= __EV_HUP; } kn->kn_fflags = so->so_error; rv = 1; } else if (so->so_error) { rv = 1; } else if (((so->so_state & SS_ISCONNECTED) == 0) && (so->so_proto->pr_flags & PR_CONNREQUIRED)) { rv = 0; } else if (kn->kn_sfflags & NOTE_LOWAT) { rv = (kn->kn_data >= kn->kn_sdata); } else { rv = (kn->kn_data >= so->so_snd.sb_lowat); } return (rv); } int filt_soexcept(struct knote *kn, long hint) { struct socket *so = kn->kn_fp->f_data; int rv = 0; MUTEX_ASSERT_LOCKED(&so->so_rcv.sb_mtx); if ((so->so_rcv.sb_flags & SB_MTXLOCK) == 0) soassertlocked_readonly(so); #ifdef SOCKET_SPLICE if (isspliced(so)) { rv = 0; } else #endif /* SOCKET_SPLICE */ if (kn->kn_sfflags & NOTE_OOB) { if (so->so_oobmark || (so->so_rcv.sb_state & SS_RCVATMARK)) { kn->kn_fflags |= NOTE_OOB; kn->kn_data -= so->so_oobmark; rv = 1; } } if (kn->kn_flags & __EV_POLL) { if (so->so_state & SS_ISDISCONNECTED) { kn->kn_flags |= __EV_HUP; rv = 1; } } return rv; } int filt_sowmodify(struct kevent *kev, struct knote *kn) { struct socket *so = kn->kn_fp->f_data; int rv; sofilt_lock(so, &so->so_snd); rv = knote_modify(kev, kn); sofilt_unlock(so, &so->so_snd); return (rv); } int filt_sowprocess(struct knote *kn, struct kevent *kev) { struct socket *so = kn->kn_fp->f_data; int rv; sofilt_lock(so, &so->so_snd); rv = knote_process(kn, kev); sofilt_unlock(so, &so->so_snd); return (rv); } int filt_sormodify(struct kevent *kev, struct knote *kn) { struct socket *so = kn->kn_fp->f_data; int rv; sofilt_lock(so, &so->so_rcv); rv = knote_modify(kev, kn); sofilt_unlock(so, &so->so_rcv); return (rv); } int filt_sorprocess(struct knote *kn, struct kevent *kev) { struct socket *so = kn->kn_fp->f_data; int rv; sofilt_lock(so, &so->so_rcv); rv = knote_process(kn, kev); sofilt_unlock(so, &so->so_rcv); return (rv); } #ifdef DDB void sobuf_print(struct sockbuf *, int (*)(const char *, ...) __attribute__((__format__(__kprintf__,1,2)))); void sobuf_print(struct sockbuf *sb, int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2)))) { (*pr)("\tsb_cc: %lu\n", sb->sb_cc); (*pr)("\tsb_datacc: %lu\n", sb->sb_datacc); (*pr)("\tsb_hiwat: %lu\n", sb->sb_hiwat); (*pr)("\tsb_wat: %lu\n", sb->sb_wat); (*pr)("\tsb_mbcnt: %lu\n", sb->sb_mbcnt); (*pr)("\tsb_mbmax: %lu\n", sb->sb_mbmax); (*pr)("\tsb_lowat: %ld\n", sb->sb_lowat); (*pr)("\tsb_mb: %p\n", sb->sb_mb); (*pr)("\tsb_mbtail: %p\n", sb->sb_mbtail); (*pr)("\tsb_lastrecord: %p\n", sb->sb_lastrecord); (*pr)("\tsb_sel: ...\n"); (*pr)("\tsb_flags: %04x\n", sb->sb_flags); (*pr)("\tsb_state: %04x\n", sb->sb_state); (*pr)("\tsb_timeo_nsecs: %llu\n", sb->sb_timeo_nsecs); } void so_print(void *v, int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2)))) { struct socket *so = v; (*pr)("socket %p\n", so); (*pr)("so_type: %i\n", so->so_type); (*pr)("so_options: 0x%04x\n", so->so_options); /* %b */ (*pr)("so_linger: %i\n", so->so_linger); (*pr)("so_state: 0x%04x\n", so->so_state); (*pr)("so_pcb: %p\n", so->so_pcb); (*pr)("so_proto: %p\n", so->so_proto); (*pr)("so_sigio: %p\n", so->so_sigio.sir_sigio); (*pr)("so_head: %p\n", so->so_head); (*pr)("so_onq: %p\n", so->so_onq); (*pr)("so_q0: @%p first: %p\n", &so->so_q0, TAILQ_FIRST(&so->so_q0)); (*pr)("so_q: @%p first: %p\n", &so->so_q, TAILQ_FIRST(&so->so_q)); (*pr)("so_eq: next: %p\n", TAILQ_NEXT(so, so_qe)); (*pr)("so_q0len: %i\n", so->so_q0len); (*pr)("so_qlen: %i\n", so->so_qlen); (*pr)("so_qlimit: %i\n", so->so_qlimit); (*pr)("so_timeo: %i\n", so->so_timeo); (*pr)("so_obmark: %lu\n", so->so_oobmark); (*pr)("so_sp: %p\n", so->so_sp); if (so->so_sp != NULL) { (*pr)("\tssp_socket: %p\n", so->so_sp->ssp_socket); (*pr)("\tssp_soback: %p\n", so->so_sp->ssp_soback); (*pr)("\tssp_len: %lld\n", (unsigned long long)so->so_sp->ssp_len); (*pr)("\tssp_max: %lld\n", (unsigned long long)so->so_sp->ssp_max); (*pr)("\tssp_idletv: %lld %ld\n", so->so_sp->ssp_idletv.tv_sec, so->so_sp->ssp_idletv.tv_usec); (*pr)("\tssp_idleto: %spending (@%i)\n", timeout_pending(&so->so_sp->ssp_idleto) ? "" : "not ", so->so_sp->ssp_idleto.to_time); } (*pr)("so_rcv:\n"); sobuf_print(&so->so_rcv, pr); (*pr)("so_snd:\n"); sobuf_print(&so->so_snd, pr); (*pr)("so_upcall: %p so_upcallarg: %p\n", so->so_upcall, so->so_upcallarg); (*pr)("so_euid: %d so_ruid: %d\n", so->so_euid, so->so_ruid); (*pr)("so_egid: %d so_rgid: %d\n", so->so_egid, so->so_rgid); (*pr)("so_cpid: %d\n", so->so_cpid); } #endif
8 12 8 8 8 1 3 10 6 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 /* $OpenBSD: clock_subr.c,v 1.6 2016/08/26 07:09:56 guenther Exp $ */ /* $NetBSD: clock_subr.c,v 1.3 1997/03/15 18:11:16 is Exp $ */ /* * Copyright (c) 1988 University of Utah. * Copyright (c) 1982, 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: Utah $Hdr: clock.c 1.18 91/01/21$ * * @(#)clock.c 8.2 (Berkeley) 1/12/94 */ /* * Generic routines to convert between a POSIX date * (seconds since 1/1/1970) and yr/mo/day/hr/min/sec * Derived from arch/hp300/hp300/clock.c */ #include <sys/types.h> #include <sys/time.h> #include <sys/systm.h> static inline int leapyear(int year); #define FEBRUARY 2 #define days_in_year(a) (leapyear(a) ? 366 : 365) #define days_in_month(a) (month_days[(a) - 1]) static const int month_days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; /* * This inline avoids some unnecessary modulo operations * as compared with the usual macro: * ( ((year % 4) == 0 && * (year % 100) != 0) || * ((year % 400) == 0) ) * It is otherwise equivalent. */ static inline int leapyear(int year) { int rv = 0; if ((year & 3) == 0) { rv = 1; if ((year % 100) == 0) { rv = 0; if ((year % 400) == 0) rv = 1; } } return (rv); } time_t clock_ymdhms_to_secs(struct clock_ymdhms *dt) { time_t secs; int i, year, days; year = dt->dt_year; /* * Compute days since start of time. * First from years, then from months. */ days = 0; for (i = POSIX_BASE_YEAR; i < year; i++) days += days_in_year(i); if (leapyear(year) && dt->dt_mon > FEBRUARY) days++; /* Months */ for (i = 1; i < dt->dt_mon; i++) days += days_in_month(i); days += (dt->dt_day - 1); /* Add hours, minutes, seconds. */ secs = (time_t)((days * 24 + dt->dt_hour) * 60 + dt->dt_min) * 60 + dt->dt_sec; return (secs); } /* This function uses a copy of month_days[] */ #undef days_in_month #define days_in_month(a) (mthdays[(a) - 1]) void clock_secs_to_ymdhms(time_t secs, struct clock_ymdhms *dt) { int mthdays[12]; int i, days; int rsec; /* remainder seconds */ memcpy(mthdays, month_days, sizeof(mthdays)); days = secs / SECDAY; rsec = secs % SECDAY; /* Day of week (Note: 1/1/1970 was a Thursday) */ dt->dt_wday = (days + 4) % 7; /* Subtract out whole years, counting them in i. */ for (i = POSIX_BASE_YEAR; days >= days_in_year(i); i++) days -= days_in_year(i); dt->dt_year = i; /* Subtract out whole months, counting them in i. */ if (leapyear(i)) days_in_month(FEBRUARY) = 29; for (i = 1; days >= days_in_month(i); i++) days -= days_in_month(i); dt->dt_mon = i; /* Days are what is left over (+1) from all that. */ dt->dt_day = days + 1; /* Hours, minutes, seconds are easy */ dt->dt_hour = rsec / 3600; rsec = rsec % 3600; dt->dt_min = rsec / 60; rsec = rsec % 60; dt->dt_sec = rsec; }
71 71 71 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 /* $OpenBSD: vfs_sync.c,v 1.72 2024/05/13 11:17:40 semarie Exp $ */ /* * Portions of this code are: * * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Syncer daemon */ #include <sys/queue.h> #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/mount.h> #include <sys/vnode.h> #include <sys/lock.h> #include <sys/malloc.h> #include <sys/time.h> /* * The workitem queue. */ #define SYNCER_MAXDELAY 32 /* maximum sync delay time */ #define SYNCER_DEFAULT 30 /* default sync delay time */ int syncer_maxdelay = SYNCER_MAXDELAY; /* maximum delay time */ int syncdelay = SYNCER_DEFAULT; /* time to delay syncing vnodes */ int syncer_delayno = 0; long syncer_mask; LIST_HEAD(synclist, vnode); static struct synclist *syncer_workitem_pending; struct proc *syncerproc; int syncer_chan; /* * The workitem queue. * * It is useful to delay writes of file data and filesystem metadata * for tens of seconds so that quickly created and deleted files need * not waste disk bandwidth being created and removed. To realize this, * we append vnodes to a "workitem" queue. When running with a soft * updates implementation, most pending metadata dependencies should * not wait for more than a few seconds. Thus, mounted block devices * are delayed only about half the time that file data is delayed. * Similarly, directory updates are more critical, so are only delayed * about a third the time that file data is delayed. Thus, there are * SYNCER_MAXDELAY queues that are processed round-robin at a rate of * one each second (driven off the filesystem syncer process). The * syncer_delayno variable indicates the next queue that is to be processed. * Items that need to be processed soon are placed in this queue: * * syncer_workitem_pending[syncer_delayno] * * A delay of fifteen seconds is done by placing the request fifteen * entries later in the queue: * * syncer_workitem_pending[(syncer_delayno + 15) & syncer_mask] * */ void vn_initialize_syncerd(void) { syncer_workitem_pending = hashinit(syncer_maxdelay, M_VNODE, M_WAITOK, &syncer_mask); syncer_maxdelay = syncer_mask + 1; } /* * Add an item to the syncer work queue. */ void vn_syncer_add_to_worklist(struct vnode *vp, int delay) { int s, slot; if (delay > syncer_maxdelay - 2) delay = syncer_maxdelay - 2; slot = (syncer_delayno + delay) & syncer_mask; s = splbio(); if (vp->v_bioflag & VBIOONSYNCLIST) LIST_REMOVE(vp, v_synclist); vp->v_bioflag |= VBIOONSYNCLIST; LIST_INSERT_HEAD(&syncer_workitem_pending[slot], vp, v_synclist); splx(s); } /* * System filesystem synchronizer daemon. */ void syncer_thread(void *arg) { uint64_t elapsed, start; struct proc *p = curproc; struct synclist *slp; struct vnode *vp; int s; for (;;) { start = getnsecuptime(); /* * Push files whose dirty time has expired. */ s = splbio(); slp = &syncer_workitem_pending[syncer_delayno]; syncer_delayno += 1; if (syncer_delayno == syncer_maxdelay) syncer_delayno = 0; while ((vp = LIST_FIRST(slp)) != NULL) { if (vget(vp, LK_EXCLUSIVE | LK_NOWAIT)) { /* * If we fail to get the lock, we move this * vnode one second ahead in time. * XXX - no good, but the best we can do. */ vn_syncer_add_to_worklist(vp, 1); continue; } splx(s); (void) VOP_FSYNC(vp, p->p_ucred, MNT_LAZY, p); vput(vp); s = splbio(); if (LIST_FIRST(slp) == vp) { /* * Note: disk vps can remain on the * worklist too with no dirty blocks, but * since sync_fsync() moves it to a different * slot we are safe. */ #ifdef DIAGNOSTIC if (LIST_FIRST(&vp->v_dirtyblkhd) == NULL && vp->v_type != VBLK) { vprint("fsync failed", vp); if (vp->v_mount != NULL) printf("mounted on: %s\n", vp->v_mount->mnt_stat.f_mntonname); panic("%s: fsync failed", __func__); } #endif /* DIAGNOSTIC */ /* * Put us back on the worklist. The worklist * routine will remove us from our current * position and then add us back in at a later * position. */ vn_syncer_add_to_worklist(vp, syncdelay); } sched_pause(yield); } splx(s); /* * If it has taken us less than a second to process the * current work, then wait. Otherwise start right over * again. We can still lose time if any single round * takes more than two seconds, but it does not really * matter as we are just trying to generally pace the * filesystem activity. */ elapsed = getnsecuptime() - start; if (elapsed < SEC_TO_NSEC(1)) { tsleep_nsec(&syncer_chan, PPAUSE, "syncer", SEC_TO_NSEC(1) - elapsed); } } } /* Routine to create and manage a filesystem syncer vnode. */ int sync_fsync(void *); int sync_inactive(void *); int sync_print(void *); const struct vops sync_vops = { .vop_close = nullop, .vop_fsync = sync_fsync, .vop_inactive = sync_inactive, .vop_reclaim = nullop, .vop_lock = nullop, .vop_unlock = nullop, .vop_islocked = nullop, .vop_print = sync_print, .vop_abortop = NULL, .vop_access = NULL, .vop_advlock = NULL, .vop_bmap = NULL, .vop_bwrite = NULL, .vop_create = NULL, .vop_getattr = NULL, .vop_ioctl = NULL, .vop_link = NULL, .vop_lookup = NULL, .vop_mknod = NULL, .vop_open = NULL, .vop_pathconf = NULL, .vop_read = NULL, .vop_readdir = NULL, .vop_readlink = NULL, .vop_remove = eopnotsupp, .vop_rename = NULL, .vop_revoke = NULL, .vop_mkdir = NULL, .vop_rmdir = NULL, .vop_setattr = NULL, .vop_strategy = NULL, .vop_symlink = NULL, .vop_write = NULL, .vop_kqfilter = NULL }; /* * Create a new filesystem syncer vnode for the specified mount point. */ int vfs_allocate_syncvnode(struct mount *mp) { struct vnode *vp; static long start, incr, next; int error; /* Allocate a new vnode */ if ((error = getnewvnode(VT_VFS, mp, &sync_vops, &vp)) != 0) { mp->mnt_syncer = NULL; return (error); } vp->v_writecount = 1; vp->v_type = VNON; /* * Place the vnode onto the syncer worklist. We attempt to * scatter them about on the list so that they will go off * at evenly distributed times even if all the filesystems * are mounted at once. */ next += incr; if (next == 0 || next > syncer_maxdelay) { start /= 2; incr /= 2; if (start == 0) { start = syncer_maxdelay / 2; incr = syncer_maxdelay; } next = start; } vn_syncer_add_to_worklist(vp, next); mp->mnt_syncer = vp; return (0); } /* * Do a lazy sync of the filesystem. */ int sync_fsync(void *v) { struct vop_fsync_args *ap = v; struct vnode *syncvp = ap->a_vp; struct mount *mp = syncvp->v_mount; int asyncflag; /* * We only need to do something if this is a lazy evaluation. */ if (ap->a_waitfor != MNT_LAZY) return (0); /* * Move ourselves to the back of the sync list. */ vn_syncer_add_to_worklist(syncvp, syncdelay); /* * Walk the list of vnodes pushing all that are dirty and * not already on the sync list. */ if (vfs_busy(mp, VB_READ|VB_NOWAIT) == 0) { asyncflag = mp->mnt_flag & MNT_ASYNC; mp->mnt_flag &= ~MNT_ASYNC; VFS_SYNC(mp, MNT_LAZY, 0, ap->a_cred, ap->a_p); if (asyncflag) mp->mnt_flag |= MNT_ASYNC; vfs_unbusy(mp); } return (0); } /* * The syncer vnode is no longer needed and is being decommissioned. */ int sync_inactive(void *v) { struct vop_inactive_args *ap = v; struct vnode *vp = ap->a_vp; int s; if (vp->v_usecount == 0) { VOP_UNLOCK(vp); return (0); } vp->v_mount->mnt_syncer = NULL; s = splbio(); LIST_REMOVE(vp, v_synclist); vp->v_bioflag &= ~VBIOONSYNCLIST; splx(s); vp->v_writecount = 0; vput(vp); return (0); } /* * Print out a syncer vnode. */ int sync_print(void *v) { printf("syncer vnode\n"); return (0); }
3393 1603 3386 3 1 3 1 2 2 3 3 3 4 4 4 4 4 4689 4692 4691 4685 4481 1302 4684 4684 4690 4683 129 4687 4690 4675 1058 4688 2573 4196 4194 4195 12 4198 12 4199 4199 4197 4203 4197 4204 4200 4199 4162 2073 4165 839 2 2 2 2 129 25 130 126 127 128 128 130 16 16 16 15 1 129 112 25 23 119 15 1 16 2586 921 4 4 1 18 15 2 1 4 9 2 4 117 15 10 10 1 1 10 9 3 4838 4843 4644 4646 141 141 111 111 98 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 /* $OpenBSD: subr_pool.c,v 1.236 2022/08/14 01:58:28 jsg Exp $ */ /* $NetBSD: subr_pool.c,v 1.61 2001/09/26 07:14:56 chs Exp $ */ /*- * Copyright (c) 1997, 1999, 2000 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Paul Kranenburg; by Jason R. Thorpe of the Numerical Aerospace * Simulation Facility, NASA Ames Research Center. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/errno.h> #include <sys/malloc.h> #include <sys/pool.h> #include <sys/proc.h> #include <sys/sysctl.h> #include <sys/task.h> #include <sys/time.h> #include <sys/timeout.h> #include <sys/percpu.h> #include <sys/tracepoint.h> #include <uvm/uvm_extern.h> /* * Pool resource management utility. * * Memory is allocated in pages which are split into pieces according to * the pool item size. Each page is kept on one of three lists in the * pool structure: `pr_emptypages', `pr_fullpages' and `pr_partpages', * for empty, full and partially-full pages respectively. The individual * pool items are on a linked list headed by `ph_items' in each page * header. The memory for building the page list is either taken from * the allocated pages themselves (for small pool items) or taken from * an internal pool of page headers (`phpool'). */ /* List of all pools */ SIMPLEQ_HEAD(,pool) pool_head = SIMPLEQ_HEAD_INITIALIZER(pool_head); /* * Every pool gets a unique serial number assigned to it. If this counter * wraps, we're screwed, but we shouldn't create so many pools anyway. */ unsigned int pool_serial; unsigned int pool_count; /* Lock the previous variables making up the global pool state */ struct rwlock pool_lock = RWLOCK_INITIALIZER("pools"); /* Private pool for page header structures */ struct pool phpool; struct pool_lock_ops { void (*pl_init)(struct pool *, union pool_lock *, const struct lock_type *); void (*pl_enter)(union pool_lock *); int (*pl_enter_try)(union pool_lock *); void (*pl_leave)(union pool_lock *); void (*pl_assert_locked)(union pool_lock *); void (*pl_assert_unlocked)(union pool_lock *); int (*pl_sleep)(void *, union pool_lock *, int, const char *); }; static const struct pool_lock_ops pool_lock_ops_mtx; static const struct pool_lock_ops pool_lock_ops_rw; #ifdef WITNESS #define pl_init(pp, pl) do { \ static const struct lock_type __lock_type = { .lt_name = #pl }; \ (pp)->pr_lock_ops->pl_init(pp, pl, &__lock_type); \ } while (0) #else /* WITNESS */ #define pl_init(pp, pl) (pp)->pr_lock_ops->pl_init(pp, pl, NULL) #endif /* WITNESS */ static inline void pl_enter(struct pool *pp, union pool_lock *pl) { pp->pr_lock_ops->pl_enter(pl); } static inline int pl_enter_try(struct pool *pp, union pool_lock *pl) { return pp->pr_lock_ops->pl_enter_try(pl); } static inline void pl_leave(struct pool *pp, union pool_lock *pl) { pp->pr_lock_ops->pl_leave(pl); } static inline void pl_assert_locked(struct pool *pp, union pool_lock *pl) { pp->pr_lock_ops->pl_assert_locked(pl); } static inline void pl_assert_unlocked(struct pool *pp, union pool_lock *pl) { pp->pr_lock_ops->pl_assert_unlocked(pl); } static inline int pl_sleep(struct pool *pp, void *ident, union pool_lock *lock, int priority, const char *wmesg) { return pp->pr_lock_ops->pl_sleep(ident, lock, priority, wmesg); } struct pool_item { u_long pi_magic; XSIMPLEQ_ENTRY(pool_item) pi_list; }; #define POOL_IMAGIC(ph, pi) ((u_long)(pi) ^ (ph)->ph_magic) struct pool_page_header { /* Page headers */ TAILQ_ENTRY(pool_page_header) ph_entry; /* pool page list */ XSIMPLEQ_HEAD(, pool_item) ph_items; /* free items on the page */ RBT_ENTRY(pool_page_header) ph_node; /* off-page page headers */ unsigned int ph_nmissing; /* # of chunks in use */ caddr_t ph_page; /* this page's address */ caddr_t ph_colored; /* page's colored address */ unsigned long ph_magic; uint64_t ph_timestamp; }; #define POOL_MAGICBIT (1 << 3) /* keep away from perturbed low bits */ #define POOL_PHPOISON(ph) ISSET((ph)->ph_magic, POOL_MAGICBIT) #ifdef MULTIPROCESSOR struct pool_cache_item { struct pool_cache_item *ci_next; /* next item in list */ unsigned long ci_nitems; /* number of items in list */ TAILQ_ENTRY(pool_cache_item) ci_nextl; /* entry in list of lists */ }; /* we store whether the cached item is poisoned in the high bit of nitems */ #define POOL_CACHE_ITEM_NITEMS_MASK 0x7ffffffUL #define POOL_CACHE_ITEM_NITEMS_POISON 0x8000000UL #define POOL_CACHE_ITEM_NITEMS(_ci) \ ((_ci)->ci_nitems & POOL_CACHE_ITEM_NITEMS_MASK) #define POOL_CACHE_ITEM_POISONED(_ci) \ ISSET((_ci)->ci_nitems, POOL_CACHE_ITEM_NITEMS_POISON) struct pool_cache { struct pool_cache_item *pc_actv; /* active list of items */ unsigned long pc_nactv; /* actv head nitems cache */ struct pool_cache_item *pc_prev; /* previous list of items */ uint64_t pc_gen; /* generation number */ uint64_t pc_nget; /* # of successful requests */ uint64_t pc_nfail; /* # of unsuccessful reqs */ uint64_t pc_nput; /* # of releases */ uint64_t pc_nlget; /* # of list requests */ uint64_t pc_nlfail; /* # of fails getting a list */ uint64_t pc_nlput; /* # of list releases */ int pc_nout; }; void *pool_cache_get(struct pool *); void pool_cache_put(struct pool *, void *); void pool_cache_destroy(struct pool *); void pool_cache_gc(struct pool *); #endif void pool_cache_pool_info(struct pool *, struct kinfo_pool *); int pool_cache_info(struct pool *, void *, size_t *); int pool_cache_cpus_info(struct pool *, void *, size_t *); #ifdef POOL_DEBUG int pool_debug = 1; #else int pool_debug = 0; #endif #define POOL_INPGHDR(pp) ((pp)->pr_phoffset != 0) struct pool_page_header * pool_p_alloc(struct pool *, int, int *); void pool_p_insert(struct pool *, struct pool_page_header *); void pool_p_remove(struct pool *, struct pool_page_header *); void pool_p_free(struct pool *, struct pool_page_header *); void pool_update_curpage(struct pool *); void *pool_do_get(struct pool *, int, int *); void pool_do_put(struct pool *, void *); int pool_chk_page(struct pool *, struct pool_page_header *, int); int pool_chk(struct pool *); void pool_get_done(struct pool *, void *, void *); void pool_runqueue(struct pool *, int); void *pool_allocator_alloc(struct pool *, int, int *); void pool_allocator_free(struct pool *, void *); /* * The default pool allocator. */ void *pool_page_alloc(struct pool *, int, int *); void pool_page_free(struct pool *, void *); /* * safe for interrupts; this is the default allocator */ struct pool_allocator pool_allocator_single = { pool_page_alloc, pool_page_free, POOL_ALLOC_SIZE(PAGE_SIZE, POOL_ALLOC_ALIGNED) }; void *pool_multi_alloc(struct pool *, int, int *); void pool_multi_free(struct pool *, void *); struct pool_allocator pool_allocator_multi = { pool_multi_alloc, pool_multi_free, POOL_ALLOC_SIZES(PAGE_SIZE, (1UL << 31), POOL_ALLOC_ALIGNED) }; void *pool_multi_alloc_ni(struct pool *, int, int *); void pool_multi_free_ni(struct pool *, void *); struct pool_allocator pool_allocator_multi_ni = { pool_multi_alloc_ni, pool_multi_free_ni, POOL_ALLOC_SIZES(PAGE_SIZE, (1UL << 31), POOL_ALLOC_ALIGNED) }; #ifdef DDB void pool_print_pagelist(struct pool_pagelist *, int (*)(const char *, ...) __attribute__((__format__(__kprintf__,1,2)))); void pool_print1(struct pool *, const char *, int (*)(const char *, ...) __attribute__((__format__(__kprintf__,1,2)))); #endif /* stale page garbage collectors */ void pool_gc_sched(void *); struct timeout pool_gc_tick = TIMEOUT_INITIALIZER(pool_gc_sched, NULL); void pool_gc_pages(void *); struct task pool_gc_task = TASK_INITIALIZER(pool_gc_pages, NULL); #define POOL_WAIT_FREE SEC_TO_NSEC(1) #define POOL_WAIT_GC SEC_TO_NSEC(8) RBT_PROTOTYPE(phtree, pool_page_header, ph_node, phtree_compare); static inline int phtree_compare(const struct pool_page_header *a, const struct pool_page_header *b) { vaddr_t va = (vaddr_t)a->ph_page; vaddr_t vb = (vaddr_t)b->ph_page; /* the compares in this order are important for the NFIND to work */ if (vb < va) return (-1); if (vb > va) return (1); return (0); } RBT_GENERATE(phtree, pool_page_header, ph_node, phtree_compare); /* * Return the pool page header based on page address. */ static inline struct pool_page_header * pr_find_pagehead(struct pool *pp, void *v) { struct pool_page_header *ph, key; if (POOL_INPGHDR(pp)) { caddr_t page; page = (caddr_t)((vaddr_t)v & pp->pr_pgmask); return ((struct pool_page_header *)(page + pp->pr_phoffset)); } key.ph_page = v; ph = RBT_NFIND(phtree, &pp->pr_phtree, &key); if (ph == NULL) panic("%s: %s: page header missing", __func__, pp->pr_wchan); KASSERT(ph->ph_page <= (caddr_t)v); if (ph->ph_page + pp->pr_pgsize <= (caddr_t)v) panic("%s: %s: incorrect page", __func__, pp->pr_wchan); return (ph); } /* * Initialize the given pool resource structure. * * We export this routine to allow other kernel parts to declare * static pools that must be initialized before malloc() is available. */ void pool_init(struct pool *pp, size_t size, u_int align, int ipl, int flags, const char *wchan, struct pool_allocator *palloc) { int off = 0, space; unsigned int pgsize = PAGE_SIZE, items; size_t pa_pagesz; #ifdef DIAGNOSTIC struct pool *iter; #endif if (align == 0) align = ALIGN(1); if (size < sizeof(struct pool_item)) size = sizeof(struct pool_item); size = roundup(size, align); while (size * 8 > pgsize) pgsize <<= 1; if (palloc == NULL) { if (pgsize > PAGE_SIZE) { palloc = ISSET(flags, PR_WAITOK) ? &pool_allocator_multi_ni : &pool_allocator_multi; } else palloc = &pool_allocator_single; pa_pagesz = palloc->pa_pagesz; } else { size_t pgsizes; pa_pagesz = palloc->pa_pagesz; if (pa_pagesz == 0) pa_pagesz = POOL_ALLOC_DEFAULT; pgsizes = pa_pagesz & ~POOL_ALLOC_ALIGNED; /* make sure the allocator can fit at least one item */ if (size > pgsizes) { panic("%s: pool %s item size 0x%zx > " "allocator %p sizes 0x%zx", __func__, wchan, size, palloc, pgsizes); } /* shrink pgsize until it fits into the range */ while (!ISSET(pgsizes, pgsize)) pgsize >>= 1; } KASSERT(ISSET(pa_pagesz, pgsize)); items = pgsize / size; /* * Decide whether to put the page header off page to avoid * wasting too large a part of the page. Off-page page headers * go into an RB tree, so we can match a returned item with * its header based on the page address. */ if (ISSET(pa_pagesz, POOL_ALLOC_ALIGNED)) { if (pgsize - (size * items) > sizeof(struct pool_page_header)) { off = pgsize - sizeof(struct pool_page_header); } else if (sizeof(struct pool_page_header) * 2 >= size) { off = pgsize - sizeof(struct pool_page_header); items = off / size; } } KASSERT(items > 0); /* * Initialize the pool structure. */ memset(pp, 0, sizeof(*pp)); if (ISSET(flags, PR_RWLOCK)) { KASSERT(flags & PR_WAITOK); pp->pr_lock_ops = &pool_lock_ops_rw; } else pp->pr_lock_ops = &pool_lock_ops_mtx; TAILQ_INIT(&pp->pr_emptypages); TAILQ_INIT(&pp->pr_fullpages); TAILQ_INIT(&pp->pr_partpages); pp->pr_curpage = NULL; pp->pr_npages = 0; pp->pr_minitems = 0; pp->pr_minpages = 0; pp->pr_maxpages = 8; pp->pr_size = size; pp->pr_pgsize = pgsize; pp->pr_pgmask = ~0UL ^ (pgsize - 1); pp->pr_phoffset = off; pp->pr_itemsperpage = items; pp->pr_wchan = wchan; pp->pr_alloc = palloc; pp->pr_nitems = 0; pp->pr_nout = 0; pp->pr_hardlimit = UINT_MAX; pp->pr_hardlimit_warning = NULL; pp->pr_hardlimit_ratecap.tv_sec = 0; pp->pr_hardlimit_ratecap.tv_usec = 0; pp->pr_hardlimit_warning_last.tv_sec = 0; pp->pr_hardlimit_warning_last.tv_usec = 0; RBT_INIT(phtree, &pp->pr_phtree); /* * Use the space between the chunks and the page header * for cache coloring. */ space = POOL_INPGHDR(pp) ? pp->pr_phoffset : pp->pr_pgsize; space -= pp->pr_itemsperpage * pp->pr_size; pp->pr_align = align; pp->pr_maxcolors = (space / align) + 1; pp->pr_nget = 0; pp->pr_nfail = 0; pp->pr_nput = 0; pp->pr_npagealloc = 0; pp->pr_npagefree = 0; pp->pr_hiwat = 0; pp->pr_nidle = 0; pp->pr_ipl = ipl; pp->pr_flags = flags; pl_init(pp, &pp->pr_lock); pl_init(pp, &pp->pr_requests_lock); TAILQ_INIT(&pp->pr_requests); if (phpool.pr_size == 0) { pool_init(&phpool, sizeof(struct pool_page_header), 0, IPL_HIGH, 0, "phpool", NULL); /* make sure phpool won't "recurse" */ KASSERT(POOL_INPGHDR(&phpool)); } /* pglistalloc/constraint parameters */ pp->pr_crange = &kp_dirty; /* Insert this into the list of all pools. */ rw_enter_write(&pool_lock); #ifdef DIAGNOSTIC SIMPLEQ_FOREACH(iter, &pool_head, pr_poollist) { if (iter == pp) panic("%s: pool %s already on list", __func__, wchan); } #endif pp->pr_serial = ++pool_serial; if (pool_serial == 0) panic("%s: too much uptime", __func__); SIMPLEQ_INSERT_HEAD(&pool_head, pp, pr_poollist); pool_count++; rw_exit_write(&pool_lock); } /* * Decommission a pool resource. */ void pool_destroy(struct pool *pp) { struct pool_page_header *ph; struct pool *prev, *iter; #ifdef MULTIPROCESSOR if (pp->pr_cache != NULL) pool_cache_destroy(pp); #endif #ifdef DIAGNOSTIC if (pp->pr_nout != 0) panic("%s: pool busy: still out: %u", __func__, pp->pr_nout); #endif /* Remove from global pool list */ rw_enter_write(&pool_lock); pool_count--; if (pp == SIMPLEQ_FIRST(&pool_head)) SIMPLEQ_REMOVE_HEAD(&pool_head, pr_poollist); else { prev = SIMPLEQ_FIRST(&pool_head); SIMPLEQ_FOREACH(iter, &pool_head, pr_poollist) { if (iter == pp) { SIMPLEQ_REMOVE_AFTER(&pool_head, prev, pr_poollist); break; } prev = iter; } } rw_exit_write(&pool_lock); /* Remove all pages */ while ((ph = TAILQ_FIRST(&pp->pr_emptypages)) != NULL) { pl_enter(pp, &pp->pr_lock); pool_p_remove(pp, ph); pl_leave(pp, &pp->pr_lock); pool_p_free(pp, ph); } KASSERT(TAILQ_EMPTY(&pp->pr_fullpages)); KASSERT(TAILQ_EMPTY(&pp->pr_partpages)); } void pool_request_init(struct pool_request *pr, void (*handler)(struct pool *, void *, void *), void *cookie) { pr->pr_handler = handler; pr->pr_cookie = cookie; pr->pr_item = NULL; } void pool_request(struct pool *pp, struct pool_request *pr) { pl_enter(pp, &pp->pr_requests_lock); TAILQ_INSERT_TAIL(&pp->pr_requests, pr, pr_entry); pool_runqueue(pp, PR_NOWAIT); pl_leave(pp, &pp->pr_requests_lock); } struct pool_get_memory { union pool_lock lock; void * volatile v; }; /* * Grab an item from the pool. */ void * pool_get(struct pool *pp, int flags) { void *v = NULL; int slowdown = 0; KASSERT(flags & (PR_WAITOK | PR_NOWAIT)); if (pp->pr_flags & PR_RWLOCK) KASSERT(flags & PR_WAITOK); #ifdef MULTIPROCESSOR if (pp->pr_cache != NULL) { v = pool_cache_get(pp); if (v != NULL) goto good; } #endif pl_enter(pp, &pp->pr_lock); if (pp->pr_nout >= pp->pr_hardlimit) { if (ISSET(flags, PR_NOWAIT|PR_LIMITFAIL)) goto fail; } else if ((v = pool_do_get(pp, flags, &slowdown)) == NULL) { if (ISSET(flags, PR_NOWAIT)) goto fail; } pl_leave(pp, &pp->pr_lock); if ((slowdown || pool_debug == 2) && ISSET(flags, PR_WAITOK)) yield(); if (v == NULL) { struct pool_get_memory mem = { .v = NULL }; struct pool_request pr; #ifdef DIAGNOSTIC if (ISSET(flags, PR_WAITOK) && curproc == &proc0) panic("%s: cannot sleep for memory during boot", __func__); #endif pl_init(pp, &mem.lock); pool_request_init(&pr, pool_get_done, &mem); pool_request(pp, &pr); pl_enter(pp, &mem.lock); while (mem.v == NULL) pl_sleep(pp, &mem, &mem.lock, PSWP, pp->pr_wchan); pl_leave(pp, &mem.lock); v = mem.v; } #ifdef MULTIPROCESSOR good: #endif if (ISSET(flags, PR_ZERO)) memset(v, 0, pp->pr_size); TRACEPOINT(uvm, pool_get, pp, v, flags); return (v); fail: pp->pr_nfail++; pl_leave(pp, &pp->pr_lock); return (NULL); } void pool_get_done(struct pool *pp, void *xmem, void *v) { struct pool_get_memory *mem = xmem; pl_enter(pp, &mem->lock); mem->v = v; pl_leave(pp, &mem->lock); wakeup_one(mem); } void pool_runqueue(struct pool *pp, int flags) { struct pool_requests prl = TAILQ_HEAD_INITIALIZER(prl); struct pool_request *pr; pl_assert_unlocked(pp, &pp->pr_lock); pl_assert_locked(pp, &pp->pr_requests_lock); if (pp->pr_requesting++) return; do { pp->pr_requesting = 1; TAILQ_CONCAT(&prl, &pp->pr_requests, pr_entry); if (TAILQ_EMPTY(&prl)) continue; pl_leave(pp, &pp->pr_requests_lock); pl_enter(pp, &pp->pr_lock); pr = TAILQ_FIRST(&prl); while (pr != NULL) { int slowdown = 0; if (pp->pr_nout >= pp->pr_hardlimit) break; pr->pr_item = pool_do_get(pp, flags, &slowdown); if (pr->pr_item == NULL) /* || slowdown ? */ break; pr = TAILQ_NEXT(pr, pr_entry); } pl_leave(pp, &pp->pr_lock); while ((pr = TAILQ_FIRST(&prl)) != NULL && pr->pr_item != NULL) { TAILQ_REMOVE(&prl, pr, pr_entry); (*pr->pr_handler)(pp, pr->pr_cookie, pr->pr_item); } pl_enter(pp, &pp->pr_requests_lock); } while (--pp->pr_requesting); TAILQ_CONCAT(&pp->pr_requests, &prl, pr_entry); } void * pool_do_get(struct pool *pp, int flags, int *slowdown) { struct pool_item *pi; struct pool_page_header *ph; pl_assert_locked(pp, &pp->pr_lock); splassert(pp->pr_ipl); /* * Account for this item now to avoid races if we need to give up * pr_lock to allocate a page. */ pp->pr_nout++; if (pp->pr_curpage == NULL) { pl_leave(pp, &pp->pr_lock); ph = pool_p_alloc(pp, flags, slowdown); pl_enter(pp, &pp->pr_lock); if (ph == NULL) { pp->pr_nout--; return (NULL); } pool_p_insert(pp, ph); } ph = pp->pr_curpage; pi = XSIMPLEQ_FIRST(&ph->ph_items); if (__predict_false(pi == NULL)) panic("%s: %s: page empty", __func__, pp->pr_wchan); if (__predict_false(pi->pi_magic != POOL_IMAGIC(ph, pi))) { panic("%s: %s free list modified: " "page %p; item addr %p; offset 0x%x=0x%lx != 0x%lx", __func__, pp->pr_wchan, ph->ph_page, pi, 0, pi->pi_magic, POOL_IMAGIC(ph, pi)); } XSIMPLEQ_REMOVE_HEAD(&ph->ph_items, pi_list); #ifdef DIAGNOSTIC if (pool_debug && POOL_PHPOISON(ph)) { size_t pidx; uint32_t pval; if (poison_check(pi + 1, pp->pr_size - sizeof(*pi), &pidx, &pval)) { int *ip = (int *)(pi + 1); panic("%s: %s free list modified: " "page %p; item addr %p; offset 0x%zx=0x%x", __func__, pp->pr_wchan, ph->ph_page, pi, (pidx * sizeof(int)) + sizeof(*pi), ip[pidx]); } } #endif /* DIAGNOSTIC */ if (ph->ph_nmissing++ == 0) { /* * This page was previously empty. Move it to the list of * partially-full pages. This page is already curpage. */ TAILQ_REMOVE(&pp->pr_emptypages, ph, ph_entry); TAILQ_INSERT_TAIL(&pp->pr_partpages, ph, ph_entry); pp->pr_nidle--; } if (ph->ph_nmissing == pp->pr_itemsperpage) { /* * This page is now full. Move it to the full list * and select a new current page. */ TAILQ_REMOVE(&pp->pr_partpages, ph, ph_entry); TAILQ_INSERT_TAIL(&pp->pr_fullpages, ph, ph_entry); pool_update_curpage(pp); } pp->pr_nget++; return (pi); } /* * Return resource to the pool. */ void pool_put(struct pool *pp, void *v) { struct pool_page_header *ph, *freeph = NULL; #ifdef DIAGNOSTIC if (v == NULL) panic("%s: NULL item", __func__); #endif TRACEPOINT(uvm, pool_put, pp, v); #ifdef MULTIPROCESSOR if (pp->pr_cache != NULL && TAILQ_EMPTY(&pp->pr_requests)) { pool_cache_put(pp, v); return; } #endif pl_enter(pp, &pp->pr_lock); pool_do_put(pp, v); pp->pr_nout--; pp->pr_nput++; /* is it time to free a page? */ if (pp->pr_nidle > pp->pr_maxpages && (ph = TAILQ_FIRST(&pp->pr_emptypages)) != NULL && getnsecuptime() - ph->ph_timestamp > POOL_WAIT_FREE) { freeph = ph; pool_p_remove(pp, freeph); } pl_leave(pp, &pp->pr_lock); if (freeph != NULL) pool_p_free(pp, freeph); pool_wakeup(pp); } void pool_wakeup(struct pool *pp) { if (!TAILQ_EMPTY(&pp->pr_requests)) { pl_enter(pp, &pp->pr_requests_lock); pool_runqueue(pp, PR_NOWAIT); pl_leave(pp, &pp->pr_requests_lock); } } void pool_do_put(struct pool *pp, void *v) { struct pool_item *pi = v; struct pool_page_header *ph; splassert(pp->pr_ipl); ph = pr_find_pagehead(pp, v); #ifdef DIAGNOSTIC if (pool_debug) { struct pool_item *qi; XSIMPLEQ_FOREACH(qi, &ph->ph_items, pi_list) { if (pi == qi) { panic("%s: %s: double pool_put: %p", __func__, pp->pr_wchan, pi); } } } #endif /* DIAGNOSTIC */ pi->pi_magic = POOL_IMAGIC(ph, pi); XSIMPLEQ_INSERT_HEAD(&ph->ph_items, pi, pi_list); #ifdef DIAGNOSTIC if (POOL_PHPOISON(ph)) poison_mem(pi + 1, pp->pr_size - sizeof(*pi)); #endif /* DIAGNOSTIC */ if (ph->ph_nmissing-- == pp->pr_itemsperpage) { /* * The page was previously completely full, move it to the * partially-full list. */ TAILQ_REMOVE(&pp->pr_fullpages, ph, ph_entry); TAILQ_INSERT_TAIL(&pp->pr_partpages, ph, ph_entry); } if (ph->ph_nmissing == 0) { /* * The page is now empty, so move it to the empty page list. */ pp->pr_nidle++; ph->ph_timestamp = getnsecuptime(); TAILQ_REMOVE(&pp->pr_partpages, ph, ph_entry); TAILQ_INSERT_TAIL(&pp->pr_emptypages, ph, ph_entry); pool_update_curpage(pp); } } /* * Add N items to the pool. */ int pool_prime(struct pool *pp, int n) { struct pool_pagelist pl = TAILQ_HEAD_INITIALIZER(pl); struct pool_page_header *ph; int newpages; newpages = roundup(n, pp->pr_itemsperpage) / pp->pr_itemsperpage; while (newpages-- > 0) { int slowdown = 0; ph = pool_p_alloc(pp, PR_NOWAIT, &slowdown); if (ph == NULL) /* or slowdown? */ break; TAILQ_INSERT_TAIL(&pl, ph, ph_entry); } pl_enter(pp, &pp->pr_lock); while ((ph = TAILQ_FIRST(&pl)) != NULL) { TAILQ_REMOVE(&pl, ph, ph_entry); pool_p_insert(pp, ph); } pl_leave(pp, &pp->pr_lock); return (0); } struct pool_page_header * pool_p_alloc(struct pool *pp, int flags, int *slowdown) { struct pool_page_header *ph; struct pool_item *pi; caddr_t addr; unsigned int order; int o; int n; pl_assert_unlocked(pp, &pp->pr_lock); KASSERT(pp->pr_size >= sizeof(*pi)); addr = pool_allocator_alloc(pp, flags, slowdown); if (addr == NULL) return (NULL); if (POOL_INPGHDR(pp)) ph = (struct pool_page_header *)(addr + pp->pr_phoffset); else { ph = pool_get(&phpool, flags); if (ph == NULL) { pool_allocator_free(pp, addr); return (NULL); } } XSIMPLEQ_INIT(&ph->ph_items); ph->ph_page = addr; addr += pp->pr_align * (pp->pr_npagealloc % pp->pr_maxcolors); ph->ph_colored = addr; ph->ph_nmissing = 0; arc4random_buf(&ph->ph_magic, sizeof(ph->ph_magic)); #ifdef DIAGNOSTIC /* use a bit in ph_magic to record if we poison page items */ if (pool_debug) SET(ph->ph_magic, POOL_MAGICBIT); else CLR(ph->ph_magic, POOL_MAGICBIT); #endif /* DIAGNOSTIC */ n = pp->pr_itemsperpage; o = 32; while (n--) { pi = (struct pool_item *)addr; pi->pi_magic = POOL_IMAGIC(ph, pi); if (o == 32) { order = arc4random(); o = 0; } if (ISSET(order, 1U << o++)) XSIMPLEQ_INSERT_TAIL(&ph->ph_items, pi, pi_list); else XSIMPLEQ_INSERT_HEAD(&ph->ph_items, pi, pi_list); #ifdef DIAGNOSTIC if (POOL_PHPOISON(ph)) poison_mem(pi + 1, pp->pr_size - sizeof(*pi)); #endif /* DIAGNOSTIC */ addr += pp->pr_size; } return (ph); } void pool_p_free(struct pool *pp, struct pool_page_header *ph) { struct pool_item *pi; pl_assert_unlocked(pp, &pp->pr_lock); KASSERT(ph->ph_nmissing == 0); XSIMPLEQ_FOREACH(pi, &ph->ph_items, pi_list) { if (__predict_false(pi->pi_magic != POOL_IMAGIC(ph, pi))) { panic("%s: %s free list modified: " "page %p; item addr %p; offset 0x%x=0x%lx", __func__, pp->pr_wchan, ph->ph_page, pi, 0, pi->pi_magic); } #ifdef DIAGNOSTIC if (POOL_PHPOISON(ph)) { size_t pidx; uint32_t pval; if (poison_check(pi + 1, pp->pr_size - sizeof(*pi), &pidx, &pval)) { int *ip = (int *)(pi + 1); panic("%s: %s free list modified: " "page %p; item addr %p; offset 0x%zx=0x%x", __func__, pp->pr_wchan, ph->ph_page, pi, pidx * sizeof(int), ip[pidx]); } } #endif } pool_allocator_free(pp, ph->ph_page); if (!POOL_INPGHDR(pp)) pool_put(&phpool, ph); } void pool_p_insert(struct pool *pp, struct pool_page_header *ph) { pl_assert_locked(pp, &pp->pr_lock); /* If the pool was depleted, point at the new page */ if (pp->pr_curpage == NULL) pp->pr_curpage = ph; TAILQ_INSERT_TAIL(&pp->pr_emptypages, ph, ph_entry); if (!POOL_INPGHDR(pp)) RBT_INSERT(phtree, &pp->pr_phtree, ph); pp->pr_nitems += pp->pr_itemsperpage; pp->pr_nidle++; pp->pr_npagealloc++; if (++pp->pr_npages > pp->pr_hiwat) pp->pr_hiwat = pp->pr_npages; } void pool_p_remove(struct pool *pp, struct pool_page_header *ph) { pl_assert_locked(pp, &pp->pr_lock); pp->pr_npagefree++; pp->pr_npages--; pp->pr_nidle--; pp->pr_nitems -= pp->pr_itemsperpage; if (!POOL_INPGHDR(pp)) RBT_REMOVE(phtree, &pp->pr_phtree, ph); TAILQ_REMOVE(&pp->pr_emptypages, ph, ph_entry); pool_update_curpage(pp); } void pool_update_curpage(struct pool *pp) { pp->pr_curpage = TAILQ_LAST(&pp->pr_partpages, pool_pagelist); if (pp->pr_curpage == NULL) { pp->pr_curpage = TAILQ_LAST(&pp->pr_emptypages, pool_pagelist); } } void pool_setlowat(struct pool *pp, int n) { int prime = 0; pl_enter(pp, &pp->pr_lock); pp->pr_minitems = n; pp->pr_minpages = (n == 0) ? 0 : roundup(n, pp->pr_itemsperpage) / pp->pr_itemsperpage; if (pp->pr_nitems < n) prime = n - pp->pr_nitems; pl_leave(pp, &pp->pr_lock); if (prime > 0) pool_prime(pp, prime); } void pool_sethiwat(struct pool *pp, int n) { pp->pr_maxpages = (n == 0) ? 0 : roundup(n, pp->pr_itemsperpage) / pp->pr_itemsperpage; } int pool_sethardlimit(struct pool *pp, u_int n, const char *warnmsg, int ratecap) { int error = 0; if (n < pp->pr_nout) { error = EINVAL; goto done; } pp->pr_hardlimit = n; pp->pr_hardlimit_warning = warnmsg; pp->pr_hardlimit_ratecap.tv_sec = ratecap; pp->pr_hardlimit_warning_last.tv_sec = 0; pp->pr_hardlimit_warning_last.tv_usec = 0; done: return (error); } void pool_set_constraints(struct pool *pp, const struct kmem_pa_mode *mode) { pp->pr_crange = mode; } /* * Release all complete pages that have not been used recently. * * Returns non-zero if any pages have been reclaimed. */ int pool_reclaim(struct pool *pp) { struct pool_page_header *ph, *phnext; struct pool_pagelist pl = TAILQ_HEAD_INITIALIZER(pl); pl_enter(pp, &pp->pr_lock); for (ph = TAILQ_FIRST(&pp->pr_emptypages); ph != NULL; ph = phnext) { phnext = TAILQ_NEXT(ph, ph_entry); /* Check our minimum page claim */ if (pp->pr_npages <= pp->pr_minpages) break; /* * If freeing this page would put us below * the low water mark, stop now. */ if ((pp->pr_nitems - pp->pr_itemsperpage) < pp->pr_minitems) break; pool_p_remove(pp, ph); TAILQ_INSERT_TAIL(&pl, ph, ph_entry); } pl_leave(pp, &pp->pr_lock); if (TAILQ_EMPTY(&pl)) return (0); while ((ph = TAILQ_FIRST(&pl)) != NULL) { TAILQ_REMOVE(&pl, ph, ph_entry); pool_p_free(pp, ph); } return (1); } /* * Release all complete pages that have not been used recently * from all pools. */ void pool_reclaim_all(void) { struct pool *pp; rw_enter_read(&pool_lock); SIMPLEQ_FOREACH(pp, &pool_head, pr_poollist) pool_reclaim(pp); rw_exit_read(&pool_lock); } #ifdef DDB #include <machine/db_machdep.h> #include <ddb/db_output.h> /* * Diagnostic helpers. */ void pool_printit(struct pool *pp, const char *modif, int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2)))) { pool_print1(pp, modif, pr); } void pool_print_pagelist(struct pool_pagelist *pl, int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2)))) { struct pool_page_header *ph; struct pool_item *pi; TAILQ_FOREACH(ph, pl, ph_entry) { (*pr)("\t\tpage %p, color %p, nmissing %d\n", ph->ph_page, ph->ph_colored, ph->ph_nmissing); XSIMPLEQ_FOREACH(pi, &ph->ph_items, pi_list) { if (pi->pi_magic != POOL_IMAGIC(ph, pi)) { (*pr)("\t\t\titem %p, magic 0x%lx\n", pi, pi->pi_magic); } } } } void pool_print1(struct pool *pp, const char *modif, int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2)))) { struct pool_page_header *ph; int print_pagelist = 0; char c; while ((c = *modif++) != '\0') { if (c == 'p') print_pagelist = 1; modif++; } (*pr)("POOL %s: size %u maxcolors %u\n", pp->pr_wchan, pp->pr_size, pp->pr_maxcolors); (*pr)("\talloc %p\n", pp->pr_alloc); (*pr)("\tminitems %u, minpages %u, maxpages %u, npages %u\n", pp->pr_minitems, pp->pr_minpages, pp->pr_maxpages, pp->pr_npages); (*pr)("\titemsperpage %u, nitems %u, nout %u, hardlimit %u\n", pp->pr_itemsperpage, pp->pr_nitems, pp->pr_nout, pp->pr_hardlimit); (*pr)("\n\tnget %lu, nfail %lu, nput %lu\n", pp->pr_nget, pp->pr_nfail, pp->pr_nput); (*pr)("\tnpagealloc %lu, npagefree %lu, hiwat %u, nidle %lu\n", pp->pr_npagealloc, pp->pr_npagefree, pp->pr_hiwat, pp->pr_nidle); if (print_pagelist == 0) return; if ((ph = TAILQ_FIRST(&pp->pr_emptypages)) != NULL) (*pr)("\n\tempty page list:\n"); pool_print_pagelist(&pp->pr_emptypages, pr); if ((ph = TAILQ_FIRST(&pp->pr_fullpages)) != NULL) (*pr)("\n\tfull page list:\n"); pool_print_pagelist(&pp->pr_fullpages, pr); if ((ph = TAILQ_FIRST(&pp->pr_partpages)) != NULL) (*pr)("\n\tpartial-page list:\n"); pool_print_pagelist(&pp->pr_partpages, pr); if (pp->pr_curpage == NULL) (*pr)("\tno current page\n"); else (*pr)("\tcurpage %p\n", pp->pr_curpage->ph_page); } void db_show_all_pools(db_expr_t expr, int haddr, db_expr_t count, char *modif) { struct pool *pp; char maxp[16]; int ovflw; char mode; mode = modif[0]; if (mode != '\0' && mode != 'a') { db_printf("usage: show all pools [/a]\n"); return; } if (mode == '\0') db_printf("%-10s%4s%9s%5s%9s%6s%6s%6s%6s%6s%6s%5s\n", "Name", "Size", "Requests", "Fail", "Releases", "Pgreq", "Pgrel", "Npage", "Hiwat", "Minpg", "Maxpg", "Idle"); else db_printf("%-12s %18s %18s\n", "Name", "Address", "Allocator"); SIMPLEQ_FOREACH(pp, &pool_head, pr_poollist) { if (mode == 'a') { db_printf("%-12s %18p %18p\n", pp->pr_wchan, pp, pp->pr_alloc); continue; } if (!pp->pr_nget) continue; if (pp->pr_maxpages == UINT_MAX) snprintf(maxp, sizeof maxp, "inf"); else snprintf(maxp, sizeof maxp, "%u", pp->pr_maxpages); #define PRWORD(ovflw, fmt, width, fixed, val) do { \ (ovflw) += db_printf((fmt), \ (width) - (fixed) - (ovflw) > 0 ? \ (width) - (fixed) - (ovflw) : 0, \ (val)) - (width); \ if ((ovflw) < 0) \ (ovflw) = 0; \ } while (/* CONSTCOND */0) ovflw = 0; PRWORD(ovflw, "%-*s", 10, 0, pp->pr_wchan); PRWORD(ovflw, " %*u", 4, 1, pp->pr_size); PRWORD(ovflw, " %*lu", 9, 1, pp->pr_nget); PRWORD(ovflw, " %*lu", 5, 1, pp->pr_nfail); PRWORD(ovflw, " %*lu", 9, 1, pp->pr_nput); PRWORD(ovflw, " %*lu", 6, 1, pp->pr_npagealloc); PRWORD(ovflw, " %*lu", 6, 1, pp->pr_npagefree); PRWORD(ovflw, " %*d", 6, 1, pp->pr_npages); PRWORD(ovflw, " %*d", 6, 1, pp->pr_hiwat); PRWORD(ovflw, " %*d", 6, 1, pp->pr_minpages); PRWORD(ovflw, " %*s", 6, 1, maxp); PRWORD(ovflw, " %*lu\n", 5, 1, pp->pr_nidle); pool_chk(pp); } } #endif /* DDB */ #if defined(POOL_DEBUG) || defined(DDB) int pool_chk_page(struct pool *pp, struct pool_page_header *ph, int expected) { struct pool_item *pi; caddr_t page; int n; const char *label = pp->pr_wchan; page = (caddr_t)((u_long)ph & pp->pr_pgmask); if (page != ph->ph_page && POOL_INPGHDR(pp)) { printf("%s: ", label); printf("pool(%p:%s): page inconsistency: page %p; " "at page head addr %p (p %p)\n", pp, pp->pr_wchan, ph->ph_page, ph, page); return 1; } for (pi = XSIMPLEQ_FIRST(&ph->ph_items), n = 0; pi != NULL; pi = XSIMPLEQ_NEXT(&ph->ph_items, pi, pi_list), n++) { if ((caddr_t)pi < ph->ph_page || (caddr_t)pi >= ph->ph_page + pp->pr_pgsize) { printf("%s: ", label); printf("pool(%p:%s): page inconsistency: page %p;" " item ordinal %d; addr %p\n", pp, pp->pr_wchan, ph->ph_page, n, pi); return (1); } if (pi->pi_magic != POOL_IMAGIC(ph, pi)) { printf("%s: ", label); printf("pool(%p:%s): free list modified: " "page %p; item ordinal %d; addr %p " "(p %p); offset 0x%x=0x%lx\n", pp, pp->pr_wchan, ph->ph_page, n, pi, page, 0, pi->pi_magic); } #ifdef DIAGNOSTIC if (POOL_PHPOISON(ph)) { size_t pidx; uint32_t pval; if (poison_check(pi + 1, pp->pr_size - sizeof(*pi), &pidx, &pval)) { int *ip = (int *)(pi + 1); printf("pool(%s): free list modified: " "page %p; item ordinal %d; addr %p " "(p %p); offset 0x%zx=0x%x\n", pp->pr_wchan, ph->ph_page, n, pi, page, pidx * sizeof(int), ip[pidx]); } } #endif /* DIAGNOSTIC */ } if (n + ph->ph_nmissing != pp->pr_itemsperpage) { printf("pool(%p:%s): page inconsistency: page %p;" " %d on list, %d missing, %d items per page\n", pp, pp->pr_wchan, ph->ph_page, n, ph->ph_nmissing, pp->pr_itemsperpage); return 1; } if (expected >= 0 && n != expected) { printf("pool(%p:%s): page inconsistency: page %p;" " %d on list, %d missing, %d expected\n", pp, pp->pr_wchan, ph->ph_page, n, ph->ph_nmissing, expected); return 1; } return 0; } int pool_chk(struct pool *pp) { struct pool_page_header *ph; int r = 0; TAILQ_FOREACH(ph, &pp->pr_emptypages, ph_entry) r += pool_chk_page(pp, ph, pp->pr_itemsperpage); TAILQ_FOREACH(ph, &pp->pr_fullpages, ph_entry) r += pool_chk_page(pp, ph, 0); TAILQ_FOREACH(ph, &pp->pr_partpages, ph_entry) r += pool_chk_page(pp, ph, -1); return (r); } #endif /* defined(POOL_DEBUG) || defined(DDB) */ #ifdef DDB void pool_walk(struct pool *pp, int full, int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2))), void (*func)(void *, int, int (*)(const char *, ...) __attribute__((__format__(__kprintf__,1,2))))) { struct pool_page_header *ph; struct pool_item *pi; caddr_t cp; int n; TAILQ_FOREACH(ph, &pp->pr_fullpages, ph_entry) { cp = ph->ph_colored; n = ph->ph_nmissing; while (n--) { func(cp, full, pr); cp += pp->pr_size; } } TAILQ_FOREACH(ph, &pp->pr_partpages, ph_entry) { cp = ph->ph_colored; n = ph->ph_nmissing; do { XSIMPLEQ_FOREACH(pi, &ph->ph_items, pi_list) { if (cp == (caddr_t)pi) break; } if (cp != (caddr_t)pi) { func(cp, full, pr); n--; } cp += pp->pr_size; } while (n > 0); } } #endif /* * We have three different sysctls. * kern.pool.npools - the number of pools. * kern.pool.pool.<pool#> - the pool struct for the pool#. * kern.pool.name.<pool#> - the name for pool#. */ int sysctl_dopool(int *name, u_int namelen, char *oldp, size_t *oldlenp) { struct kinfo_pool pi; struct pool *pp; int rv = ENOENT; switch (name[0]) { case KERN_POOL_NPOOLS: if (namelen != 1) return (ENOTDIR); return (sysctl_rdint(oldp, oldlenp, NULL, pool_count)); case KERN_POOL_NAME: case KERN_POOL_POOL: case KERN_POOL_CACHE: case KERN_POOL_CACHE_CPUS: break; default: return (EOPNOTSUPP); } if (namelen != 2) return (ENOTDIR); rw_enter_read(&pool_lock); SIMPLEQ_FOREACH(pp, &pool_head, pr_poollist) { if (name[1] == pp->pr_serial) break; } if (pp == NULL) goto done; switch (name[0]) { case KERN_POOL_NAME: rv = sysctl_rdstring(oldp, oldlenp, NULL, pp->pr_wchan); break; case KERN_POOL_POOL: memset(&pi, 0, sizeof(pi)); pl_enter(pp, &pp->pr_lock); pi.pr_size = pp->pr_size; pi.pr_pgsize = pp->pr_pgsize; pi.pr_itemsperpage = pp->pr_itemsperpage; pi.pr_npages = pp->pr_npages; pi.pr_minpages = pp->pr_minpages; pi.pr_maxpages = pp->pr_maxpages; pi.pr_hardlimit = pp->pr_hardlimit; pi.pr_nout = pp->pr_nout; pi.pr_nitems = pp->pr_nitems; pi.pr_nget = pp->pr_nget; pi.pr_nput = pp->pr_nput; pi.pr_nfail = pp->pr_nfail; pi.pr_npagealloc = pp->pr_npagealloc; pi.pr_npagefree = pp->pr_npagefree; pi.pr_hiwat = pp->pr_hiwat; pi.pr_nidle = pp->pr_nidle; pl_leave(pp, &pp->pr_lock); pool_cache_pool_info(pp, &pi); rv = sysctl_rdstruct(oldp, oldlenp, NULL, &pi, sizeof(pi)); break; case KERN_POOL_CACHE: rv = pool_cache_info(pp, oldp, oldlenp); break; case KERN_POOL_CACHE_CPUS: rv = pool_cache_cpus_info(pp, oldp, oldlenp); break; } done: rw_exit_read(&pool_lock); return (rv); } void pool_gc_sched(void *null) { task_add(systqmp, &pool_gc_task); } void pool_gc_pages(void *null) { struct pool *pp; struct pool_page_header *ph, *freeph; int s; rw_enter_read(&pool_lock); s = splvm(); /* XXX go to splvm until all pools _setipl properly */ SIMPLEQ_FOREACH(pp, &pool_head, pr_poollist) { #ifdef MULTIPROCESSOR if (pp->pr_cache != NULL) pool_cache_gc(pp); #endif if (pp->pr_nidle <= pp->pr_minpages || /* guess */ !pl_enter_try(pp, &pp->pr_lock)) /* try */ continue; /* is it time to free a page? */ if (pp->pr_nidle > pp->pr_minpages && (ph = TAILQ_FIRST(&pp->pr_emptypages)) != NULL && getnsecuptime() - ph->ph_timestamp > POOL_WAIT_GC) { freeph = ph; pool_p_remove(pp, freeph); } else freeph = NULL; pl_leave(pp, &pp->pr_lock); if (freeph != NULL) pool_p_free(pp, freeph); } splx(s); rw_exit_read(&pool_lock); timeout_add_sec(&pool_gc_tick, 1); } /* * Pool backend allocators. */ void * pool_allocator_alloc(struct pool *pp, int flags, int *slowdown) { void *v; v = (*pp->pr_alloc->pa_alloc)(pp, flags, slowdown); #ifdef DIAGNOSTIC if (v != NULL && POOL_INPGHDR(pp)) { vaddr_t addr = (vaddr_t)v; if ((addr & pp->pr_pgmask) != addr) { panic("%s: %s page address %p isn't aligned to %u", __func__, pp->pr_wchan, v, pp->pr_pgsize); } } #endif return (v); } void pool_allocator_free(struct pool *pp, void *v) { struct pool_allocator *pa = pp->pr_alloc; (*pa->pa_free)(pp, v); } void * pool_page_alloc(struct pool *pp, int flags, int *slowdown) { struct kmem_dyn_mode kd = KMEM_DYN_INITIALIZER; kd.kd_waitok = ISSET(flags, PR_WAITOK); kd.kd_slowdown = slowdown; return (km_alloc(pp->pr_pgsize, &kv_page, pp->pr_crange, &kd)); } void pool_page_free(struct pool *pp, void *v) { km_free(v, pp->pr_pgsize, &kv_page, pp->pr_crange); } void * pool_multi_alloc(struct pool *pp, int flags, int *slowdown) { struct kmem_va_mode kv = kv_intrsafe; struct kmem_dyn_mode kd = KMEM_DYN_INITIALIZER; void *v; int s; if (POOL_INPGHDR(pp)) kv.kv_align = pp->pr_pgsize; kd.kd_waitok = ISSET(flags, PR_WAITOK); kd.kd_slowdown = slowdown; s = splvm(); v = km_alloc(pp->pr_pgsize, &kv, pp->pr_crange, &kd); splx(s); return (v); } void pool_multi_free(struct pool *pp, void *v) { struct kmem_va_mode kv = kv_intrsafe; int s; if (POOL_INPGHDR(pp)) kv.kv_align = pp->pr_pgsize; s = splvm(); km_free(v, pp->pr_pgsize, &kv, pp->pr_crange); splx(s); } void * pool_multi_alloc_ni(struct pool *pp, int flags, int *slowdown) { struct kmem_va_mode kv = kv_any; struct kmem_dyn_mode kd = KMEM_DYN_INITIALIZER; void *v; if (POOL_INPGHDR(pp)) kv.kv_align = pp->pr_pgsize; kd.kd_waitok = ISSET(flags, PR_WAITOK); kd.kd_slowdown = slowdown; KERNEL_LOCK(); v = km_alloc(pp->pr_pgsize, &kv, pp->pr_crange, &kd); KERNEL_UNLOCK(); return (v); } void pool_multi_free_ni(struct pool *pp, void *v) { struct kmem_va_mode kv = kv_any; if (POOL_INPGHDR(pp)) kv.kv_align = pp->pr_pgsize; KERNEL_LOCK(); km_free(v, pp->pr_pgsize, &kv, pp->pr_crange); KERNEL_UNLOCK(); } #ifdef MULTIPROCESSOR struct pool pool_caches; /* per cpu cache entries */ void pool_cache_init(struct pool *pp) { struct cpumem *cm; struct pool_cache *pc; struct cpumem_iter i; if (pool_caches.pr_size == 0) { pool_init(&pool_caches, sizeof(struct pool_cache), CACHELINESIZE, IPL_NONE, PR_WAITOK | PR_RWLOCK, "plcache", NULL); } /* must be able to use the pool items as cache list items */ KASSERT(pp->pr_size >= sizeof(struct pool_cache_item)); cm = cpumem_get(&pool_caches); pl_init(pp, &pp->pr_cache_lock); arc4random_buf(pp->pr_cache_magic, sizeof(pp->pr_cache_magic)); TAILQ_INIT(&pp->pr_cache_lists); pp->pr_cache_nitems = 0; pp->pr_cache_timestamp = getnsecuptime(); pp->pr_cache_items = 8; pp->pr_cache_contention = 0; pp->pr_cache_ngc = 0; CPUMEM_FOREACH(pc, &i, cm) { pc->pc_actv = NULL; pc->pc_nactv = 0; pc->pc_prev = NULL; pc->pc_nget = 0; pc->pc_nfail = 0; pc->pc_nput = 0; pc->pc_nlget = 0; pc->pc_nlfail = 0; pc->pc_nlput = 0; pc->pc_nout = 0; } membar_producer(); pp->pr_cache = cm; } static inline void pool_cache_item_magic(struct pool *pp, struct pool_cache_item *ci) { unsigned long *entry = (unsigned long *)&ci->ci_nextl; entry[0] = pp->pr_cache_magic[0] ^ (u_long)ci; entry[1] = pp->pr_cache_magic[1] ^ (u_long)ci->ci_next; } static inline void pool_cache_item_magic_check(struct pool *pp, struct pool_cache_item *ci) { unsigned long *entry; unsigned long val; entry = (unsigned long *)&ci->ci_nextl; val = pp->pr_cache_magic[0] ^ (u_long)ci; if (*entry != val) goto fail; entry++; val = pp->pr_cache_magic[1] ^ (u_long)ci->ci_next; if (*entry != val) goto fail; return; fail: panic("%s: %s cpu free list modified: item addr %p+%zu 0x%lx!=0x%lx", __func__, pp->pr_wchan, ci, (caddr_t)entry - (caddr_t)ci, *entry, val); } static inline void pool_list_enter(struct pool *pp) { if (pl_enter_try(pp, &pp->pr_cache_lock) == 0) { pl_enter(pp, &pp->pr_cache_lock); pp->pr_cache_contention++; } } static inline void pool_list_leave(struct pool *pp) { pl_leave(pp, &pp->pr_cache_lock); } static inline struct pool_cache_item * pool_cache_list_alloc(struct pool *pp, struct pool_cache *pc) { struct pool_cache_item *pl; pool_list_enter(pp); pl = TAILQ_FIRST(&pp->pr_cache_lists); if (pl != NULL) { TAILQ_REMOVE(&pp->pr_cache_lists, pl, ci_nextl); pp->pr_cache_nitems -= POOL_CACHE_ITEM_NITEMS(pl); pool_cache_item_magic(pp, pl); pc->pc_nlget++; } else pc->pc_nlfail++; /* fold this cpus nout into the global while we have the lock */ pp->pr_cache_nout += pc->pc_nout; pc->pc_nout = 0; pool_list_leave(pp); return (pl); } static inline void pool_cache_list_free(struct pool *pp, struct pool_cache *pc, struct pool_cache_item *ci) { pool_list_enter(pp); if (TAILQ_EMPTY(&pp->pr_cache_lists)) pp->pr_cache_timestamp = getnsecuptime(); pp->pr_cache_nitems += POOL_CACHE_ITEM_NITEMS(ci); TAILQ_INSERT_TAIL(&pp->pr_cache_lists, ci, ci_nextl); pc->pc_nlput++; /* fold this cpus nout into the global while we have the lock */ pp->pr_cache_nout += pc->pc_nout; pc->pc_nout = 0; pool_list_leave(pp); } static inline struct pool_cache * pool_cache_enter(struct pool *pp, int *s) { struct pool_cache *pc; pc = cpumem_enter(pp->pr_cache); *s = splraise(pp->pr_ipl); pc->pc_gen++; return (pc); } static inline void pool_cache_leave(struct pool *pp, struct pool_cache *pc, int s) { pc->pc_gen++; splx(s); cpumem_leave(pp->pr_cache, pc); } void * pool_cache_get(struct pool *pp) { struct pool_cache *pc; struct pool_cache_item *ci; int s; pc = pool_cache_enter(pp, &s); if (pc->pc_actv != NULL) { ci = pc->pc_actv; } else if (pc->pc_prev != NULL) { ci = pc->pc_prev; pc->pc_prev = NULL; } else if ((ci = pool_cache_list_alloc(pp, pc)) == NULL) { pc->pc_nfail++; goto done; } pool_cache_item_magic_check(pp, ci); #ifdef DIAGNOSTIC if (pool_debug && POOL_CACHE_ITEM_POISONED(ci)) { size_t pidx; uint32_t pval; if (poison_check(ci + 1, pp->pr_size - sizeof(*ci), &pidx, &pval)) { int *ip = (int *)(ci + 1); ip += pidx; panic("%s: %s cpu free list modified: " "item addr %p+%zu 0x%x!=0x%x", __func__, pp->pr_wchan, ci, (caddr_t)ip - (caddr_t)ci, *ip, pval); } } #endif pc->pc_actv = ci->ci_next; pc->pc_nactv = POOL_CACHE_ITEM_NITEMS(ci) - 1; pc->pc_nget++; pc->pc_nout++; done: pool_cache_leave(pp, pc, s); return (ci); } void pool_cache_put(struct pool *pp, void *v) { struct pool_cache *pc; struct pool_cache_item *ci = v; unsigned long nitems; int s; #ifdef DIAGNOSTIC int poison = pool_debug && pp->pr_size > sizeof(*ci); if (poison) poison_mem(ci + 1, pp->pr_size - sizeof(*ci)); #endif pc = pool_cache_enter(pp, &s); nitems = pc->pc_nactv; if (nitems >= pp->pr_cache_items) { if (pc->pc_prev != NULL) pool_cache_list_free(pp, pc, pc->pc_prev); pc->pc_prev = pc->pc_actv; pc->pc_actv = NULL; pc->pc_nactv = 0; nitems = 0; } ci->ci_next = pc->pc_actv; ci->ci_nitems = ++nitems; #ifdef DIAGNOSTIC ci->ci_nitems |= poison ? POOL_CACHE_ITEM_NITEMS_POISON : 0; #endif pool_cache_item_magic(pp, ci); pc->pc_actv = ci; pc->pc_nactv = nitems; pc->pc_nput++; pc->pc_nout--; pool_cache_leave(pp, pc, s); } struct pool_cache_item * pool_cache_list_put(struct pool *pp, struct pool_cache_item *pl) { struct pool_cache_item *rpl, *next; if (pl == NULL) return (NULL); rpl = TAILQ_NEXT(pl, ci_nextl); pl_enter(pp, &pp->pr_lock); do { next = pl->ci_next; pool_do_put(pp, pl); pl = next; } while (pl != NULL); pl_leave(pp, &pp->pr_lock); return (rpl); } void pool_cache_destroy(struct pool *pp) { struct pool_cache *pc; struct pool_cache_item *pl; struct cpumem_iter i; struct cpumem *cm; rw_enter_write(&pool_lock); /* serialise with the gc */ cm = pp->pr_cache; pp->pr_cache = NULL; /* make pool_put avoid the cache */ rw_exit_write(&pool_lock); CPUMEM_FOREACH(pc, &i, cm) { pool_cache_list_put(pp, pc->pc_actv); pool_cache_list_put(pp, pc->pc_prev); } cpumem_put(&pool_caches, cm); pl = TAILQ_FIRST(&pp->pr_cache_lists); while (pl != NULL) pl = pool_cache_list_put(pp, pl); } void pool_cache_gc(struct pool *pp) { unsigned int contention, delta; if (getnsecuptime() - pp->pr_cache_timestamp > POOL_WAIT_GC && !TAILQ_EMPTY(&pp->pr_cache_lists) && pl_enter_try(pp, &pp->pr_cache_lock)) { struct pool_cache_item *pl = NULL; pl = TAILQ_FIRST(&pp->pr_cache_lists); if (pl != NULL) { TAILQ_REMOVE(&pp->pr_cache_lists, pl, ci_nextl); pp->pr_cache_nitems -= POOL_CACHE_ITEM_NITEMS(pl); pp->pr_cache_timestamp = getnsecuptime(); pp->pr_cache_ngc++; } pl_leave(pp, &pp->pr_cache_lock); pool_cache_list_put(pp, pl); } /* * if there's a lot of contention on the pr_cache_mtx then consider * growing the length of the list to reduce the need to access the * global pool. */ contention = pp->pr_cache_contention; delta = contention - pp->pr_cache_contention_prev; if (delta > 8 /* magic */) { if ((ncpusfound * 8 * 2) <= pp->pr_cache_nitems) pp->pr_cache_items += 8; } else if (delta == 0) { if (pp->pr_cache_items > 8) pp->pr_cache_items--; } pp->pr_cache_contention_prev = contention; } void pool_cache_pool_info(struct pool *pp, struct kinfo_pool *pi) { struct pool_cache *pc; struct cpumem_iter i; if (pp->pr_cache == NULL) return; /* loop through the caches twice to collect stats */ /* once without the lock so we can yield while reading nget/nput */ CPUMEM_FOREACH(pc, &i, pp->pr_cache) { uint64_t gen, nget, nput; do { while ((gen = pc->pc_gen) & 1) yield(); nget = pc->pc_nget; nput = pc->pc_nput; } while (gen != pc->pc_gen); pi->pr_nget += nget; pi->pr_nput += nput; } /* and once with the mtx so we can get consistent nout values */ pl_enter(pp, &pp->pr_cache_lock); CPUMEM_FOREACH(pc, &i, pp->pr_cache) pi->pr_nout += pc->pc_nout; pi->pr_nout += pp->pr_cache_nout; pl_leave(pp, &pp->pr_cache_lock); } int pool_cache_info(struct pool *pp, void *oldp, size_t *oldlenp) { struct kinfo_pool_cache kpc; if (pp->pr_cache == NULL) return (EOPNOTSUPP); memset(&kpc, 0, sizeof(kpc)); /* don't leak padding */ pl_enter(pp, &pp->pr_cache_lock); kpc.pr_ngc = pp->pr_cache_ngc; kpc.pr_len = pp->pr_cache_items; kpc.pr_nitems = pp->pr_cache_nitems; kpc.pr_contention = pp->pr_cache_contention; pl_leave(pp, &pp->pr_cache_lock); return (sysctl_rdstruct(oldp, oldlenp, NULL, &kpc, sizeof(kpc))); } int pool_cache_cpus_info(struct pool *pp, void *oldp, size_t *oldlenp) { struct pool_cache *pc; struct kinfo_pool_cache_cpu *kpcc, *info; unsigned int cpu = 0; struct cpumem_iter i; int error = 0; size_t len; if (pp->pr_cache == NULL) return (EOPNOTSUPP); if (*oldlenp % sizeof(*kpcc)) return (EINVAL); kpcc = mallocarray(ncpusfound, sizeof(*kpcc), M_TEMP, M_WAITOK|M_CANFAIL|M_ZERO); if (kpcc == NULL) return (EIO); len = ncpusfound * sizeof(*kpcc); CPUMEM_FOREACH(pc, &i, pp->pr_cache) { uint64_t gen; if (cpu >= ncpusfound) { error = EIO; goto err; } info = &kpcc[cpu]; info->pr_cpu = cpu; do { while ((gen = pc->pc_gen) & 1) yield(); info->pr_nget = pc->pc_nget; info->pr_nfail = pc->pc_nfail; info->pr_nput = pc->pc_nput; info->pr_nlget = pc->pc_nlget; info->pr_nlfail = pc->pc_nlfail; info->pr_nlput = pc->pc_nlput; } while (gen != pc->pc_gen); cpu++; } error = sysctl_rdstruct(oldp, oldlenp, NULL, kpcc, len); err: free(kpcc, M_TEMP, len); return (error); } #else /* MULTIPROCESSOR */ void pool_cache_init(struct pool *pp) { /* nop */ } void pool_cache_pool_info(struct pool *pp, struct kinfo_pool *pi) { /* nop */ } int pool_cache_info(struct pool *pp, void *oldp, size_t *oldlenp) { return (EOPNOTSUPP); } int pool_cache_cpus_info(struct pool *pp, void *oldp, size_t *oldlenp) { return (EOPNOTSUPP); } #endif /* MULTIPROCESSOR */ void pool_lock_mtx_init(struct pool *pp, union pool_lock *lock, const struct lock_type *type) { _mtx_init_flags(&lock->prl_mtx, pp->pr_ipl, pp->pr_wchan, 0, type); } void pool_lock_mtx_enter(union pool_lock *lock) { mtx_enter(&lock->prl_mtx); } int pool_lock_mtx_enter_try(union pool_lock *lock) { return (mtx_enter_try(&lock->prl_mtx)); } void pool_lock_mtx_leave(union pool_lock *lock) { mtx_leave(&lock->prl_mtx); } void pool_lock_mtx_assert_locked(union pool_lock *lock) { MUTEX_ASSERT_LOCKED(&lock->prl_mtx); } void pool_lock_mtx_assert_unlocked(union pool_lock *lock) { MUTEX_ASSERT_UNLOCKED(&lock->prl_mtx); } int pool_lock_mtx_sleep(void *ident, union pool_lock *lock, int priority, const char *wmesg) { return msleep_nsec(ident, &lock->prl_mtx, priority, wmesg, INFSLP); } static const struct pool_lock_ops pool_lock_ops_mtx = { pool_lock_mtx_init, pool_lock_mtx_enter, pool_lock_mtx_enter_try, pool_lock_mtx_leave, pool_lock_mtx_assert_locked, pool_lock_mtx_assert_unlocked, pool_lock_mtx_sleep, }; void pool_lock_rw_init(struct pool *pp, union pool_lock *lock, const struct lock_type *type) { _rw_init_flags(&lock->prl_rwlock, pp->pr_wchan, 0, type); } void pool_lock_rw_enter(union pool_lock *lock) { rw_enter_write(&lock->prl_rwlock); } int pool_lock_rw_enter_try(union pool_lock *lock) { return (rw_enter(&lock->prl_rwlock, RW_WRITE | RW_NOSLEEP) == 0); } void pool_lock_rw_leave(union pool_lock *lock) { rw_exit_write(&lock->prl_rwlock); } void pool_lock_rw_assert_locked(union pool_lock *lock) { rw_assert_wrlock(&lock->prl_rwlock); } void pool_lock_rw_assert_unlocked(union pool_lock *lock) { KASSERT(rw_status(&lock->prl_rwlock) != RW_WRITE); } int pool_lock_rw_sleep(void *ident, union pool_lock *lock, int priority, const char *wmesg) { return rwsleep_nsec(ident, &lock->prl_rwlock, priority, wmesg, INFSLP); } static const struct pool_lock_ops pool_lock_ops_rw = { pool_lock_rw_init, pool_lock_rw_enter, pool_lock_rw_enter_try, pool_lock_rw_leave, pool_lock_rw_assert_locked, pool_lock_rw_assert_unlocked, pool_lock_rw_sleep, };
1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 /* $OpenBSD: cy.c,v 1.42 2023/09/11 08:41:26 mvs Exp $ */ /* * Copyright (c) 1996 Timo Rossi. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * cy.c * * Driver for Cyclades Cyclom-8/16/32 multiport serial cards * (currently not tested with Cyclom-32 cards) * * Timo Rossi, 1996 * * Supports both ISA and PCI Cyclom cards * * Uses CD1400 automatic CTS flow control, and * if CY_HW_RTS is defined, uses CD1400 automatic input flow control. * This requires a special cable that exchanges the RTS and DTR lines. * * Lots of debug output can be enabled by defining CY_DEBUG * Some debugging counters (number of receive/transmit interrupts etc.) * can be enabled by defining CY_DEBUG1 * * This version uses the bus_space/io_??() stuff * */ #include <sys/param.h> #include <sys/ioctl.h> #include <sys/syslog.h> #include <sys/fcntl.h> #include <sys/tty.h> #include <sys/conf.h> #include <sys/device.h> #include <sys/malloc.h> #include <sys/systm.h> #include <machine/bus.h> #include <machine/intr.h> #include <dev/ic/cd1400reg.h> #include <dev/ic/cyreg.h> int cy_intr(void *); int cyparam(struct tty *, struct termios *); void cystart(struct tty *); void cy_poll(void *); int cy_modem_control(struct cy_port *, int, int); void cy_enable_transmitter(struct cy_port *); void cd1400_channel_cmd(struct cy_port *, int); int cy_speed(speed_t, int *, int *, int); struct cfdriver cy_cd = { NULL, "cy", DV_TTY }; /* * Common probe routine * * returns the number of chips found. */ int cy_probe_common(bus_space_tag_t memt, bus_space_handle_t memh, int bustype) { int cy_chip, chip_offs; u_char firmware_ver; int nchips; /* Cyclom card hardware reset */ bus_space_write_1(memt, memh, CY16_RESET<<bustype, 0); DELAY(500); /* wait for reset to complete */ bus_space_write_1(memt, memh, CY_CLEAR_INTR<<bustype, 0); #ifdef CY_DEBUG printf("cy: card reset done\n"); #endif nchips = 0; for (cy_chip = 0, chip_offs = 0; cy_chip < CY_MAX_CD1400s; cy_chip++, chip_offs += (CY_CD1400_MEMSPACING << bustype)) { int i; /* the last 4 cd1400s are 'interleaved' with the first 4 on 32-port boards */ if (cy_chip == 4) chip_offs -= (CY32_ADDR_FIX << bustype); #ifdef CY_DEBUG printf("cy: probe chip %d offset 0x%x ... ", cy_chip, chip_offs); #endif /* wait until the chip is ready for command */ DELAY(1000); if (bus_space_read_1(memt, memh, chip_offs + ((CD1400_CCR << 1) << bustype)) != 0) { #ifdef CY_DEBUG printf("not ready for command\n"); #endif break; } /* clear the firmware version reg. */ bus_space_write_1(memt, memh, chip_offs + ((CD1400_GFRCR << 1) << bustype), 0); /* * On Cyclom-16 references to non-existent chip 4 * actually access chip 0 (address line 9 not decoded). * Here we check if the clearing of chip 4 GFRCR actually * cleared chip 0 GFRCR. In that case we have a 16 port card. */ if (cy_chip == 4 && bus_space_read_1(memt, memh, chip_offs + ((CD1400_GFRCR << 1) << bustype)) == 0) break; /* reset the chip */ bus_space_write_1(memt, memh, chip_offs + ((CD1400_CCR << 1) << bustype), CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); /* wait for the chip to initialize itself */ for (i = 0; i < 200; i++) { DELAY(50); firmware_ver = bus_space_read_1(memt, memh, chip_offs + ((CD1400_GFRCR << 1) << bustype)); if ((firmware_ver & 0xf0) == 0x40) /* found a CD1400 */ break; } #ifdef CY_DEBUG printf("firmware version 0x%x\n", firmware_ver); #endif if ((firmware_ver & 0xf0) != 0x40) break; /* firmware version OK, CD1400 found */ nchips++; } if (nchips == 0) { #ifdef CY_DEBUG printf("no CD1400s found\n"); #endif return (0); } #ifdef CY_DEBUG printf("found %d CD1400s\n", nchips); #endif return (nchips); } void cy_attach(struct device *parent, struct device *self) { int card, port, cy_chip, num_chips, cdu, chip_offs, cy_clock; struct cy_softc *sc = (void *)self; card = sc->sc_dev.dv_unit; num_chips = sc->sc_nr_cd1400s; if (num_chips == 0) return; timeout_set(&sc->sc_poll_to, cy_poll, sc); bzero(sc->sc_ports, sizeof(sc->sc_ports)); sc->sc_nports = num_chips * CD1400_NO_OF_CHANNELS; port = 0; for (cy_chip = 0, chip_offs = 0; cy_chip < num_chips; cy_chip++, chip_offs += (CY_CD1400_MEMSPACING<<sc->sc_bustype)) { if (cy_chip == 4) chip_offs -= (CY32_ADDR_FIX<<sc->sc_bustype); #ifdef CY_DEBUG printf("attach CD1400 #%d offset 0x%x\n", cy_chip, chip_offs); #endif sc->sc_cd1400_offs[cy_chip] = chip_offs; /* configure port 0 as serial port (should already be after reset) */ cd_write_reg_sc(sc, cy_chip, CD1400_GCR, 0); /* Set cy_clock depending on firmware version */ if (cd_read_reg_sc(sc, cy_chip, CD1400_GFRCR) <= 0x46) cy_clock = CY_CLOCK; else cy_clock = CY_CLOCK_60; /* set up a receive timeout period (1ms) */ cd_write_reg_sc(sc, cy_chip, CD1400_PPR, (cy_clock / CD1400_PPR_PRESCALER / 1000) + 1); for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; cdu++) { sc->sc_ports[port].cy_port_num = port; sc->sc_ports[port].cy_memt = sc->sc_memt; sc->sc_ports[port].cy_memh = sc->sc_memh; sc->sc_ports[port].cy_chip_offs = chip_offs; sc->sc_ports[port].cy_bustype = sc->sc_bustype; sc->sc_ports[port].cy_clock = cy_clock; /* should we initialize anything else here? */ port++; } /* for(each port on one CD1400...) */ } /* for(each CD1400 on a card... ) */ printf(": %d ports\n", port); /* ensure an edge for the next interrupt */ bus_space_write_1(sc->sc_memt, sc->sc_memh, CY_CLEAR_INTR<<sc->sc_bustype, 0); } /* * open routine. returns zero if successful, else error code */ int cyopen(dev_t, int, int, struct proc *); int cyclose(dev_t, int, int, struct proc *); int cyread(dev_t, struct uio *, int); int cywrite(dev_t, struct uio *, int); struct tty *cytty(dev_t); int cyioctl(dev_t, u_long, caddr_t, int, struct proc *); int cystop(struct tty *, int flag); int cyopen(dev_t dev, int flag, int mode, struct proc *p) { int card = CY_CARD(dev); int port = CY_PORT(dev); struct cy_softc *sc; struct cy_port *cy; struct tty *tp; int s, error; if (card >= cy_cd.cd_ndevs || (sc = cy_cd.cd_devs[card]) == NULL) { return (ENXIO); } #ifdef CY_DEBUG printf("%s open port %d flag 0x%x mode 0x%x\n", sc->sc_dev.dv_xname, port, flag, mode); #endif cy = &sc->sc_ports[port]; s = spltty(); if (cy->cy_tty == NULL) { cy->cy_tty = ttymalloc(0); } splx(s); tp = cy->cy_tty; tp->t_oproc = cystart; tp->t_param = cyparam; tp->t_dev = dev; if (!ISSET(tp->t_state, TS_ISOPEN)) { SET(tp->t_state, TS_WOPEN); ttychars(tp); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_cflag = TTYDEF_CFLAG; if (ISSET(cy->cy_openflags, TIOCFLAG_CLOCAL)) SET(tp->t_cflag, CLOCAL); if (ISSET(cy->cy_openflags, TIOCFLAG_CRTSCTS)) SET(tp->t_cflag, CRTSCTS); if (ISSET(cy->cy_openflags, TIOCFLAG_MDMBUF)) SET(tp->t_cflag, MDMBUF); tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; s = spltty(); /* * Allocate input ring buffer if we don't already have one */ if (cy->cy_ibuf == NULL) { cy->cy_ibuf = malloc(IBUF_SIZE, M_DEVBUF, M_NOWAIT); if (cy->cy_ibuf == NULL) { printf("%s: (port %d) can't allocate input buffer\n", sc->sc_dev.dv_xname, port); splx(s); return (ENOMEM); } cy->cy_ibuf_end = cy->cy_ibuf + IBUF_SIZE; } /* mark the ring buffer as empty */ cy->cy_ibuf_rd_ptr = cy->cy_ibuf_wr_ptr = cy->cy_ibuf; /* select CD1400 channel */ cd_write_reg(cy, CD1400_CAR, port & CD1400_CAR_CHAN); /* reset the channel */ cd1400_channel_cmd(cy, CD1400_CCR_CMDRESET); /* encode unit (port) number in LIVR */ /* there is just enough space for 5 bits (32 ports) */ cd_write_reg(cy, CD1400_LIVR, port << 3); cy->cy_channel_control = 0; if (!timeout_pending(&sc->sc_poll_to)) timeout_add(&sc->sc_poll_to, 1); /* this sets parameters and raises DTR */ cyparam(tp, &tp->t_termios); ttsetwater(tp); /* raise RTS too */ cy_modem_control(cy, TIOCM_RTS, DMBIS); cy->cy_carrier_stat = cd_read_reg(cy, CD1400_MSVR2); /* enable receiver and modem change interrupts */ cd_write_reg(cy, CD1400_SRER, CD1400_SRER_MDMCH | CD1400_SRER_RXDATA); if (CY_DIALOUT(dev) || ISSET(cy->cy_openflags, TIOCFLAG_SOFTCAR) || ISSET(tp->t_cflag, MDMBUF) || ISSET(cy->cy_carrier_stat, CD1400_MSVR2_CD)) SET(tp->t_state, TS_CARR_ON); else CLR(tp->t_state, TS_CARR_ON); } else if (ISSET(tp->t_state, TS_XCLUDE) && suser(p) != 0) { return (EBUSY); } else { s = spltty(); } /* wait for carrier if necessary */ if (!ISSET(flag, O_NONBLOCK)) { while (!ISSET(tp->t_cflag, CLOCAL) && !ISSET(tp->t_state, TS_CARR_ON)) { SET(tp->t_state, TS_WOPEN); error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, ttopen); if (error != 0) { splx(s); CLR(tp->t_state, TS_WOPEN); return (error); } } } splx(s); return (*linesw[tp->t_line].l_open)(dev, tp, p); } /* * close routine. returns zero if successful, else error code */ int cyclose(dev_t dev, int flag, int mode, struct proc *p) { int card = CY_CARD(dev); int port = CY_PORT(dev); struct cy_softc *sc = cy_cd.cd_devs[card]; struct cy_port *cy = &sc->sc_ports[port]; struct tty *tp = cy->cy_tty; int s; #ifdef CY_DEBUG printf("%s close port %d, flag 0x%x, mode 0x%x\n", sc->sc_dev.dv_xname, port, flag, mode); #endif (*linesw[tp->t_line].l_close)(tp, flag, p); s = spltty(); if (ISSET(tp->t_cflag, HUPCL) && !ISSET(cy->cy_openflags, TIOCFLAG_SOFTCAR)) { /* drop DTR and RTS (should we wait for output buffer to become empty first?) */ cy_modem_control(cy, 0, DMSET); } /* * XXX should we disable modem change and * receive interrupts here or somewhere ? */ CLR(tp->t_state, TS_BUSY | TS_FLUSH); splx(s); ttyclose(tp); return (0); } /* * Read routine */ int cyread(dev_t dev, struct uio *uio, int flag) { int card = CY_CARD(dev); int port = CY_PORT(dev); struct cy_softc *sc = cy_cd.cd_devs[card]; struct cy_port *cy = &sc->sc_ports[port]; struct tty *tp = cy->cy_tty; #ifdef CY_DEBUG printf("%s read port %d uio %p flag 0x%x\n", sc->sc_dev.dv_xname, port, uio, flag); #endif return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); } /* * Write routine */ int cywrite(dev_t dev, struct uio *uio, int flag) { int card = CY_CARD(dev); int port = CY_PORT(dev); struct cy_softc *sc = cy_cd.cd_devs[card]; struct cy_port *cy = &sc->sc_ports[port]; struct tty *tp = cy->cy_tty; #ifdef CY_DEBUG printf("%s write port %d uio %p flag 0x%x\n", sc->sc_dev.dv_xname, port, uio, flag); #endif return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); } /* * return tty pointer */ struct tty * cytty(dev_t dev) { int card = CY_CARD(dev); int port = CY_PORT(dev); struct cy_softc *sc = cy_cd.cd_devs[card]; struct cy_port *cy = &sc->sc_ports[port]; struct tty *tp = cy->cy_tty; return (tp); } /* * ioctl routine */ int cyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { int card = CY_CARD(dev); int port = CY_PORT(dev); struct cy_softc *sc = cy_cd.cd_devs[card]; struct cy_port *cy = &sc->sc_ports[port]; struct tty *tp = cy->cy_tty; int error; #ifdef CY_DEBUG printf("%s port %d ioctl cmd 0x%lx data %p flag 0x%x\n", sc->sc_dev.dv_xname, port, cmd, data, flag); #endif error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); if (error >= 0) return (error); error = ttioctl(tp, cmd, data, flag, p); if (error >= 0) return (error); /* XXX should not allow dropping DTR when dialin? */ switch (cmd) { case TIOCSBRK: /* start break */ SET(cy->cy_flags, CYF_START_BREAK); cy_enable_transmitter(cy); break; case TIOCCBRK: /* stop break */ SET(cy->cy_flags, CYF_END_BREAK); cy_enable_transmitter(cy); break; case TIOCSDTR: /* DTR on */ cy_modem_control(cy, TIOCM_DTR, DMBIS); break; case TIOCCDTR: /* DTR off */ cy_modem_control(cy, TIOCM_DTR, DMBIC); break; case TIOCMSET: /* set new modem control line values */ cy_modem_control(cy, *((int *)data), DMSET); break; case TIOCMBIS: /* turn modem control bits on */ cy_modem_control(cy, *((int *)data), DMBIS); break; case TIOCMBIC: /* turn modem control bits off */ cy_modem_control(cy, *((int *)data), DMBIC); break; case TIOCMGET: /* get modem control/status line state */ *((int *)data) = cy_modem_control(cy, 0, DMGET); break; case TIOCGFLAGS: *((int *)data) = cy->cy_openflags | (CY_DIALOUT(dev) ? TIOCFLAG_SOFTCAR : 0); break; case TIOCSFLAGS: error = suser(p); if (error != 0) return (EPERM); cy->cy_openflags = *((int *)data) & (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF); break; default: return (ENOTTY); } return (0); } /* * start output */ void cystart(struct tty *tp) { int card = CY_CARD(tp->t_dev); int port = CY_PORT(tp->t_dev); struct cy_softc *sc = cy_cd.cd_devs[card]; struct cy_port *cy = &sc->sc_ports[port]; int s; #ifdef CY_DEBUG printf("%s port %d start, tty %p\n", sc->sc_dev.dv_xname, port, tp); #endif s = spltty(); #ifdef CY_DEBUG1 cy->cy_start_count++; #endif if (!ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) { ttwakeupwr(tp); if (tp->t_outq.c_cc == 0) goto out; SET(tp->t_state, TS_BUSY); cy_enable_transmitter(cy); } out: splx(s); } /* * stop output */ int cystop(struct tty *tp, int flag) { int card = CY_CARD(tp->t_dev); int port = CY_PORT(tp->t_dev); struct cy_softc *sc = cy_cd.cd_devs[card]; struct cy_port *cy = &sc->sc_ports[port]; int s; #ifdef CY_DEBUG printf("%s port %d stop tty %p flag 0x%x\n", sc->sc_dev.dv_xname, port, tp, flag); #endif s = spltty(); if (ISSET(tp->t_state, TS_BUSY)) { if (!ISSET(tp->t_state, TS_TTSTOP)) SET(tp->t_state, TS_FLUSH); /* * the transmit interrupt routine will disable transmit when it * notices that CYF_STOP has been set. */ SET(cy->cy_flags, CYF_STOP); } splx(s); return (0); } /* * parameter setting routine. * returns 0 if successful, else returns error code */ int cyparam(struct tty *tp, struct termios *t) { int card = CY_CARD(tp->t_dev); int port = CY_PORT(tp->t_dev); struct cy_softc *sc = cy_cd.cd_devs[card]; struct cy_port *cy = &sc->sc_ports[port]; int ibpr, obpr, i_clk_opt, o_clk_opt; int s, opt; #ifdef CY_DEBUG printf("%s port %d param tty %p termios %p\n", sc->sc_dev.dv_xname, port, tp, t); printf("ispeed %d ospeed %d\n", t->c_ispeed, t->c_ospeed); #endif if (t->c_ospeed != 0 && cy_speed(t->c_ospeed, &o_clk_opt, &obpr, cy->cy_clock) < 0) return (EINVAL); if (t->c_ispeed != 0 && cy_speed(t->c_ispeed, &i_clk_opt, &ibpr, cy->cy_clock) < 0) return (EINVAL); s = spltty(); /* hang up the line is ospeed is zero, else turn DTR on */ cy_modem_control(cy, TIOCM_DTR, (t->c_ospeed == 0 ? DMBIC : DMBIS)); /* channel was selected by the above call to cy_modem_control() */ /* cd_write_reg(cy, CD1400_CAR, port & CD1400_CAR_CHAN); */ /* set transmit speed */ if (t->c_ospeed != 0) { cd_write_reg(cy, CD1400_TCOR, o_clk_opt); cd_write_reg(cy, CD1400_TBPR, obpr); } /* set receive speed */ if (t->c_ispeed != 0) { cd_write_reg(cy, CD1400_RCOR, i_clk_opt); cd_write_reg(cy, CD1400_RBPR, ibpr); } opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN | (ISSET(t->c_cflag, CREAD) ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS); if (opt != cy->cy_channel_control) { cy->cy_channel_control = opt; cd1400_channel_cmd(cy, opt); } /* compute COR1 contents */ opt = 0; if (ISSET(t->c_cflag, PARENB)) { if (ISSET(t->c_cflag, PARODD)) opt |= CD1400_COR1_PARODD; opt |= CD1400_COR1_PARNORMAL; } if (!ISSET(t->c_iflag, INPCK)) opt |= CD1400_COR1_NOINPCK; /* no parity checking */ if (ISSET(t->c_cflag, CSTOPB)) opt |= CD1400_COR1_STOP2; switch (t->c_cflag & CSIZE) { case CS5: opt |= CD1400_COR1_CS5; break; case CS6: opt |= CD1400_COR1_CS6; break; case CS7: opt |= CD1400_COR1_CS7; break; default: opt |= CD1400_COR1_CS8; break; } cd_write_reg(cy, CD1400_COR1, opt); #ifdef CY_DEBUG printf("cor1 = 0x%x...", opt); #endif /* * use the CD1400 automatic CTS flow control if CRTSCTS is set * * CD1400_COR2_ETC is used because breaks are generated with * embedded transmit commands */ cd_write_reg(cy, CD1400_COR2, CD1400_COR2_ETC | (ISSET(t->c_cflag, CRTSCTS) ? CD1400_COR2_CCTS_OFLOW : 0)); cd_write_reg(cy, CD1400_COR3, RX_FIFO_THRESHOLD); cd1400_channel_cmd(cy, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR1 | CD1400_CCR_COR2 | CD1400_CCR_COR3); cd_write_reg(cy, CD1400_COR4, CD1400_COR4_PFO_EXCEPTION); cd_write_reg(cy, CD1400_COR5, 0); /* * set modem change option registers to generate interrupts * on carrier detect changes. * * if hardware RTS handshaking is used (CY_HW_RTS, DTR and RTS lines * exchanged), also set the handshaking threshold. */ #ifdef CY_HW_RTS cd_write_reg(cy, CD1400_MCOR1, CD1400_MCOR1_CDzd | (ISSET(t->c_cflag, CRTSCTS) ? RX_DTR_THRESHOLD : 0)); #else cd_write_reg(cy, CD1400_MCOR1, CD1400_MCOR1_CDzd); #endif /* CY_HW_RTS */ cd_write_reg(cy, CD1400_MCOR2, CD1400_MCOR2_CDod); /* * set receive timeout to approx. 2ms * could use more complex logic here... * (but is it actually needed or even useful?) */ cd_write_reg(cy, CD1400_RTPR, 2); /* * should do anything else here? * XXX check MDMBUF handshaking like in com.c? */ splx(s); return (0); } /* * set/get modem line status * * bits can be: TIOCM_DTR, TIOCM_RTS, TIOCM_CTS, TIOCM_CD, TIOCM_RI, TIOCM_DSR * * RTS and DTR are exchanged if CY_HW_RTS is set * */ int cy_modem_control(struct cy_port *cy, int bits, int howto) { int s, msvr; s = spltty(); /* select channel */ cd_write_reg(cy, CD1400_CAR, cy->cy_port_num & CD1400_CAR_CHAN); /* does not manipulate RTS if it is used for flow control */ switch (howto) { case DMGET: bits = 0; if (cy->cy_channel_control & CD1400_CCR_RCVEN) bits |= TIOCM_LE; msvr = cd_read_reg(cy, CD1400_MSVR2); #ifdef CY_HW_RTS if (cd_read_reg(cy, CD1400_MSVR1) & CD1400_MSVR1_RTS) bits |= TIOCM_DTR; if (msvr & CD1400_MSVR2_DTR) bits |= TIOCM_RTS; #else if (cd_read_reg(cy, CD1400_MSVR1) & CD1400_MSVR1_RTS) bits |= TIOCM_RTS; if (msvr & CD1400_MSVR2_DTR) bits |= TIOCM_DTR; #endif /* CY_HW_RTS */ if (msvr & CD1400_MSVR2_CTS) bits |= TIOCM_CTS; if (msvr & CD1400_MSVR2_CD) bits |= TIOCM_CD; if (msvr & CD1400_MSVR2_DSR) /* not connected on some Cyclom cards? */ bits |= TIOCM_DSR; if (msvr & CD1400_MSVR2_RI) /* not connected on Cyclom-8Y cards? */ bits |= TIOCM_RI; splx(s); return (bits); case DMSET: /* replace old values with new ones */ #ifdef CY_HW_RTS if (!ISSET(cy->cy_tty->t_cflag, CRTSCTS)) cd_write_reg(cy, CD1400_MSVR2, ((bits & TIOCM_RTS) ? CD1400_MSVR2_DTR : 0)); cd_write_reg(cy, CD1400_MSVR1, ((bits & TIOCM_DTR) ? CD1400_MSVR1_RTS : 0)); #else if (!ISSET(cy->cy_tty->t_cflag, CRTSCTS)) cd_write_reg(cy, CD1400_MSVR1, ((bits & TIOCM_RTS) ? CD1400_MSVR1_RTS : 0)); cd_write_reg(cy, CD1400_MSVR2, ((bits & TIOCM_DTR) ? CD1400_MSVR2_DTR : 0)); #endif /* CY_HW_RTS */ break; case DMBIS: /* set bits */ #ifdef CY_HW_RTS if (!ISSET(cy->cy_tty->t_cflag, CRTSCTS) && (bits & TIOCM_RTS) != 0) cd_write_reg(cy, CD1400_MSVR2, CD1400_MSVR2_DTR); if (bits & TIOCM_DTR) cd_write_reg(cy, CD1400_MSVR1, CD1400_MSVR1_RTS); #else if (!ISSET(cy->cy_tty->t_cflag, CRTSCTS) && (bits & TIOCM_RTS) != 0) cd_write_reg(cy, CD1400_MSVR1, CD1400_MSVR1_RTS); if (bits & TIOCM_DTR) cd_write_reg(cy, CD1400_MSVR2, CD1400_MSVR2_DTR); #endif /* CY_HW_RTS */ break; case DMBIC: /* clear bits */ #ifdef CY_HW_RTS if (!ISSET(cy->cy_tty->t_cflag, CRTSCTS) && (bits & TIOCM_RTS)) cd_write_reg(cy, CD1400_MSVR2, 0); if (bits & TIOCM_DTR) cd_write_reg(cy, CD1400_MSVR1, 0); #else if (!ISSET(cy->cy_tty->t_cflag, CRTSCTS) && (bits & TIOCM_RTS)) cd_write_reg(cy, CD1400_MSVR1, 0); if (bits & TIOCM_DTR) cd_write_reg(cy, CD1400_MSVR2, 0); #endif /* CY_HW_RTS */ break; } splx(s); return (0); } /* * Upper-level handler loop (called from timer interrupt?) * This routine is common for multiple cards */ void cy_poll(void *arg) { int port; struct cy_softc *sc = arg; struct cy_port *cy; struct tty *tp; static int counter = 0; #ifdef CY_DEBUG1 int did_something; #endif int s; s = spltty(); if (sc->sc_events == 0 && ++counter < 200) { splx(s); goto out; } sc->sc_events = 0; splx(s); #ifdef CY_DEBUG1 sc->sc_poll_count1++; did_something = 0; #endif for (port = 0; port < sc->sc_nports; port++) { cy = &sc->sc_ports[port]; if ((tp = cy->cy_tty) == NULL || cy->cy_ibuf == NULL || !ISSET(tp->t_state, TS_ISOPEN | TS_WOPEN)) continue; /* * handle received data */ while (cy->cy_ibuf_rd_ptr != cy->cy_ibuf_wr_ptr) { u_char line_stat; int chr; line_stat = cy->cy_ibuf_rd_ptr[0]; chr = cy->cy_ibuf_rd_ptr[1]; if (line_stat & (CD1400_RDSR_BREAK|CD1400_RDSR_FE)) chr |= TTY_FE; if (line_stat & CD1400_RDSR_PE) chr |= TTY_PE; /* * on an overrun error the data is treated as * good just as it should be. */ #ifdef CY_DEBUG printf("%s port %d ttyinput 0x%x\n", sc->sc_dev.dv_xname, port, chr); #endif (*linesw[tp->t_line].l_rint)(chr, tp); s = spltty(); /* really necessary? */ if ((cy->cy_ibuf_rd_ptr += 2) == cy->cy_ibuf_end) cy->cy_ibuf_rd_ptr = cy->cy_ibuf; splx(s); #ifdef CY_DEBUG1 did_something = 1; #endif } #ifndef CY_HW_RTS /* * If we don't have any received data in ibuf and * CRTSCTS is on and RTS is turned off, it is time * to turn RTS back on */ if (ISSET(tp->t_cflag, CRTSCTS)) { /* we can't use cy_modem_control() here as it doesn't change RTS if RTSCTS is on */ cd_write_reg(cy, CD1400_CAR, port & CD1400_CAR_CHAN); if ((cd_read_reg(cy, CD1400_MSVR1) & CD1400_MSVR1_RTS) == 0) { cd_write_reg(cy, CD1400_MSVR1, CD1400_MSVR1_RTS); #ifdef CY_DEBUG1 did_something = 1; #endif } } #endif /* CY_HW_RTS */ /* * handle carrier changes */ s = spltty(); if (ISSET(cy->cy_flags, CYF_CARRIER_CHANGED)) { int carrier; CLR(cy->cy_flags, CYF_CARRIER_CHANGED); splx(s); carrier = ((cy->cy_carrier_stat & CD1400_MSVR2_CD) != 0); #ifdef CY_DEBUG printf("%s: cy_poll: carrier change " "(port %d, carrier %d)\n", sc->sc_dev.dv_xname, port, carrier); #endif if (CY_DIALIN(tp->t_dev) && !(*linesw[tp->t_line].l_modem)(tp, carrier)) cy_modem_control(cy, TIOCM_DTR, DMBIC); #ifdef CY_DEBUG1 did_something = 1; #endif } else { splx(s); } s = spltty(); if (ISSET(cy->cy_flags, CYF_START)) { CLR(cy->cy_flags, CYF_START); splx(s); (*linesw[tp->t_line].l_start)(tp); #ifdef CY_DEBUG1 did_something = 1; #endif } else { splx(s); } /* could move this to even upper level... */ if (cy->cy_fifo_overruns) { cy->cy_fifo_overruns = 0; /* doesn't report overrun count, but shouldn't really matter */ log(LOG_WARNING, "%s: port %d fifo overrun\n", sc->sc_dev.dv_xname, port); } if (cy->cy_ibuf_overruns) { cy->cy_ibuf_overruns = 0; log(LOG_WARNING, "%s: port %d ibuf overrun\n", sc->sc_dev.dv_xname, port); } } /* for(port...) */ #ifdef CY_DEBUG1 if (did_something && counter >= 200) sc->sc_poll_count2++; #endif counter = 0; out: timeout_add(&sc->sc_poll_to, 1); } /* * hardware interrupt routine */ int cy_intr(void *arg) { struct cy_softc *sc = arg; struct cy_port *cy; int cy_chip, stat; int int_serviced = -1; /* * Check interrupt status of each CD1400 chip on this card * (multiple cards cannot share the same interrupt) */ for (cy_chip = 0; cy_chip < sc->sc_nr_cd1400s; cy_chip++) { stat = cd_read_reg_sc(sc, cy_chip, CD1400_SVRR); if (stat == 0) continue; if (ISSET(stat, CD1400_SVRR_RXRDY)) { u_char save_car, save_rir, serv_type; u_char line_stat, recv_data, n_chars; u_char *buf_p; save_rir = cd_read_reg_sc(sc, cy_chip, CD1400_RIR); save_car = cd_read_reg_sc(sc, cy_chip, CD1400_CAR); /* enter rx service */ cd_write_reg_sc(sc, cy_chip, CD1400_CAR, save_rir); serv_type = cd_read_reg_sc(sc, cy_chip, CD1400_RIVR); cy = &sc->sc_ports[serv_type >> 3]; #ifdef CY_DEBUG1 cy->cy_rx_int_count++; #endif buf_p = cy->cy_ibuf_wr_ptr; if (ISSET(serv_type, CD1400_RIVR_EXCEPTION)) { line_stat = cd_read_reg(cy, CD1400_RDSR); recv_data = cd_read_reg(cy, CD1400_RDSR); if (cy->cy_tty == NULL || !ISSET(cy->cy_tty->t_state, TS_ISOPEN)) goto end_rx_serv; #ifdef CY_DEBUG printf("%s port %d recv exception, " "line_stat 0x%x, char 0x%x\n", sc->sc_dev.dv_xname, cy->cy_port_num, line_stat, recv_data); #endif if (ISSET(line_stat, CD1400_RDSR_OE)) cy->cy_fifo_overruns++; *buf_p++ = line_stat; *buf_p++ = recv_data; if (buf_p == cy->cy_ibuf_end) buf_p = cy->cy_ibuf; if (buf_p == cy->cy_ibuf_rd_ptr) { if (buf_p == cy->cy_ibuf) buf_p = cy->cy_ibuf_end; buf_p -= 2; cy->cy_ibuf_overruns++; } sc->sc_events = 1; } else { /* no exception, received data OK */ n_chars = cd_read_reg(cy, CD1400_RDCR); /* If no tty or not open, discard data */ if (cy->cy_tty == NULL || !ISSET(cy->cy_tty->t_state, TS_ISOPEN)) { while (n_chars--) cd_read_reg(cy, CD1400_RDSR); goto end_rx_serv; } #ifdef CY_DEBUG printf("%s port %d receive ok %d chars\n", sc->sc_dev.dv_xname, cy->cy_port_num, n_chars); #endif while (n_chars--) { *buf_p++ = 0; /* status: OK */ *buf_p++ = cd_read_reg(cy, CD1400_RDSR); /* data byte */ if (buf_p == cy->cy_ibuf_end) buf_p = cy->cy_ibuf; if (buf_p == cy->cy_ibuf_rd_ptr) { if (buf_p == cy->cy_ibuf) buf_p = cy->cy_ibuf_end; buf_p -= 2; cy->cy_ibuf_overruns++; break; } } sc->sc_events = 1; } cy->cy_ibuf_wr_ptr = buf_p; #ifndef CY_HW_RTS /* RTS handshaking for incoming data */ if (ISSET(cy->cy_tty->t_cflag, CRTSCTS)) { int bf; bf = buf_p - cy->cy_ibuf_rd_ptr; if (bf < 0) bf += IBUF_SIZE; if (bf > (IBUF_SIZE/2)) /* turn RTS off */ cd_write_reg(cy, CD1400_MSVR1, 0); } #endif /* CY_HW_RTS */ end_rx_serv: /* terminate service context */ cd_write_reg(cy, CD1400_RIR, save_rir & 0x3f); cd_write_reg(cy, CD1400_CAR, save_car); int_serviced = 1; } /* if(rx_service...) */ if (ISSET(stat, CD1400_SVRR_MDMCH)) { u_char save_car, save_mir, serv_type, modem_stat; save_mir = cd_read_reg_sc(sc, cy_chip, CD1400_MIR); save_car = cd_read_reg_sc(sc, cy_chip, CD1400_CAR); /* enter modem service */ cd_write_reg_sc(sc, cy_chip, CD1400_CAR, save_mir); serv_type = cd_read_reg_sc(sc, cy_chip, CD1400_MIVR); cy = &sc->sc_ports[serv_type >> 3]; #ifdef CY_DEBUG1 cy->cy_modem_int_count++; #endif modem_stat = cd_read_reg(cy, CD1400_MSVR2); #ifdef CY_DEBUG printf("%s port %d modem line change, new stat 0x%x\n", sc->sc_dev.dv_xname, cy->cy_port_num, modem_stat); #endif if (ISSET((cy->cy_carrier_stat ^ modem_stat), CD1400_MSVR2_CD)) { SET(cy->cy_flags, CYF_CARRIER_CHANGED); sc->sc_events = 1; } cy->cy_carrier_stat = modem_stat; /* terminate service context */ cd_write_reg(cy, CD1400_MIR, save_mir & 0x3f); cd_write_reg(cy, CD1400_CAR, save_car); int_serviced = 1; } /* if(modem_service...) */ if (ISSET(stat, CD1400_SVRR_TXRDY)) { u_char save_car, save_tir, serv_type, count, ch; struct tty *tp; save_tir = cd_read_reg_sc(sc, cy_chip, CD1400_TIR); save_car = cd_read_reg_sc(sc, cy_chip, CD1400_CAR); /* enter tx service */ cd_write_reg_sc(sc, cy_chip, CD1400_CAR, save_tir); serv_type = cd_read_reg_sc(sc, cy_chip, CD1400_TIVR); cy = &sc->sc_ports[serv_type >> 3]; #ifdef CY_DEBUG1 cy->cy_tx_int_count++; #endif #ifdef CY_DEBUG printf("%s port %d tx service\n", sc->sc_dev.dv_xname, cy->cy_port_num); #endif /* stop transmitting if no tty or CYF_STOP set */ tp = cy->cy_tty; if (tp == NULL || ISSET(cy->cy_flags, CYF_STOP)) goto txdone; count = 0; if (ISSET(cy->cy_flags, CYF_SEND_NUL)) { cd_write_reg(cy, CD1400_TDR, 0); cd_write_reg(cy, CD1400_TDR, 0); count += 2; CLR(cy->cy_flags, CYF_SEND_NUL); } if (tp->t_outq.c_cc > 0) { SET(tp->t_state, TS_BUSY); while (tp->t_outq.c_cc > 0 && count < CD1400_TX_FIFO_SIZE) { ch = getc(&tp->t_outq); /* remember to double NUL characters because embedded transmit commands are enabled */ if (ch == 0) { if (count >= CD1400_TX_FIFO_SIZE-2) { SET(cy->cy_flags, CYF_SEND_NUL); break; } cd_write_reg(cy, CD1400_TDR, ch); count++; } cd_write_reg(cy, CD1400_TDR, ch); count++; } } else { /* no data to send -- check if we should start/stop a break */ /* XXX does this cause too much delay before breaks? */ if (ISSET(cy->cy_flags, CYF_START_BREAK)) { cd_write_reg(cy, CD1400_TDR, 0); cd_write_reg(cy, CD1400_TDR, 0x81); CLR(cy->cy_flags, CYF_START_BREAK); } if (ISSET(cy->cy_flags, CYF_END_BREAK)) { cd_write_reg(cy, CD1400_TDR, 0); cd_write_reg(cy, CD1400_TDR, 0x83); CLR(cy->cy_flags, CYF_END_BREAK); } } if (tp->t_outq.c_cc == 0) { txdone: /* * No data to send or requested to stop. * Disable transmit interrupt */ cd_write_reg(cy, CD1400_SRER, cd_read_reg(cy, CD1400_SRER) & ~CD1400_SRER_TXRDY); CLR(cy->cy_flags, CYF_STOP); CLR(tp->t_state, TS_BUSY); } if (tp->t_outq.c_cc <= tp->t_lowat) { SET(cy->cy_flags, CYF_START); sc->sc_events = 1; } /* terminate service context */ cd_write_reg(cy, CD1400_TIR, save_tir & 0x3f); cd_write_reg(cy, CD1400_CAR, save_car); int_serviced = 1; } /* if(tx_service...) */ } /* for(...all CD1400s on a card) */ /* ensure an edge for next interrupt */ bus_space_write_1(sc->sc_memt, sc->sc_memh, CY_CLEAR_INTR<<sc->sc_bustype, 0); return (int_serviced); } /* * subroutine to enable CD1400 transmitter */ void cy_enable_transmitter(struct cy_port *cy) { int s; s = spltty(); cd_write_reg(cy, CD1400_CAR, cy->cy_port_num & CD1400_CAR_CHAN); cd_write_reg(cy, CD1400_SRER, cd_read_reg(cy, CD1400_SRER) | CD1400_SRER_TXRDY); splx(s); } /* * Execute a CD1400 channel command */ void cd1400_channel_cmd(struct cy_port *cy, int cmd) { u_int waitcnt = 5 * 8 * 1024; /* approx 5 ms */ #ifdef CY_DEBUG printf("c1400_channel_cmd cy %p command 0x%x\n", cy, cmd); #endif /* wait until cd1400 is ready to process a new command */ while (cd_read_reg(cy, CD1400_CCR) != 0 && waitcnt-- > 0) ; if (waitcnt == 0) log(LOG_ERR, "cy: channel command timeout\n"); cd_write_reg(cy, CD1400_CCR, cmd); } /* * Compute clock option register and baud rate register values * for a given speed. Return 0 on success, -1 on failure. * * The error between requested and actual speed seems * to be well within allowed limits (less than 3%) * with every speed value between 50 and 150000 bps. */ int cy_speed(speed_t speed, int *cor, int *bpr, int cy_clock) { int c, co, br; if (speed < 50 || speed > 150000) return (-1); for (c = 0, co = 8; co <= 2048; co <<= 2, c++) { br = (cy_clock + (co * speed) / 2) / (co * speed); if (br < 0x100) { *bpr = br; *cor = c; return (0); } } return (-1); }
1059 1056 1 1056 1 763 763 38 763 354 489 333 761 763 763 6501 1056 1058 1058 1058 1 1057 6501 1310 1307 1310 6491 6494 6497 6513 3205 4111 59 6446 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 /* $OpenBSD: trap.c,v 1.105 2024/02/21 15:53:07 deraadt Exp $ */ /* $NetBSD: trap.c,v 1.2 2003/05/04 23:51:56 fvdl Exp $ */ /*- * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Charles M. Hannum. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * the University of Utah, and William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)trap.c 7.4 (Berkeley) 5/13/91 */ /* * amd64 Trap and System call handling */ #undef TRAP_SIGDEBUG #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/signalvar.h> #include <sys/user.h> #include <sys/signal.h> #include <sys/syscall.h> #include <sys/syscall_mi.h> #include <sys/stdarg.h> #include <uvm/uvm_extern.h> #include <machine/cpu.h> #include <machine/cpufunc.h> #include <machine/fpu.h> #include <machine/psl.h> #include <machine/trap.h> #ifdef DDB #include <ddb/db_output.h> #include <machine/db_machdep.h> #endif #include "isa.h" int upageflttrap(struct trapframe *, uint64_t); int kpageflttrap(struct trapframe *, uint64_t); void kerntrap(struct trapframe *); void usertrap(struct trapframe *); void ast(struct trapframe *); void syscall(struct trapframe *); const char * const trap_type[] = { "privileged instruction fault", /* 0 T_PRIVINFLT */ "breakpoint trap", /* 1 T_BPTFLT */ "arithmetic trap", /* 2 T_ARITHTRAP */ "reserved trap", /* 3 T_RESERVED */ "protection fault", /* 4 T_PROTFLT */ "trace trap", /* 5 T_TRCTRAP */ "page fault", /* 6 T_PAGEFLT */ "alignment fault", /* 7 T_ALIGNFLT */ "integer divide fault", /* 8 T_DIVIDE */ "non-maskable interrupt", /* 9 T_NMI */ "overflow trap", /* 10 T_OFLOW */ "bounds check fault", /* 11 T_BOUND */ "FPU not available fault", /* 12 T_DNA */ "double fault", /* 13 T_DOUBLEFLT */ "FPU operand fetch fault", /* 14 T_FPOPFLT */ "invalid TSS fault", /* 15 T_TSSFLT */ "segment not present fault", /* 16 T_SEGNPFLT */ "stack fault", /* 17 T_STKFLT */ "machine check", /* 18 T_MCA */ "SSE FP exception", /* 19 T_XMM */ "virtualization exception", /* 20 T_VE */ "control protection exception", /* 21 T_CP */ }; const int trap_types = nitems(trap_type); #ifdef DEBUG int trapdebug = 0; #endif static void trap_print(struct trapframe *, int _type); static inline void frame_dump(struct trapframe *_tf, struct proc *_p, const char *_sig, uint64_t _cr2); static inline void verify_smap(const char *_func); static inline int verify_pkru(struct proc *); static inline void debug_trap(struct trapframe *_frame, struct proc *_p, long _type); static inline void fault(const char *fmt, ...) { struct cpu_info *ci = curcpu(); va_list ap; atomic_cas_ptr(&panicstr, NULL, ci->ci_panicbuf); va_start(ap, fmt); vsnprintf(ci->ci_panicbuf, sizeof(ci->ci_panicbuf), fmt, ap); va_end(ap); #ifdef DDB db_printf("%s\n", ci->ci_panicbuf); #else printf("%s\n", ci->ci_panicbuf); #endif } static inline int pgex2access(int pgex) { if (pgex & PGEX_W) return PROT_WRITE; else if (pgex & PGEX_I) return PROT_EXEC; return PROT_READ; } /* * upageflttrap(frame, usermode): page fault handler * Returns non-zero if the fault was handled (possibly by generating * a signal). Returns zero, possibly still holding the kernel lock, * if something was so broken that we should panic. */ int upageflttrap(struct trapframe *frame, uint64_t cr2) { struct proc *p = curproc; vaddr_t va = trunc_page((vaddr_t)cr2); vm_prot_t access_type = pgex2access(frame->tf_err); union sigval sv; int signal, sicode, error; /* * If NX is not enabled, we cant distinguish between PROT_READ * and PROT_EXEC access, so try both. */ error = uvm_fault(&p->p_vmspace->vm_map, va, 0, access_type); if (pg_nx == 0 && error == EACCES && access_type == PROT_READ) error = uvm_fault(&p->p_vmspace->vm_map, va, 0, PROT_EXEC); if (error == 0) { uvm_grow(p, va); return 1; } signal = SIGSEGV; sicode = SEGV_MAPERR; if (error == ENOMEM) { printf("UVM: pid %d (%s), uid %d killed:" " out of swap\n", p->p_p->ps_pid, p->p_p->ps_comm, p->p_ucred ? (int)p->p_ucred->cr_uid : -1); signal = SIGKILL; } else { if (error == EACCES) sicode = SEGV_ACCERR; else if (error == EIO) { signal = SIGBUS; sicode = BUS_OBJERR; } } sv.sival_ptr = (void *)cr2; trapsignal(p, signal, T_PAGEFLT, sicode, sv); return 1; } /* * kpageflttrap(frame, usermode): page fault handler * Returns non-zero if the fault was handled (possibly by generating a signal). * Returns zero if something was so broken that we should panic. */ int kpageflttrap(struct trapframe *frame, uint64_t cr2) { struct proc *p = curproc; struct pcb *pcb; vaddr_t va = trunc_page((vaddr_t)cr2); struct vm_map *map; vm_prot_t access_type = pgex2access(frame->tf_err); caddr_t onfault; int error; if (p == NULL || p->p_addr == NULL || p->p_vmspace == NULL) return 0; pcb = &p->p_addr->u_pcb; if (pcb->pcb_onfault != NULL) { extern caddr_t __nofault_start[], __nofault_end[]; caddr_t *nf = __nofault_start; while (*nf++ != pcb->pcb_onfault) { if (nf >= __nofault_end) { fault("invalid pcb_nofault=%lx", (long)pcb->pcb_onfault); return 0; } } } /* This will only trigger if SMEP is enabled */ if (pcb->pcb_onfault == NULL && cr2 <= VM_MAXUSER_ADDRESS && frame->tf_err & PGEX_I) { fault("attempt to execute user address %p " "in supervisor mode", (void *)cr2); return 0; } /* This will only trigger if SMAP is enabled */ if (pcb->pcb_onfault == NULL && cr2 <= VM_MAXUSER_ADDRESS && frame->tf_err & PGEX_P) { fault("attempt to access user address %p " "in supervisor mode", (void *)cr2); return 0; } /* * It is only a kernel address space fault iff: * 1. when running in ring 0 and * 2. pcb_onfault not set or * 3. pcb_onfault set but supervisor space fault * The last can occur during an exec() copyin where the * argument space is lazy-allocated. */ map = &p->p_vmspace->vm_map; if (va >= VM_MIN_KERNEL_ADDRESS) map = kernel_map; if (curcpu()->ci_inatomic == 0 || map == kernel_map) { onfault = pcb->pcb_onfault; pcb->pcb_onfault = NULL; error = uvm_fault(map, va, 0, access_type); pcb->pcb_onfault = onfault; if (error == 0 && map != kernel_map) uvm_grow(p, va); } else error = EFAULT; if (error) { if (pcb->pcb_onfault == NULL) { /* bad memory access in the kernel */ fault("uvm_fault(%p, 0x%llx, 0, %d) -> %x", map, cr2, access_type, error); return 0; } frame->tf_rip = (u_int64_t)pcb->pcb_onfault; } return 1; } /* * kerntrap(frame): * Exception, fault, and trap interface to BSD kernel. This * common code is called from assembly language IDT gate entry * routines that prepare a suitable stack frame, and restore this * frame after the exception has been processed. */ void kerntrap(struct trapframe *frame) { int type = (int)frame->tf_trapno; uint64_t cr2 = rcr2(); verify_smap(__func__); uvmexp.traps++; debug_trap(frame, curproc, type); switch (type) { default: we_re_toast: #ifdef DDB if (db_ktrap(type, frame->tf_err, frame)) return; #endif trap_print(frame, type); panic("trap type %d, code=%llx, pc=%llx", type, frame->tf_err, frame->tf_rip); /*NOTREACHED*/ case T_PAGEFLT: /* allow page faults in kernel mode */ if (kpageflttrap(frame, cr2)) return; goto we_re_toast; #if NISA > 0 case T_NMI: #ifdef DDB /* NMI can be hooked up to a pushbutton for debugging */ printf ("NMI ... going to debugger\n"); if (db_ktrap(type, 0, frame)) return; #endif /* machine/parity/power fail/"kitchen sink" faults */ if (x86_nmi() != 0) goto we_re_toast; else return; #endif /* NISA > 0 */ } } /* If we find out userland changed the pkru register, punish the process */ static inline int verify_pkru(struct proc *p) { if (pg_xo == 0 || rdpkru(0) == PGK_VALUE) return 0; KERNEL_LOCK(); sigabort(p); KERNEL_UNLOCK(); return 1; } /* * usertrap(frame): handler for exceptions, faults, and traps from userspace * This is called from the assembly language IDT gate entries * which prepare a suitable stack frame and restores the CPU state * after the fault has been processed. */ void usertrap(struct trapframe *frame) { struct proc *p = curproc; int type = (int)frame->tf_trapno; uint64_t cr2 = rcr2(); union sigval sv; int sig, code; verify_smap(__func__); uvmexp.traps++; debug_trap(frame, p, type); p->p_md.md_regs = frame; refreshcreds(p); if (verify_pkru(p)) goto out; switch (type) { case T_TSSFLT: sig = SIGBUS; code = BUS_OBJERR; break; case T_PROTFLT: /* protection fault */ case T_SEGNPFLT: case T_STKFLT: frame_dump(frame, p, "SEGV", 0); sig = SIGSEGV; code = SEGV_MAPERR; break; case T_ALIGNFLT: sig = SIGBUS; code = BUS_ADRALN; break; case T_PRIVINFLT: /* privileged instruction fault */ sig = SIGILL; code = ILL_PRVOPC; break; case T_DIVIDE: sig = SIGFPE; code = FPE_INTDIV; break; case T_ARITHTRAP: case T_XMM: /* real arithmetic exceptions */ sig = SIGFPE; code = fputrap(type); break; case T_BPTFLT: /* bpt instruction fault */ case T_TRCTRAP: /* trace trap */ sig = SIGTRAP; code = TRAP_BRKPT; break; case T_CP: sig = SIGILL; code = (frame->tf_err & 0x7fff) < 4 ? ILL_BTCFI : ILL_BADSTK; break; case T_PAGEFLT: /* page fault */ if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p), "[%s]%d/%d sp=%lx inside %lx-%lx: not MAP_STACK\n", uvm_map_inentry_sp, p->p_vmspace->vm_map.sserial)) goto out; if (upageflttrap(frame, cr2)) goto out; /* FALLTHROUGH */ default: trap_print(frame, type); panic("impossible trap"); } sv.sival_ptr = (void *)frame->tf_rip; trapsignal(p, sig, type, code, sv); out: userret(p); } static void trap_print(struct trapframe *frame, int type) { if (type < trap_types) printf("fatal %s", trap_type[type]); else printf("unknown trap %d", type); printf(" in %s mode\n", KERNELMODE(frame->tf_cs, frame->tf_rflags) ? "supervisor" : "user"); printf("trap type %d code %llx rip %llx cs %llx rflags %llx cr2 " "%llx cpl %x rsp %llx\n", type, frame->tf_err, frame->tf_rip, frame->tf_cs, frame->tf_rflags, rcr2(), curcpu()->ci_ilevel, frame->tf_rsp); printf("gsbase %p kgsbase %p\n", (void *)rdmsr(MSR_GSBASE), (void *)rdmsr(MSR_KERNELGSBASE)); } static inline void frame_dump(struct trapframe *tf, struct proc *p, const char *sig, uint64_t cr2) { #ifdef TRAP_SIGDEBUG printf("pid %d (%s): %s at rip %llx addr %llx\n", p->p_p->ps_pid, p->p_p->ps_comm, sig, tf->tf_rip, cr2); printf("rip %p cs 0x%x rfl %p rsp %p ss 0x%x\n", (void *)tf->tf_rip, (unsigned)tf->tf_cs & 0xffff, (void *)tf->tf_rflags, (void *)tf->tf_rsp, (unsigned)tf->tf_ss & 0xffff); printf("err 0x%llx trapno 0x%llx\n", tf->tf_err, tf->tf_trapno); printf("rdi %p rsi %p rdx %p\n", (void *)tf->tf_rdi, (void *)tf->tf_rsi, (void *)tf->tf_rdx); printf("rcx %p r8 %p r9 %p\n", (void *)tf->tf_rcx, (void *)tf->tf_r8, (void *)tf->tf_r9); printf("r10 %p r11 %p r12 %p\n", (void *)tf->tf_r10, (void *)tf->tf_r11, (void *)tf->tf_r12); printf("r13 %p r14 %p r15 %p\n", (void *)tf->tf_r13, (void *)tf->tf_r14, (void *)tf->tf_r15); printf("rbp %p rbx %p rax %p\n", (void *)tf->tf_rbp, (void *)tf->tf_rbx, (void *)tf->tf_rax); #endif } static inline void verify_smap(const char *func) { #ifdef DIAGNOSTIC if (curcpu()->ci_feature_sefflags_ebx & SEFF0EBX_SMAP) { u_long rf = read_rflags(); if (rf & PSL_AC) { write_rflags(rf & ~PSL_AC); panic("%s: AC set on entry", func); } } #endif } static inline void debug_trap(struct trapframe *frame, struct proc *p, long type) { #ifdef DEBUG if (trapdebug) { printf("trap %ld code %llx rip %llx cs %llx rflags %llx " "cr2 %llx cpl %x\n", type, frame->tf_err, frame->tf_rip, frame->tf_cs, frame->tf_rflags, rcr2(), curcpu()->ci_ilevel); printf("curproc %p\n", (void *)p); if (p != NULL) printf("pid %d\n", p->p_p->ps_pid); } #endif } /* * ast(frame): * AST handler. This is called from assembly language stubs when * returning to userspace after a syscall or interrupt. */ void ast(struct trapframe *frame) { struct proc *p = curproc; uvmexp.traps++; KASSERT(!KERNELMODE(frame->tf_cs, frame->tf_rflags)); p->p_md.md_regs = frame; refreshcreds(p); uvmexp.softs++; mi_ast(p, curcpu()->ci_want_resched); userret(p); } /* * syscall(frame): * System call request from POSIX system call gate interface to kernel. */ void syscall(struct trapframe *frame) { const struct sysent *callp; struct proc *p; int error = ENOSYS; register_t code, *args, rval[2]; verify_smap(__func__); uvmexp.syscalls++; p = curproc; if (verify_pkru(p)) { userret(p); return; } code = frame->tf_rax; args = (register_t *)&frame->tf_rdi; if (code <= 0 || code >= SYS_MAXSYSCALL) goto bad; callp = sysent + code; rval[0] = 0; rval[1] = 0; error = mi_syscall(p, code, callp, args, rval); switch (error) { case 0: frame->tf_rax = rval[0]; frame->tf_rflags &= ~PSL_C; /* carry bit */ break; case ERESTART: /* Back up over the syscall instruction (2 bytes) */ frame->tf_rip -= 2; break; case EJUSTRETURN: /* nothing to do */ break; default: bad: frame->tf_rax = error; frame->tf_rflags |= PSL_C; /* carry bit */ break; } mi_syscall_return(p, code, error, rval); } void child_return(void *arg) { struct proc *p = arg; struct trapframe *tf = p->p_md.md_regs; tf->tf_rax = 0; tf->tf_rflags &= ~PSL_C; KERNEL_UNLOCK(); mi_child_return(p); }
521 492 4 49 11 11 11 11 11 11 11 11 11 1 11 11 11 4 4 4 4 54 11 6 52 29 25 53 5 4 4 3 13 10 52 5 52 14 30 11 10 13 46 5 1 14 6 24 19 14 22 3 3 22 22 22 18 6 6 19 17 3 16 19 17 17 3 3 1 1 6 6 4 2 6 6 6 28 28 13 5 22 22 21 20 19 19 19 17 3 17 15 15 15 15 10 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 /* $OpenBSD: ufs_dirhash.c,v 1.43 2024/01/09 03:15:59 guenther Exp $ */ /* * Copyright (c) 2001, 2002 Ian Dowse. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * This implements a hash-based lookup scheme for UFS directories. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/lock.h> #include <sys/malloc.h> #include <sys/pool.h> #include <sys/buf.h> #include <sys/vnode.h> #include <sys/mount.h> #include <sys/sysctl.h> #include <sys/mutex.h> #include <crypto/siphash.h> #include <ufs/ufs/quota.h> #include <ufs/ufs/inode.h> #include <ufs/ufs/dir.h> #include <ufs/ufs/dirhash.h> #include <ufs/ufs/ufsmount.h> #include <ufs/ufs/ufs_extern.h> #define WRAPINCR(val, limit) (((val) + 1 == (limit)) ? 0 : ((val) + 1)) #define WRAPDECR(val, limit) (((val) == 0) ? ((limit) - 1) : ((val) - 1)) #define BLKFREE2IDX(n) ((n) > DH_NFSTATS ? DH_NFSTATS : (n)) int ufs_mindirhashsize; int ufs_dirhashmaxmem; int ufs_dirhashmem; int ufs_dirhashcheck; SIPHASH_KEY ufsdirhash_key; int ufsdirhash_hash(struct dirhash *dh, char *name, int namelen); void ufsdirhash_adjfree(struct dirhash *dh, doff_t offset, int diff); void ufsdirhash_delslot(struct dirhash *dh, int slot); int ufsdirhash_findslot(struct dirhash *dh, char *name, int namelen, doff_t offset); doff_t ufsdirhash_getprev(struct direct *dp, doff_t offset); int ufsdirhash_recycle(int wanted); struct pool ufsdirhash_pool; #define DIRHASHLIST_LOCK() rw_enter_write(&ufsdirhash_mtx) #define DIRHASHLIST_UNLOCK() rw_exit_write(&ufsdirhash_mtx) #define DIRHASH_LOCK(dh) rw_enter_write(&(dh)->dh_mtx) #define DIRHASH_UNLOCK(dh) rw_exit_write(&(dh)->dh_mtx) #define DIRHASH_BLKALLOC_WAITOK() pool_get(&ufsdirhash_pool, PR_WAITOK) #define DIRHASH_BLKFREE(v) pool_put(&ufsdirhash_pool, v) #define mtx_assert(l, f) /* nothing */ #define DIRHASH_ASSERT(e, m) KASSERT((e)) /* Dirhash list; recently-used entries are near the tail. */ TAILQ_HEAD(, dirhash) ufsdirhash_list; /* Protects: ufsdirhash_list, `dh_list' field, ufs_dirhashmem. */ struct rwlock ufsdirhash_mtx; /* * Locking order: * ufsdirhash_mtx * dh_mtx * * The dh_mtx mutex should be acquired either via the inode lock, or via * ufsdirhash_mtx. Only the owner of the inode may free the associated * dirhash, but anything can steal its memory and set dh_hash to NULL. */ /* * Attempt to build up a hash table for the directory contents in * inode 'ip'. Returns 0 on success, or -1 of the operation failed. */ int ufsdirhash_build(struct inode *ip) { struct dirhash *dh; struct buf *bp = NULL; struct direct *ep; struct vnode *vp; doff_t bmask, pos; int dirblocks, i, j, memreqd, nblocks, narrays, nslots, slot; /* Check if we can/should use dirhash. */ if (ip->i_dirhash == NULL) { if (DIP(ip, size) < ufs_mindirhashsize) return (-1); } else { /* Hash exists, but sysctls could have changed. */ if (DIP(ip, size) < ufs_mindirhashsize || ufs_dirhashmem > ufs_dirhashmaxmem) { ufsdirhash_free(ip); return (-1); } /* Check if hash exists and is intact (note: unlocked read). */ if (ip->i_dirhash->dh_hash != NULL) return (0); /* Free the old, recycled hash and build a new one. */ ufsdirhash_free(ip); } /* Don't hash removed directories. */ if (ip->i_effnlink == 0) return (-1); vp = ip->i_vnode; /* Allocate 50% more entries than this dir size could ever need. */ DIRHASH_ASSERT(DIP(ip, size) >= DIRBLKSIZ, ("ufsdirhash_build size")); nslots = DIP(ip, size) / DIRECTSIZ(1); nslots = (nslots * 3 + 1) / 2; narrays = howmany(nslots, DH_NBLKOFF); nslots = narrays * DH_NBLKOFF; dirblocks = howmany(DIP(ip, size), DIRBLKSIZ); nblocks = (dirblocks * 3 + 1) / 2; memreqd = sizeof(*dh) + narrays * sizeof(*dh->dh_hash) + narrays * DH_NBLKOFF * sizeof(**dh->dh_hash) + nblocks * sizeof(*dh->dh_blkfree); DIRHASHLIST_LOCK(); if (memreqd + ufs_dirhashmem > ufs_dirhashmaxmem) { DIRHASHLIST_UNLOCK(); if (memreqd > ufs_dirhashmaxmem / 2) return (-1); /* Try to free some space. */ if (ufsdirhash_recycle(memreqd) != 0) return (-1); /* Enough was freed, and list has been locked. */ } ufs_dirhashmem += memreqd; DIRHASHLIST_UNLOCK(); /* * Use non-blocking mallocs so that we will revert to a linear * lookup on failure rather than potentially blocking forever. */ dh = malloc(sizeof(*dh), M_DIRHASH, M_NOWAIT|M_ZERO); if (dh == NULL) { DIRHASHLIST_LOCK(); ufs_dirhashmem -= memreqd; DIRHASHLIST_UNLOCK(); return (-1); } dh->dh_hash = mallocarray(narrays, sizeof(dh->dh_hash[0]), M_DIRHASH, M_NOWAIT|M_ZERO); dh->dh_blkfree = mallocarray(nblocks, sizeof(dh->dh_blkfree[0]), M_DIRHASH, M_NOWAIT | M_ZERO); if (dh->dh_hash == NULL || dh->dh_blkfree == NULL) goto fail; for (i = 0; i < narrays; i++) { if ((dh->dh_hash[i] = DIRHASH_BLKALLOC_WAITOK()) == NULL) goto fail; for (j = 0; j < DH_NBLKOFF; j++) dh->dh_hash[i][j] = DIRHASH_EMPTY; } /* Initialise the hash table and block statistics. */ rw_init(&dh->dh_mtx, "dirhash"); dh->dh_narrays = narrays; dh->dh_hlen = nslots; dh->dh_nblk = nblocks; dh->dh_dirblks = dirblocks; for (i = 0; i < dirblocks; i++) dh->dh_blkfree[i] = DIRBLKSIZ / DIRALIGN; for (i = 0; i < DH_NFSTATS; i++) dh->dh_firstfree[i] = -1; dh->dh_firstfree[DH_NFSTATS] = 0; dh->dh_seqopt = 0; dh->dh_seqoff = 0; dh->dh_score = DH_SCOREINIT; ip->i_dirhash = dh; bmask = VFSTOUFS(vp->v_mount)->um_mountp->mnt_stat.f_iosize - 1; pos = 0; while (pos < DIP(ip, size)) { /* If necessary, get the next directory block. */ if ((pos & bmask) == 0) { if (bp != NULL) brelse(bp); if (UFS_BUFATOFF(ip, (off_t)pos, NULL, &bp) != 0) goto fail; } /* Add this entry to the hash. */ ep = (struct direct *)((char *)bp->b_data + (pos & bmask)); if (ep->d_reclen == 0 || ep->d_reclen > DIRBLKSIZ - (pos & (DIRBLKSIZ - 1))) { /* Corrupted directory. */ brelse(bp); goto fail; } if (ep->d_ino != 0) { /* Add the entry (simplified ufsdirhash_add). */ slot = ufsdirhash_hash(dh, ep->d_name, ep->d_namlen); while (DH_ENTRY(dh, slot) != DIRHASH_EMPTY) slot = WRAPINCR(slot, dh->dh_hlen); dh->dh_hused++; DH_ENTRY(dh, slot) = pos; ufsdirhash_adjfree(dh, pos, -DIRSIZ(ep)); } pos += ep->d_reclen; } if (bp != NULL) brelse(bp); DIRHASHLIST_LOCK(); TAILQ_INSERT_TAIL(&ufsdirhash_list, dh, dh_list); dh->dh_onlist = 1; DIRHASHLIST_UNLOCK(); return (0); fail: if (dh->dh_hash != NULL) { for (i = 0; i < narrays; i++) if (dh->dh_hash[i] != NULL) DIRHASH_BLKFREE(dh->dh_hash[i]); free(dh->dh_hash, M_DIRHASH, narrays * sizeof(dh->dh_hash[0])); } if (dh->dh_blkfree != NULL) free(dh->dh_blkfree, M_DIRHASH, nblocks * sizeof(dh->dh_blkfree[0])); free(dh, M_DIRHASH, sizeof(*dh)); ip->i_dirhash = NULL; DIRHASHLIST_LOCK(); ufs_dirhashmem -= memreqd; DIRHASHLIST_UNLOCK(); return (-1); } /* * Free any hash table associated with inode 'ip'. */ void ufsdirhash_free(struct inode *ip) { struct dirhash *dh; int i, mem; if ((dh = ip->i_dirhash) == NULL) return; DIRHASHLIST_LOCK(); DIRHASH_LOCK(dh); if (dh->dh_onlist) TAILQ_REMOVE(&ufsdirhash_list, dh, dh_list); DIRHASH_UNLOCK(dh); DIRHASHLIST_UNLOCK(); /* The dirhash pointed to by 'dh' is exclusively ours now. */ mem = sizeof(*dh); if (dh->dh_hash != NULL) { for (i = 0; i < dh->dh_narrays; i++) DIRHASH_BLKFREE(dh->dh_hash[i]); free(dh->dh_hash, M_DIRHASH, dh->dh_narrays * sizeof(dh->dh_hash[0])); free(dh->dh_blkfree, M_DIRHASH, dh->dh_nblk * sizeof(dh->dh_blkfree[0])); mem += dh->dh_narrays * sizeof(*dh->dh_hash) + dh->dh_narrays * DH_NBLKOFF * sizeof(**dh->dh_hash) + dh->dh_nblk * sizeof(*dh->dh_blkfree); } free(dh, M_DIRHASH, sizeof(*dh)); ip->i_dirhash = NULL; DIRHASHLIST_LOCK(); ufs_dirhashmem -= mem; DIRHASHLIST_UNLOCK(); } /* * Find the offset of the specified name within the given inode. * Returns 0 on success, ENOENT if the entry does not exist, or * EJUSTRETURN if the caller should revert to a linear search. * * If successful, the directory offset is stored in *offp, and a * pointer to a struct buf containing the entry is stored in *bpp. If * prevoffp is non-NULL, the offset of the previous entry within * the DIRBLKSIZ-sized block is stored in *prevoffp (if the entry * is the first in a block, the start of the block is used). */ int ufsdirhash_lookup(struct inode *ip, char *name, int namelen, doff_t *offp, struct buf **bpp, doff_t *prevoffp) { struct dirhash *dh, *dh_next; struct direct *dp; struct vnode *vp; struct buf *bp; doff_t blkoff, bmask, offset, prevoff; int i, slot; if ((dh = ip->i_dirhash) == NULL) return (EJUSTRETURN); /* * Move this dirhash towards the end of the list if it has a * score higher than the next entry, and acquire the dh_mtx. * Optimise the case where it's already the last by performing * an unlocked read of the TAILQ_NEXT pointer. * * In both cases, end up holding just dh_mtx. */ if (TAILQ_NEXT(dh, dh_list) != NULL) { DIRHASHLIST_LOCK(); DIRHASH_LOCK(dh); /* * If the new score will be greater than that of the next * entry, then move this entry past it. With both mutexes * held, dh_next won't go away, but its dh_score could * change; that's not important since it is just a hint. */ if (dh->dh_hash != NULL && (dh_next = TAILQ_NEXT(dh, dh_list)) != NULL && dh->dh_score >= dh_next->dh_score) { DIRHASH_ASSERT(dh->dh_onlist, ("dirhash: not on list")); TAILQ_REMOVE(&ufsdirhash_list, dh, dh_list); TAILQ_INSERT_AFTER(&ufsdirhash_list, dh_next, dh, dh_list); } DIRHASHLIST_UNLOCK(); } else { /* Already the last, though that could change as we wait. */ DIRHASH_LOCK(dh); } if (dh->dh_hash == NULL) { DIRHASH_UNLOCK(dh); ufsdirhash_free(ip); return (EJUSTRETURN); } /* Update the score. */ if (dh->dh_score < DH_SCOREMAX) dh->dh_score++; vp = ip->i_vnode; bmask = VFSTOUFS(vp->v_mount)->um_mountp->mnt_stat.f_iosize - 1; blkoff = -1; bp = NULL; restart: slot = ufsdirhash_hash(dh, name, namelen); if (dh->dh_seqopt) { /* * Sequential access optimisation. dh_seqoff contains the * offset of the directory entry immediately following * the last entry that was looked up. Check if this offset * appears in the hash chain for the name we are looking for. */ for (i = slot; (offset = DH_ENTRY(dh, i)) != DIRHASH_EMPTY; i = WRAPINCR(i, dh->dh_hlen)) if (offset == dh->dh_seqoff) break; if (offset == dh->dh_seqoff) { /* * We found an entry with the expected offset. This * is probably the entry we want, but if not, the * code below will turn off seqopt and retry. */ slot = i; } else dh->dh_seqopt = 0; } for (; (offset = DH_ENTRY(dh, slot)) != DIRHASH_EMPTY; slot = WRAPINCR(slot, dh->dh_hlen)) { if (offset == DIRHASH_DEL) continue; DIRHASH_UNLOCK(dh); if (offset < 0 || offset >= DIP(ip, size)) panic("ufsdirhash_lookup: bad offset in hash array"); if ((offset & ~bmask) != blkoff) { if (bp != NULL) brelse(bp); blkoff = offset & ~bmask; if (UFS_BUFATOFF(ip, (off_t)blkoff, NULL, &bp) != 0) return (EJUSTRETURN); } dp = (struct direct *)(bp->b_data + (offset & bmask)); if (dp->d_reclen == 0 || dp->d_reclen > DIRBLKSIZ - (offset & (DIRBLKSIZ - 1))) { /* Corrupted directory. */ brelse(bp); return (EJUSTRETURN); } if (dp->d_namlen == namelen && memcmp(dp->d_name, name, namelen) == 0) { /* Found. Get the prev offset if needed. */ if (prevoffp != NULL) { if (offset & (DIRBLKSIZ - 1)) { prevoff = ufsdirhash_getprev(dp, offset); if (prevoff == -1) { brelse(bp); return (EJUSTRETURN); } } else prevoff = offset; *prevoffp = prevoff; } /* Check for sequential access, and update offset. */ if (dh->dh_seqopt == 0 && dh->dh_seqoff == offset) dh->dh_seqopt = 1; dh->dh_seqoff = offset + DIRSIZ(dp); *bpp = bp; *offp = offset; return (0); } DIRHASH_LOCK(dh); if (dh->dh_hash == NULL) { DIRHASH_UNLOCK(dh); if (bp != NULL) brelse(bp); ufsdirhash_free(ip); return (EJUSTRETURN); } /* * When the name doesn't match in the seqopt case, go back * and search normally. */ if (dh->dh_seqopt) { dh->dh_seqopt = 0; goto restart; } } DIRHASH_UNLOCK(dh); if (bp != NULL) brelse(bp); return (ENOENT); } /* * Find a directory block with room for 'slotneeded' bytes. Returns * the offset of the directory entry that begins the free space. * This will either be the offset of an existing entry that has free * space at the end, or the offset of an entry with d_ino == 0 at * the start of a DIRBLKSIZ block. * * To use the space, the caller may need to compact existing entries in * the directory. The total number of bytes in all of the entries involved * in the compaction is stored in *slotsize. In other words, all of * the entries that must be compacted are exactly contained in the * region beginning at the returned offset and spanning *slotsize bytes. * * Returns -1 if no space was found, indicating that the directory * must be extended. */ doff_t ufsdirhash_findfree(struct inode *ip, int slotneeded, int *slotsize) { struct direct *dp; struct dirhash *dh; struct buf *bp; doff_t pos, slotstart; int dirblock, error, freebytes, i; if ((dh = ip->i_dirhash) == NULL) return (-1); DIRHASH_LOCK(dh); if (dh->dh_hash == NULL) { DIRHASH_UNLOCK(dh); ufsdirhash_free(ip); return (-1); } /* Find a directory block with the desired free space. */ dirblock = -1; for (i = howmany(slotneeded, DIRALIGN); i <= DH_NFSTATS; i++) if ((dirblock = dh->dh_firstfree[i]) != -1) break; if (dirblock == -1) { DIRHASH_UNLOCK(dh); return (-1); } DIRHASH_ASSERT(dirblock < dh->dh_nblk && dh->dh_blkfree[dirblock] >= howmany(slotneeded, DIRALIGN), ("ufsdirhash_findfree: bad stats")); DIRHASH_UNLOCK(dh); pos = dirblock * DIRBLKSIZ; error = UFS_BUFATOFF(ip, (off_t)pos, (char **)&dp, &bp); if (error) return (-1); /* Find the first entry with free space. */ for (i = 0; i < DIRBLKSIZ; ) { if (dp->d_reclen == 0) { brelse(bp); return (-1); } if (dp->d_ino == 0 || dp->d_reclen > DIRSIZ(dp)) break; i += dp->d_reclen; dp = (struct direct *)((char *)dp + dp->d_reclen); } if (i > DIRBLKSIZ) { brelse(bp); return (-1); } slotstart = pos + i; /* Find the range of entries needed to get enough space */ freebytes = 0; while (i < DIRBLKSIZ && freebytes < slotneeded) { freebytes += dp->d_reclen; if (dp->d_ino != 0) freebytes -= DIRSIZ(dp); if (dp->d_reclen == 0) { brelse(bp); return (-1); } i += dp->d_reclen; dp = (struct direct *)((char *)dp + dp->d_reclen); } if (i > DIRBLKSIZ) { brelse(bp); return (-1); } if (freebytes < slotneeded) panic("ufsdirhash_findfree: free mismatch"); brelse(bp); *slotsize = pos + i - slotstart; return (slotstart); } /* * Return the start of the unused space at the end of a directory, or * -1 if there are no trailing unused blocks. */ doff_t ufsdirhash_enduseful(struct inode *ip) { struct dirhash *dh; int i; if ((dh = ip->i_dirhash) == NULL) return (-1); DIRHASH_LOCK(dh); if (dh->dh_hash == NULL) { DIRHASH_UNLOCK(dh); ufsdirhash_free(ip); return (-1); } if (dh->dh_blkfree[dh->dh_dirblks - 1] != DIRBLKSIZ / DIRALIGN) { DIRHASH_UNLOCK(dh); return (-1); } for (i = dh->dh_dirblks - 1; i >= 0; i--) if (dh->dh_blkfree[i] != DIRBLKSIZ / DIRALIGN) break; DIRHASH_UNLOCK(dh); return ((doff_t)(i + 1) * DIRBLKSIZ); } /* * Insert information into the hash about a new directory entry. dirp * points to a struct direct containing the entry, and offset specifies * the offset of this entry. */ void ufsdirhash_add(struct inode *ip, struct direct *dirp, doff_t offset) { struct dirhash *dh; int slot; if ((dh = ip->i_dirhash) == NULL) return; DIRHASH_LOCK(dh); if (dh->dh_hash == NULL) { DIRHASH_UNLOCK(dh); ufsdirhash_free(ip); return; } DIRHASH_ASSERT(offset < dh->dh_dirblks * DIRBLKSIZ, ("ufsdirhash_add: bad offset")); /* * Normal hash usage is < 66%. If the usage gets too high then * remove the hash entirely and let it be rebuilt later. */ if (dh->dh_hused >= (dh->dh_hlen * 3) / 4) { DIRHASH_UNLOCK(dh); ufsdirhash_free(ip); return; } /* Find a free hash slot (empty or deleted), and add the entry. */ slot = ufsdirhash_hash(dh, dirp->d_name, dirp->d_namlen); while (DH_ENTRY(dh, slot) >= 0) slot = WRAPINCR(slot, dh->dh_hlen); if (DH_ENTRY(dh, slot) == DIRHASH_EMPTY) dh->dh_hused++; DH_ENTRY(dh, slot) = offset; /* Update the per-block summary info. */ ufsdirhash_adjfree(dh, offset, -DIRSIZ(dirp)); DIRHASH_UNLOCK(dh); } /* * Remove the specified directory entry from the hash. The entry to remove * is defined by the name in `dirp', which must exist at the specified * `offset' within the directory. */ void ufsdirhash_remove(struct inode *ip, struct direct *dirp, doff_t offset) { struct dirhash *dh; int slot; if ((dh = ip->i_dirhash) == NULL) return; DIRHASH_LOCK(dh); if (dh->dh_hash == NULL) { DIRHASH_UNLOCK(dh); ufsdirhash_free(ip); return; } DIRHASH_ASSERT(offset < dh->dh_dirblks * DIRBLKSIZ, ("ufsdirhash_remove: bad offset")); /* Find the entry */ slot = ufsdirhash_findslot(dh, dirp->d_name, dirp->d_namlen, offset); /* Remove the hash entry. */ ufsdirhash_delslot(dh, slot); /* Update the per-block summary info. */ ufsdirhash_adjfree(dh, offset, DIRSIZ(dirp)); DIRHASH_UNLOCK(dh); } /* * Change the offset associated with a directory entry in the hash. Used * when compacting directory blocks. */ void ufsdirhash_move(struct inode *ip, struct direct *dirp, doff_t oldoff, doff_t newoff) { struct dirhash *dh; int slot; if ((dh = ip->i_dirhash) == NULL) return; DIRHASH_LOCK(dh); if (dh->dh_hash == NULL) { DIRHASH_UNLOCK(dh); ufsdirhash_free(ip); return; } DIRHASH_ASSERT(oldoff < dh->dh_dirblks * DIRBLKSIZ && newoff < dh->dh_dirblks * DIRBLKSIZ, ("ufsdirhash_move: bad offset")); /* Find the entry, and update the offset. */ slot = ufsdirhash_findslot(dh, dirp->d_name, dirp->d_namlen, oldoff); DH_ENTRY(dh, slot) = newoff; DIRHASH_UNLOCK(dh); } /* * Inform dirhash that the directory has grown by one block that * begins at offset (i.e. the new length is offset + DIRBLKSIZ). */ void ufsdirhash_newblk(struct inode *ip, doff_t offset) { struct dirhash *dh; int block; if ((dh = ip->i_dirhash) == NULL) return; DIRHASH_LOCK(dh); if (dh->dh_hash == NULL) { DIRHASH_UNLOCK(dh); ufsdirhash_free(ip); return; } DIRHASH_ASSERT(offset == dh->dh_dirblks * DIRBLKSIZ, ("ufsdirhash_newblk: bad offset")); block = offset / DIRBLKSIZ; if (block >= dh->dh_nblk) { /* Out of space; must rebuild. */ DIRHASH_UNLOCK(dh); ufsdirhash_free(ip); return; } dh->dh_dirblks = block + 1; /* Account for the new free block. */ dh->dh_blkfree[block] = DIRBLKSIZ / DIRALIGN; if (dh->dh_firstfree[DH_NFSTATS] == -1) dh->dh_firstfree[DH_NFSTATS] = block; DIRHASH_UNLOCK(dh); } /* * Inform dirhash that the directory is being truncated. */ void ufsdirhash_dirtrunc(struct inode *ip, doff_t offset) { struct dirhash *dh; int block, i; if ((dh = ip->i_dirhash) == NULL) return; DIRHASH_LOCK(dh); if (dh->dh_hash == NULL) { DIRHASH_UNLOCK(dh); ufsdirhash_free(ip); return; } DIRHASH_ASSERT(offset <= dh->dh_dirblks * DIRBLKSIZ, ("ufsdirhash_dirtrunc: bad offset")); block = howmany(offset, DIRBLKSIZ); /* * If the directory shrinks to less than 1/8 of dh_nblk blocks * (about 20% of its original size due to the 50% extra added in * ufsdirhash_build) then free it, and let the caller rebuild * if necessary. */ if (block < dh->dh_nblk / 8 && dh->dh_narrays > 1) { DIRHASH_UNLOCK(dh); ufsdirhash_free(ip); return; } /* * Remove any `first free' information pertaining to the * truncated blocks. All blocks we're removing should be * completely unused. */ if (dh->dh_firstfree[DH_NFSTATS] >= block) dh->dh_firstfree[DH_NFSTATS] = -1; for (i = block; i < dh->dh_dirblks; i++) if (dh->dh_blkfree[i] != DIRBLKSIZ / DIRALIGN) panic("ufsdirhash_dirtrunc: blocks in use"); for (i = 0; i < DH_NFSTATS; i++) if (dh->dh_firstfree[i] >= block) panic("ufsdirhash_dirtrunc: first free corrupt"); dh->dh_dirblks = block; DIRHASH_UNLOCK(dh); } /* * Debugging function to check that the dirhash information about * a directory block matches its actual contents. Panics if a mismatch * is detected. * * On entry, `buf' should point to the start of an in-core * DIRBLKSIZ-sized directory block, and `offset' should contain the * offset from the start of the directory of that block. */ void ufsdirhash_checkblock(struct inode *ip, char *buf, doff_t offset) { struct dirhash *dh; struct direct *dp; int block, ffslot, i, nfree; if (!ufs_dirhashcheck) return; if ((dh = ip->i_dirhash) == NULL) return; DIRHASH_LOCK(dh); if (dh->dh_hash == NULL) { DIRHASH_UNLOCK(dh); ufsdirhash_free(ip); return; } block = offset / DIRBLKSIZ; if ((offset & (DIRBLKSIZ - 1)) != 0 || block >= dh->dh_dirblks) panic("ufsdirhash_checkblock: bad offset"); nfree = 0; for (i = 0; i < DIRBLKSIZ; i += dp->d_reclen) { dp = (struct direct *)(buf + i); if (dp->d_reclen == 0 || i + dp->d_reclen > DIRBLKSIZ) panic("ufsdirhash_checkblock: bad dir"); if (dp->d_ino == 0) { #if 0 /* * XXX entries with d_ino == 0 should only occur * at the start of a DIRBLKSIZ block. However the * ufs code is tolerant of such entries at other * offsets, and fsck does not fix them. */ if (i != 0) panic("ufsdirhash_checkblock: bad dir inode"); #endif nfree += dp->d_reclen; continue; } /* Check that the entry exists (will panic if it doesn't). */ ufsdirhash_findslot(dh, dp->d_name, dp->d_namlen, offset + i); nfree += dp->d_reclen - DIRSIZ(dp); } if (i != DIRBLKSIZ) panic("ufsdirhash_checkblock: bad dir end"); if (dh->dh_blkfree[block] * DIRALIGN != nfree) panic("ufsdirhash_checkblock: bad free count"); ffslot = BLKFREE2IDX(nfree / DIRALIGN); for (i = 0; i <= DH_NFSTATS; i++) if (dh->dh_firstfree[i] == block && i != ffslot) panic("ufsdirhash_checkblock: bad first-free"); if (dh->dh_firstfree[ffslot] == -1) panic("ufsdirhash_checkblock: missing first-free entry"); DIRHASH_UNLOCK(dh); } /* * Hash the specified filename into a dirhash slot. */ int ufsdirhash_hash(struct dirhash *dh, char *name, int namelen) { return SipHash24(&ufsdirhash_key, name, namelen) % dh->dh_hlen; } /* * Adjust the number of free bytes in the block containing `offset' * by the value specified by `diff'. * * The caller must ensure we have exclusive access to `dh'; normally * that means that dh_mtx should be held, but this is also called * from ufsdirhash_build() where exclusive access can be assumed. */ void ufsdirhash_adjfree(struct dirhash *dh, doff_t offset, int diff) { int block, i, nfidx, ofidx; /* Update the per-block summary info. */ block = offset / DIRBLKSIZ; DIRHASH_ASSERT(block < dh->dh_nblk && block < dh->dh_dirblks, ("dirhash bad offset")); ofidx = BLKFREE2IDX(dh->dh_blkfree[block]); dh->dh_blkfree[block] = (int)dh->dh_blkfree[block] + (diff / DIRALIGN); nfidx = BLKFREE2IDX(dh->dh_blkfree[block]); /* Update the `first free' list if necessary. */ if (ofidx != nfidx) { /* If removing, scan forward for the next block. */ if (dh->dh_firstfree[ofidx] == block) { for (i = block + 1; i < dh->dh_dirblks; i++) if (BLKFREE2IDX(dh->dh_blkfree[i]) == ofidx) break; dh->dh_firstfree[ofidx] = (i < dh->dh_dirblks) ? i : -1; } /* Make this the new `first free' if necessary */ if (dh->dh_firstfree[nfidx] > block || dh->dh_firstfree[nfidx] == -1) dh->dh_firstfree[nfidx] = block; } } /* * Find the specified name which should have the specified offset. * Returns a slot number, and panics on failure. * * `dh' must be locked on entry and remains so on return. */ int ufsdirhash_findslot(struct dirhash *dh, char *name, int namelen, doff_t offset) { int slot; mtx_assert(&dh->dh_mtx, MA_OWNED); /* Find the entry. */ DIRHASH_ASSERT(dh->dh_hused < dh->dh_hlen, ("dirhash find full")); slot = ufsdirhash_hash(dh, name, namelen); while (DH_ENTRY(dh, slot) != offset && DH_ENTRY(dh, slot) != DIRHASH_EMPTY) slot = WRAPINCR(slot, dh->dh_hlen); if (DH_ENTRY(dh, slot) != offset) panic("ufsdirhash_findslot: '%.*s' not found", namelen, name); return (slot); } /* * Remove the entry corresponding to the specified slot from the hash array. * * `dh' must be locked on entry and remains so on return. */ void ufsdirhash_delslot(struct dirhash *dh, int slot) { int i; mtx_assert(&dh->dh_mtx, MA_OWNED); /* Mark the entry as deleted. */ DH_ENTRY(dh, slot) = DIRHASH_DEL; /* If this is the end of a chain of DIRHASH_DEL slots, remove them. */ for (i = slot; DH_ENTRY(dh, i) == DIRHASH_DEL; ) i = WRAPINCR(i, dh->dh_hlen); if (DH_ENTRY(dh, i) == DIRHASH_EMPTY) { i = WRAPDECR(i, dh->dh_hlen); while (DH_ENTRY(dh, i) == DIRHASH_DEL) { DH_ENTRY(dh, i) = DIRHASH_EMPTY; dh->dh_hused--; i = WRAPDECR(i, dh->dh_hlen); } DIRHASH_ASSERT(dh->dh_hused >= 0, ("ufsdirhash_delslot neg hlen")); } } /* * Given a directory entry and its offset, find the offset of the * previous entry in the same DIRBLKSIZ-sized block. Returns an * offset, or -1 if there is no previous entry in the block or some * other problem occurred. */ doff_t ufsdirhash_getprev(struct direct *dirp, doff_t offset) { struct direct *dp; char *blkbuf; doff_t blkoff, prevoff; int entrypos, i; blkoff = offset & ~(DIRBLKSIZ - 1); /* offset of start of block */ entrypos = offset & (DIRBLKSIZ - 1); /* entry relative to block */ blkbuf = (char *)dirp - entrypos; prevoff = blkoff; /* If `offset' is the start of a block, there is no previous entry. */ if (entrypos == 0) return (-1); /* Scan from the start of the block until we get to the entry. */ for (i = 0; i < entrypos; i += dp->d_reclen) { dp = (struct direct *)(blkbuf + i); if (dp->d_reclen == 0 || i + dp->d_reclen > entrypos) return (-1); /* Corrupted directory. */ prevoff = blkoff + i; } return (prevoff); } /* * Try to free up `wanted' bytes by stealing memory from existing * dirhashes. Returns zero with list locked if successful. */ int ufsdirhash_recycle(int wanted) { struct dirhash *dh; doff_t **hash; u_int8_t *blkfree; int i, mem, narrays, nblk; DIRHASHLIST_LOCK(); while (wanted + ufs_dirhashmem > ufs_dirhashmaxmem) { /* Find a dirhash, and lock it. */ if ((dh = TAILQ_FIRST(&ufsdirhash_list)) == NULL) { DIRHASHLIST_UNLOCK(); return (-1); } DIRHASH_LOCK(dh); DIRHASH_ASSERT(dh->dh_hash != NULL, ("dirhash: NULL hash on list")); /* Decrement the score; only recycle if it becomes zero. */ if (--dh->dh_score > 0) { DIRHASH_UNLOCK(dh); DIRHASHLIST_UNLOCK(); return (-1); } /* Remove it from the list and detach its memory. */ TAILQ_REMOVE(&ufsdirhash_list, dh, dh_list); dh->dh_onlist = 0; hash = dh->dh_hash; dh->dh_hash = NULL; blkfree = dh->dh_blkfree; dh->dh_blkfree = NULL; narrays = dh->dh_narrays; nblk = dh->dh_nblk; mem = narrays * sizeof(*dh->dh_hash) + narrays * DH_NBLKOFF * sizeof(**dh->dh_hash) + dh->dh_nblk * sizeof(*dh->dh_blkfree); /* Unlock everything, free the detached memory. */ DIRHASH_UNLOCK(dh); DIRHASHLIST_UNLOCK(); for (i = 0; i < narrays; i++) DIRHASH_BLKFREE(hash[i]); free(hash, M_DIRHASH, narrays * sizeof(hash[0])); free(blkfree, M_DIRHASH, nblk * sizeof(blkfree[0])); /* Account for the returned memory, and repeat if necessary. */ DIRHASHLIST_LOCK(); ufs_dirhashmem -= mem; } /* Success; return with list locked. */ return (0); } void ufsdirhash_init(void) { pool_init(&ufsdirhash_pool, DH_NBLKOFF * sizeof(doff_t), 0, IPL_NONE, PR_WAITOK, "dirhash", NULL); rw_init(&ufsdirhash_mtx, "dirhash_list"); arc4random_buf(&ufsdirhash_key, sizeof(ufsdirhash_key)); TAILQ_INIT(&ufsdirhash_list); ufs_dirhashmaxmem = 5 * 1024 * 1024; ufs_mindirhashsize = 5 * DIRBLKSIZ; } void ufsdirhash_uninit(void) { DIRHASH_ASSERT(TAILQ_EMPTY(&ufsdirhash_list), ("ufsdirhash_uninit")); pool_destroy(&ufsdirhash_pool); }
2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 /* $OpenBSD: ext2fs_vfsops.c,v 1.119 2024/05/12 09:19:54 jsg Exp $ */ /* $NetBSD: ext2fs_vfsops.c,v 1.1 1997/06/11 09:34:07 bouyer Exp $ */ /* * Copyright (c) 1997 Manuel Bouyer. * Copyright (c) 1989, 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ffs_vfsops.c 8.14 (Berkeley) 11/28/94 * Modified for ext2fs by Manuel Bouyer. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/namei.h> #include <sys/proc.h> #include <sys/kernel.h> #include <sys/vnode.h> #include <sys/socket.h> #include <sys/mount.h> #include <sys/buf.h> #include <sys/disk.h> #include <sys/mbuf.h> #include <sys/fcntl.h> #include <sys/disklabel.h> #include <sys/ioctl.h> #include <sys/errno.h> #include <sys/malloc.h> #include <sys/pool.h> #include <sys/lock.h> #include <sys/dkio.h> #include <sys/specdev.h> #include <ufs/ufs/quota.h> #include <ufs/ufs/ufsmount.h> #include <ufs/ufs/inode.h> #include <ufs/ufs/dir.h> #include <ufs/ufs/ufs_extern.h> #include <ufs/ext2fs/ext2fs.h> #include <ufs/ext2fs/ext2fs_extern.h> int ext2fs_sbupdate(struct ufsmount *, int); static int e2fs_sbcheck(struct ext2fs *, int); const struct vfsops ext2fs_vfsops = { .vfs_mount = ext2fs_mount, .vfs_start = ufs_start, .vfs_unmount = ext2fs_unmount, .vfs_root = ufs_root, .vfs_quotactl = ufs_quotactl, .vfs_statfs = ext2fs_statfs, .vfs_sync = ext2fs_sync, .vfs_vget = ext2fs_vget, .vfs_fhtovp = ext2fs_fhtovp, .vfs_vptofh = ext2fs_vptofh, .vfs_init = ext2fs_init, .vfs_sysctl = ext2fs_sysctl, .vfs_checkexp = ufs_check_export, }; struct pool ext2fs_inode_pool; struct pool ext2fs_dinode_pool; extern u_long ext2gennumber; int ext2fs_init(struct vfsconf *vfsp) { pool_init(&ext2fs_inode_pool, sizeof(struct inode), 0, IPL_NONE, PR_WAITOK, "ext2inopl", NULL); pool_init(&ext2fs_dinode_pool, sizeof(struct ext2fs_dinode), 0, IPL_NONE, PR_WAITOK, "ext2dinopl", NULL); return (ufs_init(vfsp)); } /* * Called by main() when ext2fs is going to be mounted as root. * * Name is updated by mount(8) after booting. */ #define ROOTNAME "root_device" int ext2fs_mountroot(void) { struct m_ext2fs *fs; struct mount *mp; struct proc *p = curproc; /* XXX */ struct ufsmount *ump; int error; /* * Get vnodes for swapdev and rootdev. */ if (bdevvp(swapdev, &swapdev_vp) || bdevvp(rootdev, &rootvp)) panic("ext2fs_mountroot: can't setup bdevvp's"); if ((error = vfs_rootmountalloc("ext2fs", "root_device", &mp)) != 0) { vrele(rootvp); return (error); } if ((error = ext2fs_mountfs(rootvp, mp, p)) != 0) { vfs_unbusy(mp); vfs_mount_free(mp); vrele(rootvp); return (error); } TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list); ump = VFSTOUFS(mp); fs = ump->um_e2fs; memset(fs->e2fs_fsmnt, 0, sizeof(fs->e2fs_fsmnt)); strlcpy(fs->e2fs_fsmnt, mp->mnt_stat.f_mntonname, sizeof(fs->e2fs_fsmnt)); if (fs->e2fs.e2fs_rev > E2FS_REV0) { memset(fs->e2fs.e2fs_fsmnt, 0, sizeof(fs->e2fs.e2fs_fsmnt)); strlcpy(fs->e2fs.e2fs_fsmnt, mp->mnt_stat.f_mntonname, sizeof(fs->e2fs.e2fs_fsmnt)); } (void)ext2fs_statfs(mp, &mp->mnt_stat, p); vfs_unbusy(mp); inittodr(fs->e2fs.e2fs_wtime); return (0); } /* * VFS Operations. * * mount system call */ int ext2fs_mount(struct mount *mp, const char *path, void *data, struct nameidata *ndp, struct proc *p) { struct vnode *devvp; struct ufs_args *args = data; struct ufsmount *ump = NULL; struct m_ext2fs *fs; char fname[MNAMELEN]; char fspec[MNAMELEN]; int error, flags; /* * If updating, check whether changing from read-only to * read/write; if there is no device name, that's all we do. */ if (mp->mnt_flag & MNT_UPDATE) { ump = VFSTOUFS(mp); fs = ump->um_e2fs; if (fs->e2fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { flags = WRITECLOSE; if (mp->mnt_flag & MNT_FORCE) flags |= FORCECLOSE; error = ext2fs_flushfiles(mp, flags, p); if (error == 0 && ext2fs_cgupdate(ump, MNT_WAIT) == 0 && (fs->e2fs.e2fs_state & E2FS_ERRORS) == 0) { fs->e2fs.e2fs_state = E2FS_ISCLEAN; (void)ext2fs_sbupdate(ump, MNT_WAIT); } if (error) return (error); fs->e2fs_ronly = 1; } if (mp->mnt_flag & MNT_RELOAD) { error = ext2fs_reload(mp, ndp->ni_cnd.cn_cred, p); if (error) return (error); } if (fs->e2fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) { fs->e2fs_ronly = 0; if (fs->e2fs.e2fs_state == E2FS_ISCLEAN) fs->e2fs.e2fs_state = 0; else fs->e2fs.e2fs_state = E2FS_ERRORS; fs->e2fs_fmod = 1; } if (args && args->fspec == NULL) { /* * Process export requests. */ return (vfs_export(mp, &ump->um_export, &args->export_info)); } if (args == NULL) goto success; } /* * Not an update, or updating the name: look up the name * and verify that it refers to a sensible block device. */ error = copyinstr(args->fspec, fspec, sizeof(fspec), NULL); if (error) goto error; if (disk_map(fspec, fname, MNAMELEN, DM_OPENBLCK) == -1) memcpy(fname, fspec, sizeof(fname)); NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fname, p); if ((error = namei(ndp)) != 0) goto error; devvp = ndp->ni_vp; if (devvp->v_type != VBLK) { error = ENOTBLK; goto error_devvp; } if (major(devvp->v_rdev) >= nblkdev) { error = ENXIO; goto error_devvp; } if ((mp->mnt_flag & MNT_UPDATE) == 0) error = ext2fs_mountfs(devvp, mp, p); else { if (devvp != ump->um_devvp) error = EINVAL; /* XXX needs translation */ else vrele(devvp); } if (error) goto error_devvp; ump = VFSTOUFS(mp); fs = ump->um_e2fs; memset(fs->e2fs_fsmnt, 0, sizeof(fs->e2fs_fsmnt)); strlcpy(fs->e2fs_fsmnt, path, sizeof(fs->e2fs_fsmnt)); if (fs->e2fs.e2fs_rev > E2FS_REV0) { memset(fs->e2fs.e2fs_fsmnt, 0, sizeof(fs->e2fs.e2fs_fsmnt)); strlcpy(fs->e2fs.e2fs_fsmnt, mp->mnt_stat.f_mntonname, sizeof(fs->e2fs.e2fs_fsmnt)); } memcpy(mp->mnt_stat.f_mntonname, fs->e2fs_fsmnt, MNAMELEN); memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN); strlcpy(mp->mnt_stat.f_mntfromname, fname, MNAMELEN); memset(mp->mnt_stat.f_mntfromspec, 0, MNAMELEN); strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN); memcpy(&mp->mnt_stat.mount_info.ufs_args, args, sizeof(*args)); if (fs->e2fs_fmod != 0) { /* XXX */ fs->e2fs_fmod = 0; if (fs->e2fs.e2fs_state == 0) fs->e2fs.e2fs_wtime = gettime(); else printf("%s: file system not clean; please fsck(8)\n", mp->mnt_stat.f_mntfromname); ext2fs_cgupdate(ump, MNT_WAIT); } goto success; error_devvp: /* Error with devvp held. */ vrele(devvp); error: /* Error with no state to backout. */ success: return (error); } int ext2fs_reload_vnode(struct vnode *, void *args); struct ext2fs_reload_args { struct m_ext2fs *fs; struct proc *p; struct ucred *cred; struct vnode *devvp; }; int ext2fs_reload_vnode(struct vnode *vp, void *args) { struct ext2fs_reload_args *era = args; struct buf *bp; struct inode *ip; int error; caddr_t cp; /* * Step 4: invalidate all inactive vnodes. */ if (vp->v_usecount == 0) { vgonel(vp, era->p); return (0); } /* * Step 5: invalidate all cached file data. */ if (vget(vp, LK_EXCLUSIVE)) return (0); if (vinvalbuf(vp, 0, era->cred, era->p, 0, INFSLP)) panic("ext2fs_reload: dirty2"); /* * Step 6: re-read inode data for all active vnodes. */ ip = VTOI(vp); error = bread(era->devvp, fsbtodb(era->fs, ino_to_fsba(era->fs, ip->i_number)), (int)era->fs->e2fs_bsize, &bp); if (error) { vput(vp); return (error); } cp = (caddr_t)bp->b_data + (ino_to_fsbo(era->fs, ip->i_number) * EXT2_DINODE_SIZE(era->fs)); e2fs_iload(era->fs, (struct ext2fs_dinode *)cp, ip->i_e2din); brelse(bp); vput(vp); return (0); } static off_t ext2fs_maxfilesize(struct m_ext2fs *fs) { bool huge = fs->e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_HUGE_FILE; off_t b = fs->e2fs_bsize / 4; off_t physically, logically; physically = dbtob(huge ? ((1ULL << 48) - 1) : UINT_MAX); logically = (12ULL + b + b*b + b*b*b) * fs->e2fs_bsize; return MIN(logically, physically); } static int e2fs_sbfill(struct vnode *devvp, struct m_ext2fs *fs) { struct buf *bp = NULL; int i, error; /* XXX assume hardware block size == 512 */ fs->e2fs_ncg = howmany(fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock, fs->e2fs.e2fs_bpg); fs->e2fs_fsbtodb = fs->e2fs.e2fs_log_bsize + 1; fs->e2fs_bsize = 1024 << fs->e2fs.e2fs_log_bsize; fs->e2fs_bshift = LOG_MINBSIZE + fs->e2fs.e2fs_log_bsize; fs->e2fs_fsize = 1024 << fs->e2fs.e2fs_log_fsize; fs->e2fs_qbmask = fs->e2fs_bsize - 1; fs->e2fs_bmask = ~fs->e2fs_qbmask; fs->e2fs_ipb = fs->e2fs_bsize / EXT2_DINODE_SIZE(fs); fs->e2fs_itpg = fs->e2fs.e2fs_ipg / fs->e2fs_ipb; /* Re-read group descriptors from the disk. */ fs->e2fs_ngdb = howmany(fs->e2fs_ncg, fs->e2fs_bsize / sizeof(struct ext2_gd)); fs->e2fs_gd = mallocarray(fs->e2fs_ngdb, fs->e2fs_bsize, M_UFSMNT, M_WAITOK); for (i = 0; i < fs->e2fs_ngdb; ++i) { daddr_t dblk = ((fs->e2fs_bsize > 1024) ? 0 : 1) + i + 1; size_t gdesc = i * fs->e2fs_bsize / sizeof(struct ext2_gd); struct ext2_gd *gd; error = bread(devvp, fsbtodb(fs, dblk), fs->e2fs_bsize, &bp); if (error) { size_t gdescs_space = fs->e2fs_ngdb * fs->e2fs_bsize; free(fs->e2fs_gd, M_UFSMNT, gdescs_space); fs->e2fs_gd = NULL; brelse(bp); return (error); } gd = (struct ext2_gd *) bp->b_data; e2fs_cgload(gd, fs->e2fs_gd + gdesc, fs->e2fs_bsize); brelse(bp); bp = NULL; } if (!(fs->e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_LARGE_FILE) || (fs->e2fs.e2fs_rev == E2FS_REV0)) fs->e2fs_maxfilesize = INT_MAX; else fs->e2fs_maxfilesize = ext2fs_maxfilesize(fs); if (fs->e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_EXTENTS) fs->e2fs_maxfilesize *= 4; return (0); } /* * Reload all incore data for a filesystem (used after running fsck on * the root filesystem and finding things to fix). The filesystem must * be mounted read-only. * * Things to do to update the mount: * 1) invalidate all cached meta-data. * 2) re-read superblock from disk. * 3) re-read summary information from disk. * 4) invalidate all inactive vnodes. * 5) invalidate all cached file data. * 6) re-read inode data for all active vnodes. */ int ext2fs_reload(struct mount *mountp, struct ucred *cred, struct proc *p) { struct vnode *devvp; struct buf *bp; struct m_ext2fs *fs; struct ext2fs *newfs; int error; struct ext2fs_reload_args era; if ((mountp->mnt_flag & MNT_RDONLY) == 0) return (EINVAL); /* * Step 1: invalidate all cached meta-data. */ devvp = VFSTOUFS(mountp)->um_devvp; vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); error = vinvalbuf(devvp, 0, cred, p, 0, INFSLP); VOP_UNLOCK(devvp); if (error != 0) panic("ext2fs_reload: dirty1"); /* * Step 2: re-read superblock from disk. */ error = bread(devvp, (daddr_t)(SBOFF / DEV_BSIZE), SBSIZE, &bp); if (error) { brelse(bp); return (error); } newfs = (struct ext2fs *)bp->b_data; error = e2fs_sbcheck(newfs, (mountp->mnt_flag & MNT_RDONLY)); if (error) { brelse(bp); return (error); } fs = VFSTOUFS(mountp)->um_e2fs; /* * Copy in the new superblock, compute in-memory values * and load group descriptors. */ e2fs_sbload(newfs, &fs->e2fs); if ((error = e2fs_sbfill(devvp, fs)) != 0) return (error); era.p = p; era.cred = cred; era.fs = fs; era.devvp = devvp; error = vfs_mount_foreach_vnode(mountp, ext2fs_reload_vnode, &era); return (error); } /* * Common code for mount and mountroot */ int ext2fs_mountfs(struct vnode *devvp, struct mount *mp, struct proc *p) { struct ufsmount *ump; struct buf *bp; struct ext2fs *fs; dev_t dev; int error, ronly; struct ucred *cred; dev = devvp->v_rdev; cred = p ? p->p_ucred : NOCRED; /* * Disallow multiple mounts of the same device. * Disallow mounting of a device that is currently in use * (except for root, which might share swap device for miniroot). * Flush out any old buffers remaining from a previous use. */ if ((error = vfs_mountedon(devvp)) != 0) return (error); if (vcount(devvp) > 1 && devvp != rootvp) return (EBUSY); vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); error = vinvalbuf(devvp, V_SAVE, cred, p, 0, INFSLP); VOP_UNLOCK(devvp); if (error != 0) return (error); ronly = (mp->mnt_flag & MNT_RDONLY) != 0; error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p); if (error) return (error); bp = NULL; ump = NULL; /* * Read the superblock from disk. */ error = bread(devvp, (daddr_t)(SBOFF / DEV_BSIZE), SBSIZE, &bp); if (error) goto out; fs = (struct ext2fs *)bp->b_data; error = e2fs_sbcheck(fs, ronly); if (error) goto out; ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK | M_ZERO); ump->um_e2fs = malloc(sizeof(struct m_ext2fs), M_UFSMNT, M_WAITOK | M_ZERO); /* * Copy in the superblock, compute in-memory values * and load group descriptors. */ e2fs_sbload(fs, &ump->um_e2fs->e2fs); if ((error = e2fs_sbfill(devvp, ump->um_e2fs)) != 0) goto out; brelse(bp); bp = NULL; fs = &ump->um_e2fs->e2fs; ump->um_e2fs->e2fs_ronly = ronly; ump->um_fstype = UM_EXT2FS; if (ronly == 0) { if (fs->e2fs_state == E2FS_ISCLEAN) fs->e2fs_state = 0; else fs->e2fs_state = E2FS_ERRORS; ump->um_e2fs->e2fs_fmod = 1; } mp->mnt_data = ump; mp->mnt_stat.f_fsid.val[0] = (long)dev; mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; mp->mnt_stat.f_namemax = MAXNAMLEN; mp->mnt_flag |= MNT_LOCAL; ump->um_mountp = mp; ump->um_dev = dev; ump->um_devvp = devvp; ump->um_nindir = NINDIR(ump->um_e2fs); ump->um_bptrtodb = ump->um_e2fs->e2fs_fsbtodb; ump->um_seqinc = 1; /* no frags */ ump->um_maxsymlinklen = EXT2_MAXSYMLINKLEN; devvp->v_specmountpoint = mp; return (0); out: if (devvp->v_specinfo) devvp->v_specmountpoint = NULL; if (bp) brelse(bp); vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p); VOP_UNLOCK(devvp); if (ump) { free(ump->um_e2fs, M_UFSMNT, sizeof *ump->um_e2fs); free(ump, M_UFSMNT, sizeof *ump); mp->mnt_data = NULL; } return (error); } /* * unmount system call */ int ext2fs_unmount(struct mount *mp, int mntflags, struct proc *p) { struct ufsmount *ump; struct m_ext2fs *fs; int error, flags; size_t gdescs_space; flags = 0; if (mntflags & MNT_FORCE) flags |= FORCECLOSE; if ((error = ext2fs_flushfiles(mp, flags, p)) != 0) return (error); ump = VFSTOUFS(mp); fs = ump->um_e2fs; gdescs_space = fs->e2fs_ngdb * fs->e2fs_bsize; if (!fs->e2fs_ronly && ext2fs_cgupdate(ump, MNT_WAIT) == 0 && (fs->e2fs.e2fs_state & E2FS_ERRORS) == 0) { fs->e2fs.e2fs_state = E2FS_ISCLEAN; (void) ext2fs_sbupdate(ump, MNT_WAIT); } if (ump->um_devvp->v_type != VBAD) ump->um_devvp->v_specmountpoint = NULL; vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY); (void)VOP_CLOSE(ump->um_devvp, fs->e2fs_ronly ? FREAD : FREAD|FWRITE, NOCRED, p); vput(ump->um_devvp); free(fs->e2fs_gd, M_UFSMNT, gdescs_space); free(fs, M_UFSMNT, sizeof *fs); free(ump, M_UFSMNT, sizeof *ump); mp->mnt_data = NULL; mp->mnt_flag &= ~MNT_LOCAL; return (0); } /* * Flush out all the files in a filesystem. */ int ext2fs_flushfiles(struct mount *mp, int flags, struct proc *p) { struct ufsmount *ump; int error; ump = VFSTOUFS(mp); /* * Flush all the files. */ if ((error = vflush(mp, NULL, flags)) != 0) return (error); /* * Flush filesystem metadata. */ vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY); error = VOP_FSYNC(ump->um_devvp, p->p_ucred, MNT_WAIT, p); VOP_UNLOCK(ump->um_devvp); return (error); } /* * Get file system statistics. */ int ext2fs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p) { struct ufsmount *ump; struct m_ext2fs *fs; u_int32_t overhead, overhead_per_group; int i, ngroups; ump = VFSTOUFS(mp); fs = ump->um_e2fs; if (fs->e2fs.e2fs_magic != E2FS_MAGIC) panic("ext2fs_statfs"); /* * Compute the overhead (FS structures) */ overhead_per_group = 1 /* block bitmap */ + 1 /* inode bitmap */ + fs->e2fs_itpg; overhead = fs->e2fs.e2fs_first_dblock + fs->e2fs_ncg * overhead_per_group; if (fs->e2fs.e2fs_rev > E2FS_REV0 && fs->e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_SPARSE_SUPER) { for (i = 0, ngroups = 0; i < fs->e2fs_ncg; i++) { if (cg_has_sb(i)) ngroups++; } } else { ngroups = fs->e2fs_ncg; } overhead += ngroups * (1 + fs->e2fs_ngdb); sbp->f_bsize = fs->e2fs_bsize; sbp->f_iosize = fs->e2fs_bsize; sbp->f_blocks = fs->e2fs.e2fs_bcount - overhead; sbp->f_bfree = fs->e2fs.e2fs_fbcount; sbp->f_bavail = sbp->f_bfree - fs->e2fs.e2fs_rbcount; sbp->f_files = fs->e2fs.e2fs_icount; sbp->f_favail = sbp->f_ffree = fs->e2fs.e2fs_ficount; copy_statfs_info(sbp, mp); return (0); } int ext2fs_sync_vnode(struct vnode *vp, void *); struct ext2fs_sync_args { int allerror; int waitfor; int nlink0; int inflight; struct proc *p; struct ucred *cred; }; int ext2fs_sync_vnode(struct vnode *vp, void *args) { struct ext2fs_sync_args *esa = args; struct inode *ip; int error, nlink0 = 0; int s, skip = 0; if (vp->v_type == VNON) return (0); ip = VTOI(vp); if (ip->i_e2fs_nlink == 0) nlink0 = 1; s = splbio(); if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 && LIST_EMPTY(&vp->v_dirtyblkhd)) { skip = 1; } splx(s); if (skip) goto end; if (vget(vp, LK_EXCLUSIVE | LK_NOWAIT)) { esa->inflight = MIN(esa->inflight+1, 65536); goto end; } if ((error = VOP_FSYNC(vp, esa->cred, esa->waitfor, esa->p)) != 0) esa->allerror = error; vput(vp); end: esa->nlink0 = MIN(esa->nlink0 + nlink0, 65536); return (0); } /* * Go through the disk queues to initiate sandbagged IO; * go through the inodes to write those that have been modified; * initiate the writing of the super block if it has been modified. * * Should always be called with the mount point locked. */ int ext2fs_sync(struct mount *mp, int waitfor, int stall, struct ucred *cred, struct proc *p) { struct ufsmount *ump = VFSTOUFS(mp); struct m_ext2fs *fs; int error, allerror = 0, state, fmod; struct ext2fs_sync_args esa; fs = ump->um_e2fs; if (fs->e2fs_ronly != 0) { /* XXX */ printf("fs = %s\n", fs->e2fs_fsmnt); panic("update: rofs mod"); } /* * Write back each (modified) inode. */ esa.p = p; esa.cred = cred; esa.allerror = 0; esa.waitfor = waitfor; esa.nlink0 = 0; esa.inflight = 0; vfs_mount_foreach_vnode(mp, ext2fs_sync_vnode, &esa); if (esa.allerror != 0) allerror = esa.allerror; /* * Force stale file system control information to be flushed. */ if (waitfor != MNT_LAZY) { vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY); if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0) allerror = error; VOP_UNLOCK(ump->um_devvp); } /* * Write back modified superblock. */ state = fs->e2fs.e2fs_state; fmod = fs->e2fs_fmod; if (stall && fs->e2fs_ronly == 0) { fs->e2fs_fmod = 1; if (allerror == 0 && esa.nlink0 == 0 && esa.inflight == 0) { if ((fs->e2fs.e2fs_state & E2FS_ERRORS) == 0) fs->e2fs.e2fs_state = E2FS_ISCLEAN; #if 0 printf("%s force clean (dangling %d inflight %d)\n", mp->mnt_stat.f_mntonname, esa.nlink0, esa.inflight); #endif } else { fs->e2fs.e2fs_state = 0; #if 0 printf("%s force dirty (dangling %d inflight %d)\n", mp->mnt_stat.f_mntonname, esa.nlink0, esa.inflight); #endif } } if (fs->e2fs_fmod != 0) { fs->e2fs_fmod = 0; fs->e2fs.e2fs_wtime = gettime(); if ((error = ext2fs_cgupdate(ump, waitfor))) allerror = error; } fs->e2fs.e2fs_state = state; fs->e2fs_fmod = fmod; return (allerror); } /* * Look up a EXT2FS dinode number to find its incore vnode, otherwise read it * in from disk. If it is in core, wait for the lock bit to clear, then * return the inode locked. Detection and handling of mount points must be * done by the calling routine. */ int ext2fs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) { struct m_ext2fs *fs; struct inode *ip; struct ext2fs_dinode *dp; struct ufsmount *ump; struct buf *bp; struct vnode *vp; dev_t dev; int error; if (ino > (ufsino_t)-1) panic("ext2fs_vget: alien ino_t %llu", (unsigned long long)ino); ump = VFSTOUFS(mp); dev = ump->um_dev; retry: if ((*vpp = ufs_ihashget(dev, ino)) != NULL) return (0); /* Allocate a new vnode/inode. */ if ((error = getnewvnode(VT_EXT2FS, mp, &ext2fs_vops, &vp)) != 0) { *vpp = NULL; return (error); } ip = pool_get(&ext2fs_inode_pool, PR_WAITOK|PR_ZERO); rrw_init_flags(&ip->i_lock, "inode", RWL_DUPOK | RWL_IS_VNODE); vp->v_data = ip; ip->i_vnode = vp; ip->i_ump = ump; ip->i_e2fs = fs = ump->um_e2fs; ip->i_dev = dev; ip->i_number = ino; ip->i_e2fs_last_lblk = 0; ip->i_e2fs_last_blk = 0; /* * Put it onto its hash chain and lock it so that other requests for * this inode will block if they arrive while we are sleeping waiting * for old data structures to be purged or for the contents of the * disk portion of this inode to be read. */ error = ufs_ihashins(ip); if (error) { vrele(vp); if (error == EEXIST) goto retry; return (error); } /* Read in the disk contents for the inode, copy into the inode. */ error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)), (int)fs->e2fs_bsize, &bp); if (error) { /* * The inode does not contain anything useful, so it would * be misleading to leave it on its hash chain. With mode * still zero, it will be unlinked and returned to the free * list by vput(). */ vput(vp); brelse(bp); *vpp = NULL; return (error); } dp = (struct ext2fs_dinode *) ((char *)bp->b_data + EXT2_DINODE_SIZE(fs) * ino_to_fsbo(fs, ino)); ip->i_e2din = pool_get(&ext2fs_dinode_pool, PR_WAITOK); e2fs_iload(fs, dp, ip->i_e2din); brelse(bp); ip->i_effnlink = ip->i_e2fs_nlink; /* * The fields for storing the UID and GID of an ext2fs inode are * limited to 16 bits. To overcome this limitation, Linux decided to * scatter the highest bits of these values into a previously reserved * area on the disk inode. We deal with this situation by having two * 32-bit fields *out* of the disk inode to hold the complete values. * Now that we are reading in the inode, compute these fields. */ ip->i_e2fs_uid = ip->i_e2fs_uid_low | (ip->i_e2fs_uid_high << 16); ip->i_e2fs_gid = ip->i_e2fs_gid_low | (ip->i_e2fs_gid_high << 16); /* If the inode was deleted, reset all fields */ if (ip->i_e2fs_dtime != 0) { ip->i_e2fs_mode = ip->i_e2fs_nblock = 0; (void)ext2fs_setsize(ip, 0); } /* * Initialize the vnode from the inode, check for aliases. * Note that the underlying vnode may have changed. */ error = ext2fs_vinit(mp, &vp); if (error) { vput(vp); *vpp = NULL; return (error); } /* * Finish inode initialization now that aliasing has been resolved. */ vref(ip->i_devvp); /* * Set up a generation number for this inode if it does not * already have one. This should only happen on old filesystems. */ if (ip->i_e2fs_gen == 0) { if (++ext2gennumber < (u_long)gettime()) ext2gennumber = gettime(); ip->i_e2fs_gen = ext2gennumber; if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) ip->i_flag |= IN_MODIFIED; } *vpp = vp; return (0); } /* * File handle to vnode * * Have to be really careful about stale file handles: * - check that the inode number is valid * - call ext2fs_vget() to get the locked inode * - check for an unallocated inode (i_mode == 0) * - check that the given client host has export rights and return * those rights via. exflagsp and credanonp */ int ext2fs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) { struct inode *ip; struct vnode *nvp; int error; struct ufid *ufhp; struct m_ext2fs *fs; ufhp = (struct ufid *)fhp; fs = VFSTOUFS(mp)->um_e2fs; if ((ufhp->ufid_ino < EXT2_FIRSTINO && ufhp->ufid_ino != EXT2_ROOTINO) || ufhp->ufid_ino > fs->e2fs_ncg * fs->e2fs.e2fs_ipg) return (ESTALE); if ((error = VFS_VGET(mp, ufhp->ufid_ino, &nvp)) != 0) { *vpp = NULLVP; return (error); } ip = VTOI(nvp); if (ip->i_e2fs_mode == 0 || ip->i_e2fs_dtime != 0 || ip->i_e2fs_gen != ufhp->ufid_gen) { vput(nvp); *vpp = NULLVP; return (ESTALE); } *vpp = nvp; return (0); } /* * Vnode pointer to File handle */ int ext2fs_vptofh(struct vnode *vp, struct fid *fhp) { struct inode *ip; struct ufid *ufhp; ip = VTOI(vp); ufhp = (struct ufid *)fhp; ufhp->ufid_len = sizeof(struct ufid); ufhp->ufid_ino = ip->i_number; ufhp->ufid_gen = ip->i_e2fs_gen; return (0); } /* * no sysctl for ext2fs */ int ext2fs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { return (EOPNOTSUPP); } /* * Write a superblock and associated information back to disk. */ int ext2fs_sbupdate(struct ufsmount *mp, int waitfor) { struct m_ext2fs *fs = mp->um_e2fs; struct buf *bp; int error = 0; bp = getblk(mp->um_devvp, SBLOCK, SBSIZE, 0, INFSLP); e2fs_sbsave(&fs->e2fs, (struct ext2fs *) bp->b_data); if (waitfor == MNT_WAIT) error = bwrite(bp); else bawrite(bp); fs->e2fs_fmod = 0; return (error); } int ext2fs_cgupdate(struct ufsmount *mp, int waitfor) { struct m_ext2fs *fs = mp->um_e2fs; struct buf *bp; int i, error = 0, allerror = 0; allerror = ext2fs_sbupdate(mp, waitfor); for (i = 0; i < fs->e2fs_ngdb; i++) { bp = getblk(mp->um_devvp, fsbtodb(fs, ((fs->e2fs_bsize>1024)?0:1)+i+1), fs->e2fs_bsize, 0, INFSLP); e2fs_cgsave(&fs->e2fs_gd[i* fs->e2fs_bsize / sizeof(struct ext2_gd)], (struct ext2_gd*)bp->b_data, fs->e2fs_bsize); if (waitfor == MNT_WAIT) error = bwrite(bp); else bawrite(bp); } if (!allerror && error) allerror = error; return (allerror); } /* This is called before the superblock is copied. Watch out for endianity! */ static int e2fs_sbcheck(struct ext2fs *fs, int ronly) { u_int32_t mask, tmp; int i; tmp = letoh16(fs->e2fs_magic); if (tmp != E2FS_MAGIC) { printf("ext2fs: wrong magic number 0x%x\n", tmp); return (EIO); /* XXX needs translation */ } tmp = letoh32(fs->e2fs_log_bsize); if (tmp > 2) { /* skewed log(block size): 1024 -> 0 | 2048 -> 1 | 4096 -> 2 */ tmp += 10; printf("ext2fs: wrong log2(block size) %d\n", tmp); return (EIO); /* XXX needs translation */ } if (fs->e2fs_bpg == 0) { printf("ext2fs: zero blocks per group\n"); return (EIO); } tmp = letoh32(fs->e2fs_rev); if (tmp > E2FS_REV1) { printf("ext2fs: wrong revision number 0x%x\n", tmp); return (EIO); /* XXX needs translation */ } else if (tmp == E2FS_REV0) return (0); tmp = letoh32(fs->e2fs_first_ino); if (tmp != EXT2_FIRSTINO) { printf("ext2fs: first inode at 0x%x\n", tmp); return (EINVAL); /* XXX needs translation */ } tmp = letoh32(fs->e2fs_features_incompat); mask = tmp & ~(EXT2F_INCOMPAT_SUPP | EXT4F_RO_INCOMPAT_SUPP); if (mask) { printf("ext2fs: unsupported incompat features: "); for (i = 0; i < nitems(incompat); i++) if (mask & incompat[i].mask) printf("%s ", incompat[i].name); printf("\n"); return (EINVAL); /* XXX needs translation */ } if (!ronly && (tmp & EXT4F_RO_INCOMPAT_SUPP)) { printf("ext4fs: only read-only support right now\n"); return (EROFS); /* XXX needs translation */ } if (tmp & EXT2F_INCOMPAT_RECOVER) { printf("ext2fs: your file system says it needs recovery\n"); if (!ronly) return (EROFS); /* XXX needs translation */ } tmp = letoh32(fs->e2fs_features_rocompat) & ~EXT2F_ROCOMPAT_SUPP; if (!ronly && tmp) { printf("ext2fs: unsupported R/O compat features: "); for (i = 0; i < nitems(ro_compat); i++) if (tmp & ro_compat[i].mask) printf("%s ", ro_compat[i].name); printf("\n"); return (EROFS); /* XXX needs translation */ } return (0); }
21 21 14 72 74 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 /* $OpenBSD: subr_percpu.c,v 1.11 2023/09/16 09:33:27 mpi Exp $ */ /* * Copyright (c) 2016 David Gwynne <dlg@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/pool.h> #include <sys/malloc.h> #include <sys/percpu.h> #ifdef MULTIPROCESSOR struct pool cpumem_pl; void percpu_init(void) { pool_init(&cpumem_pl, sizeof(struct cpumem) * ncpusfound, 0, IPL_NONE, PR_WAITOK, "percpumem", &pool_allocator_single); } struct cpumem * cpumem_get(struct pool *pp) { struct cpumem *cm; unsigned int cpu; cm = pool_get(&cpumem_pl, PR_WAITOK); for (cpu = 0; cpu < ncpusfound; cpu++) cm[cpu].mem = pool_get(pp, PR_WAITOK | PR_ZERO); return (cm); } void cpumem_put(struct pool *pp, struct cpumem *cm) { unsigned int cpu; for (cpu = 0; cpu < ncpusfound; cpu++) pool_put(pp, cm[cpu].mem); pool_put(&cpumem_pl, cm); } struct cpumem * cpumem_malloc(size_t sz, int type) { struct cpumem *cm; unsigned int cpu; sz = roundup(sz, CACHELINESIZE); cm = pool_get(&cpumem_pl, PR_WAITOK); for (cpu = 0; cpu < ncpusfound; cpu++) cm[cpu].mem = malloc(sz, type, M_WAITOK | M_ZERO); return (cm); } struct cpumem * cpumem_malloc_ncpus(struct cpumem *bootcm, size_t sz, int type) { struct cpumem *cm; unsigned int cpu; sz = roundup(sz, CACHELINESIZE); cm = pool_get(&cpumem_pl, PR_WAITOK); cm[0].mem = bootcm[0].mem; for (cpu = 1; cpu < ncpusfound; cpu++) cm[cpu].mem = malloc(sz, type, M_WAITOK | M_ZERO); return (cm); } void cpumem_free(struct cpumem *cm, int type, size_t sz) { unsigned int cpu; sz = roundup(sz, CACHELINESIZE); for (cpu = 0; cpu < ncpusfound; cpu++) free(cm[cpu].mem, type, sz); pool_put(&cpumem_pl, cm); } void * cpumem_first(struct cpumem_iter *i, struct cpumem *cm) { i->cpu = 0; return (cm[0].mem); } void * cpumem_next(struct cpumem_iter *i, struct cpumem *cm) { unsigned int cpu = ++i->cpu; if (cpu >= ncpusfound) return (NULL); return (cm[cpu].mem); } struct cpumem * counters_alloc(unsigned int n) { struct cpumem *cm; struct cpumem_iter cmi; uint64_t *counters; unsigned int i; KASSERT(n > 0); n++; /* add space for a generation number */ cm = cpumem_malloc(n * sizeof(uint64_t), M_COUNTERS); CPUMEM_FOREACH(counters, &cmi, cm) { for (i = 0; i < n; i++) counters[i] = 0; } return (cm); } struct cpumem * counters_alloc_ncpus(struct cpumem *cm, unsigned int n) { n++; /* the generation number */ return (cpumem_malloc_ncpus(cm, n * sizeof(uint64_t), M_COUNTERS)); } void counters_free(struct cpumem *cm, unsigned int n) { n++; /* generation number */ cpumem_free(cm, M_COUNTERS, n * sizeof(uint64_t)); } void counters_read(struct cpumem *cm, uint64_t *output, unsigned int n, uint64_t *scratch) { struct cpumem_iter cmi; uint64_t *gen, *counters, *temp = scratch; uint64_t enter, leave; unsigned int i; for (i = 0; i < n; i++) output[i] = 0; if (scratch == NULL) temp = mallocarray(n, sizeof(uint64_t), M_TEMP, M_WAITOK); gen = cpumem_first(&cmi, cm); do { counters = gen + 1; enter = *gen; for (;;) { /* the generation number is odd during an update */ while (enter & 1) { yield(); enter = *gen; } membar_consumer(); for (i = 0; i < n; i++) temp[i] = counters[i]; membar_consumer(); leave = *gen; if (enter == leave) break; enter = leave; } for (i = 0; i < n; i++) output[i] += temp[i]; gen = cpumem_next(&cmi, cm); } while (gen != NULL); if (scratch == NULL) free(temp, M_TEMP, n * sizeof(uint64_t)); } void counters_zero(struct cpumem *cm, unsigned int n) { struct cpumem_iter cmi; uint64_t *counters; unsigned int i; counters = cpumem_first(&cmi, cm); membar_producer(); do { for (i = 0; i < n; i++) counters[i] = 0; /* zero the generation numbers too */ membar_producer(); counters[i] = 0; counters = cpumem_next(&cmi, cm); } while (counters != NULL); } #else /* MULTIPROCESSOR */ /* * Uniprocessor implementation of per-CPU data structures. * * UP percpu memory is a single memory allocation cast to/from the * cpumem struct. It is not scaled up to the size of cacheline because * there's no other cache to contend with. */ void percpu_init(void) { /* nop */ } struct cpumem * cpumem_get(struct pool *pp) { return (pool_get(pp, PR_WAITOK | PR_ZERO)); } void cpumem_put(struct pool *pp, struct cpumem *cm) { pool_put(pp, cm); } struct cpumem * cpumem_malloc(size_t sz, int type) { return (malloc(sz, type, M_WAITOK | M_ZERO)); } struct cpumem * cpumem_malloc_ncpus(struct cpumem *cm, size_t sz, int type) { return (cm); } void cpumem_free(struct cpumem *cm, int type, size_t sz) { free(cm, type, sz); } void * cpumem_first(struct cpumem_iter *i, struct cpumem *cm) { return (cm); } void * cpumem_next(struct cpumem_iter *i, struct cpumem *cm) { return (NULL); } struct cpumem * counters_alloc(unsigned int n) { KASSERT(n > 0); return (cpumem_malloc(n * sizeof(uint64_t), M_COUNTERS)); } struct cpumem * counters_alloc_ncpus(struct cpumem *cm, unsigned int n) { /* this is unnecessary, but symmetrical */ return (cpumem_malloc_ncpus(cm, n * sizeof(uint64_t), M_COUNTERS)); } void counters_free(struct cpumem *cm, unsigned int n) { cpumem_free(cm, M_COUNTERS, n * sizeof(uint64_t)); } void counters_read(struct cpumem *cm, uint64_t *output, unsigned int n, uint64_t *scratch) { uint64_t *counters; unsigned int i; int s; counters = (uint64_t *)cm; s = splhigh(); for (i = 0; i < n; i++) output[i] = counters[i]; splx(s); } void counters_zero(struct cpumem *cm, unsigned int n) { uint64_t *counters; unsigned int i; int s; counters = (uint64_t *)cm; s = splhigh(); for (i = 0; i < n; i++) counters[i] = 0; splx(s); } #endif /* MULTIPROCESSOR */
63 60 51 48 5 3 61 2 59 2 1 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 /* $OpenBSD: pcppi.c,v 1.19 2022/04/06 18:59:28 naddy Exp $ */ /* $NetBSD: pcppi.c,v 1.1 1998/04/15 20:26:18 drochner Exp $ */ /* * Copyright (c) 1996 Carnegie-Mellon University. * All rights reserved. * * Author: Chris G. Demetriou * * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/device.h> #include <sys/errno.h> #include <sys/timeout.h> #include <machine/bus.h> #include <dev/isa/isareg.h> #include <dev/isa/isavar.h> #include <dev/isa/pcppireg.h> #include <dev/isa/pcppivar.h> #include <dev/ic/i8253reg.h> #include "pckbd.h" #include "hidkbd.h" #if NPCKBD > 0 || NHIDKBD > 0 #include <dev/ic/pckbcvar.h> #include <dev/pckbc/pckbdvar.h> #include <dev/hid/hidkbdvar.h> void pcppi_kbd_bell(void *, u_int, u_int, u_int, int); #endif struct pcppi_softc { struct device sc_dv; bus_space_tag_t sc_iot; bus_space_handle_t sc_ppi_ioh, sc_pit1_ioh; struct timeout sc_bell_timeout; int sc_bellactive, sc_bellpitch; int sc_slp; int sc_timeout; }; int pcppi_match(struct device *, void *, void *); void pcppi_attach(struct device *, struct device *, void *); const struct cfattach pcppi_ca = { sizeof(struct pcppi_softc), pcppi_match, pcppi_attach, }; struct cfdriver pcppi_cd = { NULL, "pcppi", DV_DULL }; static void pcppi_bell_stop(void *); #define PCPPIPRI (PZERO - 1) int pcppi_match(struct device *parent, void *match, void *aux) { struct isa_attach_args *ia = aux; bus_space_handle_t ppi_ioh, pit1_ioh; int have_pit1, have_ppi, rv; u_int8_t v, nv; /* If values are hardwired to something that they can't be, punt. */ if ((ia->ia_iobase != IOBASEUNK && ia->ia_iobase != IO_PPI) || ia->ia_maddr != MADDRUNK || ia->ia_msize != 0 || ia->ia_irq != IRQUNK || ia->ia_drq != DRQUNK) return (0); rv = 0; have_pit1 = have_ppi = 0; if (bus_space_map(ia->ia_iot, IO_TIMER1, 4, 0, &pit1_ioh)) goto lose; have_pit1 = 1; if (bus_space_map(ia->ia_iot, IO_PPI, 1, 0, &ppi_ioh)) goto lose; have_ppi = 1; /* * Check for existence of PPI. Realistically, this is either going to * be here or nothing is going to be here. * * We don't want to have any chance of changing speaker output (which * this test might, if it crashes in the middle, or something; * normally it's too quick to produce anything audible), but * many "combo chip" mock-PPI's don't seem to support the top bit * of Port B as a settable bit. The bottom bit has to be settable, * since the speaker driver hardware still uses it. */ v = bus_space_read_1(ia->ia_iot, ppi_ioh, 0); /* XXX */ bus_space_write_1(ia->ia_iot, ppi_ioh, 0, v ^ 0x01); /* XXX */ nv = bus_space_read_1(ia->ia_iot, ppi_ioh, 0); /* XXX */ if (((nv ^ v) & 0x01) == 0x01) rv = 1; bus_space_write_1(ia->ia_iot, ppi_ioh, 0, v); /* XXX */ nv = bus_space_read_1(ia->ia_iot, ppi_ioh, 0); /* XXX */ if (((nv ^ v) & 0x01) != 0x00) { rv = 0; goto lose; } /* * We assume that the programmable interval timer is there. */ lose: if (have_pit1) bus_space_unmap(ia->ia_iot, pit1_ioh, 4); if (have_ppi) bus_space_unmap(ia->ia_iot, ppi_ioh, 1); if (rv) { ia->ia_iobase = IO_PPI; ia->ia_iosize = 0x1; ia->ia_msize = 0x0; } return (rv); } void pcppi_attach(struct device *parent, struct device *self, void *aux) { struct pcppi_softc *sc = (struct pcppi_softc *)self; struct isa_attach_args *ia = aux; bus_space_tag_t iot; struct pcppi_attach_args pa; timeout_set(&sc->sc_bell_timeout, pcppi_bell_stop, sc); sc->sc_iot = iot = ia->ia_iot; if (bus_space_map(iot, IO_TIMER1, 4, 0, &sc->sc_pit1_ioh) || bus_space_map(iot, IO_PPI, 1, 0, &sc->sc_ppi_ioh)) panic("pcppi_attach: couldn't map"); printf("\n"); sc->sc_bellactive = sc->sc_bellpitch = sc->sc_slp = 0; /* Provide a beeper for the keyboard, if there isn't one already. */ #if NPCKBD > 0 pckbd_hookup_bell(pcppi_kbd_bell, sc); #endif #if NHIDKBD > 0 hidkbd_hookup_bell(pcppi_kbd_bell, sc); #endif pa.pa_cookie = sc; while (config_found(self, &pa, 0)) ; } void pcppi_bell(pcppi_tag_t self, int pitch, int period_ms, int slp) { struct pcppi_softc *sc = self; int s1, s2; if (pitch < 0) pitch = 0; else if (pitch > INT_MAX - TIMER_FREQ) pitch = INT_MAX - TIMER_FREQ; if (period_ms < 0) period_ms = 0; else if (period_ms > INT_MAX / 1000) period_ms = INT_MAX / 1000; s1 = spltty(); /* ??? */ if (sc->sc_bellactive) { if (sc->sc_timeout) { sc->sc_timeout = 0; timeout_del(&sc->sc_bell_timeout); } if (sc->sc_slp) wakeup(pcppi_bell_stop); } if (pitch == 0 || period_ms == 0) { pcppi_bell_stop(sc); sc->sc_bellpitch = 0; splx(s1); return; } if (!sc->sc_bellactive || sc->sc_bellpitch != pitch) { s2 = splhigh(); bus_space_write_1(sc->sc_iot, sc->sc_pit1_ioh, TIMER_MODE, TIMER_SEL2 | TIMER_16BIT | TIMER_SQWAVE); bus_space_write_1(sc->sc_iot, sc->sc_pit1_ioh, TIMER_CNTR2, TIMER_DIV(pitch) % 256); bus_space_write_1(sc->sc_iot, sc->sc_pit1_ioh, TIMER_CNTR2, TIMER_DIV(pitch) / 256); splx(s2); /* enable speaker */ bus_space_write_1(sc->sc_iot, sc->sc_ppi_ioh, 0, bus_space_read_1(sc->sc_iot, sc->sc_ppi_ioh, 0) | PIT_SPKR); } sc->sc_bellpitch = pitch; sc->sc_bellactive = 1; if (slp & PCPPI_BELL_POLL) { delay(period_ms * 1000); pcppi_bell_stop(sc); } else { sc->sc_timeout = 1; timeout_add_msec(&sc->sc_bell_timeout, period_ms); if (slp & PCPPI_BELL_SLEEP) { sc->sc_slp = 1; tsleep_nsec(pcppi_bell_stop, PCPPIPRI | PCATCH, "bell", INFSLP); sc->sc_slp = 0; } } splx(s1); } static void pcppi_bell_stop(void *arg) { struct pcppi_softc *sc = arg; int s; s = spltty(); /* ??? */ sc->sc_timeout = 0; /* disable bell */ bus_space_write_1(sc->sc_iot, sc->sc_ppi_ioh, 0, bus_space_read_1(sc->sc_iot, sc->sc_ppi_ioh, 0) & ~PIT_SPKR); sc->sc_bellactive = 0; if (sc->sc_slp) wakeup(pcppi_bell_stop); splx(s); } #if NPCKBD > 0 || NHIDKBD > 0 void pcppi_kbd_bell(void *arg, u_int pitch, u_int period, u_int volume, int poll) { /* * NB: volume ignored. */ pcppi_bell(arg, volume ? pitch : 0, period, poll ? PCPPI_BELL_POLL : 0); } #endif /* NPCKBD > 0 || NHIDKBD > 0 */
30 25 26 28 2 28 28 28 3 3 5 5 2 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 /* $OpenBSD: pci_machdep.c,v 1.80 2024/05/13 10:01:53 kettenis Exp $ */ /* $NetBSD: pci_machdep.c,v 1.3 2003/05/07 21:33:58 fvdl Exp $ */ /*- * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, * NASA Ames Research Center. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. * Copyright (c) 1994 Charles M. Hannum. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Charles M. Hannum. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Machine-specific functions for PCI autoconfiguration. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/extent.h> #include <sys/malloc.h> #include <machine/bus.h> #include <machine/pio.h> #include <machine/intr.h> #include <machine/biosvar.h> #include <dev/isa/isareg.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcireg.h> #include <dev/pci/pcidevs.h> #include <dev/pci/ppbreg.h> #include "ioapic.h" #if NIOAPIC > 0 #include <machine/i82093var.h> #include <machine/mpbiosvar.h> #endif #include "acpi.h" #include "acpidmar.h" #if NACPIDMAR > 0 #include <dev/acpi/acpidmar.h> #endif /* * Memory Mapped Configuration space access. * * Since mapping the whole configuration space will cost us up to * 256MB of kernel virtual memory, we use separate mappings per bus. * The mappings are created on-demand, such that we only use kernel * virtual memory for busses that are actually present. */ bus_addr_t pci_mcfg_addr; int pci_mcfg_min_bus, pci_mcfg_max_bus; bus_space_tag_t pci_mcfgt; bus_space_handle_t pci_mcfgh[256]; struct mutex pci_conf_lock = MUTEX_INITIALIZER(IPL_HIGH); #define PCI_CONF_LOCK() \ do { \ mtx_enter(&pci_conf_lock); \ } while (0) #define PCI_CONF_UNLOCK() \ do { \ mtx_leave(&pci_conf_lock); \ } while (0) #define PCI_MODE1_ENABLE 0x80000000UL #define PCI_MODE1_ADDRESS_REG 0x0cf8 #define PCI_MODE1_DATA_REG 0x0cfc /* * PCI doesn't have any special needs; just use the generic versions * of these functions. */ struct bus_dma_tag pci_bus_dma_tag = { NULL, /* _may_bounce */ _bus_dmamap_create, _bus_dmamap_destroy, _bus_dmamap_load, _bus_dmamap_load_mbuf, _bus_dmamap_load_uio, _bus_dmamap_load_raw, _bus_dmamap_unload, _bus_dmamap_sync, _bus_dmamem_alloc, _bus_dmamem_alloc_range, _bus_dmamem_free, _bus_dmamem_map, _bus_dmamem_unmap, _bus_dmamem_mmap, }; void pci_mcfg_init(bus_space_tag_t iot, bus_addr_t addr, int segment, int min_bus, int max_bus) { if (segment == 0) { pci_mcfgt = iot; pci_mcfg_addr = addr; pci_mcfg_min_bus = min_bus; pci_mcfg_max_bus = max_bus; } } pci_chipset_tag_t pci_lookup_segment(int segment) { KASSERT(segment == 0); return NULL; } void pci_attach_hook(struct device *parent, struct device *self, struct pcibus_attach_args *pba) { } int pci_bus_maxdevs(pci_chipset_tag_t pc, int busno) { return (32); } pcitag_t pci_make_tag(pci_chipset_tag_t pc, int bus, int device, int function) { if (bus >= 256 || device >= 32 || function >= 8) panic("pci_make_tag: bad request"); return (PCI_MODE1_ENABLE | (bus << 16) | (device << 11) | (function << 8)); } void pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag, int *bp, int *dp, int *fp) { if (bp != NULL) *bp = (tag >> 16) & 0xff; if (dp != NULL) *dp = (tag >> 11) & 0x1f; if (fp != NULL) *fp = (tag >> 8) & 0x7; } int pci_conf_size(pci_chipset_tag_t pc, pcitag_t tag) { int bus; if (pci_mcfg_addr) { pci_decompose_tag(pc, tag, &bus, NULL, NULL); if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus) return PCIE_CONFIG_SPACE_SIZE; } return PCI_CONFIG_SPACE_SIZE; } void pci_mcfg_map_bus(int bus) { if (pci_mcfgh[bus]) return; if (bus_space_map(pci_mcfgt, pci_mcfg_addr + (bus << 20), 1 << 20, 0, &pci_mcfgh[bus])) panic("pci_conf_read: cannot map mcfg space"); } pcireg_t pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) { pcireg_t data; int bus; KASSERT((reg & 0x3) == 0); if (pci_mcfg_addr && reg >= PCI_CONFIG_SPACE_SIZE) { pci_decompose_tag(pc, tag, &bus, NULL, NULL); if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus) { pci_mcfg_map_bus(bus); data = bus_space_read_4(pci_mcfgt, pci_mcfgh[bus], (tag & 0x000ff00) << 4 | reg); return data; } } PCI_CONF_LOCK(); outl(PCI_MODE1_ADDRESS_REG, tag | reg); data = inl(PCI_MODE1_DATA_REG); outl(PCI_MODE1_ADDRESS_REG, 0); PCI_CONF_UNLOCK(); return data; } void pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) { int bus; KASSERT((reg & 0x3) == 0); if (pci_mcfg_addr && reg >= PCI_CONFIG_SPACE_SIZE) { pci_decompose_tag(pc, tag, &bus, NULL, NULL); if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus) { pci_mcfg_map_bus(bus); bus_space_write_4(pci_mcfgt, pci_mcfgh[bus], (tag & 0x000ff00) << 4 | reg, data); return; } } PCI_CONF_LOCK(); outl(PCI_MODE1_ADDRESS_REG, tag | reg); outl(PCI_MODE1_DATA_REG, data); outl(PCI_MODE1_ADDRESS_REG, 0); PCI_CONF_UNLOCK(); } int pci_msix_table_map(pci_chipset_tag_t pc, pcitag_t tag, bus_space_tag_t memt, bus_space_handle_t *memh) { bus_addr_t base; pcireg_t reg, table, type; int bir, offset; int off, tblsz; if (pci_get_capability(pc, tag, PCI_CAP_MSIX, &off, &reg) == 0) panic("%s: no msix capability", __func__); table = pci_conf_read(pc, tag, off + PCI_MSIX_TABLE); bir = (table & PCI_MSIX_TABLE_BIR); offset = (table & PCI_MSIX_TABLE_OFF); tblsz = PCI_MSIX_MC_TBLSZ(reg) + 1; bir = PCI_MAPREG_START + bir * 4; type = pci_mapreg_type(pc, tag, bir); if (pci_mapreg_info(pc, tag, bir, type, &base, NULL, NULL) || _bus_space_map(memt, base + offset, tblsz * 16, 0, memh)) return -1; return 0; } void pci_msix_table_unmap(pci_chipset_tag_t pc, pcitag_t tag, bus_space_tag_t memt, bus_space_handle_t memh) { pcireg_t reg; int tblsz; if (pci_get_capability(pc, tag, PCI_CAP_MSIX, NULL, &reg) == 0) panic("%s: no msix capability", __func__); tblsz = PCI_MSIX_MC_TBLSZ(reg) + 1; _bus_space_unmap(memt, memh, tblsz * 16, NULL); } /* * We pack the MSI vector number into the lower 8 bits of the PCI tag * and use that as the MSI/MSI-X "PIC" pin number. This allows us to * address 256 MSI vectors which ought to be enough for anybody. */ #define PCI_MSI_VEC_MASK 0xff #define PCI_MSI_VEC(pin) ((pin) & PCI_MSI_VEC_MASK) #define PCI_MSI_TAG(pin) ((pin) & ~PCI_MSI_VEC_MASK) #define PCI_MSI_PIN(tag, vec) ((tag) | (vec)) void msi_hwmask(struct pic *, int); void msi_hwunmask(struct pic *, int); void msi_addroute(struct pic *, struct cpu_info *, int, int, int); void msi_delroute(struct pic *, struct cpu_info *, int, int, int); int msi_allocidtvec(struct pic *, int, int, int); struct pic msi_pic = { {0, {NULL}, NULL, 0, "msi", NULL, 0, 0}, PIC_MSI, #ifdef MULTIPROCESSOR {}, #endif msi_hwmask, msi_hwunmask, msi_addroute, msi_delroute, msi_allocidtvec, NULL, ioapic_edge_stubs }; void msi_hwmask(struct pic *pic, int pin) { pci_chipset_tag_t pc = NULL; /* XXX */ pcitag_t tag = PCI_MSI_TAG(pin); int vec = PCI_MSI_VEC(pin); pcireg_t reg, mask; int off; if (pci_get_capability(pc, tag, PCI_CAP_MSIX, &off, &reg) == 0) return; /* We can't mask if per-vector masking isn't implemented. */ if ((reg & PCI_MSI_MC_PVMASK) == 0) return; if (reg & PCI_MSI_MC_C64) { mask = pci_conf_read(pc, tag, off + PCI_MSI_MASK64); pci_conf_write(pc, tag, off + PCI_MSI_MASK64, mask | (1U << vec)); } else { mask = pci_conf_read(pc, tag, off + PCI_MSI_MASK32); pci_conf_write(pc, tag, off + PCI_MSI_MASK32, mask | (1U << vec)); } } void msi_hwunmask(struct pic *pic, int pin) { pci_chipset_tag_t pc = NULL; /* XXX */ pcitag_t tag = PCI_MSI_TAG(pin); int vec = PCI_MSI_VEC(pin); pcireg_t reg, mask; int off; if (pci_get_capability(pc, tag, PCI_CAP_MSIX, &off, &reg) == 0) return; /* We can't mask if per-vector masking isn't implemented. */ if ((reg & PCI_MSI_MC_PVMASK) == 0) return; if (reg & PCI_MSI_MC_C64) { mask = pci_conf_read(pc, tag, off + PCI_MSI_MASK64); pci_conf_write(pc, tag, off + PCI_MSI_MASK64, mask & ~(1U << vec)); } else { mask = pci_conf_read(pc, tag, off + PCI_MSI_MASK32); pci_conf_write(pc, tag, off + PCI_MSI_MASK32, mask & ~(1U << vec)); } } void msi_addroute(struct pic *pic, struct cpu_info *ci, int pin, int idtvec, int type) { pci_chipset_tag_t pc = NULL; /* XXX */ pcitag_t tag = PCI_MSI_TAG(pin); int vec = PCI_MSI_VEC(pin); pcireg_t reg, addr; int off; if (pci_get_capability(pc, tag, PCI_CAP_MSI, &off, &reg) == 0) panic("%s: no msi capability", __func__); if (vec != 0) return; addr = 0xfee00000UL | (ci->ci_apicid << 12); if (reg & PCI_MSI_MC_C64) { pci_conf_write(pc, tag, off + PCI_MSI_MA, addr); pci_conf_write(pc, tag, off + PCI_MSI_MAU32, 0); pci_conf_write(pc, tag, off + PCI_MSI_MD64, idtvec); } else { pci_conf_write(pc, tag, off + PCI_MSI_MA, addr); pci_conf_write(pc, tag, off + PCI_MSI_MD32, idtvec); } pci_conf_write(pc, tag, off, reg | PCI_MSI_MC_MSIE); } void msi_delroute(struct pic *pic, struct cpu_info *ci, int pin, int idtvec, int type) { pci_chipset_tag_t pc = NULL; /* XXX */ pcitag_t tag = PCI_MSI_TAG(pin); int vec = PCI_MSI_VEC(pin); pcireg_t reg; int off; if (vec != 0) return; if (pci_get_capability(pc, tag, PCI_CAP_MSI, &off, &reg)) pci_conf_write(pc, tag, off, reg & ~PCI_MSI_MC_MSIE); } int msi_allocidtvec(struct pic *pic, int pin, int low, int high) { pci_chipset_tag_t pc = NULL; /* XXX */ pcitag_t tag = PCI_MSI_TAG(pin); int vec = PCI_MSI_VEC(pin); int idtvec, mme, off; pcireg_t reg; if (pci_get_capability(pc, tag, PCI_CAP_MSI, &off, &reg) == 0) panic("%s: no msi capability", __func__); reg = pci_conf_read(pc, tag, off); mme = ((reg & PCI_MSI_MC_MME_MASK) >> PCI_MSI_MC_MME_SHIFT); if (vec >= (1 << mme)) return 0; if (vec == 0) { idtvec = idt_vec_alloc_range(low, high, (1 << mme)); if (reg & PCI_MSI_MC_C64) pci_conf_write(pc, tag, off + PCI_MSI_MD64, idtvec); else pci_conf_write(pc, tag, off + PCI_MSI_MD32, idtvec); } else { if (reg & PCI_MSI_MC_C64) reg = pci_conf_read(pc, tag, off + PCI_MSI_MD64); else reg = pci_conf_read(pc, tag, off + PCI_MSI_MD32); KASSERT(reg > 0); idtvec = reg + vec; } return idtvec; } int pci_intr_enable_msivec(struct pci_attach_args *pa, int num_vec) { pci_chipset_tag_t pc = pa->pa_pc; pcitag_t tag = pa->pa_tag; pcireg_t reg; int mmc, mme, off; if ((pa->pa_flags & PCI_FLAGS_MSI_ENABLED) == 0 || mp_busses == NULL || pci_get_capability(pc, tag, PCI_CAP_MSI, &off, &reg) == 0) return 1; mmc = ((reg & PCI_MSI_MC_MMC_MASK) >> PCI_MSI_MC_MMC_SHIFT); if (num_vec > (1 << mmc)) return 1; mme = ((reg & PCI_MSI_MC_MME_MASK) >> PCI_MSI_MC_MME_SHIFT); while ((1 << mme) < num_vec) mme++; reg &= ~PCI_MSI_MC_MME_MASK; reg |= (mme << PCI_MSI_MC_MME_SHIFT); pci_conf_write(pc, tag, off, reg); return 0; } int pci_intr_map_msi(struct pci_attach_args *pa, pci_intr_handle_t *ihp) { pci_chipset_tag_t pc = pa->pa_pc; pcitag_t tag = pa->pa_tag; pcireg_t reg; int off; if ((pa->pa_flags & PCI_FLAGS_MSI_ENABLED) == 0 || mp_busses == NULL || pci_get_capability(pc, tag, PCI_CAP_MSI, &off, &reg) == 0) return 1; /* Make sure we only enable one MSI vector. */ reg &= ~PCI_MSI_MC_MME_MASK; pci_conf_write(pc, tag, off, reg); ihp->tag = tag; ihp->line = APIC_INT_VIA_MSG; ihp->pin = 0; return 0; } int pci_intr_map_msivec(struct pci_attach_args *pa, int vec, pci_intr_handle_t *ihp) { pci_chipset_tag_t pc = pa->pa_pc; pcitag_t tag = pa->pa_tag; pcireg_t reg; int mme, off; if ((pa->pa_flags & PCI_FLAGS_MSI_ENABLED) == 0 || mp_busses == NULL || pci_get_capability(pc, tag, PCI_CAP_MSI, &off, &reg) == 0) return 1; mme = ((reg & PCI_MSI_MC_MME_MASK) >> PCI_MSI_MC_MME_SHIFT); if (vec >= (1 << mme)) return 1; ihp->tag = PCI_MSI_PIN(tag, vec); ihp->line = APIC_INT_VIA_MSG; ihp->pin = 0; return 0; } void msix_hwmask(struct pic *, int); void msix_hwunmask(struct pic *, int); void msix_addroute(struct pic *, struct cpu_info *, int, int, int); void msix_delroute(struct pic *, struct cpu_info *, int, int, int); struct pic msix_pic = { {0, {NULL}, NULL, 0, "msix", NULL, 0, 0}, PIC_MSI, #ifdef MULTIPROCESSOR {}, #endif msix_hwmask, msix_hwunmask, msix_addroute, msix_delroute, NULL, NULL, ioapic_edge_stubs }; void msix_hwmask(struct pic *pic, int pin) { pci_chipset_tag_t pc = NULL; /* XXX */ bus_space_tag_t memt = X86_BUS_SPACE_MEM; /* XXX */ bus_space_handle_t memh; pcitag_t tag = PCI_MSI_TAG(pin); int entry = PCI_MSI_VEC(pin); pcireg_t reg; uint32_t ctrl; if (pci_get_capability(pc, tag, PCI_CAP_MSIX, NULL, &reg) == 0) return; KASSERT(entry <= PCI_MSIX_MC_TBLSZ(reg)); if (pci_msix_table_map(pc, tag, memt, &memh)) panic("%s: cannot map registers", __func__); ctrl = bus_space_read_4(memt, memh, PCI_MSIX_VC(entry)); bus_space_write_4(memt, memh, PCI_MSIX_VC(entry), ctrl | PCI_MSIX_VC_MASK); pci_msix_table_unmap(pc, tag, memt, memh); } void msix_hwunmask(struct pic *pic, int pin) { pci_chipset_tag_t pc = NULL; /* XXX */ bus_space_tag_t memt = X86_BUS_SPACE_MEM; /* XXX */ bus_space_handle_t memh; pcitag_t tag = PCI_MSI_TAG(pin); int entry = PCI_MSI_VEC(pin); pcireg_t reg; uint32_t ctrl; if (pci_get_capability(pc, tag, PCI_CAP_MSIX, NULL, &reg) == 0) return; if (pci_msix_table_map(pc, tag, memt, &memh)) panic("%s: cannot map registers", __func__); ctrl = bus_space_read_4(memt, memh, PCI_MSIX_VC(entry)); bus_space_write_4(memt, memh, PCI_MSIX_VC(entry), ctrl & ~PCI_MSIX_VC_MASK); pci_msix_table_unmap(pc, tag, memt, memh); } void msix_addroute(struct pic *pic, struct cpu_info *ci, int pin, int idtvec, int type) { pci_chipset_tag_t pc = NULL; /* XXX */ bus_space_tag_t memt = X86_BUS_SPACE_MEM; /* XXX */ bus_space_handle_t memh; pcitag_t tag = PCI_MSI_TAG(pin); int entry = PCI_MSI_VEC(pin); pcireg_t reg, addr; uint32_t ctrl; int off; if (pci_get_capability(pc, tag, PCI_CAP_MSIX, &off, &reg) == 0) panic("%s: no msix capability", __func__); KASSERT(entry <= PCI_MSIX_MC_TBLSZ(reg)); if (pci_msix_table_map(pc, tag, memt, &memh)) panic("%s: cannot map registers", __func__); addr = 0xfee00000UL | (ci->ci_apicid << 12); bus_space_write_4(memt, memh, PCI_MSIX_MA(entry), addr); bus_space_write_4(memt, memh, PCI_MSIX_MAU32(entry), 0); bus_space_write_4(memt, memh, PCI_MSIX_MD(entry), idtvec); bus_space_barrier(memt, memh, PCI_MSIX_MA(entry), 16, BUS_SPACE_BARRIER_WRITE); ctrl = bus_space_read_4(memt, memh, PCI_MSIX_VC(entry)); bus_space_write_4(memt, memh, PCI_MSIX_VC(entry), ctrl & ~PCI_MSIX_VC_MASK); pci_msix_table_unmap(pc, tag, memt, memh); pci_conf_write(pc, tag, off, reg | PCI_MSIX_MC_MSIXE); } void msix_delroute(struct pic *pic, struct cpu_info *ci, int pin, int idtvec, int type) { pci_chipset_tag_t pc = NULL; /* XXX */ bus_space_tag_t memt = X86_BUS_SPACE_MEM; /* XXX */ bus_space_handle_t memh; pcitag_t tag = PCI_MSI_TAG(pin); int entry = PCI_MSI_VEC(pin); pcireg_t reg; uint32_t ctrl; if (pci_get_capability(pc, tag, PCI_CAP_MSIX, NULL, &reg) == 0) return; KASSERT(entry <= PCI_MSIX_MC_TBLSZ(reg)); if (pci_msix_table_map(pc, tag, memt, &memh)) return; ctrl = bus_space_read_4(memt, memh, PCI_MSIX_VC(entry)); bus_space_write_4(memt, memh, PCI_MSIX_VC(entry), ctrl | PCI_MSIX_VC_MASK); pci_msix_table_unmap(pc, tag, memt, memh); } int pci_intr_map_msix(struct pci_attach_args *pa, int vec, pci_intr_handle_t *ihp) { pci_chipset_tag_t pc = pa->pa_pc; pcitag_t tag = pa->pa_tag; pcireg_t reg; KASSERT(PCI_MSI_VEC(vec) == vec); if ((pa->pa_flags & PCI_FLAGS_MSI_ENABLED) == 0 || mp_busses == NULL || pci_get_capability(pc, tag, PCI_CAP_MSIX, NULL, &reg) == 0) return 1; if (vec > PCI_MSIX_MC_TBLSZ(reg)) return 1; ihp->tag = PCI_MSI_PIN(tag, vec); ihp->line = APIC_INT_VIA_MSGX; ihp->pin = 0; return 0; } int pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) { int pin = pa->pa_rawintrpin; int line = pa->pa_intrline; #if NIOAPIC > 0 struct mp_intr_map *mip; int bus, dev, func; #endif if (pin == 0) { /* No IRQ used. */ goto bad; } if (pin > PCI_INTERRUPT_PIN_MAX) { printf("pci_intr_map: bad interrupt pin %d\n", pin); goto bad; } ihp->tag = pa->pa_tag; ihp->line = line; ihp->pin = pin; #if NIOAPIC > 0 pci_decompose_tag(pa->pa_pc, pa->pa_tag, &bus, &dev, &func); if (mp_busses != NULL) { int mpspec_pin = (dev << 2) | (pin - 1); if (bus < mp_nbusses) { for (mip = mp_busses[bus].mb_intrs; mip != NULL; mip = mip->next) { if (&mp_busses[bus] == mp_isa_bus || &mp_busses[bus] == mp_eisa_bus) continue; if (mip->bus_pin == mpspec_pin) { ihp->line = mip->ioapic_ih | line; return 0; } } } if (pa->pa_bridgetag) { int swizpin = PPB_INTERRUPT_SWIZZLE(pin, dev); if (pa->pa_bridgeih[swizpin - 1].line != -1) { ihp->line = pa->pa_bridgeih[swizpin - 1].line; ihp->line |= line; return 0; } } /* * No explicit PCI mapping found. This is not fatal, * we'll try the ISA (or possibly EISA) mappings next. */ } #endif /* * Section 6.2.4, `Miscellaneous Functions', says that 255 means * `unknown' or `no connection' on a PC. We assume that a device with * `no connection' either doesn't have an interrupt (in which case the * pin number should be 0, and would have been noticed above), or * wasn't configured by the BIOS (in which case we punt, since there's * no real way we can know how the interrupt lines are mapped in the * hardware). * * XXX * Since IRQ 0 is only used by the clock, and we can't actually be sure * that the BIOS did its job, we also recognize that as meaning that * the BIOS has not configured the device. */ if (line == 0 || line == X86_PCI_INTERRUPT_LINE_NO_CONNECTION) goto bad; if (line >= NUM_LEGACY_IRQS) { printf("pci_intr_map: bad interrupt line %d\n", line); goto bad; } if (line == 2) { printf("pci_intr_map: changed line 2 to line 9\n"); line = 9; } #if NIOAPIC > 0 if (mp_busses != NULL) { if (mip == NULL && mp_isa_bus) { for (mip = mp_isa_bus->mb_intrs; mip != NULL; mip = mip->next) { if (mip->bus_pin == line) { ihp->line = mip->ioapic_ih | line; return 0; } } } #if NEISA > 0 if (mip == NULL && mp_eisa_bus) { for (mip = mp_eisa_bus->mb_intrs; mip != NULL; mip = mip->next) { if (mip->bus_pin == line) { ihp->line = mip->ioapic_ih | line; return 0; } } } #endif if (mip == NULL) { printf("pci_intr_map: " "bus %d dev %d func %d pin %d; line %d\n", bus, dev, func, pin, line); printf("pci_intr_map: no MP mapping found\n"); } } #endif return 0; bad: ihp->line = -1; return 1; } const char * pci_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih) { static char irqstr[64]; if (ih.line == 0) panic("pci_intr_string: bogus handle 0x%x", ih.line); if (ih.line & APIC_INT_VIA_MSG) return ("msi"); if (ih.line & APIC_INT_VIA_MSGX) return ("msix"); #if NIOAPIC > 0 if (ih.line & APIC_INT_VIA_APIC) snprintf(irqstr, sizeof(irqstr), "apic %d int %d", APIC_IRQ_APIC(ih.line), APIC_IRQ_PIN(ih.line)); else snprintf(irqstr, sizeof(irqstr), "irq %d", pci_intr_line(pc, ih)); #else snprintf(irqstr, sizeof(irqstr), "irq %d", pci_intr_line(pc, ih)); #endif return (irqstr); } #include "acpiprt.h" #if NACPIPRT > 0 void acpiprt_route_interrupt(int bus, int dev, int pin); #endif void * pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level, int (*func)(void *), void *arg, const char *what) { return pci_intr_establish_cpu(pc, ih, level, NULL, func, arg, what); } void * pci_intr_establish_cpu(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level, struct cpu_info *ci, int (*func)(void *), void *arg, const char *what) { int pin, irq; int bus, dev; pcitag_t tag = ih.tag; struct pic *pic; if (ih.line & APIC_INT_VIA_MSG) { return intr_establish(-1, &msi_pic, tag, IST_PULSE, level, ci, func, arg, what); } if (ih.line & APIC_INT_VIA_MSGX) { return intr_establish(-1, &msix_pic, tag, IST_PULSE, level, ci, func, arg, what); } pci_decompose_tag(pc, ih.tag, &bus, &dev, NULL); #if NACPIPRT > 0 acpiprt_route_interrupt(bus, dev, ih.pin); #endif pic = &i8259_pic; pin = irq = ih.line; #if NIOAPIC > 0 if (ih.line & APIC_INT_VIA_APIC) { pic = (struct pic *)ioapic_find(APIC_IRQ_APIC(ih.line)); if (pic == NULL) { printf("pci_intr_establish: bad ioapic %d\n", APIC_IRQ_APIC(ih.line)); return NULL; } pin = APIC_IRQ_PIN(ih.line); irq = APIC_IRQ_LEGACY_IRQ(ih.line); if (irq < 0 || irq >= NUM_LEGACY_IRQS) irq = -1; } #endif return intr_establish(irq, pic, pin, IST_LEVEL, level, ci, func, arg, what); } void pci_intr_disestablish(pci_chipset_tag_t pc, void *cookie) { intr_disestablish(cookie); } struct extent *pciio_ex; struct extent *pcimem_ex; struct extent *pcibus_ex; void pci_init_extents(void) { bios_memmap_t *bmp; u_int64_t size; if (pciio_ex == NULL) { /* * We only have 64K of addressable I/O space. * However, since BARs may contain garbage, we cover * the full 32-bit address space defined by PCI of * which we only make the first 64K available. */ pciio_ex = extent_create("pciio", 0, 0xffffffff, M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED); if (pciio_ex == NULL) return; extent_free(pciio_ex, 0, 0x10000, EX_NOWAIT); } if (pcimem_ex == NULL) { /* * Cover the 36-bit address space addressable by PAE * here. As long as vendors continue to support * 32-bit operating systems, we should never see BARs * outside that region. * * Dell 13G servers have important devices outside the * 36-bit address space. Until we can extract the address * ranges from ACPI, expand the allowed range to suit. */ pcimem_ex = extent_create("pcimem", 0, 0xffffffffffffffffUL, M_DEVBUF, NULL, 0, EX_NOWAIT); if (pcimem_ex == NULL) return; extent_alloc_region(pcimem_ex, 0x40000000000UL, 0xfffffc0000000000UL, EX_NOWAIT); for (bmp = bios_memmap; bmp->type != BIOS_MAP_END; bmp++) { /* * Ignore address space beyond 4G. */ if (bmp->addr >= 0x100000000ULL) continue; size = bmp->size; if (bmp->addr + size >= 0x100000000ULL) size = 0x100000000ULL - bmp->addr; /* Ignore zero-sized regions. */ if (size == 0) continue; if (extent_alloc_region(pcimem_ex, bmp->addr, size, EX_NOWAIT)) printf("memory map conflict 0x%llx/0x%llx\n", bmp->addr, bmp->size); } /* Take out the video buffer area and BIOS areas. */ extent_alloc_region(pcimem_ex, IOM_BEGIN, IOM_SIZE, EX_CONFLICTOK | EX_NOWAIT); } if (pcibus_ex == NULL) { pcibus_ex = extent_create("pcibus", 0, 0xff, M_DEVBUF, NULL, 0, EX_NOWAIT); } } int pci_probe_device_hook(pci_chipset_tag_t pc, struct pci_attach_args *pa) { #if NACPIDMAR > 0 acpidmar_pci_hook(pc, pa); #endif return 0; } #if NACPI > 0 void acpi_pci_match(struct device *, struct pci_attach_args *); pcireg_t acpi_pci_min_powerstate(pci_chipset_tag_t, pcitag_t); void acpi_pci_set_powerstate(pci_chipset_tag_t, pcitag_t, int, int); #endif void pci_dev_postattach(struct device *dev, struct pci_attach_args *pa) { #if NACPI > 0 acpi_pci_match(dev, pa); #endif } pcireg_t pci_min_powerstate(pci_chipset_tag_t pc, pcitag_t tag) { #if NACPI > 0 return acpi_pci_min_powerstate(pc, tag); #else return pci_get_powerstate(pc, tag); #endif } void pci_set_powerstate_md(pci_chipset_tag_t pc, pcitag_t tag, int state, int pre) { #if NACPI > 0 acpi_pci_set_powerstate(pc, tag, state, pre); #endif }
71 1 44 67 1 4 32 2 7 16 6 10 15 183 1 4 178 67 2 17 38 39 3 4 15 107 46 7 38 14 154 106 20 3 7 2 5 4 6 8 5 5 5 12 12 3 114 1 3 109 112 111 123 84 3 1 1 1 1 2 32 13 13 52 41 14 22 30 52 52 384 216 211 238 17 177 54 55 54 13 11 4 4 5 2 2 1 1 167 167 15 35 7 30 22 2 1 15 52 48 29 19 69 69 3 12 57 1 10 17 42 59 92 171 172 186 187 124 61 187 42 42 6 6 42 34 8 43 8 7 7 2 5 7 5 1 1 3 13 9 4 13 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 /* $OpenBSD: in_pcb.c,v 1.302 2024/04/19 10:13:58 bluhm Exp $ */ /* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 * * NRL grants permission for redistribution and use in source and binary * forms, with or without modification, of the software and documentation * created at NRL provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgements: * This product includes software developed by the University of * California, Berkeley and its contributors. * This product includes software developed at the Information * Technology Division, US Naval Research Laboratory. * 4. Neither the name of the NRL nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the US Naval * Research Laboratory (NRL). */ #include "pf.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/protosw.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/domain.h> #include <sys/mount.h> #include <sys/pool.h> #include <sys/proc.h> #include <net/if.h> #include <net/if_var.h> #include <net/pfvar.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/in_var.h> #include <netinet/ip.h> #include <netinet/ip_var.h> #include <netinet6/ip6_var.h> #include <netinet/in_pcb.h> #ifdef IPSEC #include <netinet/ip_esp.h> #endif /* IPSEC */ #include "stoeplitz.h" #if NSTOEPLITZ > 0 #include <net/toeplitz.h> #endif const struct in_addr zeroin_addr; const union inpaddru zeroin46_addr; /* * These configure the range of local port addresses assigned to * "unspecified" outgoing connections/packets/whatever. */ int ipport_firstauto = IPPORT_RESERVED; int ipport_lastauto = IPPORT_USERRESERVED; int ipport_hifirstauto = IPPORT_HIFIRSTAUTO; int ipport_hilastauto = IPPORT_HILASTAUTO; struct baddynamicports baddynamicports; struct baddynamicports rootonlyports; struct pool inpcb_pool; void in_pcbhash_insert(struct inpcb *); struct inpcb *in_pcbhash_lookup(struct inpcbtable *, uint64_t, u_int, const struct in_addr *, u_short, const struct in_addr *, u_short); int in_pcbresize(struct inpcbtable *, int); #define INPCBHASH_LOADFACTOR(_x) (((_x) * 3) / 4) uint64_t in_pcbhash(struct inpcbtable *, u_int, const struct in_addr *, u_short, const struct in_addr *, u_short); uint64_t in_pcblhash(struct inpcbtable *, u_int, u_short); struct inpcb *in_pcblookup_lock(struct inpcbtable *, struct in_addr, u_int, struct in_addr, u_int, u_int, int); int in_pcbaddrisavail_lock(const struct inpcb *, struct sockaddr_in *, int, struct proc *, int); int in_pcbpickport(u_int16_t *, const void *, int, const struct inpcb *, struct proc *); /* * in_pcb is used for inet and inet6. in6_pcb only contains special * IPv6 cases. So the internet initializer is used for both domains. */ void in_init(void) { pool_init(&inpcb_pool, sizeof(struct inpcb), 0, IPL_SOFTNET, 0, "inpcb", NULL); } uint64_t in_pcbhash(struct inpcbtable *table, u_int rdomain, const struct in_addr *faddr, u_short fport, const struct in_addr *laddr, u_short lport) { SIPHASH_CTX ctx; u_int32_t nrdom = htonl(rdomain); SipHash24_Init(&ctx, &table->inpt_key); SipHash24_Update(&ctx, &nrdom, sizeof(nrdom)); SipHash24_Update(&ctx, faddr, sizeof(*faddr)); SipHash24_Update(&ctx, &fport, sizeof(fport)); SipHash24_Update(&ctx, laddr, sizeof(*laddr)); SipHash24_Update(&ctx, &lport, sizeof(lport)); return SipHash24_End(&ctx); } uint64_t in_pcblhash(struct inpcbtable *table, u_int rdomain, u_short lport) { SIPHASH_CTX ctx; u_int32_t nrdom = htonl(rdomain); SipHash24_Init(&ctx, &table->inpt_lkey); SipHash24_Update(&ctx, &nrdom, sizeof(nrdom)); SipHash24_Update(&ctx, &lport, sizeof(lport)); return SipHash24_End(&ctx); } void in_pcbinit(struct inpcbtable *table, int hashsize) { mtx_init(&table->inpt_mtx, IPL_SOFTNET); rw_init(&table->inpt_notify, "inpnotify"); TAILQ_INIT(&table->inpt_queue); table->inpt_hashtbl = hashinit(hashsize, M_PCB, M_WAITOK, &table->inpt_mask); table->inpt_lhashtbl = hashinit(hashsize, M_PCB, M_WAITOK, &table->inpt_lmask); table->inpt_count = 0; table->inpt_size = hashsize; arc4random_buf(&table->inpt_key, sizeof(table->inpt_key)); arc4random_buf(&table->inpt_lkey, sizeof(table->inpt_lkey)); } /* * Check if the specified port is invalid for dynamic allocation. */ int in_baddynamic(u_int16_t port, u_int16_t proto) { switch (proto) { case IPPROTO_TCP: return (DP_ISSET(baddynamicports.tcp, port)); case IPPROTO_UDP: #ifdef IPSEC /* Cannot preset this as it is a sysctl */ if (port == udpencap_port) return (1); #endif return (DP_ISSET(baddynamicports.udp, port)); default: return (0); } } int in_rootonly(u_int16_t port, u_int16_t proto) { switch (proto) { case IPPROTO_TCP: return (port < IPPORT_RESERVED || DP_ISSET(rootonlyports.tcp, port)); case IPPROTO_UDP: return (port < IPPORT_RESERVED || DP_ISSET(rootonlyports.udp, port)); default: return (0); } } int in_pcballoc(struct socket *so, struct inpcbtable *table, int wait) { struct inpcb *inp; inp = pool_get(&inpcb_pool, (wait == M_WAIT ? PR_WAITOK : PR_NOWAIT) | PR_ZERO); if (inp == NULL) return (ENOBUFS); inp->inp_table = table; inp->inp_socket = so; refcnt_init_trace(&inp->inp_refcnt, DT_REFCNT_IDX_INPCB); mtx_init(&inp->inp_mtx, IPL_SOFTNET); inp->inp_seclevel.sl_auth = IPSEC_AUTH_LEVEL_DEFAULT; inp->inp_seclevel.sl_esp_trans = IPSEC_ESP_TRANS_LEVEL_DEFAULT; inp->inp_seclevel.sl_esp_network = IPSEC_ESP_NETWORK_LEVEL_DEFAULT; inp->inp_seclevel.sl_ipcomp = IPSEC_IPCOMP_LEVEL_DEFAULT; inp->inp_rtableid = curproc->p_p->ps_rtableid; inp->inp_hops = -1; #ifdef INET6 switch (so->so_proto->pr_domain->dom_family) { case PF_INET6: inp->inp_flags = INP_IPV6; break; case PF_INET: /* inp->inp_flags is initialized to 0 */ break; default: unhandled_af(so->so_proto->pr_domain->dom_family); } inp->inp_cksum6 = -1; #endif /* INET6 */ mtx_enter(&table->inpt_mtx); if (table->inpt_count++ > INPCBHASH_LOADFACTOR(table->inpt_size)) (void)in_pcbresize(table, table->inpt_size * 2); TAILQ_INSERT_HEAD(&table->inpt_queue, inp, inp_queue); in_pcbhash_insert(inp); mtx_leave(&table->inpt_mtx); so->so_pcb = inp; return (0); } int in_pcbbind_locked(struct inpcb *inp, struct mbuf *nam, const void *laddr, struct proc *p) { struct socket *so = inp->inp_socket; u_int16_t lport = 0; int wild = 0; int error; if (inp->inp_lport) return (EINVAL); if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 && ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 || (so->so_options & SO_ACCEPTCONN) == 0)) wild = INPLOOKUP_WILDCARD; #ifdef INET6 if (ISSET(inp->inp_flags, INP_IPV6)) { if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) return (EINVAL); wild |= INPLOOKUP_IPV6; if (nam) { struct sockaddr_in6 *sin6; if ((error = in6_nam2sin6(nam, &sin6))) return (error); if ((error = in6_pcbaddrisavail_lock(inp, sin6, wild, p, IN_PCBLOCK_HOLD))) return (error); laddr = &sin6->sin6_addr; lport = sin6->sin6_port; } } else #endif { if (inp->inp_laddr.s_addr != INADDR_ANY) return (EINVAL); if (nam) { struct sockaddr_in *sin; if ((error = in_nam2sin(nam, &sin))) return (error); if ((error = in_pcbaddrisavail_lock(inp, sin, wild, p, IN_PCBLOCK_HOLD))) return (error); laddr = &sin->sin_addr; lport = sin->sin_port; } } if (lport == 0) { if ((error = in_pcbpickport(&lport, laddr, wild, inp, p))) return (error); } else { if (in_rootonly(ntohs(lport), so->so_proto->pr_protocol) && suser(p) != 0) return (EACCES); } if (nam) { #ifdef INET6 if (ISSET(inp->inp_flags, INP_IPV6)) inp->inp_laddr6 = *(struct in6_addr *)laddr; else #endif inp->inp_laddr = *(struct in_addr *)laddr; } inp->inp_lport = lport; in_pcbrehash(inp); return (0); } int in_pcbbind(struct inpcb *inp, struct mbuf *nam, struct proc *p) { struct inpcbtable *table = inp->inp_table; int error; /* keep lookup, modification, and rehash in sync */ mtx_enter(&table->inpt_mtx); error = in_pcbbind_locked(inp, nam, &zeroin46_addr, p); mtx_leave(&table->inpt_mtx); return error; } int in_pcbaddrisavail_lock(const struct inpcb *inp, struct sockaddr_in *sin, int wild, struct proc *p, int lock) { struct socket *so = inp->inp_socket; struct inpcbtable *table = inp->inp_table; u_int16_t lport = sin->sin_port; int reuseport = (so->so_options & SO_REUSEPORT); if (IN_MULTICAST(sin->sin_addr.s_addr)) { /* * Treat SO_REUSEADDR as SO_REUSEPORT for multicast; * allow complete duplication of binding if * SO_REUSEPORT is set, or if SO_REUSEADDR is set * and a multicast address is bound on both * new and duplicated sockets. */ if (so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) reuseport = SO_REUSEADDR|SO_REUSEPORT; } else if (sin->sin_addr.s_addr != INADDR_ANY) { /* * we must check that we are binding to an address we * own except when: * - SO_BINDANY is set or * - we are binding a UDP socket to 255.255.255.255 or * - we are binding a UDP socket to one of our broadcast * addresses */ if (!ISSET(so->so_options, SO_BINDANY) && !(so->so_type == SOCK_DGRAM && sin->sin_addr.s_addr == INADDR_BROADCAST) && !(so->so_type == SOCK_DGRAM && in_broadcast(sin->sin_addr, inp->inp_rtableid))) { struct ifaddr *ia; sin->sin_port = 0; memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); ia = ifa_ifwithaddr(sintosa(sin), inp->inp_rtableid); sin->sin_port = lport; if (ia == NULL) return (EADDRNOTAVAIL); } } if (lport) { struct inpcb *t; int error = 0; if (so->so_euid && !IN_MULTICAST(sin->sin_addr.s_addr)) { t = in_pcblookup_local_lock(table, &sin->sin_addr, lport, INPLOOKUP_WILDCARD, inp->inp_rtableid, lock); if (t && (so->so_euid != t->inp_socket->so_euid)) error = EADDRINUSE; if (lock == IN_PCBLOCK_GRAB) in_pcbunref(t); if (error) return (error); } t = in_pcblookup_local_lock(table, &sin->sin_addr, lport, wild, inp->inp_rtableid, lock); if (t && (reuseport & t->inp_socket->so_options) == 0) error = EADDRINUSE; if (lock == IN_PCBLOCK_GRAB) in_pcbunref(t); if (error) return (error); } return (0); } int in_pcbaddrisavail(const struct inpcb *inp, struct sockaddr_in *sin, int wild, struct proc *p) { return in_pcbaddrisavail_lock(inp, sin, wild, p, IN_PCBLOCK_GRAB); } int in_pcbpickport(u_int16_t *lport, const void *laddr, int wild, const struct inpcb *inp, struct proc *p) { struct socket *so = inp->inp_socket; struct inpcbtable *table = inp->inp_table; struct inpcb *t; u_int16_t first, last, lower, higher, candidate, localport; int count; MUTEX_ASSERT_LOCKED(&table->inpt_mtx); if (inp->inp_flags & INP_HIGHPORT) { first = ipport_hifirstauto; /* sysctl */ last = ipport_hilastauto; } else if (inp->inp_flags & INP_LOWPORT) { if (suser(p)) return (EACCES); first = IPPORT_RESERVED-1; /* 1023 */ last = 600; /* not IPPORT_RESERVED/2 */ } else { first = ipport_firstauto; /* sysctl */ last = ipport_lastauto; } if (first < last) { lower = first; higher = last; } else { lower = last; higher = first; } /* * Simple check to ensure all ports are not used up causing * a deadlock here. */ count = higher - lower; candidate = lower + arc4random_uniform(count); do { do { if (count-- < 0) /* completely used? */ return (EADDRNOTAVAIL); ++candidate; if (candidate < lower || candidate > higher) candidate = lower; localport = htons(candidate); } while (in_baddynamic(candidate, so->so_proto->pr_protocol)); t = in_pcblookup_local_lock(table, laddr, localport, wild, inp->inp_rtableid, IN_PCBLOCK_HOLD); } while (t != NULL); *lport = localport; return (0); } /* * Connect from a socket to a specified address. * Both address and port must be specified in argument sin. * If don't have a local address for this socket yet, * then pick one. */ int in_pcbconnect(struct inpcb *inp, struct mbuf *nam) { struct inpcbtable *table = inp->inp_table; struct in_addr ina; struct sockaddr_in *sin; struct inpcb *t; int error; #ifdef INET6 if (ISSET(inp->inp_flags, INP_IPV6)) return (in6_pcbconnect(inp, nam)); #endif if ((error = in_nam2sin(nam, &sin))) return (error); if (sin->sin_port == 0) return (EADDRNOTAVAIL); error = in_pcbselsrc(&ina, sin, inp); if (error) return (error); /* keep lookup, modification, and rehash in sync */ mtx_enter(&table->inpt_mtx); t = in_pcblookup_lock(inp->inp_table, sin->sin_addr, sin->sin_port, ina, inp->inp_lport, inp->inp_rtableid, IN_PCBLOCK_HOLD); if (t != NULL) { mtx_leave(&table->inpt_mtx); return (EADDRINUSE); } KASSERT(inp->inp_laddr.s_addr == INADDR_ANY || inp->inp_lport); if (inp->inp_laddr.s_addr == INADDR_ANY) { if (inp->inp_lport == 0) { error = in_pcbbind_locked(inp, NULL, &ina, curproc); if (error) { mtx_leave(&table->inpt_mtx); return (error); } t = in_pcblookup_lock(inp->inp_table, sin->sin_addr, sin->sin_port, ina, inp->inp_lport, inp->inp_rtableid, IN_PCBLOCK_HOLD); if (t != NULL) { inp->inp_lport = 0; mtx_leave(&table->inpt_mtx); return (EADDRINUSE); } } inp->inp_laddr = ina; } inp->inp_faddr = sin->sin_addr; inp->inp_fport = sin->sin_port; in_pcbrehash(inp); mtx_leave(&table->inpt_mtx); #if NSTOEPLITZ > 0 inp->inp_flowid = stoeplitz_ip4port(inp->inp_faddr.s_addr, inp->inp_laddr.s_addr, inp->inp_fport, inp->inp_lport); #endif return (0); } void in_pcbdisconnect(struct inpcb *inp) { #if NPF > 0 pf_remove_divert_state(inp); pf_inp_unlink(inp); #endif inp->inp_flowid = 0; if (inp->inp_socket->so_state & SS_NOFDREF) in_pcbdetach(inp); } void in_pcbdetach(struct inpcb *inp) { struct socket *so = inp->inp_socket; struct inpcbtable *table = inp->inp_table; so->so_pcb = NULL; /* * As long as the NET_LOCK() is the default lock for Internet * sockets, do not release it to not introduce new sleeping * points. */ sofree(so, 1); if (inp->inp_route.ro_rt) { rtfree(inp->inp_route.ro_rt); inp->inp_route.ro_rt = NULL; } #ifdef INET6 if (ISSET(inp->inp_flags, INP_IPV6)) { ip6_freepcbopts(inp->inp_outputopts6); ip6_freemoptions(inp->inp_moptions6); } else #endif { m_freem(inp->inp_options); ip_freemoptions(inp->inp_moptions); } #if NPF > 0 pf_remove_divert_state(inp); pf_inp_unlink(inp); #endif mtx_enter(&table->inpt_mtx); LIST_REMOVE(inp, inp_lhash); LIST_REMOVE(inp, inp_hash); TAILQ_REMOVE(&table->inpt_queue, inp, inp_queue); table->inpt_count--; mtx_leave(&table->inpt_mtx); in_pcbunref(inp); } struct inpcb * in_pcbref(struct inpcb *inp) { if (inp == NULL) return NULL; refcnt_take(&inp->inp_refcnt); return inp; } void in_pcbunref(struct inpcb *inp) { if (inp == NULL) return; if (refcnt_rele(&inp->inp_refcnt) == 0) return; KASSERT((LIST_NEXT(inp, inp_hash) == NULL) || (LIST_NEXT(inp, inp_hash) == _Q_INVALID)); KASSERT((LIST_NEXT(inp, inp_lhash) == NULL) || (LIST_NEXT(inp, inp_lhash) == _Q_INVALID)); KASSERT((TAILQ_NEXT(inp, inp_queue) == NULL) || (TAILQ_NEXT(inp, inp_queue) == _Q_INVALID)); pool_put(&inpcb_pool, inp); } void in_setsockaddr(struct inpcb *inp, struct mbuf *nam) { struct sockaddr_in *sin; #ifdef INET6 if (ISSET(inp->inp_flags, INP_IPV6)) { in6_setsockaddr(inp, nam); return; } #endif nam->m_len = sizeof(*sin); sin = mtod(nam, struct sockaddr_in *); memset(sin, 0, sizeof(*sin)); sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); sin->sin_port = inp->inp_lport; sin->sin_addr = inp->inp_laddr; } void in_setpeeraddr(struct inpcb *inp, struct mbuf *nam) { struct sockaddr_in *sin; #ifdef INET6 if (ISSET(inp->inp_flags, INP_IPV6)) { in6_setpeeraddr(inp, nam); return; } #endif nam->m_len = sizeof(*sin); sin = mtod(nam, struct sockaddr_in *); memset(sin, 0, sizeof(*sin)); sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); sin->sin_port = inp->inp_fport; sin->sin_addr = inp->inp_faddr; } int in_sockaddr(struct socket *so, struct mbuf *nam) { struct inpcb *inp; inp = sotoinpcb(so); in_setsockaddr(inp, nam); return (0); } int in_peeraddr(struct socket *so, struct mbuf *nam) { struct inpcb *inp; inp = sotoinpcb(so); in_setpeeraddr(inp, nam); return (0); } /* * Pass some notification to all connections of a protocol * associated with address dst. The "usual action" will be * taken, depending on the ctlinput cmd. The caller must filter any * cmds that are uninteresting (e.g., no error in the map). * Call the protocol specific routine (if any) to report * any errors for each matching socket. */ void in_pcbnotifyall(struct inpcbtable *table, const struct sockaddr_in *dst, u_int rtable, int errno, void (*notify)(struct inpcb *, int)) { SIMPLEQ_HEAD(, inpcb) inpcblist; struct inpcb *inp; u_int rdomain; if (dst->sin_addr.s_addr == INADDR_ANY) return; if (notify == NULL) return; /* * Use a temporary notify list protected by rwlock to run over * selected PCB. This is necessary as the list of all PCB is * protected by a mutex. Notify may call ip_output() eventually * which may sleep as pf lock is a rwlock. Also the SRP * implementation of the routing table might sleep. * The same inp_notify list entry and inpt_notify rwlock are * used for UDP multicast and raw IP delivery. */ SIMPLEQ_INIT(&inpcblist); rdomain = rtable_l2(rtable); rw_enter_write(&table->inpt_notify); mtx_enter(&table->inpt_mtx); TAILQ_FOREACH(inp, &table->inpt_queue, inp_queue) { KASSERT(!ISSET(inp->inp_flags, INP_IPV6)); if (inp->inp_faddr.s_addr != dst->sin_addr.s_addr || rtable_l2(inp->inp_rtableid) != rdomain) { continue; } in_pcbref(inp); SIMPLEQ_INSERT_TAIL(&inpcblist, inp, inp_notify); } mtx_leave(&table->inpt_mtx); while ((inp = SIMPLEQ_FIRST(&inpcblist)) != NULL) { SIMPLEQ_REMOVE_HEAD(&inpcblist, inp_notify); (*notify)(inp, errno); in_pcbunref(inp); } rw_exit_write(&table->inpt_notify); } /* * Check for alternatives when higher level complains * about service problems. For now, invalidate cached * routing information. If the route was created dynamically * (by a redirect), time to try a default gateway again. */ void in_losing(struct inpcb *inp) { struct rtentry *rt = inp->inp_route.ro_rt; if (rt) { inp->inp_route.ro_rt = NULL; if (rt->rt_flags & RTF_DYNAMIC) { struct ifnet *ifp; ifp = if_get(rt->rt_ifidx); /* * If the interface is gone, all its attached * route entries have been removed from the table, * so we're dealing with a stale cache and have * nothing to do. */ if (ifp != NULL) rtdeletemsg(rt, ifp, inp->inp_rtableid); if_put(ifp); } /* * A new route can be allocated * the next time output is attempted. * rtfree() needs to be called in anycase because the inp * is still holding a reference to rt. */ rtfree(rt); } } /* * After a routing change, flush old routing * and allocate a (hopefully) better one. */ void in_rtchange(struct inpcb *inp, int errno) { if (inp->inp_route.ro_rt) { rtfree(inp->inp_route.ro_rt); inp->inp_route.ro_rt = NULL; /* * A new route can be allocated the next time * output is attempted. */ } } struct inpcb * in_pcblookup_local_lock(struct inpcbtable *table, const void *laddrp, u_int lport_arg, int flags, u_int rtable, int lock) { struct inpcb *inp, *match = NULL; int matchwild = 3, wildcard; u_int16_t lport = lport_arg; const struct in_addr laddr = *(const struct in_addr *)laddrp; #ifdef INET6 const struct in6_addr *laddr6 = (const struct in6_addr *)laddrp; #endif struct inpcbhead *head; uint64_t lhash; u_int rdomain; rdomain = rtable_l2(rtable); lhash = in_pcblhash(table, rdomain, lport); if (lock == IN_PCBLOCK_GRAB) { mtx_enter(&table->inpt_mtx); } else { KASSERT(lock == IN_PCBLOCK_HOLD); MUTEX_ASSERT_LOCKED(&table->inpt_mtx); } head = &table->inpt_lhashtbl[lhash & table->inpt_lmask]; LIST_FOREACH(inp, head, inp_lhash) { if (rtable_l2(inp->inp_rtableid) != rdomain) continue; if (inp->inp_lport != lport) continue; wildcard = 0; #ifdef INET6 if (ISSET(flags, INPLOOKUP_IPV6)) { KASSERT(ISSET(inp->inp_flags, INP_IPV6)); if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) wildcard++; if (!IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, laddr6)) { if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6) || IN6_IS_ADDR_UNSPECIFIED(laddr6)) wildcard++; else continue; } } else #endif /* INET6 */ { KASSERT(!ISSET(inp->inp_flags, INP_IPV6)); if (inp->inp_faddr.s_addr != INADDR_ANY) wildcard++; if (inp->inp_laddr.s_addr != laddr.s_addr) { if (inp->inp_laddr.s_addr == INADDR_ANY || laddr.s_addr == INADDR_ANY) wildcard++; else continue; } } if ((!wildcard || (flags & INPLOOKUP_WILDCARD)) && wildcard < matchwild) { match = inp; if ((matchwild = wildcard) == 0) break; } } if (lock == IN_PCBLOCK_GRAB) { in_pcbref(match); mtx_leave(&table->inpt_mtx); } return (match); } struct rtentry * in_pcbrtentry(struct inpcb *inp) { #ifdef INET6 if (ISSET(inp->inp_flags, INP_IPV6)) return in6_pcbrtentry(inp); #endif if (inp->inp_faddr.s_addr == INADDR_ANY) return (NULL); return (route_mpath(&inp->inp_route, &inp->inp_faddr, &inp->inp_laddr, inp->inp_rtableid)); } /* * Return an IPv4 address, which is the most appropriate for a given * destination. * If necessary, this function lookups the routing table and returns * an entry to the caller for later use. */ int in_pcbselsrc(struct in_addr *insrc, struct sockaddr_in *sin, struct inpcb *inp) { struct ip_moptions *mopts = inp->inp_moptions; struct rtentry *rt; const struct in_addr *laddr = &inp->inp_laddr; u_int rtableid = inp->inp_rtableid; struct sockaddr *ip4_source = NULL; struct in_ifaddr *ia = NULL; /* * If the socket(if any) is already bound, use that bound address * unless it is INADDR_ANY or INADDR_BROADCAST. */ if (laddr->s_addr != INADDR_ANY && laddr->s_addr != INADDR_BROADCAST) { *insrc = *laddr; return (0); } /* * If the destination address is multicast or limited * broadcast (255.255.255.255) and an outgoing interface has * been set as a multicast option, use the address of that * interface as our source address. */ if ((IN_MULTICAST(sin->sin_addr.s_addr) || sin->sin_addr.s_addr == INADDR_BROADCAST) && mopts != NULL) { struct ifnet *ifp; ifp = if_get(mopts->imo_ifidx); if (ifp != NULL) { if (ifp->if_rdomain == rtable_l2(rtableid)) IFP_TO_IA(ifp, ia); if (ia == NULL) { if_put(ifp); return (EADDRNOTAVAIL); } *insrc = ia->ia_addr.sin_addr; if_put(ifp); return (0); } } /* * If route is known or can be allocated now, * our src addr is taken from the i/f, else punt. */ rt = route_mpath(&inp->inp_route, &sin->sin_addr, NULL, rtableid); /* * If we found a route, use the address * corresponding to the outgoing interface. */ if (rt != NULL) ia = ifatoia(rt->rt_ifa); /* * Use preferred source address if : * - destination is not onlink * - preferred source address is set * - output interface is UP */ if (rt != NULL && !(rt->rt_flags & RTF_LLINFO) && !(rt->rt_flags & RTF_HOST)) { ip4_source = rtable_getsource(rtableid, AF_INET); if (ip4_source != NULL) { struct ifaddr *ifa; if ((ifa = ifa_ifwithaddr(ip4_source, rtableid)) != NULL && ISSET(ifa->ifa_ifp->if_flags, IFF_UP)) { *insrc = satosin(ip4_source)->sin_addr; return (0); } } } if (ia == NULL) return (EADDRNOTAVAIL); *insrc = ia->ia_addr.sin_addr; return (0); } void in_pcbrehash(struct inpcb *inp) { LIST_REMOVE(inp, inp_lhash); LIST_REMOVE(inp, inp_hash); in_pcbhash_insert(inp); } void in_pcbhash_insert(struct inpcb *inp) { struct inpcbtable *table = inp->inp_table; struct inpcbhead *head; uint64_t hash, lhash; MUTEX_ASSERT_LOCKED(&table->inpt_mtx); lhash = in_pcblhash(table, inp->inp_rtableid, inp->inp_lport); head = &table->inpt_lhashtbl[lhash & table->inpt_lmask]; LIST_INSERT_HEAD(head, inp, inp_lhash); #ifdef INET6 if (ISSET(inp->inp_flags, INP_IPV6)) hash = in6_pcbhash(table, rtable_l2(inp->inp_rtableid), &inp->inp_faddr6, inp->inp_fport, &inp->inp_laddr6, inp->inp_lport); else #endif hash = in_pcbhash(table, rtable_l2(inp->inp_rtableid), &inp->inp_faddr, inp->inp_fport, &inp->inp_laddr, inp->inp_lport); head = &table->inpt_hashtbl[hash & table->inpt_mask]; LIST_INSERT_HEAD(head, inp, inp_hash); } struct inpcb * in_pcbhash_lookup(struct inpcbtable *table, uint64_t hash, u_int rdomain, const struct in_addr *faddr, u_short fport, const struct in_addr *laddr, u_short lport) { struct inpcbhead *head; struct inpcb *inp; MUTEX_ASSERT_LOCKED(&table->inpt_mtx); head = &table->inpt_hashtbl[hash & table->inpt_mask]; LIST_FOREACH(inp, head, inp_hash) { KASSERT(!ISSET(inp->inp_flags, INP_IPV6)); if (inp->inp_fport == fport && inp->inp_lport == lport && inp->inp_faddr.s_addr == faddr->s_addr && inp->inp_laddr.s_addr == laddr->s_addr && rtable_l2(inp->inp_rtableid) == rdomain) { break; } } if (inp != NULL) { /* * Move this PCB to the head of hash chain so that * repeated accesses are quicker. This is analogous to * the historic single-entry PCB cache. */ if (inp != LIST_FIRST(head)) { LIST_REMOVE(inp, inp_hash); LIST_INSERT_HEAD(head, inp, inp_hash); } } return (inp); } int in_pcbresize(struct inpcbtable *table, int hashsize) { u_long nmask, nlmask; int osize; void *nhashtbl, *nlhashtbl, *ohashtbl, *olhashtbl; struct inpcb *inp; MUTEX_ASSERT_LOCKED(&table->inpt_mtx); ohashtbl = table->inpt_hashtbl; olhashtbl = table->inpt_lhashtbl; osize = table->inpt_size; nhashtbl = hashinit(hashsize, M_PCB, M_NOWAIT, &nmask); if (nhashtbl == NULL) return ENOBUFS; nlhashtbl = hashinit(hashsize, M_PCB, M_NOWAIT, &nlmask); if (nlhashtbl == NULL) { hashfree(nhashtbl, hashsize, M_PCB); return ENOBUFS; } table->inpt_hashtbl = nhashtbl; table->inpt_lhashtbl = nlhashtbl; table->inpt_mask = nmask; table->inpt_lmask = nlmask; table->inpt_size = hashsize; TAILQ_FOREACH(inp, &table->inpt_queue, inp_queue) { LIST_REMOVE(inp, inp_lhash); LIST_REMOVE(inp, inp_hash); in_pcbhash_insert(inp); } hashfree(ohashtbl, osize, M_PCB); hashfree(olhashtbl, osize, M_PCB); return (0); } #ifdef DIAGNOSTIC int in_pcbnotifymiss = 0; #endif /* * The in(6)_pcblookup functions are used to locate connected sockets * quickly: * faddr.fport <-> laddr.lport * No wildcard matching is done so that listening sockets are not found. * If the functions return NULL in(6)_pcblookup_listen can be used to * find a listening/bound socket that may accept the connection. * After those two lookups no other are necessary. */ struct inpcb * in_pcblookup_lock(struct inpcbtable *table, struct in_addr faddr, u_int fport, struct in_addr laddr, u_int lport, u_int rtable, int lock) { struct inpcb *inp; uint64_t hash; u_int rdomain; rdomain = rtable_l2(rtable); hash = in_pcbhash(table, rdomain, &faddr, fport, &laddr, lport); if (lock == IN_PCBLOCK_GRAB) { mtx_enter(&table->inpt_mtx); } else { KASSERT(lock == IN_PCBLOCK_HOLD); MUTEX_ASSERT_LOCKED(&table->inpt_mtx); } inp = in_pcbhash_lookup(table, hash, rdomain, &faddr, fport, &laddr, lport); if (lock == IN_PCBLOCK_GRAB) { in_pcbref(inp); mtx_leave(&table->inpt_mtx); } #ifdef DIAGNOSTIC if (inp == NULL && in_pcbnotifymiss) { printf("%s: faddr=%08x fport=%d laddr=%08x lport=%d rdom=%u\n", __func__, ntohl(faddr.s_addr), ntohs(fport), ntohl(laddr.s_addr), ntohs(lport), rdomain); } #endif return (inp); } struct inpcb * in_pcblookup(struct inpcbtable *table, struct in_addr faddr, u_int fport, struct in_addr laddr, u_int lport, u_int rtable) { return in_pcblookup_lock(table, faddr, fport, laddr, lport, rtable, IN_PCBLOCK_GRAB); } /* * The in(6)_pcblookup_listen functions are used to locate listening * sockets quickly. This are sockets with unspecified foreign address * and port: * *.* <-> laddr.lport * *.* <-> *.lport */ struct inpcb * in_pcblookup_listen(struct inpcbtable *table, struct in_addr laddr, u_int lport_arg, struct mbuf *m, u_int rtable) { const struct in_addr *key1, *key2; struct inpcb *inp; uint64_t hash; u_int16_t lport = lport_arg; u_int rdomain; key1 = &laddr; key2 = &zeroin_addr; #if NPF > 0 if (m && m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { struct pf_divert *divert; divert = pf_find_divert(m); KASSERT(divert != NULL); switch (divert->type) { case PF_DIVERT_TO: key1 = key2 = &divert->addr.v4; lport = divert->port; break; case PF_DIVERT_REPLY: return (NULL); default: panic("%s: unknown divert type %d, mbuf %p, divert %p", __func__, divert->type, m, divert); } } else if (m && m->m_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST) { /* * Redirected connections should not be treated the same * as connections directed to 127.0.0.0/8 since localhost * can only be accessed from the host itself. * For example portmap(8) grants more permissions for * connections to the socket bound to 127.0.0.1 than * to the * socket. */ key1 = &zeroin_addr; key2 = &laddr; } #endif rdomain = rtable_l2(rtable); hash = in_pcbhash(table, rdomain, &zeroin_addr, 0, key1, lport); mtx_enter(&table->inpt_mtx); inp = in_pcbhash_lookup(table, hash, rdomain, &zeroin_addr, 0, key1, lport); if (inp == NULL && key1->s_addr != key2->s_addr) { hash = in_pcbhash(table, rdomain, &zeroin_addr, 0, key2, lport); inp = in_pcbhash_lookup(table, hash, rdomain, &zeroin_addr, 0, key2, lport); } in_pcbref(inp); mtx_leave(&table->inpt_mtx); #ifdef DIAGNOSTIC if (inp == NULL && in_pcbnotifymiss) { printf("%s: laddr=%08x lport=%d rdom=%u\n", __func__, ntohl(laddr.s_addr), ntohs(lport), rdomain); } #endif return (inp); } int in_pcbset_rtableid(struct inpcb *inp, u_int rtableid) { struct inpcbtable *table = inp->inp_table; /* table must exist */ if (!rtable_exists(rtableid)) return (EINVAL); mtx_enter(&table->inpt_mtx); if (inp->inp_lport) { mtx_leave(&table->inpt_mtx); return (EBUSY); } inp->inp_rtableid = rtableid; in_pcbrehash(inp); mtx_leave(&table->inpt_mtx); return (0); } void in_pcbset_laddr(struct inpcb *inp, const struct sockaddr *sa, u_int rtableid) { struct inpcbtable *table = inp->inp_table; mtx_enter(&table->inpt_mtx); inp->inp_rtableid = rtableid; #ifdef INET6 if (ISSET(inp->inp_flags, INP_IPV6)) { const struct sockaddr_in6 *sin6; KASSERT(sa->sa_family == AF_INET6); sin6 = satosin6_const(sa); inp->inp_lport = sin6->sin6_port; inp->inp_laddr6 = sin6->sin6_addr; } else #endif { const struct sockaddr_in *sin; KASSERT(sa->sa_family == AF_INET); sin = satosin_const(sa); inp->inp_lport = sin->sin_port; inp->inp_laddr = sin->sin_addr; } in_pcbrehash(inp); mtx_leave(&table->inpt_mtx); } void in_pcbunset_faddr(struct inpcb *inp) { struct inpcbtable *table = inp->inp_table; mtx_enter(&table->inpt_mtx); #ifdef INET6 if (ISSET(inp->inp_flags, INP_IPV6)) inp->inp_faddr6 = in6addr_any; else #endif inp->inp_faddr.s_addr = INADDR_ANY; inp->inp_fport = 0; in_pcbrehash(inp); mtx_leave(&table->inpt_mtx); } void in_pcbunset_laddr(struct inpcb *inp) { struct inpcbtable *table = inp->inp_table; mtx_enter(&table->inpt_mtx); #ifdef INET6 if (ISSET(inp->inp_flags, INP_IPV6)) { inp->inp_faddr6 = in6addr_any; inp->inp_laddr6 = in6addr_any; } else #endif { inp->inp_faddr.s_addr = INADDR_ANY; inp->inp_laddr.s_addr = INADDR_ANY; } inp->inp_fport = 0; in_pcbrehash(inp); mtx_leave(&table->inpt_mtx); }
6503 7 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 /* $OpenBSD: proc.h,v 1.361 2024/05/20 10:32:20 claudio Exp $ */ /* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */ /*- * Copyright (c) 1986, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)proc.h 8.8 (Berkeley) 1/21/94 */ #ifndef _SYS_PROC_H_ #define _SYS_PROC_H_ #include <machine/proc.h> /* Machine-dependent proc substruct. */ #include <sys/selinfo.h> /* For struct selinfo */ #include <sys/syslimits.h> /* For LOGIN_NAME_MAX */ #include <sys/queue.h> #include <sys/timeout.h> /* For struct timeout */ #include <sys/event.h> /* For struct klist */ #include <sys/mutex.h> /* For struct mutex */ #include <sys/resource.h> /* For struct rusage */ #include <sys/rwlock.h> /* For struct rwlock */ #include <sys/sigio.h> /* For struct sigio */ #ifdef _KERNEL #include <sys/atomic.h> #define __need_process #endif /* * One structure allocated per session. */ struct process; struct session { int s_count; /* Ref cnt; pgrps in session. */ struct process *s_leader; /* Session leader. */ struct vnode *s_ttyvp; /* Vnode of controlling terminal. */ struct tty *s_ttyp; /* Controlling terminal. */ char s_login[LOGIN_NAME_MAX]; /* Setlogin() name. */ pid_t s_verauthppid; uid_t s_verauthuid; struct timeout s_verauthto; }; void zapverauth(/* struct session */ void *); /* * One structure allocated per process group. */ struct pgrp { LIST_ENTRY(pgrp) pg_hash; /* Hash chain. */ LIST_HEAD(, process) pg_members;/* Pointer to pgrp members. */ struct session *pg_session; /* Pointer to session. */ struct sigiolst pg_sigiolst; /* List of sigio structures. */ pid_t pg_id; /* Pgrp id. */ int pg_jobc; /* # procs qualifying pgrp for job control */ }; /* * time usage: accumulated times in ticks * Once a second, each thread's immediate counts (p_[usi]ticks) are * accumulated into these. */ struct tusage { struct timespec tu_runtime; /* Realtime. */ uint64_t tu_uticks; /* Statclock hits in user mode. */ uint64_t tu_sticks; /* Statclock hits in system mode. */ uint64_t tu_iticks; /* Statclock hits processing intr. */ }; /* * Description of a process. * * These structures contain the information needed to manage a thread of * control, known in UN*X as a process; it has references to substructures * containing descriptions of things that the process uses, but may share * with related processes. * * struct process is the higher level process containing information * shared by all threads in a process, while struct proc contains the * run-time information needed by threads. */ #ifdef __need_process struct futex; LIST_HEAD(futex_list, futex); struct proc; struct tslpentry; TAILQ_HEAD(tslpqueue, tslpentry); struct unveil; struct pinsyscall { vaddr_t pn_start; vaddr_t pn_end; u_int *pn_pins; /* array of offsets indexed by syscall# */ int pn_npins; /* number of entries in table */ }; /* * Locks used to protect struct members in this file: * I immutable after creation * a atomic operations * K kernel lock * m this process' `ps_mtx' * p this process' `ps_lock' * R rlimit_lock * S scheduler lock * T itimer_mtx */ struct process { /* * ps_mainproc is the original thread in the process. * It's only still special for the handling of * some signal and ptrace behaviors that need to be fixed. */ struct proc *ps_mainproc; struct ucred *ps_ucred; /* Process owner's identity. */ LIST_ENTRY(process) ps_list; /* List of all processes. */ TAILQ_HEAD(,proc) ps_threads; /* [K|m] Threads in this process. */ LIST_ENTRY(process) ps_pglist; /* List of processes in pgrp. */ struct process *ps_pptr; /* Pointer to parent process. */ LIST_ENTRY(process) ps_sibling; /* List of sibling processes. */ LIST_HEAD(, process) ps_children;/* Pointer to list of children. */ LIST_ENTRY(process) ps_hash; /* Hash chain. */ /* * An orphan is the child that has been re-parented to the * debugger as a result of attaching to it. Need to keep * track of them for parent to be able to collect the exit * status of what used to be children. */ LIST_ENTRY(process) ps_orphan; /* List of orphan processes. */ LIST_HEAD(, process) ps_orphans;/* Pointer to list of orphans. */ struct sigiolst ps_sigiolst; /* List of sigio structures. */ struct sigacts *ps_sigacts; /* [I] Signal actions, state */ struct vnode *ps_textvp; /* Vnode of executable. */ struct filedesc *ps_fd; /* Ptr to open files structure */ struct vmspace *ps_vmspace; /* Address space */ pid_t ps_pid; /* Process identifier. */ struct futex_list ps_ftlist; /* futexes attached to this process */ struct tslpqueue ps_tslpqueue; /* [p] queue of threads in thrsleep */ struct rwlock ps_lock; /* per-process rwlock */ struct mutex ps_mtx; /* per-process mutex */ /* The following fields are all zeroed upon creation in process_new. */ #define ps_startzero ps_klist struct klist ps_klist; /* knotes attached to this process */ u_int ps_flags; /* [a] PS_* flags. */ int ps_siglist; /* Signals pending for the process. */ struct proc *ps_single; /* [m] Thread for single-threading. */ u_int ps_singlecnt; /* [m] Number of threads to suspend. */ u_int ps_exitcnt; /* [m] Number of threads in exit1. */ int ps_traceflag; /* Kernel trace points. */ struct vnode *ps_tracevp; /* Trace to vnode. */ struct ucred *ps_tracecred; /* Creds for writing trace */ u_int ps_xexit; /* Exit status for wait */ int ps_xsig; /* Stopping or killing signal */ pid_t ps_ppid; /* [a] Cached parent pid */ pid_t ps_oppid; /* [a] Save parent pid during ptrace. */ int ps_ptmask; /* Ptrace event mask */ struct ptrace_state *ps_ptstat;/* Ptrace state */ struct rusage *ps_ru; /* sum of stats for dead threads. */ struct tusage ps_tu; /* accumulated times. */ struct rusage ps_cru; /* sum of stats for reaped children */ struct itimerspec ps_timer[3]; /* [m] ITIMER_REAL timer */ /* [T] ITIMER_{VIRTUAL,PROF} timers */ struct timeout ps_rucheck_to; /* [] resource limit check timer */ time_t ps_nextxcpu; /* when to send next SIGXCPU, */ /* in seconds of process runtime */ u_int64_t ps_wxcounter; struct unveil *ps_uvpaths; /* unveil vnodes and names */ ssize_t ps_uvvcount; /* count of unveil vnodes held */ size_t ps_uvncount; /* count of unveil names allocated */ int ps_uvdone; /* no more unveil is permitted */ /* End area that is zeroed on creation. */ #define ps_endzero ps_startcopy /* The following fields are all copied upon creation in process_new. */ #define ps_startcopy ps_limit struct plimit *ps_limit; /* [m,R] Process limits. */ struct pgrp *ps_pgrp; /* Pointer to process group. */ char ps_comm[_MAXCOMLEN]; /* command name, incl NUL */ vaddr_t ps_strings; /* User pointers to argv/env */ vaddr_t ps_auxinfo; /* User pointer to auxinfo */ vaddr_t ps_timekeep; /* User pointer to timekeep */ vaddr_t ps_sigcode; /* [I] User pointer to signal code */ vaddr_t ps_sigcoderet; /* [I] User ptr to sigreturn retPC */ u_long ps_sigcookie; /* [I] */ u_int ps_rtableid; /* [a] Process routing table/domain. */ char ps_nice; /* Process "nice" value. */ struct uprof { /* profile arguments */ caddr_t pr_base; /* buffer base */ size_t pr_size; /* buffer size */ u_long pr_off; /* pc offset */ u_int pr_scale; /* pc scaling */ } ps_prof; u_int32_t ps_acflag; /* Accounting flags. */ uint64_t ps_pledge; /* [m] pledge promises */ uint64_t ps_execpledge; /* [m] execpledge promises */ int64_t ps_kbind_cookie; /* [m] */ u_long ps_kbind_addr; /* [m] */ /* an address that can't be in userspace or kernelspace */ #define BOGO_PC (u_long)-1 struct pinsyscall ps_pin; /* static or ld.so */ struct pinsyscall ps_libcpin; /* libc.so, from pinsyscalls(2) */ /* End area that is copied on creation. */ #define ps_endcopy ps_threadcnt u_int ps_threadcnt; /* [m] Number of threads. */ struct timespec ps_start; /* starting uptime. */ struct timeout ps_realit_to; /* [m] ITIMER_REAL timeout */ }; #define ps_session ps_pgrp->pg_session #define ps_pgid ps_pgrp->pg_id #endif /* __need_process */ /* * These flags are kept in ps_flags. */ #define PS_CONTROLT 0x00000001 /* Has a controlling terminal. */ #define PS_EXEC 0x00000002 /* Process called exec. */ #define PS_INEXEC 0x00000004 /* Process is doing an exec right now */ #define PS_EXITING 0x00000008 /* Process is exiting. */ #define PS_SUGID 0x00000010 /* Had set id privs since last exec. */ #define PS_SUGIDEXEC 0x00000020 /* last execve() was set[ug]id */ #define PS_PPWAIT 0x00000040 /* Parent waits for exec/exit. */ #define PS_ISPWAIT 0x00000080 /* Is parent of PPWAIT child. */ #define PS_PROFIL 0x00000100 /* Has started profiling. */ #define PS_TRACED 0x00000200 /* Being ptraced. */ #define PS_WAITED 0x00000400 /* Stopped proc was waited for. */ #define PS_COREDUMP 0x00000800 /* Busy coredumping */ #define PS_SINGLEEXIT 0x00001000 /* Other threads must die. */ #define PS_SINGLEUNWIND 0x00002000 /* Other threads must unwind. */ #define PS_NOZOMBIE 0x00004000 /* No signal or zombie at exit. */ #define PS_STOPPED 0x00008000 /* Just stopped, need sig to parent. */ #define PS_SYSTEM 0x00010000 /* No sigs, stats or swapping. */ #define PS_EMBRYO 0x00020000 /* New process, not yet fledged */ #define PS_ZOMBIE 0x00040000 /* Dead and ready to be waited for */ #define PS_NOBROADCASTKILL 0x00080000 /* Process excluded from kill -1. */ #define PS_PLEDGE 0x00100000 /* Has called pledge(2) */ #define PS_WXNEEDED 0x00200000 /* Process allowed to violate W^X */ #define PS_EXECPLEDGE 0x00400000 /* Has exec pledges */ #define PS_ORPHAN 0x00800000 /* Process is on an orphan list */ #define PS_CHROOT 0x01000000 /* Process is chrooted */ #define PS_NOBTCFI 0x02000000 /* No Branch Target CFI */ #define PS_ITIMER 0x04000000 /* Virtual interval timers running */ #define PS_PIN 0x08000000 /* ld.so or static syscall pin */ #define PS_LIBCPIN 0x10000000 /* libc.so syscall pin */ #define PS_BITS \ ("\20" "\01CONTROLT" "\02EXEC" "\03INEXEC" "\04EXITING" "\05SUGID" \ "\06SUGIDEXEC" "\07PPWAIT" "\010ISPWAIT" "\011PROFIL" "\012TRACED" \ "\013WAITED" "\014COREDUMP" "\015SINGLEEXIT" "\016SINGLEUNWIND" \ "\017NOZOMBIE" "\020STOPPED" "\021SYSTEM" "\022EMBRYO" "\023ZOMBIE" \ "\024NOBROADCASTKILL" "\025PLEDGE" "\026WXNEEDED" "\027EXECPLEDGE" \ "\030ORPHAN" "\031CHROOT" "\032NOBTCFI" "\033ITIMER") struct kcov_dev; struct lock_list_entry; struct kqueue; struct p_inentry { u_long ie_serial; vaddr_t ie_start; vaddr_t ie_end; }; /* * Locks used to protect struct members in this file: * I immutable after creation * S scheduler lock * U uidinfolk * l read only reference, see lim_read_enter() * o owned (modified only) by this thread * m this proc's' `p->p_p->ps_mtx' */ struct proc { TAILQ_ENTRY(proc) p_runq; /* [S] current run/sleep queue */ LIST_ENTRY(proc) p_list; /* List of all threads. */ struct process *p_p; /* [I] The process of this thread. */ TAILQ_ENTRY(proc) p_thr_link; /* [K|m] Threads in a process linkage. */ TAILQ_ENTRY(proc) p_fut_link; /* Threads in a futex linkage. */ struct futex *p_futex; /* Current sleeping futex. */ /* substructures: */ struct filedesc *p_fd; /* copy of p_p->ps_fd */ struct vmspace *p_vmspace; /* [I] copy of p_p->ps_vmspace */ struct p_inentry p_spinentry; /* [o] cache for SP check */ int p_flag; /* P_* flags. */ u_char p_spare; /* unused */ char p_stat; /* [S] S* process status. */ u_char p_runpri; /* [S] Runqueue priority */ u_char p_descfd; /* if not 255, fdesc permits this fd */ pid_t p_tid; /* Thread identifier. */ LIST_ENTRY(proc) p_hash; /* Hash chain. */ /* The following fields are all zeroed upon creation in fork. */ #define p_startzero p_dupfd int p_dupfd; /* Sideways return value from filedescopen. XXX */ /* scheduling */ int p_cpticks; /* Ticks of cpu time. */ const volatile void *p_wchan; /* [S] Sleep address. */ struct timeout p_sleep_to;/* timeout for tsleep() */ const char *p_wmesg; /* [S] Reason for sleep. */ fixpt_t p_pctcpu; /* [S] %cpu for this thread */ u_int p_slptime; /* [S] Time since last blocked. */ u_int p_uticks; /* Statclock hits in user mode. */ u_int p_sticks; /* Statclock hits in system mode. */ u_int p_iticks; /* Statclock hits processing intr. */ struct cpu_info * volatile p_cpu; /* [S] CPU we're running on. */ struct rusage p_ru; /* Statistics */ struct tusage p_tu; /* accumulated times. */ struct plimit *p_limit; /* [l] read ref. of p_p->ps_limit */ struct kcov_dev *p_kd; /* kcov device handle */ struct lock_list_entry *p_sleeplocks; /* WITNESS lock tracking */ struct kqueue *p_kq; /* [o] select/poll queue of evts */ unsigned long p_kq_serial; /* [o] to check against enqueued evts */ int p_siglist; /* [a] Signals arrived & not delivered*/ /* End area that is zeroed on creation. */ #define p_endzero p_startcopy /* The following fields are all copied upon creation in fork. */ #define p_startcopy p_sigmask sigset_t p_sigmask; /* [o] Current signal mask */ char p_name[_MAXCOMLEN]; /* thread name, incl NUL */ u_char p_slppri; /* [S] Sleeping priority */ u_char p_usrpri; /* [S] Priority based on p_estcpu & ps_nice */ u_int p_estcpu; /* [S] Time averaged val of p_cpticks */ int p_pledge_syscall; /* Cache of current syscall */ struct ucred *p_ucred; /* [o] cached credentials */ struct sigaltstack p_sigstk; /* sp & on stack state variable */ u_long p_prof_addr; /* tmp storage for profiling addr until AST */ u_long p_prof_ticks; /* tmp storage for profiling ticks until AST */ /* End area that is copied on creation. */ #define p_endcopy p_addr struct user *p_addr; /* Kernel virtual addr of u-area */ struct mdproc p_md; /* Any machine-dependent fields. */ sigset_t p_oldmask; /* [o] Saved mask from before sigpause */ int p_sisig; /* For core dump/debugger XXX */ union sigval p_sigval; /* For core dump/debugger XXX */ long p_sitrapno; /* For core dump/debugger XXX */ int p_sicode; /* For core dump/debugger XXX */ }; /* Status values. */ #define SIDL 1 /* Thread being created by fork. */ #define SRUN 2 /* Currently runnable. */ #define SSLEEP 3 /* Sleeping on an address. */ #define SSTOP 4 /* Debugging or suspension. */ #define SZOMB 5 /* unused */ #define SDEAD 6 /* Thread is almost gone */ #define SONPROC 7 /* Thread is currently on a CPU. */ #define P_ZOMBIE(p) ((p)->p_stat == SDEAD) #define P_HASSIBLING(p) ((p)->p_p->ps_threadcnt > 1) /* * These flags are per-thread and kept in p_flag */ #define P_INKTR 0x00000001 /* In a ktrace op, don't recurse */ #define P_PROFPEND 0x00000002 /* SIGPROF needs to be posted */ #define P_ALRMPEND 0x00000004 /* SIGVTALRM needs to be posted */ #define P_SIGSUSPEND 0x00000008 /* Need to restore before-suspend mask*/ #define P_CANTSLEEP 0x00000010 /* insomniac thread */ #define P_WSLEEP 0x00000020 /* Working on going to sleep. */ #define P_SINTR 0x00000080 /* Sleep is interruptible. */ #define P_SYSTEM 0x00000200 /* No sigs, stats or swapping. */ #define P_TIMEOUT 0x00000400 /* Timing out during sleep. */ #define P_WEXIT 0x00002000 /* Working on exiting. */ #define P_OWEUPC 0x00008000 /* Owe proc an addupc() at next ast. */ #define P_SUSPSINGLE 0x00080000 /* Need to stop for single threading. */ #define P_CONTINUED 0x00800000 /* Proc has continued from a stopped state. */ #define P_THREAD 0x04000000 /* Only a thread, not a real process */ #define P_SUSPSIG 0x08000000 /* Stopped from signal. */ #define P_CPUPEG 0x40000000 /* Do not move to another cpu. */ #define P_BITS \ ("\20" "\01INKTR" "\02PROFPEND" "\03ALRMPEND" "\04SIGSUSPEND" \ "\05CANTSLEEP" "\06WSLEEP" "\010SINTR" "\012SYSTEM" "\013TIMEOUT" \ "\016WEXIT" "\020OWEUPC" "\024SUSPSINGLE" "\027XX" \ "\030CONTINUED" "\033THREAD" "\034SUSPSIG" "\035SOFTDEP" "\037CPUPEG") #define THREAD_PID_OFFSET 100000 #ifdef _KERNEL struct uidinfo { LIST_ENTRY(uidinfo) ui_hash; /* [U] */ uid_t ui_uid; /* [I] */ long ui_proccnt; /* [U] proc structs */ long ui_lockcnt; /* [U] lockf structs */ }; struct uidinfo *uid_find(uid_t); void uid_release(struct uidinfo *); /* * We use process IDs <= PID_MAX; PID_MAX + 1 must also fit in a pid_t, * as it is used to represent "no process group". * We set PID_MAX to 99999 to keep it in 5 columns in ps * When exposed to userspace, thread IDs have THREAD_PID_OFFSET * added to keep them from overlapping the PID range. For them, * we use a * a (0 .. 2^n] range for cheapness, picking 'n' such * that 2^n + THREAD_PID_OFFSET and THREAD_PID_OFFSET have * the same number of columns when printed. */ #define PID_MAX 99999 #define TID_MASK 0x7ffff #define NO_PID (PID_MAX+1) #define SESS_LEADER(pr) ((pr)->ps_session->s_leader == (pr)) #define SESSHOLD(s) ((s)->s_count++) #define SESSRELE(s) do { \ if (--(s)->s_count == 0) { \ timeout_del(&(s)->s_verauthto); \ pool_put(&session_pool, (s)); \ } \ } while (/* CONSTCOND */ 0) /* * Flags to fork1(). */ #define FORK_FORK 0x00000001 #define FORK_VFORK 0x00000002 #define FORK_IDLE 0x00000004 #define FORK_PPWAIT 0x00000008 #define FORK_SHAREFILES 0x00000010 #define FORK_SYSTEM 0x00000020 #define FORK_NOZOMBIE 0x00000040 #define FORK_SHAREVM 0x00000080 #define FORK_PTRACE 0x00000400 #define EXIT_NORMAL 0x00000001 #define EXIT_THREAD 0x00000002 #define EXIT_THREAD_NOCHECK 0x00000003 #define TIDHASH(tid) (&tidhashtbl[(tid) & tidhash]) extern LIST_HEAD(tidhashhead, proc) *tidhashtbl; extern u_long tidhash; #define PIDHASH(pid) (&pidhashtbl[(pid) & pidhash]) extern LIST_HEAD(pidhashhead, process) *pidhashtbl; extern u_long pidhash; #define PGRPHASH(pgid) (&pgrphashtbl[(pgid) & pgrphash]) extern LIST_HEAD(pgrphashhead, pgrp) *pgrphashtbl; extern u_long pgrphash; extern struct proc proc0; /* Process slot for swapper. */ extern struct process process0; /* Process slot for kernel threads. */ extern int nprocesses, maxprocess; /* Cur and max number of processes. */ extern int nthreads, maxthread; /* Cur and max number of threads. */ LIST_HEAD(proclist, proc); LIST_HEAD(processlist, process); extern struct processlist allprocess; /* List of all processes. */ extern struct processlist zombprocess; /* List of zombie processes. */ extern struct proclist allproc; /* List of all threads. */ extern struct process *initprocess; /* Process slot for init. */ extern struct proc *reaperproc; /* Thread slot for reaper. */ extern struct proc *syncerproc; /* filesystem syncer daemon */ extern struct pool process_pool; /* memory pool for processes */ extern struct pool proc_pool; /* memory pool for procs */ extern struct pool rusage_pool; /* memory pool for zombies */ extern struct pool ucred_pool; /* memory pool for ucreds */ extern struct pool session_pool; /* memory pool for sessions */ extern struct pool pgrp_pool; /* memory pool for pgrps */ void freepid(pid_t); struct process *prfind(pid_t); /* Find process by id. */ struct process *zombiefind(pid_t); /* Find zombie process by id. */ struct proc *tfind(pid_t); /* Find thread by id. */ struct pgrp *pgfind(pid_t); /* Find process group by id. */ struct proc *tfind_user(pid_t, struct process *); /* Find thread by userspace id. */ void proc_printit(struct proc *p, const char *modif, int (*pr)(const char *, ...)); int chgproccnt(uid_t uid, int diff); void enternewpgrp(struct process *, struct pgrp *, struct session *); void enterthispgrp(struct process *, struct pgrp *); int inferior(struct process *, struct process *); void leavepgrp(struct process *); void killjobc(struct process *); void preempt(void); void procinit(void); void setpriority(struct proc *, uint32_t, uint8_t); void setrunnable(struct proc *); void endtsleep(void *); int wakeup_proc(struct proc *, int); void unsleep(struct proc *); void reaper(void *); __dead void exit1(struct proc *, int, int, int); void exit2(struct proc *); void cpu_fork(struct proc *_curp, struct proc *_child, void *_stack, void *_tcb, void (*_func)(void *), void *_arg); void cpu_exit(struct proc *); void process_initialize(struct process *, struct proc *); int fork1(struct proc *_curp, int _flags, void (*_func)(void *), void *_arg, register_t *_retval, struct proc **_newprocp); int thread_fork(struct proc *_curp, void *_stack, void *_tcb, pid_t *_tidptr, register_t *_retval); int groupmember(gid_t, struct ucred *); void dorefreshcreds(struct process *, struct proc *); void dosigsuspend(struct proc *, sigset_t); static inline void refreshcreds(struct proc *p) { struct process *pr = p->p_p; /* this is an unlocked access to ps_ucred, but the result is benign */ if (pr->ps_ucred != p->p_ucred) dorefreshcreds(pr, p); } #define SINGLE_SUSPEND 0x01 /* other threads to stop wherever they are */ #define SINGLE_UNWIND 0x02 /* other threads to unwind and stop */ #define SINGLE_EXIT 0x03 /* other threads to unwind and then exit */ #define SINGLE_MASK 0x0f /* extra flags for single_thread_set */ #define SINGLE_DEEP 0x10 /* call is in deep */ #define SINGLE_NOWAIT 0x20 /* do not wait for other threads to stop */ int single_thread_set(struct proc *, int); int single_thread_wait(struct process *, int); void single_thread_clear(struct proc *, int); int single_thread_check(struct proc *, int); void child_return(void *); int proc_cansugid(struct proc *); struct cond { unsigned int c_wait; /* [a] initialized and waiting */ }; #define COND_INITIALIZER() { .c_wait = 1 } void proc_trampoline_mi(void); /* * functions to handle sets of cpus. * * For now we keep the cpus in ints so that we can use the generic * atomic ops. */ #define CPUSET_ASIZE(x) (((x) - 1)/32 + 1) #define CPUSET_SSIZE CPUSET_ASIZE(MAXCPUS) struct cpuset { int cs_set[CPUSET_SSIZE]; }; void cpuset_init_cpu(struct cpu_info *); void cpuset_clear(struct cpuset *); void cpuset_add(struct cpuset *, struct cpu_info *); void cpuset_del(struct cpuset *, struct cpu_info *); int cpuset_isset(struct cpuset *, struct cpu_info *); void cpuset_add_all(struct cpuset *); void cpuset_copy(struct cpuset *, struct cpuset *); void cpuset_union(struct cpuset *, struct cpuset *, struct cpuset *); void cpuset_intersection(struct cpuset *t, struct cpuset *, struct cpuset *); void cpuset_complement(struct cpuset *, struct cpuset *, struct cpuset *); int cpuset_cardinality(struct cpuset *); struct cpu_info *cpuset_first(struct cpuset *); #endif /* _KERNEL */ #endif /* !_SYS_PROC_H_ */
41 41 41 40 12 1 1 40 2 2 2 2 2 2 1 1 2 1 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 /* $OpenBSD: subr_log.c,v 1.78 2023/09/22 20:03:05 mvs Exp $ */ /* $NetBSD: subr_log.c,v 1.11 1996/03/30 22:24:44 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)subr_log.c 8.1 (Berkeley) 6/10/93 */ /* * Error log buffer for kernel printf's. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/vnode.h> #include <sys/ioctl.h> #include <sys/msgbuf.h> #include <sys/file.h> #include <sys/tty.h> #include <sys/signalvar.h> #include <sys/syslog.h> #include <sys/malloc.h> #include <sys/filedesc.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/event.h> #include <sys/fcntl.h> #include <sys/mutex.h> #include <sys/timeout.h> #ifdef KTRACE #include <sys/ktrace.h> #endif #include <sys/mount.h> #include <sys/syscallargs.h> #include <dev/cons.h> #define LOG_RDPRI (PZERO + 1) #define LOG_TICK 50 /* log tick interval in msec */ #define LOG_ASYNC 0x04 #define LOG_RDWAIT 0x08 /* * Locking: * L log_mtx */ struct logsoftc { int sc_state; /* [L] see above for possibilities */ struct klist sc_klist; /* process waiting on kevent call */ struct sigio_ref sc_sigio; /* async I/O registration */ int sc_need_wakeup; /* if set, wake up waiters */ struct timeout sc_tick; /* wakeup poll timeout */ } logsoftc; int log_open; /* also used in log() */ int msgbufmapped; /* is the message buffer mapped */ struct msgbuf *msgbufp; /* the mapped buffer, itself. */ struct msgbuf *consbufp; /* console message buffer. */ struct file *syslogf; struct rwlock syslogf_rwlock = RWLOCK_INITIALIZER("syslogf"); /* * Lock that serializes access to log message buffers. * This should be kept as a leaf lock in order not to constrain where * printf(9) can be used. */ struct mutex log_mtx = MUTEX_INITIALIZER_FLAGS(IPL_HIGH, "logmtx", MTX_NOWITNESS); void filt_logrdetach(struct knote *kn); int filt_logread(struct knote *kn, long hint); int filt_logmodify(struct kevent *, struct knote *); int filt_logprocess(struct knote *, struct kevent *); const struct filterops logread_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_logrdetach, .f_event = filt_logread, .f_modify = filt_logmodify, .f_process = filt_logprocess, }; int dosendsyslog(struct proc *, const char *, size_t, int, enum uio_seg); void logtick(void *); size_t msgbuf_getlen(struct msgbuf *); void msgbuf_putchar_locked(struct msgbuf *, const char); void initmsgbuf(caddr_t buf, size_t bufsize) { struct msgbuf *mbp; long new_bufs; /* Sanity-check the given size. */ if (bufsize < sizeof(struct msgbuf)) return; mbp = msgbufp = (struct msgbuf *)buf; new_bufs = bufsize - offsetof(struct msgbuf, msg_bufc); if ((mbp->msg_magic != MSG_MAGIC) || (mbp->msg_bufs != new_bufs) || (mbp->msg_bufr < 0) || (mbp->msg_bufr >= mbp->msg_bufs) || (mbp->msg_bufx < 0) || (mbp->msg_bufx >= mbp->msg_bufs)) { /* * If the buffer magic number is wrong, has changed * size (which shouldn't happen often), or is * internally inconsistent, initialize it. */ memset(buf, 0, bufsize); mbp->msg_magic = MSG_MAGIC; mbp->msg_bufs = new_bufs; } /* * Always start new buffer data on a new line. * Avoid using log_mtx because mutexes do not work during early boot * on some architectures. */ if (mbp->msg_bufx > 0 && mbp->msg_bufc[mbp->msg_bufx - 1] != '\n') msgbuf_putchar_locked(mbp, '\n'); /* mark it as ready for use. */ msgbufmapped = 1; } void initconsbuf(void) { /* Set up a buffer to collect /dev/console output */ consbufp = malloc(CONSBUFSIZE, M_TTYS, M_WAITOK | M_ZERO); consbufp->msg_magic = MSG_MAGIC; consbufp->msg_bufs = CONSBUFSIZE - offsetof(struct msgbuf, msg_bufc); } void msgbuf_putchar(struct msgbuf *mbp, const char c) { if (mbp->msg_magic != MSG_MAGIC) /* Nothing we can do */ return; mtx_enter(&log_mtx); msgbuf_putchar_locked(mbp, c); mtx_leave(&log_mtx); } void msgbuf_putchar_locked(struct msgbuf *mbp, const char c) { mbp->msg_bufc[mbp->msg_bufx++] = c; if (mbp->msg_bufx < 0 || mbp->msg_bufx >= mbp->msg_bufs) mbp->msg_bufx = 0; /* If the buffer is full, keep the most recent data. */ if (mbp->msg_bufr == mbp->msg_bufx) { if (++mbp->msg_bufr >= mbp->msg_bufs) mbp->msg_bufr = 0; mbp->msg_bufd++; } } size_t msgbuf_getlen(struct msgbuf *mbp) { long len; len = mbp->msg_bufx - mbp->msg_bufr; if (len < 0) len += mbp->msg_bufs; return (len); } int logopen(dev_t dev, int flags, int mode, struct proc *p) { if (log_open) return (EBUSY); log_open = 1; klist_init_mutex(&logsoftc.sc_klist, &log_mtx); sigio_init(&logsoftc.sc_sigio); timeout_set(&logsoftc.sc_tick, logtick, NULL); timeout_add_msec(&logsoftc.sc_tick, LOG_TICK); return (0); } int logclose(dev_t dev, int flag, int mode, struct proc *p) { struct file *fp; rw_enter_write(&syslogf_rwlock); fp = syslogf; syslogf = NULL; rw_exit(&syslogf_rwlock); if (fp) FRELE(fp, p); log_open = 0; timeout_del(&logsoftc.sc_tick); klist_invalidate(&logsoftc.sc_klist); klist_free(&logsoftc.sc_klist); logsoftc.sc_state = 0; sigio_free(&logsoftc.sc_sigio); return (0); } int logread(dev_t dev, struct uio *uio, int flag) { struct msgbuf *mbp = msgbufp; size_t l, rpos; int error = 0; mtx_enter(&log_mtx); while (mbp->msg_bufr == mbp->msg_bufx) { if (flag & IO_NDELAY) { error = EWOULDBLOCK; goto out; } logsoftc.sc_state |= LOG_RDWAIT; mtx_leave(&log_mtx); /* * Set up and enter sleep manually instead of using msleep() * to keep log_mtx as a leaf lock. */ sleep_setup(mbp, LOG_RDPRI | PCATCH, "klog"); error = sleep_finish(0, logsoftc.sc_state & LOG_RDWAIT); mtx_enter(&log_mtx); if (error) goto out; } if (mbp->msg_bufd > 0) { char buf[64]; long ndropped; ndropped = mbp->msg_bufd; mtx_leave(&log_mtx); l = snprintf(buf, sizeof(buf), "<%d>klog: dropped %ld byte%s, message buffer full\n", LOG_KERN|LOG_WARNING, ndropped, ndropped == 1 ? "" : "s"); error = uiomove(buf, ulmin(l, sizeof(buf) - 1), uio); mtx_enter(&log_mtx); if (error) goto out; mbp->msg_bufd -= ndropped; } while (uio->uio_resid > 0) { if (mbp->msg_bufx >= mbp->msg_bufr) l = mbp->msg_bufx - mbp->msg_bufr; else l = mbp->msg_bufs - mbp->msg_bufr; l = ulmin(l, uio->uio_resid); if (l == 0) break; rpos = mbp->msg_bufr; mtx_leave(&log_mtx); /* Ignore that concurrent readers may consume the same data. */ error = uiomove(&mbp->msg_bufc[rpos], l, uio); mtx_enter(&log_mtx); if (error) break; mbp->msg_bufr += l; if (mbp->msg_bufr < 0 || mbp->msg_bufr >= mbp->msg_bufs) mbp->msg_bufr = 0; } out: mtx_leave(&log_mtx); return (error); } int logkqfilter(dev_t dev, struct knote *kn) { struct klist *klist; switch (kn->kn_filter) { case EVFILT_READ: klist = &logsoftc.sc_klist; kn->kn_fop = &logread_filtops; break; default: return (EINVAL); } kn->kn_hook = (void *)msgbufp; klist_insert(klist, kn); return (0); } void filt_logrdetach(struct knote *kn) { klist_remove(&logsoftc.sc_klist, kn); } int filt_logread(struct knote *kn, long hint) { struct msgbuf *mbp = kn->kn_hook; kn->kn_data = msgbuf_getlen(mbp); return (kn->kn_data != 0); } int filt_logmodify(struct kevent *kev, struct knote *kn) { int active; mtx_enter(&log_mtx); active = knote_modify(kev, kn); mtx_leave(&log_mtx); return (active); } int filt_logprocess(struct knote *kn, struct kevent *kev) { int active; mtx_enter(&log_mtx); active = knote_process(kn, kev); mtx_leave(&log_mtx); return (active); } void logwakeup(void) { /* * The actual wakeup has to be deferred because logwakeup() can be * called in very varied contexts. * Keep the print routines usable in as many situations as possible * by not using locking here. */ /* * Ensure that preceding stores become visible to other CPUs * before the flag. */ membar_producer(); logsoftc.sc_need_wakeup = 1; } void logtick(void *arg) { int state; if (!log_open) return; if (!logsoftc.sc_need_wakeup) goto out; logsoftc.sc_need_wakeup = 0; /* * sc_need_wakeup has to be cleared before handling the wakeup. * Visiting log_mtx ensures the proper order. */ mtx_enter(&log_mtx); state = logsoftc.sc_state; if (logsoftc.sc_state & LOG_RDWAIT) logsoftc.sc_state &= ~LOG_RDWAIT; knote_locked(&logsoftc.sc_klist, 0); mtx_leave(&log_mtx); if (state & LOG_ASYNC) pgsigio(&logsoftc.sc_sigio, SIGIO, 0); if (state & LOG_RDWAIT) wakeup(msgbufp); out: timeout_add_msec(&logsoftc.sc_tick, LOG_TICK); } int logioctl(dev_t dev, u_long com, caddr_t data, int flag, struct proc *p) { struct file *fp, *newfp; int error; switch (com) { /* return number of characters immediately available */ case FIONREAD: mtx_enter(&log_mtx); *(int *)data = (int)msgbuf_getlen(msgbufp); mtx_leave(&log_mtx); break; case FIONBIO: break; case FIOASYNC: mtx_enter(&log_mtx); if (*(int *)data) logsoftc.sc_state |= LOG_ASYNC; else logsoftc.sc_state &= ~LOG_ASYNC; mtx_leave(&log_mtx); break; case FIOSETOWN: case TIOCSPGRP: return (sigio_setown(&logsoftc.sc_sigio, com, data)); case FIOGETOWN: case TIOCGPGRP: sigio_getown(&logsoftc.sc_sigio, com, data); break; case LIOCSFD: if ((error = suser(p)) != 0) return (error); if ((error = getsock(p, *(int *)data, &newfp)) != 0) return (error); rw_enter_write(&syslogf_rwlock); fp = syslogf; syslogf = newfp; rw_exit(&syslogf_rwlock); if (fp) FRELE(fp, p); break; default: return (ENOTTY); } return (0); } /* * If syslogd is not running, temporarily store a limited amount of messages * in kernel. After log stash is full, drop messages and count them. When * syslogd is available again, next log message will flush the stashed * messages and insert a message with drop count. Calls to malloc(9) and * copyin(9) may sleep, protect data structures with rwlock. */ #define LOGSTASH_SIZE 100 struct logstash_message { char *lgs_buffer; size_t lgs_size; } logstash_messages[LOGSTASH_SIZE]; struct logstash_message *logstash_in = &logstash_messages[0]; struct logstash_message *logstash_out = &logstash_messages[0]; struct rwlock logstash_rwlock = RWLOCK_INITIALIZER("logstash"); int logstash_dropped, logstash_error, logstash_pid; int logstash_insert(const char *, size_t, int, pid_t); void logstash_remove(void); int logstash_sendsyslog(struct proc *); static inline int logstash_full(void) { rw_assert_anylock(&logstash_rwlock); return logstash_out->lgs_buffer != NULL && logstash_in == logstash_out; } static inline void logstash_increment(struct logstash_message **msg) { rw_assert_wrlock(&logstash_rwlock); KASSERT((*msg) >= &logstash_messages[0]); KASSERT((*msg) < &logstash_messages[LOGSTASH_SIZE]); if ((*msg) == &logstash_messages[LOGSTASH_SIZE - 1]) (*msg) = &logstash_messages[0]; else (*msg)++; } int logstash_insert(const char *buf, size_t nbyte, int logerror, pid_t pid) { int error; rw_enter_write(&logstash_rwlock); if (logstash_full()) { if (logstash_dropped == 0) { logstash_error = logerror; logstash_pid = pid; } logstash_dropped++; rw_exit(&logstash_rwlock); return (0); } logstash_in->lgs_buffer = malloc(nbyte, M_LOG, M_WAITOK); error = copyin(buf, logstash_in->lgs_buffer, nbyte); if (error) { free(logstash_in->lgs_buffer, M_LOG, nbyte); logstash_in->lgs_buffer = NULL; rw_exit(&logstash_rwlock); return (error); } logstash_in->lgs_size = nbyte; logstash_increment(&logstash_in); rw_exit(&logstash_rwlock); return (0); } void logstash_remove(void) { rw_assert_wrlock(&logstash_rwlock); KASSERT(logstash_out->lgs_buffer != NULL); free(logstash_out->lgs_buffer, M_LOG, logstash_out->lgs_size); logstash_out->lgs_buffer = NULL; logstash_increment(&logstash_out); /* Insert dropped message in sequence where messages were dropped. */ if (logstash_dropped) { size_t l, nbyte; char buf[80]; l = snprintf(buf, sizeof(buf), "<%d>sendsyslog: dropped %d message%s, error %d, pid %d", LOG_KERN|LOG_WARNING, logstash_dropped, logstash_dropped == 1 ? "" : "s", logstash_error, logstash_pid); logstash_dropped = 0; logstash_error = 0; logstash_pid = 0; /* Cannot fail, we have just freed a slot. */ KASSERT(!logstash_full()); nbyte = ulmin(l, sizeof(buf) - 1); logstash_in->lgs_buffer = malloc(nbyte, M_LOG, M_WAITOK); memcpy(logstash_in->lgs_buffer, buf, nbyte); logstash_in->lgs_size = nbyte; logstash_increment(&logstash_in); } } int logstash_sendsyslog(struct proc *p) { int error; rw_enter_write(&logstash_rwlock); while (logstash_out->lgs_buffer != NULL) { error = dosendsyslog(p, logstash_out->lgs_buffer, logstash_out->lgs_size, 0, UIO_SYSSPACE); if (error) { rw_exit(&logstash_rwlock); return (error); } logstash_remove(); } rw_exit(&logstash_rwlock); return (0); } /* * Send syslog(3) message from userland to socketpair(2) created by syslogd(8). * Store message in kernel log stash for later if syslogd(8) is not available * or sending fails. Send to console if LOG_CONS is set and syslogd(8) socket * does not exist. */ int sys_sendsyslog(struct proc *p, void *v, register_t *retval) { struct sys_sendsyslog_args /* { syscallarg(const char *) buf; syscallarg(size_t) nbyte; syscallarg(int) flags; } */ *uap = v; size_t nbyte; int error; nbyte = SCARG(uap, nbyte); if (nbyte > LOG_MAXLINE) nbyte = LOG_MAXLINE; logstash_sendsyslog(p); error = dosendsyslog(p, SCARG(uap, buf), nbyte, SCARG(uap, flags), UIO_USERSPACE); if (error && error != EFAULT) logstash_insert(SCARG(uap, buf), nbyte, error, p->p_p->ps_pid); return (error); } int dosendsyslog(struct proc *p, const char *buf, size_t nbyte, int flags, enum uio_seg sflg) { #ifdef KTRACE struct iovec ktriov; #endif struct file *fp; char pri[6], *kbuf; struct iovec aiov; struct uio auio; size_t i, len; int error; /* Global variable syslogf may change during sleep, use local copy. */ rw_enter_read(&syslogf_rwlock); fp = syslogf; if (fp) FREF(fp); rw_exit(&syslogf_rwlock); if (fp == NULL) { if (!ISSET(flags, LOG_CONS)) return (ENOTCONN); /* * Strip off syslog priority when logging to console. * LOG_PRIMASK | LOG_FACMASK is 0x03ff, so at most 4 * decimal digits may appear in priority as <1023>. */ len = MIN(nbyte, sizeof(pri)); if (sflg == UIO_USERSPACE) { if ((error = copyin(buf, pri, len))) return (error); } else memcpy(pri, buf, len); if (0 < len && pri[0] == '<') { for (i = 1; i < len; i++) { if (pri[i] < '0' || pri[i] > '9') break; } if (i < len && pri[i] == '>') { i++; /* There must be at least one digit <0>. */ if (i >= 3) { buf += i; nbyte -= i; } } } } aiov.iov_base = (char *)buf; aiov.iov_len = nbyte; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_segflg = sflg; auio.uio_rw = UIO_WRITE; auio.uio_procp = p; auio.uio_offset = 0; auio.uio_resid = aiov.iov_len; #ifdef KTRACE if (sflg == UIO_USERSPACE && KTRPOINT(p, KTR_GENIO)) ktriov = aiov; else ktriov.iov_len = 0; #endif len = auio.uio_resid; if (fp) { int flags = (fp->f_flag & FNONBLOCK) ? MSG_DONTWAIT : 0; error = sosend(fp->f_data, NULL, &auio, NULL, NULL, flags); if (error == 0) len -= auio.uio_resid; } else { KERNEL_LOCK(); if (constty || cn_devvp) { error = cnwrite(0, &auio, 0); if (error == 0) len -= auio.uio_resid; aiov.iov_base = "\r\n"; aiov.iov_len = 2; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_segflg = UIO_SYSSPACE; auio.uio_rw = UIO_WRITE; auio.uio_procp = p; auio.uio_offset = 0; auio.uio_resid = aiov.iov_len; cnwrite(0, &auio, 0); } else { /* XXX console redirection breaks down... */ if (sflg == UIO_USERSPACE) { kbuf = malloc(len, M_TEMP, M_WAITOK); error = copyin(aiov.iov_base, kbuf, len); } else { kbuf = aiov.iov_base; error = 0; } if (error == 0) for (i = 0; i < len; i++) { if (kbuf[i] == '\0') break; cnputc(kbuf[i]); auio.uio_resid--; } if (sflg == UIO_USERSPACE) free(kbuf, M_TEMP, len); if (error == 0) len -= auio.uio_resid; cnputc('\n'); } KERNEL_UNLOCK(); } #ifdef KTRACE if (error == 0 && ktriov.iov_len != 0) ktrgenio(p, -1, UIO_WRITE, &ktriov, len); #endif if (fp) FRELE(fp, p); else if (error != EFAULT) error = ENOTCONN; return (error); }
1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 /* $OpenBSD: softraid.c,v 1.430 2024/02/03 18:51:58 beck Exp $ */ /* * Copyright (c) 2007, 2008, 2009 Marco Peereboom <marco@peereboom.us> * Copyright (c) 2008 Chris Kuethe <ckuethe@openbsd.org> * Copyright (c) 2009 Joel Sing <jsing@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "bio.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/buf.h> #include <sys/device.h> #include <sys/ioctl.h> #include <sys/malloc.h> #include <sys/pool.h> #include <sys/kernel.h> #include <sys/disk.h> #include <sys/rwlock.h> #include <sys/queue.h> #include <sys/fcntl.h> #include <sys/disklabel.h> #include <sys/vnode.h> #include <sys/lock.h> #include <sys/mount.h> #include <sys/sensors.h> #include <sys/stat.h> #include <sys/conf.h> #include <sys/uio.h> #include <sys/task.h> #include <sys/kthread.h> #include <sys/dkio.h> #include <sys/stdint.h> #include <scsi/scsi_all.h> #include <scsi/scsiconf.h> #include <scsi/scsi_disk.h> #include <dev/softraidvar.h> #ifdef HIBERNATE #include <lib/libsa/aes_xts.h> #include <sys/hibernate.h> #include <scsi/sdvar.h> #endif /* HIBERNATE */ /* #define SR_FANCY_STATS */ #ifdef SR_DEBUG #define SR_FANCY_STATS uint32_t sr_debug = 0 /* | SR_D_CMD */ /* | SR_D_MISC */ /* | SR_D_INTR */ /* | SR_D_IOCTL */ /* | SR_D_CCB */ /* | SR_D_WU */ /* | SR_D_META */ /* | SR_D_DIS */ /* | SR_D_STATE */ /* | SR_D_REBUILD */ ; #endif struct sr_softc *softraid0; struct sr_uuid sr_bootuuid; u_int8_t sr_bootkey[SR_CRYPTO_MAXKEYBYTES]; int sr_match(struct device *, void *, void *); void sr_attach(struct device *, struct device *, void *); int sr_detach(struct device *, int); void sr_map_root(void); const struct cfattach softraid_ca = { sizeof(struct sr_softc), sr_match, sr_attach, sr_detach, }; struct cfdriver softraid_cd = { NULL, "softraid", DV_DULL }; /* scsi & discipline */ void sr_scsi_cmd(struct scsi_xfer *); int sr_scsi_probe(struct scsi_link *); int sr_scsi_ioctl(struct scsi_link *, u_long, caddr_t, int); int sr_bio_ioctl(struct device *, u_long, caddr_t); int sr_bio_handler(struct sr_softc *, struct sr_discipline *, u_long, struct bio *); int sr_ioctl_inq(struct sr_softc *, struct bioc_inq *); int sr_ioctl_vol(struct sr_softc *, struct bioc_vol *); int sr_ioctl_disk(struct sr_softc *, struct bioc_disk *); int sr_ioctl_setstate(struct sr_softc *, struct bioc_setstate *); int sr_ioctl_createraid(struct sr_softc *, struct bioc_createraid *, int, void *); int sr_ioctl_deleteraid(struct sr_softc *, struct sr_discipline *, struct bioc_deleteraid *); int sr_ioctl_discipline(struct sr_softc *, struct sr_discipline *, struct bioc_discipline *); int sr_ioctl_installboot(struct sr_softc *, struct sr_discipline *, struct bioc_installboot *); void sr_chunks_unwind(struct sr_softc *, struct sr_chunk_head *); void sr_discipline_free(struct sr_discipline *); void sr_discipline_shutdown(struct sr_discipline *, int, int); int sr_discipline_init(struct sr_discipline *, int); int sr_alloc_resources(struct sr_discipline *); void sr_free_resources(struct sr_discipline *); void sr_set_chunk_state(struct sr_discipline *, int, int); void sr_set_vol_state(struct sr_discipline *); /* utility functions */ void sr_shutdown(int); void sr_uuid_generate(struct sr_uuid *); char *sr_uuid_format(struct sr_uuid *); void sr_uuid_print(struct sr_uuid *, int); void sr_checksum_print(u_int8_t *); int sr_boot_assembly(struct sr_softc *); int sr_already_assembled(struct sr_discipline *); int sr_hotspare(struct sr_softc *, dev_t); void sr_hotspare_rebuild(struct sr_discipline *); int sr_rebuild_init(struct sr_discipline *, dev_t, int); void sr_rebuild_start(void *); void sr_rebuild_thread(void *); void sr_rebuild(struct sr_discipline *); void sr_roam_chunks(struct sr_discipline *); int sr_chunk_in_use(struct sr_softc *, dev_t); int sr_rw(struct sr_softc *, dev_t, char *, size_t, daddr_t, long); void sr_wu_done_callback(void *); struct sr_discipline *sr_find_discipline(struct sr_softc *sc, const char *); /* don't include these on RAMDISK */ #ifndef SMALL_KERNEL void sr_sensors_refresh(void *); int sr_sensors_create(struct sr_discipline *); void sr_sensors_delete(struct sr_discipline *); #endif /* metadata */ int sr_meta_probe(struct sr_discipline *, dev_t *, int); int sr_meta_attach(struct sr_discipline *, int, int); int sr_meta_rw(struct sr_discipline *, dev_t, void *, long); int sr_meta_clear(struct sr_discipline *); void sr_meta_init(struct sr_discipline *, int, int); void sr_meta_init_complete(struct sr_discipline *); void sr_meta_opt_handler(struct sr_discipline *, struct sr_meta_opt_hdr *); /* hotplug magic */ void sr_disk_attach(struct disk *, int); struct sr_hotplug_list { void (*sh_hotplug)(struct sr_discipline *, struct disk *, int); struct sr_discipline *sh_sd; SLIST_ENTRY(sr_hotplug_list) shl_link; }; SLIST_HEAD(sr_hotplug_list_head, sr_hotplug_list); struct sr_hotplug_list_head sr_hotplug_callbacks; extern void (*softraid_disk_attach)(struct disk *, int); /* scsi glue */ const struct scsi_adapter sr_switch = { sr_scsi_cmd, NULL, sr_scsi_probe, NULL, sr_scsi_ioctl }; /* native metadata format */ int sr_meta_native_bootprobe(struct sr_softc *, dev_t, struct sr_boot_chunk_head *); #define SR_META_NOTCLAIMED (0) #define SR_META_CLAIMED (1) int sr_meta_native_probe(struct sr_softc *, struct sr_chunk *); int sr_meta_native_attach(struct sr_discipline *, int); int sr_meta_native_write(struct sr_discipline *, dev_t, struct sr_metadata *,void *); #ifdef SR_DEBUG void sr_meta_print(struct sr_metadata *); #else #define sr_meta_print(m) #endif /* the metadata driver should remain stateless */ struct sr_meta_driver { daddr_t smd_offset; /* metadata location */ u_int32_t smd_size; /* size of metadata */ int (*smd_probe)(struct sr_softc *, struct sr_chunk *); int (*smd_attach)(struct sr_discipline *, int); int (*smd_detach)(struct sr_discipline *); int (*smd_read)(struct sr_discipline *, dev_t, struct sr_metadata *, void *); int (*smd_write)(struct sr_discipline *, dev_t, struct sr_metadata *, void *); int (*smd_validate)(struct sr_discipline *, struct sr_metadata *, void *); } smd[] = { { SR_META_OFFSET, SR_META_SIZE * DEV_BSIZE, sr_meta_native_probe, sr_meta_native_attach, NULL, sr_meta_native_read, sr_meta_native_write, NULL }, { 0, 0, NULL, NULL, NULL, NULL } }; int sr_meta_attach(struct sr_discipline *sd, int chunk_no, int force) { struct sr_softc *sc = sd->sd_sc; struct sr_chunk_head *cl; struct sr_chunk *ch_entry, *chunk1, *chunk2; int rv = 1, i = 0; DNPRINTF(SR_D_META, "%s: sr_meta_attach(%d)\n", DEVNAME(sc), chunk_no); /* in memory copy of metadata */ sd->sd_meta = malloc(SR_META_SIZE * DEV_BSIZE, M_DEVBUF, M_ZERO | M_NOWAIT); if (!sd->sd_meta) { sr_error(sc, "could not allocate memory for metadata"); goto bad; } if (sd->sd_meta_type != SR_META_F_NATIVE) { /* in memory copy of foreign metadata */ sd->sd_meta_foreign = malloc(smd[sd->sd_meta_type].smd_size, M_DEVBUF, M_ZERO | M_NOWAIT); if (!sd->sd_meta_foreign) { /* unwind frees sd_meta */ sr_error(sc, "could not allocate memory for foreign " "metadata"); goto bad; } } /* we have a valid list now create an array index */ cl = &sd->sd_vol.sv_chunk_list; sd->sd_vol.sv_chunks = mallocarray(chunk_no, sizeof(struct sr_chunk *), M_DEVBUF, M_WAITOK | M_ZERO); /* fill out chunk array */ i = 0; SLIST_FOREACH(ch_entry, cl, src_link) sd->sd_vol.sv_chunks[i++] = ch_entry; /* attach metadata */ if (smd[sd->sd_meta_type].smd_attach(sd, force)) goto bad; /* Force chunks into correct order now that metadata is attached. */ SLIST_INIT(cl); for (i = 0; i < chunk_no; i++) { ch_entry = sd->sd_vol.sv_chunks[i]; chunk2 = NULL; SLIST_FOREACH(chunk1, cl, src_link) { if (chunk1->src_meta.scmi.scm_chunk_id > ch_entry->src_meta.scmi.scm_chunk_id) break; chunk2 = chunk1; } if (chunk2 == NULL) SLIST_INSERT_HEAD(cl, ch_entry, src_link); else SLIST_INSERT_AFTER(chunk2, ch_entry, src_link); } i = 0; SLIST_FOREACH(ch_entry, cl, src_link) sd->sd_vol.sv_chunks[i++] = ch_entry; rv = 0; bad: return (rv); } int sr_meta_probe(struct sr_discipline *sd, dev_t *dt, int no_chunk) { struct sr_softc *sc = sd->sd_sc; struct vnode *vn; struct sr_chunk *ch_entry, *ch_prev = NULL; struct sr_chunk_head *cl; char devname[32]; int i, d, type, found, prevf, error; dev_t dev; DNPRINTF(SR_D_META, "%s: sr_meta_probe(%d)\n", DEVNAME(sc), no_chunk); if (no_chunk == 0) goto unwind; cl = &sd->sd_vol.sv_chunk_list; for (d = 0, prevf = SR_META_F_INVALID; d < no_chunk; d++) { ch_entry = malloc(sizeof(struct sr_chunk), M_DEVBUF, M_WAITOK | M_ZERO); /* keep disks in user supplied order */ if (ch_prev) SLIST_INSERT_AFTER(ch_prev, ch_entry, src_link); else SLIST_INSERT_HEAD(cl, ch_entry, src_link); ch_prev = ch_entry; dev = dt[d]; ch_entry->src_dev_mm = dev; if (dev == NODEV) { ch_entry->src_meta.scm_status = BIOC_SDOFFLINE; continue; } else { sr_meta_getdevname(sc, dev, devname, sizeof(devname)); if (bdevvp(dev, &vn)) { sr_error(sc, "sr_meta_probe: cannot allocate " "vnode"); goto unwind; } /* * XXX leaving dev open for now; move this to attach * and figure out the open/close dance for unwind. */ error = VOP_OPEN(vn, FREAD | FWRITE, NOCRED, curproc); if (error) { DNPRINTF(SR_D_META,"%s: sr_meta_probe can't " "open %s\n", DEVNAME(sc), devname); vput(vn); goto unwind; } strlcpy(ch_entry->src_devname, devname, sizeof(ch_entry->src_devname)); ch_entry->src_vn = vn; } /* determine if this is a device we understand */ for (i = 0, found = SR_META_F_INVALID; smd[i].smd_probe; i++) { type = smd[i].smd_probe(sc, ch_entry); if (type == SR_META_F_INVALID) continue; else { found = type; break; } } if (found == SR_META_F_INVALID) goto unwind; if (prevf == SR_META_F_INVALID) prevf = found; if (prevf != found) { DNPRINTF(SR_D_META, "%s: prevf != found\n", DEVNAME(sc)); goto unwind; } } return (prevf); unwind: return (SR_META_F_INVALID); } void sr_meta_getdevname(struct sr_softc *sc, dev_t dev, char *buf, int size) { int maj, unit, part; char *name; DNPRINTF(SR_D_META, "%s: sr_meta_getdevname(%p, %d)\n", DEVNAME(sc), buf, size); if (!buf) return; maj = major(dev); part = DISKPART(dev); unit = DISKUNIT(dev); name = findblkname(maj); if (name == NULL) return; snprintf(buf, size, "%s%d%c", name, unit, part + 'a'); } int sr_rw(struct sr_softc *sc, dev_t dev, char *buf, size_t size, daddr_t blkno, long flags) { struct vnode *vp; struct buf b; size_t bufsize, dma_bufsize; int rv = 1; char *dma_buf; int s; DNPRINTF(SR_D_MISC, "%s: sr_rw(0x%x, %p, %zu, %lld 0x%lx)\n", DEVNAME(sc), dev, buf, size, (long long)blkno, flags); dma_bufsize = (size > MAXPHYS) ? MAXPHYS : size; dma_buf = dma_alloc(dma_bufsize, PR_WAITOK); if (bdevvp(dev, &vp)) { printf("%s: sr_rw: failed to allocate vnode\n", DEVNAME(sc)); goto done; } while (size > 0) { DNPRINTF(SR_D_MISC, "%s: dma_buf %p, size %zu, blkno %lld)\n", DEVNAME(sc), dma_buf, size, (long long)blkno); bufsize = (size > MAXPHYS) ? MAXPHYS : size; if (flags == B_WRITE) memcpy(dma_buf, buf, bufsize); bzero(&b, sizeof(b)); b.b_flags = flags | B_PHYS; b.b_proc = curproc; b.b_dev = dev; b.b_iodone = NULL; b.b_error = 0; b.b_blkno = blkno; b.b_data = dma_buf; b.b_bcount = bufsize; b.b_bufsize = bufsize; b.b_resid = bufsize; b.b_vp = vp; if ((b.b_flags & B_READ) == 0) { s = splbio(); vp->v_numoutput++; splx(s); } VOP_STRATEGY(vp, &b); biowait(&b); if (b.b_flags & B_ERROR) { printf("%s: I/O error %d on dev 0x%x at block %llu\n", DEVNAME(sc), b.b_error, dev, b.b_blkno); goto done; } if (flags == B_READ) memcpy(buf, dma_buf, bufsize); size -= bufsize; buf += bufsize; blkno += howmany(bufsize, DEV_BSIZE); } rv = 0; done: if (vp) vput(vp); dma_free(dma_buf, dma_bufsize); return (rv); } int sr_meta_rw(struct sr_discipline *sd, dev_t dev, void *md, long flags) { int rv = 1; DNPRINTF(SR_D_META, "%s: sr_meta_rw(0x%x, %p, 0x%lx)\n", DEVNAME(sd->sd_sc), dev, md, flags); if (md == NULL) { printf("%s: sr_meta_rw: invalid metadata pointer\n", DEVNAME(sd->sd_sc)); goto done; } rv = sr_rw(sd->sd_sc, dev, md, SR_META_SIZE * DEV_BSIZE, SR_META_OFFSET, flags); done: return (rv); } int sr_meta_clear(struct sr_discipline *sd) { struct sr_softc *sc = sd->sd_sc; struct sr_chunk_head *cl = &sd->sd_vol.sv_chunk_list; struct sr_chunk *ch_entry; void *m; int rv = 1; DNPRINTF(SR_D_META, "%s: sr_meta_clear\n", DEVNAME(sc)); if (sd->sd_meta_type != SR_META_F_NATIVE) { sr_error(sc, "cannot clear foreign metadata"); goto done; } m = malloc(SR_META_SIZE * DEV_BSIZE, M_DEVBUF, M_WAITOK | M_ZERO); SLIST_FOREACH(ch_entry, cl, src_link) { if (sr_meta_native_write(sd, ch_entry->src_dev_mm, m, NULL)) { /* XXX mark disk offline */ DNPRINTF(SR_D_META, "%s: sr_meta_clear failed to " "clear %s\n", DEVNAME(sc), ch_entry->src_devname); rv++; continue; } bzero(&ch_entry->src_meta, sizeof(ch_entry->src_meta)); } bzero(sd->sd_meta, SR_META_SIZE * DEV_BSIZE); free(m, M_DEVBUF, SR_META_SIZE * DEV_BSIZE); rv = 0; done: return (rv); } void sr_meta_init(struct sr_discipline *sd, int level, int no_chunk) { struct sr_softc *sc = sd->sd_sc; struct sr_metadata *sm = sd->sd_meta; struct sr_chunk_head *cl = &sd->sd_vol.sv_chunk_list; struct sr_meta_chunk *scm; struct sr_chunk *chunk; int cid = 0; u_int64_t max_chunk_sz = 0, min_chunk_sz = 0; u_int32_t secsize = DEV_BSIZE; DNPRINTF(SR_D_META, "%s: sr_meta_init\n", DEVNAME(sc)); if (!sm) return; /* Initialise volume metadata. */ sm->ssdi.ssd_magic = SR_MAGIC; sm->ssdi.ssd_version = SR_META_VERSION; sm->ssdi.ssd_vol_flags = sd->sd_meta_flags; sm->ssdi.ssd_volid = 0; sm->ssdi.ssd_chunk_no = no_chunk; sm->ssdi.ssd_level = level; sm->ssd_data_blkno = SR_DATA_OFFSET; sm->ssd_ondisk = 0; sr_uuid_generate(&sm->ssdi.ssd_uuid); /* Initialise chunk metadata and get min/max chunk sizes & secsize. */ SLIST_FOREACH(chunk, cl, src_link) { scm = &chunk->src_meta; scm->scmi.scm_size = chunk->src_size; scm->scmi.scm_chunk_id = cid++; scm->scm_status = BIOC_SDONLINE; scm->scmi.scm_volid = 0; strlcpy(scm->scmi.scm_devname, chunk->src_devname, sizeof(scm->scmi.scm_devname)); memcpy(&scm->scmi.scm_uuid, &sm->ssdi.ssd_uuid, sizeof(scm->scmi.scm_uuid)); sr_checksum(sc, scm, &scm->scm_checksum, sizeof(scm->scm_checksum)); if (min_chunk_sz == 0) min_chunk_sz = scm->scmi.scm_size; if (chunk->src_secsize > secsize) secsize = chunk->src_secsize; min_chunk_sz = MIN(min_chunk_sz, scm->scmi.scm_size); max_chunk_sz = MAX(max_chunk_sz, scm->scmi.scm_size); } sm->ssdi.ssd_secsize = secsize; /* Equalize chunk sizes. */ SLIST_FOREACH(chunk, cl, src_link) chunk->src_meta.scmi.scm_coerced_size = min_chunk_sz; sd->sd_vol.sv_chunk_minsz = min_chunk_sz; sd->sd_vol.sv_chunk_maxsz = max_chunk_sz; } void sr_meta_init_complete(struct sr_discipline *sd) { #ifdef SR_DEBUG struct sr_softc *sc = sd->sd_sc; #endif struct sr_metadata *sm = sd->sd_meta; DNPRINTF(SR_D_META, "%s: sr_meta_complete\n", DEVNAME(sc)); /* Complete initialisation of volume metadata. */ strlcpy(sm->ssdi.ssd_vendor, "OPENBSD", sizeof(sm->ssdi.ssd_vendor)); snprintf(sm->ssdi.ssd_product, sizeof(sm->ssdi.ssd_product), "SR %s", sd->sd_name); snprintf(sm->ssdi.ssd_revision, sizeof(sm->ssdi.ssd_revision), "%03d", sm->ssdi.ssd_version); } void sr_meta_opt_handler(struct sr_discipline *sd, struct sr_meta_opt_hdr *om) { if (om->som_type != SR_OPT_BOOT) panic("unknown optional metadata type"); } void sr_meta_save_callback(void *xsd) { struct sr_discipline *sd = xsd; int s; s = splbio(); if (sr_meta_save(sd, SR_META_DIRTY)) printf("%s: save metadata failed\n", DEVNAME(sd->sd_sc)); sd->sd_must_flush = 0; splx(s); } int sr_meta_save(struct sr_discipline *sd, u_int32_t flags) { struct sr_softc *sc = sd->sd_sc; struct sr_metadata *sm = sd->sd_meta, *m; struct sr_meta_driver *s; struct sr_chunk *src; struct sr_meta_chunk *cm; struct sr_workunit wu; struct sr_meta_opt_hdr *omh; struct sr_meta_opt_item *omi; int i; DNPRINTF(SR_D_META, "%s: sr_meta_save %s\n", DEVNAME(sc), sd->sd_meta->ssd_devname); if (!sm) { printf("%s: no in memory copy of metadata\n", DEVNAME(sc)); goto bad; } /* meta scratchpad */ s = &smd[sd->sd_meta_type]; m = malloc(SR_META_SIZE * DEV_BSIZE, M_DEVBUF, M_ZERO | M_NOWAIT); if (!m) { printf("%s: could not allocate metadata scratch area\n", DEVNAME(sc)); goto bad; } /* from here on out metadata is updated */ restart: sm->ssd_ondisk++; sm->ssd_meta_flags = flags; memcpy(m, sm, sizeof(*m)); /* Chunk metadata. */ cm = (struct sr_meta_chunk *)(m + 1); for (i = 0; i < sm->ssdi.ssd_chunk_no; i++) { src = sd->sd_vol.sv_chunks[i]; memcpy(cm, &src->src_meta, sizeof(*cm)); cm++; } /* Optional metadata. */ omh = (struct sr_meta_opt_hdr *)(cm); SLIST_FOREACH(omi, &sd->sd_meta_opt, omi_link) { DNPRINTF(SR_D_META, "%s: saving optional metadata type %u with " "length %u\n", DEVNAME(sc), omi->omi_som->som_type, omi->omi_som->som_length); bzero(&omi->omi_som->som_checksum, MD5_DIGEST_LENGTH); sr_checksum(sc, omi->omi_som, &omi->omi_som->som_checksum, omi->omi_som->som_length); memcpy(omh, omi->omi_som, omi->omi_som->som_length); omh = (struct sr_meta_opt_hdr *)((u_int8_t *)omh + omi->omi_som->som_length); } for (i = 0; i < sm->ssdi.ssd_chunk_no; i++) { src = sd->sd_vol.sv_chunks[i]; /* skip disks that are offline */ if (src->src_meta.scm_status == BIOC_SDOFFLINE) continue; /* calculate metadata checksum for correct chunk */ m->ssdi.ssd_chunk_id = i; sr_checksum(sc, m, &m->ssd_checksum, sizeof(struct sr_meta_invariant)); #ifdef SR_DEBUG DNPRINTF(SR_D_META, "%s: sr_meta_save %s: volid: %d " "chunkid: %d checksum: ", DEVNAME(sc), src->src_meta.scmi.scm_devname, m->ssdi.ssd_volid, m->ssdi.ssd_chunk_id); if (sr_debug & SR_D_META) sr_checksum_print((u_int8_t *)&m->ssd_checksum); DNPRINTF(SR_D_META, "\n"); sr_meta_print(m); #endif /* translate and write to disk */ if (s->smd_write(sd, src->src_dev_mm, m, NULL /* XXX */)) { printf("%s: could not write metadata to %s\n", DEVNAME(sc), src->src_devname); /* restart the meta write */ src->src_meta.scm_status = BIOC_SDOFFLINE; /* XXX recalculate volume status */ goto restart; } } /* not all disciplines have sync */ if (sd->sd_scsi_sync) { bzero(&wu, sizeof(wu)); wu.swu_flags |= SR_WUF_FAKE; wu.swu_dis = sd; sd->sd_scsi_sync(&wu); } free(m, M_DEVBUF, SR_META_SIZE * DEV_BSIZE); return (0); bad: return (1); } int sr_meta_read(struct sr_discipline *sd) { struct sr_softc *sc = sd->sd_sc; struct sr_chunk_head *cl = &sd->sd_vol.sv_chunk_list; struct sr_metadata *sm; struct sr_chunk *ch_entry; struct sr_meta_chunk *cp; struct sr_meta_driver *s; void *fm = NULL; int no_disk = 0, got_meta = 0; DNPRINTF(SR_D_META, "%s: sr_meta_read\n", DEVNAME(sc)); sm = malloc(SR_META_SIZE * DEV_BSIZE, M_DEVBUF, M_WAITOK | M_ZERO); s = &smd[sd->sd_meta_type]; if (sd->sd_meta_type != SR_META_F_NATIVE) fm = malloc(s->smd_size, M_DEVBUF, M_WAITOK | M_ZERO); cp = (struct sr_meta_chunk *)(sm + 1); SLIST_FOREACH(ch_entry, cl, src_link) { /* skip disks that are offline */ if (ch_entry->src_meta.scm_status == BIOC_SDOFFLINE) { DNPRINTF(SR_D_META, "%s: %s chunk marked offline, spoofing status\n", DEVNAME(sc), ch_entry->src_devname); cp++; /* adjust chunk pointer to match failure */ continue; } else if (s->smd_read(sd, ch_entry->src_dev_mm, sm, fm)) { /* read and translate */ /* XXX mark chunk offline, elsewhere!! */ ch_entry->src_meta.scm_status = BIOC_SDOFFLINE; cp++; /* adjust chunk pointer to match failure */ DNPRINTF(SR_D_META, "%s: sr_meta_read failed\n", DEVNAME(sc)); continue; } if (sm->ssdi.ssd_magic != SR_MAGIC) { DNPRINTF(SR_D_META, "%s: sr_meta_read !SR_MAGIC\n", DEVNAME(sc)); continue; } /* validate metadata */ if (sr_meta_validate(sd, ch_entry->src_dev_mm, sm, fm)) { DNPRINTF(SR_D_META, "%s: invalid metadata\n", DEVNAME(sc)); no_disk = -1; goto done; } /* assume first chunk contains metadata */ if (got_meta == 0) { sr_meta_opt_load(sc, sm, &sd->sd_meta_opt); memcpy(sd->sd_meta, sm, sizeof(*sd->sd_meta)); got_meta = 1; } memcpy(&ch_entry->src_meta, cp, sizeof(ch_entry->src_meta)); no_disk++; cp++; } free(sm, M_DEVBUF, SR_META_SIZE * DEV_BSIZE); free(fm, M_DEVBUF, s->smd_size); done: DNPRINTF(SR_D_META, "%s: sr_meta_read found %d parts\n", DEVNAME(sc), no_disk); return (no_disk); } void sr_meta_opt_load(struct sr_softc *sc, struct sr_metadata *sm, struct sr_meta_opt_head *som) { struct sr_meta_opt_hdr *omh; struct sr_meta_opt_item *omi; u_int8_t checksum[MD5_DIGEST_LENGTH]; int i; /* Process optional metadata. */ omh = (struct sr_meta_opt_hdr *)((u_int8_t *)(sm + 1) + sizeof(struct sr_meta_chunk) * sm->ssdi.ssd_chunk_no); for (i = 0; i < sm->ssdi.ssd_opt_no; i++) { omi = malloc(sizeof(struct sr_meta_opt_item), M_DEVBUF, M_WAITOK | M_ZERO); SLIST_INSERT_HEAD(som, omi, omi_link); if (omh->som_length == 0) { /* Load old fixed length optional metadata. */ DNPRINTF(SR_D_META, "%s: old optional metadata of type " "%u\n", DEVNAME(sc), omh->som_type); /* Validate checksum. */ sr_checksum(sc, (void *)omh, &checksum, SR_OLD_META_OPT_SIZE - MD5_DIGEST_LENGTH); if (bcmp(&checksum, (void *)omh + SR_OLD_META_OPT_MD5, sizeof(checksum))) panic("%s: invalid optional metadata checksum", DEVNAME(sc)); /* Determine correct length. */ switch (omh->som_type) { case SR_OPT_CRYPTO: omh->som_length = sizeof(struct sr_meta_crypto); break; case SR_OPT_BOOT: omh->som_length = sizeof(struct sr_meta_boot); break; case SR_OPT_KEYDISK: omh->som_length = sizeof(struct sr_meta_keydisk); break; default: panic("unknown old optional metadata type %u", omh->som_type); } omi->omi_som = malloc(omh->som_length, M_DEVBUF, M_WAITOK | M_ZERO); memcpy((u_int8_t *)omi->omi_som + sizeof(*omi->omi_som), (u_int8_t *)omh + SR_OLD_META_OPT_OFFSET, omh->som_length - sizeof(*omi->omi_som)); omi->omi_som->som_type = omh->som_type; omi->omi_som->som_length = omh->som_length; omh = (struct sr_meta_opt_hdr *)((void *)omh + SR_OLD_META_OPT_SIZE); } else { /* Load variable length optional metadata. */ DNPRINTF(SR_D_META, "%s: optional metadata of type %u, " "length %u\n", DEVNAME(sc), omh->som_type, omh->som_length); omi->omi_som = malloc(omh->som_length, M_DEVBUF, M_WAITOK | M_ZERO); memcpy(omi->omi_som, omh, omh->som_length); /* Validate checksum. */ memcpy(&checksum, &omi->omi_som->som_checksum, MD5_DIGEST_LENGTH); bzero(&omi->omi_som->som_checksum, MD5_DIGEST_LENGTH); sr_checksum(sc, omi->omi_som, &omi->omi_som->som_checksum, omh->som_length); if (bcmp(&checksum, &omi->omi_som->som_checksum, sizeof(checksum))) panic("%s: invalid optional metadata checksum", DEVNAME(sc)); omh = (struct sr_meta_opt_hdr *)((void *)omh + omh->som_length); } } } int sr_meta_validate(struct sr_discipline *sd, dev_t dev, struct sr_metadata *sm, void *fm) { struct sr_softc *sc = sd->sd_sc; struct sr_meta_driver *s; #ifdef SR_DEBUG struct sr_meta_chunk *mc; #endif u_int8_t checksum[MD5_DIGEST_LENGTH]; char devname[32]; int rv = 1; DNPRINTF(SR_D_META, "%s: sr_meta_validate(%p)\n", DEVNAME(sc), sm); sr_meta_getdevname(sc, dev, devname, sizeof(devname)); s = &smd[sd->sd_meta_type]; if (sd->sd_meta_type != SR_META_F_NATIVE) if (s->smd_validate(sd, sm, fm)) { sr_error(sc, "invalid foreign metadata"); goto done; } /* * at this point all foreign metadata has been translated to the native * format and will be treated just like the native format */ if (sm->ssdi.ssd_magic != SR_MAGIC) { sr_error(sc, "not valid softraid metadata"); goto done; } /* Verify metadata checksum. */ sr_checksum(sc, sm, &checksum, sizeof(struct sr_meta_invariant)); if (bcmp(&checksum, &sm->ssd_checksum, sizeof(checksum))) { sr_error(sc, "invalid metadata checksum"); goto done; } /* Handle changes between versions. */ if (sm->ssdi.ssd_version == 3) { /* * Version 3 - update metadata version and fix up data blkno * value since this did not exist in version 3. */ if (sm->ssd_data_blkno == 0) sm->ssd_data_blkno = SR_META_V3_DATA_OFFSET; sm->ssdi.ssd_secsize = DEV_BSIZE; } else if (sm->ssdi.ssd_version == 4) { /* * Version 4 - original metadata format did not store * data blkno so fix this up if necessary. */ if (sm->ssd_data_blkno == 0) sm->ssd_data_blkno = SR_DATA_OFFSET; sm->ssdi.ssd_secsize = DEV_BSIZE; } else if (sm->ssdi.ssd_version == 5) { /* * Version 5 - variable length optional metadata. Migration * from earlier fixed length optional metadata is handled * in sr_meta_read(). */ sm->ssdi.ssd_secsize = DEV_BSIZE; } else if (sm->ssdi.ssd_version == SR_META_VERSION) { /* * Version 6 - store & report a sector size. */ } else { sr_error(sc, "cannot read metadata version %u on %s, " "expected version %u or earlier", sm->ssdi.ssd_version, devname, SR_META_VERSION); goto done; } /* Update version number and revision string. */ sm->ssdi.ssd_version = SR_META_VERSION; snprintf(sm->ssdi.ssd_revision, sizeof(sm->ssdi.ssd_revision), "%03d", SR_META_VERSION); #ifdef SR_DEBUG /* warn if disk changed order */ mc = (struct sr_meta_chunk *)(sm + 1); if (strncmp(mc[sm->ssdi.ssd_chunk_id].scmi.scm_devname, devname, sizeof(mc[sm->ssdi.ssd_chunk_id].scmi.scm_devname))) DNPRINTF(SR_D_META, "%s: roaming device %s -> %s\n", DEVNAME(sc), mc[sm->ssdi.ssd_chunk_id].scmi.scm_devname, devname); #endif /* we have meta data on disk */ DNPRINTF(SR_D_META, "%s: sr_meta_validate valid metadata %s\n", DEVNAME(sc), devname); rv = 0; done: return (rv); } int sr_meta_native_bootprobe(struct sr_softc *sc, dev_t devno, struct sr_boot_chunk_head *bch) { struct vnode *vn; struct disklabel label; struct sr_metadata *md = NULL; struct sr_discipline *fake_sd = NULL; struct sr_boot_chunk *bc; char devname[32]; dev_t chrdev, rawdev; int error, i; int rv = SR_META_NOTCLAIMED; DNPRINTF(SR_D_META, "%s: sr_meta_native_bootprobe\n", DEVNAME(sc)); /* * Use character raw device to avoid SCSI complaints about missing * media on removable media devices. */ chrdev = blktochr(devno); rawdev = MAKEDISKDEV(major(chrdev), DISKUNIT(devno), RAW_PART); if (cdevvp(rawdev, &vn)) { sr_error(sc, "sr_meta_native_bootprobe: cannot allocate vnode"); goto done; } /* open device */ error = VOP_OPEN(vn, FREAD, NOCRED, curproc); if (error) { DNPRINTF(SR_D_META, "%s: sr_meta_native_bootprobe open " "failed\n", DEVNAME(sc)); vput(vn); goto done; } /* get disklabel */ error = VOP_IOCTL(vn, DIOCGDINFO, (caddr_t)&label, FREAD, NOCRED, curproc); if (error) { DNPRINTF(SR_D_META, "%s: sr_meta_native_bootprobe ioctl " "failed\n", DEVNAME(sc)); VOP_CLOSE(vn, FREAD, NOCRED, curproc); vput(vn); goto done; } /* we are done, close device */ error = VOP_CLOSE(vn, FREAD, NOCRED, curproc); if (error) { DNPRINTF(SR_D_META, "%s: sr_meta_native_bootprobe close " "failed\n", DEVNAME(sc)); vput(vn); goto done; } vput(vn); md = malloc(SR_META_SIZE * DEV_BSIZE, M_DEVBUF, M_ZERO | M_NOWAIT); if (md == NULL) { sr_error(sc, "not enough memory for metadata buffer"); goto done; } /* create fake sd to use utility functions */ fake_sd = malloc(sizeof(struct sr_discipline), M_DEVBUF, M_ZERO | M_NOWAIT); if (fake_sd == NULL) { sr_error(sc, "not enough memory for fake discipline"); goto done; } fake_sd->sd_sc = sc; fake_sd->sd_meta_type = SR_META_F_NATIVE; for (i = 0; i < MAXPARTITIONS; i++) { if (label.d_partitions[i].p_fstype != FS_RAID) continue; /* open partition */ rawdev = MAKEDISKDEV(major(devno), DISKUNIT(devno), i); if (bdevvp(rawdev, &vn)) { sr_error(sc, "sr_meta_native_bootprobe: cannot " "allocate vnode for partition"); goto done; } error = VOP_OPEN(vn, FREAD, NOCRED, curproc); if (error) { DNPRINTF(SR_D_META, "%s: sr_meta_native_bootprobe " "open failed, partition %d\n", DEVNAME(sc), i); vput(vn); continue; } if (sr_meta_native_read(fake_sd, rawdev, md, NULL)) { sr_error(sc, "native bootprobe could not read native " "metadata"); VOP_CLOSE(vn, FREAD, NOCRED, curproc); vput(vn); continue; } /* are we a softraid partition? */ if (md->ssdi.ssd_magic != SR_MAGIC) { VOP_CLOSE(vn, FREAD, NOCRED, curproc); vput(vn); continue; } sr_meta_getdevname(sc, rawdev, devname, sizeof(devname)); if (sr_meta_validate(fake_sd, rawdev, md, NULL) == 0) { /* XXX fix M_WAITOK, this is boot time */ bc = malloc(sizeof(struct sr_boot_chunk), M_DEVBUF, M_WAITOK | M_ZERO); bc->sbc_metadata = malloc(sizeof(struct sr_metadata), M_DEVBUF, M_WAITOK | M_ZERO); memcpy(bc->sbc_metadata, md, sizeof(struct sr_metadata)); bc->sbc_mm = rawdev; SLIST_INSERT_HEAD(bch, bc, sbc_link); rv = SR_META_CLAIMED; } /* we are done, close partition */ VOP_CLOSE(vn, FREAD, NOCRED, curproc); vput(vn); } done: free(fake_sd, M_DEVBUF, sizeof(struct sr_discipline)); free(md, M_DEVBUF, SR_META_SIZE * DEV_BSIZE); return (rv); } int sr_boot_assembly(struct sr_softc *sc) { struct sr_boot_volume_head bvh; struct sr_boot_chunk_head bch, kdh; struct sr_boot_volume *bv, *bv1, *bv2; struct sr_boot_chunk *bc, *bcnext, *bc1, *bc2; struct sr_disk_head sdklist; struct sr_disk *sdk; struct disk *dk; struct bioc_createraid bcr; struct sr_meta_chunk *hm; struct sr_chunk_head *cl; struct sr_chunk *hotspare, *chunk, *last; u_int64_t *ondisk = NULL; dev_t *devs = NULL; void *data; char devname[32]; int rv = 0, i; DNPRINTF(SR_D_META, "%s: sr_boot_assembly\n", DEVNAME(sc)); SLIST_INIT(&sdklist); SLIST_INIT(&bvh); SLIST_INIT(&bch); SLIST_INIT(&kdh); dk = TAILQ_FIRST(&disklist); while (dk != NULL) { /* See if this disk has been checked. */ SLIST_FOREACH(sdk, &sdklist, sdk_link) if (sdk->sdk_devno == dk->dk_devno) break; if (sdk != NULL || dk->dk_devno == NODEV) { dk = TAILQ_NEXT(dk, dk_link); continue; } /* Add this disk to the list that we've checked. */ sdk = malloc(sizeof(struct sr_disk), M_DEVBUF, M_NOWAIT | M_ZERO); if (sdk == NULL) goto unwind; sdk->sdk_devno = dk->dk_devno; SLIST_INSERT_HEAD(&sdklist, sdk, sdk_link); /* Only check sd(4) and wd(4) devices. */ if (strncmp(dk->dk_name, "sd", 2) && strncmp(dk->dk_name, "wd", 2)) { dk = TAILQ_NEXT(dk, dk_link); continue; } /* native softraid uses partitions */ rw_enter_write(&sc->sc_lock); bio_status_init(&sc->sc_status, &sc->sc_dev); sr_meta_native_bootprobe(sc, dk->dk_devno, &bch); rw_exit_write(&sc->sc_lock); /* probe non-native disks if native failed. */ /* Restart scan since we may have slept. */ dk = TAILQ_FIRST(&disklist); } /* * Create a list of volumes and associate chunks with each volume. */ for (bc = SLIST_FIRST(&bch); bc != NULL; bc = bcnext) { bcnext = SLIST_NEXT(bc, sbc_link); SLIST_REMOVE(&bch, bc, sr_boot_chunk, sbc_link); bc->sbc_chunk_id = bc->sbc_metadata->ssdi.ssd_chunk_id; /* Handle key disks separately. */ if (bc->sbc_metadata->ssdi.ssd_level == SR_KEYDISK_LEVEL) { SLIST_INSERT_HEAD(&kdh, bc, sbc_link); continue; } SLIST_FOREACH(bv, &bvh, sbv_link) { if (bcmp(&bc->sbc_metadata->ssdi.ssd_uuid, &bv->sbv_uuid, sizeof(bc->sbc_metadata->ssdi.ssd_uuid)) == 0) break; } if (bv == NULL) { bv = malloc(sizeof(struct sr_boot_volume), M_DEVBUF, M_NOWAIT | M_ZERO); if (bv == NULL) { printf("%s: failed to allocate boot volume\n", DEVNAME(sc)); goto unwind; } bv->sbv_level = bc->sbc_metadata->ssdi.ssd_level; bv->sbv_volid = bc->sbc_metadata->ssdi.ssd_volid; bv->sbv_chunk_no = bc->sbc_metadata->ssdi.ssd_chunk_no; bv->sbv_flags = bc->sbc_metadata->ssdi.ssd_vol_flags; memcpy(&bv->sbv_uuid, &bc->sbc_metadata->ssdi.ssd_uuid, sizeof(bc->sbc_metadata->ssdi.ssd_uuid)); SLIST_INIT(&bv->sbv_chunks); /* Maintain volume order. */ bv2 = NULL; SLIST_FOREACH(bv1, &bvh, sbv_link) { if (bv1->sbv_volid > bv->sbv_volid) break; bv2 = bv1; } if (bv2 == NULL) { DNPRINTF(SR_D_META, "%s: insert volume %u " "at head\n", DEVNAME(sc), bv->sbv_volid); SLIST_INSERT_HEAD(&bvh, bv, sbv_link); } else { DNPRINTF(SR_D_META, "%s: insert volume %u " "after %u\n", DEVNAME(sc), bv->sbv_volid, bv2->sbv_volid); SLIST_INSERT_AFTER(bv2, bv, sbv_link); } } /* Maintain chunk order. */ bc2 = NULL; SLIST_FOREACH(bc1, &bv->sbv_chunks, sbc_link) { if (bc1->sbc_chunk_id > bc->sbc_chunk_id) break; bc2 = bc1; } if (bc2 == NULL) { DNPRINTF(SR_D_META, "%s: volume %u insert chunk %u " "at head\n", DEVNAME(sc), bv->sbv_volid, bc->sbc_chunk_id); SLIST_INSERT_HEAD(&bv->sbv_chunks, bc, sbc_link); } else { DNPRINTF(SR_D_META, "%s: volume %u insert chunk %u " "after %u\n", DEVNAME(sc), bv->sbv_volid, bc->sbc_chunk_id, bc2->sbc_chunk_id); SLIST_INSERT_AFTER(bc2, bc, sbc_link); } bv->sbv_chunks_found++; } /* Allocate memory for device and ondisk version arrays. */ devs = mallocarray(BIOC_CRMAXLEN, sizeof(dev_t), M_DEVBUF, M_NOWAIT); if (devs == NULL) { printf("%s: failed to allocate device array\n", DEVNAME(sc)); goto unwind; } ondisk = mallocarray(BIOC_CRMAXLEN, sizeof(u_int64_t), M_DEVBUF, M_NOWAIT); if (ondisk == NULL) { printf("%s: failed to allocate ondisk array\n", DEVNAME(sc)); goto unwind; } /* * Assemble hotspare "volumes". */ SLIST_FOREACH(bv, &bvh, sbv_link) { /* Check if this is a hotspare "volume". */ if (bv->sbv_level != SR_HOTSPARE_LEVEL || bv->sbv_chunk_no != 1) continue; #ifdef SR_DEBUG DNPRINTF(SR_D_META, "%s: assembling hotspare volume ", DEVNAME(sc)); if (sr_debug & SR_D_META) sr_uuid_print(&bv->sbv_uuid, 0); DNPRINTF(SR_D_META, " volid %u with %u chunks\n", bv->sbv_volid, bv->sbv_chunk_no); #endif /* Create hotspare chunk metadata. */ hotspare = malloc(sizeof(struct sr_chunk), M_DEVBUF, M_NOWAIT | M_ZERO); if (hotspare == NULL) { printf("%s: failed to allocate hotspare\n", DEVNAME(sc)); goto unwind; } bc = SLIST_FIRST(&bv->sbv_chunks); sr_meta_getdevname(sc, bc->sbc_mm, devname, sizeof(devname)); hotspare->src_dev_mm = bc->sbc_mm; strlcpy(hotspare->src_devname, devname, sizeof(hotspare->src_devname)); hotspare->src_size = bc->sbc_metadata->ssdi.ssd_size; hm = &hotspare->src_meta; hm->scmi.scm_volid = SR_HOTSPARE_VOLID; hm->scmi.scm_chunk_id = 0; hm->scmi.scm_size = bc->sbc_metadata->ssdi.ssd_size; hm->scmi.scm_coerced_size = bc->sbc_metadata->ssdi.ssd_size; strlcpy(hm->scmi.scm_devname, devname, sizeof(hm->scmi.scm_devname)); memcpy(&hm->scmi.scm_uuid, &bc->sbc_metadata->ssdi.ssd_uuid, sizeof(struct sr_uuid)); sr_checksum(sc, hm, &hm->scm_checksum, sizeof(struct sr_meta_chunk_invariant)); hm->scm_status = BIOC_SDHOTSPARE; /* Add chunk to hotspare list. */ rw_enter_write(&sc->sc_hs_lock); cl = &sc->sc_hotspare_list; if (SLIST_EMPTY(cl)) SLIST_INSERT_HEAD(cl, hotspare, src_link); else { SLIST_FOREACH(chunk, cl, src_link) last = chunk; SLIST_INSERT_AFTER(last, hotspare, src_link); } sc->sc_hotspare_no++; rw_exit_write(&sc->sc_hs_lock); } /* * Assemble RAID volumes. */ SLIST_FOREACH(bv, &bvh, sbv_link) { bzero(&bcr, sizeof(bcr)); data = NULL; /* Check if this is a hotspare "volume". */ if (bv->sbv_level == SR_HOTSPARE_LEVEL && bv->sbv_chunk_no == 1) continue; /* * Skip volumes that are marked as no auto assemble, unless * this was the volume which we actually booted from. */ if (bcmp(&sr_bootuuid, &bv->sbv_uuid, sizeof(sr_bootuuid)) != 0) if (bv->sbv_flags & BIOC_SCNOAUTOASSEMBLE) continue; #ifdef SR_DEBUG DNPRINTF(SR_D_META, "%s: assembling volume ", DEVNAME(sc)); if (sr_debug & SR_D_META) sr_uuid_print(&bv->sbv_uuid, 0); DNPRINTF(SR_D_META, " volid %u with %u chunks\n", bv->sbv_volid, bv->sbv_chunk_no); #endif /* * If this is a crypto volume, try to find a matching * key disk... */ bcr.bc_key_disk = NODEV; if (bv->sbv_level == 'C' || bv->sbv_level == 0x1C) { SLIST_FOREACH(bc, &kdh, sbc_link) { if (bcmp(&bc->sbc_metadata->ssdi.ssd_uuid, &bv->sbv_uuid, sizeof(bc->sbc_metadata->ssdi.ssd_uuid)) == 0) bcr.bc_key_disk = bc->sbc_mm; } } for (i = 0; i < BIOC_CRMAXLEN; i++) { devs[i] = NODEV; /* mark device as illegal */ ondisk[i] = 0; } SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link) { if (devs[bc->sbc_chunk_id] != NODEV) { bv->sbv_chunks_found--; sr_meta_getdevname(sc, bc->sbc_mm, devname, sizeof(devname)); printf("%s: found duplicate chunk %u for " "volume %u on device %s\n", DEVNAME(sc), bc->sbc_chunk_id, bv->sbv_volid, devname); } if (devs[bc->sbc_chunk_id] == NODEV || bc->sbc_metadata->ssd_ondisk > ondisk[bc->sbc_chunk_id]) { devs[bc->sbc_chunk_id] = bc->sbc_mm; ondisk[bc->sbc_chunk_id] = bc->sbc_metadata->ssd_ondisk; DNPRINTF(SR_D_META, "%s: using ondisk " "metadata version %llu for chunk %u\n", DEVNAME(sc), ondisk[bc->sbc_chunk_id], bc->sbc_chunk_id); } } if (bv->sbv_chunk_no != bv->sbv_chunks_found) { printf("%s: not all chunks were provided; " "attempting to bring volume %d online\n", DEVNAME(sc), bv->sbv_volid); } bcr.bc_level = bv->sbv_level; bcr.bc_dev_list_len = bv->sbv_chunk_no * sizeof(dev_t); bcr.bc_dev_list = devs; bcr.bc_flags = BIOC_SCDEVT | (bv->sbv_flags & BIOC_SCNOAUTOASSEMBLE); if ((bv->sbv_level == 'C' || bv->sbv_level == 0x1C) && bcmp(&sr_bootuuid, &bv->sbv_uuid, sizeof(sr_bootuuid)) == 0) data = sr_bootkey; rw_enter_write(&sc->sc_lock); bio_status_init(&sc->sc_status, &sc->sc_dev); sr_ioctl_createraid(sc, &bcr, 0, data); rw_exit_write(&sc->sc_lock); rv++; } /* done with metadata */ unwind: /* Free boot volumes and associated chunks. */ for (bv1 = SLIST_FIRST(&bvh); bv1 != NULL; bv1 = bv2) { bv2 = SLIST_NEXT(bv1, sbv_link); for (bc1 = SLIST_FIRST(&bv1->sbv_chunks); bc1 != NULL; bc1 = bc2) { bc2 = SLIST_NEXT(bc1, sbc_link); free(bc1->sbc_metadata, M_DEVBUF, sizeof(*bc1->sbc_metadata)); free(bc1, M_DEVBUF, sizeof(*bc1)); } free(bv1, M_DEVBUF, sizeof(*bv1)); } /* Free keydisks chunks. */ for (bc1 = SLIST_FIRST(&kdh); bc1 != NULL; bc1 = bc2) { bc2 = SLIST_NEXT(bc1, sbc_link); free(bc1->sbc_metadata, M_DEVBUF, sizeof(*bc1->sbc_metadata)); free(bc1, M_DEVBUF, sizeof(*bc1)); } /* Free unallocated chunks. */ for (bc1 = SLIST_FIRST(&bch); bc1 != NULL; bc1 = bc2) { bc2 = SLIST_NEXT(bc1, sbc_link); free(bc1->sbc_metadata, M_DEVBUF, sizeof(*bc1->sbc_metadata)); free(bc1, M_DEVBUF, sizeof(*bc1)); } while (!SLIST_EMPTY(&sdklist)) { sdk = SLIST_FIRST(&sdklist); SLIST_REMOVE_HEAD(&sdklist, sdk_link); free(sdk, M_DEVBUF, sizeof(*sdk)); } free(devs, M_DEVBUF, BIOC_CRMAXLEN * sizeof(dev_t)); free(ondisk, M_DEVBUF, BIOC_CRMAXLEN * sizeof(u_int64_t)); return (rv); } void sr_map_root(void) { struct sr_softc *sc = softraid0; struct sr_discipline *sd; struct sr_meta_opt_item *omi; struct sr_meta_boot *sbm; u_char duid[8]; int i; if (sc == NULL) return; DNPRINTF(SR_D_MISC, "%s: sr_map_root\n", DEVNAME(sc)); bzero(duid, sizeof(duid)); if (bcmp(rootduid, duid, sizeof(duid)) == 0) { DNPRINTF(SR_D_MISC, "%s: root duid is zero\n", DEVNAME(sc)); return; } TAILQ_FOREACH(sd, &sc->sc_dis_list, sd_link) { SLIST_FOREACH(omi, &sd->sd_meta_opt, omi_link) { if (omi->omi_som->som_type != SR_OPT_BOOT) continue; sbm = (struct sr_meta_boot *)omi->omi_som; for (i = 0; i < SR_MAX_BOOT_DISKS; i++) { if (bcmp(rootduid, sbm->sbm_boot_duid[i], sizeof(rootduid)) == 0) { memcpy(rootduid, sbm->sbm_root_duid, sizeof(rootduid)); DNPRINTF(SR_D_MISC, "%s: root duid " "mapped to %s\n", DEVNAME(sc), duid_format(rootduid)); return; } } } } } int sr_meta_native_probe(struct sr_softc *sc, struct sr_chunk *ch_entry) { struct disklabel label; char *devname; int error, part; u_int64_t size; DNPRINTF(SR_D_META, "%s: sr_meta_native_probe(%s)\n", DEVNAME(sc), ch_entry->src_devname); devname = ch_entry->src_devname; part = DISKPART(ch_entry->src_dev_mm); /* get disklabel */ error = VOP_IOCTL(ch_entry->src_vn, DIOCGDINFO, (caddr_t)&label, FREAD, NOCRED, curproc); if (error) { DNPRINTF(SR_D_META, "%s: %s can't obtain disklabel\n", DEVNAME(sc), devname); goto unwind; } memcpy(ch_entry->src_duid, label.d_uid, sizeof(ch_entry->src_duid)); /* make sure the partition is of the right type */ if (label.d_partitions[part].p_fstype != FS_RAID) { DNPRINTF(SR_D_META, "%s: %s partition not of type RAID (%d)\n", DEVNAME(sc), devname, label.d_partitions[part].p_fstype); goto unwind; } size = DL_SECTOBLK(&label, DL_GETPSIZE(&label.d_partitions[part])); if (size <= SR_DATA_OFFSET) { DNPRINTF(SR_D_META, "%s: %s partition too small\n", DEVNAME(sc), devname); goto unwind; } size -= SR_DATA_OFFSET; if (size > INT64_MAX) { DNPRINTF(SR_D_META, "%s: %s partition too large\n", DEVNAME(sc), devname); goto unwind; } ch_entry->src_size = size; ch_entry->src_secsize = label.d_secsize; DNPRINTF(SR_D_META, "%s: probe found %s size %lld\n", DEVNAME(sc), devname, (long long)size); return (SR_META_F_NATIVE); unwind: DNPRINTF(SR_D_META, "%s: invalid device: %s\n", DEVNAME(sc), devname ? devname : "nodev"); return (SR_META_F_INVALID); } int sr_meta_native_attach(struct sr_discipline *sd, int force) { struct sr_softc *sc = sd->sd_sc; struct sr_chunk_head *cl = &sd->sd_vol.sv_chunk_list; struct sr_metadata *md = NULL; struct sr_chunk *ch_entry, *ch_next; struct sr_uuid uuid; u_int64_t version = 0; int sr, not_sr, rv = 1, d, expected = -1, old_meta = 0; DNPRINTF(SR_D_META, "%s: sr_meta_native_attach\n", DEVNAME(sc)); md = malloc(SR_META_SIZE * DEV_BSIZE, M_DEVBUF, M_ZERO | M_NOWAIT); if (md == NULL) { sr_error(sc, "not enough memory for metadata buffer"); goto bad; } bzero(&uuid, sizeof uuid); sr = not_sr = d = 0; SLIST_FOREACH(ch_entry, cl, src_link) { if (ch_entry->src_dev_mm == NODEV) continue; if (sr_meta_native_read(sd, ch_entry->src_dev_mm, md, NULL)) { sr_error(sc, "could not read native metadata"); goto bad; } if (md->ssdi.ssd_magic == SR_MAGIC) { sr++; ch_entry->src_meta.scmi.scm_chunk_id = md->ssdi.ssd_chunk_id; if (d == 0) { memcpy(&uuid, &md->ssdi.ssd_uuid, sizeof uuid); expected = md->ssdi.ssd_chunk_no; version = md->ssd_ondisk; d++; continue; } else if (bcmp(&md->ssdi.ssd_uuid, &uuid, sizeof uuid)) { sr_error(sc, "not part of the same volume"); goto bad; } if (md->ssd_ondisk != version) { old_meta++; version = MAX(md->ssd_ondisk, version); } } else not_sr++; } if (sr && not_sr && !force) { sr_error(sc, "not all chunks are of the native metadata " "format"); goto bad; } /* mixed metadata versions; mark bad disks offline */ if (old_meta) { d = 0; for (ch_entry = SLIST_FIRST(cl); ch_entry != NULL; ch_entry = ch_next, d++) { ch_next = SLIST_NEXT(ch_entry, src_link); /* XXX do we want to read this again? */ if (ch_entry->src_dev_mm == NODEV) panic("src_dev_mm == NODEV"); if (sr_meta_native_read(sd, ch_entry->src_dev_mm, md, NULL)) sr_warn(sc, "could not read native metadata"); if (md->ssd_ondisk != version) sd->sd_vol.sv_chunks[d]->src_meta.scm_status = BIOC_SDOFFLINE; } } if (expected != sr && !force && expected != -1) { DNPRINTF(SR_D_META, "%s: not all chunks were provided, trying " "anyway\n", DEVNAME(sc)); } rv = 0; bad: free(md, M_DEVBUF, SR_META_SIZE * DEV_BSIZE); return (rv); } int sr_meta_native_read(struct sr_discipline *sd, dev_t dev, struct sr_metadata *md, void *fm) { #ifdef SR_DEBUG struct sr_softc *sc = sd->sd_sc; #endif DNPRINTF(SR_D_META, "%s: sr_meta_native_read(0x%x, %p)\n", DEVNAME(sc), dev, md); return (sr_meta_rw(sd, dev, md, B_READ)); } int sr_meta_native_write(struct sr_discipline *sd, dev_t dev, struct sr_metadata *md, void *fm) { #ifdef SR_DEBUG struct sr_softc *sc = sd->sd_sc; #endif DNPRINTF(SR_D_META, "%s: sr_meta_native_write(0x%x, %p)\n", DEVNAME(sc), dev, md); return (sr_meta_rw(sd, dev, md, B_WRITE)); } void sr_hotplug_register(struct sr_discipline *sd, void *func) { struct sr_hotplug_list *mhe; DNPRINTF(SR_D_MISC, "%s: sr_hotplug_register: %p\n", DEVNAME(sd->sd_sc), func); /* make sure we aren't on the list yet */ SLIST_FOREACH(mhe, &sr_hotplug_callbacks, shl_link) if (mhe->sh_hotplug == func) return; mhe = malloc(sizeof(struct sr_hotplug_list), M_DEVBUF, M_WAITOK | M_ZERO); mhe->sh_hotplug = func; mhe->sh_sd = sd; SLIST_INSERT_HEAD(&sr_hotplug_callbacks, mhe, shl_link); } void sr_hotplug_unregister(struct sr_discipline *sd, void *func) { struct sr_hotplug_list *mhe; DNPRINTF(SR_D_MISC, "%s: sr_hotplug_unregister: %s %p\n", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname, func); /* make sure we are on the list yet */ SLIST_FOREACH(mhe, &sr_hotplug_callbacks, shl_link) { if (mhe->sh_hotplug == func) break; } if (mhe != NULL) { SLIST_REMOVE(&sr_hotplug_callbacks, mhe, sr_hotplug_list, shl_link); free(mhe, M_DEVBUF, sizeof(*mhe)); } } void sr_disk_attach(struct disk *diskp, int action) { struct sr_hotplug_list *mhe; SLIST_FOREACH(mhe, &sr_hotplug_callbacks, shl_link) if (mhe->sh_sd->sd_ready) mhe->sh_hotplug(mhe->sh_sd, diskp, action); } int sr_match(struct device *parent, void *match, void *aux) { return (1); } void sr_attach(struct device *parent, struct device *self, void *aux) { struct sr_softc *sc = (void *)self; struct scsibus_attach_args saa; DNPRINTF(SR_D_MISC, "\n%s: sr_attach", DEVNAME(sc)); if (softraid0 == NULL) softraid0 = sc; rw_init(&sc->sc_lock, "sr_lock"); rw_init(&sc->sc_hs_lock, "sr_hs_lock"); SLIST_INIT(&sr_hotplug_callbacks); TAILQ_INIT(&sc->sc_dis_list); SLIST_INIT(&sc->sc_hotspare_list); #if NBIO > 0 if (bio_register(&sc->sc_dev, sr_bio_ioctl) != 0) printf("%s: controller registration failed", DEVNAME(sc)); #endif /* NBIO > 0 */ #ifndef SMALL_KERNEL strlcpy(sc->sc_sensordev.xname, DEVNAME(sc), sizeof(sc->sc_sensordev.xname)); sensordev_install(&sc->sc_sensordev); #endif /* SMALL_KERNEL */ printf("\n"); saa.saa_adapter_softc = sc; saa.saa_adapter = &sr_switch; saa.saa_adapter_target = SDEV_NO_ADAPTER_TARGET; saa.saa_adapter_buswidth = SR_MAX_LD; saa.saa_luns = 1; saa.saa_openings = 0; saa.saa_pool = NULL; saa.saa_quirks = saa.saa_flags = 0; saa.saa_wwpn = saa.saa_wwnn = 0; sc->sc_scsibus = (struct scsibus_softc *)config_found(&sc->sc_dev, &saa, scsiprint); softraid_disk_attach = sr_disk_attach; sr_boot_assembly(sc); explicit_bzero(sr_bootkey, sizeof(sr_bootkey)); } int sr_detach(struct device *self, int flags) { struct sr_softc *sc = (void *)self; int rv; DNPRINTF(SR_D_MISC, "%s: sr_detach\n", DEVNAME(sc)); softraid_disk_attach = NULL; sr_shutdown(0); #ifndef SMALL_KERNEL if (sc->sc_sensor_task != NULL) sensor_task_unregister(sc->sc_sensor_task); sensordev_deinstall(&sc->sc_sensordev); #endif /* SMALL_KERNEL */ if (sc->sc_scsibus != NULL) { rv = config_detach((struct device *)sc->sc_scsibus, flags); if (rv != 0) return (rv); sc->sc_scsibus = NULL; } return (0); } void sr_info(struct sr_softc *sc, const char *fmt, ...) { va_list ap; rw_assert_wrlock(&sc->sc_lock); va_start(ap, fmt); bio_status(&sc->sc_status, 0, BIO_MSG_INFO, fmt, &ap); va_end(ap); } void sr_warn(struct sr_softc *sc, const char *fmt, ...) { va_list ap; rw_assert_wrlock(&sc->sc_lock); va_start(ap, fmt); bio_status(&sc->sc_status, 1, BIO_MSG_WARN, fmt, &ap); va_end(ap); } void sr_error(struct sr_softc *sc, const char *fmt, ...) { va_list ap; rw_assert_wrlock(&sc->sc_lock); va_start(ap, fmt); bio_status(&sc->sc_status, 1, BIO_MSG_ERROR, fmt, &ap); va_end(ap); } int sr_ccb_alloc(struct sr_discipline *sd) { struct sr_ccb *ccb; int i; if (!sd) return (1); DNPRINTF(SR_D_CCB, "%s: sr_ccb_alloc\n", DEVNAME(sd->sd_sc)); if (sd->sd_ccb) return (1); sd->sd_ccb = mallocarray(sd->sd_max_wu, sd->sd_max_ccb_per_wu * sizeof(struct sr_ccb), M_DEVBUF, M_WAITOK | M_ZERO); TAILQ_INIT(&sd->sd_ccb_freeq); for (i = 0; i < sd->sd_max_wu * sd->sd_max_ccb_per_wu; i++) { ccb = &sd->sd_ccb[i]; ccb->ccb_dis = sd; sr_ccb_put(ccb); } DNPRINTF(SR_D_CCB, "%s: sr_ccb_alloc ccb: %d\n", DEVNAME(sd->sd_sc), sd->sd_max_wu * sd->sd_max_ccb_per_wu); return (0); } void sr_ccb_free(struct sr_discipline *sd) { struct sr_ccb *ccb; if (!sd) return; DNPRINTF(SR_D_CCB, "%s: sr_ccb_free %p\n", DEVNAME(sd->sd_sc), sd); while ((ccb = TAILQ_FIRST(&sd->sd_ccb_freeq)) != NULL) TAILQ_REMOVE(&sd->sd_ccb_freeq, ccb, ccb_link); free(sd->sd_ccb, M_DEVBUF, sd->sd_max_wu * sd->sd_max_ccb_per_wu * sizeof(struct sr_ccb)); } struct sr_ccb * sr_ccb_get(struct sr_discipline *sd) { struct sr_ccb *ccb; int s; s = splbio(); ccb = TAILQ_FIRST(&sd->sd_ccb_freeq); if (ccb) { TAILQ_REMOVE(&sd->sd_ccb_freeq, ccb, ccb_link); ccb->ccb_state = SR_CCB_INPROGRESS; } splx(s); DNPRINTF(SR_D_CCB, "%s: sr_ccb_get: %p\n", DEVNAME(sd->sd_sc), ccb); return (ccb); } void sr_ccb_put(struct sr_ccb *ccb) { struct sr_discipline *sd = ccb->ccb_dis; int s; DNPRINTF(SR_D_CCB, "%s: sr_ccb_put: %p\n", DEVNAME(sd->sd_sc), ccb); s = splbio(); ccb->ccb_wu = NULL; ccb->ccb_state = SR_CCB_FREE; ccb->ccb_target = -1; ccb->ccb_opaque = NULL; TAILQ_INSERT_TAIL(&sd->sd_ccb_freeq, ccb, ccb_link); splx(s); } struct sr_ccb * sr_ccb_rw(struct sr_discipline *sd, int chunk, daddr_t blkno, long len, u_int8_t *data, int xsflags, int ccbflags) { struct sr_chunk *sc = sd->sd_vol.sv_chunks[chunk]; struct sr_ccb *ccb = NULL; int s; ccb = sr_ccb_get(sd); if (ccb == NULL) goto out; ccb->ccb_flags = ccbflags; ccb->ccb_target = chunk; ccb->ccb_buf.b_flags = B_PHYS | B_CALL; if (ISSET(xsflags, SCSI_DATA_IN)) ccb->ccb_buf.b_flags |= B_READ; else ccb->ccb_buf.b_flags |= B_WRITE; ccb->ccb_buf.b_blkno = blkno + sd->sd_meta->ssd_data_blkno; ccb->ccb_buf.b_bcount = len; ccb->ccb_buf.b_bufsize = len; ccb->ccb_buf.b_resid = len; ccb->ccb_buf.b_data = data; ccb->ccb_buf.b_error = 0; ccb->ccb_buf.b_iodone = sd->sd_scsi_intr; ccb->ccb_buf.b_proc = curproc; ccb->ccb_buf.b_dev = sc->src_dev_mm; ccb->ccb_buf.b_vp = sc->src_vn; ccb->ccb_buf.b_bq = NULL; if (!ISSET(ccb->ccb_buf.b_flags, B_READ)) { s = splbio(); ccb->ccb_buf.b_vp->v_numoutput++; splx(s); } DNPRINTF(SR_D_DIS, "%s: %s %s ccb " "b_bcount %ld b_blkno %lld b_flags 0x%0lx b_data %p\n", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname, sd->sd_name, ccb->ccb_buf.b_bcount, (long long)ccb->ccb_buf.b_blkno, ccb->ccb_buf.b_flags, ccb->ccb_buf.b_data); out: return ccb; } void sr_ccb_done(struct sr_ccb *ccb) { struct sr_workunit *wu = ccb->ccb_wu; struct sr_discipline *sd = wu->swu_dis; struct sr_softc *sc = sd->sd_sc; DNPRINTF(SR_D_INTR, "%s: %s %s ccb done b_bcount %ld b_resid %zu" " b_flags 0x%0lx block %lld target %d\n", DEVNAME(sc), sd->sd_meta->ssd_devname, sd->sd_name, ccb->ccb_buf.b_bcount, ccb->ccb_buf.b_resid, ccb->ccb_buf.b_flags, (long long)ccb->ccb_buf.b_blkno, ccb->ccb_target); splassert(IPL_BIO); if (ccb->ccb_target == -1) panic("%s: invalid target on wu: %p", DEVNAME(sc), wu); if (ccb->ccb_buf.b_flags & B_ERROR) { DNPRINTF(SR_D_INTR, "%s: i/o error on block %lld target %d\n", DEVNAME(sc), (long long)ccb->ccb_buf.b_blkno, ccb->ccb_target); if (ISSET(sd->sd_capabilities, SR_CAP_REDUNDANT)) sd->sd_set_chunk_state(sd, ccb->ccb_target, BIOC_SDOFFLINE); else printf("%s: %s: i/o error %d @ %s block %lld\n", DEVNAME(sc), sd->sd_meta->ssd_devname, ccb->ccb_buf.b_error, sd->sd_name, (long long)ccb->ccb_buf.b_blkno); ccb->ccb_state = SR_CCB_FAILED; wu->swu_ios_failed++; } else { ccb->ccb_state = SR_CCB_OK; wu->swu_ios_succeeded++; } wu->swu_ios_complete++; } int sr_wu_alloc(struct sr_discipline *sd) { struct sr_workunit *wu; int i, no_wu; DNPRINTF(SR_D_WU, "%s: sr_wu_alloc %p %d\n", DEVNAME(sd->sd_sc), sd, sd->sd_max_wu); no_wu = sd->sd_max_wu; sd->sd_wu_pending = no_wu; mtx_init(&sd->sd_wu_mtx, IPL_BIO); TAILQ_INIT(&sd->sd_wu); TAILQ_INIT(&sd->sd_wu_freeq); TAILQ_INIT(&sd->sd_wu_pendq); TAILQ_INIT(&sd->sd_wu_defq); for (i = 0; i < no_wu; i++) { wu = malloc(sd->sd_wu_size, M_DEVBUF, M_WAITOK | M_ZERO); TAILQ_INSERT_TAIL(&sd->sd_wu, wu, swu_next); TAILQ_INIT(&wu->swu_ccb); wu->swu_dis = sd; task_set(&wu->swu_task, sr_wu_done_callback, wu); sr_wu_put(sd, wu); } return (0); } void sr_wu_free(struct sr_discipline *sd) { struct sr_workunit *wu; DNPRINTF(SR_D_WU, "%s: sr_wu_free %p\n", DEVNAME(sd->sd_sc), sd); while ((wu = TAILQ_FIRST(&sd->sd_wu_freeq)) != NULL) TAILQ_REMOVE(&sd->sd_wu_freeq, wu, swu_link); while ((wu = TAILQ_FIRST(&sd->sd_wu_pendq)) != NULL) TAILQ_REMOVE(&sd->sd_wu_pendq, wu, swu_link); while ((wu = TAILQ_FIRST(&sd->sd_wu_defq)) != NULL) TAILQ_REMOVE(&sd->sd_wu_defq, wu, swu_link); while ((wu = TAILQ_FIRST(&sd->sd_wu)) != NULL) { TAILQ_REMOVE(&sd->sd_wu, wu, swu_next); free(wu, M_DEVBUF, sd->sd_wu_size); } } void * sr_wu_get(void *xsd) { struct sr_discipline *sd = (struct sr_discipline *)xsd; struct sr_workunit *wu; mtx_enter(&sd->sd_wu_mtx); wu = TAILQ_FIRST(&sd->sd_wu_freeq); if (wu) { TAILQ_REMOVE(&sd->sd_wu_freeq, wu, swu_link); sd->sd_wu_pending++; } mtx_leave(&sd->sd_wu_mtx); DNPRINTF(SR_D_WU, "%s: sr_wu_get: %p\n", DEVNAME(sd->sd_sc), wu); return (wu); } void sr_wu_put(void *xsd, void *xwu) { struct sr_discipline *sd = (struct sr_discipline *)xsd; struct sr_workunit *wu = (struct sr_workunit *)xwu; DNPRINTF(SR_D_WU, "%s: sr_wu_put: %p\n", DEVNAME(sd->sd_sc), wu); sr_wu_release_ccbs(wu); sr_wu_init(sd, wu); mtx_enter(&sd->sd_wu_mtx); TAILQ_INSERT_TAIL(&sd->sd_wu_freeq, wu, swu_link); sd->sd_wu_pending--; mtx_leave(&sd->sd_wu_mtx); } void sr_wu_init(struct sr_discipline *sd, struct sr_workunit *wu) { int s; s = splbio(); if (wu->swu_cb_active == 1) panic("%s: sr_wu_init got active wu", DEVNAME(sd->sd_sc)); splx(s); wu->swu_xs = NULL; wu->swu_state = SR_WU_FREE; wu->swu_flags = 0; wu->swu_blk_start = 0; wu->swu_blk_end = 0; wu->swu_collider = NULL; } void sr_wu_enqueue_ccb(struct sr_workunit *wu, struct sr_ccb *ccb) { struct sr_discipline *sd = wu->swu_dis; int s; s = splbio(); if (wu->swu_cb_active == 1) panic("%s: sr_wu_enqueue_ccb got active wu", DEVNAME(sd->sd_sc)); ccb->ccb_wu = wu; wu->swu_io_count++; TAILQ_INSERT_TAIL(&wu->swu_ccb, ccb, ccb_link); splx(s); } void sr_wu_release_ccbs(struct sr_workunit *wu) { struct sr_ccb *ccb; /* Return all ccbs that are associated with this workunit. */ while ((ccb = TAILQ_FIRST(&wu->swu_ccb)) != NULL) { TAILQ_REMOVE(&wu->swu_ccb, ccb, ccb_link); sr_ccb_put(ccb); } wu->swu_io_count = 0; wu->swu_ios_complete = 0; wu->swu_ios_failed = 0; wu->swu_ios_succeeded = 0; } void sr_wu_done(struct sr_workunit *wu) { struct sr_discipline *sd = wu->swu_dis; DNPRINTF(SR_D_INTR, "%s: sr_wu_done count %d completed %d failed %d\n", DEVNAME(sd->sd_sc), wu->swu_io_count, wu->swu_ios_complete, wu->swu_ios_failed); if (wu->swu_ios_complete < wu->swu_io_count) return; task_add(sd->sd_taskq, &wu->swu_task); } void sr_wu_done_callback(void *xwu) { struct sr_workunit *wu = xwu; struct sr_discipline *sd = wu->swu_dis; struct scsi_xfer *xs = wu->swu_xs; struct sr_workunit *wup; int s; /* * The SR_WUF_DISCIPLINE or SR_WUF_REBUILD flag must be set if * the work unit is not associated with a scsi_xfer. */ KASSERT(xs != NULL || (wu->swu_flags & (SR_WUF_DISCIPLINE|SR_WUF_REBUILD))); s = splbio(); if (xs != NULL) { if (wu->swu_ios_failed) xs->error = XS_DRIVER_STUFFUP; else xs->error = XS_NOERROR; } if (sd->sd_scsi_wu_done) { if (sd->sd_scsi_wu_done(wu) == SR_WU_RESTART) goto done; } /* Remove work unit from pending queue. */ TAILQ_FOREACH(wup, &sd->sd_wu_pendq, swu_link) if (wup == wu) break; if (wup == NULL) panic("%s: wu %p not on pending queue", DEVNAME(sd->sd_sc), wu); TAILQ_REMOVE(&sd->sd_wu_pendq, wu, swu_link); if (wu->swu_collider) { if (wu->swu_ios_failed) sr_raid_recreate_wu(wu->swu_collider); /* XXX Should the collider be failed if this xs failed? */ sr_raid_startwu(wu->swu_collider); } /* * If a discipline provides its own sd_scsi_done function, then it * is responsible for calling sr_scsi_done() once I/O is complete. */ if (wu->swu_flags & SR_WUF_REBUILD) wu->swu_flags |= SR_WUF_REBUILDIOCOMP; if (wu->swu_flags & SR_WUF_WAKEUP) wakeup(wu); if (sd->sd_scsi_done) sd->sd_scsi_done(wu); else if (wu->swu_flags & SR_WUF_DISCIPLINE) sr_scsi_wu_put(sd, wu); else if (!(wu->swu_flags & SR_WUF_REBUILD)) sr_scsi_done(sd, xs); done: splx(s); } struct sr_workunit * sr_scsi_wu_get(struct sr_discipline *sd, int flags) { return scsi_io_get(&sd->sd_iopool, flags); } void sr_scsi_wu_put(struct sr_discipline *sd, struct sr_workunit *wu) { scsi_io_put(&sd->sd_iopool, wu); if (sd->sd_sync && sd->sd_wu_pending == 0) wakeup(sd); } void sr_scsi_done(struct sr_discipline *sd, struct scsi_xfer *xs) { DNPRINTF(SR_D_DIS, "%s: sr_scsi_done: xs %p\n", DEVNAME(sd->sd_sc), xs); if (xs->error == XS_NOERROR) xs->resid = 0; scsi_done(xs); if (sd->sd_sync && sd->sd_wu_pending == 0) wakeup(sd); } void sr_scsi_cmd(struct scsi_xfer *xs) { struct scsi_link *link = xs->sc_link; struct sr_softc *sc = link->bus->sb_adapter_softc; struct sr_workunit *wu = xs->io; struct sr_discipline *sd; DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd target %d xs %p flags %#x\n", DEVNAME(sc), link->target, xs, xs->flags); sd = sc->sc_targets[link->target]; if (sd == NULL) panic("%s: sr_scsi_cmd NULL discipline", DEVNAME(sc)); if (sd->sd_deleted) { printf("%s: %s device is being deleted, failing io\n", DEVNAME(sc), sd->sd_meta->ssd_devname); goto stuffup; } /* scsi layer *can* re-send wu without calling sr_wu_put(). */ sr_wu_release_ccbs(wu); sr_wu_init(sd, wu); wu->swu_state = SR_WU_INPROGRESS; wu->swu_xs = xs; switch (xs->cmd.opcode) { case READ_COMMAND: case READ_10: case READ_16: case WRITE_COMMAND: case WRITE_10: case WRITE_16: DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: READ/WRITE %02x\n", DEVNAME(sc), xs->cmd.opcode); if (sd->sd_scsi_rw(wu)) goto stuffup; break; case SYNCHRONIZE_CACHE: DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: SYNCHRONIZE_CACHE\n", DEVNAME(sc)); if (sd->sd_scsi_sync(wu)) goto stuffup; goto complete; case TEST_UNIT_READY: DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: TEST_UNIT_READY\n", DEVNAME(sc)); if (sd->sd_scsi_tur(wu)) goto stuffup; goto complete; case START_STOP: DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: START_STOP\n", DEVNAME(sc)); if (sd->sd_scsi_start_stop(wu)) goto stuffup; goto complete; case INQUIRY: DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: INQUIRY\n", DEVNAME(sc)); if (sd->sd_scsi_inquiry(wu)) goto stuffup; goto complete; case READ_CAPACITY: case READ_CAPACITY_16: DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd READ CAPACITY 0x%02x\n", DEVNAME(sc), xs->cmd.opcode); if (sd->sd_scsi_read_cap(wu)) goto stuffup; goto complete; case REQUEST_SENSE: DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd REQUEST SENSE\n", DEVNAME(sc)); if (sd->sd_scsi_req_sense(wu)) goto stuffup; goto complete; default: DNPRINTF(SR_D_CMD, "%s: unsupported scsi command %x\n", DEVNAME(sc), xs->cmd.opcode); /* XXX might need to add generic function to handle others */ goto stuffup; } return; stuffup: if (sd->sd_scsi_sense.error_code) { xs->error = XS_SENSE; memcpy(&xs->sense, &sd->sd_scsi_sense, sizeof(xs->sense)); bzero(&sd->sd_scsi_sense, sizeof(sd->sd_scsi_sense)); } else { xs->error = XS_DRIVER_STUFFUP; } complete: sr_scsi_done(sd, xs); } int sr_scsi_probe(struct scsi_link *link) { struct sr_softc *sc = link->bus->sb_adapter_softc; struct sr_discipline *sd; KASSERT(link->target < SR_MAX_LD && link->lun == 0); sd = sc->sc_targets[link->target]; if (sd == NULL) return (ENODEV); link->pool = &sd->sd_iopool; if (sd->sd_openings) link->openings = sd->sd_openings(sd); else link->openings = sd->sd_max_wu; return (0); } int sr_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag) { struct sr_softc *sc = link->bus->sb_adapter_softc; struct sr_discipline *sd; sd = sc->sc_targets[link->target]; if (sd == NULL) return (ENODEV); DNPRINTF(SR_D_IOCTL, "%s: %s sr_scsi_ioctl cmd: %#lx\n", DEVNAME(sc), sd->sd_meta->ssd_devname, cmd); /* Pass bio ioctls through to the bio handler. */ if (IOCGROUP(cmd) == 'B') return (sr_bio_handler(sc, sd, cmd, (struct bio *)addr)); switch (cmd) { case DIOCGCACHE: case DIOCSCACHE: return (EOPNOTSUPP); default: return (ENOTTY); } } int sr_bio_ioctl(struct device *dev, u_long cmd, caddr_t addr) { struct sr_softc *sc = (struct sr_softc *) dev; DNPRINTF(SR_D_IOCTL, "%s: sr_bio_ioctl\n", DEVNAME(sc)); return sr_bio_handler(sc, NULL, cmd, (struct bio *)addr); } int sr_bio_handler(struct sr_softc *sc, struct sr_discipline *sd, u_long cmd, struct bio *bio) { int rv = 0; DNPRINTF(SR_D_IOCTL, "%s: sr_bio_handler ", DEVNAME(sc)); rw_enter_write(&sc->sc_lock); bio_status_init(&sc->sc_status, &sc->sc_dev); switch (cmd) { case BIOCINQ: DNPRINTF(SR_D_IOCTL, "inq\n"); rv = sr_ioctl_inq(sc, (struct bioc_inq *)bio); break; case BIOCVOL: DNPRINTF(SR_D_IOCTL, "vol\n"); rv = sr_ioctl_vol(sc, (struct bioc_vol *)bio); break; case BIOCDISK: DNPRINTF(SR_D_IOCTL, "disk\n"); rv = sr_ioctl_disk(sc, (struct bioc_disk *)bio); break; case BIOCALARM: DNPRINTF(SR_D_IOCTL, "alarm\n"); /*rv = sr_ioctl_alarm(sc, (struct bioc_alarm *)bio); */ break; case BIOCBLINK: DNPRINTF(SR_D_IOCTL, "blink\n"); /*rv = sr_ioctl_blink(sc, (struct bioc_blink *)bio); */ break; case BIOCSETSTATE: DNPRINTF(SR_D_IOCTL, "setstate\n"); rv = sr_ioctl_setstate(sc, (struct bioc_setstate *)bio); break; case BIOCCREATERAID: DNPRINTF(SR_D_IOCTL, "createraid\n"); rv = sr_ioctl_createraid(sc, (struct bioc_createraid *)bio, 1, NULL); break; case BIOCDELETERAID: DNPRINTF(SR_D_IOCTL, "deleteraid\n"); rv = sr_ioctl_deleteraid(sc, sd, (struct bioc_deleteraid *)bio); break; case BIOCDISCIPLINE: DNPRINTF(SR_D_IOCTL, "discipline\n"); rv = sr_ioctl_discipline(sc, sd, (struct bioc_discipline *)bio); break; case BIOCINSTALLBOOT: DNPRINTF(SR_D_IOCTL, "installboot\n"); rv = sr_ioctl_installboot(sc, sd, (struct bioc_installboot *)bio); break; default: DNPRINTF(SR_D_IOCTL, "invalid ioctl\n"); rv = ENOTTY; } sc->sc_status.bs_status = (rv ? BIO_STATUS_ERROR : BIO_STATUS_SUCCESS); if (sc->sc_status.bs_msg_count > 0) rv = 0; memcpy(&bio->bio_status, &sc->sc_status, sizeof(struct bio_status)); rw_exit_write(&sc->sc_lock); return (rv); } int sr_ioctl_inq(struct sr_softc *sc, struct bioc_inq *bi) { struct sr_discipline *sd; int vol = 0, disk = 0; TAILQ_FOREACH(sd, &sc->sc_dis_list, sd_link) { vol++; disk += sd->sd_meta->ssdi.ssd_chunk_no; } strlcpy(bi->bi_dev, sc->sc_dev.dv_xname, sizeof(bi->bi_dev)); bi->bi_novol = vol + sc->sc_hotspare_no; bi->bi_nodisk = disk + sc->sc_hotspare_no; return (0); } int sr_ioctl_vol(struct sr_softc *sc, struct bioc_vol *bv) { int vol = -1, rv = EINVAL; struct sr_discipline *sd; struct sr_chunk *hotspare; TAILQ_FOREACH(sd, &sc->sc_dis_list, sd_link) { vol++; if (vol != bv->bv_volid) continue; bv->bv_status = sd->sd_vol_status; bv->bv_size = sd->sd_meta->ssdi.ssd_size << DEV_BSHIFT; bv->bv_level = sd->sd_meta->ssdi.ssd_level; bv->bv_nodisk = sd->sd_meta->ssdi.ssd_chunk_no; #ifdef CRYPTO if (sd->sd_meta->ssdi.ssd_level == 'C' && sd->mds.mdd_crypto.key_disk != NULL) bv->bv_nodisk++; else if (sd->sd_meta->ssdi.ssd_level == 0x1C && sd->mds.mdd_raid1c.sr1c_crypto.key_disk != NULL) bv->bv_nodisk++; #endif if (bv->bv_status == BIOC_SVREBUILD) bv->bv_percent = sr_rebuild_percent(sd); strlcpy(bv->bv_dev, sd->sd_meta->ssd_devname, sizeof(bv->bv_dev)); strlcpy(bv->bv_vendor, sd->sd_meta->ssdi.ssd_vendor, sizeof(bv->bv_vendor)); rv = 0; goto done; } /* Check hotspares list. */ SLIST_FOREACH(hotspare, &sc->sc_hotspare_list, src_link) { vol++; if (vol != bv->bv_volid) continue; bv->bv_status = BIOC_SVONLINE; bv->bv_size = hotspare->src_meta.scmi.scm_size << DEV_BSHIFT; bv->bv_level = -1; /* Hotspare. */ bv->bv_nodisk = 1; strlcpy(bv->bv_dev, hotspare->src_meta.scmi.scm_devname, sizeof(bv->bv_dev)); strlcpy(bv->bv_vendor, hotspare->src_meta.scmi.scm_devname, sizeof(bv->bv_vendor)); rv = 0; goto done; } done: return (rv); } int sr_ioctl_disk(struct sr_softc *sc, struct bioc_disk *bd) { struct sr_discipline *sd; struct sr_chunk *src, *hotspare; int vol = -1, rv = EINVAL; if (bd->bd_diskid < 0) goto done; TAILQ_FOREACH(sd, &sc->sc_dis_list, sd_link) { vol++; if (vol != bd->bd_volid) continue; if (bd->bd_diskid < sd->sd_meta->ssdi.ssd_chunk_no) src = sd->sd_vol.sv_chunks[bd->bd_diskid]; #ifdef CRYPTO else if (bd->bd_diskid == sd->sd_meta->ssdi.ssd_chunk_no && sd->sd_meta->ssdi.ssd_level == 'C' && sd->mds.mdd_crypto.key_disk != NULL) src = sd->mds.mdd_crypto.key_disk; else if (bd->bd_diskid == sd->sd_meta->ssdi.ssd_chunk_no && sd->sd_meta->ssdi.ssd_level == 0x1C && sd->mds.mdd_raid1c.sr1c_crypto.key_disk != NULL) src = sd->mds.mdd_crypto.key_disk; #endif else break; bd->bd_status = src->src_meta.scm_status; bd->bd_size = src->src_meta.scmi.scm_size << DEV_BSHIFT; bd->bd_channel = vol; bd->bd_target = bd->bd_diskid; strlcpy(bd->bd_vendor, src->src_meta.scmi.scm_devname, sizeof(bd->bd_vendor)); rv = 0; goto done; } /* Check hotspares list. */ SLIST_FOREACH(hotspare, &sc->sc_hotspare_list, src_link) { vol++; if (vol != bd->bd_volid) continue; if (bd->bd_diskid != 0) break; bd->bd_status = hotspare->src_meta.scm_status; bd->bd_size = hotspare->src_meta.scmi.scm_size << DEV_BSHIFT; bd->bd_channel = vol; bd->bd_target = bd->bd_diskid; strlcpy(bd->bd_vendor, hotspare->src_meta.scmi.scm_devname, sizeof(bd->bd_vendor)); rv = 0; goto done; } done: return (rv); } int sr_ioctl_setstate(struct sr_softc *sc, struct bioc_setstate *bs) { int rv = EINVAL; int vol = -1, found, c; struct sr_discipline *sd; struct sr_chunk *ch_entry; struct sr_chunk_head *cl; if (bs->bs_other_id_type == BIOC_SSOTHER_UNUSED) goto done; if (bs->bs_status == BIOC_SSHOTSPARE) { rv = sr_hotspare(sc, (dev_t)bs->bs_other_id); goto done; } TAILQ_FOREACH(sd, &sc->sc_dis_list, sd_link) { vol++; if (vol == bs->bs_volid) break; } if (sd == NULL) goto done; switch (bs->bs_status) { case BIOC_SSOFFLINE: /* Take chunk offline */ found = c = 0; cl = &sd->sd_vol.sv_chunk_list; SLIST_FOREACH(ch_entry, cl, src_link) { if (ch_entry->src_dev_mm == bs->bs_other_id) { found = 1; break; } c++; } if (found == 0) { sr_error(sc, "chunk not part of array"); goto done; } /* XXX: check current state first */ sd->sd_set_chunk_state(sd, c, BIOC_SDOFFLINE); if (sr_meta_save(sd, SR_META_DIRTY)) { sr_error(sc, "could not save metadata for %s", sd->sd_meta->ssd_devname); goto done; } rv = 0; break; case BIOC_SDSCRUB: break; case BIOC_SSREBUILD: rv = sr_rebuild_init(sd, (dev_t)bs->bs_other_id, 0); break; default: sr_error(sc, "unsupported state request %d", bs->bs_status); } done: return (rv); } int sr_chunk_in_use(struct sr_softc *sc, dev_t dev) { struct sr_discipline *sd; struct sr_chunk *chunk; int i; DNPRINTF(SR_D_MISC, "%s: sr_chunk_in_use(%d)\n", DEVNAME(sc), dev); if (dev == NODEV) return BIOC_SDINVALID; /* See if chunk is already in use. */ TAILQ_FOREACH(sd, &sc->sc_dis_list, sd_link) { for (i = 0; i < sd->sd_meta->ssdi.ssd_chunk_no; i++) { chunk = sd->sd_vol.sv_chunks[i]; if (chunk->src_dev_mm == dev) return chunk->src_meta.scm_status; } } /* Check hotspares list. */ SLIST_FOREACH(chunk, &sc->sc_hotspare_list, src_link) if (chunk->src_dev_mm == dev) return chunk->src_meta.scm_status; return BIOC_SDINVALID; } int sr_hotspare(struct sr_softc *sc, dev_t dev) { struct sr_discipline *sd = NULL; struct sr_metadata *sm = NULL; struct sr_meta_chunk *hm; struct sr_chunk_head *cl; struct sr_chunk *chunk, *last, *hotspare = NULL; struct sr_uuid uuid; struct disklabel label; struct vnode *vn; u_int64_t size; char devname[32]; int rv = EINVAL; int c, part, open = 0; /* * Add device to global hotspares list. */ sr_meta_getdevname(sc, dev, devname, sizeof(devname)); /* Make sure chunk is not already in use. */ c = sr_chunk_in_use(sc, dev); if (c != BIOC_SDINVALID && c != BIOC_SDOFFLINE) { if (c == BIOC_SDHOTSPARE) sr_error(sc, "%s is already a hotspare", devname); else sr_error(sc, "%s is already in use", devname); goto done; } /* XXX - See if there is an existing degraded volume... */ /* Open device. */ if (bdevvp(dev, &vn)) { sr_error(sc, "sr_hotspare: cannot allocate vnode"); goto done; } if (VOP_OPEN(vn, FREAD | FWRITE, NOCRED, curproc)) { DNPRINTF(SR_D_META,"%s: sr_hotspare cannot open %s\n", DEVNAME(sc), devname); vput(vn); goto fail; } open = 1; /* close dev on error */ /* Get partition details. */ part = DISKPART(dev); if (VOP_IOCTL(vn, DIOCGDINFO, (caddr_t)&label, FREAD, NOCRED, curproc)) { DNPRINTF(SR_D_META, "%s: sr_hotspare ioctl failed\n", DEVNAME(sc)); goto fail; } if (label.d_partitions[part].p_fstype != FS_RAID) { sr_error(sc, "%s partition not of type RAID (%d)", devname, label.d_partitions[part].p_fstype); goto fail; } /* Calculate partition size. */ size = DL_SECTOBLK(&label, DL_GETPSIZE(&label.d_partitions[part])); if (size <= SR_DATA_OFFSET) { DNPRINTF(SR_D_META, "%s: %s partition too small\n", DEVNAME(sc), devname); goto fail; } size -= SR_DATA_OFFSET; if (size > INT64_MAX) { DNPRINTF(SR_D_META, "%s: %s partition too large\n", DEVNAME(sc), devname); goto fail; } /* * Create and populate chunk metadata. */ sr_uuid_generate(&uuid); hotspare = malloc(sizeof(struct sr_chunk), M_DEVBUF, M_WAITOK | M_ZERO); hotspare->src_dev_mm = dev; hotspare->src_vn = vn; strlcpy(hotspare->src_devname, devname, sizeof(hm->scmi.scm_devname)); hotspare->src_size = size; hm = &hotspare->src_meta; hm->scmi.scm_volid = SR_HOTSPARE_VOLID; hm->scmi.scm_chunk_id = 0; hm->scmi.scm_size = size; hm->scmi.scm_coerced_size = size; strlcpy(hm->scmi.scm_devname, devname, sizeof(hm->scmi.scm_devname)); memcpy(&hm->scmi.scm_uuid, &uuid, sizeof(struct sr_uuid)); sr_checksum(sc, hm, &hm->scm_checksum, sizeof(struct sr_meta_chunk_invariant)); hm->scm_status = BIOC_SDHOTSPARE; /* * Create and populate our own discipline and metadata. */ sm = malloc(sizeof(struct sr_metadata), M_DEVBUF, M_WAITOK | M_ZERO); sm->ssdi.ssd_magic = SR_MAGIC; sm->ssdi.ssd_version = SR_META_VERSION; sm->ssd_ondisk = 0; sm->ssdi.ssd_vol_flags = 0; memcpy(&sm->ssdi.ssd_uuid, &uuid, sizeof(struct sr_uuid)); sm->ssdi.ssd_chunk_no = 1; sm->ssdi.ssd_volid = SR_HOTSPARE_VOLID; sm->ssdi.ssd_level = SR_HOTSPARE_LEVEL; sm->ssdi.ssd_size = size; sm->ssdi.ssd_secsize = label.d_secsize; strlcpy(sm->ssdi.ssd_vendor, "OPENBSD", sizeof(sm->ssdi.ssd_vendor)); snprintf(sm->ssdi.ssd_product, sizeof(sm->ssdi.ssd_product), "SR %s", "HOTSPARE"); snprintf(sm->ssdi.ssd_revision, sizeof(sm->ssdi.ssd_revision), "%03d", SR_META_VERSION); sd = malloc(sizeof(struct sr_discipline), M_DEVBUF, M_WAITOK | M_ZERO); sd->sd_sc = sc; sd->sd_meta = sm; sd->sd_meta_type = SR_META_F_NATIVE; sd->sd_vol_status = BIOC_SVONLINE; strlcpy(sd->sd_name, "HOTSPARE", sizeof(sd->sd_name)); SLIST_INIT(&sd->sd_meta_opt); /* Add chunk to volume. */ sd->sd_vol.sv_chunks = malloc(sizeof(struct sr_chunk *), M_DEVBUF, M_WAITOK | M_ZERO); sd->sd_vol.sv_chunks[0] = hotspare; SLIST_INIT(&sd->sd_vol.sv_chunk_list); SLIST_INSERT_HEAD(&sd->sd_vol.sv_chunk_list, hotspare, src_link); /* Save metadata. */ if (sr_meta_save(sd, SR_META_DIRTY)) { sr_error(sc, "could not save metadata to %s", devname); goto fail; } /* * Add chunk to hotspare list. */ rw_enter_write(&sc->sc_hs_lock); cl = &sc->sc_hotspare_list; if (SLIST_EMPTY(cl)) SLIST_INSERT_HEAD(cl, hotspare, src_link); else { SLIST_FOREACH(chunk, cl, src_link) last = chunk; SLIST_INSERT_AFTER(last, hotspare, src_link); } sc->sc_hotspare_no++; rw_exit_write(&sc->sc_hs_lock); rv = 0; goto done; fail: free(hotspare, M_DEVBUF, sizeof(*hotspare)); done: if (sd) free(sd->sd_vol.sv_chunks, M_DEVBUF, sizeof(sd->sd_vol.sv_chunks)); free(sd, M_DEVBUF, sizeof(*sd)); free(sm, M_DEVBUF, sizeof(*sm)); if (open) { VOP_CLOSE(vn, FREAD | FWRITE, NOCRED, curproc); vput(vn); } return (rv); } void sr_hotspare_rebuild_callback(void *xsd) { struct sr_discipline *sd = xsd; sr_hotspare_rebuild(sd); } void sr_hotspare_rebuild(struct sr_discipline *sd) { struct sr_softc *sc = sd->sd_sc; struct sr_chunk_head *cl; struct sr_chunk *hotspare, *chunk = NULL; struct sr_workunit *wu; struct sr_ccb *ccb; int i, s, cid, busy; /* * Attempt to locate a hotspare and initiate rebuild. */ /* Find first offline chunk. */ for (cid = 0; cid < sd->sd_meta->ssdi.ssd_chunk_no; cid++) { if (sd->sd_vol.sv_chunks[cid]->src_meta.scm_status == BIOC_SDOFFLINE) { chunk = sd->sd_vol.sv_chunks[cid]; break; } } if (chunk == NULL) { printf("%s: no offline chunk found on %s!\n", DEVNAME(sc), sd->sd_meta->ssd_devname); return; } /* See if we have a suitable hotspare... */ rw_enter_write(&sc->sc_hs_lock); cl = &sc->sc_hotspare_list; SLIST_FOREACH(hotspare, cl, src_link) if (hotspare->src_size >= chunk->src_size && hotspare->src_secsize <= sd->sd_meta->ssdi.ssd_secsize) break; if (hotspare != NULL) { printf("%s: %s volume degraded, will attempt to " "rebuild on hotspare %s\n", DEVNAME(sc), sd->sd_meta->ssd_devname, hotspare->src_devname); /* * Ensure that all pending I/O completes on the failed chunk * before trying to initiate a rebuild. */ i = 0; do { busy = 0; s = splbio(); TAILQ_FOREACH(wu, &sd->sd_wu_pendq, swu_link) { TAILQ_FOREACH(ccb, &wu->swu_ccb, ccb_link) { if (ccb->ccb_target == cid) busy = 1; } } TAILQ_FOREACH(wu, &sd->sd_wu_defq, swu_link) { TAILQ_FOREACH(ccb, &wu->swu_ccb, ccb_link) { if (ccb->ccb_target == cid) busy = 1; } } splx(s); if (busy) { tsleep_nsec(sd, PRIBIO, "sr_hotspare", SEC_TO_NSEC(1)); i++; } } while (busy && i < 120); DNPRINTF(SR_D_META, "%s: waited %i seconds for I/O to " "complete on failed chunk %s\n", DEVNAME(sc), i, chunk->src_devname); if (busy) { printf("%s: pending I/O failed to complete on " "failed chunk %s, hotspare rebuild aborted...\n", DEVNAME(sc), chunk->src_devname); goto done; } s = splbio(); rw_enter_write(&sc->sc_lock); bio_status_init(&sc->sc_status, &sc->sc_dev); if (sr_rebuild_init(sd, hotspare->src_dev_mm, 1) == 0) { /* Remove hotspare from available list. */ sc->sc_hotspare_no--; SLIST_REMOVE(cl, hotspare, sr_chunk, src_link); free(hotspare, M_DEVBUF, sizeof(*hotspare)); } rw_exit_write(&sc->sc_lock); splx(s); } done: rw_exit_write(&sc->sc_hs_lock); } int sr_rebuild_init(struct sr_discipline *sd, dev_t dev, int hotspare) { struct sr_softc *sc = sd->sd_sc; struct sr_chunk *chunk = NULL; struct sr_meta_chunk *meta; struct disklabel label; struct vnode *vn; u_int64_t size; int64_t csize; char devname[32]; int rv = EINVAL, open = 0; int cid, i, part, status; /* * Attempt to initiate a rebuild onto the specified device. */ if (!(sd->sd_capabilities & SR_CAP_REBUILD)) { sr_error(sc, "discipline does not support rebuild"); goto done; } /* make sure volume is in the right state */ if (sd->sd_vol_status == BIOC_SVREBUILD) { sr_error(sc, "rebuild already in progress"); goto done; } if (sd->sd_vol_status != BIOC_SVDEGRADED) { sr_error(sc, "volume not degraded"); goto done; } /* Find first offline chunk. */ for (cid = 0; cid < sd->sd_meta->ssdi.ssd_chunk_no; cid++) { if (sd->sd_vol.sv_chunks[cid]->src_meta.scm_status == BIOC_SDOFFLINE) { chunk = sd->sd_vol.sv_chunks[cid]; break; } } if (chunk == NULL) { sr_error(sc, "no offline chunks available to rebuild"); goto done; } /* Get coerced size from another online chunk. */ csize = 0; for (i = 0; i < sd->sd_meta->ssdi.ssd_chunk_no; i++) { if (sd->sd_vol.sv_chunks[i]->src_meta.scm_status == BIOC_SDONLINE) { meta = &sd->sd_vol.sv_chunks[i]->src_meta; csize = meta->scmi.scm_coerced_size; break; } } if (csize == 0) { sr_error(sc, "no online chunks available for rebuild"); goto done; } sr_meta_getdevname(sc, dev, devname, sizeof(devname)); if (bdevvp(dev, &vn)) { printf("%s: sr_rebuild_init: can't allocate vnode\n", DEVNAME(sc)); goto done; } if (VOP_OPEN(vn, FREAD | FWRITE, NOCRED, curproc)) { DNPRINTF(SR_D_META,"%s: sr_ioctl_setstate can't " "open %s\n", DEVNAME(sc), devname); vput(vn); goto done; } open = 1; /* close dev on error */ /* Get disklabel and check partition. */ part = DISKPART(dev); if (VOP_IOCTL(vn, DIOCGDINFO, (caddr_t)&label, FREAD, NOCRED, curproc)) { DNPRINTF(SR_D_META, "%s: sr_ioctl_setstate ioctl failed\n", DEVNAME(sc)); goto done; } if (label.d_partitions[part].p_fstype != FS_RAID) { sr_error(sc, "%s partition not of type RAID (%d)", devname, label.d_partitions[part].p_fstype); goto done; } /* Is the partition large enough? */ size = DL_SECTOBLK(&label, DL_GETPSIZE(&label.d_partitions[part])); if (size <= sd->sd_meta->ssd_data_blkno) { sr_error(sc, "%s: %s partition too small", DEVNAME(sc), devname); goto done; } size -= sd->sd_meta->ssd_data_blkno; if (size > INT64_MAX) { sr_error(sc, "%s: %s partition too large", DEVNAME(sc), devname); goto done; } if (size < csize) { sr_error(sc, "%s partition too small, at least %lld bytes " "required", devname, (long long)(csize << DEV_BSHIFT)); goto done; } else if (size > csize) sr_warn(sc, "%s partition too large, wasting %lld bytes", devname, (long long)((size - csize) << DEV_BSHIFT)); if (label.d_secsize > sd->sd_meta->ssdi.ssd_secsize) { sr_error(sc, "%s sector size too large, <= %u bytes " "required", devname, sd->sd_meta->ssdi.ssd_secsize); goto done; } /* Ensure that this chunk is not already in use. */ status = sr_chunk_in_use(sc, dev); if (status != BIOC_SDINVALID && status != BIOC_SDOFFLINE && !(hotspare && status == BIOC_SDHOTSPARE)) { sr_error(sc, "%s is already in use", devname); goto done; } /* Reset rebuild counter since we rebuilding onto a new chunk. */ sd->sd_meta->ssd_rebuild = 0; open = 0; /* leave dev open from here on out */ /* Fix up chunk. */ memcpy(chunk->src_duid, label.d_uid, sizeof(chunk->src_duid)); chunk->src_dev_mm = dev; chunk->src_vn = vn; /* Reconstruct metadata. */ meta = &chunk->src_meta; meta->scmi.scm_volid = sd->sd_meta->ssdi.ssd_volid; meta->scmi.scm_chunk_id = cid; strlcpy(meta->scmi.scm_devname, devname, sizeof(meta->scmi.scm_devname)); meta->scmi.scm_size = size; meta->scmi.scm_coerced_size = csize; memcpy(&meta->scmi.scm_uuid, &sd->sd_meta->ssdi.ssd_uuid, sizeof(meta->scmi.scm_uuid)); sr_checksum(sc, meta, &meta->scm_checksum, sizeof(struct sr_meta_chunk_invariant)); sd->sd_set_chunk_state(sd, cid, BIOC_SDREBUILD); if (sr_meta_save(sd, SR_META_DIRTY)) { sr_error(sc, "could not save metadata to %s", devname); open = 1; goto done; } sr_warn(sc, "rebuild of %s started on %s", sd->sd_meta->ssd_devname, devname); sd->sd_reb_abort = 0; kthread_create_deferred(sr_rebuild_start, sd); rv = 0; done: if (open) { VOP_CLOSE(vn, FREAD | FWRITE, NOCRED, curproc); vput(vn); } return (rv); } int sr_rebuild_percent(struct sr_discipline *sd) { daddr_t rb, sz; sz = sd->sd_meta->ssdi.ssd_size; rb = sd->sd_meta->ssd_rebuild; if (rb > 0) return (100 - ((sz * 100 - rb * 100) / sz) - 1); return (0); } void sr_roam_chunks(struct sr_discipline *sd) { struct sr_softc *sc = sd->sd_sc; struct sr_chunk *chunk; struct sr_meta_chunk *meta; int roamed = 0; /* Have any chunks roamed? */ SLIST_FOREACH(chunk, &sd->sd_vol.sv_chunk_list, src_link) { meta = &chunk->src_meta; if (strncmp(meta->scmi.scm_devname, chunk->src_devname, sizeof(meta->scmi.scm_devname))) { printf("%s: roaming device %s -> %s\n", DEVNAME(sc), meta->scmi.scm_devname, chunk->src_devname); strlcpy(meta->scmi.scm_devname, chunk->src_devname, sizeof(meta->scmi.scm_devname)); roamed++; } } if (roamed) sr_meta_save(sd, SR_META_DIRTY); } int sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, int user, void *data) { struct sr_meta_opt_item *omi; struct sr_chunk_head *cl; struct sr_discipline *sd = NULL; struct sr_chunk *ch_entry; struct scsi_link *link; struct device *dev; char *uuid, devname[32]; dev_t *dt = NULL; int i, no_chunk, rv = EINVAL, target, vol; int no_meta; DNPRINTF(SR_D_IOCTL, "%s: sr_ioctl_createraid(%d)\n", DEVNAME(sc), user); /* user input */ if (bc->bc_dev_list_len > BIOC_CRMAXLEN) goto unwind; dt = malloc(bc->bc_dev_list_len, M_DEVBUF, M_WAITOK | M_ZERO); if (user) { if (copyin(bc->bc_dev_list, dt, bc->bc_dev_list_len) != 0) goto unwind; } else memcpy(dt, bc->bc_dev_list, bc->bc_dev_list_len); /* Initialise discipline. */ sd = malloc(sizeof(struct sr_discipline), M_DEVBUF, M_WAITOK | M_ZERO); sd->sd_sc = sc; SLIST_INIT(&sd->sd_meta_opt); sd->sd_taskq = taskq_create("srdis", 1, IPL_BIO, 0); if (sd->sd_taskq == NULL) { sr_error(sc, "could not create discipline taskq"); goto unwind; } if (sr_discipline_init(sd, bc->bc_level)) { sr_error(sc, "could not initialize discipline"); goto unwind; } no_chunk = bc->bc_dev_list_len / sizeof(dev_t); cl = &sd->sd_vol.sv_chunk_list; SLIST_INIT(cl); /* Ensure that chunks are not already in use. */ for (i = 0; i < no_chunk; i++) { if (sr_chunk_in_use(sc, dt[i]) != BIOC_SDINVALID) { sr_meta_getdevname(sc, dt[i], devname, sizeof(devname)); sr_error(sc, "chunk %s already in use", devname); goto unwind; } } sd->sd_meta_type = sr_meta_probe(sd, dt, no_chunk); if (sd->sd_meta_type == SR_META_F_INVALID) { sr_error(sc, "invalid metadata format"); goto unwind; } if (sr_meta_attach(sd, no_chunk, bc->bc_flags & BIOC_SCFORCE)) goto unwind; /* force the raid volume by clearing metadata region */ if (bc->bc_flags & BIOC_SCFORCE) { /* make sure disk isn't up and running */ if (sr_meta_read(sd)) if (sr_already_assembled(sd)) { uuid = sr_uuid_format( &sd->sd_meta->ssdi.ssd_uuid); sr_error(sc, "disk %s is currently in use; " "cannot force create", uuid); free(uuid, M_DEVBUF, 37); goto unwind; } if (sr_meta_clear(sd)) { sr_error(sc, "failed to clear metadata"); goto unwind; } } no_meta = sr_meta_read(sd); if (no_meta == -1) { /* Corrupt metadata on one or more chunks. */ sr_error(sc, "one of the chunks has corrupt metadata; " "aborting assembly"); goto unwind; } else if (no_meta == 0) { /* Initialise volume and chunk metadata. */ sr_meta_init(sd, bc->bc_level, no_chunk); sd->sd_vol_status = BIOC_SVONLINE; sd->sd_meta_flags = bc->bc_flags & BIOC_SCNOAUTOASSEMBLE; if (sd->sd_create) { if ((i = sd->sd_create(sd, bc, no_chunk, sd->sd_vol.sv_chunk_minsz))) { rv = i; goto unwind; } } sr_meta_init_complete(sd); DNPRINTF(SR_D_IOCTL, "%s: sr_ioctl_createraid: vol_size: %lld\n", DEVNAME(sc), sd->sd_meta->ssdi.ssd_size); /* Warn if we've wasted chunk space due to coercing. */ if ((sd->sd_capabilities & SR_CAP_NON_COERCED) == 0 && sd->sd_vol.sv_chunk_minsz != sd->sd_vol.sv_chunk_maxsz) sr_warn(sc, "chunk sizes are not equal; up to %llu " "blocks wasted per chunk", sd->sd_vol.sv_chunk_maxsz - sd->sd_vol.sv_chunk_minsz); } else { /* Ensure we are assembling the correct # of chunks. */ if (bc->bc_level == 0x1C && sd->sd_meta->ssdi.ssd_chunk_no > no_chunk) { sr_warn(sc, "trying to bring up %s degraded", sd->sd_meta->ssd_devname); } else if (sd->sd_meta->ssdi.ssd_chunk_no != no_chunk) { sr_error(sc, "volume chunk count does not match metadata " "chunk count"); goto unwind; } /* Ensure metadata level matches requested assembly level. */ if (sd->sd_meta->ssdi.ssd_level != bc->bc_level) { sr_error(sc, "volume level does not match metadata " "level"); goto unwind; } if (sr_already_assembled(sd)) { uuid = sr_uuid_format(&sd->sd_meta->ssdi.ssd_uuid); sr_error(sc, "disk %s already assembled", uuid); free(uuid, M_DEVBUF, 37); goto unwind; } if (user == 0 && sd->sd_meta_flags & BIOC_SCNOAUTOASSEMBLE) { DNPRINTF(SR_D_META, "%s: disk not auto assembled from " "metadata\n", DEVNAME(sc)); goto unwind; } if (no_meta != no_chunk) sr_warn(sc, "trying to bring up %s degraded", sd->sd_meta->ssd_devname); if (sd->sd_meta->ssd_meta_flags & SR_META_DIRTY) sr_warn(sc, "%s was not shutdown properly", sd->sd_meta->ssd_devname); SLIST_FOREACH(omi, &sd->sd_meta_opt, omi_link) if (sd->sd_meta_opt_handler == NULL || sd->sd_meta_opt_handler(sd, omi->omi_som) != 0) sr_meta_opt_handler(sd, omi->omi_som); if (sd->sd_assemble) { if ((i = sd->sd_assemble(sd, bc, no_chunk, data))) { rv = i; goto unwind; } } DNPRINTF(SR_D_META, "%s: disk assembled from metadata\n", DEVNAME(sc)); } /* Metadata MUST be fully populated by this point. */ TAILQ_INSERT_TAIL(&sc->sc_dis_list, sd, sd_link); /* Allocate all resources. */ if ((rv = sd->sd_alloc_resources(sd))) goto unwind; /* Adjust flags if necessary. */ if ((sd->sd_capabilities & SR_CAP_AUTO_ASSEMBLE) && (bc->bc_flags & BIOC_SCNOAUTOASSEMBLE) != (sd->sd_meta->ssdi.ssd_vol_flags & BIOC_SCNOAUTOASSEMBLE)) { sd->sd_meta->ssdi.ssd_vol_flags &= ~BIOC_SCNOAUTOASSEMBLE; sd->sd_meta->ssdi.ssd_vol_flags |= bc->bc_flags & BIOC_SCNOAUTOASSEMBLE; } if (sd->sd_capabilities & SR_CAP_SYSTEM_DISK) { /* Initialise volume state. */ sd->sd_set_vol_state(sd); if (sd->sd_vol_status == BIOC_SVOFFLINE) { sr_error(sc, "%s is offline, will not be brought " "online", sd->sd_meta->ssd_devname); goto unwind; } /* Setup SCSI iopool. */ scsi_iopool_init(&sd->sd_iopool, sd, sr_wu_get, sr_wu_put); /* * All checks passed - return ENXIO if volume cannot be created. */ rv = ENXIO; /* * Find a free target. * * XXX: We reserve sd_target == 0 to indicate the * discipline is not linked into sc->sc_targets, so begin * the search with target = 1. */ for (target = 1; target < SR_MAX_LD; target++) if (sc->sc_targets[target] == NULL) break; if (target == SR_MAX_LD) { sr_error(sc, "no free target for %s", sd->sd_meta->ssd_devname); goto unwind; } /* Clear sense data. */ bzero(&sd->sd_scsi_sense, sizeof(sd->sd_scsi_sense)); /* Attach discipline and get midlayer to probe it. */ sd->sd_target = target; sc->sc_targets[target] = sd; if (scsi_probe_lun(sc->sc_scsibus, target, 0) != 0) { sr_error(sc, "scsi_probe_lun failed"); sc->sc_targets[target] = NULL; sd->sd_target = 0; goto unwind; } link = scsi_get_link(sc->sc_scsibus, target, 0); if (link == NULL) goto unwind; dev = link->device_softc; DNPRINTF(SR_D_IOCTL, "%s: sr device added: %s at target %d\n", DEVNAME(sc), dev->dv_xname, sd->sd_target); /* XXX - Count volumes, not targets. */ for (i = 0, vol = -1; i <= sd->sd_target; i++) if (sc->sc_targets[i]) vol++; rv = 0; if (sd->sd_meta->ssd_devname[0] != '\0' && strncmp(sd->sd_meta->ssd_devname, dev->dv_xname, sizeof(dev->dv_xname))) sr_warn(sc, "volume %s is roaming, it used to be %s, " "updating metadata", dev->dv_xname, sd->sd_meta->ssd_devname); /* Populate remaining volume metadata. */ sd->sd_meta->ssdi.ssd_volid = vol; strlcpy(sd->sd_meta->ssd_devname, dev->dv_xname, sizeof(sd->sd_meta->ssd_devname)); sr_info(sc, "%s volume attached as %s", sd->sd_name, sd->sd_meta->ssd_devname); /* Update device name on any roaming chunks. */ sr_roam_chunks(sd); #ifndef SMALL_KERNEL if (sr_sensors_create(sd)) sr_warn(sc, "unable to create sensor for %s", dev->dv_xname); #endif /* SMALL_KERNEL */ } else { /* This volume does not attach as a system disk. */ ch_entry = SLIST_FIRST(cl); /* XXX */ strlcpy(sd->sd_meta->ssd_devname, ch_entry->src_devname, sizeof(sd->sd_meta->ssd_devname)); if (sd->sd_start_discipline(sd)) goto unwind; } /* Save current metadata to disk. */ rv = sr_meta_save(sd, SR_META_DIRTY); if (sd->sd_vol_status == BIOC_SVREBUILD) kthread_create_deferred(sr_rebuild_start, sd); sd->sd_ready = 1; free(dt, M_DEVBUF, bc->bc_dev_list_len); return (rv); unwind: free(dt, M_DEVBUF, bc->bc_dev_list_len); sr_discipline_shutdown(sd, 0, 0); if (rv == EAGAIN) rv = 0; return (rv); } int sr_ioctl_deleteraid(struct sr_softc *sc, struct sr_discipline *sd, struct bioc_deleteraid *bd) { int rv = 1; DNPRINTF(SR_D_IOCTL, "%s: sr_ioctl_deleteraid %s\n", DEVNAME(sc), bd->bd_dev); if (sd == NULL && (sd = sr_find_discipline(sc, bd->bd_dev)) == NULL) { sr_error(sc, "volume %s not found", bd->bd_dev); goto bad; } /* * XXX Better check for mounted file systems and refuse to detach any * volume that is actively in use. */ if (bcmp(&sr_bootuuid, &sd->sd_meta->ssdi.ssd_uuid, sizeof(sr_bootuuid)) == 0) { sr_error(sc, "refusing to delete boot volume"); goto bad; } sd->sd_deleted = 1; sd->sd_meta->ssdi.ssd_vol_flags = BIOC_SCNOAUTOASSEMBLE; sr_discipline_shutdown(sd, 1, 0); rv = 0; bad: return (rv); } int sr_ioctl_discipline(struct sr_softc *sc, struct sr_discipline *sd, struct bioc_discipline *bd) { int rv = 1; /* Dispatch a discipline specific ioctl. */ DNPRINTF(SR_D_IOCTL, "%s: sr_ioctl_discipline %s\n", DEVNAME(sc), bd->bd_dev); if (sd == NULL && (sd = sr_find_discipline(sc, bd->bd_dev)) == NULL) { sr_error(sc, "volume %s not found", bd->bd_dev); goto bad; } if (sd->sd_ioctl_handler) rv = sd->sd_ioctl_handler(sd, bd); bad: return (rv); } int sr_ioctl_installboot(struct sr_softc *sc, struct sr_discipline *sd, struct bioc_installboot *bb) { void *bootblk = NULL, *bootldr = NULL; struct sr_chunk *chunk; struct sr_meta_opt_item *omi; struct sr_meta_boot *sbm; struct disk *dk; u_int32_t bbs = 0, bls = 0, secsize; u_char duid[8]; int rv = EINVAL; int i; DNPRINTF(SR_D_IOCTL, "%s: sr_ioctl_installboot %s\n", DEVNAME(sc), bb->bb_dev); if (sd == NULL && (sd = sr_find_discipline(sc, bb->bb_dev)) == NULL) { sr_error(sc, "volume %s not found", bb->bb_dev); goto done; } TAILQ_FOREACH(dk, &disklist, dk_link) if (!strncmp(dk->dk_name, bb->bb_dev, sizeof(bb->bb_dev))) break; if (dk == NULL || dk->dk_label == NULL || duid_iszero(dk->dk_label->d_uid)) { sr_error(sc, "failed to get DUID for softraid volume"); goto done; } memcpy(duid, dk->dk_label->d_uid, sizeof(duid)); /* Ensure that boot storage area is large enough. */ if (sd->sd_meta->ssd_data_blkno < (SR_BOOT_OFFSET + SR_BOOT_SIZE)) { sr_error(sc, "insufficient boot storage"); goto done; } if (bb->bb_bootblk_size > SR_BOOT_BLOCKS_SIZE * DEV_BSIZE) { sr_error(sc, "boot block too large (%d > %d)", bb->bb_bootblk_size, SR_BOOT_BLOCKS_SIZE * DEV_BSIZE); goto done; } if (bb->bb_bootldr_size > SR_BOOT_LOADER_SIZE * DEV_BSIZE) { sr_error(sc, "boot loader too large (%d > %d)", bb->bb_bootldr_size, SR_BOOT_LOADER_SIZE * DEV_BSIZE); goto done; } secsize = sd->sd_meta->ssdi.ssd_secsize; /* Copy in boot block. */ bbs = howmany(bb->bb_bootblk_size, secsize) * secsize; bootblk = malloc(bbs, M_DEVBUF, M_WAITOK | M_ZERO); if (copyin(bb->bb_bootblk, bootblk, bb->bb_bootblk_size) != 0) goto done; /* Copy in boot loader. */ bls = howmany(bb->bb_bootldr_size, secsize) * secsize; bootldr = malloc(bls, M_DEVBUF, M_WAITOK | M_ZERO); if (copyin(bb->bb_bootldr, bootldr, bb->bb_bootldr_size) != 0) goto done; /* Create or update optional meta for bootable volumes. */ SLIST_FOREACH(omi, &sd->sd_meta_opt, omi_link) if (omi->omi_som->som_type == SR_OPT_BOOT) break; if (omi == NULL) { omi = malloc(sizeof(struct sr_meta_opt_item), M_DEVBUF, M_WAITOK | M_ZERO); omi->omi_som = malloc(sizeof(struct sr_meta_boot), M_DEVBUF, M_WAITOK | M_ZERO); omi->omi_som->som_type = SR_OPT_BOOT; omi->omi_som->som_length = sizeof(struct sr_meta_boot); SLIST_INSERT_HEAD(&sd->sd_meta_opt, omi, omi_link); sd->sd_meta->ssdi.ssd_opt_no++; } sbm = (struct sr_meta_boot *)omi->omi_som; memcpy(sbm->sbm_root_duid, duid, sizeof(sbm->sbm_root_duid)); bzero(&sbm->sbm_boot_duid, sizeof(sbm->sbm_boot_duid)); sbm->sbm_bootblk_size = bbs; sbm->sbm_bootldr_size = bls; DNPRINTF(SR_D_IOCTL, "sr_ioctl_installboot: root duid is %s\n", duid_format(sbm->sbm_root_duid)); /* Save boot block and boot loader to each chunk. */ for (i = 0; i < sd->sd_meta->ssdi.ssd_chunk_no; i++) { chunk = sd->sd_vol.sv_chunks[i]; if (chunk->src_meta.scm_status != BIOC_SDONLINE && chunk->src_meta.scm_status != BIOC_SDREBUILD) continue; if (i < SR_MAX_BOOT_DISKS) memcpy(&sbm->sbm_boot_duid[i], chunk->src_duid, sizeof(sbm->sbm_boot_duid[i])); /* Save boot blocks. */ DNPRINTF(SR_D_IOCTL, "sr_ioctl_installboot: saving boot block to %s " "(%u bytes)\n", chunk->src_devname, bbs); if (sr_rw(sc, chunk->src_dev_mm, bootblk, bbs, SR_BOOT_BLOCKS_OFFSET, B_WRITE)) { sr_error(sc, "failed to write boot block"); goto done; } /* Save boot loader.*/ DNPRINTF(SR_D_IOCTL, "sr_ioctl_installboot: saving boot loader to %s " "(%u bytes)\n", chunk->src_devname, bls); if (sr_rw(sc, chunk->src_dev_mm, bootldr, bls, SR_BOOT_LOADER_OFFSET, B_WRITE)) { sr_error(sc, "failed to write boot loader"); goto done; } } /* XXX - Install boot block on disk - MD code. */ /* Mark volume as bootable and save metadata. */ sd->sd_meta->ssdi.ssd_vol_flags |= BIOC_SCBOOTABLE; if (sr_meta_save(sd, SR_META_DIRTY)) { sr_error(sc, "could not save metadata to %s", DEVNAME(sc)); goto done; } rv = 0; done: free(bootblk, M_DEVBUF, bbs); free(bootldr, M_DEVBUF, bls); return (rv); } void sr_chunks_unwind(struct sr_softc *sc, struct sr_chunk_head *cl) { struct sr_chunk *ch_entry, *ch_next; DNPRINTF(SR_D_IOCTL, "%s: sr_chunks_unwind\n", DEVNAME(sc)); if (!cl) return; for (ch_entry = SLIST_FIRST(cl); ch_entry != NULL; ch_entry = ch_next) { ch_next = SLIST_NEXT(ch_entry, src_link); DNPRINTF(SR_D_IOCTL, "%s: sr_chunks_unwind closing: %s\n", DEVNAME(sc), ch_entry->src_devname); if (ch_entry->src_vn) { /* * XXX - explicitly lock the vnode until we can resolve * the problem introduced by vnode aliasing... specfs * has no locking, whereas ufs/ffs does! */ vn_lock(ch_entry->src_vn, LK_EXCLUSIVE | LK_RETRY); VOP_CLOSE(ch_entry->src_vn, FREAD | FWRITE, NOCRED, curproc); vput(ch_entry->src_vn); } free(ch_entry, M_DEVBUF, sizeof(*ch_entry)); } SLIST_INIT(cl); } void sr_discipline_free(struct sr_discipline *sd) { struct sr_softc *sc; struct sr_discipline *sdtmp1; struct sr_meta_opt_head *som; struct sr_meta_opt_item *omi, *omi_next; if (!sd) return; sc = sd->sd_sc; DNPRINTF(SR_D_DIS, "%s: sr_discipline_free %s\n", DEVNAME(sc), sd->sd_meta ? sd->sd_meta->ssd_devname : "nodev"); if (sd->sd_free_resources) sd->sd_free_resources(sd); free(sd->sd_vol.sv_chunks, M_DEVBUF, 0); free(sd->sd_meta, M_DEVBUF, SR_META_SIZE * DEV_BSIZE); free(sd->sd_meta_foreign, M_DEVBUF, smd[sd->sd_meta_type].smd_size); som = &sd->sd_meta_opt; for (omi = SLIST_FIRST(som); omi != NULL; omi = omi_next) { omi_next = SLIST_NEXT(omi, omi_link); free(omi->omi_som, M_DEVBUF, 0); free(omi, M_DEVBUF, sizeof(*omi)); } if (sd->sd_target != 0) { KASSERT(sc->sc_targets[sd->sd_target] == sd); sc->sc_targets[sd->sd_target] = NULL; } TAILQ_FOREACH(sdtmp1, &sc->sc_dis_list, sd_link) { if (sdtmp1 == sd) break; } if (sdtmp1 != NULL) TAILQ_REMOVE(&sc->sc_dis_list, sd, sd_link); explicit_bzero(sd, sizeof *sd); free(sd, M_DEVBUF, sizeof(*sd)); } void sr_discipline_shutdown(struct sr_discipline *sd, int meta_save, int dying) { struct sr_softc *sc; int ret, s; if (!sd) return; sc = sd->sd_sc; DNPRINTF(SR_D_DIS, "%s: sr_discipline_shutdown %s\n", DEVNAME(sc), sd->sd_meta ? sd->sd_meta->ssd_devname : "nodev"); /* If rebuilding, abort rebuild and drain I/O. */ if (sd->sd_reb_active) { sd->sd_reb_abort = 1; while (sd->sd_reb_active) tsleep_nsec(sd, PWAIT, "sr_shutdown", MSEC_TO_NSEC(1)); } if (meta_save) sr_meta_save(sd, 0); s = splbio(); sd->sd_ready = 0; /* make sure there isn't a sync pending and yield */ wakeup(sd); while (sd->sd_sync || sd->sd_must_flush) { ret = tsleep_nsec(&sd->sd_sync, MAXPRI, "sr_down", SEC_TO_NSEC(60)); if (ret == EWOULDBLOCK) break; } if (dying == -1) { sd->sd_ready = 1; splx(s); return; } #ifndef SMALL_KERNEL sr_sensors_delete(sd); #endif /* SMALL_KERNEL */ if (sd->sd_target != 0) scsi_detach_lun(sc->sc_scsibus, sd->sd_target, 0, dying ? 0 : DETACH_FORCE); sr_chunks_unwind(sc, &sd->sd_vol.sv_chunk_list); if (sd->sd_taskq) taskq_destroy(sd->sd_taskq); sr_discipline_free(sd); splx(s); } int sr_discipline_init(struct sr_discipline *sd, int level) { int rv = 1; /* Initialise discipline function pointers with defaults. */ sd->sd_alloc_resources = sr_alloc_resources; sd->sd_assemble = NULL; sd->sd_create = NULL; sd->sd_free_resources = sr_free_resources; sd->sd_ioctl_handler = NULL; sd->sd_openings = NULL; sd->sd_meta_opt_handler = NULL; sd->sd_rebuild = sr_rebuild; sd->sd_scsi_inquiry = sr_raid_inquiry; sd->sd_scsi_read_cap = sr_raid_read_cap; sd->sd_scsi_tur = sr_raid_tur; sd->sd_scsi_req_sense = sr_raid_request_sense; sd->sd_scsi_start_stop = sr_raid_start_stop; sd->sd_scsi_sync = sr_raid_sync; sd->sd_scsi_rw = NULL; sd->sd_scsi_intr = sr_raid_intr; sd->sd_scsi_wu_done = NULL; sd->sd_scsi_done = NULL; sd->sd_set_chunk_state = sr_set_chunk_state; sd->sd_set_vol_state = sr_set_vol_state; sd->sd_start_discipline = NULL; task_set(&sd->sd_meta_save_task, sr_meta_save_callback, sd); task_set(&sd->sd_hotspare_rebuild_task, sr_hotspare_rebuild_callback, sd); sd->sd_wu_size = sizeof(struct sr_workunit); switch (level) { case 0: sr_raid0_discipline_init(sd); break; case 1: sr_raid1_discipline_init(sd); break; case 5: sr_raid5_discipline_init(sd); break; case 6: sr_raid6_discipline_init(sd); break; #ifdef CRYPTO case 'C': sr_crypto_discipline_init(sd); break; case 0x1C: sr_raid1c_discipline_init(sd); break; #endif case 'c': sr_concat_discipline_init(sd); break; default: goto bad; } rv = 0; bad: return (rv); } int sr_raid_inquiry(struct sr_workunit *wu) { struct sr_discipline *sd = wu->swu_dis; struct scsi_xfer *xs = wu->swu_xs; struct scsi_inquiry *cdb = (struct scsi_inquiry *)&xs->cmd; struct scsi_inquiry_data inq; DNPRINTF(SR_D_DIS, "%s: sr_raid_inquiry\n", DEVNAME(sd->sd_sc)); if (xs->cmdlen != sizeof(*cdb)) return (EINVAL); if (ISSET(cdb->flags, SI_EVPD)) return (EOPNOTSUPP); bzero(&inq, sizeof(inq)); inq.device = T_DIRECT; inq.dev_qual2 = 0; inq.version = SCSI_REV_2; inq.response_format = SID_SCSI2_RESPONSE; inq.additional_length = SID_SCSI2_ALEN; inq.flags |= SID_CmdQue; strlcpy(inq.vendor, sd->sd_meta->ssdi.ssd_vendor, sizeof(inq.vendor)); strlcpy(inq.product, sd->sd_meta->ssdi.ssd_product, sizeof(inq.product)); strlcpy(inq.revision, sd->sd_meta->ssdi.ssd_revision, sizeof(inq.revision)); scsi_copy_internal_data(xs, &inq, sizeof(inq)); return (0); } int sr_raid_read_cap(struct sr_workunit *wu) { struct sr_discipline *sd = wu->swu_dis; struct scsi_xfer *xs = wu->swu_xs; struct scsi_read_cap_data rcd; struct scsi_read_cap_data_16 rcd16; u_int64_t addr; int rv = 1; u_int32_t secsize; DNPRINTF(SR_D_DIS, "%s: sr_raid_read_cap\n", DEVNAME(sd->sd_sc)); secsize = sd->sd_meta->ssdi.ssd_secsize; addr = ((sd->sd_meta->ssdi.ssd_size * DEV_BSIZE) / secsize) - 1; if (xs->cmd.opcode == READ_CAPACITY) { bzero(&rcd, sizeof(rcd)); if (addr > 0xffffffffllu) _lto4b(0xffffffff, rcd.addr); else _lto4b(addr, rcd.addr); _lto4b(secsize, rcd.length); scsi_copy_internal_data(xs, &rcd, sizeof(rcd)); rv = 0; } else if (xs->cmd.opcode == READ_CAPACITY_16) { bzero(&rcd16, sizeof(rcd16)); _lto8b(addr, rcd16.addr); _lto4b(secsize, rcd16.length); scsi_copy_internal_data(xs, &rcd16, sizeof(rcd16)); rv = 0; } return (rv); } int sr_raid_tur(struct sr_workunit *wu) { struct sr_discipline *sd = wu->swu_dis; DNPRINTF(SR_D_DIS, "%s: sr_raid_tur\n", DEVNAME(sd->sd_sc)); if (sd->sd_vol_status == BIOC_SVOFFLINE) { sd->sd_scsi_sense.error_code = SSD_ERRCODE_CURRENT; sd->sd_scsi_sense.flags = SKEY_NOT_READY; sd->sd_scsi_sense.add_sense_code = 0x04; sd->sd_scsi_sense.add_sense_code_qual = 0x11; sd->sd_scsi_sense.extra_len = 4; return (1); } else if (sd->sd_vol_status == BIOC_SVINVALID) { sd->sd_scsi_sense.error_code = SSD_ERRCODE_CURRENT; sd->sd_scsi_sense.flags = SKEY_HARDWARE_ERROR; sd->sd_scsi_sense.add_sense_code = 0x05; sd->sd_scsi_sense.add_sense_code_qual = 0x00; sd->sd_scsi_sense.extra_len = 4; return (1); } return (0); } int sr_raid_request_sense(struct sr_workunit *wu) { struct sr_discipline *sd = wu->swu_dis; struct scsi_xfer *xs = wu->swu_xs; DNPRINTF(SR_D_DIS, "%s: sr_raid_request_sense\n", DEVNAME(sd->sd_sc)); /* use latest sense data */ memcpy(&xs->sense, &sd->sd_scsi_sense, sizeof(xs->sense)); /* clear sense data */ bzero(&sd->sd_scsi_sense, sizeof(sd->sd_scsi_sense)); return (0); } int sr_raid_start_stop(struct sr_workunit *wu) { struct scsi_xfer *xs = wu->swu_xs; struct scsi_start_stop *ss = (struct scsi_start_stop *)&xs->cmd; DNPRINTF(SR_D_DIS, "%s: sr_raid_start_stop\n", DEVNAME(wu->swu_dis->sd_sc)); if (!ss) return (1); /* * do nothing! * a softraid discipline should always reflect correct status */ return (0); } int sr_raid_sync(struct sr_workunit *wu) { struct sr_discipline *sd = wu->swu_dis; int s, ret, rv = 0, ios; DNPRINTF(SR_D_DIS, "%s: sr_raid_sync\n", DEVNAME(sd->sd_sc)); /* when doing a fake sync don't count the wu */ ios = (wu->swu_flags & SR_WUF_FAKE) ? 0 : 1; s = splbio(); sd->sd_sync = 1; while (sd->sd_wu_pending > ios) { ret = tsleep_nsec(sd, PRIBIO, "sr_sync", SEC_TO_NSEC(15)); if (ret == EWOULDBLOCK) { DNPRINTF(SR_D_DIS, "%s: sr_raid_sync timeout\n", DEVNAME(sd->sd_sc)); rv = 1; break; } } sd->sd_sync = 0; splx(s); wakeup(&sd->sd_sync); return (rv); } void sr_raid_intr(struct buf *bp) { struct sr_ccb *ccb = (struct sr_ccb *)bp; struct sr_workunit *wu = ccb->ccb_wu; #ifdef SR_DEBUG struct sr_discipline *sd = wu->swu_dis; struct scsi_xfer *xs = wu->swu_xs; #endif int s; DNPRINTF(SR_D_INTR, "%s: %s %s intr bp %p xs %p\n", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname, sd->sd_name, bp, xs); s = splbio(); sr_ccb_done(ccb); sr_wu_done(wu); splx(s); } void sr_schedule_wu(struct sr_workunit *wu) { struct sr_discipline *sd = wu->swu_dis; struct sr_workunit *wup; int s; DNPRINTF(SR_D_WU, "sr_schedule_wu: schedule wu %p state %i " "flags 0x%x\n", wu, wu->swu_state, wu->swu_flags); KASSERT(wu->swu_io_count > 0); s = splbio(); /* Construct the work unit, do not schedule it. */ if (wu->swu_state == SR_WU_CONSTRUCT) goto queued; /* Deferred work unit being reconstructed, do not start. */ if (wu->swu_state == SR_WU_REQUEUE) goto queued; /* Current work unit failed, restart. */ if (wu->swu_state == SR_WU_RESTART) goto start; if (wu->swu_state != SR_WU_INPROGRESS) panic("sr_schedule_wu: work unit not in progress (state %i)", wu->swu_state); /* Walk queue backwards and fill in collider if we have one. */ TAILQ_FOREACH_REVERSE(wup, &sd->sd_wu_pendq, sr_wu_list, swu_link) { if (wu->swu_blk_end < wup->swu_blk_start || wup->swu_blk_end < wu->swu_blk_start) continue; /* Defer work unit due to LBA collision. */ DNPRINTF(SR_D_WU, "sr_schedule_wu: deferring work unit %p\n", wu); wu->swu_state = SR_WU_DEFERRED; while (wup->swu_collider) wup = wup->swu_collider; wup->swu_collider = wu; TAILQ_INSERT_TAIL(&sd->sd_wu_defq, wu, swu_link); sd->sd_wu_collisions++; goto queued; } start: sr_raid_startwu(wu); queued: splx(s); } void sr_raid_startwu(struct sr_workunit *wu) { struct sr_discipline *sd = wu->swu_dis; struct sr_ccb *ccb; DNPRINTF(SR_D_WU, "sr_raid_startwu: start wu %p\n", wu); splassert(IPL_BIO); if (wu->swu_state == SR_WU_DEFERRED) { TAILQ_REMOVE(&sd->sd_wu_defq, wu, swu_link); wu->swu_state = SR_WU_INPROGRESS; } if (wu->swu_state != SR_WU_RESTART) TAILQ_INSERT_TAIL(&sd->sd_wu_pendq, wu, swu_link); /* Start all of the individual I/Os. */ if (wu->swu_cb_active == 1) panic("%s: sr_startwu_callback", DEVNAME(sd->sd_sc)); wu->swu_cb_active = 1; TAILQ_FOREACH(ccb, &wu->swu_ccb, ccb_link) VOP_STRATEGY(ccb->ccb_buf.b_vp, &ccb->ccb_buf); wu->swu_cb_active = 0; } void sr_raid_recreate_wu(struct sr_workunit *wu) { struct sr_discipline *sd = wu->swu_dis; struct sr_workunit *wup = wu; /* * Recreate a work unit by releasing the associated CCBs and reissuing * the SCSI I/O request. This process is then repeated for all of the * colliding work units. */ do { sr_wu_release_ccbs(wup); wup->swu_state = SR_WU_REQUEUE; if (sd->sd_scsi_rw(wup)) panic("could not requeue I/O"); wup = wup->swu_collider; } while (wup); } int sr_alloc_resources(struct sr_discipline *sd) { if (sr_wu_alloc(sd)) { sr_error(sd->sd_sc, "unable to allocate work units"); return (ENOMEM); } if (sr_ccb_alloc(sd)) { sr_error(sd->sd_sc, "unable to allocate ccbs"); return (ENOMEM); } return (0); } void sr_free_resources(struct sr_discipline *sd) { sr_wu_free(sd); sr_ccb_free(sd); } void sr_set_chunk_state(struct sr_discipline *sd, int c, int new_state) { int old_state, s; DNPRINTF(SR_D_STATE, "%s: %s: %s: sr_set_chunk_state %d -> %d\n", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname, sd->sd_vol.sv_chunks[c]->src_meta.scmi.scm_devname, c, new_state); /* ok to go to splbio since this only happens in error path */ s = splbio(); old_state = sd->sd_vol.sv_chunks[c]->src_meta.scm_status; /* multiple IOs to the same chunk that fail will come through here */ if (old_state == new_state) goto done; switch (old_state) { case BIOC_SDONLINE: if (new_state == BIOC_SDOFFLINE) break; else goto die; break; case BIOC_SDOFFLINE: goto die; default: die: splx(s); /* XXX */ panic("%s: %s: %s: invalid chunk state transition %d -> %d", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname, sd->sd_vol.sv_chunks[c]->src_meta.scmi.scm_devname, old_state, new_state); /* NOTREACHED */ } sd->sd_vol.sv_chunks[c]->src_meta.scm_status = new_state; sd->sd_set_vol_state(sd); sd->sd_must_flush = 1; task_add(systq, &sd->sd_meta_save_task); done: splx(s); } void sr_set_vol_state(struct sr_discipline *sd) { int states[SR_MAX_STATES]; int new_state, i, nd; int old_state = sd->sd_vol_status; u_int32_t s; DNPRINTF(SR_D_STATE, "%s: %s: sr_set_vol_state\n", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname); nd = sd->sd_meta->ssdi.ssd_chunk_no; for (i = 0; i < SR_MAX_STATES; i++) states[i] = 0; for (i = 0; i < nd; i++) { s = sd->sd_vol.sv_chunks[i]->src_meta.scm_status; if (s >= SR_MAX_STATES) panic("%s: %s: %s: invalid chunk state", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname, sd->sd_vol.sv_chunks[i]->src_meta.scmi.scm_devname); states[s]++; } if (states[BIOC_SDONLINE] == nd) new_state = BIOC_SVONLINE; else new_state = BIOC_SVOFFLINE; DNPRINTF(SR_D_STATE, "%s: %s: sr_set_vol_state %d -> %d\n", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname, old_state, new_state); switch (old_state) { case BIOC_SVONLINE: if (new_state == BIOC_SVOFFLINE || new_state == BIOC_SVONLINE) break; else goto die; break; case BIOC_SVOFFLINE: /* XXX this might be a little too much */ goto die; default: die: panic("%s: %s: invalid volume state transition %d -> %d", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname, old_state, new_state); /* NOTREACHED */ } sd->sd_vol_status = new_state; } void * sr_block_get(struct sr_discipline *sd, long length) { return dma_alloc(length, PR_NOWAIT | PR_ZERO); } void sr_block_put(struct sr_discipline *sd, void *ptr, int length) { dma_free(ptr, length); } void sr_checksum_print(u_int8_t *md5) { int i; for (i = 0; i < MD5_DIGEST_LENGTH; i++) printf("%02x", md5[i]); } void sr_checksum(struct sr_softc *sc, void *src, void *md5, u_int32_t len) { MD5_CTX ctx; DNPRINTF(SR_D_MISC, "%s: sr_checksum(%p %p %d)\n", DEVNAME(sc), src, md5, len); MD5Init(&ctx); MD5Update(&ctx, src, len); MD5Final(md5, &ctx); } void sr_uuid_generate(struct sr_uuid *uuid) { arc4random_buf(uuid->sui_id, sizeof(uuid->sui_id)); /* UUID version 4: random */ uuid->sui_id[6] &= 0x0f; uuid->sui_id[6] |= 0x40; /* RFC4122 variant */ uuid->sui_id[8] &= 0x3f; uuid->sui_id[8] |= 0x80; } char * sr_uuid_format(struct sr_uuid *uuid) { char *uuidstr; uuidstr = malloc(37, M_DEVBUF, M_WAITOK); snprintf(uuidstr, 37, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-" "%02x%02x%02x%02x%02x%02x", uuid->sui_id[0], uuid->sui_id[1], uuid->sui_id[2], uuid->sui_id[3], uuid->sui_id[4], uuid->sui_id[5], uuid->sui_id[6], uuid->sui_id[7], uuid->sui_id[8], uuid->sui_id[9], uuid->sui_id[10], uuid->sui_id[11], uuid->sui_id[12], uuid->sui_id[13], uuid->sui_id[14], uuid->sui_id[15]); return uuidstr; } void sr_uuid_print(struct sr_uuid *uuid, int cr) { char *uuidstr; uuidstr = sr_uuid_format(uuid); printf("%s%s", uuidstr, (cr ? "\n" : "")); free(uuidstr, M_DEVBUF, 37); } int sr_already_assembled(struct sr_discipline *sd) { struct sr_softc *sc = sd->sd_sc; struct sr_discipline *sdtmp; TAILQ_FOREACH(sdtmp, &sc->sc_dis_list, sd_link) { if (!bcmp(&sd->sd_meta->ssdi.ssd_uuid, &sdtmp->sd_meta->ssdi.ssd_uuid, sizeof(sd->sd_meta->ssdi.ssd_uuid))) return (1); } return (0); } int32_t sr_validate_stripsize(u_int32_t b) { int s = 0; if (b % DEV_BSIZE) return (-1); while ((b & 1) == 0) { b >>= 1; s++; } /* only multiple of twos */ b >>= 1; if (b) return(-1); return (s); } void sr_quiesce(void) { struct sr_softc *sc = softraid0; struct sr_discipline *sd, *nsd; if (sc == NULL) return; /* Shutdown disciplines in reverse attach order. */ TAILQ_FOREACH_REVERSE_SAFE(sd, &sc->sc_dis_list, sr_discipline_list, sd_link, nsd) sr_discipline_shutdown(sd, 1, -1); } void sr_shutdown(int dying) { struct sr_softc *sc = softraid0; struct sr_discipline *sd; if (sc == NULL) return; DNPRINTF(SR_D_MISC, "%s: sr_shutdown\n", DEVNAME(sc)); /* * Since softraid is not under mainbus, we have to explicitly * notify its children that the power is going down, so they * can execute their shutdown hooks. */ config_suspend((struct device *)sc, DVACT_POWERDOWN); /* Shutdown disciplines in reverse attach order. */ while ((sd = TAILQ_LAST(&sc->sc_dis_list, sr_discipline_list)) != NULL) sr_discipline_shutdown(sd, 1, dying); } int sr_validate_io(struct sr_workunit *wu, daddr_t *blkno, char *func) { struct sr_discipline *sd = wu->swu_dis; struct scsi_xfer *xs = wu->swu_xs; int rv = 1; DNPRINTF(SR_D_DIS, "%s: %s 0x%02x\n", DEVNAME(sd->sd_sc), func, xs->cmd.opcode); if (sd->sd_meta->ssd_data_blkno == 0) panic("invalid data blkno"); if (sd->sd_vol_status == BIOC_SVOFFLINE) { DNPRINTF(SR_D_DIS, "%s: %s device offline\n", DEVNAME(sd->sd_sc), func); goto bad; } if (xs->datalen == 0) { printf("%s: %s: illegal block count for %s\n", DEVNAME(sd->sd_sc), func, sd->sd_meta->ssd_devname); goto bad; } if (xs->cmdlen == 10) *blkno = _4btol(((struct scsi_rw_10 *)&xs->cmd)->addr); else if (xs->cmdlen == 16) *blkno = _8btol(((struct scsi_rw_16 *)&xs->cmd)->addr); else if (xs->cmdlen == 6) *blkno = _3btol(((struct scsi_rw *)&xs->cmd)->addr); else { printf("%s: %s: illegal cmdlen for %s\n", DEVNAME(sd->sd_sc), func, sd->sd_meta->ssd_devname); goto bad; } *blkno *= (sd->sd_meta->ssdi.ssd_secsize / DEV_BSIZE); wu->swu_blk_start = *blkno; wu->swu_blk_end = *blkno + (xs->datalen >> DEV_BSHIFT) - 1; if (wu->swu_blk_end > sd->sd_meta->ssdi.ssd_size) { DNPRINTF(SR_D_DIS, "%s: %s out of bounds start: %lld " "end: %lld length: %d\n", DEVNAME(sd->sd_sc), func, (long long)wu->swu_blk_start, (long long)wu->swu_blk_end, xs->datalen); sd->sd_scsi_sense.error_code = SSD_ERRCODE_CURRENT | SSD_ERRCODE_VALID; sd->sd_scsi_sense.flags = SKEY_ILLEGAL_REQUEST; sd->sd_scsi_sense.add_sense_code = 0x21; sd->sd_scsi_sense.add_sense_code_qual = 0x00; sd->sd_scsi_sense.extra_len = 4; goto bad; } rv = 0; bad: return (rv); } void sr_rebuild_start(void *arg) { struct sr_discipline *sd = arg; struct sr_softc *sc = sd->sd_sc; DNPRINTF(SR_D_REBUILD, "%s: %s starting rebuild thread\n", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname); if (kthread_create(sr_rebuild_thread, sd, &sd->sd_background_proc, DEVNAME(sc)) != 0) printf("%s: unable to start background operation\n", DEVNAME(sc)); } void sr_rebuild_thread(void *arg) { struct sr_discipline *sd = arg; DNPRINTF(SR_D_REBUILD, "%s: %s rebuild thread started\n", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname); sd->sd_reb_active = 1; sd->sd_rebuild(sd); sd->sd_reb_active = 0; kthread_exit(0); } void sr_rebuild(struct sr_discipline *sd) { struct sr_softc *sc = sd->sd_sc; u_int64_t sz, whole_blk, partial_blk, blk, restart; daddr_t lba; struct sr_workunit *wu_r, *wu_w; struct scsi_xfer xs_r, xs_w; struct scsi_rw_16 *cr, *cw; int c, s, slept, percent = 0, old_percent = -1; u_int8_t *buf; whole_blk = sd->sd_meta->ssdi.ssd_size / SR_REBUILD_IO_SIZE; partial_blk = sd->sd_meta->ssdi.ssd_size % SR_REBUILD_IO_SIZE; restart = sd->sd_meta->ssd_rebuild / SR_REBUILD_IO_SIZE; if (restart > whole_blk) { printf("%s: bogus rebuild restart offset, starting from 0\n", DEVNAME(sc)); restart = 0; } if (restart) { /* * XXX there is a hole here; there is a possibility that we * had a restart however the chunk that was supposed to * be rebuilt is no longer valid; we can reach this situation * when a rebuild is in progress and the box crashes and * on reboot the rebuild chunk is different (like zero'd or * replaced). We need to check the uuid of the chunk that is * being rebuilt to assert this. */ percent = sr_rebuild_percent(sd); printf("%s: resuming rebuild on %s at %d%%\n", DEVNAME(sc), sd->sd_meta->ssd_devname, percent); } /* currently this is 64k therefore we can use dma_alloc */ buf = dma_alloc(SR_REBUILD_IO_SIZE << DEV_BSHIFT, PR_WAITOK); for (blk = restart; blk <= whole_blk; blk++) { lba = blk * SR_REBUILD_IO_SIZE; sz = SR_REBUILD_IO_SIZE; if (blk == whole_blk) { if (partial_blk == 0) break; sz = partial_blk; } /* get some wu */ wu_r = sr_scsi_wu_get(sd, 0); wu_w = sr_scsi_wu_get(sd, 0); DNPRINTF(SR_D_REBUILD, "%s: %s rebuild wu_r %p, wu_w %p\n", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname, wu_r, wu_w); /* setup read io */ bzero(&xs_r, sizeof xs_r); xs_r.error = XS_NOERROR; xs_r.flags = SCSI_DATA_IN; xs_r.datalen = sz << DEV_BSHIFT; xs_r.data = buf; xs_r.cmdlen = sizeof(*cr); cr = (struct scsi_rw_16 *)&xs_r.cmd; cr->opcode = READ_16; _lto4b(sz, cr->length); _lto8b(lba, cr->addr); wu_r->swu_state = SR_WU_CONSTRUCT; wu_r->swu_flags |= SR_WUF_REBUILD; wu_r->swu_xs = &xs_r; if (sd->sd_scsi_rw(wu_r)) { printf("%s: could not create read io\n", DEVNAME(sc)); goto fail; } /* setup write io */ bzero(&xs_w, sizeof xs_w); xs_w.error = XS_NOERROR; xs_w.flags = SCSI_DATA_OUT; xs_w.datalen = sz << DEV_BSHIFT; xs_w.data = buf; xs_w.cmdlen = sizeof(*cw); cw = (struct scsi_rw_16 *)&xs_w.cmd; cw->opcode = WRITE_16; _lto4b(sz, cw->length); _lto8b(lba, cw->addr); wu_w->swu_state = SR_WU_CONSTRUCT; wu_w->swu_flags |= SR_WUF_REBUILD | SR_WUF_WAKEUP; wu_w->swu_xs = &xs_w; if (sd->sd_scsi_rw(wu_w)) { printf("%s: could not create write io\n", DEVNAME(sc)); goto fail; } /* * collide with the read io so that we get automatically * started when the read is done */ wu_w->swu_state = SR_WU_DEFERRED; wu_r->swu_collider = wu_w; s = splbio(); TAILQ_INSERT_TAIL(&sd->sd_wu_defq, wu_w, swu_link); splx(s); DNPRINTF(SR_D_REBUILD, "%s: %s rebuild scheduling wu_r %p\n", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname, wu_r); wu_r->swu_state = SR_WU_INPROGRESS; sr_schedule_wu(wu_r); /* wait for write completion */ slept = 0; while ((wu_w->swu_flags & SR_WUF_REBUILDIOCOMP) == 0) { tsleep_nsec(wu_w, PRIBIO, "sr_rebuild", INFSLP); slept = 1; } /* yield if we didn't sleep */ if (slept == 0) tsleep_nsec(sc, PWAIT, "sr_yield", MSEC_TO_NSEC(1)); sr_scsi_wu_put(sd, wu_r); sr_scsi_wu_put(sd, wu_w); sd->sd_meta->ssd_rebuild = lba; /* XXX - this should be based on size, not percentage. */ /* save metadata every percent */ percent = sr_rebuild_percent(sd); if (percent != old_percent && blk != whole_blk) { if (sr_meta_save(sd, SR_META_DIRTY)) printf("%s: could not save metadata to %s\n", DEVNAME(sc), sd->sd_meta->ssd_devname); old_percent = percent; } if (sd->sd_reb_abort) goto abort; } /* all done */ sd->sd_meta->ssd_rebuild = 0; for (c = 0; c < sd->sd_meta->ssdi.ssd_chunk_no; c++) { if (sd->sd_vol.sv_chunks[c]->src_meta.scm_status == BIOC_SDREBUILD) { sd->sd_set_chunk_state(sd, c, BIOC_SDONLINE); break; } } abort: if (sr_meta_save(sd, SR_META_DIRTY)) printf("%s: could not save metadata to %s\n", DEVNAME(sc), sd->sd_meta->ssd_devname); fail: dma_free(buf, SR_REBUILD_IO_SIZE << DEV_BSHIFT); } struct sr_discipline * sr_find_discipline(struct sr_softc *sc, const char *devname) { struct sr_discipline *sd; TAILQ_FOREACH(sd, &sc->sc_dis_list, sd_link) if (!strncmp(sd->sd_meta->ssd_devname, devname, sizeof(sd->sd_meta->ssd_devname))) break; return sd; } #ifndef SMALL_KERNEL int sr_sensors_create(struct sr_discipline *sd) { struct sr_softc *sc = sd->sd_sc; int rv = 1; DNPRINTF(SR_D_STATE, "%s: %s: sr_sensors_create\n", DEVNAME(sc), sd->sd_meta->ssd_devname); sd->sd_vol.sv_sensor.type = SENSOR_DRIVE; sd->sd_vol.sv_sensor.status = SENSOR_S_UNKNOWN; strlcpy(sd->sd_vol.sv_sensor.desc, sd->sd_meta->ssd_devname, sizeof(sd->sd_vol.sv_sensor.desc)); sensor_attach(&sc->sc_sensordev, &sd->sd_vol.sv_sensor); sd->sd_vol.sv_sensor_attached = 1; if (sc->sc_sensor_task == NULL) { sc->sc_sensor_task = sensor_task_register(sc, sr_sensors_refresh, 10); if (sc->sc_sensor_task == NULL) goto bad; } rv = 0; bad: return (rv); } void sr_sensors_delete(struct sr_discipline *sd) { DNPRINTF(SR_D_STATE, "%s: sr_sensors_delete\n", DEVNAME(sd->sd_sc)); if (sd->sd_vol.sv_sensor_attached) sensor_detach(&sd->sd_sc->sc_sensordev, &sd->sd_vol.sv_sensor); } void sr_sensors_refresh(void *arg) { struct sr_softc *sc = arg; struct sr_volume *sv; struct sr_discipline *sd; DNPRINTF(SR_D_STATE, "%s: sr_sensors_refresh\n", DEVNAME(sc)); TAILQ_FOREACH(sd, &sc->sc_dis_list, sd_link) { sv = &sd->sd_vol; switch(sd->sd_vol_status) { case BIOC_SVOFFLINE: sv->sv_sensor.value = SENSOR_DRIVE_FAIL; sv->sv_sensor.status = SENSOR_S_CRIT; break; case BIOC_SVDEGRADED: sv->sv_sensor.value = SENSOR_DRIVE_PFAIL; sv->sv_sensor.status = SENSOR_S_WARN; break; case BIOC_SVREBUILD: sv->sv_sensor.value = SENSOR_DRIVE_REBUILD; sv->sv_sensor.status = SENSOR_S_WARN; break; case BIOC_SVSCRUB: case BIOC_SVONLINE: sv->sv_sensor.value = SENSOR_DRIVE_ONLINE; sv->sv_sensor.status = SENSOR_S_OK; break; default: sv->sv_sensor.value = 0; /* unknown */ sv->sv_sensor.status = SENSOR_S_UNKNOWN; } } } #endif /* SMALL_KERNEL */ #ifdef SR_FANCY_STATS void sr_print_stats(void); void sr_print_stats(void) { struct sr_softc *sc = softraid0; struct sr_discipline *sd; if (sc == NULL) { printf("no softraid softc found\n"); return; } TAILQ_FOREACH(sd, &sc->sc_dis_list, sd_link) { printf("%s: ios pending %d, collisions %llu\n", sd->sd_meta->ssd_devname, sd->sd_wu_pending, sd->sd_wu_collisions); } } #endif /* SR_FANCY_STATS */ #ifdef SR_DEBUG void sr_meta_print(struct sr_metadata *m) { int i; struct sr_meta_chunk *mc; struct sr_meta_opt_hdr *omh; if (!(sr_debug & SR_D_META)) return; printf("\tssd_magic 0x%llx\n", m->ssdi.ssd_magic); printf("\tssd_version %d\n", m->ssdi.ssd_version); printf("\tssd_vol_flags 0x%x\n", m->ssdi.ssd_vol_flags); printf("\tssd_uuid "); sr_uuid_print(&m->ssdi.ssd_uuid, 1); printf("\tssd_chunk_no %d\n", m->ssdi.ssd_chunk_no); printf("\tssd_chunk_id %d\n", m->ssdi.ssd_chunk_id); printf("\tssd_opt_no %d\n", m->ssdi.ssd_opt_no); printf("\tssd_volid %d\n", m->ssdi.ssd_volid); printf("\tssd_level %d\n", m->ssdi.ssd_level); printf("\tssd_size %lld\n", m->ssdi.ssd_size); printf("\tssd_devname %s\n", m->ssd_devname); printf("\tssd_vendor %s\n", m->ssdi.ssd_vendor); printf("\tssd_product %s\n", m->ssdi.ssd_product); printf("\tssd_revision %s\n", m->ssdi.ssd_revision); printf("\tssd_strip_size %d\n", m->ssdi.ssd_strip_size); printf("\tssd_checksum "); sr_checksum_print(m->ssd_checksum); printf("\n"); printf("\tssd_meta_flags 0x%x\n", m->ssd_meta_flags); printf("\tssd_ondisk %llu\n", m->ssd_ondisk); mc = (struct sr_meta_chunk *)(m + 1); for (i = 0; i < m->ssdi.ssd_chunk_no; i++, mc++) { printf("\t\tscm_volid %d\n", mc->scmi.scm_volid); printf("\t\tscm_chunk_id %d\n", mc->scmi.scm_chunk_id); printf("\t\tscm_devname %s\n", mc->scmi.scm_devname); printf("\t\tscm_size %lld\n", mc->scmi.scm_size); printf("\t\tscm_coerced_size %lld\n",mc->scmi.scm_coerced_size); printf("\t\tscm_uuid "); sr_uuid_print(&mc->scmi.scm_uuid, 1); printf("\t\tscm_checksum "); sr_checksum_print(mc->scm_checksum); printf("\n"); printf("\t\tscm_status %d\n", mc->scm_status); } omh = (struct sr_meta_opt_hdr *)((u_int8_t *)(m + 1) + sizeof(struct sr_meta_chunk) * m->ssdi.ssd_chunk_no); for (i = 0; i < m->ssdi.ssd_opt_no; i++) { printf("\t\t\tsom_type %d\n", omh->som_type); printf("\t\t\tsom_checksum "); sr_checksum_print(omh->som_checksum); printf("\n"); omh = (struct sr_meta_opt_hdr *)((void *)omh + omh->som_length); } } void sr_dump_block(void *blk, int len) { uint8_t *b = blk; int i, j, c; for (i = 0; i < len; i += 16) { for (j = 0; j < 16; j++) printf("%.2x ", b[i + j]); printf(" "); for (j = 0; j < 16; j++) { c = b[i + j]; if (c < ' ' || c > 'z' || i + j > len) c = '.'; printf("%c", c); } printf("\n"); } } void sr_dump_mem(u_int8_t *p, int len) { int i; for (i = 0; i < len; i++) printf("%02x ", *p++); printf("\n"); } #endif /* SR_DEBUG */ #ifdef HIBERNATE /* * Side-effect free (no malloc, printf, pool, splx) softraid crypto writer. * * This function must perform the following: * 1. Determine the underlying device's own side-effect free I/O function * (eg, ahci_hibernate_io, wd_hibernate_io, etc). * 2. Store enough information in the provided page argument for subsequent * I/O calls (such as the crypto discipline structure for the keys, the * offset of the softraid partition on the underlying disk, as well as * the offset of the swap partition within the crypto volume. * 3. Encrypt the incoming data using the sr_discipline keys, then pass * the request to the underlying device's own I/O function. */ int sr_hibernate_io(dev_t dev, daddr_t blkno, vaddr_t addr, size_t size, int op, void *page) { /* Struct for stashing data obtained on HIB_INIT. * XXX * We share the page with the underlying device's own * side-effect free I/O function, so we pad our data to * the end of the page. Presently this does not overlap * with either of the two other side-effect free i/o * functions (ahci/wd). */ struct { char pad[3072]; struct sr_discipline *srd; hibio_fn subfn; /* underlying device i/o fn */ dev_t subdev; /* underlying device dev_t */ daddr_t sr_swapoff; /* ofs of swap part in sr volume */ char buf[DEV_BSIZE]; /* encryption performed into this buf */ } *my = page; extern struct cfdriver sd_cd; char errstr[128], *dl_ret; struct sr_chunk *schunk; struct sd_softc *sd; struct aes_xts_ctx ctx; struct sr_softc *sc; struct device *dv; daddr_t key_blkno; uint32_t sub_raidoff; /* ofs of sr part in underlying dev */ struct disklabel dl; struct partition *pp; size_t i, j; u_char iv[8]; /* * In HIB_INIT, we are passed the swap partition size and offset * in 'size' and 'blkno' respectively. These are relative to the * start of the softraid partition, and we need to save these * for later translation to the underlying device's layout. */ if (op == HIB_INIT) { dv = disk_lookup(&sd_cd, DISKUNIT(dev)); sd = (struct sd_softc *)dv; sc = (struct sr_softc *)dv->dv_parent->dv_parent; /* * Look up the sr discipline. This is used to determine * if we are SR crypto and what the underlying device is. */ my->srd = sc->sc_targets[sd->sc_link->target]; DNPRINTF(SR_D_MISC, "sr_hibernate_io: discipline is %s\n", my->srd->sd_name); if (strncmp(my->srd->sd_name, "CRYPTO", sizeof(my->srd->sd_name))) return (ENOTSUP); /* Find the underlying device */ schunk = my->srd->sd_vol.sv_chunks[0]; my->subdev = schunk->src_dev_mm; /* * Find the appropriate underlying device side effect free * I/O function, based on the type of device it is. */ my->subfn = get_hibernate_io_function(my->subdev); if (!my->subfn) return (ENODEV); /* * Find blkno where this raid partition starts on * the underlying disk. */ dl_ret = disk_readlabel(&dl, my->subdev, errstr, sizeof(errstr)); if (dl_ret) { printf("Hibernate error reading disklabel: %s\n", dl_ret); return (ENOTSUP); } pp = &dl.d_partitions[DISKPART(my->subdev)]; if (pp->p_fstype != FS_RAID || DL_GETPSIZE(pp) == 0) return (ENOTSUP); /* Find the blkno of the SR part in the underlying device */ sub_raidoff = my->srd->sd_meta->ssd_data_blkno + DL_SECTOBLK(&dl, DL_GETPOFFSET(pp)); DNPRINTF(SR_D_MISC,"sr_hibernate_io: blk trans ofs: %d blks\n", sub_raidoff); /* Save the blkno of the swap partition in the SR disk */ my->sr_swapoff = blkno; /* Initialize the sub-device */ return my->subfn(my->subdev, sub_raidoff + blkno, addr, size, op, page); } /* Hibernate only uses (and we only support) writes */ if (op != HIB_W) return (ENOTSUP); /* * Blocks act as the IV for the encryption. These block numbers * are relative to the start of the sr partition, but the 'blkno' * passed above is relative to the start of the swap partition * inside the sr partition, so bias appropriately. */ key_blkno = my->sr_swapoff + blkno; /* Process each disk block one at a time. */ for (i = 0; i < size; i += DEV_BSIZE) { int res; bzero(&ctx, sizeof(ctx)); /* * Set encryption key (from the sr discipline stashed * during HIB_INIT. This code is based on the softraid * bootblock code. */ aes_xts_setkey(&ctx, my->srd->mds.mdd_crypto.scr_key[0], 64); /* We encrypt DEV_BSIZE bytes at a time in my->buf */ memcpy(my->buf, ((char *)addr) + i, DEV_BSIZE); /* Block number is the IV */ memcpy(&iv, &key_blkno, sizeof(key_blkno)); aes_xts_reinit(&ctx, iv); /* Encrypt DEV_BSIZE bytes, AES_XTS_BLOCKSIZE bytes at a time */ for (j = 0; j < DEV_BSIZE; j += AES_XTS_BLOCKSIZE) aes_xts_encrypt(&ctx, my->buf + j); /* * Write one block out from my->buf to the underlying device * using its own side-effect free I/O function. */ res = my->subfn(my->subdev, blkno + (i / DEV_BSIZE), (vaddr_t)(my->buf), DEV_BSIZE, op, page); if (res != 0) return (res); key_blkno++; } return (0); } #endif /* HIBERNATE */
1 1 5 5 2 5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 /* $OpenBSD: ucom.c,v 1.79 2024/05/23 03:21:09 jsg Exp $ */ /* $NetBSD: ucom.c,v 1.49 2003/01/01 00:10:25 thorpej Exp $ */ /* * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Lennart Augustsson (lennart@augustsson.net) at * Carlstedt Research & Technology. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * This code is very heavily based on the 16550 driver, com.c. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/rwlock.h> #include <sys/ioctl.h> #include <sys/conf.h> #include <sys/tty.h> #include <sys/fcntl.h> #include <sys/vnode.h> #include <sys/device.h> #include <sys/malloc.h> #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> #include <dev/usb/usbdi_util.h> #include <dev/usb/uhidev.h> #include <dev/usb/ucomvar.h> #include "ucom.h" #if NUCOM > 0 #ifdef UCOM_DEBUG #define DPRINTFN(n, x) do { if (ucomdebug > (n)) printf x; } while (0) int ucomdebug = 0; #else #define DPRINTFN(n, x) #endif #define DPRINTF(x) DPRINTFN(0, x) #define UCOMUNIT_MASK 0x7f #define UCOMCUA_MASK 0x80 #define LINESW(tp, func) (linesw[(tp)->t_line].func) #define UCOMUNIT(x) (minor(x) & UCOMUNIT_MASK) #define UCOMCUA(x) (minor(x) & UCOMCUA_MASK) #define ROUTEROOTPORT(_x) ((_x) & 0xff) #define ROUTESTRING(_x) (((_x) >> 8) & 0xfffff) struct ucom_softc { struct device sc_dev; /* base device */ struct usbd_device *sc_uparent; /* USB device */ struct uhidev_softc *sc_uhidev; /* hid device (if deeper) */ struct usbd_interface *sc_iface; /* data interface */ int sc_bulkin_no; /* bulk in endpoint address */ struct usbd_pipe *sc_bulkin_pipe;/* bulk in pipe */ struct usbd_xfer *sc_ixfer; /* read request */ u_char *sc_ibuf; /* read buffer */ u_int sc_ibufsize; /* read buffer size */ u_int sc_ibufsizepad; /* read buffer size padded */ int sc_bulkout_no; /* bulk out endpoint address */ struct usbd_pipe *sc_bulkout_pipe;/* bulk out pipe */ struct usbd_xfer *sc_oxfer; /* write request */ u_char *sc_obuf; /* write buffer */ u_int sc_obufsize; /* write buffer size */ u_int sc_opkthdrlen; /* header length of * output packet */ struct usbd_pipe *sc_ipipe; /* hid interrupt input pipe */ struct usbd_pipe *sc_opipe; /* hid interrupt pipe */ const struct ucom_methods *sc_methods; void *sc_parent; int sc_portno; struct tty *sc_tty; /* our tty */ u_char sc_lsr; u_char sc_msr; u_char sc_mcr; u_char sc_tx_stopped; int sc_swflags; u_char sc_cua; int sc_error; struct rwlock sc_lock; /* lock during open */ int sc_open; int sc_refcnt; }; void ucom_cleanup(struct ucom_softc *); void ucom_hwiflow(struct ucom_softc *); int ucomparam(struct tty *, struct termios *); void ucomstart(struct tty *); void ucom_shutdown(struct ucom_softc *); int ucom_do_open(dev_t, int, int, struct proc *); int ucom_do_ioctl(struct ucom_softc *, u_long, caddr_t, int, struct proc *); int ucom_do_close(struct ucom_softc *, int, int , struct proc *); void ucom_dtr(struct ucom_softc *, int); void ucom_rts(struct ucom_softc *, int); void ucom_break(struct ucom_softc *, int); usbd_status ucomstartread(struct ucom_softc *); void ucomreadcb(struct usbd_xfer *, void *, usbd_status); void ucomwritecb(struct usbd_xfer *, void *, usbd_status); void tiocm_to_ucom(struct ucom_softc *, u_long, int); int ucom_to_tiocm(struct ucom_softc *); void ucom_lock(struct ucom_softc *); void ucom_unlock(struct ucom_softc *); int ucom_match(struct device *, void *, void *); void ucom_attach(struct device *, struct device *, void *); int ucom_detach(struct device *, int); struct cfdriver ucom_cd = { NULL, "ucom", DV_TTY }; const struct cfattach ucom_ca = { sizeof(struct ucom_softc), ucom_match, ucom_attach, ucom_detach, }; static int ucom_change; struct rwlock sysctl_ucomlock = RWLOCK_INITIALIZER("sysctlulk"); void ucom_lock(struct ucom_softc *sc) { rw_enter_write(&sc->sc_lock); } void ucom_unlock(struct ucom_softc *sc) { rw_exit_write(&sc->sc_lock); } int ucom_match(struct device *parent, void *match, void *aux) { return (1); } void ucom_attach(struct device *parent, struct device *self, void *aux) { char path[32]; /* "usb000.000.00000.000" */ struct ucom_softc *sc = (struct ucom_softc *)self; struct ucom_attach_args *uca = aux; struct tty *tp; uint32_t route; uint8_t bus, ifaceno; if (uca->info != NULL) printf(", %s", uca->info); sc->sc_uparent = uca->device; sc->sc_iface = uca->iface; sc->sc_bulkout_no = uca->bulkout; sc->sc_bulkin_no = uca->bulkin; sc->sc_uhidev = uca->uhidev; sc->sc_ibufsize = uca->ibufsize; sc->sc_ibufsizepad = uca->ibufsizepad; sc->sc_obufsize = uca->obufsize; sc->sc_opkthdrlen = uca->opkthdrlen; sc->sc_methods = uca->methods; sc->sc_parent = uca->arg; sc->sc_portno = uca->portno; if (usbd_get_location(sc->sc_uparent, sc->sc_iface, &bus, &route, &ifaceno) == 0) { if (snprintf(path, sizeof(path), "usb%u.%u.%05x.%u", bus, ROUTEROOTPORT(route), ROUTESTRING(route), ifaceno) < sizeof(path)) printf(": %s", path); } printf("\n"); tp = ttymalloc(1000000); tp->t_oproc = ucomstart; tp->t_param = ucomparam; sc->sc_tty = tp; sc->sc_cua = 0; ucom_change = 1; rw_init(&sc->sc_lock, "ucomlk"); } int ucom_detach(struct device *self, int flags) { struct ucom_softc *sc = (struct ucom_softc *)self; struct tty *tp = sc->sc_tty; int maj, mn; int s; DPRINTF(("ucom_detach: sc=%p flags=%d tp=%p, pipe=%d,%d\n", sc, flags, tp, sc->sc_bulkin_no, sc->sc_bulkout_no)); if (sc->sc_bulkin_pipe != NULL) { usbd_close_pipe(sc->sc_bulkin_pipe); sc->sc_bulkin_pipe = NULL; } if (sc->sc_bulkout_pipe != NULL) { usbd_close_pipe(sc->sc_bulkout_pipe); sc->sc_bulkout_pipe = NULL; } if (sc->sc_ixfer != NULL) { if (sc->sc_bulkin_no != -1) { usbd_free_buffer(sc->sc_ixfer); sc->sc_ibuf = NULL; usbd_free_xfer(sc->sc_ixfer); } sc->sc_ixfer = NULL; } if (sc->sc_oxfer != NULL) { usbd_free_buffer(sc->sc_oxfer); sc->sc_obuf = NULL; if (sc->sc_bulkin_no != -1) usbd_free_xfer(sc->sc_oxfer); sc->sc_oxfer = NULL; } s = splusb(); if (--sc->sc_refcnt >= 0) { /* Wake up anyone waiting */ if (tp != NULL) { CLR(tp->t_state, TS_CARR_ON); CLR(tp->t_cflag, CLOCAL | MDMBUF); ttyflush(tp, FREAD|FWRITE); } usb_detach_wait(&sc->sc_dev); } splx(s); /* locate the major number */ for (maj = 0; maj < nchrdev; maj++) if (cdevsw[maj].d_open == ucomopen) break; /* Nuke the vnodes for any open instances. */ mn = self->dv_unit; DPRINTF(("ucom_detach: maj=%d mn=%d\n", maj, mn)); vdevgone(maj, mn, mn, VCHR); vdevgone(maj, mn | UCOMCUA_MASK, mn | UCOMCUA_MASK, VCHR); /* Detach and free the tty. */ if (tp != NULL) { (*LINESW(tp, l_close))(tp, FNONBLOCK, curproc); s = spltty(); CLR(tp->t_state, TS_BUSY | TS_FLUSH); ttyclose(tp); splx(s); ttyfree(tp); sc->sc_tty = NULL; } ucom_change = 1; return (0); } void ucom_shutdown(struct ucom_softc *sc) { struct tty *tp = sc->sc_tty; DPRINTF(("ucom_shutdown\n")); /* * Hang up if necessary. Wait a bit, so the other side has time to * notice even if we immediately open the port again. */ if (ISSET(tp->t_cflag, HUPCL)) { ucom_dtr(sc, 0); ucom_rts(sc, 0); tsleep_nsec(sc, TTIPRI, ttclos, SEC_TO_NSEC(1)); } } int ucomopen(dev_t dev, int flag, int mode, struct proc *p) { int unit = UCOMUNIT(dev); struct ucom_softc *sc; int error; if (unit >= ucom_cd.cd_ndevs) return (ENXIO); sc = ucom_cd.cd_devs[unit]; if (sc == NULL) return (ENXIO); sc->sc_error = 0; if (usbd_is_dying(sc->sc_uparent)) return (EIO); if (ISSET(sc->sc_dev.dv_flags, DVF_ACTIVE) == 0) return (ENXIO); sc->sc_refcnt++; error = ucom_do_open(dev, flag, mode, p); if (--sc->sc_refcnt < 0) usb_detach_wakeup(&sc->sc_dev); return (error); } int ucom_do_open(dev_t dev, int flag, int mode, struct proc *p) { struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; usbd_status err; struct tty *tp; struct termios t; int error, s; /* open the pipes if this is the first open */ ucom_lock(sc); s = splusb(); if (sc->sc_open == 0) { DPRINTF(("ucomopen: open pipes in=%d out=%d\n", sc->sc_bulkin_no, sc->sc_bulkout_no)); DPRINTF(("ucomopen: hid %p pipes in=%p out=%p\n", sc->sc_uhidev, sc->sc_ipipe, sc->sc_opipe)); if (sc->sc_bulkin_no != -1) { /* Open the bulk pipes */ err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no, 0, &sc->sc_bulkin_pipe); if (err) { DPRINTF(("%s: open bulk out error (addr %d), err=%s\n", sc->sc_dev.dv_xname, sc->sc_bulkin_no, usbd_errstr(err))); error = EIO; goto fail_0; } err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no, USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe); if (err) { DPRINTF(("%s: open bulk in error (addr %d), err=%s\n", sc->sc_dev.dv_xname, sc->sc_bulkout_no, usbd_errstr(err))); error = EIO; goto fail_1; } /* Allocate a request and an input buffer and start reading. */ sc->sc_ixfer = usbd_alloc_xfer(sc->sc_uparent); if (sc->sc_ixfer == NULL) { error = ENOMEM; goto fail_2; } sc->sc_ibuf = usbd_alloc_buffer(sc->sc_ixfer, sc->sc_ibufsizepad); if (sc->sc_ibuf == NULL) { error = ENOMEM; goto fail_2; } sc->sc_oxfer = usbd_alloc_xfer(sc->sc_uparent); if (sc->sc_oxfer == NULL) { error = ENOMEM; goto fail_3; } } else { /* * input/output pipes and xfers already allocated * as is the input buffer. */ sc->sc_ipipe = sc->sc_uhidev->sc_ipipe; sc->sc_ixfer = sc->sc_uhidev->sc_ixfer; sc->sc_opipe = sc->sc_uhidev->sc_opipe; sc->sc_oxfer = sc->sc_uhidev->sc_oxfer; } sc->sc_obuf = usbd_alloc_buffer(sc->sc_oxfer, sc->sc_obufsize + sc->sc_opkthdrlen); if (sc->sc_obuf == NULL) { error = ENOMEM; goto fail_4; } if (sc->sc_methods->ucom_open != NULL) { error = sc->sc_methods->ucom_open(sc->sc_parent, sc->sc_portno); if (error) { ucom_cleanup(sc); splx(s); ucom_unlock(sc); return (error); } } ucom_status_change(sc); ucomstartread(sc); sc->sc_open = 1; } splx(s); s = spltty(); ucom_unlock(sc); tp = sc->sc_tty; splx(s); DPRINTF(("ucomopen: unit=%d, tp=%p\n", UCOMUNIT(dev), tp)); tp->t_dev = dev; if (!ISSET(tp->t_state, TS_ISOPEN)) { SET(tp->t_state, TS_WOPEN); ttychars(tp); /* * Initialize the termios status to the defaults. Add in the * sticky bits from TIOCSFLAGS. */ t.c_ispeed = 0; t.c_ospeed = TTYDEF_SPEED; t.c_cflag = TTYDEF_CFLAG; if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL)) SET(t.c_cflag, CLOCAL); if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS)) SET(t.c_cflag, CRTSCTS); if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF)) SET(t.c_cflag, MDMBUF); /* Make sure ucomparam() will do something. */ tp->t_ospeed = 0; (void) ucomparam(tp, &t); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_lflag = TTYDEF_LFLAG; s = spltty(); ttsetwater(tp); /* * Turn on DTR. We must always do this, even if carrier is not * present, because otherwise we'd have to use TIOCSDTR * immediately after setting CLOCAL, which applications do not * expect. We always assert DTR while the device is open * unless explicitly requested to deassert it. */ ucom_dtr(sc, 1); /* When not using CRTSCTS, RTS follows DTR. */ if (!ISSET(t.c_cflag, CRTSCTS)) ucom_rts(sc, 1); /* XXX CLR(sc->sc_rx_flags, RX_ANY_BLOCK);*/ ucom_hwiflow(sc); if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) || UCOMCUA(dev) || ISSET(sc->sc_msr, UMSR_DCD) || ISSET(tp->t_cflag, MDMBUF)) SET(tp->t_state, TS_CARR_ON); else CLR(tp->t_state, TS_CARR_ON); } else if (ISSET(tp->t_state, TS_XCLUDE) && suser(p) != 0) return (EBUSY); else s = spltty(); if (UCOMCUA(dev)) { if (ISSET(tp->t_state, TS_ISOPEN)) { /* Someone is already dialed in */ splx(s); return (EBUSY); } sc->sc_cua = 1; } else { /* tty (not cua) device, wait for carrier */ if (ISSET(flag, O_NONBLOCK)) { if (sc->sc_cua) { splx(s); return (EBUSY); } } else { while (sc->sc_cua || (!ISSET(tp->t_cflag, CLOCAL) && !ISSET(tp->t_state, TS_CARR_ON))) { SET(tp->t_state, TS_WOPEN); error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, ttopen); if (usbd_is_dying(sc->sc_uparent)) { splx(s); return (EIO); } /* * If TS_WOPEN has been reset, that means the * cua device has been closed. We don't want * to fail in that case, so just go around * again. */ if (error && ISSET(tp->t_state, TS_WOPEN)) { CLR(tp->t_state, TS_WOPEN); splx(s); goto bad; } } } } splx(s); error = (*LINESW(tp, l_open))(dev, tp, p); if (error) goto bad; return (0); fail_4: if (sc->sc_bulkin_no != -1) usbd_free_xfer(sc->sc_oxfer); sc->sc_oxfer = NULL; fail_3: usbd_free_xfer(sc->sc_ixfer); sc->sc_ixfer = NULL; fail_2: usbd_close_pipe(sc->sc_bulkout_pipe); sc->sc_bulkout_pipe = NULL; fail_1: usbd_close_pipe(sc->sc_bulkin_pipe); sc->sc_bulkin_pipe = NULL; fail_0: splx(s); ucom_unlock(sc); return (error); bad: ucom_lock(sc); ucom_cleanup(sc); ucom_unlock(sc); return (error); } int ucomclose(dev_t dev, int flag, int mode, struct proc *p) { struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; int error; if (sc == NULL || usbd_is_dying(sc->sc_uparent)) return (EIO); DPRINTF(("ucomclose: unit=%d\n", UCOMUNIT(dev))); sc->sc_refcnt++; error = ucom_do_close(sc, flag, mode, p); if (--sc->sc_refcnt < 0) usb_detach_wakeup(&sc->sc_dev); return (error); } int ucom_do_close(struct ucom_softc *sc, int flag, int mode, struct proc *p) { struct tty *tp = sc->sc_tty; int s; if (!ISSET(tp->t_state, TS_ISOPEN)) return (0); ucom_lock(sc); (*LINESW(tp, l_close))(tp, flag, p); s = spltty(); CLR(tp->t_state, TS_BUSY | TS_FLUSH); sc->sc_cua = 0; ttyclose(tp); splx(s); ucom_cleanup(sc); if (sc->sc_methods->ucom_close != NULL) sc->sc_methods->ucom_close(sc->sc_parent, sc->sc_portno); ucom_unlock(sc); return (0); } int ucomread(dev_t dev, struct uio *uio, int flag) { struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; struct tty *tp; int error; if (sc == NULL || usbd_is_dying(sc->sc_uparent)) return (EIO); if (sc->sc_error) return (sc->sc_error); sc->sc_refcnt++; tp = sc->sc_tty; error = (*LINESW(tp, l_read))(tp, uio, flag); if (--sc->sc_refcnt < 0) usb_detach_wakeup(&sc->sc_dev); return (error); } int ucomwrite(dev_t dev, struct uio *uio, int flag) { struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; struct tty *tp; int error; if (sc == NULL || usbd_is_dying(sc->sc_uparent)) return (EIO); sc->sc_refcnt++; tp = sc->sc_tty; error = (*LINESW(tp, l_write))(tp, uio, flag); if (--sc->sc_refcnt < 0) usb_detach_wakeup(&sc->sc_dev); return (error); } struct tty * ucomtty(dev_t dev) { struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; /* * Return a pointer to our tty even if the device is dying * in order to properly close it in the detach routine. */ if (sc == NULL) return (NULL); return (sc->sc_tty); } int ucomioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; int error; if (sc == NULL || usbd_is_dying(sc->sc_uparent)) return (EIO); sc->sc_refcnt++; error = ucom_do_ioctl(sc, cmd, data, flag, p); if (--sc->sc_refcnt < 0) usb_detach_wakeup(&sc->sc_dev); return (error); } int ucom_do_ioctl(struct ucom_softc *sc, u_long cmd, caddr_t data, int flag, struct proc *p) { struct tty *tp = sc->sc_tty; int error; int s; DPRINTF(("ucomioctl: cmd=0x%08lx\n", cmd)); error = (*LINESW(tp, l_ioctl))(tp, cmd, data, flag, p); if (error >= 0) return (error); error = ttioctl(tp, cmd, data, flag, p); if (error >= 0) return (error); if (sc->sc_methods->ucom_ioctl != NULL) { error = sc->sc_methods->ucom_ioctl(sc->sc_parent, sc->sc_portno, cmd, data, flag, p); if (error != ENOTTY) return (error); } error = 0; DPRINTF(("ucomioctl: our cmd=0x%08lx\n", cmd)); s = spltty(); switch (cmd) { case TIOCSBRK: ucom_break(sc, 1); break; case TIOCCBRK: ucom_break(sc, 0); break; case TIOCSDTR: ucom_dtr(sc, 1); break; case TIOCCDTR: ucom_dtr(sc, 0); break; case TIOCGFLAGS: *(int *)data = sc->sc_swflags; break; case TIOCSFLAGS: error = suser(p); if (error) break; sc->sc_swflags = *(int *)data; break; case TIOCMSET: case TIOCMBIS: case TIOCMBIC: tiocm_to_ucom(sc, cmd, *(int *)data); break; case TIOCMGET: *(int *)data = ucom_to_tiocm(sc); break; default: error = ENOTTY; break; } splx(s); return (error); } void tiocm_to_ucom(struct ucom_softc *sc, u_long how, int ttybits) { u_char combits; combits = 0; if (ISSET(ttybits, TIOCM_DTR)) SET(combits, UMCR_DTR); if (ISSET(ttybits, TIOCM_RTS)) SET(combits, UMCR_RTS); switch (how) { case TIOCMBIC: CLR(sc->sc_mcr, combits); break; case TIOCMBIS: SET(sc->sc_mcr, combits); break; case TIOCMSET: CLR(sc->sc_mcr, UMCR_DTR | UMCR_RTS); SET(sc->sc_mcr, combits); break; } if (how == TIOCMSET || ISSET(combits, UMCR_DTR)) ucom_dtr(sc, (sc->sc_mcr & UMCR_DTR) != 0); if (how == TIOCMSET || ISSET(combits, UMCR_RTS)) ucom_rts(sc, (sc->sc_mcr & UMCR_RTS) != 0); } int ucom_to_tiocm(struct ucom_softc *sc) { u_char combits; int ttybits = 0; combits = sc->sc_mcr; if (ISSET(combits, UMCR_DTR)) SET(ttybits, TIOCM_DTR); if (ISSET(combits, UMCR_RTS)) SET(ttybits, TIOCM_RTS); combits = sc->sc_msr; if (ISSET(combits, UMSR_DCD)) SET(ttybits, TIOCM_CD); if (ISSET(combits, UMSR_CTS)) SET(ttybits, TIOCM_CTS); if (ISSET(combits, UMSR_DSR)) SET(ttybits, TIOCM_DSR); if (ISSET(combits, UMSR_RI | UMSR_TERI)) SET(ttybits, TIOCM_RI); #if 0 XXX; if (sc->sc_ier != 0) SET(ttybits, TIOCM_LE); #endif return (ttybits); } void ucom_break(struct ucom_softc *sc, int onoff) { DPRINTF(("ucom_break: onoff=%d\n", onoff)); if (sc->sc_methods->ucom_set != NULL) sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno, UCOM_SET_BREAK, onoff); } void ucom_dtr(struct ucom_softc *sc, int onoff) { DPRINTF(("ucom_dtr: onoff=%d\n", onoff)); if (sc->sc_methods->ucom_set != NULL) sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno, UCOM_SET_DTR, onoff); } void ucom_rts(struct ucom_softc *sc, int onoff) { DPRINTF(("ucom_rts: onoff=%d\n", onoff)); if (sc->sc_methods->ucom_set != NULL) sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno, UCOM_SET_RTS, onoff); } void ucom_status_change(struct ucom_softc *sc) { struct tty *tp = sc->sc_tty; u_char old_msr; if (sc->sc_methods->ucom_get_status != NULL) { old_msr = sc->sc_msr; sc->sc_methods->ucom_get_status(sc->sc_parent, sc->sc_portno, &sc->sc_lsr, &sc->sc_msr); ttytstamp(tp, old_msr & UMSR_CTS, sc->sc_msr & UMSR_CTS, old_msr & UMSR_DCD, sc->sc_msr & UMSR_DCD); if (ISSET((sc->sc_msr ^ old_msr), UMSR_DCD)) (*LINESW(tp, l_modem))(tp, ISSET(sc->sc_msr, UMSR_DCD)); } else { sc->sc_lsr = 0; sc->sc_msr = 0; } } int ucomparam(struct tty *tp, struct termios *t) { struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)]; int error; if (sc == NULL || usbd_is_dying(sc->sc_uparent)) return (EIO); /* Check requested parameters. */ if (t->c_ispeed && t->c_ispeed != t->c_ospeed) return (EINVAL); /* * For the console, always force CLOCAL and !HUPCL, so that the port * is always active. */ if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR)) { SET(t->c_cflag, CLOCAL); CLR(t->c_cflag, HUPCL); } /* * If there were no changes, don't do anything. This avoids dropping * input and improves performance when all we did was frob things like * VMIN and VTIME. */ if (tp->t_ospeed == t->c_ospeed && tp->t_cflag == t->c_cflag) return (0); /* XXX lcr = ISSET(sc->sc_lcr, LCR_SBREAK) | cflag2lcr(t->c_cflag); */ /* And copy to tty. */ tp->t_ispeed = 0; tp->t_ospeed = t->c_ospeed; tp->t_cflag = t->c_cflag; /* * When not using CRTSCTS, RTS follows DTR. * This assumes that the ucom_param() call will enable these signals * for real. */ if (!ISSET(t->c_cflag, CRTSCTS)) sc->sc_mcr = UMCR_DTR | UMCR_RTS; else sc->sc_mcr = UMCR_DTR; if (sc->sc_methods->ucom_param != NULL) { error = sc->sc_methods->ucom_param(sc->sc_parent, sc->sc_portno, t); if (error) return (error); } /* XXX worry about CHWFLOW */ /* * Update the tty layer's idea of the carrier bit, in case we changed * CLOCAL or MDMBUF. We don't hang up here; we only do that by * explicit request. */ DPRINTF(("ucomparam: l_modem\n")); (void) (*LINESW(tp, l_modem))(tp, 1 /* XXX carrier */ ); #if 0 XXX what if the hardware is not open if (!ISSET(t->c_cflag, CHWFLOW)) { if (sc->sc_tx_stopped) { sc->sc_tx_stopped = 0; ucomstart(tp); } } #endif return (0); } /* * (un)block input via hw flowcontrol */ void ucom_hwiflow(struct ucom_softc *sc) { DPRINTF(("ucom_hwiflow:\n")); #if 0 XXX bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; if (sc->sc_mcr_rts == 0) return; if (ISSET(sc->sc_rx_flags, RX_ANY_BLOCK)) { CLR(sc->sc_mcr, sc->sc_mcr_rts); CLR(sc->sc_mcr_active, sc->sc_mcr_rts); } else { SET(sc->sc_mcr, sc->sc_mcr_rts); SET(sc->sc_mcr_active, sc->sc_mcr_rts); } bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr_active); #endif } void ucomstart(struct tty *tp) { struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)]; usbd_status err; int s; u_char *data; int cnt; if (sc == NULL || usbd_is_dying(sc->sc_uparent)) return; s = spltty(); if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) { DPRINTFN(4,("ucomstart: no go, state=0x%x\n", tp->t_state)); goto out; } if (sc->sc_tx_stopped) goto out; ttwakeupwr(tp); if (tp->t_outq.c_cc == 0) goto out; /* Grab the first contiguous region of buffer space. */ data = tp->t_outq.c_cf; cnt = ndqb(&tp->t_outq, 0); if (cnt == 0) { DPRINTF(("ucomstart: cnt==0\n")); goto out; } SET(tp->t_state, TS_BUSY); if (cnt > sc->sc_obufsize) { DPRINTF(("ucomstart: big buffer %d chars\n", cnt)); cnt = sc->sc_obufsize; } if (sc->sc_methods->ucom_write != NULL) sc->sc_methods->ucom_write(sc->sc_parent, sc->sc_portno, sc->sc_obuf, data, &cnt); else memcpy(sc->sc_obuf, data, cnt); DPRINTFN(4,("ucomstart: %d chars\n", cnt)); #ifdef DIAGNOSTIC if (sc->sc_oxfer == NULL) { printf("ucomstart: null oxfer\n"); goto out; } #endif if (sc->sc_bulkout_pipe != NULL) { usbd_setup_xfer(sc->sc_oxfer, sc->sc_bulkout_pipe, (void *)sc, sc->sc_obuf, cnt, USBD_NO_COPY, USBD_NO_TIMEOUT, ucomwritecb); } else { usbd_setup_xfer(sc->sc_oxfer, sc->sc_opipe, (void *)sc, sc->sc_obuf, cnt, USBD_NO_COPY, USBD_NO_TIMEOUT, ucomwritecb); } /* What can we do on error? */ err = usbd_transfer(sc->sc_oxfer); #ifdef DIAGNOSTIC if (err != USBD_IN_PROGRESS) printf("ucomstart: err=%s\n", usbd_errstr(err)); #endif out: splx(s); } int ucomstop(struct tty *tp, int flag) { DPRINTF(("ucomstop: flag=%d\n", flag)); #if 0 /*struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)];*/ int s; s = spltty(); if (ISSET(tp->t_state, TS_BUSY)) { DPRINTF(("ucomstop: XXX\n")); /* sc->sc_tx_stopped = 1; */ if (!ISSET(tp->t_state, TS_TTSTOP)) SET(tp->t_state, TS_FLUSH); } splx(s); #endif return (0); } void ucomwritecb(struct usbd_xfer *xfer, void *p, usbd_status status) { struct ucom_softc *sc = (struct ucom_softc *)p; struct tty *tp = sc->sc_tty; u_int32_t cc; int s; DPRINTFN(5,("ucomwritecb: %p %p status=%d\n", xfer, p, status)); if (status == USBD_CANCELLED || usbd_is_dying(sc->sc_uparent)) goto error; if (sc->sc_bulkin_pipe != NULL) { if (status) { usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe); /* XXX we should restart after some delay. */ goto error; } usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); } else { usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); // XXX above gives me wrong cc, no? } DPRINTFN(5,("ucomwritecb: cc=%d\n", cc)); /* convert from USB bytes to tty bytes */ cc -= sc->sc_opkthdrlen; s = spltty(); CLR(tp->t_state, TS_BUSY); if (ISSET(tp->t_state, TS_FLUSH)) CLR(tp->t_state, TS_FLUSH); else ndflush(&tp->t_outq, cc); (*LINESW(tp, l_start))(tp); splx(s); return; error: s = spltty(); CLR(tp->t_state, TS_BUSY); splx(s); } usbd_status ucomstartread(struct ucom_softc *sc) { usbd_status err; DPRINTFN(5,("ucomstartread: start\n")); #ifdef DIAGNOSTIC if (sc->sc_ixfer == NULL) { DPRINTF(("ucomstartread: null ixfer\n")); return (USBD_INVAL); } #endif if (sc->sc_bulkin_pipe != NULL) { usbd_setup_xfer(sc->sc_ixfer, sc->sc_bulkin_pipe, (void *)sc, sc->sc_ibuf, sc->sc_ibufsize, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, ucomreadcb); err = usbd_transfer(sc->sc_ixfer); if (err != USBD_IN_PROGRESS) { DPRINTF(("ucomstartread: err=%s\n", usbd_errstr(err))); return (err); } } return (USBD_NORMAL_COMPLETION); } void ucomreadcb(struct usbd_xfer *xfer, void *p, usbd_status status) { struct ucom_softc *sc = (struct ucom_softc *)p; struct tty *tp = sc->sc_tty; int (*rint)(int c, struct tty *tp) = LINESW(tp, l_rint); usbd_status err; u_int32_t cc; u_char *cp; int s; DPRINTFN(5,("ucomreadcb: status=%d\n", status)); if (status == USBD_CANCELLED || status == USBD_IOERROR || usbd_is_dying(sc->sc_uparent)) { DPRINTF(("ucomreadcb: dying\n")); /* Send something to wake upper layer */ sc->sc_error = EIO; s = spltty(); (*rint)('\n', tp); ttwakeup(tp); splx(s); return; } if (status) { if (sc->sc_bulkin_pipe != NULL) { usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe); /* XXX we should restart after some delay. */ return; } } usbd_get_xfer_status(xfer, NULL, (void *)&cp, &cc, NULL); DPRINTFN(5,("ucomreadcb: got %d chars, tp=%p\n", cc, tp)); if (sc->sc_methods->ucom_read != NULL) sc->sc_methods->ucom_read(sc->sc_parent, sc->sc_portno, &cp, &cc); s = spltty(); /* Give characters to tty layer. */ while (cc-- > 0) { DPRINTFN(7,("ucomreadcb: char=0x%02x\n", *cp)); if ((*rint)(*cp++, tp) == -1) { /* XXX what should we do? */ printf("%s: lost %d chars\n", sc->sc_dev.dv_xname, cc); break; } } splx(s); err = ucomstartread(sc); if (err) { printf("%s: read start failed\n", sc->sc_dev.dv_xname); /* XXX what should we dow now? */ } } void ucom_cleanup(struct ucom_softc *sc) { DPRINTF(("ucom_cleanup: closing pipes\n")); sc->sc_open = 0; ucom_shutdown(sc); if (sc->sc_bulkin_pipe != NULL) { usbd_close_pipe(sc->sc_bulkin_pipe); sc->sc_bulkin_pipe = NULL; } if (sc->sc_bulkout_pipe != NULL) { usbd_close_pipe(sc->sc_bulkout_pipe); sc->sc_bulkout_pipe = NULL; } if (sc->sc_ixfer != NULL) { if (sc->sc_bulkin_no != -1) { usbd_free_buffer(sc->sc_ixfer); sc->sc_ibuf = NULL; usbd_free_xfer(sc->sc_ixfer); } sc->sc_ixfer = NULL; } if (sc->sc_oxfer != NULL) { usbd_free_buffer(sc->sc_oxfer); sc->sc_obuf = NULL; if (sc->sc_bulkin_no != -1) usbd_free_xfer(sc->sc_oxfer); sc->sc_oxfer = NULL; } } /* * Update ucom names for export by sysctl. */ char * sysctl_ucominit(void) { static char *ucoms = NULL; static size_t ucomslen = 0; char name[64]; /* dv_xname + ":usb000.000.00000.000," */ struct ucom_softc *sc; int rslt; unsigned int unit; uint32_t route; uint8_t bus, ifaceno; KERNEL_ASSERT_LOCKED(); if (rw_enter(&sysctl_ucomlock, RW_WRITE|RW_INTR) != 0) return NULL; if (ucoms == NULL || ucom_change) { free(ucoms, M_SYSCTL, ucomslen); ucomslen = ucom_cd.cd_ndevs * sizeof(name); ucoms = malloc(ucomslen, M_SYSCTL, M_WAITOK | M_ZERO); for (unit = 0; unit < ucom_cd.cd_ndevs; unit++) { sc = ucom_cd.cd_devs[unit]; if (sc == NULL || sc->sc_iface == NULL) continue; if (usbd_get_location(sc->sc_uparent, sc->sc_iface, &bus, &route, &ifaceno) == -1) continue; rslt = snprintf(name, sizeof(name), "%s:usb%u.%u.%05x.%u,", sc->sc_dev.dv_xname, bus, ROUTEROOTPORT(route), ROUTESTRING(route), ifaceno); if (rslt < sizeof(name) && (strlen(ucoms) + rslt) < ucomslen) strlcat(ucoms, name, ucomslen); } } /* Remove trailing ','. */ if (strlen(ucoms)) ucoms[strlen(ucoms) - 1] = '\0'; rw_exit_write(&sysctl_ucomlock); return ucoms; } #endif /* NUCOM > 0 */ int ucomprint(void *aux, const char *pnp) { struct ucom_attach_args *uca = aux; if (pnp) printf("ucom at %s", pnp); if (uca->portno != UCOM_UNK_PORTNO) printf(" portno %d", uca->portno); return (UNCONF); } int ucomsubmatch(struct device *parent, void *match, void *aux) { struct ucom_attach_args *uca = aux; struct cfdata *cf = match; if (uca->portno != UCOM_UNK_PORTNO && cf->ucomcf_portno != UCOM_UNK_PORTNO && cf->ucomcf_portno != uca->portno) return (0); return ((*cf->cf_attach->ca_match)(parent, cf, aux)); }
210 208 11 9 10 11 2 220 220 219 220 220 220 219 186 181 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 /* $OpenBSD: bus_dma.c,v 1.51 2019/06/09 12:52:04 kettenis Exp $ */ /* $NetBSD: bus_dma.c,v 1.3 2003/05/07 21:33:58 fvdl Exp $ */ /*- * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace * Simulation Facility, NASA Ames Research Center. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * The following is included because _bus_dma_uiomove is derived from * uiomove() in kern_subr.c. */ /* * Copyright (c) 1982, 1986, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Lawrence Berkeley Laboratory. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/proc.h> #include <machine/bus.h> #include <uvm/uvm_extern.h> int _bus_dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t, struct proc *, int, paddr_t *, int *, int); /* * Common function for DMA map creation. May be called by bus-specific * DMA map creation functions. */ int _bus_dmamap_create(bus_dma_tag_t t, bus_size_t size, int nsegments, bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp) { struct bus_dmamap *map; void *mapstore; size_t mapsize; /* * Allocate and initialize the DMA map. The end of the map * is a variable-sized array of segments, so we allocate enough * room for them in one shot. * * Note we don't preserve the WAITOK or NOWAIT flags. Preservation * of ALLOCNOW notifies others that we've reserved these resources, * and they are not to be freed. * * The bus_dmamap_t includes one bus_dma_segment_t, hence * the (nsegments - 1). */ mapsize = sizeof(struct bus_dmamap) + (sizeof(bus_dma_segment_t) * (nsegments - 1)); if ((mapstore = malloc(mapsize, M_DEVBUF, (flags & BUS_DMA_NOWAIT) ? (M_NOWAIT|M_ZERO) : (M_WAITOK|M_ZERO))) == NULL) return (ENOMEM); map = (struct bus_dmamap *)mapstore; map->_dm_size = size; map->_dm_segcnt = nsegments; map->_dm_maxsegsz = maxsegsz; map->_dm_boundary = boundary; map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT); *dmamp = map; return (0); } /* * Common function for DMA map destruction. May be called by bus-specific * DMA map destruction functions. */ void _bus_dmamap_destroy(bus_dma_tag_t t, bus_dmamap_t map) { size_t mapsize; mapsize = sizeof(struct bus_dmamap) + (sizeof(bus_dma_segment_t) * (map->_dm_segcnt - 1)); free(map, M_DEVBUF, mapsize); } /* * Common function for loading a DMA map with a linear buffer. May * be called by bus-specific DMA map load functions. */ int _bus_dmamap_load(bus_dma_tag_t t, bus_dmamap_t map, void *buf, bus_size_t buflen, struct proc *p, int flags) { bus_addr_t lastaddr = 0; int seg, error; /* * Make sure that on error condition we return "no valid mappings". */ map->dm_mapsize = 0; map->dm_nsegs = 0; if (buflen > map->_dm_size) return (EINVAL); seg = 0; error = _bus_dmamap_load_buffer(t, map, buf, buflen, p, flags, &lastaddr, &seg, 1); if (error == 0) { map->dm_mapsize = buflen; map->dm_nsegs = seg + 1; } return (error); } /* * Like _bus_dmamap_load(), but for mbufs. */ int _bus_dmamap_load_mbuf(bus_dma_tag_t t, bus_dmamap_t map, struct mbuf *m0, int flags) { paddr_t lastaddr = 0; int seg, error, first; struct mbuf *m; /* * Make sure that on error condition we return "no valid mappings". */ map->dm_mapsize = 0; map->dm_nsegs = 0; #ifdef DIAGNOSTIC if ((m0->m_flags & M_PKTHDR) == 0) panic("_bus_dmamap_load_mbuf: no packet header"); #endif if (m0->m_pkthdr.len > map->_dm_size) return (EINVAL); first = 1; seg = 0; error = 0; for (m = m0; m != NULL && error == 0; m = m->m_next) { if (m->m_len == 0) continue; error = _bus_dmamap_load_buffer(t, map, m->m_data, m->m_len, NULL, flags, &lastaddr, &seg, first); first = 0; } if (error == 0) { map->dm_mapsize = m0->m_pkthdr.len; map->dm_nsegs = seg + 1; } return (error); } /* * Like _bus_dmamap_load(), but for uios. */ int _bus_dmamap_load_uio(bus_dma_tag_t t, bus_dmamap_t map, struct uio *uio, int flags) { paddr_t lastaddr = 0; int seg, i, error, first; bus_size_t minlen, resid; struct proc *p = NULL; struct iovec *iov; caddr_t addr; /* * Make sure that on error condition we return "no valid mappings". */ map->dm_mapsize = 0; map->dm_nsegs = 0; resid = uio->uio_resid; iov = uio->uio_iov; if (uio->uio_segflg == UIO_USERSPACE) { p = uio->uio_procp; #ifdef DIAGNOSTIC if (p == NULL) panic("_bus_dmamap_load_uio: USERSPACE but no proc"); #endif } first = 1; seg = 0; error = 0; for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0; i++) { /* * Now at the first iovec to load. Load each iovec * until we have exhausted the residual count. */ minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len; addr = (caddr_t)iov[i].iov_base; error = _bus_dmamap_load_buffer(t, map, addr, minlen, p, flags, &lastaddr, &seg, first); first = 0; resid -= minlen; } if (error == 0) { map->dm_mapsize = uio->uio_resid; map->dm_nsegs = seg + 1; } return (error); } /* * Like _bus_dmamap_load(), but for raw memory allocated with * bus_dmamem_alloc(). */ int _bus_dmamap_load_raw(bus_dma_tag_t t, bus_dmamap_t map, bus_dma_segment_t *segs, int nsegs, bus_size_t size, int flags) { bus_addr_t paddr, baddr, bmask, lastaddr = 0; bus_size_t plen, sgsize, mapsize; int first = 1; int i, seg = 0; /* * Make sure that on error condition we return "no valid mappings". */ map->dm_mapsize = 0; map->dm_nsegs = 0; if (nsegs > map->_dm_segcnt || size > map->_dm_size) return (EINVAL); mapsize = size; bmask = ~(map->_dm_boundary - 1); for (i = 0; i < nsegs && size > 0; i++) { paddr = segs[i].ds_addr; plen = MIN(segs[i].ds_len, size); while (plen > 0) { /* * Compute the segment size, and adjust counts. */ sgsize = PAGE_SIZE - ((u_long)paddr & PGOFSET); if (plen < sgsize) sgsize = plen; if (paddr > dma_constraint.ucr_high && (map->_dm_flags & BUS_DMA_64BIT) == 0) panic("Non dma-reachable buffer at paddr %#lx(raw)", paddr); /* * Make sure we don't cross any boundaries. */ if (map->_dm_boundary > 0) { baddr = (paddr + map->_dm_boundary) & bmask; if (sgsize > (baddr - paddr)) sgsize = (baddr - paddr); } /* * Insert chunk into a segment, coalescing with * previous segment if possible. */ if (first) { map->dm_segs[seg].ds_addr = paddr; map->dm_segs[seg].ds_len = sgsize; first = 0; } else { if (paddr == lastaddr && (map->dm_segs[seg].ds_len + sgsize) <= map->_dm_maxsegsz && (map->_dm_boundary == 0 || (map->dm_segs[seg].ds_addr & bmask) == (paddr & bmask))) map->dm_segs[seg].ds_len += sgsize; else { if (++seg >= map->_dm_segcnt) return (EINVAL); map->dm_segs[seg].ds_addr = paddr; map->dm_segs[seg].ds_len = sgsize; } } paddr += sgsize; plen -= sgsize; size -= sgsize; lastaddr = paddr; } } map->dm_mapsize = mapsize; map->dm_nsegs = seg + 1; return (0); } /* * Common function for unloading a DMA map. May be called by * bus-specific DMA map unload functions. */ void _bus_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t map) { /* * No resources to free; just mark the mappings as * invalid. */ map->dm_mapsize = 0; map->dm_nsegs = 0; } /* * Common function for DMA map synchronization. May be called * by bus-specific DMA map synchronization functions. */ void _bus_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t addr, bus_size_t size, int op) { /* Nothing to do here. */ } /* * Common function for DMA-safe memory allocation. May be called * by bus-specific DMA memory allocation functions. */ int _bus_dmamem_alloc(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment, bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags) { /* * XXX in the presence of decent (working) iommus and bouncebuffers * we can then fallback this allocation to a range of { 0, -1 }. * However for now we err on the side of caution and allocate dma * memory under the 4gig boundary. */ return (_bus_dmamem_alloc_range(t, size, alignment, boundary, segs, nsegs, rsegs, flags, (bus_addr_t)0, (bus_addr_t)0xffffffff)); } /* * Common function for freeing DMA-safe memory. May be called by * bus-specific DMA memory free functions. */ void _bus_dmamem_free(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs) { struct vm_page *m; bus_addr_t addr; struct pglist mlist; int curseg; /* * Build a list of pages to free back to the VM system. */ TAILQ_INIT(&mlist); for (curseg = 0; curseg < nsegs; curseg++) { for (addr = segs[curseg].ds_addr; addr < (segs[curseg].ds_addr + segs[curseg].ds_len); addr += PAGE_SIZE) { m = PHYS_TO_VM_PAGE(addr); TAILQ_INSERT_TAIL(&mlist, m, pageq); } } uvm_pglistfree(&mlist); } /* * Common function for mapping DMA-safe memory. May be called by * bus-specific DMA memory map functions. */ int _bus_dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, size_t size, caddr_t *kvap, int flags) { vaddr_t va, sva; size_t ssize; bus_addr_t addr; int curseg, pmapflags = 0, error; const struct kmem_dyn_mode *kd; if (nsegs == 1 && (flags & BUS_DMA_NOCACHE) == 0) { *kvap = (caddr_t)PMAP_DIRECT_MAP(segs[0].ds_addr); return (0); } if (flags & BUS_DMA_NOCACHE) pmapflags |= PMAP_NOCACHE; size = round_page(size); kd = flags & BUS_DMA_NOWAIT ? &kd_trylock : &kd_waitok; va = (vaddr_t)km_alloc(size, &kv_any, &kp_none, kd); if (va == 0) return (ENOMEM); *kvap = (caddr_t)va; sva = va; ssize = size; for (curseg = 0; curseg < nsegs; curseg++) { for (addr = segs[curseg].ds_addr; addr < (segs[curseg].ds_addr + segs[curseg].ds_len); addr += PAGE_SIZE, va += PAGE_SIZE, size -= PAGE_SIZE) { if (size == 0) panic("_bus_dmamem_map: size botch"); error = pmap_enter(pmap_kernel(), va, addr | pmapflags, PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE | PMAP_WIRED | PMAP_CANFAIL); if (error) { pmap_update(pmap_kernel()); km_free((void *)sva, ssize, &kv_any, &kp_none); return (error); } } } pmap_update(pmap_kernel()); return (0); } /* * Common function for unmapping DMA-safe memory. May be called by * bus-specific DMA memory unmapping functions. */ void _bus_dmamem_unmap(bus_dma_tag_t t, caddr_t kva, size_t size) { #ifdef DIAGNOSTIC if ((u_long)kva & PGOFSET) panic("_bus_dmamem_unmap"); #endif if (kva >= (caddr_t)PMAP_DIRECT_BASE && kva <= (caddr_t)PMAP_DIRECT_END) return; km_free(kva, round_page(size), &kv_any, &kp_none); } /* * Common function for mmap(2)'ing DMA-safe memory. May be called by * bus-specific DMA mmap(2)'ing functions. */ paddr_t _bus_dmamem_mmap(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, off_t off, int prot, int flags) { int i, pmapflags = 0; if (flags & BUS_DMA_NOCACHE) pmapflags |= PMAP_NOCACHE; for (i = 0; i < nsegs; i++) { #ifdef DIAGNOSTIC if (off & PGOFSET) panic("_bus_dmamem_mmap: offset unaligned"); if (segs[i].ds_addr & PGOFSET) panic("_bus_dmamem_mmap: segment unaligned"); if (segs[i].ds_len & PGOFSET) panic("_bus_dmamem_mmap: segment size not multiple" " of page size"); #endif if (off >= segs[i].ds_len) { off -= segs[i].ds_len; continue; } return ((segs[i].ds_addr + off) | pmapflags); } /* Page not found. */ return (-1); } /********************************************************************** * DMA utility functions **********************************************************************/ /* * Utility function to load a linear buffer. lastaddrp holds state * between invocations (for multiple-buffer loads). segp contains * the starting segment on entrance, and the ending segment on exit. * first indicates if this is the first invocation of this function. */ int _bus_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map, void *buf, bus_size_t buflen, struct proc *p, int flags, paddr_t *lastaddrp, int *segp, int first) { bus_size_t sgsize; bus_addr_t curaddr, lastaddr, baddr, bmask; vaddr_t vaddr = (vaddr_t)buf; int seg; pmap_t pmap; if (p != NULL) pmap = p->p_vmspace->vm_map.pmap; else pmap = pmap_kernel(); lastaddr = *lastaddrp; bmask = ~(map->_dm_boundary - 1); for (seg = *segp; buflen > 0 ; ) { /* * Get the physical address for this segment. */ pmap_extract(pmap, vaddr, (paddr_t *)&curaddr); if (curaddr > dma_constraint.ucr_high && (map->_dm_flags & BUS_DMA_64BIT) == 0) panic("Non dma-reachable buffer at curaddr %#lx(raw)", curaddr); /* * Compute the segment size, and adjust counts. */ sgsize = PAGE_SIZE - ((u_long)vaddr & PGOFSET); if (buflen < sgsize) sgsize = buflen; /* * Make sure we don't cross any boundaries. */ if (map->_dm_boundary > 0) { baddr = (curaddr + map->_dm_boundary) & bmask; if (sgsize > (baddr - curaddr)) sgsize = (baddr - curaddr); } /* * Insert chunk into a segment, coalescing with * previous segment if possible. */ if (first) { map->dm_segs[seg].ds_addr = curaddr; map->dm_segs[seg].ds_len = sgsize; first = 0; } else { if (curaddr == lastaddr && (map->dm_segs[seg].ds_len + sgsize) <= map->_dm_maxsegsz && (map->_dm_boundary == 0 || (map->dm_segs[seg].ds_addr & bmask) == (curaddr & bmask))) map->dm_segs[seg].ds_len += sgsize; else { if (++seg >= map->_dm_segcnt) break; map->dm_segs[seg].ds_addr = curaddr; map->dm_segs[seg].ds_len = sgsize; } } lastaddr = curaddr + sgsize; vaddr += sgsize; buflen -= sgsize; } *segp = seg; *lastaddrp = lastaddr; /* * Did we fit? */ if (buflen != 0) return (EFBIG); /* XXX better return value here? */ return (0); } /* * Allocate physical memory from the given physical address range. * Called by DMA-safe memory allocation methods. */ int _bus_dmamem_alloc_range(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment, bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags, bus_addr_t low, bus_addr_t high) { paddr_t curaddr, lastaddr; struct vm_page *m; struct pglist mlist; int curseg, error, plaflag; /* Always round the size. */ size = round_page(size); segs[0]._ds_boundary = boundary; segs[0]._ds_align = alignment; /* * Allocate pages from the VM system. */ plaflag = flags & BUS_DMA_NOWAIT ? UVM_PLA_NOWAIT : UVM_PLA_WAITOK; if (flags & BUS_DMA_ZERO) plaflag |= UVM_PLA_ZERO; TAILQ_INIT(&mlist); error = uvm_pglistalloc(size, low, high, alignment, boundary, &mlist, nsegs, plaflag); if (error) return (error); /* * Compute the location, size, and number of segments actually * returned by the VM code. */ m = TAILQ_FIRST(&mlist); curseg = 0; lastaddr = segs[curseg].ds_addr = VM_PAGE_TO_PHYS(m); segs[curseg].ds_len = PAGE_SIZE; for (m = TAILQ_NEXT(m, pageq); m != NULL; m = TAILQ_NEXT(m, pageq)) { curaddr = VM_PAGE_TO_PHYS(m); #ifdef DIAGNOSTIC if (curseg == nsegs) { printf("uvm_pglistalloc returned too many\n"); panic("_bus_dmamem_alloc_range"); } if (curaddr < low || curaddr >= high) { printf("uvm_pglistalloc returned non-sensical" " address 0x%lx\n", curaddr); panic("_bus_dmamem_alloc_range"); } #endif if (curaddr == (lastaddr + PAGE_SIZE)) segs[curseg].ds_len += PAGE_SIZE; else { curseg++; segs[curseg].ds_addr = curaddr; segs[curseg].ds_len = PAGE_SIZE; } lastaddr = curaddr; } *rsegs = curseg + 1; return (0); }
1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 /* $OpenBSD: identcpu.c,v 1.143 2024/05/14 01:42:07 guenther Exp $ */ /* $NetBSD: identcpu.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */ /* * Copyright (c) 2003 Wasabi Systems, Inc. * All rights reserved. * * Written by Frank van der Linden for Wasabi Systems, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed for the NetBSD Project by * Wasabi Systems, Inc. * 4. The name of Wasabi Systems, Inc. may not be used to endorse * or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/atomic.h> #include <sys/proc.h> #include <sys/sysctl.h> #include "vmm.h" #include "pvbus.h" #include <machine/cpu.h> #include <machine/cpufunc.h> #if NPVBUS > 0 #include <dev/pv/pvvar.h> #endif void replacesmap(void); void replacemeltdown(void); uint64_t cpu_freq(struct cpu_info *); void tsc_identify(struct cpu_info *); void tsc_timecounter_init(struct cpu_info *, uint64_t); #if NVMM > 0 void cpu_check_vmm_cap(struct cpu_info *); #endif /* NVMM > 0 */ /* sysctl wants this. */ char cpu_model[48]; int cpuspeed; int amd64_has_xcrypt; int has_rdrand; int has_rdseed; int cpu_amd64speed(int *freq) { *freq = cpuspeed; return (0); } #ifndef SMALL_KERNEL void intelcore_update_sensor(void *); void cpu_hz_update_sensor(void *); /* * Temperature read on the CPU is relative to the maximum * temperature supported by the CPU, Tj(Max). * Refer to: * 64-ia-32-architectures-software-developer-vol-3c-part-3-manual.pdf * Section 35 and * http://www.intel.com/content/dam/www/public/us/en/documents/ * white-papers/cpu-monitoring-dts-peci-paper.pdf * * The temperature on Intel CPUs can be between 70 and 105 degC, since * Westmere we can read the TJmax from the die. For older CPUs we have * to guess or use undocumented MSRs. Then we subtract the temperature * portion of thermal status from max to get current temperature. */ void intelcore_update_sensor(void *args) { struct cpu_info *ci = (struct cpu_info *) args; u_int64_t msr; int max = 100; /* Only some Core family chips have MSR_TEMPERATURE_TARGET. */ if (ci->ci_model == 0x0e && (rdmsr(MSR_TEMPERATURE_TARGET_UNDOCUMENTED) & MSR_TEMPERATURE_TARGET_LOW_BIT_UNDOCUMENTED)) max = 85; /* * Newer CPUs can tell you what their max temperature is. * See: '64-ia-32-architectures-software-developer- * vol-3c-part-3-manual.pdf' */ if (ci->ci_model > 0x17 && ci->ci_model != 0x1c && ci->ci_model != 0x26 && ci->ci_model != 0x27 && ci->ci_model != 0x35 && ci->ci_model != 0x36) max = MSR_TEMPERATURE_TARGET_TJMAX( rdmsr(MSR_TEMPERATURE_TARGET)); msr = rdmsr(MSR_THERM_STATUS); if (msr & MSR_THERM_STATUS_VALID_BIT) { ci->ci_sensor.value = max - MSR_THERM_STATUS_TEMP(msr); /* micro degrees */ ci->ci_sensor.value *= 1000000; /* kelvin */ ci->ci_sensor.value += 273150000; ci->ci_sensor.flags &= ~SENSOR_FINVALID; } else { ci->ci_sensor.value = 0; ci->ci_sensor.flags |= SENSOR_FINVALID; } } /* * Effective CPU frequency measurement * * Refer to: * 64-ia-32-architectures-software-developer-vol-3b-part-2-manual.pdf * Section 14.2 and * OSRR for AMD Family 17h processors Section 2.1.2 * Round to 50Mhz which is the accuracy of this measurement. */ #define FREQ_50MHZ (50ULL * 1000000ULL * 1000000ULL) void cpu_hz_update_sensor(void *args) { extern uint64_t tsc_frequency; struct cpu_info *ci = args; uint64_t mperf, aperf, mdelta, adelta, val; unsigned long s; sched_peg_curproc(ci); s = intr_disable(); mperf = rdmsr(MSR_MPERF); aperf = rdmsr(MSR_APERF); intr_restore(s); mdelta = mperf - ci->ci_hz_mperf; adelta = aperf - ci->ci_hz_aperf; ci->ci_hz_mperf = mperf; ci->ci_hz_aperf = aperf; if (mdelta > 0) { val = (adelta * 1000000) / mdelta * tsc_frequency; val = ((val + FREQ_50MHZ / 2) / FREQ_50MHZ) * FREQ_50MHZ; ci->ci_hz_sensor.value = val; } atomic_clearbits_int(&curproc->p_flag, P_CPUPEG); } #endif void (*setperf_setup)(struct cpu_info *); void via_nano_setup(struct cpu_info *ci); void cpu_topology(struct cpu_info *ci); void via_nano_setup(struct cpu_info *ci) { u_int32_t regs[4], val; u_int64_t msreg; int model = (ci->ci_signature >> 4) & 15; if (model >= 9) { CPUID(0xC0000000, regs[0], regs[1], regs[2], regs[3]); val = regs[0]; if (val >= 0xC0000001) { CPUID(0xC0000001, regs[0], regs[1], regs[2], regs[3]); val = regs[3]; } else val = 0; if (val & (C3_CPUID_HAS_RNG | C3_CPUID_HAS_ACE)) printf("%s:", ci->ci_dev->dv_xname); /* Enable RNG if present and disabled */ if (val & C3_CPUID_HAS_RNG) { extern int viac3_rnd_present; if (!(val & C3_CPUID_DO_RNG)) { msreg = rdmsr(0x110B); msreg |= 0x40; wrmsr(0x110B, msreg); } viac3_rnd_present = 1; printf(" RNG"); } /* Enable AES engine if present and disabled */ if (val & C3_CPUID_HAS_ACE) { #ifdef CRYPTO if (!(val & C3_CPUID_DO_ACE)) { msreg = rdmsr(0x1107); msreg |= (0x01 << 28); wrmsr(0x1107, msreg); } amd64_has_xcrypt |= C3_HAS_AES; #endif /* CRYPTO */ printf(" AES"); } /* Enable ACE2 engine if present and disabled */ if (val & C3_CPUID_HAS_ACE2) { #ifdef CRYPTO if (!(val & C3_CPUID_DO_ACE2)) { msreg = rdmsr(0x1107); msreg |= (0x01 << 28); wrmsr(0x1107, msreg); } amd64_has_xcrypt |= C3_HAS_AESCTR; #endif /* CRYPTO */ printf(" AES-CTR"); } /* Enable SHA engine if present and disabled */ if (val & C3_CPUID_HAS_PHE) { #ifdef CRYPTO if (!(val & C3_CPUID_DO_PHE)) { msreg = rdmsr(0x1107); msreg |= (0x01 << 28/**/); wrmsr(0x1107, msreg); } amd64_has_xcrypt |= C3_HAS_SHA; #endif /* CRYPTO */ printf(" SHA1 SHA256"); } /* Enable MM engine if present and disabled */ if (val & C3_CPUID_HAS_PMM) { #ifdef CRYPTO if (!(val & C3_CPUID_DO_PMM)) { msreg = rdmsr(0x1107); msreg |= (0x01 << 28/**/); wrmsr(0x1107, msreg); } amd64_has_xcrypt |= C3_HAS_MM; #endif /* CRYPTO */ printf(" RSA"); } printf("\n"); } } #ifndef SMALL_KERNEL void via_update_sensor(void *args); void via_update_sensor(void *args) { struct cpu_info *ci = (struct cpu_info *) args; u_int64_t msr; msr = rdmsr(MSR_CENT_TMTEMPERATURE); ci->ci_sensor.value = (msr & 0xffffff); /* micro degrees */ ci->ci_sensor.value *= 1000000; ci->ci_sensor.value += 273150000; ci->ci_sensor.flags &= ~SENSOR_FINVALID; } #endif uint64_t cpu_freq_ctr(struct cpu_info *ci, uint32_t cpu_perf_eax, uint32_t cpu_perf_edx) { uint64_t count, last_count, msr; if ((ci->ci_flags & CPUF_CONST_TSC) == 0 || (cpu_perf_eax & CPUIDEAX_VERID) <= 1 || CPUIDEDX_NUM_FC(cpu_perf_edx) <= 1) return (0); msr = rdmsr(MSR_PERF_FIXED_CTR_CTRL); if (msr & MSR_PERF_FIXED_CTR_FC(1, MSR_PERF_FIXED_CTR_FC_MASK)) { /* some hypervisor is dicking us around */ return (0); } msr |= MSR_PERF_FIXED_CTR_FC(1, MSR_PERF_FIXED_CTR_FC_1); wrmsr(MSR_PERF_FIXED_CTR_CTRL, msr); msr = rdmsr(MSR_PERF_GLOBAL_CTRL) | MSR_PERF_GLOBAL_CTR1_EN; wrmsr(MSR_PERF_GLOBAL_CTRL, msr); last_count = rdmsr(MSR_PERF_FIXED_CTR1); delay(100000); count = rdmsr(MSR_PERF_FIXED_CTR1); msr = rdmsr(MSR_PERF_FIXED_CTR_CTRL); msr &= MSR_PERF_FIXED_CTR_FC(1, MSR_PERF_FIXED_CTR_FC_MASK); wrmsr(MSR_PERF_FIXED_CTR_CTRL, msr); msr = rdmsr(MSR_PERF_GLOBAL_CTRL); msr &= ~MSR_PERF_GLOBAL_CTR1_EN; wrmsr(MSR_PERF_GLOBAL_CTRL, msr); return ((count - last_count) * 10); } uint64_t cpu_freq(struct cpu_info *ci) { uint64_t last_count, count; last_count = rdtsc(); delay(100000); count = rdtsc(); return ((count - last_count) * 10); } /* print flags from one cpuid for cpu0 */ static inline void pcpu0id3(const char *id, char reg1, uint32_t val1, const char *bits1, char reg2, uint32_t val2, const char *bits2, char reg3, uint32_t val3, const char *bits3) { if (val1 || val2 || val3) { printf("\ncpu0: cpuid %s", id); if (val1) printf(" e%cx=%b", reg1, val1, bits1); if (val2) printf(" e%cx=%b", reg2, val2, bits2); if (val3) printf(" e%cx=%b", reg3, val3, bits3); } } /* print flags from one, 32-bit MSR for cpu0 */ static inline void pmsr032(uint32_t msr, uint32_t value, const char *bits) { if (value) printf("\ncpu0: msr %x=%b", msr, value, bits); } static void pbitdiff(uint32_t value, uint32_t base_value, const char *bits) { uint32_t minus; if (value == base_value) return; minus = base_value & ~value; value &= ~base_value; if (minus) printf("-%b", minus, bits); if (value) printf("+%b", value, bits); } static inline void pcpuid(struct cpu_info *ci, const char *id, char reg, uint32_t val, uint32_t prev_val, const char *bits) { if (CPU_IS_PRIMARY(ci)) pcpu0id3(id, reg, val, bits, 0, 0, NULL, 0, 0, NULL); else if (val != prev_val) { printf("\n%s: cpuid %s e%cx=", ci->ci_dev->dv_xname, id, reg); pbitdiff(val, prev_val, bits); } } static inline void pcpuid2(struct cpu_info *ci, const char *id, char reg1, uint32_t val1, uint32_t prev_val1, const char *bits1, char reg2, uint32_t val2, uint32_t prev_val2, const char *bits2) { if (CPU_IS_PRIMARY(ci)) pcpu0id3(id, reg1, val1, bits1, reg2, val2, bits2, 0, 0, NULL); else if (val1 != prev_val1 || val2 != prev_val2) { printf("\n%s: cpuid %s", ci->ci_dev->dv_xname, id); if (val1 != prev_val1) { printf(" e%cx=", reg1); pbitdiff(val1, prev_val1, bits1); } if (val2 != prev_val2) { printf(" e%cx=", reg2); pbitdiff(val2, prev_val2, bits2); } } } static inline void pcpuid3(struct cpu_info *ci, const char *id, char reg1, uint32_t val1, uint32_t prev_val1, const char *bits1, char reg2, uint32_t val2, uint32_t prev_val2, const char *bits2, char reg3, uint32_t val3, uint32_t prev_val3, const char *bits3) { if (CPU_IS_PRIMARY(ci)) pcpu0id3(id, reg1, val1, bits1, reg2, val2, bits2, reg3, val3, bits3); else if (val1 != prev_val1 || val2 != prev_val2 || val3 != prev_val3) { printf("\n%s: cpuid %s", ci->ci_dev->dv_xname, id); if (val1 != prev_val1) { printf(" e%cx=", reg1); pbitdiff(val1, prev_val1, bits1); } if (val2 != prev_val2) { printf(" e%cx=", reg2); pbitdiff(val2, prev_val2, bits2); } if (val3 != prev_val3) { printf(" e%cx=", reg3); pbitdiff(val3, prev_val3, bits3); } } } static inline void pmsr32(struct cpu_info *ci, uint32_t msr, uint32_t value, uint32_t prev_value, const char *bits) { if (CPU_IS_PRIMARY(ci)) pmsr032(msr, value, bits); else if (value != prev_value) { printf("\n%s: msr %x=", ci->ci_dev->dv_xname, msr); pbitdiff(value, prev_value, bits); } } #ifdef MULTIPROCESSOR static uint32_t prevcpu_perf_eax; static uint32_t prevcpu_perf_edx; #endif static inline void print_perf_cpuid(struct cpu_info *ci, uint32_t cpu_perf_eax, uint32_t cpu_perf_edx) { uint32_t version; if (CPU_IS_PRIMARY(ci)) { version = cpu_perf_eax & CPUIDEAX_VERID; if (version == 0) return; } #ifdef MULTIPROCESSOR else { /* if no difference on the bits we care about, say nothing */ if (((cpu_perf_eax ^ prevcpu_perf_eax) & 0x00ffffff) == 0 && ((cpu_perf_edx ^ prevcpu_perf_edx) & 0x00001fff) == 0) return; version = cpu_perf_eax & CPUIDEAX_VERID; } prevcpu_perf_eax = cpu_perf_eax; prevcpu_perf_edx = cpu_perf_edx; #endif printf("\n%s: cpuid a vers=%d", ci->ci_dev->dv_xname, version); if (version) { printf(", gp=%d, gpwidth=%d", CPUIDEAX_NUM_GC(cpu_perf_eax), CPUIDEAX_BIT_GC(cpu_perf_eax)); if (version > 1) { printf(", ff=%d, ffwidth=%d", CPUIDEDX_NUM_FC(cpu_perf_edx), CPUIDEDX_BIT_FC(cpu_perf_edx)); } } } void identifycpu(struct cpu_info *ci) { static uint32_t prevcpu_1_ecx, prevcpu_tpm_ecxflags, prevcpu_d_1_eax; static uint32_t prevcpu_apmi_edx, prevcpu_arch_capa; static struct cpu_info *prevci = &cpu_info_primary; #define CPUID_MEMBER(member) ci->member, prevci->member uint32_t cflushsz, curcpu_1_ecx, curcpu_apmi_edx = 0; uint32_t curcpu_perf_eax = 0, curcpu_perf_edx = 0; uint32_t curcpu_tpm_ecxflags = 0, curcpu_d_1_eax = 0; uint64_t freq = 0; u_int32_t dummy; char mycpu_model[48]; char *brandstr_from, *brandstr_to; int skipspace; CPUID(0x80000000, ci->ci_pnfeatset, dummy, dummy, dummy); CPUID(0x80000001, ci->ci_efeature_eax, dummy, ci->ci_efeature_ecx, ci->ci_feature_eflags); if (CPU_IS_PRIMARY(ci)) { ci->ci_signature = cpu_id; ci->ci_feature_flags = cpu_feature & ~CPUID_NXE; cflushsz = cpu_ebxfeature; curcpu_1_ecx = cpu_ecxfeature; ecpu_ecxfeature = ci->ci_efeature_ecx; } else { CPUID(1, ci->ci_signature, cflushsz, curcpu_1_ecx, ci->ci_feature_flags); /* Let cpu_feature be the common bits */ cpu_feature &= ci->ci_feature_flags | (ci->ci_feature_eflags & CPUID_NXE); cpu_ecxfeature &= curcpu_1_ecx; } /* cflush cacheline size is equal to bits 15-8 of ebx * 8 */ ci->ci_cflushsz = ((cflushsz >> 8) & 0xff) * 8; CPUID(0x80000002, ci->ci_brand[0], ci->ci_brand[1], ci->ci_brand[2], ci->ci_brand[3]); CPUID(0x80000003, ci->ci_brand[4], ci->ci_brand[5], ci->ci_brand[6], ci->ci_brand[7]); CPUID(0x80000004, ci->ci_brand[8], ci->ci_brand[9], ci->ci_brand[10], ci->ci_brand[11]); strlcpy(mycpu_model, (char *)ci->ci_brand, sizeof(mycpu_model)); /* Remove leading, trailing and duplicated spaces from mycpu_model */ brandstr_from = brandstr_to = mycpu_model; skipspace = 1; while (*brandstr_from != '\0') { if (!skipspace || *brandstr_from != ' ') { skipspace = 0; *(brandstr_to++) = *brandstr_from; } if (*brandstr_from == ' ') skipspace = 1; brandstr_from++; } if (skipspace && brandstr_to > mycpu_model) brandstr_to--; *brandstr_to = '\0'; if (mycpu_model[0] == 0) strlcpy(mycpu_model, "Opteron or Athlon 64", sizeof(mycpu_model)); /* If primary cpu, fill in the global cpu_model used by sysctl */ if (CPU_IS_PRIMARY(ci)) strlcpy(cpu_model, mycpu_model, sizeof(cpu_model)); ci->ci_family = (ci->ci_signature >> 8) & 0x0f; ci->ci_model = (ci->ci_signature >> 4) & 0x0f; if (ci->ci_family == 0x6 || ci->ci_family == 0xf) { ci->ci_family += (ci->ci_signature >> 20) & 0xff; ci->ci_model += ((ci->ci_signature >> 16) & 0x0f) << 4; } #if NPVBUS > 0 /* Detect hypervisors early, attach the paravirtual bus later */ if (CPU_IS_PRIMARY(ci) && cpu_ecxfeature & CPUIDECX_HV) pvbus_identify(); #endif if (ci->ci_pnfeatset >= 0x80000007) CPUID(0x80000007, dummy, dummy, dummy, curcpu_apmi_edx); if (ci->ci_feature_flags && ci->ci_feature_flags & CPUID_TSC) { /* Has TSC, check if it's constant */ if (ci->ci_vendor == CPUV_INTEL) { if ((ci->ci_family == 0x0f && ci->ci_model >= 0x03) || (ci->ci_family == 0x06 && ci->ci_model >= 0x0e)) { atomic_setbits_int(&ci->ci_flags, CPUF_CONST_TSC); } } else if (ci->ci_vendor == CPUV_VIA) { /* VIA */ if (ci->ci_model >= 0x0f) { atomic_setbits_int(&ci->ci_flags, CPUF_CONST_TSC); } } else if (ci->ci_vendor == CPUV_AMD) { if (curcpu_apmi_edx & CPUIDEDX_ITSC) { /* Invariant TSC indicates constant TSC on AMD */ atomic_setbits_int(&ci->ci_flags, CPUF_CONST_TSC); } } /* Check if it's an invariant TSC */ if (curcpu_apmi_edx & CPUIDEDX_ITSC) atomic_setbits_int(&ci->ci_flags, CPUF_INVAR_TSC); tsc_identify(ci); } if (ci->ci_cpuid_level >= 0xa) { CPUID(0xa, curcpu_perf_eax, dummy, dummy, curcpu_perf_edx); freq = cpu_freq_ctr(ci, curcpu_perf_eax, curcpu_perf_edx); } if (freq == 0) freq = cpu_freq(ci); if (ci->ci_cpuid_level >= 0x07) { /* "Structured Extended Feature Flags" */ CPUID_LEAF(0x7, 0, dummy, ci->ci_feature_sefflags_ebx, ci->ci_feature_sefflags_ecx, ci->ci_feature_sefflags_edx); /* SEFF0ECX_OSPKE is set late on AP */ ci->ci_feature_sefflags_ecx &= ~SEFF0ECX_OSPKE; } printf("%s: %s", ci->ci_dev->dv_xname, mycpu_model); if (freq != 0) printf(", %llu.%02llu MHz", (freq + 4999) / 1000000, ((freq + 4999) / 10000) % 100); if (CPU_IS_PRIMARY(ci)) { cpuspeed = (freq + 4999) / 1000000; cpu_cpuspeed = cpu_amd64speed; } printf(", %02x-%02x-%02x", ci->ci_family, ci->ci_model, ci->ci_signature & 0x0f); if ((cpu_ecxfeature & CPUIDECX_HV) == 0) { uint64_t level = 0; uint32_t dummy; if (ci->ci_vendor == CPUV_AMD) { level = rdmsr(MSR_PATCH_LEVEL); } else if (ci->ci_vendor == CPUV_INTEL) { wrmsr(MSR_BIOS_SIGN, 0); CPUID(1, dummy, dummy, dummy, dummy); level = rdmsr(MSR_BIOS_SIGN) >> 32; } if (level != 0) printf(", patch %08llx", level); } if (ci->ci_cpuid_level >= 0x06) CPUID(0x06, ci->ci_feature_tpmflags, dummy, curcpu_tpm_ecxflags, dummy); if (ci->ci_vendor == CPUV_AMD && ci->ci_family >= 0x12) ci->ci_feature_tpmflags |= TPM_ARAT; /* xsave subfeatures */ if (ci->ci_cpuid_level >= 0xd) CPUID_LEAF(0xd, 1, curcpu_d_1_eax, dummy, dummy, dummy); pcpuid2(ci, "1", 'd', CPUID_MEMBER(ci_feature_flags), CPUID_EDX_BITS, 'c', curcpu_1_ecx, prevcpu_1_ecx, CPUID_ECX_BITS); pcpuid2(ci, "6", 'a', CPUID_MEMBER(ci_feature_tpmflags), TPM_EAX_BITS, 'c', curcpu_tpm_ecxflags, prevcpu_tpm_ecxflags, TPM_ECX_BITS); pcpuid3(ci, "7.0", 'b', CPUID_MEMBER(ci_feature_sefflags_ebx), SEFF0_EBX_BITS, 'c', CPUID_MEMBER(ci_feature_sefflags_ecx), SEFF0_ECX_BITS, 'd', CPUID_MEMBER(ci_feature_sefflags_edx), SEFF0_EDX_BITS); print_perf_cpuid(ci, curcpu_perf_eax, curcpu_perf_edx); pcpuid(ci, "d.1", 'a', curcpu_d_1_eax, prevcpu_d_1_eax, XSAVE_BITS); pcpuid2(ci, "80000001", 'd', CPUID_MEMBER(ci_feature_eflags), CPUIDE_EDX_BITS, 'c', CPUID_MEMBER(ci_efeature_ecx), CPUIDE_ECX_BITS); pcpuid(ci, "80000007", 'd', curcpu_apmi_edx, prevcpu_apmi_edx, CPUID_APMI_EDX_BITS); #ifdef MULTIPROCESSOR prevcpu_1_ecx = curcpu_1_ecx; prevcpu_tpm_ecxflags = curcpu_tpm_ecxflags; prevcpu_d_1_eax = curcpu_d_1_eax; prevcpu_apmi_edx = curcpu_apmi_edx; #endif /* speculation control features */ if (ci->ci_vendor == CPUV_AMD) { if (ci->ci_pnfeatset >= 0x80000008) { CPUID(0x80000008, dummy, ci->ci_feature_amdspec_ebx, dummy, dummy); pcpuid(ci, "80000008", 'b', CPUID_MEMBER(ci_feature_amdspec_ebx), CPUID_AMDSPEC_EBX_BITS); } } else if (ci->ci_vendor == CPUV_INTEL) { if (ci->ci_feature_sefflags_edx & SEFF0EDX_ARCH_CAP) { uint32_t msr = rdmsr(MSR_ARCH_CAPABILITIES); pmsr32(ci, MSR_ARCH_CAPABILITIES, msr, prevcpu_arch_capa, ARCH_CAP_MSR_BITS); prevcpu_arch_capa = msr; if (!CPU_IS_PRIMARY(ci) && cpu_meltdown && (msr & ARCH_CAP_RDCL_NO)) printf("\n%s: -MELTDOWN", ci->ci_dev->dv_xname); } if (cpu_meltdown && CPU_IS_PRIMARY(ci)) printf("\n%s: MELTDOWN", ci->ci_dev->dv_xname); } printf("\n"); replacemeltdown(); x86_print_cacheinfo(ci); if (CPU_IS_PRIMARY(ci)) { #ifndef SMALL_KERNEL if (ci->ci_vendor == CPUV_AMD && ci->ci_pnfeatset >= 0x80000007) { if (curcpu_apmi_edx & 0x06) { if ((ci->ci_signature & 0xF00) == 0xF00) setperf_setup = k8_powernow_init; } if (ci->ci_family >= 0x10) setperf_setup = k1x_init; } if (cpu_ecxfeature & CPUIDECX_EST) setperf_setup = est_init; #endif if (cpu_ecxfeature & CPUIDECX_RDRAND) has_rdrand = 1; if (ci->ci_feature_sefflags_ebx & SEFF0EBX_RDSEED) has_rdseed = 1; if (ci->ci_feature_sefflags_ebx & SEFF0EBX_SMAP) replacesmap(); } #ifndef SMALL_KERNEL if (CPU_IS_PRIMARY(ci) && (ci->ci_feature_tpmflags & TPM_SENSOR)) { ci->ci_sensor.type = SENSOR_TEMP; sensor_task_register(ci, intelcore_update_sensor, 5); sensor_attach(&ci->ci_sensordev, &ci->ci_sensor); } #endif if (CPU_IS_PRIMARY(ci) && ci->ci_vendor == CPUV_VIA) { ci->cpu_setup = via_nano_setup; #ifndef SMALL_KERNEL ci->ci_sensor.type = SENSOR_TEMP; sensor_task_register(ci, via_update_sensor, 5); sensor_attach(&ci->ci_sensordev, &ci->ci_sensor); #endif } tsc_timecounter_init(ci, freq); cpu_topology(ci); #if NVMM > 0 cpu_check_vmm_cap(ci); #endif /* NVMM > 0 */ /* Check for effective frequency via MPERF, APERF */ if ((curcpu_tpm_ecxflags & TPM_EFFFREQ) && ci->ci_smt_id == 0) { #ifndef SMALL_KERNEL ci->ci_hz_sensor.type = SENSOR_FREQ; sensor_task_register(ci, cpu_hz_update_sensor, 1); sensor_attach(&ci->ci_sensordev, &ci->ci_hz_sensor); #endif } prevci = ci; } #ifndef SMALL_KERNEL /* * Base 2 logarithm of an int. returns 0 for 0 (yeye, I know). */ static int log2(unsigned int i) { int ret = 0; while (i >>= 1) ret++; return (ret); } static int mask_width(u_int x) { int bit; int mask; int powerof2; powerof2 = ((x - 1) & x) == 0; mask = (x << (1 - powerof2)) - 1; /* fls */ if (mask == 0) return (0); for (bit = 1; mask != 1; bit++) mask = (unsigned int)mask >> 1; return (bit); } #endif /* * Build up cpu topology for given cpu, must run on the core itself. */ void cpu_topology(struct cpu_info *ci) { #ifndef SMALL_KERNEL u_int32_t eax, ebx, ecx, edx; u_int32_t apicid, max_apicid = 0, max_coreid = 0; u_int32_t smt_bits = 0, core_bits, pkg_bits = 0; u_int32_t smt_mask = 0, core_mask, pkg_mask = 0; /* We need at least apicid at CPUID 1 */ if (ci->ci_cpuid_level < 1) goto no_topology; /* Initial apicid */ CPUID(1, eax, ebx, ecx, edx); apicid = (ebx >> 24) & 0xff; if (ci->ci_vendor == CPUV_AMD) { uint32_t nthreads = 1; /* per core */ uint32_t thread_id; /* within a package */ /* We need at least apicid at CPUID 0x80000008 */ if (ci->ci_pnfeatset < 0x80000008) goto no_topology; CPUID(0x80000008, eax, ebx, ecx, edx); core_bits = (ecx >> 12) & 0xf; if (ci->ci_pnfeatset >= 0x8000001e) { CPUID(0x8000001e, eax, ebx, ecx, edx); nthreads = ((ebx >> 8) & 0xf) + 1; } /* Shift the core_bits off to get at the pkg bits */ ci->ci_pkg_id = apicid >> core_bits; /* Get rid of the package bits */ core_mask = (1U << core_bits) - 1; thread_id = apicid & core_mask; /* Cut logical thread_id into core id, and smt id in a core */ ci->ci_core_id = thread_id / nthreads; ci->ci_smt_id = thread_id % nthreads; } else if (ci->ci_vendor == CPUV_INTEL) { /* We only support leaf 1/4 detection */ if (ci->ci_cpuid_level < 4) goto no_topology; /* Get max_apicid */ CPUID(1, eax, ebx, ecx, edx); max_apicid = (ebx >> 16) & 0xff; /* Get max_coreid */ CPUID_LEAF(4, 0, eax, ebx, ecx, edx); max_coreid = ((eax >> 26) & 0x3f) + 1; /* SMT */ smt_bits = mask_width(max_apicid / max_coreid); smt_mask = (1U << smt_bits) - 1; /* Core */ core_bits = log2(max_coreid); core_mask = (1U << (core_bits + smt_bits)) - 1; core_mask ^= smt_mask; /* Pkg */ pkg_bits = core_bits + smt_bits; pkg_mask = ~0U << core_bits; ci->ci_smt_id = apicid & smt_mask; ci->ci_core_id = (apicid & core_mask) >> smt_bits; ci->ci_pkg_id = (apicid & pkg_mask) >> pkg_bits; } else goto no_topology; #ifdef DEBUG printf("cpu%d: smt %u, core %u, pkg %u " "(apicid 0x%x, max_apicid 0x%x, max_coreid 0x%x, smt_bits 0x%x, smt_mask 0x%x, " "core_bits 0x%x, core_mask 0x%x, pkg_bits 0x%x, pkg_mask 0x%x)\n", ci->ci_cpuid, ci->ci_smt_id, ci->ci_core_id, ci->ci_pkg_id, apicid, max_apicid, max_coreid, smt_bits, smt_mask, core_bits, core_mask, pkg_bits, pkg_mask); #else printf("cpu%d: smt %u, core %u, package %u\n", ci->ci_cpuid, ci->ci_smt_id, ci->ci_core_id, ci->ci_pkg_id); #endif return; /* We can't map, so consider ci_core_id as ci_cpuid */ no_topology: #endif ci->ci_smt_id = 0; ci->ci_core_id = ci->ci_cpuid; ci->ci_pkg_id = 0; } #if NVMM > 0 /* * cpu_check_vmm_cap * * Checks for VMM capabilities for 'ci'. Initializes certain per-cpu VMM * state in 'ci' if virtualization extensions are found. * * Parameters: * ci: the cpu being checked */ void cpu_check_vmm_cap(struct cpu_info *ci) { uint64_t msr; uint32_t cap, dummy, edx; /* * Check for workable VMX */ if (cpu_ecxfeature & CPUIDECX_VMX) { msr = rdmsr(MSR_IA32_FEATURE_CONTROL); if (!(msr & IA32_FEATURE_CONTROL_LOCK)) ci->ci_vmm_flags |= CI_VMM_VMX; else { if (msr & IA32_FEATURE_CONTROL_VMX_EN) ci->ci_vmm_flags |= CI_VMM_VMX; else ci->ci_vmm_flags |= CI_VMM_DIS; } } /* * Check for EPT (Intel Nested Paging) and other secondary * controls */ if (ci->ci_vmm_flags & CI_VMM_VMX) { /* Secondary controls available? */ /* XXX should we check true procbased ctls here if avail? */ msr = rdmsr(IA32_VMX_PROCBASED_CTLS); if (msr & (IA32_VMX_ACTIVATE_SECONDARY_CONTROLS) << 32) { msr = rdmsr(IA32_VMX_PROCBASED2_CTLS); /* EPT available? */ if (msr & (IA32_VMX_ENABLE_EPT) << 32) ci->ci_vmm_flags |= CI_VMM_EPT; /* VM Functions available? */ if (msr & (IA32_VMX_ENABLE_VM_FUNCTIONS) << 32) { ci->ci_vmm_cap.vcc_vmx.vmx_vm_func = rdmsr(IA32_VMX_VMFUNC); } } } /* * Check startup config (VMX) */ if (ci->ci_vmm_flags & CI_VMM_VMX) { /* CR0 fixed and flexible bits */ msr = rdmsr(IA32_VMX_CR0_FIXED0); ci->ci_vmm_cap.vcc_vmx.vmx_cr0_fixed0 = msr; msr = rdmsr(IA32_VMX_CR0_FIXED1); ci->ci_vmm_cap.vcc_vmx.vmx_cr0_fixed1 = msr; /* CR4 fixed and flexible bits */ msr = rdmsr(IA32_VMX_CR4_FIXED0); ci->ci_vmm_cap.vcc_vmx.vmx_cr4_fixed0 = msr; msr = rdmsr(IA32_VMX_CR4_FIXED1); ci->ci_vmm_cap.vcc_vmx.vmx_cr4_fixed1 = msr; /* VMXON region revision ID (bits 30:0 of IA32_VMX_BASIC) */ msr = rdmsr(IA32_VMX_BASIC); ci->ci_vmm_cap.vcc_vmx.vmx_vmxon_revision = (uint32_t)(msr & 0x7FFFFFFF); /* MSR save / load table size */ msr = rdmsr(IA32_VMX_MISC); ci->ci_vmm_cap.vcc_vmx.vmx_msr_table_size = (uint32_t)(msr & IA32_VMX_MSR_LIST_SIZE_MASK) >> 25; /* CR3 target count size */ ci->ci_vmm_cap.vcc_vmx.vmx_cr3_tgt_count = (uint32_t)(msr & IA32_VMX_CR3_TGT_SIZE_MASK) >> 16; } /* * Check for workable SVM */ if (ecpu_ecxfeature & CPUIDECX_SVM) { msr = rdmsr(MSR_AMD_VM_CR); if (!(msr & AMD_SVMDIS)) ci->ci_vmm_flags |= CI_VMM_SVM; CPUID(CPUID_AMD_SVM_CAP, dummy, ci->ci_vmm_cap.vcc_svm.svm_max_asid, dummy, edx); if (ci->ci_vmm_cap.vcc_svm.svm_max_asid > 0xFFF) ci->ci_vmm_cap.vcc_svm.svm_max_asid = 0xFFF; if (edx & AMD_SVM_FLUSH_BY_ASID_CAP) ci->ci_vmm_cap.vcc_svm.svm_flush_by_asid = 1; if (edx & AMD_SVM_VMCB_CLEAN_CAP) ci->ci_vmm_cap.vcc_svm.svm_vmcb_clean = 1; if (edx & AMD_SVM_DECODE_ASSIST_CAP) ci->ci_vmm_cap.vcc_svm.svm_decode_assist = 1; } /* * Check for SVM Nested Paging */ if ((ci->ci_vmm_flags & CI_VMM_SVM) && ci->ci_pnfeatset >= CPUID_AMD_SVM_CAP) { CPUID(CPUID_AMD_SVM_CAP, dummy, dummy, dummy, cap); if (cap & AMD_SVM_NESTED_PAGING_CAP) ci->ci_vmm_flags |= CI_VMM_RVI; } /* * Check "L1 flush on VM entry" (Intel L1TF vuln) semantics * Full details can be found here: * https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-l1-terminal-fault */ if (ci->ci_vendor == CPUV_INTEL) { if (ci->ci_feature_sefflags_edx & SEFF0EDX_L1DF) ci->ci_vmm_cap.vcc_vmx.vmx_has_l1_flush_msr = 1; else ci->ci_vmm_cap.vcc_vmx.vmx_has_l1_flush_msr = 0; /* * Certain CPUs may have the vulnerability remedied in * hardware (RDCL_NO), or we may be nested in an VMM that * is doing flushes (SKIP_L1DFL_VMENTRY) using the MSR. * In either case no mitigation at all is necessary. */ if (ci->ci_feature_sefflags_edx & SEFF0EDX_ARCH_CAP) { msr = rdmsr(MSR_ARCH_CAPABILITIES); if ((msr & ARCH_CAP_RDCL_NO) || ((msr & ARCH_CAP_SKIP_L1DFL_VMENTRY) && ci->ci_vmm_cap.vcc_vmx.vmx_has_l1_flush_msr)) ci->ci_vmm_cap.vcc_vmx.vmx_has_l1_flush_msr = VMX_SKIP_L1D_FLUSH; } } } #endif /* NVMM > 0 */
891 891 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 /* $OpenBSD: explicit_bzero.c,v 1.3 2014/06/21 02:34:26 matthew Exp $ */ /* * Public domain. * Written by Matthew Dempsky. */ #include <lib/libkern/libkern.h> __attribute__((weak)) void __explicit_bzero_hook(void *, size_t); __attribute__((weak)) void __explicit_bzero_hook(void *buf, size_t len) { } void explicit_bzero(void *buf, size_t len) { memset(buf, 0, len); __explicit_bzero_hook(buf, len); }
15 1 3 12 1 1 1 10 2 1 2 2 2 2 3 3 2 4 12 1 1 5 5 11 1 1 1 9 1 4 4 4 1 3 3 3 1 3 3 1 42 42 3 3 3 3 3 19 20 2 11 9 11 6 11 9 16 5 5 3 2 3 2 2 3 2 2 3 3 2 9 4 5 2 7 3 6 6 3 6 6 3 4 5 4 5 6 6 6 6 6 6 6 1 1 3 1 4 9 9 6 6 9 9 6 6 6 6 6 6 6 6 6 6 6 3 1 1 1 4 1 3 6 6 6 2 2 2 2 2 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857 6858 6859 6860 6861 6862 6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889 6890 6891 6892 6893 6894 6895 6896 6897 6898 6899 6900 6901 6902 6903 6904 6905 6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932 6933 6934 6935 6936 6937 6938 6939 6940 6941 6942 6943 6944 6945 6946 6947 6948 6949 6950 6951 6952 6953 6954 6955 6956 6957 6958 6959 6960 6961 6962 6963 6964 6965 6966 6967 6968 6969 6970 6971 6972 6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991 6992 6993 6994 6995 6996 6997 6998 6999 7000 7001 7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053 7054 7055 7056 7057 7058 7059 7060 7061 7062 7063 7064 7065 7066 7067 7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126 7127 7128 7129 7130 7131 7132 7133 7134 7135 7136 7137 7138 7139 7140 7141 7142 7143 7144 7145 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 7222 7223 7224 7225 7226 7227 7228 7229 7230 7231 7232 7233 7234 7235 7236 7237 7238 7239 7240 7241 7242 7243 7244 7245 7246 7247 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257 7258 7259 7260 7261 7262 7263 7264 7265 7266 7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 7282 7283 7284 7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296 7297 7298 7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 7344 7345 7346 7347 7348 7349 7350 7351 7352 7353 7354 7355 7356 7357 7358 7359 7360 7361 7362 7363 7364 7365 7366 7367 7368 7369 7370 7371 7372 7373 7374 7375 7376 7377 7378 7379 7380 7381 7382 7383 7384 7385 7386 7387 7388 7389 7390 7391 7392 7393 7394 7395 7396 7397 7398 7399 7400 7401 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425 7426 7427 7428 7429 7430 7431 7432 7433 7434 7435 7436 7437 7438 7439 7440 7441 7442 7443 7444 7445 7446 7447 7448 7449 7450 7451 7452 7453 7454 7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 7499 7500 7501 7502 7503 7504 7505 7506 7507 7508 7509 7510 7511 7512 7513 7514 7515 7516 7517 7518 7519 7520 7521 7522 7523 7524 7525 7526 7527 7528 7529 7530 7531 7532 7533 7534 7535 7536 7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571 7572 7573 7574 7575 7576 7577 7578 7579 7580 7581 7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599 7600 7601 7602 7603 7604 7605 7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 7616 7617 7618 7619 7620 7621 7622 7623 7624 7625 7626 7627 7628 7629 7630 7631 7632 7633 7634 7635 7636 7637 7638 7639 7640 7641 7642 7643 7644 7645 7646 7647 7648 7649 7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 7663 7664 7665 7666 7667 7668 7669 7670 7671 7672 7673 7674 7675 7676 7677 7678 7679 7680 7681 7682 7683 7684 7685 7686 7687 7688 7689 7690 7691 7692 7693 7694 7695 7696 7697 7698 7699 7700 7701 7702 7703 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717 7718 7719 7720 7721 7722 7723 7724 7725 7726 7727 7728 7729 7730 7731 7732 7733 7734 7735 7736 7737 7738 7739 7740 7741 7742 7743 7744 7745 7746 7747 7748 7749 7750 7751 7752 7753 7754 7755 7756 7757 7758 7759 7760 7761 7762 7763 7764 7765 7766 7767 7768 7769 7770 7771 7772 7773 7774 7775 7776 7777 7778 7779 7780 7781 7782 7783 7784 7785 7786 7787 7788 7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807 7808 7809 7810 7811 7812 7813 7814 7815 7816 7817 7818 7819 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 7832 7833 7834 7835 7836 7837 7838 7839 7840 7841 7842 7843 7844 7845 7846 7847 7848 7849 7850 7851 7852 7853 7854 7855 7856 7857 7858 7859 7860 7861 7862 7863 7864 7865 7866 7867 7868 7869 7870 7871 7872 7873 7874 7875 7876 7877 7878 7879 7880 7881 7882 7883 7884 7885 7886 7887 7888 7889 7890 7891 7892 7893 7894 7895 7896 7897 7898 7899 7900 7901 7902 7903 7904 7905 7906 7907 7908 7909 7910 7911 7912 7913 7914 7915 7916 7917 7918 7919 7920 7921 7922 7923 7924 7925 7926 7927 7928 7929 7930 7931 7932 7933 7934 7935 7936 7937 7938 7939 7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956 7957 7958 7959 7960 7961 7962 7963 7964 7965 7966 7967 7968 7969 7970 7971 7972 7973 7974 7975 7976 7977 7978 7979 7980 7981 7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993 7994 7995 7996 7997 7998 7999 8000 8001 8002 8003 8004 8005 8006 8007 8008 8009 8010 8011 8012 8013 8014 8015 8016 8017 8018 8019 8020 8021 8022 8023 8024 8025 8026 8027 8028 8029 8030 8031 8032 8033 8034 8035 8036 8037 8038 8039 8040 8041 8042 8043 8044 8045 8046 8047 8048 8049 8050 8051 8052 8053 8054 8055 8056 8057 8058 8059 8060 8061 8062 8063 8064 8065 8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083 8084 8085 8086 8087 8088 8089 8090 8091 8092 8093 8094 8095 8096 8097 8098 8099 8100 8101 8102 8103 8104 8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126 8127 8128 8129 8130 8131 8132 8133 8134 8135 8136 8137 8138 8139 8140 8141 8142 8143 8144 8145 8146 8147 8148 8149 8150 8151 8152 8153 8154 8155 8156 8157 8158 8159 8160 8161 8162 8163 8164 8165 8166 8167 8168 8169 8170 8171 8172 8173 8174 8175 8176 8177 8178 8179 8180 8181 8182 8183 8184 8185 8186 8187 8188 8189 8190 8191 8192 8193 8194 8195 8196 8197 8198 8199 8200 8201 8202 8203 8204 8205 8206 8207 8208 8209 8210 8211 8212 8213 8214 8215 8216 8217 8218 8219 8220 8221 8222 8223 8224 8225 8226 8227 8228 8229 8230 8231 8232 8233 8234 8235 8236 8237 8238 8239 8240 8241 8242 8243 8244 8245 8246 8247 8248 8249 8250 8251 8252 8253 8254 8255 8256 8257 8258 8259 8260 8261 8262 8263 8264 8265 8266 8267 8268 8269 8270 8271 8272 8273 8274 8275 8276 8277 8278 8279 8280 8281 8282 8283 8284 8285 8286 8287 8288 8289 8290 8291 8292 8293 8294 8295 8296 8297 8298 8299 8300 8301 8302 8303 8304 8305 8306 8307 8308 8309 8310 8311 8312 8313 8314 8315 8316 8317 8318 8319 8320 8321 8322 8323 8324 8325 8326 8327 8328 8329 8330 8331 8332 8333 8334 8335 8336 8337 8338 8339 8340 8341 8342 8343 8344 8345 8346 8347 8348 8349 8350 8351 8352 8353 8354 8355 8356 8357 8358 8359 8360 8361 8362 8363 8364 8365 8366 8367 8368 8369 8370 8371 8372 8373 8374 8375 8376 8377 8378 8379 8380 8381 8382 8383 8384 8385 8386 8387 8388 8389 8390 8391 8392 8393 8394 8395 8396 8397 8398 8399 8400 8401 8402 8403 8404 8405 8406 8407 8408 8409 8410 8411 8412 8413 8414 8415 8416 8417 8418 8419 8420 8421 8422 8423 8424 8425 8426 8427 8428 8429 8430 8431 8432 8433 8434 8435 8436 8437 8438 8439 8440 8441 8442 8443 8444 8445 8446 8447 8448 8449 8450 8451 8452 8453 8454 8455 8456 8457 8458 8459 8460 8461 8462 8463 8464 8465 8466 8467 8468 8469 8470 8471 8472 8473 8474 8475 8476 8477 8478 8479 8480 8481 8482 8483 8484 8485 8486 8487 8488 8489 8490 8491 8492 8493 8494 8495 8496 8497 8498 8499 8500 8501 8502 8503 8504 8505 8506 8507 8508 8509 8510 8511 8512 8513 8514 8515 8516 8517 8518 8519 8520 8521 8522 8523 8524 8525 8526 8527 8528 8529 8530 8531 /* $OpenBSD: vmm_machdep.c,v 1.27 2024/05/13 01:15:50 jsg Exp $ */ /* * Copyright (c) 2014 Mike Larkin <mlarkin@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/signalvar.h> #include <sys/malloc.h> #include <sys/device.h> #include <sys/pool.h> #include <sys/proc.h> #include <sys/user.h> #include <sys/ioctl.h> #include <sys/queue.h> #include <sys/refcnt.h> #include <sys/rwlock.h> #include <sys/pledge.h> #include <sys/memrange.h> #include <sys/tracepoint.h> #include <uvm/uvm_extern.h> #include <machine/fpu.h> #include <machine/pmap.h> #include <machine/biosvar.h> #include <machine/segments.h> #include <machine/cpufunc.h> #include <machine/vmmvar.h> #include <dev/isa/isareg.h> #include <dev/pv/pvreg.h> #include <dev/vmm/vmm.h> #ifdef MP_LOCKDEBUG #include <ddb/db_output.h> extern int __mp_lock_spinout; #endif /* MP_LOCKDEBUG */ void *l1tf_flush_region; #define DEVNAME(s) ((s)->sc_dev.dv_xname) #define CTRL_DUMP(x,y,z) printf(" %s: Can set:%s Can clear:%s\n", #z , \ vcpu_vmx_check_cap(x, IA32_VMX_##y ##_CTLS, \ IA32_VMX_##z, 1) ? "Yes" : "No", \ vcpu_vmx_check_cap(x, IA32_VMX_##y ##_CTLS, \ IA32_VMX_##z, 0) ? "Yes" : "No"); #define VMX_EXIT_INFO_HAVE_RIP 0x1 #define VMX_EXIT_INFO_HAVE_REASON 0x2 #define VMX_EXIT_INFO_COMPLETE \ (VMX_EXIT_INFO_HAVE_RIP | VMX_EXIT_INFO_HAVE_REASON) void vmx_dump_vmcs_field(uint16_t, const char *); int vmm_enabled(void); void vmm_activate_machdep(struct device *, int); int vmmioctl_machdep(dev_t, u_long, caddr_t, int, struct proc *); int vmm_quiesce_vmx(void); int vm_run(struct vm_run_params *); int vm_intr_pending(struct vm_intr_params *); int vm_rwregs(struct vm_rwregs_params *, int); int vm_mprotect_ept(struct vm_mprotect_ept_params *); int vm_rwvmparams(struct vm_rwvmparams_params *, int); int vcpu_readregs_vmx(struct vcpu *, uint64_t, int, struct vcpu_reg_state *); int vcpu_readregs_svm(struct vcpu *, uint64_t, struct vcpu_reg_state *); int vcpu_writeregs_vmx(struct vcpu *, uint64_t, int, struct vcpu_reg_state *); int vcpu_writeregs_svm(struct vcpu *, uint64_t, struct vcpu_reg_state *); int vcpu_reset_regs(struct vcpu *, struct vcpu_reg_state *); int vcpu_reset_regs_vmx(struct vcpu *, struct vcpu_reg_state *); int vcpu_reset_regs_svm(struct vcpu *, struct vcpu_reg_state *); int vcpu_reload_vmcs_vmx(struct vcpu *); int vcpu_init(struct vcpu *); int vcpu_init_vmx(struct vcpu *); int vcpu_init_svm(struct vcpu *); int vcpu_run_vmx(struct vcpu *, struct vm_run_params *); int vcpu_run_svm(struct vcpu *, struct vm_run_params *); void vcpu_deinit(struct vcpu *); void vcpu_deinit_svm(struct vcpu *); void vcpu_deinit_vmx(struct vcpu *); int vcpu_vmx_check_cap(struct vcpu *, uint32_t, uint32_t, int); int vcpu_vmx_compute_ctrl(uint64_t, uint16_t, uint32_t, uint32_t, uint32_t *); int vmx_get_exit_info(uint64_t *, uint64_t *); int vmx_load_pdptes(struct vcpu *); int vmx_handle_exit(struct vcpu *); int svm_handle_exit(struct vcpu *); int svm_handle_msr(struct vcpu *); int vmm_handle_xsetbv(struct vcpu *, uint64_t *); int vmx_handle_xsetbv(struct vcpu *); int svm_handle_xsetbv(struct vcpu *); int vmm_handle_cpuid(struct vcpu *); int vmx_handle_rdmsr(struct vcpu *); int vmx_handle_wrmsr(struct vcpu *); int vmx_handle_cr0_write(struct vcpu *, uint64_t); int vmx_handle_cr4_write(struct vcpu *, uint64_t); int vmx_handle_cr(struct vcpu *); int svm_handle_inout(struct vcpu *); int vmx_handle_inout(struct vcpu *); int svm_handle_hlt(struct vcpu *); int vmx_handle_hlt(struct vcpu *); int vmm_inject_ud(struct vcpu *); int vmm_inject_gp(struct vcpu *); int vmm_inject_db(struct vcpu *); void vmx_handle_intr(struct vcpu *); void vmx_handle_misc_enable_msr(struct vcpu *); int vmm_get_guest_memtype(struct vm *, paddr_t); int vmx_get_guest_faulttype(void); int svm_get_guest_faulttype(struct vmcb *); int vmx_get_exit_qualification(uint64_t *); int vmm_get_guest_cpu_cpl(struct vcpu *); int vmm_get_guest_cpu_mode(struct vcpu *); int svm_fault_page(struct vcpu *, paddr_t); int vmx_fault_page(struct vcpu *, paddr_t); int vmx_handle_np_fault(struct vcpu *); int svm_handle_np_fault(struct vcpu *); int vmx_mprotect_ept(vm_map_t, paddr_t, paddr_t, int); pt_entry_t *vmx_pmap_find_pte_ept(pmap_t, paddr_t); int vmm_alloc_vpid(uint16_t *); void vmm_free_vpid(uint16_t); const char *vcpu_state_decode(u_int); const char *vmx_exit_reason_decode(uint32_t); const char *svm_exit_reason_decode(uint32_t); const char *vmx_instruction_error_decode(uint32_t); void svm_setmsrbr(struct vcpu *, uint32_t); void svm_setmsrbw(struct vcpu *, uint32_t); void svm_setmsrbrw(struct vcpu *, uint32_t); void vmx_setmsrbr(struct vcpu *, uint32_t); void vmx_setmsrbw(struct vcpu *, uint32_t); void vmx_setmsrbrw(struct vcpu *, uint32_t); void svm_set_clean(struct vcpu *, uint32_t); void svm_set_dirty(struct vcpu *, uint32_t); int vmm_gpa_is_valid(struct vcpu *vcpu, paddr_t gpa, size_t obj_size); void vmm_init_pvclock(struct vcpu *, paddr_t); int vmm_update_pvclock(struct vcpu *); int vmm_pat_is_valid(uint64_t); #ifdef MULTIPROCESSOR static int vmx_remote_vmclear(struct cpu_info*, struct vcpu *); #endif #ifdef VMM_DEBUG void vmx_vcpu_dump_regs(struct vcpu *); void vmx_dump_vmcs(struct vcpu *); const char *msr_name_decode(uint32_t); void vmm_segment_desc_decode(uint64_t); void vmm_decode_cr0(uint64_t); void vmm_decode_cr3(uint64_t); void vmm_decode_cr4(uint64_t); void vmm_decode_msr_value(uint64_t, uint64_t); void vmm_decode_apicbase_msr_value(uint64_t); void vmm_decode_ia32_fc_value(uint64_t); void vmm_decode_mtrrcap_value(uint64_t); void vmm_decode_perf_status_value(uint64_t); void vmm_decode_perf_ctl_value(uint64_t); void vmm_decode_mtrrdeftype_value(uint64_t); void vmm_decode_efer_value(uint64_t); void vmm_decode_rflags(uint64_t); void vmm_decode_misc_enable_value(uint64_t); const char *vmm_decode_cpu_mode(struct vcpu *); extern int mtrr2mrt(int); struct vmm_reg_debug_info { uint64_t vrdi_bit; const char *vrdi_present; const char *vrdi_absent; }; #endif /* VMM_DEBUG */ extern uint64_t tsc_frequency; extern int tsc_is_invariant; const char *vmm_hv_signature = VMM_HV_SIGNATURE; const struct kmem_pa_mode vmm_kp_contig = { .kp_constraint = &no_constraint, .kp_maxseg = 1, .kp_align = 4096, .kp_zero = 1, }; extern struct cfdriver vmm_cd; extern const struct cfattach vmm_ca; /* * Helper struct to easily get the VMCS field IDs needed in vmread/vmwrite * to access the individual fields of the guest segment registers. This * struct is indexed by VCPU_REGS_* id. */ const struct { uint64_t selid; uint64_t limitid; uint64_t arid; uint64_t baseid; } vmm_vmx_sreg_vmcs_fields[] = { { VMCS_GUEST_IA32_ES_SEL, VMCS_GUEST_IA32_ES_LIMIT, VMCS_GUEST_IA32_ES_AR, VMCS_GUEST_IA32_ES_BASE }, { VMCS_GUEST_IA32_CS_SEL, VMCS_GUEST_IA32_CS_LIMIT, VMCS_GUEST_IA32_CS_AR, VMCS_GUEST_IA32_CS_BASE }, { VMCS_GUEST_IA32_SS_SEL, VMCS_GUEST_IA32_SS_LIMIT, VMCS_GUEST_IA32_SS_AR, VMCS_GUEST_IA32_SS_BASE }, { VMCS_GUEST_IA32_DS_SEL, VMCS_GUEST_IA32_DS_LIMIT, VMCS_GUEST_IA32_DS_AR, VMCS_GUEST_IA32_DS_BASE }, { VMCS_GUEST_IA32_FS_SEL, VMCS_GUEST_IA32_FS_LIMIT, VMCS_GUEST_IA32_FS_AR, VMCS_GUEST_IA32_FS_BASE }, { VMCS_GUEST_IA32_GS_SEL, VMCS_GUEST_IA32_GS_LIMIT, VMCS_GUEST_IA32_GS_AR, VMCS_GUEST_IA32_GS_BASE }, { VMCS_GUEST_IA32_LDTR_SEL, VMCS_GUEST_IA32_LDTR_LIMIT, VMCS_GUEST_IA32_LDTR_AR, VMCS_GUEST_IA32_LDTR_BASE }, { VMCS_GUEST_IA32_TR_SEL, VMCS_GUEST_IA32_TR_LIMIT, VMCS_GUEST_IA32_TR_AR, VMCS_GUEST_IA32_TR_BASE } }; /* Pools for VMs and VCPUs */ extern struct pool vm_pool; extern struct pool vcpu_pool; extern struct vmm_softc *vmm_softc; /* IDT information used when populating host state area */ extern vaddr_t idt_vaddr; extern struct gate_descriptor *idt; /* Constants used in "CR access exit" */ #define CR_WRITE 0 #define CR_READ 1 #define CR_CLTS 2 #define CR_LMSW 3 /* * vmm_enabled * * Checks if we have at least one CPU with either VMX or SVM. * Returns 1 if we have at least one of either type, but not both, 0 otherwise. */ int vmm_enabled(void) { struct cpu_info *ci; CPU_INFO_ITERATOR cii; int found_vmx = 0, found_svm = 0; /* Check if we have at least one CPU with either VMX or SVM */ CPU_INFO_FOREACH(cii, ci) { if (ci->ci_vmm_flags & CI_VMM_VMX) found_vmx = 1; if (ci->ci_vmm_flags & CI_VMM_SVM) found_svm = 1; } /* Don't support both SVM and VMX at the same time */ if (found_vmx && found_svm) return (0); if (found_vmx || found_svm) return 1; return 0; } void vmm_attach_machdep(struct device *parent, struct device *self, void *aux) { struct vmm_softc *sc = (struct vmm_softc *)self; struct cpu_info *ci; CPU_INFO_ITERATOR cii; sc->sc_md.nr_rvi_cpus = 0; sc->sc_md.nr_ept_cpus = 0; /* Calculate CPU features */ CPU_INFO_FOREACH(cii, ci) { if (ci->ci_vmm_flags & CI_VMM_RVI) sc->sc_md.nr_rvi_cpus++; if (ci->ci_vmm_flags & CI_VMM_EPT) sc->sc_md.nr_ept_cpus++; } sc->sc_md.pkru_enabled = 0; if (rcr4() & CR4_PKE) sc->sc_md.pkru_enabled = 1; if (sc->sc_md.nr_ept_cpus) { printf(": VMX/EPT"); sc->mode = VMM_MODE_EPT; } else if (sc->sc_md.nr_rvi_cpus) { printf(": SVM/RVI"); sc->mode = VMM_MODE_RVI; } else { printf(": unknown"); sc->mode = VMM_MODE_UNKNOWN; } if (sc->mode == VMM_MODE_EPT) { if (!(curcpu()->ci_vmm_cap.vcc_vmx.vmx_has_l1_flush_msr)) { l1tf_flush_region = km_alloc(VMX_L1D_FLUSH_SIZE, &kv_any, &vmm_kp_contig, &kd_waitok); if (!l1tf_flush_region) { printf(" (failing, no memory)"); sc->mode = VMM_MODE_UNKNOWN; } else { printf(" (using slow L1TF mitigation)"); memset(l1tf_flush_region, 0xcc, VMX_L1D_FLUSH_SIZE); } } } if (sc->mode == VMM_MODE_RVI) { sc->max_vpid = curcpu()->ci_vmm_cap.vcc_svm.svm_max_asid; } else { sc->max_vpid = 0xFFF; } bzero(&sc->vpids, sizeof(sc->vpids)); rw_init(&sc->vpid_lock, "vpid"); } /* * vmm_quiesce_vmx * * Prepare the host for suspend by flushing all VMCS states. */ int vmm_quiesce_vmx(void) { struct vm *vm; struct vcpu *vcpu; int err; /* * We should be only called from a quiescing device state so we * don't expect to sleep here. If we can't get all our locks, * something is wrong. */ if ((err = rw_enter(&vmm_softc->vm_lock, RW_WRITE | RW_NOSLEEP))) return (err); /* Iterate over each vm... */ SLIST_FOREACH(vm, &vmm_softc->vm_list, vm_link) { /* Iterate over each vcpu... */ SLIST_FOREACH(vcpu, &vm->vm_vcpu_list, vc_vcpu_link) { err = rw_enter(&vcpu->vc_lock, RW_WRITE | RW_NOSLEEP); if (err) break; /* We can skip unlaunched VMCS. Nothing to flush. */ if (atomic_load_int(&vcpu->vc_vmx_vmcs_state) != VMCS_LAUNCHED) { DPRINTF("%s: skipping vcpu %d for vm %d\n", __func__, vcpu->vc_id, vm->vm_id); rw_exit_write(&vcpu->vc_lock); continue; } #ifdef MULTIPROCESSOR if (vcpu->vc_last_pcpu != curcpu()) { /* Remote cpu vmclear via ipi. */ err = vmx_remote_vmclear(vcpu->vc_last_pcpu, vcpu); if (err) printf("%s: failed to remote vmclear " "vcpu %d of vm %d\n", __func__, vcpu->vc_id, vm->vm_id); } else #endif { /* Local cpu vmclear instruction. */ if ((err = vmclear(&vcpu->vc_control_pa))) printf("%s: failed to locally vmclear " "vcpu %d of vm %d\n", __func__, vcpu->vc_id, vm->vm_id); atomic_swap_uint(&vcpu->vc_vmx_vmcs_state, VMCS_CLEARED); } rw_exit_write(&vcpu->vc_lock); if (err) break; DPRINTF("%s: cleared vcpu %d for vm %d\n", __func__, vcpu->vc_id, vm->vm_id); } if (err) break; } rw_exit_write(&vmm_softc->vm_lock); if (err) return (err); return (0); } void vmm_activate_machdep(struct device *self, int act) { struct cpu_info *ci = curcpu(); switch (act) { case DVACT_QUIESCE: /* If we're not in vmm mode, nothing to do. */ if ((ci->ci_flags & CPUF_VMM) == 0) break; /* Intel systems need extra steps to sync vcpu state. */ if (vmm_softc->mode == VMM_MODE_EPT) if (vmm_quiesce_vmx()) DPRINTF("%s: vmx quiesce failed\n", __func__); /* Stop virtualization mode on all cpus. */ vmm_stop(); break; case DVACT_WAKEUP: /* Restart virtualization mode on all cpu's. */ if (vmm_softc->vm_ct > 0) vmm_start(); break; } } int vmmioctl_machdep(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { int ret; switch (cmd) { case VMM_IOC_INTR: ret = vm_intr_pending((struct vm_intr_params *)data); break; case VMM_IOC_MPROTECT_EPT: ret = vm_mprotect_ept((struct vm_mprotect_ept_params *)data); break; default: DPRINTF("%s: unknown ioctl code 0x%lx\n", __func__, cmd); ret = ENOTTY; } return (ret); } int pledge_ioctl_vmm_machdep(struct proc *p, long com) { switch (com) { case VMM_IOC_INTR: case VMM_IOC_MPROTECT_EPT: return (0); } return (EPERM); } /* * vm_intr_pending * * IOCTL handler routine for VMM_IOC_INTR messages, sent from vmd when an * interrupt is pending and needs acknowledgment * * Parameters: * vip: Describes the vm/vcpu for which the interrupt is pending * * Return values: * 0: if successful * ENOENT: if the VM/VCPU defined by 'vip' cannot be found */ int vm_intr_pending(struct vm_intr_params *vip) { struct vm *vm; struct vcpu *vcpu; #ifdef MULTIPROCESSOR struct cpu_info *ci; #endif int error, ret = 0; /* Find the desired VM */ error = vm_find(vip->vip_vm_id, &vm); /* Not found? exit. */ if (error != 0) return (error); vcpu = vm_find_vcpu(vm, vip->vip_vcpu_id); if (vcpu == NULL) { ret = ENOENT; goto out; } vcpu->vc_intr = vip->vip_intr; #ifdef MULTIPROCESSOR ci = READ_ONCE(vcpu->vc_curcpu); if (ci != NULL) x86_send_ipi(ci, X86_IPI_NOP); #endif out: refcnt_rele_wake(&vm->vm_refcnt); return (ret); } /* * vm_rwvmparams * * IOCTL handler to read/write the current vmm params like pvclock gpa, pvclock * version, etc. * * Parameters: * vrwp: Describes the VM and VCPU to get/set the params from * dir: 0 for reading, 1 for writing * * Return values: * 0: if successful * ENOENT: if the VM/VCPU defined by 'vpp' cannot be found * EINVAL: if an error occurred reading the registers of the guest */ int vm_rwvmparams(struct vm_rwvmparams_params *vpp, int dir) { struct vm *vm; struct vcpu *vcpu; int error, ret = 0; /* Find the desired VM */ error = vm_find(vpp->vpp_vm_id, &vm); /* Not found? exit. */ if (error != 0) return (error); vcpu = vm_find_vcpu(vm, vpp->vpp_vcpu_id); if (vcpu == NULL) { ret = ENOENT; goto out; } if (dir == 0) { if (vpp->vpp_mask & VM_RWVMPARAMS_PVCLOCK_VERSION) vpp->vpp_pvclock_version = vcpu->vc_pvclock_version; if (vpp->vpp_mask & VM_RWVMPARAMS_PVCLOCK_SYSTEM_GPA) vpp->vpp_pvclock_system_gpa = \ vcpu->vc_pvclock_system_gpa; } else { if (vpp->vpp_mask & VM_RWVMPARAMS_PVCLOCK_VERSION) vcpu->vc_pvclock_version = vpp->vpp_pvclock_version; if (vpp->vpp_mask & VM_RWVMPARAMS_PVCLOCK_SYSTEM_GPA) { vmm_init_pvclock(vcpu, vpp->vpp_pvclock_system_gpa); } } out: refcnt_rele_wake(&vm->vm_refcnt); return (ret); } /* * vm_readregs * * IOCTL handler to read/write the current register values of a guest VCPU. * The VCPU must not be running. * * Parameters: * vrwp: Describes the VM and VCPU to get/set the registers from. The * register values are returned here as well. * dir: 0 for reading, 1 for writing * * Return values: * 0: if successful * ENOENT: if the VM/VCPU defined by 'vrwp' cannot be found * EINVAL: if an error occurred accessing the registers of the guest * EPERM: if the vm cannot be accessed from the calling process */ int vm_rwregs(struct vm_rwregs_params *vrwp, int dir) { struct vm *vm; struct vcpu *vcpu; struct vcpu_reg_state *vrs = &vrwp->vrwp_regs; int error, ret = 0; /* Find the desired VM */ error = vm_find(vrwp->vrwp_vm_id, &vm); /* Not found? exit. */ if (error != 0) return (error); vcpu = vm_find_vcpu(vm, vrwp->vrwp_vcpu_id); if (vcpu == NULL) { ret = ENOENT; goto out; } rw_enter_write(&vcpu->vc_lock); if (vmm_softc->mode == VMM_MODE_EPT) ret = (dir == 0) ? vcpu_readregs_vmx(vcpu, vrwp->vrwp_mask, 1, vrs) : vcpu_writeregs_vmx(vcpu, vrwp->vrwp_mask, 1, vrs); else if (vmm_softc->mode == VMM_MODE_RVI) ret = (dir == 0) ? vcpu_readregs_svm(vcpu, vrwp->vrwp_mask, vrs) : vcpu_writeregs_svm(vcpu, vrwp->vrwp_mask, vrs); else { DPRINTF("%s: unknown vmm mode", __func__); ret = EINVAL; } rw_exit_write(&vcpu->vc_lock); out: refcnt_rele_wake(&vm->vm_refcnt); return (ret); } /* * vm_mprotect_ept * * IOCTL handler to sets the access protections of the ept * * Parameters: * vmep: describes the memory for which the protect will be applied.. * * Return values: * 0: if successful * ENOENT: if the VM defined by 'vmep' cannot be found * EINVAL: if the sgpa or size is not page aligned, the prot is invalid, * size is too large (512GB), there is wraparound * (like start = 512GB-1 and end = 512GB-2), * the address specified is not within the vm's mem range * or the address lies inside reserved (MMIO) memory */ int vm_mprotect_ept(struct vm_mprotect_ept_params *vmep) { struct vm *vm; struct vcpu *vcpu; vaddr_t sgpa; size_t size; vm_prot_t prot; uint64_t msr; int ret = 0, memtype; /* If not EPT or RVI, nothing to do here */ if (!(vmm_softc->mode == VMM_MODE_EPT || vmm_softc->mode == VMM_MODE_RVI)) return (0); /* Find the desired VM */ ret = vm_find(vmep->vmep_vm_id, &vm); /* Not found? exit. */ if (ret != 0) { DPRINTF("%s: vm id %u not found\n", __func__, vmep->vmep_vm_id); return (ret); } vcpu = vm_find_vcpu(vm, vmep->vmep_vcpu_id); if (vcpu == NULL) { DPRINTF("%s: vcpu id %u of vm %u not found\n", __func__, vmep->vmep_vcpu_id, vmep->vmep_vm_id); ret = ENOENT; goto out_nolock; } rw_enter_write(&vcpu->vc_lock); if (vcpu->vc_state != VCPU_STATE_STOPPED) { DPRINTF("%s: mprotect_ept %u on vm %u attempted " "while vcpu was in state %u (%s)\n", __func__, vmep->vmep_vcpu_id, vmep->vmep_vm_id, vcpu->vc_state, vcpu_state_decode(vcpu->vc_state)); ret = EBUSY; goto out; } /* Only proceed if the pmap is in the correct mode */ KASSERT((vmm_softc->mode == VMM_MODE_EPT && vm->vm_map->pmap->pm_type == PMAP_TYPE_EPT) || (vmm_softc->mode == VMM_MODE_RVI && vm->vm_map->pmap->pm_type == PMAP_TYPE_RVI)); sgpa = vmep->vmep_sgpa; size = vmep->vmep_size; prot = vmep->vmep_prot; /* No W^X permissions */ if ((prot & PROT_MASK) != prot && (prot & (PROT_WRITE | PROT_EXEC)) == (PROT_WRITE | PROT_EXEC)) { DPRINTF("%s: W+X permission requested\n", __func__); ret = EINVAL; goto out; } /* No Write only permissions */ if ((prot & (PROT_READ | PROT_WRITE | PROT_EXEC)) == PROT_WRITE) { DPRINTF("%s: No Write only permissions\n", __func__); ret = EINVAL; goto out; } /* No empty permissions */ if (prot == 0) { DPRINTF("%s: No empty permissions\n", __func__); ret = EINVAL; goto out; } /* No execute only on EPT CPUs that don't have that capability */ if (vmm_softc->mode == VMM_MODE_EPT) { msr = rdmsr(IA32_VMX_EPT_VPID_CAP); if (prot == PROT_EXEC && (msr & IA32_EPT_VPID_CAP_XO_TRANSLATIONS) == 0) { DPRINTF("%s: Execute only permissions unsupported," " adding read permission\n", __func__); prot |= PROT_READ; } } /* Must be page aligned */ if ((sgpa & PAGE_MASK) || (size & PAGE_MASK) || size == 0) { ret = EINVAL; goto out; } /* size must be less then 512GB */ if (size >= NBPD_L4) { ret = EINVAL; goto out; } /* no wraparound */ if (sgpa + size < sgpa) { ret = EINVAL; goto out; } /* * Specifying addresses within the PCI MMIO space is forbidden. * Disallow addresses that start inside the MMIO space: * [VMM_PCI_MMIO_BAR_BASE .. VMM_PCI_MMIO_BAR_END] */ if (sgpa >= VMM_PCI_MMIO_BAR_BASE && sgpa <= VMM_PCI_MMIO_BAR_END) { ret = EINVAL; goto out; } /* * ... and disallow addresses that end inside the MMIO space: * (VMM_PCI_MMIO_BAR_BASE .. VMM_PCI_MMIO_BAR_END] */ if (sgpa + size > VMM_PCI_MMIO_BAR_BASE && sgpa + size <= VMM_PCI_MMIO_BAR_END) { ret = EINVAL; goto out; } memtype = vmm_get_guest_memtype(vm, sgpa); if (memtype == VMM_MEM_TYPE_UNKNOWN) { ret = EINVAL; goto out; } if (vmm_softc->mode == VMM_MODE_EPT) ret = vmx_mprotect_ept(vm->vm_map, sgpa, sgpa + size, prot); else if (vmm_softc->mode == VMM_MODE_RVI) { pmap_write_protect(vm->vm_map->pmap, sgpa, sgpa + size, prot); /* XXX requires a invlpga */ ret = 0; } else ret = EINVAL; out: if (vcpu != NULL) rw_exit_write(&vcpu->vc_lock); out_nolock: refcnt_rele_wake(&vm->vm_refcnt); return (ret); } /* * vmx_mprotect_ept * * apply the ept protections to the requested pages, faulting in the page if * required. */ int vmx_mprotect_ept(vm_map_t vm_map, paddr_t sgpa, paddr_t egpa, int prot) { struct vmx_invept_descriptor vid; pmap_t pmap; pt_entry_t *pte; paddr_t addr; int ret = 0; pmap = vm_map->pmap; KERNEL_LOCK(); for (addr = sgpa; addr < egpa; addr += PAGE_SIZE) { pte = vmx_pmap_find_pte_ept(pmap, addr); if (pte == NULL) { ret = uvm_fault(vm_map, addr, VM_FAULT_WIRE, PROT_READ | PROT_WRITE | PROT_EXEC); if (ret) printf("%s: uvm_fault returns %d, GPA=0x%llx\n", __func__, ret, (uint64_t)addr); pte = vmx_pmap_find_pte_ept(pmap, addr); if (pte == NULL) { KERNEL_UNLOCK(); return EFAULT; } } if (prot & PROT_READ) *pte |= EPT_R; else *pte &= ~EPT_R; if (prot & PROT_WRITE) *pte |= EPT_W; else *pte &= ~EPT_W; if (prot & PROT_EXEC) *pte |= EPT_X; else *pte &= ~EPT_X; } /* * SDM 3C: 28.3.3.4 Guidelines for Use of the INVEPT Instruction * the first bullet point seems to say we should call invept. * * Software should use the INVEPT instruction with the “single-context” * INVEPT type after making any of the following changes to an EPT * paging-structure entry (the INVEPT descriptor should contain an * EPTP value that references — directly or indirectly * — the modified EPT paging structure): * — Changing any of the privilege bits 2:0 from 1 to 0. * */ if (pmap->eptp != 0) { memset(&vid, 0, sizeof(vid)); vid.vid_eptp = pmap->eptp; DPRINTF("%s: flushing EPT TLB for EPTP 0x%llx\n", __func__, vid.vid_eptp); invept(IA32_VMX_INVEPT_SINGLE_CTX, &vid); } KERNEL_UNLOCK(); return ret; } /* * vmx_pmap_find_pte_ept * * find the page table entry specified by addr in the pmap supplied. */ pt_entry_t * vmx_pmap_find_pte_ept(pmap_t pmap, paddr_t addr) { int l4idx, l3idx, l2idx, l1idx; pd_entry_t *pd; paddr_t pdppa; pt_entry_t *ptes, *pte; l4idx = (addr & L4_MASK) >> L4_SHIFT; /* PML4E idx */ l3idx = (addr & L3_MASK) >> L3_SHIFT; /* PDPTE idx */ l2idx = (addr & L2_MASK) >> L2_SHIFT; /* PDE idx */ l1idx = (addr & L1_MASK) >> L1_SHIFT; /* PTE idx */ pd = (pd_entry_t *)pmap->pm_pdir; if (pd == NULL) return NULL; /* * l4idx should always be 0 since we don't support more than 512GB * guest physical memory. */ if (l4idx > 0) return NULL; /* * l3idx should always be < MAXDSIZ/1GB because we don't support more * than MAXDSIZ guest phys mem. */ if (l3idx >= MAXDSIZ / ((paddr_t)1024 * 1024 * 1024)) return NULL; pdppa = pd[l4idx] & PG_FRAME; if (pdppa == 0) return NULL; ptes = (pt_entry_t *)PMAP_DIRECT_MAP(pdppa); pdppa = ptes[l3idx] & PG_FRAME; if (pdppa == 0) return NULL; ptes = (pt_entry_t *)PMAP_DIRECT_MAP(pdppa); pdppa = ptes[l2idx] & PG_FRAME; if (pdppa == 0) return NULL; ptes = (pt_entry_t *)PMAP_DIRECT_MAP(pdppa); pte = &ptes[l1idx]; if (*pte == 0) return NULL; return pte; } /* * vmm_start * * Starts VMM mode on the system */ int vmm_start(void) { int rv = 0; struct cpu_info *self = curcpu(); #ifdef MULTIPROCESSOR struct cpu_info *ci; CPU_INFO_ITERATOR cii; #ifdef MP_LOCKDEBUG int nticks; #endif /* MP_LOCKDEBUG */ #endif /* MULTIPROCESSOR */ rw_enter_write(&vmm_softc->sc_slock); /* VMM is already running */ if (self->ci_flags & CPUF_VMM) goto unlock; /* Start VMM on this CPU */ start_vmm_on_cpu(self); if (!(self->ci_flags & CPUF_VMM)) { printf("%s: failed to enter VMM mode\n", self->ci_dev->dv_xname); rv = EIO; goto unlock; } #ifdef MULTIPROCESSOR /* Broadcast start VMM IPI */ x86_broadcast_ipi(X86_IPI_START_VMM); CPU_INFO_FOREACH(cii, ci) { if (ci == self) continue; #ifdef MP_LOCKDEBUG nticks = __mp_lock_spinout; #endif /* MP_LOCKDEBUG */ while (!(ci->ci_flags & CPUF_VMM)) { CPU_BUSY_CYCLE(); #ifdef MP_LOCKDEBUG if (--nticks <= 0) { db_printf("%s: spun out", __func__); db_enter(); nticks = __mp_lock_spinout; } #endif /* MP_LOCKDEBUG */ } } #endif /* MULTIPROCESSOR */ unlock: rw_exit_write(&vmm_softc->sc_slock); return (rv); } /* * vmm_stop * * Stops VMM mode on the system */ int vmm_stop(void) { int rv = 0; struct cpu_info *self = curcpu(); #ifdef MULTIPROCESSOR struct cpu_info *ci; CPU_INFO_ITERATOR cii; #ifdef MP_LOCKDEBUG int nticks; #endif /* MP_LOCKDEBUG */ #endif /* MULTIPROCESSOR */ rw_enter_write(&vmm_softc->sc_slock); /* VMM is not running */ if (!(self->ci_flags & CPUF_VMM)) goto unlock; /* Stop VMM on this CPU */ stop_vmm_on_cpu(self); if (self->ci_flags & CPUF_VMM) { printf("%s: failed to exit VMM mode\n", self->ci_dev->dv_xname); rv = EIO; goto unlock; } #ifdef MULTIPROCESSOR /* Stop VMM on other CPUs */ x86_broadcast_ipi(X86_IPI_STOP_VMM); CPU_INFO_FOREACH(cii, ci) { if (ci == self) continue; #ifdef MP_LOCKDEBUG nticks = __mp_lock_spinout; #endif /* MP_LOCKDEBUG */ while ((ci->ci_flags & CPUF_VMM)) { CPU_BUSY_CYCLE(); #ifdef MP_LOCKDEBUG if (--nticks <= 0) { db_printf("%s: spunout", __func__); db_enter(); nticks = __mp_lock_spinout; } #endif /* MP_LOCKDEBUG */ } } #endif /* MULTIPROCESSOR */ unlock: rw_exit_write(&vmm_softc->sc_slock); return (0); } /* * start_vmm_on_cpu * * Starts VMM mode on 'ci' by executing the appropriate CPU-specific insn * sequence to enter VMM mode (eg, VMXON) */ void start_vmm_on_cpu(struct cpu_info *ci) { uint64_t msr; uint32_t cr4; struct vmx_invept_descriptor vid; /* No VMM mode? exit. */ if ((ci->ci_vmm_flags & CI_VMM_VMX) == 0 && (ci->ci_vmm_flags & CI_VMM_SVM) == 0) return; /* * AMD SVM */ if (ci->ci_vmm_flags & CI_VMM_SVM) { msr = rdmsr(MSR_EFER); msr |= EFER_SVME; wrmsr(MSR_EFER, msr); } /* * Intel VMX */ if (ci->ci_vmm_flags & CI_VMM_VMX) { if (ci->ci_vmxon_region == 0) return; else { bzero(ci->ci_vmxon_region, PAGE_SIZE); ci->ci_vmxon_region->vr_revision = ci->ci_vmm_cap.vcc_vmx.vmx_vmxon_revision; /* Enable VMX */ msr = rdmsr(MSR_IA32_FEATURE_CONTROL); if (msr & IA32_FEATURE_CONTROL_LOCK) { if (!(msr & IA32_FEATURE_CONTROL_VMX_EN)) return; } else { msr |= IA32_FEATURE_CONTROL_VMX_EN | IA32_FEATURE_CONTROL_LOCK; wrmsr(MSR_IA32_FEATURE_CONTROL, msr); } /* Set CR4.VMXE */ cr4 = rcr4(); cr4 |= CR4_VMXE; lcr4(cr4); /* Enter VMX mode and clear EPTs on this cpu */ if (vmxon((uint64_t *)&ci->ci_vmxon_region_pa)) panic("vmxon failed"); memset(&vid, 0, sizeof(vid)); if (invept(IA32_VMX_INVEPT_GLOBAL_CTX, &vid)) panic("invept failed"); } } atomic_setbits_int(&ci->ci_flags, CPUF_VMM); } /* * stop_vmm_on_cpu * * Stops VMM mode on 'ci' by executing the appropriate CPU-specific insn * sequence to exit VMM mode (eg, VMXOFF) */ void stop_vmm_on_cpu(struct cpu_info *ci) { uint64_t msr; uint32_t cr4; if (!(ci->ci_flags & CPUF_VMM)) return; /* * AMD SVM */ if (ci->ci_vmm_flags & CI_VMM_SVM) { msr = rdmsr(MSR_EFER); msr &= ~EFER_SVME; wrmsr(MSR_EFER, msr); } /* * Intel VMX */ if (ci->ci_vmm_flags & CI_VMM_VMX) { if (vmxoff()) panic("VMXOFF failed"); cr4 = rcr4(); cr4 &= ~CR4_VMXE; lcr4(cr4); } atomic_clearbits_int(&ci->ci_flags, CPUF_VMM); } /* * vmclear_on_cpu * * Flush and clear VMCS on 'ci' by executing vmclear. * */ void vmclear_on_cpu(struct cpu_info *ci) { if ((ci->ci_flags & CPUF_VMM) && (ci->ci_vmm_flags & CI_VMM_VMX)) { if (vmclear(&ci->ci_vmcs_pa)) panic("VMCLEAR ipi failed"); atomic_swap_ulong(&ci->ci_vmcs_pa, VMX_VMCS_PA_CLEAR); } } #ifdef MULTIPROCESSOR static int vmx_remote_vmclear(struct cpu_info *ci, struct vcpu *vcpu) { #ifdef MP_LOCKDEBUG int nticks = __mp_lock_spinout; #endif /* MP_LOCKDEBUG */ rw_enter_write(&ci->ci_vmcs_lock); atomic_swap_ulong(&ci->ci_vmcs_pa, vcpu->vc_control_pa); x86_send_ipi(ci, X86_IPI_VMCLEAR_VMM); while (ci->ci_vmcs_pa != VMX_VMCS_PA_CLEAR) { CPU_BUSY_CYCLE(); #ifdef MP_LOCKDEBUG if (--nticks <= 0) { db_printf("%s: spun out\n", __func__); db_enter(); nticks = __mp_lock_spinout; } #endif /* MP_LOCKDEBUG */ } atomic_swap_uint(&vcpu->vc_vmx_vmcs_state, VMCS_CLEARED); rw_exit_write(&ci->ci_vmcs_lock); return (0); } #endif /* MULTIPROCESSOR */ /* * vm_impl_init * * VM address space initialization routine * * Parameters: * vm: the VM being initialized * p: vmd process owning the VM * * Return values: * 0: the initialization was successful * EINVAL: unsupported vmm mode * ENOMEM: the initialization failed (lack of resources) */ int vm_impl_init(struct vm *vm, struct proc *p) { int i, mode, ret; vaddr_t mingpa, maxgpa; struct vm_mem_range *vmr; /* If not EPT or RVI, nothing to do here */ switch (vmm_softc->mode) { case VMM_MODE_EPT: mode = PMAP_TYPE_EPT; break; case VMM_MODE_RVI: mode = PMAP_TYPE_RVI; break; default: printf("%s: invalid vmm mode %d\n", __func__, vmm_softc->mode); return (EINVAL); } vmr = &vm->vm_memranges[0]; mingpa = vmr->vmr_gpa; vmr = &vm->vm_memranges[vm->vm_nmemranges - 1]; maxgpa = vmr->vmr_gpa + vmr->vmr_size; /* * uvmspace_alloc (currently) always returns a valid vmspace */ vm->vm_vmspace = uvmspace_alloc(mingpa, maxgpa, TRUE, FALSE); vm->vm_map = &vm->vm_vmspace->vm_map; /* Map the new map with an anon */ DPRINTF("%s: created vm_map @ %p\n", __func__, vm->vm_map); for (i = 0; i < vm->vm_nmemranges; i++) { vmr = &vm->vm_memranges[i]; ret = uvm_share(vm->vm_map, vmr->vmr_gpa, PROT_READ | PROT_WRITE | PROT_EXEC, &p->p_vmspace->vm_map, vmr->vmr_va, vmr->vmr_size); if (ret) { printf("%s: uvm_share failed (%d)\n", __func__, ret); /* uvmspace_free calls pmap_destroy for us */ KERNEL_LOCK(); uvmspace_free(vm->vm_vmspace); vm->vm_vmspace = NULL; KERNEL_UNLOCK(); return (ENOMEM); } } pmap_convert(vm->vm_map->pmap, mode); return (0); } void vm_impl_deinit(struct vm *vm) { /* unused */ } /* * vcpu_reload_vmcs_vmx * * (Re)load the VMCS on the current cpu. Must be called with the VMCS write * lock acquired. If the VMCS is determined to be loaded on a remote cpu, an * ipi will be used to remotely flush it before loading the VMCS locally. * * Parameters: * vcpu: Pointer to the vcpu needing its VMCS * * Return values: * 0: if successful * EINVAL: an error occurred during flush or reload */ int vcpu_reload_vmcs_vmx(struct vcpu *vcpu) { struct cpu_info *ci, *last_ci; rw_assert_wrlock(&vcpu->vc_lock); ci = curcpu(); last_ci = vcpu->vc_last_pcpu; if (last_ci == NULL) { /* First launch */ if (vmclear(&vcpu->vc_control_pa)) return (EINVAL); atomic_swap_uint(&vcpu->vc_vmx_vmcs_state, VMCS_CLEARED); #ifdef MULTIPROCESSOR } else if (last_ci != ci) { /* We've moved CPUs at some point, so remote VMCLEAR */ if (vmx_remote_vmclear(last_ci, vcpu)) return (EINVAL); KASSERT(vcpu->vc_vmx_vmcs_state == VMCS_CLEARED); #endif /* MULTIPROCESSOR */ } if (vmptrld(&vcpu->vc_control_pa)) { printf("%s: vmptrld\n", __func__); return (EINVAL); } return (0); } /* * vcpu_readregs_vmx * * Reads 'vcpu's registers * * Parameters: * vcpu: the vcpu to read register values from * regmask: the types of registers to read * loadvmcs: bit to indicate whether the VMCS has to be loaded first * vrs: output parameter where register values are stored * * Return values: * 0: if successful * EINVAL: an error reading registers occurred */ int vcpu_readregs_vmx(struct vcpu *vcpu, uint64_t regmask, int loadvmcs, struct vcpu_reg_state *vrs) { int i, ret = 0; uint64_t sel, limit, ar; uint64_t *gprs = vrs->vrs_gprs; uint64_t *crs = vrs->vrs_crs; uint64_t *msrs = vrs->vrs_msrs; uint64_t *drs = vrs->vrs_drs; struct vcpu_segment_info *sregs = vrs->vrs_sregs; struct vmx_msr_store *msr_store; if (loadvmcs) { if (vcpu_reload_vmcs_vmx(vcpu)) return (EINVAL); } #ifdef VMM_DEBUG /* VMCS should be loaded... */ paddr_t pa = 0ULL; if (vmptrst(&pa)) panic("%s: vmptrst", __func__); KASSERT(pa == vcpu->vc_control_pa); #endif /* VMM_DEBUG */ if (regmask & VM_RWREGS_GPRS) { gprs[VCPU_REGS_RAX] = vcpu->vc_gueststate.vg_rax; gprs[VCPU_REGS_RBX] = vcpu->vc_gueststate.vg_rbx; gprs[VCPU_REGS_RCX] = vcpu->vc_gueststate.vg_rcx; gprs[VCPU_REGS_RDX] = vcpu->vc_gueststate.vg_rdx; gprs[VCPU_REGS_RSI] = vcpu->vc_gueststate.vg_rsi; gprs[VCPU_REGS_RDI] = vcpu->vc_gueststate.vg_rdi; gprs[VCPU_REGS_R8] = vcpu->vc_gueststate.vg_r8; gprs[VCPU_REGS_R9] = vcpu->vc_gueststate.vg_r9; gprs[VCPU_REGS_R10] = vcpu->vc_gueststate.vg_r10; gprs[VCPU_REGS_R11] = vcpu->vc_gueststate.vg_r11; gprs[VCPU_REGS_R12] = vcpu->vc_gueststate.vg_r12; gprs[VCPU_REGS_R13] = vcpu->vc_gueststate.vg_r13; gprs[VCPU_REGS_R14] = vcpu->vc_gueststate.vg_r14; gprs[VCPU_REGS_R15] = vcpu->vc_gueststate.vg_r15; gprs[VCPU_REGS_RBP] = vcpu->vc_gueststate.vg_rbp; gprs[VCPU_REGS_RIP] = vcpu->vc_gueststate.vg_rip; if (vmread(VMCS_GUEST_IA32_RSP, &gprs[VCPU_REGS_RSP])) goto errout; if (vmread(VMCS_GUEST_IA32_RFLAGS, &gprs[VCPU_REGS_RFLAGS])) goto errout; } if (regmask & VM_RWREGS_SREGS) { for (i = 0; i < nitems(vmm_vmx_sreg_vmcs_fields); i++) { if (vmread(vmm_vmx_sreg_vmcs_fields[i].selid, &sel)) goto errout; if (vmread(vmm_vmx_sreg_vmcs_fields[i].limitid, &limit)) goto errout; if (vmread(vmm_vmx_sreg_vmcs_fields[i].arid, &ar)) goto errout; if (vmread(vmm_vmx_sreg_vmcs_fields[i].baseid, &sregs[i].vsi_base)) goto errout; sregs[i].vsi_sel = sel; sregs[i].vsi_limit = limit; sregs[i].vsi_ar = ar; } if (vmread(VMCS_GUEST_IA32_GDTR_LIMIT, &limit)) goto errout; if (vmread(VMCS_GUEST_IA32_GDTR_BASE, &vrs->vrs_gdtr.vsi_base)) goto errout; vrs->vrs_gdtr.vsi_limit = limit; if (vmread(VMCS_GUEST_IA32_IDTR_LIMIT, &limit)) goto errout; if (vmread(VMCS_GUEST_IA32_IDTR_BASE, &vrs->vrs_idtr.vsi_base)) goto errout; vrs->vrs_idtr.vsi_limit = limit; } if (regmask & VM_RWREGS_CRS) { crs[VCPU_REGS_CR2] = vcpu->vc_gueststate.vg_cr2; crs[VCPU_REGS_XCR0] = vcpu->vc_gueststate.vg_xcr0; if (vmread(VMCS_GUEST_IA32_CR0, &crs[VCPU_REGS_CR0])) goto errout; if (vmread(VMCS_GUEST_IA32_CR3, &crs[VCPU_REGS_CR3])) goto errout; if (vmread(VMCS_GUEST_IA32_CR4, &crs[VCPU_REGS_CR4])) goto errout; if (vmread(VMCS_GUEST_PDPTE0, &crs[VCPU_REGS_PDPTE0])) goto errout; if (vmread(VMCS_GUEST_PDPTE1, &crs[VCPU_REGS_PDPTE1])) goto errout; if (vmread(VMCS_GUEST_PDPTE2, &crs[VCPU_REGS_PDPTE2])) goto errout; if (vmread(VMCS_GUEST_PDPTE3, &crs[VCPU_REGS_PDPTE3])) goto errout; } msr_store = (struct vmx_msr_store *)vcpu->vc_vmx_msr_exit_save_va; if (regmask & VM_RWREGS_MSRS) { for (i = 0; i < VCPU_REGS_NMSRS; i++) { msrs[i] = msr_store[i].vms_data; } } if (regmask & VM_RWREGS_DRS) { drs[VCPU_REGS_DR0] = vcpu->vc_gueststate.vg_dr0; drs[VCPU_REGS_DR1] = vcpu->vc_gueststate.vg_dr1; drs[VCPU_REGS_DR2] = vcpu->vc_gueststate.vg_dr2; drs[VCPU_REGS_DR3] = vcpu->vc_gueststate.vg_dr3; drs[VCPU_REGS_DR6] = vcpu->vc_gueststate.vg_dr6; if (vmread(VMCS_GUEST_IA32_DR7, &drs[VCPU_REGS_DR7])) goto errout; } goto out; errout: ret = EINVAL; out: return (ret); } /* * vcpu_readregs_svm * * Reads 'vcpu's registers * * Parameters: * vcpu: the vcpu to read register values from * regmask: the types of registers to read * vrs: output parameter where register values are stored * * Return values: * 0: if successful */ int vcpu_readregs_svm(struct vcpu *vcpu, uint64_t regmask, struct vcpu_reg_state *vrs) { uint64_t *gprs = vrs->vrs_gprs; uint64_t *crs = vrs->vrs_crs; uint64_t *msrs = vrs->vrs_msrs; uint64_t *drs = vrs->vrs_drs; uint32_t attr; struct vcpu_segment_info *sregs = vrs->vrs_sregs; struct vmcb *vmcb = (struct vmcb *)vcpu->vc_control_va; if (regmask & VM_RWREGS_GPRS) { gprs[VCPU_REGS_RAX] = vmcb->v_rax; gprs[VCPU_REGS_RBX] = vcpu->vc_gueststate.vg_rbx; gprs[VCPU_REGS_RCX] = vcpu->vc_gueststate.vg_rcx; gprs[VCPU_REGS_RDX] = vcpu->vc_gueststate.vg_rdx; gprs[VCPU_REGS_RSI] = vcpu->vc_gueststate.vg_rsi; gprs[VCPU_REGS_RDI] = vcpu->vc_gueststate.vg_rdi; gprs[VCPU_REGS_R8] = vcpu->vc_gueststate.vg_r8; gprs[VCPU_REGS_R9] = vcpu->vc_gueststate.vg_r9; gprs[VCPU_REGS_R10] = vcpu->vc_gueststate.vg_r10; gprs[VCPU_REGS_R11] = vcpu->vc_gueststate.vg_r11; gprs[VCPU_REGS_R12] = vcpu->vc_gueststate.vg_r12; gprs[VCPU_REGS_R13] = vcpu->vc_gueststate.vg_r13; gprs[VCPU_REGS_R14] = vcpu->vc_gueststate.vg_r14; gprs[VCPU_REGS_R15] = vcpu->vc_gueststate.vg_r15; gprs[VCPU_REGS_RBP] = vcpu->vc_gueststate.vg_rbp; gprs[VCPU_REGS_RIP] = vmcb->v_rip; gprs[VCPU_REGS_RSP] = vmcb->v_rsp; gprs[VCPU_REGS_RFLAGS] = vmcb->v_rflags; } if (regmask & VM_RWREGS_SREGS) { sregs[VCPU_REGS_CS].vsi_sel = vmcb->v_cs.vs_sel; sregs[VCPU_REGS_CS].vsi_limit = vmcb->v_cs.vs_lim; attr = vmcb->v_cs.vs_attr; sregs[VCPU_REGS_CS].vsi_ar = (attr & 0xff) | ((attr << 4) & 0xf000); sregs[VCPU_REGS_CS].vsi_base = vmcb->v_cs.vs_base; sregs[VCPU_REGS_DS].vsi_sel = vmcb->v_ds.vs_sel; sregs[VCPU_REGS_DS].vsi_limit = vmcb->v_ds.vs_lim; attr = vmcb->v_ds.vs_attr; sregs[VCPU_REGS_DS].vsi_ar = (attr & 0xff) | ((attr << 4) & 0xf000); sregs[VCPU_REGS_DS].vsi_base = vmcb->v_ds.vs_base; sregs[VCPU_REGS_ES].vsi_sel = vmcb->v_es.vs_sel; sregs[VCPU_REGS_ES].vsi_limit = vmcb->v_es.vs_lim; attr = vmcb->v_es.vs_attr; sregs[VCPU_REGS_ES].vsi_ar = (attr & 0xff) | ((attr << 4) & 0xf000); sregs[VCPU_REGS_ES].vsi_base = vmcb->v_es.vs_base; sregs[VCPU_REGS_FS].vsi_sel = vmcb->v_fs.vs_sel; sregs[VCPU_REGS_FS].vsi_limit = vmcb->v_fs.vs_lim; attr = vmcb->v_fs.vs_attr; sregs[VCPU_REGS_FS].vsi_ar = (attr & 0xff) | ((attr << 4) & 0xf000); sregs[VCPU_REGS_FS].vsi_base = vmcb->v_fs.vs_base; sregs[VCPU_REGS_GS].vsi_sel = vmcb->v_gs.vs_sel; sregs[VCPU_REGS_GS].vsi_limit = vmcb->v_gs.vs_lim; attr = vmcb->v_gs.vs_attr; sregs[VCPU_REGS_GS].vsi_ar = (attr & 0xff) | ((attr << 4) & 0xf000); sregs[VCPU_REGS_GS].vsi_base = vmcb->v_gs.vs_base; sregs[VCPU_REGS_SS].vsi_sel = vmcb->v_ss.vs_sel; sregs[VCPU_REGS_SS].vsi_limit = vmcb->v_ss.vs_lim; attr = vmcb->v_ss.vs_attr; sregs[VCPU_REGS_SS].vsi_ar = (attr & 0xff) | ((attr << 4) & 0xf000); sregs[VCPU_REGS_SS].vsi_base = vmcb->v_ss.vs_base; sregs[VCPU_REGS_LDTR].vsi_sel = vmcb->v_ldtr.vs_sel; sregs[VCPU_REGS_LDTR].vsi_limit = vmcb->v_ldtr.vs_lim; attr = vmcb->v_ldtr.vs_attr; sregs[VCPU_REGS_LDTR].vsi_ar = (attr & 0xff) | ((attr << 4) & 0xf000); sregs[VCPU_REGS_LDTR].vsi_base = vmcb->v_ldtr.vs_base; sregs[VCPU_REGS_TR].vsi_sel = vmcb->v_tr.vs_sel; sregs[VCPU_REGS_TR].vsi_limit = vmcb->v_tr.vs_lim; attr = vmcb->v_tr.vs_attr; sregs[VCPU_REGS_TR].vsi_ar = (attr & 0xff) | ((attr << 4) & 0xf000); sregs[VCPU_REGS_TR].vsi_base = vmcb->v_tr.vs_base; vrs->vrs_gdtr.vsi_limit = vmcb->v_gdtr.vs_lim; vrs->vrs_gdtr.vsi_base = vmcb->v_gdtr.vs_base; vrs->vrs_idtr.vsi_limit = vmcb->v_idtr.vs_lim; vrs->vrs_idtr.vsi_base = vmcb->v_idtr.vs_base; } if (regmask & VM_RWREGS_CRS) { crs[VCPU_REGS_CR0] = vmcb->v_cr0; crs[VCPU_REGS_CR3] = vmcb->v_cr3; crs[VCPU_REGS_CR4] = vmcb->v_cr4; crs[VCPU_REGS_CR2] = vcpu->vc_gueststate.vg_cr2; crs[VCPU_REGS_XCR0] = vcpu->vc_gueststate.vg_xcr0; } if (regmask & VM_RWREGS_MSRS) { msrs[VCPU_REGS_EFER] = vmcb->v_efer; msrs[VCPU_REGS_STAR] = vmcb->v_star; msrs[VCPU_REGS_LSTAR] = vmcb->v_lstar; msrs[VCPU_REGS_CSTAR] = vmcb->v_cstar; msrs[VCPU_REGS_SFMASK] = vmcb->v_sfmask; msrs[VCPU_REGS_KGSBASE] = vmcb->v_kgsbase; } if (regmask & VM_RWREGS_DRS) { drs[VCPU_REGS_DR0] = vcpu->vc_gueststate.vg_dr0; drs[VCPU_REGS_DR1] = vcpu->vc_gueststate.vg_dr1; drs[VCPU_REGS_DR2] = vcpu->vc_gueststate.vg_dr2; drs[VCPU_REGS_DR3] = vcpu->vc_gueststate.vg_dr3; drs[VCPU_REGS_DR6] = vmcb->v_dr6; drs[VCPU_REGS_DR7] = vmcb->v_dr7; } return (0); } /* * vcpu_writeregs_vmx * * Writes VCPU registers * * Parameters: * vcpu: the vcpu that has to get its registers written to * regmask: the types of registers to write * loadvmcs: bit to indicate whether the VMCS has to be loaded first * vrs: the register values to write * * Return values: * 0: if successful * EINVAL an error writing registers occurred */ int vcpu_writeregs_vmx(struct vcpu *vcpu, uint64_t regmask, int loadvmcs, struct vcpu_reg_state *vrs) { int i, ret = 0; uint16_t sel; uint64_t limit, ar; uint64_t *gprs = vrs->vrs_gprs; uint64_t *crs = vrs->vrs_crs; uint64_t *msrs = vrs->vrs_msrs; uint64_t *drs = vrs->vrs_drs; struct vcpu_segment_info *sregs = vrs->vrs_sregs; struct vmx_msr_store *msr_store; if (loadvmcs) { if (vcpu_reload_vmcs_vmx(vcpu)) return (EINVAL); } #ifdef VMM_DEBUG /* VMCS should be loaded... */ paddr_t pa = 0ULL; if (vmptrst(&pa)) panic("%s: vmptrst", __func__); KASSERT(pa == vcpu->vc_control_pa); #endif /* VMM_DEBUG */ if (regmask & VM_RWREGS_GPRS) { vcpu->vc_gueststate.vg_rax = gprs[VCPU_REGS_RAX]; vcpu->vc_gueststate.vg_rbx = gprs[VCPU_REGS_RBX]; vcpu->vc_gueststate.vg_rcx = gprs[VCPU_REGS_RCX]; vcpu->vc_gueststate.vg_rdx = gprs[VCPU_REGS_RDX]; vcpu->vc_gueststate.vg_rsi = gprs[VCPU_REGS_RSI]; vcpu->vc_gueststate.vg_rdi = gprs[VCPU_REGS_RDI]; vcpu->vc_gueststate.vg_r8 = gprs[VCPU_REGS_R8]; vcpu->vc_gueststate.vg_r9 = gprs[VCPU_REGS_R9]; vcpu->vc_gueststate.vg_r10 = gprs[VCPU_REGS_R10]; vcpu->vc_gueststate.vg_r11 = gprs[VCPU_REGS_R11]; vcpu->vc_gueststate.vg_r12 = gprs[VCPU_REGS_R12]; vcpu->vc_gueststate.vg_r13 = gprs[VCPU_REGS_R13]; vcpu->vc_gueststate.vg_r14 = gprs[VCPU_REGS_R14]; vcpu->vc_gueststate.vg_r15 = gprs[VCPU_REGS_R15]; vcpu->vc_gueststate.vg_rbp = gprs[VCPU_REGS_RBP]; vcpu->vc_gueststate.vg_rip = gprs[VCPU_REGS_RIP]; if (vmwrite(VMCS_GUEST_IA32_RIP, gprs[VCPU_REGS_RIP])) goto errout; if (vmwrite(VMCS_GUEST_IA32_RSP, gprs[VCPU_REGS_RSP])) goto errout; if (vmwrite(VMCS_GUEST_IA32_RFLAGS, gprs[VCPU_REGS_RFLAGS])) goto errout; } if (regmask & VM_RWREGS_SREGS) { for (i = 0; i < nitems(vmm_vmx_sreg_vmcs_fields); i++) { sel = sregs[i].vsi_sel; limit = sregs[i].vsi_limit; ar = sregs[i].vsi_ar; if (vmwrite(vmm_vmx_sreg_vmcs_fields[i].selid, sel)) goto errout; if (vmwrite(vmm_vmx_sreg_vmcs_fields[i].limitid, limit)) goto errout; if (vmwrite(vmm_vmx_sreg_vmcs_fields[i].arid, ar)) goto errout; if (vmwrite(vmm_vmx_sreg_vmcs_fields[i].baseid, sregs[i].vsi_base)) goto errout; } if (vmwrite(VMCS_GUEST_IA32_GDTR_LIMIT, vrs->vrs_gdtr.vsi_limit)) goto errout; if (vmwrite(VMCS_GUEST_IA32_GDTR_BASE, vrs->vrs_gdtr.vsi_base)) goto errout; if (vmwrite(VMCS_GUEST_IA32_IDTR_LIMIT, vrs->vrs_idtr.vsi_limit)) goto errout; if (vmwrite(VMCS_GUEST_IA32_IDTR_BASE, vrs->vrs_idtr.vsi_base)) goto errout; } if (regmask & VM_RWREGS_CRS) { vcpu->vc_gueststate.vg_xcr0 = crs[VCPU_REGS_XCR0]; if (vmwrite(VMCS_GUEST_IA32_CR0, crs[VCPU_REGS_CR0])) goto errout; if (vmwrite(VMCS_GUEST_IA32_CR3, crs[VCPU_REGS_CR3])) goto errout; if (vmwrite(VMCS_GUEST_IA32_CR4, crs[VCPU_REGS_CR4])) goto errout; if (vmwrite(VMCS_GUEST_PDPTE0, crs[VCPU_REGS_PDPTE0])) goto errout; if (vmwrite(VMCS_GUEST_PDPTE1, crs[VCPU_REGS_PDPTE1])) goto errout; if (vmwrite(VMCS_GUEST_PDPTE2, crs[VCPU_REGS_PDPTE2])) goto errout; if (vmwrite(VMCS_GUEST_PDPTE3, crs[VCPU_REGS_PDPTE3])) goto errout; } msr_store = (struct vmx_msr_store *)vcpu->vc_vmx_msr_exit_save_va; if (regmask & VM_RWREGS_MSRS) { for (i = 0; i < VCPU_REGS_NMSRS; i++) { msr_store[i].vms_data = msrs[i]; } } if (regmask & VM_RWREGS_DRS) { vcpu->vc_gueststate.vg_dr0 = drs[VCPU_REGS_DR0]; vcpu->vc_gueststate.vg_dr1 = drs[VCPU_REGS_DR1]; vcpu->vc_gueststate.vg_dr2 = drs[VCPU_REGS_DR2]; vcpu->vc_gueststate.vg_dr3 = drs[VCPU_REGS_DR3]; vcpu->vc_gueststate.vg_dr6 = drs[VCPU_REGS_DR6]; if (vmwrite(VMCS_GUEST_IA32_DR7, drs[VCPU_REGS_DR7])) goto errout; } goto out; errout: ret = EINVAL; out: if (loadvmcs) { if (vmclear(&vcpu->vc_control_pa)) ret = EINVAL; atomic_swap_uint(&vcpu->vc_vmx_vmcs_state, VMCS_CLEARED); } return (ret); } /* * vcpu_writeregs_svm * * Writes 'vcpu's registers * * Parameters: * vcpu: the vcpu that has to get its registers written to * regmask: the types of registers to write * vrs: the register values to write * * Return values: * 0: if successful * EINVAL an error writing registers occurred */ int vcpu_writeregs_svm(struct vcpu *vcpu, uint64_t regmask, struct vcpu_reg_state *vrs) { uint64_t *gprs = vrs->vrs_gprs; uint64_t *crs = vrs->vrs_crs; uint16_t attr; uint64_t *msrs = vrs->vrs_msrs; uint64_t *drs = vrs->vrs_drs; struct vcpu_segment_info *sregs = vrs->vrs_sregs; struct vmcb *vmcb = (struct vmcb *)vcpu->vc_control_va; if (regmask & VM_RWREGS_GPRS) { vcpu->vc_gueststate.vg_rax = gprs[VCPU_REGS_RAX]; vcpu->vc_gueststate.vg_rbx = gprs[VCPU_REGS_RBX]; vcpu->vc_gueststate.vg_rcx = gprs[VCPU_REGS_RCX]; vcpu->vc_gueststate.vg_rdx = gprs[VCPU_REGS_RDX]; vcpu->vc_gueststate.vg_rsi = gprs[VCPU_REGS_RSI]; vcpu->vc_gueststate.vg_rdi = gprs[VCPU_REGS_RDI]; vcpu->vc_gueststate.vg_r8 = gprs[VCPU_REGS_R8]; vcpu->vc_gueststate.vg_r9 = gprs[VCPU_REGS_R9]; vcpu->vc_gueststate.vg_r10 = gprs[VCPU_REGS_R10]; vcpu->vc_gueststate.vg_r11 = gprs[VCPU_REGS_R11]; vcpu->vc_gueststate.vg_r12 = gprs[VCPU_REGS_R12]; vcpu->vc_gueststate.vg_r13 = gprs[VCPU_REGS_R13]; vcpu->vc_gueststate.vg_r14 = gprs[VCPU_REGS_R14]; vcpu->vc_gueststate.vg_r15 = gprs[VCPU_REGS_R15]; vcpu->vc_gueststate.vg_rbp = gprs[VCPU_REGS_RBP]; vcpu->vc_gueststate.vg_rip = gprs[VCPU_REGS_RIP]; vmcb->v_rax = gprs[VCPU_REGS_RAX]; vmcb->v_rip = gprs[VCPU_REGS_RIP]; vmcb->v_rsp = gprs[VCPU_REGS_RSP]; vmcb->v_rflags = gprs[VCPU_REGS_RFLAGS]; } if (regmask & VM_RWREGS_SREGS) { vmcb->v_cs.vs_sel = sregs[VCPU_REGS_CS].vsi_sel; vmcb->v_cs.vs_lim = sregs[VCPU_REGS_CS].vsi_limit; attr = sregs[VCPU_REGS_CS].vsi_ar; vmcb->v_cs.vs_attr = (attr & 0xff) | ((attr >> 4) & 0xf00); vmcb->v_cs.vs_base = sregs[VCPU_REGS_CS].vsi_base; vmcb->v_ds.vs_sel = sregs[VCPU_REGS_DS].vsi_sel; vmcb->v_ds.vs_lim = sregs[VCPU_REGS_DS].vsi_limit; attr = sregs[VCPU_REGS_DS].vsi_ar; vmcb->v_ds.vs_attr = (attr & 0xff) | ((attr >> 4) & 0xf00); vmcb->v_ds.vs_base = sregs[VCPU_REGS_DS].vsi_base; vmcb->v_es.vs_sel = sregs[VCPU_REGS_ES].vsi_sel; vmcb->v_es.vs_lim = sregs[VCPU_REGS_ES].vsi_limit; attr = sregs[VCPU_REGS_ES].vsi_ar; vmcb->v_es.vs_attr = (attr & 0xff) | ((attr >> 4) & 0xf00); vmcb->v_es.vs_base = sregs[VCPU_REGS_ES].vsi_base; vmcb->v_fs.vs_sel = sregs[VCPU_REGS_FS].vsi_sel; vmcb->v_fs.vs_lim = sregs[VCPU_REGS_FS].vsi_limit; attr = sregs[VCPU_REGS_FS].vsi_ar; vmcb->v_fs.vs_attr = (attr & 0xff) | ((attr >> 4) & 0xf00); vmcb->v_fs.vs_base = sregs[VCPU_REGS_FS].vsi_base; vmcb->v_gs.vs_sel = sregs[VCPU_REGS_GS].vsi_sel; vmcb->v_gs.vs_lim = sregs[VCPU_REGS_GS].vsi_limit; attr = sregs[VCPU_REGS_GS].vsi_ar; vmcb->v_gs.vs_attr = (attr & 0xff) | ((attr >> 4) & 0xf00); vmcb->v_gs.vs_base = sregs[VCPU_REGS_GS].vsi_base; vmcb->v_ss.vs_sel = sregs[VCPU_REGS_SS].vsi_sel; vmcb->v_ss.vs_lim = sregs[VCPU_REGS_SS].vsi_limit; attr = sregs[VCPU_REGS_SS].vsi_ar; vmcb->v_ss.vs_attr = (attr & 0xff) | ((attr >> 4) & 0xf00); vmcb->v_ss.vs_base = sregs[VCPU_REGS_SS].vsi_base; vmcb->v_ldtr.vs_sel = sregs[VCPU_REGS_LDTR].vsi_sel; vmcb->v_ldtr.vs_lim = sregs[VCPU_REGS_LDTR].vsi_limit; attr = sregs[VCPU_REGS_LDTR].vsi_ar; vmcb->v_ldtr.vs_attr = (attr & 0xff) | ((attr >> 4) & 0xf00); vmcb->v_ldtr.vs_base = sregs[VCPU_REGS_LDTR].vsi_base; vmcb->v_tr.vs_sel = sregs[VCPU_REGS_TR].vsi_sel; vmcb->v_tr.vs_lim = sregs[VCPU_REGS_TR].vsi_limit; attr = sregs[VCPU_REGS_TR].vsi_ar; vmcb->v_tr.vs_attr = (attr & 0xff) | ((attr >> 4) & 0xf00); vmcb->v_tr.vs_base = sregs[VCPU_REGS_TR].vsi_base; vmcb->v_gdtr.vs_lim = vrs->vrs_gdtr.vsi_limit; vmcb->v_gdtr.vs_base = vrs->vrs_gdtr.vsi_base; vmcb->v_idtr.vs_lim = vrs->vrs_idtr.vsi_limit; vmcb->v_idtr.vs_base = vrs->vrs_idtr.vsi_base; } if (regmask & VM_RWREGS_CRS) { vmcb->v_cr0 = crs[VCPU_REGS_CR0]; vmcb->v_cr3 = crs[VCPU_REGS_CR3]; vmcb->v_cr4 = crs[VCPU_REGS_CR4]; vcpu->vc_gueststate.vg_cr2 = crs[VCPU_REGS_CR2]; vcpu->vc_gueststate.vg_xcr0 = crs[VCPU_REGS_XCR0]; } if (regmask & VM_RWREGS_MSRS) { vmcb->v_efer |= msrs[VCPU_REGS_EFER]; vmcb->v_star = msrs[VCPU_REGS_STAR]; vmcb->v_lstar = msrs[VCPU_REGS_LSTAR]; vmcb->v_cstar = msrs[VCPU_REGS_CSTAR]; vmcb->v_sfmask = msrs[VCPU_REGS_SFMASK]; vmcb->v_kgsbase = msrs[VCPU_REGS_KGSBASE]; } if (regmask & VM_RWREGS_DRS) { vcpu->vc_gueststate.vg_dr0 = drs[VCPU_REGS_DR0]; vcpu->vc_gueststate.vg_dr1 = drs[VCPU_REGS_DR1]; vcpu->vc_gueststate.vg_dr2 = drs[VCPU_REGS_DR2]; vcpu->vc_gueststate.vg_dr3 = drs[VCPU_REGS_DR3]; vmcb->v_dr6 = drs[VCPU_REGS_DR6]; vmcb->v_dr7 = drs[VCPU_REGS_DR7]; } return (0); } /* * vcpu_reset_regs_svm * * Initializes 'vcpu's registers to supplied state * * Parameters: * vcpu: the vcpu whose register state is to be initialized * vrs: the register state to set * * Return values: * 0: registers init'ed successfully * EINVAL: an error occurred setting register state */ int vcpu_reset_regs_svm(struct vcpu *vcpu, struct vcpu_reg_state *vrs) { struct vmcb *vmcb; int ret; uint16_t asid; vmcb = (struct vmcb *)vcpu->vc_control_va; /* * Intercept controls * * External Interrupt exiting (SVM_INTERCEPT_INTR) * External NMI exiting (SVM_INTERCEPT_NMI) * CPUID instruction (SVM_INTERCEPT_CPUID) * HLT instruction (SVM_INTERCEPT_HLT) * I/O instructions (SVM_INTERCEPT_INOUT) * MSR access (SVM_INTERCEPT_MSR) * shutdown events (SVM_INTERCEPT_SHUTDOWN) * * VMRUN instruction (SVM_INTERCEPT_VMRUN) * VMMCALL instruction (SVM_INTERCEPT_VMMCALL) * VMLOAD instruction (SVM_INTERCEPT_VMLOAD) * VMSAVE instruction (SVM_INTERCEPT_VMSAVE) * STGI instruction (SVM_INTERCEPT_STGI) * CLGI instruction (SVM_INTERCEPT_CLGI) * SKINIT instruction (SVM_INTERCEPT_SKINIT) * ICEBP instruction (SVM_INTERCEPT_ICEBP) * MWAIT instruction (SVM_INTERCEPT_MWAIT_UNCOND) * MWAIT instruction (SVM_INTERCEPT_MWAIT_COND) * MONITOR instruction (SVM_INTERCEPT_MONITOR) * RDTSCP instruction (SVM_INTERCEPT_RDTSCP) * INVLPGA instruction (SVM_INTERCEPT_INVLPGA) * XSETBV instruction (SVM_INTERCEPT_XSETBV) (if available) */ vmcb->v_intercept1 = SVM_INTERCEPT_INTR | SVM_INTERCEPT_NMI | SVM_INTERCEPT_CPUID | SVM_INTERCEPT_HLT | SVM_INTERCEPT_INOUT | SVM_INTERCEPT_MSR | SVM_INTERCEPT_SHUTDOWN; vmcb->v_intercept2 = SVM_INTERCEPT_VMRUN | SVM_INTERCEPT_VMMCALL | SVM_INTERCEPT_VMLOAD | SVM_INTERCEPT_VMSAVE | SVM_INTERCEPT_STGI | SVM_INTERCEPT_CLGI | SVM_INTERCEPT_SKINIT | SVM_INTERCEPT_ICEBP | SVM_INTERCEPT_MWAIT_UNCOND | SVM_INTERCEPT_MONITOR | SVM_INTERCEPT_MWAIT_COND | SVM_INTERCEPT_RDTSCP | SVM_INTERCEPT_INVLPGA; if (xsave_mask) vmcb->v_intercept2 |= SVM_INTERCEPT_XSETBV; /* Setup I/O bitmap */ memset((uint8_t *)vcpu->vc_svm_ioio_va, 0xFF, 3 * PAGE_SIZE); vmcb->v_iopm_pa = (uint64_t)(vcpu->vc_svm_ioio_pa); /* Setup MSR bitmap */ memset((uint8_t *)vcpu->vc_msr_bitmap_va, 0xFF, 2 * PAGE_SIZE); vmcb->v_msrpm_pa = (uint64_t)(vcpu->vc_msr_bitmap_pa); svm_setmsrbrw(vcpu, MSR_IA32_FEATURE_CONTROL); svm_setmsrbrw(vcpu, MSR_SYSENTER_CS); svm_setmsrbrw(vcpu, MSR_SYSENTER_ESP); svm_setmsrbrw(vcpu, MSR_SYSENTER_EIP); svm_setmsrbrw(vcpu, MSR_STAR); svm_setmsrbrw(vcpu, MSR_LSTAR); svm_setmsrbrw(vcpu, MSR_CSTAR); svm_setmsrbrw(vcpu, MSR_SFMASK); svm_setmsrbrw(vcpu, MSR_FSBASE); svm_setmsrbrw(vcpu, MSR_GSBASE); svm_setmsrbrw(vcpu, MSR_KERNELGSBASE); /* EFER is R/O so we can ensure the guest always has SVME */ svm_setmsrbr(vcpu, MSR_EFER); /* allow reading TSC */ svm_setmsrbr(vcpu, MSR_TSC); /* allow reading HWCR and PSTATEDEF to determine TSC frequency */ svm_setmsrbr(vcpu, MSR_HWCR); svm_setmsrbr(vcpu, MSR_PSTATEDEF(0)); /* Guest VCPU ASID */ if (vmm_alloc_vpid(&asid)) { DPRINTF("%s: could not allocate asid\n", __func__); ret = EINVAL; goto exit; } vmcb->v_asid = asid; vcpu->vc_vpid = asid; /* TLB Control - First time in, flush all*/ vmcb->v_tlb_control = SVM_TLB_CONTROL_FLUSH_ALL; /* INTR masking */ vmcb->v_intr_masking = 1; /* PAT */ vmcb->v_g_pat = PATENTRY(0, PAT_WB) | PATENTRY(1, PAT_WC) | PATENTRY(2, PAT_UCMINUS) | PATENTRY(3, PAT_UC) | PATENTRY(4, PAT_WB) | PATENTRY(5, PAT_WC) | PATENTRY(6, PAT_UCMINUS) | PATENTRY(7, PAT_UC); /* NPT */ if (vmm_softc->mode == VMM_MODE_RVI) { vmcb->v_np_enable = 1; vmcb->v_n_cr3 = vcpu->vc_parent->vm_map->pmap->pm_pdirpa; } /* Enable SVME in EFER (must always be set) */ vmcb->v_efer |= EFER_SVME; ret = vcpu_writeregs_svm(vcpu, VM_RWREGS_ALL, vrs); /* xcr0 power on default sets bit 0 (x87 state) */ vcpu->vc_gueststate.vg_xcr0 = XFEATURE_X87 & xsave_mask; vcpu->vc_parent->vm_map->pmap->eptp = 0; exit: return ret; } /* * svm_setmsrbr * * Allow read access to the specified msr on the supplied vcpu. * * Parameters: * vcpu: the VCPU to allow access * msr: the MSR number to allow access to */ void svm_setmsrbr(struct vcpu *vcpu, uint32_t msr) { uint8_t *msrs; uint16_t idx; msrs = (uint8_t *)vcpu->vc_msr_bitmap_va; /* * MSR Read bitmap layout: * Pentium MSRs (0x0 - 0x1fff) @ 0x0 * Gen6 and Syscall MSRs (0xc0000000 - 0xc0001fff) @ 0x800 * Gen7 and Gen8 MSRs (0xc0010000 - 0xc0011fff) @ 0x1000 * * Read enable bit is low order bit of 2-bit pair * per MSR (eg, MSR 0x0 write bit is at bit 0 @ 0x0) */ if (msr <= 0x1fff) { idx = SVM_MSRIDX(msr); msrs[idx] &= ~(SVM_MSRBIT_R(msr)); } else if (msr >= 0xc0000000 && msr <= 0xc0001fff) { idx = SVM_MSRIDX(msr - 0xc0000000) + 0x800; msrs[idx] &= ~(SVM_MSRBIT_R(msr - 0xc0000000)); } else if (msr >= 0xc0010000 && msr <= 0xc0011fff) { idx = SVM_MSRIDX(msr - 0xc0010000) + 0x1000; msrs[idx] &= ~(SVM_MSRBIT_R(msr - 0xc0010000)); } else { printf("%s: invalid msr 0x%x\n", __func__, msr); return; } } /* * svm_setmsrbw * * Allow write access to the specified msr on the supplied vcpu * * Parameters: * vcpu: the VCPU to allow access * msr: the MSR number to allow access to */ void svm_setmsrbw(struct vcpu *vcpu, uint32_t msr) { uint8_t *msrs; uint16_t idx; msrs = (uint8_t *)vcpu->vc_msr_bitmap_va; /* * MSR Write bitmap layout: * Pentium MSRs (0x0 - 0x1fff) @ 0x0 * Gen6 and Syscall MSRs (0xc0000000 - 0xc0001fff) @ 0x800 * Gen7 and Gen8 MSRs (0xc0010000 - 0xc0011fff) @ 0x1000 * * Write enable bit is high order bit of 2-bit pair * per MSR (eg, MSR 0x0 write bit is at bit 1 @ 0x0) */ if (msr <= 0x1fff) { idx = SVM_MSRIDX(msr); msrs[idx] &= ~(SVM_MSRBIT_W(msr)); } else if (msr >= 0xc0000000 && msr <= 0xc0001fff) { idx = SVM_MSRIDX(msr - 0xc0000000) + 0x800; msrs[idx] &= ~(SVM_MSRBIT_W(msr - 0xc0000000)); } else if (msr >= 0xc0010000 && msr <= 0xc0011fff) { idx = SVM_MSRIDX(msr - 0xc0010000) + 0x1000; msrs[idx] &= ~(SVM_MSRBIT_W(msr - 0xc0010000)); } else { printf("%s: invalid msr 0x%x\n", __func__, msr); return; } } /* * svm_setmsrbrw * * Allow read/write access to the specified msr on the supplied vcpu * * Parameters: * vcpu: the VCPU to allow access * msr: the MSR number to allow access to */ void svm_setmsrbrw(struct vcpu *vcpu, uint32_t msr) { svm_setmsrbr(vcpu, msr); svm_setmsrbw(vcpu, msr); } /* * vmx_setmsrbr * * Allow read access to the specified msr on the supplied vcpu. * * Parameters: * vcpu: the VCPU to allow access * msr: the MSR number to allow access to */ void vmx_setmsrbr(struct vcpu *vcpu, uint32_t msr) { uint8_t *msrs; uint16_t idx; msrs = (uint8_t *)vcpu->vc_msr_bitmap_va; /* * MSR Read bitmap layout: * "Low" MSRs (0x0 - 0x1fff) @ 0x0 * "High" MSRs (0xc0000000 - 0xc0001fff) @ 0x400 */ if (msr <= 0x1fff) { idx = VMX_MSRIDX(msr); msrs[idx] &= ~(VMX_MSRBIT(msr)); } else if (msr >= 0xc0000000 && msr <= 0xc0001fff) { idx = VMX_MSRIDX(msr - 0xc0000000) + 0x400; msrs[idx] &= ~(VMX_MSRBIT(msr - 0xc0000000)); } else printf("%s: invalid msr 0x%x\n", __func__, msr); } /* * vmx_setmsrbw * * Allow write access to the specified msr on the supplied vcpu * * Parameters: * vcpu: the VCPU to allow access * msr: the MSR number to allow access to */ void vmx_setmsrbw(struct vcpu *vcpu, uint32_t msr) { uint8_t *msrs; uint16_t idx; msrs = (uint8_t *)vcpu->vc_msr_bitmap_va; /* * MSR Write bitmap layout: * "Low" MSRs (0x0 - 0x1fff) @ 0x800 * "High" MSRs (0xc0000000 - 0xc0001fff) @ 0xc00 */ if (msr <= 0x1fff) { idx = VMX_MSRIDX(msr) + 0x800; msrs[idx] &= ~(VMX_MSRBIT(msr)); } else if (msr >= 0xc0000000 && msr <= 0xc0001fff) { idx = VMX_MSRIDX(msr - 0xc0000000) + 0xc00; msrs[idx] &= ~(VMX_MSRBIT(msr - 0xc0000000)); } else printf("%s: invalid msr 0x%x\n", __func__, msr); } /* * vmx_setmsrbrw * * Allow read/write access to the specified msr on the supplied vcpu * * Parameters: * vcpu: the VCPU to allow access * msr: the MSR number to allow access to */ void vmx_setmsrbrw(struct vcpu *vcpu, uint32_t msr) { vmx_setmsrbr(vcpu, msr); vmx_setmsrbw(vcpu, msr); } /* * svm_set_clean * * Sets (mark as unmodified) the VMCB clean bit set in 'value'. * For example, to set the clean bit for the VMCB intercepts (bit position 0), * the caller provides 'SVM_CLEANBITS_I' (0x1) for the 'value' argument. * Multiple cleanbits can be provided in 'value' at the same time (eg, * "SVM_CLEANBITS_I | SVM_CLEANBITS_TPR"). * * Note that this function does not clear any bits; to clear bits in the * vmcb cleanbits bitfield, use 'svm_set_dirty'. * * Parameters: * vmcs: the VCPU whose VMCB clean value should be set * value: the value(s) to enable in the cleanbits mask */ void svm_set_clean(struct vcpu *vcpu, uint32_t value) { struct vmcb *vmcb; /* If no cleanbits support, do nothing */ if (!curcpu()->ci_vmm_cap.vcc_svm.svm_vmcb_clean) return; vmcb = (struct vmcb *)vcpu->vc_control_va; vmcb->v_vmcb_clean_bits |= value; } /* * svm_set_dirty * * Clears (mark as modified) the VMCB clean bit set in 'value'. * For example, to clear the bit for the VMCB intercepts (bit position 0) * the caller provides 'SVM_CLEANBITS_I' (0x1) for the 'value' argument. * Multiple dirty bits can be provided in 'value' at the same time (eg, * "SVM_CLEANBITS_I | SVM_CLEANBITS_TPR"). * * Parameters: * vmcs: the VCPU whose VMCB dirty value should be set * value: the value(s) to dirty in the cleanbits mask */ void svm_set_dirty(struct vcpu *vcpu, uint32_t value) { struct vmcb *vmcb; /* If no cleanbits support, do nothing */ if (!curcpu()->ci_vmm_cap.vcc_svm.svm_vmcb_clean) return; vmcb = (struct vmcb *)vcpu->vc_control_va; vmcb->v_vmcb_clean_bits &= ~value; } /* * vcpu_reset_regs_vmx * * Initializes 'vcpu's registers to supplied state * * Parameters: * vcpu: the vcpu whose register state is to be initialized * vrs: the register state to set * * Return values: * 0: registers init'ed successfully * EINVAL: an error occurred setting register state */ int vcpu_reset_regs_vmx(struct vcpu *vcpu, struct vcpu_reg_state *vrs) { int ret = 0, ug = 0; uint32_t cr0, cr4; uint32_t pinbased, procbased, procbased2, exit, entry; uint32_t want1, want0; uint64_t ctrlval, cr3, msr_misc_enable; uint16_t ctrl, vpid; struct vmx_msr_store *msr_store; rw_assert_wrlock(&vcpu->vc_lock); cr0 = vrs->vrs_crs[VCPU_REGS_CR0]; if (vcpu_reload_vmcs_vmx(vcpu)) { DPRINTF("%s: error reloading VMCS\n", __func__); ret = EINVAL; goto exit; } #ifdef VMM_DEBUG /* VMCS should be loaded... */ paddr_t pa = 0ULL; if (vmptrst(&pa)) panic("%s: vmptrst", __func__); KASSERT(pa == vcpu->vc_control_pa); #endif /* VMM_DEBUG */ /* Compute Basic Entry / Exit Controls */ vcpu->vc_vmx_basic = rdmsr(IA32_VMX_BASIC); vcpu->vc_vmx_entry_ctls = rdmsr(IA32_VMX_ENTRY_CTLS); vcpu->vc_vmx_exit_ctls = rdmsr(IA32_VMX_EXIT_CTLS); vcpu->vc_vmx_pinbased_ctls = rdmsr(IA32_VMX_PINBASED_CTLS); vcpu->vc_vmx_procbased_ctls = rdmsr(IA32_VMX_PROCBASED_CTLS); /* Compute True Entry / Exit Controls (if applicable) */ if (vcpu->vc_vmx_basic & IA32_VMX_TRUE_CTLS_AVAIL) { vcpu->vc_vmx_true_entry_ctls = rdmsr(IA32_VMX_TRUE_ENTRY_CTLS); vcpu->vc_vmx_true_exit_ctls = rdmsr(IA32_VMX_TRUE_EXIT_CTLS); vcpu->vc_vmx_true_pinbased_ctls = rdmsr(IA32_VMX_TRUE_PINBASED_CTLS); vcpu->vc_vmx_true_procbased_ctls = rdmsr(IA32_VMX_TRUE_PROCBASED_CTLS); } /* Compute Secondary Procbased Controls (if applicable) */ if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED_CTLS, IA32_VMX_ACTIVATE_SECONDARY_CONTROLS, 1)) vcpu->vc_vmx_procbased2_ctls = rdmsr(IA32_VMX_PROCBASED2_CTLS); /* * Pinbased ctrls * * We must be able to set the following: * IA32_VMX_EXTERNAL_INT_EXITING - exit on host interrupt * IA32_VMX_NMI_EXITING - exit on host NMI */ want1 = IA32_VMX_EXTERNAL_INT_EXITING | IA32_VMX_NMI_EXITING; want0 = 0; if (vcpu->vc_vmx_basic & IA32_VMX_TRUE_CTLS_AVAIL) { ctrl = IA32_VMX_TRUE_PINBASED_CTLS; ctrlval = vcpu->vc_vmx_true_pinbased_ctls; } else { ctrl = IA32_VMX_PINBASED_CTLS; ctrlval = vcpu->vc_vmx_pinbased_ctls; } if (vcpu_vmx_compute_ctrl(ctrlval, ctrl, want1, want0, &pinbased)) { DPRINTF("%s: error computing pinbased controls\n", __func__); ret = EINVAL; goto exit; } if (vmwrite(VMCS_PINBASED_CTLS, pinbased)) { DPRINTF("%s: error setting pinbased controls\n", __func__); ret = EINVAL; goto exit; } /* * Procbased ctrls * * We must be able to set the following: * IA32_VMX_HLT_EXITING - exit on HLT instruction * IA32_VMX_MWAIT_EXITING - exit on MWAIT instruction * IA32_VMX_UNCONDITIONAL_IO_EXITING - exit on I/O instructions * IA32_VMX_USE_MSR_BITMAPS - exit on various MSR accesses * IA32_VMX_CR8_LOAD_EXITING - guest TPR access * IA32_VMX_CR8_STORE_EXITING - guest TPR access * IA32_VMX_USE_TPR_SHADOW - guest TPR access (shadow) * IA32_VMX_MONITOR_EXITING - exit on MONITOR instruction * * If we have EPT, we must be able to clear the following * IA32_VMX_CR3_LOAD_EXITING - don't care about guest CR3 accesses * IA32_VMX_CR3_STORE_EXITING - don't care about guest CR3 accesses */ want1 = IA32_VMX_HLT_EXITING | IA32_VMX_MWAIT_EXITING | IA32_VMX_UNCONDITIONAL_IO_EXITING | IA32_VMX_USE_MSR_BITMAPS | IA32_VMX_CR8_LOAD_EXITING | IA32_VMX_CR8_STORE_EXITING | IA32_VMX_MONITOR_EXITING | IA32_VMX_USE_TPR_SHADOW; want0 = 0; if (vmm_softc->mode == VMM_MODE_EPT) { want1 |= IA32_VMX_ACTIVATE_SECONDARY_CONTROLS; want0 |= IA32_VMX_CR3_LOAD_EXITING | IA32_VMX_CR3_STORE_EXITING; } if (vcpu->vc_vmx_basic & IA32_VMX_TRUE_CTLS_AVAIL) { ctrl = IA32_VMX_TRUE_PROCBASED_CTLS; ctrlval = vcpu->vc_vmx_true_procbased_ctls; } else { ctrl = IA32_VMX_PROCBASED_CTLS; ctrlval = vcpu->vc_vmx_procbased_ctls; } if (vcpu_vmx_compute_ctrl(ctrlval, ctrl, want1, want0, &procbased)) { DPRINTF("%s: error computing procbased controls\n", __func__); ret = EINVAL; goto exit; } if (vmwrite(VMCS_PROCBASED_CTLS, procbased)) { DPRINTF("%s: error setting procbased controls\n", __func__); ret = EINVAL; goto exit; } /* * Secondary Procbased ctrls * * We want to be able to set the following, if available: * IA32_VMX_ENABLE_VPID - use VPIDs where available * * If we have EPT, we must be able to set the following: * IA32_VMX_ENABLE_EPT - enable EPT * * If we have unrestricted guest capability, we must be able to set * the following: * IA32_VMX_UNRESTRICTED_GUEST - enable unrestricted guest (if caller * specified CR0_PG | CR0_PE in %cr0 in the 'vrs' parameter) */ want1 = 0; /* XXX checking for 2ndary controls can be combined here */ if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED_CTLS, IA32_VMX_ACTIVATE_SECONDARY_CONTROLS, 1)) { if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED2_CTLS, IA32_VMX_ENABLE_VPID, 1)) { want1 |= IA32_VMX_ENABLE_VPID; vcpu->vc_vmx_vpid_enabled = 1; } } if (vmm_softc->mode == VMM_MODE_EPT) want1 |= IA32_VMX_ENABLE_EPT; if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED_CTLS, IA32_VMX_ACTIVATE_SECONDARY_CONTROLS, 1)) { if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED2_CTLS, IA32_VMX_UNRESTRICTED_GUEST, 1)) { if ((cr0 & (CR0_PE | CR0_PG)) == 0) { want1 |= IA32_VMX_UNRESTRICTED_GUEST; ug = 1; } } } want0 = ~want1; ctrlval = vcpu->vc_vmx_procbased2_ctls; ctrl = IA32_VMX_PROCBASED2_CTLS; if (vcpu_vmx_compute_ctrl(ctrlval, ctrl, want1, want0, &procbased2)) { DPRINTF("%s: error computing secondary procbased controls\n", __func__); ret = EINVAL; goto exit; } if (vmwrite(VMCS_PROCBASED2_CTLS, procbased2)) { DPRINTF("%s: error setting secondary procbased controls\n", __func__); ret = EINVAL; goto exit; } /* * Exit ctrls * * We must be able to set the following: * IA32_VMX_SAVE_DEBUG_CONTROLS * IA32_VMX_HOST_SPACE_ADDRESS_SIZE - exit to long mode * IA32_VMX_ACKNOWLEDGE_INTERRUPT_ON_EXIT - ack interrupt on exit */ want1 = IA32_VMX_HOST_SPACE_ADDRESS_SIZE | IA32_VMX_ACKNOWLEDGE_INTERRUPT_ON_EXIT | IA32_VMX_SAVE_DEBUG_CONTROLS; want0 = 0; if (vcpu->vc_vmx_basic & IA32_VMX_TRUE_CTLS_AVAIL) { ctrl = IA32_VMX_TRUE_EXIT_CTLS; ctrlval = vcpu->vc_vmx_true_exit_ctls; } else { ctrl = IA32_VMX_EXIT_CTLS; ctrlval = vcpu->vc_vmx_exit_ctls; } if (rcr4() & CR4_CET) want1 |= IA32_VMX_LOAD_HOST_CET_STATE; else want0 |= IA32_VMX_LOAD_HOST_CET_STATE; if (vcpu_vmx_compute_ctrl(ctrlval, ctrl, want1, want0, &exit)) { DPRINTF("%s: error computing exit controls\n", __func__); ret = EINVAL; goto exit; } if (vmwrite(VMCS_EXIT_CTLS, exit)) { DPRINTF("%s: error setting exit controls\n", __func__); ret = EINVAL; goto exit; } /* * Entry ctrls * * We must be able to set the following: * IA32_VMX_IA32E_MODE_GUEST (if no unrestricted guest) * IA32_VMX_LOAD_DEBUG_CONTROLS * We must be able to clear the following: * IA32_VMX_ENTRY_TO_SMM - enter to SMM * IA32_VMX_DEACTIVATE_DUAL_MONITOR_TREATMENT * IA32_VMX_LOAD_IA32_PERF_GLOBAL_CTRL_ON_ENTRY */ want1 = IA32_VMX_LOAD_DEBUG_CONTROLS; if (vrs->vrs_msrs[VCPU_REGS_EFER] & EFER_LMA) want1 |= IA32_VMX_IA32E_MODE_GUEST; want0 = IA32_VMX_ENTRY_TO_SMM | IA32_VMX_DEACTIVATE_DUAL_MONITOR_TREATMENT | IA32_VMX_LOAD_IA32_PERF_GLOBAL_CTRL_ON_ENTRY; if (vcpu->vc_vmx_basic & IA32_VMX_TRUE_CTLS_AVAIL) { ctrl = IA32_VMX_TRUE_ENTRY_CTLS; ctrlval = vcpu->vc_vmx_true_entry_ctls; } else { ctrl = IA32_VMX_ENTRY_CTLS; ctrlval = vcpu->vc_vmx_entry_ctls; } if (rcr4() & CR4_CET) want1 |= IA32_VMX_LOAD_GUEST_CET_STATE; else want0 |= IA32_VMX_LOAD_GUEST_CET_STATE; if (vcpu_vmx_compute_ctrl(ctrlval, ctrl, want1, want0, &entry)) { ret = EINVAL; goto exit; } if (vmwrite(VMCS_ENTRY_CTLS, entry)) { ret = EINVAL; goto exit; } if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED_CTLS, IA32_VMX_ACTIVATE_SECONDARY_CONTROLS, 1)) { if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED2_CTLS, IA32_VMX_ENABLE_VPID, 1)) { /* We may sleep during allocation, so reload VMCS. */ vcpu->vc_last_pcpu = curcpu(); ret = vmm_alloc_vpid(&vpid); if (vcpu_reload_vmcs_vmx(vcpu)) { printf("%s: failed to reload vmcs\n", __func__); ret = EINVAL; goto exit; } if (ret) { DPRINTF("%s: could not allocate VPID\n", __func__); ret = EINVAL; goto exit; } if (vmwrite(VMCS_GUEST_VPID, vpid)) { DPRINTF("%s: error setting guest VPID\n", __func__); ret = EINVAL; goto exit; } vcpu->vc_vpid = vpid; } } /* * Determine which bits in CR0 have to be set to a fixed * value as per Intel SDM A.7. * CR0 bits in the vrs parameter must match these. */ want1 = (curcpu()->ci_vmm_cap.vcc_vmx.vmx_cr0_fixed0) & (curcpu()->ci_vmm_cap.vcc_vmx.vmx_cr0_fixed1); want0 = ~(curcpu()->ci_vmm_cap.vcc_vmx.vmx_cr0_fixed0) & ~(curcpu()->ci_vmm_cap.vcc_vmx.vmx_cr0_fixed1); /* * CR0_FIXED0 and CR0_FIXED1 may report the CR0_PG and CR0_PE bits as * fixed to 1 even if the CPU supports the unrestricted guest * feature. Update want1 and want0 accordingly to allow * any value for CR0_PG and CR0_PE in vrs->vrs_crs[VCPU_REGS_CR0] if * the CPU has the unrestricted guest capability. */ if (ug) { want1 &= ~(CR0_PG | CR0_PE); want0 &= ~(CR0_PG | CR0_PE); } /* * VMX may require some bits to be set that userland should not have * to care about. Set those here. */ if (want1 & CR0_NE) cr0 |= CR0_NE; if ((cr0 & want1) != want1) { ret = EINVAL; goto exit; } if ((~cr0 & want0) != want0) { ret = EINVAL; goto exit; } vcpu->vc_vmx_cr0_fixed1 = want1; vcpu->vc_vmx_cr0_fixed0 = want0; /* * Determine which bits in CR4 have to be set to a fixed * value as per Intel SDM A.8. * CR4 bits in the vrs parameter must match these, except * CR4_VMXE - we add that here since it must always be set. */ want1 = (curcpu()->ci_vmm_cap.vcc_vmx.vmx_cr4_fixed0) & (curcpu()->ci_vmm_cap.vcc_vmx.vmx_cr4_fixed1); want0 = ~(curcpu()->ci_vmm_cap.vcc_vmx.vmx_cr4_fixed0) & ~(curcpu()->ci_vmm_cap.vcc_vmx.vmx_cr4_fixed1); cr4 = vrs->vrs_crs[VCPU_REGS_CR4] | CR4_VMXE; if ((cr4 & want1) != want1) { ret = EINVAL; goto exit; } if ((~cr4 & want0) != want0) { ret = EINVAL; goto exit; } cr3 = vrs->vrs_crs[VCPU_REGS_CR3]; /* Restore PDPTEs if 32-bit PAE paging is being used */ if (cr3 && (cr4 & CR4_PAE) && !(vrs->vrs_msrs[VCPU_REGS_EFER] & EFER_LMA)) { if (vmwrite(VMCS_GUEST_PDPTE0, vrs->vrs_crs[VCPU_REGS_PDPTE0])) { ret = EINVAL; goto exit; } if (vmwrite(VMCS_GUEST_PDPTE1, vrs->vrs_crs[VCPU_REGS_PDPTE1])) { ret = EINVAL; goto exit; } if (vmwrite(VMCS_GUEST_PDPTE2, vrs->vrs_crs[VCPU_REGS_PDPTE2])) { ret = EINVAL; goto exit; } if (vmwrite(VMCS_GUEST_PDPTE3, vrs->vrs_crs[VCPU_REGS_PDPTE3])) { ret = EINVAL; goto exit; } } vrs->vrs_crs[VCPU_REGS_CR0] = cr0; vrs->vrs_crs[VCPU_REGS_CR4] = cr4; msr_misc_enable = rdmsr(MSR_MISC_ENABLE); /* * Select host MSRs to be loaded on exit */ msr_store = (struct vmx_msr_store *)vcpu->vc_vmx_msr_exit_load_va; msr_store[VCPU_HOST_REGS_EFER].vms_index = MSR_EFER; msr_store[VCPU_HOST_REGS_EFER].vms_data = rdmsr(MSR_EFER); msr_store[VCPU_HOST_REGS_STAR].vms_index = MSR_STAR; msr_store[VCPU_HOST_REGS_STAR].vms_data = rdmsr(MSR_STAR); msr_store[VCPU_HOST_REGS_LSTAR].vms_index = MSR_LSTAR; msr_store[VCPU_HOST_REGS_LSTAR].vms_data = rdmsr(MSR_LSTAR); msr_store[VCPU_HOST_REGS_CSTAR].vms_index = MSR_CSTAR; msr_store[VCPU_HOST_REGS_CSTAR].vms_data = 0; msr_store[VCPU_HOST_REGS_SFMASK].vms_index = MSR_SFMASK; msr_store[VCPU_HOST_REGS_SFMASK].vms_data = rdmsr(MSR_SFMASK); msr_store[VCPU_HOST_REGS_KGSBASE].vms_index = MSR_KERNELGSBASE; msr_store[VCPU_HOST_REGS_KGSBASE].vms_data = 0; msr_store[VCPU_HOST_REGS_MISC_ENABLE].vms_index = MSR_MISC_ENABLE; msr_store[VCPU_HOST_REGS_MISC_ENABLE].vms_data = msr_misc_enable; /* * Select guest MSRs to be loaded on entry / saved on exit */ msr_store = (struct vmx_msr_store *)vcpu->vc_vmx_msr_exit_save_va; msr_store[VCPU_REGS_EFER].vms_index = MSR_EFER; msr_store[VCPU_REGS_STAR].vms_index = MSR_STAR; msr_store[VCPU_REGS_LSTAR].vms_index = MSR_LSTAR; msr_store[VCPU_REGS_CSTAR].vms_index = MSR_CSTAR; msr_store[VCPU_REGS_SFMASK].vms_index = MSR_SFMASK; msr_store[VCPU_REGS_KGSBASE].vms_index = MSR_KERNELGSBASE; msr_store[VCPU_REGS_MISC_ENABLE].vms_index = MSR_MISC_ENABLE; /* * Initialize MSR_MISC_ENABLE as it can't be read and populated from vmd * and some of the content is based on the host. */ msr_store[VCPU_REGS_MISC_ENABLE].vms_data = msr_misc_enable; msr_store[VCPU_REGS_MISC_ENABLE].vms_data &= ~(MISC_ENABLE_TCC | MISC_ENABLE_PERF_MON_AVAILABLE | MISC_ENABLE_EIST_ENABLED | MISC_ENABLE_ENABLE_MONITOR_FSM | MISC_ENABLE_xTPR_MESSAGE_DISABLE); msr_store[VCPU_REGS_MISC_ENABLE].vms_data |= MISC_ENABLE_BTS_UNAVAILABLE | MISC_ENABLE_PEBS_UNAVAILABLE; /* * Currently we use the same memory for guest MSRs (entry-load and * exit-store) so they have the same count. We exit-load the same * host MSRs, so same count but different memory. Those are just * our current choices, not architectural requirements. */ if (vmwrite(VMCS_EXIT_MSR_STORE_COUNT, VCPU_REGS_NMSRS)) { DPRINTF("%s: error setting guest MSR exit store count\n", __func__); ret = EINVAL; goto exit; } if (vmwrite(VMCS_EXIT_MSR_LOAD_COUNT, VCPU_HOST_REGS_NMSRS)) { DPRINTF("%s: error setting guest MSR exit load count\n", __func__); ret = EINVAL; goto exit; } if (vmwrite(VMCS_ENTRY_MSR_LOAD_COUNT, VCPU_REGS_NMSRS)) { DPRINTF("%s: error setting guest MSR entry load count\n", __func__); ret = EINVAL; goto exit; } if (vmwrite(VMCS_EXIT_STORE_MSR_ADDRESS, vcpu->vc_vmx_msr_exit_save_pa)) { DPRINTF("%s: error setting guest MSR exit store address\n", __func__); ret = EINVAL; goto exit; } if (vmwrite(VMCS_EXIT_LOAD_MSR_ADDRESS, vcpu->vc_vmx_msr_exit_load_pa)) { DPRINTF("%s: error setting guest MSR exit load address\n", __func__); ret = EINVAL; goto exit; } if (vmwrite(VMCS_ENTRY_LOAD_MSR_ADDRESS, vcpu->vc_vmx_msr_exit_save_pa)) { DPRINTF("%s: error setting guest MSR entry load address\n", __func__); ret = EINVAL; goto exit; } if (vmwrite(VMCS_MSR_BITMAP_ADDRESS, vcpu->vc_msr_bitmap_pa)) { DPRINTF("%s: error setting guest MSR bitmap address\n", __func__); ret = EINVAL; goto exit; } if (vmwrite(VMCS_CR4_MASK, CR4_VMXE)) { DPRINTF("%s: error setting guest CR4 mask\n", __func__); ret = EINVAL; goto exit; } if (vmwrite(VMCS_CR0_MASK, CR0_NE)) { DPRINTF("%s: error setting guest CR0 mask\n", __func__); ret = EINVAL; goto exit; } /* * Set up the VMCS for the register state we want during VCPU start. * This matches what the CPU state would be after a bootloader * transition to 'start'. */ ret = vcpu_writeregs_vmx(vcpu, VM_RWREGS_ALL, 0, vrs); /* * Set up the MSR bitmap */ memset((uint8_t *)vcpu->vc_msr_bitmap_va, 0xFF, PAGE_SIZE); vmx_setmsrbrw(vcpu, MSR_IA32_FEATURE_CONTROL); vmx_setmsrbrw(vcpu, MSR_SYSENTER_CS); vmx_setmsrbrw(vcpu, MSR_SYSENTER_ESP); vmx_setmsrbrw(vcpu, MSR_SYSENTER_EIP); vmx_setmsrbrw(vcpu, MSR_EFER); vmx_setmsrbrw(vcpu, MSR_STAR); vmx_setmsrbrw(vcpu, MSR_LSTAR); vmx_setmsrbrw(vcpu, MSR_CSTAR); vmx_setmsrbrw(vcpu, MSR_SFMASK); vmx_setmsrbrw(vcpu, MSR_FSBASE); vmx_setmsrbrw(vcpu, MSR_GSBASE); vmx_setmsrbrw(vcpu, MSR_KERNELGSBASE); vmx_setmsrbr(vcpu, MSR_MISC_ENABLE); vmx_setmsrbr(vcpu, MSR_TSC); /* If host supports CET, pass through access to the guest. */ if (rcr4() & CR4_CET) vmx_setmsrbrw(vcpu, MSR_S_CET); /* XXX CR0 shadow */ /* XXX CR4 shadow */ /* xcr0 power on default sets bit 0 (x87 state) */ vcpu->vc_gueststate.vg_xcr0 = XFEATURE_X87 & xsave_mask; /* XXX PAT shadow */ vcpu->vc_shadow_pat = rdmsr(MSR_CR_PAT); /* Flush the VMCS */ if (vmclear(&vcpu->vc_control_pa)) { DPRINTF("%s: vmclear failed\n", __func__); ret = EINVAL; } atomic_swap_uint(&vcpu->vc_vmx_vmcs_state, VMCS_CLEARED); exit: return (ret); } /* * vcpu_init_vmx * * Intel VMX specific VCPU initialization routine. * * This function allocates various per-VCPU memory regions, sets up initial * VCPU VMCS controls, and sets initial register values. * * Parameters: * vcpu: the VCPU structure being initialized * * Return values: * 0: the VCPU was initialized successfully * ENOMEM: insufficient resources * EINVAL: an error occurred during VCPU initialization */ int vcpu_init_vmx(struct vcpu *vcpu) { struct vmcs *vmcs; uint64_t msr, eptp; uint32_t cr0, cr4; int ret = 0; /* Allocate VMCS VA */ vcpu->vc_control_va = (vaddr_t)km_alloc(PAGE_SIZE, &kv_page, &kp_zero, &kd_waitok); vcpu->vc_vmx_vmcs_state = VMCS_CLEARED; if (!vcpu->vc_control_va) return (ENOMEM); /* Compute VMCS PA */ if (!pmap_extract(pmap_kernel(), vcpu->vc_control_va, (paddr_t *)&vcpu->vc_control_pa)) { ret = ENOMEM; goto exit; } /* Allocate MSR bitmap VA */ vcpu->vc_msr_bitmap_va = (vaddr_t)km_alloc(PAGE_SIZE, &kv_page, &kp_zero, &kd_waitok); if (!vcpu->vc_msr_bitmap_va) { ret = ENOMEM; goto exit; } /* Compute MSR bitmap PA */ if (!pmap_extract(pmap_kernel(), vcpu->vc_msr_bitmap_va, (paddr_t *)&vcpu->vc_msr_bitmap_pa)) { ret = ENOMEM; goto exit; } /* Allocate MSR exit load area VA */ vcpu->vc_vmx_msr_exit_load_va = (vaddr_t)km_alloc(PAGE_SIZE, &kv_page, &kp_zero, &kd_waitok); if (!vcpu->vc_vmx_msr_exit_load_va) { ret = ENOMEM; goto exit; } /* Compute MSR exit load area PA */ if (!pmap_extract(pmap_kernel(), vcpu->vc_vmx_msr_exit_load_va, &vcpu->vc_vmx_msr_exit_load_pa)) { ret = ENOMEM; goto exit; } /* Allocate MSR exit save area VA */ vcpu->vc_vmx_msr_exit_save_va = (vaddr_t)km_alloc(PAGE_SIZE, &kv_page, &kp_zero, &kd_waitok); if (!vcpu->vc_vmx_msr_exit_save_va) { ret = ENOMEM; goto exit; } /* Compute MSR exit save area PA */ if (!pmap_extract(pmap_kernel(), vcpu->vc_vmx_msr_exit_save_va, &vcpu->vc_vmx_msr_exit_save_pa)) { ret = ENOMEM; goto exit; } #if 0 /* XXX currently use msr_exit_save for msr_entry_load too */ /* Allocate MSR entry load area VA */ vcpu->vc_vmx_msr_entry_load_va = (vaddr_t)km_alloc(PAGE_SIZE, &kv_page, &kp_zero, &kd_waitok); if (!vcpu->vc_vmx_msr_entry_load_va) { ret = ENOMEM; goto exit; } /* Compute MSR entry load area PA */ if (!pmap_extract(pmap_kernel(), vcpu->vc_vmx_msr_entry_load_va, &vcpu->vc_vmx_msr_entry_load_pa)) { ret = ENOMEM; goto exit; } #endif vmcs = (struct vmcs *)vcpu->vc_control_va; vmcs->vmcs_revision = curcpu()->ci_vmm_cap.vcc_vmx.vmx_vmxon_revision; /* * Load the VMCS onto this PCPU so we can write registers */ if (vmptrld(&vcpu->vc_control_pa)) { ret = EINVAL; goto exit; } /* Configure EPT Pointer */ eptp = vcpu->vc_parent->vm_map->pmap->pm_pdirpa; msr = rdmsr(IA32_VMX_EPT_VPID_CAP); if (msr & IA32_EPT_VPID_CAP_PAGE_WALK_4) { /* Page walk length 4 supported */ eptp |= ((IA32_EPT_PAGE_WALK_LENGTH - 1) << 3); } else { DPRINTF("EPT page walk length 4 not supported\n"); ret = EINVAL; goto exit; } if (msr & IA32_EPT_VPID_CAP_WB) { /* WB cache type supported */ eptp |= IA32_EPT_PAGING_CACHE_TYPE_WB; } else DPRINTF("%s: no WB cache type available, guest VM will run " "uncached\n", __func__); DPRINTF("Guest EPTP = 0x%llx\n", eptp); if (vmwrite(VMCS_GUEST_IA32_EPTP, eptp)) { DPRINTF("%s: error setting guest EPTP\n", __func__); ret = EINVAL; goto exit; } vcpu->vc_parent->vm_map->pmap->eptp = eptp; /* Host CR0 */ cr0 = rcr0() & ~CR0_TS; if (vmwrite(VMCS_HOST_IA32_CR0, cr0)) { DPRINTF("%s: error writing host CR0\n", __func__); ret = EINVAL; goto exit; } /* Host CR4 */ cr4 = rcr4(); if (vmwrite(VMCS_HOST_IA32_CR4, cr4)) { DPRINTF("%s: error writing host CR4\n", __func__); ret = EINVAL; goto exit; } /* Host Segment Selectors */ if (vmwrite(VMCS_HOST_IA32_CS_SEL, GSEL(GCODE_SEL, SEL_KPL))) { DPRINTF("%s: error writing host CS selector\n", __func__); ret = EINVAL; goto exit; } if (vmwrite(VMCS_HOST_IA32_DS_SEL, GSEL(GDATA_SEL, SEL_KPL))) { DPRINTF("%s: error writing host DS selector\n", __func__); ret = EINVAL; goto exit; } if (vmwrite(VMCS_HOST_IA32_ES_SEL, GSEL(GDATA_SEL, SEL_KPL))) { DPRINTF("%s: error writing host ES selector\n", __func__); ret = EINVAL; goto exit; } if (vmwrite(VMCS_HOST_IA32_FS_SEL, GSEL(GDATA_SEL, SEL_KPL))) { DPRINTF("%s: error writing host FS selector\n", __func__); ret = EINVAL; goto exit; } if (vmwrite(VMCS_HOST_IA32_GS_SEL, GSEL(GDATA_SEL, SEL_KPL))) { DPRINTF("%s: error writing host GS selector\n", __func__); ret = EINVAL; goto exit; } if (vmwrite(VMCS_HOST_IA32_SS_SEL, GSEL(GDATA_SEL, SEL_KPL))) { DPRINTF("%s: error writing host SS selector\n", __func__); ret = EINVAL; goto exit; } if (vmwrite(VMCS_HOST_IA32_TR_SEL, GSYSSEL(GPROC0_SEL, SEL_KPL))) { DPRINTF("%s: error writing host TR selector\n", __func__); ret = EINVAL; goto exit; } /* Host IDTR base */ if (vmwrite(VMCS_HOST_IA32_IDTR_BASE, idt_vaddr)) { DPRINTF("%s: error writing host IDTR base\n", __func__); ret = EINVAL; goto exit; } /* VMCS link */ if (vmwrite(VMCS_LINK_POINTER, VMX_VMCS_PA_CLEAR)) { DPRINTF("%s: error writing VMCS link pointer\n", __func__); ret = EINVAL; goto exit; } /* Flush the initial VMCS */ if (vmclear(&vcpu->vc_control_pa)) { DPRINTF("%s: vmclear failed\n", __func__); ret = EINVAL; } exit: if (ret) vcpu_deinit_vmx(vcpu); return (ret); } /* * vcpu_reset_regs * * Resets a vcpu's registers to the provided state * * Parameters: * vcpu: the vcpu whose registers shall be reset * vrs: the desired register state * * Return values: * 0: the vcpu's registers were successfully reset * !0: the vcpu's registers could not be reset (see arch-specific reset * function for various values that can be returned here) */ int vcpu_reset_regs(struct vcpu *vcpu, struct vcpu_reg_state *vrs) { int ret; if (vmm_softc->mode == VMM_MODE_EPT) ret = vcpu_reset_regs_vmx(vcpu, vrs); else if (vmm_softc->mode == VMM_MODE_RVI) ret = vcpu_reset_regs_svm(vcpu, vrs); else panic("%s: unknown vmm mode: %d", __func__, vmm_softc->mode); return (ret); } /* * vcpu_init_svm * * AMD SVM specific VCPU initialization routine. * * This function allocates various per-VCPU memory regions, sets up initial * VCPU VMCB controls, and sets initial register values. * * Parameters: * vcpu: the VCPU structure being initialized * * Return values: * 0: the VCPU was initialized successfully * ENOMEM: insufficient resources * EINVAL: an error occurred during VCPU initialization */ int vcpu_init_svm(struct vcpu *vcpu) { int ret = 0; /* Allocate VMCB VA */ vcpu->vc_control_va = (vaddr_t)km_alloc(PAGE_SIZE, &kv_page, &kp_zero, &kd_waitok); if (!vcpu->vc_control_va) return (ENOMEM); /* Compute VMCB PA */ if (!pmap_extract(pmap_kernel(), vcpu->vc_control_va, (paddr_t *)&vcpu->vc_control_pa)) { ret = ENOMEM; goto exit; } DPRINTF("%s: VMCB va @ 0x%llx, pa @ 0x%llx\n", __func__, (uint64_t)vcpu->vc_control_va, (uint64_t)vcpu->vc_control_pa); /* Allocate MSR bitmap VA (2 pages) */ vcpu->vc_msr_bitmap_va = (vaddr_t)km_alloc(2 * PAGE_SIZE, &kv_any, &vmm_kp_contig, &kd_waitok); if (!vcpu->vc_msr_bitmap_va) { ret = ENOMEM; goto exit; } /* Compute MSR bitmap PA */ if (!pmap_extract(pmap_kernel(), vcpu->vc_msr_bitmap_va, (paddr_t *)&vcpu->vc_msr_bitmap_pa)) { ret = ENOMEM; goto exit; } DPRINTF("%s: MSR bitmap va @ 0x%llx, pa @ 0x%llx\n", __func__, (uint64_t)vcpu->vc_msr_bitmap_va, (uint64_t)vcpu->vc_msr_bitmap_pa); /* Allocate host state area VA */ vcpu->vc_svm_hsa_va = (vaddr_t)km_alloc(PAGE_SIZE, &kv_page, &kp_zero, &kd_waitok); if (!vcpu->vc_svm_hsa_va) { ret = ENOMEM; goto exit; } /* Compute host state area PA */ if (!pmap_extract(pmap_kernel(), vcpu->vc_svm_hsa_va, &vcpu->vc_svm_hsa_pa)) { ret = ENOMEM; goto exit; } DPRINTF("%s: HSA va @ 0x%llx, pa @ 0x%llx\n", __func__, (uint64_t)vcpu->vc_svm_hsa_va, (uint64_t)vcpu->vc_svm_hsa_pa); /* Allocate IOIO area VA (3 pages) */ vcpu->vc_svm_ioio_va = (vaddr_t)km_alloc(3 * PAGE_SIZE, &kv_any, &vmm_kp_contig, &kd_waitok); if (!vcpu->vc_svm_ioio_va) { ret = ENOMEM; goto exit; } /* Compute IOIO area PA */ if (!pmap_extract(pmap_kernel(), vcpu->vc_svm_ioio_va, &vcpu->vc_svm_ioio_pa)) { ret = ENOMEM; goto exit; } DPRINTF("%s: IOIO va @ 0x%llx, pa @ 0x%llx\n", __func__, (uint64_t)vcpu->vc_svm_ioio_va, (uint64_t)vcpu->vc_svm_ioio_pa); exit: if (ret) vcpu_deinit_svm(vcpu); return (ret); } /* * vcpu_init * * Calls the architecture-specific VCPU init routine */ int vcpu_init(struct vcpu *vcpu) { int ret = 0; vcpu->vc_virt_mode = vmm_softc->mode; vcpu->vc_state = VCPU_STATE_STOPPED; vcpu->vc_vpid = 0; vcpu->vc_pvclock_system_gpa = 0; vcpu->vc_last_pcpu = NULL; rw_init(&vcpu->vc_lock, "vcpu"); /* Shadow PAT MSR, starting with host's value. */ vcpu->vc_shadow_pat = rdmsr(MSR_CR_PAT); if (vmm_softc->mode == VMM_MODE_EPT) ret = vcpu_init_vmx(vcpu); else if (vmm_softc->mode == VMM_MODE_RVI) ret = vcpu_init_svm(vcpu); else panic("%s: unknown vmm mode: %d", __func__, vmm_softc->mode); return (ret); } /* * vcpu_deinit_vmx * * Deinitializes the vcpu described by 'vcpu' * * Parameters: * vcpu: the vcpu to be deinited */ void vcpu_deinit_vmx(struct vcpu *vcpu) { if (vcpu->vc_control_va) { km_free((void *)vcpu->vc_control_va, PAGE_SIZE, &kv_page, &kp_zero); vcpu->vc_control_va = 0; } if (vcpu->vc_vmx_msr_exit_save_va) { km_free((void *)vcpu->vc_vmx_msr_exit_save_va, PAGE_SIZE, &kv_page, &kp_zero); vcpu->vc_vmx_msr_exit_save_va = 0; } if (vcpu->vc_vmx_msr_exit_load_va) { km_free((void *)vcpu->vc_vmx_msr_exit_load_va, PAGE_SIZE, &kv_page, &kp_zero); vcpu->vc_vmx_msr_exit_load_va = 0; } #if 0 if (vcpu->vc_vmx_msr_entry_load_va) { km_free((void *)vcpu->vc_vmx_msr_entry_load_va, PAGE_SIZE, &kv_page, &kp_zero); vcpu->vc_vmx_msr_entry_load_va = 0; } #endif if (vcpu->vc_vmx_vpid_enabled) vmm_free_vpid(vcpu->vc_vpid); } /* * vcpu_deinit_svm * * Deinitializes the vcpu described by 'vcpu' * * Parameters: * vcpu: the vcpu to be deinited */ void vcpu_deinit_svm(struct vcpu *vcpu) { if (vcpu->vc_control_va) { km_free((void *)vcpu->vc_control_va, PAGE_SIZE, &kv_page, &kp_zero); vcpu->vc_control_va = 0; } if (vcpu->vc_msr_bitmap_va) { km_free((void *)vcpu->vc_msr_bitmap_va, 2 * PAGE_SIZE, &kv_any, &vmm_kp_contig); vcpu->vc_msr_bitmap_va = 0; } if (vcpu->vc_svm_hsa_va) { km_free((void *)vcpu->vc_svm_hsa_va, PAGE_SIZE, &kv_page, &kp_zero); vcpu->vc_svm_hsa_va = 0; } if (vcpu->vc_svm_ioio_va) { km_free((void *)vcpu->vc_svm_ioio_va, 3 * PAGE_SIZE, &kv_any, &vmm_kp_contig); vcpu->vc_svm_ioio_va = 0; } vmm_free_vpid(vcpu->vc_vpid); } /* * vcpu_deinit * * Calls the architecture-specific VCPU deinit routine * * Parameters: * vcpu: the vcpu to be deinited */ void vcpu_deinit(struct vcpu *vcpu) { if (vmm_softc->mode == VMM_MODE_EPT) vcpu_deinit_vmx(vcpu); else if (vmm_softc->mode == VMM_MODE_RVI) vcpu_deinit_svm(vcpu); else panic("%s: unknown vmm mode: %d", __func__, vmm_softc->mode); } /* * vcpu_vmx_check_cap * * Checks if the 'cap' bit in the 'msr' MSR can be set or cleared (set = 1 * or set = 0, respectively). * * When considering 'msr', we check to see if true controls are available, * and use those if so. * * Returns 1 of 'cap' can be set/cleared as requested, 0 otherwise. */ int vcpu_vmx_check_cap(struct vcpu *vcpu, uint32_t msr, uint32_t cap, int set) { uint64_t ctl; if (vcpu->vc_vmx_basic & IA32_VMX_TRUE_CTLS_AVAIL) { switch (msr) { case IA32_VMX_PINBASED_CTLS: ctl = vcpu->vc_vmx_true_pinbased_ctls; break; case IA32_VMX_PROCBASED_CTLS: ctl = vcpu->vc_vmx_true_procbased_ctls; break; case IA32_VMX_PROCBASED2_CTLS: ctl = vcpu->vc_vmx_procbased2_ctls; break; case IA32_VMX_ENTRY_CTLS: ctl = vcpu->vc_vmx_true_entry_ctls; break; case IA32_VMX_EXIT_CTLS: ctl = vcpu->vc_vmx_true_exit_ctls; break; default: return (0); } } else { switch (msr) { case IA32_VMX_PINBASED_CTLS: ctl = vcpu->vc_vmx_pinbased_ctls; break; case IA32_VMX_PROCBASED_CTLS: ctl = vcpu->vc_vmx_procbased_ctls; break; case IA32_VMX_PROCBASED2_CTLS: ctl = vcpu->vc_vmx_procbased2_ctls; break; case IA32_VMX_ENTRY_CTLS: ctl = vcpu->vc_vmx_entry_ctls; break; case IA32_VMX_EXIT_CTLS: ctl = vcpu->vc_vmx_exit_ctls; break; default: return (0); } } if (set) { /* Check bit 'cap << 32', must be !0 */ return (ctl & ((uint64_t)cap << 32)) != 0; } else { /* Check bit 'cap', must be 0 */ return (ctl & cap) == 0; } } /* * vcpu_vmx_compute_ctrl * * Computes the appropriate control value, given the supplied parameters * and CPU capabilities. * * Intel has made somewhat of a mess of this computation - it is described * using no fewer than three different approaches, spread across many * pages of the SDM. Further compounding the problem is the fact that now * we have "true controls" for each type of "control", and each needs to * be examined to get the calculation right, but only if "true" controls * are present on the CPU we're on. * * Parameters: * ctrlval: the control value, as read from the CPU MSR * ctrl: which control is being set (eg, pinbased, procbased, etc) * want0: the set of desired 0 bits * want1: the set of desired 1 bits * out: (out) the correct value to write into the VMCS for this VCPU, * for the 'ctrl' desired. * * Returns 0 if successful, or EINVAL if the supplied parameters define * an unworkable control setup. */ int vcpu_vmx_compute_ctrl(uint64_t ctrlval, uint16_t ctrl, uint32_t want1, uint32_t want0, uint32_t *out) { int i, set, clear; *out = 0; /* * The Intel SDM gives three formulae for determining which bits to * set/clear for a given control and desired functionality. Formula * 1 is the simplest but disallows use of newer features that are * enabled by functionality in later CPUs. * * Formulas 2 and 3 allow such extra functionality. We use formula * 2 - this requires us to know the identity of controls in the * "default1" class for each control register, but allows us to not * have to pass along and/or query both sets of capability MSRs for * each control lookup. This makes the code slightly longer, * however. */ for (i = 0; i < 32; i++) { /* Figure out if we can set and / or clear this bit */ set = (ctrlval & (1ULL << (i + 32))) != 0; clear = ((1ULL << i) & ((uint64_t)ctrlval)) == 0; /* If the bit can't be set nor cleared, something's wrong */ if (!set && !clear) return (EINVAL); /* * Formula 2.c.i - "If the relevant VMX capability MSR * reports that a control has a single setting, use that * setting." */ if (set && !clear) { if (want0 & (1ULL << i)) return (EINVAL); else *out |= (1ULL << i); } else if (clear && !set) { if (want1 & (1ULL << i)) return (EINVAL); else *out &= ~(1ULL << i); } else { /* * 2.c.ii - "If the relevant VMX capability MSR * reports that a control can be set to 0 or 1 * and that control's meaning is known to the VMM, * set the control based on the functionality desired." */ if (want1 & (1ULL << i)) *out |= (1ULL << i); else if (want0 & (1 << i)) *out &= ~(1ULL << i); else { /* * ... assuming the control's meaning is not * known to the VMM ... * * 2.c.iii - "If the relevant VMX capability * MSR reports that a control can be set to 0 * or 1 and the control is not in the default1 * class, set the control to 0." * * 2.c.iv - "If the relevant VMX capability * MSR reports that a control can be set to 0 * or 1 and the control is in the default1 * class, set the control to 1." */ switch (ctrl) { case IA32_VMX_PINBASED_CTLS: case IA32_VMX_TRUE_PINBASED_CTLS: /* * A.3.1 - default1 class of pinbased * controls comprises bits 1,2,4 */ switch (i) { case 1: case 2: case 4: *out |= (1ULL << i); break; default: *out &= ~(1ULL << i); break; } break; case IA32_VMX_PROCBASED_CTLS: case IA32_VMX_TRUE_PROCBASED_CTLS: /* * A.3.2 - default1 class of procbased * controls comprises bits 1, 4-6, 8, * 13-16, 26 */ switch (i) { case 1: case 4 ... 6: case 8: case 13 ... 16: case 26: *out |= (1ULL << i); break; default: *out &= ~(1ULL << i); break; } break; /* * Unknown secondary procbased controls * can always be set to 0 */ case IA32_VMX_PROCBASED2_CTLS: *out &= ~(1ULL << i); break; case IA32_VMX_EXIT_CTLS: case IA32_VMX_TRUE_EXIT_CTLS: /* * A.4 - default1 class of exit * controls comprises bits 0-8, 10, * 11, 13, 14, 16, 17 */ switch (i) { case 0 ... 8: case 10 ... 11: case 13 ... 14: case 16 ... 17: *out |= (1ULL << i); break; default: *out &= ~(1ULL << i); break; } break; case IA32_VMX_ENTRY_CTLS: case IA32_VMX_TRUE_ENTRY_CTLS: /* * A.5 - default1 class of entry * controls comprises bits 0-8, 12 */ switch (i) { case 0 ... 8: case 12: *out |= (1ULL << i); break; default: *out &= ~(1ULL << i); break; } break; } } } } return (0); } /* * vm_run * * Run the vm / vcpu specified by 'vrp' * * Parameters: * vrp: structure defining the VM to run * * Return value: * ENOENT: the VM defined in 'vrp' could not be located * EBUSY: the VM defined in 'vrp' is already running * EFAULT: error copying data from userspace (vmd) on return from previous * exit. * EAGAIN: help is needed from vmd(8) (device I/O or exit vmm(4) cannot * handle in-kernel.) * 0: the run loop exited and no help is needed from vmd(8) */ int vm_run(struct vm_run_params *vrp) { struct vm *vm; struct vcpu *vcpu; int ret = 0; u_int old, next; /* * Find desired VM */ ret = vm_find(vrp->vrp_vm_id, &vm); if (ret) return (ret); vcpu = vm_find_vcpu(vm, vrp->vrp_vcpu_id); if (vcpu == NULL) { ret = ENOENT; goto out; } /* * Attempt to transition from VCPU_STATE_STOPPED -> VCPU_STATE_RUNNING. * Failure to make the transition indicates the VCPU is busy. */ rw_enter_write(&vcpu->vc_lock); old = VCPU_STATE_STOPPED; next = VCPU_STATE_RUNNING; if (atomic_cas_uint(&vcpu->vc_state, old, next) != old) { ret = EBUSY; goto out_unlock; } /* * We may be returning from userland helping us from the last * exit. Copy in the exit data from vmd. The exit data will be * consumed before the next entry (this typically comprises * VCPU register changes as the result of vmd(8)'s actions). */ ret = copyin(vrp->vrp_exit, &vcpu->vc_exit, sizeof(struct vm_exit)); if (ret) goto out_unlock; vcpu->vc_inject.vie_type = vrp->vrp_inject.vie_type; vcpu->vc_inject.vie_vector = vrp->vrp_inject.vie_vector; vcpu->vc_inject.vie_errorcode = vrp->vrp_inject.vie_errorcode; WRITE_ONCE(vcpu->vc_curcpu, curcpu()); /* Run the VCPU specified in vrp */ if (vcpu->vc_virt_mode == VMM_MODE_EPT) { ret = vcpu_run_vmx(vcpu, vrp); } else if (vcpu->vc_virt_mode == VMM_MODE_RVI) { ret = vcpu_run_svm(vcpu, vrp); } WRITE_ONCE(vcpu->vc_curcpu, NULL); if (ret == 0 || ret == EAGAIN) { /* If we are exiting, populate exit data so vmd can help. */ vrp->vrp_exit_reason = (ret == 0) ? VM_EXIT_NONE : vcpu->vc_gueststate.vg_exit_reason; vrp->vrp_irqready = vcpu->vc_irqready; vcpu->vc_state = VCPU_STATE_STOPPED; if (copyout(&vcpu->vc_exit, vrp->vrp_exit, sizeof(struct vm_exit)) == EFAULT) { ret = EFAULT; } else ret = 0; } else { vrp->vrp_exit_reason = VM_EXIT_TERMINATED; vcpu->vc_state = VCPU_STATE_TERMINATED; } out_unlock: rw_exit_write(&vcpu->vc_lock); out: refcnt_rele_wake(&vm->vm_refcnt); return (ret); } /* * vmm_fpurestore * * Restore the guest's FPU state, saving the existing userland thread's * FPU context if necessary. Must be called with interrupts disabled. */ int vmm_fpurestore(struct vcpu *vcpu) { struct cpu_info *ci = curcpu(); rw_assert_wrlock(&vcpu->vc_lock); /* save vmm's FPU state if we haven't already */ if (ci->ci_pflags & CPUPF_USERXSTATE) { ci->ci_pflags &= ~CPUPF_USERXSTATE; fpusavereset(&curproc->p_addr->u_pcb.pcb_savefpu); } if (vcpu->vc_fpuinited) xrstor_kern(&vcpu->vc_g_fpu, xsave_mask); if (xsave_mask) { /* Restore guest %xcr0 */ if (xsetbv_user(0, vcpu->vc_gueststate.vg_xcr0)) { DPRINTF("%s: guest attempted to set invalid bits in " "xcr0 (guest %%xcr0=0x%llx, host %%xcr0=0x%llx)\n", __func__, vcpu->vc_gueststate.vg_xcr0, xsave_mask); return EINVAL; } } return 0; } /* * vmm_fpusave * * Save the guest's FPU state. Must be called with interrupts disabled. */ void vmm_fpusave(struct vcpu *vcpu) { rw_assert_wrlock(&vcpu->vc_lock); if (xsave_mask) { /* Save guest %xcr0 */ vcpu->vc_gueststate.vg_xcr0 = xgetbv(0); /* Restore host %xcr0 */ xsetbv(0, xsave_mask & XFEATURE_XCR0_MASK); } /* * Save full copy of FPU state - guest content is always * a subset of host's save area (see xsetbv exit handler) */ fpusavereset(&vcpu->vc_g_fpu); vcpu->vc_fpuinited = 1; } /* * vmm_translate_gva * * Translates a guest virtual address to a guest physical address by walking * the currently active page table (if needed). * * Note - this function can possibly alter the supplied VCPU state. * Specifically, it may inject exceptions depending on the current VCPU * configuration, and may alter %cr2 on #PF. Consequently, this function * should only be used as part of instruction emulation. * * Parameters: * vcpu: The VCPU this translation should be performed for (guest MMU settings * are gathered from this VCPU) * va: virtual address to translate * pa: pointer to paddr_t variable that will receive the translated physical * address. 'pa' is unchanged on error. * mode: one of PROT_READ, PROT_WRITE, PROT_EXEC indicating the mode in which * the address should be translated * * Return values: * 0: the address was successfully translated - 'pa' contains the physical * address currently mapped by 'va'. * EFAULT: the PTE for 'VA' is unmapped. A #PF will be injected in this case * and %cr2 set in the vcpu structure. * EINVAL: an error occurred reading paging table structures */ int vmm_translate_gva(struct vcpu *vcpu, uint64_t va, uint64_t *pa, int mode) { int level, shift, pdidx; uint64_t pte, pt_paddr, pte_paddr, mask, low_mask, high_mask; uint64_t shift_width, pte_size, *hva; paddr_t hpa; struct vcpu_reg_state vrs; level = 0; if (vmm_softc->mode == VMM_MODE_EPT) { if (vcpu_readregs_vmx(vcpu, VM_RWREGS_ALL, 1, &vrs)) return (EINVAL); } else if (vmm_softc->mode == VMM_MODE_RVI) { if (vcpu_readregs_svm(vcpu, VM_RWREGS_ALL, &vrs)) return (EINVAL); } else { printf("%s: unknown vmm mode", __func__); return (EINVAL); } DPRINTF("%s: guest %%cr0=0x%llx, %%cr3=0x%llx\n", __func__, vrs.vrs_crs[VCPU_REGS_CR0], vrs.vrs_crs[VCPU_REGS_CR3]); if (!(vrs.vrs_crs[VCPU_REGS_CR0] & CR0_PG)) { DPRINTF("%s: unpaged, va=pa=0x%llx\n", __func__, va); *pa = va; return (0); } pt_paddr = vrs.vrs_crs[VCPU_REGS_CR3]; if (vrs.vrs_crs[VCPU_REGS_CR0] & CR0_PE) { if (vrs.vrs_crs[VCPU_REGS_CR4] & CR4_PAE) { pte_size = sizeof(uint64_t); shift_width = 9; if (vrs.vrs_msrs[VCPU_REGS_EFER] & EFER_LMA) { level = 4; mask = L4_MASK; shift = L4_SHIFT; } else { level = 3; mask = L3_MASK; shift = L3_SHIFT; } } else { level = 2; shift_width = 10; mask = 0xFFC00000; shift = 22; pte_size = sizeof(uint32_t); } } else { return (EINVAL); } DPRINTF("%s: pte size=%lld level=%d mask=0x%llx, shift=%d, " "shift_width=%lld\n", __func__, pte_size, level, mask, shift, shift_width); /* XXX: Check for R bit in segment selector and set A bit */ for (;level > 0; level--) { pdidx = (va & mask) >> shift; pte_paddr = (pt_paddr) + (pdidx * pte_size); DPRINTF("%s: read pte level %d @ GPA 0x%llx\n", __func__, level, pte_paddr); if (!pmap_extract(vcpu->vc_parent->vm_map->pmap, pte_paddr, &hpa)) { DPRINTF("%s: cannot extract HPA for GPA 0x%llx\n", __func__, pte_paddr); return (EINVAL); } hpa = hpa | (pte_paddr & 0xFFF); hva = (uint64_t *)PMAP_DIRECT_MAP(hpa); DPRINTF("%s: GPA 0x%llx -> HPA 0x%llx -> HVA 0x%llx\n", __func__, pte_paddr, (uint64_t)hpa, (uint64_t)hva); if (pte_size == 8) pte = *hva; else pte = *(uint32_t *)hva; DPRINTF("%s: PTE @ 0x%llx = 0x%llx\n", __func__, pte_paddr, pte); /* XXX: Set CR2 */ if (!(pte & PG_V)) return (EFAULT); /* XXX: Check for SMAP */ if ((mode == PROT_WRITE) && !(pte & PG_RW)) return (EPERM); if ((vcpu->vc_exit.cpl > 0) && !(pte & PG_u)) return (EPERM); pte = pte | PG_U; if (mode == PROT_WRITE) pte = pte | PG_M; *hva = pte; /* XXX: EINVAL if in 32bit and PG_PS is 1 but CR4.PSE is 0 */ if (pte & PG_PS) break; if (level > 1) { pt_paddr = pte & PG_FRAME; shift -= shift_width; mask = mask >> shift_width; } } low_mask = ((uint64_t)1ULL << shift) - 1; high_mask = (((uint64_t)1ULL << ((pte_size * 8) - 1)) - 1) ^ low_mask; *pa = (pte & high_mask) | (va & low_mask); DPRINTF("%s: final GPA for GVA 0x%llx = 0x%llx\n", __func__, va, *pa); return (0); } /* * vcpu_run_vmx * * VMX main loop used to run a VCPU. * * Parameters: * vcpu: The VCPU to run * vrp: run parameters * * Return values: * 0: The run loop exited and no help is needed from vmd * EAGAIN: The run loop exited and help from vmd is needed * EINVAL: an error occurred */ int vcpu_run_vmx(struct vcpu *vcpu, struct vm_run_params *vrp) { int ret = 0, exitinfo; struct region_descriptor gdt; struct cpu_info *ci = NULL; uint64_t exit_reason, cr3, msr, insn_error; struct schedstate_percpu *spc; struct vmx_msr_store *msr_store; struct vmx_invvpid_descriptor vid; uint64_t cr0, eii, procbased, int_st; u_long s; rw_assert_wrlock(&vcpu->vc_lock); if (vcpu_reload_vmcs_vmx(vcpu)) { printf("%s: failed (re)loading vmcs\n", __func__); return (EINVAL); } /* * If we are returning from userspace (vmd) because we exited * last time, fix up any needed vcpu state first. Which state * needs to be fixed up depends on what vmd populated in the * exit data structure. */ if (vrp->vrp_intr_pending) vcpu->vc_intr = 1; else vcpu->vc_intr = 0; switch (vcpu->vc_gueststate.vg_exit_reason) { case VMX_EXIT_IO: if (vcpu->vc_exit.vei.vei_dir == VEI_DIR_IN) vcpu->vc_gueststate.vg_rax = vcpu->vc_exit.vei.vei_data; vcpu->vc_gueststate.vg_rip = vcpu->vc_exit.vrs.vrs_gprs[VCPU_REGS_RIP]; if (vmwrite(VMCS_GUEST_IA32_RIP, vcpu->vc_gueststate.vg_rip)) { printf("%s: failed to update rip\n", __func__); return (EINVAL); } break; case VMX_EXIT_EPT_VIOLATION: ret = vcpu_writeregs_vmx(vcpu, VM_RWREGS_GPRS, 0, &vcpu->vc_exit.vrs); if (ret) { printf("%s: vm %d vcpu %d failed to update registers\n", __func__, vcpu->vc_parent->vm_id, vcpu->vc_id); return (EINVAL); } break; } memset(&vcpu->vc_exit, 0, sizeof(vcpu->vc_exit)); /* Host CR3 */ cr3 = rcr3(); if (vmwrite(VMCS_HOST_IA32_CR3, cr3)) { printf("%s: vmwrite(0x%04X, 0x%llx)\n", __func__, VMCS_HOST_IA32_CR3, cr3); return (EINVAL); } /* Handle vmd(8) injected interrupts */ /* Is there an interrupt pending injection? */ if (vcpu->vc_inject.vie_type == VCPU_INJECT_INTR) { if (vmread(VMCS_GUEST_INTERRUPTIBILITY_ST, &int_st)) { printf("%s: can't get interruptibility state\n", __func__); return (EINVAL); } /* Interruptibility state 0x3 covers NMIs and STI */ if (!(int_st & 0x3) && vcpu->vc_irqready) { eii = (uint64_t)vcpu->vc_inject.vie_vector; eii |= (1ULL << 31); /* Valid */ if (vmwrite(VMCS_ENTRY_INTERRUPTION_INFO, eii)) { printf("vcpu_run_vmx: can't vector " "interrupt to guest\n"); return (EINVAL); } vcpu->vc_inject.vie_type = VCPU_INJECT_NONE; } } else if (!vcpu->vc_intr) { /* * Disable window exiting */ if (vmread(VMCS_PROCBASED_CTLS, &procbased)) { printf("%s: can't read procbased ctls on exit\n", __func__); return (EINVAL); } else { procbased &= ~IA32_VMX_INTERRUPT_WINDOW_EXITING; if (vmwrite(VMCS_PROCBASED_CTLS, procbased)) { printf("%s: can't write procbased ctls " "on exit\n", __func__); return (EINVAL); } } } msr_store = (struct vmx_msr_store *)vcpu->vc_vmx_msr_exit_load_va; while (ret == 0) { #ifdef VMM_DEBUG paddr_t pa = 0ULL; vmptrst(&pa); KASSERT(pa == vcpu->vc_control_pa); #endif /* VMM_DEBUG */ vmm_update_pvclock(vcpu); if (ci != curcpu()) { ci = curcpu(); vcpu->vc_last_pcpu = ci; setregion(&gdt, ci->ci_gdt, GDT_SIZE - 1); if (gdt.rd_base == 0) { printf("%s: setregion\n", __func__); return (EINVAL); } /* Host GDTR base */ if (vmwrite(VMCS_HOST_IA32_GDTR_BASE, gdt.rd_base)) { printf("%s: vmwrite(0x%04X, 0x%llx)\n", __func__, VMCS_HOST_IA32_GDTR_BASE, gdt.rd_base); return (EINVAL); } /* Host TR base */ if (vmwrite(VMCS_HOST_IA32_TR_BASE, (uint64_t)ci->ci_tss)) { printf("%s: vmwrite(0x%04X, 0x%llx)\n", __func__, VMCS_HOST_IA32_TR_BASE, (uint64_t)ci->ci_tss); return (EINVAL); } /* Host GS.base (aka curcpu) */ if (vmwrite(VMCS_HOST_IA32_GS_BASE, (uint64_t)ci)) { printf("%s: vmwrite(0x%04X, 0x%llx)\n", __func__, VMCS_HOST_IA32_GS_BASE, (uint64_t)ci); return (EINVAL); } /* Host FS.base */ msr = rdmsr(MSR_FSBASE); if (vmwrite(VMCS_HOST_IA32_FS_BASE, msr)) { printf("%s: vmwrite(0x%04X, 0x%llx)\n", __func__, VMCS_HOST_IA32_FS_BASE, msr); return (EINVAL); } /* Host KernelGS.base (userspace GS.base here) */ msr_store[VCPU_HOST_REGS_KGSBASE].vms_data = rdmsr(MSR_KERNELGSBASE); } /* Inject event if present */ if (vcpu->vc_inject.vie_type == VCPU_INJECT_EX) { eii = (uint64_t)vcpu->vc_inject.vie_vector; eii |= (1ULL << 31); /* Valid */ switch (vcpu->vc_inject.vie_vector) { case VMM_EX_BP: case VMM_EX_OF: /* Software Exceptions */ eii |= (4ULL << 8); break; case VMM_EX_DF: case VMM_EX_TS: case VMM_EX_NP: case VMM_EX_SS: case VMM_EX_GP: case VMM_EX_PF: case VMM_EX_AC: /* Hardware Exceptions */ eii |= (3ULL << 8); cr0 = 0; if (vmread(VMCS_GUEST_IA32_CR0, &cr0)) { printf("%s: vmread(VMCS_GUEST_IA32_CR0)" "\n", __func__); ret = EINVAL; break; } /* Don't set error codes if in real mode. */ if (ret == EINVAL || !(cr0 & CR0_PE)) break; eii |= (1ULL << 11); /* Enforce a 0 error code for #AC. */ if (vcpu->vc_inject.vie_vector == VMM_EX_AC) vcpu->vc_inject.vie_errorcode = 0; /* * XXX: Intel SDM says if IA32_VMX_BASIC[56] is * set, error codes can be injected for hw * exceptions with or without error code, * regardless of vector. See Vol 3D. A1. Ignore * this capability for now. */ if (vmwrite(VMCS_ENTRY_EXCEPTION_ERROR_CODE, vcpu->vc_inject.vie_errorcode)) { printf("%s: can't write error code to " "guest\n", __func__); ret = EINVAL; } } /* switch */ if (ret == EINVAL) break; if (vmwrite(VMCS_ENTRY_INTERRUPTION_INFO, eii)) { printf("%s: can't vector event to guest\n", __func__); ret = EINVAL; break; } vcpu->vc_inject.vie_type = VCPU_INJECT_NONE; } if (vcpu->vc_vmx_vpid_enabled) { /* Invalidate old TLB mappings */ vid.vid_vpid = vcpu->vc_vpid; vid.vid_addr = 0; invvpid(IA32_VMX_INVVPID_SINGLE_CTX_GLB, &vid); } /* Start / resume the VCPU */ /* Disable interrupts and save the current host FPU state. */ s = intr_disable(); if ((ret = vmm_fpurestore(vcpu))) { intr_restore(s); break; } TRACEPOINT(vmm, guest_enter, vcpu, vrp); /* * If we're resuming to a different VCPU and have IBPB, * then use it to prevent cross-VM branch-target injection. */ if (ci->ci_guest_vcpu != vcpu && (ci->ci_feature_sefflags_edx & SEFF0EDX_IBRS)) { wrmsr(MSR_PRED_CMD, PRED_CMD_IBPB); ci->ci_guest_vcpu = vcpu; } /* Restore any guest PKRU state. */ if (vmm_softc->sc_md.pkru_enabled) wrpkru(0, vcpu->vc_pkru); ret = vmx_enter_guest(&vcpu->vc_control_pa, &vcpu->vc_gueststate, (vcpu->vc_vmx_vmcs_state == VMCS_LAUNCHED), ci->ci_vmm_cap.vcc_vmx.vmx_has_l1_flush_msr); /* Restore host PKRU state. */ if (vmm_softc->sc_md.pkru_enabled) { vcpu->vc_pkru = rdpkru(0); wrpkru(0, PGK_VALUE); } /* * VM exit restores the GDT and IDT bases, but gives * them high limits. Reload with the correct limits here. * 'gdt' is set above first time through and reset there * whenever this thread switches CPU. */ bare_lgdt(&gdt); cpu_init_idt(); /* * On exit, interrupts are disabled, and we are running with * the guest FPU state still possibly on the CPU. Save the FPU * state before re-enabling interrupts. */ vmm_fpusave(vcpu); intr_restore(s); atomic_swap_uint(&vcpu->vc_vmx_vmcs_state, VMCS_LAUNCHED); exit_reason = VM_EXIT_NONE; /* If we exited successfully ... */ if (ret == 0) { exitinfo = vmx_get_exit_info( &vcpu->vc_gueststate.vg_rip, &exit_reason); if (!(exitinfo & VMX_EXIT_INFO_HAVE_RIP)) { printf("%s: cannot read guest rip\n", __func__); ret = EINVAL; break; } if (!(exitinfo & VMX_EXIT_INFO_HAVE_REASON)) { printf("%s: cant read exit reason\n", __func__); ret = EINVAL; break; } vcpu->vc_gueststate.vg_exit_reason = exit_reason; TRACEPOINT(vmm, guest_exit, vcpu, vrp, exit_reason); /* Update our state */ if (vmread(VMCS_GUEST_IA32_RFLAGS, &vcpu->vc_gueststate.vg_rflags)) { printf("%s: can't read guest rflags during " "exit\n", __func__); ret = EINVAL; break; } /* * Handle the exit. This will alter "ret" to EAGAIN if * the exit handler determines help from vmd is needed. */ ret = vmx_handle_exit(vcpu); if (vcpu->vc_gueststate.vg_rflags & PSL_I) vcpu->vc_irqready = 1; else vcpu->vc_irqready = 0; /* * If not ready for interrupts, but interrupts pending, * enable interrupt window exiting. */ if (vcpu->vc_irqready == 0 && vcpu->vc_intr) { if (vmread(VMCS_PROCBASED_CTLS, &procbased)) { printf("%s: can't read procbased ctls " "on intwin exit\n", __func__); ret = EINVAL; break; } procbased |= IA32_VMX_INTERRUPT_WINDOW_EXITING; if (vmwrite(VMCS_PROCBASED_CTLS, procbased)) { printf("%s: can't write procbased ctls " "on intwin exit\n", __func__); ret = EINVAL; break; } } /* * Exit to vmd if we are terminating, failed to enter, * or need help (device I/O) */ if (ret || vcpu_must_stop(vcpu)) break; if (vcpu->vc_intr && vcpu->vc_irqready) { ret = EAGAIN; break; } /* Check if we should yield - don't hog the {p,v}pu */ spc = &ci->ci_schedstate; if (spc->spc_schedflags & SPCF_SHOULDYIELD) break; } else { /* * We failed vmresume or vmlaunch for some reason, * typically due to invalid vmcs state or other * reasons documented in SDM Vol 3C 30.4. */ switch (ret) { case VMX_FAIL_LAUNCH_INVALID_VMCS: printf("%s: failed %s with invalid vmcs\n", __func__, (vcpu->vc_vmx_vmcs_state == VMCS_LAUNCHED ? "vmresume" : "vmlaunch")); break; case VMX_FAIL_LAUNCH_VALID_VMCS: printf("%s: failed %s with valid vmcs\n", __func__, (vcpu->vc_vmx_vmcs_state == VMCS_LAUNCHED ? "vmresume" : "vmlaunch")); break; default: printf("%s: failed %s for unknown reason\n", __func__, (vcpu->vc_vmx_vmcs_state == VMCS_LAUNCHED ? "vmresume" : "vmlaunch")); } ret = EINVAL; /* Try to translate a vmfail error code, if possible. */ if (vmread(VMCS_INSTRUCTION_ERROR, &insn_error)) { printf("%s: can't read insn error field\n", __func__); } else printf("%s: error code = %lld, %s\n", __func__, insn_error, vmx_instruction_error_decode(insn_error)); #ifdef VMM_DEBUG vmx_vcpu_dump_regs(vcpu); dump_vcpu(vcpu); #endif /* VMM_DEBUG */ } } vcpu->vc_last_pcpu = curcpu(); /* Copy the VCPU register state to the exit structure */ if (vcpu_readregs_vmx(vcpu, VM_RWREGS_ALL, 0, &vcpu->vc_exit.vrs)) ret = EINVAL; vcpu->vc_exit.cpl = vmm_get_guest_cpu_cpl(vcpu); return (ret); } /* * vmx_handle_intr * * Handle host (external) interrupts. We read which interrupt fired by * extracting the vector from the VMCS and dispatch the interrupt directly * to the host using vmm_dispatch_intr. */ void vmx_handle_intr(struct vcpu *vcpu) { uint8_t vec; uint64_t eii; struct gate_descriptor *idte; vaddr_t handler; if (vmread(VMCS_EXIT_INTERRUPTION_INFO, &eii)) { printf("%s: can't obtain intr info\n", __func__); return; } vec = eii & 0xFF; /* XXX check "error valid" code in eii, abort if 0 */ idte=&idt[vec]; handler = idte->gd_looffset + ((uint64_t)idte->gd_hioffset << 16); vmm_dispatch_intr(handler); } /* * svm_handle_hlt * * Handle HLT exits * * Parameters * vcpu: The VCPU that executed the HLT instruction * * Return Values: * EIO: The guest halted with interrupts disabled * EAGAIN: Normal return to vmd - vmd should halt scheduling this VCPU * until a virtual interrupt is ready to inject */ int svm_handle_hlt(struct vcpu *vcpu) { struct vmcb *vmcb = (struct vmcb *)vcpu->vc_control_va; uint64_t rflags = vmcb->v_rflags; /* All HLT insns are 1 byte */ vcpu->vc_gueststate.vg_rip += 1; if (!(rflags & PSL_I)) { DPRINTF("%s: guest halted with interrupts disabled\n", __func__); return (EIO); } return (EAGAIN); } /* * vmx_handle_hlt * * Handle HLT exits. HLTing the CPU with interrupts disabled will terminate * the guest (no NMIs handled) by returning EIO to vmd. * * Parameters: * vcpu: The VCPU that executed the HLT instruction * * Return Values: * EINVAL: An error occurred extracting information from the VMCS, or an * invalid HLT instruction was encountered * EIO: The guest halted with interrupts disabled * EAGAIN: Normal return to vmd - vmd should halt scheduling this VCPU * until a virtual interrupt is ready to inject * */ int vmx_handle_hlt(struct vcpu *vcpu) { uint64_t insn_length, rflags; if (vmread(VMCS_INSTRUCTION_LENGTH, &insn_length)) { printf("%s: can't obtain instruction length\n", __func__); return (EINVAL); } if (vmread(VMCS_GUEST_IA32_RFLAGS, &rflags)) { printf("%s: can't obtain guest rflags\n", __func__); return (EINVAL); } if (insn_length != 1) { DPRINTF("%s: HLT with instruction length %lld not supported\n", __func__, insn_length); return (EINVAL); } if (!(rflags & PSL_I)) { DPRINTF("%s: guest halted with interrupts disabled\n", __func__); return (EIO); } vcpu->vc_gueststate.vg_rip += insn_length; return (EAGAIN); } /* * vmx_get_exit_info * * Returns exit information containing the current guest RIP and exit reason * in rip and exit_reason. The return value is a bitmask indicating whether * reading the RIP and exit reason was successful. */ int vmx_get_exit_info(uint64_t *rip, uint64_t *exit_reason) { int rv = 0; if (vmread(VMCS_GUEST_IA32_RIP, rip) == 0) { rv |= VMX_EXIT_INFO_HAVE_RIP; if (vmread(VMCS_EXIT_REASON, exit_reason) == 0) rv |= VMX_EXIT_INFO_HAVE_REASON; } return (rv); } /* * svm_handle_exit * * Handle exits from the VM by decoding the exit reason and calling various * subhandlers as needed. */ int svm_handle_exit(struct vcpu *vcpu) { uint64_t exit_reason, rflags; int update_rip, ret = 0; struct vmcb *vmcb = (struct vmcb *)vcpu->vc_control_va; update_rip = 0; exit_reason = vcpu->vc_gueststate.vg_exit_reason; rflags = vcpu->vc_gueststate.vg_rflags; switch (exit_reason) { case SVM_VMEXIT_VINTR: if (!(rflags & PSL_I)) { DPRINTF("%s: impossible interrupt window exit " "config\n", __func__); ret = EINVAL; break; } /* * Guest is now ready for interrupts, so disable interrupt * window exiting. */ vmcb->v_irq = 0; vmcb->v_intr_vector = 0; vmcb->v_intercept1 &= ~SVM_INTERCEPT_VINTR; svm_set_dirty(vcpu, SVM_CLEANBITS_TPR | SVM_CLEANBITS_I); update_rip = 0; break; case SVM_VMEXIT_INTR: update_rip = 0; break; case SVM_VMEXIT_SHUTDOWN: update_rip = 0; ret = EAGAIN; break; case SVM_VMEXIT_NPF: ret = svm_handle_np_fault(vcpu); break; case SVM_VMEXIT_CPUID: ret = vmm_handle_cpuid(vcpu); update_rip = 1; break; case SVM_VMEXIT_MSR: ret = svm_handle_msr(vcpu); update_rip = 1; break; case SVM_VMEXIT_XSETBV: ret = svm_handle_xsetbv(vcpu); update_rip = 1; break; case SVM_VMEXIT_IOIO: if (svm_handle_inout(vcpu) == 0) ret = EAGAIN; break; case SVM_VMEXIT_HLT: ret = svm_handle_hlt(vcpu); update_rip = 1; break; case SVM_VMEXIT_MWAIT: case SVM_VMEXIT_MWAIT_CONDITIONAL: case SVM_VMEXIT_MONITOR: case SVM_VMEXIT_VMRUN: case SVM_VMEXIT_VMMCALL: case SVM_VMEXIT_VMLOAD: case SVM_VMEXIT_VMSAVE: case SVM_VMEXIT_STGI: case SVM_VMEXIT_CLGI: case SVM_VMEXIT_SKINIT: case SVM_VMEXIT_RDTSCP: case SVM_VMEXIT_ICEBP: case SVM_VMEXIT_INVLPGA: ret = vmm_inject_ud(vcpu); update_rip = 0; break; default: DPRINTF("%s: unhandled exit 0x%llx (pa=0x%llx)\n", __func__, exit_reason, (uint64_t)vcpu->vc_control_pa); return (EINVAL); } if (update_rip) { vmcb->v_rip = vcpu->vc_gueststate.vg_rip; if (rflags & PSL_T) { if (vmm_inject_db(vcpu)) { printf("%s: can't inject #DB exception to " "guest", __func__); return (EINVAL); } } } /* Enable SVME in EFER (must always be set) */ vmcb->v_efer |= EFER_SVME; svm_set_dirty(vcpu, SVM_CLEANBITS_CR); return (ret); } /* * vmx_handle_exit * * Handle exits from the VM by decoding the exit reason and calling various * subhandlers as needed. */ int vmx_handle_exit(struct vcpu *vcpu) { uint64_t exit_reason, rflags, istate; int update_rip, ret = 0; update_rip = 0; exit_reason = vcpu->vc_gueststate.vg_exit_reason; rflags = vcpu->vc_gueststate.vg_rflags; switch (exit_reason) { case VMX_EXIT_INT_WINDOW: if (!(rflags & PSL_I)) { DPRINTF("%s: impossible interrupt window exit " "config\n", __func__); ret = EINVAL; break; } ret = EAGAIN; update_rip = 0; break; case VMX_EXIT_EPT_VIOLATION: ret = vmx_handle_np_fault(vcpu); break; case VMX_EXIT_CPUID: ret = vmm_handle_cpuid(vcpu); update_rip = 1; break; case VMX_EXIT_IO: if (vmx_handle_inout(vcpu) == 0) ret = EAGAIN; break; case VMX_EXIT_EXTINT: vmx_handle_intr(vcpu); update_rip = 0; break; case VMX_EXIT_CR_ACCESS: ret = vmx_handle_cr(vcpu); update_rip = 1; break; case VMX_EXIT_HLT: ret = vmx_handle_hlt(vcpu); update_rip = 1; break; case VMX_EXIT_RDMSR: ret = vmx_handle_rdmsr(vcpu); update_rip = 1; break; case VMX_EXIT_WRMSR: ret = vmx_handle_wrmsr(vcpu); update_rip = 1; break; case VMX_EXIT_XSETBV: ret = vmx_handle_xsetbv(vcpu); update_rip = 1; break; case VMX_EXIT_MWAIT: case VMX_EXIT_MONITOR: case VMX_EXIT_VMXON: case VMX_EXIT_VMWRITE: case VMX_EXIT_VMREAD: case VMX_EXIT_VMLAUNCH: case VMX_EXIT_VMRESUME: case VMX_EXIT_VMPTRLD: case VMX_EXIT_VMPTRST: case VMX_EXIT_VMCLEAR: case VMX_EXIT_VMCALL: case VMX_EXIT_VMFUNC: case VMX_EXIT_VMXOFF: case VMX_EXIT_INVVPID: case VMX_EXIT_INVEPT: ret = vmm_inject_ud(vcpu); update_rip = 0; break; case VMX_EXIT_TRIPLE_FAULT: #ifdef VMM_DEBUG DPRINTF("%s: vm %d vcpu %d triple fault\n", __func__, vcpu->vc_parent->vm_id, vcpu->vc_id); vmx_vcpu_dump_regs(vcpu); dump_vcpu(vcpu); vmx_dump_vmcs(vcpu); #endif /* VMM_DEBUG */ ret = EAGAIN; update_rip = 0; break; default: #ifdef VMM_DEBUG DPRINTF("%s: unhandled exit 0x%llx (%s)\n", __func__, exit_reason, vmx_exit_reason_decode(exit_reason)); #endif /* VMM_DEBUG */ return (EINVAL); } if (update_rip) { if (vmwrite(VMCS_GUEST_IA32_RIP, vcpu->vc_gueststate.vg_rip)) { printf("%s: can't advance rip\n", __func__); return (EINVAL); } if (vmread(VMCS_GUEST_INTERRUPTIBILITY_ST, &istate)) { printf("%s: can't read interruptibility state\n", __func__); return (EINVAL); } /* Interruptibility state 0x3 covers NMIs and STI */ istate &= ~0x3; if (vmwrite(VMCS_GUEST_INTERRUPTIBILITY_ST, istate)) { printf("%s: can't write interruptibility state\n", __func__); return (EINVAL); } if (rflags & PSL_T) { if (vmm_inject_db(vcpu)) { printf("%s: can't inject #DB exception to " "guest", __func__); return (EINVAL); } } } return (ret); } /* * vmm_inject_gp * * Injects an #GP exception into the guest VCPU. * * Parameters: * vcpu: vcpu to inject into * * Return values: * Always 0 */ int vmm_inject_gp(struct vcpu *vcpu) { DPRINTF("%s: injecting #GP at guest %%rip 0x%llx\n", __func__, vcpu->vc_gueststate.vg_rip); vcpu->vc_inject.vie_vector = VMM_EX_GP; vcpu->vc_inject.vie_type = VCPU_INJECT_EX; vcpu->vc_inject.vie_errorcode = 0; return (0); } /* * vmm_inject_ud * * Injects an #UD exception into the guest VCPU. * * Parameters: * vcpu: vcpu to inject into * * Return values: * Always 0 */ int vmm_inject_ud(struct vcpu *vcpu) { DPRINTF("%s: injecting #UD at guest %%rip 0x%llx\n", __func__, vcpu->vc_gueststate.vg_rip); vcpu->vc_inject.vie_vector = VMM_EX_UD; vcpu->vc_inject.vie_type = VCPU_INJECT_EX; vcpu->vc_inject.vie_errorcode = 0; return (0); } /* * vmm_inject_db * * Injects a #DB exception into the guest VCPU. * * Parameters: * vcpu: vcpu to inject into * * Return values: * Always 0 */ int vmm_inject_db(struct vcpu *vcpu) { DPRINTF("%s: injecting #DB at guest %%rip 0x%llx\n", __func__, vcpu->vc_gueststate.vg_rip); vcpu->vc_inject.vie_vector = VMM_EX_DB; vcpu->vc_inject.vie_type = VCPU_INJECT_EX; vcpu->vc_inject.vie_errorcode = 0; return (0); } /* * vmm_get_guest_memtype * * Returns the type of memory 'gpa' refers to in the context of vm 'vm' */ int vmm_get_guest_memtype(struct vm *vm, paddr_t gpa) { int i; struct vm_mem_range *vmr; /* XXX Use binary search? */ for (i = 0; i < vm->vm_nmemranges; i++) { vmr = &vm->vm_memranges[i]; /* * vm_memranges are ascending. gpa can no longer be in one of * the memranges */ if (gpa < vmr->vmr_gpa) break; if (gpa < vmr->vmr_gpa + vmr->vmr_size) { if (vmr->vmr_type == VM_MEM_MMIO) return (VMM_MEM_TYPE_MMIO); return (VMM_MEM_TYPE_REGULAR); } } DPRINTF("guest memtype @ 0x%llx unknown\n", (uint64_t)gpa); return (VMM_MEM_TYPE_UNKNOWN); } /* * vmx_get_exit_qualification * * Return the current VMCS' exit qualification information */ int vmx_get_exit_qualification(uint64_t *exit_qualification) { if (vmread(VMCS_GUEST_EXIT_QUALIFICATION, exit_qualification)) { printf("%s: can't extract exit qual\n", __func__); return (EINVAL); } return (0); } /* * vmx_get_guest_faulttype * * Determines the type (R/W/X) of the last fault on the VCPU last run on * this PCPU. */ int vmx_get_guest_faulttype(void) { uint64_t exit_qual; uint64_t presentmask = IA32_VMX_EPT_FAULT_WAS_READABLE | IA32_VMX_EPT_FAULT_WAS_WRITABLE | IA32_VMX_EPT_FAULT_WAS_EXECABLE; vm_prot_t prot, was_prot; if (vmx_get_exit_qualification(&exit_qual)) return (-1); if ((exit_qual & presentmask) == 0) return VM_FAULT_INVALID; was_prot = 0; if (exit_qual & IA32_VMX_EPT_FAULT_WAS_READABLE) was_prot |= PROT_READ; if (exit_qual & IA32_VMX_EPT_FAULT_WAS_WRITABLE) was_prot |= PROT_WRITE; if (exit_qual & IA32_VMX_EPT_FAULT_WAS_EXECABLE) was_prot |= PROT_EXEC; prot = 0; if (exit_qual & IA32_VMX_EPT_FAULT_READ) prot = PROT_READ; else if (exit_qual & IA32_VMX_EPT_FAULT_WRITE) prot = PROT_WRITE; else if (exit_qual & IA32_VMX_EPT_FAULT_EXEC) prot = PROT_EXEC; if ((was_prot & prot) == 0) return VM_FAULT_PROTECT; return (-1); } /* * svm_get_guest_faulttype * * Determines the type (R/W/X) of the last fault on the VCPU last run on * this PCPU. */ int svm_get_guest_faulttype(struct vmcb *vmcb) { if (!(vmcb->v_exitinfo1 & 0x1)) return VM_FAULT_INVALID; return VM_FAULT_PROTECT; } /* * svm_fault_page * * Request a new page to be faulted into the UVM map of the VM owning 'vcpu' * at address 'gpa'. */ int svm_fault_page(struct vcpu *vcpu, paddr_t gpa) { int ret; ret = uvm_fault(vcpu->vc_parent->vm_map, gpa, VM_FAULT_WIRE, PROT_READ | PROT_WRITE | PROT_EXEC); if (ret) printf("%s: uvm_fault returns %d, GPA=0x%llx, rip=0x%llx\n", __func__, ret, (uint64_t)gpa, vcpu->vc_gueststate.vg_rip); return (ret); } /* * svm_handle_np_fault * * High level nested paging handler for SVM. Verifies that a fault is for a * valid memory region, then faults a page, or aborts otherwise. */ int svm_handle_np_fault(struct vcpu *vcpu) { uint64_t gpa; int gpa_memtype, ret = 0; struct vmcb *vmcb = (struct vmcb *)vcpu->vc_control_va; struct vm_exit_eptviolation *vee = &vcpu->vc_exit.vee; struct cpu_info *ci = curcpu(); memset(vee, 0, sizeof(*vee)); gpa = vmcb->v_exitinfo2; gpa_memtype = vmm_get_guest_memtype(vcpu->vc_parent, gpa); switch (gpa_memtype) { case VMM_MEM_TYPE_REGULAR: vee->vee_fault_type = VEE_FAULT_HANDLED; ret = svm_fault_page(vcpu, gpa); break; case VMM_MEM_TYPE_MMIO: vee->vee_fault_type = VEE_FAULT_MMIO_ASSIST; if (ci->ci_vmm_cap.vcc_svm.svm_decode_assist) { vee->vee_insn_len = vmcb->v_n_bytes_fetched; memcpy(&vee->vee_insn_bytes, vmcb->v_guest_ins_bytes, sizeof(vee->vee_insn_bytes)); vee->vee_insn_info |= VEE_BYTES_VALID; } ret = EAGAIN; break; default: printf("%s: unknown memory type %d for GPA 0x%llx\n", __func__, gpa_memtype, gpa); return (EINVAL); } return (ret); } /* * vmx_fault_page * * Request a new page to be faulted into the UVM map of the VM owning 'vcpu' * at address 'gpa'. * * Parameters: * vcpu: guest VCPU requiring the page to be faulted into the UVM map * gpa: guest physical address that triggered the fault * * Return Values: * 0: if successful * EINVAL: if fault type could not be determined or VMCS reload fails * EAGAIN: if a protection fault occurred, ie writing to a read-only page * errno: if uvm_fault(9) fails to wire in the page */ int vmx_fault_page(struct vcpu *vcpu, paddr_t gpa) { int fault_type, ret; fault_type = vmx_get_guest_faulttype(); switch (fault_type) { case -1: printf("%s: invalid fault type\n", __func__); return (EINVAL); case VM_FAULT_PROTECT: vcpu->vc_exit.vee.vee_fault_type = VEE_FAULT_PROTECT; return (EAGAIN); default: vcpu->vc_exit.vee.vee_fault_type = VEE_FAULT_HANDLED; break; } /* We may sleep during uvm_fault(9), so reload VMCS. */ vcpu->vc_last_pcpu = curcpu(); ret = uvm_fault(vcpu->vc_parent->vm_map, gpa, VM_FAULT_WIRE, PROT_READ | PROT_WRITE | PROT_EXEC); if (vcpu_reload_vmcs_vmx(vcpu)) { printf("%s: failed to reload vmcs\n", __func__); return (EINVAL); } if (ret) printf("%s: uvm_fault returns %d, GPA=0x%llx, rip=0x%llx\n", __func__, ret, (uint64_t)gpa, vcpu->vc_gueststate.vg_rip); return (ret); } /* * vmx_handle_np_fault * * High level nested paging handler for VMX. Verifies that a fault is for a * valid memory region, then faults a page, or aborts otherwise. */ int vmx_handle_np_fault(struct vcpu *vcpu) { uint64_t insn_len = 0, gpa; int gpa_memtype, ret = 0; struct vm_exit_eptviolation *vee = &vcpu->vc_exit.vee; memset(vee, 0, sizeof(*vee)); if (vmread(VMCS_GUEST_PHYSICAL_ADDRESS, &gpa)) { printf("%s: cannot extract faulting pa\n", __func__); return (EINVAL); } gpa_memtype = vmm_get_guest_memtype(vcpu->vc_parent, gpa); switch (gpa_memtype) { case VMM_MEM_TYPE_REGULAR: vee->vee_fault_type = VEE_FAULT_HANDLED; ret = vmx_fault_page(vcpu, gpa); break; case VMM_MEM_TYPE_MMIO: vee->vee_fault_type = VEE_FAULT_MMIO_ASSIST; if (vmread(VMCS_INSTRUCTION_LENGTH, &insn_len) || insn_len == 0 || insn_len > 15) { printf("%s: failed to extract instruction length\n", __func__); ret = EINVAL; } else { vee->vee_insn_len = (uint32_t)insn_len; vee->vee_insn_info |= VEE_LEN_VALID; ret = EAGAIN; } break; default: printf("%s: unknown memory type %d for GPA 0x%llx\n", __func__, gpa_memtype, gpa); return (EINVAL); } return (ret); } /* * vmm_get_guest_cpu_cpl * * Determines current CPL of 'vcpu'. On VMX/Intel, this is gathered from the * VMCS field for the DPL of SS (this seems odd, but is documented that way * in the SDM). For SVM/AMD, this is gathered directly from the VMCB's 'cpl' * field, as per the APM. * * Parameters: * vcpu: guest VCPU for which CPL is to be checked * * Return Values: * -1: the CPL could not be determined * 0-3 indicating the current CPL. For real mode operation, 0 is returned. */ int vmm_get_guest_cpu_cpl(struct vcpu *vcpu) { int mode; struct vmcb *vmcb; uint64_t ss_ar; mode = vmm_get_guest_cpu_mode(vcpu); if (mode == VMM_CPU_MODE_UNKNOWN) return (-1); if (mode == VMM_CPU_MODE_REAL) return (0); if (vmm_softc->mode == VMM_MODE_RVI) { vmcb = (struct vmcb *)vcpu->vc_control_va; return (vmcb->v_cpl); } else if (vmm_softc->mode == VMM_MODE_EPT) { if (vmread(VMCS_GUEST_IA32_SS_AR, &ss_ar)) return (-1); return ((ss_ar & 0x60) >> 5); } else return (-1); } /* * vmm_get_guest_cpu_mode * * Determines current CPU mode of 'vcpu'. * * Parameters: * vcpu: guest VCPU for which mode is to be checked * * Return Values: * One of VMM_CPU_MODE_*, or VMM_CPU_MODE_UNKNOWN if the mode could not be * ascertained. */ int vmm_get_guest_cpu_mode(struct vcpu *vcpu) { uint64_t cr0, efer, cs_ar; uint8_t l, dib; struct vmcb *vmcb; struct vmx_msr_store *msr_store; if (vmm_softc->mode == VMM_MODE_RVI) { vmcb = (struct vmcb *)vcpu->vc_control_va; cr0 = vmcb->v_cr0; efer = vmcb->v_efer; cs_ar = vmcb->v_cs.vs_attr; cs_ar = (cs_ar & 0xff) | ((cs_ar << 4) & 0xf000); } else if (vmm_softc->mode == VMM_MODE_EPT) { if (vmread(VMCS_GUEST_IA32_CR0, &cr0)) return (VMM_CPU_MODE_UNKNOWN); if (vmread(VMCS_GUEST_IA32_CS_AR, &cs_ar)) return (VMM_CPU_MODE_UNKNOWN); msr_store = (struct vmx_msr_store *)vcpu->vc_vmx_msr_exit_save_va; efer = msr_store[VCPU_REGS_EFER].vms_data; } else return (VMM_CPU_MODE_UNKNOWN); l = (cs_ar & 0x2000) >> 13; dib = (cs_ar & 0x4000) >> 14; /* Check CR0.PE */ if (!(cr0 & CR0_PE)) return (VMM_CPU_MODE_REAL); /* Check EFER */ if (efer & EFER_LMA) { /* Could be compat or long mode, check CS.L */ if (l) return (VMM_CPU_MODE_LONG); else return (VMM_CPU_MODE_COMPAT); } /* Check prot vs prot32 */ if (dib) return (VMM_CPU_MODE_PROT32); else return (VMM_CPU_MODE_PROT); } /* * svm_handle_inout * * Exit handler for IN/OUT instructions. * * Parameters: * vcpu: The VCPU where the IN/OUT instruction occurred * * Return values: * 0: if successful * EINVAL: an invalid IN/OUT instruction was encountered */ int svm_handle_inout(struct vcpu *vcpu) { uint64_t insn_length, exit_qual; struct vmcb *vmcb = (struct vmcb *)vcpu->vc_control_va; insn_length = vmcb->v_exitinfo2 - vmcb->v_rip; exit_qual = vmcb->v_exitinfo1; /* Bit 0 - direction */ if (exit_qual & 0x1) vcpu->vc_exit.vei.vei_dir = VEI_DIR_IN; else vcpu->vc_exit.vei.vei_dir = VEI_DIR_OUT; /* Bit 2 - string instruction? */ vcpu->vc_exit.vei.vei_string = (exit_qual & 0x4) >> 2; /* Bit 3 - REP prefix? */ vcpu->vc_exit.vei.vei_rep = (exit_qual & 0x8) >> 3; /* Bits 4:6 - size of exit */ if (exit_qual & 0x10) vcpu->vc_exit.vei.vei_size = 1; else if (exit_qual & 0x20) vcpu->vc_exit.vei.vei_size = 2; else if (exit_qual & 0x40) vcpu->vc_exit.vei.vei_size = 4; /* Bit 16:31 - port */ vcpu->vc_exit.vei.vei_port = (exit_qual & 0xFFFF0000) >> 16; /* Data */ vcpu->vc_exit.vei.vei_data = vmcb->v_rax; vcpu->vc_exit.vei.vei_insn_len = (uint8_t)insn_length; TRACEPOINT(vmm, inout, vcpu, vcpu->vc_exit.vei.vei_port, vcpu->vc_exit.vei.vei_dir, vcpu->vc_exit.vei.vei_data); return (0); } /* * vmx_handle_inout * * Exit handler for IN/OUT instructions. * * Parameters: * vcpu: The VCPU where the IN/OUT instruction occurred * * Return values: * 0: if successful * EINVAL: invalid IN/OUT instruction or vmread failures occurred */ int vmx_handle_inout(struct vcpu *vcpu) { uint64_t insn_length, exit_qual; if (vmread(VMCS_INSTRUCTION_LENGTH, &insn_length)) { printf("%s: can't obtain instruction length\n", __func__); return (EINVAL); } if (vmx_get_exit_qualification(&exit_qual)) { printf("%s: can't get exit qual\n", __func__); return (EINVAL); } /* Bits 0:2 - size of exit */ vcpu->vc_exit.vei.vei_size = (exit_qual & 0x7) + 1; /* Bit 3 - direction */ if ((exit_qual & 0x8) >> 3) vcpu->vc_exit.vei.vei_dir = VEI_DIR_IN; else vcpu->vc_exit.vei.vei_dir = VEI_DIR_OUT; /* Bit 4 - string instruction? */ vcpu->vc_exit.vei.vei_string = (exit_qual & 0x10) >> 4; /* Bit 5 - REP prefix? */ vcpu->vc_exit.vei.vei_rep = (exit_qual & 0x20) >> 5; /* Bit 6 - Operand encoding */ vcpu->vc_exit.vei.vei_encoding = (exit_qual & 0x40) >> 6; /* Bit 16:31 - port */ vcpu->vc_exit.vei.vei_port = (exit_qual & 0xFFFF0000) >> 16; /* Data */ vcpu->vc_exit.vei.vei_data = (uint32_t)vcpu->vc_gueststate.vg_rax; vcpu->vc_exit.vei.vei_insn_len = (uint8_t)insn_length; TRACEPOINT(vmm, inout, vcpu, vcpu->vc_exit.vei.vei_port, vcpu->vc_exit.vei.vei_dir, vcpu->vc_exit.vei.vei_data); return (0); } /* * vmx_load_pdptes * * Update the PDPTEs in the VMCS with the values currently indicated by the * guest CR3. This is used for 32-bit PAE guests when enabling paging. * * Parameters * vcpu: The vcpu whose PDPTEs should be loaded * * Return values: * 0: if successful * EINVAL: if the PDPTEs could not be loaded * ENOMEM: memory allocation failure */ int vmx_load_pdptes(struct vcpu *vcpu) { uint64_t cr3, cr3_host_phys; vaddr_t cr3_host_virt; pd_entry_t *pdptes; int ret; if (vmread(VMCS_GUEST_IA32_CR3, &cr3)) { printf("%s: can't read guest cr3\n", __func__); return (EINVAL); } if (!pmap_extract(vcpu->vc_parent->vm_map->pmap, (vaddr_t)cr3, (paddr_t *)&cr3_host_phys)) { DPRINTF("%s: nonmapped guest CR3, setting PDPTEs to 0\n", __func__); if (vmwrite(VMCS_GUEST_PDPTE0, 0)) { printf("%s: can't write guest PDPTE0\n", __func__); return (EINVAL); } if (vmwrite(VMCS_GUEST_PDPTE1, 0)) { printf("%s: can't write guest PDPTE1\n", __func__); return (EINVAL); } if (vmwrite(VMCS_GUEST_PDPTE2, 0)) { printf("%s: can't write guest PDPTE2\n", __func__); return (EINVAL); } if (vmwrite(VMCS_GUEST_PDPTE3, 0)) { printf("%s: can't write guest PDPTE3\n", __func__); return (EINVAL); } return (0); } ret = 0; /* We may sleep during km_alloc(9), so reload VMCS. */ vcpu->vc_last_pcpu = curcpu(); cr3_host_virt = (vaddr_t)km_alloc(PAGE_SIZE, &kv_any, &kp_none, &kd_waitok); if (vcpu_reload_vmcs_vmx(vcpu)) { printf("%s: failed to reload vmcs\n", __func__); ret = EINVAL; goto exit; } if (!cr3_host_virt) { printf("%s: can't allocate address for guest CR3 mapping\n", __func__); return (ENOMEM); } pmap_kenter_pa(cr3_host_virt, cr3_host_phys, PROT_READ); pdptes = (pd_entry_t *)cr3_host_virt; if (vmwrite(VMCS_GUEST_PDPTE0, pdptes[0])) { printf("%s: can't write guest PDPTE0\n", __func__); ret = EINVAL; goto exit; } if (vmwrite(VMCS_GUEST_PDPTE1, pdptes[1])) { printf("%s: can't write guest PDPTE1\n", __func__); ret = EINVAL; goto exit; } if (vmwrite(VMCS_GUEST_PDPTE2, pdptes[2])) { printf("%s: can't write guest PDPTE2\n", __func__); ret = EINVAL; goto exit; } if (vmwrite(VMCS_GUEST_PDPTE3, pdptes[3])) { printf("%s: can't write guest PDPTE3\n", __func__); ret = EINVAL; goto exit; } exit: pmap_kremove(cr3_host_virt, PAGE_SIZE); /* km_free(9) might sleep, so we need to reload VMCS. */ vcpu->vc_last_pcpu = curcpu(); km_free((void *)cr3_host_virt, PAGE_SIZE, &kv_any, &kp_none); if (vcpu_reload_vmcs_vmx(vcpu)) { printf("%s: failed to reload vmcs after km_free\n", __func__); ret = EINVAL; } return (ret); } /* * vmx_handle_cr0_write * * Write handler for CR0. This function ensures valid values are written into * CR0 for the cpu/vmm mode in use (cr0 must-be-0 and must-be-1 bits, etc). * * Parameters * vcpu: The vcpu taking the cr0 write exit * r: The guest's desired (incoming) cr0 value * * Return values: * 0: if successful * EINVAL: if an error occurred */ int vmx_handle_cr0_write(struct vcpu *vcpu, uint64_t r) { struct vmx_msr_store *msr_store; struct vmx_invvpid_descriptor vid; uint64_t ectls, oldcr0, cr4, mask; int ret; /* Check must-be-0 bits */ mask = vcpu->vc_vmx_cr0_fixed1; if (~r & mask) { /* Inject #GP, let the guest handle it */ DPRINTF("%s: guest set invalid bits in %%cr0. Zeros " "mask=0x%llx, data=0x%llx\n", __func__, vcpu->vc_vmx_cr0_fixed1, r); vmm_inject_gp(vcpu); return (0); } /* Check must-be-1 bits */ mask = vcpu->vc_vmx_cr0_fixed0; if ((r & mask) != mask) { /* Inject #GP, let the guest handle it */ DPRINTF("%s: guest set invalid bits in %%cr0. Ones " "mask=0x%llx, data=0x%llx\n", __func__, vcpu->vc_vmx_cr0_fixed0, r); vmm_inject_gp(vcpu); return (0); } if (r & 0xFFFFFFFF00000000ULL) { DPRINTF("%s: setting bits 63:32 of %%cr0 is invalid," " inject #GP, cr0=0x%llx\n", __func__, r); vmm_inject_gp(vcpu); return (0); } if ((r & CR0_PG) && (r & CR0_PE) == 0) { DPRINTF("%s: PG flag set when the PE flag is clear," " inject #GP, cr0=0x%llx\n", __func__, r); vmm_inject_gp(vcpu); return (0); } if ((r & CR0_NW) && (r & CR0_CD) == 0) { DPRINTF("%s: NW flag set when the CD flag is clear," " inject #GP, cr0=0x%llx\n", __func__, r); vmm_inject_gp(vcpu); return (0); } if (vmread(VMCS_GUEST_IA32_CR0, &oldcr0)) { printf("%s: can't read guest cr0\n", __func__); return (EINVAL); } /* CR0 must always have NE set */ r |= CR0_NE; if (vmwrite(VMCS_GUEST_IA32_CR0, r)) { printf("%s: can't write guest cr0\n", __func__); return (EINVAL); } /* If the guest hasn't enabled paging ... */ if (!(r & CR0_PG) && (oldcr0 & CR0_PG)) { /* Paging was disabled (prev. enabled) - Flush TLB */ if (vmm_softc->mode == VMM_MODE_EPT && vcpu->vc_vmx_vpid_enabled) { vid.vid_vpid = vcpu->vc_vpid; vid.vid_addr = 0; invvpid(IA32_VMX_INVVPID_SINGLE_CTX_GLB, &vid); } } else if (!(oldcr0 & CR0_PG) && (r & CR0_PG)) { /* * Since the guest has enabled paging, then the IA32_VMX_IA32E_MODE_GUEST * control must be set to the same as EFER_LME. */ msr_store = (struct vmx_msr_store *)vcpu->vc_vmx_msr_exit_save_va; if (vmread(VMCS_ENTRY_CTLS, &ectls)) { printf("%s: can't read entry controls", __func__); return (EINVAL); } if (msr_store[VCPU_REGS_EFER].vms_data & EFER_LME) ectls |= IA32_VMX_IA32E_MODE_GUEST; else ectls &= ~IA32_VMX_IA32E_MODE_GUEST; if (vmwrite(VMCS_ENTRY_CTLS, ectls)) { printf("%s: can't write entry controls", __func__); return (EINVAL); } if (vmread(VMCS_GUEST_IA32_CR4, &cr4)) { printf("%s: can't read guest cr4\n", __func__); return (EINVAL); } /* Load PDPTEs if PAE guest enabling paging */ if (cr4 & CR4_PAE) { ret = vmx_load_pdptes(vcpu); if (ret) { printf("%s: updating PDPTEs failed\n", __func__); return (ret); } } } return (0); } /* * vmx_handle_cr4_write * * Write handler for CR4. This function ensures valid values are written into * CR4 for the cpu/vmm mode in use (cr4 must-be-0 and must-be-1 bits, etc). * * Parameters * vcpu: The vcpu taking the cr4 write exit * r: The guest's desired (incoming) cr4 value * * Return values: * 0: if successful * EINVAL: if an error occurred */ int vmx_handle_cr4_write(struct vcpu *vcpu, uint64_t r) { uint64_t mask; /* Check must-be-0 bits */ mask = ~(curcpu()->ci_vmm_cap.vcc_vmx.vmx_cr4_fixed1); if (r & mask) { /* Inject #GP, let the guest handle it */ DPRINTF("%s: guest set invalid bits in %%cr4. Zeros " "mask=0x%llx, data=0x%llx\n", __func__, curcpu()->ci_vmm_cap.vcc_vmx.vmx_cr4_fixed1, r); vmm_inject_gp(vcpu); return (0); } /* Check must-be-1 bits */ mask = curcpu()->ci_vmm_cap.vcc_vmx.vmx_cr4_fixed0; if ((r & mask) != mask) { /* Inject #GP, let the guest handle it */ DPRINTF("%s: guest set invalid bits in %%cr4. Ones " "mask=0x%llx, data=0x%llx\n", __func__, curcpu()->ci_vmm_cap.vcc_vmx.vmx_cr4_fixed0, r); vmm_inject_gp(vcpu); return (0); } /* CR4_VMXE must always be enabled */ r |= CR4_VMXE; if (vmwrite(VMCS_GUEST_IA32_CR4, r)) { printf("%s: can't write guest cr4\n", __func__); return (EINVAL); } return (0); } /* * vmx_handle_cr * * Handle reads/writes to control registers (except CR3) */ int vmx_handle_cr(struct vcpu *vcpu) { uint64_t insn_length, exit_qual, r; uint8_t crnum, dir, reg; if (vmread(VMCS_INSTRUCTION_LENGTH, &insn_length)) { printf("%s: can't obtain instruction length\n", __func__); return (EINVAL); } if (vmx_get_exit_qualification(&exit_qual)) { printf("%s: can't get exit qual\n", __func__); return (EINVAL); } /* Low 4 bits of exit_qual represent the CR number */ crnum = exit_qual & 0xf; /* * Bits 5:4 indicate the direction of operation (or special CR-modifying * instruction) */ dir = (exit_qual & 0x30) >> 4; /* Bits 11:8 encode the source/target register */ reg = (exit_qual & 0xf00) >> 8; switch (dir) { case CR_WRITE: if (crnum == 0 || crnum == 4) { switch (reg) { case 0: r = vcpu->vc_gueststate.vg_rax; break; case 1: r = vcpu->vc_gueststate.vg_rcx; break; case 2: r = vcpu->vc_gueststate.vg_rdx; break; case 3: r = vcpu->vc_gueststate.vg_rbx; break; case 4: if (vmread(VMCS_GUEST_IA32_RSP, &r)) { printf("%s: unable to read guest " "RSP\n", __func__); return (EINVAL); } break; case 5: r = vcpu->vc_gueststate.vg_rbp; break; case 6: r = vcpu->vc_gueststate.vg_rsi; break; case 7: r = vcpu->vc_gueststate.vg_rdi; break; case 8: r = vcpu->vc_gueststate.vg_r8; break; case 9: r = vcpu->vc_gueststate.vg_r9; break; case 10: r = vcpu->vc_gueststate.vg_r10; break; case 11: r = vcpu->vc_gueststate.vg_r11; break; case 12: r = vcpu->vc_gueststate.vg_r12; break; case 13: r = vcpu->vc_gueststate.vg_r13; break; case 14: r = vcpu->vc_gueststate.vg_r14; break; case 15: r = vcpu->vc_gueststate.vg_r15; break; } DPRINTF("%s: mov to cr%d @ %llx, data=0x%llx\n", __func__, crnum, vcpu->vc_gueststate.vg_rip, r); } if (crnum == 0) vmx_handle_cr0_write(vcpu, r); if (crnum == 4) vmx_handle_cr4_write(vcpu, r); break; case CR_READ: DPRINTF("%s: mov from cr%d @ %llx\n", __func__, crnum, vcpu->vc_gueststate.vg_rip); break; case CR_CLTS: DPRINTF("%s: clts instruction @ %llx\n", __func__, vcpu->vc_gueststate.vg_rip); break; case CR_LMSW: DPRINTF("%s: lmsw instruction @ %llx\n", __func__, vcpu->vc_gueststate.vg_rip); break; default: DPRINTF("%s: unknown cr access @ %llx\n", __func__, vcpu->vc_gueststate.vg_rip); } vcpu->vc_gueststate.vg_rip += insn_length; return (0); } /* * vmx_handle_rdmsr * * Handler for rdmsr instructions. Bitmap MSRs are allowed implicit access * and won't end up here. This handler is primarily intended to catch otherwise * unknown MSR access for possible later inclusion in the bitmap list. For * each MSR access that ends up here, we log the access (when VMM_DEBUG is * enabled) * * Parameters: * vcpu: vcpu structure containing instruction info causing the exit * * Return value: * 0: The operation was successful * EINVAL: An error occurred */ int vmx_handle_rdmsr(struct vcpu *vcpu) { uint64_t insn_length; uint64_t *rax, *rdx; uint64_t *rcx; int ret; if (vmread(VMCS_INSTRUCTION_LENGTH, &insn_length)) { printf("%s: can't obtain instruction length\n", __func__); return (EINVAL); } if (insn_length != 2) { DPRINTF("%s: RDMSR with instruction length %lld not " "supported\n", __func__, insn_length); return (EINVAL); } rax = &vcpu->vc_gueststate.vg_rax; rcx = &vcpu->vc_gueststate.vg_rcx; rdx = &vcpu->vc_gueststate.vg_rdx; switch (*rcx) { case MSR_BIOS_SIGN: case MSR_PLATFORM_ID: /* Ignored */ *rax = 0; *rdx = 0; break; case MSR_CR_PAT: *rax = (vcpu->vc_shadow_pat & 0xFFFFFFFFULL); *rdx = (vcpu->vc_shadow_pat >> 32); break; default: /* Unsupported MSRs causes #GP exception, don't advance %rip */ DPRINTF("%s: unsupported rdmsr (msr=0x%llx), injecting #GP\n", __func__, *rcx); ret = vmm_inject_gp(vcpu); return (ret); } vcpu->vc_gueststate.vg_rip += insn_length; return (0); } /* * vmx_handle_xsetbv * * VMX-specific part of the xsetbv instruction exit handler * * Parameters: * vcpu: vcpu structure containing instruction info causing the exit * * Return value: * 0: The operation was successful * EINVAL: An error occurred */ int vmx_handle_xsetbv(struct vcpu *vcpu) { uint64_t insn_length, *rax; int ret; if (vmread(VMCS_INSTRUCTION_LENGTH, &insn_length)) { printf("%s: can't obtain instruction length\n", __func__); return (EINVAL); } /* All XSETBV instructions are 3 bytes */ if (insn_length != 3) { DPRINTF("%s: XSETBV with instruction length %lld not " "supported\n", __func__, insn_length); return (EINVAL); } rax = &vcpu->vc_gueststate.vg_rax; ret = vmm_handle_xsetbv(vcpu, rax); vcpu->vc_gueststate.vg_rip += insn_length; return ret; } /* * svm_handle_xsetbv * * SVM-specific part of the xsetbv instruction exit handler * * Parameters: * vcpu: vcpu structure containing instruction info causing the exit * * Return value: * 0: The operation was successful * EINVAL: An error occurred */ int svm_handle_xsetbv(struct vcpu *vcpu) { uint64_t insn_length, *rax; int ret; struct vmcb *vmcb = (struct vmcb *)vcpu->vc_control_va; /* All XSETBV instructions are 3 bytes */ insn_length = 3; rax = &vmcb->v_rax; ret = vmm_handle_xsetbv(vcpu, rax); vcpu->vc_gueststate.vg_rip += insn_length; return ret; } /* * vmm_handle_xsetbv * * Handler for xsetbv instructions. We allow the guest VM to set xcr0 values * limited to the xsave_mask in use in the host. * * Parameters: * vcpu: vcpu structure containing instruction info causing the exit * rax: pointer to guest %rax * * Return value: * 0: The operation was successful * EINVAL: An error occurred */ int vmm_handle_xsetbv(struct vcpu *vcpu, uint64_t *rax) { uint64_t *rdx, *rcx, val; rcx = &vcpu->vc_gueststate.vg_rcx; rdx = &vcpu->vc_gueststate.vg_rdx; if (vmm_get_guest_cpu_cpl(vcpu) != 0) { DPRINTF("%s: guest cpl not zero\n", __func__); return (vmm_inject_gp(vcpu)); } if (*rcx != 0) { DPRINTF("%s: guest specified invalid xcr register number " "%lld\n", __func__, *rcx); return (vmm_inject_gp(vcpu)); } val = *rax + (*rdx << 32); if (val & ~xsave_mask) { DPRINTF("%s: guest specified xcr0 outside xsave_mask %lld\n", __func__, val); return (vmm_inject_gp(vcpu)); } vcpu->vc_gueststate.vg_xcr0 = val; return (0); } /* * vmx_handle_misc_enable_msr * * Handler for writes to the MSR_MISC_ENABLE (0x1a0) MSR on Intel CPUs. We * limit what the guest can write to this MSR (certain hardware-related * settings like speedstep, etc). * * Parameters: * vcpu: vcpu structure containing information about the wrmsr causing this * exit */ void vmx_handle_misc_enable_msr(struct vcpu *vcpu) { uint64_t *rax, *rdx; struct vmx_msr_store *msr_store; rax = &vcpu->vc_gueststate.vg_rax; rdx = &vcpu->vc_gueststate.vg_rdx; msr_store = (struct vmx_msr_store *)vcpu->vc_vmx_msr_exit_save_va; /* Filter out guest writes to TCC, EIST, and xTPR */ *rax &= ~(MISC_ENABLE_TCC | MISC_ENABLE_EIST_ENABLED | MISC_ENABLE_xTPR_MESSAGE_DISABLE); msr_store[VCPU_REGS_MISC_ENABLE].vms_data = *rax | (*rdx << 32); } /* * vmx_handle_wrmsr * * Handler for wrmsr instructions. This handler logs the access, and discards * the written data (when VMM_DEBUG is enabled). Any valid wrmsr will not end * up here (it will be whitelisted in the MSR bitmap). * * Parameters: * vcpu: vcpu structure containing instruction info causing the exit * * Return value: * 0: The operation was successful * EINVAL: An error occurred */ int vmx_handle_wrmsr(struct vcpu *vcpu) { uint64_t insn_length, val; uint64_t *rax, *rdx, *rcx; int ret; if (vmread(VMCS_INSTRUCTION_LENGTH, &insn_length)) { printf("%s: can't obtain instruction length\n", __func__); return (EINVAL); } if (insn_length != 2) { DPRINTF("%s: WRMSR with instruction length %lld not " "supported\n", __func__, insn_length); return (EINVAL); } rax = &vcpu->vc_gueststate.vg_rax; rcx = &vcpu->vc_gueststate.vg_rcx; rdx = &vcpu->vc_gueststate.vg_rdx; val = (*rdx << 32) | (*rax & 0xFFFFFFFFULL); switch (*rcx) { case MSR_CR_PAT: if (!vmm_pat_is_valid(val)) { ret = vmm_inject_gp(vcpu); return (ret); } vcpu->vc_shadow_pat = val; break; case MSR_MISC_ENABLE: vmx_handle_misc_enable_msr(vcpu); break; case MSR_SMM_MONITOR_CTL: /* * 34.15.5 - Enabling dual monitor treatment * * Unsupported, so inject #GP and return without * advancing %rip. */ ret = vmm_inject_gp(vcpu); return (ret); case KVM_MSR_SYSTEM_TIME: vmm_init_pvclock(vcpu, (*rax & 0xFFFFFFFFULL) | (*rdx << 32)); break; #ifdef VMM_DEBUG default: /* * Log the access, to be able to identify unknown MSRs */ DPRINTF("%s: wrmsr exit, msr=0x%llx, discarding data " "written from guest=0x%llx:0x%llx\n", __func__, *rcx, *rdx, *rax); #endif /* VMM_DEBUG */ } vcpu->vc_gueststate.vg_rip += insn_length; return (0); } /* * svm_handle_msr * * Handler for MSR instructions. * * Parameters: * vcpu: vcpu structure containing instruction info causing the exit * * Return value: * Always 0 (successful) */ int svm_handle_msr(struct vcpu *vcpu) { uint64_t insn_length, val; uint64_t *rax, *rcx, *rdx; struct vmcb *vmcb = (struct vmcb *)vcpu->vc_control_va; int ret; /* XXX: Validate RDMSR / WRMSR insn_length */ insn_length = 2; rax = &vmcb->v_rax; rcx = &vcpu->vc_gueststate.vg_rcx; rdx = &vcpu->vc_gueststate.vg_rdx; if (vmcb->v_exitinfo1 == 1) { /* WRMSR */ val = (*rdx << 32) | (*rax & 0xFFFFFFFFULL); switch (*rcx) { case MSR_CR_PAT: if (!vmm_pat_is_valid(val)) { ret = vmm_inject_gp(vcpu); return (ret); } vcpu->vc_shadow_pat = val; break; case MSR_EFER: vmcb->v_efer = *rax | EFER_SVME; break; case KVM_MSR_SYSTEM_TIME: vmm_init_pvclock(vcpu, (*rax & 0xFFFFFFFFULL) | (*rdx << 32)); break; default: /* Log the access, to be able to identify unknown MSRs */ DPRINTF("%s: wrmsr exit, msr=0x%llx, discarding data " "written from guest=0x%llx:0x%llx\n", __func__, *rcx, *rdx, *rax); } } else { /* RDMSR */ switch (*rcx) { case MSR_BIOS_SIGN: case MSR_INT_PEN_MSG: case MSR_PLATFORM_ID: /* Ignored */ *rax = 0; *rdx = 0; break; case MSR_CR_PAT: *rax = (vcpu->vc_shadow_pat & 0xFFFFFFFFULL); *rdx = (vcpu->vc_shadow_pat >> 32); break; case MSR_DE_CFG: /* LFENCE serializing bit is set by host */ *rax = DE_CFG_SERIALIZE_LFENCE; *rdx = 0; break; default: /* * Unsupported MSRs causes #GP exception, don't advance * %rip */ DPRINTF("%s: unsupported rdmsr (msr=0x%llx), " "injecting #GP\n", __func__, *rcx); ret = vmm_inject_gp(vcpu); return (ret); } } vcpu->vc_gueststate.vg_rip += insn_length; return (0); } /* Handle cpuid(0xd) and its subleafs */ static void vmm_handle_cpuid_0xd(struct vcpu *vcpu, uint32_t subleaf, uint64_t *rax, uint32_t eax, uint32_t ebx, uint32_t ecx, uint32_t edx) { if (subleaf == 0) { /* * CPUID(0xd.0) depends on the value in XCR0 and MSR_XSS. If * the guest XCR0 isn't the same as the host then set it, redo * the CPUID, and restore it. */ uint64_t xcr0 = vcpu->vc_gueststate.vg_xcr0; /* * "ecx enumerates the size required ... for an area * containing all the ... components supported by this * processor" * "ebx enumerates the size required ... for an area * containing all the ... components corresponding to bits * currently set in xcr0" * So: since the VMM 'processor' is what our base kernel uses, * the VMM ecx is our ebx */ ecx = ebx; if (xcr0 != (xsave_mask & XFEATURE_XCR0_MASK)) { uint32_t dummy; xsetbv(0, xcr0); CPUID_LEAF(0xd, subleaf, eax, ebx, dummy, edx); xsetbv(0, xsave_mask & XFEATURE_XCR0_MASK); } eax = xsave_mask & XFEATURE_XCR0_MASK; edx = (xsave_mask & XFEATURE_XCR0_MASK) >> 32; } else if (subleaf == 1) { /* mask out XSAVEC, XSAVES, and XFD support */ eax &= XSAVE_XSAVEOPT | XSAVE_XGETBV1; ebx = 0; /* no xsavec or xsaves for now */ ecx = edx = 0; /* no xsaves for now */ } else if (subleaf >= 63 || ((1ULL << subleaf) & xsave_mask & XFEATURE_XCR0_MASK) == 0) { /* disclaim subleaves of features we don't expose */ eax = ebx = ecx = edx = 0; } else { /* disclaim compressed alignment or xfd support */ ecx = 0; } *rax = eax; vcpu->vc_gueststate.vg_rbx = ebx; vcpu->vc_gueststate.vg_rcx = ecx; vcpu->vc_gueststate.vg_rdx = edx; } /* * vmm_handle_cpuid * * Exit handler for CPUID instruction * * Parameters: * vcpu: vcpu causing the CPUID exit * * Return value: * 0: the exit was processed successfully * EINVAL: error occurred validating the CPUID instruction arguments */ int vmm_handle_cpuid(struct vcpu *vcpu) { uint64_t insn_length, cr4; uint64_t *rax, *rbx, *rcx, *rdx; struct vmcb *vmcb; uint32_t leaf, subleaf, eax, ebx, ecx, edx; struct vmx_msr_store *msr_store; int vmm_cpuid_level; /* what's the cpuid level we support/advertise? */ vmm_cpuid_level = cpuid_level; if (vmm_cpuid_level < 0x15 && tsc_is_invariant) vmm_cpuid_level = 0x15; if (vmm_softc->mode == VMM_MODE_EPT) { if (vmread(VMCS_INSTRUCTION_LENGTH, &insn_length)) { DPRINTF("%s: can't obtain instruction length\n", __func__); return (EINVAL); } if (vmread(VMCS_GUEST_IA32_CR4, &cr4)) { DPRINTF("%s: can't obtain cr4\n", __func__); return (EINVAL); } rax = &vcpu->vc_gueststate.vg_rax; /* * "CPUID leaves above 02H and below 80000000H are only * visible when IA32_MISC_ENABLE MSR has bit 22 set to its * default value 0" */ msr_store = (struct vmx_msr_store *)vcpu->vc_vmx_msr_exit_save_va; if (msr_store[VCPU_REGS_MISC_ENABLE].vms_data & MISC_ENABLE_LIMIT_CPUID_MAXVAL) vmm_cpuid_level = 0x02; } else { /* XXX: validate insn_length 2 */ insn_length = 2; vmcb = (struct vmcb *)vcpu->vc_control_va; rax = &vmcb->v_rax; cr4 = vmcb->v_cr4; } rbx = &vcpu->vc_gueststate.vg_rbx; rcx = &vcpu->vc_gueststate.vg_rcx; rdx = &vcpu->vc_gueststate.vg_rdx; vcpu->vc_gueststate.vg_rip += insn_length; leaf = *rax; subleaf = *rcx; /* * "If a value entered for CPUID.EAX is higher than the maximum input * value for basic or extended function for that processor then the * data for the highest basic information leaf is returned." * * "When CPUID returns the highest basic leaf information as a result * of an invalid input EAX value, any dependence on input ECX value * in the basic leaf is honored." * * This means if leaf is between vmm_cpuid_level and 0x40000000 (the start * of the hypervisor info leaves), clamp to vmm_cpuid_level, but without * altering subleaf. Also, if leaf is greater than the extended function * info, clamp also to vmm_cpuid_level. */ if ((leaf > vmm_cpuid_level && leaf < 0x40000000) || (leaf > curcpu()->ci_pnfeatset)) { DPRINTF("%s: invalid cpuid input leaf 0x%x, guest rip=" "0x%llx - resetting to 0x%x\n", __func__, leaf, vcpu->vc_gueststate.vg_rip - insn_length, vmm_cpuid_level); leaf = vmm_cpuid_level; } /* we fake up values in the range (cpuid_level, vmm_cpuid_level] */ if (leaf <= cpuid_level || leaf > 0x80000000) CPUID_LEAF(leaf, subleaf, eax, ebx, ecx, edx); else eax = ebx = ecx = edx = 0; switch (leaf) { case 0x00: /* Max level and vendor ID */ *rax = vmm_cpuid_level; *rbx = *((uint32_t *)&cpu_vendor); *rdx = *((uint32_t *)&cpu_vendor + 1); *rcx = *((uint32_t *)&cpu_vendor + 2); break; case 0x01: /* Version, brand, feature info */ *rax = cpu_id; /* mask off host's APIC ID, reset to vcpu id */ *rbx = cpu_ebxfeature & 0x0000FFFF; *rbx |= (vcpu->vc_id & 0xFF) << 24; *rcx = (cpu_ecxfeature | CPUIDECX_HV) & VMM_CPUIDECX_MASK; /* Guest CR4.OSXSAVE determines presence of CPUIDECX_OSXSAVE */ if (cr4 & CR4_OSXSAVE) *rcx |= CPUIDECX_OSXSAVE; else *rcx &= ~CPUIDECX_OSXSAVE; *rdx = curcpu()->ci_feature_flags & VMM_CPUIDEDX_MASK; break; case 0x02: /* Cache and TLB information */ *rax = eax; *rbx = ebx; *rcx = ecx; *rdx = edx; break; case 0x03: /* Processor serial number (not supported) */ DPRINTF("%s: function 0x03 (processor serial number) not " "supported\n", __func__); *rax = 0; *rbx = 0; *rcx = 0; *rdx = 0; break; case 0x04: /* Deterministic cache info */ *rax = eax & VMM_CPUID4_CACHE_TOPOLOGY_MASK; *rbx = ebx; *rcx = ecx; *rdx = edx; break; case 0x05: /* MONITOR/MWAIT (not supported) */ DPRINTF("%s: function 0x05 (monitor/mwait) not supported\n", __func__); *rax = 0; *rbx = 0; *rcx = 0; *rdx = 0; break; case 0x06: /* Thermal / Power management (not supported) */ DPRINTF("%s: function 0x06 (thermal/power mgt) not supported\n", __func__); *rax = 0; *rbx = 0; *rcx = 0; *rdx = 0; break; case 0x07: /* SEFF */ if (subleaf == 0) { *rax = 0; /* Highest subleaf supported */ *rbx = curcpu()->ci_feature_sefflags_ebx & VMM_SEFF0EBX_MASK; *rcx = curcpu()->ci_feature_sefflags_ecx & VMM_SEFF0ECX_MASK; *rdx = curcpu()->ci_feature_sefflags_edx & VMM_SEFF0EDX_MASK; /* * Only expose PKU support if we've detected it in use * on the host. */ if (vmm_softc->sc_md.pkru_enabled) *rcx |= SEFF0ECX_PKU; else *rcx &= ~SEFF0ECX_PKU; /* Expose IBT bit if we've enabled CET on the host. */ if (rcr4() & CR4_CET) *rdx |= SEFF0EDX_IBT; else *rdx &= ~SEFF0EDX_IBT; } else { /* Unsupported subleaf */ DPRINTF("%s: function 0x07 (SEFF) unsupported subleaf " "0x%x not supported\n", __func__, subleaf); *rax = 0; *rbx = 0; *rcx = 0; *rdx = 0; } break; case 0x09: /* Direct Cache Access (not supported) */ DPRINTF("%s: function 0x09 (direct cache access) not " "supported\n", __func__); *rax = 0; *rbx = 0; *rcx = 0; *rdx = 0; break; case 0x0a: /* Architectural perf monitoring (not supported) */ DPRINTF("%s: function 0x0a (arch. perf mon) not supported\n", __func__); *rax = 0; *rbx = 0; *rcx = 0; *rdx = 0; break; case 0x0b: /* Extended topology enumeration (not supported) */ DPRINTF("%s: function 0x0b (topology enumeration) not " "supported\n", __func__); *rax = 0; *rbx = 0; *rcx = 0; *rdx = 0; break; case 0x0d: /* Processor ext. state information */ vmm_handle_cpuid_0xd(vcpu, subleaf, rax, eax, ebx, ecx, edx); break; case 0x0f: /* QoS info (not supported) */ DPRINTF("%s: function 0x0f (QoS info) not supported\n", __func__); *rax = 0; *rbx = 0; *rcx = 0; *rdx = 0; break; case 0x14: /* Processor Trace info (not supported) */ DPRINTF("%s: function 0x14 (processor trace info) not " "supported\n", __func__); *rax = 0; *rbx = 0; *rcx = 0; *rdx = 0; break; case 0x15: if (cpuid_level >= 0x15) { *rax = eax; *rbx = ebx; *rcx = ecx; *rdx = edx; } else { KASSERT(tsc_is_invariant); *rax = 1; *rbx = 100; *rcx = tsc_frequency / 100; *rdx = 0; } break; case 0x16: /* Processor frequency info */ *rax = eax; *rbx = ebx; *rcx = ecx; *rdx = edx; break; case 0x40000000: /* Hypervisor information */ *rax = 0; *rbx = *((uint32_t *)&vmm_hv_signature[0]); *rcx = *((uint32_t *)&vmm_hv_signature[4]); *rdx = *((uint32_t *)&vmm_hv_signature[8]); break; case 0x40000001: /* KVM hypervisor features */ *rax = (1 << KVM_FEATURE_CLOCKSOURCE2) | (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT); *rbx = 0; *rcx = 0; *rdx = 0; break; case 0x80000000: /* Extended function level */ *rax = 0x80000008; /* curcpu()->ci_pnfeatset */ *rbx = 0; *rcx = 0; *rdx = 0; break; case 0x80000001: /* Extended function info */ *rax = curcpu()->ci_efeature_eax; *rbx = 0; /* Reserved */ *rcx = curcpu()->ci_efeature_ecx & VMM_ECPUIDECX_MASK; *rdx = curcpu()->ci_feature_eflags & VMM_FEAT_EFLAGS_MASK; break; case 0x80000002: /* Brand string */ *rax = curcpu()->ci_brand[0]; *rbx = curcpu()->ci_brand[1]; *rcx = curcpu()->ci_brand[2]; *rdx = curcpu()->ci_brand[3]; break; case 0x80000003: /* Brand string */ *rax = curcpu()->ci_brand[4]; *rbx = curcpu()->ci_brand[5]; *rcx = curcpu()->ci_brand[6]; *rdx = curcpu()->ci_brand[7]; break; case 0x80000004: /* Brand string */ *rax = curcpu()->ci_brand[8]; *rbx = curcpu()->ci_brand[9]; *rcx = curcpu()->ci_brand[10]; *rdx = curcpu()->ci_brand[11]; break; case 0x80000005: /* Reserved (Intel), cacheinfo (AMD) */ *rax = eax; *rbx = ebx; *rcx = ecx; *rdx = edx; break; case 0x80000006: /* ext. cache info */ *rax = eax; *rbx = ebx; *rcx = ecx; *rdx = edx; break; case 0x80000007: /* apmi */ *rax = eax; *rbx = ebx; *rcx = ecx; *rdx = edx & VMM_APMI_EDX_INCLUDE_MASK; break; case 0x80000008: /* Phys bits info and topology (AMD) */ *rax = eax; *rbx = ebx & VMM_AMDSPEC_EBX_MASK; /* Reset %rcx (topology) */ *rcx = 0; *rdx = edx; break; case 0x8000001d: /* cache topology (AMD) */ *rax = eax; *rbx = ebx; *rcx = ecx; *rdx = edx; break; default: DPRINTF("%s: unsupported rax=0x%llx\n", __func__, *rax); *rax = 0; *rbx = 0; *rcx = 0; *rdx = 0; } if (vmm_softc->mode == VMM_MODE_RVI) { /* * update %rax. the rest of the registers get updated in * svm_enter_guest */ vmcb->v_rax = *rax; } return (0); } /* * vcpu_run_svm * * SVM main loop used to run a VCPU. * * Parameters: * vcpu: The VCPU to run * vrp: run parameters * * Return values: * 0: The run loop exited and no help is needed from vmd * EAGAIN: The run loop exited and help from vmd is needed * EINVAL: an error occurred */ int vcpu_run_svm(struct vcpu *vcpu, struct vm_run_params *vrp) { int ret = 0; struct region_descriptor gdt; struct cpu_info *ci = NULL; uint64_t exit_reason; struct schedstate_percpu *spc; struct vmcb *vmcb = (struct vmcb *)vcpu->vc_control_va; if (vrp->vrp_intr_pending) vcpu->vc_intr = 1; else vcpu->vc_intr = 0; /* * If we are returning from userspace (vmd) because we exited * last time, fix up any needed vcpu state first. Which state * needs to be fixed up depends on what vmd populated in the * exit data structure. */ switch (vcpu->vc_gueststate.vg_exit_reason) { case SVM_VMEXIT_IOIO: if (vcpu->vc_exit.vei.vei_dir == VEI_DIR_IN) { vcpu->vc_gueststate.vg_rax = vcpu->vc_exit.vei.vei_data; vmcb->v_rax = vcpu->vc_gueststate.vg_rax; } vcpu->vc_gueststate.vg_rip = vcpu->vc_exit.vrs.vrs_gprs[VCPU_REGS_RIP]; vmcb->v_rip = vcpu->vc_gueststate.vg_rip; break; case SVM_VMEXIT_NPF: ret = vcpu_writeregs_svm(vcpu, VM_RWREGS_GPRS, &vcpu->vc_exit.vrs); if (ret) { printf("%s: vm %d vcpu %d failed to update " "registers\n", __func__, vcpu->vc_parent->vm_id, vcpu->vc_id); return (EINVAL); } break; } memset(&vcpu->vc_exit, 0, sizeof(vcpu->vc_exit)); while (ret == 0) { vmm_update_pvclock(vcpu); if (ci != curcpu()) { /* * We are launching for the first time, or we are * resuming from a different pcpu, so we need to * reset certain pcpu-specific values. */ ci = curcpu(); setregion(&gdt, ci->ci_gdt, GDT_SIZE - 1); if (ci != vcpu->vc_last_pcpu) { /* * Flush TLB by guest ASID if feature * available, flush entire TLB if not. */ if (ci->ci_vmm_cap.vcc_svm.svm_flush_by_asid) vmcb->v_tlb_control = SVM_TLB_CONTROL_FLUSH_ASID; else vmcb->v_tlb_control = SVM_TLB_CONTROL_FLUSH_ALL; svm_set_dirty(vcpu, SVM_CLEANBITS_ALL); } vcpu->vc_last_pcpu = ci; if (gdt.rd_base == 0) { ret = EINVAL; break; } } /* Handle vmd(8) injected interrupts */ /* Is there an interrupt pending injection? */ if (vcpu->vc_inject.vie_type == VCPU_INJECT_INTR && vcpu->vc_irqready) { vmcb->v_eventinj = vcpu->vc_inject.vie_vector | (1U << 31); vcpu->vc_inject.vie_type = VCPU_INJECT_NONE; } /* Inject event if present */ if (vcpu->vc_inject.vie_type == VCPU_INJECT_EX) { vmcb->v_eventinj = vcpu->vc_inject.vie_vector; /* Set the "Event Valid" flag for certain vectors */ switch (vcpu->vc_inject.vie_vector) { case VMM_EX_BP: case VMM_EX_OF: case VMM_EX_DB: /* * Software exception. * XXX check nRIP support. */ vmcb->v_eventinj |= (4ULL << 8); break; case VMM_EX_AC: vcpu->vc_inject.vie_errorcode = 0; /* fallthrough */ case VMM_EX_DF: case VMM_EX_TS: case VMM_EX_NP: case VMM_EX_SS: case VMM_EX_GP: case VMM_EX_PF: /* Hardware exception. */ vmcb->v_eventinj |= (3ULL << 8); if (vmcb->v_cr0 & CR0_PE) { /* Error code valid. */ vmcb->v_eventinj |= (1ULL << 11); vmcb->v_eventinj |= (uint64_t) vcpu->vc_inject.vie_errorcode << 32; } break; default: printf("%s: unsupported exception vector %u\n", __func__, vcpu->vc_inject.vie_vector); ret = EINVAL; } /* switch */ if (ret == EINVAL) break; /* Event is valid. */ vmcb->v_eventinj |= (1U << 31); vcpu->vc_inject.vie_type = VCPU_INJECT_NONE; } TRACEPOINT(vmm, guest_enter, vcpu, vrp); /* Start / resume the VCPU */ /* Disable interrupts and save the current host FPU state. */ clgi(); if ((ret = vmm_fpurestore(vcpu))) { stgi(); break; } /* * If we're resuming to a different VCPU and have IBPB, * then use it to prevent cross-VM branch-target injection. */ if (ci->ci_guest_vcpu != vcpu && (ci->ci_feature_amdspec_ebx & CPUIDEBX_IBPB)) { wrmsr(MSR_PRED_CMD, PRED_CMD_IBPB); ci->ci_guest_vcpu = vcpu; } /* Restore any guest PKRU state. */ if (vmm_softc->sc_md.pkru_enabled) wrpkru(0, vcpu->vc_pkru); KASSERT(vmcb->v_intercept1 & SVM_INTERCEPT_INTR); wrmsr(MSR_AMD_VM_HSAVE_PA, vcpu->vc_svm_hsa_pa); ret = svm_enter_guest(vcpu->vc_control_pa, &vcpu->vc_gueststate, &gdt); /* Restore host PKRU state. */ if (vmm_softc->sc_md.pkru_enabled) { vcpu->vc_pkru = rdpkru(0); wrpkru(0, PGK_VALUE); } /* * On exit, interrupts are disabled, and we are running with * the guest FPU state still possibly on the CPU. Save the FPU * state before re-enabling interrupts. */ vmm_fpusave(vcpu); /* * Enable interrupts now. Note that if the exit was due to INTR * (external interrupt), the interrupt will be processed now. */ stgi(); vcpu->vc_gueststate.vg_rip = vmcb->v_rip; vmcb->v_tlb_control = SVM_TLB_CONTROL_FLUSH_NONE; svm_set_clean(vcpu, SVM_CLEANBITS_ALL); /* If we exited successfully ... */ if (ret == 0) { exit_reason = vmcb->v_exitcode; vcpu->vc_gueststate.vg_exit_reason = exit_reason; TRACEPOINT(vmm, guest_exit, vcpu, vrp, exit_reason); vcpu->vc_gueststate.vg_rflags = vmcb->v_rflags; /* * Handle the exit. This will alter "ret" to EAGAIN if * the exit handler determines help from vmd is needed. */ ret = svm_handle_exit(vcpu); if (vcpu->vc_gueststate.vg_rflags & PSL_I) vcpu->vc_irqready = 1; else vcpu->vc_irqready = 0; /* * If not ready for interrupts, but interrupts pending, * enable interrupt window exiting. */ if (vcpu->vc_irqready == 0 && vcpu->vc_intr) { vmcb->v_intercept1 |= SVM_INTERCEPT_VINTR; vmcb->v_irq = 1; vmcb->v_intr_misc = SVM_INTR_MISC_V_IGN_TPR; vmcb->v_intr_vector = 0; svm_set_dirty(vcpu, SVM_CLEANBITS_TPR | SVM_CLEANBITS_I); } /* * Exit to vmd if we are terminating, failed to enter, * or need help (device I/O) */ if (ret || vcpu_must_stop(vcpu)) break; if (vcpu->vc_intr && vcpu->vc_irqready) { ret = EAGAIN; break; } /* Check if we should yield - don't hog the cpu */ spc = &ci->ci_schedstate; if (spc->spc_schedflags & SPCF_SHOULDYIELD) break; } } /* * We are heading back to userspace (vmd), either because we need help * handling an exit, a guest interrupt is pending, or we failed in some * way to enter the guest. Copy the guest registers to the exit struct * and return to vmd. */ if (vcpu_readregs_svm(vcpu, VM_RWREGS_ALL, &vcpu->vc_exit.vrs)) ret = EINVAL; return (ret); } /* * vmm_alloc_vpid * * Sets the memory location pointed to by "vpid" to the next available VPID * or ASID. * * Parameters: * vpid: Pointer to location to receive the next VPID/ASID * * Return Values: * 0: The operation completed successfully * ENOMEM: No VPIDs/ASIDs were available. Content of 'vpid' is unchanged. */ int vmm_alloc_vpid(uint16_t *vpid) { uint16_t i; uint8_t idx, bit; struct vmm_softc *sc = vmm_softc; rw_enter_write(&vmm_softc->vpid_lock); for (i = 1; i <= sc->max_vpid; i++) { idx = i / 8; bit = i - (idx * 8); if (!(sc->vpids[idx] & (1 << bit))) { sc->vpids[idx] |= (1 << bit); *vpid = i; DPRINTF("%s: allocated VPID/ASID %d\n", __func__, i); rw_exit_write(&vmm_softc->vpid_lock); return 0; } } printf("%s: no available %ss\n", __func__, (sc->mode == VMM_MODE_EPT) ? "VPID" : "ASID"); rw_exit_write(&vmm_softc->vpid_lock); return ENOMEM; } /* * vmm_free_vpid * * Frees the VPID/ASID id supplied in "vpid". * * Parameters: * vpid: VPID/ASID to free. */ void vmm_free_vpid(uint16_t vpid) { uint8_t idx, bit; struct vmm_softc *sc = vmm_softc; rw_enter_write(&vmm_softc->vpid_lock); idx = vpid / 8; bit = vpid - (idx * 8); sc->vpids[idx] &= ~(1 << bit); DPRINTF("%s: freed VPID/ASID %d\n", __func__, vpid); rw_exit_write(&vmm_softc->vpid_lock); } /* vmm_gpa_is_valid * * Check if the given gpa is within guest memory space. * * Parameters: * vcpu: The virtual cpu we are running on. * gpa: The address to check. * obj_size: The size of the object assigned to gpa * * Return values: * 1: gpa is within the memory ranges allocated for the vcpu * 0: otherwise */ int vmm_gpa_is_valid(struct vcpu *vcpu, paddr_t gpa, size_t obj_size) { struct vm *vm = vcpu->vc_parent; struct vm_mem_range *vmr; size_t i; for (i = 0; i < vm->vm_nmemranges; ++i) { vmr = &vm->vm_memranges[i]; if (vmr->vmr_size >= obj_size && vmr->vmr_gpa <= gpa && gpa < (vmr->vmr_gpa + vmr->vmr_size - obj_size)) { return 1; } } return 0; } void vmm_init_pvclock(struct vcpu *vcpu, paddr_t gpa) { paddr_t pvclock_gpa = gpa & 0xFFFFFFFFFFFFFFF0; if (!vmm_gpa_is_valid(vcpu, pvclock_gpa, sizeof(struct pvclock_time_info))) { /* XXX: Kill guest? */ vmm_inject_gp(vcpu); return; } /* XXX: handle case when this struct goes over page boundaries */ if ((pvclock_gpa & PAGE_MASK) + sizeof(struct pvclock_time_info) > PAGE_SIZE) { vmm_inject_gp(vcpu); return; } vcpu->vc_pvclock_system_gpa = gpa; if (tsc_frequency > 0) vcpu->vc_pvclock_system_tsc_mul = (int) ((1000000000L << 20) / tsc_frequency); else vcpu->vc_pvclock_system_tsc_mul = 0; vmm_update_pvclock(vcpu); } int vmm_update_pvclock(struct vcpu *vcpu) { struct pvclock_time_info *pvclock_ti; struct timespec tv; struct vm *vm = vcpu->vc_parent; paddr_t pvclock_hpa, pvclock_gpa; if (vcpu->vc_pvclock_system_gpa & PVCLOCK_SYSTEM_TIME_ENABLE) { pvclock_gpa = vcpu->vc_pvclock_system_gpa & 0xFFFFFFFFFFFFFFF0; if (!pmap_extract(vm->vm_map->pmap, pvclock_gpa, &pvclock_hpa)) return (EINVAL); pvclock_ti = (void*) PMAP_DIRECT_MAP(pvclock_hpa); /* START next cycle (must be odd) */ pvclock_ti->ti_version = (++vcpu->vc_pvclock_version << 1) | 0x1; pvclock_ti->ti_tsc_timestamp = rdtsc(); nanotime(&tv); pvclock_ti->ti_system_time = tv.tv_sec * 1000000000L + tv.tv_nsec; pvclock_ti->ti_tsc_shift = 12; pvclock_ti->ti_tsc_to_system_mul = vcpu->vc_pvclock_system_tsc_mul; pvclock_ti->ti_flags = PVCLOCK_FLAG_TSC_STABLE; /* END (must be even) */ pvclock_ti->ti_version &= ~0x1; } return (0); } int vmm_pat_is_valid(uint64_t pat) { int i; uint8_t *byte = (uint8_t *)&pat; /* Intel SDM Vol 3A, 11.12.2: 0x02, 0x03, and 0x08-0xFF result in #GP */ for (i = 0; i < 8; i++) { if (byte[i] == 0x02 || byte[i] == 0x03 || byte[i] > 0x07) { DPRINTF("%s: invalid pat %llx\n", __func__, pat); return 0; } } return 1; } /* * vmx_exit_reason_decode * * Returns a human readable string describing exit type 'code' */ const char * vmx_exit_reason_decode(uint32_t code) { switch (code) { case VMX_EXIT_NMI: return "NMI"; case VMX_EXIT_EXTINT: return "External interrupt"; case VMX_EXIT_TRIPLE_FAULT: return "Triple fault"; case VMX_EXIT_INIT: return "INIT signal"; case VMX_EXIT_SIPI: return "SIPI signal"; case VMX_EXIT_IO_SMI: return "I/O SMI"; case VMX_EXIT_OTHER_SMI: return "other SMI"; case VMX_EXIT_INT_WINDOW: return "Interrupt window"; case VMX_EXIT_NMI_WINDOW: return "NMI window"; case VMX_EXIT_TASK_SWITCH: return "Task switch"; case VMX_EXIT_CPUID: return "CPUID instruction"; case VMX_EXIT_GETSEC: return "GETSEC instruction"; case VMX_EXIT_HLT: return "HLT instruction"; case VMX_EXIT_INVD: return "INVD instruction"; case VMX_EXIT_INVLPG: return "INVLPG instruction"; case VMX_EXIT_RDPMC: return "RDPMC instruction"; case VMX_EXIT_RDTSC: return "RDTSC instruction"; case VMX_EXIT_RSM: return "RSM instruction"; case VMX_EXIT_VMCALL: return "VMCALL instruction"; case VMX_EXIT_VMCLEAR: return "VMCLEAR instruction"; case VMX_EXIT_VMLAUNCH: return "VMLAUNCH instruction"; case VMX_EXIT_VMPTRLD: return "VMPTRLD instruction"; case VMX_EXIT_VMPTRST: return "VMPTRST instruction"; case VMX_EXIT_VMREAD: return "VMREAD instruction"; case VMX_EXIT_VMRESUME: return "VMRESUME instruction"; case VMX_EXIT_VMWRITE: return "VMWRITE instruction"; case VMX_EXIT_VMXOFF: return "VMXOFF instruction"; case VMX_EXIT_VMXON: return "VMXON instruction"; case VMX_EXIT_CR_ACCESS: return "CR access"; case VMX_EXIT_MOV_DR: return "MOV DR instruction"; case VMX_EXIT_IO: return "I/O instruction"; case VMX_EXIT_RDMSR: return "RDMSR instruction"; case VMX_EXIT_WRMSR: return "WRMSR instruction"; case VMX_EXIT_ENTRY_FAILED_GUEST_STATE: return "guest state invalid"; case VMX_EXIT_ENTRY_FAILED_MSR_LOAD: return "MSR load failed"; case VMX_EXIT_MWAIT: return "MWAIT instruction"; case VMX_EXIT_MTF: return "monitor trap flag"; case VMX_EXIT_MONITOR: return "MONITOR instruction"; case VMX_EXIT_PAUSE: return "PAUSE instruction"; case VMX_EXIT_ENTRY_FAILED_MCE: return "MCE during entry"; case VMX_EXIT_TPR_BELOW_THRESHOLD: return "TPR below threshold"; case VMX_EXIT_APIC_ACCESS: return "APIC access"; case VMX_EXIT_VIRTUALIZED_EOI: return "virtualized EOI"; case VMX_EXIT_GDTR_IDTR: return "GDTR/IDTR access"; case VMX_EXIT_LDTR_TR: return "LDTR/TR access"; case VMX_EXIT_EPT_VIOLATION: return "EPT violation"; case VMX_EXIT_EPT_MISCONFIGURATION: return "EPT misconfiguration"; case VMX_EXIT_INVEPT: return "INVEPT instruction"; case VMX_EXIT_RDTSCP: return "RDTSCP instruction"; case VMX_EXIT_VMX_PREEMPTION_TIMER_EXPIRED: return "preemption timer expired"; case VMX_EXIT_INVVPID: return "INVVPID instruction"; case VMX_EXIT_WBINVD: return "WBINVD instruction"; case VMX_EXIT_XSETBV: return "XSETBV instruction"; case VMX_EXIT_APIC_WRITE: return "APIC write"; case VMX_EXIT_RDRAND: return "RDRAND instruction"; case VMX_EXIT_INVPCID: return "INVPCID instruction"; case VMX_EXIT_VMFUNC: return "VMFUNC instruction"; case VMX_EXIT_RDSEED: return "RDSEED instruction"; case VMX_EXIT_XSAVES: return "XSAVES instruction"; case VMX_EXIT_XRSTORS: return "XRSTORS instruction"; default: return "unknown"; } } /* * svm_exit_reason_decode * * Returns a human readable string describing exit type 'code' */ const char * svm_exit_reason_decode(uint32_t code) { switch (code) { case SVM_VMEXIT_CR0_READ: return "CR0 read"; /* 0x00 */ case SVM_VMEXIT_CR1_READ: return "CR1 read"; /* 0x01 */ case SVM_VMEXIT_CR2_READ: return "CR2 read"; /* 0x02 */ case SVM_VMEXIT_CR3_READ: return "CR3 read"; /* 0x03 */ case SVM_VMEXIT_CR4_READ: return "CR4 read"; /* 0x04 */ case SVM_VMEXIT_CR5_READ: return "CR5 read"; /* 0x05 */ case SVM_VMEXIT_CR6_READ: return "CR6 read"; /* 0x06 */ case SVM_VMEXIT_CR7_READ: return "CR7 read"; /* 0x07 */ case SVM_VMEXIT_CR8_READ: return "CR8 read"; /* 0x08 */ case SVM_VMEXIT_CR9_READ: return "CR9 read"; /* 0x09 */ case SVM_VMEXIT_CR10_READ: return "CR10 read"; /* 0x0A */ case SVM_VMEXIT_CR11_READ: return "CR11 read"; /* 0x0B */ case SVM_VMEXIT_CR12_READ: return "CR12 read"; /* 0x0C */ case SVM_VMEXIT_CR13_READ: return "CR13 read"; /* 0x0D */ case SVM_VMEXIT_CR14_READ: return "CR14 read"; /* 0x0E */ case SVM_VMEXIT_CR15_READ: return "CR15 read"; /* 0x0F */ case SVM_VMEXIT_CR0_WRITE: return "CR0 write"; /* 0x10 */ case SVM_VMEXIT_CR1_WRITE: return "CR1 write"; /* 0x11 */ case SVM_VMEXIT_CR2_WRITE: return "CR2 write"; /* 0x12 */ case SVM_VMEXIT_CR3_WRITE: return "CR3 write"; /* 0x13 */ case SVM_VMEXIT_CR4_WRITE: return "CR4 write"; /* 0x14 */ case SVM_VMEXIT_CR5_WRITE: return "CR5 write"; /* 0x15 */ case SVM_VMEXIT_CR6_WRITE: return "CR6 write"; /* 0x16 */ case SVM_VMEXIT_CR7_WRITE: return "CR7 write"; /* 0x17 */ case SVM_VMEXIT_CR8_WRITE: return "CR8 write"; /* 0x18 */ case SVM_VMEXIT_CR9_WRITE: return "CR9 write"; /* 0x19 */ case SVM_VMEXIT_CR10_WRITE: return "CR10 write"; /* 0x1A */ case SVM_VMEXIT_CR11_WRITE: return "CR11 write"; /* 0x1B */ case SVM_VMEXIT_CR12_WRITE: return "CR12 write"; /* 0x1C */ case SVM_VMEXIT_CR13_WRITE: return "CR13 write"; /* 0x1D */ case SVM_VMEXIT_CR14_WRITE: return "CR14 write"; /* 0x1E */ case SVM_VMEXIT_CR15_WRITE: return "CR15 write"; /* 0x1F */ case SVM_VMEXIT_DR0_READ: return "DR0 read"; /* 0x20 */ case SVM_VMEXIT_DR1_READ: return "DR1 read"; /* 0x21 */ case SVM_VMEXIT_DR2_READ: return "DR2 read"; /* 0x22 */ case SVM_VMEXIT_DR3_READ: return "DR3 read"; /* 0x23 */ case SVM_VMEXIT_DR4_READ: return "DR4 read"; /* 0x24 */ case SVM_VMEXIT_DR5_READ: return "DR5 read"; /* 0x25 */ case SVM_VMEXIT_DR6_READ: return "DR6 read"; /* 0x26 */ case SVM_VMEXIT_DR7_READ: return "DR7 read"; /* 0x27 */ case SVM_VMEXIT_DR8_READ: return "DR8 read"; /* 0x28 */ case SVM_VMEXIT_DR9_READ: return "DR9 read"; /* 0x29 */ case SVM_VMEXIT_DR10_READ: return "DR10 read"; /* 0x2A */ case SVM_VMEXIT_DR11_READ: return "DR11 read"; /* 0x2B */ case SVM_VMEXIT_DR12_READ: return "DR12 read"; /* 0x2C */ case SVM_VMEXIT_DR13_READ: return "DR13 read"; /* 0x2D */ case SVM_VMEXIT_DR14_READ: return "DR14 read"; /* 0x2E */ case SVM_VMEXIT_DR15_READ: return "DR15 read"; /* 0x2F */ case SVM_VMEXIT_DR0_WRITE: return "DR0 write"; /* 0x30 */ case SVM_VMEXIT_DR1_WRITE: return "DR1 write"; /* 0x31 */ case SVM_VMEXIT_DR2_WRITE: return "DR2 write"; /* 0x32 */ case SVM_VMEXIT_DR3_WRITE: return "DR3 write"; /* 0x33 */ case SVM_VMEXIT_DR4_WRITE: return "DR4 write"; /* 0x34 */ case SVM_VMEXIT_DR5_WRITE: return "DR5 write"; /* 0x35 */ case SVM_VMEXIT_DR6_WRITE: return "DR6 write"; /* 0x36 */ case SVM_VMEXIT_DR7_WRITE: return "DR7 write"; /* 0x37 */ case SVM_VMEXIT_DR8_WRITE: return "DR8 write"; /* 0x38 */ case SVM_VMEXIT_DR9_WRITE: return "DR9 write"; /* 0x39 */ case SVM_VMEXIT_DR10_WRITE: return "DR10 write"; /* 0x3A */ case SVM_VMEXIT_DR11_WRITE: return "DR11 write"; /* 0x3B */ case SVM_VMEXIT_DR12_WRITE: return "DR12 write"; /* 0x3C */ case SVM_VMEXIT_DR13_WRITE: return "DR13 write"; /* 0x3D */ case SVM_VMEXIT_DR14_WRITE: return "DR14 write"; /* 0x3E */ case SVM_VMEXIT_DR15_WRITE: return "DR15 write"; /* 0x3F */ case SVM_VMEXIT_EXCP0: return "Exception 0x00"; /* 0x40 */ case SVM_VMEXIT_EXCP1: return "Exception 0x01"; /* 0x41 */ case SVM_VMEXIT_EXCP2: return "Exception 0x02"; /* 0x42 */ case SVM_VMEXIT_EXCP3: return "Exception 0x03"; /* 0x43 */ case SVM_VMEXIT_EXCP4: return "Exception 0x04"; /* 0x44 */ case SVM_VMEXIT_EXCP5: return "Exception 0x05"; /* 0x45 */ case SVM_VMEXIT_EXCP6: return "Exception 0x06"; /* 0x46 */ case SVM_VMEXIT_EXCP7: return "Exception 0x07"; /* 0x47 */ case SVM_VMEXIT_EXCP8: return "Exception 0x08"; /* 0x48 */ case SVM_VMEXIT_EXCP9: return "Exception 0x09"; /* 0x49 */ case SVM_VMEXIT_EXCP10: return "Exception 0x0A"; /* 0x4A */ case SVM_VMEXIT_EXCP11: return "Exception 0x0B"; /* 0x4B */ case SVM_VMEXIT_EXCP12: return "Exception 0x0C"; /* 0x4C */ case SVM_VMEXIT_EXCP13: return "Exception 0x0D"; /* 0x4D */ case SVM_VMEXIT_EXCP14: return "Exception 0x0E"; /* 0x4E */ case SVM_VMEXIT_EXCP15: return "Exception 0x0F"; /* 0x4F */ case SVM_VMEXIT_EXCP16: return "Exception 0x10"; /* 0x50 */ case SVM_VMEXIT_EXCP17: return "Exception 0x11"; /* 0x51 */ case SVM_VMEXIT_EXCP18: return "Exception 0x12"; /* 0x52 */ case SVM_VMEXIT_EXCP19: return "Exception 0x13"; /* 0x53 */ case SVM_VMEXIT_EXCP20: return "Exception 0x14"; /* 0x54 */ case SVM_VMEXIT_EXCP21: return "Exception 0x15"; /* 0x55 */ case SVM_VMEXIT_EXCP22: return "Exception 0x16"; /* 0x56 */ case SVM_VMEXIT_EXCP23: return "Exception 0x17"; /* 0x57 */ case SVM_VMEXIT_EXCP24: return "Exception 0x18"; /* 0x58 */ case SVM_VMEXIT_EXCP25: return "Exception 0x19"; /* 0x59 */ case SVM_VMEXIT_EXCP26: return "Exception 0x1A"; /* 0x5A */ case SVM_VMEXIT_EXCP27: return "Exception 0x1B"; /* 0x5B */ case SVM_VMEXIT_EXCP28: return "Exception 0x1C"; /* 0x5C */ case SVM_VMEXIT_EXCP29: return "Exception 0x1D"; /* 0x5D */ case SVM_VMEXIT_EXCP30: return "Exception 0x1E"; /* 0x5E */ case SVM_VMEXIT_EXCP31: return "Exception 0x1F"; /* 0x5F */ case SVM_VMEXIT_INTR: return "External interrupt"; /* 0x60 */ case SVM_VMEXIT_NMI: return "NMI"; /* 0x61 */ case SVM_VMEXIT_SMI: return "SMI"; /* 0x62 */ case SVM_VMEXIT_INIT: return "INIT"; /* 0x63 */ case SVM_VMEXIT_VINTR: return "Interrupt window"; /* 0x64 */ case SVM_VMEXIT_CR0_SEL_WRITE: return "Sel CR0 write"; /* 0x65 */ case SVM_VMEXIT_IDTR_READ: return "IDTR read"; /* 0x66 */ case SVM_VMEXIT_GDTR_READ: return "GDTR read"; /* 0x67 */ case SVM_VMEXIT_LDTR_READ: return "LDTR read"; /* 0x68 */ case SVM_VMEXIT_TR_READ: return "TR read"; /* 0x69 */ case SVM_VMEXIT_IDTR_WRITE: return "IDTR write"; /* 0x6A */ case SVM_VMEXIT_GDTR_WRITE: return "GDTR write"; /* 0x6B */ case SVM_VMEXIT_LDTR_WRITE: return "LDTR write"; /* 0x6C */ case SVM_VMEXIT_TR_WRITE: return "TR write"; /* 0x6D */ case SVM_VMEXIT_RDTSC: return "RDTSC instruction"; /* 0x6E */ case SVM_VMEXIT_RDPMC: return "RDPMC instruction"; /* 0x6F */ case SVM_VMEXIT_PUSHF: return "PUSHF instruction"; /* 0x70 */ case SVM_VMEXIT_POPF: return "POPF instruction"; /* 0x71 */ case SVM_VMEXIT_CPUID: return "CPUID instruction"; /* 0x72 */ case SVM_VMEXIT_RSM: return "RSM instruction"; /* 0x73 */ case SVM_VMEXIT_IRET: return "IRET instruction"; /* 0x74 */ case SVM_VMEXIT_SWINT: return "SWINT instruction"; /* 0x75 */ case SVM_VMEXIT_INVD: return "INVD instruction"; /* 0x76 */ case SVM_VMEXIT_PAUSE: return "PAUSE instruction"; /* 0x77 */ case SVM_VMEXIT_HLT: return "HLT instruction"; /* 0x78 */ case SVM_VMEXIT_INVLPG: return "INVLPG instruction"; /* 0x79 */ case SVM_VMEXIT_INVLPGA: return "INVLPGA instruction"; /* 0x7A */ case SVM_VMEXIT_IOIO: return "I/O instruction"; /* 0x7B */ case SVM_VMEXIT_MSR: return "RDMSR/WRMSR instruction"; /* 0x7C */ case SVM_VMEXIT_TASK_SWITCH: return "Task switch"; /* 0x7D */ case SVM_VMEXIT_FERR_FREEZE: return "FERR_FREEZE"; /* 0x7E */ case SVM_VMEXIT_SHUTDOWN: return "Triple fault"; /* 0x7F */ case SVM_VMEXIT_VMRUN: return "VMRUN instruction"; /* 0x80 */ case SVM_VMEXIT_VMMCALL: return "VMMCALL instruction"; /* 0x81 */ case SVM_VMEXIT_VMLOAD: return "VMLOAD instruction"; /* 0x82 */ case SVM_VMEXIT_VMSAVE: return "VMSAVE instruction"; /* 0x83 */ case SVM_VMEXIT_STGI: return "STGI instruction"; /* 0x84 */ case SVM_VMEXIT_CLGI: return "CLGI instruction"; /* 0x85 */ case SVM_VMEXIT_SKINIT: return "SKINIT instruction"; /* 0x86 */ case SVM_VMEXIT_RDTSCP: return "RDTSCP instruction"; /* 0x87 */ case SVM_VMEXIT_ICEBP: return "ICEBP instruction"; /* 0x88 */ case SVM_VMEXIT_WBINVD: return "WBINVD instruction"; /* 0x89 */ case SVM_VMEXIT_MONITOR: return "MONITOR instruction"; /* 0x8A */ case SVM_VMEXIT_MWAIT: return "MWAIT instruction"; /* 0x8B */ case SVM_VMEXIT_MWAIT_CONDITIONAL: return "Cond MWAIT"; /* 0x8C */ case SVM_VMEXIT_NPF: return "NPT violation"; /* 0x400 */ default: return "unknown"; } } /* * vmx_instruction_error_decode * * Returns a human readable string describing the instruction error in 'code' */ const char * vmx_instruction_error_decode(uint32_t code) { switch (code) { case 1: return "VMCALL: unsupported in VMX root"; case 2: return "VMCLEAR: invalid paddr"; case 3: return "VMCLEAR: VMXON pointer"; case 4: return "VMLAUNCH: non-clear VMCS"; case 5: return "VMRESUME: non-launched VMCS"; case 6: return "VMRESUME: executed after VMXOFF"; case 7: return "VM entry: invalid control field(s)"; case 8: return "VM entry: invalid host state field(s)"; case 9: return "VMPTRLD: invalid paddr"; case 10: return "VMPTRLD: VMXON pointer"; case 11: return "VMPTRLD: incorrect VMCS revid"; case 12: return "VMREAD/VMWRITE: unsupported VMCS field"; case 13: return "VMWRITE: RO VMCS field"; case 15: return "VMXON: unsupported in VMX root"; case 20: return "VMCALL: invalid VM exit control fields"; case 26: return "VM entry: blocked by MOV SS"; case 28: return "Invalid operand to INVEPT/INVVPID"; case 0x80000021: return "VM entry: invalid guest state"; case 0x80000022: return "VM entry: failure due to MSR loading"; case 0x80000029: return "VM entry: machine-check event"; default: return "unknown"; } } /* * vcpu_state_decode * * Returns a human readable string describing the vcpu state in 'state'. */ const char * vcpu_state_decode(u_int state) { switch (state) { case VCPU_STATE_STOPPED: return "stopped"; case VCPU_STATE_RUNNING: return "running"; case VCPU_STATE_REQTERM: return "requesting termination"; case VCPU_STATE_TERMINATED: return "terminated"; case VCPU_STATE_UNKNOWN: return "unknown"; default: return "invalid"; } } #ifdef VMM_DEBUG /* * dump_vcpu * * Dumps the VMX capabilities of vcpu 'vcpu' */ void dump_vcpu(struct vcpu *vcpu) { printf("vcpu @ %p\n", vcpu); printf(" parent vm @ %p\n", vcpu->vc_parent); printf(" mode: "); if (vcpu->vc_virt_mode == VMM_MODE_EPT) { printf("VMX\n"); printf(" pinbased ctls: 0x%llx\n", vcpu->vc_vmx_pinbased_ctls); printf(" true pinbased ctls: 0x%llx\n", vcpu->vc_vmx_true_pinbased_ctls); CTRL_DUMP(vcpu, PINBASED, EXTERNAL_INT_EXITING); CTRL_DUMP(vcpu, PINBASED, NMI_EXITING); CTRL_DUMP(vcpu, PINBASED, VIRTUAL_NMIS); CTRL_DUMP(vcpu, PINBASED, ACTIVATE_VMX_PREEMPTION_TIMER); CTRL_DUMP(vcpu, PINBASED, PROCESS_POSTED_INTERRUPTS); printf(" procbased ctls: 0x%llx\n", vcpu->vc_vmx_procbased_ctls); printf(" true procbased ctls: 0x%llx\n", vcpu->vc_vmx_true_procbased_ctls); CTRL_DUMP(vcpu, PROCBASED, INTERRUPT_WINDOW_EXITING); CTRL_DUMP(vcpu, PROCBASED, USE_TSC_OFFSETTING); CTRL_DUMP(vcpu, PROCBASED, HLT_EXITING); CTRL_DUMP(vcpu, PROCBASED, INVLPG_EXITING); CTRL_DUMP(vcpu, PROCBASED, MWAIT_EXITING); CTRL_DUMP(vcpu, PROCBASED, RDPMC_EXITING); CTRL_DUMP(vcpu, PROCBASED, RDTSC_EXITING); CTRL_DUMP(vcpu, PROCBASED, CR3_LOAD_EXITING); CTRL_DUMP(vcpu, PROCBASED, CR3_STORE_EXITING); CTRL_DUMP(vcpu, PROCBASED, CR8_LOAD_EXITING); CTRL_DUMP(vcpu, PROCBASED, CR8_STORE_EXITING); CTRL_DUMP(vcpu, PROCBASED, USE_TPR_SHADOW); CTRL_DUMP(vcpu, PROCBASED, NMI_WINDOW_EXITING); CTRL_DUMP(vcpu, PROCBASED, MOV_DR_EXITING); CTRL_DUMP(vcpu, PROCBASED, UNCONDITIONAL_IO_EXITING); CTRL_DUMP(vcpu, PROCBASED, USE_IO_BITMAPS); CTRL_DUMP(vcpu, PROCBASED, MONITOR_TRAP_FLAG); CTRL_DUMP(vcpu, PROCBASED, USE_MSR_BITMAPS); CTRL_DUMP(vcpu, PROCBASED, MONITOR_EXITING); CTRL_DUMP(vcpu, PROCBASED, PAUSE_EXITING); if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED_CTLS, IA32_VMX_ACTIVATE_SECONDARY_CONTROLS, 1)) { printf(" procbased2 ctls: 0x%llx\n", vcpu->vc_vmx_procbased2_ctls); CTRL_DUMP(vcpu, PROCBASED2, VIRTUALIZE_APIC); CTRL_DUMP(vcpu, PROCBASED2, ENABLE_EPT); CTRL_DUMP(vcpu, PROCBASED2, DESCRIPTOR_TABLE_EXITING); CTRL_DUMP(vcpu, PROCBASED2, ENABLE_RDTSCP); CTRL_DUMP(vcpu, PROCBASED2, VIRTUALIZE_X2APIC_MODE); CTRL_DUMP(vcpu, PROCBASED2, ENABLE_VPID); CTRL_DUMP(vcpu, PROCBASED2, WBINVD_EXITING); CTRL_DUMP(vcpu, PROCBASED2, UNRESTRICTED_GUEST); CTRL_DUMP(vcpu, PROCBASED2, APIC_REGISTER_VIRTUALIZATION); CTRL_DUMP(vcpu, PROCBASED2, VIRTUAL_INTERRUPT_DELIVERY); CTRL_DUMP(vcpu, PROCBASED2, PAUSE_LOOP_EXITING); CTRL_DUMP(vcpu, PROCBASED2, RDRAND_EXITING); CTRL_DUMP(vcpu, PROCBASED2, ENABLE_INVPCID); CTRL_DUMP(vcpu, PROCBASED2, ENABLE_VM_FUNCTIONS); CTRL_DUMP(vcpu, PROCBASED2, VMCS_SHADOWING); CTRL_DUMP(vcpu, PROCBASED2, ENABLE_ENCLS_EXITING); CTRL_DUMP(vcpu, PROCBASED2, RDSEED_EXITING); CTRL_DUMP(vcpu, PROCBASED2, ENABLE_PML); CTRL_DUMP(vcpu, PROCBASED2, EPT_VIOLATION_VE); CTRL_DUMP(vcpu, PROCBASED2, CONCEAL_VMX_FROM_PT); CTRL_DUMP(vcpu, PROCBASED2, ENABLE_XSAVES_XRSTORS); CTRL_DUMP(vcpu, PROCBASED2, ENABLE_TSC_SCALING); } printf(" entry ctls: 0x%llx\n", vcpu->vc_vmx_entry_ctls); printf(" true entry ctls: 0x%llx\n", vcpu->vc_vmx_true_entry_ctls); CTRL_DUMP(vcpu, ENTRY, LOAD_DEBUG_CONTROLS); CTRL_DUMP(vcpu, ENTRY, IA32E_MODE_GUEST); CTRL_DUMP(vcpu, ENTRY, ENTRY_TO_SMM); CTRL_DUMP(vcpu, ENTRY, DEACTIVATE_DUAL_MONITOR_TREATMENT); CTRL_DUMP(vcpu, ENTRY, LOAD_IA32_PERF_GLOBAL_CTRL_ON_ENTRY); CTRL_DUMP(vcpu, ENTRY, LOAD_IA32_PAT_ON_ENTRY); CTRL_DUMP(vcpu, ENTRY, LOAD_IA32_EFER_ON_ENTRY); CTRL_DUMP(vcpu, ENTRY, LOAD_IA32_BNDCFGS_ON_ENTRY); CTRL_DUMP(vcpu, ENTRY, CONCEAL_VM_ENTRIES_FROM_PT); printf(" exit ctls: 0x%llx\n", vcpu->vc_vmx_exit_ctls); printf(" true exit ctls: 0x%llx\n", vcpu->vc_vmx_true_exit_ctls); CTRL_DUMP(vcpu, EXIT, SAVE_DEBUG_CONTROLS); CTRL_DUMP(vcpu, EXIT, HOST_SPACE_ADDRESS_SIZE); CTRL_DUMP(vcpu, EXIT, LOAD_IA32_PERF_GLOBAL_CTRL_ON_EXIT); CTRL_DUMP(vcpu, EXIT, ACKNOWLEDGE_INTERRUPT_ON_EXIT); CTRL_DUMP(vcpu, EXIT, SAVE_IA32_PAT_ON_EXIT); CTRL_DUMP(vcpu, EXIT, LOAD_IA32_PAT_ON_EXIT); CTRL_DUMP(vcpu, EXIT, SAVE_IA32_EFER_ON_EXIT); CTRL_DUMP(vcpu, EXIT, LOAD_IA32_EFER_ON_EXIT); CTRL_DUMP(vcpu, EXIT, SAVE_VMX_PREEMPTION_TIMER); CTRL_DUMP(vcpu, EXIT, CLEAR_IA32_BNDCFGS_ON_EXIT); CTRL_DUMP(vcpu, EXIT, CONCEAL_VM_EXITS_FROM_PT); } } /* * vmx_dump_vmcs_field * * Debug function to dump the contents of a single VMCS field * * Parameters: * fieldid: VMCS Field ID * msg: string to display */ void vmx_dump_vmcs_field(uint16_t fieldid, const char *msg) { uint8_t width; uint64_t val; DPRINTF("%s (0x%04x): ", msg, fieldid); if (vmread(fieldid, &val)) DPRINTF("???? "); else { /* * Field width encoding : bits 13:14 * * 0: 16-bit * 1: 64-bit * 2: 32-bit * 3: natural width */ width = (fieldid >> 13) & 0x3; switch (width) { case 0: DPRINTF("0x%04llx ", val); break; case 1: case 3: DPRINTF("0x%016llx ", val); break; case 2: DPRINTF("0x%08llx ", val); } } } /* * vmx_dump_vmcs * * Debug function to dump the contents of the current VMCS. */ void vmx_dump_vmcs(struct vcpu *vcpu) { int has_sec, i; uint32_t cr3_tgt_ct; /* XXX save and load new vmcs, restore at end */ DPRINTF("--CURRENT VMCS STATE--\n"); printf("VMCS launched: %s\n", (vcpu->vc_vmx_vmcs_state == VMCS_LAUNCHED) ? "Yes" : "No"); DPRINTF("VMXON revision : 0x%x\n", curcpu()->ci_vmm_cap.vcc_vmx.vmx_vmxon_revision); DPRINTF("CR0 fixed0: 0x%llx\n", curcpu()->ci_vmm_cap.vcc_vmx.vmx_cr0_fixed0); DPRINTF("CR0 fixed1: 0x%llx\n", curcpu()->ci_vmm_cap.vcc_vmx.vmx_cr0_fixed1); DPRINTF("CR4 fixed0: 0x%llx\n", curcpu()->ci_vmm_cap.vcc_vmx.vmx_cr4_fixed0); DPRINTF("CR4 fixed1: 0x%llx\n", curcpu()->ci_vmm_cap.vcc_vmx.vmx_cr4_fixed1); DPRINTF("MSR table size: 0x%x\n", 512 * (curcpu()->ci_vmm_cap.vcc_vmx.vmx_msr_table_size + 1)); has_sec = vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED_CTLS, IA32_VMX_ACTIVATE_SECONDARY_CONTROLS, 1); if (has_sec) { if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED2_CTLS, IA32_VMX_ENABLE_VPID, 1)) { vmx_dump_vmcs_field(VMCS_GUEST_VPID, "VPID"); } } if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PINBASED_CTLS, IA32_VMX_PROCESS_POSTED_INTERRUPTS, 1)) { vmx_dump_vmcs_field(VMCS_POSTED_INT_NOTIF_VECTOR, "Posted Int Notif Vec"); } if (has_sec) { if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED2_CTLS, IA32_VMX_EPT_VIOLATION_VE, 1)) { vmx_dump_vmcs_field(VMCS_EPTP_INDEX, "EPTP idx"); } } DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_ES_SEL, "G.ES"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_CS_SEL, "G.CS"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_SS_SEL, "G.SS"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_DS_SEL, "G.DS"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_FS_SEL, "G.FS"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_GS_SEL, "G.GS"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_LDTR_SEL, "LDTR"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_TR_SEL, "G.TR"); if (has_sec) { if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED2_CTLS, IA32_VMX_VIRTUAL_INTERRUPT_DELIVERY, 1)) { vmx_dump_vmcs_field(VMCS_GUEST_INTERRUPT_STATUS, "Int sts"); } if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED2_CTLS, IA32_VMX_ENABLE_PML, 1)) { vmx_dump_vmcs_field(VMCS_GUEST_PML_INDEX, "PML Idx"); } } DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_HOST_IA32_ES_SEL, "H.ES"); vmx_dump_vmcs_field(VMCS_HOST_IA32_CS_SEL, "H.CS"); vmx_dump_vmcs_field(VMCS_HOST_IA32_SS_SEL, "H.SS"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_HOST_IA32_DS_SEL, "H.DS"); vmx_dump_vmcs_field(VMCS_HOST_IA32_FS_SEL, "H.FS"); vmx_dump_vmcs_field(VMCS_HOST_IA32_GS_SEL, "H.GS"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_IO_BITMAP_A, "I/O Bitmap A"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_IO_BITMAP_B, "I/O Bitmap B"); DPRINTF("\n"); if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED_CTLS, IA32_VMX_USE_MSR_BITMAPS, 1)) { vmx_dump_vmcs_field(VMCS_MSR_BITMAP_ADDRESS, "MSR Bitmap"); DPRINTF("\n"); } vmx_dump_vmcs_field(VMCS_EXIT_STORE_MSR_ADDRESS, "Exit Store MSRs"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_EXIT_LOAD_MSR_ADDRESS, "Exit Load MSRs"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_ENTRY_LOAD_MSR_ADDRESS, "Entry Load MSRs"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_EXECUTIVE_VMCS_POINTER, "Exec VMCS Ptr"); DPRINTF("\n"); if (has_sec) { if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED2_CTLS, IA32_VMX_ENABLE_PML, 1)) { vmx_dump_vmcs_field(VMCS_PML_ADDRESS, "PML Addr"); DPRINTF("\n"); } } vmx_dump_vmcs_field(VMCS_TSC_OFFSET, "TSC Offset"); DPRINTF("\n"); if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED_CTLS, IA32_VMX_USE_TPR_SHADOW, 1)) { vmx_dump_vmcs_field(VMCS_VIRTUAL_APIC_ADDRESS, "Virtual APIC Addr"); DPRINTF("\n"); } if (has_sec) { if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED2_CTLS, IA32_VMX_VIRTUALIZE_APIC, 1)) { vmx_dump_vmcs_field(VMCS_APIC_ACCESS_ADDRESS, "APIC Access Addr"); DPRINTF("\n"); } } if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PINBASED_CTLS, IA32_VMX_PROCESS_POSTED_INTERRUPTS, 1)) { vmx_dump_vmcs_field(VMCS_POSTED_INTERRUPT_DESC, "Posted Int Desc Addr"); DPRINTF("\n"); } if (has_sec) { if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED2_CTLS, IA32_VMX_ENABLE_VM_FUNCTIONS, 1)) { vmx_dump_vmcs_field(VMCS_VM_FUNCTION_CONTROLS, "VM Function Controls"); DPRINTF("\n"); } if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED2_CTLS, IA32_VMX_ENABLE_EPT, 1)) { vmx_dump_vmcs_field(VMCS_GUEST_IA32_EPTP, "EPT Pointer"); DPRINTF("\n"); } if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED2_CTLS, IA32_VMX_VIRTUAL_INTERRUPT_DELIVERY, 1)) { vmx_dump_vmcs_field(VMCS_EOI_EXIT_BITMAP_0, "EOI Exit Bitmap 0"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_EOI_EXIT_BITMAP_1, "EOI Exit Bitmap 1"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_EOI_EXIT_BITMAP_2, "EOI Exit Bitmap 2"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_EOI_EXIT_BITMAP_3, "EOI Exit Bitmap 3"); DPRINTF("\n"); } if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED2_CTLS, IA32_VMX_ENABLE_VM_FUNCTIONS, 1)) { /* We assume all CPUs have the same VMFUNC caps */ if (curcpu()->ci_vmm_cap.vcc_vmx.vmx_vm_func & 0x1) { vmx_dump_vmcs_field(VMCS_EPTP_LIST_ADDRESS, "EPTP List Addr"); DPRINTF("\n"); } } if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED2_CTLS, IA32_VMX_VMCS_SHADOWING, 1)) { vmx_dump_vmcs_field(VMCS_VMREAD_BITMAP_ADDRESS, "VMREAD Bitmap Addr"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_VMWRITE_BITMAP_ADDRESS, "VMWRITE Bitmap Addr"); DPRINTF("\n"); } if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED2_CTLS, IA32_VMX_EPT_VIOLATION_VE, 1)) { vmx_dump_vmcs_field(VMCS_VIRTUALIZATION_EXC_ADDRESS, "#VE Addr"); DPRINTF("\n"); } if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED2_CTLS, IA32_VMX_ENABLE_XSAVES_XRSTORS, 1)) { vmx_dump_vmcs_field(VMCS_XSS_EXITING_BITMAP, "XSS exiting bitmap addr"); DPRINTF("\n"); } if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED2_CTLS, IA32_VMX_ENABLE_ENCLS_EXITING, 1)) { vmx_dump_vmcs_field(VMCS_ENCLS_EXITING_BITMAP, "Encls exiting bitmap addr"); DPRINTF("\n"); } if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED2_CTLS, IA32_VMX_ENABLE_TSC_SCALING, 1)) { vmx_dump_vmcs_field(VMCS_TSC_MULTIPLIER, "TSC scaling factor"); DPRINTF("\n"); } if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED2_CTLS, IA32_VMX_ENABLE_EPT, 1)) { vmx_dump_vmcs_field(VMCS_GUEST_PHYSICAL_ADDRESS, "Guest PA"); DPRINTF("\n"); } } vmx_dump_vmcs_field(VMCS_LINK_POINTER, "VMCS Link Pointer"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_DEBUGCTL, "Guest DEBUGCTL"); DPRINTF("\n"); if (vcpu_vmx_check_cap(vcpu, IA32_VMX_ENTRY_CTLS, IA32_VMX_LOAD_IA32_PAT_ON_ENTRY, 1) || vcpu_vmx_check_cap(vcpu, IA32_VMX_EXIT_CTLS, IA32_VMX_SAVE_IA32_PAT_ON_EXIT, 1)) { vmx_dump_vmcs_field(VMCS_GUEST_IA32_PAT, "Guest PAT"); DPRINTF("\n"); } if (vcpu_vmx_check_cap(vcpu, IA32_VMX_ENTRY_CTLS, IA32_VMX_LOAD_IA32_EFER_ON_ENTRY, 1) || vcpu_vmx_check_cap(vcpu, IA32_VMX_EXIT_CTLS, IA32_VMX_SAVE_IA32_EFER_ON_EXIT, 1)) { vmx_dump_vmcs_field(VMCS_GUEST_IA32_EFER, "Guest EFER"); DPRINTF("\n"); } if (vcpu_vmx_check_cap(vcpu, IA32_VMX_ENTRY_CTLS, IA32_VMX_LOAD_IA32_PERF_GLOBAL_CTRL_ON_ENTRY, 1)) { vmx_dump_vmcs_field(VMCS_GUEST_IA32_PERF_GBL_CTRL, "Guest Perf Global Ctrl"); DPRINTF("\n"); } if (has_sec) { if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED2_CTLS, IA32_VMX_ENABLE_EPT, 1)) { vmx_dump_vmcs_field(VMCS_GUEST_PDPTE0, "Guest PDPTE0"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_PDPTE1, "Guest PDPTE1"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_PDPTE2, "Guest PDPTE2"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_PDPTE3, "Guest PDPTE3"); DPRINTF("\n"); } } if (vcpu_vmx_check_cap(vcpu, IA32_VMX_ENTRY_CTLS, IA32_VMX_LOAD_IA32_BNDCFGS_ON_ENTRY, 1) || vcpu_vmx_check_cap(vcpu, IA32_VMX_EXIT_CTLS, IA32_VMX_CLEAR_IA32_BNDCFGS_ON_EXIT, 1)) { vmx_dump_vmcs_field(VMCS_GUEST_IA32_BNDCFGS, "Guest BNDCFGS"); DPRINTF("\n"); } if (vcpu_vmx_check_cap(vcpu, IA32_VMX_EXIT_CTLS, IA32_VMX_LOAD_IA32_PAT_ON_EXIT, 1)) { vmx_dump_vmcs_field(VMCS_HOST_IA32_PAT, "Host PAT"); DPRINTF("\n"); } if (vcpu_vmx_check_cap(vcpu, IA32_VMX_EXIT_CTLS, IA32_VMX_LOAD_IA32_EFER_ON_EXIT, 1)) { vmx_dump_vmcs_field(VMCS_HOST_IA32_EFER, "Host EFER"); DPRINTF("\n"); } if (vcpu_vmx_check_cap(vcpu, IA32_VMX_EXIT_CTLS, IA32_VMX_LOAD_IA32_PERF_GLOBAL_CTRL_ON_EXIT, 1)) { vmx_dump_vmcs_field(VMCS_HOST_IA32_PERF_GBL_CTRL, "Host Perf Global Ctrl"); DPRINTF("\n"); } vmx_dump_vmcs_field(VMCS_PINBASED_CTLS, "Pinbased Ctrls"); vmx_dump_vmcs_field(VMCS_PROCBASED_CTLS, "Procbased Ctrls"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_EXCEPTION_BITMAP, "Exception Bitmap"); vmx_dump_vmcs_field(VMCS_PF_ERROR_CODE_MASK, "#PF Err Code Mask"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_PF_ERROR_CODE_MATCH, "#PF Err Code Match"); vmx_dump_vmcs_field(VMCS_CR3_TARGET_COUNT, "CR3 Tgt Count"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_EXIT_CTLS, "Exit Ctrls"); vmx_dump_vmcs_field(VMCS_EXIT_MSR_STORE_COUNT, "Exit MSR Store Ct"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_EXIT_MSR_LOAD_COUNT, "Exit MSR Load Ct"); vmx_dump_vmcs_field(VMCS_ENTRY_CTLS, "Entry Ctrls"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_ENTRY_MSR_LOAD_COUNT, "Entry MSR Load Ct"); vmx_dump_vmcs_field(VMCS_ENTRY_INTERRUPTION_INFO, "Entry Int. Info"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_ENTRY_EXCEPTION_ERROR_CODE, "Entry Ex. Err Code"); vmx_dump_vmcs_field(VMCS_ENTRY_INSTRUCTION_LENGTH, "Entry Insn Len"); DPRINTF("\n"); if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED_CTLS, IA32_VMX_USE_TPR_SHADOW, 1)) { vmx_dump_vmcs_field(VMCS_TPR_THRESHOLD, "TPR Threshold"); DPRINTF("\n"); } if (has_sec) { vmx_dump_vmcs_field(VMCS_PROCBASED2_CTLS, "2ndary Ctrls"); DPRINTF("\n"); if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PROCBASED2_CTLS, IA32_VMX_PAUSE_LOOP_EXITING, 1)) { vmx_dump_vmcs_field(VMCS_PLE_GAP, "PLE Gap"); vmx_dump_vmcs_field(VMCS_PLE_WINDOW, "PLE Window"); } DPRINTF("\n"); } vmx_dump_vmcs_field(VMCS_INSTRUCTION_ERROR, "Insn Error"); vmx_dump_vmcs_field(VMCS_EXIT_REASON, "Exit Reason"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_EXIT_INTERRUPTION_INFO, "Exit Int. Info"); vmx_dump_vmcs_field(VMCS_EXIT_INTERRUPTION_ERR_CODE, "Exit Int. Err Code"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_IDT_VECTORING_INFO, "IDT vect info"); vmx_dump_vmcs_field(VMCS_IDT_VECTORING_ERROR_CODE, "IDT vect err code"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_INSTRUCTION_LENGTH, "Insn Len"); vmx_dump_vmcs_field(VMCS_EXIT_INSTRUCTION_INFO, "Exit Insn Info"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_ES_LIMIT, "G. ES Lim"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_CS_LIMIT, "G. CS Lim"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_SS_LIMIT, "G. SS Lim"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_DS_LIMIT, "G. DS Lim"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_FS_LIMIT, "G. FS Lim"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_GS_LIMIT, "G. GS Lim"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_LDTR_LIMIT, "G. LDTR Lim"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_TR_LIMIT, "G. TR Lim"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_GDTR_LIMIT, "G. GDTR Lim"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_IDTR_LIMIT, "G. IDTR Lim"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_ES_AR, "G. ES AR"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_CS_AR, "G. CS AR"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_SS_AR, "G. SS AR"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_DS_AR, "G. DS AR"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_FS_AR, "G. FS AR"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_GS_AR, "G. GS AR"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_LDTR_AR, "G. LDTR AR"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_TR_AR, "G. TR AR"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_INTERRUPTIBILITY_ST, "G. Int St."); vmx_dump_vmcs_field(VMCS_GUEST_ACTIVITY_STATE, "G. Act St."); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_SMBASE, "G. SMBASE"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_SYSENTER_CS, "G. SYSENTER CS"); DPRINTF("\n"); if (vcpu_vmx_check_cap(vcpu, IA32_VMX_PINBASED_CTLS, IA32_VMX_ACTIVATE_VMX_PREEMPTION_TIMER, 1)) { vmx_dump_vmcs_field(VMCS_VMX_PREEMPTION_TIMER_VAL, "VMX Preempt Timer"); DPRINTF("\n"); } vmx_dump_vmcs_field(VMCS_HOST_IA32_SYSENTER_CS, "H. SYSENTER CS"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_CR0_MASK, "CR0 Mask"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_CR4_MASK, "CR4 Mask"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_CR0_READ_SHADOW, "CR0 RD Shadow"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_CR4_READ_SHADOW, "CR4 RD Shadow"); DPRINTF("\n"); /* We assume all CPUs have the same max CR3 target ct */ cr3_tgt_ct = curcpu()->ci_vmm_cap.vcc_vmx.vmx_cr3_tgt_count; DPRINTF("Max CR3 target count: 0x%x\n", cr3_tgt_ct); if (cr3_tgt_ct <= VMX_MAX_CR3_TARGETS) { for (i = 0 ; i < cr3_tgt_ct; i++) { vmx_dump_vmcs_field(VMCS_CR3_TARGET_0 + (2 * i), "CR3 Target"); DPRINTF("\n"); } } else { DPRINTF("(Bogus CR3 Target Count > %d", VMX_MAX_CR3_TARGETS); } vmx_dump_vmcs_field(VMCS_GUEST_EXIT_QUALIFICATION, "G. Exit Qual"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_IO_RCX, "I/O RCX"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_IO_RSI, "I/O RSI"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_IO_RDI, "I/O RDI"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_IO_RIP, "I/O RIP"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_LINEAR_ADDRESS, "G. Lin Addr"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_CR0, "G. CR0"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_CR3, "G. CR3"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_CR4, "G. CR4"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_ES_BASE, "G. ES Base"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_CS_BASE, "G. CS Base"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_SS_BASE, "G. SS Base"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_DS_BASE, "G. DS Base"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_FS_BASE, "G. FS Base"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_GS_BASE, "G. GS Base"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_LDTR_BASE, "G. LDTR Base"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_TR_BASE, "G. TR Base"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_GDTR_BASE, "G. GDTR Base"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_IDTR_BASE, "G. IDTR Base"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_DR7, "G. DR7"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_RSP, "G. RSP"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_RIP, "G. RIP"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_RFLAGS, "G. RFLAGS"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_PENDING_DBG_EXC, "G. Pend Dbg Exc"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_SYSENTER_ESP, "G. SYSENTER ESP"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_GUEST_IA32_SYSENTER_EIP, "G. SYSENTER EIP"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_HOST_IA32_CR0, "H. CR0"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_HOST_IA32_CR3, "H. CR3"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_HOST_IA32_CR4, "H. CR4"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_HOST_IA32_FS_BASE, "H. FS Base"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_HOST_IA32_GS_BASE, "H. GS Base"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_HOST_IA32_TR_BASE, "H. TR Base"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_HOST_IA32_GDTR_BASE, "H. GDTR Base"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_HOST_IA32_IDTR_BASE, "H. IDTR Base"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_HOST_IA32_SYSENTER_ESP, "H. SYSENTER ESP"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_HOST_IA32_SYSENTER_EIP, "H. SYSENTER EIP"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_HOST_IA32_RSP, "H. RSP"); DPRINTF("\n"); vmx_dump_vmcs_field(VMCS_HOST_IA32_RIP, "H. RIP"); DPRINTF("\n"); } /* * vmx_vcpu_dump_regs * * Debug function to print vcpu regs from the current vcpu * note - vmcs for 'vcpu' must be on this pcpu. * * Parameters: * vcpu - vcpu whose registers should be dumped */ void vmx_vcpu_dump_regs(struct vcpu *vcpu) { uint64_t r; int i; struct vmx_msr_store *msr_store; /* XXX reformat this for 32 bit guest as needed */ DPRINTF("vcpu @ %p in %s mode\n", vcpu, vmm_decode_cpu_mode(vcpu)); i = vmm_get_guest_cpu_cpl(vcpu); if (i == -1) DPRINTF(" CPL=unknown\n"); else DPRINTF(" CPL=%d\n", i); DPRINTF(" rax=0x%016llx rbx=0x%016llx rcx=0x%016llx\n", vcpu->vc_gueststate.vg_rax, vcpu->vc_gueststate.vg_rbx, vcpu->vc_gueststate.vg_rcx); DPRINTF(" rdx=0x%016llx rbp=0x%016llx rdi=0x%016llx\n", vcpu->vc_gueststate.vg_rdx, vcpu->vc_gueststate.vg_rbp, vcpu->vc_gueststate.vg_rdi); DPRINTF(" rsi=0x%016llx r8=0x%016llx r9=0x%016llx\n", vcpu->vc_gueststate.vg_rsi, vcpu->vc_gueststate.vg_r8, vcpu->vc_gueststate.vg_r9); DPRINTF(" r10=0x%016llx r11=0x%016llx r12=0x%016llx\n", vcpu->vc_gueststate.vg_r10, vcpu->vc_gueststate.vg_r11, vcpu->vc_gueststate.vg_r12); DPRINTF(" r13=0x%016llx r14=0x%016llx r15=0x%016llx\n", vcpu->vc_gueststate.vg_r13, vcpu->vc_gueststate.vg_r14, vcpu->vc_gueststate.vg_r15); DPRINTF(" rip=0x%016llx rsp=", vcpu->vc_gueststate.vg_rip); if (vmread(VMCS_GUEST_IA32_RSP, &r)) DPRINTF("(error reading)\n"); else DPRINTF("0x%016llx\n", r); DPRINTF(" rflags="); if (vmread(VMCS_GUEST_IA32_RFLAGS, &r)) DPRINTF("(error reading)\n"); else { DPRINTF("0x%016llx ", r); vmm_decode_rflags(r); } DPRINTF(" cr0="); if (vmread(VMCS_GUEST_IA32_CR0, &r)) DPRINTF("(error reading)\n"); else { DPRINTF("0x%016llx ", r); vmm_decode_cr0(r); } DPRINTF(" cr2=0x%016llx\n", vcpu->vc_gueststate.vg_cr2); DPRINTF(" cr3="); if (vmread(VMCS_GUEST_IA32_CR3, &r)) DPRINTF("(error reading)\n"); else { DPRINTF("0x%016llx ", r); vmm_decode_cr3(r); } DPRINTF(" cr4="); if (vmread(VMCS_GUEST_IA32_CR4, &r)) DPRINTF("(error reading)\n"); else { DPRINTF("0x%016llx ", r); vmm_decode_cr4(r); } DPRINTF(" --Guest Segment Info--\n"); DPRINTF(" cs="); if (vmread(VMCS_GUEST_IA32_CS_SEL, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%04llx rpl=%lld", r, r & 0x3); DPRINTF(" base="); if (vmread(VMCS_GUEST_IA32_CS_BASE, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%016llx", r); DPRINTF(" limit="); if (vmread(VMCS_GUEST_IA32_CS_LIMIT, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%016llx", r); DPRINTF(" a/r="); if (vmread(VMCS_GUEST_IA32_CS_AR, &r)) DPRINTF("(error reading)\n"); else { DPRINTF("0x%04llx\n ", r); vmm_segment_desc_decode(r); } DPRINTF(" ds="); if (vmread(VMCS_GUEST_IA32_DS_SEL, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%04llx rpl=%lld", r, r & 0x3); DPRINTF(" base="); if (vmread(VMCS_GUEST_IA32_DS_BASE, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%016llx", r); DPRINTF(" limit="); if (vmread(VMCS_GUEST_IA32_DS_LIMIT, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%016llx", r); DPRINTF(" a/r="); if (vmread(VMCS_GUEST_IA32_DS_AR, &r)) DPRINTF("(error reading)\n"); else { DPRINTF("0x%04llx\n ", r); vmm_segment_desc_decode(r); } DPRINTF(" es="); if (vmread(VMCS_GUEST_IA32_ES_SEL, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%04llx rpl=%lld", r, r & 0x3); DPRINTF(" base="); if (vmread(VMCS_GUEST_IA32_ES_BASE, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%016llx", r); DPRINTF(" limit="); if (vmread(VMCS_GUEST_IA32_ES_LIMIT, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%016llx", r); DPRINTF(" a/r="); if (vmread(VMCS_GUEST_IA32_ES_AR, &r)) DPRINTF("(error reading)\n"); else { DPRINTF("0x%04llx\n ", r); vmm_segment_desc_decode(r); } DPRINTF(" fs="); if (vmread(VMCS_GUEST_IA32_FS_SEL, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%04llx rpl=%lld", r, r & 0x3); DPRINTF(" base="); if (vmread(VMCS_GUEST_IA32_FS_BASE, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%016llx", r); DPRINTF(" limit="); if (vmread(VMCS_GUEST_IA32_FS_LIMIT, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%016llx", r); DPRINTF(" a/r="); if (vmread(VMCS_GUEST_IA32_FS_AR, &r)) DPRINTF("(error reading)\n"); else { DPRINTF("0x%04llx\n ", r); vmm_segment_desc_decode(r); } DPRINTF(" gs="); if (vmread(VMCS_GUEST_IA32_GS_SEL, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%04llx rpl=%lld", r, r & 0x3); DPRINTF(" base="); if (vmread(VMCS_GUEST_IA32_GS_BASE, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%016llx", r); DPRINTF(" limit="); if (vmread(VMCS_GUEST_IA32_GS_LIMIT, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%016llx", r); DPRINTF(" a/r="); if (vmread(VMCS_GUEST_IA32_GS_AR, &r)) DPRINTF("(error reading)\n"); else { DPRINTF("0x%04llx\n ", r); vmm_segment_desc_decode(r); } DPRINTF(" ss="); if (vmread(VMCS_GUEST_IA32_SS_SEL, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%04llx rpl=%lld", r, r & 0x3); DPRINTF(" base="); if (vmread(VMCS_GUEST_IA32_SS_BASE, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%016llx", r); DPRINTF(" limit="); if (vmread(VMCS_GUEST_IA32_SS_LIMIT, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%016llx", r); DPRINTF(" a/r="); if (vmread(VMCS_GUEST_IA32_SS_AR, &r)) DPRINTF("(error reading)\n"); else { DPRINTF("0x%04llx\n ", r); vmm_segment_desc_decode(r); } DPRINTF(" tr="); if (vmread(VMCS_GUEST_IA32_TR_SEL, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%04llx", r); DPRINTF(" base="); if (vmread(VMCS_GUEST_IA32_TR_BASE, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%016llx", r); DPRINTF(" limit="); if (vmread(VMCS_GUEST_IA32_TR_LIMIT, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%016llx", r); DPRINTF(" a/r="); if (vmread(VMCS_GUEST_IA32_TR_AR, &r)) DPRINTF("(error reading)\n"); else { DPRINTF("0x%04llx\n ", r); vmm_segment_desc_decode(r); } DPRINTF(" gdtr base="); if (vmread(VMCS_GUEST_IA32_GDTR_BASE, &r)) DPRINTF("(error reading) "); else DPRINTF("0x%016llx", r); DPRINTF(" limit="); if (vmread(VMCS_GUEST_IA32_GDTR_LIMIT, &r)) DPRINTF("(error reading)\n"); else DPRINTF("0x%016llx\n", r); DPRINTF(" idtr base="); if (vmread(VMCS_GUEST_IA32_IDTR_BASE, &r)) DPRINTF("(error reading) "); else DPRINTF("0x%016llx", r); DPRINTF(" limit="); if (vmread(VMCS_GUEST_IA32_IDTR_LIMIT, &r)) DPRINTF("(error reading)\n"); else DPRINTF("0x%016llx\n", r); DPRINTF(" ldtr="); if (vmread(VMCS_GUEST_IA32_LDTR_SEL, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%04llx", r); DPRINTF(" base="); if (vmread(VMCS_GUEST_IA32_LDTR_BASE, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%016llx", r); DPRINTF(" limit="); if (vmread(VMCS_GUEST_IA32_LDTR_LIMIT, &r)) DPRINTF("(error reading)"); else DPRINTF("0x%016llx", r); DPRINTF(" a/r="); if (vmread(VMCS_GUEST_IA32_LDTR_AR, &r)) DPRINTF("(error reading)\n"); else { DPRINTF("0x%04llx\n ", r); vmm_segment_desc_decode(r); } DPRINTF(" --Guest MSRs @ 0x%016llx (paddr: 0x%016llx)--\n", (uint64_t)vcpu->vc_vmx_msr_exit_save_va, (uint64_t)vcpu->vc_vmx_msr_exit_save_pa); msr_store = (struct vmx_msr_store *)vcpu->vc_vmx_msr_exit_save_va; for (i = 0; i < VCPU_REGS_NMSRS; i++) { DPRINTF(" MSR %d @ %p : 0x%08llx (%s), " "value=0x%016llx ", i, &msr_store[i], msr_store[i].vms_index, msr_name_decode(msr_store[i].vms_index), msr_store[i].vms_data); vmm_decode_msr_value(msr_store[i].vms_index, msr_store[i].vms_data); } } /* * msr_name_decode * * Returns a human-readable name for the MSR supplied in 'msr'. * * Parameters: * msr - The MSR to decode * * Return value: * NULL-terminated character string containing the name of the MSR requested */ const char * msr_name_decode(uint32_t msr) { /* * Add as needed. Also consider adding a decode function when * adding to this table. */ switch (msr) { case MSR_TSC: return "TSC"; case MSR_APICBASE: return "APIC base"; case MSR_IA32_FEATURE_CONTROL: return "IA32 feature control"; case MSR_PERFCTR0: return "perf counter 0"; case MSR_PERFCTR1: return "perf counter 1"; case MSR_TEMPERATURE_TARGET: return "temperature target"; case MSR_MTRRcap: return "MTRR cap"; case MSR_PERF_STATUS: return "perf status"; case MSR_PERF_CTL: return "perf control"; case MSR_MTRRvarBase: return "MTRR variable base"; case MSR_MTRRfix64K_00000: return "MTRR fixed 64K"; case MSR_MTRRfix16K_80000: return "MTRR fixed 16K"; case MSR_MTRRfix4K_C0000: return "MTRR fixed 4K"; case MSR_CR_PAT: return "PAT"; case MSR_MTRRdefType: return "MTRR default type"; case MSR_EFER: return "EFER"; case MSR_STAR: return "STAR"; case MSR_LSTAR: return "LSTAR"; case MSR_CSTAR: return "CSTAR"; case MSR_SFMASK: return "SFMASK"; case MSR_FSBASE: return "FSBASE"; case MSR_GSBASE: return "GSBASE"; case MSR_KERNELGSBASE: return "KGSBASE"; case MSR_MISC_ENABLE: return "Misc Enable"; default: return "Unknown MSR"; } } /* * vmm_segment_desc_decode * * Debug function to print segment information for supplied descriptor * * Parameters: * val - The A/R bytes for the segment descriptor to decode */ void vmm_segment_desc_decode(uint64_t val) { uint16_t ar; uint8_t g, type, s, dpl, p, dib, l; uint32_t unusable; /* Exit early on unusable descriptors */ unusable = val & 0x10000; if (unusable) { DPRINTF("(unusable)\n"); return; } ar = (uint16_t)val; g = (ar & 0x8000) >> 15; dib = (ar & 0x4000) >> 14; l = (ar & 0x2000) >> 13; p = (ar & 0x80) >> 7; dpl = (ar & 0x60) >> 5; s = (ar & 0x10) >> 4; type = (ar & 0xf); DPRINTF("granularity=%d dib=%d l(64 bit)=%d present=%d sys=%d ", g, dib, l, p, s); DPRINTF("type="); if (!s) { switch (type) { case SDT_SYSLDT: DPRINTF("ldt\n"); break; case SDT_SYS386TSS: DPRINTF("tss (available)\n"); break; case SDT_SYS386BSY: DPRINTF("tss (busy)\n"); break; case SDT_SYS386CGT: DPRINTF("call gate\n"); break; case SDT_SYS386IGT: DPRINTF("interrupt gate\n"); break; case SDT_SYS386TGT: DPRINTF("trap gate\n"); break; /* XXX handle 32 bit segment types by inspecting mode */ default: DPRINTF("unknown"); } } else { switch (type + 16) { case SDT_MEMRO: DPRINTF("data, r/o\n"); break; case SDT_MEMROA: DPRINTF("data, r/o, accessed\n"); break; case SDT_MEMRW: DPRINTF("data, r/w\n"); break; case SDT_MEMRWA: DPRINTF("data, r/w, accessed\n"); break; case SDT_MEMROD: DPRINTF("data, r/o, expand down\n"); break; case SDT_MEMRODA: DPRINTF("data, r/o, expand down, " "accessed\n"); break; case SDT_MEMRWD: DPRINTF("data, r/w, expand down\n"); break; case SDT_MEMRWDA: DPRINTF("data, r/w, expand down, " "accessed\n"); break; case SDT_MEME: DPRINTF("code, x only\n"); break; case SDT_MEMEA: DPRINTF("code, x only, accessed\n"); case SDT_MEMER: DPRINTF("code, r/x\n"); break; case SDT_MEMERA: DPRINTF("code, r/x, accessed\n"); break; case SDT_MEMEC: DPRINTF("code, x only, conforming\n"); break; case SDT_MEMEAC: DPRINTF("code, x only, conforming, " "accessed\n"); break; case SDT_MEMERC: DPRINTF("code, r/x, conforming\n"); break; case SDT_MEMERAC: DPRINTF("code, r/x, conforming, accessed\n"); break; } } } void vmm_decode_cr0(uint64_t cr0) { struct vmm_reg_debug_info cr0_info[11] = { { CR0_PG, "PG ", "pg " }, { CR0_CD, "CD ", "cd " }, { CR0_NW, "NW ", "nw " }, { CR0_AM, "AM ", "am " }, { CR0_WP, "WP ", "wp " }, { CR0_NE, "NE ", "ne " }, { CR0_ET, "ET ", "et " }, { CR0_TS, "TS ", "ts " }, { CR0_EM, "EM ", "em " }, { CR0_MP, "MP ", "mp " }, { CR0_PE, "PE", "pe" } }; uint8_t i; DPRINTF("("); for (i = 0; i < nitems(cr0_info); i++) if (cr0 & cr0_info[i].vrdi_bit) DPRINTF("%s", cr0_info[i].vrdi_present); else DPRINTF("%s", cr0_info[i].vrdi_absent); DPRINTF(")\n"); } void vmm_decode_cr3(uint64_t cr3) { struct vmm_reg_debug_info cr3_info[2] = { { CR3_PWT, "PWT ", "pwt "}, { CR3_PCD, "PCD", "pcd"} }; uint64_t cr4; uint8_t i; if (vmread(VMCS_GUEST_IA32_CR4, &cr4)) { DPRINTF("(error)\n"); return; } /* If CR4.PCIDE = 0, interpret CR3.PWT and CR3.PCD */ if ((cr4 & CR4_PCIDE) == 0) { DPRINTF("("); for (i = 0 ; i < nitems(cr3_info) ; i++) if (cr3 & cr3_info[i].vrdi_bit) DPRINTF("%s", cr3_info[i].vrdi_present); else DPRINTF("%s", cr3_info[i].vrdi_absent); DPRINTF(")\n"); } else { DPRINTF("(pcid=0x%llx)\n", cr3 & 0xFFF); } } void vmm_decode_cr4(uint64_t cr4) { struct vmm_reg_debug_info cr4_info[19] = { { CR4_PKE, "PKE ", "pke "}, { CR4_SMAP, "SMAP ", "smap "}, { CR4_SMEP, "SMEP ", "smep "}, { CR4_OSXSAVE, "OSXSAVE ", "osxsave "}, { CR4_PCIDE, "PCIDE ", "pcide "}, { CR4_FSGSBASE, "FSGSBASE ", "fsgsbase "}, { CR4_SMXE, "SMXE ", "smxe "}, { CR4_VMXE, "VMXE ", "vmxe "}, { CR4_OSXMMEXCPT, "OSXMMEXCPT ", "osxmmexcpt "}, { CR4_OSFXSR, "OSFXSR ", "osfxsr "}, { CR4_PCE, "PCE ", "pce "}, { CR4_PGE, "PGE ", "pge "}, { CR4_MCE, "MCE ", "mce "}, { CR4_PAE, "PAE ", "pae "}, { CR4_PSE, "PSE ", "pse "}, { CR4_DE, "DE ", "de "}, { CR4_TSD, "TSD ", "tsd "}, { CR4_PVI, "PVI ", "pvi "}, { CR4_VME, "VME", "vme"} }; uint8_t i; DPRINTF("("); for (i = 0; i < nitems(cr4_info); i++) if (cr4 & cr4_info[i].vrdi_bit) DPRINTF("%s", cr4_info[i].vrdi_present); else DPRINTF("%s", cr4_info[i].vrdi_absent); DPRINTF(")\n"); } void vmm_decode_apicbase_msr_value(uint64_t apicbase) { struct vmm_reg_debug_info apicbase_info[3] = { { APICBASE_BSP, "BSP ", "bsp "}, { APICBASE_ENABLE_X2APIC, "X2APIC ", "x2apic "}, { APICBASE_GLOBAL_ENABLE, "GLB_EN", "glb_en"} }; uint8_t i; DPRINTF("("); for (i = 0; i < nitems(apicbase_info); i++) if (apicbase & apicbase_info[i].vrdi_bit) DPRINTF("%s", apicbase_info[i].vrdi_present); else DPRINTF("%s", apicbase_info[i].vrdi_absent); DPRINTF(")\n"); } void vmm_decode_ia32_fc_value(uint64_t fcr) { struct vmm_reg_debug_info fcr_info[4] = { { IA32_FEATURE_CONTROL_LOCK, "LOCK ", "lock "}, { IA32_FEATURE_CONTROL_SMX_EN, "SMX ", "smx "}, { IA32_FEATURE_CONTROL_VMX_EN, "VMX ", "vmx "}, { IA32_FEATURE_CONTROL_SENTER_EN, "SENTER ", "senter "} }; uint8_t i; DPRINTF("("); for (i = 0; i < nitems(fcr_info); i++) if (fcr & fcr_info[i].vrdi_bit) DPRINTF("%s", fcr_info[i].vrdi_present); else DPRINTF("%s", fcr_info[i].vrdi_absent); if (fcr & IA32_FEATURE_CONTROL_SENTER_EN) DPRINTF(" [SENTER param = 0x%llx]", (fcr & IA32_FEATURE_CONTROL_SENTER_PARAM_MASK) >> 8); DPRINTF(")\n"); } void vmm_decode_mtrrcap_value(uint64_t val) { struct vmm_reg_debug_info mtrrcap_info[3] = { { MTRRcap_FIXED, "FIXED ", "fixed "}, { MTRRcap_WC, "WC ", "wc "}, { MTRRcap_SMRR, "SMRR ", "smrr "} }; uint8_t i; DPRINTF("("); for (i = 0; i < nitems(mtrrcap_info); i++) if (val & mtrrcap_info[i].vrdi_bit) DPRINTF("%s", mtrrcap_info[i].vrdi_present); else DPRINTF("%s", mtrrcap_info[i].vrdi_absent); if (val & MTRRcap_FIXED) DPRINTF(" [nr fixed ranges = 0x%llx]", (val & 0xff)); DPRINTF(")\n"); } void vmm_decode_perf_status_value(uint64_t val) { DPRINTF("(pstate ratio = 0x%llx)\n", (val & 0xffff)); } void vmm_decode_perf_ctl_value(uint64_t val) { DPRINTF("(%s ", (val & PERF_CTL_TURBO) ? "TURBO" : "turbo"); DPRINTF("pstate req = 0x%llx)\n", (val & 0xfffF)); } void vmm_decode_mtrrdeftype_value(uint64_t mtrrdeftype) { struct vmm_reg_debug_info mtrrdeftype_info[2] = { { MTRRdefType_FIXED_ENABLE, "FIXED ", "fixed "}, { MTRRdefType_ENABLE, "ENABLED ", "enabled "}, }; uint8_t i; int type; DPRINTF("("); for (i = 0; i < nitems(mtrrdeftype_info); i++) if (mtrrdeftype & mtrrdeftype_info[i].vrdi_bit) DPRINTF("%s", mtrrdeftype_info[i].vrdi_present); else DPRINTF("%s", mtrrdeftype_info[i].vrdi_absent); DPRINTF("type = "); type = mtrr2mrt(mtrrdeftype & 0xff); switch (type) { case MDF_UNCACHEABLE: DPRINTF("UC"); break; case MDF_WRITECOMBINE: DPRINTF("WC"); break; case MDF_WRITETHROUGH: DPRINTF("WT"); break; case MDF_WRITEPROTECT: DPRINTF("RO"); break; case MDF_WRITEBACK: DPRINTF("WB"); break; case MDF_UNKNOWN: default: DPRINTF("??"); break; } DPRINTF(")\n"); } void vmm_decode_efer_value(uint64_t efer) { struct vmm_reg_debug_info efer_info[4] = { { EFER_SCE, "SCE ", "sce "}, { EFER_LME, "LME ", "lme "}, { EFER_LMA, "LMA ", "lma "}, { EFER_NXE, "NXE", "nxe"}, }; uint8_t i; DPRINTF("("); for (i = 0; i < nitems(efer_info); i++) if (efer & efer_info[i].vrdi_bit) DPRINTF("%s", efer_info[i].vrdi_present); else DPRINTF("%s", efer_info[i].vrdi_absent); DPRINTF(")\n"); } void vmm_decode_msr_value(uint64_t msr, uint64_t val) { switch (msr) { case MSR_APICBASE: vmm_decode_apicbase_msr_value(val); break; case MSR_IA32_FEATURE_CONTROL: vmm_decode_ia32_fc_value(val); break; case MSR_MTRRcap: vmm_decode_mtrrcap_value(val); break; case MSR_PERF_STATUS: vmm_decode_perf_status_value(val); break; case MSR_PERF_CTL: vmm_decode_perf_ctl_value(val); break; case MSR_MTRRdefType: vmm_decode_mtrrdeftype_value(val); break; case MSR_EFER: vmm_decode_efer_value(val); break; case MSR_MISC_ENABLE: vmm_decode_misc_enable_value(val); break; default: DPRINTF("\n"); } } void vmm_decode_rflags(uint64_t rflags) { struct vmm_reg_debug_info rflags_info[16] = { { PSL_C, "CF ", "cf "}, { PSL_PF, "PF ", "pf "}, { PSL_AF, "AF ", "af "}, { PSL_Z, "ZF ", "zf "}, { PSL_N, "SF ", "sf "}, /* sign flag */ { PSL_T, "TF ", "tf "}, { PSL_I, "IF ", "if "}, { PSL_D, "DF ", "df "}, { PSL_V, "OF ", "of "}, /* overflow flag */ { PSL_NT, "NT ", "nt "}, { PSL_RF, "RF ", "rf "}, { PSL_VM, "VM ", "vm "}, { PSL_AC, "AC ", "ac "}, { PSL_VIF, "VIF ", "vif "}, { PSL_VIP, "VIP ", "vip "}, { PSL_ID, "ID ", "id "}, }; uint8_t i, iopl; DPRINTF("("); for (i = 0; i < nitems(rflags_info); i++) if (rflags & rflags_info[i].vrdi_bit) DPRINTF("%s", rflags_info[i].vrdi_present); else DPRINTF("%s", rflags_info[i].vrdi_absent); iopl = (rflags & PSL_IOPL) >> 12; DPRINTF("IOPL=%d", iopl); DPRINTF(")\n"); } void vmm_decode_misc_enable_value(uint64_t misc) { struct vmm_reg_debug_info misc_info[10] = { { MISC_ENABLE_FAST_STRINGS, "FSE ", "fse "}, { MISC_ENABLE_TCC, "TCC ", "tcc "}, { MISC_ENABLE_PERF_MON_AVAILABLE, "PERF ", "perf "}, { MISC_ENABLE_BTS_UNAVAILABLE, "BTSU ", "btsu "}, { MISC_ENABLE_PEBS_UNAVAILABLE, "PEBSU ", "pebsu "}, { MISC_ENABLE_EIST_ENABLED, "EIST ", "eist "}, { MISC_ENABLE_ENABLE_MONITOR_FSM, "MFSM ", "mfsm "}, { MISC_ENABLE_LIMIT_CPUID_MAXVAL, "CMAX ", "cmax "}, { MISC_ENABLE_xTPR_MESSAGE_DISABLE, "xTPRD ", "xtprd "}, { MISC_ENABLE_XD_BIT_DISABLE, "NXD", "nxd"}, }; uint8_t i; DPRINTF("("); for (i = 0; i < nitems(misc_info); i++) if (misc & misc_info[i].vrdi_bit) DPRINTF("%s", misc_info[i].vrdi_present); else DPRINTF("%s", misc_info[i].vrdi_absent); DPRINTF(")\n"); } const char * vmm_decode_cpu_mode(struct vcpu *vcpu) { int mode = vmm_get_guest_cpu_mode(vcpu); switch (mode) { case VMM_CPU_MODE_REAL: return "real"; case VMM_CPU_MODE_PROT: return "16 bit protected"; case VMM_CPU_MODE_PROT32: return "32 bit protected"; case VMM_CPU_MODE_COMPAT: return "compatibility"; case VMM_CPU_MODE_LONG: return "long"; default: return "unknown"; } } #endif /* VMM_DEBUG */
18 18 18 155 96 92 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 /* $OpenBSD: vfs_default.c,v 1.51 2022/04/27 14:52:25 claudio Exp $ */ /* * Portions of this code are: * * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/mount.h> #include <sys/vnode.h> #include <sys/namei.h> #include <sys/pool.h> #include <sys/event.h> #include <sys/specdev.h> int filt_generic_readwrite(struct knote *, long); void filt_generic_detach(struct knote *); /* * Eliminate all activity associated with the requested vnode * and with all vnodes aliased to the requested vnode. */ int vop_generic_revoke(void *v) { struct vop_revoke_args *ap = v; struct vnode *vp, *vq; struct proc *p = curproc; #ifdef DIAGNOSTIC if ((ap->a_flags & REVOKEALL) == 0) panic("vop_generic_revoke"); #endif vp = ap->a_vp; while (vp->v_type == VBLK && vp->v_specinfo != NULL && vp->v_specmountpoint != NULL) { struct mount *mp = vp->v_specmountpoint; /* * If we have a mount point associated with the vnode, we must * flush it out now, as to not leave a dangling zombie mount * point laying around in VFS. */ if (!vfs_busy(mp, VB_WRITE|VB_WAIT)) { dounmount(mp, MNT_FORCE | MNT_DOOMED, p); break; } } if (vp->v_flag & VALIASED) { /* * If a vgone (or vclean) is already in progress, * wait until it is done and return. */ mtx_enter(&vnode_mtx); if (vp->v_lflag & VXLOCK) { vp->v_lflag |= VXWANT; msleep_nsec(vp, &vnode_mtx, PINOD, "vop_generic_revokeall", INFSLP); mtx_leave(&vnode_mtx); return(0); } /* * Ensure that vp will not be vgone'd while we * are eliminating its aliases. */ vp->v_lflag |= VXLOCK; mtx_leave(&vnode_mtx); while (vp->v_flag & VALIASED) { SLIST_FOREACH(vq, vp->v_hashchain, v_specnext) { if (vq->v_rdev != vp->v_rdev || vq->v_type != vp->v_type || vp == vq) continue; vgonel(vq, p); break; } } /* * Remove the lock so that vgone below will * really eliminate the vnode after which time * vgone will awaken any sleepers. */ mtx_enter(&vnode_mtx); vp->v_lflag &= ~VXLOCK; mtx_leave(&vnode_mtx); } vgonel(vp, p); return (0); } int vop_generic_badop(void *v) { panic("%s", __func__); } int vop_generic_bmap(void *v) { struct vop_bmap_args *ap = v; if (ap->a_vpp) *ap->a_vpp = ap->a_vp; if (ap->a_bnp) *ap->a_bnp = ap->a_bn; if (ap->a_runp) *ap->a_runp = 0; return (0); } int vop_generic_bwrite(void *v) { struct vop_bwrite_args *ap = v; return (bwrite(ap->a_bp)); } int vop_generic_abortop(void *v) { struct vop_abortop_args *ap = v; if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) pool_put(&namei_pool, ap->a_cnp->cn_pnbuf); return (0); } const struct filterops generic_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, .f_detach = filt_generic_detach, .f_event = filt_generic_readwrite, }; int vop_generic_kqfilter(void *v) { struct vop_kqfilter_args *ap = v; struct knote *kn = ap->a_kn; switch (kn->kn_filter) { case EVFILT_READ: case EVFILT_WRITE: kn->kn_fop = &generic_filtops; break; default: return (EINVAL); } return (0); } /* Trivial lookup routine that always fails. */ int vop_generic_lookup(void *v) { struct vop_lookup_args *ap = v; *ap->a_vpp = NULL; return (ENOTDIR); } void filt_generic_detach(struct knote *kn) { } int filt_generic_readwrite(struct knote *kn, long hint) { /* * filesystem is gone, so set the EOF flag and schedule * the knote for deletion. */ if (hint == NOTE_REVOKE) { kn->kn_flags |= (EV_EOF | EV_ONESHOT); return (1); } kn->kn_data = 0; return (1); }
11 11 11 11 9 219 220 209 25 221 221 211 221 11 221 11 11 210 210 211 11 11 2 2 2 2 2 2 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 /* $OpenBSD: virtio.c,v 1.25 2024/05/24 10:05:55 jsg Exp $ */ /* $NetBSD: virtio.c,v 1.3 2011/11/02 23:05:52 njoly Exp $ */ /* * Copyright (c) 2012 Stefan Fritsch, Alexander Fiveg. * Copyright (c) 2010 Minoura Makoto. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> #include <sys/atomic.h> #include <sys/malloc.h> #include <dev/pv/virtioreg.h> #include <dev/pv/virtiovar.h> #if VIRTIO_DEBUG #define VIRTIO_ASSERT(x) KASSERT(x) #else #define VIRTIO_ASSERT(x) #endif void virtio_init_vq(struct virtio_softc *, struct virtqueue *); void vq_free_entry(struct virtqueue *, struct vq_entry *); struct vq_entry *vq_alloc_entry(struct virtqueue *); struct cfdriver virtio_cd = { NULL, "virtio", DV_DULL }; static const char * const virtio_device_name[] = { "Unknown (0)", /* 0 */ "Network", /* 1 */ "Block", /* 2 */ "Console", /* 3 */ "Entropy", /* 4 */ "Memory Balloon", /* 5 */ "IO Memory", /* 6 */ "Rpmsg", /* 7 */ "SCSI host", /* 8 */ "9P Transport", /* 9 */ "mac80211 wlan", /* 10 */ NULL, /* 11 */ NULL, /* 12 */ NULL, /* 13 */ NULL, /* 14 */ NULL, /* 15 */ "GPU", /* 16 */ }; #define NDEVNAMES (sizeof(virtio_device_name)/sizeof(char*)) const char * virtio_device_string(int id) { return id < NDEVNAMES ? virtio_device_name[id] : "Unknown"; } #if VIRTIO_DEBUG static const struct virtio_feature_name transport_feature_names[] = { { VIRTIO_F_NOTIFY_ON_EMPTY, "NotifyOnEmpty"}, { VIRTIO_F_RING_INDIRECT_DESC, "RingIndirectDesc"}, { VIRTIO_F_RING_EVENT_IDX, "RingEventIdx"}, { VIRTIO_F_BAD_FEATURE, "BadFeature"}, { VIRTIO_F_VERSION_1, "Version1"}, { 0, NULL} }; void virtio_log_features(uint64_t host, uint64_t neg, const struct virtio_feature_name *guest_feature_names) { const struct virtio_feature_name *namep; int i; char c; uint64_t bit; for (i = 0; i < 64; i++) { if (i == 30) { /* * VIRTIO_F_BAD_FEATURE is only used for * checking correct negotiation */ continue; } bit = 1ULL << i; if ((host&bit) == 0) continue; namep = guest_feature_names; while (namep->bit && namep->bit != bit) namep++; if (namep->name == NULL) { namep = transport_feature_names; while (namep->bit && namep->bit != bit) namep++; } c = (neg&bit) ? '+' : '-'; if (namep->name) printf(" %c%s", c, namep->name); else printf(" %cUnknown(%d)", c, i); } } #endif /* * Reset the device. */ /* * To reset the device to a known state, do following: * virtio_reset(sc); // this will stop the device activity * <dequeue finished requests>; // virtio_dequeue() still can be called * <revoke pending requests in the vqs if any>; * virtio_reinit_start(sc); // dequeue prohibited * <some other initialization>; * virtio_reinit_end(sc); // device activated; enqueue allowed * Once attached, features are assumed to not change again. */ void virtio_reset(struct virtio_softc *sc) { virtio_device_reset(sc); sc->sc_active_features = 0; } void virtio_reinit_start(struct virtio_softc *sc) { int i; virtio_set_status(sc, VIRTIO_CONFIG_DEVICE_STATUS_ACK); virtio_set_status(sc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER); virtio_negotiate_features(sc, NULL); for (i = 0; i < sc->sc_nvqs; i++) { int n; struct virtqueue *vq = &sc->sc_vqs[i]; n = virtio_read_queue_size(sc, vq->vq_index); if (n == 0) /* vq disappeared */ continue; if (n != vq->vq_num) { panic("%s: virtqueue size changed, vq index %d", sc->sc_dev.dv_xname, vq->vq_index); } virtio_init_vq(sc, vq); virtio_setup_queue(sc, vq, vq->vq_dmamap->dm_segs[0].ds_addr); } } void virtio_reinit_end(struct virtio_softc *sc) { virtio_set_status(sc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK); } /* * dmamap sync operations for a virtqueue. */ static inline void vq_sync_descs(struct virtio_softc *sc, struct virtqueue *vq, int ops) { /* availoffset == sizeof(vring_desc)*vq_num */ bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap, 0, vq->vq_availoffset, ops); } static inline void vq_sync_aring(struct virtio_softc *sc, struct virtqueue *vq, int ops) { bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap, vq->vq_availoffset, offsetof(struct vring_avail, ring) + vq->vq_num * sizeof(uint16_t), ops); } static inline void vq_sync_uring(struct virtio_softc *sc, struct virtqueue *vq, int ops) { bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap, vq->vq_usedoffset, offsetof(struct vring_used, ring) + vq->vq_num * sizeof(struct vring_used_elem), ops); } static inline void vq_sync_indirect(struct virtio_softc *sc, struct virtqueue *vq, int slot, int ops) { int offset = vq->vq_indirectoffset + sizeof(struct vring_desc) * vq->vq_maxnsegs * slot; bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap, offset, sizeof(struct vring_desc) * vq->vq_maxnsegs, ops); } /* * Scan vq, bus_dmamap_sync for the vqs (not for the payload), * and calls (*vq_done)() if some entries are consumed. * For use in transport specific irq handlers. */ int virtio_check_vqs(struct virtio_softc *sc) { int i, r = 0; /* going backwards is better for if_vio */ for (i = sc->sc_nvqs - 1; i >= 0; i--) r |= virtio_check_vq(sc, &sc->sc_vqs[i]); return r; } int virtio_check_vq(struct virtio_softc *sc, struct virtqueue *vq) { if (vq->vq_queued) { vq->vq_queued = 0; vq_sync_aring(sc, vq, BUS_DMASYNC_POSTWRITE); } vq_sync_uring(sc, vq, BUS_DMASYNC_POSTREAD); if (vq->vq_used_idx != vq->vq_used->idx) { if (vq->vq_done) return (vq->vq_done)(vq); } return 0; } /* * Initialize vq structure. */ void virtio_init_vq(struct virtio_softc *sc, struct virtqueue *vq) { int i, j; int vq_size = vq->vq_num; memset(vq->vq_vaddr, 0, vq->vq_bytesize); /* build the indirect descriptor chain */ if (vq->vq_indirect != NULL) { struct vring_desc *vd; for (i = 0; i < vq_size; i++) { vd = vq->vq_indirect; vd += vq->vq_maxnsegs * i; for (j = 0; j < vq->vq_maxnsegs-1; j++) vd[j].next = j + 1; } } /* free slot management */ SLIST_INIT(&vq->vq_freelist); /* * virtio_enqueue_trim needs monotonely raising entries, therefore * initialize in reverse order */ for (i = vq_size - 1; i >= 0; i--) { SLIST_INSERT_HEAD(&vq->vq_freelist, &vq->vq_entries[i], qe_list); vq->vq_entries[i].qe_index = i; } /* enqueue/dequeue status */ vq->vq_avail_idx = 0; vq->vq_used_idx = 0; vq_sync_aring(sc, vq, BUS_DMASYNC_PREWRITE); vq_sync_uring(sc, vq, BUS_DMASYNC_PREREAD); vq->vq_queued = 1; } /* * Allocate/free a vq. * * maxnsegs denotes how much space should be allocated for indirect * descriptors. maxnsegs == 1 can be used to disable use indirect * descriptors for this queue. */ int virtio_alloc_vq(struct virtio_softc *sc, struct virtqueue *vq, int index, int maxsegsize, int maxnsegs, const char *name) { int vq_size, allocsize1, allocsize2, allocsize3, allocsize = 0; int rsegs, r, hdrlen; #define VIRTQUEUE_ALIGN(n) (((n)+(VIRTIO_PAGE_SIZE-1))& \ ~(VIRTIO_PAGE_SIZE-1)) memset(vq, 0, sizeof(*vq)); vq_size = virtio_read_queue_size(sc, index); if (vq_size == 0) { printf("virtqueue not exist, index %d for %s\n", index, name); goto err; } if (((vq_size - 1) & vq_size) != 0) panic("vq_size not power of two: %d", vq_size); hdrlen = virtio_has_feature(sc, VIRTIO_F_RING_EVENT_IDX) ? 3 : 2; /* allocsize1: descriptor table + avail ring + pad */ allocsize1 = VIRTQUEUE_ALIGN(sizeof(struct vring_desc) * vq_size + sizeof(uint16_t) * (hdrlen + vq_size)); /* allocsize2: used ring + pad */ allocsize2 = VIRTQUEUE_ALIGN(sizeof(uint16_t) * hdrlen + sizeof(struct vring_used_elem) * vq_size); /* allocsize3: indirect table */ if (sc->sc_indirect && maxnsegs > 1) allocsize3 = sizeof(struct vring_desc) * maxnsegs * vq_size; else allocsize3 = 0; allocsize = allocsize1 + allocsize2 + allocsize3; /* alloc and map the memory */ r = bus_dmamem_alloc(sc->sc_dmat, allocsize, VIRTIO_PAGE_SIZE, 0, &vq->vq_segs[0], 1, &rsegs, BUS_DMA_NOWAIT); if (r != 0) { printf("virtqueue %d for %s allocation failed, error %d\n", index, name, r); goto err; } r = bus_dmamem_map(sc->sc_dmat, &vq->vq_segs[0], 1, allocsize, (caddr_t*)&vq->vq_vaddr, BUS_DMA_NOWAIT); if (r != 0) { printf("virtqueue %d for %s map failed, error %d\n", index, name, r); goto err; } r = bus_dmamap_create(sc->sc_dmat, allocsize, 1, allocsize, 0, BUS_DMA_NOWAIT, &vq->vq_dmamap); if (r != 0) { printf("virtqueue %d for %s dmamap creation failed, " "error %d\n", index, name, r); goto err; } r = bus_dmamap_load(sc->sc_dmat, vq->vq_dmamap, vq->vq_vaddr, allocsize, NULL, BUS_DMA_NOWAIT); if (r != 0) { printf("virtqueue %d for %s dmamap load failed, error %d\n", index, name, r); goto err; } /* remember addresses and offsets for later use */ vq->vq_owner = sc; vq->vq_num = vq_size; vq->vq_mask = vq_size - 1; vq->vq_index = index; vq->vq_desc = vq->vq_vaddr; vq->vq_availoffset = sizeof(struct vring_desc)*vq_size; vq->vq_avail = (struct vring_avail*)(((char*)vq->vq_desc) + vq->vq_availoffset); vq->vq_usedoffset = allocsize1; vq->vq_used = (struct vring_used*)(((char*)vq->vq_desc) + vq->vq_usedoffset); if (allocsize3 > 0) { vq->vq_indirectoffset = allocsize1 + allocsize2; vq->vq_indirect = (void*)(((char*)vq->vq_desc) + vq->vq_indirectoffset); } vq->vq_bytesize = allocsize; vq->vq_maxnsegs = maxnsegs; /* free slot management */ vq->vq_entries = mallocarray(vq_size, sizeof(struct vq_entry), M_DEVBUF, M_NOWAIT | M_ZERO); if (vq->vq_entries == NULL) { r = ENOMEM; goto err; } virtio_init_vq(sc, vq); virtio_setup_queue(sc, vq, vq->vq_dmamap->dm_segs[0].ds_addr); #if VIRTIO_DEBUG printf("\nallocated %u byte for virtqueue %d for %s, size %d\n", allocsize, index, name, vq_size); if (allocsize3 > 0) printf("using %d byte (%d entries) indirect descriptors\n", allocsize3, maxnsegs * vq_size); #endif return 0; err: if (vq->vq_dmamap) bus_dmamap_destroy(sc->sc_dmat, vq->vq_dmamap); if (vq->vq_vaddr) bus_dmamem_unmap(sc->sc_dmat, vq->vq_vaddr, allocsize); if (vq->vq_segs[0].ds_addr) bus_dmamem_free(sc->sc_dmat, &vq->vq_segs[0], 1); memset(vq, 0, sizeof(*vq)); return -1; } int virtio_free_vq(struct virtio_softc *sc, struct virtqueue *vq) { struct vq_entry *qe; int i = 0; /* device must be already deactivated */ /* confirm the vq is empty */ SLIST_FOREACH(qe, &vq->vq_freelist, qe_list) { i++; } if (i != vq->vq_num) { printf("%s: freeing non-empty vq, index %d\n", sc->sc_dev.dv_xname, vq->vq_index); return EBUSY; } /* tell device that there's no virtqueue any longer */ virtio_setup_queue(sc, vq, 0); free(vq->vq_entries, M_DEVBUF, 0); bus_dmamap_unload(sc->sc_dmat, vq->vq_dmamap); bus_dmamap_destroy(sc->sc_dmat, vq->vq_dmamap); bus_dmamem_unmap(sc->sc_dmat, vq->vq_vaddr, vq->vq_bytesize); bus_dmamem_free(sc->sc_dmat, &vq->vq_segs[0], 1); memset(vq, 0, sizeof(*vq)); return 0; } /* * Free descriptor management. */ struct vq_entry * vq_alloc_entry(struct virtqueue *vq) { struct vq_entry *qe; if (SLIST_EMPTY(&vq->vq_freelist)) return NULL; qe = SLIST_FIRST(&vq->vq_freelist); SLIST_REMOVE_HEAD(&vq->vq_freelist, qe_list); return qe; } void vq_free_entry(struct virtqueue *vq, struct vq_entry *qe) { SLIST_INSERT_HEAD(&vq->vq_freelist, qe, qe_list); } /* * Enqueue several dmamaps as a single request. */ /* * Typical usage: * <queue size> number of followings are stored in arrays * - command blocks (in dmamem) should be pre-allocated and mapped * - dmamaps for command blocks should be pre-allocated and loaded * - dmamaps for payload should be pre-allocated * r = virtio_enqueue_prep(sc, vq, &slot); // allocate a slot * if (r) // currently 0 or EAGAIN * return r; * r = bus_dmamap_load(dmat, dmamap_payload[slot], data, count, ..); * if (r) { * virtio_enqueue_abort(sc, vq, slot); * bus_dmamap_unload(dmat, dmamap_payload[slot]); * return r; * } * r = virtio_enqueue_reserve(sc, vq, slot, * dmamap_payload[slot]->dm_nsegs+1); * // ^ +1 for command * if (r) { // currently 0 or EAGAIN * bus_dmamap_unload(dmat, dmamap_payload[slot]); * return r; // do not call abort() * } * <setup and prepare commands> * bus_dmamap_sync(dmat, dmamap_cmd[slot],... BUS_DMASYNC_PREWRITE); * bus_dmamap_sync(dmat, dmamap_payload[slot],...); * virtio_enqueue(sc, vq, slot, dmamap_cmd[slot], 0); * virtio_enqueue(sc, vq, slot, dmamap_payload[slot], iswrite); * virtio_enqueue_commit(sc, vq, slot, 1); * * Alternative usage with statically allocated slots: * <during initialization> * // while not out of slots, do * virtio_enqueue_prep(sc, vq, &slot); // allocate a slot * virtio_enqueue_reserve(sc, vq, slot, max_segs); // reserve all slots * that may ever be needed * * <when enqueuing a request> * // Don't call virtio_enqueue_prep() * bus_dmamap_load(dmat, dmamap_payload[slot], data, count, ..); * bus_dmamap_sync(dmat, dmamap_cmd[slot],... BUS_DMASYNC_PREWRITE); * bus_dmamap_sync(dmat, dmamap_payload[slot],...); * virtio_enqueue_trim(sc, vq, slot, num_segs_needed); * virtio_enqueue(sc, vq, slot, dmamap_cmd[slot], 0); * virtio_enqueue(sc, vq, slot, dmamap_payload[slot], iswrite); * virtio_enqueue_commit(sc, vq, slot, 1); * * <when dequeuing> * // don't call virtio_dequeue_commit() */ /* * enqueue_prep: allocate a slot number */ int virtio_enqueue_prep(struct virtqueue *vq, int *slotp) { struct vq_entry *qe1; VIRTIO_ASSERT(slotp != NULL); qe1 = vq_alloc_entry(vq); if (qe1 == NULL) return EAGAIN; /* next slot is not allocated yet */ qe1->qe_next = -1; *slotp = qe1->qe_index; return 0; } /* * enqueue_reserve: allocate remaining slots and build the descriptor chain. * Calls virtio_enqueue_abort() on failure. */ int virtio_enqueue_reserve(struct virtqueue *vq, int slot, int nsegs) { struct vq_entry *qe1 = &vq->vq_entries[slot]; VIRTIO_ASSERT(qe1->qe_next == -1); VIRTIO_ASSERT(1 <= nsegs && nsegs <= vq->vq_num); if (vq->vq_indirect != NULL && nsegs > 1 && nsegs <= vq->vq_maxnsegs) { struct vring_desc *vd; int i; qe1->qe_indirect = 1; vd = &vq->vq_desc[qe1->qe_index]; vd->addr = vq->vq_dmamap->dm_segs[0].ds_addr + vq->vq_indirectoffset; vd->addr += sizeof(struct vring_desc) * vq->vq_maxnsegs * qe1->qe_index; vd->len = sizeof(struct vring_desc) * nsegs; vd->flags = VRING_DESC_F_INDIRECT; vd = vq->vq_indirect; vd += vq->vq_maxnsegs * qe1->qe_index; qe1->qe_desc_base = vd; for (i = 0; i < nsegs-1; i++) vd[i].flags = VRING_DESC_F_NEXT; vd[i].flags = 0; qe1->qe_next = 0; return 0; } else { struct vring_desc *vd; struct vq_entry *qe; int i, s; qe1->qe_indirect = 0; vd = &vq->vq_desc[0]; qe1->qe_desc_base = vd; qe1->qe_next = qe1->qe_index; s = slot; for (i = 0; i < nsegs - 1; i++) { qe = vq_alloc_entry(vq); if (qe == NULL) { vd[s].flags = 0; virtio_enqueue_abort(vq, slot); return EAGAIN; } vd[s].flags = VRING_DESC_F_NEXT; vd[s].next = qe->qe_index; s = qe->qe_index; } vd[s].flags = 0; return 0; } } /* * enqueue: enqueue a single dmamap. */ int virtio_enqueue(struct virtqueue *vq, int slot, bus_dmamap_t dmamap, int write) { struct vq_entry *qe1 = &vq->vq_entries[slot]; struct vring_desc *vd = qe1->qe_desc_base; int i; int s = qe1->qe_next; VIRTIO_ASSERT(s >= 0); VIRTIO_ASSERT(dmamap->dm_nsegs > 0); if (dmamap->dm_nsegs > vq->vq_maxnsegs) { #if VIRTIO_DEBUG for (i = 0; i < dmamap->dm_nsegs; i++) { printf(" %d (%d): %p %lx \n", i, write, (void *)dmamap->dm_segs[i].ds_addr, dmamap->dm_segs[i].ds_len); } #endif panic("dmamap->dm_nseg %d > vq->vq_maxnsegs %d", dmamap->dm_nsegs, vq->vq_maxnsegs); } for (i = 0; i < dmamap->dm_nsegs; i++) { vd[s].addr = dmamap->dm_segs[i].ds_addr; vd[s].len = dmamap->dm_segs[i].ds_len; if (!write) vd[s].flags |= VRING_DESC_F_WRITE; s = vd[s].next; } qe1->qe_next = s; return 0; } int virtio_enqueue_p(struct virtqueue *vq, int slot, bus_dmamap_t dmamap, bus_addr_t start, bus_size_t len, int write) { struct vq_entry *qe1 = &vq->vq_entries[slot]; struct vring_desc *vd = qe1->qe_desc_base; int s = qe1->qe_next; VIRTIO_ASSERT(s >= 0); /* XXX todo: handle more segments */ VIRTIO_ASSERT(dmamap->dm_nsegs == 1); VIRTIO_ASSERT((dmamap->dm_segs[0].ds_len > start) && (dmamap->dm_segs[0].ds_len >= start + len)); vd[s].addr = dmamap->dm_segs[0].ds_addr + start; vd[s].len = len; if (!write) vd[s].flags |= VRING_DESC_F_WRITE; qe1->qe_next = vd[s].next; return 0; } static void publish_avail_idx(struct virtio_softc *sc, struct virtqueue *vq) { vq_sync_aring(sc, vq, BUS_DMASYNC_PREWRITE); virtio_membar_producer(); vq->vq_avail->idx = vq->vq_avail_idx; vq_sync_aring(sc, vq, BUS_DMASYNC_POSTWRITE); vq->vq_queued = 1; } /* * enqueue_commit: add it to the aring. */ void virtio_enqueue_commit(struct virtio_softc *sc, struct virtqueue *vq, int slot, int notifynow) { struct vq_entry *qe1; if (slot < 0) goto notify; vq_sync_descs(sc, vq, BUS_DMASYNC_PREWRITE); qe1 = &vq->vq_entries[slot]; if (qe1->qe_indirect) vq_sync_indirect(sc, vq, slot, BUS_DMASYNC_PREWRITE); vq->vq_avail->ring[(vq->vq_avail_idx++) & vq->vq_mask] = slot; notify: if (notifynow) { if (virtio_has_feature(vq->vq_owner, VIRTIO_F_RING_EVENT_IDX)) { uint16_t o = vq->vq_avail->idx; uint16_t n = vq->vq_avail_idx; uint16_t t; publish_avail_idx(sc, vq); virtio_membar_sync(); t = VQ_AVAIL_EVENT(vq) + 1; if ((uint16_t)(n - t) < (uint16_t)(n - o)) sc->sc_ops->kick(sc, vq->vq_index); } else { publish_avail_idx(sc, vq); virtio_membar_sync(); if (!(vq->vq_used->flags & VRING_USED_F_NO_NOTIFY)) sc->sc_ops->kick(sc, vq->vq_index); } } } /* * enqueue_abort: rollback. */ int virtio_enqueue_abort(struct virtqueue *vq, int slot) { struct vq_entry *qe = &vq->vq_entries[slot]; struct vring_desc *vd; int s; if (qe->qe_next < 0) { vq_free_entry(vq, qe); return 0; } s = slot; vd = &vq->vq_desc[0]; while (vd[s].flags & VRING_DESC_F_NEXT) { s = vd[s].next; vq_free_entry(vq, qe); qe = &vq->vq_entries[s]; } vq_free_entry(vq, qe); return 0; } /* * enqueue_trim: adjust buffer size to given # of segments, a.k.a. * descriptors. */ void virtio_enqueue_trim(struct virtqueue *vq, int slot, int nsegs) { struct vq_entry *qe1 = &vq->vq_entries[slot]; struct vring_desc *vd = &vq->vq_desc[0]; int i; if ((vd[slot].flags & VRING_DESC_F_INDIRECT) == 0) { qe1->qe_next = qe1->qe_index; /* * N.B.: the vq_entries are ASSUMED to be a contiguous * block with slot being the index to the first one. */ } else { qe1->qe_next = 0; vd = &vq->vq_desc[qe1->qe_index]; vd->len = sizeof(struct vring_desc) * nsegs; vd = qe1->qe_desc_base; slot = 0; } for (i = 0; i < nsegs -1 ; i++) { vd[slot].flags = VRING_DESC_F_NEXT; slot++; } vd[slot].flags = 0; } /* * Dequeue a request. */ /* * dequeue: dequeue a request from uring; dmamap_sync for uring is * already done in the interrupt handler. */ int virtio_dequeue(struct virtio_softc *sc, struct virtqueue *vq, int *slotp, int *lenp) { uint16_t slot, usedidx; struct vq_entry *qe; if (vq->vq_used_idx == vq->vq_used->idx) return ENOENT; usedidx = vq->vq_used_idx++; usedidx &= vq->vq_mask; virtio_membar_consumer(); slot = vq->vq_used->ring[usedidx].id; qe = &vq->vq_entries[slot]; if (qe->qe_indirect) vq_sync_indirect(sc, vq, slot, BUS_DMASYNC_POSTWRITE); if (slotp) *slotp = slot; if (lenp) *lenp = vq->vq_used->ring[usedidx].len; return 0; } /* * dequeue_commit: complete dequeue; the slot is recycled for future use. * if you forget to call this the slot will be leaked. * * Don't call this if you use statically allocated slots * and virtio_dequeue_trim(). */ int virtio_dequeue_commit(struct virtqueue *vq, int slot) { struct vq_entry *qe = &vq->vq_entries[slot]; struct vring_desc *vd = &vq->vq_desc[0]; int s = slot; while (vd[s].flags & VRING_DESC_F_NEXT) { s = vd[s].next; vq_free_entry(vq, qe); qe = &vq->vq_entries[s]; } vq_free_entry(vq, qe); return 0; } /* * Increase the event index in order to delay interrupts. * Returns 0 on success; returns 1 if the used ring has already advanced * too far, and the caller must process the queue again (otherwise, no * more interrupts will happen). */ int virtio_postpone_intr(struct virtqueue *vq, uint16_t nslots) { uint16_t idx; idx = vq->vq_used_idx + nslots; /* set the new event index: avail_ring->used_event = idx */ VQ_USED_EVENT(vq) = idx; virtio_membar_sync(); vq_sync_aring(vq->vq_owner, vq, BUS_DMASYNC_PREWRITE); vq->vq_queued++; if (nslots < virtio_nused(vq)) return 1; return 0; } /* * Postpone interrupt until 3/4 of the available descriptors have been * consumed. */ int virtio_postpone_intr_smart(struct virtqueue *vq) { uint16_t nslots; nslots = (uint16_t)(vq->vq_avail->idx - vq->vq_used_idx) * 3 / 4; return virtio_postpone_intr(vq, nslots); } /* * Postpone interrupt until all of the available descriptors have been * consumed. */ int virtio_postpone_intr_far(struct virtqueue *vq) { uint16_t nslots; nslots = (uint16_t)(vq->vq_avail->idx - vq->vq_used_idx); return virtio_postpone_intr(vq, nslots); } /* * Start/stop vq interrupt. No guarantee. */ void virtio_stop_vq_intr(struct virtio_softc *sc, struct virtqueue *vq) { if (virtio_has_feature(sc, VIRTIO_F_RING_EVENT_IDX)) { /* * No way to disable the interrupt completely with * RingEventIdx. Instead advance used_event by half * the possible value. This won't happen soon and * is far enough in the past to not trigger a spurious * interrupt. */ VQ_USED_EVENT(vq) = vq->vq_used_idx + 0x8000; } else { vq->vq_avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; } vq_sync_aring(sc, vq, BUS_DMASYNC_PREWRITE); vq->vq_queued++; } int virtio_start_vq_intr(struct virtio_softc *sc, struct virtqueue *vq) { /* * If event index feature is negotiated, enabling * interrupts is done through setting the latest * consumed index in the used_event field */ if (virtio_has_feature(sc, VIRTIO_F_RING_EVENT_IDX)) VQ_USED_EVENT(vq) = vq->vq_used_idx; else vq->vq_avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; virtio_membar_sync(); vq_sync_aring(sc, vq, BUS_DMASYNC_PREWRITE); vq->vq_queued++; if (vq->vq_used_idx != vq->vq_used->idx) return 1; return 0; } /* * Returns a number of slots in the used ring available to * be supplied to the avail ring. */ int virtio_nused(struct virtqueue *vq) { uint16_t n; n = (uint16_t)(vq->vq_used->idx - vq->vq_used_idx); VIRTIO_ASSERT(n <= vq->vq_num); return n; } #if VIRTIO_DEBUG void virtio_vq_dump(struct virtqueue *vq) { /* Common fields */ printf(" + vq num: %d\n", vq->vq_num); printf(" + vq mask: 0x%X\n", vq->vq_mask); printf(" + vq index: %d\n", vq->vq_index); printf(" + vq used idx: %d\n", vq->vq_used_idx); printf(" + vq avail idx: %d\n", vq->vq_avail_idx); printf(" + vq queued: %d\n",vq->vq_queued); /* Avail ring fields */ printf(" + avail flags: 0x%X\n", vq->vq_avail->flags); printf(" + avail idx: %d\n", vq->vq_avail->idx); printf(" + avail event: %d\n", VQ_AVAIL_EVENT(vq)); /* Used ring fields */ printf(" + used flags: 0x%X\n",vq->vq_used->flags); printf(" + used idx: %d\n",vq->vq_used->idx); printf(" + used event: %d\n", VQ_USED_EVENT(vq)); printf(" +++++++++++++++++++++++++++\n"); } #endif
5 1 13 32 1 31 7 1 7 1 7 1 4 4 8 8 8 8 8 8 8 8 8 8 8 26 29 1 1 2 1 23 2 7 5 3 4 7 1 6 10 10 10 3 8 10 10 10 2 8 5 10 11 61 44 3 1 1 1 1 1 2 1 1 1 3 18 18 2 2 2 2 9 11 4 13 10 10 10 10 10 4 13 6 2 7 5 3 3 14 30 15 1 27 15 14 14 14 15 3 9 8 1 29 30 5 30 30 30 16 19 40 30 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 /* $OpenBSD: com.c,v 1.179 2024/05/13 01:15:50 jsg Exp $ */ /* $NetBSD: com.c,v 1.82.4.1 1996/06/02 09:08:00 mrg Exp $ */ /* * Copyright (c) 1997 - 1999, Jason Downs. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /*- * Copyright (c) 1993, 1994, 1995, 1996 * Charles M. Hannum. All rights reserved. * Copyright (c) 1991 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)com.c 7.5 (Berkeley) 5/16/91 */ /* * COM driver, based on HP dca driver * uses National Semiconductor NS16450/NS16550AF UART */ #include <sys/param.h> #include <sys/systm.h> #include <sys/ioctl.h> #include <sys/tty.h> #include <sys/conf.h> #include <sys/fcntl.h> #include <sys/uio.h> #include <sys/kernel.h> #include <sys/syslog.h> #include <sys/device.h> #include <sys/vnode.h> #ifdef DDB #include <ddb/db_var.h> #endif #include <machine/bus.h> #include <machine/intr.h> #define COM_CONSOLE #include <dev/cons.h> #include <dev/ic/comreg.h> #include <dev/ic/comvar.h> #include <dev/ic/ns16550reg.h> #define com_lcr com_cfcr cdev_decl(com); static u_char tiocm_xxx2mcr(int); void compwroff(struct com_softc *); void cominit(bus_space_tag_t, bus_space_handle_t, int, int); struct cfdriver com_cd = { NULL, "com", DV_TTY }; int comdefaultrate = TTYDEF_SPEED; #ifdef COM_CONSOLE int comconsfreq; int comconsrate = TTYDEF_SPEED; bus_addr_t comconsaddr = 0; int comconsattached; bus_space_tag_t comconsiot; bus_space_handle_t comconsioh; int comconsunit; tcflag_t comconscflag = TTYDEF_CFLAG; #endif int commajor; #define DEVUNIT(x) (minor(x) & 0x7f) #define DEVCUA(x) (minor(x) & 0x80) int comspeed(long freq, long speed) { #define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */ int x, err; if (speed == 0) return 0; if (speed < 0) return -1; x = divrnd((freq / 16), speed); if (x <= 0) return -1; err = divrnd((quad_t)freq * 1000 / 16, speed * x) - 1000; if (err < 0) err = -err; if (err > COM_TOLERANCE) return -1; return x; #undef divrnd } #ifdef COM_CONSOLE int comprobe1(bus_space_tag_t iot, bus_space_handle_t ioh) { int i; /* force access to id reg */ bus_space_write_1(iot, ioh, com_lcr, LCR_8BITS); bus_space_write_1(iot, ioh, com_iir, 0); for (i = 0; i < 32; i++) { if ((bus_space_read_1(iot, ioh, com_lcr) != LCR_8BITS) || (bus_space_read_1(iot, ioh, com_iir) & 0x38)) { bus_space_read_1(iot, ioh, com_data); /* cleanup */ } else break; } if (i >= 32) return 0; return 1; } #endif int com_detach(struct device *self, int flags) { struct com_softc *sc = (struct com_softc *)self; int maj, mn; sc->sc_swflags |= COM_SW_DEAD; /* Locate the major number. */ for (maj = 0; maj < nchrdev; maj++) if (cdevsw[maj].d_open == comopen) break; /* Nuke the vnodes for any open instances. */ mn = self->dv_unit; vdevgone(maj, mn, mn, VCHR); /* XXX a symbolic constant for the cua bit would be nicer. */ mn |= 0x80; vdevgone(maj, mn, mn, VCHR); timeout_del(&sc->sc_dtr_tmo); timeout_del(&sc->sc_diag_tmo); softintr_disestablish(sc->sc_si); /* Detach and free the tty. */ if (sc->sc_tty) { ttyfree(sc->sc_tty); } return (0); } int com_activate(struct device *self, int act) { struct com_softc *sc = (struct com_softc *)self; int s, rv = 0; switch (act) { case DVACT_SUSPEND: if (timeout_del(&sc->sc_dtr_tmo)) { /* Make sure DTR gets raised upon resume. */ SET(sc->sc_mcr, MCR_DTR | MCR_RTS); } timeout_del(&sc->sc_diag_tmo); break; case DVACT_RESUME: com_resume(sc); break; case DVACT_DEACTIVATE: if (sc->sc_hwflags & COM_HW_CONSOLE) { rv = EBUSY; break; } s = spltty(); if (sc->disable != NULL && sc->enabled != 0) { (*sc->disable)(sc); sc->enabled = 0; } splx(s); break; } return (rv); } int comopen(dev_t dev, int flag, int mode, struct proc *p) { int unit = DEVUNIT(dev); struct com_softc *sc; struct tty *tp; int s; int error = 0; if (unit >= com_cd.cd_ndevs) return ENXIO; sc = com_cd.cd_devs[unit]; if (!sc) return ENXIO; s = spltty(); if (!sc->sc_tty) { tp = sc->sc_tty = ttymalloc(1000000); } else tp = sc->sc_tty; splx(s); tp->t_oproc = comstart; tp->t_param = comparam; tp->t_dev = dev; if (!ISSET(tp->t_state, TS_ISOPEN)) { SET(tp->t_state, TS_WOPEN); ttychars(tp); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; #ifdef COM_CONSOLE if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { tp->t_cflag = comconscflag; tp->t_ispeed = tp->t_ospeed = comconsrate; } else #endif { tp->t_cflag = TTYDEF_CFLAG; tp->t_ispeed = tp->t_ospeed = comdefaultrate; } if (ISSET(sc->sc_swflags, COM_SW_CLOCAL)) SET(tp->t_cflag, CLOCAL); if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS)) SET(tp->t_cflag, CRTSCTS); if (ISSET(sc->sc_swflags, COM_SW_MDMBUF)) SET(tp->t_cflag, MDMBUF); tp->t_lflag = TTYDEF_LFLAG; s = spltty(); sc->sc_initialize = 1; comparam(tp, &tp->t_termios); ttsetwater(tp); sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0]; sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER; sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE; /* * Wake up the sleepy heads. */ if (!ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { switch (sc->sc_uarttype) { case COM_UART_ST16650: case COM_UART_ST16650V2: com_write_reg(sc, com_lcr, LCR_EFR); com_write_reg(sc, com_efr, EFR_ECB); com_write_reg(sc, com_ier, 0); com_write_reg(sc, com_efr, 0); com_write_reg(sc, com_lcr, 0); break; case COM_UART_TI16750: com_write_reg(sc, com_ier, 0); break; case COM_UART_XR17V35X: com_write_reg(sc, UART_EXAR_SLEEP, 0); break; } } if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) { u_int8_t fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST; u_int8_t lcr; if (tp->t_ispeed <= 1200) fifo |= FIFO_TRIGGER_1; else if (tp->t_ispeed <= 38400) fifo |= FIFO_TRIGGER_4; else fifo |= FIFO_TRIGGER_8; if (sc->sc_uarttype == COM_UART_TI16750) { fifo |= FIFO_ENABLE_64BYTE; lcr = com_read_reg(sc, com_lcr); com_write_reg(sc, com_lcr, lcr | LCR_DLAB); } /* * (Re)enable and drain FIFOs. * * Certain SMC chips cause problems if the FIFOs are * enabled while input is ready. Turn off the FIFO * if necessary to clear the input. Test the input * ready bit after enabling the FIFOs to handle races * between enabling and fresh input. * * Set the FIFO threshold based on the receive speed. */ for (;;) { com_write_reg(sc, com_fifo, 0); delay(100); (void) com_read_reg(sc, com_data); com_write_reg(sc, com_fifo, fifo | FIFO_RCV_RST | FIFO_XMT_RST); delay(100); if(!ISSET(com_read_reg(sc, com_lsr), LSR_RXRDY)) break; } if (sc->sc_uarttype == COM_UART_TI16750) com_write_reg(sc, com_lcr, lcr); } /* Flush any pending I/O. */ while (ISSET(com_read_reg(sc, com_lsr), LSR_RXRDY)) (void) com_read_reg(sc, com_data); /* You turn me on, baby! */ sc->sc_mcr = MCR_DTR | MCR_RTS; if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN)) SET(sc->sc_mcr, MCR_IENABLE); com_write_reg(sc, com_mcr, sc->sc_mcr); sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC; com_write_reg(sc, com_ier, sc->sc_ier); sc->sc_msr = com_read_reg(sc, com_msr); if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) || DEVCUA(dev) || ISSET(sc->sc_msr, MSR_DCD) || ISSET(tp->t_cflag, MDMBUF)) SET(tp->t_state, TS_CARR_ON); else CLR(tp->t_state, TS_CARR_ON); } else if (ISSET(tp->t_state, TS_XCLUDE) && suser(p) != 0) return EBUSY; else s = spltty(); if (DEVCUA(dev)) { if (ISSET(tp->t_state, TS_ISOPEN)) { /* Ah, but someone already is dialed in... */ splx(s); return EBUSY; } sc->sc_cua = 1; /* We go into CUA mode. */ } else { /* tty (not cua) device; wait for carrier if necessary. */ if (ISSET(flag, O_NONBLOCK)) { if (sc->sc_cua) { /* Opening TTY non-blocking... but the CUA is busy. */ splx(s); return EBUSY; } } else { while (sc->sc_cua || (!ISSET(tp->t_cflag, CLOCAL) && !ISSET(tp->t_state, TS_CARR_ON))) { SET(tp->t_state, TS_WOPEN); error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, ttopen); /* * If TS_WOPEN has been reset, that means the cua device * has been closed. We don't want to fail in that case, * so just go around again. */ if (error && ISSET(tp->t_state, TS_WOPEN)) { CLR(tp->t_state, TS_WOPEN); if (!sc->sc_cua && !ISSET(tp->t_state, TS_ISOPEN)) compwroff(sc); splx(s); return error; } } } } splx(s); return (*linesw[tp->t_line].l_open)(dev, tp, p); } int comclose(dev_t dev, int flag, int mode, struct proc *p) { int unit = DEVUNIT(dev); struct com_softc *sc = com_cd.cd_devs[unit]; struct tty *tp = sc->sc_tty; int s; #ifdef COM_CONSOLE /* XXX This is for cons.c. */ if (!ISSET(tp->t_state, TS_ISOPEN)) return 0; #endif if(sc->sc_swflags & COM_SW_DEAD) return 0; (*linesw[tp->t_line].l_close)(tp, flag, p); s = spltty(); if (ISSET(tp->t_state, TS_WOPEN)) { /* tty device is waiting for carrier; drop dtr then re-raise */ CLR(sc->sc_mcr, MCR_DTR | MCR_RTS); com_write_reg(sc, com_mcr, sc->sc_mcr); timeout_add_sec(&sc->sc_dtr_tmo, 2); } else { /* no one else waiting; turn off the uart */ compwroff(sc); } CLR(tp->t_state, TS_BUSY | TS_FLUSH); sc->sc_cua = 0; splx(s); ttyclose(tp); #ifdef COM_CONSOLE #ifdef notyet /* XXXX */ if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { ttyfree(tp); sc->sc_tty = 0; } #endif #endif return 0; } void compwroff(struct com_softc *sc) { struct tty *tp = sc->sc_tty; CLR(sc->sc_lcr, LCR_SBREAK); com_write_reg(sc, com_lcr, sc->sc_lcr); com_write_reg(sc, com_ier, 0); if (ISSET(tp->t_cflag, HUPCL) && !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) { /* XXX perhaps only clear DTR */ sc->sc_mcr = 0; com_write_reg(sc, com_mcr, sc->sc_mcr); } /* * Turn FIFO off; enter sleep mode if possible. */ com_write_reg(sc, com_fifo, 0); delay(100); if (ISSET(com_read_reg(sc, com_lsr), LSR_RXRDY)) (void) com_read_reg(sc, com_data); delay(100); com_write_reg(sc, com_fifo, FIFO_RCV_RST | FIFO_XMT_RST); if (!ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { switch (sc->sc_uarttype) { case COM_UART_ST16650: case COM_UART_ST16650V2: com_write_reg(sc, com_lcr, LCR_EFR); com_write_reg(sc, com_efr, EFR_ECB); com_write_reg(sc, com_ier, IER_SLEEP); com_write_reg(sc, com_lcr, 0); break; case COM_UART_TI16750: com_write_reg(sc, com_ier, IER_SLEEP); break; case COM_UART_XR17V35X: com_write_reg(sc, UART_EXAR_SLEEP, 0xff); break; } } } void com_resume(struct com_softc *sc) { struct tty *tp = sc->sc_tty; int ospeed; if (!tp || !ISSET(tp->t_state, TS_ISOPEN)) { #ifdef COM_CONSOLE if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) cominit(comconsiot, comconsioh, comconsrate, comconsfreq); #endif return; } /* * Wake up the sleepy heads. */ if (!ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { switch (sc->sc_uarttype) { case COM_UART_ST16650: case COM_UART_ST16650V2: com_write_reg(sc, com_lcr, LCR_EFR); com_write_reg(sc, com_efr, EFR_ECB); com_write_reg(sc, com_ier, 0); com_write_reg(sc, com_efr, 0); com_write_reg(sc, com_lcr, 0); break; case COM_UART_TI16750: com_write_reg(sc, com_ier, 0); break; case COM_UART_XR17V35X: com_write_reg(sc, UART_EXAR_SLEEP, 0); break; } } ospeed = comspeed(sc->sc_frequency, tp->t_ospeed); if (ospeed != 0) { com_write_reg(sc, com_lcr, sc->sc_lcr | LCR_DLAB); com_write_reg(sc, com_dlbl, ospeed); com_write_reg(sc, com_dlbh, ospeed >> 8); com_write_reg(sc, com_lcr, sc->sc_lcr); } else { com_write_reg(sc, com_lcr, sc->sc_lcr); } if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) { u_int8_t fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST; u_int8_t lcr; if (tp->t_ispeed <= 1200) fifo |= FIFO_TRIGGER_1; else if (tp->t_ispeed <= 38400) fifo |= FIFO_TRIGGER_4; else fifo |= FIFO_TRIGGER_8; if (sc->sc_uarttype == COM_UART_TI16750) { fifo |= FIFO_ENABLE_64BYTE; lcr = com_read_reg(sc, com_lcr); com_write_reg(sc, com_lcr, lcr | LCR_DLAB); } /* * (Re)enable and drain FIFOs. * * Certain SMC chips cause problems if the FIFOs are * enabled while input is ready. Turn off the FIFO * if necessary to clear the input. Test the input * ready bit after enabling the FIFOs to handle races * between enabling and fresh input. * * Set the FIFO threshold based on the receive speed. */ for (;;) { com_write_reg(sc, com_fifo, 0); delay(100); (void) com_read_reg(sc, com_data); com_write_reg(sc, com_fifo, fifo | FIFO_RCV_RST | FIFO_XMT_RST); delay(100); if(!ISSET(com_read_reg(sc, com_lsr), LSR_RXRDY)) break; } if (sc->sc_uarttype == COM_UART_TI16750) com_write_reg(sc, com_lcr, lcr); } /* You turn me on, baby! */ com_write_reg(sc, com_mcr, sc->sc_mcr); com_write_reg(sc, com_ier, sc->sc_ier); } void com_raisedtr(void *arg) { struct com_softc *sc = arg; SET(sc->sc_mcr, MCR_DTR | MCR_RTS); com_write_reg(sc, com_mcr, sc->sc_mcr); } int comread(dev_t dev, struct uio *uio, int flag) { struct com_softc *sc = com_cd.cd_devs[DEVUNIT(dev)]; struct tty *tp = sc->sc_tty; return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); } int comwrite(dev_t dev, struct uio *uio, int flag) { struct com_softc *sc = com_cd.cd_devs[DEVUNIT(dev)]; struct tty *tp = sc->sc_tty; return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); } struct tty * comtty(dev_t dev) { struct com_softc *sc = com_cd.cd_devs[DEVUNIT(dev)]; struct tty *tp = sc->sc_tty; return (tp); } static u_char tiocm_xxx2mcr(int data) { u_char m = 0; if (ISSET(data, TIOCM_DTR)) SET(m, MCR_DTR); if (ISSET(data, TIOCM_RTS)) SET(m, MCR_RTS); return m; } int comioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { int unit = DEVUNIT(dev); struct com_softc *sc = com_cd.cd_devs[unit]; struct tty *tp = sc->sc_tty; int error; error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); if (error >= 0) return error; error = ttioctl(tp, cmd, data, flag, p); if (error >= 0) return error; switch (cmd) { case TIOCSBRK: SET(sc->sc_lcr, LCR_SBREAK); com_write_reg(sc, com_lcr, sc->sc_lcr); break; case TIOCCBRK: CLR(sc->sc_lcr, LCR_SBREAK); com_write_reg(sc, com_lcr, sc->sc_lcr); break; case TIOCSDTR: SET(sc->sc_mcr, sc->sc_dtr); com_write_reg(sc, com_mcr, sc->sc_mcr); break; case TIOCCDTR: CLR(sc->sc_mcr, sc->sc_dtr); com_write_reg(sc, com_mcr, sc->sc_mcr); break; case TIOCMSET: CLR(sc->sc_mcr, MCR_DTR | MCR_RTS); case TIOCMBIS: SET(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data)); com_write_reg(sc, com_mcr, sc->sc_mcr); break; case TIOCMBIC: CLR(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data)); com_write_reg(sc, com_mcr, sc->sc_mcr); break; case TIOCMGET: { u_char m; int bits = 0; m = sc->sc_mcr; if (ISSET(m, MCR_DTR)) SET(bits, TIOCM_DTR); if (ISSET(m, MCR_RTS)) SET(bits, TIOCM_RTS); m = sc->sc_msr; if (ISSET(m, MSR_DCD)) SET(bits, TIOCM_CD); if (ISSET(m, MSR_CTS)) SET(bits, TIOCM_CTS); if (ISSET(m, MSR_DSR)) SET(bits, TIOCM_DSR); if (ISSET(m, MSR_RI | MSR_TERI)) SET(bits, TIOCM_RI); if (com_read_reg(sc, com_ier)) SET(bits, TIOCM_LE); *(int *)data = bits; break; } case TIOCGFLAGS: { int driverbits, userbits = 0; driverbits = sc->sc_swflags; if (ISSET(driverbits, COM_SW_SOFTCAR)) SET(userbits, TIOCFLAG_SOFTCAR); if (ISSET(driverbits, COM_SW_CLOCAL)) SET(userbits, TIOCFLAG_CLOCAL); if (ISSET(driverbits, COM_SW_CRTSCTS)) SET(userbits, TIOCFLAG_CRTSCTS); if (ISSET(driverbits, COM_SW_MDMBUF)) SET(userbits, TIOCFLAG_MDMBUF); if (ISSET(driverbits, COM_SW_PPS)) SET(userbits, TIOCFLAG_PPS); *(int *)data = userbits; break; } case TIOCSFLAGS: { int userbits, driverbits = 0; error = suser(p); if (error != 0) return(EPERM); userbits = *(int *)data; if (ISSET(userbits, TIOCFLAG_SOFTCAR) || ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) SET(driverbits, COM_SW_SOFTCAR); if (ISSET(userbits, TIOCFLAG_CLOCAL)) SET(driverbits, COM_SW_CLOCAL); if (ISSET(userbits, TIOCFLAG_CRTSCTS)) SET(driverbits, COM_SW_CRTSCTS); if (ISSET(userbits, TIOCFLAG_MDMBUF)) SET(driverbits, COM_SW_MDMBUF); if (ISSET(userbits, TIOCFLAG_PPS)) SET(driverbits, COM_SW_PPS); sc->sc_swflags = driverbits; break; } default: return ENOTTY; } return 0; } /* already called at spltty */ int comparam(struct tty *tp, struct termios *t) { struct com_softc *sc = com_cd.cd_devs[DEVUNIT(tp->t_dev)]; int ospeed = comspeed(sc->sc_frequency, t->c_ospeed); u_char lcr; tcflag_t oldcflag; /* Check requested parameters. */ if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) return EINVAL; lcr = ISSET(sc->sc_lcr, LCR_SBREAK); switch (ISSET(t->c_cflag, CSIZE)) { case CS5: SET(lcr, LCR_5BITS); break; case CS6: SET(lcr, LCR_6BITS); break; case CS7: SET(lcr, LCR_7BITS); break; case CS8: SET(lcr, LCR_8BITS); break; } if (ISSET(t->c_cflag, PARENB)) { SET(lcr, LCR_PENAB); if (!ISSET(t->c_cflag, PARODD)) SET(lcr, LCR_PEVEN); } if (ISSET(t->c_cflag, CSTOPB)) SET(lcr, LCR_STOPB); sc->sc_lcr = lcr; if (ospeed == 0) { CLR(sc->sc_mcr, MCR_DTR); com_write_reg(sc, com_mcr, sc->sc_mcr); } /* * Set the FIFO threshold based on the receive speed, if we are * changing it. */ if (sc->sc_initialize || (tp->t_ispeed != t->c_ispeed)) { sc->sc_initialize = 0; if (ospeed != 0) { /* * Make sure the transmit FIFO is empty before * proceeding. If we don't do this, some revisions * of the UART will hang. Interestingly enough, * even if we do this while the last character is * still being pushed out, they don't hang. This * seems good enough. */ while (ISSET(tp->t_state, TS_BUSY)) { int error; ++sc->sc_halt; error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, "comprm"); --sc->sc_halt; if (error) { comstart(tp); return (error); } } com_write_reg(sc, com_lcr, lcr | LCR_DLAB); com_write_reg(sc, com_dlbl, ospeed); com_write_reg(sc, com_dlbh, ospeed >> 8); com_write_reg(sc, com_lcr, lcr); SET(sc->sc_mcr, MCR_DTR); com_write_reg(sc, com_mcr, sc->sc_mcr); } else com_write_reg(sc, com_lcr, lcr); if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) { if (sc->sc_uarttype == COM_UART_TI16750) { com_write_reg(sc, com_lcr, lcr | LCR_DLAB); com_write_reg(sc, com_fifo, FIFO_ENABLE | FIFO_ENABLE_64BYTE | (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8)); com_write_reg(sc, com_lcr, lcr); } else com_write_reg(sc, com_fifo, FIFO_ENABLE | (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8)); } } else com_write_reg(sc, com_lcr, lcr); /* When not using CRTSCTS, RTS follows DTR. */ if (!ISSET(t->c_cflag, CRTSCTS)) { if (ISSET(sc->sc_mcr, MCR_DTR)) { if (!ISSET(sc->sc_mcr, MCR_RTS)) { SET(sc->sc_mcr, MCR_RTS); com_write_reg(sc, com_mcr, sc->sc_mcr); } } else { if (ISSET(sc->sc_mcr, MCR_RTS)) { CLR(sc->sc_mcr, MCR_RTS); com_write_reg(sc, com_mcr, sc->sc_mcr); } } sc->sc_dtr = MCR_DTR | MCR_RTS; } else sc->sc_dtr = MCR_DTR; /* and copy to tty */ tp->t_ispeed = t->c_ispeed; tp->t_ospeed = t->c_ospeed; oldcflag = tp->t_cflag; tp->t_cflag = t->c_cflag; /* * If DCD is off and MDMBUF is changed, ask the tty layer if we should * stop the device. */ if (!ISSET(sc->sc_msr, MSR_DCD) && !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) && ISSET(oldcflag, MDMBUF) != ISSET(tp->t_cflag, MDMBUF) && (*linesw[tp->t_line].l_modem)(tp, 0) == 0) { CLR(sc->sc_mcr, sc->sc_dtr); com_write_reg(sc, com_mcr, sc->sc_mcr); } /* Just to be sure... */ comstart(tp); return 0; } void comstart(struct tty *tp) { struct com_softc *sc = com_cd.cd_devs[DEVUNIT(tp->t_dev)]; int s; s = spltty(); if (ISSET(tp->t_state, TS_BUSY)) goto out; if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP) || sc->sc_halt > 0) goto stopped; if (ISSET(tp->t_cflag, CRTSCTS) && !ISSET(sc->sc_msr, MSR_CTS)) goto stopped; ttwakeupwr(tp); if (tp->t_outq.c_cc == 0) goto stopped; SET(tp->t_state, TS_BUSY); /* Enable transmit completion interrupts. */ if (!ISSET(sc->sc_ier, IER_ETXRDY)) { SET(sc->sc_ier, IER_ETXRDY); com_write_reg(sc, com_ier, sc->sc_ier); } if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) { u_char buffer[256]; /* largest fifo */ int i, n; n = q_to_b(&tp->t_outq, buffer, min(sc->sc_fifolen, sizeof buffer)); for (i = 0; i < n; i++) { com_write_reg(sc, com_data, buffer[i]); } bzero(buffer, n); } else if (tp->t_outq.c_cc != 0) com_write_reg(sc, com_data, getc(&tp->t_outq)); out: splx(s); return; stopped: if (ISSET(sc->sc_ier, IER_ETXRDY)) { CLR(sc->sc_ier, IER_ETXRDY); com_write_reg(sc, com_ier, sc->sc_ier); } splx(s); } /* * Stop output on a line. */ int comstop(struct tty *tp, int flag) { int s; s = spltty(); if (ISSET(tp->t_state, TS_BUSY)) if (!ISSET(tp->t_state, TS_TTSTOP)) SET(tp->t_state, TS_FLUSH); splx(s); return 0; } void comdiag(void *arg) { struct com_softc *sc = arg; int overflows, floods; int s; s = spltty(); sc->sc_errors = 0; overflows = sc->sc_overflows; sc->sc_overflows = 0; floods = sc->sc_floods; sc->sc_floods = 0; splx(s); log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf overflow%s\n", sc->sc_dev.dv_xname, overflows, overflows == 1 ? "" : "s", floods, floods == 1 ? "" : "s"); } void comsoft(void *arg) { struct com_softc *sc = (struct com_softc *)arg; struct tty *tp; u_char *ibufp; u_char *ibufend; int c; int s; static int lsrmap[8] = { 0, TTY_PE, TTY_FE, TTY_PE|TTY_FE, TTY_FE, TTY_PE|TTY_FE, TTY_FE, TTY_PE|TTY_FE }; if (sc == NULL || sc->sc_ibufp == sc->sc_ibuf) return; tp = sc->sc_tty; s = spltty(); ibufp = sc->sc_ibuf; ibufend = sc->sc_ibufp; if (ibufp == ibufend) { splx(s); return; } sc->sc_ibufp = sc->sc_ibuf = (ibufp == sc->sc_ibufs[0]) ? sc->sc_ibufs[1] : sc->sc_ibufs[0]; sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER; sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE; if (tp == NULL || !ISSET(tp->t_state, TS_ISOPEN)) { splx(s); return; } if (ISSET(tp->t_cflag, CRTSCTS) && !ISSET(sc->sc_mcr, MCR_RTS)) { /* XXX */ SET(sc->sc_mcr, MCR_RTS); com_write_reg(sc, com_mcr, sc->sc_mcr); } splx(s); while (ibufp < ibufend) { c = *ibufp++; if (ISSET(*ibufp, LSR_OE)) { sc->sc_overflows++; if (sc->sc_errors++ == 0) timeout_add_sec(&sc->sc_diag_tmo, 60); } /* This is ugly, but fast. */ c |= lsrmap[(*ibufp++ & (LSR_BI|LSR_FE|LSR_PE)) >> 2]; (*linesw[tp->t_line].l_rint)(c, tp); } } int comintr(void *arg) { struct com_softc *sc = arg; struct tty *tp; u_char lsr, data, msr, delta; if (!sc->sc_tty) return (0); /* Can't do squat. */ if (ISSET(com_read_reg(sc, com_iir), IIR_NOPEND)) return (0); tp = sc->sc_tty; for (;;) { lsr = com_read_reg(sc, com_lsr); if (ISSET(lsr, LSR_RXRDY)) { u_char *p = sc->sc_ibufp; softintr_schedule(sc->sc_si); do { data = com_read_reg(sc, com_data); if (ISSET(lsr, LSR_BI)) { #if defined(COM_CONSOLE) && defined(DDB) if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { if (db_console) db_enter(); goto next; } #endif data = 0; } if (p >= sc->sc_ibufend) { sc->sc_floods++; if (sc->sc_errors++ == 0) timeout_add_sec(&sc->sc_diag_tmo, 60); } else { *p++ = data; *p++ = lsr; if (p == sc->sc_ibufhigh && ISSET(tp->t_cflag, CRTSCTS)) { /* XXX */ CLR(sc->sc_mcr, MCR_RTS); com_write_reg(sc, com_mcr, sc->sc_mcr); } } #if defined(COM_CONSOLE) && defined(DDB) next: #endif lsr = com_read_reg(sc, com_lsr); } while (ISSET(lsr, LSR_RXRDY)); sc->sc_ibufp = p; } msr = com_read_reg(sc, com_msr); if (msr != sc->sc_msr) { delta = msr ^ sc->sc_msr; ttytstamp(tp, sc->sc_msr & MSR_CTS, msr & MSR_CTS, sc->sc_msr & MSR_DCD, msr & MSR_DCD); sc->sc_msr = msr; if (ISSET(delta, MSR_DCD)) { if (!ISSET(sc->sc_swflags, COM_SW_SOFTCAR) && (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD)) == 0) { CLR(sc->sc_mcr, sc->sc_dtr); com_write_reg(sc, com_mcr, sc->sc_mcr); } } if (ISSET(delta & msr, MSR_CTS) && ISSET(tp->t_cflag, CRTSCTS)) { /* the line is up and we want to do rts/cts flow control */ (*linesw[tp->t_line].l_start)(tp); } } if (ISSET(lsr, LSR_TXRDY) && ISSET(tp->t_state, TS_BUSY)) { CLR(tp->t_state, TS_BUSY | TS_FLUSH); if (sc->sc_halt > 0) wakeup(&tp->t_outq); (*linesw[tp->t_line].l_start)(tp); } if (ISSET(com_read_reg(sc, com_iir), IIR_NOPEND)) return (1); } } void cominit(bus_space_tag_t iot, bus_space_handle_t ioh, int rate, int frequency) { int s = splhigh(); u_char stat; bus_space_write_1(iot, ioh, com_lcr, LCR_DLAB); rate = comspeed(frequency, rate); /* XXX not comdefaultrate? */ bus_space_write_1(iot, ioh, com_dlbl, rate); bus_space_write_1(iot, ioh, com_dlbh, rate >> 8); bus_space_write_1(iot, ioh, com_lcr, LCR_8BITS); bus_space_write_1(iot, ioh, com_mcr, MCR_DTR | MCR_RTS); bus_space_write_1(iot, ioh, com_ier, 0); /* Make sure they are off */ bus_space_write_1(iot, ioh, com_fifo, FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1); stat = bus_space_read_1(iot, ioh, com_iir); splx(s); } #ifdef COM_CONSOLE void comcnprobe(struct consdev *cp) { bus_space_handle_t ioh; int found = 1; if (comconsaddr == 0) return; if (bus_space_map(comconsiot, comconsaddr, COM_NPORTS, 0, &ioh)) return; /* XXX Some com@acpi devices will fail the comprobe1() check */ if (comcons_reg_width != 4) found = comprobe1(comconsiot, ioh); bus_space_unmap(comconsiot, ioh, COM_NPORTS); if (!found) return; /* Locate the major number. */ for (commajor = 0; commajor < nchrdev; commajor++) if (cdevsw[commajor].d_open == comopen) break; /* Initialize required fields. */ cp->cn_dev = makedev(commajor, comconsunit); cp->cn_pri = CN_HIGHPRI; } void comcninit(struct consdev *cp) { if (bus_space_map(comconsiot, comconsaddr, COM_NPORTS, 0, &comconsioh)) panic("comcninit: mapping failed"); if (comconsfreq == 0) comconsfreq = COM_FREQ; cominit(comconsiot, comconsioh, comconsrate, comconsfreq); } int comcnattach(bus_space_tag_t iot, bus_addr_t iobase, int rate, int frequency, tcflag_t cflag) { static struct consdev comcons = { NULL, NULL, comcngetc, comcnputc, comcnpollc, NULL, NODEV, CN_LOWPRI }; #ifndef __sparc64__ if (bus_space_map(iot, iobase, COM_NPORTS, 0, &comconsioh)) return ENOMEM; #endif cominit(iot, comconsioh, rate, frequency); cn_tab = &comcons; comconsiot = iot; comconsaddr = iobase; comconscflag = cflag; comconsfreq = frequency; comconsrate = rate; return (0); } int comcngetc(dev_t dev) { int s = splhigh(); u_char stat, c; /* Block until a character becomes available. */ while (!ISSET(stat = comcn_read_reg(com_lsr), LSR_RXRDY)) continue; c = comcn_read_reg(com_data); /* Clear any interrupts generated by this transmission. */ stat = comcn_read_reg(com_iir); splx(s); return (c); } /* * Console kernel output character routine. */ void comcnputc(dev_t dev, int c) { int s = spltty(); int timo; /* Wait for any pending transmission to finish. */ timo = 2000; while (!ISSET(comcn_read_reg(com_lsr), LSR_TXRDY) && --timo) delay(1); comcn_write_reg(com_data, (u_int8_t)(c & 0xff)); bus_space_barrier(comconsiot, comconsioh, 0, COM_NPORTS << comcons_reg_shift, (BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE)); /* Wait for this transmission to complete. */ timo = 2000; while (!ISSET(comcn_read_reg(com_lsr), LSR_TXRDY) && --timo) delay(1); splx(s); } void comcnpollc(dev_t dev, int on) { } #endif /* COM_CONSOLE */ void com_enable_debugport(struct com_softc *); void com_fifo_probe(struct com_softc *); #ifdef COM_CONSOLE void com_enable_debugport(struct com_softc *sc) { int s; /* Turn on line break interrupt, set carrier. */ s = splhigh(); SET(sc->sc_mcr, MCR_DTR | MCR_RTS | MCR_IENABLE); com_write_reg(sc, com_mcr, sc->sc_mcr); splx(s); } #endif /* COM_CONSOLE */ void com_attach_subr(struct com_softc *sc) { int probe = 0; u_int8_t lcr, fifo; u_int32_t cpr; sc->sc_ier = 0; /* disable interrupts */ com_write_reg(sc, com_ier, sc->sc_ier); #ifdef COM_CONSOLE if (sc->sc_iot == comconsiot && sc->sc_iobase == comconsaddr) { comconsattached = 1; delay(10000); /* wait for output to finish */ SET(sc->sc_hwflags, COM_HW_CONSOLE); SET(sc->sc_swflags, COM_SW_SOFTCAR); } #endif /* * Probe for all known forms of UART. */ lcr = com_read_reg(sc, com_lcr); com_write_reg(sc, com_lcr, LCR_EFR); com_write_reg(sc, com_efr, 0); com_write_reg(sc, com_lcr, 0); com_write_reg(sc, com_fifo, FIFO_ENABLE); delay(100); /* * Skip specific probes if attachment code knows it already. */ if (sc->sc_uarttype == COM_UART_UNKNOWN) { switch (com_read_reg(sc, com_iir) >> 6) { case 0: sc->sc_uarttype = COM_UART_16450; break; case 2: sc->sc_uarttype = COM_UART_16550; break; case 3: sc->sc_uarttype = COM_UART_16550A; break; default: sc->sc_uarttype = COM_UART_UNKNOWN; break; } probe = 1; } /* Probe for ST16650s */ if (probe && sc->sc_uarttype == COM_UART_16550A) { com_write_reg(sc, com_lcr, lcr | LCR_DLAB); if (com_read_reg(sc, com_efr) == 0) { com_write_reg(sc, com_efr, EFR_CTS); if (com_read_reg(sc, com_efr) != 0) sc->sc_uarttype = COM_UART_ST16650; com_write_reg(sc, com_efr, 0); } else { com_write_reg(sc, com_lcr, LCR_EFR); if (com_read_reg(sc, com_efr) == 0) sc->sc_uarttype = COM_UART_ST16650V2; } } #if 0 /* until com works with large FIFOs */ /* Probe for XR16850s */ if (probe && sc->sc_uarttype == COM_UART_ST16650V2) { u_int8_t dlbl, dlbh; /* Enable latch access and get the current values. */ com_write_reg(sc, com_lcr, lcr | LCR_DLAB); dlbl = com_read_reg(sc, com_dlbl); dlbh = com_read_reg(sc, com_dlbh); /* Zero out the latch divisors */ com_write_reg(sc, com_dlbl, 0); com_write_reg(sc, com_dlbh, 0); if (com_read_reg(sc, com_dlbh) == 0x10) { sc->sc_uarttype = COM_UART_XR16850; sc->sc_uartrev = com_read_reg(sc, com_dlbl); } /* Reset to original. */ com_write_reg(sc, com_dlbl, dlbl); com_write_reg(sc, com_dlbh, dlbh); } #endif /* Probe for TI16750s */ if (probe && sc->sc_uarttype == COM_UART_16550A) { com_write_reg(sc, com_lcr, lcr | LCR_DLAB); com_write_reg(sc, com_fifo, FIFO_ENABLE | FIFO_ENABLE_64BYTE); if ((com_read_reg(sc, com_iir) >> 5) == 7) { #if 0 com_write_reg(sc, com_lcr, 0); if ((com_read_reg(sc, com_iir) >> 5) == 6) #endif sc->sc_uarttype = COM_UART_TI16750; } com_write_reg(sc, com_fifo, FIFO_ENABLE); } /* Reset the LCR (latch access is probably enabled). */ com_write_reg(sc, com_lcr, lcr); /* Probe for 8250 */ if (probe && sc->sc_uarttype == COM_UART_16450) { u_int8_t scr0, scr1, scr2; scr0 = com_read_reg(sc, com_scratch); com_write_reg(sc, com_scratch, 0xa5); scr1 = com_read_reg(sc, com_scratch); com_write_reg(sc, com_scratch, 0x5a); scr2 = com_read_reg(sc, com_scratch); com_write_reg(sc, com_scratch, scr0); if ((scr1 != 0xa5) || (scr2 != 0x5a)) sc->sc_uarttype = COM_UART_8250; } /* * Print UART type and initialize ourself. */ switch (sc->sc_uarttype) { case COM_UART_UNKNOWN: printf(": unknown uart\n"); break; case COM_UART_8250: printf(": ns8250, no fifo\n"); break; case COM_UART_16450: printf(": ns16450, no fifo\n"); break; case COM_UART_16550: printf(": ns16550, no working fifo\n"); break; case COM_UART_16550A: if (sc->sc_fifolen == 0) sc->sc_fifolen = 16; printf(": ns16550a, %d byte fifo\n", sc->sc_fifolen); SET(sc->sc_hwflags, COM_HW_FIFO); break; case COM_UART_ST16650: printf(": st16650, no working fifo\n"); break; case COM_UART_ST16650V2: if (sc->sc_fifolen == 0) sc->sc_fifolen = 32; printf(": st16650, %d byte fifo\n", sc->sc_fifolen); SET(sc->sc_hwflags, COM_HW_FIFO); break; case COM_UART_ST16C654: printf(": st16c654, 64 byte fifo\n"); SET(sc->sc_hwflags, COM_HW_FIFO); sc->sc_fifolen = 64; break; case COM_UART_TI16750: printf(": ti16750, 64 byte fifo\n"); SET(sc->sc_hwflags, COM_HW_FIFO); sc->sc_fifolen = 64; break; #if 0 case COM_UART_XR16850: printf(": xr16850 (rev %d), 128 byte fifo\n", sc->sc_uartrev); SET(sc->sc_hwflags, COM_HW_FIFO); sc->sc_fifolen = 128; break; #ifdef COM_UART_OX16C950 case COM_UART_OX16C950: printf(": ox16c950 (rev %d), 128 byte fifo\n", sc->sc_uartrev); SET(sc->sc_hwflags, COM_HW_FIFO); sc->sc_fifolen = 128; break; #endif #endif case COM_UART_XR17V35X: printf(": xr17v35x, 256 byte fifo\n"); SET(sc->sc_hwflags, COM_HW_FIFO); sc->sc_fifolen = 256; break; case COM_UART_DW_APB: printf(": dw16550"); SET(sc->sc_hwflags, COM_HW_FIFO); cpr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, com_cpr << 2); sc->sc_fifolen = CPR_FIFO_MODE(cpr) * 16; if (sc->sc_fifolen) { printf(", %d byte fifo\n", sc->sc_fifolen); } else { printf("\n"); /* * The DW-APB configuration on the Allwinner H6 SoC * does not provide the CPR register and will be * detected as having no FIFO. But it does have a * 256-byte FIFO and with the FIFO disabled the * LSR_RXRDY bit remains set even if the input * buffer is empty. As a workaround, treat as a * 1-byte FIFO. */ sc->sc_fifolen = 1; } break; default: panic("comattach: bad fifo type"); } #ifdef COM_CONSOLE if (!ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) #endif if (sc->sc_fifolen < 256) com_fifo_probe(sc); if (sc->sc_fifolen == 0) { CLR(sc->sc_hwflags, COM_HW_FIFO); sc->sc_fifolen = 1; } /* clear and disable fifo */ /* DW-APB UART cannot turn off FIFO here (ddb will not work) */ fifo = (sc->sc_uarttype == COM_UART_DW_APB) ? (FIFO_ENABLE | FIFO_TRIGGER_1) : 0; com_write_reg(sc, com_fifo, fifo | FIFO_RCV_RST | FIFO_XMT_RST); if (ISSET(com_read_reg(sc, com_lsr), LSR_RXRDY)) (void)com_read_reg(sc, com_data); com_write_reg(sc, com_fifo, fifo); sc->sc_mcr = 0; com_write_reg(sc, com_mcr, sc->sc_mcr); #ifdef COM_CONSOLE if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { int maj; /* locate the major number */ for (maj = 0; maj < nchrdev; maj++) if (cdevsw[maj].d_open == comopen) break; KASSERT(maj < nchrdev); cn_tab->cn_dev = makedev(maj, sc->sc_dev.dv_unit); printf("%s: console\n", sc->sc_dev.dv_xname); } #endif timeout_set(&sc->sc_diag_tmo, comdiag, sc); timeout_set(&sc->sc_dtr_tmo, com_raisedtr, sc); sc->sc_si = softintr_establish(IPL_TTY, comsoft, sc); if (sc->sc_si == NULL) panic("%s: can't establish soft interrupt", sc->sc_dev.dv_xname); /* * If there are no enable/disable functions, assume the device * is always enabled. */ if (!sc->enable) sc->enabled = 1; #ifdef COM_CONSOLE if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) com_enable_debugport(sc); #endif } void com_fifo_probe(struct com_softc *sc) { u_int8_t fifo, ier; int timo, len; if (!ISSET(sc->sc_hwflags, COM_HW_FIFO)) return; ier = 0; com_write_reg(sc, com_ier, ier); com_write_reg(sc, com_lcr, LCR_DLAB); com_write_reg(sc, com_dlbl, 3); com_write_reg(sc, com_dlbh, 0); com_write_reg(sc, com_lcr, LCR_PNONE | LCR_8BITS); com_write_reg(sc, com_mcr, MCR_LOOPBACK); fifo = FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST; if (sc->sc_uarttype == COM_UART_TI16750) fifo |= FIFO_ENABLE_64BYTE; com_write_reg(sc, com_fifo, fifo); for (len = 0; len < 256; len++) { com_write_reg(sc, com_data, (len + 1)); timo = 2000; while (!ISSET(com_read_reg(sc, com_lsr), LSR_TXRDY) && --timo) delay(1); if (!timo) break; } delay(100); for (len = 0; len < 256; len++) { timo = 2000; while (!ISSET(com_read_reg(sc, com_lsr), LSR_RXRDY) && --timo) delay(1); if (!timo || com_read_reg(sc, com_data) != (len + 1)) break; } /* For safety, always use the smaller value. */ if (sc->sc_fifolen > len) { printf("%s: probed fifo depth: %d bytes\n", sc->sc_dev.dv_xname, len); sc->sc_fifolen = len; } } uint8_t com_read_reg(struct com_softc *sc, bus_size_t reg) { reg <<= sc->sc_reg_shift; if (sc->sc_reg_width == 4) return bus_space_read_4(sc->sc_iot, sc->sc_ioh, reg); else return bus_space_read_1(sc->sc_iot, sc->sc_ioh, reg); } void com_write_reg(struct com_softc *sc, bus_size_t reg, uint8_t value) { reg <<= sc->sc_reg_shift; if (sc->sc_reg_width == 4) bus_space_write_4(sc->sc_iot, sc->sc_ioh, reg, value); else bus_space_write_1(sc->sc_iot, sc->sc_ioh, reg, value); } #ifdef COM_CONSOLE u_char comcons_reg_width; u_char comcons_reg_shift; uint8_t comcn_read_reg(bus_size_t reg) { reg <<= comcons_reg_shift; if (comcons_reg_width == 4) return bus_space_read_4(comconsiot, comconsioh, reg); else return bus_space_read_1(comconsiot, comconsioh, reg); } void comcn_write_reg(bus_size_t reg, uint8_t value) { reg <<= comcons_reg_shift; if (comcons_reg_width == 4) bus_space_write_4(comconsiot, comconsioh, reg, value); else bus_space_write_1(comconsiot, comconsioh, reg, value); } #endif
2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 /* $OpenBSD: ip_var.h,v 1.117 2024/04/17 20:48:51 bluhm Exp $ */ /* $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ip_var.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET_IP_VAR_H_ #define _NETINET_IP_VAR_H_ /* * Structure stored in mbuf in inpcb.ip_options * and passed to ip_output when ip options are in use. * The actual length of the options (including ipopt_dst) * is in m_len. */ #define MAX_IPOPTLEN 40 /* * Overlay for ip header used by other protocols (tcp, udp). */ struct ipovly { u_int8_t ih_x1[9]; /* (unused) */ u_int8_t ih_pr; /* protocol */ u_int16_t ih_len; /* protocol length */ struct in_addr ih_src; /* source internet address */ struct in_addr ih_dst; /* destination internet address */ }; struct ipstat { u_long ips_total; /* total packets received */ u_long ips_badsum; /* checksum bad */ u_long ips_tooshort; /* packet too short */ u_long ips_toosmall; /* not enough data */ u_long ips_badhlen; /* ip header length < data size */ u_long ips_badlen; /* ip length < ip header length */ u_long ips_fragments; /* fragments received */ u_long ips_fragdropped; /* frags dropped (dups, out of space) */ u_long ips_fragtimeout; /* fragments timed out */ u_long ips_forward; /* packets forwarded */ u_long ips_cantforward; /* packets rcvd for unreachable dest */ u_long ips_redirectsent; /* packets forwarded on same net */ u_long ips_noproto; /* unknown or unsupported protocol */ u_long ips_delivered; /* datagrams delivered to upper level*/ u_long ips_localout; /* total ip packets generated here */ u_long ips_odropped; /* lost output due to nobufs, etc. */ u_long ips_reassembled; /* total packets reassembled ok */ u_long ips_fragmented; /* datagrams successfully fragmented */ u_long ips_ofragments; /* output fragments created */ u_long ips_cantfrag; /* don't fragment flag was set, etc. */ u_long ips_badoptions; /* error in option processing */ u_long ips_noroute; /* packets discarded due to no route */ u_long ips_badvers; /* ip version != 4 */ u_long ips_rawout; /* total raw ip packets generated */ u_long ips_badfrags; /* malformed fragments (bad length) */ u_long ips_rcvmemdrop; /* frags dropped for lack of memory */ u_long ips_toolong; /* ip length > max ip packet size */ u_long ips_nogif; /* no match gif found */ u_long ips_badaddr; /* invalid address on header */ u_long ips_inswcsum; /* software checksummed on input */ u_long ips_outswcsum; /* software checksummed on output */ u_long ips_notmember; /* multicasts for unregistered groups */ u_long ips_rtcachehit; /* valid route found in cache */ u_long ips_rtcachemiss; /* route cache with new destination */ u_long ips_wrongif; /* packet received on wrong interface */ u_long ips_idropped; /* lost input due to nobufs, etc. */ }; struct ipoption { struct in_addr ipopt_dst; /* first-hop dst if source routed */ int8_t ipopt_list[MAX_IPOPTLEN]; /* options proper */ }; #ifdef _KERNEL #include <sys/percpu.h> enum ipstat_counters { ips_total, /* total packets received */ ips_badsum, /* checksum bad */ ips_tooshort, /* packet too short */ ips_toosmall, /* not enough data */ ips_badhlen, /* ip header length < data size */ ips_badlen, /* ip length < ip header length */ ips_fragments, /* fragments received */ ips_fragdropped, /* frags dropped (dups, out of space) */ ips_fragtimeout, /* fragments timed out */ ips_forward, /* packets forwarded */ ips_cantforward, /* packets rcvd for unreachable dest */ ips_redirectsent, /* packets forwarded on same net */ ips_noproto, /* unknown or unsupported protocol */ ips_delivered, /* datagrams delivered to upper level*/ ips_localout, /* total ip packets generated here */ ips_odropped, /* lost output packets due to nobufs, etc. */ ips_reassembled, /* total packets reassembled ok */ ips_fragmented, /* datagrams successfully fragmented */ ips_ofragments, /* output fragments created */ ips_cantfrag, /* don't fragment flag was set, etc. */ ips_badoptions, /* error in option processing */ ips_noroute, /* packets discarded due to no route */ ips_badvers, /* ip version != 4 */ ips_rawout, /* total raw ip packets generated */ ips_badfrags, /* malformed fragments (bad length) */ ips_rcvmemdrop, /* frags dropped for lack of memory */ ips_toolong, /* ip length > max ip packet size */ ips_nogif, /* no match gif found */ ips_badaddr, /* invalid address on header */ ips_inswcsum, /* software checksummed on input */ ips_outswcsum, /* software checksummed on output */ ips_notmember, /* multicasts for unregistered groups */ ips_rtcachehit, /* valid route to destination found in cache */ ips_rtcachemiss, /* route cache filled with new destination */ ips_wrongif, /* packet received on wrong interface */ ips_idropped, /* lost input packets due to nobufs, etc. */ ips_ncounters }; extern struct cpumem *ipcounters; static inline void ipstat_inc(enum ipstat_counters c) { counters_inc(ipcounters, c); } static inline void ipstat_add(enum ipstat_counters c, uint64_t v) { counters_add(ipcounters, c, v); } /* * Structure attached to inpcb.ip_moptions and * passed to ip_output when IP multicast options are in use. */ struct ip_moptions { struct in_multi **imo_membership; /* group memberships */ unsigned short imo_ifidx; /* ifp index for outgoing multicasts */ u_int8_t imo_ttl; /* TTL for outgoing multicasts */ u_int8_t imo_loop; /* 1 => hear sends if a member */ u_int16_t imo_num_memberships; /* no. memberships this socket */ u_int16_t imo_max_memberships; /* max memberships this socket */ }; #include <sys/queue.h> /* * Ip reassembly queue structures. */ LIST_HEAD(ipqehead, ipqent); struct ipqent { LIST_ENTRY(ipqent) ipqe_q; struct ip *ipqe_ip; struct mbuf *ipqe_m; /* mbuf contains packet */ uint16_t ipqe_mff; /* for IP fragmentation */ }; /* * Ip reassembly queue structure. Each fragment * being reassembled is attached to one of these structures. * They are timed out after ipq_ttl drops to 0, and may also * be reclaimed if memory becomes tight. */ struct ipq { LIST_ENTRY(ipq) ipq_q; /* to other reass headers */ u_int8_t ipq_ttl; /* time for reass q to live */ u_int8_t ipq_p; /* protocol of this fragment */ u_int16_t ipq_id; /* sequence id for reassembly */ struct ipqehead ipq_fragq; /* to ip fragment queue */ struct in_addr ipq_src, ipq_dst; }; struct ipoffnxt { int ion_off; int ion_nxt; }; /* flags passed to ip_output */ #define IP_FORWARDING 0x1 /* most of ip header exists */ #define IP_RAWOUTPUT 0x2 /* raw ip header exists */ #define IP_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */ #define IP_MTUDISC 0x0800 /* pmtu discovery, set DF */ extern struct ipstat ipstat; extern int ip_defttl; /* default IP ttl */ #define IPMTUDISCTIMEOUT (10 * 60) /* as per RFC 1191 */ extern int ip_mtudisc; /* mtu discovery */ extern int ip_mtudisc_timeout; /* seconds to timeout mtu discovery */ extern int ipport_firstauto; /* min port for port allocation */ extern int ipport_lastauto; /* max port for port allocation */ extern int ipport_hifirstauto; /* min dynamic/private port number */ extern int ipport_hilastauto; /* max dynamic/private port number */ extern int ipforwarding; /* enable IP forwarding */ #ifdef MROUTING extern int ipmforwarding; /* enable multicast forwarding */ #endif extern int ipmultipath; /* enable multipath routing */ extern unsigned int la_hold_total; extern const struct pr_usrreqs rip_usrreqs; extern struct rttimer_queue ip_mtudisc_timeout_q; extern struct pool ipqent_pool; struct rtentry; struct route; struct inpcb; struct ipsec_level; int ip_ctloutput(int, struct socket *, int, int, struct mbuf *); int ip_fragment(struct mbuf *, struct mbuf_list *, struct ifnet *, u_long); void ip_freemoptions(struct ip_moptions *); int ip_getmoptions(int, struct ip_moptions *, struct mbuf *); void ip_init(void); struct mbuf* ip_insertoptions(struct mbuf *, struct mbuf *, int *); int ip_mforward(struct mbuf *, struct ifnet *); int ip_optcopy(struct ip *, struct ip *); int ip_output(struct mbuf *, struct mbuf *, struct route *, int, struct ip_moptions *, const struct ipsec_level *, u_int32_t); u_int16_t ip_randomid(void); void ip_send(struct mbuf *); void ip_send_raw(struct mbuf *); void ip_slowtimo(void); struct mbuf * ip_srcroute(struct mbuf *); void ip_stripoptions(struct mbuf *); int ip_sysctl(int *, u_int, void *, size_t *, void *, size_t); void ip_savecontrol(struct inpcb *, struct mbuf **, struct ip *, struct mbuf *); int ip_input_if(struct mbuf **, int *, int, int, struct ifnet *); int ip_deliver(struct mbuf **, int *, int, int, int); void ip_forward(struct mbuf *, struct ifnet *, struct route *, int); int rip_ctloutput(int, struct socket *, int, int, struct mbuf *); void rip_init(void); int rip_input(struct mbuf **, int *, int, int); int rip_output(struct mbuf *, struct socket *, struct sockaddr *, struct mbuf *); struct mbuf * rip_chkhdr(struct mbuf *, struct mbuf *); int rip_attach(struct socket *, int, int); int rip_detach(struct socket *); void rip_lock(struct socket *); void rip_unlock(struct socket *); int rip_locked(struct socket *); int rip_bind(struct socket *, struct mbuf *, struct proc *); int rip_connect(struct socket *, struct mbuf *); int rip_disconnect(struct socket *); int rip_shutdown(struct socket *); int rip_send(struct socket *, struct mbuf *, struct mbuf *, struct mbuf *); #ifdef MROUTING extern struct socket *ip_mrouter[]; /* multicast routing daemon */ #endif #endif /* _KERNEL */ #endif /* _NETINET_IP_VAR_H_ */
763 765 765 661 728 53 729 6 61 20 725 26 743 103 641 8 2 2 29 12 70 32 18 10 30 10 504 211 11 3 3 6 9 1 3 1 2 5 8 4 8 733 105 719 660 2 98 3 11 731 729 2 730 5 685 723 7 17 729 5 12 13 59 108 110 92 37 714 708 24 13 531 648 675 581 98 11 590 79 198 501 561 157 2 1 3 50 2 50 50 50 50 50 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 /* $OpenBSD: vfs_lookup.c,v 1.88 2023/01/06 19:08:36 miod Exp $ */ /* $NetBSD: vfs_lookup.c,v 1.17 1996/02/09 19:00:59 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)vfs_lookup.c 8.6 (Berkeley) 11/21/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/syslimits.h> #include <sys/namei.h> #include <sys/vnode.h> #include <sys/lock.h> #include <sys/mount.h> #include <sys/errno.h> #include <sys/pool.h> #include <sys/filedesc.h> #include <sys/proc.h> #include <sys/pledge.h> #include <sys/file.h> #include <sys/fcntl.h> #ifdef KTRACE #include <sys/ktrace.h> #endif int component_push(struct componentname *cnp, char *component, size_t len) { if (cnp->cn_rpi + len + 1 >= MAXPATHLEN) return 0; if (cnp->cn_rpi > 1) cnp->cn_rpbuf[cnp->cn_rpi++] = '/'; memcpy(cnp->cn_rpbuf + cnp->cn_rpi, component, len); cnp->cn_rpi+=len; cnp->cn_rpbuf[cnp->cn_rpi] = '\0'; return 1; } void component_pop(struct componentname *cnp) { while(cnp->cn_rpi && cnp->cn_rpbuf[cnp->cn_rpi] != '/' ) cnp->cn_rpi--; if (cnp->cn_rpi == 0 && cnp->cn_rpbuf[0] == '/') cnp->cn_rpi++; cnp->cn_rpbuf[cnp->cn_rpi] = '\0'; } void ndinitat(struct nameidata *ndp, u_long op, u_long flags, enum uio_seg segflg, int dirfd, const char *namep, struct proc *p) { memset(ndp, 0, sizeof(*ndp)); ndp->ni_cnd.cn_nameiop = op; ndp->ni_cnd.cn_flags = flags; ndp->ni_segflg = segflg; ndp->ni_dirfd = dirfd; ndp->ni_dirp = namep; ndp->ni_cnd.cn_proc = p; } /* * Convert a pathname into a pointer to a vnode. * * The FOLLOW flag is set when symbolic links are to be followed * when they occur at the end of the name translation process. * Symbolic links are always followed for all other pathname * components other than the last. * * If the LOCKLEAF flag is set, a locked vnode is returned. * * The segflg defines whether the name is to be copied from user * space or kernel space. * * Overall outline of namei: * * copy in name * get starting directory * while (!done && !error) { * call lookup to search path. * if symbolic link, massage name in buffer and continue * } */ int namei(struct nameidata *ndp) { struct filedesc *fdp; /* pointer to file descriptor state */ char *cp; /* pointer into pathname argument */ struct vnode *dp; /* the directory we are searching */ struct iovec aiov; /* uio for reading symbolic links */ struct uio auio; int error, linklen; struct componentname *cnp = &ndp->ni_cnd; struct proc *p = cnp->cn_proc; ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_proc->p_ucred; #ifdef DIAGNOSTIC if (!cnp->cn_cred || !cnp->cn_proc) panic ("namei: bad cred/proc"); if (cnp->cn_nameiop & (~OPMASK)) panic ("namei: nameiop contaminated with flags"); if (cnp->cn_flags & OPMASK) panic ("namei: flags contaminated with nameiops"); #endif fdp = cnp->cn_proc->p_fd; /* * Get a buffer for the name to be translated, and copy the * name into the buffer. */ if ((cnp->cn_flags & HASBUF) == 0) cnp->cn_pnbuf = pool_get(&namei_pool, PR_WAITOK); if (ndp->ni_segflg == UIO_SYSSPACE) { ndp->ni_pathlen = strlcpy(cnp->cn_pnbuf, ndp->ni_dirp, MAXPATHLEN); if (ndp->ni_pathlen >= MAXPATHLEN) { error = ENAMETOOLONG; } else { error = 0; ndp->ni_pathlen++; /* ni_pathlen includes NUL */ } } else error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf, MAXPATHLEN, &ndp->ni_pathlen); /* * Fail on null pathnames */ if (error == 0 && ndp->ni_pathlen == 1) error = ENOENT; if (error) goto fail; #ifdef KTRACE if (KTRPOINT(cnp->cn_proc, KTR_NAMEI)) ktrnamei(cnp->cn_proc, cnp->cn_pnbuf); #endif /* * Strip trailing slashes, as requested */ if (cnp->cn_flags & STRIPSLASHES) { char *end = cnp->cn_pnbuf + ndp->ni_pathlen - 2; cp = end; while (cp >= cnp->cn_pnbuf && (*cp == '/')) cp--; /* Still some remaining characters in the buffer */ if (cp >= cnp->cn_pnbuf) { ndp->ni_pathlen -= (end - cp); *(cp + 1) = '\0'; } } ndp->ni_loopcnt = 0; /* * Get starting point for the translation. */ if ((ndp->ni_rootdir = fdp->fd_rdir) == NULL || (ndp->ni_cnd.cn_flags & KERNELPATH)) ndp->ni_rootdir = rootvnode; if (ndp->ni_cnd.cn_flags & KERNELPATH) { ndp->ni_cnd.cn_flags |= BYPASSUNVEIL; } else { error = pledge_namei(p, ndp, cnp->cn_pnbuf); if (error) goto fail; } /* * Check if starting from root directory or current directory. */ if (cnp->cn_pnbuf[0] == '/') { dp = ndp->ni_rootdir; vref(dp); if (cnp->cn_flags & REALPATH && cnp->cn_rpi == 0) { cnp->cn_rpbuf[0] = '/'; cnp->cn_rpbuf[1] = '\0'; cnp->cn_rpi = 1; } } else if (ndp->ni_dirfd == AT_FDCWD) { dp = fdp->fd_cdir; vref(dp); unveil_start_relative(p, ndp, dp); unveil_check_component(p, ndp, dp); } else { struct file *fp = fd_getfile(fdp, ndp->ni_dirfd); if (fp == NULL) { error = EBADF; goto fail; } dp = (struct vnode *)fp->f_data; if (fp->f_type != DTYPE_VNODE || dp->v_type != VDIR) { FRELE(fp, p); error = ENOTDIR; goto fail; } vref(dp); unveil_start_relative(p, ndp, dp); unveil_check_component(p, ndp, dp); FRELE(fp, p); } for (;;) { if (!dp->v_mount) { /* Give up if the directory is no longer mounted */ vrele(dp); error = ENOENT; goto fail; } cnp->cn_nameptr = cnp->cn_pnbuf; ndp->ni_startdir = dp; if ((error = vfs_lookup(ndp)) != 0) goto fail; /* * If not a symbolic link, return search result. */ if ((cnp->cn_flags & ISSYMLINK) == 0) { if ((error = unveil_check_final(p, ndp))) { if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN) && (ndp->ni_vp != ndp->ni_dvp)) vput(ndp->ni_dvp); if (ndp->ni_vp) { if ((cnp->cn_flags & LOCKLEAF)) vput(ndp->ni_vp); else vrele(ndp->ni_vp); } goto fail; } if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0) pool_put(&namei_pool, cnp->cn_pnbuf); else cnp->cn_flags |= HASBUF; return (0); } if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN)) VOP_UNLOCK(ndp->ni_dvp); if (ndp->ni_loopcnt++ >= SYMLOOP_MAX) { error = ELOOP; break; } if (ndp->ni_pathlen > 1) cp = pool_get(&namei_pool, PR_WAITOK); else cp = cnp->cn_pnbuf; aiov.iov_base = cp; aiov.iov_len = MAXPATHLEN; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_offset = 0; auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_SYSSPACE; auio.uio_procp = cnp->cn_proc; auio.uio_resid = MAXPATHLEN; error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred); if (error) { badlink: if (ndp->ni_pathlen > 1) pool_put(&namei_pool, cp); break; } linklen = MAXPATHLEN - auio.uio_resid; if (linklen == 0) { error = ENOENT; goto badlink; } if (linklen + ndp->ni_pathlen >= MAXPATHLEN) { error = ENAMETOOLONG; goto badlink; } if (ndp->ni_pathlen > 1) { memcpy(cp + linklen, ndp->ni_next, ndp->ni_pathlen); pool_put(&namei_pool, cnp->cn_pnbuf); cnp->cn_pnbuf = cp; } else cnp->cn_pnbuf[linklen] = '\0'; ndp->ni_pathlen += linklen; vput(ndp->ni_vp); dp = ndp->ni_dvp; /* * Check if root directory should replace current directory. */ if (cnp->cn_pnbuf[0] == '/') { vrele(dp); dp = ndp->ni_rootdir; vref(dp); ndp->ni_unveil_match = NULL; unveil_check_component(p, ndp, dp); if (cnp->cn_flags & REALPATH) { cnp->cn_rpbuf[0] = '/'; cnp->cn_rpbuf[1] = '\0'; cnp->cn_rpi = 1; } } else if (cnp->cn_flags & REALPATH) { component_pop(cnp); } } vrele(ndp->ni_dvp); vput(ndp->ni_vp); fail: pool_put(&namei_pool, cnp->cn_pnbuf); ndp->ni_vp = NULL; return (error); } /* * Search a pathname. * This is a very central and rather complicated routine. * * The pathname is pointed to by ni_cnd.cn_nameptr and is of length * ni_pathlen. The starting directory is taken from ni_startdir. The * pathname is descended until done, or a symbolic link is encountered. * If the path is completed the flag ISLASTCN is set in ni_cnd.cn_flags. * If a symbolic link need interpretation is encountered, the flag ISSYMLINK * is set in ni_cnd.cn_flags. * * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on * whether the name is to be looked up, created, renamed, or deleted. * When CREATE, RENAME, or DELETE is specified, information usable in * creating, renaming, or deleting a directory entry may be calculated. * If flag has LOCKPARENT or'ed into it, the parent directory is returned * locked. If flag has WANTPARENT or'ed into it, the parent directory is * returned unlocked. Otherwise the parent directory is not returned. If * the target of the pathname exists and LOCKLEAF is or'ed into the flag * the target is returned locked, otherwise it is returned unlocked. * When creating or renaming and LOCKPARENT is specified, the target may not * be ".". When deleting and LOCKPARENT is specified, the target may be ".". * * Overall outline of lookup: * * dirloop: * identify next component of name at ndp->ni_ptr * handle degenerate case where name is null string * if .. and crossing mount points and on mounted filesys, find parent * call VOP_LOOKUP routine for next component name * directory vnode returned in ni_dvp, unlocked unless LOCKPARENT set * component vnode returned in ni_vp (if it exists), locked. * if result vnode is mounted on and crossing mount points, * find mounted on vnode * if more components of name, do next level at dirloop * return the answer in ni_vp, locked if LOCKLEAF set * if LOCKPARENT set, return locked parent in ni_dvp * if WANTPARENT set, return unlocked parent in ni_dvp */ int vfs_lookup(struct nameidata *ndp) { char *cp; /* pointer into pathname argument */ struct vnode *dp = NULL; /* the directory we are searching */ struct vnode *tdp; /* saved dp */ struct mount *mp; /* mount table entry */ int docache; /* == 0 do not cache last component */ int wantparent; /* 1 => wantparent or lockparent flag */ int rdonly; /* lookup read-only flag bit */ int error = 0; int dpunlocked = 0; /* dp has already been unlocked */ int slashes; struct componentname *cnp = &ndp->ni_cnd; /* * Setup: break out flag bits into variables. */ wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT); docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE; if (cnp->cn_nameiop == DELETE || (wantparent && cnp->cn_nameiop != CREATE)) docache = 0; rdonly = cnp->cn_flags & RDONLY; ndp->ni_dvp = NULL; cnp->cn_flags &= ~ISSYMLINK; dp = ndp->ni_startdir; ndp->ni_startdir = NULLVP; vn_lock(dp, LK_EXCLUSIVE | LK_RETRY); /* * If we have a leading string of slashes, remove them, and just make * sure the current node is a directory. */ cp = cnp->cn_nameptr; if (*cp == '/') { do { cp++; } while (*cp == '/'); ndp->ni_pathlen -= cp - cnp->cn_nameptr; cnp->cn_nameptr = cp; if (dp->v_type != VDIR) { error = ENOTDIR; goto bad; } /* * If we've exhausted the path name, then just return the * current node. If the caller requested the parent node (i.e. * it's a CREATE, DELETE, or RENAME), and we don't have one * (because this is the root directory), then we must fail. */ if (cnp->cn_nameptr[0] == '\0') { if (ndp->ni_dvp == NULL && wantparent) { error = EISDIR; goto bad; } ndp->ni_vp = dp; cnp->cn_flags |= ISLASTCN; goto terminal; } } dirloop: /* * Search a new directory. * * The last component of the filename is left accessible via * cnp->cn_nameptr for callers that need the name. Callers needing * the name set the SAVENAME flag. When done, they assume * responsibility for freeing the pathname buffer. */ cnp->cn_consume = 0; /* XXX: Figure out the length of the last component. */ cp = cnp->cn_nameptr; while (*cp && (*cp != '/')) cp++; cnp->cn_namelen = cp - cnp->cn_nameptr; if (cnp->cn_namelen > NAME_MAX) { error = ENAMETOOLONG; goto bad; } #ifdef NAMEI_DIAGNOSTIC { char c = *cp; *cp = '\0'; printf("{%s}: ", cnp->cn_nameptr); *cp = c; } #endif if (cnp->cn_flags & REALPATH) { size_t len = cp - cnp->cn_nameptr; if (len == 2 && cnp->cn_nameptr[0] == '.' && cnp->cn_nameptr[1] == '.') component_pop(cnp); else if (!(len == 1 && cnp->cn_nameptr[0] == '.')) { if (!component_push(cnp, cnp->cn_nameptr, len)) { error = ENAMETOOLONG; goto bad; } } } ndp->ni_pathlen -= cnp->cn_namelen; ndp->ni_next = cp; /* * If this component is followed by a slash, then move the pointer to * the next component forward, and remember that this component must be * a directory. */ if (*cp == '/') { do { cp++; } while (*cp == '/'); slashes = cp - ndp->ni_next; ndp->ni_pathlen -= slashes; ndp->ni_next = cp; cnp->cn_flags |= REQUIREDIR; } else { slashes = 0; cnp->cn_flags &= ~REQUIREDIR; } /* * We do special processing on the last component, whether or not it's * a directory. Cache all intervening lookups, but not the final one. */ if (*cp == '\0') { if (docache) cnp->cn_flags |= MAKEENTRY; else cnp->cn_flags &= ~MAKEENTRY; cnp->cn_flags |= ISLASTCN; } else { cnp->cn_flags |= MAKEENTRY; cnp->cn_flags &= ~ISLASTCN; } if (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.' && cnp->cn_nameptr[0] == '.') cnp->cn_flags |= ISDOTDOT; else cnp->cn_flags &= ~ISDOTDOT; /* * Handle "..": two special cases. * 1. If at root directory (e.g. after chroot) * or at absolute root directory * then ignore it so can't get out. * 2. If this vnode is the root of a mounted * filesystem, then replace it with the * vnode which was mounted on so we take the * .. in the other file system. */ if (cnp->cn_flags & ISDOTDOT) { for (;;) { if (dp == ndp->ni_rootdir || dp == rootvnode) { ndp->ni_dvp = dp; ndp->ni_vp = dp; vref(dp); ndp->ni_unveil_match = NULL; goto nextname; } if ((dp->v_flag & VROOT) == 0 || (cnp->cn_flags & NOCROSSMOUNT)) break; tdp = dp; dp = dp->v_mount->mnt_vnodecovered; vput(tdp); vref(dp); unveil_check_component(curproc, ndp, dp); vn_lock(dp, LK_EXCLUSIVE | LK_RETRY); } } /* * We now have a segment name to search for, and a directory to search. */ ndp->ni_dvp = dp; ndp->ni_vp = NULL; cnp->cn_flags &= ~PDIRUNLOCK; unveil_check_component(curproc, ndp, dp); if ((error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) != 0) { #ifdef DIAGNOSTIC if (ndp->ni_vp != NULL) panic("leaf should be empty"); #endif #ifdef NAMEI_DIAGNOSTIC printf("not found\n"); #endif /* * Allow for unveiling a file in a directory which we cannot * create ourselves. */ if (ndp->ni_pledge == PLEDGE_UNVEIL && (error == EPERM || error == EACCES || error == EROFS)) error = EJUSTRETURN; if (error != EJUSTRETURN) goto bad; /* * If this was not the last component, or there were trailing * slashes, then the name must exist. */ if (cnp->cn_flags & REQUIREDIR) { error = ENOENT; goto bad; } /* * If creating and at end of pathname, then can consider * allowing file to be created. Check for a read only * filesystem and disallow this unless we are unveil'ing */ if (ndp->ni_pledge != PLEDGE_UNVEIL && (rdonly || (ndp->ni_dvp->v_mount->mnt_flag & MNT_RDONLY))) { error = EROFS; goto bad; } /* * We return with ni_vp NULL to indicate that the entry * doesn't currently exist, leaving a pointer to the * (possibly locked) directory inode in ndp->ni_dvp. */ if (cnp->cn_flags & SAVESTART) { ndp->ni_startdir = ndp->ni_dvp; vref(ndp->ni_startdir); } return (0); } #ifdef NAMEI_DIAGNOSTIC printf("found\n"); #endif /* * Take into account any additional components consumed by the * underlying filesystem. This will include any trailing slashes after * the last component consumed. */ if (cnp->cn_consume > 0) { if (cnp->cn_consume >= slashes) { cnp->cn_flags &= ~REQUIREDIR; } ndp->ni_pathlen -= cnp->cn_consume - slashes; ndp->ni_next += cnp->cn_consume - slashes; cnp->cn_consume = 0; if (ndp->ni_next[0] == '\0') cnp->cn_flags |= ISLASTCN; } dp = ndp->ni_vp; /* * Check to see if the vnode has been mounted on; * if so find the root of the mounted file system. */ while (dp->v_type == VDIR && (mp = dp->v_mountedhere) && (cnp->cn_flags & NOCROSSMOUNT) == 0) { if (vfs_busy(mp, VB_READ|VB_WAIT)) continue; VOP_UNLOCK(dp); error = VFS_ROOT(mp, &tdp); vfs_unbusy(mp); if (error) { dpunlocked = 1; goto bad2; } vrele(dp); ndp->ni_vp = dp = tdp; } /* * Check for symbolic link. Back up over any slashes that we skipped, * as we will need them again. */ if ((dp->v_type == VLNK) && (cnp->cn_flags & (FOLLOW|REQUIREDIR))) { ndp->ni_pathlen += slashes; ndp->ni_next -= slashes; cnp->cn_flags |= ISSYMLINK; return (0); } /* * Check for directory, if the component was followed by a series of * slashes. */ if ((dp->v_type != VDIR) && (cnp->cn_flags & REQUIREDIR)) { error = ENOTDIR; goto bad2; } nextname: /* * Not a symbolic link. If this was not the last component, then * continue at the next component, else return. */ if (!(cnp->cn_flags & ISLASTCN)) { cnp->cn_nameptr = ndp->ni_next; vrele(ndp->ni_dvp); goto dirloop; } terminal: /* * Check for read-only file systems. */ if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) { /* * Disallow directory write attempts on read-only * file systems. */ if (rdonly || (dp->v_mount->mnt_flag & MNT_RDONLY) || (wantparent && (ndp->ni_dvp->v_mount->mnt_flag & MNT_RDONLY))) { error = EROFS; goto bad2; } } if (ndp->ni_dvp != NULL) { if (cnp->cn_flags & SAVESTART) { ndp->ni_startdir = ndp->ni_dvp; vref(ndp->ni_startdir); } if (!wantparent) vrele(ndp->ni_dvp); } if ((cnp->cn_flags & LOCKLEAF) == 0) VOP_UNLOCK(dp); return (0); bad2: if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN) && ((cnp->cn_flags & PDIRUNLOCK) == 0)) VOP_UNLOCK(ndp->ni_dvp); vrele(ndp->ni_dvp); bad: if (dpunlocked) vrele(dp); else vput(dp); ndp->ni_vp = NULL; return (error); } /* * Reacquire a path name component. */ int vfs_relookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp) { struct vnode *dp = NULL; /* the directory we are searching */ int wantparent; /* 1 => wantparent or lockparent flag */ int rdonly; /* lookup read-only flag bit */ int error = 0; #ifdef NAMEI_DIAGNOSTIC char *cp; /* DEBUG: check name ptr/len */ #endif /* * Setup: break out flag bits into variables. */ wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT); rdonly = cnp->cn_flags & RDONLY; cnp->cn_flags &= ~ISSYMLINK; dp = dvp; vn_lock(dp, LK_EXCLUSIVE | LK_RETRY); /* dirloop: */ /* * Search a new directory. * * The last component of the filename is left accessible via * cnp->cn_nameptr for callers that need the name. Callers needing * the name set the SAVENAME flag. When done, they assume * responsibility for freeing the pathname buffer. */ #ifdef NAMEI_DIAGNOSTIC /* XXX: Figure out the length of the last component. */ cp = cnp->cn_nameptr; while (*cp && (*cp != '/')) { cp++; } if (cnp->cn_namelen != cp - cnp->cn_nameptr) panic("relookup: bad len"); if (*cp != 0) panic("relookup: not last component"); printf("{%s}: ", cnp->cn_nameptr); #endif /* * Check for degenerate name (e.g. / or "") * which is a way of talking about a directory, * e.g. like "/." or ".". */ if (cnp->cn_nameptr[0] == '\0') panic("relookup: null name"); if (cnp->cn_flags & ISDOTDOT) panic ("relookup: lookup on dot-dot"); /* * We now have a segment name to search for, and a directory to search. */ if ((error = VOP_LOOKUP(dp, vpp, cnp)) != 0) { #ifdef DIAGNOSTIC if (*vpp != NULL) panic("leaf should be empty"); #endif if (error != EJUSTRETURN) goto bad; /* * If creating and at end of pathname, then can consider * allowing file to be created. */ if (rdonly || (dvp->v_mount->mnt_flag & MNT_RDONLY)) { error = EROFS; goto bad; } /* ASSERT(dvp == ndp->ni_startdir) */ if (cnp->cn_flags & SAVESTART) vref(dvp); /* * We return with ni_vp NULL to indicate that the entry * doesn't currently exist, leaving a pointer to the * (possibly locked) directory inode in ndp->ni_dvp. */ return (0); } dp = *vpp; #ifdef DIAGNOSTIC /* * Check for symbolic link */ if (dp->v_type == VLNK && (cnp->cn_flags & FOLLOW)) panic ("relookup: symlink found."); #endif /* * Check for read-only file systems. */ if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) { /* * Disallow directory write attempts on read-only * file systems. */ if (rdonly || (dp->v_mount->mnt_flag & MNT_RDONLY) || (wantparent && (dvp->v_mount->mnt_flag & MNT_RDONLY))) { error = EROFS; goto bad2; } } /* ASSERT(dvp == ndp->ni_startdir) */ if (cnp->cn_flags & SAVESTART) vref(dvp); if (!wantparent) vrele(dvp); if ((cnp->cn_flags & LOCKLEAF) == 0) VOP_UNLOCK(dp); return (0); bad2: if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN)) VOP_UNLOCK(dvp); vrele(dvp); bad: vput(dp); *vpp = NULL; return (error); }
22 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 /* $OpenBSD: tcp_timer.c,v 1.76 2024/01/28 20:34:25 bluhm Exp $ */ /* $NetBSD: tcp_timer.c,v 1.14 1996/02/13 23:44:09 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)tcp_timer.c 8.1 (Berkeley) 6/10/93 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/protosw.h> #include <sys/kernel.h> #include <sys/pool.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/in_pcb.h> #include <netinet/ip_var.h> #include <netinet/tcp.h> #include <netinet/tcp_fsm.h> #include <netinet/tcp_timer.h> #include <netinet/tcp_var.h> #include <netinet/tcp_debug.h> #include <netinet/ip_icmp.h> #include <netinet/tcp_seq.h> /* * Locks used to protect struct members in this file: * T tcp_timer_mtx global tcp timer data structures */ int tcp_always_keepalive; int tcp_keepidle; int tcp_keepintvl; int tcp_maxpersistidle; /* max idle time in persist */ int tcp_maxidle; /* [T] max idle time for keep alive */ /* * Time to delay the ACK. This is initialized in tcp_init(), unless * its patched. */ int tcp_delack_msecs; void tcp_timer_rexmt(void *); void tcp_timer_persist(void *); void tcp_timer_keep(void *); void tcp_timer_2msl(void *); void tcp_timer_reaper(void *); void tcp_timer_delack(void *); const tcp_timer_func_t tcp_timer_funcs[TCPT_NTIMERS] = { tcp_timer_rexmt, tcp_timer_persist, tcp_timer_keep, tcp_timer_2msl, tcp_timer_reaper, tcp_timer_delack, }; /* * Timer state initialization, called from tcp_init(). */ void tcp_timer_init(void) { if (tcp_keepidle == 0) tcp_keepidle = TCPTV_KEEP_IDLE; if (tcp_keepintvl == 0) tcp_keepintvl = TCPTV_KEEPINTVL; if (tcp_maxpersistidle == 0) tcp_maxpersistidle = TCPTV_KEEP_IDLE; if (tcp_delack_msecs == 0) tcp_delack_msecs = TCP_DELACK_MSECS; } /* * Callout to process delayed ACKs for a TCPCB. */ void tcp_timer_delack(void *arg) { struct tcpcb *otp = NULL, *tp = arg; short ostate; /* * If tcp_output() wasn't able to transmit the ACK * for whatever reason, it will restart the delayed * ACK callout. */ NET_LOCK(); /* Ignore canceled timeouts or timeouts that have been rescheduled. */ if (!ISSET((tp)->t_flags, TF_TMR_DELACK) || timeout_pending(&tp->t_timer[TCPT_DELACK])) goto out; CLR((tp)->t_flags, TF_TMR_DELACK); if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG) { otp = tp; ostate = tp->t_state; } tp->t_flags |= TF_ACKNOW; (void) tcp_output(tp); if (otp) tcp_trace(TA_TIMER, ostate, tp, otp, NULL, TCPT_DELACK, 0); out: NET_UNLOCK(); } /* * Tcp protocol timeout routine called every 500 ms. * Updates the timers in all active tcb's and * causes finite state machine actions if timers expire. */ void tcp_slowtimo(void) { mtx_enter(&tcp_timer_mtx); tcp_maxidle = TCPTV_KEEPCNT * tcp_keepintvl; tcp_iss += TCP_ISSINCR2/PR_SLOWHZ; /* increment iss */ mtx_leave(&tcp_timer_mtx); } /* * Cancel all timers for TCP tp. */ void tcp_canceltimers(struct tcpcb *tp) { int i; for (i = 0; i < TCPT_NTIMERS; i++) TCP_TIMER_DISARM(tp, i); } int tcp_backoff[TCP_MAXRXTSHIFT + 1] = { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 }; int tcp_totbackoff = 511; /* sum of tcp_backoff[] */ /* * TCP timer processing. */ void tcp_timer_freesack(struct tcpcb *); void tcp_timer_freesack(struct tcpcb *tp) { struct sackhole *p, *q; /* * Free SACK holes for 2MSL and REXMT timers. */ q = tp->snd_holes; while (q != NULL) { p = q; q = q->next; pool_put(&sackhl_pool, p); } tp->snd_holes = 0; } void tcp_timer_rexmt(void *arg) { struct tcpcb *otp = NULL, *tp = arg; struct inpcb *inp; uint32_t rto; short ostate; NET_LOCK(); inp = tp->t_inpcb; /* Ignore canceled timeouts or timeouts that have been rescheduled. */ if (!ISSET((tp)->t_flags, TF_TMR_REXMT) || timeout_pending(&tp->t_timer[TCPT_REXMT])) goto out; CLR((tp)->t_flags, TF_TMR_REXMT); if ((tp->t_flags & TF_PMTUD_PEND) && inp && SEQ_GEQ(tp->t_pmtud_th_seq, tp->snd_una) && SEQ_LT(tp->t_pmtud_th_seq, (int)(tp->snd_una + tp->t_maxseg))) { struct sockaddr_in sin; struct icmp icmp; /* TF_PMTUD_PEND is set in tcp_ctlinput() which is IPv4 only */ KASSERT(!ISSET(inp->inp_flags, INP_IPV6)); tp->t_flags &= ~TF_PMTUD_PEND; /* XXX create fake icmp message with relevant entries */ icmp.icmp_nextmtu = tp->t_pmtud_nextmtu; icmp.icmp_ip.ip_len = tp->t_pmtud_ip_len; icmp.icmp_ip.ip_hl = tp->t_pmtud_ip_hl; icmp.icmp_ip.ip_dst = inp->inp_faddr; icmp_mtudisc(&icmp, inp->inp_rtableid); /* * Notify all connections to the same peer about * new mss and trigger retransmit. */ bzero(&sin, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_addr = inp->inp_faddr; in_pcbnotifyall(&tcbtable, &sin, inp->inp_rtableid, EMSGSIZE, tcp_mtudisc); goto out; } tcp_timer_freesack(tp); if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) { tp->t_rxtshift = TCP_MAXRXTSHIFT; tcpstat_inc(tcps_timeoutdrop); tp = tcp_drop(tp, tp->t_softerror ? tp->t_softerror : ETIMEDOUT); goto out; } if (inp->inp_socket->so_options & SO_DEBUG) { otp = tp; ostate = tp->t_state; } tcpstat_inc(tcps_rexmttimeo); rto = TCP_REXMTVAL(tp); if (rto < tp->t_rttmin) rto = tp->t_rttmin; TCPT_RANGESET(tp->t_rxtcur, rto * tcp_backoff[tp->t_rxtshift], tp->t_rttmin, TCPTV_REXMTMAX); TCP_TIMER_ARM(tp, TCPT_REXMT, tp->t_rxtcur); /* * If we are losing and we are trying path MTU discovery, * try turning it off. This will avoid black holes in * the network which suppress or fail to send "packet * too big" ICMP messages. We should ideally do * lots more sophisticated searching to find the right * value here... */ if (ip_mtudisc && inp && TCPS_HAVEESTABLISHED(tp->t_state) && tp->t_rxtshift > TCP_MAXRXTSHIFT / 6) { struct rtentry *rt = NULL; /* No data to send means path mtu is not a problem */ if (!inp->inp_socket->so_snd.sb_cc) goto leave; rt = in_pcbrtentry(inp); /* Check if path MTU discovery is disabled already */ if (rt && (rt->rt_flags & RTF_HOST) && (rt->rt_locks & RTV_MTU)) goto leave; rt = NULL; switch(tp->pf) { #ifdef INET6 case PF_INET6: /* * We can not turn off path MTU for IPv6. * Do nothing for now, maybe lower to * minimum MTU. */ break; #endif case PF_INET: rt = icmp_mtudisc_clone(inp->inp_faddr, inp->inp_rtableid, 0); break; } if (rt != NULL) { /* Disable path MTU discovery */ if ((rt->rt_locks & RTV_MTU) == 0) { rt->rt_locks |= RTV_MTU; in_rtchange(inp, 0); } rtfree(rt); } leave: ; } /* * If losing, let the lower level know and try for * a better route. Also, if we backed off this far, * our srtt estimate is probably bogus. Clobber it * so we'll take the next rtt measurement as our srtt; * move the current srtt into rttvar to keep the current * retransmit times until then. */ if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) { in_losing(inp); tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT); tp->t_srtt = 0; } tp->snd_nxt = tp->snd_una; /* * Note: We overload snd_last to function also as the * snd_last variable described in RFC 2582 */ tp->snd_last = tp->snd_max; /* * If timing a segment in this window, stop the timer. */ tp->t_rtttime = 0; #ifdef TCP_ECN /* * if ECN is enabled, there might be a broken firewall which * blocks ecn packets. fall back to non-ecn. */ if ((tp->t_state == TCPS_SYN_SENT || tp->t_state == TCPS_SYN_RECEIVED) && tcp_do_ecn && !(tp->t_flags & TF_DISABLE_ECN)) tp->t_flags |= TF_DISABLE_ECN; #endif /* * Close the congestion window down to one segment * (we'll open it by one segment for each ack we get). * Since we probably have a window's worth of unacked * data accumulated, this "slow start" keeps us from * dumping all that data as back-to-back packets (which * might overwhelm an intermediate gateway). * * There are two phases to the opening: Initially we * open by one mss on each ack. This makes the window * size increase exponentially with time. If the * window is larger than the path can handle, this * exponential growth results in dropped packet(s) * almost immediately. To get more time between * drops but still "push" the network to take advantage * of improving conditions, we switch from exponential * to linear window opening at some threshold size. * For a threshold, we use half the current window * size, truncated to a multiple of the mss. * * (the minimum cwnd that will give us exponential * growth is 2 mss. We don't allow the threshold * to go below this.) */ { u_long win; win = ulmin(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg; if (win < 2) win = 2; tp->snd_cwnd = tp->t_maxseg; tp->snd_ssthresh = win * tp->t_maxseg; tp->t_dupacks = 0; #ifdef TCP_ECN tp->snd_last = tp->snd_max; tp->t_flags |= TF_SEND_CWR; #endif #if 1 /* TCP_ECN */ tcpstat_inc(tcps_cwr_timeout); #endif } (void) tcp_output(tp); if (otp) tcp_trace(TA_TIMER, ostate, tp, otp, NULL, TCPT_REXMT, 0); out: NET_UNLOCK(); } void tcp_timer_persist(void *arg) { struct tcpcb *otp = NULL, *tp = arg; uint32_t rto; short ostate; uint64_t now; NET_LOCK(); /* Ignore canceled timeouts or timeouts that have been rescheduled. */ if (!ISSET((tp)->t_flags, TF_TMR_PERSIST) || timeout_pending(&tp->t_timer[TCPT_PERSIST])) goto out; CLR((tp)->t_flags, TF_TMR_PERSIST); if (TCP_TIMER_ISARMED(tp, TCPT_REXMT)) goto out; if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG) { otp = tp; ostate = tp->t_state; } tcpstat_inc(tcps_persisttimeo); /* * Hack: if the peer is dead/unreachable, we do not * time out if the window is closed. After a full * backoff, drop the connection if the idle time * (no responses to probes) reaches the maximum * backoff that we would use if retransmitting. */ rto = TCP_REXMTVAL(tp); if (rto < tp->t_rttmin) rto = tp->t_rttmin; now = tcp_now(); if (tp->t_rxtshift == TCP_MAXRXTSHIFT && ((now - tp->t_rcvtime) >= tcp_maxpersistidle || (now - tp->t_rcvtime) >= rto * tcp_totbackoff)) { tcpstat_inc(tcps_persistdrop); tp = tcp_drop(tp, ETIMEDOUT); goto out; } tcp_setpersist(tp); tp->t_force = 1; (void) tcp_output(tp); tp->t_force = 0; if (otp) tcp_trace(TA_TIMER, ostate, tp, otp, NULL, TCPT_PERSIST, 0); out: NET_UNLOCK(); } void tcp_timer_keep(void *arg) { struct tcpcb *otp = NULL, *tp = arg; short ostate; NET_LOCK(); /* Ignore canceled timeouts or timeouts that have been rescheduled. */ if (!ISSET((tp)->t_flags, TF_TMR_KEEP) || timeout_pending(&tp->t_timer[TCPT_KEEP])) goto out; CLR((tp)->t_flags, TF_TMR_KEEP); if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG) { otp = tp; ostate = tp->t_state; } tcpstat_inc(tcps_keeptimeo); if (TCPS_HAVEESTABLISHED(tp->t_state) == 0) goto dropit; if ((tcp_always_keepalive || tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE) && tp->t_state <= TCPS_CLOSING) { int maxidle; uint64_t now; maxidle = READ_ONCE(tcp_maxidle); now = tcp_now(); if ((maxidle > 0) && ((now - tp->t_rcvtime) >= tcp_keepidle + maxidle)) goto dropit; /* * Send a packet designed to force a response * if the peer is up and reachable: * either an ACK if the connection is still alive, * or an RST if the peer has closed the connection * due to timeout or reboot. * Using sequence number tp->snd_una-1 * causes the transmitted zero-length segment * to lie outside the receive window; * by the protocol spec, this requires the * correspondent TCP to respond. */ tcpstat_inc(tcps_keepprobe); tcp_respond(tp, mtod(tp->t_template, caddr_t), NULL, tp->rcv_nxt, tp->snd_una - 1, 0, 0, now); TCP_TIMER_ARM(tp, TCPT_KEEP, tcp_keepintvl); } else TCP_TIMER_ARM(tp, TCPT_KEEP, tcp_keepidle); if (otp) tcp_trace(TA_TIMER, ostate, tp, otp, NULL, TCPT_KEEP, 0); out: NET_UNLOCK(); return; dropit: tcpstat_inc(tcps_keepdrops); tp = tcp_drop(tp, ETIMEDOUT); NET_UNLOCK(); } void tcp_timer_2msl(void *arg) { struct tcpcb *otp = NULL, *tp = arg; short ostate; int maxidle; uint64_t now; NET_LOCK(); /* Ignore canceled timeouts or timeouts that have been rescheduled. */ if (!ISSET((tp)->t_flags, TF_TMR_2MSL) || timeout_pending(&tp->t_timer[TCPT_2MSL])) goto out; CLR((tp)->t_flags, TF_TMR_2MSL); if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG) { otp = tp; ostate = tp->t_state; } tcp_timer_freesack(tp); maxidle = READ_ONCE(tcp_maxidle); now = tcp_now(); if (tp->t_state != TCPS_TIME_WAIT && ((maxidle == 0) || ((now - tp->t_rcvtime) <= maxidle))) TCP_TIMER_ARM(tp, TCPT_2MSL, tcp_keepintvl); else tp = tcp_close(tp); if (otp) tcp_trace(TA_TIMER, ostate, tp, otp, NULL, TCPT_2MSL, 0); out: NET_UNLOCK(); } void tcp_timer_reaper(void *arg) { struct tcpcb *tp = arg; /* * This timer is necessary to delay the pool_put() after all timers * have finished, even if they were sleeping to grab the net lock. * Putting the pool_put() in a timer is sufficient as all timers run * from the same timeout thread. Note that neither softnet thread nor * user process may access the tcpcb after arming the reaper timer. * Freeing may run in parallel as it does not grab the net lock. */ pool_put(&tcpcb_pool, tp); tcpstat_inc(tcps_closed); }
3 3 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 /* $OpenBSD: ipsec_output.c,v 1.98 2024/02/11 01:27:45 bluhm Exp $ */ /* * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) * * Copyright (c) 2000-2001 Angelos D. Keromytis. * * Permission to use, copy, and modify this software with or without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or * modification of this software. * You may use this code under the GNU public license if you so wish. Please * contribute changes back to the authors under this freer than GPL license * so that we may further the use of strong encryption without limitations to * all. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR * PURPOSE. */ #include "pf.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/kernel.h> #include <sys/timeout.h> #include <net/if.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/in_pcb.h> #include <netinet/ip_var.h> #include <netinet6/ip6_var.h> #if NPF > 0 #include <net/pfvar.h> #endif #include <netinet/udp.h> #include <netinet/ip_ipip.h> #include <netinet/ip_ah.h> #include <netinet/ip_esp.h> #include <netinet/ip_ipcomp.h> #include <crypto/cryptodev.h> #include <crypto/xform.h> #ifdef ENCDEBUG #define DPRINTF(fmt, args...) \ do { \ if (encdebug) \ printf("%s: " fmt "\n", __func__, ## args); \ } while (0) #else #define DPRINTF(fmt, args...) \ do { } while (0) #endif int udpencap_enable = 1; /* enabled by default */ int udpencap_port = 4500; /* triggers decapsulation */ /* * Loop over a tdb chain, taking into consideration protocol tunneling. The * fourth argument is set if the first encapsulation header is already in * place. */ int ipsp_process_packet(struct mbuf *m, struct tdb *tdb, int af, int tunalready) { int hlen, off, error; #ifdef INET6 struct ip6_ext ip6e; int nxt; int dstopt = 0; #endif int setdf = 0; struct ip *ip; #ifdef INET6 struct ip6_hdr *ip6; #endif /* INET6 */ #ifdef ENCDEBUG char buf[INET6_ADDRSTRLEN]; #endif /* Check that the transform is allowed by the administrator. */ if ((tdb->tdb_sproto == IPPROTO_ESP && !esp_enable) || (tdb->tdb_sproto == IPPROTO_AH && !ah_enable) || (tdb->tdb_sproto == IPPROTO_IPCOMP && !ipcomp_enable)) { DPRINTF("IPsec outbound packet dropped due to policy " "(check your sysctls)"); error = EHOSTUNREACH; goto drop; } /* Sanity check. */ if (!tdb->tdb_xform) { DPRINTF("uninitialized TDB"); error = EHOSTUNREACH; goto drop; } /* Check if the SPI is invalid. */ if (tdb->tdb_flags & TDBF_INVALID) { DPRINTF("attempt to use invalid SA %s/%08x/%u", ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi), tdb->tdb_sproto); error = ENXIO; goto drop; } /* Check that the network protocol is supported */ switch (tdb->tdb_dst.sa.sa_family) { case AF_INET: break; #ifdef INET6 case AF_INET6: break; #endif /* INET6 */ default: DPRINTF("attempt to use SA %s/%08x/%u for protocol family %d", ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi), tdb->tdb_sproto, tdb->tdb_dst.sa.sa_family); error = EPFNOSUPPORT; goto drop; } /* * Register first use if applicable, setup relevant expiration timer. */ if (tdb->tdb_first_use == 0) { tdb->tdb_first_use = gettime(); if (tdb->tdb_flags & TDBF_FIRSTUSE) { if (timeout_add_sec(&tdb->tdb_first_tmo, tdb->tdb_exp_first_use)) tdb_ref(tdb); } if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE) { if (timeout_add_sec(&tdb->tdb_sfirst_tmo, tdb->tdb_soft_first_use)) tdb_ref(tdb); } } /* * Check for tunneling if we don't have the first header in place. * When doing Ethernet-over-IP, we are handed an already-encapsulated * frame, so we don't need to re-encapsulate. */ if (tunalready == 0) { /* * If the target protocol family is different, we know we'll be * doing tunneling. */ if (af == tdb->tdb_dst.sa.sa_family) { switch (af) { case AF_INET: hlen = sizeof(struct ip); break; #ifdef INET6 case AF_INET6: hlen = sizeof(struct ip6_hdr); break; #endif /* INET6 */ } /* Bring the network header in the first mbuf. */ if (m->m_len < hlen) { if ((m = m_pullup(m, hlen)) == NULL) { error = ENOBUFS; goto drop; } } if (af == AF_INET) { ip = mtod(m, struct ip *); /* * This is not a bridge packet, remember if we * had IP_DF. */ setdf = ip->ip_off & htons(IP_DF); } #ifdef INET6 if (af == AF_INET6) ip6 = mtod(m, struct ip6_hdr *); #endif /* INET6 */ } /* Do the appropriate encapsulation, if necessary. */ if ((tdb->tdb_dst.sa.sa_family != af) || /* PF mismatch */ (tdb->tdb_flags & TDBF_TUNNELING) || /* Tunneling needed */ (tdb->tdb_xform->xf_type == XF_IP4) || /* ditto */ ((tdb->tdb_dst.sa.sa_family == AF_INET) && (tdb->tdb_dst.sin.sin_addr.s_addr != INADDR_ANY) && (tdb->tdb_dst.sin.sin_addr.s_addr != ip->ip_dst.s_addr)) || #ifdef INET6 ((tdb->tdb_dst.sa.sa_family == AF_INET6) && (!IN6_IS_ADDR_UNSPECIFIED(&tdb->tdb_dst.sin6.sin6_addr)) && (!IN6_ARE_ADDR_EQUAL(&tdb->tdb_dst.sin6.sin6_addr, &ip6->ip6_dst))) || #endif /* INET6 */ 0) { /* Fix IPv4 header checksum and length. */ if (af == AF_INET) { if (m->m_len < sizeof(struct ip)) if ((m = m_pullup(m, sizeof(struct ip))) == NULL) { error = ENOBUFS; goto drop; } ip = mtod(m, struct ip *); ip->ip_len = htons(m->m_pkthdr.len); ip->ip_sum = 0; ip->ip_sum = in_cksum(m, ip->ip_hl << 2); } #ifdef INET6 /* Fix IPv6 header payload length. */ if (af == AF_INET6) { if (m->m_len < sizeof(struct ip6_hdr)) if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) { error = ENOBUFS; goto drop; } if (m->m_pkthdr.len - sizeof(*ip6) > IPV6_MAXPACKET) { /* No jumbogram support. */ error = ENXIO; /*?*/ goto drop; } ip6 = mtod(m, struct ip6_hdr *); ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6)); } #endif /* INET6 */ /* Encapsulate -- m may be changed or set to NULL. */ error = ipip_output(&m, tdb); if ((m == NULL) && (!error)) error = EFAULT; if (error) goto drop; if (tdb->tdb_dst.sa.sa_family == AF_INET && setdf) { if (m->m_len < sizeof(struct ip)) if ((m = m_pullup(m, sizeof(struct ip))) == NULL) { error = ENOBUFS; goto drop; } ip = mtod(m, struct ip *); ip->ip_off |= htons(IP_DF); } /* Remember that we appended a tunnel header. */ mtx_enter(&tdb->tdb_mtx); tdb->tdb_flags |= TDBF_USEDTUNNEL; mtx_leave(&tdb->tdb_mtx); } } /* * If this is just an IP-IP TDB and we're told there's already an * encapsulation header or ipip_output() has encapsulated it, move on. */ if (tdb->tdb_xform->xf_type == XF_IP4) return ipsp_process_done(m, tdb); /* Extract some information off the headers. */ switch (tdb->tdb_dst.sa.sa_family) { case AF_INET: ip = mtod(m, struct ip *); hlen = ip->ip_hl << 2; off = offsetof(struct ip, ip_p); break; #ifdef INET6 case AF_INET6: ip6 = mtod(m, struct ip6_hdr *); hlen = sizeof(struct ip6_hdr); off = offsetof(struct ip6_hdr, ip6_nxt); nxt = ip6->ip6_nxt; /* * chase mbuf chain to find the appropriate place to * put AH/ESP/IPcomp header. * IPv6 hbh dest1 rthdr ah* [esp* dest2 payload] */ do { switch (nxt) { case IPPROTO_AH: case IPPROTO_ESP: case IPPROTO_IPCOMP: /* * we should not skip security header added * beforehand. */ goto exitip6loop; case IPPROTO_HOPOPTS: case IPPROTO_DSTOPTS: case IPPROTO_ROUTING: /* * if we see 2nd destination option header, * we should stop there. */ if (nxt == IPPROTO_DSTOPTS && dstopt) goto exitip6loop; if (nxt == IPPROTO_DSTOPTS) { /* * seen 1st or 2nd destination option. * next time we see one, it must be 2nd. */ dstopt = 1; } else if (nxt == IPPROTO_ROUTING) { /* * if we see destination option next * time, it must be dest2. */ dstopt = 2; } if (m->m_pkthdr.len < hlen + sizeof(ip6e)) { error = EINVAL; goto drop; } /* skip this header */ m_copydata(m, hlen, sizeof(ip6e), (caddr_t)&ip6e); nxt = ip6e.ip6e_nxt; off = hlen + offsetof(struct ip6_ext, ip6e_nxt); /* * we will never see nxt == IPPROTO_AH * so it is safe to omit AH case. */ hlen += (ip6e.ip6e_len + 1) << 3; break; default: goto exitip6loop; } } while (hlen < m->m_pkthdr.len); exitip6loop: break; #endif /* INET6 */ default: error = EPFNOSUPPORT; goto drop; } if (m->m_pkthdr.len < hlen) { error = EINVAL; goto drop; } ipsecstat_add(ipsec_ouncompbytes, m->m_pkthdr.len); tdbstat_add(tdb, tdb_ouncompbytes, m->m_pkthdr.len); /* Non expansion policy for IPCOMP */ if (tdb->tdb_sproto == IPPROTO_IPCOMP) { if ((m->m_pkthdr.len - hlen) < tdb->tdb_compalgxform->minlen) { /* No need to compress, leave the packet untouched */ ipcompstat_inc(ipcomps_minlen); return ipsp_process_done(m, tdb); } } /* Invoke the IPsec transform. */ return (*(tdb->tdb_xform->xf_output))(m, tdb, hlen, off); drop: m_freem(m); return error; } /* * Called by the IPsec output transform callbacks, to transmit the packet * or do further processing, as necessary. */ int ipsp_process_done(struct mbuf *m, struct tdb *tdb) { struct ip *ip; #ifdef INET6 struct ip6_hdr *ip6; #endif /* INET6 */ struct tdb *tdbo; struct tdb_ident *tdbi; struct m_tag *mtag; int roff, error; NET_ASSERT_LOCKED(); tdb->tdb_last_used = gettime(); if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0) { struct mbuf *mi; struct udphdr *uh; int iphlen; if (!udpencap_enable || !udpencap_port) { error = ENXIO; goto drop; } switch (tdb->tdb_dst.sa.sa_family) { case AF_INET: iphlen = sizeof(struct ip); break; #ifdef INET6 case AF_INET6: iphlen = sizeof(struct ip6_hdr); break; #endif /* INET6 */ default: DPRINTF("unknown protocol family (%d)", tdb->tdb_dst.sa.sa_family); error = EPFNOSUPPORT; goto drop; } mi = m_makespace(m, iphlen, sizeof(struct udphdr), &roff); if (mi == NULL) { error = ENOMEM; goto drop; } uh = (struct udphdr *)(mtod(mi, caddr_t) + roff); uh->uh_sport = uh->uh_dport = htons(udpencap_port); if (tdb->tdb_udpencap_port) uh->uh_dport = tdb->tdb_udpencap_port; uh->uh_ulen = htons(m->m_pkthdr.len - iphlen); uh->uh_sum = 0; #ifdef INET6 if (tdb->tdb_dst.sa.sa_family == AF_INET6) m->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT; #endif /* INET6 */ espstat_inc(esps_udpencout); } switch (tdb->tdb_dst.sa.sa_family) { case AF_INET: /* Fix the header length, for AH processing. */ ip = mtod(m, struct ip *); ip->ip_len = htons(m->m_pkthdr.len); if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0) ip->ip_p = IPPROTO_UDP; break; #ifdef INET6 case AF_INET6: /* Fix the header length, for AH processing. */ if (m->m_pkthdr.len < sizeof(*ip6)) { error = ENXIO; goto drop; } if (m->m_pkthdr.len - sizeof(*ip6) > IPV6_MAXPACKET) { /* No jumbogram support. */ error = ENXIO; goto drop; } ip6 = mtod(m, struct ip6_hdr *); ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6)); if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0) ip6->ip6_nxt = IPPROTO_UDP; break; #endif /* INET6 */ default: DPRINTF("unknown protocol family (%d)", tdb->tdb_dst.sa.sa_family); error = EPFNOSUPPORT; goto drop; } /* * Add a record of what we've done or what needs to be done to the * packet. */ mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_DONE, sizeof(struct tdb_ident), M_NOWAIT); if (mtag == NULL) { DPRINTF("could not allocate packet tag"); error = ENOMEM; goto drop; } tdbi = (struct tdb_ident *)(mtag + 1); tdbi->dst = tdb->tdb_dst; tdbi->proto = tdb->tdb_sproto; tdbi->spi = tdb->tdb_spi; tdbi->rdomain = tdb->tdb_rdomain; m_tag_prepend(m, mtag); ipsecstat_pkt(ipsec_opackets, ipsec_obytes, m->m_pkthdr.len); tdbstat_pkt(tdb, tdb_opackets, tdb_obytes, m->m_pkthdr.len); /* If there's another (bundled) TDB to apply, do so. */ tdbo = tdb_ref(tdb->tdb_onext); if (tdbo != NULL) { KERNEL_ASSERT_LOCKED(); error = ipsp_process_packet(m, tdbo, tdb->tdb_dst.sa.sa_family, 0); tdb_unref(tdbo); return error; } #if NPF > 0 /* Add pf tag if requested. */ pf_tag_packet(m, tdb->tdb_tag, -1); pf_pkt_addr_changed(m); #endif if (tdb->tdb_rdomain != tdb->tdb_rdomain_post) m->m_pkthdr.ph_rtableid = tdb->tdb_rdomain_post; /* * We're done with IPsec processing, transmit the packet using the * appropriate network protocol (IP or IPv6). SPD lookup will be * performed again there. */ switch (tdb->tdb_dst.sa.sa_family) { case AF_INET: error = ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL, 0); break; #ifdef INET6 case AF_INET6: /* * We don't need massage, IPv6 header fields are always in * net endian. */ error = ip6_output(m, NULL, NULL, 0, NULL, NULL); break; #endif /* INET6 */ default: error = EPFNOSUPPORT; break; } return error; drop: m_freem(m); return error; } ssize_t ipsec_hdrsz(struct tdb *tdbp) { ssize_t adjust; switch (tdbp->tdb_sproto) { case IPPROTO_IPIP: adjust = 0; break; case IPPROTO_ESP: if (tdbp->tdb_encalgxform == NULL) return (-1); /* Header length */ adjust = 2 * sizeof(u_int32_t) + tdbp->tdb_ivlen; if (tdbp->tdb_flags & TDBF_UDPENCAP) adjust += sizeof(struct udphdr); /* Authenticator */ if (tdbp->tdb_authalgxform != NULL) adjust += tdbp->tdb_authalgxform->authsize; /* Padding */ adjust += MAX(4, tdbp->tdb_encalgxform->blocksize); break; case IPPROTO_AH: if (tdbp->tdb_authalgxform == NULL) return (-1); adjust = AH_FLENGTH + sizeof(u_int32_t); adjust += tdbp->tdb_authalgxform->authsize; break; default: return (-1); } if (!(tdbp->tdb_flags & TDBF_TUNNELING) && !(tdbp->tdb_flags & TDBF_USEDTUNNEL)) return (adjust); switch (tdbp->tdb_dst.sa.sa_family) { case AF_INET: adjust += sizeof(struct ip); break; #ifdef INET6 case AF_INET6: adjust += sizeof(struct ip6_hdr); break; #endif /* INET6 */ } return (adjust); } void ipsec_adjust_mtu(struct mbuf *m, u_int32_t mtu) { struct tdb_ident *tdbi; struct tdb *tdbp; struct m_tag *mtag; ssize_t adjust; NET_ASSERT_LOCKED(); for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_OUT_DONE, NULL); mtag; mtag = m_tag_find(m, PACKET_TAG_IPSEC_OUT_DONE, mtag)) { tdbi = (struct tdb_ident *)(mtag + 1); tdbp = gettdb(tdbi->rdomain, tdbi->spi, &tdbi->dst, tdbi->proto); if (tdbp == NULL) break; if ((adjust = ipsec_hdrsz(tdbp)) == -1) { tdb_unref(tdbp); break; } mtu -= adjust; tdbp->tdb_mtu = mtu; tdbp->tdb_mtutimeout = gettime() + ip_mtudisc_timeout; DPRINTF("spi %08x mtu %d adjust %ld mbuf %p", ntohl(tdbp->tdb_spi), tdbp->tdb_mtu, adjust, m); tdb_unref(tdbp); } }
21 21 21 21 2 1 1 1 21 21 21 21 21 21 21 21 21 21 20 21 15 21 21 21 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 /* $OpenBSD: kstat.c,v 1.2 2022/01/31 05:09:17 dlg Exp $ */ /* * Copyright (c) 2020 David Gwynne <dlg@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/types.h> #include <sys/malloc.h> #include <sys/pool.h> #include <sys/time.h> /* for kstat_set_cpu */ #include <sys/proc.h> #include <sys/sched.h> #include <sys/kstat.h> RBT_HEAD(kstat_id_tree, kstat); static inline int kstat_id_cmp(const struct kstat *a, const struct kstat *b) { if (a->ks_id > b->ks_id) return (1); if (a->ks_id < b->ks_id) return (-1); return (0); } RBT_PROTOTYPE(kstat_id_tree, kstat, ks_id_entry, kstat_id_cmp); RBT_HEAD(kstat_pv_tree, kstat); static inline int kstat_pv_cmp(const struct kstat *a, const struct kstat *b) { int rv; rv = strcmp(a->ks_provider, b->ks_provider); if (rv != 0) return (rv); if (a->ks_instance > b->ks_instance) return (1); if (a->ks_instance < b->ks_instance) return (-1); rv = strcmp(a->ks_name, b->ks_name); if (rv != 0) return (rv); if (a->ks_unit > b->ks_unit) return (1); if (a->ks_unit < b->ks_unit) return (-1); return (0); } RBT_PROTOTYPE(kstat_pv_tree, kstat, ks_pv_entry, kstat_pv_cmp); RBT_HEAD(kstat_nm_tree, kstat); static inline int kstat_nm_cmp(const struct kstat *a, const struct kstat *b) { int rv; rv = strcmp(a->ks_name, b->ks_name); if (rv != 0) return (rv); if (a->ks_unit > b->ks_unit) return (1); if (a->ks_unit < b->ks_unit) return (-1); rv = strcmp(a->ks_provider, b->ks_provider); if (rv != 0) return (rv); if (a->ks_instance > b->ks_instance) return (1); if (a->ks_instance < b->ks_instance) return (-1); return (0); } RBT_PROTOTYPE(kstat_nm_tree, kstat, ks_nm_entry, kstat_nm_cmp); struct kstat_lock_ops { void (*enter)(void *); void (*leave)(void *); }; #define kstat_enter(_ks) (_ks)->ks_lock_ops->enter((_ks)->ks_lock) #define kstat_leave(_ks) (_ks)->ks_lock_ops->leave((_ks)->ks_lock) const struct kstat_lock_ops kstat_rlock_ops = { (void (*)(void *))rw_enter_read, (void (*)(void *))rw_exit_read, }; const struct kstat_lock_ops kstat_wlock_ops = { (void (*)(void *))rw_enter_write, (void (*)(void *))rw_exit_write, }; const struct kstat_lock_ops kstat_mutex_ops = { (void (*)(void *))mtx_enter, (void (*)(void *))mtx_leave, }; void kstat_cpu_enter(void *); void kstat_cpu_leave(void *); const struct kstat_lock_ops kstat_cpu_ops = { kstat_cpu_enter, kstat_cpu_leave, }; struct rwlock kstat_lock = RWLOCK_INITIALIZER("kstat"); /* * The global state is versioned so changes to the set of kstats * can be detected. This is an int so it can be read atomically on * any arch, which is a ridiculous optimisation, really. */ unsigned int kstat_version = 0; /* * kstat structures have a unique identifier so they can be found * quickly. Identifiers are 64bit in the hope that it won't wrap * during the runtime of a system. The identifiers start at 1 so that * 0 can be used as the first value for userland to iterate with. */ uint64_t kstat_next_id = 1; struct kstat_id_tree kstat_id_tree = RBT_INITIALIZER(); struct kstat_pv_tree kstat_pv_tree = RBT_INITIALIZER(); struct kstat_nm_tree kstat_nm_tree = RBT_INITIALIZER(); struct pool kstat_pool; struct rwlock kstat_default_lock = RWLOCK_INITIALIZER("kstatlk"); int kstat_read(struct kstat *); int kstat_copy(struct kstat *, void *); int kstatattach(int num) { /* XXX install system stats here */ return (0); } int kstatopen(dev_t dev, int flag, int mode, struct proc *p) { return (0); } int kstatclose(dev_t dev, int flag, int mode, struct proc *p) { return (0); } int kstatioc_enter(struct kstat_req *ksreq) { int error; error = rw_enter(&kstat_lock, RW_READ | RW_INTR); if (error != 0) return (error); if (!ISSET(ksreq->ks_rflags, KSTATIOC_F_IGNVER) && ksreq->ks_version != kstat_version) { error = EINVAL; goto error; } return (0); error: rw_exit(&kstat_lock); return (error); } int kstatioc_leave(struct kstat_req *ksreq, struct kstat *ks) { void *buf = NULL; size_t klen = 0, ulen = 0; struct timespec updated; int error = 0; if (ks == NULL) { error = ENOENT; goto error; } switch (ks->ks_state) { case KSTAT_S_CREATED: ksreq->ks_updated = ks->ks_created; ksreq->ks_interval.tv_sec = 0; ksreq->ks_interval.tv_nsec = 0; ksreq->ks_datalen = 0; ksreq->ks_dataver = 0; break; case KSTAT_S_INSTALLED: ksreq->ks_dataver = ks->ks_dataver; ksreq->ks_interval = ks->ks_interval; if (ksreq->ks_data == NULL) { /* userland doesn't want actual data, so shortcut */ kstat_enter(ks); ksreq->ks_datalen = ks->ks_datalen; ksreq->ks_updated = ks->ks_updated; kstat_leave(ks); break; } klen = ks->ks_datalen; /* KSTAT_F_REALLOC */ buf = malloc(klen, M_TEMP, M_WAITOK|M_CANFAIL); if (buf == NULL) { error = ENOMEM; goto error; } kstat_enter(ks); error = (*ks->ks_read)(ks); if (error == 0) { updated = ks->ks_updated; /* KSTAT_F_REALLOC */ KASSERTMSG(ks->ks_datalen == klen, "kstat doesnt support resized data yet"); error = (*ks->ks_copy)(ks, buf); } kstat_leave(ks); if (error != 0) goto error; ulen = ksreq->ks_datalen; ksreq->ks_datalen = klen; /* KSTAT_F_REALLOC */ ksreq->ks_updated = updated; break; default: panic("ks %p unexpected state %u", ks, ks->ks_state); } ksreq->ks_version = kstat_version; ksreq->ks_id = ks->ks_id; if (strlcpy(ksreq->ks_provider, ks->ks_provider, sizeof(ksreq->ks_provider)) >= sizeof(ksreq->ks_provider)) panic("kstat %p provider string has grown", ks); ksreq->ks_instance = ks->ks_instance; if (strlcpy(ksreq->ks_name, ks->ks_name, sizeof(ksreq->ks_name)) >= sizeof(ksreq->ks_name)) panic("kstat %p name string has grown", ks); ksreq->ks_unit = ks->ks_unit; ksreq->ks_created = ks->ks_created; ksreq->ks_type = ks->ks_type; ksreq->ks_state = ks->ks_state; error: rw_exit(&kstat_lock); if (buf != NULL) { if (error == 0) error = copyout(buf, ksreq->ks_data, min(klen, ulen)); free(buf, M_TEMP, klen); } return (error); } int kstatioc_find_id(struct kstat_req *ksreq) { struct kstat *ks, key; int error; error = kstatioc_enter(ksreq); if (error != 0) return (error); key.ks_id = ksreq->ks_id; ks = RBT_FIND(kstat_id_tree, &kstat_id_tree, &key); return (kstatioc_leave(ksreq, ks)); } int kstatioc_nfind_id(struct kstat_req *ksreq) { struct kstat *ks, key; int error; error = kstatioc_enter(ksreq); if (error != 0) return (error); key.ks_id = ksreq->ks_id; ks = RBT_NFIND(kstat_id_tree, &kstat_id_tree, &key); return (kstatioc_leave(ksreq, ks)); } int kstatioc_find_pv(struct kstat_req *ksreq) { struct kstat *ks, key; int error; error = kstatioc_enter(ksreq); if (error != 0) return (error); key.ks_provider = ksreq->ks_provider; key.ks_instance = ksreq->ks_instance; key.ks_name = ksreq->ks_name; key.ks_unit = ksreq->ks_unit; ks = RBT_FIND(kstat_pv_tree, &kstat_pv_tree, &key); return (kstatioc_leave(ksreq, ks)); } int kstatioc_nfind_pv(struct kstat_req *ksreq) { struct kstat *ks, key; int error; error = kstatioc_enter(ksreq); if (error != 0) return (error); key.ks_provider = ksreq->ks_provider; key.ks_instance = ksreq->ks_instance; key.ks_name = ksreq->ks_name; key.ks_unit = ksreq->ks_unit; ks = RBT_NFIND(kstat_pv_tree, &kstat_pv_tree, &key); return (kstatioc_leave(ksreq, ks)); } int kstatioc_find_nm(struct kstat_req *ksreq) { struct kstat *ks, key; int error; error = kstatioc_enter(ksreq); if (error != 0) return (error); key.ks_name = ksreq->ks_name; key.ks_unit = ksreq->ks_unit; key.ks_provider = ksreq->ks_provider; key.ks_instance = ksreq->ks_instance; ks = RBT_FIND(kstat_nm_tree, &kstat_nm_tree, &key); return (kstatioc_leave(ksreq, ks)); } int kstatioc_nfind_nm(struct kstat_req *ksreq) { struct kstat *ks, key; int error; error = kstatioc_enter(ksreq); if (error != 0) return (error); key.ks_name = ksreq->ks_name; key.ks_unit = ksreq->ks_unit; key.ks_provider = ksreq->ks_provider; key.ks_instance = ksreq->ks_instance; ks = RBT_NFIND(kstat_nm_tree, &kstat_nm_tree, &key); return (kstatioc_leave(ksreq, ks)); } int kstatioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { struct kstat_req *ksreq = (struct kstat_req *)data; int error = 0; KERNEL_UNLOCK(); switch (cmd) { case KSTATIOC_VERSION: *(unsigned int *)data = kstat_version; break; case KSTATIOC_FIND_ID: error = kstatioc_find_id(ksreq); break; case KSTATIOC_NFIND_ID: error = kstatioc_nfind_id(ksreq); break; case KSTATIOC_FIND_PROVIDER: error = kstatioc_find_pv(ksreq); break; case KSTATIOC_NFIND_PROVIDER: error = kstatioc_nfind_pv(ksreq); break; case KSTATIOC_FIND_NAME: error = kstatioc_find_nm(ksreq); break; case KSTATIOC_NFIND_NAME: error = kstatioc_nfind_nm(ksreq); break; default: error = ENOTTY; break; } KERNEL_LOCK(); return (error); } void kstat_init(void) { static int initialized = 0; if (initialized) return; pool_init(&kstat_pool, sizeof(struct kstat), 0, IPL_NONE, PR_WAITOK | PR_RWLOCK, "kstatmem", NULL); initialized = 1; } int kstat_strcheck(const char *str) { size_t i, l; l = strlen(str); if (l == 0 || l >= KSTAT_STRLEN) return (-1); for (i = 0; i < l; i++) { int ch = str[i]; if (ch >= 'a' && ch <= 'z') continue; if (ch >= 'A' && ch <= 'Z') continue; if (ch >= '0' && ch <= '9') continue; switch (ch) { case '-': case '_': case '.': break; default: return (-1); } } return (0); } struct kstat * kstat_create(const char *provider, unsigned int instance, const char *name, unsigned int unit, unsigned int type, unsigned int flags) { struct kstat *ks, *oks; if (kstat_strcheck(provider) == -1) panic("invalid provider string"); if (kstat_strcheck(name) == -1) panic("invalid name string"); kstat_init(); ks = pool_get(&kstat_pool, PR_WAITOK|PR_ZERO); ks->ks_provider = provider; ks->ks_instance = instance; ks->ks_name = name; ks->ks_unit = unit; ks->ks_flags = flags; ks->ks_type = type; ks->ks_state = KSTAT_S_CREATED; getnanouptime(&ks->ks_created); ks->ks_updated = ks->ks_created; ks->ks_lock = &kstat_default_lock; ks->ks_lock_ops = &kstat_wlock_ops; ks->ks_read = kstat_read; ks->ks_copy = kstat_copy; rw_enter_write(&kstat_lock); ks->ks_id = kstat_next_id; oks = RBT_INSERT(kstat_pv_tree, &kstat_pv_tree, ks); if (oks == NULL) { /* commit */ kstat_next_id++; kstat_version++; oks = RBT_INSERT(kstat_nm_tree, &kstat_nm_tree, ks); if (oks != NULL) panic("kstat name collision! (%llu)", ks->ks_id); oks = RBT_INSERT(kstat_id_tree, &kstat_id_tree, ks); if (oks != NULL) panic("kstat id collision! (%llu)", ks->ks_id); } rw_exit_write(&kstat_lock); if (oks != NULL) { pool_put(&kstat_pool, ks); return (NULL); } return (ks); } void kstat_set_rlock(struct kstat *ks, struct rwlock *rwl) { KASSERT(ks->ks_state == KSTAT_S_CREATED); ks->ks_lock = rwl; ks->ks_lock_ops = &kstat_rlock_ops; } void kstat_set_wlock(struct kstat *ks, struct rwlock *rwl) { KASSERT(ks->ks_state == KSTAT_S_CREATED); ks->ks_lock = rwl; ks->ks_lock_ops = &kstat_wlock_ops; } void kstat_set_mutex(struct kstat *ks, struct mutex *mtx) { KASSERT(ks->ks_state == KSTAT_S_CREATED); ks->ks_lock = mtx; ks->ks_lock_ops = &kstat_mutex_ops; } void kstat_cpu_enter(void *p) { struct cpu_info *ci = p; sched_peg_curproc(ci); } void kstat_cpu_leave(void *p) { atomic_clearbits_int(&curproc->p_flag, P_CPUPEG); } void kstat_set_cpu(struct kstat *ks, struct cpu_info *ci) { KASSERT(ks->ks_state == KSTAT_S_CREATED); ks->ks_lock = ci; ks->ks_lock_ops = &kstat_cpu_ops; } int kstat_read_nop(struct kstat *ks) { return (0); } void kstat_install(struct kstat *ks) { if (!ISSET(ks->ks_flags, KSTAT_F_REALLOC)) { KASSERTMSG(ks->ks_copy != NULL || ks->ks_data != NULL, "kstat %p %s:%u:%s:%u must provide ks_copy or ks_data", ks, ks->ks_provider, ks->ks_instance, ks->ks_name, ks->ks_unit); KASSERT(ks->ks_datalen > 0); } rw_enter_write(&kstat_lock); ks->ks_state = KSTAT_S_INSTALLED; rw_exit_write(&kstat_lock); } void kstat_remove(struct kstat *ks) { rw_enter_write(&kstat_lock); KASSERTMSG(ks->ks_state == KSTAT_S_INSTALLED, "kstat %p %s:%u:%s:%u is not installed", ks, ks->ks_provider, ks->ks_instance, ks->ks_name, ks->ks_unit); ks->ks_state = KSTAT_S_CREATED; rw_exit_write(&kstat_lock); } void kstat_destroy(struct kstat *ks) { rw_enter_write(&kstat_lock); RBT_REMOVE(kstat_id_tree, &kstat_id_tree, ks); RBT_REMOVE(kstat_pv_tree, &kstat_pv_tree, ks); RBT_REMOVE(kstat_nm_tree, &kstat_nm_tree, ks); kstat_version++; rw_exit_write(&kstat_lock); pool_put(&kstat_pool, ks); } int kstat_read(struct kstat *ks) { getnanouptime(&ks->ks_updated); return (0); } int kstat_copy(struct kstat *ks, void *buf) { memcpy(buf, ks->ks_data, ks->ks_datalen); return (0); } RBT_GENERATE(kstat_id_tree, kstat, ks_id_entry, kstat_id_cmp); RBT_GENERATE(kstat_pv_tree, kstat, ks_pv_entry, kstat_pv_cmp); RBT_GENERATE(kstat_nm_tree, kstat, ks_nm_entry, kstat_nm_cmp); void kstat_kv_init(struct kstat_kv *kv, const char *name, enum kstat_kv_type type) { memset(kv, 0, sizeof(*kv)); strlcpy(kv->kv_key, name, sizeof(kv->kv_key)); /* XXX truncated? */ kv->kv_type = type; kv->kv_unit = KSTAT_KV_U_NONE; } void kstat_kv_unit_init(struct kstat_kv *kv, const char *name, enum kstat_kv_type type, enum kstat_kv_unit unit) { switch (type) { case KSTAT_KV_T_COUNTER64: case KSTAT_KV_T_COUNTER32: case KSTAT_KV_T_UINT64: case KSTAT_KV_T_INT64: case KSTAT_KV_T_UINT32: case KSTAT_KV_T_INT32: break; default: panic("kv unit init %s: unit for non-integer type", name); } memset(kv, 0, sizeof(*kv)); strlcpy(kv->kv_key, name, sizeof(kv->kv_key)); /* XXX truncated? */ kv->kv_type = type; kv->kv_unit = unit; }
1 1 1 1 4 3 1 1 2 1 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 /* $OpenBSD: pf_ioctl.c,v 1.417 2024/05/13 01:15:53 jsg Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier * Copyright (c) 2002 - 2018 Henning Brauer <henning@openbsd.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Effort sponsored in part by the Defense Advanced Research Projects * Agency (DARPA) and Air Force Research Laboratory, Air Force * Materiel Command, USAF, under agreement number F30602-01-2-0537. * */ #include "pfsync.h" #include "pflog.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/sysctl.h> #include <sys/mbuf.h> #include <sys/filio.h> #include <sys/fcntl.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/kernel.h> #include <sys/time.h> #include <sys/timeout.h> #include <sys/pool.h> #include <sys/malloc.h> #include <sys/proc.h> #include <sys/rwlock.h> #include <sys/syslog.h> #include <sys/specdev.h> #include <uvm/uvm_extern.h> #include <crypto/md5.h> #include <net/if.h> #include <net/if_var.h> #include <net/route.h> #include <net/hfsc.h> #include <net/fq_codel.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/in_pcb.h> #include <netinet/ip_var.h> #include <netinet/ip_icmp.h> #include <netinet/tcp.h> #include <netinet/udp.h> #ifdef INET6 #include <netinet/ip6.h> #include <netinet/icmp6.h> #endif /* INET6 */ #include <net/pfvar.h> #include <net/pfvar_priv.h> #if NPFSYNC > 0 #include <netinet/ip_ipsp.h> #include <net/if_pfsync.h> #endif /* NPFSYNC > 0 */ struct pool pf_tag_pl; void pfattach(int); int pfopen(dev_t, int, int, struct proc *); int pfclose(dev_t, int, int, struct proc *); int pfioctl(dev_t, u_long, caddr_t, int, struct proc *); int pf_begin_rules(u_int32_t *, const char *); void pf_rollback_rules(u_int32_t, char *); void pf_remove_queues(void); int pf_commit_queues(void); void pf_free_queues(struct pf_queuehead *); void pf_calc_chksum(struct pf_ruleset *); void pf_hash_rule(MD5_CTX *, struct pf_rule *); void pf_hash_rule_addr(MD5_CTX *, struct pf_rule_addr *); int pf_commit_rules(u_int32_t, char *); int pf_addr_setup(struct pf_ruleset *, struct pf_addr_wrap *, sa_family_t); struct pfi_kif *pf_kif_setup(struct pfi_kif *); void pf_addr_copyout(struct pf_addr_wrap *); void pf_trans_set_commit(void); void pf_pool_copyin(struct pf_pool *, struct pf_pool *); int pf_validate_range(u_int8_t, u_int16_t[2], int); int pf_rule_copyin(struct pf_rule *, struct pf_rule *); int pf_rule_checkaf(struct pf_rule *); u_int16_t pf_qname2qid(char *, int); void pf_qid2qname(u_int16_t, char *); void pf_qid_unref(u_int16_t); int pf_states_clr(struct pfioc_state_kill *); int pf_states_get(struct pfioc_states *); struct pf_trans *pf_open_trans(uint32_t); struct pf_trans *pf_find_trans(uint32_t, uint64_t); void pf_free_trans(struct pf_trans *); void pf_rollback_trans(struct pf_trans *); void pf_init_tgetrule(struct pf_trans *, struct pf_anchor *, uint32_t, struct pf_rule *); void pf_cleanup_tgetrule(struct pf_trans *t); struct pf_rule pf_default_rule, pf_default_rule_new; struct { char statusif[IFNAMSIZ]; u_int32_t debug; u_int32_t hostid; u_int32_t reass; u_int32_t mask; } pf_trans_set; #define PF_ORDER_HOST 0 #define PF_ORDER_NET 1 #define PF_TSET_STATUSIF 0x01 #define PF_TSET_DEBUG 0x02 #define PF_TSET_HOSTID 0x04 #define PF_TSET_REASS 0x08 #define TAGID_MAX 50000 TAILQ_HEAD(pf_tags, pf_tagname) pf_tags = TAILQ_HEAD_INITIALIZER(pf_tags), pf_qids = TAILQ_HEAD_INITIALIZER(pf_qids); /* * pf_lock protects consistency of PF data structures, which don't have * their dedicated lock yet. The pf_lock currently protects: * - rules, * - radix tables, * - source nodes * All callers must grab pf_lock exclusively. * * pf_state_lock protects consistency of state table. Packets, which do state * look up grab the lock as readers. If packet must create state, then it must * grab the lock as writer. Whenever packet creates state it grabs pf_lock * first then it locks pf_state_lock as the writer. */ struct rwlock pf_lock = RWLOCK_INITIALIZER("pf_lock"); struct rwlock pf_state_lock = RWLOCK_INITIALIZER("pf_state_lock"); struct rwlock pfioctl_rw = RWLOCK_INITIALIZER("pfioctl_rw"); struct cpumem *pf_anchor_stack; #if (PF_QNAME_SIZE != PF_TAG_NAME_SIZE) #error PF_QNAME_SIZE must be equal to PF_TAG_NAME_SIZE #endif u_int16_t tagname2tag(struct pf_tags *, char *, int); void tag2tagname(struct pf_tags *, u_int16_t, char *); void tag_unref(struct pf_tags *, u_int16_t); int pf_rtlabel_add(struct pf_addr_wrap *); void pf_rtlabel_remove(struct pf_addr_wrap *); void pf_rtlabel_copyout(struct pf_addr_wrap *); LIST_HEAD(, pf_trans) pf_ioctl_trans = LIST_HEAD_INITIALIZER(pf_trans); /* counts transactions opened by a device */ unsigned int pf_tcount[CLONE_MAPSZ * NBBY]; #define pf_unit2idx(_unit_) ((_unit_) >> CLONE_SHIFT) void pfattach(int num) { u_int32_t *timeout = pf_default_rule.timeout; struct pf_anchor_stackframe *sf; struct cpumem_iter cmi; pool_init(&pf_rule_pl, sizeof(struct pf_rule), 0, IPL_SOFTNET, 0, "pfrule", NULL); pool_init(&pf_src_tree_pl, sizeof(struct pf_src_node), 0, IPL_SOFTNET, 0, "pfsrctr", NULL); pool_init(&pf_sn_item_pl, sizeof(struct pf_sn_item), 0, IPL_SOFTNET, 0, "pfsnitem", NULL); pool_init(&pf_state_pl, sizeof(struct pf_state), 0, IPL_SOFTNET, 0, "pfstate", NULL); pool_init(&pf_state_key_pl, sizeof(struct pf_state_key), 0, IPL_SOFTNET, 0, "pfstkey", NULL); pool_init(&pf_state_item_pl, sizeof(struct pf_state_item), 0, IPL_SOFTNET, 0, "pfstitem", NULL); pool_init(&pf_rule_item_pl, sizeof(struct pf_rule_item), 0, IPL_SOFTNET, 0, "pfruleitem", NULL); pool_init(&pf_queue_pl, sizeof(struct pf_queuespec), 0, IPL_SOFTNET, 0, "pfqueue", NULL); pool_init(&pf_tag_pl, sizeof(struct pf_tagname), 0, IPL_SOFTNET, 0, "pftag", NULL); pool_init(&pf_pktdelay_pl, sizeof(struct pf_pktdelay), 0, IPL_SOFTNET, 0, "pfpktdelay", NULL); pool_init(&pf_anchor_pl, sizeof(struct pf_anchor), 0, IPL_SOFTNET, 0, "pfanchor", NULL); hfsc_initialize(); pfr_initialize(); pfi_initialize(); pf_osfp_initialize(); pf_syncookies_init(); pool_sethardlimit(pf_pool_limits[PF_LIMIT_STATES].pp, pf_pool_limits[PF_LIMIT_STATES].limit, NULL, 0); pool_sethardlimit(pf_pool_limits[PF_LIMIT_ANCHORS].pp, pf_pool_limits[PF_LIMIT_ANCHORS].limit, NULL, 0); if (physmem <= atop(100*1024*1024)) pf_pool_limits[PF_LIMIT_TABLE_ENTRIES].limit = PFR_KENTRY_HIWAT_SMALL; RB_INIT(&tree_src_tracking); RB_INIT(&pf_anchors); pf_init_ruleset(&pf_main_ruleset); TAILQ_INIT(&pf_queues[0]); TAILQ_INIT(&pf_queues[1]); pf_queues_active = &pf_queues[0]; pf_queues_inactive = &pf_queues[1]; /* default rule should never be garbage collected */ pf_default_rule.entries.tqe_prev = &pf_default_rule.entries.tqe_next; pf_default_rule.action = PF_PASS; pf_default_rule.nr = (u_int32_t)-1; pf_default_rule.rtableid = -1; /* initialize default timeouts */ timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL; timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL; timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL; timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL; timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL; timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL; timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL; timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL; timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL; timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL; timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL; timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL; timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL; timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL; timeout[PFTM_FRAG] = PFTM_FRAG_VAL; timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL; timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL; timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL; timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START; timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END; pf_default_rule.src.addr.type = PF_ADDR_ADDRMASK; pf_default_rule.dst.addr.type = PF_ADDR_ADDRMASK; pf_default_rule.rdr.addr.type = PF_ADDR_NONE; pf_default_rule.nat.addr.type = PF_ADDR_NONE; pf_default_rule.route.addr.type = PF_ADDR_NONE; pf_normalize_init(); memset(&pf_status, 0, sizeof(pf_status)); pf_status.debug = LOG_ERR; pf_status.reass = PF_REASS_ENABLED; /* XXX do our best to avoid a conflict */ pf_status.hostid = arc4random(); pf_default_rule_new = pf_default_rule; /* * we waste two stack frames as meta-data. * frame[0] always presents a top, which can not be used for data * frame[PF_ANCHOR_STACK_MAX] denotes a bottom of the stack and keeps * the pointer to currently used stack frame. */ pf_anchor_stack = cpumem_malloc( sizeof(struct pf_anchor_stackframe) * (PF_ANCHOR_STACK_MAX + 2), M_WAITOK|M_ZERO); CPUMEM_FOREACH(sf, &cmi, pf_anchor_stack) sf[PF_ANCHOR_STACK_MAX].sf_stack_top = &sf[0]; } int pfopen(dev_t dev, int flags, int fmt, struct proc *p) { int unit = minor(dev); if (unit & ((1 << CLONE_SHIFT) - 1)) return (ENXIO); return (0); } int pfclose(dev_t dev, int flags, int fmt, struct proc *p) { struct pf_trans *w, *s; LIST_HEAD(, pf_trans) tmp_list; uint32_t unit = minor(dev); LIST_INIT(&tmp_list); rw_enter_write(&pfioctl_rw); LIST_FOREACH_SAFE(w, &pf_ioctl_trans, pft_entry, s) { if (w->pft_unit == unit) { LIST_REMOVE(w, pft_entry); LIST_INSERT_HEAD(&tmp_list, w, pft_entry); } } rw_exit_write(&pfioctl_rw); while ((w = LIST_FIRST(&tmp_list)) != NULL) { LIST_REMOVE(w, pft_entry); pf_free_trans(w); } return (0); } void pf_rule_free(struct pf_rule *rule) { if (rule == NULL) return; pfi_kif_free(rule->kif); pfi_kif_free(rule->rcv_kif); pfi_kif_free(rule->rdr.kif); pfi_kif_free(rule->nat.kif); pfi_kif_free(rule->route.kif); pool_put(&pf_rule_pl, rule); } void pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule) { if (rulequeue != NULL) { if (rule->states_cur == 0 && rule->src_nodes == 0) { /* * XXX - we need to remove the table *before* detaching * the rule to make sure the table code does not delete * the anchor under our feet. */ pf_tbladdr_remove(&rule->src.addr); pf_tbladdr_remove(&rule->dst.addr); pf_tbladdr_remove(&rule->rdr.addr); pf_tbladdr_remove(&rule->nat.addr); pf_tbladdr_remove(&rule->route.addr); if (rule->overload_tbl) pfr_detach_table(rule->overload_tbl); } TAILQ_REMOVE(rulequeue, rule, entries); rule->entries.tqe_prev = NULL; rule->nr = (u_int32_t)-1; } if (rule->states_cur > 0 || rule->src_nodes > 0 || rule->entries.tqe_prev != NULL) return; pf_tag_unref(rule->tag); pf_tag_unref(rule->match_tag); pf_rtlabel_remove(&rule->src.addr); pf_rtlabel_remove(&rule->dst.addr); pfi_dynaddr_remove(&rule->src.addr); pfi_dynaddr_remove(&rule->dst.addr); pfi_dynaddr_remove(&rule->rdr.addr); pfi_dynaddr_remove(&rule->nat.addr); pfi_dynaddr_remove(&rule->route.addr); if (rulequeue == NULL) { pf_tbladdr_remove(&rule->src.addr); pf_tbladdr_remove(&rule->dst.addr); pf_tbladdr_remove(&rule->rdr.addr); pf_tbladdr_remove(&rule->nat.addr); pf_tbladdr_remove(&rule->route.addr); if (rule->overload_tbl) pfr_detach_table(rule->overload_tbl); } pfi_kif_unref(rule->rcv_kif, PFI_KIF_REF_RULE); pfi_kif_unref(rule->kif, PFI_KIF_REF_RULE); pfi_kif_unref(rule->rdr.kif, PFI_KIF_REF_RULE); pfi_kif_unref(rule->nat.kif, PFI_KIF_REF_RULE); pfi_kif_unref(rule->route.kif, PFI_KIF_REF_RULE); pf_remove_anchor(rule); pool_put(&pf_rule_pl, rule); } u_int16_t tagname2tag(struct pf_tags *head, char *tagname, int create) { struct pf_tagname *tag, *p = NULL; u_int16_t new_tagid = 1; TAILQ_FOREACH(tag, head, entries) if (strcmp(tagname, tag->name) == 0) { tag->ref++; return (tag->tag); } if (!create) return (0); /* * to avoid fragmentation, we do a linear search from the beginning * and take the first free slot we find. if there is none or the list * is empty, append a new entry at the end. */ /* new entry */ TAILQ_FOREACH(p, head, entries) { if (p->tag != new_tagid) break; new_tagid = p->tag + 1; } if (new_tagid > TAGID_MAX) return (0); /* allocate and fill new struct pf_tagname */ tag = pool_get(&pf_tag_pl, PR_NOWAIT | PR_ZERO); if (tag == NULL) return (0); strlcpy(tag->name, tagname, sizeof(tag->name)); tag->tag = new_tagid; tag->ref++; if (p != NULL) /* insert new entry before p */ TAILQ_INSERT_BEFORE(p, tag, entries); else /* either list empty or no free slot in between */ TAILQ_INSERT_TAIL(head, tag, entries); return (tag->tag); } void tag2tagname(struct pf_tags *head, u_int16_t tagid, char *p) { struct pf_tagname *tag; TAILQ_FOREACH(tag, head, entries) if (tag->tag == tagid) { strlcpy(p, tag->name, PF_TAG_NAME_SIZE); return; } } void tag_unref(struct pf_tags *head, u_int16_t tag) { struct pf_tagname *p, *next; if (tag == 0) return; TAILQ_FOREACH_SAFE(p, head, entries, next) { if (tag == p->tag) { if (--p->ref == 0) { TAILQ_REMOVE(head, p, entries); pool_put(&pf_tag_pl, p); } break; } } } u_int16_t pf_tagname2tag(char *tagname, int create) { return (tagname2tag(&pf_tags, tagname, create)); } void pf_tag2tagname(u_int16_t tagid, char *p) { tag2tagname(&pf_tags, tagid, p); } void pf_tag_ref(u_int16_t tag) { struct pf_tagname *t; TAILQ_FOREACH(t, &pf_tags, entries) if (t->tag == tag) break; if (t != NULL) t->ref++; } void pf_tag_unref(u_int16_t tag) { tag_unref(&pf_tags, tag); } int pf_rtlabel_add(struct pf_addr_wrap *a) { if (a->type == PF_ADDR_RTLABEL && (a->v.rtlabel = rtlabel_name2id(a->v.rtlabelname)) == 0) return (-1); return (0); } void pf_rtlabel_remove(struct pf_addr_wrap *a) { if (a->type == PF_ADDR_RTLABEL) rtlabel_unref(a->v.rtlabel); } void pf_rtlabel_copyout(struct pf_addr_wrap *a) { if (a->type == PF_ADDR_RTLABEL && a->v.rtlabel) { if (rtlabel_id2name(a->v.rtlabel, a->v.rtlabelname, sizeof(a->v.rtlabelname)) == NULL) strlcpy(a->v.rtlabelname, "?", sizeof(a->v.rtlabelname)); } } u_int16_t pf_qname2qid(char *qname, int create) { return (tagname2tag(&pf_qids, qname, create)); } void pf_qid2qname(u_int16_t qid, char *p) { tag2tagname(&pf_qids, qid, p); } void pf_qid_unref(u_int16_t qid) { tag_unref(&pf_qids, (u_int16_t)qid); } int pf_begin_rules(u_int32_t *version, const char *anchor) { struct pf_ruleset *rs; struct pf_rule *rule; if ((rs = pf_find_or_create_ruleset(anchor)) == NULL) return (EINVAL); while ((rule = TAILQ_FIRST(rs->rules.inactive.ptr)) != NULL) { pf_rm_rule(rs->rules.inactive.ptr, rule); rs->rules.inactive.rcount--; } *version = ++rs->rules.inactive.version; rs->rules.inactive.open = 1; return (0); } void pf_rollback_rules(u_int32_t version, char *anchor) { struct pf_ruleset *rs; struct pf_rule *rule; rs = pf_find_ruleset(anchor); if (rs == NULL || !rs->rules.inactive.open || rs->rules.inactive.version != version) return; while ((rule = TAILQ_FIRST(rs->rules.inactive.ptr)) != NULL) { pf_rm_rule(rs->rules.inactive.ptr, rule); rs->rules.inactive.rcount--; } rs->rules.inactive.open = 0; /* queue defs only in the main ruleset */ if (anchor[0]) return; pf_free_queues(pf_queues_inactive); } void pf_free_queues(struct pf_queuehead *where) { struct pf_queuespec *q, *qtmp; TAILQ_FOREACH_SAFE(q, where, entries, qtmp) { TAILQ_REMOVE(where, q, entries); pfi_kif_unref(q->kif, PFI_KIF_REF_RULE); pool_put(&pf_queue_pl, q); } } void pf_remove_queues(void) { struct pf_queuespec *q; struct ifnet *ifp; /* put back interfaces in normal queueing mode */ TAILQ_FOREACH(q, pf_queues_active, entries) { if (q->parent_qid != 0) continue; ifp = q->kif->pfik_ifp; if (ifp == NULL) continue; ifq_attach(&ifp->if_snd, ifq_priq_ops, NULL); } } struct pf_queue_if { struct ifnet *ifp; const struct ifq_ops *ifqops; const struct pfq_ops *pfqops; void *disc; struct pf_queue_if *next; }; static inline struct pf_queue_if * pf_ifp2q(struct pf_queue_if *list, struct ifnet *ifp) { struct pf_queue_if *qif = list; while (qif != NULL) { if (qif->ifp == ifp) return (qif); qif = qif->next; } return (qif); } int pf_create_queues(void) { struct pf_queuespec *q; struct ifnet *ifp; struct pf_queue_if *list = NULL, *qif; int error; /* * Find root queues and allocate traffic conditioner * private data for these interfaces */ TAILQ_FOREACH(q, pf_queues_active, entries) { if (q->parent_qid != 0) continue; ifp = q->kif->pfik_ifp; if (ifp == NULL) continue; qif = malloc(sizeof(*qif), M_PF, M_WAITOK); qif->ifp = ifp; if (q->flags & PFQS_ROOTCLASS) { qif->ifqops = ifq_hfsc_ops; qif->pfqops = pfq_hfsc_ops; } else { qif->ifqops = ifq_fqcodel_ops; qif->pfqops = pfq_fqcodel_ops; } qif->disc = qif->pfqops->pfq_alloc(ifp); qif->next = list; list = qif; } /* and now everything */ TAILQ_FOREACH(q, pf_queues_active, entries) { ifp = q->kif->pfik_ifp; if (ifp == NULL) continue; qif = pf_ifp2q(list, ifp); KASSERT(qif != NULL); error = qif->pfqops->pfq_addqueue(qif->disc, q); if (error != 0) goto error; } /* find root queues in old list to disable them if necessary */ TAILQ_FOREACH(q, pf_queues_inactive, entries) { if (q->parent_qid != 0) continue; ifp = q->kif->pfik_ifp; if (ifp == NULL) continue; qif = pf_ifp2q(list, ifp); if (qif != NULL) continue; ifq_attach(&ifp->if_snd, ifq_priq_ops, NULL); } /* commit the new queues */ while (list != NULL) { qif = list; list = qif->next; ifp = qif->ifp; ifq_attach(&ifp->if_snd, qif->ifqops, qif->disc); free(qif, M_PF, sizeof(*qif)); } return (0); error: while (list != NULL) { qif = list; list = qif->next; qif->pfqops->pfq_free(qif->disc); free(qif, M_PF, sizeof(*qif)); } return (error); } int pf_commit_queues(void) { struct pf_queuehead *qswap; int error; /* swap */ qswap = pf_queues_active; pf_queues_active = pf_queues_inactive; pf_queues_inactive = qswap; error = pf_create_queues(); if (error != 0) { pf_queues_inactive = pf_queues_active; pf_queues_active = qswap; return (error); } pf_free_queues(pf_queues_inactive); return (0); } const struct pfq_ops * pf_queue_manager(struct pf_queuespec *q) { if (q->flags & PFQS_FLOWQUEUE) return pfq_fqcodel_ops; return (/* pfq_default_ops */ NULL); } #define PF_MD5_UPD(st, elm) \ MD5Update(ctx, (u_int8_t *) &(st)->elm, sizeof((st)->elm)) #define PF_MD5_UPD_STR(st, elm) \ MD5Update(ctx, (u_int8_t *) (st)->elm, strlen((st)->elm)) #define PF_MD5_UPD_HTONL(st, elm, stor) do { \ (stor) = htonl((st)->elm); \ MD5Update(ctx, (u_int8_t *) &(stor), sizeof(u_int32_t));\ } while (0) #define PF_MD5_UPD_HTONS(st, elm, stor) do { \ (stor) = htons((st)->elm); \ MD5Update(ctx, (u_int8_t *) &(stor), sizeof(u_int16_t));\ } while (0) void pf_hash_rule_addr(MD5_CTX *ctx, struct pf_rule_addr *pfr) { PF_MD5_UPD(pfr, addr.type); switch (pfr->addr.type) { case PF_ADDR_DYNIFTL: PF_MD5_UPD(pfr, addr.v.ifname); PF_MD5_UPD(pfr, addr.iflags); break; case PF_ADDR_TABLE: if (strncmp(pfr->addr.v.tblname, PF_OPTIMIZER_TABLE_PFX, strlen(PF_OPTIMIZER_TABLE_PFX))) PF_MD5_UPD(pfr, addr.v.tblname); break; case PF_ADDR_ADDRMASK: /* XXX ignore af? */ PF_MD5_UPD(pfr, addr.v.a.addr.addr32); PF_MD5_UPD(pfr, addr.v.a.mask.addr32); break; case PF_ADDR_RTLABEL: PF_MD5_UPD(pfr, addr.v.rtlabelname); break; } PF_MD5_UPD(pfr, port[0]); PF_MD5_UPD(pfr, port[1]); PF_MD5_UPD(pfr, neg); PF_MD5_UPD(pfr, port_op); } void pf_hash_rule(MD5_CTX *ctx, struct pf_rule *rule) { u_int16_t x; u_int32_t y; pf_hash_rule_addr(ctx, &rule->src); pf_hash_rule_addr(ctx, &rule->dst); PF_MD5_UPD_STR(rule, label); PF_MD5_UPD_STR(rule, ifname); PF_MD5_UPD_STR(rule, rcv_ifname); PF_MD5_UPD_STR(rule, match_tagname); PF_MD5_UPD_HTONS(rule, match_tag, x); /* dup? */ PF_MD5_UPD_HTONL(rule, os_fingerprint, y); PF_MD5_UPD_HTONL(rule, prob, y); PF_MD5_UPD_HTONL(rule, uid.uid[0], y); PF_MD5_UPD_HTONL(rule, uid.uid[1], y); PF_MD5_UPD(rule, uid.op); PF_MD5_UPD_HTONL(rule, gid.gid[0], y); PF_MD5_UPD_HTONL(rule, gid.gid[1], y); PF_MD5_UPD(rule, gid.op); PF_MD5_UPD_HTONL(rule, rule_flag, y); PF_MD5_UPD(rule, action); PF_MD5_UPD(rule, direction); PF_MD5_UPD(rule, af); PF_MD5_UPD(rule, quick); PF_MD5_UPD(rule, ifnot); PF_MD5_UPD(rule, rcvifnot); PF_MD5_UPD(rule, match_tag_not); PF_MD5_UPD(rule, keep_state); PF_MD5_UPD(rule, proto); PF_MD5_UPD(rule, type); PF_MD5_UPD(rule, code); PF_MD5_UPD(rule, flags); PF_MD5_UPD(rule, flagset); PF_MD5_UPD(rule, allow_opts); PF_MD5_UPD(rule, rt); PF_MD5_UPD(rule, tos); } int pf_commit_rules(u_int32_t version, char *anchor) { struct pf_ruleset *rs; struct pf_rule *rule; struct pf_rulequeue *old_rules; u_int32_t old_rcount; PF_ASSERT_LOCKED(); rs = pf_find_ruleset(anchor); if (rs == NULL || !rs->rules.inactive.open || version != rs->rules.inactive.version) return (EBUSY); if (rs == &pf_main_ruleset) pf_calc_chksum(rs); /* Swap rules, keep the old. */ old_rules = rs->rules.active.ptr; old_rcount = rs->rules.active.rcount; rs->rules.active.ptr = rs->rules.inactive.ptr; rs->rules.active.rcount = rs->rules.inactive.rcount; rs->rules.inactive.ptr = old_rules; rs->rules.inactive.rcount = old_rcount; rs->rules.active.version = rs->rules.inactive.version; pf_calc_skip_steps(rs->rules.active.ptr); /* Purge the old rule list. */ while ((rule = TAILQ_FIRST(old_rules)) != NULL) pf_rm_rule(old_rules, rule); rs->rules.inactive.rcount = 0; rs->rules.inactive.open = 0; pf_remove_if_empty_ruleset(rs); /* queue defs only in the main ruleset */ if (anchor[0]) return (0); return (pf_commit_queues()); } void pf_calc_chksum(struct pf_ruleset *rs) { MD5_CTX ctx; struct pf_rule *rule; u_int8_t digest[PF_MD5_DIGEST_LENGTH]; MD5Init(&ctx); if (rs->rules.inactive.rcount) { TAILQ_FOREACH(rule, rs->rules.inactive.ptr, entries) { pf_hash_rule(&ctx, rule); } } MD5Final(digest, &ctx); memcpy(pf_status.pf_chksum, digest, sizeof(pf_status.pf_chksum)); } int pf_addr_setup(struct pf_ruleset *ruleset, struct pf_addr_wrap *addr, sa_family_t af) { if (pfi_dynaddr_setup(addr, af, PR_WAITOK) || pf_tbladdr_setup(ruleset, addr, PR_WAITOK) || pf_rtlabel_add(addr)) return (EINVAL); return (0); } struct pfi_kif * pf_kif_setup(struct pfi_kif *kif_buf) { struct pfi_kif *kif; if (kif_buf == NULL) return (NULL); KASSERT(kif_buf->pfik_name[0] != '\0'); kif = pfi_kif_get(kif_buf->pfik_name, &kif_buf); if (kif_buf != NULL) pfi_kif_free(kif_buf); pfi_kif_ref(kif, PFI_KIF_REF_RULE); return (kif); } void pf_addr_copyout(struct pf_addr_wrap *addr) { pfi_dynaddr_copyout(addr); pf_tbladdr_copyout(addr); pf_rtlabel_copyout(addr); } int pf_states_clr(struct pfioc_state_kill *psk) { struct pf_state *st, *nextst; struct pf_state *head, *tail; u_int killed = 0; int error; NET_LOCK(); /* lock against the gc removing an item from the list */ error = rw_enter(&pf_state_list.pfs_rwl, RW_READ|RW_INTR); if (error != 0) goto unlock; /* get a snapshot view of the ends of the list to traverse between */ mtx_enter(&pf_state_list.pfs_mtx); head = TAILQ_FIRST(&pf_state_list.pfs_list); tail = TAILQ_LAST(&pf_state_list.pfs_list, pf_state_queue); mtx_leave(&pf_state_list.pfs_mtx); st = NULL; nextst = head; PF_LOCK(); PF_STATE_ENTER_WRITE(); while (st != tail) { st = nextst; nextst = TAILQ_NEXT(st, entry_list); if (st->timeout == PFTM_UNLINKED) continue; if (!psk->psk_ifname[0] || !strcmp(psk->psk_ifname, st->kif->pfik_name)) { #if NPFSYNC > 0 /* don't send out individual delete messages */ SET(st->state_flags, PFSTATE_NOSYNC); #endif /* NPFSYNC > 0 */ pf_remove_state(st); killed++; } } PF_STATE_EXIT_WRITE(); PF_UNLOCK(); rw_exit(&pf_state_list.pfs_rwl); psk->psk_killed = killed; #if NPFSYNC > 0 pfsync_clear_states(pf_status.hostid, psk->psk_ifname); #endif /* NPFSYNC > 0 */ unlock: NET_UNLOCK(); return (error); } int pf_states_get(struct pfioc_states *ps) { struct pf_state *st, *nextst; struct pf_state *head, *tail; struct pfsync_state *p, pstore; u_int32_t nr = 0; int error; if (ps->ps_len == 0) { nr = pf_status.states; ps->ps_len = sizeof(struct pfsync_state) * nr; return (0); } p = ps->ps_states; /* lock against the gc removing an item from the list */ error = rw_enter(&pf_state_list.pfs_rwl, RW_READ|RW_INTR); if (error != 0) return (error); /* get a snapshot view of the ends of the list to traverse between */ mtx_enter(&pf_state_list.pfs_mtx); head = TAILQ_FIRST(&pf_state_list.pfs_list); tail = TAILQ_LAST(&pf_state_list.pfs_list, pf_state_queue); mtx_leave(&pf_state_list.pfs_mtx); st = NULL; nextst = head; while (st != tail) { st = nextst; nextst = TAILQ_NEXT(st, entry_list); if (st->timeout == PFTM_UNLINKED) continue; if ((nr+1) * sizeof(*p) > ps->ps_len) break; pf_state_export(&pstore, st); error = copyout(&pstore, p, sizeof(*p)); if (error) goto fail; p++; nr++; } ps->ps_len = sizeof(struct pfsync_state) * nr; fail: rw_exit(&pf_state_list.pfs_rwl); return (error); } int pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) { int error = 0; /* XXX keep in sync with switch() below */ if (securelevel > 1) switch (cmd) { case DIOCGETRULES: case DIOCGETRULE: case DIOCGETSTATE: case DIOCSETSTATUSIF: case DIOCGETSTATUS: case DIOCCLRSTATUS: case DIOCNATLOOK: case DIOCSETDEBUG: case DIOCGETSTATES: case DIOCGETTIMEOUT: case DIOCGETLIMIT: case DIOCGETRULESETS: case DIOCGETRULESET: case DIOCGETQUEUES: case DIOCGETQUEUE: case DIOCGETQSTATS: case DIOCRGETTABLES: case DIOCRGETTSTATS: case DIOCRCLRTSTATS: case DIOCRCLRADDRS: case DIOCRADDADDRS: case DIOCRDELADDRS: case DIOCRSETADDRS: case DIOCRGETADDRS: case DIOCRGETASTATS: case DIOCRCLRASTATS: case DIOCRTSTADDRS: case DIOCOSFPGET: case DIOCGETSRCNODES: case DIOCCLRSRCNODES: case DIOCIGETIFACES: case DIOCSETIFFLAG: case DIOCCLRIFFLAG: case DIOCGETSYNFLWATS: break; case DIOCRCLRTABLES: case DIOCRADDTABLES: case DIOCRDELTABLES: case DIOCRSETTFLAGS: if (((struct pfioc_table *)addr)->pfrio_flags & PFR_FLAG_DUMMY) break; /* dummy operation ok */ return (EPERM); default: return (EPERM); } if (!(flags & FWRITE)) switch (cmd) { case DIOCGETRULES: case DIOCGETSTATE: case DIOCGETSTATUS: case DIOCGETSTATES: case DIOCGETTIMEOUT: case DIOCGETLIMIT: case DIOCGETRULESETS: case DIOCGETRULESET: case DIOCGETQUEUES: case DIOCGETQUEUE: case DIOCGETQSTATS: case DIOCNATLOOK: case DIOCRGETTABLES: case DIOCRGETTSTATS: case DIOCRGETADDRS: case DIOCRGETASTATS: case DIOCRTSTADDRS: case DIOCOSFPGET: case DIOCGETSRCNODES: case DIOCIGETIFACES: case DIOCGETSYNFLWATS: case DIOCXEND: break; case DIOCRCLRTABLES: case DIOCRADDTABLES: case DIOCRDELTABLES: case DIOCRCLRTSTATS: case DIOCRCLRADDRS: case DIOCRADDADDRS: case DIOCRDELADDRS: case DIOCRSETADDRS: case DIOCRSETTFLAGS: if (((struct pfioc_table *)addr)->pfrio_flags & PFR_FLAG_DUMMY) { flags |= FWRITE; /* need write lock for dummy */ break; /* dummy operation ok */ } return (EACCES); case DIOCGETRULE: if (((struct pfioc_rule *)addr)->action == PF_GET_CLR_CNTR) return (EACCES); break; default: return (EACCES); } rw_enter_write(&pfioctl_rw); switch (cmd) { case DIOCSTART: NET_LOCK(); PF_LOCK(); if (pf_status.running) error = EEXIST; else { pf_status.running = 1; pf_status.since = getuptime(); if (pf_status.stateid == 0) { pf_status.stateid = gettime(); pf_status.stateid = pf_status.stateid << 32; } timeout_add_sec(&pf_purge_states_to, 1); timeout_add_sec(&pf_purge_to, 1); pf_create_queues(); DPFPRINTF(LOG_NOTICE, "pf: started"); } PF_UNLOCK(); NET_UNLOCK(); break; case DIOCSTOP: NET_LOCK(); PF_LOCK(); if (!pf_status.running) error = ENOENT; else { pf_status.running = 0; pf_status.since = getuptime(); pf_remove_queues(); DPFPRINTF(LOG_NOTICE, "pf: stopped"); } PF_UNLOCK(); NET_UNLOCK(); break; case DIOCGETQUEUES: { struct pfioc_queue *pq = (struct pfioc_queue *)addr; struct pf_queuespec *qs; u_int32_t nr = 0; PF_LOCK(); pq->ticket = pf_main_ruleset.rules.active.version; /* save state to not run over them all each time? */ qs = TAILQ_FIRST(pf_queues_active); while (qs != NULL) { qs = TAILQ_NEXT(qs, entries); nr++; } pq->nr = nr; PF_UNLOCK(); break; } case DIOCGETQUEUE: { struct pfioc_queue *pq = (struct pfioc_queue *)addr; struct pf_queuespec *qs; u_int32_t nr = 0; PF_LOCK(); if (pq->ticket != pf_main_ruleset.rules.active.version) { error = EBUSY; PF_UNLOCK(); goto fail; } /* save state to not run over them all each time? */ qs = TAILQ_FIRST(pf_queues_active); while ((qs != NULL) && (nr++ < pq->nr)) qs = TAILQ_NEXT(qs, entries); if (qs == NULL) { error = EBUSY; PF_UNLOCK(); goto fail; } memcpy(&pq->queue, qs, sizeof(pq->queue)); PF_UNLOCK(); break; } case DIOCGETQSTATS: { struct pfioc_qstats *pq = (struct pfioc_qstats *)addr; struct pf_queuespec *qs; u_int32_t nr; int nbytes; NET_LOCK(); PF_LOCK(); if (pq->ticket != pf_main_ruleset.rules.active.version) { error = EBUSY; PF_UNLOCK(); NET_UNLOCK(); goto fail; } nbytes = pq->nbytes; nr = 0; /* save state to not run over them all each time? */ qs = TAILQ_FIRST(pf_queues_active); while ((qs != NULL) && (nr++ < pq->nr)) qs = TAILQ_NEXT(qs, entries); if (qs == NULL) { error = EBUSY; PF_UNLOCK(); NET_UNLOCK(); goto fail; } memcpy(&pq->queue, qs, sizeof(pq->queue)); /* It's a root flow queue but is not an HFSC root class */ if ((qs->flags & PFQS_FLOWQUEUE) && qs->parent_qid == 0 && !(qs->flags & PFQS_ROOTCLASS)) error = pfq_fqcodel_ops->pfq_qstats(qs, pq->buf, &nbytes); else error = pfq_hfsc_ops->pfq_qstats(qs, pq->buf, &nbytes); if (error == 0) pq->nbytes = nbytes; PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCADDQUEUE: { struct pfioc_queue *q = (struct pfioc_queue *)addr; struct pf_queuespec *qs; qs = pool_get(&pf_queue_pl, PR_WAITOK|PR_LIMITFAIL|PR_ZERO); if (qs == NULL) { error = ENOMEM; goto fail; } NET_LOCK(); PF_LOCK(); if (q->ticket != pf_main_ruleset.rules.inactive.version) { error = EBUSY; PF_UNLOCK(); NET_UNLOCK(); pool_put(&pf_queue_pl, qs); goto fail; } memcpy(qs, &q->queue, sizeof(*qs)); qs->qid = pf_qname2qid(qs->qname, 1); if (qs->qid == 0) { error = EBUSY; PF_UNLOCK(); NET_UNLOCK(); pool_put(&pf_queue_pl, qs); goto fail; } if (qs->parent[0] && (qs->parent_qid = pf_qname2qid(qs->parent, 0)) == 0) { error = ESRCH; PF_UNLOCK(); NET_UNLOCK(); pool_put(&pf_queue_pl, qs); goto fail; } qs->kif = pfi_kif_get(qs->ifname, NULL); if (qs->kif == NULL) { error = ESRCH; PF_UNLOCK(); NET_UNLOCK(); pool_put(&pf_queue_pl, qs); goto fail; } /* XXX resolve bw percentage specs */ pfi_kif_ref(qs->kif, PFI_KIF_REF_RULE); TAILQ_INSERT_TAIL(pf_queues_inactive, qs, entries); PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCADDRULE: { struct pfioc_rule *pr = (struct pfioc_rule *)addr; struct pf_ruleset *ruleset; struct pf_rule *rule, *tail; rule = pool_get(&pf_rule_pl, PR_WAITOK|PR_LIMITFAIL|PR_ZERO); if (rule == NULL) { error = ENOMEM; goto fail; } if ((error = pf_rule_copyin(&pr->rule, rule))) { pf_rule_free(rule); rule = NULL; goto fail; } if (pr->rule.return_icmp >> 8 > ICMP_MAXTYPE) { error = EINVAL; pf_rule_free(rule); rule = NULL; goto fail; } if ((error = pf_rule_checkaf(rule))) { pf_rule_free(rule); rule = NULL; goto fail; } if (rule->src.addr.type == PF_ADDR_NONE || rule->dst.addr.type == PF_ADDR_NONE) { error = EINVAL; pf_rule_free(rule); rule = NULL; goto fail; } if (rule->rt && !rule->direction) { error = EINVAL; pf_rule_free(rule); rule = NULL; goto fail; } NET_LOCK(); PF_LOCK(); pr->anchor[sizeof(pr->anchor) - 1] = '\0'; ruleset = pf_find_ruleset(pr->anchor); if (ruleset == NULL) { error = EINVAL; PF_UNLOCK(); NET_UNLOCK(); pf_rule_free(rule); goto fail; } if (pr->ticket != ruleset->rules.inactive.version) { error = EBUSY; PF_UNLOCK(); NET_UNLOCK(); pf_rule_free(rule); goto fail; } rule->cuid = p->p_ucred->cr_ruid; rule->cpid = p->p_p->ps_pid; tail = TAILQ_LAST(ruleset->rules.inactive.ptr, pf_rulequeue); if (tail) rule->nr = tail->nr + 1; else rule->nr = 0; rule->kif = pf_kif_setup(rule->kif); rule->rcv_kif = pf_kif_setup(rule->rcv_kif); rule->rdr.kif = pf_kif_setup(rule->rdr.kif); rule->nat.kif = pf_kif_setup(rule->nat.kif); rule->route.kif = pf_kif_setup(rule->route.kif); if (rule->overload_tblname[0]) { if ((rule->overload_tbl = pfr_attach_table(ruleset, rule->overload_tblname, PR_WAITOK)) == NULL) error = EINVAL; else rule->overload_tbl->pfrkt_flags |= PFR_TFLAG_ACTIVE; } if (pf_addr_setup(ruleset, &rule->src.addr, rule->af)) error = EINVAL; if (pf_addr_setup(ruleset, &rule->dst.addr, rule->af)) error = EINVAL; if (pf_addr_setup(ruleset, &rule->rdr.addr, rule->af)) error = EINVAL; if (pf_addr_setup(ruleset, &rule->nat.addr, rule->af)) error = EINVAL; if (pf_addr_setup(ruleset, &rule->route.addr, rule->af)) error = EINVAL; if (pf_anchor_setup(rule, ruleset, pr->anchor_call)) error = EINVAL; if (error) { pf_rm_rule(NULL, rule); PF_UNLOCK(); NET_UNLOCK(); goto fail; } TAILQ_INSERT_TAIL(ruleset->rules.inactive.ptr, rule, entries); ruleset->rules.inactive.rcount++; PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCGETRULES: { struct pfioc_rule *pr = (struct pfioc_rule *)addr; struct pf_ruleset *ruleset; struct pf_rule *rule; struct pf_trans *t; u_int32_t ruleset_version; NET_LOCK(); PF_LOCK(); pr->anchor[sizeof(pr->anchor) - 1] = '\0'; ruleset = pf_find_ruleset(pr->anchor); if (ruleset == NULL) { error = EINVAL; PF_UNLOCK(); NET_UNLOCK(); goto fail; } rule = TAILQ_LAST(ruleset->rules.active.ptr, pf_rulequeue); if (rule) pr->nr = rule->nr + 1; else pr->nr = 0; ruleset_version = ruleset->rules.active.version; pf_anchor_take(ruleset->anchor); rule = TAILQ_FIRST(ruleset->rules.active.ptr); PF_UNLOCK(); NET_UNLOCK(); t = pf_open_trans(minor(dev)); if (t == NULL) { error = EBUSY; goto fail; } pf_init_tgetrule(t, ruleset->anchor, ruleset_version, rule); pr->ticket = t->pft_ticket; break; } case DIOCGETRULE: { struct pfioc_rule *pr = (struct pfioc_rule *)addr; struct pf_ruleset *ruleset; struct pf_rule *rule; struct pf_trans *t; int i; t = pf_find_trans(minor(dev), pr->ticket); if (t == NULL) { error = ENXIO; goto fail; } KASSERT(t->pft_unit == minor(dev)); if (t->pft_type != PF_TRANS_GETRULE) { error = EINVAL; goto fail; } NET_LOCK(); PF_LOCK(); KASSERT(t->pftgr_anchor != NULL); ruleset = &t->pftgr_anchor->ruleset; if (t->pftgr_version != ruleset->rules.active.version) { error = EBUSY; PF_UNLOCK(); NET_UNLOCK(); goto fail; } rule = t->pftgr_rule; if (rule == NULL) { error = ENOENT; PF_UNLOCK(); NET_UNLOCK(); goto fail; } memcpy(&pr->rule, rule, sizeof(struct pf_rule)); memset(&pr->rule.entries, 0, sizeof(pr->rule.entries)); pr->rule.kif = NULL; pr->rule.nat.kif = NULL; pr->rule.rdr.kif = NULL; pr->rule.route.kif = NULL; pr->rule.rcv_kif = NULL; pr->rule.anchor = NULL; pr->rule.overload_tbl = NULL; pr->rule.pktrate.limit /= PF_THRESHOLD_MULT; if (pf_anchor_copyout(ruleset, rule, pr)) { error = EBUSY; PF_UNLOCK(); NET_UNLOCK(); goto fail; } pf_addr_copyout(&pr->rule.src.addr); pf_addr_copyout(&pr->rule.dst.addr); pf_addr_copyout(&pr->rule.rdr.addr); pf_addr_copyout(&pr->rule.nat.addr); pf_addr_copyout(&pr->rule.route.addr); for (i = 0; i < PF_SKIP_COUNT; ++i) if (rule->skip[i].ptr == NULL) pr->rule.skip[i].nr = (u_int32_t)-1; else pr->rule.skip[i].nr = rule->skip[i].ptr->nr; if (pr->action == PF_GET_CLR_CNTR) { rule->evaluations = 0; rule->packets[0] = rule->packets[1] = 0; rule->bytes[0] = rule->bytes[1] = 0; rule->states_tot = 0; } pr->nr = rule->nr; t->pftgr_rule = TAILQ_NEXT(rule, entries); PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCCHANGERULE: { struct pfioc_rule *pcr = (struct pfioc_rule *)addr; struct pf_ruleset *ruleset; struct pf_rule *oldrule = NULL, *newrule = NULL; u_int32_t nr = 0; if (pcr->action < PF_CHANGE_ADD_HEAD || pcr->action > PF_CHANGE_GET_TICKET) { error = EINVAL; goto fail; } if (pcr->action == PF_CHANGE_GET_TICKET) { NET_LOCK(); PF_LOCK(); ruleset = pf_find_ruleset(pcr->anchor); if (ruleset == NULL) error = EINVAL; else pcr->ticket = ++ruleset->rules.active.version; PF_UNLOCK(); NET_UNLOCK(); goto fail; } if (pcr->action != PF_CHANGE_REMOVE) { newrule = pool_get(&pf_rule_pl, PR_WAITOK|PR_LIMITFAIL|PR_ZERO); if (newrule == NULL) { error = ENOMEM; goto fail; } if (pcr->rule.return_icmp >> 8 > ICMP_MAXTYPE) { error = EINVAL; pool_put(&pf_rule_pl, newrule); goto fail; } error = pf_rule_copyin(&pcr->rule, newrule); if (error != 0) { pf_rule_free(newrule); newrule = NULL; goto fail; } if ((error = pf_rule_checkaf(newrule))) { pf_rule_free(newrule); newrule = NULL; goto fail; } if (newrule->rt && !newrule->direction) { pf_rule_free(newrule); error = EINVAL; newrule = NULL; goto fail; } } NET_LOCK(); PF_LOCK(); ruleset = pf_find_ruleset(pcr->anchor); if (ruleset == NULL) { error = EINVAL; PF_UNLOCK(); NET_UNLOCK(); pf_rule_free(newrule); goto fail; } if (pcr->ticket != ruleset->rules.active.version) { error = EINVAL; PF_UNLOCK(); NET_UNLOCK(); pf_rule_free(newrule); goto fail; } if (pcr->action != PF_CHANGE_REMOVE) { KASSERT(newrule != NULL); newrule->cuid = p->p_ucred->cr_ruid; newrule->cpid = p->p_p->ps_pid; newrule->kif = pf_kif_setup(newrule->kif); newrule->rcv_kif = pf_kif_setup(newrule->rcv_kif); newrule->rdr.kif = pf_kif_setup(newrule->rdr.kif); newrule->nat.kif = pf_kif_setup(newrule->nat.kif); newrule->route.kif = pf_kif_setup(newrule->route.kif); if (newrule->overload_tblname[0]) { newrule->overload_tbl = pfr_attach_table( ruleset, newrule->overload_tblname, PR_WAITOK); if (newrule->overload_tbl == NULL) error = EINVAL; else newrule->overload_tbl->pfrkt_flags |= PFR_TFLAG_ACTIVE; } if (pf_addr_setup(ruleset, &newrule->src.addr, newrule->af)) error = EINVAL; if (pf_addr_setup(ruleset, &newrule->dst.addr, newrule->af)) error = EINVAL; if (pf_addr_setup(ruleset, &newrule->rdr.addr, newrule->af)) error = EINVAL; if (pf_addr_setup(ruleset, &newrule->nat.addr, newrule->af)) error = EINVAL; if (pf_addr_setup(ruleset, &newrule->route.addr, newrule->af)) error = EINVAL; if (pf_anchor_setup(newrule, ruleset, pcr->anchor_call)) error = EINVAL; if (error) { pf_rm_rule(NULL, newrule); PF_UNLOCK(); NET_UNLOCK(); goto fail; } } if (pcr->action == PF_CHANGE_ADD_HEAD) oldrule = TAILQ_FIRST(ruleset->rules.active.ptr); else if (pcr->action == PF_CHANGE_ADD_TAIL) oldrule = TAILQ_LAST(ruleset->rules.active.ptr, pf_rulequeue); else { oldrule = TAILQ_FIRST(ruleset->rules.active.ptr); while ((oldrule != NULL) && (oldrule->nr != pcr->nr)) oldrule = TAILQ_NEXT(oldrule, entries); if (oldrule == NULL) { if (newrule != NULL) pf_rm_rule(NULL, newrule); error = EINVAL; PF_UNLOCK(); NET_UNLOCK(); goto fail; } } if (pcr->action == PF_CHANGE_REMOVE) { pf_rm_rule(ruleset->rules.active.ptr, oldrule); ruleset->rules.active.rcount--; } else { if (oldrule == NULL) TAILQ_INSERT_TAIL( ruleset->rules.active.ptr, newrule, entries); else if (pcr->action == PF_CHANGE_ADD_HEAD || pcr->action == PF_CHANGE_ADD_BEFORE) TAILQ_INSERT_BEFORE(oldrule, newrule, entries); else TAILQ_INSERT_AFTER( ruleset->rules.active.ptr, oldrule, newrule, entries); ruleset->rules.active.rcount++; } nr = 0; TAILQ_FOREACH(oldrule, ruleset->rules.active.ptr, entries) oldrule->nr = nr++; ruleset->rules.active.version++; pf_calc_skip_steps(ruleset->rules.active.ptr); pf_remove_if_empty_ruleset(ruleset); PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCCLRSTATES: error = pf_states_clr((struct pfioc_state_kill *)addr); break; case DIOCKILLSTATES: { struct pf_state *st, *nextst; struct pf_state_item *si, *sit; struct pf_state_key *sk, key; struct pf_addr *srcaddr, *dstaddr; u_int16_t srcport, dstport; struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr; u_int i, killed = 0; const int dirs[] = { PF_IN, PF_OUT }; int sidx, didx; if (psk->psk_pfcmp.id) { if (psk->psk_pfcmp.creatorid == 0) psk->psk_pfcmp.creatorid = pf_status.hostid; NET_LOCK(); PF_LOCK(); PF_STATE_ENTER_WRITE(); if ((st = pf_find_state_byid(&psk->psk_pfcmp))) { pf_remove_state(st); psk->psk_killed = 1; } PF_STATE_EXIT_WRITE(); PF_UNLOCK(); NET_UNLOCK(); goto fail; } if (psk->psk_af && psk->psk_proto && psk->psk_src.port_op == PF_OP_EQ && psk->psk_dst.port_op == PF_OP_EQ) { key.af = psk->psk_af; key.proto = psk->psk_proto; key.rdomain = psk->psk_rdomain; NET_LOCK(); PF_LOCK(); PF_STATE_ENTER_WRITE(); for (i = 0; i < nitems(dirs); i++) { if (dirs[i] == PF_IN) { sidx = 0; didx = 1; } else { sidx = 1; didx = 0; } pf_addrcpy(&key.addr[sidx], &psk->psk_src.addr.v.a.addr, key.af); pf_addrcpy(&key.addr[didx], &psk->psk_dst.addr.v.a.addr, key.af); key.port[sidx] = psk->psk_src.port[0]; key.port[didx] = psk->psk_dst.port[0]; sk = RBT_FIND(pf_state_tree, &pf_statetbl, &key); if (sk == NULL) continue; TAILQ_FOREACH_SAFE(si, &sk->sk_states, si_entry, sit) { struct pf_state *sist = si->si_st; if (((sist->key[PF_SK_WIRE]->af == sist->key[PF_SK_STACK]->af && sk == (dirs[i] == PF_IN ? sist->key[PF_SK_WIRE] : sist->key[PF_SK_STACK])) || (sist->key[PF_SK_WIRE]->af != sist->key[PF_SK_STACK]->af && dirs[i] == PF_IN && (sk == sist->key[PF_SK_STACK] || sk == sist->key[PF_SK_WIRE]))) && (!psk->psk_ifname[0] || (sist->kif != pfi_all && !strcmp(psk->psk_ifname, sist->kif->pfik_name)))) { pf_remove_state(sist); killed++; } } } if (killed) psk->psk_killed = killed; PF_STATE_EXIT_WRITE(); PF_UNLOCK(); NET_UNLOCK(); goto fail; } NET_LOCK(); PF_LOCK(); PF_STATE_ENTER_WRITE(); RBT_FOREACH_SAFE(st, pf_state_tree_id, &tree_id, nextst) { if (st->direction == PF_OUT) { sk = st->key[PF_SK_STACK]; srcaddr = &sk->addr[1]; dstaddr = &sk->addr[0]; srcport = sk->port[1]; dstport = sk->port[0]; } else { sk = st->key[PF_SK_WIRE]; srcaddr = &sk->addr[0]; dstaddr = &sk->addr[1]; srcport = sk->port[0]; dstport = sk->port[1]; } if ((!psk->psk_af || sk->af == psk->psk_af) && (!psk->psk_proto || psk->psk_proto == sk->proto) && psk->psk_rdomain == sk->rdomain && pf_match_addr(psk->psk_src.neg, &psk->psk_src.addr.v.a.addr, &psk->psk_src.addr.v.a.mask, srcaddr, sk->af) && pf_match_addr(psk->psk_dst.neg, &psk->psk_dst.addr.v.a.addr, &psk->psk_dst.addr.v.a.mask, dstaddr, sk->af) && (psk->psk_src.port_op == 0 || pf_match_port(psk->psk_src.port_op, psk->psk_src.port[0], psk->psk_src.port[1], srcport)) && (psk->psk_dst.port_op == 0 || pf_match_port(psk->psk_dst.port_op, psk->psk_dst.port[0], psk->psk_dst.port[1], dstport)) && (!psk->psk_label[0] || (st->rule.ptr->label[0] && !strcmp(psk->psk_label, st->rule.ptr->label))) && (!psk->psk_ifname[0] || !strcmp(psk->psk_ifname, st->kif->pfik_name))) { pf_remove_state(st); killed++; } } psk->psk_killed = killed; PF_STATE_EXIT_WRITE(); PF_UNLOCK(); NET_UNLOCK(); break; } #if NPFSYNC > 0 case DIOCADDSTATE: { struct pfioc_state *ps = (struct pfioc_state *)addr; struct pfsync_state *sp = &ps->state; if (sp->timeout >= PFTM_MAX) { error = EINVAL; goto fail; } NET_LOCK(); PF_LOCK(); error = pf_state_import(sp, PFSYNC_SI_IOCTL); PF_UNLOCK(); NET_UNLOCK(); break; } #endif /* NPFSYNC > 0 */ case DIOCGETSTATE: { struct pfioc_state *ps = (struct pfioc_state *)addr; struct pf_state *st; struct pf_state_cmp id_key; memset(&id_key, 0, sizeof(id_key)); id_key.id = ps->state.id; id_key.creatorid = ps->state.creatorid; NET_LOCK(); PF_STATE_ENTER_READ(); st = pf_find_state_byid(&id_key); st = pf_state_ref(st); PF_STATE_EXIT_READ(); NET_UNLOCK(); if (st == NULL) { error = ENOENT; goto fail; } pf_state_export(&ps->state, st); pf_state_unref(st); break; } case DIOCGETSTATES: error = pf_states_get((struct pfioc_states *)addr); break; case DIOCGETSTATUS: { struct pf_status *s = (struct pf_status *)addr; NET_LOCK(); PF_LOCK(); PF_FRAG_LOCK(); memcpy(s, &pf_status, sizeof(struct pf_status)); PF_FRAG_UNLOCK(); pfi_update_status(s->ifname, s); PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCSETSTATUSIF: { struct pfioc_iface *pi = (struct pfioc_iface *)addr; NET_LOCK(); PF_LOCK(); if (pi->pfiio_name[0] == 0) { memset(pf_status.ifname, 0, IFNAMSIZ); PF_UNLOCK(); NET_UNLOCK(); goto fail; } strlcpy(pf_trans_set.statusif, pi->pfiio_name, IFNAMSIZ); pf_trans_set.mask |= PF_TSET_STATUSIF; PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCCLRSTATUS: { struct pfioc_iface *pi = (struct pfioc_iface *)addr; NET_LOCK(); PF_LOCK(); /* if ifname is specified, clear counters there only */ if (pi->pfiio_name[0]) { pfi_update_status(pi->pfiio_name, NULL); PF_UNLOCK(); NET_UNLOCK(); goto fail; } memset(pf_status.counters, 0, sizeof(pf_status.counters)); memset(pf_status.fcounters, 0, sizeof(pf_status.fcounters)); memset(pf_status.scounters, 0, sizeof(pf_status.scounters)); PF_FRAG_LOCK(); memset(pf_status.ncounters, 0, sizeof(pf_status.ncounters)); PF_FRAG_UNLOCK(); pf_status.since = getuptime(); PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCNATLOOK: { struct pfioc_natlook *pnl = (struct pfioc_natlook *)addr; struct pf_state_key *sk; struct pf_state *st; struct pf_state_key_cmp key; int m = 0, direction = pnl->direction; int sidx, didx; switch (pnl->af) { case AF_INET: break; #ifdef INET6 case AF_INET6: break; #endif /* INET6 */ default: error = EAFNOSUPPORT; goto fail; } /* NATLOOK src and dst are reversed, so reverse sidx/didx */ sidx = (direction == PF_IN) ? 1 : 0; didx = (direction == PF_IN) ? 0 : 1; if (!pnl->proto || PF_AZERO(&pnl->saddr, pnl->af) || PF_AZERO(&pnl->daddr, pnl->af) || ((pnl->proto == IPPROTO_TCP || pnl->proto == IPPROTO_UDP) && (!pnl->dport || !pnl->sport)) || pnl->rdomain > RT_TABLEID_MAX) error = EINVAL; else { key.af = pnl->af; key.proto = pnl->proto; key.rdomain = pnl->rdomain; pf_addrcpy(&key.addr[sidx], &pnl->saddr, pnl->af); key.port[sidx] = pnl->sport; pf_addrcpy(&key.addr[didx], &pnl->daddr, pnl->af); key.port[didx] = pnl->dport; NET_LOCK(); PF_STATE_ENTER_READ(); st = pf_find_state_all(&key, direction, &m); st = pf_state_ref(st); PF_STATE_EXIT_READ(); NET_UNLOCK(); if (m > 1) error = E2BIG; /* more than one state */ else if (st != NULL) { sk = st->key[sidx]; pf_addrcpy(&pnl->rsaddr, &sk->addr[sidx], sk->af); pnl->rsport = sk->port[sidx]; pf_addrcpy(&pnl->rdaddr, &sk->addr[didx], sk->af); pnl->rdport = sk->port[didx]; pnl->rrdomain = sk->rdomain; } else error = ENOENT; pf_state_unref(st); } break; } case DIOCSETTIMEOUT: { struct pfioc_tm *pt = (struct pfioc_tm *)addr; if (pt->timeout < 0 || pt->timeout >= PFTM_MAX || pt->seconds < 0) { error = EINVAL; goto fail; } NET_LOCK(); PF_LOCK(); if (pt->timeout == PFTM_INTERVAL && pt->seconds == 0) pt->seconds = 1; pf_default_rule_new.timeout[pt->timeout] = pt->seconds; pt->seconds = pf_default_rule.timeout[pt->timeout]; PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCGETTIMEOUT: { struct pfioc_tm *pt = (struct pfioc_tm *)addr; if (pt->timeout < 0 || pt->timeout >= PFTM_MAX) { error = EINVAL; goto fail; } PF_LOCK(); pt->seconds = pf_default_rule.timeout[pt->timeout]; PF_UNLOCK(); break; } case DIOCGETLIMIT: { struct pfioc_limit *pl = (struct pfioc_limit *)addr; if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) { error = EINVAL; goto fail; } PF_LOCK(); pl->limit = pf_pool_limits[pl->index].limit; PF_UNLOCK(); break; } case DIOCSETLIMIT: { struct pfioc_limit *pl = (struct pfioc_limit *)addr; PF_LOCK(); if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) { error = EINVAL; PF_UNLOCK(); goto fail; } if (((struct pool *)pf_pool_limits[pl->index].pp)->pr_nout > pl->limit) { error = EBUSY; PF_UNLOCK(); goto fail; } /* Fragments reference mbuf clusters. */ if (pl->index == PF_LIMIT_FRAGS && pl->limit > nmbclust) { error = EINVAL; PF_UNLOCK(); goto fail; } pf_pool_limits[pl->index].limit_new = pl->limit; pl->limit = pf_pool_limits[pl->index].limit; PF_UNLOCK(); break; } case DIOCSETDEBUG: { u_int32_t *level = (u_int32_t *)addr; NET_LOCK(); PF_LOCK(); pf_trans_set.debug = *level; pf_trans_set.mask |= PF_TSET_DEBUG; PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCGETRULESETS: { struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr; struct pf_ruleset *ruleset; struct pf_anchor *anchor; PF_LOCK(); pr->path[sizeof(pr->path) - 1] = '\0'; if ((ruleset = pf_find_ruleset(pr->path)) == NULL) { error = EINVAL; PF_UNLOCK(); goto fail; } pr->nr = 0; if (ruleset == &pf_main_ruleset) { /* XXX kludge for pf_main_ruleset */ RB_FOREACH(anchor, pf_anchor_global, &pf_anchors) if (anchor->parent == NULL) pr->nr++; } else { RB_FOREACH(anchor, pf_anchor_node, &ruleset->anchor->children) pr->nr++; } PF_UNLOCK(); break; } case DIOCGETRULESET: { struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr; struct pf_ruleset *ruleset; struct pf_anchor *anchor; u_int32_t nr = 0; PF_LOCK(); pr->path[sizeof(pr->path) - 1] = '\0'; if ((ruleset = pf_find_ruleset(pr->path)) == NULL) { error = EINVAL; PF_UNLOCK(); goto fail; } pr->name[0] = '\0'; if (ruleset == &pf_main_ruleset) { /* XXX kludge for pf_main_ruleset */ RB_FOREACH(anchor, pf_anchor_global, &pf_anchors) if (anchor->parent == NULL && nr++ == pr->nr) { strlcpy(pr->name, anchor->name, sizeof(pr->name)); break; } } else { RB_FOREACH(anchor, pf_anchor_node, &ruleset->anchor->children) if (nr++ == pr->nr) { strlcpy(pr->name, anchor->name, sizeof(pr->name)); break; } } PF_UNLOCK(); if (!pr->name[0]) error = EBUSY; break; } case DIOCRCLRTABLES: { struct pfioc_table *io = (struct pfioc_table *)addr; if (io->pfrio_esize != 0) { error = ENODEV; goto fail; } NET_LOCK(); PF_LOCK(); error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCRADDTABLES: { struct pfioc_table *io = (struct pfioc_table *)addr; if (io->pfrio_esize != sizeof(struct pfr_table)) { error = ENODEV; goto fail; } error = pfr_add_tables(io->pfrio_buffer, io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags | PFR_FLAG_USERIOCTL); break; } case DIOCRDELTABLES: { struct pfioc_table *io = (struct pfioc_table *)addr; if (io->pfrio_esize != sizeof(struct pfr_table)) { error = ENODEV; goto fail; } NET_LOCK(); PF_LOCK(); error = pfr_del_tables(io->pfrio_buffer, io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCRGETTABLES: { struct pfioc_table *io = (struct pfioc_table *)addr; if (io->pfrio_esize != sizeof(struct pfr_table)) { error = ENODEV; goto fail; } NET_LOCK(); PF_LOCK(); error = pfr_get_tables(&io->pfrio_table, io->pfrio_buffer, &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCRGETTSTATS: { struct pfioc_table *io = (struct pfioc_table *)addr; if (io->pfrio_esize != sizeof(struct pfr_tstats)) { error = ENODEV; goto fail; } NET_LOCK(); PF_LOCK(); error = pfr_get_tstats(&io->pfrio_table, io->pfrio_buffer, &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCRCLRTSTATS: { struct pfioc_table *io = (struct pfioc_table *)addr; if (io->pfrio_esize != sizeof(struct pfr_table)) { error = ENODEV; goto fail; } NET_LOCK(); PF_LOCK(); error = pfr_clr_tstats(io->pfrio_buffer, io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCRSETTFLAGS: { struct pfioc_table *io = (struct pfioc_table *)addr; if (io->pfrio_esize != sizeof(struct pfr_table)) { error = ENODEV; goto fail; } NET_LOCK(); PF_LOCK(); error = pfr_set_tflags(io->pfrio_buffer, io->pfrio_size, io->pfrio_setflag, io->pfrio_clrflag, &io->pfrio_nchange, &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCRCLRADDRS: { struct pfioc_table *io = (struct pfioc_table *)addr; if (io->pfrio_esize != 0) { error = ENODEV; goto fail; } NET_LOCK(); PF_LOCK(); error = pfr_clr_addrs(&io->pfrio_table, &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCRADDADDRS: { struct pfioc_table *io = (struct pfioc_table *)addr; if (io->pfrio_esize != sizeof(struct pfr_addr)) { error = ENODEV; goto fail; } error = pfr_add_addrs(&io->pfrio_table, io->pfrio_buffer, io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags | PFR_FLAG_USERIOCTL); break; } case DIOCRDELADDRS: { struct pfioc_table *io = (struct pfioc_table *)addr; if (io->pfrio_esize != sizeof(struct pfr_addr)) { error = ENODEV; goto fail; } NET_LOCK(); PF_LOCK(); error = pfr_del_addrs(&io->pfrio_table, io->pfrio_buffer, io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCRSETADDRS: { struct pfioc_table *io = (struct pfioc_table *)addr; if (io->pfrio_esize != sizeof(struct pfr_addr)) { error = ENODEV; goto fail; } NET_LOCK(); PF_LOCK(); error = pfr_set_addrs(&io->pfrio_table, io->pfrio_buffer, io->pfrio_size, &io->pfrio_size2, &io->pfrio_nadd, &io->pfrio_ndel, &io->pfrio_nchange, io->pfrio_flags | PFR_FLAG_USERIOCTL, 0); PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCRGETADDRS: { struct pfioc_table *io = (struct pfioc_table *)addr; if (io->pfrio_esize != sizeof(struct pfr_addr)) { error = ENODEV; goto fail; } NET_LOCK(); PF_LOCK(); error = pfr_get_addrs(&io->pfrio_table, io->pfrio_buffer, &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCRGETASTATS: { struct pfioc_table *io = (struct pfioc_table *)addr; if (io->pfrio_esize != sizeof(struct pfr_astats)) { error = ENODEV; goto fail; } NET_LOCK(); PF_LOCK(); error = pfr_get_astats(&io->pfrio_table, io->pfrio_buffer, &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCRCLRASTATS: { struct pfioc_table *io = (struct pfioc_table *)addr; if (io->pfrio_esize != sizeof(struct pfr_addr)) { error = ENODEV; goto fail; } NET_LOCK(); PF_LOCK(); error = pfr_clr_astats(&io->pfrio_table, io->pfrio_buffer, io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCRTSTADDRS: { struct pfioc_table *io = (struct pfioc_table *)addr; if (io->pfrio_esize != sizeof(struct pfr_addr)) { error = ENODEV; goto fail; } NET_LOCK(); PF_LOCK(); error = pfr_tst_addrs(&io->pfrio_table, io->pfrio_buffer, io->pfrio_size, &io->pfrio_nmatch, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCRINADEFINE: { struct pfioc_table *io = (struct pfioc_table *)addr; if (io->pfrio_esize != sizeof(struct pfr_addr)) { error = ENODEV; goto fail; } NET_LOCK(); PF_LOCK(); error = pfr_ina_define(&io->pfrio_table, io->pfrio_buffer, io->pfrio_size, &io->pfrio_nadd, &io->pfrio_naddr, io->pfrio_ticket, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCOSFPADD: { struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr; error = pf_osfp_add(io); break; } case DIOCOSFPGET: { struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr; error = pf_osfp_get(io); break; } case DIOCXBEGIN: { struct pfioc_trans *io = (struct pfioc_trans *)addr; struct pfioc_trans_e *ioe; struct pfr_table *table; int i; if (io->esize != sizeof(*ioe)) { error = ENODEV; goto fail; } ioe = malloc(sizeof(*ioe), M_PF, M_WAITOK); table = malloc(sizeof(*table), M_PF, M_WAITOK); NET_LOCK(); PF_LOCK(); pf_default_rule_new = pf_default_rule; PF_UNLOCK(); NET_UNLOCK(); memset(&pf_trans_set, 0, sizeof(pf_trans_set)); for (i = 0; i < io->size; i++) { if (copyin(io->array+i, ioe, sizeof(*ioe))) { free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); error = EFAULT; goto fail; } if (strnlen(ioe->anchor, sizeof(ioe->anchor)) == sizeof(ioe->anchor)) { free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); error = ENAMETOOLONG; goto fail; } NET_LOCK(); PF_LOCK(); switch (ioe->type) { case PF_TRANS_TABLE: memset(table, 0, sizeof(*table)); strlcpy(table->pfrt_anchor, ioe->anchor, sizeof(table->pfrt_anchor)); if ((error = pfr_ina_begin(table, &ioe->ticket, NULL, 0))) { PF_UNLOCK(); NET_UNLOCK(); free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); goto fail; } break; case PF_TRANS_RULESET: if ((error = pf_begin_rules(&ioe->ticket, ioe->anchor))) { PF_UNLOCK(); NET_UNLOCK(); free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); goto fail; } break; default: PF_UNLOCK(); NET_UNLOCK(); free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); error = EINVAL; goto fail; } PF_UNLOCK(); NET_UNLOCK(); if (copyout(ioe, io->array+i, sizeof(io->array[i]))) { free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); error = EFAULT; goto fail; } } free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); break; } case DIOCXROLLBACK: { struct pfioc_trans *io = (struct pfioc_trans *)addr; struct pfioc_trans_e *ioe; struct pfr_table *table; int i; if (io->esize != sizeof(*ioe)) { error = ENODEV; goto fail; } ioe = malloc(sizeof(*ioe), M_PF, M_WAITOK); table = malloc(sizeof(*table), M_PF, M_WAITOK); for (i = 0; i < io->size; i++) { if (copyin(io->array+i, ioe, sizeof(*ioe))) { free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); error = EFAULT; goto fail; } if (strnlen(ioe->anchor, sizeof(ioe->anchor)) == sizeof(ioe->anchor)) { free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); error = ENAMETOOLONG; goto fail; } NET_LOCK(); PF_LOCK(); switch (ioe->type) { case PF_TRANS_TABLE: memset(table, 0, sizeof(*table)); strlcpy(table->pfrt_anchor, ioe->anchor, sizeof(table->pfrt_anchor)); if ((error = pfr_ina_rollback(table, ioe->ticket, NULL, 0))) { PF_UNLOCK(); NET_UNLOCK(); free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); goto fail; /* really bad */ } break; case PF_TRANS_RULESET: pf_rollback_rules(ioe->ticket, ioe->anchor); break; default: PF_UNLOCK(); NET_UNLOCK(); free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); error = EINVAL; goto fail; /* really bad */ } PF_UNLOCK(); NET_UNLOCK(); } free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); break; } case DIOCXCOMMIT: { struct pfioc_trans *io = (struct pfioc_trans *)addr; struct pfioc_trans_e *ioe; struct pfr_table *table; struct pf_ruleset *rs; int i; if (io->esize != sizeof(*ioe)) { error = ENODEV; goto fail; } ioe = malloc(sizeof(*ioe), M_PF, M_WAITOK); table = malloc(sizeof(*table), M_PF, M_WAITOK); /* first makes sure everything will succeed */ for (i = 0; i < io->size; i++) { if (copyin(io->array+i, ioe, sizeof(*ioe))) { free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); error = EFAULT; goto fail; } if (strnlen(ioe->anchor, sizeof(ioe->anchor)) == sizeof(ioe->anchor)) { free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); error = ENAMETOOLONG; goto fail; } NET_LOCK(); PF_LOCK(); switch (ioe->type) { case PF_TRANS_TABLE: rs = pf_find_ruleset(ioe->anchor); if (rs == NULL || !rs->topen || ioe->ticket != rs->tticket) { PF_UNLOCK(); NET_UNLOCK(); free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); error = EBUSY; goto fail; } break; case PF_TRANS_RULESET: rs = pf_find_ruleset(ioe->anchor); if (rs == NULL || !rs->rules.inactive.open || rs->rules.inactive.version != ioe->ticket) { PF_UNLOCK(); NET_UNLOCK(); free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); error = EBUSY; goto fail; } break; default: PF_UNLOCK(); NET_UNLOCK(); free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); error = EINVAL; goto fail; } PF_UNLOCK(); NET_UNLOCK(); } NET_LOCK(); PF_LOCK(); /* * Checked already in DIOCSETLIMIT, but check again as the * situation might have changed. */ for (i = 0; i < PF_LIMIT_MAX; i++) { if (((struct pool *)pf_pool_limits[i].pp)->pr_nout > pf_pool_limits[i].limit_new) { PF_UNLOCK(); NET_UNLOCK(); free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); error = EBUSY; goto fail; } } /* now do the commit - no errors should happen here */ for (i = 0; i < io->size; i++) { PF_UNLOCK(); NET_UNLOCK(); if (copyin(io->array+i, ioe, sizeof(*ioe))) { free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); error = EFAULT; goto fail; } if (strnlen(ioe->anchor, sizeof(ioe->anchor)) == sizeof(ioe->anchor)) { free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); error = ENAMETOOLONG; goto fail; } NET_LOCK(); PF_LOCK(); switch (ioe->type) { case PF_TRANS_TABLE: memset(table, 0, sizeof(*table)); strlcpy(table->pfrt_anchor, ioe->anchor, sizeof(table->pfrt_anchor)); if ((error = pfr_ina_commit(table, ioe->ticket, NULL, NULL, 0))) { PF_UNLOCK(); NET_UNLOCK(); free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); goto fail; /* really bad */ } break; case PF_TRANS_RULESET: if ((error = pf_commit_rules(ioe->ticket, ioe->anchor))) { PF_UNLOCK(); NET_UNLOCK(); free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); goto fail; /* really bad */ } break; default: PF_UNLOCK(); NET_UNLOCK(); free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); error = EINVAL; goto fail; /* really bad */ } } for (i = 0; i < PF_LIMIT_MAX; i++) { if (pf_pool_limits[i].limit_new != pf_pool_limits[i].limit && pool_sethardlimit(pf_pool_limits[i].pp, pf_pool_limits[i].limit_new, NULL, 0) != 0) { PF_UNLOCK(); NET_UNLOCK(); free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); error = EBUSY; goto fail; /* really bad */ } pf_pool_limits[i].limit = pf_pool_limits[i].limit_new; } for (i = 0; i < PFTM_MAX; i++) { int old = pf_default_rule.timeout[i]; pf_default_rule.timeout[i] = pf_default_rule_new.timeout[i]; if (pf_default_rule.timeout[i] == PFTM_INTERVAL && pf_default_rule.timeout[i] < old && timeout_del(&pf_purge_to)) task_add(systqmp, &pf_purge_task); } pfi_xcommit(); pf_trans_set_commit(); PF_UNLOCK(); NET_UNLOCK(); free(table, M_PF, sizeof(*table)); free(ioe, M_PF, sizeof(*ioe)); break; } case DIOCXEND: { u_int32_t *ticket = (u_int32_t *)addr; struct pf_trans *t; t = pf_find_trans(minor(dev), *ticket); if (t != NULL) pf_rollback_trans(t); else error = ENXIO; break; } case DIOCGETSRCNODES: { struct pfioc_src_nodes *psn = (struct pfioc_src_nodes *)addr; struct pf_src_node *n, *p, *pstore; u_int32_t nr = 0; size_t space = psn->psn_len; pstore = malloc(sizeof(*pstore), M_PF, M_WAITOK); NET_LOCK(); PF_LOCK(); if (space == 0) { RB_FOREACH(n, pf_src_tree, &tree_src_tracking) nr++; psn->psn_len = sizeof(struct pf_src_node) * nr; PF_UNLOCK(); NET_UNLOCK(); free(pstore, M_PF, sizeof(*pstore)); goto fail; } p = psn->psn_src_nodes; RB_FOREACH(n, pf_src_tree, &tree_src_tracking) { int secs = getuptime(), diff; if ((nr + 1) * sizeof(*p) > psn->psn_len) break; memcpy(pstore, n, sizeof(*pstore)); memset(&pstore->entry, 0, sizeof(pstore->entry)); pstore->rule.ptr = NULL; pstore->kif = NULL; pstore->rule.nr = n->rule.ptr->nr; pstore->creation = secs - pstore->creation; if (pstore->expire > secs) pstore->expire -= secs; else pstore->expire = 0; /* adjust the connection rate estimate */ diff = secs - n->conn_rate.last; if (diff >= n->conn_rate.seconds) pstore->conn_rate.count = 0; else pstore->conn_rate.count -= n->conn_rate.count * diff / n->conn_rate.seconds; error = copyout(pstore, p, sizeof(*p)); if (error) { PF_UNLOCK(); NET_UNLOCK(); free(pstore, M_PF, sizeof(*pstore)); goto fail; } p++; nr++; } psn->psn_len = sizeof(struct pf_src_node) * nr; PF_UNLOCK(); NET_UNLOCK(); free(pstore, M_PF, sizeof(*pstore)); break; } case DIOCCLRSRCNODES: { struct pf_src_node *n; struct pf_state *st; NET_LOCK(); PF_LOCK(); PF_STATE_ENTER_WRITE(); RBT_FOREACH(st, pf_state_tree_id, &tree_id) pf_src_tree_remove_state(st); PF_STATE_EXIT_WRITE(); RB_FOREACH(n, pf_src_tree, &tree_src_tracking) n->expire = 1; pf_purge_expired_src_nodes(); PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCKILLSRCNODES: { struct pf_src_node *sn; struct pf_state *st; struct pfioc_src_node_kill *psnk = (struct pfioc_src_node_kill *)addr; u_int killed = 0; NET_LOCK(); PF_LOCK(); RB_FOREACH(sn, pf_src_tree, &tree_src_tracking) { if (pf_match_addr(psnk->psnk_src.neg, &psnk->psnk_src.addr.v.a.addr, &psnk->psnk_src.addr.v.a.mask, &sn->addr, sn->af) && pf_match_addr(psnk->psnk_dst.neg, &psnk->psnk_dst.addr.v.a.addr, &psnk->psnk_dst.addr.v.a.mask, &sn->raddr, sn->af)) { /* Handle state to src_node linkage */ if (sn->states != 0) { PF_ASSERT_LOCKED(); PF_STATE_ENTER_WRITE(); RBT_FOREACH(st, pf_state_tree_id, &tree_id) pf_state_rm_src_node(st, sn); PF_STATE_EXIT_WRITE(); } sn->expire = 1; killed++; } } if (killed > 0) pf_purge_expired_src_nodes(); psnk->psnk_killed = killed; PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCSETHOSTID: { u_int32_t *hostid = (u_int32_t *)addr; NET_LOCK(); PF_LOCK(); if (*hostid == 0) pf_trans_set.hostid = arc4random(); else pf_trans_set.hostid = *hostid; pf_trans_set.mask |= PF_TSET_HOSTID; PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCOSFPFLUSH: pf_osfp_flush(); break; case DIOCIGETIFACES: { struct pfioc_iface *io = (struct pfioc_iface *)addr; struct pfi_kif *kif_buf; int apfiio_size = io->pfiio_size; if (io->pfiio_esize != sizeof(struct pfi_kif)) { error = ENODEV; goto fail; } if ((kif_buf = mallocarray(sizeof(*kif_buf), apfiio_size, M_PF, M_WAITOK|M_CANFAIL)) == NULL) { error = EINVAL; goto fail; } NET_LOCK_SHARED(); PF_LOCK(); pfi_get_ifaces(io->pfiio_name, kif_buf, &io->pfiio_size); PF_UNLOCK(); NET_UNLOCK_SHARED(); if (copyout(kif_buf, io->pfiio_buffer, sizeof(*kif_buf) * io->pfiio_size)) error = EFAULT; free(kif_buf, M_PF, sizeof(*kif_buf) * apfiio_size); break; } case DIOCSETIFFLAG: { struct pfioc_iface *io = (struct pfioc_iface *)addr; if (io == NULL) { error = EINVAL; goto fail; } PF_LOCK(); error = pfi_set_flags(io->pfiio_name, io->pfiio_flags); PF_UNLOCK(); break; } case DIOCCLRIFFLAG: { struct pfioc_iface *io = (struct pfioc_iface *)addr; if (io == NULL) { error = EINVAL; goto fail; } PF_LOCK(); error = pfi_clear_flags(io->pfiio_name, io->pfiio_flags); PF_UNLOCK(); break; } case DIOCSETREASS: { u_int32_t *reass = (u_int32_t *)addr; NET_LOCK(); PF_LOCK(); pf_trans_set.reass = *reass; pf_trans_set.mask |= PF_TSET_REASS; PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCSETSYNFLWATS: { struct pfioc_synflwats *io = (struct pfioc_synflwats *)addr; NET_LOCK(); PF_LOCK(); error = pf_syncookies_setwats(io->hiwat, io->lowat); PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCGETSYNFLWATS: { struct pfioc_synflwats *io = (struct pfioc_synflwats *)addr; NET_LOCK(); PF_LOCK(); error = pf_syncookies_getwats(io); PF_UNLOCK(); NET_UNLOCK(); break; } case DIOCSETSYNCOOKIES: { u_int8_t *mode = (u_int8_t *)addr; NET_LOCK(); PF_LOCK(); error = pf_syncookies_setmode(*mode); PF_UNLOCK(); NET_UNLOCK(); break; } default: error = ENODEV; break; } fail: rw_exit_write(&pfioctl_rw); return (error); } void pf_trans_set_commit(void) { if (pf_trans_set.mask & PF_TSET_STATUSIF) strlcpy(pf_status.ifname, pf_trans_set.statusif, IFNAMSIZ); if (pf_trans_set.mask & PF_TSET_DEBUG) pf_status.debug = pf_trans_set.debug; if (pf_trans_set.mask & PF_TSET_HOSTID) pf_status.hostid = pf_trans_set.hostid; if (pf_trans_set.mask & PF_TSET_REASS) pf_status.reass = pf_trans_set.reass; } void pf_pool_copyin(struct pf_pool *from, struct pf_pool *to) { memmove(to, from, sizeof(*to)); to->kif = NULL; to->addr.p.tbl = NULL; } int pf_validate_range(u_int8_t op, u_int16_t port[2], int order) { u_int16_t a = (order == PF_ORDER_NET) ? ntohs(port[0]) : port[0]; u_int16_t b = (order == PF_ORDER_NET) ? ntohs(port[1]) : port[1]; if ((op == PF_OP_RRG && a > b) || /* 34:12, i.e. none */ (op == PF_OP_IRG && a >= b) || /* 34><12, i.e. none */ (op == PF_OP_XRG && a > b)) /* 34<>22, i.e. all */ return 1; return 0; } int pf_rule_copyin(struct pf_rule *from, struct pf_rule *to) { int i; if (from->scrub_flags & PFSTATE_SETPRIO && (from->set_prio[0] > IFQ_MAXPRIO || from->set_prio[1] > IFQ_MAXPRIO)) return (EINVAL); to->src = from->src; to->src.addr.p.tbl = NULL; to->dst = from->dst; to->dst.addr.p.tbl = NULL; if (pf_validate_range(to->src.port_op, to->src.port, PF_ORDER_NET)) return (EINVAL); if (pf_validate_range(to->dst.port_op, to->dst.port, PF_ORDER_NET)) return (EINVAL); /* XXX union skip[] */ strlcpy(to->label, from->label, sizeof(to->label)); strlcpy(to->ifname, from->ifname, sizeof(to->ifname)); strlcpy(to->rcv_ifname, from->rcv_ifname, sizeof(to->rcv_ifname)); strlcpy(to->qname, from->qname, sizeof(to->qname)); strlcpy(to->pqname, from->pqname, sizeof(to->pqname)); strlcpy(to->tagname, from->tagname, sizeof(to->tagname)); strlcpy(to->match_tagname, from->match_tagname, sizeof(to->match_tagname)); strlcpy(to->overload_tblname, from->overload_tblname, sizeof(to->overload_tblname)); pf_pool_copyin(&from->nat, &to->nat); pf_pool_copyin(&from->rdr, &to->rdr); pf_pool_copyin(&from->route, &to->route); if (pf_validate_range(to->rdr.port_op, to->rdr.proxy_port, PF_ORDER_HOST)) return (EINVAL); to->kif = (to->ifname[0]) ? pfi_kif_alloc(to->ifname, M_WAITOK) : NULL; to->rcv_kif = (to->rcv_ifname[0]) ? pfi_kif_alloc(to->rcv_ifname, M_WAITOK) : NULL; to->rdr.kif = (to->rdr.ifname[0]) ? pfi_kif_alloc(to->rdr.ifname, M_WAITOK) : NULL; to->nat.kif = (to->nat.ifname[0]) ? pfi_kif_alloc(to->nat.ifname, M_WAITOK) : NULL; to->route.kif = (to->route.ifname[0]) ? pfi_kif_alloc(to->route.ifname, M_WAITOK) : NULL; to->os_fingerprint = from->os_fingerprint; to->rtableid = from->rtableid; if (to->rtableid >= 0 && !rtable_exists(to->rtableid)) return (EBUSY); to->onrdomain = from->onrdomain; if (to->onrdomain != -1 && (to->onrdomain < 0 || to->onrdomain > RT_TABLEID_MAX)) return (EINVAL); for (i = 0; i < PFTM_MAX; i++) to->timeout[i] = from->timeout[i]; to->states_tot = from->states_tot; to->max_states = from->max_states; to->max_src_nodes = from->max_src_nodes; to->max_src_states = from->max_src_states; to->max_src_conn = from->max_src_conn; to->max_src_conn_rate.limit = from->max_src_conn_rate.limit; to->max_src_conn_rate.seconds = from->max_src_conn_rate.seconds; pf_init_threshold(&to->pktrate, from->pktrate.limit, from->pktrate.seconds); if (to->qname[0] != 0) { if ((to->qid = pf_qname2qid(to->qname, 0)) == 0) return (EBUSY); if (to->pqname[0] != 0) { if ((to->pqid = pf_qname2qid(to->pqname, 0)) == 0) return (EBUSY); } else to->pqid = to->qid; } to->rt_listid = from->rt_listid; to->prob = from->prob; to->return_icmp = from->return_icmp; to->return_icmp6 = from->return_icmp6; to->max_mss = from->max_mss; if (to->tagname[0]) if ((to->tag = pf_tagname2tag(to->tagname, 1)) == 0) return (EBUSY); if (to->match_tagname[0]) if ((to->match_tag = pf_tagname2tag(to->match_tagname, 1)) == 0) return (EBUSY); to->scrub_flags = from->scrub_flags; to->delay = from->delay; to->uid = from->uid; to->gid = from->gid; to->rule_flag = from->rule_flag; to->action = from->action; to->direction = from->direction; to->log = from->log; to->logif = from->logif; #if NPFLOG > 0 if (!to->log) to->logif = 0; #endif /* NPFLOG > 0 */ to->quick = from->quick; to->ifnot = from->ifnot; to->rcvifnot = from->rcvifnot; to->match_tag_not = from->match_tag_not; to->keep_state = from->keep_state; to->af = from->af; to->naf = from->naf; to->proto = from->proto; to->type = from->type; to->code = from->code; to->flags = from->flags; to->flagset = from->flagset; to->min_ttl = from->min_ttl; to->allow_opts = from->allow_opts; to->rt = from->rt; to->return_ttl = from->return_ttl; to->tos = from->tos; to->set_tos = from->set_tos; to->anchor_relative = from->anchor_relative; /* XXX */ to->anchor_wildcard = from->anchor_wildcard; /* XXX */ to->flush = from->flush; to->divert.addr = from->divert.addr; to->divert.port = from->divert.port; to->divert.type = from->divert.type; to->prio = from->prio; to->set_prio[0] = from->set_prio[0]; to->set_prio[1] = from->set_prio[1]; return (0); } int pf_rule_checkaf(struct pf_rule *r) { switch (r->af) { case 0: if (r->rule_flag & PFRULE_AFTO) return (EPFNOSUPPORT); break; case AF_INET: if ((r->rule_flag & PFRULE_AFTO) && r->naf != AF_INET6) return (EPFNOSUPPORT); break; #ifdef INET6 case AF_INET6: if ((r->rule_flag & PFRULE_AFTO) && r->naf != AF_INET) return (EPFNOSUPPORT); break; #endif /* INET6 */ default: return (EPFNOSUPPORT); } if ((r->rule_flag & PFRULE_AFTO) == 0 && r->naf != 0) return (EPFNOSUPPORT); return (0); } int pf_sysctl(void *oldp, size_t *oldlenp, void *newp, size_t newlen) { struct pf_status pfs; NET_LOCK_SHARED(); PF_LOCK(); PF_FRAG_LOCK(); memcpy(&pfs, &pf_status, sizeof(struct pf_status)); PF_FRAG_UNLOCK(); pfi_update_status(pfs.ifname, &pfs); PF_UNLOCK(); NET_UNLOCK_SHARED(); return sysctl_rdstruct(oldp, oldlenp, newp, &pfs, sizeof(pfs)); } struct pf_trans * pf_open_trans(uint32_t unit) { static uint64_t ticket = 1; struct pf_trans *t; rw_assert_wrlock(&pfioctl_rw); KASSERT(pf_unit2idx(unit) < nitems(pf_tcount)); if (pf_tcount[pf_unit2idx(unit)] >= (PF_ANCHOR_STACK_MAX * 8)) return (NULL); t = malloc(sizeof(*t), M_PF, M_WAITOK|M_ZERO); t->pft_unit = unit; t->pft_ticket = ticket++; pf_tcount[pf_unit2idx(unit)]++; LIST_INSERT_HEAD(&pf_ioctl_trans, t, pft_entry); return (t); } struct pf_trans * pf_find_trans(uint32_t unit, uint64_t ticket) { struct pf_trans *t; rw_assert_anylock(&pfioctl_rw); LIST_FOREACH(t, &pf_ioctl_trans, pft_entry) { if (t->pft_ticket == ticket && t->pft_unit == unit) break; } return (t); } void pf_init_tgetrule(struct pf_trans *t, struct pf_anchor *a, uint32_t rs_version, struct pf_rule *r) { t->pft_type = PF_TRANS_GETRULE; if (a == NULL) t->pftgr_anchor = &pf_main_anchor; else t->pftgr_anchor = a; t->pftgr_version = rs_version; t->pftgr_rule = r; } void pf_cleanup_tgetrule(struct pf_trans *t) { KASSERT(t->pft_type == PF_TRANS_GETRULE); pf_anchor_rele(t->pftgr_anchor); } void pf_free_trans(struct pf_trans *t) { switch (t->pft_type) { case PF_TRANS_GETRULE: pf_cleanup_tgetrule(t); break; default: log(LOG_ERR, "%s unknown transaction type: %d\n", __func__, t->pft_type); } KASSERT(pf_unit2idx(t->pft_unit) < nitems(pf_tcount)); KASSERT(pf_tcount[pf_unit2idx(t->pft_unit)] >= 1); pf_tcount[pf_unit2idx(t->pft_unit)]--; free(t, M_PF, sizeof(*t)); } void pf_rollback_trans(struct pf_trans *t) { if (t != NULL) { rw_assert_wrlock(&pfioctl_rw); LIST_REMOVE(t, pft_entry); pf_free_trans(t); } }
1 1 1 57 53 50 103 42 3 5 1 9 6 6 5 6 6 16 37 6 32 41 20 2 11 9 9 41 3 28 6 3 3 3 2 10 11 11 5 1 4 3 3 3 3 1 1 9 1 1 1 4 2 6 1 1 1 1 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 /* $OpenBSD: vmm.c,v 1.2 2023/05/13 23:15:28 dv Exp $ */ /* * Copyright (c) 2014-2023 Mike Larkin <mlarkin@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> #include <sys/pool.h> #include <sys/pledge.h> #include <sys/proc.h> #include <sys/ioctl.h> #include <sys/malloc.h> #include <sys/signalvar.h> #include <machine/vmmvar.h> #include <dev/vmm/vmm.h> struct vmm_softc *vmm_softc; struct pool vm_pool; struct pool vcpu_pool; struct cfdriver vmm_cd = { NULL, "vmm", DV_DULL, CD_SKIPHIBERNATE }; const struct cfattach vmm_ca = { sizeof(struct vmm_softc), vmm_probe, vmm_attach, NULL, vmm_activate }; int vmm_probe(struct device *parent, void *match, void *aux) { const char **busname = (const char **)aux; if (strcmp(*busname, vmm_cd.cd_name) != 0) return (0); return (1); } void vmm_attach(struct device *parent, struct device *self, void *aux) { struct vmm_softc *sc = (struct vmm_softc *)self; rw_init(&sc->sc_slock, "vmmslk"); sc->sc_status = VMM_ACTIVE; refcnt_init(&sc->sc_refcnt); sc->vcpu_ct = 0; sc->vcpu_max = VMM_MAX_VCPUS; sc->vm_ct = 0; sc->vm_idx = 0; SLIST_INIT(&sc->vm_list); rw_init(&sc->vm_lock, "vm_list"); pool_init(&vm_pool, sizeof(struct vm), 0, IPL_MPFLOOR, PR_WAITOK, "vmpool", NULL); pool_init(&vcpu_pool, sizeof(struct vcpu), 64, IPL_MPFLOOR, PR_WAITOK, "vcpupl", NULL); vmm_attach_machdep(parent, self, aux); vmm_softc = sc; printf("\n"); } int vmm_activate(struct device *self, int act) { switch (act) { case DVACT_QUIESCE: /* Block device users as we're suspending operation. */ rw_enter_write(&vmm_softc->sc_slock); KASSERT(vmm_softc->sc_status == VMM_ACTIVE); vmm_softc->sc_status = VMM_SUSPENDED; rw_exit_write(&vmm_softc->sc_slock); /* Wait for any device users to finish. */ refcnt_finalize(&vmm_softc->sc_refcnt, "vmmsusp"); vmm_activate_machdep(self, act); break; case DVACT_WAKEUP: vmm_activate_machdep(self, act); /* Set the device back to active. */ rw_enter_write(&vmm_softc->sc_slock); KASSERT(vmm_softc->sc_status == VMM_SUSPENDED); refcnt_init(&vmm_softc->sc_refcnt); vmm_softc->sc_status = VMM_ACTIVE; rw_exit_write(&vmm_softc->sc_slock); /* Notify any waiting device users. */ wakeup(&vmm_softc->sc_status); break; } return (0); } /* * vmmopen * * Called during open of /dev/vmm. * * Parameters: * dev, flag, mode, p: These come from the character device and are * all unused for this function * * Return values: * ENODEV: if vmm(4) didn't attach or no supported CPUs detected * 0: successful open */ int vmmopen(dev_t dev, int flag, int mode, struct proc *p) { /* Don't allow open if we didn't attach */ if (vmm_softc == NULL) return (ENODEV); /* Don't allow open if we didn't detect any supported CPUs */ if (vmm_softc->mode == VMM_MODE_UNKNOWN) return (ENODEV); return 0; } /* * vmmclose * * Called when /dev/vmm is closed. Presently unused. */ int vmmclose(dev_t dev, int flag, int mode, struct proc *p) { return 0; } /* * vm_find * * Function to find an existing VM by its identifier. * Must be called under the global vm_lock. * * Parameters: * id: The VM identifier. * *res: A pointer to the VM or NULL if not found * * Return values: * 0: if successful * ENOENT: if the VM defined by 'id' cannot be found * EPERM: if the VM cannot be accessed by the current process */ int vm_find(uint32_t id, struct vm **res) { struct proc *p = curproc; struct vm *vm; int ret = ENOENT; *res = NULL; rw_enter_read(&vmm_softc->vm_lock); SLIST_FOREACH(vm, &vmm_softc->vm_list, vm_link) { if (vm->vm_id == id) { /* * In the pledged VM process, only allow to find * the VM that is running in the current process. * The managing vmm parent process can lookup all * all VMs and is indicated by PLEDGE_PROC. */ if (((p->p_p->ps_pledge & (PLEDGE_VMM | PLEDGE_PROC)) == PLEDGE_VMM) && (vm->vm_creator_pid != p->p_p->ps_pid)) ret = EPERM; else { refcnt_take(&vm->vm_refcnt); *res = vm; ret = 0; } break; } } rw_exit_read(&vmm_softc->vm_lock); if (ret == EPERM) return (pledge_fail(p, EPERM, PLEDGE_VMM)); return (ret); } /* * vmmioctl * * Main ioctl dispatch routine for /dev/vmm. Parses ioctl type and calls * appropriate lower level handler routine. Returns result to ioctl caller. */ int vmmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { int ret; KERNEL_UNLOCK(); ret = rw_enter(&vmm_softc->sc_slock, RW_READ | RW_INTR); if (ret != 0) goto out; while (vmm_softc->sc_status != VMM_ACTIVE) { ret = rwsleep_nsec(&vmm_softc->sc_status, &vmm_softc->sc_slock, PWAIT | PCATCH, "vmmresume", INFSLP); if (ret != 0) { rw_exit(&vmm_softc->sc_slock); goto out; } } refcnt_take(&vmm_softc->sc_refcnt); rw_exit(&vmm_softc->sc_slock); switch (cmd) { case VMM_IOC_CREATE: if ((ret = vmm_start()) != 0) { vmm_stop(); break; } ret = vm_create((struct vm_create_params *)data, p); break; case VMM_IOC_RUN: ret = vm_run((struct vm_run_params *)data); break; case VMM_IOC_INFO: ret = vm_get_info((struct vm_info_params *)data); break; case VMM_IOC_TERM: ret = vm_terminate((struct vm_terminate_params *)data); break; case VMM_IOC_RESETCPU: ret = vm_resetcpu((struct vm_resetcpu_params *)data); break; case VMM_IOC_READREGS: ret = vm_rwregs((struct vm_rwregs_params *)data, 0); break; case VMM_IOC_WRITEREGS: ret = vm_rwregs((struct vm_rwregs_params *)data, 1); break; case VMM_IOC_READVMPARAMS: ret = vm_rwvmparams((struct vm_rwvmparams_params *)data, 0); break; case VMM_IOC_WRITEVMPARAMS: ret = vm_rwvmparams((struct vm_rwvmparams_params *)data, 1); break; case VMM_IOC_SHAREMEM: ret = vm_share_mem((struct vm_sharemem_params *)data, p); break; default: ret = vmmioctl_machdep(dev, cmd, data, flag, p); break; } refcnt_rele_wake(&vmm_softc->sc_refcnt); out: KERNEL_LOCK(); return (ret); } /* * pledge_ioctl_vmm * * Restrict the allowed ioctls in a pledged process context. * Is called from pledge_ioctl(). */ int pledge_ioctl_vmm(struct proc *p, long com) { switch (com) { case VMM_IOC_CREATE: case VMM_IOC_INFO: case VMM_IOC_SHAREMEM: /* The "parent" process in vmd forks and manages VMs */ if (p->p_p->ps_pledge & PLEDGE_PROC) return (0); break; case VMM_IOC_TERM: /* XXX VM processes should only terminate themselves */ case VMM_IOC_RUN: case VMM_IOC_RESETCPU: case VMM_IOC_READREGS: case VMM_IOC_WRITEREGS: case VMM_IOC_READVMPARAMS: case VMM_IOC_WRITEVMPARAMS: return (0); default: return pledge_ioctl_vmm_machdep(p, com); } return (EPERM); } /* * vm_find_vcpu * * Lookup VMM VCPU by ID number * * Parameters: * vm: vm structure * id: index id of vcpu * * Returns pointer to vcpu structure if successful, NULL otherwise */ struct vcpu * vm_find_vcpu(struct vm *vm, uint32_t id) { struct vcpu *vcpu; if (vm == NULL) return (NULL); SLIST_FOREACH(vcpu, &vm->vm_vcpu_list, vc_vcpu_link) { if (vcpu->vc_id == id) return (vcpu); } return (NULL); } /* * vm_create * * Creates the in-memory VMM structures for the VM defined by 'vcp'. The * parent of this VM shall be the process defined by 'p'. * This function does not start the VCPU(s) - see vm_start. * * Return Values: * 0: the create operation was successful * ENOMEM: out of memory * various other errors from vcpu_init/vm_impl_init */ int vm_create(struct vm_create_params *vcp, struct proc *p) { int i, ret; size_t memsize; struct vm *vm; struct vcpu *vcpu; memsize = vm_create_check_mem_ranges(vcp); if (memsize == 0) return (EINVAL); /* XXX - support UP only (for now) */ if (vcp->vcp_ncpus != 1) return (EINVAL); /* Bail early if we're already at vcpu capacity. */ rw_enter_read(&vmm_softc->vm_lock); if (vmm_softc->vcpu_ct + vcp->vcp_ncpus > vmm_softc->vcpu_max) { DPRINTF("%s: maximum vcpus (%lu) reached\n", __func__, vmm_softc->vcpu_max); rw_exit_read(&vmm_softc->vm_lock); return (ENOMEM); } rw_exit_read(&vmm_softc->vm_lock); /* Instantiate and configure the new vm. */ vm = pool_get(&vm_pool, PR_WAITOK | PR_ZERO); vm->vm_creator_pid = p->p_p->ps_pid; vm->vm_nmemranges = vcp->vcp_nmemranges; memcpy(vm->vm_memranges, vcp->vcp_memranges, vm->vm_nmemranges * sizeof(vm->vm_memranges[0])); vm->vm_memory_size = memsize; strncpy(vm->vm_name, vcp->vcp_name, VMM_MAX_NAME_LEN - 1); if (vm_impl_init(vm, p)) { printf("failed to init arch-specific features for vm %p\n", vm); vm_teardown(&vm); return (ENOMEM); } vm->vm_vcpu_ct = 0; /* Initialize each VCPU defined in 'vcp' */ SLIST_INIT(&vm->vm_vcpu_list); for (i = 0; i < vcp->vcp_ncpus; i++) { vcpu = pool_get(&vcpu_pool, PR_WAITOK | PR_ZERO); vcpu->vc_parent = vm; if ((ret = vcpu_init(vcpu)) != 0) { printf("failed to init vcpu %d for vm %p\n", i, vm); vm_teardown(&vm); return (ret); } vcpu->vc_id = vm->vm_vcpu_ct; vm->vm_vcpu_ct++; /* Publish vcpu to list, inheriting the reference. */ SLIST_INSERT_HEAD(&vm->vm_vcpu_list, vcpu, vc_vcpu_link); } /* Attempt to register the vm now that it's configured. */ rw_enter_write(&vmm_softc->vm_lock); if (vmm_softc->vcpu_ct + vm->vm_vcpu_ct > vmm_softc->vcpu_max) { /* Someone already took our capacity. */ printf("%s: maximum vcpus (%lu) reached\n", __func__, vmm_softc->vcpu_max); rw_exit_write(&vmm_softc->vm_lock); vm_teardown(&vm); return (ENOMEM); } /* Update the global index and identify the vm. */ vmm_softc->vm_idx++; vm->vm_id = vmm_softc->vm_idx; vcp->vcp_id = vm->vm_id; /* Publish the vm into the list and update counts. */ refcnt_init(&vm->vm_refcnt); SLIST_INSERT_HEAD(&vmm_softc->vm_list, vm, vm_link); vmm_softc->vm_ct++; vmm_softc->vcpu_ct += vm->vm_vcpu_ct; rw_exit_write(&vmm_softc->vm_lock); return (0); } /* * vm_create_check_mem_ranges * * Make sure that the guest physical memory ranges given by the user process * do not overlap and are in ascending order. * * The last physical address may not exceed VMM_MAX_VM_MEM_SIZE. * * Return Values: * The total memory size in bytes if the checks were successful * 0: One of the memory ranges was invalid or VMM_MAX_VM_MEM_SIZE was * exceeded */ size_t vm_create_check_mem_ranges(struct vm_create_params *vcp) { size_t i, memsize = 0; struct vm_mem_range *vmr, *pvmr; const paddr_t maxgpa = VMM_MAX_VM_MEM_SIZE; if (vcp->vcp_nmemranges == 0 || vcp->vcp_nmemranges > VMM_MAX_MEM_RANGES) { DPRINTF("invalid number of guest memory ranges\n"); return (0); } for (i = 0; i < vcp->vcp_nmemranges; i++) { vmr = &vcp->vcp_memranges[i]; /* Only page-aligned addresses and sizes are permitted */ if ((vmr->vmr_gpa & PAGE_MASK) || (vmr->vmr_va & PAGE_MASK) || (vmr->vmr_size & PAGE_MASK) || vmr->vmr_size == 0) { DPRINTF("memory range %zu is not page aligned\n", i); return (0); } /* Make sure that VMM_MAX_VM_MEM_SIZE is not exceeded */ if (vmr->vmr_gpa >= maxgpa || vmr->vmr_size > maxgpa - vmr->vmr_gpa) { DPRINTF("exceeded max memory size\n"); return (0); } /* * Make sure that all virtual addresses are within the address * space of the process and that they do not wrap around. * Calling uvm_share() when creating the VM will take care of * further checks. */ if (vmr->vmr_va < VM_MIN_ADDRESS || vmr->vmr_va >= VM_MAXUSER_ADDRESS || vmr->vmr_size >= VM_MAXUSER_ADDRESS - vmr->vmr_va) { DPRINTF("guest va not within range or wraps\n"); return (0); } /* * Make sure that guest physical memory ranges do not overlap * and that they are ascending. */ if (i > 0 && pvmr->vmr_gpa + pvmr->vmr_size > vmr->vmr_gpa) { DPRINTF("guest range %zu overlaps or !ascending\n", i); return (0); } /* * No memory is mappable in MMIO ranges, so don't count towards * the total guest memory size. */ if (vmr->vmr_type != VM_MEM_MMIO) memsize += vmr->vmr_size; pvmr = vmr; } return (memsize); } /* * vm_teardown * * Tears down (destroys) the vm indicated by 'vm'. * * Assumes the vm is already removed from the global vm list (or was never * added). * * Parameters: * vm: vm to be torn down */ void vm_teardown(struct vm **target) { size_t nvcpu = 0; struct vcpu *vcpu, *tmp; struct vm *vm = *target; struct vmspace *vm_vmspace; KERNEL_ASSERT_UNLOCKED(); /* Free VCPUs */ SLIST_FOREACH_SAFE(vcpu, &vm->vm_vcpu_list, vc_vcpu_link, tmp) { SLIST_REMOVE(&vm->vm_vcpu_list, vcpu, vcpu, vc_vcpu_link); vcpu_deinit(vcpu); pool_put(&vcpu_pool, vcpu); nvcpu++; } vm_impl_deinit(vm); /* teardown guest vmspace */ KERNEL_LOCK(); vm_vmspace = vm->vm_vmspace; if (vm_vmspace != NULL) { vm->vm_vmspace = NULL; uvmspace_free(vm_vmspace); } KERNEL_UNLOCK(); pool_put(&vm_pool, vm); *target = NULL; } /* * vm_get_info * * Returns information about the VM indicated by 'vip'. The 'vip_size' field * in the 'vip' parameter is used to indicate the size of the caller's buffer. * If insufficient space exists in that buffer, the required size needed is * returned in vip_size and the number of VM information structures returned * in vip_info_count is set to 0. The caller should then try the ioctl again * after allocating a sufficiently large buffer. * * Parameters: * vip: information structure identifying the VM to query * * Return values: * 0: the operation succeeded * ENOMEM: memory allocation error during processing * EFAULT: error copying data to user process */ int vm_get_info(struct vm_info_params *vip) { struct vm_info_result *out; struct vm *vm; struct vcpu *vcpu; int i = 0, j; size_t need, vm_ct; rw_enter_read(&vmm_softc->vm_lock); vm_ct = vmm_softc->vm_ct; rw_exit_read(&vmm_softc->vm_lock); need = vm_ct * sizeof(struct vm_info_result); if (vip->vip_size < need) { vip->vip_info_ct = 0; vip->vip_size = need; return (0); } out = malloc(need, M_DEVBUF, M_NOWAIT|M_ZERO); if (out == NULL) { vip->vip_info_ct = 0; return (ENOMEM); } vip->vip_info_ct = vm_ct; rw_enter_read(&vmm_softc->vm_lock); SLIST_FOREACH(vm, &vmm_softc->vm_list, vm_link) { refcnt_take(&vm->vm_refcnt); out[i].vir_memory_size = vm->vm_memory_size; out[i].vir_used_size = pmap_resident_count(vm->vm_map->pmap) * PAGE_SIZE; out[i].vir_ncpus = vm->vm_vcpu_ct; out[i].vir_id = vm->vm_id; out[i].vir_creator_pid = vm->vm_creator_pid; strlcpy(out[i].vir_name, vm->vm_name, VMM_MAX_NAME_LEN); for (j = 0; j < vm->vm_vcpu_ct; j++) { out[i].vir_vcpu_state[j] = VCPU_STATE_UNKNOWN; SLIST_FOREACH(vcpu, &vm->vm_vcpu_list, vc_vcpu_link) { if (vcpu->vc_id == j) out[i].vir_vcpu_state[j] = vcpu->vc_state; } } refcnt_rele_wake(&vm->vm_refcnt); i++; if (i == vm_ct) break; /* Truncate to keep within bounds of 'out'. */ } rw_exit_read(&vmm_softc->vm_lock); if (copyout(out, vip->vip_info, need) == EFAULT) { free(out, M_DEVBUF, need); return (EFAULT); } free(out, M_DEVBUF, need); return (0); } /* * vm_terminate * * Terminates the VM indicated by 'vtp'. * * Parameters: * vtp: structure defining the VM to terminate * * Return values: * 0: the VM was terminated * !0: the VM could not be located */ int vm_terminate(struct vm_terminate_params *vtp) { struct vm *vm; int error, nvcpu, vm_id; /* * Find desired VM */ error = vm_find(vtp->vtp_vm_id, &vm); if (error) return (error); /* Pop the vm out of the global vm list. */ rw_enter_write(&vmm_softc->vm_lock); SLIST_REMOVE(&vmm_softc->vm_list, vm, vm, vm_link); rw_exit_write(&vmm_softc->vm_lock); /* Drop the vm_list's reference to the vm. */ if (refcnt_rele(&vm->vm_refcnt)) panic("%s: vm %d(%p) vm_list refcnt drop was the last", __func__, vm->vm_id, vm); /* Wait for our reference (taken from vm_find) is the last active. */ refcnt_finalize(&vm->vm_refcnt, __func__); vm_id = vm->vm_id; nvcpu = vm->vm_vcpu_ct; vm_teardown(&vm); if (vm_id > 0) { rw_enter_write(&vmm_softc->vm_lock); vmm_softc->vm_ct--; vmm_softc->vcpu_ct -= nvcpu; if (vmm_softc->vm_ct < 1) vmm_stop(); rw_exit_write(&vmm_softc->vm_lock); } return (0); } /* * vm_resetcpu * * Resets the vcpu defined in 'vrp' to power-on-init register state * * Parameters: * vrp: ioctl structure defining the vcpu to reset (see vmmvar.h) * * Returns 0 if successful, or various error codes on failure: * ENOENT if the VM id contained in 'vrp' refers to an unknown VM or * if vrp describes an unknown vcpu for this VM * EBUSY if the indicated VCPU is not stopped * EIO if the indicated VCPU failed to reset */ int vm_resetcpu(struct vm_resetcpu_params *vrp) { struct vm *vm; struct vcpu *vcpu; int error, ret = 0; /* Find the desired VM */ error = vm_find(vrp->vrp_vm_id, &vm); /* Not found? exit. */ if (error != 0) { DPRINTF("%s: vm id %u not found\n", __func__, vrp->vrp_vm_id); return (error); } vcpu = vm_find_vcpu(vm, vrp->vrp_vcpu_id); if (vcpu == NULL) { DPRINTF("%s: vcpu id %u of vm %u not found\n", __func__, vrp->vrp_vcpu_id, vrp->vrp_vm_id); ret = ENOENT; goto out; } rw_enter_write(&vcpu->vc_lock); if (vcpu->vc_state != VCPU_STATE_STOPPED) ret = EBUSY; else { if (vcpu_reset_regs(vcpu, &vrp->vrp_init_state)) { printf("%s: failed\n", __func__); #ifdef VMM_DEBUG dump_vcpu(vcpu); #endif /* VMM_DEBUG */ ret = EIO; } } rw_exit_write(&vcpu->vc_lock); out: refcnt_rele_wake(&vm->vm_refcnt); return (ret); } /* * vcpu_must_stop * * Check if we need to (temporarily) stop running the VCPU for some reason, * such as: * - the VM was requested to terminate * - the proc running this VCPU has pending signals * * Parameters: * vcpu: the VCPU to check * * Return values: * 1: the VM owning this VCPU should stop * 0: no stop is needed */ int vcpu_must_stop(struct vcpu *vcpu) { struct proc *p = curproc; if (vcpu->vc_state == VCPU_STATE_REQTERM) return (1); if (SIGPENDING(p) != 0) return (1); return (0); } /* * vm_share_mem * * Share a uvm mapping for the vm guest memory ranges into the calling process. * * Return values: * 0: if successful * ENOENT: if the vm cannot be found by vm_find * EPERM: if the vm cannot be accessed by the current process * EINVAL: if the provide memory ranges fail checks * ENOMEM: if uvm_share fails to find available memory in the destination map */ int vm_share_mem(struct vm_sharemem_params *vsp, struct proc *p) { int ret = EINVAL; size_t i, n; struct vm *vm; struct vm_mem_range *src, *dst; ret = vm_find(vsp->vsp_vm_id, &vm); if (ret) return (ret); /* Check we have the expected number of ranges. */ if (vm->vm_nmemranges != vsp->vsp_nmemranges) goto out; n = vm->vm_nmemranges; /* Check their types, sizes, and gpa's (implying page alignment). */ for (i = 0; i < n; i++) { src = &vm->vm_memranges[i]; dst = &vsp->vsp_memranges[i]; /* * The vm memranges were already checked during creation, so * compare to them to confirm validity of mapping request. */ if (src->vmr_type != dst->vmr_type) goto out; if (src->vmr_gpa != dst->vmr_gpa) goto out; if (src->vmr_size != dst->vmr_size) goto out; /* Check our intended destination is page-aligned. */ if (dst->vmr_va & PAGE_MASK) goto out; } /* * Share each range individually with the calling process. We do * not need PROC_EXEC as the emulated devices do not need to execute * instructions from guest memory. */ for (i = 0; i < n; i++) { src = &vm->vm_memranges[i]; dst = &vsp->vsp_memranges[i]; /* Skip MMIO range. */ if (src->vmr_type == VM_MEM_MMIO) continue; DPRINTF("sharing gpa=0x%lx for pid %d @ va=0x%lx\n", src->vmr_gpa, p->p_p->ps_pid, dst->vmr_va); ret = uvm_share(&p->p_vmspace->vm_map, dst->vmr_va, PROT_READ | PROT_WRITE, vm->vm_map, src->vmr_gpa, src->vmr_size); if (ret) { printf("%s: uvm_share failed (%d)\n", __func__, ret); break; } } ret = 0; out: refcnt_rele_wake(&vm->vm_refcnt); return (ret); }
231 72 209 211 136 100 100 21 75 5 2 10 43 24 9 10 14 63 10 63 65 28 55 65 65 65 63 64 9 12 63 56 49 39 39 55 18 1 17 17 7 10 65 65 20 20 15 8 20 14 9 9 9 20 20 20 20 5 20 4 1 3 9 14 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 /* $OpenBSD: ffs_inode.c,v 1.83 2024/02/03 18:51:58 beck Exp $ */ /* $NetBSD: ffs_inode.c,v 1.10 1996/05/11 18:27:19 mycroft Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ffs_inode.c 8.8 (Berkeley) 10/19/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/mount.h> #include <sys/proc.h> #include <sys/buf.h> #include <sys/vnode.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/resourcevar.h> #include <ufs/ufs/quota.h> #include <ufs/ufs/inode.h> #include <ufs/ufs/ufsmount.h> #include <ufs/ufs/ufs_extern.h> #include <ufs/ffs/fs.h> #include <ufs/ffs/ffs_extern.h> int ffs_indirtrunc(struct inode *, daddr_t, daddr_t, daddr_t, int, long *); /* * Update the access, modified, and inode change times as specified by the * IN_ACCESS, IN_UPDATE, and IN_CHANGE flags respectively. The IN_MODIFIED * flag is used to specify that the inode needs to be updated but that the * times have already been set. The IN_LAZYMOD flag is used to specify * that the inode needs to be updated at some point, by reclaim if not * in the course of other changes; this is used to defer writes just to * update device timestamps. If waitfor is set, then wait for the disk * write of the inode to complete. */ int ffs_update(struct inode *ip, int waitfor) { struct vnode *vp; struct fs *fs; struct buf *bp; int error; vp = ITOV(ip); ufs_itimes(vp); if ((ip->i_flag & IN_MODIFIED) == 0 && waitfor == 0) return (0); ip->i_flag &= ~(IN_MODIFIED | IN_LAZYMOD); fs = ip->i_fs; /* * Ensure that uid and gid are correct. This is a temporary * fix until fsck has been changed to do the update. */ if (fs->fs_magic == FS_UFS1_MAGIC && fs->fs_inodefmt < FS_44INODEFMT) { ip->i_din1->di_ouid = ip->i_ffs1_uid; ip->i_din1->di_ogid = ip->i_ffs1_gid; } error = bread(ip->i_devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)), (int)fs->fs_bsize, &bp); if (error) { brelse(bp); return (error); } if (ip->i_effnlink != DIP(ip, nlink)) panic("ffs_update: bad link cnt"); #ifdef FFS2 if (ip->i_ump->um_fstype == UM_UFS2) *((struct ufs2_dinode *)bp->b_data + ino_to_fsbo(fs, ip->i_number)) = *ip->i_din2; else #endif *((struct ufs1_dinode *)bp->b_data + ino_to_fsbo(fs, ip->i_number)) = *ip->i_din1; if (waitfor && !DOINGASYNC(vp)) { return (bwrite(bp)); } else { bdwrite(bp); return (0); } } #define SINGLE 0 /* index of single indirect block */ #define DOUBLE 1 /* index of double indirect block */ #define TRIPLE 2 /* index of triple indirect block */ /* * Truncate the inode oip to at most length size, freeing the * disk blocks. */ int ffs_truncate(struct inode *oip, off_t length, int flags, struct ucred *cred) { struct vnode *ovp; daddr_t lastblock; daddr_t bn, lbn, lastiblock[NIADDR], indir_lbn[NIADDR]; daddr_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR]; struct fs *fs; struct buf *bp; int offset, size, level; long count, nblocks, vflags, blocksreleased = 0; int i, aflags, error, allerror; off_t osize; if (length < 0) return (EINVAL); ovp = ITOV(oip); if (ovp->v_type != VREG && ovp->v_type != VDIR && ovp->v_type != VLNK) return (0); if (DIP(oip, size) == length) return (0); if (ovp->v_type == VLNK && DIP(oip, size) < oip->i_ump->um_maxsymlinklen) { #ifdef DIAGNOSTIC if (length != 0) panic("ffs_truncate: partial truncate of symlink"); #endif memset(SHORTLINK(oip), 0, (size_t) DIP(oip, size)); DIP_ASSIGN(oip, size, 0); oip->i_flag |= IN_CHANGE | IN_UPDATE; return (UFS_UPDATE(oip, 1)); } if ((error = getinoquota(oip)) != 0) return (error); fs = oip->i_fs; if (length > fs->fs_maxfilesize) return (EFBIG); uvm_vnp_setsize(ovp, length); oip->i_ci.ci_lasta = oip->i_ci.ci_clen = oip->i_ci.ci_cstart = oip->i_ci.ci_lastw = 0; osize = DIP(oip, size); /* * Lengthen the size of the file. We must ensure that the * last byte of the file is allocated. Since the smallest * value of osize is 0, length will be at least 1. */ if (osize < length) { aflags = B_CLRBUF; if (flags & IO_SYNC) aflags |= B_SYNC; error = UFS_BUF_ALLOC(oip, length - 1, 1, cred, aflags, &bp); if (error) return (error); DIP_ASSIGN(oip, size, length); uvm_vnp_setsize(ovp, length); (void) uvm_vnp_uncache(ovp); if (aflags & B_SYNC) bwrite(bp); else bawrite(bp); oip->i_flag |= IN_CHANGE | IN_UPDATE; return (UFS_UPDATE(oip, 1)); } uvm_vnp_setsize(ovp, length); /* * Shorten the size of the file. If the file is not being * truncated to a block boundary, the contents of the * partial block following the end of the file must be * zero'ed in case it ever becomes accessible again because * of subsequent file growth. Directories however are not * zero'ed as they should grow back initialized to empty. */ offset = blkoff(fs, length); if (offset == 0) { DIP_ASSIGN(oip, size, length); } else { lbn = lblkno(fs, length); aflags = B_CLRBUF; if (flags & IO_SYNC) aflags |= B_SYNC; error = UFS_BUF_ALLOC(oip, length - 1, 1, cred, aflags, &bp); if (error) return (error); DIP_ASSIGN(oip, size, length); size = blksize(fs, oip, lbn); (void) uvm_vnp_uncache(ovp); if (ovp->v_type != VDIR) memset(bp->b_data + offset, 0, size - offset); buf_adjcnt(bp, size); if (aflags & B_SYNC) bwrite(bp); else bawrite(bp); } /* * Calculate index into inode's block list of * last direct and indirect blocks (if any) * which we want to keep. Lastblock is -1 when * the file is truncated to 0. */ lastblock = lblkno(fs, length + fs->fs_bsize - 1) - 1; lastiblock[SINGLE] = lastblock - NDADDR; lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR(fs); lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR(fs) * NINDIR(fs); nblocks = btodb(fs->fs_bsize); /* * Update file and block pointers on disk before we start freeing * blocks. If we crash before free'ing blocks below, the blocks * will be returned to the free list. lastiblock values are also * normalized to -1 for calls to ffs_indirtrunc below. */ for (level = TRIPLE; level >= SINGLE; level--) { oldblks[NDADDR + level] = DIP(oip, ib[level]); if (lastiblock[level] < 0) { DIP_ASSIGN(oip, ib[level], 0); lastiblock[level] = -1; } } for (i = 0; i < NDADDR; i++) { oldblks[i] = DIP(oip, db[i]); if (i > lastblock) DIP_ASSIGN(oip, db[i], 0); } oip->i_flag |= IN_CHANGE | IN_UPDATE; if ((error = UFS_UPDATE(oip, 1)) != 0) allerror = error; /* * Having written the new inode to disk, save its new configuration * and put back the old block pointers long enough to process them. * Note that we save the new block configuration so we can check it * when we are done. */ for (i = 0; i < NDADDR; i++) { newblks[i] = DIP(oip, db[i]); DIP_ASSIGN(oip, db[i], oldblks[i]); } for (i = 0; i < NIADDR; i++) { newblks[NDADDR + i] = DIP(oip, ib[i]); DIP_ASSIGN(oip, ib[i], oldblks[NDADDR + i]); } DIP_ASSIGN(oip, size, osize); vflags = ((length > 0) ? V_SAVE : 0) | V_SAVEMETA; allerror = vinvalbuf(ovp, vflags, cred, curproc, 0, INFSLP); /* * Indirect blocks first. */ indir_lbn[SINGLE] = -NDADDR; indir_lbn[DOUBLE] = indir_lbn[SINGLE] - NINDIR(fs) - 1; indir_lbn[TRIPLE] = indir_lbn[DOUBLE] - NINDIR(fs) * NINDIR(fs) - 1; for (level = TRIPLE; level >= SINGLE; level--) { bn = DIP(oip, ib[level]); if (bn != 0) { error = ffs_indirtrunc(oip, indir_lbn[level], fsbtodb(fs, bn), lastiblock[level], level, &count); if (error) allerror = error; blocksreleased += count; if (lastiblock[level] < 0) { DIP_ASSIGN(oip, ib[level], 0); ffs_blkfree(oip, bn, fs->fs_bsize); blocksreleased += nblocks; } } if (lastiblock[level] >= 0) goto done; } /* * All whole direct blocks or frags. */ for (i = NDADDR - 1; i > lastblock; i--) { long bsize; bn = DIP(oip, db[i]); if (bn == 0) continue; DIP_ASSIGN(oip, db[i], 0); bsize = blksize(fs, oip, i); ffs_blkfree(oip, bn, bsize); blocksreleased += btodb(bsize); } if (lastblock < 0) goto done; /* * Finally, look for a change in size of the * last direct block; release any frags. */ bn = DIP(oip, db[lastblock]); if (bn != 0) { long oldspace, newspace; /* * Calculate amount of space we're giving * back as old block size minus new block size. */ oldspace = blksize(fs, oip, lastblock); DIP_ASSIGN(oip, size, length); newspace = blksize(fs, oip, lastblock); if (newspace == 0) panic("ffs_truncate: newspace"); if (oldspace - newspace > 0) { /* * Block number of space to be free'd is * the old block # plus the number of frags * required for the storage we're keeping. */ bn += numfrags(fs, newspace); ffs_blkfree(oip, bn, oldspace - newspace); blocksreleased += btodb(oldspace - newspace); } } done: #ifdef DIAGNOSTIC for (level = SINGLE; level <= TRIPLE; level++) if (newblks[NDADDR + level] != DIP(oip, ib[level])) panic("ffs_truncate1"); for (i = 0; i < NDADDR; i++) if (newblks[i] != DIP(oip, db[i])) panic("ffs_truncate2"); #endif /* DIAGNOSTIC */ /* * Put back the real size. */ DIP_ASSIGN(oip, size, length); if (DIP(oip, blocks) >= blocksreleased) DIP_ADD(oip, blocks, -blocksreleased); else /* sanity */ DIP_ASSIGN(oip, blocks, 0); oip->i_flag |= IN_CHANGE; (void)ufs_quota_free_blocks(oip, blocksreleased, NOCRED); return (allerror); } #ifdef FFS2 #define BAP(ip, i) (((ip)->i_ump->um_fstype == UM_UFS2) ? bap2[i] : bap1[i]) #define BAP_ASSIGN(ip, i, value) \ do { \ if ((ip)->i_ump->um_fstype == UM_UFS2) \ bap2[i] = (value); \ else \ bap1[i] = (value); \ } while (0) #else #define BAP(ip, i) bap1[i] #define BAP_ASSIGN(ip, i, value) do { bap1[i] = (value); } while (0) #endif /* FFS2 */ /* * Release blocks associated with the inode ip and stored in the indirect * block bn. Blocks are free'd in LIFO order up to (but not including) * lastbn. If level is greater than SINGLE, the block is an indirect block * and recursive calls to indirtrunc must be used to cleanse other indirect * blocks. * * NB: triple indirect blocks are untested. */ int ffs_indirtrunc(struct inode *ip, daddr_t lbn, daddr_t dbn, daddr_t lastbn, int level, long *countp) { int i; struct buf *bp; struct fs *fs = ip->i_fs; struct vnode *vp; void *copy = NULL; daddr_t nb, nlbn, last; long blkcount, factor; int nblocks, blocksreleased = 0; int error = 0, allerror = 0; int32_t *bap1 = NULL; #ifdef FFS2 int64_t *bap2 = NULL; #endif /* * Calculate index in current block of last * block to be kept. -1 indicates the entire * block so we need not calculate the index. */ factor = 1; for (i = SINGLE; i < level; i++) factor *= NINDIR(fs); last = lastbn; if (lastbn > 0) last /= factor; nblocks = btodb(fs->fs_bsize); /* * Get buffer of block pointers, zero those entries corresponding * to blocks to be free'd, and update on disk copy first. Since * double(triple) indirect before single(double) indirect, calls * to bmap on these blocks will fail. However, we already have * the on disk address, so we have to set the b_blkno field * explicitly instead of letting bread do everything for us. */ vp = ITOV(ip); bp = getblk(vp, lbn, (int)fs->fs_bsize, 0, INFSLP); if (!(bp->b_flags & (B_DONE | B_DELWRI))) { curproc->p_ru.ru_inblock++; /* pay for read */ bcstats.pendingreads++; bcstats.numreads++; bp->b_flags |= B_READ; if (bp->b_bcount > bp->b_bufsize) panic("ffs_indirtrunc: bad buffer size"); bp->b_blkno = dbn; VOP_STRATEGY(bp->b_vp, bp); error = biowait(bp); } if (error) { brelse(bp); *countp = 0; return (error); } #ifdef FFS2 if (ip->i_ump->um_fstype == UM_UFS2) bap2 = (int64_t *)bp->b_data; else #endif bap1 = (int32_t *)bp->b_data; if (lastbn != -1) { copy = malloc(fs->fs_bsize, M_TEMP, M_WAITOK); memcpy(copy, bp->b_data, fs->fs_bsize); for (i = last + 1; i < NINDIR(fs); i++) BAP_ASSIGN(ip, i, 0); if (!DOINGASYNC(vp)) { error = bwrite(bp); if (error) allerror = error; } else { bawrite(bp); } #ifdef FFS2 if (ip->i_ump->um_fstype == UM_UFS2) bap2 = (int64_t *)copy; else #endif bap1 = (int32_t *)copy; } /* * Recursively free totally unused blocks. */ for (i = NINDIR(fs) - 1, nlbn = lbn + 1 - i * factor; i > last; i--, nlbn += factor) { nb = BAP(ip, i); if (nb == 0) continue; if (level > SINGLE) { error = ffs_indirtrunc(ip, nlbn, fsbtodb(fs, nb), -1, level - 1, &blkcount); if (error) allerror = error; blocksreleased += blkcount; } ffs_blkfree(ip, nb, fs->fs_bsize); blocksreleased += nblocks; } /* * Recursively free last partial block. */ if (level > SINGLE && lastbn >= 0) { last = lastbn % factor; nb = BAP(ip, i); if (nb != 0) { error = ffs_indirtrunc(ip, nlbn, fsbtodb(fs, nb), last, level - 1, &blkcount); if (error) allerror = error; blocksreleased += blkcount; } } if (copy != NULL) { free(copy, M_TEMP, fs->fs_bsize); } else { bp->b_flags |= B_INVAL; brelse(bp); } *countp = blocksreleased; return (allerror); }
8 2 1 2 3 234 234 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 /* $OpenBSD: ip_carp.c,v 1.361 2024/02/13 12:22:09 bluhm Exp $ */ /* * Copyright (c) 2002 Michael Shalayeff. All rights reserved. * Copyright (c) 2003 Ryan McBride. All rights reserved. * Copyright (c) 2006-2008 Marco Pfatschbacher. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /* * TODO: * - iface reconfigure * - support for hardware checksum calculations; * */ #include "ether.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/timeout.h> #include <sys/ioctl.h> #include <sys/errno.h> #include <sys/device.h> #include <sys/kernel.h> #include <sys/sysctl.h> #include <sys/syslog.h> #include <sys/refcnt.h> #include <net/if.h> #include <net/if_var.h> #include <net/if_types.h> #include <net/netisr.h> #include <net/route.h> #include <crypto/sha1.h> #include <netinet/in.h> #include <netinet/in_var.h> #include <netinet/ip.h> #include <netinet/ip_var.h> #include <netinet/if_ether.h> #include <netinet/ip_ipsp.h> #include <net/if_dl.h> #ifdef INET6 #include <netinet6/in6_var.h> #include <netinet/icmp6.h> #include <netinet/ip6.h> #include <netinet6/ip6_var.h> #include <netinet6/nd6.h> #include <netinet6/in6_ifattach.h> #endif #include "bpfilter.h" #if NBPFILTER > 0 #include <net/bpf.h> #endif #include "vlan.h" #if NVLAN > 0 #include <net/if_vlan_var.h> #endif #include <netinet/ip_carp.h> struct carp_mc_entry { LIST_ENTRY(carp_mc_entry) mc_entries; union { struct ether_multi *mcu_enm; } mc_u; struct sockaddr_storage mc_addr; }; #define mc_enm mc_u.mcu_enm enum { HMAC_ORIG=0, HMAC_NOV6LL=1, HMAC_MAX=2 }; struct carp_vhost_entry { SRPL_ENTRY(carp_vhost_entry) vhost_entries; struct refcnt vhost_refcnt; struct carp_softc *parent_sc; int vhe_leader; int vhid; int advskew; enum { INIT = 0, BACKUP, MASTER } state; struct timeout ad_tmo; /* advertisement timeout */ struct timeout md_tmo; /* master down timeout */ struct timeout md6_tmo; /* master down timeout */ u_int64_t vhe_replay_cookie; /* authentication */ #define CARP_HMAC_PAD 64 unsigned char vhe_pad[CARP_HMAC_PAD]; SHA1_CTX vhe_sha1[HMAC_MAX]; u_int8_t vhe_enaddr[ETHER_ADDR_LEN]; }; void carp_vh_ref(void *, void *); void carp_vh_unref(void *, void *); struct srpl_rc carp_vh_rc = SRPL_RC_INITIALIZER(carp_vh_ref, carp_vh_unref, NULL); struct carp_softc { struct arpcom sc_ac; #define sc_if sc_ac.ac_if #define sc_carpdevidx sc_ac.ac_if.if_carpdevidx struct task sc_atask; struct task sc_ltask; struct task sc_dtask; struct ip_moptions sc_imo; #ifdef INET6 struct ip6_moptions sc_im6o; #endif /* INET6 */ SRPL_ENTRY(carp_softc) sc_list; struct refcnt sc_refcnt; int sc_suppress; int sc_bow_out; int sc_demote_cnt; int sc_sendad_errors; #define CARP_SENDAD_MAX_ERRORS(sc) (3 * (sc)->sc_vhe_count) int sc_sendad_success; #define CARP_SENDAD_MIN_SUCCESS(sc) (3 * (sc)->sc_vhe_count) char sc_curlladdr[ETHER_ADDR_LEN]; SRPL_HEAD(, carp_vhost_entry) carp_vhosts; int sc_vhe_count; u_int8_t sc_vhids[CARP_MAXNODES]; u_int8_t sc_advskews[CARP_MAXNODES]; u_int8_t sc_balancing; int sc_naddrs; int sc_naddrs6; int sc_advbase; /* seconds */ /* authentication */ unsigned char sc_key[CARP_KEY_LEN]; u_int32_t sc_hashkey[2]; u_int32_t sc_lsmask; /* load sharing mask */ int sc_lscount; /* # load sharing interfaces (max 32) */ int sc_delayed_arp; /* delayed ARP request countdown */ int sc_realmac; /* using real mac */ struct in_addr sc_peer; LIST_HEAD(__carp_mchead, carp_mc_entry) carp_mc_listhead; struct carp_vhost_entry *cur_vhe; /* current active vhe */ }; void carp_sc_ref(void *, void *); void carp_sc_unref(void *, void *); struct srpl_rc carp_sc_rc = SRPL_RC_INITIALIZER(carp_sc_ref, carp_sc_unref, NULL); int carp_opts[CARPCTL_MAXID] = { 0, 1, 0, LOG_CRIT }; /* XXX for now */ struct cpumem *carpcounters; int carp_send_all_recur = 0; #define CARP_LOG(l, sc, s) \ do { \ if (carp_opts[CARPCTL_LOG] >= l) { \ if (sc) \ log(l, "%s: ", \ (sc)->sc_if.if_xname); \ else \ log(l, "carp: "); \ addlog s; \ addlog("\n"); \ } \ } while (0) void carp_hmac_prepare(struct carp_softc *); void carp_hmac_prepare_ctx(struct carp_vhost_entry *, u_int8_t); void carp_hmac_generate(struct carp_vhost_entry *, u_int32_t *, unsigned char *, u_int8_t); int carp_hmac_verify(struct carp_vhost_entry *, u_int32_t *, unsigned char *); void carp_proto_input_c(struct ifnet *, struct mbuf *, struct carp_header *, int, sa_family_t); int carp_proto_input_if(struct ifnet *, struct mbuf **, int *, int); #ifdef INET6 int carp6_proto_input_if(struct ifnet *, struct mbuf **, int *, int); #endif void carpattach(int); void carpdetach(void *); void carp_prepare_ad(struct mbuf *, struct carp_vhost_entry *, struct carp_header *); void carp_send_ad_all(void); void carp_vhe_send_ad_all(struct carp_softc *); void carp_timer_ad(void *); void carp_send_ad(struct carp_vhost_entry *); void carp_send_arp(struct carp_softc *); void carp_timer_down(void *); void carp_master_down(struct carp_vhost_entry *); int carp_ioctl(struct ifnet *, u_long, caddr_t); int carp_vhids_ioctl(struct carp_softc *, struct carpreq *); int carp_check_dup_vhids(struct carp_softc *, struct srpl *, struct carpreq *); void carp_ifgroup_ioctl(struct ifnet *, u_long, caddr_t); void carp_ifgattr_ioctl(struct ifnet *, u_long, caddr_t); void carp_start(struct ifnet *); int carp_enqueue(struct ifnet *, struct mbuf *); void carp_transmit(struct carp_softc *, struct ifnet *, struct mbuf *); void carp_setrun_all(struct carp_softc *, sa_family_t); void carp_setrun(struct carp_vhost_entry *, sa_family_t); void carp_set_state_all(struct carp_softc *, int); void carp_set_state(struct carp_vhost_entry *, int); void carp_multicast_cleanup(struct carp_softc *); int carp_set_ifp(struct carp_softc *, struct ifnet *); void carp_set_enaddr(struct carp_softc *); void carp_set_vhe_enaddr(struct carp_vhost_entry *); void carp_addr_updated(void *); int carp_set_addr(struct carp_softc *, struct sockaddr_in *); int carp_join_multicast(struct carp_softc *); #ifdef INET6 void carp_send_na(struct carp_softc *); int carp_set_addr6(struct carp_softc *, struct sockaddr_in6 *); int carp_join_multicast6(struct carp_softc *); #endif int carp_clone_create(struct if_clone *, int); int carp_clone_destroy(struct ifnet *); int carp_ether_addmulti(struct carp_softc *, struct ifreq *); int carp_ether_delmulti(struct carp_softc *, struct ifreq *); void carp_ether_purgemulti(struct carp_softc *); int carp_group_demote_count(struct carp_softc *); void carp_update_lsmask(struct carp_softc *); int carp_new_vhost(struct carp_softc *, int, int); void carp_destroy_vhosts(struct carp_softc *); void carp_del_all_timeouts(struct carp_softc *); int carp_vhe_match(struct carp_softc *, uint64_t); struct if_clone carp_cloner = IF_CLONE_INITIALIZER("carp", carp_clone_create, carp_clone_destroy); #define carp_cksum(_m, _l) ((u_int16_t)in_cksum((_m), (_l))) #define CARP_IFQ_PRIO 6 void carp_hmac_prepare(struct carp_softc *sc) { struct carp_vhost_entry *vhe; u_int8_t i; KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */ SRPL_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) { for (i = 0; i < HMAC_MAX; i++) { carp_hmac_prepare_ctx(vhe, i); } } } void carp_hmac_prepare_ctx(struct carp_vhost_entry *vhe, u_int8_t ctx) { struct carp_softc *sc = vhe->parent_sc; u_int8_t version = CARP_VERSION, type = CARP_ADVERTISEMENT; u_int8_t vhid = vhe->vhid & 0xff; SHA1_CTX sha1ctx; u_int32_t kmd[5]; struct ifaddr *ifa; int i, found; struct in_addr last, cur, in; #ifdef INET6 struct in6_addr last6, cur6, in6; #endif /* INET6 */ /* compute ipad from key */ memset(vhe->vhe_pad, 0, sizeof(vhe->vhe_pad)); bcopy(sc->sc_key, vhe->vhe_pad, sizeof(sc->sc_key)); for (i = 0; i < sizeof(vhe->vhe_pad); i++) vhe->vhe_pad[i] ^= 0x36; /* precompute first part of inner hash */ SHA1Init(&vhe->vhe_sha1[ctx]); SHA1Update(&vhe->vhe_sha1[ctx], vhe->vhe_pad, sizeof(vhe->vhe_pad)); SHA1Update(&vhe->vhe_sha1[ctx], (void *)&version, sizeof(version)); SHA1Update(&vhe->vhe_sha1[ctx], (void *)&type, sizeof(type)); /* generate a key for the arpbalance hash, before the vhid is hashed */ if (vhe->vhe_leader) { bcopy(&vhe->vhe_sha1[ctx], &sha1ctx, sizeof(sha1ctx)); SHA1Final((unsigned char *)kmd, &sha1ctx); sc->sc_hashkey[0] = kmd[0] ^ kmd[1]; sc->sc_hashkey[1] = kmd[2] ^ kmd[3]; } /* the rest of the precomputation */ if (!sc->sc_realmac && vhe->vhe_leader && memcmp(sc->sc_ac.ac_enaddr, vhe->vhe_enaddr, ETHER_ADDR_LEN) != 0) SHA1Update(&vhe->vhe_sha1[ctx], sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN); SHA1Update(&vhe->vhe_sha1[ctx], (void *)&vhid, sizeof(vhid)); /* Hash the addresses from smallest to largest, not interface order */ cur.s_addr = 0; do { found = 0; last = cur; cur.s_addr = 0xffffffff; TAILQ_FOREACH(ifa, &sc->sc_if.if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET) continue; in.s_addr = ifatoia(ifa)->ia_addr.sin_addr.s_addr; if (ntohl(in.s_addr) > ntohl(last.s_addr) && ntohl(in.s_addr) < ntohl(cur.s_addr)) { cur.s_addr = in.s_addr; found++; } } if (found) SHA1Update(&vhe->vhe_sha1[ctx], (void *)&cur, sizeof(cur)); } while (found); #ifdef INET6 memset(&cur6, 0x00, sizeof(cur6)); do { found = 0; last6 = cur6; memset(&cur6, 0xff, sizeof(cur6)); TAILQ_FOREACH(ifa, &sc->sc_if.if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; in6 = ifatoia6(ifa)->ia_addr.sin6_addr; if (IN6_IS_SCOPE_EMBED(&in6)) { if (ctx == HMAC_NOV6LL) continue; in6.s6_addr16[1] = 0; } if (memcmp(&in6, &last6, sizeof(in6)) > 0 && memcmp(&in6, &cur6, sizeof(in6)) < 0) { cur6 = in6; found++; } } if (found) SHA1Update(&vhe->vhe_sha1[ctx], (void *)&cur6, sizeof(cur6)); } while (found); #endif /* INET6 */ /* convert ipad to opad */ for (i = 0; i < sizeof(vhe->vhe_pad); i++) vhe->vhe_pad[i] ^= 0x36 ^ 0x5c; } void carp_hmac_generate(struct carp_vhost_entry *vhe, u_int32_t counter[2], unsigned char md[20], u_int8_t ctx) { SHA1_CTX sha1ctx; /* fetch first half of inner hash */ bcopy(&vhe->vhe_sha1[ctx], &sha1ctx, sizeof(sha1ctx)); SHA1Update(&sha1ctx, (void *)counter, sizeof(vhe->vhe_replay_cookie)); SHA1Final(md, &sha1ctx); /* outer hash */ SHA1Init(&sha1ctx); SHA1Update(&sha1ctx, vhe->vhe_pad, sizeof(vhe->vhe_pad)); SHA1Update(&sha1ctx, md, 20); SHA1Final(md, &sha1ctx); } int carp_hmac_verify(struct carp_vhost_entry *vhe, u_int32_t counter[2], unsigned char md[20]) { unsigned char md2[20]; u_int8_t i; for (i = 0; i < HMAC_MAX; i++) { carp_hmac_generate(vhe, counter, md2, i); if (!timingsafe_bcmp(md, md2, sizeof(md2))) return (0); } return (1); } int carp_proto_input(struct mbuf **mp, int *offp, int proto, int af) { struct ifnet *ifp; ifp = if_get((*mp)->m_pkthdr.ph_ifidx); if (ifp == NULL) { m_freemp(mp); return IPPROTO_DONE; } proto = carp_proto_input_if(ifp, mp, offp, proto); if_put(ifp); return proto; } /* * process input packet. * we have rearranged checks order compared to the rfc, * but it seems more efficient this way or not possible otherwise. */ int carp_proto_input_if(struct ifnet *ifp, struct mbuf **mp, int *offp, int proto) { struct mbuf *m = *mp; struct ip *ip = mtod(m, struct ip *); struct carp_softc *sc = NULL; struct carp_header *ch; int iplen, len, ismulti; carpstat_inc(carps_ipackets); if (!carp_opts[CARPCTL_ALLOW]) { m_freem(m); return IPPROTO_DONE; } ismulti = IN_MULTICAST(ip->ip_dst.s_addr); /* check if received on a valid carp interface */ switch (ifp->if_type) { case IFT_CARP: break; case IFT_ETHER: if (ismulti || !SRPL_EMPTY_LOCKED(&ifp->if_carp)) break; /* FALLTHROUGH */ default: carpstat_inc(carps_badif); CARP_LOG(LOG_INFO, sc, ("packet received on non-carp interface: %s", ifp->if_xname)); m_freem(m); return IPPROTO_DONE; } /* verify that the IP TTL is 255. */ if (ip->ip_ttl != CARP_DFLTTL) { carpstat_inc(carps_badttl); CARP_LOG(LOG_NOTICE, sc, ("received ttl %d != %d on %s", ip->ip_ttl, CARP_DFLTTL, ifp->if_xname)); m_freem(m); return IPPROTO_DONE; } /* * verify that the received packet length is * equal to the CARP header */ iplen = ip->ip_hl << 2; len = iplen + sizeof(*ch); if (len > m->m_pkthdr.len) { carpstat_inc(carps_badlen); CARP_LOG(LOG_INFO, sc, ("packet too short %d on %s", m->m_pkthdr.len, ifp->if_xname)); m_freem(m); return IPPROTO_DONE; } if ((m = *mp = m_pullup(m, len)) == NULL) { carpstat_inc(carps_hdrops); return IPPROTO_DONE; } ip = mtod(m, struct ip *); ch = (struct carp_header *)(mtod(m, caddr_t) + iplen); /* verify the CARP checksum */ m->m_data += iplen; if (carp_cksum(m, len - iplen)) { carpstat_inc(carps_badsum); CARP_LOG(LOG_INFO, sc, ("checksum failed on %s", ifp->if_xname)); m_freem(m); return IPPROTO_DONE; } m->m_data -= iplen; KERNEL_LOCK(); carp_proto_input_c(ifp, m, ch, ismulti, AF_INET); KERNEL_UNLOCK(); return IPPROTO_DONE; } #ifdef INET6 int carp6_proto_input(struct mbuf **mp, int *offp, int proto, int af) { struct ifnet *ifp; ifp = if_get((*mp)->m_pkthdr.ph_ifidx); if (ifp == NULL) { m_freemp(mp); return IPPROTO_DONE; } proto = carp6_proto_input_if(ifp, mp, offp, proto); if_put(ifp); return proto; } int carp6_proto_input_if(struct ifnet *ifp, struct mbuf **mp, int *offp, int proto) { struct mbuf *m = *mp; struct carp_softc *sc = NULL; struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); struct carp_header *ch; u_int len; carpstat_inc(carps_ipackets6); if (!carp_opts[CARPCTL_ALLOW]) { m_freem(m); return IPPROTO_DONE; } /* check if received on a valid carp interface */ if (ifp->if_type != IFT_CARP) { carpstat_inc(carps_badif); CARP_LOG(LOG_INFO, sc, ("packet received on non-carp interface: %s", ifp->if_xname)); m_freem(m); return IPPROTO_DONE; } /* verify that the IP TTL is 255 */ if (ip6->ip6_hlim != CARP_DFLTTL) { carpstat_inc(carps_badttl); CARP_LOG(LOG_NOTICE, sc, ("received ttl %d != %d on %s", ip6->ip6_hlim, CARP_DFLTTL, ifp->if_xname)); m_freem(m); return IPPROTO_DONE; } /* verify that we have a complete carp packet */ len = m->m_len; if ((m = *mp = m_pullup(m, *offp + sizeof(*ch))) == NULL) { carpstat_inc(carps_badlen); CARP_LOG(LOG_INFO, sc, ("packet size %u too small", len)); return IPPROTO_DONE; } ch = (struct carp_header *)(mtod(m, caddr_t) + *offp); /* verify the CARP checksum */ m->m_data += *offp; if (carp_cksum(m, sizeof(*ch))) { carpstat_inc(carps_badsum); CARP_LOG(LOG_INFO, sc, ("checksum failed, on %s", ifp->if_xname)); m_freem(m); return IPPROTO_DONE; } m->m_data -= *offp; KERNEL_LOCK(); carp_proto_input_c(ifp, m, ch, 1, AF_INET6); KERNEL_UNLOCK(); return IPPROTO_DONE; } #endif /* INET6 */ void carp_proto_input_c(struct ifnet *ifp, struct mbuf *m, struct carp_header *ch, int ismulti, sa_family_t af) { struct carp_softc *sc; struct ifnet *ifp0; struct carp_vhost_entry *vhe; struct timeval sc_tv, ch_tv; struct srpl *cif; KERNEL_ASSERT_LOCKED(); /* touching if_carp + carp_vhosts */ ifp0 = if_get(ifp->if_carpdevidx); if (ifp->if_type == IFT_CARP) { /* * If the parent of this carp(4) got destroyed while * `m' was being processed, silently drop it. */ if (ifp0 == NULL) goto rele; cif = &ifp0->if_carp; } else cif = &ifp->if_carp; SRPL_FOREACH_LOCKED(sc, cif, sc_list) { if (af == AF_INET && ismulti != IN_MULTICAST(sc->sc_peer.s_addr)) continue; SRPL_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) { if (vhe->vhid == ch->carp_vhid) goto found; } } found: if (!sc || (sc->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { carpstat_inc(carps_badvhid); goto rele; } getmicrotime(&sc->sc_if.if_lastchange); /* verify the CARP version. */ if (ch->carp_version != CARP_VERSION) { carpstat_inc(carps_badver); sc->sc_if.if_ierrors++; CARP_LOG(LOG_NOTICE, sc, ("invalid version %d != %d", ch->carp_version, CARP_VERSION)); goto rele; } /* verify the hash */ if (carp_hmac_verify(vhe, ch->carp_counter, ch->carp_md)) { carpstat_inc(carps_badauth); sc->sc_if.if_ierrors++; CARP_LOG(LOG_INFO, sc, ("incorrect hash")); goto rele; } if (!memcmp(&vhe->vhe_replay_cookie, ch->carp_counter, sizeof(ch->carp_counter))) { struct ifnet *ifp2; ifp2 = if_get(sc->sc_carpdevidx); /* Do not log duplicates from non simplex interfaces */ if (ifp2 && ifp2->if_flags & IFF_SIMPLEX) { carpstat_inc(carps_badauth); sc->sc_if.if_ierrors++; CARP_LOG(LOG_WARNING, sc, ("replay or network loop detected")); } if_put(ifp2); goto rele; } sc_tv.tv_sec = sc->sc_advbase; sc_tv.tv_usec = vhe->advskew * 1000000 / 256; ch_tv.tv_sec = ch->carp_advbase; ch_tv.tv_usec = ch->carp_advskew * 1000000 / 256; switch (vhe->state) { case INIT: break; case MASTER: /* * If we receive an advertisement from a master who's going to * be more frequent than us, and whose demote count is not higher * than ours, go into BACKUP state. If his demote count is lower, * also go into BACKUP. */ if (((timercmp(&sc_tv, &ch_tv, >) || timercmp(&sc_tv, &ch_tv, ==)) && (ch->carp_demote <= carp_group_demote_count(sc))) || ch->carp_demote < carp_group_demote_count(sc)) { timeout_del(&vhe->ad_tmo); carp_set_state(vhe, BACKUP); carp_setrun(vhe, 0); } break; case BACKUP: /* * If we're pre-empting masters who advertise slower than us, * and do not have a better demote count, treat them as down. * */ if (carp_opts[CARPCTL_PREEMPT] && timercmp(&sc_tv, &ch_tv, <) && ch->carp_demote >= carp_group_demote_count(sc)) { carp_master_down(vhe); break; } /* * Take over masters advertising with a higher demote count, * regardless of CARPCTL_PREEMPT. */ if (ch->carp_demote > carp_group_demote_count(sc)) { carp_master_down(vhe); break; } /* * If the master is going to advertise at such a low frequency * that he's guaranteed to time out, we'd might as well just * treat him as timed out now. */ sc_tv.tv_sec = sc->sc_advbase * 3; if (sc->sc_advbase && timercmp(&sc_tv, &ch_tv, <)) { carp_master_down(vhe); break; } /* * Otherwise, we reset the counter and wait for the next * advertisement. */ carp_setrun(vhe, af); break; } rele: if_put(ifp0); m_freem(m); return; } int carp_sysctl_carpstat(void *oldp, size_t *oldlenp, void *newp) { struct carpstats carpstat; CTASSERT(sizeof(carpstat) == (carps_ncounters * sizeof(uint64_t))); memset(&carpstat, 0, sizeof carpstat); counters_read(carpcounters, (uint64_t *)&carpstat, carps_ncounters, NULL); return (sysctl_rdstruct(oldp, oldlenp, newp, &carpstat, sizeof(carpstat))); } int carp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int error; /* All sysctl names at this level are terminal. */ if (namelen != 1) return (ENOTDIR); switch (name[0]) { case CARPCTL_STATS: return (carp_sysctl_carpstat(oldp, oldlenp, newp)); default: if (name[0] <= 0 || name[0] >= CARPCTL_MAXID) return (ENOPROTOOPT); NET_LOCK(); error = sysctl_int(oldp, oldlenp, newp, newlen, &carp_opts[name[0]]); NET_UNLOCK(); return (error); } } /* * Interface side of the CARP implementation. */ void carpattach(int n) { if_creategroup("carp"); /* keep around even if empty */ if_clone_attach(&carp_cloner); carpcounters = counters_alloc(carps_ncounters); } int carp_clone_create(struct if_clone *ifc, int unit) { struct carp_softc *sc; struct ifnet *ifp; sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); refcnt_init(&sc->sc_refcnt); SRPL_INIT(&sc->carp_vhosts); sc->sc_vhe_count = 0; if (carp_new_vhost(sc, 0, 0)) { free(sc, M_DEVBUF, sizeof(*sc)); return (ENOMEM); } task_set(&sc->sc_atask, carp_addr_updated, sc); task_set(&sc->sc_ltask, carp_carpdev_state, sc); task_set(&sc->sc_dtask, carpdetach, sc); sc->sc_suppress = 0; sc->sc_advbase = CARP_DFLTINTV; sc->sc_naddrs = sc->sc_naddrs6 = 0; #ifdef INET6 sc->sc_im6o.im6o_hlim = CARP_DFLTTL; #endif /* INET6 */ sc->sc_imo.imo_membership = mallocarray(IP_MIN_MEMBERSHIPS, sizeof(struct in_multi *), M_IPMOPTS, M_WAITOK|M_ZERO); sc->sc_imo.imo_max_memberships = IP_MIN_MEMBERSHIPS; LIST_INIT(&sc->carp_mc_listhead); ifp = &sc->sc_if; ifp->if_softc = sc; snprintf(ifp->if_xname, sizeof ifp->if_xname, "%s%d", ifc->ifc_name, unit); ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = carp_ioctl; ifp->if_start = carp_start; ifp->if_enqueue = carp_enqueue; ifp->if_xflags = IFXF_CLONED; if_counters_alloc(ifp); if_attach(ifp); ether_ifattach(ifp); ifp->if_type = IFT_CARP; ifp->if_sadl->sdl_type = IFT_CARP; ifp->if_output = carp_output; ifp->if_priority = IF_CARP_DEFAULT_PRIORITY; ifp->if_link_state = LINK_STATE_INVALID; /* Hook carp_addr_updated to cope with address and route changes. */ if_addrhook_add(&sc->sc_if, &sc->sc_atask); return (0); } int carp_new_vhost(struct carp_softc *sc, int vhid, int advskew) { struct carp_vhost_entry *vhe, *vhe0; vhe = malloc(sizeof(*vhe), M_DEVBUF, M_NOWAIT | M_ZERO); if (vhe == NULL) return (ENOMEM); refcnt_init(&vhe->vhost_refcnt); carp_sc_ref(NULL, sc); /* give a sc ref to the vhe */ vhe->parent_sc = sc; vhe->vhid = vhid; vhe->advskew = advskew; vhe->state = INIT; timeout_set_proc(&vhe->ad_tmo, carp_timer_ad, vhe); timeout_set_proc(&vhe->md_tmo, carp_timer_down, vhe); timeout_set_proc(&vhe->md6_tmo, carp_timer_down, vhe); KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */ /* mark the first vhe as leader */ if (SRPL_EMPTY_LOCKED(&sc->carp_vhosts)) { vhe->vhe_leader = 1; SRPL_INSERT_HEAD_LOCKED(&carp_vh_rc, &sc->carp_vhosts, vhe, vhost_entries); sc->sc_vhe_count = 1; return (0); } SRPL_FOREACH_LOCKED(vhe0, &sc->carp_vhosts, vhost_entries) { if (SRPL_NEXT_LOCKED(vhe0, vhost_entries) == NULL) break; } SRPL_INSERT_AFTER_LOCKED(&carp_vh_rc, vhe0, vhe, vhost_entries); sc->sc_vhe_count++; return (0); } int carp_clone_destroy(struct ifnet *ifp) { struct carp_softc *sc = ifp->if_softc; if_addrhook_del(&sc->sc_if, &sc->sc_atask); NET_LOCK(); carpdetach(sc); NET_UNLOCK(); ether_ifdetach(ifp); if_detach(ifp); carp_destroy_vhosts(ifp->if_softc); refcnt_finalize(&sc->sc_refcnt, "carpdtor"); free(sc->sc_imo.imo_membership, M_IPMOPTS, sc->sc_imo.imo_max_memberships * sizeof(struct in_multi *)); free(sc, M_DEVBUF, sizeof(*sc)); return (0); } void carp_del_all_timeouts(struct carp_softc *sc) { struct carp_vhost_entry *vhe; KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */ SRPL_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) { timeout_del(&vhe->ad_tmo); timeout_del(&vhe->md_tmo); timeout_del(&vhe->md6_tmo); } } void carpdetach(void *arg) { struct carp_softc *sc = arg; struct ifnet *ifp0; struct srpl *cif; carp_del_all_timeouts(sc); if (sc->sc_demote_cnt) carp_group_demote_adj(&sc->sc_if, -sc->sc_demote_cnt, "detach"); sc->sc_suppress = 0; sc->sc_sendad_errors = 0; carp_set_state_all(sc, INIT); sc->sc_if.if_flags &= ~IFF_UP; carp_setrun_all(sc, 0); carp_multicast_cleanup(sc); ifp0 = if_get(sc->sc_carpdevidx); if (ifp0 == NULL) return; KERNEL_ASSERT_LOCKED(); /* touching if_carp */ cif = &ifp0->if_carp; SRPL_REMOVE_LOCKED(&carp_sc_rc, cif, sc, carp_softc, sc_list); sc->sc_carpdevidx = 0; if_linkstatehook_del(ifp0, &sc->sc_ltask); if_detachhook_del(ifp0, &sc->sc_dtask); ifpromisc(ifp0, 0); if_put(ifp0); } void carp_destroy_vhosts(struct carp_softc *sc) { /* XXX bow out? */ struct carp_vhost_entry *vhe; KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */ while ((vhe = SRPL_FIRST_LOCKED(&sc->carp_vhosts)) != NULL) { SRPL_REMOVE_LOCKED(&carp_vh_rc, &sc->carp_vhosts, vhe, carp_vhost_entry, vhost_entries); carp_vh_unref(NULL, vhe); /* drop last ref */ } sc->sc_vhe_count = 0; } void carp_prepare_ad(struct mbuf *m, struct carp_vhost_entry *vhe, struct carp_header *ch) { if (!vhe->vhe_replay_cookie) { arc4random_buf(&vhe->vhe_replay_cookie, sizeof(vhe->vhe_replay_cookie)); } bcopy(&vhe->vhe_replay_cookie, ch->carp_counter, sizeof(ch->carp_counter)); /* * For the time being, do not include the IPv6 linklayer addresses * in the HMAC. */ carp_hmac_generate(vhe, ch->carp_counter, ch->carp_md, HMAC_NOV6LL); } void carp_send_ad_all(void) { struct ifnet *ifp0; struct srpl *cif; struct carp_softc *vh; KERNEL_ASSERT_LOCKED(); /* touching if_carp */ if (carp_send_all_recur > 0) return; ++carp_send_all_recur; TAILQ_FOREACH(ifp0, &ifnetlist, if_list) { if (ifp0->if_type != IFT_ETHER) continue; cif = &ifp0->if_carp; SRPL_FOREACH_LOCKED(vh, cif, sc_list) { if ((vh->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING)) { carp_vhe_send_ad_all(vh); } } } --carp_send_all_recur; } void carp_vhe_send_ad_all(struct carp_softc *sc) { struct carp_vhost_entry *vhe; KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */ SRPL_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) { if (vhe->state == MASTER) carp_send_ad(vhe); } } void carp_timer_ad(void *v) { NET_LOCK(); carp_send_ad(v); NET_UNLOCK(); } void carp_send_ad(struct carp_vhost_entry *vhe) { struct carp_header ch; struct timeval tv; struct carp_softc *sc = vhe->parent_sc; struct carp_header *ch_ptr; struct mbuf *m; int error, len, advbase, advskew; struct ifnet *ifp; struct ifaddr *ifa; struct sockaddr sa; NET_ASSERT_LOCKED(); if ((ifp = if_get(sc->sc_carpdevidx)) == NULL) { sc->sc_if.if_oerrors++; return; } /* bow out if we've gone to backup (the carp interface is going down) */ if (sc->sc_bow_out) { advbase = 255; advskew = 255; } else { advbase = sc->sc_advbase; advskew = vhe->advskew; tv.tv_sec = advbase; if (advbase == 0 && advskew == 0) tv.tv_usec = 1 * 1000000 / 256; else tv.tv_usec = advskew * 1000000 / 256; } ch.carp_version = CARP_VERSION; ch.carp_type = CARP_ADVERTISEMENT; ch.carp_vhid = vhe->vhid; ch.carp_demote = carp_group_demote_count(sc) & 0xff; ch.carp_advbase = advbase; ch.carp_advskew = advskew; ch.carp_authlen = 7; /* XXX DEFINE */ ch.carp_cksum = 0; sc->cur_vhe = vhe; /* we need the vhe later on the output path */ if (sc->sc_naddrs) { struct ip *ip; MGETHDR(m, M_DONTWAIT, MT_HEADER); if (m == NULL) { sc->sc_if.if_oerrors++; carpstat_inc(carps_onomem); /* XXX maybe less ? */ goto retry_later; } len = sizeof(*ip) + sizeof(ch); m->m_pkthdr.pf.prio = CARP_IFQ_PRIO; m->m_pkthdr.ph_rtableid = sc->sc_if.if_rdomain; m->m_pkthdr.len = len; m->m_len = len; m_align(m, len); ip = mtod(m, struct ip *); ip->ip_v = IPVERSION; ip->ip_hl = sizeof(*ip) >> 2; ip->ip_tos = IPTOS_LOWDELAY; ip->ip_len = htons(len); ip->ip_id = htons(ip_randomid()); ip->ip_off = htons(IP_DF); ip->ip_ttl = CARP_DFLTTL; ip->ip_p = IPPROTO_CARP; ip->ip_sum = 0; memset(&sa, 0, sizeof(sa)); sa.sa_family = AF_INET; /* Prefer addresses on the parent interface as source for AD. */ ifa = ifaof_ifpforaddr(&sa, ifp); if (ifa == NULL) ifa = ifaof_ifpforaddr(&sa, &sc->sc_if); KASSERT(ifa != NULL); ip->ip_src.s_addr = ifatoia(ifa)->ia_addr.sin_addr.s_addr; ip->ip_dst.s_addr = sc->sc_peer.s_addr; if (IN_MULTICAST(ip->ip_dst.s_addr)) m->m_flags |= M_MCAST; ch_ptr = (struct carp_header *)(ip + 1); bcopy(&ch, ch_ptr, sizeof(ch)); carp_prepare_ad(m, vhe, ch_ptr); m->m_data += sizeof(*ip); ch_ptr->carp_cksum = carp_cksum(m, len - sizeof(*ip)); m->m_data -= sizeof(*ip); getmicrotime(&sc->sc_if.if_lastchange); carpstat_inc(carps_opackets); error = ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL, 0); if (error && /* when unicast, the peer's down is not our fault */ !(!IN_MULTICAST(sc->sc_peer.s_addr) && error == EHOSTDOWN)){ if (error == ENOBUFS) carpstat_inc(carps_onomem); else CARP_LOG(LOG_WARNING, sc, ("ip_output failed: %d", error)); sc->sc_if.if_oerrors++; if (sc->sc_sendad_errors < INT_MAX) sc->sc_sendad_errors++; if (sc->sc_sendad_errors == CARP_SENDAD_MAX_ERRORS(sc)) carp_group_demote_adj(&sc->sc_if, 1, "> snderrors"); sc->sc_sendad_success = 0; } else { if (sc->sc_sendad_errors >= CARP_SENDAD_MAX_ERRORS(sc)) { if (++sc->sc_sendad_success >= CARP_SENDAD_MIN_SUCCESS(sc)) { carp_group_demote_adj(&sc->sc_if, -1, "< snderrors"); sc->sc_sendad_errors = 0; } } else sc->sc_sendad_errors = 0; } if (vhe->vhe_leader) { if (sc->sc_delayed_arp > 0) sc->sc_delayed_arp--; if (sc->sc_delayed_arp == 0) { carp_send_arp(sc); sc->sc_delayed_arp = -1; } } } #ifdef INET6 if (sc->sc_naddrs6) { struct ip6_hdr *ip6; MGETHDR(m, M_DONTWAIT, MT_HEADER); if (m == NULL) { sc->sc_if.if_oerrors++; carpstat_inc(carps_onomem); /* XXX maybe less ? */ goto retry_later; } len = sizeof(*ip6) + sizeof(ch); m->m_pkthdr.pf.prio = CARP_IFQ_PRIO; m->m_pkthdr.ph_rtableid = sc->sc_if.if_rdomain; m->m_pkthdr.len = len; m->m_len = len; m_align(m, len); m->m_flags |= M_MCAST; ip6 = mtod(m, struct ip6_hdr *); memset(ip6, 0, sizeof(*ip6)); ip6->ip6_vfc |= IPV6_VERSION; ip6->ip6_hlim = CARP_DFLTTL; ip6->ip6_nxt = IPPROTO_CARP; /* set the source address */ memset(&sa, 0, sizeof(sa)); sa.sa_family = AF_INET6; /* Prefer addresses on the parent interface as source for AD. */ ifa = ifaof_ifpforaddr(&sa, ifp); if (ifa == NULL) ifa = ifaof_ifpforaddr(&sa, &sc->sc_if); KASSERT(ifa != NULL); bcopy(ifatoia6(ifa)->ia_addr.sin6_addr.s6_addr, &ip6->ip6_src, sizeof(struct in6_addr)); /* set the multicast destination */ ip6->ip6_dst.s6_addr16[0] = htons(0xff02); ip6->ip6_dst.s6_addr16[1] = htons(ifp->if_index); ip6->ip6_dst.s6_addr8[15] = 0x12; ch_ptr = (struct carp_header *)(ip6 + 1); bcopy(&ch, ch_ptr, sizeof(ch)); carp_prepare_ad(m, vhe, ch_ptr); m->m_data += sizeof(*ip6); ch_ptr->carp_cksum = carp_cksum(m, len - sizeof(*ip6)); m->m_data -= sizeof(*ip6); getmicrotime(&sc->sc_if.if_lastchange); carpstat_inc(carps_opackets6); error = ip6_output(m, NULL, NULL, 0, &sc->sc_im6o, NULL); if (error) { if (error == ENOBUFS) carpstat_inc(carps_onomem); else CARP_LOG(LOG_WARNING, sc, ("ip6_output failed: %d", error)); sc->sc_if.if_oerrors++; if (sc->sc_sendad_errors < INT_MAX) sc->sc_sendad_errors++; if (sc->sc_sendad_errors == CARP_SENDAD_MAX_ERRORS(sc)) carp_group_demote_adj(&sc->sc_if, 1, "> snd6errors"); sc->sc_sendad_success = 0; } else { if (sc->sc_sendad_errors >= CARP_SENDAD_MAX_ERRORS(sc)) { if (++sc->sc_sendad_success >= CARP_SENDAD_MIN_SUCCESS(sc)) { carp_group_demote_adj(&sc->sc_if, -1, "< snd6errors"); sc->sc_sendad_errors = 0; } } else sc->sc_sendad_errors = 0; } } #endif /* INET6 */ retry_later: sc->cur_vhe = NULL; if (advbase != 255 || advskew != 255) timeout_add_tv(&vhe->ad_tmo, &tv); if_put(ifp); } /* * Broadcast a gratuitous ARP request containing * the virtual router MAC address for each IP address * associated with the virtual router. */ void carp_send_arp(struct carp_softc *sc) { struct ifaddr *ifa; in_addr_t in; TAILQ_FOREACH(ifa, &sc->sc_if.if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET) continue; in = ifatoia(ifa)->ia_addr.sin_addr.s_addr; arprequest(&sc->sc_if, &in, &in, sc->sc_ac.ac_enaddr); } } #ifdef INET6 void carp_send_na(struct carp_softc *sc) { struct ifaddr *ifa; struct in6_addr *in6; static struct in6_addr mcast = IN6ADDR_LINKLOCAL_ALLNODES_INIT; TAILQ_FOREACH(ifa, &sc->sc_if.if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; in6 = &ifatoia6(ifa)->ia_addr.sin6_addr; nd6_na_output(&sc->sc_if, &mcast, in6, ND_NA_FLAG_OVERRIDE | (ip6_forwarding ? ND_NA_FLAG_ROUTER : 0), 1, NULL); } } #endif /* INET6 */ void carp_update_lsmask(struct carp_softc *sc) { struct carp_vhost_entry *vhe; int count; if (sc->sc_balancing == CARP_BAL_NONE) return; sc->sc_lsmask = 0; count = 0; KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */ SRPL_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) { if (vhe->state == MASTER && count < sizeof(sc->sc_lsmask) * 8) sc->sc_lsmask |= 1 << count; count++; } sc->sc_lscount = count; CARP_LOG(LOG_DEBUG, sc, ("carp_update_lsmask: %x", sc->sc_lsmask)); } int carp_iamatch(struct ifnet *ifp) { struct carp_softc *sc = ifp->if_softc; struct carp_vhost_entry *vhe; struct srp_ref sr; int match = 0; vhe = SRPL_FIRST(&sr, &sc->carp_vhosts); if (vhe->state == MASTER) match = 1; SRPL_LEAVE(&sr); return (match); } int carp_ourether(struct ifnet *ifp, uint8_t *ena) { struct srpl *cif = &ifp->if_carp; struct carp_softc *sc; struct srp_ref sr; int match = 0; uint64_t dst = ether_addr_to_e64((struct ether_addr *)ena); KASSERT(ifp->if_type == IFT_ETHER); SRPL_FOREACH(sc, &sr, cif, sc_list) { if ((sc->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) continue; if (carp_vhe_match(sc, dst)) { match = 1; break; } } SRPL_LEAVE(&sr); return (match); } int carp_vhe_match(struct carp_softc *sc, uint64_t dst) { struct carp_vhost_entry *vhe; struct srp_ref sr; int active = 0; vhe = SRPL_FIRST(&sr, &sc->carp_vhosts); active = (vhe->state == MASTER || sc->sc_balancing >= CARP_BAL_IP); SRPL_LEAVE(&sr); return (active && (dst == ether_addr_to_e64((struct ether_addr *)sc->sc_ac.ac_enaddr))); } struct mbuf * carp_input(struct ifnet *ifp0, struct mbuf *m, uint64_t dst) { struct srpl *cif; struct carp_softc *sc; struct srp_ref sr; cif = &ifp0->if_carp; SRPL_FOREACH(sc, &sr, cif, sc_list) { if ((sc->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) continue; if (carp_vhe_match(sc, dst)) { /* * These packets look like layer 2 multicast but they * are unicast at layer 3. With help of the tag the * mbuf's M_MCAST flag can be removed by carp_lsdrop() * after we have passed layer 2. */ if (sc->sc_balancing == CARP_BAL_IP) { struct m_tag *mtag; mtag = m_tag_get(PACKET_TAG_CARP_BAL_IP, 0, M_NOWAIT); if (mtag == NULL) { m_freem(m); goto out; } m_tag_prepend(m, mtag); } break; } } if (sc == NULL) { SRPL_LEAVE(&sr); if (!ETH64_IS_MULTICAST(dst)) return (m); /* * XXX Should really check the list of multicast addresses * for each CARP interface _before_ copying. */ SRPL_FOREACH(sc, &sr, cif, sc_list) { struct mbuf *m0; if (!(sc->sc_if.if_flags & IFF_UP)) continue; m0 = m_dup_pkt(m, ETHER_ALIGN, M_DONTWAIT); if (m0 == NULL) continue; if_vinput(&sc->sc_if, m0); } SRPL_LEAVE(&sr); return (m); } if_vinput(&sc->sc_if, m); out: SRPL_LEAVE(&sr); return (NULL); } int carp_lsdrop(struct ifnet *ifp, struct mbuf *m, sa_family_t af, u_int32_t *src, u_int32_t *dst, int drop) { struct carp_softc *sc; u_int32_t fold; struct m_tag *mtag; if (ifp->if_type != IFT_CARP) return 0; sc = ifp->if_softc; if (sc->sc_balancing == CARP_BAL_NONE) return 0; /* * Remove M_MCAST flag from mbuf of balancing ip traffic, since the fact * that it is layer 2 multicast does not implicate that it is also layer * 3 multicast. */ if (m->m_flags & M_MCAST && (mtag = m_tag_find(m, PACKET_TAG_CARP_BAL_IP, NULL))) { m_tag_delete(m, mtag); m->m_flags &= ~M_MCAST; } /* * Return without making a drop decision. This allows to clear the * M_MCAST flag and do nothing else. */ if (!drop) return 0; /* * Never drop carp advertisements. * XXX Bad idea to pass all broadcast / multicast traffic? */ if (m->m_flags & (M_BCAST|M_MCAST)) return 0; fold = src[0] ^ dst[0]; #ifdef INET6 if (af == AF_INET6) { int i; for (i = 1; i < 4; i++) fold ^= src[i] ^ dst[i]; } #endif if (sc->sc_lscount == 0) /* just to be safe */ return 1; return ((1 << (ntohl(fold) % sc->sc_lscount)) & sc->sc_lsmask) == 0; } void carp_timer_down(void *v) { NET_LOCK(); carp_master_down(v); NET_UNLOCK(); } void carp_master_down(struct carp_vhost_entry *vhe) { struct carp_softc *sc = vhe->parent_sc; NET_ASSERT_LOCKED(); switch (vhe->state) { case INIT: printf("%s: master_down event in INIT state\n", sc->sc_if.if_xname); break; case MASTER: break; case BACKUP: carp_set_state(vhe, MASTER); carp_send_ad(vhe); if (sc->sc_balancing == CARP_BAL_NONE && vhe->vhe_leader) { carp_send_arp(sc); /* Schedule a delayed ARP to deal w/ some L3 switches */ sc->sc_delayed_arp = 2; #ifdef INET6 carp_send_na(sc); #endif /* INET6 */ } carp_setrun(vhe, 0); carpstat_inc(carps_preempt); break; } } void carp_setrun_all(struct carp_softc *sc, sa_family_t af) { struct carp_vhost_entry *vhe; KERNEL_ASSERT_LOCKED(); /* touching carp_vhost */ SRPL_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) { carp_setrun(vhe, af); } } /* * When in backup state, af indicates whether to reset the master down timer * for v4 or v6. If it's set to zero, reset the ones which are already pending. */ void carp_setrun(struct carp_vhost_entry *vhe, sa_family_t af) { struct ifnet *ifp; struct timeval tv; struct carp_softc *sc = vhe->parent_sc; if ((ifp = if_get(sc->sc_carpdevidx)) == NULL) { sc->sc_if.if_flags &= ~IFF_RUNNING; carp_set_state_all(sc, INIT); return; } if (memcmp(((struct arpcom *)ifp)->ac_enaddr, sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN) == 0) sc->sc_realmac = 1; else sc->sc_realmac = 0; if_put(ifp); if (sc->sc_if.if_flags & IFF_UP && vhe->vhid > 0 && (sc->sc_naddrs || sc->sc_naddrs6) && !sc->sc_suppress) { sc->sc_if.if_flags |= IFF_RUNNING; } else { sc->sc_if.if_flags &= ~IFF_RUNNING; return; } switch (vhe->state) { case INIT: carp_set_state(vhe, BACKUP); carp_setrun(vhe, 0); break; case BACKUP: timeout_del(&vhe->ad_tmo); tv.tv_sec = 3 * sc->sc_advbase; if (sc->sc_advbase == 0 && vhe->advskew == 0) tv.tv_usec = 3 * 1000000 / 256; else if (sc->sc_advbase == 0) tv.tv_usec = 3 * vhe->advskew * 1000000 / 256; else tv.tv_usec = vhe->advskew * 1000000 / 256; if (vhe->vhe_leader) sc->sc_delayed_arp = -1; switch (af) { case AF_INET: timeout_add_tv(&vhe->md_tmo, &tv); break; #ifdef INET6 case AF_INET6: timeout_add_tv(&vhe->md6_tmo, &tv); break; #endif /* INET6 */ default: if (sc->sc_naddrs) timeout_add_tv(&vhe->md_tmo, &tv); if (sc->sc_naddrs6) timeout_add_tv(&vhe->md6_tmo, &tv); break; } break; case MASTER: tv.tv_sec = sc->sc_advbase; if (sc->sc_advbase == 0 && vhe->advskew == 0) tv.tv_usec = 1 * 1000000 / 256; else tv.tv_usec = vhe->advskew * 1000000 / 256; timeout_add_tv(&vhe->ad_tmo, &tv); break; } } void carp_multicast_cleanup(struct carp_softc *sc) { struct ip_moptions *imo = &sc->sc_imo; #ifdef INET6 struct ip6_moptions *im6o = &sc->sc_im6o; #endif u_int16_t n = imo->imo_num_memberships; /* Clean up our own multicast memberships */ while (n-- > 0) { if (imo->imo_membership[n] != NULL) { in_delmulti(imo->imo_membership[n]); imo->imo_membership[n] = NULL; } } imo->imo_num_memberships = 0; imo->imo_ifidx = 0; #ifdef INET6 while (!LIST_EMPTY(&im6o->im6o_memberships)) { struct in6_multi_mship *imm = LIST_FIRST(&im6o->im6o_memberships); LIST_REMOVE(imm, i6mm_chain); in6_leavegroup(imm); } im6o->im6o_ifidx = 0; #endif /* And any other multicast memberships */ carp_ether_purgemulti(sc); } int carp_set_ifp(struct carp_softc *sc, struct ifnet *ifp0) { struct srpl *cif; struct carp_softc *vr, *last = NULL, *after = NULL; int myself = 0, error = 0; KASSERT(ifp0->if_index != sc->sc_carpdevidx); KERNEL_ASSERT_LOCKED(); /* touching if_carp */ if ((ifp0->if_flags & IFF_MULTICAST) == 0) return (EADDRNOTAVAIL); if (ifp0->if_type != IFT_ETHER) return (EINVAL); cif = &ifp0->if_carp; if (carp_check_dup_vhids(sc, cif, NULL)) return (EINVAL); if ((error = ifpromisc(ifp0, 1))) return (error); /* detach from old interface */ if (sc->sc_carpdevidx != 0) carpdetach(sc); /* attach carp interface to physical interface */ if_detachhook_add(ifp0, &sc->sc_dtask); if_linkstatehook_add(ifp0, &sc->sc_ltask); sc->sc_carpdevidx = ifp0->if_index; sc->sc_if.if_capabilities = ifp0->if_capabilities & (IFCAP_CSUM_MASK | IFCAP_TSOv4 | IFCAP_TSOv6); SRPL_FOREACH_LOCKED(vr, cif, sc_list) { struct carp_vhost_entry *vrhead, *schead; last = vr; if (vr == sc) myself = 1; vrhead = SRPL_FIRST_LOCKED(&vr->carp_vhosts); schead = SRPL_FIRST_LOCKED(&sc->carp_vhosts); if (vrhead->vhid < schead->vhid) after = vr; } if (!myself) { /* We're trying to keep things in order */ if (last == NULL) { SRPL_INSERT_HEAD_LOCKED(&carp_sc_rc, cif, sc, sc_list); } else if (after == NULL) { SRPL_INSERT_AFTER_LOCKED(&carp_sc_rc, last, sc, sc_list); } else { SRPL_INSERT_AFTER_LOCKED(&carp_sc_rc, after, sc, sc_list); } } if (sc->sc_naddrs || sc->sc_naddrs6) sc->sc_if.if_flags |= IFF_UP; carp_set_enaddr(sc); carp_carpdev_state(sc); return (0); } void carp_set_vhe_enaddr(struct carp_vhost_entry *vhe) { struct carp_softc *sc = vhe->parent_sc; if (vhe->vhid != 0 && sc->sc_carpdevidx != 0) { if (vhe->vhe_leader && sc->sc_balancing == CARP_BAL_IP) vhe->vhe_enaddr[0] = 1; else vhe->vhe_enaddr[0] = 0; vhe->vhe_enaddr[1] = 0; vhe->vhe_enaddr[2] = 0x5e; vhe->vhe_enaddr[3] = 0; vhe->vhe_enaddr[4] = 1; vhe->vhe_enaddr[5] = vhe->vhid; } else memset(vhe->vhe_enaddr, 0, ETHER_ADDR_LEN); } void carp_set_enaddr(struct carp_softc *sc) { struct carp_vhost_entry *vhe; KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */ SRPL_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) carp_set_vhe_enaddr(vhe); vhe = SRPL_FIRST_LOCKED(&sc->carp_vhosts); /* * Use the carp lladdr if the running one isn't manually set. * Only compare static parts of the lladdr. */ if ((memcmp(sc->sc_ac.ac_enaddr + 1, vhe->vhe_enaddr + 1, ETHER_ADDR_LEN - 2) == 0) || (!sc->sc_ac.ac_enaddr[0] && !sc->sc_ac.ac_enaddr[1] && !sc->sc_ac.ac_enaddr[2] && !sc->sc_ac.ac_enaddr[3] && !sc->sc_ac.ac_enaddr[4] && !sc->sc_ac.ac_enaddr[5])) bcopy(vhe->vhe_enaddr, sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN); /* Make sure the enaddr has changed before further twiddling. */ if (memcmp(sc->sc_ac.ac_enaddr, sc->sc_curlladdr, ETHER_ADDR_LEN) != 0) { bcopy(sc->sc_ac.ac_enaddr, LLADDR(sc->sc_if.if_sadl), ETHER_ADDR_LEN); bcopy(sc->sc_ac.ac_enaddr, sc->sc_curlladdr, ETHER_ADDR_LEN); #ifdef INET6 /* * (re)attach a link-local address which matches * our new MAC address. */ if (sc->sc_naddrs6) in6_ifattach_linklocal(&sc->sc_if, NULL); #endif carp_set_state_all(sc, INIT); carp_setrun_all(sc, 0); } } void carp_addr_updated(void *v) { struct carp_softc *sc = (struct carp_softc *) v; struct ifaddr *ifa; int new_naddrs = 0, new_naddrs6 = 0; TAILQ_FOREACH(ifa, &sc->sc_if.if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family == AF_INET) new_naddrs++; #ifdef INET6 else if (ifa->ifa_addr->sa_family == AF_INET6) new_naddrs6++; #endif /* INET6 */ } /* We received address changes from if_addrhooks callback */ if (new_naddrs != sc->sc_naddrs || new_naddrs6 != sc->sc_naddrs6) { sc->sc_naddrs = new_naddrs; sc->sc_naddrs6 = new_naddrs6; /* Re-establish multicast membership removed by in_control */ if (IN_MULTICAST(sc->sc_peer.s_addr)) { if (!in_hasmulti(&sc->sc_peer, &sc->sc_if)) { struct in_multi **imm = sc->sc_imo.imo_membership; u_int16_t maxmem = sc->sc_imo.imo_max_memberships; memset(&sc->sc_imo, 0, sizeof(sc->sc_imo)); sc->sc_imo.imo_membership = imm; sc->sc_imo.imo_max_memberships = maxmem; if (sc->sc_carpdevidx != 0 && sc->sc_naddrs > 0) carp_join_multicast(sc); } } if (sc->sc_naddrs == 0 && sc->sc_naddrs6 == 0) { sc->sc_if.if_flags &= ~IFF_UP; carp_set_state_all(sc, INIT); } else carp_hmac_prepare(sc); } carp_setrun_all(sc, 0); } int carp_set_addr(struct carp_softc *sc, struct sockaddr_in *sin) { struct in_addr *in = &sin->sin_addr; int error; KASSERT(sc->sc_carpdevidx != 0); /* XXX is this necessary? */ if (in->s_addr == INADDR_ANY) { carp_setrun_all(sc, 0); return (0); } if (sc->sc_naddrs == 0 && (error = carp_join_multicast(sc)) != 0) return (error); carp_set_state_all(sc, INIT); return (0); } int carp_join_multicast(struct carp_softc *sc) { struct ip_moptions *imo = &sc->sc_imo; struct in_multi *imm; struct in_addr addr; if (!IN_MULTICAST(sc->sc_peer.s_addr)) return (0); addr.s_addr = sc->sc_peer.s_addr; if ((imm = in_addmulti(&addr, &sc->sc_if)) == NULL) return (ENOBUFS); imo->imo_membership[0] = imm; imo->imo_num_memberships = 1; imo->imo_ifidx = sc->sc_if.if_index; imo->imo_ttl = CARP_DFLTTL; imo->imo_loop = 0; return (0); } #ifdef INET6 int carp_set_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6) { int error; KASSERT(sc->sc_carpdevidx != 0); if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { carp_setrun_all(sc, 0); return (0); } if (sc->sc_naddrs6 == 0 && (error = carp_join_multicast6(sc)) != 0) return (error); carp_set_state_all(sc, INIT); return (0); } int carp_join_multicast6(struct carp_softc *sc) { struct in6_multi_mship *imm, *imm2; struct ip6_moptions *im6o = &sc->sc_im6o; struct sockaddr_in6 addr6; int error; /* Join IPv6 CARP multicast group */ memset(&addr6, 0, sizeof(addr6)); addr6.sin6_family = AF_INET6; addr6.sin6_len = sizeof(addr6); addr6.sin6_addr.s6_addr16[0] = htons(0xff02); addr6.sin6_addr.s6_addr16[1] = htons(sc->sc_if.if_index); addr6.sin6_addr.s6_addr8[15] = 0x12; if ((imm = in6_joingroup(&sc->sc_if, &addr6.sin6_addr, &error)) == NULL) { return (error); } /* join solicited multicast address */ memset(&addr6.sin6_addr, 0, sizeof(addr6.sin6_addr)); addr6.sin6_addr.s6_addr16[0] = htons(0xff02); addr6.sin6_addr.s6_addr16[1] = htons(sc->sc_if.if_index); addr6.sin6_addr.s6_addr32[1] = 0; addr6.sin6_addr.s6_addr32[2] = htonl(1); addr6.sin6_addr.s6_addr32[3] = 0; addr6.sin6_addr.s6_addr8[12] = 0xff; if ((imm2 = in6_joingroup(&sc->sc_if, &addr6.sin6_addr, &error)) == NULL) { in6_leavegroup(imm); return (error); } /* apply v6 multicast membership */ im6o->im6o_ifidx = sc->sc_if.if_index; if (imm) LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain); if (imm2) LIST_INSERT_HEAD(&im6o->im6o_memberships, imm2, i6mm_chain); return (0); } #endif /* INET6 */ int carp_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr) { struct proc *p = curproc; /* XXX */ struct carp_softc *sc = ifp->if_softc; struct carp_vhost_entry *vhe; struct carpreq carpr; struct ifaddr *ifa = (struct ifaddr *)addr; struct ifreq *ifr = (struct ifreq *)addr; struct ifnet *ifp0 = NULL; int i, error = 0; switch (cmd) { case SIOCSIFADDR: if (sc->sc_carpdevidx == 0) return (EINVAL); switch (ifa->ifa_addr->sa_family) { case AF_INET: sc->sc_if.if_flags |= IFF_UP; error = carp_set_addr(sc, satosin(ifa->ifa_addr)); break; #ifdef INET6 case AF_INET6: sc->sc_if.if_flags |= IFF_UP; error = carp_set_addr6(sc, satosin6(ifa->ifa_addr)); break; #endif /* INET6 */ default: error = EAFNOSUPPORT; break; } break; case SIOCSIFFLAGS: KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */ vhe = SRPL_FIRST_LOCKED(&sc->carp_vhosts); if (vhe->state != INIT && !(ifr->ifr_flags & IFF_UP)) { carp_del_all_timeouts(sc); /* we need the interface up to bow out */ sc->sc_if.if_flags |= IFF_UP; sc->sc_bow_out = 1; carp_vhe_send_ad_all(sc); sc->sc_bow_out = 0; sc->sc_if.if_flags &= ~IFF_UP; carp_set_state_all(sc, INIT); carp_setrun_all(sc, 0); } else if (vhe->state == INIT && (ifr->ifr_flags & IFF_UP)) { sc->sc_if.if_flags |= IFF_UP; carp_setrun_all(sc, 0); } break; case SIOCSVH: KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */ vhe = SRPL_FIRST_LOCKED(&sc->carp_vhosts); if ((error = suser(p)) != 0) break; if ((error = copyin(ifr->ifr_data, &carpr, sizeof carpr))) break; error = 1; if (carpr.carpr_carpdev[0] != '\0' && (ifp0 = if_unit(carpr.carpr_carpdev)) == NULL) return (EINVAL); if (carpr.carpr_peer.s_addr == 0) sc->sc_peer.s_addr = INADDR_CARP_GROUP; else sc->sc_peer.s_addr = carpr.carpr_peer.s_addr; if (ifp0 != NULL && ifp0->if_index != sc->sc_carpdevidx) { if ((error = carp_set_ifp(sc, ifp0))) { if_put(ifp0); return (error); } } if_put(ifp0); if (vhe->state != INIT && carpr.carpr_state != vhe->state) { switch (carpr.carpr_state) { case BACKUP: timeout_del(&vhe->ad_tmo); carp_set_state_all(sc, BACKUP); carp_setrun_all(sc, 0); break; case MASTER: KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */ SRPL_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) carp_master_down(vhe); break; default: break; } } if ((error = carp_vhids_ioctl(sc, &carpr))) return (error); if (carpr.carpr_advbase >= 0) { if (carpr.carpr_advbase > 255) { error = EINVAL; break; } sc->sc_advbase = carpr.carpr_advbase; error--; } if (memcmp(sc->sc_advskews, carpr.carpr_advskews, sizeof(sc->sc_advskews))) { i = 0; KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */ SRPL_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) vhe->advskew = carpr.carpr_advskews[i++]; bcopy(carpr.carpr_advskews, sc->sc_advskews, sizeof(sc->sc_advskews)); } if (sc->sc_balancing != carpr.carpr_balancing) { if (carpr.carpr_balancing > CARP_BAL_MAXID) { error = EINVAL; break; } sc->sc_balancing = carpr.carpr_balancing; carp_set_enaddr(sc); carp_update_lsmask(sc); } bcopy(carpr.carpr_key, sc->sc_key, sizeof(sc->sc_key)); if (error > 0) error = EINVAL; else { error = 0; carp_hmac_prepare(sc); carp_setrun_all(sc, 0); } break; case SIOCGVH: memset(&carpr, 0, sizeof(carpr)); if ((ifp0 = if_get(sc->sc_carpdevidx)) != NULL) strlcpy(carpr.carpr_carpdev, ifp0->if_xname, IFNAMSIZ); if_put(ifp0); i = 0; KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */ SRPL_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) { carpr.carpr_vhids[i] = vhe->vhid; carpr.carpr_advskews[i] = vhe->advskew; carpr.carpr_states[i] = vhe->state; i++; } carpr.carpr_advbase = sc->sc_advbase; carpr.carpr_balancing = sc->sc_balancing; if (suser(p) == 0) bcopy(sc->sc_key, carpr.carpr_key, sizeof(carpr.carpr_key)); carpr.carpr_peer.s_addr = sc->sc_peer.s_addr; error = copyout(&carpr, ifr->ifr_data, sizeof(carpr)); break; case SIOCADDMULTI: error = carp_ether_addmulti(sc, ifr); break; case SIOCDELMULTI: error = carp_ether_delmulti(sc, ifr); break; case SIOCAIFGROUP: case SIOCDIFGROUP: if (sc->sc_demote_cnt) carp_ifgroup_ioctl(ifp, cmd, addr); break; case SIOCSIFGATTR: carp_ifgattr_ioctl(ifp, cmd, addr); break; default: error = ENOTTY; } if (memcmp(sc->sc_ac.ac_enaddr, sc->sc_curlladdr, ETHER_ADDR_LEN) != 0) carp_set_enaddr(sc); return (error); } int carp_check_dup_vhids(struct carp_softc *sc, struct srpl *cif, struct carpreq *carpr) { struct carp_softc *vr; struct carp_vhost_entry *vhe, *vhe0; int i; KERNEL_ASSERT_LOCKED(); /* touching if_carp + carp_vhosts */ SRPL_FOREACH_LOCKED(vr, cif, sc_list) { if (vr == sc) continue; SRPL_FOREACH_LOCKED(vhe, &vr->carp_vhosts, vhost_entries) { if (carpr) { for (i = 0; carpr->carpr_vhids[i]; i++) { if (vhe->vhid == carpr->carpr_vhids[i]) return (EINVAL); } } SRPL_FOREACH_LOCKED(vhe0, &sc->carp_vhosts, vhost_entries) { if (vhe->vhid == vhe0->vhid) return (EINVAL); } } } return (0); } int carp_vhids_ioctl(struct carp_softc *sc, struct carpreq *carpr) { int i, j; u_int8_t taken_vhids[256]; if (carpr->carpr_vhids[0] == 0 || !memcmp(sc->sc_vhids, carpr->carpr_vhids, sizeof(sc->sc_vhids))) return (0); memset(taken_vhids, 0, sizeof(taken_vhids)); for (i = 0; carpr->carpr_vhids[i]; i++) { struct ifnet *ifp; if (taken_vhids[carpr->carpr_vhids[i]]) return (EINVAL); taken_vhids[carpr->carpr_vhids[i]] = 1; if ((ifp = if_get(sc->sc_carpdevidx)) != NULL) { struct srpl *cif; cif = &ifp->if_carp; if (carp_check_dup_vhids(sc, cif, carpr)) { if_put(ifp); return (EINVAL); } } if_put(ifp); if (carpr->carpr_advskews[i] >= 255) return (EINVAL); } /* set sane balancing defaults */ if (i <= 1) carpr->carpr_balancing = CARP_BAL_NONE; else if (carpr->carpr_balancing == CARP_BAL_NONE && sc->sc_balancing == CARP_BAL_NONE) carpr->carpr_balancing = CARP_BAL_IP; /* destroy all */ carp_del_all_timeouts(sc); carp_destroy_vhosts(sc); memset(sc->sc_vhids, 0, sizeof(sc->sc_vhids)); /* sort vhosts list by vhid */ for (j = 1; j <= 255; j++) { for (i = 0; carpr->carpr_vhids[i]; i++) { if (carpr->carpr_vhids[i] != j) continue; if (carp_new_vhost(sc, carpr->carpr_vhids[i], carpr->carpr_advskews[i])) return (ENOMEM); sc->sc_vhids[i] = carpr->carpr_vhids[i]; sc->sc_advskews[i] = carpr->carpr_advskews[i]; } } carp_set_enaddr(sc); carp_set_state_all(sc, INIT); return (0); } void carp_ifgroup_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr) { struct ifgroupreq *ifgr = (struct ifgroupreq *)addr; struct ifg_list *ifgl; int *dm, adj; if (!strcmp(ifgr->ifgr_group, IFG_ALL)) return; adj = ((struct carp_softc *)ifp->if_softc)->sc_demote_cnt; if (cmd == SIOCDIFGROUP) adj = adj * -1; TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) if (!strcmp(ifgl->ifgl_group->ifg_group, ifgr->ifgr_group)) { dm = &ifgl->ifgl_group->ifg_carp_demoted; if (*dm + adj >= 0) *dm += adj; else *dm = 0; } } void carp_ifgattr_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr) { struct ifgroupreq *ifgr = (struct ifgroupreq *)addr; struct carp_softc *sc = ifp->if_softc; if (ifgr->ifgr_attrib.ifg_carp_demoted > 0 && (sc->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING)) carp_vhe_send_ad_all(sc); } void carp_start(struct ifnet *ifp) { struct carp_softc *sc = ifp->if_softc; struct ifnet *ifp0; struct mbuf *m; if ((ifp0 = if_get(sc->sc_carpdevidx)) == NULL) { ifq_purge(&ifp->if_snd); return; } while ((m = ifq_dequeue(&ifp->if_snd)) != NULL) carp_transmit(sc, ifp0, m); if_put(ifp0); } void carp_transmit(struct carp_softc *sc, struct ifnet *ifp0, struct mbuf *m) { struct ifnet *ifp = &sc->sc_if; #if NBPFILTER > 0 { caddr_t if_bpf = ifp->if_bpf; if (if_bpf) bpf_mtap_ether(if_bpf, m, BPF_DIRECTION_OUT); } #endif /* NBPFILTER > 0 */ if (!ISSET(ifp0->if_flags, IFF_RUNNING)) { counters_inc(ifp->if_counters, ifc_oerrors); m_freem(m); return; } /* * Do not leak the multicast address when sending * advertisements in 'ip' and 'ip-stealth' balancing * modes. */ if (sc->sc_balancing == CARP_BAL_IP || sc->sc_balancing == CARP_BAL_IPSTEALTH) { struct ether_header *eh = mtod(m, struct ether_header *); memcpy(eh->ether_shost, sc->sc_ac.ac_enaddr, sizeof(eh->ether_shost)); } if (if_enqueue(ifp0, m)) counters_inc(ifp->if_counters, ifc_oerrors); } int carp_enqueue(struct ifnet *ifp, struct mbuf *m) { struct carp_softc *sc = ifp->if_softc; struct ifnet *ifp0; /* no ifq_is_priq, cos hfsc on carp doesn't make sense */ /* * If the parent of this carp(4) got destroyed while * `m' was being processed, silently drop it. */ if ((ifp0 = if_get(sc->sc_carpdevidx)) == NULL) { m_freem(m); return (0); } counters_pkt(ifp->if_counters, ifc_opackets, ifc_obytes, m->m_pkthdr.len); carp_transmit(sc, ifp0, m); if_put(ifp0); return (0); } int carp_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa, struct rtentry *rt) { struct carp_softc *sc = ((struct carp_softc *)ifp->if_softc); struct carp_vhost_entry *vhe; struct srp_ref sr; int ismaster; if (sc->cur_vhe == NULL) { vhe = SRPL_FIRST(&sr, &sc->carp_vhosts); ismaster = (vhe->state == MASTER); SRPL_LEAVE(&sr); } else { ismaster = (sc->cur_vhe->state == MASTER); } if ((sc->sc_balancing == CARP_BAL_NONE && !ismaster)) { m_freem(m); return (ENETUNREACH); } return (ether_output(ifp, m, sa, rt)); } void carp_set_state_all(struct carp_softc *sc, int state) { struct carp_vhost_entry *vhe; KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */ SRPL_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) { if (vhe->state == state) continue; carp_set_state(vhe, state); } } void carp_set_state(struct carp_vhost_entry *vhe, int state) { struct carp_softc *sc = vhe->parent_sc; static const char *carp_states[] = { CARP_STATES }; int loglevel; struct carp_vhost_entry *vhe0; KASSERT(vhe->state != state); if (vhe->state == INIT || state == INIT) loglevel = LOG_WARNING; else loglevel = LOG_CRIT; if (sc->sc_vhe_count > 1) CARP_LOG(loglevel, sc, ("state transition (vhid %d): %s -> %s", vhe->vhid, carp_states[vhe->state], carp_states[state])); else CARP_LOG(loglevel, sc, ("state transition: %s -> %s", carp_states[vhe->state], carp_states[state])); vhe->state = state; carp_update_lsmask(sc); KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */ sc->sc_if.if_link_state = LINK_STATE_INVALID; SRPL_FOREACH_LOCKED(vhe0, &sc->carp_vhosts, vhost_entries) { /* * Link must be up if at least one vhe is in state MASTER to * bring or keep route up. */ if (vhe0->state == MASTER) { sc->sc_if.if_link_state = LINK_STATE_UP; break; } else if (vhe0->state == BACKUP) { sc->sc_if.if_link_state = LINK_STATE_DOWN; } } if_link_state_change(&sc->sc_if); } void carp_group_demote_adj(struct ifnet *ifp, int adj, char *reason) { struct ifg_list *ifgl; int *dm, need_ad; struct carp_softc *nil = NULL; if (ifp->if_type == IFT_CARP) { dm = &((struct carp_softc *)ifp->if_softc)->sc_demote_cnt; if (*dm + adj >= 0) *dm += adj; else *dm = 0; } need_ad = 0; TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) { if (!strcmp(ifgl->ifgl_group->ifg_group, IFG_ALL)) continue; dm = &ifgl->ifgl_group->ifg_carp_demoted; if (*dm + adj >= 0) *dm += adj; else *dm = 0; if (adj > 0 && *dm == 1) need_ad = 1; CARP_LOG(LOG_ERR, nil, ("%s demoted group %s by %d to %d (%s)", ifp->if_xname, ifgl->ifgl_group->ifg_group, adj, *dm, reason)); } if (need_ad) carp_send_ad_all(); } int carp_group_demote_count(struct carp_softc *sc) { struct ifg_list *ifgl; int count = 0; TAILQ_FOREACH(ifgl, &sc->sc_if.if_groups, ifgl_next) count += ifgl->ifgl_group->ifg_carp_demoted; if (count == 0 && sc->sc_demote_cnt) count = sc->sc_demote_cnt; return (count > 255 ? 255 : count); } void carp_carpdev_state(void *v) { struct carp_softc *sc = v; struct ifnet *ifp0; int suppressed = sc->sc_suppress; if ((ifp0 = if_get(sc->sc_carpdevidx)) == NULL) return; if (ifp0->if_link_state == LINK_STATE_DOWN || !(ifp0->if_flags & IFF_UP)) { sc->sc_if.if_flags &= ~IFF_RUNNING; carp_del_all_timeouts(sc); carp_set_state_all(sc, INIT); sc->sc_suppress = 1; carp_setrun_all(sc, 0); if (!suppressed) carp_group_demote_adj(&sc->sc_if, 1, "carpdev"); } else if (suppressed) { carp_set_state_all(sc, INIT); sc->sc_suppress = 0; carp_setrun_all(sc, 0); carp_group_demote_adj(&sc->sc_if, -1, "carpdev"); } if_put(ifp0); } int carp_ether_addmulti(struct carp_softc *sc, struct ifreq *ifr) { struct ifnet *ifp0; struct carp_mc_entry *mc; u_int8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN]; int error; ifp0 = if_get(sc->sc_carpdevidx); if (ifp0 == NULL) return (EINVAL); error = ether_addmulti(ifr, (struct arpcom *)&sc->sc_ac); if (error != ENETRESET) { if_put(ifp0); return (error); } /* * This is new multicast address. We have to tell parent * about it. Also, remember this multicast address so that * we can delete them on unconfigure. */ mc = malloc(sizeof(*mc), M_DEVBUF, M_NOWAIT); if (mc == NULL) { error = ENOMEM; goto alloc_failed; } /* * As ether_addmulti() returns ENETRESET, following two * statement shouldn't fail. */ (void)ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi); ETHER_LOOKUP_MULTI(addrlo, addrhi, &sc->sc_ac, mc->mc_enm); memcpy(&mc->mc_addr, &ifr->ifr_addr, ifr->ifr_addr.sa_len); LIST_INSERT_HEAD(&sc->carp_mc_listhead, mc, mc_entries); error = (*ifp0->if_ioctl)(ifp0, SIOCADDMULTI, (caddr_t)ifr); if (error != 0) goto ioctl_failed; if_put(ifp0); return (error); ioctl_failed: LIST_REMOVE(mc, mc_entries); free(mc, M_DEVBUF, sizeof(*mc)); alloc_failed: (void)ether_delmulti(ifr, (struct arpcom *)&sc->sc_ac); if_put(ifp0); return (error); } int carp_ether_delmulti(struct carp_softc *sc, struct ifreq *ifr) { struct ifnet *ifp0; struct ether_multi *enm; struct carp_mc_entry *mc; u_int8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN]; int error; ifp0 = if_get(sc->sc_carpdevidx); if (ifp0 == NULL) return (EINVAL); /* * Find a key to lookup carp_mc_entry. We have to do this * before calling ether_delmulti for obvious reason. */ if ((error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi)) != 0) goto rele; ETHER_LOOKUP_MULTI(addrlo, addrhi, &sc->sc_ac, enm); if (enm == NULL) { error = EINVAL; goto rele; } LIST_FOREACH(mc, &sc->carp_mc_listhead, mc_entries) if (mc->mc_enm == enm) break; /* We won't delete entries we didn't add */ if (mc == NULL) { error = EINVAL; goto rele; } error = ether_delmulti(ifr, (struct arpcom *)&sc->sc_ac); if (error != ENETRESET) goto rele; /* We no longer use this multicast address. Tell parent so. */ error = (*ifp0->if_ioctl)(ifp0, SIOCDELMULTI, (caddr_t)ifr); if (error == 0) { /* And forget about this address. */ LIST_REMOVE(mc, mc_entries); free(mc, M_DEVBUF, sizeof(*mc)); } else (void)ether_addmulti(ifr, (struct arpcom *)&sc->sc_ac); rele: if_put(ifp0); return (error); } /* * Delete any multicast address we have asked to add from parent * interface. Called when the carp is being unconfigured. */ void carp_ether_purgemulti(struct carp_softc *sc) { struct ifnet *ifp0; /* Parent. */ struct carp_mc_entry *mc; union { struct ifreq ifreq; struct { char ifr_name[IFNAMSIZ]; struct sockaddr_storage ifr_ss; } ifreq_storage; } u; struct ifreq *ifr = &u.ifreq; if ((ifp0 = if_get(sc->sc_carpdevidx)) == NULL) return; memcpy(ifr->ifr_name, ifp0->if_xname, IFNAMSIZ); while ((mc = LIST_FIRST(&sc->carp_mc_listhead)) != NULL) { memcpy(&ifr->ifr_addr, &mc->mc_addr, mc->mc_addr.ss_len); (void)(*ifp0->if_ioctl)(ifp0, SIOCDELMULTI, (caddr_t)ifr); LIST_REMOVE(mc, mc_entries); free(mc, M_DEVBUF, sizeof(*mc)); } if_put(ifp0); } void carp_vh_ref(void *null, void *v) { struct carp_vhost_entry *vhe = v; refcnt_take(&vhe->vhost_refcnt); } void carp_vh_unref(void *null, void *v) { struct carp_vhost_entry *vhe = v; if (refcnt_rele(&vhe->vhost_refcnt)) { carp_sc_unref(NULL, vhe->parent_sc); free(vhe, M_DEVBUF, sizeof(*vhe)); } } void carp_sc_ref(void *null, void *s) { struct carp_softc *sc = s; refcnt_take(&sc->sc_refcnt); } void carp_sc_unref(void *null, void *s) { struct carp_softc *sc = s; refcnt_rele_wake(&sc->sc_refcnt); }
2 10 10 9 10 71 71 1 30 41 41 29 71 30 31 30 68 68 128 98 31 71 68 128 113 122 31 30 19 106 13 54 54 26 11 114 22 119 1 30 127 126 13 126 31 10 127 127 127 127 69 68 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 /* $OpenBSD: subr_prf.c,v 1.106 2022/08/14 01:58:28 jsg Exp $ */ /* $NetBSD: subr_prf.c,v 1.45 1997/10/24 18:14:25 chuck Exp $ */ /*- * Copyright (c) 1986, 1988, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/reboot.h> #include <sys/msgbuf.h> #include <sys/proc.h> #include <sys/tty.h> #include <sys/tprintf.h> #include <sys/syslog.h> #include <sys/pool.h> #include <sys/mutex.h> #include <dev/cons.h> /* * note that stdarg.h and the ansi style va_start macro is used for both * ansi and traditional c compilers. */ #include <sys/stdarg.h> #ifdef DDB #include <ddb/db_output.h> /* db_printf, db_putchar prototypes */ #include <ddb/db_var.h> /* db_log, db_radix */ #endif /* * defines */ /* flags for kprintf */ #define TOCONS 0x01 /* to the console */ #define TOTTY 0x02 /* to the process' tty */ #define TOLOG 0x04 /* to the kernel message buffer */ #define TOBUFONLY 0x08 /* to the buffer (only) [for snprintf] */ #define TODDB 0x10 /* to ddb console */ #define TOCOUNT 0x20 /* act like [v]snprintf */ /* max size buffer kprintf needs to print quad_t [size in base 8 + \0] */ #define KPRINTF_BUFSIZE (sizeof(quad_t) * NBBY / 3 + 2) /* * local prototypes */ int kprintf(const char *, int, void *, char *, va_list); void kputchar(int, int, struct tty *); struct mutex kprintf_mutex = MUTEX_INITIALIZER_FLAGS(IPL_HIGH, "kprintf", MTX_NOWITNESS); /* * globals */ extern int log_open; /* subr_log: is /dev/klog open? */ const char *panicstr; /* arg to first call to panic (used as a flag to indicate that panic has already been called). */ #ifdef DDB /* * Enter ddb on panic. */ int db_panic = 1; /* * db_console controls if we can be able to enter ddb by a special key * combination (machine dependent). * If DDB_SAFE_CONSOLE is defined in the kernel configuration it allows * to break into console during boot. It's _really_ useful when debugging * some things in the kernel that can cause init(8) to crash. */ #ifdef DDB_SAFE_CONSOLE int db_console = 1; #else int db_console = 0; #endif #endif /* * panic on spl assertion failure? */ #ifdef SPLASSERT_WATCH int splassert_ctl = 3; #else int splassert_ctl = 1; #endif /* * v_putc: routine to putc on virtual console * * the v_putc pointer can be used to redirect the console cnputc elsewhere * [e.g. to a "virtual console"]. */ void (*v_putc)(int) = cnputc; /* start with cnputc (normal cons) */ /* * Silence kernel printf when masquerading as a bootloader. */ #ifdef BOOT_QUIET int printf_flags = TOLOG; #else int printf_flags = TOCONS | TOLOG; #endif /* * functions */ /* * Partial support (the failure case) of the assertion facility * commonly found in userland. */ void __assert(const char *t, const char *f, int l, const char *e) { panic(__KASSERTSTR, t, e, f, l); } /* * tablefull: warn that a system table is full */ void tablefull(const char *tab) { log(LOG_ERR, "%s: table is full\n", tab); } /* * If we have panicked, prefer db_printf() and db_vprintf() where * available. */ #ifdef DDB #define panic_printf(...) db_printf(__VA_ARGS__) #define panic_vprintf(...) db_vprintf(__VA_ARGS__) #else #define panic_printf(...) printf(__VA_ARGS__) #define panic_vprintf(...) vprintf(__VA_ARGS__) #endif /* * panic: handle an unresolvable fatal error * * prints "panic: <message>" and reboots. if called twice (i.e. recursive * call) we avoid trying to sync the disk and just reboot (to avoid * recursive panics). */ void panic(const char *fmt, ...) { struct cpu_info *ci = curcpu(); int bootopt; va_list ap; bootopt = RB_AUTOBOOT | RB_DUMP; if (atomic_cas_ptr(&panicstr, NULL, ci->ci_panicbuf) != NULL) bootopt |= RB_NOSYNC; /* do not trigger assertions, we know that we are inconsistent */ splassert_ctl = 0; #ifdef BOOT_QUIET printf_flags |= TOCONS; /* make sure we see kernel printf output */ #endif /* * All panic messages are printed, but only the first panic on a * given CPU is written to its panicbuf. */ if (ci->ci_panicbuf[0] == '\0') { va_start(ap, fmt); vsnprintf(ci->ci_panicbuf, sizeof(ci->ci_panicbuf), fmt, ap); va_end(ap); panic_printf("panic: %s\n", ci->ci_panicbuf); } else { panic_printf("panic: "); va_start(ap, fmt); panic_vprintf(fmt, ap); va_end(ap); panic_printf("\n"); } #ifdef DDB if (db_panic) db_enter(); else db_stack_dump(); #endif reboot(bootopt); /* NOTREACHED */ } /* * We print only the function name. The file name is usually very long and * would eat tons of space in the kernel. */ void splassert_fail(int wantipl, int haveipl, const char *func) { if (panicstr || db_active) return; printf("splassert: %s: want %d have %d\n", func, wantipl, haveipl); switch (splassert_ctl) { case 1: break; case 2: #ifdef DDB db_stack_dump(); #endif break; case 3: #ifdef DDB db_stack_dump(); db_enter(); #endif break; default: panic("spl assertion failure in %s", func); } } /* * kernel logging functions: log, logpri, addlog */ /* * log: write to the log buffer * * => will not sleep [so safe to call from interrupt] * => will log to console if /dev/klog isn't open */ void log(int level, const char *fmt, ...) { int s; va_list ap; s = splhigh(); logpri(level); /* log the level first */ va_start(ap, fmt); kprintf(fmt, TOLOG, NULL, NULL, ap); va_end(ap); splx(s); if (!log_open) { va_start(ap, fmt); mtx_enter(&kprintf_mutex); kprintf(fmt, TOCONS, NULL, NULL, ap); mtx_leave(&kprintf_mutex); va_end(ap); } logwakeup(); /* wake up anyone waiting for log msgs */ } /* * logpri: log the priority level to the klog */ void logpri(int level) { char *p; char snbuf[KPRINTF_BUFSIZE]; kputchar('<', TOLOG, NULL); snprintf(snbuf, sizeof snbuf, "%d", level); for (p = snbuf ; *p ; p++) kputchar(*p, TOLOG, NULL); kputchar('>', TOLOG, NULL); } /* * addlog: add info to previous log message */ int addlog(const char *fmt, ...) { int s; va_list ap; s = splhigh(); va_start(ap, fmt); kprintf(fmt, TOLOG, NULL, NULL, ap); va_end(ap); splx(s); if (!log_open) { va_start(ap, fmt); mtx_enter(&kprintf_mutex); kprintf(fmt, TOCONS, NULL, NULL, ap); mtx_leave(&kprintf_mutex); va_end(ap); } logwakeup(); return(0); } /* * kputchar: print a single character on console or user terminal. * * => if console, then the last MSGBUFS chars are saved in msgbuf * for inspection later (e.g. dmesg/syslog) */ void kputchar(int c, int flags, struct tty *tp) { extern int msgbufmapped; if (panicstr) constty = NULL; if ((flags & TOCONS) && tp == NULL && constty != NULL && !db_active) { tp = constty; flags |= TOTTY; } if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 && (flags & TOCONS) && tp == constty) constty = NULL; if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 && msgbufmapped) msgbuf_putchar(msgbufp, c); if ((flags & TOCONS) && (constty == NULL || db_active) && c != '\0') (*v_putc)(c); #ifdef DDB if (flags & TODDB) db_putchar(c); #endif } /* * uprintf: print to the controlling tty of the current process * * => we may block if the tty queue is full * => no message is printed if the queue doesn't clear in a reasonable * time */ void uprintf(const char *fmt, ...) { struct process *pr = curproc->p_p; va_list ap; if (pr->ps_flags & PS_CONTROLT && pr->ps_session->s_ttyvp) { va_start(ap, fmt); kprintf(fmt, TOTTY, pr->ps_session->s_ttyp, NULL, ap); va_end(ap); } } #if defined(NFSSERVER) || defined(NFSCLIENT) /* * tprintf functions: used to send messages to a specific process * * usage: * get a tpr_t handle on a process "p" by using "tprintf_open(p)" * use the handle when calling "tprintf" * when done, do a "tprintf_close" to drop the handle */ /* * tprintf_open: get a tprintf handle on a process "p" * XXX change s/proc/process * * => returns NULL if process can't be printed to */ tpr_t tprintf_open(struct proc *p) { struct process *pr = p->p_p; if (pr->ps_flags & PS_CONTROLT && pr->ps_session->s_ttyvp) { SESSHOLD(pr->ps_session); return ((tpr_t)pr->ps_session); } return ((tpr_t) NULL); } /* * tprintf_close: dispose of a tprintf handle obtained with tprintf_open */ void tprintf_close(tpr_t sess) { if (sess) SESSRELE((struct session *) sess); } /* * tprintf: given tprintf handle to a process [obtained with tprintf_open], * send a message to the controlling tty for that process. * * => also sends message to /dev/klog */ void tprintf(tpr_t tpr, const char *fmt, ...) { struct session *sess = (struct session *)tpr; struct tty *tp = NULL; int flags = TOLOG; va_list ap; logpri(LOG_INFO); if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) { flags |= TOTTY; tp = sess->s_ttyp; } va_start(ap, fmt); kprintf(fmt, flags, tp, NULL, ap); va_end(ap); logwakeup(); } #endif /* NFSSERVER || NFSCLIENT */ /* * ttyprintf: send a message to a specific tty * * => should be used only by tty driver or anything that knows the * underlying tty will not be revoked(2)'d away. [otherwise, * use tprintf] */ void ttyprintf(struct tty *tp, const char *fmt, ...) { va_list ap; va_start(ap, fmt); kprintf(fmt, TOTTY, tp, NULL, ap); va_end(ap); } #ifdef DDB /* * db_printf: printf for DDB (via db_putchar) */ int db_printf(const char *fmt, ...) { va_list ap; int retval; va_start(ap, fmt); retval = db_vprintf(fmt, ap); va_end(ap); return(retval); } int db_vprintf(const char *fmt, va_list ap) { int flags; flags = TODDB; if (db_log) flags |= TOLOG; return (kprintf(fmt, flags, NULL, NULL, ap)); } #endif /* DDB */ /* * normal kernel printf functions: printf, vprintf, snprintf */ /* * printf: print a message to the console and the log */ int printf(const char *fmt, ...) { va_list ap; int retval; va_start(ap, fmt); mtx_enter(&kprintf_mutex); retval = kprintf(fmt, printf_flags, NULL, NULL, ap); mtx_leave(&kprintf_mutex); va_end(ap); if (!panicstr) logwakeup(); return(retval); } /* * vprintf: print a message to the console and the log [already have a * va_list] */ int vprintf(const char *fmt, va_list ap) { int retval; mtx_enter(&kprintf_mutex); retval = kprintf(fmt, TOCONS | TOLOG, NULL, NULL, ap); mtx_leave(&kprintf_mutex); if (!panicstr) logwakeup(); return (retval); } /* * snprintf: print a message to a buffer */ int snprintf(char *buf, size_t size, const char *fmt, ...) { int retval; va_list ap; char *p; p = buf; if (size > 0) p += size - 1; va_start(ap, fmt); retval = kprintf(fmt, TOBUFONLY | TOCOUNT, &p, buf, ap); va_end(ap); if (size > 0) *p = '\0'; /* null terminate */ return(retval); } /* * vsnprintf: print a message to a buffer [already have va_alist] */ int vsnprintf(char *buf, size_t size, const char *fmt, va_list ap) { int retval; char *p; p = buf + size - 1; if (size < 1) p = buf; retval = kprintf(fmt, TOBUFONLY | TOCOUNT, &p, buf, ap); if (size > 0) *(p) = 0; /* null terminate */ return(retval); } /* * kprintf: scaled down version of printf(3). * * this version based on vfprintf() from libc which was derived from * software contributed to Berkeley by Chris Torek. * * The additional format %b is supported to decode error registers. * Its usage is: * * printf("reg=%b\n", regval, "<base><arg>*"); * * where <base> is the output base expressed as a control character, e.g. * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, * the first of which gives the bit number to be inspected (origin 1), and * the next characters (up to a control character, i.e. a character <= 32), * give the name of the register. Thus: * * kprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); * * would produce output: * * reg=3<BITTWO,BITONE> * * To support larger integers (> 32 bits), %b formatting will also accept * control characters in the region 0x80 - 0xff. 0x80 refers to bit 0, * 0x81 refers to bit 1, and so on. The equivalent string to the above is: * * kprintf("reg=%b\n", 3, "\10\201BITTWO\200BITONE\n"); * * and would produce the same output. * * Like the rest of printf, %b can be prefixed to handle various size * modifiers, eg. %b is for "int", %lb is for "long", and %llb supports * "long long". * * This code is large and complicated... */ /* * macros for converting digits to letters and vice versa */ #define to_digit(c) ((c) - '0') #define is_digit(c) ((unsigned)to_digit(c) <= 9) #define to_char(n) ((n) + '0') /* * flags used during conversion. */ #define ALT 0x001 /* alternate form */ #define HEXPREFIX 0x002 /* add 0x or 0X prefix */ #define LADJUST 0x004 /* left adjustment */ #define LONGDBL 0x008 /* long double; unimplemented */ #define LONGINT 0x010 /* long integer */ #define QUADINT 0x020 /* quad integer */ #define SHORTINT 0x040 /* short integer */ #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */ #define FPT 0x100 /* Floating point number */ #define SIZEINT 0x200 /* (signed) size_t */ /* * To extend shorts properly, we need both signed and unsigned * argument extraction methods. */ #define SARG() \ (flags&QUADINT ? va_arg(ap, quad_t) : \ flags&LONGINT ? va_arg(ap, long) : \ flags&SIZEINT ? va_arg(ap, ssize_t) : \ flags&SHORTINT ? (long)(short)va_arg(ap, int) : \ (long)va_arg(ap, int)) #define UARG() \ (flags&QUADINT ? va_arg(ap, u_quad_t) : \ flags&LONGINT ? va_arg(ap, u_long) : \ flags&SIZEINT ? va_arg(ap, size_t) : \ flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \ (u_long)va_arg(ap, u_int)) #define KPRINTF_PUTCHAR(C) do { \ int chr = (C); \ ret += 1; \ if (oflags & TOBUFONLY) { \ if ((vp != NULL) && (sbuf == tailp)) { \ if (!(oflags & TOCOUNT)) \ goto overflow; \ } else \ *sbuf++ = chr; \ } else { \ kputchar(chr, oflags, (struct tty *)vp); \ } \ } while(0) int kprintf(const char *fmt0, int oflags, void *vp, char *sbuf, va_list ap) { char *fmt; /* format string */ int ch; /* character from fmt */ int n; /* handy integer (short term usage) */ char *cp = NULL; /* handy char pointer (short term usage) */ int flags; /* flags as above */ int ret; /* return value accumulator */ int width; /* width from format (%8d), or 0 */ int prec; /* precision from format (%.3d), or -1 */ char sign; /* sign prefix (' ', '+', '-', or \0) */ u_quad_t _uquad; /* integer arguments %[diouxX] */ enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */ int dprec; /* a copy of prec if [diouxX], 0 otherwise */ int realsz; /* field size expanded by dprec */ int size = 0; /* size of converted field or string */ char *xdigs = NULL; /* digits for [xX] conversion */ char buf[KPRINTF_BUFSIZE]; /* space for %c, %[diouxX] */ char *tailp = NULL; /* tail pointer for snprintf */ if (oflags & TOCONS) MUTEX_ASSERT_LOCKED(&kprintf_mutex); if ((oflags & TOBUFONLY) && (vp != NULL)) tailp = *(char **)vp; fmt = (char *)fmt0; ret = 0; /* * Scan the format for conversions (`%' character). */ for (;;) { while (*fmt != '%' && *fmt) { KPRINTF_PUTCHAR(*fmt++); } if (*fmt == 0) goto done; fmt++; /* skip over '%' */ flags = 0; dprec = 0; width = 0; prec = -1; sign = '\0'; rflag: ch = *fmt++; reswitch: switch (ch) { /* XXX: non-standard '%b' format */ case 'b': { char *b, *z; int tmp; _uquad = UARG(); b = va_arg(ap, char *); if (*b == 8) snprintf(buf, sizeof buf, "%llo", _uquad); else if (*b == 10) snprintf(buf, sizeof buf, "%lld", _uquad); else if (*b == 16) snprintf(buf, sizeof buf, "%llx", _uquad); else break; b++; z = buf; while (*z) { KPRINTF_PUTCHAR(*z++); } if (_uquad) { tmp = 0; while ((n = *b++) != 0) { if (n & 0x80) n &= 0x7f; else if (n <= ' ') n = n - 1; if (_uquad & (1LL << n)) { KPRINTF_PUTCHAR(tmp ? ',':'<'); while (*b > ' ' && (*b & 0x80) == 0) { KPRINTF_PUTCHAR(*b); b++; } tmp = 1; } else { while (*b > ' ' && (*b & 0x80) == 0) b++; } } if (tmp) { KPRINTF_PUTCHAR('>'); } } continue; /* no output */ } case ' ': /* * ``If the space and + flags both appear, the space * flag will be ignored.'' * -- ANSI X3J11 */ if (!sign) sign = ' '; goto rflag; case '#': flags |= ALT; goto rflag; case '*': /* * ``A negative field width argument is taken as a * - flag followed by a positive field width.'' * -- ANSI X3J11 * They don't exclude field widths read from args. */ if ((width = va_arg(ap, int)) >= 0) goto rflag; width = -width; /* FALLTHROUGH */ case '-': flags |= LADJUST; goto rflag; case '+': sign = '+'; goto rflag; case '.': if ((ch = *fmt++) == '*') { n = va_arg(ap, int); prec = n < 0 ? -1 : n; goto rflag; } n = 0; while (is_digit(ch)) { n = 10 * n + to_digit(ch); ch = *fmt++; } prec = n < 0 ? -1 : n; goto reswitch; case '0': /* * ``Note that 0 is taken as a flag, not as the * beginning of a field width.'' * -- ANSI X3J11 */ flags |= ZEROPAD; goto rflag; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': n = 0; do { n = 10 * n + to_digit(ch); ch = *fmt++; } while (is_digit(ch)); width = n; goto reswitch; case 'h': flags |= SHORTINT; goto rflag; case 'l': if (*fmt == 'l') { fmt++; flags |= QUADINT; } else { flags |= LONGINT; } goto rflag; case 'q': flags |= QUADINT; goto rflag; case 'z': flags |= SIZEINT; goto rflag; case 'c': *(cp = buf) = va_arg(ap, int); size = 1; sign = '\0'; break; case 't': /* ptrdiff_t */ /* FALLTHROUGH */ case 'D': flags |= LONGINT; /*FALLTHROUGH*/ case 'd': case 'i': _uquad = SARG(); if ((quad_t)_uquad < 0) { _uquad = -_uquad; sign = '-'; } base = DEC; goto number; case 'n': panic("no %%n support"); break; case 'O': flags |= LONGINT; /*FALLTHROUGH*/ case 'o': _uquad = UARG(); base = OCT; goto nosign; case 'p': /* * ``The argument shall be a pointer to void. The * value of the pointer is converted to a sequence * of printable characters, in an implementation- * defined manner.'' * -- ANSI X3J11 */ _uquad = (u_long)va_arg(ap, void *); base = HEX; xdigs = "0123456789abcdef"; flags |= HEXPREFIX; ch = 'x'; goto nosign; case 's': if ((cp = va_arg(ap, char *)) == NULL) cp = "(null)"; if (prec >= 0) { /* * can't use strlen; can only look for the * NUL in the first `prec' characters, and * strlen() will go further. */ char *p = memchr(cp, 0, prec); if (p != NULL) { size = p - cp; if (size > prec) size = prec; } else size = prec; } else size = strlen(cp); sign = '\0'; break; case 'U': flags |= LONGINT; /*FALLTHROUGH*/ case 'u': _uquad = UARG(); base = DEC; goto nosign; case 'X': xdigs = "0123456789ABCDEF"; goto hex; case 'x': xdigs = "0123456789abcdef"; hex: _uquad = UARG(); base = HEX; /* leading 0x/X only if non-zero */ if (flags & ALT && _uquad != 0) flags |= HEXPREFIX; /* unsigned conversions */ nosign: sign = '\0'; /* * ``... diouXx conversions ... if a precision is * specified, the 0 flag will be ignored.'' * -- ANSI X3J11 */ number: if ((dprec = prec) >= 0) flags &= ~ZEROPAD; /* * ``The result of converting a zero value with an * explicit precision of zero is no characters.'' * -- ANSI X3J11 */ cp = buf + KPRINTF_BUFSIZE; if (_uquad != 0 || prec != 0) { /* * Unsigned mod is hard, and unsigned mod * by a constant is easier than that by * a variable; hence this switch. */ switch (base) { case OCT: do { *--cp = to_char(_uquad & 7); _uquad >>= 3; } while (_uquad); /* handle octal leading 0 */ if (flags & ALT && *cp != '0') *--cp = '0'; break; case DEC: /* many numbers are 1 digit */ while (_uquad >= 10) { *--cp = to_char(_uquad % 10); _uquad /= 10; } *--cp = to_char(_uquad); break; case HEX: do { *--cp = xdigs[_uquad & 15]; _uquad >>= 4; } while (_uquad); break; default: cp = "bug in kprintf: bad base"; size = strlen(cp); goto skipsize; } } size = buf + KPRINTF_BUFSIZE - cp; skipsize: break; default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') goto done; /* pretend it was %c with argument ch */ cp = buf; *cp = ch; size = 1; sign = '\0'; break; } /* * All reasonable formats wind up here. At this point, `cp' * points to a string which (if not flags&LADJUST) should be * padded out to `width' places. If flags&ZEROPAD, it should * first be prefixed by any sign or other prefix; otherwise, * it should be blank padded before the prefix is emitted. * After any left-hand padding and prefixing, emit zeroes * required by a decimal [diouxX] precision, then print the * string proper, then emit zeroes required by any leftover * floating precision; finally, if LADJUST, pad with blanks. * * Compute actual size, so we know how much to pad. * size excludes decimal prec; realsz includes it. */ realsz = dprec > size ? dprec : size; if (sign) realsz++; else if (flags & HEXPREFIX) realsz+= 2; /* right-adjusting blank padding */ if ((flags & (LADJUST|ZEROPAD)) == 0) { n = width - realsz; while (n-- > 0) KPRINTF_PUTCHAR(' '); } /* prefix */ if (sign) { KPRINTF_PUTCHAR(sign); } else if (flags & HEXPREFIX) { KPRINTF_PUTCHAR('0'); KPRINTF_PUTCHAR(ch); } /* right-adjusting zero padding */ if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) { n = width - realsz; while (n-- > 0) KPRINTF_PUTCHAR('0'); } /* leading zeroes from decimal precision */ n = dprec - size; while (n-- > 0) KPRINTF_PUTCHAR('0'); /* the string or number proper */ while (size--) KPRINTF_PUTCHAR(*cp++); /* left-adjusting padding (always blank) */ if (flags & LADJUST) { n = width - realsz; while (n-- > 0) KPRINTF_PUTCHAR(' '); } } done: if ((oflags & TOBUFONLY) && (vp != NULL)) *(char **)vp = sbuf; overflow: return (ret); /* NOTREACHED */ } #if __GNUC_PREREQ__(2,96) /* * XXX - these functions shouldn't be in the kernel, but gcc 3.X feels like * translating some printf calls to puts and since it doesn't seem * possible to just turn off parts of those optimizations (some of * them are really useful), we have to provide a dummy puts and putchar * that are wrappers around printf. */ int puts(const char *); int putchar(int c); int puts(const char *str) { printf("%s\n", str); return (0); } int putchar(int c) { printf("%c", c); return (c); } #endif
5 2 2 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 /* $OpenBSD: if_etherip.c,v 1.55 2024/02/13 12:22:09 bluhm Exp $ */ /* * Copyright (c) 2015 Kazuya GODA <goda@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "bpfilter.h" #include "pf.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <sys/device.h> #include <sys/sysctl.h> #include <sys/tree.h> #include <net/if.h> #include <net/if_var.h> #include <net/if_dl.h> #include <net/if_media.h> #include <net/route.h> #include <net/rtable.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_var.h> #include <netinet/if_ether.h> #include <netinet/ip_ether.h> #ifdef INET6 #include <netinet/ip6.h> #include <netinet6/ip6_var.h> #endif #if NBPFILTER > 0 #include <net/bpf.h> #endif #if NPF > 0 #include <net/pfvar.h> #endif #include <net/if_etherip.h> union etherip_addr { struct in_addr in4; struct in6_addr in6; }; struct etherip_tunnel { union etherip_addr _t_src; #define t_src4 _t_src.in4 #define t_src6 _t_src.in6 union etherip_addr _t_dst; #define t_dst4 _t_dst.in4 #define t_dst6 _t_dst.in6 unsigned int t_rtableid; sa_family_t t_af; uint8_t t_tos; TAILQ_ENTRY(etherip_tunnel) t_entry; }; TAILQ_HEAD(etherip_list, etherip_tunnel); static inline int etherip_cmp(const struct etherip_tunnel *, const struct etherip_tunnel *); struct etherip_softc { struct etherip_tunnel sc_tunnel; /* must be first */ struct arpcom sc_ac; struct ifmedia sc_media; int sc_txhprio; int sc_rxhprio; uint16_t sc_df; uint8_t sc_ttl; }; /* * We can control the acceptance of EtherIP packets by altering the sysctl * net.inet.etherip.allow value. Zero means drop them, all else is acceptance. */ int etherip_allow = 0; struct cpumem *etheripcounters; void etheripattach(int); int etherip_clone_create(struct if_clone *, int); int etherip_clone_destroy(struct ifnet *); int etherip_ioctl(struct ifnet *, u_long, caddr_t); int etherip_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); void etherip_start(struct ifnet *); int etherip_media_change(struct ifnet *); void etherip_media_status(struct ifnet *, struct ifmediareq *); int etherip_set_tunnel(struct etherip_softc *, struct if_laddrreq *); int etherip_get_tunnel(struct etherip_softc *, struct if_laddrreq *); int etherip_del_tunnel(struct etherip_softc *); int etherip_up(struct etherip_softc *); int etherip_down(struct etherip_softc *); struct etherip_softc *etherip_find(const struct etherip_tunnel *); int etherip_input(struct etherip_tunnel *, struct mbuf *, uint8_t, int); struct if_clone etherip_cloner = IF_CLONE_INITIALIZER("etherip", etherip_clone_create, etherip_clone_destroy); struct etherip_list etherip_list = TAILQ_HEAD_INITIALIZER(etherip_list); void etheripattach(int count) { if_clone_attach(&etherip_cloner); etheripcounters = counters_alloc(etherips_ncounters); } int etherip_clone_create(struct if_clone *ifc, int unit) { struct ifnet *ifp; struct etherip_softc *sc; sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); ifp = &sc->sc_ac.ac_if; snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d", ifc->ifc_name, unit); sc->sc_ttl = ip_defttl; sc->sc_txhprio = IFQ_TOS2PRIO(IPTOS_PREC_ROUTINE); /* 0 */ sc->sc_rxhprio = IF_HDRPRIO_PACKET; sc->sc_df = htons(0); ifp->if_softc = sc; ifp->if_hardmtu = ETHER_MAX_HARDMTU_LEN; ifp->if_ioctl = etherip_ioctl; ifp->if_output = etherip_output; ifp->if_start = etherip_start; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_xflags = IFXF_CLONED; ifp->if_capabilities = IFCAP_VLAN_MTU; ether_fakeaddr(ifp); ifmedia_init(&sc->sc_media, 0, etherip_media_change, etherip_media_status); ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL); ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO); if_counters_alloc(ifp); if_attach(ifp); ether_ifattach(ifp); NET_LOCK(); TAILQ_INSERT_TAIL(&etherip_list, &sc->sc_tunnel, t_entry); NET_UNLOCK(); return (0); } int etherip_clone_destroy(struct ifnet *ifp) { struct etherip_softc *sc = ifp->if_softc; NET_LOCK(); if (ISSET(ifp->if_flags, IFF_RUNNING)) etherip_down(sc); TAILQ_REMOVE(&etherip_list, &sc->sc_tunnel, t_entry); NET_UNLOCK(); ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY); ether_ifdetach(ifp); if_detach(ifp); free(sc, M_DEVBUF, sizeof(*sc)); return (0); } int etherip_media_change(struct ifnet *ifp) { return 0; } void etherip_media_status(struct ifnet *ifp, struct ifmediareq *imr) { imr->ifm_active = IFM_ETHER | IFM_AUTO; imr->ifm_status = IFM_AVALID | IFM_ACTIVE; } int etherip_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) { struct m_tag *mtag; mtag = NULL; while ((mtag = m_tag_find(m, PACKET_TAG_GRE, mtag)) != NULL) { if (*(int *)(mtag + 1) == ifp->if_index) { m_freem(m); return (EIO); } } return (ether_output(ifp, m, dst, rt)); } void etherip_start(struct ifnet *ifp) { struct etherip_softc *sc = ifp->if_softc; struct mbuf *m; int error; #if NBPFILTER > 0 caddr_t if_bpf; #endif while ((m = ifq_dequeue(&ifp->if_snd)) != NULL) { #if NBPFILTER > 0 if_bpf = ifp->if_bpf; if (if_bpf) bpf_mtap_ether(if_bpf, m, BPF_DIRECTION_OUT); #endif switch (sc->sc_tunnel.t_af) { case AF_INET: error = ip_etherip_output(ifp, m); break; #ifdef INET6 case AF_INET6: error = ip6_etherip_output(ifp, m); break; #endif default: /* unhandled_af(sc->sc_tunnel.t_af); */ m_freem(m); continue; } if (error) ifp->if_oerrors++; } } int etherip_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct etherip_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *)data; int error = 0; switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; /* FALLTHROUGH */ case SIOCSIFFLAGS: if (ISSET(ifp->if_flags, IFF_UP)) { if (!ISSET(ifp->if_flags, IFF_RUNNING)) error = etherip_up(sc); else error = 0; } else { if (ISSET(ifp->if_flags, IFF_RUNNING)) error = etherip_down(sc); } break; case SIOCSLIFPHYRTABLE: if (ifr->ifr_rdomainid < 0 || ifr->ifr_rdomainid > RT_TABLEID_MAX || !rtable_exists(ifr->ifr_rdomainid)) { error = EINVAL; break; } sc->sc_tunnel.t_rtableid = ifr->ifr_rdomainid; break; case SIOCGLIFPHYRTABLE: ifr->ifr_rdomainid = sc->sc_tunnel.t_rtableid; break; case SIOCSLIFPHYADDR: error = etherip_set_tunnel(sc, (struct if_laddrreq *)data); break; case SIOCGLIFPHYADDR: error = etherip_get_tunnel(sc, (struct if_laddrreq *)data); break; case SIOCDIFPHYADDR: error = etherip_del_tunnel(sc); break; case SIOCSTXHPRIO: error = if_txhprio_l2_check(ifr->ifr_hdrprio); if (error != 0) break; sc->sc_txhprio = ifr->ifr_hdrprio; break; case SIOCGTXHPRIO: ifr->ifr_hdrprio = sc->sc_txhprio; break; case SIOCSRXHPRIO: error = if_rxhprio_l2_check(ifr->ifr_hdrprio); if (error != 0) break; sc->sc_rxhprio = ifr->ifr_hdrprio; break; case SIOCGRXHPRIO: ifr->ifr_hdrprio = sc->sc_rxhprio; break; case SIOCSLIFPHYTTL: if (ifr->ifr_ttl < 1 || ifr->ifr_ttl > 0xff) { error = EINVAL; break; } /* commit */ sc->sc_ttl = (uint8_t)ifr->ifr_ttl; break; case SIOCGLIFPHYTTL: ifr->ifr_ttl = (int)sc->sc_ttl; break; case SIOCSLIFPHYDF: /* commit */ sc->sc_df = ifr->ifr_df ? htons(IP_DF) : htons(0); break; case SIOCGLIFPHYDF: ifr->ifr_df = sc->sc_df ? 1 : 0; break; case SIOCSIFMEDIA: case SIOCGIFMEDIA: error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); break; case SIOCADDMULTI: case SIOCDELMULTI: break; default: error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); break; } if (error == ENETRESET) { /* no hardware to program */ error = 0; } return (error); } int etherip_set_tunnel(struct etherip_softc *sc, struct if_laddrreq *req) { struct sockaddr *src = (struct sockaddr *)&req->addr; struct sockaddr *dst = (struct sockaddr *)&req->dstaddr; struct sockaddr_in *src4, *dst4; #ifdef INET6 struct sockaddr_in6 *src6, *dst6; int error; #endif /* sa_family and sa_len must be equal */ if (src->sa_family != dst->sa_family || src->sa_len != dst->sa_len) return (EINVAL); /* validate */ switch (dst->sa_family) { case AF_INET: if (dst->sa_len != sizeof(*dst4)) return (EINVAL); src4 = (struct sockaddr_in *)src; if (in_nullhost(src4->sin_addr) || IN_MULTICAST(src4->sin_addr.s_addr)) return (EINVAL); dst4 = (struct sockaddr_in *)dst; if (in_nullhost(dst4->sin_addr) || IN_MULTICAST(dst4->sin_addr.s_addr)) return (EINVAL); sc->sc_tunnel.t_src4 = src4->sin_addr; sc->sc_tunnel.t_dst4 = dst4->sin_addr; break; #ifdef INET6 case AF_INET6: if (dst->sa_len != sizeof(*dst6)) return (EINVAL); src6 = (struct sockaddr_in6 *)src; if (IN6_IS_ADDR_UNSPECIFIED(&src6->sin6_addr) || IN6_IS_ADDR_MULTICAST(&src6->sin6_addr)) return (EINVAL); dst6 = (struct sockaddr_in6 *)dst; if (IN6_IS_ADDR_UNSPECIFIED(&dst6->sin6_addr) || IN6_IS_ADDR_MULTICAST(&dst6->sin6_addr)) return (EINVAL); error = in6_embedscope(&sc->sc_tunnel.t_src6, src6, NULL, NULL); if (error != 0) return (error); error = in6_embedscope(&sc->sc_tunnel.t_dst6, dst6, NULL, NULL); if (error != 0) return (error); break; #endif default: return (EAFNOSUPPORT); } /* commit */ sc->sc_tunnel.t_af = dst->sa_family; return (0); } int etherip_get_tunnel(struct etherip_softc *sc, struct if_laddrreq *req) { struct sockaddr *src = (struct sockaddr *)&req->addr; struct sockaddr *dst = (struct sockaddr *)&req->dstaddr; struct sockaddr_in *sin; #ifdef INET6 /* ifconfig already embeds the scopeid */ struct sockaddr_in6 *sin6; #endif switch (sc->sc_tunnel.t_af) { case AF_UNSPEC: return (EADDRNOTAVAIL); case AF_INET: sin = (struct sockaddr_in *)src; memset(sin, 0, sizeof(*sin)); sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); sin->sin_addr = sc->sc_tunnel.t_src4; sin = (struct sockaddr_in *)dst; memset(sin, 0, sizeof(*sin)); sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); sin->sin_addr = sc->sc_tunnel.t_dst4; break; #ifdef INET6 case AF_INET6: sin6 = (struct sockaddr_in6 *)src; memset(sin6, 0, sizeof(*sin6)); sin6->sin6_family = AF_INET6; sin6->sin6_len = sizeof(*sin6); in6_recoverscope(sin6, &sc->sc_tunnel.t_src6); sin6 = (struct sockaddr_in6 *)dst; memset(sin6, 0, sizeof(*sin6)); sin6->sin6_family = AF_INET6; sin6->sin6_len = sizeof(*sin6); in6_recoverscope(sin6, &sc->sc_tunnel.t_dst6); break; #endif default: return (EAFNOSUPPORT); } return (0); } int etherip_del_tunnel(struct etherip_softc *sc) { /* commit */ sc->sc_tunnel.t_af = AF_UNSPEC; return (0); } int etherip_up(struct etherip_softc *sc) { struct ifnet *ifp = &sc->sc_ac.ac_if; NET_ASSERT_LOCKED(); SET(ifp->if_flags, IFF_RUNNING); return (0); } int etherip_down(struct etherip_softc *sc) { struct ifnet *ifp = &sc->sc_ac.ac_if; NET_ASSERT_LOCKED(); CLR(ifp->if_flags, IFF_RUNNING); return (0); } int ip_etherip_output(struct ifnet *ifp, struct mbuf *m) { struct etherip_softc *sc = (struct etherip_softc *)ifp->if_softc; struct m_tag *mtag; struct etherip_header *eip; struct ip *ip; M_PREPEND(m, sizeof(*ip) + sizeof(*eip), M_DONTWAIT); if (m == NULL) { etheripstat_inc(etherips_adrops); return ENOBUFS; } ip = mtod(m, struct ip *); memset(ip, 0, sizeof(struct ip)); ip->ip_v = IPVERSION; ip->ip_hl = sizeof(*ip) >> 2; ip->ip_tos = IFQ_PRIO2TOS(sc->sc_txhprio == IF_HDRPRIO_PACKET ? m->m_pkthdr.pf.prio : sc->sc_txhprio); ip->ip_len = htons(m->m_pkthdr.len); ip->ip_id = htons(ip_randomid()); ip->ip_off = sc->sc_df; ip->ip_ttl = sc->sc_ttl; ip->ip_p = IPPROTO_ETHERIP; ip->ip_src = sc->sc_tunnel.t_src4; ip->ip_dst = sc->sc_tunnel.t_dst4; eip = (struct etherip_header *)(ip + 1); eip->eip_ver = ETHERIP_VERSION; eip->eip_res = 0; eip->eip_pad = 0; mtag = m_tag_get(PACKET_TAG_GRE, sizeof(ifp->if_index), M_NOWAIT); if (mtag == NULL) { m_freem(m); return (ENOMEM); } *(int *)(mtag + 1) = ifp->if_index; m_tag_prepend(m, mtag); m->m_flags &= ~(M_BCAST|M_MCAST); m->m_pkthdr.ph_rtableid = sc->sc_tunnel.t_rtableid; #if NPF > 0 pf_pkt_addr_changed(m); #endif etheripstat_pkt(etherips_opackets, etherips_obytes, m->m_pkthdr.len - (sizeof(struct ip) + sizeof(struct etherip_header))); ip_send(m); return (0); } int ip_etherip_input(struct mbuf **mp, int *offp, int type, int af) { struct mbuf *m = *mp; struct etherip_tunnel key; struct ip *ip; ip = mtod(m, struct ip *); key.t_af = AF_INET; key.t_src4 = ip->ip_dst; key.t_dst4 = ip->ip_src; return (etherip_input(&key, m, ip->ip_tos, *offp)); } struct etherip_softc * etherip_find(const struct etherip_tunnel *key) { struct etherip_tunnel *t; struct etherip_softc *sc; TAILQ_FOREACH(t, &etherip_list, t_entry) { if (etherip_cmp(key, t) != 0) continue; sc = (struct etherip_softc *)t; if (!ISSET(sc->sc_ac.ac_if.if_flags, IFF_RUNNING)) continue; return (sc); } return (NULL); } int etherip_input(struct etherip_tunnel *key, struct mbuf *m, uint8_t tos, int hlen) { struct etherip_softc *sc; struct ifnet *ifp; struct etherip_header *eip; int rxprio; if (!etherip_allow && (m->m_flags & (M_AUTH|M_CONF)) == 0) { etheripstat_inc(etherips_pdrops); goto drop; } key->t_rtableid = m->m_pkthdr.ph_rtableid; NET_ASSERT_LOCKED(); sc = etherip_find(key); if (sc == NULL) { etheripstat_inc(etherips_noifdrops); goto drop; } m_adj(m, hlen); m = m_pullup(m, sizeof(*eip)); if (m == NULL) { etheripstat_inc(etherips_adrops); return IPPROTO_DONE; } eip = mtod(m, struct etherip_header *); if (eip->eip_ver != ETHERIP_VERSION || eip->eip_pad) { etheripstat_inc(etherips_adrops); goto drop; } m_adj(m, sizeof(struct etherip_header)); etheripstat_pkt(etherips_ipackets, etherips_ibytes, m->m_pkthdr.len); m = m_pullup(m, sizeof(struct ether_header)); if (m == NULL) { etheripstat_inc(etherips_adrops); return IPPROTO_DONE; } rxprio = sc->sc_rxhprio; switch (rxprio) { case IF_HDRPRIO_PACKET: break; case IF_HDRPRIO_OUTER: m->m_pkthdr.pf.prio = IFQ_TOS2PRIO(tos); break; default: m->m_pkthdr.pf.prio = rxprio; break; } ifp = &sc->sc_ac.ac_if; m->m_flags &= ~(M_BCAST|M_MCAST); m->m_pkthdr.ph_ifidx = ifp->if_index; m->m_pkthdr.ph_rtableid = ifp->if_rdomain; #if NPF > 0 pf_pkt_addr_changed(m); #endif if_vinput(ifp, m); return IPPROTO_DONE; drop: m_freem(m); return (IPPROTO_DONE); } #ifdef INET6 int ip6_etherip_output(struct ifnet *ifp, struct mbuf *m) { struct etherip_softc *sc = ifp->if_softc; struct m_tag *mtag; struct ip6_hdr *ip6; struct etherip_header *eip; uint16_t len; uint32_t flow; if (IN6_IS_ADDR_UNSPECIFIED(&sc->sc_tunnel.t_dst6)) { m_freem(m); return (ENETUNREACH); } len = m->m_pkthdr.len; M_PREPEND(m, sizeof(*ip6) + sizeof(*eip), M_DONTWAIT); if (m == NULL) { etheripstat_inc(etherips_adrops); return ENOBUFS; } flow = IPV6_VERSION << 24; flow |= IFQ_PRIO2TOS(sc->sc_txhprio == IF_HDRPRIO_PACKET ? m->m_pkthdr.pf.prio : sc->sc_txhprio) << 20; ip6 = mtod(m, struct ip6_hdr *); htobem32(&ip6->ip6_flow, flow); ip6->ip6_nxt = IPPROTO_ETHERIP; ip6->ip6_hlim = sc->sc_ttl; ip6->ip6_plen = htons(len); memcpy(&ip6->ip6_src, &sc->sc_tunnel.t_src6, sizeof(ip6->ip6_src)); memcpy(&ip6->ip6_dst, &sc->sc_tunnel.t_dst6, sizeof(ip6->ip6_dst)); eip = (struct etherip_header *)(ip6 + 1); eip->eip_ver = ETHERIP_VERSION; eip->eip_res = 0; eip->eip_pad = 0; mtag = m_tag_get(PACKET_TAG_GRE, sizeof(ifp->if_index), M_NOWAIT); if (mtag == NULL) { m_freem(m); return (ENOMEM); } *(int *)(mtag + 1) = ifp->if_index; m_tag_prepend(m, mtag); if (sc->sc_df) SET(m->m_pkthdr.csum_flags, M_IPV6_DF_OUT); m->m_flags &= ~(M_BCAST|M_MCAST); m->m_pkthdr.ph_rtableid = sc->sc_tunnel.t_rtableid; #if NPF > 0 pf_pkt_addr_changed(m); #endif etheripstat_pkt(etherips_opackets, etherips_obytes, len); ip6_send(m); return (0); } int ip6_etherip_input(struct mbuf **mp, int *offp, int proto, int af) { struct mbuf *m = *mp; struct etherip_tunnel key; const struct ip6_hdr *ip6; uint32_t flow; ip6 = mtod(m, const struct ip6_hdr *); key.t_af = AF_INET6; key.t_src6 = ip6->ip6_dst; key.t_dst6 = ip6->ip6_src; flow = bemtoh32(&ip6->ip6_flow); return (etherip_input(&key, m, flow >> 20, *offp)); } #endif /* INET6 */ int etherip_sysctl_etheripstat(void *oldp, size_t *oldlenp, void *newp) { struct etheripstat etheripstat; CTASSERT(sizeof(etheripstat) == (etherips_ncounters * sizeof(uint64_t))); memset(&etheripstat, 0, sizeof etheripstat); counters_read(etheripcounters, (uint64_t *)&etheripstat, etherips_ncounters, NULL); return (sysctl_rdstruct(oldp, oldlenp, newp, &etheripstat, sizeof(etheripstat))); } int etherip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int error; /* All sysctl names at this level are terminal. */ if (namelen != 1) return ENOTDIR; switch (name[0]) { case ETHERIPCTL_ALLOW: NET_LOCK(); error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &etherip_allow, 0, 1); NET_UNLOCK(); return (error); case ETHERIPCTL_STATS: return (etherip_sysctl_etheripstat(oldp, oldlenp, newp)); default: break; } return ENOPROTOOPT; } static inline int etherip_ip_cmp(int af, const union etherip_addr *a, const union etherip_addr *b) { switch (af) { #ifdef INET6 case AF_INET6: return (memcmp(&a->in6, &b->in6, sizeof(a->in6))); /* FALLTHROUGH */ #endif /* INET6 */ case AF_INET: return (memcmp(&a->in4, &b->in4, sizeof(a->in4))); break; default: panic("%s: unsupported af %d", __func__, af); } return (0); } static inline int etherip_cmp(const struct etherip_tunnel *a, const struct etherip_tunnel *b) { int rv; if (a->t_rtableid > b->t_rtableid) return (1); if (a->t_rtableid < b->t_rtableid) return (-1); /* sort by address */ if (a->t_af > b->t_af) return (1); if (a->t_af < b->t_af) return (-1); rv = etherip_ip_cmp(a->t_af, &a->_t_dst, &b->_t_dst); if (rv != 0) return (rv); rv = etherip_ip_cmp(a->t_af, &a->_t_src, &b->_t_src); if (rv != 0) return (rv); return (0); }
1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 /* $OpenBSD: ulpt.c,v 1.59 2024/05/13 01:15:53 jsg Exp $ */ /* $NetBSD: ulpt.c,v 1.57 2003/01/05 10:19:42 scw Exp $ */ /* $FreeBSD: src/sys/dev/usb/ulpt.c,v 1.24 1999/11/17 22:33:44 n_hibma Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Lennart Augustsson (lennart@augustsson.net) at * Carlstedt Research & Technology. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Printer Class spec: * https://www.usb.org/sites/default/files/usbprint11a021811.pdf */ #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> #include <sys/uio.h> #include <sys/conf.h> #include <sys/vnode.h> #include <sys/syslog.h> #include <sys/malloc.h> #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> #include <dev/usb/usbdi_util.h> #include <dev/usb/usbdevs.h> #include <dev/usb/usb_quirks.h> #define LPTPRI (PZERO+8) #define ULPT_BSIZE 16384 #ifdef ULPT_DEBUG #define DPRINTF(x) do { if (ulptdebug) printf x; } while (0) #define DPRINTFN(n,x) do { if (ulptdebug>(n)) printf x; } while (0) int ulptdebug = 0; #else #define DPRINTF(x) #define DPRINTFN(n,x) #endif #define UR_GET_DEVICE_ID 0 #define UR_GET_PORT_STATUS 1 #define UR_SOFT_RESET 2 #define LPS_NERR 0x08 /* printer no error */ #define LPS_SELECT 0x10 /* printer selected */ #define LPS_NOPAPER 0x20 /* printer out of paper */ #define LPS_INVERT (LPS_SELECT|LPS_NERR) #define LPS_MASK (LPS_SELECT|LPS_NERR|LPS_NOPAPER) struct ulpt_softc { struct device sc_dev; struct usbd_device *sc_udev; /* device */ struct usbd_interface *sc_iface;/* interface */ int sc_ifaceno; int sc_out; struct usbd_pipe *sc_out_pipe; /* bulk out pipe */ int sc_in; struct usbd_pipe *sc_in_pipe; /* bulk in pipe */ struct usbd_xfer *sc_in_xfer1; struct usbd_xfer *sc_in_xfer2; u_char sc_junk[64]; /* somewhere to dump input */ u_char sc_state; #define ULPT_OPEN 0x01 /* device is open */ #define ULPT_OBUSY 0x02 /* printer is busy doing output */ #define ULPT_INIT 0x04 /* waiting to initialize for open */ u_char sc_flags; #define ULPT_NOPRIME 0x40 /* don't prime on open */ #define ULPT_EFIRMWARE 0x80 /* error loading firmware */ u_char sc_laststatus; int sc_refcnt; struct ulpt_fwdev *sc_fwdev; }; int ulpt_do_write(struct ulpt_softc *, struct uio *uio, int); int ulpt_status(struct ulpt_softc *); void ulpt_reset(struct ulpt_softc *); int ulpt_statusmsg(u_char, struct ulpt_softc *); /* * Printers which need firmware uploads. */ void ulpt_load_firmware(struct device *); usbd_status ulpt_ucode_loader_hp(struct ulpt_softc *); struct ulpt_fwdev { struct usb_devno uv_dev; char *ucode_name; usbd_status (*ucode_loader)(struct ulpt_softc *); } ulpt_fwdevs[] = { { { USB_VENDOR_HP, USB_PRODUCT_HP_1000 }, "ulpt-hp1000", ulpt_ucode_loader_hp }, { { USB_VENDOR_HP, USB_PRODUCT_HP_1005 }, "ulpt-hp1005", ulpt_ucode_loader_hp }, { { USB_VENDOR_HP, USB_PRODUCT_HP_1018 }, "ulpt-hp1018", ulpt_ucode_loader_hp }, { { USB_VENDOR_HP, USB_PRODUCT_HP_1020 }, "ulpt-hp1020", ulpt_ucode_loader_hp }, }; #if 0 void ieee1284_print_id(char *); #endif #define ULPTUNIT(s) (minor(s) & 0x1f) #define ULPTFLAGS(s) (minor(s) & 0xe0) int ulpt_match(struct device *, void *, void *); void ulpt_attach(struct device *, struct device *, void *); int ulpt_detach(struct device *, int); struct cfdriver ulpt_cd = { NULL, "ulpt", DV_DULL }; const struct cfattach ulpt_ca = { sizeof(struct ulpt_softc), ulpt_match, ulpt_attach, ulpt_detach }; int ulpt_match(struct device *parent, void *match, void *aux) { struct usb_attach_arg *uaa = aux; usb_interface_descriptor_t *id; DPRINTFN(10,("ulpt_match\n")); if (uaa->iface == NULL) return (UMATCH_NONE); id = usbd_get_interface_descriptor(uaa->iface); if (id != NULL && id->bInterfaceClass == UICLASS_PRINTER && id->bInterfaceSubClass == UISUBCLASS_PRINTER && ((id->bInterfaceProtocol == UIPROTO_PRINTER_UNI) || (id->bInterfaceProtocol == UIPROTO_PRINTER_BI) || (id->bInterfaceProtocol == UIPROTO_PRINTER_1284))) return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO); return (UMATCH_NONE); } void ulpt_load_firmware(struct device *self) { struct ulpt_softc *sc = (struct ulpt_softc *)self; usbd_status err; err = (sc->sc_fwdev->ucode_loader)(sc); if (err != USBD_NORMAL_COMPLETION) { sc->sc_flags |= ULPT_EFIRMWARE; printf("%s: could not load firmware '%s'\n", sc->sc_dev.dv_xname, sc->sc_fwdev->ucode_name); } else sc->sc_flags &= ~ULPT_EFIRMWARE; } #define ulpt_lookup(v, p) \ ((struct ulpt_fwdev *)usb_lookup(ulpt_fwdevs, v, p)) void ulpt_attach(struct device *parent, struct device *self, void *aux) { struct ulpt_softc *sc = (struct ulpt_softc *)self; struct usb_attach_arg *uaa = aux; struct usbd_device *dev = uaa->device; struct usbd_interface *iface = uaa->iface; usb_interface_descriptor_t *ifcd = usbd_get_interface_descriptor(iface); usb_interface_descriptor_t *id, *iend; usb_config_descriptor_t *cdesc; usbd_status err; usb_endpoint_descriptor_t *ed; int i, altno; DPRINTFN(10,("ulpt_attach: sc=%p\n", sc)); //printf("%s: iclass %d/%d\n", sc->sc_dev.dv_xname, // ifcd->bInterfaceClass, ifcd->bInterfaceSubClass); /* XXX * Stepping through the alternate settings needs to be abstracted out. */ cdesc = usbd_get_config_descriptor(dev); if (cdesc == NULL) { printf("%s: failed to get configuration descriptor\n", sc->sc_dev.dv_xname); return; } iend = (usb_interface_descriptor_t *) ((char *)cdesc + UGETW(cdesc->wTotalLength)); #ifdef DIAGNOSTIC if (ifcd < (usb_interface_descriptor_t *)cdesc || ifcd >= iend) panic("ulpt: iface desc out of range"); #endif /* Step through all the descriptors looking for bidir mode */ for (id = ifcd, altno = 0; id < iend; id = (void *)((char *)id + id->bLength)) { if (id->bDescriptorType == UDESC_INTERFACE && id->bInterfaceNumber == ifcd->bInterfaceNumber) { if (id->bInterfaceClass == UICLASS_PRINTER && id->bInterfaceSubClass == UISUBCLASS_PRINTER && (id->bInterfaceProtocol == UIPROTO_PRINTER_BI /*|| id->bInterfaceProtocol == UIPROTO_PRINTER_1284*/)) goto found; altno++; } } id = ifcd; /* not found, use original */ found: if (id != ifcd) { /* Found a new bidir setting */ DPRINTF(("ulpt_attach: set altno = %d\n", altno)); err = usbd_set_interface(iface, altno); if (err) { printf("%s: setting alternate interface failed\n", sc->sc_dev.dv_xname); usbd_deactivate(sc->sc_udev); return; } } sc->sc_in = -1; sc->sc_out = -1; id = usbd_get_interface_descriptor(iface); for (i = 0; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(iface, i); if (ed == NULL) { printf("%s: couldn't get ep %d\n", sc->sc_dev.dv_xname, i); return; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { sc->sc_in = ed->bEndpointAddress; } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { sc->sc_out = ed->bEndpointAddress; } } if (sc->sc_out == -1) { printf("%s: could not find bulk out endpoint\n", sc->sc_dev.dv_xname); usbd_deactivate(sc->sc_udev); return; } if (usbd_get_quirks(dev)->uq_flags & UQ_BROKEN_BIDIR) { /* This device doesn't handle reading properly. */ sc->sc_in = -1; } printf("%s: using %s-directional mode\n", sc->sc_dev.dv_xname, sc->sc_in >= 0 ? "bi" : "uni"); DPRINTFN(10, ("ulpt_attach: bulk=%d\n", sc->sc_out)); sc->sc_iface = iface; sc->sc_ifaceno = id->bInterfaceNumber; sc->sc_udev = dev; /* maybe the device needs firmware */ sc->sc_fwdev = ulpt_lookup(uaa->vendor, uaa->product); if (sc->sc_fwdev) config_mountroot(self, ulpt_load_firmware); #if 0 /* * This code is disabled because for some mysterious reason it causes * printing not to work. But only sometimes, and mostly with * UHCI and less often with OHCI. *sigh* */ { usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev); usb_device_request_t req; int len, alen; req.bmRequestType = UT_READ_CLASS_INTERFACE; req.bRequest = UR_GET_DEVICE_ID; USETW(req.wValue, cd->bConfigurationValue); USETW2(req.wIndex, id->bInterfaceNumber, id->bAlternateSetting); USETW(req.wLength, DEVINFOSIZE - 1); err = usbd_do_request_flags(dev, &req, devinfop, USBD_SHORT_XFER_OK, &alen, USBD_DEFAULT_TIMEOUT); if (err) { printf("%s: cannot get device id\n", sc->sc_dev.dv_xname); } else if (alen <= 2) { printf("%s: empty device id, no printer connected?\n", sc->sc_dev.dv_xname); } else { /* devinfop now contains an IEEE-1284 device ID */ len = ((devinfop[0] & 0xff) << 8) | (devinfop[1] & 0xff); if (len > DEVINFOSIZE - 3) len = DEVINFOSIZE - 3; devinfo[len] = 0; printf("%s: device id <", sc->sc_dev.dv_xname); ieee1284_print_id(devinfop+2); printf(">\n"); } } #endif } int ulpt_detach(struct device *self, int flags) { struct ulpt_softc *sc = (struct ulpt_softc *)self; int s; int maj, mn; DPRINTF(("ulpt_detach: sc=%p\n", sc)); if (sc->sc_out_pipe != NULL) usbd_abort_pipe(sc->sc_out_pipe); if (sc->sc_in_pipe != NULL) usbd_abort_pipe(sc->sc_in_pipe); s = splusb(); if (--sc->sc_refcnt >= 0) { /* There is noone to wake, aborting the pipe is enough */ /* Wait for processes to go away. */ usb_detach_wait(&sc->sc_dev); } splx(s); /* locate the major number */ for (maj = 0; maj < nchrdev; maj++) if (cdevsw[maj].d_open == ulptopen) break; /* Nuke the vnodes for any open instances (calls close). */ mn = self->dv_unit; vdevgone(maj, mn, mn, VCHR); vdevgone(maj, mn | ULPT_NOPRIME , mn | ULPT_NOPRIME, VCHR); return (0); } int ulpt_status(struct ulpt_softc *sc) { usb_device_request_t req; usbd_status err; u_char status; req.bmRequestType = UT_READ_CLASS_INTERFACE; req.bRequest = UR_GET_PORT_STATUS; USETW(req.wValue, 0); USETW(req.wIndex, sc->sc_ifaceno); USETW(req.wLength, 1); err = usbd_do_request(sc->sc_udev, &req, &status); DPRINTFN(1, ("ulpt_status: status=0x%02x err=%d\n", status, err)); if (!err) return (status); else return (0); } void ulpt_reset(struct ulpt_softc *sc) { usb_device_request_t req; DPRINTFN(1, ("ulpt_reset\n")); req.bRequest = UR_SOFT_RESET; USETW(req.wValue, 0); USETW(req.wIndex, sc->sc_ifaceno); USETW(req.wLength, 0); /* * There was a mistake in the USB printer 1.0 spec that gave the * request type as UT_WRITE_CLASS_OTHER; it should have been * UT_WRITE_CLASS_INTERFACE. Many printers use the old one, * so we try both. */ req.bmRequestType = UT_WRITE_CLASS_OTHER; if (usbd_do_request(sc->sc_udev, &req, 0)) { /* 1.0 */ req.bmRequestType = UT_WRITE_CLASS_INTERFACE; (void)usbd_do_request(sc->sc_udev, &req, 0); /* 1.1 */ } } static void ulpt_input(struct usbd_xfer *xfer, void *priv, usbd_status status) { struct ulpt_softc *sc = priv; DPRINTFN(2,("ulpt_input: got some data\n")); /* Do it again. */ if (xfer == sc->sc_in_xfer1) usbd_transfer(sc->sc_in_xfer2); else usbd_transfer(sc->sc_in_xfer1); } int ulptusein = 1; /* * Reset the printer, then wait until it's selected and not busy. */ int ulptopen(dev_t dev, int flag, int mode, struct proc *p) { u_char flags = ULPTFLAGS(dev); struct ulpt_softc *sc; usbd_status err; int error; if (ULPTUNIT(dev) >= ulpt_cd.cd_ndevs) return (ENXIO); sc = ulpt_cd.cd_devs[ULPTUNIT(dev)]; if (sc == NULL) return (ENXIO); if (sc == NULL || sc->sc_iface == NULL || usbd_is_dying(sc->sc_udev)) return (ENXIO); if (sc->sc_state) return (EBUSY); /* If a previous attempt to load firmware failed, retry. */ if (sc->sc_flags & ULPT_EFIRMWARE) { ulpt_load_firmware(&sc->sc_dev); if (sc->sc_flags & ULPT_EFIRMWARE) return (EIO); } sc->sc_state = ULPT_INIT; sc->sc_flags = flags; DPRINTF(("ulptopen: flags=0x%x\n", (unsigned)flags)); error = 0; sc->sc_refcnt++; if ((flags & ULPT_NOPRIME) == 0) { ulpt_reset(sc); if (usbd_is_dying(sc->sc_udev)) { error = ENXIO; sc->sc_state = 0; goto done; } } err = usbd_open_pipe(sc->sc_iface, sc->sc_out, 0, &sc->sc_out_pipe); if (err) { sc->sc_state = 0; error = EIO; goto done; } if (ulptusein && sc->sc_in != -1) { DPRINTF(("ulpt_open: open input pipe\n")); err = usbd_open_pipe(sc->sc_iface, sc->sc_in,0,&sc->sc_in_pipe); if (err) { error = EIO; usbd_close_pipe(sc->sc_out_pipe); sc->sc_out_pipe = NULL; sc->sc_state = 0; goto done; } sc->sc_in_xfer1 = usbd_alloc_xfer(sc->sc_udev); sc->sc_in_xfer2 = usbd_alloc_xfer(sc->sc_udev); if (sc->sc_in_xfer1 == NULL || sc->sc_in_xfer2 == NULL) { error = ENOMEM; if (sc->sc_in_xfer1 != NULL) { usbd_free_xfer(sc->sc_in_xfer1); sc->sc_in_xfer1 = NULL; } if (sc->sc_in_xfer2 != NULL) { usbd_free_xfer(sc->sc_in_xfer2); sc->sc_in_xfer2 = NULL; } usbd_close_pipe(sc->sc_out_pipe); sc->sc_out_pipe = NULL; usbd_close_pipe(sc->sc_in_pipe); sc->sc_in_pipe = NULL; sc->sc_state = 0; goto done; } usbd_setup_xfer(sc->sc_in_xfer1, sc->sc_in_pipe, sc, sc->sc_junk, sizeof sc->sc_junk, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, ulpt_input); usbd_setup_xfer(sc->sc_in_xfer2, sc->sc_in_pipe, sc, sc->sc_junk, sizeof sc->sc_junk, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, ulpt_input); usbd_transfer(sc->sc_in_xfer1); /* ignore failed start */ } sc->sc_state = ULPT_OPEN; done: if (--sc->sc_refcnt < 0) usb_detach_wakeup(&sc->sc_dev); DPRINTF(("ulptopen: done, error=%d\n", error)); return (error); } int ulpt_statusmsg(u_char status, struct ulpt_softc *sc) { u_char new; status = (status ^ LPS_INVERT) & LPS_MASK; new = status & ~sc->sc_laststatus; sc->sc_laststatus = status; if (new & LPS_SELECT) log(LOG_NOTICE, "%s: offline\n", sc->sc_dev.dv_xname); else if (new & LPS_NOPAPER) log(LOG_NOTICE, "%s: out of paper\n", sc->sc_dev.dv_xname); else if (new & LPS_NERR) log(LOG_NOTICE, "%s: output error\n", sc->sc_dev.dv_xname); return (status); } int ulptclose(dev_t dev, int flag, int mode, struct proc *p) { struct ulpt_softc *sc; sc = ulpt_cd.cd_devs[ULPTUNIT(dev)]; if (sc->sc_state != ULPT_OPEN) /* We are being forced to close before the open completed. */ return (0); if (sc->sc_out_pipe != NULL) { usbd_close_pipe(sc->sc_out_pipe); sc->sc_out_pipe = NULL; } if (sc->sc_in_pipe != NULL) { usbd_close_pipe(sc->sc_in_pipe); sc->sc_in_pipe = NULL; if (sc->sc_in_xfer1 != NULL) { usbd_free_xfer(sc->sc_in_xfer1); sc->sc_in_xfer1 = NULL; } if (sc->sc_in_xfer2 != NULL) { usbd_free_xfer(sc->sc_in_xfer2); sc->sc_in_xfer2 = NULL; } } sc->sc_state = 0; DPRINTF(("ulptclose: closed\n")); return (0); } int ulpt_do_write(struct ulpt_softc *sc, struct uio *uio, int flags) { size_t n; int error = 0; void *bufp; struct usbd_xfer *xfer; usbd_status err; DPRINTF(("ulptwrite\n")); xfer = usbd_alloc_xfer(sc->sc_udev); if (xfer == NULL) return (ENOMEM); bufp = usbd_alloc_buffer(xfer, ULPT_BSIZE); if (bufp == NULL) { usbd_free_xfer(xfer); return (ENOMEM); } while ((n = ulmin(ULPT_BSIZE, uio->uio_resid)) != 0) { ulpt_statusmsg(ulpt_status(sc), sc); error = uiomove(bufp, n, uio); if (error) break; DPRINTFN(1, ("ulptwrite: transfer %zu bytes\n", n)); usbd_setup_xfer(xfer, sc->sc_out_pipe, 0, bufp, n, USBD_NO_COPY | USBD_SYNCHRONOUS | USBD_CATCH, 0, NULL); err = usbd_transfer(xfer); if (err) { usbd_clear_endpoint_stall(sc->sc_out_pipe); DPRINTF(("ulptwrite: error=%d\n", err)); error = EIO; break; } } usbd_free_xfer(xfer); return (error); } int ulptwrite(dev_t dev, struct uio *uio, int flags) { struct ulpt_softc *sc; int error; sc = ulpt_cd.cd_devs[ULPTUNIT(dev)]; if (usbd_is_dying(sc->sc_udev) || (sc->sc_flags & ULPT_EFIRMWARE)) return (EIO); sc->sc_refcnt++; error = ulpt_do_write(sc, uio, flags); if (--sc->sc_refcnt < 0) usb_detach_wakeup(&sc->sc_dev); return (error); } usbd_status ulpt_ucode_loader_hp(struct ulpt_softc *sc) { usbd_status error; int load_error; uint8_t *ucode; uint32_t len; size_t ucode_size; const char *ucode_name = sc->sc_fwdev->ucode_name; int offset = 0, remain; struct usbd_xfer *xfer; void *bufp; /* open microcode file */ load_error = loadfirmware(ucode_name, &ucode, &ucode_size); if (load_error != 0) { printf("%s: failed loadfirmware of file %s (error %d)\n", sc->sc_dev.dv_xname, ucode_name, load_error); return (USBD_INVAL); } /* upload microcode */ error = usbd_open_pipe(sc->sc_iface, sc->sc_out, 0, &sc->sc_out_pipe); if (error) goto free_ucode; xfer = usbd_alloc_xfer(sc->sc_udev); if (xfer == NULL) goto close_pipe; bufp = usbd_alloc_buffer(xfer, ULPT_BSIZE); if (bufp == NULL) { error = USBD_NOMEM; goto free_xfer; } remain = ucode_size; while (remain > 0) { len = min(remain, ULPT_BSIZE); memcpy(bufp, &ucode[offset], len); usbd_setup_xfer(xfer, sc->sc_out_pipe, 0, bufp, len, USBD_NO_COPY | USBD_SYNCHRONOUS, 0, NULL); error = usbd_transfer(xfer); if (error != USBD_NORMAL_COMPLETION) { usbd_clear_endpoint_stall(sc->sc_out_pipe); printf("%s: ucode upload error=%s!\n", sc->sc_dev.dv_xname, usbd_errstr(error)); break; } DPRINTF(("%s: uploaded %d bytes ucode\n", sc->sc_dev.dv_xname, len)); offset += len; remain -= len; } free_xfer: usbd_free_xfer(xfer); close_pipe: usbd_close_pipe(sc->sc_out_pipe); sc->sc_out_pipe = NULL; free_ucode: free(ucode, M_DEVBUF, ucode_size); return (error); } #if 0 /* XXX This does not belong here. */ /* * Print select parts of a IEEE 1284 device ID. */ void ieee1284_print_id(char *str) { char *p, *q; for (p = str-1; p; p = strchr(p, ';')) { p++; /* skip ';' */ if (strncmp(p, "MFG:", 4) == 0 || strncmp(p, "MANUFACTURER:", 14) == 0 || strncmp(p, "MDL:", 4) == 0 || strncmp(p, "MODEL:", 6) == 0) { q = strchr(p, ';'); if (q) printf("%.*s", (int)(q - p + 1), p); } } } #endif
112 111 112 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 /* $OpenBSD: ip_id.c,v 1.25 2021/03/10 10:21:48 jsg Exp $ */ /* * Copyright (c) 2008 Theo de Raadt, Ryan McBride * * Slightly different algorithm from the one designed by * Matthew Dillon <dillon@backplane.com> for The DragonFly Project * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * Random ip sequence number generator. Use the system PRNG to shuffle * the 65536 entry ID space. We reshuffle the ID we pick out of the array * into the previous 32767 cells, providing an guarantee that an ID will not * be reused for at least 32768 calls. */ #include <sys/param.h> #include <sys/systm.h> static u_int16_t ip_shuffle[65536]; static int isindex = 0; u_int16_t ip_randomid(void); /* * Return a random IP id. Shuffle the new value we get into the previous half * of the ip_shuffle ring (-32767 or swap with ourself), to avoid duplicates * occurring too quickly but also still be random. * * 0 is a special IP ID -- don't return it. */ u_int16_t ip_randomid(void) { static int ipid_initialized; u_int16_t si, r; int i, i2; if (!ipid_initialized) { ipid_initialized = 1; /* * Initialize with a random permutation. Do so using Knuth * which avoids the exchange in the Durstenfeld shuffle. * (See "The Art of Computer Programming, Vol 2" 3rd ed, pg. 145). * * Even if our PRNG is imperfect at boot time, we have deferred * doing this until the first packet being sent and now must * generate an ID. */ for (i = 0; i < nitems(ip_shuffle); ++i) { i2 = arc4random_uniform(i + 1); ip_shuffle[i] = ip_shuffle[i2]; ip_shuffle[i2] = i; } } do { arc4random_buf(&si, sizeof(si)); i = isindex & 0xFFFF; i2 = (isindex - (si & 0x7FFF)) & 0xFFFF; r = ip_shuffle[i]; ip_shuffle[i] = ip_shuffle[i2]; ip_shuffle[i2] = r; isindex++; } while (r == 0); return (r); }
1 1 1 6 2 2 2 1 1 1 1 6 1 1 4 14 1 10 4 7 3 1 4 1 4 10 17 17 6 2 4 6 5 2 11 4 1 2 8 3 7 10 4 10 16 16 6 2 4 3 5 2 3 8 3 1 4 2 7 3 6 7 4 2 4 4 9 6 5 1 2 3 3 1 2 4 4 1 3 2 5 4 1 3 1 3 3 4 1 3 2 6 1 1 2 2 148 117 49 6 1065 21 26 955 1054 1064 55 23 7 7 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 /* $OpenBSD: kern_prot.c,v 1.82 2023/01/09 02:12:13 guenther Exp $ */ /* $NetBSD: kern_prot.c,v 1.33 1996/02/09 18:59:42 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_prot.c 8.6 (Berkeley) 1/21/94 */ /* * System calls related to processes and protection */ #include <sys/param.h> #include <sys/atomic.h> #include <sys/systm.h> #include <sys/ucred.h> #include <sys/proc.h> #include <sys/filedesc.h> #include <sys/pool.h> #include <sys/mount.h> #include <sys/syscallargs.h> #include <machine/tcb.h> inline void crset(struct ucred *newcr, const struct ucred *cr) { KASSERT(cr->cr_refcnt.r_refs > 0); memcpy( (char *)newcr + offsetof(struct ucred, cr_startcopy), (const char *)cr + offsetof(struct ucred, cr_startcopy), sizeof(*cr) - offsetof(struct ucred, cr_startcopy)); } int sys_getpid(struct proc *p, void *v, register_t *retval) { *retval = p->p_p->ps_pid; return (0); } int sys_getthrid(struct proc *p, void *v, register_t *retval) { *retval = p->p_tid + THREAD_PID_OFFSET; return (0); } int sys_getppid(struct proc *p, void *v, register_t *retval) { *retval = p->p_p->ps_ppid; return (0); } /* Get process group ID; note that POSIX getpgrp takes no parameter */ int sys_getpgrp(struct proc *p, void *v, register_t *retval) { *retval = p->p_p->ps_pgrp->pg_id; return (0); } /* * SysVR.4 compatible getpgid() */ int sys_getpgid(struct proc *curp, void *v, register_t *retval) { struct sys_getpgid_args /* { syscallarg(pid_t) pid; } */ *uap = v; struct process *targpr = curp->p_p; if (SCARG(uap, pid) == 0 || SCARG(uap, pid) == targpr->ps_pid) goto found; if ((targpr = prfind(SCARG(uap, pid))) == NULL) return (ESRCH); if (targpr->ps_session != curp->p_p->ps_session) return (EPERM); found: *retval = targpr->ps_pgid; return (0); } int sys_getsid(struct proc *curp, void *v, register_t *retval) { struct sys_getsid_args /* { syscallarg(pid_t) pid; } */ *uap = v; struct process *targpr = curp->p_p; if (SCARG(uap, pid) == 0 || SCARG(uap, pid) == targpr->ps_pid) goto found; if ((targpr = prfind(SCARG(uap, pid))) == NULL) return (ESRCH); if (targpr->ps_session != curp->p_p->ps_session) return (EPERM); found: /* Skip exiting processes */ if (targpr->ps_pgrp->pg_session->s_leader == NULL) return (ESRCH); *retval = targpr->ps_pgrp->pg_session->s_leader->ps_pid; return (0); } int sys_getuid(struct proc *p, void *v, register_t *retval) { *retval = p->p_ucred->cr_ruid; return (0); } int sys_geteuid(struct proc *p, void *v, register_t *retval) { *retval = p->p_ucred->cr_uid; return (0); } int sys_issetugid(struct proc *p, void *v, register_t *retval) { if (p->p_p->ps_flags & PS_SUGIDEXEC) *retval = 1; else *retval = 0; return (0); } int sys_getgid(struct proc *p, void *v, register_t *retval) { *retval = p->p_ucred->cr_rgid; return (0); } /* * Get effective group ID. The "egid" is groups[0], and could be obtained * via getgroups. This syscall exists because it is somewhat painful to do * correctly in a library function. */ int sys_getegid(struct proc *p, void *v, register_t *retval) { *retval = p->p_ucred->cr_gid; return (0); } int sys_getgroups(struct proc *p, void *v, register_t *retval) { struct sys_getgroups_args /* { syscallarg(int) gidsetsize; syscallarg(gid_t *) gidset; } */ *uap = v; struct ucred *uc = p->p_ucred; int ngrp; int error; if ((ngrp = SCARG(uap, gidsetsize)) == 0) { *retval = uc->cr_ngroups; return (0); } if (ngrp < uc->cr_ngroups) return (EINVAL); ngrp = uc->cr_ngroups; error = copyout(uc->cr_groups, SCARG(uap, gidset), ngrp * sizeof(gid_t)); if (error) return (error); *retval = ngrp; return (0); } int sys_setsid(struct proc *p, void *v, register_t *retval) { struct session *newsess; struct pgrp *newpgrp; struct process *pr = p->p_p; pid_t pid = pr->ps_pid; newsess = pool_get(&session_pool, PR_WAITOK); newpgrp = pool_get(&pgrp_pool, PR_WAITOK); if (pr->ps_pgid == pid || pgfind(pid) != NULL) { pool_put(&pgrp_pool, newpgrp); pool_put(&session_pool, newsess); return (EPERM); } else { enternewpgrp(pr, newpgrp, newsess); *retval = pid; return (0); } } /* * set process group (setpgid/old setpgrp) * * caller does setpgid(targpid, targpgid) * * pid must be caller or child of caller (ESRCH) * if a child * pid must be in same session (EPERM) * pid can't have done an exec (EACCES) * if pgid != pid * there must exist some pid in same session having pgid (EPERM) * pid must not be session leader (EPERM) */ int sys_setpgid(struct proc *curp, void *v, register_t *retval) { struct sys_setpgid_args /* { syscallarg(pid_t) pid; syscallarg(pid_t) pgid; } */ *uap = v; struct process *curpr = curp->p_p; struct process *targpr; /* target process */ struct pgrp *pgrp, *newpgrp; /* target pgrp */ pid_t pid, pgid; int error; pid = SCARG(uap, pid); pgid = SCARG(uap, pgid); if (pgid < 0) return (EINVAL); newpgrp = pool_get(&pgrp_pool, PR_WAITOK); if (pid != 0 && pid != curpr->ps_pid) { if ((targpr = prfind(pid)) == NULL || !inferior(targpr, curpr)) { error = ESRCH; goto out; } if (targpr->ps_session != curpr->ps_session) { error = EPERM; goto out; } if (targpr->ps_flags & PS_EXEC) { error = EACCES; goto out; } } else targpr = curpr; if (SESS_LEADER(targpr)) { error = EPERM; goto out; } if (pgid == 0) pgid = targpr->ps_pid; error = 0; if ((pgrp = pgfind(pgid)) == NULL) { /* can only create a new process group with pgid == pid */ if (pgid != targpr->ps_pid) error = EPERM; else { enternewpgrp(targpr, newpgrp, NULL); newpgrp = NULL; } } else if (pgrp != targpr->ps_pgrp) { /* anything to do? */ if (pgid != targpr->ps_pid && pgrp->pg_session != curpr->ps_session) error = EPERM; else enterthispgrp(targpr, pgrp); } out: if (newpgrp != NULL) pool_put(&pgrp_pool, newpgrp); return (error); } int sys_getresuid(struct proc *p, void *v, register_t *retval) { struct sys_getresuid_args /* { syscallarg(uid_t *) ruid; syscallarg(uid_t *) euid; syscallarg(uid_t *) suid; } */ *uap = v; struct ucred *uc = p->p_ucred; uid_t *ruid, *euid, *suid; int error1 = 0, error2 = 0, error3 = 0; ruid = SCARG(uap, ruid); euid = SCARG(uap, euid); suid = SCARG(uap, suid); if (ruid != NULL) error1 = copyout(&uc->cr_ruid, ruid, sizeof(*ruid)); if (euid != NULL) error2 = copyout(&uc->cr_uid, euid, sizeof(*euid)); if (suid != NULL) error3 = copyout(&uc->cr_svuid, suid, sizeof(*suid)); return (error1 ? error1 : error2 ? error2 : error3); } int sys_setresuid(struct proc *p, void *v, register_t *retval) { struct sys_setresuid_args /* { syscallarg(uid_t) ruid; syscallarg(uid_t) euid; syscallarg(uid_t) suid; } */ *uap = v; struct process *pr = p->p_p; struct ucred *pruc, *newcred, *uc = p->p_ucred; uid_t ruid, euid, suid; int error; ruid = SCARG(uap, ruid); euid = SCARG(uap, euid); suid = SCARG(uap, suid); /* * make permission checks against the thread's ucred, * but the actual changes will be to the process's ucred */ pruc = pr->ps_ucred; if ((ruid == (uid_t)-1 || ruid == pruc->cr_ruid) && (euid == (uid_t)-1 || euid == pruc->cr_uid) && (suid == (uid_t)-1 || suid == pruc->cr_svuid)) return (0); /* no change */ /* * Any of the real, effective, and saved uids may be changed * to the current value of one of the three (root is not limited). */ if (ruid != (uid_t)-1 && ruid != uc->cr_ruid && ruid != uc->cr_uid && ruid != uc->cr_svuid && (error = suser(p))) return (error); if (euid != (uid_t)-1 && euid != uc->cr_ruid && euid != uc->cr_uid && euid != uc->cr_svuid && (error = suser(p))) return (error); if (suid != (uid_t)-1 && suid != uc->cr_ruid && suid != uc->cr_uid && suid != uc->cr_svuid && (error = suser(p))) return (error); /* * Copy credentials so other references do not see our changes. * ps_ucred may change during the crget(). */ newcred = crget(); pruc = pr->ps_ucred; crset(newcred, pruc); /* * Note that unlike the other set*uid() calls, each * uid type is set independently of the others. */ if (ruid != (uid_t)-1) newcred->cr_ruid = ruid; if (euid != (uid_t)-1) newcred->cr_uid = euid; if (suid != (uid_t)-1) newcred->cr_svuid = suid; pr->ps_ucred = newcred; atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); /* now that we can sleep, transfer proc count to new user */ if (ruid != (uid_t)-1 && ruid != pruc->cr_ruid) { chgproccnt(pruc->cr_ruid, -1); chgproccnt(ruid, 1); } crfree(pruc); return (0); } int sys_getresgid(struct proc *p, void *v, register_t *retval) { struct sys_getresgid_args /* { syscallarg(gid_t *) rgid; syscallarg(gid_t *) egid; syscallarg(gid_t *) sgid; } */ *uap = v; struct ucred *uc = p->p_ucred; gid_t *rgid, *egid, *sgid; int error1 = 0, error2 = 0, error3 = 0; rgid = SCARG(uap, rgid); egid = SCARG(uap, egid); sgid = SCARG(uap, sgid); if (rgid != NULL) error1 = copyout(&uc->cr_rgid, rgid, sizeof(*rgid)); if (egid != NULL) error2 = copyout(&uc->cr_gid, egid, sizeof(*egid)); if (sgid != NULL) error3 = copyout(&uc->cr_svgid, sgid, sizeof(*sgid)); return (error1 ? error1 : error2 ? error2 : error3); } int sys_setresgid(struct proc *p, void *v, register_t *retval) { struct sys_setresgid_args /* { syscallarg(gid_t) rgid; syscallarg(gid_t) egid; syscallarg(gid_t) sgid; } */ *uap = v; struct process *pr = p->p_p; struct ucred *pruc, *newcred, *uc = p->p_ucred; gid_t rgid, egid, sgid; int error; rgid = SCARG(uap, rgid); egid = SCARG(uap, egid); sgid = SCARG(uap, sgid); /* * make permission checks against the thread's ucred, * but the actual changes will be to the process's ucred */ pruc = pr->ps_ucred; if ((rgid == (gid_t)-1 || rgid == pruc->cr_rgid) && (egid == (gid_t)-1 || egid == pruc->cr_gid) && (sgid == (gid_t)-1 || sgid == pruc->cr_svgid)) return (0); /* no change */ /* * Any of the real, effective, and saved gids may be changed * to the current value of one of the three (root is not limited). */ if (rgid != (gid_t)-1 && rgid != uc->cr_rgid && rgid != uc->cr_gid && rgid != uc->cr_svgid && (error = suser(p))) return (error); if (egid != (gid_t)-1 && egid != uc->cr_rgid && egid != uc->cr_gid && egid != uc->cr_svgid && (error = suser(p))) return (error); if (sgid != (gid_t)-1 && sgid != uc->cr_rgid && sgid != uc->cr_gid && sgid != uc->cr_svgid && (error = suser(p))) return (error); /* * Copy credentials so other references do not see our changes. * ps_ucred may change during the crget(). */ newcred = crget(); pruc = pr->ps_ucred; crset(newcred, pruc); /* * Note that unlike the other set*gid() calls, each * gid type is set independently of the others. */ if (rgid != (gid_t)-1) newcred->cr_rgid = rgid; if (egid != (gid_t)-1) newcred->cr_gid = egid; if (sgid != (gid_t)-1) newcred->cr_svgid = sgid; pr->ps_ucred = newcred; atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); crfree(pruc); return (0); } int sys_setregid(struct proc *p, void *v, register_t *retval) { struct sys_setregid_args /* { syscallarg(gid_t) rgid; syscallarg(gid_t) egid; } */ *uap = v; struct process *pr = p->p_p; struct ucred *pruc, *newcred, *uc = p->p_ucred; gid_t rgid, egid; int error; rgid = SCARG(uap, rgid); egid = SCARG(uap, egid); /* * make permission checks against the thread's ucred, * but the actual changes will be to the process's ucred * * The saved gid check here is complicated: we reset the * saved gid to the real gid if the real gid is specified * *and* either it's changing _or_ the saved gid won't equal * the effective gid. So, the svgid *won't* change when * the rgid isn't specified or when the rgid isn't changing * and the svgid equals the requested egid. */ pruc = pr->ps_ucred; if ((rgid == (gid_t)-1 || rgid == pruc->cr_rgid) && (egid == (gid_t)-1 || egid == pruc->cr_gid) && (rgid == (gid_t)-1 || (rgid == pruc->cr_rgid && pruc->cr_svgid == (egid != (gid_t)-1 ? egid : pruc->cr_gid)))) return (0); /* no change */ /* * Any of the real, effective, and saved gids may be changed * to the current value of one of the three (root is not limited). */ if (rgid != (gid_t)-1 && rgid != uc->cr_rgid && rgid != uc->cr_gid && rgid != uc->cr_svgid && (error = suser(p))) return (error); if (egid != (gid_t)-1 && egid != uc->cr_rgid && egid != uc->cr_gid && egid != uc->cr_svgid && (error = suser(p))) return (error); /* * Copy credentials so other references do not see our changes. * ps_ucred may change during the crget(). */ newcred = crget(); pruc = pr->ps_ucred; crset(newcred, pruc); if (rgid != (gid_t)-1) newcred->cr_rgid = rgid; if (egid != (gid_t)-1) newcred->cr_gid = egid; /* * The saved gid presents a bit of a dilemma, as it did not * exist when setregid(2) was conceived. We only set the saved * gid when the real gid is specified and either its value would * change, or where the saved and effective gids are different. */ if (rgid != (gid_t)-1 && (rgid != pruc->cr_rgid || pruc->cr_svgid != (egid != (gid_t)-1 ? egid : pruc->cr_gid))) newcred->cr_svgid = rgid; pr->ps_ucred = newcred; atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); crfree(pruc); return (0); } int sys_setreuid(struct proc *p, void *v, register_t *retval) { struct sys_setreuid_args /* { syscallarg(uid_t) ruid; syscallarg(uid_t) euid; } */ *uap = v; struct process *pr = p->p_p; struct ucred *pruc, *newcred, *uc = p->p_ucred; uid_t ruid, euid; int error; ruid = SCARG(uap, ruid); euid = SCARG(uap, euid); /* * make permission checks against the thread's ucred, * but the actual changes will be to the process's ucred * * The saved uid check here is complicated: we reset the * saved uid to the real uid if the real uid is specified * *and* either it's changing _or_ the saved uid won't equal * the effective uid. So, the svuid *won't* change when * the ruid isn't specified or when the ruid isn't changing * and the svuid equals the requested euid. */ pruc = pr->ps_ucred; if ((ruid == (uid_t)-1 || ruid == pruc->cr_ruid) && (euid == (uid_t)-1 || euid == pruc->cr_uid) && (ruid == (uid_t)-1 || (ruid == pruc->cr_ruid && pruc->cr_svuid == (euid != (uid_t)-1 ? euid : pruc->cr_uid)))) return (0); /* no change */ /* * Any of the real, effective, and saved uids may be changed * to the current value of one of the three (root is not limited). */ if (ruid != (uid_t)-1 && ruid != uc->cr_ruid && ruid != uc->cr_uid && ruid != uc->cr_svuid && (error = suser(p))) return (error); if (euid != (uid_t)-1 && euid != uc->cr_ruid && euid != uc->cr_uid && euid != uc->cr_svuid && (error = suser(p))) return (error); /* * Copy credentials so other references do not see our changes. * ps_ucred may change during the crget(). */ newcred = crget(); pruc = pr->ps_ucred; crset(newcred, pruc); if (ruid != (uid_t)-1) newcred->cr_ruid = ruid; if (euid != (uid_t)-1) newcred->cr_uid = euid; /* * The saved uid presents a bit of a dilemma, as it did not * exist when setreuid(2) was conceived. We only set the saved * uid when the real uid is specified and either its value would * change, or where the saved and effective uids are different. */ if (ruid != (uid_t)-1 && (ruid != pruc->cr_ruid || pruc->cr_svuid != (euid != (uid_t)-1 ? euid : pruc->cr_uid))) newcred->cr_svuid = ruid; pr->ps_ucred = newcred; atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); /* now that we can sleep, transfer proc count to new user */ if (ruid != (uid_t)-1 && ruid != pruc->cr_ruid) { chgproccnt(pruc->cr_ruid, -1); chgproccnt(ruid, 1); } crfree(pruc); return (0); } int sys_setuid(struct proc *p, void *v, register_t *retval) { struct sys_setuid_args /* { syscallarg(uid_t) uid; } */ *uap = v; struct process *pr = p->p_p; struct ucred *pruc, *newcred, *uc = p->p_ucred; uid_t uid; int did_real, error; uid = SCARG(uap, uid); pruc = pr->ps_ucred; if (pruc->cr_uid == uid && pruc->cr_ruid == uid && pruc->cr_svuid == uid) return (0); if (uid != uc->cr_ruid && uid != uc->cr_svuid && uid != uc->cr_uid && (error = suser(p))) return (error); /* * Copy credentials so other references do not see our changes. * ps_ucred may change during the crget(). */ newcred = crget(); pruc = pr->ps_ucred; crset(newcred, pruc); /* * Everything's okay, do it. */ if (uid == pruc->cr_uid || suser(p) == 0) { did_real = 1; newcred->cr_ruid = uid; newcred->cr_svuid = uid; } else did_real = 0; newcred->cr_uid = uid; pr->ps_ucred = newcred; atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); /* * Transfer proc count to new user. */ if (did_real && uid != pruc->cr_ruid) { chgproccnt(pruc->cr_ruid, -1); chgproccnt(uid, 1); } crfree(pruc); return (0); } int sys_seteuid(struct proc *p, void *v, register_t *retval) { struct sys_seteuid_args /* { syscallarg(uid_t) euid; } */ *uap = v; struct process *pr = p->p_p; struct ucred *pruc, *newcred, *uc = p->p_ucred; uid_t euid; int error; euid = SCARG(uap, euid); if (pr->ps_ucred->cr_uid == euid) return (0); if (euid != uc->cr_ruid && euid != uc->cr_svuid && (error = suser(p))) return (error); /* * Copy credentials so other references do not see our changes. * ps_ucred may change during the crget(). */ newcred = crget(); pruc = pr->ps_ucred; crset(newcred, pruc); newcred->cr_uid = euid; pr->ps_ucred = newcred; atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); crfree(pruc); return (0); } int sys_setgid(struct proc *p, void *v, register_t *retval) { struct sys_setgid_args /* { syscallarg(gid_t) gid; } */ *uap = v; struct process *pr = p->p_p; struct ucred *pruc, *newcred, *uc = p->p_ucred; gid_t gid; int error; gid = SCARG(uap, gid); pruc = pr->ps_ucred; if (pruc->cr_gid == gid && pruc->cr_rgid == gid && pruc->cr_svgid == gid) return (0); if (gid != uc->cr_rgid && gid != uc->cr_svgid && gid != uc->cr_gid && (error = suser(p))) return (error); /* * Copy credentials so other references do not see our changes. * ps_ucred may change during the crget(). */ newcred = crget(); pruc = pr->ps_ucred; crset(newcred, pruc); if (gid == pruc->cr_gid || suser(p) == 0) { newcred->cr_rgid = gid; newcred->cr_svgid = gid; } newcred->cr_gid = gid; pr->ps_ucred = newcred; atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); crfree(pruc); return (0); } int sys_setegid(struct proc *p, void *v, register_t *retval) { struct sys_setegid_args /* { syscallarg(gid_t) egid; } */ *uap = v; struct process *pr = p->p_p; struct ucred *pruc, *newcred, *uc = p->p_ucred; gid_t egid; int error; egid = SCARG(uap, egid); if (pr->ps_ucred->cr_gid == egid) return (0); if (egid != uc->cr_rgid && egid != uc->cr_svgid && (error = suser(p))) return (error); /* * Copy credentials so other references do not see our changes. * ps_ucred may change during the crget(). */ newcred = crget(); pruc = pr->ps_ucred; crset(newcred, pruc); newcred->cr_gid = egid; pr->ps_ucred = newcred; atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); crfree(pruc); return (0); } int sys_setgroups(struct proc *p, void *v, register_t *retval) { struct sys_setgroups_args /* { syscallarg(int) gidsetsize; syscallarg(const gid_t *) gidset; } */ *uap = v; struct process *pr = p->p_p; struct ucred *pruc, *newcred; gid_t groups[NGROUPS_MAX]; int ngrp; int error; if ((error = suser(p)) != 0) return (error); ngrp = SCARG(uap, gidsetsize); if (ngrp > NGROUPS_MAX || ngrp < 0) return (EINVAL); error = copyin(SCARG(uap, gidset), groups, ngrp * sizeof(gid_t)); if (error == 0) { newcred = crget(); pruc = pr->ps_ucred; crset(newcred, pruc); memcpy(newcred->cr_groups, groups, ngrp * sizeof(gid_t)); newcred->cr_ngroups = ngrp; pr->ps_ucred = newcred; atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); crfree(pruc); } return (error); } /* * Check if gid is a member of the group set. */ int groupmember(gid_t gid, struct ucred *cred) { gid_t *gp; gid_t *egp; if (cred->cr_gid == gid) return (1); egp = &(cred->cr_groups[cred->cr_ngroups]); for (gp = cred->cr_groups; gp < egp; gp++) if (*gp == gid) return (1); return (0); } /* * Test whether this process has special user powers. * Returns 0 or error. */ int suser(struct proc *p) { struct ucred *cred = p->p_ucred; if (cred->cr_uid == 0) return (0); return (EPERM); } /* * replacement for old suser, for callers who don't have a process */ int suser_ucred(struct ucred *cred) { if (cred->cr_uid == 0) return (0); return (EPERM); } /* * Allocate a zeroed cred structure. */ struct ucred * crget(void) { struct ucred *cr; cr = pool_get(&ucred_pool, PR_WAITOK|PR_ZERO); refcnt_init(&cr->cr_refcnt); return (cr); } /* * Increment the reference count of a cred structure. * Returns the passed structure. */ struct ucred * crhold(struct ucred *cr) { refcnt_take(&cr->cr_refcnt); return (cr); } /* * Free a cred structure. * Throws away space when ref count gets to 0. */ void crfree(struct ucred *cr) { if (refcnt_rele(&cr->cr_refcnt)) pool_put(&ucred_pool, cr); } /* * Copy cred structure to a new one and free the old one. */ struct ucred * crcopy(struct ucred *cr) { struct ucred *newcr; if (!refcnt_shared(&cr->cr_refcnt)) return (cr); newcr = crget(); *newcr = *cr; crfree(cr); refcnt_init(&newcr->cr_refcnt); return (newcr); } /* * Dup cred struct to a new held one. */ struct ucred * crdup(struct ucred *cr) { struct ucred *newcr; newcr = crget(); *newcr = *cr; refcnt_init(&newcr->cr_refcnt); return (newcr); } /* * Convert the userspace xucred to a kernel ucred */ int crfromxucred(struct ucred *cr, const struct xucred *xcr) { if (xcr->cr_ngroups < 0 || xcr->cr_ngroups > NGROUPS_MAX) return (EINVAL); refcnt_init(&cr->cr_refcnt); cr->cr_uid = xcr->cr_uid; cr->cr_gid = xcr->cr_gid; cr->cr_ngroups = xcr->cr_ngroups; memcpy(cr->cr_groups, xcr->cr_groups, sizeof(cr->cr_groups[0]) * xcr->cr_ngroups); return (0); } /* * Get login name, if available. */ int sys_getlogin_r(struct proc *p, void *v, register_t *retval) { struct sys_getlogin_r_args /* { syscallarg(char *) namebuf; syscallarg(size_t) namelen; } */ *uap = v; size_t namelen = SCARG(uap, namelen); struct session *s = p->p_p->ps_pgrp->pg_session; int error; if (namelen > sizeof(s->s_login)) namelen = sizeof(s->s_login); error = copyoutstr(s->s_login, SCARG(uap, namebuf), namelen, NULL); if (error == ENAMETOOLONG) error = ERANGE; *retval = error; return (0); } /* * Set login name. */ int sys_setlogin(struct proc *p, void *v, register_t *retval) { struct sys_setlogin_args /* { syscallarg(const char *) namebuf; } */ *uap = v; struct session *s = p->p_p->ps_pgrp->pg_session; char buf[sizeof(s->s_login)]; int error; if ((error = suser(p)) != 0) return (error); error = copyinstr(SCARG(uap, namebuf), buf, sizeof(buf), NULL); if (error == 0) strlcpy(s->s_login, buf, sizeof(s->s_login)); else if (error == ENAMETOOLONG) error = EINVAL; return (error); } /* * Check if a process is allowed to raise its privileges. */ int proc_cansugid(struct proc *p) { /* ptrace(2)d processes shouldn't. */ if ((p->p_p->ps_flags & PS_TRACED) != 0) return (0); /* processes with shared filedescriptors shouldn't. */ if (p->p_fd->fd_refcnt > 1) return (0); /* Allow. */ return (1); } /* * Set address of the proc's thread-control-block */ int sys___set_tcb(struct proc *p, void *v, register_t *retval) { struct sys___set_tcb_args /* { syscallarg(void *) tcb; } */ *uap = v; void *tcb = SCARG(uap, tcb); #ifdef TCB_INVALID if (TCB_INVALID(tcb)) return EINVAL; #endif /* TCB_INVALID */ TCB_SET(p, tcb); return (0); } /* * Get address of the proc's thread-control-block */ int sys___get_tcb(struct proc *p, void *v, register_t *retval) { *retval = (register_t)TCB_GET(p); return (0); } int sys_getthrname(struct proc *curp, void *v, register_t *retval) { struct sys_getthrname_args /* { syscallarg(pid_t) tid; syscallarg(char *) name; syscallarg(size_t) len; } */ *uap = v; struct proc *p; size_t len; int tid = SCARG(uap, tid); int error; p = tid ? tfind_user(tid, curp->p_p) : curp; if (p == NULL) return ESRCH; len = SCARG(uap, len); if (len > sizeof(p->p_name)) len = sizeof(p->p_name); error = copyoutstr(p->p_name, SCARG(uap, name), len, NULL); if (error == ENAMETOOLONG) error = ERANGE; *retval = error; return 0; } int sys_setthrname(struct proc *curp, void *v, register_t *retval) { struct sys_setthrname_args /* { syscallarg(pid_t) tid; syscallarg(const char *) name; } */ *uap = v; struct proc *p; char buf[sizeof p->p_name]; int tid = SCARG(uap, tid); int error; p = tid ? tfind_user(tid, curp->p_p) : curp; if (p == NULL) return ESRCH; error = copyinstr(SCARG(uap, name), buf, sizeof buf, NULL); if (error == 0) strlcpy(p->p_name, buf, sizeof(p->p_name)); else if (error == ENAMETOOLONG) error = EINVAL; *retval = error; return 0; } /* * Refresh the thread's reference to the process's credentials */ void dorefreshcreds(struct process *pr, struct proc *p) { struct ucred *uc = p->p_ucred; KERNEL_LOCK(); /* XXX should be PROCESS_RLOCK(pr) */ if (uc != pr->ps_ucred) { p->p_ucred = pr->ps_ucred; crhold(p->p_ucred); crfree(uc); } KERNEL_UNLOCK(); }
157 139 18 6 21 14 8 45 61 5 23 12 10 43 18 25 43 61 61 1 10 5 9 4 5 113 112 7 26 16 10 16 11 3 3 6 151 150 209 208 62 55 3 55 8 48 48 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 /* $OpenBSD: in6_src.c,v 1.99 2024/04/21 17:32:11 florian Exp $ */ /* $KAME: in6_src.c,v 1.36 2001/02/06 04:08:17 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 1982, 1986, 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)in_pcb.c 8.2 (Berkeley) 1/4/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/ioctl.h> #include <sys/errno.h> #include <sys/time.h> #include <net/if.h> #include <net/if_var.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/in_pcb.h> #include <netinet6/in6_var.h> #include <netinet/ip6.h> #include <netinet6/ip6_var.h> #include <netinet6/nd6.h> int in6_selectif(const struct in6_addr *, struct ip6_pktopts *, struct ip6_moptions *, struct route *, struct ifnet **, u_int); /* * Return an IPv6 address, which is the most appropriate for a given * destination and pcb. We need the additional opt parameter because * the values set at pcb level can be overridden via cmsg. */ int in6_pcbselsrc(const struct in6_addr **in6src, struct sockaddr_in6 *dstsock, struct inpcb *inp, struct ip6_pktopts *opts) { struct ip6_moptions *mopts = inp->inp_moptions6; struct rtentry *rt; const struct in6_addr *laddr = &inp->inp_laddr6; u_int rtableid = inp->inp_rtableid; struct ifnet *ifp = NULL; struct sockaddr *ip6_source = NULL; struct in6_addr *dst; struct in6_ifaddr *ia6 = NULL; struct in6_pktinfo *pi = NULL; int error; dst = &dstsock->sin6_addr; /* * If the source address is explicitly specified by the caller, * check if the requested source address is indeed a unicast address * assigned to the node, and can be used as the packet's source * address. If everything is okay, use the address as source. */ if (opts && (pi = opts->ip6po_pktinfo) && !IN6_IS_ADDR_UNSPECIFIED(&pi->ipi6_addr)) { struct sockaddr_in6 sa6; /* get the outgoing interface */ error = in6_selectif(dst, opts, mopts, &inp->inp_route, &ifp, rtableid); if (error) return (error); bzero(&sa6, sizeof(sa6)); sa6.sin6_family = AF_INET6; sa6.sin6_len = sizeof(sa6); sa6.sin6_addr = pi->ipi6_addr; if (ifp && IN6_IS_SCOPE_EMBED(&sa6.sin6_addr)) sa6.sin6_addr.s6_addr16[1] = htons(ifp->if_index); if_put(ifp); /* put reference from in6_selectif */ ia6 = ifatoia6(ifa_ifwithaddr(sin6tosa(&sa6), rtableid)); if (ia6 == NULL || (ia6->ia6_flags & (IN6_IFF_ANYCAST|IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED))) return (EADDRNOTAVAIL); pi->ipi6_addr = sa6.sin6_addr; /* XXX: this overrides pi */ *in6src = &pi->ipi6_addr; return (0); } /* * If the source address is not specified but the socket(if any) * is already bound, use the bound address. */ if (laddr && !IN6_IS_ADDR_UNSPECIFIED(laddr)) { *in6src = laddr; return (0); } /* * If the caller doesn't specify the source address but * the outgoing interface, use an address associated with * the interface. */ if (pi && pi->ipi6_ifindex) { ifp = if_get(pi->ipi6_ifindex); if (ifp == NULL) return (ENXIO); /* XXX: better error? */ ia6 = in6_ifawithscope(ifp, dst, rtableid, NULL); if_put(ifp); if (ia6 == NULL) return (EADDRNOTAVAIL); *in6src = &ia6->ia_addr.sin6_addr; return (0); } error = in6_selectsrc(in6src, dstsock, mopts, rtableid); if (error != EADDRNOTAVAIL) return (error); /* * If route is known or can be allocated now, * our src addr is taken from the i/f, else punt. */ rt = route6_mpath(&inp->inp_route, dst, NULL, rtableid); /* * in_pcbconnect() checks out IFF_LOOPBACK to skip using * the address. But we don't know why it does so. * It is necessary to ensure the scope even for lo0 * so doesn't check out IFF_LOOPBACK. */ if (rt != NULL) { ifp = if_get(rt->rt_ifidx); if (ifp != NULL) { ia6 = in6_ifawithscope(ifp, dst, rtableid, rt); if_put(ifp); } if (ia6 == NULL) /* xxx scope error ?*/ ia6 = ifatoia6(rt->rt_ifa); } /* * Use preferred source address if : * - destination is not onlink * - preferred source address is set * - output interface is UP */ if (rt != NULL && !(rt->rt_flags & RTF_LLINFO) && !(rt->rt_flags & RTF_HOST)) { ip6_source = rtable_getsource(rtableid, AF_INET6); if (ip6_source != NULL) { struct ifaddr *ifa; if ((ifa = ifa_ifwithaddr(ip6_source, rtableid)) != NULL && ISSET(ifa->ifa_ifp->if_flags, IFF_UP)) { *in6src = &satosin6(ip6_source)->sin6_addr; return (0); } } } if (ia6 == NULL) return (EHOSTUNREACH); /* no route */ *in6src = &ia6->ia_addr.sin6_addr; return (0); } /* * Return an IPv6 address, which is the most appropriate for a given * destination and multicast options. * If necessary, this function lookups the routing table and returns * an entry to the caller for later use. */ int in6_selectsrc(const struct in6_addr **in6src, struct sockaddr_in6 *dstsock, struct ip6_moptions *mopts, unsigned int rtableid) { struct ifnet *ifp = NULL; struct in6_addr *dst; struct in6_ifaddr *ia6 = NULL; dst = &dstsock->sin6_addr; /* * If the destination address is a link-local unicast address or * a link/interface-local multicast address, and if the outgoing * interface is specified by the sin6_scope_id filed, use an address * associated with the interface. * XXX: We're now trying to define more specific semantics of * sin6_scope_id field, so this part will be rewritten in * the near future. */ if ((IN6_IS_ADDR_LINKLOCAL(dst) || IN6_IS_ADDR_MC_LINKLOCAL(dst) || IN6_IS_ADDR_MC_INTFACELOCAL(dst)) && dstsock->sin6_scope_id) { ifp = if_get(dstsock->sin6_scope_id); if (ifp == NULL) return (ENXIO); /* XXX: better error? */ ia6 = in6_ifawithscope(ifp, dst, rtableid, NULL); if_put(ifp); if (ia6 == NULL) return (EADDRNOTAVAIL); *in6src = &ia6->ia_addr.sin6_addr; return (0); } /* * If the destination address is a multicast address and * the outgoing interface for the address is specified * by the caller, use an address associated with the interface. * Even if the outgoing interface is not specified, we also * choose a loopback interface as the outgoing interface. */ if (IN6_IS_ADDR_MULTICAST(dst)) { ifp = mopts ? if_get(mopts->im6o_ifidx) : NULL; if (!ifp && dstsock->sin6_scope_id) ifp = if_get(htons(dstsock->sin6_scope_id)); if (ifp) { ia6 = in6_ifawithscope(ifp, dst, rtableid, NULL); if_put(ifp); if (ia6 == NULL) return (EADDRNOTAVAIL); *in6src = &ia6->ia_addr.sin6_addr; return (0); } } return (EADDRNOTAVAIL); } struct rtentry * in6_selectroute(const struct in6_addr *dst, struct ip6_pktopts *opts, struct route *ro, unsigned int rtableid) { /* * Use a cached route if it exists and is valid, else try to allocate * a new one. */ if (ro) { struct rtentry *rt; rt = route6_mpath(ro, dst, NULL, rtableid); /* * Check if the outgoing interface conflicts with * the interface specified by ipi6_ifindex (if specified). * Note that loopback interface is always okay. * (this may happen when we are sending a packet to one of * our own addresses.) */ if (opts && opts->ip6po_pktinfo && opts->ip6po_pktinfo->ipi6_ifindex) { if (rt != NULL && !ISSET(rt->rt_flags, RTF_LOCAL) && rt->rt_ifidx != opts->ip6po_pktinfo->ipi6_ifindex) { return (NULL); } } return (rt); } return (NULL); } int in6_selectif(const struct in6_addr *dst, struct ip6_pktopts *opts, struct ip6_moptions *mopts, struct route *ro, struct ifnet **retifp, u_int rtableid) { struct rtentry *rt; struct in6_pktinfo *pi = NULL; /* If the caller specify the outgoing interface explicitly, use it. */ if (opts && (pi = opts->ip6po_pktinfo) != NULL && pi->ipi6_ifindex) { *retifp = if_get(pi->ipi6_ifindex); if (*retifp != NULL) return (0); } /* * If the destination address is a multicast address and the outgoing * interface for the address is specified by the caller, use it. */ if (IN6_IS_ADDR_MULTICAST(dst) && mopts != NULL && (*retifp = if_get(mopts->im6o_ifidx)) != NULL) return (0); rt = in6_selectroute(dst, opts, ro, rtableid); if (rt == NULL) return (EHOSTUNREACH); /* * do not use a rejected or black hole route. * XXX: this check should be done in the L2 output routine. * However, if we skipped this check here, we'd see the following * scenario: * - install a rejected route for a scoped address prefix * (like fe80::/10) * - send a packet to a destination that matches the scoped prefix, * with ambiguity about the scope zone. * - pick the outgoing interface from the route, and disambiguate the * scope zone with the interface. * - ip6_output() would try to get another route with the "new" * destination, which may be valid. * - we'd see no error on output. * Although this may not be very harmful, it should still be confusing. * We thus reject the case here. */ if (ISSET(rt->rt_flags, RTF_REJECT | RTF_BLACKHOLE)) return (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); *retifp = if_get(rt->rt_ifidx); return (0); } int in6_selecthlim(const struct inpcb *inp) { if (inp && inp->inp_hops >= 0) return (inp->inp_hops); return (ip6_defhlim); } /* * generate kernel-internal form (scopeid embedded into s6_addr16[1]). * If the address scope of is link-local, embed the interface index in the * address. The routine determines our precedence * between advanced API scope/interface specification and basic API * specification. * * this function should be nuked in the future, when we get rid of * embedded scopeid thing. * * XXX actually, it is over-specification to return ifp against sin6_scope_id. * there can be multiple interfaces that belong to a particular scope zone * (in specification, we have 1:N mapping between a scope zone and interfaces). * we may want to change the function to return something other than ifp. */ int in6_embedscope(struct in6_addr *in6, const struct sockaddr_in6 *sin6, const struct ip6_pktopts *outputopts6, const struct ip6_moptions *moptions6) { u_int32_t scopeid; *in6 = sin6->sin6_addr; /* * don't try to read sin6->sin6_addr beyond here, since the caller may * ask us to overwrite existing sockaddr_in6 */ if (IN6_IS_SCOPE_EMBED(in6)) { struct in6_pktinfo *pi; /* * KAME assumption: link id == interface id */ if (outputopts6 && (pi = outputopts6->ip6po_pktinfo) && pi->ipi6_ifindex) scopeid = pi->ipi6_ifindex; else if (moptions6 && IN6_IS_ADDR_MULTICAST(in6) && moptions6->im6o_ifidx) scopeid = moptions6->im6o_ifidx; else scopeid = sin6->sin6_scope_id; if (scopeid) { struct ifnet *ifp; ifp = if_get(scopeid); if (ifp == NULL) return ENXIO; /* XXX EINVAL? */ /*XXX assignment to 16bit from 32bit variable */ in6->s6_addr16[1] = htons(scopeid & 0xffff); if_put(ifp); } } return 0; } /* * generate standard sockaddr_in6 from embedded form. * touches sin6_addr and sin6_scope_id only. * * this function should be nuked in the future, when we get rid of * embedded scopeid thing. */ void in6_recoverscope(struct sockaddr_in6 *sin6, const struct in6_addr *in6) { u_int32_t scopeid; sin6->sin6_addr = *in6; /* * don't try to read *in6 beyond here, since the caller may * ask us to overwrite existing sockaddr_in6 */ sin6->sin6_scope_id = 0; if (IN6_IS_SCOPE_EMBED(in6)) { /* * KAME assumption: link id == interface id */ scopeid = ntohs(sin6->sin6_addr.s6_addr16[1]); if (scopeid) { sin6->sin6_addr.s6_addr16[1] = 0; sin6->sin6_scope_id = scopeid; } } } /* * just clear the embedded scope identifier. */ void in6_clearscope(struct in6_addr *addr) { if (IN6_IS_SCOPE_EMBED(addr)) addr->s6_addr16[1] = 0; }
33 33 33 33 63 63 63 99 97 2 19 80 97 2 99 97 2 97 2 63 163 33 131 131 44 44 10 61 12 16 16 33 33 12 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 /* $OpenBSD: uvm_km.c,v 1.152 2024/03/27 15:41:40 kurt Exp $ */ /* $NetBSD: uvm_km.c,v 1.42 2001/01/14 02:10:01 thorpej Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. * Copyright (c) 1991, 1993, The Regents of the University of California. * * All rights reserved. * * This code is derived from software contributed to Berkeley by * The Mach Operating System project at Carnegie-Mellon University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)vm_kern.c 8.3 (Berkeley) 1/12/94 * from: Id: uvm_km.c,v 1.1.2.14 1998/02/06 05:19:27 chs Exp * * * Copyright (c) 1987, 1990 Carnegie-Mellon University. * All rights reserved. * * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ /* * uvm_km.c: handle kernel memory allocation and management */ /* * overview of kernel memory management: * * the kernel virtual address space is mapped by "kernel_map." kernel_map * starts at a machine-dependent address and is VM_KERNEL_SPACE_SIZE bytes * large. * * the kernel_map has several "submaps." submaps can only appear in * the kernel_map (user processes can't use them). submaps "take over" * the management of a sub-range of the kernel's address space. submaps * are typically allocated at boot time and are never released. kernel * virtual address space that is mapped by a submap is locked by the * submap's lock -- not the kernel_map's lock. * * thus, the useful feature of submaps is that they allow us to break * up the locking and protection of the kernel address space into smaller * chunks. * * The VM system has several standard kernel submaps: * kmem_map: Contains only wired kernel memory for malloc(9). * Note: All access to this map must be protected by splvm as * calls to malloc(9) are allowed in interrupt handlers. * exec_map: Memory to hold arguments to system calls are allocated from * this map. * XXX: This is primeraly used to artificially limit the number * of concurrent processes doing an exec. * phys_map: Buffers for vmapbuf (physio) are allocated from this map. * * the kernel allocates its private memory out of special uvm_objects whose * reference count is set to UVM_OBJ_KERN (thus indicating that the objects * are "special" and never die). all kernel objects should be thought of * as large, fixed-sized, sparsely populated uvm_objects. each kernel * object is equal to the size of kernel virtual address space (i.e. * VM_KERNEL_SPACE_SIZE). * * most kernel private memory lives in kernel_object. the only exception * to this is for memory that belongs to submaps that must be protected * by splvm(). each of these submaps manages their own pages. * * note that just because a kernel object spans the entire kernel virtual * address space doesn't mean that it has to be mapped into the entire space. * large chunks of a kernel object's space go unused either because * that area of kernel VM is unmapped, or there is some other type of * object mapped into that range (e.g. a vnode). for submap's kernel * objects, the only part of the object that can ever be populated is the * offsets that are managed by the submap. * * note that the "offset" in a kernel object is always the kernel virtual * address minus the vm_map_min(kernel_map). * example: * suppose kernel_map starts at 0xf8000000 and the kernel does a * uvm_km_alloc(kernel_map, PAGE_SIZE) [allocate 1 wired down page in the * kernel map]. if uvm_km_alloc returns virtual address 0xf8235000, * then that means that the page at offset 0x235000 in kernel_object is * mapped at 0xf8235000. * * kernel objects have one other special property: when the kernel virtual * memory mapping them is unmapped, the backing memory in the object is * freed right away. this is done with the uvm_km_pgremove() function. * this has to be done because there is no backing store for kernel pages * and no need to save them after they are no longer referenced. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/kthread.h> #include <uvm/uvm.h> /* * global data structures */ struct vm_map *kernel_map = NULL; /* Unconstraint range. */ struct uvm_constraint_range no_constraint = { 0x0, (paddr_t)-1 }; /* * local data structures */ static struct vm_map kernel_map_store; /* * uvm_km_init: init kernel maps and objects to reflect reality (i.e. * KVM already allocated for text, data, bss, and static data structures). * * => KVM is defined by [base.. base + VM_KERNEL_SPACE_SIZE]. * we assume that [base -> start] has already been allocated and that * "end" is the end of the kernel image span. */ void uvm_km_init(vaddr_t base, vaddr_t start, vaddr_t end) { /* kernel_object: for pageable anonymous kernel memory */ uao_init(); uvm.kernel_object = uao_create(VM_KERNEL_SPACE_SIZE, UAO_FLAG_KERNOBJ); /* * init the map and reserve already allocated kernel space * before installing. */ uvm_map_setup(&kernel_map_store, pmap_kernel(), base, end, #ifdef KVA_GUARDPAGES VM_MAP_PAGEABLE | VM_MAP_GUARDPAGES #else VM_MAP_PAGEABLE #endif ); if (base != start && uvm_map(&kernel_map_store, &base, start - base, NULL, UVM_UNKNOWN_OFFSET, 0, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE, MAP_INHERIT_NONE, MADV_RANDOM, UVM_FLAG_FIXED)) != 0) panic("uvm_km_init: could not reserve space for kernel"); kernel_map = &kernel_map_store; #ifndef __HAVE_PMAP_DIRECT /* allow km_alloc calls before uvm_km_thread starts */ mtx_init(&uvm_km_pages.mtx, IPL_VM); #endif } /* * uvm_km_suballoc: allocate a submap in the kernel map. once a submap * is allocated all references to that area of VM must go through it. this * allows the locking of VAs in kernel_map to be broken up into regions. * * => if `fixed' is true, *min specifies where the region described * by the submap must start * => if submap is non NULL we use that as the submap, otherwise we * alloc a new map */ struct vm_map * uvm_km_suballoc(struct vm_map *map, vaddr_t *min, vaddr_t *max, vsize_t size, int flags, boolean_t fixed, struct vm_map *submap) { int mapflags = UVM_FLAG_NOMERGE | (fixed ? UVM_FLAG_FIXED : 0); size = round_page(size); /* round up to pagesize */ /* first allocate a blank spot in the parent map */ if (uvm_map(map, min, size, NULL, UVM_UNKNOWN_OFFSET, 0, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE, MAP_INHERIT_NONE, MADV_RANDOM, mapflags)) != 0) { panic("uvm_km_suballoc: unable to allocate space in parent map"); } /* set VM bounds (min is filled in by uvm_map) */ *max = *min + size; /* add references to pmap and create or init the submap */ pmap_reference(vm_map_pmap(map)); if (submap == NULL) { submap = uvm_map_create(vm_map_pmap(map), *min, *max, flags); if (submap == NULL) panic("uvm_km_suballoc: unable to create submap"); } else { uvm_map_setup(submap, vm_map_pmap(map), *min, *max, flags); } /* * now let uvm_map_submap plug in it... */ if (uvm_map_submap(map, *min, *max, submap) != 0) panic("uvm_km_suballoc: submap allocation failed"); return(submap); } /* * uvm_km_pgremove: remove pages from a kernel uvm_object. * * => when you unmap a part of anonymous kernel memory you want to toss * the pages right away. (this gets called from uvm_unmap_...). */ void uvm_km_pgremove(struct uvm_object *uobj, vaddr_t startva, vaddr_t endva) { const voff_t start = startva - vm_map_min(kernel_map); const voff_t end = endva - vm_map_min(kernel_map); struct vm_page *pp; voff_t curoff; int slot; int swpgonlydelta = 0; KASSERT(UVM_OBJ_IS_AOBJ(uobj)); KASSERT(rw_write_held(uobj->vmobjlock)); pmap_remove(pmap_kernel(), startva, endva); for (curoff = start ; curoff < end ; curoff += PAGE_SIZE) { pp = uvm_pagelookup(uobj, curoff); if (pp && pp->pg_flags & PG_BUSY) { uvm_pagewait(pp, uobj->vmobjlock, "km_pgrm"); rw_enter(uobj->vmobjlock, RW_WRITE); curoff -= PAGE_SIZE; /* loop back to us */ continue; } /* free the swap slot, then the page */ slot = uao_dropswap(uobj, curoff >> PAGE_SHIFT); if (pp != NULL) { uvm_lock_pageq(); uvm_pagefree(pp); uvm_unlock_pageq(); } else if (slot != 0) { swpgonlydelta++; } } if (swpgonlydelta > 0) { KASSERT(uvmexp.swpgonly >= swpgonlydelta); atomic_add_int(&uvmexp.swpgonly, -swpgonlydelta); } } /* * uvm_km_pgremove_intrsafe: like uvm_km_pgremove(), but for "intrsafe" * objects * * => when you unmap a part of anonymous kernel memory you want to toss * the pages right away. (this gets called from uvm_unmap_...). * => none of the pages will ever be busy, and none of them will ever * be on the active or inactive queues (because these objects are * never allowed to "page"). */ void uvm_km_pgremove_intrsafe(vaddr_t start, vaddr_t end) { struct vm_page *pg; vaddr_t va; paddr_t pa; for (va = start; va < end; va += PAGE_SIZE) { if (!pmap_extract(pmap_kernel(), va, &pa)) continue; pg = PHYS_TO_VM_PAGE(pa); if (pg == NULL) panic("uvm_km_pgremove_intrsafe: no page"); uvm_pagefree(pg); } pmap_kremove(start, end - start); } /* * uvm_km_kmemalloc: lower level kernel memory allocator for malloc() * * => we map wired memory into the specified map using the obj passed in * => NOTE: we can return NULL even if we can wait if there is not enough * free VM space in the map... caller should be prepared to handle * this case. * => we return KVA of memory allocated * => flags: NOWAIT, VALLOC - just allocate VA, TRYLOCK - fail if we can't * lock the map * => low, high, alignment, boundary, nsegs are the corresponding parameters * to uvm_pglistalloc * => flags: ZERO - correspond to uvm_pglistalloc flags */ vaddr_t uvm_km_kmemalloc_pla(struct vm_map *map, struct uvm_object *obj, vsize_t size, vsize_t valign, int flags, paddr_t low, paddr_t high, paddr_t alignment, paddr_t boundary, int nsegs) { vaddr_t kva, loopva; voff_t offset; struct vm_page *pg; struct pglist pgl; int pla_flags; KASSERT(vm_map_pmap(map) == pmap_kernel()); /* UVM_KMF_VALLOC => !UVM_KMF_ZERO */ KASSERT(!(flags & UVM_KMF_VALLOC) || !(flags & UVM_KMF_ZERO)); /* setup for call */ size = round_page(size); kva = vm_map_min(map); /* hint */ if (nsegs == 0) nsegs = atop(size); /* allocate some virtual space */ if (__predict_false(uvm_map(map, &kva, size, obj, UVM_UNKNOWN_OFFSET, valign, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE, MAP_INHERIT_NONE, MADV_RANDOM, (flags & UVM_KMF_TRYLOCK))) != 0)) { return 0; } /* if all we wanted was VA, return now */ if (flags & UVM_KMF_VALLOC) { return kva; } /* recover object offset from virtual address */ if (obj != NULL) offset = kva - vm_map_min(kernel_map); else offset = 0; /* * now allocate and map in the memory... note that we are the only ones * whom should ever get a handle on this area of VM. */ TAILQ_INIT(&pgl); pla_flags = 0; KASSERT(uvmexp.swpgonly <= uvmexp.swpages); if ((flags & UVM_KMF_NOWAIT) || ((flags & UVM_KMF_CANFAIL) && uvmexp.swpages - uvmexp.swpgonly <= atop(size))) pla_flags |= UVM_PLA_NOWAIT; else pla_flags |= UVM_PLA_WAITOK; if (flags & UVM_KMF_ZERO) pla_flags |= UVM_PLA_ZERO; if (uvm_pglistalloc(size, low, high, alignment, boundary, &pgl, nsegs, pla_flags) != 0) { /* Failed. */ uvm_unmap(map, kva, kva + size); return (0); } if (obj != NULL) rw_enter(obj->vmobjlock, RW_WRITE); loopva = kva; while (loopva != kva + size) { pg = TAILQ_FIRST(&pgl); TAILQ_REMOVE(&pgl, pg, pageq); uvm_pagealloc_pg(pg, obj, offset, NULL); atomic_clearbits_int(&pg->pg_flags, PG_BUSY); UVM_PAGE_OWN(pg, NULL); /* * map it in: note that we call pmap_enter with the map and * object unlocked in case we are kmem_map. */ if (obj == NULL) { pmap_kenter_pa(loopva, VM_PAGE_TO_PHYS(pg), PROT_READ | PROT_WRITE); } else { pmap_enter(map->pmap, loopva, VM_PAGE_TO_PHYS(pg), PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE | PMAP_WIRED); } loopva += PAGE_SIZE; offset += PAGE_SIZE; } KASSERT(TAILQ_EMPTY(&pgl)); pmap_update(pmap_kernel()); if (obj != NULL) rw_exit(obj->vmobjlock); return kva; } /* * uvm_km_free: free an area of kernel memory */ void uvm_km_free(struct vm_map *map, vaddr_t addr, vsize_t size) { uvm_unmap(map, trunc_page(addr), round_page(addr+size)); } /* * uvm_km_alloc1: allocate wired down memory in the kernel map. * * => we can sleep if needed */ vaddr_t uvm_km_alloc1(struct vm_map *map, vsize_t size, vsize_t align, boolean_t zeroit) { vaddr_t kva, loopva; voff_t offset; struct vm_page *pg; KASSERT(vm_map_pmap(map) == pmap_kernel()); size = round_page(size); kva = vm_map_min(map); /* hint */ /* allocate some virtual space */ if (__predict_false(uvm_map(map, &kva, size, uvm.kernel_object, UVM_UNKNOWN_OFFSET, align, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_INHERIT_NONE, MADV_RANDOM, 0)) != 0)) { return 0; } /* recover object offset from virtual address */ offset = kva - vm_map_min(kernel_map); /* now allocate the memory. we must be careful about released pages. */ loopva = kva; while (size) { rw_enter(uvm.kernel_object->vmobjlock, RW_WRITE); /* allocate ram */ pg = uvm_pagealloc(uvm.kernel_object, offset, NULL, 0); if (pg) { atomic_clearbits_int(&pg->pg_flags, PG_BUSY); UVM_PAGE_OWN(pg, NULL); } rw_exit(uvm.kernel_object->vmobjlock); if (__predict_false(pg == NULL)) { if (curproc == uvm.pagedaemon_proc) { /* * It is unfeasible for the page daemon to * sleep for memory, so free what we have * allocated and fail. */ uvm_unmap(map, kva, loopva - kva); return (0); } else { uvm_wait("km_alloc1w"); /* wait for memory */ continue; } } /* * map it in; note we're never called with an intrsafe * object, so we always use regular old pmap_enter(). */ pmap_enter(map->pmap, loopva, VM_PAGE_TO_PHYS(pg), PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE | PMAP_WIRED); loopva += PAGE_SIZE; offset += PAGE_SIZE; size -= PAGE_SIZE; } pmap_update(map->pmap); /* * zero on request (note that "size" is now zero due to the above loop * so we need to subtract kva from loopva to reconstruct the size). */ if (zeroit) memset((caddr_t)kva, 0, loopva - kva); return kva; } #if defined(__HAVE_PMAP_DIRECT) /* * uvm_km_page allocator, __HAVE_PMAP_DIRECT arch * On architectures with machine memory direct mapped into a portion * of KVM, we have very little work to do. Just get a physical page, * and find and return its VA. */ void uvm_km_page_init(void) { /* nothing */ } void uvm_km_page_lateinit(void) { /* nothing */ } #else /* * uvm_km_page allocator, non __HAVE_PMAP_DIRECT archs * This is a special allocator that uses a reserve of free pages * to fulfill requests. It is fast and interrupt safe, but can only * return page sized regions. Its primary use is as a backend for pool. * * The memory returned is allocated from the larger kernel_map, sparing * pressure on the small interrupt-safe kmem_map. It is wired, but * not zero filled. */ struct uvm_km_pages uvm_km_pages; void uvm_km_createthread(void *); void uvm_km_thread(void *); struct uvm_km_free_page *uvm_km_doputpage(struct uvm_km_free_page *); /* * Allocate the initial reserve, and create the thread which will * keep the reserve full. For bootstrapping, we allocate more than * the lowat amount, because it may be a while before the thread is * running. */ void uvm_km_page_init(void) { int lowat_min; int i; int len, bulk; vaddr_t addr; if (!uvm_km_pages.lowat) { /* based on physmem, calculate a good value here */ uvm_km_pages.lowat = physmem / 256; lowat_min = physmem < atop(16 * 1024 * 1024) ? 32 : 128; if (uvm_km_pages.lowat < lowat_min) uvm_km_pages.lowat = lowat_min; } if (uvm_km_pages.lowat > UVM_KM_PAGES_LOWAT_MAX) uvm_km_pages.lowat = UVM_KM_PAGES_LOWAT_MAX; uvm_km_pages.hiwat = 4 * uvm_km_pages.lowat; if (uvm_km_pages.hiwat > UVM_KM_PAGES_HIWAT_MAX) uvm_km_pages.hiwat = UVM_KM_PAGES_HIWAT_MAX; /* Allocate all pages in as few allocations as possible. */ len = 0; bulk = uvm_km_pages.hiwat; while (len < uvm_km_pages.hiwat && bulk > 0) { bulk = MIN(bulk, uvm_km_pages.hiwat - len); addr = vm_map_min(kernel_map); if (uvm_map(kernel_map, &addr, (vsize_t)bulk << PAGE_SHIFT, NULL, UVM_UNKNOWN_OFFSET, 0, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE, MAP_INHERIT_NONE, MADV_RANDOM, UVM_KMF_TRYLOCK)) != 0) { bulk /= 2; continue; } for (i = len; i < len + bulk; i++, addr += PAGE_SIZE) uvm_km_pages.page[i] = addr; len += bulk; } uvm_km_pages.free = len; for (i = len; i < UVM_KM_PAGES_HIWAT_MAX; i++) uvm_km_pages.page[i] = 0; /* tone down if really high */ if (uvm_km_pages.lowat > 512) uvm_km_pages.lowat = 512; } void uvm_km_page_lateinit(void) { kthread_create_deferred(uvm_km_createthread, NULL); } void uvm_km_createthread(void *arg) { kthread_create(uvm_km_thread, NULL, &uvm_km_pages.km_proc, "kmthread"); } /* * Endless loop. We grab pages in increments of 16 pages, then * quickly swap them into the list. */ void uvm_km_thread(void *arg) { vaddr_t pg[16]; int i; int allocmore = 0; int flags; struct uvm_km_free_page *fp = NULL; KERNEL_UNLOCK(); for (;;) { mtx_enter(&uvm_km_pages.mtx); if (uvm_km_pages.free >= uvm_km_pages.lowat && uvm_km_pages.freelist == NULL) { msleep_nsec(&uvm_km_pages.km_proc, &uvm_km_pages.mtx, PVM, "kmalloc", INFSLP); } allocmore = uvm_km_pages.free < uvm_km_pages.lowat; fp = uvm_km_pages.freelist; uvm_km_pages.freelist = NULL; uvm_km_pages.freelistlen = 0; mtx_leave(&uvm_km_pages.mtx); if (allocmore) { /* * If there was nothing on the freelist, then we * must obtain at least one page to make progress. * So, only use UVM_KMF_TRYLOCK for the first page * if fp != NULL */ flags = UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE, MAP_INHERIT_NONE, MADV_RANDOM, fp != NULL ? UVM_KMF_TRYLOCK : 0); memset(pg, 0, sizeof(pg)); for (i = 0; i < nitems(pg); i++) { pg[i] = vm_map_min(kernel_map); if (uvm_map(kernel_map, &pg[i], PAGE_SIZE, NULL, UVM_UNKNOWN_OFFSET, 0, flags) != 0) { pg[i] = 0; break; } /* made progress, so don't sleep for more */ flags = UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE, MAP_INHERIT_NONE, MADV_RANDOM, UVM_KMF_TRYLOCK); } mtx_enter(&uvm_km_pages.mtx); for (i = 0; i < nitems(pg); i++) { if (uvm_km_pages.free == nitems(uvm_km_pages.page)) break; else if (pg[i] != 0) uvm_km_pages.page[uvm_km_pages.free++] = pg[i]; } wakeup(&uvm_km_pages.free); mtx_leave(&uvm_km_pages.mtx); /* Cleanup left-over pages (if any). */ for (; i < nitems(pg); i++) { if (pg[i] != 0) { uvm_unmap(kernel_map, pg[i], pg[i] + PAGE_SIZE); } } } while (fp) { fp = uvm_km_doputpage(fp); } } } struct uvm_km_free_page * uvm_km_doputpage(struct uvm_km_free_page *fp) { vaddr_t va = (vaddr_t)fp; struct vm_page *pg; int freeva = 1; struct uvm_km_free_page *nextfp = fp->next; pg = uvm_atopg(va); pmap_kremove(va, PAGE_SIZE); pmap_update(kernel_map->pmap); mtx_enter(&uvm_km_pages.mtx); if (uvm_km_pages.free < uvm_km_pages.hiwat) { uvm_km_pages.page[uvm_km_pages.free++] = va; freeva = 0; } mtx_leave(&uvm_km_pages.mtx); if (freeva) uvm_unmap(kernel_map, va, va + PAGE_SIZE); uvm_pagefree(pg); return (nextfp); } #endif /* !__HAVE_PMAP_DIRECT */ void * km_alloc(size_t sz, const struct kmem_va_mode *kv, const struct kmem_pa_mode *kp, const struct kmem_dyn_mode *kd) { struct vm_map *map; struct vm_page *pg; struct pglist pgl; int mapflags = 0; vm_prot_t prot; paddr_t pla_align; int pla_flags; int pla_maxseg; vaddr_t va, sva = 0; KASSERT(sz == round_page(sz)); TAILQ_INIT(&pgl); if (kp->kp_nomem || kp->kp_pageable) goto alloc_va; pla_flags = kd->kd_waitok ? UVM_PLA_WAITOK : UVM_PLA_NOWAIT; pla_flags |= UVM_PLA_TRYCONTIG; if (kp->kp_zero) pla_flags |= UVM_PLA_ZERO; pla_align = kp->kp_align; #ifdef __HAVE_PMAP_DIRECT if (pla_align < kv->kv_align) pla_align = kv->kv_align; #endif pla_maxseg = kp->kp_maxseg; if (pla_maxseg == 0) pla_maxseg = sz / PAGE_SIZE; if (uvm_pglistalloc(sz, kp->kp_constraint->ucr_low, kp->kp_constraint->ucr_high, pla_align, kp->kp_boundary, &pgl, pla_maxseg, pla_flags)) { return (NULL); } #ifdef __HAVE_PMAP_DIRECT /* * Only use direct mappings for single page or single segment * allocations. */ if (kv->kv_singlepage || kp->kp_maxseg == 1) { TAILQ_FOREACH(pg, &pgl, pageq) { va = pmap_map_direct(pg); if (pg == TAILQ_FIRST(&pgl)) sva = va; } return ((void *)sva); } #endif alloc_va: prot = PROT_READ | PROT_WRITE; if (kp->kp_pageable) { KASSERT(kp->kp_object); KASSERT(!kv->kv_singlepage); } else { KASSERT(kp->kp_object == NULL); } if (kv->kv_singlepage) { KASSERT(sz == PAGE_SIZE); #ifdef __HAVE_PMAP_DIRECT panic("km_alloc: DIRECT single page"); #else mtx_enter(&uvm_km_pages.mtx); while (uvm_km_pages.free == 0) { if (kd->kd_waitok == 0) { mtx_leave(&uvm_km_pages.mtx); uvm_pglistfree(&pgl); return NULL; } msleep_nsec(&uvm_km_pages.free, &uvm_km_pages.mtx, PVM, "getpage", INFSLP); } va = uvm_km_pages.page[--uvm_km_pages.free]; if (uvm_km_pages.free < uvm_km_pages.lowat && curproc != uvm_km_pages.km_proc) { if (kd->kd_slowdown) *kd->kd_slowdown = 1; wakeup(&uvm_km_pages.km_proc); } mtx_leave(&uvm_km_pages.mtx); #endif } else { struct uvm_object *uobj = NULL; if (kd->kd_trylock) mapflags |= UVM_KMF_TRYLOCK; if (kp->kp_object) uobj = *kp->kp_object; try_map: map = *kv->kv_map; va = vm_map_min(map); if (uvm_map(map, &va, sz, uobj, kd->kd_prefer, kv->kv_align, UVM_MAPFLAG(prot, prot, MAP_INHERIT_NONE, MADV_RANDOM, mapflags))) { if (kv->kv_wait && kd->kd_waitok) { tsleep_nsec(map, PVM, "km_allocva", INFSLP); goto try_map; } uvm_pglistfree(&pgl); return (NULL); } } sva = va; TAILQ_FOREACH(pg, &pgl, pageq) { if (kp->kp_pageable) pmap_enter(pmap_kernel(), va, VM_PAGE_TO_PHYS(pg), prot, prot | PMAP_WIRED); else pmap_kenter_pa(va, VM_PAGE_TO_PHYS(pg), prot); va += PAGE_SIZE; } pmap_update(pmap_kernel()); return ((void *)sva); } void km_free(void *v, size_t sz, const struct kmem_va_mode *kv, const struct kmem_pa_mode *kp) { vaddr_t sva, eva, va; struct vm_page *pg; struct pglist pgl; sva = (vaddr_t)v; eva = sva + sz; if (kp->kp_nomem) goto free_va; #ifdef __HAVE_PMAP_DIRECT if (kv->kv_singlepage || kp->kp_maxseg == 1) { TAILQ_INIT(&pgl); for (va = sva; va < eva; va += PAGE_SIZE) { pg = pmap_unmap_direct(va); TAILQ_INSERT_TAIL(&pgl, pg, pageq); } uvm_pglistfree(&pgl); return; } #else if (kv->kv_singlepage) { struct uvm_km_free_page *fp = v; mtx_enter(&uvm_km_pages.mtx); fp->next = uvm_km_pages.freelist; uvm_km_pages.freelist = fp; if (uvm_km_pages.freelistlen++ > 16) wakeup(&uvm_km_pages.km_proc); mtx_leave(&uvm_km_pages.mtx); return; } #endif if (kp->kp_pageable) { pmap_remove(pmap_kernel(), sva, eva); pmap_update(pmap_kernel()); } else { TAILQ_INIT(&pgl); for (va = sva; va < eva; va += PAGE_SIZE) { paddr_t pa; if (!pmap_extract(pmap_kernel(), va, &pa)) continue; pg = PHYS_TO_VM_PAGE(pa); if (pg == NULL) { panic("km_free: unmanaged page 0x%lx", pa); } TAILQ_INSERT_TAIL(&pgl, pg, pageq); } pmap_kremove(sva, sz); pmap_update(pmap_kernel()); uvm_pglistfree(&pgl); } free_va: uvm_unmap(*kv->kv_map, sva, eva); if (kv->kv_wait) wakeup(*kv->kv_map); } const struct kmem_va_mode kv_any = { .kv_map = &kernel_map, }; const struct kmem_va_mode kv_intrsafe = { .kv_map = &kmem_map, }; const struct kmem_va_mode kv_page = { .kv_singlepage = 1 }; const struct kmem_pa_mode kp_dirty = { .kp_constraint = &no_constraint }; const struct kmem_pa_mode kp_dma = { .kp_constraint = &dma_constraint }; const struct kmem_pa_mode kp_dma_contig = { .kp_constraint = &dma_constraint, .kp_maxseg = 1 }; const struct kmem_pa_mode kp_dma_zero = { .kp_constraint = &dma_constraint, .kp_zero = 1 }; const struct kmem_pa_mode kp_zero = { .kp_constraint = &no_constraint, .kp_zero = 1 }; const struct kmem_pa_mode kp_pageable = { .kp_object = &uvm.kernel_object, .kp_pageable = 1 /* XXX - kp_nomem, maybe, but we'll need to fix km_free. */ }; const struct kmem_pa_mode kp_none = { .kp_nomem = 1 }; const struct kmem_dyn_mode kd_waitok = { .kd_waitok = 1, .kd_prefer = UVM_UNKNOWN_OFFSET }; const struct kmem_dyn_mode kd_nowait = { .kd_prefer = UVM_UNKNOWN_OFFSET }; const struct kmem_dyn_mode kd_trylock = { .kd_trylock = 1, .kd_prefer = UVM_UNKNOWN_OFFSET };
1 1 16 16 1792 1775 1773 215 215 161 17 17 931 932 69 69 69 857 756 754 125 123 63 45 46 252 251 378 379 37 39 8 8 12 12 12 12 12 12 12 12 12 12 12 12 12 12 8 6 2 5 5 5 16 2 8 5 1 12 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 /* $OpenBSD: kern_tc.c,v 1.83 2024/02/23 23:01:15 cheloha Exp $ */ /* * Copyright (c) 2000 Poul-Henning Kamp <phk@FreeBSD.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * If we meet some day, and you think this stuff is worth it, you * can buy me a beer in return. Poul-Henning Kamp */ #include <sys/param.h> #include <sys/atomic.h> #include <sys/kernel.h> #include <sys/mutex.h> #include <sys/rwlock.h> #include <sys/stdint.h> #include <sys/timeout.h> #include <sys/sysctl.h> #include <sys/syslog.h> #include <sys/systm.h> #include <sys/timetc.h> #include <sys/queue.h> #include <sys/malloc.h> u_int dummy_get_timecount(struct timecounter *); int sysctl_tc_hardware(void *, size_t *, void *, size_t); int sysctl_tc_choice(void *, size_t *, void *, size_t); /* * Implement a dummy timecounter which we can use until we get a real one * in the air. This allows the console and other early stuff to use * time services. */ u_int dummy_get_timecount(struct timecounter *tc) { static u_int now; return atomic_inc_int_nv(&now); } static struct timecounter dummy_timecounter = { .tc_get_timecount = dummy_get_timecount, .tc_counter_mask = ~0u, .tc_frequency = 1000000, .tc_name = "dummy", .tc_quality = -1000000, .tc_priv = NULL, .tc_user = 0, }; /* * Locks used to protect struct members, global variables in this file: * I immutable after initialization * T tc_lock * W windup_mtx */ struct timehands { /* These fields must be initialized by the driver. */ struct timecounter *th_counter; /* [W] */ int64_t th_adjtimedelta; /* [T,W] */ struct bintime th_next_ntp_update; /* [T,W] */ int64_t th_adjustment; /* [W] */ u_int64_t th_scale; /* [W] */ u_int th_offset_count; /* [W] */ struct bintime th_boottime; /* [T,W] */ struct bintime th_offset; /* [W] */ struct bintime th_naptime; /* [W] */ struct timeval th_microtime; /* [W] */ struct timespec th_nanotime; /* [W] */ /* Fields not to be copied in tc_windup start with th_generation. */ volatile u_int th_generation; /* [W] */ struct timehands *th_next; /* [I] */ }; static struct timehands th0; static struct timehands th1 = { .th_next = &th0 }; static struct timehands th0 = { .th_counter = &dummy_timecounter, .th_scale = UINT64_MAX / 1000000, .th_offset = { .sec = 0, .frac = 0 }, .th_generation = 1, .th_next = &th1 }; struct rwlock tc_lock = RWLOCK_INITIALIZER("tc_lock"); /* * tc_windup() must be called before leaving this mutex. */ struct mutex windup_mtx = MUTEX_INITIALIZER(IPL_CLOCK); static struct timehands *volatile timehands = &th0; /* [W] */ struct timecounter *timecounter = &dummy_timecounter; /* [T] */ static SLIST_HEAD(, timecounter) tc_list = SLIST_HEAD_INITIALIZER(tc_list); /* * These are updated from tc_windup(). They are useful when * examining kernel core dumps. */ volatile time_t naptime = 0; volatile time_t time_second = 0; volatile time_t time_uptime = 0; static int timestepwarnings; void ntp_update_second(struct timehands *); void tc_windup(struct bintime *, struct bintime *, int64_t *); /* * Return the difference between the timehands' counter value now and what * was when we copied it to the timehands' offset_count. */ static __inline u_int tc_delta(struct timehands *th) { struct timecounter *tc; tc = th->th_counter; return ((tc->tc_get_timecount(tc) - th->th_offset_count) & tc->tc_counter_mask); } /* * Functions for reading the time. We have to loop until we are sure that * the timehands that we operated on was not updated under our feet. See * the comment in <sys/time.h> for a description of these functions. */ void binboottime(struct bintime *bt) { struct timehands *th; u_int gen; do { th = timehands; gen = th->th_generation; membar_consumer(); *bt = th->th_boottime; membar_consumer(); } while (gen == 0 || gen != th->th_generation); } void microboottime(struct timeval *tvp) { struct bintime bt; binboottime(&bt); BINTIME_TO_TIMEVAL(&bt, tvp); } void nanoboottime(struct timespec *tsp) { struct bintime bt; binboottime(&bt); BINTIME_TO_TIMESPEC(&bt, tsp); } void binuptime(struct bintime *bt) { struct timehands *th; u_int gen; do { th = timehands; gen = th->th_generation; membar_consumer(); TIMECOUNT_TO_BINTIME(tc_delta(th), th->th_scale, bt); bintimeadd(bt, &th->th_offset, bt); membar_consumer(); } while (gen == 0 || gen != th->th_generation); } void getbinuptime(struct bintime *bt) { struct timehands *th; u_int gen; do { th = timehands; gen = th->th_generation; membar_consumer(); *bt = th->th_offset; membar_consumer(); } while (gen == 0 || gen != th->th_generation); } void nanouptime(struct timespec *tsp) { struct bintime bt; binuptime(&bt); BINTIME_TO_TIMESPEC(&bt, tsp); } void microuptime(struct timeval *tvp) { struct bintime bt; binuptime(&bt); BINTIME_TO_TIMEVAL(&bt, tvp); } time_t getuptime(void) { #if defined(__LP64__) return time_uptime; /* atomic */ #else time_t now; struct timehands *th; u_int gen; do { th = timehands; gen = th->th_generation; membar_consumer(); now = th->th_offset.sec; membar_consumer(); } while (gen == 0 || gen != th->th_generation); return now; #endif } uint64_t nsecuptime(void) { struct bintime bt; binuptime(&bt); return BINTIME_TO_NSEC(&bt); } uint64_t getnsecuptime(void) { struct bintime bt; getbinuptime(&bt); return BINTIME_TO_NSEC(&bt); } void binruntime(struct bintime *bt) { struct timehands *th; u_int gen; do { th = timehands; gen = th->th_generation; membar_consumer(); TIMECOUNT_TO_BINTIME(tc_delta(th), th->th_scale, bt); bintimeadd(bt, &th->th_offset, bt); bintimesub(bt, &th->th_naptime, bt); membar_consumer(); } while (gen == 0 || gen != th->th_generation); } void nanoruntime(struct timespec *ts) { struct bintime bt; binruntime(&bt); BINTIME_TO_TIMESPEC(&bt, ts); } void getbinruntime(struct bintime *bt) { struct timehands *th; u_int gen; do { th = timehands; gen = th->th_generation; membar_consumer(); bintimesub(&th->th_offset, &th->th_naptime, bt); membar_consumer(); } while (gen == 0 || gen != th->th_generation); } uint64_t getnsecruntime(void) { struct bintime bt; getbinruntime(&bt); return BINTIME_TO_NSEC(&bt); } void bintime(struct bintime *bt) { struct timehands *th; u_int gen; do { th = timehands; gen = th->th_generation; membar_consumer(); TIMECOUNT_TO_BINTIME(tc_delta(th), th->th_scale, bt); bintimeadd(bt, &th->th_offset, bt); bintimeadd(bt, &th->th_boottime, bt); membar_consumer(); } while (gen == 0 || gen != th->th_generation); } void nanotime(struct timespec *tsp) { struct bintime bt; bintime(&bt); BINTIME_TO_TIMESPEC(&bt, tsp); } void microtime(struct timeval *tvp) { struct bintime bt; bintime(&bt); BINTIME_TO_TIMEVAL(&bt, tvp); } time_t gettime(void) { #if defined(__LP64__) return time_second; /* atomic */ #else time_t now; struct timehands *th; u_int gen; do { th = timehands; gen = th->th_generation; membar_consumer(); now = th->th_microtime.tv_sec; membar_consumer(); } while (gen == 0 || gen != th->th_generation); return now; #endif } void getnanouptime(struct timespec *tsp) { struct timehands *th; u_int gen; do { th = timehands; gen = th->th_generation; membar_consumer(); BINTIME_TO_TIMESPEC(&th->th_offset, tsp); membar_consumer(); } while (gen == 0 || gen != th->th_generation); } void getmicrouptime(struct timeval *tvp) { struct timehands *th; u_int gen; do { th = timehands; gen = th->th_generation; membar_consumer(); BINTIME_TO_TIMEVAL(&th->th_offset, tvp); membar_consumer(); } while (gen == 0 || gen != th->th_generation); } void getnanotime(struct timespec *tsp) { struct timehands *th; u_int gen; do { th = timehands; gen = th->th_generation; membar_consumer(); *tsp = th->th_nanotime; membar_consumer(); } while (gen == 0 || gen != th->th_generation); } void getmicrotime(struct timeval *tvp) { struct timehands *th; u_int gen; do { th = timehands; gen = th->th_generation; membar_consumer(); *tvp = th->th_microtime; membar_consumer(); } while (gen == 0 || gen != th->th_generation); } /* * Initialize a new timecounter and possibly use it. */ void tc_init(struct timecounter *tc) { u_int64_t tmp; u_int u; u = tc->tc_frequency / tc->tc_counter_mask; /* XXX: We need some margin here, 10% is a guess */ u *= 11; u /= 10; if (tc->tc_quality >= 0) { if (u > hz) { tc->tc_quality = -2000; printf("Timecounter \"%s\" frequency %lu Hz", tc->tc_name, (unsigned long)tc->tc_frequency); printf(" -- Insufficient hz, needs at least %u\n", u); } } /* Determine the counter's precision. */ for (tmp = 1; (tmp & tc->tc_counter_mask) == 0; tmp <<= 1) continue; tc->tc_precision = tmp; SLIST_INSERT_HEAD(&tc_list, tc, tc_next); /* * Never automatically use a timecounter with negative quality. * Even though we run on the dummy counter, switching here may be * worse since this timecounter may not be monotonic. */ if (tc->tc_quality < 0) return; if (tc->tc_quality < timecounter->tc_quality) return; if (tc->tc_quality == timecounter->tc_quality && tc->tc_frequency < timecounter->tc_frequency) return; (void)tc->tc_get_timecount(tc); enqueue_randomness(tc->tc_get_timecount(tc)); timecounter = tc; } /* * Change the given timecounter's quality. If it is the active * counter and it is no longer the best counter, activate the * best counter. */ void tc_reset_quality(struct timecounter *tc, int quality) { struct timecounter *best = &dummy_timecounter, *tmp; if (tc == &dummy_timecounter) panic("%s: cannot change dummy counter quality", __func__); tc->tc_quality = quality; if (timecounter == tc) { SLIST_FOREACH(tmp, &tc_list, tc_next) { if (tmp->tc_quality < 0) continue; if (tmp->tc_quality < best->tc_quality) continue; if (tmp->tc_quality == best->tc_quality && tmp->tc_frequency < best->tc_frequency) continue; best = tmp; } if (best != tc) { enqueue_randomness(best->tc_get_timecount(best)); timecounter = best; printf("timecounter: active counter changed: %s -> %s\n", tc->tc_name, best->tc_name); } } } /* Report the frequency of the current timecounter. */ u_int64_t tc_getfrequency(void) { return (timehands->th_counter->tc_frequency); } /* Report the precision of the current timecounter. */ u_int64_t tc_getprecision(void) { return (timehands->th_counter->tc_precision); } /* * Step our concept of UTC, aka the realtime clock. * This is done by modifying our estimate of when we booted. * * Any ongoing adjustment is meaningless after a clock jump, * so we zero adjtimedelta here as well. */ void tc_setrealtimeclock(const struct timespec *ts) { struct bintime boottime, old_utc, uptime, utc; struct timespec tmp; int64_t zero = 0; TIMESPEC_TO_BINTIME(ts, &utc); rw_enter_write(&tc_lock); mtx_enter(&windup_mtx); binuptime(&uptime); bintimesub(&utc, &uptime, &boottime); bintimeadd(&timehands->th_boottime, &uptime, &old_utc); /* XXX fiddle all the little crinkly bits around the fiords... */ tc_windup(&boottime, NULL, &zero); mtx_leave(&windup_mtx); rw_exit_write(&tc_lock); enqueue_randomness(ts->tv_sec); if (timestepwarnings) { BINTIME_TO_TIMESPEC(&old_utc, &tmp); log(LOG_INFO, "Time stepped from %lld.%09ld to %lld.%09ld\n", (long long)tmp.tv_sec, tmp.tv_nsec, (long long)ts->tv_sec, ts->tv_nsec); } } /* * Step the monotonic and realtime clocks, triggering any timeouts that * should have occurred across the interval. */ void tc_setclock(const struct timespec *ts) { struct bintime new_naptime, old_naptime, uptime, utc; static int first = 1; #ifndef SMALL_KERNEL struct bintime elapsed; long long adj_ticks; #endif /* * When we're called for the first time, during boot when * the root partition is mounted, we need to set boottime. */ if (first) { tc_setrealtimeclock(ts); first = 0; return; } enqueue_randomness(ts->tv_sec); TIMESPEC_TO_BINTIME(ts, &utc); mtx_enter(&windup_mtx); bintimesub(&utc, &timehands->th_boottime, &uptime); old_naptime = timehands->th_naptime; /* XXX fiddle all the little crinkly bits around the fiords... */ tc_windup(NULL, &uptime, NULL); new_naptime = timehands->th_naptime; mtx_leave(&windup_mtx); #ifndef SMALL_KERNEL /* convert the bintime to ticks */ bintimesub(&new_naptime, &old_naptime, &elapsed); adj_ticks = BINTIME_TO_NSEC(&elapsed) / tick_nsec; if (adj_ticks > 0) { if (adj_ticks > INT_MAX) adj_ticks = INT_MAX; timeout_adjust_ticks(adj_ticks); } #endif } void tc_update_timekeep(void) { static struct timecounter *last_tc = NULL; struct timehands *th; MUTEX_ASSERT_LOCKED(&windup_mtx); if (timekeep == NULL) return; th = timehands; timekeep->tk_generation = 0; membar_producer(); timekeep->tk_scale = th->th_scale; timekeep->tk_offset_count = th->th_offset_count; timekeep->tk_offset = th->th_offset; timekeep->tk_naptime = th->th_naptime; timekeep->tk_boottime = th->th_boottime; if (last_tc != th->th_counter) { timekeep->tk_counter_mask = th->th_counter->tc_counter_mask; timekeep->tk_user = th->th_counter->tc_user; last_tc = th->th_counter; } membar_producer(); timekeep->tk_generation = th->th_generation; return; } /* * Initialize the next struct timehands in the ring and make * it the active timehands. Along the way we might switch to a different * timecounter and/or do seconds processing in NTP. Slightly magic. */ void tc_windup(struct bintime *new_boottime, struct bintime *new_offset, int64_t *new_adjtimedelta) { struct bintime bt; struct timecounter *active_tc; struct timehands *th, *tho; u_int64_t scale; u_int delta, ncount, ogen; if (new_boottime != NULL || new_adjtimedelta != NULL) rw_assert_wrlock(&tc_lock); MUTEX_ASSERT_LOCKED(&windup_mtx); active_tc = timecounter; /* * Make the next timehands a copy of the current one, but do not * overwrite the generation or next pointer. While we update * the contents, the generation must be zero. */ tho = timehands; ogen = tho->th_generation; th = tho->th_next; th->th_generation = 0; membar_producer(); memcpy(th, tho, offsetof(struct timehands, th_generation)); /* * Capture a timecounter delta on the current timecounter and if * changing timecounters, a counter value from the new timecounter. * Update the offset fields accordingly. */ delta = tc_delta(th); if (th->th_counter != active_tc) ncount = active_tc->tc_get_timecount(active_tc); else ncount = 0; th->th_offset_count += delta; th->th_offset_count &= th->th_counter->tc_counter_mask; TIMECOUNT_TO_BINTIME(delta, th->th_scale, &bt); bintimeadd(&th->th_offset, &bt, &th->th_offset); /* * Ignore new offsets that predate the current offset. * If changing the offset, first increase the naptime * accordingly. */ if (new_offset != NULL && bintimecmp(&th->th_offset, new_offset, <)) { bintimesub(new_offset, &th->th_offset, &bt); bintimeadd(&th->th_naptime, &bt, &th->th_naptime); naptime = th->th_naptime.sec; th->th_offset = *new_offset; } /* * If changing the boot time or clock adjustment, do so before * NTP processing. */ if (new_boottime != NULL) th->th_boottime = *new_boottime; if (new_adjtimedelta != NULL) { th->th_adjtimedelta = *new_adjtimedelta; /* Reset the NTP update period. */ bintimesub(&th->th_offset, &th->th_naptime, &th->th_next_ntp_update); } /* * Deal with NTP second processing. The while-loop normally * iterates at most once, but in extreme situations it might * keep NTP sane if tc_windup() is not run for several seconds. */ bintimesub(&th->th_offset, &th->th_naptime, &bt); while (bintimecmp(&th->th_next_ntp_update, &bt, <=)) { ntp_update_second(th); th->th_next_ntp_update.sec++; } /* Update the UTC timestamps used by the get*() functions. */ bintimeadd(&th->th_boottime, &th->th_offset, &bt); BINTIME_TO_TIMEVAL(&bt, &th->th_microtime); BINTIME_TO_TIMESPEC(&bt, &th->th_nanotime); /* Now is a good time to change timecounters. */ if (th->th_counter != active_tc) { th->th_counter = active_tc; th->th_offset_count = ncount; } /*- * Recalculate the scaling factor. We want the number of 1/2^64 * fractions of a second per period of the hardware counter, taking * into account the th_adjustment factor which the NTP PLL/adjtime(2) * processing provides us with. * * The th_adjustment is nanoseconds per second with 32 bit binary * fraction and we want 64 bit binary fraction of second: * * x = a * 2^32 / 10^9 = a * 4.294967296 * * The range of th_adjustment is +/- 5000PPM so inside a 64bit int * we can only multiply by about 850 without overflowing, but that * leaves suitably precise fractions for multiply before divide. * * Divide before multiply with a fraction of 2199/512 results in a * systematic undercompensation of 10PPM of th_adjustment. On a * 5000PPM adjustment this is a 0.05PPM error. This is acceptable. * * We happily sacrifice the lowest of the 64 bits of our result * to the goddess of code clarity. * */ scale = (u_int64_t)1 << 63; scale += \ ((th->th_adjustment + th->th_counter->tc_freq_adj) / 1024) * 2199; scale /= th->th_counter->tc_frequency; th->th_scale = scale * 2; /* * Now that the struct timehands is again consistent, set the new * generation number, making sure to not make it zero. */ if (++ogen == 0) ogen = 1; membar_producer(); th->th_generation = ogen; /* Go live with the new struct timehands. */ time_second = th->th_microtime.tv_sec; time_uptime = th->th_offset.sec; membar_producer(); timehands = th; tc_update_timekeep(); } /* Report or change the active timecounter hardware. */ int sysctl_tc_hardware(void *oldp, size_t *oldlenp, void *newp, size_t newlen) { char newname[32]; struct timecounter *newtc, *tc; int error; tc = timecounter; strlcpy(newname, tc->tc_name, sizeof(newname)); error = sysctl_string(oldp, oldlenp, newp, newlen, newname, sizeof(newname)); if (error != 0 || strcmp(newname, tc->tc_name) == 0) return (error); SLIST_FOREACH(newtc, &tc_list, tc_next) { if (strcmp(newname, newtc->tc_name) != 0) continue; /* Warm up new timecounter. */ (void)newtc->tc_get_timecount(newtc); (void)newtc->tc_get_timecount(newtc); rw_enter_write(&tc_lock); timecounter = newtc; rw_exit_write(&tc_lock); return (0); } return (EINVAL); } /* Report or change the active timecounter hardware. */ int sysctl_tc_choice(void *oldp, size_t *oldlenp, void *newp, size_t newlen) { char buf[32], *spc, *choices; struct timecounter *tc; int error, maxlen; if (SLIST_EMPTY(&tc_list)) return (sysctl_rdstring(oldp, oldlenp, newp, "")); spc = ""; maxlen = 0; SLIST_FOREACH(tc, &tc_list, tc_next) maxlen += sizeof(buf); choices = malloc(maxlen, M_TEMP, M_WAITOK); *choices = '\0'; SLIST_FOREACH(tc, &tc_list, tc_next) { snprintf(buf, sizeof(buf), "%s%s(%d)", spc, tc->tc_name, tc->tc_quality); spc = " "; strlcat(choices, buf, maxlen); } error = sysctl_rdstring(oldp, oldlenp, newp, choices); free(choices, M_TEMP, maxlen); return (error); } /* * Timecounters need to be updated every so often to prevent the hardware * counter from overflowing. Updating also recalculates the cached values * used by the get*() family of functions, so their precision depends on * the update frequency. */ static int tc_tick; void tc_ticktock(void) { static int count; if (++count < tc_tick) return; if (!mtx_enter_try(&windup_mtx)) return; count = 0; tc_windup(NULL, NULL, NULL); mtx_leave(&windup_mtx); } void inittimecounter(void) { #ifdef DEBUG u_int p; #endif /* * Set the initial timeout to * max(1, <approx. number of hardclock ticks in a millisecond>). * People should probably not use the sysctl to set the timeout * to smaller than its initial value, since that value is the * smallest reasonable one. If they want better timestamps they * should use the non-"get"* functions. */ if (hz > 1000) tc_tick = (hz + 500) / 1000; else tc_tick = 1; #ifdef DEBUG p = (tc_tick * 1000000) / hz; printf("Timecounters tick every %d.%03u msec\n", p / 1000, p % 1000); #endif /* warm up new timecounter (again) and get rolling. */ (void)timecounter->tc_get_timecount(timecounter); (void)timecounter->tc_get_timecount(timecounter); } const struct sysctl_bounded_args tc_vars[] = { { KERN_TIMECOUNTER_TICK, &tc_tick, SYSCTL_INT_READONLY }, { KERN_TIMECOUNTER_TIMESTEPWARNINGS, &timestepwarnings, 0, 1 }, }; /* * Return timecounter-related information. */ int sysctl_tc(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { if (namelen != 1) return (ENOTDIR); switch (name[0]) { case KERN_TIMECOUNTER_HARDWARE: return (sysctl_tc_hardware(oldp, oldlenp, newp, newlen)); case KERN_TIMECOUNTER_CHOICE: return (sysctl_tc_choice(oldp, oldlenp, newp, newlen)); default: return (sysctl_bounded_arr(tc_vars, nitems(tc_vars), name, namelen, oldp, oldlenp, newp, newlen)); } /* NOTREACHED */ } /* * Skew the timehands according to any adjtime(2) adjustment. */ void ntp_update_second(struct timehands *th) { int64_t adj; MUTEX_ASSERT_LOCKED(&windup_mtx); if (th->th_adjtimedelta > 0) adj = MIN(5000, th->th_adjtimedelta); else adj = MAX(-5000, th->th_adjtimedelta); th->th_adjtimedelta -= adj; th->th_adjustment = (adj * 1000) << 32; } void tc_adjfreq(int64_t *old, int64_t *new) { if (old != NULL) { rw_assert_anylock(&tc_lock); *old = timecounter->tc_freq_adj; } if (new != NULL) { rw_assert_wrlock(&tc_lock); mtx_enter(&windup_mtx); timecounter->tc_freq_adj = *new; tc_windup(NULL, NULL, NULL); mtx_leave(&windup_mtx); } } void tc_adjtime(int64_t *old, int64_t *new) { struct timehands *th; u_int gen; if (old != NULL) { do { th = timehands; gen = th->th_generation; membar_consumer(); *old = th->th_adjtimedelta; membar_consumer(); } while (gen == 0 || gen != th->th_generation); } if (new != NULL) { rw_assert_wrlock(&tc_lock); mtx_enter(&windup_mtx); tc_windup(NULL, NULL, new); mtx_leave(&windup_mtx); } }
27 2 24 4 27 2 15 10 6 2 7 7 2 15 9 20 4 16 1 2 6 24 7 1 4 2 1752 1748 1747 1745 19 17 10 19 10 18 1 13 5 18 1 8 8 8 5 4 8 8 8 7 8 26 9 2 2 24 6 24 24 24 648 619 123 3 646 654 653 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 /* $OpenBSD: kern_resource.c,v 1.83 2024/05/22 09:20:22 claudio Exp $ */ /* $NetBSD: kern_resource.c,v 1.38 1996/10/23 07:19:38 matthias Exp $ */ /*- * Copyright (c) 1982, 1986, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_resource.c 8.5 (Berkeley) 1/21/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/file.h> #include <sys/resourcevar.h> #include <sys/pool.h> #include <sys/proc.h> #include <sys/ktrace.h> #include <sys/sched.h> #include <sys/signalvar.h> #include <sys/mount.h> #include <sys/syscallargs.h> #include <uvm/uvm_extern.h> #include <uvm/uvm.h> /* Resource usage check interval in msec */ #define RUCHECK_INTERVAL 1000 /* SIGXCPU interval in seconds of process runtime */ #define SIGXCPU_INTERVAL 5 struct plimit *lim_copy(struct plimit *); struct plimit *lim_write_begin(void); void lim_write_commit(struct plimit *); void tuagg_sub(struct tusage *, struct proc *, const struct timespec *); /* * Patchable maximum data and stack limits. */ rlim_t maxdmap = MAXDSIZ; rlim_t maxsmap = MAXSSIZ; /* * Serializes resource limit updates. * This lock has to be held together with ps_mtx when updating * the process' ps_limit. */ struct rwlock rlimit_lock = RWLOCK_INITIALIZER("rlimitlk"); /* * Resource controls and accounting. */ int sys_getpriority(struct proc *curp, void *v, register_t *retval) { struct sys_getpriority_args /* { syscallarg(int) which; syscallarg(id_t) who; } */ *uap = v; struct process *pr; int low = NZERO + PRIO_MAX + 1; switch (SCARG(uap, which)) { case PRIO_PROCESS: if (SCARG(uap, who) == 0) pr = curp->p_p; else pr = prfind(SCARG(uap, who)); if (pr == NULL) break; if (pr->ps_nice < low) low = pr->ps_nice; break; case PRIO_PGRP: { struct pgrp *pg; if (SCARG(uap, who) == 0) pg = curp->p_p->ps_pgrp; else if ((pg = pgfind(SCARG(uap, who))) == NULL) break; LIST_FOREACH(pr, &pg->pg_members, ps_pglist) if (pr->ps_nice < low) low = pr->ps_nice; break; } case PRIO_USER: if (SCARG(uap, who) == 0) SCARG(uap, who) = curp->p_ucred->cr_uid; LIST_FOREACH(pr, &allprocess, ps_list) if (pr->ps_ucred->cr_uid == SCARG(uap, who) && pr->ps_nice < low) low = pr->ps_nice; break; default: return (EINVAL); } if (low == NZERO + PRIO_MAX + 1) return (ESRCH); *retval = low - NZERO; return (0); } int sys_setpriority(struct proc *curp, void *v, register_t *retval) { struct sys_setpriority_args /* { syscallarg(int) which; syscallarg(id_t) who; syscallarg(int) prio; } */ *uap = v; struct process *pr; int found = 0, error = 0; switch (SCARG(uap, which)) { case PRIO_PROCESS: if (SCARG(uap, who) == 0) pr = curp->p_p; else pr = prfind(SCARG(uap, who)); if (pr == NULL) break; error = donice(curp, pr, SCARG(uap, prio)); found = 1; break; case PRIO_PGRP: { struct pgrp *pg; if (SCARG(uap, who) == 0) pg = curp->p_p->ps_pgrp; else if ((pg = pgfind(SCARG(uap, who))) == NULL) break; LIST_FOREACH(pr, &pg->pg_members, ps_pglist) { error = donice(curp, pr, SCARG(uap, prio)); found = 1; } break; } case PRIO_USER: if (SCARG(uap, who) == 0) SCARG(uap, who) = curp->p_ucred->cr_uid; LIST_FOREACH(pr, &allprocess, ps_list) if (pr->ps_ucred->cr_uid == SCARG(uap, who)) { error = donice(curp, pr, SCARG(uap, prio)); found = 1; } break; default: return (EINVAL); } if (!found) return (ESRCH); return (error); } int donice(struct proc *curp, struct process *chgpr, int n) { struct ucred *ucred = curp->p_ucred; struct proc *p; int s; if (ucred->cr_uid != 0 && ucred->cr_ruid != 0 && ucred->cr_uid != chgpr->ps_ucred->cr_uid && ucred->cr_ruid != chgpr->ps_ucred->cr_uid) return (EPERM); if (n > PRIO_MAX) n = PRIO_MAX; if (n < PRIO_MIN) n = PRIO_MIN; n += NZERO; if (n < chgpr->ps_nice && suser(curp)) return (EACCES); chgpr->ps_nice = n; mtx_enter(&chgpr->ps_mtx); SCHED_LOCK(s); TAILQ_FOREACH(p, &chgpr->ps_threads, p_thr_link) { setpriority(p, p->p_estcpu, n); } SCHED_UNLOCK(s); mtx_leave(&chgpr->ps_mtx); return (0); } int sys_setrlimit(struct proc *p, void *v, register_t *retval) { struct sys_setrlimit_args /* { syscallarg(int) which; syscallarg(const struct rlimit *) rlp; } */ *uap = v; struct rlimit alim; int error; error = copyin((caddr_t)SCARG(uap, rlp), (caddr_t)&alim, sizeof (struct rlimit)); if (error) return (error); #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrrlimit(p, &alim); #endif return (dosetrlimit(p, SCARG(uap, which), &alim)); } int dosetrlimit(struct proc *p, u_int which, struct rlimit *limp) { struct rlimit *alimp; struct plimit *limit; rlim_t maxlim; int error; if (which >= RLIM_NLIMITS || limp->rlim_cur > limp->rlim_max) return (EINVAL); rw_enter_write(&rlimit_lock); alimp = &p->p_p->ps_limit->pl_rlimit[which]; if (limp->rlim_max > alimp->rlim_max) { if ((error = suser(p)) != 0) { rw_exit_write(&rlimit_lock); return (error); } } /* Get exclusive write access to the limit structure. */ limit = lim_write_begin(); alimp = &limit->pl_rlimit[which]; switch (which) { case RLIMIT_DATA: maxlim = maxdmap; break; case RLIMIT_STACK: maxlim = maxsmap; break; case RLIMIT_NOFILE: maxlim = maxfiles; break; case RLIMIT_NPROC: maxlim = maxprocess; break; default: maxlim = RLIM_INFINITY; break; } if (limp->rlim_max > maxlim) limp->rlim_max = maxlim; if (limp->rlim_cur > limp->rlim_max) limp->rlim_cur = limp->rlim_max; if (which == RLIMIT_CPU && limp->rlim_cur != RLIM_INFINITY && alimp->rlim_cur == RLIM_INFINITY) timeout_add_msec(&p->p_p->ps_rucheck_to, RUCHECK_INTERVAL); if (which == RLIMIT_STACK) { /* * Stack is allocated to the max at exec time with only * "rlim_cur" bytes accessible. If stack limit is going * up make more accessible, if going down make inaccessible. */ if (limp->rlim_cur != alimp->rlim_cur) { vaddr_t addr; vsize_t size; vm_prot_t prot; struct vmspace *vm = p->p_vmspace; if (limp->rlim_cur > alimp->rlim_cur) { prot = PROT_READ | PROT_WRITE; size = limp->rlim_cur - alimp->rlim_cur; #ifdef MACHINE_STACK_GROWS_UP addr = (vaddr_t)vm->vm_maxsaddr + alimp->rlim_cur; #else addr = (vaddr_t)vm->vm_minsaddr - limp->rlim_cur; #endif } else { prot = PROT_NONE; size = alimp->rlim_cur - limp->rlim_cur; #ifdef MACHINE_STACK_GROWS_UP addr = (vaddr_t)vm->vm_maxsaddr + limp->rlim_cur; #else addr = (vaddr_t)vm->vm_minsaddr - alimp->rlim_cur; #endif } addr = trunc_page(addr); size = round_page(size); KERNEL_LOCK(); (void) uvm_map_protect(&vm->vm_map, addr, addr+size, prot, UVM_ET_STACK, FALSE, FALSE); KERNEL_UNLOCK(); } } *alimp = *limp; lim_write_commit(limit); rw_exit_write(&rlimit_lock); return (0); } int sys_getrlimit(struct proc *p, void *v, register_t *retval) { struct sys_getrlimit_args /* { syscallarg(int) which; syscallarg(struct rlimit *) rlp; } */ *uap = v; struct plimit *limit; struct rlimit alimp; int error; if (SCARG(uap, which) < 0 || SCARG(uap, which) >= RLIM_NLIMITS) return (EINVAL); limit = lim_read_enter(); alimp = limit->pl_rlimit[SCARG(uap, which)]; lim_read_leave(limit); error = copyout(&alimp, SCARG(uap, rlp), sizeof(struct rlimit)); #ifdef KTRACE if (error == 0 && KTRPOINT(p, KTR_STRUCT)) ktrrlimit(p, &alimp); #endif return (error); } void tuagg_sub(struct tusage *tup, struct proc *p, const struct timespec *ts) { if (ts != NULL) timespecadd(&tup->tu_runtime, ts, &tup->tu_runtime); tup->tu_uticks += p->p_uticks; tup->tu_sticks += p->p_sticks; tup->tu_iticks += p->p_iticks; } /* * Aggregate a single thread's immediate time counts into the running * totals for the thread and process */ void tuagg_locked(struct process *pr, struct proc *p, const struct timespec *ts) { tuagg_sub(&pr->ps_tu, p, ts); tuagg_sub(&p->p_tu, p, ts); p->p_uticks = 0; p->p_sticks = 0; p->p_iticks = 0; } void tuagg(struct process *pr, struct proc *p) { int s; SCHED_LOCK(s); tuagg_locked(pr, p, NULL); SCHED_UNLOCK(s); } /* * Transform the running time and tick information in a struct tusage * into user, system, and interrupt time usage. */ void calctsru(struct tusage *tup, struct timespec *up, struct timespec *sp, struct timespec *ip) { u_quad_t st, ut, it; st = tup->tu_sticks; ut = tup->tu_uticks; it = tup->tu_iticks; if (st + ut + it == 0) { timespecclear(up); timespecclear(sp); if (ip != NULL) timespecclear(ip); return; } st = st * 1000000000 / stathz; sp->tv_sec = st / 1000000000; sp->tv_nsec = st % 1000000000; ut = ut * 1000000000 / stathz; up->tv_sec = ut / 1000000000; up->tv_nsec = ut % 1000000000; if (ip != NULL) { it = it * 1000000000 / stathz; ip->tv_sec = it / 1000000000; ip->tv_nsec = it % 1000000000; } } void calcru(struct tusage *tup, struct timeval *up, struct timeval *sp, struct timeval *ip) { struct timespec u, s, i; calctsru(tup, &u, &s, ip != NULL ? &i : NULL); TIMESPEC_TO_TIMEVAL(up, &u); TIMESPEC_TO_TIMEVAL(sp, &s); if (ip != NULL) TIMESPEC_TO_TIMEVAL(ip, &i); } int sys_getrusage(struct proc *p, void *v, register_t *retval) { struct sys_getrusage_args /* { syscallarg(int) who; syscallarg(struct rusage *) rusage; } */ *uap = v; struct rusage ru; int error; error = dogetrusage(p, SCARG(uap, who), &ru); if (error == 0) { error = copyout(&ru, SCARG(uap, rusage), sizeof(ru)); #ifdef KTRACE if (error == 0 && KTRPOINT(p, KTR_STRUCT)) ktrrusage(p, &ru); #endif } return (error); } int dogetrusage(struct proc *p, int who, struct rusage *rup) { struct process *pr = p->p_p; struct proc *q; KERNEL_ASSERT_LOCKED(); switch (who) { case RUSAGE_SELF: /* start with the sum of dead threads, if any */ if (pr->ps_ru != NULL) *rup = *pr->ps_ru; else memset(rup, 0, sizeof(*rup)); /* add on all living threads */ TAILQ_FOREACH(q, &pr->ps_threads, p_thr_link) { ruadd(rup, &q->p_ru); tuagg(pr, q); } calcru(&pr->ps_tu, &rup->ru_utime, &rup->ru_stime, NULL); break; case RUSAGE_THREAD: *rup = p->p_ru; calcru(&p->p_tu, &rup->ru_utime, &rup->ru_stime, NULL); break; case RUSAGE_CHILDREN: *rup = pr->ps_cru; break; default: return (EINVAL); } return (0); } void ruadd(struct rusage *ru, struct rusage *ru2) { long *ip, *ip2; int i; timeradd(&ru->ru_utime, &ru2->ru_utime, &ru->ru_utime); timeradd(&ru->ru_stime, &ru2->ru_stime, &ru->ru_stime); if (ru->ru_maxrss < ru2->ru_maxrss) ru->ru_maxrss = ru2->ru_maxrss; ip = &ru->ru_first; ip2 = &ru2->ru_first; for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--) *ip++ += *ip2++; } /* * Check if the process exceeds its cpu resource allocation. * If over max, kill it. */ void rucheck(void *arg) { struct rlimit rlim; struct process *pr = arg; time_t runtime; int s; KERNEL_ASSERT_LOCKED(); SCHED_LOCK(s); runtime = pr->ps_tu.tu_runtime.tv_sec; SCHED_UNLOCK(s); mtx_enter(&pr->ps_mtx); rlim = pr->ps_limit->pl_rlimit[RLIMIT_CPU]; mtx_leave(&pr->ps_mtx); if ((rlim_t)runtime >= rlim.rlim_cur) { if ((rlim_t)runtime >= rlim.rlim_max) { prsignal(pr, SIGKILL); } else if (runtime >= pr->ps_nextxcpu) { prsignal(pr, SIGXCPU); pr->ps_nextxcpu = runtime + SIGXCPU_INTERVAL; } } timeout_add_msec(&pr->ps_rucheck_to, RUCHECK_INTERVAL); } struct pool plimit_pool; void lim_startup(struct plimit *limit0) { rlim_t lim; int i; pool_init(&plimit_pool, sizeof(struct plimit), 0, IPL_MPFLOOR, PR_WAITOK, "plimitpl", NULL); for (i = 0; i < nitems(limit0->pl_rlimit); i++) limit0->pl_rlimit[i].rlim_cur = limit0->pl_rlimit[i].rlim_max = RLIM_INFINITY; limit0->pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE; limit0->pl_rlimit[RLIMIT_NOFILE].rlim_max = MIN(NOFILE_MAX, (maxfiles - NOFILE > NOFILE) ? maxfiles - NOFILE : NOFILE); limit0->pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC; lim = ptoa(uvmexp.free); limit0->pl_rlimit[RLIMIT_RSS].rlim_max = lim; lim = ptoa(64*1024); /* Default to very low */ limit0->pl_rlimit[RLIMIT_MEMLOCK].rlim_max = lim; limit0->pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = lim / 3; refcnt_init(&limit0->pl_refcnt); } /* * Make a copy of the plimit structure. * We share these structures copy-on-write after fork, * and copy when a limit is changed. */ struct plimit * lim_copy(struct plimit *lim) { struct plimit *newlim; newlim = pool_get(&plimit_pool, PR_WAITOK); memcpy(newlim->pl_rlimit, lim->pl_rlimit, sizeof(struct rlimit) * RLIM_NLIMITS); refcnt_init(&newlim->pl_refcnt); return (newlim); } void lim_free(struct plimit *lim) { if (refcnt_rele(&lim->pl_refcnt) == 0) return; pool_put(&plimit_pool, lim); } void lim_fork(struct process *parent, struct process *child) { struct plimit *limit; mtx_enter(&parent->ps_mtx); limit = parent->ps_limit; refcnt_take(&limit->pl_refcnt); mtx_leave(&parent->ps_mtx); child->ps_limit = limit; if (limit->pl_rlimit[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) timeout_add_msec(&child->ps_rucheck_to, RUCHECK_INTERVAL); } /* * Return an exclusive write reference to the process' resource limit structure. * The caller has to release the structure by calling lim_write_commit(). * * This invalidates any plimit read reference held by the calling thread. */ struct plimit * lim_write_begin(void) { struct plimit *limit; struct proc *p = curproc; rw_assert_wrlock(&rlimit_lock); if (p->p_limit != NULL) lim_free(p->p_limit); p->p_limit = NULL; /* * It is safe to access ps_limit here without holding ps_mtx * because rlimit_lock excludes other writers. */ limit = p->p_p->ps_limit; if (P_HASSIBLING(p) || refcnt_shared(&limit->pl_refcnt)) limit = lim_copy(limit); return (limit); } /* * Finish exclusive write access to the plimit structure. * This makes the structure visible to other threads in the process. */ void lim_write_commit(struct plimit *limit) { struct plimit *olimit; struct proc *p = curproc; rw_assert_wrlock(&rlimit_lock); if (limit != p->p_p->ps_limit) { mtx_enter(&p->p_p->ps_mtx); olimit = p->p_p->ps_limit; p->p_p->ps_limit = limit; mtx_leave(&p->p_p->ps_mtx); lim_free(olimit); } } /* * Begin read access to the process' resource limit structure. * The access has to be finished by calling lim_read_leave(). * * Sections denoted by lim_read_enter() and lim_read_leave() cannot nest. */ struct plimit * lim_read_enter(void) { struct plimit *limit; struct proc *p = curproc; struct process *pr = p->p_p; /* * This thread might not observe the latest value of ps_limit * if another thread updated the limits very recently on another CPU. * However, the anomaly should disappear quickly, especially if * there is any synchronization activity between the threads (or * the CPUs). */ limit = p->p_limit; if (limit != pr->ps_limit) { mtx_enter(&pr->ps_mtx); limit = pr->ps_limit; refcnt_take(&limit->pl_refcnt); mtx_leave(&pr->ps_mtx); if (p->p_limit != NULL) lim_free(p->p_limit); p->p_limit = limit; } KASSERT(limit != NULL); return (limit); } /* * Get the value of the resource limit in given process. */ rlim_t lim_cur_proc(struct proc *p, int which) { struct process *pr = p->p_p; rlim_t val; KASSERT(which >= 0 && which < RLIM_NLIMITS); mtx_enter(&pr->ps_mtx); val = pr->ps_limit->pl_rlimit[which].rlim_cur; mtx_leave(&pr->ps_mtx); return (val); }
684 687 687 674 222 686 162 674 684 687 687 687 54 687 687 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 /* $OpenBSD: siphash.c,v 1.5 2018/01/05 19:05:09 mikeb Exp $ */ /*- * Copyright (c) 2013 Andre Oppermann <andre@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * SipHash is a family of PRFs SipHash-c-d where the integer parameters c and d * are the number of compression rounds and the number of finalization rounds. * A compression round is identical to a finalization round and this round * function is called SipRound. Given a 128-bit key k and a (possibly empty) * byte string m, SipHash-c-d returns a 64-bit value SipHash-c-d(k; m). * * Implemented from the paper "SipHash: a fast short-input PRF", 2012.09.18, * by Jean-Philippe Aumasson and Daniel J. Bernstein, * Permanent Document ID b9a943a805fbfc6fde808af9fc0ecdfa * https://131002.net/siphash/siphash.pdf * https://131002.net/siphash/ */ #include <sys/param.h> #include <sys/systm.h> #include <crypto/siphash.h> static void SipHash_CRounds(SIPHASH_CTX *, int); static void SipHash_Rounds(SIPHASH_CTX *, int); void SipHash_Init(SIPHASH_CTX *ctx, const SIPHASH_KEY *key) { uint64_t k0, k1; k0 = lemtoh64(&key->k0); k1 = lemtoh64(&key->k1); ctx->v[0] = 0x736f6d6570736575ULL ^ k0; ctx->v[1] = 0x646f72616e646f6dULL ^ k1; ctx->v[2] = 0x6c7967656e657261ULL ^ k0; ctx->v[3] = 0x7465646279746573ULL ^ k1; memset(ctx->buf, 0, sizeof(ctx->buf)); ctx->bytes = 0; } void SipHash_Update(SIPHASH_CTX *ctx, int rc, int rf, const void *src, size_t len) { const uint8_t *ptr = src; size_t left, used; if (len == 0) return; used = ctx->bytes % sizeof(ctx->buf); ctx->bytes += len; if (used > 0) { left = sizeof(ctx->buf) - used; if (len >= left) { memcpy(&ctx->buf[used], ptr, left); SipHash_CRounds(ctx, rc); len -= left; ptr += left; } else { memcpy(&ctx->buf[used], ptr, len); return; } } while (len >= sizeof(ctx->buf)) { memcpy(ctx->buf, ptr, sizeof(ctx->buf)); SipHash_CRounds(ctx, rc); len -= sizeof(ctx->buf); ptr += sizeof(ctx->buf); } if (len > 0) memcpy(ctx->buf, ptr, len); } void SipHash_Final(void *dst, SIPHASH_CTX *ctx, int rc, int rf) { uint64_t r; htolem64(&r, SipHash_End(ctx, rc, rf)); memcpy(dst, &r, sizeof r); } uint64_t SipHash_End(SIPHASH_CTX *ctx, int rc, int rf) { uint64_t r; size_t left, used; used = ctx->bytes % sizeof(ctx->buf); left = sizeof(ctx->buf) - used; memset(&ctx->buf[used], 0, left - 1); ctx->buf[7] = ctx->bytes; SipHash_CRounds(ctx, rc); ctx->v[2] ^= 0xff; SipHash_Rounds(ctx, rf); r = (ctx->v[0] ^ ctx->v[1]) ^ (ctx->v[2] ^ ctx->v[3]); explicit_bzero(ctx, sizeof(*ctx)); return (r); } uint64_t SipHash(const SIPHASH_KEY *key, int rc, int rf, const void *src, size_t len) { SIPHASH_CTX ctx; SipHash_Init(&ctx, key); SipHash_Update(&ctx, rc, rf, src, len); return (SipHash_End(&ctx, rc, rf)); } #define SIP_ROTL(x, b) ((x) << (b)) | ( (x) >> (64 - (b))) static void SipHash_Rounds(SIPHASH_CTX *ctx, int rounds) { while (rounds--) { ctx->v[0] += ctx->v[1]; ctx->v[2] += ctx->v[3]; ctx->v[1] = SIP_ROTL(ctx->v[1], 13); ctx->v[3] = SIP_ROTL(ctx->v[3], 16); ctx->v[1] ^= ctx->v[0]; ctx->v[3] ^= ctx->v[2]; ctx->v[0] = SIP_ROTL(ctx->v[0], 32); ctx->v[2] += ctx->v[1]; ctx->v[0] += ctx->v[3]; ctx->v[1] = SIP_ROTL(ctx->v[1], 17); ctx->v[3] = SIP_ROTL(ctx->v[3], 21); ctx->v[1] ^= ctx->v[2]; ctx->v[3] ^= ctx->v[0]; ctx->v[2] = SIP_ROTL(ctx->v[2], 32); } } static void SipHash_CRounds(SIPHASH_CTX *ctx, int rounds) { uint64_t m = lemtoh64((uint64_t *)ctx->buf); ctx->v[3] ^= m; SipHash_Rounds(ctx, rounds); ctx->v[0] ^= m; }
58 57 58 1 1 1 1 1 1 57 58 57 57 58 58 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 /* $OpenBSD: ip6_id.c,v 1.17 2024/02/13 12:22:09 bluhm Exp $ */ /* $NetBSD: ip6_id.c,v 1.7 2003/09/13 21:32:59 itojun Exp $ */ /* $KAME: ip6_id.c,v 1.8 2003/09/06 13:41:06 itojun Exp $ */ /* * Copyright (C) 2003 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright 1998 Niels Provos <provos@citi.umich.edu> * All rights reserved. * * Theo de Raadt <deraadt@openbsd.org> came up with the idea of using * such a mathematical system to generate more random (yet non-repeating) * ids to solve the resolver/named problem. But Niels designed the * actual system based on the constraints. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * seed = random (bits - 1) bit * n = prime, g0 = generator to n, * j = random so that gcd(j,n-1) == 1 * g = g0^j mod n will be a generator again. * * X[0] = random seed. * X[n] = a*X[n-1]+b mod m is a Linear Congruential Generator * with a = 7^(even random) mod m, * b = random with gcd(b,m) == 1 * m = constant and a maximal period of m-1. * * The transaction id is determined by: * id[n] = seed xor (g^X[n] mod n) * * Effectivly the id is restricted to the lower (bits - 1) bits, thus * yielding two different cycles by toggling the msb on and off. * This avoids reuse issues caused by reseeding. */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/systm.h> #include <netinet/in.h> #include <netinet/ip6.h> struct randomtab { const int ru_bits; /* resulting bits */ const long ru_out; /* Time after which will be reseeded */ const u_int32_t ru_max; /* Uniq cycle, avoid blackjack prediction */ const u_int32_t ru_gen; /* Starting generator */ const u_int32_t ru_n; /* ru_n: prime, ru_n - 1: product of pfacts[] */ const u_int32_t ru_agen; /* determine ru_a as ru_agen^(2*rand) */ const u_int32_t ru_m; /* ru_m = 2^x*3^y */ const u_int32_t pfacts[4]; /* factors of ru_n */ u_int32_t ru_counter; u_int32_t ru_msb; u_int32_t ru_x; u_int32_t ru_seed, ru_seed2; u_int32_t ru_a, ru_b; u_int32_t ru_g; long ru_reseed; }; static struct randomtab randomtab_20 = { 20, /* resulting bits */ 180, /* Time after which will be reseeded */ 200000, /* Uniq cycle, avoid blackjack prediction */ 2, /* Starting generator */ 524269, /* RU_N-1 = 2^2*3^2*14563 */ 7, /* determine ru_a as RU_AGEN^(2*rand) */ 279936, /* RU_M = 2^7*3^7 - don't change */ { 2, 3, 14563, 0 }, /* factors of ru_n */ }; u_int32_t ip6id_pmod(u_int32_t, u_int32_t, u_int32_t); void ip6id_initid(struct randomtab *); u_int32_t ip6id_randomid(struct randomtab *); /* * Do a fast modular exponation, returned value will be in the range * of 0 - (mod-1) */ u_int32_t ip6id_pmod(u_int32_t gen, u_int32_t expo, u_int32_t mod) { u_int64_t s, t, u; s = 1; t = gen; u = expo; while (u) { if (u & 1) s = (s * t) % mod; u >>= 1; t = (t * t) % mod; } return (s); } /* * Initializes the seed and chooses a suitable generator. Also toggles * the msb flag. The msb flag is used to generate two distinct * cycles of random numbers and thus avoiding reuse of ids. * * This function is called from id_randomid() when needed, an * application does not have to worry about it. */ void ip6id_initid(struct randomtab *p) { u_int32_t j, i; int noprime = 1; p->ru_x = arc4random_uniform(p->ru_m); /* (bits - 1) bits of random seed */ p->ru_seed = arc4random() & (~0U >> (32 - p->ru_bits + 1)); p->ru_seed2 = arc4random() & (~0U >> (32 - p->ru_bits + 1)); /* Determine the LCG we use */ p->ru_b = (arc4random() & (~0U >> (32 - p->ru_bits))) | 1; p->ru_a = ip6id_pmod(p->ru_agen, (arc4random() & (~0U >> (32 - p->ru_bits))) & (~1U), p->ru_m); while (p->ru_b % 3 == 0) p->ru_b += 2; j = arc4random_uniform(p->ru_n); /* * Do a fast gcd(j, RU_N - 1), so we can find a j with * gcd(j, RU_N - 1) == 1, giving a new generator for * RU_GEN^j mod RU_N */ while (noprime) { for (i = 0; p->pfacts[i] > 0; i++) if (j % p->pfacts[i] == 0) break; if (p->pfacts[i] == 0) noprime = 0; else j = (j + 1) % p->ru_n; } p->ru_g = ip6id_pmod(p->ru_gen, j, p->ru_n); p->ru_counter = 0; p->ru_reseed = getuptime() + p->ru_out; p->ru_msb = p->ru_msb ? 0 : (1U << (p->ru_bits - 1)); } u_int32_t ip6id_randomid(struct randomtab *p) { int i, n; if (p->ru_counter >= p->ru_max || getuptime() > p->ru_reseed) ip6id_initid(p); /* Skip a random number of ids */ n = arc4random() & 0x3; if (p->ru_counter + n >= p->ru_max) ip6id_initid(p); for (i = 0; i <= n; i++) { /* Linear Congruential Generator */ p->ru_x = (u_int32_t)((u_int64_t)p->ru_a * p->ru_x + p->ru_b) % p->ru_m; } p->ru_counter += i; return (p->ru_seed ^ ip6id_pmod(p->ru_g, p->ru_seed2 + p->ru_x, p->ru_n)) | p->ru_msb; } u_int32_t ip6_randomflowlabel(void) { return ip6id_randomid(&randomtab_20) & 0xfffff; }
12 12 69 2246 3 6 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 /* $OpenBSD: time.h,v 1.66 2023/10/17 00:04:02 cheloha Exp $ */ /* $NetBSD: time.h,v 1.18 1996/04/23 10:29:33 mycroft Exp $ */ /* * Copyright (c) 1982, 1986, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)time.h 8.2 (Berkeley) 7/10/94 */ #ifndef _SYS_TIME_H_ #define _SYS_TIME_H_ #include <sys/select.h> #ifndef _TIMEVAL_DECLARED #define _TIMEVAL_DECLARED /* * Structure returned by gettimeofday(2) system call, * and used in other calls. */ struct timeval { time_t tv_sec; /* seconds */ suseconds_t tv_usec; /* and microseconds */ }; #endif #ifndef _TIMESPEC_DECLARED #define _TIMESPEC_DECLARED /* * Structure defined by POSIX.1b to be like a timeval. */ struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* and nanoseconds */ }; #endif #define TIMEVAL_TO_TIMESPEC(tv, ts) do { \ (ts)->tv_sec = (tv)->tv_sec; \ (ts)->tv_nsec = (tv)->tv_usec * 1000; \ } while (0) #define TIMESPEC_TO_TIMEVAL(tv, ts) do { \ (tv)->tv_sec = (ts)->tv_sec; \ (tv)->tv_usec = (ts)->tv_nsec / 1000; \ } while (0) struct timezone { int tz_minuteswest; /* minutes west of Greenwich */ int tz_dsttime; /* type of dst correction */ }; #define DST_NONE 0 /* not on dst */ #define DST_USA 1 /* USA style dst */ #define DST_AUST 2 /* Australian style dst */ #define DST_WET 3 /* Western European dst */ #define DST_MET 4 /* Middle European dst */ #define DST_EET 5 /* Eastern European dst */ #define DST_CAN 6 /* Canada */ /* Operations on timevals. */ #define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 #define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) #define timerisvalid(tvp) \ ((tvp)->tv_usec >= 0 && (tvp)->tv_usec < 1000000) #define timercmp(tvp, uvp, cmp) \ (((tvp)->tv_sec == (uvp)->tv_sec) ? \ ((tvp)->tv_usec cmp (uvp)->tv_usec) : \ ((tvp)->tv_sec cmp (uvp)->tv_sec)) #define timeradd(tvp, uvp, vvp) \ do { \ (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \ (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \ if ((vvp)->tv_usec >= 1000000) { \ (vvp)->tv_sec++; \ (vvp)->tv_usec -= 1000000; \ } \ } while (0) #define timersub(tvp, uvp, vvp) \ do { \ (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ if ((vvp)->tv_usec < 0) { \ (vvp)->tv_sec--; \ (vvp)->tv_usec += 1000000; \ } \ } while (0) /* Operations on timespecs. */ #define timespecclear(tsp) (tsp)->tv_sec = (tsp)->tv_nsec = 0 #define timespecisset(tsp) ((tsp)->tv_sec || (tsp)->tv_nsec) #define timespecisvalid(tsp) \ ((tsp)->tv_nsec >= 0 && (tsp)->tv_nsec < 1000000000L) #define timespeccmp(tsp, usp, cmp) \ (((tsp)->tv_sec == (usp)->tv_sec) ? \ ((tsp)->tv_nsec cmp (usp)->tv_nsec) : \ ((tsp)->tv_sec cmp (usp)->tv_sec)) #define timespecadd(tsp, usp, vsp) \ do { \ (vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec; \ (vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec; \ if ((vsp)->tv_nsec >= 1000000000L) { \ (vsp)->tv_sec++; \ (vsp)->tv_nsec -= 1000000000L; \ } \ } while (0) #define timespecsub(tsp, usp, vsp) \ do { \ (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \ (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \ if ((vsp)->tv_nsec < 0) { \ (vsp)->tv_sec--; \ (vsp)->tv_nsec += 1000000000L; \ } \ } while (0) /* * Names of the interval timers, and structure * defining a timer setting. */ #define ITIMER_REAL 0 #define ITIMER_VIRTUAL 1 #define ITIMER_PROF 2 struct itimerval { struct timeval it_interval; /* timer interval */ struct timeval it_value; /* current value */ }; #if __BSD_VISIBLE /* * clock information structure for sysctl({CTL_KERN, KERN_CLOCKRATE}) */ struct clockinfo { int hz; /* clock frequency */ int tick; /* micro-seconds per hz tick */ int stathz; /* statistics clock frequency */ int profhz; /* profiling clock frequency */ }; #endif /* __BSD_VISIBLE */ #if defined(_KERNEL) || defined(_STANDALONE) || defined (_LIBC) #include <sys/_time.h> /* Time expressed as seconds and fractions of a second + operations on it. */ struct bintime { time_t sec; uint64_t frac; }; #endif #if defined(_KERNEL) || defined(_STANDALONE) || defined (_LIBC) #define bintimecmp(btp, ctp, cmp) \ ((btp)->sec == (ctp)->sec ? \ (btp)->frac cmp (ctp)->frac : \ (btp)->sec cmp (ctp)->sec) static inline void bintimeaddfrac(const struct bintime *bt, uint64_t x, struct bintime *ct) { ct->sec = bt->sec; if (bt->frac > bt->frac + x) ct->sec++; ct->frac = bt->frac + x; } static inline void bintimeadd(const struct bintime *bt, const struct bintime *ct, struct bintime *dt) { dt->sec = bt->sec + ct->sec; if (bt->frac > bt->frac + ct->frac) dt->sec++; dt->frac = bt->frac + ct->frac; } static inline void bintimesub(const struct bintime *bt, const struct bintime *ct, struct bintime *dt) { dt->sec = bt->sec - ct->sec; if (bt->frac < bt->frac - ct->frac) dt->sec--; dt->frac = bt->frac - ct->frac; } static inline void TIMECOUNT_TO_BINTIME(u_int count, uint64_t scale, struct bintime *bt) { uint64_t hi64; hi64 = count * (scale >> 32); bt->sec = hi64 >> 32; bt->frac = hi64 << 32; bintimeaddfrac(bt, count * (scale & 0xffffffff), bt); } /*- * Background information: * * When converting between timestamps on parallel timescales of differing * resolutions it is historical and scientific practice to round down rather * than doing 4/5 rounding. * * The date changes at midnight, not at noon. * * Even at 15:59:59.999999999 it's not four'o'clock. * * time_second ticks after N.999999999 not after N.4999999999 */ static inline uint32_t FRAC_TO_NSEC(uint64_t frac) { return ((frac >> 32) * 1000000000ULL) >> 32; } static inline void BINTIME_TO_TIMESPEC(const struct bintime *bt, struct timespec *ts) { ts->tv_sec = bt->sec; ts->tv_nsec = FRAC_TO_NSEC(bt->frac); } static inline void TIMESPEC_TO_BINTIME(const struct timespec *ts, struct bintime *bt) { bt->sec = ts->tv_sec; /* 18446744073 = int(2^64 / 1000000000) */ bt->frac = (uint64_t)ts->tv_nsec * (uint64_t)18446744073ULL; } static inline void BINTIME_TO_TIMEVAL(const struct bintime *bt, struct timeval *tv) { tv->tv_sec = bt->sec; tv->tv_usec = (long)(((uint64_t)1000000 * (uint32_t)(bt->frac >> 32)) >> 32); } static inline void TIMEVAL_TO_BINTIME(const struct timeval *tv, struct bintime *bt) { bt->sec = (time_t)tv->tv_sec; /* 18446744073709 = int(2^64 / 1000000) */ bt->frac = (uint64_t)tv->tv_usec * (uint64_t)18446744073709ULL; } #endif #if defined(_KERNEL) || defined(_STANDALONE) /* * Functions for looking at our clocks: [get]{bin,nano,micro}[boot|up]time() * * Functions without the "get" prefix returns the best timestamp * we can produce in the given format. * * "bin" == struct bintime == seconds + 64 bit fraction of seconds. * "nano" == struct timespec == seconds + nanoseconds. * "micro" == struct timeval == seconds + microseconds. * * Functions containing "up" returns time relative to boot and * should be used for calculating time intervals. * * Functions containing "boot" return the GMT time at which the * system booted. * * Functions with just "time" return the current GMT time. * * Functions with the "get" prefix returns a less precise result * much faster than the functions without "get" prefix and should * be used where a precision of 10 msec is acceptable or where * performance is priority. (NB: "precision", _not_ "resolution" !) */ void bintime(struct bintime *); void nanotime(struct timespec *); void microtime(struct timeval *); void getnanotime(struct timespec *); void getmicrotime(struct timeval *); void binuptime(struct bintime *); void nanouptime(struct timespec *); void microuptime(struct timeval *); void getbinuptime(struct bintime *); void getnanouptime(struct timespec *); void getmicrouptime(struct timeval *); void binboottime(struct bintime *); void microboottime(struct timeval *); void nanoboottime(struct timespec *); void binruntime(struct bintime *); void nanoruntime(struct timespec *); void getbinruntime(struct bintime *); uint64_t getnsecruntime(void); time_t gettime(void); time_t getuptime(void); uint64_t nsecuptime(void); uint64_t getnsecuptime(void); struct proc; int clock_gettime(struct proc *, clockid_t, struct timespec *); struct clockrequest; void itimer_update(struct clockrequest *, void *, void *); void cancel_all_itimers(void); int settime(const struct timespec *); int ratecheck(struct timeval *, const struct timeval *); int ppsratecheck(struct timeval *, int *, int); /* * "POSIX time" to/from "YY/MM/DD/hh/mm/ss" */ struct clock_ymdhms { u_short dt_year; u_char dt_mon; u_char dt_day; u_char dt_wday; /* Day of week */ u_char dt_hour; u_char dt_min; u_char dt_sec; }; time_t clock_ymdhms_to_secs(struct clock_ymdhms *); void clock_secs_to_ymdhms(time_t, struct clock_ymdhms *); /* * BCD to decimal and decimal to BCD. */ #define FROMBCD(x) (((x) >> 4) * 10 + ((x) & 0xf)) #define TOBCD(x) (((x) / 10 * 16) + ((x) % 10)) /* Some handy constants. */ #define SECDAY 86400L #define SECYR (SECDAY * 365) /* Traditional POSIX base year */ #define POSIX_BASE_YEAR 1970 #include <sys/stdint.h> static inline void USEC_TO_TIMEVAL(uint64_t us, struct timeval *tv) { tv->tv_sec = us / 1000000; tv->tv_usec = us % 1000000; } static inline void NSEC_TO_TIMEVAL(uint64_t ns, struct timeval *tv) { tv->tv_sec = ns / 1000000000L; tv->tv_usec = (ns % 1000000000L) / 1000; } static inline uint64_t TIMEVAL_TO_NSEC(const struct timeval *tv) { uint64_t nsecs; if (tv->tv_sec > UINT64_MAX / 1000000000ULL) return UINT64_MAX; nsecs = tv->tv_sec * 1000000000ULL; if (tv->tv_usec * 1000ULL > UINT64_MAX - nsecs) return UINT64_MAX; return nsecs + tv->tv_usec * 1000ULL; } static inline void NSEC_TO_TIMESPEC(uint64_t ns, struct timespec *ts) { ts->tv_sec = ns / 1000000000L; ts->tv_nsec = ns % 1000000000L; } static inline uint64_t SEC_TO_NSEC(uint64_t seconds) { if (seconds > UINT64_MAX / 1000000000ULL) return UINT64_MAX; return seconds * 1000000000ULL; } static inline uint64_t MSEC_TO_NSEC(uint64_t milliseconds) { if (milliseconds > UINT64_MAX / 1000000ULL) return UINT64_MAX; return milliseconds * 1000000ULL; } static inline uint64_t USEC_TO_NSEC(uint64_t microseconds) { if (microseconds > UINT64_MAX / 1000ULL) return UINT64_MAX; return microseconds * 1000ULL; } static inline uint64_t TIMESPEC_TO_NSEC(const struct timespec *ts) { if (ts->tv_sec > (UINT64_MAX - ts->tv_nsec) / 1000000000ULL) return UINT64_MAX; return ts->tv_sec * 1000000000ULL + ts->tv_nsec; } static inline uint64_t BINTIME_TO_NSEC(const struct bintime *bt) { return bt->sec * 1000000000ULL + FRAC_TO_NSEC(bt->frac); } #else /* !_KERNEL */ #include <time.h> #if __BSD_VISIBLE || __XPG_VISIBLE __BEGIN_DECLS #if __BSD_VISIBLE int adjtime(const struct timeval *, struct timeval *); int adjfreq(const int64_t *, int64_t *); #endif #if __XPG_VISIBLE int futimes(int, const struct timeval *); int getitimer(int, struct itimerval *); int gettimeofday(struct timeval *, struct timezone *); int setitimer(int, const struct itimerval *, struct itimerval *); int settimeofday(const struct timeval *, const struct timezone *); int utimes(const char *, const struct timeval *); #endif /* __XPG_VISIBLE */ __END_DECLS #endif /* __BSD_VISIBLE || __XPG_VISIBLE */ #endif /* !_KERNEL */ #endif /* !_SYS_TIME_H_ */
58 58 58 399 397 128 127 1285 1286 1285 58 58 229 230 229 1796 1986 354 351 1795 1887 133 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857 6858 6859 6860 6861 6862 6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889 6890 6891 6892 6893 6894 6895 6896 6897 6898 6899 6900 6901 6902 6903 6904 6905 6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932 6933 6934 6935 6936 6937 6938 6939 6940 6941 6942 6943 6944 6945 6946 6947 6948 6949 6950 6951 6952 6953 6954 6955 6956 6957 6958 6959 6960 6961 6962 6963 6964 6965 6966 6967 6968 6969 6970 6971 6972 6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991 6992 6993 6994 6995 6996 6997 6998 6999 7000 7001 7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053 7054 7055 7056 7057 7058 7059 7060 7061 7062 7063 7064 7065 7066 7067 7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126 7127 7128 7129 7130 7131 7132 7133 7134 7135 7136 7137 7138 7139 7140 7141 7142 7143 7144 7145 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 7222 7223 7224 7225 7226 7227 7228 7229 7230 7231 7232 7233 7234 7235 7236 7237 7238 7239 7240 7241 7242 7243 7244 7245 7246 7247 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257 7258 7259 7260 7261 7262 7263 7264 7265 7266 7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 7282 7283 7284 7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296 7297 7298 7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 7344 7345 7346 7347 7348 7349 7350 7351 7352 7353 7354 7355 7356 7357 7358 7359 7360 7361 7362 7363 7364 7365 7366 7367 7368 7369 7370 7371 7372 7373 7374 7375 7376 7377 7378 7379 7380 7381 7382 7383 7384 7385 7386 7387 7388 7389 7390 7391 7392 7393 7394 7395 7396 7397 7398 7399 7400 7401 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425 7426 7427 7428 7429 7430 7431 7432 7433 7434 7435 7436 7437 7438 7439 7440 7441 7442 7443 7444 7445 7446 7447 7448 7449 7450 7451 7452 7453 7454 7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 7499 7500 7501 7502 7503 7504 7505 7506 7507 7508 7509 7510 7511 7512 7513 7514 7515 7516 7517 7518 7519 7520 7521 7522 7523 7524 7525 7526 7527 7528 7529 7530 7531 7532 7533 7534 7535 7536 7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571 7572 7573 7574 7575 7576 7577 7578 7579 7580 7581 7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599 7600 7601 7602 7603 7604 7605 7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 7616 7617 7618 7619 7620 7621 7622 7623 7624 7625 7626 7627 7628 7629 7630 7631 7632 7633 7634 7635 7636 7637 7638 7639 7640 7641 7642 7643 7644 7645 7646 7647 7648 7649 7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 7663 7664 7665 7666 7667 7668 7669 7670 7671 7672 7673 7674 7675 7676 7677 7678 7679 7680 7681 7682 7683 7684 7685 7686 7687 7688 7689 7690 7691 7692 7693 7694 7695 7696 7697 7698 7699 7700 7701 7702 7703 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717 7718 7719 7720 7721 7722 7723 7724 7725 7726 7727 7728 7729 7730 7731 7732 7733 7734 7735 7736 7737 7738 7739 7740 7741 7742 7743 7744 7745 7746 7747 7748 7749 7750 7751 7752 7753 7754 7755 7756 7757 7758 7759 7760 7761 7762 7763 7764 7765 7766 7767 7768 7769 7770 7771 7772 7773 7774 7775 7776 7777 7778 7779 7780 7781 7782 7783 7784 7785 7786 7787 7788 7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807 7808 7809 7810 7811 7812 7813 7814 7815 7816 7817 7818 7819 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 7832 7833 7834 7835 7836 7837 7838 7839 7840 7841 7842 7843 7844 7845 7846 7847 7848 7849 7850 7851 7852 7853 7854 7855 7856 7857 7858 7859 7860 7861 7862 7863 7864 7865 7866 7867 7868 7869 7870 7871 7872 7873 7874 7875 7876 7877 7878 7879 7880 7881 7882 7883 7884 7885 7886 7887 7888 7889 7890 7891 7892 7893 7894 7895 7896 7897 7898 7899 7900 7901 7902 7903 7904 7905 7906 7907 7908 7909 7910 7911 7912 7913 7914 7915 7916 7917 7918 7919 7920 7921 7922 7923 7924 7925 7926 7927 7928 7929 7930 7931 7932 7933 7934 7935 7936 7937 7938 7939 7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956 7957 7958 7959 7960 7961 7962 7963 7964 7965 7966 7967 7968 7969 7970 7971 7972 7973 7974 7975 7976 7977 7978 7979 7980 7981 7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993 7994 7995 7996 7997 7998 7999 8000 8001 8002 8003 8004 8005 8006 8007 8008 8009 8010 8011 8012 8013 8014 8015 8016 8017 8018 8019 8020 8021 8022 8023 8024 8025 8026 8027 8028 8029 8030 8031 8032 8033 8034 8035 8036 8037 8038 8039 8040 8041 8042 8043 8044 8045 8046 8047 8048 8049 8050 8051 8052 8053 8054 8055 8056 8057 8058 8059 8060 8061 8062 8063 8064 8065 8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083 8084 8085 8086 8087 8088 8089 8090 8091 8092 8093 8094 8095 8096 8097 8098 8099 8100 8101 8102 8103 8104 8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126 8127 8128 8129 8130 8131 8132 8133 8134 8135 8136 8137 8138 8139 8140 8141 8142 8143 8144 8145 8146 8147 8148 8149 8150 8151 8152 8153 8154 8155 8156 8157 8158 8159 8160 8161 8162 8163 8164 8165 8166 8167 8168 8169 8170 8171 8172 8173 8174 8175 8176 8177 8178 8179 8180 8181 8182 8183 8184 8185 8186 8187 8188 8189 8190 8191 8192 8193 8194 8195 8196 8197 8198 8199 8200 8201 8202 8203 8204 8205 8206 8207 8208 8209 8210 8211 8212 8213 8214 8215 8216 8217 8218 8219 8220 8221 8222 8223 8224 8225 8226 8227 8228 8229 8230 8231 8232 8233 8234 8235 8236 8237 8238 8239 8240 8241 8242 8243 8244 8245 8246 8247 8248 8249 8250 8251 8252 8253 8254 8255 8256 8257 8258 8259 8260 8261 8262 8263 8264 8265 8266 8267 8268 8269 8270 8271 8272 8273 8274 8275 8276 8277 8278 8279 8280 8281 8282 8283 8284 8285 8286 8287 8288 8289 8290 8291 8292 8293 8294 8295 8296 8297 8298 8299 8300 8301 8302 8303 8304 8305 8306 8307 8308 8309 8310 8311 8312 8313 8314 8315 8316 8317 8318 8319 8320 8321 8322 8323 8324 8325 8326 8327 8328 8329 8330 8331 8332 8333 8334 8335 8336 8337 8338 8339 8340 8341 /* $OpenBSD: pf.c,v 1.1196 2024/05/14 08:26:13 jsg Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier * Copyright (c) 2002 - 2013 Henning Brauer <henning@openbsd.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Effort sponsored in part by the Defense Advanced Research Projects * Agency (DARPA) and Air Force Research Laboratory, Air Force * Materiel Command, USAF, under agreement number F30602-01-2-0537. * */ #include "bpfilter.h" #include "carp.h" #include "pflog.h" #include "pfsync.h" #include "pflow.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/filio.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/kernel.h> #include <sys/time.h> #include <sys/pool.h> #include <sys/proc.h> #include <sys/rwlock.h> #include <sys/syslog.h> #include <crypto/sha2.h> #include <net/if.h> #include <net/if_var.h> #include <net/if_types.h> #include <net/route.h> #include <net/toeplitz.h> #include <netinet/in.h> #include <netinet/in_var.h> #include <netinet/ip.h> #include <netinet/in_pcb.h> #include <netinet/ip_var.h> #include <netinet/ip_icmp.h> #include <netinet/icmp_var.h> #include <netinet/tcp.h> #include <netinet/tcp_seq.h> #include <netinet/tcp_timer.h> #include <netinet/tcp_var.h> #include <netinet/tcp_fsm.h> #include <netinet/udp.h> #include <netinet/udp_var.h> #include <netinet/ip_divert.h> #ifdef INET6 #include <netinet6/in6_var.h> #include <netinet/ip6.h> #include <netinet6/ip6_var.h> #include <netinet/icmp6.h> #include <netinet6/nd6.h> #include <netinet6/ip6_divert.h> #endif /* INET6 */ #include <net/pfvar.h> #include <net/pfvar_priv.h> #if NPFLOG > 0 #include <net/if_pflog.h> #endif /* NPFLOG > 0 */ #if NPFLOW > 0 #include <net/if_pflow.h> #endif /* NPFLOW > 0 */ #if NPFSYNC > 0 #include <net/if_pfsync.h> #endif /* NPFSYNC > 0 */ /* * Global variables */ struct pf_state_tree pf_statetbl; struct pf_queuehead pf_queues[2]; struct pf_queuehead *pf_queues_active; struct pf_queuehead *pf_queues_inactive; struct pf_status pf_status; struct mutex pf_inp_mtx = MUTEX_INITIALIZER(IPL_SOFTNET); int pf_hdr_limit = 20; /* arbitrary limit, tune in ddb */ SHA2_CTX pf_tcp_secret_ctx; u_char pf_tcp_secret[16]; int pf_tcp_secret_init; int pf_tcp_iss_off; enum pf_test_status { PF_TEST_FAIL = -1, PF_TEST_OK, PF_TEST_QUICK }; struct pf_test_ctx { struct pf_pdesc *pd; struct pf_rule_actions act; u_int8_t icmpcode; u_int8_t icmptype; int icmp_dir; int state_icmp; int tag; u_short reason; struct pf_rule_item *ri; struct pf_src_node *sns[PF_SN_MAX]; struct pf_rule_slist rules; struct pf_rule *nr; struct pf_rule **rm; struct pf_rule *a; struct pf_rule **am; struct pf_ruleset **rsm; struct pf_ruleset *arsm; struct pf_ruleset *aruleset; struct tcphdr *th; }; struct pool pf_src_tree_pl, pf_rule_pl, pf_queue_pl; struct pool pf_state_pl, pf_state_key_pl, pf_state_item_pl; struct pool pf_rule_item_pl, pf_sn_item_pl, pf_pktdelay_pl; void pf_add_threshold(struct pf_threshold *); int pf_check_threshold(struct pf_threshold *); int pf_check_tcp_cksum(struct mbuf *, int, int, sa_family_t); __inline void pf_cksum_fixup(u_int16_t *, u_int16_t, u_int16_t, u_int8_t); void pf_cksum_fixup_a(u_int16_t *, const struct pf_addr *, const struct pf_addr *, sa_family_t, u_int8_t); int pf_modulate_sack(struct pf_pdesc *, struct pf_state_peer *); int pf_icmp_mapping(struct pf_pdesc *, u_int8_t, int *, u_int16_t *, u_int16_t *); int pf_change_icmp_af(struct mbuf *, int, struct pf_pdesc *, struct pf_pdesc *, struct pf_addr *, struct pf_addr *, sa_family_t, sa_family_t); int pf_translate_a(struct pf_pdesc *, struct pf_addr *, struct pf_addr *); void pf_translate_icmp(struct pf_pdesc *, struct pf_addr *, u_int16_t *, struct pf_addr *, struct pf_addr *, u_int16_t); int pf_translate_icmp_af(struct pf_pdesc*, int, void *); void pf_send_icmp(struct mbuf *, u_int8_t, u_int8_t, int, sa_family_t, struct pf_rule *, u_int); void pf_detach_state(struct pf_state *); struct pf_state_key *pf_state_key_attach(struct pf_state_key *, struct pf_state *, int); void pf_state_key_detach(struct pf_state *, int); u_int32_t pf_tcp_iss(struct pf_pdesc *); void pf_rule_to_actions(struct pf_rule *, struct pf_rule_actions *); int pf_test_rule(struct pf_pdesc *, struct pf_rule **, struct pf_state **, struct pf_rule **, struct pf_ruleset **, u_short *); static __inline int pf_create_state(struct pf_pdesc *, struct pf_rule *, struct pf_rule *, struct pf_rule *, struct pf_state_key **, struct pf_state_key **, int *, struct pf_state **, int, struct pf_rule_slist *, struct pf_rule_actions *, struct pf_src_node **); static __inline int pf_state_key_addr_setup(struct pf_pdesc *, void *, int, struct pf_addr *, int, struct pf_addr *, int, int); int pf_state_key_setup(struct pf_pdesc *, struct pf_state_key **, struct pf_state_key **, int); int pf_tcp_track_full(struct pf_pdesc *, struct pf_state **, u_short *, int *, int); int pf_tcp_track_sloppy(struct pf_pdesc *, struct pf_state **, u_short *); static __inline int pf_synproxy(struct pf_pdesc *, struct pf_state **, u_short *); int pf_test_state(struct pf_pdesc *, struct pf_state **, u_short *); int pf_icmp_state_lookup(struct pf_pdesc *, struct pf_state_key_cmp *, struct pf_state **, u_int16_t, u_int16_t, int, int *, int, int); int pf_test_state_icmp(struct pf_pdesc *, struct pf_state **, u_short *); u_int16_t pf_calc_mss(struct pf_addr *, sa_family_t, int, u_int16_t); static __inline int pf_set_rt_ifp(struct pf_state *, struct pf_addr *, sa_family_t, struct pf_src_node **); struct pf_divert *pf_get_divert(struct mbuf *); int pf_walk_option(struct pf_pdesc *, struct ip *, int, int, u_short *); int pf_walk_header(struct pf_pdesc *, struct ip *, u_short *); int pf_walk_option6(struct pf_pdesc *, struct ip6_hdr *, int, int, u_short *); int pf_walk_header6(struct pf_pdesc *, struct ip6_hdr *, u_short *); void pf_print_state_parts(struct pf_state *, struct pf_state_key *, struct pf_state_key *); int pf_addr_wrap_neq(struct pf_addr_wrap *, struct pf_addr_wrap *); int pf_compare_state_keys(struct pf_state_key *, struct pf_state_key *, struct pfi_kif *, u_int); u_int16_t pf_pkt_hash(sa_family_t, uint8_t, const struct pf_addr *, const struct pf_addr *, uint16_t, uint16_t); int pf_find_state(struct pf_pdesc *, struct pf_state_key_cmp *, struct pf_state **); int pf_src_connlimit(struct pf_state **); int pf_match_rcvif(struct mbuf *, struct pf_rule *); enum pf_test_status pf_match_rule(struct pf_test_ctx *, struct pf_ruleset *); void pf_counters_inc(int, struct pf_pdesc *, struct pf_state *, struct pf_rule *, struct pf_rule *); int pf_state_insert(struct pfi_kif *, struct pf_state_key **, struct pf_state_key **, struct pf_state *); int pf_state_key_isvalid(struct pf_state_key *); struct pf_state_key *pf_state_key_ref(struct pf_state_key *); void pf_state_key_unref(struct pf_state_key *); void pf_state_key_link_reverse(struct pf_state_key *, struct pf_state_key *); void pf_state_key_unlink_reverse(struct pf_state_key *); void pf_state_key_link_inpcb(struct pf_state_key *, struct inpcb *); void pf_state_key_unlink_inpcb(struct pf_state_key *); void pf_pktenqueue_delayed(void *); int32_t pf_state_expires(const struct pf_state *, uint8_t); #if NPFLOG > 0 void pf_log_matches(struct pf_pdesc *, struct pf_rule *, struct pf_rule *, struct pf_ruleset *, struct pf_rule_slist *); #endif /* NPFLOG > 0 */ extern struct pool pfr_ktable_pl; extern struct pool pfr_kentry_pl; struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = { { &pf_state_pl, PFSTATE_HIWAT, PFSTATE_HIWAT }, { &pf_src_tree_pl, PFSNODE_HIWAT, PFSNODE_HIWAT }, { &pf_frent_pl, PFFRAG_FRENT_HIWAT, PFFRAG_FRENT_HIWAT }, { &pfr_ktable_pl, PFR_KTABLE_HIWAT, PFR_KTABLE_HIWAT }, { &pfr_kentry_pl, PFR_KENTRY_HIWAT, PFR_KENTRY_HIWAT }, { &pf_pktdelay_pl, PF_PKTDELAY_MAXPKTS, PF_PKTDELAY_MAXPKTS }, { &pf_anchor_pl, PF_ANCHOR_HIWAT, PF_ANCHOR_HIWAT } }; #define BOUND_IFACE(r, k) \ ((r)->rule_flag & PFRULE_IFBOUND) ? (k) : pfi_all #define STATE_INC_COUNTERS(s) \ do { \ struct pf_rule_item *mrm; \ s->rule.ptr->states_cur++; \ s->rule.ptr->states_tot++; \ if (s->anchor.ptr != NULL) { \ s->anchor.ptr->states_cur++; \ s->anchor.ptr->states_tot++; \ } \ SLIST_FOREACH(mrm, &s->match_rules, entry) \ mrm->r->states_cur++; \ } while (0) static __inline int pf_src_compare(struct pf_src_node *, struct pf_src_node *); static inline int pf_state_compare_key(const struct pf_state_key *, const struct pf_state_key *); static inline int pf_state_compare_id(const struct pf_state *, const struct pf_state *); #ifdef INET6 static __inline void pf_cksum_uncover(u_int16_t *, u_int16_t, u_int8_t); static __inline void pf_cksum_cover(u_int16_t *, u_int16_t, u_int8_t); #endif /* INET6 */ static __inline void pf_set_protostate(struct pf_state *, int, u_int8_t); struct pf_src_tree tree_src_tracking; struct pf_state_tree_id tree_id; struct pf_state_list pf_state_list = PF_STATE_LIST_INITIALIZER(pf_state_list); RB_GENERATE(pf_src_tree, pf_src_node, entry, pf_src_compare); RBT_GENERATE(pf_state_tree, pf_state_key, sk_entry, pf_state_compare_key); RBT_GENERATE(pf_state_tree_id, pf_state, entry_id, pf_state_compare_id); int pf_addr_compare(const struct pf_addr *a, const struct pf_addr *b, sa_family_t af) { switch (af) { case AF_INET: if (a->addr32[0] > b->addr32[0]) return (1); if (a->addr32[0] < b->addr32[0]) return (-1); break; #ifdef INET6 case AF_INET6: if (a->addr32[3] > b->addr32[3]) return (1); if (a->addr32[3] < b->addr32[3]) return (-1); if (a->addr32[2] > b->addr32[2]) return (1); if (a->addr32[2] < b->addr32[2]) return (-1); if (a->addr32[1] > b->addr32[1]) return (1); if (a->addr32[1] < b->addr32[1]) return (-1); if (a->addr32[0] > b->addr32[0]) return (1); if (a->addr32[0] < b->addr32[0]) return (-1); break; #endif /* INET6 */ } return (0); } static __inline int pf_src_compare(struct pf_src_node *a, struct pf_src_node *b) { int diff; if (a->rule.ptr > b->rule.ptr) return (1); if (a->rule.ptr < b->rule.ptr) return (-1); if ((diff = a->type - b->type) != 0) return (diff); if ((diff = a->af - b->af) != 0) return (diff); if ((diff = pf_addr_compare(&a->addr, &b->addr, a->af)) != 0) return (diff); return (0); } static __inline void pf_set_protostate(struct pf_state *st, int which, u_int8_t newstate) { if (which == PF_PEER_DST || which == PF_PEER_BOTH) st->dst.state = newstate; if (which == PF_PEER_DST) return; if (st->src.state == newstate) return; if (st->creatorid == pf_status.hostid && st->key[PF_SK_STACK]->proto == IPPROTO_TCP && !(TCPS_HAVEESTABLISHED(st->src.state) || st->src.state == TCPS_CLOSED) && (TCPS_HAVEESTABLISHED(newstate) || newstate == TCPS_CLOSED)) pf_status.states_halfopen--; st->src.state = newstate; } void pf_addrcpy(struct pf_addr *dst, struct pf_addr *src, sa_family_t af) { switch (af) { case AF_INET: dst->addr32[0] = src->addr32[0]; break; #ifdef INET6 case AF_INET6: dst->addr32[0] = src->addr32[0]; dst->addr32[1] = src->addr32[1]; dst->addr32[2] = src->addr32[2]; dst->addr32[3] = src->addr32[3]; break; #endif /* INET6 */ default: unhandled_af(af); } } void pf_init_threshold(struct pf_threshold *threshold, u_int32_t limit, u_int32_t seconds) { threshold->limit = limit * PF_THRESHOLD_MULT; threshold->seconds = seconds; threshold->count = 0; threshold->last = getuptime(); } void pf_add_threshold(struct pf_threshold *threshold) { u_int32_t t = getuptime(), diff = t - threshold->last; if (diff >= threshold->seconds) threshold->count = 0; else threshold->count -= threshold->count * diff / threshold->seconds; threshold->count += PF_THRESHOLD_MULT; threshold->last = t; } int pf_check_threshold(struct pf_threshold *threshold) { return (threshold->count > threshold->limit); } void pf_state_list_insert(struct pf_state_list *pfs, struct pf_state *st) { /* * we can always put states on the end of the list. * * things reading the list should take a read lock, then * the mutex, get the head and tail pointers, release the * mutex, and then they can iterate between the head and tail. */ pf_state_ref(st); /* get a ref for the list */ mtx_enter(&pfs->pfs_mtx); TAILQ_INSERT_TAIL(&pfs->pfs_list, st, entry_list); mtx_leave(&pfs->pfs_mtx); } void pf_state_list_remove(struct pf_state_list *pfs, struct pf_state *st) { /* states can only be removed when the write lock is held */ rw_assert_wrlock(&pfs->pfs_rwl); mtx_enter(&pfs->pfs_mtx); TAILQ_REMOVE(&pfs->pfs_list, st, entry_list); mtx_leave(&pfs->pfs_mtx); pf_state_unref(st); /* list no longer references the state */ } void pf_update_state_timeout(struct pf_state *st, int to) { mtx_enter(&st->mtx); if (st->timeout != PFTM_UNLINKED) st->timeout = to; mtx_leave(&st->mtx); } int pf_src_connlimit(struct pf_state **stp) { int bad = 0; struct pf_src_node *sn; if ((sn = pf_get_src_node((*stp), PF_SN_NONE)) == NULL) return (0); sn->conn++; (*stp)->src.tcp_est = 1; pf_add_threshold(&sn->conn_rate); if ((*stp)->rule.ptr->max_src_conn && (*stp)->rule.ptr->max_src_conn < sn->conn) { pf_status.lcounters[LCNT_SRCCONN]++; bad++; } if ((*stp)->rule.ptr->max_src_conn_rate.limit && pf_check_threshold(&sn->conn_rate)) { pf_status.lcounters[LCNT_SRCCONNRATE]++; bad++; } if (!bad) return (0); if ((*stp)->rule.ptr->overload_tbl) { struct pfr_addr p; u_int32_t killed = 0; pf_status.lcounters[LCNT_OVERLOAD_TABLE]++; if (pf_status.debug >= LOG_NOTICE) { log(LOG_NOTICE, "pf: pf_src_connlimit: blocking address "); pf_print_host(&sn->addr, 0, (*stp)->key[PF_SK_WIRE]->af); } memset(&p, 0, sizeof(p)); p.pfra_af = (*stp)->key[PF_SK_WIRE]->af; switch ((*stp)->key[PF_SK_WIRE]->af) { case AF_INET: p.pfra_net = 32; p.pfra_ip4addr = sn->addr.v4; break; #ifdef INET6 case AF_INET6: p.pfra_net = 128; p.pfra_ip6addr = sn->addr.v6; break; #endif /* INET6 */ } pfr_insert_kentry((*stp)->rule.ptr->overload_tbl, &p, gettime()); /* kill existing states if that's required. */ if ((*stp)->rule.ptr->flush) { struct pf_state_key *sk; struct pf_state *st; pf_status.lcounters[LCNT_OVERLOAD_FLUSH]++; RBT_FOREACH(st, pf_state_tree_id, &tree_id) { sk = st->key[PF_SK_WIRE]; /* * Kill states from this source. (Only those * from the same rule if PF_FLUSH_GLOBAL is not * set) */ if (sk->af == (*stp)->key[PF_SK_WIRE]->af && (((*stp)->direction == PF_OUT && PF_AEQ(&sn->addr, &sk->addr[1], sk->af)) || ((*stp)->direction == PF_IN && PF_AEQ(&sn->addr, &sk->addr[0], sk->af))) && ((*stp)->rule.ptr->flush & PF_FLUSH_GLOBAL || (*stp)->rule.ptr == st->rule.ptr)) { pf_update_state_timeout(st, PFTM_PURGE); pf_set_protostate(st, PF_PEER_BOTH, TCPS_CLOSED); killed++; } } if (pf_status.debug >= LOG_NOTICE) addlog(", %u states killed", killed); } if (pf_status.debug >= LOG_NOTICE) addlog("\n"); } /* kill this state */ pf_update_state_timeout(*stp, PFTM_PURGE); pf_set_protostate(*stp, PF_PEER_BOTH, TCPS_CLOSED); return (1); } int pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule, enum pf_sn_types type, sa_family_t af, struct pf_addr *src, struct pf_addr *raddr, struct pfi_kif *kif) { struct pf_src_node k; if (*sn == NULL) { k.af = af; k.type = type; pf_addrcpy(&k.addr, src, af); k.rule.ptr = rule; pf_status.scounters[SCNT_SRC_NODE_SEARCH]++; *sn = RB_FIND(pf_src_tree, &tree_src_tracking, &k); } if (*sn == NULL) { if (!rule->max_src_nodes || rule->src_nodes < rule->max_src_nodes) (*sn) = pool_get(&pf_src_tree_pl, PR_NOWAIT | PR_ZERO); else pf_status.lcounters[LCNT_SRCNODES]++; if ((*sn) == NULL) return (-1); pf_init_threshold(&(*sn)->conn_rate, rule->max_src_conn_rate.limit, rule->max_src_conn_rate.seconds); (*sn)->type = type; (*sn)->af = af; (*sn)->rule.ptr = rule; pf_addrcpy(&(*sn)->addr, src, af); if (raddr) pf_addrcpy(&(*sn)->raddr, raddr, af); if (RB_INSERT(pf_src_tree, &tree_src_tracking, *sn) != NULL) { if (pf_status.debug >= LOG_NOTICE) { log(LOG_NOTICE, "pf: src_tree insert failed: "); pf_print_host(&(*sn)->addr, 0, af); addlog("\n"); } pool_put(&pf_src_tree_pl, *sn); return (-1); } (*sn)->creation = getuptime(); (*sn)->rule.ptr->src_nodes++; if (kif != NULL) { (*sn)->kif = kif; pfi_kif_ref(kif, PFI_KIF_REF_SRCNODE); } pf_status.scounters[SCNT_SRC_NODE_INSERT]++; pf_status.src_nodes++; } else { if (rule->max_src_states && (*sn)->states >= rule->max_src_states) { pf_status.lcounters[LCNT_SRCSTATES]++; return (-1); } } return (0); } void pf_remove_src_node(struct pf_src_node *sn) { if (sn->states > 0 || sn->expire > getuptime()) return; sn->rule.ptr->src_nodes--; if (sn->rule.ptr->states_cur == 0 && sn->rule.ptr->src_nodes == 0) pf_rm_rule(NULL, sn->rule.ptr); RB_REMOVE(pf_src_tree, &tree_src_tracking, sn); pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++; pf_status.src_nodes--; pfi_kif_unref(sn->kif, PFI_KIF_REF_SRCNODE); pool_put(&pf_src_tree_pl, sn); } struct pf_src_node * pf_get_src_node(struct pf_state *st, enum pf_sn_types type) { struct pf_sn_item *sni; SLIST_FOREACH(sni, &st->src_nodes, next) if (sni->sn->type == type) return (sni->sn); return (NULL); } void pf_state_rm_src_node(struct pf_state *st, struct pf_src_node *sn) { struct pf_sn_item *sni, *snin, *snip = NULL; for (sni = SLIST_FIRST(&st->src_nodes); sni; sni = snin) { snin = SLIST_NEXT(sni, next); if (sni->sn == sn) { if (snip) SLIST_REMOVE_AFTER(snip, next); else SLIST_REMOVE_HEAD(&st->src_nodes, next); pool_put(&pf_sn_item_pl, sni); sni = NULL; sn->states--; } if (sni != NULL) snip = sni; } } /* state table stuff */ static inline int pf_state_compare_key(const struct pf_state_key *a, const struct pf_state_key *b) { int diff; if ((diff = a->hash - b->hash) != 0) return (diff); if ((diff = a->proto - b->proto) != 0) return (diff); if ((diff = a->af - b->af) != 0) return (diff); if ((diff = pf_addr_compare(&a->addr[0], &b->addr[0], a->af)) != 0) return (diff); if ((diff = pf_addr_compare(&a->addr[1], &b->addr[1], a->af)) != 0) return (diff); if ((diff = a->port[0] - b->port[0]) != 0) return (diff); if ((diff = a->port[1] - b->port[1]) != 0) return (diff); if ((diff = a->rdomain - b->rdomain) != 0) return (diff); return (0); } static inline int pf_state_compare_id(const struct pf_state *a, const struct pf_state *b) { if (a->id > b->id) return (1); if (a->id < b->id) return (-1); if (a->creatorid > b->creatorid) return (1); if (a->creatorid < b->creatorid) return (-1); return (0); } /* * on failure, pf_state_key_attach() releases the pf_state_key * reference and returns NULL. */ struct pf_state_key * pf_state_key_attach(struct pf_state_key *sk, struct pf_state *st, int idx) { struct pf_state_item *si; struct pf_state_key *cur; struct pf_state *oldst = NULL; PF_ASSERT_LOCKED(); KASSERT(st->key[idx] == NULL); sk->sk_removed = 0; cur = RBT_INSERT(pf_state_tree, &pf_statetbl, sk); if (cur != NULL) { sk->sk_removed = 1; /* key exists. check for same kif, if none, add to key */ TAILQ_FOREACH(si, &cur->sk_states, si_entry) { struct pf_state *sist = si->si_st; if (sist->kif == st->kif && ((sist->key[PF_SK_WIRE]->af == sk->af && sist->direction == st->direction) || (sist->key[PF_SK_WIRE]->af != sist->key[PF_SK_STACK]->af && sk->af == sist->key[PF_SK_STACK]->af && sist->direction != st->direction))) { int reuse = 0; if (sk->proto == IPPROTO_TCP && sist->src.state >= TCPS_FIN_WAIT_2 && sist->dst.state >= TCPS_FIN_WAIT_2) reuse = 1; if (pf_status.debug >= LOG_NOTICE) { log(LOG_NOTICE, "pf: %s key attach %s on %s: ", (idx == PF_SK_WIRE) ? "wire" : "stack", reuse ? "reuse" : "failed", st->kif->pfik_name); pf_print_state_parts(st, (idx == PF_SK_WIRE) ? sk : NULL, (idx == PF_SK_STACK) ? sk : NULL); addlog(", existing: "); pf_print_state_parts(sist, (idx == PF_SK_WIRE) ? sk : NULL, (idx == PF_SK_STACK) ? sk : NULL); addlog("\n"); } if (reuse) { pf_set_protostate(sist, PF_PEER_BOTH, TCPS_CLOSED); /* remove late or sks can go away */ oldst = sist; } else { pf_state_key_unref(sk); return (NULL); /* collision! */ } } } /* reuse the existing state key */ pf_state_key_unref(sk); sk = cur; } if ((si = pool_get(&pf_state_item_pl, PR_NOWAIT)) == NULL) { if (TAILQ_EMPTY(&sk->sk_states)) { KASSERT(cur == NULL); RBT_REMOVE(pf_state_tree, &pf_statetbl, sk); sk->sk_removed = 1; pf_state_key_unref(sk); } return (NULL); } st->key[idx] = pf_state_key_ref(sk); /* give a ref to state */ si->si_st = pf_state_ref(st); /* list is sorted, if-bound states before floating */ if (st->kif == pfi_all) TAILQ_INSERT_TAIL(&sk->sk_states, si, si_entry); else TAILQ_INSERT_HEAD(&sk->sk_states, si, si_entry); if (oldst) pf_remove_state(oldst); /* caller owns the pf_state ref, which owns a pf_state_key ref now */ return (sk); } void pf_detach_state(struct pf_state *st) { KASSERT(st->key[PF_SK_WIRE] != NULL); pf_state_key_detach(st, PF_SK_WIRE); KASSERT(st->key[PF_SK_STACK] != NULL); if (st->key[PF_SK_STACK] != st->key[PF_SK_WIRE]) pf_state_key_detach(st, PF_SK_STACK); } void pf_state_key_detach(struct pf_state *st, int idx) { struct pf_state_item *si; struct pf_state_key *sk; PF_ASSERT_LOCKED(); sk = st->key[idx]; if (sk == NULL) return; TAILQ_FOREACH(si, &sk->sk_states, si_entry) { if (si->si_st == st) break; } if (si == NULL) return; TAILQ_REMOVE(&sk->sk_states, si, si_entry); pool_put(&pf_state_item_pl, si); if (TAILQ_EMPTY(&sk->sk_states)) { RBT_REMOVE(pf_state_tree, &pf_statetbl, sk); sk->sk_removed = 1; pf_state_key_unlink_reverse(sk); pf_state_key_unlink_inpcb(sk); pf_state_key_unref(sk); } pf_state_unref(st); } struct pf_state_key * pf_alloc_state_key(int pool_flags) { struct pf_state_key *sk; if ((sk = pool_get(&pf_state_key_pl, pool_flags)) == NULL) return (NULL); PF_REF_INIT(sk->sk_refcnt); TAILQ_INIT(&sk->sk_states); sk->sk_removed = 1; return (sk); } static __inline int pf_state_key_addr_setup(struct pf_pdesc *pd, void *arg, int sidx, struct pf_addr *saddr, int didx, struct pf_addr *daddr, int af, int multi) { struct pf_state_key_cmp *key = arg; #ifdef INET6 struct pf_addr *target; if (af == AF_INET || pd->proto != IPPROTO_ICMPV6) goto copy; switch (pd->hdr.icmp6.icmp6_type) { case ND_NEIGHBOR_SOLICIT: if (multi) return (-1); target = (struct pf_addr *)&pd->hdr.nd_ns.nd_ns_target; daddr = target; break; case ND_NEIGHBOR_ADVERT: if (multi) return (-1); target = (struct pf_addr *)&pd->hdr.nd_ns.nd_ns_target; saddr = target; if (IN6_IS_ADDR_MULTICAST(&pd->dst->v6)) { key->addr[didx].addr32[0] = 0; key->addr[didx].addr32[1] = 0; key->addr[didx].addr32[2] = 0; key->addr[didx].addr32[3] = 0; daddr = NULL; /* overwritten */ } break; default: if (multi) { key->addr[sidx].addr32[0] = __IPV6_ADDR_INT32_MLL; key->addr[sidx].addr32[1] = 0; key->addr[sidx].addr32[2] = 0; key->addr[sidx].addr32[3] = __IPV6_ADDR_INT32_ONE; saddr = NULL; /* overwritten */ } } copy: #endif /* INET6 */ if (saddr) pf_addrcpy(&key->addr[sidx], saddr, af); if (daddr) pf_addrcpy(&key->addr[didx], daddr, af); return (0); } int pf_state_key_setup(struct pf_pdesc *pd, struct pf_state_key **skw, struct pf_state_key **sks, int rtableid) { /* if returning error we MUST pool_put state keys ourselves */ struct pf_state_key *sk1, *sk2; u_int wrdom = pd->rdomain; int afto = pd->af != pd->naf; if ((sk1 = pf_alloc_state_key(PR_NOWAIT | PR_ZERO)) == NULL) return (ENOMEM); pf_state_key_addr_setup(pd, sk1, pd->sidx, pd->src, pd->didx, pd->dst, pd->af, 0); sk1->port[pd->sidx] = pd->osport; sk1->port[pd->didx] = pd->odport; sk1->proto = pd->proto; sk1->af = pd->af; sk1->rdomain = pd->rdomain; sk1->hash = pf_pkt_hash(sk1->af, sk1->proto, &sk1->addr[0], &sk1->addr[1], sk1->port[0], sk1->port[1]); if (rtableid >= 0) wrdom = rtable_l2(rtableid); if (PF_ANEQ(&pd->nsaddr, pd->src, pd->af) || PF_ANEQ(&pd->ndaddr, pd->dst, pd->af) || pd->nsport != pd->osport || pd->ndport != pd->odport || wrdom != pd->rdomain || afto) { /* NAT/NAT64 */ if ((sk2 = pf_alloc_state_key(PR_NOWAIT | PR_ZERO)) == NULL) { pf_state_key_unref(sk1); return (ENOMEM); } pf_state_key_addr_setup(pd, sk2, afto ? pd->didx : pd->sidx, &pd->nsaddr, afto ? pd->sidx : pd->didx, &pd->ndaddr, pd->naf, 0); sk2->port[afto ? pd->didx : pd->sidx] = pd->nsport; sk2->port[afto ? pd->sidx : pd->didx] = pd->ndport; if (afto) { switch (pd->proto) { case IPPROTO_ICMP: sk2->proto = IPPROTO_ICMPV6; break; case IPPROTO_ICMPV6: sk2->proto = IPPROTO_ICMP; break; default: sk2->proto = pd->proto; } } else sk2->proto = pd->proto; sk2->af = pd->naf; sk2->rdomain = wrdom; sk2->hash = pf_pkt_hash(sk2->af, sk2->proto, &sk2->addr[0], &sk2->addr[1], sk2->port[0], sk2->port[1]); } else sk2 = pf_state_key_ref(sk1); if (pd->dir == PF_IN) { *skw = sk1; *sks = sk2; } else { *sks = sk1; *skw = sk2; } if (pf_status.debug >= LOG_DEBUG) { log(LOG_DEBUG, "pf: key setup: "); pf_print_state_parts(NULL, *skw, *sks); addlog("\n"); } return (0); } /* * pf_state_insert() does the following: * - links the pf_state up with pf_state_key(s). * - inserts the pf_state_keys into pf_state_tree. * - inserts the pf_state into the into pf_state_tree_id. * - tells pfsync about the state. * * pf_state_insert() owns the references to the pf_state_key structs * it is given. on failure to insert, these references are released. * on success, the caller owns a pf_state reference that allows it * to access the state keys. */ int pf_state_insert(struct pfi_kif *kif, struct pf_state_key **skwp, struct pf_state_key **sksp, struct pf_state *st) { struct pf_state_key *skw = *skwp; struct pf_state_key *sks = *sksp; int same = (skw == sks); PF_ASSERT_LOCKED(); st->kif = kif; PF_STATE_ENTER_WRITE(); skw = pf_state_key_attach(skw, st, PF_SK_WIRE); if (skw == NULL) { pf_state_key_unref(sks); PF_STATE_EXIT_WRITE(); return (-1); } if (same) { /* pf_state_key_attach might have swapped skw */ pf_state_key_unref(sks); st->key[PF_SK_STACK] = sks = pf_state_key_ref(skw); } else if (pf_state_key_attach(sks, st, PF_SK_STACK) == NULL) { pf_state_key_detach(st, PF_SK_WIRE); PF_STATE_EXIT_WRITE(); return (-1); } if (st->id == 0 && st->creatorid == 0) { st->id = htobe64(pf_status.stateid++); st->creatorid = pf_status.hostid; } if (RBT_INSERT(pf_state_tree_id, &tree_id, st) != NULL) { if (pf_status.debug >= LOG_NOTICE) { log(LOG_NOTICE, "pf: state insert failed: " "id: %016llx creatorid: %08x", betoh64(st->id), ntohl(st->creatorid)); addlog("\n"); } pf_detach_state(st); PF_STATE_EXIT_WRITE(); return (-1); } pf_state_list_insert(&pf_state_list, st); pf_status.fcounters[FCNT_STATE_INSERT]++; pf_status.states++; pfi_kif_ref(kif, PFI_KIF_REF_STATE); PF_STATE_EXIT_WRITE(); #if NPFSYNC > 0 pfsync_insert_state(st); #endif /* NPFSYNC > 0 */ *skwp = skw; *sksp = sks; return (0); } struct pf_state * pf_find_state_byid(struct pf_state_cmp *key) { pf_status.fcounters[FCNT_STATE_SEARCH]++; return (RBT_FIND(pf_state_tree_id, &tree_id, (struct pf_state *)key)); } int pf_compare_state_keys(struct pf_state_key *a, struct pf_state_key *b, struct pfi_kif *kif, u_int dir) { /* a (from hdr) and b (new) must be exact opposites of each other */ if (a->af == b->af && a->proto == b->proto && PF_AEQ(&a->addr[0], &b->addr[1], a->af) && PF_AEQ(&a->addr[1], &b->addr[0], a->af) && a->port[0] == b->port[1] && a->port[1] == b->port[0] && a->rdomain == b->rdomain) return (0); else { /* mismatch. must not happen. */ if (pf_status.debug >= LOG_ERR) { log(LOG_ERR, "pf: state key linking mismatch! dir=%s, " "if=%s, stored af=%u, a0: ", dir == PF_OUT ? "OUT" : "IN", kif->pfik_name, a->af); pf_print_host(&a->addr[0], a->port[0], a->af); addlog(", a1: "); pf_print_host(&a->addr[1], a->port[1], a->af); addlog(", proto=%u", a->proto); addlog(", found af=%u, a0: ", b->af); pf_print_host(&b->addr[0], b->port[0], b->af); addlog(", a1: "); pf_print_host(&b->addr[1], b->port[1], b->af); addlog(", proto=%u", b->proto); addlog("\n"); } return (-1); } } int pf_find_state(struct pf_pdesc *pd, struct pf_state_key_cmp *key, struct pf_state **stp) { struct pf_state_key *sk, *pkt_sk; struct pf_state_item *si; struct pf_state *st = NULL; pf_status.fcounters[FCNT_STATE_SEARCH]++; if (pf_status.debug >= LOG_DEBUG) { log(LOG_DEBUG, "pf: key search, %s on %s: ", pd->dir == PF_OUT ? "out" : "in", pd->kif->pfik_name); pf_print_state_parts(NULL, (struct pf_state_key *)key, NULL); addlog("\n"); } pkt_sk = NULL; sk = NULL; if (pd->dir == PF_OUT) { /* first if block deals with outbound forwarded packet */ pkt_sk = pd->m->m_pkthdr.pf.statekey; if (!pf_state_key_isvalid(pkt_sk)) { pf_mbuf_unlink_state_key(pd->m); pkt_sk = NULL; } if (pkt_sk && pf_state_key_isvalid(pkt_sk->sk_reverse)) sk = pkt_sk->sk_reverse; if (pkt_sk == NULL) { struct inpcb *inp = pd->m->m_pkthdr.pf.inp; /* here we deal with local outbound packet */ if (inp != NULL) { struct pf_state_key *inp_sk; mtx_enter(&pf_inp_mtx); inp_sk = inp->inp_pf_sk; if (pf_state_key_isvalid(inp_sk)) { sk = inp_sk; mtx_leave(&pf_inp_mtx); } else if (inp_sk != NULL) { KASSERT(inp_sk->sk_inp == inp); inp_sk->sk_inp = NULL; inp->inp_pf_sk = NULL; mtx_leave(&pf_inp_mtx); pf_state_key_unref(inp_sk); in_pcbunref(inp); } else mtx_leave(&pf_inp_mtx); } } } if (sk == NULL) { if ((sk = RBT_FIND(pf_state_tree, &pf_statetbl, (struct pf_state_key *)key)) == NULL) return (PF_DROP); if (pd->dir == PF_OUT && pkt_sk && pf_compare_state_keys(pkt_sk, sk, pd->kif, pd->dir) == 0) pf_state_key_link_reverse(sk, pkt_sk); else if (pd->dir == PF_OUT) pf_state_key_link_inpcb(sk, pd->m->m_pkthdr.pf.inp); } /* remove firewall data from outbound packet */ if (pd->dir == PF_OUT) pf_pkt_addr_changed(pd->m); /* list is sorted, if-bound states before floating ones */ TAILQ_FOREACH(si, &sk->sk_states, si_entry) { struct pf_state *sist = si->si_st; if (sist->timeout != PFTM_PURGE && (sist->kif == pfi_all || sist->kif == pd->kif) && ((sist->key[PF_SK_WIRE]->af == sist->key[PF_SK_STACK]->af && sk == (pd->dir == PF_IN ? sist->key[PF_SK_WIRE] : sist->key[PF_SK_STACK])) || (sist->key[PF_SK_WIRE]->af != sist->key[PF_SK_STACK]->af && pd->dir == PF_IN && (sk == sist->key[PF_SK_STACK] || sk == sist->key[PF_SK_WIRE])))) { st = sist; break; } } if (st == NULL) return (PF_DROP); if (ISSET(st->state_flags, PFSTATE_INP_UNLINKED)) return (PF_DROP); if (st->rule.ptr->pktrate.limit && pd->dir == st->direction) { pf_add_threshold(&st->rule.ptr->pktrate); if (pf_check_threshold(&st->rule.ptr->pktrate)) return (PF_DROP); } *stp = st; return (PF_MATCH); } struct pf_state * pf_find_state_all(struct pf_state_key_cmp *key, u_int dir, int *more) { struct pf_state_key *sk; struct pf_state_item *si, *ret = NULL; pf_status.fcounters[FCNT_STATE_SEARCH]++; sk = RBT_FIND(pf_state_tree, &pf_statetbl, (struct pf_state_key *)key); if (sk != NULL) { TAILQ_FOREACH(si, &sk->sk_states, si_entry) { struct pf_state *sist = si->si_st; if (dir == PF_INOUT || (sk == (dir == PF_IN ? sist->key[PF_SK_WIRE] : sist->key[PF_SK_STACK]))) { if (more == NULL) return (sist); if (ret) (*more)++; else ret = si; } } } return (ret ? ret->si_st : NULL); } void pf_state_peer_hton(const struct pf_state_peer *s, struct pfsync_state_peer *d) { d->seqlo = htonl(s->seqlo); d->seqhi = htonl(s->seqhi); d->seqdiff = htonl(s->seqdiff); d->max_win = htons(s->max_win); d->mss = htons(s->mss); d->state = s->state; d->wscale = s->wscale; if (s->scrub) { d->scrub.pfss_flags = htons(s->scrub->pfss_flags & PFSS_TIMESTAMP); d->scrub.pfss_ttl = (s)->scrub->pfss_ttl; d->scrub.pfss_ts_mod = htonl((s)->scrub->pfss_ts_mod); d->scrub.scrub_flag = PFSYNC_SCRUB_FLAG_VALID; } } void pf_state_peer_ntoh(const struct pfsync_state_peer *s, struct pf_state_peer *d) { d->seqlo = ntohl(s->seqlo); d->seqhi = ntohl(s->seqhi); d->seqdiff = ntohl(s->seqdiff); d->max_win = ntohs(s->max_win); d->mss = ntohs(s->mss); d->state = s->state; d->wscale = s->wscale; if (s->scrub.scrub_flag == PFSYNC_SCRUB_FLAG_VALID && d->scrub != NULL) { d->scrub->pfss_flags = ntohs(s->scrub.pfss_flags) & PFSS_TIMESTAMP; d->scrub->pfss_ttl = s->scrub.pfss_ttl; d->scrub->pfss_ts_mod = ntohl(s->scrub.pfss_ts_mod); } } void pf_state_export(struct pfsync_state *sp, struct pf_state *st) { int32_t expire; memset(sp, 0, sizeof(struct pfsync_state)); /* copy from state key */ sp->key[PF_SK_WIRE].addr[0] = st->key[PF_SK_WIRE]->addr[0]; sp->key[PF_SK_WIRE].addr[1] = st->key[PF_SK_WIRE]->addr[1]; sp->key[PF_SK_WIRE].port[0] = st->key[PF_SK_WIRE]->port[0]; sp->key[PF_SK_WIRE].port[1] = st->key[PF_SK_WIRE]->port[1]; sp->key[PF_SK_WIRE].rdomain = htons(st->key[PF_SK_WIRE]->rdomain); sp->key[PF_SK_WIRE].af = st->key[PF_SK_WIRE]->af; sp->key[PF_SK_STACK].addr[0] = st->key[PF_SK_STACK]->addr[0]; sp->key[PF_SK_STACK].addr[1] = st->key[PF_SK_STACK]->addr[1]; sp->key[PF_SK_STACK].port[0] = st->key[PF_SK_STACK]->port[0]; sp->key[PF_SK_STACK].port[1] = st->key[PF_SK_STACK]->port[1]; sp->key[PF_SK_STACK].rdomain = htons(st->key[PF_SK_STACK]->rdomain); sp->key[PF_SK_STACK].af = st->key[PF_SK_STACK]->af; sp->rtableid[PF_SK_WIRE] = htonl(st->rtableid[PF_SK_WIRE]); sp->rtableid[PF_SK_STACK] = htonl(st->rtableid[PF_SK_STACK]); sp->proto = st->key[PF_SK_WIRE]->proto; sp->af = st->key[PF_SK_WIRE]->af; /* copy from state */ strlcpy(sp->ifname, st->kif->pfik_name, sizeof(sp->ifname)); sp->rt = st->rt; sp->rt_addr = st->rt_addr; sp->creation = htonl(getuptime() - st->creation); expire = pf_state_expires(st, st->timeout); if (expire <= getuptime()) sp->expire = htonl(0); else sp->expire = htonl(expire - getuptime()); sp->direction = st->direction; #if NPFLOG > 0 sp->log = st->log; #endif /* NPFLOG > 0 */ sp->timeout = st->timeout; sp->state_flags = htons(st->state_flags); if (READ_ONCE(st->sync_defer) != NULL) sp->state_flags |= htons(PFSTATE_ACK); if (!SLIST_EMPTY(&st->src_nodes)) sp->sync_flags |= PFSYNC_FLAG_SRCNODE; sp->id = st->id; sp->creatorid = st->creatorid; pf_state_peer_hton(&st->src, &sp->src); pf_state_peer_hton(&st->dst, &sp->dst); if (st->rule.ptr == NULL) sp->rule = htonl(-1); else sp->rule = htonl(st->rule.ptr->nr); if (st->anchor.ptr == NULL) sp->anchor = htonl(-1); else sp->anchor = htonl(st->anchor.ptr->nr); sp->nat_rule = htonl(-1); /* left for compat, nat_rule is gone */ pf_state_counter_hton(st->packets[0], sp->packets[0]); pf_state_counter_hton(st->packets[1], sp->packets[1]); pf_state_counter_hton(st->bytes[0], sp->bytes[0]); pf_state_counter_hton(st->bytes[1], sp->bytes[1]); sp->max_mss = htons(st->max_mss); sp->min_ttl = st->min_ttl; sp->set_tos = st->set_tos; sp->set_prio[0] = st->set_prio[0]; sp->set_prio[1] = st->set_prio[1]; } int pf_state_alloc_scrub_memory(const struct pfsync_state_peer *s, struct pf_state_peer *d) { if (s->scrub.scrub_flag && d->scrub == NULL) return (pf_normalize_tcp_alloc(d)); return (0); } #if NPFSYNC > 0 int pf_state_import(const struct pfsync_state *sp, int flags) { struct pf_state *st = NULL; struct pf_state_key *skw = NULL, *sks = NULL; struct pf_rule *r = NULL; struct pfi_kif *kif; int pool_flags; int error = ENOMEM; int n = 0; PF_ASSERT_LOCKED(); if (sp->creatorid == 0) { DPFPRINTF(LOG_NOTICE, "%s: invalid creator id: %08x", __func__, ntohl(sp->creatorid)); return (EINVAL); } if ((kif = pfi_kif_get(sp->ifname, NULL)) == NULL) { DPFPRINTF(LOG_NOTICE, "%s: unknown interface: %s", __func__, sp->ifname); if (flags & PFSYNC_SI_IOCTL) return (EINVAL); return (0); /* skip this state */ } if (sp->af == 0) return (0); /* skip this state */ /* * If the ruleset checksums match or the state is coming from the ioctl, * it's safe to associate the state with the rule of that number. */ if (sp->rule != htonl(-1) && sp->anchor == htonl(-1) && (flags & (PFSYNC_SI_IOCTL | PFSYNC_SI_CKSUM)) && ntohl(sp->rule) < pf_main_ruleset.rules.active.rcount) { TAILQ_FOREACH(r, pf_main_ruleset.rules.active.ptr, entries) if (ntohl(sp->rule) == n++) break; } else r = &pf_default_rule; if ((r->max_states && r->states_cur >= r->max_states)) goto cleanup; if (flags & PFSYNC_SI_IOCTL) pool_flags = PR_WAITOK | PR_LIMITFAIL | PR_ZERO; else pool_flags = PR_NOWAIT | PR_LIMITFAIL | PR_ZERO; if ((st = pool_get(&pf_state_pl, pool_flags)) == NULL) goto cleanup; if ((skw = pf_alloc_state_key(pool_flags)) == NULL) goto cleanup; if ((sp->key[PF_SK_WIRE].af && (sp->key[PF_SK_WIRE].af != sp->key[PF_SK_STACK].af)) || PF_ANEQ(&sp->key[PF_SK_WIRE].addr[0], &sp->key[PF_SK_STACK].addr[0], sp->af) || PF_ANEQ(&sp->key[PF_SK_WIRE].addr[1], &sp->key[PF_SK_STACK].addr[1], sp->af) || sp->key[PF_SK_WIRE].port[0] != sp->key[PF_SK_STACK].port[0] || sp->key[PF_SK_WIRE].port[1] != sp->key[PF_SK_STACK].port[1] || sp->key[PF_SK_WIRE].rdomain != sp->key[PF_SK_STACK].rdomain) { if ((sks = pf_alloc_state_key(pool_flags)) == NULL) goto cleanup; } else sks = pf_state_key_ref(skw); /* allocate memory for scrub info */ if (pf_state_alloc_scrub_memory(&sp->src, &st->src) || pf_state_alloc_scrub_memory(&sp->dst, &st->dst)) goto cleanup; /* copy to state key(s) */ skw->addr[0] = sp->key[PF_SK_WIRE].addr[0]; skw->addr[1] = sp->key[PF_SK_WIRE].addr[1]; skw->port[0] = sp->key[PF_SK_WIRE].port[0]; skw->port[1] = sp->key[PF_SK_WIRE].port[1]; skw->rdomain = ntohs(sp->key[PF_SK_WIRE].rdomain); skw->proto = sp->proto; if (!(skw->af = sp->key[PF_SK_WIRE].af)) skw->af = sp->af; skw->hash = pf_pkt_hash(skw->af, skw->proto, &skw->addr[0], &skw->addr[1], skw->port[0], skw->port[1]); if (sks != skw) { sks->addr[0] = sp->key[PF_SK_STACK].addr[0]; sks->addr[1] = sp->key[PF_SK_STACK].addr[1]; sks->port[0] = sp->key[PF_SK_STACK].port[0]; sks->port[1] = sp->key[PF_SK_STACK].port[1]; sks->rdomain = ntohs(sp->key[PF_SK_STACK].rdomain); if (!(sks->af = sp->key[PF_SK_STACK].af)) sks->af = sp->af; if (sks->af != skw->af) { switch (sp->proto) { case IPPROTO_ICMP: sks->proto = IPPROTO_ICMPV6; break; case IPPROTO_ICMPV6: sks->proto = IPPROTO_ICMP; break; default: sks->proto = sp->proto; } } else sks->proto = sp->proto; if (((sks->af != AF_INET) && (sks->af != AF_INET6)) || ((skw->af != AF_INET) && (skw->af != AF_INET6))) { error = EINVAL; goto cleanup; } sks->hash = pf_pkt_hash(sks->af, sks->proto, &sks->addr[0], &sks->addr[1], sks->port[0], sks->port[1]); } else if ((sks->af != AF_INET) && (sks->af != AF_INET6)) { error = EINVAL; goto cleanup; } st->rtableid[PF_SK_WIRE] = ntohl(sp->rtableid[PF_SK_WIRE]); st->rtableid[PF_SK_STACK] = ntohl(sp->rtableid[PF_SK_STACK]); /* copy to state */ st->rt_addr = sp->rt_addr; st->rt = sp->rt; st->creation = getuptime() - ntohl(sp->creation); st->expire = getuptime(); if (ntohl(sp->expire)) { u_int32_t timeout; timeout = r->timeout[sp->timeout]; if (!timeout) timeout = pf_default_rule.timeout[sp->timeout]; /* sp->expire may have been adaptively scaled by export. */ st->expire -= timeout - ntohl(sp->expire); } st->direction = sp->direction; st->log = sp->log; st->timeout = sp->timeout; st->state_flags = ntohs(sp->state_flags); st->max_mss = ntohs(sp->max_mss); st->min_ttl = sp->min_ttl; st->set_tos = sp->set_tos; st->set_prio[0] = sp->set_prio[0]; st->set_prio[1] = sp->set_prio[1]; st->id = sp->id; st->creatorid = sp->creatorid; pf_state_peer_ntoh(&sp->src, &st->src); pf_state_peer_ntoh(&sp->dst, &st->dst); st->rule.ptr = r; st->anchor.ptr = NULL; PF_REF_INIT(st->refcnt); mtx_init(&st->mtx, IPL_NET); /* XXX when we have anchors, use STATE_INC_COUNTERS */ r->states_cur++; r->states_tot++; st->sync_state = PFSYNC_S_NONE; st->pfsync_time = getuptime(); #if NPFSYNC > 0 pfsync_init_state(st, skw, sks, flags); #endif if (pf_state_insert(kif, &skw, &sks, st) != 0) { /* XXX when we have anchors, use STATE_DEC_COUNTERS */ r->states_cur--; error = EEXIST; goto cleanup_state; } return (0); cleanup: if (skw != NULL) pf_state_key_unref(skw); if (sks != NULL) pf_state_key_unref(sks); cleanup_state: /* pf_state_insert frees the state keys */ if (st) { if (st->dst.scrub) pool_put(&pf_state_scrub_pl, st->dst.scrub); if (st->src.scrub) pool_put(&pf_state_scrub_pl, st->src.scrub); pool_put(&pf_state_pl, st); } return (error); } #endif /* NPFSYNC > 0 */ /* END state table stuff */ void pf_purge_states(void *); struct task pf_purge_states_task = TASK_INITIALIZER(pf_purge_states, NULL); void pf_purge_states_tick(void *); struct timeout pf_purge_states_to = TIMEOUT_INITIALIZER(pf_purge_states_tick, NULL); unsigned int pf_purge_expired_states(unsigned int, unsigned int); /* * how many states to scan this interval. * * this is set when the timeout fires, and reduced by the task. the * task will reschedule itself until the limit is reduced to zero, * and then it adds the timeout again. */ unsigned int pf_purge_states_limit; /* * limit how many states are processed with locks held per run of * the state purge task. */ unsigned int pf_purge_states_collect = 64; void pf_purge_states_tick(void *null) { unsigned int limit = pf_status.states; unsigned int interval = pf_default_rule.timeout[PFTM_INTERVAL]; if (limit == 0) { timeout_add_sec(&pf_purge_states_to, 1); return; } /* * process a fraction of the state table every second */ if (interval > 1) limit /= interval; pf_purge_states_limit = limit; task_add(systqmp, &pf_purge_states_task); } void pf_purge_states(void *null) { unsigned int limit; unsigned int scanned; limit = pf_purge_states_limit; if (limit < pf_purge_states_collect) limit = pf_purge_states_collect; scanned = pf_purge_expired_states(limit, pf_purge_states_collect); if (scanned >= pf_purge_states_limit) { /* we've run out of states to scan this "interval" */ timeout_add_sec(&pf_purge_states_to, 1); return; } pf_purge_states_limit -= scanned; task_add(systqmp, &pf_purge_states_task); } void pf_purge_tick(void *); struct timeout pf_purge_to = TIMEOUT_INITIALIZER(pf_purge_tick, NULL); void pf_purge(void *); struct task pf_purge_task = TASK_INITIALIZER(pf_purge, NULL); void pf_purge_tick(void *null) { task_add(systqmp, &pf_purge_task); } void pf_purge(void *null) { unsigned int interval = max(1, pf_default_rule.timeout[PFTM_INTERVAL]); PF_LOCK(); pf_purge_expired_src_nodes(); PF_UNLOCK(); /* * Fragments don't require PF_LOCK(), they use their own lock. */ pf_purge_expired_fragments(); /* interpret the interval as idle time between runs */ timeout_add_sec(&pf_purge_to, interval); } int32_t pf_state_expires(const struct pf_state *st, uint8_t stimeout) { u_int32_t timeout; u_int32_t start; u_int32_t end; u_int32_t states; /* * pf_state_expires is used by the state purge task to * decide if a state is a candidate for cleanup, and by the * pfsync state export code to populate an expiry time. * * this function may be called by the state purge task while * the state is being modified. avoid inconsistent reads of * state->timeout by having the caller do the read (and any * checks it needs to do on the same variable) and then pass * their view of the timeout in here for this function to use. * the only consequence of using a stale timeout value is * that the state won't be a candidate for purging until the * next pass of the purge task. */ /* handle all PFTM_* >= PFTM_MAX here */ if (stimeout >= PFTM_MAX) return (0); KASSERT(stimeout < PFTM_MAX); timeout = st->rule.ptr->timeout[stimeout]; if (!timeout) timeout = pf_default_rule.timeout[stimeout]; start = st->rule.ptr->timeout[PFTM_ADAPTIVE_START]; if (start) { end = st->rule.ptr->timeout[PFTM_ADAPTIVE_END]; states = st->rule.ptr->states_cur; } else { start = pf_default_rule.timeout[PFTM_ADAPTIVE_START]; end = pf_default_rule.timeout[PFTM_ADAPTIVE_END]; states = pf_status.states; } if (end && states > start && start < end) { if (states >= end) return (0); timeout = (u_int64_t)timeout * (end - states) / (end - start); } return (st->expire + timeout); } void pf_purge_expired_src_nodes(void) { struct pf_src_node *cur, *next; PF_ASSERT_LOCKED(); RB_FOREACH_SAFE(cur, pf_src_tree, &tree_src_tracking, next) { if (cur->states == 0 && cur->expire <= getuptime()) { pf_remove_src_node(cur); } } } void pf_src_tree_remove_state(struct pf_state *st) { u_int32_t timeout; struct pf_sn_item *sni; while ((sni = SLIST_FIRST(&st->src_nodes)) != NULL) { SLIST_REMOVE_HEAD(&st->src_nodes, next); if (st->src.tcp_est) --sni->sn->conn; if (--sni->sn->states == 0) { timeout = st->rule.ptr->timeout[PFTM_SRC_NODE]; if (!timeout) timeout = pf_default_rule.timeout[PFTM_SRC_NODE]; sni->sn->expire = getuptime() + timeout; } pool_put(&pf_sn_item_pl, sni); } } void pf_remove_state(struct pf_state *st) { PF_ASSERT_LOCKED(); mtx_enter(&st->mtx); if (st->timeout == PFTM_UNLINKED) { mtx_leave(&st->mtx); return; } st->timeout = PFTM_UNLINKED; mtx_leave(&st->mtx); /* handle load balancing related tasks */ pf_postprocess_addr(st); if (st->src.state == PF_TCPS_PROXY_DST) { pf_send_tcp(st->rule.ptr, st->key[PF_SK_WIRE]->af, &st->key[PF_SK_WIRE]->addr[1], &st->key[PF_SK_WIRE]->addr[0], st->key[PF_SK_WIRE]->port[1], st->key[PF_SK_WIRE]->port[0], st->src.seqhi, st->src.seqlo + 1, TH_RST|TH_ACK, 0, 0, 0, 1, st->tag, st->key[PF_SK_WIRE]->rdomain); } if (st->key[PF_SK_STACK]->proto == IPPROTO_TCP) pf_set_protostate(st, PF_PEER_BOTH, TCPS_CLOSED); RBT_REMOVE(pf_state_tree_id, &tree_id, st); #if NPFLOW > 0 if (st->state_flags & PFSTATE_PFLOW) export_pflow(st); #endif /* NPFLOW > 0 */ #if NPFSYNC > 0 pfsync_delete_state(st); #endif /* NPFSYNC > 0 */ pf_src_tree_remove_state(st); pf_detach_state(st); } void pf_remove_divert_state(struct inpcb *inp) { struct pf_state_key *sk; struct pf_state_item *si; PF_ASSERT_UNLOCKED(); if (READ_ONCE(inp->inp_pf_sk) == NULL) return; mtx_enter(&pf_inp_mtx); sk = pf_state_key_ref(inp->inp_pf_sk); mtx_leave(&pf_inp_mtx); if (sk == NULL) return; PF_LOCK(); PF_STATE_ENTER_WRITE(); TAILQ_FOREACH(si, &sk->sk_states, si_entry) { struct pf_state *sist = si->si_st; if (sk == sist->key[PF_SK_STACK] && sist->rule.ptr && (sist->rule.ptr->divert.type == PF_DIVERT_TO || sist->rule.ptr->divert.type == PF_DIVERT_REPLY)) { if (sist->key[PF_SK_STACK]->proto == IPPROTO_TCP && sist->key[PF_SK_WIRE] != sist->key[PF_SK_STACK]) { /* * If the local address is translated, keep * the state for "tcp.closed" seconds to * prevent its source port from being reused. */ if (sist->src.state < TCPS_FIN_WAIT_2 || sist->dst.state < TCPS_FIN_WAIT_2) { pf_set_protostate(sist, PF_PEER_BOTH, TCPS_TIME_WAIT); pf_update_state_timeout(sist, PFTM_TCP_CLOSED); sist->expire = getuptime(); } sist->state_flags |= PFSTATE_INP_UNLINKED; } else pf_remove_state(sist); break; } } PF_STATE_EXIT_WRITE(); PF_UNLOCK(); pf_state_key_unref(sk); } void pf_free_state(struct pf_state *st) { struct pf_rule_item *ri; PF_ASSERT_LOCKED(); #if NPFSYNC > 0 if (pfsync_state_in_use(st)) return; #endif /* NPFSYNC > 0 */ KASSERT(st->timeout == PFTM_UNLINKED); if (--st->rule.ptr->states_cur == 0 && st->rule.ptr->src_nodes == 0) pf_rm_rule(NULL, st->rule.ptr); if (st->anchor.ptr != NULL) if (--st->anchor.ptr->states_cur == 0) pf_rm_rule(NULL, st->anchor.ptr); while ((ri = SLIST_FIRST(&st->match_rules))) { SLIST_REMOVE_HEAD(&st->match_rules, entry); if (--ri->r->states_cur == 0 && ri->r->src_nodes == 0) pf_rm_rule(NULL, ri->r); pool_put(&pf_rule_item_pl, ri); } pf_normalize_tcp_cleanup(st); pfi_kif_unref(st->kif, PFI_KIF_REF_STATE); pf_state_list_remove(&pf_state_list, st); if (st->tag) pf_tag_unref(st->tag); pf_state_unref(st); pf_status.fcounters[FCNT_STATE_REMOVALS]++; pf_status.states--; } unsigned int pf_purge_expired_states(const unsigned int limit, const unsigned int collect) { /* * this task/thread/context/whatever is the only thing that * removes states from the pf_state_list, so the cur reference * it holds between calls is guaranteed to still be in the * list. */ static struct pf_state *cur = NULL; struct pf_state *head, *tail; struct pf_state *st; SLIST_HEAD(pf_state_gcl, pf_state) gcl = SLIST_HEAD_INITIALIZER(gcl); time_t now; unsigned int scanned; unsigned int collected = 0; PF_ASSERT_UNLOCKED(); rw_enter_read(&pf_state_list.pfs_rwl); mtx_enter(&pf_state_list.pfs_mtx); head = TAILQ_FIRST(&pf_state_list.pfs_list); tail = TAILQ_LAST(&pf_state_list.pfs_list, pf_state_queue); mtx_leave(&pf_state_list.pfs_mtx); if (head == NULL) { /* the list is empty */ rw_exit_read(&pf_state_list.pfs_rwl); return (limit); } /* (re)start at the front of the list */ if (cur == NULL) cur = head; now = getuptime(); for (scanned = 0; scanned < limit; scanned++) { uint8_t stimeout = cur->timeout; unsigned int limited = 0; if ((stimeout == PFTM_UNLINKED) || (pf_state_expires(cur, stimeout) <= now)) { st = pf_state_ref(cur); SLIST_INSERT_HEAD(&gcl, st, gc_list); if (++collected >= collect) limited = 1; } /* don't iterate past the end of our view of the list */ if (cur == tail) { cur = NULL; break; } cur = TAILQ_NEXT(cur, entry_list); /* don't spend too much time here. */ if (ISSET(READ_ONCE(curcpu()->ci_schedstate.spc_schedflags), SPCF_SHOULDYIELD) || limited) break; } rw_exit_read(&pf_state_list.pfs_rwl); if (SLIST_EMPTY(&gcl)) return (scanned); rw_enter_write(&pf_state_list.pfs_rwl); PF_LOCK(); PF_STATE_ENTER_WRITE(); SLIST_FOREACH(st, &gcl, gc_list) { if (st->timeout != PFTM_UNLINKED) pf_remove_state(st); pf_free_state(st); } PF_STATE_EXIT_WRITE(); PF_UNLOCK(); rw_exit_write(&pf_state_list.pfs_rwl); while ((st = SLIST_FIRST(&gcl)) != NULL) { SLIST_REMOVE_HEAD(&gcl, gc_list); pf_state_unref(st); } return (scanned); } int pf_tbladdr_setup(struct pf_ruleset *rs, struct pf_addr_wrap *aw, int wait) { if (aw->type != PF_ADDR_TABLE) return (0); if ((aw->p.tbl = pfr_attach_table(rs, aw->v.tblname, wait)) == NULL) return (1); return (0); } void pf_tbladdr_remove(struct pf_addr_wrap *aw) { if (aw->type != PF_ADDR_TABLE || aw->p.tbl == NULL) return; pfr_detach_table(aw->p.tbl); aw->p.tbl = NULL; } void pf_tbladdr_copyout(struct pf_addr_wrap *aw) { struct pfr_ktable *kt = aw->p.tbl; if (aw->type != PF_ADDR_TABLE || kt == NULL) return; if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL) kt = kt->pfrkt_root; aw->p.tbl = NULL; aw->p.tblcnt = (kt->pfrkt_flags & PFR_TFLAG_ACTIVE) ? kt->pfrkt_cnt : -1; } void pf_print_host(struct pf_addr *addr, u_int16_t p, sa_family_t af) { switch (af) { case AF_INET: { u_int32_t a = ntohl(addr->addr32[0]); addlog("%u.%u.%u.%u", (a>>24)&255, (a>>16)&255, (a>>8)&255, a&255); if (p) { p = ntohs(p); addlog(":%u", p); } break; } #ifdef INET6 case AF_INET6: { u_int16_t b; u_int8_t i, curstart, curend, maxstart, maxend; curstart = curend = maxstart = maxend = 255; for (i = 0; i < 8; i++) { if (!addr->addr16[i]) { if (curstart == 255) curstart = i; curend = i; } else { if ((curend - curstart) > (maxend - maxstart)) { maxstart = curstart; maxend = curend; } curstart = curend = 255; } } if ((curend - curstart) > (maxend - maxstart)) { maxstart = curstart; maxend = curend; } for (i = 0; i < 8; i++) { if (i >= maxstart && i <= maxend) { if (i == 0) addlog(":"); if (i == maxend) addlog(":"); } else { b = ntohs(addr->addr16[i]); addlog("%x", b); if (i < 7) addlog(":"); } } if (p) { p = ntohs(p); addlog("[%u]", p); } break; } #endif /* INET6 */ } } void pf_print_state(struct pf_state *st) { pf_print_state_parts(st, NULL, NULL); } void pf_print_state_parts(struct pf_state *st, struct pf_state_key *skwp, struct pf_state_key *sksp) { struct pf_state_key *skw, *sks; u_int8_t proto, dir; /* Do our best to fill these, but they're skipped if NULL */ skw = skwp ? skwp : (st ? st->key[PF_SK_WIRE] : NULL); sks = sksp ? sksp : (st ? st->key[PF_SK_STACK] : NULL); proto = skw ? skw->proto : (sks ? sks->proto : 0); dir = st ? st->direction : 0; switch (proto) { case IPPROTO_IPV4: addlog("IPv4"); break; case IPPROTO_IPV6: addlog("IPv6"); break; case IPPROTO_TCP: addlog("TCP"); break; case IPPROTO_UDP: addlog("UDP"); break; case IPPROTO_ICMP: addlog("ICMP"); break; case IPPROTO_ICMPV6: addlog("ICMPv6"); break; default: addlog("%u", proto); break; } switch (dir) { case PF_IN: addlog(" in"); break; case PF_OUT: addlog(" out"); break; } if (skw) { addlog(" wire: (%d) ", skw->rdomain); pf_print_host(&skw->addr[0], skw->port[0], skw->af); addlog(" "); pf_print_host(&skw->addr[1], skw->port[1], skw->af); } if (sks) { addlog(" stack: (%d) ", sks->rdomain); if (sks != skw) { pf_print_host(&sks->addr[0], sks->port[0], sks->af); addlog(" "); pf_print_host(&sks->addr[1], sks->port[1], sks->af); } else addlog("-"); } if (st) { if (proto == IPPROTO_TCP) { addlog(" [lo=%u high=%u win=%u modulator=%u", st->src.seqlo, st->src.seqhi, st->src.max_win, st->src.seqdiff); if (st->src.wscale && st->dst.wscale) addlog(" wscale=%u", st->src.wscale & PF_WSCALE_MASK); addlog("]"); addlog(" [lo=%u high=%u win=%u modulator=%u", st->dst.seqlo, st->dst.seqhi, st->dst.max_win, st->dst.seqdiff); if (st->src.wscale && st->dst.wscale) addlog(" wscale=%u", st->dst.wscale & PF_WSCALE_MASK); addlog("]"); } addlog(" %u:%u", st->src.state, st->dst.state); if (st->rule.ptr) addlog(" @%d", st->rule.ptr->nr); } } void pf_print_flags(u_int8_t f) { if (f) addlog(" "); if (f & TH_FIN) addlog("F"); if (f & TH_SYN) addlog("S"); if (f & TH_RST) addlog("R"); if (f & TH_PUSH) addlog("P"); if (f & TH_ACK) addlog("A"); if (f & TH_URG) addlog("U"); if (f & TH_ECE) addlog("E"); if (f & TH_CWR) addlog("W"); } #define PF_SET_SKIP_STEPS(i) \ do { \ while (head[i] != cur) { \ head[i]->skip[i].ptr = cur; \ head[i] = TAILQ_NEXT(head[i], entries); \ } \ } while (0) void pf_calc_skip_steps(struct pf_rulequeue *rules) { struct pf_rule *cur, *prev, *head[PF_SKIP_COUNT]; int i; cur = TAILQ_FIRST(rules); prev = cur; for (i = 0; i < PF_SKIP_COUNT; ++i) head[i] = cur; while (cur != NULL) { if (cur->kif != prev->kif || cur->ifnot != prev->ifnot) PF_SET_SKIP_STEPS(PF_SKIP_IFP); if (cur->direction != prev->direction) PF_SET_SKIP_STEPS(PF_SKIP_DIR); if (cur->onrdomain != prev->onrdomain || cur->ifnot != prev->ifnot) PF_SET_SKIP_STEPS(PF_SKIP_RDOM); if (cur->af != prev->af) PF_SET_SKIP_STEPS(PF_SKIP_AF); if (cur->proto != prev->proto) PF_SET_SKIP_STEPS(PF_SKIP_PROTO); if (cur->src.neg != prev->src.neg || pf_addr_wrap_neq(&cur->src.addr, &prev->src.addr)) PF_SET_SKIP_STEPS(PF_SKIP_SRC_ADDR); if (cur->dst.neg != prev->dst.neg || pf_addr_wrap_neq(&cur->dst.addr, &prev->dst.addr)) PF_SET_SKIP_STEPS(PF_SKIP_DST_ADDR); if (cur->src.port[0] != prev->src.port[0] || cur->src.port[1] != prev->src.port[1] || cur->src.port_op != prev->src.port_op) PF_SET_SKIP_STEPS(PF_SKIP_SRC_PORT); if (cur->dst.port[0] != prev->dst.port[0] || cur->dst.port[1] != prev->dst.port[1] || cur->dst.port_op != prev->dst.port_op) PF_SET_SKIP_STEPS(PF_SKIP_DST_PORT); prev = cur; cur = TAILQ_NEXT(cur, entries); } for (i = 0; i < PF_SKIP_COUNT; ++i) PF_SET_SKIP_STEPS(i); } int pf_addr_wrap_neq(struct pf_addr_wrap *aw1, struct pf_addr_wrap *aw2) { if (aw1->type != aw2->type) return (1); switch (aw1->type) { case PF_ADDR_ADDRMASK: case PF_ADDR_RANGE: if (PF_ANEQ(&aw1->v.a.addr, &aw2->v.a.addr, AF_INET6)) return (1); if (PF_ANEQ(&aw1->v.a.mask, &aw2->v.a.mask, AF_INET6)) return (1); return (0); case PF_ADDR_DYNIFTL: return (aw1->p.dyn->pfid_kt != aw2->p.dyn->pfid_kt); case PF_ADDR_NONE: case PF_ADDR_NOROUTE: case PF_ADDR_URPFFAILED: return (0); case PF_ADDR_TABLE: return (aw1->p.tbl != aw2->p.tbl); case PF_ADDR_RTLABEL: return (aw1->v.rtlabel != aw2->v.rtlabel); default: addlog("invalid address type: %d\n", aw1->type); return (1); } } /* This algorithm computes 'a + b - c' in ones-complement using a trick to * emulate at most one ones-complement subtraction. This thereby limits net * carries/borrows to at most one, eliminating a reduction step and saving one * each of +, >>, & and ~. * * def. x mod y = x - (x//y)*y for integer x,y * def. sum = x mod 2^16 * def. accumulator = (x >> 16) mod 2^16 * * The trick works as follows: subtracting exactly one u_int16_t from the * u_int32_t x incurs at most one underflow, wrapping its upper 16-bits, the * accumulator, to 2^16 - 1. Adding this to the 16-bit sum preserves the * ones-complement borrow: * * (sum + accumulator) mod 2^16 * = { assume underflow: accumulator := 2^16 - 1 } * (sum + 2^16 - 1) mod 2^16 * = { mod } * (sum - 1) mod 2^16 * * Although this breaks for sum = 0, giving 0xffff, which is ones-complement's * other zero, not -1, that cannot occur: the 16-bit sum cannot be underflown * to zero as that requires subtraction of at least 2^16, which exceeds a * single u_int16_t's range. * * We use the following theorem to derive the implementation: * * th. (x + (y mod z)) mod z = (x + y) mod z (0) * proof. * (x + (y mod z)) mod z * = { def mod } * (x + y - (y//z)*z) mod z * = { (a + b*c) mod c = a mod c } * (x + y) mod z [end of proof] * * ... and thereby obtain: * * (sum + accumulator) mod 2^16 * = { def. accumulator, def. sum } * (x mod 2^16 + (x >> 16) mod 2^16) mod 2^16 * = { (0), twice } * (x + (x >> 16)) mod 2^16 * = { x mod 2^n = x & (2^n - 1) } * (x + (x >> 16)) & 0xffff * * Note: this serves also as a reduction step for at most one add (as the * trailing mod 2^16 prevents further reductions by destroying carries). */ __inline void pf_cksum_fixup(u_int16_t *cksum, u_int16_t was, u_int16_t now, u_int8_t proto) { u_int32_t x; const int udp = proto == IPPROTO_UDP; x = *cksum + was - now; x = (x + (x >> 16)) & 0xffff; /* optimise: eliminate a branch when not udp */ if (udp && *cksum == 0x0000) return; if (udp && x == 0x0000) x = 0xffff; *cksum = (u_int16_t)(x); } #ifdef INET6 /* pre: coverage(cksum) is superset of coverage(covered_cksum) */ static __inline void pf_cksum_uncover(u_int16_t *cksum, u_int16_t covered_cksum, u_int8_t proto) { pf_cksum_fixup(cksum, ~covered_cksum, 0x0, proto); } /* pre: disjoint(coverage(cksum), coverage(uncovered_cksum)) */ static __inline void pf_cksum_cover(u_int16_t *cksum, u_int16_t uncovered_cksum, u_int8_t proto) { pf_cksum_fixup(cksum, 0x0, ~uncovered_cksum, proto); } #endif /* INET6 */ /* pre: *a is 16-bit aligned within its packet * * This algorithm emulates 16-bit ones-complement sums on a twos-complement * machine by conserving ones-complement's otherwise discarded carries in the * upper bits of x. These accumulated carries when added to the lower 16-bits * over at least zero 'reduction' steps then complete the ones-complement sum. * * def. sum = x mod 2^16 * def. accumulator = (x >> 16) * * At most two reduction steps * * x := sum + accumulator * = { def sum, def accumulator } * x := x mod 2^16 + (x >> 16) * = { x mod 2^n = x & (2^n - 1) } * x := (x & 0xffff) + (x >> 16) * * are necessary to incorporate the accumulated carries (at most one per add) * i.e. to reduce x < 2^16 from at most 16 carries in the upper 16 bits. * * The function is also invariant over the endian of the host. Why? * * Define the unary transpose operator ~ on a bitstring in python slice * notation as lambda m: m[P:] + m[:P] , for some constant pivot P. * * th. ~ distributes over ones-complement addition, denoted by +_1, i.e. * * ~m +_1 ~n = ~(m +_1 n) (for all bitstrings m,n of equal length) * * proof. Regard the bitstrings in m +_1 n as split at P, forming at most two * 'half-adds'. Under ones-complement addition, each half-add carries to the * other, so the sum of each half-add is unaffected by their relative * order. Therefore: * * ~m +_1 ~n * = { half-adds invariant under transposition } * ~s * = { substitute } * ~(m +_1 n) [end of proof] * * th. Summing two in-memory ones-complement 16-bit variables m,n on a machine * with the converse endian does not alter the result. * * proof. * { converse machine endian: load/store transposes, P := 8 } * ~(~m +_1 ~n) * = { ~ over +_1 } * ~~m +_1 ~~n * = { ~ is an involution } * m +_1 n [end of proof] * */ #define NEG(x) ((u_int16_t)~(x)) void pf_cksum_fixup_a(u_int16_t *cksum, const struct pf_addr *a, const struct pf_addr *an, sa_family_t af, u_int8_t proto) { u_int32_t x; const u_int16_t *n = an->addr16; const u_int16_t *o = a->addr16; const int udp = proto == IPPROTO_UDP; switch (af) { case AF_INET: x = *cksum + o[0] + NEG(n[0]) + o[1] + NEG(n[1]); break; #ifdef INET6 case AF_INET6: x = *cksum + o[0] + NEG(n[0]) + o[1] + NEG(n[1]) +\ o[2] + NEG(n[2]) + o[3] + NEG(n[3]) +\ o[4] + NEG(n[4]) + o[5] + NEG(n[5]) +\ o[6] + NEG(n[6]) + o[7] + NEG(n[7]); break; #endif /* INET6 */ default: unhandled_af(af); } x = (x & 0xffff) + (x >> 16); x = (x & 0xffff) + (x >> 16); /* optimise: eliminate a branch when not udp */ if (udp && *cksum == 0x0000) return; if (udp && x == 0x0000) x = 0xffff; *cksum = (u_int16_t)(x); } int pf_patch_8(struct pf_pdesc *pd, u_int8_t *f, u_int8_t v, bool hi) { int rewrite = 0; if (*f != v) { u_int16_t old = htons(hi ? (*f << 8) : *f); u_int16_t new = htons(hi ? ( v << 8) : v); pf_cksum_fixup(pd->pcksum, old, new, pd->proto); *f = v; rewrite = 1; } return (rewrite); } /* pre: *f is 16-bit aligned within its packet */ int pf_patch_16(struct pf_pdesc *pd, u_int16_t *f, u_int16_t v) { int rewrite = 0; if (*f != v) { pf_cksum_fixup(pd->pcksum, *f, v, pd->proto); *f = v; rewrite = 1; } return (rewrite); } int pf_patch_16_unaligned(struct pf_pdesc *pd, void *f, u_int16_t v, bool hi) { int rewrite = 0; u_int8_t *fb = (u_int8_t*)f; u_int8_t *vb = (u_int8_t*)&v; if (hi && ALIGNED_POINTER(f, u_int16_t)) { return (pf_patch_16(pd, f, v)); /* optimise */ } rewrite += pf_patch_8(pd, fb++, *vb++, hi); rewrite += pf_patch_8(pd, fb++, *vb++,!hi); return (rewrite); } /* pre: *f is 16-bit aligned within its packet */ /* pre: pd->proto != IPPROTO_UDP */ int pf_patch_32(struct pf_pdesc *pd, u_int32_t *f, u_int32_t v) { int rewrite = 0; u_int16_t *pc = pd->pcksum; u_int8_t proto = pd->proto; /* optimise: inline udp fixup code is unused; let compiler scrub it */ if (proto == IPPROTO_UDP) panic("%s: udp", __func__); /* optimise: skip *f != v guard; true for all use-cases */ pf_cksum_fixup(pc, *f / (1 << 16), v / (1 << 16), proto); pf_cksum_fixup(pc, *f % (1 << 16), v % (1 << 16), proto); *f = v; rewrite = 1; return (rewrite); } int pf_patch_32_unaligned(struct pf_pdesc *pd, void *f, u_int32_t v, bool hi) { int rewrite = 0; u_int8_t *fb = (u_int8_t*)f; u_int8_t *vb = (u_int8_t*)&v; if (hi && ALIGNED_POINTER(f, u_int32_t)) { return (pf_patch_32(pd, f, v)); /* optimise */ } rewrite += pf_patch_8(pd, fb++, *vb++, hi); rewrite += pf_patch_8(pd, fb++, *vb++,!hi); rewrite += pf_patch_8(pd, fb++, *vb++, hi); rewrite += pf_patch_8(pd, fb++, *vb++,!hi); return (rewrite); } int pf_icmp_mapping(struct pf_pdesc *pd, u_int8_t type, int *icmp_dir, u_int16_t *virtual_id, u_int16_t *virtual_type) { /* * ICMP types marked with PF_OUT are typically responses to * PF_IN, and will match states in the opposite direction. * PF_IN ICMP types need to match a state with that type. */ *icmp_dir = PF_OUT; /* Queries (and responses) */ switch (pd->af) { case AF_INET: switch (type) { case ICMP_ECHO: *icmp_dir = PF_IN; /* FALLTHROUGH */ case ICMP_ECHOREPLY: *virtual_type = ICMP_ECHO; *virtual_id = pd->hdr.icmp.icmp_id; break; case ICMP_TSTAMP: *icmp_dir = PF_IN; /* FALLTHROUGH */ case ICMP_TSTAMPREPLY: *virtual_type = ICMP_TSTAMP; *virtual_id = pd->hdr.icmp.icmp_id; break; case ICMP_IREQ: *icmp_dir = PF_IN; /* FALLTHROUGH */ case ICMP_IREQREPLY: *virtual_type = ICMP_IREQ; *virtual_id = pd->hdr.icmp.icmp_id; break; case ICMP_MASKREQ: *icmp_dir = PF_IN; /* FALLTHROUGH */ case ICMP_MASKREPLY: *virtual_type = ICMP_MASKREQ; *virtual_id = pd->hdr.icmp.icmp_id; break; case ICMP_IPV6_WHEREAREYOU: *icmp_dir = PF_IN; /* FALLTHROUGH */ case ICMP_IPV6_IAMHERE: *virtual_type = ICMP_IPV6_WHEREAREYOU; *virtual_id = 0; /* Nothing sane to match on! */ break; case ICMP_MOBILE_REGREQUEST: *icmp_dir = PF_IN; /* FALLTHROUGH */ case ICMP_MOBILE_REGREPLY: *virtual_type = ICMP_MOBILE_REGREQUEST; *virtual_id = 0; /* Nothing sane to match on! */ break; case ICMP_ROUTERSOLICIT: *icmp_dir = PF_IN; /* FALLTHROUGH */ case ICMP_ROUTERADVERT: *virtual_type = ICMP_ROUTERSOLICIT; *virtual_id = 0; /* Nothing sane to match on! */ break; /* These ICMP types map to other connections */ case ICMP_UNREACH: case ICMP_SOURCEQUENCH: case ICMP_REDIRECT: case ICMP_TIMXCEED: case ICMP_PARAMPROB: /* These will not be used, but set them anyway */ *icmp_dir = PF_IN; *virtual_type = htons(type); *virtual_id = 0; return (1); /* These types match to another state */ /* * All remaining ICMP types get their own states, * and will only match in one direction. */ default: *icmp_dir = PF_IN; *virtual_type = type; *virtual_id = 0; break; } break; #ifdef INET6 case AF_INET6: switch (type) { case ICMP6_ECHO_REQUEST: *icmp_dir = PF_IN; /* FALLTHROUGH */ case ICMP6_ECHO_REPLY: *virtual_type = ICMP6_ECHO_REQUEST; *virtual_id = pd->hdr.icmp6.icmp6_id; break; case MLD_LISTENER_QUERY: case MLD_LISTENER_REPORT: { struct mld_hdr *mld = &pd->hdr.mld; u_int32_t h; /* * Listener Report can be sent by clients * without an associated Listener Query. * In addition to that, when Report is sent as a * reply to a Query its source and destination * address are different. */ *icmp_dir = PF_IN; *virtual_type = MLD_LISTENER_QUERY; /* generate fake id for these messages */ h = mld->mld_addr.s6_addr32[0] ^ mld->mld_addr.s6_addr32[1] ^ mld->mld_addr.s6_addr32[2] ^ mld->mld_addr.s6_addr32[3]; *virtual_id = (h >> 16) ^ (h & 0xffff); break; } /* * ICMP6_FQDN and ICMP6_NI query/reply are the same type as * ICMP6_WRU */ case ICMP6_WRUREQUEST: *icmp_dir = PF_IN; /* FALLTHROUGH */ case ICMP6_WRUREPLY: *virtual_type = ICMP6_WRUREQUEST; *virtual_id = 0; /* Nothing sane to match on! */ break; case MLD_MTRACE: *icmp_dir = PF_IN; /* FALLTHROUGH */ case MLD_MTRACE_RESP: *virtual_type = MLD_MTRACE; *virtual_id = 0; /* Nothing sane to match on! */ break; case ND_NEIGHBOR_SOLICIT: *icmp_dir = PF_IN; /* FALLTHROUGH */ case ND_NEIGHBOR_ADVERT: { struct nd_neighbor_solicit *nd = &pd->hdr.nd_ns; u_int32_t h; *virtual_type = ND_NEIGHBOR_SOLICIT; /* generate fake id for these messages */ h = nd->nd_ns_target.s6_addr32[0] ^ nd->nd_ns_target.s6_addr32[1] ^ nd->nd_ns_target.s6_addr32[2] ^ nd->nd_ns_target.s6_addr32[3]; *virtual_id = (h >> 16) ^ (h & 0xffff); /* * the extra work here deals with 'keep state' option * at pass rule for unsolicited advertisement. By * returning 1 (state_icmp = 1) we override 'keep * state' to 'no state' so we don't create state for * unsolicited advertisements. No one expects answer to * unsolicited advertisements so we should be good. */ if (type == ND_NEIGHBOR_ADVERT) { *virtual_type = htons(*virtual_type); return (1); } break; } /* * These ICMP types map to other connections. * ND_REDIRECT can't be in this list because the triggering * packet header is optional. */ case ICMP6_DST_UNREACH: case ICMP6_PACKET_TOO_BIG: case ICMP6_TIME_EXCEEDED: case ICMP6_PARAM_PROB: /* These will not be used, but set them anyway */ *icmp_dir = PF_IN; *virtual_type = htons(type); *virtual_id = 0; return (1); /* These types match to another state */ /* * All remaining ICMP6 types get their own states, * and will only match in one direction. */ default: *icmp_dir = PF_IN; *virtual_type = type; *virtual_id = 0; break; } break; #endif /* INET6 */ } *virtual_type = htons(*virtual_type); return (0); /* These types match to their own state */ } void pf_translate_icmp(struct pf_pdesc *pd, struct pf_addr *qa, u_int16_t *qp, struct pf_addr *oa, struct pf_addr *na, u_int16_t np) { /* note: doesn't trouble to fixup quoted checksums, if any */ /* change quoted protocol port */ if (qp != NULL) pf_patch_16(pd, qp, np); /* change quoted ip address */ pf_cksum_fixup_a(pd->pcksum, qa, na, pd->af, pd->proto); pf_addrcpy(qa, na, pd->af); /* change network-header's ip address */ if (oa) pf_translate_a(pd, oa, na); } /* pre: *a is 16-bit aligned within its packet */ /* *a is a network header src/dst address */ int pf_translate_a(struct pf_pdesc *pd, struct pf_addr *a, struct pf_addr *an) { int rewrite = 0; /* warning: !PF_ANEQ != PF_AEQ */ if (!PF_ANEQ(a, an, pd->af)) return (0); /* fixup transport pseudo-header, if any */ switch (pd->proto) { case IPPROTO_TCP: /* FALLTHROUGH */ case IPPROTO_UDP: /* FALLTHROUGH */ case IPPROTO_ICMPV6: pf_cksum_fixup_a(pd->pcksum, a, an, pd->af, pd->proto); break; default: break; /* assume no pseudo-header */ } pf_addrcpy(a, an, pd->af); rewrite = 1; return (rewrite); } #ifdef INET6 /* pf_translate_af() may change pd->m, adjust local copies after calling */ int pf_translate_af(struct pf_pdesc *pd) { static const struct pf_addr zero; struct ip *ip4; struct ip6_hdr *ip6; int copyback = 0; u_int hlen, ohlen, dlen; u_int16_t *pc; u_int8_t af_proto, naf_proto; hlen = (pd->naf == AF_INET) ? sizeof(*ip4) : sizeof(*ip6); ohlen = pd->off; dlen = pd->tot_len - pd->off; pc = pd->pcksum; af_proto = naf_proto = pd->proto; if (naf_proto == IPPROTO_ICMP) af_proto = IPPROTO_ICMPV6; if (naf_proto == IPPROTO_ICMPV6) af_proto = IPPROTO_ICMP; /* uncover stale pseudo-header */ switch (af_proto) { case IPPROTO_ICMPV6: /* optimise: unchanged for TCP/UDP */ pf_cksum_fixup(pc, htons(af_proto), 0x0, af_proto); pf_cksum_fixup(pc, htons(dlen), 0x0, af_proto); /* FALLTHROUGH */ case IPPROTO_UDP: /* FALLTHROUGH */ case IPPROTO_TCP: pf_cksum_fixup_a(pc, pd->src, &zero, pd->af, af_proto); pf_cksum_fixup_a(pc, pd->dst, &zero, pd->af, af_proto); copyback = 1; break; default: break; /* assume no pseudo-header */ } /* replace the network header */ m_adj(pd->m, pd->off); pd->src = NULL; pd->dst = NULL; if ((M_PREPEND(pd->m, hlen, M_DONTWAIT)) == NULL) { pd->m = NULL; return (-1); } pd->off = hlen; pd->tot_len += hlen - ohlen; switch (pd->naf) { case AF_INET: ip4 = mtod(pd->m, struct ip *); memset(ip4, 0, hlen); ip4->ip_v = IPVERSION; ip4->ip_hl = hlen >> 2; ip4->ip_tos = pd->tos; ip4->ip_len = htons(hlen + dlen); ip4->ip_id = htons(ip_randomid()); ip4->ip_off = htons(IP_DF); ip4->ip_ttl = pd->ttl; ip4->ip_p = pd->proto; ip4->ip_src = pd->nsaddr.v4; ip4->ip_dst = pd->ndaddr.v4; break; case AF_INET6: ip6 = mtod(pd->m, struct ip6_hdr *); memset(ip6, 0, hlen); ip6->ip6_vfc = IPV6_VERSION; ip6->ip6_flow |= htonl((u_int32_t)pd->tos << 20); ip6->ip6_plen = htons(dlen); ip6->ip6_nxt = pd->proto; if (!pd->ttl || pd->ttl > IPV6_DEFHLIM) ip6->ip6_hlim = IPV6_DEFHLIM; else ip6->ip6_hlim = pd->ttl; ip6->ip6_src = pd->nsaddr.v6; ip6->ip6_dst = pd->ndaddr.v6; break; default: unhandled_af(pd->naf); } /* UDP over IPv6 must be checksummed per rfc2460 p27 */ if (naf_proto == IPPROTO_UDP && *pc == 0x0000 && pd->naf == AF_INET6) { pd->m->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT; } /* cover fresh pseudo-header */ switch (naf_proto) { case IPPROTO_ICMPV6: /* optimise: unchanged for TCP/UDP */ pf_cksum_fixup(pc, 0x0, htons(naf_proto), naf_proto); pf_cksum_fixup(pc, 0x0, htons(dlen), naf_proto); /* FALLTHROUGH */ case IPPROTO_UDP: /* FALLTHROUGH */ case IPPROTO_TCP: pf_cksum_fixup_a(pc, &zero, &pd->nsaddr, pd->naf, naf_proto); pf_cksum_fixup_a(pc, &zero, &pd->ndaddr, pd->naf, naf_proto); copyback = 1; break; default: break; /* assume no pseudo-header */ } /* flush pd->pcksum */ if (copyback) m_copyback(pd->m, pd->off, pd->hdrlen, &pd->hdr, M_NOWAIT); return (0); } int pf_change_icmp_af(struct mbuf *m, int ipoff2, struct pf_pdesc *pd, struct pf_pdesc *pd2, struct pf_addr *src, struct pf_addr *dst, sa_family_t af, sa_family_t naf) { struct mbuf *n = NULL; struct ip *ip4; struct ip6_hdr *ip6; u_int hlen, ohlen, dlen; int d; if (af == naf || (af != AF_INET && af != AF_INET6) || (naf != AF_INET && naf != AF_INET6)) return (-1); /* split the mbuf chain on the quoted ip/ip6 header boundary */ if ((n = m_split(m, ipoff2, M_DONTWAIT)) == NULL) return (-1); /* new quoted header */ hlen = naf == AF_INET ? sizeof(*ip4) : sizeof(*ip6); /* old quoted header */ ohlen = pd2->off - ipoff2; /* trim old quoted header */ pf_cksum_uncover(pd->pcksum, in_cksum(n, ohlen), pd->proto); m_adj(n, ohlen); /* prepend a new, translated, quoted header */ if ((M_PREPEND(n, hlen, M_DONTWAIT)) == NULL) return (-1); switch (naf) { case AF_INET: ip4 = mtod(n, struct ip *); memset(ip4, 0, sizeof(*ip4)); ip4->ip_v = IPVERSION; ip4->ip_hl = sizeof(*ip4) >> 2; ip4->ip_len = htons(sizeof(*ip4) + pd2->tot_len - ohlen); ip4->ip_id = htons(ip_randomid()); ip4->ip_off = htons(IP_DF); ip4->ip_ttl = pd2->ttl; if (pd2->proto == IPPROTO_ICMPV6) ip4->ip_p = IPPROTO_ICMP; else ip4->ip_p = pd2->proto; ip4->ip_src = src->v4; ip4->ip_dst = dst->v4; in_hdr_cksum_out(n, NULL); break; case AF_INET6: ip6 = mtod(n, struct ip6_hdr *); memset(ip6, 0, sizeof(*ip6)); ip6->ip6_vfc = IPV6_VERSION; ip6->ip6_plen = htons(pd2->tot_len - ohlen); if (pd2->proto == IPPROTO_ICMP) ip6->ip6_nxt = IPPROTO_ICMPV6; else ip6->ip6_nxt = pd2->proto; if (!pd2->ttl || pd2->ttl > IPV6_DEFHLIM) ip6->ip6_hlim = IPV6_DEFHLIM; else ip6->ip6_hlim = pd2->ttl; ip6->ip6_src = src->v6; ip6->ip6_dst = dst->v6; break; } /* cover new quoted header */ /* optimise: any new AF_INET header of ours sums to zero */ if (naf != AF_INET) { pf_cksum_cover(pd->pcksum, in_cksum(n, hlen), pd->proto); } /* reattach modified quoted packet to outer header */ { int nlen = n->m_pkthdr.len; m_cat(m, n); m->m_pkthdr.len += nlen; } /* account for altered length */ d = hlen - ohlen; if (pd->proto == IPPROTO_ICMPV6) { /* fixup pseudo-header */ dlen = pd->tot_len - pd->off; pf_cksum_fixup(pd->pcksum, htons(dlen), htons(dlen + d), pd->proto); } pd->tot_len += d; pd2->tot_len += d; pd2->off += d; /* note: not bothering to update network headers as these due for rewrite by pf_translate_af() */ return (0); } #define PTR_IP(field) (offsetof(struct ip, field)) #define PTR_IP6(field) (offsetof(struct ip6_hdr, field)) int pf_translate_icmp_af(struct pf_pdesc *pd, int af, void *arg) { struct icmp *icmp4; struct icmp6_hdr *icmp6; u_int32_t mtu; int32_t ptr = -1; u_int8_t type; u_int8_t code; switch (af) { case AF_INET: icmp6 = arg; type = icmp6->icmp6_type; code = icmp6->icmp6_code; mtu = ntohl(icmp6->icmp6_mtu); switch (type) { case ICMP6_ECHO_REQUEST: type = ICMP_ECHO; break; case ICMP6_ECHO_REPLY: type = ICMP_ECHOREPLY; break; case ICMP6_DST_UNREACH: type = ICMP_UNREACH; switch (code) { case ICMP6_DST_UNREACH_NOROUTE: case ICMP6_DST_UNREACH_BEYONDSCOPE: case ICMP6_DST_UNREACH_ADDR: code = ICMP_UNREACH_HOST; break; case ICMP6_DST_UNREACH_ADMIN: code = ICMP_UNREACH_HOST_PROHIB; break; case ICMP6_DST_UNREACH_NOPORT: code = ICMP_UNREACH_PORT; break; default: return (-1); } break; case ICMP6_PACKET_TOO_BIG: type = ICMP_UNREACH; code = ICMP_UNREACH_NEEDFRAG; mtu -= 20; break; case ICMP6_TIME_EXCEEDED: type = ICMP_TIMXCEED; break; case ICMP6_PARAM_PROB: switch (code) { case ICMP6_PARAMPROB_HEADER: type = ICMP_PARAMPROB; code = ICMP_PARAMPROB_ERRATPTR; ptr = ntohl(icmp6->icmp6_pptr); if (ptr == PTR_IP6(ip6_vfc)) ; /* preserve */ else if (ptr == PTR_IP6(ip6_vfc) + 1) ptr = PTR_IP(ip_tos); else if (ptr == PTR_IP6(ip6_plen) || ptr == PTR_IP6(ip6_plen) + 1) ptr = PTR_IP(ip_len); else if (ptr == PTR_IP6(ip6_nxt)) ptr = PTR_IP(ip_p); else if (ptr == PTR_IP6(ip6_hlim)) ptr = PTR_IP(ip_ttl); else if (ptr >= PTR_IP6(ip6_src) && ptr < PTR_IP6(ip6_dst)) ptr = PTR_IP(ip_src); else if (ptr >= PTR_IP6(ip6_dst) && ptr < sizeof(struct ip6_hdr)) ptr = PTR_IP(ip_dst); else { return (-1); } break; case ICMP6_PARAMPROB_NEXTHEADER: type = ICMP_UNREACH; code = ICMP_UNREACH_PROTOCOL; break; default: return (-1); } break; default: return (-1); } pf_patch_8(pd, &icmp6->icmp6_type, type, PF_HI); pf_patch_8(pd, &icmp6->icmp6_code, code, PF_LO); /* aligns well with a icmpv4 nextmtu */ pf_patch_32(pd, &icmp6->icmp6_mtu, htonl(mtu)); /* icmpv4 pptr is a one most significant byte */ if (ptr >= 0) pf_patch_32(pd, &icmp6->icmp6_pptr, htonl(ptr << 24)); break; case AF_INET6: icmp4 = arg; type = icmp4->icmp_type; code = icmp4->icmp_code; mtu = ntohs(icmp4->icmp_nextmtu); switch (type) { case ICMP_ECHO: type = ICMP6_ECHO_REQUEST; break; case ICMP_ECHOREPLY: type = ICMP6_ECHO_REPLY; break; case ICMP_UNREACH: type = ICMP6_DST_UNREACH; switch (code) { case ICMP_UNREACH_NET: case ICMP_UNREACH_HOST: case ICMP_UNREACH_NET_UNKNOWN: case ICMP_UNREACH_HOST_UNKNOWN: case ICMP_UNREACH_ISOLATED: case ICMP_UNREACH_TOSNET: case ICMP_UNREACH_TOSHOST: code = ICMP6_DST_UNREACH_NOROUTE; break; case ICMP_UNREACH_PORT: code = ICMP6_DST_UNREACH_NOPORT; break; case ICMP_UNREACH_NET_PROHIB: case ICMP_UNREACH_HOST_PROHIB: case ICMP_UNREACH_FILTER_PROHIB: case ICMP_UNREACH_PRECEDENCE_CUTOFF: code = ICMP6_DST_UNREACH_ADMIN; break; case ICMP_UNREACH_PROTOCOL: type = ICMP6_PARAM_PROB; code = ICMP6_PARAMPROB_NEXTHEADER; ptr = offsetof(struct ip6_hdr, ip6_nxt); break; case ICMP_UNREACH_NEEDFRAG: type = ICMP6_PACKET_TOO_BIG; code = 0; mtu += 20; break; default: return (-1); } break; case ICMP_TIMXCEED: type = ICMP6_TIME_EXCEEDED; break; case ICMP_PARAMPROB: type = ICMP6_PARAM_PROB; switch (code) { case ICMP_PARAMPROB_ERRATPTR: code = ICMP6_PARAMPROB_HEADER; break; case ICMP_PARAMPROB_LENGTH: code = ICMP6_PARAMPROB_HEADER; break; default: return (-1); } ptr = icmp4->icmp_pptr; if (ptr == 0 || ptr == PTR_IP(ip_tos)) ; /* preserve */ else if (ptr == PTR_IP(ip_len) || ptr == PTR_IP(ip_len) + 1) ptr = PTR_IP6(ip6_plen); else if (ptr == PTR_IP(ip_ttl)) ptr = PTR_IP6(ip6_hlim); else if (ptr == PTR_IP(ip_p)) ptr = PTR_IP6(ip6_nxt); else if (ptr >= PTR_IP(ip_src) && ptr < PTR_IP(ip_dst)) ptr = PTR_IP6(ip6_src); else if (ptr >= PTR_IP(ip_dst) && ptr < sizeof(struct ip)) ptr = PTR_IP6(ip6_dst); else { return (-1); } break; default: return (-1); } pf_patch_8(pd, &icmp4->icmp_type, type, PF_HI); pf_patch_8(pd, &icmp4->icmp_code, code, PF_LO); pf_patch_16(pd, &icmp4->icmp_nextmtu, htons(mtu)); if (ptr >= 0) pf_patch_32(pd, &icmp4->icmp_void, htonl(ptr)); break; } return (0); } #endif /* INET6 */ /* * Need to modulate the sequence numbers in the TCP SACK option * (credits to Krzysztof Pfaff for report and patch) */ int pf_modulate_sack(struct pf_pdesc *pd, struct pf_state_peer *dst) { struct sackblk sack; int copyback = 0, i; int olen, optsoff; u_int8_t opts[MAX_TCPOPTLEN], *opt, *eoh; olen = (pd->hdr.tcp.th_off << 2) - sizeof(struct tcphdr); optsoff = pd->off + sizeof(struct tcphdr); #define TCPOLEN_MINSACK (TCPOLEN_SACK + 2) if (olen < TCPOLEN_MINSACK || !pf_pull_hdr(pd->m, optsoff, opts, olen, NULL, pd->af)) return (0); eoh = opts + olen; opt = opts; while ((opt = pf_find_tcpopt(opt, opts, olen, TCPOPT_SACK, TCPOLEN_MINSACK)) != NULL) { size_t safelen = MIN(opt[1], (eoh - opt)); for (i = 2; i + TCPOLEN_SACK <= safelen; i += TCPOLEN_SACK) { size_t startoff = (opt + i) - opts; memcpy(&sack, &opt[i], sizeof(sack)); pf_patch_32_unaligned(pd, &sack.start, htonl(ntohl(sack.start) - dst->seqdiff), PF_ALGNMNT(startoff)); pf_patch_32_unaligned(pd, &sack.end, htonl(ntohl(sack.end) - dst->seqdiff), PF_ALGNMNT(startoff + sizeof(sack.start))); memcpy(&opt[i], &sack, sizeof(sack)); } copyback = 1; opt += opt[1]; } if (copyback) m_copyback(pd->m, optsoff, olen, opts, M_NOWAIT); return (copyback); } struct mbuf * pf_build_tcp(const struct pf_rule *r, sa_family_t af, const struct pf_addr *saddr, const struct pf_addr *daddr, u_int16_t sport, u_int16_t dport, u_int32_t seq, u_int32_t ack, u_int8_t flags, u_int16_t win, u_int16_t mss, u_int8_t ttl, int tag, u_int16_t rtag, u_int sack, u_int rdom) { struct mbuf *m; int len, tlen; struct ip *h; #ifdef INET6 struct ip6_hdr *h6; #endif /* INET6 */ struct tcphdr *th; char *opt; /* maximum segment size tcp option */ tlen = sizeof(struct tcphdr); if (mss) tlen += 4; if (sack) tlen += 2; switch (af) { case AF_INET: len = sizeof(struct ip) + tlen; break; #ifdef INET6 case AF_INET6: len = sizeof(struct ip6_hdr) + tlen; break; #endif /* INET6 */ default: unhandled_af(af); } /* create outgoing mbuf */ m = m_gethdr(M_DONTWAIT, MT_HEADER); if (m == NULL) return (NULL); if (tag) m->m_pkthdr.pf.flags |= PF_TAG_GENERATED; m->m_pkthdr.pf.tag = rtag; m->m_pkthdr.ph_rtableid = rdom; if (r && (r->scrub_flags & PFSTATE_SETPRIO)) m->m_pkthdr.pf.prio = r->set_prio[0]; if (r && r->qid) m->m_pkthdr.pf.qid = r->qid; m->m_data += max_linkhdr; m->m_pkthdr.len = m->m_len = len; m->m_pkthdr.ph_ifidx = 0; m->m_pkthdr.csum_flags |= M_TCP_CSUM_OUT; memset(m->m_data, 0, len); switch (af) { case AF_INET: h = mtod(m, struct ip *); h->ip_p = IPPROTO_TCP; h->ip_len = htons(tlen); h->ip_v = 4; h->ip_hl = sizeof(*h) >> 2; h->ip_tos = IPTOS_LOWDELAY; h->ip_len = htons(len); h->ip_off = htons(ip_mtudisc ? IP_DF : 0); h->ip_ttl = ttl ? ttl : ip_defttl; h->ip_sum = 0; h->ip_src.s_addr = saddr->v4.s_addr; h->ip_dst.s_addr = daddr->v4.s_addr; th = (struct tcphdr *)((caddr_t)h + sizeof(struct ip)); break; #ifdef INET6 case AF_INET6: h6 = mtod(m, struct ip6_hdr *); h6->ip6_nxt = IPPROTO_TCP; h6->ip6_plen = htons(tlen); h6->ip6_vfc |= IPV6_VERSION; h6->ip6_hlim = IPV6_DEFHLIM; memcpy(&h6->ip6_src, &saddr->v6, sizeof(struct in6_addr)); memcpy(&h6->ip6_dst, &daddr->v6, sizeof(struct in6_addr)); th = (struct tcphdr *)((caddr_t)h6 + sizeof(struct ip6_hdr)); break; #endif /* INET6 */ default: unhandled_af(af); } /* TCP header */ th->th_sport = sport; th->th_dport = dport; th->th_seq = htonl(seq); th->th_ack = htonl(ack); th->th_off = tlen >> 2; th->th_flags = flags; th->th_win = htons(win); opt = (char *)(th + 1); if (mss) { opt[0] = TCPOPT_MAXSEG; opt[1] = 4; mss = htons(mss); memcpy((opt + 2), &mss, 2); opt += 4; } if (sack) { opt[0] = TCPOPT_SACK_PERMITTED; opt[1] = 2; opt += 2; } return (m); } void pf_send_tcp(const struct pf_rule *r, sa_family_t af, const struct pf_addr *saddr, const struct pf_addr *daddr, u_int16_t sport, u_int16_t dport, u_int32_t seq, u_int32_t ack, u_int8_t flags, u_int16_t win, u_int16_t mss, u_int8_t ttl, int tag, u_int16_t rtag, u_int rdom) { struct mbuf *m; if ((m = pf_build_tcp(r, af, saddr, daddr, sport, dport, seq, ack, flags, win, mss, ttl, tag, rtag, 0, rdom)) == NULL) return; switch (af) { case AF_INET: ip_send(m); break; #ifdef INET6 case AF_INET6: ip6_send(m); break; #endif /* INET6 */ } } static void pf_send_challenge_ack(struct pf_pdesc *pd, struct pf_state *st, struct pf_state_peer *src, struct pf_state_peer *dst) { /* * We are sending challenge ACK as a response to SYN packet, which * matches existing state (modulo TCP window check). Therefore packet * must be sent on behalf of destination. * * We expect sender to remain either silent, or send RST packet * so both, firewall and remote peer, can purge dead state from * memory. */ pf_send_tcp(st->rule.ptr, pd->af, pd->dst, pd->src, pd->hdr.tcp.th_dport, pd->hdr.tcp.th_sport, dst->seqlo, src->seqlo, TH_ACK, 0, 0, st->rule.ptr->return_ttl, 1, 0, pd->rdomain); } void pf_send_icmp(struct mbuf *m, u_int8_t type, u_int8_t code, int param, sa_family_t af, struct pf_rule *r, u_int rdomain) { struct mbuf *m0; if ((m0 = m_copym(m, 0, M_COPYALL, M_NOWAIT)) == NULL) return; m0->m_pkthdr.pf.flags |= PF_TAG_GENERATED; m0->m_pkthdr.ph_rtableid = rdomain; if (r && (r->scrub_flags & PFSTATE_SETPRIO)) m0->m_pkthdr.pf.prio = r->set_prio[0]; if (r && r->qid) m0->m_pkthdr.pf.qid = r->qid; switch (af) { case AF_INET: icmp_error(m0, type, code, 0, param); break; #ifdef INET6 case AF_INET6: icmp6_error(m0, type, code, param); break; #endif /* INET6 */ } } /* * Return ((n = 0) == (a = b [with mask m])) * Note: n != 0 => returns (a != b [with mask m]) */ int pf_match_addr(u_int8_t n, struct pf_addr *a, struct pf_addr *m, struct pf_addr *b, sa_family_t af) { switch (af) { case AF_INET: if ((a->addr32[0] & m->addr32[0]) == (b->addr32[0] & m->addr32[0])) return (n == 0); break; #ifdef INET6 case AF_INET6: if (((a->addr32[0] & m->addr32[0]) == (b->addr32[0] & m->addr32[0])) && ((a->addr32[1] & m->addr32[1]) == (b->addr32[1] & m->addr32[1])) && ((a->addr32[2] & m->addr32[2]) == (b->addr32[2] & m->addr32[2])) && ((a->addr32[3] & m->addr32[3]) == (b->addr32[3] & m->addr32[3]))) return (n == 0); break; #endif /* INET6 */ } return (n != 0); } /* * Return 1 if b <= a <= e, otherwise return 0. */ int pf_match_addr_range(struct pf_addr *b, struct pf_addr *e, struct pf_addr *a, sa_family_t af) { switch (af) { case AF_INET: if ((ntohl(a->addr32[0]) < ntohl(b->addr32[0])) || (ntohl(a->addr32[0]) > ntohl(e->addr32[0]))) return (0); break; #ifdef INET6 case AF_INET6: { int i; /* check a >= b */ for (i = 0; i < 4; ++i) if (ntohl(a->addr32[i]) > ntohl(b->addr32[i])) break; else if (ntohl(a->addr32[i]) < ntohl(b->addr32[i])) return (0); /* check a <= e */ for (i = 0; i < 4; ++i) if (ntohl(a->addr32[i]) < ntohl(e->addr32[i])) break; else if (ntohl(a->addr32[i]) > ntohl(e->addr32[i])) return (0); break; } #endif /* INET6 */ } return (1); } int pf_match(u_int8_t op, u_int32_t a1, u_int32_t a2, u_int32_t p) { switch (op) { case PF_OP_IRG: return ((p > a1) && (p < a2)); case PF_OP_XRG: return ((p < a1) || (p > a2)); case PF_OP_RRG: return ((p >= a1) && (p <= a2)); case PF_OP_EQ: return (p == a1); case PF_OP_NE: return (p != a1); case PF_OP_LT: return (p < a1); case PF_OP_LE: return (p <= a1); case PF_OP_GT: return (p > a1); case PF_OP_GE: return (p >= a1); } return (0); /* never reached */ } int pf_match_port(u_int8_t op, u_int16_t a1, u_int16_t a2, u_int16_t p) { return (pf_match(op, ntohs(a1), ntohs(a2), ntohs(p))); } int pf_match_uid(u_int8_t op, uid_t a1, uid_t a2, uid_t u) { if (u == -1 && op != PF_OP_EQ && op != PF_OP_NE) return (0); return (pf_match(op, a1, a2, u)); } int pf_match_gid(u_int8_t op, gid_t a1, gid_t a2, gid_t g) { if (g == -1 && op != PF_OP_EQ && op != PF_OP_NE) return (0); return (pf_match(op, a1, a2, g)); } int pf_match_tag(struct mbuf *m, struct pf_rule *r, int *tag) { if (*tag == -1) *tag = m->m_pkthdr.pf.tag; return ((!r->match_tag_not && r->match_tag == *tag) || (r->match_tag_not && r->match_tag != *tag)); } int pf_match_rcvif(struct mbuf *m, struct pf_rule *r) { struct ifnet *ifp; #if NCARP > 0 struct ifnet *ifp0; #endif struct pfi_kif *kif; ifp = if_get(m->m_pkthdr.ph_ifidx); if (ifp == NULL) return (0); #if NCARP > 0 if (ifp->if_type == IFT_CARP && (ifp0 = if_get(ifp->if_carpdevidx)) != NULL) { kif = (struct pfi_kif *)ifp0->if_pf_kif; if_put(ifp0); } else #endif /* NCARP */ kif = (struct pfi_kif *)ifp->if_pf_kif; if_put(ifp); if (kif == NULL) { DPFPRINTF(LOG_ERR, "%s: kif == NULL, @%d via %s", __func__, r->nr, r->rcv_ifname); return (0); } return (pfi_kif_match(r->rcv_kif, kif)); } void pf_tag_packet(struct mbuf *m, int tag, int rtableid) { if (tag > 0) m->m_pkthdr.pf.tag = tag; if (rtableid >= 0) m->m_pkthdr.ph_rtableid = (u_int)rtableid; } void pf_anchor_stack_init(void) { struct pf_anchor_stackframe *stack; stack = (struct pf_anchor_stackframe *)cpumem_enter(pf_anchor_stack); stack[PF_ANCHOR_STACK_MAX].sf_stack_top = &stack[0]; cpumem_leave(pf_anchor_stack, stack); } int pf_anchor_stack_is_full(struct pf_anchor_stackframe *sf) { struct pf_anchor_stackframe *stack; int rv; stack = (struct pf_anchor_stackframe *)cpumem_enter(pf_anchor_stack); rv = (sf == &stack[PF_ANCHOR_STACK_MAX]); cpumem_leave(pf_anchor_stack, stack); return (rv); } int pf_anchor_stack_is_empty(struct pf_anchor_stackframe *sf) { struct pf_anchor_stackframe *stack; int rv; stack = (struct pf_anchor_stackframe *)cpumem_enter(pf_anchor_stack); rv = (sf == &stack[0]); cpumem_leave(pf_anchor_stack, stack); return (rv); } struct pf_anchor_stackframe * pf_anchor_stack_top(void) { struct pf_anchor_stackframe *stack; struct pf_anchor_stackframe *top_sf; stack = (struct pf_anchor_stackframe *)cpumem_enter(pf_anchor_stack); top_sf = stack[PF_ANCHOR_STACK_MAX].sf_stack_top; cpumem_leave(pf_anchor_stack, stack); return (top_sf); } int pf_anchor_stack_push(struct pf_ruleset *rs, struct pf_rule *r, struct pf_anchor *child, int jump_target) { struct pf_anchor_stackframe *stack; struct pf_anchor_stackframe *top_sf = pf_anchor_stack_top(); top_sf++; if (pf_anchor_stack_is_full(top_sf)) return (-1); top_sf->sf_rs = rs; top_sf->sf_r = r; top_sf->sf_child = child; top_sf->sf_jump_target = jump_target; stack = (struct pf_anchor_stackframe *)cpumem_enter(pf_anchor_stack); if ((top_sf <= &stack[0]) || (top_sf >= &stack[PF_ANCHOR_STACK_MAX])) panic("%s: top frame outside of anchor stack range", __func__); stack[PF_ANCHOR_STACK_MAX].sf_stack_top = top_sf; cpumem_leave(pf_anchor_stack, stack); return (0); } int pf_anchor_stack_pop(struct pf_ruleset **rs, struct pf_rule **r, struct pf_anchor **child, int *jump_target) { struct pf_anchor_stackframe *top_sf = pf_anchor_stack_top(); struct pf_anchor_stackframe *stack; int on_top; stack = (struct pf_anchor_stackframe *)cpumem_enter(pf_anchor_stack); if (pf_anchor_stack_is_empty(top_sf)) { on_top = -1; } else { if ((top_sf <= &stack[0]) || (top_sf >= &stack[PF_ANCHOR_STACK_MAX])) panic("%s: top frame outside of anchor stack range", __func__); *rs = top_sf->sf_rs; *r = top_sf->sf_r; *child = top_sf->sf_child; *jump_target = top_sf->sf_jump_target; top_sf--; stack[PF_ANCHOR_STACK_MAX].sf_stack_top = top_sf; on_top = 0; } cpumem_leave(pf_anchor_stack, stack); return (on_top); } void pf_poolmask(struct pf_addr *naddr, struct pf_addr *raddr, struct pf_addr *rmask, struct pf_addr *saddr, sa_family_t af) { switch (af) { case AF_INET: naddr->addr32[0] = (raddr->addr32[0] & rmask->addr32[0]) | ((rmask->addr32[0] ^ 0xffffffff ) & saddr->addr32[0]); break; #ifdef INET6 case AF_INET6: naddr->addr32[0] = (raddr->addr32[0] & rmask->addr32[0]) | ((rmask->addr32[0] ^ 0xffffffff ) & saddr->addr32[0]); naddr->addr32[1] = (raddr->addr32[1] & rmask->addr32[1]) | ((rmask->addr32[1] ^ 0xffffffff ) & saddr->addr32[1]); naddr->addr32[2] = (raddr->addr32[2] & rmask->addr32[2]) | ((rmask->addr32[2] ^ 0xffffffff ) & saddr->addr32[2]); naddr->addr32[3] = (raddr->addr32[3] & rmask->addr32[3]) | ((rmask->addr32[3] ^ 0xffffffff ) & saddr->addr32[3]); break; #endif /* INET6 */ default: unhandled_af(af); } } void pf_addr_inc(struct pf_addr *addr, sa_family_t af) { switch (af) { case AF_INET: addr->addr32[0] = htonl(ntohl(addr->addr32[0]) + 1); break; #ifdef INET6 case AF_INET6: if (addr->addr32[3] == 0xffffffff) { addr->addr32[3] = 0; if (addr->addr32[2] == 0xffffffff) { addr->addr32[2] = 0; if (addr->addr32[1] == 0xffffffff) { addr->addr32[1] = 0; addr->addr32[0] = htonl(ntohl(addr->addr32[0]) + 1); } else addr->addr32[1] = htonl(ntohl(addr->addr32[1]) + 1); } else addr->addr32[2] = htonl(ntohl(addr->addr32[2]) + 1); } else addr->addr32[3] = htonl(ntohl(addr->addr32[3]) + 1); break; #endif /* INET6 */ default: unhandled_af(af); } } int pf_socket_lookup(struct pf_pdesc *pd) { struct pf_addr *saddr, *daddr; u_int16_t sport, dport; struct inpcbtable *table; struct inpcb *inp; pd->lookup.uid = -1; pd->lookup.gid = -1; pd->lookup.pid = NO_PID; switch (pd->virtual_proto) { case IPPROTO_TCP: sport = pd->hdr.tcp.th_sport; dport = pd->hdr.tcp.th_dport; PF_ASSERT_LOCKED(); NET_ASSERT_LOCKED(); table = &tcbtable; break; case IPPROTO_UDP: sport = pd->hdr.udp.uh_sport; dport = pd->hdr.udp.uh_dport; PF_ASSERT_LOCKED(); NET_ASSERT_LOCKED(); table = &udbtable; break; default: return (-1); } if (pd->dir == PF_IN) { saddr = pd->src; daddr = pd->dst; } else { u_int16_t p; p = sport; sport = dport; dport = p; saddr = pd->dst; daddr = pd->src; } switch (pd->af) { case AF_INET: /* * Fails when rtable is changed while evaluating the ruleset * The socket looked up will not match the one hit in the end. */ inp = in_pcblookup(table, saddr->v4, sport, daddr->v4, dport, pd->rdomain); if (inp == NULL) { inp = in_pcblookup_listen(table, daddr->v4, dport, NULL, pd->rdomain); if (inp == NULL) return (-1); } break; #ifdef INET6 case AF_INET6: if (pd->virtual_proto == IPPROTO_UDP) table = &udb6table; if (pd->virtual_proto == IPPROTO_TCP) table = &tcb6table; inp = in6_pcblookup(table, &saddr->v6, sport, &daddr->v6, dport, pd->rdomain); if (inp == NULL) { inp = in6_pcblookup_listen(table, &daddr->v6, dport, NULL, pd->rdomain); if (inp == NULL) return (-1); } break; #endif /* INET6 */ default: unhandled_af(pd->af); } pd->lookup.uid = inp->inp_socket->so_euid; pd->lookup.gid = inp->inp_socket->so_egid; pd->lookup.pid = inp->inp_socket->so_cpid; in_pcbunref(inp); return (1); } /* post: r => (r[0] == type /\ r[1] >= min_typelen >= 2 "validity" * /\ (eoh - r) >= min_typelen >= 2 "safety" ) * * warning: r + r[1] may exceed opts bounds for r[1] > min_typelen */ u_int8_t* pf_find_tcpopt(u_int8_t *opt, u_int8_t *opts, size_t hlen, u_int8_t type, u_int8_t min_typelen) { u_int8_t *eoh = opts + hlen; if (min_typelen < 2) return (NULL); while ((eoh - opt) >= min_typelen) { switch (*opt) { case TCPOPT_EOL: /* FALLTHROUGH - Workaround the failure of some systems to NOP-pad their bzero'd option buffers, producing spurious EOLs */ case TCPOPT_NOP: opt++; continue; default: if (opt[0] == type && opt[1] >= min_typelen) return (opt); } opt += MAX(opt[1], 2); /* evade infinite loops */ } return (NULL); } u_int8_t pf_get_wscale(struct pf_pdesc *pd) { int olen; u_int8_t opts[MAX_TCPOPTLEN], *opt; u_int8_t wscale = 0; olen = (pd->hdr.tcp.th_off << 2) - sizeof(struct tcphdr); if (olen < TCPOLEN_WINDOW || !pf_pull_hdr(pd->m, pd->off + sizeof(struct tcphdr), opts, olen, NULL, pd->af)) return (0); opt = opts; while ((opt = pf_find_tcpopt(opt, opts, olen, TCPOPT_WINDOW, TCPOLEN_WINDOW)) != NULL) { wscale = opt[2]; wscale = MIN(wscale, TCP_MAX_WINSHIFT); wscale |= PF_WSCALE_FLAG; opt += opt[1]; } return (wscale); } u_int16_t pf_get_mss(struct pf_pdesc *pd) { int olen; u_int8_t opts[MAX_TCPOPTLEN], *opt; u_int16_t mss = tcp_mssdflt; olen = (pd->hdr.tcp.th_off << 2) - sizeof(struct tcphdr); if (olen < TCPOLEN_MAXSEG || !pf_pull_hdr(pd->m, pd->off + sizeof(struct tcphdr), opts, olen, NULL, pd->af)) return (0); opt = opts; while ((opt = pf_find_tcpopt(opt, opts, olen, TCPOPT_MAXSEG, TCPOLEN_MAXSEG)) != NULL) { memcpy(&mss, (opt + 2), 2); mss = ntohs(mss); opt += opt[1]; } return (mss); } u_int16_t pf_calc_mss(struct pf_addr *addr, sa_family_t af, int rtableid, u_int16_t offer) { struct ifnet *ifp; struct sockaddr_in *dst; #ifdef INET6 struct sockaddr_in6 *dst6; #endif /* INET6 */ struct rtentry *rt = NULL; struct sockaddr_storage ss; int hlen; u_int16_t mss = tcp_mssdflt; memset(&ss, 0, sizeof(ss)); switch (af) { case AF_INET: hlen = sizeof(struct ip); dst = (struct sockaddr_in *)&ss; dst->sin_family = AF_INET; dst->sin_len = sizeof(*dst); dst->sin_addr = addr->v4; rt = rtalloc(sintosa(dst), 0, rtableid); break; #ifdef INET6 case AF_INET6: hlen = sizeof(struct ip6_hdr); dst6 = (struct sockaddr_in6 *)&ss; dst6->sin6_family = AF_INET6; dst6->sin6_len = sizeof(*dst6); dst6->sin6_addr = addr->v6; rt = rtalloc(sin6tosa(dst6), 0, rtableid); break; #endif /* INET6 */ } if (rt != NULL && (ifp = if_get(rt->rt_ifidx)) != NULL) { mss = ifp->if_mtu - hlen - sizeof(struct tcphdr); mss = max(tcp_mssdflt, mss); if_put(ifp); } rtfree(rt); mss = min(mss, offer); mss = max(mss, 64); /* sanity - at least max opt space */ return (mss); } static __inline int pf_set_rt_ifp(struct pf_state *st, struct pf_addr *saddr, sa_family_t af, struct pf_src_node **sns) { struct pf_rule *r = st->rule.ptr; int rv; if (!r->rt) return (0); rv = pf_map_addr(af, r, saddr, &st->rt_addr, NULL, sns, &r->route, PF_SN_ROUTE); if (rv == 0) st->rt = r->rt; return (rv); } u_int32_t pf_tcp_iss(struct pf_pdesc *pd) { SHA2_CTX ctx; union { uint8_t bytes[SHA512_DIGEST_LENGTH]; uint32_t words[1]; } digest; if (pf_tcp_secret_init == 0) { arc4random_buf(pf_tcp_secret, sizeof(pf_tcp_secret)); SHA512Init(&pf_tcp_secret_ctx); SHA512Update(&pf_tcp_secret_ctx, pf_tcp_secret, sizeof(pf_tcp_secret)); pf_tcp_secret_init = 1; } ctx = pf_tcp_secret_ctx; SHA512Update(&ctx, &pd->rdomain, sizeof(pd->rdomain)); SHA512Update(&ctx, &pd->hdr.tcp.th_sport, sizeof(u_short)); SHA512Update(&ctx, &pd->hdr.tcp.th_dport, sizeof(u_short)); switch (pd->af) { case AF_INET: SHA512Update(&ctx, &pd->src->v4, sizeof(struct in_addr)); SHA512Update(&ctx, &pd->dst->v4, sizeof(struct in_addr)); break; #ifdef INET6 case AF_INET6: SHA512Update(&ctx, &pd->src->v6, sizeof(struct in6_addr)); SHA512Update(&ctx, &pd->dst->v6, sizeof(struct in6_addr)); break; #endif /* INET6 */ } SHA512Final(digest.bytes, &ctx); pf_tcp_iss_off += 4096; return (digest.words[0] + READ_ONCE(tcp_iss) + pf_tcp_iss_off); } void pf_rule_to_actions(struct pf_rule *r, struct pf_rule_actions *a) { if (r->qid) a->qid = r->qid; if (r->pqid) a->pqid = r->pqid; if (r->rtableid >= 0) a->rtableid = r->rtableid; #if NPFLOG > 0 a->log |= r->log; #endif /* NPFLOG > 0 */ if (r->scrub_flags & PFSTATE_SETTOS) a->set_tos = r->set_tos; if (r->min_ttl) a->min_ttl = r->min_ttl; if (r->max_mss) a->max_mss = r->max_mss; a->flags |= (r->scrub_flags & (PFSTATE_NODF|PFSTATE_RANDOMID| PFSTATE_SETTOS|PFSTATE_SCRUB_TCP|PFSTATE_SETPRIO)); if (r->scrub_flags & PFSTATE_SETPRIO) { a->set_prio[0] = r->set_prio[0]; a->set_prio[1] = r->set_prio[1]; } if (r->rule_flag & PFRULE_SETDELAY) a->delay = r->delay; } #define PF_TEST_ATTRIB(t, a) \ if (t) { \ r = a; \ continue; \ } else do { \ } while (0) enum pf_test_status pf_match_rule(struct pf_test_ctx *ctx, struct pf_ruleset *ruleset) { struct pf_rule *r; struct pf_anchor *child = NULL; int target; pf_anchor_stack_init(); enter_ruleset: r = TAILQ_FIRST(ruleset->rules.active.ptr); while (r != NULL) { PF_TEST_ATTRIB(r->rule_flag & PFRULE_EXPIRED, TAILQ_NEXT(r, entries)); r->evaluations++; PF_TEST_ATTRIB( (pfi_kif_match(r->kif, ctx->pd->kif) == r->ifnot), r->skip[PF_SKIP_IFP].ptr); PF_TEST_ATTRIB((r->direction && r->direction != ctx->pd->dir), r->skip[PF_SKIP_DIR].ptr); PF_TEST_ATTRIB((r->onrdomain >= 0 && (r->onrdomain == ctx->pd->rdomain) == r->ifnot), r->skip[PF_SKIP_RDOM].ptr); PF_TEST_ATTRIB((r->af && r->af != ctx->pd->af), r->skip[PF_SKIP_AF].ptr); PF_TEST_ATTRIB((r->proto && r->proto != ctx->pd->proto), r->skip[PF_SKIP_PROTO].ptr); PF_TEST_ATTRIB((PF_MISMATCHAW(&r->src.addr, &ctx->pd->nsaddr, ctx->pd->naf, r->src.neg, ctx->pd->kif, ctx->act.rtableid)), r->skip[PF_SKIP_SRC_ADDR].ptr); PF_TEST_ATTRIB((PF_MISMATCHAW(&r->dst.addr, &ctx->pd->ndaddr, ctx->pd->af, r->dst.neg, NULL, ctx->act.rtableid)), r->skip[PF_SKIP_DST_ADDR].ptr); switch (ctx->pd->virtual_proto) { case PF_VPROTO_FRAGMENT: /* tcp/udp only. port_op always 0 in other cases */ PF_TEST_ATTRIB((r->src.port_op || r->dst.port_op), TAILQ_NEXT(r, entries)); PF_TEST_ATTRIB((ctx->pd->proto == IPPROTO_TCP && r->flagset), TAILQ_NEXT(r, entries)); /* icmp only. type/code always 0 in other cases */ PF_TEST_ATTRIB((r->type || r->code), TAILQ_NEXT(r, entries)); /* tcp/udp only. {uid|gid}.op always 0 in other cases */ PF_TEST_ATTRIB((r->gid.op || r->uid.op), TAILQ_NEXT(r, entries)); break; case IPPROTO_TCP: PF_TEST_ATTRIB(((r->flagset & ctx->th->th_flags) != r->flags), TAILQ_NEXT(r, entries)); PF_TEST_ATTRIB((r->os_fingerprint != PF_OSFP_ANY && !pf_osfp_match(pf_osfp_fingerprint(ctx->pd), r->os_fingerprint)), TAILQ_NEXT(r, entries)); /* FALLTHROUGH */ case IPPROTO_UDP: /* tcp/udp only. port_op always 0 in other cases */ PF_TEST_ATTRIB((r->src.port_op && !pf_match_port(r->src.port_op, r->src.port[0], r->src.port[1], ctx->pd->nsport)), r->skip[PF_SKIP_SRC_PORT].ptr); PF_TEST_ATTRIB((r->dst.port_op && !pf_match_port(r->dst.port_op, r->dst.port[0], r->dst.port[1], ctx->pd->ndport)), r->skip[PF_SKIP_DST_PORT].ptr); /* tcp/udp only. uid.op always 0 in other cases */ PF_TEST_ATTRIB((r->uid.op && (ctx->pd->lookup.done || (ctx->pd->lookup.done = pf_socket_lookup(ctx->pd), 1)) && !pf_match_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1], ctx->pd->lookup.uid)), TAILQ_NEXT(r, entries)); /* tcp/udp only. gid.op always 0 in other cases */ PF_TEST_ATTRIB((r->gid.op && (ctx->pd->lookup.done || (ctx->pd->lookup.done = pf_socket_lookup(ctx->pd), 1)) && !pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1], ctx->pd->lookup.gid)), TAILQ_NEXT(r, entries)); break; case IPPROTO_ICMP: /* icmp only. type always 0 in other cases */ PF_TEST_ATTRIB((r->type && r->type != ctx->icmptype + 1), TAILQ_NEXT(r, entries)); /* icmp only. type always 0 in other cases */ PF_TEST_ATTRIB((r->code && r->code != ctx->icmpcode + 1), TAILQ_NEXT(r, entries)); /* icmp only. don't create states on replies */ PF_TEST_ATTRIB((r->keep_state && !ctx->state_icmp && (r->rule_flag & PFRULE_STATESLOPPY) == 0 && ctx->icmp_dir != PF_IN), TAILQ_NEXT(r, entries)); break; case IPPROTO_ICMPV6: /* icmp only. type always 0 in other cases */ PF_TEST_ATTRIB((r->type && r->type != ctx->icmptype + 1), TAILQ_NEXT(r, entries)); /* icmp only. type always 0 in other cases */ PF_TEST_ATTRIB((r->code && r->code != ctx->icmpcode + 1), TAILQ_NEXT(r, entries)); /* icmp only. don't create states on replies */ PF_TEST_ATTRIB((r->keep_state && !ctx->state_icmp && (r->rule_flag & PFRULE_STATESLOPPY) == 0 && ctx->icmp_dir != PF_IN && ctx->icmptype != ND_NEIGHBOR_ADVERT), TAILQ_NEXT(r, entries)); break; default: break; } PF_TEST_ATTRIB((r->rule_flag & PFRULE_FRAGMENT && ctx->pd->virtual_proto != PF_VPROTO_FRAGMENT), TAILQ_NEXT(r, entries)); PF_TEST_ATTRIB((r->tos && !(r->tos == ctx->pd->tos)), TAILQ_NEXT(r, entries)); PF_TEST_ATTRIB((r->prob && r->prob <= arc4random_uniform(UINT_MAX - 1) + 1), TAILQ_NEXT(r, entries)); PF_TEST_ATTRIB((r->match_tag && !pf_match_tag(ctx->pd->m, r, &ctx->tag)), TAILQ_NEXT(r, entries)); PF_TEST_ATTRIB((r->rcv_kif && pf_match_rcvif(ctx->pd->m, r) == r->rcvifnot), TAILQ_NEXT(r, entries)); PF_TEST_ATTRIB((r->prio && (r->prio == PF_PRIO_ZERO ? 0 : r->prio) != ctx->pd->m->m_pkthdr.pf.prio), TAILQ_NEXT(r, entries)); /* must be last! */ if (r->pktrate.limit) { pf_add_threshold(&r->pktrate); PF_TEST_ATTRIB((pf_check_threshold(&r->pktrate)), TAILQ_NEXT(r, entries)); } /* FALLTHROUGH */ if (r->tag) ctx->tag = r->tag; if (r->anchor == NULL) { if (r->rule_flag & PFRULE_ONCE) { u_int32_t rule_flag; rule_flag = r->rule_flag; if (((rule_flag & PFRULE_EXPIRED) == 0) && atomic_cas_uint(&r->rule_flag, rule_flag, rule_flag | PFRULE_EXPIRED) == rule_flag) { r->exptime = gettime(); } else { r = TAILQ_NEXT(r, entries); continue; } } if (r->action == PF_MATCH) { if ((ctx->ri = pool_get(&pf_rule_item_pl, PR_NOWAIT)) == NULL) { REASON_SET(&ctx->reason, PFRES_MEMORY); return (PF_TEST_FAIL); } ctx->ri->r = r; /* order is irrelevant */ SLIST_INSERT_HEAD(&ctx->rules, ctx->ri, entry); ctx->ri = NULL; pf_rule_to_actions(r, &ctx->act); if (r->rule_flag & PFRULE_AFTO) ctx->pd->naf = r->naf; if (pf_get_transaddr(r, ctx->pd, ctx->sns, &ctx->nr) == -1) { REASON_SET(&ctx->reason, PFRES_TRANSLATE); return (PF_TEST_FAIL); } #if NPFLOG > 0 if (r->log) { REASON_SET(&ctx->reason, PFRES_MATCH); pflog_packet(ctx->pd, ctx->reason, r, ctx->a, ruleset, NULL); } #endif /* NPFLOG > 0 */ } else { /* * found matching r */ *ctx->rm = r; /* * anchor, with ruleset, where r belongs to */ *ctx->am = ctx->a; /* * ruleset where r belongs to */ *ctx->rsm = ruleset; /* * ruleset, where anchor belongs to. */ ctx->arsm = ctx->aruleset; } #if NPFLOG > 0 if (ctx->act.log & PF_LOG_MATCHES) pf_log_matches(ctx->pd, r, ctx->a, ruleset, &ctx->rules); #endif /* NPFLOG > 0 */ if (r->quick) return (PF_TEST_QUICK); } else { ctx->a = r; ctx->aruleset = &r->anchor->ruleset; if (r->anchor_wildcard) { RB_FOREACH(child, pf_anchor_node, &r->anchor->children) { if (pf_anchor_stack_push(ruleset, r, child, PF_NEXT_CHILD) != 0) return (PF_TEST_FAIL); ruleset = &child->ruleset; goto enter_ruleset; next_child: continue; /* with RB_FOREACH() */ } } else { if (pf_anchor_stack_push(ruleset, r, child, PF_NEXT_RULE) != 0) return (PF_TEST_FAIL); ruleset = &r->anchor->ruleset; child = NULL; goto enter_ruleset; next_rule: ; } } r = TAILQ_NEXT(r, entries); } if (pf_anchor_stack_pop(&ruleset, &r, &child, &target) == 0) { /* stop if any rule matched within quick anchors. */ if (r->quick == PF_TEST_QUICK && *ctx->am == r) return (PF_TEST_QUICK); switch (target) { case PF_NEXT_CHILD: goto next_child; case PF_NEXT_RULE: goto next_rule; default: panic("%s: unknown jump target", __func__); } } return (PF_TEST_OK); } int pf_test_rule(struct pf_pdesc *pd, struct pf_rule **rm, struct pf_state **sm, struct pf_rule **am, struct pf_ruleset **rsm, u_short *reason) { struct pf_rule *r = NULL; struct pf_rule *a = NULL; struct pf_ruleset *ruleset = NULL; struct pf_state_key *skw = NULL, *sks = NULL; int rewrite = 0; u_int16_t virtual_type, virtual_id; int action = PF_DROP; struct pf_test_ctx ctx; int rv; PF_ASSERT_LOCKED(); memset(&ctx, 0, sizeof(ctx)); ctx.pd = pd; ctx.rm = rm; ctx.am = am; ctx.rsm = rsm; ctx.th = &pd->hdr.tcp; ctx.act.rtableid = pd->rdomain; ctx.tag = -1; SLIST_INIT(&ctx.rules); if (pd->dir == PF_IN && if_congested()) { REASON_SET(&ctx.reason, PFRES_CONGEST); return (PF_DROP); } switch (pd->virtual_proto) { case IPPROTO_ICMP: ctx.icmptype = pd->hdr.icmp.icmp_type; ctx.icmpcode = pd->hdr.icmp.icmp_code; ctx.state_icmp = pf_icmp_mapping(pd, ctx.icmptype, &ctx.icmp_dir, &virtual_id, &virtual_type); if (ctx.icmp_dir == PF_IN) { pd->osport = pd->nsport = virtual_id; pd->odport = pd->ndport = virtual_type; } else { pd->osport = pd->nsport = virtual_type; pd->odport = pd->ndport = virtual_id; } break; #ifdef INET6 case IPPROTO_ICMPV6: ctx.icmptype = pd->hdr.icmp6.icmp6_type; ctx.icmpcode = pd->hdr.icmp6.icmp6_code; ctx.state_icmp = pf_icmp_mapping(pd, ctx.icmptype, &ctx.icmp_dir, &virtual_id, &virtual_type); if (ctx.icmp_dir == PF_IN) { pd->osport = pd->nsport = virtual_id; pd->odport = pd->ndport = virtual_type; } else { pd->osport = pd->nsport = virtual_type; pd->odport = pd->ndport = virtual_id; } break; #endif /* INET6 */ } ruleset = &pf_main_ruleset; rv = pf_match_rule(&ctx, ruleset); if (rv == PF_TEST_FAIL) { /* * Reason has been set in pf_match_rule() already. */ goto cleanup; } r = *ctx.rm; /* matching rule */ a = *ctx.am; /* rule that defines an anchor containing 'r' */ ruleset = *ctx.rsm;/* ruleset of the anchor defined by the rule 'a' */ ctx.aruleset = ctx.arsm;/* ruleset of the 'a' rule itself */ /* apply actions for last matching pass/block rule */ pf_rule_to_actions(r, &ctx.act); if (r->rule_flag & PFRULE_AFTO) pd->naf = r->naf; if (pf_get_transaddr(r, pd, ctx.sns, &ctx.nr) == -1) { REASON_SET(&ctx.reason, PFRES_TRANSLATE); goto cleanup; } REASON_SET(&ctx.reason, PFRES_MATCH); #if NPFLOG > 0 if (r->log) pflog_packet(pd, ctx.reason, r, a, ruleset, NULL); if (ctx.act.log & PF_LOG_MATCHES) pf_log_matches(pd, r, a, ruleset, &ctx.rules); #endif /* NPFLOG > 0 */ if (pd->virtual_proto != PF_VPROTO_FRAGMENT && (r->action == PF_DROP) && ((r->rule_flag & PFRULE_RETURNRST) || (r->rule_flag & PFRULE_RETURNICMP) || (r->rule_flag & PFRULE_RETURN))) { if (pd->proto == IPPROTO_TCP && ((r->rule_flag & PFRULE_RETURNRST) || (r->rule_flag & PFRULE_RETURN)) && !(ctx.th->th_flags & TH_RST)) { u_int32_t ack = ntohl(ctx.th->th_seq) + pd->p_len; if (pf_check_tcp_cksum(pd->m, pd->off, pd->tot_len - pd->off, pd->af)) REASON_SET(&ctx.reason, PFRES_PROTCKSUM); else { if (ctx.th->th_flags & TH_SYN) ack++; if (ctx.th->th_flags & TH_FIN) ack++; pf_send_tcp(r, pd->af, pd->dst, pd->src, ctx.th->th_dport, ctx.th->th_sport, ntohl(ctx.th->th_ack), ack, TH_RST|TH_ACK, 0, 0, r->return_ttl, 1, 0, pd->rdomain); } } else if ((pd->proto != IPPROTO_ICMP || ICMP_INFOTYPE(ctx.icmptype)) && pd->af == AF_INET && r->return_icmp) pf_send_icmp(pd->m, r->return_icmp >> 8, r->return_icmp & 255, 0, pd->af, r, pd->rdomain); else if ((pd->proto != IPPROTO_ICMPV6 || (ctx.icmptype >= ICMP6_ECHO_REQUEST && ctx.icmptype != ND_REDIRECT)) && pd->af == AF_INET6 && r->return_icmp6) pf_send_icmp(pd->m, r->return_icmp6 >> 8, r->return_icmp6 & 255, 0, pd->af, r, pd->rdomain); } if (r->action == PF_DROP) goto cleanup; pf_tag_packet(pd->m, ctx.tag, ctx.act.rtableid); if (ctx.act.rtableid >= 0 && rtable_l2(ctx.act.rtableid) != pd->rdomain) pd->destchg = 1; if (r->action == PF_PASS && pd->badopts != 0 && ! r->allow_opts) { REASON_SET(&ctx.reason, PFRES_IPOPTIONS); #if NPFLOG > 0 pd->pflog |= PF_LOG_FORCE; #endif /* NPFLOG > 0 */ DPFPRINTF(LOG_NOTICE, "dropping packet with " "ip/ipv6 options in pf_test_rule()"); goto cleanup; } if (pd->virtual_proto != PF_VPROTO_FRAGMENT && !ctx.state_icmp && r->keep_state) { if (r->rule_flag & PFRULE_SRCTRACK && pf_insert_src_node(&ctx.sns[PF_SN_NONE], r, PF_SN_NONE, pd->af, pd->src, NULL, NULL) != 0) { REASON_SET(&ctx.reason, PFRES_SRCLIMIT); goto cleanup; } if (r->max_states && (r->states_cur >= r->max_states)) { pf_status.lcounters[LCNT_STATES]++; REASON_SET(&ctx.reason, PFRES_MAXSTATES); goto cleanup; } action = pf_create_state(pd, r, a, ctx.nr, &skw, &sks, &rewrite, sm, ctx.tag, &ctx.rules, &ctx.act, ctx.sns); if (action != PF_PASS) goto cleanup; if (sks != skw) { struct pf_state_key *sk; if (pd->dir == PF_IN) sk = sks; else sk = skw; rewrite += pf_translate(pd, &sk->addr[pd->af == pd->naf ? pd->sidx : pd->didx], sk->port[pd->af == pd->naf ? pd->sidx : pd->didx], &sk->addr[pd->af == pd->naf ? pd->didx : pd->sidx], sk->port[pd->af == pd->naf ? pd->didx : pd->sidx], virtual_type, ctx.icmp_dir); } #ifdef INET6 if (rewrite && skw->af != sks->af) action = PF_AFRT; #endif /* INET6 */ } else { action = PF_PASS; while ((ctx.ri = SLIST_FIRST(&ctx.rules))) { SLIST_REMOVE_HEAD(&ctx.rules, entry); pool_put(&pf_rule_item_pl, ctx.ri); } } /* copy back packet headers if needed */ if (rewrite && pd->hdrlen) { m_copyback(pd->m, pd->off, pd->hdrlen, &pd->hdr, M_NOWAIT); } #if NPFSYNC > 0 if (*sm != NULL && !ISSET((*sm)->state_flags, PFSTATE_NOSYNC) && pd->dir == PF_OUT && pfsync_is_up()) { /* * We want the state created, but we dont * want to send this in case a partner * firewall has to know about it to allow * replies through it. */ if (pfsync_defer(*sm, pd->m)) return (PF_DEFER); } #endif /* NPFSYNC > 0 */ return (action); cleanup: while ((ctx.ri = SLIST_FIRST(&ctx.rules))) { SLIST_REMOVE_HEAD(&ctx.rules, entry); pool_put(&pf_rule_item_pl, ctx.ri); } return (action); } static __inline int pf_create_state(struct pf_pdesc *pd, struct pf_rule *r, struct pf_rule *a, struct pf_rule *nr, struct pf_state_key **skw, struct pf_state_key **sks, int *rewrite, struct pf_state **sm, int tag, struct pf_rule_slist *rules, struct pf_rule_actions *act, struct pf_src_node *sns[PF_SN_MAX]) { struct pf_state *st = NULL; struct tcphdr *th = &pd->hdr.tcp; u_int16_t mss = tcp_mssdflt; u_short reason; u_int i; st = pool_get(&pf_state_pl, PR_NOWAIT | PR_ZERO); if (st == NULL) { REASON_SET(&reason, PFRES_MEMORY); goto csfailed; } st->rule.ptr = r; st->anchor.ptr = a; st->natrule.ptr = nr; if (r->allow_opts) st->state_flags |= PFSTATE_ALLOWOPTS; if (r->rule_flag & PFRULE_STATESLOPPY) st->state_flags |= PFSTATE_SLOPPY; if (r->rule_flag & PFRULE_PFLOW) st->state_flags |= PFSTATE_PFLOW; if (r->rule_flag & PFRULE_NOSYNC) st->state_flags |= PFSTATE_NOSYNC; #if NPFLOG > 0 st->log = act->log & PF_LOG_ALL; #endif /* NPFLOG > 0 */ st->qid = act->qid; st->pqid = act->pqid; st->rtableid[pd->didx] = act->rtableid; st->rtableid[pd->sidx] = -1; /* return traffic is routed normally */ st->min_ttl = act->min_ttl; st->set_tos = act->set_tos; st->max_mss = act->max_mss; st->state_flags |= act->flags; #if NPFSYNC > 0 st->sync_state = PFSYNC_S_NONE; #endif /* NPFSYNC > 0 */ st->set_prio[0] = act->set_prio[0]; st->set_prio[1] = act->set_prio[1]; st->delay = act->delay; SLIST_INIT(&st->src_nodes); /* * must initialize refcnt, before pf_state_insert() gets called. * pf_state_inserts() grabs reference for pfsync! */ PF_REF_INIT(st->refcnt); mtx_init(&st->mtx, IPL_NET); switch (pd->proto) { case IPPROTO_TCP: st->src.seqlo = ntohl(th->th_seq); st->src.seqhi = st->src.seqlo + pd->p_len + 1; if ((th->th_flags & (TH_SYN|TH_ACK)) == TH_SYN && r->keep_state == PF_STATE_MODULATE) { /* Generate sequence number modulator */ st->src.seqdiff = pf_tcp_iss(pd) - st->src.seqlo; if (st->src.seqdiff == 0) st->src.seqdiff = 1; pf_patch_32(pd, &th->th_seq, htonl(st->src.seqlo + st->src.seqdiff)); *rewrite = 1; } else st->src.seqdiff = 0; if (th->th_flags & TH_SYN) { st->src.seqhi++; st->src.wscale = pf_get_wscale(pd); } st->src.max_win = MAX(ntohs(th->th_win), 1); if (st->src.wscale & PF_WSCALE_MASK) { /* Remove scale factor from initial window */ int win = st->src.max_win; win += 1 << (st->src.wscale & PF_WSCALE_MASK); st->src.max_win = (win - 1) >> (st->src.wscale & PF_WSCALE_MASK); } if (th->th_flags & TH_FIN) st->src.seqhi++; st->dst.seqhi = 1; st->dst.max_win = 1; pf_set_protostate(st, PF_PEER_SRC, TCPS_SYN_SENT); pf_set_protostate(st, PF_PEER_DST, TCPS_CLOSED); st->timeout = PFTM_TCP_FIRST_PACKET; pf_status.states_halfopen++; break; case IPPROTO_UDP: pf_set_protostate(st, PF_PEER_SRC, PFUDPS_SINGLE); pf_set_protostate(st, PF_PEER_DST, PFUDPS_NO_TRAFFIC); st->timeout = PFTM_UDP_FIRST_PACKET; break; case IPPROTO_ICMP: #ifdef INET6 case IPPROTO_ICMPV6: #endif /* INET6 */ st->timeout = PFTM_ICMP_FIRST_PACKET; break; default: pf_set_protostate(st, PF_PEER_SRC, PFOTHERS_SINGLE); pf_set_protostate(st, PF_PEER_DST, PFOTHERS_NO_TRAFFIC); st->timeout = PFTM_OTHER_FIRST_PACKET; } st->creation = getuptime(); st->expire = getuptime(); if (pd->proto == IPPROTO_TCP) { if (st->state_flags & PFSTATE_SCRUB_TCP && pf_normalize_tcp_init(pd, &st->src)) { REASON_SET(&reason, PFRES_MEMORY); goto csfailed; } if (st->state_flags & PFSTATE_SCRUB_TCP && st->src.scrub && pf_normalize_tcp_stateful(pd, &reason, st, &st->src, &st->dst, rewrite)) { /* This really shouldn't happen!!! */ DPFPRINTF(LOG_ERR, "%s: tcp normalize failed on first pkt", __func__); goto csfailed; } } st->direction = pd->dir; if (pf_state_key_setup(pd, skw, sks, act->rtableid)) { REASON_SET(&reason, PFRES_MEMORY); goto csfailed; } if (pf_set_rt_ifp(st, pd->src, (*skw)->af, sns) != 0) { REASON_SET(&reason, PFRES_NOROUTE); goto csfailed; } for (i = 0; i < PF_SN_MAX; i++) if (sns[i] != NULL) { struct pf_sn_item *sni; sni = pool_get(&pf_sn_item_pl, PR_NOWAIT); if (sni == NULL) { REASON_SET(&reason, PFRES_MEMORY); goto csfailed; } sni->sn = sns[i]; SLIST_INSERT_HEAD(&st->src_nodes, sni, next); sni->sn->states++; } #if NPFSYNC > 0 pfsync_init_state(st, *skw, *sks, 0); #endif if (pf_state_insert(BOUND_IFACE(r, pd->kif), skw, sks, st)) { *sks = *skw = NULL; REASON_SET(&reason, PFRES_STATEINS); goto csfailed; } else *sm = st; /* * Make state responsible for rules it binds here. */ memcpy(&st->match_rules, rules, sizeof(st->match_rules)); memset(rules, 0, sizeof(*rules)); STATE_INC_COUNTERS(st); if (tag > 0) { pf_tag_ref(tag); st->tag = tag; } if (pd->proto == IPPROTO_TCP && (th->th_flags & (TH_SYN|TH_ACK)) == TH_SYN && r->keep_state == PF_STATE_SYNPROXY && pd->dir == PF_IN) { int rtid = pd->rdomain; if (act->rtableid >= 0) rtid = act->rtableid; pf_set_protostate(st, PF_PEER_SRC, PF_TCPS_PROXY_SRC); st->src.seqhi = arc4random(); /* Find mss option */ mss = pf_get_mss(pd); mss = pf_calc_mss(pd->src, pd->af, rtid, mss); mss = pf_calc_mss(pd->dst, pd->af, rtid, mss); st->src.mss = mss; pf_send_tcp(r, pd->af, pd->dst, pd->src, th->th_dport, th->th_sport, st->src.seqhi, ntohl(th->th_seq) + 1, TH_SYN|TH_ACK, 0, st->src.mss, 0, 1, 0, pd->rdomain); REASON_SET(&reason, PFRES_SYNPROXY); return (PF_SYNPROXY_DROP); } return (PF_PASS); csfailed: if (st) { pf_normalize_tcp_cleanup(st); /* safe even w/o init */ pf_src_tree_remove_state(st); pool_put(&pf_state_pl, st); } for (i = 0; i < PF_SN_MAX; i++) if (sns[i] != NULL) pf_remove_src_node(sns[i]); return (PF_DROP); } int pf_translate(struct pf_pdesc *pd, struct pf_addr *saddr, u_int16_t sport, struct pf_addr *daddr, u_int16_t dport, u_int16_t virtual_type, int icmp_dir) { int rewrite = 0; int afto = pd->af != pd->naf; if (afto || PF_ANEQ(daddr, pd->dst, pd->af)) pd->destchg = 1; switch (pd->proto) { case IPPROTO_TCP: /* FALLTHROUGH */ case IPPROTO_UDP: rewrite += pf_patch_16(pd, pd->sport, sport); rewrite += pf_patch_16(pd, pd->dport, dport); break; case IPPROTO_ICMP: if (pd->af != AF_INET) return (0); #ifdef INET6 if (afto) { if (pf_translate_icmp_af(pd, AF_INET6, &pd->hdr.icmp)) return (0); pd->proto = IPPROTO_ICMPV6; rewrite = 1; } #endif /* INET6 */ if (virtual_type == htons(ICMP_ECHO)) { u_int16_t icmpid = (icmp_dir == PF_IN) ? sport : dport; rewrite += pf_patch_16(pd, &pd->hdr.icmp.icmp_id, icmpid); } break; #ifdef INET6 case IPPROTO_ICMPV6: if (pd->af != AF_INET6) return (0); if (afto) { if (pf_translate_icmp_af(pd, AF_INET, &pd->hdr.icmp6)) return (0); pd->proto = IPPROTO_ICMP; rewrite = 1; } if (virtual_type == htons(ICMP6_ECHO_REQUEST)) { u_int16_t icmpid = (icmp_dir == PF_IN) ? sport : dport; rewrite += pf_patch_16(pd, &pd->hdr.icmp6.icmp6_id, icmpid); } break; #endif /* INET6 */ } if (!afto) { rewrite += pf_translate_a(pd, pd->src, saddr); rewrite += pf_translate_a(pd, pd->dst, daddr); } return (rewrite); } int pf_tcp_track_full(struct pf_pdesc *pd, struct pf_state **stp, u_short *reason, int *copyback, int reverse) { struct tcphdr *th = &pd->hdr.tcp; struct pf_state_peer *src, *dst; u_int16_t win = ntohs(th->th_win); u_int32_t ack, end, data_end, seq, orig_seq; u_int8_t sws, dws, psrc, pdst; int ackskew; if ((pd->dir == (*stp)->direction && !reverse) || (pd->dir != (*stp)->direction && reverse)) { src = &(*stp)->src; dst = &(*stp)->dst; psrc = PF_PEER_SRC; pdst = PF_PEER_DST; } else { src = &(*stp)->dst; dst = &(*stp)->src; psrc = PF_PEER_DST; pdst = PF_PEER_SRC; } if (src->wscale && dst->wscale && !(th->th_flags & TH_SYN)) { sws = src->wscale & PF_WSCALE_MASK; dws = dst->wscale & PF_WSCALE_MASK; } else sws = dws = 0; /* * Sequence tracking algorithm from Guido van Rooij's paper: * http://www.madison-gurkha.com/publications/tcp_filtering/ * tcp_filtering.ps */ orig_seq = seq = ntohl(th->th_seq); if (src->seqlo == 0) { /* First packet from this end. Set its state */ if (((*stp)->state_flags & PFSTATE_SCRUB_TCP || dst->scrub) && src->scrub == NULL) { if (pf_normalize_tcp_init(pd, src)) { REASON_SET(reason, PFRES_MEMORY); return (PF_DROP); } } /* Deferred generation of sequence number modulator */ if (dst->seqdiff && !src->seqdiff) { /* use random iss for the TCP server */ while ((src->seqdiff = arc4random() - seq) == 0) continue; ack = ntohl(th->th_ack) - dst->seqdiff; pf_patch_32(pd, &th->th_seq, htonl(seq + src->seqdiff)); pf_patch_32(pd, &th->th_ack, htonl(ack)); *copyback = 1; } else { ack = ntohl(th->th_ack); } end = seq + pd->p_len; if (th->th_flags & TH_SYN) { end++; if (dst->wscale & PF_WSCALE_FLAG) { src->wscale = pf_get_wscale(pd); if (src->wscale & PF_WSCALE_FLAG) { /* Remove scale factor from initial * window */ sws = src->wscale & PF_WSCALE_MASK; win = ((u_int32_t)win + (1 << sws) - 1) >> sws; dws = dst->wscale & PF_WSCALE_MASK; } else { /* fixup other window */ dst->max_win = MIN(TCP_MAXWIN, (u_int32_t)dst->max_win << (dst->wscale & PF_WSCALE_MASK)); /* in case of a retrans SYN|ACK */ dst->wscale = 0; } } } data_end = end; if (th->th_flags & TH_FIN) end++; src->seqlo = seq; if (src->state < TCPS_SYN_SENT) pf_set_protostate(*stp, psrc, TCPS_SYN_SENT); /* * May need to slide the window (seqhi may have been set by * the crappy stack check or if we picked up the connection * after establishment) */ if (src->seqhi == 1 || SEQ_GEQ(end + MAX(1, dst->max_win << dws), src->seqhi)) src->seqhi = end + MAX(1, dst->max_win << dws); if (win > src->max_win) src->max_win = win; } else { ack = ntohl(th->th_ack) - dst->seqdiff; if (src->seqdiff) { /* Modulate sequence numbers */ pf_patch_32(pd, &th->th_seq, htonl(seq + src->seqdiff)); pf_patch_32(pd, &th->th_ack, htonl(ack)); *copyback = 1; } end = seq + pd->p_len; if (th->th_flags & TH_SYN) end++; data_end = end; if (th->th_flags & TH_FIN) end++; } if ((th->th_flags & TH_ACK) == 0) { /* Let it pass through the ack skew check */ ack = dst->seqlo; } else if ((ack == 0 && (th->th_flags & (TH_ACK|TH_RST)) == (TH_ACK|TH_RST)) || /* broken tcp stacks do not set ack */ (dst->state < TCPS_SYN_SENT)) { /* * Many stacks (ours included) will set the ACK number in an * FIN|ACK if the SYN times out -- no sequence to ACK. */ ack = dst->seqlo; } if (seq == end) { /* Ease sequencing restrictions on no data packets */ seq = src->seqlo; data_end = end = seq; } ackskew = dst->seqlo - ack; /* * Need to demodulate the sequence numbers in any TCP SACK options * (Selective ACK). We could optionally validate the SACK values * against the current ACK window, either forwards or backwards, but * I'm not confident that SACK has been implemented properly * everywhere. It wouldn't surprise me if several stacks accidently * SACK too far backwards of previously ACKed data. There really aren't * any security implications of bad SACKing unless the target stack * doesn't validate the option length correctly. Someone trying to * spoof into a TCP connection won't bother blindly sending SACK * options anyway. */ if (dst->seqdiff && (th->th_off << 2) > sizeof(struct tcphdr)) { if (pf_modulate_sack(pd, dst)) *copyback = 1; } #define MAXACKWINDOW (0xffff + 1500) /* 1500 is an arbitrary fudge factor */ if (SEQ_GEQ(src->seqhi, data_end) && /* Last octet inside other's window space */ SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)) && /* Retrans: not more than one window back */ (ackskew >= -MAXACKWINDOW) && /* Acking not more than one reassembled fragment backwards */ (ackskew <= (MAXACKWINDOW << sws)) && /* Acking not more than one window forward */ ((th->th_flags & TH_RST) == 0 || orig_seq == src->seqlo || (orig_seq == src->seqlo + 1) || (orig_seq + 1 == src->seqlo))) { /* Require an exact/+1 sequence match on resets when possible */ if (dst->scrub || src->scrub) { if (pf_normalize_tcp_stateful(pd, reason, *stp, src, dst, copyback)) return (PF_DROP); } /* update max window */ if (src->max_win < win) src->max_win = win; /* synchronize sequencing */ if (SEQ_GT(end, src->seqlo)) src->seqlo = end; /* slide the window of what the other end can send */ if (SEQ_GEQ(ack + (win << sws), dst->seqhi)) dst->seqhi = ack + MAX((win << sws), 1); /* update states */ if (th->th_flags & TH_SYN) if (src->state < TCPS_SYN_SENT) pf_set_protostate(*stp, psrc, TCPS_SYN_SENT); if (th->th_flags & TH_FIN) if (src->state < TCPS_CLOSING) pf_set_protostate(*stp, psrc, TCPS_CLOSING); if (th->th_flags & TH_ACK) { if (dst->state == TCPS_SYN_SENT) { pf_set_protostate(*stp, pdst, TCPS_ESTABLISHED); if (src->state == TCPS_ESTABLISHED && !SLIST_EMPTY(&(*stp)->src_nodes) && pf_src_connlimit(stp)) { REASON_SET(reason, PFRES_SRCLIMIT); return (PF_DROP); } } else if (dst->state == TCPS_CLOSING) pf_set_protostate(*stp, pdst, TCPS_FIN_WAIT_2); } if (th->th_flags & TH_RST) pf_set_protostate(*stp, PF_PEER_BOTH, TCPS_TIME_WAIT); /* update expire time */ (*stp)->expire = getuptime(); if (src->state >= TCPS_FIN_WAIT_2 && dst->state >= TCPS_FIN_WAIT_2) pf_update_state_timeout(*stp, PFTM_TCP_CLOSED); else if (src->state >= TCPS_CLOSING && dst->state >= TCPS_CLOSING) pf_update_state_timeout(*stp, PFTM_TCP_FIN_WAIT); else if (src->state < TCPS_ESTABLISHED || dst->state < TCPS_ESTABLISHED) pf_update_state_timeout(*stp, PFTM_TCP_OPENING); else if (src->state >= TCPS_CLOSING || dst->state >= TCPS_CLOSING) pf_update_state_timeout(*stp, PFTM_TCP_CLOSING); else pf_update_state_timeout(*stp, PFTM_TCP_ESTABLISHED); /* Fall through to PASS packet */ } else if ((dst->state < TCPS_SYN_SENT || dst->state >= TCPS_FIN_WAIT_2 || src->state >= TCPS_FIN_WAIT_2) && SEQ_GEQ(src->seqhi + MAXACKWINDOW, data_end) && /* Within a window forward of the originating packet */ SEQ_GEQ(seq, src->seqlo - MAXACKWINDOW)) { /* Within a window backward of the originating packet */ /* * This currently handles three situations: * 1) Stupid stacks will shotgun SYNs before their peer * replies. * 2) When PF catches an already established stream (the * firewall rebooted, the state table was flushed, routes * changed...) * 3) Packets get funky immediately after the connection * closes (this should catch Solaris spurious ACK|FINs * that web servers like to spew after a close) * * This must be a little more careful than the above code * since packet floods will also be caught here. We don't * update the TTL here to mitigate the damage of a packet * flood and so the same code can handle awkward establishment * and a loosened connection close. * In the establishment case, a correct peer response will * validate the connection, go through the normal state code * and keep updating the state TTL. */ if (pf_status.debug >= LOG_NOTICE) { log(LOG_NOTICE, "pf: loose state match: "); pf_print_state(*stp); pf_print_flags(th->th_flags); addlog(" seq=%u (%u) ack=%u len=%u ackskew=%d " "pkts=%llu:%llu dir=%s,%s\n", seq, orig_seq, ack, pd->p_len, ackskew, (*stp)->packets[0], (*stp)->packets[1], pd->dir == PF_IN ? "in" : "out", pd->dir == (*stp)->direction ? "fwd" : "rev"); } if (dst->scrub || src->scrub) { if (pf_normalize_tcp_stateful(pd, reason, *stp, src, dst, copyback)) return (PF_DROP); } /* update max window */ if (src->max_win < win) src->max_win = win; /* synchronize sequencing */ if (SEQ_GT(end, src->seqlo)) src->seqlo = end; /* slide the window of what the other end can send */ if (SEQ_GEQ(ack + (win << sws), dst->seqhi)) dst->seqhi = ack + MAX((win << sws), 1); /* * Cannot set dst->seqhi here since this could be a shotgunned * SYN and not an already established connection. */ if (th->th_flags & TH_FIN) if (src->state < TCPS_CLOSING) pf_set_protostate(*stp, psrc, TCPS_CLOSING); if (th->th_flags & TH_RST) pf_set_protostate(*stp, PF_PEER_BOTH, TCPS_TIME_WAIT); /* Fall through to PASS packet */ } else { if ((*stp)->dst.state == TCPS_SYN_SENT && (*stp)->src.state == TCPS_SYN_SENT) { /* Send RST for state mismatches during handshake */ if (!(th->th_flags & TH_RST)) pf_send_tcp((*stp)->rule.ptr, pd->af, pd->dst, pd->src, th->th_dport, th->th_sport, ntohl(th->th_ack), 0, TH_RST, 0, 0, (*stp)->rule.ptr->return_ttl, 1, 0, pd->rdomain); src->seqlo = 0; src->seqhi = 1; src->max_win = 1; } else if (pf_status.debug >= LOG_NOTICE) { log(LOG_NOTICE, "pf: BAD state: "); pf_print_state(*stp); pf_print_flags(th->th_flags); addlog(" seq=%u (%u) ack=%u len=%u ackskew=%d " "pkts=%llu:%llu dir=%s,%s\n", seq, orig_seq, ack, pd->p_len, ackskew, (*stp)->packets[0], (*stp)->packets[1], pd->dir == PF_IN ? "in" : "out", pd->dir == (*stp)->direction ? "fwd" : "rev"); addlog("pf: State failure on: %c %c %c %c | %c %c\n", SEQ_GEQ(src->seqhi, data_end) ? ' ' : '1', SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)) ? ' ': '2', (ackskew >= -MAXACKWINDOW) ? ' ' : '3', (ackskew <= (MAXACKWINDOW << sws)) ? ' ' : '4', SEQ_GEQ(src->seqhi + MAXACKWINDOW, data_end) ? ' ' :'5', SEQ_GEQ(seq, src->seqlo - MAXACKWINDOW) ?' ' :'6'); } REASON_SET(reason, PFRES_BADSTATE); return (PF_DROP); } return (PF_PASS); } int pf_tcp_track_sloppy(struct pf_pdesc *pd, struct pf_state **stp, u_short *reason) { struct tcphdr *th = &pd->hdr.tcp; struct pf_state_peer *src, *dst; u_int8_t psrc, pdst; if (pd->dir == (*stp)->direction) { src = &(*stp)->src; dst = &(*stp)->dst; psrc = PF_PEER_SRC; pdst = PF_PEER_DST; } else { src = &(*stp)->dst; dst = &(*stp)->src; psrc = PF_PEER_DST; pdst = PF_PEER_SRC; } if (th->th_flags & TH_SYN) if (src->state < TCPS_SYN_SENT) pf_set_protostate(*stp, psrc, TCPS_SYN_SENT); if (th->th_flags & TH_FIN) if (src->state < TCPS_CLOSING) pf_set_protostate(*stp, psrc, TCPS_CLOSING); if (th->th_flags & TH_ACK) { if (dst->state == TCPS_SYN_SENT) { pf_set_protostate(*stp, pdst, TCPS_ESTABLISHED); if (src->state == TCPS_ESTABLISHED && !SLIST_EMPTY(&(*stp)->src_nodes) && pf_src_connlimit(stp)) { REASON_SET(reason, PFRES_SRCLIMIT); return (PF_DROP); } } else if (dst->state == TCPS_CLOSING) { pf_set_protostate(*stp, pdst, TCPS_FIN_WAIT_2); } else if (src->state == TCPS_SYN_SENT && dst->state < TCPS_SYN_SENT) { /* * Handle a special sloppy case where we only see one * half of the connection. If there is a ACK after * the initial SYN without ever seeing a packet from * the destination, set the connection to established. */ pf_set_protostate(*stp, PF_PEER_BOTH, TCPS_ESTABLISHED); if (!SLIST_EMPTY(&(*stp)->src_nodes) && pf_src_connlimit(stp)) { REASON_SET(reason, PFRES_SRCLIMIT); return (PF_DROP); } } else if (src->state == TCPS_CLOSING && dst->state == TCPS_ESTABLISHED && dst->seqlo == 0) { /* * Handle the closing of half connections where we * don't see the full bidirectional FIN/ACK+ACK * handshake. */ pf_set_protostate(*stp, pdst, TCPS_CLOSING); } } if (th->th_flags & TH_RST) pf_set_protostate(*stp, PF_PEER_BOTH, TCPS_TIME_WAIT); /* update expire time */ (*stp)->expire = getuptime(); if (src->state >= TCPS_FIN_WAIT_2 && dst->state >= TCPS_FIN_WAIT_2) pf_update_state_timeout(*stp, PFTM_TCP_CLOSED); else if (src->state >= TCPS_CLOSING && dst->state >= TCPS_CLOSING) pf_update_state_timeout(*stp, PFTM_TCP_FIN_WAIT); else if (src->state < TCPS_ESTABLISHED || dst->state < TCPS_ESTABLISHED) pf_update_state_timeout(*stp, PFTM_TCP_OPENING); else if (src->state >= TCPS_CLOSING || dst->state >= TCPS_CLOSING) pf_update_state_timeout(*stp, PFTM_TCP_CLOSING); else pf_update_state_timeout(*stp, PFTM_TCP_ESTABLISHED); return (PF_PASS); } static __inline int pf_synproxy(struct pf_pdesc *pd, struct pf_state **stp, u_short *reason) { struct pf_state_key *sk = (*stp)->key[pd->didx]; if ((*stp)->src.state == PF_TCPS_PROXY_SRC) { struct tcphdr *th = &pd->hdr.tcp; if (pd->dir != (*stp)->direction) { REASON_SET(reason, PFRES_SYNPROXY); return (PF_SYNPROXY_DROP); } if (th->th_flags & TH_SYN) { if (ntohl(th->th_seq) != (*stp)->src.seqlo) { REASON_SET(reason, PFRES_SYNPROXY); return (PF_DROP); } pf_send_tcp((*stp)->rule.ptr, pd->af, pd->dst, pd->src, th->th_dport, th->th_sport, (*stp)->src.seqhi, ntohl(th->th_seq) + 1, TH_SYN|TH_ACK, 0, (*stp)->src.mss, 0, 1, 0, pd->rdomain); REASON_SET(reason, PFRES_SYNPROXY); return (PF_SYNPROXY_DROP); } else if ((th->th_flags & (TH_ACK|TH_RST|TH_FIN)) != TH_ACK || (ntohl(th->th_ack) != (*stp)->src.seqhi + 1) || (ntohl(th->th_seq) != (*stp)->src.seqlo + 1)) { REASON_SET(reason, PFRES_SYNPROXY); return (PF_DROP); } else if (!SLIST_EMPTY(&(*stp)->src_nodes) && pf_src_connlimit(stp)) { REASON_SET(reason, PFRES_SRCLIMIT); return (PF_DROP); } else pf_set_protostate(*stp, PF_PEER_SRC, PF_TCPS_PROXY_DST); } if ((*stp)->src.state == PF_TCPS_PROXY_DST) { struct tcphdr *th = &pd->hdr.tcp; if (pd->dir == (*stp)->direction) { if (((th->th_flags & (TH_SYN|TH_ACK)) != TH_ACK) || (ntohl(th->th_ack) != (*stp)->src.seqhi + 1) || (ntohl(th->th_seq) != (*stp)->src.seqlo + 1)) { REASON_SET(reason, PFRES_SYNPROXY); return (PF_DROP); } (*stp)->src.max_win = MAX(ntohs(th->th_win), 1); if ((*stp)->dst.seqhi == 1) (*stp)->dst.seqhi = arc4random(); pf_send_tcp((*stp)->rule.ptr, pd->af, &sk->addr[pd->sidx], &sk->addr[pd->didx], sk->port[pd->sidx], sk->port[pd->didx], (*stp)->dst.seqhi, 0, TH_SYN, 0, (*stp)->src.mss, 0, 0, (*stp)->tag, sk->rdomain); REASON_SET(reason, PFRES_SYNPROXY); return (PF_SYNPROXY_DROP); } else if (((th->th_flags & (TH_SYN|TH_ACK)) != (TH_SYN|TH_ACK)) || (ntohl(th->th_ack) != (*stp)->dst.seqhi + 1)) { REASON_SET(reason, PFRES_SYNPROXY); return (PF_DROP); } else { (*stp)->dst.max_win = MAX(ntohs(th->th_win), 1); (*stp)->dst.seqlo = ntohl(th->th_seq); pf_send_tcp((*stp)->rule.ptr, pd->af, pd->dst, pd->src, th->th_dport, th->th_sport, ntohl(th->th_ack), ntohl(th->th_seq) + 1, TH_ACK, (*stp)->src.max_win, 0, 0, 0, (*stp)->tag, pd->rdomain); pf_send_tcp((*stp)->rule.ptr, pd->af, &sk->addr[pd->sidx], &sk->addr[pd->didx], sk->port[pd->sidx], sk->port[pd->didx], (*stp)->src.seqhi + 1, (*stp)->src.seqlo + 1, TH_ACK, (*stp)->dst.max_win, 0, 0, 1, 0, sk->rdomain); (*stp)->src.seqdiff = (*stp)->dst.seqhi - (*stp)->src.seqlo; (*stp)->dst.seqdiff = (*stp)->src.seqhi - (*stp)->dst.seqlo; (*stp)->src.seqhi = (*stp)->src.seqlo + (*stp)->dst.max_win; (*stp)->dst.seqhi = (*stp)->dst.seqlo + (*stp)->src.max_win; (*stp)->src.wscale = (*stp)->dst.wscale = 0; pf_set_protostate(*stp, PF_PEER_BOTH, TCPS_ESTABLISHED); REASON_SET(reason, PFRES_SYNPROXY); return (PF_SYNPROXY_DROP); } } return (PF_PASS); } int pf_test_state(struct pf_pdesc *pd, struct pf_state **stp, u_short *reason) { int copyback = 0; struct pf_state_peer *src, *dst; int action; struct inpcb *inp = pd->m->m_pkthdr.pf.inp; u_int8_t psrc, pdst; action = PF_PASS; if (pd->dir == (*stp)->direction) { src = &(*stp)->src; dst = &(*stp)->dst; psrc = PF_PEER_SRC; pdst = PF_PEER_DST; } else { src = &(*stp)->dst; dst = &(*stp)->src; psrc = PF_PEER_DST; pdst = PF_PEER_SRC; } switch (pd->virtual_proto) { case IPPROTO_TCP: if ((action = pf_synproxy(pd, stp, reason)) != PF_PASS) return (action); if ((pd->hdr.tcp.th_flags & (TH_SYN|TH_ACK)) == TH_SYN) { if (dst->state >= TCPS_FIN_WAIT_2 && src->state >= TCPS_FIN_WAIT_2) { if (pf_status.debug >= LOG_NOTICE) { log(LOG_NOTICE, "pf: state reuse "); pf_print_state(*stp); pf_print_flags(pd->hdr.tcp.th_flags); addlog("\n"); } /* XXX make sure it's the same direction ?? */ pf_update_state_timeout(*stp, PFTM_PURGE); pf_state_unref(*stp); *stp = NULL; pf_mbuf_link_inpcb(pd->m, inp); return (PF_DROP); } else if (dst->state >= TCPS_ESTABLISHED && src->state >= TCPS_ESTABLISHED) { /* * SYN matches existing state??? * Typically happens when sender boots up after * sudden panic. Certain protocols (NFSv3) are * always using same port numbers. Challenge * ACK enables all parties (firewall and peers) * to get in sync again. */ pf_send_challenge_ack(pd, *stp, src, dst); return (PF_DROP); } } if ((*stp)->state_flags & PFSTATE_SLOPPY) { if (pf_tcp_track_sloppy(pd, stp, reason) == PF_DROP) return (PF_DROP); } else { if (pf_tcp_track_full(pd, stp, reason, &copyback, PF_REVERSED_KEY((*stp)->key, pd->af)) == PF_DROP) return (PF_DROP); } break; case IPPROTO_UDP: /* update states */ if (src->state < PFUDPS_SINGLE) pf_set_protostate(*stp, psrc, PFUDPS_SINGLE); if (dst->state == PFUDPS_SINGLE) pf_set_protostate(*stp, pdst, PFUDPS_MULTIPLE); /* update expire time */ (*stp)->expire = getuptime(); if (src->state == PFUDPS_MULTIPLE && dst->state == PFUDPS_MULTIPLE) pf_update_state_timeout(*stp, PFTM_UDP_MULTIPLE); else pf_update_state_timeout(*stp, PFTM_UDP_SINGLE); break; default: /* update states */ if (src->state < PFOTHERS_SINGLE) pf_set_protostate(*stp, psrc, PFOTHERS_SINGLE); if (dst->state == PFOTHERS_SINGLE) pf_set_protostate(*stp, pdst, PFOTHERS_MULTIPLE); /* update expire time */ (*stp)->expire = getuptime(); if (src->state == PFOTHERS_MULTIPLE && dst->state == PFOTHERS_MULTIPLE) pf_update_state_timeout(*stp, PFTM_OTHER_MULTIPLE); else pf_update_state_timeout(*stp, PFTM_OTHER_SINGLE); break; } /* translate source/destination address, if necessary */ if ((*stp)->key[PF_SK_WIRE] != (*stp)->key[PF_SK_STACK]) { struct pf_state_key *nk; int afto, sidx, didx; if (PF_REVERSED_KEY((*stp)->key, pd->af)) nk = (*stp)->key[pd->sidx]; else nk = (*stp)->key[pd->didx]; afto = pd->af != nk->af; sidx = afto ? pd->didx : pd->sidx; didx = afto ? pd->sidx : pd->didx; #ifdef INET6 if (afto) { pf_addrcpy(&pd->nsaddr, &nk->addr[sidx], nk->af); pf_addrcpy(&pd->ndaddr, &nk->addr[didx], nk->af); pd->naf = nk->af; action = PF_AFRT; } #endif /* INET6 */ if (!afto) pf_translate_a(pd, pd->src, &nk->addr[sidx]); if (pd->sport != NULL) pf_patch_16(pd, pd->sport, nk->port[sidx]); if (afto || PF_ANEQ(pd->dst, &nk->addr[didx], pd->af) || pd->rdomain != nk->rdomain) pd->destchg = 1; if (!afto) pf_translate_a(pd, pd->dst, &nk->addr[didx]); if (pd->dport != NULL) pf_patch_16(pd, pd->dport, nk->port[didx]); pd->m->m_pkthdr.ph_rtableid = nk->rdomain; copyback = 1; } if (copyback && pd->hdrlen > 0) { m_copyback(pd->m, pd->off, pd->hdrlen, &pd->hdr, M_NOWAIT); } return (action); } int pf_icmp_state_lookup(struct pf_pdesc *pd, struct pf_state_key_cmp *key, struct pf_state **stp, u_int16_t icmpid, u_int16_t type, int icmp_dir, int *iidx, int multi, int inner) { int direction, action; key->af = pd->af; key->proto = pd->proto; key->rdomain = pd->rdomain; if (icmp_dir == PF_IN) { *iidx = pd->sidx; key->port[pd->sidx] = icmpid; key->port[pd->didx] = type; } else { *iidx = pd->didx; key->port[pd->sidx] = type; key->port[pd->didx] = icmpid; } if (pf_state_key_addr_setup(pd, key, pd->sidx, pd->src, pd->didx, pd->dst, pd->af, multi)) return (PF_DROP); key->hash = pf_pkt_hash(key->af, key->proto, &key->addr[0], &key->addr[1], 0, 0); action = pf_find_state(pd, key, stp); if (action != PF_MATCH) return (action); if ((*stp)->state_flags & PFSTATE_SLOPPY) return (-1); /* Is this ICMP message flowing in right direction? */ if ((*stp)->key[PF_SK_WIRE]->af != (*stp)->key[PF_SK_STACK]->af) direction = (pd->af == (*stp)->key[PF_SK_WIRE]->af) ? PF_IN : PF_OUT; else direction = (*stp)->direction; if ((((!inner && direction == pd->dir) || (inner && direction != pd->dir)) ? PF_IN : PF_OUT) != icmp_dir) { if (pf_status.debug >= LOG_NOTICE) { log(LOG_NOTICE, "pf: icmp type %d in wrong direction (%d): ", ntohs(type), icmp_dir); pf_print_state(*stp); addlog("\n"); } return (PF_DROP); } return (-1); } int pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **stp, u_short *reason) { u_int16_t virtual_id, virtual_type; u_int8_t icmptype, icmpcode; int icmp_dir, iidx, ret, copyback = 0; struct pf_state_key_cmp key; switch (pd->proto) { case IPPROTO_ICMP: icmptype = pd->hdr.icmp.icmp_type; icmpcode = pd->hdr.icmp.icmp_code; break; #ifdef INET6 case IPPROTO_ICMPV6: icmptype = pd->hdr.icmp6.icmp6_type; icmpcode = pd->hdr.icmp6.icmp6_code; break; #endif /* INET6 */ default: panic("unhandled proto %d", pd->proto); } if (pf_icmp_mapping(pd, icmptype, &icmp_dir, &virtual_id, &virtual_type) == 0) { /* * ICMP query/reply message not related to a TCP/UDP packet. * Search for an ICMP state. */ ret = pf_icmp_state_lookup(pd, &key, stp, virtual_id, virtual_type, icmp_dir, &iidx, 0, 0); /* IPv6? try matching a multicast address */ if (ret == PF_DROP && pd->af == AF_INET6 && icmp_dir == PF_OUT) ret = pf_icmp_state_lookup(pd, &key, stp, virtual_id, virtual_type, icmp_dir, &iidx, 1, 0); if (ret >= 0) return (ret); (*stp)->expire = getuptime(); pf_update_state_timeout(*stp, PFTM_ICMP_ERROR_REPLY); /* translate source/destination address, if necessary */ if ((*stp)->key[PF_SK_WIRE] != (*stp)->key[PF_SK_STACK]) { struct pf_state_key *nk; int afto, sidx, didx; if (PF_REVERSED_KEY((*stp)->key, pd->af)) nk = (*stp)->key[pd->sidx]; else nk = (*stp)->key[pd->didx]; afto = pd->af != nk->af; sidx = afto ? pd->didx : pd->sidx; didx = afto ? pd->sidx : pd->didx; iidx = afto ? !iidx : iidx; #ifdef INET6 if (afto) { pf_addrcpy(&pd->nsaddr, &nk->addr[sidx], nk->af); pf_addrcpy(&pd->ndaddr, &nk->addr[didx], nk->af); pd->naf = nk->af; } #endif /* INET6 */ if (!afto) { pf_translate_a(pd, pd->src, &nk->addr[sidx]); pf_translate_a(pd, pd->dst, &nk->addr[didx]); } if (pd->rdomain != nk->rdomain) pd->destchg = 1; if (!afto && PF_ANEQ(pd->dst, &nk->addr[didx], pd->af)) pd->destchg = 1; pd->m->m_pkthdr.ph_rtableid = nk->rdomain; switch (pd->af) { case AF_INET: #ifdef INET6 if (afto) { if (pf_translate_icmp_af(pd, AF_INET6, &pd->hdr.icmp)) return (PF_DROP); pd->proto = IPPROTO_ICMPV6; } #endif /* INET6 */ pf_patch_16(pd, &pd->hdr.icmp.icmp_id, nk->port[iidx]); m_copyback(pd->m, pd->off, ICMP_MINLEN, &pd->hdr.icmp, M_NOWAIT); copyback = 1; break; #ifdef INET6 case AF_INET6: if (afto) { if (pf_translate_icmp_af(pd, AF_INET, &pd->hdr.icmp6)) return (PF_DROP); pd->proto = IPPROTO_ICMP; } pf_patch_16(pd, &pd->hdr.icmp6.icmp6_id, nk->port[iidx]); m_copyback(pd->m, pd->off, sizeof(struct icmp6_hdr), &pd->hdr.icmp6, M_NOWAIT); copyback = 1; break; #endif /* INET6 */ } #ifdef INET6 if (afto) return (PF_AFRT); #endif /* INET6 */ } } else { /* * ICMP error message in response to a TCP/UDP packet. * Extract the inner TCP/UDP header and search for that state. */ struct pf_pdesc pd2; struct ip h2; #ifdef INET6 struct ip6_hdr h2_6; #endif /* INET6 */ int ipoff2; /* Initialize pd2 fields valid for both packets with pd. */ memset(&pd2, 0, sizeof(pd2)); pd2.af = pd->af; pd2.dir = pd->dir; pd2.kif = pd->kif; pd2.m = pd->m; pd2.rdomain = pd->rdomain; /* Payload packet is from the opposite direction. */ pd2.sidx = (pd2.dir == PF_IN) ? 1 : 0; pd2.didx = (pd2.dir == PF_IN) ? 0 : 1; switch (pd->af) { case AF_INET: /* offset of h2 in mbuf chain */ ipoff2 = pd->off + ICMP_MINLEN; if (!pf_pull_hdr(pd2.m, ipoff2, &h2, sizeof(h2), reason, pd2.af)) { DPFPRINTF(LOG_NOTICE, "ICMP error message too short (ip)"); return (PF_DROP); } /* * ICMP error messages don't refer to non-first * fragments */ if (h2.ip_off & htons(IP_OFFMASK)) { REASON_SET(reason, PFRES_FRAG); return (PF_DROP); } /* offset of protocol header that follows h2 */ pd2.off = ipoff2; if (pf_walk_header(&pd2, &h2, reason) != PF_PASS) return (PF_DROP); pd2.tot_len = ntohs(h2.ip_len); pd2.src = (struct pf_addr *)&h2.ip_src; pd2.dst = (struct pf_addr *)&h2.ip_dst; break; #ifdef INET6 case AF_INET6: ipoff2 = pd->off + sizeof(struct icmp6_hdr); if (!pf_pull_hdr(pd2.m, ipoff2, &h2_6, sizeof(h2_6), reason, pd2.af)) { DPFPRINTF(LOG_NOTICE, "ICMP error message too short (ip6)"); return (PF_DROP); } pd2.off = ipoff2; if (pf_walk_header6(&pd2, &h2_6, reason) != PF_PASS) return (PF_DROP); pd2.tot_len = ntohs(h2_6.ip6_plen) + sizeof(struct ip6_hdr); pd2.src = (struct pf_addr *)&h2_6.ip6_src; pd2.dst = (struct pf_addr *)&h2_6.ip6_dst; break; #endif /* INET6 */ default: unhandled_af(pd->af); } if (PF_ANEQ(pd->dst, pd2.src, pd->af)) { if (pf_status.debug >= LOG_NOTICE) { log(LOG_NOTICE, "pf: BAD ICMP %d:%d outer dst: ", icmptype, icmpcode); pf_print_host(pd->src, 0, pd->af); addlog(" -> "); pf_print_host(pd->dst, 0, pd->af); addlog(" inner src: "); pf_print_host(pd2.src, 0, pd2.af); addlog(" -> "); pf_print_host(pd2.dst, 0, pd2.af); addlog("\n"); } REASON_SET(reason, PFRES_BADSTATE); return (PF_DROP); } switch (pd2.proto) { case IPPROTO_TCP: { struct tcphdr *th = &pd2.hdr.tcp; u_int32_t seq; struct pf_state_peer *src, *dst; u_int8_t dws; int action; /* * Only the first 8 bytes of the TCP header can be * expected. Don't access any TCP header fields after * th_seq, an ackskew test is not possible. */ if (!pf_pull_hdr(pd2.m, pd2.off, th, 8, reason, pd2.af)) { DPFPRINTF(LOG_NOTICE, "ICMP error message too short (tcp)"); return (PF_DROP); } key.af = pd2.af; key.proto = IPPROTO_TCP; key.rdomain = pd2.rdomain; pf_addrcpy(&key.addr[pd2.sidx], pd2.src, key.af); pf_addrcpy(&key.addr[pd2.didx], pd2.dst, key.af); key.port[pd2.sidx] = th->th_sport; key.port[pd2.didx] = th->th_dport; key.hash = pf_pkt_hash(pd2.af, pd2.proto, pd2.src, pd2.dst, th->th_sport, th->th_dport); action = pf_find_state(&pd2, &key, stp); if (action != PF_MATCH) return (action); if (pd2.dir == (*stp)->direction) { if (PF_REVERSED_KEY((*stp)->key, pd->af)) { src = &(*stp)->src; dst = &(*stp)->dst; } else { src = &(*stp)->dst; dst = &(*stp)->src; } } else { if (PF_REVERSED_KEY((*stp)->key, pd->af)) { src = &(*stp)->dst; dst = &(*stp)->src; } else { src = &(*stp)->src; dst = &(*stp)->dst; } } if (src->wscale && dst->wscale) dws = dst->wscale & PF_WSCALE_MASK; else dws = 0; /* Demodulate sequence number */ seq = ntohl(th->th_seq) - src->seqdiff; if (src->seqdiff) { pf_patch_32(pd, &th->th_seq, htonl(seq)); copyback = 1; } if (!((*stp)->state_flags & PFSTATE_SLOPPY) && (!SEQ_GEQ(src->seqhi, seq) || !SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)))) { if (pf_status.debug >= LOG_NOTICE) { log(LOG_NOTICE, "pf: BAD ICMP %d:%d ", icmptype, icmpcode); pf_print_host(pd->src, 0, pd->af); addlog(" -> "); pf_print_host(pd->dst, 0, pd->af); addlog(" state: "); pf_print_state(*stp); addlog(" seq=%u\n", seq); } REASON_SET(reason, PFRES_BADSTATE); return (PF_DROP); } else { if (pf_status.debug >= LOG_DEBUG) { log(LOG_DEBUG, "pf: OK ICMP %d:%d ", icmptype, icmpcode); pf_print_host(pd->src, 0, pd->af); addlog(" -> "); pf_print_host(pd->dst, 0, pd->af); addlog(" state: "); pf_print_state(*stp); addlog(" seq=%u\n", seq); } } /* translate source/destination address, if necessary */ if ((*stp)->key[PF_SK_WIRE] != (*stp)->key[PF_SK_STACK]) { struct pf_state_key *nk; int afto, sidx, didx; if (PF_REVERSED_KEY((*stp)->key, pd->af)) nk = (*stp)->key[pd->sidx]; else nk = (*stp)->key[pd->didx]; afto = pd->af != nk->af; sidx = afto ? pd2.didx : pd2.sidx; didx = afto ? pd2.sidx : pd2.didx; #ifdef INET6 if (afto) { if (pf_translate_icmp_af(pd, nk->af, &pd->hdr.icmp)) return (PF_DROP); m_copyback(pd->m, pd->off, sizeof(struct icmp6_hdr), &pd->hdr.icmp6, M_NOWAIT); if (pf_change_icmp_af(pd->m, ipoff2, pd, &pd2, &nk->addr[sidx], &nk->addr[didx], pd->af, nk->af)) return (PF_DROP); if (nk->af == AF_INET) pd->proto = IPPROTO_ICMP; else pd->proto = IPPROTO_ICMPV6; pd->m->m_pkthdr.ph_rtableid = nk->rdomain; pd->destchg = 1; pf_addrcpy(&pd->nsaddr, &nk->addr[pd2.sidx], nk->af); pf_addrcpy(&pd->ndaddr, &nk->addr[pd2.didx], nk->af); pd->naf = nk->af; pf_patch_16(pd, &th->th_sport, nk->port[sidx]); pf_patch_16(pd, &th->th_dport, nk->port[didx]); m_copyback(pd2.m, pd2.off, 8, th, M_NOWAIT); return (PF_AFRT); } #endif /* INET6 */ if (PF_ANEQ(pd2.src, &nk->addr[pd2.sidx], pd2.af) || nk->port[pd2.sidx] != th->th_sport) pf_translate_icmp(pd, pd2.src, &th->th_sport, pd->dst, &nk->addr[pd2.sidx], nk->port[pd2.sidx]); if (PF_ANEQ(pd2.dst, &nk->addr[pd2.didx], pd2.af) || pd2.rdomain != nk->rdomain) pd->destchg = 1; pd->m->m_pkthdr.ph_rtableid = nk->rdomain; if (PF_ANEQ(pd2.dst, &nk->addr[pd2.didx], pd2.af) || nk->port[pd2.didx] != th->th_dport) pf_translate_icmp(pd, pd2.dst, &th->th_dport, pd->src, &nk->addr[pd2.didx], nk->port[pd2.didx]); copyback = 1; } if (copyback) { switch (pd2.af) { case AF_INET: m_copyback(pd->m, pd->off, ICMP_MINLEN, &pd->hdr.icmp, M_NOWAIT); m_copyback(pd2.m, ipoff2, sizeof(h2), &h2, M_NOWAIT); break; #ifdef INET6 case AF_INET6: m_copyback(pd->m, pd->off, sizeof(struct icmp6_hdr), &pd->hdr.icmp6, M_NOWAIT); m_copyback(pd2.m, ipoff2, sizeof(h2_6), &h2_6, M_NOWAIT); break; #endif /* INET6 */ } m_copyback(pd2.m, pd2.off, 8, th, M_NOWAIT); } break; } case IPPROTO_UDP: { struct udphdr *uh = &pd2.hdr.udp; int action; if (!pf_pull_hdr(pd2.m, pd2.off, uh, sizeof(*uh), reason, pd2.af)) { DPFPRINTF(LOG_NOTICE, "ICMP error message too short (udp)"); return (PF_DROP); } key.af = pd2.af; key.proto = IPPROTO_UDP; key.rdomain = pd2.rdomain; pf_addrcpy(&key.addr[pd2.sidx], pd2.src, key.af); pf_addrcpy(&key.addr[pd2.didx], pd2.dst, key.af); key.port[pd2.sidx] = uh->uh_sport; key.port[pd2.didx] = uh->uh_dport; key.hash = pf_pkt_hash(pd2.af, pd2.proto, pd2.src, pd2.dst, uh->uh_sport, uh->uh_dport); action = pf_find_state(&pd2, &key, stp); if (action != PF_MATCH) return (action); /* translate source/destination address, if necessary */ if ((*stp)->key[PF_SK_WIRE] != (*stp)->key[PF_SK_STACK]) { struct pf_state_key *nk; int afto, sidx, didx; if (PF_REVERSED_KEY((*stp)->key, pd->af)) nk = (*stp)->key[pd->sidx]; else nk = (*stp)->key[pd->didx]; afto = pd->af != nk->af; sidx = afto ? pd2.didx : pd2.sidx; didx = afto ? pd2.sidx : pd2.didx; #ifdef INET6 if (afto) { if (pf_translate_icmp_af(pd, nk->af, &pd->hdr.icmp)) return (PF_DROP); m_copyback(pd->m, pd->off, sizeof(struct icmp6_hdr), &pd->hdr.icmp6, M_NOWAIT); if (pf_change_icmp_af(pd->m, ipoff2, pd, &pd2, &nk->addr[sidx], &nk->addr[didx], pd->af, nk->af)) return (PF_DROP); if (nk->af == AF_INET) pd->proto = IPPROTO_ICMP; else pd->proto = IPPROTO_ICMPV6; pd->m->m_pkthdr.ph_rtableid = nk->rdomain; pd->destchg = 1; pf_addrcpy(&pd->nsaddr, &nk->addr[pd2.sidx], nk->af); pf_addrcpy(&pd->ndaddr, &nk->addr[pd2.didx], nk->af); pd->naf = nk->af; pf_patch_16(pd, &uh->uh_sport, nk->port[sidx]); pf_patch_16(pd, &uh->uh_dport, nk->port[didx]); m_copyback(pd2.m, pd2.off, sizeof(*uh), uh, M_NOWAIT); return (PF_AFRT); } #endif /* INET6 */ if (PF_ANEQ(pd2.src, &nk->addr[pd2.sidx], pd2.af) || nk->port[pd2.sidx] != uh->uh_sport) pf_translate_icmp(pd, pd2.src, &uh->uh_sport, pd->dst, &nk->addr[pd2.sidx], nk->port[pd2.sidx]); if (PF_ANEQ(pd2.dst, &nk->addr[pd2.didx], pd2.af) || pd2.rdomain != nk->rdomain) pd->destchg = 1; pd->m->m_pkthdr.ph_rtableid = nk->rdomain; if (PF_ANEQ(pd2.dst, &nk->addr[pd2.didx], pd2.af) || nk->port[pd2.didx] != uh->uh_dport) pf_translate_icmp(pd, pd2.dst, &uh->uh_dport, pd->src, &nk->addr[pd2.didx], nk->port[pd2.didx]); switch (pd2.af) { case AF_INET: m_copyback(pd->m, pd->off, ICMP_MINLEN, &pd->hdr.icmp, M_NOWAIT); m_copyback(pd2.m, ipoff2, sizeof(h2), &h2, M_NOWAIT); break; #ifdef INET6 case AF_INET6: m_copyback(pd->m, pd->off, sizeof(struct icmp6_hdr), &pd->hdr.icmp6, M_NOWAIT); m_copyback(pd2.m, ipoff2, sizeof(h2_6), &h2_6, M_NOWAIT); break; #endif /* INET6 */ } /* Avoid recomputing quoted UDP checksum. * note: udp6 0 csum invalid per rfc2460 p27. * but presumed nothing cares in this context */ pf_patch_16(pd, &uh->uh_sum, 0); m_copyback(pd2.m, pd2.off, sizeof(*uh), uh, M_NOWAIT); copyback = 1; } break; } case IPPROTO_ICMP: { struct icmp *iih = &pd2.hdr.icmp; if (pd2.af != AF_INET) { REASON_SET(reason, PFRES_NORM); return (PF_DROP); } if (!pf_pull_hdr(pd2.m, pd2.off, iih, ICMP_MINLEN, reason, pd2.af)) { DPFPRINTF(LOG_NOTICE, "ICMP error message too short (icmp)"); return (PF_DROP); } pf_icmp_mapping(&pd2, iih->icmp_type, &icmp_dir, &virtual_id, &virtual_type); ret = pf_icmp_state_lookup(&pd2, &key, stp, virtual_id, virtual_type, icmp_dir, &iidx, 0, 1); if (ret >= 0) return (ret); /* translate source/destination address, if necessary */ if ((*stp)->key[PF_SK_WIRE] != (*stp)->key[PF_SK_STACK]) { struct pf_state_key *nk; int afto, sidx, didx; if (PF_REVERSED_KEY((*stp)->key, pd->af)) nk = (*stp)->key[pd->sidx]; else nk = (*stp)->key[pd->didx]; afto = pd->af != nk->af; sidx = afto ? pd2.didx : pd2.sidx; didx = afto ? pd2.sidx : pd2.didx; iidx = afto ? !iidx : iidx; #ifdef INET6 if (afto) { if (nk->af != AF_INET6) return (PF_DROP); if (pf_translate_icmp_af(pd, nk->af, &pd->hdr.icmp)) return (PF_DROP); m_copyback(pd->m, pd->off, sizeof(struct icmp6_hdr), &pd->hdr.icmp6, M_NOWAIT); if (pf_change_icmp_af(pd->m, ipoff2, pd, &pd2, &nk->addr[sidx], &nk->addr[didx], pd->af, nk->af)) return (PF_DROP); pd->proto = IPPROTO_ICMPV6; if (pf_translate_icmp_af(pd, nk->af, iih)) return (PF_DROP); if (virtual_type == htons(ICMP_ECHO)) pf_patch_16(pd, &iih->icmp_id, nk->port[iidx]); m_copyback(pd2.m, pd2.off, ICMP_MINLEN, iih, M_NOWAIT); pd->m->m_pkthdr.ph_rtableid = nk->rdomain; pd->destchg = 1; pf_addrcpy(&pd->nsaddr, &nk->addr[pd2.sidx], nk->af); pf_addrcpy(&pd->ndaddr, &nk->addr[pd2.didx], nk->af); pd->naf = nk->af; return (PF_AFRT); } #endif /* INET6 */ if (PF_ANEQ(pd2.src, &nk->addr[pd2.sidx], pd2.af) || (virtual_type == htons(ICMP_ECHO) && nk->port[iidx] != iih->icmp_id)) pf_translate_icmp(pd, pd2.src, (virtual_type == htons(ICMP_ECHO)) ? &iih->icmp_id : NULL, pd->dst, &nk->addr[pd2.sidx], (virtual_type == htons(ICMP_ECHO)) ? nk->port[iidx] : 0); if (PF_ANEQ(pd2.dst, &nk->addr[pd2.didx], pd2.af) || pd2.rdomain != nk->rdomain) pd->destchg = 1; pd->m->m_pkthdr.ph_rtableid = nk->rdomain; if (PF_ANEQ(pd2.dst, &nk->addr[pd2.didx], pd2.af)) pf_translate_icmp(pd, pd2.dst, NULL, pd->src, &nk->addr[pd2.didx], 0); m_copyback(pd->m, pd->off, ICMP_MINLEN, &pd->hdr.icmp, M_NOWAIT); m_copyback(pd2.m, ipoff2, sizeof(h2), &h2, M_NOWAIT); m_copyback(pd2.m, pd2.off, ICMP_MINLEN, iih, M_NOWAIT); copyback = 1; } break; } #ifdef INET6 case IPPROTO_ICMPV6: { struct icmp6_hdr *iih = &pd2.hdr.icmp6; if (pd2.af != AF_INET6) { REASON_SET(reason, PFRES_NORM); return (PF_DROP); } if (!pf_pull_hdr(pd2.m, pd2.off, iih, sizeof(struct icmp6_hdr), reason, pd2.af)) { DPFPRINTF(LOG_NOTICE, "ICMP error message too short (icmp6)"); return (PF_DROP); } pf_icmp_mapping(&pd2, iih->icmp6_type, &icmp_dir, &virtual_id, &virtual_type); ret = pf_icmp_state_lookup(&pd2, &key, stp, virtual_id, virtual_type, icmp_dir, &iidx, 0, 1); /* IPv6? try matching a multicast address */ if (ret == PF_DROP && pd2.af == AF_INET6 && icmp_dir == PF_OUT) ret = pf_icmp_state_lookup(&pd2, &key, stp, virtual_id, virtual_type, icmp_dir, &iidx, 1, 1); if (ret >= 0) return (ret); /* translate source/destination address, if necessary */ if ((*stp)->key[PF_SK_WIRE] != (*stp)->key[PF_SK_STACK]) { struct pf_state_key *nk; int afto, sidx, didx; if (PF_REVERSED_KEY((*stp)->key, pd->af)) nk = (*stp)->key[pd->sidx]; else nk = (*stp)->key[pd->didx]; afto = pd->af != nk->af; sidx = afto ? pd2.didx : pd2.sidx; didx = afto ? pd2.sidx : pd2.didx; iidx = afto ? !iidx : iidx; if (afto) { if (nk->af != AF_INET) return (PF_DROP); if (pf_translate_icmp_af(pd, nk->af, &pd->hdr.icmp)) return (PF_DROP); m_copyback(pd->m, pd->off, sizeof(struct icmp6_hdr), &pd->hdr.icmp6, M_NOWAIT); if (pf_change_icmp_af(pd->m, ipoff2, pd, &pd2, &nk->addr[sidx], &nk->addr[didx], pd->af, nk->af)) return (PF_DROP); pd->proto = IPPROTO_ICMP; if (pf_translate_icmp_af(pd, nk->af, iih)) return (PF_DROP); if (virtual_type == htons(ICMP6_ECHO_REQUEST)) pf_patch_16(pd, &iih->icmp6_id, nk->port[iidx]); m_copyback(pd2.m, pd2.off, sizeof(struct icmp6_hdr), iih, M_NOWAIT); pd->m->m_pkthdr.ph_rtableid = nk->rdomain; pd->destchg = 1; pf_addrcpy(&pd->nsaddr, &nk->addr[pd2.sidx], nk->af); pf_addrcpy(&pd->ndaddr, &nk->addr[pd2.didx], nk->af); pd->naf = nk->af; return (PF_AFRT); } if (PF_ANEQ(pd2.src, &nk->addr[pd2.sidx], pd2.af) || ((virtual_type == htons(ICMP6_ECHO_REQUEST)) && nk->port[pd2.sidx] != iih->icmp6_id)) pf_translate_icmp(pd, pd2.src, (virtual_type == htons(ICMP6_ECHO_REQUEST)) ? &iih->icmp6_id : NULL, pd->dst, &nk->addr[pd2.sidx], (virtual_type == htons(ICMP6_ECHO_REQUEST)) ? nk->port[iidx] : 0); if (PF_ANEQ(pd2.dst, &nk->addr[pd2.didx], pd2.af) || pd2.rdomain != nk->rdomain) pd->destchg = 1; pd->m->m_pkthdr.ph_rtableid = nk->rdomain; if (PF_ANEQ(pd2.dst, &nk->addr[pd2.didx], pd2.af)) pf_translate_icmp(pd, pd2.dst, NULL, pd->src, &nk->addr[pd2.didx], 0); m_copyback(pd->m, pd->off, sizeof(struct icmp6_hdr), &pd->hdr.icmp6, M_NOWAIT); m_copyback(pd2.m, ipoff2, sizeof(h2_6), &h2_6, M_NOWAIT); m_copyback(pd2.m, pd2.off, sizeof(struct icmp6_hdr), iih, M_NOWAIT); copyback = 1; } break; } #endif /* INET6 */ default: { int action; key.af = pd2.af; key.proto = pd2.proto; key.rdomain = pd2.rdomain; pf_addrcpy(&key.addr[pd2.sidx], pd2.src, key.af); pf_addrcpy(&key.addr[pd2.didx], pd2.dst, key.af); key.port[0] = key.port[1] = 0; key.hash = pf_pkt_hash(pd2.af, pd2.proto, pd2.src, pd2.dst, 0, 0); action = pf_find_state(&pd2, &key, stp); if (action != PF_MATCH) return (action); /* translate source/destination address, if necessary */ if ((*stp)->key[PF_SK_WIRE] != (*stp)->key[PF_SK_STACK]) { struct pf_state_key *nk = (*stp)->key[pd->didx]; if (PF_ANEQ(pd2.src, &nk->addr[pd2.sidx], pd2.af)) pf_translate_icmp(pd, pd2.src, NULL, pd->dst, &nk->addr[pd2.sidx], 0); if (PF_ANEQ(pd2.dst, &nk->addr[pd2.didx], pd2.af) || pd2.rdomain != nk->rdomain) pd->destchg = 1; pd->m->m_pkthdr.ph_rtableid = nk->rdomain; if (PF_ANEQ(pd2.dst, &nk->addr[pd2.didx], pd2.af)) pf_translate_icmp(pd, pd2.dst, NULL, pd->src, &nk->addr[pd2.didx], 0); switch (pd2.af) { case AF_INET: m_copyback(pd->m, pd->off, ICMP_MINLEN, &pd->hdr.icmp, M_NOWAIT); m_copyback(pd2.m, ipoff2, sizeof(h2), &h2, M_NOWAIT); break; #ifdef INET6 case AF_INET6: m_copyback(pd->m, pd->off, sizeof(struct icmp6_hdr), &pd->hdr.icmp6, M_NOWAIT); m_copyback(pd2.m, ipoff2, sizeof(h2_6), &h2_6, M_NOWAIT); break; #endif /* INET6 */ } copyback = 1; } break; } } } if (copyback) { m_copyback(pd->m, pd->off, pd->hdrlen, &pd->hdr, M_NOWAIT); } return (PF_PASS); } /* * ipoff and off are measured from the start of the mbuf chain. * h must be at "ipoff" on the mbuf chain. */ void * pf_pull_hdr(struct mbuf *m, int off, void *p, int len, u_short *reasonp, sa_family_t af) { int iplen = 0; switch (af) { case AF_INET: { struct ip *h = mtod(m, struct ip *); u_int16_t fragoff = (ntohs(h->ip_off) & IP_OFFMASK) << 3; if (fragoff) { REASON_SET(reasonp, PFRES_FRAG); return (NULL); } iplen = ntohs(h->ip_len); break; } #ifdef INET6 case AF_INET6: { struct ip6_hdr *h = mtod(m, struct ip6_hdr *); iplen = ntohs(h->ip6_plen) + sizeof(struct ip6_hdr); break; } #endif /* INET6 */ } if (m->m_pkthdr.len < off + len || iplen < off + len) { REASON_SET(reasonp, PFRES_SHORT); return (NULL); } m_copydata(m, off, len, p); return (p); } int pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *kif, int rtableid) { struct sockaddr_storage ss; struct sockaddr_in *dst; int ret = 1; int check_mpath; #ifdef INET6 struct sockaddr_in6 *dst6; #endif /* INET6 */ struct rtentry *rt = NULL; check_mpath = 0; memset(&ss, 0, sizeof(ss)); switch (af) { case AF_INET: dst = (struct sockaddr_in *)&ss; dst->sin_family = AF_INET; dst->sin_len = sizeof(*dst); dst->sin_addr = addr->v4; if (ipmultipath) check_mpath = 1; break; #ifdef INET6 case AF_INET6: /* * Skip check for addresses with embedded interface scope, * as they would always match anyway. */ if (IN6_IS_SCOPE_EMBED(&addr->v6)) goto out; dst6 = (struct sockaddr_in6 *)&ss; dst6->sin6_family = AF_INET6; dst6->sin6_len = sizeof(*dst6); dst6->sin6_addr = addr->v6; if (ip6_multipath) check_mpath = 1; break; #endif /* INET6 */ } /* Skip checks for ipsec interfaces */ if (kif != NULL && kif->pfik_ifp->if_type == IFT_ENC) goto out; rt = rtalloc(sstosa(&ss), 0, rtableid); if (rt != NULL) { /* No interface given, this is a no-route check */ if (kif == NULL) goto out; if (kif->pfik_ifp == NULL) { ret = 0; goto out; } /* Perform uRPF check if passed input interface */ ret = 0; do { if (rt->rt_ifidx == kif->pfik_ifp->if_index) { ret = 1; #if NCARP > 0 } else { struct ifnet *ifp; ifp = if_get(rt->rt_ifidx); if (ifp != NULL && ifp->if_type == IFT_CARP && ifp->if_carpdevidx == kif->pfik_ifp->if_index) ret = 1; if_put(ifp); #endif /* NCARP */ } rt = rtable_iterate(rt); } while (check_mpath == 1 && rt != NULL && ret == 0); } else ret = 0; out: rtfree(rt); return (ret); } int pf_rtlabel_match(struct pf_addr *addr, sa_family_t af, struct pf_addr_wrap *aw, int rtableid) { struct sockaddr_storage ss; struct sockaddr_in *dst; #ifdef INET6 struct sockaddr_in6 *dst6; #endif /* INET6 */ struct rtentry *rt; int ret = 0; memset(&ss, 0, sizeof(ss)); switch (af) { case AF_INET: dst = (struct sockaddr_in *)&ss; dst->sin_family = AF_INET; dst->sin_len = sizeof(*dst); dst->sin_addr = addr->v4; break; #ifdef INET6 case AF_INET6: dst6 = (struct sockaddr_in6 *)&ss; dst6->sin6_family = AF_INET6; dst6->sin6_len = sizeof(*dst6); dst6->sin6_addr = addr->v6; break; #endif /* INET6 */ } rt = rtalloc(sstosa(&ss), RT_RESOLVE, rtableid); if (rt != NULL) { if (rt->rt_labelid == aw->v.rtlabel) ret = 1; rtfree(rt); } return (ret); } /* pf_route() may change pd->m, adjust local copies after calling */ void pf_route(struct pf_pdesc *pd, struct pf_state *st) { struct mbuf *m0; struct mbuf_list ml; struct sockaddr_in *dst, sin; struct rtentry *rt = NULL; struct ip *ip; struct ifnet *ifp = NULL; unsigned int rtableid; if (pd->m->m_pkthdr.pf.routed++ > 3) { m_freem(pd->m); pd->m = NULL; return; } if (st->rt == PF_DUPTO) { if ((m0 = m_dup_pkt(pd->m, max_linkhdr, M_NOWAIT)) == NULL) return; } else { if ((st->rt == PF_REPLYTO) == (st->direction == pd->dir)) return; m0 = pd->m; pd->m = NULL; } if (m0->m_len < sizeof(struct ip)) { DPFPRINTF(LOG_ERR, "%s: m0->m_len < sizeof(struct ip)", __func__); goto bad; } ip = mtod(m0, struct ip *); if (pd->dir == PF_IN) { if (ip->ip_ttl <= IPTTLDEC) { if (st->rt != PF_DUPTO) { pf_send_icmp(m0, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, 0, pd->af, st->rule.ptr, pd->rdomain); } goto bad; } ip->ip_ttl -= IPTTLDEC; } memset(&sin, 0, sizeof(sin)); dst = &sin; dst->sin_family = AF_INET; dst->sin_len = sizeof(*dst); dst->sin_addr = st->rt_addr.v4; rtableid = m0->m_pkthdr.ph_rtableid; rt = rtalloc_mpath(sintosa(dst), &ip->ip_src.s_addr, rtableid); if (!rtisvalid(rt)) { if (st->rt != PF_DUPTO) { pf_send_icmp(m0, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, pd->af, st->rule.ptr, pd->rdomain); } ipstat_inc(ips_noroute); goto bad; } ifp = if_get(rt->rt_ifidx); if (ifp == NULL) goto bad; /* A locally generated packet may have invalid source address. */ if ((ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET && (ifp->if_flags & IFF_LOOPBACK) == 0) ip->ip_src = ifatoia(rt->rt_ifa)->ia_addr.sin_addr; if (st->rt != PF_DUPTO && pd->dir == PF_IN) { if (pf_test(AF_INET, PF_OUT, ifp, &m0) != PF_PASS) goto bad; else if (m0 == NULL) goto done; if (m0->m_len < sizeof(struct ip)) { DPFPRINTF(LOG_ERR, "%s: m0->m_len < sizeof(struct ip)", __func__); goto bad; } ip = mtod(m0, struct ip *); } if (if_output_tso(ifp, &m0, sintosa(dst), rt, ifp->if_mtu) || m0 == NULL) goto done; /* * Too large for interface; fragment if possible. * Must be able to put at least 8 bytes per fragment. */ if (ip->ip_off & htons(IP_DF)) { ipstat_inc(ips_cantfrag); if (st->rt != PF_DUPTO) pf_send_icmp(m0, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, ifp->if_mtu, pd->af, st->rule.ptr, pd->rdomain); goto bad; } if (ip_fragment(m0, &ml, ifp, ifp->if_mtu) || if_output_ml(ifp, &ml, sintosa(dst), rt)) goto done; ipstat_inc(ips_fragmented); done: if_put(ifp); rtfree(rt); return; bad: m_freem(m0); goto done; } #ifdef INET6 /* pf_route6() may change pd->m, adjust local copies after calling */ void pf_route6(struct pf_pdesc *pd, struct pf_state *st) { struct mbuf *m0; struct sockaddr_in6 *dst, sin6; struct rtentry *rt = NULL; struct ip6_hdr *ip6; struct ifnet *ifp = NULL; struct m_tag *mtag; unsigned int rtableid; if (pd->m->m_pkthdr.pf.routed++ > 3) { m_freem(pd->m); pd->m = NULL; return; } if (st->rt == PF_DUPTO) { if ((m0 = m_dup_pkt(pd->m, max_linkhdr, M_NOWAIT)) == NULL) return; } else { if ((st->rt == PF_REPLYTO) == (st->direction == pd->dir)) return; m0 = pd->m; pd->m = NULL; } if (m0->m_len < sizeof(struct ip6_hdr)) { DPFPRINTF(LOG_ERR, "%s: m0->m_len < sizeof(struct ip6_hdr)", __func__); goto bad; } ip6 = mtod(m0, struct ip6_hdr *); if (pd->dir == PF_IN) { if (ip6->ip6_hlim <= IPV6_HLIMDEC) { if (st->rt != PF_DUPTO) { pf_send_icmp(m0, ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT, 0, pd->af, st->rule.ptr, pd->rdomain); } goto bad; } ip6->ip6_hlim -= IPV6_HLIMDEC; } memset(&sin6, 0, sizeof(sin6)); dst = &sin6; dst->sin6_family = AF_INET6; dst->sin6_len = sizeof(*dst); dst->sin6_addr = st->rt_addr.v6; rtableid = m0->m_pkthdr.ph_rtableid; rt = rtalloc_mpath(sin6tosa(dst), &ip6->ip6_src.s6_addr32[0], rtableid); if (!rtisvalid(rt)) { if (st->rt != PF_DUPTO) { pf_send_icmp(m0, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE, 0, pd->af, st->rule.ptr, pd->rdomain); } ip6stat_inc(ip6s_noroute); goto bad; } ifp = if_get(rt->rt_ifidx); if (ifp == NULL) goto bad; /* A locally generated packet may have invalid source address. */ if (IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) && (ifp->if_flags & IFF_LOOPBACK) == 0) ip6->ip6_src = ifatoia6(rt->rt_ifa)->ia_addr.sin6_addr; if (st->rt != PF_DUPTO && pd->dir == PF_IN) { if (pf_test(AF_INET6, PF_OUT, ifp, &m0) != PF_PASS) goto bad; else if (m0 == NULL) goto done; if (m0->m_len < sizeof(struct ip6_hdr)) { DPFPRINTF(LOG_ERR, "%s: m0->m_len < sizeof(struct ip6_hdr)", __func__); goto bad; } } /* * If packet has been reassembled by PF earlier, we have to * use pf_refragment6() here to turn it back to fragments. */ if ((mtag = m_tag_find(m0, PACKET_TAG_PF_REASSEMBLED, NULL))) { (void) pf_refragment6(&m0, mtag, dst, ifp, rt); goto done; } if (if_output_tso(ifp, &m0, sin6tosa(dst), rt, ifp->if_mtu) || m0 == NULL) goto done; ip6stat_inc(ip6s_cantfrag); if (st->rt != PF_DUPTO) pf_send_icmp(m0, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu, pd->af, st->rule.ptr, pd->rdomain); goto bad; done: if_put(ifp); rtfree(rt); return; bad: m_freem(m0); goto done; } #endif /* INET6 */ /* * check TCP checksum and set mbuf flag * off is the offset where the protocol header starts * len is the total length of protocol header plus payload * returns 0 when the checksum is valid, otherwise returns 1. * if the _OUT flag is set the checksum isn't done yet, consider these ok */ int pf_check_tcp_cksum(struct mbuf *m, int off, int len, sa_family_t af) { u_int16_t sum; if (m->m_pkthdr.csum_flags & (M_TCP_CSUM_IN_OK | M_TCP_CSUM_OUT)) { return (0); } if (m->m_pkthdr.csum_flags & M_TCP_CSUM_IN_BAD || off < sizeof(struct ip) || m->m_pkthdr.len < off + len) { return (1); } /* need to do it in software */ tcpstat_inc(tcps_inswcsum); switch (af) { case AF_INET: if (m->m_len < sizeof(struct ip)) return (1); sum = in4_cksum(m, IPPROTO_TCP, off, len); break; #ifdef INET6 case AF_INET6: if (m->m_len < sizeof(struct ip6_hdr)) return (1); sum = in6_cksum(m, IPPROTO_TCP, off, len); break; #endif /* INET6 */ default: unhandled_af(af); } if (sum) { tcpstat_inc(tcps_rcvbadsum); m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_BAD; return (1); } m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK; return (0); } struct pf_divert * pf_find_divert(struct mbuf *m) { struct m_tag *mtag; if ((mtag = m_tag_find(m, PACKET_TAG_PF_DIVERT, NULL)) == NULL) return (NULL); return ((struct pf_divert *)(mtag + 1)); } struct pf_divert * pf_get_divert(struct mbuf *m) { struct m_tag *mtag; if ((mtag = m_tag_find(m, PACKET_TAG_PF_DIVERT, NULL)) == NULL) { mtag = m_tag_get(PACKET_TAG_PF_DIVERT, sizeof(struct pf_divert), M_NOWAIT); if (mtag == NULL) return (NULL); memset(mtag + 1, 0, sizeof(struct pf_divert)); m_tag_prepend(m, mtag); } return ((struct pf_divert *)(mtag + 1)); } int pf_walk_option(struct pf_pdesc *pd, struct ip *h, int off, int end, u_short *reason) { uint8_t type, length, opts[15 * 4 - sizeof(struct ip)]; /* IP header in payload of ICMP packet may be too short */ if (pd->m->m_pkthdr.len < end) { DPFPRINTF(LOG_NOTICE, "IP option too short"); REASON_SET(reason, PFRES_SHORT); return (PF_DROP); } KASSERT(end - off <= sizeof(opts)); m_copydata(pd->m, off, end - off, opts); end -= off; off = 0; while (off < end) { type = opts[off]; if (type == IPOPT_EOL) break; if (type == IPOPT_NOP) { off++; continue; } if (off + 2 > end) { DPFPRINTF(LOG_NOTICE, "IP length opt"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } length = opts[off + 1]; if (length < 2) { DPFPRINTF(LOG_NOTICE, "IP short opt"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } if (off + length > end) { DPFPRINTF(LOG_NOTICE, "IP long opt"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } switch (type) { case IPOPT_RA: SET(pd->badopts, PF_OPT_ROUTER_ALERT); break; default: SET(pd->badopts, PF_OPT_OTHER); break; } off += length; } return (PF_PASS); } int pf_walk_header(struct pf_pdesc *pd, struct ip *h, u_short *reason) { struct ip6_ext ext; u_int32_t hlen, end; int hdr_cnt; hlen = h->ip_hl << 2; if (hlen < sizeof(struct ip) || hlen > ntohs(h->ip_len)) { REASON_SET(reason, PFRES_SHORT); return (PF_DROP); } if (hlen != sizeof(struct ip)) { if (pf_walk_option(pd, h, pd->off + sizeof(struct ip), pd->off + hlen, reason) != PF_PASS) return (PF_DROP); /* header options which contain only padding is fishy */ if (pd->badopts == 0) SET(pd->badopts, PF_OPT_OTHER); } end = pd->off + ntohs(h->ip_len); pd->off += hlen; pd->proto = h->ip_p; /* IGMP packets have router alert options, allow them */ if (pd->proto == IPPROTO_IGMP) { /* * According to RFC 1112 ttl must be set to 1 in all IGMP * packets sent to 224.0.0.1 */ if ((h->ip_ttl != 1) && (h->ip_dst.s_addr == INADDR_ALLHOSTS_GROUP)) { DPFPRINTF(LOG_NOTICE, "Invalid IGMP"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } CLR(pd->badopts, PF_OPT_ROUTER_ALERT); } /* stop walking over non initial fragments */ if ((h->ip_off & htons(IP_OFFMASK)) != 0) return (PF_PASS); for (hdr_cnt = 0; hdr_cnt < pf_hdr_limit; hdr_cnt++) { switch (pd->proto) { case IPPROTO_AH: /* fragments may be short */ if ((h->ip_off & htons(IP_MF | IP_OFFMASK)) != 0 && end < pd->off + sizeof(ext)) return (PF_PASS); if (!pf_pull_hdr(pd->m, pd->off, &ext, sizeof(ext), reason, AF_INET)) { DPFPRINTF(LOG_NOTICE, "IP short exthdr"); return (PF_DROP); } pd->off += (ext.ip6e_len + 2) * 4; pd->proto = ext.ip6e_nxt; break; default: return (PF_PASS); } } DPFPRINTF(LOG_NOTICE, "IPv4 nested authentication header limit"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } #ifdef INET6 int pf_walk_option6(struct pf_pdesc *pd, struct ip6_hdr *h, int off, int end, u_short *reason) { struct ip6_opt opt; struct ip6_opt_jumbo jumbo; while (off < end) { if (!pf_pull_hdr(pd->m, off, &opt.ip6o_type, sizeof(opt.ip6o_type), reason, AF_INET6)) { DPFPRINTF(LOG_NOTICE, "IPv6 short opt type"); return (PF_DROP); } if (opt.ip6o_type == IP6OPT_PAD1) { off++; continue; } if (!pf_pull_hdr(pd->m, off, &opt, sizeof(opt), reason, AF_INET6)) { DPFPRINTF(LOG_NOTICE, "IPv6 short opt"); return (PF_DROP); } if (off + sizeof(opt) + opt.ip6o_len > end) { DPFPRINTF(LOG_NOTICE, "IPv6 long opt"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } switch (opt.ip6o_type) { case IP6OPT_PADN: break; case IP6OPT_JUMBO: SET(pd->badopts, PF_OPT_JUMBO); if (pd->jumbolen != 0) { DPFPRINTF(LOG_NOTICE, "IPv6 multiple jumbo"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } if (ntohs(h->ip6_plen) != 0) { DPFPRINTF(LOG_NOTICE, "IPv6 bad jumbo plen"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } if (!pf_pull_hdr(pd->m, off, &jumbo, sizeof(jumbo), reason, AF_INET6)) { DPFPRINTF(LOG_NOTICE, "IPv6 short jumbo"); return (PF_DROP); } memcpy(&pd->jumbolen, jumbo.ip6oj_jumbo_len, sizeof(pd->jumbolen)); pd->jumbolen = ntohl(pd->jumbolen); if (pd->jumbolen < IPV6_MAXPACKET) { DPFPRINTF(LOG_NOTICE, "IPv6 short jumbolen"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } break; case IP6OPT_ROUTER_ALERT: SET(pd->badopts, PF_OPT_ROUTER_ALERT); break; default: SET(pd->badopts, PF_OPT_OTHER); break; } off += sizeof(opt) + opt.ip6o_len; } return (PF_PASS); } int pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason) { struct ip6_frag frag; struct ip6_ext ext; struct icmp6_hdr icmp6; struct ip6_rthdr rthdr; u_int32_t end; int hdr_cnt, fraghdr_cnt = 0, rthdr_cnt = 0; pd->off += sizeof(struct ip6_hdr); end = pd->off + ntohs(h->ip6_plen); pd->fragoff = pd->extoff = pd->jumbolen = 0; pd->proto = h->ip6_nxt; for (hdr_cnt = 0; hdr_cnt < pf_hdr_limit; hdr_cnt++) { switch (pd->proto) { case IPPROTO_ROUTING: case IPPROTO_DSTOPTS: SET(pd->badopts, PF_OPT_OTHER); break; case IPPROTO_HOPOPTS: if (!pf_pull_hdr(pd->m, pd->off, &ext, sizeof(ext), reason, AF_INET6)) { DPFPRINTF(LOG_NOTICE, "IPv6 short exthdr"); return (PF_DROP); } if (pf_walk_option6(pd, h, pd->off + sizeof(ext), pd->off + (ext.ip6e_len + 1) * 8, reason) != PF_PASS) return (PF_DROP); /* option header which contains only padding is fishy */ if (pd->badopts == 0) SET(pd->badopts, PF_OPT_OTHER); break; } switch (pd->proto) { case IPPROTO_FRAGMENT: if (fraghdr_cnt++) { DPFPRINTF(LOG_NOTICE, "IPv6 multiple fragment"); REASON_SET(reason, PFRES_FRAG); return (PF_DROP); } /* jumbo payload packets cannot be fragmented */ if (pd->jumbolen != 0) { DPFPRINTF(LOG_NOTICE, "IPv6 fragmented jumbo"); REASON_SET(reason, PFRES_FRAG); return (PF_DROP); } if (!pf_pull_hdr(pd->m, pd->off, &frag, sizeof(frag), reason, AF_INET6)) { DPFPRINTF(LOG_NOTICE, "IPv6 short fragment"); return (PF_DROP); } /* stop walking over non initial fragments */ if (ntohs((frag.ip6f_offlg & IP6F_OFF_MASK)) != 0) { pd->fragoff = pd->off; return (PF_PASS); } /* RFC6946: reassemble only non atomic fragments */ if (frag.ip6f_offlg & IP6F_MORE_FRAG) pd->fragoff = pd->off; pd->off += sizeof(frag); pd->proto = frag.ip6f_nxt; break; case IPPROTO_ROUTING: if (rthdr_cnt++) { DPFPRINTF(LOG_NOTICE, "IPv6 multiple rthdr"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } /* fragments may be short */ if (pd->fragoff != 0 && end < pd->off + sizeof(rthdr)) { pd->off = pd->fragoff; pd->proto = IPPROTO_FRAGMENT; return (PF_PASS); } if (!pf_pull_hdr(pd->m, pd->off, &rthdr, sizeof(rthdr), reason, AF_INET6)) { DPFPRINTF(LOG_NOTICE, "IPv6 short rthdr"); return (PF_DROP); } if (rthdr.ip6r_type == IPV6_RTHDR_TYPE_0) { DPFPRINTF(LOG_NOTICE, "IPv6 rthdr0"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } /* FALLTHROUGH */ case IPPROTO_HOPOPTS: /* RFC2460 4.1: Hop-by-Hop only after IPv6 header */ if (pd->proto == IPPROTO_HOPOPTS && hdr_cnt > 0) { DPFPRINTF(LOG_NOTICE, "IPv6 hopopts not first"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } /* FALLTHROUGH */ case IPPROTO_AH: case IPPROTO_DSTOPTS: /* fragments may be short */ if (pd->fragoff != 0 && end < pd->off + sizeof(ext)) { pd->off = pd->fragoff; pd->proto = IPPROTO_FRAGMENT; return (PF_PASS); } if (!pf_pull_hdr(pd->m, pd->off, &ext, sizeof(ext), reason, AF_INET6)) { DPFPRINTF(LOG_NOTICE, "IPv6 short exthdr"); return (PF_DROP); } /* reassembly needs the ext header before the frag */ if (pd->fragoff == 0) pd->extoff = pd->off; if (pd->proto == IPPROTO_HOPOPTS && pd->fragoff == 0 && ntohs(h->ip6_plen) == 0 && pd->jumbolen != 0) { DPFPRINTF(LOG_NOTICE, "IPv6 missing jumbo"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } if (pd->proto == IPPROTO_AH) pd->off += (ext.ip6e_len + 2) * 4; else pd->off += (ext.ip6e_len + 1) * 8; pd->proto = ext.ip6e_nxt; break; case IPPROTO_ICMPV6: /* fragments may be short, ignore inner header then */ if (pd->fragoff != 0 && end < pd->off + sizeof(icmp6)) { pd->off = pd->fragoff; pd->proto = IPPROTO_FRAGMENT; return (PF_PASS); } if (!pf_pull_hdr(pd->m, pd->off, &icmp6, sizeof(icmp6), reason, AF_INET6)) { DPFPRINTF(LOG_NOTICE, "IPv6 short icmp6hdr"); return (PF_DROP); } /* ICMP multicast packets have router alert options */ switch (icmp6.icmp6_type) { case MLD_LISTENER_QUERY: case MLD_LISTENER_REPORT: case MLD_LISTENER_DONE: case MLDV2_LISTENER_REPORT: /* * According to RFC 2710 all MLD messages are * sent with hop-limit (ttl) set to 1, and link * local source address. If either one is * missing then MLD message is invalid and * should be discarded. */ if ((h->ip6_hlim != 1) || !IN6_IS_ADDR_LINKLOCAL(&h->ip6_src)) { DPFPRINTF(LOG_NOTICE, "Invalid MLD"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } CLR(pd->badopts, PF_OPT_ROUTER_ALERT); break; } return (PF_PASS); case IPPROTO_TCP: case IPPROTO_UDP: /* fragments may be short, ignore inner header then */ if (pd->fragoff != 0 && end < pd->off + (pd->proto == IPPROTO_TCP ? sizeof(struct tcphdr) : pd->proto == IPPROTO_UDP ? sizeof(struct udphdr) : sizeof(struct icmp6_hdr))) { pd->off = pd->fragoff; pd->proto = IPPROTO_FRAGMENT; } /* FALLTHROUGH */ default: return (PF_PASS); } } DPFPRINTF(LOG_NOTICE, "IPv6 nested extension header limit"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } #endif /* INET6 */ u_int16_t pf_pkt_hash(sa_family_t af, uint8_t proto, const struct pf_addr *src, const struct pf_addr *dst, uint16_t sport, uint16_t dport) { uint32_t hash; hash = src->addr32[0] ^ dst->addr32[0]; #ifdef INET6 if (af == AF_INET6) { hash ^= src->addr32[1] ^ dst->addr32[1]; hash ^= src->addr32[2] ^ dst->addr32[2]; hash ^= src->addr32[3] ^ dst->addr32[3]; } #endif switch (proto) { case IPPROTO_TCP: case IPPROTO_UDP: hash ^= sport ^ dport; break; } return stoeplitz_n32(hash); } int pf_setup_pdesc(struct pf_pdesc *pd, sa_family_t af, int dir, struct pfi_kif *kif, struct mbuf *m, u_short *reason) { memset(pd, 0, sizeof(*pd)); pd->dir = dir; pd->kif = kif; /* kif is NULL when called by pflog */ pd->m = m; pd->sidx = (dir == PF_IN) ? 0 : 1; pd->didx = (dir == PF_IN) ? 1 : 0; pd->af = pd->naf = af; pd->rdomain = rtable_l2(pd->m->m_pkthdr.ph_rtableid); switch (pd->af) { case AF_INET: { struct ip *h; /* Check for illegal packets */ if (pd->m->m_pkthdr.len < (int)sizeof(struct ip)) { REASON_SET(reason, PFRES_SHORT); return (PF_DROP); } h = mtod(pd->m, struct ip *); if (pd->m->m_pkthdr.len < ntohs(h->ip_len)) { REASON_SET(reason, PFRES_SHORT); return (PF_DROP); } if (pf_walk_header(pd, h, reason) != PF_PASS) return (PF_DROP); pd->src = (struct pf_addr *)&h->ip_src; pd->dst = (struct pf_addr *)&h->ip_dst; pd->tot_len = ntohs(h->ip_len); pd->tos = h->ip_tos & ~IPTOS_ECN_MASK; pd->ttl = h->ip_ttl; pd->virtual_proto = (h->ip_off & htons(IP_MF | IP_OFFMASK)) ? PF_VPROTO_FRAGMENT : pd->proto; break; } #ifdef INET6 case AF_INET6: { struct ip6_hdr *h; /* Check for illegal packets */ if (pd->m->m_pkthdr.len < (int)sizeof(struct ip6_hdr)) { REASON_SET(reason, PFRES_SHORT); return (PF_DROP); } h = mtod(pd->m, struct ip6_hdr *); if (pd->m->m_pkthdr.len < sizeof(struct ip6_hdr) + ntohs(h->ip6_plen)) { REASON_SET(reason, PFRES_SHORT); return (PF_DROP); } if (pf_walk_header6(pd, h, reason) != PF_PASS) return (PF_DROP); #if 1 /* * we do not support jumbogram yet. if we keep going, zero * ip6_plen will do something bad, so drop the packet for now. */ if (pd->jumbolen != 0) { REASON_SET(reason, PFRES_NORM); return (PF_DROP); } #endif /* 1 */ pd->src = (struct pf_addr *)&h->ip6_src; pd->dst = (struct pf_addr *)&h->ip6_dst; pd->tot_len = ntohs(h->ip6_plen) + sizeof(struct ip6_hdr); pd->tos = (ntohl(h->ip6_flow) & 0x0fc00000) >> 20; pd->ttl = h->ip6_hlim; pd->virtual_proto = (pd->fragoff != 0) ? PF_VPROTO_FRAGMENT : pd->proto; break; } #endif /* INET6 */ default: panic("pf_setup_pdesc called with illegal af %u", pd->af); } pf_addrcpy(&pd->nsaddr, pd->src, pd->af); pf_addrcpy(&pd->ndaddr, pd->dst, pd->af); switch (pd->virtual_proto) { case IPPROTO_TCP: { struct tcphdr *th = &pd->hdr.tcp; if (!pf_pull_hdr(pd->m, pd->off, th, sizeof(*th), reason, pd->af)) return (PF_DROP); pd->hdrlen = sizeof(*th); if (th->th_dport == 0 || pd->off + (th->th_off << 2) > pd->tot_len || (th->th_off << 2) < sizeof(struct tcphdr)) { REASON_SET(reason, PFRES_SHORT); return (PF_DROP); } pd->p_len = pd->tot_len - pd->off - (th->th_off << 2); pd->sport = &th->th_sport; pd->dport = &th->th_dport; pd->pcksum = &th->th_sum; break; } case IPPROTO_UDP: { struct udphdr *uh = &pd->hdr.udp; if (!pf_pull_hdr(pd->m, pd->off, uh, sizeof(*uh), reason, pd->af)) return (PF_DROP); pd->hdrlen = sizeof(*uh); if (uh->uh_dport == 0 || pd->off + ntohs(uh->uh_ulen) > pd->tot_len || ntohs(uh->uh_ulen) < sizeof(struct udphdr)) { REASON_SET(reason, PFRES_SHORT); return (PF_DROP); } pd->sport = &uh->uh_sport; pd->dport = &uh->uh_dport; pd->pcksum = &uh->uh_sum; break; } case IPPROTO_ICMP: { if (!pf_pull_hdr(pd->m, pd->off, &pd->hdr.icmp, ICMP_MINLEN, reason, pd->af)) return (PF_DROP); pd->hdrlen = ICMP_MINLEN; if (pd->off + pd->hdrlen > pd->tot_len) { REASON_SET(reason, PFRES_SHORT); return (PF_DROP); } pd->pcksum = &pd->hdr.icmp.icmp_cksum; break; } #ifdef INET6 case IPPROTO_ICMPV6: { size_t icmp_hlen = sizeof(struct icmp6_hdr); if (!pf_pull_hdr(pd->m, pd->off, &pd->hdr.icmp6, icmp_hlen, reason, pd->af)) return (PF_DROP); /* ICMP headers we look further into to match state */ switch (pd->hdr.icmp6.icmp6_type) { case MLD_LISTENER_QUERY: case MLD_LISTENER_REPORT: icmp_hlen = sizeof(struct mld_hdr); break; case ND_NEIGHBOR_SOLICIT: case ND_NEIGHBOR_ADVERT: icmp_hlen = sizeof(struct nd_neighbor_solicit); /* FALLTHROUGH */ case ND_ROUTER_SOLICIT: case ND_ROUTER_ADVERT: case ND_REDIRECT: if (pd->ttl != 255) { REASON_SET(reason, PFRES_NORM); return (PF_DROP); } break; } if (icmp_hlen > sizeof(struct icmp6_hdr) && !pf_pull_hdr(pd->m, pd->off, &pd->hdr.icmp6, icmp_hlen, reason, pd->af)) return (PF_DROP); pd->hdrlen = icmp_hlen; if (pd->off + pd->hdrlen > pd->tot_len) { REASON_SET(reason, PFRES_SHORT); return (PF_DROP); } pd->pcksum = &pd->hdr.icmp6.icmp6_cksum; break; } #endif /* INET6 */ } if (pd->sport) pd->osport = pd->nsport = *pd->sport; if (pd->dport) pd->odport = pd->ndport = *pd->dport; pd->hash = pf_pkt_hash(pd->af, pd->proto, pd->src, pd->dst, pd->osport, pd->odport); return (PF_PASS); } void pf_counters_inc(int action, struct pf_pdesc *pd, struct pf_state *st, struct pf_rule *r, struct pf_rule *a) { int dirndx; pd->kif->pfik_bytes[pd->af == AF_INET6][pd->dir == PF_OUT] [action != PF_PASS] += pd->tot_len; pd->kif->pfik_packets[pd->af == AF_INET6][pd->dir == PF_OUT] [action != PF_PASS]++; if (action == PF_PASS || action == PF_AFRT || r->action == PF_DROP) { dirndx = (pd->dir == PF_OUT); r->packets[dirndx]++; r->bytes[dirndx] += pd->tot_len; if (a != NULL) { a->packets[dirndx]++; a->bytes[dirndx] += pd->tot_len; } if (st != NULL) { struct pf_rule_item *ri; struct pf_sn_item *sni; SLIST_FOREACH(sni, &st->src_nodes, next) { sni->sn->packets[dirndx]++; sni->sn->bytes[dirndx] += pd->tot_len; } dirndx = (pd->dir == st->direction) ? 0 : 1; st->packets[dirndx]++; st->bytes[dirndx] += pd->tot_len; SLIST_FOREACH(ri, &st->match_rules, entry) { ri->r->packets[dirndx]++; ri->r->bytes[dirndx] += pd->tot_len; if (ri->r->src.addr.type == PF_ADDR_TABLE) pfr_update_stats(ri->r->src.addr.p.tbl, &st->key[(st->direction == PF_IN)]-> addr[(st->direction == PF_OUT)], pd, ri->r->action, ri->r->src.neg); if (ri->r->dst.addr.type == PF_ADDR_TABLE) pfr_update_stats(ri->r->dst.addr.p.tbl, &st->key[(st->direction == PF_IN)]-> addr[(st->direction == PF_IN)], pd, ri->r->action, ri->r->dst.neg); } } if (r->src.addr.type == PF_ADDR_TABLE) pfr_update_stats(r->src.addr.p.tbl, (st == NULL) ? pd->src : &st->key[(st->direction == PF_IN)]-> addr[(st->direction == PF_OUT)], pd, r->action, r->src.neg); if (r->dst.addr.type == PF_ADDR_TABLE) pfr_update_stats(r->dst.addr.p.tbl, (st == NULL) ? pd->dst : &st->key[(st->direction == PF_IN)]-> addr[(st->direction == PF_IN)], pd, r->action, r->dst.neg); } } int pf_test(sa_family_t af, int fwdir, struct ifnet *ifp, struct mbuf **m0) { #if NCARP > 0 struct ifnet *ifp0; #endif struct pfi_kif *kif; u_short action, reason = 0; struct pf_rule *a = NULL, *r = &pf_default_rule; struct pf_state *st = NULL; struct pf_state_key_cmp key; struct pf_ruleset *ruleset = NULL; struct pf_pdesc pd; int dir = (fwdir == PF_FWD) ? PF_OUT : fwdir; u_int32_t qid, pqid = 0; int have_pf_lock = 0; if (!pf_status.running) return (PF_PASS); #if NCARP > 0 if (ifp->if_type == IFT_CARP && (ifp0 = if_get(ifp->if_carpdevidx)) != NULL) { kif = (struct pfi_kif *)ifp0->if_pf_kif; if_put(ifp0); } else #endif /* NCARP */ kif = (struct pfi_kif *)ifp->if_pf_kif; if (kif == NULL) { DPFPRINTF(LOG_ERR, "%s: kif == NULL, if_xname %s", __func__, ifp->if_xname); return (PF_DROP); } if (kif->pfik_flags & PFI_IFLAG_SKIP) return (PF_PASS); #ifdef DIAGNOSTIC if (((*m0)->m_flags & M_PKTHDR) == 0) panic("non-M_PKTHDR is passed to pf_test"); #endif /* DIAGNOSTIC */ if ((*m0)->m_pkthdr.pf.flags & PF_TAG_GENERATED) return (PF_PASS); if ((*m0)->m_pkthdr.pf.flags & PF_TAG_DIVERTED_PACKET) { (*m0)->m_pkthdr.pf.flags &= ~PF_TAG_DIVERTED_PACKET; return (PF_PASS); } if ((*m0)->m_pkthdr.pf.flags & PF_TAG_REFRAGMENTED) { (*m0)->m_pkthdr.pf.flags &= ~PF_TAG_REFRAGMENTED; return (PF_PASS); } action = pf_setup_pdesc(&pd, af, dir, kif, *m0, &reason); if (action != PF_PASS) { #if NPFLOG > 0 pd.pflog |= PF_LOG_FORCE; #endif /* NPFLOG > 0 */ goto done; } /* packet normalization and reassembly */ switch (pd.af) { case AF_INET: action = pf_normalize_ip(&pd, &reason); break; #ifdef INET6 case AF_INET6: action = pf_normalize_ip6(&pd, &reason); break; #endif /* INET6 */ } *m0 = pd.m; /* if packet sits in reassembly queue, return without error */ if (pd.m == NULL) return PF_PASS; if (action != PF_PASS) { #if NPFLOG > 0 pd.pflog |= PF_LOG_FORCE; #endif /* NPFLOG > 0 */ goto done; } /* if packet has been reassembled, update packet description */ if (pf_status.reass && pd.virtual_proto == PF_VPROTO_FRAGMENT) { action = pf_setup_pdesc(&pd, af, dir, kif, pd.m, &reason); if (action != PF_PASS) { #if NPFLOG > 0 pd.pflog |= PF_LOG_FORCE; #endif /* NPFLOG > 0 */ goto done; } } pd.m->m_pkthdr.pf.flags |= PF_TAG_PROCESSED; /* * Avoid pcb-lookups from the forwarding path. They should never * match and would cause MP locking problems. */ if (fwdir == PF_FWD) { pd.lookup.done = -1; pd.lookup.uid = -1; pd.lookup.gid = -1; pd.lookup.pid = NO_PID; } switch (pd.virtual_proto) { case PF_VPROTO_FRAGMENT: { /* * handle fragments that aren't reassembled by * normalization */ PF_LOCK(); have_pf_lock = 1; action = pf_test_rule(&pd, &r, &st, &a, &ruleset, &reason); st = pf_state_ref(st); if (action != PF_PASS) REASON_SET(&reason, PFRES_FRAG); break; } case IPPROTO_ICMP: { if (pd.af != AF_INET) { action = PF_DROP; REASON_SET(&reason, PFRES_NORM); DPFPRINTF(LOG_NOTICE, "dropping IPv6 packet with ICMPv4 payload"); break; } PF_STATE_ENTER_READ(); action = pf_test_state_icmp(&pd, &st, &reason); st = pf_state_ref(st); PF_STATE_EXIT_READ(); if (action == PF_PASS || action == PF_AFRT) { #if NPFSYNC > 0 pfsync_update_state(st); #endif /* NPFSYNC > 0 */ r = st->rule.ptr; a = st->anchor.ptr; #if NPFLOG > 0 pd.pflog |= st->log; #endif /* NPFLOG > 0 */ } else if (st == NULL) { PF_LOCK(); have_pf_lock = 1; action = pf_test_rule(&pd, &r, &st, &a, &ruleset, &reason); st = pf_state_ref(st); } break; } #ifdef INET6 case IPPROTO_ICMPV6: { if (pd.af != AF_INET6) { action = PF_DROP; REASON_SET(&reason, PFRES_NORM); DPFPRINTF(LOG_NOTICE, "dropping IPv4 packet with ICMPv6 payload"); break; } PF_STATE_ENTER_READ(); action = pf_test_state_icmp(&pd, &st, &reason); st = pf_state_ref(st); PF_STATE_EXIT_READ(); if (action == PF_PASS || action == PF_AFRT) { #if NPFSYNC > 0 pfsync_update_state(st); #endif /* NPFSYNC > 0 */ r = st->rule.ptr; a = st->anchor.ptr; #if NPFLOG > 0 pd.pflog |= st->log; #endif /* NPFLOG > 0 */ } else if (st == NULL) { PF_LOCK(); have_pf_lock = 1; action = pf_test_rule(&pd, &r, &st, &a, &ruleset, &reason); st = pf_state_ref(st); } break; } #endif /* INET6 */ default: if (pd.virtual_proto == IPPROTO_TCP) { if (pd.dir == PF_IN && (pd.hdr.tcp.th_flags & (TH_SYN|TH_ACK)) == TH_SYN && pf_synflood_check(&pd)) { PF_LOCK(); have_pf_lock = 1; pf_syncookie_send(&pd); action = PF_DROP; break; } if ((pd.hdr.tcp.th_flags & TH_ACK) && pd.p_len == 0) pqid = 1; action = pf_normalize_tcp(&pd); if (action == PF_DROP) break; } key.af = pd.af; key.proto = pd.virtual_proto; key.rdomain = pd.rdomain; pf_addrcpy(&key.addr[pd.sidx], pd.src, key.af); pf_addrcpy(&key.addr[pd.didx], pd.dst, key.af); key.port[pd.sidx] = pd.osport; key.port[pd.didx] = pd.odport; key.hash = pd.hash; PF_STATE_ENTER_READ(); action = pf_find_state(&pd, &key, &st); st = pf_state_ref(st); PF_STATE_EXIT_READ(); /* check for syncookies if tcp ack and no active state */ if (pd.dir == PF_IN && pd.virtual_proto == IPPROTO_TCP && (st == NULL || (st->src.state >= TCPS_FIN_WAIT_2 && st->dst.state >= TCPS_FIN_WAIT_2)) && (pd.hdr.tcp.th_flags & (TH_SYN|TH_ACK|TH_RST)) == TH_ACK && pf_syncookie_validate(&pd)) { struct mbuf *msyn = pf_syncookie_recreate_syn(&pd); if (msyn) { action = pf_test(af, fwdir, ifp, &msyn); m_freem(msyn); if (action == PF_PASS || action == PF_AFRT) { PF_STATE_ENTER_READ(); pf_state_unref(st); action = pf_find_state(&pd, &key, &st); st = pf_state_ref(st); PF_STATE_EXIT_READ(); if (st == NULL) return (PF_DROP); st->src.seqhi = st->dst.seqhi = ntohl(pd.hdr.tcp.th_ack) - 1; st->src.seqlo = ntohl(pd.hdr.tcp.th_seq) - 1; pf_set_protostate(st, PF_PEER_SRC, PF_TCPS_PROXY_DST); } } else action = PF_DROP; } if (action == PF_MATCH) action = pf_test_state(&pd, &st, &reason); if (action == PF_PASS || action == PF_AFRT) { #if NPFSYNC > 0 pfsync_update_state(st); #endif /* NPFSYNC > 0 */ r = st->rule.ptr; a = st->anchor.ptr; #if NPFLOG > 0 pd.pflog |= st->log; #endif /* NPFLOG > 0 */ } else if (st == NULL) { PF_LOCK(); have_pf_lock = 1; action = pf_test_rule(&pd, &r, &st, &a, &ruleset, &reason); st = pf_state_ref(st); } if (pd.virtual_proto == IPPROTO_TCP) { if (st) { if (st->max_mss) pf_normalize_mss(&pd, st->max_mss); } else if (r->max_mss) pf_normalize_mss(&pd, r->max_mss); } break; } if (have_pf_lock != 0) PF_UNLOCK(); /* * At the moment, we rely on NET_LOCK() to prevent removal of items * we've collected above ('r', 'anchor' and 'ruleset'). They'll have * to be refcounted when NET_LOCK() is gone. */ done: if (action != PF_DROP) { if (st) { /* The non-state case is handled in pf_test_rule() */ if (action == PF_PASS && pd.badopts != 0 && !(st->state_flags & PFSTATE_ALLOWOPTS)) { action = PF_DROP; REASON_SET(&reason, PFRES_IPOPTIONS); #if NPFLOG > 0 pd.pflog |= PF_LOG_FORCE; #endif /* NPFLOG > 0 */ DPFPRINTF(LOG_NOTICE, "dropping packet with " "ip/ipv6 options in pf_test()"); } pf_scrub(pd.m, st->state_flags, pd.af, st->min_ttl, st->set_tos); pf_tag_packet(pd.m, st->tag, st->rtableid[pd.didx]); if (pqid || (pd.tos & IPTOS_LOWDELAY)) { qid = st->pqid; if (st->state_flags & PFSTATE_SETPRIO) { pd.m->m_pkthdr.pf.prio = st->set_prio[1]; } } else { qid = st->qid; if (st->state_flags & PFSTATE_SETPRIO) { pd.m->m_pkthdr.pf.prio = st->set_prio[0]; } } pd.m->m_pkthdr.pf.delay = st->delay; } else { pf_scrub(pd.m, r->scrub_flags, pd.af, r->min_ttl, r->set_tos); if (pqid || (pd.tos & IPTOS_LOWDELAY)) { qid = r->pqid; if (r->scrub_flags & PFSTATE_SETPRIO) pd.m->m_pkthdr.pf.prio = r->set_prio[1]; } else { qid = r->qid; if (r->scrub_flags & PFSTATE_SETPRIO) pd.m->m_pkthdr.pf.prio = r->set_prio[0]; } pd.m->m_pkthdr.pf.delay = r->delay; } } if (action == PF_PASS && qid) pd.m->m_pkthdr.pf.qid = qid; if (pd.dir == PF_IN && st && st->key[PF_SK_STACK]) pf_mbuf_link_state_key(pd.m, st->key[PF_SK_STACK]); if (pd.dir == PF_OUT && st && st->key[PF_SK_STACK]) pf_state_key_link_inpcb(st->key[PF_SK_STACK], pd.m->m_pkthdr.pf.inp); if (st != NULL && !ISSET(pd.m->m_pkthdr.csum_flags, M_FLOWID)) { pd.m->m_pkthdr.ph_flowid = st->key[PF_SK_WIRE]->hash; SET(pd.m->m_pkthdr.csum_flags, M_FLOWID); } /* * connections redirected to loopback should not match sockets * bound specifically to loopback due to security implications, * see in_pcblookup_listen(). */ if (pd.destchg) if ((pd.af == AF_INET && (ntohl(pd.dst->v4.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) || (pd.af == AF_INET6 && IN6_IS_ADDR_LOOPBACK(&pd.dst->v6))) pd.m->m_pkthdr.pf.flags |= PF_TAG_TRANSLATE_LOCALHOST; /* We need to redo the route lookup on outgoing routes. */ if (pd.destchg && pd.dir == PF_OUT) pd.m->m_pkthdr.pf.flags |= PF_TAG_REROUTE; if (pd.dir == PF_IN && action == PF_PASS && (r->divert.type == PF_DIVERT_TO || r->divert.type == PF_DIVERT_REPLY)) { struct pf_divert *divert; if ((divert = pf_get_divert(pd.m))) { pd.m->m_pkthdr.pf.flags |= PF_TAG_DIVERTED; divert->addr = r->divert.addr; divert->port = r->divert.port; divert->rdomain = pd.rdomain; divert->type = r->divert.type; } } if (action == PF_PASS && r->divert.type == PF_DIVERT_PACKET) action = PF_DIVERT; #if NPFLOG > 0 if (pd.pflog) { struct pf_rule_item *ri; if (pd.pflog & PF_LOG_FORCE || r->log & PF_LOG_ALL) pflog_packet(&pd, reason, r, a, ruleset, NULL); if (st) { SLIST_FOREACH(ri, &st->match_rules, entry) if (ri->r->log & PF_LOG_ALL) pflog_packet(&pd, reason, ri->r, a, ruleset, NULL); } } #endif /* NPFLOG > 0 */ pf_counters_inc(action, &pd, st, r, a); switch (action) { case PF_SYNPROXY_DROP: m_freem(pd.m); /* FALLTHROUGH */ case PF_DEFER: pd.m = NULL; action = PF_PASS; break; case PF_DIVERT: switch (pd.af) { case AF_INET: divert_packet(pd.m, pd.dir, r->divert.port); pd.m = NULL; break; #ifdef INET6 case AF_INET6: divert6_packet(pd.m, pd.dir, r->divert.port); pd.m = NULL; break; #endif /* INET6 */ } action = PF_PASS; break; #ifdef INET6 case PF_AFRT: if (pf_translate_af(&pd)) { action = PF_DROP; break; } pd.m->m_pkthdr.pf.flags |= PF_TAG_GENERATED; switch (pd.naf) { case AF_INET: if (pd.dir == PF_IN) { if (ipforwarding == 0) { ipstat_inc(ips_cantforward); action = PF_DROP; break; } ip_forward(pd.m, ifp, NULL, 1); } else ip_output(pd.m, NULL, NULL, 0, NULL, NULL, 0); break; case AF_INET6: if (pd.dir == PF_IN) { if (ip6_forwarding == 0) { ip6stat_inc(ip6s_cantforward); action = PF_DROP; break; } ip6_forward(pd.m, NULL, 1); } else ip6_output(pd.m, NULL, NULL, 0, NULL, NULL); break; } if (action != PF_DROP) { pd.m = NULL; action = PF_PASS; } break; #endif /* INET6 */ case PF_DROP: m_freem(pd.m); pd.m = NULL; break; default: if (st && st->rt) { switch (pd.af) { case AF_INET: pf_route(&pd, st); break; #ifdef INET6 case AF_INET6: pf_route6(&pd, st); break; #endif /* INET6 */ } } break; } #ifdef INET6 /* if reassembled packet passed, create new fragments */ if (pf_status.reass && action == PF_PASS && pd.m && fwdir == PF_FWD && pd.af == AF_INET6) { struct m_tag *mtag; if ((mtag = m_tag_find(pd.m, PACKET_TAG_PF_REASSEMBLED, NULL))) action = pf_refragment6(&pd.m, mtag, NULL, NULL, NULL); } #endif /* INET6 */ if (st && action != PF_DROP) { if (!st->if_index_in && dir == PF_IN) st->if_index_in = ifp->if_index; else if (!st->if_index_out && dir == PF_OUT) st->if_index_out = ifp->if_index; } *m0 = pd.m; pf_state_unref(st); return (action); } int pf_ouraddr(struct mbuf *m) { struct pf_state_key *sk; if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) return (1); sk = m->m_pkthdr.pf.statekey; if (sk != NULL) { if (READ_ONCE(sk->sk_inp) != NULL) return (1); } return (-1); } /* * must be called whenever any addressing information such as * address, port, protocol has changed */ void pf_pkt_addr_changed(struct mbuf *m) { pf_mbuf_unlink_state_key(m); pf_mbuf_unlink_inpcb(m); } struct inpcb * pf_inp_lookup(struct mbuf *m) { struct inpcb *inp = NULL; struct pf_state_key *sk = m->m_pkthdr.pf.statekey; if (!pf_state_key_isvalid(sk)) pf_mbuf_unlink_state_key(m); else if (READ_ONCE(sk->sk_inp) != NULL) { mtx_enter(&pf_inp_mtx); inp = in_pcbref(sk->sk_inp); mtx_leave(&pf_inp_mtx); } return (inp); } void pf_inp_link(struct mbuf *m, struct inpcb *inp) { struct pf_state_key *sk = m->m_pkthdr.pf.statekey; if (!pf_state_key_isvalid(sk)) { pf_mbuf_unlink_state_key(m); return; } /* * we don't need to grab PF-lock here. At worst case we link inp to * state, which might be just being marked as deleted by another * thread. */ pf_state_key_link_inpcb(sk, inp); /* The statekey has finished finding the inp, it is no longer needed. */ pf_mbuf_unlink_state_key(m); } void pf_inp_unlink(struct inpcb *inp) { struct pf_state_key *sk; if (READ_ONCE(inp->inp_pf_sk) == NULL) return; mtx_enter(&pf_inp_mtx); sk = inp->inp_pf_sk; if (sk == NULL) { mtx_leave(&pf_inp_mtx); return; } KASSERT(sk->sk_inp == inp); sk->sk_inp = NULL; inp->inp_pf_sk = NULL; mtx_leave(&pf_inp_mtx); pf_state_key_unref(sk); in_pcbunref(inp); } void pf_state_key_link_reverse(struct pf_state_key *sk, struct pf_state_key *skrev) { struct pf_state_key *old_reverse; old_reverse = atomic_cas_ptr(&sk->sk_reverse, NULL, skrev); if (old_reverse != NULL) KASSERT(old_reverse == skrev); else { pf_state_key_ref(skrev); /* * NOTE: if sk == skrev, then KASSERT() below holds true, we * still want to grab a reference in such case, because * pf_state_key_unlink_reverse() does not check whether keys * are identical or not. */ old_reverse = atomic_cas_ptr(&skrev->sk_reverse, NULL, sk); if (old_reverse != NULL) KASSERT(old_reverse == sk); pf_state_key_ref(sk); } } #if NPFLOG > 0 void pf_log_matches(struct pf_pdesc *pd, struct pf_rule *rm, struct pf_rule *am, struct pf_ruleset *ruleset, struct pf_rule_slist *matchrules) { struct pf_rule_item *ri; /* if this is the log(matches) rule, packet has been logged already */ if (rm->log & PF_LOG_MATCHES) return; SLIST_FOREACH(ri, matchrules, entry) if (ri->r->log & PF_LOG_MATCHES) pflog_packet(pd, PFRES_MATCH, rm, am, ruleset, ri->r); } #endif /* NPFLOG > 0 */ struct pf_state_key * pf_state_key_ref(struct pf_state_key *sk) { if (sk != NULL) PF_REF_TAKE(sk->sk_refcnt); return (sk); } void pf_state_key_unref(struct pf_state_key *sk) { if (PF_REF_RELE(sk->sk_refcnt)) { /* state key must be removed from tree */ KASSERT(!pf_state_key_isvalid(sk)); /* state key must be unlinked from reverse key */ KASSERT(sk->sk_reverse == NULL); /* state key must be unlinked from socket */ KASSERT(sk->sk_inp == NULL); pool_put(&pf_state_key_pl, sk); } } int pf_state_key_isvalid(struct pf_state_key *sk) { return ((sk != NULL) && (sk->sk_removed == 0)); } void pf_mbuf_link_state_key(struct mbuf *m, struct pf_state_key *sk) { KASSERT(m->m_pkthdr.pf.statekey == NULL); m->m_pkthdr.pf.statekey = pf_state_key_ref(sk); } void pf_mbuf_unlink_state_key(struct mbuf *m) { struct pf_state_key *sk = m->m_pkthdr.pf.statekey; if (sk != NULL) { m->m_pkthdr.pf.statekey = NULL; pf_state_key_unref(sk); } } void pf_mbuf_link_inpcb(struct mbuf *m, struct inpcb *inp) { KASSERT(m->m_pkthdr.pf.inp == NULL); m->m_pkthdr.pf.inp = in_pcbref(inp); } void pf_mbuf_unlink_inpcb(struct mbuf *m) { struct inpcb *inp = m->m_pkthdr.pf.inp; if (inp != NULL) { m->m_pkthdr.pf.inp = NULL; in_pcbunref(inp); } } void pf_state_key_link_inpcb(struct pf_state_key *sk, struct inpcb *inp) { if (inp == NULL || READ_ONCE(sk->sk_inp) != NULL) return; mtx_enter(&pf_inp_mtx); if (inp->inp_pf_sk != NULL || sk->sk_inp != NULL) { mtx_leave(&pf_inp_mtx); return; } sk->sk_inp = in_pcbref(inp); inp->inp_pf_sk = pf_state_key_ref(sk); mtx_leave(&pf_inp_mtx); } void pf_state_key_unlink_inpcb(struct pf_state_key *sk) { struct inpcb *inp; if (READ_ONCE(sk->sk_inp) == NULL) return; mtx_enter(&pf_inp_mtx); inp = sk->sk_inp; if (inp == NULL) { mtx_leave(&pf_inp_mtx); return; } KASSERT(inp->inp_pf_sk == sk); sk->sk_inp = NULL; inp->inp_pf_sk = NULL; mtx_leave(&pf_inp_mtx); pf_state_key_unref(sk); in_pcbunref(inp); } void pf_state_key_unlink_reverse(struct pf_state_key *sk) { struct pf_state_key *skrev = sk->sk_reverse; /* Note that sk and skrev may be equal, then we unref twice. */ if (skrev != NULL) { KASSERT(skrev->sk_reverse == sk); sk->sk_reverse = NULL; skrev->sk_reverse = NULL; pf_state_key_unref(skrev); pf_state_key_unref(sk); } } struct pf_state * pf_state_ref(struct pf_state *st) { if (st != NULL) PF_REF_TAKE(st->refcnt); return (st); } void pf_state_unref(struct pf_state *st) { if ((st != NULL) && PF_REF_RELE(st->refcnt)) { /* never inserted or removed */ #if NPFSYNC > 0 KASSERT((TAILQ_NEXT(st, sync_list) == NULL) || ((TAILQ_NEXT(st, sync_list) == _Q_INVALID) && (st->sync_state >= PFSYNC_S_NONE))); #endif /* NPFSYNC */ KASSERT((TAILQ_NEXT(st, entry_list) == NULL) || (TAILQ_NEXT(st, entry_list) == _Q_INVALID)); pf_state_key_unref(st->key[PF_SK_WIRE]); pf_state_key_unref(st->key[PF_SK_STACK]); pool_put(&pf_state_pl, st); } } int pf_delay_pkt(struct mbuf *m, u_int ifidx) { struct pf_pktdelay *pdy; if ((pdy = pool_get(&pf_pktdelay_pl, PR_NOWAIT)) == NULL) { m_freem(m); return (ENOBUFS); } pdy->ifidx = ifidx; pdy->m = m; timeout_set(&pdy->to, pf_pktenqueue_delayed, pdy); timeout_add_msec(&pdy->to, m->m_pkthdr.pf.delay); m->m_pkthdr.pf.delay = 0; return (0); } void pf_pktenqueue_delayed(void *arg) { struct pf_pktdelay *pdy = arg; struct ifnet *ifp; ifp = if_get(pdy->ifidx); if (ifp != NULL) { if_enqueue(ifp, pdy->m); if_put(ifp); } else m_freem(pdy->m); pool_put(&pf_pktdelay_pl, pdy); }
335 335 43 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 /* $OpenBSD: strlcpy.c,v 1.9 2019/01/25 00:19:26 millert Exp $ */ /* * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <lib/libkern/libkern.h> /* * Copy string src to buffer dst of size dsize. At most dsize-1 * chars will be copied. Always NUL terminates (unless dsize == 0). * Returns strlen(src); if retval >= dsize, truncation occurred. */ size_t strlcpy(char *dst, const char *src, size_t dsize) { const char *osrc = src; size_t nleft = dsize; /* Copy as many bytes as will fit. */ if (nleft != 0) { while (--nleft != 0) { if ((*dst++ = *src++) == '\0') break; } } /* Not enough room in dst, add NUL and traverse rest of src. */ if (nleft == 0) { if (dsize != 0) *dst = '\0'; /* NUL-terminate dst */ while (*src++) ; } return(src - osrc - 1); /* count does not include NUL */ }
47 1 18 28 2 2 1 1 2 2 2 22 22 22 22 47 47 4 4 4 47 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 /* $OpenBSD: tcp_subr.c,v 1.201 2024/04/17 20:48:51 bluhm Exp $ */ /* $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 * * NRL grants permission for redistribution and use in source and binary * forms, with or without modification, of the software and documentation * created at NRL provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgements: * This product includes software developed by the University of * California, Berkeley and its contributors. * This product includes software developed at the Information * Technology Division, US Naval Research Laboratory. * 4. Neither the name of the NRL nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the US Naval * Research Laboratory (NRL). */ #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/mutex.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/timeout.h> #include <sys/protosw.h> #include <sys/kernel.h> #include <sys/pool.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/in_pcb.h> #include <netinet/ip_var.h> #include <netinet6/ip6_var.h> #include <netinet/ip_icmp.h> #include <netinet/tcp.h> #include <netinet/tcp_fsm.h> #include <netinet/tcp_seq.h> #include <netinet/tcp_timer.h> #include <netinet/tcp_var.h> #ifdef INET6 #include <netinet6/ip6protosw.h> #endif /* INET6 */ #include <crypto/md5.h> #include <crypto/sha2.h> /* * Locks used to protect struct members in this file: * I immutable after creation * T tcp_timer_mtx global tcp timer data structures */ struct mutex tcp_timer_mtx = MUTEX_INITIALIZER(IPL_SOFTNET); /* patchable/settable parameters for tcp */ int tcp_mssdflt = TCP_MSS; int tcp_rttdflt = TCPTV_SRTTDFLT; /* values controllable via sysctl */ int tcp_do_rfc1323 = 1; int tcp_do_sack = 1; /* RFC 2018 selective ACKs */ int tcp_ack_on_push = 0; /* set to enable immediate ACK-on-PUSH */ #ifdef TCP_ECN int tcp_do_ecn = 0; /* RFC3168 ECN enabled/disabled? */ #endif int tcp_do_rfc3390 = 2; /* Increase TCP's Initial Window to 10*mss */ int tcp_do_tso = 1; /* TCP segmentation offload for output */ #ifndef TCB_INITIAL_HASH_SIZE #define TCB_INITIAL_HASH_SIZE 128 #endif int tcp_reass_limit = NMBCLUSTERS / 8; /* hardlimit for tcpqe_pool */ int tcp_sackhole_limit = 32*1024; /* hardlimit for sackhl_pool */ struct pool tcpcb_pool; struct pool tcpqe_pool; struct pool sackhl_pool; struct cpumem *tcpcounters; /* tcp statistics */ u_char tcp_secret[16]; /* [I] */ SHA2_CTX tcp_secret_ctx; /* [I] */ tcp_seq tcp_iss; /* [T] updated by timer and connection */ uint64_t tcp_starttime; /* [I] random offset for tcp_now() */ /* * Tcp initialization */ void tcp_init(void) { tcp_iss = 1; /* wrong */ /* 0 is treated special so add 1, 63 bits to count is enough */ arc4random_buf(&tcp_starttime, sizeof(tcp_starttime)); tcp_starttime = 1ULL + (tcp_starttime / 2); pool_init(&tcpcb_pool, sizeof(struct tcpcb), 0, IPL_SOFTNET, 0, "tcpcb", NULL); pool_init(&tcpqe_pool, sizeof(struct tcpqent), 0, IPL_SOFTNET, 0, "tcpqe", NULL); pool_sethardlimit(&tcpqe_pool, tcp_reass_limit, NULL, 0); pool_init(&sackhl_pool, sizeof(struct sackhole), 0, IPL_SOFTNET, 0, "sackhl", NULL); pool_sethardlimit(&sackhl_pool, tcp_sackhole_limit, NULL, 0); in_pcbinit(&tcbtable, TCB_INITIAL_HASH_SIZE); #ifdef INET6 in_pcbinit(&tcb6table, TCB_INITIAL_HASH_SIZE); #endif tcpcounters = counters_alloc(tcps_ncounters); arc4random_buf(tcp_secret, sizeof(tcp_secret)); SHA512Init(&tcp_secret_ctx); SHA512Update(&tcp_secret_ctx, tcp_secret, sizeof(tcp_secret)); #ifdef INET6 /* * Since sizeof(struct ip6_hdr) > sizeof(struct ip), we * do max length checks/computations only on the former. */ if (max_protohdr < (sizeof(struct ip6_hdr) + sizeof(struct tcphdr))) max_protohdr = (sizeof(struct ip6_hdr) + sizeof(struct tcphdr)); if ((max_linkhdr + sizeof(struct ip6_hdr) + sizeof(struct tcphdr)) > MHLEN) panic("tcp_init"); icmp6_mtudisc_callback_register(tcp6_mtudisc_callback); #endif /* INET6 */ /* Initialize the compressed state engine. */ syn_cache_init(); /* Initialize timer state. */ tcp_timer_init(); } /* * Create template to be used to send tcp packets on a connection. * Call after host entry created, allocates an mbuf and fills * in a skeletal tcp/ip header, minimizing the amount of work * necessary when the connection is used. * * To support IPv6 in addition to IPv4 and considering that the sizes of * the IPv4 and IPv6 headers are not the same, we now use a separate pointer * for the TCP header. Also, we made the former tcpiphdr header pointer * into just an IP overlay pointer, with casting as appropriate for v6. rja */ struct mbuf * tcp_template(struct tcpcb *tp) { struct inpcb *inp = tp->t_inpcb; struct mbuf *m; struct tcphdr *th; CTASSERT(sizeof(struct ip) + sizeof(struct tcphdr) <= MHLEN); CTASSERT(sizeof(struct ip6_hdr) + sizeof(struct tcphdr) <= MHLEN); if ((m = tp->t_template) == 0) { m = m_get(M_DONTWAIT, MT_HEADER); if (m == NULL) return (0); switch (tp->pf) { case 0: /*default to PF_INET*/ case AF_INET: m->m_len = sizeof(struct ip); break; #ifdef INET6 case AF_INET6: m->m_len = sizeof(struct ip6_hdr); break; #endif /* INET6 */ } m->m_len += sizeof (struct tcphdr); } switch(tp->pf) { case AF_INET: { struct ipovly *ipovly; ipovly = mtod(m, struct ipovly *); bzero(ipovly->ih_x1, sizeof ipovly->ih_x1); ipovly->ih_pr = IPPROTO_TCP; ipovly->ih_len = htons(sizeof (struct tcphdr)); ipovly->ih_src = inp->inp_laddr; ipovly->ih_dst = inp->inp_faddr; th = (struct tcphdr *)(mtod(m, caddr_t) + sizeof(struct ip)); } break; #ifdef INET6 case AF_INET6: { struct ip6_hdr *ip6; ip6 = mtod(m, struct ip6_hdr *); ip6->ip6_src = inp->inp_laddr6; ip6->ip6_dst = inp->inp_faddr6; ip6->ip6_flow = htonl(0x60000000) | (inp->inp_flowinfo & IPV6_FLOWLABEL_MASK); ip6->ip6_nxt = IPPROTO_TCP; ip6->ip6_plen = htons(sizeof(struct tcphdr)); /*XXX*/ ip6->ip6_hlim = in6_selecthlim(inp); /*XXX*/ th = (struct tcphdr *)(mtod(m, caddr_t) + sizeof(struct ip6_hdr)); } break; #endif /* INET6 */ } th->th_sport = inp->inp_lport; th->th_dport = inp->inp_fport; th->th_seq = 0; th->th_ack = 0; th->th_x2 = 0; th->th_off = 5; th->th_flags = 0; th->th_win = 0; th->th_urp = 0; th->th_sum = 0; return (m); } /* * Send a single message to the TCP at address specified by * the given TCP/IP header. If m == 0, then we make a copy * of the tcpiphdr at ti and send directly to the addressed host. * This is used to force keep alive messages out using the TCP * template for a connection tp->t_template. If flags are given * then we send a message back to the TCP which originated the * segment ti, and discard the mbuf containing it and any other * attached mbufs. * * In any case the ack and sequence number of the transmitted * segment are as specified by the parameters. */ void tcp_respond(struct tcpcb *tp, caddr_t template, struct tcphdr *th0, tcp_seq ack, tcp_seq seq, int flags, u_int rtableid, uint64_t now) { int tlen; int win = 0; struct mbuf *m = NULL; struct tcphdr *th; struct ip *ip; #ifdef INET6 struct ip6_hdr *ip6; #endif int af; /* af on wire */ if (tp) { struct socket *so = tp->t_inpcb->inp_socket; win = sbspace(so, &so->so_rcv); /* * If this is called with an unconnected * socket/tp/pcb (tp->pf is 0), we lose. */ af = tp->pf; } else af = (((struct ip *)template)->ip_v == 6) ? AF_INET6 : AF_INET; m = m_gethdr(M_DONTWAIT, MT_HEADER); if (m == NULL) return; m->m_data += max_linkhdr; tlen = 0; #define xchg(a,b,type) do { type t; t=a; a=b; b=t; } while (0) switch (af) { #ifdef INET6 case AF_INET6: ip6 = mtod(m, struct ip6_hdr *); th = (struct tcphdr *)(ip6 + 1); tlen = sizeof(*ip6) + sizeof(*th); if (th0) { bcopy(template, ip6, sizeof(*ip6)); bcopy(th0, th, sizeof(*th)); xchg(ip6->ip6_dst, ip6->ip6_src, struct in6_addr); } else { bcopy(template, ip6, tlen); } break; #endif /* INET6 */ case AF_INET: ip = mtod(m, struct ip *); th = (struct tcphdr *)(ip + 1); tlen = sizeof(*ip) + sizeof(*th); if (th0) { bcopy(template, ip, sizeof(*ip)); bcopy(th0, th, sizeof(*th)); xchg(ip->ip_dst.s_addr, ip->ip_src.s_addr, u_int32_t); } else { bcopy(template, ip, tlen); } break; } if (th0) xchg(th->th_dport, th->th_sport, u_int16_t); else flags = TH_ACK; #undef xchg th->th_seq = htonl(seq); th->th_ack = htonl(ack); th->th_x2 = 0; th->th_off = sizeof (struct tcphdr) >> 2; th->th_flags = flags; if (tp) win >>= tp->rcv_scale; if (win > TCP_MAXWIN) win = TCP_MAXWIN; th->th_win = htons((u_int16_t)win); th->th_urp = 0; if (tp && (tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP && (flags & TH_RST) == 0 && (tp->t_flags & TF_RCVD_TSTMP)) { u_int32_t *lp = (u_int32_t *)(th + 1); /* Form timestamp option as shown in appendix A of RFC 1323. */ *lp++ = htonl(TCPOPT_TSTAMP_HDR); *lp++ = htonl(now + tp->ts_modulate); *lp = htonl(tp->ts_recent); tlen += TCPOLEN_TSTAMP_APPA; th->th_off = (sizeof(struct tcphdr) + TCPOLEN_TSTAMP_APPA) >> 2; } m->m_len = tlen; m->m_pkthdr.len = tlen; m->m_pkthdr.ph_ifidx = 0; m->m_pkthdr.csum_flags |= M_TCP_CSUM_OUT; /* force routing table */ if (tp) m->m_pkthdr.ph_rtableid = tp->t_inpcb->inp_rtableid; else m->m_pkthdr.ph_rtableid = rtableid; switch (af) { #ifdef INET6 case AF_INET6: ip6->ip6_flow = htonl(0x60000000); ip6->ip6_nxt = IPPROTO_TCP; ip6->ip6_hlim = in6_selecthlim(tp ? tp->t_inpcb : NULL); /*XXX*/ ip6->ip6_plen = tlen - sizeof(struct ip6_hdr); ip6->ip6_plen = htons(ip6->ip6_plen); ip6_output(m, tp ? tp->t_inpcb->inp_outputopts6 : NULL, tp ? &tp->t_inpcb->inp_route : NULL, 0, NULL, tp ? &tp->t_inpcb->inp_seclevel : NULL); break; #endif /* INET6 */ case AF_INET: ip->ip_len = htons(tlen); ip->ip_ttl = ip_defttl; ip->ip_tos = 0; ip_output(m, NULL, tp ? &tp->t_inpcb->inp_route : NULL, ip_mtudisc ? IP_MTUDISC : 0, NULL, tp ? &tp->t_inpcb->inp_seclevel : NULL, 0); break; } } /* * Create a new TCP control block, making an * empty reassembly queue and hooking it to the argument * protocol control block. */ struct tcpcb * tcp_newtcpcb(struct inpcb *inp, int wait) { struct tcpcb *tp; int i; tp = pool_get(&tcpcb_pool, (wait == M_WAIT ? PR_WAITOK : PR_NOWAIT) | PR_ZERO); if (tp == NULL) return (NULL); TAILQ_INIT(&tp->t_segq); tp->t_maxseg = tcp_mssdflt; tp->t_maxopd = 0; for (i = 0; i < TCPT_NTIMERS; i++) TCP_TIMER_INIT(tp, i); tp->sack_enable = tcp_do_sack; tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0; tp->t_inpcb = inp; /* * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no * rtt estimate. Set rttvar so that srtt + 2 * rttvar gives * reasonable initial retransmit time. */ tp->t_srtt = TCPTV_SRTTBASE; tp->t_rttvar = tcp_rttdflt << (TCP_RTTVAR_SHIFT + TCP_RTT_BASE_SHIFT - 1); tp->t_rttmin = TCPTV_MIN; TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp), TCPTV_MIN, TCPTV_REXMTMAX); tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT; tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT; tp->t_pmtud_mtu_sent = 0; tp->t_pmtud_mss_acked = 0; #ifdef INET6 if (ISSET(inp->inp_flags, INP_IPV6)) { tp->pf = PF_INET6; inp->inp_ipv6.ip6_hlim = ip6_defhlim; } else #endif { tp->pf = PF_INET; inp->inp_ip.ip_ttl = ip_defttl; } inp->inp_ppcb = (caddr_t)tp; return (tp); } /* * Drop a TCP connection, reporting * the specified error. If connection is synchronized, * then send a RST to peer. */ struct tcpcb * tcp_drop(struct tcpcb *tp, int errno) { struct socket *so = tp->t_inpcb->inp_socket; if (TCPS_HAVERCVDSYN(tp->t_state)) { tp->t_state = TCPS_CLOSED; (void) tcp_output(tp); tcpstat_inc(tcps_drops); } else tcpstat_inc(tcps_conndrops); if (errno == ETIMEDOUT && tp->t_softerror) errno = tp->t_softerror; so->so_error = errno; return (tcp_close(tp)); } /* * Close a TCP control block: * discard all space held by the tcp * discard internet protocol block * wake up any sleepers */ struct tcpcb * tcp_close(struct tcpcb *tp) { struct inpcb *inp = tp->t_inpcb; struct socket *so = inp->inp_socket; struct sackhole *p, *q; /* free the reassembly queue, if any */ tcp_freeq(tp); tcp_canceltimers(tp); syn_cache_cleanup(tp); /* Free SACK holes. */ q = p = tp->snd_holes; while (p != 0) { q = p->next; pool_put(&sackhl_pool, p); p = q; } m_free(tp->t_template); /* Free tcpcb after all pending timers have been run. */ TCP_TIMER_ARM(tp, TCPT_REAPER, 1); inp->inp_ppcb = NULL; soisdisconnected(so); in_pcbdetach(inp); return (NULL); } int tcp_freeq(struct tcpcb *tp) { struct tcpqent *qe; int rv = 0; while ((qe = TAILQ_FIRST(&tp->t_segq)) != NULL) { TAILQ_REMOVE(&tp->t_segq, qe, tcpqe_q); m_freem(qe->tcpqe_m); pool_put(&tcpqe_pool, qe); rv = 1; } return (rv); } /* * Compute proper scaling value for receiver window from buffer space */ void tcp_rscale(struct tcpcb *tp, u_long hiwat) { tp->request_r_scale = 0; while (tp->request_r_scale < TCP_MAX_WINSHIFT && TCP_MAXWIN << tp->request_r_scale < hiwat) tp->request_r_scale++; } /* * Notify a tcp user of an asynchronous error; * store error as soft error, but wake up user * (for now, won't do anything until can select for soft error). */ void tcp_notify(struct inpcb *inp, int error) { struct tcpcb *tp = intotcpcb(inp); struct socket *so = inp->inp_socket; /* * Ignore some errors if we are hooked up. * If connection hasn't completed, has retransmitted several times, * and receives a second error, give up now. This is better * than waiting a long time to establish a connection that * can never complete. */ if (tp->t_state == TCPS_ESTABLISHED && (error == EHOSTUNREACH || error == ENETUNREACH || error == EHOSTDOWN)) { return; } else if (TCPS_HAVEESTABLISHED(tp->t_state) == 0 && tp->t_rxtshift > 3 && tp->t_softerror) so->so_error = error; else tp->t_softerror = error; wakeup((caddr_t) &so->so_timeo); sorwakeup(so); sowwakeup(so); } #ifdef INET6 void tcp6_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *d) { struct tcphdr th; struct tcpcb *tp; void (*notify)(struct inpcb *, int) = tcp_notify; struct ip6_hdr *ip6; const struct sockaddr_in6 *sa6_src = NULL; struct sockaddr_in6 *sa6 = satosin6(sa); struct inpcb *inp; struct mbuf *m; tcp_seq seq; int off; struct { u_int16_t th_sport; u_int16_t th_dport; u_int32_t th_seq; } *thp; CTASSERT(sizeof(*thp) <= sizeof(th)); if (sa->sa_family != AF_INET6 || sa->sa_len != sizeof(struct sockaddr_in6) || IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr) || IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) return; if ((unsigned)cmd >= PRC_NCMDS) return; else if (cmd == PRC_QUENCH) { /* * Don't honor ICMP Source Quench messages meant for * TCP connections. */ /* XXX there's no PRC_QUENCH in IPv6 */ return; } else if (PRC_IS_REDIRECT(cmd)) notify = in_rtchange, d = NULL; else if (cmd == PRC_MSGSIZE) ; /* special code is present, see below */ else if (cmd == PRC_HOSTDEAD) d = NULL; else if (inet6ctlerrmap[cmd] == 0) return; /* if the parameter is from icmp6, decode it. */ if (d != NULL) { struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d; m = ip6cp->ip6c_m; ip6 = ip6cp->ip6c_ip6; off = ip6cp->ip6c_off; sa6_src = ip6cp->ip6c_src; } else { m = NULL; ip6 = NULL; sa6_src = &sa6_any; } if (ip6) { /* * XXX: We assume that when ip6 is non NULL, * M and OFF are valid. */ /* check if we can safely examine src and dst ports */ if (m->m_pkthdr.len < off + sizeof(*thp)) return; bzero(&th, sizeof(th)); m_copydata(m, off, sizeof(*thp), &th); /* * Check to see if we have a valid TCP connection * corresponding to the address in the ICMPv6 message * payload. */ inp = in6_pcblookup(&tcb6table, &sa6->sin6_addr, th.th_dport, &sa6_src->sin6_addr, th.th_sport, rdomain); if (cmd == PRC_MSGSIZE) { /* * Depending on the value of "valid" and routing table * size (mtudisc_{hi,lo}wat), we will: * - recalculate the new MTU and create the * corresponding routing entry, or * - ignore the MTU change notification. */ icmp6_mtudisc_update((struct ip6ctlparam *)d, inp != NULL); in_pcbunref(inp); return; } if (inp) { seq = ntohl(th.th_seq); if ((tp = intotcpcb(inp)) && SEQ_GEQ(seq, tp->snd_una) && SEQ_LT(seq, tp->snd_max)) notify(inp, inet6ctlerrmap[cmd]); } else if (inet6ctlerrmap[cmd] == EHOSTUNREACH || inet6ctlerrmap[cmd] == ENETUNREACH || inet6ctlerrmap[cmd] == EHOSTDOWN) syn_cache_unreach(sin6tosa_const(sa6_src), sa, &th, rdomain); in_pcbunref(inp); } else { in6_pcbnotify(&tcb6table, sa6, 0, sa6_src, 0, rdomain, cmd, NULL, notify); } } #endif void tcp_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *v) { struct ip *ip = v; struct tcphdr *th; struct tcpcb *tp; struct inpcb *inp; struct in_addr faddr; tcp_seq seq; u_int mtu; void (*notify)(struct inpcb *, int) = tcp_notify; int errno; if (sa->sa_family != AF_INET) return; faddr = satosin(sa)->sin_addr; if (faddr.s_addr == INADDR_ANY) return; if ((unsigned)cmd >= PRC_NCMDS) return; errno = inetctlerrmap[cmd]; if (cmd == PRC_QUENCH) /* * Don't honor ICMP Source Quench messages meant for * TCP connections. */ return; else if (PRC_IS_REDIRECT(cmd)) notify = in_rtchange, ip = 0; else if (cmd == PRC_MSGSIZE && ip_mtudisc && ip) { /* * Verify that the packet in the icmp payload refers * to an existing TCP connection. */ th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2)); seq = ntohl(th->th_seq); inp = in_pcblookup(&tcbtable, ip->ip_dst, th->th_dport, ip->ip_src, th->th_sport, rdomain); if (inp && (tp = intotcpcb(inp)) && SEQ_GEQ(seq, tp->snd_una) && SEQ_LT(seq, tp->snd_max)) { struct icmp *icp; icp = (struct icmp *)((caddr_t)ip - offsetof(struct icmp, icmp_ip)); /* * If the ICMP message advertises a Next-Hop MTU * equal or larger than the maximum packet size we have * ever sent, drop the message. */ mtu = (u_int)ntohs(icp->icmp_nextmtu); if (mtu >= tp->t_pmtud_mtu_sent) { in_pcbunref(inp); return; } if (mtu >= tcp_hdrsz(tp) + tp->t_pmtud_mss_acked) { /* * Calculate new MTU, and create corresponding * route (traditional PMTUD). */ tp->t_flags &= ~TF_PMTUD_PEND; icmp_mtudisc(icp, inp->inp_rtableid); } else { /* * Record the information got in the ICMP * message; act on it later. * If we had already recorded an ICMP message, * replace the old one only if the new message * refers to an older TCP segment */ if (tp->t_flags & TF_PMTUD_PEND) { if (SEQ_LT(tp->t_pmtud_th_seq, seq)) { in_pcbunref(inp); return; } } else tp->t_flags |= TF_PMTUD_PEND; tp->t_pmtud_th_seq = seq; tp->t_pmtud_nextmtu = icp->icmp_nextmtu; tp->t_pmtud_ip_len = icp->icmp_ip.ip_len; tp->t_pmtud_ip_hl = icp->icmp_ip.ip_hl; in_pcbunref(inp); return; } } else { /* ignore if we don't have a matching connection */ in_pcbunref(inp); return; } in_pcbunref(inp); notify = tcp_mtudisc, ip = 0; } else if (cmd == PRC_MTUINC) notify = tcp_mtudisc_increase, ip = 0; else if (cmd == PRC_HOSTDEAD) ip = 0; else if (errno == 0) return; if (ip) { th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2)); inp = in_pcblookup(&tcbtable, ip->ip_dst, th->th_dport, ip->ip_src, th->th_sport, rdomain); if (inp) { seq = ntohl(th->th_seq); if ((tp = intotcpcb(inp)) && SEQ_GEQ(seq, tp->snd_una) && SEQ_LT(seq, tp->snd_max)) notify(inp, errno); } else if (inetctlerrmap[cmd] == EHOSTUNREACH || inetctlerrmap[cmd] == ENETUNREACH || inetctlerrmap[cmd] == EHOSTDOWN) { struct sockaddr_in sin; bzero(&sin, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_port = th->th_sport; sin.sin_addr = ip->ip_src; syn_cache_unreach(sintosa(&sin), sa, th, rdomain); } in_pcbunref(inp); } else in_pcbnotifyall(&tcbtable, satosin(sa), rdomain, errno, notify); } #ifdef INET6 /* * Path MTU Discovery handlers. */ void tcp6_mtudisc_callback(struct sockaddr_in6 *sin6, u_int rdomain) { in6_pcbnotify(&tcb6table, sin6, 0, &sa6_any, 0, rdomain, PRC_MSGSIZE, NULL, tcp_mtudisc); } #endif /* INET6 */ /* * On receipt of path MTU corrections, flush old route and replace it * with the new one. Retransmit all unacknowledged packets, to ensure * that all packets will be received. */ void tcp_mtudisc(struct inpcb *inp, int errno) { struct tcpcb *tp = intotcpcb(inp); struct rtentry *rt; int orig_maxseg, change = 0; if (tp == NULL) return; orig_maxseg = tp->t_maxseg; rt = in_pcbrtentry(inp); if (rt != NULL) { unsigned int orig_mtulock = (rt->rt_locks & RTV_MTU); /* * If this was not a host route, remove and realloc. */ if ((rt->rt_flags & RTF_HOST) == 0) { in_rtchange(inp, errno); if ((rt = in_pcbrtentry(inp)) == NULL) return; } if (orig_mtulock < (rt->rt_locks & RTV_MTU)) change = 1; } tcp_mss(tp, -1); if (orig_maxseg > tp->t_maxseg) change = 1; /* * Resend unacknowledged packets */ tp->snd_nxt = tp->snd_una; if (change || errno > 0) tcp_output(tp); } void tcp_mtudisc_increase(struct inpcb *inp, int errno) { struct tcpcb *tp = intotcpcb(inp); struct rtentry *rt = in_pcbrtentry(inp); if (tp != 0 && rt != 0) { /* * If this was a host route, remove and realloc. */ if (rt->rt_flags & RTF_HOST) in_rtchange(inp, errno); /* also takes care of congestion window */ tcp_mss(tp, -1); } } /* * Generate new ISNs with a method based on RFC1948 */ #define TCP_ISS_CONN_INC 4096 void tcp_set_iss_tsm(struct tcpcb *tp) { SHA2_CTX ctx; union { uint8_t bytes[SHA512_DIGEST_LENGTH]; uint32_t words[2]; } digest; u_int rdomain = rtable_l2(tp->t_inpcb->inp_rtableid); tcp_seq iss; mtx_enter(&tcp_timer_mtx); tcp_iss += TCP_ISS_CONN_INC; iss = tcp_iss; mtx_leave(&tcp_timer_mtx); ctx = tcp_secret_ctx; SHA512Update(&ctx, &rdomain, sizeof(rdomain)); SHA512Update(&ctx, &tp->t_inpcb->inp_lport, sizeof(u_short)); SHA512Update(&ctx, &tp->t_inpcb->inp_fport, sizeof(u_short)); if (tp->pf == AF_INET6) { SHA512Update(&ctx, &tp->t_inpcb->inp_laddr6, sizeof(struct in6_addr)); SHA512Update(&ctx, &tp->t_inpcb->inp_faddr6, sizeof(struct in6_addr)); } else { SHA512Update(&ctx, &tp->t_inpcb->inp_laddr, sizeof(struct in_addr)); SHA512Update(&ctx, &tp->t_inpcb->inp_faddr, sizeof(struct in_addr)); } SHA512Final(digest.bytes, &ctx); tp->iss = digest.words[0] + iss; tp->ts_modulate = digest.words[1]; } #ifdef TCP_SIGNATURE int tcp_signature_tdb_attach(void) { return (0); } int tcp_signature_tdb_init(struct tdb *tdbp, const struct xformsw *xsp, struct ipsecinit *ii) { if ((ii->ii_authkeylen < 1) || (ii->ii_authkeylen > 80)) return (EINVAL); tdbp->tdb_amxkey = malloc(ii->ii_authkeylen, M_XDATA, M_NOWAIT); if (tdbp->tdb_amxkey == NULL) return (ENOMEM); memcpy(tdbp->tdb_amxkey, ii->ii_authkey, ii->ii_authkeylen); tdbp->tdb_amxkeylen = ii->ii_authkeylen; return (0); } int tcp_signature_tdb_zeroize(struct tdb *tdbp) { if (tdbp->tdb_amxkey) { explicit_bzero(tdbp->tdb_amxkey, tdbp->tdb_amxkeylen); free(tdbp->tdb_amxkey, M_XDATA, tdbp->tdb_amxkeylen); tdbp->tdb_amxkey = NULL; } return (0); } int tcp_signature_tdb_input(struct mbuf **mp, struct tdb *tdbp, int skip, int protoff) { m_freemp(mp); return (IPPROTO_DONE); } int tcp_signature_tdb_output(struct mbuf *m, struct tdb *tdbp, int skip, int protoff) { m_freem(m); return (EINVAL); } int tcp_signature_apply(caddr_t fstate, caddr_t data, unsigned int len) { MD5Update((MD5_CTX *)fstate, (char *)data, len); return 0; } int tcp_signature(struct tdb *tdb, int af, struct mbuf *m, struct tcphdr *th, int iphlen, int doswap, char *sig) { MD5_CTX ctx; int len; struct tcphdr th0; MD5Init(&ctx); switch(af) { case 0: case AF_INET: { struct ippseudo ippseudo; struct ip *ip; ip = mtod(m, struct ip *); ippseudo.ippseudo_src = ip->ip_src; ippseudo.ippseudo_dst = ip->ip_dst; ippseudo.ippseudo_pad = 0; ippseudo.ippseudo_p = IPPROTO_TCP; ippseudo.ippseudo_len = htons(m->m_pkthdr.len - iphlen); MD5Update(&ctx, (char *)&ippseudo, sizeof(struct ippseudo)); break; } #ifdef INET6 case AF_INET6: { struct ip6_hdr_pseudo ip6pseudo; struct ip6_hdr *ip6; ip6 = mtod(m, struct ip6_hdr *); bzero(&ip6pseudo, sizeof(ip6pseudo)); ip6pseudo.ip6ph_src = ip6->ip6_src; ip6pseudo.ip6ph_dst = ip6->ip6_dst; in6_clearscope(&ip6pseudo.ip6ph_src); in6_clearscope(&ip6pseudo.ip6ph_dst); ip6pseudo.ip6ph_nxt = IPPROTO_TCP; ip6pseudo.ip6ph_len = htonl(m->m_pkthdr.len - iphlen); MD5Update(&ctx, (char *)&ip6pseudo, sizeof(ip6pseudo)); break; } #endif } th0 = *th; th0.th_sum = 0; if (doswap) { th0.th_seq = htonl(th0.th_seq); th0.th_ack = htonl(th0.th_ack); th0.th_win = htons(th0.th_win); th0.th_urp = htons(th0.th_urp); } MD5Update(&ctx, (char *)&th0, sizeof(th0)); len = m->m_pkthdr.len - iphlen - th->th_off * sizeof(uint32_t); if (len > 0 && m_apply(m, iphlen + th->th_off * sizeof(uint32_t), len, tcp_signature_apply, (caddr_t)&ctx)) return (-1); MD5Update(&ctx, tdb->tdb_amxkey, tdb->tdb_amxkeylen); MD5Final(sig, &ctx); return (0); } #endif /* TCP_SIGNATURE */
242 241 1 136 12 83 91 2 1 92 170 78 20 204 1 14 2 1 222 222 2 214 1 3 2 2 5 33 1622 1623 1618 2 2 1 3 796 112 1 1 3 107 1 1 212 149 143 25 122 7 3 4 112 38 117 25 14 14 4 4 39 20 1 5 19 3 16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 /* $OpenBSD: spec_vnops.c,v 1.112 2024/02/03 18:51:58 beck Exp $ */ /* $NetBSD: spec_vnops.c,v 1.29 1996/04/22 01:42:38 christos Exp $ */ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)spec_vnops.c 8.8 (Berkeley) 11/21/94 */ #include <sys/param.h> #include <sys/proc.h> #include <sys/systm.h> #include <sys/conf.h> #include <sys/buf.h> #include <sys/mount.h> #include <sys/vnode.h> #include <sys/lock.h> #include <sys/stat.h> #include <sys/errno.h> #include <sys/fcntl.h> #include <sys/disklabel.h> #include <sys/lockf.h> #include <sys/dkio.h> #include <sys/malloc.h> #include <sys/specdev.h> #include <sys/unistd.h> #define v_lastr v_specinfo->si_lastr int spec_open_clone(struct vop_open_args *); struct vnodechain speclisth[SPECHSZ]; const struct vops spec_vops = { .vop_lookup = vop_generic_lookup, .vop_create = vop_generic_badop, .vop_mknod = vop_generic_badop, .vop_open = spec_open, .vop_close = spec_close, .vop_access = spec_access, .vop_getattr = spec_getattr, .vop_setattr = spec_setattr, .vop_read = spec_read, .vop_write = spec_write, .vop_ioctl = spec_ioctl, .vop_kqfilter = spec_kqfilter, .vop_revoke = vop_generic_revoke, .vop_fsync = spec_fsync, .vop_remove = vop_generic_badop, .vop_link = vop_generic_badop, .vop_rename = vop_generic_badop, .vop_mkdir = vop_generic_badop, .vop_rmdir = vop_generic_badop, .vop_symlink = vop_generic_badop, .vop_readdir = vop_generic_badop, .vop_readlink = vop_generic_badop, .vop_abortop = vop_generic_badop, .vop_inactive = spec_inactive, .vop_reclaim = nullop, .vop_lock = nullop, .vop_unlock = nullop, .vop_islocked = nullop, .vop_bmap = vop_generic_bmap, .vop_strategy = spec_strategy, .vop_print = spec_print, .vop_pathconf = spec_pathconf, .vop_advlock = spec_advlock, .vop_bwrite = vop_generic_bwrite, }; /* * Open a special file. */ int spec_open(void *v) { struct vop_open_args *ap = v; struct proc *p = ap->a_p; struct vnode *vp = ap->a_vp; struct vnode *bvp; dev_t bdev; dev_t dev = (dev_t)vp->v_rdev; int maj = major(dev); int error; /* * Don't allow open if fs is mounted -nodev. */ if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_NODEV)) return (ENXIO); switch (vp->v_type) { case VCHR: if ((u_int)maj >= nchrdev) return (ENXIO); if (ap->a_cred != FSCRED && (ap->a_mode & FWRITE)) { /* * When running in very secure mode, do not allow * opens for writing of any disk character devices. */ if (securelevel >= 2 && cdevsw[maj].d_type == D_DISK) return (EPERM); /* * When running in secure mode, do not allow opens * for writing of /dev/mem, /dev/kmem, or character * devices whose corresponding block devices are * currently mounted. */ if (securelevel >= 1) { if ((bdev = chrtoblk(dev)) != NODEV && vfinddev(bdev, VBLK, &bvp) && bvp->v_usecount > 0 && (error = vfs_mountedon(bvp))) return (error); if (iskmemdev(dev)) return (EPERM); } } if (cdevsw[maj].d_type == D_TTY) vp->v_flag |= VISTTY; if (cdevsw[maj].d_flags & D_CLONE) return (spec_open_clone(ap)); VOP_UNLOCK(vp); error = (*cdevsw[maj].d_open)(dev, ap->a_mode, S_IFCHR, p); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); return (error); case VBLK: if ((u_int)maj >= nblkdev) return (ENXIO); /* * When running in very secure mode, do not allow * opens for writing of any disk block devices. */ if (securelevel >= 2 && ap->a_cred != FSCRED && (ap->a_mode & FWRITE) && bdevsw[maj].d_type == D_DISK) return (EPERM); /* * Do not allow opens of block devices that are * currently mounted. */ if ((error = vfs_mountedon(vp)) != 0) return (error); return ((*bdevsw[maj].d_open)(dev, ap->a_mode, S_IFBLK, p)); case VNON: case VLNK: case VDIR: case VREG: case VBAD: case VFIFO: case VSOCK: break; } return (0); } /* * Vnode op for read */ int spec_read(void *v) { struct vop_read_args *ap = v; struct vnode *vp = ap->a_vp; struct uio *uio = ap->a_uio; struct proc *p = uio->uio_procp; struct buf *bp; daddr_t bn, nextbn, bscale; int bsize; struct partinfo dpart; size_t n; int on, majordev; int (*ioctl)(dev_t, u_long, caddr_t, int, struct proc *); int error = 0; #ifdef DIAGNOSTIC if (uio->uio_rw != UIO_READ) panic("spec_read mode"); if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc) panic("spec_read proc"); #endif if (uio->uio_resid == 0) return (0); switch (vp->v_type) { case VCHR: VOP_UNLOCK(vp); error = (*cdevsw[major(vp->v_rdev)].d_read) (vp->v_rdev, uio, ap->a_ioflag); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); return (error); case VBLK: if (uio->uio_offset < 0) return (EINVAL); bsize = BLKDEV_IOSIZE; if ((majordev = major(vp->v_rdev)) < nblkdev && (ioctl = bdevsw[majordev].d_ioctl) != NULL && (*ioctl)(vp->v_rdev, DIOCGPART, (caddr_t)&dpart, FREAD, p) == 0) { u_int32_t frag = DISKLABELV1_FFS_FRAG(dpart.part->p_fragblock); u_int32_t fsize = DISKLABELV1_FFS_FSIZE(dpart.part->p_fragblock); if (dpart.part->p_fstype == FS_BSDFFS && frag != 0 && fsize != 0) bsize = frag * fsize; } bscale = btodb(bsize); do { bn = btodb(uio->uio_offset) & ~(bscale - 1); on = uio->uio_offset % bsize; n = ulmin((bsize - on), uio->uio_resid); if (vp->v_lastr + bscale == bn) { nextbn = bn + bscale; error = breadn(vp, bn, bsize, &nextbn, &bsize, 1, &bp); } else error = bread(vp, bn, bsize, &bp); vp->v_lastr = bn; n = ulmin(n, bsize - bp->b_resid); if (error) { brelse(bp); return (error); } error = uiomove((char *)bp->b_data + on, n, uio); brelse(bp); } while (error == 0 && uio->uio_resid > 0 && n != 0); return (error); default: panic("spec_read type"); } /* NOTREACHED */ } int spec_inactive(void *v) { struct vop_inactive_args *ap = v; VOP_UNLOCK(ap->a_vp); return (0); } /* * Vnode op for write */ int spec_write(void *v) { struct vop_write_args *ap = v; struct vnode *vp = ap->a_vp; struct uio *uio = ap->a_uio; struct proc *p = uio->uio_procp; struct buf *bp; daddr_t bn, bscale; int bsize; struct partinfo dpart; size_t n; int on, majordev; int (*ioctl)(dev_t, u_long, caddr_t, int, struct proc *); int error = 0; #ifdef DIAGNOSTIC if (uio->uio_rw != UIO_WRITE) panic("spec_write mode"); if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc) panic("spec_write proc"); #endif switch (vp->v_type) { case VCHR: VOP_UNLOCK(vp); error = (*cdevsw[major(vp->v_rdev)].d_write) (vp->v_rdev, uio, ap->a_ioflag); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); return (error); case VBLK: if (uio->uio_resid == 0) return (0); if (uio->uio_offset < 0) return (EINVAL); bsize = BLKDEV_IOSIZE; if ((majordev = major(vp->v_rdev)) < nblkdev && (ioctl = bdevsw[majordev].d_ioctl) != NULL && (*ioctl)(vp->v_rdev, DIOCGPART, (caddr_t)&dpart, FREAD, p) == 0) { u_int32_t frag = DISKLABELV1_FFS_FRAG(dpart.part->p_fragblock); u_int32_t fsize = DISKLABELV1_FFS_FSIZE(dpart.part->p_fragblock); if (dpart.part->p_fstype == FS_BSDFFS && frag != 0 && fsize != 0) bsize = frag * fsize; } bscale = btodb(bsize); do { bn = btodb(uio->uio_offset) & ~(bscale - 1); on = uio->uio_offset % bsize; n = ulmin((bsize - on), uio->uio_resid); error = bread(vp, bn, bsize, &bp); n = ulmin(n, bsize - bp->b_resid); if (error) { brelse(bp); return (error); } error = uiomove((char *)bp->b_data + on, n, uio); if (n + on == bsize) bawrite(bp); else bdwrite(bp); } while (error == 0 && uio->uio_resid > 0 && n != 0); return (error); default: panic("spec_write type"); } /* NOTREACHED */ } /* * Device ioctl operation. */ int spec_ioctl(void *v) { struct vop_ioctl_args *ap = v; dev_t dev = ap->a_vp->v_rdev; int maj = major(dev); switch (ap->a_vp->v_type) { case VCHR: return ((*cdevsw[maj].d_ioctl)(dev, ap->a_command, ap->a_data, ap->a_fflag, ap->a_p)); case VBLK: return ((*bdevsw[maj].d_ioctl)(dev, ap->a_command, ap->a_data, ap->a_fflag, ap->a_p)); default: panic("spec_ioctl"); /* NOTREACHED */ } } int spec_kqfilter(void *v) { struct vop_kqfilter_args *ap = v; dev_t dev; dev = ap->a_vp->v_rdev; switch (ap->a_vp->v_type) { default: if (ap->a_kn->kn_flags & (__EV_POLL | __EV_SELECT)) return seltrue_kqfilter(dev, ap->a_kn); break; case VCHR: if (cdevsw[major(dev)].d_kqfilter) return (*cdevsw[major(dev)].d_kqfilter)(dev, ap->a_kn); } return (EOPNOTSUPP); } /* * Synch buffers associated with a block device */ int spec_fsync(void *v) { struct vop_fsync_args *ap = v; struct vnode *vp = ap->a_vp; struct buf *bp; struct buf *nbp; int s; if (vp->v_type == VCHR) return (0); /* * Flush all dirty buffers associated with a block device. */ loop: s = splbio(); LIST_FOREACH_SAFE(bp, &vp->v_dirtyblkhd, b_vnbufs, nbp) { if ((bp->b_flags & B_BUSY)) continue; if ((bp->b_flags & B_DELWRI) == 0) panic("spec_fsync: not dirty"); bremfree(bp); buf_acquire(bp); splx(s); bawrite(bp); goto loop; } if (ap->a_waitfor == MNT_WAIT) { vwaitforio (vp, 0, "spec_fsync", INFSLP); #ifdef DIAGNOSTIC if (!LIST_EMPTY(&vp->v_dirtyblkhd)) { splx(s); vprint("spec_fsync: dirty", vp); goto loop; } #endif } splx(s); return (0); } int spec_strategy(void *v) { struct vop_strategy_args *ap = v; struct buf *bp = ap->a_bp; int maj = major(bp->b_dev); (*bdevsw[maj].d_strategy)(bp); return (0); } /* * Device close routine */ int spec_close(void *v) { struct vop_close_args *ap = v; struct proc *p = ap->a_p; struct vnode *vp = ap->a_vp; dev_t dev = vp->v_rdev; int (*devclose)(dev_t, int, int, struct proc *); int mode, relock, xlocked, error; int clone = 0; mtx_enter(&vnode_mtx); xlocked = (vp->v_lflag & VXLOCK); mtx_leave(&vnode_mtx); switch (vp->v_type) { case VCHR: /* * Hack: a tty device that is a controlling terminal * has a reference from the session structure. * We cannot easily tell that a character device is * a controlling terminal, unless it is the closing * process' controlling terminal. In that case, * if the reference count is 2 (this last descriptor * plus the session), release the reference from the session. */ if (vcount(vp) == 2 && p != NULL && p->p_p->ps_pgrp && vp == p->p_p->ps_pgrp->pg_session->s_ttyvp) { vrele(vp); p->p_p->ps_pgrp->pg_session->s_ttyvp = NULL; } if (cdevsw[major(dev)].d_flags & D_CLONE) { clone = 1; } else { /* * If the vnode is locked, then we are in the midst * of forcibly closing the device, otherwise we only * close on last reference. */ if (vcount(vp) > 1 && !xlocked) return (0); } devclose = cdevsw[major(dev)].d_close; mode = S_IFCHR; break; case VBLK: /* * On last close of a block device (that isn't mounted) * we must invalidate any in core blocks, so that * we can, for instance, change floppy disks. In order to do * that, we must lock the vnode. If we are coming from * vclean(), the vnode is already locked. */ if (!xlocked) vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); error = vinvalbuf(vp, V_SAVE, ap->a_cred, p, 0, INFSLP); if (!xlocked) VOP_UNLOCK(vp); if (error) return (error); /* * We do not want to really close the device if it * is still in use unless we are trying to close it * forcibly. Since every use (buffer, vnode, swap, cmap) * holds a reference to the vnode, and because we mark * any other vnodes that alias this device, when the * sum of the reference counts on all the aliased * vnodes descends to one, we are on last close. */ if (vcount(vp) > 1 && !xlocked) return (0); devclose = bdevsw[major(dev)].d_close; mode = S_IFBLK; break; default: panic("spec_close: not special"); } /* release lock if held and this isn't coming from vclean() */ relock = VOP_ISLOCKED(vp) && !xlocked; if (relock) VOP_UNLOCK(vp); error = (*devclose)(dev, ap->a_fflag, mode, p); if (relock) vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if (error == 0 && clone) { struct vnode *pvp; pvp = vp->v_specparent; /* get parent device */ clrbit(pvp->v_specbitmap, minor(dev) >> CLONE_SHIFT); vrele(pvp); } return (error); } int spec_getattr(void *v) { struct vop_getattr_args *ap = v; struct vnode *vp = ap->a_vp; int error; if (!(vp->v_flag & VCLONE)) return (EBADF); vn_lock(vp->v_specparent, LK_EXCLUSIVE|LK_RETRY); error = VOP_GETATTR(vp->v_specparent, ap->a_vap, ap->a_cred, ap->a_p); VOP_UNLOCK(vp->v_specparent); return (error); } int spec_setattr(void *v) { struct vop_getattr_args *ap = v; struct proc *p = ap->a_p; struct vnode *vp = ap->a_vp; int error; if (!(vp->v_flag & VCLONE)) return (EBADF); vn_lock(vp->v_specparent, LK_EXCLUSIVE|LK_RETRY); error = VOP_SETATTR(vp->v_specparent, ap->a_vap, ap->a_cred, p); VOP_UNLOCK(vp->v_specparent); return (error); } int spec_access(void *v) { struct vop_access_args *ap = v; struct vnode *vp = ap->a_vp; int error; if (!(vp->v_flag & VCLONE)) return (EBADF); vn_lock(vp->v_specparent, LK_EXCLUSIVE|LK_RETRY); error = VOP_ACCESS(vp->v_specparent, ap->a_mode, ap->a_cred, ap->a_p); VOP_UNLOCK(vp->v_specparent); return (error); } /* * Print out the contents of a special device vnode. */ int spec_print(void *v) { struct vop_print_args *ap = v; printf("tag VT_NON, dev %d, %d\n", major(ap->a_vp->v_rdev), minor(ap->a_vp->v_rdev)); return 0; } /* * Return POSIX pathconf information applicable to special devices. */ int spec_pathconf(void *v) { struct vop_pathconf_args *ap = v; int error = 0; switch (ap->a_name) { case _PC_LINK_MAX: *ap->a_retval = LINK_MAX; break; case _PC_MAX_CANON: *ap->a_retval = MAX_CANON; break; case _PC_MAX_INPUT: *ap->a_retval = MAX_INPUT; break; case _PC_CHOWN_RESTRICTED: *ap->a_retval = 1; break; case _PC_VDISABLE: *ap->a_retval = _POSIX_VDISABLE; break; case _PC_TIMESTAMP_RESOLUTION: *ap->a_retval = 1; break; default: error = EINVAL; break; } return (error); } /* * Special device advisory byte-level locks. */ int spec_advlock(void *v) { struct vop_advlock_args *ap = v; struct vnode *vp = ap->a_vp; return (lf_advlock(&vp->v_speclockf, (off_t)0, ap->a_id, ap->a_op, ap->a_fl, ap->a_flags)); } /* * Copyright (c) 2006 Pedro Martelletto <pedro@ambientworks.net> * Copyright (c) 2006 Thordur Bjornsson <thib@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifdef CLONE_DEBUG #define DNPRINTF(m...) do { printf(m); } while (0) #else #define DNPRINTF(m...) /* nothing */ #endif int spec_open_clone(struct vop_open_args *ap) { struct vnode *cvp, *vp = ap->a_vp; struct cloneinfo *cip; int error, i; DNPRINTF("cloning vnode\n"); if (minor(vp->v_rdev) >= (1 << CLONE_SHIFT)) return (ENXIO); for (i = 1; i < CLONE_MAPSZ * NBBY; i++) if (isclr(vp->v_specbitmap, i)) { setbit(vp->v_specbitmap, i); break; } if (i == CLONE_MAPSZ * NBBY) return (EBUSY); /* too many open instances */ error = cdevvp(makedev(major(vp->v_rdev), (i << CLONE_SHIFT) | minor(vp->v_rdev)), &cvp); if (error) { clrbit(vp->v_specbitmap, i); return (error); /* out of vnodes */ } VOP_UNLOCK(vp); error = cdevsw[major(vp->v_rdev)].d_open(cvp->v_rdev, ap->a_mode, S_IFCHR, ap->a_p); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if (error) { vput(cvp); clrbit(vp->v_specbitmap, i); return (error); /* device open failed */ } cvp->v_flag |= VCLONE; cip = malloc(sizeof(struct cloneinfo), M_TEMP, M_WAITOK); cip->ci_data = vp->v_data; cip->ci_vp = cvp; cvp->v_specparent = vp; vp->v_flag |= VCLONED; vp->v_data = cip; DNPRINTF("clone of vnode %p is vnode %p\n", vp, cvp); return (0); /* device cloned */ }
1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 /* $OpenBSD: mpls_raw.c,v 1.20 2024/04/29 00:29:48 jsg Exp $ */ /* * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <sys/param.h> #include <sys/mbuf.h> #include <sys/errno.h> #include <sys/sockio.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/systm.h> #include <sys/sysctl.h> #include <net/if.h> #include <net/if_var.h> #include <netmpls/mpls.h> int mpls_defttl = 255; int mpls_mapttl_ip = 1; int mpls_mapttl_ip6 = 0; const struct sysctl_bounded_args mplsctl_vars[] = { { MPLSCTL_DEFTTL, &mpls_defttl, 0, 255 }, { MPLSCTL_MAPTTL_IP, &mpls_mapttl_ip, 0, 1 }, { MPLSCTL_MAPTTL_IP6, &mpls_mapttl_ip6, 0, 1 }, }; int mpls_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { return sysctl_bounded_arr(mplsctl_vars, nitems(mplsctl_vars), name, namelen, oldp, oldlenp, newp, newlen); }
9 9 6 6 5 1 1 1 2 2 3 2 2 3 3 1 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 /* $OpenBSD: wsevent.c,v 1.28 2024/03/25 13:01:49 mvs Exp $ */ /* $NetBSD: wsevent.c,v 1.16 2003/08/07 16:31:29 agc Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Christopher G. Demetriou * for the NetBSD Project. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Lawrence Berkeley Laboratory. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)event.c 8.1 (Berkeley) 6/11/93 */ /* * Internal "wscons_event" queue interface for the keyboard and mouse drivers. */ #include <sys/param.h> #include <sys/malloc.h> #include <sys/systm.h> #include <sys/vnode.h> #include <dev/wscons/wsconsio.h> #include <dev/wscons/wseventvar.h> void filt_wseventdetach(struct knote *); int filt_wseventread(struct knote *, long); const struct filterops wsevent_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, .f_detach = filt_wseventdetach, .f_event = filt_wseventread, }; /* * Initialize a wscons_event queue. */ int wsevent_init(struct wseventvar *ev) { struct wscons_event *queue; if (ev->ws_q != NULL) return (0); queue = mallocarray(WSEVENT_QSIZE, sizeof(struct wscons_event), M_DEVBUF, M_WAITOK | M_ZERO); if (ev->ws_q != NULL) { free(queue, M_DEVBUF, WSEVENT_QSIZE * sizeof(struct wscons_event)); return (1); } ev->ws_q = queue; ev->ws_get = ev->ws_put = 0; sigio_init(&ev->ws_sigio); return (0); } /* * Tear down a wscons_event queue. */ void wsevent_fini(struct wseventvar *ev) { if (ev->ws_q == NULL) { #ifdef DIAGNOSTIC printf("wsevent_fini: already invoked\n"); #endif return; } free(ev->ws_q, M_DEVBUF, WSEVENT_QSIZE * sizeof(struct wscons_event)); ev->ws_q = NULL; klist_invalidate(&ev->ws_sel.si_note); sigio_free(&ev->ws_sigio); } /* * User-level interface: read, kqueue. * (User cannot write an event queue.) */ int wsevent_read(struct wseventvar *ev, struct uio *uio, int flags) { int s, error; u_int cnt; size_t n; /* * Make sure we can return at least 1. */ if (uio->uio_resid < sizeof(struct wscons_event)) return (EMSGSIZE); /* ??? */ s = splwsevent(); while (ev->ws_get == ev->ws_put) { if (flags & IO_NDELAY) { splx(s); return (EWOULDBLOCK); } ev->ws_wanted = 1; error = tsleep_nsec(ev, PWSEVENT | PCATCH, "wsevent_read", INFSLP); if (error) { splx(s); return (error); } } /* * Move wscons_event from tail end of queue (there is at least one * there). */ if (ev->ws_put < ev->ws_get) cnt = WSEVENT_QSIZE - ev->ws_get; /* events in [get..QSIZE) */ else cnt = ev->ws_put - ev->ws_get; /* events in [get..put) */ splx(s); n = howmany(uio->uio_resid, sizeof(struct wscons_event)); if (cnt > n) cnt = n; error = uiomove((caddr_t)&ev->ws_q[ev->ws_get], cnt * sizeof(struct wscons_event), uio); n -= cnt; /* * If we do not wrap to 0, used up all our space, or had an error, * stop. Otherwise move from front of queue to put index, if there * is anything there to move. */ if ((ev->ws_get = (ev->ws_get + cnt) % WSEVENT_QSIZE) != 0 || n == 0 || error || (cnt = ev->ws_put) == 0) return (error); if (cnt > n) cnt = n; error = uiomove((caddr_t)&ev->ws_q[0], cnt * sizeof(struct wscons_event), uio); ev->ws_get = cnt; return (error); } int wsevent_kqfilter(struct wseventvar *ev, struct knote *kn) { struct klist *klist; int s; klist = &ev->ws_sel.si_note; switch (kn->kn_filter) { case EVFILT_READ: kn->kn_fop = &wsevent_filtops; break; default: return (EINVAL); } kn->kn_hook = ev; s = splwsevent(); klist_insert_locked(klist, kn); splx(s); return (0); } void filt_wseventdetach(struct knote *kn) { struct wseventvar *ev = kn->kn_hook; struct klist *klist = &ev->ws_sel.si_note; int s; s = splwsevent(); klist_remove_locked(klist, kn); splx(s); } int filt_wseventread(struct knote *kn, long hint) { struct wseventvar *ev = kn->kn_hook; if (ev->ws_get == ev->ws_put) return (0); if (ev->ws_get < ev->ws_put) kn->kn_data = ev->ws_put - ev->ws_get; else kn->kn_data = (WSEVENT_QSIZE - ev->ws_get) + ev->ws_put; return (1); }
86 86 78 8 8 2 1 2 2 6 5 1 4 122 25 99 46 12 41 2 2 4 4 4 7 7 7 7 4 3 3 3 3 3 7 7 3 7 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 /* $OpenBSD: kern_proc.c,v 1.98 2024/05/20 10:32:20 claudio Exp $ */ /* $NetBSD: kern_proc.c,v 1.14 1996/02/09 18:59:41 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_proc.c 8.4 (Berkeley) 1/4/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/wait.h> #include <sys/rwlock.h> #include <sys/malloc.h> #include <sys/tty.h> #include <sys/signalvar.h> #include <sys/pool.h> #include <sys/vnode.h> /* * Locks used to protect struct members in this file: * I immutable after creation * U uidinfolk */ struct rwlock uidinfolk; #define UIHASH(uid) (&uihashtbl[(uid) & uihash]) LIST_HEAD(uihashhead, uidinfo) *uihashtbl; /* [U] */ u_long uihash; /* [I] size of hash table - 1 */ /* * Other process lists */ struct tidhashhead *tidhashtbl; u_long tidhash; struct pidhashhead *pidhashtbl; u_long pidhash; struct pgrphashhead *pgrphashtbl; u_long pgrphash; struct processlist allprocess; struct processlist zombprocess; struct proclist allproc; struct pool proc_pool; struct pool process_pool; struct pool rusage_pool; struct pool ucred_pool; struct pool pgrp_pool; struct pool session_pool; void pgdelete(struct pgrp *); void fixjobc(struct process *, struct pgrp *, int); static void orphanpg(struct pgrp *); #ifdef DEBUG void pgrpdump(void); #endif /* * Initialize global process hashing structures. */ void procinit(void) { LIST_INIT(&allprocess); LIST_INIT(&zombprocess); LIST_INIT(&allproc); rw_init(&uidinfolk, "uidinfo"); tidhashtbl = hashinit(maxthread / 4, M_PROC, M_NOWAIT, &tidhash); pidhashtbl = hashinit(maxprocess / 4, M_PROC, M_NOWAIT, &pidhash); pgrphashtbl = hashinit(maxprocess / 4, M_PROC, M_NOWAIT, &pgrphash); uihashtbl = hashinit(maxprocess / 16, M_PROC, M_NOWAIT, &uihash); if (!tidhashtbl || !pidhashtbl || !pgrphashtbl || !uihashtbl) panic("procinit: malloc"); pool_init(&proc_pool, sizeof(struct proc), 0, IPL_NONE, PR_WAITOK, "procpl", NULL); pool_init(&process_pool, sizeof(struct process), 0, IPL_NONE, PR_WAITOK, "processpl", NULL); pool_init(&rusage_pool, sizeof(struct rusage), 0, IPL_NONE, PR_WAITOK, "zombiepl", NULL); pool_init(&ucred_pool, sizeof(struct ucred), 0, IPL_MPFLOOR, 0, "ucredpl", NULL); pool_init(&pgrp_pool, sizeof(struct pgrp), 0, IPL_NONE, PR_WAITOK, "pgrppl", NULL); pool_init(&session_pool, sizeof(struct session), 0, IPL_NONE, PR_WAITOK, "sessionpl", NULL); } /* * This returns with `uidinfolk' held: caller must call uid_release() * after making whatever change they needed. */ struct uidinfo * uid_find(uid_t uid) { struct uidinfo *uip, *nuip; struct uihashhead *uipp; uipp = UIHASH(uid); rw_enter_write(&uidinfolk); LIST_FOREACH(uip, uipp, ui_hash) if (uip->ui_uid == uid) break; if (uip) return (uip); rw_exit_write(&uidinfolk); nuip = malloc(sizeof(*nuip), M_PROC, M_WAITOK|M_ZERO); rw_enter_write(&uidinfolk); LIST_FOREACH(uip, uipp, ui_hash) if (uip->ui_uid == uid) break; if (uip) { free(nuip, M_PROC, sizeof(*nuip)); return (uip); } nuip->ui_uid = uid; LIST_INSERT_HEAD(uipp, nuip, ui_hash); return (nuip); } void uid_release(struct uidinfo *uip) { rw_exit_write(&uidinfolk); } /* * Change the count associated with number of threads * a given user is using. */ int chgproccnt(uid_t uid, int diff) { struct uidinfo *uip; long count; uip = uid_find(uid); count = (uip->ui_proccnt += diff); uid_release(uip); if (count < 0) panic("chgproccnt: procs < 0"); return count; } /* * Is pr an inferior of parent? */ int inferior(struct process *pr, struct process *parent) { for (; pr != parent; pr = pr->ps_pptr) if (pr->ps_pid == 0 || pr->ps_pid == 1) return (0); return (1); } /* * Locate a proc (thread) by number */ struct proc * tfind(pid_t tid) { struct proc *p; LIST_FOREACH(p, TIDHASH(tid), p_hash) if (p->p_tid == tid) return (p); return (NULL); } /* * Locate a thread by userspace id, from a given process. */ struct proc * tfind_user(pid_t tid, struct process *pr) { struct proc *p; if (tid < THREAD_PID_OFFSET) return NULL; p = tfind(tid - THREAD_PID_OFFSET); /* verify we found a thread in the correct process */ if (p != NULL && p->p_p != pr) p = NULL; return p; } /* * Locate a process by number */ struct process * prfind(pid_t pid) { struct process *pr; LIST_FOREACH(pr, PIDHASH(pid), ps_hash) if (pr->ps_pid == pid) return (pr); return (NULL); } /* * Locate a process group by number */ struct pgrp * pgfind(pid_t pgid) { struct pgrp *pgrp; LIST_FOREACH(pgrp, PGRPHASH(pgid), pg_hash) if (pgrp->pg_id == pgid) return (pgrp); return (NULL); } /* * Locate a zombie process */ struct process * zombiefind(pid_t pid) { struct process *pr; LIST_FOREACH(pr, &zombprocess, ps_list) if (pr->ps_pid == pid) return (pr); return (NULL); } /* * Move process to a new process group. If a session is provided * then it's a new session to contain this process group; otherwise * the process is staying within its existing session. */ void enternewpgrp(struct process *pr, struct pgrp *pgrp, struct session *newsess) { #ifdef DIAGNOSTIC if (SESS_LEADER(pr)) panic("%s: session leader attempted setpgrp", __func__); #endif if (newsess != NULL) { /* * New session. Initialize it completely */ timeout_set(&newsess->s_verauthto, zapverauth, newsess); newsess->s_leader = pr; newsess->s_count = 1; newsess->s_ttyvp = NULL; newsess->s_ttyp = NULL; memcpy(newsess->s_login, pr->ps_session->s_login, sizeof(newsess->s_login)); atomic_clearbits_int(&pr->ps_flags, PS_CONTROLT); pgrp->pg_session = newsess; #ifdef DIAGNOSTIC if (pr != curproc->p_p) panic("%s: mksession but not curproc", __func__); #endif } else { pgrp->pg_session = pr->ps_session; pgrp->pg_session->s_count++; } pgrp->pg_id = pr->ps_pid; LIST_INIT(&pgrp->pg_members); LIST_INIT(&pgrp->pg_sigiolst); LIST_INSERT_HEAD(PGRPHASH(pr->ps_pid), pgrp, pg_hash); pgrp->pg_jobc = 0; enterthispgrp(pr, pgrp); } /* * move process to an existing process group */ void enterthispgrp(struct process *pr, struct pgrp *pgrp) { struct pgrp *savepgrp = pr->ps_pgrp; /* * Adjust eligibility of affected pgrps to participate in job control. * Increment eligibility counts before decrementing, otherwise we * could reach 0 spuriously during the first call. */ fixjobc(pr, pgrp, 1); fixjobc(pr, savepgrp, 0); LIST_REMOVE(pr, ps_pglist); pr->ps_pgrp = pgrp; LIST_INSERT_HEAD(&pgrp->pg_members, pr, ps_pglist); if (LIST_EMPTY(&savepgrp->pg_members)) pgdelete(savepgrp); } /* * remove process from process group */ void leavepgrp(struct process *pr) { if (pr->ps_session->s_verauthppid == pr->ps_pid) zapverauth(pr->ps_session); LIST_REMOVE(pr, ps_pglist); if (LIST_EMPTY(&pr->ps_pgrp->pg_members)) pgdelete(pr->ps_pgrp); pr->ps_pgrp = NULL; } /* * delete a process group */ void pgdelete(struct pgrp *pgrp) { sigio_freelist(&pgrp->pg_sigiolst); if (pgrp->pg_session->s_ttyp != NULL && pgrp->pg_session->s_ttyp->t_pgrp == pgrp) pgrp->pg_session->s_ttyp->t_pgrp = NULL; LIST_REMOVE(pgrp, pg_hash); SESSRELE(pgrp->pg_session); pool_put(&pgrp_pool, pgrp); } void zapverauth(void *v) { struct session *sess = v; sess->s_verauthuid = 0; sess->s_verauthppid = 0; } /* * Adjust pgrp jobc counters when specified process changes process group. * We count the number of processes in each process group that "qualify" * the group for terminal job control (those with a parent in a different * process group of the same session). If that count reaches zero, the * process group becomes orphaned. Check both the specified process' * process group and that of its children. * entering == 0 => pr is leaving specified group. * entering == 1 => pr is entering specified group. * XXX need proctree lock */ void fixjobc(struct process *pr, struct pgrp *pgrp, int entering) { struct pgrp *hispgrp; struct session *mysession = pgrp->pg_session; /* * Check pr's parent to see whether pr qualifies its own process * group; if so, adjust count for pr's process group. */ if ((hispgrp = pr->ps_pptr->ps_pgrp) != pgrp && hispgrp->pg_session == mysession) { if (entering) pgrp->pg_jobc++; else if (--pgrp->pg_jobc == 0) orphanpg(pgrp); } /* * Check this process' children to see whether they qualify * their process groups; if so, adjust counts for children's * process groups. */ LIST_FOREACH(pr, &pr->ps_children, ps_sibling) if ((hispgrp = pr->ps_pgrp) != pgrp && hispgrp->pg_session == mysession && (pr->ps_flags & PS_ZOMBIE) == 0) { if (entering) hispgrp->pg_jobc++; else if (--hispgrp->pg_jobc == 0) orphanpg(hispgrp); } } void killjobc(struct process *pr) { if (SESS_LEADER(pr)) { struct session *sp = pr->ps_session; if (sp->s_ttyvp) { struct vnode *ovp; /* * Controlling process. * Signal foreground pgrp, * drain controlling terminal * and revoke access to controlling terminal. */ if (sp->s_ttyp->t_session == sp) { if (sp->s_ttyp->t_pgrp) pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1); ttywait(sp->s_ttyp); /* * The tty could have been revoked * if we blocked. */ if (sp->s_ttyvp) VOP_REVOKE(sp->s_ttyvp, REVOKEALL); } ovp = sp->s_ttyvp; sp->s_ttyvp = NULL; if (ovp) vrele(ovp); /* * s_ttyp is not zero'd; we use this to * indicate that the session once had a * controlling terminal. (for logging and * informational purposes) */ } sp->s_leader = NULL; } fixjobc(pr, pr->ps_pgrp, 0); } /* * A process group has become orphaned; * if there are any stopped processes in the group, * hang-up all process in that group. */ static void orphanpg(struct pgrp *pg) { struct process *pr; LIST_FOREACH(pr, &pg->pg_members, ps_pglist) { if (pr->ps_mainproc->p_stat == SSTOP) { LIST_FOREACH(pr, &pg->pg_members, ps_pglist) { prsignal(pr, SIGHUP); prsignal(pr, SIGCONT); } return; } } } #ifdef DDB void proc_printit(struct proc *p, const char *modif, int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2)))) { static const char *const pstat[] = { "idle", "run", "sleep", "stop", "zombie", "dead", "onproc" }; char pstbuf[5]; const char *pst = pstbuf; if (p->p_stat < 1 || p->p_stat > sizeof(pstat) / sizeof(pstat[0])) snprintf(pstbuf, sizeof(pstbuf), "%d", p->p_stat); else pst = pstat[(int)p->p_stat - 1]; (*pr)("PROC (%s) tid=%d pid=%d tcnt=%d stat=%s\n", p->p_p->ps_comm, p->p_tid, p->p_p->ps_pid, p->p_p->ps_threadcnt, pst); (*pr)(" flags process=%b proc=%b\n", p->p_p->ps_flags, PS_BITS, p->p_flag, P_BITS); (*pr)(" runpri=%u, usrpri=%u, slppri=%u, nice=%d\n", p->p_runpri, p->p_usrpri, p->p_slppri, p->p_p->ps_nice); (*pr)(" wchan=%p, wmesg=%s, ps_single=%p scnt=%d ecnt=%d\n", p->p_wchan, (p->p_wchan && p->p_wmesg) ? p->p_wmesg : "", p->p_p->ps_single, p->p_p->ps_singlecnt, p->p_p->ps_exitcnt); (*pr)(" forw=%p, list=%p,%p\n", TAILQ_NEXT(p, p_runq), p->p_list.le_next, p->p_list.le_prev); (*pr)(" process=%p user=%p, vmspace=%p\n", p->p_p, p->p_addr, p->p_vmspace); (*pr)(" estcpu=%u, cpticks=%d, pctcpu=%u.%u, " "user=%u, sys=%u, intr=%u\n", p->p_estcpu, p->p_cpticks, p->p_pctcpu / 100, p->p_pctcpu % 100, p->p_uticks, p->p_sticks, p->p_iticks); } #include <machine/db_machdep.h> #include <ddb/db_output.h> void db_kill_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) { struct process *pr; struct proc *p; pr = prfind(addr); if (pr == NULL) { db_printf("%ld: No such process", addr); return; } p = TAILQ_FIRST(&pr->ps_threads); /* Send uncatchable SIGABRT for coredump */ sigabort(p); } void db_show_all_procs(db_expr_t addr, int haddr, db_expr_t count, char *modif) { char *mode; int skipzomb = 0; int has_kernel_lock = 0; struct proc *p; struct process *pr, *ppr; if (modif[0] == 0) modif[0] = 'n'; /* default == normal mode */ mode = "mawno"; while (*mode && *mode != modif[0]) mode++; if (*mode == 0 || *mode == 'm') { db_printf("usage: show all procs [/a] [/n] [/w]\n"); db_printf("\t/a == show process address info\n"); db_printf("\t/n == show normal process info [default]\n"); db_printf("\t/w == show process pgrp/wait info\n"); db_printf("\t/o == show normal info for non-idle SONPROC\n"); return; } pr = LIST_FIRST(&allprocess); switch (*mode) { case 'a': db_printf(" TID %-9s %18s %18s %18s\n", "COMMAND", "STRUCT PROC *", "UAREA *", "VMSPACE/VM_MAP"); break; case 'n': db_printf(" PID %6s %5s %5s S %10s %-12s %-15s\n", "TID", "PPID", "UID", "FLAGS", "WAIT", "COMMAND"); break; case 'w': db_printf(" TID %-15s %-5s %18s %s\n", "COMMAND", "PGRP", "WAIT-CHANNEL", "WAIT-MSG"); break; case 'o': skipzomb = 1; db_printf(" TID %5s %5s %10s %10s %3s %-30s\n", "PID", "UID", "PRFLAGS", "PFLAGS", "CPU", "COMMAND"); break; } while (pr != NULL) { ppr = pr->ps_pptr; TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) { #ifdef MULTIPROCESSOR if (__mp_lock_held(&kernel_lock, p->p_cpu)) has_kernel_lock = 1; else has_kernel_lock = 0; #endif if (p->p_stat) { if (*mode == 'o') { if (p->p_stat != SONPROC) continue; if (p->p_cpu != NULL && p->p_cpu-> ci_schedstate.spc_idleproc == p) continue; } if (*mode == 'n') { db_printf("%c%5d ", (p == curproc ? '*' : ' '), pr->ps_pid); } else { db_printf("%c%6d ", (p == curproc ? '*' : ' '), p->p_tid); } switch (*mode) { case 'a': db_printf("%-9.9s %18p %18p %18p\n", pr->ps_comm, p, p->p_addr, p->p_vmspace); break; case 'n': db_printf("%6d %5d %5d %d %#10x " "%-12.12s %-15s\n", p->p_tid, ppr ? ppr->ps_pid : -1, pr->ps_ucred->cr_ruid, p->p_stat, p->p_flag | pr->ps_flags, (p->p_wchan && p->p_wmesg) ? p->p_wmesg : "", pr->ps_comm); break; case 'w': db_printf("%-15s %-5d %18p %s\n", pr->ps_comm, (pr->ps_pgrp ? pr->ps_pgrp->pg_id : -1), p->p_wchan, (p->p_wchan && p->p_wmesg) ? p->p_wmesg : ""); break; case 'o': db_printf("%5d %5d %#10x %#10x %3d" "%c %-31s\n", pr->ps_pid, pr->ps_ucred->cr_ruid, pr->ps_flags, p->p_flag, CPU_INFO_UNIT(p->p_cpu), has_kernel_lock ? 'K' : ' ', pr->ps_comm); break; } } } pr = LIST_NEXT(pr, ps_list); if (pr == NULL && skipzomb == 0) { skipzomb = 1; pr = LIST_FIRST(&zombprocess); } } } #endif #ifdef DEBUG void pgrpdump(void) { struct pgrp *pgrp; struct process *pr; int i; for (i = 0; i <= pgrphash; i++) { if (!LIST_EMPTY(&pgrphashtbl[i])) { printf("\tindx %d\n", i); LIST_FOREACH(pgrp, &pgrphashtbl[i], pg_hash) { printf("\tpgrp %p, pgid %d, sess %p, sesscnt %d, mem %p\n", pgrp, pgrp->pg_id, pgrp->pg_session, pgrp->pg_session->s_count, LIST_FIRST(&pgrp->pg_members)); LIST_FOREACH(pr, &pgrp->pg_members, ps_pglist) { printf("\t\tpid %d addr %p pgrp %p\n", pr->ps_pid, pr, pr->ps_pgrp); } } } } } #endif /* DEBUG */
418 1 12 8 2 10 2 45 3 44 56 323 2 3 9 105 259 183 2 176 341 7 131 218 16 92 150 205 204 205 635 2 629 8 105 117 137 70 23 47 68 2 23 40 44 21 227 177 52 2 2 44 170 1662 1658 1421 247 6 1588 9 9 871 869 2 5 852 3057 4 3059 4 155 146 11 154 144 9 1 1 2 1 2 2 3 3 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 /* $OpenBSD: vfs_vnops.c,v 1.122 2023/07/10 22:54:40 deraadt Exp $ */ /* $NetBSD: vfs_vnops.c,v 1.20 1996/02/04 02:18:41 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)vfs_vnops.c 8.5 (Berkeley) 12/8/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/fcntl.h> #include <sys/file.h> #include <sys/stat.h> #include <sys/proc.h> #include <sys/resourcevar.h> #include <sys/signalvar.h> #include <sys/mount.h> #include <sys/namei.h> #include <sys/lock.h> #include <sys/vnode.h> #include <sys/ioctl.h> #include <sys/tty.h> #include <sys/specdev.h> #include <sys/unistd.h> int vn_read(struct file *, struct uio *, int); int vn_write(struct file *, struct uio *, int); int vn_kqfilter(struct file *, struct knote *); int vn_closefile(struct file *, struct proc *); int vn_seek(struct file *, off_t *, int, struct proc *); const struct fileops vnops = { .fo_read = vn_read, .fo_write = vn_write, .fo_ioctl = vn_ioctl, .fo_kqfilter = vn_kqfilter, .fo_stat = vn_statfile, .fo_close = vn_closefile, .fo_seek = vn_seek, }; /* * Common code for vnode open operations. * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. */ int vn_open(struct nameidata *ndp, int fmode, int cmode) { struct vnode *vp; struct proc *p = ndp->ni_cnd.cn_proc; struct ucred *cred = p->p_ucred; struct vattr va; struct cloneinfo *cip; int error; /* * The only valid flags to pass in here from NDINIT are * KERNELPATH or BYPASSUNVEIL. This function will override the * nameiop based on the fmode and cmode flags, so validate that * our caller has not set other flags or operations in the nameidata * structure. */ KASSERT((ndp->ni_cnd.cn_flags & ~(KERNELPATH|BYPASSUNVEIL)) == 0); KASSERT(ndp->ni_cnd.cn_nameiop == 0); if ((fmode & (FREAD|FWRITE)) == 0) return (EINVAL); if ((fmode & (O_TRUNC | FWRITE)) == O_TRUNC) return (EINVAL); if (fmode & O_CREAT) { ndp->ni_cnd.cn_nameiop = CREATE; ndp->ni_cnd.cn_flags |= LOCKPARENT | LOCKLEAF; if ((fmode & O_EXCL) == 0 && (fmode & O_NOFOLLOW) == 0) ndp->ni_cnd.cn_flags |= FOLLOW; if ((error = namei(ndp)) != 0) return (error); if (ndp->ni_vp == NULL) { VATTR_NULL(&va); va.va_type = VREG; va.va_mode = cmode; if (fmode & O_EXCL) va.va_vaflags |= VA_EXCLUSIVE; error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp, &ndp->ni_cnd, &va); vput(ndp->ni_dvp); if (error) return (error); fmode &= ~O_TRUNC; vp = ndp->ni_vp; } else { VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd); if (ndp->ni_dvp == ndp->ni_vp) vrele(ndp->ni_dvp); else vput(ndp->ni_dvp); ndp->ni_dvp = NULL; vp = ndp->ni_vp; if (fmode & O_EXCL) { error = EEXIST; goto bad; } fmode &= ~O_CREAT; } } else { ndp->ni_cnd.cn_nameiop = LOOKUP; ndp->ni_cnd.cn_flags |= ((fmode & O_NOFOLLOW) ? NOFOLLOW : FOLLOW) | LOCKLEAF; if ((error = namei(ndp)) != 0) return (error); vp = ndp->ni_vp; } if (vp->v_type == VSOCK) { error = EOPNOTSUPP; goto bad; } if (vp->v_type == VLNK) { error = ELOOP; goto bad; } if ((fmode & O_DIRECTORY) && vp->v_type != VDIR) { error = ENOTDIR; goto bad; } if ((fmode & O_CREAT) == 0) { if (fmode & FREAD) { if ((error = VOP_ACCESS(vp, VREAD, cred, p)) != 0) goto bad; } if (fmode & FWRITE) { if (vp->v_type == VDIR) { error = EISDIR; goto bad; } if ((error = vn_writechk(vp)) != 0 || (error = VOP_ACCESS(vp, VWRITE, cred, p)) != 0) goto bad; } } if ((fmode & O_TRUNC) && vp->v_type == VREG) { VATTR_NULL(&va); va.va_size = 0; if ((error = VOP_SETATTR(vp, &va, cred, p)) != 0) goto bad; } if ((error = VOP_OPEN(vp, fmode, cred, p)) != 0) goto bad; if (vp->v_flag & VCLONED) { cip = (struct cloneinfo *)vp->v_data; vp->v_flag &= ~VCLONED; ndp->ni_vp = cip->ci_vp; /* return cloned vnode */ vp->v_data = cip->ci_data; /* restore v_data */ VOP_UNLOCK(vp); /* keep a reference */ vp = ndp->ni_vp; /* for the increment below */ free(cip, M_TEMP, sizeof(*cip)); } if (fmode & FWRITE) vp->v_writecount++; return (0); bad: vput(vp); return (error); } /* * Check for write permissions on the specified vnode. * Prototype text segments cannot be written. */ int vn_writechk(struct vnode *vp) { /* * Disallow write attempts on read-only file systems; * unless the file is a socket or a block or character * device resident on the file system. */ if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_RDONLY)) { switch (vp->v_type) { case VREG: case VDIR: case VLNK: return (EROFS); case VNON: case VCHR: case VSOCK: case VFIFO: case VBAD: case VBLK: break; } } /* * If there's shared text associated with * the vnode, try to free it up once. If * we fail, we can't allow writing. */ if ((vp->v_flag & VTEXT) && !uvm_vnp_uncache(vp)) return (ETXTBSY); return (0); } /* * Check whether a write operation would exceed the file size rlimit * for the process, if one should be applied for this operation. * If a partial write should take place, the uio is adjusted and the * amount by which the request would have exceeded the limit is returned * via the 'overrun' argument. */ int vn_fsizechk(struct vnode *vp, struct uio *uio, int ioflag, ssize_t *overrun) { struct proc *p = uio->uio_procp; *overrun = 0; if (vp->v_type == VREG && p != NULL && !(ioflag & IO_NOLIMIT)) { rlim_t limit = lim_cur_proc(p, RLIMIT_FSIZE); /* if already at or over the limit, send the signal and fail */ if (uio->uio_offset >= limit) { psignal(p, SIGXFSZ); return (EFBIG); } /* otherwise, clamp the write to stay under the limit */ if (uio->uio_resid > limit - uio->uio_offset) { *overrun = uio->uio_resid - (limit - uio->uio_offset); uio->uio_resid = limit - uio->uio_offset; } } return (0); } /* * Mark a vnode as being the text image of a running process. */ void vn_marktext(struct vnode *vp) { vp->v_flag |= VTEXT; } /* * Vnode close call */ int vn_close(struct vnode *vp, int flags, struct ucred *cred, struct proc *p) { int error; if (flags & FWRITE) vp->v_writecount--; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); error = VOP_CLOSE(vp, flags, cred, p); vput(vp); return (error); } /* * Package up an I/O request on a vnode into a uio and do it. */ int vn_rdwr(enum uio_rw rw, struct vnode *vp, caddr_t base, int len, off_t offset, enum uio_seg segflg, int ioflg, struct ucred *cred, size_t *aresid, struct proc *p) { struct uio auio; struct iovec aiov; int error; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; aiov.iov_base = base; aiov.iov_len = len; auio.uio_resid = len; auio.uio_offset = offset; auio.uio_segflg = segflg; auio.uio_rw = rw; auio.uio_procp = p; if ((ioflg & IO_NODELOCKED) == 0) vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if (rw == UIO_READ) { error = VOP_READ(vp, &auio, ioflg, cred); } else { error = VOP_WRITE(vp, &auio, ioflg, cred); } if ((ioflg & IO_NODELOCKED) == 0) VOP_UNLOCK(vp); if (aresid) *aresid = auio.uio_resid; else if (auio.uio_resid && error == 0) error = EIO; return (error); } /* * File table vnode read routine. */ int vn_read(struct file *fp, struct uio *uio, int fflags) { struct vnode *vp = fp->f_data; struct ucred *cred = fp->f_cred; size_t count = uio->uio_resid; off_t offset; int error; KERNEL_LOCK(); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if ((fflags & FO_POSITION) == 0) offset = uio->uio_offset = fp->f_offset; else offset = uio->uio_offset; /* no wrap around of offsets except on character devices */ if (vp->v_type != VCHR && count > LLONG_MAX - offset) { error = EINVAL; goto done; } if (vp->v_type == VDIR) { error = EISDIR; goto done; } error = VOP_READ(vp, uio, (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0, cred); if ((fflags & FO_POSITION) == 0) { mtx_enter(&fp->f_mtx); fp->f_offset += count - uio->uio_resid; mtx_leave(&fp->f_mtx); } done: VOP_UNLOCK(vp); KERNEL_UNLOCK(); return (error); } /* * File table vnode write routine. */ int vn_write(struct file *fp, struct uio *uio, int fflags) { struct vnode *vp = fp->f_data; struct ucred *cred = fp->f_cred; int error, ioflag = IO_UNIT; size_t count; KERNEL_LOCK(); /* note: pwrite/pwritev are unaffected by O_APPEND */ if (vp->v_type == VREG && (fp->f_flag & O_APPEND) && (fflags & FO_POSITION) == 0) ioflag |= IO_APPEND; if (fp->f_flag & FNONBLOCK) ioflag |= IO_NDELAY; if ((fp->f_flag & FFSYNC) || (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS))) ioflag |= IO_SYNC; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if ((fflags & FO_POSITION) == 0) uio->uio_offset = fp->f_offset; count = uio->uio_resid; error = VOP_WRITE(vp, uio, ioflag, cred); if ((fflags & FO_POSITION) == 0) { mtx_enter(&fp->f_mtx); if (ioflag & IO_APPEND) fp->f_offset = uio->uio_offset; else fp->f_offset += count - uio->uio_resid; mtx_leave(&fp->f_mtx); } VOP_UNLOCK(vp); KERNEL_UNLOCK(); return (error); } /* * File table wrapper for vn_stat */ int vn_statfile(struct file *fp, struct stat *sb, struct proc *p) { struct vnode *vp = fp->f_data; return vn_stat(vp, sb, p); } /* * vnode stat routine. */ int vn_stat(struct vnode *vp, struct stat *sb, struct proc *p) { struct vattr va; int error; mode_t mode; error = VOP_GETATTR(vp, &va, p->p_ucred, p); if (error) return (error); /* * Copy from vattr table */ memset(sb, 0, sizeof(*sb)); sb->st_dev = va.va_fsid; sb->st_ino = va.va_fileid; mode = va.va_mode; switch (vp->v_type) { case VREG: mode |= S_IFREG; break; case VDIR: mode |= S_IFDIR; break; case VBLK: mode |= S_IFBLK; break; case VCHR: mode |= S_IFCHR; break; case VLNK: mode |= S_IFLNK; break; case VSOCK: mode |= S_IFSOCK; break; case VFIFO: mode |= S_IFIFO; break; default: return (EBADF); } sb->st_mode = mode; sb->st_nlink = va.va_nlink; sb->st_uid = va.va_uid; sb->st_gid = va.va_gid; sb->st_rdev = va.va_rdev; sb->st_size = va.va_size; sb->st_atim.tv_sec = va.va_atime.tv_sec; sb->st_atim.tv_nsec = va.va_atime.tv_nsec; sb->st_mtim.tv_sec = va.va_mtime.tv_sec; sb->st_mtim.tv_nsec = va.va_mtime.tv_nsec; sb->st_ctim.tv_sec = va.va_ctime.tv_sec; sb->st_ctim.tv_nsec = va.va_ctime.tv_nsec; sb->st_blksize = va.va_blocksize; sb->st_flags = va.va_flags; sb->st_gen = va.va_gen; sb->st_blocks = va.va_bytes / S_BLKSIZE; return (0); } /* * File table vnode ioctl routine. */ int vn_ioctl(struct file *fp, u_long com, caddr_t data, struct proc *p) { struct vnode *vp = fp->f_data; struct vattr vattr; int error = ENOTTY; KERNEL_LOCK(); switch (vp->v_type) { case VREG: case VDIR: if (com == FIONREAD) { error = VOP_GETATTR(vp, &vattr, p->p_ucred, p); if (error) break; *(int *)data = vattr.va_size - foffset(fp); } else if (com == FIONBIO || com == FIOASYNC) /* XXX */ error = 0; /* XXX */ break; case VFIFO: case VCHR: case VBLK: error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p); if (error == 0 && com == TIOCSCTTY) { struct session *s = p->p_p->ps_session; struct vnode *ovp = s->s_ttyvp; s->s_ttyvp = vp; vref(vp); if (ovp) vrele(ovp); } break; default: break; } KERNEL_UNLOCK(); return (error); } /* * Check that the vnode is still valid, and if so * acquire requested lock. */ int vn_lock(struct vnode *vp, int flags) { int error, xlocked, do_wakeup; do { mtx_enter(&vnode_mtx); if (vp->v_lflag & VXLOCK) { vp->v_lflag |= VXWANT; msleep_nsec(vp, &vnode_mtx, PINOD, "vn_lock", INFSLP); mtx_leave(&vnode_mtx); error = ENOENT; } else { vp->v_lockcount++; mtx_leave(&vnode_mtx); error = VOP_LOCK(vp, flags); mtx_enter(&vnode_mtx); vp->v_lockcount--; do_wakeup = (vp->v_lockcount == 0); xlocked = vp->v_lflag & VXLOCK; mtx_leave(&vnode_mtx); if (error == 0) { if (!xlocked) return (0); /* * The vnode was exclusively locked while * acquiring the requested lock. Release it and * try again. */ error = ENOENT; VOP_UNLOCK(vp); if (do_wakeup) wakeup_one(&vp->v_lockcount); } } } while (flags & LK_RETRY); return (error); } /* * File table vnode close routine. */ int vn_closefile(struct file *fp, struct proc *p) { struct vnode *vp = fp->f_data; struct flock lf; int error; KERNEL_LOCK(); if ((fp->f_iflags & FIF_HASLOCK)) { lf.l_whence = SEEK_SET; lf.l_start = 0; lf.l_len = 0; lf.l_type = F_UNLCK; (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK); } error = vn_close(vp, fp->f_flag, fp->f_cred, p); KERNEL_UNLOCK(); return (error); } int vn_kqfilter(struct file *fp, struct knote *kn) { int error; KERNEL_LOCK(); error = VOP_KQFILTER(fp->f_data, fp->f_flag, kn); KERNEL_UNLOCK(); return (error); } int vn_seek(struct file *fp, off_t *offset, int whence, struct proc *p) { struct ucred *cred = p->p_ucred; struct vnode *vp = fp->f_data; struct vattr vattr; off_t newoff; int error = 0; int special; if (vp->v_type == VFIFO) return (ESPIPE); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if (vp->v_type == VCHR) special = 1; else special = 0; switch (whence) { case SEEK_CUR: newoff = fp->f_offset + *offset; break; case SEEK_END: KERNEL_LOCK(); error = VOP_GETATTR(vp, &vattr, cred, p); KERNEL_UNLOCK(); if (error) goto out; newoff = *offset + (off_t)vattr.va_size; break; case SEEK_SET: newoff = *offset; break; default: error = EINVAL; goto out; } if (!special && newoff < 0) { error = EINVAL; goto out; } mtx_enter(&fp->f_mtx); fp->f_offset = newoff; mtx_leave(&fp->f_mtx); *offset = newoff; out: VOP_UNLOCK(vp); return (error); } /* * Common code for vnode access operations. */ /* Check if a directory can be found inside another in the hierarchy */ int vn_isunder(struct vnode *lvp, struct vnode *rvp, struct proc *p) { int error; error = vfs_getcwd_common(lvp, rvp, NULL, NULL, MAXPATHLEN/2, 0, p); if (!error) return (1); return (0); }
3 1 1 1 1 5 1 1 2 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 /* $OpenBSD: ksyms.c,v 1.34 2022/01/08 22:54:49 guenther Exp $ */ /* * Copyright (c) 1998 Todd C. Miller <millert@openbsd.org> * Copyright (c) 2001 Artur Grabowski <art@openbsd.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/exec.h> #include <sys/systm.h> #include <sys/uio.h> #include <sys/malloc.h> #include <sys/fcntl.h> #include <sys/conf.h> #include <sys/exec_elf.h> extern char *esym; /* end of symbol table */ #if defined(__sparc64__) || defined(__mips__) || defined(__amd64__) || \ defined(__i386__) || defined(__powerpc64__) extern char *ssym; /* end of kernel */ #else extern long end; /* end of kernel */ #endif static caddr_t ksym_head; static caddr_t ksym_syms; static size_t ksym_head_size; static size_t ksym_syms_size; void ksymsattach(int); void ksymsattach(int num) { #if defined(__sparc64__) || defined(__mips__) || defined(__amd64__) || \ defined(__i386__) || defined(__powerpc64__) if (esym <= ssym) { printf("/dev/ksyms: Symbol table not valid.\n"); return; } #else if (esym <= (char *)&end) { printf("/dev/ksyms: Symbol table not valid.\n"); return; } #endif do { #if defined(__sparc64__) || defined(__mips__) || defined(__amd64__) || \ defined(__i386__) || defined(__powerpc64__) caddr_t symtab = ssym; #else caddr_t symtab = (caddr_t)&end; #endif Elf_Ehdr *elf; Elf_Shdr *shdr; int i; elf = (Elf_Ehdr *)symtab; if (memcmp(elf->e_ident, ELFMAG, SELFMAG) != 0 || elf->e_ident[EI_CLASS] != ELFCLASS || elf->e_machine != ELF_TARG_MACH) break; shdr = (Elf_Shdr *)&symtab[elf->e_shoff]; for (i = 0; i < elf->e_shnum; i++) { if (shdr[i].sh_type == SHT_SYMTAB) { break; } } /* * No symbol table found. */ if (i == elf->e_shnum) break; /* * No additional header. */ ksym_head_size = 0; ksym_syms = symtab; ksym_syms_size = (size_t)(esym - symtab); return; } while (0); } int ksymsopen(dev_t dev, int flag, int mode, struct proc *p) { /* There are no non-zero minor devices */ if (minor(dev) != 0) return (ENXIO); /* This device is read-only */ if ((flag & FWRITE)) return (EPERM); /* ksym_syms must be initialized */ if (ksym_syms == NULL) return (ENXIO); return (0); } int ksymsclose(dev_t dev, int flag, int mode, struct proc *p) { return (0); } int ksymsread(dev_t dev, struct uio *uio, int flags) { int error; size_t len; caddr_t v; size_t off; if (uio->uio_offset < 0) return (EINVAL); while (uio->uio_resid > 0) { if (uio->uio_offset >= ksym_head_size + ksym_syms_size) break; if (uio->uio_offset < ksym_head_size) { v = ksym_head + uio->uio_offset; len = ksym_head_size - uio->uio_offset; } else { off = uio->uio_offset - ksym_head_size; v = ksym_syms + off; len = ksym_syms_size - off; } if (len > uio->uio_resid) len = uio->uio_resid; if ((error = uiomove(v, len, uio)) != 0) return (error); } return (0); }
1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 /* $OpenBSD: uk.c,v 1.26 2021/10/24 16:57:30 mpi Exp $ */ /* $NetBSD: uk.c,v 1.15 1996/03/17 00:59:57 thorpej Exp $ */ /* * Copyright (c) 1994 Charles Hannum. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Charles Hannum. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Dummy driver for a device we can't identify. * Originally by Julian Elischer (julian@tfs.com) */ #include <sys/param.h> #include <sys/systm.h> #include <sys/errno.h> #include <sys/ioctl.h> #include <sys/conf.h> #include <sys/device.h> #include <sys/vnode.h> #include <scsi/scsi_all.h> #include <scsi/scsi_debug.h> #include <scsi/scsiconf.h> #define UKUNIT(z) (minor(z)) struct uk_softc { struct device sc_dev; struct scsi_link *sc_link; /* all the inter level info */ }; int ukmatch(struct device *, void *, void *); void ukattach(struct device *, struct device *, void *); int ukdetach(struct device *, int); const struct cfattach uk_ca = { sizeof(struct uk_softc), ukmatch, ukattach, ukdetach }; struct cfdriver uk_cd = { NULL, "uk", DV_DULL }; #define uklookup(unit) (struct uk_softc *)device_lookup(&uk_cd, (unit)) int ukmatch(struct device *parent, void *match, void *aux) { return 1; } /* * The routine called by the low level scsi routine when it discovers * a device suitable for this driver. */ void ukattach(struct device *parent, struct device *self, void *aux) { struct uk_softc *sc = (void *)self; struct scsi_attach_args *sa = aux; struct scsi_link *link = sa->sa_sc_link; SC_DEBUG(link, SDEV_DB2, ("ukattach: ")); /* Store information needed to contact our base driver. */ sc->sc_link = link; link->device_softc = sc; link->openings = 1; printf("\n"); } int ukdetach(struct device *self, int flags) { int bmaj, cmaj, mn; mn = self->dv_unit; for (bmaj = 0; bmaj < nblkdev; bmaj++) if (bdevsw[bmaj].d_open == ukopen) vdevgone(bmaj, mn, mn, VBLK); for (cmaj = 0; cmaj < nchrdev; cmaj++) if (cdevsw[cmaj].d_open == ukopen) vdevgone(cmaj, mn, mn, VCHR); return 0; } /* * Open the device. */ int ukopen(dev_t dev, int flag, int fmt, struct proc *p) { struct uk_softc *sc; struct scsi_link *link; int unit; unit = UKUNIT(dev); sc = uklookup(unit); if (sc == NULL) return ENXIO; link = sc->sc_link; SC_DEBUG(link, SDEV_DB1, ("ukopen: dev=0x%x (unit %d (of %d))\n", dev, unit, uk_cd.cd_ndevs)); /* Only allow one at a time. */ if (ISSET(link->flags, SDEV_OPEN)) { device_unref(&sc->sc_dev); return EBUSY; } SET(link->flags, SDEV_OPEN); SC_DEBUG(link, SDEV_DB3, ("open complete\n")); device_unref(&sc->sc_dev); return 0; } /* * Close the device. Called only if we are the LAST * occurrence of an open device. */ int ukclose(dev_t dev, int flag, int fmt, struct proc *p) { struct uk_softc *sc; sc = uklookup(UKUNIT(dev)); if (sc == NULL) return ENXIO; SC_DEBUG(sc->sc_link, SDEV_DB1, ("closing\n")); CLR(sc->sc_link->flags, SDEV_OPEN); device_unref(&sc->sc_dev); return 0; } /* * Perform special action on behalf of the user * Only does generic scsi ioctls. */ int ukioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { struct uk_softc *sc; int rv; sc = uklookup(UKUNIT(dev)); if (sc == NULL) return ENXIO; rv = scsi_do_ioctl(sc->sc_link, cmd, addr, flag); device_unref(&sc->sc_dev); return rv; }
5 2 2 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 /* $OpenBSD: ip_ipip.c,v 1.102 2024/05/17 20:44:36 bluhm Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr) and * Niels Provos (provos@physnet.uni-hamburg.de). * * The original version of this code was written by John Ioannidis * for BSD/OS in Athens, Greece, in November 1995. * * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, * by Angelos D. Keromytis. * * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis * and Niels Provos. * * Additional features in 1999 by Angelos D. Keromytis. * * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, * Angelos D. Keromytis and Niels Provos. * Copyright (c) 2001, Angelos D. Keromytis. * * Permission to use, copy, and modify this software with or without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or * modification of this software. * You may use this code under the GNU public license if you so wish. Please * contribute changes back to the authors under this freer than GPL license * so that we may further the use of strong encryption without limitations to * all. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR * PURPOSE. */ /* * IP-inside-IP processing */ #include "bpfilter.h" #include "gif.h" #include "pf.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/sysctl.h> #include <net/if.h> #include <net/if_types.h> #include <net/if_var.h> #include <net/route.h> #include <net/netisr.h> #include <net/bpf.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/in_pcb.h> #include <netinet/ip_var.h> #include <netinet6/ip6_var.h> #include <netinet/ip_ecn.h> #include <netinet/ip_ipip.h> #ifdef MROUTING #include <netinet/ip_mroute.h> #endif #if NPF > 0 #include <net/pfvar.h> #endif #ifdef ENCDEBUG #define DPRINTF(fmt, args...) \ do { \ if (encdebug) \ printf("%s: " fmt "\n", __func__, ## args); \ } while (0) #else #define DPRINTF(fmt, args...) \ do { } while (0) #endif /* * We can control the acceptance of IP4 packets by altering the sysctl * net.inet.ipip.allow value. Zero means drop them, all else is acceptance. */ int ipip_allow = 0; struct cpumem *ipipcounters; void ipip_init(void) { ipipcounters = counters_alloc(ipips_ncounters); } /* * Really only a wrapper for ipip_input_if(), for use with pr_input. */ int ipip_input(struct mbuf **mp, int *offp, int nxt, int af) { struct ifnet *ifp; /* If we do not accept IP-in-IP explicitly, drop. */ if (!ipip_allow && ((*mp)->m_flags & (M_AUTH|M_CONF)) == 0) { DPRINTF("dropped due to policy"); ipipstat_inc(ipips_pdrops); m_freemp(mp); return IPPROTO_DONE; } ifp = if_get((*mp)->m_pkthdr.ph_ifidx); if (ifp == NULL) { m_freemp(mp); return IPPROTO_DONE; } nxt = ipip_input_if(mp, offp, nxt, af, ifp); if_put(ifp); return nxt; } /* * ipip_input gets called when we receive an IP{46} encapsulated packet, * either because we got it at a real interface, or because AH or ESP * were being used in tunnel mode (in which case the ph_ifidx element * will contain the index of the encX interface associated with the * tunnel. */ int ipip_input_if(struct mbuf **mp, int *offp, int proto, int oaf, struct ifnet *ifp) { struct mbuf *m = *mp; struct sockaddr_in *sin; struct ip *ip; #ifdef INET6 struct sockaddr_in6 *sin6; struct ip6_hdr *ip6; #endif int mode, hlen; u_int8_t itos, otos; sa_family_t iaf; ipipstat_inc(ipips_ipackets); switch (oaf) { case AF_INET: hlen = sizeof(struct ip); break; #ifdef INET6 case AF_INET6: hlen = sizeof(struct ip6_hdr); break; #endif default: unhandled_af(oaf); } /* Bring the IP header in the first mbuf, if not there already */ if (m->m_len < hlen) { if ((m = *mp = m_pullup(m, hlen)) == NULL) { DPRINTF("m_pullup() failed"); ipipstat_inc(ipips_hdrops); goto bad; } } /* Keep outer ecn field. */ switch (oaf) { case AF_INET: ip = mtod(m, struct ip *); otos = ip->ip_tos; break; #ifdef INET6 case AF_INET6: ip6 = mtod(m, struct ip6_hdr *); otos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; break; #endif } /* Remove outer IP header */ KASSERT(*offp > 0); m_adj(m, *offp); *offp = 0; ip = NULL; #ifdef INET6 ip6 = NULL; #endif switch (proto) { case IPPROTO_IPV4: hlen = sizeof(struct ip); break; #ifdef INET6 case IPPROTO_IPV6: hlen = sizeof(struct ip6_hdr); break; #endif default: ipipstat_inc(ipips_family); goto bad; } /* Sanity check */ if (m->m_pkthdr.len < hlen) { ipipstat_inc(ipips_hdrops); goto bad; } /* * Bring the inner header into the first mbuf, if not there already. */ if (m->m_len < hlen) { if ((m = *mp = m_pullup(m, hlen)) == NULL) { DPRINTF("m_pullup() failed"); ipipstat_inc(ipips_hdrops); goto bad; } } /* * RFC 1853 specifies that the inner TTL should not be touched on * decapsulation. There's no reason this comment should be here, but * this is as good as any a position. */ /* Some sanity checks in the inner IP header */ switch (proto) { case IPPROTO_IPV4: iaf = AF_INET; ip = mtod(m, struct ip *); hlen = ip->ip_hl << 2; if (m->m_pkthdr.len < hlen) { ipipstat_inc(ipips_hdrops); goto bad; } itos = ip->ip_tos; mode = m->m_flags & (M_AUTH|M_CONF) ? ECN_ALLOWED_IPSEC : ECN_ALLOWED; if (!ip_ecn_egress(mode, &otos, &itos)) { DPRINTF("ip_ecn_egress() failed"); ipipstat_inc(ipips_pdrops); goto bad; } /* re-calculate the checksum if ip_tos was changed */ if (itos != ip->ip_tos) ip_tos_patch(ip, itos); break; #ifdef INET6 case IPPROTO_IPV6: iaf = AF_INET6; ip6 = mtod(m, struct ip6_hdr *); itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; if (!ip_ecn_egress(ECN_ALLOWED, &otos, &itos)) { DPRINTF("ip_ecn_egress() failed"); ipipstat_inc(ipips_pdrops); goto bad; } ip6->ip6_flow &= ~htonl(0xff << 20); ip6->ip6_flow |= htonl((u_int32_t) itos << 20); break; #endif } /* Check for local address spoofing. */ if (!(ifp->if_flags & IFF_LOOPBACK) && ipip_allow != 2) { struct sockaddr_storage ss; struct rtentry *rt; memset(&ss, 0, sizeof(ss)); if (ip) { sin = (struct sockaddr_in *)&ss; sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); sin->sin_addr = ip->ip_src; #ifdef INET6 } else if (ip6) { sin6 = (struct sockaddr_in6 *)&ss; sin6->sin6_family = AF_INET6; sin6->sin6_len = sizeof(*sin6); sin6->sin6_addr = ip6->ip6_src; #endif /* INET6 */ } rt = rtalloc(sstosa(&ss), 0, m->m_pkthdr.ph_rtableid); if ((rt != NULL) && (rt->rt_flags & RTF_LOCAL)) { ipipstat_inc(ipips_spoof); rtfree(rt); goto bad; } rtfree(rt); } /* Statistics */ ipipstat_add(ipips_ibytes, m->m_pkthdr.len - hlen); #if NBPFILTER > 0 && NGIF > 0 if (ifp->if_type == IFT_GIF && ifp->if_bpf != NULL) bpf_mtap_af(ifp->if_bpf, iaf, m, BPF_DIRECTION_IN); #endif #if NPF > 0 pf_pkt_addr_changed(m); #endif /* * Interface pointer stays the same; if no IPsec processing has * been done (or will be done), this will point to a normal * interface. Otherwise, it'll point to an enc interface, which * will allow a packet filter to distinguish between secure and * untrusted packets. */ switch (proto) { case IPPROTO_IPV4: return ip_input_if(mp, offp, proto, oaf, ifp); #ifdef INET6 case IPPROTO_IPV6: return ip6_input_if(mp, offp, proto, oaf, ifp); #endif } bad: m_freemp(mp); return IPPROTO_DONE; } int ipip_output(struct mbuf **mp, struct tdb *tdb) { struct mbuf *m = *mp; u_int8_t tp, otos, itos; u_int64_t obytes; struct ip *ipo; #ifdef INET6 struct ip6_hdr *ip6, *ip6o; #endif /* INET6 */ #ifdef ENCDEBUG char buf[INET6_ADDRSTRLEN]; #endif int error; /* XXX Deal with empty TDB source/destination addresses. */ m_copydata(m, 0, 1, &tp); tp = (tp >> 4) & 0xff; /* Get the IP version number. */ switch (tdb->tdb_dst.sa.sa_family) { case AF_INET: if (tdb->tdb_src.sa.sa_family != AF_INET || tdb->tdb_src.sin.sin_addr.s_addr == INADDR_ANY || tdb->tdb_dst.sin.sin_addr.s_addr == INADDR_ANY) { DPRINTF("unspecified tunnel endpoint address " "in SA %s/%08x", ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); ipipstat_inc(ipips_unspec); error = EINVAL; goto drop; } M_PREPEND(*mp, sizeof(struct ip), M_DONTWAIT); if (*mp == NULL) { DPRINTF("M_PREPEND failed"); ipipstat_inc(ipips_hdrops); error = ENOBUFS; goto drop; } m = *mp; ipo = mtod(m, struct ip *); ipo->ip_v = IPVERSION; ipo->ip_hl = 5; ipo->ip_len = htons(m->m_pkthdr.len); ipo->ip_ttl = ip_defttl; ipo->ip_sum = 0; ipo->ip_src = tdb->tdb_src.sin.sin_addr; ipo->ip_dst = tdb->tdb_dst.sin.sin_addr; /* * We do the htons() to prevent snoopers from determining our * endianness. */ ipo->ip_id = htons(ip_randomid()); /* If the inner protocol is IP... */ if (tp == IPVERSION) { /* Save ECN notification */ m_copydata(m, sizeof(struct ip) + offsetof(struct ip, ip_tos), sizeof(u_int8_t), (caddr_t) &itos); ipo->ip_p = IPPROTO_IPIP; /* * We should be keeping tunnel soft-state and * send back ICMPs if needed. */ m_copydata(m, sizeof(struct ip) + offsetof(struct ip, ip_off), sizeof(u_int16_t), (caddr_t) &ipo->ip_off); ipo->ip_off = ntohs(ipo->ip_off); ipo->ip_off &= ~(IP_DF | IP_MF | IP_OFFMASK); ipo->ip_off = htons(ipo->ip_off); } #ifdef INET6 else if (tp == (IPV6_VERSION >> 4)) { u_int32_t itos32; /* Save ECN notification. */ m_copydata(m, sizeof(struct ip) + offsetof(struct ip6_hdr, ip6_flow), sizeof(u_int32_t), (caddr_t) &itos32); itos = ntohl(itos32) >> 20; ipo->ip_p = IPPROTO_IPV6; ipo->ip_off = 0; } #endif /* INET6 */ else { ipipstat_inc(ipips_family); error = EAFNOSUPPORT; goto drop; } otos = 0; ip_ecn_ingress(ECN_ALLOWED, &otos, &itos); ipo->ip_tos = otos; obytes = m->m_pkthdr.len - sizeof(struct ip); if (tdb->tdb_xform->xf_type == XF_IP4) tdb->tdb_cur_bytes += obytes; break; #ifdef INET6 case AF_INET6: if (IN6_IS_ADDR_UNSPECIFIED(&tdb->tdb_dst.sin6.sin6_addr) || tdb->tdb_src.sa.sa_family != AF_INET6 || IN6_IS_ADDR_UNSPECIFIED(&tdb->tdb_src.sin6.sin6_addr)) { DPRINTF("unspecified tunnel endpoint address " "in SA %s/%08x", ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); ipipstat_inc(ipips_unspec); error = EINVAL; goto drop; } /* If the inner protocol is IPv6, clear link local scope */ if (tp == (IPV6_VERSION >> 4)) { /* scoped address handling */ ip6 = mtod(m, struct ip6_hdr *); if (IN6_IS_SCOPE_EMBED(&ip6->ip6_src)) ip6->ip6_src.s6_addr16[1] = 0; if (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst)) ip6->ip6_dst.s6_addr16[1] = 0; } M_PREPEND(*mp, sizeof(struct ip6_hdr), M_DONTWAIT); if (*mp == NULL) { DPRINTF("M_PREPEND failed"); ipipstat_inc(ipips_hdrops); error = ENOBUFS; goto drop; } m = *mp; /* Initialize IPv6 header */ ip6o = mtod(m, struct ip6_hdr *); ip6o->ip6_flow = 0; ip6o->ip6_vfc &= ~IPV6_VERSION_MASK; ip6o->ip6_vfc |= IPV6_VERSION; ip6o->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6o)); ip6o->ip6_hlim = ip6_defhlim; in6_embedscope(&ip6o->ip6_src, &tdb->tdb_src.sin6, NULL, NULL); in6_embedscope(&ip6o->ip6_dst, &tdb->tdb_dst.sin6, NULL, NULL); if (tp == IPVERSION) { /* Save ECN notification */ m_copydata(m, sizeof(struct ip6_hdr) + offsetof(struct ip, ip_tos), sizeof(u_int8_t), (caddr_t) &itos); /* This is really IPVERSION. */ ip6o->ip6_nxt = IPPROTO_IPIP; } else if (tp == (IPV6_VERSION >> 4)) { u_int32_t itos32; /* Save ECN notification. */ m_copydata(m, sizeof(struct ip6_hdr) + offsetof(struct ip6_hdr, ip6_flow), sizeof(u_int32_t), (caddr_t) &itos32); itos = ntohl(itos32) >> 20; ip6o->ip6_nxt = IPPROTO_IPV6; } else { ipipstat_inc(ipips_family); error = EAFNOSUPPORT; goto drop; } otos = 0; ip_ecn_ingress(ECN_ALLOWED, &otos, &itos); ip6o->ip6_flow |= htonl((u_int32_t) otos << 20); obytes = m->m_pkthdr.len - sizeof(struct ip6_hdr); if (tdb->tdb_xform->xf_type == XF_IP4) tdb->tdb_cur_bytes += obytes; break; #endif /* INET6 */ default: DPRINTF("unsupported protocol family %d", tdb->tdb_dst.sa.sa_family); ipipstat_inc(ipips_family); error = EPFNOSUPPORT; goto drop; } ipipstat_pkt(ipips_opackets, ipips_obytes, obytes); return 0; drop: m_freemp(mp); return error; } #ifdef IPSEC int ipe4_attach(void) { return 0; } int ipe4_init(struct tdb *tdbp, const struct xformsw *xsp, struct ipsecinit *ii) { tdbp->tdb_xform = xsp; return 0; } int ipe4_zeroize(struct tdb *tdbp) { return 0; } int ipe4_input(struct mbuf **mp, struct tdb *tdb, int hlen, int proto) { /* This is a rather serious mistake, so no conditional printing. */ printf("%s: should never be called\n", __func__); m_freemp(mp); return EINVAL; } #endif /* IPSEC */ int ipip_sysctl_ipipstat(void *oldp, size_t *oldlenp, void *newp) { struct ipipstat ipipstat; CTASSERT(sizeof(ipipstat) == (ipips_ncounters * sizeof(uint64_t))); memset(&ipipstat, 0, sizeof ipipstat); counters_read(ipipcounters, (uint64_t *)&ipipstat, ipips_ncounters, NULL); return (sysctl_rdstruct(oldp, oldlenp, newp, &ipipstat, sizeof(ipipstat))); } int ipip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int error; /* All sysctl names at this level are terminal. */ if (namelen != 1) return (ENOTDIR); switch (name[0]) { case IPIPCTL_ALLOW: NET_LOCK(); error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &ipip_allow, 0, 2); NET_UNLOCK(); return (error); case IPIPCTL_STATS: return (ipip_sysctl_ipipstat(oldp, oldlenp, newp)); default: return (ENOPROTOOPT); } /* NOTREACHED */ }
2 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 /* $OpenBSD: cd.c,v 1.266 2022/09/01 13:45:27 krw Exp $ */ /* $NetBSD: cd.c,v 1.100 1997/04/02 02:29:30 mycroft Exp $ */ /* * Copyright (c) 1994, 1995, 1997 Charles M. Hannum. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Charles M. Hannum. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Originally written by Julian Elischer (julian@tfs.com) * for TRW Financial Systems for use under the MACH(2.5) operating system. * * TRW Financial Systems, in accordance with their agreement with Carnegie * Mellon University, makes this software available to CMU to distribute * or use in any manner that they see fit as long as this message is kept with * the software. For this reason TFS also grants any other persons or * organisations permission to use or modify this software. * * TFS supplies this software to be publicly redistributed * on the understanding that TFS is not responsible for the correct * functioning of this software in any circumstances. * * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/timeout.h> #include <sys/fcntl.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <sys/mtio.h> #include <sys/buf.h> #include <sys/uio.h> #include <sys/malloc.h> #include <sys/pool.h> #include <sys/errno.h> #include <sys/device.h> #include <sys/disklabel.h> #include <sys/disk.h> #include <sys/cdio.h> #include <sys/conf.h> #include <sys/scsiio.h> #include <sys/dkio.h> #include <sys/vnode.h> #include <scsi/scsi_all.h> #include <scsi/cd.h> #include <scsi/scsi_debug.h> #include <scsi/scsi_disk.h> /* rw_10 and start_stop come from there */ #include <scsi/scsiconf.h> #include <ufs/ffs/fs.h> /* for BBSIZE and SBSIZE */ #define CDOUTSTANDING 4 #define MAXTRACK 99 #define CD_FRAMES 75 #define CD_SECS 60 struct cd_toc { struct ioc_toc_header header; struct cd_toc_entry entries[MAXTRACK+1]; /* One extra for the */ /* leadout */ }; int cdmatch(struct device *, void *, void *); void cdattach(struct device *, struct device *, void *); int cdactivate(struct device *, int); int cddetach(struct device *, int); struct cd_softc { struct device sc_dev; struct disk sc_dk; int sc_flags; #define CDF_DYING 0x40 /* dying, when deactivated */ struct scsi_link *sc_link; /* contains targ, lun, etc. */ struct cd_parms { u_int32_t secsize; u_int64_t disksize; /* total number sectors */ } params; struct bufq sc_bufq; struct scsi_xshandler sc_xsh; }; void cdstart(struct scsi_xfer *); void cd_buf_done(struct scsi_xfer *); int cd_cmd_rw6(struct scsi_generic *, int, u_int64_t, u_int32_t); int cd_cmd_rw10(struct scsi_generic *, int, u_int64_t, u_int32_t); int cd_cmd_rw12(struct scsi_generic *, int, u_int64_t, u_int32_t); void cdminphys(struct buf *); int cdgetdisklabel(dev_t, struct cd_softc *, struct disklabel *, int); int cd_setchan(struct cd_softc *, int, int, int, int, int); int cd_getvol(struct cd_softc *cd, struct ioc_vol *, int); int cd_setvol(struct cd_softc *, const struct ioc_vol *, int); int cd_load_unload(struct cd_softc *, int, int); int cd_set_pa_immed(struct cd_softc *, int); int cd_play(struct cd_softc *, int, int); int cd_play_tracks(struct cd_softc *, int, int, int, int); int cd_play_msf(struct cd_softc *, int, int, int, int, int, int); int cd_pause(struct cd_softc *, int); int cd_reset(struct cd_softc *); int cd_read_subchannel(struct cd_softc *, int, int, int, struct cd_sub_channel_info *, int ); int cd_read_toc(struct cd_softc *, int, int, void *, int, int); int cd_get_parms(struct cd_softc *, int); int cd_load_toc(struct cd_softc *, struct cd_toc *, int); int cd_interpret_sense(struct scsi_xfer *); u_int64_t cd_size(struct scsi_link *, int, u_int32_t *); int dvd_auth(struct cd_softc *, union dvd_authinfo *); int dvd_read_physical(struct cd_softc *, union dvd_struct *); int dvd_read_copyright(struct cd_softc *, union dvd_struct *); int dvd_read_disckey(struct cd_softc *, union dvd_struct *); int dvd_read_bca(struct cd_softc *, union dvd_struct *); int dvd_read_manufact(struct cd_softc *, union dvd_struct *); int dvd_read_struct(struct cd_softc *, union dvd_struct *); #if defined(__macppc__) int cd_eject(void); #endif /* __macppc__ */ const struct cfattach cd_ca = { sizeof(struct cd_softc), cdmatch, cdattach, cddetach, cdactivate }; struct cfdriver cd_cd = { NULL, "cd", DV_DISK }; const struct scsi_inquiry_pattern cd_patterns[] = { {T_CDROM, T_REMOV, "", "", ""}, {T_CDROM, T_FIXED, "", "", ""}, {T_WORM, T_REMOV, "", "", ""}, {T_WORM, T_FIXED, "", "", ""}, {T_DIRECT, T_REMOV, "NEC CD-ROM DRIVE:260", "", ""}, #if 0 {T_CDROM, T_REMOV, /* more luns */ "PIONEER ", "CD-ROM DRM-600 ", ""}, #endif /* 0 */ }; #define cdlookup(unit) (struct cd_softc *)disk_lookup(&cd_cd, (unit)) int cdmatch(struct device *parent, void *match, void *aux) { struct scsi_attach_args *sa = aux; struct scsi_inquiry_data *inq = &sa->sa_sc_link->inqdata; int priority; scsi_inqmatch(inq, cd_patterns, nitems(cd_patterns), sizeof(cd_patterns[0]), &priority); return priority; } /* * The routine called by the low level scsi routine when it discovers * A device suitable for this driver */ void cdattach(struct device *parent, struct device *self, void *aux) { struct cd_softc *sc = (struct cd_softc *)self; struct scsi_attach_args *sa = aux; struct scsi_link *link = sa->sa_sc_link; SC_DEBUG(link, SDEV_DB2, ("cdattach:\n")); /* * Store information needed to contact our base driver */ sc->sc_link = link; link->interpret_sense = cd_interpret_sense; link->device_softc = sc; if (link->openings > CDOUTSTANDING) link->openings = CDOUTSTANDING; /* * Initialize disk structures. */ sc->sc_dk.dk_name = sc->sc_dev.dv_xname; bufq_init(&sc->sc_bufq, BUFQ_DEFAULT); printf("\n"); scsi_xsh_set(&sc->sc_xsh, link, cdstart); /* Attach disk. */ sc->sc_dk.dk_flags = DKF_NOLABELREAD; disk_attach(&sc->sc_dev, &sc->sc_dk); } int cdactivate(struct device *self, int act) { struct cd_softc *sc = (struct cd_softc *)self; switch (act) { case DVACT_RESUME: /* * When resuming, hardware may have forgotten we locked it. So * if there are any open partitions, lock the CD. */ if (sc->sc_dk.dk_openmask != 0) scsi_prevent(sc->sc_link, PR_PREVENT, SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE | SCSI_SILENT | SCSI_AUTOCONF); break; case DVACT_DEACTIVATE: SET(sc->sc_flags, CDF_DYING); scsi_xsh_del(&sc->sc_xsh); break; } return 0; } int cddetach(struct device *self, int flags) { struct cd_softc *sc = (struct cd_softc *)self; bufq_drain(&sc->sc_bufq); disk_gone(cdopen, self->dv_unit); /* Detach disk. */ bufq_destroy(&sc->sc_bufq); disk_detach(&sc->sc_dk); return 0; } /* * Open the device. Make sure the partition info is as up-to-date as can be. */ int cdopen(dev_t dev, int flag, int fmt, struct proc *p) { struct scsi_link *link; struct cd_softc *sc; int error = 0, part, rawopen, unit; unit = DISKUNIT(dev); part = DISKPART(dev); rawopen = (part == RAW_PART) && (fmt == S_IFCHR); sc = cdlookup(unit); if (sc == NULL) return ENXIO; if (ISSET(sc->sc_flags, CDF_DYING)) { device_unref(&sc->sc_dev); return ENXIO; } link = sc->sc_link; SC_DEBUG(link, SDEV_DB1, ("cdopen: dev=0x%x (unit %d (of %d), partition %d)\n", dev, unit, cd_cd.cd_ndevs, part)); if ((error = disk_lock(&sc->sc_dk)) != 0) { device_unref(&sc->sc_dev); return error; } if (sc->sc_dk.dk_openmask != 0) { /* * If any partition is open, but the disk has been invalidated, * disallow further opens. */ if (!ISSET(link->flags, SDEV_MEDIA_LOADED)) { if (rawopen) goto out; error = EIO; goto bad; } } else { /* * Check that it is still responding and ok. Drive can be in * progress of loading media so use increased retries number * and don't ignore NOT_READY. */ /* Use cd_interpret_sense() now. */ SET(link->flags, SDEV_OPEN); error = scsi_test_unit_ready(link, TEST_READY_RETRIES, (rawopen ? SCSI_SILENT : 0) | SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE); /* Start the cd spinning if necessary. */ if (error == EIO) error = scsi_start(link, SSS_START, SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE | SCSI_SILENT); if (error) { if (rawopen) { error = 0; goto out; } else goto bad; } /* Lock the cd in. */ error = scsi_prevent(link, PR_PREVENT, SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE | SCSI_SILENT); if (error) goto bad; /* Load the physical device parameters. */ SET(link->flags, SDEV_MEDIA_LOADED); if (cd_get_parms(sc, (rawopen ? SCSI_SILENT : 0) | SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE)) { CLR(link->flags, SDEV_MEDIA_LOADED); error = ENXIO; goto bad; } SC_DEBUG(link, SDEV_DB3, ("Params loaded\n")); /* Fabricate a disk label. */ cdgetdisklabel(dev, sc, sc->sc_dk.dk_label, 0); SC_DEBUG(link, SDEV_DB3, ("Disklabel fabricated\n")); } out: if ((error = disk_openpart(&sc->sc_dk, part, fmt, 1)) != 0) goto bad; SET(link->flags, SDEV_OPEN); SC_DEBUG(link, SDEV_DB3, ("open complete\n")); /* It's OK to fall through because dk_openmask is now non-zero. */ bad: if (sc->sc_dk.dk_openmask == 0) { scsi_prevent(link, PR_ALLOW, SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE | SCSI_SILENT); CLR(link->flags, SDEV_OPEN | SDEV_MEDIA_LOADED); } disk_unlock(&sc->sc_dk); device_unref(&sc->sc_dev); return error; } /* * Close the device. Only called if we are the last occurrence of an open * device. */ int cdclose(dev_t dev, int flag, int fmt, struct proc *p) { struct cd_softc *sc; int part = DISKPART(dev); sc = cdlookup(DISKUNIT(dev)); if (sc == NULL) return ENXIO; if (ISSET(sc->sc_flags, CDF_DYING)) { device_unref(&sc->sc_dev); return ENXIO; } disk_lock_nointr(&sc->sc_dk); disk_closepart(&sc->sc_dk, part, fmt); if (sc->sc_dk.dk_openmask == 0) { /* XXXX Must wait for I/O to complete! */ scsi_prevent(sc->sc_link, PR_ALLOW, SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY | SCSI_SILENT); CLR(sc->sc_link->flags, SDEV_OPEN | SDEV_MEDIA_LOADED); if (ISSET(sc->sc_link->flags, SDEV_EJECTING)) { scsi_start(sc->sc_link, SSS_STOP|SSS_LOEJ, 0); CLR(sc->sc_link->flags, SDEV_EJECTING); } scsi_xsh_del(&sc->sc_xsh); } disk_unlock(&sc->sc_dk); device_unref(&sc->sc_dev); return 0; } /* * Actually translate the requested transfer into one the physical driver can * understand. The transfer is described by a buf and will include only one * physical transfer. */ void cdstrategy(struct buf *bp) { struct cd_softc *sc; int s; sc = cdlookup(DISKUNIT(bp->b_dev)); if (sc == NULL) { bp->b_error = ENXIO; goto bad; } if (ISSET(sc->sc_flags, CDF_DYING)) { bp->b_error = ENXIO; goto bad; } SC_DEBUG(sc->sc_link, SDEV_DB2, ("cdstrategy: %ld bytes @ blk %lld\n", bp->b_bcount, (long long)bp->b_blkno)); /* * If the device has been made invalid, error out * maybe the media changed, or no media loaded */ if (!ISSET(sc->sc_link->flags, SDEV_MEDIA_LOADED)) { bp->b_error = EIO; goto bad; } /* Validate the request. */ if (bounds_check_with_label(bp, sc->sc_dk.dk_label) == -1) goto done; /* Place it in the queue of disk activities for this disk. */ bufq_queue(&sc->sc_bufq, bp); /* * Tell the device to get going on the transfer if it's * not doing anything, otherwise just wait for completion */ scsi_xsh_add(&sc->sc_xsh); device_unref(&sc->sc_dev); return; bad: SET(bp->b_flags, B_ERROR); bp->b_resid = bp->b_bcount; done: s = splbio(); biodone(bp); splx(s); if (sc != NULL) device_unref(&sc->sc_dev); } int cd_cmd_rw6(struct scsi_generic *generic, int read, u_int64_t secno, u_int32_t nsecs) { struct scsi_rw *cmd = (struct scsi_rw *)generic; cmd->opcode = read ? READ_COMMAND : WRITE_COMMAND; _lto3b(secno, cmd->addr); cmd->length = nsecs & 0xff; return sizeof(*cmd); } int cd_cmd_rw10(struct scsi_generic *generic, int read, u_int64_t secno, u_int32_t nsecs) { struct scsi_rw_10 *cmd = (struct scsi_rw_10 *)generic; cmd->opcode = read ? READ_10 : WRITE_10; _lto4b(secno, cmd->addr); _lto2b(nsecs, cmd->length); return sizeof(*cmd); } int cd_cmd_rw12(struct scsi_generic *generic, int read, u_int64_t secno, u_int32_t nsecs) { struct scsi_rw_12 *cmd = (struct scsi_rw_12 *)generic; cmd->opcode = read ? READ_12 : WRITE_12; _lto4b(secno, cmd->addr); _lto4b(nsecs, cmd->length); return sizeof(*cmd); } /* * cdstart looks to see if there is a buf waiting for the device * and that the device is not already busy. If both are true, * It dequeues the buf and creates a scsi command to perform the * transfer in the buf. The transfer request will call scsi_done * on completion, which will in turn call this routine again * so that the next queued transfer is performed. * The bufs are queued by the strategy routine (cdstrategy) * * This routine is also called after other non-queued requests * have been made of the scsi driver, to ensure that the queue * continues to be drained. * * must be called at the correct (highish) spl level * cdstart() is called at splbio from cdstrategy and scsi_done */ void cdstart(struct scsi_xfer *xs) { struct scsi_link *link = xs->sc_link; struct cd_softc *sc = link->device_softc; struct buf *bp; struct partition *p; u_int64_t secno; u_int32_t nsecs; int read; SC_DEBUG(link, SDEV_DB2, ("cdstart\n")); if (ISSET(sc->sc_flags, CDF_DYING)) { scsi_xs_put(xs); return; } if (!ISSET(link->flags, SDEV_MEDIA_LOADED)) { bufq_drain(&sc->sc_bufq); scsi_xs_put(xs); return; } bp = bufq_dequeue(&sc->sc_bufq); if (bp == NULL) { scsi_xs_put(xs); return; } read = ISSET(bp->b_flags, B_READ); SET(xs->flags, (read ? SCSI_DATA_IN : SCSI_DATA_OUT)); xs->timeout = 30000; xs->data = bp->b_data; xs->datalen = bp->b_bcount; xs->done = cd_buf_done; xs->cookie = bp; xs->bp = bp; p = &sc->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)]; secno = DL_GETPOFFSET(p) + DL_BLKTOSEC(sc->sc_dk.dk_label, bp->b_blkno); nsecs = howmany(bp->b_bcount, sc->sc_dk.dk_label->d_secsize); if (!ISSET(link->flags, SDEV_ATAPI | SDEV_UMASS) && (SID_ANSII_REV(&link->inqdata) < SCSI_REV_2) && ((secno & 0x1fffff) == secno) && ((nsecs & 0xff) == nsecs)) xs->cmdlen = cd_cmd_rw6(&xs->cmd, read, secno, nsecs); else if (((secno & 0xffffffff) == secno) && ((nsecs & 0xffff) == nsecs)) xs->cmdlen = cd_cmd_rw10(&xs->cmd, read, secno, nsecs); else xs->cmdlen = cd_cmd_rw12(&xs->cmd, read, secno, nsecs); disk_busy(&sc->sc_dk); scsi_xs_exec(xs); /* Move onto the next io. */ if (bufq_peek(&sc->sc_bufq)) scsi_xsh_add(&sc->sc_xsh); } void cd_buf_done(struct scsi_xfer *xs) { struct cd_softc *sc = xs->sc_link->device_softc; struct buf *bp = xs->cookie; int error, s; switch (xs->error) { case XS_NOERROR: bp->b_error = 0; CLR(bp->b_flags, B_ERROR); bp->b_resid = xs->resid; break; case XS_SENSE: case XS_SHORTSENSE: SC_DEBUG_SENSE(xs); error = cd_interpret_sense(xs); if (error == 0) { bp->b_error = 0; CLR(bp->b_flags, B_ERROR); bp->b_resid = xs->resid; break; } if (error != ERESTART) xs->retries = 0; goto retry; case XS_BUSY: if (xs->retries) { if (scsi_delay(xs, 1) != ERESTART) xs->retries = 0; } goto retry; case XS_TIMEOUT: retry: if (xs->retries--) { scsi_xs_exec(xs); return; } /* FALLTHROUGH */ default: bp->b_error = EIO; SET(bp->b_flags, B_ERROR); bp->b_resid = bp->b_bcount; break; } disk_unbusy(&sc->sc_dk, bp->b_bcount - xs->resid, bp->b_blkno, bp->b_flags & B_READ); s = splbio(); biodone(bp); splx(s); scsi_xs_put(xs); } void cdminphys(struct buf *bp) { struct scsi_link *link; struct cd_softc *sc; long max; sc = cdlookup(DISKUNIT(bp->b_dev)); if (sc == NULL) return; link = sc->sc_link; /* * If the device is ancient, we want to make sure that * the transfer fits into a 6-byte cdb. * * XXX Note that the SCSI-I spec says that 256-block transfers * are allowed in a 6-byte read/write, and are specified * by setting the "length" to 0. However, we're conservative * here, allowing only 255-block transfers in case an * ancient device gets confused by length == 0. A length of 0 * in a 10-byte read/write actually means 0 blocks. */ if (!ISSET(link->flags, SDEV_ATAPI | SDEV_UMASS) && SID_ANSII_REV(&link->inqdata) < SCSI_REV_2) { max = sc->sc_dk.dk_label->d_secsize * 0xff; if (bp->b_bcount > max) bp->b_bcount = max; } if (link->bus->sb_adapter->dev_minphys != NULL) (*link->bus->sb_adapter->dev_minphys)(bp, link); else minphys(bp); device_unref(&sc->sc_dev); } int cdread(dev_t dev, struct uio *uio, int ioflag) { return physio(cdstrategy, dev, B_READ, cdminphys, uio); } int cdwrite(dev_t dev, struct uio *uio, int ioflag) { return physio(cdstrategy, dev, B_WRITE, cdminphys, uio); } /* * Perform special action on behalf of the user. * Knows about the internals of this device */ int cdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { struct cd_softc *sc; struct disklabel *lp; int part = DISKPART(dev); int error = 0; sc = cdlookup(DISKUNIT(dev)); if (sc == NULL) return ENXIO; if (ISSET(sc->sc_flags, CDF_DYING)) { device_unref(&sc->sc_dev); return ENXIO; } SC_DEBUG(sc->sc_link, SDEV_DB2, ("cdioctl 0x%lx\n", cmd)); /* * If the device is not valid.. abandon ship */ if (!ISSET(sc->sc_link->flags, SDEV_MEDIA_LOADED)) { switch (cmd) { case DIOCLOCK: case DIOCEJECT: case SCIOCIDENTIFY: case SCIOCCOMMAND: case SCIOCDEBUG: case CDIOCLOADUNLOAD: case SCIOCRESET: case CDIOCGETVOL: case CDIOCSETVOL: case CDIOCSETMONO: case CDIOCSETSTEREO: case CDIOCSETMUTE: case CDIOCSETLEFT: case CDIOCSETRIGHT: case CDIOCCLOSE: case CDIOCEJECT: case CDIOCALLOW: case CDIOCPREVENT: case CDIOCSETDEBUG: case CDIOCCLRDEBUG: case CDIOCRESET: case DVD_AUTH: case DVD_READ_STRUCT: case MTIOCTOP: if (part == RAW_PART) break; /* FALLTHROUGH */ default: if (!ISSET(sc->sc_link->flags, SDEV_OPEN)) error = ENODEV; else error = EIO; goto exit; } } switch (cmd) { case DIOCRLDINFO: lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK); cdgetdisklabel(dev, sc, lp, 0); memcpy(sc->sc_dk.dk_label, lp, sizeof(*lp)); free(lp, M_TEMP, sizeof(*lp)); break; case DIOCGPDINFO: cdgetdisklabel(dev, sc, (struct disklabel *)addr, 1); break; case DIOCGDINFO: *(struct disklabel *)addr = *(sc->sc_dk.dk_label); break; case DIOCGPART: ((struct partinfo *)addr)->disklab = sc->sc_dk.dk_label; ((struct partinfo *)addr)->part = &sc->sc_dk.dk_label->d_partitions[DISKPART(dev)]; break; case DIOCWDINFO: case DIOCSDINFO: if (!ISSET(flag, FWRITE)) { error = EBADF; break; } if ((error = disk_lock(&sc->sc_dk)) != 0) break; error = setdisklabel(sc->sc_dk.dk_label, (struct disklabel *)addr, sc->sc_dk.dk_openmask); if (error == 0) { } disk_unlock(&sc->sc_dk); break; case CDIOCPLAYTRACKS: { struct ioc_play_track *args = (struct ioc_play_track *)addr; if ((error = cd_set_pa_immed(sc, 0)) != 0) break; error = cd_play_tracks(sc, args->start_track, args->start_index, args->end_track, args->end_index); break; } case CDIOCPLAYMSF: { struct ioc_play_msf *args = (struct ioc_play_msf *)addr; if ((error = cd_set_pa_immed(sc, 0)) != 0) break; error = cd_play_msf(sc, args->start_m, args->start_s, args->start_f, args->end_m, args->end_s, args->end_f); break; } case CDIOCPLAYBLOCKS: { struct ioc_play_blocks *args = (struct ioc_play_blocks *)addr; if ((error = cd_set_pa_immed(sc, 0)) != 0) break; error = cd_play(sc, args->blk, args->len); break; } case CDIOCREADSUBCHANNEL: { struct ioc_read_subchannel *args = (struct ioc_read_subchannel *)addr; struct cd_sub_channel_info *data; int len = args->data_len; if (len > sizeof(*data) || len < sizeof(struct cd_sub_channel_header)) { error = EINVAL; break; } data = dma_alloc(sizeof(*data), PR_WAITOK); error = cd_read_subchannel(sc, args->address_format, args->data_format, args->track, data, len); if (error) { dma_free(data, sizeof(*data)); break; } len = min(len, _2btol(data->header.data_len) + sizeof(struct cd_sub_channel_header)); error = copyout(data, args->data, len); dma_free(data, sizeof(*data)); break; } case CDIOREADTOCHEADER: { struct ioc_toc_header *th; th = dma_alloc(sizeof(*th), PR_WAITOK); if ((error = cd_read_toc(sc, 0, 0, th, sizeof(*th), 0)) != 0) { dma_free(th, sizeof(*th)); break; } if (ISSET(sc->sc_link->quirks, ADEV_LITTLETOC)) th->len = letoh16(th->len); else th->len = betoh16(th->len); if (th->len > 0) memcpy(addr, th, sizeof(*th)); else error = EIO; dma_free(th, sizeof(*th)); break; } case CDIOREADTOCENTRYS: { struct cd_toc *toc; struct ioc_read_toc_entry *te = (struct ioc_read_toc_entry *)addr; struct ioc_toc_header *th; struct cd_toc_entry *cte; int len = te->data_len; int ntracks; toc = dma_alloc(sizeof(*toc), PR_WAITOK | PR_ZERO); th = &toc->header; if (len > sizeof(toc->entries) || len < sizeof(struct cd_toc_entry)) { dma_free(toc, sizeof(*toc)); error = EINVAL; break; } error = cd_read_toc(sc, te->address_format, te->starting_track, toc, len + sizeof(struct ioc_toc_header), 0); if (error) { dma_free(toc, sizeof(*toc)); break; } if (te->address_format == CD_LBA_FORMAT) for (ntracks = th->ending_track - th->starting_track + 1; ntracks >= 0; ntracks--) { cte = &toc->entries[ntracks]; cte->addr_type = CD_LBA_FORMAT; if (ISSET(sc->sc_link->quirks, ADEV_LITTLETOC)) { #if BYTE_ORDER == BIG_ENDIAN swap16_multi((u_int16_t *)&cte->addr, sizeof(cte->addr) / 2); #endif /* BYTE_ORDER == BIG_ENDIAN */ } else cte->addr.lba = betoh32(cte->addr.lba); } if (ISSET(sc->sc_link->quirks, ADEV_LITTLETOC)) { th->len = letoh16(th->len); } else th->len = betoh16(th->len); len = min(len, th->len - (sizeof(th->starting_track) + sizeof(th->ending_track))); error = copyout(toc->entries, te->data, len); dma_free(toc, sizeof(*toc)); break; } case CDIOREADMSADDR: { struct cd_toc *toc; int sessno = *(int *)addr; struct cd_toc_entry *cte; if (sessno != 0) { error = EINVAL; break; } toc = dma_alloc(sizeof(*toc), PR_WAITOK | PR_ZERO); error = cd_read_toc(sc, 0, 0, toc, sizeof(struct ioc_toc_header) + sizeof(struct cd_toc_entry), 0x40 /* control word for "get MS info" */); if (error) { dma_free(toc, sizeof(*toc)); break; } cte = &toc->entries[0]; if (ISSET(sc->sc_link->quirks, ADEV_LITTLETOC)) { #if BYTE_ORDER == BIG_ENDIAN swap16_multi((u_int16_t *)&cte->addr, sizeof(cte->addr) / 2); #endif /* BYTE_ORDER == BIG_ENDIAN */ } else cte->addr.lba = betoh32(cte->addr.lba); if (ISSET(sc->sc_link->quirks, ADEV_LITTLETOC)) toc->header.len = letoh16(toc->header.len); else toc->header.len = betoh16(toc->header.len); *(int *)addr = (toc->header.len >= 10 && cte->track > 1) ? cte->addr.lba : 0; dma_free(toc, sizeof(*toc)); break; } case CDIOCSETPATCH: { struct ioc_patch *arg = (struct ioc_patch *)addr; error = cd_setchan(sc, arg->patch[0], arg->patch[1], arg->patch[2], arg->patch[3], 0); break; } case CDIOCGETVOL: { struct ioc_vol *arg = (struct ioc_vol *)addr; error = cd_getvol(sc, arg, 0); break; } case CDIOCSETVOL: { struct ioc_vol *arg = (struct ioc_vol *)addr; error = cd_setvol(sc, arg, 0); break; } case CDIOCSETMONO: error = cd_setchan(sc, BOTH_CHANNEL, BOTH_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL, 0); break; case CDIOCSETSTEREO: error = cd_setchan(sc, LEFT_CHANNEL, RIGHT_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL, 0); break; case CDIOCSETMUTE: error = cd_setchan(sc, MUTE_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL, 0); break; case CDIOCSETLEFT: error = cd_setchan(sc, LEFT_CHANNEL, LEFT_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL, 0); break; case CDIOCSETRIGHT: error = cd_setchan(sc, RIGHT_CHANNEL, RIGHT_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL, 0); break; case CDIOCRESUME: error = cd_pause(sc, 1); break; case CDIOCPAUSE: error = cd_pause(sc, 0); break; case CDIOCSTART: error = scsi_start(sc->sc_link, SSS_START, 0); break; case CDIOCSTOP: error = scsi_start(sc->sc_link, SSS_STOP, 0); break; close_tray: case CDIOCCLOSE: error = scsi_start(sc->sc_link, SSS_START|SSS_LOEJ, SCSI_IGNORE_NOT_READY | SCSI_IGNORE_MEDIA_CHANGE); break; case MTIOCTOP: if (((struct mtop *)addr)->mt_op == MTRETEN) goto close_tray; if (((struct mtop *)addr)->mt_op != MTOFFL) { error = EIO; break; } /* FALLTHROUGH */ case CDIOCEJECT: /* FALLTHROUGH */ case DIOCEJECT: SET(sc->sc_link->flags, SDEV_EJECTING); break; case CDIOCALLOW: error = scsi_prevent(sc->sc_link, PR_ALLOW, 0); break; case CDIOCPREVENT: error = scsi_prevent(sc->sc_link, PR_PREVENT, 0); break; case DIOCLOCK: error = scsi_prevent(sc->sc_link, (*(int *)addr) ? PR_PREVENT : PR_ALLOW, 0); break; case CDIOCSETDEBUG: SET(sc->sc_link->flags, SDEV_DB1 | SDEV_DB2); break; case CDIOCCLRDEBUG: CLR(sc->sc_link->flags, SDEV_DB1 | SDEV_DB2); break; case CDIOCRESET: case SCIOCRESET: error = cd_reset(sc); break; case CDIOCLOADUNLOAD: { struct ioc_load_unload *args = (struct ioc_load_unload *)addr; error = cd_load_unload(sc, args->options, args->slot); break; } case DVD_AUTH: error = dvd_auth(sc, (union dvd_authinfo *)addr); break; case DVD_READ_STRUCT: error = dvd_read_struct(sc, (union dvd_struct *)addr); break; default: if (DISKPART(dev) != RAW_PART) { error = ENOTTY; break; } error = scsi_do_ioctl(sc->sc_link, cmd, addr, flag); break; } exit: device_unref(&sc->sc_dev); return error; } /* * Load the label information on the named device * Actually fabricate a disklabel * * EVENTUALLY take information about different * data tracks from the TOC and put it in the disklabel */ int cdgetdisklabel(dev_t dev, struct cd_softc *sc, struct disklabel *lp, int spoofonly) { struct cd_toc *toc; int tocidx, n, audioonly = 1; bzero(lp, sizeof(struct disklabel)); lp->d_secsize = sc->params.secsize; lp->d_ntracks = 1; lp->d_nsectors = 100; lp->d_secpercyl = 100; lp->d_ncylinders = (sc->params.disksize / 100) + 1; if (ISSET(sc->sc_link->flags, SDEV_ATAPI)) { strncpy(lp->d_typename, "ATAPI CD-ROM", sizeof(lp->d_typename)); lp->d_type = DTYPE_ATAPI; } else { strncpy(lp->d_typename, "SCSI CD-ROM", sizeof(lp->d_typename)); lp->d_type = DTYPE_SCSI; } strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname)); DL_SETDSIZE(lp, sc->params.disksize); lp->d_version = 1; lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; lp->d_checksum = dkcksum(lp); toc = dma_alloc(sizeof(*toc), PR_WAITOK | PR_ZERO); if (cd_load_toc(sc, toc, CD_LBA_FORMAT)) { audioonly = 0; /* No valid TOC found == not an audio CD. */ goto done; } n = toc->header.ending_track - toc->header.starting_track + 1; for (tocidx = 0; tocidx < n; tocidx++) if (toc->entries[tocidx].control & 4) { audioonly = 0; /* Found a non-audio track. */ goto done; } done: dma_free(toc, sizeof(*toc)); if (audioonly) return 0; return readdisklabel(DISKLABELDEV(dev), cdstrategy, lp, spoofonly); } int cd_setchan(struct cd_softc *sc, int p0, int p1, int p2, int p3, int flags) { union scsi_mode_sense_buf *data; struct cd_audio_page *audio = NULL; int error, big; data = dma_alloc(sizeof(*data), PR_NOWAIT); if (data == NULL) return ENOMEM; error = scsi_do_mode_sense(sc->sc_link, AUDIO_PAGE, data, (void **)&audio, sizeof(*audio), flags, &big); if (error == 0 && audio == NULL) error = EIO; if (error == 0) { audio->port[LEFT_PORT].channels = p0; audio->port[RIGHT_PORT].channels = p1; audio->port[2].channels = p2; audio->port[3].channels = p3; if (big) error = scsi_mode_select_big(sc->sc_link, SMS_PF, &data->hdr_big, flags, 20000); else error = scsi_mode_select(sc->sc_link, SMS_PF, &data->hdr, flags, 20000); } dma_free(data, sizeof(*data)); return error; } int cd_getvol(struct cd_softc *sc, struct ioc_vol *arg, int flags) { union scsi_mode_sense_buf *data; struct cd_audio_page *audio = NULL; int big, error; data = dma_alloc(sizeof(*data), PR_NOWAIT); if (data == NULL) return ENOMEM; error = scsi_do_mode_sense(sc->sc_link, AUDIO_PAGE, data, (void **)&audio, sizeof(*audio), flags, &big); if (error == 0 && audio == NULL) error = EIO; if (error == 0) { arg->vol[0] = audio->port[0].volume; arg->vol[1] = audio->port[1].volume; arg->vol[2] = audio->port[2].volume; arg->vol[3] = audio->port[3].volume; } dma_free(data, sizeof(*data)); return 0; } int cd_setvol(struct cd_softc *sc, const struct ioc_vol *arg, int flags) { union scsi_mode_sense_buf *data; struct cd_audio_page *audio = NULL; u_int8_t mask_volume[4]; int error, big; data = dma_alloc(sizeof(*data), PR_NOWAIT); if (data == NULL) return ENOMEM; error = scsi_do_mode_sense(sc->sc_link, AUDIO_PAGE | SMS_PAGE_CTRL_CHANGEABLE, data, (void **)&audio, sizeof(*audio), flags, &big); if (error == 0 && audio == NULL) error = EIO; if (error != 0) { dma_free(data, sizeof(*data)); return error; } mask_volume[0] = audio->port[0].volume; mask_volume[1] = audio->port[1].volume; mask_volume[2] = audio->port[2].volume; mask_volume[3] = audio->port[3].volume; error = scsi_do_mode_sense(sc->sc_link, AUDIO_PAGE, data, (void **)&audio, sizeof(*audio), flags, &big); if (error == 0 && audio == NULL) error = EIO; if (error != 0) { dma_free(data, sizeof(*data)); return error; } audio->port[0].volume = arg->vol[0] & mask_volume[0]; audio->port[1].volume = arg->vol[1] & mask_volume[1]; audio->port[2].volume = arg->vol[2] & mask_volume[2]; audio->port[3].volume = arg->vol[3] & mask_volume[3]; if (big) error = scsi_mode_select_big(sc->sc_link, SMS_PF, &data->hdr_big, flags, 20000); else error = scsi_mode_select(sc->sc_link, SMS_PF, &data->hdr, flags, 20000); dma_free(data, sizeof(*data)); return error; } int cd_load_unload(struct cd_softc *sc, int options, int slot) { struct scsi_load_unload *cmd; struct scsi_xfer *xs; int error; xs = scsi_xs_get(sc->sc_link, 0); if (xs == NULL) return ENOMEM; xs->cmdlen = sizeof(*cmd); xs->timeout = 200000; cmd = (struct scsi_load_unload *)&xs->cmd; cmd->opcode = LOAD_UNLOAD; cmd->options = options; /* ioctl uses ATAPI values */ cmd->slot = slot; error = scsi_xs_sync(xs); scsi_xs_put(xs); return error; } int cd_set_pa_immed(struct cd_softc *sc, int flags) { union scsi_mode_sense_buf *data; struct cd_audio_page *audio = NULL; int error, oflags, big; if (ISSET(sc->sc_link->flags, SDEV_ATAPI)) /* XXX Noop? */ return 0; data = dma_alloc(sizeof(*data), PR_NOWAIT); if (data == NULL) return ENOMEM; error = scsi_do_mode_sense(sc->sc_link, AUDIO_PAGE, data, (void **)&audio, sizeof(*audio), flags, &big); if (error == 0 && audio == NULL) error = EIO; if (error == 0) { oflags = audio->flags; CLR(audio->flags, CD_PA_SOTC); SET(audio->flags, CD_PA_IMMED); if (audio->flags != oflags) { if (big) error = scsi_mode_select_big(sc->sc_link, SMS_PF, &data->hdr_big, flags, 20000); else error = scsi_mode_select(sc->sc_link, SMS_PF, &data->hdr, flags, 20000); } } dma_free(data, sizeof(*data)); return error; } /* * Get scsi driver to send a "start playing" command */ int cd_play(struct cd_softc *sc, int secno, int nsecs) { struct scsi_play *cmd; struct scsi_xfer *xs; int error; xs = scsi_xs_get(sc->sc_link, 0); if (xs == NULL) return ENOMEM; xs->cmdlen = sizeof(*cmd); xs->timeout = 200000; cmd = (struct scsi_play *)&xs->cmd; cmd->opcode = PLAY; _lto4b(secno, cmd->blk_addr); _lto2b(nsecs, cmd->xfer_len); error = scsi_xs_sync(xs); scsi_xs_put(xs); return error; } /* * Get scsi driver to send a "start playing" command */ int cd_play_tracks(struct cd_softc *sc, int strack, int sindex, int etrack, int eindex) { struct cd_toc *toc; int error; u_char endf, ends, endm; if (!etrack) return EIO; if (strack > etrack) return EINVAL; toc = dma_alloc(sizeof(*toc), PR_WAITOK | PR_ZERO); if ((error = cd_load_toc(sc, toc, CD_MSF_FORMAT)) != 0) goto done; if (++etrack > (toc->header.ending_track+1)) etrack = toc->header.ending_track+1; strack -= toc->header.starting_track; etrack -= toc->header.starting_track; if (strack < 0) { error = EINVAL; goto done; } /* * The track ends one frame before the next begins. The last track * is taken care of by the leadoff track. */ endm = toc->entries[etrack].addr.msf.minute; ends = toc->entries[etrack].addr.msf.second; endf = toc->entries[etrack].addr.msf.frame; if (endf-- == 0) { endf = CD_FRAMES - 1; if (ends-- == 0) { ends = CD_SECS - 1; if (endm-- == 0) { error = EINVAL; goto done; } } } error = cd_play_msf(sc, toc->entries[strack].addr.msf.minute, toc->entries[strack].addr.msf.second, toc->entries[strack].addr.msf.frame, endm, ends, endf); done: dma_free(toc, sizeof(*toc)); return error; } /* * Get scsi driver to send a "play msf" command */ int cd_play_msf(struct cd_softc *sc, int startm, int starts, int startf, int endm, int ends, int endf) { struct scsi_play_msf *cmd; struct scsi_xfer *xs; int error; xs = scsi_xs_get(sc->sc_link, 0); if (xs == NULL) return ENOMEM; xs->cmdlen = sizeof(*cmd); xs->timeout = 20000; cmd = (struct scsi_play_msf *)&xs->cmd; cmd->opcode = PLAY_MSF; cmd->start_m = startm; cmd->start_s = starts; cmd->start_f = startf; cmd->end_m = endm; cmd->end_s = ends; cmd->end_f = endf; error = scsi_xs_sync(xs); scsi_xs_put(xs); return error; } /* * Get scsi driver to send a "start up" command */ int cd_pause(struct cd_softc *sc, int go) { struct scsi_pause *cmd; struct scsi_xfer *xs; int error; xs = scsi_xs_get(sc->sc_link, 0); if (xs == NULL) return ENOMEM; xs->cmdlen = sizeof(*cmd); xs->timeout = 2000; cmd = (struct scsi_pause *)&xs->cmd; cmd->opcode = PAUSE; cmd->resume = go; error = scsi_xs_sync(xs); scsi_xs_put(xs); return error; } /* * Get scsi driver to send a "RESET" command */ int cd_reset(struct cd_softc *sc) { struct scsi_xfer *xs; int error; xs = scsi_xs_get(sc->sc_link, SCSI_RESET); if (xs == NULL) return ENOMEM; xs->timeout = 2000; error = scsi_xs_sync(xs); scsi_xs_put(xs); return error; } /* * Read subchannel */ int cd_read_subchannel(struct cd_softc *sc, int mode, int format, int track, struct cd_sub_channel_info *data, int len) { struct scsi_read_subchannel *cmd; struct scsi_xfer *xs; int error; xs = scsi_xs_get(sc->sc_link, SCSI_DATA_IN | SCSI_SILENT); if (xs == NULL) return ENOMEM; xs->cmdlen = sizeof(*cmd); xs->data = (void *)data; xs->datalen = len; xs->timeout = 5000; cmd = (struct scsi_read_subchannel *)&xs->cmd; cmd->opcode = READ_SUBCHANNEL; if (mode == CD_MSF_FORMAT) SET(cmd->byte2, CD_MSF); cmd->byte3 = SRS_SUBQ; cmd->subchan_format = format; cmd->track = track; _lto2b(len, cmd->data_len); error = scsi_xs_sync(xs); scsi_xs_put(xs); return error; } /* * Read table of contents */ int cd_read_toc(struct cd_softc *sc, int mode, int start, void *data, int len, int control) { struct scsi_read_toc *cmd; struct scsi_xfer *xs; int error; xs = scsi_xs_get(sc->sc_link, SCSI_DATA_IN | SCSI_IGNORE_ILLEGAL_REQUEST); if (xs == NULL) return ENOMEM; xs->cmdlen = sizeof(*cmd); xs->data = data; xs->datalen = len; xs->timeout = 5000; bzero(data, len); cmd = (struct scsi_read_toc *)&xs->cmd; cmd->opcode = READ_TOC; if (mode == CD_MSF_FORMAT) SET(cmd->byte2, CD_MSF); cmd->from_track = start; _lto2b(len, cmd->data_len); cmd->control = control; error = scsi_xs_sync(xs); scsi_xs_put(xs); return error; } int cd_load_toc(struct cd_softc *sc, struct cd_toc *toc, int fmt) { int n, len, error; error = cd_read_toc(sc, 0, 0, toc, sizeof(toc->header), 0); if (error == 0) { if (toc->header.ending_track < toc->header.starting_track) return EIO; /* +2 to account for leading out track. */ n = toc->header.ending_track - toc->header.starting_track + 2; len = n * sizeof(struct cd_toc_entry) + sizeof(toc->header); error = cd_read_toc(sc, fmt, 0, toc, len, 0); } return error; } /* * Get the scsi driver to send a full inquiry to the device and use the * results to fill out the disk parameter structure. */ int cd_get_parms(struct cd_softc *sc, int flags) { /* Reasonable defaults for drives that don't support READ_CAPACITY */ sc->params.secsize = 2048; sc->params.disksize = 400000; if (ISSET(sc->sc_link->quirks, ADEV_NOCAPACITY)) return 0; sc->params.disksize = cd_size(sc->sc_link, flags, &sc->params.secsize); if ((sc->params.secsize < 512) || ((sc->params.secsize & 511) != 0)) sc->params.secsize = 2048; /* some drives lie ! */ if (sc->params.disksize < 100) sc->params.disksize = 400000; return 0; } daddr_t cdsize(dev_t dev) { /* CD-ROMs are read-only. */ return -1; } int cddump(dev_t dev, daddr_t blkno, caddr_t va, size_t size) { /* Not implemented. */ return ENXIO; } #define dvd_copy_key(dst, src) memcpy((dst), (src), DVD_KEY_SIZE) #define dvd_copy_challenge(dst, src) memcpy((dst), (src), DVD_CHALLENGE_SIZE) #define DVD_AUTH_BUFSIZE 20 int dvd_auth(struct cd_softc *sc, union dvd_authinfo *a) { struct scsi_generic *cmd; struct scsi_xfer *xs; u_int8_t *buf; int error; buf = dma_alloc(DVD_AUTH_BUFSIZE, PR_WAITOK | PR_ZERO); if (buf == NULL) return ENOMEM; xs = scsi_xs_get(sc->sc_link, 0); if (xs == NULL) { error = ENOMEM; goto done; } xs->cmdlen = sizeof(*cmd); xs->timeout = 30000; xs->data = buf; cmd = &xs->cmd; switch (a->type) { case DVD_LU_SEND_AGID: cmd->opcode = GPCMD_REPORT_KEY; cmd->bytes[8] = 8; cmd->bytes[9] = 0 | (0 << 6); xs->datalen = 8; SET(xs->flags, SCSI_DATA_IN); error = scsi_xs_sync(xs); scsi_xs_put(xs); if (error == 0) a->lsa.agid = buf[7] >> 6; break; case DVD_LU_SEND_CHALLENGE: cmd->opcode = GPCMD_REPORT_KEY; cmd->bytes[8] = 16; cmd->bytes[9] = 1 | (a->lsc.agid << 6); xs->datalen = 16; SET(xs->flags, SCSI_DATA_IN); error = scsi_xs_sync(xs); scsi_xs_put(xs); if (error == 0) dvd_copy_challenge(a->lsc.chal, &buf[4]); break; case DVD_LU_SEND_KEY1: cmd->opcode = GPCMD_REPORT_KEY; cmd->bytes[8] = 12; cmd->bytes[9] = 2 | (a->lsk.agid << 6); xs->datalen = 12; SET(xs->flags, SCSI_DATA_IN); error = scsi_xs_sync(xs); scsi_xs_put(xs); if (error == 0) dvd_copy_key(a->lsk.key, &buf[4]); break; case DVD_LU_SEND_TITLE_KEY: cmd->opcode = GPCMD_REPORT_KEY; _lto4b(a->lstk.lba, &cmd->bytes[1]); cmd->bytes[8] = 12; cmd->bytes[9] = 4 | (a->lstk.agid << 6); xs->datalen = 12; SET(xs->flags, SCSI_DATA_IN); error = scsi_xs_sync(xs); scsi_xs_put(xs); if (error == 0) { a->lstk.cpm = (buf[4] >> 7) & 1; a->lstk.cp_sec = (buf[4] >> 6) & 1; a->lstk.cgms = (buf[4] >> 4) & 3; dvd_copy_key(a->lstk.title_key, &buf[5]); } break; case DVD_LU_SEND_ASF: cmd->opcode = GPCMD_REPORT_KEY; cmd->bytes[8] = 8; cmd->bytes[9] = 5 | (a->lsasf.agid << 6); xs->datalen = 8; SET(xs->flags, SCSI_DATA_IN); error = scsi_xs_sync(xs); scsi_xs_put(xs); if (error == 0) a->lsasf.asf = buf[7] & 1; break; case DVD_HOST_SEND_CHALLENGE: cmd->opcode = GPCMD_SEND_KEY; cmd->bytes[8] = 16; cmd->bytes[9] = 1 | (a->hsc.agid << 6); buf[1] = 14; dvd_copy_challenge(&buf[4], a->hsc.chal); xs->datalen = 16; SET(xs->flags, SCSI_DATA_OUT); error = scsi_xs_sync(xs); scsi_xs_put(xs); if (error == 0) a->type = DVD_LU_SEND_KEY1; break; case DVD_HOST_SEND_KEY2: cmd->opcode = GPCMD_SEND_KEY; cmd->bytes[8] = 12; cmd->bytes[9] = 3 | (a->hsk.agid << 6); buf[1] = 10; dvd_copy_key(&buf[4], a->hsk.key); xs->datalen = 12; SET(xs->flags, SCSI_DATA_OUT); error = scsi_xs_sync(xs); scsi_xs_put(xs); if (error == 0) a->type = DVD_AUTH_ESTABLISHED; else a->type = DVD_AUTH_FAILURE; break; case DVD_INVALIDATE_AGID: cmd->opcode = GPCMD_REPORT_KEY; cmd->bytes[9] = 0x3f | (a->lsa.agid << 6); xs->data = NULL; error = scsi_xs_sync(xs); scsi_xs_put(xs); break; case DVD_LU_SEND_RPC_STATE: cmd->opcode = GPCMD_REPORT_KEY; cmd->bytes[8] = 8; cmd->bytes[9] = 8 | (0 << 6); xs->datalen = 8; SET(xs->flags, SCSI_DATA_IN); error = scsi_xs_sync(xs); scsi_xs_put(xs); if (error == 0) { a->lrpcs.type = (buf[4] >> 6) & 3; a->lrpcs.vra = (buf[4] >> 3) & 7; a->lrpcs.ucca = (buf[4]) & 7; a->lrpcs.region_mask = buf[5]; a->lrpcs.rpc_scheme = buf[6]; } break; case DVD_HOST_SEND_RPC_STATE: cmd->opcode = GPCMD_SEND_KEY; cmd->bytes[8] = 8; cmd->bytes[9] = 6 | (0 << 6); buf[1] = 6; buf[4] = a->hrpcs.pdrc; xs->datalen = 8; SET(xs->flags, SCSI_DATA_OUT); error = scsi_xs_sync(xs); scsi_xs_put(xs); break; default: scsi_xs_put(xs); error = ENOTTY; break; } done: dma_free(buf, DVD_AUTH_BUFSIZE); return error; } #define DVD_READ_PHYSICAL_BUFSIZE (4 + 4 * 20) int dvd_read_physical(struct cd_softc *sc, union dvd_struct *s) { struct scsi_generic *cmd; struct dvd_layer *layer; struct scsi_xfer *xs; u_int8_t *buf, *bufp; int error, i; buf = dma_alloc(DVD_READ_PHYSICAL_BUFSIZE, PR_WAITOK | PR_ZERO); if (buf == NULL) return ENOMEM; xs = scsi_xs_get(sc->sc_link, SCSI_DATA_IN); if (xs == NULL) { error = ENOMEM; goto done; } xs->cmdlen = sizeof(*cmd); xs->data = buf; xs->datalen = DVD_READ_PHYSICAL_BUFSIZE; xs->timeout = 30000; cmd = &xs->cmd; cmd->opcode = GPCMD_READ_DVD_STRUCTURE; cmd->bytes[6] = s->type; _lto2b(xs->datalen, &cmd->bytes[7]); cmd->bytes[5] = s->physical.layer_num; error = scsi_xs_sync(xs); scsi_xs_put(xs); if (error == 0) { for (i = 0, bufp = &buf[4], layer = &s->physical.layer[0]; i < 4; i++, bufp += 20, layer++) { bzero(layer, sizeof(*layer)); layer->book_version = bufp[0] & 0xf; layer->book_type = bufp[0] >> 4; layer->min_rate = bufp[1] & 0xf; layer->disc_size = bufp[1] >> 4; layer->layer_type = bufp[2] & 0xf; layer->track_path = (bufp[2] >> 4) & 1; layer->nlayers = (bufp[2] >> 5) & 3; layer->track_density = bufp[3] & 0xf; layer->linear_density = bufp[3] >> 4; layer->start_sector = _4btol(&bufp[4]); layer->end_sector = _4btol(&bufp[8]); layer->end_sector_l0 = _4btol(&bufp[12]); layer->bca = bufp[16] >> 7; } } done: dma_free(buf, DVD_READ_PHYSICAL_BUFSIZE); return error; } #define DVD_READ_COPYRIGHT_BUFSIZE 8 int dvd_read_copyright(struct cd_softc *sc, union dvd_struct *s) { struct scsi_generic *cmd; struct scsi_xfer *xs; u_int8_t *buf; int error; buf = dma_alloc(DVD_READ_COPYRIGHT_BUFSIZE, PR_WAITOK | PR_ZERO); if (buf == NULL) return ENOMEM; xs = scsi_xs_get(sc->sc_link, SCSI_DATA_IN); if (xs == NULL) { error = ENOMEM; goto done; } xs->cmdlen = sizeof(*cmd); xs->data = buf; xs->datalen = DVD_READ_COPYRIGHT_BUFSIZE; xs->timeout = 30000; cmd = &xs->cmd; cmd->opcode = GPCMD_READ_DVD_STRUCTURE; cmd->bytes[6] = s->type; _lto2b(xs->datalen, &cmd->bytes[7]); cmd->bytes[5] = s->copyright.layer_num; error = scsi_xs_sync(xs); scsi_xs_put(xs); if (error == 0) { s->copyright.cpst = buf[4]; s->copyright.rmi = buf[5]; } done: dma_free(buf, DVD_READ_COPYRIGHT_BUFSIZE); return error; } int dvd_read_disckey(struct cd_softc *sc, union dvd_struct *s) { struct scsi_read_dvd_structure_data *buf; struct scsi_read_dvd_structure *cmd; struct scsi_xfer *xs; int error; buf = dma_alloc(sizeof(*buf), PR_WAITOK | PR_ZERO); if (buf == NULL) return ENOMEM; xs = scsi_xs_get(sc->sc_link, SCSI_DATA_IN); if (xs == NULL) { error = ENOMEM; goto done; } xs->cmdlen = sizeof(*cmd); xs->data = (void *)buf; xs->datalen = sizeof(*buf); xs->timeout = 30000; cmd = (struct scsi_read_dvd_structure *)&xs->cmd; cmd->opcode = GPCMD_READ_DVD_STRUCTURE; cmd->format = s->type; cmd->agid = s->disckey.agid << 6; _lto2b(xs->datalen, cmd->length); error = scsi_xs_sync(xs); scsi_xs_put(xs); if (error == 0) memcpy(s->disckey.value, buf->data, sizeof(s->disckey.value)); done: dma_free(buf, sizeof(*buf)); return error; } #define DVD_READ_BCA_BUFLEN (4 + 188) int dvd_read_bca(struct cd_softc *sc, union dvd_struct *s) { struct scsi_generic *cmd; struct scsi_xfer *xs; u_int8_t *buf; int error; buf = dma_alloc(DVD_READ_BCA_BUFLEN, PR_WAITOK | PR_ZERO); if (buf == NULL) return ENOMEM; xs = scsi_xs_get(sc->sc_link, SCSI_DATA_IN); if (xs == NULL) { error = ENOMEM; goto done; } xs->cmdlen = sizeof(*cmd); xs->data = buf; xs->datalen = DVD_READ_BCA_BUFLEN; xs->timeout = 30000; cmd = &xs->cmd; cmd->opcode = GPCMD_READ_DVD_STRUCTURE; cmd->bytes[6] = s->type; _lto2b(xs->datalen, &cmd->bytes[7]); error = scsi_xs_sync(xs); scsi_xs_put(xs); if (error == 0) { s->bca.len = _2btol(&buf[0]); if (s->bca.len < 12 || s->bca.len > 188) return EIO; memcpy(s->bca.value, &buf[4], s->bca.len); } done: dma_free(buf, DVD_READ_BCA_BUFLEN); return error; } int dvd_read_manufact(struct cd_softc *sc, union dvd_struct *s) { struct scsi_read_dvd_structure_data *buf; struct scsi_read_dvd_structure *cmd; struct scsi_xfer *xs; int error; buf = dma_alloc(sizeof(*buf), PR_WAITOK | PR_ZERO); if (buf == NULL) return ENOMEM; xs = scsi_xs_get(sc->sc_link, SCSI_DATA_IN); if (xs == NULL) { error = ENOMEM; goto done; } xs->cmdlen = sizeof(*cmd); xs->data = (void *)buf; xs->datalen = sizeof(*buf); xs->timeout = 30000; cmd = (struct scsi_read_dvd_structure *)&xs->cmd; cmd->opcode = GPCMD_READ_DVD_STRUCTURE; cmd->format = s->type; _lto2b(xs->datalen, cmd->length); error = scsi_xs_sync(xs); scsi_xs_put(xs); if (error == 0) { s->manufact.len = _2btol(buf->len); if (s->manufact.len >= 0 && s->manufact.len <= 2048) memcpy(s->manufact.value, buf->data, s->manufact.len); else error = EIO; } done: dma_free(buf, sizeof(*buf)); return error; } int dvd_read_struct(struct cd_softc *sc, union dvd_struct *s) { switch (s->type) { case DVD_STRUCT_PHYSICAL: return dvd_read_physical(sc, s); case DVD_STRUCT_COPYRIGHT: return dvd_read_copyright(sc, s); case DVD_STRUCT_DISCKEY: return dvd_read_disckey(sc, s); case DVD_STRUCT_BCA: return dvd_read_bca(sc, s); case DVD_STRUCT_MANUFACT: return dvd_read_manufact(sc, s); default: return EINVAL; } } int cd_interpret_sense(struct scsi_xfer *xs) { struct scsi_sense_data *sense = &xs->sense; struct scsi_link *link = xs->sc_link; u_int8_t skey = sense->flags & SSD_KEY; u_int8_t serr = sense->error_code & SSD_ERRCODE; if (!ISSET(link->flags, SDEV_OPEN) || (serr != SSD_ERRCODE_CURRENT && serr != SSD_ERRCODE_DEFERRED)) return scsi_interpret_sense(xs); /* * We do custom processing in cd for the unit becoming ready * case. We do not allow xs->retries to be decremented on the * "Unit Becoming Ready" case. This is because CD drives * report "Unit Becoming Ready" when loading media and can * take a long time. Rather than having a massive timeout for * all operations (which would cause other problems), we allow * operations to wait (but be interruptible with Ctrl-C) * forever as long as the drive is reporting that it is * becoming ready. All other cases of not being ready are * handled by the default handler. */ switch(skey) { case SKEY_NOT_READY: if (ISSET(xs->flags, SCSI_IGNORE_NOT_READY)) return 0; if (ASC_ASCQ(sense) == SENSE_NOT_READY_BECOMING_READY) { SC_DEBUG(link, SDEV_DB1, ("not ready: busy (%#x)\n", sense->add_sense_code_qual)); /* don't count this as a retry */ xs->retries++; return scsi_delay(xs, 1); } break; /* XXX more to come here for a few other cases */ default: break; } return scsi_interpret_sense(xs); } /* * Find out from the device what its capacity is. */ u_int64_t cd_size(struct scsi_link *link, int flags, u_int32_t *blksize) { struct scsi_read_cap_data_16 *rdcap16; struct scsi_read_cap_data *rdcap; u_int64_t max_addr; int error; if (blksize != NULL) *blksize = 0; CLR(flags, SCSI_IGNORE_ILLEGAL_REQUEST); /* * Start with a READ CAPACITY(10). */ rdcap = dma_alloc(sizeof(*rdcap), ((flags & SCSI_NOSLEEP) ? PR_NOWAIT : PR_WAITOK) | PR_ZERO); if (rdcap == NULL) return 0; error = scsi_read_cap_10(link, rdcap, flags); if (error) { dma_free(rdcap, sizeof(*rdcap)); return 0; } max_addr = _4btol(rdcap->addr); if (blksize != NULL) *blksize = _4btol(rdcap->length); dma_free(rdcap, sizeof(*rdcap)); /* * pre-SPC (i.e. pre-SCSI-3) devices reporting less than 2^32-1 sectors * can stop here. */ if (SID_ANSII_REV(&link->inqdata) < SCSI_REV_SPC && max_addr != 0xffffffff) goto exit; rdcap16 = dma_alloc(sizeof(*rdcap16), ((flags & SCSI_NOSLEEP) ? PR_NOWAIT : PR_WAITOK) | PR_ZERO); if (rdcap16 == NULL) goto exit; error = scsi_read_cap_16(link, rdcap16, flags); if (error) { dma_free(rdcap16, sizeof(*rdcap16)); goto exit; } max_addr = _8btol(rdcap16->addr); if (blksize != NULL) *blksize = _4btol(rdcap16->length); /* XXX The other READ CAPACITY(16) info could be stored away. */ dma_free(rdcap16, sizeof(*rdcap16)); return max_addr + 1; exit: /* Return READ CAPACITY 10 values. */ if (max_addr != 0xffffffff) return max_addr + 1; else if (blksize != NULL) *blksize = 0; return 0; } #if defined(__macppc__) int cd_eject(void) { struct cd_softc *sc; int error = 0; if (cd_cd.cd_ndevs == 0 || (sc = cd_cd.cd_devs[0]) == NULL) return ENXIO; if ((error = disk_lock(&sc->sc_dk)) != 0) return error; if (sc->sc_dk.dk_openmask == 0) { SET(sc->sc_link->flags, SDEV_EJECTING); scsi_prevent(sc->sc_link, PR_ALLOW, SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY | SCSI_SILENT | SCSI_IGNORE_MEDIA_CHANGE); CLR(sc->sc_link->flags, SDEV_MEDIA_LOADED); scsi_start(sc->sc_link, SSS_STOP|SSS_LOEJ, 0); CLR(sc->sc_link->flags, SDEV_EJECTING); } disk_unlock(&sc->sc_dk); return error; } #endif /* __macppc__ */
78 8 8 26 389 16 13 376 389 2 32 168 9 5 4 9 236 177 144 118 118 109 8 8 2 6 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 /* $OpenBSD: kern_timeout.c,v 1.97 2024/02/23 16:51:39 cheloha Exp $ */ /* * Copyright (c) 2001 Thomas Nordin <nordin@openbsd.org> * Copyright (c) 2000-2001 Artur Grabowski <art@openbsd.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/kthread.h> #include <sys/proc.h> #include <sys/timeout.h> #include <sys/mutex.h> #include <sys/kernel.h> #include <sys/queue.h> /* _Q_INVALIDATE */ #include <sys/sysctl.h> #include <sys/witness.h> #ifdef DDB #include <machine/db_machdep.h> #include <ddb/db_interface.h> #include <ddb/db_sym.h> #include <ddb/db_output.h> #endif #include "kcov.h" #if NKCOV > 0 #include <sys/kcov.h> #endif /* * Locks used to protect global variables in this file: * * I immutable after initialization * T timeout_mutex */ struct mutex timeout_mutex = MUTEX_INITIALIZER(IPL_HIGH); void *softclock_si; /* [I] softclock() interrupt handle */ struct timeoutstat tostat; /* [T] statistics and totals */ /* * Timeouts are kept in a hierarchical timing wheel. The to_time is the value * of the global variable "ticks" when the timeout should be called. There are * four levels with 256 buckets each. */ #define WHEELCOUNT 4 #define WHEELSIZE 256 #define WHEELMASK 255 #define WHEELBITS 8 #define BUCKETS (WHEELCOUNT * WHEELSIZE) struct circq timeout_wheel[BUCKETS]; /* [T] Tick-based timeouts */ struct circq timeout_wheel_kc[BUCKETS]; /* [T] Clock-based timeouts */ struct circq timeout_new; /* [T] New, unscheduled timeouts */ struct circq timeout_todo; /* [T] Due or needs rescheduling */ struct circq timeout_proc; /* [T] Due + needs process context */ #ifdef MULTIPROCESSOR struct circq timeout_proc_mp; /* [T] Process ctx + no kernel lock */ #endif time_t timeout_level_width[WHEELCOUNT]; /* [I] Wheel level width (seconds) */ struct timespec tick_ts; /* [I] Length of a tick (1/hz secs) */ struct kclock { struct timespec kc_lastscan; /* [T] Clock time at last wheel scan */ struct timespec kc_late; /* [T] Late if due prior */ struct timespec kc_offset; /* [T] Offset from primary kclock */ } timeout_kclock[KCLOCK_MAX]; #define MASKWHEEL(wheel, time) (((time) >> ((wheel)*WHEELBITS)) & WHEELMASK) #define BUCKET(rel, abs) \ (timeout_wheel[ \ ((rel) <= (1 << (2*WHEELBITS))) \ ? ((rel) <= (1 << WHEELBITS)) \ ? MASKWHEEL(0, (abs)) \ : MASKWHEEL(1, (abs)) + WHEELSIZE \ : ((rel) <= (1 << (3*WHEELBITS))) \ ? MASKWHEEL(2, (abs)) + 2*WHEELSIZE \ : MASKWHEEL(3, (abs)) + 3*WHEELSIZE]) #define MOVEBUCKET(wheel, time) \ CIRCQ_CONCAT(&timeout_todo, \ &timeout_wheel[MASKWHEEL((wheel), (time)) + (wheel)*WHEELSIZE]) /* * Circular queue definitions. */ #define CIRCQ_INIT(elem) do { \ (elem)->next = (elem); \ (elem)->prev = (elem); \ } while (0) #define CIRCQ_INSERT_TAIL(list, elem) do { \ (elem)->prev = (list)->prev; \ (elem)->next = (list); \ (list)->prev->next = (elem); \ (list)->prev = (elem); \ tostat.tos_pending++; \ } while (0) #define CIRCQ_CONCAT(fst, snd) do { \ if (!CIRCQ_EMPTY(snd)) { \ (fst)->prev->next = (snd)->next;\ (snd)->next->prev = (fst)->prev;\ (snd)->prev->next = (fst); \ (fst)->prev = (snd)->prev; \ CIRCQ_INIT(snd); \ } \ } while (0) #define CIRCQ_REMOVE(elem) do { \ (elem)->next->prev = (elem)->prev; \ (elem)->prev->next = (elem)->next; \ _Q_INVALIDATE((elem)->prev); \ _Q_INVALIDATE((elem)->next); \ tostat.tos_pending--; \ } while (0) #define CIRCQ_FIRST(elem) ((elem)->next) #define CIRCQ_EMPTY(elem) (CIRCQ_FIRST(elem) == (elem)) #define CIRCQ_FOREACH(elem, list) \ for ((elem) = CIRCQ_FIRST(list); \ (elem) != (list); \ (elem) = CIRCQ_FIRST(elem)) #ifdef WITNESS struct lock_object timeout_sleeplock_obj = { .lo_name = "timeout", .lo_flags = LO_WITNESS | LO_INITIALIZED | LO_SLEEPABLE | (LO_CLASS_RWLOCK << LO_CLASSSHIFT) }; struct lock_object timeout_spinlock_obj = { .lo_name = "timeout", .lo_flags = LO_WITNESS | LO_INITIALIZED | (LO_CLASS_MUTEX << LO_CLASSSHIFT) }; struct lock_type timeout_sleeplock_type = { .lt_name = "timeout" }; struct lock_type timeout_spinlock_type = { .lt_name = "timeout" }; #define TIMEOUT_LOCK_OBJ(needsproc) \ ((needsproc) ? &timeout_sleeplock_obj : &timeout_spinlock_obj) #endif void softclock(void *); void softclock_create_thread(void *); void softclock_process_kclock_timeout(struct timeout *, int); void softclock_process_tick_timeout(struct timeout *, int); void softclock_thread(void *); #ifdef MULTIPROCESSOR void softclock_thread_mp(void *); #endif void timeout_barrier_timeout(void *); uint32_t timeout_bucket(const struct timeout *); uint32_t timeout_maskwheel(uint32_t, const struct timespec *); void timeout_run(struct timeout *); /* * The first thing in a struct timeout is its struct circq, so we * can get back from a pointer to the latter to a pointer to the * whole timeout with just a cast. */ static inline struct timeout * timeout_from_circq(struct circq *p) { return ((struct timeout *)(p)); } static inline void timeout_sync_order(int needsproc) { WITNESS_CHECKORDER(TIMEOUT_LOCK_OBJ(needsproc), LOP_NEWORDER, NULL); } static inline void timeout_sync_enter(int needsproc) { timeout_sync_order(needsproc); WITNESS_LOCK(TIMEOUT_LOCK_OBJ(needsproc), 0); } static inline void timeout_sync_leave(int needsproc) { WITNESS_UNLOCK(TIMEOUT_LOCK_OBJ(needsproc), 0); } /* * Some of the "math" in here is a bit tricky. * * We have to beware of wrapping ints. * We use the fact that any element added to the queue must be added with a * positive time. That means that any element `to' on the queue cannot be * scheduled to timeout further in time than INT_MAX, but to->to_time can * be positive or negative so comparing it with anything is dangerous. * The only way we can use the to->to_time value in any predictable way * is when we calculate how far in the future `to' will timeout - * "to->to_time - ticks". The result will always be positive for future * timeouts and 0 or negative for due timeouts. */ void timeout_startup(void) { int b, level; CIRCQ_INIT(&timeout_new); CIRCQ_INIT(&timeout_todo); CIRCQ_INIT(&timeout_proc); #ifdef MULTIPROCESSOR CIRCQ_INIT(&timeout_proc_mp); #endif for (b = 0; b < nitems(timeout_wheel); b++) CIRCQ_INIT(&timeout_wheel[b]); for (b = 0; b < nitems(timeout_wheel_kc); b++) CIRCQ_INIT(&timeout_wheel_kc[b]); for (level = 0; level < nitems(timeout_level_width); level++) timeout_level_width[level] = 2 << (level * WHEELBITS); NSEC_TO_TIMESPEC(tick_nsec, &tick_ts); } void timeout_proc_init(void) { softclock_si = softintr_establish(IPL_SOFTCLOCK, softclock, NULL); if (softclock_si == NULL) panic("%s: unable to register softclock interrupt", __func__); WITNESS_INIT(&timeout_sleeplock_obj, &timeout_sleeplock_type); WITNESS_INIT(&timeout_spinlock_obj, &timeout_spinlock_type); kthread_create_deferred(softclock_create_thread, NULL); } void timeout_set(struct timeout *new, void (*fn)(void *), void *arg) { timeout_set_flags(new, fn, arg, KCLOCK_NONE, 0); } void timeout_set_flags(struct timeout *to, void (*fn)(void *), void *arg, int kclock, int flags) { KASSERT(!ISSET(flags, ~(TIMEOUT_PROC | TIMEOUT_MPSAFE))); KASSERT(kclock >= KCLOCK_NONE && kclock < KCLOCK_MAX); to->to_func = fn; to->to_arg = arg; to->to_kclock = kclock; to->to_flags = flags | TIMEOUT_INITIALIZED; /* For now, only process context timeouts may be marked MP-safe. */ if (ISSET(to->to_flags, TIMEOUT_MPSAFE)) KASSERT(ISSET(to->to_flags, TIMEOUT_PROC)); } void timeout_set_proc(struct timeout *new, void (*fn)(void *), void *arg) { timeout_set_flags(new, fn, arg, KCLOCK_NONE, TIMEOUT_PROC); } int timeout_add(struct timeout *new, int to_ticks) { int old_time; int ret = 1; KASSERT(ISSET(new->to_flags, TIMEOUT_INITIALIZED)); KASSERT(new->to_kclock == KCLOCK_NONE); KASSERT(to_ticks >= 0); mtx_enter(&timeout_mutex); /* Initialize the time here, it won't change. */ old_time = new->to_time; new->to_time = to_ticks + ticks; CLR(new->to_flags, TIMEOUT_TRIGGERED); /* * If this timeout already is scheduled and now is moved * earlier, reschedule it now. Otherwise leave it in place * and let it be rescheduled later. */ if (ISSET(new->to_flags, TIMEOUT_ONQUEUE)) { if (new->to_time - ticks < old_time - ticks) { CIRCQ_REMOVE(&new->to_list); CIRCQ_INSERT_TAIL(&timeout_new, &new->to_list); } tostat.tos_readded++; ret = 0; } else { SET(new->to_flags, TIMEOUT_ONQUEUE); CIRCQ_INSERT_TAIL(&timeout_new, &new->to_list); } #if NKCOV > 0 if (!kcov_cold) new->to_process = curproc->p_p; #endif tostat.tos_added++; mtx_leave(&timeout_mutex); return ret; } int timeout_add_tv(struct timeout *to, const struct timeval *tv) { uint64_t to_ticks; to_ticks = (uint64_t)hz * tv->tv_sec + tv->tv_usec / tick; if (to_ticks > INT_MAX) to_ticks = INT_MAX; if (to_ticks == 0 && tv->tv_usec > 0) to_ticks = 1; return timeout_add(to, (int)to_ticks); } int timeout_add_sec(struct timeout *to, int secs) { uint64_t to_ticks; to_ticks = (uint64_t)hz * secs; if (to_ticks > INT_MAX) to_ticks = INT_MAX; if (to_ticks == 0) to_ticks = 1; return timeout_add(to, (int)to_ticks); } int timeout_add_msec(struct timeout *to, int msecs) { uint64_t to_ticks; to_ticks = (uint64_t)msecs * 1000 / tick; if (to_ticks > INT_MAX) to_ticks = INT_MAX; if (to_ticks == 0 && msecs > 0) to_ticks = 1; return timeout_add(to, (int)to_ticks); } int timeout_add_usec(struct timeout *to, int usecs) { int to_ticks = usecs / tick; if (to_ticks == 0 && usecs > 0) to_ticks = 1; return timeout_add(to, to_ticks); } int timeout_add_nsec(struct timeout *to, int nsecs) { int to_ticks = nsecs / (tick * 1000); if (to_ticks == 0 && nsecs > 0) to_ticks = 1; return timeout_add(to, to_ticks); } int timeout_abs_ts(struct timeout *to, const struct timespec *abstime) { struct timespec old_abstime; int ret = 1; mtx_enter(&timeout_mutex); KASSERT(ISSET(to->to_flags, TIMEOUT_INITIALIZED)); KASSERT(to->to_kclock == KCLOCK_UPTIME); old_abstime = to->to_abstime; to->to_abstime = *abstime; CLR(to->to_flags, TIMEOUT_TRIGGERED); if (ISSET(to->to_flags, TIMEOUT_ONQUEUE)) { if (timespeccmp(abstime, &old_abstime, <)) { CIRCQ_REMOVE(&to->to_list); CIRCQ_INSERT_TAIL(&timeout_new, &to->to_list); } tostat.tos_readded++; ret = 0; } else { SET(to->to_flags, TIMEOUT_ONQUEUE); CIRCQ_INSERT_TAIL(&timeout_new, &to->to_list); } #if NKCOV > 0 if (!kcov_cold) to->to_process = curproc->p_p; #endif tostat.tos_added++; mtx_leave(&timeout_mutex); return ret; } int timeout_del(struct timeout *to) { int ret = 0; mtx_enter(&timeout_mutex); if (ISSET(to->to_flags, TIMEOUT_ONQUEUE)) { CIRCQ_REMOVE(&to->to_list); CLR(to->to_flags, TIMEOUT_ONQUEUE); tostat.tos_cancelled++; ret = 1; } CLR(to->to_flags, TIMEOUT_TRIGGERED); tostat.tos_deleted++; mtx_leave(&timeout_mutex); return ret; } int timeout_del_barrier(struct timeout *to) { int removed; timeout_sync_order(ISSET(to->to_flags, TIMEOUT_PROC)); removed = timeout_del(to); if (!removed) timeout_barrier(to); return removed; } void timeout_barrier(struct timeout *to) { struct timeout barrier; struct cond c; int flags; flags = to->to_flags & (TIMEOUT_PROC | TIMEOUT_MPSAFE); timeout_sync_order(ISSET(flags, TIMEOUT_PROC)); timeout_set_flags(&barrier, timeout_barrier_timeout, &c, KCLOCK_NONE, flags); barrier.to_process = curproc->p_p; cond_init(&c); mtx_enter(&timeout_mutex); barrier.to_time = ticks; SET(barrier.to_flags, TIMEOUT_ONQUEUE); if (ISSET(flags, TIMEOUT_PROC)) { #ifdef MULTIPROCESSOR if (ISSET(flags, TIMEOUT_MPSAFE)) CIRCQ_INSERT_TAIL(&timeout_proc_mp, &barrier.to_list); else #endif CIRCQ_INSERT_TAIL(&timeout_proc, &barrier.to_list); } else CIRCQ_INSERT_TAIL(&timeout_todo, &barrier.to_list); mtx_leave(&timeout_mutex); if (ISSET(flags, TIMEOUT_PROC)) { #ifdef MULTIPROCESSOR if (ISSET(flags, TIMEOUT_MPSAFE)) wakeup_one(&timeout_proc_mp); else #endif wakeup_one(&timeout_proc); } else softintr_schedule(softclock_si); cond_wait(&c, "tmobar"); } void timeout_barrier_timeout(void *arg) { struct cond *c = arg; cond_signal(c); } uint32_t timeout_bucket(const struct timeout *to) { struct timespec diff, shifted_abstime; struct kclock *kc; uint32_t level; KASSERT(to->to_kclock == KCLOCK_UPTIME); kc = &timeout_kclock[to->to_kclock]; KASSERT(timespeccmp(&kc->kc_lastscan, &to->to_abstime, <)); timespecsub(&to->to_abstime, &kc->kc_lastscan, &diff); for (level = 0; level < nitems(timeout_level_width) - 1; level++) { if (diff.tv_sec < timeout_level_width[level]) break; } timespecadd(&to->to_abstime, &kc->kc_offset, &shifted_abstime); return level * WHEELSIZE + timeout_maskwheel(level, &shifted_abstime); } /* * Hash the absolute time into a bucket on a given level of the wheel. * * The complete hash is 32 bits. The upper 25 bits are seconds, the * lower 7 bits are nanoseconds. tv_nsec is a positive value less * than one billion so we need to divide it to isolate the desired * bits. We can't just shift it. * * The level is used to isolate an 8-bit portion of the hash. The * resulting number indicates which bucket the absolute time belongs * in on the given level of the wheel. */ uint32_t timeout_maskwheel(uint32_t level, const struct timespec *abstime) { uint32_t hi, lo; hi = abstime->tv_sec << 7; lo = abstime->tv_nsec / 7812500; return ((hi | lo) >> (level * WHEELBITS)) & WHEELMASK; } /* * This is called from hardclock() on the primary CPU at the start of * every tick. */ void timeout_hardclock_update(void) { struct timespec elapsed, now; struct kclock *kc; struct timespec *lastscan = &timeout_kclock[KCLOCK_UPTIME].kc_lastscan; int b, done, first, i, last, level, need_softclock = 1, off; mtx_enter(&timeout_mutex); MOVEBUCKET(0, ticks); if (MASKWHEEL(0, ticks) == 0) { MOVEBUCKET(1, ticks); if (MASKWHEEL(1, ticks) == 0) { MOVEBUCKET(2, ticks); if (MASKWHEEL(2, ticks) == 0) MOVEBUCKET(3, ticks); } } /* * Dump the buckets that expired while we were away. * * If the elapsed time has exceeded a level's limit then we need * to dump every bucket in the level. We have necessarily completed * a lap of that level, too, so we need to process buckets in the * next level. * * Otherwise we need to compare indices: if the index of the first * expired bucket is greater than that of the last then we have * completed a lap of the level and need to process buckets in the * next level. */ nanouptime(&now); timespecsub(&now, lastscan, &elapsed); for (level = 0; level < nitems(timeout_level_width); level++) { first = timeout_maskwheel(level, lastscan); if (elapsed.tv_sec >= timeout_level_width[level]) { last = (first == 0) ? WHEELSIZE - 1 : first - 1; done = 0; } else { last = timeout_maskwheel(level, &now); done = first <= last; } off = level * WHEELSIZE; for (b = first;; b = (b + 1) % WHEELSIZE) { CIRCQ_CONCAT(&timeout_todo, &timeout_wheel_kc[off + b]); if (b == last) break; } if (done) break; } /* * Update the cached state for each kclock. */ for (i = 0; i < nitems(timeout_kclock); i++) { kc = &timeout_kclock[i]; timespecadd(&now, &kc->kc_offset, &kc->kc_lastscan); timespecsub(&kc->kc_lastscan, &tick_ts, &kc->kc_late); } if (CIRCQ_EMPTY(&timeout_new) && CIRCQ_EMPTY(&timeout_todo)) need_softclock = 0; mtx_leave(&timeout_mutex); if (need_softclock) softintr_schedule(softclock_si); } void timeout_run(struct timeout *to) { void (*fn)(void *); void *arg; int needsproc; MUTEX_ASSERT_LOCKED(&timeout_mutex); CLR(to->to_flags, TIMEOUT_ONQUEUE); SET(to->to_flags, TIMEOUT_TRIGGERED); fn = to->to_func; arg = to->to_arg; needsproc = ISSET(to->to_flags, TIMEOUT_PROC); #if NKCOV > 0 struct process *kcov_process = to->to_process; #endif mtx_leave(&timeout_mutex); timeout_sync_enter(needsproc); #if NKCOV > 0 kcov_remote_enter(KCOV_REMOTE_COMMON, kcov_process); #endif fn(arg); #if NKCOV > 0 kcov_remote_leave(KCOV_REMOTE_COMMON, kcov_process); #endif timeout_sync_leave(needsproc); mtx_enter(&timeout_mutex); } void softclock_process_kclock_timeout(struct timeout *to, int new) { struct kclock *kc = &timeout_kclock[to->to_kclock]; if (timespeccmp(&to->to_abstime, &kc->kc_lastscan, >)) { tostat.tos_scheduled++; if (!new) tostat.tos_rescheduled++; CIRCQ_INSERT_TAIL(&timeout_wheel_kc[timeout_bucket(to)], &to->to_list); return; } if (!new && timespeccmp(&to->to_abstime, &kc->kc_late, <=)) tostat.tos_late++; if (ISSET(to->to_flags, TIMEOUT_PROC)) { #ifdef MULTIPROCESSOR if (ISSET(to->to_flags, TIMEOUT_MPSAFE)) CIRCQ_INSERT_TAIL(&timeout_proc_mp, &to->to_list); else #endif CIRCQ_INSERT_TAIL(&timeout_proc, &to->to_list); return; } timeout_run(to); tostat.tos_run_softclock++; } void softclock_process_tick_timeout(struct timeout *to, int new) { int delta = to->to_time - ticks; if (delta > 0) { tostat.tos_scheduled++; if (!new) tostat.tos_rescheduled++; CIRCQ_INSERT_TAIL(&BUCKET(delta, to->to_time), &to->to_list); return; } if (!new && delta < 0) tostat.tos_late++; if (ISSET(to->to_flags, TIMEOUT_PROC)) { #ifdef MULTIPROCESSOR if (ISSET(to->to_flags, TIMEOUT_MPSAFE)) CIRCQ_INSERT_TAIL(&timeout_proc_mp, &to->to_list); else #endif CIRCQ_INSERT_TAIL(&timeout_proc, &to->to_list); return; } timeout_run(to); tostat.tos_run_softclock++; } /* * Timeouts are processed here instead of timeout_hardclock_update() * to avoid doing any more work at IPL_CLOCK than absolutely necessary. * Down here at IPL_SOFTCLOCK other interrupts can be serviced promptly * so the system remains responsive even if there is a surge of timeouts. */ void softclock(void *arg) { struct timeout *first_new, *to; int needsproc, new; #ifdef MULTIPROCESSOR int need_proc_mp; #endif first_new = NULL; new = 0; mtx_enter(&timeout_mutex); if (!CIRCQ_EMPTY(&timeout_new)) first_new = timeout_from_circq(CIRCQ_FIRST(&timeout_new)); CIRCQ_CONCAT(&timeout_todo, &timeout_new); while (!CIRCQ_EMPTY(&timeout_todo)) { to = timeout_from_circq(CIRCQ_FIRST(&timeout_todo)); CIRCQ_REMOVE(&to->to_list); if (to == first_new) new = 1; if (to->to_kclock == KCLOCK_NONE) softclock_process_tick_timeout(to, new); else if (to->to_kclock == KCLOCK_UPTIME) softclock_process_kclock_timeout(to, new); else { panic("%s: invalid to_clock: %d", __func__, to->to_kclock); } } tostat.tos_softclocks++; needsproc = !CIRCQ_EMPTY(&timeout_proc); #ifdef MULTIPROCESSOR need_proc_mp = !CIRCQ_EMPTY(&timeout_proc_mp); #endif mtx_leave(&timeout_mutex); if (needsproc) wakeup(&timeout_proc); #ifdef MULTIPROCESSOR if (need_proc_mp) wakeup(&timeout_proc_mp); #endif } void softclock_create_thread(void *arg) { if (kthread_create(softclock_thread, NULL, NULL, "softclock")) panic("fork softclock"); #ifdef MULTIPROCESSOR if (kthread_create(softclock_thread_mp, NULL, NULL, "softclockmp")) panic("kthread_create softclock_thread_mp"); #endif } void softclock_thread(void *arg) { CPU_INFO_ITERATOR cii; struct cpu_info *ci; struct timeout *to; int s; KERNEL_ASSERT_LOCKED(); /* Be conservative for the moment */ CPU_INFO_FOREACH(cii, ci) { if (CPU_IS_PRIMARY(ci)) break; } KASSERT(ci != NULL); sched_peg_curproc(ci); s = splsoftclock(); mtx_enter(&timeout_mutex); for (;;) { while (!CIRCQ_EMPTY(&timeout_proc)) { to = timeout_from_circq(CIRCQ_FIRST(&timeout_proc)); CIRCQ_REMOVE(&to->to_list); timeout_run(to); tostat.tos_run_thread++; } tostat.tos_thread_wakeups++; msleep_nsec(&timeout_proc, &timeout_mutex, PSWP, "tmoslp", INFSLP); } splx(s); } #ifdef MULTIPROCESSOR void softclock_thread_mp(void *arg) { struct timeout *to; KERNEL_ASSERT_LOCKED(); KERNEL_UNLOCK(); mtx_enter(&timeout_mutex); for (;;) { while (!CIRCQ_EMPTY(&timeout_proc_mp)) { to = timeout_from_circq(CIRCQ_FIRST(&timeout_proc_mp)); CIRCQ_REMOVE(&to->to_list); timeout_run(to); tostat.tos_run_thread++; } tostat.tos_thread_wakeups++; msleep_nsec(&timeout_proc_mp, &timeout_mutex, PSWP, "tmoslp", INFSLP); } } #endif /* MULTIPROCESSOR */ #ifndef SMALL_KERNEL void timeout_adjust_ticks(int adj) { struct timeout *to; struct circq *p; int new_ticks, b; /* adjusting the monotonic clock backwards would be a Bad Thing */ if (adj <= 0) return; mtx_enter(&timeout_mutex); new_ticks = ticks + adj; for (b = 0; b < nitems(timeout_wheel); b++) { p = CIRCQ_FIRST(&timeout_wheel[b]); while (p != &timeout_wheel[b]) { to = timeout_from_circq(p); p = CIRCQ_FIRST(p); /* when moving a timeout forward need to reinsert it */ if (to->to_time - ticks < adj) to->to_time = new_ticks; CIRCQ_REMOVE(&to->to_list); CIRCQ_INSERT_TAIL(&timeout_todo, &to->to_list); } } ticks = new_ticks; mtx_leave(&timeout_mutex); } #endif int timeout_sysctl(void *oldp, size_t *oldlenp, void *newp, size_t newlen) { struct timeoutstat status; mtx_enter(&timeout_mutex); memcpy(&status, &tostat, sizeof(status)); mtx_leave(&timeout_mutex); return sysctl_rdstruct(oldp, oldlenp, newp, &status, sizeof(status)); } #ifdef DDB const char *db_kclock(int); void db_show_callout_bucket(struct circq *); void db_show_timeout(struct timeout *, struct circq *); const char *db_timespec(const struct timespec *); const char * db_kclock(int kclock) { switch (kclock) { case KCLOCK_UPTIME: return "uptime"; default: return "invalid"; } } const char * db_timespec(const struct timespec *ts) { static char buf[32]; struct timespec tmp, zero; if (ts->tv_sec >= 0) { snprintf(buf, sizeof(buf), "%lld.%09ld", ts->tv_sec, ts->tv_nsec); return buf; } timespecclear(&zero); timespecsub(&zero, ts, &tmp); snprintf(buf, sizeof(buf), "-%lld.%09ld", tmp.tv_sec, tmp.tv_nsec); return buf; } void db_show_callout_bucket(struct circq *bucket) { struct circq *p; CIRCQ_FOREACH(p, bucket) db_show_timeout(timeout_from_circq(p), bucket); } void db_show_timeout(struct timeout *to, struct circq *bucket) { struct timespec remaining; struct kclock *kc; char buf[8]; db_expr_t offset; struct circq *wheel; char *name, *where; int width = sizeof(long) * 2; db_find_sym_and_offset((vaddr_t)to->to_func, &name, &offset); name = name ? name : "?"; if (bucket == &timeout_new) where = "new"; else if (bucket == &timeout_todo) where = "softint"; else if (bucket == &timeout_proc) where = "thread"; #ifdef MULTIPROCESSOR else if (bucket == &timeout_proc_mp) where = "thread-mp"; #endif else { if (to->to_kclock == KCLOCK_UPTIME) wheel = timeout_wheel_kc; else if (to->to_kclock == KCLOCK_NONE) wheel = timeout_wheel; else goto invalid; snprintf(buf, sizeof(buf), "%3ld/%1ld", (bucket - wheel) % WHEELSIZE, (bucket - wheel) / WHEELSIZE); where = buf; } if (to->to_kclock == KCLOCK_UPTIME) { kc = &timeout_kclock[to->to_kclock]; timespecsub(&to->to_abstime, &kc->kc_lastscan, &remaining); db_printf("%20s %8s %9s 0x%0*lx %s\n", db_timespec(&remaining), db_kclock(to->to_kclock), where, width, (ulong)to->to_arg, name); } else if (to->to_kclock == KCLOCK_NONE) { db_printf("%20d %8s %9s 0x%0*lx %s\n", to->to_time - ticks, "ticks", where, width, (ulong)to->to_arg, name); } else goto invalid; return; invalid: db_printf("%s: timeout 0x%p: invalid to_kclock: %d", __func__, to, to->to_kclock); } void db_show_callout(db_expr_t addr, int haddr, db_expr_t count, char *modif) { struct kclock *kc; int width = sizeof(long) * 2 + 2; int b, i; db_printf("%20s %8s\n", "lastscan", "clock"); db_printf("%20d %8s\n", ticks, "ticks"); for (i = 0; i < nitems(timeout_kclock); i++) { kc = &timeout_kclock[i]; db_printf("%20s %8s\n", db_timespec(&kc->kc_lastscan), db_kclock(i)); } db_printf("\n"); db_printf("%20s %8s %9s %*s %s\n", "remaining", "clock", "wheel", width, "arg", "func"); db_show_callout_bucket(&timeout_new); db_show_callout_bucket(&timeout_todo); db_show_callout_bucket(&timeout_proc); #ifdef MULTIPROCESSOR db_show_callout_bucket(&timeout_proc_mp); #endif for (b = 0; b < nitems(timeout_wheel); b++) db_show_callout_bucket(&timeout_wheel[b]); for (b = 0; b < nitems(timeout_wheel_kc); b++) db_show_callout_bucket(&timeout_wheel_kc[b]); } #endif
18 1 3 2 14 5 9 12 2 2 2 78 1 74 1 1 1 17 59 75 71 5 1 40 1 36 3 12 7 18 24 13 9 5 19 5 5 10 30 28 2 24 14 38 9 22 19 4 21 1 30 30 1 1 3 23 30 1 28 1 28 1 27 17 17 1 16 43 43 1 17 9 10 2 2 18 18 1 1 1 16 17 17 1 16 14 1 14 1 38 17 23 27 4 19 30 17 2 6 2 3 7 22 21 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 /* $OpenBSD: uvm_mmap.c,v 1.191 2024/04/05 14:16:05 deraadt Exp $ */ /* $NetBSD: uvm_mmap.c,v 1.49 2001/02/18 21:19:08 chs Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. * Copyright (c) 1991, 1993 The Regents of the University of California. * Copyright (c) 1988 University of Utah. * * All rights reserved. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: Utah $Hdr: vm_mmap.c 1.6 91/10/21$ * @(#)vm_mmap.c 8.5 (Berkeley) 5/19/94 * from: Id: uvm_mmap.c,v 1.1.2.14 1998/01/05 21:04:26 chuck Exp */ /* * uvm_mmap.c: system call interface into VM system, plus kernel vm_mmap * function. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/fcntl.h> #include <sys/file.h> #include <sys/filedesc.h> #include <sys/resourcevar.h> #include <sys/mman.h> #include <sys/mount.h> #include <sys/proc.h> #include <sys/malloc.h> #include <sys/vnode.h> #include <sys/conf.h> #include <sys/signalvar.h> #include <sys/syslog.h> #include <sys/stat.h> #include <sys/specdev.h> #include <sys/stdint.h> #include <sys/pledge.h> #include <sys/unistd.h> /* for KBIND* */ #include <sys/user.h> #include <machine/exec.h> /* for __LDPGSZ */ #include <sys/syscall.h> #include <sys/syscallargs.h> #include <uvm/uvm.h> #include <uvm/uvm_device.h> #include <uvm/uvm_vnode.h> int uvm_mmapanon(vm_map_t, vaddr_t *, vsize_t, vm_prot_t, vm_prot_t, int, vsize_t, struct proc *); int uvm_mmapfile(vm_map_t, vaddr_t *, vsize_t, vm_prot_t, vm_prot_t, int, struct vnode *, voff_t, vsize_t, struct proc *); /* * Page align addr and size, returning EINVAL on wraparound. */ #define ALIGN_ADDR(addr, size, pageoff) do { \ pageoff = (addr & PAGE_MASK); \ if (pageoff != 0) { \ if (size > SIZE_MAX - pageoff) \ return EINVAL; /* wraparound */ \ addr -= pageoff; \ size += pageoff; \ } \ if (size != 0) { \ size = (vsize_t)round_page(size); \ if (size == 0) \ return EINVAL; /* wraparound */ \ } \ } while (0) /* * sys_mquery: provide mapping hints to applications that do fixed mappings * * flags: 0 or MAP_FIXED (MAP_FIXED - means that we insist on this addr and * don't care about PMAP_PREFER or such) * addr: hint where we'd like to place the mapping. * size: size of the mapping * fd: fd of the file we want to map * off: offset within the file */ int sys_mquery(struct proc *p, void *v, register_t *retval) { struct sys_mquery_args /* { syscallarg(void *) addr; syscallarg(size_t) len; syscallarg(int) prot; syscallarg(int) flags; syscallarg(int) fd; syscallarg(off_t) pos; } */ *uap = v; struct file *fp; voff_t uoff; int error; vaddr_t vaddr; int flags = 0; vsize_t size; vm_prot_t prot; int fd; vaddr = (vaddr_t) SCARG(uap, addr); prot = SCARG(uap, prot); size = (vsize_t) SCARG(uap, len); fd = SCARG(uap, fd); if ((prot & PROT_MASK) != prot) return EINVAL; if (SCARG(uap, flags) & MAP_FIXED) flags |= UVM_FLAG_FIXED; if (fd >= 0) { if ((error = getvnode(p, fd, &fp)) != 0) return error; uoff = SCARG(uap, pos); } else { fp = NULL; uoff = UVM_UNKNOWN_OFFSET; } if (vaddr == 0) vaddr = uvm_map_hint(p->p_vmspace, prot, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS); error = uvm_map_mquery(&p->p_vmspace->vm_map, &vaddr, size, uoff, flags); if (error == 0) *retval = (register_t)(vaddr); if (fp != NULL) FRELE(fp, p); return error; } int uvm_wxabort; /* * W^X violations are only allowed on permitted filesystems. */ static inline int uvm_wxcheck(struct proc *p, char *call) { struct process *pr = p->p_p; int wxallowed = (pr->ps_textvp->v_mount && (pr->ps_textvp->v_mount->mnt_flag & MNT_WXALLOWED)); if (wxallowed && (pr->ps_flags & PS_WXNEEDED)) return 0; if (uvm_wxabort) { KERNEL_LOCK(); /* Report W^X failures */ if (pr->ps_wxcounter++ == 0) log(LOG_NOTICE, "%s(%d): %s W^X violation\n", pr->ps_comm, pr->ps_pid, call); /* Send uncatchable SIGABRT for coredump */ sigexit(p, SIGABRT); KERNEL_UNLOCK(); } return ENOTSUP; } /* * sys_mmap: mmap system call. * * => file offset and address may not be page aligned * - if MAP_FIXED, offset and address must have remainder mod PAGE_SIZE * - if address isn't page aligned the mapping starts at trunc_page(addr) * and the return value is adjusted up by the page offset. */ int sys_mmap(struct proc *p, void *v, register_t *retval) { struct sys_mmap_args /* { syscallarg(void *) addr; syscallarg(size_t) len; syscallarg(int) prot; syscallarg(int) flags; syscallarg(int) fd; syscallarg(off_t) pos; } */ *uap = v; vaddr_t addr; struct vattr va; off_t pos; vsize_t limit, pageoff, size; vm_prot_t prot, maxprot; int flags, fd; vaddr_t vm_min_address = VM_MIN_ADDRESS; struct filedesc *fdp = p->p_fd; struct file *fp = NULL; struct vnode *vp; int error; /* first, extract syscall args from the uap. */ addr = (vaddr_t) SCARG(uap, addr); size = (vsize_t) SCARG(uap, len); prot = SCARG(uap, prot); flags = SCARG(uap, flags); fd = SCARG(uap, fd); pos = SCARG(uap, pos); /* * Validate the flags. */ if ((prot & PROT_MASK) != prot) return EINVAL; if ((prot & (PROT_WRITE | PROT_EXEC)) == (PROT_WRITE | PROT_EXEC) && (error = uvm_wxcheck(p, "mmap"))) return error; if ((flags & MAP_FLAGMASK) != flags) return EINVAL; if ((flags & (MAP_SHARED|MAP_PRIVATE)) == (MAP_SHARED|MAP_PRIVATE)) return EINVAL; if ((flags & (MAP_FIXED|__MAP_NOREPLACE)) == __MAP_NOREPLACE) return EINVAL; if (flags & MAP_STACK) { if ((flags & (MAP_ANON|MAP_PRIVATE)) != (MAP_ANON|MAP_PRIVATE)) return EINVAL; if (flags & ~(MAP_STACK|MAP_FIXED|MAP_ANON|MAP_PRIVATE)) return EINVAL; if (pos != 0) return EINVAL; if ((prot & (PROT_READ|PROT_WRITE)) != (PROT_READ|PROT_WRITE)) return EINVAL; } if (size == 0) return EINVAL; error = pledge_protexec(p, prot); if (error) return error; /* align file position and save offset. adjust size. */ ALIGN_ADDR(pos, size, pageoff); /* now check (MAP_FIXED) or get (!MAP_FIXED) the "addr" */ if (flags & MAP_FIXED) { /* adjust address by the same amount as we did the offset */ addr -= pageoff; if (addr & PAGE_MASK) return EINVAL; /* not page aligned */ if (addr > SIZE_MAX - size) return EINVAL; /* no wrapping! */ if (VM_MAXUSER_ADDRESS > 0 && (addr + size) > VM_MAXUSER_ADDRESS) return EINVAL; if (vm_min_address > 0 && addr < vm_min_address) return EINVAL; } /* check for file mappings (i.e. not anonymous) and verify file. */ if ((flags & MAP_ANON) == 0) { KERNEL_LOCK(); if ((fp = fd_getfile(fdp, fd)) == NULL) { error = EBADF; goto out; } if (fp->f_type != DTYPE_VNODE) { error = ENODEV; /* only mmap vnodes! */ goto out; } vp = (struct vnode *)fp->f_data; /* convert to vnode */ if (vp->v_type != VREG && vp->v_type != VCHR && vp->v_type != VBLK) { error = ENODEV; /* only REG/CHR/BLK support mmap */ goto out; } if (vp->v_type == VREG && (pos + size) < pos) { error = EINVAL; /* no offset wrapping */ goto out; } /* special case: catch SunOS style /dev/zero */ if (vp->v_type == VCHR && iszerodev(vp->v_rdev)) { flags |= MAP_ANON; FRELE(fp, p); fp = NULL; KERNEL_UNLOCK(); goto is_anon; } /* * Old programs may not select a specific sharing type, so * default to an appropriate one. */ if ((flags & (MAP_SHARED|MAP_PRIVATE)) == 0) { #if defined(DEBUG) printf("WARNING: defaulted mmap() share type to" " %s (pid %d comm %s)\n", vp->v_type == VCHR ? "MAP_SHARED" : "MAP_PRIVATE", p->p_p->ps_pid, p->p_p->ps_comm); #endif if (vp->v_type == VCHR) flags |= MAP_SHARED; /* for a device */ else flags |= MAP_PRIVATE; /* for a file */ } /* * MAP_PRIVATE device mappings don't make sense (and aren't * supported anyway). However, some programs rely on this, * so just change it to MAP_SHARED. */ if (vp->v_type == VCHR && (flags & MAP_PRIVATE) != 0) { flags = (flags & ~MAP_PRIVATE) | MAP_SHARED; } /* now check protection */ maxprot = PROT_EXEC; /* check read access */ if (fp->f_flag & FREAD) maxprot |= PROT_READ; else if (prot & PROT_READ) { error = EACCES; goto out; } /* check write access, shared case first */ if (flags & MAP_SHARED) { /* * if the file is writable, only add PROT_WRITE to * maxprot if the file is not immutable, append-only. * otherwise, if we have asked for PROT_WRITE, return * EPERM. */ if (fp->f_flag & FWRITE) { error = VOP_GETATTR(vp, &va, p->p_ucred, p); if (error) goto out; if ((va.va_flags & (IMMUTABLE|APPEND)) == 0) maxprot |= PROT_WRITE; else if (prot & PROT_WRITE) { error = EPERM; goto out; } } else if (prot & PROT_WRITE) { error = EACCES; goto out; } } else { /* MAP_PRIVATE mappings can always write to */ maxprot |= PROT_WRITE; } if ((flags & __MAP_NOFAULT) != 0 || ((flags & MAP_PRIVATE) != 0 && (prot & PROT_WRITE) != 0)) { limit = lim_cur(RLIMIT_DATA); if (limit < size || limit - size < ptoa(p->p_vmspace->vm_dused)) { error = ENOMEM; goto out; } } error = uvm_mmapfile(&p->p_vmspace->vm_map, &addr, size, prot, maxprot, flags, vp, pos, lim_cur(RLIMIT_MEMLOCK), p); FRELE(fp, p); KERNEL_UNLOCK(); } else { /* MAP_ANON case */ if (fd != -1) return EINVAL; is_anon: /* label for SunOS style /dev/zero */ /* __MAP_NOFAULT only makes sense with a backing object */ if ((flags & __MAP_NOFAULT) != 0) return EINVAL; if (prot != PROT_NONE || (flags & MAP_SHARED)) { limit = lim_cur(RLIMIT_DATA); if (limit < size || limit - size < ptoa(p->p_vmspace->vm_dused)) { return ENOMEM; } } /* * We've been treating (MAP_SHARED|MAP_PRIVATE) == 0 as * MAP_PRIVATE, so make that clear. */ if ((flags & MAP_SHARED) == 0) flags |= MAP_PRIVATE; maxprot = PROT_MASK; error = uvm_mmapanon(&p->p_vmspace->vm_map, &addr, size, prot, maxprot, flags, lim_cur(RLIMIT_MEMLOCK), p); } if (error == 0) /* remember to add offset */ *retval = (register_t)(addr + pageoff); return error; out: KERNEL_UNLOCK(); if (fp) FRELE(fp, p); return error; } /* * sys_msync: the msync system call (a front-end for flush) */ int sys_msync(struct proc *p, void *v, register_t *retval) { struct sys_msync_args /* { syscallarg(void *) addr; syscallarg(size_t) len; syscallarg(int) flags; } */ *uap = v; vaddr_t addr; vsize_t size, pageoff; int flags, uvmflags; /* extract syscall args from the uap */ addr = (vaddr_t)SCARG(uap, addr); size = (vsize_t)SCARG(uap, len); flags = SCARG(uap, flags); /* sanity check flags */ if ((flags & ~(MS_ASYNC | MS_SYNC | MS_INVALIDATE)) != 0 || (flags & (MS_ASYNC | MS_SYNC | MS_INVALIDATE)) == 0 || (flags & (MS_ASYNC | MS_SYNC)) == (MS_ASYNC | MS_SYNC)) return EINVAL; if ((flags & (MS_ASYNC | MS_SYNC)) == 0) flags |= MS_SYNC; /* align the address to a page boundary, and adjust the size accordingly */ ALIGN_ADDR(addr, size, pageoff); if (addr > SIZE_MAX - size) return EINVAL; /* disallow wrap-around. */ /* translate MS_ flags into PGO_ flags */ uvmflags = PGO_CLEANIT; if (flags & MS_INVALIDATE) uvmflags |= PGO_FREE; if (flags & MS_SYNC) uvmflags |= PGO_SYNCIO; else uvmflags |= PGO_SYNCIO; /* XXXCDC: force sync for now! */ return uvm_map_clean(&p->p_vmspace->vm_map, addr, addr+size, uvmflags); } /* * sys_munmap: unmap a users memory */ int sys_munmap(struct proc *p, void *v, register_t *retval) { struct sys_munmap_args /* { syscallarg(void *) addr; syscallarg(size_t) len; } */ *uap = v; vaddr_t addr; vsize_t size, pageoff; vm_map_t map; vaddr_t vm_min_address = VM_MIN_ADDRESS; struct uvm_map_deadq dead_entries; /* get syscall args... */ addr = (vaddr_t) SCARG(uap, addr); size = (vsize_t) SCARG(uap, len); /* align address to a page boundary, and adjust size accordingly */ ALIGN_ADDR(addr, size, pageoff); /* * Check for illegal addresses. Watch out for address wrap... * Note that VM_*_ADDRESS are not constants due to casts (argh). */ if (addr > SIZE_MAX - size) return EINVAL; if (VM_MAXUSER_ADDRESS > 0 && addr + size > VM_MAXUSER_ADDRESS) return EINVAL; if (vm_min_address > 0 && addr < vm_min_address) return EINVAL; map = &p->p_vmspace->vm_map; vm_map_lock(map); /* lock map so we can checkprot */ /* * interesting system call semantic: make sure entire range is * allocated before allowing an unmap. */ if (!uvm_map_checkprot(map, addr, addr + size, PROT_NONE)) { vm_map_unlock(map); return EINVAL; } TAILQ_INIT(&dead_entries); if (uvm_unmap_remove(map, addr, addr + size, &dead_entries, FALSE, TRUE, TRUE) != 0) { vm_map_unlock(map); return EPERM; /* immutable entries found */ } vm_map_unlock(map); /* and unlock */ uvm_unmap_detach(&dead_entries, 0); return 0; } /* * sys_mprotect: the mprotect system call */ int sys_mprotect(struct proc *p, void *v, register_t *retval) { struct sys_mprotect_args /* { syscallarg(void *) addr; syscallarg(size_t) len; syscallarg(int) prot; } */ *uap = v; vaddr_t addr; vsize_t size, pageoff; vm_prot_t prot; int error; /* * extract syscall args from uap */ addr = (vaddr_t)SCARG(uap, addr); size = (vsize_t)SCARG(uap, len); prot = SCARG(uap, prot); if ((prot & PROT_MASK) != prot) return EINVAL; if ((prot & (PROT_WRITE | PROT_EXEC)) == (PROT_WRITE | PROT_EXEC) && (error = uvm_wxcheck(p, "mprotect"))) return error; error = pledge_protexec(p, prot); if (error) return error; /* * align the address to a page boundary, and adjust the size accordingly */ ALIGN_ADDR(addr, size, pageoff); if (addr > SIZE_MAX - size) return EINVAL; /* disallow wrap-around. */ return (uvm_map_protect(&p->p_vmspace->vm_map, addr, addr+size, prot, 0, FALSE, TRUE)); } /* * sys_pinsyscalls. The caller is required to normalize base,len * to the minimum .text region, and adjust pintable offsets relative * to that base. */ int sys_pinsyscalls(struct proc *p, void *v, register_t *retval) { struct sys_pinsyscalls_args /* { syscallarg(void *) base; syscallarg(size_t) len; syscallarg(u_int *) pins; syscallarg(int) npins; } */ *uap = v; struct process *pr = p->p_p; struct vm_map *map = &p->p_vmspace->vm_map; int npins, error = 0, i; vaddr_t base; size_t len; u_int *pins; if (pr->ps_libcpin.pn_start || (pr->ps_vmspace->vm_map.flags & VM_MAP_PINSYSCALL_ONCE)) return (EPERM); base = (vaddr_t)SCARG(uap, base); len = (vsize_t)SCARG(uap, len); if (base > SIZE_MAX - len) return (EINVAL); /* disallow wrap-around. */ if (base < map->min_offset || base+len > map->max_offset) return (EINVAL); /* XXX MP unlock */ npins = SCARG(uap, npins); if (npins < 1 || npins > SYS_MAXSYSCALL) return (E2BIG); pins = malloc(npins * sizeof(u_int), M_PINSYSCALL, M_WAITOK|M_ZERO); if (pins == NULL) return (ENOMEM); error = copyin(SCARG(uap, pins), pins, npins * sizeof(u_int)); if (error) goto err; /* Range-check pintable offsets */ for (i = 0; i < npins; i++) { if (pins[i] == (u_int)-1 || pins[i] == 0) continue; if (pins[i] > SCARG(uap, len)) { error = ERANGE; break; } } if (error) { err: free(pins, M_PINSYSCALL, npins * sizeof(u_int)); return (error); } pr->ps_libcpin.pn_start = base; pr->ps_libcpin.pn_end = base + len; pr->ps_libcpin.pn_pins = pins; pr->ps_libcpin.pn_npins = npins; pr->ps_flags |= PS_LIBCPIN; #ifdef PMAP_CHECK_COPYIN /* Assume (and insist) on libc.so text being execute-only */ if (PMAP_CHECK_COPYIN) uvm_map_check_copyin_add(map, base, base+len); #endif return (0); } /* * sys_mimmutable: the mimmutable system call */ int sys_mimmutable(struct proc *p, void *v, register_t *retval) { struct sys_mimmutable_args /* { immutablearg(void *) addr; immutablearg(size_t) len; } */ *uap = v; vaddr_t addr; vsize_t size, pageoff; addr = (vaddr_t)SCARG(uap, addr); size = (vsize_t)SCARG(uap, len); /* * align the address to a page boundary, and adjust the size accordingly */ ALIGN_ADDR(addr, size, pageoff); if (addr > SIZE_MAX - size) return EINVAL; /* disallow wrap-around. */ return uvm_map_immutable(&p->p_vmspace->vm_map, addr, addr+size, 1); } /* * sys_minherit: the minherit system call */ int sys_minherit(struct proc *p, void *v, register_t *retval) { struct sys_minherit_args /* { syscallarg(void *) addr; syscallarg(size_t) len; syscallarg(int) inherit; } */ *uap = v; vaddr_t addr; vsize_t size, pageoff; vm_inherit_t inherit; addr = (vaddr_t)SCARG(uap, addr); size = (vsize_t)SCARG(uap, len); inherit = SCARG(uap, inherit); /* * align the address to a page boundary, and adjust the size accordingly */ ALIGN_ADDR(addr, size, pageoff); if (addr > SIZE_MAX - size) return EINVAL; /* disallow wrap-around. */ return (uvm_map_inherit(&p->p_vmspace->vm_map, addr, addr+size, inherit)); } /* * sys_madvise: give advice about memory usage. */ int sys_madvise(struct proc *p, void *v, register_t *retval) { struct sys_madvise_args /* { syscallarg(void *) addr; syscallarg(size_t) len; syscallarg(int) behav; } */ *uap = v; vaddr_t addr; vsize_t size, pageoff; int advice, error; addr = (vaddr_t)SCARG(uap, addr); size = (vsize_t)SCARG(uap, len); advice = SCARG(uap, behav); /* * align the address to a page boundary, and adjust the size accordingly */ ALIGN_ADDR(addr, size, pageoff); if (addr > SIZE_MAX - size) return EINVAL; /* disallow wrap-around. */ switch (advice) { case MADV_NORMAL: case MADV_RANDOM: case MADV_SEQUENTIAL: error = uvm_map_advice(&p->p_vmspace->vm_map, addr, addr + size, advice); break; case MADV_WILLNEED: /* * Activate all these pages, pre-faulting them in if * necessary. */ /* * XXX IMPLEMENT ME. * Should invent a "weak" mode for uvm_fault() * which would only do the PGO_LOCKED pgo_get(). */ return 0; case MADV_DONTNEED: /* * Deactivate all these pages. We don't need them * any more. We don't, however, toss the data in * the pages. */ error = uvm_map_clean(&p->p_vmspace->vm_map, addr, addr + size, PGO_DEACTIVATE); break; case MADV_FREE: /* * These pages contain no valid data, and may be * garbage-collected. Toss all resources, including * any swap space in use. */ error = uvm_map_clean(&p->p_vmspace->vm_map, addr, addr + size, PGO_FREE); break; case MADV_SPACEAVAIL: /* * XXXMRG What is this? I think it's: * * Ensure that we have allocated backing-store * for these pages. * * This is going to require changes to the page daemon, * as it will free swap space allocated to pages in core. * There's also what to do for device/file/anonymous memory. */ return EINVAL; default: return EINVAL; } return error; } /* * sys_mlock: memory lock */ int sys_mlock(struct proc *p, void *v, register_t *retval) { struct sys_mlock_args /* { syscallarg(const void *) addr; syscallarg(size_t) len; } */ *uap = v; vaddr_t addr; vsize_t size, pageoff; int error; /* extract syscall args from uap */ addr = (vaddr_t)SCARG(uap, addr); size = (vsize_t)SCARG(uap, len); /* align address to a page boundary and adjust size accordingly */ ALIGN_ADDR(addr, size, pageoff); if (addr > SIZE_MAX - size) return EINVAL; /* disallow wrap-around. */ if (atop(size) + uvmexp.wired > uvmexp.wiredmax) return EAGAIN; #ifdef pmap_wired_count if (size + ptoa(pmap_wired_count(vm_map_pmap(&p->p_vmspace->vm_map))) > lim_cur(RLIMIT_MEMLOCK)) return EAGAIN; #else if ((error = suser(p)) != 0) return error; #endif error = uvm_map_pageable(&p->p_vmspace->vm_map, addr, addr+size, FALSE, 0); return error == 0 ? 0 : ENOMEM; } /* * sys_munlock: unlock wired pages */ int sys_munlock(struct proc *p, void *v, register_t *retval) { struct sys_munlock_args /* { syscallarg(const void *) addr; syscallarg(size_t) len; } */ *uap = v; vaddr_t addr; vsize_t size, pageoff; int error; /* extract syscall args from uap */ addr = (vaddr_t)SCARG(uap, addr); size = (vsize_t)SCARG(uap, len); /* align address to a page boundary, and adjust size accordingly */ ALIGN_ADDR(addr, size, pageoff); if (addr > SIZE_MAX - size) return EINVAL; /* disallow wrap-around. */ #ifndef pmap_wired_count if ((error = suser(p)) != 0) return error; #endif error = uvm_map_pageable(&p->p_vmspace->vm_map, addr, addr+size, TRUE, 0); return error == 0 ? 0 : ENOMEM; } /* * sys_mlockall: lock all pages mapped into an address space. */ int sys_mlockall(struct proc *p, void *v, register_t *retval) { struct sys_mlockall_args /* { syscallarg(int) flags; } */ *uap = v; int error, flags; flags = SCARG(uap, flags); if (flags == 0 || (flags & ~(MCL_CURRENT|MCL_FUTURE)) != 0) return EINVAL; #ifndef pmap_wired_count if ((error = suser(p)) != 0) return error; #endif error = uvm_map_pageable_all(&p->p_vmspace->vm_map, flags, lim_cur(RLIMIT_MEMLOCK)); if (error != 0 && error != ENOMEM) return EAGAIN; return error; } /* * sys_munlockall: unlock all pages mapped into an address space. */ int sys_munlockall(struct proc *p, void *v, register_t *retval) { (void) uvm_map_pageable_all(&p->p_vmspace->vm_map, 0, 0); return 0; } /* * common code for mmapanon and mmapfile to lock a mmaping */ int uvm_mmaplock(vm_map_t map, vaddr_t *addr, vsize_t size, vm_prot_t prot, vsize_t locklimit) { int error; /* * POSIX 1003.1b -- if our address space was configured * to lock all future mappings, wire the one we just made. */ if (prot == PROT_NONE) { /* * No more work to do in this case. */ return 0; } vm_map_lock(map); if (map->flags & VM_MAP_WIREFUTURE) { KERNEL_LOCK(); if ((atop(size) + uvmexp.wired) > uvmexp.wiredmax #ifdef pmap_wired_count || (locklimit != 0 && (size + ptoa(pmap_wired_count(vm_map_pmap(map)))) > locklimit) #endif ) { error = ENOMEM; vm_map_unlock(map); /* unmap the region! */ uvm_unmap(map, *addr, *addr + size); KERNEL_UNLOCK(); return error; } /* * uvm_map_pageable() always returns the map * unlocked. */ error = uvm_map_pageable(map, *addr, *addr + size, FALSE, UVM_LK_ENTER); if (error != 0) { /* unmap the region! */ uvm_unmap(map, *addr, *addr + size); KERNEL_UNLOCK(); return error; } KERNEL_UNLOCK(); return 0; } vm_map_unlock(map); return 0; } /* * uvm_mmapanon: internal version of mmap for anons * * - used by sys_mmap */ int uvm_mmapanon(vm_map_t map, vaddr_t *addr, vsize_t size, vm_prot_t prot, vm_prot_t maxprot, int flags, vsize_t locklimit, struct proc *p) { int error; int advice = MADV_NORMAL; unsigned int uvmflag = 0; vsize_t align = 0; /* userland page size */ /* * for non-fixed mappings, round off the suggested address. * for fixed mappings, check alignment and zap old mappings. */ if ((flags & MAP_FIXED) == 0) { *addr = round_page(*addr); /* round */ } else { if (*addr & PAGE_MASK) return EINVAL; uvmflag |= UVM_FLAG_FIXED; if ((flags & __MAP_NOREPLACE) == 0) uvmflag |= UVM_FLAG_UNMAP; } if ((flags & MAP_FIXED) == 0 && size >= __LDPGSZ) align = __LDPGSZ; if ((flags & MAP_SHARED) == 0) /* XXX: defer amap create */ uvmflag |= UVM_FLAG_COPYONW; else /* shared: create amap now */ uvmflag |= UVM_FLAG_OVERLAY; if (flags & MAP_STACK) uvmflag |= UVM_FLAG_STACK; if (flags & MAP_CONCEAL) uvmflag |= UVM_FLAG_CONCEAL; /* set up mapping flags */ uvmflag = UVM_MAPFLAG(prot, maxprot, (flags & MAP_SHARED) ? MAP_INHERIT_SHARE : MAP_INHERIT_COPY, advice, uvmflag); error = uvm_mapanon(map, addr, size, align, uvmflag); if (error == 0) error = uvm_mmaplock(map, addr, size, prot, locklimit); return error; } /* * uvm_mmapfile: internal version of mmap for non-anons * * - used by sys_mmap * - caller must page-align the file offset */ int uvm_mmapfile(vm_map_t map, vaddr_t *addr, vsize_t size, vm_prot_t prot, vm_prot_t maxprot, int flags, struct vnode *vp, voff_t foff, vsize_t locklimit, struct proc *p) { struct uvm_object *uobj; int error; int advice = MADV_NORMAL; unsigned int uvmflag = 0; vsize_t align = 0; /* userland page size */ /* * for non-fixed mappings, round off the suggested address. * for fixed mappings, check alignment and zap old mappings. */ if ((flags & MAP_FIXED) == 0) { *addr = round_page(*addr); /* round */ } else { if (*addr & PAGE_MASK) return EINVAL; uvmflag |= UVM_FLAG_FIXED; if ((flags & __MAP_NOREPLACE) == 0) uvmflag |= UVM_FLAG_UNMAP; } /* * attach to underlying vm object. */ if (vp->v_type != VCHR) { uobj = uvn_attach(vp, (flags & MAP_SHARED) ? maxprot : (maxprot & ~PROT_WRITE)); /* * XXXCDC: hack from old code * don't allow vnodes which have been mapped * shared-writeable to persist [forces them to be * flushed out when last reference goes]. * XXXCDC: interesting side effect: avoids a bug. * note that in WRITE [ufs_readwrite.c] that we * allocate buffer, uncache, and then do the write. * the problem with this is that if the uncache causes * VM data to be flushed to the same area of the file * we are writing to... in that case we've got the * buffer locked and our process goes to sleep forever. * * XXXCDC: checking maxprot protects us from the * "persistbug" program but this is not a long term * solution. * * XXXCDC: we don't bother calling uncache with the vp * VOP_LOCKed since we know that we are already * holding a valid reference to the uvn (from the * uvn_attach above), and thus it is impossible for * the uncache to kill the uvn and trigger I/O. */ if (flags & MAP_SHARED) { if ((prot & PROT_WRITE) || (maxprot & PROT_WRITE)) { uvm_vnp_uncache(vp); } } } else { uobj = udv_attach(vp->v_rdev, (flags & MAP_SHARED) ? maxprot : (maxprot & ~PROT_WRITE), foff, size); /* * XXX Some devices don't like to be mapped with * XXX PROT_EXEC, but we don't really have a * XXX better way of handling this, right now */ if (uobj == NULL && (prot & PROT_EXEC) == 0) { maxprot &= ~PROT_EXEC; uobj = udv_attach(vp->v_rdev, (flags & MAP_SHARED) ? maxprot : (maxprot & ~PROT_WRITE), foff, size); } advice = MADV_RANDOM; } if (uobj == NULL) return vp->v_type == VREG ? ENOMEM : EINVAL; if ((flags & MAP_SHARED) == 0) uvmflag |= UVM_FLAG_COPYONW; if (flags & __MAP_NOFAULT) uvmflag |= (UVM_FLAG_NOFAULT | UVM_FLAG_OVERLAY); if (flags & MAP_STACK) uvmflag |= UVM_FLAG_STACK; if (flags & MAP_CONCEAL) uvmflag |= UVM_FLAG_CONCEAL; /* set up mapping flags */ uvmflag = UVM_MAPFLAG(prot, maxprot, (flags & MAP_SHARED) ? MAP_INHERIT_SHARE : MAP_INHERIT_COPY, advice, uvmflag); error = uvm_map(map, addr, size, uobj, foff, align, uvmflag); if (error == 0) return uvm_mmaplock(map, addr, size, prot, locklimit); /* errors: first detach from the uobj, if any. */ if (uobj) uobj->pgops->pgo_detach(uobj); return error; } int sys_kbind(struct proc *p, void *v, register_t *retval) { struct sys_kbind_args /* { syscallarg(const struct __kbind *) param; syscallarg(size_t) psize; syscallarg(uint64_t) proc_cookie; } */ *uap = v; const struct __kbind *paramp; union { struct __kbind uk[KBIND_BLOCK_MAX]; char upad[KBIND_BLOCK_MAX * sizeof(*paramp) + KBIND_DATA_MAX]; } param; struct uvm_map_deadq dead_entries; struct process *pr = p->p_p; const char *data; vaddr_t baseva, last_baseva, endva, pageoffset, kva; size_t psize, s; u_long pc; int count, i, extra; int error, sigill = 0; /* * extract syscall args from uap */ paramp = SCARG(uap, param); psize = SCARG(uap, psize); /* * If paramp is NULL and we're uninitialized, disable the syscall * for the process. Raise SIGILL if paramp is NULL and we're * already initialized. * * If paramp is non-NULL and we're uninitialized, do initialization. * Otherwise, do security checks and raise SIGILL on failure. */ pc = PROC_PC(p); mtx_enter(&pr->ps_mtx); if (paramp == NULL) { /* ld.so disables kbind() when lazy binding is disabled */ if (pr->ps_kbind_addr == 0) pr->ps_kbind_addr = BOGO_PC; /* pre-7.3 static binaries disable kbind */ /* XXX delete check in 2026 */ else if (pr->ps_kbind_addr != BOGO_PC) sigill = 1; } else if (pr->ps_kbind_addr == 0) { pr->ps_kbind_addr = pc; pr->ps_kbind_cookie = SCARG(uap, proc_cookie); } else if (pc != pr->ps_kbind_addr || pc == BOGO_PC || pr->ps_kbind_cookie != SCARG(uap, proc_cookie)) { sigill = 1; } mtx_leave(&pr->ps_mtx); /* Raise SIGILL if something is off. */ if (sigill) { KERNEL_LOCK(); sigexit(p, SIGILL); /* NOTREACHED */ KERNEL_UNLOCK(); } /* We're done if we were disabling the syscall. */ if (paramp == NULL) return 0; if (psize < sizeof(struct __kbind) || psize > sizeof(param)) return EINVAL; if ((error = copyin(paramp, &param, psize))) return error; /* * The param argument points to an array of __kbind structures * followed by the corresponding new data areas for them. Verify * that the sizes in the __kbind structures add up to the total * size and find the start of the new area. */ paramp = &param.uk[0]; s = psize; for (count = 0; s > 0 && count < KBIND_BLOCK_MAX; count++) { if (s < sizeof(*paramp)) return EINVAL; s -= sizeof(*paramp); baseva = (vaddr_t)paramp[count].kb_addr; endva = baseva + paramp[count].kb_size - 1; if (paramp[count].kb_addr == NULL || paramp[count].kb_size == 0 || paramp[count].kb_size > KBIND_DATA_MAX || baseva >= VM_MAXUSER_ADDRESS || endva >= VM_MAXUSER_ADDRESS || s < paramp[count].kb_size) return EINVAL; s -= paramp[count].kb_size; } if (s > 0) return EINVAL; data = (const char *)&paramp[count]; /* all looks good, so do the bindings */ last_baseva = VM_MAXUSER_ADDRESS; kva = 0; TAILQ_INIT(&dead_entries); for (i = 0; i < count; i++) { baseva = (vaddr_t)paramp[i].kb_addr; s = paramp[i].kb_size; pageoffset = baseva & PAGE_MASK; baseva = trunc_page(baseva); /* hppa at least runs PLT entries over page edge */ extra = (pageoffset + s) & PAGE_MASK; if (extra > pageoffset) extra = 0; else s -= extra; redo: /* make sure the desired page is mapped into kernel_map */ if (baseva != last_baseva) { if (kva != 0) { vm_map_lock(kernel_map); uvm_unmap_remove(kernel_map, kva, kva+PAGE_SIZE, &dead_entries, FALSE, TRUE, FALSE); /* XXX */ vm_map_unlock(kernel_map); kva = 0; } if ((error = uvm_map_extract(&p->p_vmspace->vm_map, baseva, PAGE_SIZE, &kva, UVM_EXTRACT_FIXPROT))) break; last_baseva = baseva; } /* do the update */ if ((error = kcopy(data, (char *)kva + pageoffset, s))) break; data += s; if (extra > 0) { baseva += PAGE_SIZE; s = extra; pageoffset = 0; extra = 0; goto redo; } } if (kva != 0) { vm_map_lock(kernel_map); uvm_unmap_remove(kernel_map, kva, kva+PAGE_SIZE, &dead_entries, FALSE, TRUE, FALSE); /* XXX */ vm_map_unlock(kernel_map); } uvm_unmap_detach(&dead_entries, AMAP_REFALL); return error; }
10 10 10 55 455 453 451 42 442 219 303 253 100 7 7 86 56 57 59 45 68 60 60 5 60 54 51 60 60 60 15 60 3 13 54 36 36 36 36 36 36 23 36 6 23 36 36 54 24 74 36 74 53 53 57 73 72 74 74 73 50 74 73 72 74 73 30 72 73 72 74 54 5 54 54 4 53 36 36 8 3 3 7 8 3 3 3 3 8 60 60 45 45 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 /* $OpenBSD: art.c,v 1.31 2023/11/11 12:17:50 bluhm Exp $ */ /* * Copyright (c) 2015 Martin Pieuchot * Copyright (c) 2001 Yoichi Hariguchi * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * Allotment Routing Table (ART). * * Yoichi Hariguchi paper can be found at: * http://www.hariguchi.org/art/art.pdf */ #ifndef _KERNEL #include "kern_compat.h" #else #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/pool.h> #include <sys/task.h> #include <sys/socket.h> #endif #include <net/art.h> int art_bindex(struct art_table *, const uint8_t *, int); void art_allot(struct art_table *at, int, struct art_node *, struct art_node *); struct art_table *art_table_get(struct art_root *, struct art_table *, int); struct art_table *art_table_put(struct art_root *, struct art_table *); struct art_node *art_table_insert(struct art_root *, struct art_table *, int, struct art_node *); struct art_node *art_table_delete(struct art_root *, struct art_table *, int, struct art_node *); struct art_table *art_table_ref(struct art_root *, struct art_table *); int art_table_free(struct art_root *, struct art_table *); int art_table_walk(struct art_root *, struct art_table *, int (*f)(struct art_node *, void *), void *); int art_walk_apply(struct art_root *, struct art_node *, struct art_node *, int (*f)(struct art_node *, void *), void *); void art_table_gc(void *); void art_gc(void *); struct pool an_pool, at_pool, at_heap_4_pool, at_heap_8_pool; struct art_table *art_table_gc_list = NULL; struct mutex art_table_gc_mtx = MUTEX_INITIALIZER(IPL_SOFTNET); struct task art_table_gc_task = TASK_INITIALIZER(art_table_gc, NULL); struct art_node *art_node_gc_list = NULL; struct mutex art_node_gc_mtx = MUTEX_INITIALIZER(IPL_SOFTNET); struct task art_node_gc_task = TASK_INITIALIZER(art_gc, NULL); void art_init(void) { pool_init(&an_pool, sizeof(struct art_node), 0, IPL_SOFTNET, 0, "art_node", NULL); pool_init(&at_pool, sizeof(struct art_table), 0, IPL_SOFTNET, 0, "art_table", NULL); pool_init(&at_heap_4_pool, AT_HEAPSIZE(4), 0, IPL_SOFTNET, 0, "art_heap4", NULL); pool_init(&at_heap_8_pool, AT_HEAPSIZE(8), 0, IPL_SOFTNET, 0, "art_heap8", &pool_allocator_single); } /* * Per routing table initialization API function. */ struct art_root * art_alloc(unsigned int rtableid, unsigned int alen, unsigned int off) { struct art_root *ar; int i; ar = malloc(sizeof(*ar), M_RTABLE, M_NOWAIT|M_ZERO); if (ar == NULL) return (NULL); switch (alen) { case 32: ar->ar_alen = 32; ar->ar_nlvl = 7; ar->ar_bits[0] = 8; for (i = 1; i < ar->ar_nlvl; i++) ar->ar_bits[i] = 4; break; case 128: ar->ar_alen = 128; ar->ar_nlvl = 32; for (i = 0; i < ar->ar_nlvl; i++) ar->ar_bits[i] = 4; break; default: printf("%s: incorrect address length %u\n", __func__, alen); free(ar, M_RTABLE, sizeof(*ar)); return (NULL); } ar->ar_off = off; rw_init(&ar->ar_lock, "art"); return (ar); } /* * Return 1 if ``old'' and ``new`` are identical, 0 otherwise. */ static inline int art_check_duplicate(struct art_root *ar, struct art_node *old, struct art_node *new) { if (old == NULL) return (0); if (old->an_plen == new->an_plen) return (1); return (0); } /* * Return the base index of the part of ``addr'' and ``plen'' * corresponding to the range covered by the table ``at''. * * In other words, this function take the multi-level (complete) * address ``addr'' and prefix length ``plen'' and return the * single level base index for the table ``at''. * * For example with an address size of 32bit divided into four * 8bit-long tables, there's a maximum of 4 base indexes if the * prefix length is > 24. */ int art_bindex(struct art_table *at, const uint8_t *addr, int plen) { uint8_t boff, bend; uint32_t k; if (plen < at->at_offset || plen > (at->at_offset + at->at_bits)) return (-1); /* * We are only interested in the part of the prefix length * corresponding to the range of this table. */ plen -= at->at_offset; /* * Jump to the first byte of the address containing bits * covered by this table. */ addr += (at->at_offset / 8); /* ``at'' covers the bit range between ``boff'' & ``bend''. */ boff = (at->at_offset % 8); bend = (at->at_bits + boff); KASSERT(bend <= 32); if (bend > 24) { k = (addr[0] & ((1 << (8 - boff)) - 1)) << (bend - 8); k |= addr[1] << (bend - 16); k |= addr[2] << (bend - 24); k |= addr[3] >> (32 - bend); } else if (bend > 16) { k = (addr[0] & ((1 << (8 - boff)) - 1)) << (bend - 8); k |= addr[1] << (bend - 16); k |= addr[2] >> (24 - bend); } else if (bend > 8) { k = (addr[0] & ((1 << (8 - boff)) - 1)) << (bend - 8); k |= addr[1] >> (16 - bend); } else { k = (addr[0] >> (8 - bend)) & ((1 << at->at_bits) - 1); } /* * Single level base index formula: */ return ((k >> (at->at_bits - plen)) + (1 << plen)); } /* * Single level lookup function. * * Return the fringe index of the part of ``addr'' * corresponding to the range covered by the table ``at''. */ static inline int art_findex(struct art_table *at, const uint8_t *addr) { return art_bindex(at, addr, (at->at_offset + at->at_bits)); } /* * (Non-perfect) lookup API function. * * Return the best existing match for a destination. */ struct art_node * art_match(struct art_root *ar, const void *addr, struct srp_ref *nsr) { struct srp_ref dsr, ndsr; void *entry; struct art_table *at; struct art_node *dflt, *ndflt; int j; entry = srp_enter(nsr, &ar->ar_root); at = entry; if (at == NULL) goto done; /* * Remember the default route of each table we visit in case * we do not find a better matching route. */ dflt = srp_enter(&dsr, &at->at_default); /* * Iterate until we find a leaf. */ while (1) { /* Do a single level route lookup. */ j = art_findex(at, addr); entry = srp_follow(nsr, &at->at_heap[j].node); /* If this is a leaf (NULL is a leaf) we're done. */ if (ISLEAF(entry)) break; at = SUBTABLE(entry); ndflt = srp_enter(&ndsr, &at->at_default); if (ndflt != NULL) { srp_leave(&dsr); dsr = ndsr; dflt = ndflt; } else srp_leave(&ndsr); } if (entry == NULL) { srp_leave(nsr); *nsr = dsr; KASSERT(ISLEAF(dflt)); return (dflt); } srp_leave(&dsr); done: KASSERT(ISLEAF(entry)); return (entry); } /* * Perfect lookup API function. * * Return a perfect match for a destination/prefix-length pair or NULL if * it does not exist. */ struct art_node * art_lookup(struct art_root *ar, const void *addr, int plen, struct srp_ref *nsr) { void *entry; struct art_table *at; int i, j; KASSERT(plen >= 0 && plen <= ar->ar_alen); entry = srp_enter(nsr, &ar->ar_root); at = entry; if (at == NULL) goto done; /* Default route */ if (plen == 0) { entry = srp_follow(nsr, &at->at_default); goto done; } /* * If the prefix length is smaller than the sum of * the stride length at this level the entry must * be in the current table. */ while (plen > (at->at_offset + at->at_bits)) { /* Do a single level route lookup. */ j = art_findex(at, addr); entry = srp_follow(nsr, &at->at_heap[j].node); /* A leaf is a match, but not a perfect one, or NULL */ if (ISLEAF(entry)) return (NULL); at = SUBTABLE(entry); } i = art_bindex(at, addr, plen); if (i == -1) return (NULL); entry = srp_follow(nsr, &at->at_heap[i].node); if (!ISLEAF(entry)) entry = srp_follow(nsr, &SUBTABLE(entry)->at_default); done: KASSERT(ISLEAF(entry)); return (entry); } /* * Insertion API function. * * Insert the given node or return an existing one if a node with the * same destination/mask pair is already present. */ struct art_node * art_insert(struct art_root *ar, struct art_node *an, const void *addr, int plen) { struct art_table *at, *child; struct art_node *node; int i, j; rw_assert_wrlock(&ar->ar_lock); KASSERT(plen >= 0 && plen <= ar->ar_alen); at = srp_get_locked(&ar->ar_root); if (at == NULL) { at = art_table_get(ar, NULL, -1); if (at == NULL) return (NULL); srp_swap_locked(&ar->ar_root, at); } /* Default route */ if (plen == 0) { node = srp_get_locked(&at->at_default); if (node != NULL) return (node); art_table_ref(ar, at); srp_swap_locked(&at->at_default, an); return (an); } /* * If the prefix length is smaller than the sum of * the stride length at this level the entry must * be in the current table. */ while (plen > (at->at_offset + at->at_bits)) { /* Do a single level route lookup. */ j = art_findex(at, addr); node = srp_get_locked(&at->at_heap[j].node); /* * If the node corresponding to the fringe index is * a leaf we need to allocate a subtable. The route * entry of this node will then become the default * route of the subtable. */ if (ISLEAF(node)) { child = art_table_get(ar, at, j); if (child == NULL) return (NULL); art_table_ref(ar, at); srp_swap_locked(&at->at_heap[j].node, ASNODE(child)); at = child; } else at = SUBTABLE(node); } i = art_bindex(at, addr, plen); if (i == -1) return (NULL); return (art_table_insert(ar, at, i, an)); } /* * Single level insertion. */ struct art_node * art_table_insert(struct art_root *ar, struct art_table *at, int i, struct art_node *an) { struct art_node *prev, *node; node = srp_get_locked(&at->at_heap[i].node); if (!ISLEAF(node)) prev = srp_get_locked(&SUBTABLE(node)->at_default); else prev = node; if (art_check_duplicate(ar, prev, an)) return (prev); art_table_ref(ar, at); /* * If the index `i' of the route that we are inserting is not * a fringe index, we need to allot this new route pointer to * all the corresponding fringe indices. */ if (i < at->at_minfringe) art_allot(at, i, prev, an); else if (!ISLEAF(node)) srp_swap_locked(&SUBTABLE(node)->at_default, an); else srp_swap_locked(&at->at_heap[i].node, an); return (an); } /* * Deletion API function. */ struct art_node * art_delete(struct art_root *ar, struct art_node *an, const void *addr, int plen) { struct art_table *at; struct art_node *node; int i, j; rw_assert_wrlock(&ar->ar_lock); KASSERT(plen >= 0 && plen <= ar->ar_alen); at = srp_get_locked(&ar->ar_root); if (at == NULL) return (NULL); /* Default route */ if (plen == 0) { node = srp_get_locked(&at->at_default); srp_swap_locked(&at->at_default, NULL); art_table_free(ar, at); return (node); } /* * If the prefix length is smaller than the sum of * the stride length at this level the entry must * be in the current table. */ while (plen > (at->at_offset + at->at_bits)) { /* Do a single level route lookup. */ j = art_findex(at, addr); node = srp_get_locked(&at->at_heap[j].node); /* If this is a leaf, there is no route to delete. */ if (ISLEAF(node)) return (NULL); at = SUBTABLE(node); } i = art_bindex(at, addr, plen); if (i == -1) return (NULL); return (art_table_delete(ar, at, i, an)); } /* * Single level deletion. */ struct art_node * art_table_delete(struct art_root *ar, struct art_table *at, int i, struct art_node *an) { struct art_node *next, *node; #ifdef DIAGNOSTIC struct art_node *prev; #endif node = srp_get_locked(&at->at_heap[i].node); #ifdef DIAGNOSTIC if (!ISLEAF(node)) prev = srp_get_locked(&SUBTABLE(node)->at_default); else prev = node; KASSERT(prev == an); #endif /* Get the next most specific route for the index `i'. */ if ((i >> 1) > 1) next = srp_get_locked(&at->at_heap[i >> 1].node); else next = NULL; /* * If the index `i' of the route that we are removing is not * a fringe index, we need to allot the next most specific * route pointer to all the corresponding fringe indices. */ if (i < at->at_minfringe) art_allot(at, i, an, next); else if (!ISLEAF(node)) srp_swap_locked(&SUBTABLE(node)->at_default, next); else srp_swap_locked(&at->at_heap[i].node, next); /* We have removed an entry from this table. */ art_table_free(ar, at); return (an); } struct art_table * art_table_ref(struct art_root *ar, struct art_table *at) { at->at_refcnt++; return (at); } static inline int art_table_rele(struct art_table *at) { if (at == NULL) return (0); return (--at->at_refcnt == 0); } int art_table_free(struct art_root *ar, struct art_table *at) { if (art_table_rele(at)) { /* * Garbage collect this table and all its parents * that are empty. */ do { at = art_table_put(ar, at); } while (art_table_rele(at)); return (1); } return (0); } /* * Iteration API function. */ int art_walk(struct art_root *ar, int (*f)(struct art_node *, void *), void *arg) { struct srp_ref sr; struct art_table *at; struct art_node *node; int error = 0; rw_enter_write(&ar->ar_lock); at = srp_get_locked(&ar->ar_root); if (at != NULL) { art_table_ref(ar, at); /* * The default route should be processed here because the root * table does not have a parent. */ node = srp_enter(&sr, &at->at_default); error = art_walk_apply(ar, node, NULL, f, arg); srp_leave(&sr); if (error == 0) error = art_table_walk(ar, at, f, arg); art_table_free(ar, at); } rw_exit_write(&ar->ar_lock); return (error); } int art_table_walk(struct art_root *ar, struct art_table *at, int (*f)(struct art_node *, void *), void *arg) { struct srp_ref sr; struct art_node *node, *next; struct art_table *nat; int i, j, error = 0; uint32_t maxfringe = (at->at_minfringe << 1); /* * Iterate non-fringe nodes in ``natural'' order. */ for (j = 1; j < at->at_minfringe; j += 2) { /* * The default route (index 1) is processed by the * parent table (where it belongs) otherwise it could * be processed more than once. */ for (i = max(j, 2); i < at->at_minfringe; i <<= 1) { next = srp_get_locked(&at->at_heap[i >> 1].node); node = srp_enter(&sr, &at->at_heap[i].node); error = art_walk_apply(ar, node, next, f, arg); srp_leave(&sr); if (error != 0) return (error); } } /* * Iterate fringe nodes. */ for (i = at->at_minfringe; i < maxfringe; i++) { next = srp_get_locked(&at->at_heap[i >> 1].node); node = srp_enter(&sr, &at->at_heap[i].node); if (!ISLEAF(node)) { nat = art_table_ref(ar, SUBTABLE(node)); node = srp_follow(&sr, &nat->at_default); } else nat = NULL; error = art_walk_apply(ar, node, next, f, arg); srp_leave(&sr); if (error != 0) { art_table_free(ar, nat); return (error); } if (nat != NULL) { error = art_table_walk(ar, nat, f, arg); art_table_free(ar, nat); if (error != 0) return (error); } } return (0); } int art_walk_apply(struct art_root *ar, struct art_node *an, struct art_node *next, int (*f)(struct art_node *, void *), void *arg) { int error = 0; if ((an != NULL) && (an != next)) { rw_exit_write(&ar->ar_lock); error = (*f)(an, arg); rw_enter_write(&ar->ar_lock); } return (error); } /* * Create a table and use the given index to set its default route. * * Note: This function does not modify the root or the parent. */ struct art_table * art_table_get(struct art_root *ar, struct art_table *parent, int j) { struct art_table *at; struct art_node *node; void *at_heap; uint32_t lvl; KASSERT(j != 0 && j != 1); KASSERT(parent != NULL || j == -1); if (parent != NULL) lvl = parent->at_level + 1; else lvl = 0; KASSERT(lvl < ar->ar_nlvl); at = pool_get(&at_pool, PR_NOWAIT|PR_ZERO); if (at == NULL) return (NULL); switch (AT_HEAPSIZE(ar->ar_bits[lvl])) { case AT_HEAPSIZE(4): at_heap = pool_get(&at_heap_4_pool, PR_NOWAIT|PR_ZERO); break; case AT_HEAPSIZE(8): at_heap = pool_get(&at_heap_8_pool, PR_NOWAIT|PR_ZERO); break; default: panic("incorrect stride length %u", ar->ar_bits[lvl]); } if (at_heap == NULL) { pool_put(&at_pool, at); return (NULL); } at->at_parent = parent; at->at_index = j; at->at_minfringe = (1 << ar->ar_bits[lvl]); at->at_level = lvl; at->at_bits = ar->ar_bits[lvl]; at->at_heap = at_heap; at->at_refcnt = 0; if (parent != NULL) { node = srp_get_locked(&parent->at_heap[j].node); /* node isn't being deleted, no srp_finalize needed */ srp_swap_locked(&at->at_default, node); at->at_offset = (parent->at_offset + parent->at_bits); } return (at); } /* * Delete a table and use its index to restore its parent's default route. * * Note: Modify its parent to unlink the table from it. */ struct art_table * art_table_put(struct art_root *ar, struct art_table *at) { struct art_table *parent = at->at_parent; struct art_node *node; uint32_t j = at->at_index; KASSERT(at->at_refcnt == 0); KASSERT(j != 0 && j != 1); if (parent != NULL) { KASSERT(j != -1); KASSERT(at->at_level == parent->at_level + 1); KASSERT(parent->at_refcnt >= 1); /* Give the route back to its parent. */ node = srp_get_locked(&at->at_default); srp_swap_locked(&parent->at_heap[j].node, node); } else { KASSERT(j == -1); KASSERT(at->at_level == 0); srp_swap_locked(&ar->ar_root, NULL); } mtx_enter(&art_table_gc_mtx); at->at_parent = art_table_gc_list; art_table_gc_list = at; mtx_leave(&art_table_gc_mtx); task_add(systqmp, &art_table_gc_task); return (parent); } void art_table_gc(void *null) { struct art_table *at, *next; mtx_enter(&art_table_gc_mtx); at = art_table_gc_list; art_table_gc_list = NULL; mtx_leave(&art_table_gc_mtx); while (at != NULL) { next = at->at_parent; if (at->at_level == 0) srp_finalize(at, "arttfini"); else srp_finalize(ASNODE(at), "arttfini"); switch (AT_HEAPSIZE(at->at_bits)) { case AT_HEAPSIZE(4): pool_put(&at_heap_4_pool, at->at_heap); break; case AT_HEAPSIZE(8): pool_put(&at_heap_8_pool, at->at_heap); break; default: panic("incorrect stride length %u", at->at_bits); } pool_put(&at_pool, at); at = next; } } /* * Substitute a node by another in the subtree whose root index is given. * * This function iterates on the table ``at'' at index ``i'' until no * more ``old'' node can be replaced by ``new''. * * This function was originally written by Don Knuth in CWEB. The * complicated ``goto''s are the result of expansion of the two * following recursions: * * art_allot(at, i, old, new) * { * int k = i; * if (at->at_heap[k] == old) * at->at_heap[k] = new; * if (k >= at->at_minfringe) * return; * k <<= 1; * art_allot(at, k, old, new); * k++; * art_allot(at, k, old, new); * } */ void art_allot(struct art_table *at, int i, struct art_node *old, struct art_node *new) { struct art_node *node, *dflt; int k = i; KASSERT(i < at->at_minfringe); again: k <<= 1; if (k < at->at_minfringe) goto nonfringe; /* Change fringe nodes. */ while (1) { node = srp_get_locked(&at->at_heap[k].node); if (!ISLEAF(node)) { dflt = srp_get_locked(&SUBTABLE(node)->at_default); if (dflt == old) { srp_swap_locked(&SUBTABLE(node)->at_default, new); } } else if (node == old) { srp_swap_locked(&at->at_heap[k].node, new); } if (k % 2) goto moveup; k++; } nonfringe: node = srp_get_locked(&at->at_heap[k].node); if (node == old) goto again; moveon: if (k % 2) goto moveup; k++; goto nonfringe; moveup: k >>= 1; srp_swap_locked(&at->at_heap[k].node, new); /* Change non-fringe node. */ if (k != i) goto moveon; } struct art_node * art_get(uint8_t plen) { struct art_node *an; an = pool_get(&an_pool, PR_NOWAIT | PR_ZERO); if (an == NULL) return (NULL); an->an_plen = plen; SRPL_INIT(&an->an_rtlist); return (an); } void art_put(struct art_node *an) { KASSERT(SRPL_EMPTY_LOCKED(&an->an_rtlist)); mtx_enter(&art_node_gc_mtx); an->an_gc = art_node_gc_list; art_node_gc_list = an; mtx_leave(&art_node_gc_mtx); task_add(systqmp, &art_node_gc_task); } void art_gc(void *null) { struct art_node *an, *next; mtx_enter(&art_node_gc_mtx); an = art_node_gc_list; art_node_gc_list = NULL; mtx_leave(&art_node_gc_mtx); while (an != NULL) { next = an->an_gc; srp_finalize(an, "artnfini"); pool_put(&an_pool, an); an = next; } }
1 1 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 /* $OpenBSD: pctr.c,v 1.10 2024/04/03 02:01:21 guenther Exp $ */ /* * Copyright (c) 2007 Mike Belopuhov * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * Pentium performance counter driver for OpenBSD. * Copyright 1996 David Mazieres <dm@lcs.mit.edu>. * * Modification and redistribution in source and binary forms is * permitted provided that due credit is given to the author and the * OpenBSD project by leaving this copyright notice intact. */ #include <sys/param.h> #include <sys/errno.h> #include <sys/fcntl.h> #include <sys/ioccom.h> #include <sys/mutex.h> #include <sys/systm.h> #include <machine/intr.h> #include <machine/pctr.h> #include <machine/cpu.h> #include <machine/specialreg.h> #define PCTR_AMD_NUM PCTR_NUM #define PCTR_INTEL_NUM 2 /* Intel supports only 2 counters */ #define PCTR_INTEL_VERSION_MASK 0xff #define usetsc (cpu_feature & CPUID_TSC) #define usepctr ((pctr_isamd && ((cpu_id >> 8) & 15) >= 6) || \ (pctr_isintel && \ (pctr_intel_cap & PCTR_INTEL_VERSION_MASK) >= 1)) int pctr_isamd; int pctr_isintel; uint32_t pctr_intel_cap; struct mutex pctr_conf_lock = MUTEX_INITIALIZER(IPL_HIGH); uint32_t pctr_fn[PCTR_NUM]; static void pctrrd(struct pctrst *); static int pctrsel(int, uint32_t, uint32_t); static void pctr_enable(struct cpu_info *); static void pctrrd(struct pctrst *st) { int i, num, reg; num = pctr_isamd ? PCTR_AMD_NUM : PCTR_INTEL_NUM; reg = pctr_isamd ? MSR_K7_EVNTSEL0 : MSR_EVNTSEL0; for (i = 0; i < num; i++) st->pctr_fn[i] = rdmsr(reg + i); __asm volatile("cli"); st->pctr_tsc = rdtsc(); for (i = 0; i < num; i++) st->pctr_hwc[i] = rdpmc(i); __asm volatile("sti"); } void pctrattach(int num) { struct cpu_info *ci = &cpu_info_primary; uint32_t dummy; if (num > 1) return; pctr_isamd = (ci->ci_vendor == CPUV_AMD); if (!pctr_isamd) { pctr_isintel = (ci->ci_vendor == CPUV_INTEL); CPUID(0xa, pctr_intel_cap, dummy, dummy, dummy); } } void pctr_enable(struct cpu_info *ci) { if (usepctr) { /* Enable RDTSC and RDPMC instructions from user-level. */ __asm volatile("movq %%cr4,%%rax\n" "\tandq %0,%%rax\n" "\torq %1,%%rax\n" "\tmovq %%rax,%%cr4" :: "i" (~CR4_TSD), "i" (CR4_PCE) : "rax"); } else if (usetsc) { /* Enable RDTSC instruction from user-level. */ __asm volatile("movq %%cr4,%%rax\n" "\tandq %0,%%rax\n" "\tmovq %%rax,%%cr4" :: "i" (~CR4_TSD) : "rax"); } } int pctropen(dev_t dev, int oflags, int devtype, struct proc *p) { if (minor(dev)) return (ENXIO); return (0); } int pctrclose(dev_t dev, int oflags, int devtype, struct proc *p) { return (0); } static int pctrsel(int fflag, uint32_t cmd, uint32_t fn) { int msrsel, msrval, changed; cmd -= PCIOCS0; if (pctr_isamd) { if (cmd > PCTR_AMD_NUM-1) return (EINVAL); msrsel = MSR_K7_EVNTSEL0 + cmd; msrval = MSR_K7_PERFCTR0 + cmd; } else { if (cmd > PCTR_INTEL_NUM-1) return (EINVAL); msrsel = MSR_EVNTSEL0 + cmd; msrval = MSR_PERFCTR0 + cmd; } if (!(fflag & FWRITE)) return (EPERM); if (fn & 0x380000) return (EINVAL); if (fn != 0) pctr_enable(curcpu()); mtx_enter(&pctr_conf_lock); changed = fn != pctr_fn[cmd]; if (changed) { pctr_fn[cmd] = fn; wrmsr(msrval, 0); wrmsr(msrsel, fn); wrmsr(msrval, 0); } mtx_leave(&pctr_conf_lock); #ifdef MULTIPROCESSOR if (changed) x86_broadcast_ipi(X86_IPI_PCTR); #endif return (0); } int pctrioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p) { switch (cmd) { case PCIOCRD: { struct pctrst *st = (struct pctrst *)data; if (usepctr) pctrrd(st); else if (usetsc) st->pctr_tsc = rdtsc(); return (0); } case PCIOCS0: case PCIOCS1: case PCIOCS2: case PCIOCS3: if (usepctr) return (pctrsel(fflag, cmd, *(u_int *)data)); return (ENODEV); default: return (EINVAL); } } void pctr_reload(struct cpu_info *ci) { int num, i, msrsel, msrval, anyset; uint32_t fn; if (pctr_isamd) { num = PCTR_AMD_NUM; msrsel = MSR_K7_EVNTSEL0; msrval = MSR_K7_PERFCTR0; } else { num = PCTR_INTEL_NUM; msrsel = MSR_EVNTSEL0; msrval = MSR_PERFCTR0; } anyset = 0; mtx_enter(&pctr_conf_lock); for (i = 0; i < num; i++) { /* only update the ones that don't match */ /* XXX generation numbers for zeroing? */ fn = rdmsr(msrsel + i); if (fn != pctr_fn[i]) { wrmsr(msrval + i, 0); wrmsr(msrsel + i, pctr_fn[i]); wrmsr(msrval + i, 0); } if (fn) anyset = 1; } mtx_leave(&pctr_conf_lock); if (! anyset) pctr_enable(curcpu()); } void pctr_resume(struct cpu_info *ci) { if (usepctr) pctr_reload(ci); }
2 4 6 2 13 13 2 2 2 4 1 37 2 1 2 3 12 1 1 2 2 2 5 2 2 1 5 5 5 4 1 5 5 5 5 5 494 494 5497 5497 5489 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 /* $OpenBSD: machdep.c,v 1.293 2024/04/29 00:29:48 jsg Exp $ */ /* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */ /*- * Copyright (c) 1996, 1997, 1998, 2000 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace * Simulation Facility, NASA Ames Research Center. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /*- * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)machdep.c 7.4 (Berkeley) 6/3/91 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/signal.h> #include <sys/signalvar.h> #include <sys/proc.h> #include <sys/user.h> #include <sys/exec.h> #include <sys/buf.h> #include <sys/reboot.h> #include <sys/conf.h> #include <sys/msgbuf.h> #include <sys/mount.h> #include <sys/extent.h> #include <sys/core.h> #include <sys/kcore.h> #include <sys/syscallargs.h> #include <dev/cons.h> #include <stand/boot/bootarg.h> #include <net/if.h> #include <uvm/uvm_extern.h> #include <sys/sysctl.h> #include <machine/cpu_full.h> #include <machine/cpufunc.h> #include <machine/pio.h> #include <machine/psl.h> #include <machine/reg.h> #include <machine/fpu.h> #include <machine/biosvar.h> #include <machine/mpbiosvar.h> #include <machine/kcore.h> #include <machine/tss.h> #include <dev/isa/isareg.h> #include <dev/ic/i8042reg.h> #ifdef DDB #include <machine/db_machdep.h> #include <ddb/db_extern.h> extern int db_console; #endif #include "isa.h" #include "isadma.h" #include "ksyms.h" #include "acpi.h" #if NACPI > 0 #include <dev/acpi/acpivar.h> #endif #include "com.h" #if NCOM > 0 #include <sys/tty.h> #include <dev/ic/comvar.h> #include <dev/ic/comreg.h> #endif #include "efi.h" #if NEFI > 0 #include <dev/efi/efi.h> #endif #include "softraid.h" #if NSOFTRAID > 0 #include <dev/softraidvar.h> #endif #ifdef HIBERNATE #include <machine/hibernate_var.h> #endif /* HIBERNATE */ #include "ukbd.h" #include "pckbc.h" #if NPCKBC > 0 && NUKBD > 0 #include <dev/ic/pckbcvar.h> #endif /* #define MACHDEP_DEBUG */ #ifdef MACHDEP_DEBUG #define DPRINTF(x...) do { printf(x); } while(0) #else #define DPRINTF(x...) #endif /* MACHDEP_DEBUG */ /* the following is used externally (sysctl_hw) */ char machine[] = MACHINE; /* * switchto vectors */ void cpu_idle_cycle_hlt(void); void (*cpu_idle_cycle_fcn)(void) = &cpu_idle_cycle_hlt; /* the following is used externally for concurrent handlers */ int setperf_prio = 0; #ifdef CPURESET_DELAY int cpureset_delay = CPURESET_DELAY; #else int cpureset_delay = 0; #endif char *ssym = 0, *esym = 0; /* start and end of symbol table */ dev_t bootdev = 0; /* device we booted from */ int biosbasemem = 0; /* base memory reported by BIOS */ u_int bootapiver = 0; /* /boot API version */ int physmem; extern int boothowto; paddr_t dumpmem_paddr; vaddr_t dumpmem_vaddr; psize_t dumpmem_sz; vaddr_t kern_end; vaddr_t msgbuf_vaddr; paddr_t msgbuf_paddr; vaddr_t idt_vaddr; paddr_t idt_paddr; vaddr_t lo32_vaddr; paddr_t lo32_paddr; paddr_t tramp_pdirpa; int kbd_reset; int lid_action = 1; int pwr_action = 1; int forceukbd; /* * safepri is a safe priority for sleep to set for a spin-wait * during autoconfiguration or after a panic. */ int safepri = 0; struct vm_map *exec_map = NULL; struct vm_map *phys_map = NULL; /* UVM constraint ranges. */ struct uvm_constraint_range isa_constraint = { 0x0, 0x00ffffffUL }; struct uvm_constraint_range dma_constraint = { 0x0, 0xffffffffUL }; struct uvm_constraint_range *uvm_md_constraints[] = { &isa_constraint, &dma_constraint, NULL, }; paddr_t avail_start; paddr_t avail_end; void (*delay_func)(int) = i8254_delay; void (*initclock_func)(void) = i8254_initclocks; void (*startclock_func)(void) = i8254_start_both_clocks; /* * Format of boot information passed to us by 32-bit /boot */ typedef struct _boot_args32 { int ba_type; int ba_size; int ba_nextX; /* a ptr in 32-bit world, but not here */ char ba_arg[1]; } bootarg32_t; #define BOOTARGC_MAX NBPG /* one page */ bios_bootmac_t *bios_bootmac; /* locore copies the arguments from /boot to here for us */ char bootinfo[BOOTARGC_MAX]; int bootinfo_size = BOOTARGC_MAX; void getbootinfo(char *, int); /* Data passed to us by /boot, filled in by getbootinfo() */ bios_diskinfo_t *bios_diskinfo; bios_memmap_t *bios_memmap; u_int32_t bios_cksumlen; bios_efiinfo_t *bios_efiinfo; bios_ucode_t *bios_ucode; #if NEFI > 0 EFI_MEMORY_DESCRIPTOR *mmap; #endif /* * Size of memory segments, before any memory is stolen. */ phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; int mem_cluster_cnt; int cpu_dump(void); int cpu_dumpsize(void); u_long cpu_dump_mempagecnt(void); void dumpsys(void); void cpu_init_extents(void); void map_tramps(void); void init_x86_64(paddr_t); void (*cpuresetfn)(void); void enter_shared_special_pages(void); #ifdef APERTURE int allowaperture = 0; #endif /* * Machine-dependent startup code */ void cpu_startup(void) { vaddr_t minaddr, maxaddr; msgbuf_vaddr = PMAP_DIRECT_MAP(msgbuf_paddr); initmsgbuf((caddr_t)msgbuf_vaddr, round_page(MSGBUFSIZE)); printf("%s", version); startclocks(); rtcinit(); printf("real mem = %lu (%luMB)\n", ptoa((psize_t)physmem), ptoa((psize_t)physmem)/1024/1024); /* * Allocate a submap for exec arguments. This map effectively * limits the number of processes exec'ing at any time. */ minaddr = vm_map_min(kernel_map); exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); /* * Allocate a submap for physio */ minaddr = vm_map_min(kernel_map); phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, VM_PHYS_SIZE, 0, FALSE, NULL); printf("avail mem = %lu (%luMB)\n", ptoa((psize_t)uvmexp.free), ptoa((psize_t)uvmexp.free)/1024/1024); bufinit(); if (boothowto & RB_CONFIG) { #ifdef BOOT_CONFIG user_config(); #else printf("kernel does not support -c; continuing..\n"); #endif } /* Safe for i/o port / memory space allocation to use malloc now. */ x86_bus_space_mallocok(); #ifndef SMALL_KERNEL cpu_ucode_setup(); cpu_ucode_apply(&cpu_info_primary); #endif cpu_tsx_disable(&cpu_info_primary); /* enter the IDT and trampoline code in the u-k maps */ enter_shared_special_pages(); /* initialize CPU0's TSS and GDT and put them in the u-k maps */ cpu_enter_pages(&cpu_info_full_primary); } /* * enter_shared_special_pages * * Requests mapping of various special pages required in the Intel Meltdown * case (to be entered into the U-K page table): * * 1 IDT page * Various number of pages covering the U-K ".kutext" section. This section * contains code needed during trampoline operation * Various number of pages covering the U-K ".kudata" section. This section * contains data accessed by the trampoline, before switching to U+K * (for example, various shared global variables used by IPIs, etc) * * The linker script places the required symbols in the sections above. * * On CPUs not affected by Meltdown, the calls to pmap_enter_special below * become no-ops. */ void enter_shared_special_pages(void) { extern char __kutext_start[], __kutext_end[], __kernel_kutext_phys[]; extern char __text_page_start[], __text_page_end[]; extern char __kernel_kutext_page_phys[]; extern char __kudata_start[], __kudata_end[], __kernel_kudata_phys[]; vaddr_t va; paddr_t pa; /* idt */ pmap_enter_special(idt_vaddr, idt_paddr, PROT_READ); DPRINTF("%s: entered idt page va 0x%llx pa 0x%llx\n", __func__, (uint64_t)idt_vaddr, (uint64_t)idt_paddr); /* .kutext section */ va = (vaddr_t)__kutext_start; pa = (paddr_t)__kernel_kutext_phys; while (va < (vaddr_t)__kutext_end) { pmap_enter_special(va, pa, PROT_READ | PROT_EXEC); DPRINTF("%s: entered kutext page va 0x%llx pa 0x%llx\n", __func__, (uint64_t)va, (uint64_t)pa); va += PAGE_SIZE; pa += PAGE_SIZE; } /* .kutext.page section */ va = (vaddr_t)__text_page_start; pa = (paddr_t)__kernel_kutext_page_phys; while (va < (vaddr_t)__text_page_end) { pmap_enter_special(va, pa, PROT_READ | PROT_EXEC); DPRINTF("%s: entered kutext.page va 0x%llx pa 0x%llx\n", __func__, (uint64_t)va, (uint64_t)pa); va += PAGE_SIZE; pa += PAGE_SIZE; } /* .kudata section */ va = (vaddr_t)__kudata_start; pa = (paddr_t)__kernel_kudata_phys; while (va < (vaddr_t)__kudata_end) { pmap_enter_special(va, pa, PROT_READ | PROT_WRITE); DPRINTF("%s: entered kudata page va 0x%llx pa 0x%llx\n", __func__, (uint64_t)va, (uint64_t)pa); va += PAGE_SIZE; pa += PAGE_SIZE; } } /* * Set up proc0's PCB and the cpu's TSS. */ void x86_64_proc0_tss_ldt_init(void) { struct pcb *pcb; cpu_info_primary.ci_curpcb = pcb = &proc0.p_addr->u_pcb; pcb->pcb_fsbase = 0; pcb->pcb_kstack = (u_int64_t)proc0.p_addr + USPACE - 16; proc0.p_md.md_regs = (struct trapframe *)pcb->pcb_kstack - 1; ltr(GSYSSEL(GPROC0_SEL, SEL_KPL)); lldt(0); } bios_diskinfo_t * bios_getdiskinfo(dev_t dev) { bios_diskinfo_t *pdi; if (bios_diskinfo == NULL) return NULL; for (pdi = bios_diskinfo; pdi->bios_number != -1; pdi++) { if ((dev & B_MAGICMASK) == B_DEVMAGIC) { /* search by bootdev */ if (pdi->bsd_dev == dev) break; } else { if (pdi->bios_number == dev) break; } } if (pdi->bios_number == -1) return NULL; else return pdi; } int bios_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { bios_diskinfo_t *pdi; int biosdev; /* all sysctl names at this level except diskinfo are terminal */ if (namelen != 1 && name[0] != BIOS_DISKINFO) return (ENOTDIR); /* overloaded */ if (!(bootapiver & BAPIV_VECTOR)) return EOPNOTSUPP; switch (name[0]) { case BIOS_DEV: if ((pdi = bios_getdiskinfo(bootdev)) == NULL) return ENXIO; biosdev = pdi->bios_number; return sysctl_rdint(oldp, oldlenp, newp, biosdev); case BIOS_DISKINFO: if (namelen != 2) return ENOTDIR; if ((pdi = bios_getdiskinfo(name[1])) == NULL) return ENXIO; return sysctl_rdstruct(oldp, oldlenp, newp, pdi, sizeof(*pdi)); case BIOS_CKSUMLEN: return sysctl_rdint(oldp, oldlenp, newp, bios_cksumlen); default: return EOPNOTSUPP; } /* NOTREACHED */ } extern int tsc_is_invariant; extern int amd64_has_xcrypt; extern int need_retpoline; const struct sysctl_bounded_args cpuctl_vars[] = { { CPU_LIDACTION, &lid_action, 0, 2 }, { CPU_PWRACTION, &pwr_action, 0, 2 }, { CPU_CPUID, &cpu_id, SYSCTL_INT_READONLY }, { CPU_CPUFEATURE, &cpu_feature, SYSCTL_INT_READONLY }, { CPU_XCRYPT, &amd64_has_xcrypt, SYSCTL_INT_READONLY }, { CPU_INVARIANTTSC, &tsc_is_invariant, SYSCTL_INT_READONLY }, { CPU_RETPOLINE, &need_retpoline, SYSCTL_INT_READONLY }, }; /* * machine dependent system variables. */ int cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { extern uint64_t tsc_frequency; dev_t consdev; dev_t dev; switch (name[0]) { case CPU_CONSDEV: if (namelen != 1) return (ENOTDIR); /* overloaded */ if (cn_tab != NULL) consdev = cn_tab->cn_dev; else consdev = NODEV; return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev, sizeof consdev)); case CPU_CHR2BLK: if (namelen != 2) return (ENOTDIR); /* overloaded */ dev = chrtoblk((dev_t)name[1]); return sysctl_rdstruct(oldp, oldlenp, newp, &dev, sizeof(dev)); case CPU_BIOS: return bios_sysctl(name + 1, namelen - 1, oldp, oldlenp, newp, newlen, p); case CPU_CPUVENDOR: return (sysctl_rdstring(oldp, oldlenp, newp, cpu_vendor)); case CPU_KBDRESET: return (sysctl_securelevel_int(oldp, oldlenp, newp, newlen, &kbd_reset)); case CPU_ALLOWAPERTURE: if (namelen != 1) return (ENOTDIR); /* overloaded */ #ifdef APERTURE if (securelevel > 0) return (sysctl_int_lower(oldp, oldlenp, newp, newlen, &allowaperture)); else return (sysctl_int(oldp, oldlenp, newp, newlen, &allowaperture)); #else return (sysctl_rdint(oldp, oldlenp, newp, 0)); #endif #if NPCKBC > 0 && NUKBD > 0 case CPU_FORCEUKBD: { int error; if (forceukbd) return (sysctl_rdint(oldp, oldlenp, newp, forceukbd)); error = sysctl_int(oldp, oldlenp, newp, newlen, &forceukbd); if (forceukbd) pckbc_release_console(); return (error); } #endif case CPU_TSCFREQ: return (sysctl_rdquad(oldp, oldlenp, newp, tsc_frequency)); default: return (sysctl_bounded_arr(cpuctl_vars, nitems(cpuctl_vars), name, namelen, oldp, oldlenp, newp, newlen)); } /* NOTREACHED */ } static inline void maybe_enable_user_cet(struct proc *p) { #ifndef SMALL_KERNEL /* Enable indirect-branch tracking if present and not disabled */ if ((xsave_mask & XFEATURE_CET_U) && (p->p_p->ps_flags & PS_NOBTCFI) == 0) { uint64_t msr = rdmsr(MSR_U_CET); wrmsr(MSR_U_CET, msr | MSR_CET_ENDBR_EN | MSR_CET_NO_TRACK_EN); } #endif } static inline void initialize_thread_xstate(struct proc *p) { if (cpu_use_xsaves) { xrstors(fpu_cleandata, xsave_mask); maybe_enable_user_cet(p); } else { /* Reset FPU state in PCB */ memcpy(&p->p_addr->u_pcb.pcb_savefpu, fpu_cleandata, fpu_save_len); if (curcpu()->ci_pflags & CPUPF_USERXSTATE) { /* state in CPU is obsolete; reset it */ fpureset(); } } /* The reset state _is_ the userspace state for this thread now */ curcpu()->ci_pflags |= CPUPF_USERXSTATE; } /* * Copy out the FPU state, massaging it to be usable from userspace * and acceptable to xrstor_user() */ static inline int copyoutfpu(struct savefpu *sfp, char *sp, size_t len) { uint64_t bvs[2]; if (copyout(sfp, sp, len)) return 1; if (len > offsetof(struct savefpu, fp_xstate.xstate_bv)) { sp += offsetof(struct savefpu, fp_xstate.xstate_bv); len -= offsetof(struct savefpu, fp_xstate.xstate_bv); bvs[0] = sfp->fp_xstate.xstate_bv & XFEATURE_XCR0_MASK; bvs[1] = sfp->fp_xstate.xstate_xcomp_bv & (XFEATURE_XCR0_MASK | XFEATURE_COMPRESSED); if (copyout(bvs, sp, min(len, sizeof bvs))) return 1; } return 0; } /* * Send an interrupt to process. * * Stack is set up to allow sigcode to call routine, followed by * syscall to sigreturn routine below. After sigreturn resets the * signal mask, the stack, and the frame pointer, it returns to the * user specified pc. */ int sendsig(sig_t catcher, int sig, sigset_t mask, const siginfo_t *ksip, int info, int onstack) { struct proc *p = curproc; struct trapframe *tf = p->p_md.md_regs; struct sigcontext ksc; struct savefpu *sfp = &p->p_addr->u_pcb.pcb_savefpu; register_t sp, scp, sip; u_long sss; memset(&ksc, 0, sizeof ksc); ksc.sc_rdi = tf->tf_rdi; ksc.sc_rsi = tf->tf_rsi; ksc.sc_rdx = tf->tf_rdx; ksc.sc_rcx = tf->tf_rcx; ksc.sc_r8 = tf->tf_r8; ksc.sc_r9 = tf->tf_r9; ksc.sc_r10 = tf->tf_r10; ksc.sc_r11 = tf->tf_r11; ksc.sc_r12 = tf->tf_r12; ksc.sc_r13 = tf->tf_r13; ksc.sc_r14 = tf->tf_r14; ksc.sc_r15 = tf->tf_r15; ksc.sc_rbx = tf->tf_rbx; ksc.sc_rax = tf->tf_rax; ksc.sc_rbp = tf->tf_rbp; ksc.sc_rip = tf->tf_rip; ksc.sc_cs = tf->tf_cs; ksc.sc_rflags = tf->tf_rflags; ksc.sc_rsp = tf->tf_rsp; ksc.sc_ss = tf->tf_ss; ksc.sc_mask = mask; /* Allocate space for the signal handler context. */ if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 && !sigonstack(tf->tf_rsp) && onstack) sp = trunc_page((vaddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size); else sp = tf->tf_rsp - 128; sp -= fpu_save_len; if (cpu_use_xsaves) sp &= ~63ULL; /* just in case */ else sp &= ~15ULL; /* just in case */ /* Save FPU state to PCB if necessary, then copy it out */ if (curcpu()->ci_pflags & CPUPF_USERXSTATE) fpusave(&p->p_addr->u_pcb.pcb_savefpu); if (copyoutfpu(sfp, (void *)sp, fpu_save_len)) return 1; initialize_thread_xstate(p); ksc.sc_fpstate = (struct fxsave64 *)sp; sss = (sizeof(ksc) + 15) & ~15; sip = 0; if (info) { sip = sp - ((sizeof(*ksip) + 15) & ~15); sss += (sizeof(*ksip) + 15) & ~15; if (copyout(ksip, (void *)sip, sizeof(*ksip))) return 1; } scp = sp - sss; ksc.sc_cookie = (long)scp ^ p->p_p->ps_sigcookie; if (copyout(&ksc, (void *)scp, sizeof(ksc))) return 1; /* * Build context to run handler in. */ tf->tf_rax = (u_int64_t)catcher; tf->tf_rdi = sig; tf->tf_rsi = sip; tf->tf_rdx = scp; tf->tf_rip = (u_int64_t)p->p_p->ps_sigcode; tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL); tf->tf_rflags &= ~(PSL_T|PSL_D|PSL_VM|PSL_AC); tf->tf_rsp = scp; tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL); return 0; } /* * System call to cleanup state after a signal * has been taken. Reset signal mask and * stack state from context left by sendsig (above). * Return to previous pc and psl as specified by * context left by sendsig. Check carefully to * make sure that the user has not modified the * psl to gain improper privileges or to cause * a machine fault. */ int sys_sigreturn(struct proc *p, void *v, register_t *retval) { struct sys_sigreturn_args /* { syscallarg(struct sigcontext *) sigcntxp; } */ *uap = v; struct sigcontext ksc, *scp = SCARG(uap, sigcntxp); struct trapframe *tf = p->p_md.md_regs; struct savefpu *sfp = &p->p_addr->u_pcb.pcb_savefpu; int error; if (PROC_PC(p) != p->p_p->ps_sigcoderet) { sigexit(p, SIGILL); return (EPERM); } if ((error = copyin((caddr_t)scp, &ksc, sizeof ksc))) return (error); if (ksc.sc_cookie != ((long)scp ^ p->p_p->ps_sigcookie)) { sigexit(p, SIGILL); return (EFAULT); } /* Prevent reuse of the sigcontext cookie */ ksc.sc_cookie = 0; (void)copyout(&ksc.sc_cookie, (caddr_t)scp + offsetof(struct sigcontext, sc_cookie), sizeof (ksc.sc_cookie)); if (((ksc.sc_rflags ^ tf->tf_rflags) & PSL_USERSTATIC) != 0 || !USERMODE(ksc.sc_cs, ksc.sc_eflags)) return (EINVAL); /* Current FPU state is obsolete; toss it and force a reload */ if (curcpu()->ci_pflags & CPUPF_USERXSTATE) { curcpu()->ci_pflags &= ~CPUPF_USERXSTATE; fpureset(); } /* Copy in the FPU state to restore */ if (__predict_true(ksc.sc_fpstate != NULL)) { if ((error = copyin(ksc.sc_fpstate, sfp, fpu_save_len))) return error; if (xrstor_user(sfp, xsave_mask)) { memcpy(sfp, fpu_cleandata, fpu_save_len); return EINVAL; } maybe_enable_user_cet(p); curcpu()->ci_pflags |= CPUPF_USERXSTATE; } else { /* shouldn't happen, but handle it */ initialize_thread_xstate(p); } tf->tf_rdi = ksc.sc_rdi; tf->tf_rsi = ksc.sc_rsi; tf->tf_rdx = ksc.sc_rdx; tf->tf_rcx = ksc.sc_rcx; tf->tf_r8 = ksc.sc_r8; tf->tf_r9 = ksc.sc_r9; tf->tf_r10 = ksc.sc_r10; tf->tf_r11 = ksc.sc_r11; tf->tf_r12 = ksc.sc_r12; tf->tf_r13 = ksc.sc_r13; tf->tf_r14 = ksc.sc_r14; tf->tf_r15 = ksc.sc_r15; tf->tf_rbx = ksc.sc_rbx; tf->tf_rax = ksc.sc_rax; tf->tf_rbp = ksc.sc_rbp; tf->tf_rip = ksc.sc_rip; tf->tf_cs = ksc.sc_cs; tf->tf_rflags = ksc.sc_rflags; tf->tf_rsp = ksc.sc_rsp; tf->tf_ss = ksc.sc_ss; /* Restore signal mask. */ p->p_sigmask = ksc.sc_mask & ~sigcantmask; /* * sigreturn() needs to return to userspace via the 'iretq' * method, so that if the process was interrupted (by tick, * an IPI, whatever) as opposed to already being in the kernel * when a signal was being delivered, the process will be * completely restored, including the userland %rcx and %r11 * registers which the 'sysretq' instruction cannot restore. * Also need to make sure we can handle faulting on xrstor. */ p->p_md.md_flags |= MDP_IRET; return (EJUSTRETURN); } #ifdef MULTIPROCESSOR /* force a CPU into the kernel, whether or not it's idle */ void cpu_kick(struct cpu_info *ci) { /* only need to kick other CPUs */ if (ci != curcpu()) { if (cpu_mwait_size > 0) { /* * If not idling, then send an IPI, else * just clear the "keep idling" bit. */ if ((ci->ci_mwait & MWAIT_IN_IDLE) == 0) x86_send_ipi(ci, X86_IPI_NOP); else atomic_clearbits_int(&ci->ci_mwait, MWAIT_KEEP_IDLING); } else { /* no mwait, so need an IPI */ x86_send_ipi(ci, X86_IPI_NOP); } } } #endif /* * Notify the current process (p) that it has a signal pending, * process as soon as possible. */ void signotify(struct proc *p) { aston(p); cpu_kick(p->p_cpu); } #ifdef MULTIPROCESSOR void cpu_unidle(struct cpu_info *ci) { if (cpu_mwait_size > 0 && (ci->ci_mwait & MWAIT_ONLY)) { /* * Just clear the "keep idling" bit; if it wasn't * idling then we didn't need to do anything anyway. */ atomic_clearbits_int(&ci->ci_mwait, MWAIT_KEEP_IDLING); return; } if (ci != curcpu()) x86_send_ipi(ci, X86_IPI_NOP); } #endif int waittime = -1; struct pcb dumppcb; __dead void boot(int howto) { if ((howto & RB_POWERDOWN) != 0) lid_action = 0; if ((howto & RB_RESET) != 0) goto doreset; if (cold) { if ((howto & RB_USERREQ) == 0) howto |= RB_HALT; goto haltsys; } boothowto = howto; if ((howto & RB_NOSYNC) == 0 && waittime < 0) { waittime = 0; vfs_shutdown(curproc); if ((howto & RB_TIMEBAD) == 0) { resettodr(); } else { printf("WARNING: not updating battery clock\n"); } } if_downall(); uvm_shutdown(); splhigh(); cold = 1; if ((howto & RB_DUMP) != 0) dumpsys(); haltsys: config_suspend_all(DVACT_POWERDOWN); #ifdef MULTIPROCESSOR x86_broadcast_ipi(X86_IPI_HALT); #endif if ((howto & RB_HALT) != 0) { #if NACPI > 0 && !defined(SMALL_KERNEL) extern int acpi_enabled; if (acpi_enabled) { delay(500000); if ((howto & RB_POWERDOWN) != 0) acpi_powerdown(); } #endif printf("\n"); printf("The operating system has halted.\n"); printf("Please press any key to reboot.\n\n"); cnpollc(1); /* for proper keyboard command handling */ cngetc(); cnpollc(0); } doreset: printf("rebooting...\n"); if (cpureset_delay > 0) delay(cpureset_delay * 1000); cpu_reset(); for (;;) continue; /* NOTREACHED */ } /* * These variables are needed by /sbin/savecore */ u_long dumpmag = 0x8fca0101; /* magic number */ int dumpsize = 0; /* pages */ long dumplo = 0; /* blocks */ /* * cpu_dump: dump the machine-dependent kernel core dump headers. */ int cpu_dump(void) { int (*dump)(dev_t, daddr_t, caddr_t, size_t); char buf[dbtob(1)]; kcore_seg_t *segp; cpu_kcore_hdr_t *cpuhdrp; phys_ram_seg_t *memsegp; caddr_t va; int i; dump = bdevsw[major(dumpdev)].d_dump; memset(buf, 0, sizeof buf); segp = (kcore_seg_t *)buf; cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp))]; memsegp = (phys_ram_seg_t *)&buf[ALIGN(sizeof(*segp)) + ALIGN(sizeof(*cpuhdrp))]; /* * Generate a segment header. */ CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU); segp->c_size = dbtob(1) - ALIGN(sizeof(*segp)); /* * Add the machine-dependent header info. */ cpuhdrp->ptdpaddr = proc0.p_addr->u_pcb.pcb_cr3; cpuhdrp->nmemsegs = mem_cluster_cnt; /* * Fill in the memory segment descriptors. */ for (i = 0; i < mem_cluster_cnt; i++) { memsegp[i].start = mem_clusters[i].start; memsegp[i].size = mem_clusters[i].size & ~PAGE_MASK; } /* * If we have dump memory then assume the kernel stack is in high * memory and bounce */ if (dumpmem_vaddr != 0) { memcpy((char *)dumpmem_vaddr, buf, sizeof(buf)); va = (caddr_t)dumpmem_vaddr; } else { va = (caddr_t)buf; } return (dump(dumpdev, dumplo, va, dbtob(1))); } /* * This is called by main to set dumplo and dumpsize. * Dumps always skip the first PAGE_SIZE of disk space * in case there might be a disk label stored there. * If there is extra space, put dump at the end to * reduce the chance that swapping trashes it. */ void dumpconf(void) { int nblks, dumpblks; /* size of dump area */ if (dumpdev == NODEV || (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0) return; if (nblks <= ctod(1)) return; dumpblks = cpu_dumpsize(); if (dumpblks < 0) return; dumpblks += ctod(cpu_dump_mempagecnt()); /* If dump won't fit (incl. room for possible label), punt. */ if (dumpblks > (nblks - ctod(1))) return; /* Put dump at end of partition */ dumplo = nblks - dumpblks; /* dumpsize is in page units, and doesn't include headers. */ dumpsize = cpu_dump_mempagecnt(); } /* * Doadump comes here after turning off memory management and * getting on the dump stack, either when called above, or by * the auto-restart code. */ #define BYTES_PER_DUMP MAXPHYS /* must be a multiple of pagesize */ void dumpsys(void) { u_long totalbytesleft, bytes, i, n, memseg; u_long maddr; daddr_t blkno; void *va; int (*dump)(dev_t, daddr_t, caddr_t, size_t); int error; /* Save registers. */ savectx(&dumppcb); if (dumpdev == NODEV) return; /* * For dumps during autoconfiguration, * if dump device has already configured... */ if (dumpsize == 0) dumpconf(); if (dumplo <= 0 || dumpsize == 0) { printf("\ndump to dev %u,%u not possible\n", major(dumpdev), minor(dumpdev)); return; } printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev), minor(dumpdev), dumplo); error = (*bdevsw[major(dumpdev)].d_psize)(dumpdev); printf("dump "); if (error == -1) { printf("area unavailable\n"); return; } if ((error = cpu_dump()) != 0) goto err; totalbytesleft = ptoa(cpu_dump_mempagecnt()); blkno = dumplo + cpu_dumpsize(); dump = bdevsw[major(dumpdev)].d_dump; error = 0; for (memseg = 0; memseg < mem_cluster_cnt; memseg++) { maddr = mem_clusters[memseg].start; bytes = mem_clusters[memseg].size; for (i = 0; i < bytes; i += n, totalbytesleft -= n) { /* Print out how many MBs we have left to go. */ if ((totalbytesleft % (1024*1024)) < BYTES_PER_DUMP) printf("%ld ", totalbytesleft / (1024 * 1024)); /* Limit size for next transfer. */ n = bytes - i; if (n > BYTES_PER_DUMP) n = BYTES_PER_DUMP; if (maddr > 0xffffffff) { va = (void *)dumpmem_vaddr; if (n > dumpmem_sz) n = dumpmem_sz; memcpy(va, (void *)PMAP_DIRECT_MAP(maddr), n); } else { va = (void *)PMAP_DIRECT_MAP(maddr); } error = (*dump)(dumpdev, blkno, va, n); if (error) goto err; maddr += n; blkno += btodb(n); /* XXX? */ #if 0 /* XXX this doesn't work. grr. */ /* operator aborting dump? */ if (sget() != NULL) { error = EINTR; break; } #endif } } err: switch (error) { case ENXIO: printf("device bad\n"); break; case EFAULT: printf("device not ready\n"); break; case EINVAL: printf("area improper\n"); break; case EIO: printf("i/o error\n"); break; case EINTR: printf("aborted from console\n"); break; case 0: printf("succeeded\n"); break; default: printf("error %d\n", error); break; } printf("\n\n"); delay(5000000); /* 5 seconds */ } /* * Force the userspace FS.base to be reloaded from the PCB on return from * the kernel, and reset the segment registers (%ds, %es, %fs, and %gs) * to their expected userspace value. */ void reset_segs(void) { /* * This operates like the cpu_switchto() sequence: if we * haven't reset %[defg]s already, do so now. */ if (curcpu()->ci_pflags & CPUPF_USERSEGS) { curcpu()->ci_pflags &= ~CPUPF_USERSEGS; __asm volatile( "movw %%ax,%%ds\n\t" "movw %%ax,%%es\n\t" "movw %%ax,%%fs\n\t" "cli\n\t" /* block intr when on user GS.base */ "swapgs\n\t" /* swap from kernel to user GS.base */ "movw %%ax,%%gs\n\t"/* set %gs to UDATA and GS.base to 0 */ "swapgs\n\t" /* back to kernel GS.base */ "sti" : : "a"(GSEL(GUDATA_SEL, SEL_UPL))); } } /* * Clear registers on exec */ void setregs(struct proc *p, struct exec_package *pack, u_long stack, struct ps_strings *arginfo) { struct trapframe *tf; initialize_thread_xstate(p); /* To reset all registers we have to return via iretq */ p->p_md.md_flags |= MDP_IRET; reset_segs(); p->p_addr->u_pcb.pcb_fsbase = 0; tf = p->p_md.md_regs; memset(tf, 0, sizeof *tf); tf->tf_rip = pack->ep_entry; tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL); tf->tf_rflags = PSL_USERSET; tf->tf_rsp = stack; tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL); } /* * Initialize segments and descriptor tables */ struct gate_descriptor *idt; char idt_allocmap[NIDT]; struct user *proc0paddr = NULL; void setgate(struct gate_descriptor *gd, void *func, int ist, int type, int dpl, int sel) { gd->gd_looffset = (u_int64_t)func & 0xffff; gd->gd_selector = sel; gd->gd_ist = ist; gd->gd_type = type; gd->gd_dpl = dpl; gd->gd_p = 1; gd->gd_hioffset = (u_int64_t)func >> 16; gd->gd_zero = 0; gd->gd_xx1 = 0; gd->gd_xx2 = 0; gd->gd_xx3 = 0; } void unsetgate(struct gate_descriptor *gd) { memset(gd, 0, sizeof (*gd)); } void setregion(struct region_descriptor *rd, void *base, u_int16_t limit) { rd->rd_limit = limit; rd->rd_base = (u_int64_t)base; } /* * Note that the base and limit fields are ignored in long mode. */ void set_mem_segment(struct mem_segment_descriptor *sd, void *base, size_t limit, int type, int dpl, int gran, int def32, int is64) { sd->sd_lolimit = (unsigned)limit; sd->sd_lobase = (unsigned long)base; sd->sd_type = type; sd->sd_dpl = dpl; sd->sd_p = 1; sd->sd_hilimit = (unsigned)limit >> 16; sd->sd_avl = 0; sd->sd_long = is64; sd->sd_def32 = def32; sd->sd_gran = gran; sd->sd_hibase = (unsigned long)base >> 24; } void set_sys_segment(struct sys_segment_descriptor *sd, void *base, size_t limit, int type, int dpl, int gran) { memset(sd, 0, sizeof *sd); sd->sd_lolimit = (unsigned)limit; sd->sd_lobase = (u_int64_t)base; sd->sd_type = type; sd->sd_dpl = dpl; sd->sd_p = 1; sd->sd_hilimit = (unsigned)limit >> 16; sd->sd_gran = gran; sd->sd_hibase = (u_int64_t)base >> 24; } void cpu_init_idt(void) { struct region_descriptor region; setregion(&region, idt, NIDT * sizeof(idt[0]) - 1); lidt(&region); } void cpu_init_extents(void) { extern struct extent *iomem_ex; static int already_done; int i; /* We get called for each CPU, only first should do this */ if (already_done) return; /* * Allocate the physical addresses used by RAM from the iomem * extent map. */ for (i = 0; i < mem_cluster_cnt; i++) { if (extent_alloc_region(iomem_ex, mem_clusters[i].start, mem_clusters[i].size, EX_NOWAIT)) { /* XXX What should we do? */ printf("WARNING: CAN'T ALLOCATE RAM (%llx-%llx)" " FROM IOMEM EXTENT MAP!\n", mem_clusters[i].start, mem_clusters[i].start + mem_clusters[i].size - 1); } } already_done = 1; } void map_tramps(void) { #if defined(MULTIPROCESSOR) || \ (NACPI > 0 && !defined(SMALL_KERNEL)) struct pmap *kmp = pmap_kernel(); extern paddr_t tramp_pdirpa; #ifdef MULTIPROCESSOR extern u_char cpu_spinup_trampoline[]; extern u_char cpu_spinup_trampoline_end[]; extern u_char mp_tramp_data_start[]; extern u_char mp_tramp_data_end[]; extern u_int32_t mp_pdirpa; #endif /* * The initial PML4 pointer must be below 4G, so if the * current one isn't, use a "bounce buffer" and save it * for tramps to use. */ if (kmp->pm_pdirpa > 0xffffffff) { pmap_kenter_pa(lo32_vaddr, lo32_paddr, PROT_READ | PROT_WRITE); memcpy((void *)lo32_vaddr, kmp->pm_pdir, PAGE_SIZE); tramp_pdirpa = lo32_paddr; pmap_kremove(lo32_vaddr, PAGE_SIZE); } else tramp_pdirpa = kmp->pm_pdirpa; #ifdef MULTIPROCESSOR /* Map MP tramp code and data pages RW for copy */ pmap_kenter_pa(MP_TRAMPOLINE, MP_TRAMPOLINE, PROT_READ | PROT_WRITE); pmap_kenter_pa(MP_TRAMP_DATA, MP_TRAMP_DATA, PROT_READ | PROT_WRITE); memset((caddr_t)MP_TRAMPOLINE, 0xcc, PAGE_SIZE); memset((caddr_t)MP_TRAMP_DATA, 0xcc, PAGE_SIZE); memcpy((caddr_t)MP_TRAMPOLINE, cpu_spinup_trampoline, cpu_spinup_trampoline_end-cpu_spinup_trampoline); memcpy((caddr_t)MP_TRAMP_DATA, mp_tramp_data_start, mp_tramp_data_end - mp_tramp_data_start); /* * We need to patch this after we copy the tramp data, * the symbol points into the copied tramp data page. */ mp_pdirpa = tramp_pdirpa; /* Unmap, will be remapped in cpu_start_secondary */ pmap_kremove(MP_TRAMPOLINE, PAGE_SIZE); pmap_kremove(MP_TRAMP_DATA, PAGE_SIZE); #endif /* MULTIPROCESSOR */ #endif } void cpu_set_vendor(struct cpu_info *ci, int level, const char *vendor) { ci->ci_cpuid_level = level; cpuid_level = MIN(cpuid_level, level); /* map the vendor string to an integer */ if (strcmp(vendor, "AuthenticAMD") == 0) ci->ci_vendor = CPUV_AMD; else if (strcmp(vendor, "GenuineIntel") == 0) ci->ci_vendor = CPUV_INTEL; else if (strcmp(vendor, "CentaurHauls") == 0) ci->ci_vendor = CPUV_VIA; else ci->ci_vendor = CPUV_UNKNOWN; } #define IDTVEC(name) __CONCAT(X, name) typedef void (vector)(void); extern vector *IDTVEC(exceptions)[]; paddr_t early_pte_pages; void init_x86_64(paddr_t first_avail) { struct region_descriptor region; bios_memmap_t *bmp; int x, ist; uint64_t max_dm_size = ((uint64_t)512 * NUM_L4_SLOT_DIRECT) << 30; /* * locore0 mapped 3 pages for use before the pmap is initialized * starting at first_avail. These pages are currently used by * efifb to create early-use VAs for the framebuffer before efifb * is attached. */ early_pte_pages = first_avail; first_avail += 3 * NBPG; cpu_set_vendor(&cpu_info_primary, cpuid_level, cpu_vendor); cpu_init_msrs(&cpu_info_primary); proc0.p_addr = proc0paddr; cpu_info_primary.ci_curpcb = &proc0.p_addr->u_pcb; x86_bus_space_init(); i8254_startclock(); /* * Initialize PAGE_SIZE-dependent variables. */ uvm_setpagesize(); /* * Boot arguments are in a single page specified by /boot. * * We require the "new" vector form, as well as memory ranges * to be given in bytes rather than KB. * * locore copies the data into bootinfo[] for us. */ if ((bootapiver & (BAPIV_VECTOR | BAPIV_BMEMMAP)) == (BAPIV_VECTOR | BAPIV_BMEMMAP)) { if (bootinfo_size >= sizeof(bootinfo)) panic("boot args too big"); getbootinfo(bootinfo, bootinfo_size); } else panic("invalid /boot"); cninit(); /* * Memory on the AMD64 port is described by three different things. * * 1. biosbasemem - This is outdated, and should really only be used to * sanitize the other values. This is what we get back from the BIOS * using the legacy routines, describing memory below 640KB. * * 2. bios_memmap[] - This is the memory map as the bios has returned * it to us. It includes memory the kernel occupies, etc. * * 3. mem_cluster[] - This is the massaged free memory segments after * taking into account the contents of bios_memmap, biosbasemem, * and locore/machdep/pmap kernel allocations of physical * pages. * * The other thing is that the physical page *RANGE* is described by * three more variables: * * avail_start - This is a physical address of the start of available * pages, until IOM_BEGIN. This is basically the start * of the UVM managed range of memory, with some holes... * * avail_end - This is the end of physical pages. All physical pages * that UVM manages are between avail_start and avail_end. * There are holes... * * first_avail - This is the first available physical page after the * kernel, page tables, etc. * * We skip the first few pages for trampolines, hibernate, and to avoid * buggy SMI implementations that could corrupt the first 64KB. */ avail_start = 16*PAGE_SIZE; #ifdef MULTIPROCESSOR if (avail_start < MP_TRAMPOLINE + PAGE_SIZE) avail_start = MP_TRAMPOLINE + PAGE_SIZE; if (avail_start < MP_TRAMP_DATA + PAGE_SIZE) avail_start = MP_TRAMP_DATA + PAGE_SIZE; #endif #if (NACPI > 0 && !defined(SMALL_KERNEL)) if (avail_start < ACPI_TRAMPOLINE + PAGE_SIZE) avail_start = ACPI_TRAMPOLINE + PAGE_SIZE; if (avail_start < ACPI_TRAMP_DATA + PAGE_SIZE) avail_start = ACPI_TRAMP_DATA + PAGE_SIZE; #endif #ifdef HIBERNATE if (avail_start < HIBERNATE_HIBALLOC_PAGE + PAGE_SIZE) avail_start = HIBERNATE_HIBALLOC_PAGE + PAGE_SIZE; #endif /* HIBERNATE */ /* * We need to go through the BIOS memory map given, and * fill out mem_clusters and mem_cluster_cnt stuff, taking * into account all the points listed above. */ avail_end = mem_cluster_cnt = 0; for (bmp = bios_memmap; bmp->type != BIOS_MAP_END; bmp++) { paddr_t s1, s2, e1, e2; /* Ignore non-free memory */ if (bmp->type != BIOS_MAP_FREE) continue; if (bmp->size < PAGE_SIZE) continue; /* Init our segment(s), round/trunc to pages */ s1 = round_page(bmp->addr); e1 = trunc_page(bmp->addr + bmp->size); s2 = e2 = 0; /* * XXX Some buggy ACPI BIOSes use memory that they * declare as free. Current worst offender is * Supermicro 5019D-FTN4. Typically the affected memory * areas are small blocks between areas reserved for * ACPI and other BIOS goo. So skip areas smaller * than 32 MB above the 16 MB boundary (to avoid * affecting legacy stuff). */ if (s1 > 16*1024*1024 && (e1 - s1) < 32*1024*1024) continue; /* Check and adjust our segment(s) */ /* Nuke low pages */ if (s1 < avail_start) { s1 = avail_start; if (s1 > e1) continue; } /* * The direct map is limited to 512GB * NUM_L4_SLOT_DIRECT of * memory, so discard anything above that. */ if (e1 >= max_dm_size) { e1 = max_dm_size; if (s1 > e1) continue; } /* Crop stuff into "640K hole" */ if (s1 < IOM_BEGIN && e1 > IOM_BEGIN) e1 = IOM_BEGIN; if (s1 < biosbasemem && e1 > biosbasemem) e1 = biosbasemem; /* Split any segments straddling the 16MB boundary */ if (s1 < 16*1024*1024 && e1 > 16*1024*1024) { e2 = e1; s2 = e1 = 16*1024*1024; } /* Store segment(s) */ if (e1 - s1 >= PAGE_SIZE) { mem_clusters[mem_cluster_cnt].start = s1; mem_clusters[mem_cluster_cnt].size = e1 - s1; mem_cluster_cnt++; } if (e2 - s2 >= PAGE_SIZE) { mem_clusters[mem_cluster_cnt].start = s2; mem_clusters[mem_cluster_cnt].size = e2 - s2; mem_cluster_cnt++; } if (avail_end < e1) avail_end = e1; if (avail_end < e2) avail_end = e2; } /* * Call pmap initialization to make new kernel address space. * We must do this before loading pages into the VM system. */ first_avail = pmap_bootstrap(first_avail, trunc_page(avail_end)); #if NEFI > 0 /* Relocate the EFI memory map. */ if (bios_efiinfo && bios_efiinfo->mmap_start) { mmap = (EFI_MEMORY_DESCRIPTOR *)PMAP_DIRECT_MAP(first_avail); memcpy(mmap, (void *)PMAP_DIRECT_MAP(bios_efiinfo->mmap_start), bios_efiinfo->mmap_size); first_avail += round_page(bios_efiinfo->mmap_size); } #endif /* Allocate these out of the 640KB base memory */ if (avail_start != PAGE_SIZE) avail_start = pmap_prealloc_lowmem_ptps(avail_start); cpu_init_extents(); /* Make sure the end of the space used by the kernel is rounded. */ first_avail = round_page(first_avail); kern_end = KERNBASE + first_avail; /* * Now, load the memory clusters (which have already been * flensed) into the VM system. */ for (x = 0; x < mem_cluster_cnt; x++) { paddr_t seg_start = mem_clusters[x].start; paddr_t seg_end = seg_start + mem_clusters[x].size; if (seg_start < first_avail) seg_start = first_avail; if (seg_start > seg_end) continue; if (seg_end - seg_start < PAGE_SIZE) continue; physmem += atop(mem_clusters[x].size); #if DEBUG_MEMLOAD printf("loading 0x%lx-0x%lx (0x%lx-0x%lx)\n", seg_start, seg_end, atop(seg_start), atop(seg_end)); #endif uvm_page_physload(atop(seg_start), atop(seg_end), atop(seg_start), atop(seg_end), 0); } /* * Now, load the memory between the end of I/O memory "hole" * and the kernel. */ { paddr_t seg_start = round_page(IOM_END); paddr_t seg_end = trunc_page(KERNTEXTOFF - KERNBASE); if (seg_start < seg_end) { #if DEBUG_MEMLOAD printf("loading 0x%lx-0x%lx\n", seg_start, seg_end); #endif uvm_page_physload(atop(seg_start), atop(seg_end), atop(seg_start), atop(seg_end), 0); } } #if DEBUG_MEMLOAD printf("avail_start = 0x%lx\n", avail_start); printf("avail_end = 0x%lx\n", avail_end); printf("first_avail = 0x%lx\n", first_avail); #endif /* * Steal memory for the message buffer (at end of core). */ { struct vm_physseg *vps = NULL; psize_t sz = round_page(MSGBUFSIZE); psize_t reqsz = sz; for (x = 0; x < vm_nphysseg; x++) { vps = &vm_physmem[x]; if (ptoa(vps->avail_end) == avail_end) break; } if (x == vm_nphysseg) panic("init_x86_64: can't find end of memory"); /* Shrink so it'll fit in the last segment. */ if ((vps->avail_end - vps->avail_start) < atop(sz)) sz = ptoa(vps->avail_end - vps->avail_start); vps->avail_end -= atop(sz); vps->end -= atop(sz); msgbuf_paddr = ptoa(vps->avail_end); /* Remove the last segment if it now has no pages. */ if (vps->start == vps->end) { for (vm_nphysseg--; x < vm_nphysseg; x++) vm_physmem[x] = vm_physmem[x + 1]; } /* Now find where the new avail_end is. */ for (avail_end = 0, x = 0; x < vm_nphysseg; x++) if (vm_physmem[x].avail_end > avail_end) avail_end = vm_physmem[x].avail_end; avail_end = ptoa(avail_end); /* Warn if the message buffer had to be shrunk. */ if (sz != reqsz) printf("WARNING: %ld bytes not available for msgbuf " "in last cluster (%ld used)\n", reqsz, sz); } /* * Steal some memory for a dump bouncebuffer if we have memory over * the 32-bit barrier. */ if (avail_end > 0xffffffff) { struct vm_physseg *vps = NULL; psize_t sz = round_page(MAX(BYTES_PER_DUMP, dbtob(1))); /* XXX assumes segments are ordered */ for (x = 0; x < vm_nphysseg; x++) { vps = &vm_physmem[x]; /* Find something between 16meg and 4gig */ if (ptoa(vps->avail_end) <= 0xffffffff && ptoa(vps->avail_start) >= 0xffffff) break; } if (x == vm_nphysseg) panic("init_x86_64: no memory between " "0xffffff-0xffffffff"); /* Shrink so it'll fit in the segment. */ if ((vps->avail_end - vps->avail_start) < atop(sz)) sz = ptoa(vps->avail_end - vps->avail_start); vps->avail_end -= atop(sz); vps->end -= atop(sz); dumpmem_paddr = ptoa(vps->avail_end); dumpmem_vaddr = PMAP_DIRECT_MAP(dumpmem_paddr); dumpmem_sz = sz; /* Remove the last segment if it now has no pages. */ if (vps->start == vps->end) { for (vm_nphysseg--; x < vm_nphysseg; x++) vm_physmem[x] = vm_physmem[x + 1]; } } pmap_growkernel(VM_MIN_KERNEL_ADDRESS + 32 * 1024 * 1024); pmap_kenter_pa(idt_vaddr, idt_paddr, PROT_READ | PROT_WRITE); idt = (struct gate_descriptor *)idt_vaddr; cpu_info_primary.ci_tss = &cpu_info_full_primary.cif_tss; cpu_info_primary.ci_gdt = &cpu_info_full_primary.cif_gdt; /* make gdt gates and memory segments */ set_mem_segment(GDT_ADDR_MEM(cpu_info_primary.ci_gdt, GCODE_SEL), 0, 0xfffff, SDT_MEMERA, SEL_KPL, 1, 0, 1); set_mem_segment(GDT_ADDR_MEM(cpu_info_primary.ci_gdt, GDATA_SEL), 0, 0xfffff, SDT_MEMRWA, SEL_KPL, 1, 0, 1); set_mem_segment(GDT_ADDR_MEM(cpu_info_primary.ci_gdt, GUDATA_SEL), 0, atop(VM_MAXUSER_ADDRESS) - 1, SDT_MEMRWA, SEL_UPL, 1, 0, 1); set_mem_segment(GDT_ADDR_MEM(cpu_info_primary.ci_gdt, GUCODE_SEL), 0, atop(VM_MAXUSER_ADDRESS) - 1, SDT_MEMERA, SEL_UPL, 1, 0, 1); set_sys_segment(GDT_ADDR_SYS(cpu_info_primary.ci_gdt, GPROC0_SEL), cpu_info_primary.ci_tss, sizeof (struct x86_64_tss)-1, SDT_SYS386TSS, SEL_KPL, 0); /* exceptions */ for (x = 0; x < 32; x++) { /* trap2 == NMI, trap8 == double fault */ ist = (x == 2) ? 2 : (x == 8) ? 1 : 0; setgate(&idt[x], IDTVEC(exceptions)[x], ist, SDT_SYS386IGT, (x == 3) ? SEL_UPL : SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); idt_allocmap[x] = 1; } setregion(&region, cpu_info_primary.ci_gdt, GDT_SIZE - 1); lgdt(&region); cpu_init_idt(); intr_default_setup(); fpuinit(&cpu_info_primary); softintr_init(); splraise(IPL_IPI); intr_enable(); #ifdef DDB db_machine_init(); ddb_init(); if (boothowto & RB_KDB) db_enter(); #endif } void cpu_reset(void) { intr_disable(); if (cpuresetfn) (*cpuresetfn)(); /* * The keyboard controller has 4 random output pins, one of which is * connected to the RESET pin on the CPU in many PCs. We tell the * keyboard controller to pulse this line a couple of times. */ outb(IO_KBD + KBCMDP, KBC_PULSE0); delay(100000); outb(IO_KBD + KBCMDP, KBC_PULSE0); delay(100000); /* * Try to cause a triple fault and watchdog reset by making the IDT * invalid and causing a fault. */ memset((caddr_t)idt, 0, NIDT * sizeof(idt[0])); __asm volatile("divl %0,%1" : : "q" (0), "a" (0)); for (;;) continue; /* NOTREACHED */ } /* * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers. */ int cpu_dumpsize(void) { int size; size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(mem_cluster_cnt * sizeof(phys_ram_seg_t)); if (roundup(size, dbtob(1)) != dbtob(1)) return (-1); return (1); } /* * cpu_dump_mempagecnt: calculate the size of RAM (in pages) to be dumped. */ u_long cpu_dump_mempagecnt(void) { u_long i, n; n = 0; for (i = 0; i < mem_cluster_cnt; i++) n += atop(mem_clusters[i].size); return (n); } /* * Figure out which portions of memory are used by the kernel/system. */ int amd64_pa_used(paddr_t addr) { struct vm_page *pg; /* Kernel manages these */ if ((pg = PHYS_TO_VM_PAGE(addr)) && (pg->pg_flags & PG_DEV) == 0) return 1; /* Kernel is loaded here */ if (addr > IOM_END && addr < (kern_end - KERNBASE)) return 1; /* Low memory used for various bootstrap things */ if (addr < avail_start) return 1; /* * The only regions I can think of that are left are the things * we steal away from UVM. The message buffer? * XXX - ignore these for now. */ return 0; } void cpu_initclocks(void) { (*initclock_func)(); } void cpu_startclock(void) { (*startclock_func)(); } void need_resched(struct cpu_info *ci) { ci->ci_want_resched = 1; /* There's a risk we'll be called before the idle threads start */ if (ci->ci_curproc) { aston(ci->ci_curproc); cpu_kick(ci); } } /* * Allocate an IDT vector slot within the given range. * XXX needs locking to avoid MP allocation races. */ int idt_vec_alloc(int low, int high) { int vec; for (vec = low; vec <= high; vec++) { if (idt_allocmap[vec] == 0) { idt_allocmap[vec] = 1; return vec; } } return 0; } int idt_vec_alloc_range(int low, int high, int num) { int i, vec; KASSERT(powerof2(num)); low = (low + num - 1) & ~(num - 1); high = ((high + 1) & ~(num - 1)) - 1; for (vec = low; vec <= high; vec += num) { for (i = 0; i < num; i++) { if (idt_allocmap[vec + i] != 0) break; } if (i == num) { for (i = 0; i < num; i++) idt_allocmap[vec + i] = 1; return vec; } } return 0; } void idt_vec_set(int vec, void (*function)(void)) { /* * Vector should be allocated, so no locking needed. */ KASSERT(idt_allocmap[vec] == 1); setgate(&idt[vec], function, 0, SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); } void idt_vec_free(int vec) { unsetgate(&idt[vec]); idt_allocmap[vec] = 0; } #ifdef DIAGNOSTIC void splassert_check(int wantipl, const char *func) { int cpl = curcpu()->ci_ilevel; int floor = curcpu()->ci_handled_intr_level; if (cpl < wantipl) { splassert_fail(wantipl, cpl, func); } if (floor > wantipl) { splassert_fail(wantipl, floor, func); } } #endif int copyin32(const uint32_t *uaddr, uint32_t *kaddr) { if ((vaddr_t)uaddr & 0x3) return EFAULT; /* copyin(9) is atomic */ return copyin(uaddr, kaddr, sizeof(uint32_t)); } void getbootinfo(char *bootinfo, int bootinfo_size) { bootarg32_t *q; bios_ddb_t *bios_ddb; bios_bootduid_t *bios_bootduid; bios_bootsr_t *bios_bootsr; #undef BOOTINFO_DEBUG #ifdef BOOTINFO_DEBUG printf("bootargv:"); #endif for (q = (bootarg32_t *)bootinfo; (q->ba_type != BOOTARG_END) && ((((char *)q) - bootinfo) < bootinfo_size); q = (bootarg32_t *)(((char *)q) + q->ba_size)) { switch (q->ba_type) { case BOOTARG_MEMMAP: bios_memmap = (bios_memmap_t *)q->ba_arg; #ifdef BOOTINFO_DEBUG printf(" memmap %p", bios_memmap); #endif break; case BOOTARG_DISKINFO: bios_diskinfo = (bios_diskinfo_t *)q->ba_arg; #ifdef BOOTINFO_DEBUG printf(" diskinfo %p", bios_diskinfo); #endif break; case BOOTARG_APMINFO: /* generated by i386 boot loader */ break; case BOOTARG_CKSUMLEN: bios_cksumlen = *(u_int32_t *)q->ba_arg; #ifdef BOOTINFO_DEBUG printf(" cksumlen %d", bios_cksumlen); #endif break; case BOOTARG_PCIINFO: /* generated by i386 boot loader */ break; case BOOTARG_CONSDEV: { #if NCOM > 0 bios_consdev_t *cdp = (bios_consdev_t*)q->ba_arg; static const int ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; int unit = minor(cdp->consdev); uint64_t consaddr = cdp->consaddr; if (consaddr == -1 && unit >= 0 && unit < nitems(ports)) consaddr = ports[unit]; if (major(cdp->consdev) == 8 && consaddr != -1) { comconsunit = unit; comconsaddr = consaddr; comconsrate = cdp->conspeed; comconsfreq = cdp->consfreq; comcons_reg_width = cdp->reg_width; comcons_reg_shift = cdp->reg_shift; if (cdp->flags & BCD_MMIO) comconsiot = X86_BUS_SPACE_MEM; else comconsiot = X86_BUS_SPACE_IO; } #endif #ifdef BOOTINFO_DEBUG printf(" console 0x%x:%d", cdp->consdev, cdp->conspeed); #endif break; } case BOOTARG_BOOTMAC: bios_bootmac = (bios_bootmac_t *)q->ba_arg; break; case BOOTARG_DDB: bios_ddb = (bios_ddb_t *)q->ba_arg; #ifdef DDB db_console = bios_ddb->db_console; #endif break; case BOOTARG_BOOTDUID: bios_bootduid = (bios_bootduid_t *)q->ba_arg; memcpy(bootduid, bios_bootduid, sizeof(bootduid)); break; case BOOTARG_BOOTSR: bios_bootsr = (bios_bootsr_t *)q->ba_arg; #if NSOFTRAID > 0 memcpy(&sr_bootuuid, &bios_bootsr->uuid, sizeof(sr_bootuuid)); memcpy(&sr_bootkey, &bios_bootsr->maskkey, sizeof(sr_bootkey)); #endif explicit_bzero(bios_bootsr, sizeof(bios_bootsr_t)); break; case BOOTARG_EFIINFO: bios_efiinfo = (bios_efiinfo_t *)q->ba_arg; break; case BOOTARG_UCODE: bios_ucode = (bios_ucode_t *)q->ba_arg; break; default: #ifdef BOOTINFO_DEBUG printf(" unsupported arg (%d) %p", q->ba_type, q->ba_arg); #endif break; } } #ifdef BOOTINFO_DEBUG printf("\n"); #endif } int check_context(const struct reg *regs, struct trapframe *tf) { uint16_t sel; if (((regs->r_rflags ^ tf->tf_rflags) & PSL_USERSTATIC) != 0) return EINVAL; sel = regs->r_ss & 0xffff; if (!VALID_USER_DSEL(sel)) return EINVAL; sel = regs->r_cs & 0xffff; if (!VALID_USER_CSEL(sel)) return EINVAL; if (regs->r_rip >= VM_MAXUSER_ADDRESS) return EINVAL; return 0; } int amd64_delay_quality; void delay_init(void(*fn)(int), int fn_quality) { if (fn_quality > amd64_delay_quality) { delay_func = fn; amd64_delay_quality = fn_quality; } } void delay_fini(void (*fn)(int)) { if (fn == delay_func) { delay_func = i8254_delay; amd64_delay_quality = 0; } }
1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 /* $OpenBSD: bktr_os.c,v 1.37 2022/07/02 08:50:42 visa Exp $ */ /* $FreeBSD: src/sys/dev/bktr/bktr_os.c,v 1.20 2000/10/20 08:16:53 roger Exp $ */ /* * This is part of the Driver for Video Capture Cards (Frame grabbers) * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 * chipset. * Copyright Roger Hardiman and Amancio Hasty. * * bktr_os : This has all the Operating System dependant code, * probe/attach and open/close/ioctl/read/mmap * memory allocation * PCI bus interfacing * * */ /* * 1. Redistributions of source code must retain the * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Amancio Hasty and * Roger Hardiman * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #define FIFO_RISC_DISABLED 0 #define ALL_INTS_DISABLED 0 #include "radio.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/conf.h> #include <sys/uio.h> #include <sys/kernel.h> #include <sys/signalvar.h> #include <sys/mman.h> #include <sys/vnode.h> #if NRADIO > 0 #include <sys/radioio.h> #include <dev/radio_if.h> #endif #include <uvm/uvm_extern.h> #include <sys/device.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcireg.h> #include <dev/pci/pcidevs.h> #ifdef BKTR_DEBUG int bktr_debug = 1; #define DPR(x) (bktr_debug ? printf x : 0) #else #define DPR(x) #endif #include <dev/ic/bt8xx.h> /* OpenBSD location for .h files */ #include <dev/pci/bktr/bktr_reg.h> #include <dev/pci/bktr/bktr_tuner.h> #include <dev/pci/bktr/bktr_audio.h> #include <dev/pci/bktr/bktr_core.h> #include <dev/pci/bktr/bktr_os.h> #define IPL_VIDEO IPL_BIO /* XXX */ static int bktr_intr(void *arg) { return common_bktr_intr(arg); } #define bktr_open bktropen #define bktr_close bktrclose #define bktr_read bktrread #define bktr_write bktrwrite #define bktr_ioctl bktrioctl #define bktr_mmap bktrmmap int bktr_open(dev_t, int, int, struct proc *); int bktr_close(dev_t, int, int, struct proc *); int bktr_read(dev_t, struct uio *, int); int bktr_write(dev_t, struct uio *, int); int bktr_ioctl(dev_t, ioctl_cmd_t, caddr_t, int, struct proc *); paddr_t bktr_mmap(dev_t, off_t, int); static int bktr_probe(struct device *, void *, void *); static void bktr_attach(struct device *, struct device *, void *); const struct cfattach bktr_ca = { sizeof(struct bktr_softc), bktr_probe, bktr_attach }; struct cfdriver bktr_cd = { NULL, "bktr", DV_DULL }; #if NRADIO > 0 /* for radio(4) */ int bktr_get_info(void *, struct radio_info *); int bktr_set_info(void *, struct radio_info *); const struct radio_hw_if bktr_hw_if = { NULL, /* open */ NULL, /* close */ bktr_get_info, bktr_set_info, NULL /* search */ }; #endif int bktr_probe(struct device *parent, void *match, void *aux) { struct pci_attach_args *pa = aux; if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROOKTREE && (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT848 || PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT849 || PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT878 || PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT879)) return 1; return 0; } /* * the attach routine. */ static void bktr_attach(struct device *parent, struct device *self, void *aux) { bktr_ptr_t bktr; u_int latency; u_int fun; unsigned int rev; struct pci_attach_args *pa = aux; pci_intr_handle_t ih; const char *intrstr; int retval; int unit; bktr = (bktr_ptr_t)self; unit = bktr->bktr_dev.dv_unit; bktr->dmat = pa->pa_dmat; /* Enable Back-to-Back XXX: check if all old DMA is stopped first (e.g. after warm boot) */ fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); DPR((" fun=%b", fun, PCI_COMMAND_STATUS_BITS)); pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, fun | PCI_COMMAND_BACKTOBACK_ENABLE); /* * map memory */ retval = pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &bktr->memt, &bktr->memh, NULL, &bktr->obmemsz, 0); DPR(("pci_mapreg_map: memt %lx, memh %lx, size %x\n", bktr->memt, bktr->memh, bktr->obmemsz)); if (retval) { printf("%s: can't map mem space\n", bktr_name(bktr)); return; } /* * Disable the brooktree device */ OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); /* * map interrupt */ if (pci_intr_map(pa, &ih)) { printf("%s: can't map interrupt\n", bktr_name(bktr)); return; } intrstr = pci_intr_string(pa->pa_pc, ih); bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, bktr_intr, bktr, bktr->bktr_dev.dv_xname); if (bktr->ih == NULL) { printf("%s: can't establish interrupt", bktr_name(bktr)); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); return; } if (intrstr != NULL) printf(": %s\n", intrstr); /* * PCI latency timer. 32 is a good value for 4 bus mastering slots, if * you have more than four, then 16 would probably be a better value. */ #ifndef BROOKTREE_DEF_LATENCY_VALUE #define BROOKTREE_DEF_LATENCY_VALUE 0x10 #endif latency = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER); latency = (latency >> 8) & 0xff; if (!latency) { if (bootverbose) { printf("%s: PCI bus latency was 0 changing to %d", bktr_name(bktr), BROOKTREE_DEF_LATENCY_VALUE); } latency = BROOKTREE_DEF_LATENCY_VALUE; pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER, latency<<8); } /* read the pci id and determine the card type */ fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG); rev = PCI_REVISION(pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG)); common_bktr_attach(bktr, unit, fun, rev); #if NRADIO > 0 if (bktr->card.tuner->pllControl[3] != 0x00) radio_attach_mi(&bktr_hw_if, bktr, &bktr->bktr_dev); #endif } /* * Special Memory Allocation */ vaddr_t get_bktr_mem(bktr_ptr_t bktr, bus_dmamap_t *dmapp, unsigned int size) { bus_dma_tag_t dmat = bktr->dmat; bus_dma_segment_t seg; bus_size_t align; int rseg; caddr_t kva; /* * Allocate a DMA area */ align = 1 << 24; if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) { align = PAGE_SIZE; if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) { printf("%s: Unable to dmamem_alloc of %d bytes\n", bktr_name(bktr), size); return 0; } } if (bus_dmamem_map(dmat, &seg, rseg, size, &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) { printf("%s: Unable to dmamem_map of %d bytes\n", bktr_name(bktr), size); bus_dmamem_free(dmat, &seg, rseg); return 0; } /* * Create and locd the DMA map for the DMA area */ if (bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_NOWAIT, dmapp)) { printf("%s: Unable to dmamap_create of %d bytes\n", bktr_name(bktr), size); bus_dmamem_unmap(dmat, kva, size); bus_dmamem_free(dmat, &seg, rseg); return 0; } if (bus_dmamap_load(dmat, *dmapp, kva, size, NULL, BUS_DMA_NOWAIT)) { printf("%s: Unable to dmamap_load of %d bytes\n", bktr_name(bktr), size); bus_dmamem_unmap(dmat, kva, size); bus_dmamem_free(dmat, &seg, rseg); bus_dmamap_destroy(dmat, *dmapp); return 0; } return (vaddr_t)kva; } void free_bktr_mem(bktr_ptr_t bktr, bus_dmamap_t dmap, vaddr_t kva) { bus_dma_tag_t dmat = bktr->dmat; bus_dmamem_unmap(dmat, (caddr_t)kva, dmap->dm_mapsize); bus_dmamem_free(dmat, dmap->dm_segs, 1); bus_dmamap_destroy(dmat, dmap); } /*--------------------------------------------------------- ** ** BrookTree 848 character device driver routines ** **--------------------------------------------------------- */ #define VIDEO_DEV 0x00 #define TUNER_DEV 0x01 #define VBI_DEV 0x02 #define UNIT(x) ((minor((x)) < 16) ? minor((x)) : ((minor((x)) - 16) / 2)) #define FUNCTION(x) ((minor((x)) < 16) ? VIDEO_DEV : ((minor((x)) & 0x1) ? \ VBI_DEV : TUNER_DEV)) /* * */ int bktr_open(dev_t dev, int flags, int fmt, struct proc *p) { bktr_ptr_t bktr; int unit; unit = UNIT(dev); /* unit out of range */ if ((unit >= bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL)) return(ENXIO); bktr = bktr_cd.cd_devs[unit]; if (!(bktr->flags & METEOR_INITIALIZED)) /* device not found */ return(ENXIO); switch (FUNCTION(dev)) { case VIDEO_DEV: return(video_open(bktr)); case TUNER_DEV: return(tuner_open(bktr)); case VBI_DEV: return(vbi_open(bktr)); } return(ENXIO); } /* * */ int bktr_close(dev_t dev, int flags, int fmt, struct proc *p) { bktr_ptr_t bktr; int unit; unit = UNIT(dev); bktr = bktr_cd.cd_devs[unit]; switch (FUNCTION(dev)) { case VIDEO_DEV: return(video_close(bktr)); case TUNER_DEV: return(tuner_close(bktr)); case VBI_DEV: return(vbi_close(bktr)); } return(ENXIO); } /* * */ int bktr_read(dev_t dev, struct uio *uio, int ioflag) { bktr_ptr_t bktr; int unit; unit = UNIT(dev); bktr = bktr_cd.cd_devs[unit]; switch (FUNCTION(dev)) { case VIDEO_DEV: return(video_read(bktr, unit, dev, uio)); case VBI_DEV: return(vbi_read(bktr, uio, ioflag)); } return(ENXIO); } /* * */ int bktr_write(dev_t dev, struct uio *uio, int ioflag) { /* operation not supported */ return(EOPNOTSUPP); } /* * */ int bktr_ioctl(dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct proc* pr) { bktr_ptr_t bktr; int unit; unit = UNIT(dev); bktr = bktr_cd.cd_devs[unit]; if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ return(ENOMEM); switch (FUNCTION(dev)) { case VIDEO_DEV: return(video_ioctl(bktr, unit, cmd, arg, pr)); case TUNER_DEV: return(tuner_ioctl(bktr, unit, cmd, arg, pr)); } return(ENXIO); } /* * */ paddr_t bktr_mmap(dev_t dev, off_t offset, int nprot) { int unit; bktr_ptr_t bktr; unit = UNIT(dev); if (FUNCTION(dev) > 0) /* only allow mmap on /dev/bktr[n] */ return(-1); bktr = bktr_cd.cd_devs[unit]; if (offset < 0) return(-1); if (offset >= bktr->alloc_pages * PAGE_SIZE) return(-1); return (bus_dmamem_mmap(bktr->dmat, bktr->dm_mem->dm_segs, 1, offset, nprot, BUS_DMA_WAITOK)); } #if NRADIO > 0 int bktr_set_info(void *v, struct radio_info *ri) { struct bktr_softc *sc = v; struct TVTUNER *tv = &sc->tuner; u_int32_t freq; u_int32_t chan; if (ri->mute) { /* mute the audio stream by switching the mux */ set_audio(sc, AUDIO_MUTE); } else { /* unmute the audio stream */ set_audio(sc, AUDIO_UNMUTE); init_audio_devices(sc); } set_audio(sc, AUDIO_INTERN); /* use internal audio */ temp_mute(sc, TRUE); if (ri->tuner_mode == RADIO_TUNER_MODE_TV) { if (ri->chan) { if (ri->chan < MIN_TV_CHAN) ri->chan = MIN_TV_CHAN; if (ri->chan > MAX_TV_CHAN) ri->chan = MAX_TV_CHAN; chan = ri->chan; ri->chan = tv_channel(sc, chan); tv->tuner_mode = BT848_TUNER_MODE_TV; } else { ri->chan = tv->channel; } } else { if (ri->freq) { if (ri->freq < MIN_FM_FREQ) ri->freq = MIN_FM_FREQ; if (ri->freq > MAX_FM_FREQ) ri->freq = MAX_FM_FREQ; freq = ri->freq / 10; ri->freq = tv_freq(sc, freq, FM_RADIO_FREQUENCY) * 10; tv->tuner_mode = BT848_TUNER_MODE_RADIO; } else { ri->freq = tv->frequency; } } if (ri->chnlset >= CHNLSET_MIN && ri->chnlset <= CHNLSET_MAX) tv->chnlset = ri->chnlset; else tv->chnlset = DEFAULT_CHNLSET; temp_mute(sc, FALSE); return (0); } int bktr_get_info(void *v, struct radio_info *ri) { struct bktr_softc *sc = v; struct TVTUNER *tv = &sc->tuner; int status; status = get_tuner_status(sc); #define STATUSBIT_STEREO 0x10 ri->mute = (int)sc->audio_mute_state ? 1 : 0; ri->caps = RADIO_CAPS_DETECT_STEREO | RADIO_CAPS_HW_AFC; ri->info = (status & STATUSBIT_STEREO) ? RADIO_INFO_STEREO : 0; /* not yet supported */ ri->volume = ri->rfreq = ri->lock = 0; switch (tv->tuner_mode) { case BT848_TUNER_MODE_TV: ri->tuner_mode = RADIO_TUNER_MODE_TV; ri->freq = tv->frequency * 1000 / 16; break; case BT848_TUNER_MODE_RADIO: ri->tuner_mode = RADIO_TUNER_MODE_RADIO; ri->freq = tv->frequency * 10; break; } /* * The field ri->stereo is used to forcible switch to * mono/stereo, not as an indicator of received signal quality. * The ri->info is for that purpose. */ ri->stereo = 1; /* Can't switch to mono, always stereo */ ri->chan = tv->channel; ri->chnlset = tv->chnlset; return (0); } #endif /* NRADIO */
10 2 8 2 2 5 5 12 7 2 1 3 6 4 1 61 4 6 1 2 1 1 18 1 4 5 21 7 9 9 1 1 1 1 1 1 4 2 1 1 2 2 1 1 1 1 1 1 7 5 3 2 2 17 1 9 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 /* $OpenBSD: vnd.c,v 1.181 2023/05/14 18:34:02 krw Exp $ */ /* $NetBSD: vnd.c,v 1.26 1996/03/30 23:06:11 christos Exp $ */ /* * Copyright (c) 1988 University of Utah. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * There is a security issue involved with this driver. * * Once mounted all access to the contents of the "mapped" file via * the special file is controlled by the permissions on the special * file, the protection of the mapped file is ignored (effectively, * by using root credentials in all transactions). * */ #include <sys/param.h> #include <sys/systm.h> #include <sys/namei.h> #include <sys/proc.h> #include <sys/errno.h> #include <sys/limits.h> #include <sys/buf.h> #include <sys/malloc.h> #include <sys/ioctl.h> #include <sys/disklabel.h> #include <sys/device.h> #include <sys/disk.h> #include <sys/stat.h> #include <sys/vnode.h> #include <sys/fcntl.h> #include <sys/uio.h> #include <sys/conf.h> #include <sys/dkio.h> #include <sys/specdev.h> #include <crypto/blf.h> #include <dev/vndioctl.h> #ifdef VNDDEBUG int vnddebug = 0x00; #define VDB_FOLLOW 0x01 #define VDB_INIT 0x02 #define VDB_IO 0x04 #define DNPRINTF(f, p...) do { if ((f) & vnddebug) printf(p); } while (0) #else #define DNPRINTF(f, p...) /* nothing */ #endif /* VNDDEBUG */ struct vnd_softc { struct device sc_dev; struct disk sc_dk; char sc_file[VNDNLEN]; /* file we're covering */ int sc_flags; /* flags */ uint16_t sc_type; /* d_type we are emulating */ size_t sc_size; /* size of vnd in sectors */ size_t sc_secsize; /* sector size in bytes */ size_t sc_nsectors; /* # of sectors per track */ size_t sc_ntracks; /* # of tracks per cylinder */ struct vnode *sc_vp; /* vnode */ struct ucred *sc_cred; /* credentials */ blf_ctx *sc_keyctx; /* key context */ }; /* sc_flags */ #define VNF_INITED 0x0001 #define VNF_HAVELABEL 0x0002 #define VNF_READONLY 0x0004 #define VNDRW(v) ((v)->sc_flags & VNF_READONLY ? FREAD : FREAD|FWRITE) struct vnd_softc *vnd_softc; int numvnd = 0; /* called by main() at boot time */ void vndattach(int); void vndclear(struct vnd_softc *); int vndsetcred(struct proc *p, struct vnode *, struct vnd_ioctl *, struct ucred **); int vndgetdisklabel(dev_t, struct vnd_softc *, struct disklabel *, int); void vndencrypt(struct vnd_softc *, caddr_t, size_t, daddr_t, int); void vndencryptbuf(struct vnd_softc *, struct buf *, int); size_t vndbdevsize(struct vnode *, struct proc *); void vndencrypt(struct vnd_softc *sc, caddr_t addr, size_t size, daddr_t off, int encrypt) { int i, bsize; u_char iv[8]; bsize = dbtob(1); for (i = 0; i < size/bsize; i++) { memset(iv, 0, sizeof(iv)); memcpy(iv, &off, sizeof(off)); blf_ecb_encrypt(sc->sc_keyctx, iv, sizeof(iv)); if (encrypt) blf_cbc_encrypt(sc->sc_keyctx, iv, addr, bsize); else blf_cbc_decrypt(sc->sc_keyctx, iv, addr, bsize); addr += bsize; off++; } } void vndencryptbuf(struct vnd_softc *sc, struct buf *bp, int encrypt) { vndencrypt(sc, bp->b_data, bp->b_bcount, bp->b_blkno, encrypt); } void vndattach(int num) { char *mem; int i; if (num <= 0) return; mem = mallocarray(num, sizeof(struct vnd_softc), M_DEVBUF, M_NOWAIT | M_ZERO); if (mem == NULL) { printf("WARNING: no memory for vnode disks\n"); return; } vnd_softc = (struct vnd_softc *)mem; for (i = 0; i < num; i++) { struct vnd_softc *sc = &vnd_softc[i]; sc->sc_dev.dv_unit = i; snprintf(sc->sc_dev.dv_xname, sizeof(sc->sc_dev.dv_xname), "vnd%d", i); disk_construct(&sc->sc_dk); device_ref(&sc->sc_dev); } numvnd = num; } int vndopen(dev_t dev, int flags, int mode, struct proc *p) { int unit = DISKUNIT(dev); struct vnd_softc *sc; int error = 0, part; DNPRINTF(VDB_FOLLOW, "vndopen(%x, %x, %x, %p)\n", dev, flags, mode, p); if (unit >= numvnd) return (ENXIO); sc = &vnd_softc[unit]; if ((error = disk_lock(&sc->sc_dk)) != 0) return (error); if ((flags & FWRITE) && (sc->sc_flags & VNF_READONLY)) { error = EROFS; goto bad; } if ((sc->sc_flags & VNF_INITED) && (sc->sc_flags & VNF_HAVELABEL) == 0 && sc->sc_dk.dk_openmask == 0) { sc->sc_flags |= VNF_HAVELABEL; vndgetdisklabel(dev, sc, sc->sc_dk.dk_label, 0); } part = DISKPART(dev); error = disk_openpart(&sc->sc_dk, part, mode, (sc->sc_flags & VNF_HAVELABEL) != 0); bad: disk_unlock(&sc->sc_dk); return (error); } /* * Load the label information on the named device */ int vndgetdisklabel(dev_t dev, struct vnd_softc *sc, struct disklabel *lp, int spoofonly) { memset(lp, 0, sizeof(struct disklabel)); lp->d_secsize = sc->sc_secsize; lp->d_nsectors = sc->sc_nsectors; lp->d_ntracks = sc->sc_ntracks; lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; if (lp->d_secpercyl) lp->d_ncylinders = sc->sc_size / lp->d_secpercyl; strncpy(lp->d_typename, "vnd device", sizeof(lp->d_typename)); lp->d_type = sc->sc_type; strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname)); DL_SETDSIZE(lp, sc->sc_size); lp->d_version = 1; lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; lp->d_checksum = dkcksum(lp); /* Call the generic disklabel extraction routine */ return readdisklabel(DISKLABELDEV(dev), vndstrategy, lp, spoofonly); } int vndclose(dev_t dev, int flags, int mode, struct proc *p) { int unit = DISKUNIT(dev); struct vnd_softc *sc; int part; DNPRINTF(VDB_FOLLOW, "vndclose(%x, %x, %x, %p)\n", dev, flags, mode, p); if (unit >= numvnd) return (ENXIO); sc = &vnd_softc[unit]; disk_lock_nointr(&sc->sc_dk); part = DISKPART(dev); disk_closepart(&sc->sc_dk, part, mode); #if 0 if (sc->sc_dk.dk_openmask == 0) sc->sc_flags &= ~VNF_HAVELABEL; #endif disk_unlock(&sc->sc_dk); return (0); } void vndstrategy(struct buf *bp) { int unit = DISKUNIT(bp->b_dev); struct vnd_softc *sc; struct partition *p; off_t off; long origbcount; int s; DNPRINTF(VDB_FOLLOW, "vndstrategy(%p): unit %d\n", bp, unit); if (unit >= numvnd) { bp->b_error = ENXIO; goto bad; } sc = &vnd_softc[unit]; if ((sc->sc_flags & VNF_HAVELABEL) == 0) { bp->b_error = ENXIO; goto bad; } /* * Many of the distrib scripts assume they can issue arbitrary * sized requests to raw vnd devices irrespective of the * emulated disk geometry. * * To continue supporting this, round the block count up to a * multiple of d_secsize for bounds_check_with_label(), and * then restore afterwards. * * We only do this for non-encrypted vnd, because encryption * requires operating on blocks at a time. */ origbcount = bp->b_bcount; if (sc->sc_keyctx == NULL) { u_int32_t secsize = sc->sc_dk.dk_label->d_secsize; bp->b_bcount = ((origbcount + secsize - 1) & ~(secsize - 1)); #ifdef DIAGNOSTIC if (bp->b_bcount != origbcount) { struct process *curpr = curproc->p_p; printf("%s: sloppy %s from proc %d (%s): " "blkno %lld bcount %ld\n", sc->sc_dev.dv_xname, (bp->b_flags & B_READ) ? "read" : "write", curpr->ps_pid, curpr->ps_comm, (long long)bp->b_blkno, origbcount); } #endif } if (bounds_check_with_label(bp, sc->sc_dk.dk_label) == -1) { bp->b_resid = bp->b_bcount = origbcount; goto done; } if (origbcount < bp->b_bcount) bp->b_bcount = origbcount; p = &sc->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)]; off = DL_GETPOFFSET(p) * sc->sc_dk.dk_label->d_secsize + (u_int64_t)bp->b_blkno * DEV_BSIZE; if (sc->sc_keyctx && !(bp->b_flags & B_READ)) vndencryptbuf(sc, bp, 1); /* * Use IO_NOLIMIT because upper layer has already checked I/O * for limits, so there is no need to do it again. * * We use IO_NOCACHE because this data should be cached at the * upper layer, so there is no need to cache it again. */ bp->b_error = vn_rdwr((bp->b_flags & B_READ) ? UIO_READ : UIO_WRITE, sc->sc_vp, bp->b_data, bp->b_bcount, off, UIO_SYSSPACE, IO_NOCACHE | IO_SYNC | IO_NOLIMIT, sc->sc_cred, &bp->b_resid, curproc); if (bp->b_error) bp->b_flags |= B_ERROR; /* Data in buffer cache needs to be in clear */ if (sc->sc_keyctx) vndencryptbuf(sc, bp, 0); goto done; bad: bp->b_flags |= B_ERROR; bp->b_resid = bp->b_bcount; done: s = splbio(); biodone(bp); splx(s); } int vndread(dev_t dev, struct uio *uio, int flags) { return (physio(vndstrategy, dev, B_READ, minphys, uio)); } int vndwrite(dev_t dev, struct uio *uio, int flags) { return (physio(vndstrategy, dev, B_WRITE, minphys, uio)); } size_t vndbdevsize(struct vnode *vp, struct proc *p) { struct partinfo pi; struct bdevsw *bsw; dev_t dev; dev = vp->v_rdev; bsw = bdevsw_lookup(dev); if (bsw->d_ioctl == NULL) return (0); if (bsw->d_ioctl(dev, DIOCGPART, (caddr_t)&pi, FREAD, p)) return (0); DNPRINTF(VDB_INIT, "vndbdevsize: size %llu secsize %u\n", DL_GETPSIZE(pi.part), pi.disklab->d_secsize); return (DL_GETPSIZE(pi.part)); } int vndioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { int unit = DISKUNIT(dev); struct disklabel *lp; struct vnd_softc *sc; struct vnd_ioctl *vio; struct vnd_user *vnu; struct vattr vattr; int error, part, pmask; DNPRINTF(VDB_FOLLOW, "vndioctl(%x, %lx, %p, %x, %p): unit %d\n", dev, cmd, addr, flag, p, unit); error = suser(p); if (error) return (error); if (unit >= numvnd) return (ENXIO); sc = &vnd_softc[unit]; vio = (struct vnd_ioctl *)addr; switch (cmd) { case VNDIOCSET: { char name[VNDNLEN], key[BLF_MAXUTILIZED]; struct nameidata nd; struct ucred *cred = NULL; size_t size; int vplocked; int rw; if (sc->sc_flags & VNF_INITED) return (EBUSY); /* Geometry eventually has to fit into label fields */ if (vio->vnd_secsize > UINT_MAX || vio->vnd_secsize == 0 || vio->vnd_ntracks > UINT_MAX || vio->vnd_nsectors > UINT_MAX) return (EINVAL); if ((error = copyinstr(vio->vnd_file, name, sizeof(name), NULL))) return (error); if (vio->vnd_keylen > 0) { if (vio->vnd_keylen > sizeof(key)) vio->vnd_keylen = sizeof(key); if ((error = copyin(vio->vnd_key, key, vio->vnd_keylen)) != 0) return (error); } /* * Open for read and write first. This lets vn_open() weed out * directories, sockets, etc. so we don't have to worry about * them. */ NDINIT(&nd, 0, 0, UIO_SYSSPACE, name, p); nd.ni_unveil = UNVEIL_READ | UNVEIL_WRITE; rw = FREAD|FWRITE; error = vn_open(&nd, FREAD|FWRITE, 0); if (error == EROFS) { NDINIT(&nd, 0, 0, UIO_SYSSPACE, name, p); nd.ni_unveil = UNVEIL_READ | UNVEIL_WRITE; rw = FREAD; error = vn_open(&nd, FREAD, 0); } if (error) return (error); vplocked = 1; error = VOP_GETATTR(nd.ni_vp, &vattr, p->p_ucred, p); if (error) { fail: if (vplocked) VOP_UNLOCK(nd.ni_vp); vn_close(nd.ni_vp, rw, p->p_ucred, p); if (cred != NULL) crfree(cred); return (error); } /* Cannot put a vnd on top of a vnd */ if (major(vattr.va_fsid) == major(dev)) { error = EINVAL; goto fail; } if ((error = vndsetcred(p, nd.ni_vp, vio, &cred)) != 0) goto fail; VOP_UNLOCK(nd.ni_vp); vplocked = 0; if (nd.ni_vp->v_type == VBLK) { size = vndbdevsize(nd.ni_vp, p); /* XXX is size 0 ok? */ } else size = vattr.va_size / vio->vnd_secsize; if ((error = disk_lock(&sc->sc_dk)) != 0) goto fail; if (sc->sc_flags & VNF_INITED) { disk_unlock(&sc->sc_dk); error = EBUSY; goto fail; } /* Set geometry for device. */ sc->sc_type = vio->vnd_type; sc->sc_secsize = vio->vnd_secsize; sc->sc_ntracks = vio->vnd_ntracks; sc->sc_nsectors = vio->vnd_nsectors; sc->sc_size = size; if (rw == FREAD) sc->sc_flags |= VNF_READONLY; else sc->sc_flags &= ~VNF_READONLY; memcpy(sc->sc_file, name, sizeof(sc->sc_file)); if (vio->vnd_keylen > 0) { sc->sc_keyctx = malloc(sizeof(*sc->sc_keyctx), M_DEVBUF, M_WAITOK); blf_key(sc->sc_keyctx, key, vio->vnd_keylen); explicit_bzero(key, vio->vnd_keylen); } else sc->sc_keyctx = NULL; sc->sc_vp = nd.ni_vp; sc->sc_cred = cred; vio->vnd_size = sc->sc_size * sc->sc_secsize; sc->sc_flags |= VNF_INITED; DNPRINTF(VDB_INIT, "vndioctl: SET vp %p size %llx\n", sc->sc_vp, (unsigned long long)sc->sc_size); /* Attach the disk. */ sc->sc_dk.dk_name = sc->sc_dev.dv_xname; disk_attach(&sc->sc_dev, &sc->sc_dk); disk_unlock(&sc->sc_dk); break; } case VNDIOCCLR: if ((error = disk_lock(&sc->sc_dk)) != 0) return (error); if ((sc->sc_flags & VNF_INITED) == 0) { disk_unlock(&sc->sc_dk); return (ENXIO); } /* * Don't unconfigure if any other partitions are open * or if both the character and block flavors of this * partition are open. */ part = DISKPART(dev); pmask = (1 << part); if ((sc->sc_dk.dk_openmask & ~pmask) || ((sc->sc_dk.dk_bopenmask & pmask) && (sc->sc_dk.dk_copenmask & pmask))) { disk_unlock(&sc->sc_dk); return (EBUSY); } vndclear(sc); DNPRINTF(VDB_INIT, "vndioctl: CLRed\n"); /* Free crypto key */ if (sc->sc_keyctx) { explicit_bzero(sc->sc_keyctx, sizeof(*sc->sc_keyctx)); free(sc->sc_keyctx, M_DEVBUF, sizeof(*sc->sc_keyctx)); } /* Detach the disk. */ disk_detach(&sc->sc_dk); disk_unlock(&sc->sc_dk); break; case VNDIOCGET: vnu = (struct vnd_user *)addr; if (vnu->vnu_unit == -1) vnu->vnu_unit = unit; if (vnu->vnu_unit >= numvnd) return (ENXIO); if (vnu->vnu_unit < 0) return (EINVAL); sc = &vnd_softc[vnu->vnu_unit]; if (sc->sc_flags & VNF_INITED) { error = VOP_GETATTR(sc->sc_vp, &vattr, p->p_ucred, p); if (error) return (error); strlcpy(vnu->vnu_file, sc->sc_file, sizeof(vnu->vnu_file)); vnu->vnu_dev = vattr.va_fsid; vnu->vnu_ino = vattr.va_fileid; } else { vnu->vnu_dev = 0; vnu->vnu_ino = 0; } break; case DIOCRLDINFO: if ((sc->sc_flags & VNF_HAVELABEL) == 0) return (ENOTTY); lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK); vndgetdisklabel(dev, sc, lp, 0); *(sc->sc_dk.dk_label) = *lp; free(lp, M_TEMP, sizeof(*lp)); return (0); case DIOCGPDINFO: if ((sc->sc_flags & VNF_HAVELABEL) == 0) return (ENOTTY); vndgetdisklabel(dev, sc, (struct disklabel *)addr, 1); return (0); case DIOCGDINFO: if ((sc->sc_flags & VNF_HAVELABEL) == 0) return (ENOTTY); *(struct disklabel *)addr = *(sc->sc_dk.dk_label); return (0); case DIOCGPART: if ((sc->sc_flags & VNF_HAVELABEL) == 0) return (ENOTTY); ((struct partinfo *)addr)->disklab = sc->sc_dk.dk_label; ((struct partinfo *)addr)->part = &sc->sc_dk.dk_label->d_partitions[DISKPART(dev)]; return (0); case DIOCWDINFO: case DIOCSDINFO: if ((sc->sc_flags & VNF_HAVELABEL) == 0) return (ENOTTY); if ((flag & FWRITE) == 0) return (EBADF); if ((error = disk_lock(&sc->sc_dk)) != 0) return (error); error = setdisklabel(sc->sc_dk.dk_label, (struct disklabel *)addr, /* sc->sc_dk.dk_openmask */ 0); if (error == 0) { if (cmd == DIOCWDINFO) error = writedisklabel(DISKLABELDEV(dev), vndstrategy, sc->sc_dk.dk_label); } disk_unlock(&sc->sc_dk); return (error); default: return (ENOTTY); } return (0); } /* * Duplicate the current processes' credentials. Since we are called only * as the result of a SET ioctl and only root can do that, any future access * to this "disk" is essentially as root. Note that credentials may change * if some other uid can write directly to the mapped file (NFS). */ int vndsetcred(struct proc *p, struct vnode *vp, struct vnd_ioctl *vio, struct ucred **newcredp) { void *buf; size_t size; struct ucred *new; int error; new = crdup(p->p_ucred); buf = malloc(DEV_BSIZE, M_TEMP, M_WAITOK); size = DEV_BSIZE; /* XXX: Horrible kludge to establish credentials for NFS */ error = vn_rdwr(UIO_READ, vp, buf, size, 0, UIO_SYSSPACE, 0, new, NULL, curproc); free(buf, M_TEMP, DEV_BSIZE); if (error == 0) *newcredp = new; else crfree(new); return (error); } void vndclear(struct vnd_softc *sc) { struct vnode *vp = sc->sc_vp; struct proc *p = curproc; /* XXX */ DNPRINTF(VDB_FOLLOW, "vndclear(%p): vp %p\n", sc, vp); if (vp == NULL) panic("vndioctl: null vp"); (void) vn_close(vp, VNDRW(sc), sc->sc_cred, p); crfree(sc->sc_cred); sc->sc_flags = 0; sc->sc_vp = NULL; sc->sc_cred = NULL; sc->sc_size = 0; memset(sc->sc_file, 0, sizeof(sc->sc_file)); } daddr_t vndsize(dev_t dev) { /* We don't support swapping to vnd anymore. */ return (-1); } int vnddump(dev_t dev, daddr_t blkno, caddr_t va, size_t size) { /* Not implemented. */ return (ENXIO); }
8 55 55 55 55 55 8 47 8 8 8 47 8 55 55 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 /* $OpenBSD: sha2.c,v 1.21 2022/12/27 20:13:03 patrick Exp $ */ /* * FILE: sha2.c * AUTHOR: Aaron D. Gifford <me@aarongifford.com> * * Copyright (c) 2000-2001, Aaron D. Gifford * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $From: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $ */ #include <sys/time.h> #include <sys/systm.h> #include <crypto/sha2.h> /* * UNROLLED TRANSFORM LOOP NOTE: * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform * loop version for the hash transform rounds (defined using macros * later in this file). Either define on the command line, for example: * * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c * * or define below: * * #define SHA2_UNROLL_TRANSFORM * */ #ifndef SMALL_KERNEL #if defined(__amd64__) || defined(__i386__) #define SHA2_UNROLL_TRANSFORM #endif #endif /*** SHA-256/384/512 Machine Architecture Definitions *****************/ /* * BYTE_ORDER NOTE: * * Please make sure that your system defines BYTE_ORDER. If your * architecture is little-endian, make sure it also defines * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are * equivalent. * * If your system does not define the above, then you can do so by * hand like this: * * #define LITTLE_ENDIAN 1234 * #define BIG_ENDIAN 4321 * * And for little-endian machines, add: * * #define BYTE_ORDER LITTLE_ENDIAN * * Or for big-endian machines: * * #define BYTE_ORDER BIG_ENDIAN * * The FreeBSD machine this was written on defines BYTE_ORDER * appropriately by including <sys/types.h> (which in turn includes * <machine/endian.h> where the appropriate definitions are actually * made). */ #if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN) #error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN #endif /*** SHA-256/384/512 Various Length Definitions ***********************/ /* NOTE: Most of these are in sha2.h */ #define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8) #define SHA384_SHORT_BLOCK_LENGTH (SHA384_BLOCK_LENGTH - 16) #define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16) /* * Macro for incrementally adding the unsigned 64-bit integer n to the * unsigned 128-bit integer (represented using a two-element array of * 64-bit words): */ #define ADDINC128(w,n) { \ (w)[0] += (u_int64_t)(n); \ if ((w)[0] < (n)) { \ (w)[1]++; \ } \ } /*** THE SIX LOGICAL FUNCTIONS ****************************************/ /* * Bit shifting and rotation (used by the six SHA-XYZ logical functions: * * NOTE: The naming of R and S appears backwards here (R is a SHIFT and * S is a ROTATION) because the SHA-256/384/512 description document * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this * same "backwards" definition. */ /* Shift-right (used in SHA-256, SHA-384, and SHA-512): */ #define R(b,x) ((x) >> (b)) /* 32-bit Rotate-right (used in SHA-256): */ #define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) /* 64-bit Rotate-right (used in SHA-384 and SHA-512): */ #define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) /* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */ #define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) #define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) /* Four of six logical functions used in SHA-256: */ #define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x))) #define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x))) #define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x))) #define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x))) /* Four of six logical functions used in SHA-384 and SHA-512: */ #define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x))) #define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x))) #define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x))) #define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x))) /*** INTERNAL FUNCTION PROTOTYPES *************************************/ /* NOTE: These should not be accessed directly from outside this * library -- they are intended for private internal visibility/use * only. */ void SHA512Last(SHA2_CTX *); void SHA256Transform(u_int32_t *, const u_int8_t *); void SHA512Transform(u_int64_t *, const u_int8_t *); /*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/ /* Hash constant words K for SHA-256: */ static const u_int32_t K256[64] = { 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL }; /* Initial hash value H for SHA-256: */ static const u_int32_t sha256_initial_hash_value[8] = { 0x6a09e667UL, 0xbb67ae85UL, 0x3c6ef372UL, 0xa54ff53aUL, 0x510e527fUL, 0x9b05688cUL, 0x1f83d9abUL, 0x5be0cd19UL }; /* Hash constant words K for SHA-384 and SHA-512: */ static const u_int64_t K512[80] = { 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL }; /* Initial hash value H for SHA-384 */ static const u_int64_t sha384_initial_hash_value[8] = { 0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL, 0x9159015a3070dd17ULL, 0x152fecd8f70e5939ULL, 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL, 0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL }; /* Initial hash value H for SHA-512 */ static const u_int64_t sha512_initial_hash_value[8] = { 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL }; /*** SHA-256: *********************************************************/ void SHA256Init(SHA2_CTX *context) { memcpy(context->state.st32, sha256_initial_hash_value, SHA256_DIGEST_LENGTH); memset(context->buffer, 0, SHA256_BLOCK_LENGTH); context->bitcount[0] = 0; } #ifdef SHA2_UNROLL_TRANSFORM /* Unrolled SHA-256 round macros: */ #define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) do { \ W256[j] = (u_int32_t)data[3] | ((u_int32_t)data[2] << 8) | \ ((u_int32_t)data[1] << 16) | ((u_int32_t)data[0] << 24); \ data += 4; \ T1 = (h) + Sigma1_256((e)) + Ch((e), (f), (g)) + K256[j] + W256[j]; \ (d) += T1; \ (h) = T1 + Sigma0_256((a)) + Maj((a), (b), (c)); \ j++; \ } while(0) #define ROUND256(a,b,c,d,e,f,g,h) do { \ s0 = W256[(j+1)&0x0f]; \ s0 = sigma0_256(s0); \ s1 = W256[(j+14)&0x0f]; \ s1 = sigma1_256(s1); \ T1 = (h) + Sigma1_256((e)) + Ch((e), (f), (g)) + K256[j] + \ (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \ (d) += T1; \ (h) = T1 + Sigma0_256((a)) + Maj((a), (b), (c)); \ j++; \ } while(0) void SHA256Transform(u_int32_t *state, const u_int8_t *data) { u_int32_t a, b, c, d, e, f, g, h, s0, s1; u_int32_t T1, W256[16]; int j; /* Initialize registers with the prev. intermediate value */ a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; f = state[5]; g = state[6]; h = state[7]; j = 0; do { /* Rounds 0 to 15 (unrolled): */ ROUND256_0_TO_15(a,b,c,d,e,f,g,h); ROUND256_0_TO_15(h,a,b,c,d,e,f,g); ROUND256_0_TO_15(g,h,a,b,c,d,e,f); ROUND256_0_TO_15(f,g,h,a,b,c,d,e); ROUND256_0_TO_15(e,f,g,h,a,b,c,d); ROUND256_0_TO_15(d,e,f,g,h,a,b,c); ROUND256_0_TO_15(c,d,e,f,g,h,a,b); ROUND256_0_TO_15(b,c,d,e,f,g,h,a); } while (j < 16); /* Now for the remaining rounds to 64: */ do { ROUND256(a,b,c,d,e,f,g,h); ROUND256(h,a,b,c,d,e,f,g); ROUND256(g,h,a,b,c,d,e,f); ROUND256(f,g,h,a,b,c,d,e); ROUND256(e,f,g,h,a,b,c,d); ROUND256(d,e,f,g,h,a,b,c); ROUND256(c,d,e,f,g,h,a,b); ROUND256(b,c,d,e,f,g,h,a); } while (j < 64); /* Compute the current intermediate hash value */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; state[5] += f; state[6] += g; state[7] += h; /* Clean up */ a = b = c = d = e = f = g = h = T1 = 0; } #else /* SHA2_UNROLL_TRANSFORM */ void SHA256Transform(u_int32_t *state, const u_int8_t *data) { u_int32_t a, b, c, d, e, f, g, h, s0, s1; u_int32_t T1, T2, W256[16]; int j; /* Initialize registers with the prev. intermediate value */ a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; f = state[5]; g = state[6]; h = state[7]; j = 0; do { W256[j] = (u_int32_t)data[3] | ((u_int32_t)data[2] << 8) | ((u_int32_t)data[1] << 16) | ((u_int32_t)data[0] << 24); data += 4; /* Apply the SHA-256 compression function to update a..h */ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j]; T2 = Sigma0_256(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; j++; } while (j < 16); do { /* Part of the message block expansion: */ s0 = W256[(j+1)&0x0f]; s0 = sigma0_256(s0); s1 = W256[(j+14)&0x0f]; s1 = sigma1_256(s1); /* Apply the SHA-256 compression function to update a..h */ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); T2 = Sigma0_256(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; j++; } while (j < 64); /* Compute the current intermediate hash value */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; state[5] += f; state[6] += g; state[7] += h; /* Clean up */ a = b = c = d = e = f = g = h = T1 = T2 = 0; } #endif /* SHA2_UNROLL_TRANSFORM */ void SHA256Update(SHA2_CTX *context, const void *dataptr, size_t len) { const uint8_t *data = dataptr; size_t freespace, usedspace; /* Calling with no data is valid (we do nothing) */ if (len == 0) return; usedspace = (context->bitcount[0] >> 3) % SHA256_BLOCK_LENGTH; if (usedspace > 0) { /* Calculate how much free space is available in the buffer */ freespace = SHA256_BLOCK_LENGTH - usedspace; if (len >= freespace) { /* Fill the buffer completely and process it */ memcpy(&context->buffer[usedspace], data, freespace); context->bitcount[0] += freespace << 3; len -= freespace; data += freespace; SHA256Transform(context->state.st32, context->buffer); } else { /* The buffer is not yet full */ memcpy(&context->buffer[usedspace], data, len); context->bitcount[0] += len << 3; /* Clean up: */ usedspace = freespace = 0; return; } } while (len >= SHA256_BLOCK_LENGTH) { /* Process as many complete blocks as we can */ SHA256Transform(context->state.st32, data); context->bitcount[0] += SHA256_BLOCK_LENGTH << 3; len -= SHA256_BLOCK_LENGTH; data += SHA256_BLOCK_LENGTH; } if (len > 0) { /* There's left-overs, so save 'em */ memcpy(context->buffer, data, len); context->bitcount[0] += len << 3; } /* Clean up: */ usedspace = freespace = 0; } void SHA256Final(u_int8_t *digest, SHA2_CTX *context) { unsigned int usedspace; usedspace = (context->bitcount[0] >> 3) % SHA256_BLOCK_LENGTH; #if BYTE_ORDER == LITTLE_ENDIAN /* Convert FROM host byte order */ context->bitcount[0] = swap64(context->bitcount[0]); #endif if (usedspace > 0) { /* Begin padding with a 1 bit: */ context->buffer[usedspace++] = 0x80; if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) { /* Set-up for the last transform: */ memset(&context->buffer[usedspace], 0, SHA256_SHORT_BLOCK_LENGTH - usedspace); } else { if (usedspace < SHA256_BLOCK_LENGTH) { memset(&context->buffer[usedspace], 0, SHA256_BLOCK_LENGTH - usedspace); } /* Do second-to-last transform: */ SHA256Transform(context->state.st32, context->buffer); /* And set-up for the last transform: */ memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH); } } else { /* Set-up for the last transform: */ memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH); /* Begin padding with a 1 bit: */ *context->buffer = 0x80; } /* Set the bit count: */ *(u_int64_t *)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount[0]; /* Final transform: */ SHA256Transform(context->state.st32, context->buffer); #if BYTE_ORDER == LITTLE_ENDIAN { /* Convert TO host byte order */ int j; for (j = 0; j < 8; j++) { context->state.st32[j] = swap32(context->state.st32[j]); } } #endif memcpy(digest, context->state.st32, SHA256_DIGEST_LENGTH); /* Clean up state data: */ explicit_bzero(context, sizeof(*context)); usedspace = 0; } /*** SHA-512: *********************************************************/ void SHA512Init(SHA2_CTX *context) { memcpy(context->state.st64, sha512_initial_hash_value, SHA512_DIGEST_LENGTH); memset(context->buffer, 0, SHA512_BLOCK_LENGTH); context->bitcount[0] = context->bitcount[1] = 0; } #ifdef SHA2_UNROLL_TRANSFORM /* Unrolled SHA-512 round macros: */ #define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) do { \ W512[j] = (u_int64_t)data[7] | ((u_int64_t)data[6] << 8) | \ ((u_int64_t)data[5] << 16) | ((u_int64_t)data[4] << 24) | \ ((u_int64_t)data[3] << 32) | ((u_int64_t)data[2] << 40) | \ ((u_int64_t)data[1] << 48) | ((u_int64_t)data[0] << 56); \ data += 8; \ T1 = (h) + Sigma1_512((e)) + Ch((e), (f), (g)) + K512[j] + W512[j]; \ (d) += T1; \ (h) = T1 + Sigma0_512((a)) + Maj((a), (b), (c)); \ j++; \ } while(0) #define ROUND512(a,b,c,d,e,f,g,h) do { \ s0 = W512[(j+1)&0x0f]; \ s0 = sigma0_512(s0); \ s1 = W512[(j+14)&0x0f]; \ s1 = sigma1_512(s1); \ T1 = (h) + Sigma1_512((e)) + Ch((e), (f), (g)) + K512[j] + \ (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \ (d) += T1; \ (h) = T1 + Sigma0_512((a)) + Maj((a), (b), (c)); \ j++; \ } while(0) void SHA512Transform(u_int64_t *state, const u_int8_t *data) { u_int64_t a, b, c, d, e, f, g, h, s0, s1; u_int64_t T1, W512[16]; int j; /* Initialize registers with the prev. intermediate value */ a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; f = state[5]; g = state[6]; h = state[7]; j = 0; do { ROUND512_0_TO_15(a,b,c,d,e,f,g,h); ROUND512_0_TO_15(h,a,b,c,d,e,f,g); ROUND512_0_TO_15(g,h,a,b,c,d,e,f); ROUND512_0_TO_15(f,g,h,a,b,c,d,e); ROUND512_0_TO_15(e,f,g,h,a,b,c,d); ROUND512_0_TO_15(d,e,f,g,h,a,b,c); ROUND512_0_TO_15(c,d,e,f,g,h,a,b); ROUND512_0_TO_15(b,c,d,e,f,g,h,a); } while (j < 16); /* Now for the remaining rounds up to 79: */ do { ROUND512(a,b,c,d,e,f,g,h); ROUND512(h,a,b,c,d,e,f,g); ROUND512(g,h,a,b,c,d,e,f); ROUND512(f,g,h,a,b,c,d,e); ROUND512(e,f,g,h,a,b,c,d); ROUND512(d,e,f,g,h,a,b,c); ROUND512(c,d,e,f,g,h,a,b); ROUND512(b,c,d,e,f,g,h,a); } while (j < 80); /* Compute the current intermediate hash value */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; state[5] += f; state[6] += g; state[7] += h; /* Clean up */ a = b = c = d = e = f = g = h = T1 = 0; } #else /* SHA2_UNROLL_TRANSFORM */ void SHA512Transform(u_int64_t *state, const u_int8_t *data) { u_int64_t a, b, c, d, e, f, g, h, s0, s1; u_int64_t T1, T2, W512[16]; int j; /* Initialize registers with the prev. intermediate value */ a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; f = state[5]; g = state[6]; h = state[7]; j = 0; do { W512[j] = (u_int64_t)data[7] | ((u_int64_t)data[6] << 8) | ((u_int64_t)data[5] << 16) | ((u_int64_t)data[4] << 24) | ((u_int64_t)data[3] << 32) | ((u_int64_t)data[2] << 40) | ((u_int64_t)data[1] << 48) | ((u_int64_t)data[0] << 56); data += 8; /* Apply the SHA-512 compression function to update a..h */ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j]; T2 = Sigma0_512(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; j++; } while (j < 16); do { /* Part of the message block expansion: */ s0 = W512[(j+1)&0x0f]; s0 = sigma0_512(s0); s1 = W512[(j+14)&0x0f]; s1 = sigma1_512(s1); /* Apply the SHA-512 compression function to update a..h */ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); T2 = Sigma0_512(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; j++; } while (j < 80); /* Compute the current intermediate hash value */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; state[5] += f; state[6] += g; state[7] += h; /* Clean up */ a = b = c = d = e = f = g = h = T1 = T2 = 0; } #endif /* SHA2_UNROLL_TRANSFORM */ void SHA512Update(SHA2_CTX *context, const void *dataptr, size_t len) { const uint8_t *data = dataptr; size_t freespace, usedspace; /* Calling with no data is valid (we do nothing) */ if (len == 0) return; usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; if (usedspace > 0) { /* Calculate how much free space is available in the buffer */ freespace = SHA512_BLOCK_LENGTH - usedspace; if (len >= freespace) { /* Fill the buffer completely and process it */ memcpy(&context->buffer[usedspace], data, freespace); ADDINC128(context->bitcount, freespace << 3); len -= freespace; data += freespace; SHA512Transform(context->state.st64, context->buffer); } else { /* The buffer is not yet full */ memcpy(&context->buffer[usedspace], data, len); ADDINC128(context->bitcount, len << 3); /* Clean up: */ usedspace = freespace = 0; return; } } while (len >= SHA512_BLOCK_LENGTH) { /* Process as many complete blocks as we can */ SHA512Transform(context->state.st64, data); ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3); len -= SHA512_BLOCK_LENGTH; data += SHA512_BLOCK_LENGTH; } if (len > 0) { /* There's left-overs, so save 'em */ memcpy(context->buffer, data, len); ADDINC128(context->bitcount, len << 3); } /* Clean up: */ usedspace = freespace = 0; } void SHA512Last(SHA2_CTX *context) { unsigned int usedspace; usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; #if BYTE_ORDER == LITTLE_ENDIAN /* Convert FROM host byte order */ context->bitcount[0] = swap64(context->bitcount[0]); context->bitcount[1] = swap64(context->bitcount[1]); #endif if (usedspace > 0) { /* Begin padding with a 1 bit: */ context->buffer[usedspace++] = 0x80; if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) { /* Set-up for the last transform: */ memset(&context->buffer[usedspace], 0, SHA512_SHORT_BLOCK_LENGTH - usedspace); } else { if (usedspace < SHA512_BLOCK_LENGTH) { memset(&context->buffer[usedspace], 0, SHA512_BLOCK_LENGTH - usedspace); } /* Do second-to-last transform: */ SHA512Transform(context->state.st64, context->buffer); /* And set-up for the last transform: */ memset(context->buffer, 0, SHA512_BLOCK_LENGTH - 2); } } else { /* Prepare for final transform: */ memset(context->buffer, 0, SHA512_SHORT_BLOCK_LENGTH); /* Begin padding with a 1 bit: */ *context->buffer = 0x80; } /* Store the length of input data (in bits): */ *(u_int64_t *)&context->buffer[SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1]; *(u_int64_t *)&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0]; /* Final transform: */ SHA512Transform(context->state.st64, context->buffer); } void SHA512Final(u_int8_t *digest, SHA2_CTX *context) { SHA512Last(context); /* Save the hash data for output: */ #if BYTE_ORDER == LITTLE_ENDIAN { /* Convert TO host byte order */ int j; for (j = 0; j < 8; j++) { context->state.st64[j] = swap64(context->state.st64[j]); } } #endif memcpy(digest, context->state.st64, SHA512_DIGEST_LENGTH); /* Zero out state data */ explicit_bzero(context, sizeof(*context)); } /*** SHA-384: *********************************************************/ void SHA384Init(SHA2_CTX *context) { memcpy(context->state.st64, sha384_initial_hash_value, SHA512_DIGEST_LENGTH); memset(context->buffer, 0, SHA384_BLOCK_LENGTH); context->bitcount[0] = context->bitcount[1] = 0; } void SHA384Update(SHA2_CTX *context, const void *data, size_t len) { SHA512Update(context, data, len); } void SHA384Final(u_int8_t *digest, SHA2_CTX *context) { SHA512Last(context); /* Save the hash data for output: */ #if BYTE_ORDER == LITTLE_ENDIAN { /* Convert TO host byte order */ int j; for (j = 0; j < 6; j++) { context->state.st64[j] = swap64(context->state.st64[j]); } } #endif memcpy(digest, context->state.st64, SHA384_DIGEST_LENGTH); /* Zero out state data */ explicit_bzero(context, sizeof(*context)); }
70 71 5 5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 /* $OpenBSD: acpitimer.c,v 1.17 2023/02/04 19:19:37 cheloha Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> #include <sys/stdint.h> #include <sys/timetc.h> #include <machine/bus.h> #include <machine/cpu.h> #include <dev/acpi/acpireg.h> #include <dev/acpi/acpivar.h> struct acpitimer_softc { struct device sc_dev; bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; }; int acpitimermatch(struct device *, void *, void *); void acpitimerattach(struct device *, struct device *, void *); void acpitimer_delay(int); u_int acpi_get_timecount(struct timecounter *tc); uint32_t acpitimer_read(struct acpitimer_softc *); static struct timecounter acpi_timecounter = { .tc_get_timecount = acpi_get_timecount, .tc_counter_mask = 0x00ffffff, /* 24 bits */ .tc_frequency = ACPI_FREQUENCY, .tc_name = 0, .tc_quality = 1000, .tc_priv = NULL, .tc_user = 0, }; const struct cfattach acpitimer_ca = { sizeof(struct acpitimer_softc), acpitimermatch, acpitimerattach }; struct cfdriver acpitimer_cd = { NULL, "acpitimer", DV_DULL }; int acpitimermatch(struct device *parent, void *match, void *aux) { struct acpi_attach_args *aa = aux; struct cfdata *cf = match; /* sanity */ if (aa->aaa_name == NULL || strcmp(aa->aaa_name, cf->cf_driver->cd_name) != 0 || aa->aaa_table != NULL) return (0); return (1); } void acpitimerattach(struct device *parent, struct device *self, void *aux) { struct acpitimer_softc *sc = (struct acpitimer_softc *) self; struct acpi_softc *psc = (struct acpi_softc *) parent; int rc; if (psc->sc_fadt->hdr_revision >= 3 && psc->sc_fadt->x_pm_tmr_blk.address != 0) rc = acpi_map_address(psc, &psc->sc_fadt->x_pm_tmr_blk, 0, psc->sc_fadt->pm_tmr_len, &sc->sc_ioh, &sc->sc_iot); else rc = acpi_map_address(psc, NULL, psc->sc_fadt->pm_tmr_blk, psc->sc_fadt->pm_tmr_len, &sc->sc_ioh, &sc->sc_iot); if (rc) { printf(": can't map i/o space\n"); return; } printf(": %d Hz, %d bits\n", ACPI_FREQUENCY, psc->sc_fadt->flags & FADT_TMR_VAL_EXT ? 32 : 24); if (psc->sc_fadt->flags & FADT_TMR_VAL_EXT) acpi_timecounter.tc_counter_mask = 0xffffffffU; acpi_timecounter.tc_priv = sc; acpi_timecounter.tc_name = sc->sc_dev.dv_xname; tc_init(&acpi_timecounter); delay_init(acpitimer_delay, 1000); #if defined(__amd64__) extern void cpu_recalibrate_tsc(struct timecounter *); cpu_recalibrate_tsc(&acpi_timecounter); #endif } void acpitimer_delay(int usecs) { uint64_t count = 0, cycles; struct acpitimer_softc *sc = acpi_timecounter.tc_priv; uint32_t mask = acpi_timecounter.tc_counter_mask; uint32_t val1, val2; val2 = acpitimer_read(sc); cycles = usecs * acpi_timecounter.tc_frequency / 1000000; while (count < cycles) { CPU_BUSY_CYCLE(); val1 = val2; val2 = acpitimer_read(sc); count += (val2 - val1) & mask; } } u_int acpi_get_timecount(struct timecounter *tc) { return acpitimer_read(tc->tc_priv); } uint32_t acpitimer_read(struct acpitimer_softc *sc) { uint32_t u1, u2, u3; u2 = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 0); u3 = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 0); do { u1 = u2; u2 = u3; u3 = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 0); } while (u1 > u2 || u2 > u3); return (u2); }
78 54 64 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 /* $OpenBSD: strncmp.c,v 1.11 2014/06/10 04:16:57 deraadt Exp $ */ /* * Copyright (c) 1989 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <lib/libkern/libkern.h> int strncmp(const char *s1, const char *s2, size_t n) { if (n == 0) return (0); do { if (*s1 != *s2++) return (*(unsigned char *)s1 - *(unsigned char *)--s2); if (*s1++ == 0) break; } while (--n != 0); return (0); }
85 32 20 15 71 5 34 43 252 3 249 250 6 39 16 12 45 20 125 6 244 252 252 1048 1048 7 1044 2 189 935 668 271 300 5 9 2 2 1 1 4 3 3 3 3 3 6 6 16 8 10 20 20 17 6 15 11 4 15 15 5 5 10 4 6 2 2 1 1 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 /* $OpenBSD: if_ethersubr.c,v 1.293 2024/02/14 22:41:48 bluhm Exp $ */ /* $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 1982, 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93 */ /* %%% portions-copyright-nrl-95 Portions of this software are Copyright 1995-1998 by Randall Atkinson, Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights Reserved. All rights under this copyright have been assigned to the US Naval Research Laboratory (NRL). The NRL Copyright Notice and License Agreement Version 1.1 (January 17, 1995) applies to these portions of the software. You should have received a copy of the license with this software. If you didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. */ #include "bpfilter.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <sys/errno.h> #include <sys/syslog.h> #include <sys/timeout.h> #include <sys/smr.h> #include <net/if.h> #include <net/netisr.h> #include <net/route.h> #include <net/if_llc.h> #include <net/if_dl.h> #include <net/if_media.h> #include <net/if_types.h> #include <netinet/in.h> #include <netinet/if_ether.h> #include <netinet/ip_ipsp.h> #include <netinet/ip.h> #include <netinet/ip6.h> #include <netinet/tcp.h> #include <netinet/udp.h> #if NBPFILTER > 0 #include <net/bpf.h> #endif #include "vlan.h" #if NVLAN > 0 #include <net/if_vlan_var.h> #endif #include "carp.h" #if NCARP > 0 #include <netinet/ip_carp.h> #endif #include "pppoe.h" #if NPPPOE > 0 #include <net/if_pppoe.h> #endif #include "bpe.h" #if NBPE > 0 #include <net/if_bpe.h> #endif #ifdef INET6 #include <netinet6/in6_var.h> #include <netinet6/nd6.h> #endif #ifdef PIPEX #include <net/pipex.h> #endif #ifdef MPLS #include <netmpls/mpls.h> #endif /* MPLS */ /* #define ETHERDEBUG 1 */ #ifdef ETHERDEBUG int etherdebug = ETHERDEBUG; #define DNPRINTF(level, fmt, args...) \ do { \ if (etherdebug >= level) \ printf("%s: " fmt "\n", __func__, ## args); \ } while (0) #else #define DNPRINTF(level, fmt, args...) \ do { } while (0) #endif #define DPRINTF(fmt, args...) DNPRINTF(1, fmt, args) u_int8_t etherbroadcastaddr[ETHER_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; u_int8_t etheranyaddr[ETHER_ADDR_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #define senderr(e) { error = (e); goto bad;} int ether_ioctl(struct ifnet *ifp, struct arpcom *arp, u_long cmd, caddr_t data) { struct ifreq *ifr = (struct ifreq *)data; int error = 0; switch (cmd) { case SIOCSIFADDR: break; case SIOCSIFMTU: if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu) error = EINVAL; else ifp->if_mtu = ifr->ifr_mtu; break; case SIOCADDMULTI: case SIOCDELMULTI: if (ifp->if_flags & IFF_MULTICAST) { error = (cmd == SIOCADDMULTI) ? ether_addmulti(ifr, arp) : ether_delmulti(ifr, arp); } else error = ENOTTY; break; default: error = ENOTTY; } return (error); } void ether_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt) { if (rt == NULL) return; switch (rt_key(rt)->sa_family) { case AF_INET: arp_rtrequest(ifp, req, rt); break; #ifdef INET6 case AF_INET6: nd6_rtrequest(ifp, req, rt); break; #endif default: break; } } int ether_resolve(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt, struct ether_header *eh) { struct arpcom *ac = (struct arpcom *)ifp; sa_family_t af = dst->sa_family; int error = 0; if (!ISSET(ifp->if_flags, IFF_RUNNING)) senderr(ENETDOWN); KASSERT(rt != NULL || ISSET(m->m_flags, M_MCAST|M_BCAST) || af == AF_UNSPEC || af == pseudo_AF_HDRCMPLT); #ifdef DIAGNOSTIC if (ifp->if_rdomain != rtable_l2(m->m_pkthdr.ph_rtableid)) { printf("%s: trying to send packet on wrong domain. " "if %d vs. mbuf %d\n", ifp->if_xname, ifp->if_rdomain, rtable_l2(m->m_pkthdr.ph_rtableid)); } #endif switch (af) { case AF_INET: error = arpresolve(ifp, rt, m, dst, eh->ether_dhost); if (error) return (error); eh->ether_type = htons(ETHERTYPE_IP); /* * If broadcasting on a simplex interface, loopback a copy. * The checksum must be calculated in software. Keep the * condition in sync with in_ifcap_cksum(). */ if (ISSET(m->m_flags, M_BCAST) && ISSET(ifp->if_flags, IFF_SIMPLEX) && !m->m_pkthdr.pf.routed) { struct mbuf *mcopy; /* XXX Should we input an unencrypted IPsec packet? */ mcopy = m_copym(m, 0, M_COPYALL, M_NOWAIT); if (mcopy != NULL) if_input_local(ifp, mcopy, af); } break; #ifdef INET6 case AF_INET6: error = nd6_resolve(ifp, rt, m, dst, eh->ether_dhost); if (error) return (error); eh->ether_type = htons(ETHERTYPE_IPV6); break; #endif #ifdef MPLS case AF_MPLS: if (rt == NULL) senderr(EHOSTUNREACH); if (!ISSET(ifp->if_xflags, IFXF_MPLS)) senderr(ENETUNREACH); dst = ISSET(rt->rt_flags, RTF_GATEWAY) ? rt->rt_gateway : rt_key(rt); switch (dst->sa_family) { case AF_LINK: if (satosdl(dst)->sdl_alen < sizeof(eh->ether_dhost)) senderr(EHOSTUNREACH); memcpy(eh->ether_dhost, LLADDR(satosdl(dst)), sizeof(eh->ether_dhost)); break; #ifdef INET6 case AF_INET6: error = nd6_resolve(ifp, rt, m, dst, eh->ether_dhost); if (error) return (error); break; #endif case AF_INET: error = arpresolve(ifp, rt, m, dst, eh->ether_dhost); if (error) return (error); break; default: senderr(EHOSTUNREACH); } /* XXX handling for simplex devices in case of M/BCAST ?? */ if (m->m_flags & (M_BCAST | M_MCAST)) eh->ether_type = htons(ETHERTYPE_MPLS_MCAST); else eh->ether_type = htons(ETHERTYPE_MPLS); break; #endif /* MPLS */ case pseudo_AF_HDRCMPLT: /* take the whole header from the sa */ memcpy(eh, dst->sa_data, sizeof(*eh)); return (0); case AF_UNSPEC: /* take the dst and type from the sa, but get src below */ memcpy(eh, dst->sa_data, sizeof(*eh)); break; default: printf("%s: can't handle af%d\n", ifp->if_xname, af); senderr(EAFNOSUPPORT); } memcpy(eh->ether_shost, ac->ac_enaddr, sizeof(eh->ether_shost)); return (0); bad: m_freem(m); return (error); } struct mbuf* ether_encap(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt, int *errorp) { struct ether_header eh; int error; error = ether_resolve(ifp, m, dst, rt, &eh); switch (error) { case 0: break; case EAGAIN: error = 0; default: *errorp = error; return (NULL); } m = m_prepend(m, ETHER_ALIGN + sizeof(eh), M_DONTWAIT); if (m == NULL) { *errorp = ENOBUFS; return (NULL); } m_adj(m, ETHER_ALIGN); memcpy(mtod(m, struct ether_header *), &eh, sizeof(eh)); return (m); } int ether_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) { int error; m = ether_encap(ifp, m, dst, rt, &error); if (m == NULL) return (error); return (if_enqueue(ifp, m)); } /* * Process a received Ethernet packet. * * Ethernet input has several "phases" of filtering packets to * support virtual/pseudo interfaces before actual layer 3 protocol * handling. * * First phase: * * The first phase supports drivers that aggregate multiple Ethernet * ports into a single logical interface, ie, aggr(4) and trunk(4). * These drivers intercept packets by swapping out the if_input handler * on the "port" interfaces to steal the packets before they get here * to ether_input(). */ void ether_input(struct ifnet *ifp, struct mbuf *m) { struct ether_header *eh; void (*input)(struct ifnet *, struct mbuf *); u_int16_t etype; struct arpcom *ac; const struct ether_brport *eb; unsigned int sdelim = 0; uint64_t dst, self; /* Drop short frames */ if (m->m_len < ETHER_HDR_LEN) goto dropanyway; /* * Second phase: service delimited packet filtering. * * Let vlan(4) and svlan(4) look at "service delimited" * packets. If a virtual interface does not exist to take * those packets, they're returned to ether_input() so a * bridge can have a go at forwarding them. */ eh = mtod(m, struct ether_header *); dst = ether_addr_to_e64((struct ether_addr *)eh->ether_dhost); etype = ntohs(eh->ether_type); if (ISSET(m->m_flags, M_VLANTAG) || etype == ETHERTYPE_VLAN || etype == ETHERTYPE_QINQ) { #if NVLAN > 0 m = vlan_input(ifp, m, &sdelim); if (m == NULL) return; #else sdelim = 1; #endif } /* * Third phase: bridge processing. * * Give the packet to a bridge interface, ie, bridge(4), * veb(4), or tpmr(4), if it is configured. A bridge * may take the packet and forward it to another port, or it * may return it here to ether_input() to support local * delivery to this port. */ ac = (struct arpcom *)ifp; smr_read_enter(); eb = SMR_PTR_GET(&ac->ac_brport); if (eb != NULL) eb->eb_port_take(eb->eb_port); smr_read_leave(); if (eb != NULL) { m = (*eb->eb_input)(ifp, m, dst, eb->eb_port); eb->eb_port_rele(eb->eb_port); if (m == NULL) { return; } } /* * Fourth phase: drop service delimited packets. * * If the packet has a tag, and a bridge didn't want it, * it's not for this port. */ if (sdelim) goto dropanyway; /* * Fifth phase: destination address check. * * Is the packet specifically addressed to this port? */ eh = mtod(m, struct ether_header *); self = ether_addr_to_e64((struct ether_addr *)ac->ac_enaddr); if (dst != self) { #if NCARP > 0 /* * If it's not for this port, it could be for carp(4). */ if (ifp->if_type != IFT_CARP && !SRPL_EMPTY_LOCKED(&ifp->if_carp)) { m = carp_input(ifp, m, dst); if (m == NULL) return; eh = mtod(m, struct ether_header *); } #endif /* * If not, it must be multicast or broadcast to go further. */ if (!ETH64_IS_MULTICAST(dst)) goto dropanyway; /* * If this is not a simplex interface, drop the packet * if it came from us. */ if ((ifp->if_flags & IFF_SIMPLEX) == 0) { uint64_t src = ether_addr_to_e64( (struct ether_addr *)eh->ether_shost); if (self == src) goto dropanyway; } SET(m->m_flags, ETH64_IS_BROADCAST(dst) ? M_BCAST : M_MCAST); ifp->if_imcasts++; } /* * Sixth phase: protocol demux. * * At this point it is known that the packet is destined * for layer 3 protocol handling on the local port. */ etype = ntohs(eh->ether_type); switch (etype) { case ETHERTYPE_IP: input = ipv4_input; break; case ETHERTYPE_ARP: if (ifp->if_flags & IFF_NOARP) goto dropanyway; input = arpinput; break; case ETHERTYPE_REVARP: if (ifp->if_flags & IFF_NOARP) goto dropanyway; input = revarpinput; break; #ifdef INET6 /* * Schedule IPv6 software interrupt for incoming IPv6 packet. */ case ETHERTYPE_IPV6: input = ipv6_input; break; #endif /* INET6 */ #if NPPPOE > 0 || defined(PIPEX) case ETHERTYPE_PPPOEDISC: case ETHERTYPE_PPPOE: if (m->m_flags & (M_MCAST | M_BCAST)) goto dropanyway; #ifdef PIPEX if (pipex_enable) { struct pipex_session *session; if ((session = pipex_pppoe_lookup_session(m)) != NULL) { pipex_pppoe_input(m, session); pipex_rele_session(session); return; } } #endif if (etype == ETHERTYPE_PPPOEDISC) { if (mq_enqueue(&pppoediscinq, m) == 0) schednetisr(NETISR_PPPOE); } else { if (mq_enqueue(&pppoeinq, m) == 0) schednetisr(NETISR_PPPOE); } return; #endif #ifdef MPLS case ETHERTYPE_MPLS: case ETHERTYPE_MPLS_MCAST: input = mpls_input; break; #endif #if NBPE > 0 case ETHERTYPE_PBB: bpe_input(ifp, m); return; #endif default: goto dropanyway; } m_adj(m, sizeof(*eh)); (*input)(ifp, m); return; dropanyway: m_freem(m); return; } int ether_brport_isset(struct ifnet *ifp) { struct arpcom *ac = (struct arpcom *)ifp; KERNEL_ASSERT_LOCKED(); if (SMR_PTR_GET_LOCKED(&ac->ac_brport) != NULL) return (EBUSY); return (0); } void ether_brport_set(struct ifnet *ifp, const struct ether_brport *eb) { struct arpcom *ac = (struct arpcom *)ifp; KERNEL_ASSERT_LOCKED(); KASSERTMSG(SMR_PTR_GET_LOCKED(&ac->ac_brport) == NULL, "%s setting an already set brport", ifp->if_xname); SMR_PTR_SET_LOCKED(&ac->ac_brport, eb); } void ether_brport_clr(struct ifnet *ifp) { struct arpcom *ac = (struct arpcom *)ifp; KERNEL_ASSERT_LOCKED(); KASSERTMSG(SMR_PTR_GET_LOCKED(&ac->ac_brport) != NULL, "%s clearing an already clear brport", ifp->if_xname); SMR_PTR_SET_LOCKED(&ac->ac_brport, NULL); } const struct ether_brport * ether_brport_get(struct ifnet *ifp) { struct arpcom *ac = (struct arpcom *)ifp; SMR_ASSERT_CRITICAL(); return (SMR_PTR_GET(&ac->ac_brport)); } const struct ether_brport * ether_brport_get_locked(struct ifnet *ifp) { struct arpcom *ac = (struct arpcom *)ifp; KERNEL_ASSERT_LOCKED(); return (SMR_PTR_GET_LOCKED(&ac->ac_brport)); } /* * Convert Ethernet address to printable (loggable) representation. */ static char digits[] = "0123456789abcdef"; char * ether_sprintf(u_char *ap) { int i; static char etherbuf[ETHER_ADDR_LEN * 3]; char *cp = etherbuf; for (i = 0; i < ETHER_ADDR_LEN; i++) { *cp++ = digits[*ap >> 4]; *cp++ = digits[*ap++ & 0xf]; *cp++ = ':'; } *--cp = 0; return (etherbuf); } /* * Generate a (hopefully) acceptable MAC address, if asked. */ void ether_fakeaddr(struct ifnet *ifp) { static int unit; int rng = arc4random(); /* Non-multicast; locally administered address */ ((struct arpcom *)ifp)->ac_enaddr[0] = 0xfe; ((struct arpcom *)ifp)->ac_enaddr[1] = 0xe1; ((struct arpcom *)ifp)->ac_enaddr[2] = 0xba; ((struct arpcom *)ifp)->ac_enaddr[3] = 0xd0 | (unit++ & 0xf); ((struct arpcom *)ifp)->ac_enaddr[4] = rng; ((struct arpcom *)ifp)->ac_enaddr[5] = rng >> 8; } /* * Perform common duties while attaching to interface list */ void ether_ifattach(struct ifnet *ifp) { struct arpcom *ac = (struct arpcom *)ifp; /* * Any interface which provides a MAC address which is obviously * invalid gets whacked, so that users will notice. */ if (ETHER_IS_MULTICAST(((struct arpcom *)ifp)->ac_enaddr)) ether_fakeaddr(ifp); ifp->if_type = IFT_ETHER; ifp->if_addrlen = ETHER_ADDR_LEN; ifp->if_hdrlen = ETHER_HDR_LEN; ifp->if_mtu = ETHERMTU; ifp->if_input = ether_input; if (ifp->if_output == NULL) ifp->if_output = ether_output; ifp->if_rtrequest = ether_rtrequest; if (ifp->if_hardmtu == 0) ifp->if_hardmtu = ETHERMTU; if_alloc_sadl(ifp); memcpy(LLADDR(ifp->if_sadl), ac->ac_enaddr, ifp->if_addrlen); LIST_INIT(&ac->ac_multiaddrs); #if NBPFILTER > 0 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, ETHER_HDR_LEN); #endif } void ether_ifdetach(struct ifnet *ifp) { struct arpcom *ac = (struct arpcom *)ifp; struct ether_multi *enm; /* Undo pseudo-driver changes. */ if_deactivate(ifp); while (!LIST_EMPTY(&ac->ac_multiaddrs)) { enm = LIST_FIRST(&ac->ac_multiaddrs); LIST_REMOVE(enm, enm_list); free(enm, M_IFMADDR, sizeof *enm); } } #if 0 /* * This is for reference. We have table-driven versions of the * crc32 generators, which are faster than the double-loop. */ u_int32_t __pure ether_crc32_le_update(u_int_32_t crc, const u_int8_t *buf, size_t len) { u_int32_t c, carry; size_t i, j; for (i = 0; i < len; i++) { c = buf[i]; for (j = 0; j < 8; j++) { carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01); crc >>= 1; c >>= 1; if (carry) crc = (crc ^ ETHER_CRC_POLY_LE); } } return (crc); } u_int32_t __pure ether_crc32_be_update(u_int_32_t crc, const u_int8_t *buf, size_t len) { u_int32_t c, carry; size_t i, j; for (i = 0; i < len; i++) { c = buf[i]; for (j = 0; j < 8; j++) { carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01); crc <<= 1; c >>= 1; if (carry) crc = (crc ^ ETHER_CRC_POLY_BE) | carry; } } return (crc); } #else u_int32_t __pure ether_crc32_le_update(u_int32_t crc, const u_int8_t *buf, size_t len) { static const u_int32_t crctab[] = { 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c }; size_t i; for (i = 0; i < len; i++) { crc ^= buf[i]; crc = (crc >> 4) ^ crctab[crc & 0xf]; crc = (crc >> 4) ^ crctab[crc & 0xf]; } return (crc); } u_int32_t __pure ether_crc32_be_update(u_int32_t crc, const u_int8_t *buf, size_t len) { static const u_int8_t rev[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf }; static const u_int32_t crctab[] = { 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd }; size_t i; u_int8_t data; for (i = 0; i < len; i++) { data = buf[i]; crc = (crc << 4) ^ crctab[(crc >> 28) ^ rev[data & 0xf]]; crc = (crc << 4) ^ crctab[(crc >> 28) ^ rev[data >> 4]]; } return (crc); } #endif u_int32_t ether_crc32_le(const u_int8_t *buf, size_t len) { return ether_crc32_le_update(0xffffffff, buf, len); } u_int32_t ether_crc32_be(const u_int8_t *buf, size_t len) { return ether_crc32_be_update(0xffffffff, buf, len); } u_char ether_ipmulticast_min[ETHER_ADDR_LEN] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; u_char ether_ipmulticast_max[ETHER_ADDR_LEN] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff }; #ifdef INET6 u_char ether_ip6multicast_min[ETHER_ADDR_LEN] = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 }; u_char ether_ip6multicast_max[ETHER_ADDR_LEN] = { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff }; #endif /* * Convert a sockaddr into an Ethernet address or range of Ethernet * addresses. */ int ether_multiaddr(struct sockaddr *sa, u_int8_t addrlo[ETHER_ADDR_LEN], u_int8_t addrhi[ETHER_ADDR_LEN]) { struct sockaddr_in *sin; #ifdef INET6 struct sockaddr_in6 *sin6; #endif /* INET6 */ switch (sa->sa_family) { case AF_UNSPEC: memcpy(addrlo, sa->sa_data, ETHER_ADDR_LEN); memcpy(addrhi, addrlo, ETHER_ADDR_LEN); break; case AF_INET: sin = satosin(sa); if (sin->sin_addr.s_addr == INADDR_ANY) { /* * An IP address of INADDR_ANY means listen to * or stop listening to all of the Ethernet * multicast addresses used for IP. * (This is for the sake of IP multicast routers.) */ memcpy(addrlo, ether_ipmulticast_min, ETHER_ADDR_LEN); memcpy(addrhi, ether_ipmulticast_max, ETHER_ADDR_LEN); } else { ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); memcpy(addrhi, addrlo, ETHER_ADDR_LEN); } break; #ifdef INET6 case AF_INET6: sin6 = satosin6(sa); if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { /* * An IP6 address of 0 means listen to or stop * listening to all of the Ethernet multicast * address used for IP6. * * (This might not be healthy, given IPv6's reliance on * multicast for things like neighbor discovery. * Perhaps initializing all-nodes, solicited nodes, and * possibly all-routers for this interface afterwards * is not a bad idea.) */ memcpy(addrlo, ether_ip6multicast_min, ETHER_ADDR_LEN); memcpy(addrhi, ether_ip6multicast_max, ETHER_ADDR_LEN); } else { ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo); memcpy(addrhi, addrlo, ETHER_ADDR_LEN); } break; #endif default: return (EAFNOSUPPORT); } return (0); } /* * Add an Ethernet multicast address or range of addresses to the list for a * given interface. */ int ether_addmulti(struct ifreq *ifr, struct arpcom *ac) { struct ether_multi *enm; u_char addrlo[ETHER_ADDR_LEN]; u_char addrhi[ETHER_ADDR_LEN]; int s = splnet(), error; error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi); if (error != 0) { splx(s); return (error); } /* * Verify that we have valid Ethernet multicast addresses. */ if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) { splx(s); return (EINVAL); } /* * See if the address range is already in the list. */ ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); if (enm != NULL) { /* * Found it; just increment the reference count. */ refcnt_take(&enm->enm_refcnt); splx(s); return (0); } /* * New address or range; malloc a new multicast record * and link it into the interface's multicast list. */ enm = malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT); if (enm == NULL) { splx(s); return (ENOBUFS); } memcpy(enm->enm_addrlo, addrlo, ETHER_ADDR_LEN); memcpy(enm->enm_addrhi, addrhi, ETHER_ADDR_LEN); refcnt_init_trace(&enm->enm_refcnt, DT_REFCNT_IDX_ETHMULTI); LIST_INSERT_HEAD(&ac->ac_multiaddrs, enm, enm_list); ac->ac_multicnt++; if (memcmp(addrlo, addrhi, ETHER_ADDR_LEN) != 0) ac->ac_multirangecnt++; splx(s); /* * Return ENETRESET to inform the driver that the list has changed * and its reception filter should be adjusted accordingly. */ return (ENETRESET); } /* * Delete a multicast address record. */ int ether_delmulti(struct ifreq *ifr, struct arpcom *ac) { struct ether_multi *enm; u_char addrlo[ETHER_ADDR_LEN]; u_char addrhi[ETHER_ADDR_LEN]; int s = splnet(), error; error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi); if (error != 0) { splx(s); return (error); } /* * Look up the address in our list. */ ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); if (enm == NULL) { splx(s); return (ENXIO); } if (refcnt_rele(&enm->enm_refcnt) == 0) { /* * Still some claims to this record. */ splx(s); return (0); } /* * No remaining claims to this record; unlink and free it. */ LIST_REMOVE(enm, enm_list); free(enm, M_IFMADDR, sizeof *enm); ac->ac_multicnt--; if (memcmp(addrlo, addrhi, ETHER_ADDR_LEN) != 0) ac->ac_multirangecnt--; splx(s); /* * Return ENETRESET to inform the driver that the list has changed * and its reception filter should be adjusted accordingly. */ return (ENETRESET); } uint64_t ether_addr_to_e64(const struct ether_addr *ea) { uint64_t e64 = 0; size_t i; for (i = 0; i < nitems(ea->ether_addr_octet); i++) { e64 <<= 8; e64 |= ea->ether_addr_octet[i]; } return (e64); } void ether_e64_to_addr(struct ether_addr *ea, uint64_t e64) { size_t i = nitems(ea->ether_addr_octet); do { ea->ether_addr_octet[--i] = e64; e64 >>= 8; } while (i > 0); } /* Parse different TCP/IP protocol headers for a quick view inside an mbuf. */ void ether_extract_headers(struct mbuf *m0, struct ether_extracted *ext) { struct mbuf *m; size_t hlen, iplen; int hoff; uint8_t ipproto; uint16_t ether_type; /* gcc 4.2.1 on sparc64 may create 32 bit loads on unaligned mbuf */ union { u_char hc_data; #if _BYTE_ORDER == _LITTLE_ENDIAN struct { u_int hl:4, /* header length */ v:4; /* version */ } hc_ip; struct { u_int x2:4, /* (unused) */ off:4; /* data offset */ } hc_th; #endif #if _BYTE_ORDER == _BIG_ENDIAN struct { u_int v:4, /* version */ hl:4; /* header length */ } hc_ip; struct { u_int off:4, /* data offset */ x2:4; /* (unused) */ } hc_th; #endif } hdrcpy; /* Return NULL if header was not recognized. */ memset(ext, 0, sizeof(*ext)); KASSERT(ISSET(m0->m_flags, M_PKTHDR)); ext->paylen = m0->m_pkthdr.len; if (m0->m_len < sizeof(*ext->eh)) { DPRINTF("m_len %d, eh %zu", m0->m_len, sizeof(*ext->eh)); return; } ext->eh = mtod(m0, struct ether_header *); ether_type = ntohs(ext->eh->ether_type); hlen = sizeof(*ext->eh); if (ext->paylen < hlen) { DPRINTF("paylen %u, ehlen %zu", ext->paylen, hlen); ext->eh = NULL; return; } ext->paylen -= hlen; #if NVLAN > 0 if (ether_type == ETHERTYPE_VLAN) { if (m0->m_len < sizeof(*ext->evh)) { DPRINTF("m_len %d, evh %zu", m0->m_len, sizeof(*ext->evh)); return; } ext->evh = mtod(m0, struct ether_vlan_header *); ether_type = ntohs(ext->evh->evl_proto); hlen = sizeof(*ext->evh); if (sizeof(*ext->eh) + ext->paylen < hlen) { DPRINTF("paylen %zu, evhlen %zu", sizeof(*ext->eh) + ext->paylen, hlen); ext->evh = NULL; return; } ext->paylen = sizeof(*ext->eh) + ext->paylen - hlen; } #endif switch (ether_type) { case ETHERTYPE_IP: m = m_getptr(m0, hlen, &hoff); if (m == NULL || m->m_len - hoff < sizeof(*ext->ip4)) { DPRINTF("m_len %d, hoff %d, ip4 %zu", m ? m->m_len : -1, hoff, sizeof(*ext->ip4)); return; } ext->ip4 = (struct ip *)(mtod(m, caddr_t) + hoff); memcpy(&hdrcpy.hc_data, ext->ip4, 1); hlen = hdrcpy.hc_ip.hl << 2; if (m->m_len - hoff < hlen) { DPRINTF("m_len %d, hoff %d, iphl %zu", m ? m->m_len : -1, hoff, hlen); ext->ip4 = NULL; return; } if (ext->paylen < hlen) { DPRINTF("paylen %u, ip4hlen %zu", ext->paylen, hlen); ext->ip4 = NULL; return; } iplen = ntohs(ext->ip4->ip_len); if (ext->paylen < iplen) { DPRINTF("paylen %u, ip4len %zu", ext->paylen, iplen); ext->ip4 = NULL; return; } if (iplen < hlen) { DPRINTF("ip4len %zu, ip4hlen %zu", iplen, hlen); ext->ip4 = NULL; return; } ext->iplen = iplen; ext->iphlen = hlen; ext->paylen -= hlen; ipproto = ext->ip4->ip_p; if (ISSET(ntohs(ext->ip4->ip_off), IP_MF|IP_OFFMASK)) return; break; #ifdef INET6 case ETHERTYPE_IPV6: m = m_getptr(m0, hlen, &hoff); if (m == NULL || m->m_len - hoff < sizeof(*ext->ip6)) { DPRINTF("m_len %d, hoff %d, ip6 %zu", m ? m->m_len : -1, hoff, sizeof(*ext->ip6)); return; } ext->ip6 = (struct ip6_hdr *)(mtod(m, caddr_t) + hoff); hlen = sizeof(*ext->ip6); if (ext->paylen < hlen) { DPRINTF("paylen %u, ip6hlen %zu", ext->paylen, hlen); ext->ip6 = NULL; return; } iplen = hlen + ntohs(ext->ip6->ip6_plen); if (ext->paylen < iplen) { DPRINTF("paylen %u, ip6len %zu", ext->paylen, iplen); ext->ip6 = NULL; return; } ext->iplen = iplen; ext->iphlen = hlen; ext->paylen -= hlen; ipproto = ext->ip6->ip6_nxt; break; #endif default: return; } switch (ipproto) { case IPPROTO_TCP: m = m_getptr(m, hoff + hlen, &hoff); if (m == NULL || m->m_len - hoff < sizeof(*ext->tcp)) { DPRINTF("m_len %d, hoff %d, tcp %zu", m ? m->m_len : -1, hoff, sizeof(*ext->tcp)); return; } ext->tcp = (struct tcphdr *)(mtod(m, caddr_t) + hoff); memcpy(&hdrcpy.hc_data, &ext->tcp->th_flags - 1, 1); hlen = hdrcpy.hc_th.off << 2; if (m->m_len - hoff < hlen) { DPRINTF("m_len %d, hoff %d, thoff %zu", m ? m->m_len : -1, hoff, hlen); ext->tcp = NULL; return; } if (ext->iplen - ext->iphlen < hlen) { DPRINTF("iplen %u, iphlen %u, tcphlen %zu", ext->iplen, ext->iphlen, hlen); ext->tcp = NULL; return; } ext->tcphlen = hlen; ext->paylen -= hlen; break; case IPPROTO_UDP: m = m_getptr(m, hoff + hlen, &hoff); if (m == NULL || m->m_len - hoff < sizeof(*ext->udp)) { DPRINTF("m_len %d, hoff %d, tcp %zu", m ? m->m_len : -1, hoff, sizeof(*ext->tcp)); return; } ext->udp = (struct udphdr *)(mtod(m, caddr_t) + hoff); hlen = sizeof(*ext->udp); if (ext->iplen - ext->iphlen < hlen) { DPRINTF("iplen %u, iphlen %u, udphlen %zu", ext->iplen, ext->iphlen, hlen); ext->udp = NULL; return; } break; } DNPRINTF(2, "%s%s%s%s%s%s ip %u, iph %u, tcph %u, payl %u", ext->eh ? "eh," : "", ext->evh ? "evh," : "", ext->ip4 ? "ip4," : "", ext->ip6 ? "ip6," : "", ext->tcp ? "tcp," : "", ext->udp ? "udp," : "", ext->iplen, ext->iphlen, ext->tcphlen, ext->paylen); }
4 2 2 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 /* $OpenBSD: disksubr.c,v 1.78 2017/02/28 10:49:37 natano Exp $ */ /* $NetBSD: disksubr.c,v 1.21 1996/05/03 19:42:03 christos Exp $ */ /* * Copyright (c) 1996 Theo de Raadt * Copyright (c) 1982, 1986, 1988 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <sys/param.h> #include <sys/buf.h> #include <sys/disklabel.h> #include <sys/disk.h> #include <sys/reboot.h> #include <sys/conf.h> #ifdef DEBUG #include <sys/systm.h> #endif #include <machine/biosvar.h> bios_diskinfo_t *bios_getdiskinfo(dev_t dev); /* * Attempt to read a disk label from a device * using the indicated strategy routine. * The label must be partly set up before this: * secpercyl, secsize and anything required for a block i/o read * operation in the driver's strategy/start routines * must be filled in before calling us. * * If dos partition table requested, attempt to load it and * find disklabel inside a DOS partition. * * We would like to check if each MBR has a valid DOSMBR_SIGNATURE, but * we cannot because it doesn't always exist. So.. we assume the * MBR is valid. */ int readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, int spoofonly) { bios_diskinfo_t *pdi; struct buf *bp = NULL; dev_t devno; int error; if ((error = initdisklabel(lp))) goto done; /* Look for any BIOS geometry information we should honour. */ devno = chrtoblk(dev); if (devno == NODEV) devno = dev; pdi = bios_getdiskinfo(MAKEBOOTDEV(major(devno), 0, 0, DISKUNIT(devno), RAW_PART)); if (pdi != NULL && pdi->bios_heads > 0 && pdi->bios_sectors > 0) { #ifdef DEBUG printf("Disk GEOM %u/%u/%u -> BIOS GEOM %u/%u/%llu\n", lp->d_ntracks, lp->d_nsectors, lp->d_ncylinders, pdi->bios_heads, pdi->bios_sectors, DL_GETDSIZE(lp) / (pdi->bios_heads * pdi->bios_sectors)); #endif lp->d_ntracks = pdi->bios_heads; lp->d_nsectors = pdi->bios_sectors; lp->d_secpercyl = pdi->bios_sectors * pdi->bios_heads; lp->d_ncylinders = DL_GETDSIZE(lp) / lp->d_secpercyl; } /* get a buffer and initialize it */ bp = geteblk(lp->d_secsize); bp->b_dev = dev; error = readdoslabel(bp, strat, lp, NULL, spoofonly); if (error == 0) goto done; #if defined(CD9660) error = iso_disklabelspoof(dev, strat, lp); if (error == 0) goto done; #endif #if defined(UDF) error = udf_disklabelspoof(dev, strat, lp); if (error == 0) goto done; #endif done: if (bp) { bp->b_flags |= B_INVAL; brelse(bp); } disk_change = 1; return (error); } /* * Write disk label back to device after modification. */ int writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp) { daddr_t partoff = -1; int error = EIO; int offset; struct disklabel *dlp; struct buf *bp = NULL; /* get a buffer and initialize it */ bp = geteblk(lp->d_secsize); bp->b_dev = dev; if (readdoslabel(bp, strat, lp, &partoff, 1) != 0) goto done; /* Read it in, slap the new label in, and write it back out */ error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp, partoff + DOS_LABELSECTOR)); if (error) goto done; offset = DL_BLKOFFSET(lp, partoff + DOS_LABELSECTOR); dlp = (struct disklabel *)(bp->b_data + offset); *dlp = *lp; CLR(bp->b_flags, B_READ | B_WRITE | B_DONE); SET(bp->b_flags, B_BUSY | B_WRITE | B_RAW); (*strat)(bp); error = biowait(bp); done: if (bp) { bp->b_flags |= B_INVAL; brelse(bp); } disk_change = 1; return (error); }
open /syzkaller/managers/main/kernel/machine/cpufunc.h: no such file or directory
1491 1519 1918 1915 5 5 77 77 5 5 5 41 42 727 728 727 729 728 628 2756 59 2741 4 1 1516 1777 2252 677 64 115 633 101 677 677 633 2848 950 2546 150 150 7 396 396 373 36 396 235 235 233 236 205 98 202 11 119 159 27 231 326 326 326 199 199 27 99 198 9 199 86 190 9 5 4 4 5 1290 7 1287 1285 9 17 31 17 13 44 478 46 3 4 4 5 396 55 4 66 1609 1605 229 224 1 1 80 80 10 10 1 70 124 293 24 23 11 96 22 99 26 26 51 13 7 54 15 13 5 13 5 53 53 1 3 3 33 33 7 7 11 3 2 1 2 2 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 /* $OpenBSD: uipc_mbuf.c,v 1.290 2024/03/05 18:52:41 bluhm Exp $ */ /* $NetBSD: uipc_mbuf.c,v 1.15.4.1 1996/06/13 17:11:44 cgd Exp $ */ /* * Copyright (c) 1982, 1986, 1988, 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 */ /* * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 * * NRL grants permission for redistribution and use in source and binary * forms, with or without modification, of the software and documentation * created at NRL provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgements: * This product includes software developed by the University of * California, Berkeley and its contributors. * This product includes software developed at the Information * Technology Division, US Naval Research Laboratory. * 4. Neither the name of the NRL nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the US Naval * Research Laboratory (NRL). */ #include "pf.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/atomic.h> #include <sys/mbuf.h> #include <sys/pool.h> #include <sys/percpu.h> #include <sys/sysctl.h> #include <sys/socket.h> #include <net/if.h> #include <uvm/uvm_extern.h> #ifdef DDB #include <machine/db_machdep.h> #endif #if NPF > 0 #include <net/pfvar.h> #endif /* NPF > 0 */ /* mbuf stats */ COUNTERS_BOOT_MEMORY(mbstat_boot, MBSTAT_COUNT); struct cpumem *mbstat = COUNTERS_BOOT_INITIALIZER(mbstat_boot); /* mbuf pools */ struct pool mbpool; struct pool mtagpool; /* mbuf cluster pools */ u_int mclsizes[MCLPOOLS] = { MCLBYTES, /* must be at slot 0 */ MCLBYTES + 2, /* ETHER_ALIGNED 2k mbufs */ 4 * 1024, 8 * 1024, 9 * 1024, 12 * 1024, 16 * 1024, 64 * 1024 }; static char mclnames[MCLPOOLS][8]; struct pool mclpools[MCLPOOLS]; struct pool *m_clpool(u_int); int max_linkhdr; /* largest link-level header */ int max_protohdr; /* largest protocol header */ int max_hdr; /* largest link+protocol header */ struct mutex m_extref_mtx = MUTEX_INITIALIZER(IPL_NET); void m_extfree(struct mbuf *); void m_zero(struct mbuf *); unsigned long mbuf_mem_limit; /* how much memory can be allocated */ unsigned long mbuf_mem_alloc; /* how much memory has been allocated */ void *m_pool_alloc(struct pool *, int, int *); void m_pool_free(struct pool *, void *); struct pool_allocator m_pool_allocator = { m_pool_alloc, m_pool_free, 0 /* will be copied from pool_allocator_multi */ }; static void (*mextfree_fns[4])(caddr_t, u_int, void *); static u_int num_extfree_fns; #define M_DATABUF(m) ((m)->m_flags & M_EXT ? (m)->m_ext.ext_buf : \ (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat) #define M_SIZE(m) ((m)->m_flags & M_EXT ? (m)->m_ext.ext_size : \ (m)->m_flags & M_PKTHDR ? MHLEN : MLEN) /* * Initialize the mbuf allocator. */ void mbinit(void) { int i, error; unsigned int lowbits; CTASSERT(MSIZE == sizeof(struct mbuf)); m_pool_allocator.pa_pagesz = pool_allocator_multi.pa_pagesz; mbuf_mem_alloc = 0; #if DIAGNOSTIC if (mclsizes[0] != MCLBYTES) panic("mbinit: the smallest cluster size != MCLBYTES"); if (mclsizes[nitems(mclsizes) - 1] != MAXMCLBYTES) panic("mbinit: the largest cluster size != MAXMCLBYTES"); #endif m_pool_init(&mbpool, MSIZE, 64, "mbufpl"); pool_init(&mtagpool, PACKET_TAG_MAXSIZE + sizeof(struct m_tag), 0, IPL_NET, 0, "mtagpl", NULL); for (i = 0; i < nitems(mclsizes); i++) { lowbits = mclsizes[i] & ((1 << 10) - 1); if (lowbits) { snprintf(mclnames[i], sizeof(mclnames[0]), "mcl%dk%u", mclsizes[i] >> 10, lowbits); } else { snprintf(mclnames[i], sizeof(mclnames[0]), "mcl%dk", mclsizes[i] >> 10); } m_pool_init(&mclpools[i], mclsizes[i], 64, mclnames[i]); } error = nmbclust_update(nmbclust); KASSERT(error == 0); (void)mextfree_register(m_extfree_pool); KASSERT(num_extfree_fns == 1); } void mbcpuinit(void) { int i; mbstat = counters_alloc_ncpus(mbstat, MBSTAT_COUNT); pool_cache_init(&mbpool); pool_cache_init(&mtagpool); for (i = 0; i < nitems(mclsizes); i++) pool_cache_init(&mclpools[i]); } int nmbclust_update(long newval) { int i; if (newval <= 0 || newval > LONG_MAX / MCLBYTES) return ERANGE; /* update the global mbuf memory limit */ nmbclust = newval; mbuf_mem_limit = nmbclust * MCLBYTES; pool_wakeup(&mbpool); for (i = 0; i < nitems(mclsizes); i++) pool_wakeup(&mclpools[i]); return 0; } /* * Space allocation routines. */ struct mbuf * m_get(int nowait, int type) { struct mbuf *m; struct counters_ref cr; uint64_t *counters; int s; KASSERT(type >= 0 && type < MT_NTYPES); m = pool_get(&mbpool, nowait == M_WAIT ? PR_WAITOK : PR_NOWAIT); if (m == NULL) return (NULL); s = splnet(); counters = counters_enter(&cr, mbstat); counters[type]++; counters_leave(&cr, mbstat); splx(s); m->m_type = type; m->m_next = NULL; m->m_nextpkt = NULL; m->m_data = m->m_dat; m->m_flags = 0; return (m); } /* * ATTN: When changing anything here check m_inithdr() and m_defrag() those * may need to change as well. */ struct mbuf * m_gethdr(int nowait, int type) { struct mbuf *m; struct counters_ref cr; uint64_t *counters; int s; KASSERT(type >= 0 && type < MT_NTYPES); m = pool_get(&mbpool, nowait == M_WAIT ? PR_WAITOK : PR_NOWAIT); if (m == NULL) return (NULL); s = splnet(); counters = counters_enter(&cr, mbstat); counters[type]++; counters_leave(&cr, mbstat); splx(s); m->m_type = type; return (m_inithdr(m)); } struct mbuf * m_inithdr(struct mbuf *m) { /* keep in sync with m_gethdr */ m->m_next = NULL; m->m_nextpkt = NULL; m->m_data = m->m_pktdat; m->m_flags = M_PKTHDR; memset(&m->m_pkthdr, 0, sizeof(m->m_pkthdr)); m->m_pkthdr.pf.prio = IFQ_DEFPRIO; return (m); } static inline void m_clearhdr(struct mbuf *m) { /* delete all mbuf tags to reset the state */ m_tag_delete_chain(m); #if NPF > 0 pf_mbuf_unlink_state_key(m); pf_mbuf_unlink_inpcb(m); #endif /* NPF > 0 */ memset(&m->m_pkthdr, 0, sizeof(m->m_pkthdr)); } void m_removehdr(struct mbuf *m) { KASSERT(m->m_flags & M_PKTHDR); m_clearhdr(m); m->m_flags &= ~M_PKTHDR; } void m_resethdr(struct mbuf *m) { int len = m->m_pkthdr.len; u_int8_t loopcnt = m->m_pkthdr.ph_loopcnt; KASSERT(m->m_flags & M_PKTHDR); m->m_flags &= (M_EXT|M_PKTHDR|M_EOR|M_EXTWR|M_ZEROIZE); m_clearhdr(m); /* like m_inithdr(), but keep any associated data and mbufs */ m->m_pkthdr.pf.prio = IFQ_DEFPRIO; m->m_pkthdr.len = len; m->m_pkthdr.ph_loopcnt = loopcnt; } void m_calchdrlen(struct mbuf *m) { struct mbuf *n; int plen = 0; KASSERT(m->m_flags & M_PKTHDR); for (n = m; n; n = n->m_next) plen += n->m_len; m->m_pkthdr.len = plen; } struct mbuf * m_getclr(int nowait, int type) { struct mbuf *m; MGET(m, nowait, type); if (m == NULL) return (NULL); memset(mtod(m, caddr_t), 0, MLEN); return (m); } struct pool * m_clpool(u_int pktlen) { struct pool *pp; int pi; for (pi = 0; pi < nitems(mclpools); pi++) { pp = &mclpools[pi]; if (pktlen <= pp->pr_size) return (pp); } return (NULL); } struct mbuf * m_clget(struct mbuf *m, int how, u_int pktlen) { struct mbuf *m0 = NULL; struct pool *pp; caddr_t buf; pp = m_clpool(pktlen); #ifdef DIAGNOSTIC if (pp == NULL) panic("m_clget: request for %u byte cluster", pktlen); #endif if (m == NULL) { m0 = m_gethdr(how, MT_DATA); if (m0 == NULL) return (NULL); m = m0; } buf = pool_get(pp, how == M_WAIT ? PR_WAITOK : PR_NOWAIT); if (buf == NULL) { m_freem(m0); return (NULL); } MEXTADD(m, buf, pp->pr_size, M_EXTWR, MEXTFREE_POOL, pp); return (m); } void m_extfree_pool(caddr_t buf, u_int size, void *pp) { pool_put(pp, buf); } struct mbuf * m_free(struct mbuf *m) { struct mbuf *n; struct counters_ref cr; uint64_t *counters; int s; if (m == NULL) return (NULL); s = splnet(); counters = counters_enter(&cr, mbstat); counters[m->m_type]--; counters_leave(&cr, mbstat); splx(s); n = m->m_next; if (m->m_flags & M_ZEROIZE) { m_zero(m); /* propagate M_ZEROIZE to the next mbuf in the chain */ if (n) n->m_flags |= M_ZEROIZE; } if (m->m_flags & M_PKTHDR) { m_tag_delete_chain(m); #if NPF > 0 pf_mbuf_unlink_state_key(m); pf_mbuf_unlink_inpcb(m); #endif /* NPF > 0 */ } if (m->m_flags & M_EXT) m_extfree(m); pool_put(&mbpool, m); return (n); } void m_extref(struct mbuf *o, struct mbuf *n) { int refs = MCLISREFERENCED(o); n->m_flags |= o->m_flags & (M_EXT|M_EXTWR); if (refs) mtx_enter(&m_extref_mtx); n->m_ext.ext_nextref = o->m_ext.ext_nextref; n->m_ext.ext_prevref = o; o->m_ext.ext_nextref = n; n->m_ext.ext_nextref->m_ext.ext_prevref = n; if (refs) mtx_leave(&m_extref_mtx); MCLREFDEBUGN((n), __FILE__, __LINE__); } static inline u_int m_extunref(struct mbuf *m) { int refs = 0; if (!MCLISREFERENCED(m)) return (0); mtx_enter(&m_extref_mtx); if (MCLISREFERENCED(m)) { m->m_ext.ext_nextref->m_ext.ext_prevref = m->m_ext.ext_prevref; m->m_ext.ext_prevref->m_ext.ext_nextref = m->m_ext.ext_nextref; refs = 1; } mtx_leave(&m_extref_mtx); return (refs); } /* * Returns a number for use with MEXTADD. * Should only be called once per function. * Drivers can be assured that the index will be non zero. */ u_int mextfree_register(void (*fn)(caddr_t, u_int, void *)) { KASSERT(num_extfree_fns < nitems(mextfree_fns)); mextfree_fns[num_extfree_fns] = fn; return num_extfree_fns++; } void m_extfree(struct mbuf *m) { if (m_extunref(m) == 0) { KASSERT(m->m_ext.ext_free_fn < num_extfree_fns); mextfree_fns[m->m_ext.ext_free_fn](m->m_ext.ext_buf, m->m_ext.ext_size, m->m_ext.ext_arg); } m->m_flags &= ~(M_EXT|M_EXTWR); } struct mbuf * m_freem(struct mbuf *m) { struct mbuf *n; if (m == NULL) return (NULL); n = m->m_nextpkt; do m = m_free(m); while (m != NULL); return (n); } void m_purge(struct mbuf *m) { while (m != NULL) m = m_freem(m); } /* * mbuf chain defragmenter. This function uses some evil tricks to defragment * an mbuf chain into a single buffer without changing the mbuf pointer. * This needs to know a lot of the mbuf internals to make this work. * The resulting mbuf is not aligned to IP header to assist DMA transfers. */ int m_defrag(struct mbuf *m, int how) { struct mbuf *m0; if (m->m_next == NULL) return (0); KASSERT(m->m_flags & M_PKTHDR); if ((m0 = m_gethdr(how, m->m_type)) == NULL) return (ENOBUFS); if (m->m_pkthdr.len > MHLEN) { MCLGETL(m0, how, m->m_pkthdr.len); if (!(m0->m_flags & M_EXT)) { m_free(m0); return (ENOBUFS); } } m_copydata(m, 0, m->m_pkthdr.len, mtod(m0, caddr_t)); m0->m_pkthdr.len = m0->m_len = m->m_pkthdr.len; /* free chain behind and possible ext buf on the first mbuf */ m_freem(m->m_next); m->m_next = NULL; if (m->m_flags & M_EXT) m_extfree(m); /* * Bounce copy mbuf over to the original mbuf and set everything up. * This needs to reset or clear all pointers that may go into the * original mbuf chain. */ if (m0->m_flags & M_EXT) { memcpy(&m->m_ext, &m0->m_ext, sizeof(struct mbuf_ext)); MCLINITREFERENCE(m); m->m_flags |= m0->m_flags & (M_EXT|M_EXTWR); m->m_data = m->m_ext.ext_buf; } else { m->m_data = m->m_pktdat; memcpy(m->m_data, m0->m_data, m0->m_len); } m->m_pkthdr.len = m->m_len = m0->m_len; m0->m_flags &= ~(M_EXT|M_EXTWR); /* cluster is gone */ m_free(m0); return (0); } /* * Mbuffer utility routines. */ /* * Ensure len bytes of contiguous space at the beginning of the mbuf chain */ struct mbuf * m_prepend(struct mbuf *m, int len, int how) { struct mbuf *mn; if (len > MHLEN) panic("mbuf prepend length too big"); if (m_leadingspace(m) >= len) { m->m_data -= len; m->m_len += len; } else { MGET(mn, how, m->m_type); if (mn == NULL) { m_freem(m); return (NULL); } if (m->m_flags & M_PKTHDR) M_MOVE_PKTHDR(mn, m); mn->m_next = m; m = mn; m_align(m, len); m->m_len = len; } if (m->m_flags & M_PKTHDR) m->m_pkthdr.len += len; return (m); } /* * Make a copy of an mbuf chain starting "off" bytes from the beginning, * continuing for "len" bytes. If len is M_COPYALL, copy to end of mbuf. * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller. */ struct mbuf * m_copym(struct mbuf *m0, int off, int len, int wait) { struct mbuf *m, *n, **np; struct mbuf *top; int copyhdr = 0; if (off < 0 || len < 0) panic("m_copym0: off %d, len %d", off, len); if (off == 0 && m0->m_flags & M_PKTHDR) copyhdr = 1; if ((m = m_getptr(m0, off, &off)) == NULL) panic("m_copym0: short mbuf chain"); np = &top; top = NULL; while (len > 0) { if (m == NULL) { if (len != M_COPYALL) panic("m_copym0: m == NULL and not COPYALL"); break; } MGET(n, wait, m->m_type); *np = n; if (n == NULL) goto nospace; if (copyhdr) { if (m_dup_pkthdr(n, m0, wait)) goto nospace; if (len != M_COPYALL) n->m_pkthdr.len = len; copyhdr = 0; } n->m_len = min(len, m->m_len - off); if (m->m_flags & M_EXT) { n->m_data = m->m_data + off; n->m_ext = m->m_ext; MCLADDREFERENCE(m, n); } else { n->m_data += m->m_data - (m->m_flags & M_PKTHDR ? m->m_pktdat : m->m_dat); n->m_data += off; memcpy(mtod(n, caddr_t), mtod(m, caddr_t) + off, n->m_len); } if (len != M_COPYALL) len -= n->m_len; off += n->m_len; #ifdef DIAGNOSTIC if (off > m->m_len) panic("m_copym0 overrun"); #endif if (off == m->m_len) { m = m->m_next; off = 0; } np = &n->m_next; } return (top); nospace: m_freem(top); return (NULL); } /* * Copy data from an mbuf chain starting "off" bytes from the beginning, * continuing for "len" bytes, into the indicated buffer. */ void m_copydata(struct mbuf *m, int off, int len, void *p) { caddr_t cp = p; unsigned count; if (off < 0) panic("m_copydata: off %d < 0", off); if (len < 0) panic("m_copydata: len %d < 0", len); if ((m = m_getptr(m, off, &off)) == NULL) panic("m_copydata: short mbuf chain"); while (len > 0) { if (m == NULL) panic("m_copydata: null mbuf"); count = min(m->m_len - off, len); memmove(cp, mtod(m, caddr_t) + off, count); len -= count; cp += count; off = 0; m = m->m_next; } } /* * Copy data from a buffer back into the indicated mbuf chain, * starting "off" bytes from the beginning, extending the mbuf * chain if necessary. The mbuf needs to be properly initialized * including the setting of m_len. */ int m_copyback(struct mbuf *m0, int off, int len, const void *_cp, int wait) { int mlen, totlen = 0; struct mbuf *m = m0, *n; caddr_t cp = (caddr_t)_cp; int error = 0; if (m0 == NULL) return (0); while (off > (mlen = m->m_len)) { off -= mlen; totlen += mlen; if (m->m_next == NULL) { if ((n = m_get(wait, m->m_type)) == NULL) { error = ENOBUFS; goto out; } if (off + len > MLEN) { MCLGETL(n, wait, off + len); if (!(n->m_flags & M_EXT)) { m_free(n); error = ENOBUFS; goto out; } } memset(mtod(n, caddr_t), 0, off); n->m_len = len + off; m->m_next = n; } m = m->m_next; } while (len > 0) { /* extend last packet to be filled fully */ if (m->m_next == NULL && (len > m->m_len - off)) m->m_len += min(len - (m->m_len - off), m_trailingspace(m)); mlen = min(m->m_len - off, len); memmove(mtod(m, caddr_t) + off, cp, mlen); cp += mlen; len -= mlen; totlen += mlen + off; if (len == 0) break; off = 0; if (m->m_next == NULL) { if ((n = m_get(wait, m->m_type)) == NULL) { error = ENOBUFS; goto out; } if (len > MLEN) { MCLGETL(n, wait, len); if (!(n->m_flags & M_EXT)) { m_free(n); error = ENOBUFS; goto out; } } n->m_len = len; m->m_next = n; } m = m->m_next; } out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen)) m->m_pkthdr.len = totlen; return (error); } /* * Concatenate mbuf chain n to m. * n might be copied into m (when n->m_len is small), therefore data portion of * n could be copied into an mbuf of different mbuf type. * Therefore both chains should be of the same type (e.g. MT_DATA). * Any m_pkthdr is not updated. */ void m_cat(struct mbuf *m, struct mbuf *n) { while (m->m_next) m = m->m_next; while (n) { if (M_READONLY(m) || n->m_len > m_trailingspace(m)) { /* just join the two chains */ m->m_next = n; return; } /* splat the data from one into the other */ memcpy(mtod(m, caddr_t) + m->m_len, mtod(n, caddr_t), n->m_len); m->m_len += n->m_len; n = m_free(n); } } void m_adj(struct mbuf *mp, int req_len) { int len = req_len; struct mbuf *m; int count; if (mp == NULL) return; if (len >= 0) { /* * Trim from head. */ m = mp; while (m != NULL && len > 0) { if (m->m_len <= len) { len -= m->m_len; m->m_data += m->m_len; m->m_len = 0; m = m->m_next; } else { m->m_data += len; m->m_len -= len; len = 0; } } if (mp->m_flags & M_PKTHDR) mp->m_pkthdr.len -= (req_len - len); } else { /* * Trim from tail. Scan the mbuf chain, * calculating its length and finding the last mbuf. * If the adjustment only affects this mbuf, then just * adjust and return. Otherwise, rescan and truncate * after the remaining size. */ len = -len; count = 0; m = mp; for (;;) { count += m->m_len; if (m->m_next == NULL) break; m = m->m_next; } if (m->m_len >= len) { m->m_len -= len; if (mp->m_flags & M_PKTHDR) mp->m_pkthdr.len -= len; return; } count -= len; if (count < 0) count = 0; /* * Correct length for chain is "count". * Find the mbuf with last data, adjust its length, * and toss data from remaining mbufs on chain. */ if (mp->m_flags & M_PKTHDR) mp->m_pkthdr.len = count; m = mp; for (;;) { if (m->m_len >= count) { m->m_len = count; break; } count -= m->m_len; m = m->m_next; } while ((m = m->m_next) != NULL) m->m_len = 0; } } /* * Rearrange an mbuf chain so that len bytes are contiguous * and in the data area of an mbuf (so that mtod will work * for a structure of size len). Returns the resulting * mbuf chain on success, frees it and returns null on failure. */ struct mbuf * m_pullup(struct mbuf *m0, int len) { struct mbuf *m; unsigned int adj; caddr_t head, tail; unsigned int space; /* if len is already contig in m0, then don't do any work */ if (len <= m0->m_len) return (m0); /* look for some data */ m = m0->m_next; if (m == NULL) goto freem0; head = M_DATABUF(m0); if (m0->m_len == 0) { while (m->m_len == 0) { m = m_free(m); if (m == NULL) goto freem0; } adj = mtod(m, unsigned long) & (sizeof(long) - 1); } else adj = mtod(m0, unsigned long) & (sizeof(long) - 1); tail = head + M_SIZE(m0); head += adj; if (!M_READONLY(m0) && len <= tail - head) { /* we can copy everything into the first mbuf */ if (m0->m_len == 0) { m0->m_data = head; } else if (len > tail - mtod(m0, caddr_t)) { /* need to memmove to make space at the end */ memmove(head, mtod(m0, caddr_t), m0->m_len); m0->m_data = head; } len -= m0->m_len; } else { /* the first mbuf is too small or read-only, make a new one */ space = adj + len; if (space > MAXMCLBYTES) goto bad; m0->m_next = m; m = m0; MGET(m0, M_DONTWAIT, m->m_type); if (m0 == NULL) goto bad; if (space > MHLEN) { MCLGETL(m0, M_DONTWAIT, space); if ((m0->m_flags & M_EXT) == 0) goto bad; } if (m->m_flags & M_PKTHDR) M_MOVE_PKTHDR(m0, m); m0->m_len = 0; m0->m_data += adj; } KDASSERT(m_trailingspace(m0) >= len); for (;;) { space = min(len, m->m_len); memcpy(mtod(m0, caddr_t) + m0->m_len, mtod(m, caddr_t), space); len -= space; m0->m_len += space; m->m_len -= space; if (m->m_len > 0) m->m_data += space; else m = m_free(m); if (len == 0) break; if (m == NULL) goto bad; } m0->m_next = m; /* link the chain back up */ return (m0); bad: m_freem(m); freem0: m_free(m0); return (NULL); } /* * Return a pointer to mbuf/offset of location in mbuf chain. */ struct mbuf * m_getptr(struct mbuf *m, int loc, int *off) { while (loc >= 0) { /* Normal end of search */ if (m->m_len > loc) { *off = loc; return (m); } else { loc -= m->m_len; if (m->m_next == NULL) { if (loc == 0) { /* Point at the end of valid data */ *off = m->m_len; return (m); } else { return (NULL); } } else { m = m->m_next; } } } return (NULL); } /* * Partition an mbuf chain in two pieces, returning the tail -- * all but the first len0 bytes. In case of failure, it returns NULL and * attempts to restore the chain to its original state. */ struct mbuf * m_split(struct mbuf *m0, int len0, int wait) { struct mbuf *m, *n; unsigned len = len0, remain, olen; for (m = m0; m && len > m->m_len; m = m->m_next) len -= m->m_len; if (m == NULL) return (NULL); remain = m->m_len - len; if (m0->m_flags & M_PKTHDR) { MGETHDR(n, wait, m0->m_type); if (n == NULL) return (NULL); if (m_dup_pkthdr(n, m0, wait)) { m_freem(n); return (NULL); } n->m_pkthdr.len -= len0; olen = m0->m_pkthdr.len; m0->m_pkthdr.len = len0; if (remain == 0) { n->m_next = m->m_next; m->m_next = NULL; n->m_len = 0; return (n); } if ((m->m_flags & M_EXT) == 0 && remain > MHLEN) { /* m can't be the lead packet */ m_align(n, 0); n->m_next = m_split(m, len, wait); if (n->m_next == NULL) { (void) m_free(n); m0->m_pkthdr.len = olen; return (NULL); } else { n->m_len = 0; return (n); } } } else if (remain == 0) { n = m->m_next; m->m_next = NULL; return (n); } else { MGET(n, wait, m->m_type); if (n == NULL) return (NULL); } if (m->m_flags & M_EXT) { n->m_ext = m->m_ext; MCLADDREFERENCE(m, n); n->m_data = m->m_data + len; } else { m_align(n, remain); memcpy(mtod(n, caddr_t), mtod(m, caddr_t) + len, remain); } n->m_len = remain; m->m_len = len; n->m_next = m->m_next; m->m_next = NULL; return (n); } /* * Make space for a new header of length hlen at skip bytes * into the packet. When doing this we allocate new mbufs only * when absolutely necessary. The mbuf where the new header * is to go is returned together with an offset into the mbuf. * If NULL is returned then the mbuf chain may have been modified; * the caller is assumed to always free the chain. */ struct mbuf * m_makespace(struct mbuf *m0, int skip, int hlen, int *off) { struct mbuf *m; unsigned remain; KASSERT(m0->m_flags & M_PKTHDR); /* * Limit the size of the new header to MHLEN. In case * skip = 0 and the first buffer is not a cluster this * is the maximum space available in that mbuf. * In other words this code never prepends a mbuf. */ KASSERT(hlen < MHLEN); for (m = m0; m && skip > m->m_len; m = m->m_next) skip -= m->m_len; if (m == NULL) return (NULL); /* * At this point skip is the offset into the mbuf m * where the new header should be placed. Figure out * if there's space to insert the new header. If so, * and copying the remainder makes sense then do so. * Otherwise insert a new mbuf in the chain, splitting * the contents of m as needed. */ remain = m->m_len - skip; /* data to move */ if (skip < remain && hlen <= m_leadingspace(m)) { if (skip) memmove(m->m_data-hlen, m->m_data, skip); m->m_data -= hlen; m->m_len += hlen; *off = skip; } else if (hlen > m_trailingspace(m)) { struct mbuf *n; if (remain > 0) { MGET(n, M_DONTWAIT, m->m_type); if (n && remain > MLEN) { MCLGETL(n, M_DONTWAIT, remain); if ((n->m_flags & M_EXT) == 0) { m_free(n); n = NULL; } } if (n == NULL) return (NULL); memcpy(n->m_data, mtod(m, char *) + skip, remain); n->m_len = remain; m->m_len -= remain; n->m_next = m->m_next; m->m_next = n; } if (hlen <= m_trailingspace(m)) { m->m_len += hlen; *off = skip; } else { n = m_get(M_DONTWAIT, m->m_type); if (n == NULL) return NULL; n->m_len = hlen; n->m_next = m->m_next; m->m_next = n; *off = 0; /* header is at front ... */ m = n; /* ... of new mbuf */ } } else { /* * Copy the remainder to the back of the mbuf * so there's space to write the new header. */ if (remain > 0) memmove(mtod(m, caddr_t) + skip + hlen, mtod(m, caddr_t) + skip, remain); m->m_len += hlen; *off = skip; } m0->m_pkthdr.len += hlen; /* adjust packet length */ return m; } /* * Routine to copy from device local memory into mbufs. */ struct mbuf * m_devget(char *buf, int totlen, int off) { struct mbuf *m; struct mbuf *top, **mp; int len; top = NULL; mp = &top; if (off < 0 || off > MHLEN) return (NULL); MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == NULL) return (NULL); m->m_pkthdr.len = totlen; len = MHLEN; while (totlen > 0) { if (top != NULL) { MGET(m, M_DONTWAIT, MT_DATA); if (m == NULL) { /* * As we might get called by pfkey, make sure * we do not leak sensitive data. */ top->m_flags |= M_ZEROIZE; m_freem(top); return (NULL); } len = MLEN; } if (totlen + off >= MINCLSIZE) { MCLGET(m, M_DONTWAIT); if (m->m_flags & M_EXT) len = MCLBYTES; } else { /* Place initial small packet/header at end of mbuf. */ if (top == NULL && totlen + off + max_linkhdr <= len) { m->m_data += max_linkhdr; len -= max_linkhdr; } } if (off) { m->m_data += off; len -= off; off = 0; } m->m_len = len = min(totlen, len); memcpy(mtod(m, void *), buf, (size_t)len); buf += len; *mp = m; mp = &m->m_next; totlen -= len; } return (top); } void m_zero(struct mbuf *m) { if (M_READONLY(m)) { mtx_enter(&m_extref_mtx); if ((m->m_flags & M_EXT) && MCLISREFERENCED(m)) { m->m_ext.ext_nextref->m_flags |= M_ZEROIZE; m->m_ext.ext_prevref->m_flags |= M_ZEROIZE; } mtx_leave(&m_extref_mtx); return; } explicit_bzero(M_DATABUF(m), M_SIZE(m)); } /* * Apply function f to the data in an mbuf chain starting "off" bytes from the * beginning, continuing for "len" bytes. */ int m_apply(struct mbuf *m, int off, int len, int (*f)(caddr_t, caddr_t, unsigned int), caddr_t fstate) { int rval; unsigned int count; if (len < 0) panic("m_apply: len %d < 0", len); if (off < 0) panic("m_apply: off %d < 0", off); while (off > 0) { if (m == NULL) panic("m_apply: null mbuf in skip"); if (off < m->m_len) break; off -= m->m_len; m = m->m_next; } while (len > 0) { if (m == NULL) panic("m_apply: null mbuf"); count = min(m->m_len - off, len); rval = f(fstate, mtod(m, caddr_t) + off, count); if (rval) return (rval); len -= count; off = 0; m = m->m_next; } return (0); } /* * Compute the amount of space available before the current start of data * in an mbuf. Read-only clusters never have space available. */ int m_leadingspace(struct mbuf *m) { if (M_READONLY(m)) return 0; KASSERT(m->m_data >= M_DATABUF(m)); return m->m_data - M_DATABUF(m); } /* * Compute the amount of space available after the end of data in an mbuf. * Read-only clusters never have space available. */ int m_trailingspace(struct mbuf *m) { if (M_READONLY(m)) return 0; KASSERT(M_DATABUF(m) + M_SIZE(m) >= (m->m_data + m->m_len)); return M_DATABUF(m) + M_SIZE(m) - (m->m_data + m->m_len); } /* * Set the m_data pointer of a newly-allocated mbuf to place an object of * the specified size at the end of the mbuf, longword aligned. */ void m_align(struct mbuf *m, int len) { KASSERT(len >= 0 && !M_READONLY(m)); KASSERT(m->m_data == M_DATABUF(m)); /* newly-allocated check */ KASSERT(((len + sizeof(long) - 1) &~ (sizeof(long) - 1)) <= M_SIZE(m)); m->m_data = M_DATABUF(m) + ((M_SIZE(m) - (len)) &~ (sizeof(long) - 1)); } /* * Duplicate mbuf pkthdr from from to to. * from must have M_PKTHDR set, and to must be empty. */ int m_dup_pkthdr(struct mbuf *to, struct mbuf *from, int wait) { int error; KASSERT(from->m_flags & M_PKTHDR); to->m_flags = (to->m_flags & (M_EXT | M_EXTWR)); to->m_flags |= (from->m_flags & M_COPYFLAGS); to->m_pkthdr = from->m_pkthdr; #if NPF > 0 to->m_pkthdr.pf.statekey = NULL; pf_mbuf_link_state_key(to, from->m_pkthdr.pf.statekey); to->m_pkthdr.pf.inp = NULL; pf_mbuf_link_inpcb(to, from->m_pkthdr.pf.inp); #endif /* NPF > 0 */ SLIST_INIT(&to->m_pkthdr.ph_tags); if ((error = m_tag_copy_chain(to, from, wait)) != 0) return (error); if ((to->m_flags & M_EXT) == 0) to->m_data = to->m_pktdat; return (0); } struct mbuf * m_dup_pkt(struct mbuf *m0, unsigned int adj, int wait) { struct mbuf *m; int len; KASSERT(m0->m_flags & M_PKTHDR); len = m0->m_pkthdr.len + adj; if (len > MAXMCLBYTES) /* XXX */ return (NULL); m = m_get(wait, m0->m_type); if (m == NULL) return (NULL); if (m_dup_pkthdr(m, m0, wait) != 0) goto fail; if (len > MHLEN) { MCLGETL(m, wait, len); if (!ISSET(m->m_flags, M_EXT)) goto fail; } m->m_len = m->m_pkthdr.len = len; m_adj(m, adj); m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, caddr_t)); return (m); fail: m_freem(m); return (NULL); } void m_microtime(const struct mbuf *m, struct timeval *tv) { if (ISSET(m->m_pkthdr.csum_flags, M_TIMESTAMP)) { struct timeval btv, utv; NSEC_TO_TIMEVAL(m->m_pkthdr.ph_timestamp, &utv); microboottime(&btv); timeradd(&btv, &utv, tv); } else microtime(tv); } void * m_pool_alloc(struct pool *pp, int flags, int *slowdown) { void *v; if (atomic_add_long_nv(&mbuf_mem_alloc, pp->pr_pgsize) > mbuf_mem_limit) goto fail; v = (*pool_allocator_multi.pa_alloc)(pp, flags, slowdown); if (v != NULL) return (v); fail: atomic_sub_long(&mbuf_mem_alloc, pp->pr_pgsize); return (NULL); } void m_pool_free(struct pool *pp, void *v) { (*pool_allocator_multi.pa_free)(pp, v); atomic_sub_long(&mbuf_mem_alloc, pp->pr_pgsize); } void m_pool_init(struct pool *pp, u_int size, u_int align, const char *wmesg) { pool_init(pp, size, align, IPL_NET, 0, wmesg, &m_pool_allocator); pool_set_constraints(pp, &kp_dma_contig); } u_int m_pool_used(void) { return ((mbuf_mem_alloc * 100) / mbuf_mem_limit); } #ifdef DDB void m_print(void *v, int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2)))) { struct mbuf *m = v; (*pr)("mbuf %p\n", m); (*pr)("m_type: %i\tm_flags: %b\n", m->m_type, m->m_flags, M_BITS); (*pr)("m_next: %p\tm_nextpkt: %p\n", m->m_next, m->m_nextpkt); (*pr)("m_data: %p\tm_len: %u\n", m->m_data, m->m_len); (*pr)("m_dat: %p\tm_pktdat: %p\n", m->m_dat, m->m_pktdat); if (m->m_flags & M_PKTHDR) { (*pr)("m_ptkhdr.ph_ifidx: %u\tm_pkthdr.len: %i\n", m->m_pkthdr.ph_ifidx, m->m_pkthdr.len); (*pr)("m_ptkhdr.ph_tags: %p\tm_pkthdr.ph_tagsset: %b\n", SLIST_FIRST(&m->m_pkthdr.ph_tags), m->m_pkthdr.ph_tagsset, MTAG_BITS); (*pr)("m_pkthdr.ph_flowid: %u\tm_pkthdr.ph_loopcnt: %u\n", m->m_pkthdr.ph_flowid, m->m_pkthdr.ph_loopcnt); (*pr)("m_pkthdr.csum_flags: %b\n", m->m_pkthdr.csum_flags, MCS_BITS); (*pr)("m_pkthdr.ether_vtag: %u\tm_ptkhdr.ph_rtableid: %u\n", m->m_pkthdr.ether_vtag, m->m_pkthdr.ph_rtableid); (*pr)("m_pkthdr.pf.statekey: %p\tm_pkthdr.pf.inp %p\n", m->m_pkthdr.pf.statekey, m->m_pkthdr.pf.inp); (*pr)("m_pkthdr.pf.qid: %u\tm_pkthdr.pf.tag: %u\n", m->m_pkthdr.pf.qid, m->m_pkthdr.pf.tag); (*pr)("m_pkthdr.pf.flags: %b\n", m->m_pkthdr.pf.flags, MPF_BITS); (*pr)("m_pkthdr.pf.routed: %u\tm_pkthdr.pf.prio: %u\n", m->m_pkthdr.pf.routed, m->m_pkthdr.pf.prio); } if (m->m_flags & M_EXT) { (*pr)("m_ext.ext_buf: %p\tm_ext.ext_size: %u\n", m->m_ext.ext_buf, m->m_ext.ext_size); (*pr)("m_ext.ext_free_fn: %u\tm_ext.ext_arg: %p\n", m->m_ext.ext_free_fn, m->m_ext.ext_arg); (*pr)("m_ext.ext_nextref: %p\tm_ext.ext_prevref: %p\n", m->m_ext.ext_nextref, m->m_ext.ext_prevref); } } #endif /* * mbuf lists */ void ml_init(struct mbuf_list *ml) { ml->ml_head = ml->ml_tail = NULL; ml->ml_len = 0; } void ml_enqueue(struct mbuf_list *ml, struct mbuf *m) { if (ml->ml_tail == NULL) ml->ml_head = ml->ml_tail = m; else { ml->ml_tail->m_nextpkt = m; ml->ml_tail = m; } m->m_nextpkt = NULL; ml->ml_len++; } void ml_enlist(struct mbuf_list *mla, struct mbuf_list *mlb) { if (!ml_empty(mlb)) { if (ml_empty(mla)) mla->ml_head = mlb->ml_head; else mla->ml_tail->m_nextpkt = mlb->ml_head; mla->ml_tail = mlb->ml_tail; mla->ml_len += mlb->ml_len; ml_init(mlb); } } struct mbuf * ml_dequeue(struct mbuf_list *ml) { struct mbuf *m; m = ml->ml_head; if (m != NULL) { ml->ml_head = m->m_nextpkt; if (ml->ml_head == NULL) ml->ml_tail = NULL; m->m_nextpkt = NULL; ml->ml_len--; } return (m); } struct mbuf * ml_dechain(struct mbuf_list *ml) { struct mbuf *m0; m0 = ml->ml_head; ml_init(ml); return (m0); } unsigned int ml_purge(struct mbuf_list *ml) { struct mbuf *m, *n; unsigned int len; for (m = ml->ml_head; m != NULL; m = n) { n = m->m_nextpkt; m_freem(m); } len = ml->ml_len; ml_init(ml); return (len); } unsigned int ml_hdatalen(struct mbuf_list *ml) { struct mbuf *m; m = ml->ml_head; if (m == NULL) return (0); KASSERT(ISSET(m->m_flags, M_PKTHDR)); return (m->m_pkthdr.len); } /* * mbuf queues */ void mq_init(struct mbuf_queue *mq, u_int maxlen, int ipl) { mtx_init(&mq->mq_mtx, ipl); ml_init(&mq->mq_list); mq->mq_maxlen = maxlen; } int mq_push(struct mbuf_queue *mq, struct mbuf *m) { struct mbuf *dropped = NULL; mtx_enter(&mq->mq_mtx); if (mq_len(mq) >= mq->mq_maxlen) { mq->mq_drops++; dropped = ml_dequeue(&mq->mq_list); } ml_enqueue(&mq->mq_list, m); mtx_leave(&mq->mq_mtx); if (dropped) m_freem(dropped); return (dropped != NULL); } int mq_enqueue(struct mbuf_queue *mq, struct mbuf *m) { int dropped = 0; mtx_enter(&mq->mq_mtx); if (mq_len(mq) < mq->mq_maxlen) ml_enqueue(&mq->mq_list, m); else { mq->mq_drops++; dropped = 1; } mtx_leave(&mq->mq_mtx); if (dropped) m_freem(m); return (dropped); } struct mbuf * mq_dequeue(struct mbuf_queue *mq) { struct mbuf *m; mtx_enter(&mq->mq_mtx); m = ml_dequeue(&mq->mq_list); mtx_leave(&mq->mq_mtx); return (m); } int mq_enlist(struct mbuf_queue *mq, struct mbuf_list *ml) { struct mbuf *m; int dropped = 0; mtx_enter(&mq->mq_mtx); if (mq_len(mq) < mq->mq_maxlen) ml_enlist(&mq->mq_list, ml); else { dropped = ml_len(ml); mq->mq_drops += dropped; } mtx_leave(&mq->mq_mtx); if (dropped) { while ((m = ml_dequeue(ml)) != NULL) m_freem(m); } return (dropped); } void mq_delist(struct mbuf_queue *mq, struct mbuf_list *ml) { mtx_enter(&mq->mq_mtx); *ml = mq->mq_list; ml_init(&mq->mq_list); mtx_leave(&mq->mq_mtx); } struct mbuf * mq_dechain(struct mbuf_queue *mq) { struct mbuf *m0; mtx_enter(&mq->mq_mtx); m0 = ml_dechain(&mq->mq_list); mtx_leave(&mq->mq_mtx); return (m0); } unsigned int mq_purge(struct mbuf_queue *mq) { struct mbuf_list ml; mq_delist(mq, &ml); return (ml_purge(&ml)); } unsigned int mq_hdatalen(struct mbuf_queue *mq) { unsigned int hdatalen; mtx_enter(&mq->mq_mtx); hdatalen = ml_hdatalen(&mq->mq_list); mtx_leave(&mq->mq_mtx); return (hdatalen); } void mq_set_maxlen(struct mbuf_queue *mq, u_int maxlen) { mtx_enter(&mq->mq_mtx); mq->mq_maxlen = maxlen; mtx_leave(&mq->mq_mtx); } int sysctl_mq(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct mbuf_queue *mq) { unsigned int maxlen; int error; /* All sysctl names at this level are terminal. */ if (namelen != 1) return (ENOTDIR); switch (name[0]) { case IFQCTL_LEN: return (sysctl_rdint(oldp, oldlenp, newp, mq_len(mq))); case IFQCTL_MAXLEN: maxlen = mq->mq_maxlen; error = sysctl_int(oldp, oldlenp, newp, newlen, &maxlen); if (error == 0) mq_set_maxlen(mq, maxlen); return (error); case IFQCTL_DROPS: return (sysctl_rdint(oldp, oldlenp, newp, mq_drops(mq))); default: return (EOPNOTSUPP); } /* NOTREACHED */ }
7 7 9 5 4 4 3 1 6 1 2 5 4 18 7 1 11 5 3 4 3 3 6 30 20 10 8 1 3 6 1 3 1 3 4 1 4 1 2 7 1 1 1 5 1 1 4 13 13 7 5 3 7 1 25 2 2 7 2 1 8 1 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 /* $OpenBSD: sysv_shm.c,v 1.80 2022/08/14 01:58:28 jsg Exp $ */ /* $NetBSD: sysv_shm.c,v 1.50 1998/10/21 22:24:29 tron Exp $ */ /* * Copyright (c) 2002 Todd C. Miller <millert@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Sponsored in part by the Defense Advanced Research Projects * Agency (DARPA) and Air Force Research Laboratory, Air Force * Materiel Command, USAF, under agreement number F39502-99-1-0512. */ /* * Copyright (c) 1994 Adam Glass and Charles M. Hannum. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Adam Glass and Charles M. * Hannum. * 4. The names of the authors may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/shm.h> #include <sys/proc.h> #include <sys/time.h> #include <sys/malloc.h> #include <sys/mman.h> #include <sys/pool.h> #include <sys/systm.h> #include <sys/sysctl.h> #include <sys/stat.h> #include <sys/mount.h> #include <sys/syscallargs.h> #include <uvm/uvm_extern.h> extern struct shminfo shminfo; struct shmid_ds **shmsegs; /* linear mapping of shmid -> shmseg */ struct pool shm_pool; unsigned short *shmseqs; /* array of shm sequence numbers */ struct shmid_ds *shm_find_segment_by_shmid(int); /* * Provides the following externally accessible functions: * * shminit(void); initialization * shmexit(struct vmspace *) cleanup * shmfork(struct vmspace *, struct vmspace *) fork handling * shmsys(arg1, arg2, arg3, arg4); shm{at,ctl,dt,get}(arg2, arg3, arg4) * * Structures: * shmsegs (an array of 'struct shmid_ds *') * per proc 'struct shmmap_head' with an array of 'struct shmmap_state' */ #define SHMSEG_REMOVED 0x0200 /* can't overlap ACCESSPERMS */ int shm_last_free, shm_nused, shm_committed; struct shm_handle { struct uvm_object *shm_object; }; struct shmmap_state { vaddr_t va; int shmid; }; struct shmmap_head { int shmseg; struct shmmap_state state[1]; }; int shm_find_segment_by_key(key_t); void shm_deallocate_segment(struct shmid_ds *); int shm_delete_mapping(struct vmspace *, struct shmmap_state *); int shmget_existing(struct proc *, struct sys_shmget_args *, int, int, register_t *); int shmget_allocate_segment(struct proc *, struct sys_shmget_args *, int, register_t *); int shm_find_segment_by_key(key_t key) { struct shmid_ds *shmseg; int i; for (i = 0; i < shminfo.shmmni; i++) { shmseg = shmsegs[i]; if (shmseg != NULL && shmseg->shm_perm.key == key) return (i); } return (-1); } struct shmid_ds * shm_find_segment_by_shmid(int shmid) { int segnum; struct shmid_ds *shmseg; segnum = IPCID_TO_IX(shmid); if (segnum < 0 || segnum >= shminfo.shmmni || (shmseg = shmsegs[segnum]) == NULL || shmseg->shm_perm.seq != IPCID_TO_SEQ(shmid)) return (NULL); return (shmseg); } void shm_deallocate_segment(struct shmid_ds *shmseg) { struct shm_handle *shm_handle; size_t size; shm_handle = shmseg->shm_internal; size = round_page(shmseg->shm_segsz); uao_detach(shm_handle->shm_object); pool_put(&shm_pool, shmseg); shm_committed -= atop(size); shm_nused--; } int shm_delete_mapping(struct vmspace *vm, struct shmmap_state *shmmap_s) { struct shmid_ds *shmseg; int segnum; vaddr_t end; segnum = IPCID_TO_IX(shmmap_s->shmid); if (segnum < 0 || segnum >= shminfo.shmmni || (shmseg = shmsegs[segnum]) == NULL) return (EINVAL); end = round_page(shmmap_s->va+shmseg->shm_segsz); uvm_unmap(&vm->vm_map, trunc_page(shmmap_s->va), end); shmmap_s->shmid = -1; shmseg->shm_dtime = gettime(); if ((--shmseg->shm_nattch <= 0) && (shmseg->shm_perm.mode & SHMSEG_REMOVED)) { shm_deallocate_segment(shmseg); shm_last_free = segnum; shmsegs[shm_last_free] = NULL; } return (0); } int sys_shmdt(struct proc *p, void *v, register_t *retval) { struct sys_shmdt_args /* { syscallarg(const void *) shmaddr; } */ *uap = v; struct shmmap_head *shmmap_h; struct shmmap_state *shmmap_s; int i; shmmap_h = (struct shmmap_head *)p->p_vmspace->vm_shm; if (shmmap_h == NULL) return (EINVAL); for (i = 0, shmmap_s = shmmap_h->state; i < shmmap_h->shmseg; i++, shmmap_s++) if (shmmap_s->shmid != -1 && shmmap_s->va == (vaddr_t)SCARG(uap, shmaddr)) break; if (i == shmmap_h->shmseg) return (EINVAL); return (shm_delete_mapping(p->p_vmspace, shmmap_s)); } int sys_shmat(struct proc *p, void *v, register_t *retval) { struct sys_shmat_args /* { syscallarg(int) shmid; syscallarg(const void *) shmaddr; syscallarg(int) shmflg; } */ *uap = v; int error, i, flags = 0; struct ucred *cred = p->p_ucred; struct shmid_ds *shmseg; struct shmmap_head *shmmap_h; struct shmmap_state *shmmap_s; struct shm_handle *shm_handle; vaddr_t attach_va; vm_prot_t prot; vsize_t size; shmmap_h = (struct shmmap_head *)p->p_vmspace->vm_shm; if (shmmap_h == NULL) { size = sizeof(int) + shminfo.shmseg * sizeof(struct shmmap_state); shmmap_h = malloc(size, M_SHM, M_WAITOK | M_CANFAIL); if (shmmap_h == NULL) return (ENOMEM); shmmap_h->shmseg = shminfo.shmseg; for (i = 0, shmmap_s = shmmap_h->state; i < shmmap_h->shmseg; i++, shmmap_s++) shmmap_s->shmid = -1; p->p_vmspace->vm_shm = (caddr_t)shmmap_h; } shmseg = shm_find_segment_by_shmid(SCARG(uap, shmid)); if (shmseg == NULL) return (EINVAL); error = ipcperm(cred, &shmseg->shm_perm, (SCARG(uap, shmflg) & SHM_RDONLY) ? IPC_R : IPC_R|IPC_W); if (error) return (error); for (i = 0, shmmap_s = shmmap_h->state; i < shmmap_h->shmseg; i++) { if (shmmap_s->shmid == -1) break; shmmap_s++; } if (i >= shmmap_h->shmseg) return (EMFILE); size = round_page(shmseg->shm_segsz); prot = PROT_READ; if ((SCARG(uap, shmflg) & SHM_RDONLY) == 0) prot |= PROT_WRITE; if (SCARG(uap, shmaddr)) { flags |= UVM_FLAG_FIXED; if (SCARG(uap, shmflg) & SHM_RND) attach_va = (vaddr_t)SCARG(uap, shmaddr) & ~(SHMLBA-1); else if (((vaddr_t)SCARG(uap, shmaddr) & (SHMLBA-1)) == 0) attach_va = (vaddr_t)SCARG(uap, shmaddr); else return (EINVAL); } else attach_va = 0; /* * Since uvm_map() could end up sleeping, grab a reference to prevent * the segment from being deallocated while sleeping. */ shmseg->shm_nattch++; shm_handle = shmseg->shm_internal; uao_reference(shm_handle->shm_object); error = uvm_map(&p->p_vmspace->vm_map, &attach_va, size, shm_handle->shm_object, 0, 0, UVM_MAPFLAG(prot, prot, MAP_INHERIT_SHARE, MADV_RANDOM, flags)); if (error) { if ((--shmseg->shm_nattch <= 0) && (shmseg->shm_perm.mode & SHMSEG_REMOVED)) { shm_deallocate_segment(shmseg); shm_last_free = IPCID_TO_IX(SCARG(uap, shmid)); shmsegs[shm_last_free] = NULL; } else { uao_detach(shm_handle->shm_object); } return (error); } shmmap_s->va = attach_va; shmmap_s->shmid = SCARG(uap, shmid); shmseg->shm_lpid = p->p_p->ps_pid; shmseg->shm_atime = gettime(); *retval = attach_va; return (0); } int sys_shmctl(struct proc *p, void *v, register_t *retval) { struct sys_shmctl_args /* { syscallarg(int) shmid; syscallarg(int) cmd; syscallarg(struct shmid_ds *) buf; } */ *uap = v; int shmid = SCARG(uap, shmid); int cmd = SCARG(uap, cmd); void *buf = SCARG(uap, buf); struct ucred *cred = p->p_ucred; struct shmid_ds inbuf, *shmseg; int error; if (cmd == IPC_SET) { error = copyin(buf, &inbuf, sizeof(inbuf)); if (error) return (error); } shmseg = shm_find_segment_by_shmid(shmid); if (shmseg == NULL) return (EINVAL); switch (cmd) { case IPC_STAT: if ((error = ipcperm(cred, &shmseg->shm_perm, IPC_R)) != 0) return (error); error = copyout(shmseg, buf, sizeof(inbuf)); if (error) return (error); break; case IPC_SET: if ((error = ipcperm(cred, &shmseg->shm_perm, IPC_M)) != 0) return (error); shmseg->shm_perm.uid = inbuf.shm_perm.uid; shmseg->shm_perm.gid = inbuf.shm_perm.gid; shmseg->shm_perm.mode = (shmseg->shm_perm.mode & ~ACCESSPERMS) | (inbuf.shm_perm.mode & ACCESSPERMS); shmseg->shm_ctime = gettime(); break; case IPC_RMID: if ((error = ipcperm(cred, &shmseg->shm_perm, IPC_M)) != 0) return (error); shmseg->shm_perm.key = IPC_PRIVATE; shmseg->shm_perm.mode |= SHMSEG_REMOVED; if (shmseg->shm_nattch <= 0) { shm_deallocate_segment(shmseg); shm_last_free = IPCID_TO_IX(shmid); shmsegs[shm_last_free] = NULL; } break; case SHM_LOCK: case SHM_UNLOCK: default: return (EINVAL); } return (0); } int shmget_existing(struct proc *p, struct sys_shmget_args /* { syscallarg(key_t) key; syscallarg(size_t) size; syscallarg(int) shmflg; } */ *uap, int mode, int segnum, register_t *retval) { struct shmid_ds *shmseg; struct ucred *cred = p->p_ucred; int error; shmseg = shmsegs[segnum]; /* We assume the segnum is valid */ if ((error = ipcperm(cred, &shmseg->shm_perm, mode)) != 0) return (error); if (SCARG(uap, size) && SCARG(uap, size) > shmseg->shm_segsz) return (EINVAL); if ((SCARG(uap, shmflg) & (IPC_CREAT | IPC_EXCL)) == (IPC_CREAT | IPC_EXCL)) return (EEXIST); *retval = IXSEQ_TO_IPCID(segnum, shmseg->shm_perm); return (0); } int shmget_allocate_segment(struct proc *p, struct sys_shmget_args /* { syscallarg(key_t) key; syscallarg(size_t) size; syscallarg(int) shmflg; } */ *uap, int mode, register_t *retval) { size_t size; key_t key; int segnum; struct ucred *cred = p->p_ucred; struct shmid_ds *shmseg; struct shm_handle *shm_handle; int error = 0; if (SCARG(uap, size) < shminfo.shmmin || SCARG(uap, size) > shminfo.shmmax) return (EINVAL); if (shm_nused >= shminfo.shmmni) /* any shmids left? */ return (ENOSPC); size = round_page(SCARG(uap, size)); if (shm_committed + atop(size) > shminfo.shmall) return (ENOMEM); shm_nused++; shm_committed += atop(size); /* * If a key has been specified and we had to wait for memory * to be freed up we need to verify that no one has allocated * the key we want in the meantime. Yes, this is ugly. */ key = SCARG(uap, key); shmseg = pool_get(&shm_pool, key == IPC_PRIVATE ? PR_WAITOK : PR_NOWAIT); if (shmseg == NULL) { shmseg = pool_get(&shm_pool, PR_WAITOK); if (shm_find_segment_by_key(key) != -1) { pool_put(&shm_pool, shmseg); shm_nused--; shm_committed -= atop(size); return (EAGAIN); } } /* XXX - hash shmids instead */ if (shm_last_free < 0) { for (segnum = 0; segnum < shminfo.shmmni && shmsegs[segnum]; segnum++) ; if (segnum == shminfo.shmmni) panic("shmseg free count inconsistent"); } else { segnum = shm_last_free; if (++shm_last_free >= shminfo.shmmni || shmsegs[shm_last_free]) shm_last_free = -1; } shmsegs[segnum] = shmseg; shm_handle = (struct shm_handle *)((caddr_t)shmseg + sizeof(*shmseg)); shm_handle->shm_object = uao_create(size, 0); shmseg->shm_perm.cuid = shmseg->shm_perm.uid = cred->cr_uid; shmseg->shm_perm.cgid = shmseg->shm_perm.gid = cred->cr_gid; shmseg->shm_perm.mode = (mode & ACCESSPERMS); shmseg->shm_perm.seq = shmseqs[segnum] = (shmseqs[segnum] + 1) & 0x7fff; shmseg->shm_perm.key = key; shmseg->shm_segsz = SCARG(uap, size); shmseg->shm_cpid = p->p_p->ps_pid; shmseg->shm_lpid = shmseg->shm_nattch = 0; shmseg->shm_atime = shmseg->shm_dtime = 0; shmseg->shm_ctime = gettime(); shmseg->shm_internal = shm_handle; *retval = IXSEQ_TO_IPCID(segnum, shmseg->shm_perm); return (error); } int sys_shmget(struct proc *p, void *v, register_t *retval) { struct sys_shmget_args /* { syscallarg(key_t) key; syscallarg(size_t) size; syscallarg(int) shmflg; } */ *uap = v; int segnum, mode, error; mode = SCARG(uap, shmflg) & ACCESSPERMS; if (SCARG(uap, key) != IPC_PRIVATE) { again: segnum = shm_find_segment_by_key(SCARG(uap, key)); if (segnum >= 0) return (shmget_existing(p, uap, mode, segnum, retval)); if ((SCARG(uap, shmflg) & IPC_CREAT) == 0) return (ENOENT); } error = shmget_allocate_segment(p, uap, mode, retval); if (error == EAGAIN) goto again; return (error); } void shmfork(struct vmspace *vm1, struct vmspace *vm2) { struct shmmap_head *shmmap_h; struct shmmap_state *shmmap_s; struct shmid_ds *shmseg; size_t size; int i; if (vm1->vm_shm == NULL) { vm2->vm_shm = NULL; return; } shmmap_h = (struct shmmap_head *)vm1->vm_shm; size = sizeof(int) + shmmap_h->shmseg * sizeof(struct shmmap_state); vm2->vm_shm = malloc(size, M_SHM, M_WAITOK); memcpy(vm2->vm_shm, vm1->vm_shm, size); for (i = 0, shmmap_s = shmmap_h->state; i < shmmap_h->shmseg; i++, shmmap_s++) { if (shmmap_s->shmid != -1 && (shmseg = shmsegs[IPCID_TO_IX(shmmap_s->shmid)]) != NULL) shmseg->shm_nattch++; } } void shmexit(struct vmspace *vm) { struct shmmap_head *shmmap_h; struct shmmap_state *shmmap_s; size_t size; int i; shmmap_h = (struct shmmap_head *)vm->vm_shm; if (shmmap_h == NULL) return; size = sizeof(int) + shmmap_h->shmseg * sizeof(struct shmmap_state); for (i = 0, shmmap_s = shmmap_h->state; i < shmmap_h->shmseg; i++, shmmap_s++) if (shmmap_s->shmid != -1) shm_delete_mapping(vm, shmmap_s); free(vm->vm_shm, M_SHM, size); vm->vm_shm = NULL; } void shminit(void) { pool_init(&shm_pool, sizeof(struct shmid_ds) + sizeof(struct shm_handle), 0, IPL_NONE, PR_WAITOK, "shmpl", NULL); shmsegs = mallocarray(shminfo.shmmni, sizeof(struct shmid_ds *), M_SHM, M_WAITOK|M_ZERO); shmseqs = mallocarray(shminfo.shmmni, sizeof(unsigned short), M_SHM, M_WAITOK|M_ZERO); shminfo.shmmax *= PAGE_SIZE; /* actually in pages */ shm_last_free = 0; shm_nused = 0; shm_committed = 0; } /* Expand shmsegs and shmseqs arrays */ void shm_reallocate(int val) { struct shmid_ds **newsegs; unsigned short *newseqs; newsegs = mallocarray(val, sizeof(struct shmid_ds *), M_SHM, M_WAITOK | M_ZERO); memcpy(newsegs, shmsegs, shminfo.shmmni * sizeof(struct shmid_ds *)); free(shmsegs, M_SHM, shminfo.shmmni * sizeof(struct shmid_ds *)); shmsegs = newsegs; newseqs = mallocarray(val, sizeof(unsigned short), M_SHM, M_WAITOK | M_ZERO); memcpy(newseqs, shmseqs, shminfo.shmmni * sizeof(unsigned short)); free(shmseqs, M_SHM, shminfo.shmmni * sizeof(unsigned short)); shmseqs = newseqs; shminfo.shmmni = val; } /* * Userland access to struct shminfo. */ int sysctl_sysvshm(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int error, val; if (namelen != 1) return (ENOTDIR); /* leaf-only */ switch (name[0]) { case KERN_SHMINFO_SHMMAX: if ((error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &shminfo.shmmax, 0, INT_MAX)) || newp == NULL) return (error); /* If new shmmax > shmall, crank shmall */ if (atop(round_page(shminfo.shmmax)) > shminfo.shmall) shminfo.shmall = atop(round_page(shminfo.shmmax)); return (0); case KERN_SHMINFO_SHMMIN: return (sysctl_int_bounded(oldp, oldlenp, newp, newlen, &shminfo.shmmin, 1, INT_MAX)); case KERN_SHMINFO_SHMMNI: val = shminfo.shmmni; /* can't decrease shmmni */ error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &val, val, 0xffff); /* returns success and skips reallocation if val is unchanged */ if (error || val == shminfo.shmmni) return (error); shm_reallocate(val); return (0); case KERN_SHMINFO_SHMSEG: return (sysctl_int_bounded(oldp, oldlenp, newp, newlen, &shminfo.shmseg, 1, INT_MAX)); case KERN_SHMINFO_SHMALL: /* can't decrease shmall */ return (sysctl_int_bounded(oldp, oldlenp, newp, newlen, &shminfo.shmall, shminfo.shmall, INT_MAX)); default: return (EOPNOTSUPP); } /* NOTREACHED */ }
17 2 1 2 12 7 5 2 1 1 1 1 1 2 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 /* $OpenBSD: subr_evcount.c,v 1.16 2023/09/16 09:33:27 mpi Exp $ */ /* * Copyright (c) 2004 Artur Grabowski <art@openbsd.org> * Copyright (c) 2004 Aaron Campbell <aaron@openbsd.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/evcount.h> #include <sys/systm.h> #include <sys/sysctl.h> #include <sys/percpu.h> static TAILQ_HEAD(,evcount) evcount_list = TAILQ_HEAD_INITIALIZER(evcount_list); static TAILQ_HEAD(,evcount) evcount_percpu_init_list = TAILQ_HEAD_INITIALIZER(evcount_percpu_init_list); static int evcount_percpu_done; void evcount_attach(struct evcount *ec, const char *name, void *data) { static int nextid = 0; memset(ec, 0, sizeof(*ec)); ec->ec_name = name; ec->ec_id = ++nextid; ec->ec_data = data; TAILQ_INSERT_TAIL(&evcount_list, ec, next); } void evcount_percpu(struct evcount *ec) { if (evcount_percpu_done == 0) { TAILQ_REMOVE(&evcount_list, ec, next); TAILQ_INSERT_TAIL(&evcount_percpu_init_list, ec, next); } else { ec->ec_percpu = counters_alloc(1); } } void evcount_init_percpu(void) { struct evcount *ec; KASSERT(evcount_percpu_done == 0); TAILQ_FOREACH(ec, &evcount_percpu_init_list, next) { ec->ec_percpu = counters_alloc(1); counters_add(ec->ec_percpu, 0, ec->ec_count); ec->ec_count = 0; } TAILQ_CONCAT(&evcount_list, &evcount_percpu_init_list, next); evcount_percpu_done = 1; } void evcount_detach(struct evcount *ec) { TAILQ_REMOVE(&evcount_list, ec, next); if (ec->ec_percpu != NULL) { counters_free(ec->ec_percpu, 1); ec->ec_percpu = NULL; } } void evcount_inc(struct evcount *ec) { if (ec->ec_percpu != NULL) counters_inc(ec->ec_percpu, 0); else ec->ec_count++; } #ifndef SMALL_KERNEL int evcount_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int error = 0, s, nintr, i; struct evcount *ec; uint64_t count, scratch; if (newp != NULL) return (EPERM); if (name[0] != KERN_INTRCNT_NUM) { if (namelen != 2) return (ENOTDIR); if (name[1] < 0) return (EINVAL); i = name[1]; } else i = -1; nintr = 0; TAILQ_FOREACH(ec, &evcount_list, next) { if (nintr++ == i) break; } switch (name[0]) { case KERN_INTRCNT_NUM: error = sysctl_rdint(oldp, oldlenp, NULL, nintr); break; case KERN_INTRCNT_CNT: if (ec == NULL) return (ENOENT); if (ec->ec_percpu != NULL) { counters_read(ec->ec_percpu, &count, 1, &scratch); } else { s = splhigh(); count = ec->ec_count; splx(s); } error = sysctl_rdquad(oldp, oldlenp, NULL, count); break; case KERN_INTRCNT_NAME: if (ec == NULL) return (ENOENT); error = sysctl_rdstring(oldp, oldlenp, NULL, ec->ec_name); break; case KERN_INTRCNT_VECTOR: if (ec == NULL || ec->ec_data == NULL) return (ENOENT); error = sysctl_rdint(oldp, oldlenp, NULL, *((int *)ec->ec_data)); break; default: error = EOPNOTSUPP; break; } return (error); } #endif /* SMALL_KERNEL */
5 1 1 1 2 1 1 3 1 2 1 1 3 2 2 3 2 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 /* $OpenBSD: acpi_apm.c,v 1.3 2023/08/06 14:30:08 tobhe Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/fcntl.h> #include <dev/acpi/acpireg.h> #include <dev/acpi/acpivar.h> #include <dev/acpi/acpidev.h> #include <dev/acpi/dsdt.h> #include <machine/conf.h> #include <machine/cpufunc.h> #ifdef HIBERNATE #include <sys/hibernate.h> #endif #include <machine/apmvar.h> #define APMUNIT(dev) (minor(dev)&0xf0) #define APMDEV(dev) (minor(dev)&0x0f) #define APMDEV_NORMAL 0 #define APMDEV_CTL 8 #ifndef SMALL_KERNEL int acpiopen(dev_t dev, int flag, int mode, struct proc *p) { int error = 0; struct acpi_softc *sc = acpi_softc; int s; if (sc == NULL) return (ENXIO); s = splbio(); switch (APMDEV(dev)) { case APMDEV_CTL: if (!(flag & FWRITE)) { error = EINVAL; break; } if (sc->sc_flags & SCFLAG_OWRITE) { error = EBUSY; break; } sc->sc_flags |= SCFLAG_OWRITE; break; case APMDEV_NORMAL: if (!(flag & FREAD) || (flag & FWRITE)) { error = EINVAL; break; } sc->sc_flags |= SCFLAG_OREAD; break; default: error = ENXIO; break; } splx(s); return (error); } int acpiclose(dev_t dev, int flag, int mode, struct proc *p) { int error = 0; struct acpi_softc *sc = acpi_softc; int s; if (sc == NULL) return (ENXIO); s = splbio(); switch (APMDEV(dev)) { case APMDEV_CTL: sc->sc_flags &= ~SCFLAG_OWRITE; break; case APMDEV_NORMAL: sc->sc_flags &= ~SCFLAG_OREAD; break; default: error = ENXIO; break; } splx(s); return (error); } int acpiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { int error = 0; struct acpi_softc *sc = acpi_softc; struct apm_power_info *pi = (struct apm_power_info *)data; int s; if (sc == NULL) return (ENXIO); s = splbio(); /* fake APM */ switch (cmd) { #ifdef SUSPEND case APM_IOC_SUSPEND: case APM_IOC_STANDBY: if ((flag & FWRITE) == 0) { error = EBADF; break; } error = request_sleep(SLEEP_SUSPEND); if (error) break; acpi_wakeup(sc); break; #ifdef HIBERNATE case APM_IOC_HIBERNATE: if ((error = suser(p)) != 0) break; if ((flag & FWRITE) == 0) { error = EBADF; break; } if (get_hibernate_io_function(swdevt[0].sw_dev) == NULL) { error = EOPNOTSUPP; break; } error = request_sleep(SLEEP_HIBERNATE); if (error) break; acpi_wakeup(sc); break; #endif #endif case APM_IOC_GETPOWER: error = acpi_apminfo(pi); break; default: error = ENOTTY; } splx(s); return (error); } void acpi_filtdetach(struct knote *); int acpi_filtread(struct knote *, long); const struct filterops acpiread_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, .f_detach = acpi_filtdetach, .f_event = acpi_filtread, }; int acpikqfilter(dev_t dev, struct knote *kn) { struct acpi_softc *sc = acpi_softc; int s; if (sc == NULL) return (ENXIO); switch (kn->kn_filter) { case EVFILT_READ: kn->kn_fop = &acpiread_filtops; break; default: return (EINVAL); } kn->kn_hook = sc; s = splbio(); klist_insert_locked(&sc->sc_note, kn); splx(s); return (0); } void acpi_filtdetach(struct knote *kn) { struct acpi_softc *sc = kn->kn_hook; int s; s = splbio(); klist_remove_locked(&sc->sc_note, kn); splx(s); } int acpi_filtread(struct knote *kn, long hint) { /* XXX weird kqueue_scan() semantics */ if (hint && !kn->kn_data) kn->kn_data = hint; return (1); } #ifdef SUSPEND int request_sleep(int sleepmode) { struct acpi_softc *sc = acpi_softc; #ifdef HIBERNATE if (sleepmode == SLEEP_HIBERNATE) { if (get_hibernate_io_function(swdevt[0].sw_dev) == NULL) return EOPNOTSUPP; } #endif acpi_addtask(sc, acpi_sleep_task, sc, sleepmode); return 0; } #endif /* SUSPEND */ #else /* SMALL_KERNEL */ int acpiopen(dev_t dev, int flag, int mode, struct proc *p) { return (ENXIO); } int acpiclose(dev_t dev, int flag, int mode, struct proc *p) { return (ENXIO); } int acpiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { return (ENXIO); } int acpikqfilter(dev_t dev, struct knote *kn) { return (EOPNOTSUPP); } #endif /* SMALL_KERNEL */
5 5 5 5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 /* $OpenBSD: strlcat.c,v 1.9 2019/01/25 00:19:26 millert Exp $ */ /* * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <lib/libkern/libkern.h> /* * Appends src to string dst of size dsize (unlike strncat, dsize is the * full size of dst, not space left). At most dsize-1 characters * will be copied. Always NUL terminates (unless dsize <= strlen(dst)). * Returns strlen(src) + MIN(dsize, strlen(initial dst)). * If retval >= siz, truncation occurred. */ size_t strlcat(char *dst, const char *src, size_t dsize) { const char *odst = dst; const char *osrc = src; size_t n = dsize; size_t dlen; /* Find the end of dst and adjust bytes left but don't go past end. */ while (n-- != 0 && *dst != '\0') dst++; dlen = dst - odst; n = dsize - dlen; if (n-- == 0) return(dlen + strlen(src)); while (*src != '\0') { if (n != 0) { *dst++ = *src; n--; } src++; } *dst = '\0'; return(dlen + (src - osrc)); /* count does not include NUL */ }
6 6 6 6 6 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 /* $OpenBSD: idgen.c,v 1.8 2020/07/22 13:54:30 tobhe Exp $ */ /* * Copyright (c) 2008 Damien Miller <djm@mindrot.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * IDGEN32: non-repeating ID generation covering an almost maximal 32-bit * range. * * IDGEN32 is based on public domain SKIP32 by Greg Rose. */ #include <sys/types.h> #include <sys/systm.h> #include <sys/time.h> #include <crypto/idgen.h> static const u_int8_t idgen32_ftable[256] = { 0xa3, 0xd7, 0x09, 0x83, 0xf8, 0x48, 0xf6, 0xf4, 0xb3, 0x21, 0x15, 0x78, 0x99, 0xb1, 0xaf, 0xf9, 0xe7, 0x2d, 0x4d, 0x8a, 0xce, 0x4c, 0xca, 0x2e, 0x52, 0x95, 0xd9, 0x1e, 0x4e, 0x38, 0x44, 0x28, 0x0a, 0xdf, 0x02, 0xa0, 0x17, 0xf1, 0x60, 0x68, 0x12, 0xb7, 0x7a, 0xc3, 0xe9, 0xfa, 0x3d, 0x53, 0x96, 0x84, 0x6b, 0xba, 0xf2, 0x63, 0x9a, 0x19, 0x7c, 0xae, 0xe5, 0xf5, 0xf7, 0x16, 0x6a, 0xa2, 0x39, 0xb6, 0x7b, 0x0f, 0xc1, 0x93, 0x81, 0x1b, 0xee, 0xb4, 0x1a, 0xea, 0xd0, 0x91, 0x2f, 0xb8, 0x55, 0xb9, 0xda, 0x85, 0x3f, 0x41, 0xbf, 0xe0, 0x5a, 0x58, 0x80, 0x5f, 0x66, 0x0b, 0xd8, 0x90, 0x35, 0xd5, 0xc0, 0xa7, 0x33, 0x06, 0x65, 0x69, 0x45, 0x00, 0x94, 0x56, 0x6d, 0x98, 0x9b, 0x76, 0x97, 0xfc, 0xb2, 0xc2, 0xb0, 0xfe, 0xdb, 0x20, 0xe1, 0xeb, 0xd6, 0xe4, 0xdd, 0x47, 0x4a, 0x1d, 0x42, 0xed, 0x9e, 0x6e, 0x49, 0x3c, 0xcd, 0x43, 0x27, 0xd2, 0x07, 0xd4, 0xde, 0xc7, 0x67, 0x18, 0x89, 0xcb, 0x30, 0x1f, 0x8d, 0xc6, 0x8f, 0xaa, 0xc8, 0x74, 0xdc, 0xc9, 0x5d, 0x5c, 0x31, 0xa4, 0x70, 0x88, 0x61, 0x2c, 0x9f, 0x0d, 0x2b, 0x87, 0x50, 0x82, 0x54, 0x64, 0x26, 0x7d, 0x03, 0x40, 0x34, 0x4b, 0x1c, 0x73, 0xd1, 0xc4, 0xfd, 0x3b, 0xcc, 0xfb, 0x7f, 0xab, 0xe6, 0x3e, 0x5b, 0xa5, 0xad, 0x04, 0x23, 0x9c, 0x14, 0x51, 0x22, 0xf0, 0x29, 0x79, 0x71, 0x7e, 0xff, 0x8c, 0x0e, 0xe2, 0x0c, 0xef, 0xbc, 0x72, 0x75, 0x6f, 0x37, 0xa1, 0xec, 0xd3, 0x8e, 0x62, 0x8b, 0x86, 0x10, 0xe8, 0x08, 0x77, 0x11, 0xbe, 0x92, 0x4f, 0x24, 0xc5, 0x32, 0x36, 0x9d, 0xcf, 0xf3, 0xa6, 0xbb, 0xac, 0x5e, 0x6c, 0xa9, 0x13, 0x57, 0x25, 0xb5, 0xe3, 0xbd, 0xa8, 0x3a, 0x01, 0x05, 0x59, 0x2a, 0x46 }; static u_int16_t idgen32_g(u_int8_t *key, int k, u_int16_t w) { u_int8_t g1, g2, g3, g4, g5, g6; u_int o = k * 4; g1 = (w >> 8) & 0xff; g2 = w & 0xff; g3 = idgen32_ftable[g2 ^ key[o++ & (IDGEN32_KEYLEN - 1)]] ^ g1; g4 = idgen32_ftable[g3 ^ key[o++ & (IDGEN32_KEYLEN - 1)]] ^ g2; g5 = idgen32_ftable[g4 ^ key[o++ & (IDGEN32_KEYLEN - 1)]] ^ g3; g6 = idgen32_ftable[g5 ^ key[o++ & (IDGEN32_KEYLEN - 1)]] ^ g4; return (g5 << 8) | g6; } static u_int32_t idgen32_permute(struct idgen32_ctx *ctx, u_int32_t in) { u_int i, r; u_int16_t wl, wr; wl = (in >> 16) & 0x7fff; wr = in & 0xffff; /* Doubled up rounds, with an odd round at the end to swap */ for (i = r = 0; i < IDGEN32_ROUNDS / 2; ++i) { wr ^= (idgen32_g(ctx->id32_key, r, wl) ^ r); r++; wl ^= (idgen32_g(ctx->id32_key, r, wr) ^ r) & 0x7fff; r++; } wr ^= (idgen32_g(ctx->id32_key, r, wl) ^ r); return (wl << 16) | wr; } static void idgen32_rekey(struct idgen32_ctx *ctx) { ctx->id32_counter = 0; ctx->id32_hibit ^= 0x80000000; ctx->id32_offset = arc4random(); arc4random_buf(ctx->id32_key, sizeof(ctx->id32_key)); ctx->id32_rekey_time = getuptime() + IDGEN32_REKEY_TIME; } void idgen32_init(struct idgen32_ctx *ctx) { bzero(ctx, sizeof(*ctx)); ctx->id32_hibit = arc4random() & 0x80000000; idgen32_rekey(ctx); } u_int32_t idgen32(struct idgen32_ctx *ctx) { u_int32_t ret; do { /* Rekey a little early to avoid "card counting" attack */ if (ctx->id32_counter > IDGEN32_REKEY_LIMIT || ctx->id32_rekey_time < getuptime()) idgen32_rekey(ctx); ret = ctx->id32_hibit | idgen32_permute(ctx, (ctx->id32_offset + ctx->id32_counter++) & 0x7fffffff); } while (ret == 0); /* Zero IDs are often special, so avoid */ return ret; }
8 3 1 4 4 1 3 5 4 2 2 1 4 5 4 4 2 2 4 4 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 /* $OpenBSD: tty_endrun.c,v 1.8 2018/02/19 08:59:52 mpi Exp $ */ /* * Copyright (c) 2008 Marc Balmer <mbalmer@openbsd.org> * Copyright (c) 2009 Kevin Steves <stevesk@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * A tty line discipline to decode the EndRun Technologies native * time-of-day message. * http://www.endruntechnologies.com/ */ /* * EndRun Format: * * T YYYY DDD HH:MM:SS zZZ m<CR><LF> * * T is the Time Figure of Merit (TFOM) character (described below). * This is the on-time character, transmitted during the first * millisecond of each second. * * YYYY is the year * DDD is the day-of-year * : is the colon character (0x3A) * HH is the hour of the day * MM is the minute of the hour * SS is the second of the minute * z is the sign of the offset to UTC, + implies time is ahead of UTC. * ZZ is the magnitude of the offset to UTC in units of half-hours. * Non-zero only when the Timemode is Local. * m is the Timemode character and is one of: * G = GPS * L = Local * U = UTC * <CR> is the ASCII carriage return character (0x0D) * <LF> is the ASCII line feed character (0x0A) */ #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/sensors.h> #include <sys/tty.h> #include <sys/conf.h> #include <sys/time.h> #ifdef ENDRUN_DEBUG #define DPRINTFN(n, x) do { if (endrundebug > (n)) printf x; } while (0) int endrundebug = 0; #else #define DPRINTFN(n, x) #endif #define DPRINTF(x) DPRINTFN(0, x) void endrunattach(int); #define ENDRUNLEN 27 /* strlen("6 2009 018 20:41:17 +00 U\r\n") */ #define NUMFLDS 6 #ifdef ENDRUN_DEBUG #define TRUSTTIME 30 #else #define TRUSTTIME (10 * 60) /* 10 minutes */ #endif int endrun_count, endrun_nxid; struct endrun { char cbuf[ENDRUNLEN]; /* receive buffer */ struct ksensor time; /* the timedelta sensor */ struct ksensor signal; /* signal status */ struct ksensordev timedev; struct timespec ts; /* current timestamp */ struct timespec lts; /* timestamp of last TFOM */ struct timeout endrun_tout; /* invalidate sensor */ int64_t gap; /* gap between two sentences */ int64_t last; /* last time rcvd */ #define SYNC_SCAN 1 /* scanning for '\n' */ #define SYNC_EOL 2 /* '\n' seen, next char TFOM */ int sync; int pos; /* position in rcv buffer */ int no_pps; /* no PPS although requested */ #ifdef ENDRUN_DEBUG char tfom; #endif }; /* EndRun decoding */ void endrun_scan(struct endrun *, struct tty *); void endrun_decode(struct endrun *, struct tty *, char *fld[], int fldcnt); /* date and time conversion */ int endrun_atoi(char *s, int len); int endrun_date_to_nano(char *s1, char *s2, int64_t *nano); int endrun_time_to_nano(char *s, int64_t *nano); int endrun_offset_to_nano(char *s, int64_t *nano); /* degrade the timedelta sensor */ void endrun_timeout(void *); void endrunattach(int dummy) { } int endrunopen(dev_t dev, struct tty *tp, struct proc *p) { struct endrun *np; int error; DPRINTF(("endrunopen\n")); if (tp->t_line == ENDRUNDISC) return ENODEV; if ((error = suser(p)) != 0) return error; np = malloc(sizeof(struct endrun), M_DEVBUF, M_WAITOK|M_ZERO); snprintf(np->timedev.xname, sizeof(np->timedev.xname), "endrun%d", endrun_nxid++); endrun_count++; np->time.status = SENSOR_S_UNKNOWN; np->time.type = SENSOR_TIMEDELTA; #ifndef ENDRUN_DEBUG np->time.flags = SENSOR_FINVALID; #endif sensor_attach(&np->timedev, &np->time); np->signal.type = SENSOR_PERCENT; np->signal.status = SENSOR_S_UNKNOWN; np->signal.value = 100000LL; strlcpy(np->signal.desc, "Signal", sizeof(np->signal.desc)); sensor_attach(&np->timedev, &np->signal); np->sync = SYNC_SCAN; #ifdef ENDRUN_DEBUG np->tfom = '0'; #endif tp->t_sc = (caddr_t)np; error = linesw[TTYDISC].l_open(dev, tp, p); if (error) { free(np, M_DEVBUF, sizeof(*np)); tp->t_sc = NULL; } else { sensordev_install(&np->timedev); timeout_set(&np->endrun_tout, endrun_timeout, np); } return error; } int endrunclose(struct tty *tp, int flags, struct proc *p) { struct endrun *np = (struct endrun *)tp->t_sc; DPRINTF(("endrunclose\n")); tp->t_line = TTYDISC; /* switch back to termios */ timeout_del(&np->endrun_tout); sensordev_deinstall(&np->timedev); free(np, M_DEVBUF, sizeof(*np)); tp->t_sc = NULL; endrun_count--; if (endrun_count == 0) endrun_nxid = 0; return linesw[TTYDISC].l_close(tp, flags, p); } /* collect EndRun sentence from tty */ int endruninput(int c, struct tty *tp) { struct endrun *np = (struct endrun *)tp->t_sc; struct timespec ts; int64_t gap; long tmin, tmax; if (np->sync == SYNC_EOL) { nanotime(&ts); np->pos = 0; np->sync = SYNC_SCAN; np->cbuf[np->pos++] = c; /* TFOM char */ gap = (ts.tv_sec * 1000000000LL + ts.tv_nsec) - (np->lts.tv_sec * 1000000000LL + np->lts.tv_nsec); np->lts.tv_sec = ts.tv_sec; np->lts.tv_nsec = ts.tv_nsec; if (gap <= np->gap) goto nogap; np->ts.tv_sec = ts.tv_sec; np->ts.tv_nsec = ts.tv_nsec; np->gap = gap; /* * If a tty timestamp is available, make sure its value is * reasonable by comparing against the timestamp just taken. * If they differ by more than 2 seconds, assume no PPS signal * is present, note the fact, and keep using the timestamp * value. When this happens, the sensor state is set to * CRITICAL later when the EndRun sentence is decoded. */ if (tp->t_flags & (TS_TSTAMPDCDSET | TS_TSTAMPDCDCLR | TS_TSTAMPCTSSET | TS_TSTAMPCTSCLR)) { tmax = lmax(np->ts.tv_sec, tp->t_tv.tv_sec); tmin = lmin(np->ts.tv_sec, tp->t_tv.tv_sec); if (tmax - tmin > 1) np->no_pps = 1; else { np->ts.tv_sec = tp->t_tv.tv_sec; np->ts.tv_nsec = tp->t_tv.tv_usec * 1000L; np->no_pps = 0; } } } else if (c == '\n') { if (np->pos == ENDRUNLEN - 1) { /* don't copy '\n' into cbuf */ np->cbuf[np->pos] = '\0'; endrun_scan(np, tp); } np->sync = SYNC_EOL; } else { if (np->pos < ENDRUNLEN - 1) np->cbuf[np->pos++] = c; } nogap: /* pass data to termios */ return linesw[TTYDISC].l_rint(c, tp); } /* Scan the EndRun sentence just received */ void endrun_scan(struct endrun *np, struct tty *tp) { int fldcnt = 0, n; char *fld[NUMFLDS], *cs; DPRINTFN(1, ("%s\n", np->cbuf)); /* split into fields */ fld[fldcnt++] = &np->cbuf[0]; for (cs = NULL, n = 0; n < np->pos && cs == NULL; n++) { switch (np->cbuf[n]) { case '\r': np->cbuf[n] = '\0'; cs = &np->cbuf[n + 1]; break; case ' ': if (fldcnt < NUMFLDS) { np->cbuf[n] = '\0'; fld[fldcnt++] = &np->cbuf[n + 1]; } else { DPRINTF(("endrun: nr of fields in sentence " "exceeds expected: %d\n", NUMFLDS)); return; } break; } } endrun_decode(np, tp, fld, fldcnt); } /* Decode the time string */ void endrun_decode(struct endrun *np, struct tty *tp, char *fld[], int fldcnt) { int64_t date_nano, time_nano, offset_nano, endrun_now; char tfom; int jumped = 0; if (fldcnt != NUMFLDS) { DPRINTF(("endrun: field count mismatch, %d\n", fldcnt)); return; } if (endrun_time_to_nano(fld[3], &time_nano) == -1) { DPRINTF(("endrun: illegal time, %s\n", fld[3])); return; } if (endrun_date_to_nano(fld[1], fld[2], &date_nano) == -1) { DPRINTF(("endrun: illegal date, %s %s\n", fld[1], fld[2])); return; } offset_nano = 0; /* only parse offset when timemode is local */ if (fld[5][0] == 'L' && endrun_offset_to_nano(fld[4], &offset_nano) == -1) { DPRINTF(("endrun: illegal offset, %s\n", fld[4])); return; } endrun_now = date_nano + time_nano + offset_nano; if (endrun_now <= np->last) { DPRINTF(("endrun: time not monotonically increasing " "last %lld now %lld\n", (long long)np->last, (long long)endrun_now)); jumped = 1; } np->last = endrun_now; np->gap = 0LL; #ifdef ENDRUN_DEBUG if (np->time.status == SENSOR_S_UNKNOWN) { np->time.status = SENSOR_S_OK; timeout_add_sec(&np->endrun_tout, TRUSTTIME); } #endif np->time.value = np->ts.tv_sec * 1000000000LL + np->ts.tv_nsec - endrun_now; np->time.tv.tv_sec = np->ts.tv_sec; np->time.tv.tv_usec = np->ts.tv_nsec / 1000L; if (np->time.status == SENSOR_S_UNKNOWN) { np->time.status = SENSOR_S_OK; np->time.flags &= ~SENSOR_FINVALID; strlcpy(np->time.desc, "EndRun", sizeof(np->time.desc)); } /* * Only update the timeout if the clock reports the time as valid. * * Time Figure Of Merit (TFOM) values: * * 6 - time error is < 100 us * 7 - time error is < 1 ms * 8 - time error is < 10 ms * 9 - time error is > 10 ms, * unsynchronized state if never locked to CDMA */ switch (tfom = fld[0][0]) { case '6': case '7': case '8': np->time.status = SENSOR_S_OK; np->signal.status = SENSOR_S_OK; break; case '9': np->signal.status = SENSOR_S_WARN; break; default: DPRINTF(("endrun: invalid TFOM: '%c'\n", tfom)); np->signal.status = SENSOR_S_CRIT; break; } #ifdef ENDRUN_DEBUG if (np->tfom != tfom) { DPRINTF(("endrun: TFOM changed from %c to %c\n", np->tfom, tfom)); np->tfom = tfom; } #endif if (jumped) np->time.status = SENSOR_S_WARN; if (np->time.status == SENSOR_S_OK) timeout_add_sec(&np->endrun_tout, TRUSTTIME); /* * If tty timestamping is requested, but no PPS signal is present, set * the sensor state to CRITICAL. */ if (np->no_pps) np->time.status = SENSOR_S_CRIT; } int endrun_atoi(char *s, int len) { int n; char *p; /* make sure the input contains only numbers */ for (n = 0, p = s; n < len && *p && *p >= '0' && *p <= '9'; n++, p++) ; if (n != len || *p != '\0') return -1; for (n = 0; *s; s++) n = n * 10 + *s - '0'; return n; } /* * Convert date fields from EndRun to nanoseconds since the epoch. * The year string must be of the form YYYY . * The day of year string must be of the form DDD . * Return 0 on success, -1 if illegal characters are encountered. */ int endrun_date_to_nano(char *y, char *doy, int64_t *nano) { struct clock_ymdhms clock; time_t secs; int n, i; int year_days = 365; int month_days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; #define FEBRUARY 2 #define LEAPYEAR(x) \ ((x) % 4 == 0 && \ (x) % 100 != 0) || \ (x) % 400 == 0 if ((n = endrun_atoi(y, 4)) == -1) return -1; clock.dt_year = n; if (LEAPYEAR(n)) { month_days[FEBRUARY]++; year_days++; } if ((n = endrun_atoi(doy, 3)) == -1 || n == 0 || n > year_days) return -1; /* convert day of year to month, day */ for (i = 1; n > month_days[i]; i++) { n -= month_days[i]; } clock.dt_mon = i; clock.dt_day = n; DPRINTFN(1, ("mm/dd %d/%d\n", i, n)); clock.dt_hour = clock.dt_min = clock.dt_sec = 0; secs = clock_ymdhms_to_secs(&clock); *nano = secs * 1000000000LL; return 0; } /* * Convert time field from EndRun to nanoseconds since midnight. * The string must be of the form HH:MM:SS . * Return 0 on success, -1 if illegal characters are encountered. */ int endrun_time_to_nano(char *s, int64_t *nano) { struct clock_ymdhms clock; time_t secs; int n; if (s[2] != ':' || s[5] != ':') return -1; s[2] = '\0'; s[5] = '\0'; if ((n = endrun_atoi(&s[0], 2)) == -1 || n > 23) return -1; clock.dt_hour = n; if ((n = endrun_atoi(&s[3], 2)) == -1 || n > 59) return -1; clock.dt_min = n; if ((n = endrun_atoi(&s[6], 2)) == -1 || n > 60) return -1; clock.dt_sec = n; DPRINTFN(1, ("hh:mm:ss %d:%d:%d\n", (int)clock.dt_hour, (int)clock.dt_min, (int)clock.dt_sec)); secs = clock.dt_hour * 3600 + clock.dt_min * 60 + clock.dt_sec; DPRINTFN(1, ("secs %lu\n", (unsigned long)secs)); *nano = secs * 1000000000LL; return 0; } int endrun_offset_to_nano(char *s, int64_t *nano) { time_t secs; int n; if (!(s[0] == '+' || s[0] == '-')) return -1; if ((n = endrun_atoi(&s[1], 2)) == -1) return -1; secs = n * 30 * 60; *nano = secs * 1000000000LL; if (s[0] == '+') *nano = -*nano; DPRINTFN(1, ("offset secs %lu nanosecs %lld\n", (unsigned long)secs, (long long)*nano)); return 0; } /* * Degrade the sensor state if we received no EndRun string for more than * TRUSTTIME seconds. */ void endrun_timeout(void *xnp) { struct endrun *np = xnp; if (np->time.status == SENSOR_S_OK) { np->time.status = SENSOR_S_WARN; /* * further degrade in TRUSTTIME seconds if no new valid EndRun * strings are received. */ timeout_add_sec(&np->endrun_tout, TRUSTTIME); } else np->time.status = SENSOR_S_CRIT; }
73 72 29 1 2 148 148 148 147 1 1 13 133 141 138 135 125 93 127 113 121 120 148 31 108 8 8 8 8 108 108 99 17 17 62 17 51 15 22 5 22 15 15 73 17 36 2 19 18 4 30 2 115 103 2 4 11 4 36 58 56 55 49 21 28 68 52 34 1 23 1 5 2 2 2 2 3 1 17 8 24 8 1 11 2 3 14 13 3 11 4 13 1 12 2 11 2 11 3 1 2 4 4 1 1 3 4 10 3 7 7 111 111 1 111 1 1 1 2 11 47 111 111 111 2 5 40 5 1 1 2 1 2 7 2 3 1 7 8 2 21 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 /* $OpenBSD: ip6_input.c,v 1.262 2024/05/08 13:01:30 bluhm Exp $ */ /* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 1982, 1986, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ip_input.c 8.2 (Berkeley) 1/4/94 */ #include "pf.h" #include "carp.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/domain.h> #include <sys/sysctl.h> #include <sys/protosw.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/errno.h> #include <sys/time.h> #include <sys/timeout.h> #include <sys/kernel.h> #include <sys/syslog.h> #include <sys/task.h> #include <net/if.h> #include <net/if_var.h> #include <net/if_types.h> #include <net/route.h> #include <net/netisr.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/in_pcb.h> #include <netinet/ip_var.h> #include <netinet6/in6_var.h> #include <netinet6/in6_ifattach.h> #include <netinet/ip6.h> #include <netinet6/ip6_var.h> #include <netinet/icmp6.h> #include <netinet6/nd6.h> #include "gif.h" #include "bpfilter.h" #ifdef MROUTING #include <netinet6/ip6_mroute.h> #endif #if NPF > 0 #include <net/pfvar.h> #endif #if NCARP > 0 #include <netinet/ip_carp.h> #endif struct niqueue ip6intrq = NIQUEUE_INITIALIZER(IPQ_MAXLEN, NETISR_IPV6); struct cpumem *ip6counters; uint8_t ip6_soiikey[IP6_SOIIKEY_LEN]; int ip6_ours(struct mbuf **, int *, int, int); int ip6_check_rh0hdr(struct mbuf *, int *); int ip6_hbhchcheck(struct mbuf **, int *, int *); int ip6_hopopts_input(struct mbuf **, int *, u_int32_t *, u_int32_t *); struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int); int ip6_sysctl_soiikey(void *, size_t *, void *, size_t); static struct mbuf_queue ip6send_mq; static void ip6_send_dispatch(void *); static struct task ip6send_task = TASK_INITIALIZER(ip6_send_dispatch, &ip6send_mq); /* * IP6 initialization: fill in IP6 protocol switch table. * All protocols not implemented in kernel go to raw IP6 protocol handler. */ void ip6_init(void) { const struct protosw *pr; int i; pr = pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW); if (pr == NULL) panic("%s", __func__); for (i = 0; i < IPPROTO_MAX; i++) ip6_protox[i] = pr - inet6sw; for (pr = inet6domain.dom_protosw; pr < inet6domain.dom_protoswNPROTOSW; pr++) if (pr->pr_domain->dom_family == PF_INET6 && pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW && pr->pr_protocol < IPPROTO_MAX) ip6_protox[pr->pr_protocol] = pr - inet6sw; ip6_randomid_init(); nd6_init(); frag6_init(); mq_init(&ip6send_mq, 64, IPL_SOFTNET); ip6counters = counters_alloc(ip6s_ncounters); #ifdef MROUTING rt_timer_queue_init(&ip6_mrouterq, MCAST_EXPIRE_TIMEOUT, &mf6c_expire_route); #endif } /* * Enqueue packet for local delivery. Queuing is used as a boundary * between the network layer (input/forward path) running with * NET_LOCK_SHARED() and the transport layer needing it exclusively. */ int ip6_ours(struct mbuf **mp, int *offp, int nxt, int af) { /* ip6_hbhchcheck() may be run before, then off and nxt are set */ if (*offp == 0) { nxt = ip6_hbhchcheck(mp, offp, NULL); if (nxt == IPPROTO_DONE) return IPPROTO_DONE; } /* We are already in a IPv4/IPv6 local deliver loop. */ if (af != AF_UNSPEC) return nxt; nxt = ip_deliver(mp, offp, nxt, AF_INET6, 1); if (nxt == IPPROTO_DONE) return IPPROTO_DONE; /* save values for later, use after dequeue */ if (*offp != sizeof(struct ip6_hdr)) { struct m_tag *mtag; struct ipoffnxt *ion; /* mbuf tags are expensive, but only used for header options */ mtag = m_tag_get(PACKET_TAG_IP6_OFFNXT, sizeof(*ion), M_NOWAIT); if (mtag == NULL) { ip6stat_inc(ip6s_idropped); m_freemp(mp); return IPPROTO_DONE; } ion = (struct ipoffnxt *)(mtag + 1); ion->ion_off = *offp; ion->ion_nxt = nxt; m_tag_prepend(*mp, mtag); } niq_enqueue(&ip6intrq, *mp); *mp = NULL; return IPPROTO_DONE; } /* * Dequeue and process locally delivered packets. * This is called with exclusive NET_LOCK(). */ void ip6intr(void) { struct mbuf *m; while ((m = niq_dequeue(&ip6intrq)) != NULL) { struct m_tag *mtag; int off, nxt; #ifdef DIAGNOSTIC if ((m->m_flags & M_PKTHDR) == 0) panic("ip6intr no HDR"); #endif mtag = m_tag_find(m, PACKET_TAG_IP6_OFFNXT, NULL); if (mtag != NULL) { struct ipoffnxt *ion; ion = (struct ipoffnxt *)(mtag + 1); off = ion->ion_off; nxt = ion->ion_nxt; m_tag_delete(m, mtag); } else { struct ip6_hdr *ip6; ip6 = mtod(m, struct ip6_hdr *); off = sizeof(struct ip6_hdr); nxt = ip6->ip6_nxt; } nxt = ip_deliver(&m, &off, nxt, AF_INET6, 0); KASSERT(nxt == IPPROTO_DONE); } } void ipv6_input(struct ifnet *ifp, struct mbuf *m) { int off, nxt; off = 0; nxt = ip6_input_if(&m, &off, IPPROTO_IPV6, AF_UNSPEC, ifp); KASSERT(nxt == IPPROTO_DONE); } struct mbuf * ipv6_check(struct ifnet *ifp, struct mbuf *m) { struct ip6_hdr *ip6; if (m->m_len < sizeof(*ip6)) { m = m_pullup(m, sizeof(*ip6)); if (m == NULL) { ip6stat_inc(ip6s_toosmall); return (NULL); } } ip6 = mtod(m, struct ip6_hdr *); if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { ip6stat_inc(ip6s_badvers); goto bad; } /* * Check against address spoofing/corruption. */ if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) || IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) { /* * XXX: "badscope" is not very suitable for a multicast source. */ ip6stat_inc(ip6s_badscope); goto bad; } if ((IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) || IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)) && (ifp->if_flags & IFF_LOOPBACK) == 0) { ip6stat_inc(ip6s_badscope); goto bad; } /* Drop packets if interface ID portion is already filled. */ if (((IN6_IS_SCOPE_EMBED(&ip6->ip6_src) && ip6->ip6_src.s6_addr16[1]) || (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst) && ip6->ip6_dst.s6_addr16[1])) && (ifp->if_flags & IFF_LOOPBACK) == 0) { ip6stat_inc(ip6s_badscope); goto bad; } if (IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst) && !(m->m_flags & M_LOOP)) { /* * In this case, the packet should come from the loopback * interface. However, we cannot just check the if_flags, * because ip6_mloopback() passes the "actual" interface * as the outgoing/incoming interface. */ ip6stat_inc(ip6s_badscope); goto bad; } /* * The following check is not documented in specs. A malicious * party may be able to use IPv4 mapped addr to confuse tcp/udp stack * and bypass security checks (act as if it was from 127.0.0.1 by using * IPv6 src ::ffff:127.0.0.1). Be cautious. * * This check chokes if we are in an SIIT cloud. As none of BSDs * support IPv4-less kernel compilation, we cannot support SIIT * environment at all. So, it makes more sense for us to reject any * malicious packets for non-SIIT environment, than try to do a * partial support for SIIT environment. */ if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { ip6stat_inc(ip6s_badscope); goto bad; } /* * Reject packets with IPv4 compatible addresses (auto tunnel). * * The code forbids automatic tunneling as per RFC4213. */ if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src) || IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) { ip6stat_inc(ip6s_badscope); goto bad; } return (m); bad: m_freem(m); return (NULL); } int ip6_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp) { struct route ro; struct mbuf *m; struct ip6_hdr *ip6; struct rtentry *rt; int ours = 0; u_int16_t src_scope, dst_scope; #if NPF > 0 struct in6_addr odst; #endif int pfrdr = 0; KASSERT(*offp == 0); ro.ro_rt = NULL; ip6stat_inc(ip6s_total); m = *mp = ipv6_check(ifp, *mp); if (m == NULL) goto bad; ip6 = mtod(m, struct ip6_hdr *); #if NCARP > 0 if (carp_lsdrop(ifp, m, AF_INET6, ip6->ip6_src.s6_addr32, ip6->ip6_dst.s6_addr32, (ip6->ip6_nxt == IPPROTO_ICMPV6 ? 0 : 1))) goto bad; #endif ip6stat_inc(ip6s_nxthist + ip6->ip6_nxt); /* * If the packet has been received on a loopback interface it * can be destined to any local address, not necessarily to * an address configured on `ifp'. */ if (ifp->if_flags & IFF_LOOPBACK) { if (IN6_IS_SCOPE_EMBED(&ip6->ip6_src)) { src_scope = ip6->ip6_src.s6_addr16[1]; ip6->ip6_src.s6_addr16[1] = 0; } if (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst)) { dst_scope = ip6->ip6_dst.s6_addr16[1]; ip6->ip6_dst.s6_addr16[1] = 0; } } #if NPF > 0 /* * Packet filter */ odst = ip6->ip6_dst; if (pf_test(AF_INET6, PF_IN, ifp, mp) != PF_PASS) goto bad; m = *mp; if (m == NULL) goto bad; ip6 = mtod(m, struct ip6_hdr *); pfrdr = !IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst); #endif /* * Without embedded scope ID we cannot find link-local * addresses in the routing table. */ if (ifp->if_flags & IFF_LOOPBACK) { if (IN6_IS_SCOPE_EMBED(&ip6->ip6_src)) ip6->ip6_src.s6_addr16[1] = src_scope; if (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst)) ip6->ip6_dst.s6_addr16[1] = dst_scope; } else { if (IN6_IS_SCOPE_EMBED(&ip6->ip6_src)) ip6->ip6_src.s6_addr16[1] = htons(ifp->if_index); if (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst)) ip6->ip6_dst.s6_addr16[1] = htons(ifp->if_index); } /* * Be more secure than RFC5095 and scan for type 0 routing headers. * If pf has already scanned the header chain, do not do it twice. */ if (!(m->m_pkthdr.pf.flags & PF_TAG_PROCESSED) && ip6_check_rh0hdr(m, offp)) { ip6stat_inc(ip6s_badoptions); icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, *offp); m = *mp = NULL; goto bad; } #if NPF > 0 if (pf_ouraddr(m) == 1) { nxt = ip6_ours(mp, offp, nxt, af); goto out; } #endif /* * Multicast check */ if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { /* * Make sure M_MCAST is set. It should theoretically * already be there, but let's play safe because upper * layers check for this flag. */ m->m_flags |= M_MCAST; /* * See if we belong to the destination multicast group on the * arrival interface. */ if (in6_hasmulti(&ip6->ip6_dst, ifp)) ours = 1; #ifdef MROUTING if (ip6_mforwarding && ip6_mrouter[ifp->if_rdomain]) { int error; nxt = ip6_hbhchcheck(&m, offp, &ours); if (nxt == IPPROTO_DONE) goto out; ip6 = mtod(m, struct ip6_hdr *); /* * If we are acting as a multicast router, all * incoming multicast packets are passed to the * kernel-level multicast forwarding function. * The packet is returned (relatively) intact; if * ip6_mforward() returns a non-zero value, the packet * must be discarded, else it may be accepted below. */ KERNEL_LOCK(); error = ip6_mforward(ip6, ifp, m); KERNEL_UNLOCK(); if (error) { ip6stat_inc(ip6s_cantforward); goto bad; } if (ours) { if (af == AF_UNSPEC) nxt = ip6_ours(mp, offp, nxt, af); goto out; } goto bad; } #endif if (!ours) { ip6stat_inc(ip6s_notmember); if (!IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst)) ip6stat_inc(ip6s_cantforward); goto bad; } nxt = ip6_ours(mp, offp, nxt, af); goto out; } /* * Unicast check */ rt = route6_mpath(&ro, &ip6->ip6_dst, &ip6->ip6_src, m->m_pkthdr.ph_rtableid); /* * Accept the packet if the route to the destination is marked * as local. */ if (rt != NULL && ISSET(rt->rt_flags, RTF_LOCAL)) { struct in6_ifaddr *ia6 = ifatoia6(rt->rt_ifa); if (ip6_forwarding == 0 && rt->rt_ifidx != ifp->if_index && !((ifp->if_flags & IFF_LOOPBACK) || (ifp->if_type == IFT_ENC) || (m->m_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST))) { /* received on wrong interface */ #if NCARP > 0 struct ifnet *out_if; /* * Virtual IPs on carp interfaces need to be checked * also against the parent interface and other carp * interfaces sharing the same parent. */ out_if = if_get(rt->rt_ifidx); if (!(out_if && carp_strict_addr_chk(out_if, ifp))) { ip6stat_inc(ip6s_wrongif); if_put(out_if); goto bad; } if_put(out_if); #else ip6stat_inc(ip6s_wrongif); goto bad; #endif } /* * packets to a tentative, duplicated, or somehow invalid * address must not be accepted. */ if ((ia6->ia6_flags & (IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED))) { char src[INET6_ADDRSTRLEN], dst[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, &ip6->ip6_src, src, sizeof(src)); inet_ntop(AF_INET6, &ip6->ip6_dst, dst, sizeof(dst)); /* address is not ready, so discard the packet. */ nd6log((LOG_INFO, "%s: packet to an unready address %s->%s\n", __func__, src, dst)); goto bad; } else { nxt = ip6_ours(mp, offp, nxt, af); goto out; } } #if NCARP > 0 if (ip6->ip6_nxt == IPPROTO_ICMPV6 && carp_lsdrop(ifp, m, AF_INET6, ip6->ip6_src.s6_addr32, ip6->ip6_dst.s6_addr32, 1)) goto bad; #endif /* * Now there is no reason to process the packet if it's not our own * and we're not a router. */ if (!ip6_forwarding) { ip6stat_inc(ip6s_cantforward); goto bad; } nxt = ip6_hbhchcheck(&m, offp, &ours); if (nxt == IPPROTO_DONE) goto out; if (ours) { if (af == AF_UNSPEC) nxt = ip6_ours(mp, offp, nxt, af); goto out; } #ifdef IPSEC if (ipsec_in_use) { int rv; rv = ipsec_forward_check(m, *offp, AF_INET6); if (rv != 0) { ip6stat_inc(ip6s_cantforward); goto bad; } /* * Fall through, forward packet. Outbound IPsec policy * checking will occur in ip6_forward(). */ } #endif /* IPSEC */ ip6_forward(m, &ro, pfrdr); *mp = NULL; rtfree(ro.ro_rt); return IPPROTO_DONE; bad: nxt = IPPROTO_DONE; m_freemp(mp); out: rtfree(ro.ro_rt); return nxt; } /* On error free mbuf and return IPPROTO_DONE. */ int ip6_hbhchcheck(struct mbuf **mp, int *offp, int *oursp) { struct ip6_hdr *ip6; u_int32_t plen, rtalert = ~0; int nxt; ip6 = mtod(*mp, struct ip6_hdr *); /* * Process Hop-by-Hop options header if it's contained. * m may be modified in ip6_hopopts_input(). * If a JumboPayload option is included, plen will also be modified. */ plen = (u_int32_t)ntohs(ip6->ip6_plen); *offp = sizeof(struct ip6_hdr); if (ip6->ip6_nxt == IPPROTO_HOPOPTS) { struct ip6_hbh *hbh; if (ip6_hopopts_input(mp, offp, &plen, &rtalert)) goto bad; /* m have already been freed */ /* adjust pointer */ ip6 = mtod(*mp, struct ip6_hdr *); /* * if the payload length field is 0 and the next header field * indicates Hop-by-Hop Options header, then a Jumbo Payload * option MUST be included. */ if (ip6->ip6_plen == 0 && plen == 0) { /* * Note that if a valid jumbo payload option is * contained, ip6_hopopts_input() must set a valid * (non-zero) payload length to the variable plen. */ ip6stat_inc(ip6s_badoptions); icmp6_error(*mp, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, (caddr_t)&ip6->ip6_plen - (caddr_t)ip6); goto bad; } IP6_EXTHDR_GET(hbh, struct ip6_hbh *, *mp, sizeof(struct ip6_hdr), sizeof(struct ip6_hbh)); if (hbh == NULL) { ip6stat_inc(ip6s_tooshort); goto bad; } nxt = hbh->ip6h_nxt; /* * accept the packet if a router alert option is included * and we act as an IPv6 router. */ if (rtalert != ~0 && ip6_forwarding && oursp != NULL) *oursp = 1; } else nxt = ip6->ip6_nxt; /* * Check that the amount of data in the buffers * is as at least much as the IPv6 header would have us expect. * Trim mbufs if longer than we expect. * Drop packet if shorter than we expect. */ if ((*mp)->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) { ip6stat_inc(ip6s_tooshort); m_freemp(mp); goto bad; } if ((*mp)->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) { if ((*mp)->m_len == (*mp)->m_pkthdr.len) { (*mp)->m_len = sizeof(struct ip6_hdr) + plen; (*mp)->m_pkthdr.len = sizeof(struct ip6_hdr) + plen; } else { m_adj((*mp), sizeof(struct ip6_hdr) + plen - (*mp)->m_pkthdr.len); } } return nxt; bad: return IPPROTO_DONE; } /* scan packet for RH0 routing header. Mostly stolen from pf.c:pf_test() */ int ip6_check_rh0hdr(struct mbuf *m, int *offp) { struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); struct ip6_rthdr rthdr; struct ip6_ext opt6; u_int8_t proto = ip6->ip6_nxt; int done = 0, lim, off, rh_cnt = 0; off = ((caddr_t)ip6 - m->m_data) + sizeof(struct ip6_hdr); lim = min(m->m_pkthdr.len, ntohs(ip6->ip6_plen) + sizeof(*ip6)); do { switch (proto) { case IPPROTO_ROUTING: if (rh_cnt++) { /* more than one rh header present */ *offp = off; return (1); } if (off + sizeof(rthdr) > lim) { /* packet to short to make sense */ *offp = off; return (1); } m_copydata(m, off, sizeof(rthdr), &rthdr); if (rthdr.ip6r_type == IPV6_RTHDR_TYPE_0) { *offp = off + offsetof(struct ip6_rthdr, ip6r_type); return (1); } off += (rthdr.ip6r_len + 1) * 8; proto = rthdr.ip6r_nxt; break; case IPPROTO_AH: case IPPROTO_HOPOPTS: case IPPROTO_DSTOPTS: /* get next header and header length */ if (off + sizeof(opt6) > lim) { /* * Packet to short to make sense, we could * reject the packet but as a router we * should not do that so forward it. */ return (0); } m_copydata(m, off, sizeof(opt6), &opt6); if (proto == IPPROTO_AH) off += (opt6.ip6e_len + 2) * 4; else off += (opt6.ip6e_len + 1) * 8; proto = opt6.ip6e_nxt; break; case IPPROTO_FRAGMENT: default: /* end of header stack */ done = 1; break; } } while (!done); return (0); } /* * Hop-by-Hop options header processing. If a valid jumbo payload option is * included, the real payload length will be stored in plenp. * On error free mbuf and return -1. * * rtalertp - XXX: should be stored in a more smart way */ int ip6_hopopts_input(struct mbuf **mp, int *offp, u_int32_t *plenp, u_int32_t *rtalertp) { int off = *offp, hbhlen; struct ip6_hbh *hbh; /* validation of the length of the header */ IP6_EXTHDR_GET(hbh, struct ip6_hbh *, *mp, sizeof(struct ip6_hdr), sizeof(struct ip6_hbh)); if (hbh == NULL) { ip6stat_inc(ip6s_tooshort); return -1; } hbhlen = (hbh->ip6h_len + 1) << 3; IP6_EXTHDR_GET(hbh, struct ip6_hbh *, *mp, sizeof(struct ip6_hdr), hbhlen); if (hbh == NULL) { ip6stat_inc(ip6s_tooshort); return -1; } off += hbhlen; hbhlen -= sizeof(struct ip6_hbh); if (ip6_process_hopopts(mp, (u_int8_t *)hbh + sizeof(struct ip6_hbh), hbhlen, rtalertp, plenp) < 0) return (-1); *offp = off; return (0); } /* * Search header for all Hop-by-hop options and process each option. * This function is separate from ip6_hopopts_input() in order to * handle a case where the sending node itself process its hop-by-hop * options header. In such a case, the function is called from ip6_output(). * On error free mbuf and return -1. * * The function assumes that hbh header is located right after the IPv6 header * (RFC2460 p7), opthead is pointer into data content in m, and opthead to * opthead + hbhlen is located in continuous memory region. */ int ip6_process_hopopts(struct mbuf **mp, u_int8_t *opthead, int hbhlen, u_int32_t *rtalertp, u_int32_t *plenp) { struct ip6_hdr *ip6; int optlen = 0; u_int8_t *opt = opthead; u_int16_t rtalert_val; u_int32_t jumboplen; const int erroff = sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh); for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) { switch (*opt) { case IP6OPT_PAD1: optlen = 1; break; case IP6OPT_PADN: if (hbhlen < IP6OPT_MINLEN) { ip6stat_inc(ip6s_toosmall); goto bad; } optlen = *(opt + 1) + 2; break; case IP6OPT_ROUTER_ALERT: /* XXX may need check for alignment */ if (hbhlen < IP6OPT_RTALERT_LEN) { ip6stat_inc(ip6s_toosmall); goto bad; } if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2) { /* XXX stat */ icmp6_error(*mp, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, erroff + opt + 1 - opthead); return (-1); } optlen = IP6OPT_RTALERT_LEN; memcpy((caddr_t)&rtalert_val, (caddr_t)(opt + 2), 2); *rtalertp = ntohs(rtalert_val); break; case IP6OPT_JUMBO: /* XXX may need check for alignment */ if (hbhlen < IP6OPT_JUMBO_LEN) { ip6stat_inc(ip6s_toosmall); goto bad; } if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) { /* XXX stat */ icmp6_error(*mp, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, erroff + opt + 1 - opthead); return (-1); } optlen = IP6OPT_JUMBO_LEN; /* * IPv6 packets that have non 0 payload length * must not contain a jumbo payload option. */ ip6 = mtod(*mp, struct ip6_hdr *); if (ip6->ip6_plen) { ip6stat_inc(ip6s_badoptions); icmp6_error(*mp, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, erroff + opt - opthead); return (-1); } /* * We may see jumbolen in unaligned location, so * we'd need to perform memcpy(). */ memcpy(&jumboplen, opt + 2, sizeof(jumboplen)); jumboplen = (u_int32_t)htonl(jumboplen); #if 1 /* * if there are multiple jumbo payload options, * *plenp will be non-zero and the packet will be * rejected. * the behavior may need some debate in ipngwg - * multiple options does not make sense, however, * there's no explicit mention in specification. */ if (*plenp != 0) { ip6stat_inc(ip6s_badoptions); icmp6_error(*mp, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, erroff + opt + 2 - opthead); return (-1); } #endif /* * jumbo payload length must be larger than 65535. */ if (jumboplen <= IPV6_MAXPACKET) { ip6stat_inc(ip6s_badoptions); icmp6_error(*mp, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, erroff + opt + 2 - opthead); return (-1); } *plenp = jumboplen; break; default: /* unknown option */ if (hbhlen < IP6OPT_MINLEN) { ip6stat_inc(ip6s_toosmall); goto bad; } optlen = ip6_unknown_opt(mp, opt, erroff + opt - opthead); if (optlen == -1) return (-1); optlen += 2; break; } } return (0); bad: m_freemp(mp); return (-1); } /* * Unknown option processing. * The third argument `off' is the offset from the IPv6 header to the option, * which allows returning an ICMPv6 error even if the IPv6 header and the * option header are not continuous. * On error free mbuf and return -1. */ int ip6_unknown_opt(struct mbuf **mp, u_int8_t *optp, int off) { struct ip6_hdr *ip6; switch (IP6OPT_TYPE(*optp)) { case IP6OPT_TYPE_SKIP: /* ignore the option */ return ((int)*(optp + 1)); case IP6OPT_TYPE_DISCARD: /* silently discard */ m_freemp(mp); return (-1); case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */ ip6stat_inc(ip6s_badoptions); icmp6_error(*mp, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off); return (-1); case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */ ip6stat_inc(ip6s_badoptions); ip6 = mtod(*mp, struct ip6_hdr *); if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) || ((*mp)->m_flags & (M_BCAST|M_MCAST))) m_freemp(mp); else icmp6_error(*mp, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off); return (-1); } m_freemp(mp); /* XXX: NOTREACHED */ return (-1); } /* * Create the "control" list for this pcb. * * The routine will be called from upper layer handlers like udp_input(). * Thus the routine assumes that the caller (udp_input) have already * called IP6_EXTHDR_CHECK() and all the extension headers are located in the * very first mbuf on the mbuf chain. * We may want to add some infinite loop prevention or sanity checks for safety. * (This applies only when you are using KAME mbuf chain restriction, i.e. * you are using IP6_EXTHDR_CHECK() not m_pulldown()) */ void ip6_savecontrol(struct inpcb *inp, struct mbuf *m, struct mbuf **mp) { struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); if (inp->inp_socket->so_options & SO_TIMESTAMP) { struct timeval tv; m_microtime(m, &tv); *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv), SCM_TIMESTAMP, SOL_SOCKET); if (*mp) mp = &(*mp)->m_next; } /* RFC 2292 sec. 5 */ if ((inp->inp_flags & IN6P_PKTINFO) != 0) { struct in6_pktinfo pi6; memcpy(&pi6.ipi6_addr, &ip6->ip6_dst, sizeof(struct in6_addr)); if (IN6_IS_SCOPE_EMBED(&pi6.ipi6_addr)) pi6.ipi6_addr.s6_addr16[1] = 0; pi6.ipi6_ifindex = m ? m->m_pkthdr.ph_ifidx : 0; *mp = sbcreatecontrol((caddr_t) &pi6, sizeof(struct in6_pktinfo), IPV6_PKTINFO, IPPROTO_IPV6); if (*mp) mp = &(*mp)->m_next; } if ((inp->inp_flags & IN6P_HOPLIMIT) != 0) { int hlim = ip6->ip6_hlim & 0xff; *mp = sbcreatecontrol((caddr_t) &hlim, sizeof(int), IPV6_HOPLIMIT, IPPROTO_IPV6); if (*mp) mp = &(*mp)->m_next; } if ((inp->inp_flags & IN6P_TCLASS) != 0) { u_int32_t flowinfo; int tclass; flowinfo = (u_int32_t)ntohl(ip6->ip6_flow & IPV6_FLOWINFO_MASK); flowinfo >>= 20; tclass = flowinfo & 0xff; *mp = sbcreatecontrol((caddr_t)&tclass, sizeof(tclass), IPV6_TCLASS, IPPROTO_IPV6); if (*mp) mp = &(*mp)->m_next; } /* * IPV6_HOPOPTS socket option. Recall that we required super-user * privilege for the option (see ip6_ctloutput), but it might be too * strict, since there might be some hop-by-hop options which can be * returned to normal user. * See also RFC 2292 section 6 (or RFC 3542 section 8). */ if ((inp->inp_flags & IN6P_HOPOPTS) != 0) { /* * Check if a hop-by-hop options header is contained in the * received packet, and if so, store the options as ancillary * data. Note that a hop-by-hop options header must be * just after the IPv6 header, which is assured through the * IPv6 input processing. */ struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); if (ip6->ip6_nxt == IPPROTO_HOPOPTS) { struct ip6_hbh *hbh; int hbhlen = 0; struct mbuf *ext; ext = ip6_pullexthdr(m, sizeof(struct ip6_hdr), ip6->ip6_nxt); if (ext == NULL) { ip6stat_inc(ip6s_tooshort); return; } hbh = mtod(ext, struct ip6_hbh *); hbhlen = (hbh->ip6h_len + 1) << 3; if (hbhlen != ext->m_len) { m_freem(ext); ip6stat_inc(ip6s_tooshort); return; } /* * XXX: We copy the whole header even if a * jumbo payload option is included, the option which * is to be removed before returning according to * RFC2292. * Note: this constraint is removed in RFC3542. */ *mp = sbcreatecontrol((caddr_t)hbh, hbhlen, IPV6_HOPOPTS, IPPROTO_IPV6); if (*mp) mp = &(*mp)->m_next; m_freem(ext); } } /* IPV6_DSTOPTS and IPV6_RTHDR socket options */ if ((inp->inp_flags & (IN6P_RTHDR | IN6P_DSTOPTS)) != 0) { struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr); /* * Search for destination options headers or routing * header(s) through the header chain, and stores each * header as ancillary data. * Note that the order of the headers remains in * the chain of ancillary data. */ while (1) { /* is explicit loop prevention necessary? */ struct ip6_ext *ip6e = NULL; int elen; struct mbuf *ext = NULL; /* * if it is not an extension header, don't try to * pull it from the chain. */ switch (nxt) { case IPPROTO_DSTOPTS: case IPPROTO_ROUTING: case IPPROTO_HOPOPTS: case IPPROTO_AH: /* is it possible? */ break; default: goto loopend; } ext = ip6_pullexthdr(m, off, nxt); if (ext == NULL) { ip6stat_inc(ip6s_tooshort); return; } ip6e = mtod(ext, struct ip6_ext *); if (nxt == IPPROTO_AH) elen = (ip6e->ip6e_len + 2) << 2; else elen = (ip6e->ip6e_len + 1) << 3; if (elen != ext->m_len) { m_freem(ext); ip6stat_inc(ip6s_tooshort); return; } switch (nxt) { case IPPROTO_DSTOPTS: if (!(inp->inp_flags & IN6P_DSTOPTS)) break; *mp = sbcreatecontrol((caddr_t)ip6e, elen, IPV6_DSTOPTS, IPPROTO_IPV6); if (*mp) mp = &(*mp)->m_next; break; case IPPROTO_ROUTING: if (!(inp->inp_flags & IN6P_RTHDR)) break; *mp = sbcreatecontrol((caddr_t)ip6e, elen, IPV6_RTHDR, IPPROTO_IPV6); if (*mp) mp = &(*mp)->m_next; break; case IPPROTO_HOPOPTS: case IPPROTO_AH: /* is it possible? */ break; default: /* * other cases have been filtered in the above. * none will visit this case. here we supply * the code just in case (nxt overwritten or * other cases). */ m_freem(ext); goto loopend; } /* proceed with the next header. */ off += elen; nxt = ip6e->ip6e_nxt; ip6e = NULL; m_freem(ext); ext = NULL; } loopend: ; } } /* * pull single extension header from mbuf chain. returns single mbuf that * contains the result, or NULL on error. */ struct mbuf * ip6_pullexthdr(struct mbuf *m, size_t off, int nxt) { struct ip6_ext ip6e; size_t elen; struct mbuf *n; #ifdef DIAGNOSTIC switch (nxt) { case IPPROTO_DSTOPTS: case IPPROTO_ROUTING: case IPPROTO_HOPOPTS: case IPPROTO_AH: /* is it possible? */ break; default: printf("ip6_pullexthdr: invalid nxt=%d\n", nxt); } #endif if (off + sizeof(ip6e) > m->m_pkthdr.len) return NULL; m_copydata(m, off, sizeof(ip6e), &ip6e); if (nxt == IPPROTO_AH) elen = (ip6e.ip6e_len + 2) << 2; else elen = (ip6e.ip6e_len + 1) << 3; if (off + elen > m->m_pkthdr.len) return NULL; MGET(n, M_DONTWAIT, MT_DATA); if (n && elen >= MLEN) { MCLGET(n, M_DONTWAIT); if ((n->m_flags & M_EXT) == 0) { m_free(n); n = NULL; } } if (n == NULL) { ip6stat_inc(ip6s_idropped); return NULL; } n->m_len = 0; if (elen >= m_trailingspace(n)) { m_free(n); return NULL; } m_copydata(m, off, elen, mtod(n, caddr_t)); n->m_len = elen; return n; } /* * Get offset to the previous header followed by the header * currently processed. */ int ip6_get_prevhdr(struct mbuf *m, int off) { struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); if (off == sizeof(struct ip6_hdr)) { return offsetof(struct ip6_hdr, ip6_nxt); } else if (off < sizeof(struct ip6_hdr)) { panic("%s: off < sizeof(struct ip6_hdr)", __func__); } else { int len, nlen, nxt; struct ip6_ext ip6e; nxt = ip6->ip6_nxt; len = sizeof(struct ip6_hdr); nlen = 0; while (len < off) { m_copydata(m, len, sizeof(ip6e), &ip6e); switch (nxt) { case IPPROTO_FRAGMENT: nlen = sizeof(struct ip6_frag); break; case IPPROTO_AH: nlen = (ip6e.ip6e_len + 2) << 2; break; default: nlen = (ip6e.ip6e_len + 1) << 3; break; } len += nlen; nxt = ip6e.ip6e_nxt; } return (len - nlen); } } /* * get next header offset. m will be retained. */ int ip6_nexthdr(struct mbuf *m, int off, int proto, int *nxtp) { struct ip6_hdr ip6; struct ip6_ext ip6e; struct ip6_frag fh; /* just in case */ if (m == NULL) panic("%s: m == NULL", __func__); if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.len < off) return -1; switch (proto) { case IPPROTO_IPV6: if (m->m_pkthdr.len < off + sizeof(ip6)) return -1; m_copydata(m, off, sizeof(ip6), &ip6); if (nxtp) *nxtp = ip6.ip6_nxt; off += sizeof(ip6); return off; case IPPROTO_FRAGMENT: /* * terminate parsing if it is not the first fragment, * it does not make sense to parse through it. */ if (m->m_pkthdr.len < off + sizeof(fh)) return -1; m_copydata(m, off, sizeof(fh), &fh); if ((fh.ip6f_offlg & IP6F_OFF_MASK) != 0) return -1; if (nxtp) *nxtp = fh.ip6f_nxt; off += sizeof(struct ip6_frag); return off; case IPPROTO_AH: if (m->m_pkthdr.len < off + sizeof(ip6e)) return -1; m_copydata(m, off, sizeof(ip6e), &ip6e); if (nxtp) *nxtp = ip6e.ip6e_nxt; off += (ip6e.ip6e_len + 2) << 2; if (m->m_pkthdr.len < off) return -1; return off; case IPPROTO_HOPOPTS: case IPPROTO_ROUTING: case IPPROTO_DSTOPTS: if (m->m_pkthdr.len < off + sizeof(ip6e)) return -1; m_copydata(m, off, sizeof(ip6e), &ip6e); if (nxtp) *nxtp = ip6e.ip6e_nxt; off += (ip6e.ip6e_len + 1) << 3; if (m->m_pkthdr.len < off) return -1; return off; case IPPROTO_NONE: case IPPROTO_ESP: case IPPROTO_IPCOMP: /* give up */ return -1; default: return -1; } return -1; } /* * get offset for the last header in the chain. m will be kept untainted. */ int ip6_lasthdr(struct mbuf *m, int off, int proto, int *nxtp) { int newoff; int nxt; if (!nxtp) { nxt = -1; nxtp = &nxt; } while (1) { newoff = ip6_nexthdr(m, off, proto, nxtp); if (newoff < 0) return off; else if (newoff < off) return -1; /* invalid */ else if (newoff == off) return newoff; off = newoff; proto = *nxtp; } } /* * System control for IP6 */ const u_char inet6ctlerrmap[PRC_NCMDS] = { 0, 0, 0, 0, 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH, EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, EMSGSIZE, EHOSTUNREACH, 0, 0, 0, 0, 0, 0, ENOPROTOOPT }; #ifdef MROUTING extern int ip6_mrtproto; #endif const struct sysctl_bounded_args ipv6ctl_vars[] = { { IPV6CTL_DAD_PENDING, &ip6_dad_pending, SYSCTL_INT_READONLY }, #ifdef MROUTING { IPV6CTL_MRTPROTO, &ip6_mrtproto, SYSCTL_INT_READONLY }, #endif { IPV6CTL_FORWARDING, &ip6_forwarding, 0, 1 }, { IPV6CTL_SENDREDIRECTS, &ip6_sendredirects, 0, 1 }, { IPV6CTL_DEFHLIM, &ip6_defhlim, 0, 255 }, { IPV6CTL_MAXFRAGPACKETS, &ip6_maxfragpackets, 0, 1000 }, { IPV6CTL_LOG_INTERVAL, &ip6_log_interval, 0, INT_MAX }, { IPV6CTL_HDRNESTLIMIT, &ip6_hdrnestlimit, 0, 100 }, { IPV6CTL_DAD_COUNT, &ip6_dad_count, 0, 10 }, { IPV6CTL_AUTO_FLOWLABEL, &ip6_auto_flowlabel, 0, 1 }, { IPV6CTL_DEFMCASTHLIM, &ip6_defmcasthlim, 0, 255 }, { IPV6CTL_USE_DEPRECATED, &ip6_use_deprecated, 0, 1 }, { IPV6CTL_MAXFRAGS, &ip6_maxfrags, 0, 1000 }, { IPV6CTL_MFORWARDING, &ip6_mforwarding, 0, 1 }, { IPV6CTL_MCAST_PMTU, &ip6_mcast_pmtu, 0, 1 }, { IPV6CTL_NEIGHBORGCTHRESH, &ip6_neighborgcthresh, -1, 5 * 2048 }, { IPV6CTL_MAXDYNROUTES, &ip6_maxdynroutes, -1, 5 * 4096 }, }; int ip6_sysctl_ip6stat(void *oldp, size_t *oldlenp, void *newp) { struct ip6stat *ip6stat; int ret; CTASSERT(sizeof(*ip6stat) == (ip6s_ncounters * sizeof(uint64_t))); ip6stat = malloc(sizeof(*ip6stat), M_TEMP, M_WAITOK); counters_read(ip6counters, (uint64_t *)ip6stat, ip6s_ncounters, NULL); ret = sysctl_rdstruct(oldp, oldlenp, newp, ip6stat, sizeof(*ip6stat)); free(ip6stat, M_TEMP, sizeof(*ip6stat)); return (ret); } int ip6_sysctl_soiikey(void *oldp, size_t *oldlenp, void *newp, size_t newlen) { uint8_t oldkey[IP6_SOIIKEY_LEN]; int error; error = suser(curproc); if (error != 0) return (error); memcpy(oldkey, ip6_soiikey, sizeof(oldkey)); error = sysctl_struct(oldp, oldlenp, newp, newlen, ip6_soiikey, sizeof(ip6_soiikey)); return (error); } int ip6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { #ifdef MROUTING extern struct mrt6stat mrt6stat; #endif int oldval, error; /* Almost all sysctl names at this level are terminal. */ if (namelen != 1 && name[0] != IPV6CTL_IFQUEUE) return (ENOTDIR); switch (name[0]) { case IPV6CTL_STATS: return (ip6_sysctl_ip6stat(oldp, oldlenp, newp)); #ifdef MROUTING case IPV6CTL_MRTSTATS: if (newp != NULL) return (EPERM); NET_LOCK(); error = sysctl_struct(oldp, oldlenp, newp, newlen, &mrt6stat, sizeof(mrt6stat)); NET_UNLOCK(); return (error); case IPV6CTL_MRTMIF: if (newp) return (EPERM); NET_LOCK(); error = mrt6_sysctl_mif(oldp, oldlenp); NET_UNLOCK(); return (error); case IPV6CTL_MRTMFC: if (newp) return (EPERM); NET_LOCK(); error = mrt6_sysctl_mfc(oldp, oldlenp); NET_UNLOCK(); return (error); #else case IPV6CTL_MRTSTATS: case IPV6CTL_MRTPROTO: case IPV6CTL_MRTMIF: case IPV6CTL_MRTMFC: return (EOPNOTSUPP); #endif case IPV6CTL_MTUDISCTIMEOUT: NET_LOCK(); error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &ip6_mtudisc_timeout, 0, INT_MAX); rt_timer_queue_change(&icmp6_mtudisc_timeout_q, ip6_mtudisc_timeout); NET_UNLOCK(); return (error); case IPV6CTL_IFQUEUE: return (sysctl_niq(name + 1, namelen - 1, oldp, oldlenp, newp, newlen, &ip6intrq)); case IPV6CTL_SOIIKEY: return (ip6_sysctl_soiikey(oldp, oldlenp, newp, newlen)); case IPV6CTL_MULTIPATH: NET_LOCK(); oldval = ip6_multipath; error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &ip6_multipath, 0, 1); if (oldval != ip6_multipath) atomic_inc_long(&rtgeneration); NET_UNLOCK(); return (error); default: NET_LOCK(); error = sysctl_bounded_arr(ipv6ctl_vars, nitems(ipv6ctl_vars), name, namelen, oldp, oldlenp, newp, newlen); NET_UNLOCK(); return (error); } /* NOTREACHED */ } void ip6_send_dispatch(void *xmq) { struct mbuf_queue *mq = xmq; struct mbuf *m; struct mbuf_list ml; mq_delist(mq, &ml); if (ml_empty(&ml)) return; NET_LOCK_SHARED(); while ((m = ml_dequeue(&ml)) != NULL) { ip6_output(m, NULL, NULL, 0, NULL, NULL); } NET_UNLOCK_SHARED(); } void ip6_send(struct mbuf *m) { mq_enqueue(&ip6send_mq, m); task_add(net_tq(0), &ip6send_task); }
624 6231 904 6231 6231 900 6230 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 /* $OpenBSD: kern_lock.c,v 1.73 2024/03/26 18:18:30 bluhm Exp $ */ /* * Copyright (c) 2017 Visa Hankala * Copyright (c) 2014 David Gwynne <dlg@openbsd.org> * Copyright (c) 2004 Artur Grabowski <art@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/sched.h> #include <sys/atomic.h> #include <sys/witness.h> #include <sys/mutex.h> #include <ddb/db_output.h> #ifdef MP_LOCKDEBUG #ifndef DDB #error "MP_LOCKDEBUG requires DDB" #endif /* CPU-dependent timing, this needs to be settable from ddb. */ int __mp_lock_spinout = INT_MAX; #endif /* MP_LOCKDEBUG */ #ifdef MULTIPROCESSOR #include <sys/mplock.h> struct __mp_lock kernel_lock; /* * Functions for manipulating the kernel_lock. We put them here * so that they show up in profiles. */ void _kernel_lock_init(void) { __mp_lock_init(&kernel_lock); } /* * Acquire/release the kernel lock. Intended for use in the scheduler * and the lower half of the kernel. */ void _kernel_lock(void) { SCHED_ASSERT_UNLOCKED(); __mp_lock(&kernel_lock); } void _kernel_unlock(void) { __mp_unlock(&kernel_lock); } int _kernel_lock_held(void) { if (panicstr || db_active) return 1; return (__mp_lock_held(&kernel_lock, curcpu())); } #ifdef __USE_MI_MPLOCK /* Ticket lock implementation */ #include <machine/cpu.h> void ___mp_lock_init(struct __mp_lock *mpl, const struct lock_type *type) { memset(mpl->mpl_cpus, 0, sizeof(mpl->mpl_cpus)); mpl->mpl_users = 0; mpl->mpl_ticket = 1; #ifdef WITNESS mpl->mpl_lock_obj.lo_name = type->lt_name; mpl->mpl_lock_obj.lo_type = type; if (mpl == &kernel_lock) mpl->mpl_lock_obj.lo_flags = LO_WITNESS | LO_INITIALIZED | LO_SLEEPABLE | (LO_CLASS_KERNEL_LOCK << LO_CLASSSHIFT); else if (mpl == &sched_lock) mpl->mpl_lock_obj.lo_flags = LO_WITNESS | LO_INITIALIZED | LO_RECURSABLE | (LO_CLASS_SCHED_LOCK << LO_CLASSSHIFT); WITNESS_INIT(&mpl->mpl_lock_obj, type); #endif } static __inline void __mp_lock_spin(struct __mp_lock *mpl, u_int me) { struct schedstate_percpu *spc = &curcpu()->ci_schedstate; #ifdef MP_LOCKDEBUG int nticks = __mp_lock_spinout; #endif spc->spc_spinning++; while (mpl->mpl_ticket != me) { CPU_BUSY_CYCLE(); #ifdef MP_LOCKDEBUG if (--nticks <= 0) { db_printf("%s: %p lock spun out\n", __func__, mpl); db_enter(); nticks = __mp_lock_spinout; } #endif } spc->spc_spinning--; } void __mp_lock(struct __mp_lock *mpl) { struct __mp_lock_cpu *cpu = &mpl->mpl_cpus[cpu_number()]; unsigned long s; #ifdef WITNESS if (!__mp_lock_held(mpl, curcpu())) WITNESS_CHECKORDER(&mpl->mpl_lock_obj, LOP_EXCLUSIVE | LOP_NEWORDER, NULL); #endif s = intr_disable(); if (cpu->mplc_depth++ == 0) cpu->mplc_ticket = atomic_inc_int_nv(&mpl->mpl_users); intr_restore(s); __mp_lock_spin(mpl, cpu->mplc_ticket); membar_enter_after_atomic(); WITNESS_LOCK(&mpl->mpl_lock_obj, LOP_EXCLUSIVE); } void __mp_unlock(struct __mp_lock *mpl) { struct __mp_lock_cpu *cpu = &mpl->mpl_cpus[cpu_number()]; unsigned long s; #ifdef MP_LOCKDEBUG if (!__mp_lock_held(mpl, curcpu())) { db_printf("__mp_unlock(%p): not held lock\n", mpl); db_enter(); } #endif WITNESS_UNLOCK(&mpl->mpl_lock_obj, LOP_EXCLUSIVE); s = intr_disable(); if (--cpu->mplc_depth == 0) { membar_exit(); mpl->mpl_ticket++; } intr_restore(s); } int __mp_release_all(struct __mp_lock *mpl) { struct __mp_lock_cpu *cpu = &mpl->mpl_cpus[cpu_number()]; unsigned long s; int rv; #ifdef WITNESS int i; #endif s = intr_disable(); rv = cpu->mplc_depth; #ifdef WITNESS for (i = 0; i < rv; i++) WITNESS_UNLOCK(&mpl->mpl_lock_obj, LOP_EXCLUSIVE); #endif cpu->mplc_depth = 0; membar_exit(); mpl->mpl_ticket++; intr_restore(s); return (rv); } int __mp_release_all_but_one(struct __mp_lock *mpl) { struct __mp_lock_cpu *cpu = &mpl->mpl_cpus[cpu_number()]; int rv = cpu->mplc_depth - 1; #ifdef WITNESS int i; for (i = 0; i < rv; i++) WITNESS_UNLOCK(&mpl->mpl_lock_obj, LOP_EXCLUSIVE); #endif #ifdef MP_LOCKDEBUG if (!__mp_lock_held(mpl, curcpu())) { db_printf("__mp_release_all_but_one(%p): not held lock\n", mpl); db_enter(); } #endif cpu->mplc_depth = 1; return (rv); } void __mp_acquire_count(struct __mp_lock *mpl, int count) { while (count--) __mp_lock(mpl); } int __mp_lock_held(struct __mp_lock *mpl, struct cpu_info *ci) { struct __mp_lock_cpu *cpu = &mpl->mpl_cpus[CPU_INFO_UNIT(ci)]; return (cpu->mplc_ticket == mpl->mpl_ticket && cpu->mplc_depth > 0); } #endif /* __USE_MI_MPLOCK */ #endif /* MULTIPROCESSOR */ #ifdef __USE_MI_MUTEX void __mtx_init(struct mutex *mtx, int wantipl) { mtx->mtx_owner = NULL; mtx->mtx_wantipl = wantipl; mtx->mtx_oldipl = IPL_NONE; } #ifdef MULTIPROCESSOR void mtx_enter(struct mutex *mtx) { struct schedstate_percpu *spc = &curcpu()->ci_schedstate; #ifdef MP_LOCKDEBUG int nticks = __mp_lock_spinout; #endif WITNESS_CHECKORDER(MUTEX_LOCK_OBJECT(mtx), LOP_EXCLUSIVE | LOP_NEWORDER, NULL); spc->spc_spinning++; while (mtx_enter_try(mtx) == 0) { do { CPU_BUSY_CYCLE(); #ifdef MP_LOCKDEBUG if (--nticks == 0) { db_printf("%s: %p lock spun out\n", __func__, mtx); db_enter(); nticks = __mp_lock_spinout; } #endif } while (mtx->mtx_owner != NULL); } spc->spc_spinning--; } int mtx_enter_try(struct mutex *mtx) { struct cpu_info *owner, *ci = curcpu(); int s; /* Avoid deadlocks after panic or in DDB */ if (panicstr || db_active) return (1); if (mtx->mtx_wantipl != IPL_NONE) s = splraise(mtx->mtx_wantipl); owner = atomic_cas_ptr(&mtx->mtx_owner, NULL, ci); #ifdef DIAGNOSTIC if (__predict_false(owner == ci)) panic("mtx %p: locking against myself", mtx); #endif if (owner == NULL) { membar_enter_after_atomic(); if (mtx->mtx_wantipl != IPL_NONE) mtx->mtx_oldipl = s; #ifdef DIAGNOSTIC ci->ci_mutex_level++; #endif WITNESS_LOCK(MUTEX_LOCK_OBJECT(mtx), LOP_EXCLUSIVE); return (1); } if (mtx->mtx_wantipl != IPL_NONE) splx(s); return (0); } #else void mtx_enter(struct mutex *mtx) { struct cpu_info *ci = curcpu(); /* Avoid deadlocks after panic or in DDB */ if (panicstr || db_active) return; WITNESS_CHECKORDER(MUTEX_LOCK_OBJECT(mtx), LOP_EXCLUSIVE | LOP_NEWORDER, NULL); #ifdef DIAGNOSTIC if (__predict_false(mtx->mtx_owner == ci)) panic("mtx %p: locking against myself", mtx); #endif if (mtx->mtx_wantipl != IPL_NONE) mtx->mtx_oldipl = splraise(mtx->mtx_wantipl); mtx->mtx_owner = ci; #ifdef DIAGNOSTIC ci->ci_mutex_level++; #endif WITNESS_LOCK(MUTEX_LOCK_OBJECT(mtx), LOP_EXCLUSIVE); } int mtx_enter_try(struct mutex *mtx) { mtx_enter(mtx); return (1); } #endif void mtx_leave(struct mutex *mtx) { int s; /* Avoid deadlocks after panic or in DDB */ if (panicstr || db_active) return; MUTEX_ASSERT_LOCKED(mtx); WITNESS_UNLOCK(MUTEX_LOCK_OBJECT(mtx), LOP_EXCLUSIVE); #ifdef DIAGNOSTIC curcpu()->ci_mutex_level--; #endif s = mtx->mtx_oldipl; #ifdef MULTIPROCESSOR membar_exit(); #endif mtx->mtx_owner = NULL; if (mtx->mtx_wantipl != IPL_NONE) splx(s); } #ifdef DDB void db_mtx_enter(struct db_mutex *mtx) { struct cpu_info *ci = curcpu(), *owner; unsigned long s; #ifdef DIAGNOSTIC if (__predict_false(mtx->mtx_owner == ci)) panic("%s: mtx %p: locking against myself", __func__, mtx); #endif s = intr_disable(); for (;;) { owner = atomic_cas_ptr(&mtx->mtx_owner, NULL, ci); if (owner == NULL) break; CPU_BUSY_CYCLE(); } membar_enter_after_atomic(); mtx->mtx_intr_state = s; #ifdef DIAGNOSTIC ci->ci_mutex_level++; #endif } void db_mtx_leave(struct db_mutex *mtx) { #ifdef DIAGNOSTIC struct cpu_info *ci = curcpu(); #endif unsigned long s; #ifdef DIAGNOSTIC if (__predict_false(mtx->mtx_owner != ci)) panic("%s: mtx %p: not owned by this CPU", __func__, mtx); ci->ci_mutex_level--; #endif s = mtx->mtx_intr_state; #ifdef MULTIPROCESSOR membar_exit(); #endif mtx->mtx_owner = NULL; intr_restore(s); } #endif /* DDB */ #endif /* __USE_MI_MUTEX */ #ifdef WITNESS void _mtx_init_flags(struct mutex *m, int ipl, const char *name, int flags, const struct lock_type *type) { struct lock_object *lo = MUTEX_LOCK_OBJECT(m); lo->lo_flags = MTX_LO_FLAGS(flags); if (name != NULL) lo->lo_name = name; else lo->lo_name = type->lt_name; WITNESS_INIT(lo, type); _mtx_init(m, ipl); } #endif /* WITNESS */
5610 8 750 34 729 128 714 4027 5178 2775 2775 2746 2578 2026 157 1886 2018 144 613 725 30 6 35 33 2 35 15 14 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 /* $OpenBSD: kern_subr.c,v 1.52 2023/01/31 15:18:56 deraadt Exp $ */ /* $NetBSD: kern_subr.c,v 1.15 1996/04/09 17:21:56 ragge Exp $ */ /* * Copyright (c) 1982, 1986, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/sched.h> #include <sys/malloc.h> #include <sys/queue.h> #include <uvm/uvm_extern.h> #ifdef PMAP_CHECK_COPYIN static inline int check_copyin(struct proc *, const void *, size_t); extern int _copyinstr(const void *, void *, size_t, size_t *); extern int _copyin(const void *uaddr, void *kaddr, size_t len); /* * If range overlaps an check_copyin region, return EFAULT */ static inline int check_copyin(struct proc *p, const void *vstart, size_t len) { struct vm_map *map = &p->p_vmspace->vm_map; const vaddr_t start = (vaddr_t)vstart; const vaddr_t end = start + len; int i, max; /* XXX if the array was sorted, we could shortcut */ max = map->check_copyin_count; membar_consumer(); for (i = 0; i < max; i++) { vaddr_t s = map->check_copyin[i].start; vaddr_t e = map->check_copyin[i].end; if ((start >= s && start < e) || (end > s && end < e)) return EFAULT; } return (0); } int copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done) { size_t alen; int error; /* * Must do the copyin checks after figuring out the string length, * the buffer size length may cross into another ELF segment */ error = _copyinstr(uaddr, kaddr, len, &alen); if (PMAP_CHECK_COPYIN && error == 0) error = check_copyin(curproc, uaddr, alen); if (done) *done = alen; return (error); } int copyin(const void *uaddr, void *kaddr, size_t len) { int error = 0; if (PMAP_CHECK_COPYIN) error = check_copyin(curproc, uaddr, len); if (error == 0) error = _copyin(uaddr, kaddr, len); return (error); } #endif /* PMAP_CHECK_COPYIN */ int uiomove(void *cp, size_t n, struct uio *uio) { struct iovec *iov; size_t cnt; int error = 0; #ifdef DIAGNOSTIC if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE) panic("uiomove: mode"); if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc) panic("uiomove: proc"); #endif if (n > uio->uio_resid) n = uio->uio_resid; while (n > 0) { iov = uio->uio_iov; cnt = iov->iov_len; if (cnt == 0) { KASSERT(uio->uio_iovcnt > 0); uio->uio_iov++; uio->uio_iovcnt--; continue; } if (cnt > n) cnt = n; switch (uio->uio_segflg) { case UIO_USERSPACE: sched_pause(preempt); if (uio->uio_rw == UIO_READ) error = copyout(cp, iov->iov_base, cnt); else error = copyin(iov->iov_base, cp, cnt); if (error) return (error); break; case UIO_SYSSPACE: if (uio->uio_rw == UIO_READ) error = kcopy(cp, iov->iov_base, cnt); else error = kcopy(iov->iov_base, cp, cnt); if (error) return(error); } iov->iov_base = (caddr_t)iov->iov_base + cnt; iov->iov_len -= cnt; uio->uio_resid -= cnt; uio->uio_offset += cnt; cp = (caddr_t)cp + cnt; n -= cnt; } return (error); } /* * Give next character to user as result of read. */ int ureadc(int c, struct uio *uio) { struct iovec *iov; if (uio->uio_resid == 0) #ifdef DIAGNOSTIC panic("ureadc: zero resid"); #else return (EINVAL); #endif again: if (uio->uio_iovcnt <= 0) #ifdef DIAGNOSTIC panic("ureadc: non-positive iovcnt"); #else return (EINVAL); #endif iov = uio->uio_iov; if (iov->iov_len <= 0) { uio->uio_iovcnt--; uio->uio_iov++; goto again; } switch (uio->uio_segflg) { case UIO_USERSPACE: { char tmp = c; if (copyout(&tmp, iov->iov_base, sizeof(char)) != 0) return (EFAULT); } break; case UIO_SYSSPACE: *(char *)iov->iov_base = c; break; } iov->iov_base = (caddr_t)iov->iov_base + 1; iov->iov_len--; uio->uio_resid--; uio->uio_offset++; return (0); } /* * General routine to allocate a hash table. */ void * hashinit(int elements, int type, int flags, u_long *hashmask) { u_long hashsize, i; LIST_HEAD(generic, generic) *hashtbl; if (elements <= 0) panic("hashinit: bad cnt"); if ((elements & (elements - 1)) == 0) hashsize = elements; else for (hashsize = 1; hashsize < elements; hashsize <<= 1) continue; hashtbl = mallocarray(hashsize, sizeof(*hashtbl), type, flags); if (hashtbl == NULL) return NULL; for (i = 0; i < hashsize; i++) LIST_INIT(&hashtbl[i]); *hashmask = hashsize - 1; return (hashtbl); } void hashfree(void *hash, int elements, int type) { u_long hashsize; LIST_HEAD(generic, generic) *hashtbl = hash; if (elements <= 0) panic("hashfree: bad cnt"); if ((elements & (elements - 1)) == 0) hashsize = elements; else for (hashsize = 1; hashsize < elements; hashsize <<= 1) continue; free(hashtbl, type, sizeof(*hashtbl) * hashsize); } /* * "startup hook" types, functions, and variables. */ struct hook_desc_head startuphook_list = TAILQ_HEAD_INITIALIZER(startuphook_list); void * hook_establish(struct hook_desc_head *head, int tail, void (*fn)(void *), void *arg) { struct hook_desc *hdp; hdp = malloc(sizeof(*hdp), M_DEVBUF, M_NOWAIT); if (hdp == NULL) return (NULL); hdp->hd_fn = fn; hdp->hd_arg = arg; if (tail) TAILQ_INSERT_TAIL(head, hdp, hd_list); else TAILQ_INSERT_HEAD(head, hdp, hd_list); return (hdp); } void hook_disestablish(struct hook_desc_head *head, void *vhook) { struct hook_desc *hdp; #ifdef DIAGNOSTIC for (hdp = TAILQ_FIRST(head); hdp != NULL; hdp = TAILQ_NEXT(hdp, hd_list)) if (hdp == vhook) break; if (hdp == NULL) return; #endif hdp = vhook; TAILQ_REMOVE(head, hdp, hd_list); free(hdp, M_DEVBUF, sizeof(*hdp)); } /* * Run hooks. Startup hooks are invoked right after scheduler_start but * before root is mounted. Shutdown hooks are invoked immediately before the * system is halted or rebooted, i.e. after file systems unmounted, * after crash dump done, etc. */ void dohooks(struct hook_desc_head *head, int flags) { struct hook_desc *hdp, *hdp_temp; if ((flags & HOOK_REMOVE) == 0) { TAILQ_FOREACH_SAFE(hdp, head, hd_list, hdp_temp) { (*hdp->hd_fn)(hdp->hd_arg); } } else { while ((hdp = TAILQ_FIRST(head)) != NULL) { TAILQ_REMOVE(head, hdp, hd_list); (*hdp->hd_fn)(hdp->hd_arg); if ((flags & HOOK_FREE) != 0) free(hdp, M_DEVBUF, sizeof(*hdp)); } } }
16 16 16 16 16 1 16 15 1 1 211 243 71 242 43 33 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 /* $OpenBSD: kern_task.c,v 1.35 2024/05/14 08:26:13 jsg Exp $ */ /* * Copyright (c) 2013 David Gwynne <dlg@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/mutex.h> #include <sys/kthread.h> #include <sys/task.h> #include <sys/proc.h> #include <sys/witness.h> #include "kcov.h" #if NKCOV > 0 #include <sys/kcov.h> #endif #ifdef WITNESS static struct lock_type taskq_lock_type = { .lt_name = "taskq" }; #define TASKQ_LOCK_FLAGS LO_WITNESS | LO_INITIALIZED | LO_SLEEPABLE | \ (LO_CLASS_RWLOCK << LO_CLASSSHIFT) #endif /* WITNESS */ struct taskq_thread { SLIST_ENTRY(taskq_thread) tt_entry; struct proc *tt_thread; }; SLIST_HEAD(taskq_threads, taskq_thread); struct taskq { enum { TQ_S_CREATED, TQ_S_RUNNING, TQ_S_DESTROYED } tq_state; unsigned int tq_running; unsigned int tq_nthreads; unsigned int tq_flags; const char *tq_name; struct mutex tq_mtx; struct task_list tq_worklist; struct taskq_threads tq_threads; unsigned int tq_barriers; unsigned int tq_bgen; unsigned int tq_bthreads; #ifdef WITNESS struct lock_object tq_lock_object; #endif }; static const char taskq_sys_name[] = "systq"; struct taskq taskq_sys = { .tq_state = TQ_S_CREATED, .tq_running = 0, .tq_nthreads = 1, .tq_flags = 0, .tq_name = taskq_sys_name, .tq_mtx = MUTEX_INITIALIZER_FLAGS(IPL_HIGH, taskq_sys_name, 0), .tq_worklist = TAILQ_HEAD_INITIALIZER(taskq_sys.tq_worklist), .tq_threads = SLIST_HEAD_INITIALIZER(taskq_sys.tq_threads), .tq_barriers = 0, .tq_bgen = 0, .tq_bthreads = 0, #ifdef WITNESS .tq_lock_object = { .lo_name = taskq_sys_name, .lo_flags = TASKQ_LOCK_FLAGS, }, #endif }; static const char taskq_sys_mp_name[] = "systqmp"; struct taskq taskq_sys_mp = { .tq_state = TQ_S_CREATED, .tq_running = 0, .tq_nthreads = 1, .tq_flags = TASKQ_MPSAFE, .tq_name = taskq_sys_mp_name, .tq_mtx = MUTEX_INITIALIZER_FLAGS(IPL_HIGH, taskq_sys_mp_name, 0), .tq_worklist = TAILQ_HEAD_INITIALIZER(taskq_sys_mp.tq_worklist), .tq_threads = SLIST_HEAD_INITIALIZER(taskq_sys_mp.tq_threads), .tq_barriers = 0, .tq_bgen = 0, .tq_bthreads = 0, #ifdef WITNESS .tq_lock_object = { .lo_name = taskq_sys_mp_name, .lo_flags = TASKQ_LOCK_FLAGS, }, #endif }; struct taskq *const systq = &taskq_sys; struct taskq *const systqmp = &taskq_sys_mp; void taskq_init(void); /* called in init_main.c */ void taskq_create_thread(void *); void taskq_barrier_task(void *); int taskq_next_work(struct taskq *, struct task *); void taskq_thread(void *); void taskq_init(void) { WITNESS_INIT(&systq->tq_lock_object, &taskq_lock_type); kthread_create_deferred(taskq_create_thread, systq); WITNESS_INIT(&systqmp->tq_lock_object, &taskq_lock_type); kthread_create_deferred(taskq_create_thread, systqmp); } struct taskq * taskq_create(const char *name, unsigned int nthreads, int ipl, unsigned int flags) { struct taskq *tq; tq = malloc(sizeof(*tq), M_DEVBUF, M_WAITOK); if (tq == NULL) return (NULL); tq->tq_state = TQ_S_CREATED; tq->tq_running = 0; tq->tq_nthreads = nthreads; tq->tq_name = name; tq->tq_flags = flags; mtx_init_flags(&tq->tq_mtx, ipl, name, 0); TAILQ_INIT(&tq->tq_worklist); SLIST_INIT(&tq->tq_threads); tq->tq_barriers = 0; tq->tq_bgen = 0; tq->tq_bthreads = 0; #ifdef WITNESS memset(&tq->tq_lock_object, 0, sizeof(tq->tq_lock_object)); tq->tq_lock_object.lo_name = name; tq->tq_lock_object.lo_flags = TASKQ_LOCK_FLAGS; witness_init(&tq->tq_lock_object, &taskq_lock_type); #endif /* try to create a thread to guarantee that tasks will be serviced */ kthread_create_deferred(taskq_create_thread, tq); return (tq); } void taskq_destroy(struct taskq *tq) { mtx_enter(&tq->tq_mtx); switch (tq->tq_state) { case TQ_S_CREATED: /* tq is still referenced by taskq_create_thread */ tq->tq_state = TQ_S_DESTROYED; mtx_leave(&tq->tq_mtx); return; case TQ_S_RUNNING: tq->tq_state = TQ_S_DESTROYED; break; default: panic("unexpected %s tq state %u", tq->tq_name, tq->tq_state); } while (tq->tq_running > 0) { wakeup(tq); msleep_nsec(&tq->tq_running, &tq->tq_mtx, PWAIT, "tqdestroy", INFSLP); } mtx_leave(&tq->tq_mtx); free(tq, M_DEVBUF, sizeof(*tq)); } void taskq_create_thread(void *arg) { struct taskq *tq = arg; int rv; mtx_enter(&tq->tq_mtx); switch (tq->tq_state) { case TQ_S_DESTROYED: mtx_leave(&tq->tq_mtx); free(tq, M_DEVBUF, sizeof(*tq)); return; case TQ_S_CREATED: tq->tq_state = TQ_S_RUNNING; break; default: panic("unexpected %s tq state %d", tq->tq_name, tq->tq_state); } do { tq->tq_running++; mtx_leave(&tq->tq_mtx); rv = kthread_create(taskq_thread, tq, NULL, tq->tq_name); mtx_enter(&tq->tq_mtx); if (rv != 0) { printf("unable to create thread for \"%s\" taskq\n", tq->tq_name); tq->tq_running--; /* could have been destroyed during kthread_create */ if (tq->tq_state == TQ_S_DESTROYED && tq->tq_running == 0) wakeup_one(&tq->tq_running); break; } } while (tq->tq_running < tq->tq_nthreads); mtx_leave(&tq->tq_mtx); } void taskq_barrier_task(void *p) { struct taskq *tq = p; unsigned int gen; mtx_enter(&tq->tq_mtx); tq->tq_bthreads++; wakeup(&tq->tq_bthreads); gen = tq->tq_bgen; do { msleep_nsec(&tq->tq_bgen, &tq->tq_mtx, PWAIT, "tqbarend", INFSLP); } while (gen == tq->tq_bgen); mtx_leave(&tq->tq_mtx); } static void taskq_do_barrier(struct taskq *tq) { struct task t = TASK_INITIALIZER(taskq_barrier_task, tq); struct proc *thread = curproc; struct taskq_thread *tt; mtx_enter(&tq->tq_mtx); tq->tq_barriers++; /* is the barrier being run from a task inside the taskq? */ SLIST_FOREACH(tt, &tq->tq_threads, tt_entry) { if (tt->tt_thread == thread) { tq->tq_bthreads++; wakeup(&tq->tq_bthreads); break; } } while (tq->tq_bthreads < tq->tq_nthreads) { /* shove the task into the queue for a worker to pick up */ SET(t.t_flags, TASK_ONQUEUE); TAILQ_INSERT_TAIL(&tq->tq_worklist, &t, t_entry); wakeup_one(tq); msleep_nsec(&tq->tq_bthreads, &tq->tq_mtx, PWAIT, "tqbar", INFSLP); /* * another thread running a barrier might have * done this work for us. */ if (ISSET(t.t_flags, TASK_ONQUEUE)) TAILQ_REMOVE(&tq->tq_worklist, &t, t_entry); } if (--tq->tq_barriers == 0) { /* we're the last one out */ tq->tq_bgen++; wakeup(&tq->tq_bgen); tq->tq_bthreads = 0; } else { unsigned int gen = tq->tq_bgen; do { msleep_nsec(&tq->tq_bgen, &tq->tq_mtx, PWAIT, "tqbarwait", INFSLP); } while (gen == tq->tq_bgen); } mtx_leave(&tq->tq_mtx); } void taskq_barrier(struct taskq *tq) { WITNESS_CHECKORDER(&tq->tq_lock_object, LOP_NEWORDER, NULL); taskq_do_barrier(tq); } void taskq_del_barrier(struct taskq *tq, struct task *t) { WITNESS_CHECKORDER(&tq->tq_lock_object, LOP_NEWORDER, NULL); if (task_del(tq, t)) return; taskq_do_barrier(tq); } void task_set(struct task *t, void (*fn)(void *), void *arg) { t->t_func = fn; t->t_arg = arg; t->t_flags = 0; } int task_add(struct taskq *tq, struct task *w) { int rv = 0; if (ISSET(w->t_flags, TASK_ONQUEUE)) return (0); mtx_enter(&tq->tq_mtx); if (!ISSET(w->t_flags, TASK_ONQUEUE)) { rv = 1; SET(w->t_flags, TASK_ONQUEUE); TAILQ_INSERT_TAIL(&tq->tq_worklist, w, t_entry); #if NKCOV > 0 if (!kcov_cold) w->t_process = curproc->p_p; #endif } mtx_leave(&tq->tq_mtx); if (rv) wakeup_one(tq); return (rv); } int task_del(struct taskq *tq, struct task *w) { int rv = 0; if (!ISSET(w->t_flags, TASK_ONQUEUE)) return (0); mtx_enter(&tq->tq_mtx); if (ISSET(w->t_flags, TASK_ONQUEUE)) { rv = 1; CLR(w->t_flags, TASK_ONQUEUE); TAILQ_REMOVE(&tq->tq_worklist, w, t_entry); } mtx_leave(&tq->tq_mtx); return (rv); } int taskq_next_work(struct taskq *tq, struct task *work) { struct task *next; mtx_enter(&tq->tq_mtx); while ((next = TAILQ_FIRST(&tq->tq_worklist)) == NULL) { if (tq->tq_state != TQ_S_RUNNING) { mtx_leave(&tq->tq_mtx); return (0); } msleep_nsec(tq, &tq->tq_mtx, PWAIT, "bored", INFSLP); } TAILQ_REMOVE(&tq->tq_worklist, next, t_entry); CLR(next->t_flags, TASK_ONQUEUE); *work = *next; /* copy to caller to avoid races */ next = TAILQ_FIRST(&tq->tq_worklist); mtx_leave(&tq->tq_mtx); if (next != NULL && tq->tq_nthreads > 1) wakeup_one(tq); return (1); } void taskq_thread(void *xtq) { struct taskq_thread self = { .tt_thread = curproc }; struct taskq *tq = xtq; struct task work; int last; if (ISSET(tq->tq_flags, TASKQ_MPSAFE)) KERNEL_UNLOCK(); mtx_enter(&tq->tq_mtx); SLIST_INSERT_HEAD(&tq->tq_threads, &self, tt_entry); mtx_leave(&tq->tq_mtx); WITNESS_CHECKORDER(&tq->tq_lock_object, LOP_NEWORDER, NULL); while (taskq_next_work(tq, &work)) { WITNESS_LOCK(&tq->tq_lock_object, 0); #if NKCOV > 0 kcov_remote_enter(KCOV_REMOTE_COMMON, work.t_process); #endif (*work.t_func)(work.t_arg); #if NKCOV > 0 kcov_remote_leave(KCOV_REMOTE_COMMON, work.t_process); #endif WITNESS_UNLOCK(&tq->tq_lock_object, 0); sched_pause(yield); } mtx_enter(&tq->tq_mtx); SLIST_REMOVE(&tq->tq_threads, &self, taskq_thread, tt_entry); last = (--tq->tq_running == 0); mtx_leave(&tq->tq_mtx); if (ISSET(tq->tq_flags, TASKQ_MPSAFE)) KERNEL_LOCK(); if (last) wakeup_one(&tq->tq_running); kthread_exit(0); }
open /syzkaller/managers/main/kernel/machine/atomic.h: no such file or directory
8 1 6 3 6 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 /* $OpenBSD: nfs_syscalls.c,v 1.126 2024/05/01 13:15:59 jsg Exp $ */ /* $NetBSD: nfs_syscalls.c,v 1.19 1996/02/18 11:53:52 fvdl Exp $ */ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Rick Macklem at The University of Guelph. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)nfs_syscalls.c 8.5 (Berkeley) 3/30/95 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/file.h> #include <sys/vnode.h> #include <sys/mount.h> #include <sys/pool.h> #include <sys/malloc.h> #include <sys/buf.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/domain.h> #include <sys/protosw.h> #include <sys/filedesc.h> #include <sys/signalvar.h> #include <sys/kthread.h> #include <sys/queue.h> #include <sys/syscallargs.h> #include <netinet/in.h> #include <netinet/tcp.h> #include <nfs/nfsproto.h> #include <nfs/nfs.h> #include <nfs/nfsrvcache.h> #include <nfs/nfsnode.h> #include <nfs/nfs_var.h> /* Global defs. */ extern int nfs_numasync; extern struct nfsstats nfsstats; struct nfssvc_sock *nfs_udpsock; int nfsd_waiting = 0; #ifdef NFSSERVER struct pool nfsrv_descript_pl; int nfsrv_getslp(struct nfsd *nfsd); static int nfs_numnfsd = 0; static int (*const nfsrv3_procs[NFS_NPROCS])(struct nfsrv_descript *, struct nfssvc_sock *, struct proc *, struct mbuf **) = { nfsrv_null, nfsrv_getattr, nfsrv_setattr, nfsrv_lookup, nfsrv3_access, nfsrv_readlink, nfsrv_read, nfsrv_write, nfsrv_create, nfsrv_mkdir, nfsrv_symlink, nfsrv_mknod, nfsrv_remove, nfsrv_rmdir, nfsrv_rename, nfsrv_link, nfsrv_readdir, nfsrv_readdirplus, nfsrv_statfs, nfsrv_fsinfo, nfsrv_pathconf, nfsrv_commit, nfsrv_noop }; #endif TAILQ_HEAD(, nfssvc_sock) nfssvc_sockhead; struct nfsdhead nfsd_head; int nfssvc_sockhead_flag; #define SLP_INIT 0x01 /* NFS data undergoing initialization */ #define SLP_WANTINIT 0x02 /* thread waiting on NFS initialization */ int nfsd_head_flag; #ifdef NFSCLIENT struct proc *nfs_asyncdaemon[NFS_MAXASYNCDAEMON]; int nfs_niothreads = -1; #endif int nfssvc_addsock(struct file *, struct mbuf *); int nfssvc_nfsd(struct nfsd *); void nfsrv_slpderef(struct nfssvc_sock *); void nfsrv_zapsock(struct nfssvc_sock *); void nfssvc_iod(void *); /* * NFS server pseudo system call for the nfsd's * Based on the flag value it either: * - adds a socket to the selection list * - remains in the kernel as an nfsd */ int sys_nfssvc(struct proc *p, void *v, register_t *retval) { int error = 0; #ifdef NFSSERVER struct sys_nfssvc_args /* { syscallarg(int) flag; syscallarg(caddr_t) argp; } */ *uap = v; int flags = SCARG(uap, flag); struct file *fp; struct mbuf *nam; struct nfsd_args nfsdarg; struct nfsd_srvargs nfsd_srvargs, *nsd = &nfsd_srvargs; struct nfsd *nfsd; #endif /* Must be super user */ error = suser(p); if (error) return (error); #ifndef NFSSERVER error = ENOSYS; #else while (nfssvc_sockhead_flag & SLP_INIT) { nfssvc_sockhead_flag |= SLP_WANTINIT; tsleep_nsec(&nfssvc_sockhead, PSOCK, "nfsd init", INFSLP); } switch (flags) { case NFSSVC_ADDSOCK: error = copyin(SCARG(uap, argp), &nfsdarg, sizeof(nfsdarg)); if (error) return (error); error = getsock(p, nfsdarg.sock, &fp); if (error) return (error); /* * Get the client address for connected sockets. */ if (nfsdarg.name == NULL || nfsdarg.namelen == 0) nam = NULL; else { error = sockargs(&nam, nfsdarg.name, nfsdarg.namelen, MT_SONAME); if (error) { FRELE(fp, p); return (error); } } error = nfssvc_addsock(fp, nam); FRELE(fp, p); break; case NFSSVC_NFSD: error = copyin(SCARG(uap, argp), nsd, sizeof(*nsd)); if (error) return (error); nfsd = malloc(sizeof(*nfsd), M_NFSD, M_WAITOK|M_ZERO); nfsd->nfsd_procp = p; nfsd->nfsd_slp = NULL; error = nfssvc_nfsd(nfsd); break; default: error = EINVAL; break; } if (error == EINTR || error == ERESTART) error = 0; #endif /* !NFSSERVER */ return (error); } #ifdef NFSSERVER /* * Adds a socket to the list for servicing by nfsds. */ int nfssvc_addsock(struct file *fp, struct mbuf *mynam) { struct mbuf *m; int siz; struct nfssvc_sock *slp; struct socket *so; struct nfssvc_sock *tslp; int error; so = (struct socket *)fp->f_data; tslp = NULL; /* * Add it to the list, as required. */ if (so->so_proto->pr_protocol == IPPROTO_UDP) { tslp = nfs_udpsock; if (tslp->ns_flag & SLP_VALID) { m_freem(mynam); return (EPERM); } } /* * Allow only IPv4 UDP and TCP sockets. */ if ((so->so_type != SOCK_STREAM && so->so_type != SOCK_DGRAM) || so->so_proto->pr_domain->dom_family != AF_INET) { m_freem(mynam); return (EINVAL); } if (so->so_type == SOCK_STREAM) siz = NFS_MAXPACKET + sizeof (u_long); else siz = NFS_MAXPACKET; solock(so); error = soreserve(so, siz, siz); sounlock(so); if (error) { m_freem(mynam); return (error); } /* * Set protocol specific options { for now TCP only } and * reserve some space. For datagram sockets, this can get called * repeatedly for the same socket, but that isn't harmful. */ if (so->so_type == SOCK_STREAM) { MGET(m, M_WAIT, MT_SOOPTS); *mtod(m, int32_t *) = 1; m->m_len = sizeof(int32_t); sosetopt(so, SOL_SOCKET, SO_KEEPALIVE, m); m_freem(m); } if (so->so_proto->pr_domain->dom_family == AF_INET && so->so_proto->pr_protocol == IPPROTO_TCP) { MGET(m, M_WAIT, MT_SOOPTS); *mtod(m, int32_t *) = 1; m->m_len = sizeof(int32_t); sosetopt(so, IPPROTO_TCP, TCP_NODELAY, m); m_freem(m); } solock(so); mtx_enter(&so->so_rcv.sb_mtx); so->so_rcv.sb_flags &= ~SB_NOINTR; so->so_rcv.sb_timeo_nsecs = INFSLP; mtx_leave(&so->so_rcv.sb_mtx); mtx_enter(&so->so_snd.sb_mtx); so->so_snd.sb_flags &= ~SB_NOINTR; so->so_snd.sb_timeo_nsecs = INFSLP; mtx_leave(&so->so_snd.sb_mtx); sounlock(so); if (tslp) slp = tslp; else { slp = malloc(sizeof(*slp), M_NFSSVC, M_WAITOK|M_ZERO); TAILQ_INSERT_TAIL(&nfssvc_sockhead, slp, ns_chain); } slp->ns_so = so; slp->ns_nam = mynam; FREF(fp); slp->ns_fp = fp; so->so_upcallarg = (caddr_t)slp; so->so_upcall = nfsrv_rcv; slp->ns_flag = (SLP_VALID | SLP_NEEDQ); nfsrv_wakenfsd(slp); return (0); } static inline int nfssvc_checknam(struct mbuf *nam) { struct sockaddr_in *sin; if (nam == NULL || in_nam2sin(nam, &sin) != 0 || ntohs(sin->sin_port) >= IPPORT_RESERVED) { return -1; } return 0; } /* * Called by nfssvc() for nfsds. Just loops around servicing rpc requests * until it is killed by a signal. */ int nfssvc_nfsd(struct nfsd *nfsd) { struct mbuf *m; int siz; struct nfssvc_sock *slp; struct socket *so; int *solockp; struct nfsrv_descript *nd = NULL; struct mbuf *mreq; int error = 0, cacherep, sotype; cacherep = RC_DOIT; TAILQ_INSERT_TAIL(&nfsd_head, nfsd, nfsd_chain); nfs_numnfsd++; /* Loop getting rpc requests until SIGKILL. */ loop: if (!ISSET(nfsd->nfsd_flag, NFSD_REQINPROG)) { /* attach an nfssvc_sock to nfsd */ error = nfsrv_getslp(nfsd); if (error) goto done; slp = nfsd->nfsd_slp; if (ISSET(slp->ns_flag, SLP_VALID)) { if ((slp->ns_flag & (SLP_DISCONN | SLP_NEEDQ)) == SLP_NEEDQ) { CLR(slp->ns_flag, SLP_NEEDQ); nfs_sndlock(&slp->ns_solock, NULL); nfsrv_rcv(slp->ns_so, (caddr_t)slp, M_WAIT); nfs_sndunlock(&slp->ns_solock); } if (ISSET(slp->ns_flag, SLP_DISCONN)) nfsrv_zapsock(slp); error = nfsrv_dorec(slp, nfsd, &nd); SET(nfsd->nfsd_flag, NFSD_REQINPROG); } } else { error = 0; slp = nfsd->nfsd_slp; } if (error || !ISSET(slp->ns_flag, SLP_VALID)) { if (nd != NULL) { pool_put(&nfsrv_descript_pl, nd); nd = NULL; } nfsd->nfsd_slp = NULL; CLR(nfsd->nfsd_flag, NFSD_REQINPROG); nfsrv_slpderef(slp); goto loop; } so = slp->ns_so; sotype = so->so_type; if (ISSET(so->so_proto->pr_flags, PR_CONNREQUIRED)) solockp = &slp->ns_solock; else solockp = NULL; if (nd) { if (nd->nd_nam2) nd->nd_nam = nd->nd_nam2; else nd->nd_nam = slp->ns_nam; } cacherep = nfsrv_getcache(nd, slp, &mreq); switch (cacherep) { case RC_DOIT: /* * Unless this is a null request (server ping), make * sure that the client is using a reserved source port. */ if (nd->nd_procnum != 0 && nfssvc_checknam(nd->nd_nam) == -1) { /* drop it */ m_freem(nd->nd_mrep); m_freem(nd->nd_nam2); break; } error = (*(nfsrv3_procs[nd->nd_procnum]))(nd, slp, nfsd->nfsd_procp, &mreq); if (mreq == NULL) { if (nd != NULL) { m_freem(nd->nd_nam2); m_freem(nd->nd_mrep); } break; } if (error) { nfsstats.srv_errs++; nfsrv_updatecache(nd, 0, mreq); m_freem(nd->nd_nam2); break; } nfsstats.srvrpccnt[nd->nd_procnum]++; nfsrv_updatecache(nd, 1, mreq); nd->nd_mrep = NULL; /* FALLTHROUGH */ case RC_REPLY: m = mreq; siz = 0; while (m) { siz += m->m_len; m = m->m_next; } if (siz <= 0 || siz > NFS_MAXPACKET) panic("bad nfs svc reply, siz = %i", siz); m = mreq; m->m_pkthdr.len = siz; m->m_pkthdr.ph_ifidx = 0; /* For stream protocols, prepend a Sun RPC Record Mark. */ if (sotype == SOCK_STREAM) { M_PREPEND(m, NFSX_UNSIGNED, M_WAIT); *mtod(m, u_int32_t *) = htonl(0x80000000 | siz); } if (solockp) nfs_sndlock(solockp, NULL); if (ISSET(slp->ns_flag, SLP_VALID)) error = nfs_send(so, nd->nd_nam2, m, NULL); else { error = EPIPE; m_freem(m); } m_freem(nd->nd_nam2); m_freem(nd->nd_mrep); if (error == EPIPE) nfsrv_zapsock(slp); if (solockp) nfs_sndunlock(solockp); if (error == EINTR || error == ERESTART) { pool_put(&nfsrv_descript_pl, nd); nfsrv_slpderef(slp); goto done; } break; case RC_DROPIT: m_freem(nd->nd_mrep); m_freem(nd->nd_nam2); break; }; if (nd) { pool_put(&nfsrv_descript_pl, nd); nd = NULL; } if (nfsrv_dorec(slp, nfsd, &nd)) { nfsd->nfsd_flag &= ~NFSD_REQINPROG; nfsd->nfsd_slp = NULL; nfsrv_slpderef(slp); } goto loop; done: TAILQ_REMOVE(&nfsd_head, nfsd, nfsd_chain); free(nfsd, M_NFSD, sizeof(*nfsd)); if (--nfs_numnfsd == 0) nfsrv_init(1); /* Reinitialize everything */ return (error); } /* * Shut down a socket associated with an nfssvc_sock structure. * Should be called with the send lock set, if required. * The trick here is to increment the sref at the start, so that the nfsds * will stop using it and clear ns_flag at the end so that it will not be * reassigned during cleanup. */ void nfsrv_zapsock(struct nfssvc_sock *slp) { struct socket *so; struct file *fp; struct mbuf *m, *n; slp->ns_flag &= ~SLP_ALLFLAGS; fp = slp->ns_fp; if (fp) { FREF(fp); slp->ns_fp = NULL; so = slp->ns_so; so->so_upcall = NULL; soshutdown(so, SHUT_RDWR); closef(fp, NULL); if (slp->ns_nam) m = m_free(slp->ns_nam); m_freem(slp->ns_raw); m = slp->ns_rec; while (m) { n = m->m_nextpkt; m_freem(m); m = n; } } } /* * Dereference a server socket structure. If it has no more references and * is no longer valid, you can throw it away. */ void nfsrv_slpderef(struct nfssvc_sock *slp) { if (--(slp->ns_sref) == 0 && (slp->ns_flag & SLP_VALID) == 0) { TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain); free(slp, M_NFSSVC, sizeof(*slp)); } } /* * Initialize the data structures for the server. * Handshake with any new nfsds starting up to avoid any chance of * corruption. */ void nfsrv_init(int terminating) { struct nfssvc_sock *slp, *nslp; if (nfssvc_sockhead_flag & SLP_INIT) panic("nfsd init"); nfssvc_sockhead_flag |= SLP_INIT; if (terminating) { for (slp = TAILQ_FIRST(&nfssvc_sockhead); slp != NULL; slp = nslp) { nslp = TAILQ_NEXT(slp, ns_chain); if (slp->ns_flag & SLP_VALID) nfsrv_zapsock(slp); TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain); free(slp, M_NFSSVC, sizeof(*slp)); } nfsrv_cleancache(); /* And clear out server cache */ } TAILQ_INIT(&nfssvc_sockhead); nfssvc_sockhead_flag &= ~SLP_INIT; if (nfssvc_sockhead_flag & SLP_WANTINIT) { nfssvc_sockhead_flag &= ~SLP_WANTINIT; wakeup((caddr_t)&nfssvc_sockhead); } TAILQ_INIT(&nfsd_head); nfsd_head_flag &= ~NFSD_CHECKSLP; nfs_udpsock = malloc(sizeof(*nfs_udpsock), M_NFSSVC, M_WAITOK|M_ZERO); TAILQ_INSERT_HEAD(&nfssvc_sockhead, nfs_udpsock, ns_chain); if (!terminating) { pool_init(&nfsrv_descript_pl, sizeof(struct nfsrv_descript), 0, IPL_NONE, PR_WAITOK, "ndscpl", NULL); } } #endif /* NFSSERVER */ #ifdef NFSCLIENT /* * Asynchronous I/O threads for client nfs. * They do read-ahead and write-behind operations on the block I/O cache. * Never returns unless it fails or gets killed. */ void nfssvc_iod(void *arg) { struct proc *p = curproc; struct buf *bp, *nbp; int i, myiod; struct vnode *vp; int error = 0, s, bufcount; bufcount = MIN(256, bcstats.kvaslots / 8); bufcount = MIN(bufcount, bcstats.numbufs / 8); /* Assign my position or return error if too many already running. */ myiod = -1; for (i = 0; i < NFS_MAXASYNCDAEMON; i++) { if (nfs_asyncdaemon[i] == NULL) { myiod = i; break; } } if (myiod == -1) kthread_exit(EBUSY); nfs_asyncdaemon[myiod] = p; nfs_numasync++; /* Upper limit on how many bufs we'll queue up for this iod. */ if (nfs_bufqmax > bcstats.kvaslots / 4) { nfs_bufqmax = bcstats.kvaslots / 4; bufcount = 0; } if (nfs_bufqmax > bcstats.numbufs / 4) { nfs_bufqmax = bcstats.numbufs / 4; bufcount = 0; } nfs_bufqmax += bufcount; wakeup(&nfs_bufqlen); /* wake up anyone waiting for room to enqueue IO */ /* Just loop around doin our stuff until SIGKILL. */ for (;;) { while (TAILQ_FIRST(&nfs_bufq) == NULL && error == 0) { error = tsleep_nsec(&nfs_bufq, PWAIT | PCATCH, "nfsidl", INFSLP); } while ((bp = TAILQ_FIRST(&nfs_bufq)) != NULL) { /* Take one off the front of the list */ TAILQ_REMOVE(&nfs_bufq, bp, b_freelist); nfs_bufqlen--; wakeup_one(&nfs_bufqlen); if (bp->b_flags & B_READ) (void) nfs_doio(bp, NULL); else do { /* * Look for a delayed write for the same vnode, so I can do * it now. We must grab it before calling nfs_doio() to * avoid any risk of the vnode getting vclean()'d while * we are doing the write rpc. */ vp = bp->b_vp; s = splbio(); LIST_FOREACH(nbp, &vp->v_dirtyblkhd, b_vnbufs) { if ((nbp->b_flags & (B_BUSY|B_DELWRI|B_NEEDCOMMIT|B_NOCACHE))!=B_DELWRI) continue; nbp->b_flags |= B_ASYNC; bremfree(nbp); buf_acquire(nbp); break; } /* * For the delayed write, do the first part of nfs_bwrite() * up to, but not including nfs_strategy(). */ if (nbp) { nbp->b_flags &= ~(B_READ|B_DONE|B_ERROR); buf_undirty(nbp); nbp->b_vp->v_numoutput++; } splx(s); (void) nfs_doio(bp, NULL); } while ((bp = nbp) != NULL); } if (error) { nfs_asyncdaemon[myiod] = NULL; nfs_numasync--; nfs_bufqmax -= bufcount; kthread_exit(error); } } } void nfs_getset_niothreads(int set) { int i, have, start; for (have = 0, i = 0; i < NFS_MAXASYNCDAEMON; i++) if (nfs_asyncdaemon[i] != NULL) have++; if (set) { /* clamp to sane range */ nfs_niothreads = max(0, min(nfs_niothreads, NFS_MAXASYNCDAEMON)); start = nfs_niothreads - have; while (start > 0) { kthread_create(nfssvc_iod, NULL, NULL, "nfsio"); start--; } for (i = 0; (start < 0) && (i < NFS_MAXASYNCDAEMON); i++) if (nfs_asyncdaemon[i] != NULL) { psignal(nfs_asyncdaemon[i], SIGKILL); start++; } } else { if (nfs_niothreads >= 0) nfs_niothreads = have; } } #endif /* NFSCLIENT */ #ifdef NFSSERVER /* * Find an nfssrv_sock for nfsd, sleeping if needed. */ int nfsrv_getslp(struct nfsd *nfsd) { struct nfssvc_sock *slp; int error; again: while (nfsd->nfsd_slp == NULL && (nfsd_head_flag & NFSD_CHECKSLP) == 0) { nfsd->nfsd_flag |= NFSD_WAITING; nfsd_waiting++; error = tsleep_nsec(nfsd, PSOCK | PCATCH, "nfsd", INFSLP); nfsd_waiting--; if (error) return (error); } if (nfsd->nfsd_slp == NULL && (nfsd_head_flag & NFSD_CHECKSLP) != 0) { TAILQ_FOREACH(slp, &nfssvc_sockhead, ns_chain) { if ((slp->ns_flag & (SLP_VALID | SLP_DOREC)) == (SLP_VALID | SLP_DOREC)) { slp->ns_flag &= ~SLP_DOREC; slp->ns_sref++; nfsd->nfsd_slp = slp; break; } } if (slp == NULL) nfsd_head_flag &= ~NFSD_CHECKSLP; } if (nfsd->nfsd_slp == NULL) goto again; return (0); } #endif /* NFSSERVER */
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 #ifndef __DRM_VMA_MANAGER_H__ #define __DRM_VMA_MANAGER_H__ /* * Copyright (c) 2013 David Herrmann <dh.herrmann@gmail.com> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #include <drm/drm_mm.h> #include <linux/mm.h> #include <linux/rbtree.h> #include <linux/spinlock.h> #include <linux/types.h> /* We make up offsets for buffer objects so we can recognize them at * mmap time. pgoff in mmap is an unsigned long, so we need to make sure * that the faked up offset will fit */ #if BITS_PER_LONG == 64 #define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFFUL >> PAGE_SHIFT) + 1) #define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFFUL >> PAGE_SHIFT) * 256) #else #define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFUL >> PAGE_SHIFT) + 1) #define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFUL >> PAGE_SHIFT) * 16) #endif struct drm_file; struct drm_vma_offset_file { struct rb_node vm_rb; struct drm_file *vm_tag; unsigned long vm_count; }; struct drm_vma_offset_node { struct mutex vm_lock; struct drm_mm_node vm_node; struct rb_root vm_files; void *driver_private; }; struct drm_vma_offset_manager { struct mutex vm_lock; struct drm_mm vm_addr_space_mm; }; void drm_vma_offset_manager_init(struct drm_vma_offset_manager *mgr, unsigned long page_offset, unsigned long size); void drm_vma_offset_manager_destroy(struct drm_vma_offset_manager *mgr); struct drm_vma_offset_node *drm_vma_offset_lookup_locked(struct drm_vma_offset_manager *mgr, unsigned long start, unsigned long pages); int drm_vma_offset_add(struct drm_vma_offset_manager *mgr, struct drm_vma_offset_node *node, unsigned long pages); void drm_vma_offset_remove(struct drm_vma_offset_manager *mgr, struct drm_vma_offset_node *node); int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag); int drm_vma_node_allow_once(struct drm_vma_offset_node *node, struct drm_file *tag); void drm_vma_node_revoke(struct drm_vma_offset_node *node, struct drm_file *tag); bool drm_vma_node_is_allowed(struct drm_vma_offset_node *node, struct drm_file *tag); /** * drm_vma_offset_exact_lookup_locked() - Look up node by exact address * @mgr: Manager object * @start: Start address (page-based, not byte-based) * @pages: Size of object (page-based) * * Same as drm_vma_offset_lookup_locked() but does not allow any offset into the node. * It only returns the exact object with the given start address. * * RETURNS: * Node at exact start address @start. */ static inline struct drm_vma_offset_node * drm_vma_offset_exact_lookup_locked(struct drm_vma_offset_manager *mgr, unsigned long start, unsigned long pages) { struct drm_vma_offset_node *node; node = drm_vma_offset_lookup_locked(mgr, start, pages); return (node && node->vm_node.start == start) ? node : NULL; } /** * drm_vma_offset_lock_lookup() - Lock lookup for extended private use * @mgr: Manager object * * Lock VMA manager for extended lookups. Only locked VMA function calls * are allowed while holding this lock. All other contexts are blocked from VMA * until the lock is released via drm_vma_offset_unlock_lookup(). * * Use this if you need to take a reference to the objects returned by * drm_vma_offset_lookup_locked() before releasing this lock again. * * This lock must not be used for anything else than extended lookups. You must * not call any other VMA helpers while holding this lock. * * Note: You're in atomic-context while holding this lock! */ static inline void drm_vma_offset_lock_lookup(struct drm_vma_offset_manager *mgr) { read_lock(&mgr->vm_lock); } /** * drm_vma_offset_unlock_lookup() - Unlock lookup for extended private use * @mgr: Manager object * * Release lookup-lock. See drm_vma_offset_lock_lookup() for more information. */ static inline void drm_vma_offset_unlock_lookup(struct drm_vma_offset_manager *mgr) { read_unlock(&mgr->vm_lock); } /** * drm_vma_node_reset() - Initialize or reset node object * @node: Node to initialize or reset * * Reset a node to its initial state. This must be called before using it with * any VMA offset manager. * * This must not be called on an already allocated node, or you will leak * memory. */ static inline void drm_vma_node_reset(struct drm_vma_offset_node *node) { memset(node, 0, sizeof(*node)); node->vm_files = RB_ROOT; mtx_init(&node->vm_lock, IPL_NONE); } /** * drm_vma_node_start() - Return start address for page-based addressing * @node: Node to inspect * * Return the start address of the given node. This can be used as offset into * the linear VM space that is provided by the VMA offset manager. Note that * this can only be used for page-based addressing. If you need a proper offset * for user-space mappings, you must apply "<< PAGE_SHIFT" or use the * drm_vma_node_offset_addr() helper instead. * * RETURNS: * Start address of @node for page-based addressing. 0 if the node does not * have an offset allocated. */ static inline unsigned long drm_vma_node_start(const struct drm_vma_offset_node *node) { return node->vm_node.start; } /** * drm_vma_node_size() - Return size (page-based) * @node: Node to inspect * * Return the size as number of pages for the given node. This is the same size * that was passed to drm_vma_offset_add(). If no offset is allocated for the * node, this is 0. * * RETURNS: * Size of @node as number of pages. 0 if the node does not have an offset * allocated. */ static inline unsigned long drm_vma_node_size(struct drm_vma_offset_node *node) { return node->vm_node.size; } /** * drm_vma_node_offset_addr() - Return sanitized offset for user-space mmaps * @node: Linked offset node * * Same as drm_vma_node_start() but returns the address as a valid offset that * can be used for user-space mappings during mmap(). * This must not be called on unlinked nodes. * * RETURNS: * Offset of @node for byte-based addressing. 0 if the node does not have an * object allocated. */ static inline __u64 drm_vma_node_offset_addr(struct drm_vma_offset_node *node) { return ((__u64)node->vm_node.start) << PAGE_SHIFT; } /** * drm_vma_node_unmap() - Unmap offset node * @node: Offset node * @file_mapping: Address space to unmap @node from * * Unmap all userspace mappings for a given offset node. The mappings must be * associated with the @file_mapping address-space. If no offset exists * nothing is done. * * This call is unlocked. The caller must guarantee that drm_vma_offset_remove() * is not called on this node concurrently. */ #ifdef __linux__ static inline void drm_vma_node_unmap(struct drm_vma_offset_node *node, struct address_space *file_mapping) { if (drm_mm_node_allocated(&node->vm_node)) unmap_mapping_range(file_mapping, drm_vma_node_offset_addr(node), drm_vma_node_size(node) << PAGE_SHIFT, 1); } #endif /** * drm_vma_node_verify_access() - Access verification helper for TTM * @node: Offset node * @tag: Tag of file to check * * This checks whether @tag is granted access to @node. It is the same as * drm_vma_node_is_allowed() but suitable as drop-in helper for TTM * verify_access() callbacks. * * RETURNS: * 0 if access is granted, -EACCES otherwise. */ static inline int drm_vma_node_verify_access(struct drm_vma_offset_node *node, struct drm_file *tag) { return drm_vma_node_is_allowed(node, tag) ? 0 : -EACCES; } #endif /* __DRM_VMA_MANAGER_H__ */
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 /* $OpenBSD: percpu.h,v 1.9 2023/09/16 09:33:27 mpi Exp $ */ /* * Copyright (c) 2016 David Gwynne <dlg@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _SYS_PERCPU_H_ #define _SYS_PERCPU_H_ #ifndef CACHELINESIZE #define CACHELINESIZE 64 #endif #ifndef __upunused /* this should go in param.h */ #ifdef MULTIPROCESSOR #define __upunused #else #define __upunused __attribute__((__unused__)) #endif #endif struct cpumem { void *mem; }; struct cpumem_iter { unsigned int cpu; } __upunused; struct counters_ref { uint64_t g; uint64_t *c; }; #ifdef _KERNEL #include <sys/atomic.h> struct pool; struct cpumem *cpumem_get(struct pool *); void cpumem_put(struct pool *, struct cpumem *); struct cpumem *cpumem_malloc(size_t, int); struct cpumem *cpumem_malloc_ncpus(struct cpumem *, size_t, int); void cpumem_free(struct cpumem *, int, size_t); void *cpumem_first(struct cpumem_iter *, struct cpumem *); void *cpumem_next(struct cpumem_iter *, struct cpumem *); static inline void * cpumem_enter(struct cpumem *cm) { #ifdef MULTIPROCESSOR return (cm[cpu_number()].mem); #else return (cm); #endif } static inline void cpumem_leave(struct cpumem *cm, void *mem) { /* KDASSERT? */ } #ifdef MULTIPROCESSOR #define CPUMEM_BOOT_MEMORY(_name, _sz) \ static struct { \ unsigned char mem[_sz]; \ struct cpumem cpumem; \ } __aligned(CACHELINESIZE) _name##_boot_cpumem = { \ .cpumem = { _name##_boot_cpumem.mem } \ } #define CPUMEM_BOOT_INITIALIZER(_name) \ { &_name##_boot_cpumem.cpumem } #else /* MULTIPROCESSOR */ #define CPUMEM_BOOT_MEMORY(_name, _sz) \ static struct { \ unsigned char mem[_sz]; \ } __aligned(sizeof(uint64_t)) _name##_boot_cpumem #define CPUMEM_BOOT_INITIALIZER(_name) \ { (struct cpumem *)&_name##_boot_cpumem.mem } #endif /* MULTIPROCESSOR */ #define CPUMEM_FOREACH(_var, _iter, _cpumem) \ for ((_var) = cpumem_first((_iter), (_cpumem)); \ (_var) != NULL; \ (_var) = cpumem_next((_iter), (_cpumem))) /* * per cpu counters */ struct cpumem *counters_alloc(unsigned int); struct cpumem *counters_alloc_ncpus(struct cpumem *, unsigned int); void counters_free(struct cpumem *, unsigned int); void counters_read(struct cpumem *, uint64_t *, unsigned int, uint64_t *); void counters_zero(struct cpumem *, unsigned int); static inline uint64_t * counters_enter(struct counters_ref *ref, struct cpumem *cm) { ref->c = cpumem_enter(cm); #ifdef MULTIPROCESSOR ref->g = ++(*ref->c); /* make the generation number odd */ membar_producer(); return (ref->c + 1); #else return (ref->c); #endif } static inline void counters_leave(struct counters_ref *ref, struct cpumem *cm) { #ifdef MULTIPROCESSOR membar_producer(); (*ref->c) = ++ref->g; /* make the generation number even again */ #endif cpumem_leave(cm, ref->c); } static inline void counters_inc(struct cpumem *cm, unsigned int c) { struct counters_ref ref; uint64_t *counters; counters = counters_enter(&ref, cm); counters[c]++; counters_leave(&ref, cm); } static inline void counters_dec(struct cpumem *cm, unsigned int c) { struct counters_ref ref; uint64_t *counters; counters = counters_enter(&ref, cm); counters[c]--; counters_leave(&ref, cm); } static inline void counters_add(struct cpumem *cm, unsigned int c, uint64_t v) { struct counters_ref ref; uint64_t *counters; counters = counters_enter(&ref, cm); counters[c] += v; counters_leave(&ref, cm); } static inline void counters_pkt(struct cpumem *cm, unsigned int c, unsigned int b, uint64_t v) { struct counters_ref ref; uint64_t *counters; counters = counters_enter(&ref, cm); counters[c]++; counters[b] += v; counters_leave(&ref, cm); } #ifdef MULTIPROCESSOR #define COUNTERS_BOOT_MEMORY(_name, _n) \ CPUMEM_BOOT_MEMORY(_name, ((_n) + 1) * sizeof(uint64_t)) #else #define COUNTERS_BOOT_MEMORY(_name, _n) \ CPUMEM_BOOT_MEMORY(_name, (_n) * sizeof(uint64_t)) #endif #define COUNTERS_BOOT_INITIALIZER(_name) CPUMEM_BOOT_INITIALIZER(_name) #endif /* _KERNEL */ #endif /* _SYS_PERCPU_H_ */
4 4 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 /* $OpenBSD: scsiconf.c,v 1.253 2022/04/06 17:39:13 krw Exp $ */ /* $NetBSD: scsiconf.c,v 1.57 1996/05/02 01:09:01 neil Exp $ */ /* * Copyright (c) 1994 Charles Hannum. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Charles Hannum. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Originally written by Julian Elischer (julian@tfs.com) * for TRW Financial Systems for use under the MACH(2.5) operating system. * * TRW Financial Systems, in accordance with their agreement with Carnegie * Mellon University, makes this software available to CMU to distribute * or use in any manner that they see fit as long as this message is kept with * the software. For this reason TFS also grants any other persons or * organisations permission to use or modify this software. * * TFS supplies this software to be publicly redistributed * on the understanding that TFS is not responsible for the correct * functioning of this software in any circumstances. * * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 */ #include "bio.h" #include "mpath.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/pool.h> #include <sys/device.h> #include <sys/buf.h> #include <sys/atomic.h> #include <scsi/scsi_all.h> #include <scsi/scsi_debug.h> #include <scsi/scsiconf.h> int scsibusmatch(struct device *, void *, void *); void scsibusattach(struct device *, struct device *, void *); int scsibusactivate(struct device *, int); int scsibusdetach(struct device *, int); int scsibussubmatch(struct device *, void *, void *); int scsibussubprint(void *, const char *); #if NBIO > 0 #include <sys/ioctl.h> #include <sys/scsiio.h> #include <dev/biovar.h> int scsibusbioctl(struct device *, u_long, caddr_t); #endif /* NBIO > 0 */ void scsi_get_target_luns(struct scsibus_softc *, int, struct scsi_lun_array *); void scsi_add_link(struct scsi_link *); void scsi_remove_link(struct scsi_link *); void scsi_print_link(struct scsi_link *); int scsi_probe_link(struct scsibus_softc *, int, int, int); int scsi_activate_link(struct scsi_link *, int); int scsi_detach_link(struct scsi_link *, int); int scsi_detach_bus(struct scsibus_softc *, int); void scsi_devid(struct scsi_link *); int scsi_devid_pg80(struct scsi_link *); int scsi_devid_pg83(struct scsi_link *); int scsi_devid_wwn(struct scsi_link *); int scsi_activate_bus(struct scsibus_softc *, int); int scsi_activate_target(struct scsibus_softc *, int, int); int scsi_activate_lun(struct scsibus_softc *, int, int, int); int scsi_autoconf = SCSI_AUTOCONF; const struct cfattach scsibus_ca = { sizeof(struct scsibus_softc), scsibusmatch, scsibusattach, scsibusdetach, scsibusactivate }; struct cfdriver scsibus_cd = { NULL, "scsibus", DV_DULL }; struct scsi_quirk_inquiry_pattern { struct scsi_inquiry_pattern pattern; u_int16_t quirks; }; const struct scsi_quirk_inquiry_pattern scsi_quirk_patterns[] = { {{T_CDROM, T_REMOV, "PLEXTOR", "CD-ROM PX-40TS", "1.01"}, SDEV_NOSYNC}, {{T_DIRECT, T_FIXED, "MICROP ", "1588-15MBSUN0669", ""}, SDEV_AUTOSAVE}, {{T_DIRECT, T_FIXED, "DEC ", "RZ55 (C) DEC", ""}, SDEV_AUTOSAVE}, {{T_DIRECT, T_FIXED, "EMULEX ", "MD21/S2 ESDI", "A00"}, SDEV_AUTOSAVE}, {{T_DIRECT, T_FIXED, "IBMRAID ", "0662S", ""}, SDEV_AUTOSAVE}, {{T_DIRECT, T_FIXED, "IBM ", "0663H", ""}, SDEV_AUTOSAVE}, {{T_DIRECT, T_FIXED, "IBM", "0664", ""}, SDEV_AUTOSAVE}, {{T_DIRECT, T_FIXED, "IBM ", "H3171-S2", ""}, SDEV_AUTOSAVE}, {{T_DIRECT, T_FIXED, "IBM ", "KZ-C", ""}, SDEV_AUTOSAVE}, /* Broken IBM disk */ {{T_DIRECT, T_FIXED, "" , "DFRSS2F", ""}, SDEV_AUTOSAVE}, {{T_DIRECT, T_FIXED, "QUANTUM ", "ELS85S ", ""}, SDEV_AUTOSAVE}, {{T_DIRECT, T_REMOV, "iomega", "jaz 1GB", ""}, SDEV_NOTAGS}, {{T_DIRECT, T_FIXED, "MICROP", "4421-07", ""}, SDEV_NOTAGS}, {{T_DIRECT, T_FIXED, "SEAGATE", "ST150176LW", "0002"}, SDEV_NOTAGS}, {{T_DIRECT, T_FIXED, "HP", "C3725S", ""}, SDEV_NOTAGS}, {{T_DIRECT, T_FIXED, "IBM", "DCAS", ""}, SDEV_NOTAGS}, {{T_SEQUENTIAL, T_REMOV, "SONY ", "SDT-5000 ", "3."}, SDEV_NOSYNC|SDEV_NOWIDE}, {{T_SEQUENTIAL, T_REMOV, "WangDAT ", "Model 1300 ", "02.4"}, SDEV_NOSYNC|SDEV_NOWIDE}, {{T_SEQUENTIAL, T_REMOV, "WangDAT ", "Model 2600 ", "01.7"}, SDEV_NOSYNC|SDEV_NOWIDE}, {{T_SEQUENTIAL, T_REMOV, "WangDAT ", "Model 3200 ", "02.2"}, SDEV_NOSYNC|SDEV_NOWIDE}, /* ATAPI device quirks */ {{T_CDROM, T_REMOV, "CR-2801TE", "", "1.07"}, ADEV_NOSENSE}, {{T_CDROM, T_REMOV, "CREATIVECD3630E", "", "AC101"}, ADEV_NOSENSE}, {{T_CDROM, T_REMOV, "FX320S", "", "q01"}, ADEV_NOSENSE}, {{T_CDROM, T_REMOV, "GCD-R580B", "", "1.00"}, ADEV_LITTLETOC}, {{T_CDROM, T_REMOV, "MATSHITA CR-574", "", "1.02"}, ADEV_NOCAPACITY}, {{T_CDROM, T_REMOV, "MATSHITA CR-574", "", "1.06"}, ADEV_NOCAPACITY}, {{T_CDROM, T_REMOV, "Memorex CRW-2642", "", "1.0g"}, ADEV_NOSENSE}, {{T_CDROM, T_REMOV, "SANYO CRD-256P", "", "1.02"}, ADEV_NOCAPACITY}, {{T_CDROM, T_REMOV, "SANYO CRD-254P", "", "1.02"}, ADEV_NOCAPACITY}, {{T_CDROM, T_REMOV, "SANYO CRD-S54P", "", "1.08"}, ADEV_NOCAPACITY}, {{T_CDROM, T_REMOV, "CD-ROM CDR-S1", "", "1.70"}, ADEV_NOCAPACITY}, /* Sanyo */ {{T_CDROM, T_REMOV, "CD-ROM CDR-N16", "", "1.25"}, ADEV_NOCAPACITY}, /* Sanyo */ {{T_CDROM, T_REMOV, "UJDCD8730", "", "1.14"}, ADEV_NODOORLOCK}, /* Acer */ }; int scsiprint(void *aux, const char *pnp) { /* Only "scsibus"es can attach to "scsi"s. */ if (pnp) printf("scsibus at %s", pnp); return UNCONF; } int scsibusmatch(struct device *parent, void *match, void *aux) { return 1; } /* * The routine called by the adapter boards to get all their * devices configured in. */ void scsibusattach(struct device *parent, struct device *self, void *aux) { struct scsibus_softc *sb = (struct scsibus_softc *)self; struct scsibus_attach_args *saa = aux; if (!cold) scsi_autoconf = 0; SLIST_INIT(&sb->sc_link_list); sb->sb_adapter_softc = saa->saa_adapter_softc; sb->sb_adapter = saa->saa_adapter; sb->sb_pool = saa->saa_pool; sb->sb_quirks = saa->saa_quirks; sb->sb_flags = saa->saa_flags; sb->sb_openings = saa->saa_openings; sb->sb_adapter_buswidth = saa->saa_adapter_buswidth; sb->sb_adapter_target = saa->saa_adapter_target; sb->sb_luns = saa->saa_luns; if (sb->sb_adapter_buswidth == 0) sb->sb_adapter_buswidth = 8; if (sb->sb_luns == 0) sb->sb_luns = 8; printf(": %d targets", sb->sb_adapter_buswidth); if (sb->sb_adapter_target < sb->sb_adapter_buswidth) printf(", initiator %d", sb->sb_adapter_target); if (saa->saa_wwpn != 0x0 && saa->saa_wwnn != 0x0) { printf(", WWPN %016llx, WWNN %016llx", saa->saa_wwpn, saa->saa_wwnn); } printf("\n"); /* Initialize shared data. */ scsi_init(); SLIST_INIT(&sb->sc_link_list); #if NBIO > 0 if (bio_register(&sb->sc_dev, scsibusbioctl) != 0) printf("%s: unable to register bio\n", sb->sc_dev.dv_xname); #endif /* NBIO > 0 */ scsi_probe_bus(sb); } int scsibusactivate(struct device *dev, int act) { struct scsibus_softc *sb = (struct scsibus_softc *)dev; return scsi_activate_bus(sb, act); } int scsibusdetach(struct device *dev, int type) { struct scsibus_softc *sb = (struct scsibus_softc *)dev; int error; #if NBIO > 0 bio_unregister(&sb->sc_dev); #endif /* NBIO > 0 */ error = scsi_detach_bus(sb, type); if (error != 0) return error; KASSERT(SLIST_EMPTY(&sb->sc_link_list)); return 0; } int scsibussubmatch(struct device *parent, void *match, void *aux) { struct cfdata *cf = match; struct scsi_attach_args *sa = aux; struct scsi_link *link = sa->sa_sc_link; if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != link->target) return 0; if (cf->cf_loc[1] != -1 && cf->cf_loc[1] != link->lun) return 0; return (*cf->cf_attach->ca_match)(parent, match, aux); } /* * Print out autoconfiguration information for a subdevice. * * This is a slight abuse of 'standard' autoconfiguration semantics, * because 'print' functions don't normally print the colon and * device information. However, in this case that's better than * either printing redundant information before the attach message, * or having the device driver call a special function to print out * the standard device information. */ int scsibussubprint(void *aux, const char *pnp) { struct scsi_attach_args *sa = aux; if (pnp != NULL) printf("%s", pnp); scsi_print_link(sa->sa_sc_link); return UNCONF; } #if NBIO > 0 int scsibusbioctl(struct device *dev, u_long cmd, caddr_t addr) { struct scsibus_softc *sb = (struct scsibus_softc *)dev; struct sbioc_device *sdev; switch (cmd) { case SBIOCPROBE: sdev = (struct sbioc_device *)addr; return scsi_probe(sb, sdev->sd_target, sdev->sd_lun); case SBIOCDETACH: sdev = (struct sbioc_device *)addr; return scsi_detach(sb, sdev->sd_target, sdev->sd_lun, 0); default: return ENOTTY; } } #endif /* NBIO > 0 */ int scsi_activate(struct scsibus_softc *sb, int target, int lun, int act) { if (target == -1 && lun == -1) return scsi_activate_bus(sb, act); else if (lun == -1) return scsi_activate_target(sb, target, act); else return scsi_activate_lun(sb, target, lun, act); } int scsi_activate_bus(struct scsibus_softc *sb, int act) { struct scsi_link *link; int r, rv = 0; /* Activate all links on the bus. */ SLIST_FOREACH(link, &sb->sc_link_list, bus_list) { r = scsi_activate_link(link, act); if (r) rv = r; } return rv; } int scsi_activate_target(struct scsibus_softc *sb, int target, int act) { struct scsi_link *link; int r, rv = 0; /* Activate all links on the target. */ SLIST_FOREACH(link, &sb->sc_link_list, bus_list) { if (link->target == target) { r = scsi_activate_link(link, act); if (r) rv = r; } } return rv; } int scsi_activate_lun(struct scsibus_softc *sb, int target, int lun, int act) { struct scsi_link *link; /* Activate the (target, lun) link.*/ link = scsi_get_link(sb, target, lun); if (link == NULL) return 0; return scsi_activate_link(link, act); } int scsi_activate_link(struct scsi_link *link, int act) { struct device *dev; int rv = 0; dev = link->device_softc; switch (act) { case DVACT_DEACTIVATE: atomic_setbits_int(&link->state, SDEV_S_DYING); config_deactivate(dev); break; default: rv = config_suspend(dev, act); break; } return rv; } int scsi_probe(struct scsibus_softc *sb, int target, int lun) { if (target == -1 && lun == -1) return scsi_probe_bus(sb); else if (lun == -1) return scsi_probe_target(sb, target); else return scsi_probe_lun(sb, target, lun); } int scsi_probe_bus(struct scsibus_softc *sb) { int target, r, rv = 0; /* Probe all possible targets on bus. */ for (target = 0; target < sb->sb_adapter_buswidth; target++) { r = scsi_probe_target(sb, target); if (r != 0 && r != EINVAL) rv = r; } return rv; } int scsi_probe_target(struct scsibus_softc *sb, int target) { struct scsi_lun_array lunarray; int i, r, rv = 0; if (target < 0 || target == sb->sb_adapter_target) return EINVAL; scsi_get_target_luns(sb, target, &lunarray); if (lunarray.count == 0) return EINVAL; for (i = 0; i < lunarray.count; i++) { r = scsi_probe_link(sb, target, lunarray.luns[i], lunarray.dumbscan); if (r == EINVAL && lunarray.dumbscan == 1) return 0; if (r != 0 && r != EINVAL) rv = r; } return rv; } int scsi_probe_lun(struct scsibus_softc *sb, int target, int lun) { if (target < 0 || target == sb->sb_adapter_target || lun < 0) return EINVAL; /* Probe lun on target. *NOT* a dumbscan! */ return scsi_probe_link(sb, target, lun, 0); } int scsi_probe_link(struct scsibus_softc *sb, int target, int lun, int dumbscan) { struct scsi_attach_args sa; const struct scsi_quirk_inquiry_pattern *finger; struct scsi_inquiry_data *inqbuf, *usbinqbuf; struct scsi_link *link, *link0; struct cfdata *cf; int inqbytes, priority, rslt = 0; u_int16_t devquirks; /* Skip this slot if it is already attached and try the next LUN. */ if (scsi_get_link(sb, target, lun) != NULL) return 0; link = malloc(sizeof(*link), M_DEVBUF, M_NOWAIT); if (link == NULL) { SC_DEBUG(link, SDEV_DB2, ("malloc(scsi_link) failed.\n")); return EINVAL; } link->state = 0; link->target = target; link->lun = lun; link->openings = sb->sb_openings; link->node_wwn = link->port_wwn = 0; link->flags = sb->sb_flags; link->quirks = sb->sb_quirks; link->interpret_sense = scsi_interpret_sense; link->device_softc = NULL; link->bus = sb; memset(&link->inqdata, 0, sizeof(link->inqdata)); link->id = NULL; TAILQ_INIT(&link->queue); link->running = 0; link->pending = 0; link->pool = sb->sb_pool; SC_DEBUG(link, SDEV_DB2, ("scsi_link created.\n")); /* Ask the adapter if this will be a valid device. */ if (sb->sb_adapter->dev_probe != NULL && sb->sb_adapter->dev_probe(link) != 0) { if (lun == 0) { SC_DEBUG(link, SDEV_DB2, ("dev_probe(link) failed.\n")); rslt = EINVAL; } free(link, M_DEVBUF, sizeof(*link)); return rslt; } /* * If we havent been given an io pool by now then fall back to * using link->openings. */ if (link->pool == NULL) { link->pool = malloc(sizeof(*link->pool), M_DEVBUF, M_NOWAIT); if (link->pool == NULL) { SC_DEBUG(link, SDEV_DB2, ("malloc(pool) failed.\n")); rslt = ENOMEM; goto bad; } scsi_iopool_init(link->pool, link, scsi_default_get, scsi_default_put); SET(link->flags, SDEV_OWN_IOPL); } /* * Tell drivers that are paying attention to avoid sync/wide/tags until * INQUIRY data has been processed and the quirks information is * complete. Some drivers set bits in quirks before we get here, so * just add NOTAGS, NOWIDE and NOSYNC. */ devquirks = link->quirks; SET(link->quirks, SDEV_NOSYNC | SDEV_NOWIDE | SDEV_NOTAGS); /* * Ask the device what it is. */ #ifdef SCSIDEBUG if (((sb->sc_dev.dv_unit < 32) && ((1U << sb->sc_dev.dv_unit) & scsidebug_buses)) && ((target < 32) && ((1U << target) & scsidebug_targets)) && ((lun < 32) && ((1U << lun) & scsidebug_luns))) SET(link->flags, scsidebug_level); #endif /* SCSIDEBUG */ if (lun == 0) { /* Clear any outstanding errors. */ scsi_test_unit_ready(link, TEST_READY_RETRIES, scsi_autoconf | SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY | SCSI_IGNORE_MEDIA_CHANGE); } /* Now go ask the device all about itself. */ inqbuf = dma_alloc(sizeof(*inqbuf), PR_NOWAIT | PR_ZERO); if (inqbuf == NULL) { SC_DEBUG(link, SDEV_DB2, ("dma_alloc(inqbuf) failed.\n")); rslt = ENOMEM; goto bad; } rslt = scsi_inquire(link, inqbuf, scsi_autoconf | SCSI_SILENT); if (rslt != 0) { if (lun == 0) rslt = EINVAL; dma_free(inqbuf, sizeof(*inqbuf)); goto bad; } inqbytes = SID_SCSI2_HDRLEN + inqbuf->additional_length; memcpy(&link->inqdata, inqbuf, inqbytes); dma_free(inqbuf, sizeof(*inqbuf)); inqbuf = &link->inqdata; if (inqbytes < offsetof(struct scsi_inquiry_data, vendor)) memset(inqbuf->vendor, ' ', sizeof(inqbuf->vendor)); if (inqbytes < offsetof(struct scsi_inquiry_data, product)) memset(inqbuf->product, ' ', sizeof(inqbuf->product)); if (inqbytes < offsetof(struct scsi_inquiry_data, revision)) memset(inqbuf->revision, ' ', sizeof(inqbuf->revision)); if (inqbytes < offsetof(struct scsi_inquiry_data, extra)) memset(inqbuf->extra, ' ', sizeof(inqbuf->extra)); switch (inqbuf->device & SID_QUAL) { case SID_QUAL_RSVD: case SID_QUAL_BAD_LU: goto bad; case SID_QUAL_LU_OFFLINE: if (lun == 0 && (inqbuf->device & SID_TYPE) == T_NODEVICE) break; goto bad; case SID_QUAL_LU_OK: default: if ((inqbuf->device & SID_TYPE) == T_NODEVICE) goto bad; break; } scsi_devid(link); link0 = scsi_get_link(sb, target, 0); if (lun == 0 || link0 == NULL) ; else if (ISSET(link->flags, SDEV_UMASS)) ; else if (link->id != NULL && !DEVID_CMP(link0->id, link->id)) ; else if (dumbscan == 1 && memcmp(inqbuf, &link0->inqdata, sizeof(*inqbuf)) == 0) { /* The device doesn't distinguish between LUNs. */ SC_DEBUG(link, SDEV_DB1, ("IDENTIFY not supported.\n")); rslt = EINVAL; goto bad; } link->quirks = devquirks; /* Restore what the device wanted. */ finger = (const struct scsi_quirk_inquiry_pattern *)scsi_inqmatch( inqbuf, scsi_quirk_patterns, nitems(scsi_quirk_patterns), sizeof(scsi_quirk_patterns[0]), &priority); if (priority != 0) SET(link->quirks, finger->quirks); switch (SID_ANSII_REV(inqbuf)) { case SCSI_REV_0: case SCSI_REV_1: SET(link->quirks, SDEV_NOTAGS | SDEV_NOSYNC | SDEV_NOWIDE | SDEV_NOSYNCCACHE); break; case SCSI_REV_2: case SCSI_REV_SPC: case SCSI_REV_SPC2: if (!ISSET(inqbuf->flags, SID_CmdQue)) SET(link->quirks, SDEV_NOTAGS); if (!ISSET(inqbuf->flags, SID_Sync)) SET(link->quirks, SDEV_NOSYNC); if (!ISSET(inqbuf->flags, SID_WBus16)) SET(link->quirks, SDEV_NOWIDE); break; case SCSI_REV_SPC3: case SCSI_REV_SPC4: case SCSI_REV_SPC5: /* By this time SID_Sync and SID_WBus16 were obsolete. */ if (!ISSET(inqbuf->flags, SID_CmdQue)) SET(link->quirks, SDEV_NOTAGS); break; default: break; } /* * If the device can't use tags, >1 opening may confuse it. */ if (ISSET(link->quirks, SDEV_NOTAGS)) link->openings = 1; /* * note what BASIC type of device it is */ if (ISSET(inqbuf->dev_qual2, SID_REMOVABLE)) SET(link->flags, SDEV_REMOVABLE); sa.sa_sc_link = link; cf = config_search(scsibussubmatch, (struct device *)sb, &sa); if (cf == NULL) { scsibussubprint(&sa, sb->sc_dev.dv_xname); printf(" not configured\n"); goto bad; } /* * Braindead USB devices, especially some x-in-1 media readers, try to * 'help' by pretending any LUN is actually LUN 0 until they see a * different LUN used in a command. So do an INQUIRY on LUN 1 at this * point to prevent such helpfulness before it causes confusion. */ if (lun == 0 && ISSET(link->flags, SDEV_UMASS) && scsi_get_link(sb, target, 1) == NULL && sb->sb_luns > 1 && (usbinqbuf = dma_alloc(sizeof(*usbinqbuf), M_NOWAIT)) != NULL) { link->lun = 1; scsi_inquire(link, usbinqbuf, scsi_autoconf | SCSI_SILENT); link->lun = 0; dma_free(usbinqbuf, sizeof(*usbinqbuf)); } scsi_add_link(link); /* * Generate a TEST_UNIT_READY command. This gives drivers waiting for * valid quirks data a chance to set wide/sync/tag options * appropriately. It also clears any outstanding ACA conditions that * INQUIRY may leave behind. * * Do this now so that any messages generated by config_attach() do not * have negotiation messages inserted into their midst. */ scsi_test_unit_ready(link, TEST_READY_RETRIES, scsi_autoconf | SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY | SCSI_IGNORE_MEDIA_CHANGE); config_attach((struct device *)sb, cf, &sa, scsibussubprint); return 0; bad: scsi_detach_link(link, DETACH_FORCE); return rslt; } int scsi_detach(struct scsibus_softc *sb, int target, int lun, int flags) { if (target == -1 && lun == -1) return scsi_detach_bus(sb, flags); else if (lun == -1) return scsi_detach_target(sb, target, flags); else return scsi_detach_lun(sb, target, lun, flags); } int scsi_detach_bus(struct scsibus_softc *sb, int flags) { struct scsi_link *link, *tmp; int r, rv = 0; /* Detach all links from bus. */ SLIST_FOREACH_SAFE(link, &sb->sc_link_list, bus_list, tmp) { r = scsi_detach_link(link, flags); if (r != 0 && r != ENXIO) rv = r; } return rv; } int scsi_detach_target(struct scsibus_softc *sb, int target, int flags) { struct scsi_link *link, *tmp; int r, rv = 0; /* Detach all links from target. */ SLIST_FOREACH_SAFE(link, &sb->sc_link_list, bus_list, tmp) { if (link->target == target) { r = scsi_detach_link(link, flags); if (r != 0 && r != ENXIO) rv = r; } } return rv; } int scsi_detach_lun(struct scsibus_softc *sb, int target, int lun, int flags) { struct scsi_link *link; /* Detach (target, lun) link. */ link = scsi_get_link(sb, target, lun); if (link == NULL) return EINVAL; return scsi_detach_link(link, flags); } int scsi_detach_link(struct scsi_link *link, int flags) { struct scsibus_softc *sb = link->bus; int rv; if (!ISSET(flags, DETACH_FORCE) && ISSET(link->flags, SDEV_OPEN)) return EBUSY; /* Detaching a device from scsibus is a five step process. */ /* 1. Wake up processes sleeping for an xs. */ if (link->pool != NULL) scsi_link_shutdown(link); /* 2. Detach the device. */ if (link->device_softc != NULL) { rv = config_detach(link->device_softc, flags); if (rv != 0) return rv; } /* 3. If it's using the openings io allocator, clean that up. */ if (link->pool != NULL && ISSET(link->flags, SDEV_OWN_IOPL)) { scsi_iopool_destroy(link->pool); free(link->pool, M_DEVBUF, sizeof(*link->pool)); } /* 4. Free up its state in the adapter. */ if (sb->sb_adapter->dev_free != NULL) sb->sb_adapter->dev_free(link); /* 5. Free up its state in the midlayer. */ if (link->id != NULL) devid_free(link->id); scsi_remove_link(link); free(link, M_DEVBUF, sizeof(*link)); return 0; } struct scsi_link * scsi_get_link(struct scsibus_softc *sb, int target, int lun) { struct scsi_link *link; SLIST_FOREACH(link, &sb->sc_link_list, bus_list) { if (link->target == target && link->lun == lun) return link; } return NULL; } void scsi_add_link(struct scsi_link *link) { SLIST_INSERT_HEAD(&link->bus->sc_link_list, link, bus_list); } void scsi_remove_link(struct scsi_link *link) { struct scsibus_softc *sb = link->bus; struct scsi_link *elm, *prev = NULL; SLIST_FOREACH(elm, &sb->sc_link_list, bus_list) { if (elm == link) { if (prev == NULL) SLIST_REMOVE_HEAD(&sb->sc_link_list, bus_list); else SLIST_REMOVE_AFTER(prev, bus_list); break; } prev = elm; } } void scsi_get_target_luns(struct scsibus_softc *sb, int target, struct scsi_lun_array *lunarray) { struct scsi_report_luns_data *report; struct scsi_link *link0; int i, nluns, rv = 0; /* LUN 0 *must* be present. */ scsi_probe_link(sb, target, 0, 0); link0 = scsi_get_link(sb, target, 0); if (link0 == NULL) { lunarray->count = 0; return; } /* Initialize dumbscan result. Just in case. */ report = NULL; for (i = 0; i < link0->bus->sb_luns; i++) lunarray->luns[i] = i; lunarray->count = link0->bus->sb_luns; lunarray->dumbscan = 1; /* * ATAPI, USB and pre-SPC (i.e. pre-SCSI-3) devices can't ask * for a report of valid LUNs. */ if ((link0->flags & (SDEV_UMASS | SDEV_ATAPI)) != 0 || SID_ANSII_REV(&link0->inqdata) < SCSI_REV_SPC) goto dumbscan; report = dma_alloc(sizeof(*report), PR_WAITOK); if (report == NULL) goto dumbscan; rv = scsi_report_luns(link0, REPORT_NORMAL, report, sizeof(*report), scsi_autoconf | SCSI_SILENT | SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY | SCSI_IGNORE_MEDIA_CHANGE, 10000); if (rv != 0) goto dumbscan; /* * XXX In theory we should check if data is full, which * would indicate it needs to be enlarged and REPORT * LUNS tried again. Solaris tries up to 3 times with * larger sizes for data. */ /* Return the reported Type-0 LUNs. Type-0 only! */ lunarray->count = 0; lunarray->dumbscan = 0; nluns = _4btol(report->length) / RPL_LUNDATA_SIZE; for (i = 0; i < nluns; i++) { if (report->luns[i].lundata[0] != 0) continue; lunarray->luns[lunarray->count++] = report->luns[i].lundata[RPL_LUNDATA_T0LUN]; } dumbscan: if (report != NULL) dma_free(report, sizeof(*report)); } void scsi_strvis(u_char *dst, u_char *src, int len) { u_char last; /* Trim leading and trailing whitespace and NULs. */ while (len > 0 && (src[0] == ' ' || src[0] == '\t' || src[0] == '\n' || src[0] == '\0' || src[0] == 0xff)) ++src, --len; while (len > 0 && (src[len-1] == ' ' || src[len-1] == '\t' || src[len-1] == '\n' || src[len-1] == '\0' || src[len-1] == 0xff)) --len; last = 0xff; while (len > 0) { switch (*src) { case ' ': case '\t': case '\n': case '\0': case 0xff: /* Collapse whitespace and NULs to a single space. */ if (last != ' ') *dst++ = ' '; last = ' '; break; case '\\': /* Quote backslashes. */ *dst++ = '\\'; *dst++ = '\\'; last = '\\'; break; default: if (*src < 0x20 || *src >= 0x80) { /* Non-printable characters to octal. */ *dst++ = '\\'; *dst++ = ((*src & 0300) >> 6) + '0'; *dst++ = ((*src & 0070) >> 3) + '0'; *dst++ = ((*src & 0007) >> 0) + '0'; } else { /* Copy normal characters. */ *dst++ = *src; } last = *src; break; } ++src, --len; } *dst++ = 0; } void scsi_print_link(struct scsi_link *link) { char visbuf[65]; struct scsi_inquiry_data *inqbuf; u_int8_t *id; int i; printf(" targ %d lun %d: ", link->target, link->lun); inqbuf = &link->inqdata; scsi_strvis(visbuf, inqbuf->vendor, 8); printf("<%s, ", visbuf); scsi_strvis(visbuf, inqbuf->product, 16); printf("%s, ", visbuf); scsi_strvis(visbuf, inqbuf->revision, 4); printf("%s>", visbuf); #ifdef SCSIDEBUG if (ISSET(link->flags, SDEV_ATAPI)) printf(" ATAPI"); else if (SID_ANSII_REV(inqbuf) < SCSI_REV_SPC) printf(" SCSI/%d", SID_ANSII_REV(inqbuf)); else if (SID_ANSII_REV(inqbuf) == SCSI_REV_SPC) printf(" SCSI/SPC"); else printf(" SCSI/SPC-%d", SID_ANSII_REV(inqbuf) - 2); #endif /* SCSIDEBUG */ if (ISSET(link->flags, SDEV_REMOVABLE)) printf(" removable"); if (link->id != NULL && link->id->d_type != DEVID_NONE) { id = (u_int8_t *)(link->id + 1); switch (link->id->d_type) { case DEVID_NAA: printf(" naa."); break; case DEVID_EUI: printf(" eui."); break; case DEVID_T10: printf(" t10."); break; case DEVID_SERIAL: printf(" serial."); break; case DEVID_WWN: printf(" wwn."); break; } if (ISSET(link->id->d_flags, DEVID_F_PRINT)) { for (i = 0; i < link->id->d_len; i++) { if (id[i] == '\0' || id[i] == ' ') { /* skip leading blanks */ /* collapse multiple blanks into one */ if (i > 0 && id[i-1] != id[i]) printf("_"); } else if (id[i] < 0x20 || id[i] >= 0x80) { /* non-printable characters */ printf("~"); } else { /* normal characters */ printf("%c", id[i]); } } } else { for (i = 0; i < link->id->d_len; i++) printf("%02x", id[i]); } } #ifdef SCSIDEBUG printf("\n"); sc_print_addr(link); printf("state %u, luns %u, openings %u\n", link->state, link->bus->sb_luns, link->openings); sc_print_addr(link); printf("flags (0x%04x) ", link->flags); scsi_show_flags(link->flags, flagnames); printf("\n"); sc_print_addr(link); printf("quirks (0x%04x) ", link->quirks); scsi_show_flags(link->quirks, quirknames); #endif /* SCSIDEBUG */ } /* * Return a priority based on how much of the inquiry data matches * the patterns for the particular driver. */ const void * scsi_inqmatch(struct scsi_inquiry_data *inqbuf, const void *_base, int nmatches, int matchsize, int *bestpriority) { const unsigned char *base = (const unsigned char *)_base; const void *bestmatch; int removable; /* Include the qualifier to catch vendor-unique types. */ removable = ISSET(inqbuf->dev_qual2, SID_REMOVABLE) ? T_REMOV : T_FIXED; for (*bestpriority = 0, bestmatch = 0; nmatches--; base += matchsize) { struct scsi_inquiry_pattern *match = (void *)base; int priority, len; if (inqbuf->device != match->type) continue; if (removable != match->removable) continue; priority = 2; len = strlen(match->vendor); if (bcmp(inqbuf->vendor, match->vendor, len)) continue; priority += len; len = strlen(match->product); if (bcmp(inqbuf->product, match->product, len)) continue; priority += len; len = strlen(match->revision); if (bcmp(inqbuf->revision, match->revision, len)) continue; priority += len; #ifdef SCSIDEBUG printf("scsi_inqmatch: "); if (_base == &scsi_quirk_patterns) printf(" quirk "); else printf(" match "); printf("priority %d. %s %s <\"%s\", \"%s\", \"%s\">", priority, devicetypenames[(match->type & SID_TYPE)], (match->removable == T_FIXED) ? "T_FIXED" : "T_REMOV", match->vendor, match->product, match->revision); if (_base == &scsi_quirk_patterns) printf(" quirks: 0x%04x", ((struct scsi_quirk_inquiry_pattern *)match)->quirks ); printf("\n"); #endif /* SCSIDEBUG */ if (priority > *bestpriority) { *bestpriority = priority; bestmatch = base; } } return bestmatch; } void scsi_devid(struct scsi_link *link) { struct { struct scsi_vpd_hdr hdr; u_int8_t list[32]; } __packed *pg; size_t len; int pg80 = 0, pg83 = 0, i; if (link->id != NULL) return; pg = dma_alloc(sizeof(*pg), PR_WAITOK | PR_ZERO); if (SID_ANSII_REV(&link->inqdata) >= SCSI_REV_2) { if (scsi_inquire_vpd(link, pg, sizeof(*pg), SI_PG_SUPPORTED, scsi_autoconf) != 0) goto wwn; len = MIN(sizeof(pg->list), _2btol(pg->hdr.page_length)); for (i = 0; i < len; i++) { switch (pg->list[i]) { case SI_PG_SERIAL: pg80 = 1; break; case SI_PG_DEVID: pg83 = 1; break; } } if (pg83 && scsi_devid_pg83(link) == 0) goto done; if (pg80 && scsi_devid_pg80(link) == 0) goto done; } wwn: scsi_devid_wwn(link); done: dma_free(pg, sizeof(*pg)); } int scsi_devid_pg83(struct scsi_link *link) { struct scsi_vpd_devid_hdr dhdr, chdr; struct scsi_vpd_hdr *hdr = NULL; u_int8_t *pg = NULL, *id; int len, pos, rv, type; int idtype = 0; u_char idflags; hdr = dma_alloc(sizeof(*hdr), PR_WAITOK | PR_ZERO); rv = scsi_inquire_vpd(link, hdr, sizeof(*hdr), SI_PG_DEVID, scsi_autoconf); if (rv != 0) goto done; len = sizeof(*hdr) + _2btol(hdr->page_length); pg = dma_alloc(len, PR_WAITOK | PR_ZERO); rv = scsi_inquire_vpd(link, pg, len, SI_PG_DEVID, scsi_autoconf); if (rv != 0) goto done; pos = sizeof(*hdr); do { if (len - pos < sizeof(dhdr)) { rv = EIO; goto done; } memcpy(&dhdr, &pg[pos], sizeof(dhdr)); pos += sizeof(dhdr); if (len - pos < dhdr.len) { rv = EIO; goto done; } if (VPD_DEVID_ASSOC(dhdr.flags) == VPD_DEVID_ASSOC_LU) { type = VPD_DEVID_TYPE(dhdr.flags); switch (type) { case VPD_DEVID_TYPE_NAA: case VPD_DEVID_TYPE_EUI64: case VPD_DEVID_TYPE_T10: if (type >= idtype) { idtype = type; chdr = dhdr; id = &pg[pos]; } break; default: /* skip */ break; } } pos += dhdr.len; } while (idtype != VPD_DEVID_TYPE_NAA && len != pos); if (idtype > 0) { switch (VPD_DEVID_TYPE(chdr.flags)) { case VPD_DEVID_TYPE_NAA: idtype = DEVID_NAA; break; case VPD_DEVID_TYPE_EUI64: idtype = DEVID_EUI; break; case VPD_DEVID_TYPE_T10: idtype = DEVID_T10; break; } switch (VPD_DEVID_CODE(chdr.pi_code)) { case VPD_DEVID_CODE_ASCII: case VPD_DEVID_CODE_UTF8: idflags = DEVID_F_PRINT; break; default: idflags = 0; break; } link->id = devid_alloc(idtype, idflags, chdr.len, id); } else rv = ENODEV; done: if (pg) dma_free(pg, len); if (hdr) dma_free(hdr, sizeof(*hdr)); return rv; } int scsi_devid_pg80(struct scsi_link *link) { struct scsi_vpd_hdr *hdr = NULL; u_int8_t *pg = NULL; char *id; size_t idlen; int len, pglen, rv; hdr = dma_alloc(sizeof(*hdr), PR_WAITOK | PR_ZERO); rv = scsi_inquire_vpd(link, hdr, sizeof(*hdr), SI_PG_SERIAL, scsi_autoconf); if (rv != 0) goto freehdr; len = _2btol(hdr->page_length); if (len == 0) { rv = EINVAL; goto freehdr; } pglen = sizeof(*hdr) + len; pg = dma_alloc(pglen, PR_WAITOK | PR_ZERO); rv = scsi_inquire_vpd(link, pg, pglen, SI_PG_SERIAL, scsi_autoconf); if (rv != 0) goto free; idlen = sizeof(link->inqdata.vendor) + sizeof(link->inqdata.product) + len; id = malloc(idlen, M_TEMP, M_WAITOK); memcpy(id, link->inqdata.vendor, sizeof(link->inqdata.vendor)); memcpy(id + sizeof(link->inqdata.vendor), link->inqdata.product, sizeof(link->inqdata.product)); memcpy(id + sizeof(link->inqdata.vendor) + sizeof(link->inqdata.product), pg + sizeof(*hdr), len); link->id = devid_alloc(DEVID_SERIAL, DEVID_F_PRINT, sizeof(link->inqdata.vendor) + sizeof(link->inqdata.product) + len, id); free(id, M_TEMP, idlen); free: dma_free(pg, pglen); freehdr: dma_free(hdr, sizeof(*hdr)); return rv; } int scsi_devid_wwn(struct scsi_link *link) { u_int64_t wwnn; if (link->lun != 0 || link->node_wwn == 0) return EOPNOTSUPP; wwnn = htobe64(link->node_wwn); link->id = devid_alloc(DEVID_WWN, 0, sizeof(wwnn), (u_int8_t *)&wwnn); return 0; } struct devid * devid_alloc(u_int8_t type, u_int8_t flags, u_int8_t len, u_int8_t *id) { struct devid *d; d = malloc(sizeof(*d) + len, M_DEVBUF, M_WAITOK|M_CANFAIL); if (d == NULL) return NULL; d->d_type = type; d->d_flags = flags; d->d_len = len; d->d_refcount = 1; memcpy(d + 1, id, len); return d; } struct devid * devid_copy(struct devid *d) { d->d_refcount++; return d; } void devid_free(struct devid *d) { if (--d->d_refcount == 0) free(d, M_DEVBUF, sizeof(*d) + d->d_len); }
6 35 648 71 1895 11 71 1906 1915 11 166 1882 229 229 205 205 1582 2 2 112 1876 60 61 61 61 61 61 52 1835 166 1838 116 166 166 1761 1686 20 20 20 19 20 42 31 11 11 11 2 2 61 1961 31 258 1823 1956 258 1822 1865 1439 183 50 100 101 60 45 14 13 46 55 55 30 9 19 3 13 9 22 22 147 148 147 147 15 17 13 13 27 4 30 30 16 122 41 49 56 56 79 36 39 112 122 148 148 72 72 31 31 29 2 31 31 14 23 31 72 14 6 3 6 8 5 6 93 76 30 93 6 4 6 15 15 15 13 10 9 5 12 11 15 567 567 1 1 1 1 1 1 1 1 1847 1 1850 1848 1840 555 43 42 1582 35 1835 1841 1836 34 1582 556 555 43 43 1851 1847 1849 42 9 9 17 66 658 310 244 11 67 8 42 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 /* $OpenBSD: pmap.c,v 1.167 2024/05/03 13:48:29 dv Exp $ */ /* $NetBSD: pmap.c,v 1.3 2003/05/08 18:13:13 thorpej Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright 2001 (c) Wasabi Systems, Inc. * All rights reserved. * * Written by Frank van der Linden for Wasabi Systems, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed for the NetBSD Project by * Wasabi Systems, Inc. * 4. The name of Wasabi Systems, Inc. may not be used to endorse * or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * This is the i386 pmap modified and generalized to support x86-64 * as well. The idea is to hide the upper N levels of the page tables * inside pmap_get_ptp, pmap_free_ptp and pmap_growkernel. The rest * is mostly untouched, except that it uses some more generalized * macros and interfaces. * * This pmap has been tested on the i386 as well, and it can be easily * adapted to PAE. * * fvdl@wasabisystems.com 18-Jun-2001 */ /* * pmap.c: i386 pmap module rewrite * Chuck Cranor <chuck@ccrc.wustl.edu> * 11-Aug-97 * * history of this pmap module: in addition to my own input, i used * the following references for this rewrite of the i386 pmap: * * [1] the NetBSD i386 pmap. this pmap appears to be based on the * BSD hp300 pmap done by Mike Hibler at University of Utah. * it was then ported to the i386 by William Jolitz of UUNET * Technologies, Inc. Then Charles M. Hannum of the NetBSD * project fixed some bugs and provided some speed ups. * * [2] the FreeBSD i386 pmap. this pmap seems to be the * Hibler/Jolitz pmap, as modified for FreeBSD by John S. Dyson * and David Greenman. * * [3] the Mach pmap. this pmap, from CMU, seems to have migrated * between several processors. the VAX version was done by * Avadis Tevanian, Jr., and Michael Wayne Young. the i386 * version was done by Lance Berc, Mike Kupfer, Bob Baron, * David Golub, and Richard Draves. the alpha version was * done by Alessandro Forin (CMU/Mach) and Chris Demetriou * (NetBSD/alpha). */ #include <sys/param.h> #include <sys/systm.h> #include <sys/atomic.h> #include <sys/proc.h> #include <sys/pool.h> #include <sys/user.h> #include <sys/mutex.h> #include <uvm/uvm.h> #include <machine/cpu.h> #ifdef MULTIPROCESSOR #include <machine/i82489reg.h> #include <machine/i82489var.h> #endif #include "vmm.h" #if NVMM > 0 #include <machine/vmmvar.h> #endif /* NVMM > 0 */ #include "acpi.h" /* #define PMAP_DEBUG */ #ifdef PMAP_DEBUG #define DPRINTF(x...) do { printf(x); } while(0) #else #define DPRINTF(x...) #endif /* PMAP_DEBUG */ /* * general info: * * - for an explanation of how the i386 MMU hardware works see * the comments in <machine/pte.h>. * * - for an explanation of the general memory structure used by * this pmap (including the recursive mapping), see the comments * in <machine/pmap.h>. * * this file contains the code for the "pmap module." the module's * job is to manage the hardware's virtual to physical address mappings. * note that there are two levels of mapping in the VM system: * * [1] the upper layer of the VM system uses vm_map's and vm_map_entry's * to map ranges of virtual address space to objects/files. for * example, the vm_map may say: "map VA 0x1000 to 0x22000 read-only * to the file /bin/ls starting at offset zero." note that * the upper layer mapping is not concerned with how individual * vm_pages are mapped. * * [2] the lower layer of the VM system (the pmap) maintains the mappings * from virtual addresses. it is concerned with which vm_page is * mapped where. for example, when you run /bin/ls and start * at page 0x1000 the fault routine may lookup the correct page * of the /bin/ls file and then ask the pmap layer to establish * a mapping for it. * * note that information in the lower layer of the VM system can be * thrown away since it can easily be reconstructed from the info * in the upper layer. * * data structures we use include: * - struct pmap: describes the address space of one process * - struct pv_entry: describes one <PMAP,VA> mapping of a PA * - struct pg_to_free: a list of virtual addresses whose mappings * have been changed. used for TLB flushing. */ /* * memory allocation * * - there are three data structures that we must dynamically allocate: * * [A] new process' page directory page (PDP) * - plan 1: done at pmap_create() we use * pool_get(&pmap_pmap_pool, PR_WAITOK) to do this allocation. * * if we are low in free physical memory then we sleep in * pool_get() -- in this case this is ok since we are creating * a new pmap and should not be holding any locks. * * XXX: the fork code currently has no way to return an "out of * memory, try again" error code since uvm_fork [fka vm_fork] * is a void function. * * [B] new page tables pages (PTP) * call uvm_pagealloc() * => success: zero page, add to pm_pdir * => failure: we are out of free vm_pages, let pmap_enter() * tell UVM about it. * * note: for kernel PTPs, we start with NKPTP of them. as we map * kernel memory (at uvm_map time) we check to see if we've grown * the kernel pmap. if so, we call the optional function * pmap_growkernel() to grow the kernel PTPs in advance. * * [C] pv_entry structures * - try to allocate one from the pool. * If we fail, we simply let pmap_enter() tell UVM about it. */ long nkptp[] = NKPTP_INITIALIZER; const vaddr_t ptp_masks[] = PTP_MASK_INITIALIZER; const int ptp_shifts[] = PTP_SHIFT_INITIALIZER; const long nkptpmax[] = NKPTPMAX_INITIALIZER; const long nbpd[] = NBPD_INITIALIZER; pd_entry_t *const normal_pdes[] = PDES_INITIALIZER; #define pmap_pte_set(p, n) atomic_swap_64(p, n) #define pmap_pte_clearbits(p, b) x86_atomic_clearbits_u64(p, b) #define pmap_pte_setbits(p, b) x86_atomic_setbits_u64(p, b) /* * global data structures */ struct pmap kernel_pmap_store; /* the kernel's pmap (proc0) */ /* * pg_nx: NX PTE bit (if CPU supports) * pg_g_kern: PG_G if global pages should be used in kernel mappings, * 0 otherwise (for insecure CPUs) */ pt_entry_t pg_nx = 0; pt_entry_t pg_g_kern = 0; /* pg_xo: XO PTE bits, set to PKU key1 (if cpu supports PKU) */ pt_entry_t pg_xo; /* * pmap_pg_wc: if our processor supports PAT then we set this * to be the pte bits for Write Combining. Else we fall back to * UC- so mtrrs can override the cacheability; */ int pmap_pg_wc = PG_UCMINUS; /* * pmap_use_pcid: nonzero if PCID use is enabled (currently we require INVPCID) * * The next three are zero unless and until PCID support is enabled so code * can just 'or' them in as needed without tests. * cr3_pcid: CR3_REUSE_PCID * cr3_pcid_proc and cr3_pcid_temp: PCID_PROC and PCID_TEMP */ #if PCID_KERN != 0 # error "pmap.c assumes PCID_KERN is zero" #endif int pmap_use_pcid; static u_int cr3_pcid_proc; static u_int cr3_pcid_temp; /* these two are accessed from locore.o */ paddr_t cr3_reuse_pcid; paddr_t cr3_pcid_proc_intel; /* * other data structures */ pt_entry_t protection_codes[8]; /* maps MI prot to i386 prot code */ int pmap_initialized = 0; /* pmap_init done yet? */ /* * pv management structures. */ struct pool pmap_pv_pool; /* * linked list of all non-kernel pmaps */ struct pmap_head pmaps; struct mutex pmaps_lock = MUTEX_INITIALIZER(IPL_VM); /* * pool that pmap structures are allocated from */ struct pool pmap_pmap_pool; /* * When we're freeing a ptp, we need to delay the freeing until all * tlb shootdown has been done. This is the list of the to-be-freed pages. */ TAILQ_HEAD(pg_to_free, vm_page); /* * pool that PDPs are allocated from */ struct pool pmap_pdp_pool; void pmap_pdp_ctor(pd_entry_t *); void pmap_pdp_ctor_intel(pd_entry_t *); extern vaddr_t msgbuf_vaddr; extern paddr_t msgbuf_paddr; extern vaddr_t idt_vaddr; /* we allocate IDT early */ extern paddr_t idt_paddr; extern vaddr_t lo32_vaddr; extern vaddr_t lo32_paddr; vaddr_t virtual_avail; extern int end; /* * local prototypes */ void pmap_enter_pv(struct vm_page *, struct pv_entry *, struct pmap *, vaddr_t, struct vm_page *); struct vm_page *pmap_get_ptp(struct pmap *, vaddr_t); struct vm_page *pmap_find_ptp(struct pmap *, vaddr_t, paddr_t, int); int pmap_find_pte_direct(struct pmap *pm, vaddr_t va, pt_entry_t **pd, int *offs); void pmap_free_ptp(struct pmap *, struct vm_page *, vaddr_t, struct pg_to_free *); void pmap_freepage(struct pmap *, struct vm_page *, int, struct pg_to_free *); #ifdef MULTIPROCESSOR static int pmap_is_active(struct pmap *, struct cpu_info *); #endif paddr_t pmap_map_ptes(struct pmap *); struct pv_entry *pmap_remove_pv(struct vm_page *, struct pmap *, vaddr_t); void pmap_do_remove(struct pmap *, vaddr_t, vaddr_t, int); void pmap_remove_ept(struct pmap *, vaddr_t, vaddr_t); void pmap_do_remove_ept(struct pmap *, vaddr_t); int pmap_enter_ept(struct pmap *, vaddr_t, paddr_t, vm_prot_t); int pmap_remove_pte(struct pmap *, struct vm_page *, pt_entry_t *, vaddr_t, int, struct pv_entry **); void pmap_remove_ptes(struct pmap *, struct vm_page *, vaddr_t, vaddr_t, vaddr_t, int, struct pv_entry **); #define PMAP_REMOVE_ALL 0 /* remove all mappings */ #define PMAP_REMOVE_SKIPWIRED 1 /* skip wired mappings */ void pmap_unmap_ptes(struct pmap *, paddr_t); int pmap_get_physpage(vaddr_t, int, paddr_t *); int pmap_pdes_valid(vaddr_t, pd_entry_t *); void pmap_alloc_level(vaddr_t, int, long *); static inline void pmap_sync_flags_pte(struct vm_page *, u_long); void pmap_tlb_shootpage(struct pmap *, vaddr_t, int); void pmap_tlb_shootrange(struct pmap *, vaddr_t, vaddr_t, int); void pmap_tlb_shoottlb(struct pmap *, int); #ifdef MULTIPROCESSOR void pmap_tlb_shootwait(void); #else #define pmap_tlb_shootwait() do { } while (0) #endif /* * p m a p i n l i n e h e l p e r f u n c t i o n s */ /* * pmap_is_curpmap: is this pmap the one currently loaded [in %cr3]? * of course the kernel is always loaded */ static inline int pmap_is_curpmap(struct pmap *pmap) { return((pmap == pmap_kernel()) || (pmap->pm_pdirpa == (rcr3() & CR3_PADDR))); } /* * pmap_is_active: is this pmap loaded into the specified processor's %cr3? */ #ifdef MULTIPROCESSOR static inline int pmap_is_active(struct pmap *pmap, struct cpu_info *ci) { return pmap == pmap_kernel() || pmap == ci->ci_proc_pmap; } #endif static inline u_int pmap_pte2flags(u_long pte) { return (((pte & PG_U) ? PG_PMAP_REF : 0) | ((pte & PG_M) ? PG_PMAP_MOD : 0)); } static inline void pmap_sync_flags_pte(struct vm_page *pg, u_long pte) { if (pte & (PG_U|PG_M)) { atomic_setbits_int(&pg->pg_flags, pmap_pte2flags(pte)); } } /* * pmap_map_ptes: map a pmap's PTEs into KVM * * This should not be done for EPT pmaps */ paddr_t pmap_map_ptes(struct pmap *pmap) { paddr_t cr3; KASSERT(pmap->pm_type != PMAP_TYPE_EPT); /* the kernel's pmap is always accessible */ if (pmap == pmap_kernel()) return 0; /* * Lock the target map before switching to its page tables to * guarantee other CPUs have finished changing the tables before * we potentially start caching table and TLB entries. */ mtx_enter(&pmap->pm_mtx); cr3 = rcr3(); KASSERT((cr3 & CR3_PCID) == PCID_KERN || (cr3 & CR3_PCID) == PCID_PROC); if (pmap->pm_pdirpa == (cr3 & CR3_PADDR)) cr3 = 0; else { cr3 |= cr3_reuse_pcid; lcr3(pmap->pm_pdirpa | cr3_pcid_temp); } return cr3; } void pmap_unmap_ptes(struct pmap *pmap, paddr_t save_cr3) { if (pmap != pmap_kernel()) mtx_leave(&pmap->pm_mtx); if (save_cr3 != 0) lcr3(save_cr3); } int pmap_find_pte_direct(struct pmap *pm, vaddr_t va, pt_entry_t **pd, int *offs) { u_long mask, shift; pd_entry_t pde; paddr_t pdpa; int lev; pdpa = pm->pm_pdirpa; shift = L4_SHIFT; mask = L4_MASK; for (lev = PTP_LEVELS; lev > 0; lev--) { *pd = (pd_entry_t *)PMAP_DIRECT_MAP(pdpa); *offs = (VA_SIGN_POS(va) & mask) >> shift; pde = (*pd)[*offs]; /* Large pages are different, break early if we run into one. */ if ((pde & (PG_PS|PG_V)) != PG_V) return (lev - 1); pdpa = ((*pd)[*offs] & PG_FRAME); /* 4096/8 == 512 == 2^9 entries per level */ shift -= 9; mask >>= 9; } return (0); } /* * p m a p k e n t e r f u n c t i o n s * * functions to quickly enter/remove pages from the kernel address * space. pmap_kremove is exported to MI kernel. we make use of * the recursive PTE mappings. */ /* * pmap_kenter_pa: enter a kernel mapping without R/M (pv_entry) tracking * * => no need to lock anything, assume va is already allocated * => should be faster than normal pmap enter function */ void pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot) { pt_entry_t *pte, opte, npte; pte = kvtopte(va); npte = (pa & PMAP_PA_MASK) | ((prot & PROT_WRITE) ? PG_RW : PG_RO) | ((pa & PMAP_NOCACHE) ? PG_N : 0) | ((pa & PMAP_WC) ? pmap_pg_wc : 0) | PG_V; /* special 1:1 mappings in the first 2MB must not be global */ if (va >= (vaddr_t)NBPD_L2) npte |= pg_g_kern; if (!(prot & PROT_EXEC)) npte |= pg_nx; opte = pmap_pte_set(pte, npte); #ifdef LARGEPAGES /* XXX For now... */ if (opte & PG_PS) panic("%s: PG_PS", __func__); #endif if (pmap_valid_entry(opte)) { if (pa & PMAP_NOCACHE && (opte & PG_N) == 0) wbinvd_on_all_cpus(); /* This shouldn't happen */ pmap_tlb_shootpage(pmap_kernel(), va, 1); pmap_tlb_shootwait(); } } /* * pmap_kremove: remove a kernel mapping(s) without R/M (pv_entry) tracking * * => no need to lock anything * => caller must dispose of any vm_page mapped in the va range * => note: not an inline function * => we assume the va is page aligned and the len is a multiple of PAGE_SIZE * => we assume kernel only unmaps valid addresses and thus don't bother * checking the valid bit before doing TLB flushing */ void pmap_kremove(vaddr_t sva, vsize_t len) { pt_entry_t *pte, opte; vaddr_t va, eva; eva = sva + len; for (va = sva; va != eva; va += PAGE_SIZE) { pte = kvtopte(va); opte = pmap_pte_set(pte, 0); #ifdef LARGEPAGES KASSERT((opte & PG_PS) == 0); #endif KASSERT((opte & PG_PVLIST) == 0); } pmap_tlb_shootrange(pmap_kernel(), sva, eva, 1); pmap_tlb_shootwait(); } /* * pmap_set_pml4_early * * Utility function to map 2GB of 2MB pages to 'pa'. The VA that is assigned * is the pml4 entry for 'early mappings' (see pmap.h). This function is used * by display drivers that need to map their framebuffers early, before the * pmap is fully initialized (eg, to show panic messages). * * Users of this function must call pmap_clear_pml4_early to remove the * mapping when finished. * * Parameters: * pa: phys addr to map * * Return value: * VA mapping to 'pa'. This mapping is 2GB in size and starts at the base * of the 2MB region containing 'va'. */ vaddr_t pmap_set_pml4_early(paddr_t pa) { extern paddr_t early_pte_pages; pt_entry_t *pml4e, *pte; int i, j, off; paddr_t curpa; vaddr_t va; pml4e = (pt_entry_t *)(proc0.p_addr->u_pcb.pcb_cr3 + KERNBASE); pml4e[PDIR_SLOT_EARLY] = (pd_entry_t)early_pte_pages | PG_V | PG_RW; off = pa & PAGE_MASK_L2; curpa = pa & L2_FRAME; pte = (pt_entry_t *)PMAP_DIRECT_MAP(early_pte_pages); memset(pte, 0, 3 * NBPG); pte[0] = (early_pte_pages + NBPG) | PG_V | PG_RW; pte[1] = (early_pte_pages + 2 * NBPG) | PG_V | PG_RW; pte = (pt_entry_t *)PMAP_DIRECT_MAP(early_pte_pages + NBPG); for (i = 0; i < 2; i++) { /* 2 early pages of mappings */ for (j = 0; j < 512; j++) { /* j[0..511] : 2MB mappings per page */ pte[(i * 512) + j] = curpa | PG_V | PG_RW | PG_PS; curpa += (2 * 1024 * 1024); } } va = (vaddr_t)((PDIR_SLOT_EARLY * 512ULL) << L3_SHIFT) + off; return VA_SIGN_NEG(va); } /* * pmap_clear_pml4_early * * Clears the mapping previously established with pmap_set_pml4_early. */ void pmap_clear_pml4_early(void) { extern paddr_t early_pte_pages; pt_entry_t *pml4e, *pte; pte = (pt_entry_t *)PMAP_DIRECT_MAP(early_pte_pages); memset(pte, 0, 3 * NBPG); pml4e = (pd_entry_t *)pmap_kernel()->pm_pdir; pml4e[PDIR_SLOT_EARLY] = 0; tlbflush(); } /* * p m a p i n i t f u n c t i o n s * * pmap_bootstrap and pmap_init are called during system startup * to init the pmap module. pmap_bootstrap() does a low level * init just to get things rolling. pmap_init() finishes the job. */ /* * pmap_bootstrap: get the system in a state where it can run with VM * properly enabled (called before main()). the VM system is * fully init'd later... */ paddr_t pmap_bootstrap(paddr_t first_avail, paddr_t max_pa) { vaddr_t kva_start = VM_MIN_KERNEL_ADDRESS; struct pmap *kpm; int curslot, i, j, p; long ndmpdp; paddr_t dmpd, dmpdp, start_cur, cur_pa; vaddr_t kva, kva_end; pt_entry_t *pml3, *pml2; /* * define the boundaries of the managed kernel virtual address * space. */ virtual_avail = kva_start; /* first free KVA */ /* * If PKU is available, initialize PROT_EXEC entry correctly, * and enable the feature before it gets used * XXX Some Hypervisors forget to save/restore PKU */ if (cpuid_level >= 0x7) { uint32_t ecx, dummy; CPUID_LEAF(0x7, 0, dummy, dummy, ecx, dummy); if (ecx & SEFF0ECX_PKU) { lcr4(rcr4() | CR4_PKE); pg_xo = PG_XO; } } /* * set up protection_codes: we need to be able to convert from * a MI protection code (some combo of VM_PROT...) to something * we can jam into a i386 PTE. */ protection_codes[PROT_NONE] = pg_nx; /* --- */ protection_codes[PROT_EXEC] = pg_xo; ; /* --x */ protection_codes[PROT_READ] = PG_RO | pg_nx; /* -r- */ protection_codes[PROT_READ | PROT_EXEC] = PG_RO; /* -rx */ protection_codes[PROT_WRITE] = PG_RW | pg_nx; /* w-- */ protection_codes[PROT_WRITE | PROT_EXEC] = PG_RW; /* w-x */ protection_codes[PROT_WRITE | PROT_READ] = PG_RW | pg_nx; /* wr- */ protection_codes[PROT_READ | PROT_WRITE | PROT_EXEC] = PG_RW; /* wrx */ /* * now we init the kernel's pmap * * the kernel pmap's pm_obj is not used for much. however, in * user pmaps the pm_obj contains the list of active PTPs. * the pm_obj currently does not have a pager. */ kpm = pmap_kernel(); for (i = 0; i < PTP_LEVELS - 1; i++) { uvm_obj_init(&kpm->pm_obj[i], &pmap_pager, 1); kpm->pm_ptphint[i] = NULL; } memset(&kpm->pm_list, 0, sizeof(kpm->pm_list)); /* pm_list not used */ kpm->pm_pdir = (pd_entry_t *)(proc0.p_addr->u_pcb.pcb_cr3 + KERNBASE); kpm->pm_pdirpa = proc0.p_addr->u_pcb.pcb_cr3; kpm->pm_stats.wired_count = kpm->pm_stats.resident_count = atop(kva_start - VM_MIN_KERNEL_ADDRESS); /* * the above is just a rough estimate and not critical to the proper * operation of the system. */ kpm->pm_type = PMAP_TYPE_NORMAL; curpcb->pcb_pmap = kpm; /* proc0's pcb */ /* * Configure and enable PCID use if supported. * Currently we require INVPCID support. */ if ((cpu_ecxfeature & CPUIDECX_PCID) && cpuid_level >= 0x07) { uint32_t ebx, dummy; CPUID_LEAF(0x7, 0, dummy, ebx, dummy, dummy); if (ebx & SEFF0EBX_INVPCID) { pmap_use_pcid = 1; /* * We cannot use global mappings because * invpcid function 0 does not invalidate global * mappings. The hardware can cache kernel * mappings based on PCID_KERN, i.e. there is no * need for global mappings. */ pg_g_kern = 0; lcr4( rcr4() | CR4_PCIDE ); cr3_pcid_proc = PCID_PROC; cr3_pcid_temp = PCID_TEMP; cr3_reuse_pcid = CR3_REUSE_PCID; cr3_pcid_proc_intel = PCID_PROC_INTEL; } } /* * Add PG_G attribute to already mapped kernel pages. pg_g_kern * is calculated in locore0.S and may be set to: * * 0 if this CPU does not safely support global pages in the kernel * (Intel/Meltdown) * PG_G if this CPU does safely support global pages in the kernel * (AMD) */ #if KERNBASE == VM_MIN_KERNEL_ADDRESS for (kva = VM_MIN_KERNEL_ADDRESS ; kva < virtual_avail ; #else kva_end = roundup((vaddr_t)&end, PAGE_SIZE); for (kva = KERNBASE; kva < kva_end ; #endif kva += PAGE_SIZE) { unsigned long p1i = pl1_i(kva); if (pmap_valid_entry(PTE_BASE[p1i])) PTE_BASE[p1i] |= pg_g_kern; } /* * Map the direct map. The first 4GB were mapped in locore, here * we map the rest if it exists. We actually use the direct map * here to set up the page tables, we're assuming that we're still * operating in the lower 4GB of memory. * * Map (up to) the first 512GB of physical memory first. This part * is handled differently than physical memory > 512GB since we have * already mapped part of this range in locore0. */ ndmpdp = (max_pa + NBPD_L3 - 1) >> L3_SHIFT; if (ndmpdp < NDML2_ENTRIES) ndmpdp = NDML2_ENTRIES; /* At least 4GB */ if (ndmpdp > 512) ndmpdp = 512; /* At most 512GB */ dmpdp = kpm->pm_pdir[PDIR_SLOT_DIRECT] & PG_FRAME; dmpd = first_avail; first_avail += ndmpdp * PAGE_SIZE; for (i = NDML2_ENTRIES; i < NPDPG * ndmpdp; i++) { paddr_t pdp; vaddr_t va; pdp = (paddr_t)&(((pd_entry_t *)dmpd)[i]); va = PMAP_DIRECT_MAP(pdp); *((pd_entry_t *)va) = ((paddr_t)i << L2_SHIFT); *((pd_entry_t *)va) |= PG_RW | PG_V | PG_PS | pg_g_kern | PG_U | PG_M | pg_nx; } for (i = NDML2_ENTRIES; i < ndmpdp; i++) { paddr_t pdp; vaddr_t va; pdp = (paddr_t)&(((pd_entry_t *)dmpdp)[i]); va = PMAP_DIRECT_MAP(pdp); *((pd_entry_t *)va) = dmpd + (i << PAGE_SHIFT); *((pd_entry_t *)va) |= PG_RW | PG_V | PG_U | PG_M | pg_nx; } kpm->pm_pdir[PDIR_SLOT_DIRECT] = dmpdp | PG_V | PG_KW | PG_U | PG_M | pg_nx; /* Map any remaining physical memory > 512GB */ for (curslot = 1 ; curslot < NUM_L4_SLOT_DIRECT ; curslot++) { /* * Start of current range starts at PA (curslot) * 512GB */ start_cur = (paddr_t)(curslot * NBPD_L4); if (max_pa > start_cur) { /* Next 512GB, new PML4e and L3(512GB) page */ dmpd = first_avail; first_avail += PAGE_SIZE; pml3 = (pt_entry_t *)PMAP_DIRECT_MAP(dmpd); kpm->pm_pdir[PDIR_SLOT_DIRECT + curslot] = dmpd | PG_KW | PG_V | PG_U | PG_M | pg_nx; /* Calculate full 1GB pages in this 512GB region */ p = ((max_pa - start_cur) >> L3_SHIFT); /* Check if a partial (<1GB) page remains */ if (max_pa & L2_MASK) p++; /* * Handle the case where this range is full and there * is still more memory after (p would be > 512). */ if (p > NPDPG) p = NPDPG; /* Allocate 'p' L2(1GB) pages and populate */ for (i = 0; i < p; i++) { dmpd = first_avail; first_avail += PAGE_SIZE; pml2 = (pt_entry_t *)PMAP_DIRECT_MAP(dmpd); pml3[i] = dmpd | PG_RW | PG_V | PG_U | PG_M | pg_nx; cur_pa = start_cur + (i << L3_SHIFT); j = 0; while (cur_pa < max_pa && j < NPDPG) { pml2[j] = curslot * NBPD_L4 + (uint64_t)i * NBPD_L3 + (uint64_t)j * NBPD_L2; pml2[j] |= PG_RW | PG_V | pg_g_kern | PG_U | PG_M | pg_nx | PG_PS; cur_pa += NBPD_L2; j++; } } } } tlbflush(); msgbuf_vaddr = virtual_avail; virtual_avail += round_page(MSGBUFSIZE); idt_vaddr = virtual_avail; virtual_avail += 2 * PAGE_SIZE; idt_paddr = first_avail; /* steal a page */ first_avail += 2 * PAGE_SIZE; #if defined(MULTIPROCESSOR) || \ (NACPI > 0 && !defined(SMALL_KERNEL)) /* * Grab a page below 4G for things that need it (i.e. * having an initial %cr3 for the MP trampoline). */ lo32_vaddr = virtual_avail; virtual_avail += PAGE_SIZE; lo32_paddr = first_avail; first_avail += PAGE_SIZE; #endif /* * init the global lists. */ LIST_INIT(&pmaps); /* * initialize the pmap pools. */ pool_init(&pmap_pmap_pool, sizeof(struct pmap), 0, IPL_VM, 0, "pmappl", NULL); pool_init(&pmap_pv_pool, sizeof(struct pv_entry), 0, IPL_VM, 0, "pvpl", &pool_allocator_single); pool_sethiwat(&pmap_pv_pool, 32 * 1024); /* * initialize the PDE pool. */ pool_init(&pmap_pdp_pool, PAGE_SIZE, 0, IPL_VM, 0, "pdppl", &pool_allocator_single); kpm->pm_pdir_intel = NULL; kpm->pm_pdirpa_intel = 0; /* * ensure the TLB is sync'd with reality by flushing it... */ tlbflush(); return first_avail; } void pmap_init_percpu(void) { pool_cache_init(&pmap_pv_pool); } /* * pmap_randomize * * Randomizes the location of the kernel pmap */ void pmap_randomize(void) { pd_entry_t *pml4va, *oldpml4va; paddr_t pml4pa; int i; pml4va = km_alloc(PAGE_SIZE, &kv_page, &kp_zero, &kd_nowait); if (pml4va == NULL) panic("%s: km_alloc failed", __func__); /* Copy old PML4 page to new one */ oldpml4va = pmap_kernel()->pm_pdir; memcpy(pml4va, oldpml4va, PAGE_SIZE); /* Switch to new PML4 */ pmap_extract(pmap_kernel(), (vaddr_t)pml4va, &pml4pa); lcr3(pml4pa); /* Fixup pmap_kernel and proc0's %cr3 */ pmap_kernel()->pm_pdirpa = pml4pa; pmap_kernel()->pm_pdir = pml4va; proc0.p_addr->u_pcb.pcb_cr3 = pml4pa; /* Fixup recursive PTE PML4E slot. We are only changing the PA */ pml4va[PDIR_SLOT_PTE] = pml4pa | (pml4va[PDIR_SLOT_PTE] & ~PG_FRAME); for (i = 0; i < NPDPG; i++) { /* PTE slot already handled earlier */ if (i == PDIR_SLOT_PTE) continue; if (pml4va[i] & PG_FRAME) pmap_randomize_level(&pml4va[i], 3); } /* Wipe out bootstrap PML4 */ memset(oldpml4va, 0, PAGE_SIZE); tlbflush(); } void pmap_randomize_level(pd_entry_t *pde, int level) { pd_entry_t *new_pd_va; paddr_t old_pd_pa, new_pd_pa; vaddr_t old_pd_va; struct vm_page *pg; int i; if (level == 0) return; if (level < PTP_LEVELS - 1 && (*pde & PG_PS)) return; new_pd_va = km_alloc(PAGE_SIZE, &kv_page, &kp_zero, &kd_nowait); if (new_pd_va == NULL) panic("%s: cannot allocate page for L%d page directory", __func__, level); old_pd_pa = *pde & PG_FRAME; old_pd_va = PMAP_DIRECT_MAP(old_pd_pa); pmap_extract(pmap_kernel(), (vaddr_t)new_pd_va, &new_pd_pa); memcpy(new_pd_va, (void *)old_pd_va, PAGE_SIZE); *pde = new_pd_pa | (*pde & ~PG_FRAME); tlbflush(); memset((void *)old_pd_va, 0, PAGE_SIZE); pg = PHYS_TO_VM_PAGE(old_pd_pa); if (pg != NULL) { pg->wire_count--; pmap_kernel()->pm_stats.resident_count--; if (pg->wire_count <= 1) uvm_pagefree(pg); } for (i = 0; i < NPDPG; i++) if (new_pd_va[i] & PG_FRAME) pmap_randomize_level(&new_pd_va[i], level - 1); } /* * Pre-allocate PTPs for low memory, so that 1:1 mappings for various * trampoline code can be entered. */ paddr_t pmap_prealloc_lowmem_ptps(paddr_t first_avail) { pd_entry_t *pdes; int level; paddr_t newp; pdes = pmap_kernel()->pm_pdir; level = PTP_LEVELS; for (;;) { newp = first_avail; first_avail += PAGE_SIZE; memset((void *)PMAP_DIRECT_MAP(newp), 0, PAGE_SIZE); pdes[pl_i(0, level)] = (newp & PG_FRAME) | PG_V | PG_RW; level--; if (level <= 1) break; pdes = normal_pdes[level - 2]; } return first_avail; } /* * pmap_init: no further initialization required on this platform */ void pmap_init(void) { pmap_initialized = 1; } /* * p v _ e n t r y f u n c t i o n s */ /* * main pv_entry manipulation functions: * pmap_enter_pv: enter a mapping onto a pv list * pmap_remove_pv: remove a mapping from a pv list */ /* * pmap_enter_pv: enter a mapping onto a pv list * * => caller should adjust ptp's wire_count before calling * * pve: preallocated pve for us to use * ptp: PTP in pmap that maps this VA */ void pmap_enter_pv(struct vm_page *pg, struct pv_entry *pve, struct pmap *pmap, vaddr_t va, struct vm_page *ptp) { pve->pv_pmap = pmap; pve->pv_va = va; pve->pv_ptp = ptp; /* NULL for kernel pmap */ mtx_enter(&pg->mdpage.pv_mtx); pve->pv_next = pg->mdpage.pv_list; /* add to ... */ pg->mdpage.pv_list = pve; /* ... list */ mtx_leave(&pg->mdpage.pv_mtx); } /* * pmap_remove_pv: try to remove a mapping from a pv_list * * => caller should adjust ptp's wire_count and free PTP if needed * => we return the removed pve */ struct pv_entry * pmap_remove_pv(struct vm_page *pg, struct pmap *pmap, vaddr_t va) { struct pv_entry *pve, **prevptr; mtx_enter(&pg->mdpage.pv_mtx); prevptr = &pg->mdpage.pv_list; while ((pve = *prevptr) != NULL) { if (pve->pv_pmap == pmap && pve->pv_va == va) { /* match? */ *prevptr = pve->pv_next; /* remove it! */ break; } prevptr = &pve->pv_next; /* previous pointer */ } mtx_leave(&pg->mdpage.pv_mtx); return(pve); /* return removed pve */ } /* * p t p f u n c t i o n s */ struct vm_page * pmap_find_ptp(struct pmap *pmap, vaddr_t va, paddr_t pa, int level) { int lidx = level - 1; struct vm_page *pg; if (pa != (paddr_t)-1 && pmap->pm_ptphint[lidx] && pa == VM_PAGE_TO_PHYS(pmap->pm_ptphint[lidx])) return (pmap->pm_ptphint[lidx]); pg = uvm_pagelookup(&pmap->pm_obj[lidx], ptp_va2o(va, level)); return pg; } void pmap_freepage(struct pmap *pmap, struct vm_page *ptp, int level, struct pg_to_free *pagelist) { int lidx; struct uvm_object *obj; lidx = level - 1; obj = &pmap->pm_obj[lidx]; pmap->pm_stats.resident_count--; if (pmap->pm_ptphint[lidx] == ptp) pmap->pm_ptphint[lidx] = RBT_ROOT(uvm_objtree, &obj->memt); ptp->wire_count = 0; uvm_pagerealloc(ptp, NULL, 0); TAILQ_INSERT_TAIL(pagelist, ptp, pageq); } void pmap_free_ptp(struct pmap *pmap, struct vm_page *ptp, vaddr_t va, struct pg_to_free *pagelist) { unsigned long index; int level; vaddr_t invaladdr; level = 1; do { pmap_freepage(pmap, ptp, level, pagelist); index = pl_i(va, level + 1); pmap_pte_set(&normal_pdes[level - 1][index], 0); if (level == PTP_LEVELS - 1 && pmap->pm_pdir_intel != NULL) { /* Zap special meltdown PML4e */ pmap_pte_set(&pmap->pm_pdir_intel[index], 0); DPRINTF("%s: cleared meltdown PML4e @ index %lu " "(va range start 0x%llx)\n", __func__, index, (uint64_t)(index << L4_SHIFT)); } invaladdr = level == 1 ? (vaddr_t)PTE_BASE : (vaddr_t)normal_pdes[level - 2]; pmap_tlb_shootpage(pmap, invaladdr + index * PAGE_SIZE, pmap_is_curpmap(curpcb->pcb_pmap)); if (level < PTP_LEVELS - 1) { ptp = pmap_find_ptp(pmap, va, (paddr_t)-1, level + 1); ptp->wire_count--; if (ptp->wire_count > 1) break; } } while (++level < PTP_LEVELS); } /* * pmap_get_ptp: get a PTP (if there isn't one, allocate a new one) * * => pmap should NOT be pmap_kernel() */ struct vm_page * pmap_get_ptp(struct pmap *pmap, vaddr_t va) { struct vm_page *ptp, *pptp; int i; unsigned long index; pd_entry_t *pva, *pva_intel; paddr_t ppa, pa; struct uvm_object *obj; ptp = NULL; pa = (paddr_t)-1; /* * Loop through all page table levels seeing if we need to * add a new page to that level. */ for (i = PTP_LEVELS; i > 1; i--) { /* * Save values from previous round. */ pptp = ptp; ppa = pa; index = pl_i(va, i); pva = normal_pdes[i - 2]; if (pmap_valid_entry(pva[index])) { ppa = pva[index] & PG_FRAME; ptp = NULL; continue; } obj = &pmap->pm_obj[i-2]; ptp = uvm_pagealloc(obj, ptp_va2o(va, i - 1), NULL, UVM_PGA_USERESERVE|UVM_PGA_ZERO); if (ptp == NULL) return NULL; atomic_clearbits_int(&ptp->pg_flags, PG_BUSY); ptp->wire_count = 1; pmap->pm_ptphint[i - 2] = ptp; pa = VM_PAGE_TO_PHYS(ptp); pva[index] = (pd_entry_t) (pa | PG_u | PG_RW | PG_V); /* * Meltdown Special case - if we are adding a new PML4e for * usermode addresses, just copy the PML4e to the U-K page * table. */ if (pmap->pm_pdir_intel != NULL && i == PTP_LEVELS && va < VM_MAXUSER_ADDRESS) { pva_intel = pmap->pm_pdir_intel; pva_intel[index] = pva[index]; DPRINTF("%s: copying usermode PML4e (content=0x%llx) " "from 0x%llx -> 0x%llx\n", __func__, pva[index], (uint64_t)&pva[index], (uint64_t)&pva_intel[index]); } pmap->pm_stats.resident_count++; /* * If we're not in the top level, increase the * wire count of the parent page. */ if (i < PTP_LEVELS) { if (pptp == NULL) pptp = pmap_find_ptp(pmap, va, ppa, i); #ifdef DIAGNOSTIC if (pptp == NULL) panic("%s: pde page disappeared", __func__); #endif pptp->wire_count++; } } /* * ptp is not NULL if we just allocated a new ptp. If it's * still NULL, we must look up the existing one. */ if (ptp == NULL) { ptp = pmap_find_ptp(pmap, va, ppa, 1); #ifdef DIAGNOSTIC if (ptp == NULL) { printf("va %lx ppa %lx\n", (unsigned long)va, (unsigned long)ppa); panic("%s: unmanaged user PTP", __func__); } #endif } pmap->pm_ptphint[0] = ptp; return(ptp); } /* * p m a p l i f e c y c l e f u n c t i o n s */ /* * pmap_pdp_ctor: constructor for the PDP cache. */ void pmap_pdp_ctor(pd_entry_t *pdir) { paddr_t pdirpa; int npde, i; struct pmap *kpm = pmap_kernel(); /* fetch the physical address of the page directory. */ (void) pmap_extract(kpm, (vaddr_t) pdir, &pdirpa); /* zero init area */ memset(pdir, 0, PDIR_SLOT_PTE * sizeof(pd_entry_t)); /* put in recursive PDE to map the PTEs */ pdir[PDIR_SLOT_PTE] = pdirpa | PG_V | PG_KW | pg_nx; npde = nkptp[PTP_LEVELS - 1]; /* put in kernel VM PDEs */ memcpy(&pdir[PDIR_SLOT_KERN], &PDP_BASE[PDIR_SLOT_KERN], npde * sizeof(pd_entry_t)); /* zero the rest */ memset(&pdir[PDIR_SLOT_KERN + npde], 0, (NTOPLEVEL_PDES - (PDIR_SLOT_KERN + npde)) * sizeof(pd_entry_t)); for (i = 0; i < NUM_L4_SLOT_DIRECT; i++) pdir[PDIR_SLOT_DIRECT + i] = kpm->pm_pdir[PDIR_SLOT_DIRECT + i]; #if VM_MIN_KERNEL_ADDRESS != KERNBASE pdir[pl4_pi(KERNBASE)] = PDP_BASE[pl4_pi(KERNBASE)]; #endif } void pmap_pdp_ctor_intel(pd_entry_t *pdir) { struct pmap *kpm = pmap_kernel(); /* Copy PML4es from pmap_kernel's U-K view */ memcpy(pdir, kpm->pm_pdir_intel, PAGE_SIZE); } /* * pmap_create: create a pmap * * => note: old pmap interface took a "size" args which allowed for * the creation of "software only" pmaps (not in bsd). */ struct pmap * pmap_create(void) { struct pmap *pmap; int i; pmap = pool_get(&pmap_pmap_pool, PR_WAITOK); mtx_init(&pmap->pm_mtx, IPL_VM); /* init uvm_object */ for (i = 0; i < PTP_LEVELS - 1; i++) { uvm_obj_init(&pmap->pm_obj[i], &pmap_pager, 1); pmap->pm_ptphint[i] = NULL; } pmap->pm_stats.wired_count = 0; pmap->pm_stats.resident_count = 1; /* count the PDP allocd below */ pmap->pm_type = PMAP_TYPE_NORMAL; pmap->eptp = 0; /* allocate PDP */ /* * note that there is no need to splvm to protect us from * malloc since malloc allocates out of a submap and we should * have already allocated kernel PTPs to cover the range... */ pmap->pm_pdir = pool_get(&pmap_pdp_pool, PR_WAITOK); pmap_pdp_ctor(pmap->pm_pdir); pmap->pm_pdirpa = pmap->pm_pdir[PDIR_SLOT_PTE] & PG_FRAME; /* * Intel CPUs need a special page table to be used during usermode * execution, one that lacks all kernel mappings. */ if (cpu_meltdown) { pmap->pm_pdir_intel = pool_get(&pmap_pdp_pool, PR_WAITOK); pmap_pdp_ctor_intel(pmap->pm_pdir_intel); pmap->pm_stats.resident_count++; if (!pmap_extract(pmap_kernel(), (vaddr_t)pmap->pm_pdir_intel, &pmap->pm_pdirpa_intel)) panic("%s: unknown PA mapping for meltdown PML4", __func__); } else { pmap->pm_pdir_intel = NULL; pmap->pm_pdirpa_intel = 0; } mtx_enter(&pmaps_lock); LIST_INSERT_HEAD(&pmaps, pmap, pm_list); mtx_leave(&pmaps_lock); return (pmap); } /* * pmap_destroy: drop reference count on pmap. free pmap if * reference count goes to zero. */ void pmap_destroy(struct pmap *pmap) { struct vm_page *pg; int refs; int i; /* * drop reference count */ refs = atomic_dec_int_nv(&pmap->pm_obj[0].uo_refs); if (refs > 0) { return; } /* * remove it from global list of pmaps */ mtx_enter(&pmaps_lock); LIST_REMOVE(pmap, pm_list); mtx_leave(&pmaps_lock); /* * free any remaining PTPs */ for (i = 0; i < PTP_LEVELS - 1; i++) { while ((pg = RBT_ROOT(uvm_objtree, &pmap->pm_obj[i].memt)) != NULL) { KASSERT((pg->pg_flags & PG_BUSY) == 0); pg->wire_count = 0; pmap->pm_stats.resident_count--; uvm_pagefree(pg); } } pool_put(&pmap_pdp_pool, pmap->pm_pdir); if (pmap->pm_pdir_intel != NULL) { pmap->pm_stats.resident_count--; pool_put(&pmap_pdp_pool, pmap->pm_pdir_intel); } pool_put(&pmap_pmap_pool, pmap); } /* * Add a reference to the specified pmap. */ void pmap_reference(struct pmap *pmap) { atomic_inc_int(&pmap->pm_obj[0].uo_refs); } /* * pmap_activate: activate a process' pmap (fill in %cr3) * * => called from cpu_fork() and when switching pmaps during exec * => if p is the curproc, then load it into the MMU */ void pmap_activate(struct proc *p) { struct pcb *pcb = &p->p_addr->u_pcb; struct pmap *pmap = p->p_vmspace->vm_map.pmap; pcb->pcb_pmap = pmap; pcb->pcb_cr3 = pmap->pm_pdirpa; pcb->pcb_cr3 |= (pmap != pmap_kernel()) ? cr3_pcid_proc : (PCID_KERN | cr3_reuse_pcid); if (p != curproc) return; if ((p->p_flag & P_SYSTEM) == 0) { struct cpu_info *self = curcpu(); /* mark the pmap in use by this processor */ self->ci_proc_pmap = pmap; /* in case we return to userspace without context switching */ if (cpu_meltdown) { self->ci_kern_cr3 = pcb->pcb_cr3 | cr3_reuse_pcid; self->ci_user_cr3 = pmap->pm_pdirpa_intel | cr3_pcid_proc_intel; } } lcr3(pcb->pcb_cr3); } /* * pmap_deactivate: deactivate a process' pmap */ void pmap_deactivate(struct proc *p) { if ((p->p_flag & P_SYSTEM) == 0) { struct cpu_info *self = curcpu(); /* * mark the pmap no longer in use by this processor. */ KASSERT(self->ci_proc_pmap == p->p_vmspace->vm_map.pmap); self->ci_proc_pmap = NULL; } } /* * end of lifecycle functions */ /* * some misc. functions */ int pmap_pdes_valid(vaddr_t va, pd_entry_t *lastpde) { int i; unsigned long index; pd_entry_t pde; for (i = PTP_LEVELS; i > 1; i--) { index = pl_i(va, i); pde = normal_pdes[i - 2][index]; if (!pmap_valid_entry(pde)) return 0; } if (lastpde != NULL) *lastpde = pde; return 1; } /* * pmap_extract: extract a PA for the given VA */ int pmap_extract(struct pmap *pmap, vaddr_t va, paddr_t *pap) { pt_entry_t *ptes, pte; int level, offs; if (pmap == pmap_kernel() && va >= PMAP_DIRECT_BASE && va < PMAP_DIRECT_END) { *pap = va - PMAP_DIRECT_BASE; return 1; } if (pmap != pmap_kernel()) mtx_enter(&pmap->pm_mtx); level = pmap_find_pte_direct(pmap, va, &ptes, &offs); pte = ptes[offs]; if (pmap != pmap_kernel()) mtx_leave(&pmap->pm_mtx); if (__predict_true(level == 0 && pmap_valid_entry(pte))) { if (pap != NULL) *pap = (pte & PG_FRAME) | (va & PAGE_MASK); return 1; } if (level == 1 && (pte & (PG_PS|PG_V)) == (PG_PS|PG_V)) { if (pap != NULL) *pap = (pte & PG_LGFRAME) | (va & PAGE_MASK_L2); return 1; } return 0; } /* * pmap_zero_page: zero a page */ void pmap_zero_page(struct vm_page *pg) { pagezero(pmap_map_direct(pg)); } /* * pmap_flush_cache: flush the cache for a virtual address. */ void pmap_flush_cache(vaddr_t addr, vsize_t len) { vaddr_t i; if (curcpu()->ci_cflushsz == 0) { wbinvd_on_all_cpus(); return; } /* all cpus that have clflush also have mfence. */ mfence(); for (i = addr; i < addr + len; i += curcpu()->ci_cflushsz) clflush(i); mfence(); } /* * pmap_copy_page: copy a page */ void pmap_copy_page(struct vm_page *srcpg, struct vm_page *dstpg) { vaddr_t srcva = pmap_map_direct(srcpg); vaddr_t dstva = pmap_map_direct(dstpg); memcpy((void *)dstva, (void *)srcva, PAGE_SIZE); } /* * p m a p r e m o v e f u n c t i o n s * * functions that remove mappings */ /* * pmap_remove_ptes: remove PTEs from a PTP * * => PTP must be mapped into KVA * => PTP should be null if pmap == pmap_kernel() */ void pmap_remove_ptes(struct pmap *pmap, struct vm_page *ptp, vaddr_t ptpva, vaddr_t startva, vaddr_t endva, int flags, struct pv_entry **free_pvs) { struct pv_entry *pve; pt_entry_t *pte = (pt_entry_t *) ptpva; struct vm_page *pg; pt_entry_t opte; /* * note that ptpva points to the PTE that maps startva. this may * or may not be the first PTE in the PTP. * * we loop through the PTP while there are still PTEs to look at * and the wire_count is greater than 1 (because we use the wire_count * to keep track of the number of real PTEs in the PTP). */ for (/*null*/; startva < endva && (ptp == NULL || ptp->wire_count > 1) ; pte++, startva += PAGE_SIZE) { if (!pmap_valid_entry(*pte)) continue; /* VA not mapped */ if ((flags & PMAP_REMOVE_SKIPWIRED) && (*pte & PG_W)) { continue; } /* atomically save the old PTE and zap! it */ opte = pmap_pte_set(pte, 0); if (opte & PG_W) pmap->pm_stats.wired_count--; pmap->pm_stats.resident_count--; if (ptp != NULL) ptp->wire_count--; /* dropping a PTE */ pg = PHYS_TO_VM_PAGE(opte & PG_FRAME); /* * if we are not on a pv list we are done. */ if ((opte & PG_PVLIST) == 0) { #ifdef DIAGNOSTIC if (pg != NULL) panic("%s: managed page without PG_PVLIST: " "va 0x%lx, opte 0x%llx", __func__, startva, opte); #endif continue; } #ifdef DIAGNOSTIC if (pg == NULL) panic("%s: unmanaged page marked PG_PVLIST: " "va 0x%lx, opte 0x%llx", __func__, startva, opte); #endif /* sync R/M bits */ pmap_sync_flags_pte(pg, opte); pve = pmap_remove_pv(pg, pmap, startva); if (pve != NULL) { pve->pv_next = *free_pvs; *free_pvs = pve; } /* end of "for" loop: time for next pte */ } } /* * pmap_remove_pte: remove a single PTE from a PTP * * => PTP must be mapped into KVA * => PTP should be null if pmap == pmap_kernel() * => returns true if we removed a mapping */ int pmap_remove_pte(struct pmap *pmap, struct vm_page *ptp, pt_entry_t *pte, vaddr_t va, int flags, struct pv_entry **free_pvs) { struct pv_entry *pve; struct vm_page *pg; pt_entry_t opte; if (!pmap_valid_entry(*pte)) return 0; /* VA not mapped */ if ((flags & PMAP_REMOVE_SKIPWIRED) && (*pte & PG_W)) { return 0; } /* atomically save the old PTE and zap! it */ opte = pmap_pte_set(pte, 0); if (opte & PG_W) pmap->pm_stats.wired_count--; pmap->pm_stats.resident_count--; if (ptp != NULL) ptp->wire_count--; /* dropping a PTE */ pg = PHYS_TO_VM_PAGE(opte & PG_FRAME); /* * if we are not on a pv list we are done. */ if ((opte & PG_PVLIST) == 0) { #ifdef DIAGNOSTIC if (pg != NULL) panic("%s: managed page without PG_PVLIST: " "va 0x%lx, opte 0x%llx", __func__, va, opte); #endif return 1; } #ifdef DIAGNOSTIC if (pg == NULL) panic("%s: unmanaged page marked PG_PVLIST: " "va 0x%lx, opte 0x%llx", __func__, va, opte); #endif /* sync R/M bits */ pmap_sync_flags_pte(pg, opte); pve = pmap_remove_pv(pg, pmap, va); if (pve != NULL) { pve->pv_next = *free_pvs; *free_pvs = pve; } return 1; } /* * pmap_remove: top level mapping removal function * * => caller should not be holding any pmap locks */ void pmap_remove(struct pmap *pmap, vaddr_t sva, vaddr_t eva) { if (pmap->pm_type == PMAP_TYPE_EPT) pmap_remove_ept(pmap, sva, eva); else pmap_do_remove(pmap, sva, eva, PMAP_REMOVE_ALL); } /* * pmap_do_remove: mapping removal guts * * => caller should not be holding any pmap locks */ void pmap_do_remove(struct pmap *pmap, vaddr_t sva, vaddr_t eva, int flags) { pd_entry_t pde; int result; paddr_t ptppa; vaddr_t blkendva; struct vm_page *ptp; struct pv_entry *pve; struct pv_entry *free_pvs = NULL; vaddr_t va; int shootall = 0, shootself; struct pg_to_free empty_ptps; paddr_t scr3; TAILQ_INIT(&empty_ptps); scr3 = pmap_map_ptes(pmap); shootself = (scr3 == 0); /* * removing one page? take shortcut function. */ if (sva + PAGE_SIZE == eva) { if (pmap_pdes_valid(sva, &pde)) { /* PA of the PTP */ ptppa = pde & PG_FRAME; /* get PTP if non-kernel mapping */ if (pmap == pmap_kernel()) { /* we never free kernel PTPs */ ptp = NULL; } else { ptp = pmap_find_ptp(pmap, sva, ptppa, 1); #ifdef DIAGNOSTIC if (ptp == NULL) panic("%s: unmanaged PTP detected " "in shortcut path", __func__); #endif } /* do it! */ result = pmap_remove_pte(pmap, ptp, &PTE_BASE[pl1_i(sva)], sva, flags, &free_pvs); /* * if mapping removed and the PTP is no longer * being used, free it! */ if (result && ptp && ptp->wire_count <= 1) pmap_free_ptp(pmap, ptp, sva, &empty_ptps); pmap_tlb_shootpage(pmap, sva, shootself); pmap_unmap_ptes(pmap, scr3); pmap_tlb_shootwait(); } else { pmap_unmap_ptes(pmap, scr3); } goto cleanup; } if ((eva - sva > 32 * PAGE_SIZE) && sva < VM_MIN_KERNEL_ADDRESS) shootall = 1; for (va = sva; va < eva; va = blkendva) { /* determine range of block */ blkendva = x86_round_pdr(va + 1); if (blkendva > eva) blkendva = eva; /* * XXXCDC: our PTE mappings should never be removed * with pmap_remove! if we allow this (and why would * we?) then we end up freeing the pmap's page * directory page (PDP) before we are finished using * it when we hit it in the recursive mapping. this * is BAD. * * long term solution is to move the PTEs out of user * address space. and into kernel address space (up * with APTE). then we can set VM_MAXUSER_ADDRESS to * be VM_MAX_ADDRESS. */ if (pl_i(va, PTP_LEVELS) == PDIR_SLOT_PTE) /* XXXCDC: ugly hack to avoid freeing PDP here */ continue; if (!pmap_pdes_valid(va, &pde)) continue; /* PA of the PTP */ ptppa = pde & PG_FRAME; /* get PTP if non-kernel mapping */ if (pmap == pmap_kernel()) { /* we never free kernel PTPs */ ptp = NULL; } else { ptp = pmap_find_ptp(pmap, va, ptppa, 1); #ifdef DIAGNOSTIC if (ptp == NULL) panic("%s: unmanaged PTP detected", __func__); #endif } pmap_remove_ptes(pmap, ptp, (vaddr_t)&PTE_BASE[pl1_i(va)], va, blkendva, flags, &free_pvs); /* if PTP is no longer being used, free it! */ if (ptp && ptp->wire_count <= 1) { pmap_free_ptp(pmap, ptp, va, &empty_ptps); } } if (shootall) pmap_tlb_shoottlb(pmap, shootself); else pmap_tlb_shootrange(pmap, sva, eva, shootself); pmap_unmap_ptes(pmap, scr3); pmap_tlb_shootwait(); cleanup: while ((pve = free_pvs) != NULL) { free_pvs = pve->pv_next; pool_put(&pmap_pv_pool, pve); } while ((ptp = TAILQ_FIRST(&empty_ptps)) != NULL) { TAILQ_REMOVE(&empty_ptps, ptp, pageq); uvm_pagefree(ptp); } } /* * pmap_page_remove: remove a managed vm_page from all pmaps that map it * * => R/M bits are sync'd back to attrs */ void pmap_page_remove(struct vm_page *pg) { struct pv_entry *pve; struct pmap *pm; pt_entry_t opte; #ifdef DIAGNOSTIC pd_entry_t pde; #endif struct pg_to_free empty_ptps; struct vm_page *ptp; paddr_t scr3; int shootself; TAILQ_INIT(&empty_ptps); mtx_enter(&pg->mdpage.pv_mtx); while ((pve = pg->mdpage.pv_list) != NULL) { pmap_reference(pve->pv_pmap); pm = pve->pv_pmap; mtx_leave(&pg->mdpage.pv_mtx); /* XXX use direct map? */ scr3 = pmap_map_ptes(pm); /* locks pmap */ shootself = (scr3 == 0); /* * We dropped the pvlist lock before grabbing the pmap * lock to avoid lock ordering problems. This means * we have to check the pvlist again since somebody * else might have modified it. All we care about is * that the pvlist entry matches the pmap we just * locked. If it doesn't, unlock the pmap and try * again. */ mtx_enter(&pg->mdpage.pv_mtx); if ((pve = pg->mdpage.pv_list) == NULL || pve->pv_pmap != pm) { mtx_leave(&pg->mdpage.pv_mtx); pmap_unmap_ptes(pm, scr3); /* unlocks pmap */ pmap_destroy(pm); mtx_enter(&pg->mdpage.pv_mtx); continue; } pg->mdpage.pv_list = pve->pv_next; mtx_leave(&pg->mdpage.pv_mtx); #ifdef DIAGNOSTIC if (pve->pv_ptp != NULL && pmap_pdes_valid(pve->pv_va, &pde) && (pde & PG_FRAME) != VM_PAGE_TO_PHYS(pve->pv_ptp)) { printf("%s: pg=%p: va=%lx, pv_ptp=%p\n", __func__, pg, pve->pv_va, pve->pv_ptp); printf("%s: PTP's phys addr: " "actual=%lx, recorded=%lx\n", __func__, (unsigned long)(pde & PG_FRAME), VM_PAGE_TO_PHYS(pve->pv_ptp)); panic("%s: mapped managed page has " "invalid pv_ptp field", __func__); } #endif /* atomically save the old PTE and zap it */ opte = pmap_pte_set(&PTE_BASE[pl1_i(pve->pv_va)], 0); if (opte & PG_W) pve->pv_pmap->pm_stats.wired_count--; pve->pv_pmap->pm_stats.resident_count--; pmap_tlb_shootpage(pve->pv_pmap, pve->pv_va, shootself); pmap_sync_flags_pte(pg, opte); /* update the PTP reference count. free if last reference. */ if (pve->pv_ptp != NULL) { pve->pv_ptp->wire_count--; if (pve->pv_ptp->wire_count <= 1) { pmap_free_ptp(pve->pv_pmap, pve->pv_ptp, pve->pv_va, &empty_ptps); } } pmap_unmap_ptes(pve->pv_pmap, scr3); /* unlocks pmap */ pmap_destroy(pve->pv_pmap); pool_put(&pmap_pv_pool, pve); mtx_enter(&pg->mdpage.pv_mtx); } mtx_leave(&pg->mdpage.pv_mtx); pmap_tlb_shootwait(); while ((ptp = TAILQ_FIRST(&empty_ptps)) != NULL) { TAILQ_REMOVE(&empty_ptps, ptp, pageq); uvm_pagefree(ptp); } } /* * p m a p a t t r i b u t e f u n c t i o n s * functions that test/change managed page's attributes * since a page can be mapped multiple times we must check each PTE that * maps it by going down the pv lists. */ /* * pmap_test_attrs: test a page's attributes */ int pmap_test_attrs(struct vm_page *pg, unsigned int testbits) { struct pv_entry *pve; pt_entry_t *ptes; int level, offs; u_long mybits, testflags; testflags = pmap_pte2flags(testbits); if (pg->pg_flags & testflags) return 1; mybits = 0; mtx_enter(&pg->mdpage.pv_mtx); for (pve = pg->mdpage.pv_list; pve != NULL && mybits == 0; pve = pve->pv_next) { level = pmap_find_pte_direct(pve->pv_pmap, pve->pv_va, &ptes, &offs); mybits |= (ptes[offs] & testbits); } mtx_leave(&pg->mdpage.pv_mtx); if (mybits == 0) return 0; atomic_setbits_int(&pg->pg_flags, pmap_pte2flags(mybits)); return 1; } /* * pmap_clear_attrs: change a page's attributes * * => we return 1 if we cleared one of the bits we were asked to */ int pmap_clear_attrs(struct vm_page *pg, unsigned long clearbits) { struct pv_entry *pve; pt_entry_t *ptes, opte; u_long clearflags; int result, level, offs; clearflags = pmap_pte2flags(clearbits); result = pg->pg_flags & clearflags; if (result) atomic_clearbits_int(&pg->pg_flags, clearflags); mtx_enter(&pg->mdpage.pv_mtx); for (pve = pg->mdpage.pv_list; pve != NULL; pve = pve->pv_next) { level = pmap_find_pte_direct(pve->pv_pmap, pve->pv_va, &ptes, &offs); opte = ptes[offs]; if (opte & clearbits) { result = 1; pmap_pte_clearbits(&ptes[offs], (opte & clearbits)); pmap_tlb_shootpage(pve->pv_pmap, pve->pv_va, pmap_is_curpmap(pve->pv_pmap)); } } mtx_leave(&pg->mdpage.pv_mtx); pmap_tlb_shootwait(); return (result != 0); } /* * p m a p p r o t e c t i o n f u n c t i o n s */ /* * pmap_page_protect: change the protection of all recorded mappings * of a managed page * * => NOTE: this is an inline function in pmap.h */ /* see pmap.h */ /* * pmap_protect: set the protection in of the pages in a pmap * * => NOTE: this is an inline function in pmap.h */ /* see pmap.h */ /* * pmap_write_protect: write-protect pages in a pmap */ void pmap_write_protect(struct pmap *pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot) { pt_entry_t *spte, *epte; pt_entry_t clear = 0, set = 0; vaddr_t blockend; int shootall = 0, shootself; vaddr_t va; paddr_t scr3; scr3 = pmap_map_ptes(pmap); shootself = (scr3 == 0); /* should be ok, but just in case ... */ sva &= PG_FRAME; eva &= PG_FRAME; if (!(prot & PROT_READ)) set |= pg_xo; if (!(prot & PROT_WRITE)) clear = PG_RW; if (!(prot & PROT_EXEC)) set |= pg_nx; if ((eva - sva > 32 * PAGE_SIZE) && sva < VM_MIN_KERNEL_ADDRESS) shootall = 1; for (va = sva; va < eva ; va = blockend) { blockend = (va & L2_FRAME) + NBPD_L2; if (blockend > eva) blockend = eva; /* * XXXCDC: our PTE mappings should never be write-protected! * * long term solution is to move the PTEs out of user * address space. and into kernel address space (up * with APTE). then we can set VM_MAXUSER_ADDRESS to * be VM_MAX_ADDRESS. */ /* XXXCDC: ugly hack to avoid freeing PDP here */ if (pl_i(va, PTP_LEVELS) == PDIR_SLOT_PTE) continue; /* empty block? */ if (!pmap_pdes_valid(va, NULL)) continue; #ifdef DIAGNOSTIC if (va >= VM_MAXUSER_ADDRESS && va < VM_MAX_ADDRESS) panic("%s: PTE space", __func__); #endif spte = &PTE_BASE[pl1_i(va)]; epte = &PTE_BASE[pl1_i(blockend)]; for (/*null */; spte < epte ; spte++) { if (!pmap_valid_entry(*spte)) continue; pmap_pte_clearbits(spte, clear); pmap_pte_setbits(spte, set); } } if (shootall) pmap_tlb_shoottlb(pmap, shootself); else pmap_tlb_shootrange(pmap, sva, eva, shootself); pmap_unmap_ptes(pmap, scr3); pmap_tlb_shootwait(); } /* * end of protection functions */ /* * pmap_unwire: clear the wired bit in the PTE * * => mapping should already be in map */ void pmap_unwire(struct pmap *pmap, vaddr_t va) { pt_entry_t *ptes; int level, offs; level = pmap_find_pte_direct(pmap, va, &ptes, &offs); if (level == 0) { #ifdef DIAGNOSTIC if (!pmap_valid_entry(ptes[offs])) panic("%s: invalid (unmapped) va 0x%lx", __func__, va); #endif if (__predict_true((ptes[offs] & PG_W) != 0)) { pmap_pte_clearbits(&ptes[offs], PG_W); pmap->pm_stats.wired_count--; } #ifdef DIAGNOSTIC else { printf("%s: wiring for pmap %p va 0x%lx " "didn't change!\n", __func__, pmap, va); } #endif } #ifdef DIAGNOSTIC else { panic("%s: invalid PDE", __func__); } #endif } #if 0 /* * pmap_collect: free resources held by a pmap * * => optional function. * => called when a process is swapped out to free memory. */ void pmap_collect(struct pmap *pmap) { /* * free all of the pt pages by removing the physical mappings * for its entire address space. */ pmap_do_remove(pmap, VM_MIN_ADDRESS, VM_MAX_ADDRESS, PMAP_REMOVE_SKIPWIRED); } #endif void pmap_enter_special(vaddr_t va, paddr_t pa, vm_prot_t prot) { uint64_t l4idx, l3idx, l2idx, l1idx; pd_entry_t *pd, *ptp; paddr_t npa; struct pmap *pmap = pmap_kernel(); pt_entry_t *ptes; int level, offs; /* If CPU is secure, no need to do anything */ if (!cpu_meltdown) return; /* Must be kernel VA */ if (va < VM_MIN_KERNEL_ADDRESS) panic("%s: invalid special mapping va 0x%lx requested", __func__, va); if (pmap->pm_pdir_intel == NULL) pmap->pm_pdir_intel = pool_get(&pmap_pdp_pool, PR_WAITOK | PR_ZERO); l4idx = (va & L4_MASK) >> L4_SHIFT; /* PML4E idx */ l3idx = (va & L3_MASK) >> L3_SHIFT; /* PDPTE idx */ l2idx = (va & L2_MASK) >> L2_SHIFT; /* PDE idx */ l1idx = (va & L1_MASK) >> L1_SHIFT; /* PTE idx */ DPRINTF("%s: va=0x%llx pa=0x%llx l4idx=%lld l3idx=%lld " "l2idx=%lld l1idx=%lld\n", __func__, (uint64_t)va, (uint64_t)pa, l4idx, l3idx, l2idx, l1idx); /* Start at PML4 / top level */ pd = pmap->pm_pdir_intel; if (pd == NULL) panic("%s: PML4 not initialized for pmap @ %p", __func__, pmap); /* npa = physaddr of PDPT */ npa = pd[l4idx] & PMAP_PA_MASK; /* Valid PML4e for the 512GB region containing va? */ if (!npa) { /* No valid PML4E - allocate PDPT page and set PML4E */ ptp = pool_get(&pmap_pdp_pool, PR_WAITOK | PR_ZERO); if (!pmap_extract(pmap, (vaddr_t)ptp, &npa)) panic("%s: can't locate PDPT page", __func__); pd[l4idx] = (npa | PG_RW | PG_V); DPRINTF("%s: allocated new PDPT page at phys 0x%llx, " "setting PML4e[%lld] = 0x%llx\n", __func__, (uint64_t)npa, l4idx, pd[l4idx]); } pd = (pd_entry_t *)PMAP_DIRECT_MAP(npa); if (pd == NULL) panic("%s: can't locate PDPT @ pa=0x%llx", __func__, (uint64_t)npa); /* npa = physaddr of PD page */ npa = pd[l3idx] & PMAP_PA_MASK; /* Valid PDPTe for the 1GB region containing va? */ if (!npa) { /* No valid PDPTe - allocate PD page and set PDPTe */ ptp = pool_get(&pmap_pdp_pool, PR_WAITOK | PR_ZERO); if (!pmap_extract(pmap, (vaddr_t)ptp, &npa)) panic("%s: can't locate PD page", __func__); pd[l3idx] = (npa | PG_RW | PG_V); DPRINTF("%s: allocated new PD page at phys 0x%llx, " "setting PDPTe[%lld] = 0x%llx\n", __func__, (uint64_t)npa, l3idx, pd[l3idx]); } pd = (pd_entry_t *)PMAP_DIRECT_MAP(npa); if (pd == NULL) panic("%s: can't locate PD page @ pa=0x%llx", __func__, (uint64_t)npa); /* npa = physaddr of PT page */ npa = pd[l2idx] & PMAP_PA_MASK; /* Valid PDE for the 2MB region containing va? */ if (!npa) { /* No valid PDE - allocate PT page and set PDE */ ptp = pool_get(&pmap_pdp_pool, PR_WAITOK | PR_ZERO); if (!pmap_extract(pmap, (vaddr_t)ptp, &npa)) panic("%s: can't locate PT page", __func__); pd[l2idx] = (npa | PG_RW | PG_V); DPRINTF("%s: allocated new PT page at phys 0x%llx, " "setting PDE[%lld] = 0x%llx\n", __func__, (uint64_t)npa, l2idx, pd[l2idx]); } pd = (pd_entry_t *)PMAP_DIRECT_MAP(npa); if (pd == NULL) panic("%s: can't locate PT page @ pa=0x%llx", __func__, (uint64_t)npa); DPRINTF("%s: setting PTE, PT page @ phys 0x%llx virt 0x%llx prot " "0x%llx was 0x%llx\n", __func__, (uint64_t)npa, (uint64_t)pd, (uint64_t)prot, (uint64_t)pd[l1idx]); pd[l1idx] = pa | protection_codes[prot] | PG_V | PG_W; /* * Look up the corresponding U+K entry. If we're installing the * same PA into the U-K map then set the PG_G bit on both and copy * the cache-control bits from the U+K entry to the U-K entry. */ level = pmap_find_pte_direct(pmap, va, &ptes, &offs); if (__predict_true(level == 0 && pmap_valid_entry(ptes[offs]))) { if (((pd[l1idx] ^ ptes[offs]) & PG_FRAME) == 0) { pd[l1idx] |= PG_G | (ptes[offs] & (PG_N | PG_WT)); ptes[offs] |= PG_G; } else { DPRINTF("%s: special diffing mapping at %llx\n", __func__, (long long)va); } } else DPRINTF("%s: no U+K mapping for special mapping?\n", __func__); DPRINTF("%s: setting PTE[%lld] = 0x%llx\n", __func__, l1idx, pd[l1idx]); } void pmap_remove_ept(struct pmap *pmap, vaddr_t sgpa, vaddr_t egpa) { vaddr_t v; #if NVMM > 0 struct vmx_invept_descriptor vid; #endif /* NVMM > 0 */ DPRINTF("%s: sgpa=0x%llx egpa=0x%llx\n", __func__, (uint64_t)sgpa, (uint64_t)egpa); for (v = sgpa; v < egpa + PAGE_SIZE; v += PAGE_SIZE) pmap_do_remove_ept(pmap, v); #if NVMM > 0 if (pmap->eptp != 0) { memset(&vid, 0, sizeof(vid)); vid.vid_eptp = pmap->eptp; DPRINTF("%s: flushing EPT TLB for EPTP 0x%llx\n", __func__, vid.vid_eptp); invept(IA32_VMX_INVEPT_SINGLE_CTX, &vid); } #endif /* NVMM > 0 */ } void pmap_do_remove_ept(struct pmap *pmap, paddr_t gpa) { uint64_t l4idx, l3idx, l2idx, l1idx; struct vm_page *pg3, *pg2, *pg1; paddr_t npa3, npa2, npa1; pd_entry_t *pd4, *pd3, *pd2, *pd1; pd_entry_t *pptes; l4idx = (gpa & L4_MASK) >> L4_SHIFT; /* PML4E idx */ l3idx = (gpa & L3_MASK) >> L3_SHIFT; /* PDPTE idx */ l2idx = (gpa & L2_MASK) >> L2_SHIFT; /* PDE idx */ l1idx = (gpa & L1_MASK) >> L1_SHIFT; /* PTE idx */ /* Start at PML4 / top level */ pd4 = (pd_entry_t *)pmap->pm_pdir; if (pd4 == NULL) return; /* npa3 = physaddr of PDPT */ npa3 = pd4[l4idx] & PMAP_PA_MASK; if (!npa3) return; pd3 = (pd_entry_t *)PMAP_DIRECT_MAP(npa3); pg3 = PHYS_TO_VM_PAGE(npa3); /* npa2 = physaddr of PD page */ npa2 = pd3[l3idx] & PMAP_PA_MASK; if (!npa2) return; pd2 = (pd_entry_t *)PMAP_DIRECT_MAP(npa2); pg2 = PHYS_TO_VM_PAGE(npa2); /* npa1 = physaddr of PT page */ npa1 = pd2[l2idx] & PMAP_PA_MASK; if (!npa1) return; pd1 = (pd_entry_t *)PMAP_DIRECT_MAP(npa1); pg1 = PHYS_TO_VM_PAGE(npa1); if (pd1[l1idx] == 0) return; pd1[l1idx] = 0; pg1->wire_count--; pmap->pm_stats.resident_count--; if (pg1->wire_count > 1) return; pg1->wire_count = 0; pptes = (pd_entry_t *)PMAP_DIRECT_MAP(npa2); pptes[l2idx] = 0; uvm_pagefree(pg1); pmap->pm_stats.resident_count--; pg2->wire_count--; if (pg2->wire_count > 1) return; pg2->wire_count = 0; pptes = (pd_entry_t *)PMAP_DIRECT_MAP(npa3); pptes[l3idx] = 0; uvm_pagefree(pg2); pmap->pm_stats.resident_count--; pg3->wire_count--; if (pg3->wire_count > 1) return; pg3->wire_count = 0; pptes = pd4; pptes[l4idx] = 0; uvm_pagefree(pg3); pmap->pm_stats.resident_count--; } int pmap_enter_ept(struct pmap *pmap, paddr_t gpa, paddr_t hpa, vm_prot_t prot) { uint64_t l4idx, l3idx, l2idx, l1idx; pd_entry_t *pd, npte; struct vm_page *ptp, *pptp; paddr_t npa; struct uvm_object *obj; if (gpa > MAXDSIZ) return ENOMEM; l4idx = (gpa & L4_MASK) >> L4_SHIFT; /* PML4E idx */ l3idx = (gpa & L3_MASK) >> L3_SHIFT; /* PDPTE idx */ l2idx = (gpa & L2_MASK) >> L2_SHIFT; /* PDE idx */ l1idx = (gpa & L1_MASK) >> L1_SHIFT; /* PTE idx */ /* Start at PML4 / top level */ pd = (pd_entry_t *)pmap->pm_pdir; if (pd == NULL) return ENOMEM; /* npa = physaddr of PDPT */ npa = pd[l4idx] & PMAP_PA_MASK; /* Valid PML4e for the 512GB region containing gpa? */ if (!npa) { /* No valid PML4e - allocate PDPT page and set PML4e */ obj = &pmap->pm_obj[2]; /* PML4 UVM object */ ptp = uvm_pagealloc(obj, ptp_va2o(gpa, 3), NULL, UVM_PGA_USERESERVE|UVM_PGA_ZERO); if (ptp == NULL) return ENOMEM; /* * New PDPT page - we are setting the first entry, so set * the wired count to 1 */ ptp->wire_count = 1; /* Calculate phys address of this new PDPT page */ npa = VM_PAGE_TO_PHYS(ptp); /* * Higher levels get full perms; specific permissions are * entered at the lowest level. */ pd[l4idx] = (npa | EPT_R | EPT_W | EPT_X); pmap->pm_stats.resident_count++; pptp = ptp; } else { /* Already allocated PML4e */ pptp = PHYS_TO_VM_PAGE(npa); } pd = (pd_entry_t *)PMAP_DIRECT_MAP(npa); if (pd == NULL) panic("%s: can't locate PDPT @ pa=0x%llx", __func__, (uint64_t)npa); /* npa = physaddr of PD page */ npa = pd[l3idx] & PMAP_PA_MASK; /* Valid PDPTe for the 1GB region containing gpa? */ if (!npa) { /* No valid PDPTe - allocate PD page and set PDPTe */ obj = &pmap->pm_obj[1]; /* PDPT UVM object */ ptp = uvm_pagealloc(obj, ptp_va2o(gpa, 2), NULL, UVM_PGA_USERESERVE|UVM_PGA_ZERO); if (ptp == NULL) return ENOMEM; /* * New PD page - we are setting the first entry, so set * the wired count to 1 */ ptp->wire_count = 1; pptp->wire_count++; npa = VM_PAGE_TO_PHYS(ptp); /* * Higher levels get full perms; specific permissions are * entered at the lowest level. */ pd[l3idx] = (npa | EPT_R | EPT_W | EPT_X); pmap->pm_stats.resident_count++; pptp = ptp; } else { /* Already allocated PDPTe */ pptp = PHYS_TO_VM_PAGE(npa); } pd = (pd_entry_t *)PMAP_DIRECT_MAP(npa); if (pd == NULL) panic("%s: can't locate PD page @ pa=0x%llx", __func__, (uint64_t)npa); /* npa = physaddr of PT page */ npa = pd[l2idx] & PMAP_PA_MASK; /* Valid PDE for the 2MB region containing gpa? */ if (!npa) { /* No valid PDE - allocate PT page and set PDE */ obj = &pmap->pm_obj[0]; /* PDE UVM object */ ptp = uvm_pagealloc(obj, ptp_va2o(gpa, 1), NULL, UVM_PGA_USERESERVE|UVM_PGA_ZERO); if (ptp == NULL) return ENOMEM; pptp->wire_count++; npa = VM_PAGE_TO_PHYS(ptp); /* * Higher level get full perms; specific permissions are * entered at the lowest level. */ pd[l2idx] = (npa | EPT_R | EPT_W | EPT_X); pmap->pm_stats.resident_count++; } else { /* Find final ptp */ ptp = PHYS_TO_VM_PAGE(npa); if (ptp == NULL) panic("%s: ptp page vanished?", __func__); } pd = (pd_entry_t *)PMAP_DIRECT_MAP(npa); if (pd == NULL) panic("%s: can't locate PT page @ pa=0x%llx", __func__, (uint64_t)npa); npte = hpa | EPT_WB; if (prot & PROT_READ) npte |= EPT_R; if (prot & PROT_WRITE) npte |= EPT_W; if (prot & PROT_EXEC) npte |= EPT_X; if (pd[l1idx] == 0) { ptp->wire_count++; pmap->pm_stats.resident_count++; } else { /* XXX flush ept */ } pd[l1idx] = npte; return 0; } /* * pmap_enter: enter a mapping into a pmap * * => must be done "now" ... no lazy-evaluation */ int pmap_enter(struct pmap *pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags) { pt_entry_t opte, npte; struct vm_page *ptp, *pg = NULL; struct pv_entry *pve, *opve = NULL; int ptpdelta, wireddelta, resdelta; int wired = (flags & PMAP_WIRED) != 0; int nocache = (pa & PMAP_NOCACHE) != 0; int wc = (pa & PMAP_WC) != 0; int error, shootself; paddr_t scr3; if (pmap->pm_type == PMAP_TYPE_EPT) return pmap_enter_ept(pmap, va, pa, prot); KASSERT(!(wc && nocache)); pa &= PMAP_PA_MASK; #ifdef DIAGNOSTIC if (va == (vaddr_t) PDP_BASE) panic("%s: trying to map over PDP!", __func__); /* sanity check: kernel PTPs should already have been pre-allocated */ if (va >= VM_MIN_KERNEL_ADDRESS && !pmap_valid_entry(pmap->pm_pdir[pl_i(va, PTP_LEVELS)])) panic("%s: missing kernel PTP for va %lx!", __func__, va); #endif pve = pool_get(&pmap_pv_pool, PR_NOWAIT); if (pve == NULL) { if (flags & PMAP_CANFAIL) { error = ENOMEM; goto out; } panic("%s: no pv entries available", __func__); } /* * map in ptes and get a pointer to our PTP (unless we are the kernel) */ scr3 = pmap_map_ptes(pmap); shootself = (scr3 == 0); if (pmap == pmap_kernel()) { ptp = NULL; } else { ptp = pmap_get_ptp(pmap, va); if (ptp == NULL) { if (flags & PMAP_CANFAIL) { pmap_unmap_ptes(pmap, scr3); error = ENOMEM; goto out; } panic("%s: get ptp failed", __func__); } } opte = PTE_BASE[pl1_i(va)]; /* old PTE */ /* * is there currently a valid mapping at our VA? */ if (pmap_valid_entry(opte)) { /* * first, calculate pm_stats updates. resident count will not * change since we are replacing/changing a valid mapping. * wired count might change... */ resdelta = 0; if (wired && (opte & PG_W) == 0) wireddelta = 1; else if (!wired && (opte & PG_W) != 0) wireddelta = -1; else wireddelta = 0; ptpdelta = 0; /* * is the currently mapped PA the same as the one we * want to map? */ if ((opte & PG_FRAME) == pa) { /* if this is on the PVLIST, sync R/M bit */ if (opte & PG_PVLIST) { pg = PHYS_TO_VM_PAGE(pa); #ifdef DIAGNOSTIC if (pg == NULL) panic("%s: same pa, PG_PVLIST " "mapping with unmanaged page: " "va 0x%lx, opte 0x%llx, pa 0x%lx", __func__, va, opte, pa); #endif pmap_sync_flags_pte(pg, opte); } else { #ifdef DIAGNOSTIC if (PHYS_TO_VM_PAGE(pa) != NULL) panic("%s: same pa, no PG_PVLIST " "mapping with managed page: " "va 0x%lx, opte 0x%llx, pa 0x%lx", __func__, va, opte, pa); #endif } goto enter_now; } /* * changing PAs: we must remove the old one first */ /* * if current mapping is on a pvlist, * remove it (sync R/M bits) */ if (opte & PG_PVLIST) { pg = PHYS_TO_VM_PAGE(opte & PG_FRAME); #ifdef DIAGNOSTIC if (pg == NULL) panic("%s: PG_PVLIST mapping with unmanaged " "page: va 0x%lx, opte 0x%llx, pa 0x%lx", __func__, va, opte, pa); #endif pmap_sync_flags_pte(pg, opte); opve = pmap_remove_pv(pg, pmap, va); pg = NULL; /* This is not the page we are looking for */ } } else { /* opte not valid */ resdelta = 1; if (wired) wireddelta = 1; else wireddelta = 0; if (ptp != NULL) ptpdelta = 1; else ptpdelta = 0; } /* * pve is either NULL or points to a now-free pv_entry structure * (the latter case is if we called pmap_remove_pv above). * * if this entry is to be on a pvlist, enter it now. */ if (pmap_initialized) pg = PHYS_TO_VM_PAGE(pa); if (pg != NULL) { pmap_enter_pv(pg, pve, pmap, va, ptp); pve = NULL; } enter_now: /* * at this point pg is !NULL if we want the PG_PVLIST bit set */ pmap->pm_stats.resident_count += resdelta; pmap->pm_stats.wired_count += wireddelta; if (ptp != NULL) ptp->wire_count += ptpdelta; KASSERT(pg == PHYS_TO_VM_PAGE(pa)); npte = pa | protection_codes[prot] | PG_V; if (pg != NULL) { npte |= PG_PVLIST; /* * make sure that if the page is write combined all * instances of pmap_enter make it so. */ if (pg->pg_flags & PG_PMAP_WC) { KASSERT(nocache == 0); wc = 1; } } if (wc) npte |= pmap_pg_wc; if (wired) npte |= PG_W; if (nocache) npte |= PG_N; if (va < VM_MAXUSER_ADDRESS) npte |= ((flags & PMAP_EFI) ? 0 : PG_u); else if (va < VM_MAX_ADDRESS) npte |= (PG_u | PG_RW); /* XXXCDC: no longer needed? */ if (pmap == pmap_kernel()) npte |= pg_g_kern; /* * If the old entry wasn't valid, we can just update it and * go. If it was valid, and this isn't a read->write * transition, then we can safely just update it and flush * any old TLB entries. * * If it _was_ valid and this _is_ a read->write transition, * then this could be a CoW resolution and we need to make * sure no CPU can see the new writable mapping while another * still has the old mapping in its TLB, so insert a correct * but unwritable mapping, flush any old TLB entries, then * make it writable. */ if (! pmap_valid_entry(opte)) { PTE_BASE[pl1_i(va)] = npte; } else if ((opte | (npte ^ PG_RW)) & PG_RW) { /* previously writable or not making writable */ PTE_BASE[pl1_i(va)] = npte; if (nocache && (opte & PG_N) == 0) wbinvd_on_all_cpus(); pmap_tlb_shootpage(pmap, va, shootself); } else { PTE_BASE[pl1_i(va)] = npte ^ PG_RW; if (nocache && (opte & PG_N) == 0) /* XXX impossible? */ wbinvd_on_all_cpus(); pmap_tlb_shootpage(pmap, va, shootself); pmap_tlb_shootwait(); PTE_BASE[pl1_i(va)] = npte; } pmap_unmap_ptes(pmap, scr3); pmap_tlb_shootwait(); error = 0; out: if (pve != NULL) pool_put(&pmap_pv_pool, pve); if (opve != NULL) pool_put(&pmap_pv_pool, opve); return error; } int pmap_get_physpage(vaddr_t va, int level, paddr_t *paddrp) { struct vm_page *ptp; struct pmap *kpm = pmap_kernel(); if (uvm.page_init_done == 0) { vaddr_t va; /* * we're growing the kernel pmap early (from * uvm_pageboot_alloc()). this case must be * handled a little differently. */ va = pmap_steal_memory(PAGE_SIZE, NULL, NULL); *paddrp = PMAP_DIRECT_UNMAP(va); } else { ptp = uvm_pagealloc(&kpm->pm_obj[level - 1], ptp_va2o(va, level), NULL, UVM_PGA_USERESERVE|UVM_PGA_ZERO); if (ptp == NULL) panic("%s: out of memory", __func__); atomic_clearbits_int(&ptp->pg_flags, PG_BUSY); ptp->wire_count = 1; *paddrp = VM_PAGE_TO_PHYS(ptp); } kpm->pm_stats.resident_count++; return 1; } /* * Allocate the amount of specified ptps for a ptp level, and populate * all levels below accordingly, mapping virtual addresses starting at * kva. * * Used by pmap_growkernel. */ void pmap_alloc_level(vaddr_t kva, int lvl, long *needed_ptps) { unsigned long i; vaddr_t va; paddr_t pa; unsigned long index, endindex; int level; pd_entry_t *pdep; for (level = lvl; level > 1; level--) { if (level == PTP_LEVELS) pdep = pmap_kernel()->pm_pdir; else pdep = normal_pdes[level - 2]; va = kva; index = pl_i(kva, level); endindex = index + needed_ptps[level - 1]; /* * XXX special case for first time call. */ if (nkptp[level - 1] != 0) index++; else endindex--; for (i = index; i <= endindex; i++) { pmap_get_physpage(va, level - 1, &pa); pdep[i] = pa | PG_RW | PG_V | pg_nx; nkptp[level - 1]++; va += nbpd[level - 1]; } } } /* * pmap_growkernel: increase usage of KVM space * * => we allocate new PTPs for the kernel and install them in all * the pmaps on the system. */ static vaddr_t pmap_maxkvaddr = VM_MIN_KERNEL_ADDRESS; vaddr_t pmap_growkernel(vaddr_t maxkvaddr) { struct pmap *kpm = pmap_kernel(), *pm; int s, i; unsigned newpdes; long needed_kptp[PTP_LEVELS], target_nptp, old; if (maxkvaddr <= pmap_maxkvaddr) return pmap_maxkvaddr; maxkvaddr = x86_round_pdr(maxkvaddr); old = nkptp[PTP_LEVELS - 1]; /* * This loop could be optimized more, but pmap_growkernel() * is called infrequently. */ for (i = PTP_LEVELS - 1; i >= 1; i--) { target_nptp = pl_i(maxkvaddr, i + 1) - pl_i(VM_MIN_KERNEL_ADDRESS, i + 1); /* * XXX only need to check toplevel. */ if (target_nptp > nkptpmax[i]) panic("%s: out of KVA space", __func__); needed_kptp[i] = target_nptp - nkptp[i] + 1; } s = splhigh(); /* to be safe */ pmap_alloc_level(pmap_maxkvaddr, PTP_LEVELS, needed_kptp); /* * If the number of top level entries changed, update all * pmaps. */ if (needed_kptp[PTP_LEVELS - 1] != 0) { newpdes = nkptp[PTP_LEVELS - 1] - old; mtx_enter(&pmaps_lock); LIST_FOREACH(pm, &pmaps, pm_list) { memcpy(&pm->pm_pdir[PDIR_SLOT_KERN + old], &kpm->pm_pdir[PDIR_SLOT_KERN + old], newpdes * sizeof (pd_entry_t)); } mtx_leave(&pmaps_lock); } pmap_maxkvaddr = maxkvaddr; splx(s); return maxkvaddr; } vaddr_t pmap_steal_memory(vsize_t size, vaddr_t *start, vaddr_t *end) { int segno; u_int npg; vaddr_t va; paddr_t pa; struct vm_physseg *seg; size = round_page(size); npg = atop(size); for (segno = 0, seg = vm_physmem; segno < vm_nphysseg; segno++, seg++) { if (seg->avail_end - seg->avail_start < npg) continue; /* * We can only steal at an ``unused'' segment boundary, * i.e. either at the start or at the end. */ if (seg->avail_start == seg->start || seg->avail_end == seg->end) break; } if (segno == vm_nphysseg) { panic("%s: out of memory", __func__); } else { if (seg->avail_start == seg->start) { pa = ptoa(seg->avail_start); seg->avail_start += npg; seg->start += npg; } else { pa = ptoa(seg->avail_end) - size; seg->avail_end -= npg; seg->end -= npg; } /* * If all the segment has been consumed now, remove it. * Note that the crash dump code still knows about it * and will dump it correctly. */ if (seg->start == seg->end) { if (vm_nphysseg-- == 1) panic("%s: out of memory", __func__); while (segno < vm_nphysseg) { seg[0] = seg[1]; /* struct copy */ seg++; segno++; } } va = PMAP_DIRECT_MAP(pa); memset((void *)va, 0, size); } if (start != NULL) *start = virtual_avail; if (end != NULL) *end = VM_MAX_KERNEL_ADDRESS; return (va); } /* * pmap_convert * * Converts 'pmap' to the new 'mode'. * * Parameters: * pmap: the pmap to convert * mode: the new mode (see pmap.h, PMAP_TYPE_xxx) */ void pmap_convert(struct pmap *pmap, int mode) { pt_entry_t *pte; mtx_enter(&pmap->pm_mtx); pmap->pm_type = mode; if (mode == PMAP_TYPE_EPT) { /* Clear PML4 */ pte = (pt_entry_t *)pmap->pm_pdir; memset(pte, 0, PAGE_SIZE); /* Give back the meltdown pdir */ if (pmap->pm_pdir_intel != NULL) { pool_put(&pmap_pdp_pool, pmap->pm_pdir_intel); pmap->pm_pdir_intel = NULL; } } mtx_leave(&pmap->pm_mtx); } #ifdef MULTIPROCESSOR /* * Locking for tlb shootdown. * * We lock by setting tlb_shoot_wait to the number of cpus that will * receive our tlb shootdown. After sending the IPIs, we don't need to * worry about locking order or interrupts spinning for the lock because * the call that grabs the "lock" isn't the one that releases it. And * there is nothing that can block the IPI that releases the lock. * * The functions are organized so that we first count the number of * cpus we need to send the IPI to, then we grab the counter, then * we send the IPIs, then we finally do our own shootdown. * * Our shootdown is last to make it parallel with the other cpus * to shorten the spin time. * * Notice that we depend on failures to send IPIs only being able to * happen during boot. If they happen later, the above assumption * doesn't hold since we can end up in situations where noone will * release the lock if we get an interrupt in a bad moment. */ #ifdef MP_LOCKDEBUG #include <ddb/db_output.h> extern int __mp_lock_spinout; #endif volatile long tlb_shoot_wait __attribute__((section(".kudata"))); volatile vaddr_t tlb_shoot_addr1 __attribute__((section(".kudata"))); volatile vaddr_t tlb_shoot_addr2 __attribute__((section(".kudata"))); volatile int tlb_shoot_first_pcid __attribute__((section(".kudata"))); /* Obtain the "lock" for TLB shooting */ static inline int pmap_start_tlb_shoot(long wait, const char *func) { int s = splvm(); while (atomic_cas_ulong(&tlb_shoot_wait, 0, wait) != 0) { #ifdef MP_LOCKDEBUG int nticks = __mp_lock_spinout; #endif while (tlb_shoot_wait != 0) { CPU_BUSY_CYCLE(); #ifdef MP_LOCKDEBUG if (--nticks <= 0) { db_printf("%s: spun out", func); db_enter(); nticks = __mp_lock_spinout; } #endif } } return s; } void pmap_tlb_shootpage(struct pmap *pm, vaddr_t va, int shootself) { struct cpu_info *ci, *self = curcpu(); CPU_INFO_ITERATOR cii; long wait = 0; u_int64_t mask = 0; int is_kva = va >= VM_MIN_KERNEL_ADDRESS; CPU_INFO_FOREACH(cii, ci) { if (ci == self || !(ci->ci_flags & CPUF_RUNNING)) continue; if (!is_kva && !pmap_is_active(pm, ci)) continue; mask |= (1ULL << ci->ci_cpuid); wait++; } if (wait > 0) { int s = pmap_start_tlb_shoot(wait, __func__); tlb_shoot_first_pcid = is_kva ? PCID_KERN : PCID_PROC; tlb_shoot_addr1 = va; CPU_INFO_FOREACH(cii, ci) { if ((mask & (1ULL << ci->ci_cpuid)) == 0) continue; if (x86_fast_ipi(ci, LAPIC_IPI_INVLPG) != 0) panic("%s: ipi failed", __func__); } splx(s); } if (!pmap_use_pcid) { if (shootself) pmap_update_pg(va); } else if (is_kva) { invpcid(INVPCID_ADDR, PCID_PROC, va); invpcid(INVPCID_ADDR, PCID_KERN, va); } else if (shootself) { invpcid(INVPCID_ADDR, PCID_PROC, va); if (cpu_meltdown) invpcid(INVPCID_ADDR, PCID_PROC_INTEL, va); } } void pmap_tlb_shootrange(struct pmap *pm, vaddr_t sva, vaddr_t eva, int shootself) { struct cpu_info *ci, *self = curcpu(); CPU_INFO_ITERATOR cii; long wait = 0; u_int64_t mask = 0; int is_kva = sva >= VM_MIN_KERNEL_ADDRESS; vaddr_t va; CPU_INFO_FOREACH(cii, ci) { if (ci == self || !(ci->ci_flags & CPUF_RUNNING)) continue; if (!is_kva && !pmap_is_active(pm, ci)) continue; mask |= (1ULL << ci->ci_cpuid); wait++; } if (wait > 0) { int s = pmap_start_tlb_shoot(wait, __func__); tlb_shoot_first_pcid = is_kva ? PCID_KERN : PCID_PROC; tlb_shoot_addr1 = sva; tlb_shoot_addr2 = eva; CPU_INFO_FOREACH(cii, ci) { if ((mask & (1ULL << ci->ci_cpuid)) == 0) continue; if (x86_fast_ipi(ci, LAPIC_IPI_INVLRANGE) != 0) panic("%s: ipi failed", __func__); } splx(s); } if (!pmap_use_pcid) { if (shootself) { for (va = sva; va < eva; va += PAGE_SIZE) pmap_update_pg(va); } } else if (is_kva) { for (va = sva; va < eva; va += PAGE_SIZE) { invpcid(INVPCID_ADDR, PCID_PROC, va); invpcid(INVPCID_ADDR, PCID_KERN, va); } } else if (shootself) { if (cpu_meltdown) { for (va = sva; va < eva; va += PAGE_SIZE) { invpcid(INVPCID_ADDR, PCID_PROC, va); invpcid(INVPCID_ADDR, PCID_PROC_INTEL, va); } } else { for (va = sva; va < eva; va += PAGE_SIZE) invpcid(INVPCID_ADDR, PCID_PROC, va); } } } void pmap_tlb_shoottlb(struct pmap *pm, int shootself) { struct cpu_info *ci, *self = curcpu(); CPU_INFO_ITERATOR cii; long wait = 0; u_int64_t mask = 0; KASSERT(pm != pmap_kernel()); CPU_INFO_FOREACH(cii, ci) { if (ci == self || !pmap_is_active(pm, ci) || !(ci->ci_flags & CPUF_RUNNING)) continue; mask |= (1ULL << ci->ci_cpuid); wait++; } if (wait) { int s = pmap_start_tlb_shoot(wait, __func__); CPU_INFO_FOREACH(cii, ci) { if ((mask & (1ULL << ci->ci_cpuid)) == 0) continue; if (x86_fast_ipi(ci, LAPIC_IPI_INVLTLB) != 0) panic("%s: ipi failed", __func__); } splx(s); } if (shootself) { if (!pmap_use_pcid) tlbflush(); else { invpcid(INVPCID_PCID, PCID_PROC, 0); if (cpu_meltdown) invpcid(INVPCID_PCID, PCID_PROC_INTEL, 0); } } } void pmap_tlb_shootwait(void) { #ifdef MP_LOCKDEBUG int nticks = __mp_lock_spinout; #endif while (tlb_shoot_wait != 0) { CPU_BUSY_CYCLE(); #ifdef MP_LOCKDEBUG if (--nticks <= 0) { db_printf("%s: spun out", __func__); db_enter(); nticks = __mp_lock_spinout; } #endif } } #else /* MULTIPROCESSOR */ void pmap_tlb_shootpage(struct pmap *pm, vaddr_t va, int shootself) { if (!pmap_use_pcid) { if (shootself) pmap_update_pg(va); } else if (va >= VM_MIN_KERNEL_ADDRESS) { invpcid(INVPCID_ADDR, PCID_PROC, va); invpcid(INVPCID_ADDR, PCID_KERN, va); } else if (shootself) { invpcid(INVPCID_ADDR, PCID_PROC, va); if (cpu_meltdown) invpcid(INVPCID_ADDR, PCID_PROC_INTEL, va); } } void pmap_tlb_shootrange(struct pmap *pm, vaddr_t sva, vaddr_t eva, int shootself) { vaddr_t va; if (!pmap_use_pcid) { if (shootself) { for (va = sva; va < eva; va += PAGE_SIZE) pmap_update_pg(va); } } else if (sva >= VM_MIN_KERNEL_ADDRESS) { for (va = sva; va < eva; va += PAGE_SIZE) { invpcid(INVPCID_ADDR, PCID_PROC, va); invpcid(INVPCID_ADDR, PCID_KERN, va); } } else if (shootself) { if (cpu_meltdown) { for (va = sva; va < eva; va += PAGE_SIZE) { invpcid(INVPCID_ADDR, PCID_PROC, va); invpcid(INVPCID_ADDR, PCID_PROC_INTEL, va); } } else { for (va = sva; va < eva; va += PAGE_SIZE) invpcid(INVPCID_ADDR, PCID_PROC, va); } } } void pmap_tlb_shoottlb(struct pmap *pm, int shootself) { if (shootself) { if (!pmap_use_pcid) tlbflush(); else { invpcid(INVPCID_PCID, PCID_PROC, 0); if (cpu_meltdown) invpcid(INVPCID_PCID, PCID_PROC_INTEL, 0); } } } #endif /* MULTIPROCESSOR */
11 11 11 60 11 60 11 11 17 17 21 21 21 15 15 15 51 244 181 63 244 92 11 11 11 11 11 11 78 3 74 1 76 7 2 5 19 19 21 21 15 15 15 50 46 44 2 2 15 244 244 92 93 85 85 24 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 /* $OpenBSD: ifq.c,v 1.53 2023/11/10 15:51:24 bluhm Exp $ */ /* * Copyright (c) 2015 David Gwynne <dlg@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "bpfilter.h" #include "kstat.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/socket.h> #include <sys/mbuf.h> #include <sys/proc.h> #include <sys/sysctl.h> #include <net/if.h> #include <net/if_var.h> #if NBPFILTER > 0 #include <net/bpf.h> #endif #if NKSTAT > 0 #include <sys/kstat.h> #endif /* * priq glue */ unsigned int priq_idx(unsigned int, const struct mbuf *); struct mbuf *priq_enq(struct ifqueue *, struct mbuf *); struct mbuf *priq_deq_begin(struct ifqueue *, void **); void priq_deq_commit(struct ifqueue *, struct mbuf *, void *); void priq_purge(struct ifqueue *, struct mbuf_list *); void *priq_alloc(unsigned int, void *); void priq_free(unsigned int, void *); const struct ifq_ops priq_ops = { priq_idx, priq_enq, priq_deq_begin, priq_deq_commit, priq_purge, priq_alloc, priq_free, }; const struct ifq_ops * const ifq_priq_ops = &priq_ops; /* * priq internal structures */ struct priq { struct mbuf_list pq_lists[IFQ_NQUEUES]; }; /* * ifqueue serialiser */ void ifq_start_task(void *); void ifq_restart_task(void *); void ifq_barrier_task(void *); void ifq_bundle_task(void *); static inline void ifq_run_start(struct ifqueue *ifq) { ifq_serialize(ifq, &ifq->ifq_start); } void ifq_serialize(struct ifqueue *ifq, struct task *t) { struct task work; if (ISSET(t->t_flags, TASK_ONQUEUE)) return; mtx_enter(&ifq->ifq_task_mtx); if (!ISSET(t->t_flags, TASK_ONQUEUE)) { SET(t->t_flags, TASK_ONQUEUE); TAILQ_INSERT_TAIL(&ifq->ifq_task_list, t, t_entry); } if (ifq->ifq_serializer == NULL) { ifq->ifq_serializer = curcpu(); while ((t = TAILQ_FIRST(&ifq->ifq_task_list)) != NULL) { TAILQ_REMOVE(&ifq->ifq_task_list, t, t_entry); CLR(t->t_flags, TASK_ONQUEUE); work = *t; /* copy to caller to avoid races */ mtx_leave(&ifq->ifq_task_mtx); (*work.t_func)(work.t_arg); mtx_enter(&ifq->ifq_task_mtx); } ifq->ifq_serializer = NULL; } mtx_leave(&ifq->ifq_task_mtx); } int ifq_is_serialized(struct ifqueue *ifq) { return (ifq->ifq_serializer == curcpu()); } void ifq_start(struct ifqueue *ifq) { if (ifq_len(ifq) >= min(ifq->ifq_if->if_txmit, ifq->ifq_maxlen)) { task_del(ifq->ifq_softnet, &ifq->ifq_bundle); ifq_run_start(ifq); } else task_add(ifq->ifq_softnet, &ifq->ifq_bundle); } void ifq_start_task(void *p) { struct ifqueue *ifq = p; struct ifnet *ifp = ifq->ifq_if; if (!ISSET(ifp->if_flags, IFF_RUNNING) || ifq_empty(ifq) || ifq_is_oactive(ifq)) return; ifp->if_qstart(ifq); } void ifq_set_oactive(struct ifqueue *ifq) { if (ifq->ifq_oactive) return; mtx_enter(&ifq->ifq_mtx); if (!ifq->ifq_oactive) { ifq->ifq_oactive = 1; ifq->ifq_oactives++; } mtx_leave(&ifq->ifq_mtx); } void ifq_restart_task(void *p) { struct ifqueue *ifq = p; struct ifnet *ifp = ifq->ifq_if; ifq_clr_oactive(ifq); ifp->if_qstart(ifq); } void ifq_bundle_task(void *p) { struct ifqueue *ifq = p; ifq_run_start(ifq); } void ifq_barrier(struct ifqueue *ifq) { struct cond c = COND_INITIALIZER(); struct task t = TASK_INITIALIZER(ifq_barrier_task, &c); task_del(ifq->ifq_softnet, &ifq->ifq_bundle); if (ifq->ifq_serializer == NULL) return; ifq_serialize(ifq, &t); cond_wait(&c, "ifqbar"); } void ifq_barrier_task(void *p) { struct cond *c = p; cond_signal(c); } /* * ifqueue mbuf queue API */ #if NKSTAT > 0 struct ifq_kstat_data { struct kstat_kv kd_packets; struct kstat_kv kd_bytes; struct kstat_kv kd_qdrops; struct kstat_kv kd_errors; struct kstat_kv kd_qlen; struct kstat_kv kd_maxqlen; struct kstat_kv kd_oactive; struct kstat_kv kd_oactives; }; static const struct ifq_kstat_data ifq_kstat_tpl = { KSTAT_KV_UNIT_INITIALIZER("packets", KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), KSTAT_KV_UNIT_INITIALIZER("bytes", KSTAT_KV_T_COUNTER64, KSTAT_KV_U_BYTES), KSTAT_KV_UNIT_INITIALIZER("qdrops", KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), KSTAT_KV_UNIT_INITIALIZER("errors", KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), KSTAT_KV_UNIT_INITIALIZER("qlen", KSTAT_KV_T_UINT32, KSTAT_KV_U_PACKETS), KSTAT_KV_UNIT_INITIALIZER("maxqlen", KSTAT_KV_T_UINT32, KSTAT_KV_U_PACKETS), KSTAT_KV_INITIALIZER("oactive", KSTAT_KV_T_BOOL), KSTAT_KV_INITIALIZER("oactives", KSTAT_KV_T_COUNTER32), }; int ifq_kstat_copy(struct kstat *ks, void *dst) { struct ifqueue *ifq = ks->ks_softc; struct ifq_kstat_data *kd = dst; *kd = ifq_kstat_tpl; kstat_kv_u64(&kd->kd_packets) = ifq->ifq_packets; kstat_kv_u64(&kd->kd_bytes) = ifq->ifq_bytes; kstat_kv_u64(&kd->kd_qdrops) = ifq->ifq_qdrops; kstat_kv_u64(&kd->kd_errors) = ifq->ifq_errors; kstat_kv_u32(&kd->kd_qlen) = ifq->ifq_len; kstat_kv_u32(&kd->kd_maxqlen) = ifq->ifq_maxlen; kstat_kv_bool(&kd->kd_oactive) = ifq->ifq_oactive; kstat_kv_u32(&kd->kd_oactives) = ifq->ifq_oactives; return (0); } #endif void ifq_init(struct ifqueue *ifq, struct ifnet *ifp, unsigned int idx) { ifq->ifq_if = ifp; ifq->ifq_softnet = net_tq(idx); ifq->ifq_softc = NULL; mtx_init(&ifq->ifq_mtx, IPL_NET); /* default to priq */ ifq->ifq_ops = &priq_ops; ifq->ifq_q = priq_ops.ifqop_alloc(idx, NULL); ml_init(&ifq->ifq_free); ifq->ifq_len = 0; ifq->ifq_packets = 0; ifq->ifq_bytes = 0; ifq->ifq_qdrops = 0; ifq->ifq_errors = 0; ifq->ifq_mcasts = 0; mtx_init(&ifq->ifq_task_mtx, IPL_NET); TAILQ_INIT(&ifq->ifq_task_list); ifq->ifq_serializer = NULL; task_set(&ifq->ifq_bundle, ifq_bundle_task, ifq); task_set(&ifq->ifq_start, ifq_start_task, ifq); task_set(&ifq->ifq_restart, ifq_restart_task, ifq); if (ifq->ifq_maxlen == 0) ifq_init_maxlen(ifq, IFQ_MAXLEN); ifq->ifq_idx = idx; #if NKSTAT > 0 /* XXX xname vs driver name and unit */ ifq->ifq_kstat = kstat_create(ifp->if_xname, 0, "txq", ifq->ifq_idx, KSTAT_T_KV, 0); KASSERT(ifq->ifq_kstat != NULL); kstat_set_mutex(ifq->ifq_kstat, &ifq->ifq_mtx); ifq->ifq_kstat->ks_softc = ifq; ifq->ifq_kstat->ks_datalen = sizeof(ifq_kstat_tpl); ifq->ifq_kstat->ks_copy = ifq_kstat_copy; kstat_install(ifq->ifq_kstat); #endif } void ifq_attach(struct ifqueue *ifq, const struct ifq_ops *newops, void *opsarg) { struct mbuf_list ml = MBUF_LIST_INITIALIZER(); struct mbuf_list free_ml = MBUF_LIST_INITIALIZER(); struct mbuf *m; const struct ifq_ops *oldops; void *newq, *oldq; newq = newops->ifqop_alloc(ifq->ifq_idx, opsarg); mtx_enter(&ifq->ifq_mtx); ifq->ifq_ops->ifqop_purge(ifq, &ml); ifq->ifq_len = 0; oldops = ifq->ifq_ops; oldq = ifq->ifq_q; ifq->ifq_ops = newops; ifq->ifq_q = newq; while ((m = ml_dequeue(&ml)) != NULL) { m = ifq->ifq_ops->ifqop_enq(ifq, m); if (m != NULL) { ifq->ifq_qdrops++; ml_enqueue(&free_ml, m); } else ifq->ifq_len++; } mtx_leave(&ifq->ifq_mtx); oldops->ifqop_free(ifq->ifq_idx, oldq); ml_purge(&free_ml); } void ifq_destroy(struct ifqueue *ifq) { struct mbuf_list ml = MBUF_LIST_INITIALIZER(); #if NKSTAT > 0 kstat_destroy(ifq->ifq_kstat); #endif NET_ASSERT_UNLOCKED(); if (!task_del(ifq->ifq_softnet, &ifq->ifq_bundle)) taskq_barrier(ifq->ifq_softnet); /* don't need to lock because this is the last use of the ifq */ ifq->ifq_ops->ifqop_purge(ifq, &ml); ifq->ifq_ops->ifqop_free(ifq->ifq_idx, ifq->ifq_q); ml_purge(&ml); } void ifq_add_data(struct ifqueue *ifq, struct if_data *data) { mtx_enter(&ifq->ifq_mtx); data->ifi_opackets += ifq->ifq_packets; data->ifi_obytes += ifq->ifq_bytes; data->ifi_oqdrops += ifq->ifq_qdrops; data->ifi_omcasts += ifq->ifq_mcasts; /* ifp->if_data.ifi_oerrors */ mtx_leave(&ifq->ifq_mtx); } int ifq_enqueue(struct ifqueue *ifq, struct mbuf *m) { struct mbuf *dm; mtx_enter(&ifq->ifq_mtx); dm = ifq->ifq_ops->ifqop_enq(ifq, m); if (dm != m) { ifq->ifq_packets++; ifq->ifq_bytes += m->m_pkthdr.len; if (ISSET(m->m_flags, M_MCAST)) ifq->ifq_mcasts++; } if (dm == NULL) ifq->ifq_len++; else ifq->ifq_qdrops++; mtx_leave(&ifq->ifq_mtx); if (dm != NULL) m_freem(dm); return (dm == m ? ENOBUFS : 0); } static inline void ifq_deq_enter(struct ifqueue *ifq) { mtx_enter(&ifq->ifq_mtx); } static inline void ifq_deq_leave(struct ifqueue *ifq) { struct mbuf_list ml; ml = ifq->ifq_free; ml_init(&ifq->ifq_free); mtx_leave(&ifq->ifq_mtx); if (!ml_empty(&ml)) ml_purge(&ml); } struct mbuf * ifq_deq_begin(struct ifqueue *ifq) { struct mbuf *m = NULL; void *cookie; ifq_deq_enter(ifq); if (ifq->ifq_len == 0 || (m = ifq->ifq_ops->ifqop_deq_begin(ifq, &cookie)) == NULL) { ifq_deq_leave(ifq); return (NULL); } m->m_pkthdr.ph_cookie = cookie; return (m); } void ifq_deq_commit(struct ifqueue *ifq, struct mbuf *m) { void *cookie; KASSERT(m != NULL); cookie = m->m_pkthdr.ph_cookie; ifq->ifq_ops->ifqop_deq_commit(ifq, m, cookie); ifq->ifq_len--; ifq_deq_leave(ifq); } void ifq_deq_rollback(struct ifqueue *ifq, struct mbuf *m) { KASSERT(m != NULL); ifq_deq_leave(ifq); } struct mbuf * ifq_dequeue(struct ifqueue *ifq) { struct mbuf *m; m = ifq_deq_begin(ifq); if (m == NULL) return (NULL); ifq_deq_commit(ifq, m); return (m); } int ifq_deq_sleep(struct ifqueue *ifq, struct mbuf **mp, int nbio, int priority, const char *wmesg, volatile unsigned int *sleeping, volatile unsigned int *alive) { struct mbuf *m; void *cookie; int error = 0; ifq_deq_enter(ifq); if (ifq->ifq_len == 0 && nbio) error = EWOULDBLOCK; else { for (;;) { m = ifq->ifq_ops->ifqop_deq_begin(ifq, &cookie); if (m != NULL) { ifq->ifq_ops->ifqop_deq_commit(ifq, m, cookie); ifq->ifq_len--; *mp = m; break; } (*sleeping)++; error = msleep_nsec(ifq, &ifq->ifq_mtx, priority, wmesg, INFSLP); (*sleeping)--; if (error != 0) break; if (!(*alive)) { error = EIO; break; } } } ifq_deq_leave(ifq); return (error); } int ifq_hdatalen(struct ifqueue *ifq) { struct mbuf *m; int len = 0; if (ifq_empty(ifq)) return (0); m = ifq_deq_begin(ifq); if (m != NULL) { len = m->m_pkthdr.len; ifq_deq_rollback(ifq, m); } return (len); } void ifq_init_maxlen(struct ifqueue *ifq, unsigned int maxlen) { /* this is not MP safe, use only during attach */ ifq->ifq_maxlen = maxlen; } unsigned int ifq_purge(struct ifqueue *ifq) { struct mbuf_list ml = MBUF_LIST_INITIALIZER(); unsigned int rv; mtx_enter(&ifq->ifq_mtx); ifq->ifq_ops->ifqop_purge(ifq, &ml); rv = ifq->ifq_len; ifq->ifq_len = 0; ifq->ifq_qdrops += rv; mtx_leave(&ifq->ifq_mtx); KASSERT(rv == ml_len(&ml)); ml_purge(&ml); return (rv); } void * ifq_q_enter(struct ifqueue *ifq, const struct ifq_ops *ops) { mtx_enter(&ifq->ifq_mtx); if (ifq->ifq_ops == ops) return (ifq->ifq_q); mtx_leave(&ifq->ifq_mtx); return (NULL); } void ifq_q_leave(struct ifqueue *ifq, void *q) { KASSERT(q == ifq->ifq_q); mtx_leave(&ifq->ifq_mtx); } void ifq_mfreem(struct ifqueue *ifq, struct mbuf *m) { MUTEX_ASSERT_LOCKED(&ifq->ifq_mtx); ifq->ifq_len--; ifq->ifq_qdrops++; ml_enqueue(&ifq->ifq_free, m); } void ifq_mfreeml(struct ifqueue *ifq, struct mbuf_list *ml) { MUTEX_ASSERT_LOCKED(&ifq->ifq_mtx); ifq->ifq_len -= ml_len(ml); ifq->ifq_qdrops += ml_len(ml); ml_enlist(&ifq->ifq_free, ml); } /* * ifiq */ #if NKSTAT > 0 struct ifiq_kstat_data { struct kstat_kv kd_packets; struct kstat_kv kd_bytes; struct kstat_kv kd_fdrops; struct kstat_kv kd_qdrops; struct kstat_kv kd_errors; struct kstat_kv kd_qlen; struct kstat_kv kd_enqueues; struct kstat_kv kd_dequeues; }; static const struct ifiq_kstat_data ifiq_kstat_tpl = { KSTAT_KV_UNIT_INITIALIZER("packets", KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), KSTAT_KV_UNIT_INITIALIZER("bytes", KSTAT_KV_T_COUNTER64, KSTAT_KV_U_BYTES), KSTAT_KV_UNIT_INITIALIZER("fdrops", KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), KSTAT_KV_UNIT_INITIALIZER("qdrops", KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), KSTAT_KV_UNIT_INITIALIZER("errors", KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), KSTAT_KV_UNIT_INITIALIZER("qlen", KSTAT_KV_T_UINT32, KSTAT_KV_U_PACKETS), KSTAT_KV_INITIALIZER("enqueues", KSTAT_KV_T_COUNTER64), KSTAT_KV_INITIALIZER("dequeues", KSTAT_KV_T_COUNTER64), }; int ifiq_kstat_copy(struct kstat *ks, void *dst) { struct ifiqueue *ifiq = ks->ks_softc; struct ifiq_kstat_data *kd = dst; *kd = ifiq_kstat_tpl; kstat_kv_u64(&kd->kd_packets) = ifiq->ifiq_packets; kstat_kv_u64(&kd->kd_bytes) = ifiq->ifiq_bytes; kstat_kv_u64(&kd->kd_fdrops) = ifiq->ifiq_fdrops; kstat_kv_u64(&kd->kd_qdrops) = ifiq->ifiq_qdrops; kstat_kv_u64(&kd->kd_errors) = ifiq->ifiq_errors; kstat_kv_u32(&kd->kd_qlen) = ml_len(&ifiq->ifiq_ml); kstat_kv_u64(&kd->kd_enqueues) = ifiq->ifiq_enqueues; kstat_kv_u64(&kd->kd_dequeues) = ifiq->ifiq_dequeues; return (0); } #endif static void ifiq_process(void *); void ifiq_init(struct ifiqueue *ifiq, struct ifnet *ifp, unsigned int idx) { ifiq->ifiq_if = ifp; ifiq->ifiq_softnet = net_tq(idx); ifiq->ifiq_softc = NULL; mtx_init(&ifiq->ifiq_mtx, IPL_NET); ml_init(&ifiq->ifiq_ml); task_set(&ifiq->ifiq_task, ifiq_process, ifiq); ifiq->ifiq_pressure = 0; ifiq->ifiq_packets = 0; ifiq->ifiq_bytes = 0; ifiq->ifiq_fdrops = 0; ifiq->ifiq_qdrops = 0; ifiq->ifiq_errors = 0; ifiq->ifiq_idx = idx; #if NKSTAT > 0 /* XXX xname vs driver name and unit */ ifiq->ifiq_kstat = kstat_create(ifp->if_xname, 0, "rxq", ifiq->ifiq_idx, KSTAT_T_KV, 0); KASSERT(ifiq->ifiq_kstat != NULL); kstat_set_mutex(ifiq->ifiq_kstat, &ifiq->ifiq_mtx); ifiq->ifiq_kstat->ks_softc = ifiq; ifiq->ifiq_kstat->ks_datalen = sizeof(ifiq_kstat_tpl); ifiq->ifiq_kstat->ks_copy = ifiq_kstat_copy; kstat_install(ifiq->ifiq_kstat); #endif } void ifiq_destroy(struct ifiqueue *ifiq) { #if NKSTAT > 0 kstat_destroy(ifiq->ifiq_kstat); #endif NET_ASSERT_UNLOCKED(); if (!task_del(ifiq->ifiq_softnet, &ifiq->ifiq_task)) taskq_barrier(ifiq->ifiq_softnet); /* don't need to lock because this is the last use of the ifiq */ ml_purge(&ifiq->ifiq_ml); } unsigned int ifiq_maxlen_drop = 2048 * 5; unsigned int ifiq_maxlen_return = 2048 * 3; int ifiq_input(struct ifiqueue *ifiq, struct mbuf_list *ml) { struct ifnet *ifp = ifiq->ifiq_if; struct mbuf *m; uint64_t packets; uint64_t bytes = 0; uint64_t fdrops = 0; unsigned int len; #if NBPFILTER > 0 caddr_t if_bpf; #endif if (ml_empty(ml)) return (0); MBUF_LIST_FOREACH(ml, m) { m->m_pkthdr.ph_ifidx = ifp->if_index; m->m_pkthdr.ph_rtableid = ifp->if_rdomain; bytes += m->m_pkthdr.len; } packets = ml_len(ml); #if NBPFILTER > 0 if_bpf = ifp->if_bpf; if (if_bpf) { struct mbuf_list ml0 = *ml; ml_init(ml); while ((m = ml_dequeue(&ml0)) != NULL) { if ((*ifp->if_bpf_mtap)(if_bpf, m, BPF_DIRECTION_IN)) { m_freem(m); fdrops++; } else ml_enqueue(ml, m); } if (ml_empty(ml)) { mtx_enter(&ifiq->ifiq_mtx); ifiq->ifiq_packets += packets; ifiq->ifiq_bytes += bytes; ifiq->ifiq_fdrops += fdrops; mtx_leave(&ifiq->ifiq_mtx); return (0); } } #endif mtx_enter(&ifiq->ifiq_mtx); ifiq->ifiq_packets += packets; ifiq->ifiq_bytes += bytes; ifiq->ifiq_fdrops += fdrops; len = ml_len(&ifiq->ifiq_ml); if (__predict_true(!ISSET(ifp->if_xflags, IFXF_MONITOR))) { if (len > ifiq_maxlen_drop) ifiq->ifiq_qdrops += ml_len(ml); else { ifiq->ifiq_enqueues++; ml_enlist(&ifiq->ifiq_ml, ml); } } mtx_leave(&ifiq->ifiq_mtx); if (ml_empty(ml)) task_add(ifiq->ifiq_softnet, &ifiq->ifiq_task); else ml_purge(ml); return (len > ifiq_maxlen_return); } void ifiq_add_data(struct ifiqueue *ifiq, struct if_data *data) { mtx_enter(&ifiq->ifiq_mtx); data->ifi_ipackets += ifiq->ifiq_packets; data->ifi_ibytes += ifiq->ifiq_bytes; data->ifi_iqdrops += ifiq->ifiq_qdrops; mtx_leave(&ifiq->ifiq_mtx); } int ifiq_enqueue(struct ifiqueue *ifiq, struct mbuf *m) { struct ifnet *ifp = ifiq->ifiq_if; #if NBPFILTER > 0 caddr_t if_bpf = ifp->if_bpf; #endif m->m_pkthdr.ph_ifidx = ifp->if_index; m->m_pkthdr.ph_rtableid = ifp->if_rdomain; #if NBPFILTER > 0 if_bpf = ifp->if_bpf; if (if_bpf) { if ((*ifp->if_bpf_mtap)(if_bpf, m, BPF_DIRECTION_IN)) { mtx_enter(&ifiq->ifiq_mtx); ifiq->ifiq_packets++; ifiq->ifiq_bytes += m->m_pkthdr.len; ifiq->ifiq_fdrops++; mtx_leave(&ifiq->ifiq_mtx); m_freem(m); return (0); } } #endif mtx_enter(&ifiq->ifiq_mtx); ifiq->ifiq_packets++; ifiq->ifiq_bytes += m->m_pkthdr.len; ifiq->ifiq_enqueues++; ml_enqueue(&ifiq->ifiq_ml, m); mtx_leave(&ifiq->ifiq_mtx); task_add(ifiq->ifiq_softnet, &ifiq->ifiq_task); return (0); } static void ifiq_process(void *arg) { struct ifiqueue *ifiq = arg; struct mbuf_list ml; if (ifiq_empty(ifiq)) return; mtx_enter(&ifiq->ifiq_mtx); ifiq->ifiq_dequeues++; ml = ifiq->ifiq_ml; ml_init(&ifiq->ifiq_ml); mtx_leave(&ifiq->ifiq_mtx); if_input_process(ifiq->ifiq_if, &ml); } int net_ifiq_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int error = EOPNOTSUPP; /* pressure is disabled for 6.6-release */ #if 0 int val; if (namelen != 1) return (EISDIR); switch (name[0]) { case NET_LINK_IFRXQ_PRESSURE_RETURN: val = ifiq_pressure_return; error = sysctl_int(oldp, oldlenp, newp, newlen, &val); if (error != 0) return (error); if (val < 1 || val > ifiq_pressure_drop) return (EINVAL); ifiq_pressure_return = val; break; case NET_LINK_IFRXQ_PRESSURE_DROP: val = ifiq_pressure_drop; error = sysctl_int(oldp, oldlenp, newp, newlen, &val); if (error != 0) return (error); if (ifiq_pressure_return > val) return (EINVAL); ifiq_pressure_drop = val; break; default: error = EOPNOTSUPP; break; } #endif return (error); } /* * priq implementation */ unsigned int priq_idx(unsigned int nqueues, const struct mbuf *m) { unsigned int flow = 0; if (ISSET(m->m_pkthdr.csum_flags, M_FLOWID)) flow = m->m_pkthdr.ph_flowid; return (flow % nqueues); } void * priq_alloc(unsigned int idx, void *null) { struct priq *pq; int i; pq = malloc(sizeof(struct priq), M_DEVBUF, M_WAITOK); for (i = 0; i < IFQ_NQUEUES; i++) ml_init(&pq->pq_lists[i]); return (pq); } void priq_free(unsigned int idx, void *pq) { free(pq, M_DEVBUF, sizeof(struct priq)); } struct mbuf * priq_enq(struct ifqueue *ifq, struct mbuf *m) { struct priq *pq; struct mbuf_list *pl; struct mbuf *n = NULL; unsigned int prio; pq = ifq->ifq_q; KASSERT(m->m_pkthdr.pf.prio <= IFQ_MAXPRIO); /* Find a lower priority queue to drop from */ if (ifq_len(ifq) >= ifq->ifq_maxlen) { for (prio = 0; prio < m->m_pkthdr.pf.prio; prio++) { pl = &pq->pq_lists[prio]; if (ml_len(pl) > 0) { n = ml_dequeue(pl); goto enqueue; } } /* * There's no lower priority queue that we can * drop from so don't enqueue this one. */ return (m); } enqueue: pl = &pq->pq_lists[m->m_pkthdr.pf.prio]; ml_enqueue(pl, m); return (n); } struct mbuf * priq_deq_begin(struct ifqueue *ifq, void **cookiep) { struct priq *pq = ifq->ifq_q; struct mbuf_list *pl; unsigned int prio = nitems(pq->pq_lists); struct mbuf *m; do { pl = &pq->pq_lists[--prio]; m = MBUF_LIST_FIRST(pl); if (m != NULL) { *cookiep = pl; return (m); } } while (prio > 0); return (NULL); } void priq_deq_commit(struct ifqueue *ifq, struct mbuf *m, void *cookie) { struct mbuf_list *pl = cookie; KASSERT(MBUF_LIST_FIRST(pl) == m); ml_dequeue(pl); } void priq_purge(struct ifqueue *ifq, struct mbuf_list *ml) { struct priq *pq = ifq->ifq_q; struct mbuf_list *pl; unsigned int prio = nitems(pq->pq_lists); do { pl = &pq->pq_lists[--prio]; ml_enlist(ml, pl); } while (prio > 0); }
5 1 1 1 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 /* $OpenBSD: pfkeyv2_parsemessage.c,v 1.62 2023/09/29 18:45:42 tobhe Exp $ */ /* * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 * * NRL grants permission for redistribution and use in source and binary * forms, with or without modification, of the software and documentation * created at NRL provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgements: * This product includes software developed by the University of * California, Berkeley and its contributors. * This product includes software developed at the Information * Technology Division, US Naval Research Laboratory. * 4. Neither the name of the NRL nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the US Naval * Research Laboratory (NRL). */ /* * Copyright (c) 1995, 1996, 1997, 1998, 1999 Craig Metz. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "pf.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/socket.h> #include <sys/mbuf.h> #include <sys/proc.h> #include <netinet/ip_ipsp.h> #include <net/pfkeyv2.h> #if NPF > 0 #include <net/if.h> #include <net/pfvar.h> #endif #ifdef ENCDEBUG #define DPRINTF(fmt, args...) \ do { \ if (encdebug) \ printf("%s: " fmt "\n", __func__, ## args); \ } while (0) #else #define DPRINTF(fmt, args...) \ do { } while (0) #endif #define BITMAP_SA (1LL << SADB_EXT_SA) #define BITMAP_LIFETIME_CURRENT (1LL << SADB_EXT_LIFETIME_CURRENT) #define BITMAP_LIFETIME_HARD (1LL << SADB_EXT_LIFETIME_HARD) #define BITMAP_LIFETIME_SOFT (1LL << SADB_EXT_LIFETIME_SOFT) #define BITMAP_ADDRESS_SRC (1LL << SADB_EXT_ADDRESS_SRC) #define BITMAP_ADDRESS_DST (1LL << SADB_EXT_ADDRESS_DST) #define BITMAP_ADDRESS_PROXY (1LL << SADB_EXT_ADDRESS_PROXY) #define BITMAP_KEY_AUTH (1LL << SADB_EXT_KEY_AUTH) #define BITMAP_KEY_ENCRYPT (1LL << SADB_EXT_KEY_ENCRYPT) #define BITMAP_IDENTITY_SRC (1LL << SADB_EXT_IDENTITY_SRC) #define BITMAP_IDENTITY_DST (1LL << SADB_EXT_IDENTITY_DST) #define BITMAP_SENSITIVITY (1LL << SADB_EXT_SENSITIVITY) #define BITMAP_PROPOSAL (1LL << SADB_EXT_PROPOSAL) #define BITMAP_SUPPORTED_AUTH (1LL << SADB_EXT_SUPPORTED_AUTH) #define BITMAP_SUPPORTED_ENCRYPT (1LL << SADB_EXT_SUPPORTED_ENCRYPT) #define BITMAP_SPIRANGE (1LL << SADB_EXT_SPIRANGE) #define BITMAP_LIFETIME (BITMAP_LIFETIME_CURRENT | BITMAP_LIFETIME_HARD | BITMAP_LIFETIME_SOFT) #define BITMAP_ADDRESS (BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST) #define BITMAP_KEY (BITMAP_KEY_AUTH | BITMAP_KEY_ENCRYPT) #define BITMAP_IDENTITY (BITMAP_IDENTITY_SRC | BITMAP_IDENTITY_DST) #define BITMAP_MSG 1 #define BITMAP_X_SRC_MASK (1LL << SADB_X_EXT_SRC_MASK) #define BITMAP_X_DST_MASK (1LL << SADB_X_EXT_DST_MASK) #define BITMAP_X_PROTOCOL (1LL << SADB_X_EXT_PROTOCOL) #define BITMAP_X_SRC_FLOW (1LL << SADB_X_EXT_SRC_FLOW) #define BITMAP_X_DST_FLOW (1LL << SADB_X_EXT_DST_FLOW) #define BITMAP_X_FLOW_TYPE (1LL << SADB_X_EXT_FLOW_TYPE) #define BITMAP_X_SA2 (1LL << SADB_X_EXT_SA2) #define BITMAP_X_DST2 (1LL << SADB_X_EXT_DST2) #define BITMAP_X_POLICY (1LL << SADB_X_EXT_POLICY) #define BITMAP_X_FLOW (BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE) #define BITMAP_X_SUPPORTED_COMP (1LL << SADB_X_EXT_SUPPORTED_COMP) #define BITMAP_X_UDPENCAP (1LL << SADB_X_EXT_UDPENCAP) #define BITMAP_X_LIFETIME_LASTUSE (1LL << SADB_X_EXT_LIFETIME_LASTUSE) #define BITMAP_X_TAG (1LL << SADB_X_EXT_TAG) #define BITMAP_X_TAP (1LL << SADB_X_EXT_TAP) #define BITMAP_X_SATYPE2 (1LL << SADB_X_EXT_SATYPE2) #define BITMAP_X_RDOMAIN (1LL << SADB_X_EXT_RDOMAIN) #define BITMAP_X_COUNTER (1LL << SADB_X_EXT_COUNTER) #define BITMAP_X_MTU (1LL << SADB_X_EXT_MTU) #define BITMAP_X_REPLAY (1LL << SADB_X_EXT_REPLAY) #define BITMAP_X_IFACE (1LL << SADB_X_EXT_IFACE) uint64_t sadb_exts_allowed_in[SADB_MAX+1] = { /* RESERVED */ ~0, /* GETSPI */ BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_SPIRANGE, /* UPDATE */ BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_ADDRESS_PROXY | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN | BITMAP_X_IFACE, /* ADD */ BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_LIFETIME_LASTUSE | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN | BITMAP_X_IFACE, /* DELETE */ BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_X_RDOMAIN, /* GET */ BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_X_RDOMAIN, /* ACQUIRE */ BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | BITMAP_PROPOSAL, /* REGISTER */ 0, /* EXPIRE */ BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST, /* FLUSH */ 0, /* DUMP */ 0, /* X_PROMISC */ 0, /* X_ADDFLOW */ BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY_SRC | BITMAP_IDENTITY_DST | BITMAP_X_FLOW | BITMAP_X_RDOMAIN, /* X_DELFLOW */ BITMAP_X_FLOW | BITMAP_X_RDOMAIN, /* X_GRPSPIS */ BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_SATYPE2 | BITMAP_X_RDOMAIN, /* X_ASKPOLICY */ BITMAP_X_POLICY, }; uint64_t sadb_exts_required_in[SADB_MAX+1] = { /* RESERVED */ 0, /* GETSPI */ BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_SPIRANGE, /* UPDATE */ BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST, /* ADD */ BITMAP_SA | BITMAP_ADDRESS_DST, /* DELETE */ BITMAP_SA | BITMAP_ADDRESS_DST, /* GET */ BITMAP_SA | BITMAP_ADDRESS_DST, /* ACQUIRE */ 0, /* REGISTER */ 0, /* EXPIRE */ BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST, /* FLUSH */ 0, /* DUMP */ 0, /* X_PROMISC */ 0, /* X_ADDFLOW */ BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE, /* X_DELFLOW */ BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE, /* X_GRPSPIS */ BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_SATYPE2, /* X_ASKPOLICY */ BITMAP_X_POLICY, }; const uint64_t sadb_exts_allowed_out[SADB_MAX+1] = { /* RESERVED */ ~0, /* GETSPI */ BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST, /* UPDATE */ BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_ADDRESS_PROXY | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN | BITMAP_X_IFACE, /* ADD */ BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN | BITMAP_X_IFACE, /* DELETE */ BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_X_RDOMAIN, /* GET */ BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_UDPENCAP | BITMAP_X_LIFETIME_LASTUSE | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_FLOW_TYPE | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_COUNTER | BITMAP_X_RDOMAIN | BITMAP_X_MTU | BITMAP_X_REPLAY | BITMAP_X_IFACE, /* ACQUIRE */ BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | BITMAP_PROPOSAL, /* REGISTER */ BITMAP_SUPPORTED_AUTH | BITMAP_SUPPORTED_ENCRYPT | BITMAP_X_SUPPORTED_COMP, /* EXPIRE */ BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS, /* FLUSH */ 0, /* DUMP */ BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY, /* X_PROMISC */ 0, /* X_ADDFLOW */ BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE | BITMAP_IDENTITY_SRC | BITMAP_IDENTITY_DST | BITMAP_X_RDOMAIN, /* X_DELFLOW */ BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE | BITMAP_X_RDOMAIN, /* X_GRPSPIS */ BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_SATYPE2 | BITMAP_X_RDOMAIN, /* X_ASKPOLICY */ BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_FLOW_TYPE | BITMAP_X_POLICY, }; const uint64_t sadb_exts_required_out[SADB_MAX+1] = { /* RESERVED */ 0, /* GETSPI */ BITMAP_SA | BITMAP_ADDRESS_DST, /* UPDATE */ BITMAP_SA | BITMAP_ADDRESS_DST, /* ADD */ BITMAP_SA | BITMAP_ADDRESS_DST, /* DELETE */ BITMAP_SA | BITMAP_ADDRESS_DST, /* GET */ BITMAP_SA | BITMAP_LIFETIME_CURRENT | BITMAP_ADDRESS_DST, /* ACQUIRE */ 0, /* REGISTER */ BITMAP_SUPPORTED_AUTH | BITMAP_SUPPORTED_ENCRYPT | BITMAP_X_SUPPORTED_COMP, /* EXPIRE */ BITMAP_SA | BITMAP_ADDRESS_DST, /* FLUSH */ 0, /* DUMP */ 0, /* X_PROMISC */ 0, /* X_ADDFLOW */ BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE, /* X_DELFLOW */ BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE, /* X_GRPSPIS */ BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_SATYPE2, /* X_REPPOLICY */ BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_FLOW_TYPE, }; int pfkeyv2_parsemessage(void *p, int len, void **headers) { struct sadb_ext *sadb_ext; int i, left = len; uint64_t allow, seen = 1; struct sadb_msg *sadb_msg = (struct sadb_msg *) p; bzero(headers, (SADB_EXT_MAX + 1) * sizeof(void *)); if (left < sizeof(struct sadb_msg)) { DPRINTF("message too short"); return (EINVAL); } headers[0] = p; if (sadb_msg->sadb_msg_len * sizeof(uint64_t) != left) { DPRINTF("length not a multiple of 64"); return (EINVAL); } p += sizeof(struct sadb_msg); left -= sizeof(struct sadb_msg); if (sadb_msg->sadb_msg_reserved) { DPRINTF("message header reserved field set"); return (EINVAL); } if (sadb_msg->sadb_msg_type > SADB_MAX) { DPRINTF("message type > %d", SADB_MAX); return (EINVAL); } if (!sadb_msg->sadb_msg_type) { DPRINTF("message type unset"); return (EINVAL); } if (sadb_msg->sadb_msg_pid != curproc->p_p->ps_pid) { DPRINTF("bad PID value"); return (EINVAL); } if (sadb_msg->sadb_msg_errno) { DPRINTF("errno set"); return (EINVAL); } allow = sadb_exts_allowed_in[sadb_msg->sadb_msg_type]; while (left > 0) { sadb_ext = (struct sadb_ext *)p; if (left < sizeof(struct sadb_ext)) { DPRINTF("extension header too short"); return (EINVAL); } i = sadb_ext->sadb_ext_len * sizeof(uint64_t); if (left < i) { DPRINTF("extension header exceeds message length"); return (EINVAL); } if (sadb_ext->sadb_ext_type > SADB_EXT_MAX) { DPRINTF("unknown extension header %d", sadb_ext->sadb_ext_type); return (EINVAL); } if (!sadb_ext->sadb_ext_type) { DPRINTF("unset extension header"); return (EINVAL); } if (!(allow & (1LL << sadb_ext->sadb_ext_type))) { DPRINTF("extension header %d not permitted on message " "type %d", sadb_ext->sadb_ext_type, sadb_msg->sadb_msg_type); return (EINVAL); } if (headers[sadb_ext->sadb_ext_type]) { DPRINTF("duplicate extension header %d", sadb_ext->sadb_ext_type); return (EINVAL); } seen |= (1LL << sadb_ext->sadb_ext_type); switch (sadb_ext->sadb_ext_type) { case SADB_EXT_SA: case SADB_X_EXT_SA2: { struct sadb_sa *sadb_sa = (struct sadb_sa *)p; if (i != sizeof(struct sadb_sa)) { DPRINTF("bad header length for SA extension " "header %d", sadb_ext->sadb_ext_type); return (EINVAL); } if (sadb_sa->sadb_sa_state > SADB_SASTATE_MAX) { DPRINTF("unknown SA state %d in SA extension " "header %d", sadb_sa->sadb_sa_state, sadb_ext->sadb_ext_type); return (EINVAL); } if (sadb_sa->sadb_sa_state == SADB_SASTATE_DEAD) { DPRINTF("cannot set SA state to dead, " "SA extension header %d", sadb_ext->sadb_ext_type); return (EINVAL); } if (sadb_sa->sadb_sa_encrypt > SADB_EALG_MAX) { DPRINTF("unknown encryption algorithm %d " "in SA extension header %d", sadb_sa->sadb_sa_encrypt, sadb_ext->sadb_ext_type); return (EINVAL); } if (sadb_sa->sadb_sa_auth > SADB_AALG_MAX) { DPRINTF("unknown authentication algorithm %d " "in SA extension header %d", sadb_sa->sadb_sa_auth, sadb_ext->sadb_ext_type); return (EINVAL); } if (sadb_sa->sadb_sa_replay > 64) { DPRINTF("unsupported replay window size %d " "in SA extension header %d", sadb_sa->sadb_sa_replay, sadb_ext->sadb_ext_type); return (EINVAL); } } break; case SADB_X_EXT_PROTOCOL: case SADB_X_EXT_FLOW_TYPE: case SADB_X_EXT_SATYPE2: if (i != sizeof(struct sadb_protocol)) { DPRINTF("bad PROTOCOL/FLOW/SATYPE2 header " "length in extension header %d", sadb_ext->sadb_ext_type); return (EINVAL); } break; case SADB_X_EXT_POLICY: if (i != sizeof(struct sadb_x_policy)) { DPRINTF("bad POLICY header length"); return (EINVAL); } break; case SADB_EXT_LIFETIME_CURRENT: case SADB_EXT_LIFETIME_HARD: case SADB_EXT_LIFETIME_SOFT: case SADB_X_EXT_LIFETIME_LASTUSE: if (i != sizeof(struct sadb_lifetime)) { DPRINTF("bad header length for LIFETIME " "extension header %d", sadb_ext->sadb_ext_type); return (EINVAL); } break; case SADB_EXT_ADDRESS_SRC: case SADB_EXT_ADDRESS_DST: case SADB_EXT_ADDRESS_PROXY: case SADB_X_EXT_SRC_MASK: case SADB_X_EXT_DST_MASK: case SADB_X_EXT_SRC_FLOW: case SADB_X_EXT_DST_FLOW: case SADB_X_EXT_DST2: { struct sadb_address *sadb_address = (struct sadb_address *)p; struct sockaddr *sa = (struct sockaddr *)(p + sizeof(struct sadb_address)); if (i < sizeof(struct sadb_address) + sizeof(struct sockaddr)) { DPRINTF("bad ADDRESS extension header %d " "length", sadb_ext->sadb_ext_type); return (EINVAL); } if (sadb_address->sadb_address_reserved) { DPRINTF("ADDRESS extension header %d reserved " "field set", sadb_ext->sadb_ext_type); return (EINVAL); } if (sa->sa_len && (i != sizeof(struct sadb_address) + PADUP(sa->sa_len))) { DPRINTF("bad sockaddr length field in ADDRESS " "extension header %d", sadb_ext->sadb_ext_type); return (EINVAL); } switch (sa->sa_family) { case AF_INET: if (sizeof(struct sadb_address) + PADUP(sizeof(struct sockaddr_in)) != i) { DPRINTF("invalid ADDRESS extension " "header %d length", sadb_ext->sadb_ext_type); return (EINVAL); } if (sa->sa_len != sizeof(struct sockaddr_in)) { DPRINTF("bad sockaddr_in length in " "ADDRESS extension header %d", sadb_ext->sadb_ext_type); return (EINVAL); } /* Only check the right pieces */ switch (sadb_ext->sadb_ext_type) { case SADB_X_EXT_SRC_MASK: case SADB_X_EXT_DST_MASK: case SADB_X_EXT_SRC_FLOW: case SADB_X_EXT_DST_FLOW: break; default: if (((struct sockaddr_in *)sa)->sin_port) { DPRINTF("port field set in " "sockaddr_in of ADDRESS " "extension header %d", sadb_ext->sadb_ext_type); return (EINVAL); } break; } { char zero[sizeof(((struct sockaddr_in *)sa)->sin_zero)]; bzero(zero, sizeof(zero)); if (bcmp(&((struct sockaddr_in *)sa)->sin_zero, zero, sizeof(zero))) { DPRINTF("reserved sockaddr_in " "field non-zero'ed in " "ADDRESS extension header " "%d", sadb_ext->sadb_ext_type); return (EINVAL); } } break; #ifdef INET6 case AF_INET6: if (i != sizeof(struct sadb_address) + PADUP(sizeof(struct sockaddr_in6))) { DPRINTF("invalid sockaddr_in6 length " "in ADDRESS extension header %d", sadb_ext->sadb_ext_type); return (EINVAL); } if (sa->sa_len != sizeof(struct sockaddr_in6)) { DPRINTF("bad sockaddr_in6 length in " "ADDRESS extension header %d", sadb_ext->sadb_ext_type); return (EINVAL); } if (((struct sockaddr_in6 *)sa)->sin6_flowinfo) { DPRINTF("flowinfo field set in " "sockaddr_in6 of ADDRESS " "extension header %d", sadb_ext->sadb_ext_type); return (EINVAL); } /* Only check the right pieces */ switch (sadb_ext->sadb_ext_type) { case SADB_X_EXT_SRC_MASK: case SADB_X_EXT_DST_MASK: case SADB_X_EXT_SRC_FLOW: case SADB_X_EXT_DST_FLOW: break; default: if (((struct sockaddr_in6 *)sa)->sin6_port) { DPRINTF("port field set in " "sockaddr_in6 of ADDRESS " "extension header %d", sadb_ext->sadb_ext_type); return (EINVAL); } break; } break; #endif /* INET6 */ default: if (sadb_msg->sadb_msg_satype == SADB_X_SATYPE_TCPSIGNATURE && sa->sa_family == 0) break; DPRINTF("unknown address family %d in ADDRESS " "extension header %d", sa->sa_family, sadb_ext->sadb_ext_type); return (EINVAL); } } break; case SADB_EXT_KEY_AUTH: case SADB_EXT_KEY_ENCRYPT: { struct sadb_key *sadb_key = (struct sadb_key *)p; if (i < sizeof(struct sadb_key)) { DPRINTF("bad header length in KEY extension " "header %d", sadb_ext->sadb_ext_type); return (EINVAL); } if (!sadb_key->sadb_key_bits) { DPRINTF("key length unset in KEY extension " "header %d", sadb_ext->sadb_ext_type); return (EINVAL); } if (((sadb_key->sadb_key_bits + 63) / 64) * sizeof(uint64_t) != i - sizeof(struct sadb_key)) { DPRINTF("invalid key length in KEY extension " "header %d", sadb_ext->sadb_ext_type); return (EINVAL); } if (sadb_key->sadb_key_reserved) { DPRINTF("reserved field set in KEY extension " "header %d", sadb_ext->sadb_ext_type); return (EINVAL); } } break; case SADB_EXT_IDENTITY_SRC: case SADB_EXT_IDENTITY_DST: { struct sadb_ident *sadb_ident = (struct sadb_ident *)p; if (i < sizeof(struct sadb_ident)) { DPRINTF("bad header length of IDENTITY " "extension header %d", sadb_ext->sadb_ext_type); return (EINVAL); } if (sadb_ident->sadb_ident_type > SADB_IDENTTYPE_MAX) { DPRINTF("unknown identity type %d in IDENTITY " "extension header %d", sadb_ident->sadb_ident_type, sadb_ext->sadb_ext_type); return (EINVAL); } if (sadb_ident->sadb_ident_reserved) { DPRINTF("reserved field set in IDENTITY " "extension header %d", sadb_ext->sadb_ext_type); return (EINVAL); } if (i > sizeof(struct sadb_ident)) { char *c = (char *)(p + sizeof(struct sadb_ident)); int j; if (*(char *)(p + i - 1)) { DPRINTF("non NUL-terminated identity " "in IDENTITY extension header %d", sadb_ext->sadb_ext_type); return (EINVAL); } j = PADUP(strlen(c) + 1) + sizeof(struct sadb_ident); if (i != j) { DPRINTF("actual identity length does " "not match expected length in " "identity extension header %d", sadb_ext->sadb_ext_type); return (EINVAL); } } } break; case SADB_EXT_SENSITIVITY: { struct sadb_sens *sadb_sens = (struct sadb_sens *)p; if (i < sizeof(struct sadb_sens)) { DPRINTF("bad header length for SENSITIVITY " "extension header"); return (EINVAL); } if (i != (sadb_sens->sadb_sens_sens_len + sadb_sens->sadb_sens_integ_len) * sizeof(uint64_t) + sizeof(struct sadb_sens)) { DPRINTF("bad payload length for SENSITIVITY " "extension header"); return (EINVAL); } } break; case SADB_EXT_PROPOSAL: { struct sadb_prop *sadb_prop = (struct sadb_prop *)p; if (i < sizeof(struct sadb_prop)) { DPRINTF("bad PROPOSAL header length"); return (EINVAL); } if (sadb_prop->sadb_prop_reserved) { DPRINTF("reserved fieldset in PROPOSAL " "extension header"); return (EINVAL); } if ((i - sizeof(struct sadb_prop)) % sizeof(struct sadb_comb)) { DPRINTF("bad proposal length"); return (EINVAL); } { struct sadb_comb *sadb_comb = (struct sadb_comb *)(p + sizeof(struct sadb_prop)); int j; for (j = 0; j < (i - sizeof(struct sadb_prop))/ sizeof(struct sadb_comb); j++) { if (sadb_comb->sadb_comb_auth > SADB_AALG_MAX) { DPRINTF("unknown " "authentication algorithm " "%d in PROPOSAL", sadb_comb->sadb_comb_auth); return (EINVAL); } if (sadb_comb->sadb_comb_encrypt > SADB_EALG_MAX) { DPRINTF("unknown encryption " "algorithm %d in PROPOSAL", sadb_comb-> sadb_comb_encrypt); return (EINVAL); } if (sadb_comb->sadb_comb_reserved) { DPRINTF("reserved field set " "in COMB header"); return (EINVAL); } } } } break; case SADB_EXT_SUPPORTED_AUTH: case SADB_EXT_SUPPORTED_ENCRYPT: case SADB_X_EXT_SUPPORTED_COMP: { struct sadb_supported *sadb_supported = (struct sadb_supported *)p; int j; if (i < sizeof(struct sadb_supported)) { DPRINTF("bad header length for SUPPORTED " "extension header %d", sadb_ext->sadb_ext_type); return (EINVAL); } if (sadb_supported->sadb_supported_reserved) { DPRINTF("reserved field set in SUPPORTED " "extension header %d", sadb_ext->sadb_ext_type); return (EINVAL); } { struct sadb_alg *sadb_alg = (struct sadb_alg *)(p + sizeof(struct sadb_supported)); int max_alg; max_alg = sadb_ext->sadb_ext_type == SADB_EXT_SUPPORTED_AUTH ? SADB_AALG_MAX : SADB_EXT_SUPPORTED_ENCRYPT ? SADB_EALG_MAX : SADB_X_CALG_MAX; for (j = 0; j < sadb_supported->sadb_supported_len - 1; j++) { if (sadb_alg->sadb_alg_id > max_alg) { DPRINTF("unknown algorithm %d " "in SUPPORTED extension " "header %d", sadb_alg->sadb_alg_id, sadb_ext->sadb_ext_type); return (EINVAL); } if (sadb_alg->sadb_alg_reserved) { DPRINTF("reserved field set " "in supported algorithms " "header inside SUPPORTED " "extension header %d", sadb_ext->sadb_ext_type); return (EINVAL); } sadb_alg++; } } } break; case SADB_EXT_SPIRANGE: { struct sadb_spirange *sadb_spirange = (struct sadb_spirange *)p; if (i != sizeof(struct sadb_spirange)) { DPRINTF("bad header length of SPIRANGE " "extension header"); return (EINVAL); } if (sadb_spirange->sadb_spirange_min > sadb_spirange->sadb_spirange_max) { DPRINTF("bad SPI range"); return (EINVAL); } } break; case SADB_X_EXT_UDPENCAP: if (i != sizeof(struct sadb_x_udpencap)) { DPRINTF("bad UDPENCAP header length"); return (EINVAL); } break; case SADB_X_EXT_RDOMAIN: if (i != sizeof(struct sadb_x_rdomain)) { DPRINTF("bad RDOMAIN header length"); return (EINVAL); } break; #if NPF > 0 case SADB_X_EXT_TAG: if (i < sizeof(struct sadb_x_tag)) { DPRINTF("TAG extension header too small"); return (EINVAL); } if (i > (sizeof(struct sadb_x_tag) + PF_TAG_NAME_SIZE)) { DPRINTF("TAG extension header too long"); return (EINVAL); } break; case SADB_X_EXT_TAP: if (i < sizeof(struct sadb_x_tap)) { DPRINTF("TAP extension header too small"); return (EINVAL); } if (i > sizeof(struct sadb_x_tap)) { DPRINTF("TAP extension header too long"); return (EINVAL); } break; #endif case SADB_X_EXT_IFACE: if (i != sizeof(struct sadb_x_iface)) { DPRINTF("bad IFACE header length"); return (EINVAL); } break; default: DPRINTF("unknown extension header type %d", sadb_ext->sadb_ext_type); return (EINVAL); } headers[sadb_ext->sadb_ext_type] = p; p += i; left -= i; } if (left) { DPRINTF("message too long"); return (EINVAL); } { uint64_t required; required = sadb_exts_required_in[sadb_msg->sadb_msg_type]; if ((seen & required) != required) { DPRINTF("required fields missing"); return (EINVAL); } } switch (((struct sadb_msg *)headers[0])->sadb_msg_type) { case SADB_UPDATE: if (((struct sadb_sa *)headers[SADB_EXT_SA])->sadb_sa_state != SADB_SASTATE_MATURE) { DPRINTF("updating non-mature SA prohibited"); return (EINVAL); } break; case SADB_ADD: if (((struct sadb_sa *)headers[SADB_EXT_SA])->sadb_sa_state != SADB_SASTATE_MATURE) { DPRINTF("adding non-mature SA prohibited"); return (EINVAL); } break; } return (0); }
6 3 10 9 9 9 9 6 3 12 7 5 5 11 12 6 6 1149 7 3 10 10 1 4 9 6 6 12 4 5 29 30 28 14 4 11 2 10 5 14 29 7 24 104 31 28 18 10 2 1 1 53 184 184 184 184 3 3 18 21 16 7 1 1 1 3 1 1 2 1 1 1 1 2 76 78 75 4 3 72 74 1 1054 1055 1049 2 582 477 1 1051 1 1 2 5 7 6 4 4 2 3 5 5 4 3 3 2 7 7 9 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 /* $OpenBSD: if_tun.c,v 1.240 2023/12/23 10:52:54 bluhm Exp $ */ /* $NetBSD: if_tun.c,v 1.24 1996/05/07 02:40:48 thorpej Exp $ */ /* * Copyright (c) 1988, Julian Onions <Julian.Onions@nexor.co.uk> * Nottingham University 1987. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * This driver takes packets off the IP i/f and hands them up to a * user process to have its wicked way with. This driver has its * roots in a similar driver written by Phil Cockcroft (formerly) at * UCL. This driver is based much more on read/write/select mode of * operation though. */ /* #define TUN_DEBUG 9 */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/proc.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/sigio.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <sys/errno.h> #include <sys/syslog.h> #include <sys/fcntl.h> #include <sys/time.h> #include <sys/device.h> #include <sys/vnode.h> #include <sys/signalvar.h> #include <sys/conf.h> #include <sys/event.h> #include <sys/mutex.h> #include <sys/smr.h> #include <net/if.h> #include <net/if_types.h> #include <net/netisr.h> #include <net/rtable.h> #include <netinet/in.h> #include <netinet/if_ether.h> #include "bpfilter.h" #if NBPFILTER > 0 #include <net/bpf.h> #endif #ifdef MPLS #include <netmpls/mpls.h> #endif /* MPLS */ #include <net/if_tun.h> struct tun_softc { struct arpcom sc_ac; /* ethernet common data */ #define sc_if sc_ac.ac_if struct mutex sc_mtx; struct klist sc_rklist; /* knotes for read */ struct klist sc_wklist; /* knotes for write (unused) */ SMR_LIST_ENTRY(tun_softc) sc_entry; /* all tunnel interfaces */ int sc_unit; struct sigio_ref sc_sigio; /* async I/O registration */ unsigned int sc_flags; /* misc flags */ #define TUN_DEAD (1 << 16) dev_t sc_dev; struct refcnt sc_refs; unsigned int sc_reading; }; #ifdef TUN_DEBUG int tundebug = TUN_DEBUG; #define TUNDEBUG(a) (tundebug? printf a : 0) #else #define TUNDEBUG(a) /* (tundebug? printf a : 0) */ #endif /* Only these IFF flags are changeable by TUNSIFINFO */ #define TUN_IFF_FLAGS (IFF_UP|IFF_POINTOPOINT|IFF_MULTICAST|IFF_BROADCAST) void tunattach(int); int tun_dev_open(dev_t, const struct if_clone *, int, struct proc *); int tun_dev_close(dev_t, struct proc *); int tun_dev_ioctl(dev_t, u_long, void *); int tun_dev_read(dev_t, struct uio *, int); int tun_dev_write(dev_t, struct uio *, int, int); int tun_dev_kqfilter(dev_t, struct knote *); int tun_ioctl(struct ifnet *, u_long, caddr_t); void tun_input(struct ifnet *, struct mbuf *); int tun_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); int tun_enqueue(struct ifnet *, struct mbuf *); int tun_clone_create(struct if_clone *, int); int tap_clone_create(struct if_clone *, int); int tun_create(struct if_clone *, int, int); int tun_clone_destroy(struct ifnet *); void tun_wakeup(struct tun_softc *); int tun_init(struct tun_softc *); void tun_start(struct ifnet *); int filt_tunread(struct knote *, long); int filt_tunwrite(struct knote *, long); int filt_tunmodify(struct kevent *, struct knote *); int filt_tunprocess(struct knote *, struct kevent *); void filt_tunrdetach(struct knote *); void filt_tunwdetach(struct knote *); void tun_link_state(struct ifnet *, int); const struct filterops tunread_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_tunrdetach, .f_event = filt_tunread, .f_modify = filt_tunmodify, .f_process = filt_tunprocess, }; const struct filterops tunwrite_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_tunwdetach, .f_event = filt_tunwrite, .f_modify = filt_tunmodify, .f_process = filt_tunprocess, }; SMR_LIST_HEAD(tun_list, tun_softc); struct if_clone tun_cloner = IF_CLONE_INITIALIZER("tun", tun_clone_create, tun_clone_destroy); struct if_clone tap_cloner = IF_CLONE_INITIALIZER("tap", tap_clone_create, tun_clone_destroy); void tunattach(int n) { if_clone_attach(&tun_cloner); if_clone_attach(&tap_cloner); } int tun_clone_create(struct if_clone *ifc, int unit) { return (tun_create(ifc, unit, 0)); } int tap_clone_create(struct if_clone *ifc, int unit) { return (tun_create(ifc, unit, TUN_LAYER2)); } struct tun_list tun_devs_list = SMR_LIST_HEAD_INITIALIZER(tun_list); struct tun_softc * tun_name_lookup(const char *name) { struct tun_softc *sc; KERNEL_ASSERT_LOCKED(); SMR_LIST_FOREACH_LOCKED(sc, &tun_devs_list, sc_entry) { if (strcmp(sc->sc_if.if_xname, name) == 0) return (sc); } return (NULL); } int tun_insert(struct tun_softc *sc) { int error = 0; /* check for a race */ if (tun_name_lookup(sc->sc_if.if_xname) != NULL) error = EEXIST; else { /* tun_name_lookup checks for the right lock already */ SMR_LIST_INSERT_HEAD_LOCKED(&tun_devs_list, sc, sc_entry); } return (error); } int tun_create(struct if_clone *ifc, int unit, int flags) { struct tun_softc *sc; struct ifnet *ifp; if (unit > minor(~0U)) return (ENXIO); KERNEL_ASSERT_LOCKED(); sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); refcnt_init(&sc->sc_refs); ifp = &sc->sc_if; snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d", ifc->ifc_name, unit); mtx_init(&sc->sc_mtx, IPL_NET); klist_init_mutex(&sc->sc_rklist, &sc->sc_mtx); klist_init_mutex(&sc->sc_wklist, &sc->sc_mtx); ifp->if_softc = sc; /* this is enough state for tun_dev_open to work with */ if (tun_insert(sc) != 0) goto exists; /* build the interface */ ifp->if_ioctl = tun_ioctl; ifp->if_enqueue = tun_enqueue; ifp->if_start = tun_start; ifp->if_hardmtu = TUNMRU; ifp->if_link_state = LINK_STATE_DOWN; if_counters_alloc(ifp); if ((flags & TUN_LAYER2) == 0) { #if NBPFILTER > 0 ifp->if_bpf_mtap = bpf_mtap; #endif ifp->if_input = tun_input; ifp->if_output = tun_output; ifp->if_mtu = ETHERMTU; ifp->if_flags = (IFF_POINTOPOINT|IFF_MULTICAST); ifp->if_type = IFT_TUNNEL; ifp->if_hdrlen = sizeof(u_int32_t); ifp->if_rtrequest = p2p_rtrequest; if_attach(ifp); if_alloc_sadl(ifp); #if NBPFILTER > 0 bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(u_int32_t)); #endif } else { sc->sc_flags |= TUN_LAYER2; ether_fakeaddr(ifp); ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST); if_attach(ifp); ether_ifattach(ifp); } sigio_init(&sc->sc_sigio); /* tell tun_dev_open we're initialised */ sc->sc_flags |= TUN_INITED|TUN_STAYUP; wakeup(sc); return (0); exists: klist_free(&sc->sc_rklist); klist_free(&sc->sc_wklist); free(sc, M_DEVBUF, sizeof(*sc)); return (EEXIST); } int tun_clone_destroy(struct ifnet *ifp) { struct tun_softc *sc = ifp->if_softc; dev_t dev; KERNEL_ASSERT_LOCKED(); if (ISSET(sc->sc_flags, TUN_DEAD)) return (ENXIO); SET(sc->sc_flags, TUN_DEAD); /* kick userland off the device */ dev = sc->sc_dev; if (dev) { struct vnode *vp; if (vfinddev(dev, VCHR, &vp)) VOP_REVOKE(vp, REVOKEALL); KASSERT(sc->sc_dev == 0); } /* prevent userland from getting to the device again */ SMR_LIST_REMOVE_LOCKED(sc, sc_entry); smr_barrier(); /* help read() give up */ if (sc->sc_reading) wakeup(&ifp->if_snd); /* wait for device entrypoints to finish */ refcnt_finalize(&sc->sc_refs, "tundtor"); klist_invalidate(&sc->sc_rklist); klist_invalidate(&sc->sc_wklist); klist_free(&sc->sc_rklist); klist_free(&sc->sc_wklist); if (ISSET(sc->sc_flags, TUN_LAYER2)) ether_ifdetach(ifp); if_detach(ifp); sigio_free(&sc->sc_sigio); free(sc, M_DEVBUF, sizeof *sc); return (0); } static struct tun_softc * tun_get(dev_t dev) { struct tun_softc *sc; smr_read_enter(); SMR_LIST_FOREACH(sc, &tun_devs_list, sc_entry) { if (sc->sc_dev == dev) { refcnt_take(&sc->sc_refs); break; } } smr_read_leave(); return (sc); } static inline void tun_put(struct tun_softc *sc) { refcnt_rele_wake(&sc->sc_refs); } int tunopen(dev_t dev, int flag, int mode, struct proc *p) { return (tun_dev_open(dev, &tun_cloner, mode, p)); } int tapopen(dev_t dev, int flag, int mode, struct proc *p) { return (tun_dev_open(dev, &tap_cloner, mode, p)); } int tun_dev_open(dev_t dev, const struct if_clone *ifc, int mode, struct proc *p) { struct tun_softc *sc; struct ifnet *ifp; int error; u_short stayup = 0; struct vnode *vp; char name[IFNAMSIZ]; unsigned int rdomain; /* * Find the vnode associated with this open before we sleep * and let something else revoke it. Our caller has a reference * to it so we don't need to account for it. */ if (!vfinddev(dev, VCHR, &vp)) panic("%s vfinddev failed", __func__); snprintf(name, sizeof(name), "%s%u", ifc->ifc_name, minor(dev)); rdomain = rtable_l2(p->p_p->ps_rtableid); /* let's find or make an interface to work with */ while ((sc = tun_name_lookup(name)) == NULL) { error = if_clone_create(name, rdomain); switch (error) { case 0: /* it's probably ours */ stayup = TUN_STAYUP; /* FALLTHROUGH */ case EEXIST: /* we may have lost a race with someone else */ break; default: return (error); } } refcnt_take(&sc->sc_refs); /* wait for it to be fully constructed before we use it */ for (;;) { if (ISSET(sc->sc_flags, TUN_DEAD)) { error = ENXIO; goto done; } if (ISSET(sc->sc_flags, TUN_INITED)) break; error = tsleep_nsec(sc, PCATCH, "tuninit", INFSLP); if (error != 0) { /* XXX if_clone_destroy if stayup? */ goto done; } } /* Has tun_clone_destroy torn the rug out under us? */ if (vp->v_type == VBAD) { error = ENXIO; goto done; } if (sc->sc_dev != 0) { /* aww, we lost */ error = EBUSY; goto done; } /* it's ours now */ sc->sc_dev = dev; CLR(sc->sc_flags, stayup); /* automatically mark the interface running on open */ ifp = &sc->sc_if; NET_LOCK(); SET(ifp->if_flags, IFF_UP | IFF_RUNNING); NET_UNLOCK(); tun_link_state(ifp, LINK_STATE_FULL_DUPLEX); error = 0; done: tun_put(sc); return (error); } /* * tunclose - close the device; if closing the real device, flush pending * output and unless STAYUP bring down and destroy the interface. */ int tunclose(dev_t dev, int flag, int mode, struct proc *p) { return (tun_dev_close(dev, p)); } int tapclose(dev_t dev, int flag, int mode, struct proc *p) { return (tun_dev_close(dev, p)); } int tun_dev_close(dev_t dev, struct proc *p) { struct tun_softc *sc; struct ifnet *ifp; int error = 0; char name[IFNAMSIZ]; int destroy = 0; sc = tun_get(dev); if (sc == NULL) return (ENXIO); ifp = &sc->sc_if; /* * junk all pending output */ NET_LOCK(); CLR(ifp->if_flags, IFF_UP | IFF_RUNNING); NET_UNLOCK(); ifq_purge(&ifp->if_snd); CLR(sc->sc_flags, TUN_ASYNC); sigio_free(&sc->sc_sigio); if (!ISSET(sc->sc_flags, TUN_DEAD)) { /* we can't hold a reference to sc before we start a dtor */ if (!ISSET(sc->sc_flags, TUN_STAYUP)) { destroy = 1; strlcpy(name, ifp->if_xname, sizeof(name)); } else { tun_link_state(ifp, LINK_STATE_DOWN); } } sc->sc_dev = 0; tun_put(sc); if (destroy) if_clone_destroy(name); return (error); } int tun_init(struct tun_softc *sc) { struct ifnet *ifp = &sc->sc_if; struct ifaddr *ifa; TUNDEBUG(("%s: tun_init\n", ifp->if_xname)); ifp->if_flags |= IFF_UP | IFF_RUNNING; sc->sc_flags &= ~(TUN_IASET|TUN_DSTADDR|TUN_BRDADDR); TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family == AF_INET) { struct sockaddr_in *sin; sin = satosin(ifa->ifa_addr); if (sin && sin->sin_addr.s_addr) sc->sc_flags |= TUN_IASET; if (ifp->if_flags & IFF_POINTOPOINT) { sin = satosin(ifa->ifa_dstaddr); if (sin && sin->sin_addr.s_addr) sc->sc_flags |= TUN_DSTADDR; } else sc->sc_flags &= ~TUN_DSTADDR; if (ifp->if_flags & IFF_BROADCAST) { sin = satosin(ifa->ifa_broadaddr); if (sin && sin->sin_addr.s_addr) sc->sc_flags |= TUN_BRDADDR; } else sc->sc_flags &= ~TUN_BRDADDR; } #ifdef INET6 if (ifa->ifa_addr->sa_family == AF_INET6) { struct sockaddr_in6 *sin6; sin6 = satosin6(ifa->ifa_addr); if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) sc->sc_flags |= TUN_IASET; if (ifp->if_flags & IFF_POINTOPOINT) { sin6 = satosin6(ifa->ifa_dstaddr); if (sin6 && !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) sc->sc_flags |= TUN_DSTADDR; } else sc->sc_flags &= ~TUN_DSTADDR; } #endif /* INET6 */ } return (0); } /* * Process an ioctl request. */ int tun_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct tun_softc *sc = (struct tun_softc *)(ifp->if_softc); struct ifreq *ifr = (struct ifreq *)data; int error = 0; switch (cmd) { case SIOCSIFADDR: tun_init(sc); break; case SIOCSIFFLAGS: if (ISSET(ifp->if_flags, IFF_UP)) SET(ifp->if_flags, IFF_RUNNING); else CLR(ifp->if_flags, IFF_RUNNING); break; case SIOCSIFDSTADDR: tun_init(sc); TUNDEBUG(("%s: destination address set\n", ifp->if_xname)); break; case SIOCSIFMTU: if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > TUNMRU) error = EINVAL; else ifp->if_mtu = ifr->ifr_mtu; break; case SIOCADDMULTI: case SIOCDELMULTI: break; default: if (sc->sc_flags & TUN_LAYER2) error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); else error = ENOTTY; } return (error); } /* * tun_output - queue packets from higher level ready to put out. */ int tun_output(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst, struct rtentry *rt) { u_int32_t *af; if (!ISSET(ifp->if_flags, IFF_RUNNING)) { m_freem(m0); return (EHOSTDOWN); } M_PREPEND(m0, sizeof(*af), M_DONTWAIT); if (m0 == NULL) return (ENOBUFS); af = mtod(m0, u_int32_t *); *af = htonl(dst->sa_family); return (if_enqueue(ifp, m0)); } int tun_enqueue(struct ifnet *ifp, struct mbuf *m0) { struct tun_softc *sc = ifp->if_softc; int error; error = ifq_enqueue(&ifp->if_snd, m0); if (error != 0) return (error); tun_wakeup(sc); return (0); } void tun_wakeup(struct tun_softc *sc) { if (sc->sc_reading) wakeup(&sc->sc_if.if_snd); knote(&sc->sc_rklist, 0); if (sc->sc_flags & TUN_ASYNC) pgsigio(&sc->sc_sigio, SIGIO, 0); } /* * the cdevsw interface is now pretty minimal. */ int tunioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { return (tun_dev_ioctl(dev, cmd, data)); } int tapioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { return (tun_dev_ioctl(dev, cmd, data)); } int tun_dev_ioctl(dev_t dev, u_long cmd, void *data) { struct tun_softc *sc; struct tuninfo *tunp; int error = 0; sc = tun_get(dev); if (sc == NULL) return (ENXIO); switch (cmd) { case TUNSIFINFO: tunp = (struct tuninfo *)data; if (tunp->mtu < ETHERMIN || tunp->mtu > TUNMRU) { error = EINVAL; break; } if (tunp->type != sc->sc_if.if_type) { error = EINVAL; break; } sc->sc_if.if_mtu = tunp->mtu; sc->sc_if.if_flags = (tunp->flags & TUN_IFF_FLAGS) | (sc->sc_if.if_flags & ~TUN_IFF_FLAGS); sc->sc_if.if_baudrate = tunp->baudrate; break; case TUNGIFINFO: tunp = (struct tuninfo *)data; tunp->mtu = sc->sc_if.if_mtu; tunp->type = sc->sc_if.if_type; tunp->flags = sc->sc_if.if_flags; tunp->baudrate = sc->sc_if.if_baudrate; break; #ifdef TUN_DEBUG case TUNSDEBUG: tundebug = *(int *)data; break; case TUNGDEBUG: *(int *)data = tundebug; break; #endif case TUNSIFMODE: switch (*(int *)data & (IFF_POINTOPOINT|IFF_BROADCAST)) { case IFF_POINTOPOINT: case IFF_BROADCAST: sc->sc_if.if_flags &= ~TUN_IFF_FLAGS; sc->sc_if.if_flags |= *(int *)data & TUN_IFF_FLAGS; break; default: error = EINVAL; break; } break; case FIONBIO: break; case FIOASYNC: if (*(int *)data) sc->sc_flags |= TUN_ASYNC; else sc->sc_flags &= ~TUN_ASYNC; break; case FIONREAD: *(int *)data = ifq_hdatalen(&sc->sc_if.if_snd); break; case FIOSETOWN: case TIOCSPGRP: error = sigio_setown(&sc->sc_sigio, cmd, data); break; case FIOGETOWN: case TIOCGPGRP: sigio_getown(&sc->sc_sigio, cmd, data); break; case SIOCGIFADDR: if (!(sc->sc_flags & TUN_LAYER2)) { error = EINVAL; break; } bcopy(sc->sc_ac.ac_enaddr, data, sizeof(sc->sc_ac.ac_enaddr)); break; case SIOCSIFADDR: if (!(sc->sc_flags & TUN_LAYER2)) { error = EINVAL; break; } bcopy(data, sc->sc_ac.ac_enaddr, sizeof(sc->sc_ac.ac_enaddr)); break; default: error = ENOTTY; break; } tun_put(sc); return (error); } /* * The cdevsw read interface - reads a packet at a time, or at * least as much of a packet as can be read. */ int tunread(dev_t dev, struct uio *uio, int ioflag) { return (tun_dev_read(dev, uio, ioflag)); } int tapread(dev_t dev, struct uio *uio, int ioflag) { return (tun_dev_read(dev, uio, ioflag)); } int tun_dev_read(dev_t dev, struct uio *uio, int ioflag) { struct tun_softc *sc; struct ifnet *ifp; struct mbuf *m, *m0; int error = 0; sc = tun_get(dev); if (sc == NULL) return (ENXIO); ifp = &sc->sc_if; error = ifq_deq_sleep(&ifp->if_snd, &m0, ISSET(ioflag, IO_NDELAY), (PZERO + 1)|PCATCH, "tunread", &sc->sc_reading, &sc->sc_dev); if (error != 0) goto put; #if NBPFILTER > 0 if (ifp->if_bpf) bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT); #endif m = m0; while (uio->uio_resid > 0) { size_t len = ulmin(uio->uio_resid, m->m_len); if (len > 0) { error = uiomove(mtod(m, void *), len, uio); if (error != 0) break; } m = m->m_next; if (m == NULL) break; } m_freem(m0); put: tun_put(sc); return (error); } /* * the cdevsw write interface - an atomic write is a packet - or else! */ int tunwrite(dev_t dev, struct uio *uio, int ioflag) { return (tun_dev_write(dev, uio, ioflag, 0)); } int tapwrite(dev_t dev, struct uio *uio, int ioflag) { return (tun_dev_write(dev, uio, ioflag, ETHER_ALIGN)); } int tun_dev_write(dev_t dev, struct uio *uio, int ioflag, int align) { struct tun_softc *sc; struct ifnet *ifp; struct mbuf *m0; int error = 0; size_t mlen; sc = tun_get(dev); if (sc == NULL) return (ENXIO); ifp = &sc->sc_if; if (uio->uio_resid < ifp->if_hdrlen || uio->uio_resid > (ifp->if_hdrlen + ifp->if_hardmtu)) { error = EMSGSIZE; goto put; } align += max_linkhdr; mlen = align + uio->uio_resid; m0 = m_gethdr(M_DONTWAIT, MT_DATA); if (m0 == NULL) { error = ENOMEM; goto put; } if (mlen > MHLEN) { m_clget(m0, M_DONTWAIT, mlen); if (!ISSET(m0->m_flags, M_EXT)) { error = ENOMEM; goto drop; } } m_align(m0, mlen); m0->m_pkthdr.len = m0->m_len = mlen; m_adj(m0, align); error = uiomove(mtod(m0, void *), m0->m_len, uio); if (error != 0) goto drop; NET_LOCK(); if_vinput(ifp, m0); NET_UNLOCK(); tun_put(sc); return (0); drop: m_freem(m0); put: tun_put(sc); return (error); } void tun_input(struct ifnet *ifp, struct mbuf *m0) { uint32_t af; KASSERT(m0->m_len >= sizeof(af)); af = *mtod(m0, uint32_t *); /* strip the tunnel header */ m_adj(m0, sizeof(af)); switch (ntohl(af)) { case AF_INET: ipv4_input(ifp, m0); break; #ifdef INET6 case AF_INET6: ipv6_input(ifp, m0); break; #endif #ifdef MPLS case AF_MPLS: mpls_input(ifp, m0); break; #endif default: m_freem(m0); break; } } int tunkqfilter(dev_t dev, struct knote *kn) { return (tun_dev_kqfilter(dev, kn)); } int tapkqfilter(dev_t dev, struct knote *kn) { return (tun_dev_kqfilter(dev, kn)); } int tun_dev_kqfilter(dev_t dev, struct knote *kn) { struct tun_softc *sc; struct ifnet *ifp; struct klist *klist; int error = 0; sc = tun_get(dev); if (sc == NULL) return (ENXIO); ifp = &sc->sc_if; switch (kn->kn_filter) { case EVFILT_READ: klist = &sc->sc_rklist; kn->kn_fop = &tunread_filtops; break; case EVFILT_WRITE: klist = &sc->sc_wklist; kn->kn_fop = &tunwrite_filtops; break; default: error = EINVAL; goto put; } kn->kn_hook = sc; klist_insert(klist, kn); put: tun_put(sc); return (error); } void filt_tunrdetach(struct knote *kn) { struct tun_softc *sc = kn->kn_hook; klist_remove(&sc->sc_rklist, kn); } int filt_tunread(struct knote *kn, long hint) { struct tun_softc *sc = kn->kn_hook; struct ifnet *ifp = &sc->sc_if; MUTEX_ASSERT_LOCKED(&sc->sc_mtx); kn->kn_data = ifq_hdatalen(&ifp->if_snd); return (kn->kn_data > 0); } void filt_tunwdetach(struct knote *kn) { struct tun_softc *sc = kn->kn_hook; klist_remove(&sc->sc_wklist, kn); } int filt_tunwrite(struct knote *kn, long hint) { struct tun_softc *sc = kn->kn_hook; struct ifnet *ifp = &sc->sc_if; MUTEX_ASSERT_LOCKED(&sc->sc_mtx); kn->kn_data = ifp->if_hdrlen + ifp->if_hardmtu; return (1); } int filt_tunmodify(struct kevent *kev, struct knote *kn) { struct tun_softc *sc = kn->kn_hook; int active; mtx_enter(&sc->sc_mtx); active = knote_modify(kev, kn); mtx_leave(&sc->sc_mtx); return (active); } int filt_tunprocess(struct knote *kn, struct kevent *kev) { struct tun_softc *sc = kn->kn_hook; int active; mtx_enter(&sc->sc_mtx); active = knote_process(kn, kev); mtx_leave(&sc->sc_mtx); return (active); } void tun_start(struct ifnet *ifp) { struct tun_softc *sc = ifp->if_softc; splassert(IPL_NET); if (ifq_len(&ifp->if_snd)) tun_wakeup(sc); } void tun_link_state(struct ifnet *ifp, int link_state) { if (ifp->if_link_state != link_state) { ifp->if_link_state = link_state; if_link_state_change(ifp); } }
6 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 /* $OpenBSD: ip6_var.h,v 1.117 2024/05/13 01:15:53 jsg Exp $ */ /* $KAME: ip6_var.h,v 1.33 2000/06/11 14:59:20 jinmei Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 1982, 1986, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ip_var.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET6_IP6_VAR_H_ #define _NETINET6_IP6_VAR_H_ struct ip6stat { u_int64_t ip6s_total; /* total packets received */ u_int64_t ip6s_tooshort; /* packet too short */ u_int64_t ip6s_toosmall; /* not enough data */ u_int64_t ip6s_fragments; /* fragments received */ u_int64_t ip6s_fragdropped; /* frags dropped(dups, out of space) */ u_int64_t ip6s_fragtimeout; /* fragments timed out */ u_int64_t ip6s_fragoverflow; /* fragments that exceeded limit */ u_int64_t ip6s_forward; /* packets forwarded */ u_int64_t ip6s_cantforward; /* packets rcvd for unreachable dest */ u_int64_t ip6s_redirectsent; /* packets forwarded on same net */ u_int64_t ip6s_delivered; /* datagrams delivered to upper level*/ u_int64_t ip6s_localout; /* total ip packets generated here */ u_int64_t ip6s_odropped; /* lost output due to nobufs, etc. */ u_int64_t ip6s_reassembled; /* total packets reassembled ok */ u_int64_t ip6s_fragmented; /* datagrams successfully fragmented */ u_int64_t ip6s_ofragments; /* output fragments created */ u_int64_t ip6s_cantfrag; /* don't fragment flag was set, etc. */ u_int64_t ip6s_badoptions; /* error in option processing */ u_int64_t ip6s_noroute; /* packets discarded due to no route */ u_int64_t ip6s_badvers; /* ip6 version != 6 */ u_int64_t ip6s_rawout; /* total raw ip packets generated */ u_int64_t ip6s_badscope; /* scope error */ u_int64_t ip6s_notmember; /* don't join this multicast group */ u_int64_t ip6s_nxthist[256]; /* next header history */ u_int64_t ip6s_m1; /* one mbuf */ u_int64_t ip6s_m2m[32]; /* two or more mbuf */ u_int64_t ip6s_mext1; /* one ext mbuf */ u_int64_t ip6s_mext2m; /* two or more ext mbuf */ u_int64_t ip6s_nogif; /* no match gif found */ u_int64_t ip6s_toomanyhdr; /* discarded due to too many headers */ /* * statistics for improvement of the source address selection * algorithm: * XXX: hardcoded 16 = # of ip6 multicast scope types + 1 */ /* number of times that address selection fails */ u_int64_t ip6s_sources_none; /* number of times that an address on the outgoing I/F is chosen */ u_int64_t ip6s_sources_sameif[16]; /* number of times that an address on a non-outgoing I/F is chosen */ u_int64_t ip6s_sources_otherif[16]; /* * number of times that an address that has the same scope * from the destination is chosen. */ u_int64_t ip6s_sources_samescope[16]; /* * number of times that an address that has a different scope * from the destination is chosen. */ u_int64_t ip6s_sources_otherscope[16]; /* number of times that an deprecated address is chosen */ u_int64_t ip6s_sources_deprecated[16]; u_int64_t ip6s_rtcachehit; /* valid route found in cache */ u_int64_t ip6s_rtcachemiss; /* route cache with new destination */ u_int64_t ip6s_wrongif; /* packet received on wrong interface */ u_int64_t ip6s_idropped; /* lost input due to nobufs, etc. */ }; #ifdef _KERNEL /* * IP6 reassembly queue structure. Each fragment * being reassembled is attached to one of these structures. */ struct ip6q { TAILQ_ENTRY(ip6q) ip6q_queue; LIST_HEAD(ip6asfrag_list, ip6asfrag) ip6q_asfrag; struct in6_addr ip6q_src, ip6q_dst; int ip6q_unfrglen; /* len of unfragmentable part */ int ip6q_nfrag; /* # of fragments */ u_int32_t ip6q_ident; /* fragment identification */ u_int8_t ip6q_nxt; /* ip6f_nxt in first fragment */ u_int8_t ip6q_ecn; u_int8_t ip6q_ttl; /* time to live in slowtimo units */ }; struct ip6asfrag { LIST_ENTRY(ip6asfrag) ip6af_list; struct mbuf *ip6af_m; int ip6af_offset; /* offset in ip6af_m to next header */ int ip6af_frglen; /* fragmentable part length */ int ip6af_off; /* fragment offset */ u_int16_t ip6af_mff; /* more fragment bit in frag off */ }; struct ip6_moptions { LIST_HEAD(, in6_multi_mship) im6o_memberships; unsigned short im6o_ifidx; /* ifp index for outgoing multicasts */ u_char im6o_hlim; /* hoplimit for outgoing multicasts */ u_char im6o_loop; /* 1 >= hear sends if a member */ }; /* * Control options for outgoing packets */ /* Routing header related info */ struct ip6po_rhinfo { struct ip6_rthdr *ip6po_rhi_rthdr; /* Routing header */ struct route ip6po_rhi_route; /* Route to the 1st hop */ }; #define ip6po_rthdr ip6po_rhinfo.ip6po_rhi_rthdr #define ip6po_route ip6po_rhinfo.ip6po_rhi_route struct ip6_pktopts { /* Hoplimit for outgoing packets */ int ip6po_hlim; /* Outgoing IF/address information */ struct in6_pktinfo *ip6po_pktinfo; /* Hop-by-Hop options header */ struct ip6_hbh *ip6po_hbh; /* Destination options header (before a routing header) */ struct ip6_dest *ip6po_dest1; /* Routing header related info. */ struct ip6po_rhinfo ip6po_rhinfo; /* Destination options header (after a routing header) */ struct ip6_dest *ip6po_dest2; /* traffic class */ int ip6po_tclass; /* fragment vs PMTU discovery policy */ int ip6po_minmtu; #define IP6PO_MINMTU_MCASTONLY -1 /* default: send at min MTU for multicast */ #define IP6PO_MINMTU_DISABLE 0 /* always perform pmtu disc */ #define IP6PO_MINMTU_ALL 1 /* always send at min MTU */ int ip6po_flags; #define IP6PO_DONTFRAG 0x04 /* disable fragmentation (IPV6_DONTFRAG) */ }; #include <sys/percpu.h> enum ip6stat_counters { ip6s_total, ip6s_tooshort, ip6s_toosmall, ip6s_fragments, ip6s_fragdropped, ip6s_fragtimeout, ip6s_fragoverflow, ip6s_forward, ip6s_cantforward, ip6s_redirectsent, ip6s_delivered, ip6s_localout, ip6s_odropped, ip6s_reassembled, ip6s_fragmented, ip6s_ofragments, ip6s_cantfrag, ip6s_badoptions, ip6s_noroute, ip6s_badvers, ip6s_rawout, ip6s_badscope, ip6s_notmember, ip6s_nxthist, ip6s_m1 = ip6s_nxthist + 256, ip6s_m2m, ip6s_mext1 = ip6s_m2m + 32, ip6s_mext2m, ip6s_nogif, ip6s_toomanyhdr, ip6s_sources_none, ip6s_sources_sameif, ip6s_sources_otherif = ip6s_sources_sameif + 16, ip6s_sources_samescope = ip6s_sources_otherif + 16, ip6s_sources_otherscope = ip6s_sources_samescope + 16, ip6s_sources_deprecated = ip6s_sources_otherscope + 16, ip6s_rtcachehit = ip6s_sources_deprecated + 16, ip6s_rtcachemiss, ip6s_wrongif, ip6s_idropped, ip6s_ncounters, }; extern struct cpumem *ip6counters; static inline void ip6stat_inc(enum ip6stat_counters c) { counters_inc(ip6counters, c); } static inline void ip6stat_add(enum ip6stat_counters c, uint64_t v) { counters_add(ip6counters, c, v); } /* flags passed to ip6_output as last parameter */ #define IPV6_UNSPECSRC 0x01 /* allow :: as the source address */ #define IPV6_FORWARDING 0x02 /* most of IPv6 header exists */ #define IPV6_MINMTU 0x04 /* use minimum MTU (IPV6_USE_MIN_MTU) */ extern int ip6_mtudisc_timeout; /* mtu discovery */ extern struct rttimer_queue icmp6_mtudisc_timeout_q; extern int ip6_defhlim; /* default hop limit */ extern int ip6_defmcasthlim; /* default multicast hop limit */ extern int ip6_forwarding; /* act as router? */ extern int ip6_mforwarding; /* act as multicast router? */ extern int ip6_multipath; /* use multipath routes */ extern int ip6_sendredirect; /* send ICMPv6 redirect? */ extern int ip6_use_deprecated; /* allow deprecated addr as source */ extern int ip6_mcast_pmtu; /* path MTU discovery for multicast */ extern int ip6_neighborgcthresh; /* Threshold # of NDP entries for GC */ extern int ip6_maxdynroutes; /* Max # of routes created via redirect */ extern struct socket *ip6_mrouter[RT_TABLEID_MAX + 1]; /* multicast routing daemon */ extern int ip6_sendredirects; /* send IP redirects when forwarding? */ extern int ip6_maxfragpackets; /* Maximum packets in reassembly queue */ extern int ip6_maxfrags; /* Maximum fragments in reassembly queue */ extern int ip6_log_interval; extern time_t ip6_log_time; extern int ip6_hdrnestlimit; /* upper limit of # of extension headers */ extern int ip6_dad_count; /* DupAddrDetectionTransmits */ extern int ip6_dad_pending; /* number of currently running DADs */ extern int ip6_auto_flowlabel; #define IP6_SOIIKEY_LEN 16 extern uint8_t ip6_soiikey[IP6_SOIIKEY_LEN]; extern const struct pr_usrreqs rip6_usrreqs; struct inpcb; struct ipsec_level; int icmp6_ctloutput(int, struct socket *, int, int, struct mbuf *); void ip6_init(void); void ip6intr(void); int ip6_input_if(struct mbuf **, int *, int, int, struct ifnet *); void ip6_freepcbopts(struct ip6_pktopts *); void ip6_freemoptions(struct ip6_moptions *); int ip6_unknown_opt(struct mbuf **, u_int8_t *, int); int ip6_get_prevhdr(struct mbuf *, int); int ip6_nexthdr(struct mbuf *, int, int, int *); int ip6_lasthdr(struct mbuf *, int, int, int *); int ip6_mforward(struct ip6_hdr *, struct ifnet *, struct mbuf *); int ip6_process_hopopts(struct mbuf **, u_int8_t *, int, u_int32_t *, u_int32_t *); void ip6_savecontrol(struct inpcb *, struct mbuf *, struct mbuf **); int ip6_sysctl(int *, u_int, void *, size_t *, void *, size_t); void ip6_forward(struct mbuf *, struct route *, int); void ip6_mloopback(struct ifnet *, struct mbuf *, struct sockaddr_in6 *); int ip6_output(struct mbuf *, struct ip6_pktopts *, struct route *, int, struct ip6_moptions *, const struct ipsec_level *); int ip6_fragment(struct mbuf *, struct mbuf_list *, int, u_char, u_long); int ip6_ctloutput(int, struct socket *, int, int, struct mbuf *); int ip6_raw_ctloutput(int, struct socket *, int, int, struct mbuf *); void ip6_initpktopts(struct ip6_pktopts *); int ip6_setpktopts(struct mbuf *, struct ip6_pktopts *, struct ip6_pktopts *, int, int); void ip6_clearpktopts(struct ip6_pktopts *, int); void ip6_randomid_init(void); u_int32_t ip6_randomid(void); void ip6_send(struct mbuf *); int route6_input(struct mbuf **, int *, int, int); void frag6_init(void); int frag6_input(struct mbuf **, int *, int, int); int frag6_deletefraghdr(struct mbuf *, int); void frag6_slowtimo(void); void rip6_init(void); int rip6_input(struct mbuf **, int *, int, int); void rip6_ctlinput(int, struct sockaddr *, u_int, void *); int rip6_ctloutput(int, struct socket *, int, int, struct mbuf *); int rip6_output(struct mbuf *, struct socket *, struct sockaddr *, struct mbuf *); int rip6_attach(struct socket *, int, int); int rip6_detach(struct socket *); void rip6_lock(struct socket *); void rip6_unlock(struct socket *); int rip6_locked(struct socket *); int rip6_bind(struct socket *, struct mbuf *, struct proc *); int rip6_connect(struct socket *, struct mbuf *); int rip6_disconnect(struct socket *); int rip6_shutdown(struct socket *); int rip6_send(struct socket *, struct mbuf *, struct mbuf *, struct mbuf *); int rip6_sysctl(int *, u_int, void *, size_t *, void *, size_t); int dest6_input(struct mbuf **, int *, int, int); int in6_pcbselsrc(const struct in6_addr **, struct sockaddr_in6 *, struct inpcb *, struct ip6_pktopts *); int in6_selectsrc(const struct in6_addr **, struct sockaddr_in6 *, struct ip6_moptions *, unsigned int); struct rtentry *in6_selectroute(const struct in6_addr *, struct ip6_pktopts *, struct route *, unsigned int rtableid); u_int32_t ip6_randomflowlabel(void); #ifdef IPSEC struct tdb; int ip6_output_ipsec_lookup(struct mbuf *, const struct ipsec_level *, struct tdb **); int ip6_output_ipsec_send(struct tdb *, struct mbuf *, struct route *, int, int); #endif /* IPSEC */ #endif /* _KERNEL */ #endif /* !_NETINET6_IP6_VAR_H_ */
4 3 5 1 4 2 2 2 2 3 1 8 8 1 6 1 1 6 1 5 5 5 5 5 11 1 5 5 10 5 5 2 2 1 1 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 /* $OpenBSD: pfkeyv2.c,v 1.262 2024/05/17 19:02:04 mvs Exp $ */ /* * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 * * NRL grants permission for redistribution and use in source and binary * forms, with or without modification, of the software and documentation * created at NRL provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgements: * This product includes software developed by the University of * California, Berkeley and its contributors. * This product includes software developed at the Information * Technology Division, US Naval Research Laboratory. * 4. Neither the name of the NRL nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the US Naval * Research Laboratory (NRL). */ /* * Copyright (c) 1995, 1996, 1997, 1998, 1999 Craig Metz. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of any contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "pf.h" #include <sys/param.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/protosw.h> #include <sys/domain.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/kernel.h> #include <sys/proc.h> #include <sys/pool.h> #include <sys/mutex.h> #include <net/route.h> #include <netinet/ip_ipsp.h> #include <net/pfkeyv2.h> #include <net/radix.h> #include <netinet/ip_ah.h> #include <netinet/ip_esp.h> #include <netinet/ip_ipcomp.h> #include <crypto/blf.h> #if NPF > 0 #include <net/if.h> #include <net/pfvar.h> #endif #define PFKEYSNDQ 8192 #define PFKEYRCVQ 8192 static const struct sadb_alg ealgs[] = { { SADB_EALG_NULL, 0, 0, 0 }, { SADB_EALG_3DESCBC, 64, 192, 192 }, { SADB_X_EALG_BLF, 64, 40, BLF_MAXKEYLEN * 8}, { SADB_X_EALG_CAST, 64, 40, 128}, { SADB_X_EALG_AES, 128, 128, 256}, { SADB_X_EALG_AESCTR, 128, 128 + 32, 256 + 32} }; static const struct sadb_alg aalgs[] = { { SADB_AALG_SHA1HMAC, 0, 160, 160 }, { SADB_AALG_MD5HMAC, 0, 128, 128 }, { SADB_X_AALG_RIPEMD160HMAC, 0, 160, 160 }, { SADB_X_AALG_SHA2_256, 0, 256, 256 }, { SADB_X_AALG_SHA2_384, 0, 384, 384 }, { SADB_X_AALG_SHA2_512, 0, 512, 512 } }; static const struct sadb_alg calgs[] = { { SADB_X_CALG_DEFLATE, 0, 0, 0} }; struct pool pkpcb_pool; #define PFKEY_MSG_MAXSZ 4096 const struct sockaddr pfkey_addr = { 2, PF_KEY, }; const struct domain pfkeydomain; /* * pfkey PCB * * Locks used to protect struct members in this file: * I immutable after creation * a atomic operations * l pkptable's lock * s socket lock */ struct pkpcb { struct socket *kcb_socket; /* [I] associated socket */ SRPL_ENTRY(pkpcb) kcb_list; /* [l] */ struct refcnt kcb_refcnt; /* [a] */ int kcb_flags; /* [s] */ uint32_t kcb_reg; /* [s] Inc if SATYPE_MAX > 31 */ uint32_t kcb_pid; /* [I] */ unsigned int kcb_rdomain; /* [I] routing domain */ }; #define sotokeycb(so) ((struct pkpcb *)(so)->so_pcb) #define keylock(kp) solock((kp)->kcb_socket) #define keyunlock(kp) sounlock((kp)->kcb_socket) struct dump_state { struct sadb_msg *sadb_msg; struct socket *socket; }; struct pkptable { SRPL_HEAD(, pkpcb) pkp_list; struct srpl_rc pkp_rc; struct rwlock pkp_lk; }; struct pkptable pkptable; struct mutex pfkeyv2_mtx = MUTEX_INITIALIZER(IPL_MPFLOOR); static uint32_t pfkeyv2_seq = 1; static int nregistered = 0; static int npromisc = 0; void pfkey_init(void); int pfkeyv2_attach(struct socket *, int, int); int pfkeyv2_detach(struct socket *); int pfkeyv2_disconnect(struct socket *); int pfkeyv2_shutdown(struct socket *); int pfkeyv2_send(struct socket *, struct mbuf *, struct mbuf *, struct mbuf *); int pfkeyv2_sockaddr(struct socket *, struct mbuf *); int pfkeyv2_peeraddr(struct socket *, struct mbuf *); int pfkeyv2_output(struct mbuf *, struct socket *); int pfkey_sendup(struct pkpcb *, struct mbuf *, int); int pfkeyv2_sa_flush(struct tdb *, void *, int); int pfkeyv2_policy_flush(struct ipsec_policy *, void *, unsigned int); int pfkeyv2_sysctl_policydumper(struct ipsec_policy *, void *, unsigned int); void keycb_ref(void *, void *); void keycb_unref(void *, void *); /* * Wrapper around m_devget(); copy data from contiguous buffer to mbuf * chain. */ int pfdatatopacket(void *data, int len, struct mbuf **packet) { if (!(*packet = m_devget(data, len, 0))) return (ENOMEM); /* Make sure, all data gets zeroized on free */ (*packet)->m_flags |= M_ZEROIZE; return (0); } const struct pr_usrreqs pfkeyv2_usrreqs = { .pru_attach = pfkeyv2_attach, .pru_detach = pfkeyv2_detach, .pru_disconnect = pfkeyv2_disconnect, .pru_shutdown = pfkeyv2_shutdown, .pru_send = pfkeyv2_send, .pru_sockaddr = pfkeyv2_sockaddr, .pru_peeraddr = pfkeyv2_peeraddr, }; const struct protosw pfkeysw[] = { { .pr_type = SOCK_RAW, .pr_domain = &pfkeydomain, .pr_protocol = PF_KEY_V2, .pr_flags = PR_ATOMIC | PR_ADDR, .pr_usrreqs = &pfkeyv2_usrreqs, .pr_sysctl = pfkeyv2_sysctl, } }; const struct domain pfkeydomain = { .dom_family = PF_KEY, .dom_name = "pfkey", .dom_init = pfkey_init, .dom_protosw = pfkeysw, .dom_protoswNPROTOSW = &pfkeysw[nitems(pfkeysw)], }; void keycb_ref(void *null, void *v) { struct pkpcb *kp = v; refcnt_take(&kp->kcb_refcnt); } void keycb_unref(void *null, void *v) { struct pkpcb *kp = v; refcnt_rele_wake(&kp->kcb_refcnt); } void pfkey_init(void) { rn_init(sizeof(struct sockaddr_encap)); srpl_rc_init(&pkptable.pkp_rc, keycb_ref, keycb_unref, NULL); rw_init(&pkptable.pkp_lk, "pfkey"); SRPL_INIT(&pkptable.pkp_list); pool_init(&pkpcb_pool, sizeof(struct pkpcb), 0, IPL_SOFTNET, PR_WAITOK, "pkpcb", NULL); pool_init(&ipsec_policy_pool, sizeof(struct ipsec_policy), 0, IPL_SOFTNET, 0, "ipsec policy", NULL); pool_init(&ipsec_acquire_pool, sizeof(struct ipsec_acquire), 0, IPL_SOFTNET, 0, "ipsec acquire", NULL); } /* * Attach a new PF_KEYv2 socket. */ int pfkeyv2_attach(struct socket *so, int proto, int wait) { struct pkpcb *kp; int error; if ((so->so_state & SS_PRIV) == 0) return EACCES; error = soreserve(so, PFKEYSNDQ, PFKEYRCVQ); if (error) return (error); kp = pool_get(&pkpcb_pool, (wait == M_WAIT ? PR_WAITOK : PR_NOWAIT) | PR_ZERO); if (kp == NULL) return (ENOBUFS); so->so_pcb = kp; refcnt_init(&kp->kcb_refcnt); kp->kcb_socket = so; kp->kcb_pid = curproc->p_p->ps_pid; kp->kcb_rdomain = rtable_l2(curproc->p_p->ps_rtableid); so->so_options |= SO_USELOOPBACK; soisconnected(so); rw_enter(&pkptable.pkp_lk, RW_WRITE); SRPL_INSERT_HEAD_LOCKED(&pkptable.pkp_rc, &pkptable.pkp_list, kp, kcb_list); rw_exit(&pkptable.pkp_lk); return (0); } /* * Close a PF_KEYv2 socket. */ int pfkeyv2_detach(struct socket *so) { struct pkpcb *kp; soassertlocked(so); kp = sotokeycb(so); if (kp == NULL) return ENOTCONN; if (kp->kcb_flags & (PFKEYV2_SOCKETFLAGS_REGISTERED|PFKEYV2_SOCKETFLAGS_PROMISC)) { mtx_enter(&pfkeyv2_mtx); if (kp->kcb_flags & PFKEYV2_SOCKETFLAGS_REGISTERED) nregistered--; if (kp->kcb_flags & PFKEYV2_SOCKETFLAGS_PROMISC) npromisc--; mtx_leave(&pfkeyv2_mtx); } rw_enter(&pkptable.pkp_lk, RW_WRITE); SRPL_REMOVE_LOCKED(&pkptable.pkp_rc, &pkptable.pkp_list, kp, pkpcb, kcb_list); rw_exit(&pkptable.pkp_lk); sounlock(so); /* wait for all references to drop */ refcnt_finalize(&kp->kcb_refcnt, "pfkeyrefs"); solock(so); so->so_pcb = NULL; KASSERT((so->so_state & SS_NOFDREF) == 0); pool_put(&pkpcb_pool, kp); return (0); } int pfkeyv2_disconnect(struct socket *so) { soisdisconnected(so); return (0); } int pfkeyv2_shutdown(struct socket *so) { socantsendmore(so); return (0); } int pfkeyv2_send(struct socket *so, struct mbuf *m, struct mbuf *nam, struct mbuf *control) { int error; soassertlocked(so); if (control && control->m_len) { error = EOPNOTSUPP; goto out; } if (nam) { error = EISCONN; goto out; } error = pfkeyv2_output(m, so); m = NULL; out: m_freem(control); m_freem(m); return (error); } int pfkeyv2_sockaddr(struct socket *so, struct mbuf *nam) { return (EINVAL); } int pfkeyv2_peeraddr(struct socket *so, struct mbuf *nam) { /* minimal support, just implement a fake peer address */ bcopy(&pfkey_addr, mtod(nam, caddr_t), pfkey_addr.sa_len); nam->m_len = pfkey_addr.sa_len; return (0); } int pfkeyv2_output(struct mbuf *mbuf, struct socket *so) { void *message; int error = 0; #ifdef DIAGNOSTIC if (!mbuf || !(mbuf->m_flags & M_PKTHDR)) { error = EINVAL; goto ret; } #endif /* DIAGNOSTIC */ if (mbuf->m_pkthdr.len > PFKEY_MSG_MAXSZ) { error = EMSGSIZE; goto ret; } if (!(message = malloc((unsigned long) mbuf->m_pkthdr.len, M_PFKEY, M_DONTWAIT))) { error = ENOMEM; goto ret; } m_copydata(mbuf, 0, mbuf->m_pkthdr.len, message); /* * The socket can't be closed concurrently because the file * descriptor reference is still held. */ sounlock(so); error = pfkeyv2_dosend(so, message, mbuf->m_pkthdr.len); solock(so); ret: m_freem(mbuf); return (error); } int pfkey_sendup(struct pkpcb *kp, struct mbuf *m0, int more) { struct socket *so = kp->kcb_socket; struct mbuf *m; int ret; if (more) { if (!(m = m_dup_pkt(m0, 0, M_DONTWAIT))) return (ENOMEM); } else m = m0; mtx_enter(&so->so_rcv.sb_mtx); ret = sbappendaddr(so, &so->so_rcv, &pfkey_addr, m, NULL); mtx_leave(&so->so_rcv.sb_mtx); if (ret == 0) { m_freem(m); return (ENOBUFS); } sorwakeup(so); return (0); } /* * Send a PFKEYv2 message, possibly to many receivers, based on the * satype of the socket (which is set by the REGISTER message), and the * third argument. */ int pfkeyv2_sendmessage(void **headers, int mode, struct socket *so, u_int8_t satype, int count, u_int rdomain) { int i, j, rval; void *p, *buffer = NULL; struct mbuf *packet; struct pkpcb *kp; struct sadb_msg *smsg; struct srp_ref sr; /* Find out how much space we'll need... */ j = sizeof(struct sadb_msg); for (i = 1; i <= SADB_EXT_MAX; i++) if (headers[i]) j += ((struct sadb_ext *)headers[i])->sadb_ext_len * sizeof(uint64_t); /* ...and allocate it */ if (!(buffer = malloc(j + sizeof(struct sadb_msg), M_PFKEY, M_NOWAIT))) { rval = ENOMEM; goto ret; } p = buffer + sizeof(struct sadb_msg); bcopy(headers[0], p, sizeof(struct sadb_msg)); ((struct sadb_msg *) p)->sadb_msg_len = j / sizeof(uint64_t); p += sizeof(struct sadb_msg); /* Copy payloads in the packet */ for (i = 1; i <= SADB_EXT_MAX; i++) if (headers[i]) { ((struct sadb_ext *) headers[i])->sadb_ext_type = i; bcopy(headers[i], p, EXTLEN(headers[i])); p += EXTLEN(headers[i]); } if ((rval = pfdatatopacket(buffer + sizeof(struct sadb_msg), j, &packet)) != 0) goto ret; switch (mode) { case PFKEYV2_SENDMESSAGE_UNICAST: /* * Send message to the specified socket, plus all * promiscuous listeners. */ pfkey_sendup(sotokeycb(so), packet, 0); /* * Promiscuous messages contain the original message * encapsulated in another sadb_msg header. */ bzero(buffer, sizeof(struct sadb_msg)); smsg = (struct sadb_msg *) buffer; smsg->sadb_msg_version = PF_KEY_V2; smsg->sadb_msg_type = SADB_X_PROMISC; smsg->sadb_msg_len = (sizeof(struct sadb_msg) + j) / sizeof(uint64_t); smsg->sadb_msg_seq = 0; /* Copy to mbuf chain */ if ((rval = pfdatatopacket(buffer, sizeof(struct sadb_msg) + j, &packet)) != 0) goto ret; /* * Search for promiscuous listeners, skipping the * original destination. */ SRPL_FOREACH(kp, &sr, &pkptable.pkp_list, kcb_list) { if (kp->kcb_socket == so || kp->kcb_rdomain != rdomain) continue; if (kp->kcb_flags & PFKEYV2_SOCKETFLAGS_PROMISC) pfkey_sendup(kp, packet, 1); } SRPL_LEAVE(&sr); m_freem(packet); break; case PFKEYV2_SENDMESSAGE_REGISTERED: /* * Send the message to all registered sockets that match * the specified satype (e.g., all IPSEC-ESP negotiators) */ SRPL_FOREACH(kp, &sr, &pkptable.pkp_list, kcb_list) { if (kp->kcb_rdomain != rdomain) continue; if (kp->kcb_flags & PFKEYV2_SOCKETFLAGS_REGISTERED) { if (!satype) { /* Just send to everyone registered */ pfkey_sendup(kp, packet, 1); } else { keylock(kp); /* Check for specified satype */ if ((1 << satype) & kp->kcb_reg) pfkey_sendup(kp, packet, 1); keyunlock(kp); } } } SRPL_LEAVE(&sr); /* Free last/original copy of the packet */ m_freem(packet); /* Encapsulate the original message "inside" an sadb_msg header */ bzero(buffer, sizeof(struct sadb_msg)); smsg = (struct sadb_msg *) buffer; smsg->sadb_msg_version = PF_KEY_V2; smsg->sadb_msg_type = SADB_X_PROMISC; smsg->sadb_msg_len = (sizeof(struct sadb_msg) + j) / sizeof(uint64_t); smsg->sadb_msg_seq = 0; /* Convert to mbuf chain */ if ((rval = pfdatatopacket(buffer, sizeof(struct sadb_msg) + j, &packet)) != 0) goto ret; /* Send to all registered promiscuous listeners */ SRPL_FOREACH(kp, &sr, &pkptable.pkp_list, kcb_list) { int flags = READ_ONCE(kp->kcb_flags); if (kp->kcb_rdomain != rdomain) continue; if ((flags & PFKEYV2_SOCKETFLAGS_PROMISC) && !(flags & PFKEYV2_SOCKETFLAGS_REGISTERED)) pfkey_sendup(kp, packet, 1); } SRPL_LEAVE(&sr); m_freem(packet); break; case PFKEYV2_SENDMESSAGE_BROADCAST: /* Send message to all sockets */ SRPL_FOREACH(kp, &sr, &pkptable.pkp_list, kcb_list) { if (kp->kcb_rdomain != rdomain) continue; pfkey_sendup(kp, packet, 1); } SRPL_LEAVE(&sr); m_freem(packet); break; } ret: if (buffer != NULL) { explicit_bzero(buffer, j + sizeof(struct sadb_msg)); free(buffer, M_PFKEY, j + sizeof(struct sadb_msg)); } return (rval); } /* * Get SPD information for an ACQUIRE. We setup the message such that * the SRC/DST payloads are relative to us (regardless of whether the * SPD rule was for incoming or outgoing packets). */ int pfkeyv2_policy(struct ipsec_acquire *ipa, void **headers, void **buffer, int *bufferlen) { union sockaddr_union sunion; struct sadb_protocol *sp; int rval, i, dir; void *p; /* Find out how big a buffer we need */ i = 4 * sizeof(struct sadb_address) + sizeof(struct sadb_protocol); bzero(&sunion, sizeof(union sockaddr_union)); switch (ipa->ipa_info.sen_type) { case SENT_IP4: i += 4 * PADUP(sizeof(struct sockaddr_in)); sunion.sa.sa_family = AF_INET; sunion.sa.sa_len = sizeof(struct sockaddr_in); dir = ipa->ipa_info.sen_direction; break; #ifdef INET6 case SENT_IP6: i += 4 * PADUP(sizeof(struct sockaddr_in6)); sunion.sa.sa_family = AF_INET6; sunion.sa.sa_len = sizeof(struct sockaddr_in6); dir = ipa->ipa_info.sen_ip6_direction; break; #endif /* INET6 */ default: return (EINVAL); } if (!(p = malloc(i, M_PFKEY, M_NOWAIT | M_ZERO))) { rval = ENOMEM; goto ret; } else { *buffer = p; *bufferlen = i; } if (dir == IPSP_DIRECTION_OUT) headers[SADB_X_EXT_SRC_FLOW] = p; else headers[SADB_X_EXT_DST_FLOW] = p; switch (sunion.sa.sa_family) { case AF_INET: sunion.sin.sin_addr = ipa->ipa_info.sen_ip_src; sunion.sin.sin_port = ipa->ipa_info.sen_sport; break; #ifdef INET6 case AF_INET6: sunion.sin6.sin6_addr = ipa->ipa_info.sen_ip6_src; sunion.sin6.sin6_port = ipa->ipa_info.sen_ip6_sport; break; #endif /* INET6 */ } export_address(&p, &sunion.sa); if (dir == IPSP_DIRECTION_OUT) headers[SADB_X_EXT_SRC_MASK] = p; else headers[SADB_X_EXT_DST_MASK] = p; switch (sunion.sa.sa_family) { case AF_INET: sunion.sin.sin_addr = ipa->ipa_mask.sen_ip_src; sunion.sin.sin_port = ipa->ipa_mask.sen_sport; break; #ifdef INET6 case AF_INET6: sunion.sin6.sin6_addr = ipa->ipa_mask.sen_ip6_src; sunion.sin6.sin6_port = ipa->ipa_mask.sen_ip6_sport; break; #endif /* INET6 */ } export_address(&p, &sunion.sa); if (dir == IPSP_DIRECTION_OUT) headers[SADB_X_EXT_DST_FLOW] = p; else headers[SADB_X_EXT_SRC_FLOW] = p; switch (sunion.sa.sa_family) { case AF_INET: sunion.sin.sin_addr = ipa->ipa_info.sen_ip_dst; sunion.sin.sin_port = ipa->ipa_info.sen_dport; break; #ifdef INET6 case AF_INET6: sunion.sin6.sin6_addr = ipa->ipa_info.sen_ip6_dst; sunion.sin6.sin6_port = ipa->ipa_info.sen_ip6_dport; break; #endif /* INET6 */ } export_address(&p, &sunion.sa); if (dir == IPSP_DIRECTION_OUT) headers[SADB_X_EXT_DST_MASK] = p; else headers[SADB_X_EXT_SRC_MASK] = p; switch (sunion.sa.sa_family) { case AF_INET: sunion.sin.sin_addr = ipa->ipa_mask.sen_ip_dst; sunion.sin.sin_port = ipa->ipa_mask.sen_dport; break; #ifdef INET6 case AF_INET6: sunion.sin6.sin6_addr = ipa->ipa_mask.sen_ip6_dst; sunion.sin6.sin6_port = ipa->ipa_mask.sen_ip6_dport; break; #endif /* INET6 */ } export_address(&p, &sunion.sa); headers[SADB_X_EXT_FLOW_TYPE] = p; sp = p; sp->sadb_protocol_len = sizeof(struct sadb_protocol) / sizeof(u_int64_t); switch (sunion.sa.sa_family) { case AF_INET: if (ipa->ipa_mask.sen_proto) sp->sadb_protocol_proto = ipa->ipa_info.sen_proto; sp->sadb_protocol_direction = ipa->ipa_info.sen_direction; break; #ifdef INET6 case AF_INET6: if (ipa->ipa_mask.sen_ip6_proto) sp->sadb_protocol_proto = ipa->ipa_info.sen_ip6_proto; sp->sadb_protocol_direction = ipa->ipa_info.sen_ip6_direction; break; #endif /* INET6 */ } rval = 0; ret: return (rval); } /* * Get all the information contained in an SA to a PFKEYV2 message. */ int pfkeyv2_get(struct tdb *tdb, void **headers, void **buffer, int *lenp, int *lenused) { int rval, i; void *p; NET_ASSERT_LOCKED(); /* Find how much space we need */ i = sizeof(struct sadb_sa) + sizeof(struct sadb_lifetime) + sizeof(struct sadb_x_counter); if (tdb->tdb_soft_allocations || tdb->tdb_soft_bytes || tdb->tdb_soft_timeout || tdb->tdb_soft_first_use) i += sizeof(struct sadb_lifetime); if (tdb->tdb_exp_allocations || tdb->tdb_exp_bytes || tdb->tdb_exp_timeout || tdb->tdb_exp_first_use) i += sizeof(struct sadb_lifetime); if (tdb->tdb_last_used) i += sizeof(struct sadb_lifetime); i += sizeof(struct sadb_address) + PADUP(tdb->tdb_src.sa.sa_len); i += sizeof(struct sadb_address) + PADUP(tdb->tdb_dst.sa.sa_len); if (tdb->tdb_ids) { i += sizeof(struct sadb_ident) + PADUP(tdb->tdb_ids->id_local->len); i += sizeof(struct sadb_ident) + PADUP(tdb->tdb_ids->id_remote->len); } if (tdb->tdb_amxkey) i += sizeof(struct sadb_key) + PADUP(tdb->tdb_amxkeylen); if (tdb->tdb_emxkey) i += sizeof(struct sadb_key) + PADUP(tdb->tdb_emxkeylen); if (tdb->tdb_filter.sen_type) { i += 2 * sizeof(struct sadb_protocol); /* We'll need four of them: src, src mask, dst, dst mask. */ switch (tdb->tdb_filter.sen_type) { case SENT_IP4: i += 4 * PADUP(sizeof(struct sockaddr_in)); i += 4 * sizeof(struct sadb_address); break; #ifdef INET6 case SENT_IP6: i += 4 * PADUP(sizeof(struct sockaddr_in6)); i += 4 * sizeof(struct sadb_address); break; #endif /* INET6 */ default: rval = EINVAL; goto ret; } } if (tdb->tdb_onext) { i += sizeof(struct sadb_sa); i += sizeof(struct sadb_address) + PADUP(tdb->tdb_onext->tdb_dst.sa.sa_len); i += sizeof(struct sadb_protocol); } if (tdb->tdb_udpencap_port) i += sizeof(struct sadb_x_udpencap); i += sizeof(struct sadb_x_replay); if (tdb->tdb_mtu > 0) i+= sizeof(struct sadb_x_mtu); if (tdb->tdb_rdomain != tdb->tdb_rdomain_post) i += sizeof(struct sadb_x_rdomain); #if NPF > 0 if (tdb->tdb_tag) i += sizeof(struct sadb_x_tag) + PADUP(PF_TAG_NAME_SIZE); if (tdb->tdb_tap) i += sizeof(struct sadb_x_tap); #endif if (ISSET(tdb->tdb_flags, TDBF_IFACE)) i += sizeof(struct sadb_x_iface); if (lenp) *lenp = i; if (buffer == NULL) { rval = 0; goto ret; } if (!(p = malloc(i, M_PFKEY, M_NOWAIT | M_ZERO))) { rval = ENOMEM; goto ret; } else *buffer = p; headers[SADB_EXT_SA] = p; export_sa(&p, tdb); /* Export SA information (mostly flags) */ /* Export lifetimes where applicable */ headers[SADB_EXT_LIFETIME_CURRENT] = p; export_lifetime(&p, tdb, PFKEYV2_LIFETIME_CURRENT); if (tdb->tdb_soft_allocations || tdb->tdb_soft_bytes || tdb->tdb_soft_first_use || tdb->tdb_soft_timeout) { headers[SADB_EXT_LIFETIME_SOFT] = p; export_lifetime(&p, tdb, PFKEYV2_LIFETIME_SOFT); } if (tdb->tdb_exp_allocations || tdb->tdb_exp_bytes || tdb->tdb_exp_first_use || tdb->tdb_exp_timeout) { headers[SADB_EXT_LIFETIME_HARD] = p; export_lifetime(&p, tdb, PFKEYV2_LIFETIME_HARD); } if (tdb->tdb_last_used) { headers[SADB_X_EXT_LIFETIME_LASTUSE] = p; export_lifetime(&p, tdb, PFKEYV2_LIFETIME_LASTUSE); } /* Export TDB source address */ headers[SADB_EXT_ADDRESS_SRC] = p; export_address(&p, &tdb->tdb_src.sa); /* Export TDB destination address */ headers[SADB_EXT_ADDRESS_DST] = p; export_address(&p, &tdb->tdb_dst.sa); /* Export source/destination identities, if present */ if (tdb->tdb_ids) export_identities(&p, tdb->tdb_ids, tdb->tdb_ids_swapped, headers); /* Export authentication key, if present */ if (tdb->tdb_amxkey) { headers[SADB_EXT_KEY_AUTH] = p; export_key(&p, tdb, PFKEYV2_AUTHENTICATION_KEY); } /* Export encryption key, if present */ if (tdb->tdb_emxkey) { headers[SADB_EXT_KEY_ENCRYPT] = p; export_key(&p, tdb, PFKEYV2_ENCRYPTION_KEY); } /* Export flow/filter, if present */ if (tdb->tdb_filter.sen_type) export_flow(&p, IPSP_IPSEC_USE, &tdb->tdb_filter, &tdb->tdb_filtermask, headers); if (tdb->tdb_onext) { headers[SADB_X_EXT_SA2] = p; export_sa(&p, tdb->tdb_onext); headers[SADB_X_EXT_DST2] = p; export_address(&p, &tdb->tdb_onext->tdb_dst.sa); headers[SADB_X_EXT_SATYPE2] = p; export_satype(&p, tdb->tdb_onext); } /* Export UDP encapsulation port, if present */ if (tdb->tdb_udpencap_port) { headers[SADB_X_EXT_UDPENCAP] = p; export_udpencap(&p, tdb); } headers[SADB_X_EXT_REPLAY] = p; export_replay(&p, tdb); if (tdb->tdb_mtu > 0) { headers[SADB_X_EXT_MTU] = p; export_mtu(&p, tdb); } /* Export rdomain switch, if present */ if (tdb->tdb_rdomain != tdb->tdb_rdomain_post) { headers[SADB_X_EXT_RDOMAIN] = p; export_rdomain(&p, tdb); } #if NPF > 0 /* Export tag information, if present */ if (tdb->tdb_tag) { headers[SADB_X_EXT_TAG] = p; export_tag(&p, tdb); } /* Export tap enc(4) device information, if present */ if (tdb->tdb_tap) { headers[SADB_X_EXT_TAP] = p; export_tap(&p, tdb); } #endif /* Export sec(4) interface information, if present */ if (ISSET(tdb->tdb_flags, TDBF_IFACE)) { headers[SADB_X_EXT_IFACE] = p; export_iface(&p, tdb); } headers[SADB_X_EXT_COUNTER] = p; export_counter(&p, tdb); if (lenused) *lenused = p - *buffer; rval = 0; ret: return (rval); } /* * Dump a TDB. */ int pfkeyv2_dump_walker(struct tdb *tdb, void *state, int last) { struct dump_state *dump_state = (struct dump_state *) state; void *headers[SADB_EXT_MAX+1], *buffer; int buflen; int rval; /* If not satype was specified, dump all TDBs */ if (!dump_state->sadb_msg->sadb_msg_satype || (tdb->tdb_satype == dump_state->sadb_msg->sadb_msg_satype)) { bzero(headers, sizeof(headers)); headers[0] = (void *) dump_state->sadb_msg; /* Get the information from the TDB to a PFKEYv2 message */ if ((rval = pfkeyv2_get(tdb, headers, &buffer, &buflen, NULL)) != 0) return (rval); if (last) ((struct sadb_msg *)headers[0])->sadb_msg_seq = 0; /* Send the message to the specified socket */ rval = pfkeyv2_sendmessage(headers, PFKEYV2_SENDMESSAGE_UNICAST, dump_state->socket, 0, 0, tdb->tdb_rdomain); explicit_bzero(buffer, buflen); free(buffer, M_PFKEY, buflen); if (rval) return (rval); } return (0); } /* * Delete an SA. */ int pfkeyv2_sa_flush(struct tdb *tdb, void *satype_vp, int last) { if (!(*((u_int8_t *) satype_vp)) || tdb->tdb_satype == *((u_int8_t *) satype_vp)) tdb_delete(tdb); return (0); } /* * Convert between SATYPEs and IPsec protocols, taking into consideration * sysctl variables enabling/disabling ESP/AH and the presence of the old * IPsec transforms. */ int pfkeyv2_get_proto_alg(u_int8_t satype, u_int8_t *sproto, int *alg) { switch (satype) { #ifdef IPSEC case SADB_SATYPE_AH: if (!ah_enable) return (EOPNOTSUPP); *sproto = IPPROTO_AH; if(alg != NULL) *alg = satype = XF_AH; break; case SADB_SATYPE_ESP: if (!esp_enable) return (EOPNOTSUPP); *sproto = IPPROTO_ESP; if(alg != NULL) *alg = satype = XF_ESP; break; case SADB_X_SATYPE_IPIP: *sproto = IPPROTO_IPIP; if (alg != NULL) *alg = XF_IP4; break; case SADB_X_SATYPE_IPCOMP: if (!ipcomp_enable) return (EOPNOTSUPP); *sproto = IPPROTO_IPCOMP; if(alg != NULL) *alg = satype = XF_IPCOMP; break; #endif /* IPSEC */ #ifdef TCP_SIGNATURE case SADB_X_SATYPE_TCPSIGNATURE: *sproto = IPPROTO_TCP; if (alg != NULL) *alg = XF_TCPSIGNATURE; break; #endif /* TCP_SIGNATURE */ default: /* Nothing else supported */ return (EOPNOTSUPP); } return (0); } /* * Handle all messages from userland to kernel. */ int pfkeyv2_dosend(struct socket *so, void *message, int len) { int i, j, rval = 0, mode = PFKEYV2_SENDMESSAGE_BROADCAST; int delflag = 0; struct sockaddr_encap encapdst, encapnetmask; struct ipsec_policy *ipo; struct ipsec_acquire *ipa; struct radix_node_head *rnh; struct radix_node *rn = NULL; struct pkpcb *kp, *bkp; void *freeme = NULL, *freeme2 = NULL, *freeme3 = NULL; int freeme_sz = 0, freeme2_sz = 0, freeme3_sz = 0; void *bckptr = NULL; void *headers[SADB_EXT_MAX + 1]; union sockaddr_union *sunionp; struct tdb *sa1 = NULL, *sa2 = NULL; struct sadb_msg *smsg; struct sadb_spirange *sprng; struct sadb_sa *ssa; struct sadb_supported *ssup; struct sadb_ident *sid, *did; struct srp_ref sr; struct sadb_x_rdomain *srdomain; u_int rdomain = 0; int promisc; mtx_enter(&pfkeyv2_mtx); promisc = npromisc; mtx_leave(&pfkeyv2_mtx); /* Verify that we received this over a legitimate pfkeyv2 socket */ bzero(headers, sizeof(headers)); kp = sotokeycb(so); if (!kp) { rval = EINVAL; goto ret; } rdomain = kp->kcb_rdomain; /* Validate message format */ if ((rval = pfkeyv2_parsemessage(message, len, headers)) != 0) goto ret; /* If we have any promiscuous listeners, send them a copy of the message */ if (promisc) { struct mbuf *packet; freeme_sz = sizeof(struct sadb_msg) + len; if (!(freeme = malloc(freeme_sz, M_PFKEY, M_NOWAIT))) { rval = ENOMEM; goto ret; } /* Initialize encapsulating header */ bzero(freeme, sizeof(struct sadb_msg)); smsg = (struct sadb_msg *) freeme; smsg->sadb_msg_version = PF_KEY_V2; smsg->sadb_msg_type = SADB_X_PROMISC; smsg->sadb_msg_len = (sizeof(struct sadb_msg) + len) / sizeof(uint64_t); smsg->sadb_msg_seq = curproc->p_p->ps_pid; bcopy(message, freeme + sizeof(struct sadb_msg), len); /* Convert to mbuf chain */ if ((rval = pfdatatopacket(freeme, freeme_sz, &packet)) != 0) goto ret; /* Send to all promiscuous listeners */ SRPL_FOREACH(bkp, &sr, &pkptable.pkp_list, kcb_list) { if (bkp->kcb_rdomain != kp->kcb_rdomain) continue; if (bkp->kcb_flags & PFKEYV2_SOCKETFLAGS_PROMISC) pfkey_sendup(bkp, packet, 1); } SRPL_LEAVE(&sr); m_freem(packet); /* Paranoid */ explicit_bzero(freeme, freeme_sz); free(freeme, M_PFKEY, freeme_sz); freeme = NULL; freeme_sz = 0; } /* use specified rdomain */ srdomain = (struct sadb_x_rdomain *) headers[SADB_X_EXT_RDOMAIN]; if (srdomain) { if (!rtable_exists(srdomain->sadb_x_rdomain_dom1) || !rtable_exists(srdomain->sadb_x_rdomain_dom2)) { rval = EINVAL; goto ret; } rdomain = srdomain->sadb_x_rdomain_dom1; } smsg = (struct sadb_msg *) headers[0]; switch (smsg->sadb_msg_type) { case SADB_GETSPI: /* Reserve an SPI */ sa1 = malloc(sizeof (*sa1), M_PFKEY, M_NOWAIT | M_ZERO); if (sa1 == NULL) { rval = ENOMEM; goto ret; } sa1->tdb_satype = smsg->sadb_msg_satype; if ((rval = pfkeyv2_get_proto_alg(sa1->tdb_satype, &sa1->tdb_sproto, 0))) goto ret; import_address(&sa1->tdb_src.sa, headers[SADB_EXT_ADDRESS_SRC]); import_address(&sa1->tdb_dst.sa, headers[SADB_EXT_ADDRESS_DST]); /* Find an unused SA identifier */ sprng = (struct sadb_spirange *) headers[SADB_EXT_SPIRANGE]; NET_LOCK(); sa1->tdb_spi = reserve_spi(rdomain, sprng->sadb_spirange_min, sprng->sadb_spirange_max, &sa1->tdb_src, &sa1->tdb_dst, sa1->tdb_sproto, &rval); if (sa1->tdb_spi == 0) { NET_UNLOCK(); goto ret; } /* Send a message back telling what the SA (the SPI really) is */ freeme_sz = sizeof(struct sadb_sa); if (!(freeme = malloc(freeme_sz, M_PFKEY, M_NOWAIT | M_ZERO))) { rval = ENOMEM; NET_UNLOCK(); goto ret; } headers[SADB_EXT_SPIRANGE] = NULL; headers[SADB_EXT_SA] = freeme; bckptr = freeme; /* We really only care about the SPI, but we'll export the SA */ export_sa((void **) &bckptr, sa1); NET_UNLOCK(); break; case SADB_UPDATE: ssa = (struct sadb_sa *) headers[SADB_EXT_SA]; sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] + sizeof(struct sadb_address)); /* Either all or none of the flow must be included */ if ((headers[SADB_X_EXT_SRC_FLOW] || headers[SADB_X_EXT_PROTOCOL] || headers[SADB_X_EXT_FLOW_TYPE] || headers[SADB_X_EXT_DST_FLOW] || headers[SADB_X_EXT_SRC_MASK] || headers[SADB_X_EXT_DST_MASK]) && !(headers[SADB_X_EXT_SRC_FLOW] && headers[SADB_X_EXT_PROTOCOL] && headers[SADB_X_EXT_FLOW_TYPE] && headers[SADB_X_EXT_DST_FLOW] && headers[SADB_X_EXT_SRC_MASK] && headers[SADB_X_EXT_DST_MASK])) { rval = EINVAL; goto ret; } #ifdef IPSEC /* UDP encap has to be enabled and is only supported for ESP */ if (headers[SADB_X_EXT_UDPENCAP] && (!udpencap_enable || smsg->sadb_msg_satype != SADB_SATYPE_ESP)) { rval = EINVAL; goto ret; } #endif /* IPSEC */ /* Find TDB */ NET_LOCK(); sa2 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp, SADB_X_GETSPROTO(smsg->sadb_msg_satype)); /* If there's no such SA, we're done */ if (sa2 == NULL) { rval = ESRCH; NET_UNLOCK(); goto ret; } /* If this is a reserved SA */ if (sa2->tdb_flags & TDBF_INVALID) { struct tdb *newsa; struct ipsecinit ii; int alg; /* Create new TDB */ newsa = tdb_alloc(rdomain); newsa->tdb_satype = smsg->sadb_msg_satype; if ((rval = pfkeyv2_get_proto_alg(newsa->tdb_satype, &newsa->tdb_sproto, &alg))) { tdb_unref(newsa); NET_UNLOCK(); goto ret; } /* Initialize SA */ bzero(&ii, sizeof(struct ipsecinit)); import_sa(newsa, headers[SADB_EXT_SA], &ii); import_address(&newsa->tdb_src.sa, headers[SADB_EXT_ADDRESS_SRC]); import_address(&newsa->tdb_dst.sa, headers[SADB_EXT_ADDRESS_DST]); import_lifetime(newsa, headers[SADB_EXT_LIFETIME_CURRENT], PFKEYV2_LIFETIME_CURRENT); import_lifetime(newsa, headers[SADB_EXT_LIFETIME_SOFT], PFKEYV2_LIFETIME_SOFT); import_lifetime(newsa, headers[SADB_EXT_LIFETIME_HARD], PFKEYV2_LIFETIME_HARD); import_key(&ii, headers[SADB_EXT_KEY_AUTH], PFKEYV2_AUTHENTICATION_KEY); import_key(&ii, headers[SADB_EXT_KEY_ENCRYPT], PFKEYV2_ENCRYPTION_KEY); newsa->tdb_ids_swapped = 1; /* only on TDB_UPDATE */ import_identities(&newsa->tdb_ids, newsa->tdb_ids_swapped, headers[SADB_EXT_IDENTITY_SRC], headers[SADB_EXT_IDENTITY_DST]); if ((rval = import_flow(&newsa->tdb_filter, &newsa->tdb_filtermask, headers[SADB_X_EXT_SRC_FLOW], headers[SADB_X_EXT_SRC_MASK], headers[SADB_X_EXT_DST_FLOW], headers[SADB_X_EXT_DST_MASK], headers[SADB_X_EXT_PROTOCOL], headers[SADB_X_EXT_FLOW_TYPE]))) { tdb_unref(newsa); NET_UNLOCK(); goto ret; } import_udpencap(newsa, headers[SADB_X_EXT_UDPENCAP]); import_rdomain(newsa, headers[SADB_X_EXT_RDOMAIN]); #if NPF > 0 import_tag(newsa, headers[SADB_X_EXT_TAG]); import_tap(newsa, headers[SADB_X_EXT_TAP]); #endif import_iface(newsa, headers[SADB_X_EXT_IFACE]); /* Exclude sensitive data from reply message. */ headers[SADB_EXT_KEY_AUTH] = NULL; headers[SADB_EXT_KEY_ENCRYPT] = NULL; headers[SADB_X_EXT_LOCAL_AUTH] = NULL; headers[SADB_X_EXT_REMOTE_AUTH] = NULL; newsa->tdb_seq = smsg->sadb_msg_seq; rval = tdb_init(newsa, alg, &ii); if (rval) { rval = EINVAL; tdb_unref(newsa); NET_UNLOCK(); goto ret; } newsa->tdb_cur_allocations = sa2->tdb_cur_allocations; /* Delete old version of the SA, insert new one */ tdb_delete(sa2); tdb_addtimeouts(newsa); puttdb(newsa); } else { /* * The SA is already initialized, so we're only allowed to * change lifetimes and some other information; we're * not allowed to change keys, addresses or identities. */ if (headers[SADB_EXT_KEY_AUTH] || headers[SADB_EXT_KEY_ENCRYPT] || headers[SADB_EXT_IDENTITY_SRC] || headers[SADB_EXT_IDENTITY_DST] || headers[SADB_EXT_SENSITIVITY]) { rval = EINVAL; NET_UNLOCK(); goto ret; } import_sa(sa2, headers[SADB_EXT_SA], NULL); import_lifetime(sa2, headers[SADB_EXT_LIFETIME_CURRENT], PFKEYV2_LIFETIME_CURRENT); import_lifetime(sa2, headers[SADB_EXT_LIFETIME_SOFT], PFKEYV2_LIFETIME_SOFT); import_lifetime(sa2, headers[SADB_EXT_LIFETIME_HARD], PFKEYV2_LIFETIME_HARD); import_udpencap(sa2, headers[SADB_X_EXT_UDPENCAP]); #if NPF > 0 import_tag(sa2, headers[SADB_X_EXT_TAG]); import_tap(sa2, headers[SADB_X_EXT_TAP]); #endif import_iface(sa2, headers[SADB_X_EXT_IFACE]); tdb_addtimeouts(sa2); if (headers[SADB_EXT_ADDRESS_SRC] || headers[SADB_EXT_ADDRESS_PROXY]) { mtx_enter(&tdb_sadb_mtx); tdb_unlink_locked(sa2); import_address((struct sockaddr *)&sa2->tdb_src, headers[SADB_EXT_ADDRESS_SRC]); import_address((struct sockaddr *)&sa2->tdb_dst, headers[SADB_EXT_ADDRESS_PROXY]); puttdb_locked(sa2); mtx_leave(&tdb_sadb_mtx); } } NET_UNLOCK(); break; case SADB_ADD: ssa = (struct sadb_sa *) headers[SADB_EXT_SA]; sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] + sizeof(struct sadb_address)); /* Either all or none of the flow must be included */ if ((headers[SADB_X_EXT_SRC_FLOW] || headers[SADB_X_EXT_PROTOCOL] || headers[SADB_X_EXT_FLOW_TYPE] || headers[SADB_X_EXT_DST_FLOW] || headers[SADB_X_EXT_SRC_MASK] || headers[SADB_X_EXT_DST_MASK]) && !(headers[SADB_X_EXT_SRC_FLOW] && headers[SADB_X_EXT_PROTOCOL] && headers[SADB_X_EXT_FLOW_TYPE] && headers[SADB_X_EXT_DST_FLOW] && headers[SADB_X_EXT_SRC_MASK] && headers[SADB_X_EXT_DST_MASK])) { rval = EINVAL; goto ret; } #ifdef IPSEC /* UDP encap has to be enabled and is only supported for ESP */ if (headers[SADB_X_EXT_UDPENCAP] && (!udpencap_enable || smsg->sadb_msg_satype != SADB_SATYPE_ESP)) { rval = EINVAL; goto ret; } #endif /* IPSEC */ NET_LOCK(); sa2 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp, SADB_X_GETSPROTO(smsg->sadb_msg_satype)); /* We can't add an existing SA! */ if (sa2 != NULL) { rval = EEXIST; NET_UNLOCK(); goto ret; } /* We can only add "mature" SAs */ if (ssa->sadb_sa_state != SADB_SASTATE_MATURE) { rval = EINVAL; NET_UNLOCK(); goto ret; } { struct tdb *newsa; struct ipsecinit ii; int alg; /* Create new TDB */ newsa = tdb_alloc(rdomain); newsa->tdb_satype = smsg->sadb_msg_satype; if ((rval = pfkeyv2_get_proto_alg(newsa->tdb_satype, &newsa->tdb_sproto, &alg))) { tdb_unref(newsa); NET_UNLOCK(); goto ret; } /* Initialize SA */ bzero(&ii, sizeof(struct ipsecinit)); import_sa(newsa, headers[SADB_EXT_SA], &ii); import_address(&newsa->tdb_src.sa, headers[SADB_EXT_ADDRESS_SRC]); import_address(&newsa->tdb_dst.sa, headers[SADB_EXT_ADDRESS_DST]); import_lifetime(newsa, headers[SADB_EXT_LIFETIME_CURRENT], PFKEYV2_LIFETIME_CURRENT); import_lifetime(newsa, headers[SADB_EXT_LIFETIME_SOFT], PFKEYV2_LIFETIME_SOFT); import_lifetime(newsa, headers[SADB_EXT_LIFETIME_HARD], PFKEYV2_LIFETIME_HARD); import_key(&ii, headers[SADB_EXT_KEY_AUTH], PFKEYV2_AUTHENTICATION_KEY); import_key(&ii, headers[SADB_EXT_KEY_ENCRYPT], PFKEYV2_ENCRYPTION_KEY); import_identities(&newsa->tdb_ids, newsa->tdb_ids_swapped, headers[SADB_EXT_IDENTITY_SRC], headers[SADB_EXT_IDENTITY_DST]); if ((rval = import_flow(&newsa->tdb_filter, &newsa->tdb_filtermask, headers[SADB_X_EXT_SRC_FLOW], headers[SADB_X_EXT_SRC_MASK], headers[SADB_X_EXT_DST_FLOW], headers[SADB_X_EXT_DST_MASK], headers[SADB_X_EXT_PROTOCOL], headers[SADB_X_EXT_FLOW_TYPE]))) { tdb_unref(newsa); NET_UNLOCK(); goto ret; } import_udpencap(newsa, headers[SADB_X_EXT_UDPENCAP]); import_rdomain(newsa, headers[SADB_X_EXT_RDOMAIN]); #if NPF > 0 import_tag(newsa, headers[SADB_X_EXT_TAG]); import_tap(newsa, headers[SADB_X_EXT_TAP]); #endif import_iface(newsa, headers[SADB_X_EXT_IFACE]); /* Exclude sensitive data from reply message. */ headers[SADB_EXT_KEY_AUTH] = NULL; headers[SADB_EXT_KEY_ENCRYPT] = NULL; headers[SADB_X_EXT_LOCAL_AUTH] = NULL; headers[SADB_X_EXT_REMOTE_AUTH] = NULL; newsa->tdb_seq = smsg->sadb_msg_seq; rval = tdb_init(newsa, alg, &ii); if (rval) { rval = EINVAL; tdb_unref(newsa); NET_UNLOCK(); goto ret; } tdb_addtimeouts(newsa); /* Add TDB in table */ puttdb(newsa); } NET_UNLOCK(); break; case SADB_DELETE: ssa = (struct sadb_sa *) headers[SADB_EXT_SA]; sunionp = (union sockaddr_union *)(headers[SADB_EXT_ADDRESS_DST] + sizeof(struct sadb_address)); NET_LOCK(); sa2 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp, SADB_X_GETSPROTO(smsg->sadb_msg_satype)); if (sa2 == NULL) { rval = ESRCH; NET_UNLOCK(); goto ret; } tdb_delete(sa2); NET_UNLOCK(); break; case SADB_X_ASKPOLICY: /* Get the relevant policy */ NET_LOCK(); ipa = ipsec_get_acquire(((struct sadb_x_policy *) headers[SADB_X_EXT_POLICY])->sadb_x_policy_seq); if (ipa == NULL) { rval = ESRCH; NET_UNLOCK(); goto ret; } rval = pfkeyv2_policy(ipa, headers, &freeme, &freeme_sz); NET_UNLOCK(); ipsec_unref_acquire(ipa); if (rval) mode = PFKEYV2_SENDMESSAGE_UNICAST; break; case SADB_GET: ssa = (struct sadb_sa *) headers[SADB_EXT_SA]; sunionp = (union sockaddr_union *)(headers[SADB_EXT_ADDRESS_DST] + sizeof(struct sadb_address)); NET_LOCK(); sa2 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp, SADB_X_GETSPROTO(smsg->sadb_msg_satype)); if (sa2 == NULL) { rval = ESRCH; NET_UNLOCK(); goto ret; } rval = pfkeyv2_get(sa2, headers, &freeme, &freeme_sz, NULL); NET_UNLOCK(); if (rval) mode = PFKEYV2_SENDMESSAGE_UNICAST; break; case SADB_REGISTER: keylock(kp); if (!(kp->kcb_flags & PFKEYV2_SOCKETFLAGS_REGISTERED)) { kp->kcb_flags |= PFKEYV2_SOCKETFLAGS_REGISTERED; mtx_enter(&pfkeyv2_mtx); nregistered++; mtx_leave(&pfkeyv2_mtx); } keyunlock(kp); freeme_sz = sizeof(struct sadb_supported) + sizeof(ealgs); if (!(freeme = malloc(freeme_sz, M_PFKEY, M_NOWAIT | M_ZERO))) { rval = ENOMEM; goto ret; } ssup = (struct sadb_supported *) freeme; ssup->sadb_supported_len = freeme_sz / sizeof(uint64_t); { void *p = freeme + sizeof(struct sadb_supported); bcopy(&ealgs[0], p, sizeof(ealgs)); } headers[SADB_EXT_SUPPORTED_ENCRYPT] = freeme; freeme2_sz = sizeof(struct sadb_supported) + sizeof(aalgs); if (!(freeme2 = malloc(freeme2_sz, M_PFKEY, M_NOWAIT | M_ZERO))) { rval = ENOMEM; goto ret; } /* Keep track what this socket has registered for */ keylock(kp); kp->kcb_reg |= (1 << ((struct sadb_msg *)message)->sadb_msg_satype); keyunlock(kp); ssup = (struct sadb_supported *) freeme2; ssup->sadb_supported_len = freeme2_sz / sizeof(uint64_t); { void *p = freeme2 + sizeof(struct sadb_supported); bcopy(&aalgs[0], p, sizeof(aalgs)); } headers[SADB_EXT_SUPPORTED_AUTH] = freeme2; freeme3_sz = sizeof(struct sadb_supported) + sizeof(calgs); if (!(freeme3 = malloc(freeme3_sz, M_PFKEY, M_NOWAIT | M_ZERO))) { rval = ENOMEM; goto ret; } ssup = (struct sadb_supported *) freeme3; ssup->sadb_supported_len = freeme3_sz / sizeof(uint64_t); { void *p = freeme3 + sizeof(struct sadb_supported); bcopy(&calgs[0], p, sizeof(calgs)); } headers[SADB_X_EXT_SUPPORTED_COMP] = freeme3; break; case SADB_ACQUIRE: case SADB_EXPIRE: /* Nothing to handle */ rval = 0; break; case SADB_FLUSH: rval = 0; NET_LOCK(); switch (smsg->sadb_msg_satype) { case SADB_SATYPE_UNSPEC: spd_table_walk(rdomain, pfkeyv2_policy_flush, NULL); /* FALLTHROUGH */ case SADB_SATYPE_AH: case SADB_SATYPE_ESP: case SADB_X_SATYPE_IPIP: case SADB_X_SATYPE_IPCOMP: #ifdef TCP_SIGNATURE case SADB_X_SATYPE_TCPSIGNATURE: #endif /* TCP_SIGNATURE */ tdb_walk(rdomain, pfkeyv2_sa_flush, (u_int8_t *) &(smsg->sadb_msg_satype)); break; default: rval = EINVAL; /* Unknown/unsupported type */ } NET_UNLOCK(); break; case SADB_DUMP: { struct dump_state dump_state; dump_state.sadb_msg = (struct sadb_msg *) headers[0]; dump_state.socket = so; NET_LOCK(); rval = tdb_walk(rdomain, pfkeyv2_dump_walker, &dump_state); NET_UNLOCK(); if (!rval) goto realret; if ((rval == ENOMEM) || (rval == ENOBUFS)) rval = 0; } break; case SADB_X_GRPSPIS: { struct tdb *tdb1, *tdb2, *tdb3; struct sadb_protocol *sa_proto; ssa = (struct sadb_sa *) headers[SADB_EXT_SA]; sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] + sizeof(struct sadb_address)); NET_LOCK(); tdb1 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp, SADB_X_GETSPROTO(smsg->sadb_msg_satype)); if (tdb1 == NULL) { rval = ESRCH; NET_UNLOCK(); goto ret; } ssa = (struct sadb_sa *) headers[SADB_X_EXT_SA2]; sunionp = (union sockaddr_union *) (headers[SADB_X_EXT_DST2] + sizeof(struct sadb_address)); sa_proto = (struct sadb_protocol *) headers[SADB_X_EXT_SATYPE2]; /* optionally fetch tdb2 from rdomain2 */ tdb2 = gettdb(srdomain ? srdomain->sadb_x_rdomain_dom2 : rdomain, ssa->sadb_sa_spi, sunionp, SADB_X_GETSPROTO(sa_proto->sadb_protocol_proto)); if (tdb2 == NULL) { tdb_unref(tdb1); rval = ESRCH; NET_UNLOCK(); goto ret; } /* Detect cycles */ for (tdb3 = tdb2; tdb3; tdb3 = tdb3->tdb_onext) if (tdb3 == tdb1) { tdb_unref(tdb1); tdb_unref(tdb2); rval = ESRCH; NET_UNLOCK(); goto ret; } /* Maintenance */ if ((tdb1->tdb_onext) && (tdb1->tdb_onext->tdb_inext == tdb1)) { tdb_unref(tdb1->tdb_onext->tdb_inext); tdb1->tdb_onext->tdb_inext = NULL; } if ((tdb2->tdb_inext) && (tdb2->tdb_inext->tdb_onext == tdb2)) { tdb_unref(tdb2->tdb_inext->tdb_onext); tdb2->tdb_inext->tdb_onext = NULL; } /* Link them */ tdb1->tdb_onext = tdb2; tdb2->tdb_inext = tdb1; NET_UNLOCK(); } break; case SADB_X_DELFLOW: delflag = 1; /*FALLTHROUGH*/ case SADB_X_ADDFLOW: { struct sadb_protocol *sab; union sockaddr_union *ssrc; int exists = 0; NET_LOCK(); if ((rnh = spd_table_add(rdomain)) == NULL) { rval = ENOMEM; NET_UNLOCK(); goto ret; } sab = (struct sadb_protocol *) headers[SADB_X_EXT_FLOW_TYPE]; if ((sab->sadb_protocol_direction != IPSP_DIRECTION_IN) && (sab->sadb_protocol_direction != IPSP_DIRECTION_OUT)) { rval = EINVAL; NET_UNLOCK(); goto ret; } /* If the security protocol wasn't specified, pretend it was ESP */ if (smsg->sadb_msg_satype == 0) smsg->sadb_msg_satype = SADB_SATYPE_ESP; if (headers[SADB_EXT_ADDRESS_DST]) sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] + sizeof(struct sadb_address)); else sunionp = NULL; if (headers[SADB_EXT_ADDRESS_SRC]) ssrc = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_SRC] + sizeof(struct sadb_address)); else ssrc = NULL; if ((rval = import_flow(&encapdst, &encapnetmask, headers[SADB_X_EXT_SRC_FLOW], headers[SADB_X_EXT_SRC_MASK], headers[SADB_X_EXT_DST_FLOW], headers[SADB_X_EXT_DST_MASK], headers[SADB_X_EXT_PROTOCOL], headers[SADB_X_EXT_FLOW_TYPE]))) { NET_UNLOCK(); goto ret; } /* Determine whether the exact same SPD entry already exists. */ if ((rn = rn_match(&encapdst, rnh)) != NULL) { ipo = (struct ipsec_policy *)rn; /* Verify that the entry is identical */ if (bcmp(&ipo->ipo_addr, &encapdst, sizeof(struct sockaddr_encap)) || bcmp(&ipo->ipo_mask, &encapnetmask, sizeof(struct sockaddr_encap))) ipo = NULL; /* Fall through */ else exists = 1; } else ipo = NULL; /* * If the existing policy is static, only delete or update * it if the new one is also static. */ if (exists && (ipo->ipo_flags & IPSP_POLICY_STATIC)) { if (!(sab->sadb_protocol_flags & SADB_X_POLICYFLAGS_POLICY)) { NET_UNLOCK(); goto ret; } } /* Delete ? */ if (delflag) { if (exists) { rval = ipsec_delete_policy(ipo); NET_UNLOCK(); goto ret; } /* If we were asked to delete something non-existent, error. */ rval = ESRCH; NET_UNLOCK(); break; } if (!exists) { /* Allocate policy entry */ ipo = pool_get(&ipsec_policy_pool, PR_NOWAIT|PR_ZERO); if (ipo == NULL) { rval = ENOMEM; NET_UNLOCK(); goto ret; } } switch (sab->sadb_protocol_proto) { case SADB_X_FLOW_TYPE_USE: ipo->ipo_type = IPSP_IPSEC_USE; break; case SADB_X_FLOW_TYPE_ACQUIRE: ipo->ipo_type = IPSP_IPSEC_ACQUIRE; break; case SADB_X_FLOW_TYPE_REQUIRE: ipo->ipo_type = IPSP_IPSEC_REQUIRE; break; case SADB_X_FLOW_TYPE_DENY: ipo->ipo_type = IPSP_DENY; break; case SADB_X_FLOW_TYPE_BYPASS: ipo->ipo_type = IPSP_PERMIT; break; case SADB_X_FLOW_TYPE_DONTACQ: ipo->ipo_type = IPSP_IPSEC_DONTACQ; break; default: if (!exists) pool_put(&ipsec_policy_pool, ipo); else ipsec_delete_policy(ipo); rval = EINVAL; NET_UNLOCK(); goto ret; } if (sab->sadb_protocol_flags & SADB_X_POLICYFLAGS_POLICY) ipo->ipo_flags |= IPSP_POLICY_STATIC; if (sunionp) bcopy(sunionp, &ipo->ipo_dst, sizeof(union sockaddr_union)); else bzero(&ipo->ipo_dst, sizeof(union sockaddr_union)); if (ssrc) bcopy(ssrc, &ipo->ipo_src, sizeof(union sockaddr_union)); else bzero(&ipo->ipo_src, sizeof(union sockaddr_union)); ipo->ipo_sproto = SADB_X_GETSPROTO(smsg->sadb_msg_satype); if (ipo->ipo_ids) { ipsp_ids_free(ipo->ipo_ids); ipo->ipo_ids = NULL; } if ((sid = headers[SADB_EXT_IDENTITY_SRC]) != NULL && (did = headers[SADB_EXT_IDENTITY_DST]) != NULL) { import_identities(&ipo->ipo_ids, 0, sid, did); if (ipo->ipo_ids == NULL) { if (exists) ipsec_delete_policy(ipo); else pool_put(&ipsec_policy_pool, ipo); rval = ENOBUFS; NET_UNLOCK(); goto ret; } } /* Flow type */ if (!exists) { /* Initialize policy entry */ bcopy(&encapdst, &ipo->ipo_addr, sizeof(struct sockaddr_encap)); bcopy(&encapnetmask, &ipo->ipo_mask, sizeof(struct sockaddr_encap)); TAILQ_INIT(&ipo->ipo_acquires); ipo->ipo_rdomain = rdomain; refcnt_init(&ipo->ipo_refcnt); /* Add SPD entry */ if ((rnh = spd_table_get(rdomain)) == NULL || (rn = rn_addroute((caddr_t)&ipo->ipo_addr, (caddr_t)&ipo->ipo_mask, rnh, ipo->ipo_nodes, 0)) == NULL) { /* Remove from linked list of policies on TDB */ mtx_enter(&ipo_tdb_mtx); if (ipo->ipo_tdb != NULL) { TAILQ_REMOVE( &ipo->ipo_tdb->tdb_policy_head, ipo, ipo_tdb_next); tdb_unref(ipo->ipo_tdb); ipo->ipo_tdb = NULL; } mtx_leave(&ipo_tdb_mtx); if (ipo->ipo_ids) ipsp_ids_free(ipo->ipo_ids); pool_put(&ipsec_policy_pool, ipo); NET_UNLOCK(); goto ret; } TAILQ_INSERT_HEAD(&ipsec_policy_head, ipo, ipo_list); ipsec_in_use++; } else { ipo->ipo_last_searched = ipo->ipo_flags = 0; } NET_UNLOCK(); } break; case SADB_X_PROMISC: if (len >= 2 * sizeof(struct sadb_msg)) { struct mbuf *packet; if ((rval = pfdatatopacket(message, len, &packet)) != 0) goto ret; SRPL_FOREACH(bkp, &sr, &pkptable.pkp_list, kcb_list) { if (bkp == kp || bkp->kcb_rdomain != kp->kcb_rdomain) continue; if (!smsg->sadb_msg_seq || (smsg->sadb_msg_seq == kp->kcb_pid)) { pfkey_sendup(bkp, packet, 1); } } SRPL_LEAVE(&sr); m_freem(packet); } else { if (len != sizeof(struct sadb_msg)) { rval = EINVAL; goto ret; } keylock(kp); i = (kp->kcb_flags & PFKEYV2_SOCKETFLAGS_PROMISC) ? 1 : 0; j = smsg->sadb_msg_satype ? 1 : 0; if (i ^ j) { if (j) { kp->kcb_flags |= PFKEYV2_SOCKETFLAGS_PROMISC; mtx_enter(&pfkeyv2_mtx); npromisc++; mtx_leave(&pfkeyv2_mtx); } else { kp->kcb_flags &= ~PFKEYV2_SOCKETFLAGS_PROMISC; mtx_enter(&pfkeyv2_mtx); npromisc--; mtx_leave(&pfkeyv2_mtx); } } keyunlock(kp); } break; default: rval = EINVAL; goto ret; } ret: if (rval) { if ((rval == EINVAL) || (rval == ENOMEM) || (rval == ENOBUFS)) goto realret; for (i = 1; i <= SADB_EXT_MAX; i++) headers[i] = NULL; smsg->sadb_msg_errno = abs(rval); } else { uint64_t seen = 0LL; for (i = 1; i <= SADB_EXT_MAX; i++) if (headers[i]) seen |= (1LL << i); if ((seen & sadb_exts_allowed_out[smsg->sadb_msg_type]) != seen) { rval = EPERM; goto realret; } if ((seen & sadb_exts_required_out[smsg->sadb_msg_type]) != sadb_exts_required_out[smsg->sadb_msg_type]) { rval = EPERM; goto realret; } } rval = pfkeyv2_sendmessage(headers, mode, so, 0, 0, kp->kcb_rdomain); realret: if (freeme != NULL) explicit_bzero(freeme, freeme_sz); free(freeme, M_PFKEY, freeme_sz); free(freeme2, M_PFKEY, freeme2_sz); free(freeme3, M_PFKEY, freeme3_sz); explicit_bzero(message, len); free(message, M_PFKEY, len); free(sa1, M_PFKEY, sizeof(*sa1)); NET_LOCK(); tdb_unref(sa2); NET_UNLOCK(); return (rval); } /* * Send an ACQUIRE message to key management, to get a new SA. */ int pfkeyv2_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw, union sockaddr_union *laddr, u_int32_t *seq, struct sockaddr_encap *ddst) { void *p, *headers[SADB_EXT_MAX + 1], *buffer = NULL; struct sadb_comb *sadb_comb; struct sadb_address *sadd; struct sadb_prop *sa_prop; struct sadb_msg *smsg; int rval = 0; int i, j, registered; mtx_enter(&pfkeyv2_mtx); *seq = pfkeyv2_seq++; registered = nregistered; mtx_leave(&pfkeyv2_mtx); if (!registered) { rval = ESRCH; goto ret; } /* How large a buffer do we need... XXX we only do one proposal for now */ i = sizeof(struct sadb_msg) + (laddr == NULL ? 0 : sizeof(struct sadb_address) + PADUP(ipo->ipo_src.sa.sa_len)) + sizeof(struct sadb_address) + PADUP(gw->sa.sa_len) + sizeof(struct sadb_prop) + 1 * sizeof(struct sadb_comb); if (ipo->ipo_ids) { i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_ids->id_local->len); i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_ids->id_remote->len); } /* Allocate */ if (!(p = malloc(i, M_PFKEY, M_NOWAIT | M_ZERO))) { rval = ENOMEM; goto ret; } bzero(headers, sizeof(headers)); buffer = p; headers[0] = p; p += sizeof(struct sadb_msg); smsg = (struct sadb_msg *) headers[0]; smsg->sadb_msg_version = PF_KEY_V2; smsg->sadb_msg_type = SADB_ACQUIRE; smsg->sadb_msg_len = i / sizeof(uint64_t); smsg->sadb_msg_seq = *seq; if (ipo->ipo_sproto == IPPROTO_ESP) smsg->sadb_msg_satype = SADB_SATYPE_ESP; else if (ipo->ipo_sproto == IPPROTO_AH) smsg->sadb_msg_satype = SADB_SATYPE_AH; else if (ipo->ipo_sproto == IPPROTO_IPCOMP) smsg->sadb_msg_satype = SADB_X_SATYPE_IPCOMP; if (laddr) { headers[SADB_EXT_ADDRESS_SRC] = p; p += sizeof(struct sadb_address) + PADUP(laddr->sa.sa_len); sadd = (struct sadb_address *) headers[SADB_EXT_ADDRESS_SRC]; sadd->sadb_address_len = (sizeof(struct sadb_address) + laddr->sa.sa_len + sizeof(uint64_t) - 1) / sizeof(uint64_t); bcopy(laddr, headers[SADB_EXT_ADDRESS_SRC] + sizeof(struct sadb_address), laddr->sa.sa_len); } headers[SADB_EXT_ADDRESS_DST] = p; p += sizeof(struct sadb_address) + PADUP(gw->sa.sa_len); sadd = (struct sadb_address *) headers[SADB_EXT_ADDRESS_DST]; sadd->sadb_address_len = (sizeof(struct sadb_address) + gw->sa.sa_len + sizeof(uint64_t) - 1) / sizeof(uint64_t); bcopy(gw, headers[SADB_EXT_ADDRESS_DST] + sizeof(struct sadb_address), gw->sa.sa_len); if (ipo->ipo_ids) export_identities(&p, ipo->ipo_ids, 0, headers); headers[SADB_EXT_PROPOSAL] = p; p += sizeof(struct sadb_prop); sa_prop = (struct sadb_prop *) headers[SADB_EXT_PROPOSAL]; sa_prop->sadb_prop_num = 1; /* XXX One proposal only */ sa_prop->sadb_prop_len = (sizeof(struct sadb_prop) + (sizeof(struct sadb_comb) * sa_prop->sadb_prop_num)) / sizeof(uint64_t); sadb_comb = p; /* XXX Should actually ask the crypto layer what's supported */ for (j = 0; j < sa_prop->sadb_prop_num; j++) { sadb_comb->sadb_comb_flags = 0; #ifdef IPSEC if (ipsec_require_pfs) sadb_comb->sadb_comb_flags |= SADB_SAFLAGS_PFS; /* Set the encryption algorithm */ if (ipo->ipo_sproto == IPPROTO_ESP) { if (!strncasecmp(ipsec_def_enc, "aes", sizeof("aes"))) { sadb_comb->sadb_comb_encrypt = SADB_X_EALG_AES; sadb_comb->sadb_comb_encrypt_minbits = 128; sadb_comb->sadb_comb_encrypt_maxbits = 256; } else if (!strncasecmp(ipsec_def_enc, "aesctr", sizeof("aesctr"))) { sadb_comb->sadb_comb_encrypt = SADB_X_EALG_AESCTR; sadb_comb->sadb_comb_encrypt_minbits = 128+32; sadb_comb->sadb_comb_encrypt_maxbits = 256+32; } else if (!strncasecmp(ipsec_def_enc, "3des", sizeof("3des"))) { sadb_comb->sadb_comb_encrypt = SADB_EALG_3DESCBC; sadb_comb->sadb_comb_encrypt_minbits = 192; sadb_comb->sadb_comb_encrypt_maxbits = 192; } else if (!strncasecmp(ipsec_def_enc, "blowfish", sizeof("blowfish"))) { sadb_comb->sadb_comb_encrypt = SADB_X_EALG_BLF; sadb_comb->sadb_comb_encrypt_minbits = 40; sadb_comb->sadb_comb_encrypt_maxbits = BLF_MAXKEYLEN * 8; } else if (!strncasecmp(ipsec_def_enc, "cast128", sizeof("cast128"))) { sadb_comb->sadb_comb_encrypt = SADB_X_EALG_CAST; sadb_comb->sadb_comb_encrypt_minbits = 40; sadb_comb->sadb_comb_encrypt_maxbits = 128; } } else if (ipo->ipo_sproto == IPPROTO_IPCOMP) { /* Set the compression algorithm */ if (!strncasecmp(ipsec_def_comp, "deflate", sizeof("deflate"))) { sadb_comb->sadb_comb_encrypt = SADB_X_CALG_DEFLATE; sadb_comb->sadb_comb_encrypt_minbits = 0; sadb_comb->sadb_comb_encrypt_maxbits = 0; } } /* Set the authentication algorithm */ if (!strncasecmp(ipsec_def_auth, "hmac-sha1", sizeof("hmac-sha1"))) { sadb_comb->sadb_comb_auth = SADB_AALG_SHA1HMAC; sadb_comb->sadb_comb_auth_minbits = 160; sadb_comb->sadb_comb_auth_maxbits = 160; } else if (!strncasecmp(ipsec_def_auth, "hmac-ripemd160", sizeof("hmac_ripemd160"))) { sadb_comb->sadb_comb_auth = SADB_X_AALG_RIPEMD160HMAC; sadb_comb->sadb_comb_auth_minbits = 160; sadb_comb->sadb_comb_auth_maxbits = 160; } else if (!strncasecmp(ipsec_def_auth, "hmac-md5", sizeof("hmac-md5"))) { sadb_comb->sadb_comb_auth = SADB_AALG_MD5HMAC; sadb_comb->sadb_comb_auth_minbits = 128; sadb_comb->sadb_comb_auth_maxbits = 128; } else if (!strncasecmp(ipsec_def_auth, "hmac-sha2-256", sizeof("hmac-sha2-256"))) { sadb_comb->sadb_comb_auth = SADB_X_AALG_SHA2_256; sadb_comb->sadb_comb_auth_minbits = 256; sadb_comb->sadb_comb_auth_maxbits = 256; } else if (!strncasecmp(ipsec_def_auth, "hmac-sha2-384", sizeof("hmac-sha2-384"))) { sadb_comb->sadb_comb_auth = SADB_X_AALG_SHA2_384; sadb_comb->sadb_comb_auth_minbits = 384; sadb_comb->sadb_comb_auth_maxbits = 384; } else if (!strncasecmp(ipsec_def_auth, "hmac-sha2-512", sizeof("hmac-sha2-512"))) { sadb_comb->sadb_comb_auth = SADB_X_AALG_SHA2_512; sadb_comb->sadb_comb_auth_minbits = 512; sadb_comb->sadb_comb_auth_maxbits = 512; } sadb_comb->sadb_comb_soft_allocations = ipsec_soft_allocations; sadb_comb->sadb_comb_hard_allocations = ipsec_exp_allocations; sadb_comb->sadb_comb_soft_bytes = ipsec_soft_bytes; sadb_comb->sadb_comb_hard_bytes = ipsec_exp_bytes; sadb_comb->sadb_comb_soft_addtime = ipsec_soft_timeout; sadb_comb->sadb_comb_hard_addtime = ipsec_exp_timeout; sadb_comb->sadb_comb_soft_usetime = ipsec_soft_first_use; sadb_comb->sadb_comb_hard_usetime = ipsec_exp_first_use; #endif sadb_comb++; } /* Send the ACQUIRE message to all compliant registered listeners. */ if ((rval = pfkeyv2_sendmessage(headers, PFKEYV2_SENDMESSAGE_REGISTERED, NULL, smsg->sadb_msg_satype, 0, ipo->ipo_rdomain)) != 0) goto ret; rval = 0; ret: if (buffer != NULL) { explicit_bzero(buffer, i); free(buffer, M_PFKEY, i); } return (rval); } /* * Notify key management that an expiration went off. The second argument * specifies the type of expiration (soft or hard). */ int pfkeyv2_expire(struct tdb *tdb, u_int16_t type) { void *p, *headers[SADB_EXT_MAX+1], *buffer = NULL; struct sadb_msg *smsg; int rval = 0; int i; NET_ASSERT_LOCKED(); switch (tdb->tdb_sproto) { case IPPROTO_AH: case IPPROTO_ESP: case IPPROTO_IPIP: case IPPROTO_IPCOMP: #ifdef TCP_SIGNATURE case IPPROTO_TCP: #endif /* TCP_SIGNATURE */ break; default: rval = EOPNOTSUPP; goto ret; } i = sizeof(struct sadb_msg) + sizeof(struct sadb_sa) + 2 * sizeof(struct sadb_lifetime) + sizeof(struct sadb_address) + PADUP(tdb->tdb_src.sa.sa_len) + sizeof(struct sadb_address) + PADUP(tdb->tdb_dst.sa.sa_len); if (!(p = malloc(i, M_PFKEY, M_NOWAIT | M_ZERO))) { rval = ENOMEM; goto ret; } bzero(headers, sizeof(headers)); buffer = p; headers[0] = p; p += sizeof(struct sadb_msg); smsg = (struct sadb_msg *) headers[0]; smsg->sadb_msg_version = PF_KEY_V2; smsg->sadb_msg_type = SADB_EXPIRE; smsg->sadb_msg_satype = tdb->tdb_satype; smsg->sadb_msg_len = i / sizeof(uint64_t); mtx_enter(&pfkeyv2_mtx); smsg->sadb_msg_seq = pfkeyv2_seq++; mtx_leave(&pfkeyv2_mtx); headers[SADB_EXT_SA] = p; export_sa(&p, tdb); headers[SADB_EXT_LIFETIME_CURRENT] = p; export_lifetime(&p, tdb, PFKEYV2_LIFETIME_CURRENT); headers[type] = p; export_lifetime(&p, tdb, type == SADB_EXT_LIFETIME_SOFT ? PFKEYV2_LIFETIME_SOFT : PFKEYV2_LIFETIME_HARD); headers[SADB_EXT_ADDRESS_SRC] = p; export_address(&p, &tdb->tdb_src.sa); headers[SADB_EXT_ADDRESS_DST] = p; export_address(&p, &tdb->tdb_dst.sa); if ((rval = pfkeyv2_sendmessage(headers, PFKEYV2_SENDMESSAGE_BROADCAST, NULL, 0, 0, tdb->tdb_rdomain)) != 0) goto ret; /* XXX */ if (tdb->tdb_rdomain != tdb->tdb_rdomain_post) if ((rval = pfkeyv2_sendmessage(headers, PFKEYV2_SENDMESSAGE_BROADCAST, NULL, 0, 0, tdb->tdb_rdomain_post)) != 0) goto ret; rval = 0; ret: if (buffer != NULL) { explicit_bzero(buffer, i); free(buffer, M_PFKEY, i); } return (rval); } struct pfkeyv2_sysctl_walk { void *w_where; size_t w_len; int w_op; u_int8_t w_satype; }; int pfkeyv2_sysctl_walker(struct tdb *tdb, void *arg, int last) { struct pfkeyv2_sysctl_walk *w = (struct pfkeyv2_sysctl_walk *)arg; void *buffer = NULL; int error = 0; int usedlen, buflen, i; if (w->w_satype != SADB_SATYPE_UNSPEC && w->w_satype != tdb->tdb_satype) return (0); if (w->w_where) { void *headers[SADB_EXT_MAX+1]; struct sadb_msg msg; bzero(headers, sizeof(headers)); if ((error = pfkeyv2_get(tdb, headers, &buffer, &buflen, &usedlen)) != 0) goto done; if (w->w_len < sizeof(msg) + usedlen) { error = ENOMEM; goto done; } /* prepend header */ bzero(&msg, sizeof(msg)); msg.sadb_msg_version = PF_KEY_V2; msg.sadb_msg_satype = tdb->tdb_satype; msg.sadb_msg_type = SADB_DUMP; msg.sadb_msg_len = (sizeof(msg) + usedlen) / sizeof(uint64_t); if ((error = copyout(&msg, w->w_where, sizeof(msg))) != 0) goto done; w->w_where += sizeof(msg); w->w_len -= sizeof(msg); /* set extension type */ for (i = 1; i <= SADB_EXT_MAX; i++) if (headers[i]) ((struct sadb_ext *) headers[i])->sadb_ext_type = i; if ((error = copyout(buffer, w->w_where, usedlen)) != 0) goto done; w->w_where += usedlen; w->w_len -= usedlen; } else { if ((error = pfkeyv2_get(tdb, NULL, NULL, &buflen, NULL)) != 0) return (error); w->w_len += buflen; w->w_len += sizeof(struct sadb_msg); } done: if (buffer != NULL) { explicit_bzero(buffer, buflen); free(buffer, M_PFKEY, buflen); } return (error); } int pfkeyv2_dump_policy(struct ipsec_policy *ipo, void **headers, void **buffer, int *lenp) { int i, rval, perm; void *p; /* Find how much space we need. */ i = 2 * sizeof(struct sadb_protocol); /* We'll need four of them: src, src mask, dst, dst mask. */ switch (ipo->ipo_addr.sen_type) { case SENT_IP4: i += 4 * PADUP(sizeof(struct sockaddr_in)); i += 4 * sizeof(struct sadb_address); break; #ifdef INET6 case SENT_IP6: i += 4 * PADUP(sizeof(struct sockaddr_in6)); i += 4 * sizeof(struct sadb_address); break; #endif /* INET6 */ default: return (EINVAL); } /* Local address, might be zeroed. */ switch (ipo->ipo_src.sa.sa_family) { case 0: break; case AF_INET: i += PADUP(sizeof(struct sockaddr_in)); i += sizeof(struct sadb_address); break; #ifdef INET6 case AF_INET6: i += PADUP(sizeof(struct sockaddr_in6)); i += sizeof(struct sadb_address); break; #endif /* INET6 */ default: return (EINVAL); } /* Remote address, might be zeroed. XXX ??? */ switch (ipo->ipo_dst.sa.sa_family) { case 0: break; case AF_INET: i += PADUP(sizeof(struct sockaddr_in)); i += sizeof(struct sadb_address); break; #ifdef INET6 case AF_INET6: i += PADUP(sizeof(struct sockaddr_in6)); i += sizeof(struct sadb_address); break; #endif /* INET6 */ default: return (EINVAL); } if (ipo->ipo_ids) { i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_ids->id_local->len); i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_ids->id_remote->len); } if (lenp) *lenp = i; if (buffer == NULL) { rval = 0; goto ret; } if (!(p = malloc(i, M_PFKEY, M_NOWAIT | M_ZERO))) { rval = ENOMEM; goto ret; } else *buffer = p; /* Local address. */ if (ipo->ipo_src.sa.sa_family) { headers[SADB_EXT_ADDRESS_SRC] = p; export_address(&p, &ipo->ipo_src.sa); } /* Remote address. */ if (ipo->ipo_dst.sa.sa_family) { headers[SADB_EXT_ADDRESS_DST] = p; export_address(&p, &ipo->ipo_dst.sa); } /* Get actual flow. */ export_flow(&p, ipo->ipo_type, &ipo->ipo_addr, &ipo->ipo_mask, headers); /* Add ids only when we are root. */ perm = suser(curproc); if (perm == 0 && ipo->ipo_ids) export_identities(&p, ipo->ipo_ids, 0, headers); rval = 0; ret: return (rval); } int pfkeyv2_sysctl_policydumper(struct ipsec_policy *ipo, void *arg, unsigned int tableid) { struct pfkeyv2_sysctl_walk *w = (struct pfkeyv2_sysctl_walk *)arg; void *buffer = NULL; int i, buflen, error = 0; if (w->w_where) { void *headers[SADB_EXT_MAX + 1]; struct sadb_msg msg; bzero(headers, sizeof(headers)); if ((error = pfkeyv2_dump_policy(ipo, headers, &buffer, &buflen)) != 0) goto done; if (w->w_len < buflen) { error = ENOMEM; goto done; } /* prepend header */ bzero(&msg, sizeof(msg)); msg.sadb_msg_version = PF_KEY_V2; if (ipo->ipo_sproto == IPPROTO_ESP) msg.sadb_msg_satype = SADB_SATYPE_ESP; else if (ipo->ipo_sproto == IPPROTO_AH) msg.sadb_msg_satype = SADB_SATYPE_AH; else if (ipo->ipo_sproto == IPPROTO_IPCOMP) msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP; else if (ipo->ipo_sproto == IPPROTO_IPIP) msg.sadb_msg_satype = SADB_X_SATYPE_IPIP; msg.sadb_msg_type = SADB_X_SPDDUMP; msg.sadb_msg_len = (sizeof(msg) + buflen) / sizeof(uint64_t); if ((error = copyout(&msg, w->w_where, sizeof(msg))) != 0) goto done; w->w_where += sizeof(msg); w->w_len -= sizeof(msg); /* set extension type */ for (i = 1; i <= SADB_EXT_MAX; i++) if (headers[i]) ((struct sadb_ext *) headers[i])->sadb_ext_type = i; if ((error = copyout(buffer, w->w_where, buflen)) != 0) goto done; w->w_where += buflen; w->w_len -= buflen; } else { if ((error = pfkeyv2_dump_policy(ipo, NULL, NULL, &buflen)) != 0) goto done; w->w_len += buflen; w->w_len += sizeof(struct sadb_msg); } done: if (buffer) free(buffer, M_PFKEY, buflen); return (error); } int pfkeyv2_policy_flush(struct ipsec_policy *ipo, void *arg, unsigned int tableid) { int error; error = ipsec_delete_policy(ipo); if (error == 0) error = EAGAIN; return (error); } int pfkeyv2_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *new, size_t newlen) { struct pfkeyv2_sysctl_walk w; int error = EINVAL; u_int rdomain; u_int tableid; if (new) return (EPERM); if (namelen < 1) return (EINVAL); w.w_op = name[0]; if (namelen >= 2) w.w_satype = name[1]; else w.w_satype = SADB_SATYPE_UNSPEC; w.w_where = oldp; w.w_len = oldp ? *oldlenp : 0; if (namelen == 3) { tableid = name[2]; if (!rtable_exists(tableid)) return (ENOENT); } else tableid = curproc->p_p->ps_rtableid; rdomain = rtable_l2(tableid); switch(w.w_op) { case NET_KEY_SADB_DUMP: if ((error = suser(curproc)) != 0) return (error); NET_LOCK(); error = tdb_walk(rdomain, pfkeyv2_sysctl_walker, &w); NET_UNLOCK(); if (oldp) *oldlenp = w.w_where - oldp; else *oldlenp = w.w_len; break; case NET_KEY_SPD_DUMP: NET_LOCK_SHARED(); error = spd_table_walk(rdomain, pfkeyv2_sysctl_policydumper, &w); NET_UNLOCK_SHARED(); if (oldp) *oldlenp = w.w_where - oldp; else *oldlenp = w.w_len; break; } return (error); }
12 12 12 12 12 12 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 /* $OpenBSD: clock.c,v 1.42 2023/09/17 14:50:50 cheloha Exp $ */ /* $NetBSD: clock.c,v 1.1 2003/04/26 18:39:50 fvdl Exp $ */ /*- * Copyright (c) 1993, 1994 Charles M. Hannum. * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz and Don Ahn. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)clock.c 7.2 (Berkeley) 5/12/91 */ /* * Mach Operating System * Copyright (c) 1991,1990,1989 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie Mellon * the rights to redistribute these changes. */ /* Copyright 1988, 1989 by Intel Corporation, Santa Clara, California. All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appears in all copies and that both the copyright notice and this permission notice appear in supporting documentation, and that the name of Intel not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * Primitive clock interrupt routines. */ /* #define CLOCK_DEBUG */ #include <sys/param.h> #include <sys/systm.h> #include <sys/clockintr.h> #include <sys/time.h> #include <sys/kernel.h> #include <sys/timeout.h> #include <sys/timetc.h> #include <machine/cpu.h> #include <machine/intr.h> #include <machine/pio.h> #include <machine/cpufunc.h> #include <dev/clock_subr.h> #include <dev/isa/isareg.h> #include <dev/isa/isavar.h> #include <dev/ic/mc146818reg.h> #include <dev/ic/i8253reg.h> #include <amd64/isa/nvram.h> /* Timecounter on the i8254 */ u_int32_t i8254_lastcount; u_int32_t i8254_offset; int i8254_ticked; u_int i8254_get_timecount(struct timecounter *tc); u_int i8254_simple_get_timecount(struct timecounter *tc); static struct timecounter i8254_timecounter = { .tc_get_timecount = i8254_get_timecount, .tc_counter_mask = ~0u, .tc_frequency = TIMER_FREQ, .tc_name = "i8254", .tc_quality = 0, .tc_priv = NULL, .tc_user = 0, }; int clockintr(void *); int rtcintr(void *); int gettick(void); void rtcdrain(void *v); int rtcget(mc_todregs *); void rtcput(mc_todregs *); int bcdtobin(int); int bintobcd(int); u_int mc146818_read(void *, u_int); void mc146818_write(void *, u_int, u_int); u_int mc146818_read(void *sc, u_int reg) { outb(IO_RTC, reg); DELAY(1); return (inb(IO_RTC+1)); } void mc146818_write(void *sc, u_int reg, u_int datum) { outb(IO_RTC, reg); DELAY(1); outb(IO_RTC+1, datum); DELAY(1); } struct mutex timer_mutex = MUTEX_INITIALIZER(IPL_HIGH); u_long rtclock_tval; void startclocks(void) { mtx_enter(&timer_mutex); rtclock_tval = TIMER_DIV(hz); i8254_startclock(); mtx_leave(&timer_mutex); } int clockintr(void *frame) { if (timecounter->tc_get_timecount == i8254_get_timecount) { if (i8254_ticked) { i8254_ticked = 0; } else { i8254_offset += rtclock_tval; i8254_lastcount = 0; } } clockintr_dispatch(frame); return 1; } int rtcintr(void *frame) { u_int stat = 0; /* * If rtcintr is 'late', next intr may happen immediately. * Get them all. (Also, see comment in cpu_initclocks().) */ while (mc146818_read(NULL, MC_REGC) & MC_REGC_PF) stat = 1; if (stat) clockintr_dispatch(frame); return (stat); } int gettick(void) { u_long s; u_char lo, hi; /* Don't want someone screwing with the counter while we're here. */ mtx_enter(&timer_mutex); s = intr_disable(); /* Select counter 0 and latch it. */ outb(IO_TIMER1+TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); lo = inb(IO_TIMER1+TIMER_CNTR0); hi = inb(IO_TIMER1+TIMER_CNTR0); intr_restore(s); mtx_leave(&timer_mutex); return ((hi << 8) | lo); } /* * Wait "n" microseconds. * Relies on timer 1 counting down from (TIMER_FREQ / hz) at TIMER_FREQ Hz. * Note: timer had better have been programmed before this is first used! * (Note that we use `rate generator' mode, which counts at 1:1; `square * wave' mode counts at 2:1). */ void i8254_delay(int n) { int limit, tick, otick; static const int delaytab[26] = { 0, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 27, 28, 29, 30, }; /* * Read the counter first, so that the rest of the setup overhead is * counted. */ otick = gettick(); if (n <= 25) n = delaytab[n]; else { /* Force 64-bit math to avoid 32-bit overflow if possible. */ n = (int64_t)n * TIMER_FREQ / 1000000; } limit = TIMER_FREQ / hz; while (n > 0) { tick = gettick(); if (tick > otick) n -= limit - (tick - otick); else n -= otick - tick; otick = tick; } } void rtcdrain(void *v) { struct timeout *to = (struct timeout *)v; if (to != NULL) timeout_del(to); /* Drain any un-acknowledged RTC interrupts. */ while (mc146818_read(NULL, MC_REGC) & MC_REGC_PF) ; /* Nothing. */ } void i8254_initclocks(void) { i8254_inittimecounter(); /* hook the interrupt-based i8254 tc */ stathz = 128; profhz = 1024; /* XXX does not divide into 1 billion */ } void i8254_start_both_clocks(void) { clockintr_cpu_init(NULL); /* * While the clock interrupt handler isn't really MPSAFE, the * i8254 can't really be used as a clock on a true MP system. */ isa_intr_establish(NULL, 0, IST_PULSE, IPL_CLOCK | IPL_MPSAFE, clockintr, 0, "clock"); isa_intr_establish(NULL, 8, IST_PULSE, IPL_STATCLOCK | IPL_MPSAFE, rtcintr, 0, "rtc"); rtcstart(); /* start the mc146818 clock */ } void rtcstart(void) { static struct timeout rtcdrain_timeout; mc146818_write(NULL, MC_REGA, MC_BASE_32_KHz | MC_RATE_128_Hz); mc146818_write(NULL, MC_REGB, MC_REGB_24HR | MC_REGB_PIE); /* * On a number of i386 systems, the rtc will fail to start when booting * the system. This is due to us missing to acknowledge an interrupt * during early stages of the boot process. If we do not acknowledge * the interrupt, the rtc clock will not generate further interrupts. * To solve this, once interrupts are enabled, use a timeout (once) * to drain any un-acknowledged rtc interrupt(s). */ timeout_set(&rtcdrain_timeout, rtcdrain, (void *)&rtcdrain_timeout); timeout_add(&rtcdrain_timeout, 1); } void rtcstop(void) { mc146818_write(NULL, MC_REGB, MC_REGB_24HR); } int rtcget(mc_todregs *regs) { if ((mc146818_read(NULL, MC_REGD) & MC_REGD_VRT) == 0) /* XXX softc */ return (-1); MC146818_GETTOD(NULL, regs); /* XXX softc */ return (0); } void rtcput(mc_todregs *regs) { MC146818_PUTTOD(NULL, regs); /* XXX softc */ } int bcdtobin(int n) { return (((n >> 4) & 0x0f) * 10 + (n & 0x0f)); } int bintobcd(int n) { return ((u_char)(((n / 10) << 4) & 0xf0) | ((n % 10) & 0x0f)); } /* * check whether the CMOS layout is "standard"-like (ie, not PS/2-like), * to be called at splclock() */ static int cmoscheck(void); static int cmoscheck(void) { int i; unsigned short cksum = 0; for (i = 0x10; i <= 0x2d; i++) cksum += mc146818_read(NULL, i); /* XXX softc */ return (cksum == (mc146818_read(NULL, 0x2e) << 8) + mc146818_read(NULL, 0x2f)); } /* * patchable to control century byte handling: * 1: always update * -1: never touch * 0: try to figure out itself */ int rtc_update_century = 0; /* * Expand a two-digit year as read from the clock chip * into full width. * Being here, deal with the CMOS century byte. */ static int centb = NVRAM_CENTURY; static int clock_expandyear(int); static int clock_expandyear(int clockyear) { int s, clockcentury, cmoscentury; clockcentury = (clockyear < 70) ? 20 : 19; clockyear += 100 * clockcentury; if (rtc_update_century < 0) return (clockyear); s = splclock(); if (cmoscheck()) cmoscentury = mc146818_read(NULL, NVRAM_CENTURY); else cmoscentury = 0; splx(s); if (!cmoscentury) return (clockyear); cmoscentury = bcdtobin(cmoscentury); if (cmoscentury != clockcentury) { /* XXX note: saying "century is 20" might confuse the naive. */ printf("WARNING: NVRAM century is %d but RTC year is %d\n", cmoscentury, clockyear); /* Kludge to roll over century. */ if ((rtc_update_century > 0) || ((cmoscentury == 19) && (clockcentury == 20) && (clockyear == 2000))) { printf("WARNING: Setting NVRAM century to %d\n", clockcentury); s = splclock(); mc146818_write(NULL, centb, bintobcd(clockcentury)); splx(s); } } else if (cmoscentury == 19 && rtc_update_century == 0) rtc_update_century = 1; /* will update later in resettodr() */ return (clockyear); } int rtcgettime(struct todr_chip_handle *handle, struct timeval *tv) { mc_todregs rtclk; struct clock_ymdhms dt; int s; s = splclock(); if (rtcget(&rtclk)) { splx(s); return EINVAL; } splx(s); #ifdef CLOCK_DEBUG printf("readclock: %x/%x/%x %x:%x:%x\n", rtclk[MC_YEAR], rtclk[MC_MONTH], rtclk[MC_DOM], rtclk[MC_HOUR], rtclk[MC_MIN], rtclk[MC_SEC]); #endif dt.dt_sec = bcdtobin(rtclk[MC_SEC]); dt.dt_min = bcdtobin(rtclk[MC_MIN]); dt.dt_hour = bcdtobin(rtclk[MC_HOUR]); dt.dt_day = bcdtobin(rtclk[MC_DOM]); dt.dt_mon = bcdtobin(rtclk[MC_MONTH]); dt.dt_year = clock_expandyear(bcdtobin(rtclk[MC_YEAR])); tv->tv_sec = clock_ymdhms_to_secs(&dt) - utc_offset; tv->tv_usec = 0; return 0; } int rtcsettime(struct todr_chip_handle *handle, struct timeval *tv) { mc_todregs rtclk; struct clock_ymdhms dt; int century, s; s = splclock(); if (rtcget(&rtclk)) memset(&rtclk, 0, sizeof(rtclk)); splx(s); clock_secs_to_ymdhms(tv->tv_sec + utc_offset, &dt); rtclk[MC_SEC] = bintobcd(dt.dt_sec); rtclk[MC_MIN] = bintobcd(dt.dt_min); rtclk[MC_HOUR] = bintobcd(dt.dt_hour); rtclk[MC_DOW] = dt.dt_wday + 1; rtclk[MC_YEAR] = bintobcd(dt.dt_year % 100); rtclk[MC_MONTH] = bintobcd(dt.dt_mon); rtclk[MC_DOM] = bintobcd(dt.dt_day); #ifdef CLOCK_DEBUG printf("setclock: %x/%x/%x %x:%x:%x\n", rtclk[MC_YEAR], rtclk[MC_MONTH], rtclk[MC_DOM], rtclk[MC_HOUR], rtclk[MC_MIN], rtclk[MC_SEC]); #endif s = splclock(); rtcput(&rtclk); if (rtc_update_century > 0) { century = bintobcd(dt.dt_year / 100); mc146818_write(NULL, centb, century); /* XXX softc */ } splx(s); return 0; } struct todr_chip_handle rtc_todr; void rtcinit(void) { rtc_todr.todr_gettime = rtcgettime; rtc_todr.todr_settime = rtcsettime; rtc_todr.todr_quality = 0; todr_attach(&rtc_todr); } void setstatclockrate(int arg) { if (initclock_func == i8254_initclocks) { if (arg == stathz) mc146818_write(NULL, MC_REGA, MC_BASE_32_KHz | MC_RATE_128_Hz); else mc146818_write(NULL, MC_REGA, MC_BASE_32_KHz | MC_RATE_1024_Hz); } } void i8254_inittimecounter(void) { tc_init(&i8254_timecounter); } /* * If we're using lapic to drive hardclock, we can use a simpler * algorithm for the i8254 timecounters. */ void i8254_inittimecounter_simple(void) { i8254_timecounter.tc_get_timecount = i8254_simple_get_timecount; i8254_timecounter.tc_counter_mask = 0x7fff; i8254_timecounter.tc_frequency = TIMER_FREQ; mtx_enter(&timer_mutex); rtclock_tval = 0x8000; i8254_startclock(); mtx_leave(&timer_mutex); tc_init(&i8254_timecounter); } void i8254_startclock(void) { u_long tval = rtclock_tval; outb(IO_TIMER1 + TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); outb(IO_TIMER1 + TIMER_CNTR0, tval & 0xff); outb(IO_TIMER1 + TIMER_CNTR0, tval >> 8); } u_int i8254_simple_get_timecount(struct timecounter *tc) { return (rtclock_tval - gettick()); } u_int i8254_get_timecount(struct timecounter *tc) { u_char hi, lo; u_int count; u_long s; s = intr_disable(); outb(IO_TIMER1+TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); lo = inb(IO_TIMER1+TIMER_CNTR0); hi = inb(IO_TIMER1+TIMER_CNTR0); count = rtclock_tval - ((hi << 8) | lo); if (count < i8254_lastcount) { i8254_ticked = 1; i8254_offset += rtclock_tval; } i8254_lastcount = count; count += i8254_offset; intr_restore(s); return (count); }
198 198 1 8 8 8 8 8 8 8 8 8 8 8 546 8 244 244 1 244 471 472 11 472 473 243 244 7 139 139 3 5 9 2 7 7 7 2 9 3 2 7 10 1 8 2 8 7 4 1 8 3 2 2 6 2 2 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 /* $OpenBSD: rnd.c,v 1.226 2023/03/08 04:43:08 guenther Exp $ */ /* * Copyright (c) 2011,2020 Theo de Raadt. * Copyright (c) 2008 Damien Miller. * Copyright (c) 1996, 1997, 2000-2002 Michael Shalayeff. * Copyright (c) 2013 Markus Friedl. * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, and the entire permission notice in its entirety, * including the disclaimer of warranties. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * ALTERNATIVELY, this product may be distributed under the terms of * the GNU Public License, in which case the provisions of the GPL are * required INSTEAD OF the above restrictions. (This clause is * necessary due to a potential bad interaction between the GPL and * the restrictions contained in a BSD-style copyright.) * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * The bootblocks pre-fill the kernel .openbsd.randomdata section with seed * material (on-disk from previous boot, hopefully mixed with a hardware rng). * The first arc4random(9) call initializes this seed material as a chacha * state. Calls can be done early in kernel bootstrap code -- early use is * encouraged. * * After the kernel timeout subsystem is initialized, random_start() prepares * the entropy collection mechanism enqueue_randomness() and timeout-driven * mixing into the chacha state. The first submissions come from device * probes, later on interrupt-time submissions are more common. Entropy * data (and timing information) get mixed over the entropy input ring * rnd_event_space[] -- the goal is to collect damage. * * Based upon timeouts, a selection of the entropy ring rnd_event_space[] * CRC bit-distributed and XOR mixed into entropy_pool[]. * * From time to time, entropy_pool[] is SHA512-whitened, mixed with time * information again, XOR'd with the inner and outer states of the existing * chacha state, to create a new chacha state. * * During early boot (until cold=0), enqueue operations are immediately * dequeued, and mixed into the chacha. */ #include <sys/param.h> #include <sys/event.h> #include <sys/ioctl.h> #include <sys/malloc.h> #include <sys/timeout.h> #include <sys/atomic.h> #include <sys/task.h> #include <sys/msgbuf.h> #include <sys/mount.h> #include <sys/syscallargs.h> #include <crypto/sha2.h> #define KEYSTREAM_ONLY #include <crypto/chacha_private.h> #include <uvm/uvm_extern.h> /* * For the purposes of better mixing, we use the CRC-32 polynomial as * well to make a twisted Generalized Feedback Shift Register * * (See M. Matsumoto & Y. Kurita, 1992. Twisted GFSR generators. ACM * Transactions on Modeling and Computer Simulation 2(3):179-194. * Also see M. Matsumoto & Y. Kurita, 1994. Twisted GFSR generators * II. ACM Transactions on Modeling and Computer Simulation 4:254-266) */ /* * Stirring polynomial over GF(2). Used in add_entropy_words() below. * * The polynomial terms are chosen to be evenly spaced (minimum RMS * distance from evenly spaced; except for the last tap, which is 1 to * get the twisting happening as fast as possible. * * The resultant polynomial is: * 2^POOLWORDS + 2^POOL_TAP1 + 2^POOL_TAP2 + 2^POOL_TAP3 + 2^POOL_TAP4 + 1 */ #define POOLWORDS 2048 #define POOLBYTES (POOLWORDS*4) #define POOLMASK (POOLWORDS - 1) #define POOL_TAP1 1638 #define POOL_TAP2 1231 #define POOL_TAP3 819 #define POOL_TAP4 411 /* * Raw entropy collection from device drivers; at interrupt context or not. * enqueue_randomness() is used to submit data into the entropy input ring. */ #define QEVLEN 128 /* must be a power of 2 */ #define QEVCONSUME 8 /* how many events to consume a time */ #define KEYSZ 32 #define IVSZ 8 #define BLOCKSZ 64 #define RSBUFSZ (16*BLOCKSZ) #define EBUFSIZE KEYSZ + IVSZ struct rand_event { u_int re_time; u_int re_val; } rnd_event_space[QEVLEN]; u_int rnd_event_cons; u_int rnd_event_prod; int rnd_cold = 1; int rnd_slowextract = 1; void rnd_reinit(void *v); /* timeout to start reinit */ void rnd_init(void *); /* actually do the reinit */ static u_int32_t entropy_pool[POOLWORDS]; u_int32_t entropy_pool0[POOLWORDS] __attribute__((section(".openbsd.randomdata"))); void dequeue_randomness(void *); void add_entropy_words(const u_int32_t *, u_int); void extract_entropy(u_int8_t *) __attribute__((__bounded__(__minbytes__,1,EBUFSIZE))); struct timeout rnd_timeout = TIMEOUT_INITIALIZER(dequeue_randomness, NULL); int filt_randomread(struct knote *, long); void filt_randomdetach(struct knote *); int filt_randomwrite(struct knote *, long); static void _rs_seed(u_char *, size_t); static void _rs_clearseed(const void *p, size_t s); const struct filterops randomread_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, .f_detach = filt_randomdetach, .f_event = filt_randomread, }; const struct filterops randomwrite_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, .f_detach = filt_randomdetach, .f_event = filt_randomwrite, }; /* * This function mixes entropy and timing into the entropy input ring. */ void enqueue_randomness(u_int val) { struct rand_event *rep; int e; e = (atomic_inc_int_nv(&rnd_event_prod) - 1) & (QEVLEN-1); rep = &rnd_event_space[e]; rep->re_time += cpu_rnd_messybits(); rep->re_val += val; if (rnd_cold) { dequeue_randomness(NULL); rnd_init(NULL); if (!cold) rnd_cold = 0; } else if (!timeout_pending(&rnd_timeout) && (rnd_event_prod - rnd_event_cons) > QEVCONSUME) { rnd_slowextract = min(rnd_slowextract * 2, 5000); timeout_add_msec(&rnd_timeout, rnd_slowextract * 10); } } /* * This function merges entropy ring information into the buffer using * a polynomial to spread the bits. */ void add_entropy_words(const u_int32_t *buf, u_int n) { /* derived from IEEE 802.3 CRC-32 */ static const u_int32_t twist_table[8] = { 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158, 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 }; static u_int entropy_add_ptr; static u_char entropy_input_rotate; for (; n--; buf++) { u_int32_t w = (*buf << entropy_input_rotate) | (*buf >> ((32 - entropy_input_rotate) & 31)); u_int i = entropy_add_ptr = (entropy_add_ptr - 1) & POOLMASK; /* * Normally, we add 7 bits of rotation to the pool. * At the beginning of the pool, add an extra 7 bits * rotation, so that successive passes spread the * input bits across the pool evenly. */ entropy_input_rotate = (entropy_input_rotate + (i ? 7 : 14)) & 31; /* XOR pool contents corresponding to polynomial terms */ w ^= entropy_pool[(i + POOL_TAP1) & POOLMASK] ^ entropy_pool[(i + POOL_TAP2) & POOLMASK] ^ entropy_pool[(i + POOL_TAP3) & POOLMASK] ^ entropy_pool[(i + POOL_TAP4) & POOLMASK] ^ entropy_pool[(i + 1) & POOLMASK] ^ entropy_pool[i]; /* + 2^POOLWORDS */ entropy_pool[i] = (w >> 3) ^ twist_table[w & 7]; } } /* * Pulls entropy out of the queue and merges it into the pool with the * CRC. This takes a mix of fresh entries from the producer end of the * queue and entries from the consumer end of the queue which are * likely to have collected more damage. */ void dequeue_randomness(void *v) { u_int32_t buf[2]; u_int startp, startc, i; if (!rnd_cold) timeout_del(&rnd_timeout); /* Some very new damage */ startp = rnd_event_prod - QEVCONSUME; for (i = 0; i < QEVCONSUME; i++) { u_int e = (startp + i) & (QEVLEN-1); buf[0] = rnd_event_space[e].re_time; buf[1] = rnd_event_space[e].re_val; add_entropy_words(buf, 2); } /* and some probably more damaged */ startc = rnd_event_cons; for (i = 0; i < QEVCONSUME; i++) { u_int e = (startc + i) & (QEVLEN-1); buf[0] = rnd_event_space[e].re_time; buf[1] = rnd_event_space[e].re_val; add_entropy_words(buf, 2); } rnd_event_cons = startp + QEVCONSUME; } /* * Grabs a chunk from the entropy_pool[] and slams it through SHA512 when * requested. */ void extract_entropy(u_int8_t *buf) { static u_int32_t extract_pool[POOLWORDS]; u_char digest[SHA512_DIGEST_LENGTH]; SHA2_CTX shactx; #if SHA512_DIGEST_LENGTH < EBUFSIZE #error "need more bigger hash output" #endif /* * INTENTIONALLY not protected by any lock. Races during * memcpy() result in acceptable input data; races during * SHA512Update() would create nasty data dependencies. We * do not rely on this as a benefit, but if it happens, cool. */ memcpy(extract_pool, entropy_pool, sizeof(extract_pool)); /* Hash the pool to get the output */ SHA512Init(&shactx); SHA512Update(&shactx, (u_int8_t *)extract_pool, sizeof(extract_pool)); SHA512Final(digest, &shactx); /* Copy data to destination buffer */ memcpy(buf, digest, EBUFSIZE); /* * Modify pool so next hash will produce different results. * During boot-time enqueue/dequeue stage, avoid recursion. */ if (!rnd_cold) enqueue_randomness(extract_pool[0]); dequeue_randomness(NULL); /* Wipe data from memory */ explicit_bzero(extract_pool, sizeof(extract_pool)); explicit_bzero(digest, sizeof(digest)); } /* random keystream by ChaCha */ struct mutex rndlock = MUTEX_INITIALIZER(IPL_HIGH); struct timeout rndreinit_timeout = TIMEOUT_INITIALIZER(rnd_reinit, NULL); struct task rnd_task = TASK_INITIALIZER(rnd_init, NULL); static chacha_ctx rs; /* chacha context for random keystream */ /* keystream blocks (also chacha seed from boot) */ static u_char rs_buf[RSBUFSZ]; u_char rs_buf0[RSBUFSZ] __attribute__((section(".openbsd.randomdata"))); static size_t rs_have; /* valid bytes at end of rs_buf */ static size_t rs_count; /* bytes till reseed */ void suspend_randomness(void) { struct timespec ts; getnanotime(&ts); enqueue_randomness(ts.tv_sec); enqueue_randomness(ts.tv_nsec); dequeue_randomness(NULL); rs_count = 0; arc4random_buf(entropy_pool, sizeof(entropy_pool)); } void resume_randomness(char *buf, size_t buflen) { struct timespec ts; if (buf && buflen) _rs_seed(buf, buflen); getnanotime(&ts); enqueue_randomness(ts.tv_sec); enqueue_randomness(ts.tv_nsec); dequeue_randomness(NULL); rs_count = 0; } static inline void _rs_rekey(u_char *dat, size_t datlen); static inline void _rs_init(u_char *buf, size_t n) { KASSERT(n >= KEYSZ + IVSZ); chacha_keysetup(&rs, buf, KEYSZ * 8); chacha_ivsetup(&rs, buf + KEYSZ, NULL); } static void _rs_seed(u_char *buf, size_t n) { _rs_rekey(buf, n); /* invalidate rs_buf */ rs_have = 0; memset(rs_buf, 0, sizeof(rs_buf)); rs_count = 1600000; } static void _rs_stir(int do_lock) { struct timespec ts; u_int8_t buf[EBUFSIZE], *p; int i; /* * Use SHA512 PRNG data and a system timespec; early in the boot * process this is the best we can do -- some architectures do * not collect entropy very well during this time, but may have * clock information which is better than nothing. */ extract_entropy(buf); nanotime(&ts); for (p = (u_int8_t *)&ts, i = 0; i < sizeof(ts); i++) buf[i] ^= p[i]; if (do_lock) mtx_enter(&rndlock); _rs_seed(buf, sizeof(buf)); if (do_lock) mtx_leave(&rndlock); explicit_bzero(buf, sizeof(buf)); /* encourage fast-dequeue again */ rnd_slowextract = 1; } static inline void _rs_stir_if_needed(size_t len) { static int rs_initialized; if (!rs_initialized) { memcpy(entropy_pool, entropy_pool0, sizeof(entropy_pool)); memcpy(rs_buf, rs_buf0, sizeof(rs_buf)); /* seeds cannot be cleaned yet, random_start() will do so */ _rs_init(rs_buf, KEYSZ + IVSZ); rs_count = 1024 * 1024 * 1024; /* until main() runs */ rs_initialized = 1; } else if (rs_count <= len) _rs_stir(0); else rs_count -= len; } static void _rs_clearseed(const void *p, size_t s) { struct kmem_dyn_mode kd_avoidalias; vaddr_t va = trunc_page((vaddr_t)p); vsize_t off = (vaddr_t)p - va; vsize_t len; vaddr_t rwva; paddr_t pa; while (s > 0) { pmap_extract(pmap_kernel(), va, &pa); memset(&kd_avoidalias, 0, sizeof(kd_avoidalias)); kd_avoidalias.kd_prefer = pa; kd_avoidalias.kd_waitok = 1; rwva = (vaddr_t)km_alloc(PAGE_SIZE, &kv_any, &kp_none, &kd_avoidalias); if (!rwva) panic("_rs_clearseed"); pmap_kenter_pa(rwva, pa, PROT_READ | PROT_WRITE); pmap_update(pmap_kernel()); len = MIN(s, PAGE_SIZE - off); explicit_bzero((void *)(rwva + off), len); pmap_kremove(rwva, PAGE_SIZE); km_free((void *)rwva, PAGE_SIZE, &kv_any, &kp_none); va += PAGE_SIZE; s -= len; off = 0; } } static inline void _rs_rekey(u_char *dat, size_t datlen) { #ifndef KEYSTREAM_ONLY memset(rs_buf, 0, sizeof(rs_buf)); #endif /* fill rs_buf with the keystream */ chacha_encrypt_bytes(&rs, rs_buf, rs_buf, sizeof(rs_buf)); /* mix in optional user provided data */ if (dat) { size_t i, m; m = MIN(datlen, KEYSZ + IVSZ); for (i = 0; i < m; i++) rs_buf[i] ^= dat[i]; } /* immediately reinit for backtracking resistance */ _rs_init(rs_buf, KEYSZ + IVSZ); memset(rs_buf, 0, KEYSZ + IVSZ); rs_have = sizeof(rs_buf) - KEYSZ - IVSZ; } static inline void _rs_random_buf(void *_buf, size_t n) { u_char *buf = (u_char *)_buf; size_t m; _rs_stir_if_needed(n); while (n > 0) { if (rs_have > 0) { m = MIN(n, rs_have); memcpy(buf, rs_buf + sizeof(rs_buf) - rs_have, m); memset(rs_buf + sizeof(rs_buf) - rs_have, 0, m); buf += m; n -= m; rs_have -= m; } if (rs_have == 0) _rs_rekey(NULL, 0); } } static inline void _rs_random_u32(u_int32_t *val) { _rs_stir_if_needed(sizeof(*val)); if (rs_have < sizeof(*val)) _rs_rekey(NULL, 0); memcpy(val, rs_buf + sizeof(rs_buf) - rs_have, sizeof(*val)); memset(rs_buf + sizeof(rs_buf) - rs_have, 0, sizeof(*val)); rs_have -= sizeof(*val); } /* Return one word of randomness from a ChaCha20 generator */ u_int32_t arc4random(void) { u_int32_t ret; mtx_enter(&rndlock); _rs_random_u32(&ret); mtx_leave(&rndlock); return ret; } /* * Fill a buffer of arbitrary length with ChaCha20-derived randomness. */ void arc4random_buf(void *buf, size_t n) { mtx_enter(&rndlock); _rs_random_buf(buf, n); mtx_leave(&rndlock); } /* * Allocate a new ChaCha20 context for the caller to use. */ struct arc4random_ctx * arc4random_ctx_new(void) { char keybuf[KEYSZ + IVSZ]; chacha_ctx *ctx = malloc(sizeof(chacha_ctx), M_TEMP, M_WAITOK); arc4random_buf(keybuf, KEYSZ + IVSZ); chacha_keysetup(ctx, keybuf, KEYSZ * 8); chacha_ivsetup(ctx, keybuf + KEYSZ, NULL); explicit_bzero(keybuf, sizeof(keybuf)); return (struct arc4random_ctx *)ctx; } /* * Free a ChaCha20 context created by arc4random_ctx_new() */ void arc4random_ctx_free(struct arc4random_ctx *ctx) { explicit_bzero(ctx, sizeof(chacha_ctx)); free(ctx, M_TEMP, sizeof(chacha_ctx)); } /* * Use a given ChaCha20 context to fill a buffer */ void arc4random_ctx_buf(struct arc4random_ctx *ctx, void *buf, size_t n) { #ifndef KEYSTREAM_ONLY memset(buf, 0, n); #endif chacha_encrypt_bytes((chacha_ctx *)ctx, buf, buf, n); } /* * Calculate a uniformly distributed random number less than upper_bound * avoiding "modulo bias". * * Uniformity is achieved by generating new random numbers until the one * returned is outside the range [0, 2**32 % upper_bound). This * guarantees the selected random number will be inside * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound) * after reduction modulo upper_bound. */ u_int32_t arc4random_uniform(u_int32_t upper_bound) { u_int32_t r, min; if (upper_bound < 2) return 0; /* 2**32 % x == (2**32 - x) % x */ min = -upper_bound % upper_bound; /* * This could theoretically loop forever but each retry has * p > 0.5 (worst case, usually far better) of selecting a * number inside the range we need, so it should rarely need * to re-roll. */ for (;;) { r = arc4random(); if (r >= min) break; } return r % upper_bound; } void rnd_init(void *null) { _rs_stir(1); } /* * Called by timeout to mark arc4 for stirring, */ void rnd_reinit(void *v) { task_add(systq, &rnd_task); /* 10 minutes, per dm@'s suggestion */ timeout_add_sec(&rndreinit_timeout, 10 * 60); } /* * Start periodic services inside the random subsystem, which pull * entropy forward, hash it, and re-seed the random stream as needed. */ void random_start(int goodseed) { extern char etext[]; #if !defined(NO_PROPOLICE) extern long __guard_local; if (__guard_local == 0) printf("warning: no entropy supplied by boot loader\n"); #endif _rs_clearseed(entropy_pool0, sizeof(entropy_pool0)); _rs_clearseed(rs_buf0, sizeof(rs_buf0)); /* Message buffer may contain data from previous boot */ if (msgbufp->msg_magic == MSG_MAGIC) add_entropy_words((u_int32_t *)msgbufp->msg_bufc, msgbufp->msg_bufs / sizeof(u_int32_t)); add_entropy_words((u_int32_t *)etext - 32*1024, 8192/sizeof(u_int32_t)); dequeue_randomness(NULL); rnd_init(NULL); rnd_reinit(NULL); if (goodseed) printf("random: good seed from bootblocks\n"); else { /* XXX kernel should work harder here */ printf("random: boothowto does not indicate good seed\n"); } } int randomopen(dev_t dev, int flag, int mode, struct proc *p) { return 0; } int randomclose(dev_t dev, int flag, int mode, struct proc *p) { return 0; } /* * Maximum number of bytes to serve directly from the main ChaCha * pool. Larger requests are served from a discrete ChaCha instance keyed * from the main pool. */ #define RND_MAIN_MAX_BYTES 2048 int randomread(dev_t dev, struct uio *uio, int ioflag) { struct arc4random_ctx *lctx = NULL; size_t total = uio->uio_resid; u_char *buf; int ret = 0; if (uio->uio_resid == 0) return 0; buf = malloc(POOLBYTES, M_TEMP, M_WAITOK); if (total > RND_MAIN_MAX_BYTES) lctx = arc4random_ctx_new(); while (ret == 0 && uio->uio_resid > 0) { size_t n = ulmin(POOLBYTES, uio->uio_resid); if (lctx != NULL) arc4random_ctx_buf(lctx, buf, n); else arc4random_buf(buf, n); ret = uiomove(buf, n, uio); if (ret == 0 && uio->uio_resid > 0) yield(); } if (lctx != NULL) arc4random_ctx_free(lctx); explicit_bzero(buf, POOLBYTES); free(buf, M_TEMP, POOLBYTES); return ret; } int randomwrite(dev_t dev, struct uio *uio, int flags) { int ret = 0, newdata = 0; u_int32_t *buf; if (uio->uio_resid == 0) return 0; buf = malloc(POOLBYTES, M_TEMP, M_WAITOK); while (ret == 0 && uio->uio_resid > 0) { size_t n = ulmin(POOLBYTES, uio->uio_resid); ret = uiomove(buf, n, uio); if (ret != 0) break; while (n % sizeof(u_int32_t)) ((u_int8_t *)buf)[n++] = 0; add_entropy_words(buf, n / 4); if (uio->uio_resid > 0) yield(); newdata = 1; } if (newdata) rnd_init(NULL); explicit_bzero(buf, POOLBYTES); free(buf, M_TEMP, POOLBYTES); return ret; } int randomkqfilter(dev_t dev, struct knote *kn) { switch (kn->kn_filter) { case EVFILT_READ: kn->kn_fop = &randomread_filtops; break; case EVFILT_WRITE: kn->kn_fop = &randomwrite_filtops; break; default: return (EINVAL); } return (0); } void filt_randomdetach(struct knote *kn) { } int filt_randomread(struct knote *kn, long hint) { kn->kn_data = RND_MAIN_MAX_BYTES; return (1); } int filt_randomwrite(struct knote *kn, long hint) { kn->kn_data = POOLBYTES; return (1); } int randomioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { switch (cmd) { case FIOASYNC: /* No async flag in softc so this is a no-op. */ break; case FIONBIO: /* Handled in the upper FS layer. */ break; default: return ENOTTY; } return 0; } int sys_getentropy(struct proc *p, void *v, register_t *retval) { struct sys_getentropy_args /* { syscallarg(void *) buf; syscallarg(size_t) nbyte; } */ *uap = v; char buf[256]; int error; if (SCARG(uap, nbyte) > sizeof(buf)) return (EIO); arc4random_buf(buf, SCARG(uap, nbyte)); if ((error = copyout(buf, SCARG(uap, buf), SCARG(uap, nbyte))) != 0) return (error); explicit_bzero(buf, sizeof(buf)); *retval = 0; return (0); }
47 114 114 3 3 3 3 3 4 98 4 4 1 3 3 3 1 3 17 17 19 44 47 31 15 1290 846 488 879 552 175 383 356 161 35 33 34 34 1296 850 488 874 545 383 165 356 578 327 329 263 991 619 365 367 272 408 30 26 26 16 4 226 305 226 91 85 6 691 693 691 494 486 70 483 70 472 23 54 54 53 53 52 1 59 112 6 52 3 7 7 62 65 118 48 47 7 45 13 13 9 9 9 8 1 224 225 225 211 27 225 206 23 219 220 220 7 7 6 5 2 1 7 6 6 6 69 70 54 40 7 37 48 16 7 11 3 54 63 1 121 121 121 1 1 1 1 1 1 1 1 39 40 1 40 21 20 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 /* $OpenBSD: uipc_socket2.c,v 1.155 2024/05/17 19:11:14 mvs Exp $ */ /* $NetBSD: uipc_socket2.c,v 1.11 1996/02/04 02:17:55 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)uipc_socket2.c 8.1 (Berkeley) 6/10/93 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/protosw.h> #include <sys/domain.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/signalvar.h> #include <sys/pool.h> /* * Primitive routines for operating on sockets and socket buffers */ u_long sb_max = SB_MAX; /* patchable */ extern struct pool mclpools[]; extern struct pool mbpool; /* * Procedures to manipulate state flags of socket * and do appropriate wakeups. Normal sequence from the * active (originating) side is that soisconnecting() is * called during processing of connect() call, * resulting in an eventual call to soisconnected() if/when the * connection is established. When the connection is torn down * soisdisconnecting() is called during processing of disconnect() call, * and soisdisconnected() is called when the connection to the peer * is totally severed. The semantics of these routines are such that * connectionless protocols can call soisconnected() and soisdisconnected() * only, bypassing the in-progress calls when setting up a ``connection'' * takes no time. * * From the passive side, a socket is created with * two queues of sockets: so_q0 for connections in progress * and so_q for connections already made and awaiting user acceptance. * As a protocol is preparing incoming connections, it creates a socket * structure queued on so_q0 by calling sonewconn(). When the connection * is established, soisconnected() is called, and transfers the * socket structure to so_q, making it available to accept(). * * If a socket is closed with sockets on either * so_q0 or so_q, these sockets are dropped. * * If higher level protocols are implemented in * the kernel, the wakeups done here will sometimes * cause software-interrupt process scheduling. */ void soisconnecting(struct socket *so) { soassertlocked(so); so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING); so->so_state |= SS_ISCONNECTING; } void soisconnected(struct socket *so) { struct socket *head = so->so_head; soassertlocked(so); so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING); so->so_state |= SS_ISCONNECTED; if (head != NULL && so->so_onq == &head->so_q0) { int persocket = solock_persocket(so); if (persocket) { soref(so); soref(head); sounlock(so); solock(head); solock(so); if (so->so_onq != &head->so_q0) { sounlock(head); sorele(head); sorele(so); return; } sorele(head); sorele(so); } soqremque(so, 0); soqinsque(head, so, 1); sorwakeup(head); wakeup_one(&head->so_timeo); if (persocket) sounlock(head); } else { wakeup(&so->so_timeo); sorwakeup(so); sowwakeup(so); } } void soisdisconnecting(struct socket *so) { soassertlocked(so); so->so_state &= ~SS_ISCONNECTING; so->so_state |= SS_ISDISCONNECTING; mtx_enter(&so->so_rcv.sb_mtx); so->so_rcv.sb_state |= SS_CANTRCVMORE; mtx_leave(&so->so_rcv.sb_mtx); mtx_enter(&so->so_snd.sb_mtx); so->so_snd.sb_state |= SS_CANTSENDMORE; mtx_leave(&so->so_snd.sb_mtx); wakeup(&so->so_timeo); sowwakeup(so); sorwakeup(so); } void soisdisconnected(struct socket *so) { soassertlocked(so); so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); so->so_state |= SS_ISDISCONNECTED; mtx_enter(&so->so_rcv.sb_mtx); so->so_rcv.sb_state |= SS_CANTRCVMORE; mtx_leave(&so->so_rcv.sb_mtx); mtx_enter(&so->so_snd.sb_mtx); so->so_snd.sb_state |= SS_CANTSENDMORE; mtx_leave(&so->so_snd.sb_mtx); wakeup(&so->so_timeo); sowwakeup(so); sorwakeup(so); } /* * When an attempt at a new connection is noted on a socket * which accepts connections, sonewconn is called. If the * connection is possible (subject to space constraints, etc.) * then we allocate a new structure, properly linked into the * data structure of the original socket, and return this. * Connstatus may be 0 or SS_ISCONNECTED. */ struct socket * sonewconn(struct socket *head, int connstatus, int wait) { struct socket *so; int persocket = solock_persocket(head); int soqueue = connstatus ? 1 : 0; /* * XXXSMP as long as `so' and `head' share the same lock, we * can call soreserve() and pr_attach() below w/o explicitly * locking `so'. */ soassertlocked(head); if (m_pool_used() > 95) return (NULL); if (head->so_qlen + head->so_q0len > head->so_qlimit * 3) return (NULL); so = soalloc(head->so_proto, wait); if (so == NULL) return (NULL); so->so_type = head->so_type; so->so_options = head->so_options &~ SO_ACCEPTCONN; so->so_linger = head->so_linger; so->so_state = head->so_state | SS_NOFDREF; so->so_proto = head->so_proto; so->so_timeo = head->so_timeo; so->so_euid = head->so_euid; so->so_ruid = head->so_ruid; so->so_egid = head->so_egid; so->so_rgid = head->so_rgid; so->so_cpid = head->so_cpid; /* * Lock order will be `head' -> `so' while these sockets are linked. */ if (persocket) solock(so); /* * Inherit watermarks but those may get clamped in low mem situations. */ if (soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat)) goto fail; mtx_enter(&head->so_snd.sb_mtx); so->so_snd.sb_wat = head->so_snd.sb_wat; so->so_snd.sb_lowat = head->so_snd.sb_lowat; so->so_snd.sb_timeo_nsecs = head->so_snd.sb_timeo_nsecs; mtx_leave(&head->so_snd.sb_mtx); mtx_enter(&head->so_rcv.sb_mtx); so->so_rcv.sb_wat = head->so_rcv.sb_wat; so->so_rcv.sb_lowat = head->so_rcv.sb_lowat; so->so_rcv.sb_timeo_nsecs = head->so_rcv.sb_timeo_nsecs; mtx_leave(&head->so_rcv.sb_mtx); sigio_copy(&so->so_sigio, &head->so_sigio); soqinsque(head, so, soqueue); if (pru_attach(so, 0, wait) != 0) { soqremque(so, soqueue); goto fail; } if (connstatus) { so->so_state |= connstatus; sorwakeup(head); wakeup(&head->so_timeo); } if (persocket) sounlock(so); return (so); fail: if (persocket) sounlock(so); sigio_free(&so->so_sigio); klist_free(&so->so_rcv.sb_klist); klist_free(&so->so_snd.sb_klist); pool_put(&socket_pool, so); return (NULL); } void soqinsque(struct socket *head, struct socket *so, int q) { soassertlocked(head); soassertlocked(so); KASSERT(so->so_onq == NULL); so->so_head = head; if (q == 0) { head->so_q0len++; so->so_onq = &head->so_q0; } else { head->so_qlen++; so->so_onq = &head->so_q; } TAILQ_INSERT_TAIL(so->so_onq, so, so_qe); } int soqremque(struct socket *so, int q) { struct socket *head = so->so_head; soassertlocked(so); soassertlocked(head); if (q == 0) { if (so->so_onq != &head->so_q0) return (0); head->so_q0len--; } else { if (so->so_onq != &head->so_q) return (0); head->so_qlen--; } TAILQ_REMOVE(so->so_onq, so, so_qe); so->so_onq = NULL; so->so_head = NULL; return (1); } /* * Socantsendmore indicates that no more data will be sent on the * socket; it would normally be applied to a socket when the user * informs the system that no more data is to be sent, by the protocol * code (in case PRU_SHUTDOWN). Socantrcvmore indicates that no more data * will be received, and will normally be applied to the socket by a * protocol when it detects that the peer will send no more data. * Data queued for reading in the socket may yet be read. */ void socantsendmore(struct socket *so) { soassertlocked(so); mtx_enter(&so->so_snd.sb_mtx); so->so_snd.sb_state |= SS_CANTSENDMORE; mtx_leave(&so->so_snd.sb_mtx); sowwakeup(so); } void socantrcvmore(struct socket *so) { if ((so->so_rcv.sb_flags & SB_MTXLOCK) == 0) soassertlocked(so); mtx_enter(&so->so_rcv.sb_mtx); so->so_rcv.sb_state |= SS_CANTRCVMORE; mtx_leave(&so->so_rcv.sb_mtx); sorwakeup(so); } void solock(struct socket *so) { switch (so->so_proto->pr_domain->dom_family) { case PF_INET: case PF_INET6: NET_LOCK(); break; default: rw_enter_write(&so->so_lock); break; } } void solock_shared(struct socket *so) { switch (so->so_proto->pr_domain->dom_family) { case PF_INET: case PF_INET6: if (so->so_proto->pr_usrreqs->pru_lock != NULL) { NET_LOCK_SHARED(); rw_enter_write(&so->so_lock); } else NET_LOCK(); break; default: rw_enter_write(&so->so_lock); break; } } int solock_persocket(struct socket *so) { switch (so->so_proto->pr_domain->dom_family) { case PF_INET: case PF_INET6: return 0; default: return 1; } } void solock_pair(struct socket *so1, struct socket *so2) { KASSERT(so1 != so2); KASSERT(so1->so_type == so2->so_type); KASSERT(solock_persocket(so1)); if (so1 < so2) { solock(so1); solock(so2); } else { solock(so2); solock(so1); } } void sounlock(struct socket *so) { switch (so->so_proto->pr_domain->dom_family) { case PF_INET: case PF_INET6: NET_UNLOCK(); break; default: rw_exit_write(&so->so_lock); break; } } void sounlock_shared(struct socket *so) { switch (so->so_proto->pr_domain->dom_family) { case PF_INET: case PF_INET6: if (so->so_proto->pr_usrreqs->pru_unlock != NULL) { rw_exit_write(&so->so_lock); NET_UNLOCK_SHARED(); } else NET_UNLOCK(); break; default: rw_exit_write(&so->so_lock); break; } } void soassertlocked_readonly(struct socket *so) { switch (so->so_proto->pr_domain->dom_family) { case PF_INET: case PF_INET6: NET_ASSERT_LOCKED(); break; default: rw_assert_wrlock(&so->so_lock); break; } } void soassertlocked(struct socket *so) { switch (so->so_proto->pr_domain->dom_family) { case PF_INET: case PF_INET6: if (rw_status(&netlock) == RW_READ) { NET_ASSERT_LOCKED(); if (splassert_ctl > 0 && pru_locked(so) == 0 && rw_status(&so->so_lock) != RW_WRITE) splassert_fail(0, RW_WRITE, __func__); } else NET_ASSERT_LOCKED_EXCLUSIVE(); break; default: rw_assert_wrlock(&so->so_lock); break; } } int sosleep_nsec(struct socket *so, void *ident, int prio, const char *wmesg, uint64_t nsecs) { int ret; switch (so->so_proto->pr_domain->dom_family) { case PF_INET: case PF_INET6: if (so->so_proto->pr_usrreqs->pru_unlock != NULL && rw_status(&netlock) == RW_READ) { rw_exit_write(&so->so_lock); } ret = rwsleep_nsec(ident, &netlock, prio, wmesg, nsecs); if (so->so_proto->pr_usrreqs->pru_lock != NULL && rw_status(&netlock) == RW_READ) { rw_enter_write(&so->so_lock); } break; default: ret = rwsleep_nsec(ident, &so->so_lock, prio, wmesg, nsecs); break; } return ret; } void sbmtxassertlocked(struct socket *so, struct sockbuf *sb) { if (sb->sb_flags & SB_MTXLOCK) { if (splassert_ctl > 0 && mtx_owned(&sb->sb_mtx) == 0) splassert_fail(0, RW_WRITE, __func__); } else soassertlocked(so); } /* * Wait for data to arrive at/drain from a socket buffer. */ int sbwait(struct socket *so, struct sockbuf *sb) { uint64_t timeo_nsecs; int prio = (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH; if (sb->sb_flags & SB_MTXLOCK) { MUTEX_ASSERT_LOCKED(&sb->sb_mtx); sb->sb_flags |= SB_WAIT; return msleep_nsec(&sb->sb_cc, &sb->sb_mtx, prio, "sbwait", sb->sb_timeo_nsecs); } soassertlocked(so); mtx_enter(&sb->sb_mtx); timeo_nsecs = sb->sb_timeo_nsecs; sb->sb_flags |= SB_WAIT; mtx_leave(&sb->sb_mtx); return sosleep_nsec(so, &sb->sb_cc, prio, "netio", timeo_nsecs); } int sblock(struct sockbuf *sb, int flags) { int rwflags = RW_WRITE, error; if (!(flags & SBL_NOINTR || sb->sb_flags & SB_NOINTR)) rwflags |= RW_INTR; if (!(flags & SBL_WAIT)) rwflags |= RW_NOSLEEP; error = rw_enter(&sb->sb_lock, rwflags); if (error == EBUSY) error = EWOULDBLOCK; return error; } void sbunlock(struct sockbuf *sb) { rw_exit(&sb->sb_lock); } /* * Wakeup processes waiting on a socket buffer. * Do asynchronous notification via SIGIO * if the socket buffer has the SB_ASYNC flag set. */ void sowakeup(struct socket *so, struct sockbuf *sb) { int dowakeup = 0, dopgsigio = 0; mtx_enter(&sb->sb_mtx); if (sb->sb_flags & SB_WAIT) { sb->sb_flags &= ~SB_WAIT; dowakeup = 1; } if (sb->sb_flags & SB_ASYNC) dopgsigio = 1; knote_locked(&sb->sb_klist, 0); mtx_leave(&sb->sb_mtx); if (dowakeup) wakeup(&sb->sb_cc); if (dopgsigio) pgsigio(&so->so_sigio, SIGIO, 0); } /* * Socket buffer (struct sockbuf) utility routines. * * Each socket contains two socket buffers: one for sending data and * one for receiving data. Each buffer contains a queue of mbufs, * information about the number of mbufs and amount of data in the * queue, and other fields allowing select() statements and notification * on data availability to be implemented. * * Data stored in a socket buffer is maintained as a list of records. * Each record is a list of mbufs chained together with the m_next * field. Records are chained together with the m_nextpkt field. The upper * level routine soreceive() expects the following conventions to be * observed when placing information in the receive buffer: * * 1. If the protocol requires each message be preceded by the sender's * name, then a record containing that name must be present before * any associated data (mbuf's must be of type MT_SONAME). * 2. If the protocol supports the exchange of ``access rights'' (really * just additional data associated with the message), and there are * ``rights'' to be received, then a record containing this data * should be present (mbuf's must be of type MT_CONTROL). * 3. If a name or rights record exists, then it must be followed by * a data record, perhaps of zero length. * * Before using a new socket structure it is first necessary to reserve * buffer space to the socket, by calling sbreserve(). This should commit * some of the available buffer space in the system buffer pool for the * socket (currently, it does nothing but enforce limits). The space * should be released by calling sbrelease() when the socket is destroyed. */ int soreserve(struct socket *so, u_long sndcc, u_long rcvcc) { soassertlocked(so); mtx_enter(&so->so_rcv.sb_mtx); mtx_enter(&so->so_snd.sb_mtx); if (sbreserve(so, &so->so_snd, sndcc)) goto bad; so->so_snd.sb_wat = sndcc; if (so->so_snd.sb_lowat == 0) so->so_snd.sb_lowat = MCLBYTES; if (so->so_snd.sb_lowat > so->so_snd.sb_hiwat) so->so_snd.sb_lowat = so->so_snd.sb_hiwat; if (sbreserve(so, &so->so_rcv, rcvcc)) goto bad2; so->so_rcv.sb_wat = rcvcc; if (so->so_rcv.sb_lowat == 0) so->so_rcv.sb_lowat = 1; mtx_leave(&so->so_snd.sb_mtx); mtx_leave(&so->so_rcv.sb_mtx); return (0); bad2: sbrelease(so, &so->so_snd); bad: mtx_leave(&so->so_snd.sb_mtx); mtx_leave(&so->so_rcv.sb_mtx); return (ENOBUFS); } /* * Allot mbufs to a sockbuf. * Attempt to scale mbmax so that mbcnt doesn't become limiting * if buffering efficiency is near the normal case. */ int sbreserve(struct socket *so, struct sockbuf *sb, u_long cc) { sbmtxassertlocked(so, sb); if (cc == 0 || cc > sb_max) return (1); sb->sb_hiwat = cc; sb->sb_mbmax = max(3 * MAXMCLBYTES, cc * 8); if (sb->sb_lowat > sb->sb_hiwat) sb->sb_lowat = sb->sb_hiwat; return (0); } /* * In low memory situation, do not accept any greater than normal request. */ int sbcheckreserve(u_long cnt, u_long defcnt) { if (cnt > defcnt && sbchecklowmem()) return (ENOBUFS); return (0); } int sbchecklowmem(void) { static int sblowmem; unsigned int used = m_pool_used(); if (used < 60) sblowmem = 0; else if (used > 80) sblowmem = 1; return (sblowmem); } /* * Free mbufs held by a socket, and reserved mbuf space. */ void sbrelease(struct socket *so, struct sockbuf *sb) { sbflush(so, sb); sb->sb_hiwat = sb->sb_mbmax = 0; } /* * Routines to add and remove * data from an mbuf queue. * * The routines sbappend() or sbappendrecord() are normally called to * append new mbufs to a socket buffer, after checking that adequate * space is available, comparing the function sbspace() with the amount * of data to be added. sbappendrecord() differs from sbappend() in * that data supplied is treated as the beginning of a new record. * To place a sender's address, optional access rights, and data in a * socket receive buffer, sbappendaddr() should be used. To place * access rights and data in a socket receive buffer, sbappendrights() * should be used. In either case, the new data begins a new record. * Note that unlike sbappend() and sbappendrecord(), these routines check * for the caller that there will be enough space to store the data. * Each fails if there is not enough space, or if it cannot find mbufs * to store additional information in. * * Reliable protocols may use the socket send buffer to hold data * awaiting acknowledgement. Data is normally copied from a socket * send buffer in a protocol with m_copym for output to a peer, * and then removing the data from the socket buffer with sbdrop() * or sbdroprecord() when the data is acknowledged by the peer. */ #ifdef SOCKBUF_DEBUG void sblastrecordchk(struct sockbuf *sb, const char *where) { struct mbuf *m = sb->sb_mb; while (m && m->m_nextpkt) m = m->m_nextpkt; if (m != sb->sb_lastrecord) { printf("sblastrecordchk: sb_mb %p sb_lastrecord %p last %p\n", sb->sb_mb, sb->sb_lastrecord, m); printf("packet chain:\n"); for (m = sb->sb_mb; m != NULL; m = m->m_nextpkt) printf("\t%p\n", m); panic("sblastrecordchk from %s", where); } } void sblastmbufchk(struct sockbuf *sb, const char *where) { struct mbuf *m = sb->sb_mb; struct mbuf *n; while (m && m->m_nextpkt) m = m->m_nextpkt; while (m && m->m_next) m = m->m_next; if (m != sb->sb_mbtail) { printf("sblastmbufchk: sb_mb %p sb_mbtail %p last %p\n", sb->sb_mb, sb->sb_mbtail, m); printf("packet tree:\n"); for (m = sb->sb_mb; m != NULL; m = m->m_nextpkt) { printf("\t"); for (n = m; n != NULL; n = n->m_next) printf("%p ", n); printf("\n"); } panic("sblastmbufchk from %s", where); } } #endif /* SOCKBUF_DEBUG */ #define SBLINKRECORD(sb, m0) \ do { \ if ((sb)->sb_lastrecord != NULL) \ (sb)->sb_lastrecord->m_nextpkt = (m0); \ else \ (sb)->sb_mb = (m0); \ (sb)->sb_lastrecord = (m0); \ } while (/*CONSTCOND*/0) /* * Append mbuf chain m to the last record in the * socket buffer sb. The additional space associated * the mbuf chain is recorded in sb. Empty mbufs are * discarded and mbufs are compacted where possible. */ void sbappend(struct socket *so, struct sockbuf *sb, struct mbuf *m) { struct mbuf *n; if (m == NULL) return; sbmtxassertlocked(so, sb); SBLASTRECORDCHK(sb, "sbappend 1"); if ((n = sb->sb_lastrecord) != NULL) { /* * XXX Would like to simply use sb_mbtail here, but * XXX I need to verify that I won't miss an EOR that * XXX way. */ do { if (n->m_flags & M_EOR) { sbappendrecord(so, sb, m); /* XXXXXX!!!! */ return; } } while (n->m_next && (n = n->m_next)); } else { /* * If this is the first record in the socket buffer, it's * also the last record. */ sb->sb_lastrecord = m; } sbcompress(so, sb, m, n); SBLASTRECORDCHK(sb, "sbappend 2"); } /* * This version of sbappend() should only be used when the caller * absolutely knows that there will never be more than one record * in the socket buffer, that is, a stream protocol (such as TCP). */ void sbappendstream(struct socket *so, struct sockbuf *sb, struct mbuf *m) { KASSERT(sb == &so->so_rcv || sb == &so->so_snd); soassertlocked(so); KDASSERT(m->m_nextpkt == NULL); KASSERT(sb->sb_mb == sb->sb_lastrecord); SBLASTMBUFCHK(sb, __func__); sbcompress(so, sb, m, sb->sb_mbtail); sb->sb_lastrecord = sb->sb_mb; SBLASTRECORDCHK(sb, __func__); } #ifdef SOCKBUF_DEBUG void sbcheck(struct socket *so, struct sockbuf *sb) { struct mbuf *m, *n; u_long len = 0, mbcnt = 0; for (m = sb->sb_mb; m; m = m->m_nextpkt) { for (n = m; n; n = n->m_next) { len += n->m_len; mbcnt += MSIZE; if (n->m_flags & M_EXT) mbcnt += n->m_ext.ext_size; if (m != n && n->m_nextpkt) panic("sbcheck nextpkt"); } } if (len != sb->sb_cc || mbcnt != sb->sb_mbcnt) { printf("cc %lu != %lu || mbcnt %lu != %lu\n", len, sb->sb_cc, mbcnt, sb->sb_mbcnt); panic("sbcheck"); } } #endif /* * As above, except the mbuf chain * begins a new record. */ void sbappendrecord(struct socket *so, struct sockbuf *sb, struct mbuf *m0) { struct mbuf *m; sbmtxassertlocked(so, sb); if (m0 == NULL) return; /* * Put the first mbuf on the queue. * Note this permits zero length records. */ sballoc(so, sb, m0); SBLASTRECORDCHK(sb, "sbappendrecord 1"); SBLINKRECORD(sb, m0); m = m0->m_next; m0->m_next = NULL; if (m && (m0->m_flags & M_EOR)) { m0->m_flags &= ~M_EOR; m->m_flags |= M_EOR; } sbcompress(so, sb, m, m0); SBLASTRECORDCHK(sb, "sbappendrecord 2"); } /* * Append address and data, and optionally, control (ancillary) data * to the receive queue of a socket. If present, * m0 must include a packet header with total length. * Returns 0 if no space in sockbuf or insufficient mbufs. */ int sbappendaddr(struct socket *so, struct sockbuf *sb, const struct sockaddr *asa, struct mbuf *m0, struct mbuf *control) { struct mbuf *m, *n, *nlast; int space = asa->sa_len; sbmtxassertlocked(so, sb); if (m0 && (m0->m_flags & M_PKTHDR) == 0) panic("sbappendaddr"); if (m0) space += m0->m_pkthdr.len; for (n = control; n; n = n->m_next) { space += n->m_len; if (n->m_next == NULL) /* keep pointer to last control buf */ break; } if (space > sbspace(so, sb)) return (0); if (asa->sa_len > MLEN) return (0); MGET(m, M_DONTWAIT, MT_SONAME); if (m == NULL) return (0); m->m_len = asa->sa_len; memcpy(mtod(m, caddr_t), asa, asa->sa_len); if (n) n->m_next = m0; /* concatenate data to control */ else control = m0; m->m_next = control; SBLASTRECORDCHK(sb, "sbappendaddr 1"); for (n = m; n->m_next != NULL; n = n->m_next) sballoc(so, sb, n); sballoc(so, sb, n); nlast = n; SBLINKRECORD(sb, m); sb->sb_mbtail = nlast; SBLASTMBUFCHK(sb, "sbappendaddr"); SBLASTRECORDCHK(sb, "sbappendaddr 2"); return (1); } int sbappendcontrol(struct socket *so, struct sockbuf *sb, struct mbuf *m0, struct mbuf *control) { struct mbuf *m, *mlast, *n; int eor = 0, space = 0; sbmtxassertlocked(so, sb); if (control == NULL) panic("sbappendcontrol"); for (m = control; ; m = m->m_next) { space += m->m_len; if (m->m_next == NULL) break; } n = m; /* save pointer to last control buffer */ for (m = m0; m; m = m->m_next) { space += m->m_len; eor |= m->m_flags & M_EOR; if (eor) { if (m->m_next == NULL) m->m_flags |= M_EOR; else m->m_flags &= ~M_EOR; } } if (space > sbspace(so, sb)) return (0); n->m_next = m0; /* concatenate data to control */ SBLASTRECORDCHK(sb, "sbappendcontrol 1"); for (m = control; m->m_next != NULL; m = m->m_next) sballoc(so, sb, m); sballoc(so, sb, m); mlast = m; SBLINKRECORD(sb, control); sb->sb_mbtail = mlast; SBLASTMBUFCHK(sb, "sbappendcontrol"); SBLASTRECORDCHK(sb, "sbappendcontrol 2"); return (1); } /* * Compress mbuf chain m into the socket * buffer sb following mbuf n. If n * is null, the buffer is presumed empty. */ void sbcompress(struct socket *so, struct sockbuf *sb, struct mbuf *m, struct mbuf *n) { int eor = 0; struct mbuf *o; while (m) { eor |= m->m_flags & M_EOR; if (m->m_len == 0 && (eor == 0 || (((o = m->m_next) || (o = n)) && o->m_type == m->m_type))) { if (sb->sb_lastrecord == m) sb->sb_lastrecord = m->m_next; m = m_free(m); continue; } if (n && (n->m_flags & M_EOR) == 0 && /* m_trailingspace() checks buffer writeability */ m->m_len <= ((n->m_flags & M_EXT)? n->m_ext.ext_size : MCLBYTES) / 4 && /* XXX Don't copy too much */ m->m_len <= m_trailingspace(n) && n->m_type == m->m_type) { memcpy(mtod(n, caddr_t) + n->m_len, mtod(m, caddr_t), m->m_len); n->m_len += m->m_len; sb->sb_cc += m->m_len; if (m->m_type != MT_CONTROL && m->m_type != MT_SONAME) sb->sb_datacc += m->m_len; m = m_free(m); continue; } if (n) n->m_next = m; else sb->sb_mb = m; sb->sb_mbtail = m; sballoc(so, sb, m); n = m; m->m_flags &= ~M_EOR; m = m->m_next; n->m_next = NULL; } if (eor) { if (n) n->m_flags |= eor; else printf("semi-panic: sbcompress"); } SBLASTMBUFCHK(sb, __func__); } /* * Free all mbufs in a sockbuf. * Check that all resources are reclaimed. */ void sbflush(struct socket *so, struct sockbuf *sb) { KASSERT(sb == &so->so_rcv || sb == &so->so_snd); rw_assert_unlocked(&sb->sb_lock); while (sb->sb_mbcnt) sbdrop(so, sb, (int)sb->sb_cc); KASSERT(sb->sb_cc == 0); KASSERT(sb->sb_datacc == 0); KASSERT(sb->sb_mb == NULL); KASSERT(sb->sb_mbtail == NULL); KASSERT(sb->sb_lastrecord == NULL); } /* * Drop data from (the front of) a sockbuf. */ void sbdrop(struct socket *so, struct sockbuf *sb, int len) { struct mbuf *m, *mn; struct mbuf *next; sbmtxassertlocked(so, sb); next = (m = sb->sb_mb) ? m->m_nextpkt : NULL; while (len > 0) { if (m == NULL) { if (next == NULL) panic("sbdrop"); m = next; next = m->m_nextpkt; continue; } if (m->m_len > len) { m->m_len -= len; m->m_data += len; sb->sb_cc -= len; if (m->m_type != MT_CONTROL && m->m_type != MT_SONAME) sb->sb_datacc -= len; break; } len -= m->m_len; sbfree(so, sb, m); mn = m_free(m); m = mn; } while (m && m->m_len == 0) { sbfree(so, sb, m); mn = m_free(m); m = mn; } if (m) { sb->sb_mb = m; m->m_nextpkt = next; } else sb->sb_mb = next; /* * First part is an inline SB_EMPTY_FIXUP(). Second part * makes sure sb_lastrecord is up-to-date if we dropped * part of the last record. */ m = sb->sb_mb; if (m == NULL) { sb->sb_mbtail = NULL; sb->sb_lastrecord = NULL; } else if (m->m_nextpkt == NULL) sb->sb_lastrecord = m; } /* * Drop a record off the front of a sockbuf * and move the next record to the front. */ void sbdroprecord(struct socket *so, struct sockbuf *sb) { struct mbuf *m, *mn; m = sb->sb_mb; if (m) { sb->sb_mb = m->m_nextpkt; do { sbfree(so, sb, m); mn = m_free(m); } while ((m = mn) != NULL); } SB_EMPTY_FIXUP(sb); } /* * Create a "control" mbuf containing the specified data * with the specified type for presentation on a socket buffer. */ struct mbuf * sbcreatecontrol(const void *p, size_t size, int type, int level) { struct cmsghdr *cp; struct mbuf *m; if (CMSG_SPACE(size) > MCLBYTES) { printf("sbcreatecontrol: message too large %zu\n", size); return (NULL); } if ((m = m_get(M_DONTWAIT, MT_CONTROL)) == NULL) return (NULL); if (CMSG_SPACE(size) > MLEN) { MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { m_free(m); return NULL; } } cp = mtod(m, struct cmsghdr *); memset(cp, 0, CMSG_SPACE(size)); memcpy(CMSG_DATA(cp), p, size); m->m_len = CMSG_SPACE(size); cp->cmsg_len = CMSG_LEN(size); cp->cmsg_level = level; cp->cmsg_type = type; return (m); }
250 13 2 1 235 235 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 /* $OpenBSD: subr_autoconf.c,v 1.97 2022/11/07 14:25:44 robert Exp $ */ /* $NetBSD: subr_autoconf.c,v 1.21 1996/04/04 06:06:18 cgd Exp $ */ /* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Lawrence Berkeley Laboratories. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: Header: subr_autoconf.c,v 1.12 93/02/01 19:31:48 torek Exp (LBL) * * @(#)subr_autoconf.c 8.1 (Berkeley) 6/10/93 */ #include <sys/param.h> #include <sys/device.h> #include <sys/hotplug.h> #include <sys/malloc.h> #include <sys/systm.h> #include <sys/queue.h> #include <sys/mutex.h> #include <sys/atomic.h> #include <sys/reboot.h> #include "hotplug.h" #include "mpath.h" /* * Autoconfiguration subroutines. */ /* * ioconf.c exports exactly two names: cfdata and cfroots. All system * devices and drivers are found via these tables. */ extern short cfroots[]; #define ROOT ((struct device *)NULL) struct matchinfo { cfmatch_t fn; struct device *parent; void *match, *aux; int indirect, pri; }; #ifndef AUTOCONF_VERBOSE #define AUTOCONF_VERBOSE 0 #endif /* AUTOCONF_VERBOSE */ int autoconf_verbose = AUTOCONF_VERBOSE; /* trace probe calls */ static void mapply(struct matchinfo *, struct cfdata *); struct deferred_config { TAILQ_ENTRY(deferred_config) dc_queue; struct device *dc_dev; void (*dc_func)(struct device *); }; TAILQ_HEAD(, deferred_config) deferred_config_queue; TAILQ_HEAD(, deferred_config) mountroot_config_queue; void *config_rootsearch(cfmatch_t, char *, void *); void config_process_deferred_children(struct device *); struct devicelist alldevs; /* list of all devices */ volatile int config_pending; /* semaphore for mountroot */ struct mutex autoconf_attdet_mtx = MUTEX_INITIALIZER(IPL_HIGH); /* * If > 0, devices are being attached and any thread which tries to * detach will sleep; if < 0 devices are being detached and any * thread which tries to attach will sleep. */ int autoconf_attdet; /* * Versioned state of the devices tree so that changes can be detected. */ unsigned int autoconf_serial = 0; /* * Initialize autoconfiguration data structures. This occurs before console * initialization as that might require use of this subsystem. Furthermore * this means that malloc et al. isn't yet available. */ void config_init(void) { TAILQ_INIT(&deferred_config_queue); TAILQ_INIT(&mountroot_config_queue); TAILQ_INIT(&alldevs); } /* * Apply the matching function and choose the best. This is used * a few times and we want to keep the code small. */ void mapply(struct matchinfo *m, struct cfdata *cf) { int pri; void *match; if (m->indirect) match = config_make_softc(m->parent, cf); else match = cf; if (autoconf_verbose) { printf(">>> probing for %s", cf->cf_driver->cd_name); if (cf->cf_fstate == FSTATE_STAR) printf("*\n"); else printf("%d\n", cf->cf_unit); } if (m->fn != NULL) pri = (*m->fn)(m->parent, match, m->aux); else { if (cf->cf_attach->ca_match == NULL) { panic("mapply: no match function for '%s' device", cf->cf_driver->cd_name); } pri = (*cf->cf_attach->ca_match)(m->parent, match, m->aux); } if (autoconf_verbose) printf(">>> %s probe returned %d\n", cf->cf_driver->cd_name, pri); if (pri > m->pri) { if (m->indirect && m->match) { cf = ((struct device *)m->match)->dv_cfdata; free(m->match, M_DEVBUF, cf->cf_attach->ca_devsize); } m->match = match; m->pri = pri; } else { if (m->indirect) free(match, M_DEVBUF, cf->cf_attach->ca_devsize); } } /* * Iterate over all potential children of some device, calling the given * function (default being the child's match function) for each one. * Nonzero returns are matches; the highest value returned is considered * the best match. Return the `found child' if we got a match, or NULL * otherwise. The `aux' pointer is simply passed on through. * * Note that this function is designed so that it can be used to apply * an arbitrary function to all potential children (its return value * can be ignored). */ void * config_search(cfmatch_t fn, struct device *parent, void *aux) { struct cfdata *cf; short *p; struct matchinfo m; m.fn = fn; m.parent = parent; m.match = NULL; m.aux = aux; m.indirect = parent && (parent->dv_cfdata->cf_driver->cd_mode & CD_INDIRECT); m.pri = 0; for (cf = cfdata; cf->cf_driver; cf++) { /* * Skip cf if no longer eligible, otherwise scan * through parents for one matching `parent', * and try match function. */ if (cf->cf_fstate == FSTATE_FOUND) continue; if (cf->cf_fstate == FSTATE_DNOTFOUND || cf->cf_fstate == FSTATE_DSTAR) continue; if (boothowto & RB_UNHIBERNATE) { if (cf->cf_driver->cd_mode & CD_SKIPHIBERNATE) continue; if (cf->cf_driver->cd_class == DV_IFNET) continue; if (cf->cf_driver->cd_class == DV_TAPE) continue; } for (p = cf->cf_parents; *p >= 0; p++) if (parent->dv_cfdata == &cfdata[*p]) mapply(&m, cf); } if (autoconf_verbose) { if (m.match) { if (m.indirect) cf = ((struct device *)m.match)->dv_cfdata; else cf = (struct cfdata *)m.match; printf(">>> %s probe won\n", cf->cf_driver->cd_name); } else printf(">>> no winning probe\n"); } return (m.match); } /* * Iterate over all potential children of some device, calling the given * function for each one. * * Note that this function is designed so that it can be used to apply * an arbitrary function to all potential children (its return value * can be ignored). */ void config_scan(cfscan_t fn, struct device *parent) { struct cfdata *cf; short *p; void *match; int indirect; indirect = parent && (parent->dv_cfdata->cf_driver->cd_mode & CD_INDIRECT); for (cf = cfdata; cf->cf_driver; cf++) { /* * Skip cf if no longer eligible, otherwise scan * through parents for one matching `parent', * and try match function. */ if (cf->cf_fstate == FSTATE_FOUND) continue; if (cf->cf_fstate == FSTATE_DNOTFOUND || cf->cf_fstate == FSTATE_DSTAR) continue; for (p = cf->cf_parents; *p >= 0; p++) if (parent->dv_cfdata == &cfdata[*p]) { match = indirect? config_make_softc(parent, cf) : (void *)cf; (*fn)(parent, match); } } } /* * Find the given root device. * This is much like config_search, but there is no parent. */ void * config_rootsearch(cfmatch_t fn, char *rootname, void *aux) { struct cfdata *cf; short *p; struct matchinfo m; m.fn = fn; m.parent = ROOT; m.match = NULL; m.aux = aux; m.indirect = 0; m.pri = 0; /* * Look at root entries for matching name. We do not bother * with found-state here since only one instance of each possible * root child should ever be searched. */ for (p = cfroots; *p >= 0; p++) { cf = &cfdata[*p]; if (cf->cf_fstate == FSTATE_DNOTFOUND || cf->cf_fstate == FSTATE_DSTAR) continue; if (strcmp(cf->cf_driver->cd_name, rootname) == 0) mapply(&m, cf); } return (m.match); } const char *msgs[3] = { "", " not configured\n", " unsupported\n" }; /* * The given `aux' argument describes a device that has been found * on the given parent, but not necessarily configured. Locate the * configuration data for that device (using the submatch function * provided, or using candidates' cd_match configuration driver * functions) and attach it, and return true. If the device was * not configured, call the given `print' function and return 0. */ struct device * config_found_sm(struct device *parent, void *aux, cfprint_t print, cfmatch_t submatch) { void *match; if ((match = config_search(submatch, parent, aux)) != NULL) return (config_attach(parent, match, aux, print)); if (print) printf("%s", msgs[(*print)(aux, parent->dv_xname)]); return (NULL); } /* * As above, but for root devices. */ struct device * config_rootfound(char *rootname, void *aux) { void *match; if ((match = config_rootsearch((cfmatch_t)NULL, rootname, aux)) != NULL) return (config_attach(ROOT, match, aux, (cfprint_t)NULL)); printf("root device %s not configured\n", rootname); return (NULL); } /* * Attach a found device. Allocates memory for device variables. */ struct device * config_attach(struct device *parent, void *match, void *aux, cfprint_t print) { struct cfdata *cf; struct device *dev; struct cfdriver *cd; const struct cfattach *ca; mtx_enter(&autoconf_attdet_mtx); while (autoconf_attdet < 0) msleep_nsec(&autoconf_attdet, &autoconf_attdet_mtx, PWAIT, "autoconf", INFSLP); autoconf_attdet++; mtx_leave(&autoconf_attdet_mtx); if (parent && (parent->dv_cfdata->cf_driver->cd_mode & CD_INDIRECT)) { dev = match; cf = dev->dv_cfdata; } else { cf = match; dev = config_make_softc(parent, cf); } cd = cf->cf_driver; ca = cf->cf_attach; KASSERT(cd->cd_devs != NULL); KASSERT(dev->dv_unit < cd->cd_ndevs); KASSERT(cd->cd_devs[dev->dv_unit] == NULL); cd->cd_devs[dev->dv_unit] = dev; /* * If this is a "STAR" device and we used the last unit, prepare for * another one. */ if (cf->cf_fstate == FSTATE_STAR) { if (dev->dv_unit == cf->cf_unit) cf->cf_unit++; } else cf->cf_fstate = FSTATE_FOUND; TAILQ_INSERT_TAIL(&alldevs, dev, dv_list); device_ref(dev); if (parent == ROOT) printf("%s at root", dev->dv_xname); else { printf("%s at %s", dev->dv_xname, parent->dv_xname); if (print) (void) (*print)(aux, NULL); } /* * Before attaching, clobber any unfound devices that are * otherwise identical, or bump the unit number on all starred * cfdata for this device. */ for (cf = cfdata; cf->cf_driver; cf++) { if (cf->cf_driver == cd && cf->cf_unit == dev->dv_unit) { if (cf->cf_fstate == FSTATE_NOTFOUND) cf->cf_fstate = FSTATE_FOUND; if (cf->cf_fstate == FSTATE_STAR) cf->cf_unit++; } } device_register(dev, aux); (*ca->ca_attach)(parent, dev, aux); config_process_deferred_children(dev); #if NHOTPLUG > 0 if (!cold) hotplug_device_attach(cd->cd_class, dev->dv_xname); #endif mtx_enter(&autoconf_attdet_mtx); if (--autoconf_attdet == 0) wakeup(&autoconf_attdet); autoconf_serial++; mtx_leave(&autoconf_attdet_mtx); return (dev); } struct device * config_make_softc(struct device *parent, struct cfdata *cf) { struct device *dev; struct cfdriver *cd; const struct cfattach *ca; cd = cf->cf_driver; ca = cf->cf_attach; if (ca->ca_devsize < sizeof(struct device)) panic("config_make_softc"); /* get memory for all device vars */ dev = malloc(ca->ca_devsize, M_DEVBUF, M_NOWAIT|M_ZERO); if (dev == NULL) panic("config_make_softc: allocation for device softc failed"); dev->dv_class = cd->cd_class; dev->dv_cfdata = cf; dev->dv_flags = DVF_ACTIVE; /* always initially active */ /* If this is a STAR device, search for a free unit number */ if (cf->cf_fstate == FSTATE_STAR) { for (dev->dv_unit = cf->cf_starunit1; dev->dv_unit < cf->cf_unit; dev->dv_unit++) if (cd->cd_ndevs == 0 || dev->dv_unit >= cd->cd_ndevs || cd->cd_devs[dev->dv_unit] == NULL) break; } else dev->dv_unit = cf->cf_unit; /* Build the device name into dv_xname. */ if (snprintf(dev->dv_xname, sizeof(dev->dv_xname), "%s%d", cd->cd_name, dev->dv_unit) >= sizeof(dev->dv_xname)) panic("config_make_softc: device name too long"); dev->dv_parent = parent; /* put this device in the devices array */ if (dev->dv_unit >= cd->cd_ndevs) { /* * Need to expand the array. */ int old = cd->cd_ndevs, new; void **nsp; if (old == 0) new = MINALLOCSIZE / sizeof(void *); else new = old * 2; while (new <= dev->dv_unit) new *= 2; cd->cd_ndevs = new; nsp = mallocarray(new, sizeof(void *), M_DEVBUF, M_NOWAIT|M_ZERO); if (nsp == NULL) panic("config_make_softc: %sing dev array", old != 0 ? "expand" : "creat"); if (old != 0) { bcopy(cd->cd_devs, nsp, old * sizeof(void *)); free(cd->cd_devs, M_DEVBUF, old * sizeof(void *)); } cd->cd_devs = nsp; } if (cd->cd_devs[dev->dv_unit]) panic("config_make_softc: duplicate %s", dev->dv_xname); dev->dv_ref = 1; return (dev); } /* * Detach a device. Optionally forced (e.g. because of hardware * removal) and quiet. Returns zero if successful, non-zero * (an error code) otherwise. * * Note that this code wants to be run from a process context, so * that the detach can sleep to allow processes which have a device * open to run and unwind their stacks. */ int config_detach(struct device *dev, int flags) { struct cfdata *cf; const struct cfattach *ca; struct cfdriver *cd; int rv = 0, i; #ifdef DIAGNOSTIC struct device *d; #endif #if NHOTPLUG > 0 char devname[16]; #endif mtx_enter(&autoconf_attdet_mtx); while (autoconf_attdet > 0) msleep_nsec(&autoconf_attdet, &autoconf_attdet_mtx, PWAIT, "autoconf", INFSLP); autoconf_attdet--; mtx_leave(&autoconf_attdet_mtx); #if NHOTPLUG > 0 strlcpy(devname, dev->dv_xname, sizeof(devname)); #endif cf = dev->dv_cfdata; #ifdef DIAGNOSTIC if (cf->cf_fstate != FSTATE_FOUND && cf->cf_fstate != FSTATE_STAR) panic("config_detach: bad device fstate"); #endif ca = cf->cf_attach; cd = cf->cf_driver; /* * Ensure the device is deactivated. If the device has an * activation entry point and DVF_ACTIVE is still set, the * device is busy, and the detach fails. */ rv = config_deactivate(dev); /* * Try to detach the device. If that's not possible, then * we either panic() (for the forced but failed case), or * return an error. */ if (rv == 0) { if (ca->ca_detach != NULL) rv = (*ca->ca_detach)(dev, flags); else rv = EOPNOTSUPP; } if (rv != 0) { if ((flags & DETACH_FORCE) == 0) goto done; else panic("config_detach: forced detach of %s failed (%d)", dev->dv_xname, rv); } /* * The device has now been successfully detached. */ #ifdef DIAGNOSTIC /* * Sanity: If you're successfully detached, you should have no * children. (Note that because children must be attached * after parents, we only need to search the latter part of * the list.) */ i = 0; for (d = TAILQ_NEXT(dev, dv_list); d != NULL; d = TAILQ_NEXT(d, dv_list)) { if (d->dv_parent == dev) { printf("config_detach: %s attached at %s\n", d->dv_xname, dev->dv_xname); i = 1; } } if (i != 0) panic("config_detach: detached device (%s) has children", dev->dv_xname); #endif /* * Mark cfdata to show that the unit can be reused, if possible. * Note that we can only re-use a starred unit number if the unit * being detached had the last assigned unit number. */ for (cf = cfdata; cf->cf_driver; cf++) { if (cf->cf_driver == cd) { if (cf->cf_fstate == FSTATE_FOUND && cf->cf_unit == dev->dv_unit) cf->cf_fstate = FSTATE_NOTFOUND; if (cf->cf_fstate == FSTATE_STAR && cf->cf_unit == dev->dv_unit + 1) cf->cf_unit--; } } /* * Unlink from device list. */ TAILQ_REMOVE(&alldevs, dev, dv_list); device_unref(dev); /* * Remove from cfdriver's array, tell the world, and free softc. */ cd->cd_devs[dev->dv_unit] = NULL; if ((flags & DETACH_QUIET) == 0) printf("%s detached\n", dev->dv_xname); device_unref(dev); /* * If the device now has no units in use, deallocate its softc array. */ for (i = 0; i < cd->cd_ndevs; i++) if (cd->cd_devs[i] != NULL) break; if (i == cd->cd_ndevs) { /* nothing found; deallocate */ free(cd->cd_devs, M_DEVBUF, cd->cd_ndevs * sizeof(void *)); cd->cd_devs = NULL; cd->cd_ndevs = 0; cf->cf_unit = 0; } #if NHOTPLUG > 0 if (!cold) hotplug_device_detach(cd->cd_class, devname); #endif /* * Return success. */ done: mtx_enter(&autoconf_attdet_mtx); if (++autoconf_attdet == 0) wakeup(&autoconf_attdet); autoconf_serial++; mtx_leave(&autoconf_attdet_mtx); return (rv); } int config_deactivate(struct device *dev) { int rv = 0, oflags = dev->dv_flags; if (dev->dv_flags & DVF_ACTIVE) { dev->dv_flags &= ~DVF_ACTIVE; rv = config_suspend(dev, DVACT_DEACTIVATE); if (rv) dev->dv_flags = oflags; } return (rv); } /* * Defer the configuration of the specified device until all * of its parent's devices have been attached. */ void config_defer(struct device *dev, void (*func)(struct device *)) { struct deferred_config *dc; if (dev->dv_parent == NULL) panic("config_defer: can't defer config of a root device"); #ifdef DIAGNOSTIC for (dc = TAILQ_FIRST(&deferred_config_queue); dc != NULL; dc = TAILQ_NEXT(dc, dc_queue)) { if (dc->dc_dev == dev) panic("config_defer: deferred twice"); } #endif if ((dc = malloc(sizeof(*dc), M_DEVBUF, M_NOWAIT)) == NULL) panic("config_defer: can't allocate defer structure"); dc->dc_dev = dev; dc->dc_func = func; TAILQ_INSERT_TAIL(&deferred_config_queue, dc, dc_queue); config_pending_incr(); } /* * Defer the configuration of the specified device until after * root file system is mounted. */ void config_mountroot(struct device *dev, void (*func)(struct device *)) { struct deferred_config *dc; /* * No need to defer if root file system is already mounted. */ if (rootvp != NULL) { (*func)(dev); return; } #ifdef DIAGNOSTIC for (dc = TAILQ_FIRST(&mountroot_config_queue); dc != NULL; dc = TAILQ_NEXT(dc, dc_queue)) { if (dc->dc_dev == dev) panic("config_mountroot: deferred twice"); } #endif if ((dc = malloc(sizeof(*dc), M_DEVBUF, M_NOWAIT)) == NULL) panic("config_mountroot: can't allocate defer structure"); dc->dc_dev = dev; dc->dc_func = func; TAILQ_INSERT_TAIL(&mountroot_config_queue, dc, dc_queue); } /* * Process the deferred configuration queue for a device. */ void config_process_deferred_children(struct device *parent) { struct deferred_config *dc, *ndc; for (dc = TAILQ_FIRST(&deferred_config_queue); dc != NULL; dc = ndc) { ndc = TAILQ_NEXT(dc, dc_queue); if (dc->dc_dev->dv_parent == parent) { TAILQ_REMOVE(&deferred_config_queue, dc, dc_queue); (*dc->dc_func)(dc->dc_dev); free(dc, M_DEVBUF, sizeof(*dc)); config_pending_decr(); } } } /* * Process the deferred configuration queue after the root file * system is mounted . */ void config_process_deferred_mountroot(void) { struct deferred_config *dc; while ((dc = TAILQ_FIRST(&mountroot_config_queue)) != NULL) { TAILQ_REMOVE(&mountroot_config_queue, dc, dc_queue); (*dc->dc_func)(dc->dc_dev); free(dc, M_DEVBUF, sizeof(*dc)); } } /* * Manipulate the config_pending semaphore. */ void config_pending_incr(void) { config_pending++; } void config_pending_decr(void) { #ifdef DIAGNOSTIC if (config_pending == 0) panic("config_pending_decr: config_pending == 0"); #endif config_pending--; if (config_pending == 0) wakeup((void *)&config_pending); } int config_detach_children(struct device *parent, int flags) { struct device *dev, *next_dev; int rv = 0; /* * The config_detach routine may sleep, meaning devices * may be added to the queue. However, all devices will * be added to the tail of the queue, the queue won't * be re-organized, and the subtree of parent here should be locked * for purposes of adding/removing children. * * Note that we can not afford trying to walk the device list * once - our ``next'' device might be a child of the device * we are about to detach, so it would disappear. * Just play it safe and restart from the parent. */ for (dev = TAILQ_LAST(&alldevs, devicelist); dev != NULL; dev = next_dev) { if (dev->dv_parent == parent) { if ((rv = config_detach(dev, flags)) != 0) return (rv); next_dev = TAILQ_LAST(&alldevs, devicelist); } else { next_dev = TAILQ_PREV(dev, devicelist, dv_list); } } return (0); } int config_suspend(struct device *dev, int act) { const struct cfattach *ca = dev->dv_cfdata->cf_attach; int r; device_ref(dev); if (ca->ca_activate) r = (*ca->ca_activate)(dev, act); else r = config_activate_children(dev, act); device_unref(dev); return (r); } int config_suspend_all(int act) { struct device *mainbus = device_mainbus(); struct device *mpath = device_mpath(); int rv = 0; switch (act) { case DVACT_QUIESCE: case DVACT_SUSPEND: case DVACT_POWERDOWN: if (mpath) { rv = config_suspend(mpath, act); if (rv) return rv; } if (mainbus) rv = config_suspend(mainbus, act); break; case DVACT_RESUME: case DVACT_WAKEUP: if (mainbus) { rv = config_suspend(mainbus, act); if (rv) return rv; } if (mpath) rv = config_suspend(mpath, act); break; } return (rv); } /* * Call the ca_activate for each of our children, letting each * decide whether they wish to do the same for their children * and more. */ int config_activate_children(struct device *parent, int act) { struct device *d; int rv = 0; for (d = TAILQ_NEXT(parent, dv_list); d != NULL; d = TAILQ_NEXT(d, dv_list)) { if (d->dv_parent != parent) continue; switch (act) { case DVACT_QUIESCE: case DVACT_SUSPEND: case DVACT_RESUME: case DVACT_WAKEUP: case DVACT_POWERDOWN: rv = config_suspend(d, act); break; case DVACT_DEACTIVATE: rv = config_deactivate(d); break; } if (rv == 0) continue; /* * Found a device that refuses the action. * If we were being asked to suspend, we can * try to resume all previous devices. */ #ifdef DIAGNOSTIC printf("config_activate_children: device %s failed %d\n", d->dv_xname, act); #endif if (act == DVACT_RESUME) printf("failing resume cannot be handled\n"); if (act == DVACT_POWERDOWN) return (rv); if (act != DVACT_SUSPEND) return (rv); d = TAILQ_PREV(d, devicelist, dv_list); for (; d != NULL && d != parent; d = TAILQ_PREV(d, devicelist, dv_list)) { if (d->dv_parent != parent) continue; printf("resume %s\n", d->dv_xname); config_suspend(d, DVACT_RESUME); } return (rv); } return (rv); } /* * Lookup a device in the cfdriver device array. Does not return a * device if it is not active. * * Increments ref count on the device by one, reflecting the * new reference created on the stack. * * Context: process only */ struct device * device_lookup(struct cfdriver *cd, int unit) { struct device *dv = NULL; if (unit >= 0 && unit < cd->cd_ndevs) dv = (struct device *)(cd->cd_devs[unit]); if (!dv) return (NULL); if (!(dv->dv_flags & DVF_ACTIVE)) dv = NULL; if (dv != NULL) device_ref(dv); return (dv); } struct device * device_mainbus(void) { extern struct cfdriver mainbus_cd; if (mainbus_cd.cd_ndevs < 1) return (NULL); return (mainbus_cd.cd_devs[0]); } struct device * device_mpath(void) { #if NMPATH > 0 extern struct cfdriver mpath_cd; if (mpath_cd.cd_ndevs < 1) return (NULL); return (mpath_cd.cd_devs[0]); #else return (NULL); #endif } /* * Increments the ref count on the device structure. The device * structure is freed when the ref count hits 0. * * Context: process or interrupt */ void device_ref(struct device *dv) { atomic_inc_int(&dv->dv_ref); } /* * Decrement the ref count on the device structure. * * free's the structure when the ref count hits zero. * * Context: process or interrupt */ void device_unref(struct device *dv) { const struct cfattach *ca; if (atomic_dec_int_nv(&dv->dv_ref) == 0) { ca = dv->dv_cfdata->cf_attach; free(dv, M_DEVBUF, ca->ca_devsize); } }
9 9 9 9 9 9 9 75 71 9 76 71 9 10 4 1 7 10 2 2 4 2 6 5 6 3 10 10 10 10 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 /* $OpenBSD: uvm_pager.c,v 1.91 2023/08/11 17:53:22 mpi Exp $ */ /* $NetBSD: uvm_pager.c,v 1.36 2000/11/27 18:26:41 chs Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * from: Id: uvm_pager.c,v 1.1.2.23 1998/02/02 20:38:06 chuck Exp */ /* * uvm_pager.c: generic functions used to assist the pagers. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/pool.h> #include <sys/buf.h> #include <sys/atomic.h> #include <uvm/uvm.h> const struct uvm_pagerops *uvmpagerops[] = { &aobj_pager, &uvm_deviceops, &uvm_vnodeops, }; /* * the pager map: provides KVA for I/O * * Each uvm_pseg has room for MAX_PAGERMAP_SEGS pager io space of * MAXBSIZE bytes. * * The number of uvm_pseg instances is dynamic using an array segs. * At most UVM_PSEG_COUNT instances can exist. * * psegs[0/1] always exist (so that the pager can always map in pages). * psegs[0/1] element 0 are always reserved for the pagedaemon. * * Any other pseg is automatically created when no space is available * and automatically destroyed when it is no longer in use. */ #define MAX_PAGER_SEGS 16 #define PSEG_NUMSEGS (PAGER_MAP_SIZE / MAX_PAGER_SEGS / MAXBSIZE) struct uvm_pseg { /* Start of virtual space; 0 if not inited. */ vaddr_t start; /* Bitmap of the segments in use in this pseg. */ int use; }; struct mutex uvm_pseg_lck; struct uvm_pseg psegs[PSEG_NUMSEGS]; #define UVM_PSEG_FULL(pseg) ((pseg)->use == (1 << MAX_PAGER_SEGS) - 1) #define UVM_PSEG_EMPTY(pseg) ((pseg)->use == 0) #define UVM_PSEG_INUSE(pseg,id) (((pseg)->use & (1 << (id))) != 0) void uvm_pseg_init(struct uvm_pseg *); vaddr_t uvm_pseg_get(int); void uvm_pseg_release(vaddr_t); /* * uvm_pager_init: init pagers (at boot time) */ void uvm_pager_init(void) { int lcv; /* init pager map */ uvm_pseg_init(&psegs[0]); uvm_pseg_init(&psegs[1]); mtx_init(&uvm_pseg_lck, IPL_VM); /* init ASYNC I/O queue */ TAILQ_INIT(&uvm.aio_done); /* call pager init functions */ for (lcv = 0 ; lcv < sizeof(uvmpagerops)/sizeof(struct uvm_pagerops *); lcv++) { if (uvmpagerops[lcv]->pgo_init) uvmpagerops[lcv]->pgo_init(); } } /* * Initialize a uvm_pseg. * * May fail, in which case seg->start == 0. * * Caller locks uvm_pseg_lck. */ void uvm_pseg_init(struct uvm_pseg *pseg) { KASSERT(pseg->start == 0); KASSERT(pseg->use == 0); pseg->start = (vaddr_t)km_alloc(MAX_PAGER_SEGS * MAXBSIZE, &kv_any, &kp_none, &kd_trylock); } /* * Acquire a pager map segment. * * Returns a vaddr for paging. 0 on failure. * * Caller does not lock. */ vaddr_t uvm_pseg_get(int flags) { int i; struct uvm_pseg *pseg; /* * XXX Prevent lock ordering issue in uvm_unmap_detach(). A real * fix would be to move the KERNEL_LOCK() out of uvm_unmap_detach(). * * witness_checkorder() at witness_checkorder+0xba0 * __mp_lock() at __mp_lock+0x5f * uvm_unmap_detach() at uvm_unmap_detach+0xc5 * uvm_map() at uvm_map+0x857 * uvm_km_valloc_try() at uvm_km_valloc_try+0x65 * uvm_pseg_get() at uvm_pseg_get+0x6f * uvm_pagermapin() at uvm_pagermapin+0x45 * uvn_io() at uvn_io+0xcf * uvn_get() at uvn_get+0x156 * uvm_fault_lower() at uvm_fault_lower+0x28a * uvm_fault() at uvm_fault+0x1b3 * upageflttrap() at upageflttrap+0x62 */ KERNEL_LOCK(); mtx_enter(&uvm_pseg_lck); pager_seg_restart: /* Find first pseg that has room. */ for (pseg = &psegs[0]; pseg != &psegs[PSEG_NUMSEGS]; pseg++) { if (UVM_PSEG_FULL(pseg)) continue; if (pseg->start == 0) { /* Need initialization. */ uvm_pseg_init(pseg); if (pseg->start == 0) goto pager_seg_fail; } /* Keep indexes 0,1 reserved for pagedaemon. */ if ((pseg == &psegs[0] || pseg == &psegs[1]) && (curproc != uvm.pagedaemon_proc)) i = 2; else i = 0; for (; i < MAX_PAGER_SEGS; i++) { if (!UVM_PSEG_INUSE(pseg, i)) { pseg->use |= 1 << i; mtx_leave(&uvm_pseg_lck); KERNEL_UNLOCK(); return pseg->start + i * MAXBSIZE; } } } pager_seg_fail: if ((flags & UVMPAGER_MAPIN_WAITOK) != 0) { msleep_nsec(&psegs, &uvm_pseg_lck, PVM, "pagerseg", INFSLP); goto pager_seg_restart; } mtx_leave(&uvm_pseg_lck); KERNEL_UNLOCK(); return 0; } /* * Release a pager map segment. * * Caller does not lock. * * Deallocates pseg if it is no longer in use. */ void uvm_pseg_release(vaddr_t segaddr) { int id; struct uvm_pseg *pseg; vaddr_t va = 0; mtx_enter(&uvm_pseg_lck); for (pseg = &psegs[0]; pseg != &psegs[PSEG_NUMSEGS]; pseg++) { if (pseg->start <= segaddr && segaddr < pseg->start + MAX_PAGER_SEGS * MAXBSIZE) break; } KASSERT(pseg != &psegs[PSEG_NUMSEGS]); id = (segaddr - pseg->start) / MAXBSIZE; KASSERT(id >= 0 && id < MAX_PAGER_SEGS); /* test for no remainder */ KDASSERT(segaddr == pseg->start + id * MAXBSIZE); KASSERT(UVM_PSEG_INUSE(pseg, id)); pseg->use &= ~(1 << id); wakeup(&psegs); if ((pseg != &psegs[0] && pseg != &psegs[1]) && UVM_PSEG_EMPTY(pseg)) { va = pseg->start; pseg->start = 0; } mtx_leave(&uvm_pseg_lck); if (va) { km_free((void *)va, MAX_PAGER_SEGS * MAXBSIZE, &kv_any, &kp_none); } } /* * uvm_pagermapin: map pages into KVA for I/O that needs mappings * * We basically just km_valloc a blank map entry to reserve the space in the * kernel map and then use pmap_enter() to put the mappings in by hand. */ vaddr_t uvm_pagermapin(struct vm_page **pps, int npages, int flags) { vaddr_t kva, cva; vm_prot_t prot; vsize_t size; struct vm_page *pp; #if defined(__HAVE_PMAP_DIRECT) /* * Use direct mappings for single page, unless there is a risk * of aliasing. */ if (npages == 1 && PMAP_PREFER_ALIGN() == 0) { KASSERT(pps[0]); KASSERT(pps[0]->pg_flags & PG_BUSY); return pmap_map_direct(pps[0]); } #endif prot = PROT_READ; if (flags & UVMPAGER_MAPIN_READ) prot |= PROT_WRITE; size = ptoa(npages); KASSERT(size <= MAXBSIZE); kva = uvm_pseg_get(flags); if (kva == 0) return 0; for (cva = kva ; size != 0 ; size -= PAGE_SIZE, cva += PAGE_SIZE) { pp = *pps++; KASSERT(pp); KASSERT(pp->pg_flags & PG_BUSY); /* Allow pmap_enter to fail. */ if (pmap_enter(pmap_kernel(), cva, VM_PAGE_TO_PHYS(pp), prot, PMAP_WIRED | PMAP_CANFAIL | prot) != 0) { pmap_remove(pmap_kernel(), kva, cva); pmap_update(pmap_kernel()); uvm_pseg_release(kva); return 0; } } pmap_update(pmap_kernel()); return kva; } /* * uvm_pagermapout: remove KVA mapping * * We remove our mappings by hand and then remove the mapping. */ void uvm_pagermapout(vaddr_t kva, int npages) { #if defined(__HAVE_PMAP_DIRECT) /* * Use direct mappings for single page, unless there is a risk * of aliasing. */ if (npages == 1 && PMAP_PREFER_ALIGN() == 0) { pmap_unmap_direct(kva); return; } #endif pmap_remove(pmap_kernel(), kva, kva + ((vsize_t)npages << PAGE_SHIFT)); pmap_update(pmap_kernel()); uvm_pseg_release(kva); } /* * uvm_mk_pcluster * * generic "make 'pager put' cluster" function. a pager can either * [1] set pgo_mk_pcluster to NULL (never cluster), [2] set it to this * generic function, or [3] set it to a pager specific function. * * => caller must lock object _and_ pagequeues (since we need to look * at active vs. inactive bits, etc.) * => caller must make center page busy and write-protect it * => we mark all cluster pages busy for the caller * => the caller must unbusy all pages (and check wanted/released * status if it drops the object lock) * => flags: * PGO_ALLPAGES: all pages in object are valid targets * !PGO_ALLPAGES: use "lo" and "hi" to limit range of cluster * PGO_DOACTCLUST: include active pages in cluster. * PGO_FREE: set the PG_RELEASED bits on the cluster so they'll be freed * in async io (caller must clean on error). * NOTE: the caller should clear PG_CLEANCHK bits if PGO_DOACTCLUST. * PG_CLEANCHK is only a hint, but clearing will help reduce * the number of calls we make to the pmap layer. */ struct vm_page ** uvm_mk_pcluster(struct uvm_object *uobj, struct vm_page **pps, int *npages, struct vm_page *center, int flags, voff_t mlo, voff_t mhi) { struct vm_page **ppsp, *pclust; voff_t lo, hi, curoff; int center_idx, forward, incr; /* * center page should already be busy and write protected. XXX: * suppose page is wired? if we lock, then a process could * fault/block on it. if we don't lock, a process could write the * pages in the middle of an I/O. (consider an msync()). let's * lock it for now (better to delay than corrupt data?). */ /* get cluster boundaries, check sanity, and apply our limits as well.*/ uobj->pgops->pgo_cluster(uobj, center->offset, &lo, &hi); if ((flags & PGO_ALLPAGES) == 0) { if (lo < mlo) lo = mlo; if (hi > mhi) hi = mhi; } if ((hi - lo) >> PAGE_SHIFT > *npages) { /* pps too small, bail out! */ pps[0] = center; *npages = 1; return pps; } /* now determine the center and attempt to cluster around the edges */ center_idx = (center->offset - lo) >> PAGE_SHIFT; pps[center_idx] = center; /* plug in the center page */ ppsp = &pps[center_idx]; *npages = 1; /* * attempt to cluster around the left [backward], and then * the right side [forward]. * * note that for inactive pages (pages that have been deactivated) * there are no valid mappings and PG_CLEAN should be up to date. * [i.e. there is no need to query the pmap with pmap_is_modified * since there are no mappings]. */ for (forward = 0 ; forward <= 1 ; forward++) { incr = forward ? PAGE_SIZE : -PAGE_SIZE; curoff = center->offset + incr; for ( ;(forward == 0 && curoff >= lo) || (forward && curoff < hi); curoff += incr) { pclust = uvm_pagelookup(uobj, curoff); /* lookup page */ if (pclust == NULL) { break; /* no page */ } /* handle active pages */ /* NOTE: inactive pages don't have pmap mappings */ if ((pclust->pg_flags & PQ_INACTIVE) == 0) { if ((flags & PGO_DOACTCLUST) == 0) { /* dont want mapped pages at all */ break; } /* make sure "clean" bit is sync'd */ if ((pclust->pg_flags & PG_CLEANCHK) == 0) { if ((pclust->pg_flags & (PG_CLEAN|PG_BUSY)) == PG_CLEAN && pmap_is_modified(pclust)) atomic_clearbits_int( &pclust->pg_flags, PG_CLEAN); /* now checked */ atomic_setbits_int(&pclust->pg_flags, PG_CLEANCHK); } } /* is page available for cleaning and does it need it */ if ((pclust->pg_flags & (PG_CLEAN|PG_BUSY)) != 0) { break; /* page is already clean or is busy */ } /* yes! enroll the page in our array */ atomic_setbits_int(&pclust->pg_flags, PG_BUSY); UVM_PAGE_OWN(pclust, "uvm_mk_pcluster"); /* * If we want to free after io is done, and we're * async, set the released flag */ if ((flags & (PGO_FREE|PGO_SYNCIO)) == PGO_FREE) atomic_setbits_int(&pclust->pg_flags, PG_RELEASED); /* XXX: protect wired page? see above comment. */ pmap_page_protect(pclust, PROT_READ); if (!forward) { ppsp--; /* back up one page */ *ppsp = pclust; } else { /* move forward one page */ ppsp[*npages] = pclust; } (*npages)++; } } /* * done! return the cluster array to the caller!!! */ return ppsp; } /* * uvm_pager_put: high level pageout routine * * we want to pageout page "pg" to backing store, clustering if * possible. * * => page queues must be locked by caller * => if page is not swap-backed, then "uobj" points to the object * backing it. * => if page is swap-backed, then "uobj" should be NULL. * => "pg" should be PG_BUSY (by caller), and !PG_CLEAN * for swap-backed memory, "pg" can be NULL if there is no page * of interest [sometimes the case for the pagedaemon] * => "ppsp_ptr" should point to an array of npages vm_page pointers * for possible cluster building * => flags (first two for non-swap-backed pages) * PGO_ALLPAGES: all pages in uobj are valid targets * PGO_DOACTCLUST: include "PQ_ACTIVE" pages as valid targets * PGO_SYNCIO: do SYNC I/O (no async) * PGO_PDFREECLUST: pagedaemon: drop cluster on successful I/O * PGO_FREE: tell the aio daemon to free pages in the async case. * => start/stop: if (uobj && !PGO_ALLPAGES) limit targets to this range * if (!uobj) start is the (daddr_t) of the starting swapblk * => return state: * 1. we return the VM_PAGER status code of the pageout * 2. we return with the page queues unlocked * 3. on errors we always drop the cluster. thus, if we return * !PEND, !OK, then the caller only has to worry about * un-busying the main page (not the cluster pages). * 4. on success, if !PGO_PDFREECLUST, we return the cluster * with all pages busy (caller must un-busy and check * wanted/released flags). */ int uvm_pager_put(struct uvm_object *uobj, struct vm_page *pg, struct vm_page ***ppsp_ptr, int *npages, int flags, voff_t start, voff_t stop) { int result; daddr_t swblk; struct vm_page **ppsp = *ppsp_ptr; /* * note that uobj is null if we are doing a swap-backed pageout. * note that uobj is !null if we are doing normal object pageout. * note that the page queues must be locked to cluster. */ if (uobj) { /* if !swap-backed */ /* * attempt to build a cluster for pageout using its * make-put-cluster function (if it has one). */ if (uobj->pgops->pgo_mk_pcluster) { ppsp = uobj->pgops->pgo_mk_pcluster(uobj, ppsp, npages, pg, flags, start, stop); *ppsp_ptr = ppsp; /* update caller's pointer */ } else { ppsp[0] = pg; *npages = 1; } swblk = 0; /* XXX: keep gcc happy */ } else { /* * for swap-backed pageout, the caller (the pagedaemon) has * already built the cluster for us. the starting swap * block we are writing to has been passed in as "start." * "pg" could be NULL if there is no page we are especially * interested in (in which case the whole cluster gets dropped * in the event of an error or a sync "done"). */ swblk = start; /* ppsp and npages should be ok */ } /* now that we've clustered we can unlock the page queues */ uvm_unlock_pageq(); /* * now attempt the I/O. if we have a failure and we are * clustered, we will drop the cluster and try again. */ ReTry: if (uobj) { result = uobj->pgops->pgo_put(uobj, ppsp, *npages, flags); } else { /* XXX daddr_t -> int */ result = uvm_swap_put(swblk, ppsp, *npages, flags); } /* * we have attempted the I/O. * * if the I/O was a success then: * if !PGO_PDFREECLUST, we return the cluster to the * caller (who must un-busy all pages) * else we un-busy cluster pages for the pagedaemon * * if I/O is pending (async i/o) then we return the pending code. * [in this case the async i/o done function must clean up when * i/o is done...] */ if (result == VM_PAGER_PEND || result == VM_PAGER_OK) { if (result == VM_PAGER_OK && (flags & PGO_PDFREECLUST)) { /* drop cluster */ if (*npages > 1 || pg == NULL) uvm_pager_dropcluster(uobj, pg, ppsp, npages, PGO_PDFREECLUST); } return (result); } /* * a pager error occurred (even after dropping the cluster, if there * was one). give up! the caller only has one page ("pg") * to worry about. */ if (*npages > 1 || pg == NULL) { uvm_pager_dropcluster(uobj, pg, ppsp, npages, PGO_REALLOCSWAP); /* * for failed swap-backed pageouts with a "pg", * we need to reset pg's swslot to either: * "swblk" (for transient errors, so we can retry), * or 0 (for hard errors). */ if (uobj == NULL && pg != NULL) { /* XXX daddr_t -> int */ int nswblk = (result == VM_PAGER_AGAIN) ? swblk : 0; if (pg->pg_flags & PQ_ANON) { rw_enter(pg->uanon->an_lock, RW_WRITE); pg->uanon->an_swslot = nswblk; rw_exit(pg->uanon->an_lock); } else { rw_enter(pg->uobject->vmobjlock, RW_WRITE); uao_set_swslot(pg->uobject, pg->offset >> PAGE_SHIFT, nswblk); rw_exit(pg->uobject->vmobjlock); } } if (result == VM_PAGER_AGAIN) { /* * for transient failures, free all the swslots that * we're not going to retry with. */ if (uobj == NULL) { if (pg) { /* XXX daddr_t -> int */ uvm_swap_free(swblk + 1, *npages - 1); } else { /* XXX daddr_t -> int */ uvm_swap_free(swblk, *npages); } } if (pg) { ppsp[0] = pg; *npages = 1; goto ReTry; } } else if (uobj == NULL) { /* * for hard errors on swap-backed pageouts, * mark the swslots as bad. note that we do not * free swslots that we mark bad. */ /* XXX daddr_t -> int */ uvm_swap_markbad(swblk, *npages); } } /* * a pager error occurred (even after dropping the cluster, if there * was one). give up! the caller only has one page ("pg") * to worry about. */ return result; } /* * uvm_pager_dropcluster: drop a cluster we have built (because we * got an error, or, if PGO_PDFREECLUST we are un-busying the * cluster pages on behalf of the pagedaemon). * * => uobj, if non-null, is a non-swap-backed object * => page queues are not locked * => pg is our page of interest (the one we clustered around, can be null) * => ppsp/npages is our current cluster * => flags: PGO_PDFREECLUST: pageout was a success: un-busy cluster * pages on behalf of the pagedaemon. * PGO_REALLOCSWAP: drop previously allocated swap slots for * clustered swap-backed pages (except for "pg" if !NULL) * "swblk" is the start of swap alloc (e.g. for ppsp[0]) * [only meaningful if swap-backed (uobj == NULL)] */ void uvm_pager_dropcluster(struct uvm_object *uobj, struct vm_page *pg, struct vm_page **ppsp, int *npages, int flags) { int lcv; KASSERT(uobj == NULL || rw_write_held(uobj->vmobjlock)); /* drop all pages but "pg" */ for (lcv = 0 ; lcv < *npages ; lcv++) { /* skip "pg" or empty slot */ if (ppsp[lcv] == pg || ppsp[lcv] == NULL) continue; /* * Note that PQ_ANON bit can't change as long as we are holding * the PG_BUSY bit (so there is no need to lock the page * queues to test it). */ if (!uobj) { if (ppsp[lcv]->pg_flags & PQ_ANON) { rw_enter(ppsp[lcv]->uanon->an_lock, RW_WRITE); if (flags & PGO_REALLOCSWAP) /* zap swap block */ ppsp[lcv]->uanon->an_swslot = 0; } else { rw_enter(ppsp[lcv]->uobject->vmobjlock, RW_WRITE); if (flags & PGO_REALLOCSWAP) uao_set_swslot(ppsp[lcv]->uobject, ppsp[lcv]->offset >> PAGE_SHIFT, 0); } } /* did someone want the page while we had it busy-locked? */ if (ppsp[lcv]->pg_flags & PG_WANTED) { wakeup(ppsp[lcv]); } /* if page was released, release it. otherwise un-busy it */ if (ppsp[lcv]->pg_flags & PG_RELEASED && ppsp[lcv]->pg_flags & PQ_ANON) { /* kills anon and frees pg */ uvm_anon_release(ppsp[lcv]->uanon); continue; } else { /* * if we were planning on async io then we would * have PG_RELEASED set, clear that with the others. */ atomic_clearbits_int(&ppsp[lcv]->pg_flags, PG_BUSY|PG_WANTED|PG_FAKE|PG_RELEASED); UVM_PAGE_OWN(ppsp[lcv], NULL); } /* * if we are operating on behalf of the pagedaemon and we * had a successful pageout update the page! */ if (flags & PGO_PDFREECLUST) { pmap_clear_reference(ppsp[lcv]); pmap_clear_modify(ppsp[lcv]); atomic_setbits_int(&ppsp[lcv]->pg_flags, PG_CLEAN); } /* if anonymous cluster, unlock object and move on */ if (!uobj) { if (ppsp[lcv]->pg_flags & PQ_ANON) rw_exit(ppsp[lcv]->uanon->an_lock); else rw_exit(ppsp[lcv]->uobject->vmobjlock); } } } /* * interrupt-context iodone handler for single-buf i/os * or the top-level buf of a nested-buf i/o. * * => must be at splbio(). */ void uvm_aio_biodone(struct buf *bp) { splassert(IPL_BIO); /* reset b_iodone for when this is a single-buf i/o. */ bp->b_iodone = uvm_aio_aiodone; mtx_enter(&uvm.aiodoned_lock); TAILQ_INSERT_TAIL(&uvm.aio_done, bp, b_freelist); wakeup(&uvm.aiodoned); mtx_leave(&uvm.aiodoned_lock); } void uvm_aio_aiodone_pages(struct vm_page **pgs, int npages, boolean_t write, int error) { struct vm_page *pg; struct rwlock *slock; boolean_t swap; int i, swslot; slock = NULL; pg = pgs[0]; swap = (pg->uanon != NULL && pg->uobject == NULL) || (pg->pg_flags & PQ_AOBJ) != 0; KASSERT(swap); KASSERT(write); if (error) { if (pg->uobject != NULL) { swslot = uao_find_swslot(pg->uobject, pg->offset >> PAGE_SHIFT); } else { swslot = pg->uanon->an_swslot; } KASSERT(swslot); } for (i = 0; i < npages; i++) { int anon_disposed = 0; pg = pgs[i]; KASSERT((pg->pg_flags & PG_FAKE) == 0); /* * lock each page's object (or anon) individually since * each page may need a different lock. */ if (pg->uobject != NULL) { slock = pg->uobject->vmobjlock; } else { slock = pg->uanon->an_lock; } rw_enter(slock, RW_WRITE); anon_disposed = (pg->pg_flags & PG_RELEASED) != 0; KASSERT(!anon_disposed || pg->uobject != NULL || pg->uanon->an_ref == 0); uvm_lock_pageq(); /* * if this was a successful write, * mark the page PG_CLEAN. */ if (!error) { pmap_clear_reference(pg); pmap_clear_modify(pg); atomic_setbits_int(&pg->pg_flags, PG_CLEAN); } /* * unlock everything for this page now. */ if (pg->uobject == NULL && anon_disposed) { uvm_unlock_pageq(); uvm_anon_release(pg->uanon); } else { uvm_page_unbusy(&pg, 1); uvm_unlock_pageq(); rw_exit(slock); } } if (error) { uvm_swap_markbad(swslot, npages); } } /* * uvm_aio_aiodone: do iodone processing for async i/os. * this should be called in thread context, not interrupt context. */ void uvm_aio_aiodone(struct buf *bp) { int npages = bp->b_bufsize >> PAGE_SHIFT; struct vm_page *pgs[MAXPHYS >> PAGE_SHIFT]; int i, error; boolean_t write; KASSERT(npages <= MAXPHYS >> PAGE_SHIFT); splassert(IPL_BIO); error = (bp->b_flags & B_ERROR) ? (bp->b_error ? bp->b_error : EIO) : 0; write = (bp->b_flags & B_READ) == 0; for (i = 0; i < npages; i++) pgs[i] = uvm_atopg((vaddr_t)bp->b_data + ((vsize_t)i << PAGE_SHIFT)); uvm_pagermapout((vaddr_t)bp->b_data, npages); #ifdef UVM_SWAP_ENCRYPT /* * XXX - assumes that we only get ASYNC writes. used to be above. */ if (pgs[0]->pg_flags & PQ_ENCRYPT) { uvm_swap_freepages(pgs, npages); goto freed; } #endif /* UVM_SWAP_ENCRYPT */ uvm_aio_aiodone_pages(pgs, npages, write, error); #ifdef UVM_SWAP_ENCRYPT freed: #endif pool_put(&bufpool, bp); }
17 17 17 17 10 3 7 10 7 17 17 10 10 18 15 9 9 2 6 7 7 19 19 7 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 /* $OpenBSD: nd6_nbr.c,v 1.151 2023/07/30 12:52:03 krw Exp $ */ /* $KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/sockio.h> #include <sys/time.h> #include <sys/kernel.h> #include <sys/ioctl.h> #include <sys/syslog.h> #include <sys/queue.h> #include <sys/timeout.h> #include <net/if.h> #include <net/if_var.h> #include <net/if_types.h> #include <net/if_dl.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/if_ether.h> #include <netinet6/in6_var.h> #include <netinet/ip6.h> #include <netinet6/ip6_var.h> #include <netinet6/nd6.h> #include <netinet/icmp6.h> #include "carp.h" #if NCARP > 0 #include <netinet/ip_carp.h> #endif static TAILQ_HEAD(, dadq) dadq = TAILQ_HEAD_INITIALIZER(dadq); /* list of addresses to run DAD on */ struct dadq { TAILQ_ENTRY(dadq) dad_list; struct ifaddr *dad_ifa; int dad_count; /* max NS to send */ int dad_ns_tcount; /* # of trials to send NS */ int dad_ns_ocount; /* NS sent so far */ int dad_ns_icount; int dad_na_icount; struct timeout dad_timer_ch; }; struct dadq *nd6_dad_find(struct ifaddr *); void nd6_dad_destroy(struct dadq *); void nd6_dad_starttimer(struct dadq *); void nd6_dad_stoptimer(struct dadq *); void nd6_dad_timer(void *); void nd6_dad_ns_output(struct dadq *, struct ifaddr *); void nd6_dad_ns_input(struct ifaddr *); void nd6_dad_duplicated(struct dadq *); int nd6_isneighbor(const struct ifnet *, const struct in6_addr *); static int dad_maxtry = 15; /* max # of *tries* to transmit DAD packet */ /* * Input an Neighbor Solicitation Message. * * Based on RFC 2461 * Based on RFC 2462 (duplicated address detection) */ void nd6_ns_input(struct mbuf *m, int off, int icmp6len) { struct ifnet *ifp; struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); struct nd_neighbor_solicit *nd_ns; struct in6_addr saddr6 = ip6->ip6_src; struct in6_addr daddr6 = ip6->ip6_dst; struct in6_addr taddr6; struct in6_addr myaddr6; char *lladdr = NULL; struct ifaddr *ifa = NULL; int lladdrlen = 0; int anycast = 0, proxy = 0, tentative = 0; int router = ip6_forwarding; int tlladdr; struct nd_opts ndopts; struct sockaddr_dl *proxydl = NULL; char addr[INET6_ADDRSTRLEN], addr0[INET6_ADDRSTRLEN]; ifp = if_get(m->m_pkthdr.ph_ifidx); if (ifp == NULL) goto freeit; IP6_EXTHDR_GET(nd_ns, struct nd_neighbor_solicit *, m, off, icmp6len); if (nd_ns == NULL) { icmp6stat_inc(icp6s_tooshort); if_put(ifp); return; } ip6 = mtod(m, struct ip6_hdr *); /* adjust pointer for safety */ taddr6 = nd_ns->nd_ns_target; if (ip6->ip6_hlim != 255) { nd6log((LOG_ERR, "nd6_ns_input: invalid hlim (%d) from %s to %s on %s\n", ip6->ip6_hlim, inet_ntop(AF_INET6, &ip6->ip6_src, addr, sizeof(addr)), inet_ntop(AF_INET6, &ip6->ip6_dst, addr0, sizeof(addr0)), ifp->if_xname)); goto bad; } if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) { /* dst has to be solicited node multicast address. */ /* don't check ifindex portion */ if (daddr6.s6_addr16[0] == __IPV6_ADDR_INT16_MLL && daddr6.s6_addr32[1] == 0 && daddr6.s6_addr32[2] == __IPV6_ADDR_INT32_ONE && daddr6.s6_addr8[12] == 0xff) { ; /*good*/ } else { nd6log((LOG_INFO, "nd6_ns_input: bad DAD packet " "(wrong ip6 dst)\n")); goto bad; } } else { /* * Make sure the source address is from a neighbor's address. */ if (!nd6_isneighbor(ifp, &saddr6)) { nd6log((LOG_INFO, "nd6_ns_input: " "NS packet from non-neighbor\n")); goto bad; } } if (IN6_IS_ADDR_MULTICAST(&taddr6)) { nd6log((LOG_INFO, "nd6_ns_input: bad NS target (multicast)\n")); goto bad; } if (IN6_IS_SCOPE_EMBED(&taddr6)) taddr6.s6_addr16[1] = htons(ifp->if_index); icmp6len -= sizeof(*nd_ns); if (nd6_options(nd_ns + 1, icmp6len, &ndopts) < 0) { nd6log((LOG_INFO, "nd6_ns_input: invalid ND option, ignored\n")); /* nd6_options have incremented stats */ goto freeit; } if (ndopts.nd_opts_src_lladdr) { lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1); lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3; } if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src) && lladdr) { nd6log((LOG_INFO, "nd6_ns_input: bad DAD packet " "(link-layer address option)\n")); goto bad; } /* * Attaching target link-layer address to the NA? * (RFC 2461 7.2.4) * * NS IP dst is unicast/anycast MUST NOT add * NS IP dst is solicited-node multicast MUST add * * In implementation, we add target link-layer address by default. * We do not add one in MUST NOT cases. */ #if 0 /* too much! */ ifa = &in6ifa_ifpwithaddr(ifp, &daddr6)->ia_ifa; if (ifa && (ifatoia6(ifa)->ia6_flags & IN6_IFF_ANYCAST)) tlladdr = 0; else #endif if (!IN6_IS_ADDR_MULTICAST(&daddr6)) tlladdr = 0; else tlladdr = 1; /* * Target address (taddr6) must be either: * (1) Valid unicast/anycast address for my receiving interface, * (2) Unicast address for which I'm offering proxy service, or * (3) "tentative" address on which DAD is being performed. */ /* (1) and (3) check. */ ifa = &in6ifa_ifpwithaddr(ifp, &taddr6)->ia_ifa; #if NCARP > 0 if (ifp->if_type == IFT_CARP && ifa && !carp_iamatch(ifp)) ifa = NULL; #endif /* (2) check. */ if (!ifa) { struct rtentry *rt; struct sockaddr_in6 tsin6; bzero(&tsin6, sizeof tsin6); tsin6.sin6_len = sizeof(struct sockaddr_in6); tsin6.sin6_family = AF_INET6; tsin6.sin6_addr = taddr6; rt = rtalloc(sin6tosa(&tsin6), 0, m->m_pkthdr.ph_rtableid); if (rt && (rt->rt_flags & RTF_ANNOUNCE) != 0 && rt->rt_gateway->sa_family == AF_LINK) { /* * proxy NDP for single entry */ ifa = &in6ifa_ifpforlinklocal(ifp, IN6_IFF_TENTATIVE| IN6_IFF_DUPLICATED|IN6_IFF_ANYCAST)->ia_ifa; if (ifa) { proxy = 1; proxydl = satosdl(rt->rt_gateway); router = 0; /* XXX */ } } if (rt) rtfree(rt); } if (!ifa) { /* * We've got an NS packet, and we don't have that address * assigned for us. We MUST silently ignore it. * See RFC2461 7.2.3. */ goto freeit; } myaddr6 = *IFA_IN6(ifa); anycast = ifatoia6(ifa)->ia6_flags & IN6_IFF_ANYCAST; tentative = ifatoia6(ifa)->ia6_flags & IN6_IFF_TENTATIVE; if (ifatoia6(ifa)->ia6_flags & IN6_IFF_DUPLICATED) goto freeit; if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) { nd6log((LOG_INFO, "nd6_ns_input: lladdrlen mismatch for %s " "(if %d, NS packet %d)\n", inet_ntop(AF_INET6, &taddr6, addr, sizeof(addr)), ifp->if_addrlen, lladdrlen - 2)); goto bad; } if (IN6_ARE_ADDR_EQUAL(&myaddr6, &saddr6)) { log(LOG_INFO, "nd6_ns_input: duplicate IP6 address %s\n", inet_ntop(AF_INET6, &saddr6, addr, sizeof(addr))); goto freeit; } /* * We have neighbor solicitation packet, with target address equals to * one of my tentative address. * * src addr how to process? * --- --- * multicast of course, invalid (rejected in ip6_input) * unicast somebody is doing address resolution -> ignore * unspec dup address detection * * The processing is defined in RFC 2462. */ if (tentative) { /* * If source address is unspecified address, it is for * duplicated address detection. * * If not, the packet is for address resolution; * silently ignore it. */ if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) nd6_dad_ns_input(ifa); goto freeit; } /* * If the source address is unspecified address, entries must not * be created or updated. * It looks that sender is performing DAD. Output NA toward * all-node multicast address, to tell the sender that I'm using * the address. * S bit ("solicited") must be zero. */ if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) { saddr6 = in6addr_linklocal_allnodes; saddr6.s6_addr16[1] = htons(ifp->if_index); nd6_na_output(ifp, &saddr6, &taddr6, ((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) | (router ? ND_NA_FLAG_ROUTER : 0), tlladdr, sdltosa(proxydl)); goto freeit; } nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_NEIGHBOR_SOLICIT, 0); nd6_na_output(ifp, &saddr6, &taddr6, ((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) | (router ? ND_NA_FLAG_ROUTER : 0) | ND_NA_FLAG_SOLICITED, tlladdr, sdltosa(proxydl)); freeit: m_freem(m); if_put(ifp); return; bad: nd6log((LOG_ERR, "nd6_ns_input: src=%s\n", inet_ntop(AF_INET6, &saddr6, addr, sizeof(addr)))); nd6log((LOG_ERR, "nd6_ns_input: dst=%s\n", inet_ntop(AF_INET6, &daddr6, addr, sizeof(addr)))); nd6log((LOG_ERR, "nd6_ns_input: tgt=%s\n", inet_ntop(AF_INET6, &taddr6, addr, sizeof(addr)))); icmp6stat_inc(icp6s_badns); m_freem(m); if_put(ifp); } /* * Output an Neighbor Solicitation Message. Caller specifies: * - ICMP6 header source IP6 address * - ND6 header target IP6 address * - ND6 header source datalink address * * Based on RFC 2461 * Based on RFC 2462 (duplicated address detection) * * ln - for source address determination * dad - duplicated address detection */ void nd6_ns_output(struct ifnet *ifp, const struct in6_addr *daddr6, const struct in6_addr *taddr6, const struct in6_addr *saddr6, int dad) { struct mbuf *m; struct ip6_hdr *ip6; struct nd_neighbor_solicit *nd_ns; struct sockaddr_in6 src_sa, dst_sa; struct ip6_moptions im6o; int icmp6len; int maxlen; caddr_t mac; if (IN6_IS_ADDR_MULTICAST(taddr6)) return; /* estimate the size of message */ maxlen = sizeof(*ip6) + sizeof(*nd_ns); maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7; #ifdef DIAGNOSTIC if (max_linkhdr + maxlen >= MCLBYTES) { printf("%s: max_linkhdr + maxlen >= MCLBYTES (%d + %d > %d)\n", __func__, max_linkhdr, maxlen, MCLBYTES); panic("%s: insufficient MCLBYTES", __func__); /* NOTREACHED */ } #endif MGETHDR(m, M_DONTWAIT, MT_DATA); if (m && max_linkhdr + maxlen >= MHLEN) { MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { m_free(m); m = NULL; } } if (m == NULL) return; m->m_pkthdr.ph_ifidx = 0; m->m_pkthdr.ph_rtableid = ifp->if_rdomain; if (daddr6 == NULL || IN6_IS_ADDR_MULTICAST(daddr6)) { m->m_flags |= M_MCAST; im6o.im6o_ifidx = ifp->if_index; im6o.im6o_hlim = 255; im6o.im6o_loop = 0; } icmp6len = sizeof(*nd_ns); m->m_pkthdr.len = m->m_len = sizeof(*ip6) + icmp6len; m_align(m, maxlen); /* fill neighbor solicitation packet */ ip6 = mtod(m, struct ip6_hdr *); ip6->ip6_flow = 0; ip6->ip6_vfc &= ~IPV6_VERSION_MASK; ip6->ip6_vfc |= IPV6_VERSION; /* ip6->ip6_plen will be set later */ ip6->ip6_nxt = IPPROTO_ICMPV6; ip6->ip6_hlim = 255; /* determine the source and destination addresses */ bzero(&src_sa, sizeof(src_sa)); bzero(&dst_sa, sizeof(dst_sa)); src_sa.sin6_family = dst_sa.sin6_family = AF_INET6; src_sa.sin6_len = dst_sa.sin6_len = sizeof(struct sockaddr_in6); if (daddr6 != NULL) dst_sa.sin6_addr = *daddr6; else { dst_sa.sin6_addr.s6_addr16[0] = __IPV6_ADDR_INT16_MLL; dst_sa.sin6_addr.s6_addr16[1] = htons(ifp->if_index); dst_sa.sin6_addr.s6_addr32[1] = 0; dst_sa.sin6_addr.s6_addr32[2] = __IPV6_ADDR_INT32_ONE; dst_sa.sin6_addr.s6_addr32[3] = taddr6->s6_addr32[3]; dst_sa.sin6_addr.s6_addr8[12] = 0xff; } ip6->ip6_dst = dst_sa.sin6_addr; if (!dad) { /* * RFC2461 7.2.2: * "If the source address of the packet prompting the * solicitation is the same as one of the addresses assigned * to the outgoing interface, that address SHOULD be placed * in the IP Source Address of the outgoing solicitation. * Otherwise, any one of the addresses assigned to the * interface should be used." * * We use the source address for the prompting packet * (saddr6), if: * - saddr6 is given from the caller (by giving "ln"), and * - saddr6 belongs to the outgoing interface and * - if taddr is link local saddr6 must be link local as well * Otherwise, we perform the source address selection as usual. */ if (saddr6 != NULL) src_sa.sin6_addr = *saddr6; if (!IN6_IS_ADDR_LINKLOCAL(taddr6) || IN6_IS_ADDR_UNSPECIFIED(&src_sa.sin6_addr) || IN6_IS_ADDR_LINKLOCAL(&src_sa.sin6_addr) || !in6ifa_ifpwithaddr(ifp, &src_sa.sin6_addr)) { struct rtentry *rt; rt = rtalloc(sin6tosa(&dst_sa), RT_RESOLVE, m->m_pkthdr.ph_rtableid); if (!rtisvalid(rt)) { char addr[INET6_ADDRSTRLEN]; nd6log((LOG_DEBUG, "%s: source can't be determined: dst=%s\n", __func__, inet_ntop(AF_INET6, &dst_sa.sin6_addr, addr, sizeof(addr)))); rtfree(rt); goto bad; } src_sa.sin6_addr = ifatoia6(rt->rt_ifa)->ia_addr.sin6_addr; rtfree(rt); } } else { /* * Source address for DAD packet must always be IPv6 * unspecified address. (0::0) * We actually don't have to 0-clear the address (we did it * above), but we do so here explicitly to make the intention * clearer. */ bzero(&src_sa.sin6_addr, sizeof(src_sa.sin6_addr)); } ip6->ip6_src = src_sa.sin6_addr; nd_ns = (struct nd_neighbor_solicit *)(ip6 + 1); nd_ns->nd_ns_type = ND_NEIGHBOR_SOLICIT; nd_ns->nd_ns_code = 0; nd_ns->nd_ns_reserved = 0; nd_ns->nd_ns_target = *taddr6; if (IN6_IS_SCOPE_EMBED(&nd_ns->nd_ns_target)) nd_ns->nd_ns_target.s6_addr16[1] = 0; /* * Add source link-layer address option. * * spec implementation * --- --- * DAD packet MUST NOT do not add the option * there's no link layer address: * impossible do not add the option * there's link layer address: * Multicast NS MUST add one add the option * Unicast NS SHOULD add one add the option */ if (!dad && (mac = nd6_ifptomac(ifp))) { int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen; struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_ns + 1); /* 8 byte alignments... */ optlen = (optlen + 7) & ~7; m->m_pkthdr.len += optlen; m->m_len += optlen; icmp6len += optlen; bzero((caddr_t)nd_opt, optlen); nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; nd_opt->nd_opt_len = optlen >> 3; bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen); } ip6->ip6_plen = htons((u_short)icmp6len); nd_ns->nd_ns_cksum = 0; m->m_pkthdr.csum_flags |= M_ICMP_CSUM_OUT; ip6_output(m, NULL, NULL, dad ? IPV6_UNSPECSRC : 0, &im6o, NULL); icmp6stat_inc(icp6s_outhist + ND_NEIGHBOR_SOLICIT); return; bad: m_freem(m); } /* * Neighbor advertisement input handling. * * Based on RFC 2461 * Based on RFC 2462 (duplicated address detection) * * the following items are not implemented yet: * - proxy advertisement delay rule (RFC2461 7.2.8, last paragraph, SHOULD) * - anycast advertisement delay rule (RFC2461 7.2.7, SHOULD) */ void nd6_na_input(struct mbuf *m, int off, int icmp6len) { struct ifnet *ifp; struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); struct nd_neighbor_advert *nd_na; struct in6_addr daddr6 = ip6->ip6_dst; struct in6_addr taddr6; int flags; int is_router; int is_solicited; int is_override; char *lladdr = NULL; int lladdrlen = 0; struct ifaddr *ifa; struct in6_ifaddr *ifa6; struct llinfo_nd6 *ln; struct rtentry *rt = NULL; struct sockaddr_dl *sdl; struct nd_opts ndopts; char addr[INET6_ADDRSTRLEN], addr0[INET6_ADDRSTRLEN]; NET_ASSERT_LOCKED_EXCLUSIVE(); ifp = if_get(m->m_pkthdr.ph_ifidx); if (ifp == NULL) goto freeit; if (ip6->ip6_hlim != 255) { nd6log((LOG_ERR, "nd6_na_input: invalid hlim (%d) from %s to %s on %s\n", ip6->ip6_hlim, inet_ntop(AF_INET6, &ip6->ip6_src, addr, sizeof(addr)), inet_ntop(AF_INET6, &ip6->ip6_dst, addr0, sizeof(addr0)), ifp->if_xname)); goto bad; } IP6_EXTHDR_GET(nd_na, struct nd_neighbor_advert *, m, off, icmp6len); if (nd_na == NULL) { icmp6stat_inc(icp6s_tooshort); if_put(ifp); return; } taddr6 = nd_na->nd_na_target; flags = nd_na->nd_na_flags_reserved; is_router = ((flags & ND_NA_FLAG_ROUTER) != 0); is_solicited = ((flags & ND_NA_FLAG_SOLICITED) != 0); is_override = ((flags & ND_NA_FLAG_OVERRIDE) != 0); if (IN6_IS_SCOPE_EMBED(&taddr6)) taddr6.s6_addr16[1] = htons(ifp->if_index); if (IN6_IS_ADDR_MULTICAST(&taddr6)) { nd6log((LOG_ERR, "nd6_na_input: invalid target address %s\n", inet_ntop(AF_INET6, &taddr6, addr, sizeof(addr)))); goto bad; } if (is_solicited && IN6_IS_ADDR_MULTICAST(&daddr6)) { nd6log((LOG_ERR, "nd6_na_input: a solicited adv is multicasted\n")); goto bad; } icmp6len -= sizeof(*nd_na); if (nd6_options(nd_na + 1, icmp6len, &ndopts) < 0) { nd6log((LOG_INFO, "nd6_na_input: invalid ND option, ignored\n")); /* nd6_options have incremented stats */ goto freeit; } if (IN6_IS_ADDR_MULTICAST(&daddr6) && !ndopts.nd_opts_tgt_lladdr) { nd6log((LOG_INFO, "nd6_na_input: multicast adv without TLLA\n")); goto bad; } if (ndopts.nd_opts_tgt_lladdr) { lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1); lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3; } ifa6 = in6ifa_ifpwithaddr(ifp, &taddr6); ifa = ifa6 ? &ifa6->ia_ifa : NULL; /* * Target address matches one of my interface address. * * If my address is tentative, this means that there's somebody * already using the same address as mine. This indicates DAD failure. * This is defined in RFC 2462. * * Otherwise, process as defined in RFC 2461. */ if (ifa && (ifatoia6(ifa)->ia6_flags & IN6_IFF_TENTATIVE)) { struct dadq *dp; dp = nd6_dad_find(ifa); if (dp) { dp->dad_na_icount++; /* remove the address. */ nd6_dad_duplicated(dp); } goto freeit; } if (ifa) { #if NCARP > 0 /* * Ignore NAs silently for carp addresses if we're not * the CARP master. */ if (ifp->if_type == IFT_CARP && !carp_iamatch(ifp)) goto freeit; #endif log(LOG_ERR, "nd6_na_input: duplicate IP6 address %s\n", inet_ntop(AF_INET6, &taddr6, addr, sizeof(addr))); goto freeit; } if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) { nd6log((LOG_INFO, "nd6_na_input: lladdrlen mismatch for %s " "(if %d, NA packet %d)\n", inet_ntop(AF_INET6, &taddr6, addr, sizeof(addr)), ifp->if_addrlen, lladdrlen - 2)); goto bad; } /* Check if we already have this neighbor in our cache. */ rt = nd6_lookup(&taddr6, 0, ifp, ifp->if_rdomain); /* * If we are a router, we may create new stale cache entries upon * receiving Unsolicited Neighbor Advertisements. */ if (rt == NULL && ip6_forwarding == 1) { rt = nd6_lookup(&taddr6, 1, ifp, ifp->if_rdomain); if (rt == NULL || lladdr == NULL || ((sdl = satosdl(rt->rt_gateway)) == NULL)) goto freeit; ln = (struct llinfo_nd6 *)rt->rt_llinfo; sdl->sdl_alen = ifp->if_addrlen; bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen); /* * RFC9131 6.1.1 * * Routers SHOULD create a new entry for the target address * with the reachability state set to STALE. */ ln->ln_state = ND6_LLINFO_STALE; nd6_llinfo_settimer(ln, nd6_gctimer); goto freeit; } /* * Host: * If no neighbor cache entry is found, NA SHOULD silently be * discarded. */ if ((rt == NULL) || ((ln = (struct llinfo_nd6 *)rt->rt_llinfo) == NULL) || ((sdl = satosdl(rt->rt_gateway)) == NULL)) goto freeit; if (ln->ln_state == ND6_LLINFO_INCOMPLETE) { /* * If the link-layer has address, and no lladdr option came, * discard the packet. */ if (ifp->if_addrlen && !lladdr) goto freeit; /* * Record link-layer address, and update the state. */ sdl->sdl_alen = ifp->if_addrlen; bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen); if (is_solicited) { ln->ln_state = ND6_LLINFO_REACHABLE; ln->ln_byhint = 0; /* Notify userland that a new ND entry is reachable. */ rtm_send(rt, RTM_RESOLVE, 0, ifp->if_rdomain); if (!ND6_LLINFO_PERMANENT(ln)) { nd6_llinfo_settimer(ln, ifp->if_nd->reachable); } } else { ln->ln_state = ND6_LLINFO_STALE; nd6_llinfo_settimer(ln, nd6_gctimer); } if ((ln->ln_router = is_router) != 0) { /* * This means a router's state has changed from * non-reachable to probably reachable, and might * affect the status of associated prefixes.. */ if ((rt->rt_flags & RTF_LLINFO) == 0) goto freeit; /* ln is gone */ } } else { int llchange; /* * Check if the link-layer address has changed or not. */ if (!lladdr) llchange = 0; else { if (sdl->sdl_alen) { if (bcmp(lladdr, LLADDR(sdl), ifp->if_addrlen)) llchange = 1; else llchange = 0; } else llchange = 1; } /* * This is VERY complex. Look at it with care. * * override solicit lladdr llchange action * (L: record lladdr) * * 0 0 n -- (2c) * 0 0 y n (2b) L * 0 0 y y (1) REACHABLE->STALE * 0 1 n -- (2c) *->REACHABLE * 0 1 y n (2b) L *->REACHABLE * 0 1 y y (1) REACHABLE->STALE * 1 0 n -- (2a) * 1 0 y n (2a) L * 1 0 y y (2a) L *->STALE * 1 1 n -- (2a) *->REACHABLE * 1 1 y n (2a) L *->REACHABLE * 1 1 y y (2a) L *->REACHABLE */ if (!is_override && (lladdr && llchange)) { /* (1) */ /* * If state is REACHABLE, make it STALE. * no other updates should be done. */ if (ln->ln_state == ND6_LLINFO_REACHABLE) { ln->ln_state = ND6_LLINFO_STALE; nd6_llinfo_settimer(ln, nd6_gctimer); } goto freeit; } else if (is_override /* (2a) */ || (!is_override && (lladdr && !llchange)) /* (2b) */ || !lladdr) { /* (2c) */ /* * Update link-local address, if any. */ if (llchange) { log(LOG_INFO, "ndp info overwritten for %s " "by %s on %s\n", inet_ntop(AF_INET6, &taddr6, addr, sizeof(addr)), ether_sprintf(lladdr), ifp->if_xname); } if (lladdr) { sdl->sdl_alen = ifp->if_addrlen; bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen); } /* * If solicited, make the state REACHABLE. * If not solicited and the link-layer address was * changed, make it STALE. */ if (is_solicited) { ln->ln_state = ND6_LLINFO_REACHABLE; ln->ln_byhint = 0; if (!ND6_LLINFO_PERMANENT(ln)) { nd6_llinfo_settimer(ln, ifp->if_nd->reachable); } } else { if (lladdr && llchange) { ln->ln_state = ND6_LLINFO_STALE; nd6_llinfo_settimer(ln, nd6_gctimer); } } } if (ln->ln_router && !is_router) { if (!ip6_forwarding) { /* * The neighbor may be used * as a next hop for some destinations * (e.g. redirect case). So we must * call rt6_flush explicitly. */ rt6_flush(&ip6->ip6_src, ifp); } } ln->ln_router = is_router; } rt->rt_flags &= ~RTF_REJECT; ln->ln_asked = 0; if_output_mq(ifp, &ln->ln_mq, &ln_hold_total, rt_key(rt), rt); freeit: rtfree(rt); m_freem(m); if_put(ifp); return; bad: icmp6stat_inc(icp6s_badna); m_freem(m); if_put(ifp); } /* * Neighbor advertisement output handling. * * Based on RFC 2461 * * the following items are not implemented yet: * - proxy advertisement delay rule (RFC2461 7.2.8, last paragraph, SHOULD) * - anycast advertisement delay rule (RFC2461 7.2.7, SHOULD) * * tlladdr - 1 if include target link-layer address * sdl0 - sockaddr_dl (= proxy NA) or NULL */ void nd6_na_output(struct ifnet *ifp, const struct in6_addr *daddr6, const struct in6_addr *taddr6, u_long flags, int tlladdr, struct sockaddr *sdl0) { struct mbuf *m; struct rtentry *rt = NULL; struct ip6_hdr *ip6; struct nd_neighbor_advert *nd_na; struct ip6_moptions im6o; struct sockaddr_in6 dst_sa; int icmp6len, maxlen; caddr_t mac = NULL; #if NCARP > 0 /* Do not send NAs for carp addresses if we're not the CARP master. */ if (ifp->if_type == IFT_CARP && !carp_iamatch(ifp)) return; #endif /* estimate the size of message */ maxlen = sizeof(*ip6) + sizeof(*nd_na); maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7; #ifdef DIAGNOSTIC if (max_linkhdr + maxlen >= MCLBYTES) { printf("%s: max_linkhdr + maxlen >= MCLBYTES (%d + %d > %d)\n", __func__, max_linkhdr, maxlen, MCLBYTES); panic("%s: insufficient MCLBYTES", __func__); /* NOTREACHED */ } #endif MGETHDR(m, M_DONTWAIT, MT_DATA); if (m && max_linkhdr + maxlen >= MHLEN) { MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { m_free(m); m = NULL; } } if (m == NULL) return; m->m_pkthdr.ph_rtableid = ifp->if_rdomain; if (IN6_IS_ADDR_MULTICAST(daddr6)) { m->m_flags |= M_MCAST; im6o.im6o_ifidx = ifp->if_index; im6o.im6o_hlim = 255; im6o.im6o_loop = 0; } icmp6len = sizeof(*nd_na); m->m_pkthdr.len = m->m_len = sizeof(struct ip6_hdr) + icmp6len; m_align(m, maxlen); /* fill neighbor advertisement packet */ ip6 = mtod(m, struct ip6_hdr *); ip6->ip6_flow = 0; ip6->ip6_vfc &= ~IPV6_VERSION_MASK; ip6->ip6_vfc |= IPV6_VERSION; ip6->ip6_nxt = IPPROTO_ICMPV6; ip6->ip6_hlim = 255; bzero(&dst_sa, sizeof(dst_sa)); dst_sa.sin6_len = sizeof(struct sockaddr_in6); dst_sa.sin6_family = AF_INET6; dst_sa.sin6_addr = *daddr6; if (IN6_IS_ADDR_UNSPECIFIED(daddr6)) { /* reply to DAD */ dst_sa.sin6_addr.s6_addr16[0] = __IPV6_ADDR_INT16_MLL; dst_sa.sin6_addr.s6_addr16[1] = htons(ifp->if_index); dst_sa.sin6_addr.s6_addr32[1] = 0; dst_sa.sin6_addr.s6_addr32[2] = 0; dst_sa.sin6_addr.s6_addr32[3] = __IPV6_ADDR_INT32_ONE; flags &= ~ND_NA_FLAG_SOLICITED; } ip6->ip6_dst = dst_sa.sin6_addr; /* * Select a source whose scope is the same as that of the dest. */ rt = rtalloc(sin6tosa(&dst_sa), RT_RESOLVE, ifp->if_rdomain); if (!rtisvalid(rt)) { char addr[INET6_ADDRSTRLEN]; nd6log((LOG_DEBUG, "%s: source can't be determined: dst=%s\n", __func__, inet_ntop(AF_INET6, &dst_sa.sin6_addr, addr, sizeof(addr)))); rtfree(rt); goto bad; } ip6->ip6_src = ifatoia6(rt->rt_ifa)->ia_addr.sin6_addr; rtfree(rt); nd_na = (struct nd_neighbor_advert *)(ip6 + 1); nd_na->nd_na_type = ND_NEIGHBOR_ADVERT; nd_na->nd_na_code = 0; nd_na->nd_na_target = *taddr6; if (IN6_IS_SCOPE_EMBED(&nd_na->nd_na_target)) nd_na->nd_na_target.s6_addr16[1] = 0; /* * "tlladdr" indicates NS's condition for adding tlladdr or not. * see nd6_ns_input() for details. * Basically, if NS packet is sent to unicast/anycast addr, * target lladdr option SHOULD NOT be included. */ if (tlladdr) { /* * sdl0 != NULL indicates proxy NA. If we do proxy, use * lladdr in sdl0. If we are not proxying (sending NA for * my address) use lladdr configured for the interface. */ if (sdl0 == NULL) { mac = nd6_ifptomac(ifp); } else if (sdl0->sa_family == AF_LINK) { struct sockaddr_dl *sdl; sdl = satosdl(sdl0); if (sdl->sdl_alen == ifp->if_addrlen) mac = LLADDR(sdl); } } if (tlladdr && mac) { int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen; struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_na + 1); /* roundup to 8 bytes alignment! */ optlen = (optlen + 7) & ~7; m->m_pkthdr.len += optlen; m->m_len += optlen; icmp6len += optlen; bzero((caddr_t)nd_opt, optlen); nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR; nd_opt->nd_opt_len = optlen >> 3; bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen); } else flags &= ~ND_NA_FLAG_OVERRIDE; ip6->ip6_plen = htons((u_short)icmp6len); nd_na->nd_na_flags_reserved = flags; nd_na->nd_na_cksum = 0; m->m_pkthdr.csum_flags |= M_ICMP_CSUM_OUT; ip6_output(m, NULL, NULL, 0, &im6o, NULL); icmp6stat_inc(icp6s_outhist + ND_NEIGHBOR_ADVERT); return; bad: m_freem(m); } caddr_t nd6_ifptomac(struct ifnet *ifp) { switch (ifp->if_type) { case IFT_ETHER: case IFT_IEEE1394: case IFT_PROPVIRTUAL: case IFT_CARP: case IFT_IEEE80211: return ((caddr_t)(ifp + 1)); default: return NULL; } } struct dadq * nd6_dad_find(struct ifaddr *ifa) { struct dadq *dp; TAILQ_FOREACH(dp, &dadq, dad_list) { if (dp->dad_ifa == ifa) return dp; } return NULL; } void nd6_dad_destroy(struct dadq *dp) { TAILQ_REMOVE(&dadq, dp, dad_list); ifafree(dp->dad_ifa); free(dp, M_IP6NDP, sizeof(*dp)); ip6_dad_pending--; } void nd6_dad_starttimer(struct dadq *dp) { timeout_set_proc(&dp->dad_timer_ch, nd6_dad_timer, dp->dad_ifa); timeout_add_msec(&dp->dad_timer_ch, RETRANS_TIMER); } void nd6_dad_stoptimer(struct dadq *dp) { timeout_del(&dp->dad_timer_ch); } /* * Start Duplicated Address Detection (DAD) for specified interface address. */ void nd6_dad_start(struct ifaddr *ifa) { struct in6_ifaddr *ia6 = ifatoia6(ifa); struct dadq *dp; char addr[INET6_ADDRSTRLEN]; NET_ASSERT_LOCKED(); /* * If we don't need DAD, don't do it. * There are several cases: * - DAD is disabled (ip6_dad_count == 0) * - the interface address is anycast */ KASSERT(ia6->ia6_flags & IN6_IFF_TENTATIVE); if ((ia6->ia6_flags & IN6_IFF_ANYCAST) || (!ip6_dad_count)) { ia6->ia6_flags &= ~IN6_IFF_TENTATIVE; rtm_addr(RTM_CHGADDRATTR, ifa); return; } /* DAD already in progress */ if (nd6_dad_find(ifa) != NULL) return; dp = malloc(sizeof(*dp), M_IP6NDP, M_NOWAIT | M_ZERO); if (dp == NULL) { log(LOG_ERR, "%s: memory allocation failed for %s(%s)\n", __func__, inet_ntop(AF_INET6, &ia6->ia_addr.sin6_addr, addr, sizeof(addr)), ifa->ifa_ifp ? ifa->ifa_ifp->if_xname : "???"); return; } TAILQ_INSERT_TAIL(&dadq, dp, dad_list); ip6_dad_pending++; nd6log((LOG_DEBUG, "%s: starting DAD for %s\n", ifa->ifa_ifp->if_xname, inet_ntop(AF_INET6, &ia6->ia_addr.sin6_addr, addr, sizeof(addr)))); /* * Send NS packet for DAD, ip6_dad_count times. * Note that we must delay the first transmission, if this is the * first packet to be sent from the interface after interface * (re)initialization. */ dp->dad_ifa = ifaref(ifa); dp->dad_count = ip6_dad_count; dp->dad_ns_icount = dp->dad_na_icount = 0; dp->dad_ns_ocount = dp->dad_ns_tcount = 0; nd6_dad_ns_output(dp, ifa); nd6_dad_starttimer(dp); } /* * terminate DAD unconditionally. used for address removals. */ void nd6_dad_stop(struct ifaddr *ifa) { struct dadq *dp; dp = nd6_dad_find(ifa); if (!dp) { /* DAD wasn't started yet */ return; } nd6_dad_stoptimer(dp); nd6_dad_destroy(dp); } void nd6_dad_timer(void *xifa) { struct ifaddr *ifa; struct in6_ifaddr *ia6; struct in6_addr daddr6, taddr6; struct ifnet *ifp; struct dadq *dp; char addr[INET6_ADDRSTRLEN]; NET_LOCK(); /* Sanity check */ if (xifa == NULL) { log(LOG_ERR, "%s: called with null parameter\n", __func__); goto done; } ifa = xifa; ia6 = ifatoia6(ifa); taddr6 = ia6->ia_addr.sin6_addr; ifp = ifa->ifa_ifp; dp = nd6_dad_find(ifa); if (dp == NULL) { log(LOG_ERR, "%s: DAD structure not found\n", __func__); goto done; } if (ia6->ia6_flags & IN6_IFF_DUPLICATED) { log(LOG_ERR, "%s: called with duplicated address %s(%s)\n", __func__, inet_ntop(AF_INET6, &ia6->ia_addr.sin6_addr, addr, sizeof(addr)), ifa->ifa_ifp ? ifa->ifa_ifp->if_xname : "???"); goto done; } if ((ia6->ia6_flags & IN6_IFF_TENTATIVE) == 0) { log(LOG_ERR, "%s: called with non-tentative address %s(%s)\n", __func__, inet_ntop(AF_INET6, &ia6->ia_addr.sin6_addr, addr, sizeof(addr)), ifa->ifa_ifp ? ifa->ifa_ifp->if_xname : "???"); goto done; } /* timeouted with IFF_{RUNNING,UP} check */ if (dp->dad_ns_tcount > dad_maxtry) { nd6log((LOG_INFO, "%s: could not run DAD, driver problem?\n", ifa->ifa_ifp->if_xname)); nd6_dad_destroy(dp); goto done; } /* Need more checks? */ if (dp->dad_ns_ocount < dp->dad_count) { /* * We have more NS to go. Send NS packet for DAD. */ nd6_dad_ns_output(dp, ifa); nd6_dad_starttimer(dp); } else { /* * We have transmitted sufficient number of DAD packets. */ if (dp->dad_na_icount || dp->dad_ns_icount) { /* dp will be freed in nd6_dad_duplicated() */ nd6_dad_duplicated(dp); } else { /* * We are done with DAD. No NA came, no NS came. */ ia6->ia6_flags &= ~IN6_IFF_TENTATIVE; rtm_addr(RTM_CHGADDRATTR, ifa); nd6log((LOG_DEBUG, "%s: DAD complete for %s - no duplicates found\n", ifa->ifa_ifp->if_xname, inet_ntop(AF_INET6, &ia6->ia_addr.sin6_addr, addr, sizeof(addr)))); daddr6 = in6addr_linklocal_allrouters; daddr6.s6_addr16[1] = htons(ifp->if_index); /* RFC9131 - inform routers about our new address */ nd6_na_output(ifp, &daddr6, &taddr6, 0, 1, NULL); nd6_dad_destroy(dp); } } done: NET_UNLOCK(); } void nd6_dad_duplicated(struct dadq *dp) { struct in6_ifaddr *ia6 = ifatoia6(dp->dad_ifa); char addr[INET6_ADDRSTRLEN]; log(LOG_ERR, "%s: DAD detected duplicate IPv6 address %s: " "NS in/out=%d/%d, NA in=%d\n", ia6->ia_ifp->if_xname, inet_ntop(AF_INET6, &ia6->ia_addr.sin6_addr, addr, sizeof(addr)), dp->dad_ns_icount, dp->dad_ns_ocount, dp->dad_na_icount); ia6->ia6_flags &= ~IN6_IFF_TENTATIVE; ia6->ia6_flags |= IN6_IFF_DUPLICATED; /* We are done with DAD, with duplicated address found. (failure) */ nd6_dad_stoptimer(dp); log(LOG_ERR, "%s: DAD complete for %s - duplicate found\n", ia6->ia_ifp->if_xname, inet_ntop(AF_INET6, &ia6->ia_addr.sin6_addr, addr, sizeof(addr))); log(LOG_ERR, "%s: manual intervention required\n", ia6->ia_ifp->if_xname); rtm_addr(RTM_CHGADDRATTR, dp->dad_ifa); nd6_dad_destroy(dp); } void nd6_dad_ns_output(struct dadq *dp, struct ifaddr *ifa) { struct in6_ifaddr *ia6 = ifatoia6(ifa); struct ifnet *ifp = ifa->ifa_ifp; dp->dad_ns_tcount++; if ((ifp->if_flags & IFF_UP) == 0) { #if 0 printf("%s: interface down?\n", ifp->if_xname); #endif return; } if ((ifp->if_flags & IFF_RUNNING) == 0) { #if 0 printf("%s: interface not running?\n", ifp->if_xname); #endif return; } dp->dad_ns_ocount++; nd6_ns_output(ifp, NULL, &ia6->ia_addr.sin6_addr, NULL, 1); } void nd6_dad_ns_input(struct ifaddr *ifa) { struct dadq *dp; if (!ifa) panic("%s: ifa == NULL", __func__); dp = nd6_dad_find(ifa); if (dp == NULL) { log(LOG_ERR, "%s: DAD structure not found\n", __func__); return; } /* * if I'm yet to start DAD, someone else started using this address * first. I have a duplicate and you win. */ /* XXX more checks for loopback situation - see nd6_dad_timer too */ if (dp->dad_ns_ocount == 0) { /* dp will be freed in nd6_dad_duplicated() */ nd6_dad_duplicated(dp); } else { /* * not sure if I got a duplicate. * increment ns count and see what happens. */ dp->dad_ns_icount++; } } /* * Check whether ``addr'' is a neighbor address connected to ``ifp''. */ int nd6_isneighbor(const struct ifnet *ifp, const struct in6_addr *addr) { struct rtentry *rt; struct sockaddr_in6 sin6; unsigned int tableid = ifp->if_rdomain; int rv = 0; memset(&sin6, 0, sizeof(sin6)); sin6.sin6_len = sizeof(struct sockaddr_in6); sin6.sin6_family = AF_INET6; sin6.sin6_addr = *addr; rt = rtalloc(sin6tosa(&sin6), 0, tableid); if (rtisvalid(rt) && ISSET(rt->rt_flags, RTF_CLONING|RTF_CLONED)) rv = if_isconnected(ifp, rt->rt_ifidx); rtfree(rt); return (rv); }
2 2 2 1 2 2 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 /* $OpenBSD: if_enc.c,v 1.79 2022/08/29 07:51:45 bluhm Exp $ */ /* * Copyright (c) 2010 Reyk Floeter <reyk@vantronix.net> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "bpfilter.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/socket.h> #include <sys/sockio.h> #include <sys/mbuf.h> #include <net/if.h> #include <net/if_dl.h> #include <net/if_var.h> #include <net/if_enc.h> #include <net/if_types.h> #if NBPFILTER > 0 #include <net/bpf.h> #endif struct ifnet **enc_ifps; /* rdomain-mapped enc ifs */ u_int enc_max_rdomain; struct ifnet **enc_allifps; /* unit-mapped enc ifs */ u_int enc_max_unit; #define ENC_MAX_UNITS 4096 /* XXX n per rdomain */ void encattach(int); int enc_clone_create(struct if_clone *, int); int enc_clone_destroy(struct ifnet *); int enc_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); int enc_ioctl(struct ifnet *, u_long, caddr_t); int enc_setif(struct ifnet *, u_int); void enc_unsetif(struct ifnet *); struct if_clone enc_cloner = IF_CLONE_INITIALIZER("enc", enc_clone_create, enc_clone_destroy); void encattach(int count) { /* Create enc0 by default */ (void)enc_clone_create(&enc_cloner, 0); if_clone_attach(&enc_cloner); } int enc_clone_create(struct if_clone *ifc, int unit) { struct enc_softc *sc; struct ifnet *ifp; struct ifnet **new; size_t oldlen; int error; if (unit > ENC_MAX_UNITS) return (EINVAL); if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL) return (ENOBUFS); sc->sc_unit = unit; ifp = &sc->sc_if; ifp->if_softc = sc; ifp->if_type = IFT_ENC; ifp->if_xflags = IFXF_CLONED; ifp->if_output = enc_output; ifp->if_ioctl = enc_ioctl; ifp->if_hdrlen = ENC_HDRLEN; snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d", ifc->ifc_name, unit); if_attach(ifp); if (unit == 0) if_addgroup(ifp, ifc->ifc_name); /* * enc(4) does not have a link-layer address but rtrequest() * wants an ifa for every route entry. So let's setup a fake * and empty ifa of type AF_LINK for this purpose. */ if_alloc_sadl(ifp); refcnt_init_trace(&sc->sc_ifa.ifa_refcnt, DT_REFCNT_IDX_IFADDR); sc->sc_ifa.ifa_ifp = ifp; sc->sc_ifa.ifa_addr = sdltosa(ifp->if_sadl); sc->sc_ifa.ifa_netmask = NULL; #if NBPFILTER > 0 bpfattach(&ifp->if_bpf, ifp, DLT_ENC, ENC_HDRLEN); #endif NET_LOCK(); error = enc_setif(ifp, 0); if (error != 0) { NET_UNLOCK(); if_detach(ifp); free(sc, M_DEVBUF, sizeof(*sc)); return (error); } if (enc_allifps == NULL || unit > enc_max_unit) { if ((new = mallocarray(unit + 1, sizeof(struct ifnet *), M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL) { NET_UNLOCK(); return (ENOBUFS); } if (enc_allifps != NULL) { oldlen = sizeof(struct ifnet *) * (enc_max_unit + 1); memcpy(new, enc_allifps, oldlen); free(enc_allifps, M_DEVBUF, oldlen); } enc_allifps = new; enc_max_unit = unit; } enc_allifps[unit] = ifp; NET_UNLOCK(); return (0); } int enc_clone_destroy(struct ifnet *ifp) { struct enc_softc *sc = ifp->if_softc; /* Protect users from removing enc0 */ if (sc->sc_unit == 0) return (EPERM); NET_LOCK(); enc_allifps[sc->sc_unit] = NULL; enc_unsetif(ifp); NET_UNLOCK(); if_detach(ifp); if (refcnt_rele(&sc->sc_ifa.ifa_refcnt) == 0) { panic("%s: ifa refcnt has %u refs", __func__, sc->sc_ifa.ifa_refcnt.r_refs); } free(sc, M_DEVBUF, sizeof(*sc)); return (0); } int enc_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa, struct rtentry *rt) { m_freem(m); /* drop packet */ return (EAFNOSUPPORT); } int enc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct ifreq *ifr = (struct ifreq *)data; int error; switch (cmd) { case SIOCSIFADDR: case SIOCSIFDSTADDR: case SIOCSIFFLAGS: if (ifp->if_flags & IFF_UP) ifp->if_flags |= IFF_RUNNING; else ifp->if_flags &= ~IFF_RUNNING; break; case SIOCSIFRDOMAIN: if ((error = enc_setif(ifp, ifr->ifr_rdomainid)) != 0) return (error); /* FALLTHROUGH */ default: return (ENOTTY); } return (0); } struct ifnet * enc_getif(u_int rdomain, u_int unit) { struct ifnet *ifp; NET_ASSERT_LOCKED(); /* Check if the caller wants to get a non-default enc interface */ if (unit > 0) { if (unit > enc_max_unit) return (NULL); ifp = enc_allifps[unit]; if (ifp == NULL || ifp->if_rdomain != rdomain) return (NULL); return (ifp); } /* Otherwise return the default enc interface for this rdomain */ if (enc_ifps == NULL) return (NULL); else if (rdomain > RT_TABLEID_MAX) return (NULL); else if (rdomain > enc_max_rdomain) return (NULL); return (enc_ifps[rdomain]); } struct ifaddr * enc_getifa(u_int rdomain, u_int unit) { struct ifnet *ifp; struct enc_softc *sc; ifp = enc_getif(rdomain, unit); if (ifp == NULL) return (NULL); sc = ifp->if_softc; return (&sc->sc_ifa); } int enc_setif(struct ifnet *ifp, u_int rdomain) { struct ifnet **new; size_t oldlen; NET_ASSERT_LOCKED(); enc_unsetif(ifp); /* * There can only be one default encif per rdomain - * Don't overwrite the existing enc iface that is stored * for this rdomain, so only the first enc interface that * was added for this rdomain becomes the default. */ if (enc_getif(rdomain, 0) != NULL) return (0); if (rdomain > RT_TABLEID_MAX) return (EINVAL); if (enc_ifps == NULL || rdomain > enc_max_rdomain) { if ((new = mallocarray(rdomain + 1, sizeof(struct ifnet *), M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL) return (ENOBUFS); if (enc_ifps != NULL) { oldlen = sizeof(struct ifnet *) * (enc_max_rdomain + 1); memcpy(new, enc_ifps, oldlen); free(enc_ifps, M_DEVBUF, oldlen); } enc_ifps = new; enc_max_rdomain = rdomain; } enc_ifps[rdomain] = ifp; /* Indicate that this interface is the rdomain default */ ifp->if_link_state = LINK_STATE_UP; return (0); } void enc_unsetif(struct ifnet *ifp) { u_int rdomain = ifp->if_rdomain, i; struct ifnet *oifp, *nifp; if ((oifp = enc_getif(rdomain, 0)) == NULL || oifp != ifp) return; /* Clear slot for this rdomain */ enc_ifps[rdomain] = NULL; ifp->if_link_state = LINK_STATE_UNKNOWN; /* * Now find the next available encif to be the default interface * for this rdomain. */ for (i = 0; i < (enc_max_unit + 1); i++) { nifp = enc_allifps[i]; if (nifp == NULL || nifp == ifp || nifp->if_rdomain != rdomain) continue; enc_ifps[rdomain] = nifp; nifp->if_link_state = LINK_STATE_UP; break; } }
3 164 14 169 36 179 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 /* $OpenBSD: event.h,v 1.71 2023/08/20 15:13:43 visa Exp $ */ /*- * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD: src/sys/sys/event.h,v 1.11 2001/02/24 01:41:31 jlemon Exp $ */ #ifndef _SYS_EVENT_H_ #define _SYS_EVENT_H_ #define EVFILT_READ (-1) #define EVFILT_WRITE (-2) #define EVFILT_AIO (-3) /* attached to aio requests */ #define EVFILT_VNODE (-4) /* attached to vnodes */ #define EVFILT_PROC (-5) /* attached to struct process */ #define EVFILT_SIGNAL (-6) /* attached to struct process */ #define EVFILT_TIMER (-7) /* timers */ #define EVFILT_DEVICE (-8) /* devices */ #define EVFILT_EXCEPT (-9) /* exceptional conditions */ #define EVFILT_SYSCOUNT 9 #define EV_SET(kevp, a, b, c, d, e, f) do { \ struct kevent *__kevp = (kevp); \ (__kevp)->ident = (a); \ (__kevp)->filter = (b); \ (__kevp)->flags = (c); \ (__kevp)->fflags = (d); \ (__kevp)->data = (e); \ (__kevp)->udata = (f); \ } while(0) struct kevent { __uintptr_t ident; /* identifier for this event */ short filter; /* filter for event */ unsigned short flags; /* action flags for kqueue */ unsigned int fflags; /* filter flag value */ __int64_t data; /* filter data value */ void *udata; /* opaque user data identifier */ }; /* actions */ #define EV_ADD 0x0001 /* add event to kq (implies enable) */ #define EV_DELETE 0x0002 /* delete event from kq */ #define EV_ENABLE 0x0004 /* enable event */ #define EV_DISABLE 0x0008 /* disable event (not reported) */ /* flags */ #define EV_ONESHOT 0x0010 /* only report one occurrence */ #define EV_CLEAR 0x0020 /* clear event state after reporting */ #define EV_RECEIPT 0x0040 /* force EV_ERROR on success, data=0 */ #define EV_DISPATCH 0x0080 /* disable event after reporting */ #define EV_SYSFLAGS 0xf800 /* reserved by system */ #define EV_FLAG1 0x2000 /* filter-specific flag */ /* returned values */ #define EV_EOF 0x8000 /* EOF detected */ #define EV_ERROR 0x4000 /* error, data contains errno */ /* * data/hint flags for EVFILT_{READ|WRITE}, shared with userspace */ #define NOTE_LOWAT 0x0001 /* low water mark */ #define NOTE_EOF 0x0002 /* return on EOF */ /* * data/hint flags for EVFILT_EXCEPT, shared with userspace and with * EVFILT_{READ|WRITE} */ #define NOTE_OOB 0x0004 /* OOB data on a socket */ /* * data/hint flags for EVFILT_VNODE, shared with userspace */ #define NOTE_DELETE 0x0001 /* vnode was removed */ #define NOTE_WRITE 0x0002 /* data contents changed */ #define NOTE_EXTEND 0x0004 /* size increased */ #define NOTE_ATTRIB 0x0008 /* attributes changed */ #define NOTE_LINK 0x0010 /* link count changed */ #define NOTE_RENAME 0x0020 /* vnode was renamed */ #define NOTE_REVOKE 0x0040 /* vnode access was revoked */ #define NOTE_TRUNCATE 0x0080 /* vnode was truncated */ /* * data/hint flags for EVFILT_PROC, shared with userspace */ #define NOTE_EXIT 0x80000000 /* process exited */ #define NOTE_FORK 0x40000000 /* process forked */ #define NOTE_EXEC 0x20000000 /* process exec'd */ #define NOTE_PCTRLMASK 0xf0000000 /* mask for hint bits */ #define NOTE_PDATAMASK 0x000fffff /* mask for pid */ /* additional flags for EVFILT_PROC */ #define NOTE_TRACK 0x00000001 /* follow across forks */ #define NOTE_TRACKERR 0x00000002 /* could not track child */ #define NOTE_CHILD 0x00000004 /* am a child process */ /* data/hint flags for EVFILT_DEVICE, shared with userspace */ #define NOTE_CHANGE 0x00000001 /* device change event */ /* additional flags for EVFILT_TIMER */ #define NOTE_MSECONDS 0x00000000 /* data is milliseconds */ #define NOTE_SECONDS 0x00000001 /* data is seconds */ #define NOTE_USECONDS 0x00000002 /* data is microseconds */ #define NOTE_NSECONDS 0x00000003 /* data is nanoseconds */ #define NOTE_ABSTIME 0x00000010 /* timeout is absolute */ /* * This is currently visible to userland to work around broken * programs which pull in <sys/proc.h> or <sys/selinfo.h>. */ #include <sys/queue.h> struct klistops; struct knote; SLIST_HEAD(knlist, knote); struct klist { struct knlist kl_list; const struct klistops *kl_ops; void *kl_arg; }; #ifdef _KERNEL /* kernel-only flags */ #define __EV_SELECT 0x0800 /* match behavior of select */ #define __EV_POLL 0x1000 /* match behavior of poll */ #define __EV_HUP EV_FLAG1 /* device or socket disconnected */ #define EVFILT_MARKER 0xf /* placemarker for tailq */ /* * hint flag for in-kernel use - must not equal any existing note */ #define NOTE_SUBMIT 0x01000000 /* initial knote submission */ #define KN_HASHSIZE 64 /* XXX should be tunable */ /* * Flag indicating hint is a signal. Used by EVFILT_SIGNAL, and also * shared by EVFILT_PROC (all knotes attached to p->p_klist) */ #define NOTE_SIGNAL 0x08000000 /* * = Event filter interface * * == .f_flags * * Defines properties of the event filter: * * - FILTEROP_ISFD Each knote of this filter is associated * with a file descriptor. * * - FILTEROP_MPSAFE The kqueue subsystem can invoke .f_attach(), * .f_detach(), .f_modify() and .f_process() without * the kernel lock. * * == .f_attach() * * Attaches the knote to the object. * * == .f_detach() * * Detaches the knote from the object. The object must not use this knote * for delivering events after this callback has returned. * * == .f_event() * * Notifies the filter about an event. Called through knote(). * * == .f_modify() * * Modifies the knote with new state from the user. * * Returns non-zero if the knote has become active. * * == .f_process() * * Checks if the event is active and returns non-zero if the event should be * returned to the user. * * If kev is non-NULL and the event is active, the callback should store * the event's state in kev for delivery to the user. * * == Concurrency control * * The kqueue subsystem serializes calls of .f_attach(), .f_detach(), * .f_modify() and .f_process(). */ #define FILTEROP_ISFD 0x00000001 /* ident == filedescriptor */ #define FILTEROP_MPSAFE 0x00000002 /* safe without kernel lock */ struct filterops { int f_flags; int (*f_attach)(struct knote *kn); void (*f_detach)(struct knote *kn); int (*f_event)(struct knote *kn, long hint); int (*f_modify)(struct kevent *kev, struct knote *kn); int (*f_process)(struct knote *kn, struct kevent *kev); }; /* * Locking: * I immutable after creation * o object lock * q kn_kq->kq_lock */ struct knote { SLIST_ENTRY(knote) kn_link; /* for fd */ SLIST_ENTRY(knote) kn_selnext; /* for struct selinfo */ TAILQ_ENTRY(knote) kn_tqe; struct kqueue *kn_kq; /* [I] which queue we are on */ struct kevent kn_kevent; int kn_status; /* [q] */ int kn_sfflags; /* [o] saved filter flags */ __int64_t kn_sdata; /* [o] saved data field */ union { struct file *p_fp; /* file data pointer */ struct process *p_process; /* process pointer */ } kn_ptr; const struct filterops *kn_fop; void *kn_hook; /* [o] */ unsigned int kn_pollid; /* [I] */ #define KN_ACTIVE 0x0001 /* event has been triggered */ #define KN_QUEUED 0x0002 /* event is on queue */ #define KN_DISABLED 0x0004 /* event is disabled */ #define KN_DETACHED 0x0008 /* knote is detached */ #define KN_PROCESSING 0x0010 /* knote is being processed */ #define KN_WAITING 0x0020 /* waiting on processing */ #define kn_id kn_kevent.ident /* [I] */ #define kn_filter kn_kevent.filter /* [I] */ #define kn_flags kn_kevent.flags /* [o] */ #define kn_fflags kn_kevent.fflags /* [o] */ #define kn_data kn_kevent.data /* [o] */ #define kn_udata kn_kevent.udata /* [o] */ #define kn_fp kn_ptr.p_fp /* [o] */ }; struct klistops { void (*klo_assertlk)(void *); int (*klo_lock)(void *); void (*klo_unlock)(void *, int); }; struct kqueue_scan_state { struct kqueue *kqs_kq; /* kqueue of this scan */ struct knote kqs_start; /* start marker */ struct knote kqs_end; /* end marker */ int kqs_nevent; /* number of events collected */ int kqs_queued; /* if set, end marker is * in queue */ }; struct mutex; struct proc; struct rwlock; struct timespec; extern const struct filterops sig_filtops; extern const struct filterops dead_filtops; extern void kqpoll_init(unsigned int); extern void kqpoll_done(unsigned int); extern void kqpoll_exit(void); extern void knote(struct klist *list, long hint); extern void knote_locked(struct klist *list, long hint); extern void knote_fdclose(struct proc *p, int fd); extern void knote_processexit(struct process *); extern void knote_assign(const struct kevent *, struct knote *); extern void knote_submit(struct knote *, struct kevent *); extern void kqueue_init(void); extern void kqueue_init_percpu(void); extern int kqueue_register(struct kqueue *kq, struct kevent *kev, unsigned int pollid, struct proc *p); extern int kqueue_scan(struct kqueue_scan_state *, int, struct kevent *, struct timespec *, struct proc *, int *); extern void kqueue_scan_setup(struct kqueue_scan_state *, struct kqueue *); extern void kqueue_scan_finish(struct kqueue_scan_state *); extern int filt_seltrue(struct knote *kn, long hint); extern int seltrue_kqfilter(dev_t, struct knote *); extern void klist_init(struct klist *, const struct klistops *, void *); extern void klist_init_mutex(struct klist *, struct mutex *); extern void klist_init_rwlock(struct klist *, struct rwlock *); extern void klist_free(struct klist *); extern void klist_insert(struct klist *, struct knote *); extern void klist_insert_locked(struct klist *, struct knote *); extern void klist_remove(struct klist *, struct knote *); extern void klist_remove_locked(struct klist *, struct knote *); extern void klist_invalidate(struct klist *); static inline int knote_modify_fn(const struct kevent *kev, struct knote *kn, int (*f_event)(struct knote *, long)) { knote_assign(kev, kn); return ((*f_event)(kn, 0)); } static inline int knote_modify(const struct kevent *kev, struct knote *kn) { return (knote_modify_fn(kev, kn, kn->kn_fop->f_event)); } static inline int knote_process_fn(struct knote *kn, struct kevent *kev, int (*f_event)(struct knote *, long)) { int active; /* * If called from kqueue_scan(), skip f_event * when EV_ONESHOT is set, to preserve old behaviour. */ if (kev != NULL && (kn->kn_flags & EV_ONESHOT)) active = 1; else active = (*f_event)(kn, 0); if (active) knote_submit(kn, kev); return (active); } static inline int knote_process(struct knote *kn, struct kevent *kev) { return (knote_process_fn(kn, kev, kn->kn_fop->f_event)); } static inline int klist_empty(struct klist *klist) { return (SLIST_EMPTY(&klist->kl_list)); } #else /* !_KERNEL */ #include <sys/cdefs.h> struct timespec; __BEGIN_DECLS int kqueue(void); int kqueue1(int flags); int kevent(int kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); __END_DECLS #endif /* !_KERNEL */ #endif /* !_SYS_EVENT_H_ */
14 1 3 4 4 2 3 6 3 4 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 /* $OpenBSD: kern_acct.c,v 1.48 2024/04/13 23:44:11 jsg Exp $ */ /* $NetBSD: kern_acct.c,v 1.42 1996/02/04 02:15:12 christos Exp $ */ /*- * Copyright (c) 1994 Christopher G. Demetriou * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_acct.c 8.1 (Berkeley) 6/14/93 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/mount.h> #include <sys/vnode.h> #include <sys/fcntl.h> #include <sys/syslog.h> #include <sys/kernel.h> #include <sys/namei.h> #include <sys/errno.h> #include <sys/acct.h> #include <sys/resourcevar.h> #include <sys/tty.h> #include <sys/kthread.h> #include <sys/rwlock.h> #include <sys/syscallargs.h> /* * The routines implemented in this file are described in: * Leffler, et al.: The Design and Implementation of the 4.3BSD * UNIX Operating System (Addison Welley, 1989) * on pages 62-63. * * Arguably, to simplify accounting operations, this mechanism should * be replaced by one in which an accounting log file (similar to /dev/klog) * is read by a user process, etc. However, that has its own problems. */ /* * Internal accounting functions. */ comp_t encode_comp_t(u_long, u_long); int acct_start(void); void acct_thread(void *); void acct_shutdown(void); /* * Accounting vnode pointer, and saved vnode pointer. */ struct vnode *acctp; struct vnode *savacctp; /* * Lock protecting acctp and savacctp. */ struct rwlock acct_lock = RWLOCK_INITIALIZER("acctlk"); /* * Values associated with enabling and disabling accounting */ int acctsuspend = 2; /* stop accounting when < 2% free space left */ int acctresume = 4; /* resume when free space risen to > 4% */ int acctrate = 15; /* delay (in seconds) between space checks */ struct proc *acct_proc; /* * Accounting system call. Written based on the specification and * previous implementation done by Mark Tinguely. */ int sys_acct(struct proc *p, void *v, register_t *retval) { struct sys_acct_args /* { syscallarg(const char *) path; } */ *uap = v; struct nameidata nd; int error; /* Make sure that the caller is root. */ if ((error = suser(p)) != 0) return (error); /* * If accounting is to be started to a file, open that file for * writing and make sure it's 'normal'. */ if (SCARG(uap, path) != NULL) { NDINIT(&nd, 0, 0, UIO_USERSPACE, SCARG(uap, path), p); if ((error = vn_open(&nd, FWRITE|O_APPEND, 0)) != 0) return (error); VOP_UNLOCK(nd.ni_vp); if (nd.ni_vp->v_type != VREG) { vn_close(nd.ni_vp, FWRITE, p->p_ucred, p); return (EACCES); } } rw_enter_write(&acct_lock); /* * If accounting was previously enabled, kill the old space-watcher, * close the file, and (if no new file was specified, leave). */ if (acctp != NULL || savacctp != NULL) { wakeup(&acct_proc); (void)vn_close((acctp != NULL ? acctp : savacctp), FWRITE, p->p_ucred, p); acctp = savacctp = NULL; } if (SCARG(uap, path) == NULL) goto out; /* * Save the new accounting file vnode, and schedule the new * free space watcher. */ acctp = nd.ni_vp; if ((error = acct_start()) != 0) { acctp = NULL; (void)vn_close(nd.ni_vp, FWRITE, p->p_ucred, p); } out: rw_exit_write(&acct_lock); return (error); } /* * Write out process accounting information, on process exit. * Data to be written out is specified in Leffler, et al. * and are enumerated below. (They're also noted in the system * "acct.h" header file.) */ int acct_process(struct proc *p) { struct acct acct; struct process *pr = p->p_p; struct rusage *r; struct timespec booted, elapsed, realstart, st, tmp, uptime, ut; int t; struct vnode *vp; int error = 0; /* If accounting isn't enabled, don't bother */ if (acctp == NULL) return (0); rw_enter_read(&acct_lock); /* * Check the vnode again in case accounting got disabled while waiting * for the lock. */ vp = acctp; if (vp == NULL) goto out; /* * Get process accounting information. */ /* (1) The name of the command that ran */ memcpy(acct.ac_comm, pr->ps_comm, sizeof acct.ac_comm); /* (2) The amount of user and system time that was used */ calctsru(&pr->ps_tu, &ut, &st, NULL); acct.ac_utime = encode_comp_t(ut.tv_sec, ut.tv_nsec); acct.ac_stime = encode_comp_t(st.tv_sec, st.tv_nsec); /* (3) The elapsed time the command ran (and its starting time) */ nanouptime(&uptime); nanoboottime(&booted); timespecadd(&booted, &pr->ps_start, &realstart); acct.ac_btime = realstart.tv_sec; timespecsub(&uptime, &pr->ps_start, &elapsed); acct.ac_etime = encode_comp_t(elapsed.tv_sec, elapsed.tv_nsec); /* (4) The average amount of memory used */ r = &p->p_ru; timespecadd(&ut, &st, &tmp); t = tmp.tv_sec * hz + tmp.tv_nsec / (1000 * tick); if (t) acct.ac_mem = (r->ru_ixrss + r->ru_idrss + r->ru_isrss) / t; else acct.ac_mem = 0; /* (5) The number of disk I/O operations done */ acct.ac_io = encode_comp_t(r->ru_inblock + r->ru_oublock, 0); /* (6) The UID and GID of the process */ acct.ac_uid = pr->ps_ucred->cr_ruid; acct.ac_gid = pr->ps_ucred->cr_rgid; /* (7) The terminal from which the process was started */ if ((pr->ps_flags & PS_CONTROLT) && pr->ps_pgrp->pg_session->s_ttyp) acct.ac_tty = pr->ps_pgrp->pg_session->s_ttyp->t_dev; else acct.ac_tty = -1; /* (8) The boolean flags that tell how process terminated or misbehaved. */ acct.ac_flag = pr->ps_acflag; /* Extensions */ acct.ac_pid = pr->ps_pid; /* * Now, just write the accounting information to the file. */ error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&acct, sizeof (acct), (off_t)0, UIO_SYSSPACE, IO_APPEND|IO_UNIT|IO_NOLIMIT, p->p_ucred, NULL, p); out: rw_exit_read(&acct_lock); return (error); } /* * Encode_comp_t converts from ticks in seconds and microseconds * to ticks in 1/AHZ seconds. The encoding is described in * Leffler, et al., on page 63. */ #define MANTSIZE 13 /* 13 bit mantissa. */ #define EXPSIZE 3 /* Base 8 (3 bit) exponent. */ #define MAXFRACT ((1 << MANTSIZE) - 1) /* Maximum fractional value. */ comp_t encode_comp_t(u_long s, u_long ns) { int exp, rnd; exp = 0; rnd = 0; s *= AHZ; s += ns / (1000000000 / AHZ); /* Maximize precision. */ while (s > MAXFRACT) { rnd = s & (1 << (EXPSIZE - 1)); /* Round up? */ s >>= EXPSIZE; /* Base 8 exponent == 3 bit shift. */ exp++; } /* If we need to round up, do it (and handle overflow correctly). */ if (rnd && (++s > MAXFRACT)) { s >>= EXPSIZE; exp++; } /* Clean it up and polish it off. */ exp <<= MANTSIZE; /* Shift the exponent into place */ exp += s; /* and add on the mantissa. */ return (exp); } int acct_start(void) { /* Already running. */ if (acct_proc != NULL) return (0); return (kthread_create(acct_thread, NULL, &acct_proc, "acct")); } /* * Periodically check the file system to see if accounting * should be turned on or off. Beware the case where the vnode * has been vgone()'d out from underneath us, e.g. when the file * system containing the accounting file has been forcibly unmounted. */ void acct_thread(void *arg) { struct statfs sb; struct proc *p = curproc; rw_enter_write(&acct_lock); for (;;) { if (savacctp != NULL) { if (savacctp->v_type == VBAD) { (void) vn_close(savacctp, FWRITE, NOCRED, p); savacctp = NULL; break; } (void)VFS_STATFS(savacctp->v_mount, &sb, NULL); if (sb.f_bavail > acctresume * sb.f_blocks / 100) { acctp = savacctp; savacctp = NULL; log(LOG_NOTICE, "Accounting resumed\n"); } } else if (acctp != NULL) { if (acctp->v_type == VBAD) { (void) vn_close(acctp, FWRITE, NOCRED, p); acctp = NULL; break; } (void)VFS_STATFS(acctp->v_mount, &sb, NULL); if (sb.f_bavail <= acctsuspend * sb.f_blocks / 100) { savacctp = acctp; acctp = NULL; log(LOG_NOTICE, "Accounting suspended\n"); } } else { break; } rwsleep_nsec(&acct_proc, &acct_lock, PPAUSE, "acct", SEC_TO_NSEC(acctrate)); } acct_proc = NULL; rw_exit_write(&acct_lock); kthread_exit(0); } void acct_shutdown(void) { struct proc *p = curproc; rw_enter_write(&acct_lock); if (acctp != NULL || savacctp != NULL) { vn_close((acctp != NULL ? acctp : savacctp), FWRITE, NOCRED, p); acctp = savacctp = NULL; } rw_exit_write(&acct_lock); }
18 2 2 6 3 3 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 /* $OpenBSD: uvm_swap_encrypt.c,v 1.24 2021/03/12 14:15:49 jsg Exp $ */ /* * Copyright 1999 Niels Provos <provos@citi.umich.edu> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Niels Provos. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/sysctl.h> #include <sys/time.h> #include <crypto/rijndael.h> #include <uvm/uvm.h> #include <uvm/uvm_swap_encrypt.h> struct swap_key *kcur = NULL; rijndael_ctx swap_ctxt; int uvm_doswapencrypt = 1; u_int uvm_swpkeyscreated = 0; u_int uvm_swpkeysdeleted = 0; int swap_encrypt_initialized = 0; int swap_encrypt_ctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { /* all sysctl names at this level are terminal */ if (namelen != 1) return (ENOTDIR); /* overloaded */ switch (name[0]) { case SWPENC_ENABLE: { int doencrypt = uvm_doswapencrypt; int result; result = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &doencrypt, 0, 1); if (result) return result; /* * Swap Encryption has been turned on, we need to * initialize state for swap devices that have been * added. */ if (doencrypt) uvm_swap_initcrypt_all(); uvm_doswapencrypt = doencrypt; return (0); } case SWPENC_CREATED: return (sysctl_rdint(oldp, oldlenp, newp, uvm_swpkeyscreated)); case SWPENC_DELETED: return (sysctl_rdint(oldp, oldlenp, newp, uvm_swpkeysdeleted)); default: return (EOPNOTSUPP); } /* NOTREACHED */ } void swap_key_create(struct swap_key *key) { arc4random_buf(key->key, sizeof(key->key)); uvm_swpkeyscreated++; } void swap_key_delete(struct swap_key *key) { /* Make sure that this key gets removed if we just used it */ swap_key_cleanup(key); explicit_bzero(key, sizeof(*key)); uvm_swpkeysdeleted++; } /* * Encrypt the data before it goes to swap, the size should be 64-bit * aligned. */ void swap_encrypt(struct swap_key *key, caddr_t src, caddr_t dst, u_int64_t block, size_t count) { u_int32_t *dsrc = (u_int32_t *)src; u_int32_t *ddst = (u_int32_t *)dst; u_int32_t iv[4]; u_int32_t iv1, iv2, iv3, iv4; if (!swap_encrypt_initialized) swap_encrypt_initialized = 1; swap_key_prepare(key, 1); count /= sizeof(u_int32_t); iv[0] = block >> 32; iv[1] = block; iv[2] = ~iv[0]; iv[3] = ~iv[1]; rijndael_encrypt(&swap_ctxt, (u_char *)iv, (u_char *)iv); iv1 = iv[0]; iv2 = iv[1]; iv3 = iv[2]; iv4 = iv[3]; for (; count > 0; count -= 4) { ddst[0] = dsrc[0] ^ iv1; ddst[1] = dsrc[1] ^ iv2; ddst[2] = dsrc[2] ^ iv3; ddst[3] = dsrc[3] ^ iv4; /* * Do not worry about endianness, it only needs to decrypt * on this machine. */ rijndael_encrypt(&swap_ctxt, (u_char *)ddst, (u_char *)ddst); iv1 = ddst[0]; iv2 = ddst[1]; iv3 = ddst[2]; iv4 = ddst[3]; dsrc += 4; ddst += 4; } } /* * Decrypt the data after we retrieved it from swap, the size should be 64-bit * aligned. */ void swap_decrypt(struct swap_key *key, caddr_t src, caddr_t dst, u_int64_t block, size_t count) { u_int32_t *dsrc = (u_int32_t *)src; u_int32_t *ddst = (u_int32_t *)dst; u_int32_t iv[4]; u_int32_t iv1, iv2, iv3, iv4, niv1, niv2, niv3, niv4; if (!swap_encrypt_initialized) panic("swap_decrypt: key not initialized"); swap_key_prepare(key, 0); count /= sizeof(u_int32_t); iv[0] = block >> 32; iv[1] = block; iv[2] = ~iv[0]; iv[3] = ~iv[1]; rijndael_encrypt(&swap_ctxt, (u_char *)iv, (u_char *)iv); iv1 = iv[0]; iv2 = iv[1]; iv3 = iv[2]; iv4 = iv[3]; for (; count > 0; count -= 4) { ddst[0] = niv1 = dsrc[0]; ddst[1] = niv2 = dsrc[1]; ddst[2] = niv3 = dsrc[2]; ddst[3] = niv4 = dsrc[3]; rijndael_decrypt(&swap_ctxt, (u_char *)ddst, (u_char *)ddst); ddst[0] ^= iv1; ddst[1] ^= iv2; ddst[2] ^= iv3; ddst[3] ^= iv4; iv1 = niv1; iv2 = niv2; iv3 = niv3; iv4 = niv4; dsrc += 4; ddst += 4; } } void swap_key_prepare(struct swap_key *key, int encrypt) { /* * Check if we have prepared for this key already, * if we only have the encryption schedule, we have * to recompute and get the decryption schedule also. */ if (kcur == key && (encrypt || !swap_ctxt.enc_only)) return; if (encrypt) rijndael_set_key_enc_only(&swap_ctxt, (u_char *)key->key, sizeof(key->key) * 8); else rijndael_set_key(&swap_ctxt, (u_char *)key->key, sizeof(key->key) * 8); kcur = key; } /* * Make sure that a specific key is no longer available. */ void swap_key_cleanup(struct swap_key *key) { /* Check if we have a key */ if (kcur == NULL || kcur != key) return; /* Zero out the subkeys */ explicit_bzero(&swap_ctxt, sizeof(swap_ctxt)); kcur = NULL; }
1 67 10 67 48 65 10 67 1 11 63 63 2 5 66 67 2 1 67 1 7 67 62 8 12 3 3 2 4 5 62 3 4 11 4 10 36 47 47 20 63 20 48 63 2 65 65 3 1 11 12 5 11 12 12 53 4 4 30 29 65 64 63 9 65 2 64 65 65 63 5 62 63 2 2 63 14 5 45 45 5 63 11 7 60 63 12 60 2 63 4 2 58 6 63 34 29 60 4 8 19 16 34 40 18 28 41 1 175 175 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 /* $OpenBSD: tcp_output.c,v 1.145 2024/05/14 09:39:02 bluhm Exp $ */ /* $NetBSD: tcp_output.c,v 1.16 1997/06/03 16:17:09 kml Exp $ */ /* * Copyright (c) 1982, 1986, 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 * * NRL grants permission for redistribution and use in source and binary * forms, with or without modification, of the software and documentation * created at NRL provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgements: * This product includes software developed by the University of * California, Berkeley and its contributors. * This product includes software developed at the Information * Technology Division, US Naval Research Laboratory. * 4. Neither the name of the NRL nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the US Naval * Research Laboratory (NRL). */ #include "pf.h" #include "stoeplitz.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/protosw.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/kernel.h> #include <net/if.h> #include <net/if_var.h> #include <net/route.h> #if NPF > 0 #include <net/pfvar.h> #endif #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/in_pcb.h> #include <netinet/ip_var.h> #include <netinet6/ip6_var.h> #include <netinet/tcp.h> #define TCPOUTFLAGS #include <netinet/tcp_fsm.h> #include <netinet/tcp_seq.h> #include <netinet/tcp_timer.h> #include <netinet/tcp_var.h> #include <netinet/tcp_debug.h> #ifdef notyet extern struct mbuf *m_copypack(); #endif extern int tcprexmtthresh; #ifdef TCP_SACK_DEBUG void tcp_print_holes(struct tcpcb *tp); void tcp_print_holes(struct tcpcb *tp) { struct sackhole *p = tp->snd_holes; if (p == NULL) return; printf("Hole report: start--end dups rxmit\n"); while (p) { printf("%x--%x d %d r %x\n", p->start, p->end, p->dups, p->rxmit); p = p->next; } printf("\n"); } #endif /* TCP_SACK_DEBUG */ /* * Returns pointer to a sackhole if there are any pending retransmissions; * NULL otherwise. */ struct sackhole * tcp_sack_output(struct tcpcb *tp) { struct sackhole *p; if (!tp->sack_enable) return (NULL); p = tp->snd_holes; while (p) { if (p->dups >= tcprexmtthresh && SEQ_LT(p->rxmit, p->end)) { if (SEQ_LT(p->rxmit, tp->snd_una)) {/* old SACK hole */ p = p->next; continue; } #ifdef TCP_SACK_DEBUG if (p) tcp_print_holes(tp); #endif return (p); } p = p->next; } return (NULL); } /* * After a timeout, the SACK list may be rebuilt. This SACK information * should be used to avoid retransmitting SACKed data. This function * traverses the SACK list to see if snd_nxt should be moved forward. */ void tcp_sack_adjust(struct tcpcb *tp) { struct sackhole *cur = tp->snd_holes; if (cur == NULL) return; /* No holes */ if (SEQ_GEQ(tp->snd_nxt, tp->rcv_lastsack)) return; /* We're already beyond any SACKed blocks */ /* * Two cases for which we want to advance snd_nxt: * i) snd_nxt lies between end of one hole and beginning of another * ii) snd_nxt lies between end of last hole and rcv_lastsack */ while (cur->next) { if (SEQ_LT(tp->snd_nxt, cur->end)) return; if (SEQ_GEQ(tp->snd_nxt, cur->next->start)) cur = cur->next; else { tp->snd_nxt = cur->next->start; return; } } if (SEQ_LT(tp->snd_nxt, cur->end)) return; tp->snd_nxt = tp->rcv_lastsack; return; } /* * Tcp output routine: figure out what should be sent and send it. */ int tcp_output(struct tcpcb *tp) { struct socket *so = tp->t_inpcb->inp_socket; long len, win, txmaxseg; int off, flags, error; struct mbuf *m; struct tcphdr *th; u_int32_t optbuf[howmany(MAX_TCPOPTLEN, sizeof(u_int32_t))]; u_char *opt = (u_char *)optbuf; unsigned int optlen, hdrlen, packetlen; int idle, sendalot = 0; int i, sack_rxmit = 0; struct sackhole *p; uint64_t now; #ifdef TCP_SIGNATURE unsigned int sigoff; #endif /* TCP_SIGNATURE */ #ifdef TCP_ECN int needect; #endif int tso; if (tp->t_flags & TF_BLOCKOUTPUT) { tp->t_flags |= TF_NEEDOUTPUT; return (0); } else tp->t_flags &= ~TF_NEEDOUTPUT; #if defined(TCP_SIGNATURE) && defined(DIAGNOSTIC) if (tp->sack_enable && (tp->t_flags & TF_SIGNATURE)) return (EINVAL); #endif /* defined(TCP_SIGNATURE) && defined(DIAGNOSTIC) */ now = tcp_now(); /* * Determine length of data that should be transmitted, * and flags that will be used. * If there is some data or critical controls (SYN, RST) * to send, then transmit; otherwise, investigate further. */ idle = (tp->t_flags & TF_LASTIDLE) || (tp->snd_max == tp->snd_una); if (idle && (now - tp->t_rcvtime) >= tp->t_rxtcur) /* * We have been idle for "a while" and no acks are * expected to clock out any data we send -- * slow start to get ack "clock" running again. */ tp->snd_cwnd = 2 * tp->t_maxseg; /* remember 'idle' for next invocation of tcp_output */ if (idle && soissending(so)) { tp->t_flags |= TF_LASTIDLE; idle = 0; } else tp->t_flags &= ~TF_LASTIDLE; again: /* * If we've recently taken a timeout, snd_max will be greater than * snd_nxt. There may be SACK information that allows us to avoid * resending already delivered data. Adjust snd_nxt accordingly. */ if (tp->sack_enable && SEQ_LT(tp->snd_nxt, tp->snd_max)) tcp_sack_adjust(tp); off = tp->snd_nxt - tp->snd_una; win = ulmin(tp->snd_wnd, tp->snd_cwnd); flags = tcp_outflags[tp->t_state]; /* * Send any SACK-generated retransmissions. If we're explicitly trying * to send out new data (when sendalot is 1), bypass this function. * If we retransmit in fast recovery mode, decrement snd_cwnd, since * we're replacing a (future) new transmission with a retransmission * now, and we previously incremented snd_cwnd in tcp_input(). */ if (tp->sack_enable && !sendalot) { if (tp->t_dupacks >= tcprexmtthresh && (p = tcp_sack_output(tp))) { off = p->rxmit - tp->snd_una; sack_rxmit = 1; /* Coalesce holes into a single retransmission */ len = min(tp->t_maxseg, p->end - p->rxmit); if (SEQ_LT(tp->snd_una, tp->snd_last)) tp->snd_cwnd -= tp->t_maxseg; } } sendalot = 0; tso = 0; /* * If in persist timeout with window of 0, send 1 byte. * Otherwise, if window is small but nonzero * and timer expired, we will send what we can * and go to transmit state. */ if (tp->t_force) { if (win == 0) { /* * If we still have some data to send, then * clear the FIN bit. Usually this would * happen below when it realizes that we * aren't sending all the data. However, * if we have exactly 1 byte of unset data, * then it won't clear the FIN bit below, * and if we are in persist state, we wind * up sending the packet without recording * that we sent the FIN bit. * * We can't just blindly clear the FIN bit, * because if we don't have any more data * to send then the probe will be the FIN * itself. */ if (off < so->so_snd.sb_cc) flags &= ~TH_FIN; win = 1; } else { TCP_TIMER_DISARM(tp, TCPT_PERSIST); tp->t_rxtshift = 0; } } if (!sack_rxmit) { len = ulmin(so->so_snd.sb_cc, win) - off; } if (len < 0) { /* * If FIN has been sent but not acked, * but we haven't been called to retransmit, * len will be -1. Otherwise, window shrank * after we sent into it. If window shrank to 0, * cancel pending retransmit, pull snd_nxt back * to (closed) window, and set the persist timer * if it isn't already going. If the window didn't * close completely, just wait for an ACK. */ len = 0; if (win == 0) { TCP_TIMER_DISARM(tp, TCPT_REXMT); tp->t_rxtshift = 0; tp->snd_nxt = tp->snd_una; if (TCP_TIMER_ISARMED(tp, TCPT_PERSIST) == 0) tcp_setpersist(tp); } } /* * Never send more than half a buffer full. This insures that we can * always keep 2 packets on the wire, no matter what SO_SNDBUF is, and * therefore acks will never be delayed unless we run out of data to * transmit. */ txmaxseg = ulmin(so->so_snd.sb_hiwat / 2, tp->t_maxseg); if (len > txmaxseg) { if (tcp_do_tso && tp->t_inpcb->inp_options == NULL && tp->t_inpcb->inp_outputopts6 == NULL && #ifdef TCP_SIGNATURE ((tp->t_flags & TF_SIGNATURE) == 0) && #endif len >= 2 * tp->t_maxseg && tp->rcv_numsacks == 0 && sack_rxmit == 0 && !(flags & (TH_SYN|TH_RST|TH_FIN))) { tso = 1; /* avoid small chopped packets */ if (len > (len / tp->t_maxseg) * tp->t_maxseg) { len = (len / tp->t_maxseg) * tp->t_maxseg; sendalot = 1; } } else { len = txmaxseg; sendalot = 1; } } if (off + len < so->so_snd.sb_cc) flags &= ~TH_FIN; win = sbspace(so, &so->so_rcv); /* * Sender silly window avoidance. If connection is idle * and can send all data, a maximum segment, * at least a maximum default-size segment do it, * or are forced, do it; otherwise don't bother. * If peer's buffer is tiny, then send * when window is at least half open. * If retransmitting (possibly after persist timer forced us * to send into a small window), then must resend. */ if (len) { if (len >= txmaxseg) goto send; if ((idle || (tp->t_flags & TF_NODELAY)) && len + off >= so->so_snd.sb_cc && !soissending(so) && (tp->t_flags & TF_NOPUSH) == 0) goto send; if (tp->t_force) goto send; if (len >= tp->max_sndwnd / 2 && tp->max_sndwnd > 0) goto send; if (SEQ_LT(tp->snd_nxt, tp->snd_max)) goto send; if (sack_rxmit) goto send; } /* * Compare available window to amount of window * known to peer (as advertised window less * next expected input). If the difference is at least two * max size segments, or at least 50% of the maximum possible * window, then want to send a window update to peer. */ if (win > 0) { /* * "adv" is the amount we can increase the window, * taking into account that we are limited by * TCP_MAXWIN << tp->rcv_scale. */ long adv = lmin(win, (long)TCP_MAXWIN << tp->rcv_scale) - (tp->rcv_adv - tp->rcv_nxt); if (adv >= (long) (2 * tp->t_maxseg)) goto send; if (2 * adv >= (long) so->so_rcv.sb_hiwat) goto send; } /* * Send if we owe peer an ACK. */ if (tp->t_flags & TF_ACKNOW) goto send; if (flags & (TH_SYN|TH_RST)) goto send; if (SEQ_GT(tp->snd_up, tp->snd_una)) goto send; /* * If our state indicates that FIN should be sent * and we have not yet done so, or we're retransmitting the FIN, * then we need to send. */ if (flags & TH_FIN && ((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una)) goto send; /* * In SACK, it is possible for tcp_output to fail to send a segment * after the retransmission timer has been turned off. Make sure * that the retransmission timer is set. */ if (SEQ_GT(tp->snd_max, tp->snd_una) && TCP_TIMER_ISARMED(tp, TCPT_REXMT) == 0 && TCP_TIMER_ISARMED(tp, TCPT_PERSIST) == 0) { TCP_TIMER_ARM(tp, TCPT_REXMT, tp->t_rxtcur); return (0); } /* * TCP window updates are not reliable, rather a polling protocol * using ``persist'' packets is used to insure receipt of window * updates. The three ``states'' for the output side are: * idle not doing retransmits or persists * persisting to move a small or zero window * (re)transmitting and thereby not persisting * * tp->t_timer[TCPT_PERSIST] * is set when we are in persist state. * tp->t_force * is set when we are called to send a persist packet. * tp->t_timer[TCPT_REXMT] * is set when we are retransmitting * The output side is idle when both timers are zero. * * If send window is too small, there is data to transmit, and no * retransmit or persist is pending, then go to persist state. * If nothing happens soon, send when timer expires: * if window is nonzero, transmit what we can, * otherwise force out a byte. */ if (so->so_snd.sb_cc && TCP_TIMER_ISARMED(tp, TCPT_REXMT) == 0 && TCP_TIMER_ISARMED(tp, TCPT_PERSIST) == 0) { tp->t_rxtshift = 0; tcp_setpersist(tp); } /* * No reason to send a segment, just return. */ return (0); send: /* * Before ESTABLISHED, force sending of initial options * unless TCP set not to do any options. * NOTE: we assume that the IP/TCP header plus TCP options * always fit in a single mbuf, leaving room for a maximum * link header, i.e. * max_linkhdr + sizeof(network header) + sizeof(struct tcphdr + * optlen <= MHLEN */ optlen = 0; switch (tp->pf) { case 0: /*default to PF_INET*/ case PF_INET: hdrlen = sizeof(struct ip) + sizeof(struct tcphdr); break; #ifdef INET6 case PF_INET6: hdrlen = sizeof(struct ip6_hdr) + sizeof(struct tcphdr); break; #endif /* INET6 */ default: return (EPFNOSUPPORT); } if (flags & TH_SYN) { tp->snd_nxt = tp->iss; if ((tp->t_flags & TF_NOOPT) == 0) { u_int16_t mss; opt[0] = TCPOPT_MAXSEG; opt[1] = 4; mss = htons((u_int16_t) tcp_mss(tp, 0)); memcpy(opt + 2, &mss, sizeof(mss)); optlen = 4; if (flags & TH_ACK) tcp_mss_update(tp); /* * If this is the first SYN of connection (not a SYN * ACK), include SACK_PERMIT_HDR option. If this is a * SYN ACK, include SACK_PERMIT_HDR option if peer has * already done so. */ if (tp->sack_enable && ((flags & TH_ACK) == 0 || (tp->t_flags & TF_SACK_PERMIT))) { *((u_int32_t *) (opt + optlen)) = htonl(TCPOPT_SACK_PERMIT_HDR); optlen += 4; } if ((tp->t_flags & TF_REQ_SCALE) && ((flags & TH_ACK) == 0 || (tp->t_flags & TF_RCVD_SCALE))) { *((u_int32_t *) (opt + optlen)) = htonl( TCPOPT_NOP << 24 | TCPOPT_WINDOW << 16 | TCPOLEN_WINDOW << 8 | tp->request_r_scale); optlen += 4; } } } /* * Send a timestamp and echo-reply if this is a SYN and our side * wants to use timestamps (TF_REQ_TSTMP is set) or both our side * and our peer have sent timestamps in our SYN's. */ if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP && (flags & TH_RST) == 0 && ((flags & (TH_SYN|TH_ACK)) == TH_SYN || (tp->t_flags & TF_RCVD_TSTMP))) { u_int32_t *lp = (u_int32_t *)(opt + optlen); /* Form timestamp option as shown in appendix A of RFC 1323. */ *lp++ = htonl(TCPOPT_TSTAMP_HDR); *lp++ = htonl(now + tp->ts_modulate); *lp = htonl(tp->ts_recent); optlen += TCPOLEN_TSTAMP_APPA; } /* Set receive buffer autosizing timestamp. */ if (tp->rfbuf_ts == 0) { tp->rfbuf_ts = now; tp->rfbuf_cnt = 0; } #ifdef TCP_SIGNATURE if (tp->t_flags & TF_SIGNATURE) { u_int8_t *bp = (u_int8_t *)(opt + optlen); /* Send signature option */ *(bp++) = TCPOPT_SIGNATURE; *(bp++) = TCPOLEN_SIGNATURE; sigoff = optlen + 2; { unsigned int i; for (i = 0; i < 16; i++) *(bp++) = 0; } /* Pad options list to the next 32 bit boundary and * terminate it. */ *bp++ = TCPOPT_NOP; *bp++ = TCPOPT_NOP; optlen += TCPOLEN_SIGLEN; } #endif /* TCP_SIGNATURE */ /* * Send SACKs if necessary. This should be the last option processed. * Only as many SACKs are sent as are permitted by the maximum options * size. No more than three SACKs are sent. */ if (tp->sack_enable && tp->t_state == TCPS_ESTABLISHED && (tp->t_flags & (TF_SACK_PERMIT|TF_NOOPT)) == TF_SACK_PERMIT && tp->rcv_numsacks) { u_int32_t *lp = (u_int32_t *)(opt + optlen); u_int32_t *olp = lp++; int count = 0; /* actual number of SACKs inserted */ int maxsack = (MAX_TCPOPTLEN - (optlen + 4))/TCPOLEN_SACK; tcpstat_inc(tcps_sack_snd_opts); maxsack = min(maxsack, TCP_MAX_SACK); for (i = 0; (i < tp->rcv_numsacks && count < maxsack); i++) { struct sackblk sack = tp->sackblks[i]; if (sack.start == 0 && sack.end == 0) continue; *lp++ = htonl(sack.start); *lp++ = htonl(sack.end); count++; } *olp = htonl(TCPOPT_SACK_HDR|(TCPOLEN_SACK*count+2)); optlen += TCPOLEN_SACK*count + 4; /* including leading NOPs */ } #ifdef DIAGNOSTIC if (optlen > MAX_TCPOPTLEN) panic("tcp_output: options too long"); #endif /* DIAGNOSTIC */ hdrlen += optlen; /* * Adjust data length if insertion of options will * bump the packet length beyond the t_maxopd length. * Clear the FIN bit because we cut off the tail of * the segment. */ if (len > tp->t_maxopd - optlen) { if (tso) { if (len + hdrlen + max_linkhdr > MAXMCLBYTES) { len = MAXMCLBYTES - hdrlen - max_linkhdr; sendalot = 1; } } else { len = tp->t_maxopd - optlen; sendalot = 1; } flags &= ~TH_FIN; } #ifdef DIAGNOSTIC if (max_linkhdr + hdrlen > MCLBYTES) panic("tcphdr too big"); #endif /* * Grab a header mbuf, attaching a copy of data to * be transmitted, and initialize the header from * the template for sends on this connection. */ if (len) { if (tp->t_force && len == 1) tcpstat_inc(tcps_sndprobe); else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) { tcpstat_pkt(tcps_sndrexmitpack, tcps_sndrexmitbyte, len); tp->t_sndrexmitpack++; } else { tcpstat_pkt(tcps_sndpack, tcps_sndbyte, len); } #ifdef notyet if ((m = m_copypack(so->so_snd.sb_mb, off, (int)len, max_linkhdr + hdrlen)) == 0) { error = ENOBUFS; goto out; } /* * m_copypack left space for our hdr; use it. */ m->m_len += hdrlen; m->m_data -= hdrlen; #else MGETHDR(m, M_DONTWAIT, MT_HEADER); if (m != NULL && max_linkhdr + hdrlen > MHLEN) { MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { m_freem(m); m = NULL; } } if (m == NULL) { error = ENOBUFS; goto out; } m->m_data += max_linkhdr; m->m_len = hdrlen; if (len <= m_trailingspace(m)) { m_copydata(so->so_snd.sb_mb, off, (int) len, mtod(m, caddr_t) + hdrlen); m->m_len += len; } else { m->m_next = m_copym(so->so_snd.sb_mb, off, (int) len, M_NOWAIT); if (m->m_next == 0) { (void) m_free(m); error = ENOBUFS; goto out; } } if (so->so_snd.sb_mb->m_flags & M_PKTHDR) m->m_pkthdr.ph_loopcnt = so->so_snd.sb_mb->m_pkthdr.ph_loopcnt; #endif /* * If we're sending everything we've got, set PUSH. * (This will keep happy those implementations which only * give data to the user when a buffer fills or * a PUSH comes in.) */ if (off + len == so->so_snd.sb_cc && !soissending(so)) flags |= TH_PUSH; tp->t_sndtime = now; } else { if (tp->t_flags & TF_ACKNOW) tcpstat_inc(tcps_sndacks); else if (flags & (TH_SYN|TH_FIN|TH_RST)) tcpstat_inc(tcps_sndctrl); else if (SEQ_GT(tp->snd_up, tp->snd_una)) tcpstat_inc(tcps_sndurg); else tcpstat_inc(tcps_sndwinup); MGETHDR(m, M_DONTWAIT, MT_HEADER); if (m != NULL && max_linkhdr + hdrlen > MHLEN) { MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { m_freem(m); m = NULL; } } if (m == NULL) { error = ENOBUFS; goto out; } m->m_data += max_linkhdr; m->m_len = hdrlen; } m->m_pkthdr.ph_ifidx = 0; m->m_pkthdr.len = hdrlen + len; /* Enable TSO and specify the size of the resulting segments. */ if (tso) { SET(m->m_pkthdr.csum_flags, M_TCP_TSO); m->m_pkthdr.ph_mss = tp->t_maxseg; } if (!tp->t_template) panic("tcp_output"); #ifdef DIAGNOSTIC if (tp->t_template->m_len != hdrlen - optlen) panic("tcp_output: template len != hdrlen - optlen"); #endif /* DIAGNOSTIC */ memcpy(mtod(m, caddr_t), mtod(tp->t_template, caddr_t), tp->t_template->m_len); th = (struct tcphdr *)(mtod(m, caddr_t) + tp->t_template->m_len - sizeof(struct tcphdr)); /* * Fill in fields, remembering maximum advertised * window for use in delaying messages about window sizes. * If resending a FIN, be sure not to use a new sequence number. */ if ((flags & TH_FIN) && (tp->t_flags & TF_SENTFIN) && (tp->snd_nxt == tp->snd_max)) tp->snd_nxt--; /* * If we are doing retransmissions, then snd_nxt will * not reflect the first unsent octet. For ACK only * packets, we do not want the sequence number of the * retransmitted packet, we want the sequence number * of the next unsent octet. So, if there is no data * (and no SYN or FIN), use snd_max instead of snd_nxt * when filling in ti_seq. But if we are in persist * state, snd_max might reflect one byte beyond the * right edge of the window, so use snd_nxt in that * case, since we know we aren't doing a retransmission. * (retransmit and persist are mutually exclusive...) */ if (len || (flags & (TH_SYN|TH_FIN)) || TCP_TIMER_ISARMED(tp, TCPT_PERSIST)) th->th_seq = htonl(tp->snd_nxt); else th->th_seq = htonl(tp->snd_max); if (sack_rxmit) { /* * If sendalot was turned on (due to option stuffing), turn it * off. Properly set th_seq field. Advance the ret'x pointer * by len. */ if (sendalot) sendalot = 0; th->th_seq = htonl(p->rxmit); p->rxmit += len; tcpstat_pkt(tcps_sack_rexmits, tcps_sack_rexmit_bytes, len); } th->th_ack = htonl(tp->rcv_nxt); if (optlen) { memcpy(th + 1, opt, optlen); th->th_off = (sizeof (struct tcphdr) + optlen) >> 2; } #ifdef TCP_ECN if (tcp_do_ecn) { /* * if we have received congestion experienced segs, * set ECE bit. */ if (tp->t_flags & TF_RCVD_CE) { flags |= TH_ECE; tcpstat_inc(tcps_ecn_sndece); } if (!(tp->t_flags & TF_DISABLE_ECN)) { /* * if this is a SYN seg, set ECE and CWR. * set only ECE for SYN-ACK if peer supports ECN. */ if ((flags & (TH_SYN|TH_ACK)) == TH_SYN) flags |= (TH_ECE|TH_CWR); else if ((tp->t_flags & TF_ECN_PERMIT) && (flags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK)) flags |= TH_ECE; } /* * if we have reduced the congestion window, notify * the peer by setting CWR bit. */ if ((tp->t_flags & TF_ECN_PERMIT) && (tp->t_flags & TF_SEND_CWR)) { flags |= TH_CWR; tp->t_flags &= ~TF_SEND_CWR; tcpstat_inc(tcps_ecn_sndcwr); } } #endif th->th_flags = flags; /* * Calculate receive window. Don't shrink window, * but avoid silly window syndrome. */ if (win < (long)(so->so_rcv.sb_hiwat / 4) && win < (long)tp->t_maxseg) win = 0; if (win > (long)TCP_MAXWIN << tp->rcv_scale) win = (long)TCP_MAXWIN << tp->rcv_scale; if (win < (long)(int32_t)(tp->rcv_adv - tp->rcv_nxt)) win = (long)(int32_t)(tp->rcv_adv - tp->rcv_nxt); if (flags & TH_RST) win = 0; th->th_win = htons((u_int16_t) (win>>tp->rcv_scale)); if (th->th_win == 0) tp->t_sndzerowin++; if (SEQ_GT(tp->snd_up, tp->snd_nxt)) { u_int32_t urp = tp->snd_up - tp->snd_nxt; if (urp > IP_MAXPACKET) urp = IP_MAXPACKET; th->th_urp = htons((u_int16_t)urp); th->th_flags |= TH_URG; } else /* * If no urgent pointer to send, then we pull * the urgent pointer to the left edge of the send window * so that it doesn't drift into the send window on sequence * number wraparound. */ tp->snd_up = tp->snd_una; /* drag it along */ #ifdef TCP_SIGNATURE if (tp->t_flags & TF_SIGNATURE) { int iphlen; union sockaddr_union src, dst; struct tdb *tdb; bzero(&src, sizeof(union sockaddr_union)); bzero(&dst, sizeof(union sockaddr_union)); switch (tp->pf) { case 0: /*default to PF_INET*/ case AF_INET: iphlen = sizeof(struct ip); src.sa.sa_len = sizeof(struct sockaddr_in); src.sa.sa_family = AF_INET; src.sin.sin_addr = mtod(m, struct ip *)->ip_src; dst.sa.sa_len = sizeof(struct sockaddr_in); dst.sa.sa_family = AF_INET; dst.sin.sin_addr = mtod(m, struct ip *)->ip_dst; break; #ifdef INET6 case AF_INET6: iphlen = sizeof(struct ip6_hdr); src.sa.sa_len = sizeof(struct sockaddr_in6); src.sa.sa_family = AF_INET6; src.sin6.sin6_addr = mtod(m, struct ip6_hdr *)->ip6_src; dst.sa.sa_len = sizeof(struct sockaddr_in6); dst.sa.sa_family = AF_INET6; dst.sin6.sin6_addr = mtod(m, struct ip6_hdr *)->ip6_dst; break; #endif /* INET6 */ } tdb = gettdbbysrcdst(rtable_l2(tp->t_inpcb->inp_rtableid), 0, &src, &dst, IPPROTO_TCP); if (tdb == NULL) { m_freem(m); return (EPERM); } if (tcp_signature(tdb, tp->pf, m, th, iphlen, 0, mtod(m, caddr_t) + hdrlen - optlen + sigoff) < 0) { m_freem(m); tdb_unref(tdb); return (EINVAL); } tdb_unref(tdb); } #endif /* TCP_SIGNATURE */ /* Defer checksumming until later (ip_output() or hardware) */ m->m_pkthdr.csum_flags |= M_TCP_CSUM_OUT; /* * In transmit state, time the transmission and arrange for * the retransmit. In persist state, just set snd_max. */ if (tp->t_force == 0 || TCP_TIMER_ISARMED(tp, TCPT_PERSIST) == 0) { tcp_seq startseq = tp->snd_nxt; /* * Advance snd_nxt over sequence space of this segment. */ if (flags & (TH_SYN|TH_FIN)) { if (flags & TH_SYN) tp->snd_nxt++; if (flags & TH_FIN) { tp->snd_nxt++; tp->t_flags |= TF_SENTFIN; } } if (tp->sack_enable) { if (sack_rxmit && (p->rxmit != tp->snd_nxt)) { goto timer; } } tp->snd_nxt += len; if (SEQ_GT(tp->snd_nxt, tp->snd_max)) { tp->snd_max = tp->snd_nxt; /* * Time this transmission if not a retransmission and * not currently timing anything. */ if (tp->t_rtttime == 0) { tp->t_rtttime = now; tp->t_rtseq = startseq; tcpstat_inc(tcps_segstimed); } } /* * Set retransmit timer if not currently set, * and not doing an ack or a keep-alive probe. * Initial value for retransmit timer is smoothed * round-trip time + 2 * round-trip time variance. * Initialize shift counter which is used for backoff * of retransmit time. */ timer: if (tp->sack_enable && sack_rxmit && TCP_TIMER_ISARMED(tp, TCPT_REXMT) == 0 && tp->snd_nxt != tp->snd_max) { TCP_TIMER_ARM(tp, TCPT_REXMT, tp->t_rxtcur); if (TCP_TIMER_ISARMED(tp, TCPT_PERSIST)) { TCP_TIMER_DISARM(tp, TCPT_PERSIST); tp->t_rxtshift = 0; } } if (TCP_TIMER_ISARMED(tp, TCPT_REXMT) == 0 && tp->snd_nxt != tp->snd_una) { TCP_TIMER_ARM(tp, TCPT_REXMT, tp->t_rxtcur); if (TCP_TIMER_ISARMED(tp, TCPT_PERSIST)) { TCP_TIMER_DISARM(tp, TCPT_PERSIST); tp->t_rxtshift = 0; } } if (len == 0 && so->so_snd.sb_cc && TCP_TIMER_ISARMED(tp, TCPT_REXMT) == 0 && TCP_TIMER_ISARMED(tp, TCPT_PERSIST) == 0) { /* * Avoid a situation where we do not set persist timer * after a zero window condition. For example: * 1) A -> B: packet with enough data to fill the window * 2) B -> A: ACK for #1 + new data (0 window * advertisement) * 3) A -> B: ACK for #2, 0 len packet * * In this case, A will not activate the persist timer, * because it chose to send a packet. Unless tcp_output * is called for some other reason (delayed ack timer, * another input packet from B, socket syscall), A will * not send zero window probes. * * So, if you send a 0-length packet, but there is data * in the socket buffer, and neither the rexmt or * persist timer is already set, then activate the * persist timer. */ tp->t_rxtshift = 0; tcp_setpersist(tp); } } else if (SEQ_GT(tp->snd_nxt + len, tp->snd_max)) tp->snd_max = tp->snd_nxt + len; tcp_update_sndspace(tp); /* * Trace. */ if (so->so_options & SO_DEBUG) tcp_trace(TA_OUTPUT, tp->t_state, tp, tp, mtod(m, caddr_t), 0, len); /* * Fill in IP length and desired time to live and * send to IP level. There should be a better way * to handle ttl and tos; we could keep them in * the template, but need a way to checksum without them. */ #ifdef TCP_ECN /* * if peer is ECN capable, set the ECT bit in the IP header. * but don't set ECT for a pure ack, a retransmit or a window probe. */ needect = 0; if (tcp_do_ecn && (tp->t_flags & TF_ECN_PERMIT)) { if (len == 0 || SEQ_LT(tp->snd_nxt, tp->snd_max) || (tp->t_force && len == 1)) { /* don't set ECT */ } else { needect = 1; tcpstat_inc(tcps_ecn_sndect); } } #endif /* force routing table */ m->m_pkthdr.ph_rtableid = tp->t_inpcb->inp_rtableid; #if NPF > 0 pf_mbuf_link_inpcb(m, tp->t_inpcb); #endif switch (tp->pf) { case 0: /*default to PF_INET*/ case AF_INET: { struct ip *ip; ip = mtod(m, struct ip *); ip->ip_len = htons(m->m_pkthdr.len); packetlen = m->m_pkthdr.len; ip->ip_ttl = tp->t_inpcb->inp_ip.ip_ttl; ip->ip_tos = tp->t_inpcb->inp_ip.ip_tos; #ifdef TCP_ECN if (needect) ip->ip_tos |= IPTOS_ECN_ECT0; #endif } #if NSTOEPLITZ > 0 m->m_pkthdr.ph_flowid = tp->t_inpcb->inp_flowid; SET(m->m_pkthdr.csum_flags, M_FLOWID); #endif error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route, (ip_mtudisc ? IP_MTUDISC : 0), NULL, &tp->t_inpcb->inp_seclevel, 0); break; #ifdef INET6 case AF_INET6: { struct ip6_hdr *ip6; ip6 = mtod(m, struct ip6_hdr *); ip6->ip6_plen = m->m_pkthdr.len - sizeof(struct ip6_hdr); packetlen = m->m_pkthdr.len; ip6->ip6_nxt = IPPROTO_TCP; ip6->ip6_hlim = in6_selecthlim(tp->t_inpcb); #ifdef TCP_ECN if (needect) ip6->ip6_flow |= htonl(IPTOS_ECN_ECT0 << 20); #endif } error = ip6_output(m, tp->t_inpcb->inp_outputopts6, &tp->t_inpcb->inp_route, 0, NULL, &tp->t_inpcb->inp_seclevel); break; #endif /* INET6 */ } if (error) { out: if (error == ENOBUFS) { /* * If the interface queue is full, or IP cannot * get an mbuf, trigger TCP slow start. */ tp->snd_cwnd = tp->t_maxseg; return (0); } if (error == EMSGSIZE) { /* * ip_output() will have already fixed the route * for us. tcp_mtudisc() will, as its last action, * initiate retransmission, so it is important to * not do so here. */ tcp_mtudisc(tp->t_inpcb, -1); return (0); } if ((error == EHOSTUNREACH || error == ENETDOWN) && TCPS_HAVERCVDSYN(tp->t_state)) { tp->t_softerror = error; return (0); } /* Restart the delayed ACK timer, if necessary. */ if (TCP_TIMER_ISARMED(tp, TCPT_DELACK)) TCP_TIMER_ARM(tp, TCPT_DELACK, tcp_delack_msecs); return (error); } if (packetlen > tp->t_pmtud_mtu_sent) tp->t_pmtud_mtu_sent = packetlen; tcpstat_inc(tcps_sndtotal); if (TCP_TIMER_ISARMED(tp, TCPT_DELACK)) tcpstat_inc(tcps_delack); /* * Data sent (as far as we can tell). * If this advertises a larger window than any other segment, * then remember the size of the advertised window. * Any pending ACK has now been sent. */ if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv)) tp->rcv_adv = tp->rcv_nxt + win; tp->last_ack_sent = tp->rcv_nxt; tp->t_sndacktime = now; tp->t_flags &= ~TF_ACKNOW; TCP_TIMER_DISARM(tp, TCPT_DELACK); if (sendalot) goto again; return (0); } void tcp_setpersist(struct tcpcb *tp) { int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> (1 + TCP_RTT_BASE_SHIFT); int msec; if (TCP_TIMER_ISARMED(tp, TCPT_REXMT)) panic("tcp_output REXMT"); /* * Start/restart persistence timer. */ if (t < tp->t_rttmin) t = tp->t_rttmin; TCPT_RANGESET(msec, t * tcp_backoff[tp->t_rxtshift], TCPTV_PERSMIN, TCPTV_PERSMAX); TCP_TIMER_ARM(tp, TCPT_PERSIST, msec); if (tp->t_rxtshift < TCP_MAXRXTSHIFT) tp->t_rxtshift++; } int tcp_chopper(struct mbuf *m0, struct mbuf_list *ml, struct ifnet *ifp, u_int mss) { struct ip *ip = NULL; #ifdef INET6 struct ip6_hdr *ip6 = NULL; #endif struct tcphdr *th; int firstlen, iphlen, hlen, tlen, off; int error; ml_init(ml); ml_enqueue(ml, m0); if (mss == 0) { error = EINVAL; goto bad; } ip = mtod(m0, struct ip *); switch (ip->ip_v) { case 4: iphlen = ip->ip_hl << 2; if (ISSET(ip->ip_off, htons(IP_OFFMASK | IP_MF)) || iphlen != sizeof(struct ip) || ip->ip_p != IPPROTO_TCP) { /* only TCP without fragment or IP option supported */ error = EPROTOTYPE; goto bad; } break; #ifdef INET6 case 6: ip = NULL; ip6 = mtod(m0, struct ip6_hdr *); iphlen = sizeof(struct ip6_hdr); if (ip6->ip6_nxt != IPPROTO_TCP) { /* only TCP without IPv6 header chain supported */ error = EPROTOTYPE; goto bad; } break; #endif default: panic("%s: unknown ip version %d", __func__, ip->ip_v); } tlen = m0->m_pkthdr.len; if (tlen < iphlen + sizeof(struct tcphdr)) { error = ENOPROTOOPT; goto bad; } /* IP and TCP header should be contiguous, this check is paranoia */ if (m0->m_len < iphlen + sizeof(*th)) { ml_dequeue(ml); if ((m0 = m_pullup(m0, iphlen + sizeof(*th))) == NULL) { error = ENOBUFS; goto bad; } ml_enqueue(ml, m0); } th = (struct tcphdr *)(mtod(m0, caddr_t) + iphlen); hlen = iphlen + (th->th_off << 2); if (tlen < hlen) { error = ENOPROTOOPT; goto bad; } firstlen = MIN(tlen - hlen, mss); CLR(m0->m_pkthdr.csum_flags, M_TCP_TSO); /* * Loop through length of payload after first segment, * make new header and copy data of each part and link onto chain. */ for (off = hlen + firstlen; off < tlen; off += mss) { struct mbuf *m; struct tcphdr *mhth; int len; len = MIN(tlen - off, mss); MGETHDR(m, M_DONTWAIT, MT_HEADER); if (m == NULL) { error = ENOBUFS; goto bad; } ml_enqueue(ml, m); if ((error = m_dup_pkthdr(m, m0, M_DONTWAIT)) != 0) goto bad; /* IP and TCP header to the end, space for link layer header */ m->m_len = hlen; m_align(m, hlen); /* copy and adjust TCP header */ mhth = (struct tcphdr *)(mtod(m, caddr_t) + iphlen); memcpy(mhth, th, hlen - iphlen); mhth->th_seq = htonl(ntohl(th->th_seq) + (off - hlen)); if (off + len < tlen) CLR(mhth->th_flags, TH_PUSH|TH_FIN); /* add mbuf chain with payload */ m->m_pkthdr.len = hlen + len; if ((m->m_next = m_copym(m0, off, len, M_DONTWAIT)) == NULL) { error = ENOBUFS; goto bad; } /* copy and adjust IP header, calculate checksum */ SET(m->m_pkthdr.csum_flags, M_TCP_CSUM_OUT); if (ip) { struct ip *mhip; mhip = mtod(m, struct ip *); *mhip = *ip; mhip->ip_len = htons(hlen + len); mhip->ip_id = htons(ip_randomid()); in_hdr_cksum_out(m, ifp); in_proto_cksum_out(m, ifp); } #ifdef INET6 if (ip6) { struct ip6_hdr *mhip6; mhip6 = mtod(m, struct ip6_hdr *); *mhip6 = *ip6; mhip6->ip6_plen = htons(hlen - iphlen + len); in6_proto_cksum_out(m, ifp); } #endif } /* * Update first segment by trimming what's been copied out * and updating header, then send each segment (in order). */ if (hlen + firstlen < tlen) { m_adj(m0, hlen + firstlen - tlen); CLR(th->th_flags, TH_PUSH|TH_FIN); } /* adjust IP header, calculate checksum */ SET(m0->m_pkthdr.csum_flags, M_TCP_CSUM_OUT); if (ip) { ip->ip_len = htons(m0->m_pkthdr.len); in_hdr_cksum_out(m0, ifp); in_proto_cksum_out(m0, ifp); } #ifdef INET6 if (ip6) { ip6->ip6_plen = htons(m0->m_pkthdr.len - iphlen); in6_proto_cksum_out(m0, ifp); } #endif tcpstat_add(tcps_outpkttso, ml_len(ml)); return 0; bad: tcpstat_inc(tcps_outbadtso); ml_purge(ml); return error; } int tcp_if_output_tso(struct ifnet *ifp, struct mbuf **mp, struct sockaddr *dst, struct rtentry *rt, uint32_t ifcap, u_int mtu) { struct mbuf_list ml; int error; /* caller must fail later or fragment */ if (!ISSET((*mp)->m_pkthdr.csum_flags, M_TCP_TSO)) return 0; if ((*mp)->m_pkthdr.ph_mss > mtu) { CLR((*mp)->m_pkthdr.csum_flags, M_TCP_TSO); return 0; } /* network interface hardware will do TSO */ if (in_ifcap_cksum(*mp, ifp, ifcap)) { if (ISSET(ifcap, IFCAP_TSOv4)) { in_hdr_cksum_out(*mp, ifp); in_proto_cksum_out(*mp, ifp); } #ifdef INET6 if (ISSET(ifcap, IFCAP_TSOv6)) in6_proto_cksum_out(*mp, ifp); #endif error = ifp->if_output(ifp, *mp, dst, rt); if (!error) tcpstat_inc(tcps_outhwtso); goto done; } /* as fallback do TSO in software */ if ((error = tcp_chopper(*mp, &ml, ifp, (*mp)->m_pkthdr.ph_mss)) || (error = if_output_ml(ifp, &ml, dst, rt))) goto done; tcpstat_inc(tcps_outswtso); done: *mp = NULL; return error; }
1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 /* $OpenBSD: nvram.c,v 1.7 2016/08/03 17:29:18 jcs Exp $ */ /* * Copyright (c) 2004 Joshua Stein <jcs@openbsd.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/uio.h> #include <sys/fcntl.h> #include <sys/conf.h> #include <dev/ic/mc146818reg.h> /* checksum is calculated over bytes 2 to 31 and stored in byte 32 */ #define NVRAM_CSUM_START (MC_NVRAM_START + 2) #define NVRAM_CSUM_END (MC_NVRAM_START + 31) #define NVRAM_CSUM_LOC (MC_NVRAM_START + 32) #define NVRAM_SIZE (128 - MC_NVRAM_START) /* #define NVRAM_DEBUG 1 */ void nvramattach(int); int nvramopen(dev_t dev, int flag, int mode, struct proc *p); int nvramclose(dev_t dev, int flag, int mode, struct proc *p); int nvramread(dev_t dev, struct uio *uio, int flags); int nvram_csum_valid(void); int nvram_get_byte(int byteno); static int nvram_initialized; void nvramattach(int num) { if (num > 1) return; if (nvram_initialized || nvram_csum_valid()) { #ifdef NVRAM_DEBUG printf("nvram: initialized\n"); #endif nvram_initialized = 1; } } int nvramopen(dev_t dev, int flag, int mode, struct proc *p) { /* TODO: re-calc checksum on every open? */ if ((minor(dev) != 0) || (!nvram_initialized)) return (ENXIO); if ((flag & FWRITE)) return (EPERM); return (0); } int nvramclose(dev_t dev, int flag, int mode, struct proc *p) { return (0); } int nvramread(dev_t dev, struct uio *uio, int flags) { u_char buf[NVRAM_SIZE]; off_t pos = uio->uio_offset; u_char *tmp; size_t count = ulmin(sizeof(buf), uio->uio_resid); int ret; if (!nvram_initialized) return (ENXIO); if (uio->uio_offset < 0) return (EINVAL); if (uio->uio_resid == 0) return (0); #ifdef NVRAM_DEBUG printf("attempting to read %zu bytes at offset %lld\n", count, pos); #endif for (tmp = buf; count-- > 0 && pos < NVRAM_SIZE; ++pos, ++tmp) *tmp = nvram_get_byte(pos); #ifdef NVRAM_DEBUG printf("nvramread read %td bytes (%s)\n", (tmp - buf), tmp); #endif ret = uiomove(buf, (tmp - buf), uio); uio->uio_offset += uio->uio_resid; return (ret); } int nvram_get_byte(int byteno) { if (!nvram_initialized) return (ENXIO); return (mc146818_read(NULL, byteno + MC_NVRAM_START) & 0xff); } int nvram_csum_valid(void) { u_short csum = 0; u_short csumexpect; int nreg; for (nreg = NVRAM_CSUM_START; nreg <= NVRAM_CSUM_END; nreg++) csum += mc146818_read(NULL, nreg); csumexpect = mc146818_read(NULL, NVRAM_CSUM_LOC) << 8 | mc146818_read(NULL, NVRAM_CSUM_LOC + 1); #ifdef NVRAM_DEBUG printf("nvram: checksum is %x, expecting %x\n", (csum & 0xffff), csumexpect); #endif return ((csum & 0xffff) == csumexpect); }
10 9 2 1 5 5 11 9 4 3 2 5 2 1 1 2 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 /* $OpenBSD: mem.c,v 1.35 2021/03/24 14:26:39 bluhm Exp $ */ /* * Copyright (c) 1988 University of Utah. * Copyright (c) 1982, 1986, 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)mem.c 8.3 (Berkeley) 1/12/94 */ /* * Memory special file */ #include <sys/param.h> #include <sys/buf.h> #include <sys/filio.h> #include <sys/systm.h> #include <sys/uio.h> #include <sys/ioccom.h> #include <sys/malloc.h> #include <sys/memrange.h> #include <machine/cpu.h> #include <uvm/uvm_extern.h> caddr_t zeropage; extern int start, end, etext; /* open counter for aperture */ #ifdef APERTURE static int ap_open_count = 0; extern int allowaperture; #define VGA_START 0xA0000 #define BIOS_END 0xFFFFF #endif #ifdef MTRR struct mem_range_softc mem_range_softc; int mem_ioctl(dev_t, u_long, caddr_t, int, struct proc *); int mem_range_attr_get(struct mem_range_desc *, int *); int mem_range_attr_set(struct mem_range_desc *, int *); #endif int mmopen(dev_t dev, int flag, int mode, struct proc *p) { extern int allowkmem; switch (minor(dev)) { case 0: case 1: if (securelevel <= 0 || allowkmem) break; return (EPERM); case 2: case 12: break; #ifdef APERTURE case 4: if (suser(p) != 0 || !allowaperture) return (EPERM); /* authorize only one simultaneous open() unless * allowaperture=3 */ if (ap_open_count > 0 && allowaperture < 3) return (EPERM); ap_open_count++; break; #endif default: return (ENXIO); } return (0); } int mmclose(dev_t dev, int flag, int mode, struct proc *p) { #ifdef APERTURE if (minor(dev) == 4) ap_open_count = 0; #endif return (0); } int mmrw(dev_t dev, struct uio *uio, int flags) { extern vaddr_t kern_end; vaddr_t v; size_t c; struct iovec *iov; int error = 0; while (uio->uio_resid > 0 && error == 0) { iov = uio->uio_iov; if (iov->iov_len == 0) { uio->uio_iov++; uio->uio_iovcnt--; if (uio->uio_iovcnt < 0) panic("mmrw"); continue; } switch (minor(dev)) { /* minor device 0 is physical memory */ case 0: v = PMAP_DIRECT_MAP(uio->uio_offset); error = uiomove((caddr_t)v, uio->uio_resid, uio); continue; /* minor device 1 is kernel memory */ case 1: v = uio->uio_offset; c = ulmin(iov->iov_len, MAXPHYS); if (v >= (vaddr_t)&start && v < kern_end - c) { if (v < (vaddr_t)&etext - c && uio->uio_rw == UIO_WRITE) return EFAULT; } else if ((!uvm_kernacc((caddr_t)v, c, uio->uio_rw == UIO_READ ? B_READ : B_WRITE)) && (v < PMAP_DIRECT_BASE || v > PMAP_DIRECT_END - c)) return (EFAULT); error = uiomove((caddr_t)v, c, uio); continue; /* minor device 2 is /dev/null */ case 2: if (uio->uio_rw == UIO_WRITE) uio->uio_resid = 0; return (0); /* minor device 12 is /dev/zero */ case 12: if (uio->uio_rw == UIO_WRITE) { c = iov->iov_len; break; } if (zeropage == NULL) zeropage = malloc(PAGE_SIZE, M_TEMP, M_WAITOK|M_ZERO); c = ulmin(iov->iov_len, PAGE_SIZE); error = uiomove(zeropage, c, uio); continue; default: return (ENXIO); } iov->iov_base += c; iov->iov_len -= c; uio->uio_offset += c; uio->uio_resid -= c; } return (error); } paddr_t mmmmap(dev_t dev, off_t off, int prot) { struct proc *p = curproc; /* XXX */ switch (minor(dev)) { /* minor device 0 is physical memory */ case 0: if (suser(p) != 0 && amd64_pa_used(off)) return -1; return off; #ifdef APERTURE /* minor device 4 is aperture driver */ case 4: /* Check if a write combining mapping is requested. */ if (off >= MEMRANGE_WC_RANGE) off = (off - MEMRANGE_WC_RANGE) | PMAP_WC; switch (allowaperture) { case 1: /* Allow mapping of the VGA framebuffer & BIOS only */ if ((off >= VGA_START && off <= BIOS_END) || !amd64_pa_used(off)) return off; else return -1; case 2: case 3: /* Allow mapping of the whole 1st megabyte for x86emu */ if (off <= BIOS_END || !amd64_pa_used(off)) return off; else return -1; default: return -1; } #endif default: return -1; } } int mmioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) { switch (cmd) { case FIONBIO: case FIOASYNC: /* handled by fd layer */ return 0; } #ifdef MTRR switch (minor(dev)) { case 0: case 4: return mem_ioctl(dev, cmd, data, flags, p); } #endif return (ENODEV); } #ifdef MTRR /* * Operations for changing memory attributes. * * This is basically just an ioctl shim for mem_range_attr_get * and mem_range_attr_set. */ int mem_ioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) { int nd, error = 0; struct mem_range_op *mo = (struct mem_range_op *)data; struct mem_range_desc *md; /* is this for us? */ if ((cmd != MEMRANGE_GET) && (cmd != MEMRANGE_SET)) return (ENOTTY); /* any chance we can handle this? */ if (mem_range_softc.mr_op == NULL) return (EOPNOTSUPP); /* do we have any descriptors? */ if (mem_range_softc.mr_ndesc == 0) return (ENXIO); switch (cmd) { case MEMRANGE_GET: nd = imin(mo->mo_arg[0], mem_range_softc.mr_ndesc); if (nd > 0) { md = mallocarray(nd, sizeof(struct mem_range_desc), M_MEMDESC, M_WAITOK); error = mem_range_attr_get(md, &nd); if (!error) error = copyout(md, mo->mo_desc, nd * sizeof(struct mem_range_desc)); free(md, M_MEMDESC, nd * sizeof(struct mem_range_desc)); } else { nd = mem_range_softc.mr_ndesc; } mo->mo_arg[0] = nd; break; case MEMRANGE_SET: md = malloc(sizeof(struct mem_range_desc), M_MEMDESC, M_WAITOK); error = copyin(mo->mo_desc, md, sizeof(struct mem_range_desc)); /* clamp description string */ md->mr_owner[sizeof(md->mr_owner) - 1] = 0; if (error == 0) error = mem_range_attr_set(md, &mo->mo_arg[0]); free(md, M_MEMDESC, sizeof(struct mem_range_desc)); break; } return (error); } /* * Implementation-neutral, kernel-callable functions for manipulating * memory range attributes. */ int mem_range_attr_get(struct mem_range_desc *mrd, int *arg) { /* can we handle this? */ if (mem_range_softc.mr_op == NULL) return (EOPNOTSUPP); if (*arg == 0) { *arg = mem_range_softc.mr_ndesc; } else { memcpy(mrd, mem_range_softc.mr_desc, (*arg) * sizeof(struct mem_range_desc)); } return (0); } int mem_range_attr_set(struct mem_range_desc *mrd, int *arg) { /* can we handle this? */ if (mem_range_softc.mr_op == NULL) return (EOPNOTSUPP); return (mem_range_softc.mr_op->set(&mem_range_softc, mrd, arg)); } #endif /* MTRR */
1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 /* $OpenBSD: st.c,v 1.190 2023/04/27 18:21:44 robert Exp $ */ /* $NetBSD: st.c,v 1.71 1997/02/21 23:03:49 thorpej Exp $ */ /* * Copyright (c) 1994 Charles Hannum. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Charles Hannum. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Originally written by Julian Elischer (julian@tfs.com) * for TRW Financial Systems for use under the MACH(2.5) operating system. * * TRW Financial Systems, in accordance with their agreement with Carnegie * Mellon University, makes this software available to CMU to distribute * or use in any manner that they see fit as long as this message is kept with * the software. For this reason TFS also grants any other persons or * organisations permission to use or modify this software. * * TFS supplies this software to be publicly redistributed * on the understanding that TFS is not responsible for the correct * functioning of this software in any circumstances. * * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 * major changes by Julian Elischer (julian@jules.dialix.oz.au) May 1993 */ /* * To do: * work out some better way of guessing what a good timeout is going * to be depending on whether we expect to retension or not. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/timeout.h> #include <sys/fcntl.h> #include <sys/errno.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/pool.h> #include <sys/buf.h> #include <sys/mtio.h> #include <sys/device.h> #include <sys/disk.h> #include <sys/conf.h> #include <sys/vnode.h> #include <scsi/scsi_all.h> #include <scsi/scsi_debug.h> #include <scsi/scsi_tape.h> #include <scsi/scsiconf.h> /* Defines for device specific stuff */ #define DEF_FIXED_BSIZE 512 #define STMODE(z) ( minor(z) & 0x03) #define STUNIT(z) ((minor(z) >> 4) ) #define STMINOR(unit, mode) (((unit) << 4) + (mode)) #define MAXSTMODES 16 /* Old max retained so minor's don't change. */ #define ST_IO_TIME (3 * 60 * 1000) /* 3 minutes */ #define ST_CTL_TIME (30 * 1000) /* 30 seconds */ #define ST_SPC_TIME (4 * 60 * 60 * 1000) /* 4 hours */ /* * Maximum density code allowed in SCSI spec (SSC2R08f, Section 8.3). */ #define SCSI_MAX_DENSITY_CODE 0xff /* * Define various devices that we know mis-behave in some way, * and note how they are bad, so we can correct for them */ struct mode { int blksize; u_int8_t density; }; struct quirkdata { u_int quirks; #define ST_Q_SENSE_HELP 0x0001 /* must do READ for good MODE SENSE */ #define ST_Q_IGNORE_LOADS 0x0002 #define ST_Q_UNIMODAL 0x0004 /* unimode drive rejects mode select */ struct mode mode; }; struct st_quirk_inquiry_pattern { struct scsi_inquiry_pattern pattern; struct quirkdata quirkdata; }; const struct st_quirk_inquiry_pattern st_quirk_patterns[] = { {{T_SEQUENTIAL, T_REMOV, " ", " ", " "}, {0, {512, 0}}}, {{T_SEQUENTIAL, T_REMOV, "TANDBERG", " TDC 3800 ", ""}, {0, {512, 0}}}, {{T_SEQUENTIAL, T_REMOV, "ARCHIVE ", "VIPER 2525 25462", ""}, {ST_Q_SENSE_HELP, {0, 0}}}, {{T_SEQUENTIAL, T_REMOV, "SANKYO ", "CP525 ", ""}, {0, {512, 0}}}, {{T_SEQUENTIAL, T_REMOV, "ANRITSU ", "DMT780 ", ""}, {0, {512, 0}}}, {{T_SEQUENTIAL, T_REMOV, "ARCHIVE ", "VIPER 150 21531", ""}, {ST_Q_SENSE_HELP, {0, 0}}}, {{T_SEQUENTIAL, T_REMOV, "WANGTEK ", "5099ES SCSI", ""}, {0, {512, 0}}}, {{T_SEQUENTIAL, T_REMOV, "WANGTEK ", "5150ES SCSI", ""}, {0, {512, 0}}}, {{T_SEQUENTIAL, T_REMOV, "HP ", "T4000s ", ""}, {ST_Q_UNIMODAL, {0, QIC_3095}}}, {{T_SEQUENTIAL, T_REMOV, "WANGTEK ", "5150ES SCSI FA15", "01 A"}, {ST_Q_IGNORE_LOADS, {0, 0}}}, {{T_SEQUENTIAL, T_REMOV, "TEAC ", "MT-2ST/N50 ", ""}, {ST_Q_IGNORE_LOADS, {0, 0}}}, }; #define NOEJECT 0 #define EJECT 1 #define NOREWIND 0 #define DOREWIND 1 struct st_softc { struct device sc_dev; struct disk sc_dk; int flags; #define ST_INFO_VALID 0x00000001 #define ST_WRITTEN 0x00000004 #define ST_FIXEDBLOCKS 0x00000008 #define ST_AT_FILEMARK 0x00000010 #define ST_EIO_PENDING 0x00000020 #define ST_EOM_PENDING 0x00000040 #define ST_EOD_DETECTED 0x00000080 #define ST_FM_WRITTEN 0x00000100 #define ST_BLANK_READ 0x00000200 #define ST_2FM_AT_EOD 0x00000400 #define ST_MOUNTED 0x00000800 #define ST_DONTBUFFER 0x00001000 #define ST_DYING 0x00004000 #define ST_BOD_DETECTED 0x00008000 #define ST_MODE_DENSITY 0x00010000 #define ST_MODE_BLKSIZE 0x00040000 u_int quirks; /* quirks for the open mode */ int blksize; /* blksize we are using */ u_int8_t density; /* present density */ short mt_resid; /* last (short) resid */ short mt_erreg; /* last error (sense key) seen */ struct scsi_link *sc_link; /* our link to the adapter etc. */ int blkmin; /* min blk size */ int blkmax; /* max blk size */ u_int32_t media_blksize; /* 0 if not ST_FIXEDBLOCKS */ u_int32_t media_density; /* this is what it said when asked */ int media_fileno; /* relative to BOT. -1 means unknown. */ int media_blkno; /* relative to BOF. -1 means unknown. */ int media_eom; /* relative to BOT. -1 means unknown. */ struct mode mode; struct bufq sc_bufq; struct scsi_xshandler sc_xsh; }; int stmatch(struct device *, void *, void *); void stattach(struct device *, struct device *, void *); int stactivate(struct device *, int); int stdetach(struct device *, int); void stminphys(struct buf *); void ststart(struct scsi_xfer *); int st_mount_tape(struct st_softc *, int); void st_unmount(struct st_softc *, int, int); int st_decide_mode(struct st_softc *, int); void st_buf_done(struct scsi_xfer *); int st_read(struct st_softc *, char *, int, int); int st_read_block_limits(struct st_softc *, int); int st_mode_sense(struct st_softc *, int); int st_mode_select(struct st_softc *, int); int st_space(struct st_softc *, int, u_int, int); int st_write_filemarks(struct st_softc *, int, int); int st_check_eod(struct st_softc *, int, int *, int); int st_load(struct st_softc *, u_int, int); int st_rewind(struct st_softc *, u_int, int); int st_interpret_sense(struct scsi_xfer *); int st_touch_tape(struct st_softc *); int st_erase(struct st_softc *, int, int); const struct cfattach st_ca = { sizeof(struct st_softc), stmatch, stattach, stdetach, stactivate }; struct cfdriver st_cd = { NULL, "st", DV_TAPE }; #define ST_PER_ACTION (ST_AT_FILEMARK | ST_EIO_PENDING | ST_EOM_PENDING | \ ST_BLANK_READ) #define stlookup(unit) (struct st_softc *)device_lookup(&st_cd, (unit)) const struct scsi_inquiry_pattern st_patterns[] = { {T_SEQUENTIAL, T_REMOV, "", "", ""}, }; int stmatch(struct device *parent, void *match, void *aux) { struct scsi_attach_args *sa = aux; struct scsi_inquiry_data *inq = &sa->sa_sc_link->inqdata; int priority; (void)scsi_inqmatch(inq, st_patterns, nitems(st_patterns), sizeof(st_patterns[0]), &priority); return priority; } /* * The routine called by the low level scsi routine when it discovers * a device suitable for this driver. */ void stattach(struct device *parent, struct device *self, void *aux) { const struct st_quirk_inquiry_pattern *finger; struct st_softc *st = (void *)self; struct scsi_attach_args *sa = aux; struct scsi_link *link = sa->sa_sc_link; int priority; SC_DEBUG(link, SDEV_DB2, ("stattach:\n")); /* * Store information needed to contact our base driver */ st->sc_link = link; link->interpret_sense = st_interpret_sense; link->device_softc = st; /* Get any quirks and mode information. */ finger = (const struct st_quirk_inquiry_pattern *)scsi_inqmatch( &link->inqdata, st_quirk_patterns, nitems(st_quirk_patterns), sizeof(st_quirk_patterns[0]), &priority); if (finger != NULL) { st->quirks = finger->quirkdata.quirks; st->mode = finger->quirkdata.mode; CLR(st->flags, ST_MODE_BLKSIZE | ST_MODE_DENSITY); if (st->mode.blksize != 0) SET(st->flags, ST_MODE_BLKSIZE); if (st->mode.density != 0) SET(st->flags, ST_MODE_DENSITY); } printf("\n"); scsi_xsh_set(&st->sc_xsh, link, ststart); st->sc_dk.dk_name = st->sc_dev.dv_xname; /* Set up the buf queue for this device. */ bufq_init(&st->sc_bufq, BUFQ_FIFO); /* Start up with media position unknown. */ st->media_fileno = -1; st->media_blkno = -1; st->media_eom = -1; /* * Reset the media loaded flag, sometimes the data * acquired at boot time is not quite accurate. This * will be checked again at the first open. */ CLR(link->flags, SDEV_MEDIA_LOADED); st->sc_dk.dk_flags = DKF_NOLABELREAD; disk_attach(&st->sc_dev, &st->sc_dk); } int stactivate(struct device *self, int act) { struct st_softc *st = (struct st_softc *)self; switch (act) { case DVACT_DEACTIVATE: SET(st->flags, ST_DYING); scsi_xsh_del(&st->sc_xsh); break; } return 0; } int stdetach(struct device *self, int flags) { struct st_softc *st = (struct st_softc *)self; int cmaj, mn; bufq_drain(&st->sc_bufq); /* Locate the lowest minor number to be detached. */ mn = STMINOR(self->dv_unit, 0); for (cmaj = 0; cmaj < nchrdev; cmaj++) if (cdevsw[cmaj].d_open == stopen) vdevgone(cmaj, mn, mn + MAXSTMODES - 1, VCHR); bufq_destroy(&st->sc_bufq); disk_detach(&st->sc_dk); return 0; } /* * open the device. */ int stopen(dev_t dev, int flags, int fmt, struct proc *p) { struct scsi_link *link; struct st_softc *st; int error = 0; st = stlookup(STUNIT(dev)); if (st == NULL) return ENXIO; if (ISSET(st->flags, ST_DYING)) { device_unref(&st->sc_dev); return ENXIO; } link = st->sc_link; if ((error = disk_lock(&st->sc_dk)) != 0) { device_unref(&st->sc_dev); return error; } if (ISSET(flags, FWRITE) && ISSET(link->flags, SDEV_READONLY)) { error = EACCES; goto done; } SC_DEBUG(link, SDEV_DB1, ("open: dev=0x%x (unit %d (of %d))\n", dev, STUNIT(dev), st_cd.cd_ndevs)); /* * Tape is an exclusive media. Only one open at a time. */ if (ISSET(link->flags, SDEV_OPEN)) { SC_DEBUG(link, SDEV_DB4, ("already open\n")); error = EBUSY; goto done; } /* Use st_interpret_sense() now. */ SET(link->flags, SDEV_OPEN); /* * Check the unit status. This clears any outstanding errors and * will ensure that media is present. */ error = scsi_test_unit_ready(link, TEST_READY_RETRIES, SCSI_SILENT | SCSI_IGNORE_MEDIA_CHANGE | SCSI_IGNORE_ILLEGAL_REQUEST); /* * Terminate any existing mount session if there is no media. */ if (!ISSET(link->flags, SDEV_MEDIA_LOADED)) st_unmount(st, NOEJECT, DOREWIND); if (error != 0) { CLR(link->flags, SDEV_OPEN); goto done; } error = st_mount_tape(st, flags); if (error != 0) { CLR(link->flags, SDEV_OPEN); goto done; } /* * Make sure that a tape opened in write-only mode will have * file marks written on it when closed, even if not written to. * This is for SUN compatibility */ if ((flags & O_ACCMODE) == FWRITE) SET(st->flags, ST_WRITTEN); done: SC_DEBUG(link, SDEV_DB2, ("open complete\n")); disk_unlock(&st->sc_dk); device_unref(&st->sc_dev); return error; } /* * close the device.. only called if we are the LAST * occurrence of an open device */ int stclose(dev_t dev, int flags, int mode, struct proc *p) { struct scsi_link *link; struct st_softc *st; int error = 0; st = stlookup(STUNIT(dev)); if (st == NULL) return ENXIO; if (ISSET(st->flags, ST_DYING)) { error = ENXIO; goto done; } link = st->sc_link; disk_lock_nointr(&st->sc_dk); SC_DEBUG(link, SDEV_DB1, ("closing\n")); if (ISSET(st->flags, ST_WRITTEN) && !ISSET(st->flags, ST_FM_WRITTEN)) st_write_filemarks(st, 1, 0); switch (STMODE(dev)) { case 0: /* /dev/rstN */ st_unmount(st, NOEJECT, DOREWIND); break; case 1: /* /dev/nrstN */ st_unmount(st, NOEJECT, NOREWIND); break; case 2: /* /dev/erstN */ st_unmount(st, EJECT, DOREWIND); break; case 3: /* /dev/enrstN */ st_unmount(st, EJECT, NOREWIND); break; } CLR(link->flags, SDEV_OPEN); scsi_xsh_del(&st->sc_xsh); disk_unlock(&st->sc_dk); done: device_unref(&st->sc_dev); return error; } /* * Start a new mount session if needed. */ int st_mount_tape(struct st_softc *st, int flags) { struct scsi_link *link = st->sc_link; int error = 0; if (ISSET(st->flags, ST_MOUNTED)) return 0; SC_DEBUG(link, SDEV_DB1, ("mounting\n")); /* * Assume the media is new and give it a chance to * to do a 'load' instruction. */ if ((error = st_load(st, LD_LOAD, 0)) != 0) goto done; /* * Throw another dummy instruction to catch * 'Unit attention' errors. Some drives appear to give * these after doing a Load instruction. * (notably some DAT drives) */ /* XXX */ scsi_test_unit_ready(link, TEST_READY_RETRIES, SCSI_SILENT); /* * Some devices can't tell you much until they have been * asked to look at the media. This quirk does this. */ if (ISSET(st->quirks, ST_Q_SENSE_HELP)) if ((error = st_touch_tape(st)) != 0) return error; /* * Load the physical device parameters * loads: blkmin, blkmax */ if (!ISSET(link->flags, SDEV_ATAPI) && (error = st_read_block_limits(st, 0)) != 0) goto done; /* * Load the media dependent parameters * includes: media_blksize,media_density * As we have a tape in, it should be reflected here. * If not you may need the "quirk" above. */ if ((error = st_mode_sense(st, 0)) != 0) goto done; /* * If we have gained a permanent density from somewhere, * then use it in preference to the one supplied by * default by the driver. */ if (ISSET(st->flags, ST_MODE_DENSITY)) st->density = st->mode.density; else st->density = st->media_density; /* * If we have gained a permanent blocksize * then use it in preference to the one supplied by * default by the driver. */ CLR(st->flags, ST_FIXEDBLOCKS); if (ISSET(st->flags, ST_MODE_BLKSIZE)) { st->blksize = st->mode.blksize; if (st->blksize) SET(st->flags, ST_FIXEDBLOCKS); } else { if ((error = st_decide_mode(st, 0)) != 0) goto done; } if ((error = st_mode_select(st, 0)) != 0) { printf("%s: cannot set selected mode\n", st->sc_dev.dv_xname); goto done; } scsi_prevent(link, PR_PREVENT, SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY); SET(st->flags, ST_MOUNTED); SET(link->flags, SDEV_MEDIA_LOADED); /* move earlier? */ st->media_fileno = 0; st->media_blkno = 0; st->media_eom = -1; done: return error; } /* * End the present mount session. * Rewind, and optionally eject the tape. * Reset various flags to indicate that all new * operations require another mount operation */ void st_unmount(struct st_softc *st, int eject, int rewind) { struct scsi_link *link = st->sc_link; int nmarks; if (eject == NOEJECT && rewind == NOREWIND) { if (ISSET(link->flags, SDEV_MEDIA_LOADED)) return; } st->media_fileno = -1; st->media_blkno = -1; if (!ISSET(st->flags, ST_MOUNTED)) return; SC_DEBUG(link, SDEV_DB1, ("unmounting\n")); st_check_eod(st, 0, &nmarks, SCSI_IGNORE_NOT_READY); if (rewind == DOREWIND) st_rewind(st, 0, SCSI_IGNORE_NOT_READY); scsi_prevent(link, PR_ALLOW, SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY); if (eject == EJECT) st_load(st, LD_UNLOAD, SCSI_IGNORE_NOT_READY); CLR(st->flags, ST_MOUNTED); CLR(link->flags, SDEV_MEDIA_LOADED); } /* * Given all we know about the device, media, mode, 'quirks' and * initial operation, make a decision as to how we should be set * to run (regarding blocking and EOD marks) */ int st_decide_mode(struct st_softc *st, int first_read) { struct scsi_link *link = st->sc_link; SC_DEBUG(link, SDEV_DB2, ("starting block mode decision\n")); /* ATAPI tapes are always fixed blocksize. */ if (ISSET(link->flags, SDEV_ATAPI)) { SET(st->flags, ST_FIXEDBLOCKS); if (st->media_blksize > 0) st->blksize = st->media_blksize; else st->blksize = DEF_FIXED_BSIZE; goto done; } /* * If the drive can only handle fixed-length blocks and only at * one size, perhaps we should just do that. */ if (st->blkmin && (st->blkmin == st->blkmax)) { SET(st->flags, ST_FIXEDBLOCKS); st->blksize = st->blkmin; SC_DEBUG(link, SDEV_DB3, ("blkmin == blkmax of %d\n", st->blkmin)); goto done; } /* * If the tape density mandates (or even suggests) use of fixed * or variable-length blocks, comply. */ switch (st->density) { case HALFINCH_800: case HALFINCH_1600: case HALFINCH_6250: case DDS: CLR(st->flags, ST_FIXEDBLOCKS); st->blksize = 0; SC_DEBUG(link, SDEV_DB3, ("density specified variable\n")); goto done; case QIC_11: case QIC_24: case QIC_120: case QIC_150: case QIC_525: case QIC_1320: SET(st->flags, ST_FIXEDBLOCKS); if (st->media_blksize > 0) st->blksize = st->media_blksize; else st->blksize = DEF_FIXED_BSIZE; SC_DEBUG(link, SDEV_DB3, ("density specified fixed\n")); goto done; } /* * If we're about to read the tape, perhaps we should choose * fixed or variable-length blocks and block size according to * what the drive found on the tape. */ if (first_read) { if (st->media_blksize > 0) SET(st->flags, ST_FIXEDBLOCKS); else CLR(st->flags, ST_FIXEDBLOCKS); st->blksize = st->media_blksize; SC_DEBUG(link, SDEV_DB3, ("Used media_blksize of %d\n", st->media_blksize)); goto done; } /* * We're getting no hints from any direction. Choose variable- * length blocks arbitrarily. */ CLR(st->flags, ST_FIXEDBLOCKS); st->blksize = 0; SC_DEBUG(link, SDEV_DB3, ("Give up and default to variable mode\n")); done: /* * Decide whether or not to write two file marks to signify end- * of-data. Make the decision as a function of density. If * the decision is not to use a second file mark, the SCSI BLANK * CHECK condition code will be recognized as end-of-data when * first read. * (I think this should be a by-product of fixed/variable..julian) */ switch (st->density) { /* case 8 mm: What is the SCSI density code for 8 mm, anyway? */ case QIC_11: case QIC_24: case QIC_120: case QIC_150: case QIC_525: case QIC_1320: CLR(st->flags, ST_2FM_AT_EOD); break; default: SET(st->flags, ST_2FM_AT_EOD); } return 0; } /* * Actually translate the requested transfer into * one the physical driver can understand * The transfer is described by a buf and will include * only one physical transfer. */ void ststrategy(struct buf *bp) { struct scsi_link *link; struct st_softc *st; int s; st = stlookup(STUNIT(bp->b_dev)); if (st == NULL) { bp->b_error = ENXIO; goto bad; } if (ISSET(st->flags, ST_DYING)) { bp->b_error = ENXIO; goto bad; } link = st->sc_link; SC_DEBUG(link, SDEV_DB2, ("ststrategy: %ld bytes @ blk %lld\n", bp->b_bcount, (long long)bp->b_blkno)); /* * If it's a null transfer, return immediately. */ if (bp->b_bcount == 0) goto done; /* * Odd sized request on fixed drives are verboten */ if (ISSET(st->flags, ST_FIXEDBLOCKS)) { if (bp->b_bcount % st->blksize) { printf("%s: bad request, must be multiple of %d\n", st->sc_dev.dv_xname, st->blksize); bp->b_error = EIO; goto bad; } } /* * as are out-of-range requests on variable drives. */ else if (bp->b_bcount < st->blkmin || (st->blkmax && bp->b_bcount > st->blkmax)) { printf("%s: bad request, must be between %d and %d\n", st->sc_dev.dv_xname, st->blkmin, st->blkmax); bp->b_error = EIO; goto bad; } /* * Place it in the queue of activities for this tape * at the end (a bit silly because we only have on user.. * (but it could fork())) */ bufq_queue(&st->sc_bufq, bp); /* * Tell the device to get going on the transfer if it's * not doing anything, otherwise just wait for completion * (All a bit silly if we're only allowing 1 open but..) */ scsi_xsh_add(&st->sc_xsh); device_unref(&st->sc_dev); return; bad: SET(bp->b_flags, B_ERROR); done: /* Set b_resid to indicate no xfer was done. */ bp->b_resid = bp->b_bcount; s = splbio(); biodone(bp); splx(s); if (st) device_unref(&st->sc_dev); } void ststart(struct scsi_xfer *xs) { struct scsi_link *link = xs->sc_link; struct st_softc *st = link->device_softc; struct buf *bp; struct scsi_rw_tape *cmd; int s; SC_DEBUG(link, SDEV_DB2, ("ststart\n")); if (ISSET(st->flags, ST_DYING)) { scsi_xs_put(xs); return; } /* * if the device has been unmounted by the user * then throw away all requests until done */ if (!ISSET(st->flags, ST_MOUNTED) || !ISSET(link->flags, SDEV_MEDIA_LOADED)) { /* make sure that one implies the other.. */ CLR(link->flags, SDEV_MEDIA_LOADED); bufq_drain(&st->sc_bufq); scsi_xs_put(xs); return; } for (;;) { bp = bufq_dequeue(&st->sc_bufq); if (bp == NULL) { scsi_xs_put(xs); return; } /* * Only FIXEDBLOCK devices have pending I/O or space * operations. */ if (ISSET(st->flags, ST_FIXEDBLOCKS)) { /* * If we are at a filemark but have not reported it yet * then we should report it now */ if (ISSET(st->flags, ST_AT_FILEMARK)) { if ((bp->b_flags & B_READ) == B_WRITE) { /* * Handling of ST_AT_FILEMARK in * st_space will fill in the right file * mark count. * Back up over filemark */ if (st_space(st, 0, SP_FILEMARKS, 0)) { SET(bp->b_flags, B_ERROR); bp->b_resid = bp->b_bcount; bp->b_error = EIO; s = splbio(); biodone(bp); splx(s); continue; } } else { bp->b_resid = bp->b_bcount; bp->b_error = 0; CLR(bp->b_flags, B_ERROR); CLR(st->flags, ST_AT_FILEMARK); s = splbio(); biodone(bp); splx(s); continue; /* seek more work */ } } } /* * If we are at EIO or EOM but have not reported it * yet then we should report it now. */ if (ISSET(st->flags, ST_EOM_PENDING | ST_EIO_PENDING)) { bp->b_resid = bp->b_bcount; if (ISSET(st->flags, ST_EIO_PENDING)) { bp->b_error = EIO; SET(bp->b_flags, B_ERROR); } CLR(st->flags, ST_EOM_PENDING | ST_EIO_PENDING); s = splbio(); biodone(bp); splx(s); continue; /* seek more work */ } break; } /* * Fill out the scsi command */ cmd = (struct scsi_rw_tape *)&xs->cmd; bzero(cmd, sizeof(*cmd)); if ((bp->b_flags & B_READ) == B_WRITE) { cmd->opcode = WRITE; CLR(st->flags, ST_FM_WRITTEN); SET(st->flags, ST_WRITTEN); SET(xs->flags, SCSI_DATA_OUT); } else { cmd->opcode = READ; SET(xs->flags, SCSI_DATA_IN); } /* * Handle "fixed-block-mode" tape drives by using the * block count instead of the length. */ if (ISSET(st->flags, ST_FIXEDBLOCKS)) { SET(cmd->byte2, SRW_FIXED); _lto3b(bp->b_bcount / st->blksize, cmd->len); } else _lto3b(bp->b_bcount, cmd->len); if (st->media_blkno != -1) { /* Update block count now, errors will set it to -1. */ if (ISSET(st->flags, ST_FIXEDBLOCKS)) st->media_blkno += _3btol(cmd->len); else if (_3btol(cmd->len) != 0) st->media_blkno++; } xs->cmdlen = sizeof(*cmd); xs->timeout = ST_IO_TIME; xs->data = bp->b_data; xs->datalen = bp->b_bcount; xs->done = st_buf_done; xs->cookie = bp; xs->bp = bp; /* Instrumentation. */ disk_busy(&st->sc_dk); /* * go ask the adapter to do all this for us */ scsi_xs_exec(xs); /* * should we try do more work now? */ if (bufq_peek(&st->sc_bufq)) scsi_xsh_add(&st->sc_xsh); } void st_buf_done(struct scsi_xfer *xs) { struct st_softc *st = xs->sc_link->device_softc; struct buf *bp = xs->cookie; int error, s; switch (xs->error) { case XS_NOERROR: bp->b_error = 0; CLR(bp->b_flags, B_ERROR); bp->b_resid = xs->resid; break; case XS_SENSE: case XS_SHORTSENSE: SC_DEBUG_SENSE(xs); error = st_interpret_sense(xs); if (error == 0) { bp->b_error = 0; CLR(bp->b_flags, B_ERROR); bp->b_resid = xs->resid; break; } if (error != ERESTART) xs->retries = 0; goto retry; case XS_BUSY: if (xs->retries) { if (scsi_delay(xs, 1) != ERESTART) xs->retries = 0; } goto retry; case XS_TIMEOUT: retry: if (xs->retries--) { scsi_xs_exec(xs); return; } /* FALLTHROUGH */ default: bp->b_error = EIO; SET(bp->b_flags, B_ERROR); bp->b_resid = bp->b_bcount; break; } disk_unbusy(&st->sc_dk, bp->b_bcount - xs->resid, bp->b_blkno, bp->b_flags & B_READ); s = splbio(); biodone(bp); splx(s); scsi_xs_put(xs); } void stminphys(struct buf *bp) { struct scsi_link *link; struct st_softc *sc; sc = stlookup(STUNIT(bp->b_dev)); if (sc == NULL) return; link = sc->sc_link; if (link->bus->sb_adapter->dev_minphys != NULL) (*link->bus->sb_adapter->dev_minphys)(bp, link); else minphys(bp); device_unref(&sc->sc_dev); } int stread(dev_t dev, struct uio *uio, int iomode) { return physio(ststrategy, dev, B_READ, stminphys, uio); } int stwrite(dev_t dev, struct uio *uio, int iomode) { return physio(ststrategy, dev, B_WRITE, stminphys, uio); } /* * Perform special action on behalf of the user; * knows about the internals of this device */ int stioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p) { int error = 0; int nmarks; int flags = 0; struct st_softc *st; int hold_blksize; u_int8_t hold_density; struct mtop *mt = (struct mtop *) arg; int number; /* * Find the device that the user is talking about */ st = stlookup(STUNIT(dev)); if (st == NULL) return ENXIO; if (ISSET(st->flags, ST_DYING)) { error = ENXIO; goto done; } hold_blksize = st->blksize; hold_density = st->density; switch (cmd) { case MTIOCGET: { struct mtget *g = (struct mtget *) arg; /* * (to get the current state of READONLY) */ error = st_mode_sense(st, SCSI_SILENT); if (error != 0) break; SC_DEBUG(st->sc_link, SDEV_DB1, ("[ioctl: get status]\n")); bzero(g, sizeof(struct mtget)); g->mt_type = 0x7; /* Ultrix compat *//*? */ g->mt_blksiz = st->blksize; g->mt_density = st->density; g->mt_mblksiz = st->mode.blksize; g->mt_mdensity = st->mode.density; if (ISSET(st->sc_link->flags, SDEV_READONLY)) SET(g->mt_dsreg, MT_DS_RDONLY); if (ISSET(st->flags, ST_MOUNTED)) SET(g->mt_dsreg, MT_DS_MOUNTED); g->mt_resid = st->mt_resid; g->mt_erreg = st->mt_erreg; g->mt_fileno = st->media_fileno; g->mt_blkno = st->media_blkno; /* * clear latched errors. */ st->mt_resid = 0; st->mt_erreg = 0; break; } case MTIOCTOP: { SC_DEBUG(st->sc_link, SDEV_DB1, ("[ioctl: op=0x%x count=0x%x]\n", mt->mt_op, mt->mt_count)); number = mt->mt_count; switch (mt->mt_op) { case MTWEOF: /* write an end-of-file record */ error = st_write_filemarks(st, number, flags); break; case MTBSF: /* backward space file */ number = -number; case MTFSF: /* forward space file */ error = st_check_eod(st, 0, &nmarks, flags); if (error == 0) error = st_space(st, number - nmarks, SP_FILEMARKS, flags); break; case MTBSR: /* backward space record */ number = -number; case MTFSR: /* forward space record */ error = st_check_eod(st, 1, &nmarks, flags); if (error == 0) error = st_space(st, number, SP_BLKS, flags); break; case MTREW: /* rewind */ error = st_rewind(st, 0, flags); break; case MTOFFL: /* rewind and put the drive offline */ st_unmount(st, EJECT, DOREWIND); break; case MTNOP: /* no operation, sets status only */ break; case MTRETEN: /* retension the tape */ error = st_load(st, LD_RETENSION, flags); if (error == 0) error = st_load(st, LD_LOAD, flags); break; case MTEOM: /* forward space to end of media */ error = st_check_eod(st, 0, &nmarks, flags); if (error == 0) error = st_space(st, 1, SP_EOM, flags); break; case MTCACHE: /* enable controller cache */ CLR(st->flags, ST_DONTBUFFER); goto try_new_value; case MTNOCACHE: /* disable controller cache */ SET(st->flags, ST_DONTBUFFER); goto try_new_value; case MTERASE: /* erase volume */ error = st_erase(st, number, flags); break; case MTSETBSIZ: /* Set block size for device and mode. */ if (number == 0) { CLR(st->flags, ST_FIXEDBLOCKS); } else { if ((st->blkmin || st->blkmax) && (number < st->blkmin || number > st->blkmax)) { error = EINVAL; break; } SET(st->flags, ST_FIXEDBLOCKS); } st->blksize = number; goto try_new_value; case MTSETDNSTY: /* Set density for device and mode. */ if (number < 0 || number > SCSI_MAX_DENSITY_CODE) { error = EINVAL; break; } st->density = number; goto try_new_value; default: error = EINVAL; } break; } case MTIOCIEOT: case MTIOCEEOT: break; #if 0 case MTIOCRDSPOS: error = st_rdpos(st, 0, (u_int32_t *) arg); break; case MTIOCRDHPOS: error = st_rdpos(st, 1, (u_int32_t *) arg); break; case MTIOCSLOCATE: error = st_setpos(st, 0, (u_int32_t *) arg); break; case MTIOCHLOCATE: error = st_setpos(st, 1, (u_int32_t *) arg); break; #endif /* 0 */ default: error = scsi_do_ioctl(st->sc_link, cmd, arg, flag); break; } goto done; try_new_value: /* * Check that the mode being asked for is aggreeable to the * drive. If not, put it back the way it was. */ if ((error = st_mode_select(st, 0)) != 0) {/* put it back as it was */ printf("%s: cannot set selected mode\n", st->sc_dev.dv_xname); st->density = hold_density; st->blksize = hold_blksize; if (st->blksize) SET(st->flags, ST_FIXEDBLOCKS); else CLR(st->flags, ST_FIXEDBLOCKS); goto done; } /* * As the drive liked it, if we are setting a new default, * set it into the structures as such. */ switch (mt->mt_op) { case MTSETBSIZ: st->mode.blksize = st->blksize; SET(st->flags, ST_MODE_BLKSIZE); break; case MTSETDNSTY: st->mode.density = st->density; SET(st->flags, ST_MODE_DENSITY); break; } done: device_unref(&st->sc_dev); return error; } /* * Do a synchronous read. */ int st_read(struct st_softc *st, char *buf, int size, int flags) { struct scsi_rw_tape *cmd; struct scsi_xfer *xs; int error; if (size == 0) return 0; xs = scsi_xs_get(st->sc_link, flags | SCSI_DATA_IN); if (xs == NULL) return ENOMEM; xs->cmdlen = sizeof(*cmd); xs->data = buf; xs->datalen = size; xs->retries = 0; xs->timeout = ST_IO_TIME; cmd = (struct scsi_rw_tape *)&xs->cmd; cmd->opcode = READ; if (ISSET(st->flags, ST_FIXEDBLOCKS)) { SET(cmd->byte2, SRW_FIXED); _lto3b(size / (st->blksize ? st->blksize : DEF_FIXED_BSIZE), cmd->len); } else _lto3b(size, cmd->len); error = scsi_xs_sync(xs); scsi_xs_put(xs); return error; } /* * Ask the drive what its min and max blk sizes are. */ int st_read_block_limits(struct st_softc *st, int flags) { struct scsi_block_limits_data *block_limits = NULL; struct scsi_block_limits *cmd; struct scsi_link *link = st->sc_link; struct scsi_xfer *xs; int error = 0; if (ISSET(link->flags, SDEV_MEDIA_LOADED)) return 0; block_limits = dma_alloc(sizeof(*block_limits), PR_NOWAIT); if (block_limits == NULL) return ENOMEM; xs = scsi_xs_get(link, flags | SCSI_DATA_IN); if (xs == NULL) { error = ENOMEM; goto done; } xs->cmdlen = sizeof(*cmd); xs->data = (void *)block_limits; xs->datalen = sizeof(*block_limits); xs->timeout = ST_CTL_TIME; cmd = (struct scsi_block_limits *)&xs->cmd; cmd->opcode = READ_BLOCK_LIMITS; error = scsi_xs_sync(xs); scsi_xs_put(xs); if (error == 0) { st->blkmin = _2btol(block_limits->min_length); st->blkmax = _3btol(block_limits->max_length); SC_DEBUG(link, SDEV_DB3, ("(%d <= blksize <= %d)\n", st->blkmin, st->blkmax)); } done: if (block_limits) dma_free(block_limits, sizeof(*block_limits)); return error; } /* * Get the scsi driver to send a full inquiry to the * device and use the results to fill out the global * parameter structure. * * called from: * attach * open * ioctl (to reset original blksize) */ int st_mode_sense(struct st_softc *st, int flags) { union scsi_mode_sense_buf *data = NULL; struct scsi_link *link = st->sc_link; u_int64_t block_count; u_int32_t density, block_size; u_char *page0 = NULL; u_int8_t dev_spec; int error = 0, big; data = dma_alloc(sizeof(*data), PR_NOWAIT); if (data == NULL) return ENOMEM; /* * Ask for page 0 (vendor specific) mode sense data. */ density = 0; block_count = 0; block_size = 0; error = scsi_do_mode_sense(link, 0, data, (void **)&page0, 1, flags | SCSI_SILENT, &big); if (error != 0) goto done; scsi_parse_blkdesc(link, data, big, &density, &block_count, &block_size); /* It is valid for no page0 to be available. */ if (big) dev_spec = data->hdr_big.dev_spec; else dev_spec = data->hdr.dev_spec; if (ISSET(dev_spec, SMH_DSP_WRITE_PROT)) SET(link->flags, SDEV_READONLY); else CLR(link->flags, SDEV_READONLY); st->media_blksize = block_size; st->media_density = density; SC_DEBUG(link, SDEV_DB3, ("density code 0x%x, %d-byte blocks, write-%s, %sbuffered\n", st->media_density, st->media_blksize, ISSET(link->flags, SDEV_READONLY) ? "protected" : "enabled", ISSET(dev_spec, SMH_DSP_BUFF_MODE) ? "" : "un")); SET(link->flags, SDEV_MEDIA_LOADED); done: if (data) dma_free(data, sizeof(*data)); return error; } /* * Send a filled out parameter structure to the drive to * set it into the desire mode etc. */ int st_mode_select(struct st_softc *st, int flags) { union scsi_mode_sense_buf *inbuf = NULL, *outbuf = NULL; struct scsi_blk_desc general; struct scsi_link *link = st->sc_link; u_int8_t *page0 = NULL; int error = 0, big, page0_size; inbuf = dma_alloc(sizeof(*inbuf), PR_NOWAIT); if (inbuf == NULL) { error = ENOMEM; goto done; } outbuf = dma_alloc(sizeof(*outbuf), PR_NOWAIT | PR_ZERO); if (outbuf == NULL) { error = ENOMEM; goto done; } /* * This quirk deals with drives that have only one valid mode and think * this gives them license to reject all mode selects, even if the * selected mode is the one that is supported. */ if (ISSET(st->quirks, ST_Q_UNIMODAL)) { SC_DEBUG(link, SDEV_DB3, ("not setting density 0x%x blksize 0x%x\n", st->density, st->blksize)); error = 0; goto done; } if (ISSET(link->flags, SDEV_ATAPI)) { error = 0; goto done; } bzero(&general, sizeof(general)); general.density = st->density; if (ISSET(st->flags, ST_FIXEDBLOCKS)) _lto3b(st->blksize, general.blklen); /* * Ask for page 0 (vendor specific) mode sense data. * * page0 == NULL is a valid situation. */ error = scsi_do_mode_sense(link, 0, inbuf, (void **)&page0, 1, flags | SCSI_SILENT, &big); if (error != 0) goto done; if (page0 == NULL) { page0_size = 0; } else if (big == 0) { page0_size = inbuf->hdr.data_length + sizeof(inbuf->hdr.data_length) - sizeof(inbuf->hdr) - inbuf->hdr.blk_desc_len; memcpy(&outbuf->buf[sizeof(outbuf->hdr)+ sizeof(general)], page0, page0_size); } else { page0_size = _2btol(inbuf->hdr_big.data_length) + sizeof(inbuf->hdr_big.data_length) - sizeof(inbuf->hdr_big) - _2btol(inbuf->hdr_big.blk_desc_len); memcpy(&outbuf->buf[sizeof(outbuf->hdr_big) + sizeof(general)], page0, page0_size); } /* * Set up for a mode select. */ if (big == 0) { outbuf->hdr.data_length = sizeof(outbuf->hdr) + sizeof(general) + page0_size - sizeof(outbuf->hdr.data_length); if (!ISSET(st->flags, ST_DONTBUFFER)) outbuf->hdr.dev_spec = SMH_DSP_BUFF_MODE_ON; outbuf->hdr.blk_desc_len = sizeof(general); memcpy(&outbuf->buf[sizeof(outbuf->hdr)], &general, sizeof(general)); error = scsi_mode_select(st->sc_link, 0, &outbuf->hdr, flags, ST_CTL_TIME); goto done; } /* MODE SENSE (10) header was returned, so use MODE SELECT (10). */ _lto2b((sizeof(outbuf->hdr_big) + sizeof(general) + page0_size - sizeof(outbuf->hdr_big.data_length)), outbuf->hdr_big.data_length); if (!ISSET(st->flags, ST_DONTBUFFER)) outbuf->hdr_big.dev_spec = SMH_DSP_BUFF_MODE_ON; _lto2b(sizeof(general), outbuf->hdr_big.blk_desc_len); memcpy(&outbuf->buf[sizeof(outbuf->hdr_big)], &general, sizeof(general)); error = scsi_mode_select_big(st->sc_link, 0, &outbuf->hdr_big, flags, ST_CTL_TIME); done: if (inbuf) dma_free(inbuf, sizeof(*inbuf)); if (outbuf) dma_free(outbuf, sizeof(*outbuf)); return error; } /* * issue an erase command */ int st_erase(struct st_softc *st, int full, int flags) { struct scsi_erase *cmd; struct scsi_xfer *xs; int error; xs = scsi_xs_get(st->sc_link, flags); if (xs == NULL) return ENOMEM; xs->cmdlen = sizeof(*cmd); /* * Full erase means set LONG bit in erase command, which asks * the drive to erase the entire unit. Without this bit, we're * asking the drive to write an erase gap. */ cmd = (struct scsi_erase *)&xs->cmd; cmd->opcode = ERASE; if (full) { cmd->byte2 = SE_IMMED|SE_LONG; xs->timeout = ST_SPC_TIME; } else { cmd->byte2 = SE_IMMED; xs->timeout = ST_IO_TIME; } /* * XXX We always do this asynchronously, for now. How long should * we wait if we want to (eventually) to it synchronously? */ error = scsi_xs_sync(xs); scsi_xs_put(xs); return error; } /* * skip N blocks/filemarks/seq filemarks/eom */ int st_space(struct st_softc *st, int number, u_int what, int flags) { struct scsi_space *cmd; struct scsi_xfer *xs; int error; switch (what) { case SP_BLKS: if (ISSET(st->flags, ST_PER_ACTION)) { if (number > 0) { CLR(st->flags, ST_PER_ACTION); return EIO; } else if (number < 0) { if (ISSET(st->flags, ST_AT_FILEMARK)) { /* * Handling of ST_AT_FILEMARK * in st_space will fill in the * right file mark count. */ error = st_space(st, 0, SP_FILEMARKS, flags); if (error != 0) return error; } if (ISSET(st->flags, ST_BLANK_READ)) { CLR(st->flags, ST_BLANK_READ); return EIO; } CLR(st->flags, ST_EIO_PENDING | ST_EOM_PENDING); } } break; case SP_FILEMARKS: if (ISSET(st->flags, ST_EIO_PENDING)) { if (number > 0) { /* pretend we just discovered the error */ CLR(st->flags, ST_EIO_PENDING); return EIO; } else if (number < 0) { /* back away from the error */ CLR(st->flags, ST_EIO_PENDING); } } if (ISSET(st->flags, ST_AT_FILEMARK)) { CLR(st->flags, ST_AT_FILEMARK); number--; } if (ISSET(st->flags, ST_BLANK_READ) && (number < 0)) { /* back away from unwritten tape */ CLR(st->flags, ST_BLANK_READ); number++; /* XXX dubious */ } break; case SP_EOM: if (ISSET(st->flags, ST_EOM_PENDING)) { /* We are already there. */ CLR(st->flags, ST_EOM_PENDING); return 0; } if (ISSET(st->flags, ST_EIO_PENDING)) { /* pretend we just discovered the error */ CLR(st->flags, ST_EIO_PENDING); return EIO; } if (ISSET(st->flags, ST_AT_FILEMARK)) CLR(st->flags, ST_AT_FILEMARK); break; } if (number == 0) return 0; xs = scsi_xs_get(st->sc_link, flags); if (xs == NULL) return ENOMEM; cmd = (struct scsi_space *)&xs->cmd; cmd->opcode = SPACE; cmd->byte2 = what; _lto3b(number, cmd->number); xs->cmdlen = sizeof(*cmd); xs->timeout = ST_SPC_TIME; CLR(st->flags, ST_EOD_DETECTED); error = scsi_xs_sync(xs); scsi_xs_put(xs); if (error != 0) { st->media_fileno = -1; st->media_blkno = -1; } else { switch (what) { case SP_BLKS: if (st->media_blkno != -1) { st->media_blkno += number; if (st->media_blkno < 0) st->media_blkno = -1; } break; case SP_FILEMARKS: if (st->media_fileno != -1) { if (!ISSET(st->flags, ST_EOD_DETECTED)) st->media_fileno += number; if (st->media_fileno > st->media_eom) st->media_eom = st->media_fileno; st->media_blkno = 0; } break; case SP_EOM: if (st->media_eom != -1) { st->media_fileno = st->media_eom; st->media_blkno = 0; } else { st->media_fileno = -1; st->media_blkno = -1; } break; default: st->media_fileno = -1; st->media_blkno = -1; break; } } return error; } /* * write N filemarks */ int st_write_filemarks(struct st_softc *st, int number, int flags) { struct scsi_write_filemarks *cmd; struct scsi_xfer *xs; int error; if (number < 0) return EINVAL; xs = scsi_xs_get(st->sc_link, flags); if (xs == NULL) return ENOMEM; xs->cmdlen = sizeof(*cmd); xs->timeout = ST_IO_TIME * 4; switch (number) { case 0: /* really a command to sync the drive's buffers */ break; case 1: if (ISSET(st->flags, ST_FM_WRITTEN)) /* already have one down */ CLR(st->flags, ST_WRITTEN); else SET(st->flags, ST_FM_WRITTEN); CLR(st->flags, ST_PER_ACTION); break; default: CLR(st->flags, ST_PER_ACTION | ST_WRITTEN); break; } cmd = (struct scsi_write_filemarks *)&xs->cmd; cmd->opcode = WRITE_FILEMARKS; _lto3b(number, cmd->number); error = scsi_xs_sync(xs); scsi_xs_put(xs); if (error != 0) { st->media_fileno = -1; st->media_blkno = -1; st->media_eom = -1; } else if (st->media_fileno != -1) { st->media_fileno += number; st->media_eom = st->media_fileno; st->media_blkno = 0; } return error; } /* * Make sure the right number of file marks is on tape if the * tape has been written. If the position argument is true, * leave the tape positioned where it was originally. * * nmarks returns the number of marks to skip (or, if position * true, which were skipped) to get back original position. */ int st_check_eod(struct st_softc *st, int position, int *nmarks, int flags) { int error; switch (st->flags & (ST_WRITTEN | ST_FM_WRITTEN | ST_2FM_AT_EOD)) { default: *nmarks = 0; return 0; case ST_WRITTEN: case ST_WRITTEN | ST_FM_WRITTEN | ST_2FM_AT_EOD: *nmarks = 1; break; case ST_WRITTEN | ST_2FM_AT_EOD: *nmarks = 2; } error = st_write_filemarks(st, *nmarks, flags); if (error == 0 && position != 0) error = st_space(st, -*nmarks, SP_FILEMARKS, flags); return error; } /* * load/unload/retension */ int st_load(struct st_softc *st, u_int type, int flags) { struct scsi_load *cmd; struct scsi_xfer *xs; int error, nmarks; st->media_fileno = -1; st->media_blkno = -1; st->media_eom = -1; if (type != LD_LOAD) { error = st_check_eod(st, 0, &nmarks, flags); if (error != 0) return error; } if (ISSET(st->quirks, ST_Q_IGNORE_LOADS)) { if (type == LD_LOAD) { /* * If we ignore loads, at least we should try a rewind. */ return st_rewind(st, 0, flags); } return 0; } xs = scsi_xs_get(st->sc_link, flags); if (xs == NULL) return ENOMEM; xs->cmdlen = sizeof(*cmd); xs->timeout = ST_SPC_TIME; cmd = (struct scsi_load *)&xs->cmd; cmd->opcode = LOAD; cmd->how = type; error = scsi_xs_sync(xs); scsi_xs_put(xs); return error; } /* * Rewind the device */ int st_rewind(struct st_softc *st, u_int immediate, int flags) { struct scsi_rewind *cmd; struct scsi_xfer *xs; int error, nmarks; error = st_check_eod(st, 0, &nmarks, flags); if (error != 0) return error; CLR(st->flags, ST_PER_ACTION); xs = scsi_xs_get(st->sc_link, flags); if (xs == NULL) return ENOMEM; xs->cmdlen = sizeof(*cmd); xs->timeout = immediate ? ST_CTL_TIME : ST_SPC_TIME; cmd = (struct scsi_rewind *)&xs->cmd; cmd->opcode = REWIND; cmd->byte2 = immediate; error = scsi_xs_sync(xs); scsi_xs_put(xs); if (error == 0) { st->media_fileno = 0; st->media_blkno = 0; } return error; } /* * Look at the returned sense and act on the error to determine * the unix error number to pass back... (0 = report no error) * (-1 = continue processing) */ int st_interpret_sense(struct scsi_xfer *xs) { struct scsi_sense_data *sense = &xs->sense; struct scsi_link *link = xs->sc_link; struct scsi_space *space; struct st_softc *st = link->device_softc; u_int8_t serr = sense->error_code & SSD_ERRCODE; u_int8_t skey = sense->flags & SSD_KEY; int32_t resid, info, number; int datalen; if (!ISSET(link->flags, SDEV_OPEN) || (serr != SSD_ERRCODE_CURRENT && serr != SSD_ERRCODE_DEFERRED)) return scsi_interpret_sense(xs); info = (int32_t)_4btol(sense->info); switch (skey) { /* * We do custom processing in st for the unit becoming ready case. * in this case we do not allow xs->retries to be decremented * only on the "Unit Becoming Ready" case. This is because tape * drives report "Unit Becoming Ready" when loading media, etc. * and can take a long time. Rather than having a massive timeout * for all operations (which would cause other problems) we allow * operations to wait (but be interruptible with Ctrl-C) forever * as long as the drive is reporting that it is becoming ready. * all other cases are handled as per the default. */ case SKEY_NOT_READY: if (ISSET(xs->flags, SCSI_IGNORE_NOT_READY)) return 0; switch (ASC_ASCQ(sense)) { case SENSE_NOT_READY_BECOMING_READY: SC_DEBUG(link, SDEV_DB1, ("not ready: busy (%#x)\n", sense->add_sense_code_qual)); /* don't count this as a retry */ xs->retries++; return scsi_delay(xs, 1); default: return scsi_interpret_sense(xs); } break; case SKEY_BLANK_CHECK: if (sense->error_code & SSD_ERRCODE_VALID && xs->cmd.opcode == SPACE) { switch (ASC_ASCQ(sense)) { case SENSE_END_OF_DATA_DETECTED: SET(st->flags, ST_EOD_DETECTED); space = (struct scsi_space *)&xs->cmd; number = _3btol(space->number); st->media_fileno = number - info; st->media_eom = st->media_fileno; return 0; case SENSE_BEGINNING_OF_MEDIUM_DETECTED: /* Standard says: Position is undefined! */ SET(st->flags, ST_BOD_DETECTED); st->media_fileno = -1; st->media_blkno = -1; return 0; } } break; case SKEY_NO_SENSE: case SKEY_RECOVERED_ERROR: case SKEY_MEDIUM_ERROR: case SKEY_VOLUME_OVERFLOW: break; default: return scsi_interpret_sense(xs); } /* * 'resid' can be in units of st->blksize or bytes. xs->resid and * xs->datalen are always in units of bytes. So we need a variable * to store datalen in the same units as resid and to adjust * xs->resid to be in bytes. */ if (ISSET(sense->error_code, SSD_ERRCODE_VALID)) { if (ISSET(st->flags, ST_FIXEDBLOCKS)) resid = info * st->blksize; /* XXXX overflow? */ else resid = info; } else { resid = xs->datalen; } if (resid < 0 || resid > xs->datalen) xs->resid = xs->datalen; else xs->resid = resid; datalen = xs->datalen; if (ISSET(st->flags, ST_FIXEDBLOCKS)) { resid /= st->blksize; datalen /= st->blksize; } if (ISSET(sense->flags, SSD_FILEMARK)) { if (st->media_fileno != -1) { st->media_fileno++; if (st->media_fileno > st->media_eom) st->media_eom = st->media_fileno; st->media_blkno = 0; } if (!ISSET(st->flags, ST_FIXEDBLOCKS)) return 0; SET(st->flags, ST_AT_FILEMARK); } if (ISSET(sense->flags, SSD_EOM)) { SET(st->flags, ST_EOM_PENDING); xs->resid = 0; if (ISSET(st->flags, ST_FIXEDBLOCKS)) return 0; } if (ISSET(sense->flags, SSD_ILI)) { if (!ISSET(st->flags, ST_FIXEDBLOCKS)) { if (resid >= 0 && resid <= datalen) return 0; if (!ISSET(xs->flags, SCSI_SILENT)) printf( "%s: bad residual %d out of " "%d\n", st->sc_dev.dv_xname, resid, datalen); return EIO; } /* Fixed size blocks. */ if (ISSET(sense->error_code, SSD_ERRCODE_VALID)) if (!ISSET(xs->flags, SCSI_SILENT)) printf("%s: block wrong size, %d blocks " "residual\n", st->sc_dev.dv_xname, resid); SET(st->flags, ST_EIO_PENDING); /* * This quirk code helps the drive read the first tape block, * regardless of format. That is required for these drives to * return proper MODE SENSE information. */ if (ISSET(st->quirks, ST_Q_SENSE_HELP) && !ISSET(link->flags, SDEV_MEDIA_LOADED)) st->blksize -= 512; } if (ISSET(st->flags, ST_FIXEDBLOCKS) && xs->resid == xs->datalen) { if (ISSET(st->flags, ST_EIO_PENDING)) return EIO; if (ISSET(st->flags, ST_AT_FILEMARK)) return 0; } if (skey == SKEY_BLANK_CHECK) { /* * This quirk code helps the drive read the first tape block, * regardless of format. That is required for these drives to * return proper MODE SENSE information. */ if (ISSET(st->quirks, ST_Q_SENSE_HELP) && !ISSET(link->flags, SDEV_MEDIA_LOADED)) { /* still starting */ st->blksize -= 512; } else if (!ISSET(st->flags, ST_2FM_AT_EOD | ST_BLANK_READ)) { SET(st->flags, ST_BLANK_READ); SET(st->flags, ST_EOM_PENDING); xs->resid = xs->datalen; return 0; } } return scsi_interpret_sense(xs); } /* * The quirk here is that the drive returns some value to st_mode_sense * incorrectly until the tape has actually passed by the head. * * The method is to set the drive to large fixed-block state (user-specified * density and 1024-byte blocks), then read and rewind to get it to sense the * tape. If that doesn't work, try 512-byte fixed blocks. If that doesn't * work, as a last resort, try variable- length blocks. The result will be * the ability to do an accurate st_mode_sense. * * We know we can do a rewind because we just did a load, which implies rewind. * Rewind seems preferable to space backward if we have a virgin tape. * * The rest of the code for this quirk is in ILI processing and BLANK CHECK * error processing, both part of st_interpret_sense. */ int st_touch_tape(struct st_softc *st) { char *buf = NULL; int readsize, maxblksize = 1024; int error = 0; if ((error = st_mode_sense(st, 0)) != 0) goto done; buf = dma_alloc(maxblksize, PR_NOWAIT); if (buf == NULL) { error = ENOMEM; goto done; } st->blksize = 1024; do { switch (st->blksize) { case 512: case 1024: readsize = st->blksize; SET(st->flags, ST_FIXEDBLOCKS); break; default: readsize = 1; CLR(st->flags, ST_FIXEDBLOCKS); } if ((error = st_mode_select(st, 0)) != 0) goto done; st_read(st, buf, readsize, SCSI_SILENT); /* XXX */ if ((error = st_rewind(st, 0, 0)) != 0) goto done; } while (readsize != 1 && readsize > st->blksize); done: dma_free(buf, maxblksize); return error; }
1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 /* $OpenBSD: fido.c,v 1.6 2024/05/23 03:21:08 jsg Exp $ */ /* * Copyright (c) 2019 Reyk Floeter <reyk@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "fido.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> #include <sys/ioctl.h> #include <sys/conf.h> #include <sys/tty.h> #include <dev/usb/usb.h> #include <dev/usb/usbhid.h> #include <dev/usb/usbdi.h> #include <dev/usb/uhidev.h> #include <dev/usb/uhid.h> int fido_match(struct device *, void *, void *); struct cfdriver fido_cd = { NULL, "fido", DV_DULL }; const struct cfattach fido_ca = { sizeof(struct uhid_softc), fido_match, uhid_attach, uhid_detach, }; int fido_match(struct device *parent, void *match, void *aux) { struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux; int size; void *desc; int ret = UMATCH_NONE; if (UHIDEV_CLAIM_MULTIPLE_REPORTID(uha)) return (ret); /* Find the FIDO usage page and U2F collection */ uhidev_get_report_desc(uha->parent, &desc, &size); if (hid_is_collection(desc, size, uha->reportid, HID_USAGE2(HUP_FIDO, HUF_U2FHID))) ret = UMATCH_IFACECLASS; return (ret); } int fidoopen(dev_t dev, int flag, int mode, struct proc *p) { return (uhid_do_open(dev, flag, mode, p)); } int fidoioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { int error; switch (cmd) { case FIONBIO: case FIOASYNC: case USB_GET_DEVICEINFO: break; default: /* * Users don't need USB/HID ioctl access to fido(4) devices * but it can still be useful for debugging by root. */ if ((error = suser(p)) != 0) return (error); break; } return (uhidioctl(dev, cmd, addr, flag, p)); }
675 677 671 10 7 2 2 13 521 98 83 10 25 72 18 139 8 4 5 7 11 4 23 129 3 677 677 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 /* $OpenBSD: ffs_balloc.c,v 1.47 2024/04/13 23:44:11 jsg Exp $ */ /* $NetBSD: ffs_balloc.c,v 1.3 1996/02/09 22:22:21 christos Exp $ */ /* * Copyright (c) 2002 Networks Associates Technology, Inc. * All rights reserved. * * This software was developed for the FreeBSD Project by Marshall * Kirk McKusick and Network Associates Laboratories, the Security * Research Division of Network Associates, Inc. under DARPA/SPAWAR * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS * research program. * * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ffs_balloc.c 8.4 (Berkeley) 9/23/93 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/buf.h> #include <sys/proc.h> #include <sys/mount.h> #include <sys/vnode.h> #include <ufs/ufs/quota.h> #include <ufs/ufs/inode.h> #include <ufs/ufs/ufsmount.h> #include <ufs/ufs/ufs_extern.h> #include <ufs/ffs/fs.h> #include <ufs/ffs/ffs_extern.h> int ffs1_balloc(struct inode *, off_t, int, struct ucred *, int, struct buf **); #ifdef FFS2 int ffs2_balloc(struct inode *, off_t, int, struct ucred *, int, struct buf **); #endif /* * Balloc defines the structure of file system storage * by allocating the physical blocks on a device given * the inode and the logical block number in a file. */ int ffs1_balloc(struct inode *ip, off_t startoffset, int size, struct ucred *cred, int flags, struct buf **bpp) { daddr_t lbn, nb, newb, pref; struct fs *fs; struct buf *bp, *nbp; struct vnode *vp; struct proc *p; struct indir indirs[NIADDR + 2]; int32_t *bap; int deallocated, osize, nsize, num, i, error; int32_t *allocib, *blkp, *allocblk, allociblk[NIADDR+1]; int unwindidx = -1; vp = ITOV(ip); fs = ip->i_fs; p = curproc; lbn = lblkno(fs, startoffset); size = blkoff(fs, startoffset) + size; if (size > fs->fs_bsize) panic("ffs1_balloc: blk too big"); if (bpp != NULL) *bpp = NULL; if (lbn < 0) return (EFBIG); /* * If the next write will extend the file into a new block, * and the file is currently composed of a fragment * this fragment has to be extended to be a full block. */ nb = lblkno(fs, ip->i_ffs1_size); if (nb < NDADDR && nb < lbn) { osize = blksize(fs, ip, nb); if (osize < fs->fs_bsize && osize > 0) { error = ffs_realloccg(ip, nb, ffs1_blkpref(ip, nb, (int)nb, &ip->i_ffs1_db[0]), osize, (int)fs->fs_bsize, cred, bpp, &newb); if (error) return (error); ip->i_ffs1_size = lblktosize(fs, nb + 1); uvm_vnp_setsize(vp, ip->i_ffs1_size); ip->i_ffs1_db[nb] = newb; ip->i_flag |= IN_CHANGE | IN_UPDATE; if (bpp != NULL) { if (flags & B_SYNC) bwrite(*bpp); else bawrite(*bpp); } } } /* * The first NDADDR blocks are direct blocks */ if (lbn < NDADDR) { nb = ip->i_ffs1_db[lbn]; if (nb != 0 && ip->i_ffs1_size >= lblktosize(fs, lbn + 1)) { /* * The block is an already-allocated direct block * and the file already extends past this block, * thus this must be a whole block. * Just read the block (if requested). */ if (bpp != NULL) { error = bread(vp, lbn, fs->fs_bsize, bpp); if (error) { brelse(*bpp); return (error); } } return (0); } if (nb != 0) { /* * Consider need to reallocate a fragment. */ osize = fragroundup(fs, blkoff(fs, ip->i_ffs1_size)); nsize = fragroundup(fs, size); if (nsize <= osize) { /* * The existing block is already * at least as big as we want. * Just read the block (if requested). */ if (bpp != NULL) { error = bread(vp, lbn, fs->fs_bsize, bpp); if (error) { brelse(*bpp); return (error); } buf_adjcnt((*bpp), osize); } return (0); } else { /* * The existing block is smaller than we * want, grow it. */ error = ffs_realloccg(ip, lbn, ffs1_blkpref(ip, lbn, (int)lbn, &ip->i_ffs1_db[0]), osize, nsize, cred, bpp, &newb); if (error) return (error); } } else { /* * The block was not previously allocated, * allocate a new block or fragment. */ if (ip->i_ffs1_size < lblktosize(fs, lbn + 1)) nsize = fragroundup(fs, size); else nsize = fs->fs_bsize; error = ffs_alloc(ip, lbn, ffs1_blkpref(ip, lbn, (int)lbn, &ip->i_ffs1_db[0]), nsize, cred, &newb); if (error) return (error); if (bpp != NULL) { *bpp = getblk(vp, lbn, fs->fs_bsize, 0, INFSLP); if (nsize < fs->fs_bsize) (*bpp)->b_bcount = nsize; (*bpp)->b_blkno = fsbtodb(fs, newb); if (flags & B_CLRBUF) clrbuf(*bpp); } } ip->i_ffs1_db[lbn] = newb; ip->i_flag |= IN_CHANGE | IN_UPDATE; return (0); } /* * Determine the number of levels of indirection. */ pref = 0; if ((error = ufs_getlbns(vp, lbn, indirs, &num)) != 0) return(error); #ifdef DIAGNOSTIC if (num < 1) panic ("ffs1_balloc: ufs_bmaparray returned indirect block"); #endif /* * Fetch the first indirect block allocating if necessary. */ --num; nb = ip->i_ffs1_ib[indirs[0].in_off]; allocib = NULL; allocblk = allociblk; if (nb == 0) { pref = ffs1_blkpref(ip, lbn, -indirs[0].in_off - 1, NULL); error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &newb); if (error) goto fail; nb = newb; *allocblk++ = nb; bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, INFSLP); bp->b_blkno = fsbtodb(fs, nb); clrbuf(bp); /* * Write synchronously so that indirect blocks * never point at garbage. */ if ((error = bwrite(bp)) != 0) goto fail; allocib = &ip->i_ffs1_ib[indirs[0].in_off]; *allocib = nb; ip->i_flag |= IN_CHANGE | IN_UPDATE; } /* * Fetch through the indirect blocks, allocating as necessary. */ for (i = 1;;) { error = bread(vp, indirs[i].in_lbn, (int)fs->fs_bsize, &bp); if (error) { brelse(bp); goto fail; } bap = (int32_t *)bp->b_data; nb = bap[indirs[i].in_off]; if (i == num) break; i++; if (nb != 0) { brelse(bp); continue; } if (pref == 0) pref = ffs1_blkpref(ip, lbn, i - num - 1, NULL); error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &newb); if (error) { brelse(bp); goto fail; } nb = newb; *allocblk++ = nb; nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, INFSLP); nbp->b_blkno = fsbtodb(fs, nb); clrbuf(nbp); /* * Write synchronously so that indirect blocks * never point at garbage. */ if ((error = bwrite(nbp)) != 0) { brelse(bp); goto fail; } bap[indirs[i - 1].in_off] = nb; if (allocib == NULL && unwindidx < 0) unwindidx = i - 1; /* * If required, write synchronously, otherwise use * delayed write. */ if (flags & B_SYNC) { bwrite(bp); } else { bdwrite(bp); } } /* * Get the data block, allocating if necessary. */ if (nb == 0) { pref = ffs1_blkpref(ip, lbn, indirs[i].in_off, &bap[0]); error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &newb); if (error) { brelse(bp); goto fail; } nb = newb; *allocblk++ = nb; if (bpp != NULL) { nbp = getblk(vp, lbn, fs->fs_bsize, 0, INFSLP); nbp->b_blkno = fsbtodb(fs, nb); if (flags & B_CLRBUF) clrbuf(nbp); *bpp = nbp; } bap[indirs[i].in_off] = nb; /* * If required, write synchronously, otherwise use * delayed write. */ if (flags & B_SYNC) { bwrite(bp); } else { bdwrite(bp); } return (0); } brelse(bp); if (bpp != NULL) { if (flags & B_CLRBUF) { error = bread(vp, lbn, (int)fs->fs_bsize, &nbp); if (error) { brelse(nbp); goto fail; } } else { nbp = getblk(vp, lbn, fs->fs_bsize, 0, INFSLP); nbp->b_blkno = fsbtodb(fs, nb); } *bpp = nbp; } return (0); fail: /* * If we have failed to allocate any blocks, simply return the error. * This is the usual case and avoids the need to fsync the file. */ if (allocblk == allociblk && allocib == NULL && unwindidx == -1) return (error); /* * If we have failed part way through block allocation, we have to * deallocate any indirect blocks that we have allocated. We have to * fsync the file before we start to get rid of all of its * dependencies so that we do not leave them dangling. We have to sync * it at the end so that the softdep code does not find any untracked * changes. Although this is really slow, running out of disk space is * not expected to be a common occurrence. The error return from fsync * is ignored as we already have an error to return to the user. */ VOP_FSYNC(vp, p->p_ucred, MNT_WAIT, p); for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) { ffs_blkfree(ip, *blkp, fs->fs_bsize); deallocated += fs->fs_bsize; } if (allocib != NULL) { *allocib = 0; } else if (unwindidx >= 0) { int r; r = bread(vp, indirs[unwindidx].in_lbn, (int)fs->fs_bsize, &bp); if (r) panic("Could not unwind indirect block, error %d", r); bap = (int32_t *)bp->b_data; bap[indirs[unwindidx].in_off] = 0; if (flags & B_SYNC) { bwrite(bp); } else { bdwrite(bp); } } if (deallocated) { /* * Restore user's disk quota because allocation failed. */ (void)ufs_quota_free_blocks(ip, btodb(deallocated), cred); ip->i_ffs1_blocks -= btodb(deallocated); ip->i_flag |= IN_CHANGE | IN_UPDATE; } VOP_FSYNC(vp, p->p_ucred, MNT_WAIT, p); return (error); } #ifdef FFS2 int ffs2_balloc(struct inode *ip, off_t off, int size, struct ucred *cred, int flags, struct buf **bpp) { daddr_t lbn, lastlbn, nb, newb, *blkp; daddr_t pref, *allocblk, allociblk[NIADDR + 1]; daddr_t *bap, *allocib; int deallocated, osize, nsize, num, i, error, unwindidx, r; struct buf *bp, *nbp; struct indir indirs[NIADDR + 2]; struct fs *fs; struct vnode *vp; struct proc *p; vp = ITOV(ip); fs = ip->i_fs; p = curproc; unwindidx = -1; lbn = lblkno(fs, off); size = blkoff(fs, off) + size; if (size > fs->fs_bsize) panic("ffs2_balloc: block too big"); if (bpp != NULL) *bpp = NULL; if (lbn < 0) return (EFBIG); /* * If the next write will extend the file into a new block, and the * file is currently composed of a fragment, this fragment has to be * extended to be a full block. */ lastlbn = lblkno(fs, ip->i_ffs2_size); if (lastlbn < NDADDR && lastlbn < lbn) { nb = lastlbn; osize = blksize(fs, ip, nb); if (osize < fs->fs_bsize && osize > 0) { error = ffs_realloccg(ip, nb, ffs2_blkpref(ip, lastlbn, nb, &ip->i_ffs2_db[0]), osize, (int) fs->fs_bsize, cred, bpp, &newb); if (error) return (error); ip->i_ffs2_size = lblktosize(fs, nb + 1); uvm_vnp_setsize(vp, ip->i_ffs2_size); ip->i_ffs2_db[nb] = newb; ip->i_flag |= IN_CHANGE | IN_UPDATE; if (bpp) { if (flags & B_SYNC) bwrite(*bpp); else bawrite(*bpp); } } } /* * The first NDADDR blocks are direct. */ if (lbn < NDADDR) { nb = ip->i_ffs2_db[lbn]; if (nb != 0 && ip->i_ffs2_size >= lblktosize(fs, lbn + 1)) { /* * The direct block is already allocated and the file * extends past this block, thus this must be a whole * block. Just read it, if requested. */ if (bpp != NULL) { error = bread(vp, lbn, fs->fs_bsize, bpp); if (error) { brelse(*bpp); return (error); } } return (0); } if (nb != 0) { /* * Consider the need to allocate a fragment. */ osize = fragroundup(fs, blkoff(fs, ip->i_ffs2_size)); nsize = fragroundup(fs, size); if (nsize <= osize) { /* * The existing block is already at least as * big as we want. Just read it, if requested. */ if (bpp != NULL) { error = bread(vp, lbn, fs->fs_bsize, bpp); if (error) { brelse(*bpp); return (error); } buf_adjcnt((*bpp), osize); } return (0); } else { /* * The existing block is smaller than we want, * grow it. */ error = ffs_realloccg(ip, lbn, ffs2_blkpref(ip, lbn, (int) lbn, &ip->i_ffs2_db[0]), osize, nsize, cred, bpp, &newb); if (error) return (error); } } else { /* * The block was not previously allocated, allocate a * new block or fragment. */ if (ip->i_ffs2_size < lblktosize(fs, lbn + 1)) nsize = fragroundup(fs, size); else nsize = fs->fs_bsize; error = ffs_alloc(ip, lbn, ffs2_blkpref(ip, lbn, (int) lbn, &ip->i_ffs2_db[0]), nsize, cred, &newb); if (error) return (error); if (bpp != NULL) { bp = getblk(vp, lbn, fs->fs_bsize, 0, INFSLP); if (nsize < fs->fs_bsize) bp->b_bcount = nsize; bp->b_blkno = fsbtodb(fs, newb); if (flags & B_CLRBUF) clrbuf(bp); *bpp = bp; } } ip->i_ffs2_db[lbn] = newb; ip->i_flag |= IN_CHANGE | IN_UPDATE; return (0); } /* * Determine the number of levels of indirection. */ pref = 0; error = ufs_getlbns(vp, lbn, indirs, &num); if (error) return (error); #ifdef DIAGNOSTIC if (num < 1) panic("ffs2_balloc: ufs_bmaparray returned indirect block"); #endif /* * Fetch the first indirect block allocating it necessary. */ --num; nb = ip->i_ffs2_ib[indirs[0].in_off]; allocib = NULL; allocblk = allociblk; if (nb == 0) { pref = ffs2_blkpref(ip, lbn, -indirs[0].in_off - 1, NULL); error = ffs_alloc(ip, lbn, pref, (int) fs->fs_bsize, cred, &newb); if (error) goto fail; nb = newb; *allocblk++ = nb; bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, INFSLP); bp->b_blkno = fsbtodb(fs, nb); clrbuf(bp); /* * Write synchronously so that indirect blocks never * point at garbage. */ error = bwrite(bp); if (error) goto fail; unwindidx = 0; allocib = &ip->i_ffs2_ib[indirs[0].in_off]; *allocib = nb; ip->i_flag |= IN_CHANGE | IN_UPDATE; } /* * Fetch through the indirect blocks, allocating as necessary. */ for (i = 1;;) { error = bread(vp, indirs[i].in_lbn, (int)fs->fs_bsize, &bp); if (error) { brelse(bp); goto fail; } bap = (int64_t *) bp->b_data; nb = bap[indirs[i].in_off]; if (i == num) break; i++; if (nb != 0) { brelse(bp); continue; } if (pref == 0) pref = ffs2_blkpref(ip, lbn, i - num - 1, NULL); error = ffs_alloc(ip, lbn, pref, (int) fs->fs_bsize, cred, &newb); if (error) { brelse(bp); goto fail; } nb = newb; *allocblk++ = nb; nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, INFSLP); nbp->b_blkno = fsbtodb(fs, nb); clrbuf(nbp); /* * Write synchronously so that indirect blocks never * point at garbage. */ error = bwrite(nbp); if (error) { brelse(bp); goto fail; } if (unwindidx < 0) unwindidx = i - 1; bap[indirs[i - 1].in_off] = nb; /* * If required, write synchronously, otherwise use delayed * write. */ if (flags & B_SYNC) bwrite(bp); else bdwrite(bp); } /* * Get the data block, allocating if necessary. */ if (nb == 0) { pref = ffs2_blkpref(ip, lbn, indirs[num].in_off, &bap[0]); error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &newb); if (error) { brelse(bp); goto fail; } nb = newb; *allocblk++ = nb; if (bpp != NULL) { nbp = getblk(vp, lbn, fs->fs_bsize, 0, INFSLP); nbp->b_blkno = fsbtodb(fs, nb); if (flags & B_CLRBUF) clrbuf(nbp); *bpp = nbp; } bap[indirs[num].in_off] = nb; if (allocib == NULL && unwindidx < 0) unwindidx = i - 1; /* * If required, write synchronously, otherwise use delayed * write. */ if (flags & B_SYNC) bwrite(bp); else bdwrite(bp); return (0); } brelse(bp); if (bpp != NULL) { if (flags & B_CLRBUF) { error = bread(vp, lbn, (int)fs->fs_bsize, &nbp); if (error) { brelse(nbp); goto fail; } } else { nbp = getblk(vp, lbn, fs->fs_bsize, 0, INFSLP); nbp->b_blkno = fsbtodb(fs, nb); clrbuf(nbp); } *bpp = nbp; } return (0); fail: /* * If we have failed to allocate any blocks, simply return the error. * This is the usual case and avoids the need to fsync the file. */ if (allocblk == allociblk && allocib == NULL && unwindidx == -1) return (error); /* * If we have failed part way through block allocation, we have to * deallocate any indirect blocks that we have allocated. We have to * fsync the file before we start to get rid of all of its * dependencies so that we do not leave them dangling. We have to sync * it at the end so that the softdep code does not find any untracked * changes. Although this is really slow, running out of disk space is * not expected to be a common occurrence. The error return from fsync * is ignored as we already have an error to return to the user. */ VOP_FSYNC(vp, p->p_ucred, MNT_WAIT, p); if (unwindidx >= 0) { /* * First write out any buffers we've created to resolve their * softdeps. This must be done in reverse order of creation so * that we resolve the dependencies in one pass. * Write the cylinder group buffers for these buffers too. */ for (i = num; i >= unwindidx; i--) { if (i == 0) break; bp = getblk(vp, indirs[i].in_lbn, (int) fs->fs_bsize, 0, INFSLP); if (bp->b_flags & B_DELWRI) { nb = fsbtodb(fs, cgtod(fs, dtog(fs, dbtofsb(fs, bp->b_blkno)))); bwrite(bp); bp = getblk(ip->i_devvp, nb, (int) fs->fs_cgsize, 0, INFSLP); if (bp->b_flags & B_DELWRI) bwrite(bp); else { bp->b_flags |= B_INVAL; brelse(bp); } } else { bp->b_flags |= B_INVAL; brelse(bp); } } /* * Now that any dependencies that we created have been * resolved, we can undo the partial allocation. */ if (unwindidx == 0) { *allocib = 0; ip->i_flag |= IN_CHANGE | IN_UPDATE; } else { r = bread(vp, indirs[unwindidx].in_lbn, (int)fs->fs_bsize, &bp); if (r) panic("ffs2_balloc: unwind failed"); bap = (int64_t *) bp->b_data; bap[indirs[unwindidx].in_off] = 0; bwrite(bp); } for (i = unwindidx + 1; i <= num; i++) { bp = getblk(vp, indirs[i].in_lbn, (int)fs->fs_bsize, 0, INFSLP); bp->b_flags |= B_INVAL; brelse(bp); } } for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) { ffs_blkfree(ip, *blkp, fs->fs_bsize); deallocated += fs->fs_bsize; } if (deallocated) { /* * Restore user's disk quota because allocation failed. */ (void) ufs_quota_free_blocks(ip, btodb(deallocated), cred); ip->i_ffs2_blocks -= btodb(deallocated); ip->i_flag |= IN_CHANGE | IN_UPDATE; } VOP_FSYNC(vp, p->p_ucred, MNT_WAIT, p); return (error); } #endif /* FFS2 */ /* * Balloc defines the structure of file system storage by allocating the * physical blocks given the inode and the logical block number in a file. */ int ffs_balloc(struct inode *ip, off_t off, int size, struct ucred *cred, int flags, struct buf **bpp) { #ifdef FFS2 if (ip->i_fs->fs_magic == FS_UFS2_MAGIC) return (ffs2_balloc(ip, off, size, cred, flags, bpp)); else #endif return (ffs1_balloc(ip, off, size, cred, flags, bpp)); }
16 2 2 1 1 9 3 1 1 1 4 2 1 2 2 1 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 /* $OpenBSD: ipsec_input.c,v 1.206 2023/09/16 09:33:27 mpi Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr) and * Niels Provos (provos@physnet.uni-hamburg.de). * * This code was written by John Ioannidis for BSD/OS in Athens, Greece, * in November 1995. * * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, * by Angelos D. Keromytis. * * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis * and Niels Provos. * * Additional features in 1999 by Angelos D. Keromytis. * * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, * Angelos D. Keromytis and Niels Provos. * Copyright (c) 2001, Angelos D. Keromytis. * * Permission to use, copy, and modify this software with or without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or * modification of this software. * You may use this code under the GNU public license if you so wish. Please * contribute changes back to the authors under this freer than GPL license * so that we may further the use of strong encryption without limitations to * all. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR * PURPOSE. */ #include "pf.h" #include "sec.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/protosw.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/sysctl.h> #include <sys/kernel.h> #include <sys/timeout.h> #include <net/if.h> #include <net/if_var.h> #include <net/netisr.h> #include <net/bpf.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_var.h> #include <netinet/ip_icmp.h> #include <netinet/tcp.h> #include <netinet/udp.h> #if NPF > 0 #include <net/pfvar.h> #endif #if NSEC > 0 #include <net/if_sec.h> #endif #ifdef INET6 #include <netinet6/in6_var.h> #include <netinet/ip6.h> #include <netinet6/ip6_var.h> #endif /* INET6 */ #include <netinet/ip_ipsp.h> #include <netinet/ip_esp.h> #include <netinet/ip_ah.h> #include <netinet/ip_ipcomp.h> #include <net/if_enc.h> #include <crypto/cryptodev.h> #include <crypto/xform.h> #include "bpfilter.h" void ipsec_common_ctlinput(u_int, int, struct sockaddr *, void *, int); #ifdef ENCDEBUG #define DPRINTF(fmt, args...) \ do { \ if (encdebug) \ printf("%s: " fmt "\n", __func__, ## args); \ } while (0) #else #define DPRINTF(fmt, args...) \ do { } while (0) #endif /* sysctl variables */ int encdebug = 0; int ipsec_keep_invalid = IPSEC_DEFAULT_EMBRYONIC_SA_TIMEOUT; int ipsec_require_pfs = IPSEC_DEFAULT_PFS; int ipsec_soft_allocations = IPSEC_DEFAULT_SOFT_ALLOCATIONS; int ipsec_exp_allocations = IPSEC_DEFAULT_EXP_ALLOCATIONS; int ipsec_soft_bytes = IPSEC_DEFAULT_SOFT_BYTES; int ipsec_exp_bytes = IPSEC_DEFAULT_EXP_BYTES; int ipsec_soft_timeout = IPSEC_DEFAULT_SOFT_TIMEOUT; int ipsec_exp_timeout = IPSEC_DEFAULT_EXP_TIMEOUT; int ipsec_soft_first_use = IPSEC_DEFAULT_SOFT_FIRST_USE; int ipsec_exp_first_use = IPSEC_DEFAULT_EXP_FIRST_USE; int ipsec_expire_acquire = IPSEC_DEFAULT_EXPIRE_ACQUIRE; int esp_enable = 1; int ah_enable = 1; int ipcomp_enable = 0; const struct sysctl_bounded_args espctl_vars[] = { {ESPCTL_ENABLE, &esp_enable, 0, 1}, {ESPCTL_UDPENCAP_ENABLE, &udpencap_enable, 0, 1}, {ESPCTL_UDPENCAP_PORT, &udpencap_port, 0, 65535}, }; const struct sysctl_bounded_args ahctl_vars[] = { {AHCTL_ENABLE, &ah_enable, 0, 1}, }; const struct sysctl_bounded_args ipcompctl_vars[] = { {IPCOMPCTL_ENABLE, &ipcomp_enable, 0, 1}, }; struct cpumem *espcounters; struct cpumem *ahcounters; struct cpumem *ipcompcounters; struct cpumem *ipseccounters; char ipsec_def_enc[20]; char ipsec_def_auth[20]; char ipsec_def_comp[20]; const struct sysctl_bounded_args ipsecctl_vars[] = { { IPSEC_ENCDEBUG, &encdebug, 0, 1 }, { IPSEC_EXPIRE_ACQUIRE, &ipsec_expire_acquire, 0, INT_MAX }, { IPSEC_EMBRYONIC_SA_TIMEOUT, &ipsec_keep_invalid, 0, INT_MAX }, { IPSEC_REQUIRE_PFS, &ipsec_require_pfs, 0, 1 }, { IPSEC_SOFT_ALLOCATIONS, &ipsec_soft_allocations, 0, INT_MAX }, { IPSEC_ALLOCATIONS, &ipsec_exp_allocations, 0, INT_MAX }, { IPSEC_SOFT_BYTES, &ipsec_soft_bytes, 0, INT_MAX }, { IPSEC_BYTES, &ipsec_exp_bytes, 0, INT_MAX }, { IPSEC_TIMEOUT, &ipsec_exp_timeout, 0, INT_MAX }, { IPSEC_SOFT_TIMEOUT, &ipsec_soft_timeout,0, INT_MAX }, { IPSEC_SOFT_FIRSTUSE, &ipsec_soft_first_use, 0, INT_MAX }, { IPSEC_FIRSTUSE, &ipsec_exp_first_use, 0, INT_MAX }, }; int esp_sysctl_espstat(void *, size_t *, void *); int ah_sysctl_ahstat(void *, size_t *, void *); int ipcomp_sysctl_ipcompstat(void *, size_t *, void *); int ipsec_sysctl_ipsecstat(void *, size_t *, void *); void ipsec_init(void) { espcounters = counters_alloc(esps_ncounters); ahcounters = counters_alloc(ahs_ncounters); ipcompcounters = counters_alloc(ipcomps_ncounters); ipseccounters = counters_alloc(ipsec_ncounters); strlcpy(ipsec_def_enc, IPSEC_DEFAULT_DEF_ENC, sizeof(ipsec_def_enc)); strlcpy(ipsec_def_auth, IPSEC_DEFAULT_DEF_AUTH, sizeof(ipsec_def_auth)); strlcpy(ipsec_def_comp, IPSEC_DEFAULT_DEF_COMP, sizeof(ipsec_def_comp)); ipsp_init(); } /* * ipsec_common_input() gets called when we receive an IPsec-protected packet * in IPv4 or IPv6. All it does is find the right TDB and call the appropriate * transform. The callback takes care of further processing (like ingress * filtering). */ int ipsec_common_input(struct mbuf **mp, int skip, int protoff, int af, int sproto, int udpencap) { #define IPSEC_ISTAT(x,y,z) do { \ if (sproto == IPPROTO_ESP) \ espstat_inc(x); \ else if (sproto == IPPROTO_AH) \ ahstat_inc(y); \ else \ ipcompstat_inc(z); \ } while (0) struct mbuf *m = *mp; union sockaddr_union dst_address; struct tdb *tdbp = NULL; u_int32_t spi; u_int16_t cpi; int prot; #ifdef ENCDEBUG char buf[INET6_ADDRSTRLEN]; #endif NET_ASSERT_LOCKED(); ipsecstat_pkt(ipsec_ipackets, ipsec_ibytes, m->m_pkthdr.len); IPSEC_ISTAT(esps_input, ahs_input, ipcomps_input); if ((sproto == IPPROTO_IPCOMP) && (m->m_flags & M_COMP)) { DPRINTF("repeated decompression"); ipcompstat_inc(ipcomps_pdrops); goto drop; } if (m->m_pkthdr.len - skip < 2 * sizeof(u_int32_t)) { DPRINTF("packet too small"); IPSEC_ISTAT(esps_hdrops, ahs_hdrops, ipcomps_hdrops); goto drop; } /* Retrieve the SPI from the relevant IPsec header */ switch (sproto) { case IPPROTO_ESP: m_copydata(m, skip, sizeof(u_int32_t), (caddr_t) &spi); break; case IPPROTO_AH: m_copydata(m, skip + sizeof(u_int32_t), sizeof(u_int32_t), (caddr_t) &spi); break; case IPPROTO_IPCOMP: m_copydata(m, skip + sizeof(u_int16_t), sizeof(u_int16_t), (caddr_t) &cpi); spi = ntohl(htons(cpi)); break; default: panic("%s: unknown/unsupported security protocol %d", __func__, sproto); } /* * Find tunnel control block and (indirectly) call the appropriate * kernel crypto routine. The resulting mbuf chain is a valid * IP packet ready to go through input processing. */ memset(&dst_address, 0, sizeof(dst_address)); dst_address.sa.sa_family = af; switch (af) { case AF_INET: dst_address.sin.sin_len = sizeof(struct sockaddr_in); m_copydata(m, offsetof(struct ip, ip_dst), sizeof(struct in_addr), (caddr_t) &(dst_address.sin.sin_addr)); break; #ifdef INET6 case AF_INET6: dst_address.sin6.sin6_len = sizeof(struct sockaddr_in6); m_copydata(m, offsetof(struct ip6_hdr, ip6_dst), sizeof(struct in6_addr), (caddr_t) &(dst_address.sin6.sin6_addr)); in6_recoverscope(&dst_address.sin6, &dst_address.sin6.sin6_addr); break; #endif /* INET6 */ default: DPRINTF("unsupported protocol family %d", af); IPSEC_ISTAT(esps_nopf, ahs_nopf, ipcomps_nopf); goto drop; } tdbp = gettdb(rtable_l2(m->m_pkthdr.ph_rtableid), spi, &dst_address, sproto); if (tdbp == NULL) { DPRINTF("could not find SA for packet to %s, spi %08x", ipsp_address(&dst_address, buf, sizeof(buf)), ntohl(spi)); IPSEC_ISTAT(esps_notdb, ahs_notdb, ipcomps_notdb); goto drop; } if (tdbp->tdb_flags & TDBF_INVALID) { DPRINTF("attempted to use invalid SA %s/%08x/%u", ipsp_address(&dst_address, buf, sizeof(buf)), ntohl(spi), tdbp->tdb_sproto); IPSEC_ISTAT(esps_invalid, ahs_invalid, ipcomps_invalid); goto drop; } if (udpencap && !(tdbp->tdb_flags & TDBF_UDPENCAP)) { DPRINTF("attempted to use non-udpencap SA %s/%08x/%u", ipsp_address(&dst_address, buf, sizeof(buf)), ntohl(spi), tdbp->tdb_sproto); espstat_inc(esps_udpinval); goto drop; } if (!udpencap && (tdbp->tdb_flags & TDBF_UDPENCAP)) { DPRINTF("attempted to use udpencap SA %s/%08x/%u", ipsp_address(&dst_address, buf, sizeof(buf)), ntohl(spi), tdbp->tdb_sproto); espstat_inc(esps_udpneeded); goto drop; } if (tdbp->tdb_xform == NULL) { DPRINTF("attempted to use uninitialized SA %s/%08x/%u", ipsp_address(&dst_address, buf, sizeof(buf)), ntohl(spi), tdbp->tdb_sproto); IPSEC_ISTAT(esps_noxform, ahs_noxform, ipcomps_noxform); goto drop; } KERNEL_LOCK(); /* Register first use, setup expiration timer. */ if (tdbp->tdb_first_use == 0) { tdbp->tdb_first_use = gettime(); if (tdbp->tdb_flags & TDBF_FIRSTUSE) { if (timeout_add_sec(&tdbp->tdb_first_tmo, tdbp->tdb_exp_first_use)) tdb_ref(tdbp); } if (tdbp->tdb_flags & TDBF_SOFT_FIRSTUSE) { if (timeout_add_sec(&tdbp->tdb_sfirst_tmo, tdbp->tdb_soft_first_use)) tdb_ref(tdbp); } } tdbstat_pkt(tdbp, tdb_ipackets, tdb_ibytes, m->m_pkthdr.len); /* * Call appropriate transform and return -- callback takes care of * everything else. */ prot = (*(tdbp->tdb_xform->xf_input))(mp, tdbp, skip, protoff); if (prot == IPPROTO_DONE) { ipsecstat_inc(ipsec_idrops); tdbstat_inc(tdbp, tdb_idrops); } tdb_unref(tdbp); KERNEL_UNLOCK(); return prot; drop: m_freemp(mp); ipsecstat_inc(ipsec_idrops); if (tdbp != NULL) tdbstat_inc(tdbp, tdb_idrops); tdb_unref(tdbp); return IPPROTO_DONE; } /* * IPsec input callback, called by the transform callback. Takes care of * filtering and other sanity checks on the processed packet. */ int ipsec_common_input_cb(struct mbuf **mp, struct tdb *tdbp, int skip, int protoff) { struct mbuf *m = *mp; int af, sproto; u_int8_t prot; #if NBPFILTER > 0 struct ifnet *encif; #endif struct ip *ip; #ifdef INET6 struct ip6_hdr *ip6; #endif /* INET6 */ struct m_tag *mtag; struct tdb_ident *tdbi; #ifdef ENCDEBUG char buf[INET6_ADDRSTRLEN]; #endif af = tdbp->tdb_dst.sa.sa_family; sproto = tdbp->tdb_sproto; tdbp->tdb_last_used = gettime(); /* Fix IPv4 header */ if (af == AF_INET) { if (m->m_len < skip && (m = *mp = m_pullup(m, skip)) == NULL) { DPRINTF("processing failed for SA %s/%08x", ipsp_address(&tdbp->tdb_dst, buf, sizeof(buf)), ntohl(tdbp->tdb_spi)); IPSEC_ISTAT(esps_hdrops, ahs_hdrops, ipcomps_hdrops); goto baddone; } ip = mtod(m, struct ip *); ip->ip_len = htons(m->m_pkthdr.len); in_hdr_cksum_out(m, NULL); prot = ip->ip_p; } #ifdef INET6 /* Fix IPv6 header */ if (af == AF_INET6) { if (m->m_len < sizeof(struct ip6_hdr) && (m = *mp = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) { DPRINTF("processing failed for SA %s/%08x", ipsp_address(&tdbp->tdb_dst, buf, sizeof(buf)), ntohl(tdbp->tdb_spi)); IPSEC_ISTAT(esps_hdrops, ahs_hdrops, ipcomps_hdrops); goto baddone; } ip6 = mtod(m, struct ip6_hdr *); ip6->ip6_plen = htons(m->m_pkthdr.len - skip); /* Save protocol */ m_copydata(m, protoff, 1, (caddr_t) &prot); } #endif /* INET6 */ /* * Fix TCP/UDP checksum of UDP encapsulated transport mode ESP packet. * (RFC3948 3.1.2) */ if ((af == AF_INET || af == AF_INET6) && (tdbp->tdb_flags & TDBF_UDPENCAP) && (tdbp->tdb_flags & TDBF_TUNNELING) == 0) { u_int16_t cksum; switch (prot) { case IPPROTO_UDP: if (m->m_pkthdr.len < skip + sizeof(struct udphdr)) { IPSEC_ISTAT(esps_hdrops, ahs_hdrops, ipcomps_hdrops); goto baddone; } cksum = 0; m_copyback(m, skip + offsetof(struct udphdr, uh_sum), sizeof(cksum), &cksum, M_NOWAIT); #ifdef INET6 if (af == AF_INET6) { cksum = in6_cksum(m, IPPROTO_UDP, skip, m->m_pkthdr.len - skip); m_copyback(m, skip + offsetof(struct udphdr, uh_sum), sizeof(cksum), &cksum, M_NOWAIT); } #endif break; case IPPROTO_TCP: if (m->m_pkthdr.len < skip + sizeof(struct tcphdr)) { IPSEC_ISTAT(esps_hdrops, ahs_hdrops, ipcomps_hdrops); goto baddone; } cksum = 0; m_copyback(m, skip + offsetof(struct tcphdr, th_sum), sizeof(cksum), &cksum, M_NOWAIT); if (af == AF_INET) cksum = in4_cksum(m, IPPROTO_TCP, skip, m->m_pkthdr.len - skip); #ifdef INET6 else if (af == AF_INET6) cksum = in6_cksum(m, IPPROTO_TCP, skip, m->m_pkthdr.len - skip); #endif m_copyback(m, skip + offsetof(struct tcphdr, th_sum), sizeof(cksum), &cksum, M_NOWAIT); break; } } /* * Record what we've done to the packet (under what SA it was * processed). */ if (tdbp->tdb_sproto != IPPROTO_IPCOMP) { mtag = m_tag_get(PACKET_TAG_IPSEC_IN_DONE, sizeof(struct tdb_ident), M_NOWAIT); if (mtag == NULL) { DPRINTF("failed to get tag"); IPSEC_ISTAT(esps_hdrops, ahs_hdrops, ipcomps_hdrops); goto baddone; } tdbi = (struct tdb_ident *)(mtag + 1); tdbi->dst = tdbp->tdb_dst; tdbi->proto = tdbp->tdb_sproto; tdbi->spi = tdbp->tdb_spi; tdbi->rdomain = tdbp->tdb_rdomain; m_tag_prepend(m, mtag); } switch (sproto) { case IPPROTO_ESP: /* Packet is confidential ? */ if (tdbp->tdb_encalgxform) m->m_flags |= M_CONF; /* Check if we had authenticated ESP. */ if (tdbp->tdb_authalgxform) m->m_flags |= M_AUTH; break; case IPPROTO_AH: m->m_flags |= M_AUTH; break; case IPPROTO_IPCOMP: m->m_flags |= M_COMP; break; default: panic("%s: unknown/unsupported security protocol %d", __func__, sproto); } #if NPF > 0 /* Add pf tag if requested. */ pf_tag_packet(m, tdbp->tdb_tag, -1); pf_pkt_addr_changed(m); #endif if (tdbp->tdb_rdomain != tdbp->tdb_rdomain_post) m->m_pkthdr.ph_rtableid = tdbp->tdb_rdomain_post; if (tdbp->tdb_flags & TDBF_TUNNELING) m->m_flags |= M_TUNNEL; ipsecstat_add(ipsec_idecompbytes, m->m_pkthdr.len); tdbstat_add(tdbp, tdb_idecompbytes, m->m_pkthdr.len); #if NBPFILTER > 0 encif = enc_getif(tdbp->tdb_rdomain_post, tdbp->tdb_tap); if (encif != NULL) { encif->if_ipackets++; encif->if_ibytes += m->m_pkthdr.len; if (sproto != IPPROTO_IPCOMP) { /* XXX This conflicts with the scoped nature of IPv6 */ m->m_pkthdr.ph_ifidx = encif->if_index; } if (encif->if_bpf) { struct enchdr hdr; hdr.af = af; hdr.spi = tdbp->tdb_spi; hdr.flags = m->m_flags & (M_AUTH|M_CONF); bpf_mtap_hdr(encif->if_bpf, (char *)&hdr, ENC_HDRLEN, m, BPF_DIRECTION_IN); } } #endif if (ISSET(tdbp->tdb_flags, TDBF_IFACE)) { #if NSEC > 0 if (ISSET(tdbp->tdb_flags, TDBF_TUNNELING) && tdbp->tdb_iface_dir == IPSP_DIRECTION_IN) { struct sec_softc *sc = sec_get(tdbp->tdb_iface); if (sc == NULL) goto baddone; sec_input(sc, af, prot, m); sec_put(sc); return IPPROTO_DONE; } #endif /* NSEC > 0 */ goto baddone; } #if NPF > 0 /* * The ip_deliver() shortcut avoids running through ip_input() with the * same IP header twice. Packets in transport mode have to be be * passed to pf explicitly. In tunnel mode the inner IP header will * run through ip_input() and pf anyway. */ if ((tdbp->tdb_flags & TDBF_TUNNELING) == 0) { struct ifnet *ifp; /* This is the enc0 interface unless for ipcomp. */ if ((ifp = if_get(m->m_pkthdr.ph_ifidx)) == NULL) { goto baddone; } if (pf_test(af, PF_IN, ifp, mp) != PF_PASS) { if_put(ifp); goto baddone; } m = *mp; if_put(ifp); if (m == NULL) return IPPROTO_DONE; } #endif /* Return to the appropriate protocol handler in deliver loop. */ return prot; baddone: m_freemp(mp); return IPPROTO_DONE; #undef IPSEC_ISTAT } int ipsec_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int error; switch (name[0]) { case IPCTL_IPSEC_ENC_ALGORITHM: NET_LOCK(); error = sysctl_tstring(oldp, oldlenp, newp, newlen, ipsec_def_enc, sizeof(ipsec_def_enc)); NET_UNLOCK(); return (error); case IPCTL_IPSEC_AUTH_ALGORITHM: NET_LOCK(); error = sysctl_tstring(oldp, oldlenp, newp, newlen, ipsec_def_auth, sizeof(ipsec_def_auth)); NET_UNLOCK(); return (error); case IPCTL_IPSEC_IPCOMP_ALGORITHM: NET_LOCK(); error = sysctl_tstring(oldp, oldlenp, newp, newlen, ipsec_def_comp, sizeof(ipsec_def_comp)); NET_UNLOCK(); return (error); case IPCTL_IPSEC_STATS: return (ipsec_sysctl_ipsecstat(oldp, oldlenp, newp)); default: NET_LOCK(); error = sysctl_bounded_arr(ipsecctl_vars, nitems(ipsecctl_vars), name, namelen, oldp, oldlenp, newp, newlen); NET_UNLOCK(); return (error); } } int esp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int error; /* All sysctl names at this level are terminal. */ if (namelen != 1) return (ENOTDIR); switch (name[0]) { case ESPCTL_STATS: return (esp_sysctl_espstat(oldp, oldlenp, newp)); default: NET_LOCK(); error = sysctl_bounded_arr(espctl_vars, nitems(espctl_vars), name, namelen, oldp, oldlenp, newp, newlen); NET_UNLOCK(); return (error); } } int esp_sysctl_espstat(void *oldp, size_t *oldlenp, void *newp) { struct espstat espstat; CTASSERT(sizeof(espstat) == (esps_ncounters * sizeof(uint64_t))); memset(&espstat, 0, sizeof espstat); counters_read(espcounters, (uint64_t *)&espstat, esps_ncounters, NULL); return (sysctl_rdstruct(oldp, oldlenp, newp, &espstat, sizeof(espstat))); } int ah_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int error; /* All sysctl names at this level are terminal. */ if (namelen != 1) return (ENOTDIR); switch (name[0]) { case AHCTL_STATS: return ah_sysctl_ahstat(oldp, oldlenp, newp); default: NET_LOCK(); error = sysctl_bounded_arr(ahctl_vars, nitems(ahctl_vars), name, namelen, oldp, oldlenp, newp, newlen); NET_UNLOCK(); return (error); } } int ah_sysctl_ahstat(void *oldp, size_t *oldlenp, void *newp) { struct ahstat ahstat; CTASSERT(sizeof(ahstat) == (ahs_ncounters * sizeof(uint64_t))); memset(&ahstat, 0, sizeof ahstat); counters_read(ahcounters, (uint64_t *)&ahstat, ahs_ncounters, NULL); return (sysctl_rdstruct(oldp, oldlenp, newp, &ahstat, sizeof(ahstat))); } int ipcomp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int error; /* All sysctl names at this level are terminal. */ if (namelen != 1) return (ENOTDIR); switch (name[0]) { case IPCOMPCTL_STATS: return ipcomp_sysctl_ipcompstat(oldp, oldlenp, newp); default: NET_LOCK(); error = sysctl_bounded_arr(ipcompctl_vars, nitems(ipcompctl_vars), name, namelen, oldp, oldlenp, newp, newlen); NET_UNLOCK(); return (error); } } int ipcomp_sysctl_ipcompstat(void *oldp, size_t *oldlenp, void *newp) { struct ipcompstat ipcompstat; CTASSERT(sizeof(ipcompstat) == (ipcomps_ncounters * sizeof(uint64_t))); memset(&ipcompstat, 0, sizeof ipcompstat); counters_read(ipcompcounters, (uint64_t *)&ipcompstat, ipcomps_ncounters, NULL); return (sysctl_rdstruct(oldp, oldlenp, newp, &ipcompstat, sizeof(ipcompstat))); } int ipsec_sysctl_ipsecstat(void *oldp, size_t *oldlenp, void *newp) { struct ipsecstat ipsecstat; CTASSERT(sizeof(ipsecstat) == (ipsec_ncounters * sizeof(uint64_t))); memset(&ipsecstat, 0, sizeof ipsecstat); counters_read(ipseccounters, (uint64_t *)&ipsecstat, ipsec_ncounters, NULL); return (sysctl_rdstruct(oldp, oldlenp, newp, &ipsecstat, sizeof(ipsecstat))); } int ipsec_input_disabled(struct mbuf **mp, int *offp, int proto, int af) { switch (af) { case AF_INET: return rip_input(mp, offp, proto, af); #ifdef INET6 case AF_INET6: return rip6_input(mp, offp, proto, af); #endif default: unhandled_af(af); } } int ah46_input(struct mbuf **mp, int *offp, int proto, int af) { int protoff; if ( #if NPF > 0 ((*mp)->m_pkthdr.pf.flags & PF_TAG_DIVERTED) || #endif !ah_enable) return ipsec_input_disabled(mp, offp, proto, af); protoff = ipsec_protoff(*mp, *offp, af); if (protoff < 0) { DPRINTF("bad packet header chain"); ahstat_inc(ahs_hdrops); m_freemp(mp); return IPPROTO_DONE; } return ipsec_common_input(mp, *offp, protoff, af, proto, 0); } void ah4_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *v) { if (sa->sa_family != AF_INET || sa->sa_len != sizeof(struct sockaddr_in)) return; ipsec_common_ctlinput(rdomain, cmd, sa, v, IPPROTO_AH); } int esp46_input(struct mbuf **mp, int *offp, int proto, int af) { int protoff; if ( #if NPF > 0 ((*mp)->m_pkthdr.pf.flags & PF_TAG_DIVERTED) || #endif !esp_enable) return ipsec_input_disabled(mp, offp, proto, af); protoff = ipsec_protoff(*mp, *offp, af); if (protoff < 0) { DPRINTF("bad packet header chain"); espstat_inc(esps_hdrops); m_freemp(mp); return IPPROTO_DONE; } return ipsec_common_input(mp, *offp, protoff, af, proto, 0); } /* IPv4 IPCOMP wrapper */ int ipcomp46_input(struct mbuf **mp, int *offp, int proto, int af) { int protoff; if ( #if NPF > 0 ((*mp)->m_pkthdr.pf.flags & PF_TAG_DIVERTED) || #endif !ipcomp_enable) return ipsec_input_disabled(mp, offp, proto, af); protoff = ipsec_protoff(*mp, *offp, af); if (protoff < 0) { DPRINTF("bad packet header chain"); ipcompstat_inc(ipcomps_hdrops); m_freemp(mp); return IPPROTO_DONE; } return ipsec_common_input(mp, *offp, protoff, af, proto, 0); } void ipsec_set_mtu(struct tdb *tdbp, u_int32_t mtu) { ssize_t adjust; NET_ASSERT_LOCKED(); /* Walk the chain backwards to the first tdb */ for (; tdbp != NULL; tdbp = tdbp->tdb_inext) { if (tdbp->tdb_flags & TDBF_INVALID || (adjust = ipsec_hdrsz(tdbp)) == -1) return; mtu -= adjust; /* Store adjusted MTU in tdb */ tdbp->tdb_mtu = mtu; tdbp->tdb_mtutimeout = gettime() + ip_mtudisc_timeout; DPRINTF("spi %08x mtu %d adjust %ld", ntohl(tdbp->tdb_spi), tdbp->tdb_mtu, adjust); } } void ipsec_common_ctlinput(u_int rdomain, int cmd, struct sockaddr *sa, void *v, int proto) { struct ip *ip = v; if (cmd == PRC_MSGSIZE && ip && ip_mtudisc && ip->ip_v == 4) { struct tdb *tdbp; struct sockaddr_in dst; struct icmp *icp; int hlen = ip->ip_hl << 2; u_int32_t spi, mtu; /* Find the right MTU. */ icp = (struct icmp *)((caddr_t) ip - offsetof(struct icmp, icmp_ip)); mtu = ntohs(icp->icmp_nextmtu); /* * Ignore the packet, if we do not receive a MTU * or the MTU is too small to be acceptable. */ if (mtu < 296) return; memset(&dst, 0, sizeof(struct sockaddr_in)); dst.sin_family = AF_INET; dst.sin_len = sizeof(struct sockaddr_in); dst.sin_addr.s_addr = ip->ip_dst.s_addr; memcpy(&spi, (caddr_t)ip + hlen, sizeof(u_int32_t)); tdbp = gettdb_rev(rdomain, spi, (union sockaddr_union *)&dst, proto); ipsec_set_mtu(tdbp, mtu); tdb_unref(tdbp); } } void udpencap_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *v) { struct ip *ip = v; struct tdb *tdbp, *first; struct icmp *icp; u_int32_t mtu; struct sockaddr_in dst, src; union sockaddr_union *su_dst, *su_src; NET_ASSERT_LOCKED(); icp = (struct icmp *)((caddr_t) ip - offsetof(struct icmp, icmp_ip)); mtu = ntohs(icp->icmp_nextmtu); /* * Ignore the packet, if we do not receive a MTU * or the MTU is too small to be acceptable. */ if (mtu < 296) return; memset(&dst, 0, sizeof(dst)); dst.sin_family = AF_INET; dst.sin_len = sizeof(struct sockaddr_in); dst.sin_addr.s_addr = ip->ip_dst.s_addr; su_dst = (union sockaddr_union *)&dst; memset(&src, 0, sizeof(src)); src.sin_family = AF_INET; src.sin_len = sizeof(struct sockaddr_in); src.sin_addr.s_addr = ip->ip_src.s_addr; su_src = (union sockaddr_union *)&src; first = gettdbbysrcdst_rev(rdomain, 0, su_src, su_dst, IPPROTO_ESP); mtx_enter(&tdb_sadb_mtx); for (tdbp = first; tdbp != NULL; tdbp = tdbp->tdb_snext) { if (tdbp->tdb_sproto == IPPROTO_ESP && ((tdbp->tdb_flags & (TDBF_INVALID|TDBF_UDPENCAP)) == TDBF_UDPENCAP) && !memcmp(&tdbp->tdb_dst, &dst, su_dst->sa.sa_len) && !memcmp(&tdbp->tdb_src, &src, su_src->sa.sa_len)) ipsec_set_mtu(tdbp, mtu); } mtx_leave(&tdb_sadb_mtx); tdb_unref(first); } void esp4_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *v) { if (sa->sa_family != AF_INET || sa->sa_len != sizeof(struct sockaddr_in)) return; ipsec_common_ctlinput(rdomain, cmd, sa, v, IPPROTO_ESP); } /* Find the offset of the next protocol field in the previous header. */ int ipsec_protoff(struct mbuf *m, int off, int af) { #ifdef INET6 struct ip6_ext ip6e; int protoff, nxt, l; #endif /* INET6 */ switch (af) { case AF_INET: return offsetof(struct ip, ip_p); #ifdef INET6 case AF_INET6: break; #endif /* INET6 */ default: unhandled_af(af); } #ifdef INET6 if (off < sizeof(struct ip6_hdr)) return -1; if (off == sizeof(struct ip6_hdr)) return offsetof(struct ip6_hdr, ip6_nxt); /* Chase down the header chain... */ protoff = sizeof(struct ip6_hdr); nxt = (mtod(m, struct ip6_hdr *))->ip6_nxt; l = 0; do { protoff += l; m_copydata(m, protoff, sizeof(ip6e), (caddr_t) &ip6e); if (nxt == IPPROTO_AH) l = (ip6e.ip6e_len + 2) << 2; else l = (ip6e.ip6e_len + 1) << 3; #ifdef DIAGNOSTIC if (l <= 0) panic("%s: l went zero or negative", __func__); #endif nxt = ip6e.ip6e_nxt; } while (protoff + l < off); /* Malformed packet check */ if (protoff + l != off) return -1; protoff += offsetof(struct ip6_ext, ip6e_nxt); return protoff; #endif /* INET6 */ } int ipsec_forward_check(struct mbuf *m, int hlen, int af) { struct tdb *tdb; struct tdb_ident *tdbi; struct m_tag *mtag; int error = 0; /* * IPsec policy check for forwarded packets. Look at * inner-most IPsec SA used. */ mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); if (mtag != NULL) { tdbi = (struct tdb_ident *)(mtag + 1); tdb = gettdb(tdbi->rdomain, tdbi->spi, &tdbi->dst, tdbi->proto); } else tdb = NULL; error = ipsp_spd_lookup(m, af, hlen, IPSP_DIRECTION_IN, tdb, NULL, NULL, NULL); tdb_unref(tdb); return error; } int ipsec_local_check(struct mbuf *m, int hlen, int proto, int af) { struct tdb *tdb; struct tdb_ident *tdbi; struct m_tag *mtag; int error = 0; /* * If it's a protected packet for us, skip the policy check. * That's because we really only care about the properties of * the protected packet, and not the intermediate versions. * While this is not the most paranoid setting, it allows * some flexibility in handling nested tunnels (in setting up * the policies). */ if ((proto == IPPROTO_ESP) || (proto == IPPROTO_AH) || (proto == IPPROTO_IPCOMP)) return 0; /* * If the protected packet was tunneled, then we need to * verify the protected packet's information, not the * external headers. Thus, skip the policy lookup for the * external packet, and keep the IPsec information linked on * the packet header (the encapsulation routines know how * to deal with that). */ if ((proto == IPPROTO_IPV4) || (proto == IPPROTO_IPV6)) return 0; /* * When processing IPv6 header chains, do not look at the * outer header. The inner protocol is relevant and will * be checked by the local delivery loop later. */ if ((af == AF_INET6) && ((proto == IPPROTO_DSTOPTS) || (proto == IPPROTO_ROUTING) || (proto == IPPROTO_FRAGMENT))) return 0; /* * If the protected packet is TCP or UDP, we'll do the * policy check in the respective input routine, so we can * check for bypass sockets. */ if ((proto == IPPROTO_TCP) || (proto == IPPROTO_UDP)) return 0; /* * IPsec policy check for local-delivery packets. Look at the * inner-most SA that protected the packet. This is in fact * a bit too restrictive (it could end up causing packets to * be dropped that semantically follow the policy, e.g., in * certain SA-bundle configurations); but the alternative is * very complicated (and requires keeping track of what * kinds of tunneling headers have been seen in-between the * IPsec headers), and I don't think we lose much functionality * that's needed in the real world (who uses bundles anyway ?). */ mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); if (mtag) { tdbi = (struct tdb_ident *)(mtag + 1); tdb = gettdb(tdbi->rdomain, tdbi->spi, &tdbi->dst, tdbi->proto); } else tdb = NULL; error = ipsp_spd_lookup(m, af, hlen, IPSP_DIRECTION_IN, tdb, NULL, NULL, NULL); tdb_unref(tdb); return error; }
3 11 2 2 2 7 7 10 10 8 1 2 1 4 2 2 3 5 66 66 1 2 1 1 60 7 2 7 4 57 4 24 23 3 11 1 19 3 8 24 37 8 50 2 54 24 37 4 53 261 71 322 287 41 321 2 190 180 8 1 131 8 13 133 5 6 6 5 137 136 25 10 35 1 11 3 21 20 5 17 3 9 2 1 2 1 10 4 7 10 3 13 1 2 1 1 1 2 6 10 4 14 1 3 1 1 8 13 4 29 1 6 1 1 6 14 1 1 12 2 1 6 3 10 17 16 1 11 5 2 2 8 4 10 6 5 10 1 5 4 6 3 5 5 2 7 1 1 5 5 5 3 3 1 2 5 7 4 3 8 8 3 5 9 3 12 1 1 2 8 8 1 4 4 4 9 5 14 1 5 1 7 3 1 1 1 11 4 8 1 7 8 9 2 3 2 2 2 5 22 2 9 12 6 16 2 15 3 9 8 8 8 5 2 5 1 1 1 2 3 2 6 8 8 32 3 1 28 1 18 1 3 14 22 4 1 19 8 4 4 72 10 82 4 9 36 23 12 3 2 36 29 1 6 1 6 78 21 8 29 8 1 2 19 12 12 1 4 1 1 3 2 7 19 14 8 9 14 14 1 12 48 4 44 10 1 8 52 4 48 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 /* $OpenBSD: vfs_syscalls.c,v 1.365 2024/05/18 05:20:22 guenther Exp $ */ /* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)vfs_syscalls.c 8.28 (Berkeley) 12/10/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/namei.h> #include <sys/filedesc.h> #include <sys/conf.h> #include <sys/fcntl.h> #include <sys/file.h> #include <sys/stat.h> #include <sys/lock.h> #include <sys/vnode.h> #include <sys/mount.h> #include <sys/proc.h> #include <sys/pledge.h> #include <sys/uio.h> #include <sys/malloc.h> #include <sys/pool.h> #include <sys/ktrace.h> #include <sys/unistd.h> #include <sys/specdev.h> #include <sys/resourcevar.h> #include <sys/signalvar.h> #include <sys/syscallargs.h> extern int suid_clear; static int change_dir(struct nameidata *, struct proc *); void checkdirs(struct vnode *); int copyout_statfs(struct statfs *, void *, struct proc *); int doopenat(struct proc *, int, const char *, int, mode_t, register_t *); int domknodat(struct proc *, int, const char *, mode_t, dev_t); int dolinkat(struct proc *, int, const char *, int, const char *, int); int dosymlinkat(struct proc *, const char *, int, const char *); int dounlinkat(struct proc *, int, const char *, int); int dofaccessat(struct proc *, int, const char *, int, int); int dofstatat(struct proc *, int, const char *, struct stat *, int); int dopathconfat(struct proc *, int, const char *, int, int, register_t *); int doreadlinkat(struct proc *, int, const char *, char *, size_t, register_t *); int dochflagsat(struct proc *, int, const char *, u_int, int); int dovchflags(struct proc *, struct vnode *, u_int); int dofchmodat(struct proc *, int, const char *, mode_t, int); int dofchownat(struct proc *, int, const char *, uid_t, gid_t, int); int dorenameat(struct proc *, int, const char *, int, const char *); int domkdirat(struct proc *, int, const char *, mode_t); int doutimensat(struct proc *, int, const char *, struct timespec [2], int); int dovutimens(struct proc *, struct vnode *, struct timespec [2]); int dofutimens(struct proc *, int, struct timespec [2]); int dounmount_leaf(struct mount *, int, struct proc *); /* * Virtual File System System Calls */ /* * Mount a file system. */ int sys_mount(struct proc *p, void *v, register_t *retval) { struct sys_mount_args /* { syscallarg(const char *) type; syscallarg(const char *) path; syscallarg(int) flags; syscallarg(void *) data; } */ *uap = v; struct vnode *vp; struct mount *mp; int error, mntflag = 0; char fstypename[MFSNAMELEN]; char fspath[MNAMELEN]; struct nameidata nd; struct vfsconf *vfsp; int flags = SCARG(uap, flags); void *args = NULL; if ((error = suser(p))) return (error); /* * Mount points must fit in MNAMELEN, not MAXPATHLEN. */ error = copyinstr(SCARG(uap, path), fspath, MNAMELEN, NULL); if (error) return(error); /* * Get vnode to be covered */ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspath, p); if ((error = namei(&nd)) != 0) goto fail; vp = nd.ni_vp; if (flags & MNT_UPDATE) { if ((vp->v_flag & VROOT) == 0) { vput(vp); error = EINVAL; goto fail; } mp = vp->v_mount; vfsp = mp->mnt_vfc; args = malloc(vfsp->vfc_datasize, M_TEMP, M_WAITOK | M_ZERO); error = copyin(SCARG(uap, data), args, vfsp->vfc_datasize); if (error) { vput(vp); goto fail; } mntflag = mp->mnt_flag; /* * We only allow the filesystem to be reloaded if it * is currently mounted read-only. */ if ((flags & MNT_RELOAD) && ((mp->mnt_flag & MNT_RDONLY) == 0)) { vput(vp); error = EOPNOTSUPP; /* Needs translation */ goto fail; } if ((error = vfs_busy(mp, VB_READ|VB_NOWAIT)) != 0) { vput(vp); goto fail; } mp->mnt_flag |= flags & (MNT_RELOAD | MNT_UPDATE); goto update; } /* * Do not allow disabling of permission checks unless exec and access to * device files is disabled too. */ if ((flags & MNT_NOPERM) && (flags & (MNT_NODEV | MNT_NOEXEC)) != (MNT_NODEV | MNT_NOEXEC)) { vput(vp); error = EPERM; goto fail; } if ((error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, INFSLP)) != 0) { vput(vp); goto fail; } if (vp->v_type != VDIR) { vput(vp); goto fail; } error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL); if (error) { vput(vp); goto fail; } vfsp = vfs_byname(fstypename); if (vfsp == NULL) { vput(vp); error = EOPNOTSUPP; goto fail; } args = malloc(vfsp->vfc_datasize, M_TEMP, M_WAITOK | M_ZERO); error = copyin(SCARG(uap, data), args, vfsp->vfc_datasize); if (error) { vput(vp); goto fail; } if (vp->v_mountedhere != NULL) { vput(vp); error = EBUSY; goto fail; } /* * Allocate and initialize the file system. */ mp = vfs_mount_alloc(vp, vfsp); mp->mnt_stat.f_owner = p->p_ucred->cr_uid; update: /* Ensure that the parent mountpoint does not get unmounted. */ error = vfs_busy(vp->v_mount, VB_READ|VB_NOWAIT|VB_DUPOK); if (error) { if (mp->mnt_flag & MNT_UPDATE) { mp->mnt_flag = mntflag; vfs_unbusy(mp); } else { vfs_unbusy(mp); vfs_mount_free(mp); } vput(vp); goto fail; } /* * Set the mount level flags. */ if (flags & MNT_RDONLY) mp->mnt_flag |= MNT_RDONLY; else if (mp->mnt_flag & MNT_RDONLY) mp->mnt_flag |= MNT_WANTRDWR; mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_WXALLOWED | MNT_NODEV | MNT_SYNCHRONOUS | MNT_ASYNC | MNT_NOATIME | MNT_NOPERM | MNT_FORCE); mp->mnt_flag |= flags & (MNT_NOSUID | MNT_NOEXEC | MNT_WXALLOWED | MNT_NODEV | MNT_SYNCHRONOUS | MNT_ASYNC | MNT_NOATIME | MNT_NOPERM | MNT_FORCE); /* * Mount the filesystem. */ error = VFS_MOUNT(mp, fspath, args, &nd, p); if (!error) { mp->mnt_stat.f_ctime = gettime(); } if (mp->mnt_flag & MNT_UPDATE) { vfs_unbusy(vp->v_mount); vput(vp); if (mp->mnt_flag & MNT_WANTRDWR) mp->mnt_flag &= ~MNT_RDONLY; mp->mnt_flag &= ~MNT_OP_FLAGS; if (error) mp->mnt_flag = mntflag; if ((mp->mnt_flag & MNT_RDONLY) == 0) { if (mp->mnt_syncer == NULL) error = vfs_allocate_syncvnode(mp); } else { if (mp->mnt_syncer != NULL) vgone(mp->mnt_syncer); mp->mnt_syncer = NULL; } vfs_unbusy(mp); goto fail; } mp->mnt_flag &= ~MNT_OP_FLAGS; vp->v_mountedhere = mp; /* * Put the new filesystem on the mount list after root. */ cache_purge(vp); if (!error) { TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list); checkdirs(vp); vfs_unbusy(vp->v_mount); VOP_UNLOCK(vp); if ((mp->mnt_flag & MNT_RDONLY) == 0) error = vfs_allocate_syncvnode(mp); vfs_unbusy(mp); (void) VFS_STATFS(mp, &mp->mnt_stat, p); if ((error = VFS_START(mp, 0, p)) != 0) vrele(vp); } else { mp->mnt_vnodecovered->v_mountedhere = NULL; vfs_unbusy(mp); vfs_mount_free(mp); vfs_unbusy(vp->v_mount); vput(vp); } fail: if (args) free(args, M_TEMP, vfsp->vfc_datasize); return (error); } /* * Scan all active processes to see if any of them have a current * or root directory onto which the new filesystem has just been * mounted. If so, replace them with the new mount point, keeping * track of how many were replaced. That's the number of references * the old vnode had that we've replaced, so finish by vrele()'ing * it that many times. This puts off any possible sleeping until * we've finished walking the allprocess list. */ void checkdirs(struct vnode *olddp) { struct filedesc *fdp; struct vnode *newdp; struct process *pr; u_int free_count = 0; if (olddp->v_usecount == 1) return; if (VFS_ROOT(olddp->v_mountedhere, &newdp)) panic("mount: lost mount"); LIST_FOREACH(pr, &allprocess, ps_list) { fdp = pr->ps_fd; if (fdp->fd_cdir == olddp) { free_count++; vref(newdp); fdp->fd_cdir = newdp; } if (fdp->fd_rdir == olddp) { free_count++; vref(newdp); fdp->fd_rdir = newdp; } } if (rootvnode == olddp) { free_count++; vref(newdp); rootvnode = newdp; } while (free_count-- > 0) vrele(olddp); vput(newdp); } /* * Unmount a file system. * * Note: unmount takes a path to the vnode mounted on as argument, * not special file (as before). */ int sys_unmount(struct proc *p, void *v, register_t *retval) { struct sys_unmount_args /* { syscallarg(const char *) path; syscallarg(int) flags; } */ *uap = v; struct vnode *vp; struct mount *mp; int error; struct nameidata nd; if ((error = suser(p)) != 0) return (error); NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, SCARG(uap, path), p); if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; mp = vp->v_mount; /* * Don't allow unmounting the root file system. */ if (mp->mnt_flag & MNT_ROOTFS) { vput(vp); return (EINVAL); } /* * Must be the root of the filesystem */ if ((vp->v_flag & VROOT) == 0) { vput(vp); return (EINVAL); } vput(vp); if (vfs_busy(mp, VB_WRITE|VB_WAIT)) return (EBUSY); return (dounmount(mp, SCARG(uap, flags) & MNT_FORCE, p)); } /* * Do the actual file system unmount. */ int dounmount(struct mount *mp, int flags, struct proc *p) { SLIST_HEAD(, mount) mplist; struct mount *nmp; int error; SLIST_INIT(&mplist); SLIST_INSERT_HEAD(&mplist, mp, mnt_dounmount); /* * Collect nested mount points. This takes advantage of the mount list * being ordered - nested mount points come after their parent. */ while ((mp = TAILQ_NEXT(mp, mnt_list)) != NULL) { SLIST_FOREACH(nmp, &mplist, mnt_dounmount) { if (mp->mnt_vnodecovered == NULLVP || mp->mnt_vnodecovered->v_mount != nmp) continue; if ((flags & MNT_FORCE) == 0) { error = EBUSY; goto err; } error = vfs_busy(mp, VB_WRITE|VB_WAIT|VB_DUPOK); if (error) { if ((flags & MNT_DOOMED)) { /* * If the mount point was busy due to * being unmounted, it has been removed * from the mount list already. * Restart the iteration from the last * collected busy entry. */ mp = SLIST_FIRST(&mplist); break; } goto err; } SLIST_INSERT_HEAD(&mplist, mp, mnt_dounmount); break; } } /* * Nested mount points cannot appear during this loop as mounting * requires a read lock for the parent mount point. */ while ((mp = SLIST_FIRST(&mplist)) != NULL) { SLIST_REMOVE(&mplist, mp, mount, mnt_dounmount); error = dounmount_leaf(mp, flags, p); if (error) goto err; } return (0); err: while ((mp = SLIST_FIRST(&mplist)) != NULL) { SLIST_REMOVE(&mplist, mp, mount, mnt_dounmount); vfs_unbusy(mp); } return (error); } int dounmount_leaf(struct mount *mp, int flags, struct proc *p) { struct vnode *coveredvp; struct vnode *vp, *nvp; int error; int hadsyncer = 0; mp->mnt_flag &=~ MNT_ASYNC; cache_purgevfs(mp); /* remove cache entries for this file sys */ if (mp->mnt_syncer != NULL) { hadsyncer = 1; vgone(mp->mnt_syncer); mp->mnt_syncer = NULL; } /* * Before calling file system unmount, make sure * all unveils to vnodes in here are dropped. */ TAILQ_FOREACH_SAFE(vp , &mp->mnt_vnodelist, v_mntvnodes, nvp) { unveil_removevnode(vp); } if (((mp->mnt_flag & MNT_RDONLY) || (error = VFS_SYNC(mp, MNT_WAIT, 0, p->p_ucred, p)) == 0) || (flags & MNT_FORCE)) error = VFS_UNMOUNT(mp, flags, p); if (error && !(flags & MNT_DOOMED)) { if ((mp->mnt_flag & MNT_RDONLY) == 0 && hadsyncer) (void) vfs_allocate_syncvnode(mp); vfs_unbusy(mp); return (error); } TAILQ_REMOVE(&mountlist, mp, mnt_list); if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) { coveredvp->v_mountedhere = NULL; vrele(coveredvp); } if (!TAILQ_EMPTY(&mp->mnt_vnodelist)) panic("unmount: dangling vnode"); vfs_unbusy(mp); vfs_mount_free(mp); return (0); } /* * Sync each mounted filesystem. */ int sys_sync(struct proc *p, void *v, register_t *retval) { struct mount *mp; int asyncflag; TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) { if (vfs_busy(mp, VB_READ|VB_NOWAIT)) continue; if ((mp->mnt_flag & MNT_RDONLY) == 0) { asyncflag = mp->mnt_flag & MNT_ASYNC; mp->mnt_flag &= ~MNT_ASYNC; uvm_vnp_sync(mp); VFS_SYNC(mp, MNT_NOWAIT, 0, p->p_ucred, p); if (asyncflag) mp->mnt_flag |= MNT_ASYNC; } vfs_unbusy(mp); } return (0); } /* * Change filesystem quotas. */ int sys_quotactl(struct proc *p, void *v, register_t *retval) { struct sys_quotactl_args /* { syscallarg(const char *) path; syscallarg(int) cmd; syscallarg(int) uid; syscallarg(char *) arg; } */ *uap = v; struct mount *mp; int error; struct nameidata nd; NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); if ((error = namei(&nd)) != 0) return (error); mp = nd.ni_vp->v_mount; vrele(nd.ni_vp); return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid), SCARG(uap, arg), p)); } int copyout_statfs(struct statfs *sp, void *uaddr, struct proc *p) { size_t co_sz1 = offsetof(struct statfs, f_fsid); size_t co_off2 = co_sz1 + sizeof(fsid_t); size_t co_sz2 = sizeof(struct statfs) - co_off2; char *s, *d; int error; /* Don't let non-root see filesystem id (for NFS security) */ if (suser(p)) { fsid_t fsid; s = (char *)sp; d = (char *)uaddr; memset(&fsid, 0, sizeof(fsid)); if ((error = copyout(s, d, co_sz1)) != 0) return (error); if ((error = copyout(&fsid, d + co_sz1, sizeof(fsid))) != 0) return (error); return (copyout(s + co_off2, d + co_off2, co_sz2)); } return (copyout(sp, uaddr, sizeof(*sp))); } /* * Get filesystem statistics. */ int sys_statfs(struct proc *p, void *v, register_t *retval) { struct sys_statfs_args /* { syscallarg(const char *) path; syscallarg(struct statfs *) buf; } */ *uap = v; struct mount *mp; struct statfs *sp; int error; struct nameidata nd; NDINIT(&nd, LOOKUP, FOLLOW | BYPASSUNVEIL, UIO_USERSPACE, SCARG(uap, path), p); nd.ni_pledge = PLEDGE_RPATH; nd.ni_unveil = UNVEIL_READ; if ((error = namei(&nd)) != 0) return (error); mp = nd.ni_vp->v_mount; sp = &mp->mnt_stat; vrele(nd.ni_vp); if ((error = VFS_STATFS(mp, sp, p)) != 0) return (error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; return (copyout_statfs(sp, SCARG(uap, buf), p)); } /* * Get filesystem statistics. */ int sys_fstatfs(struct proc *p, void *v, register_t *retval) { struct sys_fstatfs_args /* { syscallarg(int) fd; syscallarg(struct statfs *) buf; } */ *uap = v; struct file *fp; struct mount *mp; struct statfs *sp; int error; if ((error = getvnode(p, SCARG(uap, fd), &fp)) != 0) return (error); mp = ((struct vnode *)fp->f_data)->v_mount; if (!mp) { FRELE(fp, p); return (ENOENT); } sp = &mp->mnt_stat; error = VFS_STATFS(mp, sp, p); FRELE(fp, p); if (error) return (error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; return (copyout_statfs(sp, SCARG(uap, buf), p)); } /* * Get statistics on all filesystems. */ int sys_getfsstat(struct proc *p, void *v, register_t *retval) { struct sys_getfsstat_args /* { syscallarg(struct statfs *) buf; syscallarg(size_t) bufsize; syscallarg(int) flags; } */ *uap = v; struct mount *mp; struct statfs *sp; struct statfs *sfsp; size_t count, maxcount; int error, flags = SCARG(uap, flags); maxcount = SCARG(uap, bufsize) / sizeof(struct statfs); sfsp = SCARG(uap, buf); count = 0; TAILQ_FOREACH(mp, &mountlist, mnt_list) { if (vfs_busy(mp, VB_READ|VB_NOWAIT)) continue; if (sfsp && count < maxcount) { sp = &mp->mnt_stat; /* Refresh stats unless MNT_NOWAIT is specified */ if (flags != MNT_NOWAIT && flags != MNT_LAZY && (flags == MNT_WAIT || flags == 0) && (error = VFS_STATFS(mp, sp, p))) { vfs_unbusy(mp); continue; } sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; #if notyet if (mp->mnt_flag & MNT_SOFTDEP) sp->f_eflags = STATFS_SOFTUPD; #endif error = (copyout_statfs(sp, sfsp, p)); if (error) { vfs_unbusy(mp); return (error); } sfsp++; } count++; vfs_unbusy(mp); } if (sfsp && count > maxcount) *retval = maxcount; else *retval = count; return (0); } /* * Change current working directory to a given file descriptor. */ int sys_fchdir(struct proc *p, void *v, register_t *retval) { struct sys_fchdir_args /* { syscallarg(int) fd; } */ *uap = v; struct filedesc *fdp = p->p_fd; struct vnode *vp, *tdp, *old_cdir; struct mount *mp; struct file *fp; int error; if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL) return (EBADF); vp = fp->f_data; if (fp->f_type != DTYPE_VNODE || vp->v_type != VDIR) { FRELE(fp, p); return (ENOTDIR); } vref(vp); FRELE(fp, p); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); while (!error && (mp = vp->v_mountedhere) != NULL) { if (vfs_busy(mp, VB_READ|VB_WAIT)) continue; error = VFS_ROOT(mp, &tdp); vfs_unbusy(mp); if (error) break; vput(vp); vp = tdp; } if (error) { vput(vp); return (error); } VOP_UNLOCK(vp); old_cdir = fdp->fd_cdir; fdp->fd_cdir = vp; vrele(old_cdir); return (0); } /* * Change current working directory (``.''). */ int sys_chdir(struct proc *p, void *v, register_t *retval) { struct sys_chdir_args /* { syscallarg(const char *) path; } */ *uap = v; struct filedesc *fdp = p->p_fd; struct vnode *old_cdir; int error; struct nameidata nd; NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, SCARG(uap, path), p); nd.ni_pledge = PLEDGE_RPATH; nd.ni_unveil = UNVEIL_READ; if ((error = change_dir(&nd, p)) != 0) return (error); old_cdir = fdp->fd_cdir; fdp->fd_cdir = nd.ni_vp; vrele(old_cdir); return (0); } /* * Change notion of root (``/'') directory. */ int sys_chroot(struct proc *p, void *v, register_t *retval) { struct sys_chroot_args /* { syscallarg(const char *) path; } */ *uap = v; struct filedesc *fdp = p->p_fd; struct vnode *old_cdir, *old_rdir; int error; struct nameidata nd; if ((error = suser(p)) != 0) return (error); NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, SCARG(uap, path), p); if ((error = change_dir(&nd, p)) != 0) return (error); if (fdp->fd_rdir != NULL) { /* * A chroot() done inside a changed root environment does * an automatic chdir to avoid the out-of-tree experience. */ vref(nd.ni_vp); old_rdir = fdp->fd_rdir; old_cdir = fdp->fd_cdir; fdp->fd_rdir = fdp->fd_cdir = nd.ni_vp; vrele(old_rdir); vrele(old_cdir); } else fdp->fd_rdir = nd.ni_vp; atomic_setbits_int(&p->p_p->ps_flags, PS_CHROOT); return (0); } /* * Common routine for chroot and chdir. */ static int change_dir(struct nameidata *ndp, struct proc *p) { struct vnode *vp; int error; if ((error = namei(ndp)) != 0) return (error); vp = ndp->ni_vp; if (vp->v_type != VDIR) error = ENOTDIR; else error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); if (error) vput(vp); else VOP_UNLOCK(vp); return (error); } int sys___realpath(struct proc *p, void *v, register_t *retval) { struct sys___realpath_args /* { syscallarg(const char *) pathname; syscallarg(char *) resolved; } */ *uap = v; char *pathname; char *rpbuf; struct nameidata nd; size_t pathlen; int error = 0; if (SCARG(uap, pathname) == NULL) return (EINVAL); pathname = pool_get(&namei_pool, PR_WAITOK); rpbuf = pool_get(&namei_pool, PR_WAITOK); if ((error = copyinstr(SCARG(uap, pathname), pathname, MAXPATHLEN, &pathlen))) goto end; if (pathlen == 1) { /* empty string "" */ error = ENOENT; goto end; } if (pathlen < 2) { error = EINVAL; goto end; } /* Get cwd for relative path if needed, prepend to rpbuf */ rpbuf[0] = '\0'; if (pathname[0] != '/') { int cwdlen = MAXPATHLEN * 4; /* for vfs_getcwd_common */ char *cwdbuf, *bp; cwdbuf = malloc(cwdlen, M_TEMP, M_WAITOK); /* vfs_getcwd_common fills this in backwards */ bp = &cwdbuf[cwdlen - 1]; *bp = '\0'; error = vfs_getcwd_common(p->p_fd->fd_cdir, NULL, &bp, cwdbuf, cwdlen/2, GETCWD_CHECK_ACCESS, p); if (error) { free(cwdbuf, M_TEMP, cwdlen); goto end; } if (strlcpy(rpbuf, bp, MAXPATHLEN) >= MAXPATHLEN) { free(cwdbuf, M_TEMP, cwdlen); error = ENAMETOOLONG; goto end; } free(cwdbuf, M_TEMP, cwdlen); } NDINIT(&nd, LOOKUP, FOLLOW | SAVENAME | REALPATH, UIO_SYSSPACE, pathname, p); nd.ni_cnd.cn_rpbuf = rpbuf; nd.ni_cnd.cn_rpi = strlen(rpbuf); nd.ni_pledge = PLEDGE_RPATH; nd.ni_unveil = UNVEIL_READ; if ((error = namei(&nd)) != 0) goto end; /* release reference from namei */ if (nd.ni_vp) vrele(nd.ni_vp); error = copyoutstr(nd.ni_cnd.cn_rpbuf, SCARG(uap, resolved), MAXPATHLEN, NULL); #ifdef KTRACE if (KTRPOINT(p, KTR_NAMEI)) ktrnamei(p, nd.ni_cnd.cn_rpbuf); #endif pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf); end: pool_put(&namei_pool, rpbuf); pool_put(&namei_pool, pathname); return (error); } int sys_unveil(struct proc *p, void *v, register_t *retval) { struct sys_unveil_args /* { syscallarg(const char *) path; syscallarg(const char *) permissions; } */ *uap = v; struct process *pr = p->p_p; char *pathname, *c; struct nameidata nd; size_t pathlen; char permissions[5]; int error, allow; if (SCARG(uap, path) == NULL && SCARG(uap, permissions) == NULL) { pr->ps_uvdone = 1; return (0); } if (pr->ps_uvdone != 0) return EPERM; error = copyinstr(SCARG(uap, permissions), permissions, sizeof(permissions), NULL); if (error) return (error); pathname = pool_get(&namei_pool, PR_WAITOK); error = copyinstr(SCARG(uap, path), pathname, MAXPATHLEN, &pathlen); if (error) goto end; #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrstruct(p, "unveil", permissions, strlen(permissions)); #endif if (pathlen < 2) { error = EINVAL; goto end; } /* find root "/" or "//" */ for (c = pathname; *c != '\0'; c++) { if (*c != '/') break; } if (*c == '\0') /* root directory */ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | SAVENAME, UIO_SYSSPACE, pathname, p); else NDINIT(&nd, CREATE, FOLLOW | LOCKLEAF | LOCKPARENT | SAVENAME, UIO_SYSSPACE, pathname, p); nd.ni_pledge = PLEDGE_UNVEIL; if ((error = namei(&nd)) != 0) goto end; /* * XXX Any access to the file or directory will allow us to * pledge path it */ allow = ((nd.ni_vp && (VOP_ACCESS(nd.ni_vp, VREAD, p->p_ucred, p) == 0 || VOP_ACCESS(nd.ni_vp, VWRITE, p->p_ucred, p) == 0 || VOP_ACCESS(nd.ni_vp, VEXEC, p->p_ucred, p) == 0)) || (nd.ni_dvp && (VOP_ACCESS(nd.ni_dvp, VREAD, p->p_ucred, p) == 0 || VOP_ACCESS(nd.ni_dvp, VWRITE, p->p_ucred, p) == 0 || VOP_ACCESS(nd.ni_dvp, VEXEC, p->p_ucred, p) == 0))); /* release lock from namei, but keep ref */ if (nd.ni_vp) VOP_UNLOCK(nd.ni_vp); if (nd.ni_dvp && nd.ni_dvp != nd.ni_vp) VOP_UNLOCK(nd.ni_dvp); if (allow) error = unveil_add(p, &nd, permissions); else error = EPERM; /* release vref from namei, but not vref from unveil_add */ if (nd.ni_vp) vrele(nd.ni_vp); if (nd.ni_dvp) vrele(nd.ni_dvp); pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf); end: pool_put(&namei_pool, pathname); return (error); } /* * Check permissions, allocate an open file structure, * and call the device open routine if any. */ int sys_open(struct proc *p, void *v, register_t *retval) { struct sys_open_args /* { syscallarg(const char *) path; syscallarg(int) flags; syscallarg(mode_t) mode; } */ *uap = v; return (doopenat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, flags), SCARG(uap, mode), retval)); } int sys_openat(struct proc *p, void *v, register_t *retval) { struct sys_openat_args /* { syscallarg(int) fd; syscallarg(const char *) path; syscallarg(int) flags; syscallarg(mode_t) mode; } */ *uap = v; return (doopenat(p, SCARG(uap, fd), SCARG(uap, path), SCARG(uap, flags), SCARG(uap, mode), retval)); } int doopenat(struct proc *p, int fd, const char *path, int oflags, mode_t mode, register_t *retval) { struct filedesc *fdp = p->p_fd; struct file *fp; struct vnode *vp; struct vattr vattr; int flags, cloexec, cmode; int type, indx, error, localtrunc = 0; struct flock lf; struct nameidata nd; uint64_t ni_pledge = 0; u_char ni_unveil = 0; if (oflags & (O_EXLOCK | O_SHLOCK)) { error = pledge_flock(p); if (error != 0) return (error); } cloexec = (oflags & O_CLOEXEC) ? UF_EXCLOSE : 0; fdplock(fdp); if ((error = falloc(p, &fp, &indx)) != 0) { fdpunlock(fdp); return (error); } fdpunlock(fdp); flags = FFLAGS(oflags); if (flags & FREAD) { ni_pledge |= PLEDGE_RPATH; ni_unveil |= UNVEIL_READ; } if (flags & FWRITE) { ni_pledge |= PLEDGE_WPATH; ni_unveil |= UNVEIL_WRITE; } if (oflags & O_CREAT) { ni_pledge |= PLEDGE_CPATH; ni_unveil |= UNVEIL_CREATE; } cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; if ((p->p_p->ps_flags & PS_PLEDGE)) cmode &= ACCESSPERMS; NDINITAT(&nd, 0, 0, UIO_USERSPACE, fd, path, p); nd.ni_pledge = ni_pledge; nd.ni_unveil = ni_unveil; p->p_dupfd = -1; /* XXX check for fdopen */ if ((flags & O_TRUNC) && (flags & (O_EXLOCK | O_SHLOCK))) { localtrunc = 1; flags &= ~O_TRUNC; /* Must do truncate ourselves */ } if ((error = vn_open(&nd, flags, cmode)) != 0) { fdplock(fdp); if (error == ENODEV && p->p_dupfd >= 0 && /* XXX from fdopen */ (error = dupfdopen(p, indx, flags)) == 0) { fdpunlock(fdp); closef(fp, p); *retval = indx; return (error); } if (error == ERESTART) error = EINTR; fdremove(fdp, indx); fdpunlock(fdp); closef(fp, p); return (error); } p->p_dupfd = 0; vp = nd.ni_vp; fp->f_flag = flags & FMASK; fp->f_type = DTYPE_VNODE; fp->f_ops = &vnops; fp->f_data = vp; if (flags & (O_EXLOCK | O_SHLOCK)) { lf.l_whence = SEEK_SET; lf.l_start = 0; lf.l_len = 0; if (flags & O_EXLOCK) lf.l_type = F_WRLCK; else lf.l_type = F_RDLCK; type = F_FLOCK; if ((flags & FNONBLOCK) == 0) type |= F_WAIT; VOP_UNLOCK(vp); error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type); if (error) { fdplock(fdp); /* closef will vn_close the file for us. */ fdremove(fdp, indx); fdpunlock(fdp); closef(fp, p); return (error); } vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); atomic_setbits_int(&fp->f_iflags, FIF_HASLOCK); } if (localtrunc) { if ((fp->f_flag & FWRITE) == 0) error = EACCES; else if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_RDONLY)) error = EROFS; else if (vp->v_type == VDIR) error = EISDIR; else if ((error = vn_writechk(vp)) == 0) { VATTR_NULL(&vattr); vattr.va_size = 0; error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); } if (error) { VOP_UNLOCK(vp); fdplock(fdp); /* closef will close the file for us. */ fdremove(fdp, indx); fdpunlock(fdp); closef(fp, p); return (error); } } VOP_UNLOCK(vp); *retval = indx; fdplock(fdp); fdinsert(fdp, indx, cloexec, fp); fdpunlock(fdp); FRELE(fp, p); return (error); } /* * Open a new created file (in /tmp) suitable for mmaping. */ int sys___tmpfd(struct proc *p, void *v, register_t *retval) { struct sys___tmpfd_args /* { syscallarg(int) flags; } */ *uap = v; struct filedesc *fdp = p->p_fd; struct file *fp; struct vnode *vp; int oflags = SCARG(uap, flags); int flags, cloexec, cmode; int indx, error; unsigned int i; struct nameidata nd; char path[64]; static const char *letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-"; /* most flags are hardwired */ oflags = O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW | (oflags & O_CLOEXEC); cloexec = (oflags & O_CLOEXEC) ? UF_EXCLOSE : 0; fdplock(fdp); if ((error = falloc(p, &fp, &indx)) != 0) { fdpunlock(fdp); return (error); } fdpunlock(fdp); flags = FFLAGS(oflags); arc4random_buf(path, sizeof(path)); memcpy(path, "/tmp/", 5); for (i = 5; i < sizeof(path) - 1; i++) path[i] = letters[(unsigned char)path[i] & 63]; path[sizeof(path)-1] = 0; cmode = 0600; NDINITAT(&nd, 0, KERNELPATH, UIO_SYSSPACE, AT_FDCWD, path, p); if ((error = vn_open(&nd, flags, cmode)) != 0) { if (error == ERESTART) error = EINTR; fdplock(fdp); fdremove(fdp, indx); fdpunlock(fdp); closef(fp, p); return (error); } vp = nd.ni_vp; fp->f_flag = flags & FMASK; fp->f_type = DTYPE_VNODE; fp->f_ops = &vnops; fp->f_data = vp; VOP_UNLOCK(vp); *retval = indx; fdplock(fdp); fdinsert(fdp, indx, cloexec, fp); fdpunlock(fdp); FRELE(fp, p); /* unlink it */ /* XXX * there is a wee race here, although it is mostly inconsequential. * perhaps someday we can create a file like object without a name... */ NDINITAT(&nd, DELETE, KERNELPATH | LOCKPARENT | LOCKLEAF, UIO_SYSSPACE, AT_FDCWD, path, p); if ((error = namei(&nd)) != 0) { printf("can't unlink temp file! %d\n", error); error = 0; } else { vp = nd.ni_vp; uvm_vnp_uncache(vp); error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); if (error) { printf("error removing vop: %d\n", error); error = 0; } } return (error); } /* * Get file handle system call */ int sys_getfh(struct proc *p, void *v, register_t *retval) { struct sys_getfh_args /* { syscallarg(const char *) fname; syscallarg(fhandle_t *) fhp; } */ *uap = v; struct vnode *vp; fhandle_t fh; int error; struct nameidata nd; /* * Must be super user */ error = suser(p); if (error) return (error); NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, SCARG(uap, fname), p); error = namei(&nd); if (error) return (error); vp = nd.ni_vp; memset(&fh, 0, sizeof(fh)); fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; error = VFS_VPTOFH(vp, &fh.fh_fid); vput(vp); if (error) return (error); error = copyout(&fh, SCARG(uap, fhp), sizeof(fh)); return (error); } /* * Open a file given a file handle. * * Check permissions, allocate an open file structure, * and call the device open routine if any. */ int sys_fhopen(struct proc *p, void *v, register_t *retval) { struct sys_fhopen_args /* { syscallarg(const fhandle_t *) fhp; syscallarg(int) flags; } */ *uap = v; struct filedesc *fdp = p->p_fd; struct file *fp; struct vnode *vp = NULL; struct mount *mp; struct ucred *cred = p->p_ucred; int flags, cloexec; int type, indx, error=0; struct flock lf; struct vattr va; fhandle_t fh; /* * Must be super user */ if ((error = suser(p))) return (error); flags = FFLAGS(SCARG(uap, flags)); if ((flags & (FREAD | FWRITE)) == 0) return (EINVAL); if ((flags & O_CREAT)) return (EINVAL); cloexec = (flags & O_CLOEXEC) ? UF_EXCLOSE : 0; fdplock(fdp); if ((error = falloc(p, &fp, &indx)) != 0) { fdpunlock(fdp); fp = NULL; goto bad; } fdpunlock(fdp); if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0) goto bad; if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) { error = ESTALE; goto bad; } if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)) != 0) { vp = NULL; /* most likely unnecessary sanity for bad: */ goto bad; } /* Now do an effective vn_open */ if (vp->v_type == VSOCK) { error = EOPNOTSUPP; goto bad; } if ((flags & O_DIRECTORY) && vp->v_type != VDIR) { error = ENOTDIR; goto bad; } if (flags & FREAD) { if ((error = VOP_ACCESS(vp, VREAD, cred, p)) != 0) goto bad; } if (flags & (FWRITE | O_TRUNC)) { if (vp->v_type == VDIR) { error = EISDIR; goto bad; } if ((error = VOP_ACCESS(vp, VWRITE, cred, p)) != 0 || (error = vn_writechk(vp)) != 0) goto bad; } if (flags & O_TRUNC) { VATTR_NULL(&va); va.va_size = 0; if ((error = VOP_SETATTR(vp, &va, cred, p)) != 0) goto bad; } if ((error = VOP_OPEN(vp, flags, cred, p)) != 0) goto bad; if (flags & FWRITE) vp->v_writecount++; /* done with modified vn_open, now finish what sys_open does. */ fp->f_flag = flags & FMASK; fp->f_type = DTYPE_VNODE; fp->f_ops = &vnops; fp->f_data = vp; if (flags & (O_EXLOCK | O_SHLOCK)) { lf.l_whence = SEEK_SET; lf.l_start = 0; lf.l_len = 0; if (flags & O_EXLOCK) lf.l_type = F_WRLCK; else lf.l_type = F_RDLCK; type = F_FLOCK; if ((flags & FNONBLOCK) == 0) type |= F_WAIT; VOP_UNLOCK(vp); error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type); if (error) { vp = NULL; /* closef will vn_close the file */ goto bad; } vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); atomic_setbits_int(&fp->f_iflags, FIF_HASLOCK); } VOP_UNLOCK(vp); *retval = indx; fdplock(fdp); fdinsert(fdp, indx, cloexec, fp); fdpunlock(fdp); FRELE(fp, p); return (0); bad: if (fp) { fdplock(fdp); fdremove(fdp, indx); fdpunlock(fdp); closef(fp, p); if (vp != NULL) vput(vp); } return (error); } int sys_fhstat(struct proc *p, void *v, register_t *retval) { struct sys_fhstat_args /* { syscallarg(const fhandle_t *) fhp; syscallarg(struct stat *) sb; } */ *uap = v; struct stat sb; int error; fhandle_t fh; struct mount *mp; struct vnode *vp; /* * Must be super user */ if ((error = suser(p))) return (error); if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0) return (error); if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) return (ESTALE); if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) return (error); error = vn_stat(vp, &sb, p); vput(vp); if (error) return (error); error = copyout(&sb, SCARG(uap, sb), sizeof(sb)); return (error); } int sys_fhstatfs(struct proc *p, void *v, register_t *retval) { struct sys_fhstatfs_args /* { syscallarg(const fhandle_t *) fhp; syscallarg(struct statfs *) buf; } */ *uap = v; struct statfs *sp; fhandle_t fh; struct mount *mp; struct vnode *vp; int error; /* * Must be super user */ if ((error = suser(p))) return (error); if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0) return (error); if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) return (ESTALE); if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) return (error); mp = vp->v_mount; sp = &mp->mnt_stat; vput(vp); if ((error = VFS_STATFS(mp, sp, p)) != 0) return (error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; return (copyout(sp, SCARG(uap, buf), sizeof(*sp))); } /* * Create a special file or named pipe. */ int sys_mknod(struct proc *p, void *v, register_t *retval) { struct sys_mknod_args /* { syscallarg(const char *) path; syscallarg(mode_t) mode; syscallarg(int) dev; } */ *uap = v; return (domknodat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, mode), SCARG(uap, dev))); } int sys_mknodat(struct proc *p, void *v, register_t *retval) { struct sys_mknodat_args /* { syscallarg(int) fd; syscallarg(const char *) path; syscallarg(mode_t) mode; syscallarg(dev_t) dev; } */ *uap = v; return (domknodat(p, SCARG(uap, fd), SCARG(uap, path), SCARG(uap, mode), SCARG(uap, dev))); } int domknodat(struct proc *p, int fd, const char *path, mode_t mode, dev_t dev) { struct vnode *vp; struct vattr vattr; int error; struct nameidata nd; if (dev == VNOVAL) return (EINVAL); NDINITAT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, fd, path, p); nd.ni_pledge = PLEDGE_DPATH; nd.ni_unveil = UNVEIL_CREATE; if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; if (!S_ISFIFO(mode) || dev != 0) { if (!vnoperm(nd.ni_dvp) && (error = suser(p)) != 0) goto out; if (p->p_fd->fd_rdir) { error = EINVAL; goto out; } } if (vp != NULL) error = EEXIST; else { VATTR_NULL(&vattr); vattr.va_mode = (mode & ALLPERMS) &~ p->p_fd->fd_cmask; if ((p->p_p->ps_flags & PS_PLEDGE)) vattr.va_mode &= ACCESSPERMS; vattr.va_rdev = dev; switch (mode & S_IFMT) { case S_IFMT: /* used by badsect to flag bad sectors */ vattr.va_type = VBAD; break; case S_IFCHR: vattr.va_type = VCHR; break; case S_IFBLK: vattr.va_type = VBLK; break; case S_IFIFO: #ifndef FIFO error = EOPNOTSUPP; break; #else if (dev == 0) { vattr.va_type = VFIFO; break; } /* FALLTHROUGH */ #endif /* FIFO */ default: error = EINVAL; break; } } out: if (!error) { error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); vput(nd.ni_dvp); } else { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); if (nd.ni_dvp == vp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); if (vp) vrele(vp); } return (error); } /* * Create a named pipe. */ int sys_mkfifo(struct proc *p, void *v, register_t *retval) { struct sys_mkfifo_args /* { syscallarg(const char *) path; syscallarg(mode_t) mode; } */ *uap = v; return (domknodat(p, AT_FDCWD, SCARG(uap, path), (SCARG(uap, mode) & ALLPERMS) | S_IFIFO, 0)); } int sys_mkfifoat(struct proc *p, void *v, register_t *retval) { struct sys_mkfifoat_args /* { syscallarg(int) fd; syscallarg(const char *) path; syscallarg(mode_t) mode; } */ *uap = v; return (domknodat(p, SCARG(uap, fd), SCARG(uap, path), (SCARG(uap, mode) & ALLPERMS) | S_IFIFO, 0)); } /* * Make a hard file link. */ int sys_link(struct proc *p, void *v, register_t *retval) { struct sys_link_args /* { syscallarg(const char *) path; syscallarg(const char *) link; } */ *uap = v; return (dolinkat(p, AT_FDCWD, SCARG(uap, path), AT_FDCWD, SCARG(uap, link), AT_SYMLINK_FOLLOW)); } int sys_linkat(struct proc *p, void *v, register_t *retval) { struct sys_linkat_args /* { syscallarg(int) fd1; syscallarg(const char *) path1; syscallarg(int) fd2; syscallarg(const char *) path2; syscallarg(int) flag; } */ *uap = v; return (dolinkat(p, SCARG(uap, fd1), SCARG(uap, path1), SCARG(uap, fd2), SCARG(uap, path2), SCARG(uap, flag))); } int dolinkat(struct proc *p, int fd1, const char *path1, int fd2, const char *path2, int flag) { struct vnode *vp; struct nameidata nd; int error, follow; if (flag & ~AT_SYMLINK_FOLLOW) return (EINVAL); follow = (flag & AT_SYMLINK_FOLLOW) ? FOLLOW : NOFOLLOW; NDINITAT(&nd, LOOKUP, follow, UIO_USERSPACE, fd1, path1, p); nd.ni_pledge = PLEDGE_RPATH; nd.ni_unveil = UNVEIL_READ; if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; if (vp->v_type == VDIR) { error = EPERM; goto out; } NDINITAT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, fd2, path2, p); nd.ni_pledge = PLEDGE_CPATH; nd.ni_unveil = UNVEIL_CREATE; if ((error = namei(&nd)) != 0) goto out; if (nd.ni_vp) { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); if (nd.ni_dvp == nd.ni_vp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); vrele(nd.ni_vp); error = EEXIST; goto out; } /* No cross-mount links! */ if (nd.ni_dvp->v_mount != vp->v_mount) { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); vput(nd.ni_dvp); error = EXDEV; goto out; } error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); out: vrele(vp); return (error); } /* * Make a symbolic link. */ int sys_symlink(struct proc *p, void *v, register_t *retval) { struct sys_symlink_args /* { syscallarg(const char *) path; syscallarg(const char *) link; } */ *uap = v; return (dosymlinkat(p, SCARG(uap, path), AT_FDCWD, SCARG(uap, link))); } int sys_symlinkat(struct proc *p, void *v, register_t *retval) { struct sys_symlinkat_args /* { syscallarg(const char *) path; syscallarg(int) fd; syscallarg(const char *) link; } */ *uap = v; return (dosymlinkat(p, SCARG(uap, path), SCARG(uap, fd), SCARG(uap, link))); } int dosymlinkat(struct proc *p, const char *upath, int fd, const char *link) { struct vattr vattr; char *path; int error; struct nameidata nd; path = pool_get(&namei_pool, PR_WAITOK); error = copyinstr(upath, path, MAXPATHLEN, NULL); if (error) goto out; NDINITAT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, fd, link, p); nd.ni_pledge = PLEDGE_CPATH; nd.ni_unveil = UNVEIL_CREATE; if ((error = namei(&nd)) != 0) goto out; if (nd.ni_vp) { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); if (nd.ni_dvp == nd.ni_vp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); vrele(nd.ni_vp); error = EEXIST; goto out; } VATTR_NULL(&vattr); vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask; error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); out: pool_put(&namei_pool, path); return (error); } /* * Delete a name from the filesystem. */ int sys_unlink(struct proc *p, void *v, register_t *retval) { struct sys_unlink_args /* { syscallarg(const char *) path; } */ *uap = v; return (dounlinkat(p, AT_FDCWD, SCARG(uap, path), 0)); } int sys_unlinkat(struct proc *p, void *v, register_t *retval) { struct sys_unlinkat_args /* { syscallarg(int) fd; syscallarg(const char *) path; syscallarg(int) flag; } */ *uap = v; return (dounlinkat(p, SCARG(uap, fd), SCARG(uap, path), SCARG(uap, flag))); } int dounlinkat(struct proc *p, int fd, const char *path, int flag) { struct vnode *vp; int error; struct nameidata nd; if (flag & ~AT_REMOVEDIR) return (EINVAL); NDINITAT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, fd, path, p); nd.ni_pledge = PLEDGE_CPATH; nd.ni_unveil = UNVEIL_CREATE; if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; if (flag & AT_REMOVEDIR) { if (vp->v_type != VDIR) { error = ENOTDIR; goto out; } /* * No rmdir "." please. */ if (nd.ni_dvp == vp) { error = EINVAL; goto out; } /* * A mounted on directory cannot be deleted. */ if (vp->v_mountedhere != NULL) { error = EBUSY; goto out; } } /* * The root of a mounted filesystem cannot be deleted. */ if (vp->v_flag & VROOT) error = EBUSY; out: if (!error) { if (flag & AT_REMOVEDIR) { error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); } else { (void)uvm_vnp_uncache(vp); error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); } } else { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); if (nd.ni_dvp == vp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); vput(vp); } return (error); } /* * Reposition read/write file offset. */ int sys_lseek(struct proc *p, void *v, register_t *retval) { struct sys_lseek_args /* { syscallarg(int) fd; syscallarg(off_t) offset; syscallarg(int) whence; } */ *uap = v; struct filedesc *fdp = p->p_fd; struct file *fp; off_t offset; int error; if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL) return (EBADF); if (fp->f_ops->fo_seek == NULL) { error = ESPIPE; goto bad; } offset = SCARG(uap, offset); error = (*fp->f_ops->fo_seek)(fp, &offset, SCARG(uap, whence), p); if (error) goto bad; *(off_t *)retval = offset; mtx_enter(&fp->f_mtx); fp->f_seek++; mtx_leave(&fp->f_mtx); error = 0; bad: FRELE(fp, p); return (error); } /* * Check access permissions. */ int sys_access(struct proc *p, void *v, register_t *retval) { struct sys_access_args /* { syscallarg(const char *) path; syscallarg(int) amode; } */ *uap = v; return (dofaccessat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, amode), 0)); } int sys_faccessat(struct proc *p, void *v, register_t *retval) { struct sys_faccessat_args /* { syscallarg(int) fd; syscallarg(const char *) path; syscallarg(int) amode; syscallarg(int) flag; } */ *uap = v; return (dofaccessat(p, SCARG(uap, fd), SCARG(uap, path), SCARG(uap, amode), SCARG(uap, flag))); } int dofaccessat(struct proc *p, int fd, const char *path, int amode, int flag) { struct vnode *vp; struct ucred *newcred, *oldcred; struct nameidata nd; int error; if (amode & ~(R_OK | W_OK | X_OK)) return (EINVAL); if (flag & ~AT_EACCESS) return (EINVAL); newcred = NULL; oldcred = p->p_ucred; /* * If access as real ids was requested and they really differ, * give the thread new creds with them reset */ if ((flag & AT_EACCESS) == 0 && (oldcred->cr_uid != oldcred->cr_ruid || (oldcred->cr_gid != oldcred->cr_rgid))) { p->p_ucred = newcred = crdup(oldcred); newcred->cr_uid = newcred->cr_ruid; newcred->cr_gid = newcred->cr_rgid; } NDINITAT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, fd, path, p); nd.ni_pledge = PLEDGE_RPATH; nd.ni_unveil = UNVEIL_READ; if ((error = namei(&nd)) != 0) goto out; vp = nd.ni_vp; /* Flags == 0 means only check for existence. */ if (amode) { int vflags = 0; if (amode & R_OK) vflags |= VREAD; if (amode & W_OK) vflags |= VWRITE; if (amode & X_OK) vflags |= VEXEC; error = VOP_ACCESS(vp, vflags, p->p_ucred, p); if (!error && (vflags & VWRITE)) error = vn_writechk(vp); } vput(vp); out: if (newcred != NULL) { p->p_ucred = oldcred; crfree(newcred); } return (error); } /* * Get file status; this version follows links. */ int sys_stat(struct proc *p, void *v, register_t *retval) { struct sys_stat_args /* { syscallarg(const char *) path; syscallarg(struct stat *) ub; } */ *uap = v; return (dofstatat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, ub), 0)); } int sys_fstatat(struct proc *p, void *v, register_t *retval) { struct sys_fstatat_args /* { syscallarg(int) fd; syscallarg(const char *) path; syscallarg(struct stat *) buf; syscallarg(int) flag; } */ *uap = v; return (dofstatat(p, SCARG(uap, fd), SCARG(uap, path), SCARG(uap, buf), SCARG(uap, flag))); } int dofstatat(struct proc *p, int fd, const char *path, struct stat *buf, int flag) { struct stat sb; int error, follow; struct nameidata nd; if (flag & ~AT_SYMLINK_NOFOLLOW) return (EINVAL); follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; NDINITAT(&nd, LOOKUP, follow | LOCKLEAF, UIO_USERSPACE, fd, path, p); nd.ni_pledge = PLEDGE_RPATH; nd.ni_unveil = UNVEIL_READ; if ((error = namei(&nd)) != 0) return (error); error = vn_stat(nd.ni_vp, &sb, p); vput(nd.ni_vp); if (error) return (error); /* Don't let non-root see generation numbers (for NFS security) */ if (suser(p)) sb.st_gen = 0; error = copyout(&sb, buf, sizeof(sb)); #ifdef KTRACE if (error == 0 && KTRPOINT(p, KTR_STRUCT)) ktrstat(p, &sb); #endif return (error); } /* * Get file status; this version does not follow links. */ int sys_lstat(struct proc *p, void *v, register_t *retval) { struct sys_lstat_args /* { syscallarg(const char *) path; syscallarg(struct stat *) ub; } */ *uap = v; return (dofstatat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, ub), AT_SYMLINK_NOFOLLOW)); } /* * Get configurable pathname variables. */ int sys_pathconf(struct proc *p, void *v, register_t *retval) { struct sys_pathconf_args /* { syscallarg(const char *) path; syscallarg(int) name; } */ *uap = v; return dopathconfat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, name), 0, retval); } int sys_pathconfat(struct proc *p, void *v, register_t *retval) { struct sys_pathconfat_args /* { syscallarg(int) fd; syscallarg(const char *) path; syscallarg(int) name; syscallarg(int) flag; } */ *uap = v; return dopathconfat(p, SCARG(uap, fd), SCARG(uap, path), SCARG(uap, name), SCARG(uap, flag), retval); } int dopathconfat(struct proc *p, int fd, const char *path, int name, int flag, register_t *retval) { int follow, error; struct nameidata nd; if (flag & ~AT_SYMLINK_NOFOLLOW) return EINVAL; follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; NDINITAT(&nd, LOOKUP, follow | LOCKLEAF, UIO_USERSPACE, fd, path, p); nd.ni_pledge = PLEDGE_RPATH; nd.ni_unveil = UNVEIL_READ; if ((error = namei(&nd)) != 0) return (error); error = VOP_PATHCONF(nd.ni_vp, name, retval); vput(nd.ni_vp); return (error); } /* * Return target name of a symbolic link. */ int sys_readlink(struct proc *p, void *v, register_t *retval) { struct sys_readlink_args /* { syscallarg(const char *) path; syscallarg(char *) buf; syscallarg(size_t) count; } */ *uap = v; return (doreadlinkat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, buf), SCARG(uap, count), retval)); } int sys_readlinkat(struct proc *p, void *v, register_t *retval) { struct sys_readlinkat_args /* { syscallarg(int) fd; syscallarg(const char *) path; syscallarg(char *) buf; syscallarg(size_t) count; } */ *uap = v; return (doreadlinkat(p, SCARG(uap, fd), SCARG(uap, path), SCARG(uap, buf), SCARG(uap, count), retval)); } int doreadlinkat(struct proc *p, int fd, const char *path, char *buf, size_t count, register_t *retval) { struct vnode *vp; struct iovec aiov; struct uio auio; int error; struct nameidata nd; NDINITAT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, fd, path, p); nd.ni_pledge = PLEDGE_RPATH; nd.ni_unveil = UNVEIL_READ; if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; if (vp->v_type != VLNK) error = EINVAL; else { aiov.iov_base = buf; aiov.iov_len = count; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_offset = 0; auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_USERSPACE; auio.uio_procp = p; auio.uio_resid = count; error = VOP_READLINK(vp, &auio, p->p_ucred); *retval = count - auio.uio_resid; } vput(vp); return (error); } /* * Change flags of a file given a path name. */ int sys_chflags(struct proc *p, void *v, register_t *retval) { struct sys_chflags_args /* { syscallarg(const char *) path; syscallarg(u_int) flags; } */ *uap = v; return (dochflagsat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, flags), 0)); } int sys_chflagsat(struct proc *p, void *v, register_t *retval) { struct sys_chflagsat_args /* { syscallarg(int) fd; syscallarg(const char *) path; syscallarg(u_int) flags; syscallarg(int) atflags; } */ *uap = v; return (dochflagsat(p, SCARG(uap, fd), SCARG(uap, path), SCARG(uap, flags), SCARG(uap, atflags))); } int dochflagsat(struct proc *p, int fd, const char *path, u_int flags, int atflags) { struct nameidata nd; int error, follow; if (atflags & ~AT_SYMLINK_NOFOLLOW) return (EINVAL); follow = (atflags & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; NDINITAT(&nd, LOOKUP, follow, UIO_USERSPACE, fd, path, p); nd.ni_pledge = PLEDGE_FATTR | PLEDGE_RPATH; nd.ni_unveil = UNVEIL_WRITE; if ((error = namei(&nd)) != 0) return (error); return (dovchflags(p, nd.ni_vp, flags)); } /* * Change flags of a file given a file descriptor. */ int sys_fchflags(struct proc *p, void *v, register_t *retval) { struct sys_fchflags_args /* { syscallarg(int) fd; syscallarg(u_int) flags; } */ *uap = v; struct file *fp; struct vnode *vp; int error; if ((error = getvnode(p, SCARG(uap, fd), &fp)) != 0) return (error); vp = fp->f_data; vref(vp); FRELE(fp, p); return (dovchflags(p, vp, SCARG(uap, flags))); } int dovchflags(struct proc *p, struct vnode *vp, u_int flags) { struct vattr vattr; int error; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if (vp->v_mount && vp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; else if (flags == VNOVAL) error = EINVAL; else { if (suser(p)) { if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0) goto out; if (vattr.va_type == VCHR || vattr.va_type == VBLK) { error = EINVAL; goto out; } } VATTR_NULL(&vattr); vattr.va_flags = flags; error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); } out: vput(vp); return (error); } /* * Change mode of a file given path name. */ int sys_chmod(struct proc *p, void *v, register_t *retval) { struct sys_chmod_args /* { syscallarg(const char *) path; syscallarg(mode_t) mode; } */ *uap = v; return (dofchmodat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, mode), 0)); } int sys_fchmodat(struct proc *p, void *v, register_t *retval) { struct sys_fchmodat_args /* { syscallarg(int) fd; syscallarg(const char *) path; syscallarg(mode_t) mode; syscallarg(int) flag; } */ *uap = v; return (dofchmodat(p, SCARG(uap, fd), SCARG(uap, path), SCARG(uap, mode), SCARG(uap, flag))); } int dofchmodat(struct proc *p, int fd, const char *path, mode_t mode, int flag) { struct vnode *vp; struct vattr vattr; int error, follow; struct nameidata nd; if (mode & ~(S_IFMT | ALLPERMS)) return (EINVAL); if ((p->p_p->ps_flags & PS_PLEDGE)) mode &= ACCESSPERMS; if (flag & ~AT_SYMLINK_NOFOLLOW) return (EINVAL); follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; NDINITAT(&nd, LOOKUP, follow, UIO_USERSPACE, fd, path, p); nd.ni_pledge = PLEDGE_FATTR | PLEDGE_RPATH; nd.ni_unveil = UNVEIL_WRITE; if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if (vp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; else { VATTR_NULL(&vattr); vattr.va_mode = mode & ALLPERMS; error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); } vput(vp); return (error); } /* * Change mode of a file given a file descriptor. */ int sys_fchmod(struct proc *p, void *v, register_t *retval) { struct sys_fchmod_args /* { syscallarg(int) fd; syscallarg(mode_t) mode; } */ *uap = v; struct vattr vattr; struct vnode *vp; struct file *fp; mode_t mode = SCARG(uap, mode); int error; if (mode & ~(S_IFMT | ALLPERMS)) return (EINVAL); if ((p->p_p->ps_flags & PS_PLEDGE)) mode &= ACCESSPERMS; if ((error = getvnode(p, SCARG(uap, fd), &fp)) != 0) return (error); vp = fp->f_data; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if (vp->v_mount && vp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; else { VATTR_NULL(&vattr); vattr.va_mode = mode & ALLPERMS; error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); } VOP_UNLOCK(vp); FRELE(fp, p); return (error); } /* * Set ownership given a path name. */ int sys_chown(struct proc *p, void *v, register_t *retval) { struct sys_chown_args /* { syscallarg(const char *) path; syscallarg(uid_t) uid; syscallarg(gid_t) gid; } */ *uap = v; return (dofchownat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, uid), SCARG(uap, gid), 0)); } int sys_fchownat(struct proc *p, void *v, register_t *retval) { struct sys_fchownat_args /* { syscallarg(int) fd; syscallarg(const char *) path; syscallarg(uid_t) uid; syscallarg(gid_t) gid; syscallarg(int) flag; } */ *uap = v; return (dofchownat(p, SCARG(uap, fd), SCARG(uap, path), SCARG(uap, uid), SCARG(uap, gid), SCARG(uap, flag))); } int dofchownat(struct proc *p, int fd, const char *path, uid_t uid, gid_t gid, int flag) { struct vnode *vp; struct vattr vattr; int error, follow; struct nameidata nd; mode_t mode; if (flag & ~AT_SYMLINK_NOFOLLOW) return (EINVAL); follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; NDINITAT(&nd, LOOKUP, follow, UIO_USERSPACE, fd, path, p); nd.ni_pledge = PLEDGE_CHOWN | PLEDGE_RPATH; nd.ni_unveil = UNVEIL_WRITE; if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if (vp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; else { if ((error = pledge_chown(p, uid, gid))) goto out; if ((uid != -1 || gid != -1) && !vnoperm(vp) && (suser(p) || suid_clear)) { error = VOP_GETATTR(vp, &vattr, p->p_ucred, p); if (error) goto out; mode = vattr.va_mode & ~(VSUID | VSGID); if (mode == vattr.va_mode) mode = VNOVAL; } else mode = VNOVAL; VATTR_NULL(&vattr); vattr.va_uid = uid; vattr.va_gid = gid; vattr.va_mode = mode; error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); } out: vput(vp); return (error); } /* * Set ownership given a path name, without following links. */ int sys_lchown(struct proc *p, void *v, register_t *retval) { struct sys_lchown_args /* { syscallarg(const char *) path; syscallarg(uid_t) uid; syscallarg(gid_t) gid; } */ *uap = v; struct vnode *vp; struct vattr vattr; int error; struct nameidata nd; mode_t mode; uid_t uid = SCARG(uap, uid); gid_t gid = SCARG(uap, gid); NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p); nd.ni_pledge = PLEDGE_CHOWN | PLEDGE_RPATH; nd.ni_unveil = UNVEIL_WRITE; if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if (vp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; else { if ((error = pledge_chown(p, uid, gid))) goto out; if ((uid != -1 || gid != -1) && !vnoperm(vp) && (suser(p) || suid_clear)) { error = VOP_GETATTR(vp, &vattr, p->p_ucred, p); if (error) goto out; mode = vattr.va_mode & ~(VSUID | VSGID); if (mode == vattr.va_mode) mode = VNOVAL; } else mode = VNOVAL; VATTR_NULL(&vattr); vattr.va_uid = uid; vattr.va_gid = gid; vattr.va_mode = mode; error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); } out: vput(vp); return (error); } /* * Set ownership given a file descriptor. */ int sys_fchown(struct proc *p, void *v, register_t *retval) { struct sys_fchown_args /* { syscallarg(int) fd; syscallarg(uid_t) uid; syscallarg(gid_t) gid; } */ *uap = v; struct vnode *vp; struct vattr vattr; int error; struct file *fp; mode_t mode; uid_t uid = SCARG(uap, uid); gid_t gid = SCARG(uap, gid); if ((error = getvnode(p, SCARG(uap, fd), &fp)) != 0) return (error); vp = fp->f_data; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_RDONLY)) error = EROFS; else { if ((error = pledge_chown(p, uid, gid))) goto out; if ((uid != -1 || gid != -1) && !vnoperm(vp) && (suser(p) || suid_clear)) { error = VOP_GETATTR(vp, &vattr, p->p_ucred, p); if (error) goto out; mode = vattr.va_mode & ~(VSUID | VSGID); if (mode == vattr.va_mode) mode = VNOVAL; } else mode = VNOVAL; VATTR_NULL(&vattr); vattr.va_uid = uid; vattr.va_gid = gid; vattr.va_mode = mode; error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); } out: VOP_UNLOCK(vp); FRELE(fp, p); return (error); } /* * Set the access and modification times given a path name. */ int sys_utimes(struct proc *p, void *v, register_t *retval) { struct sys_utimes_args /* { syscallarg(const char *) path; syscallarg(const struct timeval *) tptr; } */ *uap = v; struct timespec ts[2]; struct timeval tv[2]; const struct timeval *tvp; int error; tvp = SCARG(uap, tptr); if (tvp != NULL) { error = copyin(tvp, tv, sizeof(tv)); if (error) return (error); #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrabstimeval(p, &tv); #endif if (!timerisvalid(&tv[0]) || !timerisvalid(&tv[1])) return (EINVAL); TIMEVAL_TO_TIMESPEC(&tv[0], &ts[0]); TIMEVAL_TO_TIMESPEC(&tv[1], &ts[1]); } else ts[0].tv_nsec = ts[1].tv_nsec = UTIME_NOW; return (doutimensat(p, AT_FDCWD, SCARG(uap, path), ts, 0)); } int sys_utimensat(struct proc *p, void *v, register_t *retval) { struct sys_utimensat_args /* { syscallarg(int) fd; syscallarg(const char *) path; syscallarg(const struct timespec *) times; syscallarg(int) flag; } */ *uap = v; struct timespec ts[2]; const struct timespec *tsp; int error, i; tsp = SCARG(uap, times); if (tsp != NULL) { error = copyin(tsp, ts, sizeof(ts)); if (error) return (error); for (i = 0; i < nitems(ts); i++) { if (ts[i].tv_nsec == UTIME_NOW) continue; if (ts[i].tv_nsec == UTIME_OMIT) continue; #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrabstimespec(p, &ts[i]); #endif if (!timespecisvalid(&ts[i])) return (EINVAL); } } else ts[0].tv_nsec = ts[1].tv_nsec = UTIME_NOW; return (doutimensat(p, SCARG(uap, fd), SCARG(uap, path), ts, SCARG(uap, flag))); } int doutimensat(struct proc *p, int fd, const char *path, struct timespec ts[2], int flag) { struct vnode *vp; int error, follow; struct nameidata nd; if (flag & ~AT_SYMLINK_NOFOLLOW) return (EINVAL); follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; NDINITAT(&nd, LOOKUP, follow, UIO_USERSPACE, fd, path, p); nd.ni_pledge = PLEDGE_FATTR | PLEDGE_RPATH; nd.ni_unveil = UNVEIL_WRITE; if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; return (dovutimens(p, vp, ts)); } int dovutimens(struct proc *p, struct vnode *vp, struct timespec ts[2]) { struct vattr vattr; struct timespec now; int error; #ifdef KTRACE /* if they're both UTIME_NOW, then don't report either */ if ((ts[0].tv_nsec != UTIME_NOW || ts[1].tv_nsec != UTIME_NOW) && KTRPOINT(p, KTR_STRUCT)) { ktrabstimespec(p, &ts[0]); ktrabstimespec(p, &ts[1]); } #endif VATTR_NULL(&vattr); /* make sure ctime is updated even if neither mtime nor atime is */ vattr.va_vaflags = VA_UTIMES_CHANGE; if (ts[0].tv_nsec == UTIME_NOW || ts[1].tv_nsec == UTIME_NOW) { if (ts[0].tv_nsec == UTIME_NOW && ts[1].tv_nsec == UTIME_NOW) vattr.va_vaflags |= VA_UTIMES_NULL; getnanotime(&now); if (ts[0].tv_nsec == UTIME_NOW) ts[0] = now; if (ts[1].tv_nsec == UTIME_NOW) ts[1] = now; } if (ts[0].tv_nsec != UTIME_OMIT) vattr.va_atime = ts[0]; if (ts[1].tv_nsec != UTIME_OMIT) vattr.va_mtime = ts[1]; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if (vp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; else error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); vput(vp); return (error); } /* * Set the access and modification times given a file descriptor. */ int sys_futimes(struct proc *p, void *v, register_t *retval) { struct sys_futimes_args /* { syscallarg(int) fd; syscallarg(const struct timeval *) tptr; } */ *uap = v; struct timeval tv[2]; struct timespec ts[2]; const struct timeval *tvp; int error; tvp = SCARG(uap, tptr); if (tvp != NULL) { error = copyin(tvp, tv, sizeof(tv)); if (error) return (error); #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) { ktrabstimeval(p, &tv[0]); ktrabstimeval(p, &tv[1]); } #endif if (!timerisvalid(&tv[0]) || !timerisvalid(&tv[1])) return (EINVAL); TIMEVAL_TO_TIMESPEC(&tv[0], &ts[0]); TIMEVAL_TO_TIMESPEC(&tv[1], &ts[1]); } else ts[0].tv_nsec = ts[1].tv_nsec = UTIME_NOW; return (dofutimens(p, SCARG(uap, fd), ts)); } int sys_futimens(struct proc *p, void *v, register_t *retval) { struct sys_futimens_args /* { syscallarg(int) fd; syscallarg(const struct timespec *) times; } */ *uap = v; struct timespec ts[2]; const struct timespec *tsp; int error, i; tsp = SCARG(uap, times); if (tsp != NULL) { error = copyin(tsp, ts, sizeof(ts)); if (error) return (error); for (i = 0; i < nitems(ts); i++) { if (ts[i].tv_nsec == UTIME_NOW) continue; if (ts[i].tv_nsec == UTIME_OMIT) continue; #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrabstimespec(p, &ts[i]); #endif if (!timespecisvalid(&ts[i])) return (EINVAL); } } else ts[0].tv_nsec = ts[1].tv_nsec = UTIME_NOW; return (dofutimens(p, SCARG(uap, fd), ts)); } int dofutimens(struct proc *p, int fd, struct timespec ts[2]) { struct file *fp; struct vnode *vp; int error; if ((error = getvnode(p, fd, &fp)) != 0) return (error); vp = fp->f_data; vref(vp); FRELE(fp, p); return (dovutimens(p, vp, ts)); } /* * Truncate a file given a vnode. */ int dotruncate(struct proc *p, struct vnode *vp, off_t len) { struct vattr vattr; int error; if (len < 0) return EINVAL; if (vp->v_type == VDIR) return EISDIR; if ((error = vn_writechk(vp)) != 0) return error; if (vp->v_type == VREG && len > lim_cur_proc(p, RLIMIT_FSIZE)) { if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0) return error; if (len > vattr.va_size) { /* if extending over the limit, send signal and fail */ psignal(p, SIGXFSZ); return EFBIG; } } VATTR_NULL(&vattr); vattr.va_size = len; return VOP_SETATTR(vp, &vattr, p->p_ucred, p); } /* * Truncate a file given its path name. */ int sys_truncate(struct proc *p, void *v, register_t *retval) { struct sys_truncate_args /* { syscallarg(const char *) path; syscallarg(off_t) length; } */ *uap = v; struct vnode *vp; int error; struct nameidata nd; NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); nd.ni_pledge = PLEDGE_FATTR | PLEDGE_RPATH; nd.ni_unveil = UNVEIL_WRITE; if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if ((error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) error = dotruncate(p, vp, SCARG(uap, length)); vput(vp); return (error); } /* * Truncate a file given a file descriptor. */ int sys_ftruncate(struct proc *p, void *v, register_t *retval) { struct sys_ftruncate_args /* { syscallarg(int) fd; syscallarg(off_t) length; } */ *uap = v; struct vnode *vp; struct file *fp; int error; if ((error = getvnode(p, SCARG(uap, fd), &fp)) != 0) return (error); if ((fp->f_flag & FWRITE) == 0) { error = EINVAL; goto bad; } vp = fp->f_data; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); error = dotruncate(p, vp, SCARG(uap, length)); VOP_UNLOCK(vp); bad: FRELE(fp, p); return (error); } /* * Sync an open file. */ int sys_fsync(struct proc *p, void *v, register_t *retval) { struct sys_fsync_args /* { syscallarg(int) fd; } */ *uap = v; struct vnode *vp; struct file *fp; int error; if ((error = getvnode(p, SCARG(uap, fd), &fp)) != 0) return (error); vp = fp->f_data; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p); VOP_UNLOCK(vp); FRELE(fp, p); return (error); } /* * Rename files. Source and destination must either both be directories, * or both not be directories. If target is a directory, it must be empty. */ int sys_rename(struct proc *p, void *v, register_t *retval) { struct sys_rename_args /* { syscallarg(const char *) from; syscallarg(const char *) to; } */ *uap = v; return (dorenameat(p, AT_FDCWD, SCARG(uap, from), AT_FDCWD, SCARG(uap, to))); } int sys_renameat(struct proc *p, void *v, register_t *retval) { struct sys_renameat_args /* { syscallarg(int) fromfd; syscallarg(const char *) from; syscallarg(int) tofd; syscallarg(const char *) to; } */ *uap = v; return (dorenameat(p, SCARG(uap, fromfd), SCARG(uap, from), SCARG(uap, tofd), SCARG(uap, to))); } int dorenameat(struct proc *p, int fromfd, const char *from, int tofd, const char *to) { struct vnode *tvp, *fvp, *tdvp; struct nameidata fromnd, tond; int error; int flags; NDINITAT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, fromfd, from, p); fromnd.ni_pledge = PLEDGE_RPATH | PLEDGE_CPATH; fromnd.ni_unveil = UNVEIL_READ | UNVEIL_CREATE; if ((error = namei(&fromnd)) != 0) return (error); fvp = fromnd.ni_vp; flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART; /* * rename("foo/", "bar/"); is OK */ if (fvp->v_type == VDIR) flags |= STRIPSLASHES; NDINITAT(&tond, RENAME, flags, UIO_USERSPACE, tofd, to, p); tond.ni_pledge = PLEDGE_CPATH; tond.ni_unveil = UNVEIL_CREATE; if ((error = namei(&tond)) != 0) { VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); vrele(fromnd.ni_dvp); vrele(fvp); goto out1; } tdvp = tond.ni_dvp; tvp = tond.ni_vp; if (tvp != NULL) { if (fvp->v_type == VDIR && tvp->v_type != VDIR) { error = ENOTDIR; goto out; } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { error = EISDIR; goto out; } } if (fvp == tdvp) error = EINVAL; /* * If source is the same as the destination (that is the * same inode number) */ if (fvp == tvp) error = -1; out: if (!error) { if (tvp) { (void)uvm_vnp_uncache(tvp); } error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); } else { VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); if (tdvp == tvp) vrele(tdvp); else vput(tdvp); if (tvp) vput(tvp); VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); vrele(fromnd.ni_dvp); vrele(fvp); } vrele(tond.ni_startdir); pool_put(&namei_pool, tond.ni_cnd.cn_pnbuf); out1: if (fromnd.ni_startdir) vrele(fromnd.ni_startdir); pool_put(&namei_pool, fromnd.ni_cnd.cn_pnbuf); if (error == -1) return (0); return (error); } /* * Make a directory file. */ int sys_mkdir(struct proc *p, void *v, register_t *retval) { struct sys_mkdir_args /* { syscallarg(const char *) path; syscallarg(mode_t) mode; } */ *uap = v; return (domkdirat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, mode))); } int sys_mkdirat(struct proc *p, void *v, register_t *retval) { struct sys_mkdirat_args /* { syscallarg(int) fd; syscallarg(const char *) path; syscallarg(mode_t) mode; } */ *uap = v; return (domkdirat(p, SCARG(uap, fd), SCARG(uap, path), SCARG(uap, mode))); } int domkdirat(struct proc *p, int fd, const char *path, mode_t mode) { struct vnode *vp; struct vattr vattr; int error; struct nameidata nd; NDINITAT(&nd, CREATE, LOCKPARENT | STRIPSLASHES, UIO_USERSPACE, fd, path, p); nd.ni_pledge = PLEDGE_CPATH; nd.ni_unveil = UNVEIL_CREATE; if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; if (vp != NULL) { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); if (nd.ni_dvp == vp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); vrele(vp); return (EEXIST); } VATTR_NULL(&vattr); vattr.va_type = VDIR; vattr.va_mode = (mode & ACCESSPERMS) &~ p->p_fd->fd_cmask; error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); if (!error) vput(nd.ni_vp); return (error); } /* * Remove a directory file. */ int sys_rmdir(struct proc *p, void *v, register_t *retval) { struct sys_rmdir_args /* { syscallarg(const char *) path; } */ *uap = v; return (dounlinkat(p, AT_FDCWD, SCARG(uap, path), AT_REMOVEDIR)); } /* * Read a block of directory entries in a file system independent format. */ int sys_getdents(struct proc *p, void *v, register_t *retval) { struct sys_getdents_args /* { syscallarg(int) fd; syscallarg(void *) buf; syscallarg(size_t) buflen; } */ *uap = v; struct vnode *vp; struct file *fp; struct uio auio; struct iovec aiov; size_t buflen; int error, eofflag; buflen = SCARG(uap, buflen); if (buflen > INT_MAX) return (EINVAL); if ((error = getvnode(p, SCARG(uap, fd), &fp)) != 0) return (error); if ((fp->f_flag & FREAD) == 0) { error = EBADF; goto bad; } vp = fp->f_data; if (vp->v_type != VDIR) { error = EINVAL; goto bad; } vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if (fp->f_offset < 0) { VOP_UNLOCK(vp); error = EINVAL; goto bad; } aiov.iov_base = SCARG(uap, buf); aiov.iov_len = buflen; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_USERSPACE; auio.uio_procp = p; auio.uio_resid = buflen; auio.uio_offset = fp->f_offset; error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag); mtx_enter(&fp->f_mtx); fp->f_offset = auio.uio_offset; mtx_leave(&fp->f_mtx); VOP_UNLOCK(vp); if (error) goto bad; *retval = buflen - auio.uio_resid; bad: FRELE(fp, p); return (error); } /* * Set the mode mask for creation of filesystem nodes. */ int sys_umask(struct proc *p, void *v, register_t *retval) { struct sys_umask_args /* { syscallarg(mode_t) newmask; } */ *uap = v; struct filedesc *fdp = p->p_fd; fdplock(fdp); *retval = fdp->fd_cmask; fdp->fd_cmask = SCARG(uap, newmask) & ACCESSPERMS; fdpunlock(fdp); return (0); } /* * Void all references to file by ripping underlying filesystem * away from vnode. */ int sys_revoke(struct proc *p, void *v, register_t *retval) { struct sys_revoke_args /* { syscallarg(const char *) path; } */ *uap = v; struct vnode *vp; struct vattr vattr; int error; struct nameidata nd; NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); nd.ni_pledge = PLEDGE_RPATH | PLEDGE_TTY; nd.ni_unveil = UNVEIL_READ; if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; if (vp->v_type != VCHR || (u_int)major(vp->v_rdev) >= nchrdev || cdevsw[major(vp->v_rdev)].d_type != D_TTY) { error = ENOTTY; goto out; } if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0) goto out; if (p->p_ucred->cr_uid != vattr.va_uid && (error = suser(p))) goto out; if (vp->v_usecount > 1 || (vp->v_flag & (VALIASED))) VOP_REVOKE(vp, REVOKEALL); out: vrele(vp); return (error); } /* * Convert a user file descriptor to a kernel file entry. * * On return *fpp is FREF:ed. */ int getvnode(struct proc *p, int fd, struct file **fpp) { struct file *fp; struct vnode *vp; if ((fp = fd_getfile(p->p_fd, fd)) == NULL) return (EBADF); if (fp->f_type != DTYPE_VNODE) { FRELE(fp, p); return (EINVAL); } vp = fp->f_data; if (vp->v_type == VBAD) { FRELE(fp, p); return (EBADF); } *fpp = fp; return (0); } /* * Positional read system call. */ int sys_pread(struct proc *p, void *v, register_t *retval) { struct sys_pread_args /* { syscallarg(int) fd; syscallarg(void *) buf; syscallarg(size_t) nbyte; syscallarg(off_t) offset; } */ *uap = v; struct iovec iov; struct uio auio; iov.iov_base = SCARG(uap, buf); iov.iov_len = SCARG(uap, nbyte); if (iov.iov_len > SSIZE_MAX) return (EINVAL); auio.uio_iov = &iov; auio.uio_iovcnt = 1; auio.uio_resid = iov.iov_len; auio.uio_offset = SCARG(uap, offset); return (dofilereadv(p, SCARG(uap, fd), &auio, FO_POSITION, retval)); } /* * Positional scatter read system call. */ int sys_preadv(struct proc *p, void *v, register_t *retval) { struct sys_preadv_args /* { syscallarg(int) fd; syscallarg(const struct iovec *) iovp; syscallarg(int) iovcnt; syscallarg(off_t) offset; } */ *uap = v; struct iovec aiov[UIO_SMALLIOV], *iov = NULL; int error, iovcnt = SCARG(uap, iovcnt); struct uio auio; size_t resid; error = iovec_copyin(SCARG(uap, iovp), &iov, aiov, iovcnt, &resid); if (error) goto done; auio.uio_iov = iov; auio.uio_iovcnt = iovcnt; auio.uio_resid = resid; auio.uio_offset = SCARG(uap, offset); error = dofilereadv(p, SCARG(uap, fd), &auio, FO_POSITION, retval); done: iovec_free(iov, iovcnt); return (error); } /* * Positional write system call. */ int sys_pwrite(struct proc *p, void *v, register_t *retval) { struct sys_pwrite_args /* { syscallarg(int) fd; syscallarg(const void *) buf; syscallarg(size_t) nbyte; syscallarg(off_t) offset; } */ *uap = v; struct iovec iov; struct uio auio; iov.iov_base = (void *)SCARG(uap, buf); iov.iov_len = SCARG(uap, nbyte); if (iov.iov_len > SSIZE_MAX) return (EINVAL); auio.uio_iov = &iov; auio.uio_iovcnt = 1; auio.uio_resid = iov.iov_len; auio.uio_offset = SCARG(uap, offset); return (dofilewritev(p, SCARG(uap, fd), &auio, FO_POSITION, retval)); } /* * Positional gather write system call. */ int sys_pwritev(struct proc *p, void *v, register_t *retval) { struct sys_pwritev_args /* { syscallarg(int) fd; syscallarg(const struct iovec *) iovp; syscallarg(int) iovcnt; syscallarg(off_t) offset; } */ *uap = v; struct iovec aiov[UIO_SMALLIOV], *iov = NULL; int error, iovcnt = SCARG(uap, iovcnt); struct uio auio; size_t resid; error = iovec_copyin(SCARG(uap, iovp), &iov, aiov, iovcnt, &resid); if (error) goto done; auio.uio_iov = iov; auio.uio_iovcnt = iovcnt; auio.uio_resid = resid; auio.uio_offset = SCARG(uap, offset); error = dofilewritev(p, SCARG(uap, fd), &auio, FO_POSITION, retval); done: iovec_free(iov, iovcnt); return (error); }
26 15 16 9 7 12 3 14 17 5 3 9 5 12 5 15 2 6 1 2 3 1 2 2 62 1 15 20 26 38 21 5 6 10 11 5 8 13 10 1 1 9 17 1 1 7 3 4 1 1 4 4 9 3 2 6 2 7 7 3 4 5 5 4 10 10 2 4 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 /* $OpenBSD: fifo_vnops.c,v 1.105 2024/05/03 17:43:09 mvs Exp $ */ /* $NetBSD: fifo_vnops.c,v 1.18 1996/03/16 23:52:42 christos Exp $ */ /* * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)fifo_vnops.c 8.4 (Berkeley) 8/10/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/time.h> #include <sys/namei.h> #include <sys/vnode.h> #include <sys/lock.h> #include <sys/protosw.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <sys/fcntl.h> #include <sys/file.h> #include <sys/event.h> #include <sys/errno.h> #include <sys/malloc.h> #include <sys/unistd.h> #include <miscfs/fifofs/fifo.h> /* * This structure is associated with the FIFO vnode and stores * the state associated with the FIFO. */ struct fifoinfo { struct socket *fi_readsock; struct socket *fi_writesock; long fi_readers; long fi_writers; }; const struct vops fifo_vops = { .vop_lookup = vop_generic_lookup, .vop_create = vop_generic_badop, .vop_mknod = vop_generic_badop, .vop_open = fifo_open, .vop_close = fifo_close, .vop_access = fifo_ebadf, .vop_getattr = fifo_ebadf, .vop_setattr = fifo_ebadf, .vop_read = fifo_read, .vop_write = fifo_write, .vop_ioctl = fifo_ioctl, .vop_kqfilter = fifo_kqfilter, .vop_revoke = vop_generic_revoke, .vop_fsync = nullop, .vop_remove = vop_generic_badop, .vop_link = vop_generic_badop, .vop_rename = vop_generic_badop, .vop_mkdir = vop_generic_badop, .vop_rmdir = vop_generic_badop, .vop_symlink = vop_generic_badop, .vop_readdir = vop_generic_badop, .vop_readlink = vop_generic_badop, .vop_abortop = vop_generic_badop, .vop_inactive = fifo_inactive, .vop_reclaim = fifo_reclaim, .vop_lock = nullop, .vop_unlock = nullop, .vop_islocked = nullop, .vop_bmap = vop_generic_bmap, .vop_strategy = vop_generic_badop, .vop_print = fifo_print, .vop_pathconf = fifo_pathconf, .vop_advlock = fifo_advlock, .vop_bwrite = nullop }; void filt_fifordetach(struct knote *kn); int filt_fiforead(struct knote *kn, long hint); void filt_fifowdetach(struct knote *kn); int filt_fifowrite(struct knote *kn, long hint); int filt_fifoexcept(struct knote *kn, long hint); int filt_fiformodify(struct kevent *kev, struct knote *kn); int filt_fiforprocess(struct knote *kn, struct kevent *kev); int filt_fifowmodify(struct kevent *kev, struct knote *kn); int filt_fifowprocess(struct knote *kn, struct kevent *kev); const struct filterops fiforead_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_fifordetach, .f_event = filt_fiforead, .f_modify = filt_fiformodify, .f_process = filt_fiforprocess, }; const struct filterops fifowrite_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_fifowdetach, .f_event = filt_fifowrite, .f_modify = filt_fifowmodify, .f_process = filt_fifowprocess, }; const struct filterops fifoexcept_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_fifordetach, .f_event = filt_fifoexcept, .f_modify = filt_fiformodify, .f_process = filt_fiforprocess, }; /* * Open called to set up a new instance of a fifo or * to find an active instance of a fifo. */ int fifo_open(void *v) { struct vop_open_args *ap = v; struct vnode *vp = ap->a_vp; struct fifoinfo *fip; struct socket *rso, *wso; int error; if ((fip = vp->v_fifoinfo) == NULL) { fip = malloc(sizeof(*fip), M_VNODE, M_WAITOK); vp->v_fifoinfo = fip; if ((error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) != 0) { free(fip, M_VNODE, sizeof *fip); vp->v_fifoinfo = NULL; return (error); } fip->fi_readsock = rso; if ((error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) != 0) { (void)soclose(rso, 0); free(fip, M_VNODE, sizeof *fip); vp->v_fifoinfo = NULL; return (error); } fip->fi_writesock = wso; if ((error = soconnect2(wso, rso)) != 0) { (void)soclose(wso, 0); (void)soclose(rso, 0); free(fip, M_VNODE, sizeof *fip); vp->v_fifoinfo = NULL; return (error); } fip->fi_readers = fip->fi_writers = 0; mtx_enter(&wso->so_snd.sb_mtx); wso->so_snd.sb_state |= SS_CANTSENDMORE; wso->so_snd.sb_lowat = PIPE_BUF; mtx_leave(&wso->so_snd.sb_mtx); } else { rso = fip->fi_readsock; wso = fip->fi_writesock; } if (ap->a_mode & FREAD) { fip->fi_readers++; if (fip->fi_readers == 1) { mtx_enter(&wso->so_snd.sb_mtx); wso->so_snd.sb_state &= ~SS_CANTSENDMORE; mtx_leave(&wso->so_snd.sb_mtx); if (fip->fi_writers > 0) wakeup(&fip->fi_writers); } } if (ap->a_mode & FWRITE) { fip->fi_writers++; if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) { error = ENXIO; goto bad; } if (fip->fi_writers == 1) { solock(rso); rso->so_state &= ~SS_ISDISCONNECTED; mtx_enter(&rso->so_rcv.sb_mtx); rso->so_rcv.sb_state &= ~SS_CANTRCVMORE; mtx_leave(&rso->so_rcv.sb_mtx); sounlock(rso); if (fip->fi_readers > 0) wakeup(&fip->fi_readers); } } if ((ap->a_mode & O_NONBLOCK) == 0) { if ((ap->a_mode & FREAD) && fip->fi_writers == 0) { VOP_UNLOCK(vp); error = tsleep_nsec(&fip->fi_readers, PCATCH | PSOCK, "fifor", INFSLP); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if (error) goto bad; } if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) { VOP_UNLOCK(vp); error = tsleep_nsec(&fip->fi_writers, PCATCH | PSOCK, "fifow", INFSLP); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if (error) goto bad; } } return (0); bad: VOP_CLOSE(vp, ap->a_mode, ap->a_cred, ap->a_p); return (error); } /* * Vnode op for read */ int fifo_read(void *v) { struct vop_read_args *ap = v; struct uio *uio = ap->a_uio; struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock; int error, flags = 0; #ifdef DIAGNOSTIC if (uio->uio_rw != UIO_READ) panic("fifo_read mode"); #endif if (uio->uio_resid == 0) return (0); if (ap->a_ioflag & IO_NDELAY) flags |= MSG_DONTWAIT; VOP_UNLOCK(ap->a_vp); error = soreceive(rso, NULL, uio, NULL, NULL, &flags, 0); vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); if (ap->a_ioflag & IO_NDELAY) { if (error == EWOULDBLOCK && ap->a_vp->v_fifoinfo->fi_writers == 0) error = 0; } return (error); } /* * Vnode op for write */ int fifo_write(void *v) { struct vop_write_args *ap = v; struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock; int error, flags = 0; #ifdef DIAGNOSTIC if (ap->a_uio->uio_rw != UIO_WRITE) panic("fifo_write mode"); #endif if (ap->a_ioflag & IO_NDELAY) flags |= MSG_DONTWAIT; VOP_UNLOCK(ap->a_vp); error = sosend(wso, NULL, ap->a_uio, NULL, NULL, flags); vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); return (error); } /* * Device ioctl operation. */ int fifo_ioctl(void *v) { struct vop_ioctl_args *ap = v; struct file filetmp; int error; if (ap->a_command == FIONBIO) return (0); if (ap->a_fflag & FREAD) { filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock; error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p); if (error) return (error); } if (ap->a_fflag & FWRITE) { filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock; error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p); if (error) return (error); } return (0); } int fifo_inactive(void *v) { struct vop_inactive_args *ap = v; VOP_UNLOCK(ap->a_vp); return (0); } /* * Device close routine */ int fifo_close(void *v) { struct vop_close_args *ap = v; struct vnode *vp = ap->a_vp; struct fifoinfo *fip = vp->v_fifoinfo; int error1 = 0, error2 = 0; if (fip == NULL) return (0); if (ap->a_fflag & FREAD) { if (--fip->fi_readers == 0) { struct socket *wso = fip->fi_writesock; solock(wso); socantsendmore(wso); sounlock(wso); } } if (ap->a_fflag & FWRITE) { if (--fip->fi_writers == 0) { struct socket *rso = fip->fi_readsock; solock(rso); /* SS_ISDISCONNECTED will result in POLLHUP */ rso->so_state |= SS_ISDISCONNECTED; socantrcvmore(rso); sounlock(rso); } } if (fip->fi_readers == 0 && fip->fi_writers == 0) { error1 = soclose(fip->fi_readsock, 0); error2 = soclose(fip->fi_writesock, 0); free(fip, M_VNODE, sizeof *fip); vp->v_fifoinfo = NULL; } return (error1 ? error1 : error2); } int fifo_reclaim(void *v) { struct vop_reclaim_args *ap = v; struct vnode *vp = ap->a_vp; struct fifoinfo *fip = vp->v_fifoinfo; if (fip == NULL) return (0); soclose(fip->fi_readsock, 0); soclose(fip->fi_writesock, 0); free(fip, M_VNODE, sizeof *fip); vp->v_fifoinfo = NULL; return (0); } /* * Print out the contents of a fifo vnode. */ int fifo_print(void *v) { struct vop_print_args *ap = v; printf("tag VT_NON"); fifo_printinfo(ap->a_vp); printf("\n"); return 0; } /* * Print out internal contents of a fifo vnode. */ void fifo_printinfo(struct vnode *vp) { struct fifoinfo *fip = vp->v_fifoinfo; printf(", fifo with %ld readers and %ld writers", fip->fi_readers, fip->fi_writers); } /* * Return POSIX pathconf information applicable to fifo's. */ int fifo_pathconf(void *v) { struct vop_pathconf_args *ap = v; int error = 0; switch (ap->a_name) { case _PC_LINK_MAX: *ap->a_retval = LINK_MAX; break; case _PC_CHOWN_RESTRICTED: *ap->a_retval = 1; break; case _PC_TIMESTAMP_RESOLUTION: *ap->a_retval = 1; break; default: error = EINVAL; break; } return (error); } /* * Fifo failed operation */ int fifo_ebadf(void *v) { return (EBADF); } /* * Fifo advisory byte-level locks. */ int fifo_advlock(void *v) { return (EOPNOTSUPP); } int fifo_kqfilter(void *v) { struct vop_kqfilter_args *ap = v; struct fifoinfo *fip = ap->a_vp->v_fifoinfo; struct sockbuf *sb; struct socket *so; switch (ap->a_kn->kn_filter) { case EVFILT_READ: if (!(ap->a_fflag & FREAD)) return (EINVAL); ap->a_kn->kn_fop = &fiforead_filtops; so = fip->fi_readsock; sb = &so->so_rcv; break; case EVFILT_WRITE: if (!(ap->a_fflag & FWRITE)) { /* Tell upper layer to ask for POLLUP only */ if (ap->a_kn->kn_flags & (__EV_POLL | __EV_SELECT)) return (EPERM); return (EINVAL); } ap->a_kn->kn_fop = &fifowrite_filtops; so = fip->fi_writesock; sb = &so->so_snd; break; case EVFILT_EXCEPT: if (ap->a_kn->kn_flags & __EV_SELECT) { /* Prevent triggering exceptfds. */ return (EPERM); } if ((ap->a_kn->kn_flags & __EV_POLL) == 0) { /* Disallow usage through kevent(2). */ return (EINVAL); } ap->a_kn->kn_fop = &fifoexcept_filtops; so = fip->fi_readsock; sb = &so->so_rcv; break; default: return (EINVAL); } ap->a_kn->kn_hook = so; klist_insert(&sb->sb_klist, ap->a_kn); return (0); } void filt_fifordetach(struct knote *kn) { struct socket *so = (struct socket *)kn->kn_hook; klist_remove(&so->so_rcv.sb_klist, kn); } int filt_fiforead(struct knote *kn, long hint) { struct socket *so = kn->kn_hook; int rv; MUTEX_ASSERT_LOCKED(&so->so_rcv.sb_mtx); kn->kn_data = so->so_rcv.sb_cc; if (so->so_rcv.sb_state & SS_CANTRCVMORE) { kn->kn_flags |= EV_EOF; if (kn->kn_flags & __EV_POLL) { if (so->so_state & SS_ISDISCONNECTED) kn->kn_flags |= __EV_HUP; else kn->kn_flags &= ~__EV_HUP; } rv = 1; } else { kn->kn_flags &= ~(EV_EOF | __EV_HUP); rv = (kn->kn_data > 0); } return (rv); } void filt_fifowdetach(struct knote *kn) { struct socket *so = (struct socket *)kn->kn_hook; klist_remove(&so->so_snd.sb_klist, kn); } int filt_fifowrite(struct knote *kn, long hint) { struct socket *so = kn->kn_hook; int rv; MUTEX_ASSERT_LOCKED(&so->so_snd.sb_mtx); kn->kn_data = sbspace(so, &so->so_snd); if (so->so_snd.sb_state & SS_CANTSENDMORE) { kn->kn_flags |= EV_EOF; rv = 1; } else { kn->kn_flags &= ~EV_EOF; rv = (kn->kn_data >= so->so_snd.sb_lowat); } return (rv); } int filt_fifoexcept(struct knote *kn, long hint) { struct socket *so = kn->kn_hook; int rv = 0; MUTEX_ASSERT_LOCKED(&so->so_rcv.sb_mtx); if (kn->kn_flags & __EV_POLL) { if (so->so_state & SS_ISDISCONNECTED) { kn->kn_flags |= __EV_HUP; rv = 1; } else { kn->kn_flags &= ~__EV_HUP; } } return (rv); } int filt_fiformodify(struct kevent *kev, struct knote *kn) { struct socket *so = kn->kn_hook; int rv; solock(so); mtx_enter(&so->so_rcv.sb_mtx); rv = knote_modify(kev, kn); mtx_leave(&so->so_rcv.sb_mtx); sounlock(so); return (rv); } int filt_fiforprocess(struct knote *kn, struct kevent *kev) { struct socket *so = kn->kn_hook; int rv; solock(so); mtx_enter(&so->so_rcv.sb_mtx); rv = knote_process(kn, kev); mtx_leave(&so->so_rcv.sb_mtx); sounlock(so); return (rv); } int filt_fifowmodify(struct kevent *kev, struct knote *kn) { struct socket *so = kn->kn_hook; int rv; mtx_enter(&so->so_snd.sb_mtx); rv = knote_modify(kev, kn); mtx_leave(&so->so_snd.sb_mtx); return (rv); } int filt_fifowprocess(struct knote *kn, struct kevent *kev) { struct socket *so = kn->kn_hook; int rv; mtx_enter(&so->so_snd.sb_mtx); rv = knote_process(kn, kev); mtx_leave(&so->so_snd.sb_mtx); return (rv); }
6247 6251 6247 537 6250 6 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 /* $OpenBSD: intr.c,v 1.56 2024/01/19 18:38:16 kettenis Exp $ */ /* $NetBSD: intr.c,v 1.3 2003/03/03 22:16:20 fvdl Exp $ */ /* * Copyright 2002 (c) Wasabi Systems, Inc. * All rights reserved. * * Written by Frank van der Linden for Wasabi Systems, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed for the NetBSD Project by * Wasabi Systems, Inc. * 4. The name of Wasabi Systems, Inc. may not be used to endorse * or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* #define INTRDEBUG */ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/syslog.h> #include <sys/device.h> #include <sys/malloc.h> #include <sys/errno.h> #include <machine/atomic.h> #include <machine/i8259.h> #include <machine/cpu.h> #include <machine/pio.h> #include <machine/cpufunc.h> #include "lapic.h" #include "xen.h" #include "hyperv.h" #if NLAPIC > 0 #include <machine/i82489var.h> #endif struct pic softintr_pic = { {0, {NULL}, NULL, 0, "softintr_pic0", NULL, 0, 0}, PIC_SOFT, #ifdef MULTIPROCESSOR {}, #endif NULL, NULL, NULL, NULL, NULL, }; /* * Fill in default interrupt table (in case of spurious interrupt * during configuration of kernel), setup interrupt control unit */ void intr_default_setup(void) { int i; /* icu vectors */ for (i = 0; i < NUM_LEGACY_IRQS; i++) { idt_allocmap[ICU_OFFSET + i] = 1; setgate(&idt[ICU_OFFSET + i], i8259_stubs[i].ist_entry, 0, SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); } /* * Eventually might want to check if it's actually there. */ i8259_default_setup(); } /* * Handle a NMI, possibly a machine check. * return true to panic system, false to ignore. */ int x86_nmi(void) { log(LOG_CRIT, "NMI port 61 %x, port 70 %x\n", inb(0x61), inb(0x70)); return(0); } /* * Recalculate the interrupt masks from scratch. */ void intr_calculatemasks(struct cpu_info *ci) { int irq, level; u_int64_t unusedirqs, intrlevel[MAX_INTR_SOURCES]; struct intrhand *q; /* First, figure out which levels each IRQ uses. */ unusedirqs = 0xffffffffffffffffUL; for (irq = 0; irq < MAX_INTR_SOURCES; irq++) { int levels = 0; if (ci->ci_isources[irq] == NULL) { intrlevel[irq] = 0; continue; } for (q = ci->ci_isources[irq]->is_handlers; q; q = q->ih_next) levels |= (1 << q->ih_level); intrlevel[irq] = levels; if (levels) unusedirqs &= ~(1UL << irq); } /* Then figure out which IRQs use each level. */ for (level = 0; level < NIPL; level++) { u_int64_t irqs = 0; for (irq = 0; irq < MAX_INTR_SOURCES; irq++) if (intrlevel[irq] & (1 << level)) irqs |= (1UL << irq); ci->ci_imask[level] = irqs | unusedirqs; } for (level = 0; level< (NIPL - 1); level++) ci->ci_imask[level + 1] |= ci->ci_imask[level]; for (irq = 0; irq < MAX_INTR_SOURCES; irq++) { int maxlevel = IPL_NONE; int minlevel = IPL_HIGH; if (ci->ci_isources[irq] == NULL) continue; for (q = ci->ci_isources[irq]->is_handlers; q; q = q->ih_next) { if (q->ih_level < minlevel) minlevel = q->ih_level; if (q->ih_level > maxlevel) maxlevel = q->ih_level; } ci->ci_isources[irq]->is_maxlevel = maxlevel; ci->ci_isources[irq]->is_minlevel = minlevel; } for (level = 0; level < NIPL; level++) ci->ci_iunmask[level] = ~ci->ci_imask[level]; } int intr_allocate_slot_cpu(struct cpu_info *ci, struct pic *pic, int pin, int *index) { int start, slot, i; struct intrsource *isp; start = CPU_IS_PRIMARY(ci) ? NUM_LEGACY_IRQS : 0; slot = -1; for (i = 0; i < start; i++) { isp = ci->ci_isources[i]; if (isp != NULL && isp->is_pic == pic && isp->is_pin == pin) { slot = i; start = MAX_INTR_SOURCES; break; } } for (i = start; i < MAX_INTR_SOURCES ; i++) { isp = ci->ci_isources[i]; if (isp != NULL && isp->is_pic == pic && isp->is_pin == pin) { slot = i; break; } if (isp == NULL && slot == -1) { slot = i; continue; } } if (slot == -1) { return EBUSY; } isp = ci->ci_isources[slot]; if (isp == NULL) { isp = malloc(sizeof (struct intrsource), M_DEVBUF, M_NOWAIT|M_ZERO); if (isp == NULL) { return ENOMEM; } snprintf(isp->is_evname, sizeof (isp->is_evname), "pin %d", pin); ci->ci_isources[slot] = isp; } *index = slot; return 0; } /* * A simple round-robin allocator to assign interrupts to CPUs. */ int intr_allocate_slot(struct pic *pic, int legacy_irq, int pin, int level, struct cpu_info **cip, int *index, int *idt_slot) { CPU_INFO_ITERATOR cii; struct cpu_info *ci; struct intrsource *isp; int slot, idtvec, error; /* * If a legacy IRQ is wanted, try to use a fixed slot pointing * at the primary CPU. In the case of IO APICs, multiple pins * may map to one legacy IRQ, but they should not be shared * in that case, so the first one gets the legacy slot, but * a subsequent allocation with a different pin will get * a different slot. */ if (legacy_irq != -1) { ci = &cpu_info_primary; /* must check for duplicate pic + pin first */ for (slot = 0 ; slot < MAX_INTR_SOURCES ; slot++) { isp = ci->ci_isources[slot]; if (isp != NULL && isp->is_pic == pic && isp->is_pin == pin ) { goto duplicate; } } slot = legacy_irq; isp = ci->ci_isources[slot]; if (isp == NULL) { isp = malloc(sizeof (struct intrsource), M_DEVBUF, M_NOWAIT|M_ZERO); if (isp == NULL) return ENOMEM; snprintf(isp->is_evname, sizeof (isp->is_evname), "pin %d", pin); ci->ci_isources[slot] = isp; } else { if (isp->is_pic != pic || isp->is_pin != pin) { if (pic == &i8259_pic) return EINVAL; goto other; } } duplicate: if (pic == &i8259_pic) idtvec = ICU_OFFSET + legacy_irq; else { #ifdef IOAPIC_HWMASK if (level > isp->is_maxlevel) { #else if (isp->is_minlevel == 0 || level < isp->is_minlevel) { #endif idtvec = idt_vec_alloc(APIC_LEVEL(level), IDT_INTR_HIGH); if (idtvec == 0) return EBUSY; } else idtvec = isp->is_idtvec; } } else { other: /* * Otherwise, look for a free slot elsewhere. If cip is null, it * means try primary cpu but accept secondary, otherwise we need * a slot on the requested cpu. */ if (*cip == NULL) ci = &cpu_info_primary; else ci = *cip; error = intr_allocate_slot_cpu(ci, pic, pin, &slot); if (error == 0) goto found; /* Can't alloc on the requested cpu, fail. */ if (*cip != NULL) return EBUSY; /* * ..now try the others. */ CPU_INFO_FOREACH(cii, ci) { if (CPU_IS_PRIMARY(ci)) continue; error = intr_allocate_slot_cpu(ci, pic, pin, &slot); if (error == 0) goto found; } return EBUSY; found: if (pic->pic_allocidtvec) { idtvec = pic->pic_allocidtvec(pic, pin, APIC_LEVEL(level), IDT_INTR_HIGH); } else { idtvec = idt_vec_alloc(APIC_LEVEL(level), IDT_INTR_HIGH); } if (idtvec == 0) { free(ci->ci_isources[slot], M_DEVBUF, sizeof (struct intrsource)); ci->ci_isources[slot] = NULL; return EBUSY; } } *idt_slot = idtvec; *index = slot; *cip = ci; return 0; } /* * True if the system has any non-level interrupts which are shared * on the same pin. */ int intr_shared_edge; void * intr_establish(int legacy_irq, struct pic *pic, int pin, int type, int level, struct cpu_info *ci, int (*handler)(void *), void *arg, const char *what) { struct intrhand **p, *q, *ih; int slot, error, idt_vec; struct intrsource *source; struct intrstub *stubp; int flags; #ifdef DIAGNOSTIC if (legacy_irq != -1 && (legacy_irq < 0 || legacy_irq > 15)) panic("intr_establish: bad legacy IRQ value"); if (legacy_irq == -1 && pic == &i8259_pic) panic("intr_establish: non-legacy IRQ on i8259"); #endif flags = level & IPL_MPSAFE; level &= ~IPL_MPSAFE; KASSERT(level <= IPL_TTY || level >= IPL_CLOCK || flags & IPL_MPSAFE); error = intr_allocate_slot(pic, legacy_irq, pin, level, &ci, &slot, &idt_vec); if (error != 0) { printf("failed to allocate interrupt slot for PIC %s pin %d\n", pic->pic_dev.dv_xname, pin); return NULL; } /* no point in sleeping unless someone can free memory. */ ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK); if (ih == NULL) { printf("intr_establish: can't allocate handler info\n"); return NULL; } source = ci->ci_isources[slot]; if (source->is_handlers != NULL && source->is_pic->pic_type != pic->pic_type) { free(ih, M_DEVBUF, sizeof(*ih)); printf("intr_establish: can't share intr source between " "different PIC types (legacy_irq %d pin %d slot %d)\n", legacy_irq, pin, slot); return NULL; } source->is_pin = pin; source->is_pic = pic; switch (source->is_type) { case IST_NONE: source->is_type = type; break; case IST_EDGE: intr_shared_edge = 1; /* FALLTHROUGH */ case IST_LEVEL: if (source->is_type == type) break; case IST_PULSE: if (type != IST_NONE) { printf("intr_establish: pic %s pin %d: can't share " "type %d with %d\n", pic->pic_name, pin, source->is_type, type); free(ih, M_DEVBUF, sizeof(*ih)); return NULL; } break; default: panic("intr_establish: bad intr type %d for pic %s pin %d", source->is_type, pic->pic_dev.dv_xname, pin); } if (!cold) pic->pic_hwmask(pic, pin); /* * Figure out where to put the handler. * This is O(N^2), but we want to preserve the order, and N is * generally small. */ for (p = &ci->ci_isources[slot]->is_handlers; (q = *p) != NULL && q->ih_level > level; p = &q->ih_next) ; ih->ih_fun = handler; ih->ih_arg = arg; ih->ih_next = *p; ih->ih_level = level; ih->ih_flags = flags; ih->ih_pin = pin; ih->ih_cpu = ci; ih->ih_slot = slot; evcount_attach(&ih->ih_count, what, &source->is_idtvec); *p = ih; intr_calculatemasks(ci); if (ci->ci_isources[slot]->is_resume == NULL || source->is_idtvec != idt_vec) { if (source->is_idtvec != 0 && source->is_idtvec != idt_vec) idt_vec_free(source->is_idtvec); source->is_idtvec = idt_vec; stubp = type == IST_LEVEL ? &pic->pic_level_stubs[slot] : &pic->pic_edge_stubs[slot]; ci->ci_isources[slot]->is_resume = stubp->ist_resume; ci->ci_isources[slot]->is_recurse = stubp->ist_recurse; setgate(&idt[idt_vec], stubp->ist_entry, 0, SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); } pic->pic_addroute(pic, ci, pin, idt_vec, type); if (!cold) pic->pic_hwunmask(pic, pin); #ifdef INTRDEBUG printf("allocated pic %s type %s pin %d level %d to cpu%u slot %d idt entry %d\n", pic->pic_name, type == IST_EDGE ? "edge" : "level", pin, level, ci->ci_apicid, slot, idt_vec); #endif return (ih); } /* * Deregister an interrupt handler. */ void intr_disestablish(struct intrhand *ih) { struct intrhand **p, *q; struct cpu_info *ci; struct pic *pic; struct intrsource *source; int idtvec; ci = ih->ih_cpu; pic = ci->ci_isources[ih->ih_slot]->is_pic; source = ci->ci_isources[ih->ih_slot]; idtvec = source->is_idtvec; pic->pic_hwmask(pic, ih->ih_pin); x86_atomic_clearbits_u64(&ci->ci_ipending, (1UL << ih->ih_slot)); /* * Remove the handler from the chain. */ for (p = &source->is_handlers; (q = *p) != NULL && q != ih; p = &q->ih_next) ; if (q == NULL) { panic("intr_disestablish: handler not registered"); } *p = q->ih_next; intr_calculatemasks(ci); if (source->is_handlers == NULL) pic->pic_delroute(pic, ci, ih->ih_pin, idtvec, source->is_type); else pic->pic_hwunmask(pic, ih->ih_pin); #ifdef INTRDEBUG printf("cpu%u: remove slot %d (pic %s pin %d vec %d)\n", ci->ci_apicid, ih->ih_slot, pic->pic_dev.dv_xname, ih->ih_pin, idtvec); #endif if (source->is_handlers == NULL) { free(source, M_DEVBUF, sizeof (struct intrsource)); ci->ci_isources[ih->ih_slot] = NULL; if (pic != &i8259_pic) idt_vec_free(idtvec); } evcount_detach(&ih->ih_count); free(ih, M_DEVBUF, sizeof(*ih)); } int intr_handler(struct intrframe *frame, struct intrhand *ih) { struct cpu_info *ci = curcpu(); int floor; int rc; #ifdef MULTIPROCESSOR int need_lock; if (ih->ih_flags & IPL_MPSAFE) need_lock = 0; else need_lock = 1; if (need_lock) __mp_lock(&kernel_lock); #endif floor = ci->ci_handled_intr_level; ci->ci_handled_intr_level = ih->ih_level; rc = (*ih->ih_fun)(ih->ih_arg ? ih->ih_arg : frame); ci->ci_handled_intr_level = floor; #ifdef MULTIPROCESSOR if (need_lock) __mp_unlock(&kernel_lock); #endif return rc; } #define CONCAT(x,y) __CONCAT(x,y) /* * Fake interrupt handler structures for the benefit of symmetry with * other interrupt sources, and the benefit of intr_calculatemasks() */ struct intrhand fake_softclock_intrhand; struct intrhand fake_softnet_intrhand; struct intrhand fake_softtty_intrhand; struct intrhand fake_timer_intrhand; struct intrhand fake_ipi_intrhand; #if NXEN > 0 struct intrhand fake_xen_intrhand; #endif #if NHYPERV > 0 struct intrhand fake_hyperv_intrhand; #endif /* * Initialize all handlers that aren't dynamically allocated, and exist * for each CPU. */ void cpu_intr_init(struct cpu_info *ci) { struct intrsource *isp; #if NLAPIC > 0 && defined(MULTIPROCESSOR) && 0 int i; #endif isp = malloc(sizeof (struct intrsource), M_DEVBUF, M_NOWAIT|M_ZERO); if (isp == NULL) panic("can't allocate fixed interrupt source"); isp->is_recurse = Xsoftclock; isp->is_resume = Xsoftclock; fake_softclock_intrhand.ih_level = IPL_SOFTCLOCK; isp->is_handlers = &fake_softclock_intrhand; isp->is_pic = &softintr_pic; ci->ci_isources[SIR_CLOCK] = isp; isp = malloc(sizeof (struct intrsource), M_DEVBUF, M_NOWAIT|M_ZERO); if (isp == NULL) panic("can't allocate fixed interrupt source"); isp->is_recurse = Xsoftnet; isp->is_resume = Xsoftnet; fake_softnet_intrhand.ih_level = IPL_SOFTNET; isp->is_handlers = &fake_softnet_intrhand; isp->is_pic = &softintr_pic; ci->ci_isources[SIR_NET] = isp; isp = malloc(sizeof (struct intrsource), M_DEVBUF, M_NOWAIT|M_ZERO); if (isp == NULL) panic("can't allocate fixed interrupt source"); isp->is_recurse = Xsofttty; isp->is_resume = Xsofttty; fake_softtty_intrhand.ih_level = IPL_SOFTTTY; isp->is_handlers = &fake_softtty_intrhand; isp->is_pic = &softintr_pic; ci->ci_isources[SIR_TTY] = isp; #if NLAPIC > 0 isp = malloc(sizeof (struct intrsource), M_DEVBUF, M_NOWAIT|M_ZERO); if (isp == NULL) panic("can't allocate fixed interrupt source"); isp->is_recurse = Xrecurse_lapic_ltimer; isp->is_resume = Xresume_lapic_ltimer; fake_timer_intrhand.ih_level = IPL_CLOCK; isp->is_handlers = &fake_timer_intrhand; isp->is_pic = &local_pic; ci->ci_isources[LIR_TIMER] = isp; #ifdef MULTIPROCESSOR isp = malloc(sizeof (struct intrsource), M_DEVBUF, M_NOWAIT|M_ZERO); if (isp == NULL) panic("can't allocate fixed interrupt source"); isp->is_recurse = Xrecurse_lapic_ipi; isp->is_resume = Xresume_lapic_ipi; fake_ipi_intrhand.ih_level = IPL_IPI; isp->is_handlers = &fake_ipi_intrhand; isp->is_pic = &local_pic; ci->ci_isources[LIR_IPI] = isp; #endif #if NXEN > 0 isp = malloc(sizeof (struct intrsource), M_DEVBUF, M_NOWAIT|M_ZERO); if (isp == NULL) panic("can't allocate fixed interrupt source"); isp->is_recurse = Xrecurse_xen_upcall; isp->is_resume = Xresume_xen_upcall; fake_xen_intrhand.ih_level = IPL_NET; isp->is_handlers = &fake_xen_intrhand; isp->is_pic = &local_pic; ci->ci_isources[LIR_XEN] = isp; #endif #if NHYPERV > 0 isp = malloc(sizeof (struct intrsource), M_DEVBUF, M_NOWAIT|M_ZERO); if (isp == NULL) panic("can't allocate fixed interrupt source"); isp->is_recurse = Xrecurse_hyperv_upcall; isp->is_resume = Xresume_hyperv_upcall; fake_hyperv_intrhand.ih_level = IPL_NET; isp->is_handlers = &fake_hyperv_intrhand; isp->is_pic = &local_pic; ci->ci_isources[LIR_HYPERV] = isp; #endif #endif /* NLAPIC */ intr_calculatemasks(ci); } void intr_printconfig(void) { #ifdef INTRDEBUG int i; struct intrhand *ih; struct intrsource *isp; struct cpu_info *ci; CPU_INFO_ITERATOR cii; CPU_INFO_FOREACH(cii, ci) { printf("cpu%d: interrupt masks:\n", ci->ci_apicid); for (i = 0; i < NIPL; i++) printf("IPL %d mask %lx unmask %lx\n", i, (u_long)ci->ci_imask[i], (u_long)ci->ci_iunmask[i]); for (i = 0; i < MAX_INTR_SOURCES; i++) { isp = ci->ci_isources[i]; if (isp == NULL) continue; printf("cpu%u source %d is pin %d from pic %s maxlevel %d\n", ci->ci_apicid, i, isp->is_pin, isp->is_pic->pic_name, isp->is_maxlevel); for (ih = isp->is_handlers; ih != NULL; ih = ih->ih_next) printf("\thandler %p level %d\n", ih->ih_fun, ih->ih_level); } } #endif } void intr_barrier(void *cookie) { struct intrhand *ih = cookie; sched_barrier(ih->ih_cpu); } /* * Add a mask to cpl, and return the old value of cpl. */ int splraise(int nlevel) { int olevel; struct cpu_info *ci = curcpu(); KASSERT(nlevel >= IPL_NONE); olevel = ci->ci_ilevel; ci->ci_ilevel = MAX(ci->ci_ilevel, nlevel); return (olevel); } /* * Restore a value to cpl (unmasking interrupts). If any unmasked * interrupts are pending, call Xspllower() to process them. */ int spllower(int nlevel) { int olevel; struct cpu_info *ci = curcpu(); u_int64_t imask; u_long flags; imask = IUNMASK(ci, nlevel); olevel = ci->ci_ilevel; flags = intr_disable(); if (ci->ci_ipending & imask) { Xspllower(nlevel); } else { ci->ci_ilevel = nlevel; intr_restore(flags); } return (olevel); } /* * Software interrupt registration * * We hand-code this to ensure that it's atomic. * * XXX always scheduled on the current CPU. */ void softintr(int sir) { struct cpu_info *ci = curcpu(); __asm volatile("lock; orq %1, %0" : "=m"(ci->ci_ipending) : "ir" (1UL << sir)); }
76 75 1 74 76 76 76 75 2 2 2 2 253 252 253 252 1160 32 1172 6 1167 1169 1172 2 2 2 2 2 13 13 10 8 4 4 4 4 199 199 169 68 153 172 199 68 169 782 760 178 68 1170 2 1172 1168 8 1172 69 20 2 74 76 1169 9 1165 1173 1171 120 120 2 4 1171 120 213 1164 120 2 2 121 7 122 122 121 122 122 120 120 2 121 4 122 1175 1173 1166 8 21 21 21 19 1 8 13 2 20 991 994 1169 1171 3 1168 1162 1162 1162 15 286 577 561 267 606 34 1166 1169 1166 266 560 607 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 /* $OpenBSD: vfs_bio.c,v 1.213 2024/02/03 18:51:58 beck Exp $ */ /* $NetBSD: vfs_bio.c,v 1.44 1996/06/11 11:15:36 pk Exp $ */ /* * Copyright (c) 1994 Christopher G. Demetriou * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)vfs_bio.c 8.6 (Berkeley) 1/11/94 */ /* * Some references: * Bach: The Design of the UNIX Operating System (Prentice Hall, 1986) * Leffler, et al.: The Design and Implementation of the 4.3BSD * UNIX Operating System (Addison Welley, 1989) */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/buf.h> #include <sys/vnode.h> #include <sys/mount.h> #include <sys/malloc.h> #include <sys/pool.h> #include <sys/specdev.h> #include <sys/tracepoint.h> #include <uvm/uvm_extern.h> /* XXX Should really be in buf.h, but for uvm_constraint_range.. */ int buf_realloc_pages(struct buf *, struct uvm_constraint_range *, int); struct uvm_constraint_range high_constraint; int fliphigh; int nobuffers; int needbuffer; /* private bufcache functions */ void bufcache_init(void); void bufcache_adjust(void); struct buf *bufcache_gethighcleanbuf(void); struct buf *bufcache_getdmacleanbuf(void); /* * Buffer pool for I/O buffers. */ struct pool bufpool; struct bufhead bufhead = LIST_HEAD_INITIALIZER(bufhead); void buf_put(struct buf *); struct buf *bio_doread(struct vnode *, daddr_t, int, int); struct buf *buf_get(struct vnode *, daddr_t, size_t); void bread_cluster_callback(struct buf *); int64_t bufcache_recover_dmapages(int discard, int64_t howmany); static struct buf *incore_locked(struct vnode *vp, daddr_t blkno); struct bcachestats bcstats; /* counters */ long lodirtypages; /* dirty page count low water mark */ long hidirtypages; /* dirty page count high water mark */ long targetpages; /* target number of pages for cache size */ long buflowpages; /* smallest size cache allowed */ long bufhighpages; /* largest size cache allowed */ long bufbackpages; /* minimum number of pages we shrink when asked to */ vsize_t bufkvm; struct proc *cleanerproc; int bd_req; /* Sleep point for cleaner daemon. */ #define NUM_CACHES 2 #define DMA_CACHE 0 struct bufcache cleancache[NUM_CACHES]; struct bufqueue dirtyqueue; void buf_put(struct buf *bp) { splassert(IPL_BIO); #ifdef DIAGNOSTIC if (bp->b_pobj != NULL) KASSERT(bp->b_bufsize > 0); if (ISSET(bp->b_flags, B_DELWRI)) panic("buf_put: releasing dirty buffer"); if (bp->b_freelist.tqe_next != NOLIST && bp->b_freelist.tqe_next != (void *)-1) panic("buf_put: still on the free list"); if (bp->b_vnbufs.le_next != NOLIST && bp->b_vnbufs.le_next != (void *)-1) panic("buf_put: still on the vnode list"); #endif LIST_REMOVE(bp, b_list); bcstats.numbufs--; if (buf_dealloc_mem(bp) != 0) return; pool_put(&bufpool, bp); } /* * Initialize buffers and hash links for buffers. */ void bufinit(void) { u_int64_t dmapages; u_int64_t highpages; dmapages = uvm_pagecount(&dma_constraint); /* take away a guess at how much of this the kernel will consume */ dmapages -= (atop(physmem) - atop(uvmexp.free)); /* See if we have memory above the dma accessible region. */ high_constraint.ucr_low = dma_constraint.ucr_high; high_constraint.ucr_high = no_constraint.ucr_high; if (high_constraint.ucr_low != high_constraint.ucr_high) high_constraint.ucr_low++; highpages = uvm_pagecount(&high_constraint); /* * Do we have any significant amount of high memory above * the DMA region? if so enable moving buffers there, if not, * don't bother. */ if (highpages > dmapages / 4) fliphigh = 1; else fliphigh = 0; /* * If MD code doesn't say otherwise, use up to 10% of DMA'able * memory for buffers. */ if (bufcachepercent == 0) bufcachepercent = 10; /* * XXX these values and their same use in kern_sysctl * need to move into buf.h */ KASSERT(bufcachepercent <= 90); KASSERT(bufcachepercent >= 5); if (bufpages == 0) bufpages = dmapages * bufcachepercent / 100; if (bufpages < BCACHE_MIN) bufpages = BCACHE_MIN; KASSERT(bufpages < dmapages); bufhighpages = bufpages; /* * Set the base backoff level for the buffer cache. We will * not allow uvm to steal back more than this number of pages. */ buflowpages = dmapages * 5 / 100; if (buflowpages < BCACHE_MIN) buflowpages = BCACHE_MIN; /* * set bufbackpages to 100 pages, or 10 percent of the low water mark * if we don't have that many pages. */ bufbackpages = buflowpages * 10 / 100; if (bufbackpages > 100) bufbackpages = 100; /* * If the MD code does not say otherwise, reserve 10% of kva * space for mapping buffers. */ if (bufkvm == 0) bufkvm = VM_KERNEL_SPACE_SIZE / 10; /* * Don't use more than twice the amount of bufpages for mappings. * It's twice since we map things sparsely. */ if (bufkvm > bufpages * PAGE_SIZE) bufkvm = bufpages * PAGE_SIZE; /* * Round bufkvm to MAXPHYS because we allocate chunks of va space * in MAXPHYS chunks. */ bufkvm &= ~(MAXPHYS - 1); pool_init(&bufpool, sizeof(struct buf), 0, IPL_BIO, 0, "bufpl", NULL); bufcache_init(); /* * hmm - bufkvm is an argument because it's static, while * bufpages is global because it can change while running. */ buf_mem_init(bufkvm); /* * Set the dirty page high water mark to be less than the low * water mark for pages in the buffer cache. This ensures we * can always back off by throwing away clean pages, and give * ourselves a chance to write out the dirty pages eventually. */ hidirtypages = (buflowpages / 4) * 3; lodirtypages = buflowpages / 2; /* * We are allowed to use up to the reserve. */ targetpages = bufpages - RESERVE_PAGES; } /* * Change cachepct */ void bufadjust(int newbufpages) { int s; int64_t npages; if (newbufpages < buflowpages) newbufpages = buflowpages; s = splbio(); bufpages = newbufpages; /* * We are allowed to use up to the reserve */ targetpages = bufpages - RESERVE_PAGES; npages = bcstats.dmapages - targetpages; /* * Shrinking the cache happens here only if someone has manually * adjusted bufcachepercent - or the pagedaemon has told us * to give back memory *now* - so we give it all back. */ if (bcstats.dmapages > targetpages) (void) bufcache_recover_dmapages(0, bcstats.dmapages - targetpages); bufcache_adjust(); /* * Wake up the cleaner if we have lots of dirty pages, * or if we are getting low on buffer cache kva. */ if ((UNCLEAN_PAGES >= hidirtypages) || bcstats.kvaslots_avail <= 2 * RESERVE_SLOTS) wakeup(&bd_req); splx(s); } /* * Make the buffer cache back off from cachepct. */ int bufbackoff(struct uvm_constraint_range *range, long size) { /* * Back off "size" buffer cache pages. Called by the page * daemon to consume buffer cache pages rather than scanning. * * It returns 0 to the pagedaemon to indicate that it has * succeeded in freeing enough pages. It returns -1 to * indicate that it could not and the pagedaemon should take * other measures. * */ long pdelta, oldbufpages; /* * If we will accept high memory for this backoff * try to steal it from the high memory buffer cache. */ if (range != NULL && range->ucr_high > dma_constraint.ucr_high) { struct buf *bp; int64_t start = bcstats.numbufpages, recovered = 0; int s = splbio(); while ((recovered < size) && (bp = bufcache_gethighcleanbuf())) { bufcache_take(bp); if (bp->b_vp) { RBT_REMOVE(buf_rb_bufs, &bp->b_vp->v_bufs_tree, bp); brelvp(bp); } buf_put(bp); recovered = start - bcstats.numbufpages; } bufcache_adjust(); splx(s); /* If we got enough, return success */ if (recovered >= size) return 0; /* * If we needed only memory above DMA, * return failure */ if (range->ucr_low > dma_constraint.ucr_high) return -1; /* Otherwise get the rest from DMA */ size -= recovered; } /* * XXX Otherwise do the dma memory cache dance. this needs * refactoring later to get rid of 'bufpages' */ /* * Back off by at least bufbackpages. If the page daemon gave us * a larger size, back off by that much. */ pdelta = (size > bufbackpages) ? size : bufbackpages; if (bufpages <= buflowpages) return(-1); if (bufpages - pdelta < buflowpages) pdelta = bufpages - buflowpages; oldbufpages = bufpages; bufadjust(bufpages - pdelta); if (oldbufpages - bufpages < size) return (-1); /* we did not free what we were asked */ else return(0); } /* * Opportunistically flip a buffer into high memory. Will move the buffer * if memory is available without sleeping, and return 0, otherwise will * fail and return -1 with the buffer unchanged. */ int buf_flip_high(struct buf *bp) { int ret = -1; KASSERT(ISSET(bp->b_flags, B_BC)); KASSERT(ISSET(bp->b_flags, B_DMA)); KASSERT(bp->cache == DMA_CACHE); KASSERT(fliphigh); splassert(IPL_BIO); /* Attempt to move the buffer to high memory if we can */ if (buf_realloc_pages(bp, &high_constraint, UVM_PLA_NOWAIT) == 0) { KASSERT(!ISSET(bp->b_flags, B_DMA)); bcstats.highflips++; ret = 0; } else bcstats.highflops++; return ret; } /* * Flip a buffer to dma reachable memory, when we need it there for * I/O. This can sleep since it will wait for memory allocation in the * DMA reachable area since we have to have the buffer there to proceed. */ void buf_flip_dma(struct buf *bp) { KASSERT(ISSET(bp->b_flags, B_BC)); KASSERT(ISSET(bp->b_flags, B_BUSY)); KASSERT(bp->cache < NUM_CACHES); splassert(IPL_BIO); if (!ISSET(bp->b_flags, B_DMA)) { /* move buf to dma reachable memory */ (void) buf_realloc_pages(bp, &dma_constraint, UVM_PLA_WAITOK); KASSERT(ISSET(bp->b_flags, B_DMA)); bcstats.dmaflips++; } if (bp->cache > DMA_CACHE) { CLR(bp->b_flags, B_COLD); CLR(bp->b_flags, B_WARM); bp->cache = DMA_CACHE; } } struct buf * bio_doread(struct vnode *vp, daddr_t blkno, int size, int async) { struct buf *bp; struct mount *mp; bp = getblk(vp, blkno, size, 0, INFSLP); /* * If buffer does not have valid data, start a read. * Note that if buffer is B_INVAL, getblk() won't return it. * Therefore, it's valid if its I/O has completed or been delayed. */ if (!ISSET(bp->b_flags, (B_DONE | B_DELWRI))) { SET(bp->b_flags, B_READ | async); bcstats.pendingreads++; bcstats.numreads++; VOP_STRATEGY(bp->b_vp, bp); /* Pay for the read. */ curproc->p_ru.ru_inblock++; /* XXX */ } else if (async) { brelse(bp); } mp = vp->v_type == VBLK ? vp->v_specmountpoint : vp->v_mount; /* * Collect statistics on synchronous and asynchronous reads. * Reads from block devices are charged to their associated * filesystem (if any). */ if (mp != NULL) { if (async == 0) mp->mnt_stat.f_syncreads++; else mp->mnt_stat.f_asyncreads++; } return (bp); } /* * Read a disk block. * This algorithm described in Bach (p.54). */ int bread(struct vnode *vp, daddr_t blkno, int size, struct buf **bpp) { struct buf *bp; /* Get buffer for block. */ bp = *bpp = bio_doread(vp, blkno, size, 0); /* Wait for the read to complete, and return result. */ return (biowait(bp)); } /* * Read-ahead multiple disk blocks. The first is sync, the rest async. * Trivial modification to the breada algorithm presented in Bach (p.55). */ int breadn(struct vnode *vp, daddr_t blkno, int size, daddr_t rablks[], int rasizes[], int nrablks, struct buf **bpp) { struct buf *bp; int i; bp = *bpp = bio_doread(vp, blkno, size, 0); /* * For each of the read-ahead blocks, start a read, if necessary. */ for (i = 0; i < nrablks; i++) { /* If it's in the cache, just go on to next one. */ if (incore(vp, rablks[i])) continue; /* Get a buffer for the read-ahead block */ (void) bio_doread(vp, rablks[i], rasizes[i], B_ASYNC); } /* Otherwise, we had to start a read for it; wait until it's valid. */ return (biowait(bp)); } /* * Called from interrupt context. */ void bread_cluster_callback(struct buf *bp) { struct buf **xbpp = bp->b_saveaddr; int i; if (xbpp[1] != NULL) { size_t newsize = xbpp[1]->b_bufsize; /* * Shrink this buffer's mapping to only cover its part of * the total I/O. */ buf_fix_mapping(bp, newsize); bp->b_bcount = newsize; } /* Invalidate read-ahead buffers if read short */ if (bp->b_resid > 0) { for (i = 1; xbpp[i] != NULL; i++) continue; for (i = i - 1; i != 0; i--) { if (xbpp[i]->b_bufsize <= bp->b_resid) { bp->b_resid -= xbpp[i]->b_bufsize; SET(xbpp[i]->b_flags, B_INVAL); } else if (bp->b_resid > 0) { bp->b_resid = 0; SET(xbpp[i]->b_flags, B_INVAL); } else break; } } for (i = 1; xbpp[i] != NULL; i++) { if (ISSET(bp->b_flags, B_ERROR)) SET(xbpp[i]->b_flags, B_INVAL | B_ERROR); /* * Move the pages from the master buffer's uvm object * into the individual buffer's uvm objects. */ struct uvm_object *newobj = &xbpp[i]->b_uobj; struct uvm_object *oldobj = &bp->b_uobj; int page; uvm_obj_init(newobj, &bufcache_pager, 1); for (page = 0; page < atop(xbpp[i]->b_bufsize); page++) { struct vm_page *pg = uvm_pagelookup(oldobj, xbpp[i]->b_poffs + ptoa(page)); KASSERT(pg != NULL); KASSERT(pg->wire_count == 1); uvm_pagerealloc(pg, newobj, xbpp[i]->b_poffs + ptoa(page)); } xbpp[i]->b_pobj = newobj; biodone(xbpp[i]); } free(xbpp, M_TEMP, (i + 1) * sizeof(*xbpp)); if (ISSET(bp->b_flags, B_ASYNC)) { brelse(bp); } else { CLR(bp->b_flags, B_WANTED); wakeup(bp); } } /* * Read-ahead multiple disk blocks, but make sure only one (big) I/O * request is sent to the disk. * XXX This should probably be dropped and breadn should instead be optimized * XXX to do fewer I/O requests. */ int bread_cluster(struct vnode *vp, daddr_t blkno, int size, struct buf **rbpp) { struct buf *bp, **xbpp; int howmany, maxra, i, inc; daddr_t sblkno; *rbpp = bio_doread(vp, blkno, size, 0); /* * If the buffer is in the cache skip any I/O operation. */ if (ISSET((*rbpp)->b_flags, B_CACHE)) goto out; if (size != round_page(size)) goto out; if (VOP_BMAP(vp, blkno + 1, NULL, &sblkno, &maxra)) goto out; maxra++; if (sblkno == -1 || maxra < 2) goto out; howmany = MAXPHYS / size; if (howmany > maxra) howmany = maxra; xbpp = mallocarray(howmany + 1, sizeof(*xbpp), M_TEMP, M_NOWAIT); if (xbpp == NULL) goto out; for (i = howmany - 1; i >= 0; i--) { size_t sz; /* * First buffer allocates big enough size to cover what * all the other buffers need. */ sz = i == 0 ? howmany * size : 0; xbpp[i] = buf_get(vp, blkno + i + 1, sz); if (xbpp[i] == NULL) { for (++i; i < howmany; i++) { SET(xbpp[i]->b_flags, B_INVAL); brelse(xbpp[i]); } free(xbpp, M_TEMP, (howmany + 1) * sizeof(*xbpp)); goto out; } } bp = xbpp[0]; xbpp[howmany] = NULL; inc = btodb(size); for (i = 1; i < howmany; i++) { bcstats.pendingreads++; bcstats.numreads++; /* * We set B_DMA here because bp above will be B_DMA, * and we are playing buffer slice-n-dice games from * the memory allocated in bp. */ SET(xbpp[i]->b_flags, B_DMA | B_READ | B_ASYNC); xbpp[i]->b_blkno = sblkno + (i * inc); xbpp[i]->b_bufsize = xbpp[i]->b_bcount = size; xbpp[i]->b_data = NULL; xbpp[i]->b_pobj = bp->b_pobj; xbpp[i]->b_poffs = bp->b_poffs + (i * size); } KASSERT(bp->b_lblkno == blkno + 1); KASSERT(bp->b_vp == vp); bp->b_blkno = sblkno; SET(bp->b_flags, B_READ | B_ASYNC | B_CALL); bp->b_saveaddr = (void *)xbpp; bp->b_iodone = bread_cluster_callback; bcstats.pendingreads++; bcstats.numreads++; VOP_STRATEGY(bp->b_vp, bp); curproc->p_ru.ru_inblock++; out: return (biowait(*rbpp)); } /* * Block write. Described in Bach (p.56) */ int bwrite(struct buf *bp) { int rv, async, wasdelayed, s; struct vnode *vp; struct mount *mp; vp = bp->b_vp; if (vp != NULL) mp = vp->v_type == VBLK? vp->v_specmountpoint : vp->v_mount; else mp = NULL; /* * Remember buffer type, to switch on it later. If the write was * synchronous, but the file system was mounted with MNT_ASYNC, * convert it to a delayed write. * XXX note that this relies on delayed tape writes being converted * to async, not sync writes (which is safe, but ugly). */ async = ISSET(bp->b_flags, B_ASYNC); if (!async && mp && ISSET(mp->mnt_flag, MNT_ASYNC)) { /* * Don't convert writes from VND on async filesystems * that already have delayed writes in the upper layer. */ if (!ISSET(bp->b_flags, B_NOCACHE)) { bdwrite(bp); return (0); } } /* * Collect statistics on synchronous and asynchronous writes. * Writes to block devices are charged to their associated * filesystem (if any). */ if (mp != NULL) { if (async) mp->mnt_stat.f_asyncwrites++; else mp->mnt_stat.f_syncwrites++; } bcstats.pendingwrites++; bcstats.numwrites++; wasdelayed = ISSET(bp->b_flags, B_DELWRI); CLR(bp->b_flags, (B_READ | B_DONE | B_ERROR | B_DELWRI)); s = splbio(); /* * If not synchronous, pay for the I/O operation and make * sure the buf is on the correct vnode queue. We have * to do this now, because if we don't, the vnode may not * be properly notified that its I/O has completed. */ if (wasdelayed) { reassignbuf(bp); } else curproc->p_ru.ru_oublock++; /* Initiate disk write. Make sure the appropriate party is charged. */ bp->b_vp->v_numoutput++; buf_flip_dma(bp); SET(bp->b_flags, B_WRITEINPROG); splx(s); VOP_STRATEGY(bp->b_vp, bp); /* * If the queue is above the high water mark, wait till * the number of outstanding write bufs drops below the low * water mark. */ if (bp->b_bq) bufq_wait(bp->b_bq); if (async) return (0); /* * If I/O was synchronous, wait for it to complete. */ rv = biowait(bp); /* Release the buffer. */ brelse(bp); return (rv); } /* * Delayed write. * * The buffer is marked dirty, but is not queued for I/O. * This routine should be used when the buffer is expected * to be modified again soon, typically a small write that * partially fills a buffer. * * NB: magnetic tapes cannot be delayed; they must be * written in the order that the writes are requested. * * Described in Leffler, et al. (pp. 208-213). */ void bdwrite(struct buf *bp) { int s; /* * If the block hasn't been seen before: * (1) Mark it as having been seen, * (2) Charge for the write. * (3) Make sure it's on its vnode's correct block list, * (4) If a buffer is rewritten, move it to end of dirty list */ if (!ISSET(bp->b_flags, B_DELWRI)) { SET(bp->b_flags, B_DELWRI); s = splbio(); buf_flip_dma(bp); reassignbuf(bp); splx(s); curproc->p_ru.ru_oublock++; /* XXX */ } /* The "write" is done, so mark and release the buffer. */ CLR(bp->b_flags, B_NEEDCOMMIT); CLR(bp->b_flags, B_NOCACHE); /* Must cache delayed writes */ SET(bp->b_flags, B_DONE); brelse(bp); } /* * Asynchronous block write; just an asynchronous bwrite(). */ void bawrite(struct buf *bp) { SET(bp->b_flags, B_ASYNC); VOP_BWRITE(bp); } /* * Must be called at splbio() */ void buf_dirty(struct buf *bp) { splassert(IPL_BIO); #ifdef DIAGNOSTIC if (!ISSET(bp->b_flags, B_BUSY)) panic("Trying to dirty buffer on freelist!"); #endif if (ISSET(bp->b_flags, B_DELWRI) == 0) { SET(bp->b_flags, B_DELWRI); buf_flip_dma(bp); reassignbuf(bp); } } /* * Must be called at splbio() */ void buf_undirty(struct buf *bp) { splassert(IPL_BIO); #ifdef DIAGNOSTIC if (!ISSET(bp->b_flags, B_BUSY)) panic("Trying to undirty buffer on freelist!"); #endif if (ISSET(bp->b_flags, B_DELWRI)) { CLR(bp->b_flags, B_DELWRI); reassignbuf(bp); } } /* * Release a buffer on to the free lists. * Described in Bach (p. 46). */ void brelse(struct buf *bp) { int s; s = splbio(); if (bp->b_data != NULL) KASSERT(bp->b_bufsize > 0); /* * Determine which queue the buffer should be on, then put it there. */ /* If it's not cacheable, or an error, mark it invalid. */ if (ISSET(bp->b_flags, (B_NOCACHE|B_ERROR))) SET(bp->b_flags, B_INVAL); /* If it's a write error, also mark the vnode as damaged. */ if (ISSET(bp->b_flags, B_ERROR) && !ISSET(bp->b_flags, B_READ)) { if (bp->b_vp && bp->b_vp->v_type == VREG) SET(bp->b_vp->v_bioflag, VBIOERROR); } if (ISSET(bp->b_flags, B_INVAL)) { /* * If the buffer is invalid, free it now rather than leaving * it in a queue and wasting memory. */ if (ISSET(bp->b_flags, B_DELWRI)) { CLR(bp->b_flags, B_DELWRI); } if (bp->b_vp) { RBT_REMOVE(buf_rb_bufs, &bp->b_vp->v_bufs_tree, bp); brelvp(bp); } bp->b_vp = NULL; /* * Wake up any processes waiting for _this_ buffer to * become free. They are not allowed to grab it * since it will be freed. But the only sleeper is * getblk and it will restart the operation after * sleep. */ if (ISSET(bp->b_flags, B_WANTED)) { CLR(bp->b_flags, B_WANTED); wakeup(bp); } buf_put(bp); } else { /* * It has valid data. Put it on the end of the appropriate * queue, so that it'll stick around for as long as possible. */ bufcache_release(bp); /* Unlock the buffer. */ CLR(bp->b_flags, (B_AGE | B_ASYNC | B_NOCACHE | B_DEFERRED)); buf_release(bp); /* Wake up any processes waiting for _this_ buffer to * become free. */ if (ISSET(bp->b_flags, B_WANTED)) { CLR(bp->b_flags, B_WANTED); wakeup(bp); } if (bcstats.dmapages > targetpages) (void) bufcache_recover_dmapages(0, bcstats.dmapages - targetpages); bufcache_adjust(); } /* Wake up syncer and cleaner processes waiting for buffers. */ if (nobuffers) { nobuffers = 0; wakeup(&nobuffers); } /* Wake up any processes waiting for any buffer to become free. */ if (needbuffer && bcstats.dmapages < targetpages && bcstats.kvaslots_avail > RESERVE_SLOTS) { needbuffer = 0; wakeup(&needbuffer); } splx(s); } /* * Determine if a block is in the cache. Just look on what would be its hash * chain. If it's there, return a pointer to it, unless it's marked invalid. */ static struct buf * incore_locked(struct vnode *vp, daddr_t blkno) { struct buf *bp; struct buf b; splassert(IPL_BIO); /* Search buf lookup tree */ b.b_lblkno = blkno; bp = RBT_FIND(buf_rb_bufs, &vp->v_bufs_tree, &b); if (bp != NULL && ISSET(bp->b_flags, B_INVAL)) bp = NULL; return (bp); } struct buf * incore(struct vnode *vp, daddr_t blkno) { struct buf *bp; int s; s = splbio(); bp = incore_locked(vp, blkno); splx(s); return (bp); } /* * Get a block of requested size that is associated with * a given vnode and block offset. If it is found in the * block cache, mark it as having been found, make it busy * and return it. Otherwise, return an empty block of the * correct size. It is up to the caller to ensure that the * cached blocks be of the correct size. */ struct buf * getblk(struct vnode *vp, daddr_t blkno, int size, int slpflag, uint64_t slptimeo) { struct buf *bp; struct buf b; int s, error; /* * XXX * The following is an inlined version of 'incore()', but with * the 'invalid' test moved to after the 'busy' test. It's * necessary because there are some cases in which the NFS * code sets B_INVAL prior to writing data to the server, but * in which the buffers actually contain valid data. In this * case, we can't allow the system to allocate a new buffer for * the block until the write is finished. */ start: s = splbio(); b.b_lblkno = blkno; bp = RBT_FIND(buf_rb_bufs, &vp->v_bufs_tree, &b); if (bp != NULL) { if (ISSET(bp->b_flags, B_BUSY)) { SET(bp->b_flags, B_WANTED); error = tsleep_nsec(bp, slpflag | (PRIBIO + 1), "getblk", slptimeo); splx(s); if (error) return (NULL); goto start; } if (!ISSET(bp->b_flags, B_INVAL)) { bcstats.cachehits++; SET(bp->b_flags, B_CACHE); bufcache_take(bp); buf_acquire(bp); splx(s); return (bp); } } splx(s); if ((bp = buf_get(vp, blkno, size)) == NULL) goto start; return (bp); } /* * Get an empty, disassociated buffer of given size. */ struct buf * geteblk(size_t size) { struct buf *bp; while ((bp = buf_get(NULL, 0, size)) == NULL) continue; return (bp); } /* * Allocate a buffer. * If vp is given, put it into the buffer cache for that vnode. * If size != 0, allocate memory and call buf_map(). * If there is already a buffer for the given vnode/blkno, return NULL. */ struct buf * buf_get(struct vnode *vp, daddr_t blkno, size_t size) { struct buf *bp; int poolwait = size == 0 ? PR_NOWAIT : PR_WAITOK; int npages; int s; s = splbio(); if (size) { /* * Wake up the cleaner if we have lots of dirty pages, * or if we are getting low on buffer cache kva. */ if (UNCLEAN_PAGES >= hidirtypages || bcstats.kvaslots_avail <= 2 * RESERVE_SLOTS) wakeup(&bd_req); npages = atop(round_page(size)); /* * if our cache has been previously shrunk, * allow it to grow again with use up to * bufhighpages (cachepercent) */ if (bufpages < bufhighpages) bufadjust(bufhighpages); /* * If we would go over the page target with our * new allocation, free enough buffers first * to stay at the target with our new allocation. */ if (bcstats.dmapages + npages > targetpages) { (void) bufcache_recover_dmapages(0, npages); bufcache_adjust(); } /* * If we get here, we tried to free the world down * above, and couldn't get down - Wake the cleaner * and wait for it to push some buffers out. */ if ((bcstats.dmapages + npages > targetpages || bcstats.kvaslots_avail <= RESERVE_SLOTS) && curproc != syncerproc && curproc != cleanerproc) { wakeup(&bd_req); needbuffer++; tsleep_nsec(&needbuffer, PRIBIO, "needbuffer", INFSLP); splx(s); return (NULL); } if (bcstats.dmapages + npages > bufpages) { /* cleaner or syncer */ nobuffers = 1; tsleep_nsec(&nobuffers, PRIBIO, "nobuffers", INFSLP); splx(s); return (NULL); } } bp = pool_get(&bufpool, poolwait|PR_ZERO); if (bp == NULL) { splx(s); return (NULL); } bp->b_freelist.tqe_next = NOLIST; bp->b_dev = NODEV; bp->b_bcount = size; buf_acquire_nomap(bp); if (vp != NULL) { /* * We insert the buffer into the hash with B_BUSY set * while we allocate pages for it. This way any getblk * that happens while we allocate pages will wait for * this buffer instead of starting its own buf_get. * * But first, we check if someone beat us to it. */ if (incore_locked(vp, blkno)) { pool_put(&bufpool, bp); splx(s); return (NULL); } bp->b_blkno = bp->b_lblkno = blkno; bgetvp(vp, bp); if (RBT_INSERT(buf_rb_bufs, &vp->v_bufs_tree, bp)) panic("buf_get: dup lblk vp %p bp %p", vp, bp); } else { bp->b_vnbufs.le_next = NOLIST; SET(bp->b_flags, B_INVAL); bp->b_vp = NULL; } LIST_INSERT_HEAD(&bufhead, bp, b_list); bcstats.numbufs++; if (size) { buf_alloc_pages(bp, round_page(size)); KASSERT(ISSET(bp->b_flags, B_DMA)); buf_map(bp); } SET(bp->b_flags, B_BC); splx(s); return (bp); } /* * Buffer cleaning daemon. */ void buf_daemon(void *arg) { struct buf *bp = NULL; int s, pushed = 0; s = splbio(); for (;;) { if (bp == NULL || (pushed >= 16 && UNCLEAN_PAGES < hidirtypages && bcstats.kvaslots_avail > 2 * RESERVE_SLOTS)){ pushed = 0; /* * Wake up anyone who was waiting for buffers * to be released. */ if (needbuffer) { needbuffer = 0; wakeup(&needbuffer); } tsleep_nsec(&bd_req, PRIBIO - 7, "cleaner", INFSLP); } while ((bp = bufcache_getdirtybuf())) { TRACEPOINT(vfs, cleaner, bp->b_flags, pushed, lodirtypages, hidirtypages); if (UNCLEAN_PAGES < lodirtypages && bcstats.kvaslots_avail > 2 * RESERVE_SLOTS && pushed >= 16) break; bufcache_take(bp); buf_acquire(bp); splx(s); if (ISSET(bp->b_flags, B_INVAL)) { brelse(bp); s = splbio(); continue; } #ifdef DIAGNOSTIC if (!ISSET(bp->b_flags, B_DELWRI)) panic("Clean buffer on dirty queue"); #endif bawrite(bp); pushed++; sched_pause(yield); s = splbio(); } } } /* * Wait for operations on the buffer to complete. * When they do, extract and return the I/O's error value. */ int biowait(struct buf *bp) { int s; KASSERT(!(bp->b_flags & B_ASYNC)); s = splbio(); while (!ISSET(bp->b_flags, B_DONE)) tsleep_nsec(bp, PRIBIO + 1, "biowait", INFSLP); splx(s); /* check for interruption of I/O (e.g. via NFS), then errors. */ if (ISSET(bp->b_flags, B_EINTR)) { CLR(bp->b_flags, B_EINTR); return (EINTR); } if (ISSET(bp->b_flags, B_ERROR)) return (bp->b_error ? bp->b_error : EIO); else return (0); } /* * Mark I/O complete on a buffer. * * If a callback has been requested, e.g. the pageout * daemon, do so. Otherwise, awaken waiting processes. * * [ Leffler, et al., says on p.247: * "This routine wakes up the blocked process, frees the buffer * for an asynchronous write, or, for a request by the pagedaemon * process, invokes a procedure specified in the buffer structure" ] * * In real life, the pagedaemon (or other system processes) wants * to do async stuff to, and doesn't want the buffer brelse()'d. * (for swap pager, that puts swap buffers on the free lists (!!!), * for the vn device, that puts malloc'd buffers on the free lists!) * * Must be called at splbio(). */ void biodone(struct buf *bp) { splassert(IPL_BIO); if (ISSET(bp->b_flags, B_DONE)) panic("biodone already"); SET(bp->b_flags, B_DONE); /* note that it's done */ if (bp->b_bq) bufq_done(bp->b_bq, bp); if (!ISSET(bp->b_flags, B_READ)) { CLR(bp->b_flags, B_WRITEINPROG); vwakeup(bp->b_vp); } if (bcstats.numbufs && (!(ISSET(bp->b_flags, B_RAW) || ISSET(bp->b_flags, B_PHYS)))) { if (!ISSET(bp->b_flags, B_READ)) { bcstats.pendingwrites--; } else bcstats.pendingreads--; } if (ISSET(bp->b_flags, B_CALL)) { /* if necessary, call out */ CLR(bp->b_flags, B_CALL); /* but note callout done */ (*bp->b_iodone)(bp); } else { if (ISSET(bp->b_flags, B_ASYNC)) {/* if async, release it */ brelse(bp); } else { /* or just wakeup the buffer */ CLR(bp->b_flags, B_WANTED); wakeup(bp); } } } #ifdef DDB void bcstats_print(int (*)(const char *, ...) __attribute__((__format__(__kprintf__,1,2)))); /* * bcstats_print: ddb hook to print interesting buffer cache counters */ void bcstats_print( int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2)))) { (*pr)("Current Buffer Cache status:\n"); (*pr)("numbufs %lld busymapped %lld, delwri %lld\n", bcstats.numbufs, bcstats.busymapped, bcstats.delwribufs); (*pr)("kvaslots %lld avail kva slots %lld\n", bcstats.kvaslots, bcstats.kvaslots_avail); (*pr)("bufpages %lld, dmapages %lld, dirtypages %lld\n", bcstats.numbufpages, bcstats.dmapages, bcstats.numdirtypages); (*pr)("pendingreads %lld, pendingwrites %lld\n", bcstats.pendingreads, bcstats.pendingwrites); (*pr)("highflips %lld, highflops %lld, dmaflips %lld\n", bcstats.highflips, bcstats.highflops, bcstats.dmaflips); } #endif void buf_adjcnt(struct buf *bp, long ncount) { KASSERT(ncount <= bp->b_bufsize); bp->b_bcount = ncount; } /* bufcache freelist code below */ /* * Copyright (c) 2014 Ted Unangst <tedu@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * The code below implements a variant of the 2Q buffer cache algorithm by * Johnson and Shasha. * * General Outline * We divide the buffer cache into three working sets: current, previous, * and long term. Each list is itself LRU and buffers get promoted and moved * around between them. A buffer starts its life in the current working set. * As time passes and newer buffers push it out, it will turn into the previous * working set and is subject to recycling. But if it's accessed again from * the previous working set, that's an indication that it's actually in the * long term working set, so we promote it there. The separation of current * and previous working sets prevents us from promoting a buffer that's only * temporarily hot to the long term cache. * * The objective is to provide scan resistance by making the long term * working set ineligible for immediate recycling, even as the current * working set is rapidly turned over. * * Implementation * The code below identifies the current, previous, and long term sets as * hotqueue, coldqueue, and warmqueue. The hot and warm queues are capped at * 1/3 of the total clean pages, after which point they start pushing their * oldest buffers into coldqueue. * A buf always starts out with neither WARM or COLD flags set (implying HOT). * When released, it will be returned to the tail of the hotqueue list. * When the hotqueue gets too large, the oldest hot buf will be moved to the * coldqueue, with the B_COLD flag set. When a cold buf is released, we set * the B_WARM flag and put it onto the warmqueue. Warm bufs are also * directly returned to the end of the warmqueue. As with the hotqueue, when * the warmqueue grows too large, B_WARM bufs are moved onto the coldqueue. * * Note that this design does still support large working sets, greater * than the cap of hotqueue or warmqueue would imply. The coldqueue is still * cached and has no maximum length. The hot and warm queues form a Y feeding * into the coldqueue. Moving bufs between queues is constant time, so this * design decays to one long warm->cold queue. * * In the 2Q paper, hotqueue and coldqueue are A1in and A1out. The warmqueue * is Am. We always cache pages, as opposed to pointers to pages for A1. * * This implementation adds support for multiple 2q caches. * * If we have more than one 2q cache, as bufs fall off the cold queue * for recycling, bufs that have been warm before (which retain the * B_WARM flag in addition to B_COLD) can be put into the hot queue of * a second level 2Q cache. buffers which are only B_COLD are * recycled. Bufs falling off the last cache's cold queue are always * recycled. * */ /* * this function is called when a hot or warm queue may have exceeded its * size limit. it will move a buf to the coldqueue. */ int chillbufs(struct bufcache *cache, struct bufqueue *queue, int64_t *queuepages); void bufcache_init(void) { int i; for (i = 0; i < NUM_CACHES; i++) { TAILQ_INIT(&cleancache[i].hotqueue); TAILQ_INIT(&cleancache[i].coldqueue); TAILQ_INIT(&cleancache[i].warmqueue); } TAILQ_INIT(&dirtyqueue); } /* * if the buffer caches have shrunk, we may need to rebalance our queues. */ void bufcache_adjust(void) { int i; for (i = 0; i < NUM_CACHES; i++) { while (chillbufs(&cleancache[i], &cleancache[i].warmqueue, &cleancache[i].warmbufpages) || chillbufs(&cleancache[i], &cleancache[i].hotqueue, &cleancache[i].hotbufpages)) continue; } } /* * Get a clean buffer from the cache. if "discard" is set do not promote * previously warm buffers as normal, because we are tossing everything * away such as in a hibernation */ struct buf * bufcache_getcleanbuf(int cachenum, int discard) { struct buf *bp = NULL; struct bufcache *cache = &cleancache[cachenum]; struct bufqueue * queue; splassert(IPL_BIO); /* try cold queue */ while ((bp = TAILQ_FIRST(&cache->coldqueue)) || (bp = TAILQ_FIRST(&cache->warmqueue)) || (bp = TAILQ_FIRST(&cache->hotqueue))) { int64_t pages = atop(bp->b_bufsize); struct bufcache *newcache; if (discard || cachenum >= NUM_CACHES - 1) { /* Victim selected, give it up */ return bp; } KASSERT(bp->cache == cachenum); /* * If this buffer was warm before, move it to * the hot queue in the next cache */ if (fliphigh) { /* * If we are in the DMA cache, try to flip the * buffer up high to move it on to the other * caches. if we can't move the buffer to high * memory without sleeping, we give it up and * return it rather than fight for more memory * against non buffer cache competitors. */ SET(bp->b_flags, B_BUSY); if (bp->cache == 0 && buf_flip_high(bp) == -1) { CLR(bp->b_flags, B_BUSY); return bp; } CLR(bp->b_flags, B_BUSY); } /* Move the buffer to the hot queue in the next cache */ if (ISSET(bp->b_flags, B_COLD)) { queue = &cache->coldqueue; } else if (ISSET(bp->b_flags, B_WARM)) { queue = &cache->warmqueue; cache->warmbufpages -= pages; } else { queue = &cache->hotqueue; cache->hotbufpages -= pages; } TAILQ_REMOVE(queue, bp, b_freelist); cache->cachepages -= pages; CLR(bp->b_flags, B_WARM); CLR(bp->b_flags, B_COLD); bp->cache++; newcache= &cleancache[bp->cache]; newcache->cachepages += pages; newcache->hotbufpages += pages; chillbufs(newcache, &newcache->hotqueue, &newcache->hotbufpages); TAILQ_INSERT_TAIL(&newcache->hotqueue, bp, b_freelist); } return bp; } void discard_buffer(struct buf *bp) { splassert(IPL_BIO); bufcache_take(bp); if (bp->b_vp) { RBT_REMOVE(buf_rb_bufs, &bp->b_vp->v_bufs_tree, bp); brelvp(bp); } buf_put(bp); } int64_t bufcache_recover_dmapages(int discard, int64_t howmany) { struct buf *bp = NULL; struct bufcache *cache = &cleancache[DMA_CACHE]; struct bufqueue * queue; int64_t recovered = 0; splassert(IPL_BIO); while ((recovered < howmany) && ((bp = TAILQ_FIRST(&cache->coldqueue)) || (bp = TAILQ_FIRST(&cache->warmqueue)) || (bp = TAILQ_FIRST(&cache->hotqueue)))) { int64_t pages = atop(bp->b_bufsize); struct bufcache *newcache; if (discard || DMA_CACHE >= NUM_CACHES - 1) { discard_buffer(bp); continue; } KASSERT(bp->cache == DMA_CACHE); /* * If this buffer was warm before, move it to * the hot queue in the next cache */ /* * One way or another, the pages for this * buffer are leaving DMA memory */ recovered += pages; if (!fliphigh) { discard_buffer(bp); continue; } /* * If we are in the DMA cache, try to flip the * buffer up high to move it on to the other * caches. if we can't move the buffer to high * memory without sleeping, we give it up * now rather than fight for more memory * against non buffer cache competitors. */ SET(bp->b_flags, B_BUSY); if (bp->cache == 0 && buf_flip_high(bp) == -1) { CLR(bp->b_flags, B_BUSY); discard_buffer(bp); continue; } CLR(bp->b_flags, B_BUSY); /* * Move the buffer to the hot queue in the next cache */ if (ISSET(bp->b_flags, B_COLD)) { queue = &cache->coldqueue; } else if (ISSET(bp->b_flags, B_WARM)) { queue = &cache->warmqueue; cache->warmbufpages -= pages; } else { queue = &cache->hotqueue; cache->hotbufpages -= pages; } TAILQ_REMOVE(queue, bp, b_freelist); cache->cachepages -= pages; CLR(bp->b_flags, B_WARM); CLR(bp->b_flags, B_COLD); bp->cache++; newcache= &cleancache[bp->cache]; newcache->cachepages += pages; newcache->hotbufpages += pages; chillbufs(newcache, &newcache->hotqueue, &newcache->hotbufpages); TAILQ_INSERT_TAIL(&newcache->hotqueue, bp, b_freelist); } return recovered; } struct buf * bufcache_getcleanbuf_range(int start, int end, int discard) { int i, j = start, q = end; struct buf *bp = NULL; /* * XXX in theory we could promote warm buffers into a previous queue * so in the pathological case of where we go through all the caches * without getting a buffer we have to start at the beginning again. */ while (j <= q) { for (i = q; i >= j; i--) if ((bp = bufcache_getcleanbuf(i, discard))) return (bp); j++; } return bp; } struct buf * bufcache_gethighcleanbuf(void) { if (!fliphigh) return NULL; return bufcache_getcleanbuf_range(DMA_CACHE + 1, NUM_CACHES - 1, 0); } struct buf * bufcache_getdmacleanbuf(void) { if (fliphigh) return bufcache_getcleanbuf_range(DMA_CACHE, DMA_CACHE, 0); return bufcache_getcleanbuf_range(DMA_CACHE, NUM_CACHES - 1, 0); } struct buf * bufcache_getdirtybuf(void) { return TAILQ_FIRST(&dirtyqueue); } void bufcache_take(struct buf *bp) { struct bufqueue *queue; int64_t pages; splassert(IPL_BIO); KASSERT(ISSET(bp->b_flags, B_BC)); KASSERT(bp->cache >= DMA_CACHE); KASSERT((bp->cache < NUM_CACHES)); pages = atop(bp->b_bufsize); TRACEPOINT(vfs, bufcache_take, bp->b_flags, bp->cache, pages); struct bufcache *cache = &cleancache[bp->cache]; if (!ISSET(bp->b_flags, B_DELWRI)) { if (ISSET(bp->b_flags, B_COLD)) { queue = &cache->coldqueue; } else if (ISSET(bp->b_flags, B_WARM)) { queue = &cache->warmqueue; cache->warmbufpages -= pages; } else { queue = &cache->hotqueue; cache->hotbufpages -= pages; } bcstats.numcleanpages -= pages; cache->cachepages -= pages; } else { queue = &dirtyqueue; bcstats.numdirtypages -= pages; bcstats.delwribufs--; } TAILQ_REMOVE(queue, bp, b_freelist); } /* move buffers from a hot or warm queue to a cold queue in a cache */ int chillbufs(struct bufcache *cache, struct bufqueue *queue, int64_t *queuepages) { struct buf *bp; int64_t limit, pages; /* * We limit the hot queue to be small, with a max of 4096 pages. * We limit the warm queue to half the cache size. * * We impose a minimum size of 96 to prevent too much "wobbling". */ if (queue == &cache->hotqueue) limit = min(cache->cachepages / 20, 4096); else if (queue == &cache->warmqueue) limit = (cache->cachepages / 2); else panic("chillbufs: invalid queue"); if (*queuepages > 96 && *queuepages > limit) { bp = TAILQ_FIRST(queue); if (!bp) panic("inconsistent bufpage counts"); pages = atop(bp->b_bufsize); *queuepages -= pages; TAILQ_REMOVE(queue, bp, b_freelist); /* we do not clear B_WARM */ SET(bp->b_flags, B_COLD); TAILQ_INSERT_TAIL(&cache->coldqueue, bp, b_freelist); return 1; } return 0; } void bufcache_release(struct buf *bp) { struct bufqueue *queue; int64_t pages; struct bufcache *cache = &cleancache[bp->cache]; KASSERT(ISSET(bp->b_flags, B_BC)); pages = atop(bp->b_bufsize); TRACEPOINT(vfs, bufcache_rel, bp->b_flags, bp->cache, pages); if (fliphigh) { if (ISSET(bp->b_flags, B_DMA) && bp->cache > 0) panic("B_DMA buffer release from cache %d", bp->cache); else if ((!ISSET(bp->b_flags, B_DMA)) && bp->cache == 0) panic("Non B_DMA buffer release from cache %d", bp->cache); } if (!ISSET(bp->b_flags, B_DELWRI)) { int64_t *queuepages; if (ISSET(bp->b_flags, B_WARM | B_COLD)) { SET(bp->b_flags, B_WARM); CLR(bp->b_flags, B_COLD); queue = &cache->warmqueue; queuepages = &cache->warmbufpages; } else { queue = &cache->hotqueue; queuepages = &cache->hotbufpages; } *queuepages += pages; bcstats.numcleanpages += pages; cache->cachepages += pages; chillbufs(cache, queue, queuepages); } else { queue = &dirtyqueue; bcstats.numdirtypages += pages; bcstats.delwribufs++; } TAILQ_INSERT_TAIL(queue, bp, b_freelist); } #ifdef HIBERNATE /* * Nuke the buffer cache from orbit when hibernating. We do not want to save * any clean cache pages to swap and read them back. the original disk files * are just as good. */ void hibernate_suspend_bufcache(void) { struct buf *bp; int s; s = splbio(); /* Chuck away all the cache pages.. discard bufs, do not promote */ while ((bp = bufcache_getcleanbuf_range(DMA_CACHE, NUM_CACHES - 1, 1))) { bufcache_take(bp); if (bp->b_vp) { RBT_REMOVE(buf_rb_bufs, &bp->b_vp->v_bufs_tree, bp); brelvp(bp); } buf_put(bp); } splx(s); } void hibernate_resume_bufcache(void) { /* XXX Nothing needed here for now */ } #endif /* HIBERNATE */
5 5 4 4 3 3 1 1 1 1 3 4 8 8 4 1 2 2 2 1 3 1 2 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 /* $OpenBSD: pipex.c,v 1.153 2024/01/23 17:57:21 mvs Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <sys/sysctl.h> #include <sys/syslog.h> #include <sys/conf.h> #include <sys/time.h> #include <sys/timeout.h> #include <sys/kernel.h> #include <sys/pool.h> #include <sys/percpu.h> #include <sys/mutex.h> #include <net/if.h> #include <net/if_types.h> #include <netinet/in.h> #include <netinet/if_ether.h> #include <net/if_dl.h> #include <net/radix.h> #include <net/route.h> #include <net/ppp_defs.h> #include <net/ppp-comp.h> #include <net/netisr.h> #include "pf.h" #if NPF > 0 #include <net/pfvar.h> #endif #include "bpfilter.h" #if NBPFILTER > 0 #include <net/bpf.h> #endif #include <netinet/ip.h> #include <netinet/ip_var.h> #ifdef INET6 #include <netinet/ip6.h> #include <netinet6/ip6_var.h> #endif #include <netinet/tcp.h> #include <netinet/udp.h> #include <netinet/udp_var.h> #include <crypto/arc4.h> #include <net/pipex.h> #include "pipex_local.h" struct mutex pipex_list_mtx = MUTEX_INITIALIZER(IPL_SOFTNET); struct pool pipex_session_pool; struct pool mppe_key_pool; /* * Global data * Locks used to protect global data * A atomic operation * I immutable after creation * L pipex_list_mtx */ int pipex_enable = 0; /* [A] */ struct pipex_hash_head pipex_session_list, /* [L] master session list */ pipex_close_wait_list, /* [L] expired session list */ pipex_peer_addr_hashtable[PIPEX_HASH_SIZE], /* [L] peer's address hash */ pipex_id_hashtable[PIPEX_HASH_SIZE]; /* [L] peer id hash */ struct radix_node_head *pipex_rd_head4 = NULL; /* [L] */ struct timeout pipex_timer_ch; /* callout timer context */ int pipex_prune = 1; /* [I] walk list every seconds */ struct mbuf_queue pipexoutq = MBUF_QUEUE_INITIALIZER( IFQ_MAXLEN, IPL_SOFTNET); /* borrow an mbuf pkthdr field */ #define ph_ppp_proto ether_vtag #ifdef PIPEX_DEBUG int pipex_debug = 0; /* [A] systcl net.inet.ip.pipex_debug */ #endif /* PPP compression == MPPE is assumed, so don't answer CCP Reset-Request. */ #define PIPEX_NO_CCP_RESETACK 1 /************************************************************************ * Core functions ************************************************************************/ void pipex_init(void) { int i; static int pipex_init_done = 0; if (pipex_init_done++) return; rn_init(sizeof(struct sockaddr_in6)); pool_init(&pipex_session_pool, sizeof(struct pipex_session), 0, IPL_SOFTNET, PR_WAITOK, "ppxss", NULL); pool_init(&mppe_key_pool, PIPEX_MPPE_KEYLEN * PIPEX_MPPE_NOLDKEY, 0, IPL_SOFTNET, PR_WAITOK, "mppekey", NULL); LIST_INIT(&pipex_session_list); LIST_INIT(&pipex_close_wait_list); for (i = 0; i < nitems(pipex_id_hashtable); i++) LIST_INIT(&pipex_id_hashtable[i]); for (i = 0; i < nitems(pipex_peer_addr_hashtable); i++) LIST_INIT(&pipex_peer_addr_hashtable[i]); } void pipex_destroy_all_sessions(void *ownersc) { struct pipex_session *session, *session_tmp; mtx_enter(&pipex_list_mtx); LIST_FOREACH_SAFE(session, &pipex_session_list, session_list, session_tmp) { if (session->flags & PIPEX_SFLAGS_ITERATOR) continue; if (session->ownersc == ownersc) { KASSERT((session->flags & PIPEX_SFLAGS_PPPX) == 0); pipex_unlink_session_locked(session); pipex_rele_session(session); } } mtx_leave(&pipex_list_mtx); } int pipex_ioctl(void *ownersc, u_long cmd, caddr_t data) { int ret = 0; switch (cmd) { case PIPEXGSTAT: ret = pipex_get_stat((struct pipex_session_stat_req *)data, ownersc); break; case PIPEXGCLOSED: ret = pipex_get_closed((struct pipex_session_list_req *)data, ownersc); break; default: ret = ENOTTY; break; } return (ret); } /************************************************************************ * Software Interrupt Handler ************************************************************************/ void pipexintr(void) { struct mbuf_list ml; struct mbuf *m; struct pipex_session *session; NET_ASSERT_LOCKED(); mq_delist(&pipexoutq, &ml); while ((m = ml_dequeue(&ml)) != NULL) { struct ifnet *ifp; session = m->m_pkthdr.ph_cookie; ifp = if_get(session->proto.pppoe.over_ifidx); if (ifp != NULL) { struct pipex_pppoe_header *pppoe; int len; pppoe = mtod(m, struct pipex_pppoe_header *); len = ntohs(pppoe->length); ifp->if_output(ifp, m, &session->peer.sa, NULL); counters_pkt(session->stat_counters, pxc_opackets, pxc_obytes, len); } else { m_freem(m); counters_inc(session->stat_counters, pxc_oerrors); } if_put(ifp); pipex_rele_session(session); } } /************************************************************************ * Session management functions ************************************************************************/ int pipex_init_session(struct pipex_session **rsession, struct pipex_session_req *req) { struct pipex_session *session; #ifdef PIPEX_PPPOE struct ifnet *over_ifp = NULL; #endif /* Checks requested parameters. */ switch (req->pr_protocol) { #ifdef PIPEX_PPPOE case PIPEX_PROTO_PPPOE: if (req->pr_peer_address.ss_family != AF_UNSPEC) return (EINVAL); break; #endif #if defined(PIPEX_L2TP) || defined(PIPEX_PPTP) case PIPEX_PROTO_PPTP: case PIPEX_PROTO_L2TP: switch (req->pr_peer_address.ss_family) { case AF_INET: if (req->pr_peer_address.ss_len != sizeof(struct sockaddr_in)) return (EINVAL); break; #ifdef INET6 case AF_INET6: if (req->pr_peer_address.ss_len != sizeof(struct sockaddr_in6)) return (EINVAL); break; #endif default: return (EPROTONOSUPPORT); } if (req->pr_peer_address.ss_family != req->pr_local_address.ss_family || req->pr_peer_address.ss_len != req->pr_local_address.ss_len) return (EINVAL); break; #endif /* defined(PIPEX_PPTP) || defined(PIPEX_L2TP) */ default: return (EPROTONOSUPPORT); } #ifdef PIPEX_MPPE if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ACCEPTED) != 0) { switch (req->pr_mppe_recv.keylenbits) { case 40: case 56: case 128: break; default: return (EINVAL); } } if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ENABLED) != 0) { switch (req->pr_mppe_send.keylenbits) { case 40: case 56: case 128: break; default: return (EINVAL); } } if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_REQUIRED) != 0) { if ((req->pr_ppp_flags & (PIPEX_PPP_MPPE_ACCEPTED | PIPEX_PPP_MPPE_ENABLED)) != (PIPEX_PPP_MPPE_ACCEPTED | PIPEX_PPP_MPPE_ENABLED)) return (EINVAL); } #endif #ifdef PIPEX_PPPOE if (req->pr_protocol == PIPEX_PROTO_PPPOE) { over_ifp = if_unit(req->pr_proto.pppoe.over_ifname); if (over_ifp == NULL) return (EINVAL); } #endif /* prepare a new session */ session = pool_get(&pipex_session_pool, PR_WAITOK | PR_ZERO); refcnt_init(&session->pxs_refcnt); mtx_init(&session->pxs_mtx, IPL_SOFTNET); session->state = PIPEX_STATE_INITIAL; session->protocol = req->pr_protocol; session->session_id = req->pr_session_id; session->peer_session_id = req->pr_peer_session_id; session->peer_mru = req->pr_peer_mru; session->timeout_sec = req->pr_timeout_sec; session->ppp_flags = req->pr_ppp_flags; session->ppp_id = req->pr_ppp_id; session->stat_counters = counters_alloc(pxc_ncounters); session->ip_address.sin_family = AF_INET; session->ip_address.sin_len = sizeof(struct sockaddr_in); session->ip_address.sin_addr = req->pr_ip_address; session->ip_netmask.sin_family = AF_INET; session->ip_netmask.sin_len = sizeof(struct sockaddr_in); session->ip_netmask.sin_addr = req->pr_ip_netmask; if (session->ip_netmask.sin_addr.s_addr == 0L) session->ip_netmask.sin_addr.s_addr = 0xffffffffL; session->ip_address.sin_addr.s_addr &= session->ip_netmask.sin_addr.s_addr; if (req->pr_peer_address.ss_len > 0) memcpy(&session->peer, &req->pr_peer_address, MIN(req->pr_peer_address.ss_len, sizeof(session->peer))); if (req->pr_local_address.ss_len > 0) memcpy(&session->local, &req->pr_local_address, MIN(req->pr_local_address.ss_len, sizeof(session->local))); #ifdef PIPEX_PPPOE if (req->pr_protocol == PIPEX_PROTO_PPPOE) { session->proto.pppoe.over_ifidx = over_ifp->if_index; if_put(over_ifp); } #endif #ifdef PIPEX_PPTP if (req->pr_protocol == PIPEX_PROTO_PPTP) { struct pipex_pptp_session *sess_pptp = &session->proto.pptp; sess_pptp->snd_gap = 0; sess_pptp->rcv_gap = 0; sess_pptp->snd_una = req->pr_proto.pptp.snd_una; sess_pptp->snd_nxt = req->pr_proto.pptp.snd_nxt; sess_pptp->rcv_nxt = req->pr_proto.pptp.rcv_nxt; sess_pptp->rcv_acked = req->pr_proto.pptp.rcv_acked; sess_pptp->winsz = req->pr_proto.pptp.winsz; sess_pptp->maxwinsz = req->pr_proto.pptp.maxwinsz; sess_pptp->peer_maxwinsz = req->pr_proto.pptp.peer_maxwinsz; /* last ack number */ sess_pptp->ul_snd_una = sess_pptp->snd_una - 1; } #endif #ifdef PIPEX_L2TP if (req->pr_protocol == PIPEX_PROTO_L2TP) { struct pipex_l2tp_session *sess_l2tp = &session->proto.l2tp; /* session keys */ sess_l2tp->tunnel_id = req->pr_proto.l2tp.tunnel_id; sess_l2tp->peer_tunnel_id = req->pr_proto.l2tp.peer_tunnel_id; /* protocol options */ sess_l2tp->option_flags = req->pr_proto.l2tp.option_flags; /* initial state of dynamic context */ sess_l2tp->ns_gap = sess_l2tp->nr_gap = 0; sess_l2tp->ns_nxt = req->pr_proto.l2tp.ns_nxt; sess_l2tp->nr_nxt = req->pr_proto.l2tp.nr_nxt; sess_l2tp->ns_una = req->pr_proto.l2tp.ns_una; sess_l2tp->nr_acked = req->pr_proto.l2tp.nr_acked; /* last ack number */ sess_l2tp->ul_ns_una = sess_l2tp->ns_una - 1; sess_l2tp->ipsecflowinfo = req->pr_proto.l2tp.ipsecflowinfo; } #endif #ifdef PIPEX_MPPE if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ACCEPTED) != 0) { pipex_session_init_mppe_recv(session, req->pr_mppe_recv.stateless, req->pr_mppe_recv.keylenbits, req->pr_mppe_recv.master_key); } if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ENABLED) != 0) { pipex_session_init_mppe_send(session, req->pr_mppe_send.stateless, req->pr_mppe_send.keylenbits, req->pr_mppe_send.master_key); } #endif *rsession = session; return 0; } void pipex_rele_session(struct pipex_session *session) { if (refcnt_rele(&session->pxs_refcnt) == 0) return; if (session->mppe_recv.old_session_keys) pool_put(&mppe_key_pool, session->mppe_recv.old_session_keys); counters_free(session->stat_counters, pxc_ncounters); pool_put(&pipex_session_pool, session); } int pipex_link_session(struct pipex_session *session, struct ifnet *ifp, void *ownersc) { struct pipex_hash_head *chain; struct radix_node *rn; int error = 0; mtx_enter(&pipex_list_mtx); if (pipex_rd_head4 == NULL) { if (!rn_inithead((void **)&pipex_rd_head4, offsetof(struct sockaddr_in, sin_addr))) panic("rn_inithead() failed on pipex_link_session()"); } if (pipex_lookup_by_session_id_locked(session->protocol, session->session_id)) { error = EEXIST; goto out; } session->ownersc = ownersc; session->ifindex = ifp->if_index; if (ifp->if_flags & IFF_POINTOPOINT) session->flags |= PIPEX_SFLAGS_PPPX; if ((session->flags & PIPEX_SFLAGS_PPPX) == 0 && !in_nullhost(session->ip_address.sin_addr)) { if (pipex_lookup_by_ip_address_locked( session->ip_address.sin_addr) != NULL) { error = EADDRINUSE; goto out; } rn = rn_addroute(&session->ip_address, &session->ip_netmask, pipex_rd_head4, session->ps4_rn, RTP_STATIC); if (rn == NULL) { error = ENOMEM; goto out; } } LIST_INSERT_HEAD(&pipex_session_list, session, session_list); chain = PIPEX_ID_HASHTABLE(session->session_id); LIST_INSERT_HEAD(chain, session, id_chain); #if defined(PIPEX_PPTP) || defined(PIPEX_L2TP) switch (session->protocol) { case PIPEX_PROTO_PPTP: case PIPEX_PROTO_L2TP: chain = PIPEX_PEER_ADDR_HASHTABLE( pipex_sockaddr_hash_key(&session->peer.sa)); LIST_INSERT_HEAD(chain, session, peer_addr_chain); } #endif /* if first session is added, start timer */ if (LIST_NEXT(session, session_list) == NULL) pipex_timer_start(); session->state = PIPEX_STATE_OPENED; out: mtx_leave(&pipex_list_mtx); return error; } void pipex_unlink_session_locked(struct pipex_session *session) { struct radix_node *rn; MUTEX_ASSERT_LOCKED(&pipex_list_mtx); session->ifindex = 0; if (session->state == PIPEX_STATE_CLOSED) return; if ((session->flags & PIPEX_SFLAGS_PPPX) == 0 && !in_nullhost(session->ip_address.sin_addr)) { KASSERT(pipex_rd_head4 != NULL); rn = rn_delete(&session->ip_address, &session->ip_netmask, pipex_rd_head4, (struct radix_node *)session); KASSERT(rn != NULL); } LIST_REMOVE(session, id_chain); #if defined(PIPEX_PPTP) || defined(PIPEX_L2TP) switch (session->protocol) { case PIPEX_PROTO_PPTP: case PIPEX_PROTO_L2TP: LIST_REMOVE(session, peer_addr_chain); break; } #endif if (session->state == PIPEX_STATE_CLOSE_WAIT) LIST_REMOVE(session, state_list); LIST_REMOVE(session, session_list); session->state = PIPEX_STATE_CLOSED; /* if final session is destroyed, stop timer */ if (LIST_EMPTY(&pipex_session_list)) pipex_timer_stop(); } void pipex_unlink_session(struct pipex_session *session) { mtx_enter(&pipex_list_mtx); pipex_unlink_session_locked(session); mtx_leave(&pipex_list_mtx); } int pipex_notify_close_session(struct pipex_session *session) { MUTEX_ASSERT_LOCKED(&pipex_list_mtx); session->state = PIPEX_STATE_CLOSE_WAIT; session->idle_time = 0; LIST_INSERT_HEAD(&pipex_close_wait_list, session, state_list); return (0); } void pipex_export_session_stats(struct pipex_session *session, struct pipex_statistics *stats) { uint64_t counters[pxc_ncounters]; memset(stats, 0, sizeof(*stats)); counters_read(session->stat_counters, counters, pxc_ncounters, NULL); stats->ipackets = counters[pxc_ipackets]; stats->ierrors = counters[pxc_ierrors]; stats->ibytes = counters[pxc_ibytes]; stats->opackets = counters[pxc_opackets]; stats->oerrors = counters[pxc_oerrors]; stats->obytes = counters[pxc_obytes]; stats->idle_time = session->idle_time; } int pipex_get_stat(struct pipex_session_stat_req *req, void *ownersc) { struct pipex_session *session; int error = 0; session = pipex_lookup_by_session_id(req->psr_protocol, req->psr_session_id); if (session == NULL) return (EINVAL); if (session->ownersc == ownersc) pipex_export_session_stats(session, &req->psr_stat); else error = EINVAL; pipex_rele_session(session); return error; } int pipex_get_closed(struct pipex_session_list_req *req, void *ownersc) { struct pipex_session *session, *session_tmp; bzero(req, sizeof(*req)); mtx_enter(&pipex_list_mtx); LIST_FOREACH_SAFE(session, &pipex_close_wait_list, state_list, session_tmp) { if (session->flags & PIPEX_SFLAGS_ITERATOR) continue; if (session->ownersc != ownersc) continue; req->plr_ppp_id[req->plr_ppp_id_count++] = session->ppp_id; LIST_REMOVE(session, state_list); session->state = PIPEX_STATE_CLOSE_WAIT2; if (req->plr_ppp_id_count >= PIPEX_MAX_LISTREQ) { if (!LIST_EMPTY(&pipex_close_wait_list)) req->plr_flags |= PIPEX_LISTREQ_MORE; break; } } mtx_leave(&pipex_list_mtx); return (0); } struct pipex_session * pipex_lookup_by_ip_address_locked(struct in_addr addr) { struct pipex_session *session; struct sockaddr_in pipex_in4, pipex_in4mask; MUTEX_ASSERT_LOCKED(&pipex_list_mtx); if (pipex_rd_head4 == NULL) return (NULL); bzero(&pipex_in4, sizeof(pipex_in4)); pipex_in4.sin_addr = addr; pipex_in4.sin_family = AF_INET; pipex_in4.sin_len = sizeof(pipex_in4); bzero(&pipex_in4mask, sizeof(pipex_in4mask)); pipex_in4mask.sin_addr.s_addr = htonl(0xFFFFFFFFL); pipex_in4mask.sin_family = AF_INET; pipex_in4mask.sin_len = sizeof(pipex_in4mask); session = (struct pipex_session *)rn_lookup(&pipex_in4, &pipex_in4mask, pipex_rd_head4); #ifdef PIPEX_DEBUG if (session == NULL) { char buf[INET_ADDRSTRLEN]; PIPEX_DBG((NULL, LOG_DEBUG, "<%s> session not found (addr=%s)", __func__, inet_ntop(AF_INET, &addr, buf, sizeof(buf)))); } #endif return (session); } struct pipex_session * pipex_lookup_by_ip_address(struct in_addr addr) { struct pipex_session *session; mtx_enter(&pipex_list_mtx); session = pipex_lookup_by_ip_address_locked(addr); if (session != NULL) refcnt_take(&session->pxs_refcnt); mtx_leave(&pipex_list_mtx); return (session); } struct pipex_session * pipex_lookup_by_session_id_locked(int protocol, int session_id) { struct pipex_hash_head *list; struct pipex_session *session; MUTEX_ASSERT_LOCKED(&pipex_list_mtx); list = PIPEX_ID_HASHTABLE(session_id); LIST_FOREACH(session, list, id_chain) { if (session->protocol == protocol && session->session_id == session_id) break; } #ifdef PIPEX_DEBUG if (session == NULL) PIPEX_DBG((NULL, LOG_DEBUG, "<%s> session not found (session_id=%d)", __func__, session_id)); #endif return (session); } struct pipex_session * pipex_lookup_by_session_id(int protocol, int session_id) { struct pipex_session *session; mtx_enter(&pipex_list_mtx); session = pipex_lookup_by_session_id_locked(protocol, session_id); if (session != NULL) refcnt_take(&session->pxs_refcnt); mtx_leave(&pipex_list_mtx); return (session); } /*********************************************************************** * Timer functions ***********************************************************************/ void pipex_timer_start(void) { timeout_set_flags(&pipex_timer_ch, pipex_timer, NULL, KCLOCK_NONE, TIMEOUT_PROC | TIMEOUT_MPSAFE); timeout_add_sec(&pipex_timer_ch, pipex_prune); } void pipex_timer_stop(void) { timeout_del(&pipex_timer_ch); } void pipex_timer(void *ignored_arg) { struct pipex_session *session, *session_tmp; mtx_enter(&pipex_list_mtx); /* walk through */ LIST_FOREACH_SAFE(session, &pipex_session_list, session_list, session_tmp) { if (session->flags & PIPEX_SFLAGS_ITERATOR) continue; switch (session->state) { case PIPEX_STATE_OPENED: if (session->timeout_sec == 0) continue; session->idle_time++; if (session->idle_time < session->timeout_sec) continue; pipex_notify_close_session(session); break; case PIPEX_STATE_CLOSE_WAIT: case PIPEX_STATE_CLOSE_WAIT2: /* Waiting PIPEXDSESSION from userland */ session->idle_time++; if (session->idle_time < PIPEX_CLOSE_TIMEOUT) continue; /* Release the sessions when timeout */ pipex_unlink_session_locked(session); KASSERTMSG((session->flags & PIPEX_SFLAGS_PPPX) == 0, "FIXME session must not be released when pppx"); pipex_rele_session(session); break; default: break; } } if (LIST_FIRST(&pipex_session_list)) timeout_add_sec(&pipex_timer_ch, pipex_prune); mtx_leave(&pipex_list_mtx); } /*********************************************************************** * Common network I/O functions. (tunnel protocol independent) ***********************************************************************/ struct pipex_session * pipex_iterator(struct pipex_session *session, struct pipex_session_iterator *iter, void *ownersc) { struct pipex_session *session_tmp; mtx_enter(&pipex_list_mtx); if (session) session_tmp = LIST_NEXT(session, session_list); else session_tmp = LIST_FIRST(&pipex_session_list); while (session_tmp) { if (session_tmp->flags & PIPEX_SFLAGS_ITERATOR) goto next; if (session_tmp->ownersc != ownersc) goto next; break; next: session_tmp = LIST_NEXT(session_tmp, session_list); } if (session) LIST_REMOVE(iter, session_list); if (session_tmp) { LIST_INSERT_AFTER(session_tmp, (struct pipex_session *)&iter, session_list); refcnt_take(&session_tmp->pxs_refcnt); } mtx_leave(&pipex_list_mtx); if (session) pipex_rele_session(session); return (session_tmp); } void pipex_ip_output(struct mbuf *m0, struct pipex_session *session) { int is_idle; if ((session->flags & PIPEX_SFLAGS_MULTICAST) == 0) { /* * Multicast packet is a idle packet and it's not TCP. */ /* reset idle timer */ if (session->timeout_sec != 0) { is_idle = 0; m0 = ip_is_idle_packet(m0, &is_idle); if (m0 == NULL) goto dropped; if (is_idle == 0) { mtx_enter(&pipex_list_mtx); /* update expire time */ if (session->state == PIPEX_STATE_OPENED) session->idle_time = 0; mtx_leave(&pipex_list_mtx); } } /* adjust tcpmss */ if ((session->ppp_flags & PIPEX_PPP_ADJUST_TCPMSS) != 0) { m0 = adjust_tcp_mss(m0, session->peer_mru); if (m0 == NULL) goto dropped; } pipex_ppp_output(m0, session, PPP_IP); } else { struct pipex_session_iterator iter = { .flags = PIPEX_SFLAGS_ITERATOR, }; struct pipex_session *session_tmp; struct mbuf *m; m0->m_flags &= ~(M_BCAST|M_MCAST); session_tmp = pipex_iterator(NULL, &iter, session->ownersc); while (session_tmp) { m = m_copym(m0, 0, M_COPYALL, M_NOWAIT); if (m != NULL) pipex_ppp_output(m, session_tmp, PPP_IP); else counters_inc(session_tmp->stat_counters, pxc_oerrors); session_tmp = pipex_iterator(session_tmp, &iter, session->ownersc); } m_freem(m0); } return; dropped: counters_inc(session->stat_counters, pxc_oerrors); } void pipex_ppp_output(struct mbuf *m0, struct pipex_session *session, int proto) { u_char *cp, hdr[16]; #ifdef PIPEX_MPPE if (pipex_session_is_mppe_enabled(session)) { if (proto == PPP_IP) { m0 = pipex_mppe_output(m0, session, PPP_IP); if (m0 == NULL) goto drop; proto = PPP_COMP; } } #endif /* PIPEX_MPPE */ cp = hdr; if (session->protocol != PIPEX_PROTO_PPPOE) { /* PPPoE has not address and control field */ PUTCHAR(PPP_ALLSTATIONS, cp); PUTCHAR(PPP_UI, cp); } PUTSHORT(proto, cp); M_PREPEND(m0, cp - hdr, M_NOWAIT); if (m0 == NULL) goto drop; memcpy(mtod(m0, u_char *), hdr, cp - hdr); switch (session->protocol) { #ifdef PIPEX_PPPOE case PIPEX_PROTO_PPPOE: pipex_pppoe_output(m0, session); break; #endif #ifdef PIPEX_PPTP case PIPEX_PROTO_PPTP: mtx_enter(&session->pxs_mtx); pipex_pptp_output(m0, session, 1, 1); mtx_leave(&session->pxs_mtx); break; #endif #ifdef PIPEX_L2TP case PIPEX_PROTO_L2TP: pipex_l2tp_output(m0, session); break; #endif default: goto drop; } return; drop: m_freem(m0); counters_inc(session->stat_counters, pxc_oerrors); } void pipex_ppp_input(struct mbuf *m0, struct pipex_session *session, int decrypted) { int proto, hlen = 0; struct mbuf *n; #ifdef PIPEX_MPPE again: #endif KASSERT(m0->m_pkthdr.len >= PIPEX_PPPMINLEN); proto = pipex_ppp_proto(m0, session, 0, &hlen); #ifdef PIPEX_MPPE if (proto == PPP_COMP) { if (decrypted) goto drop; /* checked this on ppp_common_input() already. */ KASSERT(pipex_session_is_mppe_accepted(session)); m_adj(m0, hlen); m0 = pipex_mppe_input(m0, session); if (m0 == NULL) goto drop; decrypted = 1; goto again; } if (proto == PPP_CCP) { if (decrypted) goto drop; #if NBPFILTER > 0 { struct ifnet *ifp; if ((ifp = if_get(session->ifindex)) != NULL) { if (ifp->if_bpf && ifp->if_type == IFT_PPP) bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_IN); } if_put(ifp); } #endif m_adj(m0, hlen); pipex_ccp_input(m0, session); return; } #endif m_adj(m0, hlen); if (!ALIGNED_POINTER(mtod(m0, caddr_t), uint32_t)) { n = m_dup_pkt(m0, 0, M_NOWAIT); if (n == NULL) goto drop; m_freem(m0); m0 = n; } switch (proto) { case PPP_IP: if (!decrypted && pipex_session_is_mppe_required(session)) /* * if ip packet received when mppe * is required, discard it. */ goto drop; pipex_ip_input(m0, session); return; #ifdef INET6 case PPP_IPV6: if (!decrypted && pipex_session_is_mppe_required(session)) /* * if ip packet received when mppe * is required, discard it. */ goto drop; pipex_ip6_input(m0, session); return; #endif default: if (decrypted) goto drop; /* protocol must be checked on pipex_common_input() already */ KASSERT(0); goto drop; } return; drop: m_freem(m0); counters_inc(session->stat_counters, pxc_ierrors); } void pipex_ip_input(struct mbuf *m0, struct pipex_session *session) { struct ifnet *ifp; struct ip *ip; int len; int is_idle; /* change recvif */ m0->m_pkthdr.ph_ifidx = session->ifindex; if (ISSET(session->ppp_flags, PIPEX_PPP_INGRESS_FILTER)) { PIPEX_PULLUP(m0, sizeof(struct ip)); if (m0 == NULL) goto drop; /* ingress filter */ ip = mtod(m0, struct ip *); if ((ip->ip_src.s_addr & session->ip_netmask.sin_addr.s_addr) != session->ip_address.sin_addr.s_addr) { char src[INET_ADDRSTRLEN]; pipex_session_log(session, LOG_DEBUG, "ip packet discarded by ingress filter (src %s)", inet_ntop(AF_INET, &ip->ip_src, src, sizeof(src))); goto drop; } } /* idle timer */ if (session->timeout_sec != 0) { is_idle = 0; m0 = ip_is_idle_packet(m0, &is_idle); if (m0 == NULL) goto drop; if (is_idle == 0) { /* update expire time */ mtx_enter(&pipex_list_mtx); if (session->state == PIPEX_STATE_OPENED) session->idle_time = 0; mtx_leave(&pipex_list_mtx); } } /* adjust tcpmss */ if (session->ppp_flags & PIPEX_PPP_ADJUST_TCPMSS) { m0 = adjust_tcp_mss(m0, session->peer_mru); if (m0 == NULL) goto drop; } #if NPF > 0 pf_pkt_addr_changed(m0); #endif len = m0->m_pkthdr.len; if ((ifp = if_get(session->ifindex)) == NULL) goto drop; #if NBPFILTER > 0 if (ifp->if_bpf) bpf_mtap_af(ifp->if_bpf, AF_INET, m0, BPF_DIRECTION_IN); #endif counters_pkt(ifp->if_counters, ifc_ipackets, ifc_ibytes, len); counters_pkt(session->stat_counters, pxc_ipackets, pxc_ibytes, len); ipv4_input(ifp, m0); if_put(ifp); return; drop: m_freem(m0); counters_inc(session->stat_counters, pxc_ierrors); } #ifdef INET6 void pipex_ip6_input(struct mbuf *m0, struct pipex_session *session) { struct ifnet *ifp; int len; /* change recvif */ m0->m_pkthdr.ph_ifidx = session->ifindex; /* * XXX: what is reasonable ingress filter ??? * only one address is enough ?? */ /* XXX: we must define idle packet for IPv6(ICMPv6). */ /* * XXX: tcpmss adjustment for IPv6 is required??? * We may use PMTUD in IPv6.... */ #if NPF > 0 pf_pkt_addr_changed(m0); #endif len = m0->m_pkthdr.len; if ((ifp = if_get(session->ifindex)) == NULL) goto drop; #if NBPFILTER > 0 if (ifp->if_bpf) bpf_mtap_af(ifp->if_bpf, AF_INET6, m0, BPF_DIRECTION_IN); #endif counters_pkt(ifp->if_counters, ifc_ipackets, ifc_ibytes, len); counters_pkt(session->stat_counters, pxc_ipackets, pxc_ibytes, len); ipv6_input(ifp, m0); if_put(ifp); return; drop: m_freem(m0); counters_inc(session->stat_counters, pxc_ierrors); } #endif struct mbuf * pipex_common_input(struct pipex_session *session, struct mbuf *m0, int hlen, int plen, int locked) { int proto, ppphlen; u_char code; if ((m0->m_pkthdr.len < hlen + PIPEX_PPPMINLEN) || (plen < PIPEX_PPPMINLEN)) { if (locked) mtx_leave(&session->pxs_mtx); goto drop; } proto = pipex_ppp_proto(m0, session, hlen, &ppphlen); switch (proto) { #ifdef PIPEX_MPPE case PPP_CCP: code = 0; KASSERT(m0->m_pkthdr.len >= hlen + ppphlen + 1); m_copydata(m0, hlen + ppphlen, 1, &code); if (code != CCP_RESETREQ && code != CCP_RESETACK) goto not_ours; break; case PPP_COMP: if (pipex_session_is_mppe_accepted(session)) break; goto not_ours; #endif case PPP_IP: #ifdef INET6 case PPP_IPV6: #endif break; default: goto not_ours; } if (locked) mtx_leave(&session->pxs_mtx); /* ok, The packet is for PIPEX */ m_adj(m0, hlen);/* cut off the tunnel protocol header */ /* ensure the mbuf length equals the PPP frame length */ if (m0->m_pkthdr.len < plen) goto drop; if (m0->m_pkthdr.len > plen) { if (m0->m_len == m0->m_pkthdr.len) { m0->m_len = plen; m0->m_pkthdr.len = plen; } else m_adj(m0, plen - m0->m_pkthdr.len); } pipex_ppp_input(m0, session, 0); return (NULL); drop: m_freem(m0); counters_inc(session->stat_counters, pxc_ierrors); return (NULL); not_ours: return (m0); /* Not to be handled by PIPEX */ } /* * pipex_ppp_proto */ int pipex_ppp_proto(struct mbuf *m0, struct pipex_session *session, int off, int *hlenp) { int proto; u_char *cp, pktbuf[4]; KASSERT(m0->m_pkthdr.len > sizeof(pktbuf)); m_copydata(m0, off, sizeof(pktbuf), pktbuf); cp = pktbuf; if (pipex_session_has_acf(session)) { if (cp[0] == PPP_ALLSTATIONS && cp[1] == PPP_UI) cp += 2; #ifdef PIPEX_DEBUG else if (!pipex_session_is_acfc_accepted(session)) PIPEX_DBG((session, LOG_DEBUG, "no acf but acfc is not accepted by the peer.")); #endif } if ((*cp & 0x01) != 0) { if (!pipex_session_is_pfc_accepted(session)) { PIPEX_DBG((session, LOG_DEBUG, "Received a broken ppp " "frame. No protocol field. %02x-%02x", cp[0], cp[1])); return (-1); } GETCHAR(proto, cp); } else GETSHORT(proto, cp); if (hlenp != NULL) *hlenp = cp - pktbuf; return (proto); } #ifdef PIPEX_PPPOE /*********************************************************************** * PPPoE ***********************************************************************/ static const u_char pipex_pppoe_padding[ETHERMIN]; /* * pipex_pppoe_lookup_session */ struct pipex_session * pipex_pppoe_lookup_session(struct mbuf *m0) { struct pipex_session *session; struct pipex_pppoe_header pppoe; /* short packet */ if (m0->m_pkthdr.len < (sizeof(struct ether_header) + sizeof(pppoe))) return (NULL); m_copydata(m0, sizeof(struct ether_header), sizeof(struct pipex_pppoe_header), &pppoe); pppoe.session_id = ntohs(pppoe.session_id); session = pipex_lookup_by_session_id(PIPEX_PROTO_PPPOE, pppoe.session_id); #ifdef PIPEX_DEBUG if (session == NULL) PIPEX_DBG((NULL, LOG_DEBUG, "<%s> session not found (id=%d)", __func__, pppoe.session_id)); #endif if (session && session->proto.pppoe.over_ifidx != m0->m_pkthdr.ph_ifidx) { pipex_rele_session(session); session = NULL; } return (session); } struct mbuf * pipex_pppoe_input(struct mbuf *m0, struct pipex_session *session) { int hlen; struct pipex_pppoe_header pppoe; /* already checked at pipex_pppoe_lookup_session */ KASSERT(m0->m_pkthdr.len >= (sizeof(struct ether_header) + sizeof(pppoe))); m_copydata(m0, sizeof(struct ether_header), sizeof(struct pipex_pppoe_header), &pppoe); hlen = sizeof(struct ether_header) + sizeof(struct pipex_pppoe_header); m0 = pipex_common_input(session, m0, hlen, ntohs(pppoe.length), 0); if (m0 == NULL) return (NULL); m_freem(m0); counters_inc(session->stat_counters, pxc_ierrors); return (NULL); } /* * pipex_ppope_output */ void pipex_pppoe_output(struct mbuf *m0, struct pipex_session *session) { struct pipex_pppoe_header *pppoe; int len, padlen; /* save length for pppoe header */ len = m0->m_pkthdr.len; /* prepend protocol header */ M_PREPEND(m0, sizeof(struct pipex_pppoe_header), M_NOWAIT); if (m0 == NULL) { PIPEX_DBG((NULL, LOG_ERR, "<%s> cannot prepend header.", __func__)); counters_inc(session->stat_counters, pxc_oerrors); return; } padlen = ETHERMIN - m0->m_pkthdr.len; if (padlen > 0) m_copyback(m0, m0->m_pkthdr.len, padlen, pipex_pppoe_padding, M_NOWAIT); /* setup pppoe header information */ pppoe = mtod(m0, struct pipex_pppoe_header *); pppoe->vertype = PIPEX_PPPOE_VERTYPE; pppoe->code = PIPEX_PPPOE_CODE_SESSION; pppoe->session_id = htons(session->session_id); pppoe->length = htons(len); m0->m_pkthdr.ph_ifidx = session->proto.pppoe.over_ifidx; refcnt_take(&session->pxs_refcnt); m0->m_pkthdr.ph_cookie = session; m0->m_flags &= ~(M_BCAST|M_MCAST); if (mq_enqueue(&pipexoutq, m0) != 0) { counters_inc(session->stat_counters, pxc_oerrors); pipex_rele_session(session); } else schednetisr(NETISR_PIPEX); } #endif /* PIPEX_PPPOE */ #ifdef PIPEX_PPTP /*********************************************************************** * PPTP ***********************************************************************/ void pipex_pptp_output(struct mbuf *m0, struct pipex_session *session, int has_seq, int has_ack) { int len, reqlen; struct pipex_gre_header *gre = NULL; struct ip *ip; u_char *cp; MUTEX_ASSERT_LOCKED(&session->pxs_mtx); reqlen = PIPEX_IPGRE_HDRLEN + (has_seq + has_ack) * 4; len = 0; if (m0 != NULL) { /* save length for gre header */ len = m0->m_pkthdr.len; /* prepend protocol header */ M_PREPEND(m0, reqlen, M_NOWAIT); if (m0 == NULL) goto drop; } else { MGETHDR(m0, M_DONTWAIT, MT_DATA); if (m0 && reqlen > MHLEN) { MCLGET(m0, M_DONTWAIT); if ((m0->m_flags & M_EXT) == 0) { m_freem(m0); m0 = NULL; } } if (m0 == NULL) goto drop; m0->m_pkthdr.len = m0->m_len = reqlen; } /* setup ip header information */ ip = mtod(m0, struct ip *); ip->ip_len = htons(m0->m_pkthdr.len); ip->ip_off = 0; ip->ip_ttl = MAXTTL; ip->ip_p = IPPROTO_GRE; ip->ip_tos = 0; ip->ip_src = session->local.sin4.sin_addr; ip->ip_dst = session->peer.sin4.sin_addr; #if NPF > 0 pf_pkt_addr_changed(m0); #endif /* setup gre(ver1) header information */ gre = PIPEX_SEEK_NEXTHDR(ip, sizeof(struct ip), struct pipex_gre_header *); gre->type = htons(PIPEX_GRE_PROTO_PPP); gre->call_id = htons(session->peer_session_id); gre->flags = PIPEX_GRE_KFLAG | PIPEX_GRE_VER; /* do htons later */ gre->len = htons(len); cp = PIPEX_SEEK_NEXTHDR(gre, sizeof(struct pipex_gre_header),u_char *); if (has_seq) { gre->flags |= PIPEX_GRE_SFLAG; PUTLONG(session->proto.pptp.snd_nxt, cp); session->proto.pptp.snd_nxt++; session->proto.pptp.snd_gap++; } if (has_ack) { gre->flags |= PIPEX_GRE_AFLAG; session->proto.pptp.rcv_acked = session->proto.pptp.rcv_nxt - 1; PUTLONG(session->proto.pptp.rcv_acked, cp); } gre->flags = htons(gre->flags); m0->m_pkthdr.ph_ifidx = session->ifindex; ip_send(m0); if (len > 0) { /* network layer only */ /* countup statistics */ counters_pkt(session->stat_counters, pxc_opackets, pxc_obytes, len); } return; drop: counters_inc(session->stat_counters, pxc_oerrors); } struct pipex_session * pipex_pptp_lookup_session(struct mbuf *m0) { struct pipex_session *session; struct pipex_gre_header gre; struct ip ip; uint16_t flags; uint16_t id; int hlen; if (m0->m_pkthdr.len < PIPEX_IPGRE_HDRLEN) { PIPEX_DBG((NULL, LOG_DEBUG, "<%s> packet length is too short", __func__)); goto not_ours; } /* get ip header info */ m_copydata(m0, 0, sizeof(struct ip), &ip); hlen = ip.ip_hl << 2; /* * m0 has already passed ip_input(), so there is * no necessity for ip packet inspection. */ /* get gre flags */ m_copydata(m0, hlen, sizeof(gre), &gre); flags = ntohs(gre.flags); /* gre version must be '1' */ if ((flags & PIPEX_GRE_VERMASK) != PIPEX_GRE_VER) { PIPEX_DBG((NULL, LOG_DEBUG, "<%s> gre header wrong version.", __func__)); goto not_ours; } /* gre keys must be present */ if ((flags & PIPEX_GRE_KFLAG) == 0) { PIPEX_DBG((NULL, LOG_DEBUG, "<%s> gre header has no keys.", __func__)); goto not_ours; } /* flag check */ if ((flags & PIPEX_GRE_UNUSEDFLAGS) != 0) { PIPEX_DBG((NULL, LOG_DEBUG, "<%s> gre header has unused flags at pptp.", __func__)); goto not_ours; } /* lookup pipex session table */ id = ntohs(gre.call_id); session = pipex_lookup_by_session_id(PIPEX_PROTO_PPTP, id); #ifdef PIPEX_DEBUG if (session == NULL) { PIPEX_DBG((NULL, LOG_DEBUG, "<%s> session not found (id=%d)", __func__, id)); goto not_ours; } #endif return (session); not_ours: return (NULL); } struct mbuf * pipex_pptp_input(struct mbuf *m0, struct pipex_session *session) { int hlen, has_seq, has_ack, nseq; const char *reason = ""; u_char *cp, *seqp = NULL, *ackp = NULL; uint32_t flags, seq = 0, ack = 0; struct ip *ip; struct pipex_gre_header *gre; struct pipex_pptp_session *pptp_session; int rewind = 0; KASSERT(m0->m_pkthdr.len >= PIPEX_IPGRE_HDRLEN); pptp_session = &session->proto.pptp; /* get ip header */ ip = mtod(m0, struct ip *); hlen = ip->ip_hl << 2; /* seek gre header */ gre = PIPEX_SEEK_NEXTHDR(ip, hlen, struct pipex_gre_header *); flags = ntohs(gre->flags); /* pullup for seek sequences in header */ has_seq = (flags & PIPEX_GRE_SFLAG) ? 1 : 0; has_ack = (flags & PIPEX_GRE_AFLAG) ? 1 : 0; hlen = PIPEX_IPGRE_HDRLEN + 4 * (has_seq + has_ack); if (m0->m_len < hlen) { m0 = m_pullup(m0, hlen); if (m0 == NULL) { PIPEX_DBG((session, LOG_DEBUG, "pullup failed.")); goto drop; } } /* check sequence */ cp = PIPEX_SEEK_NEXTHDR(gre, sizeof(struct pipex_gre_header),u_char *); if (has_seq) { seqp = cp; GETLONG(seq, cp); } mtx_enter(&session->pxs_mtx); if (has_ack) { ackp = cp; GETLONG(ack, cp); if (ack + 1 == pptp_session->snd_una) { /* ack has not changed before */ } else if (SEQ32_LT(ack, pptp_session->snd_una)) { /* OoO ack packets should not be dropped. */ rewind = 1; } else if (SEQ32_GT(ack, pptp_session->snd_nxt)) { reason = "ack for unknown sequence"; goto out_seq; } else pptp_session->snd_una = ack + 1; } if (!has_seq) { /* ack only packet */ goto not_ours; } if (SEQ32_LT(seq, pptp_session->rcv_nxt)) { rewind = 1; if (SEQ32_LT(seq, pptp_session->rcv_nxt - PIPEX_REWIND_LIMIT)) { reason = "out of sequence"; goto out_seq; } } else if (SEQ32_GE(seq, pptp_session->rcv_nxt + pptp_session->maxwinsz)) { pipex_session_log(session, LOG_DEBUG, "received packet caused window overflow. seq=%u(%u-%u)" "may lost %d packets.", seq, pptp_session->rcv_nxt, pptp_session->rcv_nxt + pptp_session->maxwinsz, (int)SEQ32_SUB(seq, pptp_session->rcv_nxt)); } seq++; nseq = SEQ32_SUB(seq, pptp_session->rcv_nxt); if (!rewind) { pptp_session->rcv_nxt = seq; if (SEQ32_SUB(seq, pptp_session->rcv_acked) > roundup(pptp_session->winsz, 2) / 2) /* Send ack only packet. */ pipex_pptp_output(NULL, session, 0, 1); } /* * The following pipex_common_input() will release `pxs_mtx' * deep within if the packet will be consumed. In the error * path lock will be held all the time. So increment `rcv_gap' * here, and on the error path back it out, no atomicity will * be lost in all cases. */ if (!rewind) session->proto.pptp.rcv_gap += nseq; m0 = pipex_common_input(session, m0, hlen, ntohs(gre->len), 1); if (m0 == NULL) { /* * pipex_common_input() releases lock if the * packet was consumed. */ return (NULL); } if (rewind) goto out_seq; else { /* The packet is not ours, back out `rcv_gap'. */ session->proto.pptp.rcv_gap -= nseq; } not_ours: seq--; /* revert original seq value */ /* * overwrite sequence numbers to adjust a gap between pipex and * userland. */ if (seqp != NULL) { seq -= pptp_session->rcv_gap; PUTLONG(seq, seqp); } if (ackp != NULL) { if (pptp_session->snd_nxt == pptp_session->snd_una) { ack -= session->proto.pptp.snd_gap; pptp_session->ul_snd_una = ack; } else { /* * There are sending packets they are not acked. * In this situation, (ack - snd_gap) may points * before sending window of userland. So we don't * update the ack number. */ ack = pptp_session->ul_snd_una; } PUTLONG(ack, ackp); } mtx_leave(&session->pxs_mtx); return (m0); out_seq: pipex_session_log(session, LOG_DEBUG, "Received bad data packet: %s: seq=%u(%u-%u) ack=%u(%u-%u)", reason, seq, pptp_session->rcv_nxt, pptp_session->rcv_nxt + pptp_session->maxwinsz, ack, pptp_session->snd_una, pptp_session->snd_nxt); mtx_leave(&session->pxs_mtx); /* FALLTHROUGH */ drop: m_freem(m0); counters_inc(session->stat_counters, pxc_ierrors); return (NULL); } struct pipex_session * pipex_pptp_userland_lookup_session_ipv4(struct mbuf *m0, struct in_addr dst) { struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_addr = dst; return pipex_pptp_userland_lookup_session(m0, sintosa(&sin)); } #ifdef INET6 struct pipex_session * pipex_pptp_userland_lookup_session_ipv6(struct mbuf *m0, struct in6_addr dst) { struct sockaddr_in6 sin6; memset(&sin6, 0, sizeof(sin6)); sin6.sin6_len = sizeof(sin6); sin6.sin6_family = AF_INET6; in6_recoverscope(&sin6, &dst); return pipex_pptp_userland_lookup_session(m0, sin6tosa(&sin6)); } #endif struct pipex_session * pipex_pptp_userland_lookup_session(struct mbuf *m0, struct sockaddr *sa) { struct pipex_gre_header gre; struct pipex_hash_head *list; struct pipex_session *session; uint16_t id, flags; /* pullup */ if (m0->m_pkthdr.len < sizeof(gre)) { PIPEX_DBG((NULL, LOG_DEBUG, "<%s> packet length is too short", __func__)); return (NULL); } /* get flags */ m_copydata(m0, 0, sizeof(struct pipex_gre_header), &gre); flags = ntohs(gre.flags); /* gre version must be '1' */ if ((flags & PIPEX_GRE_VERMASK) != PIPEX_GRE_VER) { PIPEX_DBG((NULL, LOG_DEBUG, "<%s> gre header wrong version.", __func__)); return (NULL); } /* gre keys must be present */ if ((flags & PIPEX_GRE_KFLAG) == 0) { PIPEX_DBG((NULL, LOG_DEBUG, "<%s> gre header has no keys.", __func__)); return (NULL); } /* lookup pipex session table */ id = ntohs(gre.call_id); mtx_enter(&pipex_list_mtx); list = PIPEX_PEER_ADDR_HASHTABLE(pipex_sockaddr_hash_key(sa)); LIST_FOREACH(session, list, peer_addr_chain) { if (pipex_sockaddr_compar_addr(&session->peer.sa, sa) != 0) continue; if (session->peer_session_id == id) break; } if (session != NULL) refcnt_take(&session->pxs_refcnt); mtx_leave(&pipex_list_mtx); #ifdef PIPEX_DEBUG if (session == NULL) { PIPEX_DBG((NULL, LOG_DEBUG, "<%s> session not found (,call_id=%d)", __func__, (int)gre.call_id)); } #endif return (session); } /* * pipex_pptp_userland_output */ struct mbuf * pipex_pptp_userland_output(struct mbuf *m0, struct pipex_session *session) { int len; struct pipex_gre_header *gre, gre0; uint16_t flags; u_char *cp, *cp0; uint32_t val32; len = sizeof(struct pipex_gre_header); m_copydata(m0, 0, len, &gre0); gre = &gre0; flags = ntohs(gre->flags); if ((flags & PIPEX_GRE_SFLAG) != 0) len += 4; if ((flags & PIPEX_GRE_AFLAG) != 0) len += 4; /* check length */ PIPEX_PULLUP(m0, len); if (m0 == NULL) { PIPEX_DBG((session, LOG_DEBUG, "gre header is too short.")); return (NULL); } gre = mtod(m0, struct pipex_gre_header *); cp = PIPEX_SEEK_NEXTHDR(gre, sizeof(struct pipex_gre_header), u_char *); mtx_enter(&session->pxs_mtx); /* * overwrite sequence numbers to adjust a gap between pipex and * userland. */ if ((flags & PIPEX_GRE_SFLAG) != 0) { cp0 = cp; GETLONG(val32, cp); val32 += session->proto.pptp.snd_gap; PUTLONG(val32, cp0); session->proto.pptp.snd_nxt++; } if ((flags & PIPEX_GRE_AFLAG) != 0) { cp0 = cp; GETLONG(val32, cp); val32 += session->proto.pptp.rcv_gap; PUTLONG(val32, cp0); if (SEQ32_GT(val32, session->proto.pptp.rcv_acked)) session->proto.pptp.rcv_acked = val32; } mtx_leave(&session->pxs_mtx); return (m0); } #endif /* PIPEX_PPTP */ #ifdef PIPEX_L2TP /*********************************************************************** * L2TP support ***********************************************************************/ void pipex_l2tp_output(struct mbuf *m0, struct pipex_session *session) { int hlen, plen, datalen; struct pipex_l2tp_header *l2tp = NULL; struct pipex_l2tp_seq_header *seq = NULL; struct udphdr *udp; struct ip *ip; #ifdef INET6 struct ip6_hdr *ip6; #endif struct m_tag *mtag; hlen = sizeof(struct pipex_l2tp_header) + ((pipex_session_is_l2tp_data_sequencing_on(session)) ? sizeof(struct pipex_l2tp_seq_header) : 0) + sizeof(struct udphdr) + #ifdef INET6 ((session->peer.sin6.sin6_family == AF_INET6) ? sizeof(struct ip6_hdr) : sizeof(struct ip)); #else sizeof(struct ip); #endif datalen = 0; if (m0 != NULL) { datalen = m0->m_pkthdr.len; M_PREPEND(m0, hlen, M_NOWAIT); if (m0 == NULL) goto drop; } else { MGETHDR(m0, M_DONTWAIT, MT_DATA); if (m0 == NULL) goto drop; KASSERT(hlen <= MHLEN); m0->m_pkthdr.len = m0->m_len = hlen; } #ifdef INET6 hlen = (session->peer.sin6.sin6_family == AF_INET6) ? sizeof(struct ip6_hdr) : sizeof(struct ip); #else hlen = sizeof(struct ip); #endif plen = datalen + sizeof(struct pipex_l2tp_header) + ((pipex_session_is_l2tp_data_sequencing_on(session)) ? sizeof(struct pipex_l2tp_seq_header) : 0); l2tp = (struct pipex_l2tp_header *) (mtod(m0, caddr_t) + hlen + sizeof(struct udphdr)); l2tp->flagsver = PIPEX_L2TP_VER | PIPEX_L2TP_FLAG_LENGTH; l2tp->length = htons(plen); l2tp->tunnel_id = htons(session->proto.l2tp.peer_tunnel_id); l2tp->session_id = htons(session->peer_session_id); if (pipex_session_is_l2tp_data_sequencing_on(session)) { seq = (struct pipex_l2tp_seq_header *)(l2tp + 1); l2tp->flagsver |= PIPEX_L2TP_FLAG_SEQUENCE; mtx_enter(&session->pxs_mtx); seq->ns = htons(session->proto.l2tp.ns_nxt); session->proto.l2tp.ns_nxt++; session->proto.l2tp.ns_gap++; session->proto.l2tp.nr_acked = session->proto.l2tp.nr_nxt - 1; seq->nr = htons(session->proto.l2tp.nr_acked); mtx_leave(&session->pxs_mtx); } l2tp->flagsver = htons(l2tp->flagsver); plen += sizeof(struct udphdr); udp = (struct udphdr *)(mtod(m0, caddr_t) + hlen); udp->uh_sport = session->local.sin6.sin6_port; udp->uh_dport = session->peer.sin6.sin6_port; udp->uh_ulen = htons(plen); udp->uh_sum = 0; m0->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT; m0->m_pkthdr.ph_ifidx = session->ifindex; #if NPF > 0 pf_pkt_addr_changed(m0); #endif switch (session->peer.sin6.sin6_family) { case AF_INET: ip = mtod(m0, struct ip *); ip->ip_p = IPPROTO_UDP; ip->ip_src = session->local.sin4.sin_addr; ip->ip_dst = session->peer.sin4.sin_addr; ip->ip_len = htons(hlen + plen); ip->ip_ttl = MAXTTL; ip->ip_tos = 0; ip->ip_off = 0; mtx_enter(&session->pxs_mtx); if (session->proto.l2tp.ipsecflowinfo > 0) { if ((mtag = m_tag_get(PACKET_TAG_IPSEC_FLOWINFO, sizeof(u_int32_t), M_NOWAIT)) == NULL) { mtx_leave(&session->pxs_mtx); goto drop; } *(u_int32_t *)(mtag + 1) = session->proto.l2tp.ipsecflowinfo; m_tag_prepend(m0, mtag); } mtx_leave(&session->pxs_mtx); ip_send(m0); break; #ifdef INET6 case AF_INET6: ip6 = mtod(m0, struct ip6_hdr *); ip6->ip6_flow = 0; ip6->ip6_vfc &= ~IPV6_VERSION_MASK; ip6->ip6_vfc |= IPV6_VERSION; ip6->ip6_nxt = IPPROTO_UDP; ip6->ip6_src = session->local.sin6.sin6_addr; in6_embedscope(&ip6->ip6_dst, &session->peer.sin6, NULL, NULL); /* ip6->ip6_plen will be filled in ip6_output. */ ip6_send(m0); break; #endif } udpstat_inc(udps_opackets); if (datalen > 0) { /* network layer only */ /* countup statistics */ counters_pkt(session->stat_counters, pxc_opackets, pxc_obytes, datalen); } return; drop: m_freem(m0); counters_inc(session->stat_counters, pxc_oerrors); } struct pipex_session * pipex_l2tp_lookup_session(struct mbuf *m0, int off) { struct pipex_session *session; uint16_t flags, session_id, ver; u_char *cp, buf[PIPEX_L2TP_MINLEN]; if (m0->m_pkthdr.len < off + PIPEX_L2TP_MINLEN) { PIPEX_DBG((NULL, LOG_DEBUG, "<%s> packet length is too short", __func__)); goto not_ours; } /* get first 16bits of L2TP */ m_copydata(m0, off, sizeof(buf), buf); cp = buf; GETSHORT(flags, cp); ver = flags & PIPEX_L2TP_VER_MASK; /* l2tp version must be '2' */ if (ver != PIPEX_L2TP_VER) { PIPEX_DBG((NULL, LOG_DEBUG, "<%s> l2tp header wrong version %u.", __func__, ver)); goto not_ours; } if ((flags & PIPEX_L2TP_FLAG_TYPE) != 0) goto not_ours; if (flags & PIPEX_L2TP_FLAG_LENGTH) cp += 2; /* skip length field */ cp += 2; /* skip tunnel-id field */ GETSHORT(session_id, cp); /* get session-id field */ /* lookup pipex session table */ session = pipex_lookup_by_session_id(PIPEX_PROTO_L2TP, session_id); #ifdef PIPEX_DEBUG if (session == NULL) { PIPEX_DBG((NULL, LOG_DEBUG, "<%s> session not found (id=%d)", __func__, session_id)); goto not_ours; } #endif return (session); not_ours: return (NULL); } struct mbuf * pipex_l2tp_input(struct mbuf *m0, int off0, struct pipex_session *session, uint32_t ipsecflowinfo) { struct pipex_l2tp_session *l2tp_session; int length = 0, offset = 0, hlen, nseq; u_char *cp, *nsp = NULL, *nrp = NULL; uint16_t flags, ns = 0, nr = 0; int rewind = 0; mtx_enter(&session->pxs_mtx); l2tp_session = &session->proto.l2tp; l2tp_session->ipsecflowinfo = ipsecflowinfo; m_copydata(m0, off0, sizeof(flags), &flags); flags = ntohs(flags) & PIPEX_L2TP_FLAG_MASK; KASSERT((flags & PIPEX_L2TP_FLAG_TYPE) == 0); hlen = 2; /* flags and version fields */ if (flags & PIPEX_L2TP_FLAG_LENGTH) /* length */ hlen += 2; hlen += 4; /* tunnel-id and session-id */ if (flags & PIPEX_L2TP_FLAG_SEQUENCE) /* ns and nr */ hlen += 4; if (flags & PIPEX_L2TP_FLAG_OFFSET) /* offset */ hlen += 2; PIPEX_PULLUP(m0, off0 + hlen); if (m0 == NULL) goto drop; cp = mtod(m0, u_char *) + off0; cp += 2; /* flags and version */ if (flags & PIPEX_L2TP_FLAG_LENGTH) GETSHORT(length, cp); else length = m0->m_pkthdr.len - off0; cp += 4; /* skip tunnel-id and session-id field */ /* pullup for seek sequences in header */ nseq = 0; if (flags & PIPEX_L2TP_FLAG_SEQUENCE) { nsp = cp; GETSHORT(ns, cp); nrp = cp; GETSHORT(nr, cp); nr++; if (SEQ16_GT(nr, l2tp_session->ns_una) && SEQ16_LE(nr, l2tp_session->ns_nxt)) /* update 'ns_una' only if the ns is in valid range */ l2tp_session->ns_una = nr; if (SEQ16_LT(ns, l2tp_session->nr_nxt)) { rewind = 1; if (SEQ16_LT(ns, l2tp_session->nr_nxt - PIPEX_REWIND_LIMIT)) goto out_seq; } ns++; nseq = SEQ16_SUB(ns, l2tp_session->nr_nxt); if (!rewind) l2tp_session->nr_nxt = ns; } if (flags & PIPEX_L2TP_FLAG_OFFSET) GETSHORT(offset, cp); length -= hlen + offset; hlen += off0 + offset; /* * The following pipex_common_input() will release `pxs_mtx' * deep within if the packet will be consumed. In the error * path lock will be held all the time. So increment `nr_gap' * here, and on the error path back it out, no atomicity will * be lost in all cases. */ if (!rewind) session->proto.l2tp.nr_gap += nseq; m0 = pipex_common_input(session, m0, hlen, length, 1); if (m0 == NULL) { /* * pipex_common_input() releases lock if the * packet was consumed. */ return (NULL); } if (rewind) goto out_seq; else { /* The packet is not ours, backout `nr_gap'. */ session->proto.l2tp.nr_gap -= nseq; } /* * overwrite sequence numbers to adjust a gap between pipex and * userland. */ if (flags & PIPEX_L2TP_FLAG_SEQUENCE) { --ns; --nr; /* revert original values */ ns -= l2tp_session->nr_gap; PUTSHORT(ns, nsp); if (l2tp_session->ns_nxt == l2tp_session->ns_una) { nr -= l2tp_session->ns_gap; l2tp_session->ul_ns_una = nr; } else { /* * There are sending packets they are not acked. * In this situation, (ack - snd_gap) may points * before sending window of userland. So we don't * update the ack number. */ nr = l2tp_session->ul_ns_una; } PUTSHORT(nr, nrp); } mtx_leave(&session->pxs_mtx); return (m0); out_seq: pipex_session_log(session, LOG_DEBUG, "Received bad data packet: out of sequence: seq=%u(%u-) " "ack=%u(%u-%u)", ns, l2tp_session->nr_nxt, nr, l2tp_session->ns_una, l2tp_session->ns_nxt); /* FALLTHROUGH */ drop: mtx_leave(&session->pxs_mtx); m_freem(m0); counters_inc(session->stat_counters, pxc_ierrors); return (NULL); } struct pipex_session * pipex_l2tp_userland_lookup_session_ipv4(struct mbuf *m0, struct in_addr dst) { struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_addr = dst; return pipex_l2tp_userland_lookup_session(m0, sintosa(&sin)); } #ifdef INET6 struct pipex_session * pipex_l2tp_userland_lookup_session_ipv6(struct mbuf *m0, struct in6_addr dst) { struct sockaddr_in6 sin6; memset(&sin6, 0, sizeof(sin6)); sin6.sin6_len = sizeof(sin6); sin6.sin6_family = AF_INET6; in6_recoverscope(&sin6, &dst); return pipex_l2tp_userland_lookup_session(m0, sin6tosa(&sin6)); } #endif struct pipex_session * pipex_l2tp_userland_lookup_session(struct mbuf *m0, struct sockaddr *sa) { struct pipex_l2tp_header l2tp; struct pipex_hash_head *list; struct pipex_session *session; uint16_t session_id, tunnel_id, flags; if (sa->sa_family != AF_INET && sa->sa_family != AF_INET6) return (NULL); /* pullup */ if (m0->m_pkthdr.len < sizeof(l2tp)) { PIPEX_DBG((NULL, LOG_DEBUG, "<%s> packet length is too short", __func__)); return (NULL); } /* get flags */ m_copydata(m0, 0, sizeof(l2tp), &l2tp); flags = ntohs(l2tp.flagsver); /* l2tp version must be '2' */ if ((flags & PIPEX_L2TP_VER_MASK) != PIPEX_L2TP_VER) { PIPEX_DBG((NULL, LOG_DEBUG, "<%s> l2tp header wrong version.", __func__)); return (NULL); } /* We need L2TP data messages only */ if ((flags & PIPEX_L2TP_FLAG_TYPE) != 0) return (NULL); /* No need to hook packets that don't have the sequence field */ if ((flags & PIPEX_L2TP_FLAG_SEQUENCE) == 0) return (NULL); session_id = ntohs(l2tp.session_id); tunnel_id = ntohs(l2tp.tunnel_id); mtx_enter(&pipex_list_mtx); list = PIPEX_PEER_ADDR_HASHTABLE(pipex_sockaddr_hash_key(sa)); LIST_FOREACH(session, list, peer_addr_chain) { if (pipex_sockaddr_compar_addr(&session->peer.sa, sa) != 0) continue; if (session->proto.l2tp.peer_tunnel_id != tunnel_id) continue; if (session->peer_session_id == session_id) break; } if (session != NULL) refcnt_take(&session->pxs_refcnt); mtx_leave(&pipex_list_mtx); #ifdef PIPEX_DEBUG if (session == NULL) { PIPEX_DBG((NULL, LOG_DEBUG, "<%s> session not found " "(tunnel_id=%d, session_id=%d)", __func__, tunnel_id, session_id)); } #endif return (session); } struct mbuf * pipex_l2tp_userland_output(struct mbuf *m0, struct pipex_session *session) { struct pipex_l2tp_header *l2tp; struct pipex_l2tp_seq_header *seq; uint16_t ns, nr; /* check length */ PIPEX_PULLUP(m0, sizeof(struct pipex_l2tp_header) + sizeof(struct pipex_l2tp_seq_header)); if (m0 == NULL) return (NULL); l2tp = mtod(m0, struct pipex_l2tp_header *); KASSERT(ntohs(l2tp->flagsver) & PIPEX_L2TP_FLAG_SEQUENCE); /* * overwrite sequence numbers to adjust a gap between pipex and * userland. */ seq = (struct pipex_l2tp_seq_header *)(l2tp + 1); ns = ntohs(seq->ns); nr = ntohs(seq->nr); mtx_enter(&session->pxs_mtx); ns += session->proto.l2tp.ns_gap; seq->ns = htons(ns); session->proto.l2tp.ns_nxt++; nr += session->proto.l2tp.nr_gap; seq->nr = htons(nr); if (SEQ16_GT(nr, session->proto.l2tp.nr_acked)) session->proto.l2tp.nr_acked = nr; mtx_leave(&session->pxs_mtx); return (m0); } #endif /* PIPEX_L2TP */ #ifdef PIPEX_MPPE /********************************************************************** * MPPE ***********************************************************************/ #define PIPEX_COHERENCY_CNT_MASK 0x0fff static inline int pipex_mppe_setkey(struct pipex_mppe *mppe) { rc4_keysetup(&mppe->rc4ctx, mppe->session_key, mppe->keylen); return (0); } static inline int pipex_mppe_setoldkey(struct pipex_mppe *mppe, uint16_t coher_cnt) { KASSERT(mppe->old_session_keys != NULL); rc4_keysetup(&mppe->rc4ctx, mppe->old_session_keys[coher_cnt & PIPEX_MPPE_OLDKEYMASK], mppe->keylen); return (0); } static inline void pipex_mppe_crypt(struct pipex_mppe *mppe, int len, u_char *indata, u_char *outdata) { rc4_crypt(&mppe->rc4ctx, indata, outdata, len); } void pipex_mppe_init(struct pipex_mppe *mppe, int stateless, int keylenbits, u_char *master_key, int has_oldkey) { memset(mppe, 0, sizeof(struct pipex_mppe)); mtx_init(&mppe->pxm_mtx, IPL_SOFTNET); if (stateless) mppe->flags |= PIPEX_MPPE_STATELESS; if (has_oldkey) mppe->old_session_keys = pool_get(&mppe_key_pool, PR_WAITOK); else mppe->old_session_keys = NULL; memcpy(mppe->master_key, master_key, sizeof(mppe->master_key)); mppe->keylenbits = keylenbits; switch (keylenbits) { case 40: case 56: mppe->keylen = 8; break; case 128: mppe->keylen = 16; break; } GetNewKeyFromSHA(mppe->master_key, mppe->master_key, mppe->keylen, mppe->session_key); pipex_mppe_reduce_key(mppe); pipex_mppe_setkey(mppe); } void pipex_session_init_mppe_recv(struct pipex_session *session, int stateless, int keylenbits, u_char *master_key) { pipex_mppe_init(&session->mppe_recv, stateless, keylenbits, master_key, stateless); session->ppp_flags |= PIPEX_PPP_MPPE_ACCEPTED; } void pipex_session_init_mppe_send(struct pipex_session *session, int stateless, int keylenbits, u_char *master_key) { pipex_mppe_init(&session->mppe_send, stateless, keylenbits, master_key, 0); session->ppp_flags |= PIPEX_PPP_MPPE_ENABLED; } #include <crypto/sha1.h> static u_char SHAPad1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, SHAPad2[] = { 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, }; void GetNewKeyFromSHA(u_char *StartKey, u_char *SessionKey, int SessionKeyLength, u_char *InterimKey) { u_char Digest[20]; SHA1_CTX Context; SHA1Init(&Context); SHA1Update(&Context, StartKey, SessionKeyLength); SHA1Update(&Context, SHAPad1, 40); SHA1Update(&Context, SessionKey, SessionKeyLength); SHA1Update(&Context, SHAPad2, 40); SHA1Final(Digest, &Context); memcpy(InterimKey, Digest, SessionKeyLength); } void pipex_mppe_reduce_key(struct pipex_mppe *mppe) { switch (mppe->keylenbits) { case 40: mppe->session_key[0] = 0xd1; mppe->session_key[1] = 0x26; mppe->session_key[2] = 0x9e; break; case 56: mppe->session_key[0] = 0xd1; break; } } void mppe_key_change(struct pipex_mppe *mppe) { u_char interim[16]; struct rc4_ctx keychg; memset(&keychg, 0, sizeof(keychg)); GetNewKeyFromSHA(mppe->master_key, mppe->session_key, mppe->keylen, interim); rc4_keysetup(&keychg, interim, mppe->keylen); rc4_crypt(&keychg, interim, mppe->session_key, mppe->keylen); pipex_mppe_reduce_key(mppe); if (mppe->old_session_keys) { int idx = mppe->coher_cnt & PIPEX_MPPE_OLDKEYMASK; memcpy(mppe->old_session_keys[idx], mppe->session_key, PIPEX_MPPE_KEYLEN); } } struct mbuf * pipex_mppe_input(struct mbuf *m0, struct pipex_session *session) { int pktloss, encrypt, flushed, m, n, len; struct pipex_mppe *mppe; uint16_t coher_cnt; struct mbuf *m1; u_char *cp; int rewind = 0; /* pullup */ PIPEX_PULLUP(m0, sizeof(coher_cnt)); if (m0 == NULL) goto drop; mppe = &session->mppe_recv; /* get header information */ cp = mtod(m0, u_char *); GETSHORT(coher_cnt, cp); flushed = ((coher_cnt & 0x8000) != 0) ? 1 : 0; encrypt = ((coher_cnt & 0x1000) != 0) ? 1 : 0; coher_cnt &= PIPEX_COHERENCY_CNT_MASK; pktloss = 0; mtx_enter(&mppe->pxm_mtx); PIPEX_MPPE_DBG((session, LOG_DEBUG, "in coher_cnt=%03x %s%s", mppe->coher_cnt, (flushed) ? "[flushed]" : "", (encrypt) ? "[encrypt]" : "")); if (encrypt == 0) { mtx_leave(&mppe->pxm_mtx); pipex_session_log(session, LOG_DEBUG, "Received unexpected MPPE packet.(no ecrypt)"); goto drop; } /* adjust mbuf */ m_adj(m0, sizeof(coher_cnt)); /* * L2TP data session may be used without sequencing, PPP frames may * arrive in disorder. The 'coherency counter' of MPPE detects such * situations, but we cannot distinguish between 'disorder' and * 'packet loss' exactly. * * When 'coherency counter' detects lost packets greater than * (4096 - 256), we treat as 'disorder' otherwise treat as * 'packet loss'. */ { int coher_cnt0; coher_cnt0 = coher_cnt; if (coher_cnt < mppe->coher_cnt) coher_cnt0 += 0x1000; if (coher_cnt0 - mppe->coher_cnt > 0x0f00) { if ((mppe->flags & PIPEX_MPPE_STATELESS) == 0 || coher_cnt0 - mppe->coher_cnt <= 0x1000 - PIPEX_MPPE_NOLDKEY) { pipex_session_log(session, LOG_DEBUG, "Workaround the out-of-sequence PPP framing problem: " "%d => %d", mppe->coher_cnt, coher_cnt); mtx_leave(&mppe->pxm_mtx); goto drop; } rewind = 1; } } if ((mppe->flags & PIPEX_MPPE_STATELESS) != 0) { if (!rewind) { mppe_key_change(mppe); while (mppe->coher_cnt != coher_cnt) { mppe->coher_cnt++; mppe->coher_cnt &= PIPEX_COHERENCY_CNT_MASK; mppe_key_change(mppe); pktloss++; } } pipex_mppe_setoldkey(mppe, coher_cnt); } else { if (flushed) { if (coher_cnt < mppe->coher_cnt) { coher_cnt += 0x1000; } pktloss += coher_cnt - mppe->coher_cnt; m = mppe->coher_cnt / 256; n = coher_cnt / 256; while (m++ < n) mppe_key_change(mppe); coher_cnt &= PIPEX_COHERENCY_CNT_MASK; mppe->coher_cnt = coher_cnt; } else if (mppe->coher_cnt != coher_cnt) { int ccp_id; mtx_leave(&mppe->pxm_mtx); /* Send CCP ResetReq */ PIPEX_DBG((session, LOG_DEBUG, "CCP SendResetReq")); mtx_enter(&session->pxs_mtx); ccp_id = session->ccp_id; session->ccp_id++; mtx_leave(&session->pxs_mtx); pipex_ccp_output(session, CCP_RESETREQ, ccp_id); goto drop; } if ((coher_cnt & 0xff) == 0xff) { mppe_key_change(mppe); flushed = 1; } if (flushed) pipex_mppe_setkey(mppe); } if (pktloss > 1000) { pipex_session_log(session, LOG_DEBUG, "%d packets loss.", pktloss); } /* decrypt ppp payload */ for (m1 = m0; m1; m1 = m1->m_next) { cp = mtod(m1, u_char *); len = m1->m_len; pipex_mppe_crypt(mppe, len, cp, cp); } if (!rewind) { /* update coher_cnt */ mppe->coher_cnt++; mppe->coher_cnt &= PIPEX_COHERENCY_CNT_MASK; } mtx_leave(&mppe->pxm_mtx); if (m0->m_pkthdr.len < PIPEX_PPPMINLEN) goto drop; return (m0); drop: m_freem(m0); return (NULL); } struct mbuf * pipex_mppe_output(struct mbuf *m0, struct pipex_session *session, uint16_t protocol) { int encrypt, flushed, len; struct mppe_header { uint16_t coher_cnt; uint16_t protocol; } __packed *hdr; u_char *cp; struct pipex_mppe *mppe; struct mbuf *m; mppe = &session->mppe_send; /* * create a deep-copy if the mbuf has a shared mbuf cluster. * this is required to handle cases of tcp retransmission. */ for (m = m0; m != NULL; m = m->m_next) { if (M_READONLY(m)) { m = m_dup_pkt(m0, max_linkhdr, M_NOWAIT); m_freem(m0); if (m == NULL) return (NULL); m0 = m; break; } } /* prepend mppe header */ M_PREPEND(m0, sizeof(struct mppe_header), M_NOWAIT); if (m0 == NULL) return (NULL); hdr = mtod(m0, struct mppe_header *); hdr->protocol = protocol; /* check coherency counter */ flushed = 0; encrypt = 1; mtx_enter(&mppe->pxm_mtx); if ((mppe->flags & PIPEX_MPPE_STATELESS) != 0) { flushed = 1; mppe_key_change(mppe); } else { if ((mppe->coher_cnt % 0x100) == 0xff) { flushed = 1; mppe_key_change(mppe); } else if ((mppe->flags & PIPEX_MPPE_RESETREQ) != 0) { flushed = 1; mppe->flags &= ~PIPEX_MPPE_RESETREQ; } } if (flushed) pipex_mppe_setkey(mppe); PIPEX_MPPE_DBG((session, LOG_DEBUG, "out coher_cnt=%03x %s%s", mppe->coher_cnt, (flushed) ? "[flushed]" : "", (encrypt) ? "[encrypt]" : "")); /* setup header information */ hdr->coher_cnt = (mppe->coher_cnt++) & PIPEX_COHERENCY_CNT_MASK; hdr->coher_cnt &= PIPEX_COHERENCY_CNT_MASK; if (flushed) hdr->coher_cnt |= 0x8000; if (encrypt) hdr->coher_cnt |= 0x1000; hdr->protocol = htons(hdr->protocol); hdr->coher_cnt = htons(hdr->coher_cnt); /* encrypt chain */ for (m = m0; m; m = m->m_next) { cp = mtod(m, u_char *); len = m->m_len; if (m == m0 && len > offsetof(struct mppe_header, protocol)) { len -= offsetof(struct mppe_header, protocol); cp += offsetof(struct mppe_header, protocol); } pipex_mppe_crypt(mppe, len, cp, cp); } mtx_leave(&mppe->pxm_mtx); return (m0); } void pipex_ccp_input(struct mbuf *m0, struct pipex_session *session) { u_char *cp; int code, id, len; if (m0->m_pkthdr.len < PPP_HDRLEN) goto drop; if ((m0 = m_pullup(m0, PPP_HDRLEN)) == NULL) goto drop; cp = mtod(m0, u_char *); GETCHAR(code, cp); GETCHAR(id, cp); GETSHORT(len, cp); switch (code) { case CCP_RESETREQ: PIPEX_DBG((session, LOG_DEBUG, "CCP RecvResetReq")); mtx_enter(&session->mppe_send.pxm_mtx); session->mppe_send.flags |= PIPEX_MPPE_RESETREQ; mtx_leave(&session->mppe_send.pxm_mtx); #ifndef PIPEX_NO_CCP_RESETACK PIPEX_DBG((session, LOG_DEBUG, "CCP SendResetAck")); pipex_ccp_output(session, CCP_RESETACK, id); #endif /* ignore error */ break; case CCP_RESETACK: PIPEX_DBG((session, LOG_DEBUG, "CCP RecvResetAck")); break; default: PIPEX_DBG((session, LOG_DEBUG, "CCP Recv code=%d", code)); goto drop; } m_freem(m0); return; drop: m_freem(m0); counters_inc(session->stat_counters, pxc_ierrors); } int pipex_ccp_output(struct pipex_session *session, int code, int id) { u_char *cp; struct mbuf *m; MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == NULL) { counters_inc(session->stat_counters, pxc_oerrors); return (1); } m->m_pkthdr.len = m->m_len = 4; cp = mtod(m, u_char *); PUTCHAR(code, cp); PUTCHAR(id, cp); PUTSHORT(4, cp); pipex_ppp_output(m, session, PPP_CCP); return (0); } #endif /*********************************************************************** * Miscellaneous functions ***********************************************************************/ /* adapted from FreeBSD:src/usr.sbin/ppp/tcpmss.c */ /* * Copyright (c) 2000 Ruslan Ermilov and Brian Somers <brian@Awfulhak.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD: src/usr.sbin/ppp/tcpmss.c,v 1.1.4.3 2001/07/19 11:39:54 brian Exp $ */ #define TCP_OPTLEN_IN_SEGMENT 12 /* timestamp option and padding */ #define MAXMSS(mtu) (mtu - sizeof(struct ip) - sizeof(struct tcphdr) - \ TCP_OPTLEN_IN_SEGMENT) /* * The following macro is used to update an internet checksum. "acc" is a * 32-bit accumulation of all the changes to the checksum (adding in old * 16-bit words and subtracting out new words), and "cksum" is the checksum * value to be updated. */ #define ADJUST_CHECKSUM(acc, cksum) { \ acc += cksum; \ if (acc < 0) { \ acc = -acc; \ acc = (acc >> 16) + (acc & 0xffff); \ acc += acc >> 16; \ cksum = (u_short) ~acc; \ } else { \ acc = (acc >> 16) + (acc & 0xffff); \ acc += acc >> 16; \ cksum = (u_short) acc; \ } \ } /* * Rewrite max-segment-size TCP option to avoid PMTU blackhole issues. * The mtu parameter should be the MTU bottleneck (as far as we know) * on the link between the source and the destination. */ struct mbuf * adjust_tcp_mss(struct mbuf *m0, int mtu) { int opt, optlen, acc, mss, maxmss, lpktp; struct ip *pip; struct tcphdr *th; u_char *pktp, *mssp; u_int16_t ip_off; lpktp = sizeof(struct ip) + sizeof(struct tcphdr) + PIPEX_TCP_OPTLEN; lpktp = MIN(lpktp, m0->m_pkthdr.len); PIPEX_PULLUP(m0, lpktp); if (m0 == NULL) goto drop; pktp = mtod(m0, char *); pip = (struct ip *)pktp; ip_off = ntohs(pip->ip_off); /* Non TCP or fragmented packet must not have a MSS option */ if (pip->ip_p != IPPROTO_TCP || (ip_off & IP_MF) != 0 || (ip_off & IP_OFFMASK) != 0) goto handled; pktp += pip->ip_hl << 2; lpktp -= pip->ip_hl << 2; /* packet is broken */ if (sizeof(struct tcphdr) > lpktp) goto drop; th = (struct tcphdr *)pktp; /* * As RFC 973, a MSS field must only be sent in the initial * connection request(it must be with SYN). */ if ((th->th_flags & TH_SYN) == 0) goto handled; lpktp = MIN(th->th_off << 4, lpktp); pktp += sizeof(struct tcphdr); lpktp -= sizeof(struct tcphdr); while (lpktp >= TCPOLEN_MAXSEG) { GETCHAR(opt, pktp); switch (opt) { case TCPOPT_MAXSEG: GETCHAR(optlen, pktp); mssp = pktp; /* mss place holder */ GETSHORT(mss, pktp); maxmss = MAXMSS(mtu); if (mss > maxmss) { PIPEX_DBG((NULL, LOG_DEBUG, "change tcp-mss %d => %d", mss, maxmss)); PUTSHORT(maxmss, mssp); acc = htons(mss); acc -= htons(maxmss); ADJUST_CHECKSUM(acc, th->th_sum); } goto handled; /* NOTREACHED */ case TCPOPT_EOL: goto handled; /* NOTREACHED */ case TCPOPT_NOP: lpktp--; break; default: GETCHAR(optlen, pktp); if (optlen < 2) /* packet is broken */ goto drop; pktp += optlen - 2; lpktp -= optlen; break; } } handled: return (m0); drop: m_freem(m0); return (NULL); } /* * Check whether a packet should reset idle timer * Returns 1 to don't reset timer (i.e. the packet is "idle" packet) */ struct mbuf * ip_is_idle_packet(struct mbuf *m0, int *ris_idle) { u_int16_t ip_off; const struct udphdr *uh; struct ip *pip; int len; /* pullup ip header */ len = sizeof(struct ip); PIPEX_PULLUP(m0, len); if (m0 == NULL) goto error; pip = mtod(m0, struct ip *); /* * the packet which fragmentations was not the idle packet. */ ip_off = ntohs(pip->ip_off); if ((ip_off & IP_MF) || ((ip_off & IP_OFFMASK) != 0)) goto is_active; switch (pip->ip_p) { case IPPROTO_IGMP: goto is_active; case IPPROTO_ICMP: len = pip->ip_hl * 4 + 8; PIPEX_PULLUP(m0, len); if (m0 == NULL) goto error; pip = mtod(m0, struct ip *); switch (((unsigned char *) pip)[pip->ip_hl * 4]) { case 0: /* Echo Reply */ case 8: /* Echo Request */ goto is_active; default: goto is_idle; } case IPPROTO_UDP: case IPPROTO_TCP: len = pip->ip_hl * 4 + sizeof(struct udphdr); PIPEX_PULLUP(m0, len); if (m0 == NULL) goto error; pip = mtod(m0, struct ip *); uh = (struct udphdr *)(mtod(m0, caddr_t) + pip->ip_hl * 4); switch (ntohs(uh->uh_sport)) { case 53: /* DOMAIN */ case 67: /* BOOTPS */ case 68: /* BOOTPC */ case 123: /* NTP */ case 137: /* NETBIOS-NS */ case 520: /* RIP */ goto is_idle; } switch (ntohs(uh->uh_dport)) { case 53: /* DOMAIN */ case 67: /* BOOTPS */ case 68: /* BOOTPC */ case 123: /* NTP */ case 137: /* NETBIOS-NS */ case 520: /* RIP */ goto is_idle; } goto is_active; default: goto is_active; } is_active: *ris_idle = 0; return (m0); is_idle: *ris_idle = 1; return (m0); error: return (NULL); } void pipex_session_log(struct pipex_session *session, int prio, const char *fmt, ...) { char logbuf[1024]; va_list ap; logpri(prio); if (session != NULL) { struct ifnet *ifp; ifp = if_get(session->ifindex); addlog("pipex: ppp=%d iface=%s protocol=%s id=%d ", session->ppp_id, ifp? ifp->if_xname : "Unknown", (session->protocol == PIPEX_PROTO_PPPOE)? "PPPoE" : (session->protocol == PIPEX_PROTO_PPTP)? "PPTP" : (session->protocol == PIPEX_PROTO_L2TP) ? "L2TP" : "Unknown", session->session_id); if_put(ifp); } else addlog("pipex: "); va_start(ap, fmt); vsnprintf(logbuf, sizeof(logbuf), fmt, ap); va_end(ap); addlog("%s\n", logbuf); } uint32_t pipex_sockaddr_hash_key(struct sockaddr *sa) { switch (sa->sa_family) { case AF_INET: return ntohl(satosin(sa)->sin_addr.s_addr); case AF_INET6: return ntohl(satosin6(sa)->sin6_addr.s6_addr32[3]); } panic("pipex_sockaddr_hash_key: unknown address family"); return (0); } /* * Compare struct sockaddr_in{,6} with the address only. * The port number is not covered. */ int pipex_sockaddr_compar_addr(struct sockaddr *a, struct sockaddr *b) { int cmp; cmp = b->sa_family - a->sa_family; if (cmp != 0) return cmp; switch (a->sa_family) { case AF_INET: return (satosin(b)->sin_addr.s_addr - satosin(a)->sin_addr.s_addr); case AF_INET6: cmp = (satosin6(b)->sin6_scope_id - satosin6(a)->sin6_scope_id); if (cmp != 0) return cmp; return (memcmp(&satosin6(a)->sin6_addr, &satosin6(b)->sin6_addr, sizeof(struct in6_addr))); } panic("pipex_sockaddr_compar_addr: unknown address family"); return (-1); } int pipex_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { switch (name[0]) { case PIPEXCTL_ENABLE: if (namelen != 1) return (ENOTDIR); return (sysctl_int_bounded(oldp, oldlenp, newp, newlen, &pipex_enable, 0, 1)); default: return (ENOPROTOOPT); } /* NOTREACHED */ }
5 5 5 5 2 5 5 5 1 5 5 5 5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 /* $OpenBSD: inet_ntop.c,v 1.4 2016/09/04 17:05:24 claudio Exp $ */ /* Copyright (c) 1996 by Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/socket.h> #include <netinet/in.h> #define IN6ADDRSZ 16 #define INT16SZ 2 /* * WARNING: Don't even consider trying to compile this on a system where * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. */ static const char *inet_ntop4(const u_char *src, char *dst, size_t size); #ifdef INET6 static const char *inet_ntop6(const u_char *src, char *dst, size_t size); #endif /* INET6 */ /* char * * inet_ntop(af, src, dst, size) * convert a network format address to presentation format. * return: * pointer to presentation format address (`dst'), or NULL (see errno). * author: * Paul Vixie, 1996. */ const char * inet_ntop(int af, const void *src, char *dst, socklen_t size) { switch (af) { case AF_INET: return (inet_ntop4(src, dst, (size_t)size)); #ifdef INET6 case AF_INET6: return (inet_ntop6(src, dst, (size_t)size)); #endif /* INET6 */ default: return (NULL); } /* NOTREACHED */ } const char * sockaddr_ntop(struct sockaddr *sa, char *dst, size_t size) { u_int8_t l; size_t n; if (sa->sa_len < 2) return "bad sa"; switch (sa->sa_family) { case AF_INET: return inet_ntop4((u_char *)&satosin(sa)->sin_addr, dst, size); #ifdef INET6 case AF_INET6: return inet_ntop6((u_char *)&satosin6(sa)->sin6_addr, dst, size); #endif default: n = snprintf(dst, size, "%d ", sa->sa_family); for (l = 0; l < sa->sa_len - offsetof(struct sockaddr, sa_data); l++) { int r = snprintf(dst + n, size - n, "%02x", sa->sa_data[l]); if (r == -1) return "bad sa"; n += r; if (n > size) n = size; } return (dst); } } /* const char * * inet_ntop4(src, dst, size) * format an IPv4 address, more or less like inet_ntoa() * return: * `dst' (as a const) * notes: * (1) uses no statics * (2) takes a u_char* not an in_addr as input * author: * Paul Vixie, 1996. */ static const char * inet_ntop4(const u_char *src, char *dst, size_t size) { char tmp[sizeof "255.255.255.255"]; int l; l = snprintf(tmp, sizeof(tmp), "%u.%u.%u.%u", src[0], src[1], src[2], src[3]); if (l <= 0 || l >= size) { return (NULL); } strlcpy(dst, tmp, size); return (dst); } #ifdef INET6 /* const char * * inet_ntop6(src, dst, size) * convert IPv6 binary address into presentation (printable) format * author: * Paul Vixie, 1996. */ static const char * inet_ntop6(const u_char *src, char *dst, size_t size) { /* * Note that int32_t and int16_t need only be "at least" large enough * to contain a value of the specified size. On some systems, like * Crays, there is no such thing as an integer variable with 16 bits. * Keep this in mind if you think this function should have been coded * to use pointer overlays. All the world's not a VAX. */ char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; char *tp, *ep; struct { int base, len; } best, cur; u_int words[IN6ADDRSZ / INT16SZ]; int i; int advance; /* * Preprocess: * Copy the input (bytewise) array into a wordwise array. * Find the longest run of 0x00's in src[] for :: shorthanding. */ memset(words, '\0', sizeof words); for (i = 0; i < IN6ADDRSZ; i++) words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); best.base = -1; cur.base = -1; for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { if (words[i] == 0) { if (cur.base == -1) cur.base = i, cur.len = 1; else cur.len++; } else { if (cur.base != -1) { if (best.base == -1 || cur.len > best.len) best = cur; cur.base = -1; } } } if (cur.base != -1) { if (best.base == -1 || cur.len > best.len) best = cur; } if (best.base != -1 && best.len < 2) best.base = -1; /* * Format the result. */ tp = tmp; ep = tmp + sizeof(tmp); for (i = 0; i < (IN6ADDRSZ / INT16SZ) && tp < ep; i++) { /* Are we inside the best run of 0x00's? */ if (best.base != -1 && i >= best.base && i < (best.base + best.len)) { if (i == best.base) { if (tp + 1 >= ep) return (NULL); *tp++ = ':'; } continue; } /* Are we following an initial run of 0x00s or any real hex? */ if (i != 0) { if (tp + 1 >= ep) return (NULL); *tp++ = ':'; } /* Is this address an encapsulated IPv4? */ if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { if (!inet_ntop4(src+12, tp, (size_t)(ep - tp))) return (NULL); tp += strlen(tp); break; } advance = snprintf(tp, ep - tp, "%x", words[i]); if (advance <= 0 || advance >= ep - tp) return (NULL); tp += advance; } /* Was it a trailing run of 0x00's? */ if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) { if (tp + 1 >= ep) return (NULL); *tp++ = ':'; } if (tp + 1 >= ep) return (NULL); *tp++ = '\0'; /* * Check for overflow, copy, and we're done. */ if ((size_t)(tp - tmp) > size) { return (NULL); } strlcpy(dst, tmp, size); return (dst); } #endif /* INET6 */
93 93 10 9 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 /* $OpenBSD: conf.c,v 1.78 2023/03/06 17:20:05 miod Exp $ */ /* * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Charles Hannum. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> #include <sys/disklabel.h> #include <sys/ioctl.h> #include <sys/tty.h> #include <sys/vnode.h> #include <machine/conf.h> #include "wd.h" bdev_decl(wd); #include "fd.h" bdev_decl(fd); #include "sd.h" #include "st.h" #include "cd.h" #include "uk.h" #include "vnd.h" #include "rd.h" struct bdevsw bdevsw[] = { bdev_disk_init(NWD,wd), /* 0: ST506/ESDI/IDE disk */ bdev_swap_init(1,sw), /* 1: swap pseudo-device */ bdev_disk_init(NFD,fd), /* 2: floppy diskette */ bdev_notdef(), /* 3 */ bdev_disk_init(NSD,sd), /* 4: SCSI disk */ bdev_notdef(), /* 5: was: SCSI tape */ bdev_disk_init(NCD,cd), /* 6: SCSI CD-ROM */ bdev_notdef(), /* 7 */ bdev_notdef(), /* 8 */ bdev_notdef(), /* 9 */ bdev_notdef(), /* 10 */ bdev_notdef(), /* 11 */ bdev_notdef(), /* 12 */ bdev_notdef(), /* 13 */ bdev_disk_init(NVND,vnd), /* 14: vnode disk driver */ bdev_notdef(), /* 15: was: Sony CD-ROM */ bdev_notdef(), /* 16: was: concatenated disk driver */ bdev_disk_init(NRD,rd), /* 17: ram disk driver */ bdev_notdef(), /* 18 */ bdev_notdef(), /* 19 was: RAIDframe disk driver */ }; int nblkdev = nitems(bdevsw); /* open, close, ioctl */ #define cdev_ocis_init(c,n) { \ dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ (dev_type_stop((*))) enodev, 0, \ (dev_type_mmap((*))) enodev, 0, 0, seltrue_kqfilter } /* open, close, read */ #define cdev_nvram_init(c,n) { \ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ (dev_type_write((*))) enodev, (dev_type_ioctl((*))) enodev, \ (dev_type_stop((*))) enodev, 0, \ (dev_type_mmap((*))) enodev, 0, 0, seltrue_kqfilter } /* open, close, ioctl */ #define cdev_vmm_init(c,n) { \ dev_init(c,n,open), dev_init(c,n,close), \ (dev_type_read((*))) enodev, \ (dev_type_write((*))) enodev, \ dev_init(c,n,ioctl), \ (dev_type_stop((*))) enodev, 0, \ (dev_type_mmap((*))) enodev, 0, 0, seltrue_kqfilter } #define mmread mmrw #define mmwrite mmrw cdev_decl(mm); cdev_decl(wd); #include "bio.h" #include "pty.h" #include "com.h" cdev_decl(com); cdev_decl(fd); #include "lpt.h" cdev_decl(lpt); #include "ch.h" #include "bpfilter.h" #if 0 #include "pcmcia.h" cdev_decl(pcmcia); #endif #include "spkr.h" cdev_decl(spkr); #if 0 /* old (non-wsmouse) drivers */ #include "mms.h" cdev_decl(mms); #include "lms.h" cdev_decl(lms); #include "opms.h" cdev_decl(pms); #endif #include "cy.h" cdev_decl(cy); #include "tun.h" #include "audio.h" #include "video.h" #include "midi.h" #include "acpi.h" #include "pctr.h" #include "bktr.h" #include "ksyms.h" #include "kstat.h" #include "usb.h" #include "uhid.h" #include "fido.h" #include "ujoy.h" #include "ugen.h" #include "ulpt.h" #include "ucom.h" #include "cz.h" cdev_decl(cztty); #include "radio.h" #include "nvram.h" cdev_decl(nvram); #include "drm.h" cdev_decl(drm); #include "viocon.h" cdev_decl(viocon); #include "wsdisplay.h" #include "wskbd.h" #include "wsmouse.h" #include "wsmux.h" #include "kcov.h" #ifdef USER_PCICONF #include "pci.h" cdev_decl(pci); #endif #include "dt.h" #include "pf.h" #include "hotplug.h" #include "gpio.h" #include "vscsi.h" #include "pppx.h" #include "fuse.h" #include "pvbus.h" #include "ipmi.h" #include "efi.h" struct cdevsw cdevsw[] = { cdev_cn_init(1,cn), /* 0: virtual console */ cdev_ctty_init(1,ctty), /* 1: controlling terminal */ cdev_mm_init(1,mm), /* 2: /dev/{null,mem,kmem,...} */ cdev_disk_init(NWD,wd), /* 3: ST506/ESDI/IDE disk */ cdev_notdef(), /* 4 was /dev/drum */ cdev_tty_init(NPTY,pts), /* 5: pseudo-tty slave */ cdev_ptc_init(NPTY,ptc), /* 6: pseudo-tty master */ cdev_log_init(1,log), /* 7: /dev/klog */ cdev_tty_init(NCOM,com), /* 8: serial port */ cdev_disk_init(NFD,fd), /* 9: floppy disk */ cdev_vmm_init(NVMM,vmm), /* 10 vmm */ cdev_notdef(), /* 11: Sony CD-ROM */ cdev_wsdisplay_init(NWSDISPLAY, /* 12: frame buffers, etc. */ wsdisplay), cdev_disk_init(NSD,sd), /* 13: SCSI disk */ cdev_tape_init(NST,st), /* 14: SCSI tape */ cdev_disk_init(NCD,cd), /* 15: SCSI CD-ROM */ cdev_lpt_init(NLPT,lpt), /* 16: parallel printer */ cdev_ch_init(NCH,ch), /* 17: SCSI autochanger */ cdev_notdef(), /* 18: was: concatenated disk driver */ cdev_kcov_init(NKCOV,kcov), /* 19: kcov */ cdev_uk_init(NUK,uk), /* 20: unknown SCSI */ cdev_notdef(), /* 21 */ cdev_fd_init(1,filedesc), /* 22: file descriptor pseudo-device */ cdev_bpf_init(NBPFILTER,bpf), /* 23: Berkeley packet filter */ cdev_notdef(), /* 24 */ #if 0 cdev_ocis_init(NPCMCIA,pcmcia), /* 25: PCMCIA Bus */ #else cdev_notdef(), /* 25 */ #endif cdev_notdef(), /* 26 */ cdev_spkr_init(NSPKR,spkr), /* 27: PC speaker */ cdev_notdef(), /* 28 was LKM */ cdev_notdef(), /* 29 */ cdev_dt_init(NDT,dt), /* 30: dynamic tracer */ cdev_notdef(), /* 31 */ cdev_notdef(), /* 32 */ cdev_notdef(), /* 33 */ cdev_notdef(), /* 34 */ cdev_notdef(), /* 35: Microsoft mouse */ cdev_notdef(), /* 36: Logitech mouse */ cdev_notdef(), /* 37: Extended PS/2 mouse */ cdev_tty_init(NCY,cy), /* 38: Cyclom serial port */ cdev_notdef(), /* 39: Mitsumi CD-ROM */ cdev_tun_init(NTUN,tun), /* 40: network tunnel */ cdev_disk_init(NVND,vnd), /* 41: vnode disk driver */ cdev_audio_init(NAUDIO,audio), /* 42: generic audio I/O */ cdev_notdef(), /* 43 */ cdev_video_init(NVIDEO,video), /* 44: generic video I/O */ cdev_random_init(1,random), /* 45: random data source */ cdev_ocis_init(NPCTR,pctr), /* 46: performance counters */ cdev_disk_init(NRD,rd), /* 47: ram disk driver */ cdev_notdef(), /* 48 */ cdev_bktr_init(NBKTR,bktr), /* 49: Bt848 video capture device */ cdev_ksyms_init(NKSYMS,ksyms), /* 50: Kernel symbols device */ cdev_kstat_init(NKSTAT,kstat), /* 51: Kernel statistics */ cdev_midi_init(NMIDI,midi), /* 52: MIDI I/O */ cdev_notdef(), /* 53 was: sequencer I/O */ cdev_notdef(), /* 54 was: RAIDframe disk driver */ cdev_notdef(), /* 55: */ /* The following slots are reserved for isdn4bsd. */ cdev_notdef(), /* 56: i4b main device */ cdev_notdef(), /* 57: i4b control device */ cdev_notdef(), /* 58: i4b raw b-channel access */ cdev_notdef(), /* 59: i4b trace device */ cdev_notdef(), /* 60: i4b phone device */ /* End of reserved slots for isdn4bsd. */ cdev_usb_init(NUSB,usb), /* 61: USB controller */ cdev_usbdev_init(NUHID,uhid), /* 62: USB generic HID */ cdev_usbdev_init(NUGEN,ugen), /* 63: USB generic driver */ cdev_ulpt_init(NULPT,ulpt), /* 64: USB printers */ cdev_notdef(), /* 65: urio */ cdev_tty_init(NUCOM,ucom), /* 66: USB tty */ cdev_mouse_init(NWSKBD, wskbd), /* 67: keyboards */ cdev_mouse_init(NWSMOUSE, /* 68: mice */ wsmouse), cdev_mouse_init(NWSMUX, wsmux), /* 69: ws multiplexor */ cdev_notdef(), /* 70: was: /dev/crypto */ cdev_tty_init(NCZ,cztty), /* 71: Cyclades-Z serial port */ #ifdef USER_PCICONF cdev_pci_init(NPCI,pci), /* 72: PCI user */ #else cdev_notdef(), #endif cdev_pf_init(NPF,pf), /* 73: packet filter */ cdev_notdef(), /* 74: ALTQ (deprecated) */ cdev_notdef(), cdev_radio_init(NRADIO, radio), /* 76: generic radio I/O */ cdev_notdef(), /* 77: was USB scanners */ cdev_notdef(), /* 78 */ cdev_bio_init(NBIO,bio), /* 79: ioctl tunnel */ cdev_notdef(), /* 80 */ cdev_ptm_init(NPTY,ptm), /* 81: pseudo-tty ptm device */ cdev_hotplug_init(NHOTPLUG,hotplug), /* 82: devices hot plugging */ cdev_acpi_init(NACPI,acpi), /* 83: ACPI */ cdev_efi_init(NEFI,efi), /* 84: EFI */ cdev_nvram_init(NNVRAM,nvram), /* 85: NVRAM interface */ cdev_notdef(), /* 86 */ cdev_drm_init(NDRM,drm), /* 87: drm */ cdev_gpio_init(NGPIO,gpio), /* 88: gpio */ cdev_vscsi_init(NVSCSI,vscsi), /* 89: vscsi */ cdev_disk_init(1,diskmap), /* 90: disk mapper */ cdev_pppx_init(NPPPX,pppx), /* 91: pppx */ cdev_fuse_init(NFUSE,fuse), /* 92: fuse */ cdev_tun_init(NTUN,tap), /* 93: Ethernet network tunnel */ cdev_tty_init(NVIOCON,viocon), /* 94: virtio console */ cdev_pvbus_init(NPVBUS,pvbus), /* 95: pvbus(4) control interface */ cdev_ipmi_init(NIPMI,ipmi), /* 96: ipmi */ cdev_notdef(), /* 97: was switch(4) */ cdev_fido_init(NFIDO,fido), /* 98: FIDO/U2F security keys */ cdev_pppx_init(NPPPX,pppac), /* 99: PPP Access Concentrator */ cdev_ujoy_init(NUJOY,ujoy), /* 100: USB joystick/gamecontroller */ }; int nchrdev = nitems(cdevsw); int mem_no = 2; /* major device number of memory special file */ /* * Swapdev is a fake device implemented * in sw.c used only internally to get to swstrategy. * It cannot be provided to the users, because the * swstrategy routine munches the b_dev and b_blkno entries * before calling the appropriate driver. This would horribly * confuse, e.g. the hashing routines. Instead, /dev/drum is * provided as a character (raw) device. */ dev_t swapdev = makedev(1, 0); /* * Returns true if dev is /dev/mem or /dev/kmem. */ int iskmemdev(dev_t dev) { return (major(dev) == mem_no && minor(dev) < 2); } /* * Returns true if dev is /dev/zero. */ int iszerodev(dev_t dev) { return (major(dev) == mem_no && minor(dev) == 12); } dev_t getnulldev(void) { return makedev(mem_no, 2); } const int chrtoblktbl[] = { /*VCHR*/ /*VBLK*/ /* 0 */ NODEV, /* 1 */ NODEV, /* 2 */ NODEV, /* 3 */ 0, /* wd */ /* 4 */ NODEV, /* 5 */ NODEV, /* 6 */ NODEV, /* 7 */ NODEV, /* 8 */ NODEV, /* 9 */ 2, /* fd */ /* 10 */ NODEV, /* 11 */ NODEV, /* 12 */ NODEV, /* 13 */ 4, /* sd */ /* 14 */ NODEV, /* 15 */ 6, /* cd */ /* 16 */ NODEV, /* 17 */ NODEV, /* 18 */ NODEV, /* 19 */ NODEV, /* 20 */ NODEV, /* 21 */ NODEV, /* 22 */ NODEV, /* 23 */ NODEV, /* 24 */ NODEV, /* 25 */ NODEV, /* 26 */ NODEV, /* 27 */ NODEV, /* 28 */ NODEV, /* 29 */ NODEV, /* 30 */ NODEV, /* 31 */ NODEV, /* 32 */ NODEV, /* 33 */ NODEV, /* 34 */ NODEV, /* 35 */ NODEV, /* 36 */ NODEV, /* 37 */ NODEV, /* 38 */ NODEV, /* 39 */ NODEV, /* 40 */ NODEV, /* 41 */ 14, /* vnd */ /* 42 */ NODEV, /* 43 */ NODEV, /* 44 */ NODEV, /* 45 */ NODEV, /* 46 */ NODEV, /* 47 */ 17, /* rd */ }; const int nchrtoblktbl = nitems(chrtoblktbl); /* * In order to map BSD bdev numbers of disks to their BIOS equivalents * we use several heuristics, one being using checksums of the first * few blocks of a disk to get a signature we can match with /boot's * computed signatures. To know where from to read, we must provide a * disk driver name -> bdev major number table, which follows. * Note: floppies are not included as those are differentiated by the BIOS. */ int findblkmajor(struct device *dv); dev_t dev_rawpart(struct device *); /* XXX */ dev_t dev_rawpart(struct device *dv) { int majdev; majdev = findblkmajor(dv); switch (majdev) { /* add here any device you want to be checksummed on boot */ case 0: /* wd */ case 4: /* sd */ return (MAKEDISKDEV(majdev, dv->dv_unit, RAW_PART)); break; default: ; } return (NODEV); } #include <dev/cons.h> cons_decl(com); cons_decl(ws); struct consdev constab[] = { #if NWSDISPLAY > 0 cons_init(ws), #endif #if NCOM > 0 cons_init(com), #endif { 0 }, };
4 3 1 3 1 2 4 4 2 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 /* $OpenBSD: ip6_divert.c,v 1.95 2024/02/13 12:22:09 bluhm Exp $ */ /* * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/protosw.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/sysctl.h> #include <net/if.h> #include <net/route.h> #include <net/if_var.h> #include <net/netisr.h> #include <netinet/in.h> #include <netinet6/in6_var.h> #include <netinet/ip.h> #include <netinet/ip_var.h> #include <netinet/ip6.h> #include <netinet6/ip6_var.h> #include <netinet/in_pcb.h> #include <netinet/ip_divert.h> #include <netinet6/ip6_divert.h> #include <netinet/tcp.h> #include <netinet/udp.h> #include <netinet/icmp6.h> #include <net/pfvar.h> struct inpcbtable divb6table; struct cpumem *div6counters; #ifndef DIVERT_SENDSPACE #define DIVERT_SENDSPACE (65536 + 100) #endif u_int divert6_sendspace = DIVERT_SENDSPACE; #ifndef DIVERT_RECVSPACE #define DIVERT_RECVSPACE (65536 + 100) #endif u_int divert6_recvspace = DIVERT_RECVSPACE; #ifndef DIVERTHASHSIZE #define DIVERTHASHSIZE 128 #endif const struct sysctl_bounded_args divert6ctl_vars[] = { { DIVERT6CTL_RECVSPACE, &divert6_recvspace, 0, INT_MAX }, { DIVERT6CTL_SENDSPACE, &divert6_sendspace, 0, INT_MAX }, }; const struct pr_usrreqs divert6_usrreqs = { .pru_attach = divert6_attach, .pru_detach = divert_detach, .pru_lock = divert_lock, .pru_unlock = divert_unlock, .pru_locked = divert_locked, .pru_bind = divert_bind, .pru_shutdown = divert_shutdown, .pru_send = divert6_send, .pru_control = in6_control, .pru_sockaddr = in6_sockaddr, .pru_peeraddr = in6_peeraddr, }; int divb6hashsize = DIVERTHASHSIZE; int divert6_output(struct inpcb *, struct mbuf *, struct mbuf *, struct mbuf *); void divert6_init(void) { in_pcbinit(&divb6table, divb6hashsize); div6counters = counters_alloc(div6s_ncounters); } int divert6_output(struct inpcb *inp, struct mbuf *m, struct mbuf *nam, struct mbuf *control) { struct sockaddr_in6 *sin6; int error, min_hdrlen, nxt, off, dir; struct ip6_hdr *ip6; m_freem(control); if ((error = in6_nam2sin6(nam, &sin6))) goto fail; /* Do basic sanity checks. */ if (m->m_pkthdr.len < sizeof(struct ip6_hdr)) goto fail; if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) { /* m_pullup() has freed the mbuf, so just return. */ div6stat_inc(div6s_errors); return (ENOBUFS); } ip6 = mtod(m, struct ip6_hdr *); if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) goto fail; if (m->m_pkthdr.len < sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen)) goto fail; /* * Recalculate the protocol checksum since the userspace application * may have modified the packet prior to reinjection. */ off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt); if (off < sizeof(struct ip6_hdr)) goto fail; dir = (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ? PF_OUT : PF_IN); switch (nxt) { case IPPROTO_TCP: min_hdrlen = sizeof(struct tcphdr); m->m_pkthdr.csum_flags |= M_TCP_CSUM_OUT; break; case IPPROTO_UDP: min_hdrlen = sizeof(struct udphdr); m->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT; break; case IPPROTO_ICMPV6: min_hdrlen = sizeof(struct icmp6_hdr); m->m_pkthdr.csum_flags |= M_ICMP_CSUM_OUT; break; default: min_hdrlen = 0; break; } if (min_hdrlen && m->m_pkthdr.len < off + min_hdrlen) goto fail; m->m_pkthdr.pf.flags |= PF_TAG_DIVERTED_PACKET; if (dir == PF_IN) { struct rtentry *rt; struct ifnet *ifp; rt = rtalloc(sin6tosa(sin6), 0, inp->inp_rtableid); if (!rtisvalid(rt) || !ISSET(rt->rt_flags, RTF_LOCAL)) { rtfree(rt); error = EADDRNOTAVAIL; goto fail; } m->m_pkthdr.ph_ifidx = rt->rt_ifidx; rtfree(rt); /* * Recalculate the protocol checksum for the inbound packet * since the userspace application may have modified the packet * prior to reinjection. */ in6_proto_cksum_out(m, NULL); ifp = if_get(m->m_pkthdr.ph_ifidx); if (ifp == NULL) { error = ENETDOWN; goto fail; } ipv6_input(ifp, m); if_put(ifp); } else { m->m_pkthdr.ph_rtableid = inp->inp_rtableid; error = ip6_output(m, NULL, &inp->inp_route, IP_ALLOWBROADCAST | IP_RAWOUTPUT, NULL, NULL); } div6stat_inc(div6s_opackets); return (error); fail: div6stat_inc(div6s_errors); m_freem(m); return (error ? error : EINVAL); } void divert6_packet(struct mbuf *m, int dir, u_int16_t divert_port) { struct inpcb *inp = NULL; struct socket *so; struct sockaddr_in6 sin6; div6stat_inc(div6s_ipackets); if (m->m_len < sizeof(struct ip6_hdr) && (m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) { div6stat_inc(div6s_errors); goto bad; } mtx_enter(&divb6table.inpt_mtx); TAILQ_FOREACH(inp, &divb6table.inpt_queue, inp_queue) { if (inp->inp_lport != divert_port) continue; in_pcbref(inp); break; } mtx_leave(&divb6table.inpt_mtx); if (inp == NULL) { div6stat_inc(div6s_noport); goto bad; } memset(&sin6, 0, sizeof(sin6)); sin6.sin6_family = AF_INET6; sin6.sin6_len = sizeof(sin6); if (dir == PF_IN) { struct ifaddr *ifa; struct ifnet *ifp; ifp = if_get(m->m_pkthdr.ph_ifidx); if (ifp == NULL) { div6stat_inc(div6s_errors); goto bad; } TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; sin6.sin6_addr = satosin6(ifa->ifa_addr)->sin6_addr; break; } if_put(ifp); } else { /* * Calculate protocol checksum for outbound packet diverted * to userland. pf out rule diverts before cksum offload. */ in6_proto_cksum_out(m, NULL); } so = inp->inp_socket; mtx_enter(&so->so_rcv.sb_mtx); if (sbappendaddr(so, &so->so_rcv, sin6tosa(&sin6), m, NULL) == 0) { mtx_leave(&so->so_rcv.sb_mtx); div6stat_inc(div6s_fullsock); goto bad; } mtx_leave(&so->so_rcv.sb_mtx); sorwakeup(so); in_pcbunref(inp); return; bad: if (inp != NULL) in_pcbunref(inp); m_freem(m); } int divert6_attach(struct socket *so, int proto, int wait) { int error; if (so->so_pcb != NULL) return EINVAL; if ((so->so_state & SS_PRIV) == 0) return EACCES; error = in_pcballoc(so, &divb6table, wait); if (error) return (error); error = soreserve(so, divert6_sendspace, divert6_recvspace); if (error) return (error); return (0); } int divert6_send(struct socket *so, struct mbuf *m, struct mbuf *addr, struct mbuf *control) { struct inpcb *inp = sotoinpcb(so); soassertlocked(so); return (divert6_output(inp, m, addr, control)); } int divert6_sysctl_div6stat(void *oldp, size_t *oldlenp, void *newp) { uint64_t counters[div6s_ncounters]; struct div6stat div6stat; u_long *words = (u_long *)&div6stat; int i; CTASSERT(sizeof(div6stat) == (nitems(counters) * sizeof(u_long))); counters_read(div6counters, counters, nitems(counters), NULL); for (i = 0; i < nitems(counters); i++) words[i] = (u_long)counters[i]; return (sysctl_rdstruct(oldp, oldlenp, newp, &div6stat, sizeof(div6stat))); } /* * Sysctl for divert variables. */ int divert6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int error; /* All sysctl names at this level are terminal. */ if (namelen != 1) return (ENOTDIR); switch (name[0]) { case DIVERT6CTL_STATS: return (divert6_sysctl_div6stat(oldp, oldlenp, newp)); default: NET_LOCK(); error = sysctl_bounded_arr(divert6ctl_vars, nitems(divert6ctl_vars), name, namelen, oldp, oldlenp, newp, newlen); NET_UNLOCK(); return (error); } /* NOTREACHED */ }
24 23 10 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 /* $OpenBSD: strncpy.c,v 1.9 2014/06/10 04:16:57 deraadt Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <lib/libkern/libkern.h> /* * Copy src to dst, truncating or null-padding to always copy n bytes. * Return dst. */ char * strncpy(char *dst, const char *src, size_t n) { if (n != 0) { char *d = dst; const char *s = src; do { if ((*d++ = *s++) == 0) { /* NUL pad the remaining n-1 bytes */ while (--n != 0) *d++ = 0; break; } } while (--n != 0); } return (dst); }
38 3 2 3 2 2 11 2 6 3 2 2 3 6 9 1 2 6 2 2 5 7 7 7 5 5 2 3 3 3 3 1 1 1 3 3 1 1 1 5 5 5 5 5 2 5 21 28 3 11 11 1 10 3 1 4 6 6 1 5 2 2 2 2 3 3 3 20 10 21 9 4 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 /* $OpenBSD: ip6_mroute.c,v 1.141 2024/04/06 14:23:27 bluhm Exp $ */ /* $NetBSD: ip6_mroute.c,v 1.59 2003/12/10 09:28:38 itojun Exp $ */ /* $KAME: ip6_mroute.c,v 1.45 2001/03/25 08:38:51 itojun Exp $ */ /* * Copyright (C) 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* BSDI ip_mroute.c,v 2.10 1996/11/14 00:29:52 jch Exp */ /* * Copyright (c) 1989 Stephen Deering * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Stephen Deering of Stanford University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ip_mroute.c 8.2 (Berkeley) 11/15/93 */ /* * IP multicast forwarding procedures * * Written by David Waitzman, BBN Labs, August 1988. * Modified by Steve Deering, Stanford, February 1989. * Modified by Mark J. Steiglitz, Stanford, May, 1991 * Modified by Van Jacobson, LBL, January 1993 * Modified by Ajit Thyagarajan, PARC, August 1993 * Modified by Bill Fenner, PARC, April 1994 * * MROUTING Revision: 3.5.1.2 */ #include <sys/param.h> #include <sys/malloc.h> #include <sys/systm.h> #include <sys/timeout.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/protosw.h> #include <sys/kernel.h> #include <sys/ioctl.h> #include <sys/syslog.h> #include <sys/sysctl.h> #include <net/if.h> #include <net/if_var.h> #include <net/route.h> #include <netinet/in.h> #include <netinet6/in6_var.h> #include <netinet/ip.h> #include <netinet/ip6.h> #include <netinet/icmp6.h> #include <netinet6/ip6_var.h> #include <netinet6/ip6_mroute.h> #include <netinet/in_pcb.h> /* #define MCAST_DEBUG */ #ifdef MCAST_DEBUG int mcast6_debug = 1; #define DPRINTF(fmt, args...) \ do { \ if (mcast6_debug) \ printf("%s:%d " fmt "\n", \ __func__, __LINE__, ## args); \ } while (0) #else #define DPRINTF(fmt, args...) \ do { } while (0) #endif int ip6_mdq(struct mbuf *, struct ifnet *, struct rtentry *); void phyint_send6(struct ifnet *, struct ip6_hdr *, struct mbuf *); /* * Globals. All but ip6_mrouter, ip6_mrtproto and mrt6stat could be static, * except for netstat or debugging purposes. */ struct socket *ip6_mrouter[RT_TABLEID_MAX + 1]; struct rttimer_queue ip6_mrouterq; int ip6_mrouter_ver = 0; int ip6_mrtproto; /* for netstat only */ struct mrt6stat mrt6stat; #define NO_RTE_FOUND 0x1 #define RTE_FOUND 0x2 /* * Macros to compute elapsed time efficiently * Borrowed from Van Jacobson's scheduling code */ #define TV_DELTA(a, b, delta) do { \ int xxs; \ \ delta = (a).tv_usec - (b).tv_usec; \ if ((xxs = (a).tv_sec - (b).tv_sec)) { \ switch (xxs) { \ case 2: \ delta += 1000000; \ /* FALLTHROUGH */ \ case 1: \ delta += 1000000; \ break; \ default: \ delta += (1000000 * xxs); \ } \ } \ } while (0) #define TV_LT(a, b) (((a).tv_usec < (b).tv_usec && \ (a).tv_sec <= (b).tv_sec) || (a).tv_sec < (b).tv_sec) int get_sg6_cnt(struct sioc_sg_req6 *, unsigned int); int get_mif6_cnt(struct sioc_mif_req6 *, unsigned int); int ip6_mrouter_init(struct socket *, int, int); int add_m6if(struct socket *, struct mif6ctl *); int del_m6if(struct socket *, mifi_t *); int add_m6fc(struct socket *, struct mf6cctl *); int del_m6fc(struct socket *, struct mf6cctl *); struct ifnet *mrt6_iflookupbymif(mifi_t, unsigned int); struct rtentry *mf6c_find(struct ifnet *, struct in6_addr *, struct in6_addr *, unsigned int); struct rtentry *mrt6_mcast_add(struct ifnet *, struct sockaddr *, struct sockaddr *); void mrt6_mcast_del(struct rtentry *, unsigned int); /* * Handle MRT setsockopt commands to modify the multicast routing tables. */ int ip6_mrouter_set(int cmd, struct socket *so, struct mbuf *m) { struct inpcb *inp = sotoinpcb(so); if (cmd != MRT6_INIT && so != ip6_mrouter[inp->inp_rtableid]) return (EPERM); switch (cmd) { case MRT6_INIT: if (m == NULL || m->m_len < sizeof(int)) return (EINVAL); return (ip6_mrouter_init(so, *mtod(m, int *), cmd)); case MRT6_DONE: return (ip6_mrouter_done(so)); case MRT6_ADD_MIF: if (m == NULL || m->m_len < sizeof(struct mif6ctl)) return (EINVAL); return (add_m6if(so, mtod(m, struct mif6ctl *))); case MRT6_DEL_MIF: if (m == NULL || m->m_len < sizeof(mifi_t)) return (EINVAL); return (del_m6if(so, mtod(m, mifi_t *))); case MRT6_ADD_MFC: if (m == NULL || m->m_len < sizeof(struct mf6cctl)) return (EINVAL); return (add_m6fc(so, mtod(m, struct mf6cctl *))); case MRT6_DEL_MFC: if (m == NULL || m->m_len < sizeof(struct mf6cctl)) return (EINVAL); return (del_m6fc(so, mtod(m, struct mf6cctl *))); default: return (EOPNOTSUPP); } } /* * Handle MRT getsockopt commands */ int ip6_mrouter_get(int cmd, struct socket *so, struct mbuf *m) { struct inpcb *inp = sotoinpcb(so); if (so != ip6_mrouter[inp->inp_rtableid]) return (EPERM); switch (cmd) { default: return EOPNOTSUPP; } } /* * Handle ioctl commands to obtain information from the cache */ int mrt6_ioctl(struct socket *so, u_long cmd, caddr_t data) { struct inpcb *inp = sotoinpcb(so); int error; if (inp == NULL) return (ENOTCONN); KERNEL_LOCK(); switch (cmd) { case SIOCGETSGCNT_IN6: NET_LOCK_SHARED(); error = get_sg6_cnt((struct sioc_sg_req6 *)data, inp->inp_rtableid); NET_UNLOCK_SHARED(); break; case SIOCGETMIFCNT_IN6: NET_LOCK_SHARED(); error = get_mif6_cnt((struct sioc_mif_req6 *)data, inp->inp_rtableid); NET_UNLOCK_SHARED(); break; default: error = ENOTTY; break; } KERNEL_UNLOCK(); return error; } /* * returns the packet, byte, rpf-failure count for the source group provided */ int get_sg6_cnt(struct sioc_sg_req6 *req, unsigned int rtableid) { struct rtentry *rt; struct mf6c *mf6c; rt = mf6c_find(NULL, &req->src.sin6_addr, &req->grp.sin6_addr, rtableid); if (rt == NULL) { req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff; return EADDRNOTAVAIL; } req->pktcnt = req->bytecnt = req->wrong_if = 0; do { mf6c = (struct mf6c *)rt->rt_llinfo; if (mf6c == NULL) continue; req->pktcnt += mf6c->mf6c_pkt_cnt; req->bytecnt += mf6c->mf6c_byte_cnt; req->wrong_if += mf6c->mf6c_wrong_if; } while ((rt = rtable_iterate(rt)) != NULL); return 0; } /* * returns the input and output packet and byte counts on the mif provided */ int get_mif6_cnt(struct sioc_mif_req6 *req, unsigned int rtableid) { struct ifnet *ifp; struct mif6 *m6; if ((ifp = mrt6_iflookupbymif(req->mifi, rtableid)) == NULL) return EINVAL; m6 = (struct mif6 *)ifp->if_mcast6; req->icount = m6->m6_pkt_in; req->ocount = m6->m6_pkt_out; req->ibytes = m6->m6_bytes_in; req->obytes = m6->m6_bytes_out; return 0; } int mrt6_sysctl_mif(void *oldp, size_t *oldlenp) { struct ifnet *ifp; caddr_t where = oldp; size_t needed, given; struct mif6 *mifp; struct mif6info minfo; given = *oldlenp; needed = 0; memset(&minfo, 0, sizeof minfo); TAILQ_FOREACH(ifp, &ifnetlist, if_list) { if ((mifp = (struct mif6 *)ifp->if_mcast6) == NULL) continue; minfo.m6_mifi = mifp->m6_mifi; minfo.m6_flags = mifp->m6_flags; minfo.m6_lcl_addr = mifp->m6_lcl_addr; minfo.m6_ifindex = ifp->if_index; minfo.m6_pkt_in = mifp->m6_pkt_in; minfo.m6_pkt_out = mifp->m6_pkt_out; minfo.m6_bytes_in = mifp->m6_bytes_in; minfo.m6_bytes_out = mifp->m6_bytes_out; minfo.m6_rate_limit = mifp->m6_rate_limit; needed += sizeof(minfo); if (where && needed <= given) { int error; error = copyout(&minfo, where, sizeof(minfo)); if (error) return (error); where += sizeof(minfo); } } if (where) { *oldlenp = needed; if (given < needed) return (ENOMEM); } else *oldlenp = (11 * needed) / 10; return (0); } struct mf6csysctlarg { struct mf6cinfo *ms6a_minfos; size_t ms6a_len; size_t ms6a_needed; }; int mrt6_rtwalk_mf6csysctl(struct rtentry *rt, void *arg, unsigned int rtableid) { struct mf6c *mf6c = (struct mf6c *)rt->rt_llinfo; struct mf6csysctlarg *msa = arg; struct ifnet *ifp; struct mif6 *m6; struct mf6cinfo *minfo; int new = 0; /* Skip entries being removed. */ if (mf6c == NULL) return 0; /* Skip non-multicast routes. */ if (ISSET(rt->rt_flags, RTF_HOST | RTF_MULTICAST) != (RTF_HOST | RTF_MULTICAST)) return 0; /* User just asked for the output size. */ if (msa->ms6a_minfos == NULL) { msa->ms6a_needed += sizeof(*minfo); return 0; } /* Skip route with invalid interfaces. */ if ((ifp = if_get(rt->rt_ifidx)) == NULL) return 0; if ((m6 = (struct mif6 *)ifp->if_mcast6) == NULL) { if_put(ifp); return 0; } for (minfo = msa->ms6a_minfos; (uint8_t *)(minfo + 1) <= (uint8_t *)msa->ms6a_minfos + msa->ms6a_len; minfo++) { /* Find a new entry or update old entry. */ if (!IN6_ARE_ADDR_EQUAL(&minfo->mf6c_origin.sin6_addr, &satosin6(rt->rt_gateway)->sin6_addr) || !IN6_ARE_ADDR_EQUAL(&minfo->mf6c_mcastgrp.sin6_addr, &satosin6(rt_key(rt))->sin6_addr)) { if (!IN6_IS_ADDR_UNSPECIFIED( &minfo->mf6c_origin.sin6_addr) || !IN6_IS_ADDR_UNSPECIFIED( &minfo->mf6c_mcastgrp.sin6_addr)) continue; new = 1; } minfo->mf6c_origin = *satosin6(rt->rt_gateway); minfo->mf6c_mcastgrp = *satosin6(rt_key(rt)); minfo->mf6c_parent = mf6c->mf6c_parent; minfo->mf6c_pkt_cnt += mf6c->mf6c_pkt_cnt; minfo->mf6c_byte_cnt += mf6c->mf6c_byte_cnt; IF_SET(m6->m6_mifi, &minfo->mf6c_ifset); break; } if (new != 0) msa->ms6a_needed += sizeof(*minfo); if_put(ifp); return 0; } int mrt6_sysctl_mfc(void *oldp, size_t *oldlenp) { unsigned int rtableid; int error; struct mf6csysctlarg msa; if (oldp != NULL && *oldlenp > MAXPHYS) return EINVAL; memset(&msa, 0, sizeof(msa)); if (oldp != NULL && *oldlenp > 0) { msa.ms6a_minfos = malloc(*oldlenp, M_TEMP, M_WAITOK | M_ZERO); msa.ms6a_len = *oldlenp; } for (rtableid = 0; rtableid <= RT_TABLEID_MAX; rtableid++) { rtable_walk(rtableid, AF_INET6, NULL, mrt6_rtwalk_mf6csysctl, &msa); } if (msa.ms6a_minfos != NULL && msa.ms6a_needed > 0 && (error = copyout(msa.ms6a_minfos, oldp, msa.ms6a_needed)) != 0) { free(msa.ms6a_minfos, M_TEMP, msa.ms6a_len); return error; } free(msa.ms6a_minfos, M_TEMP, msa.ms6a_len); *oldlenp = msa.ms6a_needed; return 0; } /* * Enable multicast routing */ int ip6_mrouter_init(struct socket *so, int v, int cmd) { struct inpcb *inp = sotoinpcb(so); unsigned int rtableid = inp->inp_rtableid; if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_ICMPV6) return (EOPNOTSUPP); if (v != 1) return (ENOPROTOOPT); if (ip6_mrouter[rtableid] != NULL) return (EADDRINUSE); ip6_mrouter[rtableid] = so; ip6_mrouter_ver = cmd; return (0); } int mrouter6_rtwalk_delete(struct rtentry *rt, void *arg, unsigned int rtableid) { /* Skip non-multicast routes. */ if (ISSET(rt->rt_flags, RTF_HOST | RTF_MULTICAST) != (RTF_HOST | RTF_MULTICAST)) return 0; return EEXIST; } /* * Disable multicast routing */ int ip6_mrouter_done(struct socket *so) { struct inpcb *inp = sotoinpcb(so); struct ifnet *ifp; unsigned int rtableid = inp->inp_rtableid; int error; NET_ASSERT_LOCKED(); /* Delete all remaining installed multicast routes. */ do { struct rtentry *rt = NULL; error = rtable_walk(rtableid, AF_INET6, &rt, mrouter6_rtwalk_delete, NULL); if (rt != NULL && error == EEXIST) { mrt6_mcast_del(rt, rtableid); error = EAGAIN; } rtfree(rt); } while (error == EAGAIN); /* Unregister all interfaces in the domain. */ TAILQ_FOREACH(ifp, &ifnetlist, if_list) { if (ifp->if_rdomain != rtableid) continue; ip6_mrouter_detach(ifp); } ip6_mrouter[inp->inp_rtableid] = NULL; ip6_mrouter_ver = 0; return 0; } void ip6_mrouter_detach(struct ifnet *ifp) { struct mif6 *m6 = (struct mif6 *)ifp->if_mcast6; struct in6_ifreq ifr; if (m6 == NULL) return; ifp->if_mcast6 = NULL; memset(&ifr, 0, sizeof(ifr)); ifr.ifr_addr.sin6_family = AF_INET6; ifr.ifr_addr.sin6_addr = in6addr_any; KERNEL_LOCK(); (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr); KERNEL_UNLOCK(); free(m6, M_MRTABLE, sizeof(*m6)); } /* * Add a mif to the mif table */ int add_m6if(struct socket *so, struct mif6ctl *mifcp) { struct inpcb *inp = sotoinpcb(so); struct mif6 *mifp; struct ifnet *ifp; struct in6_ifreq ifr; int error; unsigned int rtableid = inp->inp_rtableid; NET_ASSERT_LOCKED(); if (mifcp->mif6c_mifi >= MAXMIFS) return EINVAL; if (mrt6_iflookupbymif(mifcp->mif6c_mifi, rtableid) != NULL) return EADDRINUSE; /* XXX: is it appropriate? */ { ifp = if_get(mifcp->mif6c_pifi); if (ifp == NULL) return ENXIO; /* Make sure the interface supports multicast */ if ((ifp->if_flags & IFF_MULTICAST) == 0) { if_put(ifp); return EOPNOTSUPP; } /* * Enable promiscuous reception of all IPv6 multicasts * from the interface. */ memset(&ifr, 0, sizeof(ifr)); ifr.ifr_addr.sin6_family = AF_INET6; ifr.ifr_addr.sin6_addr = in6addr_any; KERNEL_LOCK(); error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr); KERNEL_UNLOCK(); if (error) { if_put(ifp); return error; } } mifp = malloc(sizeof(*mifp), M_MRTABLE, M_WAITOK | M_ZERO); ifp->if_mcast6 = (caddr_t)mifp; mifp->m6_mifi = mifcp->mif6c_mifi; mifp->m6_flags = mifcp->mif6c_flags; #ifdef notyet /* scaling up here allows division by 1024 in critical code */ mifp->m6_rate_limit = mifcp->mif6c_rate_limit * 1024 / 1000; #endif if_put(ifp); return 0; } /* * Delete a mif from the mif table */ int del_m6if(struct socket *so, mifi_t *mifip) { struct inpcb *inp = sotoinpcb(so); struct ifnet *ifp; NET_ASSERT_LOCKED(); if (*mifip >= MAXMIFS) return EINVAL; if ((ifp = mrt6_iflookupbymif(*mifip, inp->inp_rtableid)) == NULL) return EINVAL; ip6_mrouter_detach(ifp); return 0; } int mf6c_add_route(struct ifnet *ifp, struct sockaddr *origin, struct sockaddr *group, struct mf6cctl *mf6cc, int wait) { struct rtentry *rt; struct mf6c *mf6c; unsigned int rtableid = ifp->if_rdomain; #ifdef MCAST_DEBUG char bsrc[INET6_ADDRSTRLEN], bdst[INET6_ADDRSTRLEN]; #endif /* MCAST_DEBUG */ rt = mrt6_mcast_add(ifp, origin, group); if (rt == NULL) return ENOENT; mf6c = malloc(sizeof(*mf6c), M_MRTABLE, wait | M_ZERO); if (mf6c == NULL) { DPRINTF("origin %s group %s parent %d (%s) malloc failed", inet_ntop(AF_INET6, origin, bsrc, sizeof(bsrc)), inet_ntop(AF_INET6, group, bdst, sizeof(bdst)), mf6cc->mf6cc_parent, ifp->if_xname); mrt6_mcast_del(rt, rtableid); rtfree(rt); return ENOMEM; } rt->rt_llinfo = (caddr_t)mf6c; rt_timer_add(rt, &ip6_mrouterq, rtableid); mf6c->mf6c_parent = mf6cc->mf6cc_parent; rtfree(rt); return 0; } void mf6c_update(struct mf6cctl *mf6cc, int wait, unsigned int rtableid) { struct rtentry *rt; struct mf6c *mf6c; struct ifnet *ifp; struct sockaddr_in6 osin6, gsin6; mifi_t mifi; #ifdef MCAST_DEBUG char bdst[INET6_ADDRSTRLEN]; #endif /* MCAST_DEBUG */ memset(&osin6, 0, sizeof(osin6)); osin6.sin6_family = AF_INET6; osin6.sin6_len = sizeof(osin6); osin6.sin6_addr = mf6cc->mf6cc_origin.sin6_addr; memset(&gsin6, 0, sizeof(gsin6)); gsin6.sin6_family = AF_INET6; gsin6.sin6_len = sizeof(gsin6); gsin6.sin6_addr = mf6cc->mf6cc_mcastgrp.sin6_addr; for (mifi = 0; mifi < MAXMIFS; mifi++) { if (mifi == mf6cc->mf6cc_parent) continue; /* Test for mif existence and then update the entry. */ if ((ifp = mrt6_iflookupbymif(mifi, rtableid)) == NULL) continue; rt = mf6c_find(ifp, &mf6cc->mf6cc_origin.sin6_addr, &mf6cc->mf6cc_mcastgrp.sin6_addr, rtableid); /* mif not configured or removed. */ if (!IF_ISSET(mifi, &mf6cc->mf6cc_ifset)) { /* Route doesn't exist, nothing to do. */ if (rt == NULL) continue; DPRINTF("del route (group %s) for mif %d (%s)", inet_ntop(AF_INET6, &mf6cc->mf6cc_mcastgrp.sin6_addr, bdst, sizeof(bdst)), mifi, ifp->if_xname); mrt6_mcast_del(rt, rtableid); rtfree(rt); continue; } /* Route exists, look for changes. */ if (rt != NULL) { mf6c = (struct mf6c *)rt->rt_llinfo; /* Skip route being deleted. */ if (mf6c == NULL) { rtfree(rt); continue; } /* No new changes to apply. */ if (mf6cc->mf6cc_parent == mf6c->mf6c_parent) { rtfree(rt); continue; } DPRINTF("update route (group %s) for mif %d (%s)", inet_ntop(AF_INET6, &mf6cc->mf6cc_mcastgrp.sin6_addr, bdst, sizeof(bdst)), mifi, ifp->if_xname); mf6c->mf6c_parent = mf6cc->mf6cc_parent; rtfree(rt); continue; } DPRINTF("add route (group %s) for mif %d (%s)", inet_ntop(AF_INET6, &mf6cc->mf6cc_mcastgrp.sin6_addr, bdst, sizeof(bdst)), mifi, ifp->if_xname); mf6c_add_route(ifp, sin6tosa(&osin6), sin6tosa(&gsin6), mf6cc, wait); } /* Create route for the parent interface. */ if ((ifp = mrt6_iflookupbymif(mf6cc->mf6cc_parent, rtableid)) == NULL) { DPRINTF("failed to find upstream interface %d", mf6cc->mf6cc_parent); return; } /* We already have a route, nothing to do here. */ if ((rt = mf6c_find(ifp, &mf6cc->mf6cc_origin.sin6_addr, &mf6cc->mf6cc_mcastgrp.sin6_addr, rtableid)) != NULL) { rtfree(rt); return; } DPRINTF("add upstream route (group %s) for if %s", inet_ntop(AF_INET6, &mf6cc->mf6cc_mcastgrp.sin6_addr, bdst, sizeof(bdst)), ifp->if_xname); mf6c_add_route(ifp, sin6tosa(&osin6), sin6tosa(&gsin6), mf6cc, wait); } int mf6c_add(struct mf6cctl *mfccp, struct in6_addr *origin, struct in6_addr *group, int vidx, unsigned int rtableid, int wait) { struct ifnet *ifp; struct mif6 *m6; struct mf6cctl mf6cc; ifp = mrt6_iflookupbymif(vidx, rtableid); if (ifp == NULL || (m6 = (struct mif6 *)ifp->if_mcast6) == NULL) return ENOENT; memset(&mf6cc, 0, sizeof(mf6cc)); if (mfccp == NULL) { mf6cc.mf6cc_origin.sin6_family = AF_INET6; mf6cc.mf6cc_origin.sin6_len = sizeof(mf6cc.mf6cc_origin); mf6cc.mf6cc_origin.sin6_addr = *origin; mf6cc.mf6cc_mcastgrp.sin6_family = AF_INET6; mf6cc.mf6cc_mcastgrp.sin6_len = sizeof(mf6cc.mf6cc_mcastgrp); mf6cc.mf6cc_mcastgrp.sin6_addr = *group; mf6cc.mf6cc_parent = vidx; } else memcpy(&mf6cc, mfccp, sizeof(mf6cc)); mf6c_update(&mf6cc, wait, rtableid); return 0; } int add_m6fc(struct socket *so, struct mf6cctl *mfccp) { struct inpcb *inp = sotoinpcb(so); unsigned int rtableid = inp->inp_rtableid; NET_ASSERT_LOCKED(); return mf6c_add(mfccp, &mfccp->mf6cc_origin.sin6_addr, &mfccp->mf6cc_mcastgrp.sin6_addr, mfccp->mf6cc_parent, rtableid, M_WAITOK); } int del_m6fc(struct socket *so, struct mf6cctl *mfccp) { struct inpcb *inp = sotoinpcb(so); struct rtentry *rt; unsigned int rtableid = inp->inp_rtableid; NET_ASSERT_LOCKED(); while ((rt = mf6c_find(NULL, &mfccp->mf6cc_origin.sin6_addr, &mfccp->mf6cc_mcastgrp.sin6_addr, rtableid)) != NULL) { mrt6_mcast_del(rt, rtableid); rtfree(rt); } return 0; } int socket6_send(struct socket *so, struct mbuf *mm, struct sockaddr_in6 *src) { if (so != NULL) { int ret; mtx_enter(&so->so_rcv.sb_mtx); ret = sbappendaddr(so, &so->so_rcv, sin6tosa(src), mm, NULL); mtx_leave(&so->so_rcv.sb_mtx); if (ret != 0) { sorwakeup(so); return 0; } } m_freem(mm); return -1; } /* * IPv6 multicast forwarding function. This function assumes that the packet * pointed to by "ip6" has arrived on (or is about to be sent to) the interface * pointed to by "ifp", and the packet is to be relayed to other networks * that have members of the packet's destination IPv6 multicast group. * * The packet is returned unscathed to the caller, unless it is * erroneous, in which case a non-zero return value tells the caller to * discard it. */ int ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m) { struct rtentry *rt; struct mif6 *mifp; struct mbuf *mm; struct sockaddr_in6 sin6; unsigned int rtableid = ifp->if_rdomain; NET_ASSERT_LOCKED(); /* * Don't forward a packet with Hop limit of zero or one, * or a packet destined to a local-only group. */ if (ip6->ip6_hlim <= 1 || IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst) || IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst)) return 0; ip6->ip6_hlim--; /* * Source address check: do not forward packets with unspecified * source. It was discussed in July 2000, on ipngwg mailing list. * This is rather more serious than unicast cases, because some * MLD packets can be sent with the unspecified source address * (although such packets must normally set 1 to the hop limit field). */ if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) { ip6stat_inc(ip6s_cantforward); if (ip6_log_time + ip6_log_interval < getuptime()) { char src[INET6_ADDRSTRLEN], dst[INET6_ADDRSTRLEN]; ip6_log_time = getuptime(); inet_ntop(AF_INET6, &ip6->ip6_src, src, sizeof(src)); inet_ntop(AF_INET6, &ip6->ip6_dst, dst, sizeof(dst)); log(LOG_DEBUG, "cannot forward " "from %s to %s nxt %d received on interface %u\n", src, dst, ip6->ip6_nxt, m->m_pkthdr.ph_ifidx); } return 0; } /* * Determine forwarding mifs from the forwarding cache table */ rt = mf6c_find(NULL, &ip6->ip6_src, &ip6->ip6_dst, rtableid); /* Entry exists, so forward if necessary */ if (rt) { return (ip6_mdq(m, ifp, rt)); } else { /* * If we don't have a route for packet's origin, * Make a copy of the packet & * send message to routing daemon */ mrt6stat.mrt6s_no_route++; { struct mrt6msg *im; if ((mifp = (struct mif6 *)ifp->if_mcast6) == NULL) return EHOSTUNREACH; /* * Make a copy of the header to send to the user * level process */ mm = m_copym(m, 0, sizeof(struct ip6_hdr), M_NOWAIT); if (mm == NULL) return ENOBUFS; /* * Send message to routing daemon */ (void)memset(&sin6, 0, sizeof(sin6)); sin6.sin6_len = sizeof(sin6); sin6.sin6_family = AF_INET6; sin6.sin6_addr = ip6->ip6_src; im = NULL; switch (ip6_mrouter_ver) { case MRT6_INIT: im = mtod(mm, struct mrt6msg *); im->im6_msgtype = MRT6MSG_NOCACHE; im->im6_mbz = 0; im->im6_mif = mifp->m6_mifi; break; default: m_freem(mm); return EINVAL; } if (socket6_send(ip6_mrouter[rtableid], mm, &sin6) < 0) { log(LOG_WARNING, "ip6_mforward: ip6_mrouter " "socket queue full\n"); mrt6stat.mrt6s_upq_sockfull++; return ENOBUFS; } mrt6stat.mrt6s_upcalls++; mf6c_add(NULL, &ip6->ip6_src, &ip6->ip6_dst, mifp->m6_mifi, rtableid, M_NOWAIT); } return 0; } } void mf6c_expire_route(struct rtentry *rt, u_int rtableid) { struct mf6c *mf6c = (struct mf6c *)rt->rt_llinfo; #ifdef MCAST_DEBUG char bsrc[INET6_ADDRSTRLEN], bdst[INET6_ADDRSTRLEN]; #endif /* MCAST_DEBUG */ /* Skip entry being deleted. */ if (mf6c == NULL) return; DPRINTF("origin %s group %s interface %d expire %s", inet_ntop(AF_INET6, &satosin6(rt->rt_gateway)->sin6_addr, bsrc, sizeof(bsrc)), inet_ntop(AF_INET6, &satosin6(rt_key(rt))->sin6_addr, bdst, sizeof(bdst)), rt->rt_ifidx, mf6c->mf6c_expire ? "yes" : "no"); if (mf6c->mf6c_expire == 0) { mf6c->mf6c_expire = 1; rt_timer_add(rt, &ip6_mrouterq, rtableid); return; } mrt6_mcast_del(rt, rtableid); } /* * Packet forwarding routine once entry in the cache is made */ int ip6_mdq(struct mbuf *m, struct ifnet *ifp, struct rtentry *rt) { struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); struct mif6 *m6, *mifp = (struct mif6 *)ifp->if_mcast6; struct mf6c *mf6c = (struct mf6c *)rt->rt_llinfo; struct ifnet *ifn; int plen = m->m_pkthdr.len; if (mifp == NULL || mf6c == NULL) { rtfree(rt); return EHOSTUNREACH; } /* * Don't forward if it didn't arrive from the parent mif * for its origin. */ if (mifp->m6_mifi != mf6c->mf6c_parent) { /* came in the wrong interface */ mrt6stat.mrt6s_wrong_if++; mf6c->mf6c_wrong_if++; rtfree(rt); return 0; } /* if wrong iif */ /* If I sourced this packet, it counts as output, else it was input. */ if (m->m_pkthdr.ph_ifidx == 0) { /* XXX: is ph_ifidx really 0 when output?? */ mifp->m6_pkt_out++; mifp->m6_bytes_out += plen; } else { mifp->m6_pkt_in++; mifp->m6_bytes_in += plen; } /* * For each mif, forward a copy of the packet if there are group * members downstream on the interface. */ do { /* Don't consider non multicast routes. */ if (ISSET(rt->rt_flags, RTF_HOST | RTF_MULTICAST) != (RTF_HOST | RTF_MULTICAST)) continue; mf6c = (struct mf6c *)rt->rt_llinfo; if (mf6c == NULL) continue; mf6c->mf6c_pkt_cnt++; mf6c->mf6c_byte_cnt += m->m_pkthdr.len; /* Don't let this route expire. */ mf6c->mf6c_expire = 0; if ((ifn = if_get(rt->rt_ifidx)) == NULL) continue; /* Sanity check: did we configure this? */ if ((m6 = (struct mif6 *)ifn->if_mcast6) == NULL) { if_put(ifn); continue; } /* Don't send in the upstream interface. */ if (mf6c->mf6c_parent == m6->m6_mifi) { if_put(ifn); continue; } /* * check if the outgoing packet is going to break * a scope boundary. */ if ((mifp->m6_flags & MIFF_REGISTER) == 0 && (m6->m6_flags & MIFF_REGISTER) == 0 && (in6_addr2scopeid(ifp->if_index, &ip6->ip6_dst) != in6_addr2scopeid(ifn->if_index, &ip6->ip6_dst) || in6_addr2scopeid(ifp->if_index, &ip6->ip6_src) != in6_addr2scopeid(ifn->if_index, &ip6->ip6_src))) { if_put(ifn); ip6stat_inc(ip6s_badscope); continue; } m6->m6_pkt_out++; m6->m6_bytes_out += plen; phyint_send6(ifn, ip6, m); if_put(ifn); } while ((rt = rtable_iterate(rt)) != NULL); return 0; } void phyint_send6(struct ifnet *ifp, struct ip6_hdr *ip6, struct mbuf *m) { struct mbuf *mb_copy; struct sockaddr_in6 *dst6, sin6; int error = 0; NET_ASSERT_LOCKED(); /* * Make a new reference to the packet; make sure that * the IPv6 header is actually copied, not just referenced, * so that ip6_output() only scribbles on the copy. */ mb_copy = m_dup_pkt(m, max_linkhdr, M_NOWAIT); if (mb_copy == NULL) return; /* set MCAST flag to the outgoing packet */ mb_copy->m_flags |= M_MCAST; /* * If we sourced the packet, call ip6_output since we may divide * the packet into fragments when the packet is too big for the * outgoing interface. * Otherwise, we can simply send the packet to the interface * sending queue. */ if (m->m_pkthdr.ph_ifidx == 0) { struct ip6_moptions im6o; im6o.im6o_ifidx = ifp->if_index; /* XXX: ip6_output will override ip6->ip6_hlim */ im6o.im6o_hlim = ip6->ip6_hlim; im6o.im6o_loop = 1; error = ip6_output(mb_copy, NULL, NULL, IPV6_FORWARDING, &im6o, NULL); return; } /* * If we belong to the destination multicast group * on the outgoing interface, loop back a copy. */ dst6 = &sin6; memset(&sin6, 0, sizeof(sin6)); if (in6_hasmulti(&ip6->ip6_dst, ifp)) { dst6->sin6_len = sizeof(struct sockaddr_in6); dst6->sin6_family = AF_INET6; dst6->sin6_addr = ip6->ip6_dst; ip6_mloopback(ifp, m, dst6); } /* * Put the packet into the sending queue of the outgoing interface * if it would fit in the MTU of the interface. */ if (mb_copy->m_pkthdr.len <= ifp->if_mtu || ifp->if_mtu < IPV6_MMTU) { dst6->sin6_len = sizeof(struct sockaddr_in6); dst6->sin6_family = AF_INET6; dst6->sin6_addr = ip6->ip6_dst; error = ifp->if_output(ifp, mb_copy, sin6tosa(dst6), NULL); } else { if (ip6_mcast_pmtu) icmp6_error(mb_copy, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu); else { m_freem(mb_copy); /* simply discard the packet */ } } } struct ifnet * mrt6_iflookupbymif(mifi_t mifi, unsigned int rtableid) { struct mif6 *m6; struct ifnet *ifp; TAILQ_FOREACH(ifp, &ifnetlist, if_list) { if (ifp->if_rdomain != rtableid) continue; if ((m6 = (struct mif6 *)ifp->if_mcast6) == NULL) continue; if (m6->m6_mifi != mifi) continue; return ifp; } return NULL; } struct rtentry * mf6c_find(struct ifnet *ifp, struct in6_addr *origin, struct in6_addr *group, unsigned int rtableid) { struct rtentry *rt; struct sockaddr_in6 msin6; memset(&msin6, 0, sizeof(msin6)); msin6.sin6_family = AF_INET6; msin6.sin6_len = sizeof(msin6); msin6.sin6_addr = *group; rt = rtalloc(sin6tosa(&msin6), 0, rtableid); do { if (!rtisvalid(rt)) { rtfree(rt); return NULL; } if (ISSET(rt->rt_flags, RTF_HOST | RTF_MULTICAST) != (RTF_HOST | RTF_MULTICAST)) continue; /* Return first occurrence if interface is not specified. */ if (ifp == NULL) return rt; if (rt->rt_ifidx == ifp->if_index) return rt; } while ((rt = rtable_iterate(rt)) != NULL); return NULL; } struct rtentry * mrt6_mcast_add(struct ifnet *ifp, struct sockaddr *origin, struct sockaddr *group) { struct ifaddr *ifa; int rv; unsigned int rtableid = ifp->if_rdomain; TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family == AF_INET6) break; } if (ifa == NULL) { DPRINTF("ifa == NULL"); return NULL; } rv = rt_ifa_add(ifa, RTF_HOST | RTF_MULTICAST | RTF_MPATH, group, ifp->if_rdomain); if (rv != 0) { DPRINTF("rt_ifa_add failed %d", rv); return NULL; } return mf6c_find(ifp, NULL, &satosin6(group)->sin6_addr, rtableid); } void mrt6_mcast_del(struct rtentry *rt, unsigned int rtableid) { struct ifnet *ifp; int error; /* Remove all timers related to this route. */ rt_timer_remove_all(rt); free(rt->rt_llinfo, M_MRTABLE, sizeof(struct mf6c)); rt->rt_llinfo = NULL; ifp = if_get(rt->rt_ifidx); if (ifp == NULL) return; error = rtdeletemsg(rt, ifp, rtableid); if_put(ifp); if (error) DPRINTF("delete route error %d\n", error); }
382 44 43 21 41 27 1 26 22 25 20 14 1 2 2 352 2 2 5 13 7 5 3 1 317 4 171 172 307 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 /* $OpenBSD: uipc_domain.c,v 1.65 2024/01/11 14:15:11 bluhm Exp $ */ /* $NetBSD: uipc_domain.c,v 1.14 1996/02/09 19:00:44 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)uipc_domain.c 8.2 (Berkeley) 10/18/93 */ #include <sys/param.h> #include <sys/socket.h> #include <sys/protosw.h> #include <sys/domain.h> #include <sys/mbuf.h> #include <sys/systm.h> #include <sys/sysctl.h> #include <sys/timeout.h> #include "bpfilter.h" #include "pflow.h" const struct domain *const domains[] = { #ifdef MPLS &mplsdomain, #endif #if defined (IPSEC) || defined (TCP_SIGNATURE) &pfkeydomain, #endif #ifdef INET6 &inet6domain, #endif /* INET6 */ &inetdomain, &unixdomain, &routedomain, NULL }; void pffasttimo(void *); void pfslowtimo(void *); void domaininit(void) { const struct domain *dp; const struct protosw *pr; static struct timeout pffast_timeout; static struct timeout pfslow_timeout; int i; for (i = 0; (dp = domains[i]) != NULL; i++) { if (dp->dom_init) (*dp->dom_init)(); for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) if (pr->pr_init) (*pr->pr_init)(); } /* * max_linkhdr of 64 was chosen to encompass tunnelling * traffic in IP payloads, eg, by etherip(4) or gif(4), * without needing to prepend an mbuf to fit those * headers. */ if (max_linkhdr < 64) max_linkhdr = 64; max_hdr = max_linkhdr + max_protohdr; timeout_set_proc(&pffast_timeout, pffasttimo, &pffast_timeout); timeout_set_proc(&pfslow_timeout, pfslowtimo, &pfslow_timeout); timeout_add(&pffast_timeout, 1); timeout_add(&pfslow_timeout, 1); } const struct domain * pffinddomain(int family) { const struct domain *dp; int i; for (i = 0; (dp = domains[i]) != NULL; i++) { if (dp->dom_family == family) return (dp); } return (NULL); } const struct protosw * pffindtype(int family, int type) { const struct domain *dp; const struct protosw *pr; dp = pffinddomain(family); if (dp == NULL) return (NULL); for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) if (pr->pr_type && pr->pr_type == type) return (pr); return (NULL); } const struct protosw * pffindproto(int family, int protocol, int type) { const struct domain *dp; const struct protosw *pr; const struct protosw *maybe = NULL; if (family == PF_UNSPEC) return (NULL); dp = pffinddomain(family); if (dp == NULL) return (NULL); for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) { if ((pr->pr_protocol == protocol) && (pr->pr_type == type)) return (pr); if (type == SOCK_RAW && pr->pr_type == SOCK_RAW && pr->pr_protocol == 0 && maybe == NULL) maybe = pr; } return (maybe); } static int net_link_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int node; int error; /* * All sysctl names at this level are nonterminal. */ if (namelen < 2) return (EISDIR); /* overloaded */ node = name[0]; namelen--; name++; switch (node) { case NET_LINK_IFRXQ: error = net_ifiq_sysctl(name, namelen, oldp, oldlenp, newp, newlen); break; default: error = ENOPROTOOPT; break; } return (error); } int net_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { const struct domain *dp; const struct protosw *pr; int family, protocol; /* * All sysctl names at this level are nonterminal. * Usually: next two components are protocol family and protocol * number, then at least one addition component. */ if (namelen < 2) return (EISDIR); /* overloaded */ family = name[0]; if (family == PF_UNSPEC) return (0); if (family == PF_LINK) return (net_link_sysctl(name + 1, namelen - 1, oldp, oldlenp, newp, newlen)); if (family == PF_UNIX) return (uipc_sysctl(name + 1, namelen - 1, oldp, oldlenp, newp, newlen)); #if NBPFILTER > 0 if (family == PF_BPF) return (bpf_sysctl(name + 1, namelen - 1, oldp, oldlenp, newp, newlen)); #endif #if NPFLOW > 0 if (family == PF_PFLOW) return (pflow_sysctl(name + 1, namelen - 1, oldp, oldlenp, newp, newlen)); #endif #ifdef PIPEX if (family == PF_PIPEX) return (pipex_sysctl(name + 1, namelen - 1, oldp, oldlenp, newp, newlen)); #endif #ifdef MPLS if (family == PF_MPLS) return (mpls_sysctl(name + 1, namelen - 1, oldp, oldlenp, newp, newlen)); #endif dp = pffinddomain(family); if (dp == NULL) return (ENOPROTOOPT); if (namelen < 3) return (EISDIR); /* overloaded */ protocol = name[1]; for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) if (pr->pr_protocol == protocol && pr->pr_sysctl) return ((*pr->pr_sysctl)(name + 2, namelen - 2, oldp, oldlenp, newp, newlen)); return (ENOPROTOOPT); } void pfctlinput(int cmd, struct sockaddr *sa) { const struct domain *dp; const struct protosw *pr; int i; NET_ASSERT_LOCKED(); for (i = 0; (dp = domains[i]) != NULL; i++) { for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) if (pr->pr_ctlinput) (*pr->pr_ctlinput)(cmd, sa, 0, NULL); } } void pfslowtimo(void *arg) { struct timeout *to = (struct timeout *)arg; const struct domain *dp; const struct protosw *pr; int i; for (i = 0; (dp = domains[i]) != NULL; i++) { for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) if (pr->pr_slowtimo) (*pr->pr_slowtimo)(); } timeout_add_msec(to, 500); } void pffasttimo(void *arg) { struct timeout *to = (struct timeout *)arg; const struct domain *dp; const struct protosw *pr; int i; for (i = 0; (dp = domains[i]) != NULL; i++) { for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) if (pr->pr_fasttimo) (*pr->pr_fasttimo)(); } timeout_add_msec(to, 200); }
2 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 /* $OpenBSD: kern_watchdog.c,v 1.16 2022/08/14 01:58:27 jsg Exp $ */ /* * Copyright (c) 2003 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/timeout.h> #include <sys/sysctl.h> void wdog_tickle(void *arg); int (*wdog_ctl_cb)(void *, int) = NULL; void *wdog_ctl_cb_arg = NULL; int wdog_period = 0; int wdog_auto = 1; struct timeout wdog_timeout; void wdog_register(int (*cb)(void *, int), void *cb_arg) { if (wdog_ctl_cb != NULL) return; wdog_ctl_cb = cb; wdog_ctl_cb_arg = cb_arg; timeout_set(&wdog_timeout, wdog_tickle, NULL); } void wdog_tickle(void *arg) { if (wdog_ctl_cb == NULL) return; (void) (*wdog_ctl_cb)(wdog_ctl_cb_arg, wdog_period); timeout_add_msec(&wdog_timeout, wdog_period * 1000 / 2); } void wdog_shutdown(void *arg) { if (wdog_ctl_cb == NULL || wdog_ctl_cb_arg != arg) return; timeout_del(&wdog_timeout); (void) (*wdog_ctl_cb)(wdog_ctl_cb_arg, 0); wdog_ctl_cb = NULL; wdog_period = 0; wdog_auto = 1; } int sysctl_wdog(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int error, period; if (wdog_ctl_cb == NULL) return (EOPNOTSUPP); switch (name[0]) { case KERN_WATCHDOG_PERIOD: period = wdog_period; error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &period, 0, INT_MAX); if (error) return (error); if (newp) { timeout_del(&wdog_timeout); wdog_period = (*wdog_ctl_cb)(wdog_ctl_cb_arg, period); } break; case KERN_WATCHDOG_AUTO: error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &wdog_auto, 0, 1); if (error) return (error); break; default: return (EINVAL); } if (wdog_auto && wdog_period > 0) { (void) (*wdog_ctl_cb)(wdog_ctl_cb_arg, wdog_period); timeout_add_msec(&wdog_timeout, wdog_period * 1000 / 2); } else timeout_del(&wdog_timeout); return (error); }
3 1 3 5 2 5 5 2 1 2 2 1 2 5 5 5 5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 /* $OpenBSD: dt_dev.c,v 1.33 2024/04/06 11:18:02 mpi Exp $ */ /* * Copyright (c) 2019 Martin Pieuchot <mpi@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/types.h> #include <sys/systm.h> #include <sys/param.h> #include <sys/clockintr.h> #include <sys/device.h> #include <sys/exec_elf.h> #include <sys/malloc.h> #include <sys/proc.h> #include <sys/ptrace.h> #include <dev/dt/dtvar.h> /* * Number of frames to skip in stack traces. * * The number of frames required to execute dt(4) profiling code * depends on the probe, context, architecture and possibly the * compiler. * * Static probes (tracepoints) are executed in the context of the * current thread and only need to skip frames up to the recording * function. For example the syscall provider: * * dt_prov_syscall_entry+0x141 * syscall+0x205 <--- start here * Xsyscall+0x128 * * Probes executed in their own context, like the profile provider, * need to skip the frames of that context which are different for * every architecture. For example the profile provider executed * from hardclock(9) on amd64: * * dt_prov_profile_enter+0x6e * hardclock+0x1a9 * lapic_clockintr+0x3f * Xresume_lapic_ltimer+0x26 * acpicpu_idle+0x1d2 <---- start here. * sched_idle+0x225 * proc_trampoline+0x1c */ #if defined(__amd64__) #define DT_FA_PROFILE 5 #define DT_FA_STATIC 2 #elif defined(__i386__) #define DT_FA_PROFILE 5 #define DT_FA_STATIC 2 #elif defined(__macppc__) #define DT_FA_PROFILE 5 #define DT_FA_STATIC 2 #elif defined(__octeon__) #define DT_FA_PROFILE 6 #define DT_FA_STATIC 2 #elif defined(__powerpc64__) #define DT_FA_PROFILE 6 #define DT_FA_STATIC 2 #elif defined(__sparc64__) #define DT_FA_PROFILE 7 #define DT_FA_STATIC 1 #else #define DT_FA_STATIC 0 #define DT_FA_PROFILE 0 #endif #define DT_EVTRING_SIZE 16 /* # of slots in per PCB event ring */ #define DPRINTF(x...) /* nothing */ /* * Descriptor associated with each program opening /dev/dt. It is used * to keep track of enabled PCBs. * * Locks used to protect struct members in this file: * m per-softc mutex * K kernel lock */ struct dt_softc { SLIST_ENTRY(dt_softc) ds_next; /* [K] descriptor list */ int ds_unit; /* [I] D_CLONE unique unit */ pid_t ds_pid; /* [I] PID of tracing program */ struct mutex ds_mtx; struct dt_pcb_list ds_pcbs; /* [K] list of enabled PCBs */ struct dt_evt *ds_bufqueue; /* [K] copy evts to userland */ size_t ds_bufqlen; /* [K] length of the queue */ int ds_recording; /* [K] currently recording? */ int ds_evtcnt; /* [m] # of readable evts */ /* Counters */ uint64_t ds_readevt; /* [m] # of events read */ uint64_t ds_dropevt; /* [m] # of events dropped */ }; SLIST_HEAD(, dt_softc) dtdev_list; /* [K] list of open /dev/dt nodes */ /* * Probes are created during dt_attach() and never modified/freed during * the lifetime of the system. That's why we consider them as [I]mmutable. */ unsigned int dt_nprobes; /* [I] # of probes available */ SIMPLEQ_HEAD(, dt_probe) dt_probe_list; /* [I] list of probes */ struct rwlock dt_lock = RWLOCK_INITIALIZER("dtlk"); volatile uint32_t dt_tracing = 0; /* [K] # of processes tracing */ int allowdt; void dtattach(struct device *, struct device *, void *); int dtopen(dev_t, int, int, struct proc *); int dtclose(dev_t, int, int, struct proc *); int dtread(dev_t, struct uio *, int); int dtioctl(dev_t, u_long, caddr_t, int, struct proc *); struct dt_softc *dtlookup(int); int dt_ioctl_list_probes(struct dt_softc *, struct dtioc_probe *); int dt_ioctl_get_args(struct dt_softc *, struct dtioc_arg *); int dt_ioctl_get_stats(struct dt_softc *, struct dtioc_stat *); int dt_ioctl_record_start(struct dt_softc *); void dt_ioctl_record_stop(struct dt_softc *); int dt_ioctl_probe_enable(struct dt_softc *, struct dtioc_req *); int dt_ioctl_probe_disable(struct dt_softc *, struct dtioc_req *); int dt_ioctl_get_auxbase(struct dt_softc *, struct dtioc_getaux *); int dt_pcb_ring_copy(struct dt_pcb *, struct dt_evt *, size_t, uint64_t *); void dtattach(struct device *parent, struct device *self, void *aux) { SLIST_INIT(&dtdev_list); SIMPLEQ_INIT(&dt_probe_list); /* Init providers */ dt_nprobes += dt_prov_profile_init(); dt_nprobes += dt_prov_syscall_init(); dt_nprobes += dt_prov_static_init(); #ifdef DDBPROF dt_nprobes += dt_prov_kprobe_init(); #endif } int dtopen(dev_t dev, int flags, int mode, struct proc *p) { struct dt_softc *sc; struct dt_evt *queue; size_t qlen; int unit = minor(dev); if (!allowdt) return EPERM; sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_CANFAIL|M_ZERO); if (sc == NULL) return ENOMEM; /* * Enough space to empty 2 full rings of events in a single read. */ qlen = 2 * DT_EVTRING_SIZE; queue = mallocarray(qlen, sizeof(*queue), M_DEVBUF, M_WAITOK|M_CANFAIL); if (queue == NULL) { free(sc, M_DEVBUF, sizeof(*sc)); return ENOMEM; } /* no sleep after this point */ if (dtlookup(unit) != NULL) { free(queue, M_DEVBUF, qlen * sizeof(*queue)); free(sc, M_DEVBUF, sizeof(*sc)); return EBUSY; } sc->ds_unit = unit; sc->ds_pid = p->p_p->ps_pid; TAILQ_INIT(&sc->ds_pcbs); mtx_init(&sc->ds_mtx, IPL_HIGH); sc->ds_bufqlen = qlen; sc->ds_bufqueue = queue; sc->ds_evtcnt = 0; sc->ds_readevt = 0; sc->ds_dropevt = 0; SLIST_INSERT_HEAD(&dtdev_list, sc, ds_next); DPRINTF("dt%d: pid %d open\n", sc->ds_unit, sc->ds_pid); return 0; } int dtclose(dev_t dev, int flags, int mode, struct proc *p) { struct dt_softc *sc; int unit = minor(dev); sc = dtlookup(unit); KASSERT(sc != NULL); DPRINTF("dt%d: pid %d close\n", sc->ds_unit, sc->ds_pid); SLIST_REMOVE(&dtdev_list, sc, dt_softc, ds_next); dt_ioctl_record_stop(sc); dt_pcb_purge(&sc->ds_pcbs); free(sc->ds_bufqueue, M_DEVBUF, sc->ds_bufqlen * sizeof(*sc->ds_bufqueue)); free(sc, M_DEVBUF, sizeof(*sc)); return 0; } int dtread(dev_t dev, struct uio *uio, int flags) { struct dt_softc *sc; struct dt_evt *estq; struct dt_pcb *dp; int error = 0, unit = minor(dev); size_t qlen, count, read = 0; uint64_t dropped = 0; sc = dtlookup(unit); KASSERT(sc != NULL); count = howmany(uio->uio_resid, sizeof(struct dt_evt)); if (count < 1) return (EMSGSIZE); while (!sc->ds_evtcnt) { sleep_setup(sc, PWAIT | PCATCH, "dtread"); error = sleep_finish(0, !sc->ds_evtcnt); if (error == EINTR || error == ERESTART) break; } if (error) return error; estq = sc->ds_bufqueue; qlen = MIN(sc->ds_bufqlen, count); KERNEL_ASSERT_LOCKED(); TAILQ_FOREACH(dp, &sc->ds_pcbs, dp_snext) { count = dt_pcb_ring_copy(dp, estq, qlen, &dropped); read += count; estq += count; /* pointer arithmetic */ qlen -= count; if (qlen == 0) break; } if (read > 0) uiomove(sc->ds_bufqueue, read * sizeof(struct dt_evt), uio); mtx_enter(&sc->ds_mtx); sc->ds_evtcnt -= read; sc->ds_readevt += read; sc->ds_dropevt += dropped; mtx_leave(&sc->ds_mtx); return 0; } int dtioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { struct dt_softc *sc; int unit = minor(dev); int on, error = 0; sc = dtlookup(unit); KASSERT(sc != NULL); switch (cmd) { case DTIOCGPLIST: return dt_ioctl_list_probes(sc, (struct dtioc_probe *)addr); case DTIOCGARGS: return dt_ioctl_get_args(sc, (struct dtioc_arg *)addr); case DTIOCGSTATS: return dt_ioctl_get_stats(sc, (struct dtioc_stat *)addr); case DTIOCRECORD: case DTIOCPRBENABLE: case DTIOCPRBDISABLE: case DTIOCGETAUXBASE: /* root only ioctl(2) */ break; default: return ENOTTY; } if ((error = suser(p)) != 0) return error; switch (cmd) { case DTIOCRECORD: on = *(int *)addr; if (on) error = dt_ioctl_record_start(sc); else dt_ioctl_record_stop(sc); break; case DTIOCPRBENABLE: error = dt_ioctl_probe_enable(sc, (struct dtioc_req *)addr); break; case DTIOCPRBDISABLE: error = dt_ioctl_probe_disable(sc, (struct dtioc_req *)addr); break; case DTIOCGETAUXBASE: error = dt_ioctl_get_auxbase(sc, (struct dtioc_getaux *)addr); break; default: KASSERT(0); } return error; } struct dt_softc * dtlookup(int unit) { struct dt_softc *sc; KERNEL_ASSERT_LOCKED(); SLIST_FOREACH(sc, &dtdev_list, ds_next) { if (sc->ds_unit == unit) break; } return sc; } int dt_ioctl_list_probes(struct dt_softc *sc, struct dtioc_probe *dtpr) { struct dtioc_probe_info info, *dtpi; struct dt_probe *dtp; size_t size; int error = 0; size = dtpr->dtpr_size; dtpr->dtpr_size = dt_nprobes * sizeof(*dtpi); if (size == 0) return 0; dtpi = dtpr->dtpr_probes; SIMPLEQ_FOREACH(dtp, &dt_probe_list, dtp_next) { if (size < sizeof(*dtpi)) { error = ENOSPC; break; } memset(&info, 0, sizeof(info)); info.dtpi_pbn = dtp->dtp_pbn; info.dtpi_nargs = dtp->dtp_nargs; strlcpy(info.dtpi_prov, dtp->dtp_prov->dtpv_name, sizeof(info.dtpi_prov)); strlcpy(info.dtpi_func, dtp->dtp_func, sizeof(info.dtpi_func)); strlcpy(info.dtpi_name, dtp->dtp_name, sizeof(info.dtpi_name)); error = copyout(&info, dtpi, sizeof(*dtpi)); if (error) break; size -= sizeof(*dtpi); dtpi++; } return error; } int dt_ioctl_get_args(struct dt_softc *sc, struct dtioc_arg *dtar) { struct dtioc_arg_info info, *dtai; struct dt_probe *dtp; size_t size, n, t; uint32_t pbn; int error = 0; pbn = dtar->dtar_pbn; if (pbn == 0 || pbn > dt_nprobes) return EINVAL; SIMPLEQ_FOREACH(dtp, &dt_probe_list, dtp_next) { if (pbn == dtp->dtp_pbn) break; } if (dtp == NULL) return EINVAL; if (dtp->dtp_sysnum != 0) { /* currently not supported for system calls */ dtar->dtar_size = 0; return 0; } size = dtar->dtar_size; dtar->dtar_size = dtp->dtp_nargs * sizeof(*dtar); if (size == 0) return 0; t = 0; dtai = dtar->dtar_args; for (n = 0; n < dtp->dtp_nargs; n++) { if (size < sizeof(*dtai)) { error = ENOSPC; break; } if (n >= DTMAXARGTYPES || dtp->dtp_argtype[n] == NULL) continue; memset(&info, 0, sizeof(info)); info.dtai_pbn = dtp->dtp_pbn; info.dtai_argn = t++; strlcpy(info.dtai_argtype, dtp->dtp_argtype[n], sizeof(info.dtai_argtype)); error = copyout(&info, dtai, sizeof(*dtai)); if (error) break; size -= sizeof(*dtai); dtai++; } dtar->dtar_size = t * sizeof(*dtar); return error; } int dt_ioctl_get_stats(struct dt_softc *sc, struct dtioc_stat *dtst) { mtx_enter(&sc->ds_mtx); dtst->dtst_readevt = sc->ds_readevt; dtst->dtst_dropevt = sc->ds_dropevt; mtx_leave(&sc->ds_mtx); return 0; } int dt_ioctl_record_start(struct dt_softc *sc) { uint64_t now; struct dt_pcb *dp; if (sc->ds_recording) return EBUSY; KERNEL_ASSERT_LOCKED(); if (TAILQ_EMPTY(&sc->ds_pcbs)) return ENOENT; rw_enter_write(&dt_lock); now = nsecuptime(); TAILQ_FOREACH(dp, &sc->ds_pcbs, dp_snext) { struct dt_probe *dtp = dp->dp_dtp; SMR_SLIST_INSERT_HEAD_LOCKED(&dtp->dtp_pcbs, dp, dp_pnext); dtp->dtp_recording++; dtp->dtp_prov->dtpv_recording++; if (dp->dp_nsecs != 0) { clockintr_bind(&dp->dp_clockintr, dp->dp_cpu, dt_clock, dp); clockintr_schedule(&dp->dp_clockintr, now + dp->dp_nsecs); } } rw_exit_write(&dt_lock); sc->ds_recording = 1; dt_tracing++; return 0; } void dt_ioctl_record_stop(struct dt_softc *sc) { struct dt_pcb *dp; if (!sc->ds_recording) return; DPRINTF("dt%d: pid %d disable\n", sc->ds_unit, sc->ds_pid); dt_tracing--; sc->ds_recording = 0; rw_enter_write(&dt_lock); TAILQ_FOREACH(dp, &sc->ds_pcbs, dp_snext) { struct dt_probe *dtp = dp->dp_dtp; /* * Set an execution barrier to ensure the shared * reference to dp is inactive. */ if (dp->dp_nsecs != 0) clockintr_unbind(&dp->dp_clockintr, CL_BARRIER); dtp->dtp_recording--; dtp->dtp_prov->dtpv_recording--; SMR_SLIST_REMOVE_LOCKED(&dtp->dtp_pcbs, dp, dt_pcb, dp_pnext); } rw_exit_write(&dt_lock); /* Wait until readers cannot access the PCBs. */ smr_barrier(); } int dt_ioctl_probe_enable(struct dt_softc *sc, struct dtioc_req *dtrq) { struct dt_pcb_list plist; struct dt_probe *dtp; int error; SIMPLEQ_FOREACH(dtp, &dt_probe_list, dtp_next) { if (dtp->dtp_pbn == dtrq->dtrq_pbn) break; } if (dtp == NULL) return ENOENT; TAILQ_INIT(&plist); error = dtp->dtp_prov->dtpv_alloc(dtp, sc, &plist, dtrq); if (error) return error; DPRINTF("dt%d: pid %d enable %u : %b\n", sc->ds_unit, sc->ds_pid, dtrq->dtrq_pbn, (unsigned int)dtrq->dtrq_evtflags, DTEVT_FLAG_BITS); /* Append all PCBs to this instance */ TAILQ_CONCAT(&sc->ds_pcbs, &plist, dp_snext); return 0; } int dt_ioctl_probe_disable(struct dt_softc *sc, struct dtioc_req *dtrq) { struct dt_probe *dtp; int error; SIMPLEQ_FOREACH(dtp, &dt_probe_list, dtp_next) { if (dtp->dtp_pbn == dtrq->dtrq_pbn) break; } if (dtp == NULL) return ENOENT; if (dtp->dtp_prov->dtpv_dealloc) { error = dtp->dtp_prov->dtpv_dealloc(dtp, sc, dtrq); if (error) return error; } DPRINTF("dt%d: pid %d dealloc\n", sc->ds_unit, sc->ds_pid, dtrq->dtrq_pbn); return 0; } int dt_ioctl_get_auxbase(struct dt_softc *sc, struct dtioc_getaux *dtga) { struct uio uio; struct iovec iov; struct process *pr; struct proc *p = curproc; AuxInfo auxv[ELF_AUX_ENTRIES]; int i, error; dtga->dtga_auxbase = 0; if ((pr = prfind(dtga->dtga_pid)) == NULL) return ESRCH; iov.iov_base = auxv; iov.iov_len = sizeof(auxv); uio.uio_iov = &iov; uio.uio_iovcnt = 1; uio.uio_offset = pr->ps_auxinfo; uio.uio_resid = sizeof(auxv); uio.uio_segflg = UIO_SYSSPACE; uio.uio_procp = p; uio.uio_rw = UIO_READ; error = process_domem(p, pr, &uio, PT_READ_D); if (error) return error; for (i = 0; i < ELF_AUX_ENTRIES; i++) if (auxv[i].au_id == AUX_base) dtga->dtga_auxbase = auxv[i].au_v; return 0; } struct dt_probe * dt_dev_alloc_probe(const char *func, const char *name, struct dt_provider *dtpv) { struct dt_probe *dtp; dtp = malloc(sizeof(*dtp), M_DT, M_NOWAIT|M_ZERO); if (dtp == NULL) return NULL; SMR_SLIST_INIT(&dtp->dtp_pcbs); dtp->dtp_prov = dtpv; dtp->dtp_func = func; dtp->dtp_name = name; dtp->dtp_sysnum = -1; dtp->dtp_ref = 0; return dtp; } void dt_dev_register_probe(struct dt_probe *dtp) { static uint64_t probe_nb; dtp->dtp_pbn = ++probe_nb; SIMPLEQ_INSERT_TAIL(&dt_probe_list, dtp, dtp_next); } struct dt_pcb * dt_pcb_alloc(struct dt_probe *dtp, struct dt_softc *sc) { struct dt_pcb *dp; dp = malloc(sizeof(*dp), M_DT, M_WAITOK|M_CANFAIL|M_ZERO); if (dp == NULL) goto bad; dp->dp_ring = mallocarray(DT_EVTRING_SIZE, sizeof(*dp->dp_ring), M_DT, M_WAITOK|M_CANFAIL|M_ZERO); if (dp->dp_ring == NULL) goto bad; mtx_init(&dp->dp_mtx, IPL_HIGH); dp->dp_sc = sc; dp->dp_dtp = dtp; return dp; bad: dt_pcb_free(dp); return NULL; } void dt_pcb_free(struct dt_pcb *dp) { if (dp == NULL) return; free(dp->dp_ring, M_DT, DT_EVTRING_SIZE * sizeof(*dp->dp_ring)); free(dp, M_DT, sizeof(*dp)); } void dt_pcb_purge(struct dt_pcb_list *plist) { struct dt_pcb *dp; while ((dp = TAILQ_FIRST(plist)) != NULL) { TAILQ_REMOVE(plist, dp, dp_snext); dt_pcb_free(dp); } } /* * Get a reference to the next free event state from the ring. */ struct dt_evt * dt_pcb_ring_get(struct dt_pcb *dp, int profiling) { struct proc *p = curproc; struct dt_evt *dtev; int distance; mtx_enter(&dp->dp_mtx); distance = dp->dp_prod - dp->dp_cons; if (distance == 1 || distance == (1 - DT_EVTRING_SIZE)) { /* read(2) isn't finished */ dp->dp_dropevt++; mtx_leave(&dp->dp_mtx); return NULL; } /* * Save states in next free event slot. */ dtev = &dp->dp_ring[dp->dp_cons]; memset(dtev, 0, sizeof(*dtev)); dtev->dtev_pbn = dp->dp_dtp->dtp_pbn; dtev->dtev_cpu = cpu_number(); dtev->dtev_pid = p->p_p->ps_pid; dtev->dtev_tid = p->p_tid + THREAD_PID_OFFSET; nanotime(&dtev->dtev_tsp); if (ISSET(dp->dp_evtflags, DTEVT_EXECNAME)) strlcpy(dtev->dtev_comm, p->p_p->ps_comm, sizeof(dtev->dtev_comm)); if (ISSET(dp->dp_evtflags, DTEVT_KSTACK)) { if (profiling) stacktrace_save_at(&dtev->dtev_kstack, DT_FA_PROFILE); else stacktrace_save_at(&dtev->dtev_kstack, DT_FA_STATIC); } if (ISSET(dp->dp_evtflags, DTEVT_USTACK)) stacktrace_save_utrace(&dtev->dtev_ustack); return dtev; } void dt_pcb_ring_consume(struct dt_pcb *dp, struct dt_evt *dtev) { MUTEX_ASSERT_LOCKED(&dp->dp_mtx); KASSERT(dtev == &dp->dp_ring[dp->dp_cons]); dp->dp_cons = (dp->dp_cons + 1) % DT_EVTRING_SIZE; mtx_leave(&dp->dp_mtx); mtx_enter(&dp->dp_sc->ds_mtx); dp->dp_sc->ds_evtcnt++; mtx_leave(&dp->dp_sc->ds_mtx); wakeup(dp->dp_sc); } /* * Copy at most `qlen' events from `dp', producing the same amount * of free slots. */ int dt_pcb_ring_copy(struct dt_pcb *dp, struct dt_evt *estq, size_t qlen, uint64_t *dropped) { size_t count, copied = 0; unsigned int cons, prod; KASSERT(qlen > 0); mtx_enter(&dp->dp_mtx); cons = dp->dp_cons; prod = dp->dp_prod; if (cons < prod) count = DT_EVTRING_SIZE - prod; else count = cons - prod; if (count == 0) goto out; *dropped += dp->dp_dropevt; dp->dp_dropevt = 0; count = MIN(count, qlen); memcpy(&estq[0], &dp->dp_ring[prod], count * sizeof(*estq)); copied += count; /* Produce */ prod = (prod + count) % DT_EVTRING_SIZE; /* If the queue is full or the ring didn't wrap, stop here. */ if (qlen == copied || prod != 0 || cons == 0) goto out; count = MIN(cons, (qlen - copied)); memcpy(&estq[copied], &dp->dp_ring[0], count * sizeof(*estq)); copied += count; prod += count; out: dp->dp_prod = prod; mtx_leave(&dp->dp_mtx); return copied; }
104 104 104 104 104 104 102 102 101 102 102 73 73 73 53 54 17 40 54 54 54 49 8 17 1 30 49 49 49 49 49 19 19 19 19 10 1 10 10 10 10 3 19 171 11 13 168 16 121 26 93 7 4 7 84 155 239 102 12 37 88 73 88 26 57 58 31 4 56 73 73 129 129 129 129 81 56 71 7 7 71 71 52 53 86 85 86 43 70 86 49 49 48 49 49 49 49 49 49 19 31 49 107 107 32 32 32 88 88 88 88 87 88 9 43 43 43 43 43 39 24 9 34 121 121 121 106 27 27 122 69 122 106 106 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 /* $OpenBSD: ffs_alloc.c,v 1.115 2024/02/03 18:51:58 beck Exp $ */ /* $NetBSD: ffs_alloc.c,v 1.11 1996/05/11 18:27:09 mycroft Exp $ */ /* * Copyright (c) 2002 Networks Associates Technology, Inc. * All rights reserved. * * This software was developed for the FreeBSD Project by Marshall * Kirk McKusick and Network Associates Laboratories, the Security * Research Division of Network Associates, Inc. under DARPA/SPAWAR * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS * research program. * * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ffs_alloc.c 8.11 (Berkeley) 10/27/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/buf.h> #include <sys/vnode.h> #include <sys/mount.h> #include <sys/syslog.h> #include <sys/stdint.h> #include <sys/time.h> #include <ufs/ufs/quota.h> #include <ufs/ufs/inode.h> #include <ufs/ufs/ufsmount.h> #include <ufs/ufs/ufs_extern.h> #include <ufs/ffs/fs.h> #include <ufs/ffs/ffs_extern.h> #define ffs_fserr(fs, uid, cp) do { \ log(LOG_ERR, "uid %u on %s: %s\n", (uid), \ (fs)->fs_fsmnt, (cp)); \ } while (0) daddr_t ffs_alloccg(struct inode *, u_int, daddr_t, int); struct buf * ffs_cgread(struct fs *, struct inode *, u_int); daddr_t ffs_alloccgblk(struct inode *, struct buf *, daddr_t); ufsino_t ffs_dirpref(struct inode *); daddr_t ffs_fragextend(struct inode *, u_int, daddr_t, int, int); daddr_t ffs_hashalloc(struct inode *, u_int, daddr_t, int, daddr_t (*)(struct inode *, u_int, daddr_t, int)); daddr_t ffs_nodealloccg(struct inode *, u_int, daddr_t, int); daddr_t ffs_mapsearch(struct fs *, struct cg *, daddr_t, int); static const struct timeval fserr_interval = { 2, 0 }; /* * Allocate a block in the file system. * * The size of the requested block is given, which must be some * multiple of fs_fsize and <= fs_bsize. * A preference may be optionally specified. If a preference is given * the following hierarchy is used to allocate a block: * 1) allocate the requested block. * 2) allocate a rotationally optimal block in the same cylinder. * 3) allocate a block in the same cylinder group. * 4) quadratically rehash into other cylinder groups, until an * available block is located. * If no block preference is given the following hierarchy is used * to allocate a block: * 1) allocate a block in the cylinder group that contains the * inode for the file. * 2) quadratically rehash into other cylinder groups, until an * available block is located. */ int ffs_alloc(struct inode *ip, daddr_t lbn, daddr_t bpref, int size, struct ucred *cred, daddr_t *bnp) { static struct timeval fsfull_last; struct fs *fs; daddr_t bno; u_int cg; int error; *bnp = 0; fs = ip->i_fs; #ifdef DIAGNOSTIC if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0) { printf("dev = 0x%x, bsize = %d, size = %d, fs = %s\n", ip->i_dev, fs->fs_bsize, size, fs->fs_fsmnt); panic("ffs_alloc: bad size"); } if (cred == NOCRED) panic("ffs_alloc: missing credential"); #endif /* DIAGNOSTIC */ if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0) goto nospace; if (cred->cr_uid != 0 && freespace(fs, fs->fs_minfree) <= 0) goto nospace; if ((error = ufs_quota_alloc_blocks(ip, btodb(size), cred)) != 0) return (error); /* * Start allocation in the preferred block's cylinder group or * the file's inode's cylinder group if no preferred block was * specified. */ if (bpref >= fs->fs_size) bpref = 0; if (bpref == 0) cg = ino_to_cg(fs, ip->i_number); else cg = dtog(fs, bpref); /* Try allocating a block. */ bno = ffs_hashalloc(ip, cg, bpref, size, ffs_alloccg); if (bno > 0) { /* allocation successful, update inode data */ DIP_ADD(ip, blocks, btodb(size)); ip->i_flag |= IN_CHANGE | IN_UPDATE; *bnp = bno; return (0); } /* Restore user's disk quota because allocation failed. */ (void) ufs_quota_free_blocks(ip, btodb(size), cred); nospace: if (ratecheck(&fsfull_last, &fserr_interval)) { ffs_fserr(fs, cred->cr_uid, "file system full"); uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); } return (ENOSPC); } /* * Reallocate a fragment to a bigger size * * The number and size of the old block is given, and a preference * and new size is also specified. The allocator attempts to extend * the original block. Failing that, the regular block allocator is * invoked to get an appropriate block. */ int ffs_realloccg(struct inode *ip, daddr_t lbprev, daddr_t bpref, int osize, int nsize, struct ucred *cred, struct buf **bpp, daddr_t *blknop) { static struct timeval fsfull_last; struct fs *fs; struct buf *bp = NULL; daddr_t quota_updated = 0; int request, error; u_int cg; daddr_t bprev, bno; if (bpp != NULL) *bpp = NULL; fs = ip->i_fs; #ifdef DIAGNOSTIC if ((u_int)osize > fs->fs_bsize || fragoff(fs, osize) != 0 || (u_int)nsize > fs->fs_bsize || fragoff(fs, nsize) != 0) { printf( "dev = 0x%x, bsize = %d, osize = %d, nsize = %d, fs = %s\n", ip->i_dev, fs->fs_bsize, osize, nsize, fs->fs_fsmnt); panic("ffs_realloccg: bad size"); } if (cred == NOCRED) panic("ffs_realloccg: missing credential"); #endif /* DIAGNOSTIC */ if (cred->cr_uid != 0 && freespace(fs, fs->fs_minfree) <= 0) goto nospace; bprev = DIP(ip, db[lbprev]); if (bprev == 0) { printf("dev = 0x%x, bsize = %d, bprev = %lld, fs = %s\n", ip->i_dev, fs->fs_bsize, (long long)bprev, fs->fs_fsmnt); panic("ffs_realloccg: bad bprev"); } /* * Allocate the extra space in the buffer. */ if (bpp != NULL) { if ((error = bread(ITOV(ip), lbprev, fs->fs_bsize, &bp)) != 0) goto error; buf_adjcnt(bp, osize); } if ((error = ufs_quota_alloc_blocks(ip, btodb(nsize - osize), cred)) != 0) goto error; quota_updated = btodb(nsize - osize); /* * Check for extension in the existing location. */ cg = dtog(fs, bprev); if ((bno = ffs_fragextend(ip, cg, bprev, osize, nsize)) != 0) { DIP_ADD(ip, blocks, btodb(nsize - osize)); ip->i_flag |= IN_CHANGE | IN_UPDATE; if (bpp != NULL) { if (bp->b_blkno != fsbtodb(fs, bno)) panic("ffs_realloccg: bad blockno"); #ifdef DIAGNOSTIC if (nsize > bp->b_bufsize) panic("ffs_realloccg: small buf"); #endif buf_adjcnt(bp, nsize); bp->b_flags |= B_DONE; memset(bp->b_data + osize, 0, nsize - osize); *bpp = bp; } if (blknop != NULL) { *blknop = bno; } return (0); } /* * Allocate a new disk location. */ if (bpref >= fs->fs_size) bpref = 0; switch (fs->fs_optim) { case FS_OPTSPACE: /* * Allocate an exact sized fragment. Although this makes * best use of space, we will waste time relocating it if * the file continues to grow. If the fragmentation is * less than half of the minimum free reserve, we choose * to begin optimizing for time. */ request = nsize; if (fs->fs_minfree < 5 || fs->fs_cstotal.cs_nffree > fs->fs_dsize * fs->fs_minfree / (2 * 100)) break; fs->fs_optim = FS_OPTTIME; break; case FS_OPTTIME: /* * At this point we have discovered a file that is trying to * grow a small fragment to a larger fragment. To save time, * we allocate a full sized block, then free the unused portion. * If the file continues to grow, the `ffs_fragextend' call * above will be able to grow it in place without further * copying. If aberrant programs cause disk fragmentation to * grow within 2% of the free reserve, we choose to begin * optimizing for space. */ request = fs->fs_bsize; if (fs->fs_cstotal.cs_nffree < fs->fs_dsize * (fs->fs_minfree - 2) / 100) break; fs->fs_optim = FS_OPTSPACE; break; default: printf("dev = 0x%x, optim = %d, fs = %s\n", ip->i_dev, fs->fs_optim, fs->fs_fsmnt); panic("ffs_realloccg: bad optim"); /* NOTREACHED */ } bno = ffs_hashalloc(ip, cg, bpref, request, ffs_alloccg); if (bno <= 0) goto nospace; (void) uvm_vnp_uncache(ITOV(ip)); ffs_blkfree(ip, bprev, (long)osize); if (nsize < request) ffs_blkfree(ip, bno + numfrags(fs, nsize), (long)(request - nsize)); DIP_ADD(ip, blocks, btodb(nsize - osize)); ip->i_flag |= IN_CHANGE | IN_UPDATE; if (bpp != NULL) { bp->b_blkno = fsbtodb(fs, bno); #ifdef DIAGNOSTIC if (nsize > bp->b_bufsize) panic("ffs_realloccg: small buf 2"); #endif buf_adjcnt(bp, nsize); bp->b_flags |= B_DONE; memset(bp->b_data + osize, 0, nsize - osize); *bpp = bp; } if (blknop != NULL) { *blknop = bno; } return (0); nospace: if (ratecheck(&fsfull_last, &fserr_interval)) { ffs_fserr(fs, cred->cr_uid, "file system full"); uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); } error = ENOSPC; error: if (bp != NULL) { brelse(bp); bp = NULL; } /* * Restore user's disk quota because allocation failed. */ if (quota_updated != 0) (void)ufs_quota_free_blocks(ip, quota_updated, cred); return error; } /* * Allocate an inode in the file system. * * If allocating a directory, use ffs_dirpref to select the inode. * If allocating in a directory, the following hierarchy is followed: * 1) allocate the preferred inode. * 2) allocate an inode in the same cylinder group. * 3) quadratically rehash into other cylinder groups, until an * available inode is located. * If no inode preference is given the following hierarchy is used * to allocate an inode: * 1) allocate an inode in cylinder group 0. * 2) quadratically rehash into other cylinder groups, until an * available inode is located. */ int ffs_inode_alloc(struct inode *pip, mode_t mode, struct ucred *cred, struct vnode **vpp) { static struct timeval fsnoinodes_last; struct vnode *pvp = ITOV(pip); struct fs *fs; struct inode *ip; ufsino_t ino, ipref; u_int cg; int error; *vpp = NULL; fs = pip->i_fs; if (fs->fs_cstotal.cs_nifree == 0) goto noinodes; if ((mode & IFMT) == IFDIR) ipref = ffs_dirpref(pip); else ipref = pip->i_number; if (ipref >= fs->fs_ncg * fs->fs_ipg) ipref = 0; cg = ino_to_cg(fs, ipref); /* * Track number of dirs created one after another * in a same cg without intervening by files. */ if ((mode & IFMT) == IFDIR) { if (fs->fs_contigdirs[cg] < 255) fs->fs_contigdirs[cg]++; } else { if (fs->fs_contigdirs[cg] > 0) fs->fs_contigdirs[cg]--; } ino = (ufsino_t)ffs_hashalloc(pip, cg, ipref, mode, ffs_nodealloccg); if (ino == 0) goto noinodes; error = VFS_VGET(pvp->v_mount, ino, vpp); if (error) { ffs_inode_free(pip, ino, mode); return (error); } ip = VTOI(*vpp); if (DIP(ip, mode)) { printf("mode = 0%o, inum = %u, fs = %s\n", DIP(ip, mode), ip->i_number, fs->fs_fsmnt); panic("ffs_valloc: dup alloc"); } if (DIP(ip, blocks)) { printf("free inode %s/%d had %lld blocks\n", fs->fs_fsmnt, ino, (long long)DIP(ip, blocks)); DIP_ASSIGN(ip, blocks, 0); } DIP_ASSIGN(ip, flags, 0); /* * Set up a new generation number for this inode. * On wrap, we make sure to assign a number != 0 and != UINT_MAX * (the original value). */ if (DIP(ip, gen) != 0) DIP_ADD(ip, gen, 1); while (DIP(ip, gen) == 0) DIP_ASSIGN(ip, gen, arc4random_uniform(UINT_MAX)); return (0); noinodes: if (ratecheck(&fsnoinodes_last, &fserr_interval)) { ffs_fserr(fs, cred->cr_uid, "out of inodes"); uprintf("\n%s: create/symlink failed, no inodes free\n", fs->fs_fsmnt); } return (ENOSPC); } /* * Find a cylinder group to place a directory. * * The policy implemented by this algorithm is to allocate a * directory inode in the same cylinder group as its parent * directory, but also to reserve space for its files inodes * and data. Restrict the number of directories which may be * allocated one after another in the same cylinder group * without intervening allocation of files. * * If we allocate a first level directory then force allocation * in another cylinder group. */ ufsino_t ffs_dirpref(struct inode *pip) { struct fs *fs; u_int cg, prefcg; u_int dirsize, cgsize; u_int avgifree, avgbfree, avgndir, curdirsize; u_int minifree, minbfree, maxndir; u_int mincg, minndir; u_int maxcontigdirs; fs = pip->i_fs; avgifree = fs->fs_cstotal.cs_nifree / fs->fs_ncg; avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg; avgndir = fs->fs_cstotal.cs_ndir / fs->fs_ncg; /* * Force allocation in another cg if creating a first level dir. */ if (ITOV(pip)->v_flag & VROOT) { prefcg = arc4random_uniform(fs->fs_ncg); mincg = prefcg; minndir = fs->fs_ipg; for (cg = prefcg; cg < fs->fs_ncg; cg++) if (fs->fs_cs(fs, cg).cs_ndir < minndir && fs->fs_cs(fs, cg).cs_nifree >= avgifree && fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) { mincg = cg; minndir = fs->fs_cs(fs, cg).cs_ndir; } for (cg = 0; cg < prefcg; cg++) if (fs->fs_cs(fs, cg).cs_ndir < minndir && fs->fs_cs(fs, cg).cs_nifree >= avgifree && fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) { mincg = cg; minndir = fs->fs_cs(fs, cg).cs_ndir; } cg = mincg; goto end; } else prefcg = ino_to_cg(fs, pip->i_number); /* * Count various limits which used for * optimal allocation of a directory inode. */ maxndir = min(avgndir + fs->fs_ipg / 16, fs->fs_ipg); minifree = avgifree - (avgifree / 4); if (minifree < 1) minifree = 1; minbfree = avgbfree - (avgbfree / 4); if (minbfree < 1) minbfree = 1; cgsize = fs->fs_fsize * fs->fs_fpg; dirsize = fs->fs_avgfilesize * fs->fs_avgfpdir; curdirsize = avgndir ? (cgsize - avgbfree * fs->fs_bsize) / avgndir : 0; if (dirsize < curdirsize) dirsize = curdirsize; if (dirsize <= 0) maxcontigdirs = 0; /* dirsize overflowed */ else maxcontigdirs = min(avgbfree * fs->fs_bsize / dirsize, 255); if (fs->fs_avgfpdir > 0) maxcontigdirs = min(maxcontigdirs, fs->fs_ipg / fs->fs_avgfpdir); if (maxcontigdirs == 0) maxcontigdirs = 1; /* * Limit number of dirs in one cg and reserve space for * regular files, but only if we have no deficit in * inodes or space. * * We are trying to find a suitable cylinder group nearby * our preferred cylinder group to place a new directory. * We scan from our preferred cylinder group forward looking * for a cylinder group that meets our criterion. If we get * to the final cylinder group and do not find anything, * we start scanning forwards from the beginning of the * filesystem. While it might seem sensible to start scanning * backwards or even to alternate looking forward and backward, * this approach fails badly when the filesystem is nearly full. * Specifically, we first search all the areas that have no space * and finally try the one preceding that. We repeat this on * every request and in the case of the final block end up * searching the entire filesystem. By jumping to the front * of the filesystem, our future forward searches always look * in new cylinder groups so finds every possible block after * one pass over the filesystem. */ for (cg = prefcg; cg < fs->fs_ncg; cg++) if (fs->fs_cs(fs, cg).cs_ndir < maxndir && fs->fs_cs(fs, cg).cs_nifree >= minifree && fs->fs_cs(fs, cg).cs_nbfree >= minbfree) { if (fs->fs_contigdirs[cg] < maxcontigdirs) goto end; } for (cg = 0; cg < prefcg; cg++) if (fs->fs_cs(fs, cg).cs_ndir < maxndir && fs->fs_cs(fs, cg).cs_nifree >= minifree && fs->fs_cs(fs, cg).cs_nbfree >= minbfree) { if (fs->fs_contigdirs[cg] < maxcontigdirs) goto end; } /* * This is a backstop when we have deficit in space. */ for (cg = prefcg; cg < fs->fs_ncg; cg++) if (fs->fs_cs(fs, cg).cs_nifree >= avgifree) goto end; for (cg = 0; cg < prefcg; cg++) if (fs->fs_cs(fs, cg).cs_nifree >= avgifree) goto end; end: return ((ufsino_t)(fs->fs_ipg * cg)); } /* * Select the desired position for the next block in a file. The file is * logically divided into sections. The first section is composed of the * direct blocks. Each additional section contains fs_maxbpg blocks. * * If no blocks have been allocated in the first section, the policy is to * request a block in the same cylinder group as the inode that describes * the file. The first indirect is allocated immediately following the last * direct block and the data blocks for the first indirect immediately * follow it. * * If no blocks have been allocated in any other section, the indirect * block(s) are allocated in the same cylinder group as its inode in an * area reserved immediately following the inode blocks. The policy for * the data blocks is to place them in a cylinder group with a greater than * average number of free blocks. An appropriate cylinder group is found * by using a rotor that sweeps the cylinder groups. When a new group of * blocks is needed, the sweep begins in the cylinder group following the * cylinder group from which the previous allocation was made. The sweep * continues until a cylinder group with greater than the average number * of free blocks is found. If the allocation is for the first block in an * indirect block, the information on the previous allocation is unavailable; * here a best guess is made based upon the logical block number being * allocated. */ int32_t ffs1_blkpref(struct inode *ip, daddr_t lbn, int indx, int32_t *bap) { struct fs *fs; u_int cg, inocg; u_int avgbfree, startcg; uint32_t pref; KASSERT(indx <= 0 || bap != NULL); fs = ip->i_fs; /* * Allocation of indirect blocks is indicated by passing negative * values in indx: -1 for single indirect, -2 for double indirect, * -3 for triple indirect. As noted below, we attempt to allocate * the first indirect inline with the file data. For all later * indirect blocks, the data is often allocated in other cylinder * groups. However to speed random file access and to speed up * fsck, the filesystem reserves the first fs_metaspace blocks * (typically half of fs_minfree) of the data area of each cylinder * group to hold these later indirect blocks. */ inocg = ino_to_cg(fs, ip->i_number); if (indx < 0) { /* * Our preference for indirect blocks is the zone at the * beginning of the inode's cylinder group data area that * we try to reserve for indirect blocks. */ pref = cgmeta(fs, inocg); /* * If we are allocating the first indirect block, try to * place it immediately following the last direct block. */ if (indx == -1 && lbn < NDADDR + NINDIR(fs) && ip->i_din1->di_db[NDADDR - 1] != 0) pref = ip->i_din1->di_db[NDADDR - 1] + fs->fs_frag; return (pref); } /* * If we are allocating the first data block in the first indirect * block and the indirect has been allocated in the data block area, * try to place it immediately following the indirect block. */ if (lbn == NDADDR) { pref = ip->i_din1->di_ib[0]; if (pref != 0 && pref >= cgdata(fs, inocg) && pref < cgbase(fs, inocg + 1)) return (pref + fs->fs_frag); } /* * If we are the beginning of a file, or we have already allocated * the maximum number of blocks per cylinder group, or we do not * have a block allocated immediately preceding us, then we need * to decide where to start allocating new blocks. */ if (indx % fs->fs_maxbpg == 0 || bap[indx - 1] == 0) { /* * If we are allocating a directory data block, we want * to place it in the metadata area. */ if ((DIP(ip, mode) & IFMT) == IFDIR) return (cgmeta(fs, inocg)); /* * Until we fill all the direct and all the first indirect's * blocks, we try to allocate in the data area of the inode's * cylinder group. */ if (lbn < NDADDR + NINDIR(fs)) return (cgdata(fs, inocg)); /* * Find a cylinder with greater than average number of * unused data blocks. */ if (indx == 0 || bap[indx - 1] == 0) startcg = inocg + lbn / fs->fs_maxbpg; else startcg = dtog(fs, bap[indx - 1]) + 1; startcg %= fs->fs_ncg; avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg; for (cg = startcg; cg < fs->fs_ncg; cg++) if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) { fs->fs_cgrotor = cg; return (cgdata(fs, cg)); } for (cg = 0; cg <= startcg; cg++) if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) { fs->fs_cgrotor = cg; return (cgdata(fs, cg)); } return (0); } /* * Otherwise, we just always try to lay things out contiguously. */ return (bap[indx - 1] + fs->fs_frag); } /* * Same as above, for UFS2. */ #ifdef FFS2 int64_t ffs2_blkpref(struct inode *ip, daddr_t lbn, int indx, int64_t *bap) { struct fs *fs; u_int cg, inocg; u_int avgbfree, startcg; uint64_t pref; KASSERT(indx <= 0 || bap != NULL); fs = ip->i_fs; /* * Allocation of indirect blocks is indicated by passing negative * values in indx: -1 for single indirect, -2 for double indirect, * -3 for triple indirect. As noted below, we attempt to allocate * the first indirect inline with the file data. For all later * indirect blocks, the data is often allocated in other cylinder * groups. However to speed random file access and to speed up * fsck, the filesystem reserves the first fs_metaspace blocks * (typically half of fs_minfree) of the data area of each cylinder * group to hold these later indirect blocks. */ inocg = ino_to_cg(fs, ip->i_number); if (indx < 0) { /* * Our preference for indirect blocks is the zone at the * beginning of the inode's cylinder group data area that * we try to reserve for indirect blocks. */ pref = cgmeta(fs, inocg); /* * If we are allocating the first indirect block, try to * place it immediately following the last direct block. */ if (indx == -1 && lbn < NDADDR + NINDIR(fs) && ip->i_din2->di_db[NDADDR - 1] != 0) pref = ip->i_din2->di_db[NDADDR - 1] + fs->fs_frag; return (pref); } /* * If we are allocating the first data block in the first indirect * block and the indirect has been allocated in the data block area, * try to place it immediately following the indirect block. */ if (lbn == NDADDR) { pref = ip->i_din2->di_ib[0]; if (pref != 0 && pref >= cgdata(fs, inocg) && pref < cgbase(fs, inocg + 1)) return (pref + fs->fs_frag); } /* * If we are the beginning of a file, or we have already allocated * the maximum number of blocks per cylinder group, or we do not * have a block allocated immediately preceding us, then we need * to decide where to start allocating new blocks. */ if (indx % fs->fs_maxbpg == 0 || bap[indx - 1] == 0) { /* * If we are allocating a directory data block, we want * to place it in the metadata area. */ if ((DIP(ip, mode) & IFMT) == IFDIR) return (cgmeta(fs, inocg)); /* * Until we fill all the direct and all the first indirect's * blocks, we try to allocate in the data area of the inode's * cylinder group. */ if (lbn < NDADDR + NINDIR(fs)) return (cgdata(fs, inocg)); /* * Find a cylinder with greater than average number of * unused data blocks. */ if (indx == 0 || bap[indx - 1] == 0) startcg = inocg + lbn / fs->fs_maxbpg; else startcg = dtog(fs, bap[indx - 1] + 1); startcg %= fs->fs_ncg; avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg; for (cg = startcg; cg < fs->fs_ncg; cg++) if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) return (cgbase(fs, cg) + fs->fs_frag); for (cg = 0; cg < startcg; cg++) if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) return (cgbase(fs, cg) + fs->fs_frag); return (0); } /* * Otherwise, we just always try to lay things out contiguously. */ return (bap[indx - 1] + fs->fs_frag); } #endif /* FFS2 */ /* * Implement the cylinder overflow algorithm. * * The policy implemented by this algorithm is: * 1) allocate the block in its requested cylinder group. * 2) quadratically rehash on the cylinder group number. * 3) brute force search for a free block. */ daddr_t ffs_hashalloc(struct inode *ip, u_int cg, daddr_t pref, int size, daddr_t (*allocator)(struct inode *, u_int, daddr_t, int)) { struct fs *fs; daddr_t result; u_int i, icg = cg; fs = ip->i_fs; /* * 1: preferred cylinder group */ result = (*allocator)(ip, cg, pref, size); if (result) return (result); /* * 2: quadratic rehash */ for (i = 1; i < fs->fs_ncg; i *= 2) { cg += i; if (cg >= fs->fs_ncg) cg -= fs->fs_ncg; result = (*allocator)(ip, cg, 0, size); if (result) return (result); } /* * 3: brute force search * Note that we start at i == 2, since 0 was checked initially, * and 1 is always checked in the quadratic rehash. */ cg = (icg + 2) % fs->fs_ncg; for (i = 2; i < fs->fs_ncg; i++) { result = (*allocator)(ip, cg, 0, size); if (result) return (result); cg++; if (cg == fs->fs_ncg) cg = 0; } return (0); } struct buf * ffs_cgread(struct fs *fs, struct inode *ip, u_int cg) { struct buf *bp; if (bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, &bp)) { brelse(bp); return (NULL); } if (!cg_chkmagic((struct cg *)bp->b_data)) { brelse(bp); return (NULL); } return bp; } /* * Determine whether a fragment can be extended. * * Check to see if the necessary fragments are available, and * if they are, allocate them. */ daddr_t ffs_fragextend(struct inode *ip, u_int cg, daddr_t bprev, int osize, int nsize) { struct fs *fs; struct cg *cgp; struct buf *bp; struct timespec now; daddr_t bno; int i, frags, bbase; fs = ip->i_fs; if (fs->fs_cs(fs, cg).cs_nffree < numfrags(fs, nsize - osize)) return (0); frags = numfrags(fs, nsize); bbase = fragnum(fs, bprev); if (bbase > fragnum(fs, (bprev + frags - 1))) { /* cannot extend across a block boundary */ return (0); } if (!(bp = ffs_cgread(fs, ip, cg))) return (0); cgp = (struct cg *)bp->b_data; nanotime(&now); cgp->cg_ffs2_time = now.tv_sec; cgp->cg_time = now.tv_sec; bno = dtogd(fs, bprev); for (i = numfrags(fs, osize); i < frags; i++) if (isclr(cg_blksfree(cgp), bno + i)) { brelse(bp); return (0); } /* * the current fragment can be extended * deduct the count on fragment being extended into * increase the count on the remaining fragment (if any) * allocate the extended piece */ for (i = frags; i < fs->fs_frag - bbase; i++) if (isclr(cg_blksfree(cgp), bno + i)) break; cgp->cg_frsum[i - numfrags(fs, osize)]--; if (i != frags) cgp->cg_frsum[i - frags]++; for (i = numfrags(fs, osize); i < frags; i++) { clrbit(cg_blksfree(cgp), bno + i); cgp->cg_cs.cs_nffree--; fs->fs_cstotal.cs_nffree--; fs->fs_cs(fs, cg).cs_nffree--; } fs->fs_fmod = 1; bdwrite(bp); return (bprev); } /* * Determine whether a block can be allocated. * * Check to see if a block of the appropriate size is available, * and if it is, allocate it. */ daddr_t ffs_alloccg(struct inode *ip, u_int cg, daddr_t bpref, int size) { struct fs *fs; struct cg *cgp; struct buf *bp; struct timespec now; daddr_t bno, blkno; int i, frags, allocsiz; fs = ip->i_fs; if (fs->fs_cs(fs, cg).cs_nbfree == 0 && size == fs->fs_bsize) return (0); if (!(bp = ffs_cgread(fs, ip, cg))) return (0); cgp = (struct cg *)bp->b_data; if (cgp->cg_cs.cs_nbfree == 0 && size == fs->fs_bsize) { brelse(bp); return (0); } nanotime(&now); cgp->cg_ffs2_time = now.tv_sec; cgp->cg_time = now.tv_sec; if (size == fs->fs_bsize) { /* allocate and return a complete data block */ bno = ffs_alloccgblk(ip, bp, bpref); bdwrite(bp); return (bno); } /* * check to see if any fragments are already available * allocsiz is the size which will be allocated, hacking * it down to a smaller size if necessary */ frags = numfrags(fs, size); for (allocsiz = frags; allocsiz < fs->fs_frag; allocsiz++) if (cgp->cg_frsum[allocsiz] != 0) break; if (allocsiz == fs->fs_frag) { /* * no fragments were available, so a block will be * allocated, and hacked up */ if (cgp->cg_cs.cs_nbfree == 0) { brelse(bp); return (0); } bno = ffs_alloccgblk(ip, bp, bpref); bpref = dtogd(fs, bno); for (i = frags; i < fs->fs_frag; i++) setbit(cg_blksfree(cgp), bpref + i); i = fs->fs_frag - frags; cgp->cg_cs.cs_nffree += i; fs->fs_cstotal.cs_nffree += i; fs->fs_cs(fs, cg).cs_nffree += i; fs->fs_fmod = 1; cgp->cg_frsum[i]++; bdwrite(bp); return (bno); } bno = ffs_mapsearch(fs, cgp, bpref, allocsiz); if (bno < 0) { brelse(bp); return (0); } for (i = 0; i < frags; i++) clrbit(cg_blksfree(cgp), bno + i); cgp->cg_cs.cs_nffree -= frags; fs->fs_cstotal.cs_nffree -= frags; fs->fs_cs(fs, cg).cs_nffree -= frags; fs->fs_fmod = 1; cgp->cg_frsum[allocsiz]--; if (frags != allocsiz) cgp->cg_frsum[allocsiz - frags]++; blkno = cgbase(fs, cg) + bno; bdwrite(bp); return (blkno); } /* * Allocate a block in a cylinder group. * Note that this routine only allocates fs_bsize blocks; these * blocks may be fragmented by the routine that allocates them. */ daddr_t ffs_alloccgblk(struct inode *ip, struct buf *bp, daddr_t bpref) { struct fs *fs; struct cg *cgp; daddr_t bno, blkno; u_int8_t *blksfree; int cylno, cgbpref; fs = ip->i_fs; cgp = (struct cg *) bp->b_data; blksfree = cg_blksfree(cgp); if (bpref == 0) { bpref = cgp->cg_rotor; } else if ((cgbpref = dtog(fs, bpref)) != cgp->cg_cgx) { /* map bpref to correct zone in this cg */ if (bpref < cgdata(fs, cgbpref)) bpref = cgmeta(fs, cgp->cg_cgx); else bpref = cgdata(fs, cgp->cg_cgx); } /* * If the requested block is available, use it. */ bno = dtogd(fs, blknum(fs, bpref)); if (ffs_isblock(fs, blksfree, fragstoblks(fs, bno))) goto gotit; /* * Take the next available block in this cylinder group. */ bno = ffs_mapsearch(fs, cgp, bpref, (int) fs->fs_frag); if (bno < 0) return (0); /* Update cg_rotor only if allocated from the data zone */ if (bno >= dtogd(fs, cgdata(fs, cgp->cg_cgx))) cgp->cg_rotor = bno; gotit: blkno = fragstoblks(fs, bno); ffs_clrblock(fs, blksfree, blkno); ffs_clusteracct(fs, cgp, blkno, -1); cgp->cg_cs.cs_nbfree--; fs->fs_cstotal.cs_nbfree--; fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--; if (fs->fs_magic != FS_UFS2_MAGIC) { cylno = cbtocylno(fs, bno); cg_blks(fs, cgp, cylno)[cbtorpos(fs, bno)]--; cg_blktot(cgp)[cylno]--; } fs->fs_fmod = 1; blkno = cgbase(fs, cgp->cg_cgx) + bno; return (blkno); } /* inode allocation routine */ daddr_t ffs_nodealloccg(struct inode *ip, u_int cg, daddr_t ipref, int mode) { struct fs *fs; struct cg *cgp; struct buf *bp; struct timespec now; int start, len, loc, map, i; #ifdef FFS2 struct buf *ibp = NULL; struct ufs2_dinode *dp2; #endif /* * For efficiency, before looking at the bitmaps for free inodes, * check the counters kept in the superblock cylinder group summaries, * and in the cylinder group itself. */ fs = ip->i_fs; if (fs->fs_cs(fs, cg).cs_nifree == 0) return (0); if (!(bp = ffs_cgread(fs, ip, cg))) return (0); cgp = (struct cg *)bp->b_data; if (cgp->cg_cs.cs_nifree == 0) { brelse(bp); return (0); } /* * We are committed to the allocation from now on, so update the time * on the cylinder group. */ nanotime(&now); cgp->cg_ffs2_time = now.tv_sec; cgp->cg_time = now.tv_sec; /* * If there was a preferred location for the new inode, try to find it. */ if (ipref) { ipref %= fs->fs_ipg; if (isclr(cg_inosused(cgp), ipref)) goto gotit; /* inode is free, grab it. */ } /* * Otherwise, look for the next available inode, starting at cg_irotor * (the position in the bitmap of the last used inode). */ start = cgp->cg_irotor / NBBY; len = howmany(fs->fs_ipg - cgp->cg_irotor, NBBY); loc = skpc(0xff, len, &cg_inosused(cgp)[start]); if (loc == 0) { /* * If we didn't find a free inode in the upper part of the * bitmap (from cg_irotor to the end), then look at the bottom * part (from 0 to cg_irotor). */ len = start + 1; start = 0; loc = skpc(0xff, len, &cg_inosused(cgp)[0]); if (loc == 0) { /* * If we failed again, then either the bitmap or the * counters kept for the cylinder group are wrong. */ printf("cg = %d, irotor = %d, fs = %s\n", cg, cgp->cg_irotor, fs->fs_fsmnt); panic("ffs_nodealloccg: map corrupted"); /* NOTREACHED */ } } /* skpc() returns the position relative to the end */ i = start + len - loc; /* * Okay, so now in 'i' we have the location in the bitmap of a byte * holding a free inode. Find the corresponding bit and set it, * updating cg_irotor as well, accordingly. */ map = cg_inosused(cgp)[i]; ipref = i * NBBY; for (i = 1; i < (1 << NBBY); i <<= 1, ipref++) { if ((map & i) == 0) { cgp->cg_irotor = ipref; goto gotit; } } printf("fs = %s\n", fs->fs_fsmnt); panic("ffs_nodealloccg: block not in map"); /* NOTREACHED */ gotit: #ifdef FFS2 /* * For FFS2, check if all inodes in this cylinder group have been used * at least once. If they haven't, and we are allocating an inode past * the last allocated block of inodes, read in a block and initialize * all inodes in it. */ if (fs->fs_magic == FS_UFS2_MAGIC && /* Inode is beyond last initialized block of inodes? */ ipref + INOPB(fs) > cgp->cg_initediblk && /* Has any inode not been used at least once? */ cgp->cg_initediblk < cgp->cg_ffs2_niblk) { ibp = getblk(ip->i_devvp, fsbtodb(fs, ino_to_fsba(fs, cg * fs->fs_ipg + cgp->cg_initediblk)), (int)fs->fs_bsize, 0, INFSLP); memset(ibp->b_data, 0, fs->fs_bsize); dp2 = (struct ufs2_dinode *)(ibp->b_data); /* Give each inode a generation number */ for (i = 0; i < INOPB(fs); i++) { while (dp2->di_gen == 0) dp2->di_gen = arc4random(); dp2++; } /* Update the counter of initialized inodes */ cgp->cg_initediblk += INOPB(fs); } #endif /* FFS2 */ setbit(cg_inosused(cgp), ipref); /* Update the counters we keep on free inodes */ cgp->cg_cs.cs_nifree--; fs->fs_cstotal.cs_nifree--; fs->fs_cs(fs, cg).cs_nifree--; fs->fs_fmod = 1; /* file system was modified */ /* Update the counters we keep on allocated directories */ if ((mode & IFMT) == IFDIR) { cgp->cg_cs.cs_ndir++; fs->fs_cstotal.cs_ndir++; fs->fs_cs(fs, cg).cs_ndir++; } bdwrite(bp); #ifdef FFS2 if (ibp != NULL) bawrite(ibp); #endif /* Return the allocated inode number */ return (cg * fs->fs_ipg + ipref); } /* * Free a block or fragment. * * The specified block or fragment is placed back in the * free map. If a fragment is deallocated, a possible * block reassembly is checked. */ void ffs_blkfree(struct inode *ip, daddr_t bno, long size) { struct fs *fs; struct cg *cgp; struct buf *bp; struct timespec now; daddr_t blkno; int i, cg, blk, frags, bbase; fs = ip->i_fs; if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0 || fragnum(fs, bno) + numfrags(fs, size) > fs->fs_frag) { printf("dev = 0x%x, bsize = %d, size = %ld, fs = %s\n", ip->i_dev, fs->fs_bsize, size, fs->fs_fsmnt); panic("ffs_blkfree: bad size"); } cg = dtog(fs, bno); if ((u_int)bno >= fs->fs_size) { printf("bad block %lld, ino %u\n", (long long)bno, ip->i_number); ffs_fserr(fs, DIP(ip, uid), "bad block"); return; } if (!(bp = ffs_cgread(fs, ip, cg))) return; cgp = (struct cg *)bp->b_data; nanotime(&now); cgp->cg_ffs2_time = now.tv_sec; cgp->cg_time = now.tv_sec; bno = dtogd(fs, bno); if (size == fs->fs_bsize) { blkno = fragstoblks(fs, bno); if (!ffs_isfreeblock(fs, cg_blksfree(cgp), blkno)) { printf("dev = 0x%x, block = %lld, fs = %s\n", ip->i_dev, (long long)bno, fs->fs_fsmnt); panic("ffs_blkfree: freeing free block"); } ffs_setblock(fs, cg_blksfree(cgp), blkno); ffs_clusteracct(fs, cgp, blkno, 1); cgp->cg_cs.cs_nbfree++; fs->fs_cstotal.cs_nbfree++; fs->fs_cs(fs, cg).cs_nbfree++; if (fs->fs_magic != FS_UFS2_MAGIC) { i = cbtocylno(fs, bno); cg_blks(fs, cgp, i)[cbtorpos(fs, bno)]++; cg_blktot(cgp)[i]++; } } else { bbase = bno - fragnum(fs, bno); /* * decrement the counts associated with the old frags */ blk = blkmap(fs, cg_blksfree(cgp), bbase); ffs_fragacct(fs, blk, cgp->cg_frsum, -1); /* * deallocate the fragment */ frags = numfrags(fs, size); for (i = 0; i < frags; i++) { if (isset(cg_blksfree(cgp), bno + i)) { printf("dev = 0x%x, block = %lld, fs = %s\n", ip->i_dev, (long long)(bno + i), fs->fs_fsmnt); panic("ffs_blkfree: freeing free frag"); } setbit(cg_blksfree(cgp), bno + i); } cgp->cg_cs.cs_nffree += i; fs->fs_cstotal.cs_nffree += i; fs->fs_cs(fs, cg).cs_nffree += i; /* * add back in counts associated with the new frags */ blk = blkmap(fs, cg_blksfree(cgp), bbase); ffs_fragacct(fs, blk, cgp->cg_frsum, 1); /* * if a complete block has been reassembled, account for it */ blkno = fragstoblks(fs, bbase); if (ffs_isblock(fs, cg_blksfree(cgp), blkno)) { cgp->cg_cs.cs_nffree -= fs->fs_frag; fs->fs_cstotal.cs_nffree -= fs->fs_frag; fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag; ffs_clusteracct(fs, cgp, blkno, 1); cgp->cg_cs.cs_nbfree++; fs->fs_cstotal.cs_nbfree++; fs->fs_cs(fs, cg).cs_nbfree++; if (fs->fs_magic != FS_UFS2_MAGIC) { i = cbtocylno(fs, bbase); cg_blks(fs, cgp, i)[cbtorpos(fs, bbase)]++; cg_blktot(cgp)[i]++; } } } fs->fs_fmod = 1; bdwrite(bp); } int ffs_inode_free(struct inode *pip, ufsino_t ino, mode_t mode) { return (ffs_freefile(pip, ino, mode)); } /* * Do the actual free operation. * The specified inode is placed back in the free map. */ int ffs_freefile(struct inode *pip, ufsino_t ino, mode_t mode) { struct fs *fs; struct cg *cgp; struct buf *bp; struct timespec now; u_int cg; fs = pip->i_fs; if (ino >= fs->fs_ipg * fs->fs_ncg) panic("ffs_freefile: range: dev = 0x%x, ino = %d, fs = %s", pip->i_dev, ino, fs->fs_fsmnt); cg = ino_to_cg(fs, ino); if (!(bp = ffs_cgread(fs, pip, cg))) return (0); cgp = (struct cg *)bp->b_data; nanotime(&now); cgp->cg_ffs2_time = now.tv_sec; cgp->cg_time = now.tv_sec; ino %= fs->fs_ipg; if (isclr(cg_inosused(cgp), ino)) { printf("dev = 0x%x, ino = %u, fs = %s\n", pip->i_dev, ino, fs->fs_fsmnt); if (fs->fs_ronly == 0) panic("ffs_freefile: freeing free inode"); } clrbit(cg_inosused(cgp), ino); if (ino < cgp->cg_irotor) cgp->cg_irotor = ino; cgp->cg_cs.cs_nifree++; fs->fs_cstotal.cs_nifree++; fs->fs_cs(fs, cg).cs_nifree++; if ((mode & IFMT) == IFDIR) { cgp->cg_cs.cs_ndir--; fs->fs_cstotal.cs_ndir--; fs->fs_cs(fs, cg).cs_ndir--; } fs->fs_fmod = 1; bdwrite(bp); return (0); } /* * Find a block of the specified size in the specified cylinder group. * * It is a panic if a request is made to find a block if none are * available. */ daddr_t ffs_mapsearch(struct fs *fs, struct cg *cgp, daddr_t bpref, int allocsiz) { daddr_t bno; int start, len, loc, i; int blk, field, subfield, pos; /* * find the fragment by searching through the free block * map for an appropriate bit pattern */ if (bpref) start = dtogd(fs, bpref) / NBBY; else start = cgp->cg_frotor / NBBY; len = howmany(fs->fs_fpg, NBBY) - start; loc = scanc((u_int)len, (u_char *)&cg_blksfree(cgp)[start], (u_char *)fragtbl[fs->fs_frag], (u_char)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY)))); if (loc == 0) { len = start + 1; start = 0; loc = scanc((u_int)len, (u_char *)&cg_blksfree(cgp)[0], (u_char *)fragtbl[fs->fs_frag], (u_char)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY)))); if (loc == 0) { printf("start = %d, len = %d, fs = %s\n", start, len, fs->fs_fsmnt); panic("ffs_alloccg: map corrupted"); /* NOTREACHED */ } } bno = (start + len - loc) * NBBY; cgp->cg_frotor = bno; /* * found the byte in the map * sift through the bits to find the selected frag */ for (i = bno + NBBY; bno < i; bno += fs->fs_frag) { blk = blkmap(fs, cg_blksfree(cgp), bno); blk <<= 1; field = around[allocsiz]; subfield = inside[allocsiz]; for (pos = 0; pos <= fs->fs_frag - allocsiz; pos++) { if ((blk & field) == subfield) return (bno + pos); field <<= 1; subfield <<= 1; } } printf("bno = %lld, fs = %s\n", (long long)bno, fs->fs_fsmnt); panic("ffs_alloccg: block not in map"); return (-1); } /* * Update the cluster map because of an allocation or free. * * Cnt == 1 means free; cnt == -1 means allocating. */ void ffs_clusteracct(struct fs *fs, struct cg *cgp, daddr_t blkno, int cnt) { int32_t *sump; int32_t *lp; u_char *freemapp, *mapp; int i, start, end, forw, back, map, bit; if (fs->fs_contigsumsize <= 0) return; freemapp = cg_clustersfree(cgp); sump = cg_clustersum(cgp); /* * Allocate or clear the actual block. */ if (cnt > 0) setbit(freemapp, blkno); else clrbit(freemapp, blkno); /* * Find the size of the cluster going forward. */ start = blkno + 1; end = start + fs->fs_contigsumsize; if (end >= cgp->cg_nclusterblks) end = cgp->cg_nclusterblks; mapp = &freemapp[start / NBBY]; map = *mapp++; bit = 1 << (start % NBBY); for (i = start; i < end; i++) { if ((map & bit) == 0) break; if ((i & (NBBY - 1)) != (NBBY - 1)) { bit <<= 1; } else { map = *mapp++; bit = 1; } } forw = i - start; /* * Find the size of the cluster going backward. */ start = blkno - 1; end = start - fs->fs_contigsumsize; if (end < 0) end = -1; mapp = &freemapp[start / NBBY]; map = *mapp--; bit = 1 << (start % NBBY); for (i = start; i > end; i--) { if ((map & bit) == 0) break; if ((i & (NBBY - 1)) != 0) { bit >>= 1; } else { map = *mapp--; bit = 1 << (NBBY - 1); } } back = start - i; /* * Account for old cluster and the possibly new forward and * back clusters. */ i = back + forw + 1; if (i > fs->fs_contigsumsize) i = fs->fs_contigsumsize; sump[i] += cnt; if (back > 0) sump[back] -= cnt; if (forw > 0) sump[forw] -= cnt; /* * Update cluster summary information. */ lp = &sump[fs->fs_contigsumsize]; for (i = fs->fs_contigsumsize; i > 0; i--) if (*lp-- > 0) break; fs->fs_maxcluster[cgp->cg_cgx] = i; }
1 4 2 3 1 1 3 2 1 2 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 /* $OpenBSD: pvbus.c,v 1.28 2024/05/24 10:05:55 jsg Exp $ */ /* * Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #if !defined(__i386__) && !defined(__amd64__) #error pvbus(4) is currently only supported on i386 and amd64 #endif #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/signalvar.h> #include <sys/syslog.h> #include <sys/proc.h> #include <sys/ioctl.h> #include <sys/fcntl.h> #include <machine/specialreg.h> #include <machine/cpu.h> #include <machine/conf.h> #include <machine/bus.h> #include <machine/vmmvar.h> #include <dev/pv/pvvar.h> #include <dev/pv/pvreg.h> #include <dev/pv/hypervreg.h> #include "hyperv.h" int has_hv_cpuid = 0; extern void rdrand(void *); int pvbus_activate(struct device *, int); int pvbus_match(struct device *, void *, void *); void pvbus_attach(struct device *, struct device *, void *); int pvbus_print(void *, const char *); int pvbus_search(struct device *, void *, void *); void pvbus_kvm(struct pvbus_hv *); void pvbus_hyperv(struct pvbus_hv *); void pvbus_hyperv_print(struct pvbus_hv *); void pvbus_xen(struct pvbus_hv *); void pvbus_xen_print(struct pvbus_hv *); int pvbus_minor(struct pvbus_softc *, dev_t); int pvbusgetstr(size_t, const char *, char **); const struct cfattach pvbus_ca = { sizeof(struct pvbus_softc), pvbus_match, pvbus_attach, NULL, pvbus_activate }; struct cfdriver pvbus_cd = { NULL, "pvbus", DV_DULL }; struct pvbus_type { const char *signature; const char *name; void (*init)(struct pvbus_hv *); void (*print)(struct pvbus_hv *); } pvbus_types[PVBUS_MAX] = { { "KVMKVMKVM\0\0\0", "KVM", pvbus_kvm }, { "Microsoft Hv", "Hyper-V", pvbus_hyperv, pvbus_hyperv_print }, { "VMwareVMware", "VMware" }, { "XenVMMXenVMM", "Xen", pvbus_xen, pvbus_xen_print }, { "bhyve bhyve ", "bhyve" }, { VMM_HV_SIGNATURE, "OpenBSD", pvbus_kvm }, }; struct bus_dma_tag pvbus_dma_tag = { NULL, _bus_dmamap_create, _bus_dmamap_destroy, _bus_dmamap_load, _bus_dmamap_load_mbuf, _bus_dmamap_load_uio, _bus_dmamap_load_raw, _bus_dmamap_unload, _bus_dmamap_sync, _bus_dmamem_alloc, _bus_dmamem_alloc_range, _bus_dmamem_free, _bus_dmamem_map, _bus_dmamem_unmap, _bus_dmamem_mmap, }; struct pvbus_hv pvbus_hv[PVBUS_MAX]; struct pvbus_softc *pvbus_softc; int pvbus_probe(void) { /* Must be set in identcpu */ if (!has_hv_cpuid) return (0); return (1); } int pvbus_match(struct device *parent, void *match, void *aux) { const char **busname = (const char **)aux; return (strcmp(*busname, pvbus_cd.cd_name) == 0); } void pvbus_attach(struct device *parent, struct device *self, void *aux) { struct pvbus_softc *sc = (struct pvbus_softc *)self; int i, cnt; sc->pvbus_hv = pvbus_hv; pvbus_softc = sc; printf(":"); for (i = 0, cnt = 0; i < PVBUS_MAX; i++) { if (pvbus_hv[i].hv_base == 0) continue; if (cnt++) printf(","); printf(" %s", pvbus_types[i].name); if (pvbus_types[i].print != NULL) (pvbus_types[i].print)(&pvbus_hv[i]); } printf("\n"); config_search(pvbus_search, self, sc); } void pvbus_identify(void) { struct pvbus_hv *hv; uint32_t reg0, base; union { uint32_t regs[3]; char str[CPUID_HV_SIGNATURE_STRLEN]; } r; int i, cnt; const char *pv_name; for (base = CPUID_HV_SIGNATURE_START, cnt = 0; base < CPUID_HV_SIGNATURE_END; base += CPUID_HV_SIGNATURE_STEP) { CPUID(base, reg0, r.regs[0], r.regs[1], r.regs[2]); for (i = 0; i < 4; i++) { /* * Check if first 4 chars are printable ASCII as * minimal validity check */ if (r.str[i] < 32 || r.str[i] > 126) goto out; } for (i = 0; i < PVBUS_MAX; i++) { if (pvbus_types[i].signature == NULL || memcmp(pvbus_types[i].signature, r.str, CPUID_HV_SIGNATURE_STRLEN) != 0) continue; hv = &pvbus_hv[i]; hv->hv_base = base; if (pvbus_types[i].init != NULL) (pvbus_types[i].init)(hv); if (hw_vendor == NULL) { pv_name = pvbus_types[i].name; /* * Use the HV name as a fallback if we didn't * get the vendor name from the firmware/BIOS. */ if ((hw_vendor = malloc(strlen(pv_name) + 1, M_DEVBUF, M_NOWAIT)) != NULL) { strlcpy(hw_vendor, pv_name, strlen(pv_name) + 1); } } cnt++; } } out: if (cnt) has_hv_cpuid = 1; } void pvbus_init_cpu(void) { int i; for (i = 0; i < PVBUS_MAX; i++) { if (pvbus_hv[i].hv_base == 0) continue; if (pvbus_hv[i].hv_init_cpu != NULL) (pvbus_hv[i].hv_init_cpu)(&pvbus_hv[i]); } } int pvbus_activate(struct device *self, int act) { int rv = 0; switch (act) { case DVACT_SUSPEND: rv = config_activate_children(self, act); break; case DVACT_RESUME: rv = config_activate_children(self, act); break; case DVACT_POWERDOWN: rv = config_activate_children(self, act); break; default: rv = config_activate_children(self, act); break; } return (rv); } int pvbus_search(struct device *parent, void *arg, void *aux) { struct pvbus_softc *sc = (struct pvbus_softc *)aux; struct cfdata *cf = arg; struct pv_attach_args pva; pva.pva_busname = cf->cf_driver->cd_name; pva.pva_hv = sc->pvbus_hv; pva.pva_dmat = &pvbus_dma_tag; if (cf->cf_attach->ca_match(parent, cf, &pva) > 0) config_attach(parent, cf, &pva, pvbus_print); return (0); } int pvbus_print(void *aux, const char *pnp) { struct pv_attach_args *pva = aux; if (pnp) printf("%s at %s", pva->pva_busname, pnp); return (UNCONF); } void pvbus_shutdown(struct device *dev) { suspend_randomness(); log(LOG_KERN | LOG_NOTICE, "Shutting down in response to request" " from %s host\n", dev->dv_xname); prsignal(initprocess, SIGUSR2); } void pvbus_reboot(struct device *dev) { suspend_randomness(); log(LOG_KERN | LOG_NOTICE, "Rebooting in response to request" " from %s host\n", dev->dv_xname); prsignal(initprocess, SIGINT); } void pvbus_kvm(struct pvbus_hv *hv) { uint32_t regs[4]; CPUID(hv->hv_base + CPUID_OFFSET_KVM_FEATURES, regs[0], regs[1], regs[2], regs[3]); hv->hv_features = regs[0]; } extern void hv_delay(int usecs); void pvbus_hyperv(struct pvbus_hv *hv) { uint32_t regs[4]; CPUID(hv->hv_base + CPUID_OFFSET_HYPERV_FEATURES, regs[0], regs[1], regs[2], regs[3]); hv->hv_features = regs[0]; CPUID(hv->hv_base + CPUID_OFFSET_HYPERV_VERSION, regs[0], regs[1], regs[2], regs[3]); hv->hv_major = (regs[1] & HYPERV_VERSION_EBX_MAJOR_M) >> HYPERV_VERSION_EBX_MAJOR_S; hv->hv_minor = (regs[1] & HYPERV_VERSION_EBX_MINOR_M) >> HYPERV_VERSION_EBX_MINOR_S; #if NHYPERV > 0 if (hv->hv_features & CPUID_HV_MSR_TIME_REFCNT) delay_init(hv_delay, 4000); #endif } void pvbus_hyperv_print(struct pvbus_hv *hv) { printf(" %u.%u", hv->hv_major, hv->hv_minor); } void pvbus_xen(struct pvbus_hv *hv) { uint32_t regs[4]; CPUID(hv->hv_base + CPUID_OFFSET_XEN_VERSION, regs[0], regs[1], regs[2], regs[3]); hv->hv_major = regs[0] >> XEN_VERSION_MAJOR_S; hv->hv_minor = regs[0] & XEN_VERSION_MINOR_M; /* x2apic is broken in Xen 4.2 or older */ if ((hv->hv_major < 4) || (hv->hv_major == 4 && hv->hv_minor < 3)) { /* Remove CPU flag for x2apic */ cpu_ecxfeature &= ~CPUIDECX_X2APIC; } } void pvbus_xen_print(struct pvbus_hv *hv) { printf(" %u.%u", hv->hv_major, hv->hv_minor); } int pvbus_minor(struct pvbus_softc *sc, dev_t dev) { int hvid, cnt; struct pvbus_hv *hv; for (hvid = 0, cnt = 0; hvid < PVBUS_MAX; hvid++) { hv = &sc->pvbus_hv[hvid]; if (hv->hv_base == 0) continue; if (minor(dev) == cnt++) return (hvid); } return (-1); } int pvbusopen(dev_t dev, int flags, int mode, struct proc *p) { if (pvbus_softc == NULL) return (ENODEV); if (pvbus_minor(pvbus_softc, dev) == -1) return (ENXIO); return (0); } int pvbusclose(dev_t dev, int flags, int mode, struct proc *p) { if (pvbus_softc == NULL) return (ENODEV); if (pvbus_minor(pvbus_softc, dev) == -1) return (ENXIO); return (0); } int pvbusgetstr(size_t srclen, const char *src, char **dstp) { int error = 0; char *dst; /* * Reject size that is too short or obviously too long: * - Known pv backends other than vmware have a hard limit smaller than * PVBUS_KVOP_MAXSIZE in their messaging. vmware has a software * limit at 1MB, but current open-vm-tools has a limit at 64KB * (=PVBUS_KVOP_MAXSIZE). */ if (srclen < 1) return (EINVAL); else if (srclen > PVBUS_KVOP_MAXSIZE) return (ENAMETOOLONG); *dstp = dst = malloc(srclen + 1, M_TEMP, M_WAITOK | M_ZERO); if (src != NULL) { error = copyin(src, dst, srclen); dst[srclen] = '\0'; } return (error); } int pvbusioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) { struct pvbus_req *pvr = (struct pvbus_req *)data; struct pvbus_softc *sc = pvbus_softc; char *value = NULL, *key = NULL; const char *str = NULL; size_t valuelen = 0, keylen = 0, sz; int hvid, error = 0, op; struct pvbus_hv *hv; if (sc == NULL) return (ENODEV); if ((hvid = pvbus_minor(sc, dev)) == -1) return (ENXIO); switch (cmd) { case PVBUSIOC_KVWRITE: if ((flags & FWRITE) == 0) return (EPERM); case PVBUSIOC_KVREAD: hv = &sc->pvbus_hv[hvid]; if (hv->hv_base == 0 || hv->hv_kvop == NULL) return (ENXIO); break; case PVBUSIOC_TYPE: str = pvbus_types[hvid].name; sz = strlen(str) + 1; if (sz > pvr->pvr_keylen) return (ENOMEM); error = copyout(str, pvr->pvr_key, sz); return (error); default: return (ENOTTY); } str = NULL; op = PVBUS_KVREAD; switch (cmd) { case PVBUSIOC_KVWRITE: str = pvr->pvr_value; op = PVBUS_KVWRITE; /* FALLTHROUGH */ case PVBUSIOC_KVREAD: keylen = pvr->pvr_keylen; if ((error = pvbusgetstr(keylen, pvr->pvr_key, &key)) != 0) break; valuelen = pvr->pvr_valuelen; if ((error = pvbusgetstr(valuelen, str, &value)) != 0) break; /* Call driver-specific callback */ if ((error = (hv->hv_kvop)(hv->hv_arg, op, key, value, valuelen)) != 0) break; sz = strlen(value) + 1; if ((error = copyout(value, pvr->pvr_value, sz)) != 0) break; break; default: error = ENOTTY; break; } free(key, M_TEMP, keylen + 1); free(value, M_TEMP, valuelen + 1); return (error); }
121 31 90 3 1 41 11 1 7 8 14 22 50 3 67 21 49 90 31 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 /* $OpenBSD: udp6_output.c,v 1.65 2024/04/17 20:48:51 bluhm Exp $ */ /* $KAME: udp6_output.c,v 1.21 2001/02/07 11:51:54 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "pf.h" #include <sys/param.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/errno.h> #include <sys/stat.h> #include <sys/systm.h> #include <sys/syslog.h> #include <net/if.h> #include <net/if_var.h> #include <net/route.h> #if NPF > 0 #include <net/pfvar.h> #endif #include <netinet/in.h> #include <netinet6/in6_var.h> #include <netinet/ip.h> #include <netinet/ip_var.h> #include <netinet/in_pcb.h> #include <netinet/udp.h> #include <netinet/udp_var.h> #include <netinet/ip6.h> #include <netinet6/ip6_var.h> #include <netinet/icmp6.h> /* * UDP protocol implementation. * Per RFC 768, August, 1980. */ int udp6_output(struct inpcb *inp, struct mbuf *m, struct mbuf *addr6, struct mbuf *control) { u_int32_t ulen = m->m_pkthdr.len; u_int32_t plen = sizeof(struct udphdr) + ulen; int error = 0, priv = 0, hlen, flags; struct ip6_hdr *ip6; struct udphdr *udp6; const struct in6_addr *laddr, *faddr; struct ip6_pktopts *optp, opt; struct sockaddr_in6 tmp, valid; struct proc *p = curproc; /* XXX */ u_short fport; if ((inp->inp_socket->so_state & SS_PRIV) != 0) priv = 1; if (control) { if ((error = ip6_setpktopts(control, &opt, inp->inp_outputopts6, priv, IPPROTO_UDP)) != 0) goto release; optp = &opt; } else optp = inp->inp_outputopts6; if (addr6) { struct sockaddr_in6 *sin6; if ((error = in6_nam2sin6(addr6, &sin6))) goto release; if (sin6->sin6_port == 0) { error = EADDRNOTAVAIL; goto release; } if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { error = EADDRNOTAVAIL; goto release; } if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) { error = EISCONN; goto release; } /* protect *sin6 from overwrites */ tmp = *sin6; sin6 = &tmp; faddr = &sin6->sin6_addr; fport = sin6->sin6_port; /* allow 0 port */ /* KAME hack: embed scopeid */ if (in6_embedscope(&sin6->sin6_addr, sin6, inp->inp_outputopts6, inp->inp_moptions6) != 0) { error = EINVAL; goto release; } error = in6_pcbselsrc(&laddr, sin6, inp, optp); if (error) goto release; if (inp->inp_lport == 0){ error = in_pcbbind(inp, NULL, p); if (error) goto release; } if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6) && !IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, laddr)) { valid.sin6_addr = *laddr; valid.sin6_port = inp->inp_lport; valid.sin6_scope_id = 0; valid.sin6_family = AF_INET6; valid.sin6_len = sizeof(valid); error = in6_pcbaddrisavail(inp, &valid, 0, p); if (error) goto release; } } else { if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) { error = ENOTCONN; goto release; } laddr = &inp->inp_laddr6; faddr = &inp->inp_faddr6; fport = inp->inp_fport; } hlen = sizeof(struct ip6_hdr); /* * Calculate data length and get a mbuf * for UDP and IP6 headers. */ M_PREPEND(m, hlen + sizeof(struct udphdr), M_DONTWAIT); if (m == NULL) { error = ENOBUFS; goto releaseopt; } /* * Stuff checksum and output datagram. */ udp6 = (struct udphdr *)(mtod(m, caddr_t) + hlen); udp6->uh_sport = inp->inp_lport; /* lport is always set in the PCB */ udp6->uh_dport = fport; if (plen <= 0xffff) udp6->uh_ulen = htons((u_short)plen); else udp6->uh_ulen = 0; udp6->uh_sum = 0; ip6 = mtod(m, struct ip6_hdr *); ip6->ip6_flow = inp->inp_flowinfo & IPV6_FLOWINFO_MASK; ip6->ip6_vfc &= ~IPV6_VERSION_MASK; ip6->ip6_vfc |= IPV6_VERSION; #if 0 /* ip6_plen will be filled in ip6_output. */ ip6->ip6_plen = htons((u_short)plen); #endif ip6->ip6_nxt = IPPROTO_UDP; ip6->ip6_hlim = in6_selecthlim(inp); ip6->ip6_src = *laddr; ip6->ip6_dst = *faddr; m->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT; flags = 0; if (inp->inp_flags & IN6P_MINMTU) flags |= IPV6_MINMTU; udpstat_inc(udps_opackets); /* force routing table */ m->m_pkthdr.ph_rtableid = inp->inp_rtableid; #if NPF > 0 if (inp->inp_socket->so_state & SS_ISCONNECTED) pf_mbuf_link_inpcb(m, inp); #endif error = ip6_output(m, optp, &inp->inp_route, flags, inp->inp_moptions6, &inp->inp_seclevel); goto releaseopt; release: m_freem(m); releaseopt: if (control) { ip6_clearpktopts(&opt, -1); m_freem(control); } return (error); }
61 2 60 62 37 11 2 56 85 68 54 7 54 12 14 35 50 25 36 36 3 20 7 14 11 37 37 36 7 40 40 40 38 4 1 2 2 87 1 86 1 1 22 22 2 2 1 2 8 3 7 6 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 /* $OpenBSD: spkr.c,v 1.27 2022/04/06 18:59:29 naddy Exp $ */ /* $NetBSD: spkr.c,v 1.1 1998/04/15 20:26:18 drochner Exp $ */ /* * Copyright (c) 1990 Eric S. Raymond (esr@snark.thyrsus.com) * Copyright (c) 1990 Andrew A. Chernov (ache@astral.msk.su) * Copyright (c) 1990 Lennart Augustsson (lennart@augustsson.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Eric S. Raymond * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * spkr.c -- device driver for console speaker on 80386 * * v1.1 by Eric S. Raymond (esr@snark.thyrsus.com) Feb 1990 * modified for 386bsd by Andrew A. Chernov <ache@astral.msk.su> * 386bsd only clean version, all SYSV stuff removed * use hz value from param.c */ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/errno.h> #include <sys/device.h> #include <sys/malloc.h> #include <sys/uio.h> #include <sys/ioctl.h> #include <sys/conf.h> #include <sys/fcntl.h> #include <dev/isa/pcppivar.h> #include <dev/isa/spkrio.h> cdev_decl(spkr); int spkrprobe(struct device *, void *, void *); void spkrattach(struct device *, struct device *, void *); const struct cfattach spkr_ca = { sizeof(struct device), spkrprobe, spkrattach }; struct cfdriver spkr_cd = { NULL, "spkr", DV_DULL }; static pcppi_tag_t ppicookie; #define SPKRPRI (PZERO - 1) static void tone(u_int, u_int); static void rest(int); static void playinit(void); static void playtone(int, int, int); static void playstring(char *, size_t); /* emit tone of frequency freq for given number of milliseconds */ static void tone(u_int freq, u_int ms) { pcppi_bell(ppicookie, freq, ms, PCPPI_BELL_SLEEP); } /* rest for given number of milliseconds */ static void rest(int ms) { /* * Set timeout to endrest function, then give up the timeslice. * This is so other processes can execute while the rest is being * waited out. */ #ifdef SPKRDEBUG printf("rest: %dms\n", ms); #endif /* SPKRDEBUG */ if (ms > 0) tsleep_nsec(rest, SPKRPRI | PCATCH, "rest", MSEC_TO_NSEC(ms)); } /**************** PLAY STRING INTERPRETER BEGINS HERE ********************** * * Play string interpretation is modelled on IBM BASIC 2.0's PLAY statement; * M[LNS] are missing and the ~ synonym and octave-tracking facility is added. * Requires tone(), rest(), and endtone(). String play is not interruptible * except possibly at physical block boundaries. */ #define toupper(c) ((c) - ' ' * (((c) >= 'a') && ((c) <= 'z'))) #define isdigit(c) (((c) >= '0') && ((c) <= '9')) #define dtoi(c) ((c) - '0') static int octave; /* currently selected octave */ static int whole; /* whole-note time at current tempo, in milliseconds */ static int value; /* whole divisor for note time, quarter note = 1 */ static int fill; /* controls spacing of notes */ static int octtrack; /* octave-tracking on? */ static int octprefix; /* override current octave-tracking state? */ /* * Magic number avoidance... */ #define SECS_PER_MIN 60 /* seconds per minute */ #define WHOLE_NOTE 4 /* quarter notes per whole note */ #define MIN_VALUE 64 /* the most we can divide a note by */ #define DFLT_VALUE 4 /* default value (quarter-note) */ #define FILLTIME 8 /* for articulation, break note in parts */ #define STACCATO 6 /* 6/8 = 3/4 of note is filled */ #define NORMAL 7 /* 7/8ths of note interval is filled */ #define LEGATO 8 /* all of note interval is filled */ #define DFLT_OCTAVE 4 /* default octave */ #define MIN_TEMPO 32 /* minimum tempo */ #define DFLT_TEMPO 120 /* default tempo */ #define MAX_TEMPO 255 /* max tempo */ #define NUM_MULT 3 /* numerator of dot multiplier */ #define DENOM_MULT 2 /* denominator of dot multiplier */ /* letter to half-tone: A B C D E F G */ static int notetab[8] = { 9, 11, 0, 2, 4, 5, 7 }; /* * This is the American Standard A440 Equal-Tempered scale with frequencies * rounded to nearest integer. Thank Goddess for the good ol' CRC Handbook... * our octave 0 is standard octave 2. */ #define OCTAVE_NOTES 12 /* semitones per octave */ static int pitchtab[] = { /* C C# D D# E F F# G G# A A# B*/ /* 0 */ 65, 69, 73, 78, 82, 87, 93, 98, 103, 110, 117, 123, /* 1 */ 131, 139, 147, 156, 165, 175, 185, 196, 208, 220, 233, 247, /* 2 */ 262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494, /* 3 */ 523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988, /* 4 */ 1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1975, /* 5 */ 2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951, /* 6 */ 4186, 4435, 4698, 4978, 5274, 5588, 5920, 6272, 6644, 7040, 7459, 7902, }; #define NOCTAVES (sizeof(pitchtab) / sizeof(pitchtab[0]) / OCTAVE_NOTES) static void playinit(void) { octave = DFLT_OCTAVE; whole = (1000 * SECS_PER_MIN * WHOLE_NOTE) / DFLT_TEMPO; fill = NORMAL; value = DFLT_VALUE; octtrack = 0; octprefix = 1; /* act as though there was an initial O(n) */ } /* play tone of proper duration for current rhythm signature */ static void playtone(int pitch, int value, int sustain) { int sound, silence, snum = 1, sdenom = 1; /* this weirdness avoids floating-point arithmetic */ for (; sustain; sustain--) { snum *= NUM_MULT; sdenom *= DENOM_MULT; } if (pitch == -1) rest(whole * snum / (value * sdenom)); else if (pitch >= 0 && pitch < (sizeof(pitchtab) / sizeof(pitchtab[0]))) { sound = (whole * snum) / (value * sdenom) - (whole * (FILLTIME - fill)) / (value * FILLTIME); silence = whole * (FILLTIME-fill) * snum / (FILLTIME * value * sdenom); #ifdef SPKRDEBUG printf("playtone: pitch %d for %dms, rest for %dms\n", pitch, sound, silence); #endif /* SPKRDEBUG */ tone(pitchtab[pitch], sound); if (fill != LEGATO) rest(silence); } } /* interpret and play an item from a notation string */ static void playstring(char *cp, size_t slen) { int pitch, lastpitch = OCTAVE_NOTES * DFLT_OCTAVE; #define GETNUM(cp, v) \ do { \ for (v = 0; slen > 0 && isdigit(cp[1]); ) { \ v = v * 10 + (*++cp - '0'); \ slen--; \ } \ } while (0) for (; slen--; cp++) { int sustain, timeval, tempo; char c = toupper(*cp); #ifdef SPKRDEBUG printf("playstring: %c (%x)\n", c, c); #endif /* SPKRDEBUG */ switch (c) { case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': /* compute pitch */ pitch = notetab[c - 'A'] + octave * OCTAVE_NOTES; /* this may be followed by an accidental sign */ if (slen > 0 && (cp[1] == '#' || cp[1] == '+')) { ++pitch; ++cp; slen--; } else if (slen > 0 && cp[1] == '-') { --pitch; ++cp; slen--; } /* * If octave-tracking mode is on, and there has been * no octave-setting prefix, find the version of the * current letter note closest to the last regardless * of octave. */ if (octtrack && !octprefix) { if (abs(pitch - lastpitch) > abs(pitch + OCTAVE_NOTES - lastpitch)) { ++octave; pitch += OCTAVE_NOTES; } if (abs(pitch - lastpitch) > abs(pitch - OCTAVE_NOTES - lastpitch)) { --octave; pitch -= OCTAVE_NOTES; } } octprefix = 0; lastpitch = pitch; /* * ...which may in turn be followed by an override * time value */ GETNUM(cp, timeval); if (timeval <= 0 || timeval > MIN_VALUE) timeval = value; /* ...and/or sustain dots */ for (sustain = 0; slen > 0 && cp[1] == '.'; cp++) { slen--; sustain++; } /* time to emit the actual tone */ playtone(pitch, timeval, sustain); break; case 'O': if (slen > 0 && (cp[1] == 'N' || cp[1] == 'n')) { octprefix = octtrack = 0; ++cp; slen--; } else if (slen > 0 && (cp[1] == 'L' || cp[1] == 'l')) { octtrack = 1; ++cp; slen--; } else { GETNUM(cp, octave); if (octave >= NOCTAVES) octave = DFLT_OCTAVE; octprefix = 1; } break; case '>': if (octave < NOCTAVES - 1) octave++; octprefix = 1; break; case '<': if (octave > 0) octave--; octprefix = 1; break; case 'N': GETNUM(cp, pitch); for (sustain = 0; slen > 0 && cp[1] == '.'; cp++) { slen--; sustain++; } playtone(pitch - 1, value, sustain); break; case 'L': GETNUM(cp, value); if (value <= 0 || value > MIN_VALUE) value = DFLT_VALUE; break; case 'P': case '~': /* this may be followed by an override time value */ GETNUM(cp, timeval); if (timeval <= 0 || timeval > MIN_VALUE) timeval = value; for (sustain = 0; slen > 0 && cp[1] == '.'; cp++) { slen--; sustain++; } playtone(-1, timeval, sustain); break; case 'T': GETNUM(cp, tempo); if (tempo < MIN_TEMPO || tempo > MAX_TEMPO) tempo = DFLT_TEMPO; whole = (1000 * SECS_PER_MIN * WHOLE_NOTE) / tempo; break; case 'M': if (slen > 0 && (cp[1] == 'N' || cp[1] == 'n')) { fill = NORMAL; ++cp; slen--; } else if (slen > 0 && (cp[1] == 'L' || cp[1] == 'l')) { fill = LEGATO; ++cp; slen--; } else if (slen > 0 && (cp[1] == 'S' || cp[1] == 's')) { fill = STACCATO; ++cp; slen--; } break; } } } /******************* UNIX DRIVER HOOKS BEGIN HERE ************************** * * This section implements driver hooks to run playstring() and the tone(), * endtone(), and rest() functions defined above. */ static int spkr_active; /* exclusion flag */ static void *spkr_inbuf; static int spkr_attached = 0; int spkrprobe(struct device *parent, void *match, void *aux) { return (!spkr_attached); } void spkrattach(struct device *parent, struct device *self, void *aux) { printf("\n"); ppicookie = ((struct pcppi_attach_args *)aux)->pa_cookie; spkr_attached = 1; } int spkropen(dev_t dev, int flags, int mode, struct proc *p) { #ifdef SPKRDEBUG printf("spkropen: entering with dev = %x\n", dev); #endif /* SPKRDEBUG */ if (minor(dev) != 0 || !spkr_attached) return (ENXIO); else if (spkr_active) return (EBUSY); else { playinit(); spkr_inbuf = malloc(DEV_BSIZE, M_DEVBUF, M_WAITOK); spkr_active = 1; } return (0); } int spkrwrite(dev_t dev, struct uio *uio, int flags) { size_t n; int error; #ifdef SPKRDEBUG printf("spkrwrite: entering with dev = %x, count = %zu\n", dev, uio->uio_resid); #endif /* SPKRDEBUG */ if (minor(dev) != 0) return (ENXIO); else { n = ulmin(DEV_BSIZE, uio->uio_resid); error = uiomove(spkr_inbuf, n, uio); if (!error) playstring((char *)spkr_inbuf, n); return (error); } } int spkrclose(dev_t dev, int flags, int mode, struct proc *p) { #ifdef SPKRDEBUG printf("spkrclose: entering with dev = %x\n", dev); #endif /* SPKRDEBUG */ if (minor(dev) != 0) return (ENXIO); else { tone(0, 0); free(spkr_inbuf, M_DEVBUF, DEV_BSIZE); spkr_active = 0; } return (0); } int spkrioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { tone_t *tp, ttp; int error; #ifdef SPKRDEBUG printf("spkrioctl: entering with dev = %x, cmd = %lx\n", dev, cmd); #endif /* SPKRDEBUG */ if (minor(dev) != 0) return (ENXIO); switch (cmd) { case SPKRTONE: case SPKRTUNE: if ((flag & FWRITE) == 0) return (EACCES); default: break; } switch (cmd) { case SPKRTONE: tp = (tone_t *)data; if (tp->duration < 0 || tp->frequency < 0) return (EINVAL); if (tp->frequency == 0) rest(tp->duration); else tone(tp->frequency, tp->duration); break; case SPKRTUNE: tp = (tone_t *)(*(caddr_t *)data); for (; ; tp++) { error = copyin(tp, &ttp, sizeof(tone_t)); if (error) return (error); if (ttp.duration < 0 || ttp.frequency < 0) return (EINVAL); if (ttp.duration == 0) break; if (ttp.frequency == 0) rest(ttp.duration); else tone(ttp.frequency, ttp.duration); } break; default: return (ENOTTY); } return (0); }
173 121 1 39 1 5 5 7 1 2 9 5 1 1 2 4 6 9 2 26 35 8 27 3 3 2 1 19 19 245 22 68 49 20 31 45 17 11 6 3 173 162 1 4 3 8 9 1 1 2 1 2 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 /* $OpenBSD: udp_usrreq.c,v 1.320 2024/04/17 20:48:51 bluhm Exp $ */ /* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 * * NRL grants permission for redistribution and use in source and binary * forms, with or without modification, of the software and documentation * created at NRL provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgements: * This product includes software developed by the University of * California, Berkeley and its contributors. * This product includes software developed at the Information * Technology Division, US Naval Research Laboratory. * 4. Neither the name of the NRL nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the US Naval * Research Laboratory (NRL). */ #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/protosw.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/sysctl.h> #include <sys/domain.h> #include <net/if.h> #include <net/if_var.h> #include <net/if_media.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/in_var.h> #include <netinet/ip.h> #include <netinet/in_pcb.h> #include <netinet/ip_var.h> #include <netinet/ip_icmp.h> #include <netinet/udp.h> #include <netinet/udp_var.h> #ifdef IPSEC #include <netinet/ip_ipsp.h> #include <netinet/ip_esp.h> #endif #ifdef INET6 #include <netinet6/in6_var.h> #include <netinet6/ip6_var.h> #include <netinet6/ip6protosw.h> #endif /* INET6 */ #include "pf.h" #if NPF > 0 #include <net/pfvar.h> #endif #ifdef PIPEX #include <netinet/if_ether.h> #include <net/pipex.h> #endif /* * UDP protocol implementation. * Per RFC 768, August, 1980. */ int udpcksum = 1; u_int udp_sendspace = 9216; /* really max datagram size */ u_int udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in)); /* 40 1K datagrams */ const struct pr_usrreqs udp_usrreqs = { .pru_attach = udp_attach, .pru_detach = udp_detach, .pru_lock = udp_lock, .pru_unlock = udp_unlock, .pru_locked = udp_locked, .pru_bind = udp_bind, .pru_connect = udp_connect, .pru_disconnect = udp_disconnect, .pru_shutdown = udp_shutdown, .pru_send = udp_send, .pru_control = in_control, .pru_sockaddr = in_sockaddr, .pru_peeraddr = in_peeraddr, }; #ifdef INET6 const struct pr_usrreqs udp6_usrreqs = { .pru_attach = udp_attach, .pru_detach = udp_detach, .pru_lock = udp_lock, .pru_unlock = udp_unlock, .pru_locked = udp_locked, .pru_bind = udp_bind, .pru_connect = udp_connect, .pru_disconnect = udp_disconnect, .pru_shutdown = udp_shutdown, .pru_send = udp_send, .pru_control = in6_control, .pru_sockaddr = in6_sockaddr, .pru_peeraddr = in6_peeraddr, }; #endif const struct sysctl_bounded_args udpctl_vars[] = { { UDPCTL_CHECKSUM, &udpcksum, 0, 1 }, { UDPCTL_RECVSPACE, &udp_recvspace, 0, INT_MAX }, { UDPCTL_SENDSPACE, &udp_sendspace, 0, INT_MAX }, }; struct inpcbtable udbtable; #ifdef INET6 struct inpcbtable udb6table; #endif struct cpumem *udpcounters; void udp_sbappend(struct inpcb *, struct mbuf *, struct ip *, struct ip6_hdr *, int, struct udphdr *, struct sockaddr *, u_int32_t); int udp_output(struct inpcb *, struct mbuf *, struct mbuf *, struct mbuf *); void udp_notify(struct inpcb *, int); int udp_sysctl_udpstat(void *, size_t *, void *); #ifndef UDB_INITIAL_HASH_SIZE #define UDB_INITIAL_HASH_SIZE 128 #endif void udp_init(void) { udpcounters = counters_alloc(udps_ncounters); in_pcbinit(&udbtable, UDB_INITIAL_HASH_SIZE); #ifdef INET6 in_pcbinit(&udb6table, UDB_INITIAL_HASH_SIZE); #endif } int udp_input(struct mbuf **mp, int *offp, int proto, int af) { struct mbuf *m = *mp; int iphlen = *offp; struct ip *ip = NULL; struct udphdr *uh; struct inpcb *inp = NULL; struct ip save_ip; int len; u_int16_t savesum; union { struct sockaddr sa; struct sockaddr_in sin; #ifdef INET6 struct sockaddr_in6 sin6; #endif /* INET6 */ } srcsa, dstsa; struct ip6_hdr *ip6 = NULL; u_int32_t ipsecflowinfo = 0; udpstat_inc(udps_ipackets); IP6_EXTHDR_GET(uh, struct udphdr *, m, iphlen, sizeof(struct udphdr)); if (!uh) { udpstat_inc(udps_hdrops); return IPPROTO_DONE; } /* Check for illegal destination port 0 */ if (uh->uh_dport == 0) { udpstat_inc(udps_noport); goto bad; } /* * Make mbuf data length reflect UDP length. * If not enough data to reflect UDP length, drop. */ len = ntohs((u_int16_t)uh->uh_ulen); switch (af) { case AF_INET: if (m->m_pkthdr.len - iphlen != len) { if (len > (m->m_pkthdr.len - iphlen) || len < sizeof(struct udphdr)) { udpstat_inc(udps_badlen); goto bad; } m_adj(m, len - (m->m_pkthdr.len - iphlen)); } ip = mtod(m, struct ip *); /* * Save a copy of the IP header in case we want restore it * for sending an ICMP error message in response. */ save_ip = *ip; break; #ifdef INET6 case AF_INET6: /* jumbograms */ if (len == 0 && m->m_pkthdr.len - iphlen > 0xffff) len = m->m_pkthdr.len - iphlen; if (len != m->m_pkthdr.len - iphlen) { udpstat_inc(udps_badlen); goto bad; } ip6 = mtod(m, struct ip6_hdr *); break; #endif /* INET6 */ default: unhandled_af(af); } /* * Checksum extended UDP header and data. * from W.R.Stevens: check incoming udp cksums even if * udpcksum is not set. */ savesum = uh->uh_sum; if (uh->uh_sum == 0) { udpstat_inc(udps_nosum); #ifdef INET6 /* * In IPv6, the UDP checksum is ALWAYS used. */ if (ip6) goto bad; #endif /* INET6 */ } else { if ((m->m_pkthdr.csum_flags & M_UDP_CSUM_IN_OK) == 0) { if (m->m_pkthdr.csum_flags & M_UDP_CSUM_IN_BAD) { udpstat_inc(udps_badsum); goto bad; } udpstat_inc(udps_inswcsum); if (ip) uh->uh_sum = in4_cksum(m, IPPROTO_UDP, iphlen, len); #ifdef INET6 else if (ip6) uh->uh_sum = in6_cksum(m, IPPROTO_UDP, iphlen, len); #endif /* INET6 */ if (uh->uh_sum != 0) { udpstat_inc(udps_badsum); goto bad; } } } #ifdef IPSEC if (udpencap_enable && udpencap_port && esp_enable && #if NPF > 0 !(m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) && #endif uh->uh_dport == htons(udpencap_port)) { u_int32_t spi; int skip = iphlen + sizeof(struct udphdr); if (m->m_pkthdr.len - skip < sizeof(u_int32_t)) { /* packet too short */ m_freem(m); return IPPROTO_DONE; } m_copydata(m, skip, sizeof(u_int32_t), (caddr_t) &spi); /* * decapsulate if the SPI is not zero, otherwise pass * to userland */ if (spi != 0) { int protoff; if ((m = *mp = m_pullup(m, skip)) == NULL) { udpstat_inc(udps_hdrops); return IPPROTO_DONE; } /* remove the UDP header */ bcopy(mtod(m, u_char *), mtod(m, u_char *) + sizeof(struct udphdr), iphlen); m_adj(m, sizeof(struct udphdr)); skip -= sizeof(struct udphdr); espstat_inc(esps_udpencin); protoff = af == AF_INET ? offsetof(struct ip, ip_p) : offsetof(struct ip6_hdr, ip6_nxt); return ipsec_common_input(mp, skip, protoff, af, IPPROTO_ESP, 1); } } #endif /* IPSEC */ switch (af) { case AF_INET: bzero(&srcsa, sizeof(struct sockaddr_in)); srcsa.sin.sin_len = sizeof(struct sockaddr_in); srcsa.sin.sin_family = AF_INET; srcsa.sin.sin_port = uh->uh_sport; srcsa.sin.sin_addr = ip->ip_src; bzero(&dstsa, sizeof(struct sockaddr_in)); dstsa.sin.sin_len = sizeof(struct sockaddr_in); dstsa.sin.sin_family = AF_INET; dstsa.sin.sin_port = uh->uh_dport; dstsa.sin.sin_addr = ip->ip_dst; break; #ifdef INET6 case AF_INET6: bzero(&srcsa, sizeof(struct sockaddr_in6)); srcsa.sin6.sin6_len = sizeof(struct sockaddr_in6); srcsa.sin6.sin6_family = AF_INET6; srcsa.sin6.sin6_port = uh->uh_sport; #if 0 /*XXX inbound flowinfo */ srcsa.sin6.sin6_flowinfo = htonl(0x0fffffff) & ip6->ip6_flow; #endif /* KAME hack: recover scopeid */ in6_recoverscope(&srcsa.sin6, &ip6->ip6_src); bzero(&dstsa, sizeof(struct sockaddr_in6)); dstsa.sin6.sin6_len = sizeof(struct sockaddr_in6); dstsa.sin6.sin6_family = AF_INET6; dstsa.sin6.sin6_port = uh->uh_dport; #if 0 /*XXX inbound flowinfo */ dstsa.sin6.sin6_flowinfo = htonl(0x0fffffff) & ip6->ip6_flow; #endif /* KAME hack: recover scopeid */ in6_recoverscope(&dstsa.sin6, &ip6->ip6_dst); break; #endif /* INET6 */ } if (m->m_flags & (M_BCAST|M_MCAST)) { SIMPLEQ_HEAD(, inpcb) inpcblist; struct inpcbtable *table; /* * Deliver a multicast or broadcast datagram to *all* sockets * for which the local and remote addresses and ports match * those of the incoming datagram. This allows more than * one process to receive multi/broadcasts on the same port. * (This really ought to be done for unicast datagrams as * well, but that would cause problems with existing * applications that open both address-specific sockets and * a wildcard socket listening to the same port -- they would * end up receiving duplicates of every unicast datagram. * Those applications open the multiple sockets to overcome an * inadequacy of the UDP socket interface, but for backwards * compatibility we avoid the problem here rather than * fixing the interface. Maybe 4.5BSD will remedy this?) */ /* * Locate pcb(s) for datagram. * (Algorithm copied from raw_intr().) */ SIMPLEQ_INIT(&inpcblist); #ifdef INET6 if (ip6) table = &udb6table; else #endif table = &udbtable; rw_enter_write(&table->inpt_notify); mtx_enter(&table->inpt_mtx); TAILQ_FOREACH(inp, &table->inpt_queue, inp_queue) { if (ip6) KASSERT(ISSET(inp->inp_flags, INP_IPV6)); else KASSERT(!ISSET(inp->inp_flags, INP_IPV6)); if (inp->inp_socket->so_rcv.sb_state & SS_CANTRCVMORE) continue; if (rtable_l2(inp->inp_rtableid) != rtable_l2(m->m_pkthdr.ph_rtableid)) continue; if (inp->inp_lport != uh->uh_dport) continue; #ifdef INET6 if (ip6) { if (inp->inp_ip6_minhlim && inp->inp_ip6_minhlim > ip6->ip6_hlim) continue; if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) if (!IN6_ARE_ADDR_EQUAL( &inp->inp_laddr6, &ip6->ip6_dst)) continue; } else #endif /* INET6 */ { if (inp->inp_ip_minttl && inp->inp_ip_minttl > ip->ip_ttl) continue; if (inp->inp_laddr.s_addr != INADDR_ANY) { if (inp->inp_laddr.s_addr != ip->ip_dst.s_addr) continue; } } #ifdef INET6 if (ip6) { if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) if (!IN6_ARE_ADDR_EQUAL( &inp->inp_faddr6, &ip6->ip6_src) || inp->inp_fport != uh->uh_sport) continue; } else #endif /* INET6 */ if (inp->inp_faddr.s_addr != INADDR_ANY) { if (inp->inp_faddr.s_addr != ip->ip_src.s_addr || inp->inp_fport != uh->uh_sport) continue; } in_pcbref(inp); SIMPLEQ_INSERT_TAIL(&inpcblist, inp, inp_notify); /* * Don't look for additional matches if this one does * not have either the SO_REUSEPORT or SO_REUSEADDR * socket options set. This heuristic avoids searching * through all pcbs in the common case of a non-shared * port. It assumes that an application will never * clear these options after setting them. */ if ((inp->inp_socket->so_options & (SO_REUSEPORT | SO_REUSEADDR)) == 0) break; } mtx_leave(&table->inpt_mtx); if (SIMPLEQ_EMPTY(&inpcblist)) { rw_exit_write(&table->inpt_notify); /* * No matching pcb found; discard datagram. * (No need to send an ICMP Port Unreachable * for a broadcast or multicast datgram.) */ udpstat_inc(udps_noportbcast); goto bad; } while ((inp = SIMPLEQ_FIRST(&inpcblist)) != NULL) { struct mbuf *n; SIMPLEQ_REMOVE_HEAD(&inpcblist, inp_notify); if (SIMPLEQ_EMPTY(&inpcblist)) n = m; else n = m_copym(m, 0, M_COPYALL, M_NOWAIT); if (n != NULL) { udp_sbappend(inp, n, ip, ip6, iphlen, uh, &srcsa.sa, 0); } in_pcbunref(inp); } rw_exit_write(&table->inpt_notify); return IPPROTO_DONE; } /* * Locate pcb for datagram. */ #if NPF > 0 inp = pf_inp_lookup(m); #endif if (inp == NULL) { #ifdef INET6 if (ip6) { inp = in6_pcblookup(&udb6table, &ip6->ip6_src, uh->uh_sport, &ip6->ip6_dst, uh->uh_dport, m->m_pkthdr.ph_rtableid); } else #endif /* INET6 */ { inp = in_pcblookup(&udbtable, ip->ip_src, uh->uh_sport, ip->ip_dst, uh->uh_dport, m->m_pkthdr.ph_rtableid); } } if (inp == NULL) { udpstat_inc(udps_pcbhashmiss); #ifdef INET6 if (ip6) { inp = in6_pcblookup_listen(&udb6table, &ip6->ip6_dst, uh->uh_dport, m, m->m_pkthdr.ph_rtableid); } else #endif /* INET6 */ { inp = in_pcblookup_listen(&udbtable, ip->ip_dst, uh->uh_dport, m, m->m_pkthdr.ph_rtableid); } } #ifdef IPSEC if (ipsec_in_use) { struct m_tag *mtag; struct tdb_ident *tdbi; struct tdb *tdb; int error; mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); if (mtag != NULL) { tdbi = (struct tdb_ident *)(mtag + 1); tdb = gettdb(tdbi->rdomain, tdbi->spi, &tdbi->dst, tdbi->proto); } else tdb = NULL; error = ipsp_spd_lookup(m, af, iphlen, IPSP_DIRECTION_IN, tdb, inp ? &inp->inp_seclevel : NULL, NULL, NULL); if (error) { udpstat_inc(udps_nosec); tdb_unref(tdb); goto bad; } /* create ipsec options, id is not modified after creation */ if (tdb && tdb->tdb_ids) ipsecflowinfo = tdb->tdb_ids->id_flow; tdb_unref(tdb); } #endif /*IPSEC */ if (inp == NULL) { udpstat_inc(udps_noport); if (m->m_flags & (M_BCAST | M_MCAST)) { udpstat_inc(udps_noportbcast); goto bad; } #ifdef INET6 if (ip6) { uh->uh_sum = savesum; icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT,0); } else #endif /* INET6 */ { *ip = save_ip; uh->uh_sum = savesum; icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0); } return IPPROTO_DONE; } KASSERT(sotoinpcb(inp->inp_socket) == inp); soassertlocked(inp->inp_socket); #ifdef INET6 if (ip6 && inp->inp_ip6_minhlim && inp->inp_ip6_minhlim > ip6->ip6_hlim) { goto bad; } else #endif if (ip && inp->inp_ip_minttl && inp->inp_ip_minttl > ip->ip_ttl) { goto bad; } #if NPF > 0 if (inp->inp_socket->so_state & SS_ISCONNECTED) pf_inp_link(m, inp); #endif #ifdef PIPEX if (pipex_enable && inp->inp_pipex) { struct pipex_session *session; int off = iphlen + sizeof(struct udphdr); if ((session = pipex_l2tp_lookup_session(m, off)) != NULL) { m = *mp = pipex_l2tp_input(m, off, session, ipsecflowinfo); pipex_rele_session(session); if (m == NULL) { in_pcbunref(inp); return IPPROTO_DONE; } } } #endif udp_sbappend(inp, m, ip, ip6, iphlen, uh, &srcsa.sa, ipsecflowinfo); in_pcbunref(inp); return IPPROTO_DONE; bad: m_freem(m); in_pcbunref(inp); return IPPROTO_DONE; } void udp_sbappend(struct inpcb *inp, struct mbuf *m, struct ip *ip, struct ip6_hdr *ip6, int hlen, struct udphdr *uh, struct sockaddr *srcaddr, u_int32_t ipsecflowinfo) { struct socket *so = inp->inp_socket; struct mbuf *opts = NULL; hlen += sizeof(*uh); if (inp->inp_upcall != NULL) { m = (*inp->inp_upcall)(inp->inp_upcall_arg, m, ip, ip6, uh, hlen); if (m == NULL) return; } #ifdef INET6 if (ip6 && (inp->inp_flags & IN6P_CONTROLOPTS || so->so_options & SO_TIMESTAMP)) ip6_savecontrol(inp, m, &opts); #endif /* INET6 */ if (ip && (inp->inp_flags & INP_CONTROLOPTS || so->so_options & SO_TIMESTAMP)) ip_savecontrol(inp, &opts, ip, m); #ifdef INET6 if (ip6 && (inp->inp_flags & IN6P_RECVDSTPORT)) { struct mbuf **mp = &opts; while (*mp) mp = &(*mp)->m_next; *mp = sbcreatecontrol((caddr_t)&uh->uh_dport, sizeof(u_int16_t), IPV6_RECVDSTPORT, IPPROTO_IPV6); } #endif /* INET6 */ if (ip && (inp->inp_flags & INP_RECVDSTPORT)) { struct mbuf **mp = &opts; while (*mp) mp = &(*mp)->m_next; *mp = sbcreatecontrol((caddr_t)&uh->uh_dport, sizeof(u_int16_t), IP_RECVDSTPORT, IPPROTO_IP); } #ifdef IPSEC if (ipsecflowinfo && (inp->inp_flags & INP_IPSECFLOWINFO)) { struct mbuf **mp = &opts; while (*mp) mp = &(*mp)->m_next; *mp = sbcreatecontrol((caddr_t)&ipsecflowinfo, sizeof(u_int32_t), IP_IPSECFLOWINFO, IPPROTO_IP); } #endif m_adj(m, hlen); mtx_enter(&so->so_rcv.sb_mtx); if (sbappendaddr(so, &so->so_rcv, srcaddr, m, opts) == 0) { mtx_leave(&so->so_rcv.sb_mtx); udpstat_inc(udps_fullsock); m_freem(m); m_freem(opts); return; } mtx_leave(&so->so_rcv.sb_mtx); sorwakeup(so); } /* * Notify a udp user of an asynchronous error; * just wake up so that he can collect error status. */ void udp_notify(struct inpcb *inp, int errno) { inp->inp_socket->so_error = errno; sorwakeup(inp->inp_socket); sowwakeup(inp->inp_socket); } #ifdef INET6 void udp6_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *d) { struct udphdr uh; struct sockaddr_in6 sa6; struct ip6_hdr *ip6; struct mbuf *m; int off; void *cmdarg; struct ip6ctlparam *ip6cp = NULL; struct udp_portonly { u_int16_t uh_sport; u_int16_t uh_dport; } *uhp; struct inpcb *inp; void (*notify)(struct inpcb *, int) = udp_notify; if (sa == NULL) return; if (sa->sa_family != AF_INET6 || sa->sa_len != sizeof(struct sockaddr_in6)) return; if ((unsigned)cmd >= PRC_NCMDS) return; if (PRC_IS_REDIRECT(cmd)) notify = in_rtchange, d = NULL; else if (cmd == PRC_HOSTDEAD) d = NULL; else if (cmd == PRC_MSGSIZE) ; /* special code is present, see below */ else if (inet6ctlerrmap[cmd] == 0) return; /* if the parameter is from icmp6, decode it. */ if (d != NULL) { ip6cp = (struct ip6ctlparam *)d; m = ip6cp->ip6c_m; ip6 = ip6cp->ip6c_ip6; off = ip6cp->ip6c_off; cmdarg = ip6cp->ip6c_cmdarg; } else { m = NULL; ip6 = NULL; cmdarg = NULL; /* XXX: translate addresses into internal form */ sa6 = *satosin6(sa); if (in6_embedscope(&sa6.sin6_addr, &sa6, NULL, NULL)) { /* should be impossible */ return; } } if (ip6cp && ip6cp->ip6c_finaldst) { bzero(&sa6, sizeof(sa6)); sa6.sin6_family = AF_INET6; sa6.sin6_len = sizeof(sa6); sa6.sin6_addr = *ip6cp->ip6c_finaldst; /* XXX: assuming M is valid in this case */ sa6.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.ph_ifidx, ip6cp->ip6c_finaldst); if (in6_embedscope(ip6cp->ip6c_finaldst, &sa6, NULL, NULL)) { /* should be impossible */ return; } } else { /* XXX: translate addresses into internal form */ sa6 = *satosin6(sa); if (in6_embedscope(&sa6.sin6_addr, &sa6, NULL, NULL)) { /* should be impossible */ return; } } if (ip6) { /* * XXX: We assume that when IPV6 is non NULL, * M and OFF are valid. */ struct sockaddr_in6 sa6_src; /* check if we can safely examine src and dst ports */ if (m->m_pkthdr.len < off + sizeof(*uhp)) return; bzero(&uh, sizeof(uh)); m_copydata(m, off, sizeof(*uhp), (caddr_t)&uh); bzero(&sa6_src, sizeof(sa6_src)); sa6_src.sin6_family = AF_INET6; sa6_src.sin6_len = sizeof(sa6_src); sa6_src.sin6_addr = ip6->ip6_src; sa6_src.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.ph_ifidx, &ip6->ip6_src); if (in6_embedscope(&sa6_src.sin6_addr, &sa6_src, NULL, NULL)) { /* should be impossible */ return; } if (cmd == PRC_MSGSIZE) { /* * Check to see if we have a valid UDP socket * corresponding to the address in the ICMPv6 message * payload. */ inp = in6_pcblookup(&udb6table, &sa6.sin6_addr, uh.uh_dport, &sa6_src.sin6_addr, uh.uh_sport, rdomain); #if 0 /* * As the use of sendto(2) is fairly popular, * we may want to allow non-connected pcb too. * But it could be too weak against attacks... * We should at least check if the local address (= s) * is really ours. */ if (inp == NULL) { inp = in6_pcblookup_listen(&udb6table, &sa6_src.sin6_addr, uh.uh_sport, NULL, rdomain)) } #endif /* * Depending on the value of "valid" and routing table * size (mtudisc_{hi,lo}wat), we will: * - recalculate the new MTU and create the * corresponding routing entry, or * - ignore the MTU change notification. */ icmp6_mtudisc_update((struct ip6ctlparam *)d, inp != NULL); in_pcbunref(inp); /* * regardless of if we called icmp6_mtudisc_update(), * we need to call in6_pcbnotify(), to notify path * MTU change to the userland (2292bis-02), because * some unconnected sockets may share the same * destination and want to know the path MTU. */ } in6_pcbnotify(&udb6table, &sa6, uh.uh_dport, &sa6_src, uh.uh_sport, rdomain, cmd, cmdarg, notify); } else { in6_pcbnotify(&udb6table, &sa6, 0, &sa6_any, 0, rdomain, cmd, cmdarg, notify); } } #endif void udp_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *v) { struct ip *ip = v; struct udphdr *uhp; struct in_addr faddr; struct inpcb *inp; void (*notify)(struct inpcb *, int) = udp_notify; int errno; if (sa == NULL) return; if (sa->sa_family != AF_INET || sa->sa_len != sizeof(struct sockaddr_in)) return; faddr = satosin(sa)->sin_addr; if (faddr.s_addr == INADDR_ANY) return; if ((unsigned)cmd >= PRC_NCMDS) return; errno = inetctlerrmap[cmd]; if (PRC_IS_REDIRECT(cmd)) notify = in_rtchange, ip = 0; else if (cmd == PRC_HOSTDEAD) ip = 0; else if (errno == 0) return; if (ip) { uhp = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2)); #ifdef IPSEC /* PMTU discovery for udpencap */ if (cmd == PRC_MSGSIZE && ip_mtudisc && udpencap_enable && udpencap_port && uhp->uh_sport == htons(udpencap_port)) { udpencap_ctlinput(cmd, sa, rdomain, v); return; } #endif inp = in_pcblookup(&udbtable, ip->ip_dst, uhp->uh_dport, ip->ip_src, uhp->uh_sport, rdomain); if (inp != NULL) notify(inp, errno); in_pcbunref(inp); } else in_pcbnotifyall(&udbtable, satosin(sa), rdomain, errno, notify); } int udp_output(struct inpcb *inp, struct mbuf *m, struct mbuf *addr, struct mbuf *control) { struct sockaddr_in *sin = NULL; struct udpiphdr *ui; u_int32_t ipsecflowinfo = 0; struct sockaddr_in src_sin; int len = m->m_pkthdr.len; struct in_addr laddr; int error = 0; #ifdef INET6 if (ISSET(inp->inp_flags, INP_IPV6)) return (udp6_output(inp, m, addr, control)); #endif /* * Compute the packet length of the IP header, and * punt if the length looks bogus. */ if ((len + sizeof(struct udpiphdr)) > IP_MAXPACKET) { error = EMSGSIZE; goto release; } memset(&src_sin, 0, sizeof(src_sin)); if (control) { u_int clen; struct cmsghdr *cm; caddr_t cmsgs; /* * XXX: Currently, we assume all the optional information is * stored in a single mbuf. */ if (control->m_next) { error = EINVAL; goto release; } clen = control->m_len; cmsgs = mtod(control, caddr_t); do { if (clen < CMSG_LEN(0)) { error = EINVAL; goto release; } cm = (struct cmsghdr *)cmsgs; if (cm->cmsg_len < CMSG_LEN(0) || CMSG_ALIGN(cm->cmsg_len) > clen) { error = EINVAL; goto release; } #ifdef IPSEC if ((inp->inp_flags & INP_IPSECFLOWINFO) != 0 && cm->cmsg_len == CMSG_LEN(sizeof(ipsecflowinfo)) && cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_IPSECFLOWINFO) { ipsecflowinfo = *(u_int32_t *)CMSG_DATA(cm); } else #endif if (cm->cmsg_len == CMSG_LEN(sizeof(struct in_addr)) && cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_SENDSRCADDR) { memcpy(&src_sin.sin_addr, CMSG_DATA(cm), sizeof(struct in_addr)); src_sin.sin_family = AF_INET; src_sin.sin_len = sizeof(src_sin); /* no check on reuse when sin->sin_port == 0 */ if ((error = in_pcbaddrisavail(inp, &src_sin, 0, curproc))) goto release; } clen -= CMSG_ALIGN(cm->cmsg_len); cmsgs += CMSG_ALIGN(cm->cmsg_len); } while (clen); } if (addr) { if ((error = in_nam2sin(addr, &sin))) goto release; if (sin->sin_port == 0) { error = EADDRNOTAVAIL; goto release; } if (inp->inp_faddr.s_addr != INADDR_ANY) { error = EISCONN; goto release; } error = in_pcbselsrc(&laddr, sin, inp); if (error) goto release; if (inp->inp_lport == 0) { error = in_pcbbind(inp, NULL, curproc); if (error) goto release; } if (src_sin.sin_len > 0 && src_sin.sin_addr.s_addr != INADDR_ANY && src_sin.sin_addr.s_addr != inp->inp_laddr.s_addr) { src_sin.sin_port = inp->inp_lport; if (inp->inp_laddr.s_addr != INADDR_ANY && (error = in_pcbaddrisavail(inp, &src_sin, 0, curproc))) goto release; laddr = src_sin.sin_addr; } } else { if (inp->inp_faddr.s_addr == INADDR_ANY) { error = ENOTCONN; goto release; } laddr = inp->inp_laddr; } /* * Calculate data length and get a mbuf * for UDP and IP headers. */ M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT); if (m == NULL) { error = ENOBUFS; goto bail; } /* * Fill in mbuf with extended UDP header * and addresses and length put into network format. */ ui = mtod(m, struct udpiphdr *); bzero(ui->ui_x1, sizeof ui->ui_x1); ui->ui_pr = IPPROTO_UDP; ui->ui_len = htons((u_int16_t)len + sizeof (struct udphdr)); ui->ui_src = laddr; ui->ui_dst = sin ? sin->sin_addr : inp->inp_faddr; ui->ui_sport = inp->inp_lport; ui->ui_dport = sin ? sin->sin_port : inp->inp_fport; ui->ui_ulen = ui->ui_len; ((struct ip *)ui)->ip_len = htons(sizeof (struct udpiphdr) + len); ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; if (udpcksum) m->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT; udpstat_inc(udps_opackets); /* force routing table */ m->m_pkthdr.ph_rtableid = inp->inp_rtableid; #if NPF > 0 if (inp->inp_socket->so_state & SS_ISCONNECTED) pf_mbuf_link_inpcb(m, inp); #endif error = ip_output(m, inp->inp_options, &inp->inp_route, (inp->inp_socket->so_options & SO_BROADCAST), inp->inp_moptions, &inp->inp_seclevel, ipsecflowinfo); bail: m_freem(control); return (error); release: m_freem(m); goto bail; } int udp_attach(struct socket *so, int proto, int wait) { struct inpcbtable *table; int error; if (so->so_pcb != NULL) return EINVAL; if ((error = soreserve(so, udp_sendspace, udp_recvspace))) return error; NET_ASSERT_LOCKED(); #ifdef INET6 if (so->so_proto->pr_domain->dom_family == PF_INET6) table = &udb6table; else #endif table = &udbtable; if ((error = in_pcballoc(so, table, wait))) return error; #ifdef INET6 if (ISSET(sotoinpcb(so)->inp_flags, INP_IPV6)) sotoinpcb(so)->inp_ipv6.ip6_hlim = ip6_defhlim; else #endif sotoinpcb(so)->inp_ip.ip_ttl = ip_defttl; return 0; } int udp_detach(struct socket *so) { struct inpcb *inp; soassertlocked(so); inp = sotoinpcb(so); if (inp == NULL) return (EINVAL); in_pcbdetach(inp); return (0); } void udp_lock(struct socket *so) { struct inpcb *inp = sotoinpcb(so); NET_ASSERT_LOCKED(); mtx_enter(&inp->inp_mtx); } void udp_unlock(struct socket *so) { struct inpcb *inp = sotoinpcb(so); NET_ASSERT_LOCKED(); mtx_leave(&inp->inp_mtx); } int udp_locked(struct socket *so) { struct inpcb *inp = sotoinpcb(so); return mtx_owned(&inp->inp_mtx); } int udp_bind(struct socket *so, struct mbuf *addr, struct proc *p) { struct inpcb *inp = sotoinpcb(so); soassertlocked(so); return in_pcbbind(inp, addr, p); } int udp_connect(struct socket *so, struct mbuf *addr) { struct inpcb *inp = sotoinpcb(so); int error; soassertlocked(so); #ifdef INET6 if (ISSET(inp->inp_flags, INP_IPV6)) { if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) return (EISCONN); } else #endif { if (inp->inp_faddr.s_addr != INADDR_ANY) return (EISCONN); } error = in_pcbconnect(inp, addr); if (error) return (error); soisconnected(so); return (0); } int udp_disconnect(struct socket *so) { struct inpcb *inp = sotoinpcb(so); soassertlocked(so); #ifdef INET6 if (ISSET(inp->inp_flags, INP_IPV6)) { if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) return (ENOTCONN); } else #endif { if (inp->inp_faddr.s_addr == INADDR_ANY) return (ENOTCONN); } in_pcbunset_laddr(inp); in_pcbdisconnect(inp); so->so_state &= ~SS_ISCONNECTED; /* XXX */ return (0); } int udp_shutdown(struct socket *so) { soassertlocked(so); socantsendmore(so); return (0); } int udp_send(struct socket *so, struct mbuf *m, struct mbuf *addr, struct mbuf *control) { struct inpcb *inp = sotoinpcb(so); soassertlocked(so); #ifdef PIPEX if (inp->inp_pipex) { struct pipex_session *session; if (addr != NULL) session = pipex_l2tp_userland_lookup_session(m, mtod(addr, struct sockaddr *)); else #ifdef INET6 if (ISSET(inp->inp_flags, INP_IPV6)) session = pipex_l2tp_userland_lookup_session_ipv6( m, inp->inp_faddr6); else #endif session = pipex_l2tp_userland_lookup_session_ipv4( m, inp->inp_faddr); if (session != NULL) { m = pipex_l2tp_userland_output(m, session); pipex_rele_session(session); if (m == NULL) { m_freem(control); return (ENOMEM); } } } #endif return (udp_output(inp, m, addr, control)); } /* * Sysctl for udp variables. */ int udp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int error; /* All sysctl names at this level are terminal. */ if (namelen != 1) return (ENOTDIR); switch (name[0]) { case UDPCTL_BADDYNAMIC: NET_LOCK(); error = sysctl_struct(oldp, oldlenp, newp, newlen, baddynamicports.udp, sizeof(baddynamicports.udp)); NET_UNLOCK(); return (error); case UDPCTL_ROOTONLY: if (newp && securelevel > 0) return (EPERM); NET_LOCK(); error = sysctl_struct(oldp, oldlenp, newp, newlen, rootonlyports.udp, sizeof(rootonlyports.udp)); NET_UNLOCK(); return (error); case UDPCTL_STATS: if (newp != NULL) return (EPERM); return (udp_sysctl_udpstat(oldp, oldlenp, newp)); default: NET_LOCK(); error = sysctl_bounded_arr(udpctl_vars, nitems(udpctl_vars), name, namelen, oldp, oldlenp, newp, newlen); NET_UNLOCK(); return (error); } /* NOTREACHED */ } int udp_sysctl_udpstat(void *oldp, size_t *oldlenp, void *newp) { uint64_t counters[udps_ncounters]; struct udpstat udpstat; u_long *words = (u_long *)&udpstat; int i; CTASSERT(sizeof(udpstat) == (nitems(counters) * sizeof(u_long))); memset(&udpstat, 0, sizeof udpstat); counters_read(udpcounters, counters, nitems(counters), NULL); for (i = 0; i < nitems(counters); i++) words[i] = (u_long)counters[i]; return (sysctl_rdstruct(oldp, oldlenp, newp, &udpstat, sizeof(udpstat))); }
1239 1243 1242 1243 1241 1181 487 1746 1746 1746 1750 1052 1428 11 1747 1749 1749 4 1751 2 1243 11 1245 5 5 5 5 6 6 9 6 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 /* $OpenBSD: kern_sched.c,v 1.95 2024/02/28 13:43:44 mpi Exp $ */ /* * Copyright (c) 2007, 2008 Artur Grabowski <art@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/sched.h> #include <sys/proc.h> #include <sys/kthread.h> #include <sys/systm.h> #include <sys/clockintr.h> #include <sys/resourcevar.h> #include <sys/task.h> #include <sys/time.h> #include <sys/smr.h> #include <sys/tracepoint.h> #include <uvm/uvm_extern.h> void sched_kthreads_create(void *); int sched_proc_to_cpu_cost(struct cpu_info *ci, struct proc *p); struct proc *sched_steal_proc(struct cpu_info *); /* * To help choosing which cpu should run which process we keep track * of cpus which are currently idle and which cpus have processes * queued. */ struct cpuset sched_idle_cpus; struct cpuset sched_queued_cpus; struct cpuset sched_all_cpus; /* * Some general scheduler counters. */ uint64_t sched_nmigrations; /* Cpu migration counter */ uint64_t sched_nomigrations; /* Cpu no migration counter */ uint64_t sched_noidle; /* Times we didn't pick the idle task */ uint64_t sched_stolen; /* Times we stole proc from other cpus */ uint64_t sched_choose; /* Times we chose a cpu */ uint64_t sched_wasidle; /* Times we came out of idle */ int sched_smt; /* * A few notes about cpu_switchto that is implemented in MD code. * * cpu_switchto takes two arguments, the old proc and the proc * it should switch to. The new proc will never be NULL, so we always have * a saved state that we need to switch to. The old proc however can * be NULL if the process is exiting. NULL for the old proc simply * means "don't bother saving old state". * * cpu_switchto is supposed to atomically load the new state of the process * including the pcb, pmap and setting curproc, the p_cpu pointer in the * proc and p_stat to SONPROC. Atomically with respect to interrupts, other * cpus in the system must not depend on this state being consistent. * Therefore no locking is necessary in cpu_switchto other than blocking * interrupts during the context switch. */ /* * sched_init_cpu is called from main() for the boot cpu, then it's the * responsibility of the MD code to call it for all other cpus. */ void sched_init_cpu(struct cpu_info *ci) { struct schedstate_percpu *spc = &ci->ci_schedstate; int i; for (i = 0; i < SCHED_NQS; i++) TAILQ_INIT(&spc->spc_qs[i]); spc->spc_idleproc = NULL; clockintr_bind(&spc->spc_itimer, ci, itimer_update, NULL); clockintr_bind(&spc->spc_profclock, ci, profclock, NULL); clockintr_bind(&spc->spc_roundrobin, ci, roundrobin, NULL); clockintr_bind(&spc->spc_statclock, ci, statclock, NULL); kthread_create_deferred(sched_kthreads_create, ci); LIST_INIT(&spc->spc_deadproc); SIMPLEQ_INIT(&spc->spc_deferred); /* * Slight hack here until the cpuset code handles cpu_info * structures. */ cpuset_init_cpu(ci); #ifdef __HAVE_CPU_TOPOLOGY if (!sched_smt && ci->ci_smt_id > 0) return; #endif cpuset_add(&sched_all_cpus, ci); } void sched_kthreads_create(void *v) { struct cpu_info *ci = v; struct schedstate_percpu *spc = &ci->ci_schedstate; static int num; if (fork1(&proc0, FORK_SHAREVM|FORK_SHAREFILES|FORK_NOZOMBIE| FORK_SYSTEM|FORK_IDLE, sched_idle, ci, NULL, &spc->spc_idleproc)) panic("fork idle"); /* Name it as specified. */ snprintf(spc->spc_idleproc->p_p->ps_comm, sizeof(spc->spc_idleproc->p_p->ps_comm), "idle%d", num); num++; } void sched_idle(void *v) { struct schedstate_percpu *spc; struct proc *p = curproc; struct cpu_info *ci = v; int s; KERNEL_UNLOCK(); spc = &ci->ci_schedstate; /* * First time we enter here, we're not supposed to idle, * just go away for a while. */ SCHED_LOCK(s); cpuset_add(&sched_idle_cpus, ci); p->p_stat = SSLEEP; p->p_cpu = ci; atomic_setbits_int(&p->p_flag, P_CPUPEG); mi_switch(); cpuset_del(&sched_idle_cpus, ci); SCHED_UNLOCK(s); KASSERT(ci == curcpu()); KASSERT(curproc == spc->spc_idleproc); while (1) { while (!cpu_is_idle(curcpu())) { struct proc *dead; SCHED_LOCK(s); p->p_stat = SSLEEP; mi_switch(); SCHED_UNLOCK(s); while ((dead = LIST_FIRST(&spc->spc_deadproc))) { LIST_REMOVE(dead, p_hash); exit2(dead); } } splassert(IPL_NONE); smr_idle(); cpuset_add(&sched_idle_cpus, ci); cpu_idle_enter(); while (spc->spc_whichqs == 0) { #ifdef MULTIPROCESSOR if (spc->spc_schedflags & SPCF_SHOULDHALT && (spc->spc_schedflags & SPCF_HALTED) == 0) { cpuset_del(&sched_idle_cpus, ci); SCHED_LOCK(s); atomic_setbits_int(&spc->spc_schedflags, spc->spc_whichqs ? 0 : SPCF_HALTED); SCHED_UNLOCK(s); wakeup(spc); } #endif cpu_idle_cycle(); } cpu_idle_leave(); cpuset_del(&sched_idle_cpus, ci); } } /* * To free our address space we have to jump through a few hoops. * The freeing is done by the reaper, but until we have one reaper * per cpu, we have no way of putting this proc on the deadproc list * and waking up the reaper without risking having our address space and * stack torn from under us before we manage to switch to another proc. * Therefore we have a per-cpu list of dead processes where we put this * proc and have idle clean up that list and move it to the reaper list. * All this will be unnecessary once we can bind the reaper this cpu * and not risk having it switch to another in case it sleeps. */ void sched_exit(struct proc *p) { struct schedstate_percpu *spc = &curcpu()->ci_schedstate; LIST_INSERT_HEAD(&spc->spc_deadproc, p, p_hash); KERNEL_ASSERT_LOCKED(); sched_toidle(); } void sched_toidle(void) { struct schedstate_percpu *spc = &curcpu()->ci_schedstate; struct proc *idle; int s; #ifdef MULTIPROCESSOR /* This process no longer needs to hold the kernel lock. */ if (_kernel_lock_held()) __mp_release_all(&kernel_lock); #endif if (ISSET(spc->spc_schedflags, SPCF_ITIMER)) { atomic_clearbits_int(&spc->spc_schedflags, SPCF_ITIMER); clockintr_cancel(&spc->spc_itimer); } if (ISSET(spc->spc_schedflags, SPCF_PROFCLOCK)) { atomic_clearbits_int(&spc->spc_schedflags, SPCF_PROFCLOCK); clockintr_cancel(&spc->spc_profclock); } atomic_clearbits_int(&spc->spc_schedflags, SPCF_SWITCHCLEAR); SCHED_LOCK(s); idle = spc->spc_idleproc; idle->p_stat = SRUN; uvmexp.swtch++; TRACEPOINT(sched, off__cpu, idle->p_tid + THREAD_PID_OFFSET, idle->p_p->ps_pid); cpu_switchto(NULL, idle); panic("cpu_switchto returned"); } /* * Run queue management. */ void sched_init_runqueues(void) { } void setrunqueue(struct cpu_info *ci, struct proc *p, uint8_t prio) { struct schedstate_percpu *spc; int queue = prio >> 2; if (ci == NULL) ci = sched_choosecpu(p); KASSERT(ci != NULL); SCHED_ASSERT_LOCKED(); KASSERT(p->p_wchan == NULL); p->p_cpu = ci; p->p_stat = SRUN; p->p_runpri = prio; spc = &p->p_cpu->ci_schedstate; spc->spc_nrun++; TRACEPOINT(sched, enqueue, p->p_tid + THREAD_PID_OFFSET, p->p_p->ps_pid); TAILQ_INSERT_TAIL(&spc->spc_qs[queue], p, p_runq); spc->spc_whichqs |= (1U << queue); cpuset_add(&sched_queued_cpus, p->p_cpu); if (cpuset_isset(&sched_idle_cpus, p->p_cpu)) cpu_unidle(p->p_cpu); else if (prio < spc->spc_curpriority) need_resched(ci); } void remrunqueue(struct proc *p) { struct schedstate_percpu *spc; int queue = p->p_runpri >> 2; SCHED_ASSERT_LOCKED(); spc = &p->p_cpu->ci_schedstate; spc->spc_nrun--; TRACEPOINT(sched, dequeue, p->p_tid + THREAD_PID_OFFSET, p->p_p->ps_pid); TAILQ_REMOVE(&spc->spc_qs[queue], p, p_runq); if (TAILQ_EMPTY(&spc->spc_qs[queue])) { spc->spc_whichqs &= ~(1U << queue); if (spc->spc_whichqs == 0) cpuset_del(&sched_queued_cpus, p->p_cpu); } } struct proc * sched_chooseproc(void) { struct schedstate_percpu *spc = &curcpu()->ci_schedstate; struct proc *p; int queue; SCHED_ASSERT_LOCKED(); #ifdef MULTIPROCESSOR if (spc->spc_schedflags & SPCF_SHOULDHALT) { if (spc->spc_whichqs) { for (queue = 0; queue < SCHED_NQS; queue++) { while ((p = TAILQ_FIRST(&spc->spc_qs[queue]))) { remrunqueue(p); setrunqueue(NULL, p, p->p_runpri); if (p->p_cpu == curcpu()) { KASSERT(p->p_flag & P_CPUPEG); goto again; } } } } p = spc->spc_idleproc; if (p == NULL) panic("no idleproc set on CPU%d", CPU_INFO_UNIT(curcpu())); p->p_stat = SRUN; KASSERT(p->p_wchan == NULL); return (p); } again: #endif if (spc->spc_whichqs) { queue = ffs(spc->spc_whichqs) - 1; p = TAILQ_FIRST(&spc->spc_qs[queue]); remrunqueue(p); sched_noidle++; if (p->p_stat != SRUN) panic("thread %d not in SRUN: %d", p->p_tid, p->p_stat); } else if ((p = sched_steal_proc(curcpu())) == NULL) { p = spc->spc_idleproc; if (p == NULL) panic("no idleproc set on CPU%d", CPU_INFO_UNIT(curcpu())); p->p_stat = SRUN; } KASSERT(p->p_wchan == NULL); return (p); } struct cpu_info * sched_choosecpu_fork(struct proc *parent, int flags) { #ifdef MULTIPROCESSOR struct cpu_info *choice = NULL; int run, best_run = INT_MAX; struct cpu_info *ci; struct cpuset set; #if 0 /* * XXX * Don't do this until we have a painless way to move the cpu in exec. * Preferably when nuking the old pmap and getting a new one on a * new cpu. */ /* * PPWAIT forks are simple. We know that the parent will not * run until we exec and choose another cpu, so we just steal its * cpu. */ if (flags & FORK_PPWAIT) return (parent->p_cpu); #endif /* * Look at all cpus that are currently idle and have nothing queued. * If there are none, pick the one with least queued procs first, * then the one with lowest load average. */ cpuset_complement(&set, &sched_queued_cpus, &sched_idle_cpus); cpuset_intersection(&set, &set, &sched_all_cpus); if (cpuset_first(&set) == NULL) cpuset_copy(&set, &sched_all_cpus); while ((ci = cpuset_first(&set)) != NULL) { cpuset_del(&set, ci); run = ci->ci_schedstate.spc_nrun; if (choice == NULL || run < best_run) { choice = ci; best_run = run; } } return (choice); #else return (curcpu()); #endif } struct cpu_info * sched_choosecpu(struct proc *p) { #ifdef MULTIPROCESSOR struct cpu_info *choice = NULL; int last_cost = INT_MAX; struct cpu_info *ci; struct cpuset set; /* * If pegged to a cpu, don't allow it to move. */ if (p->p_flag & P_CPUPEG) return (p->p_cpu); sched_choose++; /* * Look at all cpus that are currently idle and have nothing queued. * If there are none, pick the cheapest of those. * (idle + queued could mean that the cpu is handling an interrupt * at this moment and haven't had time to leave idle yet). */ cpuset_complement(&set, &sched_queued_cpus, &sched_idle_cpus); cpuset_intersection(&set, &set, &sched_all_cpus); /* * First, just check if our current cpu is in that set, if it is, * this is simple. * Also, our cpu might not be idle, but if it's the current cpu * and it has nothing else queued and we're curproc, take it. */ if (cpuset_isset(&set, p->p_cpu) || (p->p_cpu == curcpu() && p->p_cpu->ci_schedstate.spc_nrun == 0 && (p->p_cpu->ci_schedstate.spc_schedflags & SPCF_SHOULDHALT) == 0 && curproc == p)) { sched_wasidle++; return (p->p_cpu); } if (cpuset_first(&set) == NULL) cpuset_copy(&set, &sched_all_cpus); while ((ci = cpuset_first(&set)) != NULL) { int cost = sched_proc_to_cpu_cost(ci, p); if (choice == NULL || cost < last_cost) { choice = ci; last_cost = cost; } cpuset_del(&set, ci); } if (p->p_cpu != choice) sched_nmigrations++; else sched_nomigrations++; return (choice); #else return (curcpu()); #endif } /* * Attempt to steal a proc from some cpu. */ struct proc * sched_steal_proc(struct cpu_info *self) { struct proc *best = NULL; #ifdef MULTIPROCESSOR struct schedstate_percpu *spc; int bestcost = INT_MAX; struct cpu_info *ci; struct cpuset set; KASSERT((self->ci_schedstate.spc_schedflags & SPCF_SHOULDHALT) == 0); /* Don't steal if we don't want to schedule processes in this CPU. */ if (!cpuset_isset(&sched_all_cpus, self)) return (NULL); cpuset_copy(&set, &sched_queued_cpus); while ((ci = cpuset_first(&set)) != NULL) { struct proc *p; int queue; int cost; cpuset_del(&set, ci); spc = &ci->ci_schedstate; queue = ffs(spc->spc_whichqs) - 1; TAILQ_FOREACH(p, &spc->spc_qs[queue], p_runq) { if (p->p_flag & P_CPUPEG) continue; cost = sched_proc_to_cpu_cost(self, p); if (best == NULL || cost < bestcost) { best = p; bestcost = cost; } } } if (best == NULL) return (NULL); TRACEPOINT(sched, steal, best->p_tid + THREAD_PID_OFFSET, best->p_p->ps_pid, CPU_INFO_UNIT(self)); remrunqueue(best); best->p_cpu = self; sched_stolen++; #endif return (best); } #ifdef MULTIPROCESSOR /* * Base 2 logarithm of an int. returns 0 for 0 (yeye, I know). */ static int log2(unsigned int i) { int ret = 0; while (i >>= 1) ret++; return (ret); } /* * Calculate the cost of moving the proc to this cpu. * * What we want is some guesstimate of how much "performance" it will * cost us to move the proc here. Not just for caches and TLBs and NUMA * memory, but also for the proc itself. A highly loaded cpu might not * be the best candidate for this proc since it won't get run. * * Just total guesstimates for now. */ int sched_cost_load = 1; int sched_cost_priority = 1; int sched_cost_runnable = 3; int sched_cost_resident = 1; #endif int sched_proc_to_cpu_cost(struct cpu_info *ci, struct proc *p) { int cost = 0; #ifdef MULTIPROCESSOR struct schedstate_percpu *spc; int l2resident = 0; spc = &ci->ci_schedstate; /* * First, account for the priority of the proc we want to move. * More willing to move, the lower the priority of the destination * and the higher the priority of the proc. */ if (!cpuset_isset(&sched_idle_cpus, ci)) { cost += (p->p_usrpri - spc->spc_curpriority) * sched_cost_priority; cost += sched_cost_runnable; } if (cpuset_isset(&sched_queued_cpus, ci)) cost += spc->spc_nrun * sched_cost_runnable; /* * Try to avoid the primary cpu as it handles hardware interrupts. * * XXX Needs to be revisited when we distribute interrupts * over cpus. */ if (CPU_IS_PRIMARY(ci)) cost += sched_cost_runnable; /* * If the proc is on this cpu already, lower the cost by how much * it has been running and an estimate of its footprint. */ if (p->p_cpu == ci && p->p_slptime == 0) { l2resident = log2(pmap_resident_count(p->p_vmspace->vm_map.pmap)); cost -= l2resident * sched_cost_resident; } #endif return (cost); } /* * Peg a proc to a cpu. */ void sched_peg_curproc(struct cpu_info *ci) { struct proc *p = curproc; int s; SCHED_LOCK(s); atomic_setbits_int(&p->p_flag, P_CPUPEG); setrunqueue(ci, p, p->p_usrpri); p->p_ru.ru_nvcsw++; mi_switch(); SCHED_UNLOCK(s); } #ifdef MULTIPROCESSOR void sched_start_secondary_cpus(void) { CPU_INFO_ITERATOR cii; struct cpu_info *ci; CPU_INFO_FOREACH(cii, ci) { struct schedstate_percpu *spc = &ci->ci_schedstate; if (CPU_IS_PRIMARY(ci) || !CPU_IS_RUNNING(ci)) continue; atomic_clearbits_int(&spc->spc_schedflags, SPCF_SHOULDHALT | SPCF_HALTED); #ifdef __HAVE_CPU_TOPOLOGY if (!sched_smt && ci->ci_smt_id > 0) continue; #endif cpuset_add(&sched_all_cpus, ci); } } void sched_stop_secondary_cpus(void) { CPU_INFO_ITERATOR cii; struct cpu_info *ci; /* * Make sure we stop the secondary CPUs. */ CPU_INFO_FOREACH(cii, ci) { struct schedstate_percpu *spc = &ci->ci_schedstate; if (CPU_IS_PRIMARY(ci) || !CPU_IS_RUNNING(ci)) continue; cpuset_del(&sched_all_cpus, ci); atomic_setbits_int(&spc->spc_schedflags, SPCF_SHOULDHALT); } CPU_INFO_FOREACH(cii, ci) { struct schedstate_percpu *spc = &ci->ci_schedstate; if (CPU_IS_PRIMARY(ci) || !CPU_IS_RUNNING(ci)) continue; while ((spc->spc_schedflags & SPCF_HALTED) == 0) { sleep_setup(spc, PZERO, "schedstate"); sleep_finish(0, (spc->spc_schedflags & SPCF_HALTED) == 0); } } } struct sched_barrier_state { struct cpu_info *ci; struct cond cond; }; void sched_barrier_task(void *arg) { struct sched_barrier_state *sb = arg; struct cpu_info *ci = sb->ci; sched_peg_curproc(ci); cond_signal(&sb->cond); atomic_clearbits_int(&curproc->p_flag, P_CPUPEG); } void sched_barrier(struct cpu_info *ci) { struct sched_barrier_state sb; struct task task; CPU_INFO_ITERATOR cii; if (ci == NULL) { CPU_INFO_FOREACH(cii, ci) { if (CPU_IS_PRIMARY(ci)) break; } } KASSERT(ci != NULL); if (ci == curcpu()) return; sb.ci = ci; cond_init(&sb.cond); task_set(&task, sched_barrier_task, &sb); task_add(systqmp, &task); cond_wait(&sb.cond, "sbar"); } #else void sched_barrier(struct cpu_info *ci) { } #endif /* * Functions to manipulate cpu sets. */ struct cpu_info *cpuset_infos[MAXCPUS]; static struct cpuset cpuset_all; void cpuset_init_cpu(struct cpu_info *ci) { cpuset_add(&cpuset_all, ci); cpuset_infos[CPU_INFO_UNIT(ci)] = ci; } void cpuset_clear(struct cpuset *cs) { memset(cs, 0, sizeof(*cs)); } void cpuset_add(struct cpuset *cs, struct cpu_info *ci) { unsigned int num = CPU_INFO_UNIT(ci); atomic_setbits_int(&cs->cs_set[num/32], (1U << (num % 32))); } void cpuset_del(struct cpuset *cs, struct cpu_info *ci) { unsigned int num = CPU_INFO_UNIT(ci); atomic_clearbits_int(&cs->cs_set[num/32], (1U << (num % 32))); } int cpuset_isset(struct cpuset *cs, struct cpu_info *ci) { unsigned int num = CPU_INFO_UNIT(ci); return (cs->cs_set[num/32] & (1U << (num % 32))); } void cpuset_add_all(struct cpuset *cs) { cpuset_copy(cs, &cpuset_all); } void cpuset_copy(struct cpuset *to, struct cpuset *from) { memcpy(to, from, sizeof(*to)); } struct cpu_info * cpuset_first(struct cpuset *cs) { int i; for (i = 0; i < CPUSET_ASIZE(ncpus); i++) if (cs->cs_set[i]) return (cpuset_infos[i * 32 + ffs(cs->cs_set[i]) - 1]); return (NULL); } void cpuset_union(struct cpuset *to, struct cpuset *a, struct cpuset *b) { int i; for (i = 0; i < CPUSET_ASIZE(ncpus); i++) to->cs_set[i] = a->cs_set[i] | b->cs_set[i]; } void cpuset_intersection(struct cpuset *to, struct cpuset *a, struct cpuset *b) { int i; for (i = 0; i < CPUSET_ASIZE(ncpus); i++) to->cs_set[i] = a->cs_set[i] & b->cs_set[i]; } void cpuset_complement(struct cpuset *to, struct cpuset *a, struct cpuset *b) { int i; for (i = 0; i < CPUSET_ASIZE(ncpus); i++) to->cs_set[i] = b->cs_set[i] & ~a->cs_set[i]; } int cpuset_cardinality(struct cpuset *cs) { int cardinality, i, n; cardinality = 0; for (i = 0; i < CPUSET_ASIZE(ncpus); i++) for (n = cs->cs_set[i]; n != 0; n &= n - 1) cardinality++; return (cardinality); } int sysctl_hwncpuonline(void) { return cpuset_cardinality(&sched_all_cpus); } int cpu_is_online(struct cpu_info *ci) { return cpuset_isset(&sched_all_cpus, ci); } #ifdef __HAVE_CPU_TOPOLOGY #include <sys/sysctl.h> int sysctl_hwsmt(void *oldp, size_t *oldlenp, void *newp, size_t newlen) { CPU_INFO_ITERATOR cii; struct cpu_info *ci; int err, newsmt; newsmt = sched_smt; err = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &newsmt, 0, 1); if (err) return err; if (newsmt == sched_smt) return 0; sched_smt = newsmt; CPU_INFO_FOREACH(cii, ci) { if (CPU_IS_PRIMARY(ci) || !CPU_IS_RUNNING(ci)) continue; if (ci->ci_smt_id == 0) continue; if (sched_smt) cpuset_add(&sched_all_cpus, ci); else cpuset_del(&sched_all_cpus, ci); } return 0; } #endif
1 13 3 1 6 1 1 1 1 1 1 10 6 1 1 1 1 5 1 1 2 1 1 1 2 2 2 2 1 1 4 4 4 5 1 2 1 1 4 4 1 2 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 22 24 1 1 1 1 1 1 2 1 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 /* $OpenBSD: ip_mroute.c,v 1.142 2024/04/06 14:23:27 bluhm Exp $ */ /* $NetBSD: ip_mroute.c,v 1.85 2004/04/26 01:31:57 matt Exp $ */ /* * Copyright (c) 1989 Stephen Deering * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Stephen Deering of Stanford University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ip_mroute.c 8.2 (Berkeley) 11/15/93 */ /* * IP multicast forwarding procedures * * Written by David Waitzman, BBN Labs, August 1988. * Modified by Steve Deering, Stanford, February 1989. * Modified by Mark J. Steiglitz, Stanford, May, 1991 * Modified by Van Jacobson, LBL, January 1993 * Modified by Ajit Thyagarajan, PARC, August 1993 * Modified by Bill Fenner, PARC, April 1994 * Modified by Charles M. Hannum, NetBSD, May 1995. * Modified by Ahmed Helmy, SGI, June 1996 * Modified by George Edmond Eddy (Rusty), ISI, February 1998 * Modified by Pavlin Radoslavov, USC/ISI, May 1998, August 1999, October 2000 * Modified by Hitoshi Asaeda, WIDE, August 2000 * Modified by Pavlin Radoslavov, ICSI, October 2002 * * MROUTING Revision: 1.2 * advanced API support, bandwidth metering and signaling */ #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/protosw.h> #include <sys/ioctl.h> #include <sys/syslog.h> #include <net/if.h> #include <net/if_var.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_var.h> #include <netinet/in_pcb.h> #include <netinet/igmp.h> #include <netinet/ip_mroute.h> /* #define MCAST_DEBUG */ #ifdef MCAST_DEBUG int mcast_debug = 1; #define DPRINTF(fmt, args...) \ do { \ if (mcast_debug) \ printf("%s:%d " fmt "\n", \ __func__, __LINE__, ## args); \ } while (0) #else #define DPRINTF(fmt, args...) \ do { } while (0) #endif /* * Globals. All but ip_mrouter and ip_mrtproto could be static, * except for netstat or debugging purposes. */ struct socket *ip_mrouter[RT_TABLEID_MAX + 1]; struct rttimer_queue ip_mrouterq; uint64_t mrt_count[RT_TABLEID_MAX + 1]; int ip_mrtproto = IGMP_DVMRP; /* for netstat only */ struct mrtstat mrtstat; struct rtentry *mfc_find(struct ifnet *, struct in_addr *, struct in_addr *, unsigned int); int get_sg_cnt(unsigned int, struct sioc_sg_req *); int get_vif_cnt(unsigned int, struct sioc_vif_req *); int mrt_rtwalk_mfcsysctl(struct rtentry *, void *, unsigned int); int ip_mrouter_init(struct socket *, struct mbuf *); int mrouter_rtwalk_delete(struct rtentry *, void *, unsigned int); int get_version(struct mbuf *); int add_vif(struct socket *, struct mbuf *); int del_vif(struct socket *, struct mbuf *); void update_mfc_params(struct mfcctl2 *, int, unsigned int); int mfc_add(struct mfcctl2 *, struct in_addr *, struct in_addr *, int, unsigned int, int); int add_mfc(struct socket *, struct mbuf *); int del_mfc(struct socket *, struct mbuf *); int set_api_config(struct socket *, struct mbuf *); /* chose API capabilities */ int get_api_support(struct mbuf *); int get_api_config(struct mbuf *); int socket_send(struct socket *, struct mbuf *, struct sockaddr_in *); int ip_mdq(struct mbuf *, struct ifnet *, struct rtentry *); struct ifnet *if_lookupbyvif(vifi_t, unsigned int); struct rtentry *rt_mcast_add(struct ifnet *, struct sockaddr *, struct sockaddr *); void mrt_mcast_del(struct rtentry *, unsigned int); /* * Kernel multicast routing API capabilities and setup. * If more API capabilities are added to the kernel, they should be * recorded in `mrt_api_support'. */ static const u_int32_t mrt_api_support = (MRT_MFC_FLAGS_DISABLE_WRONGVIF | MRT_MFC_RP); static u_int32_t mrt_api_config = 0; /* * Find a route for a given origin IP address and Multicast group address * Type of service parameter to be added in the future!!! * Statistics are updated by the caller if needed * (mrtstat.mrts_mfc_lookups and mrtstat.mrts_mfc_misses) */ struct rtentry * mfc_find(struct ifnet *ifp, struct in_addr *origin, struct in_addr *group, unsigned int rtableid) { struct rtentry *rt; struct sockaddr_in msin; memset(&msin, 0, sizeof(msin)); msin.sin_len = sizeof(msin); msin.sin_family = AF_INET; msin.sin_addr = *group; rt = rtalloc(sintosa(&msin), 0, rtableid); do { if (!rtisvalid(rt)) { rtfree(rt); return NULL; } /* Don't consider non multicast routes. */ if (ISSET(rt->rt_flags, RTF_HOST | RTF_MULTICAST) != (RTF_HOST | RTF_MULTICAST)) continue; /* Return first occurrence if interface is not specified. */ if (ifp == NULL) return (rt); if (rt->rt_ifidx == ifp->if_index) return (rt); } while ((rt = rtable_iterate(rt)) != NULL); return (NULL); } /* * Handle MRT setsockopt commands to modify the multicast routing tables. */ int ip_mrouter_set(struct socket *so, int optname, struct mbuf *m) { struct inpcb *inp = sotoinpcb(so); int error; if (optname != MRT_INIT && so != ip_mrouter[inp->inp_rtableid]) error = ENOPROTOOPT; else switch (optname) { case MRT_INIT: error = ip_mrouter_init(so, m); break; case MRT_DONE: error = ip_mrouter_done(so); break; case MRT_ADD_VIF: error = add_vif(so, m); break; case MRT_DEL_VIF: error = del_vif(so, m); break; case MRT_ADD_MFC: error = add_mfc(so, m); break; case MRT_DEL_MFC: error = del_mfc(so, m); break; case MRT_API_CONFIG: error = set_api_config(so, m); break; default: error = ENOPROTOOPT; break; } return (error); } /* * Handle MRT getsockopt commands */ int ip_mrouter_get(struct socket *so, int optname, struct mbuf *m) { struct inpcb *inp = sotoinpcb(so); int error; if (so != ip_mrouter[inp->inp_rtableid]) error = ENOPROTOOPT; else { switch (optname) { case MRT_VERSION: error = get_version(m); break; case MRT_API_SUPPORT: error = get_api_support(m); break; case MRT_API_CONFIG: error = get_api_config(m); break; default: error = ENOPROTOOPT; break; } } return (error); } /* * Handle ioctl commands to obtain information from the cache */ int mrt_ioctl(struct socket *so, u_long cmd, caddr_t data) { struct inpcb *inp = sotoinpcb(so); int error; if (inp == NULL) return (ENOTCONN); KERNEL_LOCK(); if (so != ip_mrouter[inp->inp_rtableid]) error = EINVAL; else switch (cmd) { case SIOCGETVIFCNT: NET_LOCK_SHARED(); error = get_vif_cnt(inp->inp_rtableid, (struct sioc_vif_req *)data); NET_UNLOCK_SHARED(); break; case SIOCGETSGCNT: NET_LOCK_SHARED(); error = get_sg_cnt(inp->inp_rtableid, (struct sioc_sg_req *)data); NET_UNLOCK_SHARED(); break; default: error = ENOTTY; break; } KERNEL_UNLOCK(); return (error); } /* * returns the packet, byte, rpf-failure count for the source group provided */ int get_sg_cnt(unsigned int rtableid, struct sioc_sg_req *req) { struct rtentry *rt; struct mfc *mfc; rt = mfc_find(NULL, &req->src, &req->grp, rtableid); if (rt == NULL) { req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff; return (EADDRNOTAVAIL); } req->pktcnt = req->bytecnt = req->wrong_if = 0; do { /* Don't consider non multicast routes. */ if (ISSET(rt->rt_flags, RTF_HOST | RTF_MULTICAST) != (RTF_HOST | RTF_MULTICAST)) continue; mfc = (struct mfc *)rt->rt_llinfo; if (mfc == NULL) continue; req->pktcnt += mfc->mfc_pkt_cnt; req->bytecnt += mfc->mfc_byte_cnt; req->wrong_if += mfc->mfc_wrong_if; } while ((rt = rtable_iterate(rt)) != NULL); return (0); } /* * returns the input and output packet and byte counts on the vif provided */ int get_vif_cnt(unsigned int rtableid, struct sioc_vif_req *req) { struct ifnet *ifp; struct vif *v; vifi_t vifi = req->vifi; if ((ifp = if_lookupbyvif(vifi, rtableid)) == NULL) return (EINVAL); v = (struct vif *)ifp->if_mcast; req->icount = v->v_pkt_in; req->ocount = v->v_pkt_out; req->ibytes = v->v_bytes_in; req->obytes = v->v_bytes_out; return (0); } int mrt_sysctl_vif(void *oldp, size_t *oldlenp) { caddr_t where = oldp; size_t needed, given; struct ifnet *ifp; struct vif *vifp; struct vifinfo vinfo; given = *oldlenp; needed = 0; memset(&vinfo, 0, sizeof vinfo); TAILQ_FOREACH(ifp, &ifnetlist, if_list) { if ((vifp = (struct vif *)ifp->if_mcast) == NULL) continue; vinfo.v_vifi = vifp->v_id; vinfo.v_flags = vifp->v_flags; vinfo.v_threshold = vifp->v_threshold; vinfo.v_lcl_addr = vifp->v_lcl_addr; vinfo.v_rmt_addr = vifp->v_rmt_addr; vinfo.v_pkt_in = vifp->v_pkt_in; vinfo.v_pkt_out = vifp->v_pkt_out; vinfo.v_bytes_in = vifp->v_bytes_in; vinfo.v_bytes_out = vifp->v_bytes_out; needed += sizeof(vinfo); if (where && needed <= given) { int error; error = copyout(&vinfo, where, sizeof(vinfo)); if (error) return (error); where += sizeof(vinfo); } } if (where) { *oldlenp = needed; if (given < needed) return (ENOMEM); } else *oldlenp = (11 * needed) / 10; return (0); } struct mfcsysctlarg { struct mfcinfo *msa_minfos; size_t msa_len; size_t msa_needed; }; int mrt_rtwalk_mfcsysctl(struct rtentry *rt, void *arg, unsigned int rtableid) { struct mfc *mfc = (struct mfc *)rt->rt_llinfo; struct mfcsysctlarg *msa = (struct mfcsysctlarg *)arg; struct ifnet *ifp; struct vif *v; struct mfcinfo *minfo; int new = 0; /* Skip entries being removed. */ if (mfc == NULL) return (0); /* Skip non-multicast routes. */ if (ISSET(rt->rt_flags, RTF_HOST | RTF_MULTICAST) != (RTF_HOST | RTF_MULTICAST)) return (0); /* User just asked for the output size. */ if (msa->msa_minfos == NULL) { msa->msa_needed += sizeof(*minfo); return (0); } /* Skip route with invalid interfaces. */ if ((ifp = if_get(rt->rt_ifidx)) == NULL) return (0); if ((v = (struct vif *)ifp->if_mcast) == NULL) { if_put(ifp); return (0); } for (minfo = msa->msa_minfos; (uint8_t *)(minfo + 1) <= (uint8_t *)msa->msa_minfos + msa->msa_len; minfo++) { /* Find a new entry or update old entry. */ if (minfo->mfc_origin.s_addr != satosin(rt->rt_gateway)->sin_addr.s_addr || minfo->mfc_mcastgrp.s_addr != satosin(rt_key(rt))->sin_addr.s_addr) { if (minfo->mfc_origin.s_addr != 0 || minfo->mfc_mcastgrp.s_addr != 0) continue; new = 1; } minfo->mfc_origin = satosin(rt->rt_gateway)->sin_addr; minfo->mfc_mcastgrp = satosin(rt_key(rt))->sin_addr; minfo->mfc_parent = mfc->mfc_parent; minfo->mfc_pkt_cnt += mfc->mfc_pkt_cnt; minfo->mfc_byte_cnt += mfc->mfc_byte_cnt; minfo->mfc_ttls[v->v_id] = mfc->mfc_ttl; break; } if (new != 0) msa->msa_needed += sizeof(*minfo); if_put(ifp); return (0); } int mrt_sysctl_mfc(void *oldp, size_t *oldlenp) { unsigned int rtableid; int error; struct mfcsysctlarg msa; if (oldp != NULL && *oldlenp > MAXPHYS) return (EINVAL); memset(&msa, 0, sizeof(msa)); if (oldp != NULL && *oldlenp > 0) { msa.msa_minfos = malloc(*oldlenp, M_TEMP, M_WAITOK | M_ZERO); msa.msa_len = *oldlenp; } for (rtableid = 0; rtableid <= RT_TABLEID_MAX; rtableid++) { rtable_walk(rtableid, AF_INET, NULL, mrt_rtwalk_mfcsysctl, &msa); } if (msa.msa_minfos != NULL && msa.msa_needed > 0 && (error = copyout(msa.msa_minfos, oldp, msa.msa_needed)) != 0) { free(msa.msa_minfos, M_TEMP, msa.msa_len); return (error); } free(msa.msa_minfos, M_TEMP, msa.msa_len); *oldlenp = msa.msa_needed; return (0); } /* * Enable multicast routing */ int ip_mrouter_init(struct socket *so, struct mbuf *m) { struct inpcb *inp = sotoinpcb(so); unsigned int rtableid = inp->inp_rtableid; int *v; if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_IGMP) return (EOPNOTSUPP); if (m == NULL || m->m_len < sizeof(int)) return (EINVAL); v = mtod(m, int *); if (*v != 1) return (EINVAL); if (ip_mrouter[rtableid] != NULL) return (EADDRINUSE); ip_mrouter[rtableid] = so; return (0); } int mrouter_rtwalk_delete(struct rtentry *rt, void *arg, unsigned int rtableid) { /* Skip non-multicast routes. */ if (ISSET(rt->rt_flags, RTF_HOST | RTF_MULTICAST) != (RTF_HOST | RTF_MULTICAST)) return (0); return EEXIST; } /* * Disable multicast routing */ int ip_mrouter_done(struct socket *so) { struct inpcb *inp = sotoinpcb(so); struct ifnet *ifp; unsigned int rtableid = inp->inp_rtableid; int error; NET_ASSERT_LOCKED(); /* Delete all remaining installed multicast routes. */ do { struct rtentry *rt = NULL; error = rtable_walk(rtableid, AF_INET, &rt, mrouter_rtwalk_delete, NULL); if (rt != NULL && error == EEXIST) { mrt_mcast_del(rt, rtableid); error = EAGAIN; } rtfree(rt); } while (error == EAGAIN); /* Unregister all interfaces in the domain. */ TAILQ_FOREACH(ifp, &ifnetlist, if_list) { if (ifp->if_rdomain != rtableid) continue; vif_delete(ifp); } mrt_api_config = 0; ip_mrouter[rtableid] = NULL; mrt_count[rtableid] = 0; return (0); } int get_version(struct mbuf *m) { int *v = mtod(m, int *); *v = 0x0305; /* XXX !!!! */ m->m_len = sizeof(int); return (0); } /* * Configure API capabilities */ int set_api_config(struct socket *so, struct mbuf *m) { struct inpcb *inp = sotoinpcb(so); struct ifnet *ifp; u_int32_t *apival; unsigned int rtableid = inp->inp_rtableid; if (m == NULL || m->m_len < sizeof(u_int32_t)) return (EINVAL); apival = mtod(m, u_int32_t *); /* * We can set the API capabilities only if it is the first operation * after MRT_INIT. I.e.: * - there are no vifs installed * - the MFC table is empty */ TAILQ_FOREACH(ifp, &ifnetlist, if_list) { if (ifp->if_rdomain != rtableid) continue; if (ifp->if_mcast == NULL) continue; *apival = 0; return (EPERM); } if (mrt_count[rtableid] > 0) { *apival = 0; return (EPERM); } mrt_api_config = *apival & mrt_api_support; *apival = mrt_api_config; return (0); } /* * Get API capabilities */ int get_api_support(struct mbuf *m) { u_int32_t *apival; if (m == NULL || m->m_len < sizeof(u_int32_t)) return (EINVAL); apival = mtod(m, u_int32_t *); *apival = mrt_api_support; return (0); } /* * Get API configured capabilities */ int get_api_config(struct mbuf *m) { u_int32_t *apival; if (m == NULL || m->m_len < sizeof(u_int32_t)) return (EINVAL); apival = mtod(m, u_int32_t *); *apival = mrt_api_config; return (0); } static struct sockaddr_in sin = { sizeof(sin), AF_INET }; int add_vif(struct socket *so, struct mbuf *m) { struct inpcb *inp = sotoinpcb(so); struct vifctl *vifcp; struct vif *vifp; struct ifaddr *ifa; struct ifnet *ifp; struct ifreq ifr; int error; unsigned int rtableid = inp->inp_rtableid; NET_ASSERT_LOCKED(); if (m == NULL || m->m_len < sizeof(struct vifctl)) return (EINVAL); vifcp = mtod(m, struct vifctl *); if (vifcp->vifc_vifi >= MAXVIFS) return (EINVAL); if (in_nullhost(vifcp->vifc_lcl_addr)) return (EADDRNOTAVAIL); if (if_lookupbyvif(vifcp->vifc_vifi, rtableid) != NULL) return (EADDRINUSE); /* Tunnels are no longer supported use gif(4) instead. */ if (vifcp->vifc_flags & VIFF_TUNNEL) return (EOPNOTSUPP); { sin.sin_addr = vifcp->vifc_lcl_addr; ifa = ifa_ifwithaddr(sintosa(&sin), rtableid); if (ifa == NULL) return (EADDRNOTAVAIL); } /* Use the physical interface associated with the address. */ ifp = ifa->ifa_ifp; if (ifp->if_mcast != NULL) return (EADDRINUSE); { /* Make sure the interface supports multicast. */ if ((ifp->if_flags & IFF_MULTICAST) == 0) return (EOPNOTSUPP); /* Enable promiscuous reception of all IP multicasts. */ memset(&ifr, 0, sizeof(ifr)); satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in); satosin(&ifr.ifr_addr)->sin_family = AF_INET; satosin(&ifr.ifr_addr)->sin_addr = zeroin_addr; KERNEL_LOCK(); error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr); KERNEL_UNLOCK(); if (error) return (error); } vifp = malloc(sizeof(*vifp), M_MRTABLE, M_WAITOK | M_ZERO); ifp->if_mcast = (caddr_t)vifp; vifp->v_id = vifcp->vifc_vifi; vifp->v_flags = vifcp->vifc_flags; vifp->v_threshold = vifcp->vifc_threshold; vifp->v_lcl_addr = vifcp->vifc_lcl_addr; vifp->v_rmt_addr = vifcp->vifc_rmt_addr; return (0); } int del_vif(struct socket *so, struct mbuf *m) { struct inpcb *inp = sotoinpcb(so); struct ifnet *ifp; vifi_t *vifip; unsigned int rtableid = inp->inp_rtableid; NET_ASSERT_LOCKED(); if (m == NULL || m->m_len < sizeof(vifi_t)) return (EINVAL); vifip = mtod(m, vifi_t *); if ((ifp = if_lookupbyvif(*vifip, rtableid)) == NULL) return (EADDRNOTAVAIL); vif_delete(ifp); return (0); } void vif_delete(struct ifnet *ifp) { struct vif *v; struct ifreq ifr; if ((v = (struct vif *)ifp->if_mcast) == NULL) return; ifp->if_mcast = NULL; memset(&ifr, 0, sizeof(ifr)); satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in); satosin(&ifr.ifr_addr)->sin_family = AF_INET; satosin(&ifr.ifr_addr)->sin_addr = zeroin_addr; KERNEL_LOCK(); (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr); KERNEL_UNLOCK(); free(v, M_MRTABLE, sizeof(*v)); } void mfc_expire_route(struct rtentry *rt, u_int rtableid) { struct mfc *mfc = (struct mfc *)rt->rt_llinfo; /* Skip entry being deleted. */ if (mfc == NULL) return; DPRINTF("Route domain %d origin %#08X group %#08x interface %d " "expire %s", rtableid, satosin(rt->rt_gateway)->sin_addr.s_addr, satosin(rt_key(rt))->sin_addr.s_addr, rt->rt_ifidx, mfc->mfc_expire ? "yes" : "no"); /* Not expired, add it back to the queue. */ if (mfc->mfc_expire == 0) { mfc->mfc_expire = 1; rt_timer_add(rt, &ip_mrouterq, rtableid); return; } mrt_mcast_del(rt, rtableid); } int mfc_add_route(struct ifnet *ifp, struct sockaddr *origin, struct sockaddr *group, struct mfcctl2 *mfccp, int wait) { struct vif *v = (struct vif *)ifp->if_mcast; struct rtentry *rt; struct mfc *mfc; unsigned int rtableid = ifp->if_rdomain; rt = rt_mcast_add(ifp, origin, group); if (rt == NULL) return (EHOSTUNREACH); mfc = malloc(sizeof(*mfc), M_MRTABLE, wait | M_ZERO); if (mfc == NULL) { DPRINTF("origin %#08X group %#08X parent %d (%s) " "malloc failed", satosin(origin)->sin_addr.s_addr, satosin(group)->sin_addr.s_addr, mfccp->mfcc_parent, ifp->if_xname); mrt_mcast_del(rt, rtableid); rtfree(rt); return (ENOMEM); } rt->rt_llinfo = (caddr_t)mfc; rt_timer_add(rt, &ip_mrouterq, rtableid); mfc->mfc_parent = mfccp->mfcc_parent; mfc->mfc_pkt_cnt = 0; mfc->mfc_byte_cnt = 0; mfc->mfc_wrong_if = 0; mfc->mfc_ttl = mfccp->mfcc_ttls[v->v_id]; mfc->mfc_flags = mfccp->mfcc_flags[v->v_id] & mrt_api_config & MRT_MFC_FLAGS_ALL; mfc->mfc_expire = 0; /* set the RP address */ if (mrt_api_config & MRT_MFC_RP) mfc->mfc_rp = mfccp->mfcc_rp; else mfc->mfc_rp = zeroin_addr; rtfree(rt); return (0); } void update_mfc_params(struct mfcctl2 *mfccp, int wait, unsigned int rtableid) { struct rtentry *rt; struct mfc *mfc; struct ifnet *ifp; int i; struct sockaddr_in osin, msin; memset(&osin, 0, sizeof(osin)); osin.sin_len = sizeof(osin); osin.sin_family = AF_INET; osin.sin_addr = mfccp->mfcc_origin; memset(&msin, 0, sizeof(msin)); msin.sin_len = sizeof(msin); msin.sin_family = AF_INET; msin.sin_addr = mfccp->mfcc_mcastgrp; for (i = 0; i < MAXVIFS; i++) { /* Don't add/del upstream routes here. */ if (i == mfccp->mfcc_parent) continue; /* Test for vif existence and then update the entry. */ if ((ifp = if_lookupbyvif(i, rtableid)) == NULL) continue; rt = mfc_find(ifp, &mfccp->mfcc_origin, &mfccp->mfcc_mcastgrp, rtableid); /* vif not configured or removed. */ if (mfccp->mfcc_ttls[i] == 0) { /* Route doesn't exist, nothing to do. */ if (rt == NULL) continue; DPRINTF("del route (group %#08X) for vif %d (%s)", mfccp->mfcc_mcastgrp.s_addr, i, ifp->if_xname); mrt_mcast_del(rt, rtableid); rtfree(rt); continue; } /* Route exists, look for changes. */ if (rt != NULL) { mfc = (struct mfc *)rt->rt_llinfo; /* Skip route being deleted. */ if (mfc == NULL) { rtfree(rt); continue; } /* No new changes to apply. */ if (mfccp->mfcc_ttls[i] == mfc->mfc_ttl && mfccp->mfcc_parent == mfc->mfc_parent) { rtfree(rt); continue; } DPRINTF("update route (group %#08X) for vif %d (%s)", mfccp->mfcc_mcastgrp.s_addr, i, ifp->if_xname); mfc->mfc_ttl = mfccp->mfcc_ttls[i]; mfc->mfc_parent = mfccp->mfcc_parent; rtfree(rt); continue; } DPRINTF("add route (group %#08X) for vif %d (%s)", mfccp->mfcc_mcastgrp.s_addr, i, ifp->if_xname); mfc_add_route(ifp, sintosa(&osin), sintosa(&msin), mfccp, wait); } /* Create route for the parent interface. */ if ((ifp = if_lookupbyvif(mfccp->mfcc_parent, rtableid)) == NULL) { DPRINTF("failed to find upstream interface %d", mfccp->mfcc_parent); return; } /* We already have a route, nothing to do here. */ if ((rt = mfc_find(ifp, &mfccp->mfcc_origin, &mfccp->mfcc_mcastgrp, rtableid)) != NULL) { rtfree(rt); return; } DPRINTF("add upstream route (group %#08X) for if %s", mfccp->mfcc_mcastgrp.s_addr, ifp->if_xname); mfc_add_route(ifp, sintosa(&osin), sintosa(&msin), mfccp, wait); } int mfc_add(struct mfcctl2 *mfcctl2, struct in_addr *origin, struct in_addr *group, int vidx, unsigned int rtableid, int wait) { struct ifnet *ifp; struct vif *v; struct mfcctl2 mfcctl; ifp = if_lookupbyvif(vidx, rtableid); if (ifp == NULL || (v = (struct vif *)ifp->if_mcast) == NULL) return (EHOSTUNREACH); memset(&mfcctl, 0, sizeof(mfcctl)); if (mfcctl2 == NULL) { mfcctl.mfcc_origin = *origin; mfcctl.mfcc_mcastgrp = *group; mfcctl.mfcc_parent = vidx; } else memcpy(&mfcctl, mfcctl2, sizeof(mfcctl)); update_mfc_params(&mfcctl, wait, rtableid); return (0); } int add_mfc(struct socket *so, struct mbuf *m) { struct inpcb *inp = sotoinpcb(so); struct mfcctl2 mfcctl2; int mfcctl_size = sizeof(struct mfcctl); unsigned int rtableid = inp->inp_rtableid; NET_ASSERT_LOCKED(); if (mrt_api_config & MRT_API_FLAGS_ALL) mfcctl_size = sizeof(struct mfcctl2); if (m == NULL || m->m_len < mfcctl_size) return (EINVAL); /* * select data size depending on API version. */ if (mrt_api_config & MRT_API_FLAGS_ALL) { struct mfcctl2 *mp2 = mtod(m, struct mfcctl2 *); memcpy((caddr_t)&mfcctl2, mp2, sizeof(*mp2)); } else { struct mfcctl *mp = mtod(m, struct mfcctl *); memcpy((caddr_t)&mfcctl2, mp, sizeof(*mp)); memset((caddr_t)&mfcctl2 + sizeof(struct mfcctl), 0, sizeof(mfcctl2) - sizeof(struct mfcctl)); } if (mfc_add(&mfcctl2, &mfcctl2.mfcc_origin, &mfcctl2.mfcc_mcastgrp, mfcctl2.mfcc_parent, rtableid, M_WAITOK) == -1) return (EINVAL); return (0); } int del_mfc(struct socket *so, struct mbuf *m) { struct inpcb *inp = sotoinpcb(so); struct rtentry *rt; struct mfcctl2 mfcctl2; int mfcctl_size = sizeof(struct mfcctl); struct mfcctl *mp; unsigned int rtableid = inp->inp_rtableid; NET_ASSERT_LOCKED(); /* * XXX: for deleting MFC entries the information in entries * of size "struct mfcctl" is sufficient. */ if (m == NULL || m->m_len < mfcctl_size) return (EINVAL); mp = mtod(m, struct mfcctl *); memcpy((caddr_t)&mfcctl2, mp, sizeof(*mp)); memset((caddr_t)&mfcctl2 + sizeof(struct mfcctl), 0, sizeof(mfcctl2) - sizeof(struct mfcctl)); DPRINTF("origin %#08X group %#08X rtableid %d", mfcctl2.mfcc_origin.s_addr, mfcctl2.mfcc_mcastgrp.s_addr, rtableid); while ((rt = mfc_find(NULL, &mfcctl2.mfcc_origin, &mfcctl2.mfcc_mcastgrp, rtableid)) != NULL) { mrt_mcast_del(rt, rtableid); rtfree(rt); } return (0); } int socket_send(struct socket *so, struct mbuf *mm, struct sockaddr_in *src) { if (so != NULL) { int ret; mtx_enter(&so->so_rcv.sb_mtx); ret = sbappendaddr(so, &so->so_rcv, sintosa(src), mm, NULL); mtx_leave(&so->so_rcv.sb_mtx); if (ret != 0) { sorwakeup(so); return (0); } } m_freem(mm); return (-1); } /* * IP multicast forwarding function. This function assumes that the packet * pointed to by "ip" has arrived on (or is about to be sent to) the interface * pointed to by "ifp", and the packet is to be relayed to other networks * that have members of the packet's destination IP multicast group. * * The packet is returned unscathed to the caller, unless it is * erroneous, in which case a non-zero return value tells the caller to * discard it. */ #define IP_HDR_LEN 20 /* # bytes of fixed IP header (excluding options) */ #define TUNNEL_LEN 12 /* # bytes of IP option for tunnel encapsulation */ int ip_mforward(struct mbuf *m, struct ifnet *ifp) { struct ip *ip = mtod(m, struct ip *); struct vif *v; struct rtentry *rt; static int srctun = 0; struct mbuf *mm; unsigned int rtableid = ifp->if_rdomain; if (ip->ip_hl < (IP_HDR_LEN + TUNNEL_LEN) >> 2 || ((u_char *)(ip + 1))[1] != IPOPT_LSRR) { /* * Packet arrived via a physical interface or * an encapsulated tunnel or a register_vif. */ } else { /* * Packet arrived through a source-route tunnel. * Source-route tunnels are no longer supported. */ if ((srctun++ % 1000) == 0) log(LOG_ERR, "ip_mforward: received source-routed " "packet from %x\n", ntohl(ip->ip_src.s_addr)); return (EOPNOTSUPP); } /* * Don't forward a packet with time-to-live of zero or one, * or a packet destined to a local-only group. */ if (ip->ip_ttl <= 1 || IN_LOCAL_GROUP(ip->ip_dst.s_addr)) return (0); /* * Determine forwarding vifs from the forwarding cache table */ ++mrtstat.mrts_mfc_lookups; rt = mfc_find(NULL, &ip->ip_src, &ip->ip_dst, rtableid); /* Entry exists, so forward if necessary */ if (rt != NULL) { return (ip_mdq(m, ifp, rt)); } else { /* * If we don't have a route for packet's origin, * Make a copy of the packet & send message to routing daemon */ int hlen = ip->ip_hl << 2; ++mrtstat.mrts_mfc_misses; mrtstat.mrts_no_route++; { struct igmpmsg *im; /* * Locate the vifi for the incoming interface for * this packet. * If none found, drop packet. */ if ((v = (struct vif *)ifp->if_mcast) == NULL) return (EHOSTUNREACH); /* * Make a copy of the header to send to the user level * process */ mm = m_copym(m, 0, hlen, M_NOWAIT); if (mm == NULL || (mm = m_pullup(mm, hlen)) == NULL) return (ENOBUFS); /* * Send message to routing daemon to install * a route into the kernel table */ im = mtod(mm, struct igmpmsg *); im->im_msgtype = IGMPMSG_NOCACHE; im->im_mbz = 0; im->im_vif = v->v_id; mrtstat.mrts_upcalls++; sin.sin_addr = ip->ip_src; if (socket_send(ip_mrouter[rtableid], mm, &sin) < 0) { log(LOG_WARNING, "ip_mforward: ip_mrouter " "socket queue full\n"); ++mrtstat.mrts_upq_sockfull; return (ENOBUFS); } mfc_add(NULL, &ip->ip_src, &ip->ip_dst, v->v_id, rtableid, M_NOWAIT); } return (0); } } /* * Packet forwarding routine once entry in the cache is made */ int ip_mdq(struct mbuf *m, struct ifnet *ifp0, struct rtentry *rt) { struct ip *ip = mtod(m, struct ip *); struct mfc *mfc = (struct mfc *)rt->rt_llinfo; struct vif *v = (struct vif *)ifp0->if_mcast; struct ifnet *ifp; struct mbuf *mc; struct ip_moptions imo; /* Sanity check: we have all promised pointers. */ if (v == NULL || mfc == NULL) { rtfree(rt); return (EHOSTUNREACH); } /* * Don't forward if it didn't arrive from the parent vif for its origin. */ if (mfc->mfc_parent != v->v_id) { /* came in the wrong interface */ ++mrtstat.mrts_wrong_if; mfc->mfc_wrong_if++; rtfree(rt); return (0); } /* If I sourced this packet, it counts as output, else it was input. */ if (in_hosteq(ip->ip_src, v->v_lcl_addr)) { v->v_pkt_out++; v->v_bytes_out += m->m_pkthdr.len; } else { v->v_pkt_in++; v->v_bytes_in += m->m_pkthdr.len; } /* * For each vif, decide if a copy of the packet should be forwarded. * Forward if: * - the ttl exceeds the vif's threshold * - there are group members downstream on interface */ do { /* Don't consider non multicast routes. */ if (ISSET(rt->rt_flags, RTF_HOST | RTF_MULTICAST) != (RTF_HOST | RTF_MULTICAST)) continue; mfc = (struct mfc *)rt->rt_llinfo; if (mfc == NULL) continue; mfc->mfc_pkt_cnt++; mfc->mfc_byte_cnt += m->m_pkthdr.len; /* Don't let this route expire. */ mfc->mfc_expire = 0; if (ip->ip_ttl <= mfc->mfc_ttl) continue; if ((ifp = if_get(rt->rt_ifidx)) == NULL) continue; /* Sanity check: did we configure this? */ if ((v = (struct vif *)ifp->if_mcast) == NULL) { if_put(ifp); continue; } /* Don't send in the upstream interface. */ if (mfc->mfc_parent == v->v_id) { if_put(ifp); continue; } v->v_pkt_out++; v->v_bytes_out += m->m_pkthdr.len; /* * Make a new reference to the packet; make sure * that the IP header is actually copied, not * just referenced, so that ip_output() only * scribbles on the copy. */ mc = m_dup_pkt(m, max_linkhdr, M_NOWAIT); if (mc == NULL) { if_put(ifp); rtfree(rt); return (ENOBUFS); } /* * if physical interface option, extract the options * and then send */ imo.imo_ifidx = rt->rt_ifidx; imo.imo_ttl = ip->ip_ttl - IPTTLDEC; imo.imo_loop = 1; ip_output(mc, NULL, NULL, IP_FORWARDING, &imo, NULL, 0); if_put(ifp); } while ((rt = rtable_iterate(rt)) != NULL); return (0); } struct ifnet * if_lookupbyvif(vifi_t vifi, unsigned int rtableid) { struct vif *v; struct ifnet *ifp; TAILQ_FOREACH(ifp, &ifnetlist, if_list) { if (ifp->if_rdomain != rtableid) continue; if ((v = (struct vif *)ifp->if_mcast) == NULL) continue; if (v->v_id != vifi) continue; return (ifp); } return (NULL); } struct rtentry * rt_mcast_add(struct ifnet *ifp, struct sockaddr *origin, struct sockaddr *group) { struct ifaddr *ifa; int rv; unsigned int rtableid = ifp->if_rdomain; TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family == AF_INET) break; } if (ifa == NULL) { DPRINTF("ifa == NULL"); return (NULL); } rv = rt_ifa_add(ifa, RTF_HOST | RTF_MULTICAST | RTF_MPATH, group, ifp->if_rdomain); if (rv != 0) { DPRINTF("rt_ifa_add failed (%d)", rv); return (NULL); } mrt_count[rtableid]++; return (mfc_find(ifp, NULL, &satosin(group)->sin_addr, rtableid)); } void mrt_mcast_del(struct rtentry *rt, unsigned int rtableid) { struct ifnet *ifp; int error; /* Remove all timers related to this route. */ rt_timer_remove_all(rt); free(rt->rt_llinfo, M_MRTABLE, sizeof(struct mfc)); rt->rt_llinfo = NULL; ifp = if_get(rt->rt_ifidx); if (ifp == NULL) return; error = rtdeletemsg(rt, ifp, rtableid); if_put(ifp); if (error) DPRINTF("delete route error %d\n", error); mrt_count[rtableid]--; }
11 10 17 1 16 2 1 4 1 1 1 1 2 2 3 2 1 1 1 1 2 3 3 1 3 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 /* $OpenBSD: hotplug.c,v 1.24 2023/09/22 22:12:32 mvs Exp $ */ /* * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * Device attachment and detachment notifications. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> #include <sys/event.h> #include <sys/fcntl.h> #include <sys/hotplug.h> #include <sys/ioctl.h> #include <sys/mutex.h> #include <sys/vnode.h> #define HOTPLUG_MAXEVENTS 64 /* * Locks used to protect struct members and global data * M hotplug_mtx */ static struct mutex hotplug_mtx = MUTEX_INITIALIZER(IPL_MPFLOOR); static int opened; static struct hotplug_event evqueue[HOTPLUG_MAXEVENTS]; static int evqueue_head, evqueue_tail, evqueue_count; /* [M] */ static struct klist hotplug_klist; /* [M] */ void filt_hotplugrdetach(struct knote *); int filt_hotplugread(struct knote *, long); int filt_hotplugmodify(struct kevent *, struct knote *); int filt_hotplugprocess(struct knote *, struct kevent *); const struct filterops hotplugread_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_hotplugrdetach, .f_event = filt_hotplugread, .f_modify = filt_hotplugmodify, .f_process = filt_hotplugprocess, }; #define EVQUEUE_NEXT(p) (p == HOTPLUG_MAXEVENTS - 1 ? 0 : p + 1) int hotplug_put_event(struct hotplug_event *); int hotplug_get_event(struct hotplug_event *); void hotplugattach(int); void hotplugattach(int count) { opened = 0; evqueue_head = 0; evqueue_tail = 0; evqueue_count = 0; klist_init_mutex(&hotplug_klist, &hotplug_mtx); } void hotplug_device_attach(enum devclass class, char *name) { struct hotplug_event he; he.he_type = HOTPLUG_DEVAT; he.he_devclass = class; strlcpy(he.he_devname, name, sizeof(he.he_devname)); hotplug_put_event(&he); } void hotplug_device_detach(enum devclass class, char *name) { struct hotplug_event he; he.he_type = HOTPLUG_DEVDT; he.he_devclass = class; strlcpy(he.he_devname, name, sizeof(he.he_devname)); hotplug_put_event(&he); } int hotplug_put_event(struct hotplug_event *he) { mtx_enter(&hotplug_mtx); if (evqueue_count == HOTPLUG_MAXEVENTS && opened) { mtx_leave(&hotplug_mtx); printf("hotplug: event lost, queue full\n"); return (1); } evqueue[evqueue_head] = *he; evqueue_head = EVQUEUE_NEXT(evqueue_head); if (evqueue_count == HOTPLUG_MAXEVENTS) evqueue_tail = EVQUEUE_NEXT(evqueue_tail); else evqueue_count++; knote_locked(&hotplug_klist, 0); wakeup(&evqueue); mtx_leave(&hotplug_mtx); return (0); } int hotplug_get_event(struct hotplug_event *he) { if (evqueue_count == 0) return (1); *he = evqueue[evqueue_tail]; evqueue_tail = EVQUEUE_NEXT(evqueue_tail); evqueue_count--; return (0); } int hotplugopen(dev_t dev, int flag, int mode, struct proc *p) { if (minor(dev) != 0) return (ENXIO); if ((flag & FWRITE)) return (EPERM); if (opened) return (EBUSY); opened = 1; return (0); } int hotplugclose(dev_t dev, int flag, int mode, struct proc *p) { struct hotplug_event he; mtx_enter(&hotplug_mtx); while (hotplug_get_event(&he) == 0) continue; mtx_leave(&hotplug_mtx); klist_invalidate(&hotplug_klist); opened = 0; return (0); } int hotplugread(dev_t dev, struct uio *uio, int flags) { struct hotplug_event he; int error; if (uio->uio_resid != sizeof(he)) return (EINVAL); mtx_enter(&hotplug_mtx); while (hotplug_get_event(&he)) { if (flags & IO_NDELAY) { mtx_leave(&hotplug_mtx); return (EAGAIN); } error = msleep_nsec(&evqueue, &hotplug_mtx, PRIBIO | PCATCH, "htplev", INFSLP); if (error) { mtx_leave(&hotplug_mtx); return (error); } } mtx_leave(&hotplug_mtx); return (uiomove(&he, sizeof(he), uio)); } int hotplugioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { switch (cmd) { case FIOASYNC: /* ignore */ case FIONBIO: /* handled in the upper fs layer */ break; default: return (ENOTTY); } return (0); } int hotplugkqfilter(dev_t dev, struct knote *kn) { switch (kn->kn_filter) { case EVFILT_READ: kn->kn_fop = &hotplugread_filtops; break; default: return (EINVAL); } klist_insert(&hotplug_klist, kn); return (0); } void filt_hotplugrdetach(struct knote *kn) { klist_remove(&hotplug_klist, kn); } int filt_hotplugread(struct knote *kn, long hint) { kn->kn_data = evqueue_count; return (evqueue_count > 0); } int filt_hotplugmodify(struct kevent *kev, struct knote *kn) { int active; mtx_enter(&hotplug_mtx); active = knote_modify(kev, kn); mtx_leave(&hotplug_mtx); return (active); } int filt_hotplugprocess(struct knote *kn, struct kevent *kev) { int active; mtx_enter(&hotplug_mtx); active = knote_process(kn, kev); mtx_leave(&hotplug_mtx); return (active); }
5 2 3 3 1 1 1 1 1 12 2 1 5 3 1 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 /* $OpenBSD: ip_divert.c,v 1.95 2024/03/05 09:45:13 bluhm Exp $ */ /* * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/protosw.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/sysctl.h> #include <net/if.h> #include <net/route.h> #include <net/if_var.h> #include <net/netisr.h> #include <netinet/in.h> #include <netinet/in_var.h> #include <netinet/ip.h> #include <netinet/ip_var.h> #include <netinet/in_pcb.h> #include <netinet/ip_divert.h> #include <netinet/tcp.h> #include <netinet/udp.h> #include <netinet/ip_icmp.h> #include <net/pfvar.h> struct inpcbtable divbtable; struct cpumem *divcounters; #ifndef DIVERT_SENDSPACE #define DIVERT_SENDSPACE (65536 + 100) #endif u_int divert_sendspace = DIVERT_SENDSPACE; #ifndef DIVERT_RECVSPACE #define DIVERT_RECVSPACE (65536 + 100) #endif u_int divert_recvspace = DIVERT_RECVSPACE; #ifndef DIVERTHASHSIZE #define DIVERTHASHSIZE 128 #endif const struct sysctl_bounded_args divertctl_vars[] = { { DIVERTCTL_RECVSPACE, &divert_recvspace, 0, INT_MAX }, { DIVERTCTL_SENDSPACE, &divert_sendspace, 0, INT_MAX }, }; const struct pr_usrreqs divert_usrreqs = { .pru_attach = divert_attach, .pru_detach = divert_detach, .pru_lock = divert_lock, .pru_unlock = divert_unlock, .pru_locked = divert_locked, .pru_bind = divert_bind, .pru_shutdown = divert_shutdown, .pru_send = divert_send, .pru_control = in_control, .pru_sockaddr = in_sockaddr, .pru_peeraddr = in_peeraddr, }; int divbhashsize = DIVERTHASHSIZE; int divert_output(struct inpcb *, struct mbuf *, struct mbuf *, struct mbuf *); void divert_init(void) { in_pcbinit(&divbtable, divbhashsize); divcounters = counters_alloc(divs_ncounters); } int divert_output(struct inpcb *inp, struct mbuf *m, struct mbuf *nam, struct mbuf *control) { struct sockaddr_in *sin; int error, min_hdrlen, off, dir; struct ip *ip; m_freem(control); if ((error = in_nam2sin(nam, &sin))) goto fail; if (m->m_pkthdr.len > IP_MAXPACKET) { error = EMSGSIZE; goto fail; } m = rip_chkhdr(m, NULL); if (m == NULL) { error = EINVAL; goto fail; } ip = mtod(m, struct ip *); off = ip->ip_hl << 2; dir = (sin->sin_addr.s_addr == INADDR_ANY ? PF_OUT : PF_IN); switch (ip->ip_p) { case IPPROTO_TCP: min_hdrlen = sizeof(struct tcphdr); m->m_pkthdr.csum_flags |= M_TCP_CSUM_OUT; break; case IPPROTO_UDP: min_hdrlen = sizeof(struct udphdr); m->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT; break; case IPPROTO_ICMP: min_hdrlen = ICMP_MINLEN; m->m_pkthdr.csum_flags |= M_ICMP_CSUM_OUT; break; default: min_hdrlen = 0; break; } if (min_hdrlen && m->m_pkthdr.len < off + min_hdrlen) { error = EINVAL; goto fail; } m->m_pkthdr.pf.flags |= PF_TAG_DIVERTED_PACKET; if (dir == PF_IN) { struct rtentry *rt; struct ifnet *ifp; rt = rtalloc(sintosa(sin), 0, inp->inp_rtableid); if (!rtisvalid(rt) || !ISSET(rt->rt_flags, RTF_LOCAL)) { rtfree(rt); error = EADDRNOTAVAIL; goto fail; } m->m_pkthdr.ph_ifidx = rt->rt_ifidx; rtfree(rt); /* * Recalculate IP and protocol checksums for the inbound packet * since the userspace application may have modified the packet * prior to reinjection. */ in_hdr_cksum_out(m, NULL); in_proto_cksum_out(m, NULL); ifp = if_get(m->m_pkthdr.ph_ifidx); if (ifp == NULL) { error = ENETDOWN; goto fail; } ipv4_input(ifp, m); if_put(ifp); } else { m->m_pkthdr.ph_rtableid = inp->inp_rtableid; error = ip_output(m, NULL, &inp->inp_route, IP_ALLOWBROADCAST | IP_RAWOUTPUT, NULL, NULL, 0); } divstat_inc(divs_opackets); return (error); fail: m_freem(m); divstat_inc(divs_errors); return (error); } void divert_packet(struct mbuf *m, int dir, u_int16_t divert_port) { struct inpcb *inp = NULL; struct socket *so; struct sockaddr_in sin; divstat_inc(divs_ipackets); if (m->m_len < sizeof(struct ip) && (m = m_pullup(m, sizeof(struct ip))) == NULL) { divstat_inc(divs_errors); goto bad; } mtx_enter(&divbtable.inpt_mtx); TAILQ_FOREACH(inp, &divbtable.inpt_queue, inp_queue) { if (inp->inp_lport != divert_port) continue; in_pcbref(inp); break; } mtx_leave(&divbtable.inpt_mtx); if (inp == NULL) { divstat_inc(divs_noport); goto bad; } memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_len = sizeof(sin); if (dir == PF_IN) { struct ifaddr *ifa; struct ifnet *ifp; ifp = if_get(m->m_pkthdr.ph_ifidx); if (ifp == NULL) { divstat_inc(divs_errors); goto bad; } TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET) continue; sin.sin_addr = satosin(ifa->ifa_addr)->sin_addr; break; } if_put(ifp); } else { /* * Calculate IP and protocol checksums for outbound packet * diverted to userland. pf rule diverts before cksum offload. */ in_hdr_cksum_out(m, NULL); in_proto_cksum_out(m, NULL); } so = inp->inp_socket; mtx_enter(&so->so_rcv.sb_mtx); if (sbappendaddr(so, &so->so_rcv, sintosa(&sin), m, NULL) == 0) { mtx_leave(&so->so_rcv.sb_mtx); divstat_inc(divs_fullsock); goto bad; } mtx_leave(&so->so_rcv.sb_mtx); sorwakeup(so); in_pcbunref(inp); return; bad: if (inp != NULL) in_pcbunref(inp); m_freem(m); } int divert_attach(struct socket *so, int proto, int wait) { int error; if (so->so_pcb != NULL) return EINVAL; if ((so->so_state & SS_PRIV) == 0) return EACCES; error = in_pcballoc(so, &divbtable, wait); if (error) return error; error = soreserve(so, divert_sendspace, divert_recvspace); if (error) return error; sotoinpcb(so)->inp_flags |= INP_HDRINCL; return (0); } int divert_detach(struct socket *so) { struct inpcb *inp = sotoinpcb(so); soassertlocked(so); if (inp == NULL) return (EINVAL); in_pcbdetach(inp); return (0); } void divert_lock(struct socket *so) { struct inpcb *inp = sotoinpcb(so); NET_ASSERT_LOCKED(); mtx_enter(&inp->inp_mtx); } void divert_unlock(struct socket *so) { struct inpcb *inp = sotoinpcb(so); NET_ASSERT_LOCKED(); mtx_leave(&inp->inp_mtx); } int divert_locked(struct socket *so) { struct inpcb *inp = sotoinpcb(so); return mtx_owned(&inp->inp_mtx); } int divert_bind(struct socket *so, struct mbuf *addr, struct proc *p) { struct inpcb *inp = sotoinpcb(so); soassertlocked(so); return in_pcbbind(inp, addr, p); } int divert_shutdown(struct socket *so) { soassertlocked(so); socantsendmore(so); return (0); } int divert_send(struct socket *so, struct mbuf *m, struct mbuf *addr, struct mbuf *control) { struct inpcb *inp = sotoinpcb(so); soassertlocked(so); return (divert_output(inp, m, addr, control)); } int divert_sysctl_divstat(void *oldp, size_t *oldlenp, void *newp) { uint64_t counters[divs_ncounters]; struct divstat divstat; u_long *words = (u_long *)&divstat; int i; CTASSERT(sizeof(divstat) == (nitems(counters) * sizeof(u_long))); memset(&divstat, 0, sizeof divstat); counters_read(divcounters, counters, nitems(counters), NULL); for (i = 0; i < nitems(counters); i++) words[i] = (u_long)counters[i]; return (sysctl_rdstruct(oldp, oldlenp, newp, &divstat, sizeof(divstat))); } /* * Sysctl for divert variables. */ int divert_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int error; /* All sysctl names at this level are terminal. */ if (namelen != 1) return (ENOTDIR); switch (name[0]) { case DIVERTCTL_STATS: return (divert_sysctl_divstat(oldp, oldlenp, newp)); default: NET_LOCK(); error = sysctl_bounded_arr(divertctl_vars, nitems(divertctl_vars), name, namelen, oldp, oldlenp, newp, newlen); NET_UNLOCK(); return (error); } /* NOTREACHED */ }
2 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 /* $OpenBSD: lpt.c,v 1.15 2020/01/15 16:43:13 cheloha Exp $ */ /* $NetBSD: lpt.c,v 1.42 1996/10/21 22:41:14 thorpej Exp $ */ /* * Copyright (c) 1993, 1994 Charles Hannum. * Copyright (c) 1990 William F. Jolitz, TeleMuse * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This software is a component of "386BSD" developed by * William F. Jolitz, TeleMuse. * 4. Neither the name of the developer nor the name "386BSD" * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT. * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT * NOT MAKE USE OF THIS WORK. * * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN * REFERENCES SUCH AS THE "PORTING UNIX TO THE 386" SERIES * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992. * * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Device Driver for AT parallel printer port */ #include <sys/param.h> #include <sys/systm.h> #include <sys/buf.h> #include <sys/kernel.h> #include <sys/uio.h> #include <sys/device.h> #include <sys/conf.h> #include <sys/syslog.h> #include <machine/bus.h> #include <machine/intr.h> #include <dev/ic/lptreg.h> #include <dev/ic/lptvar.h> #include "lpt.h" #define TIMEOUT 16000 /* wait up to 16 seconds for a ready */ #define STEP 250 /* 1/4 seconds */ #define LPTPRI (PZERO+8) #define LPT_BSIZE 1024 #if !defined(DEBUG) || !defined(notdef) #define LPRINTF(a) #else #define LPRINTF(a) if (lptdebug) printf a int lptdebug = 1; #endif /* XXX does not belong here */ cdev_decl(lpt); struct cfdriver lpt_cd = { NULL, "lpt", DV_TTY }; #define LPTUNIT(s) (minor(s) & 0x1f) #define LPTFLAGS(s) (minor(s) & 0xe0) #define LPS_INVERT (LPS_SELECT|LPS_NERR|LPS_NBSY|LPS_NACK) #define LPS_MASK (LPS_SELECT|LPS_NERR|LPS_NBSY|LPS_NACK|LPS_NOPAPER) #define NOT_READY() \ ((bus_space_read_1(sc->sc_iot, sc->sc_ioh, lpt_status) ^ LPS_INVERT) & LPS_MASK) #define NOT_READY_ERR() \ lpt_not_ready(bus_space_read_1(sc->sc_iot, sc->sc_ioh, lpt_status), sc) int lpt_not_ready(u_int8_t, struct lpt_softc *); void lptwakeup(void *arg); int lptpushbytes(struct lpt_softc *); /* * Internal routine to lptprobe to do port tests of one byte value. */ int lpt_port_test(bus_space_tag_t iot, bus_space_handle_t ioh, bus_addr_t base, bus_size_t off, u_int8_t data, u_int8_t mask) { int timeout; u_int8_t temp; data &= mask; bus_space_write_1(iot, ioh, off, data); timeout = 1000; do { delay(10); temp = bus_space_read_1(iot, ioh, off) & mask; } while (temp != data && --timeout); LPRINTF(("lpt: port=0x%x out=0x%x in=0x%x timeout=%d\n", base + off, data, temp, timeout)); return (temp == data); } void lpt_attach_common(struct lpt_softc *sc) { printf("\n"); bus_space_write_1(sc->sc_iot, sc->sc_ioh, lpt_control, LPC_NINIT); timeout_set(&sc->sc_wakeup_tmo, lptwakeup, sc); } void lpt_detach_common(struct lpt_softc *sc) { timeout_del(&sc->sc_wakeup_tmo); if (sc->sc_state != 0) { sc->sc_state = 0; wakeup(sc); } } /* * Reset the printer, then wait until it's selected and not busy. */ int lptopen(dev_t dev, int flag, int mode, struct proc *p) { int unit = LPTUNIT(dev); u_int8_t flags = LPTFLAGS(dev); struct lpt_softc *sc; u_int8_t control; int error; int spin; if (unit >= lpt_cd.cd_ndevs) return ENXIO; sc = lpt_cd.cd_devs[unit]; if (!sc) return ENXIO; sc->sc_flags = (sc->sc_flags & LPT_POLLED) | flags; if ((sc->sc_flags & (LPT_POLLED|LPT_NOINTR)) == LPT_POLLED) return ENXIO; #ifdef DIAGNOSTIC if (sc->sc_state) printf("%s: stat=0x%x not zero\n", sc->sc_dev.dv_xname, sc->sc_state); #endif if (sc->sc_state) return EBUSY; sc->sc_state = LPT_INIT; LPRINTF(("%s: open: flags=0x%x\n", sc->sc_dev.dv_xname, flags)); if ((flags & LPT_NOPRIME) == 0) { /* assert INIT for 100 usec to start up printer */ bus_space_write_1(sc->sc_iot, sc->sc_ioh, lpt_control, LPC_SELECT); delay(100); } control = LPC_SELECT | LPC_NINIT; bus_space_write_1(sc->sc_iot, sc->sc_ioh, lpt_control, control); /* wait till ready (printer running diagnostics) */ for (spin = 0; NOT_READY_ERR(); spin += STEP) { if (spin >= TIMEOUT) { sc->sc_state = 0; return EBUSY; } /* wait 1/4 second, give up if we get a signal */ error = tsleep_nsec(sc, LPTPRI | PCATCH, "lptopen", MSEC_TO_NSEC(STEP)); if (sc->sc_state == 0) return (EIO); if (error != EWOULDBLOCK) { sc->sc_state = 0; return error; } } if ((flags & LPT_NOINTR) == 0) control |= LPC_IENABLE; if (flags & LPT_AUTOLF) control |= LPC_AUTOLF; sc->sc_control = control; bus_space_write_1(sc->sc_iot, sc->sc_ioh, lpt_control, control); sc->sc_inbuf = geteblk(LPT_BSIZE); sc->sc_count = 0; sc->sc_state = LPT_OPEN; if ((sc->sc_flags & LPT_NOINTR) == 0) lptwakeup(sc); LPRINTF(("%s: opened\n", sc->sc_dev.dv_xname)); return 0; } int lpt_not_ready(u_int8_t status, struct lpt_softc *sc) { u_int8_t new; status = (status ^ LPS_INVERT) & LPS_MASK; new = status & ~sc->sc_laststatus; sc->sc_laststatus = status; if (new & LPS_SELECT) log(LOG_NOTICE, "%s: offline\n", sc->sc_dev.dv_xname); else if (new & LPS_NOPAPER) log(LOG_NOTICE, "%s: out of paper\n", sc->sc_dev.dv_xname); else if (new & LPS_NERR) log(LOG_NOTICE, "%s: output error\n", sc->sc_dev.dv_xname); return status; } void lptwakeup(void *arg) { struct lpt_softc *sc = arg; int s; s = spltty(); lptintr(sc); splx(s); if (sc->sc_state != 0) timeout_add_msec(&sc->sc_wakeup_tmo, STEP); } /* * Close the device, and free the local line buffer. */ int lptclose(dev_t dev, int flag, int mode, struct proc *p) { int unit = LPTUNIT(dev); struct lpt_softc *sc = lpt_cd.cd_devs[unit]; bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; if (sc->sc_count) (void) lptpushbytes(sc); if ((sc->sc_flags & LPT_NOINTR) == 0) timeout_del(&sc->sc_wakeup_tmo); bus_space_write_1(iot, ioh, lpt_control, LPC_NINIT); sc->sc_state = 0; bus_space_write_1(iot, ioh, lpt_control, LPC_NINIT); brelse(sc->sc_inbuf); LPRINTF(("%s: closed\n", sc->sc_dev.dv_xname)); return 0; } int lptpushbytes(struct lpt_softc *sc) { bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; int error; if (sc->sc_flags & LPT_NOINTR) { int msecs, spin; u_int8_t control = sc->sc_control; while (sc->sc_count > 0) { spin = 0; if (sc->sc_state == 0) return (EIO); while (NOT_READY()) { if (++spin < sc->sc_spinmax) continue; msecs = 0; /* adapt busy-wait algorithm */ sc->sc_spinmax++; while (NOT_READY_ERR()) { /* exponential backoff */ msecs = msecs + msecs + 10; if (msecs > TIMEOUT) msecs = TIMEOUT; error = tsleep_nsec(sc, LPTPRI | PCATCH, "lptpsh", MSEC_TO_NSEC(msecs)); if (sc->sc_state == 0) error = EIO; if (error != EWOULDBLOCK) return error; } break; } bus_space_write_1(iot, ioh, lpt_data, *sc->sc_cp++); bus_space_write_1(iot, ioh, lpt_control, control | LPC_STROBE); sc->sc_count--; bus_space_write_1(iot, ioh, lpt_control, control); /* adapt busy-wait algorithm */ if (spin*2 + 16 < sc->sc_spinmax) sc->sc_spinmax--; } } else { int s; while (sc->sc_count > 0) { /* if the printer is ready for a char, give it one */ if ((sc->sc_state & LPT_OBUSY) == 0) { LPRINTF(("%s: write %d\n", sc->sc_dev.dv_xname, sc->sc_count)); s = spltty(); (void) lptintr(sc); splx(s); } if (sc->sc_state == 0) return (EIO); error = tsleep_nsec(sc, LPTPRI | PCATCH, "lptwrite2", INFSLP); if (sc->sc_state == 0) error = EIO; if (error) return error; } } return 0; } /* * Copy a line from user space to a local buffer, then call putc to get the * chars moved to the output queue. */ int lptwrite(dev_t dev, struct uio *uio, int flags) { struct lpt_softc *sc = lpt_cd.cd_devs[LPTUNIT(dev)]; size_t n; int error = 0; while ((n = ulmin(LPT_BSIZE, uio->uio_resid)) != 0) { error = uiomove(sc->sc_cp = sc->sc_inbuf->b_data, n, uio); if (error != 0) return error; sc->sc_count = n; error = lptpushbytes(sc); if (error) { /* * Return accurate residual if interrupted or timed * out. */ uio->uio_resid += sc->sc_count; sc->sc_count = 0; return error; } } return 0; } /* * Handle printer interrupts which occur when the printer is ready to accept * another char. */ int lptintr(void *arg) { struct lpt_softc *sc = arg; bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; if (((sc->sc_state & LPT_OPEN) == 0 && sc->sc_count == 0) || (sc->sc_flags & LPT_NOINTR)) return 0; /* is printer online and ready for output */ if (NOT_READY() && NOT_READY_ERR()) return -1; if (sc->sc_count) { u_int8_t control = sc->sc_control; /* send char */ bus_space_write_1(iot, ioh, lpt_data, *sc->sc_cp++); delay (50); bus_space_write_1(iot, ioh, lpt_control, control | LPC_STROBE); sc->sc_count--; bus_space_write_1(iot, ioh, lpt_control, control); sc->sc_state |= LPT_OBUSY; } else sc->sc_state &= ~LPT_OBUSY; if (sc->sc_count == 0) { /* none, wake up the top half to get more */ wakeup((caddr_t)sc); } return 1; } int lpt_activate(struct device *self, int act) { struct lpt_softc *sc = (struct lpt_softc *)self; switch (act) { case DVACT_SUSPEND: timeout_del(&sc->sc_wakeup_tmo); break; case DVACT_RESUME: bus_space_write_1(sc->sc_iot, sc->sc_ioh, lpt_control, LPC_NINIT); if (sc->sc_state) { int spin; if ((sc->sc_flags & LPT_NOPRIME) == 0) { /* assert INIT for 100 usec to start up printer */ bus_space_write_1(sc->sc_iot, sc->sc_ioh, lpt_control, LPC_SELECT); delay(100); } bus_space_write_1(sc->sc_iot, sc->sc_ioh, lpt_control, LPC_SELECT | LPC_NINIT); /* wait till ready (printer running diagnostics) */ for (spin = 0; NOT_READY_ERR(); spin += STEP) { if (spin >= TIMEOUT) { sc->sc_state = 0; goto fail; } /* wait 1/4 second, give up if we get a signal */ delay(STEP * 1000); } bus_space_write_1(sc->sc_iot, sc->sc_ioh, lpt_control, sc->sc_control); wakeup(sc); } fail: break; } return (0); }
61 18 2 2 1 2 1 1 1 5 2 3 5 2 3 5 2 4 1 1 6 2 2 2 2 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 /* $OpenBSD: uvm_meter.c,v 1.50 2023/09/16 09:33:27 mpi Exp $ */ /* $NetBSD: uvm_meter.c,v 1.21 2001/07/14 06:36:03 matt Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)vm_meter.c 8.4 (Berkeley) 1/4/94 * from: Id: uvm_meter.c,v 1.1.2.1 1997/08/14 19:10:35 chuck Exp */ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/percpu.h> #include <sys/proc.h> #include <sys/sysctl.h> #include <sys/vmmeter.h> #include <uvm/uvm.h> #include <uvm/uvm_ddb.h> #ifdef UVM_SWAP_ENCRYPT #include <uvm/uvm_swap.h> #include <uvm/uvm_swap_encrypt.h> #endif /* * The time for a process to be blocked before being very swappable. * This is a number of seconds which the system takes as being a non-trivial * amount of real time. You probably shouldn't change this; * it is used in subtle ways (fractions and multiples of it are, that is, like * half of a ``long time'', almost a long time, etc.) * It is related to human patience and other factors which don't really * change over time. */ #define MAXSLP 20 int maxslp = MAXSLP; /* patchable ... */ extern struct loadavg averunnable; void uvm_total(struct vmtotal *); void uvmexp_read(struct uvmexp *); char malloc_conf[16]; /* * uvm_sysctl: sysctl hook into UVM system. */ int uvm_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { struct process *pr = p->p_p; struct vmtotal vmtotals; struct uvmexp uexp; int rv, t; switch (name[0]) { case VM_SWAPENCRYPT: #ifdef UVM_SWAP_ENCRYPT return (swap_encrypt_ctl(name + 1, namelen - 1, oldp, oldlenp, newp, newlen, p)); #else return (EOPNOTSUPP); #endif default: /* all sysctl names at this level are terminal */ if (namelen != 1) return (ENOTDIR); /* overloaded */ break; } switch (name[0]) { case VM_LOADAVG: return (sysctl_rdstruct(oldp, oldlenp, newp, &averunnable, sizeof(averunnable))); case VM_METER: uvm_total(&vmtotals); return (sysctl_rdstruct(oldp, oldlenp, newp, &vmtotals, sizeof(vmtotals))); case VM_UVMEXP: uvmexp_read(&uexp); return (sysctl_rdstruct(oldp, oldlenp, newp, &uexp, sizeof(uexp))); case VM_NKMEMPAGES: return (sysctl_rdint(oldp, oldlenp, newp, nkmempages)); case VM_PSSTRINGS: return (sysctl_rdstruct(oldp, oldlenp, newp, &pr->ps_strings, sizeof(pr->ps_strings))); case VM_ANONMIN: t = uvmexp.anonminpct; rv = sysctl_int(oldp, oldlenp, newp, newlen, &t); if (rv) { return rv; } if (t + uvmexp.vtextminpct + uvmexp.vnodeminpct > 95 || t < 0) { return EINVAL; } uvmexp.anonminpct = t; uvmexp.anonmin = t * 256 / 100; return rv; case VM_VTEXTMIN: t = uvmexp.vtextminpct; rv = sysctl_int(oldp, oldlenp, newp, newlen, &t); if (rv) { return rv; } if (uvmexp.anonminpct + t + uvmexp.vnodeminpct > 95 || t < 0) { return EINVAL; } uvmexp.vtextminpct = t; uvmexp.vtextmin = t * 256 / 100; return rv; case VM_VNODEMIN: t = uvmexp.vnodeminpct; rv = sysctl_int(oldp, oldlenp, newp, newlen, &t); if (rv) { return rv; } if (uvmexp.anonminpct + uvmexp.vtextminpct + t > 95 || t < 0) { return EINVAL; } uvmexp.vnodeminpct = t; uvmexp.vnodemin = t * 256 / 100; return rv; case VM_MAXSLP: return (sysctl_rdint(oldp, oldlenp, newp, maxslp)); case VM_USPACE: return (sysctl_rdint(oldp, oldlenp, newp, USPACE)); case VM_MALLOC_CONF: return (sysctl_string(oldp, oldlenp, newp, newlen, malloc_conf, sizeof(malloc_conf))); default: return (EOPNOTSUPP); } /* NOTREACHED */ } /* * uvm_total: calculate the current state of the system. */ void uvm_total(struct vmtotal *totalp) { struct proc *p; #if 0 struct vm_map_entry * entry; struct vm_map *map; int paging; #endif memset(totalp, 0, sizeof *totalp); /* calculate process statistics */ LIST_FOREACH(p, &allproc, p_list) { switch (p->p_stat) { case 0: continue; case SSLEEP: case SSTOP: totalp->t_sl++; break; case SRUN: case SONPROC: if (p == p->p_cpu->ci_schedstate.spc_idleproc) continue; /* FALLTHROUGH */ case SIDL: totalp->t_rq++; if (p->p_stat == SIDL) continue; break; } /* * note active objects */ #if 0 /* * XXXCDC: BOGUS! rethink this. in the mean time * don't do it. */ paging = 0; vm_map_lock(map); for (map = &p->p_vmspace->vm_map, entry = map->header.next; entry != &map->header; entry = entry->next) { if (entry->is_a_map || entry->is_sub_map || entry->object.uvm_obj == NULL) continue; /* XXX how to do this with uvm */ } vm_map_unlock(map); if (paging) totalp->t_pw++; #endif } /* * Calculate object memory usage statistics. */ totalp->t_free = uvmexp.free; totalp->t_vm = uvmexp.npages - uvmexp.free + uvmexp.swpginuse; totalp->t_avm = uvmexp.active + uvmexp.swpginuse; /* XXX */ totalp->t_rm = uvmexp.npages - uvmexp.free; totalp->t_arm = uvmexp.active; totalp->t_vmshr = 0; /* XXX */ totalp->t_avmshr = 0; /* XXX */ totalp->t_rmshr = 0; /* XXX */ totalp->t_armshr = 0; /* XXX */ } void uvmexp_read(struct uvmexp *uexp) { uint64_t counters[exp_ncounters], scratch[exp_ncounters]; memcpy(uexp, &uvmexp, sizeof(*uexp)); counters_read(uvmexp_counters, counters, exp_ncounters, scratch); /* stat counters */ uexp->faults = (int)counters[faults]; uexp->pageins = (int)counters[pageins]; /* fault subcounters */ uexp->fltnoram = (int)counters[flt_noram]; uexp->fltnoanon = (int)counters[flt_noanon]; uexp->fltnoamap = (int)counters[flt_noamap]; uexp->fltpgwait = (int)counters[flt_pgwait]; uexp->fltpgrele = (int)counters[flt_pgrele]; uexp->fltrelck = (int)counters[flt_relck]; uexp->fltrelckok = (int)counters[flt_relckok]; uexp->fltanget = (int)counters[flt_anget]; uexp->fltanretry = (int)counters[flt_anretry]; uexp->fltamcopy = (int)counters[flt_amcopy]; uexp->fltnamap = (int)counters[flt_namap]; uexp->fltnomap = (int)counters[flt_nomap]; uexp->fltlget = (int)counters[flt_lget]; uexp->fltget = (int)counters[flt_get]; uexp->flt_anon = (int)counters[flt_anon]; uexp->flt_acow = (int)counters[flt_acow]; uexp->flt_obj = (int)counters[flt_obj]; uexp->flt_prcopy = (int)counters[flt_prcopy]; uexp->flt_przero = (int)counters[flt_przero]; } #ifdef DDB /* * uvmexp_print: ddb hook to print interesting uvm counters */ void uvmexp_print(int (*pr)(const char *, ...)) { struct uvmexp uexp; uvmexp_read(&uexp); (*pr)("Current UVM status:\n"); (*pr)(" pagesize=%d (0x%x), pagemask=0x%x, pageshift=%d\n", uexp.pagesize, uexp.pagesize, uexp.pagemask, uexp.pageshift); (*pr)(" %d VM pages: %d active, %d inactive, %d wired, %d free (%d zero)\n", uexp.npages, uexp.active, uexp.inactive, uexp.wired, uexp.free, uexp.zeropages); (*pr)(" min %d%% (%d) anon, %d%% (%d) vnode, %d%% (%d) vtext\n", uexp.anonminpct, uexp.anonmin, uexp.vnodeminpct, uexp.vnodemin, uexp.vtextminpct, uexp.vtextmin); (*pr)(" freemin=%d, free-target=%d, inactive-target=%d, " "wired-max=%d\n", uexp.freemin, uexp.freetarg, uexp.inactarg, uexp.wiredmax); (*pr)(" faults=%d, traps=%d, intrs=%d, ctxswitch=%d fpuswitch=%d\n", uexp.faults, uexp.traps, uexp.intrs, uexp.swtch, uexp.fpswtch); (*pr)(" softint=%d, syscalls=%d, kmapent=%d\n", uexp.softs, uexp.syscalls, uexp.kmapent); (*pr)(" fault counts:\n"); (*pr)(" noram=%d, noanon=%d, noamap=%d, pgwait=%d, pgrele=%d\n", uexp.fltnoram, uexp.fltnoanon, uexp.fltnoamap, uexp.fltpgwait, uexp.fltpgrele); (*pr)(" ok relocks(total)=%d(%d), anget(retries)=%d(%d), " "amapcopy=%d\n", uexp.fltrelckok, uexp.fltrelck, uexp.fltanget, uexp.fltanretry, uexp.fltamcopy); (*pr)(" neighbor anon/obj pg=%d/%d, gets(lock/unlock)=%d/%d\n", uexp.fltnamap, uexp.fltnomap, uexp.fltlget, uexp.fltget); (*pr)(" cases: anon=%d, anoncow=%d, obj=%d, prcopy=%d, przero=%d\n", uexp.flt_anon, uexp.flt_acow, uexp.flt_obj, uexp.flt_prcopy, uexp.flt_przero); (*pr)(" daemon and swap counts:\n"); (*pr)(" woke=%d, revs=%d, scans=%d, obscans=%d, anscans=%d\n", uexp.pdwoke, uexp.pdrevs, uexp.pdscans, uexp.pdobscan, uexp.pdanscan); (*pr)(" busy=%d, freed=%d, reactivate=%d, deactivate=%d\n", uexp.pdbusy, uexp.pdfreed, uexp.pdreact, uexp.pddeact); (*pr)(" pageouts=%d, pending=%d, nswget=%d\n", uexp.pdpageouts, uexp.pdpending, uexp.nswget); (*pr)(" nswapdev=%d\n", uexp.nswapdev); (*pr)(" swpages=%d, swpginuse=%d, swpgonly=%d paging=%d\n", uexp.swpages, uexp.swpginuse, uexp.swpgonly, uexp.paging); (*pr)(" kernel pointers:\n"); (*pr)(" objs(kern)=%p\n", uvm.kernel_object); } #endif
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 /* $OpenBSD: kern_fork.c,v 1.258 2024/05/20 10:32:20 claudio Exp $ */ /* $NetBSD: kern_fork.c,v 1.29 1996/02/09 18:59:34 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_fork.c 8.6 (Berkeley) 4/8/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/filedesc.h> #include <sys/malloc.h> #include <sys/mount.h> #include <sys/proc.h> #include <sys/resourcevar.h> #include <sys/signalvar.h> #include <sys/vnode.h> #include <sys/vmmeter.h> #include <sys/acct.h> #include <sys/ktrace.h> #include <sys/sched.h> #include <sys/smr.h> #include <sys/sysctl.h> #include <sys/pool.h> #include <sys/mman.h> #include <sys/ptrace.h> #include <sys/atomic.h> #include <sys/unistd.h> #include <sys/tracepoint.h> #include <sys/syscallargs.h> #include <uvm/uvm.h> #include <machine/tcb.h> int nprocesses = 1; /* process 0 */ int nthreads = 1; /* proc 0 */ struct forkstat forkstat; void fork_return(void *); pid_t alloctid(void); pid_t allocpid(void); int ispidtaken(pid_t); void unveil_copy(struct process *parent, struct process *child); struct proc *thread_new(struct proc *_parent, vaddr_t _uaddr); struct process *process_new(struct proc *, struct process *, int); int fork_check_maxthread(uid_t _uid); void fork_return(void *arg) { struct proc *p = (struct proc *)arg; if (p->p_p->ps_flags & PS_TRACED) psignal(p, SIGTRAP); child_return(p); } int sys_fork(struct proc *p, void *v, register_t *retval) { void (*func)(void *) = child_return; int flags; flags = FORK_FORK; if (p->p_p->ps_ptmask & PTRACE_FORK) { flags |= FORK_PTRACE; func = fork_return; } return fork1(p, flags, func, NULL, retval, NULL); } int sys_vfork(struct proc *p, void *v, register_t *retval) { return fork1(p, FORK_VFORK|FORK_PPWAIT, child_return, NULL, retval, NULL); } int sys___tfork(struct proc *p, void *v, register_t *retval) { struct sys___tfork_args /* { syscallarg(const struct __tfork) *param; syscallarg(size_t) psize; } */ *uap = v; size_t psize = SCARG(uap, psize); struct __tfork param = { 0 }; int error; if (psize == 0 || psize > sizeof(param)) return EINVAL; if ((error = copyin(SCARG(uap, param), &param, psize))) return error; #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrstruct(p, "tfork", &param, sizeof(param)); #endif #ifdef TCB_INVALID if (TCB_INVALID(param.tf_tcb)) return EINVAL; #endif /* TCB_INVALID */ return thread_fork(p, param.tf_stack, param.tf_tcb, param.tf_tid, retval); } /* * Allocate and initialize a thread (proc) structure, given the parent thread. */ struct proc * thread_new(struct proc *parent, vaddr_t uaddr) { struct proc *p; p = pool_get(&proc_pool, PR_WAITOK); p->p_stat = SIDL; /* protect against others */ p->p_runpri = 0; p->p_flag = 0; /* * Make a proc table entry for the new process. * Start by zeroing the section of proc that is zero-initialized, * then copy the section that is copied directly from the parent. */ memset(&p->p_startzero, 0, (caddr_t)&p->p_endzero - (caddr_t)&p->p_startzero); memcpy(&p->p_startcopy, &parent->p_startcopy, (caddr_t)&p->p_endcopy - (caddr_t)&p->p_startcopy); crhold(p->p_ucred); p->p_addr = (struct user *)uaddr; /* * Initialize the timeouts. */ timeout_set(&p->p_sleep_to, endtsleep, p); return p; } /* * Initialize common bits of a process structure, given the initial thread. */ void process_initialize(struct process *pr, struct proc *p) { /* initialize the thread links */ pr->ps_mainproc = p; TAILQ_INIT(&pr->ps_threads); TAILQ_INSERT_TAIL(&pr->ps_threads, p, p_thr_link); pr->ps_threadcnt = 1; p->p_p = pr; /* give the process the same creds as the initial thread */ pr->ps_ucred = p->p_ucred; crhold(pr->ps_ucred); /* new thread and new process */ KASSERT(p->p_ucred->cr_refcnt.r_refs >= 2); LIST_INIT(&pr->ps_children); LIST_INIT(&pr->ps_orphans); LIST_INIT(&pr->ps_ftlist); LIST_INIT(&pr->ps_sigiolst); TAILQ_INIT(&pr->ps_tslpqueue); rw_init(&pr->ps_lock, "pslock"); mtx_init(&pr->ps_mtx, IPL_HIGH); timeout_set_flags(&pr->ps_realit_to, realitexpire, pr, KCLOCK_UPTIME, 0); timeout_set(&pr->ps_rucheck_to, rucheck, pr); } /* * Allocate and initialize a new process. */ struct process * process_new(struct proc *p, struct process *parent, int flags) { struct process *pr; pr = pool_get(&process_pool, PR_WAITOK); /* * Make a process structure for the new process. * Start by zeroing the section of proc that is zero-initialized, * then copy the section that is copied directly from the parent. */ memset(&pr->ps_startzero, 0, (caddr_t)&pr->ps_endzero - (caddr_t)&pr->ps_startzero); memcpy(&pr->ps_startcopy, &parent->ps_startcopy, (caddr_t)&pr->ps_endcopy - (caddr_t)&pr->ps_startcopy); process_initialize(pr, p); pr->ps_pid = allocpid(); lim_fork(parent, pr); /* post-copy fixups */ pr->ps_pptr = parent; pr->ps_ppid = parent->ps_pid; /* bump references to the text vnode (for sysctl) */ pr->ps_textvp = parent->ps_textvp; if (pr->ps_textvp) vref(pr->ps_textvp); /* copy unveil if unveil is active */ unveil_copy(parent, pr); pr->ps_flags = parent->ps_flags & (PS_SUGID | PS_SUGIDEXEC | PS_PLEDGE | PS_EXECPLEDGE | PS_WXNEEDED | PS_CHROOT); if (parent->ps_session->s_ttyvp != NULL) pr->ps_flags |= parent->ps_flags & PS_CONTROLT; if (parent->ps_pin.pn_pins) { pr->ps_pin.pn_pins = mallocarray(parent->ps_pin.pn_npins, sizeof(u_int), M_PINSYSCALL, M_WAITOK); memcpy(pr->ps_pin.pn_pins, parent->ps_pin.pn_pins, parent->ps_pin.pn_npins * sizeof(u_int)); pr->ps_flags |= PS_PIN; } if (parent->ps_libcpin.pn_pins) { pr->ps_libcpin.pn_pins = mallocarray(parent->ps_libcpin.pn_npins, sizeof(u_int), M_PINSYSCALL, M_WAITOK); memcpy(pr->ps_libcpin.pn_pins, parent->ps_libcpin.pn_pins, parent->ps_libcpin.pn_npins * sizeof(u_int)); pr->ps_flags |= PS_LIBCPIN; } /* * Duplicate sub-structures as needed. * Increase reference counts on shared objects. */ if (flags & FORK_SHAREFILES) pr->ps_fd = fdshare(parent); else pr->ps_fd = fdcopy(parent); pr->ps_sigacts = sigactsinit(parent); if (flags & FORK_SHAREVM) pr->ps_vmspace = uvmspace_share(parent); else pr->ps_vmspace = uvmspace_fork(parent); if (parent->ps_flags & PS_PROFIL) startprofclock(pr); if (flags & FORK_PTRACE) pr->ps_flags |= parent->ps_flags & PS_TRACED; if (flags & FORK_NOZOMBIE) pr->ps_flags |= PS_NOZOMBIE; if (flags & FORK_SYSTEM) pr->ps_flags |= PS_SYSTEM; /* mark as embryo to protect against others */ pr->ps_flags |= PS_EMBRYO; /* Force visibility of all of the above changes */ membar_producer(); /* it's sufficiently inited to be globally visible */ LIST_INSERT_HEAD(&allprocess, pr, ps_list); return pr; } /* print the 'table full' message once per 10 seconds */ struct timeval fork_tfmrate = { 10, 0 }; int fork_check_maxthread(uid_t uid) { /* * Although process entries are dynamically created, we still keep * a global limit on the maximum number we will create. We reserve * the last 5 processes to root. The variable nprocesses is the * current number of processes, maxprocess is the limit. Similar * rules for threads (struct proc): we reserve the last 5 to root; * the variable nthreads is the current number of procs, maxthread is * the limit. */ if ((nthreads >= maxthread - 5 && uid != 0) || nthreads >= maxthread) { static struct timeval lasttfm; if (ratecheck(&lasttfm, &fork_tfmrate)) tablefull("thread"); return EAGAIN; } nthreads++; return 0; } static inline void fork_thread_start(struct proc *p, struct proc *parent, int flags) { struct cpu_info *ci; int s; SCHED_LOCK(s); ci = sched_choosecpu_fork(parent, flags); TRACEPOINT(sched, fork, p->p_tid + THREAD_PID_OFFSET, p->p_p->ps_pid, CPU_INFO_UNIT(ci)); setrunqueue(ci, p, p->p_usrpri); SCHED_UNLOCK(s); } int fork1(struct proc *curp, int flags, void (*func)(void *), void *arg, register_t *retval, struct proc **rnewprocp) { struct process *curpr = curp->p_p; struct process *pr; struct proc *p; uid_t uid = curp->p_ucred->cr_ruid; struct vmspace *vm; int count; vaddr_t uaddr; int error; struct ptrace_state *newptstat = NULL; KASSERT((flags & ~(FORK_FORK | FORK_VFORK | FORK_PPWAIT | FORK_PTRACE | FORK_IDLE | FORK_SHAREVM | FORK_SHAREFILES | FORK_NOZOMBIE | FORK_SYSTEM)) == 0); KASSERT(func != NULL); if ((error = fork_check_maxthread(uid))) return error; if ((nprocesses >= maxprocess - 5 && uid != 0) || nprocesses >= maxprocess) { static struct timeval lasttfm; if (ratecheck(&lasttfm, &fork_tfmrate)) tablefull("process"); nthreads--; return EAGAIN; } nprocesses++; /* * Increment the count of processes running with this uid. * Don't allow a nonprivileged user to exceed their current limit. */ count = chgproccnt(uid, 1); if (uid != 0 && count > lim_cur(RLIMIT_NPROC)) { (void)chgproccnt(uid, -1); nprocesses--; nthreads--; return EAGAIN; } uaddr = uvm_uarea_alloc(); if (uaddr == 0) { (void)chgproccnt(uid, -1); nprocesses--; nthreads--; return (ENOMEM); } /* * From now on, we're committed to the fork and cannot fail. */ p = thread_new(curp, uaddr); pr = process_new(p, curpr, flags); p->p_fd = pr->ps_fd; p->p_vmspace = pr->ps_vmspace; if (pr->ps_flags & PS_SYSTEM) atomic_setbits_int(&p->p_flag, P_SYSTEM); if (flags & FORK_PPWAIT) { atomic_setbits_int(&pr->ps_flags, PS_PPWAIT); atomic_setbits_int(&curpr->ps_flags, PS_ISPWAIT); } #ifdef KTRACE /* * Copy traceflag and tracefile if enabled. * If not inherited, these were zeroed above. */ if (curpr->ps_traceflag & KTRFAC_INHERIT) ktrsettrace(pr, curpr->ps_traceflag, curpr->ps_tracevp, curpr->ps_tracecred); #endif /* * Finish creating the child thread. cpu_fork() will copy * and update the pcb and make the child ready to run. If * this is a normal user fork, the child will exit directly * to user mode via child_return() on its first time slice * and will not return here. If this is a kernel thread, * the specified entry point will be executed. */ cpu_fork(curp, p, NULL, NULL, func, arg ? arg : p); vm = pr->ps_vmspace; if (flags & FORK_FORK) { forkstat.cntfork++; forkstat.sizfork += vm->vm_dsize + vm->vm_ssize; } else if (flags & FORK_VFORK) { forkstat.cntvfork++; forkstat.sizvfork += vm->vm_dsize + vm->vm_ssize; } else { forkstat.cntkthread++; } if (pr->ps_flags & PS_TRACED && flags & FORK_FORK) newptstat = malloc(sizeof(*newptstat), M_SUBPROC, M_WAITOK); p->p_tid = alloctid(); LIST_INSERT_HEAD(&allproc, p, p_list); LIST_INSERT_HEAD(TIDHASH(p->p_tid), p, p_hash); LIST_INSERT_HEAD(PIDHASH(pr->ps_pid), pr, ps_hash); LIST_INSERT_AFTER(curpr, pr, ps_pglist); LIST_INSERT_HEAD(&curpr->ps_children, pr, ps_sibling); if (pr->ps_flags & PS_TRACED) { pr->ps_oppid = curpr->ps_pid; process_reparent(pr, curpr->ps_pptr); /* * Set ptrace status. */ if (newptstat != NULL) { pr->ps_ptstat = newptstat; newptstat = NULL; curpr->ps_ptstat->pe_report_event = PTRACE_FORK; pr->ps_ptstat->pe_report_event = PTRACE_FORK; curpr->ps_ptstat->pe_other_pid = pr->ps_pid; pr->ps_ptstat->pe_other_pid = curpr->ps_pid; } } /* * For new processes, set accounting bits and mark as complete. */ nanouptime(&pr->ps_start); pr->ps_acflag = AFORK; atomic_clearbits_int(&pr->ps_flags, PS_EMBRYO); if ((flags & FORK_IDLE) == 0) fork_thread_start(p, curp, flags); else p->p_cpu = arg; free(newptstat, M_SUBPROC, sizeof(*newptstat)); /* * Notify any interested parties about the new process. */ knote_locked(&curpr->ps_klist, NOTE_FORK | pr->ps_pid); /* * Update stats now that we know the fork was successful. */ uvmexp.forks++; if (flags & FORK_PPWAIT) uvmexp.forks_ppwait++; if (flags & FORK_SHAREVM) uvmexp.forks_sharevm++; /* * Pass a pointer to the new process to the caller. */ if (rnewprocp != NULL) *rnewprocp = p; /* * Preserve synchronization semantics of vfork. If waiting for * child to exec or exit, set PS_PPWAIT on child and PS_ISPWAIT * on ourselves, and sleep on our process for the latter flag * to go away. * XXX Need to stop other rthreads in the parent */ if (flags & FORK_PPWAIT) while (curpr->ps_flags & PS_ISPWAIT) tsleep_nsec(curpr, PWAIT, "ppwait", INFSLP); /* * If we're tracing the child, alert the parent too. */ if ((flags & FORK_PTRACE) && (curpr->ps_flags & PS_TRACED)) psignal(curp, SIGTRAP); /* * Return child pid to parent process */ if (retval != NULL) *retval = pr->ps_pid; return (0); } int thread_fork(struct proc *curp, void *stack, void *tcb, pid_t *tidptr, register_t *retval) { struct process *pr = curp->p_p; struct proc *p; pid_t tid; vaddr_t uaddr; int error; if (stack == NULL) return EINVAL; if ((error = fork_check_maxthread(curp->p_ucred->cr_ruid))) return error; uaddr = uvm_uarea_alloc(); if (uaddr == 0) { nthreads--; return ENOMEM; } /* * From now on, we're committed to the fork and cannot fail. */ p = thread_new(curp, uaddr); atomic_setbits_int(&p->p_flag, P_THREAD); sigstkinit(&p->p_sigstk); memset(p->p_name, 0, sizeof p->p_name); /* other links */ p->p_p = pr; /* local copies */ p->p_fd = pr->ps_fd; p->p_vmspace = pr->ps_vmspace; /* * Finish creating the child thread. cpu_fork() will copy * and update the pcb and make the child ready to run. The * child will exit directly to user mode via child_return() * on its first time slice and will not return here. */ cpu_fork(curp, p, stack, tcb, child_return, p); p->p_tid = alloctid(); LIST_INSERT_HEAD(&allproc, p, p_list); LIST_INSERT_HEAD(TIDHASH(p->p_tid), p, p_hash); mtx_enter(&pr->ps_mtx); TAILQ_INSERT_TAIL(&pr->ps_threads, p, p_thr_link); pr->ps_threadcnt++; /* * if somebody else wants to take us to single threaded mode, * count ourselves in. */ if (pr->ps_single) { pr->ps_singlecnt++; atomic_setbits_int(&p->p_flag, P_SUSPSINGLE); } mtx_leave(&pr->ps_mtx); /* * Return tid to parent thread and copy it out to userspace */ *retval = tid = p->p_tid + THREAD_PID_OFFSET; if (tidptr != NULL) { if (copyout(&tid, tidptr, sizeof(tid))) psignal(curp, SIGSEGV); } fork_thread_start(p, curp, 0); /* * Update stats now that we know the fork was successful. */ forkstat.cnttfork++; uvmexp.forks++; uvmexp.forks_sharevm++; return 0; } /* Find an unused tid */ pid_t alloctid(void) { pid_t tid; do { /* (0 .. TID_MASK+1] */ tid = 1 + (arc4random() & TID_MASK); } while (tfind(tid) != NULL); return (tid); } /* * Checks for current use of a pid, either as a pid or pgid. */ pid_t oldpids[128]; int ispidtaken(pid_t pid) { uint32_t i; for (i = 0; i < nitems(oldpids); i++) if (pid == oldpids[i]) return (1); if (prfind(pid) != NULL) return (1); if (pgfind(pid) != NULL) return (1); if (zombiefind(pid) != NULL) return (1); return (0); } /* Find an unused pid */ pid_t allocpid(void) { static int first = 1; pid_t pid; /* The first PID allocated is always 1. */ if (first) { first = 0; return 1; } /* * All subsequent PIDs are chosen randomly. We need to * find an unused PID in the range [2, PID_MAX]. */ do { pid = 2 + arc4random_uniform(PID_MAX - 1); } while (ispidtaken(pid)); return pid; } void freepid(pid_t pid) { static uint32_t idx; oldpids[idx++ % nitems(oldpids)] = pid; } /* Do machine independent parts of switching to a new process */ void proc_trampoline_mi(void) { struct schedstate_percpu *spc = &curcpu()->ci_schedstate; struct proc *p = curproc; SCHED_ASSERT_LOCKED(); clear_resched(curcpu()); #if defined(MULTIPROCESSOR) __mp_unlock(&sched_lock); #endif spl0(); SCHED_ASSERT_UNLOCKED(); KERNEL_ASSERT_UNLOCKED(); assertwaitok(); smr_idle(); /* Start any optional clock interrupts needed by the thread. */ if (ISSET(p->p_p->ps_flags, PS_ITIMER)) { atomic_setbits_int(&spc->spc_schedflags, SPCF_ITIMER); clockintr_advance(&spc->spc_itimer, hardclock_period); } if (ISSET(p->p_p->ps_flags, PS_PROFIL)) { atomic_setbits_int(&spc->spc_schedflags, SPCF_PROFCLOCK); clockintr_advance(&spc->spc_profclock, profclock_period); } nanouptime(&spc->spc_runtime); KERNEL_LOCK(); }
37 37 37 2 2 24 22 23 23 8 19 8 19 2 17 19 29 1 27 1 27 4 22 4 1 2 1 65 1 23 2 1 1 1 14 9 37 4 1 1 2 2 3 3 1 36 7 2 2 2 1 5 3 3 2 2 1 33 2 25 2 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 /* $OpenBSD: raw_ip.c,v 1.159 2024/04/17 20:48:51 bluhm Exp $ */ /* $NetBSD: raw_ip.c,v 1.25 1996/02/18 18:58:33 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 * * NRL grants permission for redistribution and use in source and binary * forms, with or without modification, of the software and documentation * created at NRL provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgements: * This product includes software developed by the University of * California, Berkeley and its contributors. * This product includes software developed at the Information * Technology Division, US Naval Research Laboratory. * 4. Neither the name of the NRL nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the US Naval * Research Laboratory (NRL). */ #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/protosw.h> #include <sys/socketvar.h> #include <net/if.h> #include <net/if_var.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_mroute.h> #include <netinet/ip_var.h> #include <netinet/in_pcb.h> #include <netinet/in_var.h> #include <netinet/ip_icmp.h> #include <net/pfvar.h> #include "pf.h" struct inpcbtable rawcbtable; /* * Nominal space allocated to a raw ip socket. */ #define RIPSNDQ 8192 #define RIPRCVQ 8192 /* * Raw interface to IP protocol. */ const struct pr_usrreqs rip_usrreqs = { .pru_attach = rip_attach, .pru_detach = rip_detach, .pru_lock = rip_lock, .pru_unlock = rip_unlock, .pru_locked = rip_locked, .pru_bind = rip_bind, .pru_connect = rip_connect, .pru_disconnect = rip_disconnect, .pru_shutdown = rip_shutdown, .pru_send = rip_send, .pru_control = in_control, .pru_sockaddr = in_sockaddr, .pru_peeraddr = in_peeraddr, }; /* * Initialize raw connection block q. */ void rip_init(void) { in_pcbinit(&rawcbtable, 1); } int rip_input(struct mbuf **mp, int *offp, int proto, int af) { struct mbuf *m = *mp; struct ip *ip = mtod(m, struct ip *); struct inpcb *inp; SIMPLEQ_HEAD(, inpcb) inpcblist; struct in_addr *key; struct counters_ref ref; uint64_t *counters; struct sockaddr_in ripsrc; KASSERT(af == AF_INET); memset(&ripsrc, 0, sizeof(ripsrc)); ripsrc.sin_family = AF_INET; ripsrc.sin_len = sizeof(ripsrc); ripsrc.sin_addr = ip->ip_src; key = &ip->ip_dst; #if NPF > 0 if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { struct pf_divert *divert; divert = pf_find_divert(m); KASSERT(divert != NULL); switch (divert->type) { case PF_DIVERT_TO: key = &divert->addr.v4; break; case PF_DIVERT_REPLY: break; default: panic("%s: unknown divert type %d, mbuf %p, divert %p", __func__, divert->type, m, divert); } } #endif SIMPLEQ_INIT(&inpcblist); rw_enter_write(&rawcbtable.inpt_notify); mtx_enter(&rawcbtable.inpt_mtx); TAILQ_FOREACH(inp, &rawcbtable.inpt_queue, inp_queue) { KASSERT(!ISSET(inp->inp_flags, INP_IPV6)); /* * Packet must not be inserted after disconnected wakeup * call. To avoid race, check again when holding receive * buffer mutex. */ if (ISSET(READ_ONCE(inp->inp_socket->so_rcv.sb_state), SS_CANTRCVMORE)) continue; if (rtable_l2(inp->inp_rtableid) != rtable_l2(m->m_pkthdr.ph_rtableid)) continue; if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != ip->ip_p) continue; if (inp->inp_laddr.s_addr && inp->inp_laddr.s_addr != key->s_addr) continue; if (inp->inp_faddr.s_addr && inp->inp_faddr.s_addr != ip->ip_src.s_addr) continue; in_pcbref(inp); SIMPLEQ_INSERT_TAIL(&inpcblist, inp, inp_notify); } mtx_leave(&rawcbtable.inpt_mtx); if (SIMPLEQ_EMPTY(&inpcblist)) { rw_exit_write(&rawcbtable.inpt_notify); if (ip->ip_p != IPPROTO_ICMP) icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PROTOCOL, 0, 0); else m_freem(m); counters = counters_enter(&ref, ipcounters); counters[ips_noproto]++; counters[ips_delivered]--; counters_leave(&ref, ipcounters); return IPPROTO_DONE; } while ((inp = SIMPLEQ_FIRST(&inpcblist)) != NULL) { struct mbuf *n, *opts = NULL; SIMPLEQ_REMOVE_HEAD(&inpcblist, inp_notify); if (SIMPLEQ_EMPTY(&inpcblist)) n = m; else n = m_copym(m, 0, M_COPYALL, M_NOWAIT); if (n != NULL) { struct socket *so = inp->inp_socket; int ret = 0; if (inp->inp_flags & INP_CONTROLOPTS || so->so_options & SO_TIMESTAMP) ip_savecontrol(inp, &opts, ip, n); mtx_enter(&so->so_rcv.sb_mtx); if (!ISSET(inp->inp_socket->so_rcv.sb_state, SS_CANTRCVMORE)) { ret = sbappendaddr(so, &so->so_rcv, sintosa(&ripsrc), n, opts); } mtx_leave(&so->so_rcv.sb_mtx); if (ret == 0) { m_freem(n); m_freem(opts); ipstat_inc(ips_noproto); } else sorwakeup(so); } in_pcbunref(inp); } rw_exit_write(&rawcbtable.inpt_notify); return IPPROTO_DONE; } /* * Generate IP header and pass packet to ip_output. * Tack on options user may have setup with control call. */ int rip_output(struct mbuf *m, struct socket *so, struct sockaddr *dstaddr, struct mbuf *control) { struct sockaddr_in *dst = satosin(dstaddr); struct ip *ip; struct inpcb *inp; int flags, error; inp = sotoinpcb(so); flags = IP_ALLOWBROADCAST; /* * If the user handed us a complete IP packet, use it. * Otherwise, allocate an mbuf for a header and fill it in. */ if ((inp->inp_flags & INP_HDRINCL) == 0) { if ((m->m_pkthdr.len + sizeof(struct ip)) > IP_MAXPACKET) { m_freem(m); return (EMSGSIZE); } M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); if (!m) return (ENOBUFS); ip = mtod(m, struct ip *); ip->ip_tos = inp->inp_ip.ip_tos; ip->ip_off = htons(0); ip->ip_p = inp->inp_ip.ip_p; ip->ip_len = htons(m->m_pkthdr.len); ip->ip_src.s_addr = INADDR_ANY; ip->ip_dst = dst->sin_addr; ip->ip_ttl = inp->inp_ip.ip_ttl ? inp->inp_ip.ip_ttl : MAXTTL; } else { if (m->m_pkthdr.len > IP_MAXPACKET) { m_freem(m); return (EMSGSIZE); } m = rip_chkhdr(m, inp->inp_options); if (m == NULL) return (EINVAL); ip = mtod(m, struct ip *); if (ip->ip_id == 0) ip->ip_id = htons(ip_randomid()); dst->sin_addr = ip->ip_dst; /* XXX prevent ip_output from overwriting header fields */ flags |= IP_RAWOUTPUT; ipstat_inc(ips_rawout); } if (ip->ip_src.s_addr == INADDR_ANY) { error = in_pcbselsrc(&ip->ip_src, dst, inp); if (error != 0) return (error); } #ifdef INET6 /* * A thought: Even though raw IP shouldn't be able to set IPv6 * multicast options, if it does, the last parameter to * ip_output should be guarded against v6/v4 problems. */ #endif /* force routing table */ m->m_pkthdr.ph_rtableid = inp->inp_rtableid; #if NPF > 0 if (inp->inp_socket->so_state & SS_ISCONNECTED && ip->ip_p != IPPROTO_ICMP) pf_mbuf_link_inpcb(m, inp); #endif error = ip_output(m, inp->inp_options, &inp->inp_route, flags, inp->inp_moptions, &inp->inp_seclevel, 0); return (error); } struct mbuf * rip_chkhdr(struct mbuf *m, struct mbuf *options) { struct ip *ip; int hlen, opt, optlen, cnt; u_char *cp; if (m->m_pkthdr.len < sizeof(struct ip)) { m_freem(m); return NULL; } m = m_pullup(m, sizeof (struct ip)); if (m == NULL) return NULL; ip = mtod(m, struct ip *); hlen = ip->ip_hl << 2; /* Don't allow packet length sizes that will crash. */ if (hlen < sizeof (struct ip) || ntohs(ip->ip_len) < hlen || ntohs(ip->ip_len) != m->m_pkthdr.len) { m_freem(m); return NULL; } m = m_pullup(m, hlen); if (m == NULL) return NULL; ip = mtod(m, struct ip *); if (ip->ip_v != IPVERSION) { m_freem(m); return NULL; } /* * Don't allow both user specified and setsockopt options. * If options are present verify them. */ if (hlen != sizeof(struct ip)) { if (options) { m_freem(m); return NULL; } else { cp = (u_char *)(ip + 1); cnt = hlen - sizeof(struct ip); for (; cnt > 0; cnt -= optlen, cp += optlen) { opt = cp[IPOPT_OPTVAL]; if (opt == IPOPT_EOL) break; if (opt == IPOPT_NOP) optlen = 1; else { if (cnt < IPOPT_OLEN + sizeof(*cp)) { m_freem(m); return NULL; } optlen = cp[IPOPT_OLEN]; if (optlen < IPOPT_OLEN + sizeof(*cp) || optlen > cnt) { m_freem(m); return NULL; } } } } } return m; } /* * Raw IP socket option processing. */ int rip_ctloutput(int op, struct socket *so, int level, int optname, struct mbuf *m) { struct inpcb *inp = sotoinpcb(so); int error; if (level != IPPROTO_IP) return (EINVAL); switch (optname) { case IP_HDRINCL: error = 0; if (op == PRCO_SETOPT) { if (m == NULL || m->m_len < sizeof (int)) error = EINVAL; else if (*mtod(m, int *)) inp->inp_flags |= INP_HDRINCL; else inp->inp_flags &= ~INP_HDRINCL; } else { m->m_len = sizeof(int); *mtod(m, int *) = inp->inp_flags & INP_HDRINCL; } return (error); case MRT_INIT: case MRT_DONE: case MRT_ADD_VIF: case MRT_DEL_VIF: case MRT_ADD_MFC: case MRT_DEL_MFC: case MRT_VERSION: case MRT_ASSERT: case MRT_API_SUPPORT: case MRT_API_CONFIG: #ifdef MROUTING switch (op) { case PRCO_SETOPT: error = ip_mrouter_set(so, optname, m); break; case PRCO_GETOPT: error = ip_mrouter_get(so, optname, m); break; default: error = EINVAL; break; } return (error); #else return (EOPNOTSUPP); #endif } return (ip_ctloutput(op, so, level, optname, m)); } u_long rip_sendspace = RIPSNDQ; u_long rip_recvspace = RIPRCVQ; int rip_attach(struct socket *so, int proto, int wait) { struct inpcb *inp; int error; if (so->so_pcb) panic("rip_attach"); if ((so->so_state & SS_PRIV) == 0) return EACCES; if (proto < 0 || proto >= IPPROTO_MAX) return EPROTONOSUPPORT; if ((error = soreserve(so, rip_sendspace, rip_recvspace))) return error; NET_ASSERT_LOCKED(); if ((error = in_pcballoc(so, &rawcbtable, wait))) return error; inp = sotoinpcb(so); inp->inp_ip.ip_p = proto; return 0; } int rip_detach(struct socket *so) { struct inpcb *inp = sotoinpcb(so); soassertlocked(so); if (inp == NULL) return (EINVAL); #ifdef MROUTING if (so == ip_mrouter[inp->inp_rtableid]) ip_mrouter_done(so); #endif in_pcbdetach(inp); return (0); } void rip_lock(struct socket *so) { struct inpcb *inp = sotoinpcb(so); NET_ASSERT_LOCKED(); mtx_enter(&inp->inp_mtx); } void rip_unlock(struct socket *so) { struct inpcb *inp = sotoinpcb(so); NET_ASSERT_LOCKED(); mtx_leave(&inp->inp_mtx); } int rip_locked(struct socket *so) { struct inpcb *inp = sotoinpcb(so); return mtx_owned(&inp->inp_mtx); } int rip_bind(struct socket *so, struct mbuf *nam, struct proc *p) { struct inpcb *inp = sotoinpcb(so); struct sockaddr_in *addr; int error; soassertlocked(so); if ((error = in_nam2sin(nam, &addr))) return (error); if (!((so->so_options & SO_BINDANY) || addr->sin_addr.s_addr == INADDR_ANY || addr->sin_addr.s_addr == INADDR_BROADCAST || in_broadcast(addr->sin_addr, inp->inp_rtableid) || ifa_ifwithaddr(sintosa(addr), inp->inp_rtableid))) return (EADDRNOTAVAIL); mtx_enter(&rawcbtable.inpt_mtx); inp->inp_laddr = addr->sin_addr; mtx_leave(&rawcbtable.inpt_mtx); return (0); } int rip_connect(struct socket *so, struct mbuf *nam) { struct inpcb *inp = sotoinpcb(so); struct sockaddr_in *addr; int error; soassertlocked(so); if ((error = in_nam2sin(nam, &addr))) return (error); mtx_enter(&rawcbtable.inpt_mtx); inp->inp_faddr = addr->sin_addr; mtx_leave(&rawcbtable.inpt_mtx); soisconnected(so); return (0); } int rip_disconnect(struct socket *so) { struct inpcb *inp = sotoinpcb(so); soassertlocked(so); if ((so->so_state & SS_ISCONNECTED) == 0) return (ENOTCONN); soisdisconnected(so); mtx_enter(&rawcbtable.inpt_mtx); inp->inp_faddr.s_addr = INADDR_ANY; mtx_leave(&rawcbtable.inpt_mtx); return (0); } int rip_shutdown(struct socket *so) { /* * Mark the connection as being incapable of further input. */ soassertlocked(so); socantsendmore(so); return (0); } int rip_send(struct socket *so, struct mbuf *m, struct mbuf *nam, struct mbuf *control) { struct inpcb *inp = sotoinpcb(so); struct sockaddr_in dst; int error; soassertlocked(so); /* * Ship a packet out. The appropriate raw output * routine handles any massaging necessary. */ memset(&dst, 0, sizeof(dst)); dst.sin_family = AF_INET; dst.sin_len = sizeof(dst); if (so->so_state & SS_ISCONNECTED) { if (nam) { error = EISCONN; goto out; } dst.sin_addr = inp->inp_faddr; } else { struct sockaddr_in *addr; if (nam == NULL) { error = ENOTCONN; goto out; } if ((error = in_nam2sin(nam, &addr))) goto out; dst.sin_addr = addr->sin_addr; } #ifdef IPSEC /* XXX Find an IPsec TDB */ #endif error = rip_output(m, so, sintosa(&dst), NULL); m = NULL; out: m_freem(control); m_freem(m); return (error); }
16 2 18 30 30 2 2 59 54 55 5 22 50 5 55 68 53 54 20 4 20 11 46 46 13 55 55 19 35 35 47 1 4 2 27 30 10 13 9 8 7 6 3 3 7 6 658 600 70 25 5 731 681 3 3 63 43 703 657 2 37 16 8 4 6 21 5 2 12 15 28 13 10 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 /* $OpenBSD: kern_unveil.c,v 1.55 2022/12/05 23:18:37 deraadt Exp $ */ /* * Copyright (c) 2017-2019 Bob Beck <beck@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/acct.h> #include <sys/mount.h> #include <sys/filedesc.h> #include <sys/proc.h> #include <sys/namei.h> #include <sys/vnode.h> #include <sys/types.h> #include <sys/malloc.h> #include <sys/tree.h> #include <sys/lock.h> #include <sys/syscall.h> #include <sys/syscallargs.h> #include <sys/systm.h> #include <sys/pledge.h> struct unvname { char *un_name; size_t un_namesize; u_char un_flags; RBT_ENTRY(unvnmae) un_rbt; }; RBT_HEAD(unvname_rbt, unvname); struct unveil { struct vnode *uv_vp; ssize_t uv_cover; struct unvname_rbt uv_names; struct rwlock uv_lock; u_char uv_flags; }; /* #define DEBUG_UNVEIL */ #ifdef DEBUG_UNVEIL #define DPRINTF(x...) do { printf(x); } while (0) #else #define DPRINTF(x...) #endif #define UNVEIL_MAX_VNODES 128 #define UNVEIL_MAX_NAMES 128 static inline int unvname_compare(const struct unvname *n1, const struct unvname *n2) { if (n1->un_namesize == n2->un_namesize) return (memcmp(n1->un_name, n2->un_name, n1->un_namesize)); else return (n1->un_namesize - n2->un_namesize); } struct unvname * unvname_new(const char *name, size_t size, u_char flags) { struct unvname *ret = malloc(sizeof(struct unvname), M_PROC, M_WAITOK); ret->un_name = malloc(size, M_PROC, M_WAITOK); memcpy(ret->un_name, name, size); ret->un_namesize = size; ret->un_flags = flags; return ret; } void unvname_delete(struct unvname *name) { free(name->un_name, M_PROC, name->un_namesize); free(name, M_PROC, sizeof(struct unvname)); } RBT_PROTOTYPE(unvname_rbt, unvname, un_rbt, unvname_compare); RBT_GENERATE(unvname_rbt, unvname, un_rbt, unvname_compare); int unveil_delete_names(struct unveil *uv) { struct unvname *unvn, *next; int ret = 0; rw_enter_write(&uv->uv_lock); RBT_FOREACH_SAFE(unvn, unvname_rbt, &uv->uv_names, next) { RBT_REMOVE(unvname_rbt, &uv->uv_names, unvn); unvname_delete(unvn); ret++; } rw_exit_write(&uv->uv_lock); DPRINTF("deleted %d names\n", ret); return ret; } int unveil_add_name_unlocked(struct unveil *uv, char *name, u_char flags) { struct unvname *unvn; unvn = unvname_new(name, strlen(name) + 1, flags); if (RBT_INSERT(unvname_rbt, &uv->uv_names, unvn) != NULL) { /* Name already present. */ unvname_delete(unvn); return 0; } DPRINTF("added name %s underneath vnode %p\n", name, uv->uv_vp); return 1; } int unveil_add_name(struct unveil *uv, char *name, u_char flags) { int ret; rw_enter_write(&uv->uv_lock); ret = unveil_add_name_unlocked(uv, name, flags); rw_exit_write(&uv->uv_lock); return ret; } struct unvname * unveil_namelookup(struct unveil *uv, char *name) { struct unvname n, *ret = NULL; rw_enter_read(&uv->uv_lock); DPRINTF("%s: looking up name %s (%p) in vnode %p\n", __func__, name, name, uv->uv_vp); KASSERT(uv->uv_vp != NULL); n.un_name = name; n.un_namesize = strlen(name) + 1; ret = RBT_FIND(unvname_rbt, &uv->uv_names, &n); rw_exit_read(&uv->uv_lock); DPRINTF("%s: %s name %s in vnode %p\n", __func__, (ret == NULL) ? "no match for" : "matched", name, uv->uv_vp); return ret; } void unveil_destroy(struct process *ps) { size_t i; for (i = 0; ps->ps_uvpaths != NULL && i < ps->ps_uvvcount; i++) { struct unveil *uv = ps->ps_uvpaths + i; struct vnode *vp = uv->uv_vp; /* skip any vnodes zapped by unveil_removevnode */ if (vp != NULL) { vp->v_uvcount--; DPRINTF("unveil: %s(%d): removing vnode %p uvcount %d " "in position %ld\n", ps->ps_comm, ps->ps_pid, vp, vp->v_uvcount, i); vrele(vp); } ps->ps_uvncount -= unveil_delete_names(uv); uv->uv_vp = NULL; uv->uv_flags = 0; } KASSERT(ps->ps_uvncount == 0); free(ps->ps_uvpaths, M_PROC, UNVEIL_MAX_VNODES * sizeof(struct unveil)); ps->ps_uvvcount = 0; ps->ps_uvpaths = NULL; } void unveil_copy(struct process *parent, struct process *child) { size_t i; child->ps_uvdone = parent->ps_uvdone; if (parent->ps_uvvcount == 0) return; child->ps_uvpaths = mallocarray(UNVEIL_MAX_VNODES, sizeof(struct unveil), M_PROC, M_WAITOK|M_ZERO); child->ps_uvncount = 0; for (i = 0; parent->ps_uvpaths != NULL && i < parent->ps_uvvcount; i++) { struct unveil *from = parent->ps_uvpaths + i; struct unveil *to = child->ps_uvpaths + i; struct unvname *unvn, *next; to->uv_vp = from->uv_vp; if (to->uv_vp != NULL) { vref(to->uv_vp); to->uv_vp->v_uvcount++; } rw_init(&to->uv_lock, "unveil"); RBT_INIT(unvname_rbt, &to->uv_names); rw_enter_read(&from->uv_lock); RBT_FOREACH_SAFE(unvn, unvname_rbt, &from->uv_names, next) { if (unveil_add_name_unlocked(&child->ps_uvpaths[i], unvn->un_name, unvn->un_flags)) child->ps_uvncount++; } rw_exit_read(&from->uv_lock); to->uv_flags = from->uv_flags; to->uv_cover = from->uv_cover; } child->ps_uvvcount = parent->ps_uvvcount; } /* * Walk up from vnode dp, until we find a matching unveil, or the root vnode * returns -1 if no unveil to be found above dp or if dp is the root vnode. */ ssize_t unveil_find_cover(struct vnode *dp, struct proc *p) { struct vnode *vp = NULL, *parent = NULL, *root; ssize_t ret = -1; int error; /* use the correct root to stop at, chrooted or not.. */ root = p->p_fd->fd_rdir ? p->p_fd->fd_rdir : rootvnode; vp = dp; while (vp != root) { struct componentname cn = { .cn_nameiop = LOOKUP, .cn_flags = ISLASTCN | ISDOTDOT | RDONLY, .cn_proc = p, .cn_cred = p->p_ucred, .cn_pnbuf = NULL, .cn_nameptr = "..", .cn_namelen = 2, .cn_consume = 0 }; /* * If we are at the root of a filesystem, and we are * still mounted somewhere, take the .. in the above * filesystem. */ if (vp != root && (vp->v_flag & VROOT)) { if (vp->v_mount == NULL) return -1; vp = vp->v_mount->mnt_vnodecovered ? vp->v_mount->mnt_vnodecovered : vp; } if (vget(vp, LK_EXCLUSIVE|LK_RETRY) != 0) return -1; /* Get parent vnode of vp using lookup of '..' */ /* This returns with vp unlocked but ref'ed*/ error = VOP_LOOKUP(vp, &parent, &cn); if (error) { if (!(cn.cn_flags & PDIRUNLOCK)) vput(vp); else { /* * This corner case should not happen because * we have not set LOCKPARENT in the flags */ DPRINTF("vnode %p PDIRUNLOCK on error\n", vp); vrele(vp); } break; } vrele(vp); (void) unveil_lookup(parent, p->p_p, &ret); vput(parent); if (ret >= 0) break; if (vp == parent) { ret = -1; break; } vp = parent; parent = NULL; } return ret; } struct unveil * unveil_lookup(struct vnode *vp, struct process *pr, ssize_t *position) { struct unveil *uv = pr->ps_uvpaths; ssize_t i; if (position != NULL) *position = -1; if (vp->v_uvcount == 0) return NULL; for (i = 0; i < pr->ps_uvvcount; i++) { if (vp == uv[i].uv_vp) { KASSERT(uv[i].uv_vp->v_uvcount > 0); KASSERT(uv[i].uv_vp->v_usecount > 0); if (position != NULL) *position = i; return &uv[i]; } } return NULL; } int unveil_parsepermissions(const char *permissions, u_char *perms) { size_t i = 0; char c; *perms = UNVEIL_USERSET; while ((c = permissions[i++]) != '\0') { switch (c) { case 'r': *perms |= UNVEIL_READ; break; case 'w': *perms |= UNVEIL_WRITE; break; case 'x': *perms |= UNVEIL_EXEC; break; case 'c': *perms |= UNVEIL_CREATE; break; default: return -1; } } return 0; } int unveil_setflags(u_char *flags, u_char nflags) { #if 0 if (((~(*flags)) & nflags) != 0) { DPRINTF("Flags escalation %llX -> %llX\n", *flags, nflags); return 1; } #endif *flags = nflags; return 1; } struct unveil * unveil_add_vnode(struct proc *p, struct vnode *vp) { struct process *pr = p->p_p; struct unveil *uv = NULL; ssize_t i; KASSERT(pr->ps_uvvcount < UNVEIL_MAX_VNODES); uv = &pr->ps_uvpaths[pr->ps_uvvcount++]; rw_init(&uv->uv_lock, "unveil"); RBT_INIT(unvname_rbt, &uv->uv_names); uv->uv_vp = vp; uv->uv_flags = 0; /* find out what we are covered by */ uv->uv_cover = unveil_find_cover(vp, p); /* * Find anyone covered by what we are covered by * and re-check what covers them (we could have * interposed a cover) */ for (i = 0; i < pr->ps_uvvcount - 1; i++) { if (pr->ps_uvpaths[i].uv_cover == uv->uv_cover) pr->ps_uvpaths[i].uv_cover = unveil_find_cover(pr->ps_uvpaths[i].uv_vp, p); } return (uv); } int unveil_add(struct proc *p, struct nameidata *ndp, const char *permissions) { struct process *pr = p->p_p; struct vnode *vp; struct unveil *uv; int directory_add; int ret = EINVAL; u_char flags; KASSERT(ISSET(ndp->ni_cnd.cn_flags, HASBUF)); /* must have SAVENAME */ if (unveil_parsepermissions(permissions, &flags) == -1) goto done; if (pr->ps_uvpaths == NULL) { pr->ps_uvpaths = mallocarray(UNVEIL_MAX_VNODES, sizeof(struct unveil), M_PROC, M_WAITOK|M_ZERO); } if (pr->ps_uvvcount >= UNVEIL_MAX_VNODES || pr->ps_uvncount >= UNVEIL_MAX_NAMES) { ret = E2BIG; goto done; } /* Are we a directory? or something else */ directory_add = ndp->ni_vp != NULL && ndp->ni_vp->v_type == VDIR; if (directory_add) vp = ndp->ni_vp; else vp = ndp->ni_dvp; KASSERT(vp->v_type == VDIR); vref(vp); vp->v_uvcount++; if ((uv = unveil_lookup(vp, pr, NULL)) != NULL) { /* * We already have unveiled this directory * vnode */ vp->v_uvcount--; vrele(vp); /* * If we are adding a directory which was already * unveiled containing only specific terminals, * unrestrict it. */ if (directory_add) { DPRINTF("unveil: %s(%d): updating directory vnode %p" " to unrestricted uvcount %d\n", pr->ps_comm, pr->ps_pid, vp, vp->v_uvcount); if (!unveil_setflags(&uv->uv_flags, flags)) ret = EPERM; else ret = 0; goto done; } /* * If we are adding a terminal that is already unveiled, just * replace the flags and we are done */ if (!directory_add) { struct unvname *tname; if ((tname = unveil_namelookup(uv, ndp->ni_cnd.cn_nameptr)) != NULL) { DPRINTF("unveil: %s(%d): changing flags for %s" "in vnode %p, uvcount %d\n", pr->ps_comm, pr->ps_pid, tname->un_name, vp, vp->v_uvcount); if (!unveil_setflags(&tname->un_flags, flags)) ret = EPERM; else ret = 0; goto done; } } } else { /* * New unveil involving this directory vnode. */ uv = unveil_add_vnode(p, vp); } /* * At this stage with have a unveil in uv with a vnode for a * directory. If the component we are adding is a directory, * we are done. Otherwise, we add the component name the name * list in uv. */ if (directory_add) { uv->uv_flags = flags; ret = 0; DPRINTF("unveil: %s(%d): added unrestricted directory vnode %p" ", uvcount %d\n", pr->ps_comm, pr->ps_pid, vp, vp->v_uvcount); goto done; } if (unveil_add_name(uv, ndp->ni_cnd.cn_nameptr, flags)) pr->ps_uvncount++; ret = 0; DPRINTF("unveil: %s(%d): added name %s beneath %s vnode %p," " uvcount %d\n", pr->ps_comm, pr->ps_pid, ndp->ni_cnd.cn_nameptr, uv->uv_flags ? "unrestricted" : "restricted", vp, vp->v_uvcount); done: return ret; } /* * XXX this will probably change. * XXX collapse down later once debug surely unneeded */ int unveil_flagmatch(struct nameidata *ni, u_char flags) { if (flags == 0) { DPRINTF("All operations forbidden for 0 flags\n"); return 0; } if (ni->ni_unveil & UNVEIL_READ) { if ((flags & UNVEIL_READ) == 0) { DPRINTF("unveil lacks UNVEIL_READ\n"); return 0; } } if (ni->ni_unveil & UNVEIL_WRITE) { if ((flags & UNVEIL_WRITE) == 0) { DPRINTF("unveil lacks UNVEIL_WRITE\n"); return 0; } } if (ni->ni_unveil & UNVEIL_EXEC) { if ((flags & UNVEIL_EXEC) == 0) { DPRINTF("unveil lacks UNVEIL_EXEC\n"); return 0; } } if (ni->ni_unveil & UNVEIL_CREATE) { if ((flags & UNVEIL_CREATE) == 0) { DPRINTF("unveil lacks UNVEIL_CREATE\n"); return 0; } } return 1; } /* * When traversing up towards the root figure out the proper unveil for * the parent directory. */ struct unveil * unveil_covered(struct unveil *uv, struct vnode *dvp, struct proc *p) { if (uv && uv->uv_vp == dvp) { /* if at the root, chrooted or not, return the current uv */ if (dvp == (p->p_fd->fd_rdir ? p->p_fd->fd_rdir : rootvnode)) return uv; if (uv->uv_cover >=0) { KASSERT(uv->uv_cover < p->p_p->ps_uvvcount); return &p->p_p->ps_uvpaths[uv->uv_cover]; } return NULL; } return uv; } /* * Start a relative path lookup. Ensure we find whatever unveil covered * where we start from, either by having a saved current working directory * unveil, or by walking up and finding a cover the hard way if we are * doing a non AT_FDCWD relative lookup. Caller passes a NULL dp * if we are using AT_FDCWD. */ void unveil_start_relative(struct proc *p, struct nameidata *ni, struct vnode *dp) { struct process *pr = p->p_p; struct unveil *uv = NULL; ssize_t uvi; if (pr->ps_uvpaths == NULL) return; uv = unveil_lookup(dp, pr, NULL); if (uv == NULL) { uvi = unveil_find_cover(dp, p); if (uvi >= 0) { KASSERT(uvi < pr->ps_uvvcount); uv = &pr->ps_uvpaths[uvi]; } } /* * Store this match for later use. Flags are checked at the end. */ if (uv) { DPRINTF("unveil: %s(%d): relative unveil at %p matches", pr->ps_comm, pr->ps_pid, uv); ni->ni_unveil_match = uv; } } /* * unveil checking - for component directories in a namei lookup. */ void unveil_check_component(struct proc *p, struct nameidata *ni, struct vnode *dp) { struct process *pr = p->p_p; struct unveil *uv = NULL; if (ni->ni_pledge == PLEDGE_UNVEIL || pr->ps_uvpaths == NULL) return; if (ni->ni_cnd.cn_flags & BYPASSUNVEIL) return; if (ni->ni_cnd.cn_flags & ISDOTDOT) { /* * adjust unveil match as necessary */ uv = unveil_covered(ni->ni_unveil_match, dp, p); /* clear the match when we DOTDOT above it */ if (ni->ni_unveil_match && ni->ni_unveil_match->uv_vp == dp) ni->ni_unveil_match = NULL; } else uv = unveil_lookup(dp, pr, NULL); if (uv != NULL) { /* update match */ ni->ni_unveil_match = uv; DPRINTF("unveil: %s(%d): component directory match for " "vnode %p\n", pr->ps_comm, pr->ps_pid, dp); } } /* * unveil checking - only done after namei lookup has succeeded on * the last component of a namei lookup. */ int unveil_check_final(struct proc *p, struct nameidata *ni) { struct process *pr = p->p_p; struct unveil *uv = NULL, *nuv; struct unvname *tname = NULL; if (ni->ni_pledge == PLEDGE_UNVEIL || pr->ps_uvpaths == NULL) return (0); if (ni->ni_cnd.cn_flags & BYPASSUNVEIL) { DPRINTF("unveil: %s(%d): BYPASSUNVEIL.\n", pr->ps_comm, pr->ps_pid); return (0); } if (ni->ni_vp != NULL && ni->ni_vp->v_type == VDIR) { /* We are matching a directory terminal component */ uv = unveil_lookup(ni->ni_vp, pr, NULL); if (uv == NULL || (uv->uv_flags & UNVEIL_USERSET) == 0) { DPRINTF("unveil: %s(%d) no match for vnode %p\n", pr->ps_comm, pr->ps_pid, ni->ni_vp); if (uv != NULL) ni->ni_unveil_match = uv; goto done; } if (!unveil_flagmatch(ni, uv->uv_flags)) { DPRINTF("unveil: %s(%d) flag mismatch for directory" " vnode %p\n", pr->ps_comm, pr->ps_pid, ni->ni_vp); pr->ps_acflag |= AUNVEIL; if (uv->uv_flags & UNVEIL_MASK) return EACCES; else return ENOENT; } /* directory and flags match, success */ DPRINTF("unveil: %s(%d): matched directory \"%s\" at vnode %p\n", pr->ps_comm, pr->ps_pid, ni->ni_cnd.cn_nameptr, uv->uv_vp); return (0); } /* Otherwise, we are matching a non-terminal component */ uv = unveil_lookup(ni->ni_dvp, pr, NULL); if (uv == NULL) { DPRINTF("unveil: %s(%d) no match for directory vnode %p\n", pr->ps_comm, pr->ps_pid, ni->ni_dvp); goto done; } if ((tname = unveil_namelookup(uv, ni->ni_cnd.cn_nameptr)) == NULL) { DPRINTF("unveil: %s(%d) no match for terminal '%s' in " "directory vnode %p\n", pr->ps_comm, pr->ps_pid, ni->ni_cnd.cn_nameptr, ni->ni_dvp); /* no specific name, so check unveil directory flags */ if (!unveil_flagmatch(ni, uv->uv_flags)) { DPRINTF("unveil: %s(%d) terminal " "'%s' flags mismatch in directory " "vnode %p\n", pr->ps_comm, pr->ps_pid, ni->ni_cnd.cn_nameptr, ni->ni_dvp); /* * If dir has user set restrictions fail with * EACCES or ENOENT. Otherwise, use any covering * match that we found above this dir. */ if (uv->uv_flags & UNVEIL_USERSET) { pr->ps_acflag |= AUNVEIL; if (uv->uv_flags & UNVEIL_MASK) return EACCES; else return ENOENT; } /* start backtrack from this node */ ni->ni_unveil_match = uv; goto done; } /* directory flags match, success */ DPRINTF("unveil: %s(%d): matched \"%s\" underneath vnode %p\n", pr->ps_comm, pr->ps_pid, ni->ni_cnd.cn_nameptr, uv->uv_vp); return (0); } if (!unveil_flagmatch(ni, tname->un_flags)) { /* do flags match for matched name */ DPRINTF("unveil: %s(%d) flag mismatch for terminal '%s'\n", pr->ps_comm, pr->ps_pid, tname->un_name); pr->ps_acflag |= AUNVEIL; return EACCES; } /* name and flags match. success */ DPRINTF("unveil: %s(%d) matched terminal '%s'\n", pr->ps_comm, pr->ps_pid, tname->un_name); return (0); done: /* * last component did not match, check previous matches if * access is allowed or not. */ for (uv = ni->ni_unveil_match; uv != NULL; uv = nuv) { if (unveil_flagmatch(ni, uv->uv_flags)) { DPRINTF("unveil: %s(%d): matched \"%s\" underneath/at " "vnode %p\n", pr->ps_comm, pr->ps_pid, ni->ni_cnd.cn_nameptr, uv->uv_vp); return (0); } /* if node has any flags set then this is an access violation */ if (uv->uv_flags & UNVEIL_USERSET) { DPRINTF("unveil: %s(%d) flag mismatch for vnode %p\n", pr->ps_comm, pr->ps_pid, uv->uv_vp); pr->ps_acflag |= AUNVEIL; if (uv->uv_flags & UNVEIL_MASK) return EACCES; else return ENOENT; } DPRINTF("unveil: %s(%d) check cover for vnode %p, uv_cover %zd\n", pr->ps_comm, pr->ps_pid, uv->uv_vp, uv->uv_cover); nuv = unveil_covered(uv, uv->uv_vp, p); if (nuv == uv) break; } pr->ps_acflag |= AUNVEIL; return ENOENT; } /* * Scan all active processes to see if any of them have a unveil * to this vnode. If so, NULL the vnode in their unveil list, * vrele, drop the reference, and mark their unveil list * as needing to have the hole shrunk the next time the process * uses it for lookup. */ void unveil_removevnode(struct vnode *vp) { struct process *pr; if (vp->v_uvcount == 0) return; DPRINTF("%s: found vnode %p with count %d\n", __func__, vp, vp->v_uvcount); vref(vp); /* make sure it is held till we are done */ LIST_FOREACH(pr, &allprocess, ps_list) { struct unveil * uv; if ((uv = unveil_lookup(vp, pr, NULL)) != NULL && uv->uv_vp != NULL) { uv->uv_vp = NULL; uv->uv_flags = 0; DPRINTF("%s: vnode %p now count %d\n", __func__, vp, vp->v_uvcount); if (vp->v_uvcount > 0) { vrele(vp); vp->v_uvcount--; } else panic("vp %p, v_uvcount of %d should be 0", vp, vp->v_uvcount); } } KASSERT(vp->v_uvcount == 0); vrele(vp); /* release our ref */ }
2249 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 /* $OpenBSD: tsc.c,v 1.32 2024/04/03 02:01:21 guenther Exp $ */ /* * Copyright (c) 2008 The NetBSD Foundation, Inc. * Copyright (c) 2016,2017 Reyk Floeter <reyk@openbsd.org> * Copyright (c) 2017 Adam Steen <adam@adamsteen.com.au> * Copyright (c) 2017 Mike Belopuhov <mike@openbsd.org> * Copyright (c) 2019 Paul Irofti <paul@irofti.net> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/timetc.h> #include <sys/atomic.h> #include <machine/cpu.h> #include <machine/cpufunc.h> #define RECALIBRATE_MAX_RETRIES 5 #define RECALIBRATE_SMI_THRESHOLD 50000 #define RECALIBRATE_DELAY_THRESHOLD 50 int tsc_recalibrate; uint64_t tsc_frequency; int tsc_is_invariant; u_int tsc_get_timecount_lfence(struct timecounter *tc); u_int tsc_get_timecount_rdtscp(struct timecounter *tc); void tsc_delay(int usecs); #include "lapic.h" #if NLAPIC > 0 extern u_int32_t lapic_per_second; #endif u_int64_t (*tsc_rdtsc)(void) = rdtsc_lfence; struct timecounter tsc_timecounter = { .tc_get_timecount = tsc_get_timecount_lfence, .tc_counter_mask = ~0u, .tc_frequency = 0, .tc_name = "tsc", .tc_quality = -1000, .tc_priv = NULL, .tc_user = TC_TSC_LFENCE, }; uint64_t tsc_freq_cpuid(struct cpu_info *ci) { uint64_t count; uint32_t eax, ebx, khz, dummy; if (ci->ci_vendor == CPUV_INTEL && ci->ci_cpuid_level >= 0x15) { eax = ebx = khz = dummy = 0; CPUID(0x15, eax, ebx, khz, dummy); khz /= 1000; if (khz == 0) { switch (ci->ci_model) { case 0x4e: /* Skylake mobile */ case 0x5e: /* Skylake desktop */ case 0x8e: /* Kabylake mobile */ case 0x9e: /* Kabylake desktop */ case 0xa5: /* CML-H CML-S62 CML-S102 */ case 0xa6: /* CML-U62 */ khz = 24000; /* 24.0 MHz */ break; case 0x5f: /* Atom Denverton */ khz = 25000; /* 25.0 MHz */ break; case 0x5c: /* Atom Goldmont */ khz = 19200; /* 19.2 MHz */ break; } } if (ebx == 0 || eax == 0) count = 0; else if ((count = (uint64_t)khz * (uint64_t)ebx / eax) != 0) { #if NLAPIC > 0 lapic_per_second = khz * 1000; #endif return (count * 1000); } } return (0); } uint64_t tsc_freq_msr(struct cpu_info *ci) { uint64_t base, def, divisor, multiplier; if (ci->ci_vendor != CPUV_AMD) return 0; /* * All 10h+ CPUs have Core::X86::Msr:HWCR and the TscFreqSel * bit. If TscFreqSel hasn't been set, the TSC isn't advancing * at the core P0 frequency and we need to calibrate by hand. */ if (ci->ci_family < 0x10) return 0; if (!ISSET(rdmsr(MSR_HWCR), HWCR_TSCFREQSEL)) return 0; /* * In 10h+ CPUs, Core::X86::Msr::PStateDef defines the voltage * and frequency for each core P-state. We want the P0 frequency. * If the En bit isn't set, the register doesn't define a valid * P-state. */ def = rdmsr(MSR_PSTATEDEF(0)); if (!ISSET(def, PSTATEDEF_EN)) return 0; switch (ci->ci_family) { case 0x17: case 0x19: /* * PPR for AMD Family 17h [...]: * Models 01h,08h B2, Rev 3.03, pp. 33, 139-140 * Model 18h B1, Rev 3.16, pp. 36, 143-144 * Model 60h A1, Rev 3.06, pp. 33, 155-157 * Model 71h B0, Rev 3.06, pp. 28, 150-151 * * PPR for AMD Family 19h [...]: * Model 21h B0, Rev 3.05, pp. 33, 166-167 * * OSRR for AMD Family 17h processors, * Models 00h-2Fh, Rev 3.03, pp. 130-131 */ base = 200000000; /* 200.0 MHz */ divisor = (def >> 8) & 0x3f; if (divisor <= 0x07 || divisor >= 0x2d) return 0; /* reserved */ if (divisor >= 0x1b && divisor % 2 == 1) return 0; /* reserved */ multiplier = def & 0xff; if (multiplier <= 0x0f) return 0; /* reserved */ break; default: return 0; } return base * multiplier / divisor; } void tsc_identify(struct cpu_info *ci) { if (!(ci->ci_flags & CPUF_PRIMARY) || !(ci->ci_flags & CPUF_CONST_TSC) || !(ci->ci_flags & CPUF_INVAR_TSC)) return; /* Prefer RDTSCP where supported. */ if (ISSET(ci->ci_feature_eflags, CPUID_RDTSCP)) { tsc_rdtsc = rdtscp; tsc_timecounter.tc_get_timecount = tsc_get_timecount_rdtscp; tsc_timecounter.tc_user = TC_TSC_RDTSCP; } tsc_is_invariant = 1; tsc_frequency = tsc_freq_cpuid(ci); if (tsc_frequency == 0) tsc_frequency = tsc_freq_msr(ci); if (tsc_frequency > 0) delay_init(tsc_delay, 5000); } static inline int get_tsc_and_timecount(struct timecounter *tc, uint64_t *tsc, uint64_t *count) { uint64_t n, tsc1, tsc2; int i; for (i = 0; i < RECALIBRATE_MAX_RETRIES; i++) { tsc1 = tsc_rdtsc(); n = (tc->tc_get_timecount(tc) & tc->tc_counter_mask); tsc2 = tsc_rdtsc(); if ((tsc2 - tsc1) < RECALIBRATE_SMI_THRESHOLD) { *count = n; *tsc = tsc2; return (0); } } return (1); } static inline uint64_t calculate_tsc_freq(uint64_t tsc1, uint64_t tsc2, int usec) { uint64_t delta; delta = (tsc2 - tsc1); return (delta * 1000000 / usec); } static inline uint64_t calculate_tc_delay(struct timecounter *tc, uint64_t count1, uint64_t count2) { uint64_t delta; if (count2 < count1) count2 += tc->tc_counter_mask; delta = (count2 - count1); return (delta * 1000000 / tc->tc_frequency); } uint64_t measure_tsc_freq(struct timecounter *tc) { uint64_t count1, count2, frequency, min_freq, tsc1, tsc2; u_long s; int delay_usec, i, err1, err2, usec, success = 0; /* warmup the timers */ for (i = 0; i < 3; i++) { (void)tc->tc_get_timecount(tc); (void)rdtsc(); } min_freq = ULLONG_MAX; delay_usec = 100000; for (i = 0; i < 3; i++) { s = intr_disable(); err1 = get_tsc_and_timecount(tc, &tsc1, &count1); delay(delay_usec); err2 = get_tsc_and_timecount(tc, &tsc2, &count2); intr_restore(s); if (err1 || err2) continue; usec = calculate_tc_delay(tc, count1, count2); if ((usec < (delay_usec - RECALIBRATE_DELAY_THRESHOLD)) || (usec > (delay_usec + RECALIBRATE_DELAY_THRESHOLD))) continue; frequency = calculate_tsc_freq(tsc1, tsc2, usec); min_freq = MIN(min_freq, frequency); success++; } return (success > 1 ? min_freq : 0); } void calibrate_tsc_freq(void) { struct timecounter *reference = tsc_timecounter.tc_priv; uint64_t freq; if (!reference || !tsc_recalibrate) return; if ((freq = measure_tsc_freq(reference)) == 0) return; tsc_frequency = freq; tsc_timecounter.tc_frequency = freq; if (tsc_is_invariant) tsc_timecounter.tc_quality = 2000; } void cpu_recalibrate_tsc(struct timecounter *tc) { struct timecounter *reference = tsc_timecounter.tc_priv; /* Prevent recalibration with a worse timecounter source */ if (reference && reference->tc_quality > tc->tc_quality) return; tsc_timecounter.tc_priv = tc; calibrate_tsc_freq(); } u_int tsc_get_timecount_lfence(struct timecounter *tc) { return rdtsc_lfence(); } u_int tsc_get_timecount_rdtscp(struct timecounter *tc) { return rdtscp(); } void tsc_timecounter_init(struct cpu_info *ci, uint64_t cpufreq) { if (!(ci->ci_flags & CPUF_PRIMARY) || !(ci->ci_flags & CPUF_CONST_TSC) || !(ci->ci_flags & CPUF_INVAR_TSC)) return; /* Newer CPUs don't require recalibration */ if (tsc_frequency > 0) { tsc_timecounter.tc_frequency = tsc_frequency; tsc_timecounter.tc_quality = 2000; } else { tsc_recalibrate = 1; tsc_frequency = cpufreq; tsc_timecounter.tc_frequency = cpufreq; calibrate_tsc_freq(); } tc_init(&tsc_timecounter); } void tsc_delay(int usecs) { uint64_t interval, start; interval = (uint64_t)usecs * tsc_frequency / 1000000; start = tsc_rdtsc(); while (tsc_rdtsc() - start < interval) CPU_BUSY_CYCLE(); } #ifdef MULTIPROCESSOR /* * Protections for global variables in this code: * * a Modified atomically * b Protected by a barrier * p Only modified by the primary CPU */ #define TSC_TEST_MSECS 1 /* Test round duration */ #define TSC_TEST_ROUNDS 2 /* Number of test rounds */ /* * tsc_test_status.val is isolated to its own cache line to limit * false sharing and reduce the test's margin of error. */ struct tsc_test_status { volatile uint64_t val; /* [a] Latest RDTSC value */ uint64_t pad1[7]; uint64_t lag_count; /* [b] Number of lags seen by CPU */ uint64_t lag_max; /* [b] Biggest lag seen by CPU */ int64_t adj; /* [b] Initial IA32_TSC_ADJUST value */ uint64_t pad2[5]; } __aligned(64); struct tsc_test_status tsc_ap_status; /* Test results from AP */ struct tsc_test_status tsc_bp_status; /* Test results from BP */ uint64_t tsc_test_cycles; /* [p] TSC cycles per test round */ const char *tsc_ap_name; /* [b] Name of AP running test */ volatile u_int tsc_egress_barrier; /* [a] Test end barrier */ volatile u_int tsc_ingress_barrier; /* [a] Test start barrier */ volatile u_int tsc_test_rounds; /* [p] Remaining test rounds */ int tsc_is_synchronized = 1; /* [p] Have we ever failed the test? */ void tsc_adjust_reset(struct cpu_info *, struct tsc_test_status *); void tsc_report_test_results(void); void tsc_test_ap(void); void tsc_test_bp(void); void tsc_test_sync_bp(struct cpu_info *ci) { if (!tsc_is_invariant) return; #ifndef TSC_DEBUG /* No point in testing again if we already failed. */ if (!tsc_is_synchronized) return; #endif /* Reset IA32_TSC_ADJUST if it exists. */ tsc_adjust_reset(ci, &tsc_bp_status); /* Reset the test cycle limit and round count. */ tsc_test_cycles = TSC_TEST_MSECS * tsc_frequency / 1000; tsc_test_rounds = TSC_TEST_ROUNDS; do { /* * Pass through the ingress barrier, run the test, * then wait for the AP to reach the egress barrier. */ atomic_inc_int(&tsc_ingress_barrier); while (tsc_ingress_barrier != 2) CPU_BUSY_CYCLE(); tsc_test_bp(); while (tsc_egress_barrier != 1) CPU_BUSY_CYCLE(); /* * Report what happened. Adjust the TSC's quality * if this is the first time we've failed the test. */ tsc_report_test_results(); if (tsc_ap_status.lag_count || tsc_bp_status.lag_count) { if (tsc_is_synchronized) { tsc_is_synchronized = 0; tc_reset_quality(&tsc_timecounter, -1000); } tsc_test_rounds = 0; } else tsc_test_rounds--; /* * Clean up for the next round. It is safe to reset the * ingress barrier because at this point we know the AP * has reached the egress barrier. */ memset(&tsc_ap_status, 0, sizeof tsc_ap_status); memset(&tsc_bp_status, 0, sizeof tsc_bp_status); tsc_ingress_barrier = 0; if (tsc_test_rounds == 0) tsc_ap_name = NULL; /* * Pass through the egress barrier and release the AP. * The AP is responsible for resetting the egress barrier. */ if (atomic_inc_int_nv(&tsc_egress_barrier) != 2) panic("%s: unexpected egress count", __func__); } while (tsc_test_rounds > 0); } void tsc_test_sync_ap(struct cpu_info *ci) { if (!tsc_is_invariant) return; #ifndef TSC_DEBUG if (!tsc_is_synchronized) return; #endif /* The BP needs our name in order to report any problems. */ if (atomic_cas_ptr(&tsc_ap_name, NULL, ci->ci_dev->dv_xname) != NULL) { panic("%s: %s: tsc_ap_name is not NULL: %s", __func__, ci->ci_dev->dv_xname, tsc_ap_name); } tsc_adjust_reset(ci, &tsc_ap_status); /* * The AP is only responsible for running the test and * resetting the egress barrier. The BP handles everything * else. */ do { atomic_inc_int(&tsc_ingress_barrier); while (tsc_ingress_barrier != 2) CPU_BUSY_CYCLE(); tsc_test_ap(); atomic_inc_int(&tsc_egress_barrier); while (atomic_cas_uint(&tsc_egress_barrier, 2, 0) != 2) CPU_BUSY_CYCLE(); } while (tsc_test_rounds > 0); } void tsc_report_test_results(void) { #ifdef TSC_DEBUG u_int round = TSC_TEST_ROUNDS - tsc_test_rounds + 1; if (tsc_bp_status.adj != 0) { printf("tsc: cpu0: IA32_TSC_ADJUST: %lld -> 0\n", tsc_bp_status.adj); } if (tsc_ap_status.adj != 0) { printf("tsc: %s: IA32_TSC_ADJUST: %lld -> 0\n", tsc_ap_name, tsc_ap_status.adj); } if (tsc_ap_status.lag_count > 0 || tsc_bp_status.lag_count > 0) { printf("tsc: cpu0/%s: sync test round %u/%u failed\n", tsc_ap_name, round, TSC_TEST_ROUNDS); } if (tsc_bp_status.lag_count > 0) { printf("tsc: cpu0/%s: cpu0: %llu lags %llu cycles\n", tsc_ap_name, tsc_bp_status.lag_count, tsc_bp_status.lag_max); } if (tsc_ap_status.lag_count > 0) { printf("tsc: cpu0/%s: %s: %llu lags %llu cycles\n", tsc_ap_name, tsc_ap_name, tsc_ap_status.lag_count, tsc_ap_status.lag_max); } #else if (tsc_ap_status.lag_count > 0 || tsc_bp_status.lag_count > 0) printf("tsc: cpu0/%s: sync test failed\n", tsc_ap_name); #endif /* TSC_DEBUG */ } /* * Reset IA32_TSC_ADJUST if we have it. */ void tsc_adjust_reset(struct cpu_info *ci, struct tsc_test_status *tts) { if (ISSET(ci->ci_feature_sefflags_ebx, SEFF0EBX_TSC_ADJUST)) { tts->adj = rdmsr(MSR_TSC_ADJUST); if (tts->adj != 0) wrmsr(MSR_TSC_ADJUST, 0); } } void tsc_test_ap(void) { uint64_t ap_val, bp_val, end, lag; ap_val = tsc_rdtsc(); end = ap_val + tsc_test_cycles; while (__predict_true(ap_val < end)) { /* * Get the BP's latest TSC value, then read the AP's * TSC. LFENCE is a serializing instruction, so we * know bp_val predates ap_val. If ap_val is smaller * than bp_val then the AP's TSC must trail that of * the BP and the counters cannot be synchronized. */ bp_val = tsc_bp_status.val; ap_val = tsc_rdtsc(); tsc_ap_status.val = ap_val; /* * Record the magnitude of the problem if the AP's TSC * trails the BP's TSC. */ if (__predict_false(ap_val < bp_val)) { tsc_ap_status.lag_count++; lag = bp_val - ap_val; if (tsc_ap_status.lag_max < lag) tsc_ap_status.lag_max = lag; } } } /* * This is similar to tsc_test_ap(), but with all relevant variables * flipped around to run the test from the BP's perspective. */ void tsc_test_bp(void) { uint64_t ap_val, bp_val, end, lag; bp_val = tsc_rdtsc(); end = bp_val + tsc_test_cycles; while (__predict_true(bp_val < end)) { ap_val = tsc_ap_status.val; bp_val = tsc_rdtsc(); tsc_bp_status.val = bp_val; if (__predict_false(bp_val < ap_val)) { tsc_bp_status.lag_count++; lag = ap_val - bp_val; if (tsc_bp_status.lag_max < lag) tsc_bp_status.lag_max = lag; } } } #endif /* MULTIPROCESSOR */
127 105 151 2 149 11 11 11 150 150 151 151 11 20 11 300 300 12 12 159 159 158 159 139 139 139 2 20 156 104 159 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 /* $OpenBSD: uvm_addr.c,v 1.34 2024/05/13 01:15:53 jsg Exp $ */ /* * Copyright (c) 2011 Ariane van der Steldt <ariane@stack.nl> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* #define DEBUG */ #include <sys/param.h> #include <sys/systm.h> #include <uvm/uvm.h> #include <uvm/uvm_addr.h> #include <sys/pool.h> /* Max gap between hint allocations. */ #define UADDR_HINT_MAXGAP (4 * PAGE_SIZE) /* Number of pivots in pivot allocator. */ #define NUM_PIVOTS 16 /* * Max number (inclusive) of pages the pivot allocator * will place between allocations. * * The uaddr_pivot_random() function attempts to bias towards * small space between allocations, so putting a large number here is fine. */ #define PIVOT_RND 8 /* * Number of allocations that a pivot can supply before expiring. * When a pivot expires, a new pivot has to be found. * * Must be at least 1. */ #define PIVOT_EXPIRE 1024 /* Pool with uvm_addr_state structures. */ struct pool uaddr_pool; struct pool uaddr_bestfit_pool; struct pool uaddr_pivot_pool; struct pool uaddr_rnd_pool; /* uvm_addr state for bestfit selector. */ struct uaddr_bestfit_state { struct uvm_addr_state ubf_uaddr; struct uaddr_free_rbtree ubf_free; }; /* uvm_addr state for rnd selector. */ struct uaddr_rnd_state { struct uvm_addr_state ur_uaddr; #if 0 TAILQ_HEAD(, vm_map_entry) ur_free; #endif }; /* * Definition of a pivot in pivot selector. */ struct uaddr_pivot { vaddr_t addr; /* End of prev. allocation. */ int expire;/* Best before date. */ int dir; /* Direction. */ struct vm_map_entry *entry; /* Will contain next alloc. */ }; /* uvm_addr state for pivot selector. */ struct uaddr_pivot_state { struct uvm_addr_state up_uaddr; /* Free space tree, for fast pivot selection. */ struct uaddr_free_rbtree up_free; /* List of pivots. The pointers point to after the last allocation. */ struct uaddr_pivot up_pivots[NUM_PIVOTS]; }; /* Forward declaration (see below). */ extern const struct uvm_addr_functions uaddr_kernel_functions; struct uvm_addr_state uaddr_kbootstrap; /* * Support functions. */ #ifndef SMALL_KERNEL struct vm_map_entry *uvm_addr_entrybyspace(struct uaddr_free_rbtree*, vsize_t); #endif /* !SMALL_KERNEL */ void uaddr_destroy(struct uvm_addr_state *); void uaddr_kbootstrap_destroy(struct uvm_addr_state *); void uaddr_rnd_destroy(struct uvm_addr_state *); void uaddr_bestfit_destroy(struct uvm_addr_state *); void uaddr_pivot_destroy(struct uvm_addr_state *); #if 0 int uaddr_lin_select(struct vm_map *, struct uvm_addr_state *, struct vm_map_entry **, vaddr_t *, vsize_t, vaddr_t, vaddr_t, vm_prot_t, vaddr_t); #endif int uaddr_kbootstrap_select(struct vm_map *, struct uvm_addr_state *, struct vm_map_entry **, vaddr_t *, vsize_t, vaddr_t, vaddr_t, vm_prot_t, vaddr_t); int uaddr_rnd_select(struct vm_map *, struct uvm_addr_state *, struct vm_map_entry **, vaddr_t *, vsize_t, vaddr_t, vaddr_t, vm_prot_t, vaddr_t); int uaddr_bestfit_select(struct vm_map *, struct uvm_addr_state*, struct vm_map_entry **, vaddr_t *, vsize_t, vaddr_t, vaddr_t, vm_prot_t, vaddr_t); #ifndef SMALL_KERNEL int uaddr_pivot_select(struct vm_map *, struct uvm_addr_state *, struct vm_map_entry **, vaddr_t *, vsize_t, vaddr_t, vaddr_t, vm_prot_t, vaddr_t); int uaddr_stack_brk_select(struct vm_map *, struct uvm_addr_state *, struct vm_map_entry **, vaddr_t *, vsize_t, vaddr_t, vaddr_t, vm_prot_t, vaddr_t); #endif /* !SMALL_KERNEL */ void uaddr_rnd_insert(struct vm_map *, struct uvm_addr_state *, struct vm_map_entry *); void uaddr_rnd_remove(struct vm_map *, struct uvm_addr_state *, struct vm_map_entry *); void uaddr_bestfit_insert(struct vm_map *, struct uvm_addr_state *, struct vm_map_entry *); void uaddr_bestfit_remove(struct vm_map *, struct uvm_addr_state *, struct vm_map_entry *); void uaddr_pivot_insert(struct vm_map *, struct uvm_addr_state *, struct vm_map_entry *); void uaddr_pivot_remove(struct vm_map *, struct uvm_addr_state *, struct vm_map_entry *); #ifndef SMALL_KERNEL vsize_t uaddr_pivot_random(void); int uaddr_pivot_newpivot(struct vm_map *, struct uaddr_pivot_state *, struct uaddr_pivot *, struct vm_map_entry **, vaddr_t *, vsize_t, vaddr_t, vaddr_t, vsize_t, vsize_t); #endif /* !SMALL_KERNEL */ #if defined(DEBUG) || defined(DDB) void uaddr_pivot_print(struct uvm_addr_state *, boolean_t, int (*)(const char *, ...)); #if 0 void uaddr_rnd_print(struct uvm_addr_state *, boolean_t, int (*)(const char *, ...)); #endif #endif /* DEBUG || DDB */ #ifndef SMALL_KERNEL /* * Find smallest entry in tree that will fit sz bytes. */ struct vm_map_entry * uvm_addr_entrybyspace(struct uaddr_free_rbtree *free, vsize_t sz) { struct vm_map_entry *tmp, *res; tmp = RBT_ROOT(uaddr_free_rbtree, free); res = NULL; while (tmp) { if (tmp->fspace >= sz) { res = tmp; tmp = RBT_LEFT(uaddr_free_rbtree, tmp); } else if (tmp->fspace < sz) tmp = RBT_RIGHT(uaddr_free_rbtree, tmp); } return res; } #endif /* !SMALL_KERNEL */ static inline vaddr_t uvm_addr_align_forward(vaddr_t addr, vaddr_t align, vaddr_t offset) { vaddr_t adjusted; KASSERT(offset < align || (align == 0 && offset == 0)); KASSERT((align & (align - 1)) == 0); KASSERT((offset & PAGE_MASK) == 0); align = MAX(align, PAGE_SIZE); adjusted = addr & ~(align - 1); adjusted += offset; return (adjusted < addr ? adjusted + align : adjusted); } static inline vaddr_t uvm_addr_align_backward(vaddr_t addr, vaddr_t align, vaddr_t offset) { vaddr_t adjusted; KASSERT(offset < align || (align == 0 && offset == 0)); KASSERT((align & (align - 1)) == 0); KASSERT((offset & PAGE_MASK) == 0); align = MAX(align, PAGE_SIZE); adjusted = addr & ~(align - 1); adjusted += offset; return (adjusted > addr ? adjusted - align : adjusted); } /* * Try to fit the requested space into the entry. */ int uvm_addr_fitspace(vaddr_t *min_result, vaddr_t *max_result, vaddr_t low_addr, vaddr_t high_addr, vsize_t sz, vaddr_t align, vaddr_t offset, vsize_t before_gap, vsize_t after_gap) { vaddr_t tmp; vsize_t fspace; if (low_addr > high_addr) return ENOMEM; fspace = high_addr - low_addr; if (fspace < before_gap + after_gap) return ENOMEM; if (fspace - before_gap - after_gap < sz) return ENOMEM; /* * Calculate lowest address. */ low_addr += before_gap; low_addr = uvm_addr_align_forward(tmp = low_addr, align, offset); if (low_addr < tmp) /* Overflow during alignment. */ return ENOMEM; if (high_addr - after_gap - sz < low_addr) return ENOMEM; /* * Calculate highest address. */ high_addr -= after_gap + sz; high_addr = uvm_addr_align_backward(tmp = high_addr, align, offset); if (high_addr > tmp) /* Overflow during alignment. */ return ENOMEM; if (low_addr > high_addr) return ENOMEM; *min_result = low_addr; *max_result = high_addr; return 0; } /* * Initialize uvm_addr. */ void uvm_addr_init(void) { pool_init(&uaddr_pool, sizeof(struct uvm_addr_state), 0, IPL_VM, PR_WAITOK, "uaddr", NULL); pool_init(&uaddr_bestfit_pool, sizeof(struct uaddr_bestfit_state), 0, IPL_VM, PR_WAITOK, "uaddrbest", NULL); pool_init(&uaddr_pivot_pool, sizeof(struct uaddr_pivot_state), 0, IPL_VM, PR_WAITOK, "uaddrpivot", NULL); pool_init(&uaddr_rnd_pool, sizeof(struct uaddr_rnd_state), 0, IPL_VM, PR_WAITOK, "uaddrrnd", NULL); uaddr_kbootstrap.uaddr_minaddr = PAGE_SIZE; uaddr_kbootstrap.uaddr_maxaddr = -(vaddr_t)PAGE_SIZE; uaddr_kbootstrap.uaddr_functions = &uaddr_kernel_functions; } /* * Invoke destructor function of uaddr. */ void uvm_addr_destroy(struct uvm_addr_state *uaddr) { if (uaddr) (*uaddr->uaddr_functions->uaddr_destroy)(uaddr); } /* * Move address forward to satisfy align, offset. */ vaddr_t uvm_addr_align(vaddr_t addr, vaddr_t align, vaddr_t offset) { vaddr_t result = (addr & ~(align - 1)) + offset; if (result < addr) result += align; return result; } /* * Move address backwards to satisfy align, offset. */ vaddr_t uvm_addr_align_back(vaddr_t addr, vaddr_t align, vaddr_t offset) { vaddr_t result = (addr & ~(align - 1)) + offset; if (result > addr) result -= align; return result; } /* * Directional first fit. * * Do a linear search for free space, starting at addr in entry. * direction == 1: search forward * direction == -1: search backward * * Output: low <= addr <= high and entry will contain addr. * 0 will be returned if no space is available. * * gap describes the space that must appear between the preceding entry. */ int uvm_addr_linsearch(struct vm_map *map, struct uvm_addr_state *uaddr, struct vm_map_entry **entry_out, vaddr_t *addr_out, vaddr_t hint, vsize_t sz, vaddr_t align, vaddr_t offset, int direction, vaddr_t low, vaddr_t high, vsize_t before_gap, vsize_t after_gap) { struct vm_map_entry *entry; vaddr_t low_addr, high_addr; KASSERT(entry_out != NULL && addr_out != NULL); KASSERT(direction == -1 || direction == 1); KASSERT((hint & PAGE_MASK) == 0 && (high & PAGE_MASK) == 0 && (low & PAGE_MASK) == 0 && (before_gap & PAGE_MASK) == 0 && (after_gap & PAGE_MASK) == 0); KASSERT(high + sz > high); /* Check for overflow. */ /* * Hint magic. */ if (hint == 0) hint = (direction == 1 ? low : high); else if (hint > high) { if (direction != -1) return ENOMEM; hint = high; } else if (hint < low) { if (direction != 1) return ENOMEM; hint = low; } for (entry = uvm_map_entrybyaddr(&map->addr, hint - (direction == -1 ? 1 : 0)); entry != NULL; entry = (direction == 1 ? RBT_NEXT(uvm_map_addr, entry) : RBT_PREV(uvm_map_addr, entry))) { if ((direction == 1 && VMMAP_FREE_START(entry) > high) || (direction == -1 && VMMAP_FREE_END(entry) < low)) { break; } if (uvm_addr_fitspace(&low_addr, &high_addr, MAX(low, VMMAP_FREE_START(entry)), MIN(high, VMMAP_FREE_END(entry)), sz, align, offset, before_gap, after_gap) == 0) { *entry_out = entry; if (hint >= low_addr && hint <= high_addr) { *addr_out = hint; } else { *addr_out = (direction == 1 ? low_addr : high_addr); } return 0; } } return ENOMEM; } /* * Invoke address selector of uaddr. * uaddr may be NULL, in which case the algorithm will fail with ENOMEM. * * Will invoke uvm_addr_isavail to fill in last_out. */ int uvm_addr_invoke(struct vm_map *map, struct uvm_addr_state *uaddr, struct vm_map_entry **entry_out, struct vm_map_entry **last_out, vaddr_t *addr_out, vsize_t sz, vaddr_t align, vaddr_t offset, vm_prot_t prot, vaddr_t hint) { int error; if (uaddr == NULL) return ENOMEM; hint &= ~((vaddr_t)PAGE_MASK); if (hint != 0 && !(hint >= uaddr->uaddr_minaddr && hint < uaddr->uaddr_maxaddr)) return ENOMEM; vm_map_assert_anylock(map); error = (*uaddr->uaddr_functions->uaddr_select)(map, uaddr, entry_out, addr_out, sz, align, offset, prot, hint); if (error == 0) { KASSERT(*entry_out != NULL); *last_out = NULL; if (!uvm_map_isavail(map, uaddr, entry_out, last_out, *addr_out, sz)) { panic("uvm_addr_invoke: address selector %p " "(%s 0x%lx-0x%lx) " "returned unavailable address 0x%lx sz 0x%lx", uaddr, uaddr->uaddr_functions->uaddr_name, uaddr->uaddr_minaddr, uaddr->uaddr_maxaddr, *addr_out, sz); } } return error; } #if defined(DEBUG) || defined(DDB) void uvm_addr_print(struct uvm_addr_state *uaddr, const char *slot, boolean_t full, int (*pr)(const char *, ...)) { if (uaddr == NULL) { (*pr)("- uvm_addr %s: NULL\n", slot); return; } (*pr)("- uvm_addr %s: %p (%s 0x%lx-0x%lx)\n", slot, uaddr, uaddr->uaddr_functions->uaddr_name, uaddr->uaddr_minaddr, uaddr->uaddr_maxaddr); if (uaddr->uaddr_functions->uaddr_print == NULL) return; (*uaddr->uaddr_functions->uaddr_print)(uaddr, full, pr); } #endif /* DEBUG || DDB */ /* * Destroy a uvm_addr_state structure. * The uaddr must have been previously allocated from uaddr_state_pool. */ void uaddr_destroy(struct uvm_addr_state *uaddr) { pool_put(&uaddr_pool, uaddr); } #if 0 /* * Linear allocator. * This allocator uses a first-fit algorithm. * * If hint is set, search will start at the hint position. * Only searches forward. */ const struct uvm_addr_functions uaddr_lin_functions = { .uaddr_select = &uaddr_lin_select, .uaddr_destroy = &uaddr_destroy, .uaddr_name = "uaddr_lin" }; struct uvm_addr_state * uaddr_lin_create(vaddr_t minaddr, vaddr_t maxaddr) { struct uvm_addr_state *uaddr; uaddr = pool_get(&uaddr_pool, PR_WAITOK); uaddr->uaddr_minaddr = minaddr; uaddr->uaddr_maxaddr = maxaddr; uaddr->uaddr_functions = &uaddr_lin_functions; return uaddr; } int uaddr_lin_select(struct vm_map *map, struct uvm_addr_state *uaddr, struct vm_map_entry **entry_out, vaddr_t *addr_out, vsize_t sz, vaddr_t align, vaddr_t offset, vm_prot_t prot, vaddr_t hint) { vaddr_t guard_sz; /* * Deal with guardpages: search for space with one extra page. */ guard_sz = ((map->flags & VM_MAP_GUARDPAGES) == 0 ? 0 : PAGE_SIZE); if (uaddr->uaddr_maxaddr - uaddr->uaddr_minaddr - guard_sz < sz) return ENOMEM; return uvm_addr_linsearch(map, uaddr, entry_out, addr_out, 0, sz, align, offset, 1, uaddr->uaddr_minaddr, uaddr->uaddr_maxaddr - sz, 0, guard_sz); } #endif /* * Randomized allocator. * This allocator use uvm_map_hint to acquire a random address and searches * from there. */ const struct uvm_addr_functions uaddr_rnd_functions = { .uaddr_select = &uaddr_rnd_select, .uaddr_free_insert = &uaddr_rnd_insert, .uaddr_free_remove = &uaddr_rnd_remove, .uaddr_destroy = &uaddr_rnd_destroy, #if defined(DEBUG) || defined(DDB) #if 0 .uaddr_print = &uaddr_rnd_print, #endif #endif /* DEBUG || DDB */ .uaddr_name = "uaddr_rnd" }; struct uvm_addr_state * uaddr_rnd_create(vaddr_t minaddr, vaddr_t maxaddr) { struct uaddr_rnd_state *uaddr; uaddr = pool_get(&uaddr_rnd_pool, PR_WAITOK); uaddr->ur_uaddr.uaddr_minaddr = minaddr; uaddr->ur_uaddr.uaddr_maxaddr = maxaddr; uaddr->ur_uaddr.uaddr_functions = &uaddr_rnd_functions; #if 0 TAILQ_INIT(&uaddr->ur_free); #endif return &uaddr->ur_uaddr; } int uaddr_rnd_select(struct vm_map *map, struct uvm_addr_state *uaddr, struct vm_map_entry **entry_out, vaddr_t *addr_out, vsize_t sz, vaddr_t align, vaddr_t offset, vm_prot_t prot, vaddr_t hint) { struct vmspace *vm; vaddr_t minaddr, maxaddr; vaddr_t guard_sz; vaddr_t low_addr, high_addr; struct vm_map_entry *entry, *next; vsize_t before_gap, after_gap; vaddr_t tmp; KASSERT((map->flags & VM_MAP_ISVMSPACE) != 0); vm = (struct vmspace *)map; /* Deal with guardpages: search for space with one extra page. */ guard_sz = ((map->flags & VM_MAP_GUARDPAGES) == 0 ? 0 : PAGE_SIZE); if (uaddr->uaddr_maxaddr - guard_sz < sz) return ENOMEM; minaddr = uvm_addr_align_forward(uaddr->uaddr_minaddr, align, offset); maxaddr = uvm_addr_align_backward(uaddr->uaddr_maxaddr - sz - guard_sz, align, offset); /* Quick fail if the allocation won't fit. */ if (minaddr >= maxaddr) return ENOMEM; /* Select a hint. */ if (hint == 0) hint = uvm_map_hint(vm, prot, minaddr, maxaddr); /* Clamp hint to uaddr range. */ hint = MIN(MAX(hint, minaddr), maxaddr); /* Align hint to align,offset parameters. */ tmp = hint; hint = uvm_addr_align_forward(tmp, align, offset); /* Check for overflow during alignment. */ if (hint < tmp || hint > maxaddr) return ENOMEM; /* Compatibility mode: never look backwards. */ before_gap = 0; after_gap = guard_sz; hint -= MIN(hint, before_gap); /* * Use the augmented address tree to look up the first entry * at or after hint with sufficient space. * * This code is the original optimized code, but will fail if the * subtree it looks at does have sufficient space, but fails to meet * the align constraint. * * Guard: subtree is not exhausted and max(fspace) >= required. */ entry = uvm_map_entrybyaddr(&map->addr, hint); /* Walk up the tree, until there is at least sufficient space. */ while (entry != NULL && entry->fspace_augment < before_gap + after_gap + sz) entry = RBT_PARENT(uvm_map_addr, entry); while (entry != NULL) { /* Test if this fits. */ if (VMMAP_FREE_END(entry) > hint && uvm_map_uaddr_e(map, entry) == uaddr && uvm_addr_fitspace(&low_addr, &high_addr, MAX(uaddr->uaddr_minaddr, VMMAP_FREE_START(entry)), MIN(uaddr->uaddr_maxaddr, VMMAP_FREE_END(entry)), sz, align, offset, before_gap, after_gap) == 0) { *entry_out = entry; if (hint >= low_addr && hint <= high_addr) *addr_out = hint; else *addr_out = low_addr; return 0; } /* RBT_NEXT, but skip subtrees that cannot possible fit. */ next = RBT_RIGHT(uvm_map_addr, entry); if (next != NULL && next->fspace_augment >= before_gap + after_gap + sz) { entry = next; while ((next = RBT_LEFT(uvm_map_addr, entry)) != NULL) entry = next; } else { do_parent: next = RBT_PARENT(uvm_map_addr, entry); if (next == NULL) entry = NULL; else if (RBT_LEFT(uvm_map_addr, next) == entry) entry = next; else { entry = next; goto do_parent; } } } /* Lookup failed. */ return ENOMEM; } /* * Destroy a uaddr_rnd_state structure. */ void uaddr_rnd_destroy(struct uvm_addr_state *uaddr) { pool_put(&uaddr_rnd_pool, uaddr); } /* * Add entry to tailq. */ void uaddr_rnd_insert(struct vm_map *map, struct uvm_addr_state *uaddr_p, struct vm_map_entry *entry) { return; } /* * Remove entry from tailq. */ void uaddr_rnd_remove(struct vm_map *map, struct uvm_addr_state *uaddr_p, struct vm_map_entry *entry) { return; } #if 0 #if defined(DEBUG) || defined(DDB) void uaddr_rnd_print(struct uvm_addr_state *uaddr_p, boolean_t full, int (*pr)(const char*, ...)) { struct vm_map_entry *entry; struct uaddr_rnd_state *uaddr; vaddr_t addr; size_t count; vsize_t space; uaddr = (struct uaddr_rnd_state *)uaddr_p; addr = 0; count = 0; space = 0; TAILQ_FOREACH(entry, &uaddr->ur_free, dfree.tailq) { count++; space += entry->fspace; if (full) { (*pr)("\tentry %p: 0x%lx-0x%lx G=0x%lx F=0x%lx\n", entry, entry->start, entry->end, entry->guard, entry->fspace); (*pr)("\t\tfree: 0x%lx-0x%lx\n", VMMAP_FREE_START(entry), VMMAP_FREE_END(entry)); } if (entry->start < addr) { if (!full) (*pr)("\tentry %p: 0x%lx-0x%lx " "G=0x%lx F=0x%lx\n", entry, entry->start, entry->end, entry->guard, entry->fspace); (*pr)("\t\tstart=0x%lx, expected at least 0x%lx\n", entry->start, addr); } addr = VMMAP_FREE_END(entry); } (*pr)("\t0x%lu entries, 0x%lx free bytes\n", count, space); } #endif /* DEBUG || DDB */ #endif /* * Kernel allocation bootstrap logic. */ const struct uvm_addr_functions uaddr_kernel_functions = { .uaddr_select = &uaddr_kbootstrap_select, .uaddr_destroy = &uaddr_kbootstrap_destroy, .uaddr_name = "uaddr_kbootstrap" }; /* * Select an address from the map. * * This function ignores the uaddr spec and instead uses the map directly. * Because of that property, the uaddr algorithm can be shared across all * kernel maps. */ int uaddr_kbootstrap_select(struct vm_map *map, struct uvm_addr_state *uaddr, struct vm_map_entry **entry_out, vaddr_t *addr_out, vsize_t sz, vaddr_t align, vaddr_t offset, vm_prot_t prot, vaddr_t hint) { vaddr_t tmp; RBT_FOREACH(*entry_out, uvm_map_addr, &map->addr) { if (VMMAP_FREE_END(*entry_out) <= uvm_maxkaddr && uvm_addr_fitspace(addr_out, &tmp, VMMAP_FREE_START(*entry_out), VMMAP_FREE_END(*entry_out), sz, align, offset, 0, 0) == 0) return 0; } return ENOMEM; } /* * Don't destroy the kernel bootstrap allocator. */ void uaddr_kbootstrap_destroy(struct uvm_addr_state *uaddr) { KASSERT(uaddr == (struct uvm_addr_state *)&uaddr_kbootstrap); } #ifndef SMALL_KERNEL /* * Best fit algorithm. */ const struct uvm_addr_functions uaddr_bestfit_functions = { .uaddr_select = &uaddr_bestfit_select, .uaddr_free_insert = &uaddr_bestfit_insert, .uaddr_free_remove = &uaddr_bestfit_remove, .uaddr_destroy = &uaddr_bestfit_destroy, .uaddr_name = "uaddr_bestfit" }; struct uvm_addr_state * uaddr_bestfit_create(vaddr_t minaddr, vaddr_t maxaddr) { struct uaddr_bestfit_state *uaddr; uaddr = pool_get(&uaddr_bestfit_pool, PR_WAITOK); uaddr->ubf_uaddr.uaddr_minaddr = minaddr; uaddr->ubf_uaddr.uaddr_maxaddr = maxaddr; uaddr->ubf_uaddr.uaddr_functions = &uaddr_bestfit_functions; RBT_INIT(uaddr_free_rbtree, &uaddr->ubf_free); return &uaddr->ubf_uaddr; } void uaddr_bestfit_destroy(struct uvm_addr_state *uaddr) { pool_put(&uaddr_bestfit_pool, uaddr); } void uaddr_bestfit_insert(struct vm_map *map, struct uvm_addr_state *uaddr_p, struct vm_map_entry *entry) { struct uaddr_bestfit_state *uaddr; struct vm_map_entry *rb_rv; uaddr = (struct uaddr_bestfit_state *)uaddr_p; if ((rb_rv = RBT_INSERT(uaddr_free_rbtree, &uaddr->ubf_free, entry)) != NULL) { panic("%s: duplicate insertion: state %p " "inserting %p, colliding with %p", __func__, uaddr, entry, rb_rv); } } void uaddr_bestfit_remove(struct vm_map *map, struct uvm_addr_state *uaddr_p, struct vm_map_entry *entry) { struct uaddr_bestfit_state *uaddr; uaddr = (struct uaddr_bestfit_state *)uaddr_p; if (RBT_REMOVE(uaddr_free_rbtree, &uaddr->ubf_free, entry) != entry) panic("%s: entry was not in tree", __func__); } int uaddr_bestfit_select(struct vm_map *map, struct uvm_addr_state *uaddr_p, struct vm_map_entry **entry_out, vaddr_t *addr_out, vsize_t sz, vaddr_t align, vaddr_t offset, vm_prot_t prot, vaddr_t hint) { vaddr_t min, max; struct uaddr_bestfit_state *uaddr; struct vm_map_entry *entry; vsize_t guardsz; uaddr = (struct uaddr_bestfit_state *)uaddr_p; guardsz = ((map->flags & VM_MAP_GUARDPAGES) ? PAGE_SIZE : 0); if (sz + guardsz < sz) return ENOMEM; /* * Find smallest item on freelist capable of holding item. * Deal with guardpages: search for space with one extra page. */ entry = uvm_addr_entrybyspace(&uaddr->ubf_free, sz + guardsz); if (entry == NULL) return ENOMEM; /* * Walk the tree until we find an entry that fits. */ while (uvm_addr_fitspace(&min, &max, VMMAP_FREE_START(entry), VMMAP_FREE_END(entry), sz, align, offset, 0, guardsz) != 0) { entry = RBT_NEXT(uaddr_free_rbtree, entry); if (entry == NULL) return ENOMEM; } /* * Return the address that generates the least fragmentation. */ *entry_out = entry; *addr_out = (min - VMMAP_FREE_START(entry) <= VMMAP_FREE_END(entry) - guardsz - sz - max ? min : max); return 0; } #endif /* !SMALL_KERNEL */ #ifndef SMALL_KERNEL /* * A userspace allocator based on pivots. */ const struct uvm_addr_functions uaddr_pivot_functions = { .uaddr_select = &uaddr_pivot_select, .uaddr_free_insert = &uaddr_pivot_insert, .uaddr_free_remove = &uaddr_pivot_remove, .uaddr_destroy = &uaddr_pivot_destroy, #if defined(DEBUG) || defined(DDB) .uaddr_print = &uaddr_pivot_print, #endif /* DEBUG || DDB */ .uaddr_name = "uaddr_pivot" }; /* * A special random function for pivots. * * This function will return: * - a random number * - a multiple of PAGE_SIZE * - at least PAGE_SIZE * * The random function has a slightly higher change to return a small number. */ vsize_t uaddr_pivot_random(void) { int r; /* * The sum of two six-sided dice will have a normal distribution. * We map the highest probable number to 1, by folding the curve * (think of a graph on a piece of paper, that you fold). * * Because the fold happens at PIVOT_RND - 1, the numbers 0 and 1 * have the same and highest probability of happening. */ r = arc4random_uniform(PIVOT_RND) + arc4random_uniform(PIVOT_RND) - (PIVOT_RND - 1); if (r < 0) r = -r; /* * Make the returned value at least PAGE_SIZE and a multiple of * PAGE_SIZE. */ return (vaddr_t)(1 + r) << PAGE_SHIFT; } /* * Select a new pivot. * * A pivot must: * - be chosen random * - have a randomly chosen gap before it, where the uaddr_state starts * - have a randomly chosen gap after it, before the uaddr_state ends * * Furthermore, the pivot must provide sufficient space for the allocation. * The addr will be set to the selected address. * * Returns ENOMEM on failure. */ int uaddr_pivot_newpivot(struct vm_map *map, struct uaddr_pivot_state *uaddr, struct uaddr_pivot *pivot, struct vm_map_entry **entry_out, vaddr_t *addr_out, vsize_t sz, vaddr_t align, vaddr_t offset, vsize_t before_gap, vsize_t after_gap) { struct vm_map_entry *entry, *found; vaddr_t minaddr, maxaddr; vsize_t dist; vaddr_t found_minaddr, found_maxaddr; vaddr_t min, max; vsize_t arc4_arg; int fit_error; u_int32_t path; minaddr = uaddr->up_uaddr.uaddr_minaddr; maxaddr = uaddr->up_uaddr.uaddr_maxaddr; KASSERT(minaddr < maxaddr); #ifdef DIAGNOSTIC if (minaddr + 2 * PAGE_SIZE > maxaddr) { panic("uaddr_pivot_newpivot: cannot grant random pivot " "in area less than 2 pages (size = 0x%lx)", maxaddr - minaddr); } #endif /* DIAGNOSTIC */ /* * Gap calculation: 1/32 of the size of the managed area. * * At most: sufficient to not get truncated at arc4random. * At least: 2 PAGE_SIZE * * minaddr and maxaddr will be changed according to arc4random. */ dist = MAX((maxaddr - minaddr) / 32, 2 * (vaddr_t)PAGE_SIZE); if (dist >> PAGE_SHIFT > 0xffffffff) { minaddr += (vsize_t)arc4random() << PAGE_SHIFT; maxaddr -= (vsize_t)arc4random() << PAGE_SHIFT; } else { minaddr += (vsize_t)arc4random_uniform(dist >> PAGE_SHIFT) << PAGE_SHIFT; maxaddr -= (vsize_t)arc4random_uniform(dist >> PAGE_SHIFT) << PAGE_SHIFT; } /* * A very fast way to find an entry that will be large enough * to hold the allocation, but still is found more or less * randomly: the tree path selector has a 50% chance to go for * a bigger or smaller entry. * * Note that the memory may actually be available, * but the fragmentation may be so bad and the gaps chosen * so unfortunately, that the allocation will not succeed. * Or the alignment can only be satisfied by an entry that * is not visited in the randomly selected path. * * This code finds an entry with sufficient space in O(log n) time. */ path = arc4random(); found = NULL; entry = RBT_ROOT(uaddr_free_rbtree, &uaddr->up_free); while (entry != NULL) { fit_error = uvm_addr_fitspace(&min, &max, MAX(VMMAP_FREE_START(entry), minaddr), MIN(VMMAP_FREE_END(entry), maxaddr), sz, align, offset, before_gap, after_gap); /* It fits, save this entry. */ if (fit_error == 0) { found = entry; found_minaddr = min; found_maxaddr = max; } /* Next. */ if (fit_error != 0) entry = RBT_RIGHT(uaddr_free_rbtree, entry); else if ((path & 0x1) == 0) { path >>= 1; entry = RBT_RIGHT(uaddr_free_rbtree, entry); } else { path >>= 1; entry = RBT_LEFT(uaddr_free_rbtree, entry); } } if (found == NULL) return ENOMEM; /* Not found a large enough region. */ /* * Calculate a random address within found. * * found_minaddr and found_maxaddr are already aligned, so be sure * to select a multiple of align as the offset in the entry. * Preferably, arc4random_uniform is used to provide no bias within * the entry. * However if the size of the entry exceeds arc4random_uniforms * argument limit, we simply use arc4random (thus limiting ourselves * to 4G * PAGE_SIZE bytes offset). */ if (found_maxaddr == found_minaddr) *addr_out = found_minaddr; else { KASSERT(align >= PAGE_SIZE && (align & (align - 1)) == 0); arc4_arg = found_maxaddr - found_minaddr; if (arc4_arg > 0xffffffff) { *addr_out = found_minaddr + (arc4random() & ~(align - 1)); } else { *addr_out = found_minaddr + (arc4random_uniform(arc4_arg) & ~(align - 1)); } } /* Address was found in this entry. */ *entry_out = found; /* * Set up new pivot and return selected address. * * Depending on the direction of the pivot, the pivot must be placed * at the bottom or the top of the allocation: * - if the pivot moves upwards, place the pivot at the top of the * allocation, * - if the pivot moves downwards, place the pivot at the bottom * of the allocation. */ pivot->entry = found; pivot->dir = (arc4random() & 0x1 ? 1 : -1); if (pivot->dir > 0) pivot->addr = *addr_out + sz; else pivot->addr = *addr_out; pivot->expire = PIVOT_EXPIRE - 1; /* First use is right now. */ return 0; } /* * Pivot selector. * * Each time the selector is invoked, it will select a random pivot, which * it will use to select memory with. The memory will be placed at the pivot, * with a randomly sized gap between the allocation and the pivot. * The pivot will then move so it will never revisit this address. * * Each allocation, the pivot expiry timer ticks. Once the pivot becomes * expired, it will be replaced with a newly created pivot. Pivots also * automatically expire if they fail to provide memory for an allocation. * * Expired pivots are replaced using the uaddr_pivot_newpivot() function, * which will ensure the pivot points at memory in such a way that the * allocation will succeed. * As an added bonus, the uaddr_pivot_newpivot() function will perform the * allocation immediately and move the pivot as appropriate. * * If uaddr_pivot_newpivot() fails to find a new pivot that will allow the * allocation to succeed, it will not create a new pivot and the allocation * will fail. * * A pivot running into used memory will automatically expire (because it will * fail to allocate). * * Characteristics of the allocator: * - best case, an allocation is O(log N) * (it would be O(1), if it werent for the need to check if the memory is * free; although that can be avoided...) * - worst case, an allocation is O(log N) * (the uaddr_pivot_newpivot() function has that complexity) * - failed allocations always take O(log N) * (the uaddr_pivot_newpivot() function will walk that deep into the tree). */ int uaddr_pivot_select(struct vm_map *map, struct uvm_addr_state *uaddr_p, struct vm_map_entry **entry_out, vaddr_t *addr_out, vsize_t sz, vaddr_t align, vaddr_t offset, vm_prot_t prot, vaddr_t hint) { struct uaddr_pivot_state *uaddr; struct vm_map_entry *entry; struct uaddr_pivot *pivot; vaddr_t min, max; vsize_t before_gap, after_gap; int err; /* * When we have a hint, use the rnd allocator that finds the * area that is closest to the hint, if there is such an area. */ if (hint != 0) { if (uaddr_rnd_select(map, uaddr_p, entry_out, addr_out, sz, align, offset, prot, hint) == 0) return 0; return ENOMEM; } /* * Select a random pivot and a random gap sizes around the allocation. */ uaddr = (struct uaddr_pivot_state *)uaddr_p; pivot = &uaddr->up_pivots[ arc4random_uniform(nitems(uaddr->up_pivots))]; before_gap = uaddr_pivot_random(); after_gap = uaddr_pivot_random(); if (pivot->addr == 0 || pivot->entry == NULL || pivot->expire == 0) goto expired; /* Pivot is invalid (null or expired). */ /* * Attempt to use the pivot to map the entry. */ entry = pivot->entry; if (pivot->dir > 0) { if (uvm_addr_fitspace(&min, &max, MAX(VMMAP_FREE_START(entry), pivot->addr), VMMAP_FREE_END(entry), sz, align, offset, before_gap, after_gap) == 0) { *addr_out = min; *entry_out = entry; pivot->addr = min + sz; pivot->expire--; return 0; } } else { if (uvm_addr_fitspace(&min, &max, VMMAP_FREE_START(entry), MIN(VMMAP_FREE_END(entry), pivot->addr), sz, align, offset, before_gap, after_gap) == 0) { *addr_out = max; *entry_out = entry; pivot->addr = max; pivot->expire--; return 0; } } expired: /* * Pivot expired or allocation failed. * Use pivot selector to do the allocation and find a new pivot. */ err = uaddr_pivot_newpivot(map, uaddr, pivot, entry_out, addr_out, sz, align, offset, before_gap, after_gap); return err; } /* * Free the pivot. */ void uaddr_pivot_destroy(struct uvm_addr_state *uaddr) { pool_put(&uaddr_pivot_pool, uaddr); } /* * Insert an entry with free space in the space tree. */ void uaddr_pivot_insert(struct vm_map *map, struct uvm_addr_state *uaddr_p, struct vm_map_entry *entry) { struct uaddr_pivot_state *uaddr; struct vm_map_entry *rb_rv; struct uaddr_pivot *p; vaddr_t check_addr; vaddr_t start, end; uaddr = (struct uaddr_pivot_state *)uaddr_p; if ((rb_rv = RBT_INSERT(uaddr_free_rbtree, &uaddr->up_free, entry)) != NULL) { panic("%s: duplicate insertion: state %p " "inserting entry %p which collides with %p", __func__, uaddr, entry, rb_rv); } start = VMMAP_FREE_START(entry); end = VMMAP_FREE_END(entry); /* * Update all pivots that are contained in this entry. */ for (p = &uaddr->up_pivots[0]; p != &uaddr->up_pivots[nitems(uaddr->up_pivots)]; p++) { check_addr = p->addr; if (check_addr == 0) continue; if (p->dir < 0) check_addr--; if (start <= check_addr && check_addr < end) { KASSERT(p->entry == NULL); p->entry = entry; } } } /* * Remove an entry with free space from the space tree. */ void uaddr_pivot_remove(struct vm_map *map, struct uvm_addr_state *uaddr_p, struct vm_map_entry *entry) { struct uaddr_pivot_state *uaddr; struct uaddr_pivot *p; uaddr = (struct uaddr_pivot_state *)uaddr_p; if (RBT_REMOVE(uaddr_free_rbtree, &uaddr->up_free, entry) != entry) panic("%s: entry was not in tree", __func__); /* * Inform any pivot with this entry that the entry is gone. * Note that this does not automatically invalidate the pivot. */ for (p = &uaddr->up_pivots[0]; p != &uaddr->up_pivots[nitems(uaddr->up_pivots)]; p++) { if (p->entry == entry) p->entry = NULL; } } /* * Create a new pivot selector. * * Initially, all pivots are in the expired state. * Two reasons for this: * - it means this allocator will not take a huge amount of time * - pivots select better on demand, because the pivot selection will be * affected by preceding allocations: * the next pivots will likely end up in different segments of free memory, * that was segmented by an earlier allocation; better spread. */ struct uvm_addr_state * uaddr_pivot_create(vaddr_t minaddr, vaddr_t maxaddr) { struct uaddr_pivot_state *uaddr; uaddr = pool_get(&uaddr_pivot_pool, PR_WAITOK); uaddr->up_uaddr.uaddr_minaddr = minaddr; uaddr->up_uaddr.uaddr_maxaddr = maxaddr; uaddr->up_uaddr.uaddr_functions = &uaddr_pivot_functions; RBT_INIT(uaddr_free_rbtree, &uaddr->up_free); memset(uaddr->up_pivots, 0, sizeof(uaddr->up_pivots)); return &uaddr->up_uaddr; } #if defined(DEBUG) || defined(DDB) /* * Print the uaddr_pivot_state. * * If full, a listing of all entries in the state will be provided. */ void uaddr_pivot_print(struct uvm_addr_state *uaddr_p, boolean_t full, int (*pr)(const char *, ...)) { struct uaddr_pivot_state *uaddr; struct uaddr_pivot *pivot; struct vm_map_entry *entry; int i; vaddr_t check_addr; uaddr = (struct uaddr_pivot_state *)uaddr_p; for (i = 0; i < NUM_PIVOTS; i++) { pivot = &uaddr->up_pivots[i]; (*pr)("\tpivot 0x%lx, epires in %d, direction %d\n", pivot->addr, pivot->expire, pivot->dir); } if (!full) return; if (RBT_EMPTY(uaddr_free_rbtree, &uaddr->up_free)) (*pr)("\tempty\n"); /* Print list of free space. */ RBT_FOREACH(entry, uaddr_free_rbtree, &uaddr->up_free) { (*pr)("\t0x%lx - 0x%lx free (0x%lx bytes)\n", VMMAP_FREE_START(entry), VMMAP_FREE_END(entry), VMMAP_FREE_END(entry) - VMMAP_FREE_START(entry)); for (i = 0; i < NUM_PIVOTS; i++) { pivot = &uaddr->up_pivots[i]; check_addr = pivot->addr; if (check_addr == 0) continue; if (pivot->dir < 0) check_addr--; if (VMMAP_FREE_START(entry) <= check_addr && check_addr < VMMAP_FREE_END(entry)) { (*pr)("\t\tcontains pivot %d (0x%lx)\n", i, pivot->addr); } } } } #endif /* DEBUG || DDB */ #endif /* !SMALL_KERNEL */ #ifndef SMALL_KERNEL /* * Stack/break allocator. * * Stack area is grown into in the opposite direction of the stack growth, * brk area is grown downward (because sbrk() grows upward). * * Both areas are grown into proportially: a weighted chance is used to * select which one (stack or brk area) to try. If the allocation fails, * the other one is tested. */ const struct uvm_addr_functions uaddr_stack_brk_functions = { .uaddr_select = &uaddr_stack_brk_select, .uaddr_destroy = &uaddr_destroy, .uaddr_name = "uaddr_stckbrk" }; /* * Stack/brk address selector. */ int uaddr_stack_brk_select(struct vm_map *map, struct uvm_addr_state *uaddr, struct vm_map_entry **entry_out, vaddr_t *addr_out, vsize_t sz, vaddr_t align, vaddr_t offset, vm_prot_t prot, vaddr_t hint) { vaddr_t start; vaddr_t end; vsize_t before_gap; vsize_t after_gap; int dir; /* Set up brk search strategy. */ start = MAX(map->b_start, uaddr->uaddr_minaddr); end = MIN(map->b_end, uaddr->uaddr_maxaddr); before_gap = 0; after_gap = 0; dir = -1; /* Opposite of brk() growth. */ if (end - start >= sz) { if (uvm_addr_linsearch(map, uaddr, entry_out, addr_out, 0, sz, align, offset, dir, start, end - sz, before_gap, after_gap) == 0) return 0; } /* Set up stack search strategy. */ start = MAX(map->s_start, uaddr->uaddr_minaddr); end = MIN(map->s_end, uaddr->uaddr_maxaddr); before_gap = ((arc4random() & 0x3) + 1) << PAGE_SHIFT; after_gap = ((arc4random() & 0x3) + 1) << PAGE_SHIFT; #ifdef MACHINE_STACK_GROWS_UP dir = -1; #else dir = 1; #endif if (end - start >= before_gap + after_gap && end - start - before_gap - after_gap >= sz) { if (uvm_addr_linsearch(map, uaddr, entry_out, addr_out, 0, sz, align, offset, dir, start, end - sz, before_gap, after_gap) == 0) return 0; } return ENOMEM; } struct uvm_addr_state * uaddr_stack_brk_create(vaddr_t minaddr, vaddr_t maxaddr) { struct uvm_addr_state* uaddr; uaddr = pool_get(&uaddr_pool, PR_WAITOK); uaddr->uaddr_minaddr = minaddr; uaddr->uaddr_maxaddr = maxaddr; uaddr->uaddr_functions = &uaddr_stack_brk_functions; return uaddr; } #endif /* !SMALL_KERNEL */ #ifndef SMALL_KERNEL /* * Free space comparison. * Compares smaller free-space before larger free-space. */ static inline int uvm_mapent_fspace_cmp(const struct vm_map_entry *e1, const struct vm_map_entry *e2) { if (e1->fspace != e2->fspace) return (e1->fspace < e2->fspace ? -1 : 1); return (e1->start < e2->start ? -1 : e1->start > e2->start); } RBT_GENERATE(uaddr_free_rbtree, vm_map_entry, dfree.rbtree, uvm_mapent_fspace_cmp); #endif /* !SMALL_KERNEL */
149 88 75 75 75 75 30 125 4 145 145 145 144 141 4 1 144 4 144 25 121 117 124 74 1 74 87 33 34 87 54 12 34 33 26 34 22 59 81 88 24 84 3 59 8 52 58 95 42 30 95 38 19 95 3 1 86 83 16 92 49 43 43 92 92 1 81 3 2 1 5 6 129 6 6 6 6 1 28 4 4 5 1 6 38 6 29 35 366 1 304 8 24 1 1 1 1 2 1 2 2 2 2 1 2 2 1 2 2 2 6 7 8 33 2 1 1 1 1 8 4 3 3 3 3 2 1 2 2 1 44 1 1 1 1 1 1 1 1 1 1 1 1 2 4 8 1 1 1 1 2 1 8 2 1 1 1 1 1 1 49 18 31 18 3 3 3 2 2 2 1 2 1 44 44 36 3 40 42 3 40 41 1 42 41 40 40 41 2 6 3 3 6 6 6 6 22 21 1 173 141 41 10 4 2 1 10 4 5 8 5 9 15 20 18 19 8 22 20 8 4 20 9 15 16 18 3 9 7 13 11 6 7 85 31 31 30 2 2 1 1 1 1 21 19 3 2 39 33 2 13 11 16 7 18 71 14 2 11 5 6 1 13 8 6 1 4 6 4 1 1 1 1 1 2 2 2 1 3 2 3 3 2 2 3 2 1 2 3 1 1 2 1 1 2 2 1 2 1 8 8 1 8 8 32 22 10 80 80 27 28 90 11 80 80 16 49 25 16 3 48 1 11 25 129 129 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 /* $OpenBSD: ip6_output.c,v 1.291 2024/04/17 20:48:51 bluhm Exp $ */ /* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 1982, 1986, 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ip_output.c 8.3 (Berkeley) 1/21/94 */ #include "pf.h" #include <sys/param.h> #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/errno.h> #include <sys/protosw.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/proc.h> #include <sys/systm.h> #include <net/if.h> #include <net/if_var.h> #include <net/if_enc.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/in_pcb.h> #include <netinet/udp.h> #include <netinet/tcp.h> #include <netinet/ip_var.h> #include <netinet/tcp_timer.h> #include <netinet/tcp_var.h> #include <netinet/udp_var.h> #include <netinet6/in6_var.h> #include <netinet/ip6.h> #include <netinet/icmp6.h> #include <netinet6/ip6_var.h> #include <netinet6/nd6.h> #include <crypto/idgen.h> #if NPF > 0 #include <net/pfvar.h> #endif #ifdef IPSEC #include <netinet/ip_ipsp.h> #include <netinet/ip_ah.h> #include <netinet/ip_esp.h> #ifdef ENCDEBUG #define DPRINTF(fmt, args...) \ do { \ if (encdebug) \ printf("%s: " fmt "\n", __func__, ## args); \ } while (0) #else #define DPRINTF(fmt, args...) \ do { } while (0) #endif #endif /* IPSEC */ struct ip6_exthdrs { struct mbuf *ip6e_ip6; struct mbuf *ip6e_hbh; struct mbuf *ip6e_dest1; struct mbuf *ip6e_rthdr; struct mbuf *ip6e_dest2; }; int ip6_pcbopt(int, u_char *, int, struct ip6_pktopts **, int, int); int ip6_getpcbopt(struct ip6_pktopts *, int, struct mbuf *); int ip6_setpktopt(int, u_char *, int, struct ip6_pktopts *, int, int, int); int ip6_setmoptions(int, struct ip6_moptions **, struct mbuf *, unsigned int); int ip6_getmoptions(int, struct ip6_moptions *, struct mbuf *); int ip6_copyexthdr(struct mbuf **, caddr_t, int); int ip6_insertfraghdr(struct mbuf *, struct mbuf *, int, struct ip6_frag **); int ip6_insert_jumboopt(struct ip6_exthdrs *, u_int32_t); int ip6_splithdr(struct mbuf *, struct ip6_exthdrs *); int ip6_getpmtu(struct rtentry *, struct ifnet *, u_long *); int copypktopts(struct ip6_pktopts *, struct ip6_pktopts *); static __inline u_int16_t __attribute__((__unused__)) in6_cksum_phdr(const struct in6_addr *, const struct in6_addr *, u_int32_t, u_int32_t); void in6_delayed_cksum(struct mbuf *, u_int8_t); int ip6_output_ipsec_pmtu_update(struct tdb *, struct route *, struct in6_addr *, int, int, int); /* Context for non-repeating IDs */ struct idgen32_ctx ip6_id_ctx; /* * IP6 output. The packet in mbuf chain m contains a skeletal IP6 * header (with pri, len, nxt, hlim, src, dst). * This function may modify ver and hlim only. * The mbuf chain containing the packet will be freed. * The mbuf opt, if present, will not be freed. * * type of "mtu": rt_mtu is u_long, ifnet.ifr_mtu is int. * We use u_long to hold largest one, * which is rt_mtu. */ int ip6_output(struct mbuf *m, struct ip6_pktopts *opt, struct route *ro, int flags, struct ip6_moptions *im6o, const struct ipsec_level *seclevel) { struct ip6_hdr *ip6; struct ifnet *ifp = NULL; struct mbuf_list ml; int hlen, tlen; struct route iproute; struct rtentry *rt = NULL; struct sockaddr_in6 *dst; int error = 0; u_long mtu; int dontfrag; u_int16_t src_scope, dst_scope; u_int32_t optlen = 0, plen = 0, unfragpartlen = 0; struct ip6_exthdrs exthdrs; struct in6_addr finaldst; struct route *ro_pmtu = NULL; int hdrsplit = 0; u_int8_t sproto = 0; u_char nextproto; #ifdef IPSEC struct tdb *tdb = NULL; #endif /* IPSEC */ ip6 = mtod(m, struct ip6_hdr *); finaldst = ip6->ip6_dst; #define MAKE_EXTHDR(hp, mp) \ do { \ if (hp) { \ struct ip6_ext *eh = (struct ip6_ext *)(hp); \ error = ip6_copyexthdr((mp), (caddr_t)(hp), \ ((eh)->ip6e_len + 1) << 3); \ if (error) \ goto freehdrs; \ } \ } while (0) bzero(&exthdrs, sizeof(exthdrs)); if (opt) { /* Hop-by-Hop options header */ MAKE_EXTHDR(opt->ip6po_hbh, &exthdrs.ip6e_hbh); /* Destination options header(1st part) */ MAKE_EXTHDR(opt->ip6po_dest1, &exthdrs.ip6e_dest1); /* Routing header */ MAKE_EXTHDR(opt->ip6po_rthdr, &exthdrs.ip6e_rthdr); /* Destination options header(2nd part) */ MAKE_EXTHDR(opt->ip6po_dest2, &exthdrs.ip6e_dest2); } #ifdef IPSEC if (ipsec_in_use || seclevel != NULL) { error = ip6_output_ipsec_lookup(m, seclevel, &tdb); if (error) { /* * -EINVAL is used to indicate that the packet should * be silently dropped, typically because we've asked * key management for an SA. */ if (error == -EINVAL) /* Should silently drop packet */ error = 0; goto freehdrs; } } #endif /* IPSEC */ /* * Calculate the total length of the extension header chain. * Keep the length of the unfragmentable part for fragmentation. */ optlen = 0; if (exthdrs.ip6e_hbh) optlen += exthdrs.ip6e_hbh->m_len; if (exthdrs.ip6e_dest1) optlen += exthdrs.ip6e_dest1->m_len; if (exthdrs.ip6e_rthdr) optlen += exthdrs.ip6e_rthdr->m_len; unfragpartlen = optlen + sizeof(struct ip6_hdr); /* NOTE: we don't add AH/ESP length here. do that later. */ if (exthdrs.ip6e_dest2) optlen += exthdrs.ip6e_dest2->m_len; /* * If we need IPsec, or there is at least one extension header, * separate IP6 header from the payload. */ if ((sproto || optlen) && !hdrsplit) { if ((error = ip6_splithdr(m, &exthdrs)) != 0) { m = NULL; goto freehdrs; } m = exthdrs.ip6e_ip6; hdrsplit++; } /* adjust pointer */ ip6 = mtod(m, struct ip6_hdr *); /* adjust mbuf packet header length */ m->m_pkthdr.len += optlen; plen = m->m_pkthdr.len - sizeof(*ip6); /* If this is a jumbo payload, insert a jumbo payload option. */ if (plen > IPV6_MAXPACKET) { if (!hdrsplit) { if ((error = ip6_splithdr(m, &exthdrs)) != 0) { m = NULL; goto freehdrs; } m = exthdrs.ip6e_ip6; hdrsplit++; } /* adjust pointer */ ip6 = mtod(m, struct ip6_hdr *); if ((error = ip6_insert_jumboopt(&exthdrs, plen)) != 0) goto freehdrs; ip6->ip6_plen = 0; } else ip6->ip6_plen = htons(plen); /* * Concatenate headers and fill in next header fields. * Here we have, on "m" * IPv6 payload * and we insert headers accordingly. Finally, we should be getting: * IPv6 hbh dest1 rthdr ah* [esp* dest2 payload] * * during the header composing process, "m" points to IPv6 header. * "mprev" points to an extension header prior to esp. */ { u_char *nexthdrp = &ip6->ip6_nxt; struct mbuf *mprev = m; /* * we treat dest2 specially. this makes IPsec processing * much easier. the goal here is to make mprev point the * mbuf prior to dest2. * * result: IPv6 dest2 payload * m and mprev will point to IPv6 header. */ if (exthdrs.ip6e_dest2) { if (!hdrsplit) panic("%s: assumption failed: hdr not split", __func__); exthdrs.ip6e_dest2->m_next = m->m_next; m->m_next = exthdrs.ip6e_dest2; *mtod(exthdrs.ip6e_dest2, u_char *) = ip6->ip6_nxt; ip6->ip6_nxt = IPPROTO_DSTOPTS; } #define MAKE_CHAIN(m, mp, p, i)\ do {\ if (m) {\ if (!hdrsplit) \ panic("assumption failed: hdr not split"); \ *mtod((m), u_char *) = *(p);\ *(p) = (i);\ p = mtod((m), u_char *);\ (m)->m_next = (mp)->m_next;\ (mp)->m_next = (m);\ (mp) = (m);\ }\ } while (0) /* * result: IPv6 hbh dest1 rthdr dest2 payload * m will point to IPv6 header. mprev will point to the * extension header prior to dest2 (rthdr in the above case). */ MAKE_CHAIN(exthdrs.ip6e_hbh, mprev, nexthdrp, IPPROTO_HOPOPTS); MAKE_CHAIN(exthdrs.ip6e_dest1, mprev, nexthdrp, IPPROTO_DSTOPTS); MAKE_CHAIN(exthdrs.ip6e_rthdr, mprev, nexthdrp, IPPROTO_ROUTING); } /* * If there is a routing header, replace the destination address field * with the first hop of the routing header. */ if (exthdrs.ip6e_rthdr) { struct ip6_rthdr *rh; struct ip6_rthdr0 *rh0; struct in6_addr *addr; rh = (struct ip6_rthdr *)(mtod(exthdrs.ip6e_rthdr, struct ip6_rthdr *)); switch (rh->ip6r_type) { case IPV6_RTHDR_TYPE_0: rh0 = (struct ip6_rthdr0 *)rh; addr = (struct in6_addr *)(rh0 + 1); ip6->ip6_dst = addr[0]; bcopy(&addr[1], &addr[0], sizeof(struct in6_addr) * (rh0->ip6r0_segleft - 1)); addr[rh0->ip6r0_segleft - 1] = finaldst; break; default: /* is it possible? */ error = EINVAL; goto bad; } } /* Source address validation */ if (!(flags & IPV6_UNSPECSRC) && IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) { /* * XXX: we can probably assume validation in the caller, but * we explicitly check the address here for safety. */ error = EOPNOTSUPP; ip6stat_inc(ip6s_badscope); goto bad; } if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src)) { error = EOPNOTSUPP; ip6stat_inc(ip6s_badscope); goto bad; } ip6stat_inc(ip6s_localout); /* * Route packet. */ #if NPF > 0 reroute: #endif /* initialize cached route */ if (ro == NULL) { ro = &iproute; ro->ro_rt = NULL; } ro_pmtu = ro; if (opt && opt->ip6po_rthdr) ro = &opt->ip6po_route; dst = &ro->ro_dstsin6; /* * if specified, try to fill in the traffic class field. * do not override if a non-zero value is already set. * we check the diffserv field and the ecn field separately. */ if (opt && opt->ip6po_tclass >= 0) { int mask = 0; if ((ip6->ip6_flow & htonl(0xfc << 20)) == 0) mask |= 0xfc; if ((ip6->ip6_flow & htonl(0x03 << 20)) == 0) mask |= 0x03; if (mask != 0) ip6->ip6_flow |= htonl((opt->ip6po_tclass & mask) << 20); } /* fill in or override the hop limit field, if necessary. */ if (opt && opt->ip6po_hlim != -1) ip6->ip6_hlim = opt->ip6po_hlim & 0xff; else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { if (im6o != NULL) ip6->ip6_hlim = im6o->im6o_hlim; else ip6->ip6_hlim = ip6_defmcasthlim; } #ifdef IPSEC if (tdb != NULL) { /* * XXX what should we do if ip6_hlim == 0 and the * packet gets tunneled? */ /* * if we are source-routing, do not attempt to tunnel the * packet just because ip6_dst is different from what tdb has. * XXX */ error = ip6_output_ipsec_send(tdb, m, ro, exthdrs.ip6e_rthdr ? 1 : 0, 0); goto done; } #endif /* IPSEC */ if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { struct in6_pktinfo *pi = NULL; /* * If the caller specify the outgoing interface * explicitly, use it. */ if (opt != NULL && (pi = opt->ip6po_pktinfo) != NULL) ifp = if_get(pi->ipi6_ifindex); if (ifp == NULL && im6o != NULL) ifp = if_get(im6o->im6o_ifidx); } if (ifp == NULL) { rt = in6_selectroute(&ip6->ip6_dst, opt, ro, m->m_pkthdr.ph_rtableid); if (rt == NULL) { ip6stat_inc(ip6s_noroute); error = EHOSTUNREACH; goto bad; } if (ISSET(rt->rt_flags, RTF_LOCAL)) ifp = if_get(rtable_loindex(m->m_pkthdr.ph_rtableid)); else ifp = if_get(rt->rt_ifidx); /* * We aren't using rtisvalid() here because the UP/DOWN state * machine is broken with some Ethernet drivers like em(4). * As a result we might try to use an invalid cached route * entry while an interface is being detached. */ if (ifp == NULL) { ip6stat_inc(ip6s_noroute); error = EHOSTUNREACH; goto bad; } } else { route6_cache(ro, &ip6->ip6_dst, NULL, m->m_pkthdr.ph_rtableid); } if (rt && (rt->rt_flags & RTF_GATEWAY) && !IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) dst = satosin6(rt->rt_gateway); if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { /* Unicast */ m->m_flags &= ~(M_BCAST | M_MCAST); /* just in case */ } else { /* Multicast */ m->m_flags = (m->m_flags & ~M_BCAST) | M_MCAST; /* * Confirm that the outgoing interface supports multicast. */ if ((ifp->if_flags & IFF_MULTICAST) == 0) { ip6stat_inc(ip6s_noroute); error = ENETUNREACH; goto bad; } if ((im6o == NULL || im6o->im6o_loop) && in6_hasmulti(&ip6->ip6_dst, ifp)) { /* * If we belong to the destination multicast group * on the outgoing interface, and the caller did not * forbid loopback, loop back a copy. * Can't defer TCP/UDP checksumming, do the * computation now. */ in6_proto_cksum_out(m, NULL); ip6_mloopback(ifp, m, dst); } #ifdef MROUTING else { /* * If we are acting as a multicast router, perform * multicast forwarding as if the packet had just * arrived on the interface to which we are about * to send. The multicast forwarding function * recursively calls this function, using the * IPV6_FORWARDING flag to prevent infinite recursion. * * Multicasts that are looped back by ip6_mloopback(), * above, will be forwarded by the ip6_input() routine, * if necessary. */ if (ip6_mforwarding && ip6_mrouter[ifp->if_rdomain] && (flags & IPV6_FORWARDING) == 0) { if (ip6_mforward(ip6, ifp, m) != 0) { m_freem(m); goto done; } } } #endif /* * Multicasts with a hoplimit of zero may be looped back, * above, but must not be transmitted on a network. * Also, multicasts addressed to the loopback interface * are not sent -- the above call to ip6_mloopback() will * loop back a copy if this host actually belongs to the * destination group on the loopback interface. */ if (ip6->ip6_hlim == 0 || (ifp->if_flags & IFF_LOOPBACK) || IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst)) { m_freem(m); goto done; } } /* * If this packet is going through a loopback interface we won't * be able to restore its scope ID using the interface index. */ if (IN6_IS_SCOPE_EMBED(&ip6->ip6_src)) { if (ifp->if_flags & IFF_LOOPBACK) src_scope = ip6->ip6_src.s6_addr16[1]; ip6->ip6_src.s6_addr16[1] = 0; } if (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst)) { if (ifp->if_flags & IFF_LOOPBACK) dst_scope = ip6->ip6_dst.s6_addr16[1]; ip6->ip6_dst.s6_addr16[1] = 0; } /* Determine path MTU. */ if ((error = ip6_getpmtu(ro_pmtu->ro_rt, ifp, &mtu)) != 0) goto bad; /* * The caller of this function may specify to use the minimum MTU * in some cases. * An advanced API option (IPV6_USE_MIN_MTU) can also override MTU * setting. The logic is a bit complicated; by default, unicast * packets will follow path MTU while multicast packets will be sent at * the minimum MTU. If IP6PO_MINMTU_ALL is specified, all packets * including unicast ones will be sent at the minimum MTU. Multicast * packets will always be sent at the minimum MTU unless * IP6PO_MINMTU_DISABLE is explicitly specified. * See RFC 3542 for more details. */ if (mtu > IPV6_MMTU) { if ((flags & IPV6_MINMTU)) mtu = IPV6_MMTU; else if (opt && opt->ip6po_minmtu == IP6PO_MINMTU_ALL) mtu = IPV6_MMTU; else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) && (opt == NULL || opt->ip6po_minmtu != IP6PO_MINMTU_DISABLE)) { mtu = IPV6_MMTU; } } /* * If the outgoing packet contains a hop-by-hop options header, * it must be examined and processed even by the source node. * (RFC 2460, section 4.) */ if (exthdrs.ip6e_hbh) { struct ip6_hbh *hbh = mtod(exthdrs.ip6e_hbh, struct ip6_hbh *); u_int32_t rtalert; /* returned value is ignored */ u_int32_t plen = 0; /* no more than 1 jumbo payload option! */ m->m_pkthdr.ph_ifidx = ifp->if_index; if (ip6_process_hopopts(&m, (u_int8_t *)(hbh + 1), ((hbh->ip6h_len + 1) << 3) - sizeof(struct ip6_hbh), &rtalert, &plen) < 0) { /* m was already freed at this point */ error = EINVAL;/* better error? */ goto done; } m->m_pkthdr.ph_ifidx = 0; } #if NPF > 0 if (pf_test(AF_INET6, PF_OUT, ifp, &m) != PF_PASS) { error = EACCES; m_freem(m); goto done; } if (m == NULL) goto done; ip6 = mtod(m, struct ip6_hdr *); if ((m->m_pkthdr.pf.flags & (PF_TAG_REROUTE | PF_TAG_GENERATED)) == (PF_TAG_REROUTE | PF_TAG_GENERATED)) { /* already rerun the route lookup, go on */ m->m_pkthdr.pf.flags &= ~(PF_TAG_GENERATED | PF_TAG_REROUTE); } else if (m->m_pkthdr.pf.flags & PF_TAG_REROUTE) { /* tag as generated to skip over pf_test on rerun */ m->m_pkthdr.pf.flags |= PF_TAG_GENERATED; finaldst = ip6->ip6_dst; if (ro == &iproute) rtfree(ro->ro_rt); ro = NULL; if_put(ifp); /* drop reference since destination changed */ ifp = NULL; goto reroute; } #endif /* * If the packet is not going on the wire it can be destined * to any local address. In this case do not clear its scopes * to let ip6_input() find a matching local route. */ if (ifp->if_flags & IFF_LOOPBACK) { if (IN6_IS_SCOPE_EMBED(&ip6->ip6_src)) ip6->ip6_src.s6_addr16[1] = src_scope; if (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst)) ip6->ip6_dst.s6_addr16[1] = dst_scope; } /* * Send the packet to the outgoing interface. * If necessary, do IPv6 fragmentation before sending. * * the logic here is rather complex: * 1: normal case (dontfrag == 0) * 1-a: send as is if tlen <= path mtu * 1-b: fragment if tlen > path mtu * * 2: if user asks us not to fragment (dontfrag == 1) * 2-a: send as is if tlen <= interface mtu * 2-b: error if tlen > interface mtu */ tlen = ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO) ? m->m_pkthdr.ph_mss : m->m_pkthdr.len; if (ISSET(m->m_pkthdr.csum_flags, M_IPV6_DF_OUT)) { CLR(m->m_pkthdr.csum_flags, M_IPV6_DF_OUT); dontfrag = 1; } else if (opt && ISSET(opt->ip6po_flags, IP6PO_DONTFRAG)) dontfrag = 1; else dontfrag = 0; if (dontfrag && tlen > ifp->if_mtu) { /* case 2-b */ #ifdef IPSEC if (ip_mtudisc) ipsec_adjust_mtu(m, mtu); #endif error = EMSGSIZE; goto bad; } /* * transmit packet without fragmentation */ if (dontfrag || tlen <= mtu) { /* case 1-a and 2-a */ error = if_output_tso(ifp, &m, sin6tosa(dst), ro->ro_rt, ifp->if_mtu); if (error || m == NULL) goto done; goto bad; /* should not happen */ } /* * try to fragment the packet. case 1-b */ if (mtu < IPV6_MMTU) { /* path MTU cannot be less than IPV6_MMTU */ error = EMSGSIZE; goto bad; } else if (ip6->ip6_plen == 0) { /* jumbo payload cannot be fragmented */ error = EMSGSIZE; goto bad; } /* * Too large for the destination or interface; * fragment if possible. * Must be able to put at least 8 bytes per fragment. */ hlen = unfragpartlen; if (mtu > IPV6_MAXPACKET) mtu = IPV6_MAXPACKET; /* * If we are doing fragmentation, we can't defer TCP/UDP * checksumming; compute the checksum and clear the flag. */ in6_proto_cksum_out(m, NULL); /* * Change the next header field of the last header in the * unfragmentable part. */ if (exthdrs.ip6e_rthdr) { nextproto = *mtod(exthdrs.ip6e_rthdr, u_char *); *mtod(exthdrs.ip6e_rthdr, u_char *) = IPPROTO_FRAGMENT; } else if (exthdrs.ip6e_dest1) { nextproto = *mtod(exthdrs.ip6e_dest1, u_char *); *mtod(exthdrs.ip6e_dest1, u_char *) = IPPROTO_FRAGMENT; } else if (exthdrs.ip6e_hbh) { nextproto = *mtod(exthdrs.ip6e_hbh, u_char *); *mtod(exthdrs.ip6e_hbh, u_char *) = IPPROTO_FRAGMENT; } else { nextproto = ip6->ip6_nxt; ip6->ip6_nxt = IPPROTO_FRAGMENT; } if ((error = ip6_fragment(m, &ml, hlen, nextproto, mtu)) || (error = if_output_ml(ifp, &ml, sin6tosa(dst), ro->ro_rt))) goto done; ip6stat_inc(ip6s_fragmented); goto done; freehdrs: m_freem(exthdrs.ip6e_hbh); /* m_freem will check if mbuf is 0 */ m_freem(exthdrs.ip6e_dest1); m_freem(exthdrs.ip6e_rthdr); m_freem(exthdrs.ip6e_dest2); bad: m_freem(m); done: if (ro == &iproute) rtfree(ro->ro_rt); else if (ro_pmtu == &iproute) rtfree(ro_pmtu->ro_rt); if_put(ifp); #ifdef IPSEC tdb_unref(tdb); #endif /* IPSEC */ return (error); } int ip6_fragment(struct mbuf *m0, struct mbuf_list *ml, int hlen, u_char nextproto, u_long mtu) { struct ip6_hdr *ip6; u_int32_t id; int tlen, len, off; int error; ml_init(ml); ip6 = mtod(m0, struct ip6_hdr *); tlen = m0->m_pkthdr.len; len = (mtu - hlen - sizeof(struct ip6_frag)) & ~7; if (len < 8) { error = EMSGSIZE; goto bad; } id = htonl(ip6_randomid()); /* * Loop through length of payload, * make new header and copy data of each part and link onto chain. */ for (off = hlen; off < tlen; off += len) { struct mbuf *m; struct mbuf *mlast; struct ip6_hdr *mhip6; struct ip6_frag *ip6f; MGETHDR(m, M_DONTWAIT, MT_HEADER); if (m == NULL) { error = ENOBUFS; goto bad; } ml_enqueue(ml, m); if ((error = m_dup_pkthdr(m, m0, M_DONTWAIT)) != 0) goto bad; m->m_data += max_linkhdr; mhip6 = mtod(m, struct ip6_hdr *); *mhip6 = *ip6; m->m_len = sizeof(struct ip6_hdr); if ((error = ip6_insertfraghdr(m0, m, hlen, &ip6f)) != 0) goto bad; ip6f->ip6f_offlg = htons((off - hlen) & ~7); if (off + len >= tlen) len = tlen - off; else ip6f->ip6f_offlg |= IP6F_MORE_FRAG; m->m_pkthdr.len = hlen + sizeof(struct ip6_frag) + len; mhip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); for (mlast = m; mlast->m_next; mlast = mlast->m_next) ; mlast->m_next = m_copym(m0, off, len, M_DONTWAIT); if (mlast->m_next == NULL) { error = ENOBUFS; goto bad; } ip6f->ip6f_reserved = 0; ip6f->ip6f_ident = id; ip6f->ip6f_nxt = nextproto; } ip6stat_add(ip6s_ofragments, ml_len(ml)); m_freem(m0); return (0); bad: ip6stat_inc(ip6s_odropped); ml_purge(ml); m_freem(m0); return (error); } int ip6_copyexthdr(struct mbuf **mp, caddr_t hdr, int hlen) { struct mbuf *m; if (hlen > MCLBYTES) return (ENOBUFS); /* XXX */ MGET(m, M_DONTWAIT, MT_DATA); if (!m) return (ENOBUFS); if (hlen > MLEN) { MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { m_free(m); return (ENOBUFS); } } m->m_len = hlen; if (hdr) memcpy(mtod(m, caddr_t), hdr, hlen); *mp = m; return (0); } /* * Insert jumbo payload option. */ int ip6_insert_jumboopt(struct ip6_exthdrs *exthdrs, u_int32_t plen) { struct mbuf *mopt; u_int8_t *optbuf; u_int32_t v; #define JUMBOOPTLEN 8 /* length of jumbo payload option and padding */ /* * If there is no hop-by-hop options header, allocate new one. * If there is one but it doesn't have enough space to store the * jumbo payload option, allocate a cluster to store the whole options. * Otherwise, use it to store the options. */ if (exthdrs->ip6e_hbh == 0) { MGET(mopt, M_DONTWAIT, MT_DATA); if (mopt == NULL) return (ENOBUFS); mopt->m_len = JUMBOOPTLEN; optbuf = mtod(mopt, u_int8_t *); optbuf[1] = 0; /* = ((JUMBOOPTLEN) >> 3) - 1 */ exthdrs->ip6e_hbh = mopt; } else { struct ip6_hbh *hbh; mopt = exthdrs->ip6e_hbh; if (m_trailingspace(mopt) < JUMBOOPTLEN) { /* * XXX assumption: * - exthdrs->ip6e_hbh is not referenced from places * other than exthdrs. * - exthdrs->ip6e_hbh is not an mbuf chain. */ int oldoptlen = mopt->m_len; struct mbuf *n; /* * XXX: give up if the whole (new) hbh header does * not fit even in an mbuf cluster. */ if (oldoptlen + JUMBOOPTLEN > MCLBYTES) return (ENOBUFS); /* * As a consequence, we must always prepare a cluster * at this point. */ MGET(n, M_DONTWAIT, MT_DATA); if (n) { MCLGET(n, M_DONTWAIT); if ((n->m_flags & M_EXT) == 0) { m_freem(n); n = NULL; } } if (!n) return (ENOBUFS); n->m_len = oldoptlen + JUMBOOPTLEN; memcpy(mtod(n, caddr_t), mtod(mopt, caddr_t), oldoptlen); optbuf = mtod(n, u_int8_t *) + oldoptlen; m_freem(mopt); mopt = exthdrs->ip6e_hbh = n; } else { optbuf = mtod(mopt, u_int8_t *) + mopt->m_len; mopt->m_len += JUMBOOPTLEN; } optbuf[0] = IP6OPT_PADN; optbuf[1] = 0; /* * Adjust the header length according to the pad and * the jumbo payload option. */ hbh = mtod(mopt, struct ip6_hbh *); hbh->ip6h_len += (JUMBOOPTLEN >> 3); } /* fill in the option. */ optbuf[2] = IP6OPT_JUMBO; optbuf[3] = 4; v = (u_int32_t)htonl(plen + JUMBOOPTLEN); memcpy(&optbuf[4], &v, sizeof(u_int32_t)); /* finally, adjust the packet header length */ exthdrs->ip6e_ip6->m_pkthdr.len += JUMBOOPTLEN; return (0); #undef JUMBOOPTLEN } /* * Insert fragment header and copy unfragmentable header portions. */ int ip6_insertfraghdr(struct mbuf *m0, struct mbuf *m, int hlen, struct ip6_frag **frghdrp) { struct mbuf *n, *mlast; if (hlen > sizeof(struct ip6_hdr)) { n = m_copym(m0, sizeof(struct ip6_hdr), hlen - sizeof(struct ip6_hdr), M_DONTWAIT); if (n == NULL) return (ENOBUFS); m->m_next = n; } else n = m; /* Search for the last mbuf of unfragmentable part. */ for (mlast = n; mlast->m_next; mlast = mlast->m_next) ; if ((mlast->m_flags & M_EXT) == 0 && m_trailingspace(mlast) >= sizeof(struct ip6_frag)) { /* use the trailing space of the last mbuf for fragment hdr */ *frghdrp = (struct ip6_frag *)(mtod(mlast, caddr_t) + mlast->m_len); mlast->m_len += sizeof(struct ip6_frag); m->m_pkthdr.len += sizeof(struct ip6_frag); } else { /* allocate a new mbuf for the fragment header */ struct mbuf *mfrg; MGET(mfrg, M_DONTWAIT, MT_DATA); if (mfrg == NULL) return (ENOBUFS); mfrg->m_len = sizeof(struct ip6_frag); *frghdrp = mtod(mfrg, struct ip6_frag *); mlast->m_next = mfrg; } return (0); } int ip6_getpmtu(struct rtentry *rt, struct ifnet *ifp, u_long *mtup) { u_int32_t mtu = 0; int error = 0; if (rt != NULL) { mtu = rt->rt_mtu; if (mtu == 0) mtu = ifp->if_mtu; else if (mtu < IPV6_MMTU) { /* RFC8021 IPv6 Atomic Fragments Considered Harmful */ mtu = IPV6_MMTU; } else if (mtu > ifp->if_mtu) { /* * The MTU on the route is larger than the MTU on * the interface! This shouldn't happen, unless the * MTU of the interface has been changed after the * interface was brought up. Change the MTU in the * route to match the interface MTU (as long as the * field isn't locked). */ mtu = ifp->if_mtu; if (!(rt->rt_locks & RTV_MTU)) rt->rt_mtu = mtu; } } else { mtu = ifp->if_mtu; } *mtup = mtu; return (error); } /* * IP6 socket option processing. */ int ip6_ctloutput(int op, struct socket *so, int level, int optname, struct mbuf *m) { int privileged, optdatalen, uproto; void *optdata; struct inpcb *inp = sotoinpcb(so); int error, optval; struct proc *p = curproc; /* For IPsec and rdomain */ u_int rtableid, rtid = 0; error = optval = 0; privileged = (inp->inp_socket->so_state & SS_PRIV); uproto = (int)so->so_proto->pr_protocol; if (level != IPPROTO_IPV6) return (EINVAL); rtableid = p->p_p->ps_rtableid; switch (op) { case PRCO_SETOPT: switch (optname) { /* * Use of some Hop-by-Hop options or some * Destination options, might require special * privilege. That is, normal applications * (without special privilege) might be forbidden * from setting certain options in outgoing packets, * and might never see certain options in received * packets. [RFC 2292 Section 6] * KAME specific note: * KAME prevents non-privileged users from sending or * receiving ANY hbh/dst options in order to avoid * overhead of parsing options in the kernel. */ case IPV6_RECVHOPOPTS: case IPV6_RECVDSTOPTS: if (!privileged) { error = EPERM; break; } /* FALLTHROUGH */ case IPV6_UNICAST_HOPS: case IPV6_MINHOPCOUNT: case IPV6_HOPLIMIT: case IPV6_RECVPKTINFO: case IPV6_RECVHOPLIMIT: case IPV6_RECVRTHDR: case IPV6_RECVPATHMTU: case IPV6_RECVTCLASS: case IPV6_V6ONLY: case IPV6_AUTOFLOWLABEL: case IPV6_RECVDSTPORT: if (m == NULL || m->m_len != sizeof(int)) { error = EINVAL; break; } optval = *mtod(m, int *); switch (optname) { case IPV6_UNICAST_HOPS: if (optval < -1 || optval >= 256) error = EINVAL; else { /* -1 = kernel default */ inp->inp_hops = optval; } break; case IPV6_MINHOPCOUNT: if (optval < 0 || optval > 255) error = EINVAL; else inp->inp_ip6_minhlim = optval; break; #define OPTSET(bit) \ do { \ if (optval) \ inp->inp_flags |= (bit); \ else \ inp->inp_flags &= ~(bit); \ } while (/*CONSTCOND*/ 0) #define OPTBIT(bit) (inp->inp_flags & (bit) ? 1 : 0) case IPV6_RECVPKTINFO: OPTSET(IN6P_PKTINFO); break; case IPV6_HOPLIMIT: { struct ip6_pktopts **optp; optp = &inp->inp_outputopts6; error = ip6_pcbopt(IPV6_HOPLIMIT, (u_char *)&optval, sizeof(optval), optp, privileged, uproto); break; } case IPV6_RECVHOPLIMIT: OPTSET(IN6P_HOPLIMIT); break; case IPV6_RECVHOPOPTS: OPTSET(IN6P_HOPOPTS); break; case IPV6_RECVDSTOPTS: OPTSET(IN6P_DSTOPTS); break; case IPV6_RECVRTHDR: OPTSET(IN6P_RTHDR); break; case IPV6_RECVPATHMTU: /* * We ignore this option for TCP * sockets. * (RFC3542 leaves this case * unspecified.) */ if (uproto != IPPROTO_TCP) OPTSET(IN6P_MTU); break; case IPV6_V6ONLY: /* * make setsockopt(IPV6_V6ONLY) * available only prior to bind(2). * see ipng mailing list, Jun 22 2001. */ if (inp->inp_lport || !IN6_IS_ADDR_UNSPECIFIED( &inp->inp_laddr6)) { error = EINVAL; break; } /* No support for IPv4-mapped addresses. */ if (!optval) error = EINVAL; else error = 0; break; case IPV6_RECVTCLASS: OPTSET(IN6P_TCLASS); break; case IPV6_AUTOFLOWLABEL: OPTSET(IN6P_AUTOFLOWLABEL); break; case IPV6_RECVDSTPORT: OPTSET(IN6P_RECVDSTPORT); break; } break; case IPV6_TCLASS: case IPV6_DONTFRAG: case IPV6_USE_MIN_MTU: if (m == NULL || m->m_len != sizeof(optval)) { error = EINVAL; break; } optval = *mtod(m, int *); { struct ip6_pktopts **optp; optp = &inp->inp_outputopts6; error = ip6_pcbopt(optname, (u_char *)&optval, sizeof(optval), optp, privileged, uproto); break; } case IPV6_PKTINFO: case IPV6_HOPOPTS: case IPV6_RTHDR: case IPV6_DSTOPTS: case IPV6_RTHDRDSTOPTS: { /* new advanced API (RFC3542) */ u_char *optbuf; int optbuflen; struct ip6_pktopts **optp; if (m && m->m_next) { error = EINVAL; /* XXX */ break; } if (m) { optbuf = mtod(m, u_char *); optbuflen = m->m_len; } else { optbuf = NULL; optbuflen = 0; } optp = &inp->inp_outputopts6; error = ip6_pcbopt(optname, optbuf, optbuflen, optp, privileged, uproto); break; } #undef OPTSET case IPV6_MULTICAST_IF: case IPV6_MULTICAST_HOPS: case IPV6_MULTICAST_LOOP: case IPV6_JOIN_GROUP: case IPV6_LEAVE_GROUP: error = ip6_setmoptions(optname, &inp->inp_moptions6, m, inp->inp_rtableid); break; case IPV6_PORTRANGE: if (m == NULL || m->m_len != sizeof(int)) { error = EINVAL; break; } optval = *mtod(m, int *); switch (optval) { case IPV6_PORTRANGE_DEFAULT: inp->inp_flags &= ~(IN6P_LOWPORT); inp->inp_flags &= ~(IN6P_HIGHPORT); break; case IPV6_PORTRANGE_HIGH: inp->inp_flags &= ~(IN6P_LOWPORT); inp->inp_flags |= IN6P_HIGHPORT; break; case IPV6_PORTRANGE_LOW: inp->inp_flags &= ~(IN6P_HIGHPORT); inp->inp_flags |= IN6P_LOWPORT; break; default: error = EINVAL; break; } break; case IPSEC6_OUTSA: error = EINVAL; break; case IPV6_AUTH_LEVEL: case IPV6_ESP_TRANS_LEVEL: case IPV6_ESP_NETWORK_LEVEL: case IPV6_IPCOMP_LEVEL: #ifndef IPSEC error = EINVAL; #else if (m == NULL || m->m_len != sizeof(int)) { error = EINVAL; break; } optval = *mtod(m, int *); if (optval < IPSEC_LEVEL_BYPASS || optval > IPSEC_LEVEL_UNIQUE) { error = EINVAL; break; } switch (optname) { case IPV6_AUTH_LEVEL: if (optval < IPSEC_AUTH_LEVEL_DEFAULT && suser(p)) { error = EACCES; break; } inp->inp_seclevel.sl_auth = optval; break; case IPV6_ESP_TRANS_LEVEL: if (optval < IPSEC_ESP_TRANS_LEVEL_DEFAULT && suser(p)) { error = EACCES; break; } inp->inp_seclevel.sl_esp_trans = optval; break; case IPV6_ESP_NETWORK_LEVEL: if (optval < IPSEC_ESP_NETWORK_LEVEL_DEFAULT && suser(p)) { error = EACCES; break; } inp->inp_seclevel.sl_esp_network = optval; break; case IPV6_IPCOMP_LEVEL: if (optval < IPSEC_IPCOMP_LEVEL_DEFAULT && suser(p)) { error = EACCES; break; } inp->inp_seclevel.sl_ipcomp = optval; break; } #endif break; case SO_RTABLE: if (m == NULL || m->m_len < sizeof(u_int)) { error = EINVAL; break; } rtid = *mtod(m, u_int *); if (inp->inp_rtableid == rtid) break; /* needs privileges to switch when already set */ if (rtableid != rtid && rtableid != 0 && (error = suser(p)) != 0) break; error = in_pcbset_rtableid(inp, rtid); break; case IPV6_PIPEX: if (m != NULL && m->m_len == sizeof(int)) inp->inp_pipex = *mtod(m, int *); else error = EINVAL; break; default: error = ENOPROTOOPT; break; } break; case PRCO_GETOPT: switch (optname) { case IPV6_RECVHOPOPTS: case IPV6_RECVDSTOPTS: case IPV6_UNICAST_HOPS: case IPV6_MINHOPCOUNT: case IPV6_RECVPKTINFO: case IPV6_RECVHOPLIMIT: case IPV6_RECVRTHDR: case IPV6_RECVPATHMTU: case IPV6_V6ONLY: case IPV6_PORTRANGE: case IPV6_RECVTCLASS: case IPV6_AUTOFLOWLABEL: case IPV6_RECVDSTPORT: switch (optname) { case IPV6_RECVHOPOPTS: optval = OPTBIT(IN6P_HOPOPTS); break; case IPV6_RECVDSTOPTS: optval = OPTBIT(IN6P_DSTOPTS); break; case IPV6_UNICAST_HOPS: optval = inp->inp_hops; break; case IPV6_MINHOPCOUNT: optval = inp->inp_ip6_minhlim; break; case IPV6_RECVPKTINFO: optval = OPTBIT(IN6P_PKTINFO); break; case IPV6_RECVHOPLIMIT: optval = OPTBIT(IN6P_HOPLIMIT); break; case IPV6_RECVRTHDR: optval = OPTBIT(IN6P_RTHDR); break; case IPV6_RECVPATHMTU: optval = OPTBIT(IN6P_MTU); break; case IPV6_V6ONLY: optval = 1; break; case IPV6_PORTRANGE: { int flags; flags = inp->inp_flags; if (flags & IN6P_HIGHPORT) optval = IPV6_PORTRANGE_HIGH; else if (flags & IN6P_LOWPORT) optval = IPV6_PORTRANGE_LOW; else optval = 0; break; } case IPV6_RECVTCLASS: optval = OPTBIT(IN6P_TCLASS); break; case IPV6_AUTOFLOWLABEL: optval = OPTBIT(IN6P_AUTOFLOWLABEL); break; case IPV6_RECVDSTPORT: optval = OPTBIT(IN6P_RECVDSTPORT); break; } if (error) break; m->m_len = sizeof(int); *mtod(m, int *) = optval; break; case IPV6_PATHMTU: { u_long pmtu = 0; struct ip6_mtuinfo mtuinfo; struct ifnet *ifp; struct rtentry *rt; if (!(so->so_state & SS_ISCONNECTED)) return (ENOTCONN); rt = in6_pcbrtentry(inp); if (!rtisvalid(rt)) return (EHOSTUNREACH); ifp = if_get(rt->rt_ifidx); if (ifp == NULL) return (EHOSTUNREACH); /* * XXX: we dot not consider the case of source * routing, or optional information to specify * the outgoing interface. */ error = ip6_getpmtu(rt, ifp, &pmtu); if_put(ifp); if (error) break; if (pmtu > IPV6_MAXPACKET) pmtu = IPV6_MAXPACKET; bzero(&mtuinfo, sizeof(mtuinfo)); mtuinfo.ip6m_mtu = (u_int32_t)pmtu; optdata = (void *)&mtuinfo; optdatalen = sizeof(mtuinfo); if (optdatalen > MCLBYTES) return (EMSGSIZE); /* XXX */ if (optdatalen > MLEN) MCLGET(m, M_WAIT); m->m_len = optdatalen; bcopy(optdata, mtod(m, void *), optdatalen); break; } case IPV6_PKTINFO: case IPV6_HOPOPTS: case IPV6_RTHDR: case IPV6_DSTOPTS: case IPV6_RTHDRDSTOPTS: case IPV6_TCLASS: case IPV6_DONTFRAG: case IPV6_USE_MIN_MTU: error = ip6_getpcbopt(inp->inp_outputopts6, optname, m); break; case IPV6_MULTICAST_IF: case IPV6_MULTICAST_HOPS: case IPV6_MULTICAST_LOOP: case IPV6_JOIN_GROUP: case IPV6_LEAVE_GROUP: error = ip6_getmoptions(optname, inp->inp_moptions6, m); break; case IPSEC6_OUTSA: error = EINVAL; break; case IPV6_AUTH_LEVEL: case IPV6_ESP_TRANS_LEVEL: case IPV6_ESP_NETWORK_LEVEL: case IPV6_IPCOMP_LEVEL: #ifndef IPSEC m->m_len = sizeof(int); *mtod(m, int *) = IPSEC_LEVEL_NONE; #else m->m_len = sizeof(int); switch (optname) { case IPV6_AUTH_LEVEL: optval = inp->inp_seclevel.sl_auth; break; case IPV6_ESP_TRANS_LEVEL: optval = inp->inp_seclevel.sl_esp_trans; break; case IPV6_ESP_NETWORK_LEVEL: optval = inp->inp_seclevel.sl_esp_network; break; case IPV6_IPCOMP_LEVEL: optval = inp->inp_seclevel.sl_ipcomp; break; } *mtod(m, int *) = optval; #endif break; case SO_RTABLE: m->m_len = sizeof(u_int); *mtod(m, u_int *) = inp->inp_rtableid; break; case IPV6_PIPEX: m->m_len = sizeof(int); *mtod(m, int *) = inp->inp_pipex; break; default: error = ENOPROTOOPT; break; } break; } return (error); } int ip6_raw_ctloutput(int op, struct socket *so, int level, int optname, struct mbuf *m) { int error = 0, optval; const int icmp6off = offsetof(struct icmp6_hdr, icmp6_cksum); struct inpcb *inp = sotoinpcb(so); if (level != IPPROTO_IPV6) return (EINVAL); switch (optname) { case IPV6_CHECKSUM: /* * For ICMPv6 sockets, no modification allowed for checksum * offset, permit "no change" values to help existing apps. * * RFC3542 says: "An attempt to set IPV6_CHECKSUM * for an ICMPv6 socket will fail." * The current behavior does not meet RFC3542. */ switch (op) { case PRCO_SETOPT: if (m == NULL || m->m_len != sizeof(int)) { error = EINVAL; break; } optval = *mtod(m, int *); if (optval < -1 || (optval > 0 && (optval % 2) != 0)) { /* * The API assumes non-negative even offset * values or -1 as a special value. */ error = EINVAL; } else if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) { if (optval != icmp6off) error = EINVAL; } else inp->inp_cksum6 = optval; break; case PRCO_GETOPT: if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) optval = icmp6off; else optval = inp->inp_cksum6; m->m_len = sizeof(int); *mtod(m, int *) = optval; break; default: error = EINVAL; break; } break; default: error = ENOPROTOOPT; break; } return (error); } /* * initialize ip6_pktopts. beware that there are non-zero default values in * the struct. */ void ip6_initpktopts(struct ip6_pktopts *opt) { bzero(opt, sizeof(*opt)); opt->ip6po_hlim = -1; /* -1 means default hop limit */ opt->ip6po_tclass = -1; /* -1 means default traffic class */ opt->ip6po_minmtu = IP6PO_MINMTU_MCASTONLY; } int ip6_pcbopt(int optname, u_char *buf, int len, struct ip6_pktopts **pktopt, int priv, int uproto) { struct ip6_pktopts *opt; if (*pktopt == NULL) { *pktopt = malloc(sizeof(struct ip6_pktopts), M_IP6OPT, M_WAITOK); ip6_initpktopts(*pktopt); } opt = *pktopt; return (ip6_setpktopt(optname, buf, len, opt, priv, 1, uproto)); } int ip6_getpcbopt(struct ip6_pktopts *pktopt, int optname, struct mbuf *m) { void *optdata = NULL; int optdatalen = 0; struct ip6_ext *ip6e; int error = 0; struct in6_pktinfo null_pktinfo; int deftclass = 0, on; int defminmtu = IP6PO_MINMTU_MCASTONLY; switch (optname) { case IPV6_PKTINFO: if (pktopt && pktopt->ip6po_pktinfo) optdata = (void *)pktopt->ip6po_pktinfo; else { /* XXX: we don't have to do this every time... */ bzero(&null_pktinfo, sizeof(null_pktinfo)); optdata = (void *)&null_pktinfo; } optdatalen = sizeof(struct in6_pktinfo); break; case IPV6_TCLASS: if (pktopt && pktopt->ip6po_tclass >= 0) optdata = (void *)&pktopt->ip6po_tclass; else optdata = (void *)&deftclass; optdatalen = sizeof(int); break; case IPV6_HOPOPTS: if (pktopt && pktopt->ip6po_hbh) { optdata = (void *)pktopt->ip6po_hbh; ip6e = (struct ip6_ext *)pktopt->ip6po_hbh; optdatalen = (ip6e->ip6e_len + 1) << 3; } break; case IPV6_RTHDR: if (pktopt && pktopt->ip6po_rthdr) { optdata = (void *)pktopt->ip6po_rthdr; ip6e = (struct ip6_ext *)pktopt->ip6po_rthdr; optdatalen = (ip6e->ip6e_len + 1) << 3; } break; case IPV6_RTHDRDSTOPTS: if (pktopt && pktopt->ip6po_dest1) { optdata = (void *)pktopt->ip6po_dest1; ip6e = (struct ip6_ext *)pktopt->ip6po_dest1; optdatalen = (ip6e->ip6e_len + 1) << 3; } break; case IPV6_DSTOPTS: if (pktopt && pktopt->ip6po_dest2) { optdata = (void *)pktopt->ip6po_dest2; ip6e = (struct ip6_ext *)pktopt->ip6po_dest2; optdatalen = (ip6e->ip6e_len + 1) << 3; } break; case IPV6_USE_MIN_MTU: if (pktopt) optdata = (void *)&pktopt->ip6po_minmtu; else optdata = (void *)&defminmtu; optdatalen = sizeof(int); break; case IPV6_DONTFRAG: if (pktopt && ((pktopt->ip6po_flags) & IP6PO_DONTFRAG)) on = 1; else on = 0; optdata = (void *)&on; optdatalen = sizeof(on); break; default: /* should not happen */ #ifdef DIAGNOSTIC panic("%s: unexpected option", __func__); #endif return (ENOPROTOOPT); } if (optdatalen > MCLBYTES) return (EMSGSIZE); /* XXX */ if (optdatalen > MLEN) MCLGET(m, M_WAIT); m->m_len = optdatalen; if (optdatalen) bcopy(optdata, mtod(m, void *), optdatalen); return (error); } void ip6_clearpktopts(struct ip6_pktopts *pktopt, int optname) { if (optname == -1 || optname == IPV6_PKTINFO) { if (pktopt->ip6po_pktinfo) free(pktopt->ip6po_pktinfo, M_IP6OPT, 0); pktopt->ip6po_pktinfo = NULL; } if (optname == -1 || optname == IPV6_HOPLIMIT) pktopt->ip6po_hlim = -1; if (optname == -1 || optname == IPV6_TCLASS) pktopt->ip6po_tclass = -1; if (optname == -1 || optname == IPV6_HOPOPTS) { if (pktopt->ip6po_hbh) free(pktopt->ip6po_hbh, M_IP6OPT, 0); pktopt->ip6po_hbh = NULL; } if (optname == -1 || optname == IPV6_RTHDRDSTOPTS) { if (pktopt->ip6po_dest1) free(pktopt->ip6po_dest1, M_IP6OPT, 0); pktopt->ip6po_dest1 = NULL; } if (optname == -1 || optname == IPV6_RTHDR) { if (pktopt->ip6po_rhinfo.ip6po_rhi_rthdr) free(pktopt->ip6po_rhinfo.ip6po_rhi_rthdr, M_IP6OPT, 0); pktopt->ip6po_rhinfo.ip6po_rhi_rthdr = NULL; if (pktopt->ip6po_route.ro_rt) { rtfree(pktopt->ip6po_route.ro_rt); pktopt->ip6po_route.ro_rt = NULL; } } if (optname == -1 || optname == IPV6_DSTOPTS) { if (pktopt->ip6po_dest2) free(pktopt->ip6po_dest2, M_IP6OPT, 0); pktopt->ip6po_dest2 = NULL; } } #define PKTOPT_EXTHDRCPY(type) \ do {\ if (src->type) {\ size_t hlen;\ hlen = (((struct ip6_ext *)src->type)->ip6e_len + 1) << 3;\ dst->type = malloc(hlen, M_IP6OPT, M_NOWAIT);\ if (dst->type == NULL)\ goto bad;\ memcpy(dst->type, src->type, hlen);\ }\ } while (/*CONSTCOND*/ 0) int copypktopts(struct ip6_pktopts *dst, struct ip6_pktopts *src) { dst->ip6po_hlim = src->ip6po_hlim; dst->ip6po_tclass = src->ip6po_tclass; dst->ip6po_flags = src->ip6po_flags; if (src->ip6po_pktinfo) { dst->ip6po_pktinfo = malloc(sizeof(*dst->ip6po_pktinfo), M_IP6OPT, M_NOWAIT); if (dst->ip6po_pktinfo == NULL) goto bad; *dst->ip6po_pktinfo = *src->ip6po_pktinfo; } PKTOPT_EXTHDRCPY(ip6po_hbh); PKTOPT_EXTHDRCPY(ip6po_dest1); PKTOPT_EXTHDRCPY(ip6po_dest2); PKTOPT_EXTHDRCPY(ip6po_rthdr); /* not copy the cached route */ return (0); bad: ip6_clearpktopts(dst, -1); return (ENOBUFS); } #undef PKTOPT_EXTHDRCPY void ip6_freepcbopts(struct ip6_pktopts *pktopt) { if (pktopt == NULL) return; ip6_clearpktopts(pktopt, -1); free(pktopt, M_IP6OPT, 0); } /* * Set the IP6 multicast options in response to user setsockopt(). */ int ip6_setmoptions(int optname, struct ip6_moptions **im6op, struct mbuf *m, unsigned int rtableid) { int error = 0; u_int loop, ifindex; struct ipv6_mreq *mreq; struct ifnet *ifp; struct ip6_moptions *im6o = *im6op; struct in6_multi_mship *imm; struct proc *p = curproc; /* XXX */ if (im6o == NULL) { /* * No multicast option buffer attached to the pcb; * allocate one and initialize to default values. */ im6o = malloc(sizeof(*im6o), M_IPMOPTS, M_WAITOK); if (im6o == NULL) return (ENOBUFS); *im6op = im6o; im6o->im6o_ifidx = 0; im6o->im6o_hlim = ip6_defmcasthlim; im6o->im6o_loop = IPV6_DEFAULT_MULTICAST_LOOP; LIST_INIT(&im6o->im6o_memberships); } switch (optname) { case IPV6_MULTICAST_IF: /* * Select the interface for outgoing multicast packets. */ if (m == NULL || m->m_len != sizeof(u_int)) { error = EINVAL; break; } memcpy(&ifindex, mtod(m, u_int *), sizeof(ifindex)); if (ifindex != 0) { ifp = if_get(ifindex); if (ifp == NULL) { error = ENXIO; /* XXX EINVAL? */ break; } if (ifp->if_rdomain != rtable_l2(rtableid) || (ifp->if_flags & IFF_MULTICAST) == 0) { error = EADDRNOTAVAIL; if_put(ifp); break; } if_put(ifp); } im6o->im6o_ifidx = ifindex; break; case IPV6_MULTICAST_HOPS: { /* * Set the IP6 hoplimit for outgoing multicast packets. */ int optval; if (m == NULL || m->m_len != sizeof(int)) { error = EINVAL; break; } memcpy(&optval, mtod(m, u_int *), sizeof(optval)); if (optval < -1 || optval >= 256) error = EINVAL; else if (optval == -1) im6o->im6o_hlim = ip6_defmcasthlim; else im6o->im6o_hlim = optval; break; } case IPV6_MULTICAST_LOOP: /* * Set the loopback flag for outgoing multicast packets. * Must be zero or one. */ if (m == NULL || m->m_len != sizeof(u_int)) { error = EINVAL; break; } memcpy(&loop, mtod(m, u_int *), sizeof(loop)); if (loop > 1) { error = EINVAL; break; } im6o->im6o_loop = loop; break; case IPV6_JOIN_GROUP: /* * Add a multicast group membership. * Group must be a valid IP6 multicast address. */ if (m == NULL || m->m_len != sizeof(struct ipv6_mreq)) { error = EINVAL; break; } mreq = mtod(m, struct ipv6_mreq *); if (IN6_IS_ADDR_UNSPECIFIED(&mreq->ipv6mr_multiaddr)) { /* * We use the unspecified address to specify to accept * all multicast addresses. Only super user is allowed * to do this. */ if (suser(p)) { error = EACCES; break; } } else if (!IN6_IS_ADDR_MULTICAST(&mreq->ipv6mr_multiaddr)) { error = EINVAL; break; } /* * If no interface was explicitly specified, choose an * appropriate one according to the given multicast address. */ if (mreq->ipv6mr_interface == 0) { struct rtentry *rt; struct sockaddr_in6 dst; memset(&dst, 0, sizeof(dst)); dst.sin6_len = sizeof(dst); dst.sin6_family = AF_INET6; dst.sin6_addr = mreq->ipv6mr_multiaddr; rt = rtalloc(sin6tosa(&dst), RT_RESOLVE, rtableid); if (rt == NULL) { error = EADDRNOTAVAIL; break; } ifp = if_get(rt->rt_ifidx); rtfree(rt); } else { /* * If the interface is specified, validate it. */ ifp = if_get(mreq->ipv6mr_interface); if (ifp == NULL) { error = ENXIO; /* XXX EINVAL? */ break; } } /* * See if we found an interface, and confirm that it * supports multicast */ if (ifp == NULL || ifp->if_rdomain != rtable_l2(rtableid) || (ifp->if_flags & IFF_MULTICAST) == 0) { if_put(ifp); error = EADDRNOTAVAIL; break; } /* * Put interface index into the multicast address, * if the address has link/interface-local scope. */ if (IN6_IS_SCOPE_EMBED(&mreq->ipv6mr_multiaddr)) { mreq->ipv6mr_multiaddr.s6_addr16[1] = htons(ifp->if_index); } /* * See if the membership already exists. */ LIST_FOREACH(imm, &im6o->im6o_memberships, i6mm_chain) if (imm->i6mm_maddr->in6m_ifidx == ifp->if_index && IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr, &mreq->ipv6mr_multiaddr)) break; if (imm != NULL) { if_put(ifp); error = EADDRINUSE; break; } /* * Everything looks good; add a new record to the multicast * address list for the given interface. */ imm = in6_joingroup(ifp, &mreq->ipv6mr_multiaddr, &error); if_put(ifp); if (!imm) break; LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain); break; case IPV6_LEAVE_GROUP: /* * Drop a multicast group membership. * Group must be a valid IP6 multicast address. */ if (m == NULL || m->m_len != sizeof(struct ipv6_mreq)) { error = EINVAL; break; } mreq = mtod(m, struct ipv6_mreq *); if (IN6_IS_ADDR_UNSPECIFIED(&mreq->ipv6mr_multiaddr)) { if (suser(p)) { error = EACCES; break; } } else if (!IN6_IS_ADDR_MULTICAST(&mreq->ipv6mr_multiaddr)) { error = EINVAL; break; } /* * Put interface index into the multicast address, * if the address has link-local scope. */ if (IN6_IS_ADDR_MC_LINKLOCAL(&mreq->ipv6mr_multiaddr)) { mreq->ipv6mr_multiaddr.s6_addr16[1] = htons(mreq->ipv6mr_interface); } /* * If an interface address was specified, get a pointer * to its ifnet structure. */ if (mreq->ipv6mr_interface == 0) ifp = NULL; else { ifp = if_get(mreq->ipv6mr_interface); if (ifp == NULL) { error = ENXIO; /* XXX EINVAL? */ break; } } /* * Find the membership in the membership list. */ LIST_FOREACH(imm, &im6o->im6o_memberships, i6mm_chain) { if ((ifp == NULL || imm->i6mm_maddr->in6m_ifidx == ifp->if_index) && IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr, &mreq->ipv6mr_multiaddr)) break; } if_put(ifp); if (imm == NULL) { /* Unable to resolve interface */ error = EADDRNOTAVAIL; break; } /* * Give up the multicast address record to which the * membership points. */ LIST_REMOVE(imm, i6mm_chain); in6_leavegroup(imm); break; default: error = EOPNOTSUPP; break; } /* * If all options have default values, no need to keep the option * structure. */ if (im6o->im6o_ifidx == 0 && im6o->im6o_hlim == ip6_defmcasthlim && im6o->im6o_loop == IPV6_DEFAULT_MULTICAST_LOOP && LIST_EMPTY(&im6o->im6o_memberships)) { free(*im6op, M_IPMOPTS, sizeof(**im6op)); *im6op = NULL; } return (error); } /* * Return the IP6 multicast options in response to user getsockopt(). */ int ip6_getmoptions(int optname, struct ip6_moptions *im6o, struct mbuf *m) { u_int *hlim, *loop, *ifindex; switch (optname) { case IPV6_MULTICAST_IF: ifindex = mtod(m, u_int *); m->m_len = sizeof(u_int); if (im6o == NULL || im6o->im6o_ifidx == 0) *ifindex = 0; else *ifindex = im6o->im6o_ifidx; return (0); case IPV6_MULTICAST_HOPS: hlim = mtod(m, u_int *); m->m_len = sizeof(u_int); if (im6o == NULL) *hlim = ip6_defmcasthlim; else *hlim = im6o->im6o_hlim; return (0); case IPV6_MULTICAST_LOOP: loop = mtod(m, u_int *); m->m_len = sizeof(u_int); if (im6o == NULL) *loop = ip6_defmcasthlim; else *loop = im6o->im6o_loop; return (0); default: return (EOPNOTSUPP); } } /* * Discard the IP6 multicast options. */ void ip6_freemoptions(struct ip6_moptions *im6o) { struct in6_multi_mship *imm; if (im6o == NULL) return; while (!LIST_EMPTY(&im6o->im6o_memberships)) { imm = LIST_FIRST(&im6o->im6o_memberships); LIST_REMOVE(imm, i6mm_chain); in6_leavegroup(imm); } free(im6o, M_IPMOPTS, sizeof(*im6o)); } /* * Set IPv6 outgoing packet options based on advanced API. */ int ip6_setpktopts(struct mbuf *control, struct ip6_pktopts *opt, struct ip6_pktopts *stickyopt, int priv, int uproto) { u_int clen; struct cmsghdr *cm = 0; caddr_t cmsgs; int error; if (control == NULL || opt == NULL) return (EINVAL); ip6_initpktopts(opt); if (stickyopt) { int error; /* * If stickyopt is provided, make a local copy of the options * for this particular packet, then override them by ancillary * objects. * XXX: copypktopts() does not copy the cached route to a next * hop (if any). This is not very good in terms of efficiency, * but we can allow this since this option should be rarely * used. */ if ((error = copypktopts(opt, stickyopt)) != 0) return (error); } /* * XXX: Currently, we assume all the optional information is stored * in a single mbuf. */ if (control->m_next) return (EINVAL); clen = control->m_len; cmsgs = mtod(control, caddr_t); do { if (clen < CMSG_LEN(0)) return (EINVAL); cm = (struct cmsghdr *)cmsgs; if (cm->cmsg_len < CMSG_LEN(0) || cm->cmsg_len > clen || CMSG_ALIGN(cm->cmsg_len) > clen) return (EINVAL); if (cm->cmsg_level == IPPROTO_IPV6) { error = ip6_setpktopt(cm->cmsg_type, CMSG_DATA(cm), cm->cmsg_len - CMSG_LEN(0), opt, priv, 0, uproto); if (error) return (error); } clen -= CMSG_ALIGN(cm->cmsg_len); cmsgs += CMSG_ALIGN(cm->cmsg_len); } while (clen); return (0); } /* * Set a particular packet option, as a sticky option or an ancillary data * item. "len" can be 0 only when it's a sticky option. */ int ip6_setpktopt(int optname, u_char *buf, int len, struct ip6_pktopts *opt, int priv, int sticky, int uproto) { int minmtupolicy; switch (optname) { case IPV6_PKTINFO: { struct ifnet *ifp = NULL; struct in6_pktinfo *pktinfo; if (len != sizeof(struct in6_pktinfo)) return (EINVAL); pktinfo = (struct in6_pktinfo *)buf; /* * An application can clear any sticky IPV6_PKTINFO option by * doing a "regular" setsockopt with ipi6_addr being * in6addr_any and ipi6_ifindex being zero. * [RFC 3542, Section 6] */ if (opt->ip6po_pktinfo && pktinfo->ipi6_ifindex == 0 && IN6_IS_ADDR_UNSPECIFIED(&pktinfo->ipi6_addr)) { ip6_clearpktopts(opt, optname); break; } if (uproto == IPPROTO_TCP && sticky && !IN6_IS_ADDR_UNSPECIFIED(&pktinfo->ipi6_addr)) { return (EINVAL); } if (pktinfo->ipi6_ifindex) { ifp = if_get(pktinfo->ipi6_ifindex); if (ifp == NULL) return (ENXIO); if_put(ifp); } /* * We store the address anyway, and let in6_selectsrc() * validate the specified address. This is because ipi6_addr * may not have enough information about its scope zone, and * we may need additional information (such as outgoing * interface or the scope zone of a destination address) to * disambiguate the scope. * XXX: the delay of the validation may confuse the * application when it is used as a sticky option. */ if (opt->ip6po_pktinfo == NULL) { opt->ip6po_pktinfo = malloc(sizeof(*pktinfo), M_IP6OPT, M_NOWAIT); if (opt->ip6po_pktinfo == NULL) return (ENOBUFS); } bcopy(pktinfo, opt->ip6po_pktinfo, sizeof(*pktinfo)); break; } case IPV6_HOPLIMIT: { int *hlimp; /* * RFC 3542 deprecated the usage of sticky IPV6_HOPLIMIT * to simplify the ordering among hoplimit options. */ if (sticky) return (ENOPROTOOPT); if (len != sizeof(int)) return (EINVAL); hlimp = (int *)buf; if (*hlimp < -1 || *hlimp > 255) return (EINVAL); opt->ip6po_hlim = *hlimp; break; } case IPV6_TCLASS: { int tclass; if (len != sizeof(int)) return (EINVAL); tclass = *(int *)buf; if (tclass < -1 || tclass > 255) return (EINVAL); opt->ip6po_tclass = tclass; break; } case IPV6_HOPOPTS: { struct ip6_hbh *hbh; int hbhlen; /* * XXX: We don't allow a non-privileged user to set ANY HbH * options, since per-option restriction has too much * overhead. */ if (!priv) return (EPERM); if (len == 0) { ip6_clearpktopts(opt, IPV6_HOPOPTS); break; /* just remove the option */ } /* message length validation */ if (len < sizeof(struct ip6_hbh)) return (EINVAL); hbh = (struct ip6_hbh *)buf; hbhlen = (hbh->ip6h_len + 1) << 3; if (len != hbhlen) return (EINVAL); /* turn off the previous option, then set the new option. */ ip6_clearpktopts(opt, IPV6_HOPOPTS); opt->ip6po_hbh = malloc(hbhlen, M_IP6OPT, M_NOWAIT); if (opt->ip6po_hbh == NULL) return (ENOBUFS); memcpy(opt->ip6po_hbh, hbh, hbhlen); break; } case IPV6_DSTOPTS: case IPV6_RTHDRDSTOPTS: { struct ip6_dest *dest, **newdest = NULL; int destlen; if (!priv) /* XXX: see the comment for IPV6_HOPOPTS */ return (EPERM); if (len == 0) { ip6_clearpktopts(opt, optname); break; /* just remove the option */ } /* message length validation */ if (len < sizeof(struct ip6_dest)) return (EINVAL); dest = (struct ip6_dest *)buf; destlen = (dest->ip6d_len + 1) << 3; if (len != destlen) return (EINVAL); /* * Determine the position that the destination options header * should be inserted; before or after the routing header. */ switch (optname) { case IPV6_RTHDRDSTOPTS: newdest = &opt->ip6po_dest1; break; case IPV6_DSTOPTS: newdest = &opt->ip6po_dest2; break; } /* turn off the previous option, then set the new option. */ ip6_clearpktopts(opt, optname); *newdest = malloc(destlen, M_IP6OPT, M_NOWAIT); if (*newdest == NULL) return (ENOBUFS); memcpy(*newdest, dest, destlen); break; } case IPV6_RTHDR: { struct ip6_rthdr *rth; int rthlen; if (len == 0) { ip6_clearpktopts(opt, IPV6_RTHDR); break; /* just remove the option */ } /* message length validation */ if (len < sizeof(struct ip6_rthdr)) return (EINVAL); rth = (struct ip6_rthdr *)buf; rthlen = (rth->ip6r_len + 1) << 3; if (len != rthlen) return (EINVAL); switch (rth->ip6r_type) { case IPV6_RTHDR_TYPE_0: if (rth->ip6r_len == 0) /* must contain one addr */ return (EINVAL); if (rth->ip6r_len % 2) /* length must be even */ return (EINVAL); if (rth->ip6r_len / 2 != rth->ip6r_segleft) return (EINVAL); break; default: return (EINVAL); /* not supported */ } /* turn off the previous option */ ip6_clearpktopts(opt, IPV6_RTHDR); opt->ip6po_rthdr = malloc(rthlen, M_IP6OPT, M_NOWAIT); if (opt->ip6po_rthdr == NULL) return (ENOBUFS); memcpy(opt->ip6po_rthdr, rth, rthlen); break; } case IPV6_USE_MIN_MTU: if (len != sizeof(int)) return (EINVAL); minmtupolicy = *(int *)buf; if (minmtupolicy != IP6PO_MINMTU_MCASTONLY && minmtupolicy != IP6PO_MINMTU_DISABLE && minmtupolicy != IP6PO_MINMTU_ALL) { return (EINVAL); } opt->ip6po_minmtu = minmtupolicy; break; case IPV6_DONTFRAG: if (len != sizeof(int)) return (EINVAL); if (uproto == IPPROTO_TCP || *(int *)buf == 0) { /* * we ignore this option for TCP sockets. * (RFC3542 leaves this case unspecified.) */ opt->ip6po_flags &= ~IP6PO_DONTFRAG; } else opt->ip6po_flags |= IP6PO_DONTFRAG; break; default: return (ENOPROTOOPT); } /* end of switch */ return (0); } /* * Routine called from ip6_output() to loop back a copy of an IP6 multicast * packet to the input queue of a specified interface. */ void ip6_mloopback(struct ifnet *ifp, struct mbuf *m, struct sockaddr_in6 *dst) { struct mbuf *copym; struct ip6_hdr *ip6; /* * Duplicate the packet. */ copym = m_copym(m, 0, M_COPYALL, M_NOWAIT); if (copym == NULL) return; /* * Make sure to deep-copy IPv6 header portion in case the data * is in an mbuf cluster, so that we can safely override the IPv6 * header portion later. */ if ((copym->m_flags & M_EXT) != 0 || copym->m_len < sizeof(struct ip6_hdr)) { copym = m_pullup(copym, sizeof(struct ip6_hdr)); if (copym == NULL) return; } #ifdef DIAGNOSTIC if (copym->m_len < sizeof(*ip6)) { m_freem(copym); return; } #endif ip6 = mtod(copym, struct ip6_hdr *); if (IN6_IS_SCOPE_EMBED(&ip6->ip6_src)) ip6->ip6_src.s6_addr16[1] = 0; if (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst)) ip6->ip6_dst.s6_addr16[1] = 0; if_input_local(ifp, copym, dst->sin6_family); } /* * Chop IPv6 header off from the payload. */ int ip6_splithdr(struct mbuf *m, struct ip6_exthdrs *exthdrs) { struct mbuf *mh; struct ip6_hdr *ip6; ip6 = mtod(m, struct ip6_hdr *); if (m->m_len > sizeof(*ip6)) { MGET(mh, M_DONTWAIT, MT_HEADER); if (mh == NULL) { m_freem(m); return ENOBUFS; } M_MOVE_PKTHDR(mh, m); m_align(mh, sizeof(*ip6)); m->m_len -= sizeof(*ip6); m->m_data += sizeof(*ip6); mh->m_next = m; m = mh; m->m_len = sizeof(*ip6); bcopy((caddr_t)ip6, mtod(m, caddr_t), sizeof(*ip6)); } exthdrs->ip6e_ip6 = m; return 0; } u_int32_t ip6_randomid(void) { return idgen32(&ip6_id_ctx); } void ip6_randomid_init(void) { idgen32_init(&ip6_id_ctx); } /* * Compute significant parts of the IPv6 checksum pseudo-header * for use in a delayed TCP/UDP checksum calculation. */ static __inline u_int16_t __attribute__((__unused__)) in6_cksum_phdr(const struct in6_addr *src, const struct in6_addr *dst, u_int32_t len, u_int32_t nxt) { u_int32_t sum = 0; const u_int16_t *w; w = (const u_int16_t *) src; sum += w[0]; if (!IN6_IS_SCOPE_EMBED(src)) sum += w[1]; sum += w[2]; sum += w[3]; sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; w = (const u_int16_t *) dst; sum += w[0]; if (!IN6_IS_SCOPE_EMBED(dst)) sum += w[1]; sum += w[2]; sum += w[3]; sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; sum += (u_int16_t)(len >> 16) + (u_int16_t)(len /*& 0xffff*/); sum += (u_int16_t)(nxt >> 16) + (u_int16_t)(nxt /*& 0xffff*/); sum = (u_int16_t)(sum >> 16) + (u_int16_t)(sum /*& 0xffff*/); if (sum > 0xffff) sum -= 0xffff; return (sum); } /* * Process a delayed payload checksum calculation. */ void in6_delayed_cksum(struct mbuf *m, u_int8_t nxt) { int nxtp, offset; u_int16_t csum; offset = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxtp); if (offset <= 0 || nxtp != nxt) /* If the desired next protocol isn't found, punt. */ return; csum = (u_int16_t)(in6_cksum(m, 0, offset, m->m_pkthdr.len - offset)); switch (nxt) { case IPPROTO_TCP: offset += offsetof(struct tcphdr, th_sum); break; case IPPROTO_UDP: offset += offsetof(struct udphdr, uh_sum); if (csum == 0) csum = 0xffff; break; case IPPROTO_ICMPV6: offset += offsetof(struct icmp6_hdr, icmp6_cksum); break; } if ((offset + sizeof(u_int16_t)) > m->m_len) m_copyback(m, offset, sizeof(csum), &csum, M_NOWAIT); else *(u_int16_t *)(mtod(m, caddr_t) + offset) = csum; } void in6_proto_cksum_out(struct mbuf *m, struct ifnet *ifp) { struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); /* some hw and in6_delayed_cksum need the pseudo header cksum */ if (m->m_pkthdr.csum_flags & (M_TCP_CSUM_OUT|M_UDP_CSUM_OUT|M_ICMP_CSUM_OUT)) { int nxt, offset; u_int16_t csum; offset = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt); if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO) && in_ifcap_cksum(m, ifp, IFCAP_TSOv6)) { csum = in6_cksum_phdr(&ip6->ip6_src, &ip6->ip6_dst, htonl(0), htonl(nxt)); } else { csum = in6_cksum_phdr(&ip6->ip6_src, &ip6->ip6_dst, htonl(m->m_pkthdr.len - offset), htonl(nxt)); } if (nxt == IPPROTO_TCP) offset += offsetof(struct tcphdr, th_sum); else if (nxt == IPPROTO_UDP) offset += offsetof(struct udphdr, uh_sum); else if (nxt == IPPROTO_ICMPV6) offset += offsetof(struct icmp6_hdr, icmp6_cksum); if ((offset + sizeof(u_int16_t)) > m->m_len) m_copyback(m, offset, sizeof(csum), &csum, M_NOWAIT); else *(u_int16_t *)(mtod(m, caddr_t) + offset) = csum; } if (m->m_pkthdr.csum_flags & M_TCP_CSUM_OUT) { if (!ifp || !(ifp->if_capabilities & IFCAP_CSUM_TCPv6) || ip6->ip6_nxt != IPPROTO_TCP || ifp->if_bridgeidx != 0) { tcpstat_inc(tcps_outswcsum); in6_delayed_cksum(m, IPPROTO_TCP); m->m_pkthdr.csum_flags &= ~M_TCP_CSUM_OUT; /* Clear */ } } else if (m->m_pkthdr.csum_flags & M_UDP_CSUM_OUT) { if (!ifp || !(ifp->if_capabilities & IFCAP_CSUM_UDPv6) || ip6->ip6_nxt != IPPROTO_UDP || ifp->if_bridgeidx != 0) { udpstat_inc(udps_outswcsum); in6_delayed_cksum(m, IPPROTO_UDP); m->m_pkthdr.csum_flags &= ~M_UDP_CSUM_OUT; /* Clear */ } } else if (m->m_pkthdr.csum_flags & M_ICMP_CSUM_OUT) { in6_delayed_cksum(m, IPPROTO_ICMPV6); m->m_pkthdr.csum_flags &= ~M_ICMP_CSUM_OUT; /* Clear */ } } #ifdef IPSEC int ip6_output_ipsec_lookup(struct mbuf *m, const struct ipsec_level *seclevel, struct tdb **tdbout) { struct tdb *tdb; struct m_tag *mtag; struct tdb_ident *tdbi; int error; /* * Check if there was an outgoing SA bound to the flow * from a transport protocol. */ /* Do we have any pending SAs to apply ? */ error = ipsp_spd_lookup(m, AF_INET6, sizeof(struct ip6_hdr), IPSP_DIRECTION_OUT, NULL, seclevel, &tdb, NULL); if (error || tdb == NULL) { *tdbout = NULL; return error; } /* Loop detection */ for (mtag = m_tag_first(m); mtag != NULL; mtag = m_tag_next(m, mtag)) { if (mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_DONE) continue; tdbi = (struct tdb_ident *)(mtag + 1); if (tdbi->spi == tdb->tdb_spi && tdbi->proto == tdb->tdb_sproto && tdbi->rdomain == tdb->tdb_rdomain && !memcmp(&tdbi->dst, &tdb->tdb_dst, sizeof(union sockaddr_union))) { /* no IPsec needed */ tdb_unref(tdb); *tdbout = NULL; return 0; } } *tdbout = tdb; return 0; } int ip6_output_ipsec_pmtu_update(struct tdb *tdb, struct route *ro, struct in6_addr *dst, int ifidx, int rtableid, int transportmode) { struct rtentry *rt = NULL; int rt_mtucloned = 0; /* Find a host route to store the mtu in */ if (ro != NULL) rt = ro->ro_rt; /* but don't add a PMTU route for transport mode SAs */ if (transportmode) rt = NULL; else if (rt == NULL || (rt->rt_flags & RTF_HOST) == 0) { struct sockaddr_in6 sin6; int error; memset(&sin6, 0, sizeof(sin6)); sin6.sin6_family = AF_INET6; sin6.sin6_len = sizeof(sin6); sin6.sin6_addr = *dst; sin6.sin6_scope_id = in6_addr2scopeid(ifidx, dst); error = in6_embedscope(dst, &sin6, NULL, NULL); if (error) { /* should be impossible */ return error; } rt = icmp6_mtudisc_clone(&sin6, rtableid, 1); rt_mtucloned = 1; } DPRINTF("spi %08x mtu %d rt %p cloned %d", ntohl(tdb->tdb_spi), tdb->tdb_mtu, rt, rt_mtucloned); if (rt != NULL) { rt->rt_mtu = tdb->tdb_mtu; if (ro != NULL && ro->ro_rt != NULL) { rtfree(ro->ro_rt); ro->ro_rt = rtalloc(&ro->ro_dstsa, RT_RESOLVE, rtableid); } if (rt_mtucloned) rtfree(rt); } return 0; } int ip6_output_ipsec_send(struct tdb *tdb, struct mbuf *m, struct route *ro, int tunalready, int fwd) { struct mbuf_list ml; struct ifnet *encif = NULL; struct ip6_hdr *ip6; struct in6_addr dst; u_int len; int error, ifidx, rtableid, tso = 0; #if NPF > 0 /* * Packet filter */ if ((encif = enc_getif(tdb->tdb_rdomain, tdb->tdb_tap)) == NULL || pf_test(AF_INET6, fwd ? PF_FWD : PF_OUT, encif, &m) != PF_PASS) { m_freem(m); return EACCES; } if (m == NULL) return 0; /* * PF_TAG_REROUTE handling or not... * Packet is entering IPsec so the routing is * already overruled by the IPsec policy. * Until now the change was not reconsidered. * What's the behaviour? */ #endif /* Check if we can chop the TCP packet */ ip6 = mtod(m, struct ip6_hdr *); if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO) && m->m_pkthdr.ph_mss <= tdb->tdb_mtu) { tso = 1; len = m->m_pkthdr.ph_mss; } else len = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen); /* Check if we are allowed to fragment */ dst = ip6->ip6_dst; ifidx = m->m_pkthdr.ph_ifidx; rtableid = m->m_pkthdr.ph_rtableid; if (ip_mtudisc && tdb->tdb_mtu && len > tdb->tdb_mtu && tdb->tdb_mtutimeout > gettime()) { int transportmode; transportmode = (tdb->tdb_dst.sa.sa_family == AF_INET6) && (IN6_ARE_ADDR_EQUAL(&tdb->tdb_dst.sin6.sin6_addr, &dst)); error = ip6_output_ipsec_pmtu_update(tdb, ro, &dst, ifidx, rtableid, transportmode); if (error) { ipsecstat_inc(ipsec_odrops); tdbstat_inc(tdb, tdb_odrops); m_freem(m); return error; } ipsec_adjust_mtu(m, tdb->tdb_mtu); m_freem(m); return EMSGSIZE; } /* propagate don't fragment for v6-over-v6 */ if (ip_mtudisc) SET(m->m_pkthdr.csum_flags, M_IPV6_DF_OUT); /* * Clear these -- they'll be set in the recursive invocation * as needed. */ m->m_flags &= ~(M_BCAST | M_MCAST); if (tso) { error = tcp_chopper(m, &ml, encif, len); if (error) goto done; } else { CLR(m->m_pkthdr.csum_flags, M_TCP_TSO); in6_proto_cksum_out(m, encif); ml_init(&ml); ml_enqueue(&ml, m); } KERNEL_LOCK(); while ((m = ml_dequeue(&ml)) != NULL) { /* Callee frees mbuf */ error = ipsp_process_packet(m, tdb, AF_INET6, tunalready); if (error) break; } KERNEL_UNLOCK(); done: if (error) { ml_purge(&ml); ipsecstat_inc(ipsec_odrops); tdbstat_inc(tdb, tdb_odrops); } if (!error && tso) tcpstat_inc(tcps_outswtso); if (ip_mtudisc && error == EMSGSIZE) ip6_output_ipsec_pmtu_update(tdb, ro, &dst, ifidx, rtableid, 0); return error; } #endif /* IPSEC */
1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 /* $OpenBSD: usb.c,v 1.131 2024/05/23 03:21:09 jsg Exp $ */ /* $NetBSD: usb.c,v 1.77 2003/01/01 00:10:26 thorpej Exp $ */ /* * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Lennart Augustsson (lennart@augustsson.net) at * Carlstedt Research & Technology. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * USB specifications and other documentation can be found at * https://www.usb.org/documents */ #include "ohci.h" #include "uhci.h" #include "ehci.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/device.h> #include <sys/kthread.h> #include <sys/conf.h> #include <sys/fcntl.h> #include <sys/time.h> #include <sys/rwlock.h> #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> #include <machine/bus.h> #include <dev/usb/usbdivar.h> #include <dev/usb/usb_mem.h> #include <dev/usb/usbpcap.h> #ifdef USB_DEBUG #define DPRINTF(x) do { if (usbdebug) printf x; } while (0) #define DPRINTFN(n,x) do { if (usbdebug>(n)) printf x; } while (0) int usbdebug = 0; #if defined(UHCI_DEBUG) && NUHCI > 0 extern int uhcidebug; #endif #if defined(OHCI_DEBUG) && NOHCI > 0 extern int ohcidebug; #endif #if defined(EHCI_DEBUG) && NEHCI > 0 extern int ehcidebug; #endif /* * 0 - do usual exploration * !0 - do no exploration */ int usb_noexplore = 0; #else #define DPRINTF(x) #define DPRINTFN(n,x) #endif struct usb_softc { struct device sc_dev; /* base device */ struct usbd_bus *sc_bus; /* USB controller */ struct usbd_port sc_port; /* dummy port for root hub */ int sc_speed; struct usb_task sc_explore_task; struct timeval sc_ptime; }; struct rwlock usbpalock; TAILQ_HEAD(, usb_task) usb_abort_tasks; TAILQ_HEAD(, usb_task) usb_explore_tasks; TAILQ_HEAD(, usb_task) usb_generic_tasks; static int usb_nbuses = 0; static int usb_run_tasks, usb_run_abort_tasks; int explore_pending; const char *usbrev_str[] = USBREV_STR; void usb_explore(void *); void usb_create_task_threads(void *); void usb_task_thread(void *); struct proc *usb_task_thread_proc = NULL; void usb_abort_task_thread(void *); struct proc *usb_abort_task_thread_proc = NULL; void usb_fill_udc_task(void *); void usb_fill_udf_task(void *); int usb_match(struct device *, void *, void *); void usb_attach(struct device *, struct device *, void *); int usb_detach(struct device *, int); int usb_activate(struct device *, int); int usb_attach_roothub(struct usb_softc *); void usb_detach_roothub(struct usb_softc *); struct cfdriver usb_cd = { NULL, "usb", DV_DULL }; const struct cfattach usb_ca = { sizeof(struct usb_softc), usb_match, usb_attach, usb_detach, usb_activate, }; int usb_match(struct device *parent, void *match, void *aux) { return (1); } void usb_attach(struct device *parent, struct device *self, void *aux) { struct usb_softc *sc = (struct usb_softc *)self; int usbrev; if (usb_nbuses == 0) { rw_init(&usbpalock, "usbpalock"); TAILQ_INIT(&usb_abort_tasks); TAILQ_INIT(&usb_explore_tasks); TAILQ_INIT(&usb_generic_tasks); usb_run_tasks = usb_run_abort_tasks = 1; kthread_create_deferred(usb_create_task_threads, NULL); } usb_nbuses++; sc->sc_bus = aux; sc->sc_bus->usbctl = self; sc->sc_port.power = USB_MAX_POWER; usbrev = sc->sc_bus->usbrev; printf(": USB revision %s", usbrev_str[usbrev]); switch (usbrev) { case USBREV_1_0: case USBREV_1_1: sc->sc_speed = USB_SPEED_FULL; break; case USBREV_2_0: sc->sc_speed = USB_SPEED_HIGH; break; case USBREV_3_0: sc->sc_speed = USB_SPEED_SUPER; break; default: printf(", not supported\n"); sc->sc_bus->dying = 1; return; } printf("\n"); #if NBPFILTER > 0 sc->sc_bus->bpfif = bpfsattach(&sc->sc_bus->bpf, sc->sc_dev.dv_xname, DLT_USBPCAP, sizeof(struct usbpcap_pkt_hdr)); #endif /* Make sure not to use tsleep() if we are cold booting. */ if (cold) sc->sc_bus->use_polling++; /* Don't let hub interrupts cause explore until ready. */ sc->sc_bus->flags |= USB_BUS_CONFIG_PENDING; /* explore task */ usb_init_task(&sc->sc_explore_task, usb_explore, sc, USB_TASK_TYPE_EXPLORE); sc->sc_bus->soft = softintr_establish(IPL_SOFTUSB, sc->sc_bus->methods->soft_intr, sc->sc_bus); if (sc->sc_bus->soft == NULL) { printf("%s: can't register softintr\n", sc->sc_dev.dv_xname); sc->sc_bus->dying = 1; return; } if (!usb_attach_roothub(sc)) { struct usbd_device *dev = sc->sc_bus->root_hub; #if 1 /* * Turning this code off will delay attachment of USB devices * until the USB task thread is running, which means that * the keyboard will not work until after cold boot. */ if (cold && (sc->sc_dev.dv_cfdata->cf_flags & 1)) dev->hub->explore(sc->sc_bus->root_hub); #endif } if (cold) sc->sc_bus->use_polling--; if (!sc->sc_bus->dying) { getmicrouptime(&sc->sc_ptime); if (sc->sc_bus->usbrev == USBREV_2_0) explore_pending++; config_pending_incr(); usb_needs_explore(sc->sc_bus->root_hub, 1); } } int usb_attach_roothub(struct usb_softc *sc) { struct usbd_device *dev; if (usbd_new_device(&sc->sc_dev, sc->sc_bus, 0, sc->sc_speed, 0, &sc->sc_port)) { printf("%s: root hub problem\n", sc->sc_dev.dv_xname); sc->sc_bus->dying = 1; return (1); } dev = sc->sc_port.device; if (dev->hub == NULL) { printf("%s: root device is not a hub\n", sc->sc_dev.dv_xname); sc->sc_bus->dying = 1; return (1); } sc->sc_bus->root_hub = dev; return (0); } void usb_detach_roothub(struct usb_softc *sc) { /* * To avoid races with the usb task thread, mark the root hub * as disconnecting and schedule an exploration task to detach * it. */ sc->sc_bus->flags |= USB_BUS_DISCONNECTING; /* * Reset the dying flag in case it has been set by the interrupt * handler when unplugging an HC card otherwise the task wont be * scheduled. This is safe since a dead HC should not trigger * new interrupt. */ sc->sc_bus->dying = 0; usb_needs_explore(sc->sc_bus->root_hub, 0); usb_wait_task(sc->sc_bus->root_hub, &sc->sc_explore_task); sc->sc_bus->root_hub = NULL; } void usb_create_task_threads(void *arg) { if (kthread_create(usb_abort_task_thread, NULL, &usb_abort_task_thread_proc, "usbatsk")) panic("unable to create usb abort task thread"); if (kthread_create(usb_task_thread, NULL, &usb_task_thread_proc, "usbtask")) panic("unable to create usb task thread"); } /* * Add a task to be performed by the task thread. This function can be * called from any context and the task will be executed in a process * context ASAP. */ void usb_add_task(struct usbd_device *dev, struct usb_task *task) { int s; /* * If the thread detaching ``dev'' is sleeping, waiting * for all submitted transfers to finish, we must be able * to enqueue abort tasks. Otherwise timeouts can't give * back submitted transfers to the stack. */ if (usbd_is_dying(dev) && (task->type != USB_TASK_TYPE_ABORT)) return; DPRINTFN(2,("%s: task=%p state=%d type=%d\n", __func__, task, task->state, task->type)); s = splusb(); if (!(task->state & USB_TASK_STATE_ONQ)) { switch (task->type) { case USB_TASK_TYPE_ABORT: TAILQ_INSERT_TAIL(&usb_abort_tasks, task, next); break; case USB_TASK_TYPE_EXPLORE: TAILQ_INSERT_TAIL(&usb_explore_tasks, task, next); break; case USB_TASK_TYPE_GENERIC: TAILQ_INSERT_TAIL(&usb_generic_tasks, task, next); break; } task->state |= USB_TASK_STATE_ONQ; task->dev = dev; } if (task->type == USB_TASK_TYPE_ABORT) wakeup(&usb_run_abort_tasks); else wakeup(&usb_run_tasks); splx(s); } void usb_rem_task(struct usbd_device *dev, struct usb_task *task) { int s; if (!(task->state & USB_TASK_STATE_ONQ)) return; DPRINTFN(2,("%s: task=%p state=%d type=%d\n", __func__, task, task->state, task->type)); s = splusb(); switch (task->type) { case USB_TASK_TYPE_ABORT: TAILQ_REMOVE(&usb_abort_tasks, task, next); break; case USB_TASK_TYPE_EXPLORE: TAILQ_REMOVE(&usb_explore_tasks, task, next); break; case USB_TASK_TYPE_GENERIC: TAILQ_REMOVE(&usb_generic_tasks, task, next); break; } task->state &= ~USB_TASK_STATE_ONQ; if (task->state == USB_TASK_STATE_NONE) wakeup(task); splx(s); } void usb_wait_task(struct usbd_device *dev, struct usb_task *task) { int s; DPRINTFN(2,("%s: task=%p state=%d type=%d\n", __func__, task, task->state, task->type)); if (task->state == USB_TASK_STATE_NONE) return; s = splusb(); while (task->state != USB_TASK_STATE_NONE) { DPRINTF(("%s: waiting for task to complete\n", __func__)); tsleep_nsec(task, PWAIT, "endtask", INFSLP); } splx(s); } void usb_rem_wait_task(struct usbd_device *dev, struct usb_task *task) { usb_rem_task(dev, task); usb_wait_task(dev, task); } void usb_task_thread(void *arg) { struct usb_task *task; int s; DPRINTF(("usb_task_thread: start\n")); s = splusb(); while (usb_run_tasks) { if ((task = TAILQ_FIRST(&usb_explore_tasks)) != NULL) TAILQ_REMOVE(&usb_explore_tasks, task, next); else if ((task = TAILQ_FIRST(&usb_generic_tasks)) != NULL) TAILQ_REMOVE(&usb_generic_tasks, task, next); else { tsleep_nsec(&usb_run_tasks, PWAIT, "usbtsk", INFSLP); continue; } /* * Set the state run bit before clearing the onq bit. * This avoids state == none between dequeue and * execution, which could cause usb_wait_task() to do * the wrong thing. */ task->state |= USB_TASK_STATE_RUN; task->state &= ~USB_TASK_STATE_ONQ; /* Don't actually execute the task if dying. */ if (!usbd_is_dying(task->dev)) { splx(s); task->fun(task->arg); s = splusb(); } task->state &= ~USB_TASK_STATE_RUN; if (task->state == USB_TASK_STATE_NONE) wakeup(task); } splx(s); kthread_exit(0); } /* * This thread is ONLY for the HCI drivers to be able to abort xfers. * Synchronous xfers sleep the task thread, so the aborts need to happen * in a different thread. */ void usb_abort_task_thread(void *arg) { struct usb_task *task; int s; DPRINTF(("usb_xfer_abort_thread: start\n")); s = splusb(); while (usb_run_abort_tasks) { if ((task = TAILQ_FIRST(&usb_abort_tasks)) != NULL) TAILQ_REMOVE(&usb_abort_tasks, task, next); else { tsleep_nsec(&usb_run_abort_tasks, PWAIT, "usbatsk", INFSLP); continue; } /* * Set the state run bit before clearing the onq bit. * This avoids state == none between dequeue and * execution, which could cause usb_wait_task() to do * the wrong thing. */ task->state |= USB_TASK_STATE_RUN; task->state &= ~USB_TASK_STATE_ONQ; splx(s); task->fun(task->arg); s = splusb(); task->state &= ~USB_TASK_STATE_RUN; if (task->state == USB_TASK_STATE_NONE) wakeup(task); } splx(s); kthread_exit(0); } int usbctlprint(void *aux, const char *pnp) { /* only "usb"es can attach to host controllers */ if (pnp) printf("usb at %s", pnp); return (UNCONF); } int usbopen(dev_t dev, int flag, int mode, struct proc *p) { int unit = minor(dev); struct usb_softc *sc; if (unit >= usb_cd.cd_ndevs) return (ENXIO); sc = usb_cd.cd_devs[unit]; if (sc == NULL) return (ENXIO); if (sc->sc_bus->dying) return (EIO); return (0); } int usbclose(dev_t dev, int flag, int mode, struct proc *p) { return (0); } void usb_fill_udc_task(void *arg) { struct usb_device_cdesc *udc = (struct usb_device_cdesc *)arg; struct usb_softc *sc; struct usbd_device *dev; int addr = udc->udc_addr, cdesc_len; usb_config_descriptor_t *cdesc; /* check that the bus and device are still present */ if (udc->udc_bus >= usb_cd.cd_ndevs) return; sc = usb_cd.cd_devs[udc->udc_bus]; if (sc == NULL) return; dev = sc->sc_bus->devices[udc->udc_addr]; if (dev == NULL) return; cdesc = usbd_get_cdesc(sc->sc_bus->devices[addr], udc->udc_config_index, &cdesc_len); if (cdesc == NULL) return; udc->udc_desc = *cdesc; free(cdesc, M_TEMP, cdesc_len); } void usb_fill_udf_task(void *arg) { struct usb_device_fdesc *udf = (struct usb_device_fdesc *)arg; struct usb_softc *sc; struct usbd_device *dev; int addr = udf->udf_addr; usb_config_descriptor_t *cdesc; /* check that the bus and device are still present */ if (udf->udf_bus >= usb_cd.cd_ndevs) return; sc = usb_cd.cd_devs[udf->udf_bus]; if (sc == NULL) return; dev = sc->sc_bus->devices[udf->udf_addr]; if (dev == NULL) return; cdesc = usbd_get_cdesc(sc->sc_bus->devices[addr], udf->udf_config_index, &udf->udf_size); udf->udf_data = (char *)cdesc; } int usbioctl(dev_t devt, u_long cmd, caddr_t data, int flag, struct proc *p) { struct usb_softc *sc; int unit = minor(devt); int error; sc = usb_cd.cd_devs[unit]; if (sc->sc_bus->dying) return (EIO); error = 0; switch (cmd) { #ifdef USB_DEBUG case USB_SETDEBUG: /* only root can access to these debug flags */ if ((error = suser(curproc)) != 0) return (error); if (!(flag & FWRITE)) return (EBADF); usbdebug = ((*(unsigned int *)data) & 0x000000ff); #if defined(UHCI_DEBUG) && NUHCI > 0 uhcidebug = ((*(unsigned int *)data) & 0x0000ff00) >> 8; #endif #if defined(OHCI_DEBUG) && NOHCI > 0 ohcidebug = ((*(unsigned int *)data) & 0x00ff0000) >> 16; #endif #if defined(EHCI_DEBUG) && NEHCI > 0 ehcidebug = ((*(unsigned int *)data) & 0xff000000) >> 24; #endif break; #endif /* USB_DEBUG */ case USB_REQUEST: { struct usb_ctl_request *ur = (void *)data; size_t len = UGETW(ur->ucr_request.wLength), mlen; struct iovec iov; struct uio uio; void *ptr = NULL; int addr = ur->ucr_addr; usbd_status err; if (!(flag & FWRITE)) return (EBADF); DPRINTF(("%s: USB_REQUEST addr=%d len=%zu\n", __func__, addr, len)); /* Avoid requests that would damage the bus integrity. */ if ((ur->ucr_request.bmRequestType == UT_WRITE_DEVICE && ur->ucr_request.bRequest == UR_SET_ADDRESS) || (ur->ucr_request.bmRequestType == UT_WRITE_DEVICE && ur->ucr_request.bRequest == UR_SET_CONFIG) || (ur->ucr_request.bmRequestType == UT_WRITE_INTERFACE && ur->ucr_request.bRequest == UR_SET_INTERFACE)) return (EINVAL); if (len > 32767) return (EINVAL); if (addr < 0 || addr >= USB_MAX_DEVICES) return (EINVAL); if (sc->sc_bus->devices[addr] == NULL) return (ENXIO); if (len != 0) { iov.iov_base = (caddr_t)ur->ucr_data; iov.iov_len = len; uio.uio_iov = &iov; uio.uio_iovcnt = 1; uio.uio_resid = len; uio.uio_offset = 0; uio.uio_segflg = UIO_USERSPACE; uio.uio_rw = ur->ucr_request.bmRequestType & UT_READ ? UIO_READ : UIO_WRITE; uio.uio_procp = p; if ((ptr = malloc(len, M_TEMP, M_NOWAIT)) == NULL) { error = ENOMEM; goto ret; } if (uio.uio_rw == UIO_WRITE) { error = uiomove(ptr, len, &uio); if (error) goto ret; } } err = usbd_do_request_flags(sc->sc_bus->devices[addr], &ur->ucr_request, ptr, ur->ucr_flags, &ur->ucr_actlen, USBD_DEFAULT_TIMEOUT); if (err) { error = EIO; goto ret; } /* Only if USBD_SHORT_XFER_OK is set. */ mlen = len; if (mlen > ur->ucr_actlen) mlen = ur->ucr_actlen; if (mlen != 0) { if (uio.uio_rw == UIO_READ) { error = uiomove(ptr, mlen, &uio); if (error) goto ret; } } ret: free(ptr, M_TEMP, len); return (error); } case USB_DEVICEINFO: { struct usb_device_info *di = (void *)data; int addr = di->udi_addr; struct usbd_device *dev; if (addr < 1 || addr >= USB_MAX_DEVICES) return (EINVAL); dev = sc->sc_bus->devices[addr]; if (dev == NULL) return (ENXIO); usbd_fill_deviceinfo(dev, di); break; } case USB_DEVICESTATS: *(struct usb_device_stats *)data = sc->sc_bus->stats; break; case USB_DEVICE_GET_DDESC: { struct usb_device_ddesc *udd = (struct usb_device_ddesc *)data; int addr = udd->udd_addr; struct usbd_device *dev; if (addr < 1 || addr >= USB_MAX_DEVICES) return (EINVAL); dev = sc->sc_bus->devices[addr]; if (dev == NULL) return (ENXIO); udd->udd_bus = unit; udd->udd_desc = *usbd_get_device_descriptor(dev); break; } case USB_DEVICE_GET_CDESC: { struct usb_device_cdesc *udc = (struct usb_device_cdesc *)data; int addr = udc->udc_addr; struct usb_task udc_task; if (addr < 1 || addr >= USB_MAX_DEVICES) return (EINVAL); if (sc->sc_bus->devices[addr] == NULL) return (ENXIO); udc->udc_bus = unit; udc->udc_desc.bLength = 0; usb_init_task(&udc_task, usb_fill_udc_task, udc, USB_TASK_TYPE_GENERIC); usb_add_task(sc->sc_bus->root_hub, &udc_task); usb_wait_task(sc->sc_bus->root_hub, &udc_task); if (udc->udc_desc.bLength == 0) return (EINVAL); break; } case USB_DEVICE_GET_FDESC: { struct usb_device_fdesc *udf = (struct usb_device_fdesc *)data; int addr = udf->udf_addr; struct usb_task udf_task; struct usb_device_fdesc save_udf; usb_config_descriptor_t *cdesc; struct iovec iov; struct uio uio; size_t len, cdesc_len; if (addr < 1 || addr >= USB_MAX_DEVICES) return (EINVAL); if (sc->sc_bus->devices[addr] == NULL) return (ENXIO); udf->udf_bus = unit; save_udf = *udf; udf->udf_data = NULL; usb_init_task(&udf_task, usb_fill_udf_task, udf, USB_TASK_TYPE_GENERIC); usb_add_task(sc->sc_bus->root_hub, &udf_task); usb_wait_task(sc->sc_bus->root_hub, &udf_task); len = cdesc_len = udf->udf_size; cdesc = (usb_config_descriptor_t *)udf->udf_data; *udf = save_udf; if (cdesc == NULL) return (EINVAL); if (len > udf->udf_size) len = udf->udf_size; iov.iov_base = (caddr_t)udf->udf_data; iov.iov_len = len; uio.uio_iov = &iov; uio.uio_iovcnt = 1; uio.uio_resid = len; uio.uio_offset = 0; uio.uio_segflg = UIO_USERSPACE; uio.uio_rw = UIO_READ; uio.uio_procp = p; error = uiomove((void *)cdesc, len, &uio); free(cdesc, M_TEMP, cdesc_len); return (error); } default: return (EINVAL); } return (0); } /* * Explore device tree from the root. We need mutual exclusion to this * hub while traversing the device tree, but this is guaranteed since this * function is only called from the task thread, with one exception: * usb_attach() calls this function, but there shouldn't be anything else * trying to explore this hub at that time. */ void usb_explore(void *v) { struct usb_softc *sc = v; struct timeval now, waited; int pwrdly, waited_ms; DPRINTFN(2,("%s: %s\n", __func__, sc->sc_dev.dv_xname)); #ifdef USB_DEBUG if (usb_noexplore) return; #endif if (sc->sc_bus->dying) return; if (sc->sc_bus->flags & USB_BUS_CONFIG_PENDING) { /* * If this is a low/full speed hub and there is a high * speed hub that hasn't explored yet, reschedule this * task, allowing the high speed explore task to run. */ if (sc->sc_bus->usbrev < USBREV_2_0 && explore_pending > 0) { usb_add_task(sc->sc_bus->root_hub, &sc->sc_explore_task); return; } /* * Wait for power to stabilize. */ getmicrouptime(&now); timersub(&now, &sc->sc_ptime, &waited); waited_ms = waited.tv_sec * 1000 + waited.tv_usec / 1000; pwrdly = sc->sc_bus->root_hub->hub->powerdelay + USB_EXTRA_POWER_UP_TIME; if (pwrdly > waited_ms) usb_delay_ms(sc->sc_bus, pwrdly - waited_ms); } if (sc->sc_bus->flags & USB_BUS_DISCONNECTING) { /* Prevent new tasks from being scheduled. */ sc->sc_bus->dying = 1; /* Make all devices disconnect. */ if (sc->sc_port.device != NULL) { usbd_detach(sc->sc_port.device, (struct device *)sc); sc->sc_port.device = NULL; } sc->sc_bus->flags &= ~USB_BUS_DISCONNECTING; } else { sc->sc_bus->root_hub->hub->explore(sc->sc_bus->root_hub); } if (sc->sc_bus->flags & USB_BUS_CONFIG_PENDING) { DPRINTF(("%s: %s: first explore done\n", __func__, sc->sc_dev.dv_xname)); if (sc->sc_bus->usbrev == USBREV_2_0 && explore_pending) explore_pending--; config_pending_decr(); sc->sc_bus->flags &= ~(USB_BUS_CONFIG_PENDING); } } void usb_needs_explore(struct usbd_device *dev, int first_explore) { struct usb_softc *usbctl = (struct usb_softc *)dev->bus->usbctl; DPRINTFN(3,("%s: %s\n", usbctl->sc_dev.dv_xname, __func__)); if (!first_explore && (dev->bus->flags & USB_BUS_CONFIG_PENDING)) { DPRINTF(("%s: %s: not exploring before first explore\n", __func__, usbctl->sc_dev.dv_xname)); return; } usb_add_task(dev, &usbctl->sc_explore_task); } void usb_needs_reattach(struct usbd_device *dev) { DPRINTFN(2,("usb_needs_reattach\n")); dev->powersrc->reattach = 1; usb_needs_explore(dev, 0); } void usb_schedsoftintr(struct usbd_bus *bus) { DPRINTFN(10,("%s: polling=%d\n", __func__, bus->use_polling)); /* In case usb(4) is disabled */ if (bus->soft == NULL) return; if (bus->use_polling) { bus->methods->soft_intr(bus); } else { softintr_schedule(bus->soft); } } int usb_activate(struct device *self, int act) { struct usb_softc *sc = (struct usb_softc *)self; int rv = 0; switch (act) { case DVACT_QUIESCE: if (sc->sc_bus->root_hub != NULL) usb_detach_roothub(sc); break; case DVACT_RESUME: sc->sc_bus->dying = 0; /* * Make sure the root hub is present before interrupts * get enabled. As long as the bus is in polling mode * it is safe to call usbd_new_device() now since root * hub transfers do not need to sleep. */ sc->sc_bus->use_polling++; if (!usb_attach_roothub(sc)) usb_needs_explore(sc->sc_bus->root_hub, 0); sc->sc_bus->use_polling--; break; default: rv = config_activate_children(self, act); break; } return (rv); } int usb_detach(struct device *self, int flags) { struct usb_softc *sc = (struct usb_softc *)self; if (sc->sc_bus->root_hub != NULL) { usb_detach_roothub(sc); if (--usb_nbuses == 0) { usb_run_tasks = usb_run_abort_tasks = 0; wakeup(&usb_run_abort_tasks); wakeup(&usb_run_tasks); } } if (sc->sc_bus->soft != NULL) { softintr_disestablish(sc->sc_bus->soft); sc->sc_bus->soft = NULL; } #if NBPFILTER > 0 bpfsdetach(sc->sc_bus->bpfif); #endif return (0); } void usb_tap(struct usbd_bus *bus, struct usbd_xfer *xfer, uint8_t dir) { #if NBPFILTER > 0 struct usb_softc *sc = (struct usb_softc *)bus->usbctl; usb_endpoint_descriptor_t *ed = xfer->pipe->endpoint->edesc; union { struct usbpcap_ctl_hdr uch; struct usbpcap_iso_hdr_full uih; } h; struct usbpcap_pkt_hdr *uph = &h.uch.uch_hdr; uint32_t nframes, offset; unsigned int bpfdir; void *data = NULL; size_t flen; caddr_t bpf; int i; bpf = bus->bpf; if (bpf == NULL) return; switch (UE_GET_XFERTYPE(ed->bmAttributes)) { case UE_CONTROL: /* Control transfer headers include an extra byte */ uph->uph_hlen = htole16(sizeof(struct usbpcap_ctl_hdr)); uph->uph_xfertype = USBPCAP_TRANSFER_CONTROL; break; case UE_ISOCHRONOUS: offset = 0; nframes = xfer->nframes; #ifdef DIAGNOSTIC if (nframes > _USBPCAP_MAX_ISOFRAMES) { printf("%s: too many frames: %d > %d\n", __func__, xfer->nframes, _USBPCAP_MAX_ISOFRAMES); nframes = _USBPCAP_MAX_ISOFRAMES; } #endif /* Isochronous transfer headers include space for one frame */ flen = (nframes - 1) * sizeof(struct usbpcap_iso_pkt); uph->uph_hlen = htole16(sizeof(struct usbpcap_iso_hdr) + flen); uph->uph_xfertype = USBPCAP_TRANSFER_ISOCHRONOUS; h.uih.uih_startframe = 0; /* not yet used */ h.uih.uih_nframes = nframes; h.uih.uih_errors = 0; /* we don't have per-frame error */ for (i = 0; i < nframes; i++) { h.uih.uih_frames[i].uip_offset = offset; h.uih.uih_frames[i].uip_length = xfer->frlengths[i]; /* See above, we don't have per-frame error */ h.uih.uih_frames[i].uip_status = 0; offset += xfer->frlengths[i]; } break; case UE_BULK: uph->uph_hlen = htole16(sizeof(*uph)); uph->uph_xfertype = USBPCAP_TRANSFER_BULK; break; case UE_INTERRUPT: uph->uph_hlen = htole16(sizeof(*uph)); uph->uph_xfertype = USBPCAP_TRANSFER_INTERRUPT; break; default: return; } uph->uph_id = 0; /* not yet used */ uph->uph_status = htole32(xfer->status); uph->uph_function = 0; /* not yet used */ uph->uph_bus = htole32(sc->sc_dev.dv_unit); uph->uph_devaddr = htole16(xfer->device->address); uph->uph_epaddr = ed->bEndpointAddress; uph->uph_info = 0; /* Outgoing control requests start with a STAGE dump. */ if ((xfer->rqflags & URQ_REQUEST) && (dir == USBTAP_DIR_OUT)) { h.uch.uch_stage = USBPCAP_CONTROL_STAGE_SETUP; uph->uph_dlen = sizeof(usb_device_request_t); bpf_tap_hdr(bpf, uph, uph->uph_hlen, &xfer->request, uph->uph_dlen, BPF_DIRECTION_OUT); } if (dir == USBTAP_DIR_OUT) { bpfdir = BPF_DIRECTION_OUT; if (!usbd_xfer_isread(xfer)) { data = KERNADDR(&xfer->dmabuf, 0); uph->uph_dlen = xfer->length; if (xfer->rqflags & URQ_REQUEST) h.uch.uch_stage = USBPCAP_CONTROL_STAGE_DATA; } else { data = NULL; uph->uph_dlen = 0; if (xfer->rqflags & URQ_REQUEST) h.uch.uch_stage = USBPCAP_CONTROL_STAGE_STATUS; } } else { /* USBTAP_DIR_IN */ bpfdir = BPF_DIRECTION_IN; uph->uph_info = USBPCAP_INFO_DIRECTION_IN; if (usbd_xfer_isread(xfer)) { data = KERNADDR(&xfer->dmabuf, 0); uph->uph_dlen = xfer->actlen; if (xfer->rqflags & URQ_REQUEST) h.uch.uch_stage = USBPCAP_CONTROL_STAGE_DATA; } else { data = NULL; uph->uph_dlen = 0; if (xfer->rqflags & URQ_REQUEST) h.uch.uch_stage = USBPCAP_CONTROL_STAGE_STATUS; } } /* Dump bulk/intr/iso data, ctrl DATA or STATUS stage. */ bpf_tap_hdr(bpf, uph, uph->uph_hlen, data, uph->uph_dlen, bpfdir); /* Incoming control requests with DATA need a STATUS stage. */ if ((xfer->rqflags & URQ_REQUEST) && (dir == USBTAP_DIR_IN) && (h.uch.uch_stage == USBPCAP_CONTROL_STAGE_DATA)) { h.uch.uch_stage = USBPCAP_CONTROL_STAGE_STATUS; uph->uph_dlen = 0; bpf_tap_hdr(bpf, uph, uph->uph_hlen, NULL, 0, BPF_DIRECTION_IN); } #endif }
16 2 14 1 1 1 14 1 9 1 1 7 2 5 1 1 4 3 6 1 5 4 4 7 4 4 4 52 52 51 4 1 3 1 1 4 3 6 6 5 3 2 1 2 1 1 2 3 2 5 2 8 7 2 7 2 1 1 6 1 2 3 1 3 1 5 5 2 3 4 3 3 3 4 3 4 4 3 3 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 /* $OpenBSD: wsmux.c,v 1.57 2024/03/25 13:01:49 mvs Exp $ */ /* $NetBSD: wsmux.c,v 1.37 2005/04/30 03:47:12 augustss Exp $ */ /* * Copyright (c) 1998, 2005 The NetBSD Foundation, Inc. * All rights reserved. * * Author: Lennart Augustsson <augustss@carlstedt.se> * Carlstedt Research & Technology * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "wsmux.h" #include "wsdisplay.h" #include "wskbd.h" #include "wsmouse.h" /* * wscons mux device. * * The mux device is a collection of real mice and keyboards and acts as * a merge point for all the events from the different real devices. */ #include <sys/param.h> #include <sys/conf.h> #include <sys/ioctl.h> #include <sys/fcntl.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/proc.h> #include <sys/queue.h> #include <sys/syslog.h> #include <sys/systm.h> #include <sys/tty.h> #include <sys/signalvar.h> #include <sys/device.h> #include <dev/wscons/wsconsio.h> #include <dev/wscons/wsksymdef.h> #include <dev/wscons/wseventvar.h> #include <dev/wscons/wsmuxvar.h> #define WSMUX_MAXDEPTH 8 #ifdef WSMUX_DEBUG #define DPRINTF(x) if (wsmuxdebug) printf x #define DPRINTFN(n,x) if (wsmuxdebug > (n)) printf x int wsmuxdebug = 0; #else #define DPRINTF(x) #define DPRINTFN(n,x) #endif /* * The wsmux pseudo device is used to multiplex events from several wsmouse, * wskbd, and/or wsmux devices together. * The devices connected together form a tree with muxes in the interior * and real devices (mouse and kbd) at the leaves. The special case of * a tree with one node (mux or other) is supported as well. * Only the device at the root of the tree can be opened (if a non-root * device is opened the subtree rooted at that point is severed from the * containing tree). When the root is opened it allocates a wseventvar * struct which all the nodes in the tree will send their events too. * An ioctl() performed on the root is propagated to all the nodes. * There are also ioctl() operations to add and remove nodes from a tree. */ int wsmux_mux_open(struct wsevsrc *, struct wseventvar *); int wsmux_mux_close(struct wsevsrc *); int wsmux_do_open(struct wsmux_softc *, struct wseventvar *); void wsmux_do_close(struct wsmux_softc *); #if NWSDISPLAY > 0 int wsmux_evsrc_set_display(struct device *, struct device *); #else #define wsmux_evsrc_set_display NULL #endif int wsmux_do_displayioctl(struct device *dev, u_long cmd, caddr_t data, int flag, struct proc *p); int wsmux_do_ioctl(struct device *, u_long, caddr_t,int,struct proc *); int wsmux_add_mux(int, struct wsmux_softc *); int wsmux_depth(struct wsmux_softc *); void wsmuxattach(int); void wsmux_detach_sc_locked(struct wsmux_softc *, struct wsevsrc *); struct wssrcops wsmux_srcops = { .type = WSMUX_MUX, .dopen = wsmux_mux_open, .dclose = wsmux_mux_close, .dioctl = wsmux_do_ioctl, .ddispioctl = wsmux_do_displayioctl, .dsetdisplay = wsmux_evsrc_set_display, }; /* * Lock used by wsmux_add_mux() to grant exclusive access to the tree of * stacked wsmux devices. */ struct rwlock wsmux_tree_lock = RWLOCK_INITIALIZER("wsmuxtreelk"); /* From upper level */ void wsmuxattach(int n) { } /* Keep track of all muxes that have been allocated */ int nwsmux = 0; struct wsmux_softc **wsmuxdevs = NULL; /* Return mux n, create if necessary */ struct wsmux_softc * wsmux_getmux(int n) { struct wsmux_softc *sc; struct wsmux_softc **new, **old; int i; if (n >= WSMUX_MAXDEV) return (NULL); /* Make sure there is room for mux n in the table */ if (n >= nwsmux) { old = wsmuxdevs; new = mallocarray(n + 1, sizeof (*wsmuxdevs), M_DEVBUF, M_NOWAIT); if (new == NULL) { printf("wsmux_getmux: no memory for mux %d\n", n); return (NULL); } if (old != NULL) bcopy(old, new, nwsmux * sizeof(*wsmuxdevs)); for (i = nwsmux; i < (n + 1); i++) new[i] = NULL; if (old != NULL) free(old, M_DEVBUF, nwsmux * sizeof(*wsmuxdevs)); wsmuxdevs = new; nwsmux = n + 1; } sc = wsmuxdevs[n]; if (sc == NULL) { sc = wsmux_create("wsmux", n); if (sc == NULL) printf("wsmux: attach out of memory\n"); wsmuxdevs[n] = sc; } return (sc); } /* * open() of the pseudo device from device table. */ int wsmuxopen(dev_t dev, int flags, int mode, struct proc *p) { struct wsmux_softc *sc; struct wseventvar *evar; int error, unit; unit = minor(dev); sc = wsmux_getmux(unit); if (sc == NULL) return (ENXIO); DPRINTF(("%s: %s: sc=%p\n", __func__, sc->sc_base.me_dv.dv_xname, sc)); if ((flags & (FREAD | FWRITE)) == FWRITE) { /* Not opening for read, only ioctl is available. */ return (0); } if (sc->sc_base.me_parent != NULL) { /* Grab the mux out of the greedy hands of the parent mux. */ DPRINTF(("%s: detach\n", __func__)); wsmux_detach_sc(&sc->sc_base); } if (sc->sc_base.me_evp != NULL) /* Already open. */ return (EBUSY); evar = &sc->sc_base.me_evar; if (wsevent_init(evar)) return (EBUSY); #ifdef WSDISPLAY_COMPAT_RAWKBD sc->sc_rawkbd = 0; #endif error = wsmux_do_open(sc, evar); if (error) wsevent_fini(evar); return (error); } /* * Open of a mux via the parent mux. */ int wsmux_mux_open(struct wsevsrc *me, struct wseventvar *evar) { struct wsmux_softc *sc = (struct wsmux_softc *)me; #ifdef DIAGNOSTIC if (sc->sc_base.me_parent == NULL) { printf("wsmux_mux_open: no parent\n"); return (EINVAL); } #endif return (wsmux_do_open(sc, evar)); } /* Common part of opening a mux. */ int wsmux_do_open(struct wsmux_softc *sc, struct wseventvar *evar) { struct wsevsrc *me; #ifdef DIAGNOSTIC int error; #endif /* The device could already be attached to a mux. */ if (sc->sc_base.me_evp != NULL) return (EBUSY); sc->sc_base.me_evp = evar; /* remember event variable, mark as open */ /* Open all children. */ rw_enter_read(&sc->sc_lock); TAILQ_FOREACH(me, &sc->sc_cld, me_next) { DPRINTF(("%s: %s: m=%p dev=%s\n", __func__, sc->sc_base.me_dv.dv_xname, me, me->me_dv.dv_xname)); #ifdef DIAGNOSTIC if (me->me_evp != NULL) { printf("wsmuxopen: dev already in use\n"); continue; } if (me->me_parent != sc) { printf("wsmux_do_open: bad child=%p\n", me); continue; } error = wsevsrc_open(me, evar); if (error) { DPRINTF(("%s: open failed %d\n", __func__, error)); } #else /* ignore errors, failing children will not be marked open */ (void)wsevsrc_open(me, evar); #endif } rw_exit_read(&sc->sc_lock); return (0); } /* * close() of the pseudo device from device table. */ int wsmuxclose(dev_t dev, int flags, int mode, struct proc *p) { struct wsmux_softc *sc = (struct wsmux_softc *)wsmuxdevs[minor(dev)]; struct wseventvar *evar = sc->sc_base.me_evp; if ((flags & (FREAD | FWRITE)) == FWRITE) /* Not open for read */ return (0); wsmux_do_close(sc); sc->sc_base.me_evp = NULL; wsevent_fini(evar); return (0); } /* * Close of a mux via the parent mux. */ int wsmux_mux_close(struct wsevsrc *me) { struct wsmux_softc *sc = (struct wsmux_softc *)me; wsmux_do_close(sc); sc->sc_base.me_evp = NULL; return (0); } /* Common part of closing a mux. */ void wsmux_do_close(struct wsmux_softc *sc) { struct wsevsrc *me; DPRINTF(("%s: %s: sc=%p\n", __func__, sc->sc_base.me_dv.dv_xname, sc)); /* Close all the children. */ rw_enter_read(&sc->sc_lock); TAILQ_FOREACH(me, &sc->sc_cld, me_next) { DPRINTF(("%s %s: m=%p dev=%s\n", __func__, sc->sc_base.me_dv.dv_xname, me, me->me_dv.dv_xname)); #ifdef DIAGNOSTIC if (me->me_parent != sc) { printf("wsmuxclose: bad child=%p\n", me); continue; } #endif (void)wsevsrc_close(me); } rw_exit_read(&sc->sc_lock); } /* * read() of the pseudo device from device table. */ int wsmuxread(dev_t dev, struct uio *uio, int flags) { struct wsmux_softc *sc = wsmuxdevs[minor(dev)]; struct wseventvar *evar; int error; evar = sc->sc_base.me_evp; if (evar == NULL) { #ifdef DIAGNOSTIC /* XXX can we get here? */ printf("wsmuxread: not open\n"); #endif return (EINVAL); } DPRINTFN(5, ("%s: %s event read evar=%p\n", __func__, sc->sc_base.me_dv.dv_xname, evar)); error = wsevent_read(evar, uio, flags); DPRINTFN(5, ("%s: %s event read ==> error=%d\n", __func__, sc->sc_base.me_dv.dv_xname, error)); return (error); } /* * ioctl of the pseudo device from device table. */ int wsmuxioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { return wsmux_do_ioctl(&wsmuxdevs[minor(dev)]->sc_base.me_dv, cmd, data, flag, p); } /* * ioctl of a mux via the parent mux, continuation of wsmuxioctl(). */ int wsmux_do_ioctl(struct device *dv, u_long cmd, caddr_t data, int flag, struct proc *p) { struct wsmux_softc *sc = (struct wsmux_softc *)dv; struct wsevsrc *me; int error, ok; int s, put, get, n; struct wseventvar *evar; struct wscons_event *ev; struct wsmux_device_list *l; DPRINTF(("%s: %s: enter sc=%p, cmd=%08lx\n", __func__, sc->sc_base.me_dv.dv_xname, sc, cmd)); switch (cmd) { case WSMUXIO_INJECTEVENT: case WSMUXIO_ADD_DEVICE: case WSMUXIO_REMOVE_DEVICE: #ifdef WSDISPLAY_COMPAT_RAWKBD case WSKBDIO_SETMODE: #endif if ((flag & FWRITE) == 0) return (EACCES); } switch (cmd) { case WSMUXIO_INJECTEVENT: /* Inject an event, e.g., from moused. */ DPRINTF(("%s: inject\n", sc->sc_base.me_dv.dv_xname)); evar = sc->sc_base.me_evp; if (evar == NULL) { /* No event sink, so ignore it. */ DPRINTF(("%s: event ignored\n", __func__)); return (0); } s = spltty(); get = evar->ws_get; put = evar->ws_put; ev = &evar->ws_q[put]; if (++put % WSEVENT_QSIZE == get) { put--; splx(s); return (ENOSPC); } if (put >= WSEVENT_QSIZE) put = 0; *ev = *(struct wscons_event *)data; nanotime(&ev->time); evar->ws_put = put; WSEVENT_WAKEUP(evar); splx(s); return (0); case WSMUXIO_ADD_DEVICE: #define d ((struct wsmux_device *)data) DPRINTF(("%s: add type=%d, no=%d\n", sc->sc_base.me_dv.dv_xname, d->type, d->idx)); if (d->idx < 0) return (ENXIO); switch (d->type) { #if NWSMOUSE > 0 case WSMUX_MOUSE: return (wsmouse_add_mux(d->idx, sc)); #endif #if NWSKBD > 0 case WSMUX_KBD: return (wskbd_add_mux(d->idx, sc)); #endif case WSMUX_MUX: return (wsmux_add_mux(d->idx, sc)); default: return (EINVAL); } case WSMUXIO_REMOVE_DEVICE: DPRINTF(("%s: rem type=%d, no=%d\n", sc->sc_base.me_dv.dv_xname, d->type, d->idx)); /* Locate the device */ rw_enter_write(&sc->sc_lock); TAILQ_FOREACH(me, &sc->sc_cld, me_next) { if (me->me_ops->type == d->type && me->me_dv.dv_unit == d->idx) { DPRINTF(("%s: detach\n", __func__)); wsmux_detach_sc_locked(sc, me); rw_exit_write(&sc->sc_lock); return (0); } } rw_exit_write(&sc->sc_lock); return (EINVAL); #undef d case WSMUXIO_LIST_DEVICES: DPRINTF(("%s: list\n", sc->sc_base.me_dv.dv_xname)); l = (struct wsmux_device_list *)data; n = 0; rw_enter_read(&sc->sc_lock); TAILQ_FOREACH(me, &sc->sc_cld, me_next) { if (n >= WSMUX_MAXDEV) break; l->devices[n].type = me->me_ops->type; l->devices[n].idx = me->me_dv.dv_unit; n++; } rw_exit_read(&sc->sc_lock); l->ndevices = n; return (0); #ifdef WSDISPLAY_COMPAT_RAWKBD case WSKBDIO_SETMODE: sc->sc_rawkbd = *(int *)data; DPRINTF(("%s: save rawkbd = %d\n", __func__, sc->sc_rawkbd)); break; #endif case FIONBIO: DPRINTF(("%s: FIONBIO\n", sc->sc_base.me_dv.dv_xname)); return (0); case FIOASYNC: DPRINTF(("%s: FIOASYNC\n", sc->sc_base.me_dv.dv_xname)); evar = sc->sc_base.me_evp; if (evar == NULL) return (EINVAL); evar->ws_async = *(int *)data != 0; return (0); case FIOGETOWN: case TIOCGPGRP: DPRINTF(("%s: getown (%lu)\n", sc->sc_base.me_dv.dv_xname, cmd)); evar = sc->sc_base.me_evp; if (evar == NULL) return (EINVAL); sigio_getown(&evar->ws_sigio, cmd, data); return (0); case FIOSETOWN: case TIOCSPGRP: DPRINTF(("%s: setown (%lu)\n", sc->sc_base.me_dv.dv_xname, cmd)); evar = sc->sc_base.me_evp; if (evar == NULL) return (EINVAL); return (sigio_setown(&evar->ws_sigio, cmd, data)); default: DPRINTF(("%s: unknown\n", sc->sc_base.me_dv.dv_xname)); break; } if (sc->sc_base.me_evp == NULL #if NWSDISPLAY > 0 && sc->sc_displaydv == NULL #endif ) return (EACCES); /* * If children are attached: return 0 if any of the ioctl() succeeds, * otherwise the last error. */ error = ENOTTY; ok = 0; rw_enter_read(&sc->sc_lock); TAILQ_FOREACH(me, &sc->sc_cld, me_next) { #ifdef DIAGNOSTIC /* XXX check evp? */ if (me->me_parent != sc) { printf("wsmux_do_ioctl: bad child %p\n", me); continue; } #endif error = wsevsrc_ioctl(me, cmd, data, flag, p); DPRINTF(("%s: %s: me=%p dev=%s ==> %d\n", __func__, sc->sc_base.me_dv.dv_xname, me, me->me_dv.dv_xname, error)); if (!error) ok = 1; } rw_exit_read(&sc->sc_lock); if (ok) error = 0; return (error); } int wsmuxkqfilter(dev_t dev, struct knote *kn) { struct wsmux_softc *sc = wsmuxdevs[minor(dev)]; if (sc->sc_base.me_evp == NULL) return (ENXIO); return (wsevent_kqfilter(sc->sc_base.me_evp, kn)); } /* * Add mux unit as a child to muxsc. */ int wsmux_add_mux(int unit, struct wsmux_softc *muxsc) { struct wsmux_softc *sc, *m; int error; int depth = 0; sc = wsmux_getmux(unit); if (sc == NULL) return (ENXIO); rw_enter_write(&wsmux_tree_lock); DPRINTF(("%s: %s(%p) to %s(%p)\n", __func__, sc->sc_base.me_dv.dv_xname, sc, muxsc->sc_base.me_dv.dv_xname, muxsc)); if (sc->sc_base.me_parent != NULL || sc->sc_base.me_evp != NULL) { error = EBUSY; goto out; } /* The mux we are adding must not be an ancestor of itself. */ for (m = muxsc; m != NULL; m = m->sc_base.me_parent) { if (m == sc) { error = EINVAL; goto out; } depth++; } /* * Limit the number of stacked wsmux devices to avoid exhausting * the kernel stack during wsmux_do_open(). */ if (depth + wsmux_depth(sc) > WSMUX_MAXDEPTH) { error = EBUSY; goto out; } error = wsmux_attach_sc(muxsc, &sc->sc_base); out: rw_exit_write(&wsmux_tree_lock); return (error); } /* Create a new mux softc. */ struct wsmux_softc * wsmux_create(const char *name, int unit) { struct wsmux_softc *sc; DPRINTF(("%s: allocating\n", __func__)); sc = malloc(sizeof *sc, M_DEVBUF, M_NOWAIT | M_ZERO); if (sc == NULL) return (NULL); TAILQ_INIT(&sc->sc_cld); rw_init_flags(&sc->sc_lock, "wsmuxlk", RWL_DUPOK); snprintf(sc->sc_base.me_dv.dv_xname, sizeof sc->sc_base.me_dv.dv_xname, "%s%d", name, unit); sc->sc_base.me_dv.dv_unit = unit; sc->sc_base.me_ops = &wsmux_srcops; sc->sc_kbd_layout = KB_NONE; return (sc); } /* Attach me as a child to sc. */ int wsmux_attach_sc(struct wsmux_softc *sc, struct wsevsrc *me) { int error; if (sc == NULL) return (EINVAL); rw_enter_write(&sc->sc_lock); DPRINTF(("%s: %s(%p): type=%d\n", __func__, sc->sc_base.me_dv.dv_xname, sc, me->me_ops->type)); #ifdef DIAGNOSTIC if (me->me_parent != NULL) { rw_exit_write(&sc->sc_lock); printf("wsmux_attach_sc: busy\n"); return (EBUSY); } #endif me->me_parent = sc; TAILQ_INSERT_TAIL(&sc->sc_cld, me, me_next); error = 0; #if NWSDISPLAY > 0 if (sc->sc_displaydv != NULL) { /* This is a display mux, so attach the new device to it. */ DPRINTF(("%s: %s: set display %p\n", __func__, sc->sc_base.me_dv.dv_xname, sc->sc_displaydv)); if (me->me_ops->dsetdisplay != NULL) { error = wsevsrc_set_display(me, sc->sc_displaydv); /* Ignore that the console already has a display. */ if (error == EBUSY) error = 0; if (!error) { #ifdef WSDISPLAY_COMPAT_RAWKBD DPRINTF(("%s: %s set rawkbd=%d\n", __func__, me->me_dv.dv_xname, sc->sc_rawkbd)); (void)wsevsrc_ioctl(me, WSKBDIO_SETMODE, &sc->sc_rawkbd, FWRITE, 0); #endif } } } #endif if (sc->sc_base.me_evp != NULL) { /* Mux is open, try to open the subdevice. */ error = wsevsrc_open(me, sc->sc_base.me_evp); } else { /* Mux is closed, ensure that the subdevice is also closed. */ if (me->me_evp != NULL) error = EBUSY; } if (error) { me->me_parent = NULL; TAILQ_REMOVE(&sc->sc_cld, me, me_next); } rw_exit_write(&sc->sc_lock); DPRINTF(("%s: %s(%p) done, error=%d\n", __func__, sc->sc_base.me_dv.dv_xname, sc, error)); return (error); } /* Remove me from the parent. */ void wsmux_detach_sc(struct wsevsrc *me) { struct wsmux_softc *sc = me->me_parent; if (sc == NULL) { printf("wsmux_detach_sc: %s has no parent\n", me->me_dv.dv_xname); return; } rw_enter_write(&sc->sc_lock); wsmux_detach_sc_locked(sc, me); rw_exit_write(&sc->sc_lock); } void wsmux_detach_sc_locked(struct wsmux_softc *sc, struct wsevsrc *me) { rw_assert_wrlock(&sc->sc_lock); DPRINTF(("%s: %s(%p) parent=%p\n", __func__, me->me_dv.dv_xname, me, sc)); if (me->me_parent != sc) { /* Device detached or attached to another mux while sleeping. */ return; } #if NWSDISPLAY > 0 if (sc->sc_displaydv != NULL) { if (me->me_ops->dsetdisplay != NULL) /* ignore error, there's nothing we can do */ (void)wsevsrc_set_display(me, NULL); } else #endif if (me->me_evp != NULL) { DPRINTF(("%s: close\n", __func__)); /* mux device is open, so close multiplexee */ (void)wsevsrc_close(me); } TAILQ_REMOVE(&sc->sc_cld, me, me_next); me->me_parent = NULL; DPRINTF(("%s: done sc=%p\n", __func__, sc)); } /* * Display ioctl() of a mux via the parent mux. */ int wsmux_do_displayioctl(struct device *dv, u_long cmd, caddr_t data, int flag, struct proc *p) { struct wsmux_softc *sc = (struct wsmux_softc *)dv; struct wsevsrc *me; int error, ok; DPRINTF(("%s: %s: sc=%p, cmd=%08lx\n", __func__, sc->sc_base.me_dv.dv_xname, sc, cmd)); #ifdef WSDISPLAY_COMPAT_RAWKBD if (cmd == WSKBDIO_SETMODE) { sc->sc_rawkbd = *(int *)data; DPRINTF(("%s: rawkbd = %d\n", __func__, sc->sc_rawkbd)); } #endif /* * Return 0 if any of the ioctl() succeeds, otherwise the last error. * Return -1 if no mux component accepts the ioctl. */ error = -1; ok = 0; rw_enter_read(&sc->sc_lock); TAILQ_FOREACH(me, &sc->sc_cld, me_next) { DPRINTF(("%s: me=%p\n", __func__, me)); #ifdef DIAGNOSTIC if (me->me_parent != sc) { printf("wsmux_displayioctl: bad child %p\n", me); continue; } #endif if (me->me_ops->ddispioctl != NULL) { error = wsevsrc_display_ioctl(me, cmd, data, flag, p); DPRINTF(("%s: me=%p dev=%s ==> %d\n", __func__, me, me->me_dv.dv_xname, error)); if (!error) ok = 1; } } rw_exit_read(&sc->sc_lock); if (ok) error = 0; return (error); } #if NWSDISPLAY > 0 /* * Set display of a mux via the parent mux. */ int wsmux_evsrc_set_display(struct device *dv, struct device *displaydv) { struct wsmux_softc *sc = (struct wsmux_softc *)dv; DPRINTF(("%s: %s: displaydv=%p\n", __func__, sc->sc_base.me_dv.dv_xname, displaydv)); if (displaydv != NULL) { if (sc->sc_displaydv != NULL) return (EBUSY); } else { if (sc->sc_displaydv == NULL) return (ENXIO); } return wsmux_set_display(sc, displaydv); } int wsmux_set_display(struct wsmux_softc *sc, struct device *displaydv) { struct device *odisplaydv; struct wsevsrc *me; struct wsmux_softc *nsc = displaydv ? sc : NULL; int error, ok; rw_enter_read(&sc->sc_lock); odisplaydv = sc->sc_displaydv; sc->sc_displaydv = displaydv; if (displaydv) { DPRINTF(("%s: connecting to %s\n", sc->sc_base.me_dv.dv_xname, displaydv->dv_xname)); } ok = 0; error = 0; TAILQ_FOREACH(me, &sc->sc_cld, me_next) { #ifdef DIAGNOSTIC if (me->me_parent != sc) { printf("wsmux_set_display: bad child parent %p\n", me); continue; } #endif if (me->me_ops->dsetdisplay != NULL) { error = wsevsrc_set_display(me, nsc ? nsc->sc_displaydv : NULL); DPRINTF(("%s: m=%p dev=%s error=%d\n", __func__, me, me->me_dv.dv_xname, error)); if (!error) { ok = 1; #ifdef WSDISPLAY_COMPAT_RAWKBD DPRINTF(("%s: %s set rawkbd=%d\n", __func__, me->me_dv.dv_xname, sc->sc_rawkbd)); (void)wsevsrc_ioctl(me, WSKBDIO_SETMODE, &sc->sc_rawkbd, FWRITE, 0); #endif } } } if (ok) error = 0; if (displaydv == NULL) { DPRINTF(("%s: disconnecting from %s\n", sc->sc_base.me_dv.dv_xname, odisplaydv->dv_xname)); } rw_exit_read(&sc->sc_lock); return (error); } #endif /* NWSDISPLAY > 0 */ uint32_t wsmux_get_layout(struct wsmux_softc *sc) { return sc->sc_kbd_layout; } void wsmux_set_layout(struct wsmux_softc *sc, uint32_t layout) { if ((layout & (KB_DEFAULT | KB_NOENCODING)) == 0) sc->sc_kbd_layout = layout; } /* * Returns the depth of the longest chain of nested wsmux devices starting * from sc. */ int wsmux_depth(struct wsmux_softc *sc) { struct wsevsrc *me; int depth; int maxdepth = 0; rw_assert_anylock(&wsmux_tree_lock); rw_enter_read(&sc->sc_lock); TAILQ_FOREACH(me, &sc->sc_cld, me_next) { if (me->me_ops->type != WSMUX_MUX) continue; depth = wsmux_depth((struct wsmux_softc *)me); if (depth > maxdepth) maxdepth = depth; } rw_exit_read(&sc->sc_lock); return (maxdepth + 1); }
2 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 /* $OpenBSD: ujoy.c,v 1.5 2024/05/23 03:21:09 jsg Exp $ */ /* * Copyright (c) 2021 Thomas Frohwein <thfr@openbsd.org> * Copyright (c) 2021 Bryan Steele <brynet@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> #include <sys/ioctl.h> #include <sys/conf.h> #include <sys/tty.h> #include <sys/fcntl.h> #include <dev/usb/usb.h> #include <dev/usb/usbhid.h> #include <dev/usb/usbdi.h> #include <dev/usb/uhidev.h> #include <dev/usb/uhid.h> int ujoy_match(struct device *, void *, void *); struct cfdriver ujoy_cd = { NULL, "ujoy", DV_DULL }; const struct cfattach ujoy_ca = { sizeof(struct uhid_softc), ujoy_match, uhid_attach, uhid_detach, }; /* * XXX workaround: * * This is a copy of sys/dev/hid/hid.c:hid_is_collection(), synced up to the * NetBSD version. Our current hid_is_collection() is not playing nice with * all HID devices like the PS4 controller. But applying this version * globally breaks other HID devices like ims(4) and imt(4). Until our global * hid_is_collection() can't be fixed to play nice with all HID devices, we * go for this dedicated ujoy(4) version. */ int ujoy_hid_is_collection(const void *desc, int size, uint8_t id, int32_t usage) { struct hid_data *hd; struct hid_item hi; uint32_t coll_usage = ~0; hd = hid_start_parse(desc, size, hid_input); if (hd == NULL) return (0); while (hid_get_item(hd, &hi)) { if (hi.kind == hid_collection && hi.collection == HCOLL_APPLICATION) coll_usage = hi.usage; if (hi.kind == hid_endcollection) coll_usage = ~0; if (hi.kind == hid_input && coll_usage == usage && hi.report_ID == id) { hid_end_parse(hd); return (1); } } hid_end_parse(hd); return (0); } int ujoy_match(struct device *parent, void *match, void *aux) { struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux; int size; void *desc; int ret = UMATCH_NONE; if (UHIDEV_CLAIM_MULTIPLE_REPORTID(uha)) return (ret); /* Find the general usage page and gamecontroller collections */ uhidev_get_report_desc(uha->parent, &desc, &size); if (ujoy_hid_is_collection(desc, size, uha->reportid, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_JOYSTICK))) ret = UMATCH_IFACECLASS; if (ujoy_hid_is_collection(desc, size, uha->reportid, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_GAME_PAD))) ret = UMATCH_IFACECLASS; return (ret); } int ujoyopen(dev_t dev, int flag, int mode, struct proc *p) { /* Restrict ujoy devices to read operations */ if ((flag & FWRITE)) return (EPERM); return (uhid_do_open(dev, flag, mode, p)); } int ujoyioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { switch (cmd) { case FIONBIO: case FIOASYNC: case USB_GET_DEVICEINFO: case USB_GET_REPORT: case USB_GET_REPORT_DESC: case USB_GET_REPORT_ID: break; default: return (EPERM); } return (uhidioctl(dev, cmd, addr, flag, p)); }
1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 /* $OpenBSD: ntfs_vfsops.c,v 1.65 2022/01/11 03:13:59 jsg Exp $ */ /* $NetBSD: ntfs_vfsops.c,v 1.7 2003/04/24 07:50:19 christos Exp $ */ /*- * Copyright (c) 1998, 1999 Semen Ustimenko * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Id: ntfs_vfsops.c,v 1.7 1999/05/31 11:28:30 phk Exp */ #include <sys/param.h> #include <sys/systm.h> #include <sys/namei.h> #include <sys/proc.h> #include <sys/kernel.h> #include <sys/vnode.h> #include <sys/lock.h> #include <sys/mount.h> #include <sys/buf.h> #include <sys/disk.h> #include <sys/fcntl.h> #include <sys/malloc.h> #include <sys/device.h> #include <sys/conf.h> #include <sys/specdev.h> /*#define NTFS_DEBUG 1*/ #include <ntfs/ntfs.h> #include <ntfs/ntfs_inode.h> #include <ntfs/ntfs_subr.h> #include <ntfs/ntfs_vfsops.h> #include <ntfs/ntfs_ihash.h> int ntfs_mount(struct mount *, const char *, void *, struct nameidata *, struct proc *); int ntfs_quotactl(struct mount *, int, uid_t, caddr_t, struct proc *); int ntfs_root(struct mount *, struct vnode **); int ntfs_start(struct mount *, int, struct proc *); int ntfs_statfs(struct mount *, struct statfs *, struct proc *); int ntfs_sync(struct mount *, int, int, struct ucred *, struct proc *); int ntfs_unmount(struct mount *, int, struct proc *); int ntfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp); int ntfs_mountfs(struct vnode *, struct mount *, struct ntfs_args *, struct proc *); int ntfs_vptofh(struct vnode *, struct fid *); int ntfs_init(struct vfsconf *); int ntfs_fhtovp(struct mount *, struct fid *, struct vnode **); int ntfs_checkexp(struct mount *, struct mbuf *, int *, struct ucred **); int ntfs_sysctl(int *, u_int, void *, size_t *, void *, size_t, struct proc *); /* * Verify a remote client has export rights and return these rights via. * exflagsp and credanonp. */ int ntfs_checkexp(struct mount *mp, struct mbuf *nam, int *exflagsp, struct ucred **credanonp) { struct netcred *np; struct ntfsmount *ntm = VFSTONTFS(mp); /* * Get the export permission structure for this <mp, client> tuple. */ np = vfs_export_lookup(mp, &ntm->ntm_export, nam); if (np == NULL) return (EACCES); *exflagsp = np->netc_exflags; *credanonp = &np->netc_anon; return (0); } int ntfs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { return (EINVAL); } int ntfs_init(struct vfsconf *vcp) { return 0; } int ntfs_mount(struct mount *mp, const char *path, void *data, struct nameidata *ndp, struct proc *p) { int err = 0; struct vnode *devvp; struct ntfs_args *args = data; char fname[MNAMELEN]; char fspec[MNAMELEN]; ntfs_nthashinit(); /* *** * Mounting non-root file system or updating a file system *** */ /* * If updating, check whether changing from read-only to * read/write; if there is no device name, that's all we do. */ if (mp->mnt_flag & MNT_UPDATE) { /* if not updating name...*/ if (args && args->fspec == NULL) { /* * Process export requests. Jumping to "success" * will return the vfs_export() error code. */ struct ntfsmount *ntm = VFSTONTFS(mp); err = vfs_export(mp, &ntm->ntm_export, &args->export_info); goto success; } printf("ntfs_mount(): MNT_UPDATE not supported\n"); err = EINVAL; goto error_1; } /* * Not an update, or updating the name: look up the name * and verify that it refers to a sensible block device. */ err = copyinstr(args->fspec, fspec, sizeof(fspec), NULL); if (err) goto error_1; if (disk_map(fspec, fname, sizeof(fname), DM_OPENBLCK) == -1) bcopy(fspec, fname, sizeof(fname)); NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fname, p); err = namei(ndp); if (err) { /* can't get devvp!*/ goto error_1; } devvp = ndp->ni_vp; if (devvp->v_type != VBLK) { err = ENOTBLK; goto error_2; } if (major(devvp->v_rdev) >= nblkdev) { err = ENXIO; goto error_2; } if (mp->mnt_flag & MNT_UPDATE) { #if 0 /* ******************** * UPDATE ******************** */ if (devvp != ntmp->um_devvp) err = EINVAL; /* needs translation */ else vrele(devvp); /* * Update device name only on success */ if( !err) { err = set_statfs_info(NULL, UIO_USERSPACE, args->fspec, UIO_USERSPACE, mp, p); } #endif } else { /* ******************** * NEW MOUNT ******************** */ /* * Since this is a new mount, we want the names for * the device and the mount point copied in. If an * error occurs, the mountpoint is discarded by the * upper level code. */ /* Save "last mounted on" info for mount point (NULL pad)*/ bzero(mp->mnt_stat.f_mntonname, MNAMELEN); strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN); bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); strlcpy(mp->mnt_stat.f_mntfromname, fname, MNAMELEN); bzero(mp->mnt_stat.f_mntfromspec, MNAMELEN); strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN); bcopy(args, &mp->mnt_stat.mount_info.ntfs_args, sizeof(*args)); if ( !err) { err = ntfs_mountfs(devvp, mp, args, p); } } if (err) { goto error_2; } /* * Initialize FS stat information in mount struct; uses both * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname * * This code is common to root and non-root mounts */ (void)VFS_STATFS(mp, &mp->mnt_stat, p); goto success; error_2: /* error with devvp held*/ /* release devvp before failing*/ vrele(devvp); error_1: /* no state to back out*/ success: return(err); } /* * Common code for mount and mountroot */ int ntfs_mountfs(struct vnode *devvp, struct mount *mp, struct ntfs_args *argsp, struct proc *p) { struct buf *bp; struct ntfsmount *ntmp = NULL; dev_t dev = devvp->v_rdev; int error, ncount, i; struct vnode *vp; /* * Disallow multiple mounts of the same device. * Disallow mounting of a device that is currently in use * (except for root, which might share swap device for miniroot). * Flush out any old buffers remaining from a previous use. */ error = vfs_mountedon(devvp); if (error) return (error); ncount = vcount(devvp); if (ncount > 1 && devvp != rootvp) return (EBUSY); vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, INFSLP); VOP_UNLOCK(devvp); if (error) return (error); error = VOP_OPEN(devvp, FREAD, FSCRED, p); if (error) return (error); bp = NULL; error = bread(devvp, BBLOCK, BBSIZE, &bp); if (error) goto out; ntmp = malloc(sizeof *ntmp, M_NTFSMNT, M_WAITOK | M_ZERO); bcopy(bp->b_data, &ntmp->ntm_bootfile, sizeof(struct bootfile)); brelse(bp); bp = NULL; if (strncmp(ntmp->ntm_bootfile.bf_sysid, NTFS_BBID, NTFS_BBIDLEN)) { error = EINVAL; DPRINTF("ntfs_mountfs: invalid boot block\n"); goto out; } { int8_t cpr = ntmp->ntm_mftrecsz; if( cpr > 0 ) ntmp->ntm_bpmftrec = ntmp->ntm_spc * cpr; else ntmp->ntm_bpmftrec = (1 << (-cpr)) / ntmp->ntm_bps; } DPRINTF("ntfs_mountfs(): bps: %u, spc: %u, media: %x, " "mftrecsz: %u (%u sects)\n", ntmp->ntm_bps, ntmp->ntm_spc, ntmp->ntm_bootfile.bf_media, ntmp->ntm_mftrecsz, ntmp->ntm_bpmftrec); DPRINTF("ntfs_mountfs(): mftcn: 0x%llx|0x%llx\n", ntmp->ntm_mftcn, ntmp->ntm_mftmirrcn); ntmp->ntm_mountp = mp; ntmp->ntm_dev = dev; ntmp->ntm_devvp = devvp; ntmp->ntm_uid = argsp->uid; ntmp->ntm_gid = argsp->gid; ntmp->ntm_mode = argsp->mode; ntmp->ntm_flag = argsp->flag; mp->mnt_data = ntmp; TAILQ_INIT(&ntmp->ntm_ntnodeq); /* set file name encode/decode hooks XXX utf-8 only for now */ ntmp->ntm_wget = ntfs_utf8_wget; ntmp->ntm_wput = ntfs_utf8_wput; ntmp->ntm_wcmp = ntfs_utf8_wcmp; DPRINTF("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n", (ntmp->ntm_flag & NTFS_MFLAG_CASEINS) ? "insens." : "sens.", (ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES) ? " allnames," : "", ntmp->ntm_uid, ntmp->ntm_gid, ntmp->ntm_mode); /* * We read in some system nodes to do not allow * reclaim them and to have everytime access to them. */ { int pi[3] = { NTFS_MFTINO, NTFS_ROOTINO, NTFS_BITMAPINO }; for (i=0; i<3; i++) { error = VFS_VGET(mp, pi[i], &(ntmp->ntm_sysvn[pi[i]])); if(error) goto out1; ntmp->ntm_sysvn[pi[i]]->v_flag |= VSYSTEM; vref(ntmp->ntm_sysvn[pi[i]]); vput(ntmp->ntm_sysvn[pi[i]]); } } /* read the Unicode lowercase --> uppercase translation table, * if necessary */ if ((error = ntfs_toupper_use(mp, ntmp, p))) goto out1; /* * Scan $BitMap and count free clusters */ error = ntfs_calccfree(ntmp, &ntmp->ntm_cfree); if(error) goto out1; /* * Read and translate to internal format attribute * definition file. */ { int num,j; struct attrdef ad; /* Open $AttrDef */ error = VFS_VGET(mp, NTFS_ATTRDEFINO, &vp ); if(error) goto out1; /* Count valid entries */ for(num = 0; ; num++) { error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, num * sizeof(ad), sizeof(ad), &ad, NULL); if (error) goto out1; if (ad.ad_name[0] == 0) break; } /* Alloc memory for attribute definitions */ ntmp->ntm_ad = mallocarray(num, sizeof(struct ntvattrdef), M_NTFSMNT, M_WAITOK); ntmp->ntm_adnum = num; /* Read them and translate */ for(i = 0; i < num; i++){ error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, i * sizeof(ad), sizeof(ad), &ad, NULL); if (error) goto out1; j = 0; do { ntmp->ntm_ad[i].ad_name[j] = ad.ad_name[j]; } while(ad.ad_name[j++]); ntmp->ntm_ad[i].ad_namelen = j - 1; ntmp->ntm_ad[i].ad_type = ad.ad_type; } vput(vp); } mp->mnt_stat.f_fsid.val[0] = dev; mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; mp->mnt_stat.f_namemax = NTFS_MAXFILENAME; mp->mnt_flag |= MNT_LOCAL; devvp->v_specmountpoint = mp; return (0); out1: for (i = 0; i < NTFS_SYSNODESNUM; i++) if (ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]); if (vflush(mp,NULLVP,0)) DPRINTF("ntfs_mountfs: vflush failed\n"); out: if (devvp->v_specinfo) devvp->v_specmountpoint = NULL; if (bp) brelse(bp); if (ntmp != NULL) { if (ntmp->ntm_ad != NULL) free(ntmp->ntm_ad, M_NTFSMNT, 0); free(ntmp, M_NTFSMNT, 0); mp->mnt_data = NULL; } /* lock the device vnode before calling VOP_CLOSE() */ vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); (void)VOP_CLOSE(devvp, FREAD, NOCRED, p); VOP_UNLOCK(devvp); return (error); } int ntfs_start(struct mount *mp, int flags, struct proc *p) { return (0); } int ntfs_unmount(struct mount *mp, int mntflags, struct proc *p) { struct ntfsmount *ntmp; int error, flags, i; DPRINTF("ntfs_unmount: unmounting...\n"); ntmp = VFSTONTFS(mp); flags = 0; if(mntflags & MNT_FORCE) flags |= FORCECLOSE; DPRINTF("ntfs_unmount: vflushing...\n"); error = vflush(mp,NULLVP,flags | SKIPSYSTEM); if (error) { DPRINTF("ntfs_unmount: vflush failed: %d\n", error); return (error); } /* Check if system vnodes are still referenced */ for(i=0;i<NTFS_SYSNODESNUM;i++) { if(((mntflags & MNT_FORCE) == 0) && (ntmp->ntm_sysvn[i] && ntmp->ntm_sysvn[i]->v_usecount > 1)) return (EBUSY); } /* Dereference all system vnodes */ for(i=0;i<NTFS_SYSNODESNUM;i++) if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]); /* vflush system vnodes */ error = vflush(mp,NULLVP,flags); if (error) { /* XXX should this be panic() ? */ printf("ntfs_unmount: vflush failed(sysnodes): %d\n",error); } /* Check if the type of device node isn't VBAD before * touching v_specinfo. If the device vnode is revoked, the * field is NULL and touching it causes null pointer dereference. */ if (ntmp->ntm_devvp->v_type != VBAD) ntmp->ntm_devvp->v_specmountpoint = NULL; /* lock the device vnode before calling VOP_CLOSE() */ vn_lock(ntmp->ntm_devvp, LK_EXCLUSIVE | LK_RETRY); vinvalbuf(ntmp->ntm_devvp, V_SAVE, NOCRED, p, 0, INFSLP); (void)VOP_CLOSE(ntmp->ntm_devvp, FREAD, NOCRED, p); vput(ntmp->ntm_devvp); /* free the toupper table, if this has been last mounted ntfs volume */ ntfs_toupper_unuse(p); DPRINTF("ntfs_unmount: freeing memory...\n"); free(ntmp->ntm_ad, M_NTFSMNT, 0); free(ntmp, M_NTFSMNT, 0); mp->mnt_data = NULL; mp->mnt_flag &= ~MNT_LOCAL; return (0); } int ntfs_root(struct mount *mp, struct vnode **vpp) { struct vnode *nvp; int error = 0; DPRINTF("ntfs_root(): sysvn: %p\n", VFSTONTFS(mp)->ntm_sysvn[NTFS_ROOTINO]); error = VFS_VGET(mp, (ino_t)NTFS_ROOTINO, &nvp); if(error) { printf("ntfs_root: VFS_VGET failed: %d\n",error); return (error); } *vpp = nvp; return (0); } /* * Do operations associated with quotas, not supported */ int ntfs_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg, struct proc *p) { return EOPNOTSUPP; } int ntfs_calccfree(struct ntfsmount *ntmp, cn_t *cfreep) { struct vnode *vp; u_int8_t *tmp; int j, error; cn_t cfree = 0; uint64_t bmsize, offset; size_t chunksize, i; vp = ntmp->ntm_sysvn[NTFS_BITMAPINO]; bmsize = VTOF(vp)->f_size; if (bmsize > 1024 * 1024) chunksize = 1024 * 1024; else chunksize = bmsize; tmp = malloc(chunksize, M_TEMP, M_WAITOK); for (offset = 0; offset < bmsize; offset += chunksize) { if (chunksize > bmsize - offset) chunksize = bmsize - offset; error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, offset, chunksize, tmp, NULL); if (error) goto out; for (i = 0; i < chunksize; i++) for (j = 0; j < 8; j++) if (~tmp[i] & (1 << j)) cfree++; } *cfreep = cfree; out: free(tmp, M_TEMP, 0); return(error); } int ntfs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p) { struct ntfsmount *ntmp = VFSTONTFS(mp); u_int64_t mftallocated; DPRINTF("ntfs_statfs():\n"); mftallocated = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_allocated; sbp->f_bsize = ntmp->ntm_bps; sbp->f_iosize = ntmp->ntm_bps * ntmp->ntm_spc; sbp->f_blocks = ntmp->ntm_bootfile.bf_spv; sbp->f_bfree = sbp->f_bavail = ntfs_cntobn(ntmp->ntm_cfree); sbp->f_ffree = sbp->f_favail = sbp->f_bfree / ntmp->ntm_bpmftrec; sbp->f_files = mftallocated / ntfs_bntob(ntmp->ntm_bpmftrec) + sbp->f_ffree; copy_statfs_info(sbp, mp); return (0); } int ntfs_sync(struct mount *mp, int waitfor, int stall, struct ucred *cred, struct proc *p) { /*DPRINTF("ntfs_sync():\n");*/ return (0); } int ntfs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) { struct ntfid *ntfhp = (struct ntfid *)fhp; int error; DDPRINTF("ntfs_fhtovp(): %s: %u\n", mp->mnt_stat.f_mntonname, ntfhp->ntfid_ino); error = ntfs_vgetex(mp, ntfhp->ntfid_ino, ntfhp->ntfid_attr, NULL, LK_EXCLUSIVE | LK_RETRY, 0, vpp); /* XXX */ if (error != 0) { *vpp = NULLVP; return (error); } /* XXX as unlink/rmdir/mkdir/creat are not currently possible * with NTFS, we don't need to check anything else for now */ return (0); } int ntfs_vptofh(struct vnode *vp, struct fid *fhp) { struct ntnode *ntp; struct ntfid *ntfhp; struct fnode *fn; DDPRINTF("ntfs_fhtovp(): %s: %p\n", vp->v_mount->mnt_stat.f_mntonname, vp); fn = VTOF(vp); ntp = VTONT(vp); ntfhp = (struct ntfid *)fhp; ntfhp->ntfid_len = sizeof(struct ntfid); ntfhp->ntfid_ino = ntp->i_number; ntfhp->ntfid_attr = fn->f_attrtype; #ifdef notyet ntfhp->ntfid_gen = ntp->i_gen; #endif return (0); } int ntfs_vgetex(struct mount *mp, ntfsino_t ino, u_int32_t attrtype, char *attrname, u_long lkflags, u_long flags, struct vnode **vpp) { int error; struct ntfsmount *ntmp; struct ntnode *ip; struct fnode *fp; struct vnode *vp; enum vtype f_type; DPRINTF("ntfs_vgetex: ino: %u, attr: 0x%x:%s, lkf: 0x%lx, f: 0x%lx\n", ino, attrtype, attrname ? attrname : "", lkflags, flags); ntmp = VFSTONTFS(mp); *vpp = NULL; /* Get ntnode */ error = ntfs_ntlookup(ntmp, ino, &ip); if (error) { printf("ntfs_vget: ntfs_ntget failed\n"); return (error); } /* It may be not initialized fully, so force load it */ if (!(flags & VG_DONTLOADIN) && !(ip->i_flag & IN_LOADED)) { error = ntfs_loadntnode(ntmp, ip); if(error) { printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %d\n", ip->i_number); ntfs_ntput(ip); return (error); } } error = ntfs_fget(ntmp, ip, attrtype, attrname, &fp); if (error) { printf("ntfs_vget: ntfs_fget failed\n"); ntfs_ntput(ip); return (error); } if (!(flags & VG_DONTVALIDFN) && !(fp->f_flag & FN_VALID)) { if ((ip->i_frflag & NTFS_FRFLAG_DIR) && (fp->f_attrtype == NTFS_A_DATA && fp->f_attrname == NULL)) { f_type = VDIR; } else if (flags & VG_EXT) { f_type = VNON; fp->f_size = fp->f_allocated = 0; } else { f_type = VREG; error = ntfs_filesize(ntmp, fp, &fp->f_size, &fp->f_allocated); if (error) { ntfs_ntput(ip); return (error); } } fp->f_flag |= FN_VALID; } /* * We may be calling vget() now. To avoid potential deadlock, we need * to release ntnode lock, since due to locking order vnode * lock has to be acquired first. * ntfs_fget() bumped ntnode usecount, so ntnode won't be recycled * prematurely. */ ntfs_ntput(ip); if (FTOV(fp)) { /* vget() returns error if the vnode has been recycled */ if (vget(FTOV(fp), lkflags) == 0) { *vpp = FTOV(fp); return (0); } } error = getnewvnode(VT_NTFS, ntmp->ntm_mountp, &ntfs_vops, &vp); if(error) { ntfs_frele(fp); ntfs_ntput(ip); return (error); } DPRINTF("ntfs_vget: vnode: %p for ntnode: %u\n", vp, ino); fp->f_vp = vp; vp->v_data = fp; vp->v_type = f_type; if (ino == NTFS_ROOTINO) vp->v_flag |= VROOT; if (lkflags & LK_TYPE_MASK) { error = vn_lock(vp, lkflags); if (error) { vput(vp); return (error); } } *vpp = vp; return (0); } int ntfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) { if (ino > (ntfsino_t)-1) panic("ntfs_vget: alien ino_t %llu", (unsigned long long)ino); return ntfs_vgetex(mp, ino, NTFS_A_DATA, NULL, LK_EXCLUSIVE | LK_RETRY, 0, vpp); /* XXX */ } const struct vfsops ntfs_vfsops = { .vfs_mount = ntfs_mount, .vfs_start = ntfs_start, .vfs_unmount = ntfs_unmount, .vfs_root = ntfs_root, .vfs_quotactl = ntfs_quotactl, .vfs_statfs = ntfs_statfs, .vfs_sync = ntfs_sync, .vfs_vget = ntfs_vget, .vfs_fhtovp = ntfs_fhtovp, .vfs_vptofh = ntfs_vptofh, .vfs_init = ntfs_init, .vfs_sysctl = ntfs_sysctl, .vfs_checkexp = ntfs_checkexp, };
242 24 1124 1275 20 8 668 10 7 2 3 13 16 52 30 72 241 231 18 19 33 221 221 18 21 242 242 24 24 15 9 19 6 24 24 24 22 20 233 47 14 186 187 233 11 4 3 11 11 11 11 11 11 11 4 11 4 11 4 11 57 24 45 56 55 36 31 15 20 20 31 54 55 21 40 40 14 51 19 38 38 26 40 22 10 1 3 6 11 11 8 4 4 7 40 41 1438 1440 1439 1116 42 1121 5 5 3 4 67 62 11 20 1 50 29 29 71 17 24 26 23 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 /* $OpenBSD: uvm_amap.c,v 1.95 2024/05/20 17:03:36 dv Exp $ */ /* $NetBSD: uvm_amap.c,v 1.27 2000/11/25 06:27:59 chs Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * uvm_amap.c: amap operations * * this file contains functions that perform operations on amaps. see * uvm_amap.h for a brief explanation of the role of amaps in uvm. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/kernel.h> #include <sys/pool.h> #include <sys/atomic.h> #include <uvm/uvm.h> #include <uvm/uvm_swap.h> /* * pools for allocation of vm_amap structures. note that in order to * avoid an endless loop, the amap pool's allocator cannot allocate * memory from an amap (it currently goes through the kernel uobj, so * we are ok). */ struct pool uvm_amap_pool; struct pool uvm_small_amap_pool[UVM_AMAP_CHUNK]; struct pool uvm_amap_chunk_pool; LIST_HEAD(, vm_amap) amap_list; struct rwlock amap_list_lock = RWLOCK_INITIALIZER("amaplstlk"); #define amap_lock_list() rw_enter_write(&amap_list_lock) #define amap_unlock_list() rw_exit_write(&amap_list_lock) static char amap_small_pool_names[UVM_AMAP_CHUNK][9]; /* * local functions */ static struct vm_amap *amap_alloc1(int, int, int); static inline void amap_list_insert(struct vm_amap *); static inline void amap_list_remove(struct vm_amap *); struct vm_amap_chunk *amap_chunk_get(struct vm_amap *, int, int, int); void amap_chunk_free(struct vm_amap *, struct vm_amap_chunk *); /* * if we enable PPREF, then we have a couple of extra functions that * we need to prototype here... */ #ifdef UVM_AMAP_PPREF #define PPREF_NONE ((int *) -1) /* not using ppref */ void amap_pp_adjref(struct vm_amap *, int, vsize_t, int); void amap_pp_establish(struct vm_amap *); void amap_wiperange_chunk(struct vm_amap *, struct vm_amap_chunk *, int, int); void amap_wiperange(struct vm_amap *, int, int); #endif /* UVM_AMAP_PPREF */ static inline void amap_list_insert(struct vm_amap *amap) { amap_lock_list(); LIST_INSERT_HEAD(&amap_list, amap, am_list); amap_unlock_list(); } static inline void amap_list_remove(struct vm_amap *amap) { amap_lock_list(); LIST_REMOVE(amap, am_list); amap_unlock_list(); } /* * amap_chunk_get: lookup a chunk for slot. if create is non-zero, * the chunk is created if it does not yet exist. * * => returns the chunk on success or NULL on error */ struct vm_amap_chunk * amap_chunk_get(struct vm_amap *amap, int slot, int create, int waitf) { int bucket = UVM_AMAP_BUCKET(amap, slot); int baseslot = AMAP_BASE_SLOT(slot); int n; struct vm_amap_chunk *chunk, *newchunk, *pchunk = NULL; if (UVM_AMAP_SMALL(amap)) return &amap->am_small; for (chunk = amap->am_buckets[bucket]; chunk != NULL; chunk = TAILQ_NEXT(chunk, ac_list)) { if (UVM_AMAP_BUCKET(amap, chunk->ac_baseslot) != bucket) break; if (chunk->ac_baseslot == baseslot) return chunk; pchunk = chunk; } if (!create) return NULL; if (amap->am_nslot - baseslot >= UVM_AMAP_CHUNK) n = UVM_AMAP_CHUNK; else n = amap->am_nslot - baseslot; newchunk = pool_get(&uvm_amap_chunk_pool, waitf | PR_ZERO); if (newchunk == NULL) return NULL; if (pchunk == NULL) { TAILQ_INSERT_TAIL(&amap->am_chunks, newchunk, ac_list); KASSERT(amap->am_buckets[bucket] == NULL); amap->am_buckets[bucket] = newchunk; } else TAILQ_INSERT_AFTER(&amap->am_chunks, pchunk, newchunk, ac_list); amap->am_ncused++; newchunk->ac_baseslot = baseslot; newchunk->ac_nslot = n; return newchunk; } void amap_chunk_free(struct vm_amap *amap, struct vm_amap_chunk *chunk) { int bucket = UVM_AMAP_BUCKET(amap, chunk->ac_baseslot); struct vm_amap_chunk *nchunk; if (UVM_AMAP_SMALL(amap)) return; nchunk = TAILQ_NEXT(chunk, ac_list); TAILQ_REMOVE(&amap->am_chunks, chunk, ac_list); if (amap->am_buckets[bucket] == chunk) { if (nchunk != NULL && UVM_AMAP_BUCKET(amap, nchunk->ac_baseslot) == bucket) amap->am_buckets[bucket] = nchunk; else amap->am_buckets[bucket] = NULL; } pool_put(&uvm_amap_chunk_pool, chunk); amap->am_ncused--; } #ifdef UVM_AMAP_PPREF /* * what is ppref? ppref is an _optional_ amap feature which is used * to keep track of reference counts on a per-page basis. it is enabled * when UVM_AMAP_PPREF is defined. * * when enabled, an array of ints is allocated for the pprefs. this * array is allocated only when a partial reference is added to the * map (either by unmapping part of the amap, or gaining a reference * to only a part of an amap). if the allocation of the array fails * (M_NOWAIT), then we set the array pointer to PPREF_NONE to indicate * that we tried to do ppref's but couldn't alloc the array so just * give up (after all, this is an optional feature!). * * the array is divided into page sized "chunks." for chunks of length 1, * the chunk reference count plus one is stored in that chunk's slot. * for chunks of length > 1 the first slot contains (the reference count * plus one) * -1. [the negative value indicates that the length is * greater than one.] the second slot of the chunk contains the length * of the chunk. here is an example: * * actual REFS: 2 2 2 2 3 1 1 0 0 0 4 4 0 1 1 1 * ppref: -3 4 x x 4 -2 2 -1 3 x -5 2 1 -2 3 x * <----------><-><----><-------><----><-><-------> * (x = don't care) * * this allows us to allow one int to contain the ref count for the whole * chunk. note that the "plus one" part is needed because a reference * count of zero is neither positive or negative (need a way to tell * if we've got one zero or a bunch of them). * * here are some in-line functions to help us. */ /* * pp_getreflen: get the reference and length for a specific offset * * => ppref's amap must be locked */ static inline void pp_getreflen(int *ppref, int offset, int *refp, int *lenp) { if (ppref[offset] > 0) { /* chunk size must be 1 */ *refp = ppref[offset] - 1; /* don't forget to adjust */ *lenp = 1; } else { *refp = (ppref[offset] * -1) - 1; *lenp = ppref[offset+1]; } } /* * pp_setreflen: set the reference and length for a specific offset * * => ppref's amap must be locked */ static inline void pp_setreflen(int *ppref, int offset, int ref, int len) { if (len == 1) { ppref[offset] = ref + 1; } else { ppref[offset] = (ref + 1) * -1; ppref[offset+1] = len; } } #endif /* UVM_AMAP_PPREF */ /* * amap_init: called at boot time to init global amap data structures */ void amap_init(void) { int i; size_t size; /* Initialize the vm_amap pool. */ pool_init(&uvm_amap_pool, sizeof(struct vm_amap), 0, IPL_MPFLOOR, PR_WAITOK, "amappl", NULL); pool_sethiwat(&uvm_amap_pool, 4096); /* initialize small amap pools */ for (i = 0; i < nitems(uvm_small_amap_pool); i++) { snprintf(amap_small_pool_names[i], sizeof(amap_small_pool_names[0]), "amappl%d", i + 1); size = offsetof(struct vm_amap, am_small.ac_anon) + (i + 1) * sizeof(struct vm_anon *); pool_init(&uvm_small_amap_pool[i], size, 0, IPL_MPFLOOR, PR_WAITOK, amap_small_pool_names[i], NULL); } pool_init(&uvm_amap_chunk_pool, sizeof(struct vm_amap_chunk) + UVM_AMAP_CHUNK * sizeof(struct vm_anon *), 0, IPL_MPFLOOR, PR_WAITOK, "amapchunkpl", NULL); pool_sethiwat(&uvm_amap_chunk_pool, 4096); } /* * amap_alloc1: allocate an amap, but do not initialise the overlay. * * => Note: lock is not set. */ static inline struct vm_amap * amap_alloc1(int slots, int waitf, int lazyalloc) { struct vm_amap *amap; struct vm_amap_chunk *chunk, *tmp; int chunks, log_chunks, chunkperbucket = 1, hashshift = 0; int buckets, i, n; int pwaitf = (waitf & M_WAITOK) ? PR_WAITOK : PR_NOWAIT; KASSERT(slots > 0); /* * Cast to unsigned so that rounding up cannot cause integer overflow * if slots is large. */ chunks = roundup((unsigned int)slots, UVM_AMAP_CHUNK) / UVM_AMAP_CHUNK; if (lazyalloc) { /* * Basically, the amap is a hash map where the number of * buckets is fixed. We select the number of buckets using the * following strategy: * * 1. The maximal number of entries to search in a bucket upon * a collision should be less than or equal to * log2(slots / UVM_AMAP_CHUNK). This is the worst-case number * of lookups we would have if we could chunk the amap. The * log2(n) comes from the fact that amaps are chunked by * splitting up their vm_map_entries and organizing those * in a binary search tree. * * 2. The maximal number of entries in a bucket must be a * power of two. * * The maximal number of entries per bucket is used to hash * a slot to a bucket. * * In the future, this strategy could be refined to make it * even harder/impossible that the total amount of KVA needed * for the hash buckets of all amaps to exceed the maximal * amount of KVA memory reserved for amaps. */ for (log_chunks = 1; (chunks >> log_chunks) > 0; log_chunks++) continue; chunkperbucket = 1 << hashshift; while (chunkperbucket + 1 < log_chunks) { hashshift++; chunkperbucket = 1 << hashshift; } } if (slots > UVM_AMAP_CHUNK) amap = pool_get(&uvm_amap_pool, pwaitf); else amap = pool_get(&uvm_small_amap_pool[slots - 1], pwaitf | PR_ZERO); if (amap == NULL) return NULL; amap->am_lock = NULL; amap->am_ref = 1; amap->am_flags = 0; #ifdef UVM_AMAP_PPREF amap->am_ppref = NULL; #endif amap->am_nslot = slots; amap->am_nused = 0; if (UVM_AMAP_SMALL(amap)) { amap->am_small.ac_nslot = slots; return amap; } amap->am_ncused = 0; TAILQ_INIT(&amap->am_chunks); amap->am_hashshift = hashshift; amap->am_buckets = NULL; buckets = howmany(chunks, chunkperbucket); amap->am_buckets = mallocarray(buckets, sizeof(*amap->am_buckets), M_UVMAMAP, waitf | (lazyalloc ? M_ZERO : 0)); if (amap->am_buckets == NULL) goto fail1; amap->am_nbuckets = buckets; if (!lazyalloc) { for (i = 0; i < buckets; i++) { if (i == buckets - 1) { n = slots % UVM_AMAP_CHUNK; if (n == 0) n = UVM_AMAP_CHUNK; } else n = UVM_AMAP_CHUNK; chunk = pool_get(&uvm_amap_chunk_pool, PR_ZERO | pwaitf); if (chunk == NULL) goto fail1; amap->am_buckets[i] = chunk; amap->am_ncused++; chunk->ac_baseslot = i * UVM_AMAP_CHUNK; chunk->ac_nslot = n; TAILQ_INSERT_TAIL(&amap->am_chunks, chunk, ac_list); } } return amap; fail1: free(amap->am_buckets, M_UVMAMAP, buckets * sizeof(*amap->am_buckets)); TAILQ_FOREACH_SAFE(chunk, &amap->am_chunks, ac_list, tmp) pool_put(&uvm_amap_chunk_pool, chunk); pool_put(&uvm_amap_pool, amap); return NULL; } static void amap_lock_alloc(struct vm_amap *amap) { rw_obj_alloc(&amap->am_lock, "amaplk"); } /* * amap_alloc: allocate an amap to manage "sz" bytes of anonymous VM * * => caller should ensure sz is a multiple of PAGE_SIZE * => reference count to new amap is set to one * => new amap is returned unlocked */ struct vm_amap * amap_alloc(vaddr_t sz, int waitf, int lazyalloc) { struct vm_amap *amap; size_t slots; AMAP_B2SLOT(slots, sz); /* load slots */ if (slots > INT_MAX) return NULL; amap = amap_alloc1(slots, waitf, lazyalloc); if (amap != NULL) { amap_lock_alloc(amap); amap_list_insert(amap); } return amap; } /* * amap_free: free an amap * * => the amap must be unlocked * => the amap should have a zero reference count and be empty */ void amap_free(struct vm_amap *amap) { struct vm_amap_chunk *chunk, *tmp; KASSERT(amap->am_ref == 0 && amap->am_nused == 0); KASSERT((amap->am_flags & AMAP_SWAPOFF) == 0); if (amap->am_lock != NULL) { KASSERT(!rw_write_held(amap->am_lock)); rw_obj_free(amap->am_lock); } #ifdef UVM_AMAP_PPREF if (amap->am_ppref && amap->am_ppref != PPREF_NONE) free(amap->am_ppref, M_UVMAMAP, amap->am_nslot * sizeof(int)); #endif if (UVM_AMAP_SMALL(amap)) pool_put(&uvm_small_amap_pool[amap->am_nslot - 1], amap); else { TAILQ_FOREACH_SAFE(chunk, &amap->am_chunks, ac_list, tmp) pool_put(&uvm_amap_chunk_pool, chunk); free(amap->am_buckets, M_UVMAMAP, amap->am_nbuckets * sizeof(*amap->am_buckets)); pool_put(&uvm_amap_pool, amap); } } /* * amap_wipeout: wipeout all anon's in an amap; then free the amap! * * => Called from amap_unref(), when reference count drops to zero. * => amap must be locked. */ void amap_wipeout(struct vm_amap *amap) { int slot; struct vm_anon *anon; struct vm_amap_chunk *chunk; KASSERT(rw_write_held(amap->am_lock)); KASSERT(amap->am_ref == 0); if (__predict_false((amap->am_flags & AMAP_SWAPOFF) != 0)) { /* * Note: amap_swap_off() will call us again. */ amap_unlock(amap); return; } amap_list_remove(amap); AMAP_CHUNK_FOREACH(chunk, amap) { int i, refs, map = chunk->ac_usedmap; for (i = ffs(map); i != 0; i = ffs(map)) { slot = i - 1; map ^= 1 << slot; anon = chunk->ac_anon[slot]; if (anon == NULL || anon->an_ref == 0) panic("amap_wipeout: corrupt amap"); KASSERT(anon->an_lock == amap->am_lock); /* * Drop the reference. */ refs = --anon->an_ref; if (refs == 0) { uvm_anfree(anon); } } } /* * Finally, destroy the amap. */ amap->am_ref = 0; /* ... was one */ amap->am_nused = 0; amap_unlock(amap); amap_free(amap); } /* * amap_copy: ensure that a map entry's "needs_copy" flag is false * by copying the amap if necessary. * * => an entry with a null amap pointer will get a new (blank) one. * => the map that the map entry belongs to must be locked by caller. * => the amap currently attached to "entry" (if any) must be unlocked. * => if canchunk is true, then we may clip the entry into a chunk * => "startva" and "endva" are used only if canchunk is true. they are * used to limit chunking (e.g. if you have a large space that you * know you are going to need to allocate amaps for, there is no point * in allowing that to be chunked) */ void amap_copy(struct vm_map *map, struct vm_map_entry *entry, int waitf, boolean_t canchunk, vaddr_t startva, vaddr_t endva) { struct vm_amap *amap, *srcamap; int slots, lcv, lazyalloc = 0; vaddr_t chunksize; int i, j, k, n, srcslot; struct vm_amap_chunk *chunk = NULL, *srcchunk = NULL; struct vm_anon *anon; KASSERT(map != kernel_map); /* we use sleeping locks */ /* * Is there an amap to copy? If not, create one. */ if (entry->aref.ar_amap == NULL) { /* * Check to see if we have a large amap that we can * chunk. We align startva/endva to chunk-sized * boundaries and then clip to them. * * If we cannot chunk the amap, allocate it in a way * that makes it grow or shrink dynamically with * the number of slots. */ if (atop(entry->end - entry->start) >= UVM_AMAP_LARGE) { if (canchunk) { /* convert slots to bytes */ chunksize = UVM_AMAP_CHUNK << PAGE_SHIFT; startva = (startva / chunksize) * chunksize; endva = roundup(endva, chunksize); UVM_MAP_CLIP_START(map, entry, startva); /* watch out for endva wrap-around! */ if (endva >= startva) UVM_MAP_CLIP_END(map, entry, endva); } else lazyalloc = 1; } entry->aref.ar_pageoff = 0; entry->aref.ar_amap = amap_alloc(entry->end - entry->start, waitf, lazyalloc); if (entry->aref.ar_amap != NULL) entry->etype &= ~UVM_ET_NEEDSCOPY; return; } /* * First check and see if we are the only map entry referencing * he amap we currently have. If so, then just take it over instead * of copying it. Note that we are reading am_ref without lock held * as the value can only be one if we have the only reference * to the amap (via our locked map). If the value is greater than * one, then allocate amap and re-check the value. */ if (entry->aref.ar_amap->am_ref == 1) { entry->etype &= ~UVM_ET_NEEDSCOPY; return; } /* * Allocate a new amap (note: not initialised, etc). */ AMAP_B2SLOT(slots, entry->end - entry->start); if (!UVM_AMAP_SMALL(entry->aref.ar_amap) && entry->aref.ar_amap->am_hashshift != 0) lazyalloc = 1; amap = amap_alloc1(slots, waitf, lazyalloc); if (amap == NULL) return; srcamap = entry->aref.ar_amap; /* * Make the new amap share the source amap's lock, and then lock * both. */ amap->am_lock = srcamap->am_lock; rw_obj_hold(amap->am_lock); amap_lock(srcamap); /* * Re-check the reference count with the lock held. If it has * dropped to one - we can take over the existing map. */ if (srcamap->am_ref == 1) { /* Just take over the existing amap. */ entry->etype &= ~UVM_ET_NEEDSCOPY; amap_unlock(srcamap); /* Destroy the new (unused) amap. */ amap->am_ref--; amap_free(amap); return; } /* * Copy the slots. */ for (lcv = 0; lcv < slots; lcv += n) { srcslot = entry->aref.ar_pageoff + lcv; i = UVM_AMAP_SLOTIDX(lcv); j = UVM_AMAP_SLOTIDX(srcslot); n = UVM_AMAP_CHUNK; if (i > j) n -= i; else n -= j; if (lcv + n > slots) n = slots - lcv; srcchunk = amap_chunk_get(srcamap, srcslot, 0, PR_NOWAIT); if (srcchunk == NULL) continue; chunk = amap_chunk_get(amap, lcv, 1, PR_NOWAIT); if (chunk == NULL) { amap_unlock(srcamap); /* Destroy the new amap. */ amap->am_ref--; amap_free(amap); return; } for (k = 0; k < n; i++, j++, k++) { chunk->ac_anon[i] = anon = srcchunk->ac_anon[j]; if (anon == NULL) continue; KASSERT(anon->an_lock == srcamap->am_lock); KASSERT(anon->an_ref > 0); chunk->ac_usedmap |= (1 << i); anon->an_ref++; amap->am_nused++; } } /* * Drop our reference to the old amap (srcamap) and unlock. * Since the reference count on srcamap is greater than one, * (we checked above), it cannot drop to zero while it is locked. */ srcamap->am_ref--; KASSERT(srcamap->am_ref > 0); if (srcamap->am_ref == 1 && (srcamap->am_flags & AMAP_SHARED) != 0) srcamap->am_flags &= ~AMAP_SHARED; /* clear shared flag */ #ifdef UVM_AMAP_PPREF if (srcamap->am_ppref && srcamap->am_ppref != PPREF_NONE) { amap_pp_adjref(srcamap, entry->aref.ar_pageoff, (entry->end - entry->start) >> PAGE_SHIFT, -1); } #endif /* * If we referenced any anons, then share the source amap's lock. * Otherwise, we have nothing in common, so allocate a new one. */ KASSERT(amap->am_lock == srcamap->am_lock); if (amap->am_nused == 0) { rw_obj_free(amap->am_lock); amap->am_lock = NULL; } amap_unlock(srcamap); if (amap->am_lock == NULL) amap_lock_alloc(amap); /* * Install new amap. */ entry->aref.ar_pageoff = 0; entry->aref.ar_amap = amap; entry->etype &= ~UVM_ET_NEEDSCOPY; amap_list_insert(amap); } /* * amap_cow_now: resolve all copy-on-write faults in an amap now for fork(2) * * called during fork(2) when the parent process has a wired map * entry. in that case we want to avoid write-protecting pages * in the parent's map (e.g. like what you'd do for a COW page) * so we resolve the COW here. * * => assume parent's entry was wired, thus all pages are resident. * => the parent and child vm_map must both be locked. * => caller passes child's map/entry in to us * => XXXCDC: out of memory should cause fork to fail, but there is * currently no easy way to do this (needs fix) */ void amap_cow_now(struct vm_map *map, struct vm_map_entry *entry) { struct vm_amap *amap = entry->aref.ar_amap; int slot; struct vm_anon *anon, *nanon; struct vm_page *pg, *npg; struct vm_amap_chunk *chunk; /* * note that if we unlock the amap then we must ReStart the "lcv" for * loop because some other process could reorder the anon's in the * am_anon[] array on us while the lock is dropped. */ ReStart: amap_lock(amap); AMAP_CHUNK_FOREACH(chunk, amap) { int i, map = chunk->ac_usedmap; for (i = ffs(map); i != 0; i = ffs(map)) { slot = i - 1; map ^= 1 << slot; anon = chunk->ac_anon[slot]; pg = anon->an_page; KASSERT(anon->an_lock == amap->am_lock); /* * The old page must be resident since the parent is * wired. */ KASSERT(pg != NULL); /* * if the anon ref count is one, we are safe (the child * has exclusive access to the page). */ if (anon->an_ref <= 1) continue; /* * If the page is busy, then we have to unlock, wait for * it and then restart. */ if (pg->pg_flags & PG_BUSY) { uvm_pagewait(pg, amap->am_lock, "cownow"); goto ReStart; } /* * Perform a copy-on-write. * First - get a new anon and a page. */ nanon = uvm_analloc(); if (nanon != NULL) { /* the new anon will share the amap's lock */ nanon->an_lock = amap->am_lock; npg = uvm_pagealloc(NULL, 0, nanon, 0); } else npg = NULL; /* XXX: quiet gcc warning */ if (nanon == NULL || npg == NULL) { /* out of memory */ amap_unlock(amap); if (nanon != NULL) { nanon->an_lock = NULL; nanon->an_ref--; KASSERT(nanon->an_ref == 0); uvm_anfree(nanon); } uvm_wait("cownowpage"); goto ReStart; } /* * Copy the data and replace anon with the new one. * Also, setup its lock (share the with amap's lock). */ uvm_pagecopy(pg, npg); anon->an_ref--; KASSERT(anon->an_ref > 0); chunk->ac_anon[slot] = nanon; /* * Drop PG_BUSY on new page. Since its owner was write * locked all this time - it cannot be PG_RELEASED or * PG_WANTED. */ atomic_clearbits_int(&npg->pg_flags, PG_BUSY|PG_FAKE); UVM_PAGE_OWN(npg, NULL); uvm_lock_pageq(); uvm_pageactivate(npg); uvm_unlock_pageq(); } } amap_unlock(amap); } /* * amap_splitref: split a single reference into two separate references * * => called from uvm_map's clip routines * => origref's map should be locked * => origref->ar_amap should be unlocked (we will lock) */ void amap_splitref(struct vm_aref *origref, struct vm_aref *splitref, vaddr_t offset) { struct vm_amap *amap = origref->ar_amap; int leftslots; KASSERT(splitref->ar_amap == amap); AMAP_B2SLOT(leftslots, offset); if (leftslots == 0) panic("amap_splitref: split at zero offset"); amap_lock(amap); if (amap->am_nslot - origref->ar_pageoff - leftslots <= 0) panic("amap_splitref: map size check failed"); #ifdef UVM_AMAP_PPREF /* Establish ppref before we add a duplicate reference to the amap. */ if (amap->am_ppref == NULL) amap_pp_establish(amap); #endif /* Note: not a share reference. */ amap->am_ref++; splitref->ar_amap = amap; splitref->ar_pageoff = origref->ar_pageoff + leftslots; amap_unlock(amap); } #ifdef UVM_AMAP_PPREF /* * amap_pp_establish: add a ppref array to an amap, if possible. * * => amap should be locked by caller* => amap should be locked by caller */ void amap_pp_establish(struct vm_amap *amap) { KASSERT(rw_write_held(amap->am_lock)); amap->am_ppref = mallocarray(amap->am_nslot, sizeof(int), M_UVMAMAP, M_NOWAIT|M_ZERO); if (amap->am_ppref == NULL) { /* Failure - just do not use ppref. */ amap->am_ppref = PPREF_NONE; return; } pp_setreflen(amap->am_ppref, 0, amap->am_ref, amap->am_nslot); } /* * amap_pp_adjref: adjust reference count to a part of an amap using the * per-page reference count array. * * => caller must check that ppref != PPREF_NONE before calling. * => map and amap must be locked. */ void amap_pp_adjref(struct vm_amap *amap, int curslot, vsize_t slotlen, int adjval) { int stopslot, *ppref, lcv, prevlcv; int ref, len, prevref, prevlen; KASSERT(rw_write_held(amap->am_lock)); stopslot = curslot + slotlen; ppref = amap->am_ppref; prevlcv = 0; /* * Advance to the correct place in the array, fragment if needed. */ for (lcv = 0 ; lcv < curslot ; lcv += len) { pp_getreflen(ppref, lcv, &ref, &len); if (lcv + len > curslot) { /* goes past start? */ pp_setreflen(ppref, lcv, ref, curslot - lcv); pp_setreflen(ppref, curslot, ref, len - (curslot -lcv)); len = curslot - lcv; /* new length of entry @ lcv */ } prevlcv = lcv; } if (lcv != 0) pp_getreflen(ppref, prevlcv, &prevref, &prevlen); else { /* * Ensure that the "prevref == ref" test below always * fails, since we are starting from the beginning of * the ppref array; that is, there is no previous chunk. */ prevref = -1; prevlen = 0; } /* * Now adjust reference counts in range. Merge the first * changed entry with the last unchanged entry if possible. */ if (lcv != curslot) panic("amap_pp_adjref: overshot target"); for (/* lcv already set */; lcv < stopslot ; lcv += len) { pp_getreflen(ppref, lcv, &ref, &len); if (lcv + len > stopslot) { /* goes past end? */ pp_setreflen(ppref, lcv, ref, stopslot - lcv); pp_setreflen(ppref, stopslot, ref, len - (stopslot - lcv)); len = stopslot - lcv; } ref += adjval; if (ref < 0) panic("amap_pp_adjref: negative reference count"); if (lcv == prevlcv + prevlen && ref == prevref) { pp_setreflen(ppref, prevlcv, ref, prevlen + len); } else { pp_setreflen(ppref, lcv, ref, len); } if (ref == 0) amap_wiperange(amap, lcv, len); } } void amap_wiperange_chunk(struct vm_amap *amap, struct vm_amap_chunk *chunk, int slotoff, int slots) { int curslot, i, map; int startbase, endbase; struct vm_anon *anon; startbase = AMAP_BASE_SLOT(slotoff); endbase = AMAP_BASE_SLOT(slotoff + slots - 1); map = chunk->ac_usedmap; if (startbase == chunk->ac_baseslot) map &= ~((1 << (slotoff - startbase)) - 1); if (endbase == chunk->ac_baseslot) map &= (1 << (slotoff + slots - endbase)) - 1; for (i = ffs(map); i != 0; i = ffs(map)) { int refs; curslot = i - 1; map ^= 1 << curslot; chunk->ac_usedmap ^= 1 << curslot; anon = chunk->ac_anon[curslot]; KASSERT(anon->an_lock == amap->am_lock); /* remove it from the amap */ chunk->ac_anon[curslot] = NULL; amap->am_nused--; /* drop anon reference count */ refs = --anon->an_ref; if (refs == 0) { uvm_anfree(anon); } /* * done with this anon, next ...! */ } /* end of 'for' loop */ } /* * amap_wiperange: wipe out a range of an amap. * Note: different from amap_wipeout because the amap is kept intact. * * => Both map and amap must be locked by caller. */ void amap_wiperange(struct vm_amap *amap, int slotoff, int slots) { int bucket, startbucket, endbucket; struct vm_amap_chunk *chunk, *nchunk; KASSERT(rw_write_held(amap->am_lock)); startbucket = UVM_AMAP_BUCKET(amap, slotoff); endbucket = UVM_AMAP_BUCKET(amap, slotoff + slots - 1); /* * We can either traverse the amap by am_chunks or by am_buckets. * Determine which way is less expensive. */ if (UVM_AMAP_SMALL(amap)) amap_wiperange_chunk(amap, &amap->am_small, slotoff, slots); else if (endbucket + 1 - startbucket >= amap->am_ncused) { TAILQ_FOREACH_SAFE(chunk, &amap->am_chunks, ac_list, nchunk) { if (chunk->ac_baseslot + chunk->ac_nslot <= slotoff) continue; if (chunk->ac_baseslot >= slotoff + slots) continue; amap_wiperange_chunk(amap, chunk, slotoff, slots); if (chunk->ac_usedmap == 0) amap_chunk_free(amap, chunk); } } else { for (bucket = startbucket; bucket <= endbucket; bucket++) { for (chunk = amap->am_buckets[bucket]; chunk != NULL; chunk = nchunk) { nchunk = TAILQ_NEXT(chunk, ac_list); if (UVM_AMAP_BUCKET(amap, chunk->ac_baseslot) != bucket) break; if (chunk->ac_baseslot + chunk->ac_nslot <= slotoff) continue; if (chunk->ac_baseslot >= slotoff + slots) continue; amap_wiperange_chunk(amap, chunk, slotoff, slots); if (chunk->ac_usedmap == 0) amap_chunk_free(amap, chunk); } } } } #endif /* * amap_swap_off: pagein anonymous pages in amaps and drop swap slots. * * => note that we don't always traverse all anons. * eg. amaps being wiped out, released anons. * => return TRUE if failed. */ boolean_t amap_swap_off(int startslot, int endslot) { struct vm_amap *am; struct vm_amap *am_next; struct vm_amap marker; boolean_t rv = FALSE; amap_lock_list(); for (am = LIST_FIRST(&amap_list); am != NULL && !rv; am = am_next) { int i, map; struct vm_amap_chunk *chunk; amap_lock(am); if (am->am_nused == 0) { amap_unlock(am); am_next = LIST_NEXT(am, am_list); continue; } LIST_INSERT_AFTER(am, &marker, am_list); amap_unlock_list(); again: AMAP_CHUNK_FOREACH(chunk, am) { map = chunk->ac_usedmap; for (i = ffs(map); i != 0; i = ffs(map)) { int swslot; int slot = i - 1; struct vm_anon *anon; map ^= 1 << slot; anon = chunk->ac_anon[slot]; swslot = anon->an_swslot; if (swslot < startslot || endslot <= swslot) { continue; } am->am_flags |= AMAP_SWAPOFF; rv = uvm_anon_pagein(am, anon); amap_lock(am); am->am_flags &= ~AMAP_SWAPOFF; if (amap_refs(am) == 0) { amap_wipeout(am); am = NULL; goto nextamap; } if (rv) goto nextamap; goto again; } } nextamap: if (am != NULL) amap_unlock(am); amap_lock_list(); am_next = LIST_NEXT(&marker, am_list); LIST_REMOVE(&marker, am_list); } amap_unlock_list(); return rv; } /* * amap_lookup: look up a page in an amap. * * => amap should be locked by caller. */ struct vm_anon * amap_lookup(struct vm_aref *aref, vaddr_t offset) { int slot; struct vm_amap *amap = aref->ar_amap; struct vm_amap_chunk *chunk; AMAP_B2SLOT(slot, offset); slot += aref->ar_pageoff; KASSERT(slot < amap->am_nslot); chunk = amap_chunk_get(amap, slot, 0, PR_NOWAIT); if (chunk == NULL) return NULL; return chunk->ac_anon[UVM_AMAP_SLOTIDX(slot)]; } /* * amap_lookups: look up a range of pages in an amap. * * => amap should be locked by caller. * => XXXCDC: this interface is biased toward array-based amaps. fix. */ void amap_lookups(struct vm_aref *aref, vaddr_t offset, struct vm_anon **anons, int npages) { int i, lcv, n, slot; struct vm_amap *amap = aref->ar_amap; struct vm_amap_chunk *chunk = NULL; AMAP_B2SLOT(slot, offset); slot += aref->ar_pageoff; KASSERT((slot + (npages - 1)) < amap->am_nslot); for (i = 0, lcv = slot; lcv < slot + npages; i += n, lcv += n) { n = UVM_AMAP_CHUNK - UVM_AMAP_SLOTIDX(lcv); if (lcv + n > slot + npages) n = slot + npages - lcv; chunk = amap_chunk_get(amap, lcv, 0, PR_NOWAIT); if (chunk == NULL) memset(&anons[i], 0, n * sizeof(*anons)); else memcpy(&anons[i], &chunk->ac_anon[UVM_AMAP_SLOTIDX(lcv)], n * sizeof(*anons)); } } /* * amap_populate: ensure that the amap can store an anon for the page at * offset. This function can sleep until memory to store the anon is * available. */ void amap_populate(struct vm_aref *aref, vaddr_t offset) { int slot; struct vm_amap *amap = aref->ar_amap; struct vm_amap_chunk *chunk; AMAP_B2SLOT(slot, offset); slot += aref->ar_pageoff; KASSERT(slot < amap->am_nslot); chunk = amap_chunk_get(amap, slot, 1, PR_WAITOK); KASSERT(chunk != NULL); } /* * amap_add: add (or replace) a page to an amap. * * => amap should be locked by caller. * => anon must have the lock associated with this amap. */ int amap_add(struct vm_aref *aref, vaddr_t offset, struct vm_anon *anon, boolean_t replace) { int slot; struct vm_amap *amap = aref->ar_amap; struct vm_amap_chunk *chunk; AMAP_B2SLOT(slot, offset); slot += aref->ar_pageoff; KASSERT(slot < amap->am_nslot); chunk = amap_chunk_get(amap, slot, 1, PR_NOWAIT); if (chunk == NULL) return 1; slot = UVM_AMAP_SLOTIDX(slot); if (replace) { struct vm_anon *oanon = chunk->ac_anon[slot]; KASSERT(oanon != NULL); if (oanon->an_page && (amap->am_flags & AMAP_SHARED) != 0) { pmap_page_protect(oanon->an_page, PROT_NONE); /* * XXX: suppose page is supposed to be wired somewhere? */ } } else { /* !replace */ if (chunk->ac_anon[slot] != NULL) panic("amap_add: slot in use"); chunk->ac_usedmap |= 1 << slot; amap->am_nused++; } chunk->ac_anon[slot] = anon; return 0; } /* * amap_unadd: remove a page from an amap. * * => amap should be locked by caller. */ void amap_unadd(struct vm_aref *aref, vaddr_t offset) { struct vm_amap *amap = aref->ar_amap; struct vm_amap_chunk *chunk; int slot; KASSERT(rw_write_held(amap->am_lock)); AMAP_B2SLOT(slot, offset); slot += aref->ar_pageoff; KASSERT(slot < amap->am_nslot); chunk = amap_chunk_get(amap, slot, 0, PR_NOWAIT); KASSERT(chunk != NULL); slot = UVM_AMAP_SLOTIDX(slot); KASSERT(chunk->ac_anon[slot] != NULL); chunk->ac_anon[slot] = NULL; chunk->ac_usedmap &= ~(1 << slot); amap->am_nused--; if (chunk->ac_usedmap == 0) amap_chunk_free(amap, chunk); } /* * amap_adjref_anons: adjust the reference count(s) on amap and its anons. */ static void amap_adjref_anons(struct vm_amap *amap, vaddr_t offset, vsize_t len, int refv, boolean_t all) { #ifdef UVM_AMAP_PPREF KASSERT(rw_write_held(amap->am_lock)); /* * We must establish the ppref array before changing am_ref * so that the ppref values match the current amap refcount. */ if (amap->am_ppref == NULL && !all && len != amap->am_nslot) { amap_pp_establish(amap); } #endif amap->am_ref += refv; #ifdef UVM_AMAP_PPREF if (amap->am_ppref && amap->am_ppref != PPREF_NONE) { if (all) { amap_pp_adjref(amap, 0, amap->am_nslot, refv); } else { amap_pp_adjref(amap, offset, len, refv); } } #endif amap_unlock(amap); } /* * amap_ref: gain a reference to an amap. * * => amap must not be locked (we will lock). * => "offset" and "len" are in units of pages. * => Called at fork time to gain the child's reference. */ void amap_ref(struct vm_amap *amap, vaddr_t offset, vsize_t len, int flags) { amap_lock(amap); if (flags & AMAP_SHARED) amap->am_flags |= AMAP_SHARED; amap_adjref_anons(amap, offset, len, 1, (flags & AMAP_REFALL) != 0); } /* * amap_unref: remove a reference to an amap. * * => All pmap-level references to this amap must be already removed. * => Called from uvm_unmap_detach(); entry is already removed from the map. * => We will lock amap, so it must be unlocked. */ void amap_unref(struct vm_amap *amap, vaddr_t offset, vsize_t len, boolean_t all) { amap_lock(amap); KASSERT(amap->am_ref > 0); if (amap->am_ref == 1) { /* * If the last reference - wipeout and destroy the amap. */ amap->am_ref--; amap_wipeout(amap); return; } /* * Otherwise, drop the reference count(s) on anons. */ if (amap->am_ref == 2 && (amap->am_flags & AMAP_SHARED) != 0) { amap->am_flags &= ~AMAP_SHARED; } amap_adjref_anons(amap, offset, len, -1, all); }
3287 1729 427 516 391 262 590 685 27 239 544 233 151 570 588 53 161 1766 443 370 258 368 444 440 328 367 220 440 844 473 279 498 244 459 239 193 304 305 371 113 350 227 319 129 130 219 219 520 322 562 197 595 577 122 457 375 541 181 1544 1523 232 1522 844 1566 1570 1563 1767 1527 1 1513 1038 360 1723 1767 2749 2633 2731 2209 2020 3523 3529 1141 3317 2077 767 2035 371 373 286 330 245 3324 3313 1360 1303 1359 18 18 17 3250 1688 436 448 434 432 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 /* $OpenBSD: subr_tree.c,v 1.10 2018/10/09 08:28:43 dlg Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2016 David Gwynne <dlg@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/tree.h> static inline struct rb_entry * rb_n2e(const struct rb_type *t, void *node) { unsigned long addr = (unsigned long)node; return ((struct rb_entry *)(addr + t->t_offset)); } static inline void * rb_e2n(const struct rb_type *t, struct rb_entry *rbe) { unsigned long addr = (unsigned long)rbe; return ((void *)(addr - t->t_offset)); } #define RBE_LEFT(_rbe) (_rbe)->rbt_left #define RBE_RIGHT(_rbe) (_rbe)->rbt_right #define RBE_PARENT(_rbe) (_rbe)->rbt_parent #define RBE_COLOR(_rbe) (_rbe)->rbt_color #define RBH_ROOT(_rbt) (_rbt)->rbt_root static inline void rbe_set(struct rb_entry *rbe, struct rb_entry *parent) { RBE_PARENT(rbe) = parent; RBE_LEFT(rbe) = RBE_RIGHT(rbe) = NULL; RBE_COLOR(rbe) = RB_RED; } static inline void rbe_set_blackred(struct rb_entry *black, struct rb_entry *red) { RBE_COLOR(black) = RB_BLACK; RBE_COLOR(red) = RB_RED; } static inline void rbe_augment(const struct rb_type *t, struct rb_entry *rbe) { (*t->t_augment)(rb_e2n(t, rbe)); } static inline void rbe_if_augment(const struct rb_type *t, struct rb_entry *rbe) { if (t->t_augment != NULL) rbe_augment(t, rbe); } static inline void rbe_rotate_left(const struct rb_type *t, struct rb_tree *rbt, struct rb_entry *rbe) { struct rb_entry *parent; struct rb_entry *tmp; tmp = RBE_RIGHT(rbe); RBE_RIGHT(rbe) = RBE_LEFT(tmp); if (RBE_RIGHT(rbe) != NULL) RBE_PARENT(RBE_LEFT(tmp)) = rbe; parent = RBE_PARENT(rbe); RBE_PARENT(tmp) = parent; if (parent != NULL) { if (rbe == RBE_LEFT(parent)) RBE_LEFT(parent) = tmp; else RBE_RIGHT(parent) = tmp; } else RBH_ROOT(rbt) = tmp; RBE_LEFT(tmp) = rbe; RBE_PARENT(rbe) = tmp; if (t->t_augment != NULL) { rbe_augment(t, rbe); rbe_augment(t, tmp); parent = RBE_PARENT(tmp); if (parent != NULL) rbe_augment(t, parent); } } static inline void rbe_rotate_right(const struct rb_type *t, struct rb_tree *rbt, struct rb_entry *rbe) { struct rb_entry *parent; struct rb_entry *tmp; tmp = RBE_LEFT(rbe); RBE_LEFT(rbe) = RBE_RIGHT(tmp); if (RBE_LEFT(rbe) != NULL) RBE_PARENT(RBE_RIGHT(tmp)) = rbe; parent = RBE_PARENT(rbe); RBE_PARENT(tmp) = parent; if (parent != NULL) { if (rbe == RBE_LEFT(parent)) RBE_LEFT(parent) = tmp; else RBE_RIGHT(parent) = tmp; } else RBH_ROOT(rbt) = tmp; RBE_RIGHT(tmp) = rbe; RBE_PARENT(rbe) = tmp; if (t->t_augment != NULL) { rbe_augment(t, rbe); rbe_augment(t, tmp); parent = RBE_PARENT(tmp); if (parent != NULL) rbe_augment(t, parent); } } static inline void rbe_insert_color(const struct rb_type *t, struct rb_tree *rbt, struct rb_entry *rbe) { struct rb_entry *parent, *gparent, *tmp; while ((parent = RBE_PARENT(rbe)) != NULL && RBE_COLOR(parent) == RB_RED) { gparent = RBE_PARENT(parent); if (parent == RBE_LEFT(gparent)) { tmp = RBE_RIGHT(gparent); if (tmp != NULL && RBE_COLOR(tmp) == RB_RED) { RBE_COLOR(tmp) = RB_BLACK; rbe_set_blackred(parent, gparent); rbe = gparent; continue; } if (RBE_RIGHT(parent) == rbe) { rbe_rotate_left(t, rbt, parent); tmp = parent; parent = rbe; rbe = tmp; } rbe_set_blackred(parent, gparent); rbe_rotate_right(t, rbt, gparent); } else { tmp = RBE_LEFT(gparent); if (tmp != NULL && RBE_COLOR(tmp) == RB_RED) { RBE_COLOR(tmp) = RB_BLACK; rbe_set_blackred(parent, gparent); rbe = gparent; continue; } if (RBE_LEFT(parent) == rbe) { rbe_rotate_right(t, rbt, parent); tmp = parent; parent = rbe; rbe = tmp; } rbe_set_blackred(parent, gparent); rbe_rotate_left(t, rbt, gparent); } } RBE_COLOR(RBH_ROOT(rbt)) = RB_BLACK; } static inline void rbe_remove_color(const struct rb_type *t, struct rb_tree *rbt, struct rb_entry *parent, struct rb_entry *rbe) { struct rb_entry *tmp; while ((rbe == NULL || RBE_COLOR(rbe) == RB_BLACK) && rbe != RBH_ROOT(rbt)) { if (RBE_LEFT(parent) == rbe) { tmp = RBE_RIGHT(parent); if (RBE_COLOR(tmp) == RB_RED) { rbe_set_blackred(tmp, parent); rbe_rotate_left(t, rbt, parent); tmp = RBE_RIGHT(parent); } if ((RBE_LEFT(tmp) == NULL || RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK) && (RBE_RIGHT(tmp) == NULL || RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK)) { RBE_COLOR(tmp) = RB_RED; rbe = parent; parent = RBE_PARENT(rbe); } else { if (RBE_RIGHT(tmp) == NULL || RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK) { struct rb_entry *oleft; oleft = RBE_LEFT(tmp); if (oleft != NULL) RBE_COLOR(oleft) = RB_BLACK; RBE_COLOR(tmp) = RB_RED; rbe_rotate_right(t, rbt, tmp); tmp = RBE_RIGHT(parent); } RBE_COLOR(tmp) = RBE_COLOR(parent); RBE_COLOR(parent) = RB_BLACK; if (RBE_RIGHT(tmp)) RBE_COLOR(RBE_RIGHT(tmp)) = RB_BLACK; rbe_rotate_left(t, rbt, parent); rbe = RBH_ROOT(rbt); break; } } else { tmp = RBE_LEFT(parent); if (RBE_COLOR(tmp) == RB_RED) { rbe_set_blackred(tmp, parent); rbe_rotate_right(t, rbt, parent); tmp = RBE_LEFT(parent); } if ((RBE_LEFT(tmp) == NULL || RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK) && (RBE_RIGHT(tmp) == NULL || RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK)) { RBE_COLOR(tmp) = RB_RED; rbe = parent; parent = RBE_PARENT(rbe); } else { if (RBE_LEFT(tmp) == NULL || RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK) { struct rb_entry *oright; oright = RBE_RIGHT(tmp); if (oright != NULL) RBE_COLOR(oright) = RB_BLACK; RBE_COLOR(tmp) = RB_RED; rbe_rotate_left(t, rbt, tmp); tmp = RBE_LEFT(parent); } RBE_COLOR(tmp) = RBE_COLOR(parent); RBE_COLOR(parent) = RB_BLACK; if (RBE_LEFT(tmp) != NULL) RBE_COLOR(RBE_LEFT(tmp)) = RB_BLACK; rbe_rotate_right(t, rbt, parent); rbe = RBH_ROOT(rbt); break; } } } if (rbe != NULL) RBE_COLOR(rbe) = RB_BLACK; } static inline struct rb_entry * rbe_remove(const struct rb_type *t, struct rb_tree *rbt, struct rb_entry *rbe) { struct rb_entry *child, *parent, *old = rbe; unsigned int color; if (RBE_LEFT(rbe) == NULL) child = RBE_RIGHT(rbe); else if (RBE_RIGHT(rbe) == NULL) child = RBE_LEFT(rbe); else { struct rb_entry *tmp; rbe = RBE_RIGHT(rbe); while ((tmp = RBE_LEFT(rbe)) != NULL) rbe = tmp; child = RBE_RIGHT(rbe); parent = RBE_PARENT(rbe); color = RBE_COLOR(rbe); if (child != NULL) RBE_PARENT(child) = parent; if (parent != NULL) { if (RBE_LEFT(parent) == rbe) RBE_LEFT(parent) = child; else RBE_RIGHT(parent) = child; rbe_if_augment(t, parent); } else RBH_ROOT(rbt) = child; if (RBE_PARENT(rbe) == old) parent = rbe; *rbe = *old; tmp = RBE_PARENT(old); if (tmp != NULL) { if (RBE_LEFT(tmp) == old) RBE_LEFT(tmp) = rbe; else RBE_RIGHT(tmp) = rbe; rbe_if_augment(t, tmp); } else RBH_ROOT(rbt) = rbe; RBE_PARENT(RBE_LEFT(old)) = rbe; if (RBE_RIGHT(old)) RBE_PARENT(RBE_RIGHT(old)) = rbe; if (t->t_augment != NULL && parent != NULL) { tmp = parent; do { rbe_augment(t, tmp); tmp = RBE_PARENT(tmp); } while (tmp != NULL); } goto color; } parent = RBE_PARENT(rbe); color = RBE_COLOR(rbe); if (child != NULL) RBE_PARENT(child) = parent; if (parent != NULL) { if (RBE_LEFT(parent) == rbe) RBE_LEFT(parent) = child; else RBE_RIGHT(parent) = child; rbe_if_augment(t, parent); } else RBH_ROOT(rbt) = child; color: if (color == RB_BLACK) rbe_remove_color(t, rbt, parent, child); return (old); } void * _rb_remove(const struct rb_type *t, struct rb_tree *rbt, void *elm) { struct rb_entry *rbe = rb_n2e(t, elm); struct rb_entry *old; old = rbe_remove(t, rbt, rbe); return (old == NULL ? NULL : rb_e2n(t, old)); } void * _rb_insert(const struct rb_type *t, struct rb_tree *rbt, void *elm) { struct rb_entry *rbe = rb_n2e(t, elm); struct rb_entry *tmp; struct rb_entry *parent = NULL; void *node; int comp = 0; tmp = RBH_ROOT(rbt); while (tmp != NULL) { parent = tmp; node = rb_e2n(t, tmp); comp = (*t->t_compare)(elm, node); if (comp < 0) tmp = RBE_LEFT(tmp); else if (comp > 0) tmp = RBE_RIGHT(tmp); else return (node); } rbe_set(rbe, parent); if (parent != NULL) { if (comp < 0) RBE_LEFT(parent) = rbe; else RBE_RIGHT(parent) = rbe; rbe_if_augment(t, parent); } else RBH_ROOT(rbt) = rbe; rbe_insert_color(t, rbt, rbe); return (NULL); } /* Finds the node with the same key as elm */ void * _rb_find(const struct rb_type *t, struct rb_tree *rbt, const void *key) { struct rb_entry *tmp = RBH_ROOT(rbt); void *node; int comp; while (tmp != NULL) { node = rb_e2n(t, tmp); comp = (*t->t_compare)(key, node); if (comp < 0) tmp = RBE_LEFT(tmp); else if (comp > 0) tmp = RBE_RIGHT(tmp); else return (node); } return (NULL); } /* Finds the first node greater than or equal to the search key */ void * _rb_nfind(const struct rb_type *t, struct rb_tree *rbt, const void *key) { struct rb_entry *tmp = RBH_ROOT(rbt); void *node; void *res = NULL; int comp; while (tmp != NULL) { node = rb_e2n(t, tmp); comp = (*t->t_compare)(key, node); if (comp < 0) { res = node; tmp = RBE_LEFT(tmp); } else if (comp > 0) tmp = RBE_RIGHT(tmp); else return (node); } return (res); } void * _rb_next(const struct rb_type *t, void *elm) { struct rb_entry *rbe = rb_n2e(t, elm); if (RBE_RIGHT(rbe) != NULL) { rbe = RBE_RIGHT(rbe); while (RBE_LEFT(rbe) != NULL) rbe = RBE_LEFT(rbe); } else { if (RBE_PARENT(rbe) && (rbe == RBE_LEFT(RBE_PARENT(rbe)))) rbe = RBE_PARENT(rbe); else { while (RBE_PARENT(rbe) && (rbe == RBE_RIGHT(RBE_PARENT(rbe)))) rbe = RBE_PARENT(rbe); rbe = RBE_PARENT(rbe); } } return (rbe == NULL ? NULL : rb_e2n(t, rbe)); } void * _rb_prev(const struct rb_type *t, void *elm) { struct rb_entry *rbe = rb_n2e(t, elm); if (RBE_LEFT(rbe)) { rbe = RBE_LEFT(rbe); while (RBE_RIGHT(rbe)) rbe = RBE_RIGHT(rbe); } else { if (RBE_PARENT(rbe) && (rbe == RBE_RIGHT(RBE_PARENT(rbe)))) rbe = RBE_PARENT(rbe); else { while (RBE_PARENT(rbe) && (rbe == RBE_LEFT(RBE_PARENT(rbe)))) rbe = RBE_PARENT(rbe); rbe = RBE_PARENT(rbe); } } return (rbe == NULL ? NULL : rb_e2n(t, rbe)); } void * _rb_root(const struct rb_type *t, struct rb_tree *rbt) { struct rb_entry *rbe = RBH_ROOT(rbt); return (rbe == NULL ? rbe : rb_e2n(t, rbe)); } void * _rb_min(const struct rb_type *t, struct rb_tree *rbt) { struct rb_entry *rbe = RBH_ROOT(rbt); struct rb_entry *parent = NULL; while (rbe != NULL) { parent = rbe; rbe = RBE_LEFT(rbe); } return (parent == NULL ? NULL : rb_e2n(t, parent)); } void * _rb_max(const struct rb_type *t, struct rb_tree *rbt) { struct rb_entry *rbe = RBH_ROOT(rbt); struct rb_entry *parent = NULL; while (rbe != NULL) { parent = rbe; rbe = RBE_RIGHT(rbe); } return (parent == NULL ? NULL : rb_e2n(t, parent)); } void * _rb_left(const struct rb_type *t, void *node) { struct rb_entry *rbe = rb_n2e(t, node); rbe = RBE_LEFT(rbe); return (rbe == NULL ? NULL : rb_e2n(t, rbe)); } void * _rb_right(const struct rb_type *t, void *node) { struct rb_entry *rbe = rb_n2e(t, node); rbe = RBE_RIGHT(rbe); return (rbe == NULL ? NULL : rb_e2n(t, rbe)); } void * _rb_parent(const struct rb_type *t, void *node) { struct rb_entry *rbe = rb_n2e(t, node); rbe = RBE_PARENT(rbe); return (rbe == NULL ? NULL : rb_e2n(t, rbe)); } void _rb_set_left(const struct rb_type *t, void *node, void *left) { struct rb_entry *rbe = rb_n2e(t, node); struct rb_entry *rbl = (left == NULL) ? NULL : rb_n2e(t, left); RBE_LEFT(rbe) = rbl; } void _rb_set_right(const struct rb_type *t, void *node, void *right) { struct rb_entry *rbe = rb_n2e(t, node); struct rb_entry *rbr = (right == NULL) ? NULL : rb_n2e(t, right); RBE_RIGHT(rbe) = rbr; } void _rb_set_parent(const struct rb_type *t, void *node, void *parent) { struct rb_entry *rbe = rb_n2e(t, node); struct rb_entry *rbp = (parent == NULL) ? NULL : rb_n2e(t, parent); RBE_PARENT(rbe) = rbp; } void _rb_poison(const struct rb_type *t, void *node, unsigned long poison) { struct rb_entry *rbe = rb_n2e(t, node); RBE_PARENT(rbe) = RBE_LEFT(rbe) = RBE_RIGHT(rbe) = (struct rb_entry *)poison; } int _rb_check(const struct rb_type *t, void *node, unsigned long poison) { struct rb_entry *rbe = rb_n2e(t, node); return ((unsigned long)RBE_PARENT(rbe) == poison && (unsigned long)RBE_LEFT(rbe) == poison && (unsigned long)RBE_RIGHT(rbe) == poison); }
209 210 210 210 199 199 209 210 210 210 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 /* $OpenBSD: kern_bufq.c,v 1.35 2022/12/05 23:18:37 deraadt Exp $ */ /* * Copyright (c) 2010 Thordur I. Bjornsson <thib@openbsd.org> * Copyright (c) 2010 David Gwynne <dlg@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/mount.h> #include <sys/mutex.h> #include <sys/buf.h> #include <sys/errno.h> #include <sys/queue.h> SLIST_HEAD(, bufq) bufqs = SLIST_HEAD_INITIALIZER(bufqs); struct mutex bufqs_mtx = MUTEX_INITIALIZER(IPL_NONE); int bufqs_stop; struct bufq_impl { void *(*impl_create)(void); void (*impl_destroy)(void *); void (*impl_queue)(void *, struct buf *); struct buf *(*impl_dequeue)(void *); void (*impl_requeue)(void *, struct buf *); int (*impl_peek)(void *); }; void *bufq_fifo_create(void); void bufq_fifo_destroy(void *); void bufq_fifo_queue(void *, struct buf *); struct buf *bufq_fifo_dequeue(void *); void bufq_fifo_requeue(void *, struct buf *); int bufq_fifo_peek(void *); void *bufq_nscan_create(void); void bufq_nscan_destroy(void *); void bufq_nscan_queue(void *, struct buf *); struct buf *bufq_nscan_dequeue(void *); void bufq_nscan_requeue(void *, struct buf *); int bufq_nscan_peek(void *); const struct bufq_impl bufq_impls[BUFQ_HOWMANY] = { { bufq_fifo_create, bufq_fifo_destroy, bufq_fifo_queue, bufq_fifo_dequeue, bufq_fifo_requeue, bufq_fifo_peek }, { bufq_nscan_create, bufq_nscan_destroy, bufq_nscan_queue, bufq_nscan_dequeue, bufq_nscan_requeue, bufq_nscan_peek } }; int bufq_init(struct bufq *bq, int type) { u_int hi = BUFQ_HI, low = BUFQ_LOW; if (type >= BUFQ_HOWMANY) panic("bufq_init: type %i unknown", type); /* * Ensure that writes can't consume the entire amount of kva * available the buffer cache if we only have a limited amount * of kva available to us. */ if (hi >= (bcstats.kvaslots / 16)) { hi = bcstats.kvaslots / 16; if (hi < 2) hi = 2; low = hi / 2; } mtx_init(&bq->bufq_mtx, IPL_BIO); bq->bufq_hi = hi; bq->bufq_low = low; bq->bufq_type = type; bq->bufq_impl = &bufq_impls[type]; bq->bufq_data = bq->bufq_impl->impl_create(); if (bq->bufq_data == NULL) { /* * we should actually return failure so disks attaching after * boot in low memory situations dont panic the system. */ panic("bufq init fail"); } mtx_enter(&bufqs_mtx); while (bufqs_stop) { msleep_nsec(&bufqs_stop, &bufqs_mtx, PRIBIO, "bqinit", INFSLP); } SLIST_INSERT_HEAD(&bufqs, bq, bufq_entries); mtx_leave(&bufqs_mtx); return (0); } int bufq_switch(struct bufq *bq, int type) { void *data; void *odata; int otype; struct buf *bp; int ret; mtx_enter(&bq->bufq_mtx); ret = (bq->bufq_type == type); mtx_leave(&bq->bufq_mtx); if (ret) return (0); data = bufq_impls[type].impl_create(); if (data == NULL) return (ENOMEM); mtx_enter(&bq->bufq_mtx); if (bq->bufq_type != type) { /* might have changed during create */ odata = bq->bufq_data; otype = bq->bufq_type; while ((bp = bufq_impls[otype].impl_dequeue(odata)) != NULL) bufq_impls[type].impl_queue(data, bp); bq->bufq_data = data; bq->bufq_type = type; bq->bufq_impl = &bufq_impls[type]; } else { otype = type; odata = data; } mtx_leave(&bq->bufq_mtx); bufq_impls[otype].impl_destroy(odata); return (0); } void bufq_destroy(struct bufq *bq) { bufq_drain(bq); bq->bufq_impl->impl_destroy(bq->bufq_data); bq->bufq_data = NULL; mtx_enter(&bufqs_mtx); while (bufqs_stop) { msleep_nsec(&bufqs_stop, &bufqs_mtx, PRIBIO, "bqdest", INFSLP); } SLIST_REMOVE(&bufqs, bq, bufq, bufq_entries); mtx_leave(&bufqs_mtx); } void bufq_queue(struct bufq *bq, struct buf *bp) { mtx_enter(&bq->bufq_mtx); while (bq->bufq_stop) { msleep_nsec(&bq->bufq_stop, &bq->bufq_mtx, PRIBIO, "bqqueue", INFSLP); } bp->b_bq = bq; bq->bufq_outstanding++; bq->bufq_impl->impl_queue(bq->bufq_data, bp); mtx_leave(&bq->bufq_mtx); } struct buf * bufq_dequeue(struct bufq *bq) { struct buf *bp; mtx_enter(&bq->bufq_mtx); bp = bq->bufq_impl->impl_dequeue(bq->bufq_data); mtx_leave(&bq->bufq_mtx); return (bp); } void bufq_requeue(struct bufq *bq, struct buf *bp) { mtx_enter(&bq->bufq_mtx); bq->bufq_impl->impl_requeue(bq->bufq_data, bp); mtx_leave(&bq->bufq_mtx); } int bufq_peek(struct bufq *bq) { int rv; mtx_enter(&bq->bufq_mtx); rv = bq->bufq_impl->impl_peek(bq->bufq_data); mtx_leave(&bq->bufq_mtx); return (rv); } void bufq_drain(struct bufq *bq) { struct buf *bp; int s; while ((bp = bufq_dequeue(bq)) != NULL) { bp->b_error = ENXIO; bp->b_flags |= B_ERROR; s = splbio(); biodone(bp); splx(s); } } void bufq_wait(struct bufq *bq) { if (bq->bufq_hi) { assertwaitok(); mtx_enter(&bq->bufq_mtx); while (bq->bufq_outstanding >= bq->bufq_hi) { bq->bufq_waiting++; msleep_nsec(&bq->bufq_waiting, &bq->bufq_mtx, PRIBIO, "bqwait", INFSLP); bq->bufq_waiting--; } mtx_leave(&bq->bufq_mtx); } } void bufq_done(struct bufq *bq, struct buf *bp) { mtx_enter(&bq->bufq_mtx); KASSERT(bq->bufq_outstanding > 0); bq->bufq_outstanding--; if (bq->bufq_stop && bq->bufq_outstanding == 0) wakeup(&bq->bufq_outstanding); if (bq->bufq_waiting && bq->bufq_outstanding < bq->bufq_low) wakeup(&bq->bufq_waiting); mtx_leave(&bq->bufq_mtx); bp->b_bq = NULL; } void bufq_quiesce(void) { struct bufq *bq; mtx_enter(&bufqs_mtx); bufqs_stop = 1; mtx_leave(&bufqs_mtx); /* * We can safely walk the list since it can't be modified as * long as bufqs_stop is non-zero. */ SLIST_FOREACH(bq, &bufqs, bufq_entries) { mtx_enter(&bq->bufq_mtx); bq->bufq_stop = 1; while (bq->bufq_outstanding) { msleep_nsec(&bq->bufq_outstanding, &bq->bufq_mtx, PRIBIO, "bqquies", INFSLP); } mtx_leave(&bq->bufq_mtx); } } void bufq_restart(void) { struct bufq *bq; mtx_enter(&bufqs_mtx); SLIST_FOREACH(bq, &bufqs, bufq_entries) { mtx_enter(&bq->bufq_mtx); bq->bufq_stop = 0; wakeup(&bq->bufq_stop); mtx_leave(&bq->bufq_mtx); } bufqs_stop = 0; wakeup(&bufqs_stop); mtx_leave(&bufqs_mtx); } /* * fifo implementation */ void * bufq_fifo_create(void) { struct bufq_fifo_head *head; head = malloc(sizeof(*head), M_DEVBUF, M_NOWAIT | M_ZERO); if (head == NULL) return (NULL); SIMPLEQ_INIT(head); return (head); } void bufq_fifo_destroy(void *data) { struct bufq_fifo_head *head = data; free(head, M_DEVBUF, sizeof(*head)); } void bufq_fifo_queue(void *data, struct buf *bp) { struct bufq_fifo_head *head = data; SIMPLEQ_INSERT_TAIL(head, bp, b_bufq.bufq_data_fifo.bqf_entries); } struct buf * bufq_fifo_dequeue(void *data) { struct bufq_fifo_head *head = data; struct buf *bp; bp = SIMPLEQ_FIRST(head); if (bp != NULL) SIMPLEQ_REMOVE_HEAD(head, b_bufq.bufq_data_fifo.bqf_entries); return (bp); } void bufq_fifo_requeue(void *data, struct buf *bp) { struct bufq_fifo_head *head = data; SIMPLEQ_INSERT_HEAD(head, bp, b_bufq.bufq_data_fifo.bqf_entries); } int bufq_fifo_peek(void *data) { struct bufq_fifo_head *head = data; return (SIMPLEQ_FIRST(head) != NULL); } /* * nscan implementation */ #define BUF_INORDER(ba, bb) ((ba)->b_blkno < (bb)->b_blkno) #define dsentries b_bufq.bufq_data_nscan.bqf_entries struct bufq_nscan_data { struct bufq_nscan_head sorted; struct bufq_nscan_head fifo; int leftoverroom; /* Remaining number of buffer inserts allowed */ }; void bufq_nscan_resort(struct bufq_nscan_data *data); void bufq_simple_nscan(struct bufq_nscan_head *, struct buf *); void bufq_simple_nscan(struct bufq_nscan_head *head, struct buf *bp) { struct buf *cur, *prev; prev = NULL; /* * We look for the first slot where we would fit, then insert * after the element we just passed. */ SIMPLEQ_FOREACH(cur, head, dsentries) { if (BUF_INORDER(bp, cur)) break; prev = cur; } if (prev) SIMPLEQ_INSERT_AFTER(head, prev, bp, dsentries); else SIMPLEQ_INSERT_HEAD(head, bp, dsentries); } /* * Take N elements from the fifo queue and sort them */ void bufq_nscan_resort(struct bufq_nscan_data *data) { struct bufq_nscan_head *fifo = &data->fifo; struct bufq_nscan_head *sorted = &data->sorted; int count, segmentsize = BUFQ_NSCAN_N; struct buf *bp; for (count = 0; count < segmentsize; count++) { bp = SIMPLEQ_FIRST(fifo); if (!bp) break; SIMPLEQ_REMOVE_HEAD(fifo, dsentries); bufq_simple_nscan(sorted, bp); } data->leftoverroom = segmentsize - count; } void * bufq_nscan_create(void) { struct bufq_nscan_data *data; data = malloc(sizeof(*data), M_DEVBUF, M_NOWAIT | M_ZERO); if (!data) return NULL; SIMPLEQ_INIT(&data->sorted); SIMPLEQ_INIT(&data->fifo); return data; } void bufq_nscan_destroy(void *vdata) { struct bufq_nscan_data *data = vdata; free(data, M_DEVBUF, sizeof(*data)); } void bufq_nscan_queue(void *vdata, struct buf *bp) { struct bufq_nscan_data *data = vdata; /* * If the previous sorted segment was small, we will continue * packing in bufs as long as they're in order. */ if (data->leftoverroom) { struct buf *next = SIMPLEQ_FIRST(&data->sorted); if (next && BUF_INORDER(next, bp)) { bufq_simple_nscan(&data->sorted, bp); data->leftoverroom--; return; } } SIMPLEQ_INSERT_TAIL(&data->fifo, bp, dsentries); } struct buf * bufq_nscan_dequeue(void *vdata) { struct bufq_nscan_data *data = vdata; struct bufq_nscan_head *sorted = &data->sorted; struct buf *bp; if (SIMPLEQ_FIRST(sorted) == NULL) bufq_nscan_resort(data); bp = SIMPLEQ_FIRST(sorted); if (bp != NULL) SIMPLEQ_REMOVE_HEAD(sorted, dsentries); return (bp); } void bufq_nscan_requeue(void *vdata, struct buf *bp) { struct bufq_nscan_data *data = vdata; SIMPLEQ_INSERT_HEAD(&data->fifo, bp, dsentries); } int bufq_nscan_peek(void *vdata) { struct bufq_nscan_data *data = vdata; return (SIMPLEQ_FIRST(&data->sorted) != NULL) || (SIMPLEQ_FIRST(&data->fifo) != NULL); }
33 34 24 2 15 4 16 4 17 6 17 15 2 25 23 2 2 61 16 19 25 1 25 5 20 2 2 1 3 2 2 3 14 14 4 1 1 6 5 4 1 9 5 4 4 3 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 /* $OpenBSD: if_ether.c,v 1.267 2023/12/18 13:30:44 bluhm Exp $ */ /* $NetBSD: if_ether.c,v 1.31 1996/05/11 12:59:58 mycroft Exp $ */ /* * Copyright (c) 1982, 1986, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)if_ether.c 8.1 (Berkeley) 6/10/93 */ /* * Ethernet address resolution protocol. * TODO: * add "inuse/lock" bit (or ref. count) along with valid bit */ #include "carp.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/timeout.h> #include <sys/kernel.h> #include <sys/syslog.h> #include <sys/queue.h> #include <sys/pool.h> #include <net/if.h> #include <net/if_var.h> #include <net/if_dl.h> #include <net/route.h> #include <net/if_types.h> #include <net/netisr.h> #include <netinet/in.h> #include <netinet/in_var.h> #include <netinet/if_ether.h> #include <netinet/ip_var.h> #if NCARP > 0 #include <netinet/ip_carp.h> #endif /* * Locks used to protect struct members in this file: * a atomic operations * I immutable after creation * K kernel lock * m arp mutex, needed when net lock is shared * N net lock */ struct llinfo_arp { LIST_ENTRY(llinfo_arp) la_list; /* [mN] global arp_list */ struct rtentry *la_rt; /* [I] backpointer to rtentry */ struct mbuf_queue la_mq; /* packet hold queue */ time_t la_refreshed; /* when was refresh sent */ int la_asked; /* number of queries sent */ }; #define LA_HOLD_QUEUE 10 #define LA_HOLD_TOTAL 100 /* timer values */ int arpt_prune = (5 * 60); /* [I] walk list every 5 minutes */ int arpt_keep = (20 * 60); /* [a] once resolved, cache for 20 minutes */ int arpt_down = 20; /* [a] once declared down, don't send for 20 secs */ struct mbuf *arppullup(struct mbuf *m); void arpinvalidate(struct rtentry *); void arptfree(struct rtentry *); void arptimer(void *); struct rtentry *arplookup(struct in_addr *, int, int, unsigned int); void in_arpinput(struct ifnet *, struct mbuf *); void in_revarpinput(struct ifnet *, struct mbuf *); int arpcache(struct ifnet *, struct ether_arp *, struct rtentry *); void arpreply(struct ifnet *, struct mbuf *, struct in_addr *, uint8_t *, unsigned int); struct niqueue arpinq = NIQUEUE_INITIALIZER(50, NETISR_ARP); /* llinfo_arp live time, rt_llinfo and RTF_LLINFO are protected by arp_mtx */ struct mutex arp_mtx = MUTEX_INITIALIZER(IPL_SOFTNET); LIST_HEAD(, llinfo_arp) arp_list = LIST_HEAD_INITIALIZER(arp_list); /* [mN] list of llinfo_arp structures */ struct pool arp_pool; /* [I] pool for llinfo_arp structures */ int arp_maxtries = 5; /* [I] arp requests before set to rejected */ unsigned int la_hold_total; /* [a] packets currently in the arp queue */ #ifdef NFSCLIENT /* revarp state */ struct in_addr revarp_myip, revarp_srvip; int revarp_finished; unsigned int revarp_ifidx; #endif /* NFSCLIENT */ /* * Timeout routine. Age arp_tab entries periodically. */ void arptimer(void *arg) { struct timeout *to = arg; struct llinfo_arp *la, *nla; time_t uptime; NET_LOCK(); uptime = getuptime(); timeout_add_sec(to, arpt_prune); /* Net lock is exclusive, no arp mutex needed for arp_list here. */ LIST_FOREACH_SAFE(la, &arp_list, la_list, nla) { struct rtentry *rt = la->la_rt; if (rt->rt_expire && rt->rt_expire < uptime) arptfree(rt); /* timer has expired; clear */ } NET_UNLOCK(); } void arpinit(void) { static struct timeout arptimer_to; pool_init(&arp_pool, sizeof(struct llinfo_arp), 0, IPL_SOFTNET, 0, "arp", NULL); timeout_set_flags(&arptimer_to, arptimer, &arptimer_to, KCLOCK_NONE, TIMEOUT_PROC | TIMEOUT_MPSAFE); timeout_add_sec(&arptimer_to, arpt_prune); } void arp_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt) { struct sockaddr *gate = rt->rt_gateway; struct llinfo_arp *la; time_t uptime; NET_ASSERT_LOCKED(); if (ISSET(rt->rt_flags, RTF_GATEWAY|RTF_BROADCAST|RTF_MULTICAST|RTF_MPLS)) return; uptime = getuptime(); switch (req) { case RTM_ADD: if (rt->rt_flags & RTF_CLONING) { rt->rt_expire = 0; break; } if ((rt->rt_flags & RTF_LOCAL) && rt->rt_llinfo == NULL) rt->rt_expire = 0; /* * Announce a new entry if requested or warn the user * if another station has this IP address. */ if (rt->rt_flags & (RTF_ANNOUNCE|RTF_LOCAL)) arprequest(ifp, &satosin(rt_key(rt))->sin_addr.s_addr, &satosin(rt_key(rt))->sin_addr.s_addr, (u_char *)LLADDR(satosdl(gate))); /*FALLTHROUGH*/ case RTM_RESOLVE: if (gate->sa_family != AF_LINK || gate->sa_len < sizeof(struct sockaddr_dl)) { log(LOG_DEBUG, "%s: bad gateway value: %s\n", __func__, ifp->if_xname); break; } satosdl(gate)->sdl_type = ifp->if_type; satosdl(gate)->sdl_index = ifp->if_index; /* * Case 2: This route may come from cloning, or a manual route * add with a LL address. */ la = pool_get(&arp_pool, PR_NOWAIT | PR_ZERO); if (la == NULL) { log(LOG_DEBUG, "%s: pool get failed\n", __func__); break; } mtx_enter(&arp_mtx); if (rt->rt_llinfo != NULL) { /* we lost the race, another thread has entered it */ mtx_leave(&arp_mtx); pool_put(&arp_pool, la); break; } mq_init(&la->la_mq, LA_HOLD_QUEUE, IPL_SOFTNET); rt->rt_llinfo = (caddr_t)la; la->la_rt = rt; rt->rt_flags |= RTF_LLINFO; LIST_INSERT_HEAD(&arp_list, la, la_list); if ((rt->rt_flags & RTF_LOCAL) == 0) rt->rt_expire = uptime; mtx_leave(&arp_mtx); break; case RTM_DELETE: mtx_enter(&arp_mtx); la = (struct llinfo_arp *)rt->rt_llinfo; if (la == NULL) { /* we lost the race, another thread has removed it */ mtx_leave(&arp_mtx); break; } LIST_REMOVE(la, la_list); rt->rt_llinfo = NULL; rt->rt_flags &= ~RTF_LLINFO; atomic_sub_int(&la_hold_total, mq_purge(&la->la_mq)); mtx_leave(&arp_mtx); pool_put(&arp_pool, la); break; case RTM_INVALIDATE: if (!ISSET(rt->rt_flags, RTF_LOCAL)) arpinvalidate(rt); break; } } /* * Broadcast an ARP request. Caller specifies: * - arp header source ip address * - arp header target ip address * - arp header source ethernet address */ void arprequest(struct ifnet *ifp, u_int32_t *sip, u_int32_t *tip, u_int8_t *enaddr) { struct mbuf *m; struct ether_header *eh; struct ether_arp *ea; struct sockaddr sa; if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) return; m->m_len = sizeof(*ea); m->m_pkthdr.len = sizeof(*ea); m->m_pkthdr.ph_rtableid = ifp->if_rdomain; m->m_pkthdr.pf.prio = ifp->if_llprio; m_align(m, sizeof(*ea)); ea = mtod(m, struct ether_arp *); eh = (struct ether_header *)sa.sa_data; memset(ea, 0, sizeof(*ea)); memcpy(eh->ether_dhost, etherbroadcastaddr, sizeof(eh->ether_dhost)); eh->ether_type = htons(ETHERTYPE_ARP); /* if_output will not swap */ ea->arp_hrd = htons(ARPHRD_ETHER); ea->arp_pro = htons(ETHERTYPE_IP); ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */ ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */ ea->arp_op = htons(ARPOP_REQUEST); memcpy(eh->ether_shost, enaddr, sizeof(eh->ether_shost)); memcpy(ea->arp_sha, enaddr, sizeof(ea->arp_sha)); memcpy(ea->arp_spa, sip, sizeof(ea->arp_spa)); memcpy(ea->arp_tpa, tip, sizeof(ea->arp_tpa)); sa.sa_family = pseudo_AF_HDRCMPLT; sa.sa_len = sizeof(sa); m->m_flags |= M_BCAST; ifp->if_output(ifp, m, &sa, NULL); } void arpreply(struct ifnet *ifp, struct mbuf *m, struct in_addr *sip, uint8_t *eaddr, unsigned int rdomain) { struct ether_header *eh; struct ether_arp *ea; struct sockaddr sa; m_resethdr(m); m->m_pkthdr.ph_rtableid = rdomain; ea = mtod(m, struct ether_arp *); ea->arp_op = htons(ARPOP_REPLY); ea->arp_pro = htons(ETHERTYPE_IP); /* let's be sure! */ /* We're replying to a request. */ memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha)); memcpy(ea->arp_tpa, ea->arp_spa, sizeof(ea->arp_spa)); memcpy(ea->arp_sha, eaddr, sizeof(ea->arp_sha)); memcpy(ea->arp_spa, sip, sizeof(ea->arp_spa)); eh = (struct ether_header *)sa.sa_data; memcpy(eh->ether_dhost, ea->arp_tha, sizeof(eh->ether_dhost)); memcpy(eh->ether_shost, eaddr, sizeof(eh->ether_shost)); eh->ether_type = htons(ETHERTYPE_ARP); sa.sa_family = pseudo_AF_HDRCMPLT; sa.sa_len = sizeof(sa); ifp->if_output(ifp, m, &sa, NULL); } /* * Resolve an IP address into an ethernet address. If success, * desten is filled in. If there is no entry in arptab, * set one up and broadcast a request for the IP address. * Hold onto this mbuf and resend it once the address * is finally resolved. A return value of 0 indicates * that desten has been filled in and the packet should be sent * normally; A return value of EAGAIN indicates that the packet * has been taken over here, either now or for later transmission. * Any other return value indicates an error. */ int arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, struct sockaddr *dst, u_char *desten) { struct arpcom *ac = (struct arpcom *)ifp; struct llinfo_arp *la; struct sockaddr_dl *sdl; struct rtentry *rt = NULL; char addr[INET_ADDRSTRLEN]; time_t uptime; int refresh = 0, reject = 0; if (m->m_flags & M_BCAST) { /* broadcast */ memcpy(desten, etherbroadcastaddr, sizeof(etherbroadcastaddr)); return (0); } if (m->m_flags & M_MCAST) { /* multicast */ ETHER_MAP_IP_MULTICAST(&satosin(dst)->sin_addr, desten); return (0); } uptime = getuptime(); rt = rt_getll(rt0); if (ISSET(rt->rt_flags, RTF_REJECT) && (rt->rt_expire == 0 || rt->rt_expire > uptime)) { m_freem(m); return (rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); } if (!ISSET(rt->rt_flags, RTF_LLINFO)) { log(LOG_DEBUG, "%s: %s: route contains no arp information\n", __func__, inet_ntop(AF_INET, &satosin(rt_key(rt))->sin_addr, addr, sizeof(addr))); goto bad; } sdl = satosdl(rt->rt_gateway); if (sdl->sdl_alen > 0 && sdl->sdl_alen != ETHER_ADDR_LEN) { log(LOG_DEBUG, "%s: %s: incorrect arp information\n", __func__, inet_ntop(AF_INET, &satosin(dst)->sin_addr, addr, sizeof(addr))); goto bad; } /* * Check the address family and length is valid, the address * is resolved; otherwise, try to resolve. */ if ((rt->rt_expire == 0 || rt->rt_expire > uptime) && sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) { memcpy(desten, LLADDR(sdl), sdl->sdl_alen); /* refresh ARP entry when timeout gets close */ if (rt->rt_expire != 0 && rt->rt_expire - arpt_keep / 8 < uptime) { mtx_enter(&arp_mtx); la = (struct llinfo_arp *)rt->rt_llinfo; if (la != NULL) { if (la->la_refreshed + 30 < uptime) { la->la_refreshed = uptime; refresh = 1; } } mtx_leave(&arp_mtx); } if (refresh) { arprequest(ifp, &satosin(rt->rt_ifa->ifa_addr)->sin_addr.s_addr, &satosin(dst)->sin_addr.s_addr, ac->ac_enaddr); } return (0); } if (ifp->if_flags & (IFF_NOARP|IFF_STATICARP)) goto bad; mtx_enter(&arp_mtx); la = (struct llinfo_arp *)rt->rt_llinfo; if (la == NULL) { mtx_leave(&arp_mtx); goto bad; } /* * There is an arptab entry, but no ethernet address * response yet. Insert mbuf in hold queue if below limit. * If above the limit free the queue without queuing the new packet. */ if (atomic_inc_int_nv(&la_hold_total) <= LA_HOLD_TOTAL) { if (mq_push(&la->la_mq, m) != 0) atomic_dec_int(&la_hold_total); } else { atomic_sub_int(&la_hold_total, mq_purge(&la->la_mq) + 1); m_freem(m); } /* * Re-send the ARP request when appropriate. */ #ifdef DIAGNOSTIC if (rt->rt_expire == 0) { /* This should never happen. (Should it? -gwr) */ printf("%s: unresolved and rt_expire == 0\n", __func__); /* Set expiration time to now (expired). */ rt->rt_expire = uptime; } #endif if (rt->rt_expire) { reject = ~RTF_REJECT; if (la->la_asked == 0 || rt->rt_expire != uptime) { rt->rt_expire = uptime; if (la->la_asked++ < arp_maxtries) refresh = 1; else { reject = RTF_REJECT; rt->rt_expire += arpt_down; la->la_asked = 0; la->la_refreshed = 0; atomic_sub_int(&la_hold_total, mq_purge(&la->la_mq)); } } } mtx_leave(&arp_mtx); if (reject == RTF_REJECT && !ISSET(rt->rt_flags, RTF_REJECT)) { KERNEL_LOCK(); SET(rt->rt_flags, RTF_REJECT); KERNEL_UNLOCK(); } if (reject == ~RTF_REJECT && ISSET(rt->rt_flags, RTF_REJECT)) { KERNEL_LOCK(); CLR(rt->rt_flags, RTF_REJECT); KERNEL_UNLOCK(); } if (refresh) arprequest(ifp, &satosin(rt->rt_ifa->ifa_addr)->sin_addr.s_addr, &satosin(dst)->sin_addr.s_addr, ac->ac_enaddr); return (EAGAIN); bad: m_freem(m); return (EINVAL); } struct mbuf * arppullup(struct mbuf *m) { struct arphdr *ar; int len; #ifdef DIAGNOSTIC if ((m->m_flags & M_PKTHDR) == 0) panic("arp without packet header"); #endif len = sizeof(struct arphdr); if (m->m_len < len && (m = m_pullup(m, len)) == NULL) return NULL; ar = mtod(m, struct arphdr *); if (ntohs(ar->ar_hrd) != ARPHRD_ETHER || ntohs(ar->ar_pro) != ETHERTYPE_IP || ar->ar_hln != ETHER_ADDR_LEN || ar->ar_pln != sizeof(struct in_addr)) { m_freem(m); return NULL; } len += 2 * (ar->ar_hln + ar->ar_pln); if (m->m_len < len && (m = m_pullup(m, len)) == NULL) return NULL; return m; } /* * Common length and type checks are done here, * then the protocol-specific routine is called. */ void arpinput(struct ifnet *ifp, struct mbuf *m) { if ((m = arppullup(m)) == NULL) return; niq_enqueue(&arpinq, m); } void arpintr(void) { struct mbuf_list ml; struct mbuf *m; struct ifnet *ifp; niq_delist(&arpinq, &ml); while ((m = ml_dequeue(&ml)) != NULL) { ifp = if_get(m->m_pkthdr.ph_ifidx); if (ifp != NULL) in_arpinput(ifp, m); else m_freem(m); if_put(ifp); } } /* * ARP for Internet protocols on Ethernet, RFC 826. * In addition, a sanity check is performed on the sender * protocol address, to catch impersonators. */ void in_arpinput(struct ifnet *ifp, struct mbuf *m) { struct ether_arp *ea; struct rtentry *rt = NULL; struct sockaddr_in sin; struct in_addr isaddr, itaddr; char addr[INET_ADDRSTRLEN]; int op, target = 0; unsigned int rdomain; rdomain = rtable_l2(m->m_pkthdr.ph_rtableid); ea = mtod(m, struct ether_arp *); op = ntohs(ea->arp_op); if ((op != ARPOP_REQUEST) && (op != ARPOP_REPLY)) goto out; memcpy(&itaddr, ea->arp_tpa, sizeof(itaddr)); memcpy(&isaddr, ea->arp_spa, sizeof(isaddr)); memset(&sin, 0, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; if (ETHER_IS_MULTICAST(ea->arp_sha) && ETHER_IS_BROADCAST(ea->arp_sha)) { inet_ntop(AF_INET, &isaddr, addr, sizeof(addr)); log(LOG_ERR, "arp: ether address is broadcast for IP address " "%s!\n", addr); goto out; } if (!memcmp(ea->arp_sha, LLADDR(ifp->if_sadl), sizeof(ea->arp_sha))) goto out; /* it's from me, ignore it. */ /* Check target against our interface addresses. */ sin.sin_addr = itaddr; rt = rtalloc(sintosa(&sin), 0, rdomain); if (rtisvalid(rt) && ISSET(rt->rt_flags, RTF_LOCAL) && rt->rt_ifidx == ifp->if_index) target = 1; rtfree(rt); rt = NULL; #if NCARP > 0 if (target && op == ARPOP_REQUEST && ifp->if_type == IFT_CARP && !carp_iamatch(ifp)) goto out; #endif /* Do we have an ARP cache for the sender? Create if we are target. */ rt = arplookup(&isaddr, target, 0, rdomain); /* Check sender against our interface addresses. */ if (rtisvalid(rt) && ISSET(rt->rt_flags, RTF_LOCAL) && rt->rt_ifidx == ifp->if_index && isaddr.s_addr != INADDR_ANY) { inet_ntop(AF_INET, &isaddr, addr, sizeof(addr)); log(LOG_ERR, "duplicate IP address %s sent from ethernet " "address %s\n", addr, ether_sprintf(ea->arp_sha)); itaddr = isaddr; } else if (rt != NULL) { if (arpcache(ifp, ea, rt)) goto out; } if (op == ARPOP_REQUEST) { uint8_t *eaddr; if (target) { /* We already have all info for the reply */ eaddr = LLADDR(ifp->if_sadl); } else { rtfree(rt); rt = arplookup(&itaddr, 0, SIN_PROXY, rdomain); /* * Protect from possible duplicates, only owner * should respond */ if ((rt == NULL) || (rt->rt_ifidx != ifp->if_index)) goto out; eaddr = LLADDR(satosdl(rt->rt_gateway)); } arpreply(ifp, m, &itaddr, eaddr, rdomain); rtfree(rt); return; } out: rtfree(rt); m_freem(m); } int arpcache(struct ifnet *ifp, struct ether_arp *ea, struct rtentry *rt) { struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo; struct sockaddr_dl *sdl = satosdl(rt->rt_gateway); struct in_addr *spa = (struct in_addr *)ea->arp_spa; char addr[INET_ADDRSTRLEN]; struct ifnet *rifp; time_t uptime; int changed = 0; NET_ASSERT_LOCKED_EXCLUSIVE(); KASSERT(sdl != NULL); /* * This can happen if the entry has been deleted by another CPU * after we found it. */ if (la == NULL) return (0); uptime = getuptime(); if (sdl->sdl_alen > 0) { if (memcmp(ea->arp_sha, LLADDR(sdl), sdl->sdl_alen)) { if (ISSET(rt->rt_flags, RTF_PERMANENT_ARP|RTF_LOCAL)) { inet_ntop(AF_INET, spa, addr, sizeof(addr)); log(LOG_WARNING, "arp: attempt to overwrite " "permanent entry for %s by %s on %s\n", addr, ether_sprintf(ea->arp_sha), ifp->if_xname); return (-1); } else if (rt->rt_ifidx != ifp->if_index) { #if NCARP > 0 if (ifp->if_type != IFT_CARP) #endif { rifp = if_get(rt->rt_ifidx); if (rifp == NULL) return (-1); inet_ntop(AF_INET, spa, addr, sizeof(addr)); log(LOG_WARNING, "arp: attempt to " "overwrite entry for %s on %s by " "%s on %s\n", addr, rifp->if_xname, ether_sprintf(ea->arp_sha), ifp->if_xname); if_put(rifp); } return (-1); } else { inet_ntop(AF_INET, spa, addr, sizeof(addr)); log(LOG_INFO, "arp info overwritten for %s by " "%s on %s\n", addr, ether_sprintf(ea->arp_sha), ifp->if_xname); rt->rt_expire = 1;/* no longer static */ } changed = 1; } } else if (!if_isconnected(ifp, rt->rt_ifidx)) { rifp = if_get(rt->rt_ifidx); if (rifp == NULL) return (-1); inet_ntop(AF_INET, spa, addr, sizeof(addr)); log(LOG_WARNING, "arp: attempt to add entry for %s on %s by %s" " on %s\n", addr, rifp->if_xname, ether_sprintf(ea->arp_sha), ifp->if_xname); if_put(rifp); return (-1); } sdl->sdl_alen = sizeof(ea->arp_sha); memcpy(LLADDR(sdl), ea->arp_sha, sizeof(ea->arp_sha)); if (rt->rt_expire) rt->rt_expire = uptime + arpt_keep; rt->rt_flags &= ~RTF_REJECT; /* Notify userland that an ARP resolution has been done. */ if (la->la_asked || changed) { rtm_send(rt, RTM_RESOLVE, 0, ifp->if_rdomain); } la->la_asked = 0; la->la_refreshed = 0; if_output_mq(ifp, &la->la_mq, &la_hold_total, rt_key(rt), rt); return (0); } void arpinvalidate(struct rtentry *rt) { struct llinfo_arp *la; struct sockaddr_dl *sdl = satosdl(rt->rt_gateway); mtx_enter(&arp_mtx); la = (struct llinfo_arp *)rt->rt_llinfo; if (la == NULL) { mtx_leave(&arp_mtx); return; } atomic_sub_int(&la_hold_total, mq_purge(&la->la_mq)); sdl->sdl_alen = 0; la->la_asked = 0; mtx_leave(&arp_mtx); } /* * Free an arp entry. */ void arptfree(struct rtentry *rt) { struct ifnet *ifp; KASSERT(!ISSET(rt->rt_flags, RTF_LOCAL)); arpinvalidate(rt); ifp = if_get(rt->rt_ifidx); if (ifp == NULL) return; if (!ISSET(rt->rt_flags, RTF_STATIC|RTF_CACHED)) rtdeletemsg(rt, ifp, ifp->if_rdomain); if_put(ifp); } /* * Lookup or enter a new address in arptab. */ struct rtentry * arplookup(struct in_addr *inp, int create, int proxy, u_int tableid) { struct rtentry *rt; struct sockaddr_inarp sin; int flags; memset(&sin, 0, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_addr.s_addr = inp->s_addr; sin.sin_other = proxy ? SIN_PROXY : 0; flags = (create) ? RT_RESOLVE : 0; rt = rtalloc((struct sockaddr *)&sin, flags, tableid); if (!rtisvalid(rt) || ISSET(rt->rt_flags, RTF_GATEWAY) || !ISSET(rt->rt_flags, RTF_LLINFO) || rt->rt_gateway->sa_family != AF_LINK) { rtfree(rt); return (NULL); } if (proxy && !ISSET(rt->rt_flags, RTF_ANNOUNCE)) { while ((rt = rtable_iterate(rt)) != NULL) { if (ISSET(rt->rt_flags, RTF_ANNOUNCE)) { break; } } } return (rt); } /* * Check whether we do proxy ARP for this address and we point to ourselves. */ int arpproxy(struct in_addr in, unsigned int rtableid) { struct sockaddr_dl *sdl; struct rtentry *rt; struct ifnet *ifp; int found = 0; rt = arplookup(&in, 0, SIN_PROXY, rtableid); if (!rtisvalid(rt)) { rtfree(rt); return (0); } /* Check that arp information are correct. */ sdl = satosdl(rt->rt_gateway); if (sdl->sdl_alen != ETHER_ADDR_LEN) { rtfree(rt); return (0); } ifp = if_get(rt->rt_ifidx); if (ifp == NULL) { rtfree(rt); return (0); } if (!memcmp(LLADDR(sdl), LLADDR(ifp->if_sadl), sdl->sdl_alen)) found = 1; if_put(ifp); rtfree(rt); return (found); } /* * Called from Ethernet interrupt handlers * when ether packet type ETHERTYPE_REVARP * is received. Common length and type checks are done here, * then the protocol-specific routine is called. */ void revarpinput(struct ifnet *ifp, struct mbuf *m) { if ((m = arppullup(m)) == NULL) return; in_revarpinput(ifp, m); } /* * RARP for Internet protocols on Ethernet. * Algorithm is that given in RFC 903. * We are only using for bootstrap purposes to get an ip address for one of * our interfaces. Thus we support no user-interface. * * Since the contents of the RARP reply are specific to the interface that * sent the request, this code must ensure that they are properly associated. * * Note: also supports ARP via RARP packets, per the RFC. */ void in_revarpinput(struct ifnet *ifp, struct mbuf *m) { struct ether_arp *ar; int op; ar = mtod(m, struct ether_arp *); op = ntohs(ar->arp_op); switch (op) { case ARPOP_REQUEST: case ARPOP_REPLY: /* per RFC */ niq_enqueue(&arpinq, m); return; case ARPOP_REVREPLY: break; case ARPOP_REVREQUEST: /* handled by rarpd(8) */ default: goto out; } #ifdef NFSCLIENT if (revarp_ifidx == 0) goto out; if (revarp_ifidx != m->m_pkthdr.ph_ifidx) /* !same interface */ goto out; if (revarp_finished) goto wake; if (memcmp(ar->arp_tha, LLADDR(ifp->if_sadl), sizeof(ar->arp_tha))) goto out; memcpy(&revarp_srvip, ar->arp_spa, sizeof(revarp_srvip)); memcpy(&revarp_myip, ar->arp_tpa, sizeof(revarp_myip)); revarp_finished = 1; wake: /* Do wakeup every time in case it was missed. */ wakeup((caddr_t)&revarp_myip); #endif /* NFSCLIENT */ out: m_freem(m); } /* * Send a RARP request for the ip address of the specified interface. * The request should be RFC 903-compliant. */ void revarprequest(struct ifnet *ifp) { struct sockaddr sa; struct mbuf *m; struct ether_header *eh; struct ether_arp *ea; struct arpcom *ac = (struct arpcom *)ifp; if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) return; m->m_len = sizeof(*ea); m->m_pkthdr.len = sizeof(*ea); m->m_pkthdr.ph_rtableid = ifp->if_rdomain; m->m_pkthdr.pf.prio = ifp->if_llprio; m_align(m, sizeof(*ea)); ea = mtod(m, struct ether_arp *); eh = (struct ether_header *)sa.sa_data; memset(ea, 0, sizeof(*ea)); memcpy(eh->ether_dhost, etherbroadcastaddr, sizeof(eh->ether_dhost)); eh->ether_type = htons(ETHERTYPE_REVARP); ea->arp_hrd = htons(ARPHRD_ETHER); ea->arp_pro = htons(ETHERTYPE_IP); ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */ ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */ ea->arp_op = htons(ARPOP_REVREQUEST); memcpy(eh->ether_shost, ac->ac_enaddr, sizeof(ea->arp_tha)); memcpy(ea->arp_sha, ac->ac_enaddr, sizeof(ea->arp_sha)); memcpy(ea->arp_tha, ac->ac_enaddr, sizeof(ea->arp_tha)); sa.sa_family = pseudo_AF_HDRCMPLT; sa.sa_len = sizeof(sa); m->m_flags |= M_BCAST; ifp->if_output(ifp, m, &sa, NULL); } #ifdef NFSCLIENT /* * RARP for the ip address of the specified interface, but also * save the ip address of the server that sent the answer. * Timeout if no response is received. */ int revarpwhoarewe(struct ifnet *ifp, struct in_addr *serv_in, struct in_addr *clnt_in) { int result, count = 20; if (revarp_finished) return EIO; revarp_ifidx = ifp->if_index; while (count--) { revarprequest(ifp); result = tsleep_nsec(&revarp_myip, PSOCK, "revarp", MSEC_TO_NSEC(500)); if (result != EWOULDBLOCK) break; } revarp_ifidx = 0; if (!revarp_finished) return ENETUNREACH; memcpy(serv_in, &revarp_srvip, sizeof(*serv_in)); memcpy(clnt_in, &revarp_myip, sizeof(*clnt_in)); return 0; } /* For compatibility: only saves interface address. */ int revarpwhoami(struct in_addr *in, struct ifnet *ifp) { struct in_addr server; return (revarpwhoarewe(ifp, &server, in)); } #endif /* NFSCLIENT */
11 11 10 11 3 11 3 10 10 10 8 2 5 8 8 4 5 4 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 /* $OpenBSD: kern_sensors.c,v 1.40 2022/12/05 23:18:37 deraadt Exp $ */ /* * Copyright (c) 2005 David Gwynne <dlg@openbsd.org> * Copyright (c) 2006 Constantine A. Murenin <cnst+openbsd@bugmail.mojo.ru> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/queue.h> #include <sys/device.h> #include <sys/hotplug.h> #include <sys/timeout.h> #include <sys/task.h> #include <sys/rwlock.h> #include <sys/atomic.h> #include <sys/sensors.h> #include "hotplug.h" struct taskq *sensors_taskq; int sensordev_count; SLIST_HEAD(, ksensordev) sensordev_list = SLIST_HEAD_INITIALIZER(sensordev_list); void sensordev_install(struct ksensordev *sensdev) { struct ksensordev *v, *nv; int s; s = splhigh(); if (sensordev_count == 0) { sensdev->num = 0; SLIST_INSERT_HEAD(&sensordev_list, sensdev, list); } else { for (v = SLIST_FIRST(&sensordev_list); (nv = SLIST_NEXT(v, list)) != NULL; v = nv) if (nv->num - v->num > 1) break; sensdev->num = v->num + 1; SLIST_INSERT_AFTER(v, sensdev, list); } sensordev_count++; splx(s); #if NHOTPLUG > 0 hotplug_device_attach(DV_DULL, "sensordev"); #endif } void sensor_attach(struct ksensordev *sensdev, struct ksensor *sens) { struct ksensor *v, *nv; struct ksensors_head *sh; int s, i; s = splhigh(); sh = &sensdev->sensors_list; if (sensdev->sensors_count == 0) { for (i = 0; i < SENSOR_MAX_TYPES; i++) sensdev->maxnumt[i] = 0; sens->numt = 0; SLIST_INSERT_HEAD(sh, sens, list); } else { for (v = SLIST_FIRST(sh); (nv = SLIST_NEXT(v, list)) != NULL; v = nv) if (v->type == sens->type && (v->type != nv->type || (v->type == nv->type && nv->numt - v->numt > 1))) break; /* sensors of the same type go after each other */ if (v->type == sens->type) sens->numt = v->numt + 1; else sens->numt = 0; SLIST_INSERT_AFTER(v, sens, list); } /* we only increment maxnumt[] if the sensor was added * to the last position of sensors of this type */ if (sensdev->maxnumt[sens->type] == sens->numt) sensdev->maxnumt[sens->type]++; sensdev->sensors_count++; splx(s); } void sensordev_deinstall(struct ksensordev *sensdev) { int s; s = splhigh(); sensordev_count--; SLIST_REMOVE(&sensordev_list, sensdev, ksensordev, list); splx(s); #if NHOTPLUG > 0 hotplug_device_detach(DV_DULL, "sensordev"); #endif } void sensor_detach(struct ksensordev *sensdev, struct ksensor *sens) { struct ksensors_head *sh; int s; s = splhigh(); sh = &sensdev->sensors_list; sensdev->sensors_count--; SLIST_REMOVE(sh, sens, ksensor, list); /* we only decrement maxnumt[] if this is the tail * sensor of this type */ if (sens->numt == sensdev->maxnumt[sens->type] - 1) sensdev->maxnumt[sens->type]--; splx(s); } int sensordev_get(int num, struct ksensordev **sensdev) { struct ksensordev *sd; SLIST_FOREACH(sd, &sensordev_list, list) { if (sd->num == num) { *sensdev = sd; return (0); } if (sd->num > num) return (ENXIO); } return (ENOENT); } int sensor_find(int dev, enum sensor_type type, int numt, struct ksensor **ksensorp) { struct ksensor *s; struct ksensordev *sensdev; struct ksensors_head *sh; int ret; ret = sensordev_get(dev, &sensdev); if (ret) return (ret); sh = &sensdev->sensors_list; SLIST_FOREACH(s, sh, list) if (s->type == type && s->numt == numt) { *ksensorp = s; return (0); } return (ENOENT); } struct sensor_task { void (*func)(void *); void *arg; unsigned int period; struct timeout timeout; struct task task; struct rwlock lock; }; void sensor_task_tick(void *); void sensor_task_work(void *); struct sensor_task * sensor_task_register(void *arg, void (*func)(void *), unsigned int period) { struct sensor_task *st; #ifdef DIAGNOSTIC if (period == 0) panic("sensor_task_register: period is 0"); #endif if (sensors_taskq == NULL && (sensors_taskq = taskq_create("sensors", 1, IPL_HIGH, 0)) == NULL) sensors_taskq = systq; st = malloc(sizeof(*st), M_DEVBUF, M_NOWAIT); if (st == NULL) return (NULL); st->func = func; st->arg = arg; st->period = period; timeout_set(&st->timeout, sensor_task_tick, st); task_set(&st->task, sensor_task_work, st); rw_init(&st->lock, "sensor"); sensor_task_tick(st); return (st); } void sensor_task_unregister(struct sensor_task *st) { /* * we can't reliably timeout_del or task_del because there's a window * between when they come off the lists and the timeout or task code * actually runs the respective handlers for them. mark the sensor_task * as dying by setting period to 0 and let sensor_task_work mop up. */ rw_enter_write(&st->lock); st->period = 0; rw_exit_write(&st->lock); } void sensor_task_tick(void *arg) { struct sensor_task *st = arg; task_add(sensors_taskq, &st->task); } static int sensors_quiesced; static int sensors_running; void sensor_quiesce(void) { sensors_quiesced = 1; while (sensors_running > 0) tsleep_nsec(&sensors_running, PZERO, "sensorpause", INFSLP); } void sensor_restart(void) { sensors_quiesced = 0; } void sensor_task_work(void *xst) { struct sensor_task *st = xst; unsigned int period = 0; atomic_inc_int(&sensors_running); rw_enter_write(&st->lock); period = st->period; if (period > 0 && !sensors_quiesced) st->func(st->arg); rw_exit_write(&st->lock); if (atomic_dec_int_nv(&sensors_running) == 0) { if (sensors_quiesced) wakeup(&sensors_running); } if (period == 0) free(st, M_DEVBUF, sizeof(*st)); else timeout_add_sec(&st->timeout, period); }
4 4 211 211 211 210 210 211 211 211 210 210 1 1 1 211 211 1 1 209 1 1 1 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 /* $OpenBSD: scsi_base.c,v 1.283 2023/08/02 19:58:52 kettenis Exp $ */ /* $NetBSD: scsi_base.c,v 1.43 1997/04/02 02:29:36 mycroft Exp $ */ /* * Copyright (c) 1994, 1995, 1997 Charles M. Hannum. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Charles M. Hannum. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Originally written by Julian Elischer (julian@dialix.oz.au) * Detailed SCSI error printing Copyright 1997 by Matthew Jacob. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/uio.h> #include <sys/errno.h> #include <sys/device.h> #include <sys/pool.h> #include <sys/task.h> #include <scsi/scsi_all.h> #include <scsi/scsi_debug.h> #include <scsi/scsi_disk.h> #include <scsi/scsiconf.h> static __inline void asc2ascii(u_int8_t, u_int8_t ascq, char *result, size_t len); int scsi_xs_error(struct scsi_xfer *); char *scsi_decode_sense(struct scsi_sense_data *, int); void scsi_xs_sync_done(struct scsi_xfer *); /* Values for flag parameter to scsi_decode_sense. */ #define DECODE_SENSE_KEY 1 #define DECODE_ASC_ASCQ 2 #define DECODE_SKSV 3 struct pool scsi_xfer_pool; struct pool scsi_plug_pool; struct scsi_plug { struct task task; struct scsibus_softc *sb; int target; int lun; int how; }; void scsi_plug_probe(void *); void scsi_plug_detach(void *); struct scsi_xfer * scsi_xs_io(struct scsi_link *, void *, int); int scsi_ioh_pending(struct scsi_iopool *); struct scsi_iohandler * scsi_ioh_deq(struct scsi_iopool *); void scsi_xsh_runqueue(struct scsi_link *); void scsi_xsh_ioh(void *, void *); int scsi_link_open(struct scsi_link *); void scsi_link_close(struct scsi_link *); void * scsi_iopool_get(struct scsi_iopool *); void scsi_iopool_put(struct scsi_iopool *, void *); /* Various helper functions for scsi_do_mode_sense() */ int scsi_mode_sense(struct scsi_link *, int, union scsi_mode_sense_buf *, int); int scsi_mode_sense_big(struct scsi_link *, int, union scsi_mode_sense_buf *, int); void * scsi_mode_sense_page(struct scsi_mode_header *, int, int); void * scsi_mode_sense_big_page(struct scsi_mode_header_big *, int, int); /* ioh/xsh queue state */ #define RUNQ_IDLE 0 #define RUNQ_LINKQ 1 #define RUNQ_POOLQ 2 /* synchronous api for allocating an io. */ struct scsi_io_mover { struct mutex mtx; void *io; u_int done; }; #define SCSI_IO_MOVER_INITIALIZER { MUTEX_INITIALIZER(IPL_BIO), NULL, 0 } void scsi_move(struct scsi_io_mover *); void scsi_move_done(void *, void *); void scsi_io_get_done(void *, void *); void scsi_xs_get_done(void *, void *); /* * Called when a scsibus is attached to initialize global data. */ void scsi_init(void) { static int scsi_init_done; if (scsi_init_done) return; scsi_init_done = 1; #if defined(SCSI_DELAY) && SCSI_DELAY > 0 /* Historical. Older buses may need a moment to stabilize. */ delay(1000000 * SCSI_DELAY); #endif /* SCSI_DELAY && SCSI_DELAY > 0 */ /* Initialize the scsi_xfer pool. */ pool_init(&scsi_xfer_pool, sizeof(struct scsi_xfer), 0, IPL_BIO, 0, "scxspl", NULL); pool_setlowat(&scsi_xfer_pool, 8); pool_prime(&scsi_xfer_pool, 8); pool_init(&scsi_plug_pool, sizeof(struct scsi_plug), 0, IPL_BIO, 0, "scsiplug", NULL); } int scsi_req_probe(struct scsibus_softc *sb, int target, int lun) { struct scsi_plug *p; p = pool_get(&scsi_plug_pool, PR_NOWAIT); if (p == NULL) return ENOMEM; task_set(&p->task, scsi_plug_probe, p); p->sb = sb; p->target = target; p->lun = lun; task_add(systq, &p->task); return 0; } int scsi_req_detach(struct scsibus_softc *sb, int target, int lun, int how) { struct scsi_plug *p; p = pool_get(&scsi_plug_pool, PR_NOWAIT); if (p == NULL) return ENOMEM; task_set(&p->task, scsi_plug_detach, p); p->sb = sb; p->target = target; p->lun = lun; p->how = how; task_add(systq, &p->task); return 0; } void scsi_plug_probe(void *xp) { struct scsi_plug *p = xp; struct scsibus_softc *sb = p->sb; int target = p->target, lun = p->lun; pool_put(&scsi_plug_pool, p); scsi_probe(sb, target, lun); } void scsi_plug_detach(void *xp) { struct scsi_plug *p = xp; struct scsibus_softc *sb = p->sb; int target = p->target, lun = p->lun; int how = p->how; pool_put(&scsi_plug_pool, p); scsi_detach(sb, target, lun, how); } int scsi_pending_start(struct mutex *mtx, u_int *running) { int rv = 1; mtx_enter(mtx); (*running)++; if ((*running) > 1) rv = 0; mtx_leave(mtx); return rv; } int scsi_pending_finish(struct mutex *mtx, u_int *running) { int rv = 1; mtx_enter(mtx); (*running)--; if ((*running) > 0) { (*running) = 1; rv = 0; } mtx_leave(mtx); return rv; } void scsi_iopool_init(struct scsi_iopool *iopl, void *iocookie, void *(*io_get)(void *), void (*io_put)(void *, void *)) { iopl->iocookie = iocookie; iopl->io_get = io_get; iopl->io_put = io_put; TAILQ_INIT(&iopl->queue); iopl->running = 0; mtx_init(&iopl->mtx, IPL_BIO); } void * scsi_iopool_get(struct scsi_iopool *iopl) { void *io; KERNEL_LOCK(); io = iopl->io_get(iopl->iocookie); KERNEL_UNLOCK(); return io; } void scsi_iopool_put(struct scsi_iopool *iopl, void *io) { KERNEL_LOCK(); iopl->io_put(iopl->iocookie, io); KERNEL_UNLOCK(); } void scsi_iopool_destroy(struct scsi_iopool *iopl) { struct scsi_runq sleepers = TAILQ_HEAD_INITIALIZER(sleepers); struct scsi_iohandler *ioh = NULL; mtx_enter(&iopl->mtx); while ((ioh = TAILQ_FIRST(&iopl->queue)) != NULL) { TAILQ_REMOVE(&iopl->queue, ioh, q_entry); ioh->q_state = RUNQ_IDLE; if (ioh->handler == scsi_io_get_done) TAILQ_INSERT_TAIL(&sleepers, ioh, q_entry); #ifdef DIAGNOSTIC else panic("scsi_iopool_destroy: scsi_iohandler on pool"); #endif /* DIAGNOSTIC */ } mtx_leave(&iopl->mtx); while ((ioh = TAILQ_FIRST(&sleepers)) != NULL) { TAILQ_REMOVE(&sleepers, ioh, q_entry); ioh->handler(ioh->cookie, NULL); } } void * scsi_default_get(void *iocookie) { return SCSI_IOPOOL_POISON; } void scsi_default_put(void *iocookie, void *io) { #ifdef DIAGNOSTIC if (io != SCSI_IOPOOL_POISON) panic("unexpected opening returned"); #endif /* DIAGNOSTIC */ } /* * public interface to the ioh api. */ void scsi_ioh_set(struct scsi_iohandler *ioh, struct scsi_iopool *iopl, void (*handler)(void *, void *), void *cookie) { ioh->q_state = RUNQ_IDLE; ioh->pool = iopl; ioh->handler = handler; ioh->cookie = cookie; } int scsi_ioh_add(struct scsi_iohandler *ioh) { struct scsi_iopool *iopl = ioh->pool; int rv = 0; mtx_enter(&iopl->mtx); switch (ioh->q_state) { case RUNQ_IDLE: TAILQ_INSERT_TAIL(&iopl->queue, ioh, q_entry); ioh->q_state = RUNQ_POOLQ; rv = 1; break; #ifdef DIAGNOSTIC case RUNQ_POOLQ: break; default: panic("scsi_ioh_add: unexpected state %u", ioh->q_state); #endif /* DIAGNOSTIC */ } mtx_leave(&iopl->mtx); /* lets get some io up in the air */ scsi_iopool_run(iopl); return rv; } int scsi_ioh_del(struct scsi_iohandler *ioh) { struct scsi_iopool *iopl = ioh->pool; int rv = 0; mtx_enter(&iopl->mtx); switch (ioh->q_state) { case RUNQ_POOLQ: TAILQ_REMOVE(&iopl->queue, ioh, q_entry); ioh->q_state = RUNQ_IDLE; rv = 1; break; #ifdef DIAGNOSTIC case RUNQ_IDLE: break; default: panic("scsi_ioh_del: unexpected state %u", ioh->q_state); #endif /* DIAGNOSTIC */ } mtx_leave(&iopl->mtx); return rv; } /* * internal iopool runqueue handling. */ struct scsi_iohandler * scsi_ioh_deq(struct scsi_iopool *iopl) { struct scsi_iohandler *ioh = NULL; mtx_enter(&iopl->mtx); ioh = TAILQ_FIRST(&iopl->queue); if (ioh != NULL) { TAILQ_REMOVE(&iopl->queue, ioh, q_entry); ioh->q_state = RUNQ_IDLE; } mtx_leave(&iopl->mtx); return ioh; } int scsi_ioh_pending(struct scsi_iopool *iopl) { int rv; mtx_enter(&iopl->mtx); rv = !TAILQ_EMPTY(&iopl->queue); mtx_leave(&iopl->mtx); return rv; } void scsi_iopool_run(struct scsi_iopool *iopl) { struct scsi_iohandler *ioh; void *io; if (!scsi_pending_start(&iopl->mtx, &iopl->running)) return; do { while (scsi_ioh_pending(iopl)) { io = scsi_iopool_get(iopl); if (io == NULL) break; ioh = scsi_ioh_deq(iopl); if (ioh == NULL) { scsi_iopool_put(iopl, io); break; } ioh->handler(ioh->cookie, io); } } while (!scsi_pending_finish(&iopl->mtx, &iopl->running)); } /* * move an io from a runq to a proc thats waiting for an io. */ void scsi_move(struct scsi_io_mover *m) { mtx_enter(&m->mtx); while (!m->done) msleep_nsec(m, &m->mtx, PRIBIO, "scsiiomv", INFSLP); mtx_leave(&m->mtx); } void scsi_move_done(void *cookie, void *io) { struct scsi_io_mover *m = cookie; mtx_enter(&m->mtx); m->io = io; m->done = 1; wakeup_one(m); mtx_leave(&m->mtx); } /* * synchronous api for allocating an io. */ void * scsi_io_get(struct scsi_iopool *iopl, int flags) { struct scsi_io_mover m = SCSI_IO_MOVER_INITIALIZER; struct scsi_iohandler ioh; void *io; /* try and sneak an io off the backend immediately */ io = scsi_iopool_get(iopl); if (io != NULL) return io; else if (ISSET(flags, SCSI_NOSLEEP)) return NULL; /* otherwise sleep until we get one */ scsi_ioh_set(&ioh, iopl, scsi_io_get_done, &m); scsi_ioh_add(&ioh); scsi_move(&m); return m.io; } void scsi_io_get_done(void *cookie, void *io) { scsi_move_done(cookie, io); } void scsi_io_put(struct scsi_iopool *iopl, void *io) { scsi_iopool_put(iopl, io); scsi_iopool_run(iopl); } /* * public interface to the xsh api. */ void scsi_xsh_set(struct scsi_xshandler *xsh, struct scsi_link *link, void (*handler)(struct scsi_xfer *)) { scsi_ioh_set(&xsh->ioh, link->pool, scsi_xsh_ioh, xsh); xsh->link = link; xsh->handler = handler; } int scsi_xsh_add(struct scsi_xshandler *xsh) { struct scsi_link *link = xsh->link; int rv = 0; if (ISSET(link->state, SDEV_S_DYING)) return 0; mtx_enter(&link->pool->mtx); if (xsh->ioh.q_state == RUNQ_IDLE) { TAILQ_INSERT_TAIL(&link->queue, &xsh->ioh, q_entry); xsh->ioh.q_state = RUNQ_LINKQ; rv = 1; } mtx_leave(&link->pool->mtx); /* lets get some io up in the air */ scsi_xsh_runqueue(link); return rv; } int scsi_xsh_del(struct scsi_xshandler *xsh) { struct scsi_link *link = xsh->link; int rv = 1; mtx_enter(&link->pool->mtx); switch (xsh->ioh.q_state) { case RUNQ_IDLE: rv = 0; break; case RUNQ_LINKQ: TAILQ_REMOVE(&link->queue, &xsh->ioh, q_entry); break; case RUNQ_POOLQ: TAILQ_REMOVE(&link->pool->queue, &xsh->ioh, q_entry); link->pending--; if (ISSET(link->state, SDEV_S_DYING) && link->pending == 0) wakeup_one(&link->pending); break; default: panic("unexpected xsh state %u", xsh->ioh.q_state); } xsh->ioh.q_state = RUNQ_IDLE; mtx_leave(&link->pool->mtx); return rv; } /* * internal xs runqueue handling. */ void scsi_xsh_runqueue(struct scsi_link *link) { struct scsi_iohandler *ioh; int runq; if (!scsi_pending_start(&link->pool->mtx, &link->running)) return; do { runq = 0; mtx_enter(&link->pool->mtx); while (!ISSET(link->state, SDEV_S_DYING) && link->pending < link->openings && ((ioh = TAILQ_FIRST(&link->queue)) != NULL)) { link->pending++; TAILQ_REMOVE(&link->queue, ioh, q_entry); TAILQ_INSERT_TAIL(&link->pool->queue, ioh, q_entry); ioh->q_state = RUNQ_POOLQ; runq = 1; } mtx_leave(&link->pool->mtx); if (runq) scsi_iopool_run(link->pool); } while (!scsi_pending_finish(&link->pool->mtx, &link->running)); } void scsi_xsh_ioh(void *cookie, void *io) { struct scsi_xshandler *xsh = cookie; struct scsi_xfer *xs; xs = scsi_xs_io(xsh->link, io, SCSI_NOSLEEP); if (xs == NULL) { /* * in this situation we should queue things waiting for an * xs and then give them xses when they were supposed be to * returned to the pool. */ printf("scsi_xfer pool exhausted!\n"); scsi_xsh_add(xsh); return; } xsh->handler(xs); } /* * Get a scsi transfer structure for the caller. * Go to the iopool backend for an "opening" and then attach an xs to it. */ struct scsi_xfer * scsi_xs_get(struct scsi_link *link, int flags) { struct scsi_xshandler xsh; struct scsi_io_mover m = SCSI_IO_MOVER_INITIALIZER; struct scsi_iopool *iopl = link->pool; void *io; if (ISSET(link->state, SDEV_S_DYING)) return NULL; /* really custom xs handler to avoid scsi_xsh_ioh */ scsi_ioh_set(&xsh.ioh, iopl, scsi_xs_get_done, &m); xsh.link = link; if (!scsi_link_open(link)) { if (ISSET(flags, SCSI_NOSLEEP)) return NULL; scsi_xsh_add(&xsh); scsi_move(&m); if (m.io == NULL) return NULL; io = m.io; } else if ((io = scsi_iopool_get(iopl)) == NULL) { if (ISSET(flags, SCSI_NOSLEEP)) { scsi_link_close(link); return NULL; } scsi_ioh_add(&xsh.ioh); scsi_move(&m); if (m.io == NULL) return NULL; io = m.io; } return scsi_xs_io(link, io, flags); } void scsi_xs_get_done(void *cookie, void *io) { scsi_move_done(cookie, io); } void scsi_link_shutdown(struct scsi_link *link) { struct scsi_runq sleepers = TAILQ_HEAD_INITIALIZER(sleepers); struct scsi_iopool *iopl = link->pool; struct scsi_iohandler *ioh; struct scsi_xshandler *xsh; mtx_enter(&iopl->mtx); while ((ioh = TAILQ_FIRST(&link->queue)) != NULL) { TAILQ_REMOVE(&link->queue, ioh, q_entry); ioh->q_state = RUNQ_IDLE; if (ioh->handler == scsi_xs_get_done) TAILQ_INSERT_TAIL(&sleepers, ioh, q_entry); #ifdef DIAGNOSTIC else panic("scsi_link_shutdown: scsi_xshandler on link"); #endif /* DIAGNOSTIC */ } ioh = TAILQ_FIRST(&iopl->queue); while (ioh != NULL) { xsh = (struct scsi_xshandler *)ioh; ioh = TAILQ_NEXT(ioh, q_entry); #ifdef DIAGNOSTIC if (xsh->ioh.handler == scsi_xsh_ioh && xsh->link == link) panic("scsi_link_shutdown: scsi_xshandler on pool"); #endif /* DIAGNOSTIC */ if (xsh->ioh.handler == scsi_xs_get_done && xsh->link == link) { TAILQ_REMOVE(&iopl->queue, &xsh->ioh, q_entry); xsh->ioh.q_state = RUNQ_IDLE; link->pending--; TAILQ_INSERT_TAIL(&sleepers, &xsh->ioh, q_entry); } } while (link->pending > 0) msleep_nsec(&link->pending, &iopl->mtx, PRIBIO, "pendxs", INFSLP); mtx_leave(&iopl->mtx); while ((ioh = TAILQ_FIRST(&sleepers)) != NULL) { TAILQ_REMOVE(&sleepers, ioh, q_entry); ioh->handler(ioh->cookie, NULL); } } int scsi_link_open(struct scsi_link *link) { int open = 0; mtx_enter(&link->pool->mtx); if (link->pending < link->openings) { link->pending++; open = 1; } mtx_leave(&link->pool->mtx); return open; } void scsi_link_close(struct scsi_link *link) { mtx_enter(&link->pool->mtx); link->pending--; if (ISSET(link->state, SDEV_S_DYING) && link->pending == 0) wakeup_one(&link->pending); mtx_leave(&link->pool->mtx); scsi_xsh_runqueue(link); } struct scsi_xfer * scsi_xs_io(struct scsi_link *link, void *io, int flags) { struct scsi_xfer *xs; xs = pool_get(&scsi_xfer_pool, PR_ZERO | (ISSET(flags, SCSI_NOSLEEP) ? PR_NOWAIT : PR_WAITOK)); if (xs == NULL) { scsi_io_put(link->pool, io); scsi_link_close(link); } else { xs->flags = flags; xs->sc_link = link; xs->retries = SCSI_RETRIES; xs->timeout = 10000; xs->io = io; } return xs; } void scsi_xs_put(struct scsi_xfer *xs) { struct scsi_link *link = xs->sc_link; void *io = xs->io; pool_put(&scsi_xfer_pool, xs); scsi_io_put(link->pool, io); scsi_link_close(link); } /* * Get scsi driver to send a "are you ready?" command */ int scsi_test_unit_ready(struct scsi_link *link, int retries, int flags) { struct scsi_test_unit_ready *cmd; struct scsi_xfer *xs; int error; xs = scsi_xs_get(link, flags); if (xs == NULL) return ENOMEM; xs->cmdlen = sizeof(*cmd); xs->retries = retries; xs->timeout = 10000; cmd = (struct scsi_test_unit_ready *)&xs->cmd; cmd->opcode = TEST_UNIT_READY; error = scsi_xs_sync(xs); scsi_xs_put(xs); return error; } void scsi_init_inquiry(struct scsi_xfer *xs, u_int8_t flags, u_int8_t pagecode, void *data, size_t len) { struct scsi_inquiry *cmd; cmd = (struct scsi_inquiry *)&xs->cmd; cmd->opcode = INQUIRY; cmd->flags = flags; cmd->pagecode = pagecode; _lto2b(len, cmd->length); xs->cmdlen = sizeof(*cmd); SET(xs->flags, SCSI_DATA_IN); xs->data = data; xs->datalen = len; } /* * Do a scsi operation asking a device what it is. * Use the scsi_cmd routine in the switch table. */ int scsi_inquire(struct scsi_link *link, struct scsi_inquiry_data *inqbuf, int flags) { struct scsi_xfer *xs; size_t bytes; int avail, retries, error, received; /* * Start by asking for only the basic 36 bytes of SCSI2 inquiry * information. This avoids problems with devices that choke trying to * supply more. */ bytes = SID_SCSI2_HDRLEN + SID_SCSI2_ALEN; retries = 0; again: xs = scsi_xs_get(link, flags); if (xs == NULL) return EBUSY; if (bytes > sizeof(*inqbuf)) bytes = sizeof(*inqbuf); scsi_init_inquiry(xs, 0, 0, inqbuf, bytes); error = scsi_xs_sync(xs); received = xs->datalen - xs->resid; scsi_xs_put(xs); if (error != 0) { SC_DEBUG(link, SDEV_DB2, ("INQUIRE error %d\n", error)); return error; } if (received < SID_SCSI2_HDRLEN) { SC_DEBUG(link, SDEV_DB2, ("INQUIRE data < SID_SCSI2_HDRLEN\n")); return EINVAL; } avail = SID_SCSI2_HDRLEN + inqbuf->additional_length; if (received < avail && retries == 0) { retries++; bytes = avail; goto again; } #ifdef SCSIDEBUG sc_print_addr(link); printf("got %d of %d bytes of inquiry data:\n", received, avail); scsi_show_mem((u_char *)inqbuf, received); sc_print_addr(link); scsi_show_inquiry_header(inqbuf); sc_print_addr(link); scsi_show_inquiry_match(inqbuf); #endif /* SCSIDEBUG */ if (avail > received) inqbuf->additional_length = received - SID_SCSI2_HDRLEN; return 0; } /* * Query a VPD inquiry page */ int scsi_inquire_vpd(struct scsi_link *link, void *buf, u_int buflen, u_int8_t page, int flags) { struct scsi_xfer *xs; int error; #ifdef SCSIDEBUG u_int32_t bytes; #endif /* SCSIDEBUG */ if (ISSET(link->flags, SDEV_UMASS)) return EJUSTRETURN; xs = scsi_xs_get(link, flags | SCSI_DATA_IN | SCSI_SILENT); if (xs == NULL) return ENOMEM; xs->retries = 2; xs->timeout = 10000; scsi_init_inquiry(xs, SI_EVPD, page, buf, buflen); error = scsi_xs_sync(xs); scsi_xs_put(xs); #ifdef SCSIDEBUG sc_print_addr(link); if (error == 0) { bytes = sizeof(struct scsi_vpd_hdr) + _2btol(((struct scsi_vpd_hdr *)buf)->page_length); if (bytes < buflen) buflen = bytes; printf("got %u of %u bytes of VPD inquiry page %u data:\n", buflen, bytes, page); scsi_show_mem(buf, buflen); } else { printf("VPD inquiry page %u not available\n", page); } #endif /* SCSIDEBUG */ return error; } int scsi_read_cap_10(struct scsi_link *link, struct scsi_read_cap_data *rdcap, int flags) { struct scsi_read_capacity cdb; struct scsi_xfer *xs; int rv; xs = scsi_xs_get(link, flags | SCSI_DATA_IN | SCSI_SILENT); if (xs == NULL) return ENOMEM; memset(&cdb, 0, sizeof(cdb)); cdb.opcode = READ_CAPACITY; memcpy(&xs->cmd, &cdb, sizeof(cdb)); xs->cmdlen = sizeof(cdb); xs->data = (void *)rdcap; xs->datalen = sizeof(*rdcap); xs->timeout = 20000; rv = scsi_xs_sync(xs); scsi_xs_put(xs); #ifdef SCSIDEBUG if (rv == 0) { sc_print_addr(link); printf("read capacity 10 data:\n"); scsi_show_mem((u_char *)rdcap, sizeof(*rdcap)); } #endif /* SCSIDEBUG */ return rv; } int scsi_read_cap_16(struct scsi_link *link, struct scsi_read_cap_data_16 *rdcap, int flags) { struct scsi_read_capacity_16 cdb; struct scsi_xfer *xs; int rv; xs = scsi_xs_get(link, flags | SCSI_DATA_IN | SCSI_SILENT); if (xs == NULL) return ENOMEM; memset(&cdb, 0, sizeof(cdb)); cdb.opcode = READ_CAPACITY_16; cdb.byte2 = SRC16_SERVICE_ACTION; _lto4b(sizeof(*rdcap), cdb.length); memcpy(&xs->cmd, &cdb, sizeof(cdb)); xs->cmdlen = sizeof(cdb); xs->data = (void *)rdcap; xs->datalen = sizeof(*rdcap); xs->timeout = 20000; rv = scsi_xs_sync(xs); scsi_xs_put(xs); #ifdef SCSIDEBUG if (rv == 0) { sc_print_addr(link); printf("read capacity 16 data:\n"); scsi_show_mem((u_char *)rdcap, sizeof(*rdcap)); } #endif /* SCSIDEBUG */ return rv; } /* * Prevent or allow the user to remove the media */ int scsi_prevent(struct scsi_link *link, int type, int flags) { struct scsi_prevent *cmd; struct scsi_xfer *xs; int error; if (ISSET(link->quirks, ADEV_NODOORLOCK)) return 0; xs = scsi_xs_get(link, flags); if (xs == NULL) return ENOMEM; xs->cmdlen = sizeof(*cmd); xs->retries = 2; xs->timeout = 5000; cmd = (struct scsi_prevent *)&xs->cmd; cmd->opcode = PREVENT_ALLOW; cmd->how = type; error = scsi_xs_sync(xs); scsi_xs_put(xs); return error; } /* * Get scsi driver to send a "start up" command */ int scsi_start(struct scsi_link *link, int type, int flags) { struct scsi_start_stop *cmd; struct scsi_xfer *xs; int error; xs = scsi_xs_get(link, flags); if (xs == NULL) return ENOMEM; xs->cmdlen = sizeof(*cmd); xs->retries = 2; xs->timeout = (type == SSS_START) ? 30000 : 10000; cmd = (struct scsi_start_stop *)&xs->cmd; cmd->opcode = START_STOP; cmd->how = type; error = scsi_xs_sync(xs); scsi_xs_put(xs); return error; } int scsi_mode_sense(struct scsi_link *link, int pg_code, union scsi_mode_sense_buf *data, int flags) { struct scsi_mode_sense *cmd; struct scsi_xfer *xs; size_t len; int error; #ifdef SCSIDEBUG size_t bytes; #endif /* SCSIDEBUG */ len = sizeof(*data); xs = scsi_xs_get(link, flags | SCSI_DATA_IN); if (xs == NULL) return ENOMEM; xs->cmdlen = sizeof(*cmd); xs->data = (void *)data; xs->datalen = len; xs->timeout = 20000; /* * Make sure the sense buffer is clean before we do the mode sense, so * that checks for bogus values of 0 will work in case the mode sense * fails. */ memset(data, 0, len); cmd = (struct scsi_mode_sense *)&xs->cmd; cmd->opcode = MODE_SENSE; cmd->page = pg_code; if (len > 0xff) len = 0xff; cmd->length = len; error = scsi_xs_sync(xs); scsi_xs_put(xs); if (error == 0 && !VALID_MODE_HDR(&data->hdr)) error = EIO; #ifdef SCSIDEBUG sc_print_addr(link); if (error == 0) { bytes = sizeof(data->hdr.data_length) + data->hdr.data_length; if (bytes < len) len = bytes; printf("got %zu of %zu bytes of mode sense (6) page %d data:\n", len, bytes, pg_code); scsi_show_mem((u_char *)data, len); } else printf("mode sense (6) page %d not available\n", pg_code); #endif /* SCSIDEBUG */ return error; } int scsi_mode_sense_big(struct scsi_link *link, int pg_code, union scsi_mode_sense_buf *data, int flags) { struct scsi_mode_sense_big *cmd; struct scsi_xfer *xs; size_t len; int error; #ifdef SCSIDEBUG size_t bytes; #endif /* SCSIDEBUG */ len = sizeof(*data); xs = scsi_xs_get(link, flags | SCSI_DATA_IN); if (xs == NULL) return ENOMEM; xs->cmdlen = sizeof(*cmd); xs->data = (void *)data; xs->datalen = len; xs->timeout = 20000; /* * Make sure the sense buffer is clean before we do the mode sense, so * that checks for bogus values of 0 will work in case the mode sense * fails. */ memset(data, 0, len); cmd = (struct scsi_mode_sense_big *)&xs->cmd; cmd->opcode = MODE_SENSE_BIG; cmd->page = pg_code; if (len > 0xffff) len = 0xffff; _lto2b(len, cmd->length); error = scsi_xs_sync(xs); scsi_xs_put(xs); if (error == 0 && !VALID_MODE_HDR_BIG(&data->hdr_big)) error = EIO; #ifdef SCSIDEBUG sc_print_addr(link); if (error == 0) { bytes = sizeof(data->hdr_big.data_length) + _2btol(data->hdr_big.data_length); if (bytes < len) len = bytes; printf("got %zu bytes of %zu bytes of mode sense (10) page %d " "data:\n", len, bytes, pg_code); scsi_show_mem((u_char *)data, len); } else printf("mode sense (10) page %d not available\n", pg_code); #endif /* SCSIDEBUG */ return error; } void * scsi_mode_sense_page(struct scsi_mode_header *hdr, int pg_code, int pg_length) { u_int8_t *page; int total_length, header_length; total_length = hdr->data_length + sizeof(hdr->data_length); header_length = sizeof(*hdr) + hdr->blk_desc_len; page = (u_int8_t *)hdr + header_length; if ((total_length - header_length) < pg_length) return NULL; if ((*page & SMS_PAGE_CODE) != pg_code) return NULL; return page; } void * scsi_mode_sense_big_page(struct scsi_mode_header_big *hdr, int pg_code, int pg_length) { u_int8_t *page; int total_length, header_length; total_length = _2btol(hdr->data_length) + sizeof(hdr->data_length); header_length = sizeof(*hdr) + _2btol(hdr->blk_desc_len); page = (u_int8_t *)hdr + header_length; if ((total_length - header_length) < pg_length) return NULL; if ((*page & SMS_PAGE_CODE) != pg_code) return NULL; return page; } void scsi_parse_blkdesc(struct scsi_link *link, union scsi_mode_sense_buf *buf, int big, u_int32_t *density, u_int64_t *block_count, u_int32_t *block_size) { struct scsi_direct_blk_desc *direct; struct scsi_blk_desc *general; size_t offset; unsigned int blk_desc_len; if (big == 0) { offset = sizeof(struct scsi_mode_header); blk_desc_len = buf->hdr.blk_desc_len; } else { offset = sizeof(struct scsi_mode_header_big); blk_desc_len = _2btol(buf->hdr_big.blk_desc_len); } /* Both scsi_blk_desc and scsi_direct_blk_desc are 8 bytes. */ if (blk_desc_len == 0 || (blk_desc_len % 8 != 0)) return; switch (link->inqdata.device & SID_TYPE) { case T_SEQUENTIAL: /* * XXX What other device types return general block descriptors? */ general = (struct scsi_blk_desc *)&buf->buf[offset]; if (density != NULL) *density = general->density; if (block_size != NULL) *block_size = _3btol(general->blklen); if (block_count != NULL) *block_count = (u_int64_t)_3btol(general->nblocks); break; default: direct = (struct scsi_direct_blk_desc *)&buf->buf[offset]; if (density != NULL) *density = direct->density; if (block_size != NULL) *block_size = _3btol(direct->blklen); if (block_count != NULL) *block_count = (u_int64_t)_4btol(direct->nblocks); break; } } int scsi_do_mode_sense(struct scsi_link *link, int pg_code, union scsi_mode_sense_buf *buf, void **page_data, int pg_length, int flags, int *big) { int error = 0; *page_data = NULL; *big = 0; if (!ISSET(link->flags, SDEV_ATAPI) || (link->inqdata.device & SID_TYPE) == T_SEQUENTIAL) { /* * Try 6 byte mode sense request first. Some devices don't * distinguish between 6 and 10 byte MODE SENSE commands, * returning 6 byte data for 10 byte requests. ATAPI tape * drives use MODE SENSE (6) even though ATAPI uses 10 byte * everything else. Don't bother with SMS_DBD. Check returned * data length to ensure that at least a header (3 additional * bytes) is returned. */ error = scsi_mode_sense(link, pg_code, buf, flags); if (error == 0) { /* * Page data may be invalid (e.g. all zeros) but we * accept the device's word that this is the best it can * do. Some devices will freak out if their word is not * accepted and MODE_SENSE_BIG is attempted. */ *page_data = scsi_mode_sense_page(&buf->hdr, pg_code, pg_length); return 0; } } /* * non-ATAPI, non-USB devices that don't support SCSI-2 commands * (i.e. MODE SENSE (10)) are done. */ if (!ISSET(link->flags, (SDEV_ATAPI | SDEV_UMASS)) && SID_ANSII_REV(&link->inqdata) < SCSI_REV_2) return error; /* * Try 10 byte mode sense request. */ error = scsi_mode_sense_big(link, pg_code, buf, flags); if (error != 0) return error; *big = 1; *page_data = scsi_mode_sense_big_page(&buf->hdr_big, pg_code, pg_length); return 0; } int scsi_mode_select(struct scsi_link *link, int byte2, struct scsi_mode_header *data, int flags, int timeout) { struct scsi_mode_select *cmd; struct scsi_xfer *xs; int error; u_int32_t len; len = data->data_length + 1; /* 1 == sizeof(data_length) */ xs = scsi_xs_get(link, flags | SCSI_DATA_OUT); if (xs == NULL) return ENOMEM; xs->cmdlen = sizeof(*cmd); xs->data = (void *)data; xs->datalen = len; xs->timeout = timeout; cmd = (struct scsi_mode_select *)&xs->cmd; cmd->opcode = MODE_SELECT; cmd->byte2 = byte2; cmd->length = len; /* Length is reserved when doing mode select so zero it. */ data->data_length = 0; error = scsi_xs_sync(xs); scsi_xs_put(xs); SC_DEBUG(link, SDEV_DB2, ("scsi_mode_select: error = %d\n", error)); return error; } int scsi_mode_select_big(struct scsi_link *link, int byte2, struct scsi_mode_header_big *data, int flags, int timeout) { struct scsi_mode_select_big *cmd; struct scsi_xfer *xs; int error; u_int32_t len; len = _2btol(data->data_length) + 2; /* 2 == sizeof data_length */ xs = scsi_xs_get(link, flags | SCSI_DATA_OUT); if (xs == NULL) return ENOMEM; xs->cmdlen = sizeof(*cmd); xs->data = (void *)data; xs->datalen = len; xs->timeout = timeout; cmd = (struct scsi_mode_select_big *)&xs->cmd; cmd->opcode = MODE_SELECT_BIG; cmd->byte2 = byte2; _lto2b(len, cmd->length); /* Length is reserved when doing mode select so zero it. */ _lto2b(0, data->data_length); error = scsi_xs_sync(xs); scsi_xs_put(xs); SC_DEBUG(link, SDEV_DB2, ("scsi_mode_select_big: error = %d\n", error)); return error; } int scsi_report_luns(struct scsi_link *link, int selectreport, struct scsi_report_luns_data *data, u_int32_t datalen, int flags, int timeout) { struct scsi_report_luns *cmd; struct scsi_xfer *xs; int error; xs = scsi_xs_get(link, flags | SCSI_DATA_IN); if (xs == NULL) return ENOMEM; xs->cmdlen = sizeof(*cmd); xs->data = (void *)data; xs->datalen = datalen; xs->timeout = timeout; bzero(data, datalen); cmd = (struct scsi_report_luns *)&xs->cmd; cmd->opcode = REPORT_LUNS; cmd->selectreport = selectreport; _lto4b(datalen, cmd->length); error = scsi_xs_sync(xs); scsi_xs_put(xs); SC_DEBUG(link, SDEV_DB2, ("scsi_report_luns: error = %d\n", error)); return error; } void scsi_xs_exec(struct scsi_xfer *xs) { xs->error = XS_NOERROR; xs->resid = xs->datalen; xs->status = 0; CLR(xs->flags, ITSDONE); #ifdef SCSIDEBUG scsi_show_xs(xs); #endif /* SCSIDEBUG */ /* The adapter's scsi_cmd() is responsible for calling scsi_done(). */ KERNEL_LOCK(); xs->sc_link->bus->sb_adapter->scsi_cmd(xs); KERNEL_UNLOCK(); } /* * Used by device drivers that fake various scsi commands. */ void scsi_copy_internal_data(struct scsi_xfer *xs, void *data, size_t datalen) { size_t copy_cnt; SC_DEBUG(xs->sc_link, SDEV_DB3, ("scsi_copy_internal_data\n")); if (xs->datalen == 0) { sc_print_addr(xs->sc_link); printf("uio internal data copy not supported\n"); } else { copy_cnt = MIN(datalen, xs->datalen); memcpy(xs->data, data, copy_cnt); xs->resid = xs->datalen - copy_cnt; } } /* * This routine is called by the adapter when its xs handling is done. */ void scsi_done(struct scsi_xfer *xs) { #ifdef SCSIDEBUG if (ISSET(xs->sc_link->flags, SDEV_DB1)) { if (xs->datalen && ISSET(xs->flags, SCSI_DATA_IN)) scsi_show_mem(xs->data, min(64, xs->datalen)); } #endif /* SCSIDEBUG */ SET(xs->flags, ITSDONE); KERNEL_LOCK(); xs->done(xs); KERNEL_UNLOCK(); } int scsi_xs_sync(struct scsi_xfer *xs) { struct mutex cookie; int error; mtx_init(&cookie, IPL_BIO); #ifdef DIAGNOSTIC if (xs->cookie != NULL) panic("xs->cookie != NULL in scsi_xs_sync"); if (xs->done != NULL) panic("xs->done != NULL in scsi_xs_sync"); #endif /* DIAGNOSTIC */ /* * If we cant sleep while waiting for completion, get the adapter to * complete it for us. */ if (ISSET(xs->flags, SCSI_NOSLEEP)) SET(xs->flags, SCSI_POLL); xs->done = scsi_xs_sync_done; do { xs->cookie = &cookie; scsi_xs_exec(xs); mtx_enter(&cookie); while (xs->cookie != NULL) msleep_nsec(xs, &cookie, PRIBIO, "syncxs", INFSLP); mtx_leave(&cookie); error = scsi_xs_error(xs); } while (error == ERESTART); return error; } void scsi_xs_sync_done(struct scsi_xfer *xs) { struct mutex *cookie = xs->cookie; if (cookie == NULL) panic("scsi_done called twice on xs(%p)", xs); mtx_enter(cookie); xs->cookie = NULL; if (!ISSET(xs->flags, SCSI_NOSLEEP)) wakeup_one(xs); mtx_leave(cookie); } int scsi_xs_error(struct scsi_xfer *xs) { int error = EIO; SC_DEBUG(xs->sc_link, SDEV_DB3, ("scsi_xs_error,err = 0x%x\n", xs->error)); if (ISSET(xs->sc_link->state, SDEV_S_DYING)) return ENXIO; switch (xs->error) { case XS_NOERROR: /* nearly always hit this one */ error = 0; break; case XS_SENSE: case XS_SHORTSENSE: SC_DEBUG_SENSE(xs); error = xs->sc_link->interpret_sense(xs); SC_DEBUG(xs->sc_link, SDEV_DB3, ("scsi_interpret_sense returned %#x\n", error)); break; case XS_BUSY: error = scsi_delay(xs, 1); break; case XS_TIMEOUT: case XS_RESET: error = ERESTART; break; case XS_DRIVER_STUFFUP: case XS_SELTIMEOUT: break; default: sc_print_addr(xs->sc_link); printf("unknown error category (0x%x) from scsi driver\n", xs->error); break; } if (error == ERESTART && xs->retries-- < 1) return EIO; else return error; } int scsi_delay(struct scsi_xfer *xs, int seconds) { int ret; switch (xs->flags & (SCSI_POLL | SCSI_NOSLEEP)) { case SCSI_POLL: delay(1000000 * seconds); return ERESTART; case SCSI_NOSLEEP: /* Retry the command immediately since we can't delay. */ return ERESTART; case (SCSI_POLL | SCSI_NOSLEEP): /* Invalid combination! */ return EIO; } ret = tsleep_nsec(&ret, PRIBIO|PCATCH, "scbusy", SEC_TO_NSEC(seconds)); /* Signal == abort xs. */ if (ret == ERESTART || ret == EINTR) return EIO; return ERESTART; } /* * Look at the returned sense and act on the error, determining * the unix error number to pass back. (0 = report no error) * * THIS IS THE DEFAULT ERROR HANDLER */ int scsi_interpret_sense(struct scsi_xfer *xs) { struct scsi_sense_data *sense = &xs->sense; struct scsi_link *link = xs->sc_link; u_int8_t serr, skey; int error; /* Default sense interpretation. */ serr = sense->error_code & SSD_ERRCODE; if (serr != SSD_ERRCODE_CURRENT && serr != SSD_ERRCODE_DEFERRED) skey = 0xff; /* Invalid value, since key is 4 bit value. */ else skey = sense->flags & SSD_KEY; /* * Interpret the key/asc/ascq information where appropriate. */ error = 0; switch (skey) { case SKEY_NO_SENSE: case SKEY_RECOVERED_ERROR: if (xs->resid == xs->datalen) xs->resid = 0; /* not short read */ break; case SKEY_BLANK_CHECK: case SKEY_EQUAL: break; case SKEY_NOT_READY: if (ISSET(xs->flags, SCSI_IGNORE_NOT_READY)) return 0; error = EIO; if (xs->retries) { switch (ASC_ASCQ(sense)) { case SENSE_NOT_READY_BECOMING_READY: case SENSE_NOT_READY_FORMAT: case SENSE_NOT_READY_REBUILD: case SENSE_NOT_READY_RECALC: case SENSE_NOT_READY_INPROGRESS: case SENSE_NOT_READY_LONGWRITE: case SENSE_NOT_READY_SELFTEST: case SENSE_NOT_READY_INIT_REQUIRED: SC_DEBUG(link, SDEV_DB1, ("not ready (ASC_ASCQ == %#x)\n", ASC_ASCQ(sense))); return scsi_delay(xs, 1); case SENSE_NOMEDIUM: case SENSE_NOMEDIUM_TCLOSED: case SENSE_NOMEDIUM_TOPEN: case SENSE_NOMEDIUM_LOADABLE: case SENSE_NOMEDIUM_AUXMEM: CLR(link->flags, SDEV_MEDIA_LOADED); error = ENOMEDIUM; break; default: break; } } break; case SKEY_MEDIUM_ERROR: switch (ASC_ASCQ(sense)) { case SENSE_NOMEDIUM: case SENSE_NOMEDIUM_TCLOSED: case SENSE_NOMEDIUM_TOPEN: case SENSE_NOMEDIUM_LOADABLE: case SENSE_NOMEDIUM_AUXMEM: CLR(link->flags, SDEV_MEDIA_LOADED); error = ENOMEDIUM; break; case SENSE_BAD_MEDIUM: case SENSE_NR_MEDIUM_UNKNOWN_FORMAT: case SENSE_NR_MEDIUM_INCOMPATIBLE_FORMAT: case SENSE_NW_MEDIUM_UNKNOWN_FORMAT: case SENSE_NW_MEDIUM_INCOMPATIBLE_FORMAT: case SENSE_NF_MEDIUM_INCOMPATIBLE_FORMAT: case SENSE_NW_MEDIUM_AC_MISMATCH: error = EMEDIUMTYPE; break; default: error = EIO; break; } break; case SKEY_ILLEGAL_REQUEST: if (ISSET(xs->flags, SCSI_IGNORE_ILLEGAL_REQUEST)) return 0; if (ASC_ASCQ(sense) == SENSE_MEDIUM_REMOVAL_PREVENTED) return EBUSY; error = EINVAL; break; case SKEY_UNIT_ATTENTION: switch (ASC_ASCQ(sense)) { case SENSE_POWER_RESET_OR_BUS: case SENSE_POWER_ON: case SENSE_BUS_RESET: case SENSE_BUS_DEVICE_RESET: case SENSE_DEVICE_INTERNAL_RESET: case SENSE_TSC_CHANGE_SE: case SENSE_TSC_CHANGE_LVD: case SENSE_IT_NEXUS_LOSS: return scsi_delay(xs, 1); default: break; } if (ISSET(link->flags, SDEV_REMOVABLE)) CLR(link->flags, SDEV_MEDIA_LOADED); if (ISSET(xs->flags, SCSI_IGNORE_MEDIA_CHANGE) || /* XXX Should reupload any transient state. */ !ISSET(link->flags, SDEV_REMOVABLE)) { return scsi_delay(xs, 1); } error = EIO; break; case SKEY_WRITE_PROTECT: error = EROFS; break; case SKEY_ABORTED_COMMAND: error = ERESTART; break; case SKEY_VOLUME_OVERFLOW: error = ENOSPC; break; case SKEY_HARDWARE_ERROR: if (ASC_ASCQ(sense) == SENSE_CARTRIDGE_FAULT) return EMEDIUMTYPE; error = EIO; break; default: error = EIO; break; } #ifndef SCSIDEBUG /* SCSIDEBUG would mean it has already been printed. */ if (skey && !ISSET(xs->flags, SCSI_SILENT)) scsi_print_sense(xs); #endif /* ~SCSIDEBUG */ return error; } /* * Utility routines often used in SCSI stuff */ /* * Print out the scsi_link structure's address info. */ void sc_print_addr(struct scsi_link *link) { struct device *adapter_device = link->bus->sc_dev.dv_parent; printf("%s(%s:%d:%d): ", link->device_softc ? ((struct device *)link->device_softc)->dv_xname : "probe", adapter_device->dv_xname, link->target, link->lun); } static const char *sense_keys[16] = { "No Additional Sense", "Soft Error", "Not Ready", "Media Error", "Hardware Error", "Illegal Request", "Unit Attention", "Write Protected", "Blank Check", "Vendor Unique", "Copy Aborted", "Aborted Command", "Equal Error", "Volume Overflow", "Miscompare Error", "Reserved" }; #ifdef SCSITERSE static __inline void asc2ascii(u_int8_t asc, u_int8_t ascq, char *result, size_t len) { snprintf(result, len, "ASC 0x%02x ASCQ 0x%02x", asc, ascq); } #else static const struct { u_int8_t asc, ascq; char *description; } adesc[] = { /* www.t10.org/lists/asc-num.txt as of 11/15/10. */ { 0x00, 0x00, "No Additional Sense Information" }, { 0x00, 0x01, "Filemark Detected" }, { 0x00, 0x02, "End-Of-Partition/Medium Detected" }, { 0x00, 0x03, "Setmark Detected" }, { 0x00, 0x04, "Beginning-Of-Partition/Medium Detected" }, { 0x00, 0x05, "End-Of-Data Detected" }, { 0x00, 0x06, "I/O Process Terminated" }, { 0x00, 0x11, "Audio Play Operation In Progress" }, { 0x00, 0x12, "Audio Play Operation Paused" }, { 0x00, 0x13, "Audio Play Operation Successfully Completed" }, { 0x00, 0x14, "Audio Play Operation Stopped Due to Error" }, { 0x00, 0x15, "No Current Audio Status To Return" }, { 0x00, 0x16, "Operation In Progress" }, { 0x00, 0x17, "Cleaning Requested" }, { 0x00, 0x18, "Erase Operation In Progress" }, { 0x00, 0x19, "Locate Operation In Progress" }, { 0x00, 0x1A, "Rewind Operation In Progress" }, { 0x00, 0x1B, "Set Capacity Operation In Progress" }, { 0x00, 0x1C, "Verify Operation In Progress" }, { 0x01, 0x00, "No Index/Sector Signal" }, { 0x02, 0x00, "No Seek Complete" }, { 0x03, 0x00, "Peripheral Device Write Fault" }, { 0x03, 0x01, "No Write Current" }, { 0x03, 0x02, "Excessive Write Errors" }, { 0x04, 0x00, "Logical Unit Not Ready, Cause Not Reportable" }, { 0x04, 0x01, "Logical Unit Is in Process Of Becoming Ready" }, { 0x04, 0x02, "Logical Unit Not Ready, Initialization Command Required" }, { 0x04, 0x03, "Logical Unit Not Ready, Manual Intervention Required" }, { 0x04, 0x04, "Logical Unit Not Ready, Format In Progress" }, { 0x04, 0x05, "Logical Unit Not Ready, Rebuild In Progress" }, { 0x04, 0x06, "Logical Unit Not Ready, Recalculation In Progress" }, { 0x04, 0x07, "Logical Unit Not Ready, Operation In Progress" }, { 0x04, 0x08, "Logical Unit Not Ready, Long Write In Progress" }, { 0x04, 0x09, "Logical Unit Not Ready, Self-Test In Progress" }, { 0x04, 0x0A, "Logical Unit Not Accessible, Asymmetric Access State Transition" }, { 0x04, 0x0B, "Logical Unit Not Accessible, Target Port In Standby State" }, { 0x04, 0x0C, "Logical Unit Not Accessible, Target Port In Unavailable State" }, { 0x04, 0x0D, "Logical Unit Not Ready, Structure Check Required" }, { 0x04, 0x10, "Logical Unit Not Ready, Auxiliary Memory Not Accessible" }, { 0x04, 0x11, "Logical Unit Not Ready, Notify (Enable Spinup) Required" }, { 0x04, 0x12, "Logical Unit Not Ready, Offline" }, { 0x04, 0x13, "Logical Unit Not Ready, SA Creation In Progress" }, { 0x04, 0x14, "Logical Unit Not Ready, Space Allocation In Progress" }, { 0x04, 0x15, "Logical Unit Not Ready, Robotics Disabled" }, { 0x04, 0x16, "Logical Unit Not Ready, Configuration Required" }, { 0x04, 0x17, "Logical Unit Not Ready, Calibration Required" }, { 0x04, 0x18, "Logical Unit Not Ready, A Door Is Open" }, { 0x04, 0x19, "Logical Unit Not Ready, Operating In Sequential Mode" }, { 0x04, 0x1A, "Logical Unit Not Ready, Start Stop Unit Command In Progress" }, { 0x05, 0x00, "Logical Unit Does Not Respond To Selection" }, { 0x06, 0x00, "No Reference Position Found" }, { 0x07, 0x00, "Multiple Peripheral Devices Selected" }, { 0x08, 0x00, "Logical Unit Communication Failure" }, { 0x08, 0x01, "Logical Unit Communication Timeout" }, { 0x08, 0x02, "Logical Unit Communication Parity Error" }, { 0x08, 0x03, "Logical Unit Communication CRC Error (ULTRA-DMA/32)" }, { 0x08, 0x04, "Unreachable Copy Target" }, { 0x09, 0x00, "Track Following Error" }, { 0x09, 0x01, "Tracking Servo Failure" }, { 0x09, 0x02, "Focus Servo Failure" }, { 0x09, 0x03, "Spindle Servo Failure" }, { 0x09, 0x04, "Head Select Fault" }, { 0x0A, 0x00, "Error Log Overflow" }, { 0x0B, 0x00, "Warning" }, { 0x0B, 0x01, "Warning - Specified Temperature Exceeded" }, { 0x0B, 0x02, "Warning - Enclosure Degraded" }, { 0x0B, 0x03, "Warning - Background Self-Test Failed" }, { 0x0B, 0x04, "Warning - Background Pre-Scan Detected Medium Error" }, { 0x0B, 0x05, "Warning - Background Medium Scan Detected Medium Error" }, { 0x0B, 0x06, "Warning - Non-Volatile Cache Now Volatile" }, { 0x0B, 0x07, "Warning - Degraded Power To Non-Volatile Cache" }, { 0x0B, 0x08, "Warning - Power Loss Expected" }, { 0x0C, 0x00, "Write Error" }, { 0x0C, 0x01, "Write Error Recovered with Auto Reallocation" }, { 0x0C, 0x02, "Write Error - Auto Reallocate Failed" }, { 0x0C, 0x03, "Write Error - Recommend Reassignment" }, { 0x0C, 0x04, "Compression Check Miscompare Error" }, { 0x0C, 0x05, "Data Expansion Occurred During Compression" }, { 0x0C, 0x06, "Block Not Compressible" }, { 0x0C, 0x07, "Write Error - Recovery Needed" }, { 0x0C, 0x08, "Write Error - Recovery Failed" }, { 0x0C, 0x09, "Write Error - Loss Of Streaming" }, { 0x0C, 0x0A, "Write Error - Padding Blocks Added" }, { 0x0C, 0x0B, "Auxiliary Memory Write Error" }, { 0x0C, 0x0C, "Write Error - Unexpected Unsolicited Data" }, { 0x0C, 0x0D, "Write Error - Not Enough Unsolicited Data" }, { 0x0C, 0x0F, "Defects In Error Window" }, { 0x0D, 0x00, "Error Detected By Third Party Temporary Initiator" }, { 0x0D, 0x01, "Third Party Device Failure" }, { 0x0D, 0x02, "Copy Target Device Not Reachable" }, { 0x0D, 0x03, "Incorrect Copy Target Device Type" }, { 0x0D, 0x04, "Copy Target Device Data Underrun" }, { 0x0D, 0x05, "Copy Target Device Data Overrun" }, { 0x0E, 0x00, "Invalid Information Unit" }, { 0x0E, 0x01, "Information Unit Too Short" }, { 0x0E, 0x02, "Information Unit Too Long" }, { 0x10, 0x00, "ID CRC Or ECC Error" }, { 0x10, 0x01, "Logical Block Guard Check Failed" }, { 0x10, 0x02, "Logical Block Application Tag Check Failed" }, { 0x10, 0x03, "Logical Block Reference Tag Check Failed" }, { 0x10, 0x04, "Logical Block Protection Error On Recover Buffered Data" }, { 0x10, 0x05, "Logical Block Protection Method Error" }, { 0x11, 0x00, "Unrecovered Read Error" }, { 0x11, 0x01, "Read Retries Exhausted" }, { 0x11, 0x02, "Error Too Long To Correct" }, { 0x11, 0x03, "Multiple Read Errors" }, { 0x11, 0x04, "Unrecovered Read Error - Auto Reallocate Failed" }, { 0x11, 0x05, "L-EC Uncorrectable Error" }, { 0x11, 0x06, "CIRC Unrecovered Error" }, { 0x11, 0x07, "Data Resynchronization Error" }, { 0x11, 0x08, "Incomplete Block Read" }, { 0x11, 0x09, "No Gap Found" }, { 0x11, 0x0A, "Miscorrected Error" }, { 0x11, 0x0B, "Uncorrected Read Error - Recommend Reassignment" }, { 0x11, 0x0C, "Uncorrected Read Error - Recommend Rewrite The Data" }, { 0x11, 0x0D, "De-Compression CRC Error" }, { 0x11, 0x0E, "Cannot Decompress Using Declared Algorithm" }, { 0x11, 0x0F, "Error Reading UPC/EAN Number" }, { 0x11, 0x10, "Error Reading ISRC Number" }, { 0x11, 0x11, "Read Error - Loss Of Streaming" }, { 0x11, 0x12, "Auxiliary Memory Read Error" }, { 0x11, 0x13, "Read Error - Failed Retransmission Request" }, { 0x11, 0x14, "Read Error - LBA Marked Bad By Application Client" }, { 0x12, 0x00, "Address Mark Not Found for ID Field" }, { 0x13, 0x00, "Address Mark Not Found for Data Field" }, { 0x14, 0x00, "Recorded Entity Not Found" }, { 0x14, 0x01, "Record Not Found" }, { 0x14, 0x02, "Filemark or Setmark Not Found" }, { 0x14, 0x03, "End-Of-Data Not Found" }, { 0x14, 0x04, "Block Sequence Error" }, { 0x14, 0x05, "Record Not Found - Recommend Reassignment" }, { 0x14, 0x06, "Record Not Found - Data Auto-Reallocated" }, { 0x14, 0x07, "Locate Operation Failure" }, { 0x15, 0x00, "Random Positioning Error" }, { 0x15, 0x01, "Mechanical Positioning Error" }, { 0x15, 0x02, "Positioning Error Detected By Read of Medium" }, { 0x16, 0x00, "Data Synchronization Mark Error" }, { 0x16, 0x01, "Data Sync Error - Data Rewritten" }, { 0x16, 0x02, "Data Sync Error - Recommend Rewrite" }, { 0x16, 0x03, "Data Sync Error - Data Auto-Reallocated" }, { 0x16, 0x04, "Data Sync Error - Recommend Reassignment" }, { 0x17, 0x00, "Recovered Data With No Error Correction Applied" }, { 0x17, 0x01, "Recovered Data With Retries" }, { 0x17, 0x02, "Recovered Data With Positive Head Offset" }, { 0x17, 0x03, "Recovered Data With Negative Head Offset" }, { 0x17, 0x04, "Recovered Data With Retries and/or CIRC Applied" }, { 0x17, 0x05, "Recovered Data Using Previous Sector ID" }, { 0x17, 0x06, "Recovered Data Without ECC - Data Auto-Reallocated" }, { 0x17, 0x07, "Recovered Data Without ECC - Recommend Reassignment" }, { 0x17, 0x08, "Recovered Data Without ECC - Recommend Rewrite" }, { 0x17, 0x09, "Recovered Data Without ECC - Data Rewritten" }, { 0x18, 0x00, "Recovered Data With Error Correction Applied" }, { 0x18, 0x01, "Recovered Data With Error Correction & Retries Applied" }, { 0x18, 0x02, "Recovered Data - Data Auto-Reallocated" }, { 0x18, 0x03, "Recovered Data With CIRC" }, { 0x18, 0x04, "Recovered Data With L-EC" }, { 0x18, 0x05, "Recovered Data - Recommend Reassignment" }, { 0x18, 0x06, "Recovered Data - Recommend Rewrite" }, { 0x18, 0x07, "Recovered Data With ECC - Data Rewritten" }, { 0x18, 0x08, "Recovered Data With Linking" }, { 0x19, 0x00, "Defect List Error" }, { 0x19, 0x01, "Defect List Not Available" }, { 0x19, 0x02, "Defect List Error in Primary List" }, { 0x19, 0x03, "Defect List Error in Grown List" }, { 0x1A, 0x00, "Parameter List Length Error" }, { 0x1B, 0x00, "Synchronous Data Transfer Error" }, { 0x1C, 0x00, "Defect List Not Found" }, { 0x1C, 0x01, "Primary Defect List Not Found" }, { 0x1C, 0x02, "Grown Defect List Not Found" }, { 0x1D, 0x00, "Miscompare During Verify Operation" }, { 0x1D, 0x01, "Miscompare Verify Of Unmapped Lba" }, { 0x1E, 0x00, "Recovered ID with ECC" }, { 0x1F, 0x00, "Partial Defect List Transfer" }, { 0x20, 0x00, "Invalid Command Operation Code" }, { 0x20, 0x01, "Access Denied - Initiator Pending-Enrolled" }, { 0x20, 0x02, "Access Denied - No Access rights" }, { 0x20, 0x03, "Access Denied - Invalid Mgmt ID Key" }, { 0x20, 0x04, "Illegal Command While In Write Capable State" }, { 0x20, 0x05, "Obsolete" }, { 0x20, 0x06, "Illegal Command While In Explicit Address Mode" }, { 0x20, 0x07, "Illegal Command While In Implicit Address Mode" }, { 0x20, 0x08, "Access Denied - Enrollment Conflict" }, { 0x20, 0x09, "Access Denied - Invalid LU Identifier" }, { 0x20, 0x0A, "Access Denied - Invalid Proxy Token" }, { 0x20, 0x0B, "Access Denied - ACL LUN Conflict" }, { 0x20, 0x0C, "Illegal Command When Not In Append-Only Mode" }, { 0x21, 0x00, "Logical Block Address Out of Range" }, { 0x21, 0x01, "Invalid Element Address" }, { 0x21, 0x02, "Invalid Address For Write" }, { 0x21, 0x03, "Invalid Write Crossing Layer Jump" }, { 0x22, 0x00, "Illegal Function (Should 20 00, 24 00, or 26 00)" }, { 0x24, 0x00, "Illegal Field in CDB" }, { 0x24, 0x01, "CDB Decryption Error" }, { 0x24, 0x02, "Obsolete" }, { 0x24, 0x03, "Obsolete" }, { 0x24, 0x04, "Security Audit Value Frozen" }, { 0x24, 0x05, "Security Working Key Frozen" }, { 0x24, 0x06, "Nonce Not Unique" }, { 0x24, 0x07, "Nonce Timestamp Out Of Range" }, { 0x24, 0x08, "Invalid XCDB" }, { 0x25, 0x00, "Logical Unit Not Supported" }, { 0x26, 0x00, "Invalid Field In Parameter List" }, { 0x26, 0x01, "Parameter Not Supported" }, { 0x26, 0x02, "Parameter Value Invalid" }, { 0x26, 0x03, "Threshold Parameters Not Supported" }, { 0x26, 0x04, "Invalid Release Of Persistent Reservation" }, { 0x26, 0x05, "Data Decryption Error" }, { 0x26, 0x06, "Too Many Target Descriptors" }, { 0x26, 0x07, "Unsupported Target Descriptor Type Code" }, { 0x26, 0x08, "Too Many Segment Descriptors" }, { 0x26, 0x09, "Unsupported Segment Descriptor Type Code" }, { 0x26, 0x0A, "Unexpected Inexact Segment" }, { 0x26, 0x0B, "Inline Data Length Exceeded" }, { 0x26, 0x0C, "Invalid Operation For Copy Source Or Destination" }, { 0x26, 0x0D, "Copy Segment Granularity Violation" }, { 0x26, 0x0E, "Invalid Parameter While Port Is Enabled" }, { 0x26, 0x0F, "Invalid Data-Out Buffer Integrity Check Value" }, { 0x26, 0x10, "Data Decryption Key Fail Limit Reached" }, { 0x26, 0x11, "Incomplete Key-Associated Data Set" }, { 0x26, 0x12, "Vendor Specific Key Reference Not Found" }, { 0x27, 0x00, "Write Protected" }, { 0x27, 0x01, "Hardware Write Protected" }, { 0x27, 0x02, "Logical Unit Software Write Protected" }, { 0x27, 0x03, "Associated Write Protect" }, { 0x27, 0x04, "Persistent Write Protect" }, { 0x27, 0x05, "Permanent Write Protect" }, { 0x27, 0x06, "Conditional Write Protect" }, { 0x27, 0x07, "Space Allocation Failed Write Protect" }, { 0x28, 0x00, "Not Ready To Ready Transition (Medium May Have Changed)" }, { 0x28, 0x01, "Import Or Export Element Accessed" }, { 0x28, 0x02, "Format-Layer May Have Changed" }, { 0x28, 0x03, "Import/Export Element Accessed, Medium Changed" }, { 0x29, 0x00, "Power On, Reset, or Bus Device Reset Occurred" }, { 0x29, 0x01, "Power On Occurred" }, { 0x29, 0x02, "SCSI Bus Reset Occurred" }, { 0x29, 0x03, "Bus Device Reset Function Occurred" }, { 0x29, 0x04, "Device Internal Reset" }, { 0x29, 0x05, "Transceiver Mode Changed to Single Ended" }, { 0x29, 0x06, "Transceiver Mode Changed to LVD" }, { 0x29, 0x07, "I_T Nexus Loss Occurred" }, { 0x2A, 0x00, "Parameters Changed" }, { 0x2A, 0x01, "Mode Parameters Changed" }, { 0x2A, 0x02, "Log Parameters Changed" }, { 0x2A, 0x03, "Reservations Preempted" }, { 0x2A, 0x04, "Reservations Released" }, { 0x2A, 0x05, "Registrations Preempted" }, { 0x2A, 0x06, "Asymmetric Access State Changed" }, { 0x2A, 0x07, "Implicit Asymmetric Access State Transition Failed" }, { 0x2A, 0x08, "Priority Changed" }, { 0x2A, 0x09, "Capacity Data Has Changed" }, { 0x2A, 0x0A, "Error History I_T Nexus Cleared" }, { 0x2A, 0x0B, "Error History Snapshot Released" }, { 0x2A, 0x0C, "Error Recovery Attributes Have Changed" }, { 0x2A, 0x0D, "Data Encryption Capabilities Changed" }, { 0x2A, 0x10, "Timestamp Changed" }, { 0x2A, 0x11, "Data Encryption Parameters Changed By Another I_T Nexus" }, { 0x2A, 0x12, "Data Encryption Parameters Changed By Vendor Specific Event" }, { 0x2A, 0x13, "Data Encryption Key Instance Counter Has Changed" }, { 0x2A, 0x14, "SA Creation Capabilities Data Has Changed" }, { 0x2B, 0x00, "Copy Cannot Execute Since Host Cannot Disconnect" }, { 0x2C, 0x00, "Command Sequence Error" }, { 0x2C, 0x01, "Too Many Windows Specified" }, { 0x2C, 0x02, "Invalid Combination of Windows Specified" }, { 0x2C, 0x03, "Current Program Area Is Not Empty" }, { 0x2C, 0x04, "Current Program Area Is Empty" }, { 0x2C, 0x05, "Illegal Power Condition Request" }, { 0x2C, 0x06, "Persistent Prevent Conflict" }, { 0x2C, 0x07, "Previous Busy Status" }, { 0x2C, 0x08, "Previous Task Set Full Status" }, { 0x2C, 0x09, "Previous Reservation Conflict Status" }, { 0x2C, 0x0A, "Partition Or Collection Contains User Objects" }, { 0x2C, 0x0B, "Not Reserved" }, { 0x2C, 0x0C, "ORWrite Generation Does Not Match" }, { 0x2D, 0x00, "Overwrite Error On Update In Place" }, { 0x2E, 0x00, "Insufficient Time For Operation" }, { 0x2F, 0x00, "Commands Cleared By Another Initiator" }, { 0x2F, 0x01, "Commands Cleared By Power Loss Notification" }, { 0x2F, 0x02, "Commands Cleared By Device Server" }, { 0x30, 0x00, "Incompatible Medium Installed" }, { 0x30, 0x01, "Cannot Read Medium - Unknown Format" }, { 0x30, 0x02, "Cannot Read Medium - Incompatible Format" }, { 0x30, 0x03, "Cleaning Cartridge Installed" }, { 0x30, 0x04, "Cannot Write Medium - Unknown Format" }, { 0x30, 0x05, "Cannot Write Medium - Incompatible Format" }, { 0x30, 0x06, "Cannot Format Medium - Incompatible Medium" }, { 0x30, 0x07, "Cleaning Failure" }, { 0x30, 0x08, "Cannot Write - Application Code Mismatch" }, { 0x30, 0x09, "Current Session Not Fixated For Append" }, { 0x30, 0x0A, "Cleaning Request Rejected" }, { 0x30, 0x10, "Medium Not Formatted" }, { 0x30, 0x11, "Incompatible Volume Type" }, { 0x30, 0x12, "Incompatible Volume Qualifier" }, { 0x30, 0x13, "Cleaning Volume Expired" }, { 0x31, 0x00, "Medium Format Corrupted" }, { 0x31, 0x01, "Format Command Failed" }, { 0x31, 0x02, "Zoned Formatting Failed Due To Spare Linking" }, { 0x32, 0x00, "No Defect Spare Location Available" }, { 0x32, 0x01, "Defect List Update Failure" }, { 0x33, 0x00, "Tape Length Error" }, { 0x34, 0x00, "Enclosure Failure" }, { 0x35, 0x00, "Enclosure Services Failure" }, { 0x35, 0x01, "Unsupported Enclosure Function" }, { 0x35, 0x02, "Enclosure Services Unavailable" }, { 0x35, 0x03, "Enclosure Services Transfer Failure" }, { 0x35, 0x04, "Enclosure Services Transfer Refused" }, { 0x36, 0x00, "Ribbon, Ink, or Toner Failure" }, { 0x37, 0x00, "Rounded Parameter" }, { 0x38, 0x00, "Event Status Notification" }, { 0x38, 0x02, "ESN - Power Management Class Event" }, { 0x38, 0x04, "ESN - Media Class Event" }, { 0x38, 0x06, "ESN - Device Busy Class Event" }, { 0x39, 0x00, "Saving Parameters Not Supported" }, { 0x3A, 0x00, "Medium Not Present" }, { 0x3A, 0x01, "Medium Not Present - Tray Closed" }, { 0x3A, 0x02, "Medium Not Present - Tray Open" }, { 0x3A, 0x03, "Medium Not Present - Loadable" }, { 0x3A, 0x04, "Medium Not Present - Medium Auxiliary Memory Accessible" }, { 0x3B, 0x00, "Sequential Positioning Error" }, { 0x3B, 0x01, "Tape Position Error At Beginning-of-Medium" }, { 0x3B, 0x02, "Tape Position Error At End-of-Medium" }, { 0x3B, 0x03, "Tape or Electronic Vertical Forms Unit Not Ready" }, { 0x3B, 0x04, "Slew Failure" }, { 0x3B, 0x05, "Paper Jam" }, { 0x3B, 0x06, "Failed To Sense Top-Of-Form" }, { 0x3B, 0x07, "Failed To Sense Bottom-Of-Form" }, { 0x3B, 0x08, "Reposition Error" }, { 0x3B, 0x09, "Read Past End Of Medium" }, { 0x3B, 0x0A, "Read Past Beginning Of Medium" }, { 0x3B, 0x0B, "Position Past End Of Medium" }, { 0x3B, 0x0C, "Position Past Beginning Of Medium" }, { 0x3B, 0x0D, "Medium Destination Element Full" }, { 0x3B, 0x0E, "Medium Source Element Empty" }, { 0x3B, 0x0F, "End Of Medium Reached" }, { 0x3B, 0x11, "Medium Magazine Not Accessible" }, { 0x3B, 0x12, "Medium Magazine Removed" }, { 0x3B, 0x13, "Medium Magazine Inserted" }, { 0x3B, 0x14, "Medium Magazine Locked" }, { 0x3B, 0x15, "Medium Magazine Unlocked" }, { 0x3B, 0x16, "Mechanical Positioning Or Changer Error" }, { 0x3B, 0x17, "Read Past End Of User Object" }, { 0x3B, 0x18, "Element Disabled" }, { 0x3B, 0x19, "Element Enabled" }, { 0x3B, 0x1A, "Data Transfer Device Removed" }, { 0x3B, 0x1B, "Data Transfer Device Inserted" }, { 0x3D, 0x00, "Invalid Bits In IDENTIFY Message" }, { 0x3E, 0x00, "Logical Unit Has Not Self-Configured Yet" }, { 0x3E, 0x01, "Logical Unit Failure" }, { 0x3E, 0x02, "Timeout On Logical Unit" }, { 0x3E, 0x03, "Logical Unit Failed Self-Test" }, { 0x3E, 0x04, "Logical Unit Unable To Update Self-Test Log" }, { 0x3F, 0x00, "Target Operating Conditions Have Changed" }, { 0x3F, 0x01, "Microcode Has Changed" }, { 0x3F, 0x02, "Changed Operating Definition" }, { 0x3F, 0x03, "INQUIRY Data Has Changed" }, { 0x3F, 0x04, "component Device Attached" }, { 0x3F, 0x05, "Device Identifier Changed" }, { 0x3F, 0x06, "Redundancy Group Created Or Modified" }, { 0x3F, 0x07, "Redundancy Group Deleted" }, { 0x3F, 0x08, "Spare Created Or Modified" }, { 0x3F, 0x09, "Spare Deleted" }, { 0x3F, 0x0A, "Volume Set Created Or Modified" }, { 0x3F, 0x0B, "Volume Set Deleted" }, { 0x3F, 0x0C, "Volume Set Deassigned" }, { 0x3F, 0x0D, "Volume Set Reassigned" }, { 0x3F, 0x0E, "Reported LUNs Data Has Changed" }, { 0x3F, 0x0F, "Echo Buffer Overwritten" }, { 0x3F, 0x10, "Medium Loadable" }, { 0x3F, 0x11, "Medium Auxiliary Memory Accessible" }, { 0x3F, 0x12, "iSCSI IP Address Added" }, { 0x3F, 0x13, "iSCSI IP Address Removed" }, { 0x3F, 0x14, "iSCSI IP Address Changed" }, { 0x40, 0x00, "RAM FAILURE (Should Use 40 NN)" }, /* * ASC 0x40 also has an ASCQ range from 0x80 to 0xFF. * 0x40 0xNN DIAGNOSTIC FAILURE ON COMPONENT NN */ { 0x41, 0x00, "Data Path FAILURE (Should Use 40 NN)" }, { 0x42, 0x00, "Power-On or Self-Test FAILURE (Should Use 40 NN)" }, { 0x43, 0x00, "Message Error" }, { 0x44, 0x00, "Internal Target Failure" }, { 0x44, 0x71, "ATA Device Failed Set Features" }, { 0x45, 0x00, "Select Or Reselect Failure" }, { 0x46, 0x00, "Unsuccessful Soft Reset" }, { 0x47, 0x00, "SCSI Parity Error" }, { 0x47, 0x01, "Data Phase CRC Error Detected" }, { 0x47, 0x02, "SCSI Parity Error Detected During ST Data Phase" }, { 0x47, 0x03, "Information Unit iuCRC Error Detected" }, { 0x47, 0x04, "Asynchronous Information Protection Error Detected" }, { 0x47, 0x05, "Protocol Service CRC Error" }, { 0x47, 0x06, "PHY Test Function In Progress" }, { 0x47, 0x7F, "Some Commands Cleared By iSCSI Protocol Event" }, { 0x48, 0x00, "Initiator Detected Error Message Received" }, { 0x49, 0x00, "Invalid Message Error" }, { 0x4A, 0x00, "Command Phase Error" }, { 0x4B, 0x00, "Data Phase Error" }, { 0x4B, 0x01, "Invalid Target Port Transfer Tag Received" }, { 0x4B, 0x02, "Too Much Write Data" }, { 0x4B, 0x03, "ACK/NAK Timeout" }, { 0x4B, 0x04, "NAK Received" }, { 0x4B, 0x05, "Data Offset Error" }, { 0x4B, 0x06, "Initiator Response Timeout" }, { 0x4B, 0x07, "Connection Lost" }, { 0x4C, 0x00, "Logical Unit Failed Self-Configuration" }, /* * ASC 0x4D has an ASCQ range from 0x00 to 0xFF. * 0x4D 0xNN TAGGED OVERLAPPED COMMANDS (NN = TASK TAG) */ { 0x4E, 0x00, "Overlapped Commands Attempted" }, { 0x50, 0x00, "Write Append Error" }, { 0x50, 0x01, "Write Append Position Error" }, { 0x50, 0x02, "Position Error Related To Timing" }, { 0x51, 0x00, "Erase Failure" }, { 0x51, 0x01, "Erase Failure - Incomplete Erase Operation Detected" }, { 0x52, 0x00, "Cartridge Fault" }, { 0x53, 0x00, "Media Load or Eject Failed" }, { 0x53, 0x01, "Unload Tape Failure" }, { 0x53, 0x02, "Medium Removal Prevented" }, { 0x53, 0x03, "Medium Removal Prevented By Data Transfer Element" }, { 0x53, 0x04, "Medium Thread Or Unthread Failure" }, { 0x53, 0x05, "Volume Identifier Invalid" }, { 0x53, 0x06, "Volume Identifier Missing" }, { 0x53, 0x07, "Duplicate Volume Identifier" }, { 0x53, 0x08, "Element Status Unknown" }, { 0x54, 0x00, "SCSI To Host System Interface Failure" }, { 0x55, 0x00, "System Resource Failure" }, { 0x55, 0x01, "System Buffer Full" }, { 0x55, 0x02, "Insufficient Reservation Resources" }, { 0x55, 0x03, "Insufficient Resources" }, { 0x55, 0x04, "Insufficient Registration Resources" }, { 0x55, 0x05, "Insufficient Access Control Resources" }, { 0x55, 0x06, "Auxiliary Memory Out Of Space" }, { 0x55, 0x07, "Quota Error" }, { 0x55, 0x08, "Maximum Number Of Supplemental Decryption Keys Exceeded" }, { 0x55, 0x09, "Medium Auxiliary Memory Not Accessible" }, { 0x55, 0x0A, "Data Currently Unavailable" }, { 0x55, 0x0B, "Insufficient Power For Operation" }, { 0x57, 0x00, "Unable To Recover Table-Of-Contents" }, { 0x58, 0x00, "Generation Does Not Exist" }, { 0x59, 0x00, "Updated Block Read" }, { 0x5A, 0x00, "Operator Request or State Change Input" }, { 0x5A, 0x01, "Operator Medium Removal Requested" }, { 0x5A, 0x02, "Operator Selected Write Protect" }, { 0x5A, 0x03, "Operator Selected Write Permit" }, { 0x5B, 0x00, "Log Exception" }, { 0x5B, 0x01, "Threshold Condition Met" }, { 0x5B, 0x02, "Log Counter At Maximum" }, { 0x5B, 0x03, "Log List Codes Exhausted" }, { 0x5C, 0x00, "RPL Status Change" }, { 0x5C, 0x01, "Spindles Synchronized" }, { 0x5C, 0x02, "Spindles Not Synchronized" }, { 0x5D, 0x00, "Failure Prediction Threshold Exceeded" }, { 0x5D, 0x01, "Media Failure Prediction Threshold Exceeded" }, { 0x5D, 0x02, "Logical Unit Failure Prediction Threshold Exceeded" }, { 0x5D, 0x03, "Spare Area Exhaustion Prediction Threshold Exceeded" }, { 0x5D, 0x10, "Hardware Impending Failure General Hard Drive Failure" }, { 0x5D, 0x11, "Hardware Impending Failure Drive Error Rate Too High" }, { 0x5D, 0x12, "Hardware Impending Failure Data Error Rate Too High" }, { 0x5D, 0x13, "Hardware Impending Failure Seek Error Rate Too High" }, { 0x5D, 0x14, "Hardware Impending Failure Too Many Block Reassigns" }, { 0x5D, 0x15, "Hardware Impending Failure Access Times Too High" }, { 0x5D, 0x16, "Hardware Impending Failure Start Unit Times Too High" }, { 0x5D, 0x17, "Hardware Impending Failure Channel Parametrics" }, { 0x5D, 0x18, "Hardware Impending Failure Controller Detected" }, { 0x5D, 0x19, "Hardware Impending Failure Throughput Performance" }, { 0x5D, 0x1A, "Hardware Impending Failure Seek Time Performance" }, { 0x5D, 0x1B, "Hardware Impending Failure Spin-Up Retry Count" }, { 0x5D, 0x1C, "Hardware Impending Failure Drive Calibration Retry Count" }, { 0x5D, 0x20, "Controller Impending Failure General Hard Drive Failure" }, { 0x5D, 0x21, "Controller Impending Failure Drive Error Rate Too High" }, { 0x5D, 0x22, "Controller Impending Failure Data Error Rate Too High" }, { 0x5D, 0x23, "Controller Impending Failure Seek Error Rate Too High" }, { 0x5D, 0x24, "Controller Impending Failure Too Many Block Reassigns" }, { 0x5D, 0x25, "Controller Impending Failure Access Times Too High" }, { 0x5D, 0x26, "Controller Impending Failure Start Unit Times Too High" }, { 0x5D, 0x27, "Controller Impending Failure Channel Parametrics" }, { 0x5D, 0x28, "Controller Impending Failure Controller Detected" }, { 0x5D, 0x29, "Controller Impending Failure Throughput Performance" }, { 0x5D, 0x2A, "Controller Impending Failure Seek Time Performance" }, { 0x5D, 0x2B, "Controller Impending Failure Spin-Up Retry Count" }, { 0x5D, 0x2C, "Controller Impending Failure Drive Calibration Retry Count" }, { 0x5D, 0x30, "Data Channel Impending Failure General Hard Drive Failure" }, { 0x5D, 0x31, "Data Channel Impending Failure Drive Error Rate Too High" }, { 0x5D, 0x32, "Data Channel Impending Failure Data Error Rate Too High" }, { 0x5D, 0x33, "Data Channel Impending Failure Seek Error Rate Too High" }, { 0x5D, 0x34, "Data Channel Impending Failure Too Many Block Reassigns" }, { 0x5D, 0x35, "Data Channel Impending Failure Access Times Too High" }, { 0x5D, 0x36, "Data Channel Impending Failure Start Unit Times Too High" }, { 0x5D, 0x37, "Data Channel Impending Failure Channel Parametrics" }, { 0x5D, 0x38, "Data Channel Impending Failure Controller Detected" }, { 0x5D, 0x39, "Data Channel Impending Failure Throughput Performance" }, { 0x5D, 0x3A, "Data Channel Impending Failure Seek Time Performance" }, { 0x5D, 0x3B, "Data Channel Impending Failure Spin-Up Retry Count" }, { 0x5D, 0x3C, "Data Channel Impending Failure Drive Calibration Retry Count" }, { 0x5D, 0x40, "Servo Impending Failure General Hard Drive Failure" }, { 0x5D, 0x41, "Servo Impending Failure Drive Error Rate Too High" }, { 0x5D, 0x42, "Servo Impending Failure Data Error Rate Too High" }, { 0x5D, 0x43, "Servo Impending Failure Seek Error Rate Too High" }, { 0x5D, 0x44, "Servo Impending Failure Too Many Block Reassigns" }, { 0x5D, 0x45, "Servo Impending Failure Access Times Too High" }, { 0x5D, 0x46, "Servo Impending Failure Start Unit Times Too High" }, { 0x5D, 0x47, "Servo Impending Failure Channel Parametrics" }, { 0x5D, 0x48, "Servo Impending Failure Controller Detected" }, { 0x5D, 0x49, "Servo Impending Failure Throughput Performance" }, { 0x5D, 0x4A, "Servo Impending Failure Seek Time Performance" }, { 0x5D, 0x4B, "Servo Impending Failure Spin-Up Retry Count" }, { 0x5D, 0x4C, "Servo Impending Failure Drive Calibration Retry Count" }, { 0x5D, 0x50, "Spindle Impending Failure General Hard Drive Failure" }, { 0x5D, 0x51, "Spindle Impending Failure Drive Error Rate Too High" }, { 0x5D, 0x52, "Spindle Impending Failure Data Error Rate Too High" }, { 0x5D, 0x53, "Spindle Impending Failure Seek Error Rate Too High" }, { 0x5D, 0x54, "Spindle Impending Failure Too Many Block Reassigns" }, { 0x5D, 0x55, "Spindle Impending Failure Access Times Too High" }, { 0x5D, 0x56, "Spindle Impending Failure Start Unit Times Too High" }, { 0x5D, 0x57, "Spindle Impending Failure Channel Parametrics" }, { 0x5D, 0x58, "Spindle Impending Failure Controller Detected" }, { 0x5D, 0x59, "Spindle Impending Failure Throughput Performance" }, { 0x5D, 0x5A, "Spindle Impending Failure Seek Time Performance" }, { 0x5D, 0x5B, "Spindle Impending Failure Spin-Up Retry Count" }, { 0x5D, 0x5C, "Spindle Impending Failure Drive Calibration Retry Count" }, { 0x5D, 0x60, "Firmware Impending Failure General Hard Drive Failure" }, { 0x5D, 0x61, "Firmware Impending Failure Drive Error Rate Too High" }, { 0x5D, 0x62, "Firmware Impending Failure Data Error Rate Too High" }, { 0x5D, 0x63, "Firmware Impending Failure Seek Error Rate Too High" }, { 0x5D, 0x64, "Firmware Impending Failure Too Many Block Reassigns" }, { 0x5D, 0x65, "Firmware Impending Failure Access Times Too High" }, { 0x5D, 0x66, "Firmware Impending Failure Start Unit Times Too High" }, { 0x5D, 0x67, "Firmware Impending Failure Channel Parametrics" }, { 0x5D, 0x68, "Firmware Impending Failure Controller Detected" }, { 0x5D, 0x69, "Firmware Impending Failure Throughput Performance" }, { 0x5D, 0x6A, "Firmware Impending Failure Seek Time Performance" }, { 0x5D, 0x6B, "Firmware Impending Failure Spin-Up Retry Count" }, { 0x5D, 0x6C, "Firmware Impending Failure Drive Calibration Retry Count" }, { 0x5D, 0xFF, "Failure Prediction Threshold Exceeded (false)" }, { 0x5E, 0x00, "Low Power Condition On" }, { 0x5E, 0x01, "Idle Condition Activated By Timer" }, { 0x5E, 0x02, "Standby Condition Activated By Timer" }, { 0x5E, 0x03, "Idle Condition Activated By Command" }, { 0x5E, 0x04, "Standby Condition Activated By Command" }, { 0x5E, 0x05, "IDLE_B Condition Activated By Timer" }, { 0x5E, 0x06, "IDLE_B Condition Activated By Command" }, { 0x5E, 0x07, "IDLE_C Condition Activated By Timer" }, { 0x5E, 0x08, "IDLE_C Condition Activated By Command" }, { 0x5E, 0x09, "STANDBY_Y Condition Activated By Timer" }, { 0x5E, 0x0A, "STANDBY_Y Condition Activated By Command" }, { 0x5E, 0x41, "Power State Change To Active" }, { 0x5E, 0x42, "Power State Change To Idle" }, { 0x5E, 0x43, "Power State Change To Standby" }, { 0x5E, 0x45, "Power State Change To Sleep" }, { 0x5E, 0x47, "Power State Change To Device Control" }, { 0x60, 0x00, "Lamp Failure" }, { 0x61, 0x00, "Video Acquisition Error" }, { 0x61, 0x01, "Unable To Acquire Video" }, { 0x61, 0x02, "Out Of Focus" }, { 0x62, 0x00, "Scan Head Positioning Error" }, { 0x63, 0x00, "End Of User Area Encountered On This Track" }, { 0x63, 0x01, "Packet Does Not Fit In Available Space" }, { 0x64, 0x00, "Illegal Mode For This Track" }, { 0x64, 0x01, "Invalid Packet Size" }, { 0x65, 0x00, "Voltage Fault" }, { 0x66, 0x00, "Automatic Document Feeder Cover Up" }, { 0x66, 0x01, "Automatic Document Feeder Lift Up" }, { 0x66, 0x02, "Document Jam In Automatic Document Feeder" }, { 0x66, 0x03, "Document Miss Feed Automatic In Document Feeder" }, { 0x67, 0x00, "Configuration Failure" }, { 0x67, 0x01, "Configuration Of Incapable Logical Units Failed" }, { 0x67, 0x02, "Add Logical Unit Failed" }, { 0x67, 0x03, "Modification Of Logical Unit Failed" }, { 0x67, 0x04, "Exchange Of Logical Unit Failed" }, { 0x67, 0x05, "Remove Of Logical Unit Failed" }, { 0x67, 0x06, "Attachment Of Logical Unit Failed" }, { 0x67, 0x07, "Creation Of Logical Unit Failed" }, { 0x67, 0x08, "Assign Failure Occurred" }, { 0x67, 0x09, "Multiply Assigned Logical Unit" }, { 0x67, 0x0A, "Set Target Port Groups Command Failed" }, { 0x67, 0x0B, "ATA Device Feature Not Enabled" }, { 0x68, 0x00, "Logical Unit Not Configured" }, { 0x69, 0x00, "Data Loss On Logical Unit" }, { 0x69, 0x01, "Multiple Logical Unit Failures" }, { 0x69, 0x02, "Parity/Data Mismatch" }, { 0x6A, 0x00, "Informational, Refer To Log" }, { 0x6B, 0x00, "State Change Has Occurred" }, { 0x6B, 0x01, "Redundancy Level Got Better" }, { 0x6B, 0x02, "Redundancy Level Got Worse" }, { 0x6C, 0x00, "Rebuild Failure Occurred" }, { 0x6D, 0x00, "Recalculate Failure Occurred" }, { 0x6E, 0x00, "Command To Logical Unit Failed" }, { 0x6F, 0x00, "Copy Protection Key Exchange Failure - Authentication Failure" }, { 0x6F, 0x01, "Copy Protection Key Exchange Failure - Key Not Present" }, { 0x6F, 0x02, "Copy Protection Key Exchange Failure - Key Not Established" }, { 0x6F, 0x03, "Read Of Scrambled Sector Without Authentication" }, { 0x6F, 0x04, "Media Region Code Is Mismatched To Logical Unit Region" }, { 0x6F, 0x05, "Drive Region Must Be Permanent/Region Reset Count Error" }, /* * ASC 0x70 has an ASCQ range from 0x00 to 0xFF. * 0x70 0xNN DECOMPRESSION EXCEPTION SHORT ALGORITHM ID Of NN */ { 0x71, 0x00, "Decompression Exception Long Algorithm ID" }, { 0x72, 0x00, "Session Fixation Error" }, { 0x72, 0x01, "Session Fixation Error Writing Lead-In" }, { 0x72, 0x02, "Session Fixation Error Writing Lead-Out" }, { 0x72, 0x03, "Session Fixation Error - Incomplete Track In Session" }, { 0x72, 0x04, "Empty Or Partially Written Reserved Track" }, { 0x72, 0x05, "No More Track Reservations Allowed" }, { 0x72, 0x06, "RMZ Extension Is Not Allowed" }, { 0x72, 0x07, "No More Test Zone Extensions Are Allowed" }, { 0x73, 0x00, "CD Control Error" }, { 0x73, 0x01, "Power Calibration Area Almost Full" }, { 0x73, 0x02, "Power Calibration Area Is Full" }, { 0x73, 0x03, "Power Calibration Area Error" }, { 0x73, 0x04, "Program Memory Area Update Failure" }, { 0x73, 0x05, "Program Memory Area Is Full" }, { 0x73, 0x06, "RMA/PMA Is Almost Full" }, { 0x73, 0x10, "Current Power Calibration Area Almost Full" }, { 0x73, 0x11, "Current Power Calibration Area Is Full" }, { 0x73, 0x17, "RDZ Is Full" }, { 0x74, 0x00, "Security Error" }, { 0x74, 0x01, "Unable To Decrypt Data" }, { 0x74, 0x02, "Unencrypted Data Encountered While Decrypting" }, { 0x74, 0x03, "Incorrect Data Encryption Key" }, { 0x74, 0x04, "Cryptographic Integrity Validation Failed" }, { 0x74, 0x05, "Error Decrypting Data" }, { 0x74, 0x06, "Unknown Signature Verification Key" }, { 0x74, 0x07, "Encryption Parameters Not Useable" }, { 0x74, 0x08, "Digital Signature Validation Failure" }, { 0x74, 0x09, "Encryption Mode Mismatch On Read" }, { 0x74, 0x0A, "Encrypted Block Not Raw Read Enabled" }, { 0x74, 0x0B, "Incorrect Encryption Parameters" }, { 0x74, 0x0C, "Unable To Decrypt Parameter List" }, { 0x74, 0x0D, "Encryption Algorithm Disabled" }, { 0x74, 0x10, "SA Creation Parameter Value Invalid" }, { 0x74, 0x11, "SA Creation Parameter Value Rejected" }, { 0x74, 0x12, "Invalid SA Usage" }, { 0x74, 0x21, "Data Encryption Configuration Prevented" }, { 0x74, 0x30, "SA Creation Parameter Not Supported" }, { 0x74, 0x40, "Authentication Failed" }, { 0x74, 0x61, "External Data Encryption Key Manager Access Error" }, { 0x74, 0x62, "External Data Encryption Key Manager Error" }, { 0x74, 0x63, "External Data Encryption Key Not Found" }, { 0x74, 0x64, "External Data Encryption Request Not Authorized" }, { 0x74, 0x6E, "External Data Encryption Control Timeout" }, { 0x74, 0x6F, "External Data Encryption Control Error" }, { 0x74, 0x71, "Logical Unit Access Not Authorized" }, { 0x74, 0x79, "Security Conflict In Translated Device" }, { 0x00, 0x00, NULL } }; static __inline void asc2ascii(u_int8_t asc, u_int8_t ascq, char *result, size_t len) { int i; /* Check for a dynamically built description. */ switch (asc) { case 0x40: if (ascq >= 0x80) { snprintf(result, len, "Diagnostic Failure on Component 0x%02x", ascq); return; } break; case 0x4d: snprintf(result, len, "Tagged Overlapped Commands (0x%02x = TASK TAG)", ascq); return; case 0x70: snprintf(result, len, "Decompression Exception Short Algorithm ID OF 0x%02x", ascq); return; default: break; } /* Check for a fixed description. */ for (i = 0; adesc[i].description != NULL; i++) { if (adesc[i].asc == asc && adesc[i].ascq == ascq) { strlcpy(result, adesc[i].description, len); return; } } /* Just print out the ASC and ASCQ values as a description. */ snprintf(result, len, "ASC 0x%02x ASCQ 0x%02x", asc, ascq); } #endif /* SCSITERSE */ void scsi_print_sense(struct scsi_xfer *xs) { struct scsi_sense_data *sense = &xs->sense; char *sbs; int32_t info; u_int8_t serr = sense->error_code & SSD_ERRCODE; sc_print_addr(xs->sc_link); /* XXX For error 0x71, current opcode is not the relevant one. */ printf("%sCheck Condition (error %#x) on opcode 0x%x\n", (serr == SSD_ERRCODE_DEFERRED) ? "DEFERRED " : "", serr, xs->cmd.opcode); if (serr != SSD_ERRCODE_CURRENT && serr != SSD_ERRCODE_DEFERRED) { if (ISSET(sense->error_code, SSD_ERRCODE_VALID)) { struct scsi_sense_data_unextended *usense = (struct scsi_sense_data_unextended *)sense; printf(" AT BLOCK #: %d (decimal)", _3btol(usense->block)); } return; } printf(" SENSE KEY: %s\n", scsi_decode_sense(sense, DECODE_SENSE_KEY)); if (sense->flags & (SSD_FILEMARK | SSD_EOM | SSD_ILI)) { char pad = ' '; printf(" "); if (ISSET(sense->flags, SSD_FILEMARK)) { printf("%c Filemark Detected", pad); pad = ','; } if (ISSET(sense->flags, SSD_EOM)) { printf("%c EOM Detected", pad); pad = ','; } if (ISSET(sense->flags, SSD_ILI)) printf("%c Incorrect Length Indicator Set", pad); printf("\n"); } /* * It is inconvenient to use device type to figure out how to * format the info fields. So print them as 32 bit integers. */ info = _4btol(&sense->info[0]); if (info) printf(" INFO: 0x%x (VALID flag %s)\n", info, ISSET(sense->error_code, SSD_ERRCODE_VALID) ? "on" : "off"); if (sense->extra_len < 4) return; info = _4btol(&sense->cmd_spec_info[0]); if (info) printf(" COMMAND INFO: 0x%x\n", info); sbs = scsi_decode_sense(sense, DECODE_ASC_ASCQ); if (strlen(sbs) > 0) printf(" ASC/ASCQ: %s\n", sbs); if (sense->fru != 0) printf(" FRU CODE: 0x%x\n", sense->fru); sbs = scsi_decode_sense(sense, DECODE_SKSV); if (strlen(sbs) > 0) printf(" SKSV: %s\n", sbs); } char * scsi_decode_sense(struct scsi_sense_data *sense, int flag) { static char rqsbuf[132]; u_int16_t count; u_int8_t skey, spec_1; int len; bzero(rqsbuf, sizeof(rqsbuf)); skey = sense->flags & SSD_KEY; spec_1 = sense->sense_key_spec_1; count = _2btol(&sense->sense_key_spec_2); switch (flag) { case DECODE_SENSE_KEY: strlcpy(rqsbuf, sense_keys[skey], sizeof(rqsbuf)); break; case DECODE_ASC_ASCQ: asc2ascii(sense->add_sense_code, sense->add_sense_code_qual, rqsbuf, sizeof(rqsbuf)); break; case DECODE_SKSV: if (sense->extra_len < 9 || !ISSET(spec_1, SSD_SCS_VALID)) break; switch (skey) { case SKEY_ILLEGAL_REQUEST: len = snprintf(rqsbuf, sizeof rqsbuf, "Error in %s, Offset %d", ISSET(spec_1, SSD_SCS_CDB_ERROR) ? "CDB" : "Parameters", count); if ((len != -1 && len < sizeof rqsbuf) && ISSET(spec_1, SSD_SCS_VALID_BIT_INDEX)) snprintf(rqsbuf+len, sizeof rqsbuf - len, ", bit %d", spec_1 & SSD_SCS_BIT_INDEX); break; case SKEY_RECOVERED_ERROR: case SKEY_MEDIUM_ERROR: case SKEY_HARDWARE_ERROR: snprintf(rqsbuf, sizeof rqsbuf, "Actual Retry Count: %d", count); break; case SKEY_NOT_READY: snprintf(rqsbuf, sizeof rqsbuf, "Progress Indicator: %d", count); break; default: break; } break; default: break; } return rqsbuf; } void scsi_cmd_rw_decode(struct scsi_generic *cmd, u_int64_t *blkno, u_int32_t *nblks) { switch (cmd->opcode) { case READ_COMMAND: case WRITE_COMMAND: { struct scsi_rw *rw = (struct scsi_rw *)cmd; *blkno = _3btol(rw->addr) & (SRW_TOPADDR << 16 | 0xffff); *nblks = rw->length ? rw->length : 0x100; break; } case READ_10: case WRITE_10: { struct scsi_rw_10 *rw10 = (struct scsi_rw_10 *)cmd; *blkno = _4btol(rw10->addr); *nblks = _2btol(rw10->length); break; } case READ_12: case WRITE_12: { struct scsi_rw_12 *rw12 = (struct scsi_rw_12 *)cmd; *blkno = _4btol(rw12->addr); *nblks = _4btol(rw12->length); break; } case READ_16: case WRITE_16: { struct scsi_rw_16 *rw16 = (struct scsi_rw_16 *)cmd; *blkno = _8btol(rw16->addr); *nblks = _4btol(rw16->length); break; } default: panic("scsi_cmd_rw_decode: bad opcode 0x%02x", cmd->opcode); } } #ifdef SCSIDEBUG u_int32_t scsidebug_buses = SCSIDEBUG_BUSES; u_int32_t scsidebug_targets = SCSIDEBUG_TARGETS; u_int32_t scsidebug_luns = SCSIDEBUG_LUNS; int scsidebug_level = SCSIDEBUG_LEVEL; const char *flagnames[] = { "REMOVABLE", "MEDIA LOADED", "READONLY", "OPEN", "DB1", "DB2", "DB3", "DB4", "EJECTING", "ATAPI", "UMASS", "VIRTUAL", "OWN_IOPL", NULL }; const char *quirknames[] = { "AUTOSAVE", "NOSYNC", "NOWIDE", "NOTAGS", "NOSYNCCACHE", "NOSENSE", "LITTLETOC", "NOCAPACITY", "NODOORLOCK", NULL }; const char *devicetypenames[32] = { "T_DIRECT", "T_SEQUENTIAL", "T_PRINTER", "T_PROCESSOR", "T_WORM", "T_CDROM", "T_SCANNER", "T_OPTICAL", "T_CHANGER", "T_COMM", "T_ASC0", "T_ASC1", "T_STROARRAY", "T_ENCLOSURE", "T_RDIRECT", "T_OCRW", "T_BCC", "T_OSD", "T_ADC", "T_RESERVED", "T_RESERVED", "T_RESERVED", "T_RESERVED", "T_RESERVED", "T_RESERVED", "T_RESERVED", "T_RESERVED", "T_RESERVED", "T_RESERVED", "T_RESERVED", "T_WELL_KNOWN_LU", "T_NODEVICE" }; /* * Print out sense data details. */ void scsi_show_sense(struct scsi_xfer *xs) { struct scsi_sense_data *sense = &xs->sense; struct scsi_link *link = xs->sc_link; SC_DEBUG(link, SDEV_DB1, ("code:%#x valid:%d key:%#x ili:%d eom:%d fmark:%d extra:%d\n", sense->error_code & SSD_ERRCODE, sense->error_code & SSD_ERRCODE_VALID ? 1 : 0, sense->flags & SSD_KEY, sense->flags & SSD_ILI ? 1 : 0, sense->flags & SSD_EOM ? 1 : 0, sense->flags & SSD_FILEMARK ? 1 : 0, sense->extra_len)); if (ISSET(xs->sc_link->flags, SDEV_DB1)) scsi_show_mem((u_char *)&xs->sense, sizeof(xs->sense)); scsi_print_sense(xs); } /* * Given a scsi_xfer, dump the request, in all its glory */ void scsi_show_xs(struct scsi_xfer *xs) { u_char *b = (u_char *)&xs->cmd; int i = 0; if (!ISSET(xs->sc_link->flags, SDEV_DB1)) return; sc_print_addr(xs->sc_link); printf("xs (%p): ", xs); printf("flg(0x%x)", xs->flags); printf("link(%p)", xs->sc_link); printf("retr(0x%x)", xs->retries); printf("timo(0x%x)", xs->timeout); printf("data(%p)", xs->data); printf("res(0x%zx)", xs->resid); printf("err(0x%x)", xs->error); printf("bp(%p)\n", xs->bp); sc_print_addr(xs->sc_link); printf("cmd (%p): ", &xs->cmd); if (!ISSET(xs->flags, SCSI_RESET)) { while (i < xs->cmdlen) { if (i) printf(","); printf("%x", b[i++]); } printf("-[%d bytes]\n", xs->datalen); } else printf("-RESET-\n"); if (xs->datalen && ISSET(xs->flags, SCSI_DATA_OUT)) scsi_show_mem(xs->data, min(64, xs->datalen)); } void scsi_show_mem(u_char *address, int num) { int x; printf("------------------------------"); for (x = 0; x < num; x++) { if ((x % 16) == 0) printf("\n%03d: ", x); printf("%02x ", *address++); } printf("\n------------------------------\n"); } void scsi_show_flags(u_int32_t flags, const char **names) { int i, first, exhausted; u_int32_t unnamed; printf("<"); for (first = 1, exhausted = 0, unnamed = 0, i = 0; i < 32; i++) { if (!ISSET(flags, 1 << i)) continue; if (exhausted == 0 && names[i] == NULL) exhausted = 1; if (exhausted || strlen(names[i]) == 0) { SET(unnamed, 1 << i); continue; } if (first == 0) printf(", "); else first = 0; printf("%s", names[i]); } if (unnamed != 0) printf("%s0x%08x", first ? "" : ", ", unnamed); printf(">"); } void scsi_show_inquiry_header(struct scsi_inquiry_data *inqbuf) { switch (inqbuf->device & SID_QUAL) { case SID_QUAL_RSVD: printf("SID_QUAL_RSVD, "); break; case SID_QUAL_BAD_LU: printf("SID_QUAL_BAD_LU, "); break; case SID_QUAL_LU_OFFLINE: printf("SID_QUAL_LU_OFFLINE, "); break; case SID_QUAL_LU_OK: printf("SID_QUAL_LU_OK, "); break; default: printf("SID_QUAL = 0x%02x, ", inqbuf->device & SID_QUAL); break; } printf("%s, ", devicetypenames[inqbuf->device & SID_TYPE]); if (ISSET(inqbuf->dev_qual2, SID_REMOVABLE)) printf("T_REMOV, "); else printf("T_FIXED, "); printf("SID_ANSII_REV %u, SID_RESPONSE_DATA_FMT %u\n", SID_ANSII_REV(inqbuf), inqbuf->response_format & SID_RESPONSE_DATA_FMT); } void scsi_show_inquiry_match(struct scsi_inquiry_data *inqbuf) { char visbuf[65]; unsigned int inqbytes; inqbytes = SID_SCSI2_HDRLEN + inqbuf->additional_length; printf("<"); if (inqbytes >= offsetof(struct scsi_inquiry_data, product)) scsi_strvis(visbuf, inqbuf->vendor, sizeof(inqbuf->vendor)); else visbuf[0] = '\0'; printf("\"%s\", ", visbuf); if (inqbytes >= offsetof(struct scsi_inquiry_data, revision)) scsi_strvis(visbuf, inqbuf->product, sizeof(inqbuf->product)); else visbuf[0] = '\0'; printf("\"%s\", ", visbuf); if (inqbytes >= offsetof(struct scsi_inquiry_data, extra)) scsi_strvis(visbuf, inqbuf->revision, sizeof(inqbuf->revision)); else visbuf[0] = '\0'; printf("\"%s\">\n", visbuf); } #endif /* SCSIDEBUG */
30 5 3 25 6 19 19 9 4 12 11 12 11 1 10 14 8 12 10 22 10 13 1 14 8 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 /* $OpenBSD: exec_script.c,v 1.48 2019/07/15 04:11:03 visa Exp $ */ /* $NetBSD: exec_script.c,v 1.13 1996/02/04 02:15:06 christos Exp $ */ /* * Copyright (c) 1993, 1994 Christopher G. Demetriou * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Christopher G. Demetriou. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/malloc.h> #include <sys/pool.h> #include <sys/vnode.h> #include <sys/lock.h> #include <sys/namei.h> #include <sys/fcntl.h> #include <sys/file.h> #include <sys/filedesc.h> #include <sys/exec.h> #include <sys/exec_script.h> /* * exec_script_makecmds(): Check if it's an executable shell script. * * Given a proc pointer and an exec package pointer, see if the referent * of the epp is in shell script. If it is, then set things up so that * the script can be run. This involves preparing the address space * and arguments for the shell which will run the script. * * This function is ultimately responsible for creating a set of vmcmds * which can be used to build the process's vm space and inserting them * into the exec package. */ int exec_script_makecmds(struct proc *p, struct exec_package *epp) { int error, hdrlinelen, shellnamelen, shellarglen; char *hdrstr = epp->ep_hdr; char *cp, *shellname, *shellarg, *oldpnbuf; char **shellargp = NULL, **tmpsap; struct vnode *scriptvp; uid_t script_uid = -1; gid_t script_gid = -1; u_short script_sbits; /* * remember the old vp and pnbuf for later, so we can restore * them if check_exec() fails. */ scriptvp = epp->ep_vp; oldpnbuf = epp->ep_ndp->ni_cnd.cn_pnbuf; /* * if the magic isn't that of a shell script, or we've already * done shell script processing for this exec, punt on it. */ if ((epp->ep_flags & EXEC_INDIR) != 0 || epp->ep_hdrvalid < EXEC_SCRIPT_MAGICLEN || strncmp(hdrstr, EXEC_SCRIPT_MAGIC, EXEC_SCRIPT_MAGICLEN)) return ENOEXEC; /* * check that the shell spec is terminated by a newline, * and that it isn't too large. Don't modify the * buffer unless we're ready to commit to handling it. * (The latter requirement means that we have to check * for both spaces and tabs later on.) */ hdrlinelen = min(epp->ep_hdrvalid, MAXINTERP); for (cp = hdrstr + EXEC_SCRIPT_MAGICLEN; cp < hdrstr + hdrlinelen; cp++) { if (*cp == '\n') { *cp = '\0'; break; } } if (cp >= hdrstr + hdrlinelen) return ENOEXEC; shellname = NULL; shellarg = NULL; shellarglen = 0; /* strip spaces before the shell name */ for (cp = hdrstr + EXEC_SCRIPT_MAGICLEN; *cp == ' ' || *cp == '\t'; cp++) ; /* collect the shell name; remember its length for later */ shellname = cp; shellnamelen = 0; if (*cp == '\0') goto check_shell; for ( /* cp = cp */ ; *cp != '\0' && *cp != ' ' && *cp != '\t'; cp++) shellnamelen++; if (*cp == '\0') goto check_shell; *cp++ = '\0'; /* skip spaces before any argument */ for ( /* cp = cp */ ; *cp == ' ' || *cp == '\t'; cp++) ; if (*cp == '\0') goto check_shell; /* * collect the shell argument. everything after the shell name * is passed as ONE argument; that's the correct (historical) * behaviour. */ shellarg = cp; for ( /* cp = cp */ ; *cp != '\0'; cp++) shellarglen++; *cp++ = '\0'; check_shell: /* * MNT_NOSUID and STRC are already taken care of by check_exec, * so we don't need to worry about them now or later. */ script_sbits = epp->ep_vap->va_mode & (VSUID | VSGID); if (script_sbits != 0) { script_uid = epp->ep_vap->va_uid; script_gid = epp->ep_vap->va_gid; } /* * if the script isn't readable, or it's set-id, then we've * gotta supply a "/dev/fd/..." for the shell to read. * Note that stupid shells (csh) do the wrong thing, and * close all open fd's when they start. That kills this * method of implementing "safe" set-id and x-only scripts. */ vn_lock(scriptvp, LK_EXCLUSIVE|LK_RETRY); error = VOP_ACCESS(scriptvp, VREAD, p->p_ucred, p); VOP_UNLOCK(scriptvp); if (error == EACCES || script_sbits) { struct file *fp; #ifdef DIAGNOSTIC if (epp->ep_flags & EXEC_HASFD) panic("exec_script_makecmds: epp already has a fd"); #endif fdplock(p->p_fd); error = falloc(p, &fp, &epp->ep_fd); if (error) { fdpunlock(p->p_fd); goto fail; } epp->ep_flags |= EXEC_HASFD; fp->f_type = DTYPE_VNODE; fp->f_ops = &vnops; fp->f_data = (caddr_t) scriptvp; fp->f_flag = FREAD; fdinsert(p->p_fd, epp->ep_fd, 0, fp); fdpunlock(p->p_fd); FRELE(fp, p); } /* set up the parameters for the recursive check_exec() call */ epp->ep_ndp->ni_dirfd = AT_FDCWD; epp->ep_ndp->ni_dirp = shellname; epp->ep_ndp->ni_segflg = UIO_SYSSPACE; epp->ep_flags |= EXEC_INDIR; /* and set up the fake args list, for later */ shellargp = mallocarray(4, sizeof(char *), M_EXEC, M_WAITOK); tmpsap = shellargp; *tmpsap = malloc(shellnamelen + 1, M_EXEC, M_WAITOK); strlcpy(*tmpsap++, shellname, shellnamelen + 1); if (shellarg != NULL) { *tmpsap = malloc(shellarglen + 1, M_EXEC, M_WAITOK); strlcpy(*tmpsap++, shellarg, shellarglen + 1); } *tmpsap = malloc(MAXPATHLEN, M_EXEC, M_WAITOK); if ((epp->ep_flags & EXEC_HASFD) == 0) { error = copyinstr(epp->ep_name, *tmpsap, MAXPATHLEN, NULL); if (error != 0) { *(tmpsap + 1) = NULL; goto fail; } } else snprintf(*tmpsap, MAXPATHLEN, "/dev/fd/%d", epp->ep_fd); tmpsap++; *tmpsap = NULL; /* * mark the header we have as invalid; check_exec will read * the header from the new executable */ epp->ep_hdrvalid = 0; if ((error = check_exec(p, epp)) == 0) { /* note that we've clobbered the header */ epp->ep_flags |= EXEC_DESTR; /* * It succeeded. Unlock the script and * close it if we aren't using it any more. * Also, set things up so that the fake args * list will be used. */ if ((epp->ep_flags & EXEC_HASFD) == 0) vn_close(scriptvp, FREAD, p->p_ucred, p); /* free the old pathname buffer */ pool_put(&namei_pool, oldpnbuf); epp->ep_flags |= (EXEC_HASARGL | EXEC_SKIPARG); epp->ep_fa = shellargp; /* * set things up so that set-id scripts will be * handled appropriately */ epp->ep_vap->va_mode |= script_sbits; if (script_sbits & VSUID) epp->ep_vap->va_uid = script_uid; if (script_sbits & VSGID) epp->ep_vap->va_gid = script_gid; return (0); } /* XXX oldpnbuf not set for "goto fail" path */ epp->ep_ndp->ni_cnd.cn_pnbuf = oldpnbuf; fail: /* note that we've clobbered the header */ epp->ep_flags |= EXEC_DESTR; /* kill the opened file descriptor, else close the file */ if (epp->ep_flags & EXEC_HASFD) { epp->ep_flags &= ~EXEC_HASFD; fdplock(p->p_fd); /* fdrelease() unlocks p->p_fd. */ (void) fdrelease(p, epp->ep_fd); } else vn_close(scriptvp, FREAD, p->p_ucred, p); pool_put(&namei_pool, epp->ep_ndp->ni_cnd.cn_pnbuf); /* free the fake arg list, because we're not returning it */ if (shellargp != NULL) { free(shellargp[0], M_EXEC, shellnamelen + 1); if (shellargp[2] != NULL) { free(shellargp[1], M_EXEC, shellarglen + 1); free(shellargp[2], M_EXEC, MAXPATHLEN); } else free(shellargp[1], M_EXEC, MAXPATHLEN); free(shellargp, M_EXEC, 4 * sizeof(char *)); } /* * free any vmspace-creation commands, * and release their references */ kill_vmcmds(&epp->ep_vmcmds); return error; }
537 536 1 532 533 13 1 2 4 12 12 12 2 1 1 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 /* $OpenBSD: uvm_glue.c,v 1.84 2022/09/10 20:35:29 miod Exp $ */ /* $NetBSD: uvm_glue.c,v 1.44 2001/02/06 19:54:44 eeh Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. * Copyright (c) 1991, 1993, The Regents of the University of California. * * All rights reserved. * * This code is derived from software contributed to Berkeley by * The Mach Operating System project at Carnegie-Mellon University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)vm_glue.c 8.6 (Berkeley) 1/5/94 * from: Id: uvm_glue.c,v 1.1.2.8 1998/02/07 01:16:54 chs Exp * * * Copyright (c) 1987, 1990 Carnegie-Mellon University. * All rights reserved. * * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ /* * uvm_glue.c: glue functions */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/resourcevar.h> #include <sys/buf.h> #include <sys/user.h> #ifdef SYSVSHM #include <sys/shm.h> #endif #include <sys/sched.h> #include <uvm/uvm.h> /* * uvm_kernacc: can the kernel access a region of memory * * - called from malloc [DIAGNOSTIC], and /dev/kmem driver (mem.c) */ boolean_t uvm_kernacc(caddr_t addr, size_t len, int rw) { boolean_t rv; vaddr_t saddr, eaddr; vm_prot_t prot = rw == B_READ ? PROT_READ : PROT_WRITE; saddr = trunc_page((vaddr_t)addr); eaddr = round_page((vaddr_t)addr + len); vm_map_lock_read(kernel_map); rv = uvm_map_checkprot(kernel_map, saddr, eaddr, prot); vm_map_unlock_read(kernel_map); return rv; } /* * uvm_vslock: wire user memory for I/O * * - called from sys_sysctl */ int uvm_vslock(struct proc *p, caddr_t addr, size_t len, vm_prot_t access_type) { struct vm_map *map = &p->p_vmspace->vm_map; vaddr_t start, end; start = trunc_page((vaddr_t)addr); end = round_page((vaddr_t)addr + len); if (end <= start) return (EINVAL); return uvm_fault_wire(map, start, end, access_type); } /* * uvm_vsunlock: unwire user memory wired by uvm_vslock() * * - called from sys_sysctl */ void uvm_vsunlock(struct proc *p, caddr_t addr, size_t len) { vaddr_t start, end; start = trunc_page((vaddr_t)addr); end = round_page((vaddr_t)addr + len); KASSERT(end > start); uvm_fault_unwire(&p->p_vmspace->vm_map, start, end); } /* * uvm_vslock_device: wire user memory, make sure it's device reachable * and bounce if necessary. * * - called from physio */ int uvm_vslock_device(struct proc *p, void *addr, size_t len, vm_prot_t access_type, void **retp) { struct vm_map *map = &p->p_vmspace->vm_map; struct vm_page *pg; struct pglist pgl; int npages; vaddr_t start, end, off; vaddr_t sva, va; vsize_t sz; int error, mapv, i; start = trunc_page((vaddr_t)addr); end = round_page((vaddr_t)addr + len); sz = end - start; off = (vaddr_t)addr - start; if (end <= start) return (EINVAL); vm_map_lock_read(map); retry: mapv = map->timestamp; vm_map_unlock_read(map); if ((error = uvm_fault_wire(map, start, end, access_type))) return (error); vm_map_lock_read(map); if (mapv != map->timestamp) goto retry; npages = atop(sz); for (i = 0; i < npages; i++) { paddr_t pa; if (!pmap_extract(map->pmap, start + ptoa(i), &pa)) { error = EFAULT; goto out_unwire; } if (!PADDR_IS_DMA_REACHABLE(pa)) break; } if (i == npages) { *retp = NULL; return (0); } va = (vaddr_t)km_alloc(sz, &kv_any, &kp_none, &kd_nowait); if (va == 0) { error = ENOMEM; goto out_unwire; } sva = va; TAILQ_INIT(&pgl); error = uvm_pglistalloc(npages * PAGE_SIZE, dma_constraint.ucr_low, dma_constraint.ucr_high, 0, 0, &pgl, npages, UVM_PLA_WAITOK); if (error) goto out_unmap; while ((pg = TAILQ_FIRST(&pgl)) != NULL) { TAILQ_REMOVE(&pgl, pg, pageq); pmap_kenter_pa(va, VM_PAGE_TO_PHYS(pg), PROT_READ | PROT_WRITE); va += PAGE_SIZE; } pmap_update(pmap_kernel()); KASSERT(va == sva + sz); *retp = (void *)(sva + off); if ((error = copyin(addr, *retp, len)) == 0) return 0; uvm_km_pgremove_intrsafe(sva, sva + sz); pmap_kremove(sva, sz); pmap_update(pmap_kernel()); out_unmap: km_free((void *)sva, sz, &kv_any, &kp_none); out_unwire: uvm_fault_unwire_locked(map, start, end); vm_map_unlock_read(map); return (error); } /* * uvm_vsunlock_device: unwire user memory wired by uvm_vslock_device() * * - called from physio */ void uvm_vsunlock_device(struct proc *p, void *addr, size_t len, void *map) { vaddr_t start, end; vaddr_t kva; vsize_t sz; start = trunc_page((vaddr_t)addr); end = round_page((vaddr_t)addr + len); KASSERT(end > start); sz = end - start; if (map) copyout(map, addr, len); uvm_fault_unwire_locked(&p->p_vmspace->vm_map, start, end); vm_map_unlock_read(&p->p_vmspace->vm_map); if (!map) return; kva = trunc_page((vaddr_t)map); uvm_km_pgremove_intrsafe(kva, kva + sz); pmap_kremove(kva, sz); pmap_update(pmap_kernel()); uvm_km_free(kernel_map, kva, sz); } /* * uvm_uarea_alloc: allocate the u-area for a new thread */ vaddr_t uvm_uarea_alloc(void) { vaddr_t uaddr; uaddr = uvm_km_kmemalloc_pla(kernel_map, uvm.kernel_object, USPACE, USPACE_ALIGN, UVM_KMF_ZERO, no_constraint.ucr_low, no_constraint.ucr_high, 0, 0, USPACE/PAGE_SIZE); return (uaddr); } /* * uvm_uarea_free: free a dead thread's stack * * - the thread passed to us is a dead thread; we * are running on a different context now (the reaper). */ void uvm_uarea_free(struct proc *p) { uvm_km_free(kernel_map, (vaddr_t)p->p_addr, USPACE); p->p_addr = NULL; } /* * uvm_exit: exit a virtual address space */ void uvm_exit(struct process *pr) { struct vmspace *vm = pr->ps_vmspace; pr->ps_vmspace = NULL; uvmspace_free(vm); } /* * uvm_init_limit: init per-process VM limits * * - called for process 0 and then inherited by all others. */ void uvm_init_limits(struct plimit *limit0) { /* * Set up the initial limits on process VM. Set the maximum * resident set size to be all of (reasonably) available memory. * This causes any single, large process to start random page * replacement once it fills memory. */ limit0->pl_rlimit[RLIMIT_STACK].rlim_cur = DFLSSIZ; limit0->pl_rlimit[RLIMIT_STACK].rlim_max = MAXSSIZ; limit0->pl_rlimit[RLIMIT_DATA].rlim_cur = DFLDSIZ; limit0->pl_rlimit[RLIMIT_DATA].rlim_max = MAXDSIZ; limit0->pl_rlimit[RLIMIT_RSS].rlim_cur = ptoa(uvmexp.free); } #ifdef __HAVE_PMAP_COLLECT #ifdef DEBUG int enableswap = 1; int swapdebug = 0; #define SDB_FOLLOW 1 #define SDB_SWAPIN 2 #define SDB_SWAPOUT 4 #endif /* * swapout_threads: find threads that can be swapped * * - called by the pagedaemon * - try and swap at least one process * - processes that are sleeping or stopped for maxslp or more seconds * are swapped... otherwise the longest-sleeping or stopped process * is swapped, otherwise the longest resident process... */ void uvm_swapout_threads(void) { struct process *pr; struct proc *p, *slpp; struct process *outpr; int outpri; int didswap = 0; extern int maxslp; /* XXXCDC: should move off to uvmexp. or uvm., also in uvm_meter */ #ifdef DEBUG if (!enableswap) return; #endif /* * outpr/outpri : stop/sleep process whose most active thread has * the largest sleeptime < maxslp */ outpr = NULL; outpri = 0; LIST_FOREACH(pr, &allprocess, ps_list) { if (pr->ps_flags & (PS_SYSTEM | PS_EXITING)) continue; /* * slpp: the sleeping or stopped thread in pr with * the smallest p_slptime */ slpp = NULL; TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) { switch (p->p_stat) { case SRUN: case SONPROC: goto next_process; case SSLEEP: case SSTOP: if (slpp == NULL || slpp->p_slptime < p->p_slptime) slpp = p; continue; } } if (slpp != NULL) { if (slpp->p_slptime >= maxslp) { pmap_collect(pr->ps_vmspace->vm_map.pmap); didswap++; } else if (slpp->p_slptime > outpri) { outpr = pr; outpri = slpp->p_slptime; } } next_process: ; } /* * If we didn't get rid of any real duds, toss out the next most * likely sleeping/stopped or running candidate. We only do this * if we are real low on memory since we don't gain much by doing * it. */ if (didswap == 0 && uvmexp.free <= atop(round_page(USPACE)) && outpr != NULL) { #ifdef DEBUG if (swapdebug & SDB_SWAPOUT) printf("swapout_threads: no duds, try procpr %p\n", outpr); #endif pmap_collect(outpr->ps_vmspace->vm_map.pmap); } } #endif /* __HAVE_PMAP_COLLECT */ /* * uvm_atopg: convert KVAs back to their page structures. */ struct vm_page * uvm_atopg(vaddr_t kva) { struct vm_page *pg; paddr_t pa; boolean_t rv; rv = pmap_extract(pmap_kernel(), kva, &pa); KASSERT(rv); pg = PHYS_TO_VM_PAGE(pa); KASSERT(pg != NULL); return (pg); } void uvm_pause(void) { static unsigned int toggle; if (toggle++ > 128) { toggle = 0; KERNEL_UNLOCK(); KERNEL_LOCK(); } sched_pause(preempt); } #ifndef SMALL_KERNEL int fill_vmmap(struct process *pr, struct kinfo_vmentry *kve, size_t *lenp) { struct vm_map *map; if (pr != NULL) map = &pr->ps_vmspace->vm_map; else map = kernel_map; return uvm_map_fill_vmmap(map, kve, lenp); } #endif
26 19 14 26 18 21 30 5 7 20 20 3 17 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 /* $OpenBSD: mld6.c,v 1.62 2024/02/13 12:22:09 bluhm Exp $ */ /* $KAME: mld6.c,v 1.26 2001/02/16 14:50:35 itojun Exp $ */ /* * Copyright (C) 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 1988 Stephen Deering. * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Stephen Deering of Stanford University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)igmp.c 8.1 (Berkeley) 7/19/93 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/protosw.h> #include <sys/syslog.h> #include <net/if.h> #include <net/if_var.h> #include <net/route.h> #include <netinet/in.h> #include <netinet6/in6_var.h> #include <netinet/ip6.h> #include <netinet6/ip6_var.h> #include <netinet/icmp6.h> #include <netinet6/mld6.h> #include <netinet6/mld6_var.h> static struct ip6_pktopts ip6_opts; int mld6_timers_are_running; /* [N] shortcut for fast timer */ void mld6_checktimer(struct ifnet *); static void mld6_sendpkt(struct in6_multi *, int, const struct in6_addr *); void mld6_init(void) { static u_int8_t hbh_buf[8]; struct ip6_hbh *hbh = (struct ip6_hbh *)hbh_buf; u_int16_t rtalert_code = htons((u_int16_t)IP6OPT_RTALERT_MLD); mld6_timers_are_running = 0; /* ip6h_nxt will be fill in later */ hbh->ip6h_len = 0; /* (8 >> 3) - 1 */ /* XXX: grotty hard coding... */ hbh_buf[2] = IP6OPT_PADN; /* 2 byte padding */ hbh_buf[3] = 0; hbh_buf[4] = IP6OPT_ROUTER_ALERT; hbh_buf[5] = IP6OPT_RTALERT_LEN - 2; memcpy(&hbh_buf[6], (caddr_t)&rtalert_code, sizeof(u_int16_t)); ip6_initpktopts(&ip6_opts); ip6_opts.ip6po_hbh = hbh; } void mld6_start_listening(struct in6_multi *in6m) { /* XXX: These are necessary for KAME's link-local hack */ struct in6_addr all_nodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT; /* * RFC2710 page 10: * The node never sends a Report or Done for the link-scope all-nodes * address. * MLD messages are never sent for multicast addresses whose scope is 0 * (reserved) or 1 (node-local). */ all_nodes.s6_addr16[1] = htons(in6m->in6m_ifidx); if (IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr, &all_nodes) || __IPV6_ADDR_MC_SCOPE(&in6m->in6m_addr) < __IPV6_ADDR_SCOPE_LINKLOCAL) { in6m->in6m_timer = 0; in6m->in6m_state = MLD_OTHERLISTENER; } else { mld6_sendpkt(in6m, MLD_LISTENER_REPORT, NULL); in6m->in6m_timer = MLD_RANDOM_DELAY(MLD_V1_MAX_RI * PR_FASTHZ); in6m->in6m_state = MLD_IREPORTEDLAST; mld6_timers_are_running = 1; } } void mld6_stop_listening(struct in6_multi *in6m) { /* XXX: These are necessary for KAME's link-local hack */ struct in6_addr all_nodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT; struct in6_addr all_routers = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT; all_nodes.s6_addr16[1] = htons(in6m->in6m_ifidx); /* XXX: necessary when mrouting */ all_routers.s6_addr16[1] = htons(in6m->in6m_ifidx); if (in6m->in6m_state == MLD_IREPORTEDLAST && (!IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr, &all_nodes)) && __IPV6_ADDR_MC_SCOPE(&in6m->in6m_addr) > __IPV6_ADDR_SCOPE_INTFACELOCAL) mld6_sendpkt(in6m, MLD_LISTENER_DONE, &all_routers); } void mld6_input(struct mbuf *m, int off) { struct ip6_hdr *ip6; struct mld_hdr *mldh; struct ifnet *ifp; struct in6_multi *in6m; struct ifmaddr *ifma; int timer; /* timer value in the MLD query header */ /* XXX: These are necessary for KAME's link-local hack */ struct in6_addr all_nodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT; IP6_EXTHDR_GET(mldh, struct mld_hdr *, m, off, sizeof(*mldh)); if (mldh == NULL) { icmp6stat_inc(icp6s_tooshort); return; } /* source address validation */ ip6 = mtod(m, struct ip6_hdr *);/* in case mpullup */ if (!IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src)) { #if 0 char src[INET6_ADDRSTRLEN], grp[INET6_ADDRSTRLEN]; log(LOG_ERR, "mld_input: src %s is not link-local (grp=%s)\n", inet_ntop(AF_INET6, &ip6->ip6_src, src, sizeof(src)), inet_ntop(AF_INET6, &mldh->mld_addr, grp, sizeof(grp))); #endif /* * spec (RFC2710) does not explicitly * specify to discard the packet from a non link-local * source address. But we believe it's expected to do so. */ m_freem(m); return; } ifp = if_get(m->m_pkthdr.ph_ifidx); if (ifp == NULL) { m_freem(m); return; } /* * In the MLD6 specification, there are 3 states and a flag. * * In Non-Listener state, we simply don't have a membership record. * In Delaying Listener state, our timer is running (in6m->in6m_timer) * In Idle Listener state, our timer is not running (in6m->in6m_timer==0) * * The flag is in6m->in6m_state, it is set to MLD_OTHERLISTENER if * we have heard a report from another member, or MLD_IREPORTEDLAST * if we sent the last report. */ switch(mldh->mld_type) { case MLD_LISTENER_QUERY: if (ifp->if_flags & IFF_LOOPBACK) break; if (!IN6_IS_ADDR_UNSPECIFIED(&mldh->mld_addr) && !IN6_IS_ADDR_MULTICAST(&mldh->mld_addr)) break; /* print error or log stat? */ if (IN6_IS_ADDR_MC_LINKLOCAL(&mldh->mld_addr)) mldh->mld_addr.s6_addr16[1] = htons(ifp->if_index); /* XXX */ /* * - Start the timers in all of our membership records * that the query applies to for the interface on * which the query arrived excl. those that belong * to the "all-nodes" group (ff02::1). * - Restart any timer that is already running but has * A value longer than the requested timeout. * - Use the value specified in the query message as * the maximum timeout. */ /* * XXX: System timer resolution is too low to handle Max * Response Delay, so set 1 to the internal timer even if * the calculated value equals to zero when Max Response * Delay is positive. */ timer = ntohs(mldh->mld_maxdelay)*PR_FASTHZ/MLD_TIMER_SCALE; if (timer == 0 && mldh->mld_maxdelay) timer = 1; all_nodes.s6_addr16[1] = htons(ifp->if_index); TAILQ_FOREACH(ifma, &ifp->if_maddrlist, ifma_list) { if (ifma->ifma_addr->sa_family != AF_INET6) continue; in6m = ifmatoin6m(ifma); if (IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr, &all_nodes) || __IPV6_ADDR_MC_SCOPE(&in6m->in6m_addr) < __IPV6_ADDR_SCOPE_LINKLOCAL) continue; if (IN6_IS_ADDR_UNSPECIFIED(&mldh->mld_addr) || IN6_ARE_ADDR_EQUAL(&mldh->mld_addr, &in6m->in6m_addr)) { if (timer == 0) { /* send a report immediately */ mld6_sendpkt(in6m, MLD_LISTENER_REPORT, NULL); in6m->in6m_timer = 0; /* reset timer */ in6m->in6m_state = MLD_IREPORTEDLAST; } else if (in6m->in6m_timer == 0 || /* idle */ in6m->in6m_timer > timer) { in6m->in6m_timer = MLD_RANDOM_DELAY(timer); mld6_timers_are_running = 1; } } } if (IN6_IS_ADDR_MC_LINKLOCAL(&mldh->mld_addr)) mldh->mld_addr.s6_addr16[1] = 0; /* XXX */ break; case MLD_LISTENER_REPORT: /* * For fast leave to work, we have to know that we are the * last person to send a report for this group. Reports * can potentially get looped back if we are a multicast * router, so discard reports sourced by me. * Note that it is impossible to check IFF_LOOPBACK flag of * ifp for this purpose, since ip6_mloopback pass the physical * interface to if_input_local(). */ if (m->m_flags & M_LOOP) /* XXX: grotty flag, but efficient */ break; if (!IN6_IS_ADDR_MULTICAST(&mldh->mld_addr)) break; if (IN6_IS_ADDR_MC_LINKLOCAL(&mldh->mld_addr)) mldh->mld_addr.s6_addr16[1] = htons(ifp->if_index); /* XXX */ /* * If we belong to the group being reported, stop * our timer for that group. */ IN6_LOOKUP_MULTI(mldh->mld_addr, ifp, in6m); if (in6m) { in6m->in6m_timer = 0; /* transit to idle state */ in6m->in6m_state = MLD_OTHERLISTENER; /* clear flag */ } if (IN6_IS_ADDR_MC_LINKLOCAL(&mldh->mld_addr)) mldh->mld_addr.s6_addr16[1] = 0; /* XXX */ break; default: /* this is impossible */ #if 0 /* * this case should be impossible because of filtering in * icmp6_input(). But we explicitly disabled this part * just in case. */ log(LOG_ERR, "mld_input: illegal type(%d)", mldh->mld_type); #endif break; } if_put(ifp); m_freem(m); } void mld6_fasttimeo(void) { struct ifnet *ifp; /* * Quick check to see if any work needs to be done, in order * to minimize the overhead of fasttimo processing. * Variable mld6_timers_are_running is read atomically, but without * lock intentionally. In case it is not set due to MP races, we may * miss to check the timers. Then run the loop at next fast timeout. */ if (!mld6_timers_are_running) return; NET_LOCK(); mld6_timers_are_running = 0; TAILQ_FOREACH(ifp, &ifnetlist, if_list) mld6_checktimer(ifp); NET_UNLOCK(); } void mld6_checktimer(struct ifnet *ifp) { struct in6_multi *in6m; struct ifmaddr *ifma; NET_ASSERT_LOCKED(); TAILQ_FOREACH(ifma, &ifp->if_maddrlist, ifma_list) { if (ifma->ifma_addr->sa_family != AF_INET6) continue; in6m = ifmatoin6m(ifma); if (in6m->in6m_timer == 0) { /* do nothing */ } else if (--in6m->in6m_timer == 0) { mld6_sendpkt(in6m, MLD_LISTENER_REPORT, NULL); in6m->in6m_state = MLD_IREPORTEDLAST; } else { mld6_timers_are_running = 1; } } } static void mld6_sendpkt(struct in6_multi *in6m, int type, const struct in6_addr *dst) { struct mbuf *mh, *md; struct mld_hdr *mldh; struct ip6_hdr *ip6; struct ip6_moptions im6o; struct in6_ifaddr *ia6; struct ifnet *ifp; int ignflags; ifp = if_get(in6m->in6m_ifidx); if (ifp == NULL) return; /* * At first, find a link local address on the outgoing interface * to use as the source address of the MLD packet. * We do not reject tentative addresses for MLD report to deal with * the case where we first join a link-local address. */ ignflags = IN6_IFF_DUPLICATED|IN6_IFF_ANYCAST; if ((ia6 = in6ifa_ifpforlinklocal(ifp, ignflags)) == NULL) { if_put(ifp); return; } if ((ia6->ia6_flags & IN6_IFF_TENTATIVE)) ia6 = NULL; /* * Allocate mbufs to store ip6 header and MLD header. * We allocate 2 mbufs and make chain in advance because * it is more convenient when inserting the hop-by-hop option later. */ MGETHDR(mh, M_DONTWAIT, MT_HEADER); if (mh == NULL) { if_put(ifp); return; } MGET(md, M_DONTWAIT, MT_DATA); if (md == NULL) { m_free(mh); if_put(ifp); return; } mh->m_next = md; mh->m_pkthdr.ph_ifidx = 0; mh->m_pkthdr.ph_rtableid = ifp->if_rdomain; mh->m_pkthdr.len = sizeof(struct ip6_hdr) + sizeof(struct mld_hdr); mh->m_len = sizeof(struct ip6_hdr); m_align(mh, sizeof(struct ip6_hdr)); /* fill in the ip6 header */ ip6 = mtod(mh, struct ip6_hdr *); ip6->ip6_flow = 0; ip6->ip6_vfc &= ~IPV6_VERSION_MASK; ip6->ip6_vfc |= IPV6_VERSION; /* ip6_plen will be set later */ ip6->ip6_nxt = IPPROTO_ICMPV6; /* ip6_hlim will be set by im6o.im6o_hlim */ ip6->ip6_src = ia6 ? ia6->ia_addr.sin6_addr : in6addr_any; ip6->ip6_dst = dst ? *dst : in6m->in6m_addr; /* fill in the MLD header */ md->m_len = sizeof(struct mld_hdr); mldh = mtod(md, struct mld_hdr *); mldh->mld_type = type; mldh->mld_code = 0; mldh->mld_cksum = 0; /* XXX: we assume the function will not be called for query messages */ mldh->mld_maxdelay = 0; mldh->mld_reserved = 0; mldh->mld_addr = in6m->in6m_addr; if (IN6_IS_ADDR_MC_LINKLOCAL(&mldh->mld_addr)) mldh->mld_addr.s6_addr16[1] = 0; /* XXX */ mh->m_pkthdr.csum_flags |= M_ICMP_CSUM_OUT; /* construct multicast option */ bzero(&im6o, sizeof(im6o)); im6o.im6o_ifidx = ifp->if_index; im6o.im6o_hlim = 1; /* * Request loopback of the report if we are acting as a multicast * router, so that the process-level routing daemon can hear it. */ #ifdef MROUTING im6o.im6o_loop = (ip6_mrouter[ifp->if_rdomain] != NULL); #endif if_put(ifp); icmp6stat_inc(icp6s_outhist + type); ip6_output(mh, &ip6_opts, NULL, ia6 ? 0 : IPV6_UNSPECSRC, &im6o, NULL); }
4 4 1 1 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 /* $OpenBSD: if_bpe.c,v 1.22 2023/12/23 10:52:54 bluhm Exp $ */ /* * Copyright (c) 2018 David Gwynne <dlg@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "bpfilter.h" #include "pf.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <sys/timeout.h> #include <sys/pool.h> #include <sys/tree.h> #include <sys/smr.h> #include <net/if.h> #include <net/if_var.h> #include <net/if_dl.h> #include <net/if_media.h> #include <net/if_types.h> #include <net/rtable.h> #include <netinet/in.h> #include <netinet/if_ether.h> /* for bridge stuff */ #include <net/if_bridge.h> #include <net/if_etherbridge.h> #if NBPFILTER > 0 #include <net/bpf.h> #endif #include <net/if_bpe.h> #define PBB_ITAG_ISID 0x00ffffff #define PBB_ITAG_ISID_MIN 0x00000000 #define PBB_ITAG_ISID_MAX 0x00ffffff #define PBB_ITAG_RES2 0x03000000 /* must be zero on input */ #define PBB_ITAG_RES1 0x04000000 /* ignore on input */ #define PBB_ITAG_UCA 0x08000000 #define PBB_ITAG_DEI 0x10000000 #define PBB_ITAG_PCP_SHIFT 29 #define PBB_ITAG_PCP_MASK (0x7U << PBB_ITAG_PCP_SHIFT) #define BPE_BRIDGE_AGE_TMO 100 /* seconds */ struct bpe_key { int k_if; uint32_t k_isid; RBT_ENTRY(bpe_tunnel) k_entry; }; RBT_HEAD(bpe_tree, bpe_key); static inline int bpe_cmp(const struct bpe_key *, const struct bpe_key *); RBT_PROTOTYPE(bpe_tree, bpe_key, k_entry, bpe_cmp); RBT_GENERATE(bpe_tree, bpe_key, k_entry, bpe_cmp); struct bpe_softc { struct bpe_key sc_key; /* must be first */ struct arpcom sc_ac; int sc_txhprio; int sc_rxhprio; struct ether_addr sc_group; struct task sc_ltask; struct task sc_dtask; struct etherbridge sc_eb; }; void bpeattach(int); static int bpe_clone_create(struct if_clone *, int); static int bpe_clone_destroy(struct ifnet *); static void bpe_start(struct ifnet *); static int bpe_ioctl(struct ifnet *, u_long, caddr_t); static int bpe_media_get(struct bpe_softc *, struct ifreq *); static int bpe_up(struct bpe_softc *); static int bpe_down(struct bpe_softc *); static int bpe_multi(struct bpe_softc *, struct ifnet *, u_long); static int bpe_set_vnetid(struct bpe_softc *, const struct ifreq *); static void bpe_set_group(struct bpe_softc *, uint32_t); static int bpe_set_parent(struct bpe_softc *, const struct if_parent *); static int bpe_get_parent(struct bpe_softc *, struct if_parent *); static int bpe_del_parent(struct bpe_softc *); static int bpe_add_addr(struct bpe_softc *, const struct ifbareq *); static int bpe_del_addr(struct bpe_softc *, const struct ifbareq *); static void bpe_link_hook(void *); static void bpe_link_state(struct bpe_softc *, u_char, uint64_t); static void bpe_detach_hook(void *); static struct if_clone bpe_cloner = IF_CLONE_INITIALIZER("bpe", bpe_clone_create, bpe_clone_destroy); static int bpe_eb_port_eq(void *, void *, void *); static void *bpe_eb_port_take(void *, void *); static void bpe_eb_port_rele(void *, void *); static size_t bpe_eb_port_ifname(void *, char *, size_t, void *); static void bpe_eb_port_sa(void *, struct sockaddr_storage *, void *); static const struct etherbridge_ops bpe_etherbridge_ops = { bpe_eb_port_eq, bpe_eb_port_take, bpe_eb_port_rele, bpe_eb_port_ifname, bpe_eb_port_sa, }; static struct bpe_tree bpe_interfaces = RBT_INITIALIZER(); static struct rwlock bpe_lock = RWLOCK_INITIALIZER("bpeifs"); static struct pool bpe_endpoint_pool; void bpeattach(int count) { if_clone_attach(&bpe_cloner); } static int bpe_clone_create(struct if_clone *ifc, int unit) { struct bpe_softc *sc; struct ifnet *ifp; int error; if (bpe_endpoint_pool.pr_size == 0) { pool_init(&bpe_endpoint_pool, sizeof(struct ether_addr), 0, IPL_NONE, 0, "bpepl", NULL); } sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); ifp = &sc->sc_ac.ac_if; snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d", ifc->ifc_name, unit); error = etherbridge_init(&sc->sc_eb, ifp->if_xname, &bpe_etherbridge_ops, sc); if (error == -1) { free(sc, M_DEVBUF, sizeof(*sc)); return (error); } sc->sc_key.k_if = 0; sc->sc_key.k_isid = 0; bpe_set_group(sc, 0); sc->sc_txhprio = IF_HDRPRIO_PACKET; sc->sc_rxhprio = IF_HDRPRIO_OUTER; task_set(&sc->sc_ltask, bpe_link_hook, sc); task_set(&sc->sc_dtask, bpe_detach_hook, sc); ifp->if_softc = sc; ifp->if_hardmtu = ETHER_MAX_HARDMTU_LEN; ifp->if_ioctl = bpe_ioctl; ifp->if_start = bpe_start; ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST; ifp->if_xflags = IFXF_CLONED; ether_fakeaddr(ifp); if_counters_alloc(ifp); if_attach(ifp); ether_ifattach(ifp); return (0); } static int bpe_clone_destroy(struct ifnet *ifp) { struct bpe_softc *sc = ifp->if_softc; NET_LOCK(); if (ISSET(ifp->if_flags, IFF_RUNNING)) bpe_down(sc); NET_UNLOCK(); ether_ifdetach(ifp); if_detach(ifp); etherbridge_destroy(&sc->sc_eb); free(sc, M_DEVBUF, sizeof(*sc)); return (0); } static void bpe_start(struct ifnet *ifp) { struct bpe_softc *sc = ifp->if_softc; struct ifnet *ifp0; struct mbuf *m0, *m; struct ether_header *ceh; struct ether_header *beh; uint32_t itag, *itagp; int hlen = sizeof(*beh) + sizeof(*itagp); #if NBPFILTER > 0 caddr_t if_bpf; #endif int txprio; uint8_t prio; ifp0 = if_get(sc->sc_key.k_if); if (ifp0 == NULL || !ISSET(ifp0->if_flags, IFF_RUNNING)) { ifq_purge(&ifp->if_snd); goto done; } txprio = sc->sc_txhprio; while ((m0 = ifq_dequeue(&ifp->if_snd)) != NULL) { #if NBPFILTER > 0 if_bpf = ifp->if_bpf; if (if_bpf) bpf_mtap_ether(if_bpf, m0, BPF_DIRECTION_OUT); #endif ceh = mtod(m0, struct ether_header *); /* force prepend of a whole mbuf because of alignment */ m = m_get(M_DONTWAIT, m0->m_type); if (m == NULL) { m_freem(m0); continue; } M_MOVE_PKTHDR(m, m0); m->m_next = m0; m_align(m, 0); m->m_len = 0; m = m_prepend(m, hlen, M_DONTWAIT); if (m == NULL) continue; beh = mtod(m, struct ether_header *); if (ETHER_IS_BROADCAST(ceh->ether_dhost)) { memcpy(beh->ether_dhost, &sc->sc_group, sizeof(beh->ether_dhost)); } else { struct ether_addr *endpoint; smr_read_enter(); endpoint = etherbridge_resolve_ea(&sc->sc_eb, (struct ether_addr *)ceh->ether_dhost); if (endpoint == NULL) { /* "flood" to unknown hosts */ endpoint = &sc->sc_group; } memcpy(beh->ether_dhost, endpoint, sizeof(beh->ether_dhost)); smr_read_leave(); } memcpy(beh->ether_shost, ((struct arpcom *)ifp0)->ac_enaddr, sizeof(beh->ether_shost)); beh->ether_type = htons(ETHERTYPE_PBB); prio = (txprio == IF_HDRPRIO_PACKET) ? m->m_pkthdr.pf.prio : txprio; itag = sc->sc_key.k_isid; itag |= prio << PBB_ITAG_PCP_SHIFT; itagp = (uint32_t *)(beh + 1); htobem32(itagp, itag); if_enqueue(ifp0, m); } done: if_put(ifp0); } static int bpe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct bpe_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *)data; struct ifbrparam *bparam = (struct ifbrparam *)data; int error = 0; switch (cmd) { case SIOCSIFFLAGS: if (ISSET(ifp->if_flags, IFF_UP)) { if (!ISSET(ifp->if_flags, IFF_RUNNING)) error = bpe_up(sc); else error = 0; } else { if (ISSET(ifp->if_flags, IFF_RUNNING)) error = bpe_down(sc); } break; case SIOCSVNETID: error = bpe_set_vnetid(sc, ifr); break; case SIOCGVNETID: ifr->ifr_vnetid = sc->sc_key.k_isid; break; case SIOCSIFPARENT: error = bpe_set_parent(sc, (struct if_parent *)data); break; case SIOCGIFPARENT: error = bpe_get_parent(sc, (struct if_parent *)data); break; case SIOCDIFPARENT: error = bpe_del_parent(sc); break; case SIOCSTXHPRIO: error = if_txhprio_l2_check(ifr->ifr_hdrprio); if (error != 0) break; sc->sc_txhprio = ifr->ifr_hdrprio; break; case SIOCGTXHPRIO: ifr->ifr_hdrprio = sc->sc_txhprio; break; case SIOCSRXHPRIO: error = if_rxhprio_l2_check(ifr->ifr_hdrprio); if (error != 0) break; sc->sc_rxhprio = ifr->ifr_hdrprio; break; case SIOCGRXHPRIO: ifr->ifr_hdrprio = sc->sc_rxhprio; break; case SIOCGIFMEDIA: error = bpe_media_get(sc, ifr); break; case SIOCBRDGSCACHE: error = suser(curproc); if (error != 0) break; error = etherbridge_set_max(&sc->sc_eb, bparam); break; case SIOCBRDGGCACHE: error = etherbridge_get_max(&sc->sc_eb, bparam); break; case SIOCBRDGSTO: error = suser(curproc); if (error != 0) break; error = etherbridge_set_tmo(&sc->sc_eb, bparam); break; case SIOCBRDGGTO: error = etherbridge_get_tmo(&sc->sc_eb, bparam); break; case SIOCBRDGRTS: error = etherbridge_rtfind(&sc->sc_eb, (struct ifbaconf *)data); break; case SIOCBRDGFLUSH: error = suser(curproc); if (error != 0) break; etherbridge_flush(&sc->sc_eb, ((struct ifbreq *)data)->ifbr_ifsflags); break; case SIOCBRDGSADDR: error = bpe_add_addr(sc, (struct ifbareq *)data); break; case SIOCBRDGDADDR: error = bpe_del_addr(sc, (struct ifbareq *)data); break; default: error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); break; } return (error); } static int bpe_media_get(struct bpe_softc *sc, struct ifreq *ifr) { struct ifnet *ifp0; int error; ifp0 = if_get(sc->sc_key.k_if); if (ifp0 != NULL) error = (*ifp0->if_ioctl)(ifp0, SIOCGIFMEDIA, (caddr_t)ifr); else error = ENOTTY; if_put(ifp0); return (error); } static int bpe_up(struct bpe_softc *sc) { struct ifnet *ifp = &sc->sc_ac.ac_if; struct ifnet *ifp0; struct bpe_softc *osc; int error; u_int hardmtu; u_int hlen = sizeof(struct ether_header) + sizeof(uint32_t); KASSERT(!ISSET(ifp->if_flags, IFF_RUNNING)); NET_ASSERT_LOCKED(); error = etherbridge_up(&sc->sc_eb); if (error != 0) return (error); ifp0 = if_get(sc->sc_key.k_if); if (ifp0 == NULL) { error = ENXIO; goto down; } /* check again if bpe will work on top of the parent */ if (ifp0->if_type != IFT_ETHER) { error = EPROTONOSUPPORT; goto put; } hardmtu = ifp0->if_hardmtu; if (hardmtu < hlen) { error = ENOBUFS; goto put; } hardmtu -= hlen; if (ifp->if_mtu > hardmtu) { error = ENOBUFS; goto put; } /* parent is fine, let's prepare the bpe to handle packets */ ifp->if_hardmtu = hardmtu; SET(ifp->if_flags, ifp0->if_flags & IFF_SIMPLEX); /* commit the interface */ error = rw_enter(&bpe_lock, RW_WRITE | RW_INTR); if (error != 0) goto scrub; osc = (struct bpe_softc *)RBT_INSERT(bpe_tree, &bpe_interfaces, (struct bpe_key *)sc); rw_exit(&bpe_lock); if (osc != NULL) { error = EADDRINUSE; goto scrub; } if (bpe_multi(sc, ifp0, SIOCADDMULTI) != 0) { error = ENOTCONN; goto remove; } /* Register callback for physical link state changes */ if_linkstatehook_add(ifp0, &sc->sc_ltask); /* Register callback if parent wants to unregister */ if_detachhook_add(ifp0, &sc->sc_dtask); /* we're running now */ SET(ifp->if_flags, IFF_RUNNING); bpe_link_state(sc, ifp0->if_link_state, ifp0->if_baudrate); if_put(ifp0); return (0); remove: rw_enter(&bpe_lock, RW_WRITE); RBT_REMOVE(bpe_tree, &bpe_interfaces, (struct bpe_key *)sc); rw_exit(&bpe_lock); scrub: CLR(ifp->if_flags, IFF_SIMPLEX); ifp->if_hardmtu = 0xffff; put: if_put(ifp0); down: etherbridge_down(&sc->sc_eb); return (error); } static int bpe_down(struct bpe_softc *sc) { struct ifnet *ifp = &sc->sc_ac.ac_if; struct ifnet *ifp0; NET_ASSERT_LOCKED(); CLR(ifp->if_flags, IFF_RUNNING); ifp0 = if_get(sc->sc_key.k_if); if (ifp0 != NULL) { if_detachhook_del(ifp0, &sc->sc_dtask); if_linkstatehook_del(ifp0, &sc->sc_ltask); bpe_multi(sc, ifp0, SIOCDELMULTI); } if_put(ifp0); rw_enter(&bpe_lock, RW_WRITE); RBT_REMOVE(bpe_tree, &bpe_interfaces, (struct bpe_key *)sc); rw_exit(&bpe_lock); CLR(ifp->if_flags, IFF_SIMPLEX); ifp->if_hardmtu = 0xffff; etherbridge_down(&sc->sc_eb); return (0); } static int bpe_multi(struct bpe_softc *sc, struct ifnet *ifp0, u_long cmd) { struct ifreq ifr; struct sockaddr *sa; /* make it convincing */ CTASSERT(sizeof(ifr.ifr_name) == sizeof(ifp0->if_xname)); memcpy(ifr.ifr_name, ifp0->if_xname, sizeof(ifr.ifr_name)); sa = &ifr.ifr_addr; CTASSERT(sizeof(sa->sa_data) >= sizeof(sc->sc_group)); sa->sa_family = AF_UNSPEC; memcpy(sa->sa_data, &sc->sc_group, sizeof(sc->sc_group)); return ((*ifp0->if_ioctl)(ifp0, cmd, (caddr_t)&ifr)); } static void bpe_set_group(struct bpe_softc *sc, uint32_t isid) { uint8_t *group = sc->sc_group.ether_addr_octet; group[0] = 0x01; group[1] = 0x1e; group[2] = 0x83; group[3] = isid >> 16; group[4] = isid >> 8; group[5] = isid >> 0; } static int bpe_set_vnetid(struct bpe_softc *sc, const struct ifreq *ifr) { struct ifnet *ifp = &sc->sc_ac.ac_if; uint32_t isid; if (ifr->ifr_vnetid < PBB_ITAG_ISID_MIN || ifr->ifr_vnetid > PBB_ITAG_ISID_MAX) return (EINVAL); isid = ifr->ifr_vnetid; if (isid == sc->sc_key.k_isid) return (0); if (ISSET(ifp->if_flags, IFF_RUNNING)) return (EBUSY); /* commit */ sc->sc_key.k_isid = isid; bpe_set_group(sc, isid); etherbridge_flush(&sc->sc_eb, IFBF_FLUSHALL); return (0); } static int bpe_set_parent(struct bpe_softc *sc, const struct if_parent *p) { struct ifnet *ifp = &sc->sc_ac.ac_if; struct ifnet *ifp0; int error = 0; ifp0 = if_unit(p->ifp_parent); if (ifp0 == NULL) return (ENXIO); if (ifp0->if_type != IFT_ETHER) { error = ENXIO; goto put; } if (ifp0->if_index == sc->sc_key.k_if) goto put; if (ISSET(ifp->if_flags, IFF_RUNNING)) { error = EBUSY; goto put; } ifsetlro(ifp0, 0); /* commit */ sc->sc_key.k_if = ifp0->if_index; etherbridge_flush(&sc->sc_eb, IFBF_FLUSHALL); put: if_put(ifp0); return (error); } static int bpe_get_parent(struct bpe_softc *sc, struct if_parent *p) { struct ifnet *ifp0; int error = 0; ifp0 = if_get(sc->sc_key.k_if); if (ifp0 == NULL) error = EADDRNOTAVAIL; else memcpy(p->ifp_parent, ifp0->if_xname, sizeof(p->ifp_parent)); if_put(ifp0); return (error); } static int bpe_del_parent(struct bpe_softc *sc) { struct ifnet *ifp = &sc->sc_ac.ac_if; if (ISSET(ifp->if_flags, IFF_RUNNING)) return (EBUSY); /* commit */ sc->sc_key.k_if = 0; etherbridge_flush(&sc->sc_eb, IFBF_FLUSHALL); return (0); } static int bpe_add_addr(struct bpe_softc *sc, const struct ifbareq *ifba) { const struct sockaddr_dl *sdl; const struct ether_addr *endpoint; unsigned int type; /* ignore ifba_ifsname */ if (ISSET(ifba->ifba_flags, ~IFBAF_TYPEMASK)) return (EINVAL); switch (ifba->ifba_flags & IFBAF_TYPEMASK) { case IFBAF_DYNAMIC: type = EBE_DYNAMIC; break; case IFBAF_STATIC: type = EBE_STATIC; break; default: return (EINVAL); } if (ifba->ifba_dstsa.ss_family != AF_LINK) return (EAFNOSUPPORT); sdl = (struct sockaddr_dl *)&ifba->ifba_dstsa; if (sdl->sdl_type != IFT_ETHER) return (EAFNOSUPPORT); if (sdl->sdl_alen != ETHER_ADDR_LEN) return (EINVAL); endpoint = (struct ether_addr *)LLADDR(sdl); /* check endpoint for multicast or broadcast? */ return (etherbridge_add_addr(&sc->sc_eb, (void *)endpoint, &ifba->ifba_dst, type)); } static int bpe_del_addr(struct bpe_softc *sc, const struct ifbareq *ifba) { return (etherbridge_del_addr(&sc->sc_eb, &ifba->ifba_dst)); } static inline struct bpe_softc * bpe_find(struct ifnet *ifp0, uint32_t isid) { struct bpe_key k = { .k_if = ifp0->if_index, .k_isid = isid }; struct bpe_softc *sc; rw_enter_read(&bpe_lock); sc = (struct bpe_softc *)RBT_FIND(bpe_tree, &bpe_interfaces, &k); rw_exit_read(&bpe_lock); return (sc); } void bpe_input(struct ifnet *ifp0, struct mbuf *m) { struct bpe_softc *sc; struct ifnet *ifp; struct ether_header *beh, *ceh; uint32_t *itagp, itag; unsigned int hlen = sizeof(*beh) + sizeof(*itagp) + sizeof(*ceh); struct mbuf *n; int off; int prio; if (m->m_len < hlen) { m = m_pullup(m, hlen); if (m == NULL) { /* pbb short ++ */ return; } } beh = mtod(m, struct ether_header *); itagp = (uint32_t *)(beh + 1); itag = bemtoh32(itagp); if (itag & PBB_ITAG_RES2) { /* dropped by res2 ++ */ goto drop; } sc = bpe_find(ifp0, itag & PBB_ITAG_ISID); if (sc == NULL) { /* no interface found */ goto drop; } ceh = (struct ether_header *)(itagp + 1); etherbridge_map_ea(&sc->sc_eb, ceh->ether_shost, (struct ether_addr *)beh->ether_shost); m_adj(m, sizeof(*beh) + sizeof(*itagp)); n = m_getptr(m, sizeof(*ceh), &off); if (n == NULL) { /* no data ++ */ goto drop; } if (!ALIGNED_POINTER(mtod(n, caddr_t) + off, uint32_t)) { /* unaligned ++ */ n = m_dup_pkt(m, ETHER_ALIGN, M_NOWAIT); m_freem(m); if (n == NULL) return; m = n; } ifp = &sc->sc_ac.ac_if; prio = sc->sc_rxhprio; switch (prio) { case IF_HDRPRIO_PACKET: break; case IF_HDRPRIO_OUTER: m->m_pkthdr.pf.prio = (itag & PBB_ITAG_PCP_MASK) >> PBB_ITAG_PCP_SHIFT; break; default: m->m_pkthdr.pf.prio = prio; break; } m->m_flags &= ~(M_BCAST|M_MCAST); m->m_pkthdr.ph_ifidx = ifp->if_index; m->m_pkthdr.ph_rtableid = ifp->if_rdomain; #if NPF > 0 pf_pkt_addr_changed(m); #endif if_vinput(ifp, m); return; drop: m_freem(m); } void bpe_detach_hook(void *arg) { struct bpe_softc *sc = arg; struct ifnet *ifp = &sc->sc_ac.ac_if; if (ISSET(ifp->if_flags, IFF_RUNNING)) { bpe_down(sc); CLR(ifp->if_flags, IFF_UP); } sc->sc_key.k_if = 0; } static void bpe_link_hook(void *arg) { struct bpe_softc *sc = arg; struct ifnet *ifp0; u_char link = LINK_STATE_DOWN; uint64_t baud = 0; ifp0 = if_get(sc->sc_key.k_if); if (ifp0 != NULL) { link = ifp0->if_link_state; baud = ifp0->if_baudrate; } if_put(ifp0); bpe_link_state(sc, link, baud); } void bpe_link_state(struct bpe_softc *sc, u_char link, uint64_t baud) { struct ifnet *ifp = &sc->sc_ac.ac_if; if (ifp->if_link_state == link) return; ifp->if_link_state = link; ifp->if_baudrate = baud; if_link_state_change(ifp); } static inline int bpe_cmp(const struct bpe_key *a, const struct bpe_key *b) { if (a->k_if > b->k_if) return (1); if (a->k_if < b->k_if) return (-1); if (a->k_isid > b->k_isid) return (1); if (a->k_isid < b->k_isid) return (-1); return (0); } static int bpe_eb_port_eq(void *arg, void *a, void *b) { struct ether_addr *ea = a, *eb = b; return (memcmp(ea, eb, sizeof(*ea)) == 0); } static void * bpe_eb_port_take(void *arg, void *port) { struct ether_addr *ea = port; struct ether_addr *endpoint; endpoint = pool_get(&bpe_endpoint_pool, PR_NOWAIT); if (endpoint == NULL) return (NULL); memcpy(endpoint, ea, sizeof(*endpoint)); return (endpoint); } static void bpe_eb_port_rele(void *arg, void *port) { struct ether_addr *endpoint = port; pool_put(&bpe_endpoint_pool, endpoint); } static size_t bpe_eb_port_ifname(void *arg, char *dst, size_t len, void *port) { struct bpe_softc *sc = arg; return (strlcpy(dst, sc->sc_ac.ac_if.if_xname, len)); } static void bpe_eb_port_sa(void *arg, struct sockaddr_storage *ss, void *port) { struct ether_addr *endpoint = port; struct sockaddr_dl *sdl; sdl = (struct sockaddr_dl *)ss; sdl->sdl_len = sizeof(sdl); sdl->sdl_family = AF_LINK; sdl->sdl_index = 0; sdl->sdl_type = IFT_ETHER; sdl->sdl_nlen = 0; sdl->sdl_alen = sizeof(*endpoint); CTASSERT(sizeof(sdl->sdl_data) >= sizeof(*endpoint)); memcpy(sdl->sdl_data, endpoint, sizeof(*endpoint)); }
30 30 30 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 /* $OpenBSD: exec_subr.c,v 1.67 2024/04/02 08:39:16 deraadt Exp $ */ /* $NetBSD: exec_subr.c,v 1.9 1994/12/04 03:10:42 mycroft Exp $ */ /* * Copyright (c) 1993, 1994 Christopher G. Demetriou * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Christopher G. Demetriou. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/malloc.h> #include <sys/vnode.h> #include <sys/exec.h> #include <sys/mman.h> #include <sys/resourcevar.h> #include <uvm/uvm_extern.h> #ifdef DEBUG /* * new_vmcmd(): * create a new vmcmd structure and fill in its fields based * on function call arguments. make sure objects ref'd by * the vmcmd are 'held'. * * If not debugging, this is a macro, so it's expanded inline. */ void new_vmcmd(struct exec_vmcmd_set *evsp, int (*proc)(struct proc *, struct exec_vmcmd *), u_long len, u_long addr, struct vnode *vp, u_long offset, u_int prot, int flags) { struct exec_vmcmd *vcp; if (evsp->evs_used >= evsp->evs_cnt) vmcmdset_extend(evsp); vcp = &evsp->evs_cmds[evsp->evs_used++]; vcp->ev_proc = proc; vcp->ev_len = len; vcp->ev_addr = addr; if ((vcp->ev_vp = vp) != NULL) vref(vp); vcp->ev_offset = offset; vcp->ev_prot = prot; vcp->ev_flags = flags; } #endif /* DEBUG */ void vmcmdset_extend(struct exec_vmcmd_set *evsp) { struct exec_vmcmd *nvcp; u_int ocnt; #ifdef DIAGNOSTIC if (evsp->evs_used < evsp->evs_cnt) panic("vmcmdset_extend: not necessary"); #endif ocnt = evsp->evs_cnt; KASSERT(ocnt > 0); /* figure out number of entries in new set */ evsp->evs_cnt += ocnt; /* reallocate the command set */ nvcp = mallocarray(evsp->evs_cnt, sizeof(*nvcp), M_EXEC, M_WAITOK); memcpy(nvcp, evsp->evs_cmds, ocnt * sizeof(*nvcp)); if (evsp->evs_cmds != evsp->evs_start) free(evsp->evs_cmds, M_EXEC, ocnt * sizeof(*nvcp)); evsp->evs_cmds = nvcp; } void kill_vmcmds(struct exec_vmcmd_set *evsp) { struct exec_vmcmd *vcp; int i; for (i = 0; i < evsp->evs_used; i++) { vcp = &evsp->evs_cmds[i]; if (vcp->ev_vp != NULLVP) vrele(vcp->ev_vp); } /* * Free old vmcmds and reset the array. */ evsp->evs_used = 0; if (evsp->evs_cmds != evsp->evs_start) free(evsp->evs_cmds, M_EXEC, evsp->evs_cnt * sizeof(struct exec_vmcmd)); evsp->evs_cmds = evsp->evs_start; evsp->evs_cnt = EXEC_DEFAULT_VMCMD_SETSIZE; } int exec_process_vmcmds(struct proc *p, struct exec_package *epp) { struct exec_vmcmd *base_vc = NULL; int error = 0; int i; for (i = 0; i < epp->ep_vmcmds.evs_used && !error; i++) { struct exec_vmcmd *vcp; vcp = &epp->ep_vmcmds.evs_cmds[i]; if (vcp->ev_flags & VMCMD_RELATIVE) { #ifdef DIAGNOSTIC if (base_vc == NULL) panic("exec_process_vmcmds: RELATIVE no base"); #endif vcp->ev_addr += base_vc->ev_addr; } error = (*vcp->ev_proc)(p, vcp); if (vcp->ev_flags & VMCMD_BASE) { base_vc = vcp; } } kill_vmcmds(&epp->ep_vmcmds); return (error); } /* * vmcmd_map_pagedvn(): * handle vmcmd which specifies that a vnode should be mmap'd. * appropriate for handling demand-paged text and data segments. */ int vmcmd_map_pagedvn(struct proc *p, struct exec_vmcmd *cmd) { /* * note that if you're going to map part of a process as being * paged from a vnode, that vnode had damn well better be marked as * VTEXT. that's handled in the routine which sets up the vmcmd to * call this routine. */ struct uvm_object *uobj; unsigned int flags = UVM_FLAG_COPYONW | UVM_FLAG_FIXED; int error; /* * map the vnode in using uvm_map. */ if (cmd->ev_len == 0) return (0); if (cmd->ev_offset & PAGE_MASK) return (EINVAL); if (cmd->ev_addr & PAGE_MASK) return (EINVAL); if (cmd->ev_len & PAGE_MASK) return (EINVAL); /* * first, attach to the object */ uobj = uvn_attach(cmd->ev_vp, PROT_READ | PROT_EXEC); if (uobj == NULL) return (ENOMEM); /* * do the map */ error = uvm_map(&p->p_vmspace->vm_map, &cmd->ev_addr, cmd->ev_len, uobj, cmd->ev_offset, 0, UVM_MAPFLAG(cmd->ev_prot, PROT_MASK, MAP_INHERIT_COPY, MADV_NORMAL, flags)); /* * check for error */ if (error) { /* * error: detach from object */ uobj->pgops->pgo_detach(uobj); } else { if (cmd->ev_flags & VMCMD_IMMUTABLE) uvm_map_immutable(&p->p_vmspace->vm_map, cmd->ev_addr, round_page(cmd->ev_addr + cmd->ev_len), 1); #ifdef PMAP_CHECK_COPYIN if (PMAP_CHECK_COPYIN && ((cmd->ev_flags & VMCMD_IMMUTABLE) && (cmd->ev_prot & PROT_EXEC))) uvm_map_check_copyin_add(&p->p_vmspace->vm_map, cmd->ev_addr, round_page(cmd->ev_addr + cmd->ev_len)); #endif } return (error); } /* * vmcmd_map_readvn(): * handle vmcmd which specifies that a vnode should be read from. * appropriate for non-demand-paged text/data segments, i.e. impure * objects (a la OMAGIC and NMAGIC). */ int vmcmd_map_readvn(struct proc *p, struct exec_vmcmd *cmd) { int error; vm_prot_t prot; if (cmd->ev_len == 0) return (0); prot = cmd->ev_prot; KASSERT((cmd->ev_addr & PAGE_MASK) == 0); error = uvm_map(&p->p_vmspace->vm_map, &cmd->ev_addr, round_page(cmd->ev_len), NULL, UVM_UNKNOWN_OFFSET, 0, UVM_MAPFLAG(prot | PROT_WRITE, PROT_MASK, MAP_INHERIT_COPY, MADV_NORMAL, UVM_FLAG_FIXED|UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW)); if (error) return (error); error = vn_rdwr(UIO_READ, cmd->ev_vp, (caddr_t)cmd->ev_addr, cmd->ev_len, cmd->ev_offset, UIO_USERSPACE, IO_UNIT, p->p_ucred, NULL, p); if (error) return (error); if ((prot & PROT_WRITE) == 0) { /* * we had to map in the area at PROT_WRITE so that vn_rdwr() * could write to it. however, the caller seems to want * it mapped read-only, so now we are going to have to call * uvm_map_protect() to fix up the protection. ICK. */ error = (uvm_map_protect(&p->p_vmspace->vm_map, cmd->ev_addr, round_page(cmd->ev_len), prot, 0, FALSE, TRUE)); } if (error == 0) { if (cmd->ev_flags & VMCMD_IMMUTABLE) uvm_map_immutable(&p->p_vmspace->vm_map, cmd->ev_addr, round_page(cmd->ev_addr + cmd->ev_len), 1); } return (error); } /* * vmcmd_map_zero(): * handle vmcmd which specifies a zero-filled address space region. */ int vmcmd_map_zero(struct proc *p, struct exec_vmcmd *cmd) { int error; if (cmd->ev_len == 0) return (0); KASSERT((cmd->ev_addr & PAGE_MASK) == 0); error = uvm_map(&p->p_vmspace->vm_map, &cmd->ev_addr, round_page(cmd->ev_len), NULL, UVM_UNKNOWN_OFFSET, 0, UVM_MAPFLAG(cmd->ev_prot, PROT_MASK, MAP_INHERIT_COPY, MADV_NORMAL, UVM_FLAG_FIXED|UVM_FLAG_COPYONW | (cmd->ev_flags & VMCMD_STACK ? UVM_FLAG_STACK : 0))); if (cmd->ev_flags & VMCMD_IMMUTABLE) uvm_map_immutable(&p->p_vmspace->vm_map, cmd->ev_addr, round_page(cmd->ev_addr + cmd->ev_len), 1); return error; } /* * vmcmd_mutable(): * handle vmcmd which changes an address space region.back to mutable */ int vmcmd_mutable(struct proc *p, struct exec_vmcmd *cmd) { if (cmd->ev_len == 0) return (0); /* ev_addr, ev_len may be misaligned, so maximize the region */ uvm_map_immutable(&p->p_vmspace->vm_map, trunc_page(cmd->ev_addr), round_page(cmd->ev_addr + cmd->ev_len), 0); return 0; } /* * vmcmd_randomize(): * handle vmcmd which specifies a randomized address space region. */ #define RANDOMIZE_CTX_THRESHOLD 512 int vmcmd_randomize(struct proc *p, struct exec_vmcmd *cmd) { int error; struct arc4random_ctx *ctx; char *buf; size_t sublen, off = 0; size_t len = cmd->ev_len; if (len == 0) return (0); if (len > ELF_RANDOMIZE_LIMIT) return (EINVAL); buf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK); if (len < RANDOMIZE_CTX_THRESHOLD) { arc4random_buf(buf, len); error = copyout(buf, (void *)cmd->ev_addr, len); explicit_bzero(buf, len); } else { ctx = arc4random_ctx_new(); do { sublen = MIN(len, PAGE_SIZE); arc4random_ctx_buf(ctx, buf, sublen); error = copyout(buf, (void *)cmd->ev_addr + off, sublen); if (error) break; off += sublen; len -= sublen; sched_pause(yield); } while (len); arc4random_ctx_free(ctx); explicit_bzero(buf, PAGE_SIZE); } free(buf, M_TEMP, PAGE_SIZE); return (error); } #ifndef MAXSSIZ_GUARD #define MAXSSIZ_GUARD (1024 * 1024) #endif /* * exec_setup_stack(): Set up the stack segment for an executable. * * Note that the ep_ssize parameter must be set to be the current stack * limit; this is adjusted in the body of execve() to yield the * appropriate stack segment usage once the argument length is * calculated. * * This function returns an int for uniformity with other (future) formats' * stack setup functions. They might have errors to return. */ int exec_setup_stack(struct proc *p, struct exec_package *epp) { vsize_t dist = 0; #ifdef MACHINE_STACK_GROWS_UP epp->ep_maxsaddr = USRSTACK; epp->ep_minsaddr = USRSTACK + MAXSSIZ; #else epp->ep_maxsaddr = USRSTACK - MAXSSIZ - MAXSSIZ_GUARD; epp->ep_minsaddr = USRSTACK; #endif epp->ep_ssize = round_page(lim_cur(RLIMIT_STACK)); #ifdef VM_MIN_STACK_ADDRESS dist = USRSTACK - MAXSSIZ - MAXSSIZ_GUARD - VM_MIN_STACK_ADDRESS; if (dist >> PAGE_SHIFT > 0xffffffff) dist = (vsize_t)arc4random() << PAGE_SHIFT; else dist = (vsize_t)arc4random_uniform(dist >> PAGE_SHIFT) << PAGE_SHIFT; #else if (stackgap_random != 0) { dist = arc4random() & (stackgap_random - 1); dist = trunc_page(dist); } #endif #ifdef MACHINE_STACK_GROWS_UP epp->ep_maxsaddr += dist; epp->ep_minsaddr += dist; #else epp->ep_maxsaddr -= dist; epp->ep_minsaddr -= dist; #endif /* * set up commands for stack. note that this takes *two*, one to * map the part of the stack which we can access, and one to map * the part which we can't. * * arguably, it could be made into one, but that would require the * addition of another mapping proc, which is unnecessary * * note that in memory, things assumed to be: 0 ....... ep_maxsaddr * <stack> ep_minsaddr */ #ifdef MACHINE_STACK_GROWS_UP NEW_VMCMD2(&epp->ep_vmcmds, vmcmd_map_zero, ((epp->ep_minsaddr - epp->ep_ssize) - epp->ep_maxsaddr), epp->ep_maxsaddr + epp->ep_ssize, NULLVP, 0, PROT_NONE, VMCMD_IMMUTABLE); NEW_VMCMD2(&epp->ep_vmcmds, vmcmd_map_zero, epp->ep_ssize, epp->ep_maxsaddr, NULLVP, 0, PROT_READ | PROT_WRITE, VMCMD_STACK | VMCMD_IMMUTABLE); #else NEW_VMCMD2(&epp->ep_vmcmds, vmcmd_map_zero, ((epp->ep_minsaddr - epp->ep_ssize) - epp->ep_maxsaddr), epp->ep_maxsaddr, NULLVP, 0, PROT_NONE, VMCMD_IMMUTABLE); NEW_VMCMD2(&epp->ep_vmcmds, vmcmd_map_zero, epp->ep_ssize, (epp->ep_minsaddr - epp->ep_ssize), NULLVP, 0, PROT_READ | PROT_WRITE, VMCMD_STACK | VMCMD_IMMUTABLE); #endif return (0); }
1545 4686 4699 5049 5058 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 /* $OpenBSD: subr_poison.c,v 1.15 2022/08/14 01:58:28 jsg Exp $ */ /* * Copyright (c) 2013 Ted Unangst <tedu@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> /* * The POISON is used as known text to copy into free objects so * that modifications after frees can be detected. */ #ifdef DEADBEEF0 #define POISON0 ((unsigned) DEADBEEF0) #else #define POISON0 ((unsigned) 0xdeadbeef) #endif #ifdef DEADBEEF1 #define POISON1 ((unsigned) DEADBEEF1) #else #define POISON1 ((unsigned) 0xdeafbead) #endif #define POISON_SIZE 64 uint32_t poison_value(void *v) { ulong l = (u_long)v; l = l >> PAGE_SHIFT; switch (l & 3) { case 0: return POISON0; case 1: return POISON1; case 2: return (POISON0 & 0xffff0000) | (~POISON0 & 0x0000ffff); case 3: return (POISON1 & 0xffff0000) | (~POISON1 & 0x0000ffff); } return 0; } void poison_mem(void *v, size_t len) { uint32_t *ip = v; size_t i; uint32_t poison; poison = poison_value(v); if (len > POISON_SIZE) len = POISON_SIZE; len = len / sizeof(*ip); for (i = 0; i < len; i++) ip[i] = poison; } int poison_check(void *v, size_t len, size_t *pidx, uint32_t *pval) { uint32_t *ip = v; size_t i; uint32_t poison; poison = poison_value(v); if (len > POISON_SIZE) len = POISON_SIZE; len = len / sizeof(*ip); for (i = 0; i < len; i++) { if (ip[i] != poison) { *pidx = i; *pval = poison; return 1; } } return 0; }
71 3 7 1140 1750 1748 1747 1749 1748 5 1747 1749 1719 3 1720 1710 1713 509 510 47 480 503 73 74 74 2 2 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 /* $OpenBSD: sched_bsd.c,v 1.91 2024/03/30 13:33:20 mpi Exp $ */ /* $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */ /*- * Copyright (c) 1982, 1986, 1990, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_synch.c 8.6 (Berkeley) 1/21/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/clockintr.h> #include <sys/proc.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/resourcevar.h> #include <uvm/uvm_extern.h> #include <sys/sched.h> #include <sys/timeout.h> #include <sys/smr.h> #include <sys/tracepoint.h> #ifdef KTRACE #include <sys/ktrace.h> #endif uint64_t roundrobin_period; /* [I] roundrobin period (ns) */ int lbolt; /* once a second sleep address */ #ifdef MULTIPROCESSOR struct __mp_lock sched_lock; #endif void update_loadavg(void *); void schedcpu(void *); uint32_t decay_aftersleep(uint32_t, uint32_t); extern struct cpuset sched_idle_cpus; /* * constants for averages over 1, 5, and 15 minutes when sampling at * 5 second intervals. */ static const fixpt_t cexp[3] = { 0.9200444146293232 * FSCALE, /* exp(-1/12) */ 0.9834714538216174 * FSCALE, /* exp(-1/60) */ 0.9944598480048967 * FSCALE, /* exp(-1/180) */ }; struct loadavg averunnable; /* * Force switch among equal priority processes every 100ms. */ void roundrobin(struct clockrequest *cr, void *cf, void *arg) { uint64_t count; struct cpu_info *ci = curcpu(); struct schedstate_percpu *spc = &ci->ci_schedstate; count = clockrequest_advance(cr, roundrobin_period); if (ci->ci_curproc != NULL) { if (spc->spc_schedflags & SPCF_SEENRR || count >= 2) { /* * The process has already been through a roundrobin * without switching and may be hogging the CPU. * Indicate that the process should yield. */ atomic_setbits_int(&spc->spc_schedflags, SPCF_SEENRR | SPCF_SHOULDYIELD); } else { atomic_setbits_int(&spc->spc_schedflags, SPCF_SEENRR); } } if (spc->spc_nrun || spc->spc_schedflags & SPCF_SHOULDYIELD) need_resched(ci); } /* * update_loadav: compute a tenex style load average of a quantity on * 1, 5, and 15 minute intervals. */ void update_loadavg(void *unused) { static struct timeout to = TIMEOUT_INITIALIZER(update_loadavg, NULL); CPU_INFO_ITERATOR cii; struct cpu_info *ci; u_int i, nrun = 0; CPU_INFO_FOREACH(cii, ci) { if (!cpuset_isset(&sched_idle_cpus, ci)) nrun++; nrun += ci->ci_schedstate.spc_nrun; } for (i = 0; i < 3; i++) { averunnable.ldavg[i] = (cexp[i] * averunnable.ldavg[i] + nrun * FSCALE * (FSCALE - cexp[i])) >> FSHIFT; } timeout_add_sec(&to, 5); } /* * Constants for digital decay and forget: * 90% of (p_estcpu) usage in 5 * loadav time * 95% of (p_pctcpu) usage in 60 seconds (load insensitive) * Note that, as ps(1) mentions, this can let percentages * total over 100% (I've seen 137.9% for 3 processes). * * Note that hardclock updates p_estcpu and p_cpticks independently. * * We wish to decay away 90% of p_estcpu in (5 * loadavg) seconds. * That is, the system wants to compute a value of decay such * that the following for loop: * for (i = 0; i < (5 * loadavg); i++) * p_estcpu *= decay; * will compute * p_estcpu *= 0.1; * for all values of loadavg: * * Mathematically this loop can be expressed by saying: * decay ** (5 * loadavg) ~= .1 * * The system computes decay as: * decay = (2 * loadavg) / (2 * loadavg + 1) * * We wish to prove that the system's computation of decay * will always fulfill the equation: * decay ** (5 * loadavg) ~= .1 * * If we compute b as: * b = 2 * loadavg * then * decay = b / (b + 1) * * We now need to prove two things: * 1) Given factor ** (5 * loadavg) ~= .1, prove factor == b/(b+1) * 2) Given b/(b+1) ** power ~= .1, prove power == (5 * loadavg) * * Facts: * For x close to zero, exp(x) =~ 1 + x, since * exp(x) = 0! + x**1/1! + x**2/2! + ... . * therefore exp(-1/b) =~ 1 - (1/b) = (b-1)/b. * For x close to zero, ln(1+x) =~ x, since * ln(1+x) = x - x**2/2 + x**3/3 - ... -1 < x < 1 * therefore ln(b/(b+1)) = ln(1 - 1/(b+1)) =~ -1/(b+1). * ln(.1) =~ -2.30 * * Proof of (1): * Solve (factor)**(power) =~ .1 given power (5*loadav): * solving for factor, * ln(factor) =~ (-2.30/5*loadav), or * factor =~ exp(-1/((5/2.30)*loadav)) =~ exp(-1/(2*loadav)) = * exp(-1/b) =~ (b-1)/b =~ b/(b+1). QED * * Proof of (2): * Solve (factor)**(power) =~ .1 given factor == (b/(b+1)): * solving for power, * power*ln(b/(b+1)) =~ -2.30, or * power =~ 2.3 * (b + 1) = 4.6*loadav + 2.3 =~ 5*loadav. QED * * Actual power values for the implemented algorithm are as follows: * loadav: 1 2 3 4 * power: 5.68 10.32 14.94 19.55 */ /* calculations for digital decay to forget 90% of usage in 5*loadav sec */ #define loadfactor(loadav) (2 * (loadav)) #define decay_cpu(loadfac, cpu) (((loadfac) * (cpu)) / ((loadfac) + FSCALE)) /* decay 95% of `p_pctcpu' in 60 seconds; see CCPU_SHIFT before changing */ fixpt_t ccpu = 0.95122942450071400909 * FSCALE; /* exp(-1/20) */ /* * If `ccpu' is not equal to `exp(-1/20)' and you still want to use the * faster/more-accurate formula, you'll have to estimate CCPU_SHIFT below * and possibly adjust FSHIFT in "param.h" so that (FSHIFT >= CCPU_SHIFT). * * To estimate CCPU_SHIFT for exp(-1/20), the following formula was used: * 1 - exp(-1/20) ~= 0.0487 ~= 0.0488 == 1 (fixed pt, *11* bits). * * If you don't want to bother with the faster/more-accurate formula, you * can set CCPU_SHIFT to (FSHIFT + 1) which will use a slower/less-accurate * (more general) method of calculating the %age of CPU used by a process. */ #define CCPU_SHIFT 11 /* * Recompute process priorities, every second. */ void schedcpu(void *unused) { static struct timeout to = TIMEOUT_INITIALIZER(schedcpu, NULL); fixpt_t loadfac = loadfactor(averunnable.ldavg[0]); struct proc *p; int s; unsigned int newcpu; LIST_FOREACH(p, &allproc, p_list) { /* * Idle threads are never placed on the runqueue, * therefore computing their priority is pointless. */ if (p->p_cpu != NULL && p->p_cpu->ci_schedstate.spc_idleproc == p) continue; /* * Increment sleep time (if sleeping). We ignore overflow. */ if (p->p_stat == SSLEEP || p->p_stat == SSTOP) p->p_slptime++; p->p_pctcpu = (p->p_pctcpu * ccpu) >> FSHIFT; /* * If the process has slept the entire second, * stop recalculating its priority until it wakes up. */ if (p->p_slptime > 1) continue; SCHED_LOCK(s); /* * p_pctcpu is only for diagnostic tools such as ps. */ #if (FSHIFT >= CCPU_SHIFT) p->p_pctcpu += (stathz == 100)? ((fixpt_t) p->p_cpticks) << (FSHIFT - CCPU_SHIFT): 100 * (((fixpt_t) p->p_cpticks) << (FSHIFT - CCPU_SHIFT)) / stathz; #else p->p_pctcpu += ((FSCALE - ccpu) * (p->p_cpticks * FSCALE / stathz)) >> FSHIFT; #endif p->p_cpticks = 0; newcpu = (u_int) decay_cpu(loadfac, p->p_estcpu); setpriority(p, newcpu, p->p_p->ps_nice); if (p->p_stat == SRUN && (p->p_runpri / SCHED_PPQ) != (p->p_usrpri / SCHED_PPQ)) { remrunqueue(p); setrunqueue(p->p_cpu, p, p->p_usrpri); } SCHED_UNLOCK(s); } wakeup(&lbolt); timeout_add_sec(&to, 1); } /* * Recalculate the priority of a process after it has slept for a while. * For all load averages >= 1 and max p_estcpu of 255, sleeping for at * least six times the loadfactor will decay p_estcpu to zero. */ uint32_t decay_aftersleep(uint32_t estcpu, uint32_t slptime) { fixpt_t loadfac = loadfactor(averunnable.ldavg[0]); uint32_t newcpu; if (slptime > 5 * loadfac) newcpu = 0; else { newcpu = estcpu; slptime--; /* the first time was done in schedcpu */ while (newcpu && --slptime) newcpu = decay_cpu(loadfac, newcpu); } return (newcpu); } /* * General yield call. Puts the current process back on its run queue and * performs a voluntary context switch. */ void yield(void) { struct proc *p = curproc; int s; SCHED_LOCK(s); setrunqueue(p->p_cpu, p, p->p_usrpri); p->p_ru.ru_nvcsw++; mi_switch(); SCHED_UNLOCK(s); } /* * General preemption call. Puts the current process back on its run queue * and performs an involuntary context switch. If a process is supplied, * we switch to that process. Otherwise, we use the normal process selection * criteria. */ void preempt(void) { struct proc *p = curproc; int s; SCHED_LOCK(s); setrunqueue(p->p_cpu, p, p->p_usrpri); p->p_ru.ru_nivcsw++; mi_switch(); SCHED_UNLOCK(s); } void mi_switch(void) { struct schedstate_percpu *spc = &curcpu()->ci_schedstate; struct proc *p = curproc; struct proc *nextproc; struct process *pr = p->p_p; struct timespec ts; #ifdef MULTIPROCESSOR int hold_count; int sched_count; #endif assertwaitok(); KASSERT(p->p_stat != SONPROC); SCHED_ASSERT_LOCKED(); #ifdef MULTIPROCESSOR /* * Release the kernel_lock, as we are about to yield the CPU. */ sched_count = __mp_release_all_but_one(&sched_lock); if (_kernel_lock_held()) hold_count = __mp_release_all(&kernel_lock); else hold_count = 0; #endif /* * Compute the amount of time during which the current * process was running, and add that to its total so far. */ nanouptime(&ts); if (timespeccmp(&ts, &spc->spc_runtime, <)) { #if 0 printf("uptime is not monotonic! " "ts=%lld.%09lu, runtime=%lld.%09lu\n", (long long)tv.tv_sec, tv.tv_nsec, (long long)spc->spc_runtime.tv_sec, spc->spc_runtime.tv_nsec); #endif timespecclear(&ts); } else { timespecsub(&ts, &spc->spc_runtime, &ts); } /* add the time counts for this thread to the process's total */ tuagg_locked(pr, p, &ts); /* Stop any optional clock interrupts. */ if (ISSET(spc->spc_schedflags, SPCF_ITIMER)) { atomic_clearbits_int(&spc->spc_schedflags, SPCF_ITIMER); clockintr_cancel(&spc->spc_itimer); } if (ISSET(spc->spc_schedflags, SPCF_PROFCLOCK)) { atomic_clearbits_int(&spc->spc_schedflags, SPCF_PROFCLOCK); clockintr_cancel(&spc->spc_profclock); } /* * Process is about to yield the CPU; clear the appropriate * scheduling flags. */ atomic_clearbits_int(&spc->spc_schedflags, SPCF_SWITCHCLEAR); nextproc = sched_chooseproc(); if (p != nextproc) { uvmexp.swtch++; TRACEPOINT(sched, off__cpu, nextproc->p_tid + THREAD_PID_OFFSET, nextproc->p_p->ps_pid); cpu_switchto(p, nextproc); TRACEPOINT(sched, on__cpu, NULL); } else { TRACEPOINT(sched, remain__cpu, NULL); p->p_stat = SONPROC; } clear_resched(curcpu()); SCHED_ASSERT_LOCKED(); /* * To preserve lock ordering, we need to release the sched lock * and grab it after we grab the big lock. * In the future, when the sched lock isn't recursive, we'll * just release it here. */ #ifdef MULTIPROCESSOR __mp_unlock(&sched_lock); #endif SCHED_ASSERT_UNLOCKED(); smr_idle(); /* * We're running again; record our new start time. We might * be running on a new CPU now, so refetch the schedstate_percpu * pointer. */ KASSERT(p->p_cpu == curcpu()); spc = &p->p_cpu->ci_schedstate; /* Start any optional clock interrupts needed by the thread. */ if (ISSET(p->p_p->ps_flags, PS_ITIMER)) { atomic_setbits_int(&spc->spc_schedflags, SPCF_ITIMER); clockintr_advance(&spc->spc_itimer, hardclock_period); } if (ISSET(p->p_p->ps_flags, PS_PROFIL)) { atomic_setbits_int(&spc->spc_schedflags, SPCF_PROFCLOCK); clockintr_advance(&spc->spc_profclock, profclock_period); } nanouptime(&spc->spc_runtime); #ifdef MULTIPROCESSOR /* * Reacquire the kernel_lock now. We do this after we've * released the scheduler lock to avoid deadlock, and before * we reacquire the interlock and the scheduler lock. */ if (hold_count) __mp_acquire_count(&kernel_lock, hold_count); __mp_acquire_count(&sched_lock, sched_count + 1); #endif } /* * Change process state to be runnable, * placing it on the run queue. */ void setrunnable(struct proc *p) { struct process *pr = p->p_p; u_char prio; SCHED_ASSERT_LOCKED(); switch (p->p_stat) { case 0: case SRUN: case SONPROC: case SDEAD: case SIDL: default: panic("setrunnable"); case SSTOP: /* * If we're being traced (possibly because someone attached us * while we were stopped), check for a signal from the debugger. */ if ((pr->ps_flags & PS_TRACED) != 0 && pr->ps_xsig != 0) atomic_setbits_int(&p->p_siglist, sigmask(pr->ps_xsig)); prio = p->p_usrpri; setrunqueue(NULL, p, prio); break; case SSLEEP: prio = p->p_slppri; /* if not yet asleep, don't add to runqueue */ if (ISSET(p->p_flag, P_WSLEEP)) return; setrunqueue(NULL, p, prio); TRACEPOINT(sched, wakeup, p->p_tid + THREAD_PID_OFFSET, p->p_p->ps_pid, CPU_INFO_UNIT(p->p_cpu)); break; } if (p->p_slptime > 1) { uint32_t newcpu; newcpu = decay_aftersleep(p->p_estcpu, p->p_slptime); setpriority(p, newcpu, pr->ps_nice); } p->p_slptime = 0; } /* * Compute the priority of a process. */ void setpriority(struct proc *p, uint32_t newcpu, uint8_t nice) { unsigned int newprio; newprio = min((PUSER + newcpu + NICE_WEIGHT * (nice - NZERO)), MAXPRI); SCHED_ASSERT_LOCKED(); p->p_estcpu = newcpu; p->p_usrpri = newprio; } /* * We adjust the priority of the current process. The priority of a process * gets worse as it accumulates CPU time. The cpu usage estimator (p_estcpu) * is increased here. The formula for computing priorities (in kern_synch.c) * will compute a different value each time p_estcpu increases. This can * cause a switch, but unless the priority crosses a PPQ boundary the actual * queue will not change. The cpu usage estimator ramps up quite quickly * when the process is running (linearly), and decays away exponentially, at * a rate which is proportionally slower when the system is busy. The basic * principle is that the system will 90% forget that the process used a lot * of CPU time in 5 * loadav seconds. This causes the system to favor * processes which haven't run much recently, and to round-robin among other * processes. */ void schedclock(struct proc *p) { struct cpu_info *ci = curcpu(); struct schedstate_percpu *spc = &ci->ci_schedstate; uint32_t newcpu; int s; if (p == spc->spc_idleproc || spc->spc_spinning) return; SCHED_LOCK(s); newcpu = ESTCPULIM(p->p_estcpu + 1); setpriority(p, newcpu, p->p_p->ps_nice); SCHED_UNLOCK(s); } void (*cpu_setperf)(int); #define PERFPOL_MANUAL 0 #define PERFPOL_AUTO 1 #define PERFPOL_HIGH 2 int perflevel = 100; int perfpolicy = PERFPOL_AUTO; #ifndef SMALL_KERNEL /* * The code below handles CPU throttling. */ #include <sys/sysctl.h> void setperf_auto(void *); struct timeout setperf_to = TIMEOUT_INITIALIZER(setperf_auto, NULL); extern int hw_power; void setperf_auto(void *v) { static uint64_t *idleticks, *totalticks; static int downbeats; int i, j = 0; int speedup = 0; CPU_INFO_ITERATOR cii; struct cpu_info *ci; uint64_t idle, total, allidle = 0, alltotal = 0; if (perfpolicy != PERFPOL_AUTO) return; if (cpu_setperf == NULL) return; if (hw_power) { speedup = 1; goto faster; } if (!idleticks) if (!(idleticks = mallocarray(ncpusfound, sizeof(*idleticks), M_DEVBUF, M_NOWAIT | M_ZERO))) return; if (!totalticks) if (!(totalticks = mallocarray(ncpusfound, sizeof(*totalticks), M_DEVBUF, M_NOWAIT | M_ZERO))) { free(idleticks, M_DEVBUF, sizeof(*idleticks) * ncpusfound); return; } CPU_INFO_FOREACH(cii, ci) { if (!cpu_is_online(ci)) continue; total = 0; for (i = 0; i < CPUSTATES; i++) { total += ci->ci_schedstate.spc_cp_time[i]; } total -= totalticks[j]; idle = ci->ci_schedstate.spc_cp_time[CP_IDLE] - idleticks[j]; if (idle < total / 3) speedup = 1; alltotal += total; allidle += idle; idleticks[j] += idle; totalticks[j] += total; j++; } if (allidle < alltotal / 2) speedup = 1; if (speedup && downbeats < 5) downbeats++; if (speedup && perflevel != 100) { faster: perflevel = 100; cpu_setperf(perflevel); } else if (!speedup && perflevel != 0 && --downbeats <= 0) { perflevel = 0; cpu_setperf(perflevel); } timeout_add_msec(&setperf_to, 100); } int sysctl_hwsetperf(void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int err; if (!cpu_setperf) return EOPNOTSUPP; if (perfpolicy != PERFPOL_MANUAL) return sysctl_rdint(oldp, oldlenp, newp, perflevel); err = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &perflevel, 0, 100); if (err) return err; if (newp != NULL) cpu_setperf(perflevel); return 0; } int sysctl_hwperfpolicy(void *oldp, size_t *oldlenp, void *newp, size_t newlen) { char policy[32]; int err; if (!cpu_setperf) return EOPNOTSUPP; switch (perfpolicy) { case PERFPOL_MANUAL: strlcpy(policy, "manual", sizeof(policy)); break; case PERFPOL_AUTO: strlcpy(policy, "auto", sizeof(policy)); break; case PERFPOL_HIGH: strlcpy(policy, "high", sizeof(policy)); break; default: strlcpy(policy, "unknown", sizeof(policy)); break; } if (newp == NULL) return sysctl_rdstring(oldp, oldlenp, newp, policy); err = sysctl_string(oldp, oldlenp, newp, newlen, policy, sizeof(policy)); if (err) return err; if (strcmp(policy, "manual") == 0) perfpolicy = PERFPOL_MANUAL; else if (strcmp(policy, "auto") == 0) perfpolicy = PERFPOL_AUTO; else if (strcmp(policy, "high") == 0) perfpolicy = PERFPOL_HIGH; else return EINVAL; if (perfpolicy == PERFPOL_AUTO) { timeout_add_msec(&setperf_to, 200); } else if (perfpolicy == PERFPOL_HIGH) { perflevel = 100; cpu_setperf(perflevel); } return 0; } #endif /* * Start the scheduler's periodic timeouts. */ void scheduler_start(void) { schedcpu(NULL); update_loadavg(NULL); #ifndef SMALL_KERNEL if (perfpolicy == PERFPOL_AUTO) timeout_add_msec(&setperf_to, 200); #endif }
10 1 6 4 7 4 5 8 4 11 7 4 1 7 5 1 1 4 2 5 1 4 5 742 742 21 21 18 18 955 957 18 18 409 410 1254 1247 904 899 373 374 129 128 8 160 159 102 101 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 /* $OpenBSD: kern_pledge.c,v 1.314 2024/05/18 05:20:22 guenther Exp $ */ /* * Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org> * Copyright (c) 2015 Theo de Raadt <deraadt@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/mount.h> #include <sys/proc.h> #include <sys/mutex.h> #include <sys/fcntl.h> #include <sys/file.h> #include <sys/namei.h> #include <sys/socketvar.h> #include <sys/vnode.h> #include <sys/mman.h> #include <sys/sysctl.h> #include <sys/syslog.h> #include <sys/ktrace.h> #include <sys/acct.h> #include <sys/swap.h> #include <sys/ioctl.h> #include <sys/termios.h> #include <sys/tty.h> #include <sys/device.h> #include <sys/disklabel.h> #include <sys/dkio.h> #include <sys/mtio.h> #include <sys/audioio.h> #include <sys/videoio.h> #include <net/bpf.h> #include <net/route.h> #include <net/if.h> #include <net/if_var.h> #include <netinet/in.h> #include <netinet6/in6_var.h> #include <netinet6/nd6.h> #include <netinet/tcp.h> #include <net/pfvar.h> #include <sys/conf.h> #include <sys/specdev.h> #include <sys/signal.h> #include <sys/signalvar.h> #include <sys/syscall.h> #include <sys/syscallargs.h> #include <sys/systm.h> #include <dev/biovar.h> #define PLEDGENAMES #include <sys/pledge.h> #include "audio.h" #include "bpfilter.h" #include "pf.h" #include "video.h" #include "pty.h" #if defined(__amd64__) #include "vmm.h" #if NVMM > 0 #include <machine/conf.h> #endif #endif #include "drm.h" uint64_t pledgereq_flags(const char *req); int parsepledges(struct proc *p, const char *kname, const char *promises, u_int64_t *fp); int canonpath(const char *input, char *buf, size_t bufsize); void unveil_destroy(struct process *ps); /* #define DEBUG_PLEDGE */ #ifdef DEBUG_PLEDGE int debug_pledge = 1; #define DPRINTF(x...) do { if (debug_pledge) printf(x); } while (0) #define DNPRINTF(n,x...) do { if (debug_pledge >= (n)) printf(x); } while (0) #else #define DPRINTF(x...) #define DNPRINTF(n,x...) #endif /* * Ordered in blocks starting with least risky and most required. */ const uint64_t pledge_syscalls[SYS_MAXSYSCALL] = { /* * Minimum required */ [SYS_exit] = PLEDGE_ALWAYS, [SYS_kbind] = PLEDGE_ALWAYS, [SYS___get_tcb] = PLEDGE_ALWAYS, [SYS___set_tcb] = PLEDGE_ALWAYS, [SYS_pledge] = PLEDGE_ALWAYS, [SYS_sendsyslog] = PLEDGE_ALWAYS, /* stack protector reporting */ [SYS_thrkill] = PLEDGE_ALWAYS, /* raise, abort, stack pro */ [SYS_utrace] = PLEDGE_ALWAYS, /* ltrace(1) from ld.so */ [SYS_pinsyscalls] = PLEDGE_ALWAYS, /* "getting" information about self is considered safe */ [SYS_getuid] = PLEDGE_STDIO, [SYS_geteuid] = PLEDGE_STDIO, [SYS_getresuid] = PLEDGE_STDIO, [SYS_getgid] = PLEDGE_STDIO, [SYS_getegid] = PLEDGE_STDIO, [SYS_getresgid] = PLEDGE_STDIO, [SYS_getgroups] = PLEDGE_STDIO, [SYS_getlogin_r] = PLEDGE_STDIO, [SYS_getpgrp] = PLEDGE_STDIO, [SYS_getpgid] = PLEDGE_STDIO, [SYS_getppid] = PLEDGE_STDIO, [SYS_getsid] = PLEDGE_STDIO, [SYS_getthrid] = PLEDGE_STDIO, [SYS_getrlimit] = PLEDGE_STDIO, [SYS_getrtable] = PLEDGE_STDIO, [SYS_gettimeofday] = PLEDGE_STDIO, [SYS_getdtablecount] = PLEDGE_STDIO, [SYS_getrusage] = PLEDGE_STDIO, [SYS_issetugid] = PLEDGE_STDIO, [SYS_clock_getres] = PLEDGE_STDIO, [SYS_clock_gettime] = PLEDGE_STDIO, [SYS_getpid] = PLEDGE_STDIO, /* * Almost exclusively read-only, Very narrow subset. * Use of "route", "inet", "dns", "ps", or "vminfo" * expands access. */ [SYS_sysctl] = PLEDGE_STDIO, /* For moncontrol(3). Only allowed to disable profiling. */ [SYS_profil] = PLEDGE_STDIO, /* Support for malloc(3) family of operations */ [SYS_getentropy] = PLEDGE_STDIO, [SYS_madvise] = PLEDGE_STDIO, [SYS_minherit] = PLEDGE_STDIO, [SYS_mmap] = PLEDGE_STDIO, [SYS_mprotect] = PLEDGE_STDIO, [SYS_mimmutable] = PLEDGE_STDIO, [SYS_mquery] = PLEDGE_STDIO, [SYS_munmap] = PLEDGE_STDIO, [SYS_msync] = PLEDGE_STDIO, [SYS_break] = PLEDGE_STDIO, [SYS_umask] = PLEDGE_STDIO, /* read/write operations */ [SYS_read] = PLEDGE_STDIO, [SYS_readv] = PLEDGE_STDIO, [SYS_pread] = PLEDGE_STDIO, [SYS_preadv] = PLEDGE_STDIO, [SYS_write] = PLEDGE_STDIO, [SYS_writev] = PLEDGE_STDIO, [SYS_pwrite] = PLEDGE_STDIO, [SYS_pwritev] = PLEDGE_STDIO, [SYS_recvmsg] = PLEDGE_STDIO, [SYS_recvmmsg] = PLEDGE_STDIO, [SYS_recvfrom] = PLEDGE_STDIO, [SYS_ftruncate] = PLEDGE_STDIO, [SYS_lseek] = PLEDGE_STDIO, [SYS_fpathconf] = PLEDGE_STDIO, /* * Address selection required a network pledge ("inet", * "unix", "dns". */ [SYS_sendto] = PLEDGE_STDIO, /* * Address specification required a network pledge ("inet", * "unix", "dns". SCM_RIGHTS requires "sendfd" or "recvfd". */ [SYS_sendmsg] = PLEDGE_STDIO, [SYS_sendmmsg] = PLEDGE_STDIO, /* Common signal operations */ [SYS_nanosleep] = PLEDGE_STDIO, [SYS_sigaltstack] = PLEDGE_STDIO, [SYS_sigprocmask] = PLEDGE_STDIO, [SYS_sigsuspend] = PLEDGE_STDIO, [SYS_sigaction] = PLEDGE_STDIO, [SYS_sigreturn] = PLEDGE_STDIO, [SYS_sigpending] = PLEDGE_STDIO, [SYS_getitimer] = PLEDGE_STDIO, [SYS_setitimer] = PLEDGE_STDIO, /* * To support event driven programming. */ [SYS_poll] = PLEDGE_STDIO, [SYS_ppoll] = PLEDGE_STDIO, [SYS_kevent] = PLEDGE_STDIO, [SYS_kqueue] = PLEDGE_STDIO, [SYS_kqueue1] = PLEDGE_STDIO, [SYS_select] = PLEDGE_STDIO, [SYS_pselect] = PLEDGE_STDIO, [SYS_fstat] = PLEDGE_STDIO, [SYS_fsync] = PLEDGE_STDIO, [SYS_setsockopt] = PLEDGE_STDIO, /* narrow whitelist */ [SYS_getsockopt] = PLEDGE_STDIO, /* narrow whitelist */ /* F_SETOWN requires PLEDGE_PROC */ [SYS_fcntl] = PLEDGE_STDIO, [SYS_close] = PLEDGE_STDIO, [SYS_dup] = PLEDGE_STDIO, [SYS_dup2] = PLEDGE_STDIO, [SYS_dup3] = PLEDGE_STDIO, [SYS_closefrom] = PLEDGE_STDIO, [SYS_shutdown] = PLEDGE_STDIO, [SYS_fchdir] = PLEDGE_STDIO, /* XXX consider tightening */ [SYS_pipe] = PLEDGE_STDIO, [SYS_pipe2] = PLEDGE_STDIO, [SYS_socketpair] = PLEDGE_STDIO, [SYS_wait4] = PLEDGE_STDIO, [SYS_waitid] = PLEDGE_STDIO, /* * Can kill self with "stdio". Killing another pid * requires "proc" */ [SYS_kill] = PLEDGE_STDIO, /* * FIONREAD/FIONBIO for "stdio" * Other ioctl are selectively allowed based upon other pledges. */ [SYS_ioctl] = PLEDGE_STDIO, /* * Path access/creation calls encounter many extensive * checks done during pledge_namei() */ [SYS_open] = PLEDGE_STDIO, [SYS_stat] = PLEDGE_STDIO, [SYS_access] = PLEDGE_STDIO, [SYS_readlink] = PLEDGE_STDIO, [SYS___realpath] = PLEDGE_STDIO, [SYS_adjtime] = PLEDGE_STDIO, /* setting requires "settime" */ [SYS_adjfreq] = PLEDGE_SETTIME, [SYS_settimeofday] = PLEDGE_SETTIME, /* * Needed by threaded programs * XXX should we have a new "threads"? */ [SYS___tfork] = PLEDGE_STDIO, [SYS_sched_yield] = PLEDGE_STDIO, [SYS_futex] = PLEDGE_STDIO, [SYS___thrsleep] = PLEDGE_STDIO, [SYS___thrwakeup] = PLEDGE_STDIO, [SYS___threxit] = PLEDGE_STDIO, [SYS___thrsigdivert] = PLEDGE_STDIO, [SYS_getthrname] = PLEDGE_STDIO, [SYS_setthrname] = PLEDGE_STDIO, [SYS_fork] = PLEDGE_PROC, [SYS_vfork] = PLEDGE_PROC, [SYS_setpgid] = PLEDGE_PROC, [SYS_setsid] = PLEDGE_PROC, [SYS_setrlimit] = PLEDGE_PROC | PLEDGE_ID, [SYS_getpriority] = PLEDGE_PROC | PLEDGE_ID, [SYS_setpriority] = PLEDGE_PROC | PLEDGE_ID, [SYS_setuid] = PLEDGE_ID, [SYS_seteuid] = PLEDGE_ID, [SYS_setreuid] = PLEDGE_ID, [SYS_setresuid] = PLEDGE_ID, [SYS_setgid] = PLEDGE_ID, [SYS_setegid] = PLEDGE_ID, [SYS_setregid] = PLEDGE_ID, [SYS_setresgid] = PLEDGE_ID, [SYS_setgroups] = PLEDGE_ID, [SYS_setlogin] = PLEDGE_ID, [SYS_setrtable] = PLEDGE_ID, [SYS_unveil] = PLEDGE_UNVEIL, [SYS_execve] = PLEDGE_EXEC, [SYS_chdir] = PLEDGE_RPATH, [SYS_openat] = PLEDGE_RPATH | PLEDGE_WPATH, [SYS_fstatat] = PLEDGE_RPATH | PLEDGE_WPATH, [SYS_faccessat] = PLEDGE_RPATH | PLEDGE_WPATH, [SYS_readlinkat] = PLEDGE_RPATH | PLEDGE_WPATH, [SYS_lstat] = PLEDGE_RPATH | PLEDGE_WPATH | PLEDGE_TMPPATH, [SYS_truncate] = PLEDGE_WPATH, [SYS_rename] = PLEDGE_RPATH | PLEDGE_CPATH, [SYS_rmdir] = PLEDGE_CPATH, [SYS_renameat] = PLEDGE_CPATH, [SYS_link] = PLEDGE_CPATH, [SYS_linkat] = PLEDGE_CPATH, [SYS_symlink] = PLEDGE_CPATH, [SYS_symlinkat] = PLEDGE_CPATH, [SYS_unlink] = PLEDGE_CPATH | PLEDGE_TMPPATH, [SYS_unlinkat] = PLEDGE_CPATH, [SYS_mkdir] = PLEDGE_CPATH, [SYS_mkdirat] = PLEDGE_CPATH, [SYS_mkfifo] = PLEDGE_DPATH, [SYS_mkfifoat] = PLEDGE_DPATH, [SYS_mknod] = PLEDGE_DPATH, [SYS_mknodat] = PLEDGE_DPATH, [SYS_revoke] = PLEDGE_TTY, /* also requires PLEDGE_RPATH */ /* * Classify as RPATH|WPATH, because of path information leakage. * WPATH due to unknown use of mk*temp(3) on non-/tmp paths.. */ [SYS___getcwd] = PLEDGE_RPATH | PLEDGE_WPATH, /* Classify as RPATH, because these leak path information */ [SYS_getdents] = PLEDGE_RPATH, [SYS_getfsstat] = PLEDGE_RPATH, [SYS_statfs] = PLEDGE_RPATH, [SYS_fstatfs] = PLEDGE_RPATH, [SYS_pathconf] = PLEDGE_RPATH, [SYS_pathconfat] = PLEDGE_RPATH, [SYS_utimes] = PLEDGE_FATTR, [SYS_futimes] = PLEDGE_FATTR, [SYS_utimensat] = PLEDGE_FATTR, [SYS_futimens] = PLEDGE_FATTR, [SYS_chmod] = PLEDGE_FATTR, [SYS_fchmod] = PLEDGE_FATTR, [SYS_fchmodat] = PLEDGE_FATTR, [SYS_chflags] = PLEDGE_FATTR, [SYS_chflagsat] = PLEDGE_FATTR, [SYS_fchflags] = PLEDGE_FATTR, [SYS_chown] = PLEDGE_CHOWN, [SYS_fchownat] = PLEDGE_CHOWN, [SYS_lchown] = PLEDGE_CHOWN, [SYS_fchown] = PLEDGE_CHOWN, [SYS_socket] = PLEDGE_INET | PLEDGE_UNIX | PLEDGE_DNS, [SYS_connect] = PLEDGE_INET | PLEDGE_UNIX | PLEDGE_DNS, [SYS_bind] = PLEDGE_INET | PLEDGE_UNIX | PLEDGE_DNS, [SYS_getsockname] = PLEDGE_INET | PLEDGE_UNIX | PLEDGE_DNS, [SYS_listen] = PLEDGE_INET | PLEDGE_UNIX, [SYS_accept4] = PLEDGE_INET | PLEDGE_UNIX, [SYS_accept] = PLEDGE_INET | PLEDGE_UNIX, [SYS_getpeername] = PLEDGE_INET | PLEDGE_UNIX, [SYS_flock] = PLEDGE_FLOCK, [SYS_ypconnect] = PLEDGE_GETPW, [SYS_swapctl] = PLEDGE_VMINFO, }; static const struct { char *name; uint64_t flags; } pledgereq[] = { { "audio", PLEDGE_AUDIO }, { "bpf", PLEDGE_BPF }, { "chown", PLEDGE_CHOWN | PLEDGE_CHOWNUID }, { "cpath", PLEDGE_CPATH }, { "disklabel", PLEDGE_DISKLABEL }, { "dns", PLEDGE_DNS }, { "dpath", PLEDGE_DPATH }, { "drm", PLEDGE_DRM }, { "error", PLEDGE_ERROR }, { "exec", PLEDGE_EXEC }, { "fattr", PLEDGE_FATTR | PLEDGE_CHOWN }, { "flock", PLEDGE_FLOCK }, { "getpw", PLEDGE_GETPW }, { "id", PLEDGE_ID }, { "inet", PLEDGE_INET }, { "mcast", PLEDGE_MCAST }, { "pf", PLEDGE_PF }, { "proc", PLEDGE_PROC }, { "prot_exec", PLEDGE_PROTEXEC }, { "ps", PLEDGE_PS }, { "recvfd", PLEDGE_RECVFD }, { "route", PLEDGE_ROUTE }, { "rpath", PLEDGE_RPATH }, { "sendfd", PLEDGE_SENDFD }, { "settime", PLEDGE_SETTIME }, { "stdio", PLEDGE_STDIO }, { "tape", PLEDGE_TAPE }, { "tmppath", PLEDGE_TMPPATH }, { "tty", PLEDGE_TTY }, { "unix", PLEDGE_UNIX }, { "unveil", PLEDGE_UNVEIL }, { "video", PLEDGE_VIDEO }, { "vminfo", PLEDGE_VMINFO }, { "vmm", PLEDGE_VMM }, { "wpath", PLEDGE_WPATH }, { "wroute", PLEDGE_WROUTE }, }; int parsepledges(struct proc *p, const char *kname, const char *promises, u_int64_t *fp) { size_t rbuflen; char *rbuf, *rp, *pn; u_int64_t flags = 0, f; int error; rbuf = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); error = copyinstr(promises, rbuf, MAXPATHLEN, &rbuflen); if (error) { free(rbuf, M_TEMP, MAXPATHLEN); return (error); } #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrstruct(p, kname, rbuf, rbuflen-1); #endif for (rp = rbuf; rp && *rp; rp = pn) { pn = strchr(rp, ' '); /* find terminator */ if (pn) { while (*pn == ' ') *pn++ = '\0'; } if ((f = pledgereq_flags(rp)) == 0) { free(rbuf, M_TEMP, MAXPATHLEN); return (EINVAL); } flags |= f; } free(rbuf, M_TEMP, MAXPATHLEN); *fp = flags; return 0; } int sys_pledge(struct proc *p, void *v, register_t *retval) { struct sys_pledge_args /* { syscallarg(const char *)promises; syscallarg(const char *)execpromises; } */ *uap = v; struct process *pr = p->p_p; uint64_t promises, execpromises; int error; int unveil_cleanup = 0; /* Check for any error in user input */ if (SCARG(uap, promises)) { error = parsepledges(p, "pledgereq", SCARG(uap, promises), &promises); if (error) return (error); } if (SCARG(uap, execpromises)) { error = parsepledges(p, "pledgeexecreq", SCARG(uap, execpromises), &execpromises); if (error) return (error); } mtx_enter(&pr->ps_mtx); /* Check for any error wrt current promises */ if (SCARG(uap, promises)) { /* In "error" mode, ignore promise increase requests, * but accept promise decrease requests */ if (ISSET(pr->ps_flags, PS_PLEDGE) && (pr->ps_pledge & PLEDGE_ERROR)) promises &= (pr->ps_pledge & PLEDGE_USERSET); /* Only permit reductions */ if (ISSET(pr->ps_flags, PS_PLEDGE) && (((promises | pr->ps_pledge) != pr->ps_pledge))) { mtx_leave(&pr->ps_mtx); return (EPERM); } } if (SCARG(uap, execpromises)) { /* Only permit reductions */ if (ISSET(pr->ps_flags, PS_EXECPLEDGE) && (((execpromises | pr->ps_execpledge) != pr->ps_execpledge))) { mtx_leave(&pr->ps_mtx); return (EPERM); } } /* Set up promises */ if (SCARG(uap, promises)) { pr->ps_pledge = promises; atomic_setbits_int(&pr->ps_flags, PS_PLEDGE); if ((pr->ps_pledge & (PLEDGE_RPATH | PLEDGE_WPATH | PLEDGE_CPATH | PLEDGE_DPATH | PLEDGE_TMPPATH | PLEDGE_EXEC | PLEDGE_UNIX | PLEDGE_UNVEIL)) == 0) unveil_cleanup = 1; } if (SCARG(uap, execpromises)) { pr->ps_execpledge = execpromises; atomic_setbits_int(&pr->ps_flags, PS_EXECPLEDGE); } mtx_leave(&pr->ps_mtx); if (unveil_cleanup) { /* * Kill off unveil and drop unveil vnode refs if we no * longer are holding any path-accessing pledge */ KERNEL_LOCK(); unveil_destroy(pr); KERNEL_UNLOCK(); } return (0); } int pledge_syscall(struct proc *p, int code, uint64_t *tval) { p->p_pledge_syscall = code; *tval = 0; if (code < 0 || code > SYS_MAXSYSCALL - 1) return (EINVAL); if (pledge_syscalls[code] == PLEDGE_ALWAYS) return (0); if (p->p_p->ps_pledge & pledge_syscalls[code]) return (0); *tval = pledge_syscalls[code]; return (EPERM); } int pledge_fail(struct proc *p, int error, uint64_t code) { const char *codes = ""; int i; /* Print first matching pledge */ for (i = 0; code && pledgenames[i].bits != 0; i++) if (pledgenames[i].bits & code) { codes = pledgenames[i].name; break; } #ifdef KTRACE if (KTRPOINT(p, KTR_PLEDGE)) ktrpledge(p, error, code, p->p_pledge_syscall); #endif if (p->p_p->ps_pledge & PLEDGE_ERROR) return (ENOSYS); KERNEL_LOCK(); log(LOG_ERR, "%s[%d]: pledge \"%s\", syscall %d\n", p->p_p->ps_comm, p->p_p->ps_pid, codes, p->p_pledge_syscall); p->p_p->ps_acflag |= APLEDGE; /* Try to stop threads immediately, because this process is suspect */ if (P_HASSIBLING(p)) single_thread_set(p, SINGLE_UNWIND | SINGLE_DEEP); /* Send uncatchable SIGABRT for coredump */ sigabort(p); p->p_p->ps_pledge = 0; /* Disable all PLEDGE_ flags */ KERNEL_UNLOCK(); return (error); } /* * Need to make it more obvious that one cannot get through here * without the right flags set */ int pledge_namei(struct proc *p, struct nameidata *ni, char *origpath) { char path[PATH_MAX]; uint64_t pledge; int error; if ((p->p_p->ps_flags & PS_PLEDGE) == 0 || (p->p_p->ps_flags & PS_COREDUMP)) return (0); pledge = READ_ONCE(p->p_p->ps_pledge); if (ni->ni_pledge == 0) panic("pledge_namei: ni_pledge"); /* * We set the BYPASSUNVEIL flag to skip unveil checks * as necessary */ /* Doing a permitted execve() */ if ((ni->ni_pledge & PLEDGE_EXEC) && (pledge & PLEDGE_EXEC)) return (0); error = canonpath(origpath, path, sizeof(path)); if (error) return (error); /* Detect what looks like a mkstemp(3) family operation */ if ((pledge & PLEDGE_TMPPATH) && (p->p_pledge_syscall == SYS_open) && (ni->ni_pledge & PLEDGE_CPATH) && strncmp(path, "/tmp/", sizeof("/tmp/") - 1) == 0) { ni->ni_cnd.cn_flags |= BYPASSUNVEIL; return (0); } /* Allow unlinking of a mkstemp(3) file... * Good opportunity for strict checks here. */ if ((pledge & PLEDGE_TMPPATH) && (p->p_pledge_syscall == SYS_unlink) && strncmp(path, "/tmp/", sizeof("/tmp/") - 1) == 0) { ni->ni_cnd.cn_flags |= BYPASSUNVEIL; return (0); } /* Whitelisted paths */ switch (p->p_pledge_syscall) { case SYS_access: /* tzset() needs this. */ if (ni->ni_pledge == PLEDGE_RPATH && strcmp(path, "/etc/localtime") == 0) { ni->ni_cnd.cn_flags |= BYPASSUNVEIL; return (0); } break; case SYS_open: /* daemon(3) or other such functions */ if ((ni->ni_pledge & ~(PLEDGE_RPATH | PLEDGE_WPATH)) == 0 && strcmp(path, "/dev/null") == 0) { ni->ni_cnd.cn_flags |= BYPASSUNVEIL; return (0); } /* readpassphrase(3), getpass(3) */ if ((pledge & PLEDGE_TTY) && (ni->ni_pledge & ~(PLEDGE_RPATH | PLEDGE_WPATH)) == 0 && strcmp(path, "/dev/tty") == 0) { ni->ni_cnd.cn_flags |= BYPASSUNVEIL; return (0); } /* getpw* and friends need a few files */ if ((ni->ni_pledge == PLEDGE_RPATH) && (pledge & PLEDGE_GETPW)) { if (strcmp(path, "/etc/spwd.db") == 0) return (EPERM); /* don't call pledge_fail */ if (strcmp(path, "/etc/pwd.db") == 0) { ni->ni_cnd.cn_flags |= BYPASSUNVEIL; return (0); } if (strcmp(path, "/etc/group") == 0) { ni->ni_cnd.cn_flags |= BYPASSUNVEIL; return (0); } if (strcmp(path, "/etc/netid") == 0) { ni->ni_cnd.cn_flags |= BYPASSUNVEIL; return (0); } } /* DNS needs /etc/{resolv.conf,hosts,services,protocols}. */ if ((ni->ni_pledge == PLEDGE_RPATH) && (pledge & PLEDGE_DNS)) { if (strcmp(path, "/etc/resolv.conf") == 0) { ni->ni_cnd.cn_flags |= BYPASSUNVEIL; return (0); } if (strcmp(path, "/etc/hosts") == 0) { ni->ni_cnd.cn_flags |= BYPASSUNVEIL; return (0); } if (strcmp(path, "/etc/services") == 0) { ni->ni_cnd.cn_flags |= BYPASSUNVEIL; return (0); } if (strcmp(path, "/etc/protocols") == 0) { ni->ni_cnd.cn_flags |= BYPASSUNVEIL; return (0); } } /* tzset() needs these. */ if ((ni->ni_pledge == PLEDGE_RPATH) && strncmp(path, "/usr/share/zoneinfo/", sizeof("/usr/share/zoneinfo/") - 1) == 0) { ni->ni_cnd.cn_flags |= BYPASSUNVEIL; return (0); } if ((ni->ni_pledge == PLEDGE_RPATH) && strcmp(path, "/etc/localtime") == 0) { ni->ni_cnd.cn_flags |= BYPASSUNVEIL; return (0); } break; case SYS_stat: /* DNS needs /etc/{resolv.conf,hosts}. */ if ((ni->ni_pledge == PLEDGE_RPATH) && (pledge & PLEDGE_DNS)) { if (strcmp(path, "/etc/resolv.conf") == 0) { ni->ni_cnd.cn_flags |= BYPASSUNVEIL; return (0); } if (strcmp(path, "/etc/hosts") == 0) { ni->ni_cnd.cn_flags |= BYPASSUNVEIL; return (0); } } break; } /* * Ensure each flag of ni_pledge has counterpart allowing it in * ps_pledge. */ if (ni->ni_pledge & ~pledge) return (pledge_fail(p, EPERM, (ni->ni_pledge & ~pledge))); /* continue, and check unveil if present */ return (0); } /* * Only allow reception of safe file descriptors. */ int pledge_recvfd(struct proc *p, struct file *fp) { struct vnode *vp; if ((p->p_p->ps_flags & PS_PLEDGE) == 0) return (0); if ((p->p_p->ps_pledge & PLEDGE_RECVFD) == 0) return pledge_fail(p, EPERM, PLEDGE_RECVFD); switch (fp->f_type) { case DTYPE_SOCKET: case DTYPE_PIPE: case DTYPE_DMABUF: case DTYPE_SYNC: return (0); case DTYPE_VNODE: vp = fp->f_data; if (vp->v_type != VDIR) return (0); } return pledge_fail(p, EINVAL, PLEDGE_RECVFD); } /* * Only allow sending of safe file descriptors. */ int pledge_sendfd(struct proc *p, struct file *fp) { struct vnode *vp; if ((p->p_p->ps_flags & PS_PLEDGE) == 0) return (0); if ((p->p_p->ps_pledge & PLEDGE_SENDFD) == 0) return pledge_fail(p, EPERM, PLEDGE_SENDFD); switch (fp->f_type) { case DTYPE_SOCKET: case DTYPE_PIPE: case DTYPE_DMABUF: case DTYPE_SYNC: return (0); case DTYPE_VNODE: vp = fp->f_data; if (vp->v_type != VDIR) return (0); break; } return pledge_fail(p, EINVAL, PLEDGE_SENDFD); } int pledge_sysctl(struct proc *p, int miblen, int *mib, void *new) { char buf[80]; uint64_t pledge; int i; if ((p->p_p->ps_flags & PS_PLEDGE) == 0) return (0); pledge = READ_ONCE(p->p_p->ps_pledge); if (new) return pledge_fail(p, EFAULT, 0); /* routing table observation */ if ((pledge & PLEDGE_ROUTE)) { if ((miblen == 6 || miblen == 7) && mib[0] == CTL_NET && mib[1] == PF_ROUTE && mib[2] == 0 && mib[4] == NET_RT_DUMP) return (0); if (miblen == 6 && mib[0] == CTL_NET && mib[1] == PF_ROUTE && mib[2] == 0 && (mib[3] == 0 || mib[3] == AF_INET6 || mib[3] == AF_INET) && (mib[4] == NET_RT_TABLE || mib[4] == NET_RT_SOURCE)) return (0); if (miblen == 7 && /* exposes MACs */ mib[0] == CTL_NET && mib[1] == PF_ROUTE && mib[2] == 0 && (mib[3] == 0 || mib[3] == AF_INET6 || mib[3] == AF_INET) && mib[4] == NET_RT_FLAGS && mib[5] == RTF_LLINFO) return (0); } if ((pledge & PLEDGE_WROUTE)) { if (miblen == 4 && mib[0] == CTL_NET && mib[1] == PF_INET6 && mib[2] == IPPROTO_IPV6 && mib[3] == IPV6CTL_SOIIKEY) return (0); } if (pledge & (PLEDGE_PS | PLEDGE_VMINFO)) { if (miblen == 2 && /* kern.fscale */ mib[0] == CTL_KERN && mib[1] == KERN_FSCALE) return (0); if (miblen == 2 && /* kern.boottime */ mib[0] == CTL_KERN && mib[1] == KERN_BOOTTIME) return (0); if (miblen == 2 && /* kern.consdev */ mib[0] == CTL_KERN && mib[1] == KERN_CONSDEV) return (0); if (miblen == 2 && /* kern.cptime */ mib[0] == CTL_KERN && mib[1] == KERN_CPTIME) return (0); if (miblen == 3 && /* kern.cptime2 */ mib[0] == CTL_KERN && mib[1] == KERN_CPTIME2) return (0); if (miblen == 3 && /* kern.cpustats */ mib[0] == CTL_KERN && mib[1] == KERN_CPUSTATS) return (0); } if ((pledge & PLEDGE_PS)) { if (miblen == 4 && /* kern.procargs.* */ mib[0] == CTL_KERN && mib[1] == KERN_PROC_ARGS && (mib[3] == KERN_PROC_ARGV || mib[3] == KERN_PROC_ENV)) return (0); if (miblen == 6 && /* kern.proc.* */ mib[0] == CTL_KERN && mib[1] == KERN_PROC) return (0); if (miblen == 3 && /* kern.proc_cwd.* */ mib[0] == CTL_KERN && mib[1] == KERN_PROC_CWD) return (0); if (miblen == 2 && /* kern.ccpu */ mib[0] == CTL_KERN && mib[1] == KERN_CCPU) return (0); if (miblen == 2 && /* vm.maxslp */ mib[0] == CTL_VM && mib[1] == VM_MAXSLP) return (0); } if ((pledge & PLEDGE_VMINFO)) { if (miblen == 2 && /* vm.uvmexp */ mib[0] == CTL_VM && mib[1] == VM_UVMEXP) return (0); if (miblen == 3 && /* vfs.generic.bcachestat */ mib[0] == CTL_VFS && mib[1] == VFS_GENERIC && mib[2] == VFS_BCACHESTAT) return (0); if (miblen == 3 && /* for sysconf(3) */ mib[0] == CTL_NET && mib[1] == PF_INET6) return (0); } if ((pledge & (PLEDGE_INET | PLEDGE_UNIX))) { if (miblen == 2 && /* kern.somaxconn */ mib[0] == CTL_KERN && mib[1] == KERN_SOMAXCONN) return (0); } if ((pledge & (PLEDGE_ROUTE | PLEDGE_INET | PLEDGE_DNS))) { if (miblen == 6 && /* getifaddrs() */ mib[0] == CTL_NET && mib[1] == PF_ROUTE && mib[2] == 0 && (mib[3] == 0 || mib[3] == AF_INET6 || mib[3] == AF_INET) && mib[4] == NET_RT_IFLIST) return (0); } if ((pledge & PLEDGE_DISKLABEL)) { if (miblen == 2 && /* kern.rawpartition */ mib[0] == CTL_KERN && mib[1] == KERN_RAWPARTITION) return (0); if (miblen == 2 && /* kern.maxpartitions */ mib[0] == CTL_KERN && mib[1] == KERN_MAXPARTITIONS) return (0); #ifdef CPU_CHR2BLK if (miblen == 3 && /* machdep.chr2blk */ mib[0] == CTL_MACHDEP && mib[1] == CPU_CHR2BLK) return (0); #endif /* CPU_CHR2BLK */ } if (miblen >= 3 && /* ntpd(8) to read sensors */ mib[0] == CTL_HW && mib[1] == HW_SENSORS) return (0); if (miblen == 6 && /* if_nameindex() */ mib[0] == CTL_NET && mib[1] == PF_ROUTE && mib[2] == 0 && mib[3] == 0 && mib[4] == NET_RT_IFNAMES) return (0); if (miblen == 2) { switch (mib[0]) { case CTL_KERN: switch (mib[1]) { case KERN_DOMAINNAME: /* getdomainname() */ case KERN_HOSTNAME: /* gethostname() */ case KERN_OSTYPE: /* uname() */ case KERN_OSRELEASE: /* uname() */ case KERN_OSVERSION: /* uname() */ case KERN_VERSION: /* uname() */ case KERN_CLOCKRATE: /* kern.clockrate */ case KERN_ARGMAX: /* kern.argmax */ case KERN_NGROUPS: /* kern.ngroups */ case KERN_SYSVSHM: /* kern.sysvshm */ case KERN_POSIX1: /* kern.posix1version */ case KERN_AUTOCONF_SERIAL: /* kern.autoconf_serial */ return (0); } break; case CTL_HW: switch (mib[1]) { case HW_MACHINE: /* uname() */ case HW_PAGESIZE: /* getpagesize() */ case HW_PHYSMEM64: /* hw.physmem */ case HW_NCPU: /* hw.ncpu */ case HW_NCPUONLINE: /* hw.ncpuonline */ case HW_USERMEM64: /* hw.usermem */ return (0); } break; case CTL_VM: switch (mib[1]) { case VM_PSSTRINGS: /* setproctitle() */ case VM_LOADAVG: /* vm.loadavg / getloadavg(3) */ case VM_MALLOC_CONF: /* vm.malloc_conf */ return (0); } break; default: break; } } #ifdef CPU_SSE if (miblen == 2 && /* i386 libm tests for SSE */ mib[0] == CTL_MACHDEP && mib[1] == CPU_SSE) return (0); #endif /* CPU_SSE */ #ifdef CPU_ID_AA64ISAR0 if (miblen == 2 && /* arm64 libcrypto inspects CPU features */ mib[0] == CTL_MACHDEP && mib[1] == CPU_ID_AA64ISAR0) return (0); #endif /* CPU_ID_AA64ISAR0 */ snprintf(buf, sizeof(buf), "%s(%d): pledge sysctl %d:", p->p_p->ps_comm, p->p_p->ps_pid, miblen); for (i = 0; i < miblen; i++) { char *p = buf + strlen(buf); snprintf(p, sizeof(buf) - (p - buf), " %d", mib[i]); } log(LOG_ERR, "%s\n", buf); return pledge_fail(p, EINVAL, 0); } int pledge_chown(struct proc *p, uid_t uid, gid_t gid) { if ((p->p_p->ps_flags & PS_PLEDGE) == 0) return (0); if (p->p_p->ps_pledge & PLEDGE_CHOWNUID) return (0); if (uid != -1 && uid != p->p_ucred->cr_uid) return (EPERM); if (gid != -1 && !groupmember(gid, p->p_ucred)) return (EPERM); return (0); } int pledge_adjtime(struct proc *p, const void *v) { const struct timeval *delta = v; if ((p->p_p->ps_flags & PS_PLEDGE) == 0) return (0); if ((p->p_p->ps_pledge & PLEDGE_SETTIME)) return (0); if (delta) return (EPERM); return (0); } int pledge_sendit(struct proc *p, const void *to) { if ((p->p_p->ps_flags & PS_PLEDGE) == 0) return (0); if ((p->p_p->ps_pledge & (PLEDGE_INET | PLEDGE_UNIX | PLEDGE_DNS))) return (0); /* may use address */ if (to == NULL) return (0); /* behaves just like write */ return pledge_fail(p, EPERM, PLEDGE_INET); } int pledge_ioctl(struct proc *p, long com, struct file *fp) { struct vnode *vp = NULL; int error = EPERM; uint64_t pledge; if ((p->p_p->ps_flags & PS_PLEDGE) == 0) return (0); pledge = READ_ONCE(p->p_p->ps_pledge); /* * The ioctl's which are always allowed. */ switch (com) { case FIONREAD: case FIONBIO: case FIOCLEX: case FIONCLEX: return (0); } /* fp != NULL was already checked */ if (fp->f_type == DTYPE_VNODE) { vp = fp->f_data; if (vp->v_type == VBAD) return (ENOTTY); } if ((pledge & PLEDGE_INET)) { switch (com) { case SIOCATMARK: case SIOCGIFGROUP: if (fp->f_type == DTYPE_SOCKET) return (0); break; } } #if NBPFILTER > 0 if ((pledge & PLEDGE_BPF)) { switch (com) { case BIOCGSTATS: /* bpf: tcpdump privsep on ^C */ if (fp->f_type == DTYPE_VNODE && fp->f_ops->fo_ioctl == vn_ioctl && vp->v_type == VCHR && cdevsw[major(vp->v_rdev)].d_open == bpfopen) return (0); break; } } #endif /* NBPFILTER > 0 */ if ((pledge & PLEDGE_TAPE)) { switch (com) { case MTIOCGET: case MTIOCTOP: /* for pax(1) and such, checking tapes... */ if (fp->f_type == DTYPE_VNODE && vp->v_type == VCHR) { if (vp->v_flag & VISTTY) return (ENOTTY); else return (0); } break; } } #if NDRM > 0 if ((pledge & PLEDGE_DRM)) { if ((fp->f_type == DTYPE_VNODE) && (vp->v_type == VCHR) && (cdevsw[major(vp->v_rdev)].d_open == drmopen)) { error = pledge_ioctl_drm(p, com, vp->v_rdev); if (error == 0) return 0; } } #endif /* NDRM > 0 */ #if NAUDIO > 0 if ((pledge & PLEDGE_AUDIO)) { switch (com) { case AUDIO_GETDEV: case AUDIO_GETPOS: case AUDIO_GETPAR: case AUDIO_SETPAR: case AUDIO_START: case AUDIO_STOP: case AUDIO_MIXER_DEVINFO: case AUDIO_MIXER_READ: case AUDIO_MIXER_WRITE: if (fp->f_type == DTYPE_VNODE && vp->v_type == VCHR && cdevsw[major(vp->v_rdev)].d_open == audioopen) return (0); } } #endif /* NAUDIO > 0 */ if ((pledge & PLEDGE_DISKLABEL)) { switch (com) { case DIOCGDINFO: case DIOCGPDINFO: case DIOCRLDINFO: case DIOCWDINFO: case BIOCDISK: case BIOCINQ: case BIOCINSTALLBOOT: case BIOCVOL: if (fp->f_type == DTYPE_VNODE && ((vp->v_type == VCHR && cdevsw[major(vp->v_rdev)].d_type == D_DISK) || (vp->v_type == VBLK && bdevsw[major(vp->v_rdev)].d_type == D_DISK))) return (0); break; case DIOCMAP: if (fp->f_type == DTYPE_VNODE && vp->v_type == VCHR && cdevsw[major(vp->v_rdev)].d_ioctl == diskmapioctl) return (0); break; } } #if NVIDEO > 0 if ((pledge & PLEDGE_VIDEO)) { switch (com) { case VIDIOC_QUERYCAP: case VIDIOC_TRY_FMT: case VIDIOC_ENUM_FMT: case VIDIOC_S_FMT: case VIDIOC_QUERYCTRL: case VIDIOC_G_CTRL: case VIDIOC_S_CTRL: case VIDIOC_G_PARM: case VIDIOC_S_PARM: case VIDIOC_REQBUFS: case VIDIOC_QBUF: case VIDIOC_DQBUF: case VIDIOC_QUERYBUF: case VIDIOC_STREAMON: case VIDIOC_STREAMOFF: case VIDIOC_ENUM_FRAMESIZES: case VIDIOC_ENUM_FRAMEINTERVALS: case VIDIOC_DQEVENT: case VIDIOC_ENCODER_CMD: case VIDIOC_EXPBUF: case VIDIOC_G_CROP: case VIDIOC_G_EXT_CTRLS: case VIDIOC_G_FMT: case VIDIOC_G_SELECTION: case VIDIOC_QUERYMENU: case VIDIOC_SUBSCRIBE_EVENT: case VIDIOC_S_EXT_CTRLS: case VIDIOC_S_SELECTION: case VIDIOC_TRY_DECODER_CMD: case VIDIOC_TRY_ENCODER_CMD: if (fp->f_type == DTYPE_VNODE && vp->v_type == VCHR && cdevsw[major(vp->v_rdev)].d_open == videoopen) return (0); break; } } #endif #if NPF > 0 if ((pledge & PLEDGE_PF)) { switch (com) { case DIOCADDRULE: case DIOCGETSTATUS: case DIOCNATLOOK: case DIOCRADDTABLES: case DIOCRCLRADDRS: case DIOCRCLRTABLES: case DIOCRCLRTSTATS: case DIOCRGETTSTATS: case DIOCRSETADDRS: case DIOCXBEGIN: case DIOCXCOMMIT: case DIOCKILLSRCNODES: if ((fp->f_type == DTYPE_VNODE) && (vp->v_type == VCHR) && (cdevsw[major(vp->v_rdev)].d_open == pfopen)) return (0); break; } } #endif if ((pledge & PLEDGE_TTY)) { switch (com) { #if NPTY > 0 case PTMGET: if ((pledge & PLEDGE_RPATH) == 0) break; if ((pledge & PLEDGE_WPATH) == 0) break; if (fp->f_type != DTYPE_VNODE || vp->v_type != VCHR) break; if (cdevsw[major(vp->v_rdev)].d_open != ptmopen) break; return (0); case TIOCUCNTL: /* vmd */ if ((pledge & PLEDGE_RPATH) == 0) break; if ((pledge & PLEDGE_WPATH) == 0) break; if (cdevsw[major(vp->v_rdev)].d_open != ptcopen) break; return (0); #endif /* NPTY > 0 */ case TIOCSPGRP: if ((pledge & PLEDGE_PROC) == 0) break; /* FALLTHROUGH */ case TIOCFLUSH: /* getty, telnet */ case TIOCSTART: /* emacs, etc */ case TIOCGPGRP: case TIOCGETA: case TIOCGWINSZ: /* ENOTTY return for non-tty */ case TIOCSTAT: /* csh */ if (fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY)) return (0); return (ENOTTY); case TIOCSWINSZ: case TIOCEXT: /* mail, libedit .. */ case TIOCCBRK: /* cu */ case TIOCSBRK: /* cu */ case TIOCCDTR: /* cu */ case TIOCSDTR: /* cu */ case TIOCEXCL: /* cu */ case TIOCSETA: /* cu, ... */ case TIOCSETAW: /* cu, ... */ case TIOCSETAF: /* tcsetattr TCSAFLUSH, script */ case TIOCSCTTY: /* forkpty(3), login_tty(3), ... */ if (fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY)) return (0); break; } } if ((pledge & PLEDGE_ROUTE)) { switch (com) { case SIOCGIFADDR: case SIOCGIFAFLAG_IN6: case SIOCGIFALIFETIME_IN6: case SIOCGIFDESCR: case SIOCGIFFLAGS: case SIOCGIFMETRIC: case SIOCGIFGMEMB: case SIOCGIFRDOMAIN: case SIOCGIFDSTADDR_IN6: case SIOCGIFNETMASK_IN6: case SIOCGIFXFLAGS: case SIOCGNBRINFO_IN6: case SIOCGIFINFO_IN6: case SIOCGIFMEDIA: if (fp->f_type == DTYPE_SOCKET) return (0); break; } } if ((pledge & PLEDGE_WROUTE)) { switch (com) { case SIOCAIFADDR: case SIOCDIFADDR: case SIOCAIFADDR_IN6: case SIOCDIFADDR_IN6: if (fp->f_type == DTYPE_SOCKET) return (0); break; case SIOCSIFMTU: if (fp->f_type == DTYPE_SOCKET) return (0); break; } } #if NVMM > 0 if ((pledge & PLEDGE_VMM)) { if ((fp->f_type == DTYPE_VNODE) && (vp->v_type == VCHR) && (cdevsw[major(vp->v_rdev)].d_open == vmmopen)) { error = pledge_ioctl_vmm(p, com); if (error == 0) return 0; } } #endif return pledge_fail(p, error, PLEDGE_TTY); } int pledge_sockopt(struct proc *p, int set, int level, int optname) { uint64_t pledge; if ((p->p_p->ps_flags & PS_PLEDGE) == 0) return (0); pledge = READ_ONCE(p->p_p->ps_pledge); /* Always allow these, which are too common to reject */ switch (level) { case SOL_SOCKET: switch (optname) { case SO_RCVBUF: case SO_ERROR: return (0); } break; case IPPROTO_TCP: switch (optname) { case TCP_NODELAY: return (0); } break; } if ((pledge & PLEDGE_WROUTE)) { switch (level) { case SOL_SOCKET: switch (optname) { case SO_RTABLE: return (0); } } } if ((pledge & (PLEDGE_INET|PLEDGE_UNIX|PLEDGE_DNS)) == 0) return pledge_fail(p, EPERM, PLEDGE_INET); /* In use by some service libraries */ switch (level) { case SOL_SOCKET: switch (optname) { case SO_TIMESTAMP: return (0); } break; } /* DNS resolver may do these requests */ if ((pledge & PLEDGE_DNS)) { switch (level) { case IPPROTO_IPV6: switch (optname) { case IPV6_RECVPKTINFO: case IPV6_USE_MIN_MTU: return (0); } } } if ((pledge & (PLEDGE_INET|PLEDGE_UNIX)) == 0) return pledge_fail(p, EPERM, PLEDGE_INET); switch (level) { case SOL_SOCKET: switch (optname) { case SO_RTABLE: return pledge_fail(p, EINVAL, PLEDGE_WROUTE); } return (0); } if ((pledge & PLEDGE_INET) == 0) return pledge_fail(p, EPERM, PLEDGE_INET); switch (level) { case IPPROTO_TCP: switch (optname) { case TCP_MD5SIG: case TCP_SACK_ENABLE: case TCP_MAXSEG: case TCP_NOPUSH: case TCP_INFO: return (0); } break; case IPPROTO_IP: switch (optname) { case IP_OPTIONS: if (!set) return (0); break; case IP_TOS: case IP_TTL: case IP_MINTTL: case IP_IPDEFTTL: case IP_PORTRANGE: case IP_RECVDSTADDR: case IP_RECVDSTPORT: return (0); case IP_MULTICAST_IF: case IP_MULTICAST_TTL: case IP_MULTICAST_LOOP: case IP_ADD_MEMBERSHIP: case IP_DROP_MEMBERSHIP: if (pledge & PLEDGE_MCAST) return (0); break; } break; case IPPROTO_ICMP: break; case IPPROTO_IPV6: switch (optname) { case IPV6_TCLASS: case IPV6_UNICAST_HOPS: case IPV6_MINHOPCOUNT: case IPV6_RECVHOPLIMIT: case IPV6_PORTRANGE: case IPV6_RECVPKTINFO: case IPV6_RECVDSTPORT: case IPV6_V6ONLY: return (0); case IPV6_MULTICAST_IF: case IPV6_MULTICAST_HOPS: case IPV6_MULTICAST_LOOP: case IPV6_JOIN_GROUP: case IPV6_LEAVE_GROUP: if (pledge & PLEDGE_MCAST) return (0); break; } break; case IPPROTO_ICMPV6: break; } return pledge_fail(p, EPERM, PLEDGE_INET); } int pledge_socket(struct proc *p, int domain, unsigned int state) { uint64_t pledge; if (!ISSET(p->p_p->ps_flags, PS_PLEDGE)) return 0; pledge = READ_ONCE(p->p_p->ps_pledge); if (ISSET(state, SS_DNS)) { if (ISSET(pledge, PLEDGE_DNS)) return 0; return pledge_fail(p, EPERM, PLEDGE_DNS); } switch (domain) { case -1: /* accept on any domain */ return (0); case AF_INET: case AF_INET6: if (ISSET(pledge, PLEDGE_INET)) return 0; return pledge_fail(p, EPERM, PLEDGE_INET); case AF_UNIX: if (ISSET(pledge, PLEDGE_UNIX)) return 0; return pledge_fail(p, EPERM, PLEDGE_UNIX); } return pledge_fail(p, EINVAL, PLEDGE_INET); } int pledge_flock(struct proc *p) { if ((p->p_p->ps_flags & PS_PLEDGE) == 0) return (0); if ((p->p_p->ps_pledge & PLEDGE_FLOCK)) return (0); return (pledge_fail(p, EPERM, PLEDGE_FLOCK)); } int pledge_swapctl(struct proc *p, int cmd) { if ((p->p_p->ps_flags & PS_PLEDGE) == 0) return (0); if (p->p_p->ps_pledge & PLEDGE_VMINFO) { switch (cmd) { case SWAP_NSWAP: case SWAP_STATS: return (0); } } return pledge_fail(p, EPERM, PLEDGE_VMINFO); } /* bsearch over pledgereq. return flags value if found, 0 else */ uint64_t pledgereq_flags(const char *req_name) { int base = 0, cmp, i, lim; for (lim = nitems(pledgereq); lim != 0; lim >>= 1) { i = base + (lim >> 1); cmp = strcmp(req_name, pledgereq[i].name); if (cmp == 0) return (pledgereq[i].flags); if (cmp > 0) { /* not found before, move right */ base = i + 1; lim--; } /* else move left */ } return (0); } int pledge_fcntl(struct proc *p, int cmd) { if ((p->p_p->ps_flags & PS_PLEDGE) == 0) return (0); if ((p->p_p->ps_pledge & PLEDGE_PROC) == 0 && cmd == F_SETOWN) return pledge_fail(p, EPERM, PLEDGE_PROC); return (0); } int pledge_kill(struct proc *p, pid_t pid) { if ((p->p_p->ps_flags & PS_PLEDGE) == 0) return 0; if (p->p_p->ps_pledge & PLEDGE_PROC) return 0; if (pid == 0 || pid == p->p_p->ps_pid) return 0; return pledge_fail(p, EPERM, PLEDGE_PROC); } int pledge_profil(struct proc *p, u_int scale) { if ((p->p_p->ps_flags & PS_PLEDGE) == 0) return 0; if (scale != 0) return pledge_fail(p, EPERM, PLEDGE_STDIO); return 0; } int pledge_protexec(struct proc *p, int prot) { if ((p->p_p->ps_flags & PS_PLEDGE) == 0) return 0; /* Before kbind(2) call, ld.so and crt may create EXEC mappings */ if (p->p_p->ps_kbind_addr == 0 && p->p_p->ps_kbind_cookie == 0) return 0; if (!(p->p_p->ps_pledge & PLEDGE_PROTEXEC) && (prot & PROT_EXEC)) return pledge_fail(p, EPERM, PLEDGE_PROTEXEC); return 0; } int canonpath(const char *input, char *buf, size_t bufsize) { const char *p; char *q; /* can't canon relative paths, don't bother */ if (input[0] != '/') { if (strlcpy(buf, input, bufsize) >= bufsize) return ENAMETOOLONG; return 0; } p = input; q = buf; while (*p && (q - buf < bufsize)) { if (p[0] == '/' && (p[1] == '/' || p[1] == '\0')) { p += 1; } else if (p[0] == '/' && p[1] == '.' && (p[2] == '/' || p[2] == '\0')) { p += 2; } else if (p[0] == '/' && p[1] == '.' && p[2] == '.' && (p[3] == '/' || p[3] == '\0')) { p += 3; if (q != buf) /* "/../" at start of buf */ while (*--q != '/') continue; } else { *q++ = *p++; } } if ((*p == '\0') && (q - buf < bufsize)) { *q = 0; return 0; } else return ENAMETOOLONG; }
111 112 82 112 6 89 2 79 27 3 21 75 13 28 55 33 51 40 43 81 17 2 86 16 26 15 27 27 15 37 4 41 1 40 41 62 3 64 30 94 94 79 2 2 2 2 13 95 17 89 89 89 15 1 12 8 6 14 14 14 29 28 1 9 9 20 4 5 2 1 6 260 1 198 12 22 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 1 1 1 1 6 4 3 3 3 3 2 1 3 2 1 36 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 3 2 4 1 7 3 7 1 2 5 5 49 13 4 26 9 131 94 42 5 16 6 5 1 5 5 5 1 8 4 14 5 43 6 7 4 15 5 17 17 40 6 6 10 13 15 4 11 60 21 22 32 14 2 2 6 1 1 1 1 30 25 5 1 79 1 92 37 22 14 1 8 109 44 66 66 7 33 25 1 8 38 28 44 27 62 50 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 /* $OpenBSD: ip_output.c,v 1.399 2024/05/16 13:01:04 bluhm Exp $ */ /* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ip_output.c 8.3 (Berkeley) 1/21/94 */ #include "pf.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/protosw.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/proc.h> #include <sys/kernel.h> #include <net/if.h> #include <net/if_var.h> #include <net/if_enc.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/in_pcb.h> #include <netinet/in_var.h> #include <netinet/ip_var.h> #include <netinet/ip_icmp.h> #include <netinet/tcp.h> #include <netinet/udp.h> #include <netinet/tcp_timer.h> #include <netinet/tcp_var.h> #include <netinet/udp_var.h> #if NPF > 0 #include <net/pfvar.h> #endif #ifdef IPSEC #ifdef ENCDEBUG #define DPRINTF(fmt, args...) \ do { \ if (encdebug) \ printf("%s: " fmt "\n", __func__, ## args); \ } while (0) #else #define DPRINTF(fmt, args...) \ do { } while (0) #endif #endif /* IPSEC */ int ip_pcbopts(struct mbuf **, struct mbuf *); int ip_multicast_if(struct ip_mreqn *, u_int, unsigned int *); int ip_setmoptions(int, struct ip_moptions **, struct mbuf *, u_int); void ip_mloopback(struct ifnet *, struct mbuf *, struct sockaddr_in *); static u_int16_t in_cksum_phdr(u_int32_t, u_int32_t, u_int32_t); void in_delayed_cksum(struct mbuf *); int ip_output_ipsec_lookup(struct mbuf *m, int hlen, const struct ipsec_level *seclevel, struct tdb **, int ipsecflowinfo); void ip_output_ipsec_pmtu_update(struct tdb *, struct route *, struct in_addr, int, int); int ip_output_ipsec_send(struct tdb *, struct mbuf *, struct route *, int); /* * IP output. The packet in mbuf chain m contains a skeletal IP * header (with len, off, ttl, proto, tos, src, dst). * The mbuf chain containing the packet will be freed. * The mbuf opt, if present, will not be freed. */ int ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, struct ip_moptions *imo, const struct ipsec_level *seclevel, u_int32_t ipsecflowinfo) { struct ip *ip; struct ifnet *ifp = NULL; struct mbuf_list ml; int hlen = sizeof (struct ip); int error = 0; struct route iproute; struct sockaddr_in *dst; struct tdb *tdb = NULL; u_long mtu; #if NPF > 0 u_int orig_rtableid; #endif NET_ASSERT_LOCKED(); #ifdef DIAGNOSTIC if ((m->m_flags & M_PKTHDR) == 0) panic("ip_output no HDR"); #endif if (opt) m = ip_insertoptions(m, opt, &hlen); ip = mtod(m, struct ip *); /* * Fill in IP header. */ if ((flags & (IP_FORWARDING|IP_RAWOUTPUT)) == 0) { ip->ip_v = IPVERSION; ip->ip_off &= htons(IP_DF); ip->ip_id = htons(ip_randomid()); ip->ip_hl = hlen >> 2; ipstat_inc(ips_localout); } else { hlen = ip->ip_hl << 2; } /* * We should not send traffic to 0/8 say both Stevens and RFCs * 5735 section 3 and 1122 sections 3.2.1.3 and 3.3.6. */ if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == 0) { error = ENETUNREACH; goto bad; } #if NPF > 0 orig_rtableid = m->m_pkthdr.ph_rtableid; reroute: #endif /* * Do a route lookup now in case we need the source address to * do an SPD lookup in IPsec; for most packets, the source address * is set at a higher level protocol. ICMPs and other packets * though (e.g., traceroute) have a source address of zeroes. */ if (ro == NULL) { ro = &iproute; ro->ro_rt = NULL; } /* * If there is a cached route, check that it is to the same * destination and is still up. If not, free it and try again. */ route_cache(ro, &ip->ip_dst, &ip->ip_src, m->m_pkthdr.ph_rtableid); dst = &ro->ro_dstsin; if ((IN_MULTICAST(ip->ip_dst.s_addr) || (ip->ip_dst.s_addr == INADDR_BROADCAST)) && imo != NULL && (ifp = if_get(imo->imo_ifidx)) != NULL) { mtu = ifp->if_mtu; if (ip->ip_src.s_addr == INADDR_ANY) { struct in_ifaddr *ia; IFP_TO_IA(ifp, ia); if (ia != NULL) ip->ip_src = ia->ia_addr.sin_addr; } } else { struct in_ifaddr *ia; if (ro->ro_rt == NULL) ro->ro_rt = rtalloc_mpath(&ro->ro_dstsa, &ip->ip_src.s_addr, ro->ro_tableid); if (ro->ro_rt == NULL) { ipstat_inc(ips_noroute); error = EHOSTUNREACH; goto bad; } ia = ifatoia(ro->ro_rt->rt_ifa); if (ISSET(ro->ro_rt->rt_flags, RTF_LOCAL)) ifp = if_get(rtable_loindex(m->m_pkthdr.ph_rtableid)); else ifp = if_get(ro->ro_rt->rt_ifidx); /* * We aren't using rtisvalid() here because the UP/DOWN state * machine is broken with some Ethernet drivers like em(4). * As a result we might try to use an invalid cached route * entry while an interface is being detached. */ if (ifp == NULL) { ipstat_inc(ips_noroute); error = EHOSTUNREACH; goto bad; } if ((mtu = ro->ro_rt->rt_mtu) == 0) mtu = ifp->if_mtu; if (ro->ro_rt->rt_flags & RTF_GATEWAY) dst = satosin(ro->ro_rt->rt_gateway); /* Set the source IP address */ if (ip->ip_src.s_addr == INADDR_ANY && ia) ip->ip_src = ia->ia_addr.sin_addr; } #ifdef IPSEC if (ipsec_in_use || seclevel != NULL) { /* Do we have any pending SAs to apply ? */ error = ip_output_ipsec_lookup(m, hlen, seclevel, &tdb, ipsecflowinfo); if (error) { /* Should silently drop packet */ if (error == -EINVAL) error = 0; goto bad; } if (tdb != NULL) { /* * If it needs TCP/UDP hardware-checksumming, do the * computation now. */ in_proto_cksum_out(m, NULL); } } #endif /* IPSEC */ if (IN_MULTICAST(ip->ip_dst.s_addr) || (ip->ip_dst.s_addr == INADDR_BROADCAST)) { m->m_flags |= (ip->ip_dst.s_addr == INADDR_BROADCAST) ? M_BCAST : M_MCAST; /* * IP destination address is multicast. Make sure "dst" * still points to the address in "ro". (It may have been * changed to point to a gateway address, above.) */ dst = &ro->ro_dstsin; /* * See if the caller provided any multicast options */ if (imo != NULL) ip->ip_ttl = imo->imo_ttl; else ip->ip_ttl = IP_DEFAULT_MULTICAST_TTL; /* * if we don't know the outgoing ifp yet, we can't generate * output */ if (!ifp) { ipstat_inc(ips_noroute); error = EHOSTUNREACH; goto bad; } /* * Confirm that the outgoing interface supports multicast, * but only if the packet actually is going out on that * interface (i.e., no IPsec is applied). */ if ((((m->m_flags & M_MCAST) && (ifp->if_flags & IFF_MULTICAST) == 0) || ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_BROADCAST) == 0)) && (tdb == NULL)) { ipstat_inc(ips_noroute); error = ENETUNREACH; goto bad; } /* * If source address not specified yet, use address * of outgoing interface. */ if (ip->ip_src.s_addr == INADDR_ANY) { struct in_ifaddr *ia; IFP_TO_IA(ifp, ia); if (ia != NULL) ip->ip_src = ia->ia_addr.sin_addr; } if ((imo == NULL || imo->imo_loop) && in_hasmulti(&ip->ip_dst, ifp)) { /* * If we belong to the destination multicast group * on the outgoing interface, and the caller did not * forbid loopback, loop back a copy. * Can't defer TCP/UDP checksumming, do the * computation now. */ in_proto_cksum_out(m, NULL); ip_mloopback(ifp, m, dst); } #ifdef MROUTING else { /* * If we are acting as a multicast router, perform * multicast forwarding as if the packet had just * arrived on the interface to which we are about * to send. The multicast forwarding function * recursively calls this function, using the * IP_FORWARDING flag to prevent infinite recursion. * * Multicasts that are looped back by ip_mloopback(), * above, will be forwarded by the ip_input() routine, * if necessary. */ if (ipmforwarding && ip_mrouter[ifp->if_rdomain] && (flags & IP_FORWARDING) == 0) { int rv; KERNEL_LOCK(); rv = ip_mforward(m, ifp); KERNEL_UNLOCK(); if (rv != 0) goto bad; } } #endif /* * Multicasts with a time-to-live of zero may be looped- * back, above, but must not be transmitted on a network. * Also, multicasts addressed to the loopback interface * are not sent -- the above call to ip_mloopback() will * loop back a copy if this host actually belongs to the * destination group on the loopback interface. */ if (ip->ip_ttl == 0 || (ifp->if_flags & IFF_LOOPBACK) != 0) goto bad; goto sendit; } /* * Look for broadcast address and verify user is allowed to send * such a packet; if the packet is going in an IPsec tunnel, skip * this check. */ if ((tdb == NULL) && ((dst->sin_addr.s_addr == INADDR_BROADCAST) || (ro && ro->ro_rt && ISSET(ro->ro_rt->rt_flags, RTF_BROADCAST)))) { if ((ifp->if_flags & IFF_BROADCAST) == 0) { error = EADDRNOTAVAIL; goto bad; } if ((flags & IP_ALLOWBROADCAST) == 0) { error = EACCES; goto bad; } /* Don't allow broadcast messages to be fragmented */ if (ntohs(ip->ip_len) > ifp->if_mtu) { error = EMSGSIZE; goto bad; } m->m_flags |= M_BCAST; } else m->m_flags &= ~M_BCAST; sendit: /* * If we're doing Path MTU discovery, we need to set DF unless * the route's MTU is locked. */ if ((flags & IP_MTUDISC) && ro && ro->ro_rt && (ro->ro_rt->rt_locks & RTV_MTU) == 0) ip->ip_off |= htons(IP_DF); #ifdef IPSEC /* * Check if the packet needs encapsulation. */ if (tdb != NULL) { /* Callee frees mbuf */ error = ip_output_ipsec_send(tdb, m, ro, (flags & IP_FORWARDING) ? 1 : 0); goto done; } #endif /* IPSEC */ /* * Packet filter */ #if NPF > 0 if (pf_test(AF_INET, (flags & IP_FORWARDING) ? PF_FWD : PF_OUT, ifp, &m) != PF_PASS) { error = EACCES; goto bad; } if (m == NULL) goto done; ip = mtod(m, struct ip *); hlen = ip->ip_hl << 2; if ((m->m_pkthdr.pf.flags & (PF_TAG_REROUTE | PF_TAG_GENERATED)) == (PF_TAG_REROUTE | PF_TAG_GENERATED)) /* already rerun the route lookup, go on */ m->m_pkthdr.pf.flags &= ~(PF_TAG_GENERATED | PF_TAG_REROUTE); else if (m->m_pkthdr.pf.flags & PF_TAG_REROUTE) { /* tag as generated to skip over pf_test on rerun */ m->m_pkthdr.pf.flags |= PF_TAG_GENERATED; if (ro == &iproute) rtfree(ro->ro_rt); ro = NULL; if_put(ifp); /* drop reference since target changed */ ifp = NULL; goto reroute; } #endif #ifdef IPSEC if ((flags & IP_FORWARDING) && ipforwarding == 2 && (!ipsec_in_use || m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL) == NULL)) { error = EHOSTUNREACH; goto bad; } #endif /* * If TSO or small enough for interface, can just send directly. */ error = if_output_tso(ifp, &m, sintosa(dst), ro->ro_rt, mtu); if (error || m == NULL) goto done; /* * Too large for interface; fragment if possible. * Must be able to put at least 8 bytes per fragment. */ if (ip->ip_off & htons(IP_DF)) { #ifdef IPSEC if (ip_mtudisc) ipsec_adjust_mtu(m, ifp->if_mtu); #endif error = EMSGSIZE; #if NPF > 0 /* pf changed routing table, use orig rtable for path MTU */ if (ro->ro_tableid != orig_rtableid) { rtfree(ro->ro_rt); ro->ro_tableid = orig_rtableid; ro->ro_rt = icmp_mtudisc_clone( ro->ro_dstsin.sin_addr, ro->ro_tableid, 0); } #endif /* * This case can happen if the user changed the MTU * of an interface after enabling IP on it. Because * most netifs don't keep track of routes pointing to * them, there is no way for one to update all its * routes when the MTU is changed. */ if (rtisvalid(ro->ro_rt) && ISSET(ro->ro_rt->rt_flags, RTF_HOST) && !(ro->ro_rt->rt_locks & RTV_MTU) && (ro->ro_rt->rt_mtu > ifp->if_mtu)) { ro->ro_rt->rt_mtu = ifp->if_mtu; } ipstat_inc(ips_cantfrag); goto bad; } if ((error = ip_fragment(m, &ml, ifp, mtu)) || (error = if_output_ml(ifp, &ml, sintosa(dst), ro->ro_rt))) goto done; ipstat_inc(ips_fragmented); done: if (ro == &iproute) rtfree(ro->ro_rt); if_put(ifp); #ifdef IPSEC tdb_unref(tdb); #endif /* IPSEC */ return (error); bad: m_freem(m); goto done; } #ifdef IPSEC int ip_output_ipsec_lookup(struct mbuf *m, int hlen, const struct ipsec_level *seclevel, struct tdb **tdbout, int ipsecflowinfo) { struct m_tag *mtag; struct tdb_ident *tdbi; struct tdb *tdb; struct ipsec_ids *ids = NULL; int error; /* Do we have any pending SAs to apply ? */ if (ipsecflowinfo) ids = ipsp_ids_lookup(ipsecflowinfo); error = ipsp_spd_lookup(m, AF_INET, hlen, IPSP_DIRECTION_OUT, NULL, seclevel, &tdb, ids); ipsp_ids_free(ids); if (error || tdb == NULL) { *tdbout = NULL; return error; } /* Loop detection */ for (mtag = m_tag_first(m); mtag != NULL; mtag = m_tag_next(m, mtag)) { if (mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_DONE) continue; tdbi = (struct tdb_ident *)(mtag + 1); if (tdbi->spi == tdb->tdb_spi && tdbi->proto == tdb->tdb_sproto && tdbi->rdomain == tdb->tdb_rdomain && !memcmp(&tdbi->dst, &tdb->tdb_dst, sizeof(union sockaddr_union))) { /* no IPsec needed */ tdb_unref(tdb); *tdbout = NULL; return 0; } } *tdbout = tdb; return 0; } void ip_output_ipsec_pmtu_update(struct tdb *tdb, struct route *ro, struct in_addr dst, int rtableid, int transportmode) { struct rtentry *rt = NULL; int rt_mtucloned = 0; /* Find a host route to store the mtu in */ if (ro != NULL) rt = ro->ro_rt; /* but don't add a PMTU route for transport mode SAs */ if (transportmode) rt = NULL; else if (rt == NULL || (rt->rt_flags & RTF_HOST) == 0) { rt = icmp_mtudisc_clone(dst, rtableid, 1); rt_mtucloned = 1; } DPRINTF("spi %08x mtu %d rt %p cloned %d", ntohl(tdb->tdb_spi), tdb->tdb_mtu, rt, rt_mtucloned); if (rt != NULL) { rt->rt_mtu = tdb->tdb_mtu; if (ro != NULL && ro->ro_rt != NULL) { rtfree(ro->ro_rt); ro->ro_rt = rtalloc(&ro->ro_dstsa, RT_RESOLVE, rtableid); } if (rt_mtucloned) rtfree(rt); } } int ip_output_ipsec_send(struct tdb *tdb, struct mbuf *m, struct route *ro, int fwd) { struct mbuf_list ml; struct ifnet *encif = NULL; struct ip *ip; struct in_addr dst; u_int len; int error, rtableid, tso = 0; #if NPF > 0 /* * Packet filter */ if ((encif = enc_getif(tdb->tdb_rdomain, tdb->tdb_tap)) == NULL || pf_test(AF_INET, fwd ? PF_FWD : PF_OUT, encif, &m) != PF_PASS) { m_freem(m); return EACCES; } if (m == NULL) return 0; /* * PF_TAG_REROUTE handling or not... * Packet is entering IPsec so the routing is * already overruled by the IPsec policy. * Until now the change was not reconsidered. * What's the behaviour? */ #endif /* Check if we can chop the TCP packet */ ip = mtod(m, struct ip *); if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO) && m->m_pkthdr.ph_mss <= tdb->tdb_mtu) { tso = 1; len = m->m_pkthdr.ph_mss; } else len = ntohs(ip->ip_len); /* Check if we are allowed to fragment */ dst = ip->ip_dst; rtableid = m->m_pkthdr.ph_rtableid; if (ip_mtudisc && (ip->ip_off & htons(IP_DF)) && tdb->tdb_mtu && len > tdb->tdb_mtu && tdb->tdb_mtutimeout > gettime()) { int transportmode; transportmode = (tdb->tdb_dst.sa.sa_family == AF_INET) && (tdb->tdb_dst.sin.sin_addr.s_addr == dst.s_addr); ip_output_ipsec_pmtu_update(tdb, ro, dst, rtableid, transportmode); ipsec_adjust_mtu(m, tdb->tdb_mtu); m_freem(m); return EMSGSIZE; } /* propagate IP_DF for v4-over-v6 */ if (ip_mtudisc && ip->ip_off & htons(IP_DF)) SET(m->m_pkthdr.csum_flags, M_IPV6_DF_OUT); /* * Clear these -- they'll be set in the recursive invocation * as needed. */ m->m_flags &= ~(M_MCAST | M_BCAST); if (tso) { error = tcp_chopper(m, &ml, encif, len); if (error) goto done; } else { CLR(m->m_pkthdr.csum_flags, M_TCP_TSO); in_proto_cksum_out(m, encif); ml_init(&ml); ml_enqueue(&ml, m); } KERNEL_LOCK(); while ((m = ml_dequeue(&ml)) != NULL) { /* Callee frees mbuf */ error = ipsp_process_packet(m, tdb, AF_INET, 0); if (error) break; } KERNEL_UNLOCK(); done: if (error) { ml_purge(&ml); ipsecstat_inc(ipsec_odrops); tdbstat_inc(tdb, tdb_odrops); } if (!error && tso) tcpstat_inc(tcps_outswtso); if (ip_mtudisc && error == EMSGSIZE) ip_output_ipsec_pmtu_update(tdb, ro, dst, rtableid, 0); return error; } #endif /* IPSEC */ int ip_fragment(struct mbuf *m0, struct mbuf_list *ml, struct ifnet *ifp, u_long mtu) { struct ip *ip; int firstlen, hlen, tlen, len, off; int error; ml_init(ml); ml_enqueue(ml, m0); ip = mtod(m0, struct ip *); hlen = ip->ip_hl << 2; tlen = m0->m_pkthdr.len; len = (mtu - hlen) &~ 7; if (len < 8) { error = EMSGSIZE; goto bad; } firstlen = len; /* * If we are doing fragmentation, we can't defer TCP/UDP * checksumming; compute the checksum and clear the flag. */ in_proto_cksum_out(m0, NULL); /* * Loop through length of payload after first fragment, * make new header and copy data of each part and link onto chain. */ for (off = hlen + firstlen; off < tlen; off += len) { struct mbuf *m; struct ip *mhip; int mhlen; MGETHDR(m, M_DONTWAIT, MT_HEADER); if (m == NULL) { error = ENOBUFS; goto bad; } ml_enqueue(ml, m); if ((error = m_dup_pkthdr(m, m0, M_DONTWAIT)) != 0) goto bad; m->m_data += max_linkhdr; mhip = mtod(m, struct ip *); *mhip = *ip; if (hlen > sizeof(struct ip)) { mhlen = ip_optcopy(ip, mhip) + sizeof(struct ip); mhip->ip_hl = mhlen >> 2; } else mhlen = sizeof(struct ip); m->m_len = mhlen; mhip->ip_off = ((off - hlen) >> 3) + (ntohs(ip->ip_off) & ~IP_MF); if (ip->ip_off & htons(IP_MF)) mhip->ip_off |= IP_MF; if (off + len >= tlen) len = tlen - off; else mhip->ip_off |= IP_MF; mhip->ip_off = htons(mhip->ip_off); m->m_pkthdr.len = mhlen + len; mhip->ip_len = htons(m->m_pkthdr.len); m->m_next = m_copym(m0, off, len, M_NOWAIT); if (m->m_next == NULL) { error = ENOBUFS; goto bad; } in_hdr_cksum_out(m, ifp); } /* * Update first fragment by trimming what's been copied out * and updating header, then send each fragment (in order). */ if (hlen + firstlen < tlen) { m_adj(m0, hlen + firstlen - tlen); ip->ip_off |= htons(IP_MF); } ip->ip_len = htons(m0->m_pkthdr.len); in_hdr_cksum_out(m0, ifp); ipstat_add(ips_ofragments, ml_len(ml)); return (0); bad: ipstat_inc(ips_odropped); ml_purge(ml); return (error); } /* * Insert IP options into preformed packet. * Adjust IP destination as required for IP source routing, * as indicated by a non-zero in_addr at the start of the options. */ struct mbuf * ip_insertoptions(struct mbuf *m, struct mbuf *opt, int *phlen) { struct ipoption *p = mtod(opt, struct ipoption *); struct mbuf *n; struct ip *ip = mtod(m, struct ip *); unsigned int optlen; optlen = opt->m_len - sizeof(p->ipopt_dst); if (optlen + ntohs(ip->ip_len) > IP_MAXPACKET) return (m); /* XXX should fail */ /* check if options will fit to IP header */ if ((optlen + sizeof(struct ip)) > (0x0f << 2)) { *phlen = sizeof(struct ip); return (m); } if (p->ipopt_dst.s_addr) ip->ip_dst = p->ipopt_dst; if (m->m_flags & M_EXT || m->m_data - optlen < m->m_pktdat) { MGETHDR(n, M_DONTWAIT, MT_HEADER); if (n == NULL) return (m); M_MOVE_HDR(n, m); n->m_pkthdr.len += optlen; m->m_len -= sizeof(struct ip); m->m_data += sizeof(struct ip); n->m_next = m; m = n; m->m_len = optlen + sizeof(struct ip); m->m_data += max_linkhdr; memcpy(mtod(m, caddr_t), ip, sizeof(struct ip)); } else { m->m_data -= optlen; m->m_len += optlen; m->m_pkthdr.len += optlen; memmove(mtod(m, caddr_t), (caddr_t)ip, sizeof(struct ip)); } ip = mtod(m, struct ip *); memcpy(ip + 1, p->ipopt_list, optlen); *phlen = sizeof(struct ip) + optlen; ip->ip_len = htons(ntohs(ip->ip_len) + optlen); return (m); } /* * Copy options from ip to jp, * omitting those not copied during fragmentation. */ int ip_optcopy(struct ip *ip, struct ip *jp) { u_char *cp, *dp; int opt, optlen, cnt; cp = (u_char *)(ip + 1); dp = (u_char *)(jp + 1); cnt = (ip->ip_hl << 2) - sizeof (struct ip); for (; cnt > 0; cnt -= optlen, cp += optlen) { opt = cp[0]; if (opt == IPOPT_EOL) break; if (opt == IPOPT_NOP) { /* Preserve for IP mcast tunnel's LSRR alignment. */ *dp++ = IPOPT_NOP; optlen = 1; continue; } #ifdef DIAGNOSTIC if (cnt < IPOPT_OLEN + sizeof(*cp)) panic("malformed IPv4 option passed to ip_optcopy"); #endif optlen = cp[IPOPT_OLEN]; #ifdef DIAGNOSTIC if (optlen < IPOPT_OLEN + sizeof(*cp) || optlen > cnt) panic("malformed IPv4 option passed to ip_optcopy"); #endif /* bogus lengths should have been caught by ip_dooptions */ if (optlen > cnt) optlen = cnt; if (IPOPT_COPIED(opt)) { memcpy(dp, cp, optlen); dp += optlen; } } for (optlen = dp - (u_char *)(jp+1); optlen & 0x3; optlen++) *dp++ = IPOPT_EOL; return (optlen); } /* * IP socket option processing. */ int ip_ctloutput(int op, struct socket *so, int level, int optname, struct mbuf *m) { struct inpcb *inp = sotoinpcb(so); int optval = 0; struct proc *p = curproc; /* XXX */ int error = 0; u_int rtableid, rtid = 0; if (level != IPPROTO_IP) return (EINVAL); rtableid = p->p_p->ps_rtableid; switch (op) { case PRCO_SETOPT: switch (optname) { case IP_OPTIONS: return (ip_pcbopts(&inp->inp_options, m)); case IP_TOS: case IP_TTL: case IP_MINTTL: case IP_RECVOPTS: case IP_RECVRETOPTS: case IP_RECVDSTADDR: case IP_RECVIF: case IP_RECVTTL: case IP_RECVDSTPORT: case IP_RECVRTABLE: case IP_IPSECFLOWINFO: if (m == NULL || m->m_len != sizeof(int)) error = EINVAL; else { optval = *mtod(m, int *); switch (optname) { case IP_TOS: inp->inp_ip.ip_tos = optval; break; case IP_TTL: if (optval > 0 && optval <= MAXTTL) inp->inp_ip.ip_ttl = optval; else if (optval == -1) inp->inp_ip.ip_ttl = ip_defttl; else error = EINVAL; break; case IP_MINTTL: if (optval >= 0 && optval <= MAXTTL) inp->inp_ip_minttl = optval; else error = EINVAL; break; #define OPTSET(bit) \ if (optval) \ inp->inp_flags |= bit; \ else \ inp->inp_flags &= ~bit; case IP_RECVOPTS: OPTSET(INP_RECVOPTS); break; case IP_RECVRETOPTS: OPTSET(INP_RECVRETOPTS); break; case IP_RECVDSTADDR: OPTSET(INP_RECVDSTADDR); break; case IP_RECVIF: OPTSET(INP_RECVIF); break; case IP_RECVTTL: OPTSET(INP_RECVTTL); break; case IP_RECVDSTPORT: OPTSET(INP_RECVDSTPORT); break; case IP_RECVRTABLE: OPTSET(INP_RECVRTABLE); break; case IP_IPSECFLOWINFO: OPTSET(INP_IPSECFLOWINFO); break; } } break; #undef OPTSET case IP_MULTICAST_IF: case IP_MULTICAST_TTL: case IP_MULTICAST_LOOP: case IP_ADD_MEMBERSHIP: case IP_DROP_MEMBERSHIP: error = ip_setmoptions(optname, &inp->inp_moptions, m, inp->inp_rtableid); break; case IP_PORTRANGE: if (m == NULL || m->m_len != sizeof(int)) error = EINVAL; else { optval = *mtod(m, int *); switch (optval) { case IP_PORTRANGE_DEFAULT: inp->inp_flags &= ~(INP_LOWPORT); inp->inp_flags &= ~(INP_HIGHPORT); break; case IP_PORTRANGE_HIGH: inp->inp_flags &= ~(INP_LOWPORT); inp->inp_flags |= INP_HIGHPORT; break; case IP_PORTRANGE_LOW: inp->inp_flags &= ~(INP_HIGHPORT); inp->inp_flags |= INP_LOWPORT; break; default: error = EINVAL; break; } } break; case IP_AUTH_LEVEL: case IP_ESP_TRANS_LEVEL: case IP_ESP_NETWORK_LEVEL: case IP_IPCOMP_LEVEL: #ifndef IPSEC error = EOPNOTSUPP; #else if (m == NULL || m->m_len != sizeof(int)) { error = EINVAL; break; } optval = *mtod(m, int *); if (optval < IPSEC_LEVEL_BYPASS || optval > IPSEC_LEVEL_UNIQUE) { error = EINVAL; break; } switch (optname) { case IP_AUTH_LEVEL: if (optval < IPSEC_AUTH_LEVEL_DEFAULT && suser(p)) { error = EACCES; break; } inp->inp_seclevel.sl_auth = optval; break; case IP_ESP_TRANS_LEVEL: if (optval < IPSEC_ESP_TRANS_LEVEL_DEFAULT && suser(p)) { error = EACCES; break; } inp->inp_seclevel.sl_esp_trans = optval; break; case IP_ESP_NETWORK_LEVEL: if (optval < IPSEC_ESP_NETWORK_LEVEL_DEFAULT && suser(p)) { error = EACCES; break; } inp->inp_seclevel.sl_esp_network = optval; break; case IP_IPCOMP_LEVEL: if (optval < IPSEC_IPCOMP_LEVEL_DEFAULT && suser(p)) { error = EACCES; break; } inp->inp_seclevel.sl_ipcomp = optval; break; } #endif break; case IP_IPSEC_LOCAL_ID: case IP_IPSEC_REMOTE_ID: error = EOPNOTSUPP; break; case SO_RTABLE: if (m == NULL || m->m_len < sizeof(u_int)) { error = EINVAL; break; } rtid = *mtod(m, u_int *); if (inp->inp_rtableid == rtid) break; /* needs privileges to switch when already set */ if (rtableid != rtid && rtableid != 0 && (error = suser(p)) != 0) break; error = in_pcbset_rtableid(inp, rtid); break; case IP_PIPEX: if (m != NULL && m->m_len == sizeof(int)) inp->inp_pipex = *mtod(m, int *); else error = EINVAL; break; default: error = ENOPROTOOPT; break; } break; case PRCO_GETOPT: switch (optname) { case IP_OPTIONS: case IP_RETOPTS: if (inp->inp_options) { m->m_len = inp->inp_options->m_len; memcpy(mtod(m, caddr_t), mtod(inp->inp_options, caddr_t), m->m_len); } else m->m_len = 0; break; case IP_TOS: case IP_TTL: case IP_MINTTL: case IP_RECVOPTS: case IP_RECVRETOPTS: case IP_RECVDSTADDR: case IP_RECVIF: case IP_RECVTTL: case IP_RECVDSTPORT: case IP_RECVRTABLE: case IP_IPSECFLOWINFO: case IP_IPDEFTTL: m->m_len = sizeof(int); switch (optname) { case IP_TOS: optval = inp->inp_ip.ip_tos; break; case IP_TTL: optval = inp->inp_ip.ip_ttl; break; case IP_MINTTL: optval = inp->inp_ip_minttl; break; case IP_IPDEFTTL: optval = ip_defttl; break; #define OPTBIT(bit) (inp->inp_flags & bit ? 1 : 0) case IP_RECVOPTS: optval = OPTBIT(INP_RECVOPTS); break; case IP_RECVRETOPTS: optval = OPTBIT(INP_RECVRETOPTS); break; case IP_RECVDSTADDR: optval = OPTBIT(INP_RECVDSTADDR); break; case IP_RECVIF: optval = OPTBIT(INP_RECVIF); break; case IP_RECVTTL: optval = OPTBIT(INP_RECVTTL); break; case IP_RECVDSTPORT: optval = OPTBIT(INP_RECVDSTPORT); break; case IP_RECVRTABLE: optval = OPTBIT(INP_RECVRTABLE); break; case IP_IPSECFLOWINFO: optval = OPTBIT(INP_IPSECFLOWINFO); break; } *mtod(m, int *) = optval; break; case IP_MULTICAST_IF: case IP_MULTICAST_TTL: case IP_MULTICAST_LOOP: case IP_ADD_MEMBERSHIP: case IP_DROP_MEMBERSHIP: error = ip_getmoptions(optname, inp->inp_moptions, m); break; case IP_PORTRANGE: m->m_len = sizeof(int); if (inp->inp_flags & INP_HIGHPORT) optval = IP_PORTRANGE_HIGH; else if (inp->inp_flags & INP_LOWPORT) optval = IP_PORTRANGE_LOW; else optval = 0; *mtod(m, int *) = optval; break; case IP_AUTH_LEVEL: case IP_ESP_TRANS_LEVEL: case IP_ESP_NETWORK_LEVEL: case IP_IPCOMP_LEVEL: #ifndef IPSEC m->m_len = sizeof(int); *mtod(m, int *) = IPSEC_LEVEL_NONE; #else m->m_len = sizeof(int); switch (optname) { case IP_AUTH_LEVEL: optval = inp->inp_seclevel.sl_auth; break; case IP_ESP_TRANS_LEVEL: optval = inp->inp_seclevel.sl_esp_trans; break; case IP_ESP_NETWORK_LEVEL: optval = inp->inp_seclevel.sl_esp_network; break; case IP_IPCOMP_LEVEL: optval = inp->inp_seclevel.sl_ipcomp; break; } *mtod(m, int *) = optval; #endif break; case IP_IPSEC_LOCAL_ID: case IP_IPSEC_REMOTE_ID: error = EOPNOTSUPP; break; case SO_RTABLE: m->m_len = sizeof(u_int); *mtod(m, u_int *) = inp->inp_rtableid; break; case IP_PIPEX: m->m_len = sizeof(int); *mtod(m, int *) = inp->inp_pipex; break; default: error = ENOPROTOOPT; break; } break; } return (error); } /* * Set up IP options in pcb for insertion in output packets. * Store in mbuf with pointer in pcbopt, adding pseudo-option * with destination address if source routed. */ int ip_pcbopts(struct mbuf **pcbopt, struct mbuf *m) { struct mbuf *n; struct ipoption *p; int cnt, off, optlen; u_char *cp; u_char opt; /* turn off any old options */ m_freem(*pcbopt); *pcbopt = NULL; if (m == NULL || m->m_len == 0) { /* * Only turning off any previous options. */ return (0); } if (m->m_len % sizeof(int32_t) || m->m_len > MAX_IPOPTLEN + sizeof(struct in_addr)) return (EINVAL); /* Don't sleep because NET_LOCK() is hold. */ if ((n = m_get(M_NOWAIT, MT_SOOPTS)) == NULL) return (ENOBUFS); p = mtod(n, struct ipoption *); memset(p, 0, sizeof (*p)); /* 0 = IPOPT_EOL, needed for padding */ n->m_len = sizeof(struct in_addr); off = 0; cnt = m->m_len; cp = mtod(m, u_char *); while (cnt > 0) { opt = cp[IPOPT_OPTVAL]; if (opt == IPOPT_NOP || opt == IPOPT_EOL) { optlen = 1; } else { if (cnt < IPOPT_OLEN + sizeof(*cp)) goto bad; optlen = cp[IPOPT_OLEN]; if (optlen < IPOPT_OLEN + sizeof(*cp) || optlen > cnt) goto bad; } switch (opt) { default: memcpy(p->ipopt_list + off, cp, optlen); break; case IPOPT_LSRR: case IPOPT_SSRR: /* * user process specifies route as: * ->A->B->C->D * D must be our final destination (but we can't * check that since we may not have connected yet). * A is first hop destination, which doesn't appear in * actual IP option, but is stored before the options. */ if (optlen < IPOPT_MINOFF - 1 + sizeof(struct in_addr)) goto bad; /* * Optlen is smaller because first address is popped. * Cnt and cp will be adjusted a bit later to reflect * this. */ optlen -= sizeof(struct in_addr); p->ipopt_list[off + IPOPT_OPTVAL] = opt; p->ipopt_list[off + IPOPT_OLEN] = optlen; /* * Move first hop before start of options. */ memcpy(&p->ipopt_dst, cp + IPOPT_OFFSET, sizeof(struct in_addr)); cp += sizeof(struct in_addr); cnt -= sizeof(struct in_addr); /* * Then copy rest of options */ memcpy(p->ipopt_list + off + IPOPT_OFFSET, cp + IPOPT_OFFSET, optlen - IPOPT_OFFSET); break; } off += optlen; cp += optlen; cnt -= optlen; if (opt == IPOPT_EOL) break; } /* pad options to next word, since p was zeroed just adjust off */ off = (off + sizeof(int32_t) - 1) & ~(sizeof(int32_t) - 1); n->m_len += off; if (n->m_len > sizeof(*p)) { bad: m_freem(n); return (EINVAL); } *pcbopt = n; return (0); } /* * Lookup the interface based on the information in the ip_mreqn struct. */ int ip_multicast_if(struct ip_mreqn *mreq, u_int rtableid, unsigned int *ifidx) { struct sockaddr_in sin; struct rtentry *rt; /* * In case userland provides the imr_ifindex use this as interface. * If no interface address was provided, use the interface of * the route to the given multicast address. */ if (mreq->imr_ifindex != 0) { *ifidx = mreq->imr_ifindex; } else if (mreq->imr_address.s_addr == INADDR_ANY) { memset(&sin, 0, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_addr = mreq->imr_multiaddr; rt = rtalloc(sintosa(&sin), RT_RESOLVE, rtableid); if (!rtisvalid(rt)) { rtfree(rt); return EADDRNOTAVAIL; } *ifidx = rt->rt_ifidx; rtfree(rt); } else { memset(&sin, 0, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_addr = mreq->imr_address; rt = rtalloc(sintosa(&sin), 0, rtableid); if (!rtisvalid(rt) || !ISSET(rt->rt_flags, RTF_LOCAL)) { rtfree(rt); return EADDRNOTAVAIL; } *ifidx = rt->rt_ifidx; rtfree(rt); } return 0; } /* * Set the IP multicast options in response to user setsockopt(). */ int ip_setmoptions(int optname, struct ip_moptions **imop, struct mbuf *m, u_int rtableid) { struct in_addr addr; struct in_ifaddr *ia; struct ip_mreqn mreqn; struct ifnet *ifp = NULL; struct ip_moptions *imo = *imop; struct in_multi **immp; struct sockaddr_in sin; unsigned int ifidx; int i, error = 0; u_char loop; if (imo == NULL) { /* * No multicast option buffer attached to the pcb; * allocate one and initialize to default values. */ imo = malloc(sizeof(*imo), M_IPMOPTS, M_WAITOK|M_ZERO); immp = mallocarray(IP_MIN_MEMBERSHIPS, sizeof(*immp), M_IPMOPTS, M_WAITOK|M_ZERO); *imop = imo; imo->imo_ifidx = 0; imo->imo_ttl = IP_DEFAULT_MULTICAST_TTL; imo->imo_loop = IP_DEFAULT_MULTICAST_LOOP; imo->imo_num_memberships = 0; imo->imo_max_memberships = IP_MIN_MEMBERSHIPS; imo->imo_membership = immp; } switch (optname) { case IP_MULTICAST_IF: /* * Select the interface for outgoing multicast packets. */ if (m == NULL) { error = EINVAL; break; } if (m->m_len == sizeof(struct in_addr)) { addr = *(mtod(m, struct in_addr *)); } else if (m->m_len == sizeof(struct ip_mreq) || m->m_len == sizeof(struct ip_mreqn)) { memset(&mreqn, 0, sizeof(mreqn)); memcpy(&mreqn, mtod(m, void *), m->m_len); /* * If an interface index is given use this * index to set the imo_ifidx but check first * that the interface actually exists. * In the other case just set the addr to * the imr_address and fall through to the * regular code. */ if (mreqn.imr_ifindex != 0) { ifp = if_get(mreqn.imr_ifindex); if (ifp == NULL || ifp->if_rdomain != rtable_l2(rtableid)) { error = EADDRNOTAVAIL; if_put(ifp); break; } imo->imo_ifidx = ifp->if_index; if_put(ifp); break; } else addr = mreqn.imr_address; } else { error = EINVAL; break; } /* * INADDR_ANY is used to remove a previous selection. * When no interface is selected, a default one is * chosen every time a multicast packet is sent. */ if (addr.s_addr == INADDR_ANY) { imo->imo_ifidx = 0; break; } /* * The selected interface is identified by its local * IP address. Find the interface and confirm that * it supports multicasting. */ memset(&sin, 0, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_addr = addr; ia = ifatoia(ifa_ifwithaddr(sintosa(&sin), rtableid)); if (ia == NULL || (ia->ia_ifp->if_flags & IFF_MULTICAST) == 0) { error = EADDRNOTAVAIL; break; } imo->imo_ifidx = ia->ia_ifp->if_index; break; case IP_MULTICAST_TTL: /* * Set the IP time-to-live for outgoing multicast packets. */ if (m == NULL || m->m_len != 1) { error = EINVAL; break; } imo->imo_ttl = *(mtod(m, u_char *)); break; case IP_MULTICAST_LOOP: /* * Set the loopback flag for outgoing multicast packets. * Must be zero or one. */ if (m == NULL || m->m_len != 1 || (loop = *(mtod(m, u_char *))) > 1) { error = EINVAL; break; } imo->imo_loop = loop; break; case IP_ADD_MEMBERSHIP: /* * Add a multicast group membership. * Group must be a valid IP multicast address. */ if (m == NULL || !(m->m_len == sizeof(struct ip_mreq) || m->m_len == sizeof(struct ip_mreqn))) { error = EINVAL; break; } memset(&mreqn, 0, sizeof(mreqn)); memcpy(&mreqn, mtod(m, void *), m->m_len); if (!IN_MULTICAST(mreqn.imr_multiaddr.s_addr)) { error = EINVAL; break; } error = ip_multicast_if(&mreqn, rtableid, &ifidx); if (error) break; /* * See if we found an interface, and confirm that it * supports multicast. */ ifp = if_get(ifidx); if (ifp == NULL || ifp->if_rdomain != rtable_l2(rtableid) || (ifp->if_flags & IFF_MULTICAST) == 0) { error = EADDRNOTAVAIL; if_put(ifp); break; } /* * See if the membership already exists or if all the * membership slots are full. */ for (i = 0; i < imo->imo_num_memberships; ++i) { if (imo->imo_membership[i]->inm_ifidx == ifidx && imo->imo_membership[i]->inm_addr.s_addr == mreqn.imr_multiaddr.s_addr) break; } if (i < imo->imo_num_memberships) { error = EADDRINUSE; if_put(ifp); break; } if (imo->imo_num_memberships == imo->imo_max_memberships) { struct in_multi **nmships, **omships; size_t newmax; /* * Resize the vector to next power-of-two minus 1. If * the size would exceed the maximum then we know we've * really run out of entries. Otherwise, we reallocate * the vector. */ nmships = NULL; omships = imo->imo_membership; newmax = ((imo->imo_max_memberships + 1) * 2) - 1; if (newmax <= IP_MAX_MEMBERSHIPS) { nmships = mallocarray(newmax, sizeof(*nmships), M_IPMOPTS, M_NOWAIT|M_ZERO); if (nmships != NULL) { memcpy(nmships, omships, sizeof(*omships) * imo->imo_max_memberships); free(omships, M_IPMOPTS, sizeof(*omships) * imo->imo_max_memberships); imo->imo_membership = nmships; imo->imo_max_memberships = newmax; } } if (nmships == NULL) { error = ENOBUFS; if_put(ifp); break; } } /* * Everything looks good; add a new record to the multicast * address list for the given interface. */ if ((imo->imo_membership[i] = in_addmulti(&mreqn.imr_multiaddr, ifp)) == NULL) { error = ENOBUFS; if_put(ifp); break; } ++imo->imo_num_memberships; if_put(ifp); break; case IP_DROP_MEMBERSHIP: /* * Drop a multicast group membership. * Group must be a valid IP multicast address. */ if (m == NULL || !(m->m_len == sizeof(struct ip_mreq) || m->m_len == sizeof(struct ip_mreqn))) { error = EINVAL; break; } memset(&mreqn, 0, sizeof(mreqn)); memcpy(&mreqn, mtod(m, void *), m->m_len); if (!IN_MULTICAST(mreqn.imr_multiaddr.s_addr)) { error = EINVAL; break; } /* * If an interface address was specified, get a pointer * to its ifnet structure. */ error = ip_multicast_if(&mreqn, rtableid, &ifidx); if (error) break; /* * Find the membership in the membership array. */ for (i = 0; i < imo->imo_num_memberships; ++i) { if ((ifidx == 0 || imo->imo_membership[i]->inm_ifidx == ifidx) && imo->imo_membership[i]->inm_addr.s_addr == mreqn.imr_multiaddr.s_addr) break; } if (i == imo->imo_num_memberships) { error = EADDRNOTAVAIL; break; } /* * Give up the multicast address record to which the * membership points. */ in_delmulti(imo->imo_membership[i]); /* * Remove the gap in the membership array. */ for (++i; i < imo->imo_num_memberships; ++i) imo->imo_membership[i-1] = imo->imo_membership[i]; --imo->imo_num_memberships; break; default: error = EOPNOTSUPP; break; } /* * If all options have default values, no need to keep the data. */ if (imo->imo_ifidx == 0 && imo->imo_ttl == IP_DEFAULT_MULTICAST_TTL && imo->imo_loop == IP_DEFAULT_MULTICAST_LOOP && imo->imo_num_memberships == 0) { free(imo->imo_membership , M_IPMOPTS, imo->imo_max_memberships * sizeof(struct in_multi *)); free(*imop, M_IPMOPTS, sizeof(**imop)); *imop = NULL; } return (error); } /* * Return the IP multicast options in response to user getsockopt(). */ int ip_getmoptions(int optname, struct ip_moptions *imo, struct mbuf *m) { u_char *ttl; u_char *loop; struct in_addr *addr; struct in_ifaddr *ia; struct ifnet *ifp; switch (optname) { case IP_MULTICAST_IF: addr = mtod(m, struct in_addr *); m->m_len = sizeof(struct in_addr); if (imo == NULL || (ifp = if_get(imo->imo_ifidx)) == NULL) addr->s_addr = INADDR_ANY; else { IFP_TO_IA(ifp, ia); addr->s_addr = (ia == NULL) ? INADDR_ANY : ia->ia_addr.sin_addr.s_addr; if_put(ifp); } return (0); case IP_MULTICAST_TTL: ttl = mtod(m, u_char *); m->m_len = 1; *ttl = (imo == NULL) ? IP_DEFAULT_MULTICAST_TTL : imo->imo_ttl; return (0); case IP_MULTICAST_LOOP: loop = mtod(m, u_char *); m->m_len = 1; *loop = (imo == NULL) ? IP_DEFAULT_MULTICAST_LOOP : imo->imo_loop; return (0); default: return (EOPNOTSUPP); } } /* * Discard the IP multicast options. */ void ip_freemoptions(struct ip_moptions *imo) { int i; if (imo != NULL) { for (i = 0; i < imo->imo_num_memberships; ++i) in_delmulti(imo->imo_membership[i]); free(imo->imo_membership, M_IPMOPTS, imo->imo_max_memberships * sizeof(struct in_multi *)); free(imo, M_IPMOPTS, sizeof(*imo)); } } /* * Routine called from ip_output() to loop back a copy of an IP multicast * packet to the input queue of a specified interface. */ void ip_mloopback(struct ifnet *ifp, struct mbuf *m, struct sockaddr_in *dst) { struct mbuf *copym; copym = m_dup_pkt(m, max_linkhdr, M_DONTWAIT); if (copym != NULL) { /* * We don't bother to fragment if the IP length is greater * than the interface's MTU. Can this possibly matter? */ in_hdr_cksum_out(copym, NULL); if_input_local(ifp, copym, dst->sin_family); } } void in_hdr_cksum_out(struct mbuf *m, struct ifnet *ifp) { struct ip *ip = mtod(m, struct ip *); ip->ip_sum = 0; if (in_ifcap_cksum(m, ifp, IFCAP_CSUM_IPv4)) { SET(m->m_pkthdr.csum_flags, M_IPV4_CSUM_OUT); } else { ipstat_inc(ips_outswcsum); ip->ip_sum = in_cksum(m, ip->ip_hl << 2); CLR(m->m_pkthdr.csum_flags, M_IPV4_CSUM_OUT); } } /* * Compute significant parts of the IPv4 checksum pseudo-header * for use in a delayed TCP/UDP checksum calculation. */ static u_int16_t in_cksum_phdr(u_int32_t src, u_int32_t dst, u_int32_t lenproto) { u_int32_t sum; sum = lenproto + (u_int16_t)(src >> 16) + (u_int16_t)(src /*& 0xffff*/) + (u_int16_t)(dst >> 16) + (u_int16_t)(dst /*& 0xffff*/); sum = (u_int16_t)(sum >> 16) + (u_int16_t)(sum /*& 0xffff*/); if (sum > 0xffff) sum -= 0xffff; return (sum); } /* * Process a delayed payload checksum calculation. */ void in_delayed_cksum(struct mbuf *m) { struct ip *ip; u_int16_t csum, offset; ip = mtod(m, struct ip *); offset = ip->ip_hl << 2; csum = in4_cksum(m, 0, offset, m->m_pkthdr.len - offset); if (csum == 0 && ip->ip_p == IPPROTO_UDP) csum = 0xffff; switch (ip->ip_p) { case IPPROTO_TCP: offset += offsetof(struct tcphdr, th_sum); break; case IPPROTO_UDP: offset += offsetof(struct udphdr, uh_sum); break; case IPPROTO_ICMP: offset += offsetof(struct icmp, icmp_cksum); break; default: return; } if ((offset + sizeof(u_int16_t)) > m->m_len) m_copyback(m, offset, sizeof(csum), &csum, M_NOWAIT); else *(u_int16_t *)(mtod(m, caddr_t) + offset) = csum; } void in_proto_cksum_out(struct mbuf *m, struct ifnet *ifp) { struct ip *ip = mtod(m, struct ip *); /* some hw and in_delayed_cksum need the pseudo header cksum */ if (m->m_pkthdr.csum_flags & (M_TCP_CSUM_OUT|M_UDP_CSUM_OUT|M_ICMP_CSUM_OUT)) { u_int16_t csum = 0, offset; offset = ip->ip_hl << 2; if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO) && in_ifcap_cksum(m, ifp, IFCAP_TSOv4)) { csum = in_cksum_phdr(ip->ip_src.s_addr, ip->ip_dst.s_addr, htonl(ip->ip_p)); } else if (ISSET(m->m_pkthdr.csum_flags, M_TCP_CSUM_OUT|M_UDP_CSUM_OUT)) { csum = in_cksum_phdr(ip->ip_src.s_addr, ip->ip_dst.s_addr, htonl(ntohs(ip->ip_len) - offset + ip->ip_p)); } if (ip->ip_p == IPPROTO_TCP) offset += offsetof(struct tcphdr, th_sum); else if (ip->ip_p == IPPROTO_UDP) offset += offsetof(struct udphdr, uh_sum); else if (ip->ip_p == IPPROTO_ICMP) offset += offsetof(struct icmp, icmp_cksum); if ((offset + sizeof(u_int16_t)) > m->m_len) m_copyback(m, offset, sizeof(csum), &csum, M_NOWAIT); else *(u_int16_t *)(mtod(m, caddr_t) + offset) = csum; } if (m->m_pkthdr.csum_flags & M_TCP_CSUM_OUT) { if (!in_ifcap_cksum(m, ifp, IFCAP_CSUM_TCPv4) || ip->ip_hl != 5) { tcpstat_inc(tcps_outswcsum); in_delayed_cksum(m); m->m_pkthdr.csum_flags &= ~M_TCP_CSUM_OUT; /* Clear */ } } else if (m->m_pkthdr.csum_flags & M_UDP_CSUM_OUT) { if (!in_ifcap_cksum(m, ifp, IFCAP_CSUM_UDPv4) || ip->ip_hl != 5) { udpstat_inc(udps_outswcsum); in_delayed_cksum(m); m->m_pkthdr.csum_flags &= ~M_UDP_CSUM_OUT; /* Clear */ } } else if (m->m_pkthdr.csum_flags & M_ICMP_CSUM_OUT) { in_delayed_cksum(m); m->m_pkthdr.csum_flags &= ~M_ICMP_CSUM_OUT; /* Clear */ } } int in_ifcap_cksum(struct mbuf *m, struct ifnet *ifp, int ifcap) { if ((ifp == NULL) || !ISSET(ifp->if_capabilities, ifcap) || (ifp->if_bridgeidx != 0)) return (0); /* * Simplex interface sends packet back without hardware cksum. * Keep this check in sync with the condition where ether_resolve() * calls if_input_local(). */ if (ISSET(m->m_flags, M_BCAST) && ISSET(ifp->if_flags, IFF_SIMPLEX) && !m->m_pkthdr.pf.routed) return (0); return (1); }
54 10 76 55 54 98 93 7 6 3 16 67 3 5 10 68 14 76 77 59 25 8 59 49 14 2 10 11 7 12 8 5 5 7 1 13 1 24 2 2 2 1 3 4 9 5 9 6 12 3 3 3 1 2 30 1 17 23 11 2 5 5 2 2 7 6 4 56 9 77 63 69 45 4 6 9 33 18 28 20 5 4 112 109 3 3 3 3 3 8 3 5 5 2 37 7 7 7 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 /* $OpenBSD: vfs_lockf.c,v 1.50 2022/08/14 01:58:28 jsg Exp $ */ /* $NetBSD: vfs_lockf.c,v 1.7 1996/02/04 02:18:21 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Scooter Morris at Genentech Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ufs_lockf.c 8.3 (Berkeley) 1/6/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/pool.h> #include <sys/fcntl.h> #include <sys/lockf.h> #include <sys/rwlock.h> #include <sys/unistd.h> /* * The lockf structure is a kernel structure which contains the information * associated with a byte range lock. The lockf structures are linked into * the inode structure. Locks are sorted by the starting byte of the lock for * efficiency. */ TAILQ_HEAD(locklist, lockf); struct lockf { short lf_flags; /* Lock semantics: F_POSIX, F_FLOCK, F_WAIT */ short lf_type; /* Lock type: F_RDLCK, F_WRLCK */ off_t lf_start; /* The byte # of the start of the lock */ off_t lf_end; /* The byte # of the end of the lock (-1=EOF)*/ caddr_t lf_id; /* The id of the resource holding the lock */ struct lockf_state *lf_state; /* State associated with the lock */ TAILQ_ENTRY(lockf) lf_entry; struct lockf *lf_blk; /* The lock that blocks us */ struct locklist lf_blkhd; /* The list of blocked locks */ TAILQ_ENTRY(lockf) lf_block; /* A request waiting for a lock */ uid_t lf_uid; /* User ID responsible */ pid_t lf_pid; /* POSIX - owner pid */ }; struct lockf_state { TAILQ_HEAD(, lockf) ls_locks; /* list of active locks */ TAILQ_HEAD(, lockf) ls_pending; /* list of pending locks */ struct lockf_state **ls_owner; /* owner */ int ls_refs; /* reference counter */ }; struct pool lockf_state_pool; struct pool lockf_pool; #define SELF 0x1 #define OTHERS 0x2 #ifdef LOCKF_DEBUG #define DEBUG_SETLOCK 0x01 #define DEBUG_CLEARLOCK 0x02 #define DEBUG_GETLOCK 0x04 #define DEBUG_FINDOVR 0x08 #define DEBUG_SPLIT 0x10 #define DEBUG_WAKELOCK 0x20 #define DEBUG_LINK 0x40 int lockf_debug = DEBUG_SETLOCK|DEBUG_CLEARLOCK|DEBUG_WAKELOCK; void lf_print(const char *, struct lockf *); void lf_printlist(const char *, struct lockf *); #define DPRINTF(args, level) if (lockf_debug & (level)) printf args #define LFPRINT(args, level) if (lockf_debug & (level)) lf_print args #else #define DPRINTF(args, level) #define LFPRINT(args, level) #endif struct lockf *lf_alloc(uid_t, int); void lf_free(struct lockf *); int lf_clearlock(struct lockf *); int lf_findoverlap(struct lockf *, struct lockf *, int, struct lockf **); struct lockf *lf_getblock(struct lockf *, struct lockf *); int lf_getlock(struct lockf *, struct flock *); int lf_setlock(struct lockf *); void lf_split(struct lockf *, struct lockf *); void lf_wakelock(struct lockf *, int); int lf_deadlock(struct lockf *); void ls_ref(struct lockf_state *); void ls_rele(struct lockf_state *); /* * Serializes access to each instance of struct lockf and struct lockf_state * and each pointer from a vnode to struct lockf_state. */ struct rwlock lockf_lock = RWLOCK_INITIALIZER("lockflk"); void lf_init(void) { pool_init(&lockf_state_pool, sizeof(struct lockf_state), 0, IPL_NONE, PR_WAITOK | PR_RWLOCK, "lockfspl", NULL); pool_init(&lockf_pool, sizeof(struct lockf), 0, IPL_NONE, PR_WAITOK | PR_RWLOCK, "lockfpl", NULL); } void ls_ref(struct lockf_state *ls) { rw_assert_wrlock(&lockf_lock); ls->ls_refs++; } void ls_rele(struct lockf_state *ls) { rw_assert_wrlock(&lockf_lock); if (--ls->ls_refs > 0) return; KASSERT(TAILQ_EMPTY(&ls->ls_locks)); KASSERT(TAILQ_EMPTY(&ls->ls_pending)); *ls->ls_owner = NULL; pool_put(&lockf_state_pool, ls); } /* * We enforce a limit on locks by uid, so that a single user cannot * run the kernel out of memory. For now, the limit is pretty coarse. * There is no limit on root. * * Splitting a lock will always succeed, regardless of current allocations. * If you're slightly above the limit, we still have to permit an allocation * so that the unlock can succeed. If the unlocking causes too many splits, * however, you're totally cutoff. */ int maxlocksperuid = 1024; /* * 3 options for allowfail. * 0 - always allocate. 1 - cutoff at limit. 2 - cutoff at double limit. */ struct lockf * lf_alloc(uid_t uid, int allowfail) { struct uidinfo *uip; struct lockf *lock; uip = uid_find(uid); if (uid && allowfail && uip->ui_lockcnt > (allowfail == 1 ? maxlocksperuid : (maxlocksperuid * 2))) { uid_release(uip); return (NULL); } uip->ui_lockcnt++; uid_release(uip); lock = pool_get(&lockf_pool, PR_WAITOK); lock->lf_uid = uid; return (lock); } void lf_free(struct lockf *lock) { struct uidinfo *uip; rw_assert_wrlock(&lockf_lock); LFPRINT(("lf_free", lock), DEBUG_LINK); KASSERT(TAILQ_EMPTY(&lock->lf_blkhd)); ls_rele(lock->lf_state); uip = uid_find(lock->lf_uid); uip->ui_lockcnt--; uid_release(uip); pool_put(&lockf_pool, lock); } /* * Do an advisory lock operation. */ int lf_advlock(struct lockf_state **state, off_t size, caddr_t id, int op, struct flock *fl, int flags) { struct proc *p = curproc; struct lockf_state *ls; struct lockf *lock; off_t start, end; int error = 0; /* * Convert the flock structure into a start and end. */ switch (fl->l_whence) { case SEEK_SET: case SEEK_CUR: /* * Caller is responsible for adding any necessary offset * when SEEK_CUR is used. */ start = fl->l_start; break; case SEEK_END: start = size + fl->l_start; break; default: return (EINVAL); } if (start < 0) return (EINVAL); if (fl->l_len > 0) { if (fl->l_len - 1 > LLONG_MAX - start) return (EOVERFLOW); end = start + (fl->l_len - 1); /* Avoid ambiguity at the end of the range. */ if (end == LLONG_MAX) end = -1; } else if (fl->l_len < 0) { if (start + fl->l_len < 0) return (EINVAL); end = start - 1; start += fl->l_len; } else { end = -1; } rw_enter_write(&lockf_lock); ls = *state; /* * Avoid the common case of unlocking when inode has no locks. */ if (ls == NULL && op != F_SETLK) { fl->l_type = F_UNLCK; goto out; } if (ls == NULL) { ls = pool_get(&lockf_state_pool, PR_WAITOK | PR_ZERO); ls->ls_owner = state; TAILQ_INIT(&ls->ls_locks); TAILQ_INIT(&ls->ls_pending); *state = ls; } ls_ref(ls); lock = lf_alloc(p->p_ucred->cr_uid, op == F_SETLK ? 1 : 2); if (!lock) { ls_rele(ls); error = ENOLCK; goto out; } lock->lf_flags = flags; lock->lf_type = fl->l_type; lock->lf_start = start; lock->lf_end = end; lock->lf_id = id; lock->lf_state = ls; lock->lf_blk = NULL; lock->lf_pid = (flags & F_POSIX) ? p->p_p->ps_pid : -1; TAILQ_INIT(&lock->lf_blkhd); switch (op) { case F_SETLK: error = lf_setlock(lock); break; case F_UNLCK: error = lf_clearlock(lock); lf_free(lock); break; case F_GETLK: error = lf_getlock(lock, fl); lf_free(lock); break; default: lf_free(lock); error = EINVAL; break; } out: rw_exit_write(&lockf_lock); return (error); } /* * Set a byte-range lock. */ int lf_setlock(struct lockf *lock) { struct lockf *block; struct lockf *overlap, *ltmp; int ovcase, priority, needtolink, error; rw_assert_wrlock(&lockf_lock); LFPRINT(("lf_setlock", lock), DEBUG_SETLOCK); priority = PLOCK; if (lock->lf_type == F_WRLCK) priority += 4; priority |= PCATCH; /* * Scan lock list for this file looking for locks that would block us. */ for (;;) { block = lf_getblock(TAILQ_FIRST(&lock->lf_state->ls_locks), lock); if (block == NULL) break; if ((lock->lf_flags & F_WAIT) == 0) { lf_free(lock); return (EAGAIN); } /* * Lock is blocked, check for deadlock before proceeding. * Note: flock style locks cover the whole file, there is no * chance for deadlock. */ if ((lock->lf_flags & F_POSIX) && lf_deadlock(lock)) { lf_free(lock); return (EDEADLK); } /* * For flock type locks, we must first remove * any shared locks that we hold before we sleep * waiting for an exclusive lock. */ if ((lock->lf_flags & F_FLOCK) && lock->lf_type == F_WRLCK) { lock->lf_type = F_UNLCK; (void)lf_clearlock(lock); lock->lf_type = F_WRLCK; } /* * Add our lock to the blocked list and sleep until we're free. * Remember who blocked us (for deadlock detection). */ lock->lf_blk = block; LFPRINT(("lf_setlock", lock), DEBUG_SETLOCK); LFPRINT(("lf_setlock: blocking on", block), DEBUG_SETLOCK); TAILQ_INSERT_TAIL(&block->lf_blkhd, lock, lf_block); TAILQ_INSERT_TAIL(&lock->lf_state->ls_pending, lock, lf_entry); error = rwsleep_nsec(lock, &lockf_lock, priority, "lockf", INFSLP); TAILQ_REMOVE(&lock->lf_state->ls_pending, lock, lf_entry); wakeup_one(lock->lf_state); if (lock->lf_blk != NULL) { TAILQ_REMOVE(&lock->lf_blk->lf_blkhd, lock, lf_block); lock->lf_blk = NULL; } if (error) { lf_free(lock); return (error); } if (lock->lf_flags & F_INTR) { lf_free(lock); return (EINTR); } } /* * No blocks!! Add the lock. Note that we will * downgrade or upgrade any overlapping locks this * process already owns. * * Skip over locks owned by other processes. * Handle any locks that overlap and are owned by ourselves. */ block = TAILQ_FIRST(&lock->lf_state->ls_locks); overlap = NULL; needtolink = 1; for (;;) { ovcase = lf_findoverlap(block, lock, SELF, &overlap); if (ovcase) block = TAILQ_NEXT(overlap, lf_entry); /* * Six cases: * 0) no overlap * 1) overlap == lock * 2) overlap contains lock * 3) lock contains overlap * 4) overlap starts before lock * 5) overlap ends after lock */ switch (ovcase) { case 0: /* no overlap */ if (needtolink) { if (overlap) /* insert before overlap */ TAILQ_INSERT_BEFORE(overlap, lock, lf_entry); else /* first or last lock in list */ TAILQ_INSERT_TAIL(&lock->lf_state->ls_locks, lock, lf_entry); } break; case 1: /* overlap == lock */ /* * If downgrading lock, others may be * able to acquire it. */ if (lock->lf_type == F_RDLCK && overlap->lf_type == F_WRLCK) lf_wakelock(overlap, 0); overlap->lf_type = lock->lf_type; lf_free(lock); lock = overlap; /* for debug output below */ break; case 2: /* overlap contains lock */ /* * Check for common starting point and different types. */ if (overlap->lf_type == lock->lf_type) { if (!needtolink) TAILQ_REMOVE(&lock->lf_state->ls_locks, lock, lf_entry); lf_free(lock); lock = overlap; /* for debug output below */ break; } if (overlap->lf_start == lock->lf_start) { if (!needtolink) TAILQ_REMOVE(&lock->lf_state->ls_locks, lock, lf_entry); TAILQ_INSERT_BEFORE(overlap, lock, lf_entry); overlap->lf_start = lock->lf_end + 1; } else lf_split(overlap, lock); lf_wakelock(overlap, 0); break; case 3: /* lock contains overlap */ /* * If downgrading lock, others may be able to * acquire it, otherwise take the list. */ if (lock->lf_type == F_RDLCK && overlap->lf_type == F_WRLCK) { lf_wakelock(overlap, 0); } else { while ((ltmp = TAILQ_FIRST(&overlap->lf_blkhd))) { TAILQ_REMOVE(&overlap->lf_blkhd, ltmp, lf_block); ltmp->lf_blk = lock; TAILQ_INSERT_TAIL(&lock->lf_blkhd, ltmp, lf_block); } } /* * Add the new lock if necessary and delete the overlap. */ if (needtolink) { TAILQ_INSERT_BEFORE(overlap, lock, lf_entry); needtolink = 0; } TAILQ_REMOVE(&lock->lf_state->ls_locks, overlap, lf_entry); lf_free(overlap); continue; case 4: /* overlap starts before lock */ /* * Add lock after overlap on the list. */ if (!needtolink) TAILQ_REMOVE(&lock->lf_state->ls_locks, lock, lf_entry); TAILQ_INSERT_AFTER(&lock->lf_state->ls_locks, overlap, lock, lf_entry); overlap->lf_end = lock->lf_start - 1; lf_wakelock(overlap, 0); needtolink = 0; continue; case 5: /* overlap ends after lock */ /* * Add the new lock before overlap. */ if (needtolink) TAILQ_INSERT_BEFORE(overlap, lock, lf_entry); overlap->lf_start = lock->lf_end + 1; lf_wakelock(overlap, 0); break; } break; } LFPRINT(("lf_setlock: got the lock", lock), DEBUG_SETLOCK); return (0); } /* * Remove a byte-range lock on an inode. * * Generally, find the lock (or an overlap to that lock) * and remove it (or shrink it), then wakeup anyone we can. */ int lf_clearlock(struct lockf *lock) { struct lockf *lf, *overlap; int ovcase; rw_assert_wrlock(&lockf_lock); lf = TAILQ_FIRST(&lock->lf_state->ls_locks); if (lf == NULL) return (0); LFPRINT(("lf_clearlock", lock), DEBUG_CLEARLOCK); while ((ovcase = lf_findoverlap(lf, lock, SELF, &overlap))) { lf_wakelock(overlap, 0); switch (ovcase) { case 1: /* overlap == lock */ TAILQ_REMOVE(&lock->lf_state->ls_locks, overlap, lf_entry); lf_free(overlap); break; case 2: /* overlap contains lock: split it */ if (overlap->lf_start == lock->lf_start) { overlap->lf_start = lock->lf_end + 1; break; } lf_split(overlap, lock); /* * The lock is now part of the list, lf_clearlock() must * ensure that the lock remains detached from the list. */ TAILQ_REMOVE(&lock->lf_state->ls_locks, lock, lf_entry); break; case 3: /* lock contains overlap */ lf = TAILQ_NEXT(overlap, lf_entry); TAILQ_REMOVE(&lock->lf_state->ls_locks, overlap, lf_entry); lf_free(overlap); continue; case 4: /* overlap starts before lock */ overlap->lf_end = lock->lf_start - 1; lf = TAILQ_NEXT(overlap, lf_entry); continue; case 5: /* overlap ends after lock */ overlap->lf_start = lock->lf_end + 1; break; } break; } return (0); } /* * Check whether there is a blocking lock, * and if so return its process identifier. */ int lf_getlock(struct lockf *lock, struct flock *fl) { struct lockf *block, *lf; rw_assert_wrlock(&lockf_lock); LFPRINT(("lf_getlock", lock), DEBUG_CLEARLOCK); lf = TAILQ_FIRST(&lock->lf_state->ls_locks); if ((block = lf_getblock(lf, lock)) != NULL) { fl->l_type = block->lf_type; fl->l_whence = SEEK_SET; fl->l_start = block->lf_start; if (block->lf_end == -1) fl->l_len = 0; else fl->l_len = block->lf_end - block->lf_start + 1; fl->l_pid = block->lf_pid; } else { fl->l_type = F_UNLCK; } return (0); } /* * Walk the list of locks for an inode and * return the first blocking lock. */ struct lockf * lf_getblock(struct lockf *lf, struct lockf *lock) { struct lockf *overlap; rw_assert_wrlock(&lockf_lock); while (lf_findoverlap(lf, lock, OTHERS, &overlap) != 0) { /* * We've found an overlap, see if it blocks us */ if ((lock->lf_type == F_WRLCK || overlap->lf_type == F_WRLCK)) return (overlap); /* * Nope, point to the next one on the list and * see if it blocks us */ lf = TAILQ_NEXT(overlap, lf_entry); } return (NULL); } /* * Walk the list of locks for an inode to * find an overlapping lock (if any). * * NOTE: this returns only the FIRST overlapping lock. There * may be more than one. */ int lf_findoverlap(struct lockf *lf, struct lockf *lock, int type, struct lockf **overlap) { off_t start, end; rw_assert_wrlock(&lockf_lock); LFPRINT(("lf_findoverlap: looking for overlap in", lock), DEBUG_FINDOVR); *overlap = lf; start = lock->lf_start; end = lock->lf_end; while (lf != NULL) { if (((type & SELF) && lf->lf_id != lock->lf_id) || ((type & OTHERS) && lf->lf_id == lock->lf_id)) { *overlap = lf = TAILQ_NEXT(lf, lf_entry); continue; } LFPRINT(("\tchecking", lf), DEBUG_FINDOVR); /* * OK, check for overlap * * Six cases: * 0) no overlap * 1) overlap == lock * 2) overlap contains lock * 3) lock contains overlap * 4) overlap starts before lock * 5) overlap ends after lock */ /* Case 0 */ if ((lf->lf_end != -1 && start > lf->lf_end) || (end != -1 && lf->lf_start > end)) { DPRINTF(("no overlap\n"), DEBUG_FINDOVR); if ((type & SELF) && end != -1 && lf->lf_start > end) return (0); *overlap = lf = TAILQ_NEXT(lf, lf_entry); continue; } /* Case 1 */ if ((lf->lf_start == start) && (lf->lf_end == end)) { DPRINTF(("overlap == lock\n"), DEBUG_FINDOVR); return (1); } /* Case 2 */ if ((lf->lf_start <= start) && (lf->lf_end == -1 || (end != -1 && lf->lf_end >= end))) { DPRINTF(("overlap contains lock\n"), DEBUG_FINDOVR); return (2); } /* Case 3 */ if (start <= lf->lf_start && (end == -1 || (lf->lf_end != -1 && end >= lf->lf_end))) { DPRINTF(("lock contains overlap\n"), DEBUG_FINDOVR); return (3); } /* Case 4 */ if ((lf->lf_start < start) && ((lf->lf_end >= start) || (lf->lf_end == -1))) { DPRINTF(("overlap starts before lock\n"), DEBUG_FINDOVR); return (4); } /* Case 5 */ if ((lf->lf_start > start) && (end != -1) && ((lf->lf_end > end) || (lf->lf_end == -1))) { DPRINTF(("overlap ends after lock\n"), DEBUG_FINDOVR); return (5); } panic("lf_findoverlap: default"); } return (0); } /* * Purge all locks associated with the given lock state. */ void lf_purgelocks(struct lockf_state **state) { struct lockf_state *ls; struct lockf *lock; rw_enter_write(&lockf_lock); ls = *state; if (ls == NULL) goto out; ls_ref(ls); /* Interrupt blocked locks and wait for all of them to finish. */ TAILQ_FOREACH(lock, &ls->ls_locks, lf_entry) { LFPRINT(("lf_purgelocks: wakeup", lock), DEBUG_SETLOCK); lf_wakelock(lock, F_INTR); } while (!TAILQ_EMPTY(&ls->ls_pending)) rwsleep_nsec(ls, &lockf_lock, PLOCK, "lockfp", INFSLP); /* * Any remaining locks cannot block other locks at this point and can * safely be removed. */ while ((lock = TAILQ_FIRST(&ls->ls_locks))) { TAILQ_REMOVE(&ls->ls_locks, lock, lf_entry); lf_free(lock); } /* This is the last expected thread to hold a lock state reference. */ KASSERT(ls->ls_refs == 1); ls_rele(ls); out: rw_exit_write(&lockf_lock); } /* * Split a lock and a contained region into * two or three locks as necessary. */ void lf_split(struct lockf *lock1, struct lockf *lock2) { struct lockf *splitlock; rw_assert_wrlock(&lockf_lock); LFPRINT(("lf_split", lock1), DEBUG_SPLIT); LFPRINT(("splitting from", lock2), DEBUG_SPLIT); /* * Check to see if splitting into only two pieces. */ if (lock1->lf_start == lock2->lf_start) { lock1->lf_start = lock2->lf_end + 1; TAILQ_INSERT_BEFORE(lock1, lock2, lf_entry); return; } if (lock1->lf_end == lock2->lf_end) { lock1->lf_end = lock2->lf_start - 1; TAILQ_INSERT_AFTER(&lock1->lf_state->ls_locks, lock1, lock2, lf_entry); return; } /* * Make a new lock consisting of the last part of * the encompassing lock */ splitlock = lf_alloc(lock1->lf_uid, 0); splitlock->lf_flags = lock1->lf_flags; splitlock->lf_type = lock1->lf_type; splitlock->lf_start = lock2->lf_end + 1; splitlock->lf_end = lock1->lf_end; splitlock->lf_id = lock1->lf_id; splitlock->lf_state = lock1->lf_state; splitlock->lf_blk = NULL; splitlock->lf_pid = lock1->lf_pid; TAILQ_INIT(&splitlock->lf_blkhd); ls_ref(splitlock->lf_state); lock1->lf_end = lock2->lf_start - 1; TAILQ_INSERT_AFTER(&lock1->lf_state->ls_locks, lock1, lock2, lf_entry); TAILQ_INSERT_AFTER(&lock1->lf_state->ls_locks, lock2, splitlock, lf_entry); } /* * Wakeup a blocklist */ void lf_wakelock(struct lockf *lock, int flags) { struct lockf *wakelock; rw_assert_wrlock(&lockf_lock); while ((wakelock = TAILQ_FIRST(&lock->lf_blkhd))) { TAILQ_REMOVE(&lock->lf_blkhd, wakelock, lf_block); wakelock->lf_blk = NULL; wakelock->lf_flags |= flags; wakeup_one(wakelock); } } /* * Returns non-zero if the given lock would cause a deadlock. */ int lf_deadlock(struct lockf *lock) { struct lockf *block, *lf, *pending; lf = TAILQ_FIRST(&lock->lf_state->ls_locks); for (; (block = lf_getblock(lf, lock)) != NULL; lf = TAILQ_NEXT(block, lf_entry)) { if ((block->lf_flags & F_POSIX) == 0) continue; TAILQ_FOREACH(pending, &lock->lf_state->ls_pending, lf_entry) { if (pending->lf_blk == NULL) continue; /* lock already unblocked */ if (pending->lf_pid == block->lf_pid && pending->lf_blk->lf_pid == lock->lf_pid) return (1); } } return (0); } #ifdef LOCKF_DEBUG /* * Print out a lock. */ void lf_print(const char *tag, struct lockf *lock) { struct lockf *block; if (tag) printf("%s: ", tag); printf("lock %p", lock); if (lock == NULL) { printf("\n"); return; } printf(", %s %p %s, start %lld, end %lld", lock->lf_flags & F_POSIX ? "posix" : "flock", lock->lf_id, lock->lf_type == F_RDLCK ? "shared" : lock->lf_type == F_WRLCK ? "exclusive" : lock->lf_type == F_UNLCK ? "unlock" : "unknown", lock->lf_start, lock->lf_end); printf(", next %p, state %p", TAILQ_NEXT(lock, lf_entry), lock->lf_state); block = TAILQ_FIRST(&lock->lf_blkhd); if (block) printf(", block"); TAILQ_FOREACH(block, &lock->lf_blkhd, lf_block) printf(" %p,", block); printf("\n"); } void lf_printlist(const char *tag, struct lockf *lock) { struct lockf *lf; printf("%s: Lock list:\n", tag); TAILQ_FOREACH(lf, &lock->lf_state->ls_locks, lf_entry) { if (lock == lf) printf(" * "); else printf(" "); lf_print(NULL, lf); } } #endif /* LOCKF_DEBUG */
178 178 177 178 177 178 72 109 109 178 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 /* $OpenBSD: in_cksum.c,v 1.9 2019/04/22 22:47:49 bluhm Exp $ */ /* $NetBSD: in_cksum.c,v 1.11 1996/04/08 19:55:37 jonathan Exp $ */ /* * Copyright (c) 1988, 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93 */ #include <sys/param.h> #include <sys/mbuf.h> #include <sys/systm.h> /* * Checksum routine for Internet Protocol family headers (Portable Version). * * This routine is very heavily used in the network * code and should be modified for each CPU to be as fast as possible. */ #define ADDCARRY(x) (x > 65535 ? x -= 65535 : x) #define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);} int in_cksum(struct mbuf *m, int len) { uint16_t *w; int sum = 0; int mlen = 0; int byte_swapped = 0; union { uint8_t c[2]; uint16_t s; } s_util; union { uint16_t s[2]; uint32_t l; } l_util; for (;m && len; m = m->m_next) { if (m->m_len == 0) continue; w = mtod(m, uint16_t *); if (mlen == -1) { /* * The first byte of this mbuf is the continuation * of a word spanning between this mbuf and the * last mbuf. * * s_util.c[0] is already saved when scanning previous * mbuf. */ s_util.c[1] = *(uint8_t *)w; sum += s_util.s; w = (uint16_t *)((uint8_t *)w + 1); mlen = m->m_len - 1; len--; } else mlen = m->m_len; if (len < mlen) mlen = len; len -= mlen; /* * Force to even boundary. */ if ((1 & (long) w) && (mlen > 0)) { REDUCE; sum <<= 8; s_util.c[0] = *(uint8_t *)w; w = (uint16_t *)((uint8_t *)w + 1); mlen--; byte_swapped = 1; } /* * Unroll the loop to make overhead from * branches &c small. */ while ((mlen -= 32) >= 0) { sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11]; sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15]; w += 16; } mlen += 32; while ((mlen -= 8) >= 0) { sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; w += 4; } mlen += 8; if (mlen == 0 && byte_swapped == 0) continue; REDUCE; while ((mlen -= 2) >= 0) { sum += *w++; } if (byte_swapped) { REDUCE; sum <<= 8; byte_swapped = 0; if (mlen == -1) { s_util.c[1] = *(uint8_t *)w; sum += s_util.s; mlen = 0; } else mlen = -1; } else if (mlen == -1) s_util.c[0] = *(uint8_t *)w; } if (len) panic("%s: out of data, len %d", __func__, len); if (mlen == -1) { /* The last mbuf has odd # of bytes. Follow the standard (the odd byte may be shifted left by 8 bits or not as determined by endian-ness of the machine) */ s_util.c[1] = 0; sum += s_util.s; } REDUCE; return (~sum & 0xffff); }
160 146 14 14 14 215 14 4 10 5 5 2 2 2 14 14 13 3 5 5 1 3 1 1 3 3 1 1 1 1 5 16 2 4 25 8 3 16 8 8 8 27 27 10 16 4 5 4 2 2 28 27 6 10 2 26 16 22 6 10 1 9 11 12 7 20 4 3 40 5 6 176 28 74 41 205 58 166 165 205 202 201 4 4 3 3 4 133 3 1 118 2 9 3 11 48 2 97 15 79 100 34 70 3 61 44 6 32 6 35 6 102 294 295 186 295 292 272 271 78 4 36 241 15 259 81 9 231 4 233 8 31 4 34 246 46 2 53 6 8 5 59 218 216 149 117 1 48 29 30 47 1 3 3 202 45 211 36 13 24 220 51 224 105 29 13 11 2 142 24 68 24 5 114 5 1 114 113 73 1 1 108 20 38 4 69 4 106 6 39 10 63 60 63 114 104 146 38 112 2 2 8 16 16 11 5 16 16 16 15 1 16 183 97 256 9 11 31 146 191 3 56 254 255 122 128 238 194 195 195 1766 1766 1767 40 169 74 74 14 47 13 7 24 13 26 13 13 226 227 226 19 71 242 215 33 159 149 15 162 162 137 28 162 20 144 238 238 30 30 38 86 69 77 30 142 142 106 112 112 134 135 56 61 61 61 40 42 43 20 20 20 20 3 3 3 3 19 351 6 351 6 678 681 337 337 84 135 14 14 16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 /* $OpenBSD: kern_event.c,v 1.198 2023/08/20 15:13:43 visa Exp $ */ /*- * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD: src/sys/kern/kern_event.c,v 1.22 2001/02/23 20:32:42 jlemon Exp $ */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/pledge.h> #include <sys/malloc.h> #include <sys/file.h> #include <sys/filedesc.h> #include <sys/fcntl.h> #include <sys/queue.h> #include <sys/event.h> #include <sys/eventvar.h> #include <sys/ktrace.h> #include <sys/pool.h> #include <sys/stat.h> #include <sys/mount.h> #include <sys/syscallargs.h> #include <sys/time.h> #include <sys/timeout.h> #include <sys/vnode.h> #include <sys/wait.h> #ifdef DIAGNOSTIC #define KLIST_ASSERT_LOCKED(kl) do { \ if ((kl)->kl_ops != NULL) \ (kl)->kl_ops->klo_assertlk((kl)->kl_arg); \ else \ KERNEL_ASSERT_LOCKED(); \ } while (0) #else #define KLIST_ASSERT_LOCKED(kl) ((void)(kl)) #endif int dokqueue(struct proc *, int, register_t *); struct kqueue *kqueue_alloc(struct filedesc *); void kqueue_terminate(struct proc *p, struct kqueue *); void KQREF(struct kqueue *); void KQRELE(struct kqueue *); void kqueue_purge(struct proc *, struct kqueue *); int kqueue_sleep(struct kqueue *, struct timespec *); int kqueue_read(struct file *, struct uio *, int); int kqueue_write(struct file *, struct uio *, int); int kqueue_ioctl(struct file *fp, u_long com, caddr_t data, struct proc *p); int kqueue_kqfilter(struct file *fp, struct knote *kn); int kqueue_stat(struct file *fp, struct stat *st, struct proc *p); int kqueue_close(struct file *fp, struct proc *p); void kqueue_wakeup(struct kqueue *kq); #ifdef KQUEUE_DEBUG void kqueue_do_check(struct kqueue *kq, const char *func, int line); #define kqueue_check(kq) kqueue_do_check((kq), __func__, __LINE__) #else #define kqueue_check(kq) do {} while (0) #endif static int filter_attach(struct knote *kn); static void filter_detach(struct knote *kn); static int filter_event(struct knote *kn, long hint); static int filter_modify(struct kevent *kev, struct knote *kn); static int filter_process(struct knote *kn, struct kevent *kev); static void kqueue_expand_hash(struct kqueue *kq); static void kqueue_expand_list(struct kqueue *kq, int fd); static void kqueue_task(void *); static int klist_lock(struct klist *); static void klist_unlock(struct klist *, int); const struct fileops kqueueops = { .fo_read = kqueue_read, .fo_write = kqueue_write, .fo_ioctl = kqueue_ioctl, .fo_kqfilter = kqueue_kqfilter, .fo_stat = kqueue_stat, .fo_close = kqueue_close }; void knote_attach(struct knote *kn); void knote_detach(struct knote *kn); void knote_drop(struct knote *kn, struct proc *p); void knote_enqueue(struct knote *kn); void knote_dequeue(struct knote *kn); int knote_acquire(struct knote *kn, struct klist *, int); void knote_release(struct knote *kn); void knote_activate(struct knote *kn); void knote_remove(struct proc *p, struct kqueue *kq, struct knlist **plist, int idx, int purge); void filt_kqdetach(struct knote *kn); int filt_kqueue(struct knote *kn, long hint); int filt_kqueuemodify(struct kevent *kev, struct knote *kn); int filt_kqueueprocess(struct knote *kn, struct kevent *kev); int filt_kqueue_common(struct knote *kn, struct kqueue *kq); int filt_procattach(struct knote *kn); void filt_procdetach(struct knote *kn); int filt_proc(struct knote *kn, long hint); int filt_fileattach(struct knote *kn); void filt_timerexpire(void *knx); int filt_timerattach(struct knote *kn); void filt_timerdetach(struct knote *kn); int filt_timermodify(struct kevent *kev, struct knote *kn); int filt_timerprocess(struct knote *kn, struct kevent *kev); void filt_seltruedetach(struct knote *kn); const struct filterops kqread_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_kqdetach, .f_event = filt_kqueue, .f_modify = filt_kqueuemodify, .f_process = filt_kqueueprocess, }; const struct filterops proc_filtops = { .f_flags = 0, .f_attach = filt_procattach, .f_detach = filt_procdetach, .f_event = filt_proc, }; const struct filterops file_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = filt_fileattach, .f_detach = NULL, .f_event = NULL, }; const struct filterops timer_filtops = { .f_flags = 0, .f_attach = filt_timerattach, .f_detach = filt_timerdetach, .f_event = NULL, .f_modify = filt_timermodify, .f_process = filt_timerprocess, }; struct pool knote_pool; struct pool kqueue_pool; struct mutex kqueue_klist_lock = MUTEX_INITIALIZER(IPL_MPFLOOR); int kq_ntimeouts = 0; int kq_timeoutmax = (4 * 1024); #define KN_HASH(val, mask) (((val) ^ (val >> 8)) & (mask)) /* * Table for all system-defined filters. */ const struct filterops *const sysfilt_ops[] = { &file_filtops, /* EVFILT_READ */ &file_filtops, /* EVFILT_WRITE */ NULL, /*&aio_filtops,*/ /* EVFILT_AIO */ &file_filtops, /* EVFILT_VNODE */ &proc_filtops, /* EVFILT_PROC */ &sig_filtops, /* EVFILT_SIGNAL */ &timer_filtops, /* EVFILT_TIMER */ &file_filtops, /* EVFILT_DEVICE */ &file_filtops, /* EVFILT_EXCEPT */ }; void KQREF(struct kqueue *kq) { refcnt_take(&kq->kq_refcnt); } void KQRELE(struct kqueue *kq) { struct filedesc *fdp; if (refcnt_rele(&kq->kq_refcnt) == 0) return; fdp = kq->kq_fdp; if (rw_status(&fdp->fd_lock) == RW_WRITE) { LIST_REMOVE(kq, kq_next); } else { fdplock(fdp); LIST_REMOVE(kq, kq_next); fdpunlock(fdp); } KASSERT(TAILQ_EMPTY(&kq->kq_head)); KASSERT(kq->kq_nknotes == 0); free(kq->kq_knlist, M_KEVENT, kq->kq_knlistsize * sizeof(struct knlist)); hashfree(kq->kq_knhash, KN_HASHSIZE, M_KEVENT); klist_free(&kq->kq_klist); pool_put(&kqueue_pool, kq); } void kqueue_init(void) { pool_init(&kqueue_pool, sizeof(struct kqueue), 0, IPL_MPFLOOR, PR_WAITOK, "kqueuepl", NULL); pool_init(&knote_pool, sizeof(struct knote), 0, IPL_MPFLOOR, PR_WAITOK, "knotepl", NULL); } void kqueue_init_percpu(void) { pool_cache_init(&knote_pool); } int filt_fileattach(struct knote *kn) { struct file *fp = kn->kn_fp; return fp->f_ops->fo_kqfilter(fp, kn); } int kqueue_kqfilter(struct file *fp, struct knote *kn) { struct kqueue *kq = kn->kn_fp->f_data; if (kn->kn_filter != EVFILT_READ) return (EINVAL); kn->kn_fop = &kqread_filtops; klist_insert(&kq->kq_klist, kn); return (0); } void filt_kqdetach(struct knote *kn) { struct kqueue *kq = kn->kn_fp->f_data; klist_remove(&kq->kq_klist, kn); } int filt_kqueue_common(struct knote *kn, struct kqueue *kq) { MUTEX_ASSERT_LOCKED(&kq->kq_lock); kn->kn_data = kq->kq_count; return (kn->kn_data > 0); } int filt_kqueue(struct knote *kn, long hint) { struct kqueue *kq = kn->kn_fp->f_data; int active; mtx_enter(&kq->kq_lock); active = filt_kqueue_common(kn, kq); mtx_leave(&kq->kq_lock); return (active); } int filt_kqueuemodify(struct kevent *kev, struct knote *kn) { struct kqueue *kq = kn->kn_fp->f_data; int active; mtx_enter(&kq->kq_lock); knote_assign(kev, kn); active = filt_kqueue_common(kn, kq); mtx_leave(&kq->kq_lock); return (active); } int filt_kqueueprocess(struct knote *kn, struct kevent *kev) { struct kqueue *kq = kn->kn_fp->f_data; int active; mtx_enter(&kq->kq_lock); if (kev != NULL && (kn->kn_flags & EV_ONESHOT)) active = 1; else active = filt_kqueue_common(kn, kq); if (active) knote_submit(kn, kev); mtx_leave(&kq->kq_lock); return (active); } int filt_procattach(struct knote *kn) { struct process *pr; int s; if ((curproc->p_p->ps_flags & PS_PLEDGE) && (curproc->p_p->ps_pledge & PLEDGE_PROC) == 0) return pledge_fail(curproc, EPERM, PLEDGE_PROC); if (kn->kn_id > PID_MAX) return ESRCH; pr = prfind(kn->kn_id); if (pr == NULL) return (ESRCH); /* exiting processes can't be specified */ if (pr->ps_flags & PS_EXITING) return (ESRCH); kn->kn_ptr.p_process = pr; kn->kn_flags |= EV_CLEAR; /* automatically set */ /* * internal flag indicating registration done by kernel */ if (kn->kn_flags & EV_FLAG1) { kn->kn_data = kn->kn_sdata; /* ppid */ kn->kn_fflags = NOTE_CHILD; kn->kn_flags &= ~EV_FLAG1; } s = splhigh(); klist_insert_locked(&pr->ps_klist, kn); splx(s); return (0); } /* * The knote may be attached to a different process, which may exit, * leaving nothing for the knote to be attached to. So when the process * exits, the knote is marked as DETACHED and also flagged as ONESHOT so * it will be deleted when read out. However, as part of the knote deletion, * this routine is called, so a check is needed to avoid actually performing * a detach, because the original process does not exist any more. */ void filt_procdetach(struct knote *kn) { struct kqueue *kq = kn->kn_kq; struct process *pr = kn->kn_ptr.p_process; int s, status; mtx_enter(&kq->kq_lock); status = kn->kn_status; mtx_leave(&kq->kq_lock); if (status & KN_DETACHED) return; s = splhigh(); klist_remove_locked(&pr->ps_klist, kn); splx(s); } int filt_proc(struct knote *kn, long hint) { struct kqueue *kq = kn->kn_kq; u_int event; /* * mask off extra data */ event = (u_int)hint & NOTE_PCTRLMASK; /* * if the user is interested in this event, record it. */ if (kn->kn_sfflags & event) kn->kn_fflags |= event; /* * process is gone, so flag the event as finished and remove it * from the process's klist */ if (event == NOTE_EXIT) { struct process *pr = kn->kn_ptr.p_process; int s; mtx_enter(&kq->kq_lock); kn->kn_status |= KN_DETACHED; mtx_leave(&kq->kq_lock); s = splhigh(); kn->kn_flags |= (EV_EOF | EV_ONESHOT); kn->kn_data = W_EXITCODE(pr->ps_xexit, pr->ps_xsig); klist_remove_locked(&pr->ps_klist, kn); splx(s); return (1); } /* * process forked, and user wants to track the new process, * so attach a new knote to it, and immediately report an * event with the parent's pid. */ if ((event == NOTE_FORK) && (kn->kn_sfflags & NOTE_TRACK)) { struct kevent kev; int error; /* * register knote with new process. */ memset(&kev, 0, sizeof(kev)); kev.ident = hint & NOTE_PDATAMASK; /* pid */ kev.filter = kn->kn_filter; kev.flags = kn->kn_flags | EV_ADD | EV_ENABLE | EV_FLAG1; kev.fflags = kn->kn_sfflags; kev.data = kn->kn_id; /* parent */ kev.udata = kn->kn_udata; /* preserve udata */ error = kqueue_register(kq, &kev, 0, NULL); if (error) kn->kn_fflags |= NOTE_TRACKERR; } return (kn->kn_fflags != 0); } #define NOTE_TIMER_UNITMASK \ (NOTE_SECONDS|NOTE_MSECONDS|NOTE_USECONDS|NOTE_NSECONDS) static int filt_timervalidate(int sfflags, int64_t sdata, struct timespec *ts) { if (sfflags & ~(NOTE_TIMER_UNITMASK | NOTE_ABSTIME)) return (EINVAL); switch (sfflags & NOTE_TIMER_UNITMASK) { case NOTE_SECONDS: ts->tv_sec = sdata; ts->tv_nsec = 0; break; case NOTE_MSECONDS: ts->tv_sec = sdata / 1000; ts->tv_nsec = (sdata % 1000) * 1000000; break; case NOTE_USECONDS: ts->tv_sec = sdata / 1000000; ts->tv_nsec = (sdata % 1000000) * 1000; break; case NOTE_NSECONDS: ts->tv_sec = sdata / 1000000000; ts->tv_nsec = sdata % 1000000000; break; default: return (EINVAL); } return (0); } static void filt_timeradd(struct knote *kn, struct timespec *ts) { struct timespec expiry, now; struct timeout *to = kn->kn_hook; int tticks; if (kn->kn_sfflags & NOTE_ABSTIME) { nanotime(&now); if (timespeccmp(ts, &now, >)) { timespecsub(ts, &now, &expiry); /* XXX timeout_abs_ts with CLOCK_REALTIME */ timeout_add(to, tstohz(&expiry)); } else { /* Expire immediately. */ filt_timerexpire(kn); } return; } tticks = tstohz(ts); /* Remove extra tick from tstohz() if timeout has fired before. */ if (timeout_triggered(to)) tticks--; timeout_add(to, (tticks > 0) ? tticks : 1); } void filt_timerexpire(void *knx) { struct timespec ts; struct knote *kn = knx; struct kqueue *kq = kn->kn_kq; kn->kn_data++; mtx_enter(&kq->kq_lock); knote_activate(kn); mtx_leave(&kq->kq_lock); if ((kn->kn_flags & EV_ONESHOT) == 0 && (kn->kn_sfflags & NOTE_ABSTIME) == 0) { (void)filt_timervalidate(kn->kn_sfflags, kn->kn_sdata, &ts); filt_timeradd(kn, &ts); } } /* * data contains amount of time to sleep */ int filt_timerattach(struct knote *kn) { struct timespec ts; struct timeout *to; int error; error = filt_timervalidate(kn->kn_sfflags, kn->kn_sdata, &ts); if (error != 0) return (error); if (kq_ntimeouts > kq_timeoutmax) return (ENOMEM); kq_ntimeouts++; if ((kn->kn_sfflags & NOTE_ABSTIME) == 0) kn->kn_flags |= EV_CLEAR; /* automatically set */ to = malloc(sizeof(*to), M_KEVENT, M_WAITOK); timeout_set(to, filt_timerexpire, kn); kn->kn_hook = to; filt_timeradd(kn, &ts); return (0); } void filt_timerdetach(struct knote *kn) { struct timeout *to; to = (struct timeout *)kn->kn_hook; timeout_del_barrier(to); free(to, M_KEVENT, sizeof(*to)); kq_ntimeouts--; } int filt_timermodify(struct kevent *kev, struct knote *kn) { struct timespec ts; struct kqueue *kq = kn->kn_kq; struct timeout *to = kn->kn_hook; int error; error = filt_timervalidate(kev->fflags, kev->data, &ts); if (error != 0) { kev->flags |= EV_ERROR; kev->data = error; return (0); } /* Reset the timer. Any pending events are discarded. */ timeout_del_barrier(to); mtx_enter(&kq->kq_lock); if (kn->kn_status & KN_QUEUED) knote_dequeue(kn); kn->kn_status &= ~KN_ACTIVE; mtx_leave(&kq->kq_lock); kn->kn_data = 0; knote_assign(kev, kn); /* Reinit timeout to invoke tick adjustment again. */ timeout_set(to, filt_timerexpire, kn); filt_timeradd(kn, &ts); return (0); } int filt_timerprocess(struct knote *kn, struct kevent *kev) { int active, s; s = splsoftclock(); active = (kn->kn_data != 0); if (active) knote_submit(kn, kev); splx(s); return (active); } /* * filt_seltrue: * * This filter "event" routine simulates seltrue(). */ int filt_seltrue(struct knote *kn, long hint) { /* * We don't know how much data can be read/written, * but we know that it *can* be. This is about as * good as select/poll does as well. */ kn->kn_data = 0; return (1); } int filt_seltruemodify(struct kevent *kev, struct knote *kn) { knote_assign(kev, kn); return (kn->kn_fop->f_event(kn, 0)); } int filt_seltrueprocess(struct knote *kn, struct kevent *kev) { int active; active = kn->kn_fop->f_event(kn, 0); if (active) knote_submit(kn, kev); return (active); } /* * This provides full kqfilter entry for device switch tables, which * has same effect as filter using filt_seltrue() as filter method. */ void filt_seltruedetach(struct knote *kn) { /* Nothing to do */ } const struct filterops seltrue_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_seltruedetach, .f_event = filt_seltrue, .f_modify = filt_seltruemodify, .f_process = filt_seltrueprocess, }; int seltrue_kqfilter(dev_t dev, struct knote *kn) { switch (kn->kn_filter) { case EVFILT_READ: case EVFILT_WRITE: kn->kn_fop = &seltrue_filtops; break; default: return (EINVAL); } /* Nothing more to do */ return (0); } static int filt_dead(struct knote *kn, long hint) { if (kn->kn_filter == EVFILT_EXCEPT) { /* * Do not deliver event because there is no out-of-band data. * However, let HUP condition pass for poll(2). */ if ((kn->kn_flags & __EV_POLL) == 0) { kn->kn_flags |= EV_DISABLE; return (0); } } kn->kn_flags |= (EV_EOF | EV_ONESHOT); if (kn->kn_flags & __EV_POLL) kn->kn_flags |= __EV_HUP; kn->kn_data = 0; return (1); } static void filt_deaddetach(struct knote *kn) { /* Nothing to do */ } const struct filterops dead_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_deaddetach, .f_event = filt_dead, .f_modify = filt_seltruemodify, .f_process = filt_seltrueprocess, }; static int filt_badfd(struct knote *kn, long hint) { kn->kn_flags |= (EV_ERROR | EV_ONESHOT); kn->kn_data = EBADF; return (1); } /* For use with kqpoll. */ const struct filterops badfd_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_deaddetach, .f_event = filt_badfd, .f_modify = filt_seltruemodify, .f_process = filt_seltrueprocess, }; static int filter_attach(struct knote *kn) { int error; if (kn->kn_fop->f_flags & FILTEROP_MPSAFE) { error = kn->kn_fop->f_attach(kn); } else { KERNEL_LOCK(); error = kn->kn_fop->f_attach(kn); KERNEL_UNLOCK(); } return (error); } static void filter_detach(struct knote *kn) { if (kn->kn_fop->f_flags & FILTEROP_MPSAFE) { kn->kn_fop->f_detach(kn); } else { KERNEL_LOCK(); kn->kn_fop->f_detach(kn); KERNEL_UNLOCK(); } } static int filter_event(struct knote *kn, long hint) { if ((kn->kn_fop->f_flags & FILTEROP_MPSAFE) == 0) KERNEL_ASSERT_LOCKED(); return (kn->kn_fop->f_event(kn, hint)); } static int filter_modify(struct kevent *kev, struct knote *kn) { int active, s; if (kn->kn_fop->f_flags & FILTEROP_MPSAFE) { active = kn->kn_fop->f_modify(kev, kn); } else { KERNEL_LOCK(); if (kn->kn_fop->f_modify != NULL) { active = kn->kn_fop->f_modify(kev, kn); } else { s = splhigh(); active = knote_modify(kev, kn); splx(s); } KERNEL_UNLOCK(); } return (active); } static int filter_process(struct knote *kn, struct kevent *kev) { int active, s; if (kn->kn_fop->f_flags & FILTEROP_MPSAFE) { active = kn->kn_fop->f_process(kn, kev); } else { KERNEL_LOCK(); if (kn->kn_fop->f_process != NULL) { active = kn->kn_fop->f_process(kn, kev); } else { s = splhigh(); active = knote_process(kn, kev); splx(s); } KERNEL_UNLOCK(); } return (active); } /* * Initialize the current thread for poll/select system call. * num indicates the number of serials that the system call may utilize. * After this function, the valid range of serials is * p_kq_serial <= x < p_kq_serial + num. */ void kqpoll_init(unsigned int num) { struct proc *p = curproc; struct filedesc *fdp; if (p->p_kq == NULL) { p->p_kq = kqueue_alloc(p->p_fd); p->p_kq_serial = arc4random(); fdp = p->p_fd; fdplock(fdp); LIST_INSERT_HEAD(&fdp->fd_kqlist, p->p_kq, kq_next); fdpunlock(fdp); } if (p->p_kq_serial + num < p->p_kq_serial) { /* Serial is about to wrap. Clear all attached knotes. */ kqueue_purge(p, p->p_kq); p->p_kq_serial = 0; } } /* * Finish poll/select system call. * num must have the same value that was used with kqpoll_init(). */ void kqpoll_done(unsigned int num) { struct proc *p = curproc; struct kqueue *kq = p->p_kq; KASSERT(p->p_kq != NULL); KASSERT(p->p_kq_serial + num >= p->p_kq_serial); p->p_kq_serial += num; /* * Because of kn_pollid key, a thread can in principle allocate * up to O(maxfiles^2) knotes by calling poll(2) repeatedly * with suitably varying pollfd arrays. * Prevent such a large allocation by clearing knotes eagerly * if there are too many of them. * * A small multiple of kq_knlistsize should give enough margin * that eager clearing is infrequent, or does not happen at all, * with normal programs. * A single pollfd entry can use up to three knotes. * Typically there is no significant overlap of fd and events * between different entries in the pollfd array. */ if (kq->kq_nknotes > 4 * kq->kq_knlistsize) kqueue_purge(p, kq); } void kqpoll_exit(void) { struct proc *p = curproc; if (p->p_kq == NULL) return; kqueue_purge(p, p->p_kq); kqueue_terminate(p, p->p_kq); KASSERT(p->p_kq->kq_refcnt.r_refs == 1); KQRELE(p->p_kq); p->p_kq = NULL; } struct kqueue * kqueue_alloc(struct filedesc *fdp) { struct kqueue *kq; kq = pool_get(&kqueue_pool, PR_WAITOK | PR_ZERO); refcnt_init(&kq->kq_refcnt); kq->kq_fdp = fdp; TAILQ_INIT(&kq->kq_head); mtx_init(&kq->kq_lock, IPL_HIGH); task_set(&kq->kq_task, kqueue_task, kq); klist_init_mutex(&kq->kq_klist, &kqueue_klist_lock); return (kq); } int dokqueue(struct proc *p, int flags, register_t *retval) { struct filedesc *fdp = p->p_fd; struct kqueue *kq; struct file *fp; int cloexec, error, fd; cloexec = (flags & O_CLOEXEC) ? UF_EXCLOSE : 0; kq = kqueue_alloc(fdp); fdplock(fdp); error = falloc(p, &fp, &fd); if (error) goto out; fp->f_flag = FREAD | FWRITE | (flags & FNONBLOCK); fp->f_type = DTYPE_KQUEUE; fp->f_ops = &kqueueops; fp->f_data = kq; *retval = fd; LIST_INSERT_HEAD(&fdp->fd_kqlist, kq, kq_next); kq = NULL; fdinsert(fdp, fd, cloexec, fp); FRELE(fp, p); out: fdpunlock(fdp); if (kq != NULL) pool_put(&kqueue_pool, kq); return (error); } int sys_kqueue(struct proc *p, void *v, register_t *retval) { return (dokqueue(p, 0, retval)); } int sys_kqueue1(struct proc *p, void *v, register_t *retval) { struct sys_kqueue1_args /* { syscallarg(int) flags; } */ *uap = v; if (SCARG(uap, flags) & ~(O_CLOEXEC | FNONBLOCK)) return (EINVAL); return (dokqueue(p, SCARG(uap, flags), retval)); } int sys_kevent(struct proc *p, void *v, register_t *retval) { struct kqueue_scan_state scan; struct filedesc* fdp = p->p_fd; struct sys_kevent_args /* { syscallarg(int) fd; syscallarg(const struct kevent *) changelist; syscallarg(int) nchanges; syscallarg(struct kevent *) eventlist; syscallarg(int) nevents; syscallarg(const struct timespec *) timeout; } */ *uap = v; struct kevent *kevp; struct kqueue *kq; struct file *fp; struct timespec ts; struct timespec *tsp = NULL; int i, n, nerrors, error; int ready, total; struct kevent kev[KQ_NEVENTS]; if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL) return (EBADF); if (fp->f_type != DTYPE_KQUEUE) { error = EBADF; goto done; } if (SCARG(uap, timeout) != NULL) { error = copyin(SCARG(uap, timeout), &ts, sizeof(ts)); if (error) goto done; #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrreltimespec(p, &ts); #endif if (ts.tv_sec < 0 || !timespecisvalid(&ts)) { error = EINVAL; goto done; } tsp = &ts; } kq = fp->f_data; nerrors = 0; while ((n = SCARG(uap, nchanges)) > 0) { if (n > nitems(kev)) n = nitems(kev); error = copyin(SCARG(uap, changelist), kev, n * sizeof(struct kevent)); if (error) goto done; #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrevent(p, kev, n); #endif for (i = 0; i < n; i++) { kevp = &kev[i]; kevp->flags &= ~EV_SYSFLAGS; error = kqueue_register(kq, kevp, 0, p); if (error || (kevp->flags & EV_RECEIPT)) { if (SCARG(uap, nevents) != 0) { kevp->flags = EV_ERROR; kevp->data = error; copyout(kevp, SCARG(uap, eventlist), sizeof(*kevp)); SCARG(uap, eventlist)++; SCARG(uap, nevents)--; nerrors++; } else { goto done; } } } SCARG(uap, nchanges) -= n; SCARG(uap, changelist) += n; } if (nerrors) { *retval = nerrors; error = 0; goto done; } kqueue_scan_setup(&scan, kq); FRELE(fp, p); /* * Collect as many events as we can. The timeout on successive * loops is disabled (kqueue_scan() becomes non-blocking). */ total = 0; error = 0; while ((n = SCARG(uap, nevents) - total) > 0) { if (n > nitems(kev)) n = nitems(kev); ready = kqueue_scan(&scan, n, kev, tsp, p, &error); if (ready == 0) break; error = copyout(kev, SCARG(uap, eventlist) + total, sizeof(struct kevent) * ready); #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrevent(p, kev, ready); #endif total += ready; if (error || ready < n) break; } kqueue_scan_finish(&scan); *retval = total; return (error); done: FRELE(fp, p); return (error); } #ifdef KQUEUE_DEBUG void kqueue_do_check(struct kqueue *kq, const char *func, int line) { struct knote *kn; int count = 0, nmarker = 0; MUTEX_ASSERT_LOCKED(&kq->kq_lock); TAILQ_FOREACH(kn, &kq->kq_head, kn_tqe) { if (kn->kn_filter == EVFILT_MARKER) { if ((kn->kn_status & KN_QUEUED) != 0) panic("%s:%d: kq=%p kn=%p marker QUEUED", func, line, kq, kn); nmarker++; } else { if ((kn->kn_status & KN_ACTIVE) == 0) panic("%s:%d: kq=%p kn=%p knote !ACTIVE", func, line, kq, kn); if ((kn->kn_status & KN_QUEUED) == 0) panic("%s:%d: kq=%p kn=%p knote !QUEUED", func, line, kq, kn); if (kn->kn_kq != kq) panic("%s:%d: kq=%p kn=%p kn_kq=%p != kq", func, line, kq, kn, kn->kn_kq); count++; if (count > kq->kq_count) goto bad; } } if (count != kq->kq_count) { bad: panic("%s:%d: kq=%p kq_count=%d count=%d nmarker=%d", func, line, kq, kq->kq_count, count, nmarker); } } #endif int kqueue_register(struct kqueue *kq, struct kevent *kev, unsigned int pollid, struct proc *p) { struct filedesc *fdp = kq->kq_fdp; const struct filterops *fops = NULL; struct file *fp = NULL; struct knote *kn = NULL, *newkn = NULL; struct knlist *list = NULL; int active, error = 0; KASSERT(pollid == 0 || (p != NULL && p->p_kq == kq)); if (kev->filter < 0) { if (kev->filter + EVFILT_SYSCOUNT < 0) return (EINVAL); fops = sysfilt_ops[~kev->filter]; /* to 0-base index */ } if (fops == NULL) { /* * XXX * filter attach routine is responsible for ensuring that * the identifier can be attached to it. */ return (EINVAL); } if (fops->f_flags & FILTEROP_ISFD) { /* validate descriptor */ if (kev->ident > INT_MAX) return (EBADF); } if (kev->flags & EV_ADD) newkn = pool_get(&knote_pool, PR_WAITOK | PR_ZERO); again: if (fops->f_flags & FILTEROP_ISFD) { if ((fp = fd_getfile(fdp, kev->ident)) == NULL) { error = EBADF; goto done; } mtx_enter(&kq->kq_lock); if (kev->flags & EV_ADD) kqueue_expand_list(kq, kev->ident); if (kev->ident < kq->kq_knlistsize) list = &kq->kq_knlist[kev->ident]; } else { mtx_enter(&kq->kq_lock); if (kev->flags & EV_ADD) kqueue_expand_hash(kq); if (kq->kq_knhashmask != 0) { list = &kq->kq_knhash[ KN_HASH((u_long)kev->ident, kq->kq_knhashmask)]; } } if (list != NULL) { SLIST_FOREACH(kn, list, kn_link) { if (kev->filter == kn->kn_filter && kev->ident == kn->kn_id && pollid == kn->kn_pollid) { if (!knote_acquire(kn, NULL, 0)) { /* knote_acquire() has released * kq_lock. */ if (fp != NULL) { FRELE(fp, p); fp = NULL; } goto again; } break; } } } KASSERT(kn == NULL || (kn->kn_status & KN_PROCESSING) != 0); if (kn == NULL && ((kev->flags & EV_ADD) == 0)) { mtx_leave(&kq->kq_lock); error = ENOENT; goto done; } /* * kn now contains the matching knote, or NULL if no match. */ if (kev->flags & EV_ADD) { if (kn == NULL) { kn = newkn; newkn = NULL; kn->kn_status = KN_PROCESSING; kn->kn_fp = fp; kn->kn_kq = kq; kn->kn_fop = fops; /* * apply reference count to knote structure, and * do not release it at the end of this routine. */ fp = NULL; kn->kn_sfflags = kev->fflags; kn->kn_sdata = kev->data; kev->fflags = 0; kev->data = 0; kn->kn_kevent = *kev; kn->kn_pollid = pollid; knote_attach(kn); mtx_leave(&kq->kq_lock); error = filter_attach(kn); if (error != 0) { knote_drop(kn, p); goto done; } /* * If this is a file descriptor filter, check if * fd was closed while the knote was being added. * knote_fdclose() has missed kn if the function * ran before kn appeared in kq_knlist. */ if ((fops->f_flags & FILTEROP_ISFD) && fd_checkclosed(fdp, kev->ident, kn->kn_fp)) { /* * Drop the knote silently without error * because another thread might already have * seen it. This corresponds to the insert * happening in full before the close. */ filter_detach(kn); knote_drop(kn, p); goto done; } /* Check if there is a pending event. */ active = filter_process(kn, NULL); mtx_enter(&kq->kq_lock); if (active) knote_activate(kn); } else if (kn->kn_fop == &badfd_filtops) { /* * Nothing expects this badfd knote any longer. * Drop it to make room for the new knote and retry. */ KASSERT(kq == p->p_kq); mtx_leave(&kq->kq_lock); filter_detach(kn); knote_drop(kn, p); KASSERT(fp != NULL); FRELE(fp, p); fp = NULL; goto again; } else { /* * The user may change some filter values after the * initial EV_ADD, but doing so will not reset any * filters which have already been triggered. */ mtx_leave(&kq->kq_lock); active = filter_modify(kev, kn); mtx_enter(&kq->kq_lock); if (active) knote_activate(kn); if (kev->flags & EV_ERROR) { error = kev->data; goto release; } } } else if (kev->flags & EV_DELETE) { mtx_leave(&kq->kq_lock); filter_detach(kn); knote_drop(kn, p); goto done; } if ((kev->flags & EV_DISABLE) && ((kn->kn_status & KN_DISABLED) == 0)) kn->kn_status |= KN_DISABLED; if ((kev->flags & EV_ENABLE) && (kn->kn_status & KN_DISABLED)) { kn->kn_status &= ~KN_DISABLED; mtx_leave(&kq->kq_lock); /* Check if there is a pending event. */ active = filter_process(kn, NULL); mtx_enter(&kq->kq_lock); if (active) knote_activate(kn); } release: knote_release(kn); mtx_leave(&kq->kq_lock); done: if (fp != NULL) FRELE(fp, p); if (newkn != NULL) pool_put(&knote_pool, newkn); return (error); } int kqueue_sleep(struct kqueue *kq, struct timespec *tsp) { struct timespec elapsed, start, stop; uint64_t nsecs; int error; MUTEX_ASSERT_LOCKED(&kq->kq_lock); if (tsp != NULL) { getnanouptime(&start); nsecs = MIN(TIMESPEC_TO_NSEC(tsp), MAXTSLP); } else nsecs = INFSLP; error = msleep_nsec(kq, &kq->kq_lock, PSOCK | PCATCH | PNORELOCK, "kqread", nsecs); if (tsp != NULL) { getnanouptime(&stop); timespecsub(&stop, &start, &elapsed); timespecsub(tsp, &elapsed, tsp); if (tsp->tv_sec < 0) timespecclear(tsp); } return (error); } /* * Scan the kqueue, blocking if necessary until the target time is reached. * If tsp is NULL we block indefinitely. If tsp->ts_secs/nsecs are both * 0 we do not block at all. */ int kqueue_scan(struct kqueue_scan_state *scan, int maxevents, struct kevent *kevp, struct timespec *tsp, struct proc *p, int *errorp) { struct kqueue *kq = scan->kqs_kq; struct knote *kn; int error = 0, nkev = 0; int reinserted; if (maxevents == 0) goto done; retry: KASSERT(nkev == 0); error = 0; reinserted = 0; mtx_enter(&kq->kq_lock); if (kq->kq_state & KQ_DYING) { mtx_leave(&kq->kq_lock); error = EBADF; goto done; } if (kq->kq_count == 0) { /* * Successive loops are only necessary if there are more * ready events to gather, so they don't need to block. */ if ((tsp != NULL && !timespecisset(tsp)) || scan->kqs_nevent != 0) { mtx_leave(&kq->kq_lock); error = 0; goto done; } kq->kq_state |= KQ_SLEEP; error = kqueue_sleep(kq, tsp); /* kqueue_sleep() has released kq_lock. */ if (error == 0 || error == EWOULDBLOCK) goto retry; /* don't restart after signals... */ if (error == ERESTART) error = EINTR; goto done; } /* * Put the end marker in the queue to limit the scan to the events * that are currently active. This prevents events from being * recollected if they reactivate during scan. * * If a partial scan has been performed already but no events have * been collected, reposition the end marker to make any new events * reachable. */ if (!scan->kqs_queued) { TAILQ_INSERT_TAIL(&kq->kq_head, &scan->kqs_end, kn_tqe); scan->kqs_queued = 1; } else if (scan->kqs_nevent == 0) { TAILQ_REMOVE(&kq->kq_head, &scan->kqs_end, kn_tqe); TAILQ_INSERT_TAIL(&kq->kq_head, &scan->kqs_end, kn_tqe); } TAILQ_INSERT_HEAD(&kq->kq_head, &scan->kqs_start, kn_tqe); while (nkev < maxevents) { kn = TAILQ_NEXT(&scan->kqs_start, kn_tqe); if (kn->kn_filter == EVFILT_MARKER) { if (kn == &scan->kqs_end) break; /* Move start marker past another thread's marker. */ TAILQ_REMOVE(&kq->kq_head, &scan->kqs_start, kn_tqe); TAILQ_INSERT_AFTER(&kq->kq_head, kn, &scan->kqs_start, kn_tqe); continue; } if (!knote_acquire(kn, NULL, 0)) { /* knote_acquire() has released kq_lock. */ mtx_enter(&kq->kq_lock); continue; } kqueue_check(kq); TAILQ_REMOVE(&kq->kq_head, kn, kn_tqe); kn->kn_status &= ~KN_QUEUED; kq->kq_count--; kqueue_check(kq); if (kn->kn_status & KN_DISABLED) { knote_release(kn); continue; } mtx_leave(&kq->kq_lock); /* Drop expired kqpoll knotes. */ if (p->p_kq == kq && p->p_kq_serial > (unsigned long)kn->kn_udata) { filter_detach(kn); knote_drop(kn, p); mtx_enter(&kq->kq_lock); continue; } /* * Invalidate knotes whose vnodes have been revoked. * This is a workaround; it is tricky to clear existing * knotes and prevent new ones from being registered * with the current revocation mechanism. */ if ((kn->kn_fop->f_flags & FILTEROP_ISFD) && kn->kn_fp != NULL && kn->kn_fp->f_type == DTYPE_VNODE) { struct vnode *vp = kn->kn_fp->f_data; if (__predict_false(vp->v_op == &dead_vops && kn->kn_fop != &dead_filtops)) { filter_detach(kn); kn->kn_fop = &dead_filtops; /* * Check if the event should be delivered. * Use f_event directly because this is * a special situation. */ if (kn->kn_fop->f_event(kn, 0) == 0) { filter_detach(kn); knote_drop(kn, p); mtx_enter(&kq->kq_lock); continue; } } } memset(kevp, 0, sizeof(*kevp)); if (filter_process(kn, kevp) == 0) { mtx_enter(&kq->kq_lock); if ((kn->kn_status & KN_QUEUED) == 0) kn->kn_status &= ~KN_ACTIVE; knote_release(kn); kqueue_check(kq); continue; } /* * Post-event action on the note */ if (kevp->flags & EV_ONESHOT) { filter_detach(kn); knote_drop(kn, p); mtx_enter(&kq->kq_lock); } else if (kevp->flags & (EV_CLEAR | EV_DISPATCH)) { mtx_enter(&kq->kq_lock); if (kevp->flags & EV_DISPATCH) kn->kn_status |= KN_DISABLED; if ((kn->kn_status & KN_QUEUED) == 0) kn->kn_status &= ~KN_ACTIVE; knote_release(kn); } else { mtx_enter(&kq->kq_lock); if ((kn->kn_status & KN_QUEUED) == 0) { kqueue_check(kq); kq->kq_count++; kn->kn_status |= KN_QUEUED; TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe); /* Wakeup is done after loop. */ reinserted = 1; } knote_release(kn); } kqueue_check(kq); kevp++; nkev++; scan->kqs_nevent++; } TAILQ_REMOVE(&kq->kq_head, &scan->kqs_start, kn_tqe); if (reinserted && kq->kq_count != 0) kqueue_wakeup(kq); mtx_leave(&kq->kq_lock); if (scan->kqs_nevent == 0) goto retry; done: *errorp = error; return (nkev); } void kqueue_scan_setup(struct kqueue_scan_state *scan, struct kqueue *kq) { memset(scan, 0, sizeof(*scan)); KQREF(kq); scan->kqs_kq = kq; scan->kqs_start.kn_filter = EVFILT_MARKER; scan->kqs_start.kn_status = KN_PROCESSING; scan->kqs_end.kn_filter = EVFILT_MARKER; scan->kqs_end.kn_status = KN_PROCESSING; } void kqueue_scan_finish(struct kqueue_scan_state *scan) { struct kqueue *kq = scan->kqs_kq; KASSERT(scan->kqs_start.kn_filter == EVFILT_MARKER); KASSERT(scan->kqs_start.kn_status == KN_PROCESSING); KASSERT(scan->kqs_end.kn_filter == EVFILT_MARKER); KASSERT(scan->kqs_end.kn_status == KN_PROCESSING); if (scan->kqs_queued) { scan->kqs_queued = 0; mtx_enter(&kq->kq_lock); TAILQ_REMOVE(&kq->kq_head, &scan->kqs_end, kn_tqe); mtx_leave(&kq->kq_lock); } KQRELE(kq); } /* * XXX * This could be expanded to call kqueue_scan, if desired. */ int kqueue_read(struct file *fp, struct uio *uio, int fflags) { return (ENXIO); } int kqueue_write(struct file *fp, struct uio *uio, int fflags) { return (ENXIO); } int kqueue_ioctl(struct file *fp, u_long com, caddr_t data, struct proc *p) { return (ENOTTY); } int kqueue_stat(struct file *fp, struct stat *st, struct proc *p) { struct kqueue *kq = fp->f_data; memset(st, 0, sizeof(*st)); st->st_size = kq->kq_count; /* unlocked read */ st->st_blksize = sizeof(struct kevent); st->st_mode = S_IFIFO; return (0); } void kqueue_purge(struct proc *p, struct kqueue *kq) { int i; mtx_enter(&kq->kq_lock); for (i = 0; i < kq->kq_knlistsize; i++) knote_remove(p, kq, &kq->kq_knlist, i, 1); if (kq->kq_knhashmask != 0) { for (i = 0; i < kq->kq_knhashmask + 1; i++) knote_remove(p, kq, &kq->kq_knhash, i, 1); } mtx_leave(&kq->kq_lock); } void kqueue_terminate(struct proc *p, struct kqueue *kq) { struct knote *kn; int state; mtx_enter(&kq->kq_lock); /* * Any remaining entries should be scan markers. * They are removed when the ongoing scans finish. */ KASSERT(kq->kq_count == 0); TAILQ_FOREACH(kn, &kq->kq_head, kn_tqe) KASSERT(kn->kn_filter == EVFILT_MARKER); kq->kq_state |= KQ_DYING; state = kq->kq_state; kqueue_wakeup(kq); mtx_leave(&kq->kq_lock); /* * Any knotes that were attached to this kqueue were deleted * by knote_fdclose() when this kqueue's file descriptor was closed. */ KASSERT(klist_empty(&kq->kq_klist)); if (state & KQ_TASK) taskq_del_barrier(systqmp, &kq->kq_task); } int kqueue_close(struct file *fp, struct proc *p) { struct kqueue *kq = fp->f_data; fp->f_data = NULL; kqueue_purge(p, kq); kqueue_terminate(p, kq); KQRELE(kq); return (0); } static void kqueue_task(void *arg) { struct kqueue *kq = arg; knote(&kq->kq_klist, 0); } void kqueue_wakeup(struct kqueue *kq) { MUTEX_ASSERT_LOCKED(&kq->kq_lock); if (kq->kq_state & KQ_SLEEP) { kq->kq_state &= ~KQ_SLEEP; wakeup(kq); } if (!klist_empty(&kq->kq_klist)) { /* Defer activation to avoid recursion. */ kq->kq_state |= KQ_TASK; task_add(systqmp, &kq->kq_task); } } static void kqueue_expand_hash(struct kqueue *kq) { struct knlist *hash; u_long hashmask; MUTEX_ASSERT_LOCKED(&kq->kq_lock); if (kq->kq_knhashmask == 0) { mtx_leave(&kq->kq_lock); hash = hashinit(KN_HASHSIZE, M_KEVENT, M_WAITOK, &hashmask); mtx_enter(&kq->kq_lock); if (kq->kq_knhashmask == 0) { kq->kq_knhash = hash; kq->kq_knhashmask = hashmask; } else { /* Another thread has allocated the hash. */ mtx_leave(&kq->kq_lock); hashfree(hash, KN_HASHSIZE, M_KEVENT); mtx_enter(&kq->kq_lock); } } } static void kqueue_expand_list(struct kqueue *kq, int fd) { struct knlist *list, *olist; int size, osize; MUTEX_ASSERT_LOCKED(&kq->kq_lock); if (kq->kq_knlistsize <= fd) { size = kq->kq_knlistsize; mtx_leave(&kq->kq_lock); while (size <= fd) size += KQEXTENT; list = mallocarray(size, sizeof(*list), M_KEVENT, M_WAITOK); mtx_enter(&kq->kq_lock); if (kq->kq_knlistsize <= fd) { memcpy(list, kq->kq_knlist, kq->kq_knlistsize * sizeof(*list)); memset(&list[kq->kq_knlistsize], 0, (size - kq->kq_knlistsize) * sizeof(*list)); olist = kq->kq_knlist; osize = kq->kq_knlistsize; kq->kq_knlist = list; kq->kq_knlistsize = size; mtx_leave(&kq->kq_lock); free(olist, M_KEVENT, osize * sizeof(*list)); mtx_enter(&kq->kq_lock); } else { /* Another thread has expanded the list. */ mtx_leave(&kq->kq_lock); free(list, M_KEVENT, size * sizeof(*list)); mtx_enter(&kq->kq_lock); } } } /* * Acquire a knote, return non-zero on success, 0 on failure. * * If we cannot acquire the knote we sleep and return 0. The knote * may be stale on return in this case and the caller must restart * whatever loop they are in. * * If we are about to sleep and klist is non-NULL, the list is unlocked * before sleep and remains unlocked on return. */ int knote_acquire(struct knote *kn, struct klist *klist, int ls) { struct kqueue *kq = kn->kn_kq; MUTEX_ASSERT_LOCKED(&kq->kq_lock); KASSERT(kn->kn_filter != EVFILT_MARKER); if (kn->kn_status & KN_PROCESSING) { kn->kn_status |= KN_WAITING; if (klist != NULL) { mtx_leave(&kq->kq_lock); klist_unlock(klist, ls); /* XXX Timeout resolves potential loss of wakeup. */ tsleep_nsec(kn, 0, "kqepts", SEC_TO_NSEC(1)); } else { msleep_nsec(kn, &kq->kq_lock, PNORELOCK, "kqepts", SEC_TO_NSEC(1)); } /* knote may be stale now */ return (0); } kn->kn_status |= KN_PROCESSING; return (1); } /* * Release an acquired knote, clearing KN_PROCESSING. */ void knote_release(struct knote *kn) { MUTEX_ASSERT_LOCKED(&kn->kn_kq->kq_lock); KASSERT(kn->kn_filter != EVFILT_MARKER); KASSERT(kn->kn_status & KN_PROCESSING); if (kn->kn_status & KN_WAITING) { kn->kn_status &= ~KN_WAITING; wakeup(kn); } kn->kn_status &= ~KN_PROCESSING; /* kn should not be accessed anymore */ } /* * activate one knote. */ void knote_activate(struct knote *kn) { MUTEX_ASSERT_LOCKED(&kn->kn_kq->kq_lock); kn->kn_status |= KN_ACTIVE; if ((kn->kn_status & (KN_QUEUED | KN_DISABLED)) == 0) knote_enqueue(kn); } /* * walk down a list of knotes, activating them if their event has triggered. */ void knote(struct klist *list, long hint) { int ls; ls = klist_lock(list); knote_locked(list, hint); klist_unlock(list, ls); } void knote_locked(struct klist *list, long hint) { struct knote *kn, *kn0; struct kqueue *kq; KLIST_ASSERT_LOCKED(list); SLIST_FOREACH_SAFE(kn, &list->kl_list, kn_selnext, kn0) { if (filter_event(kn, hint)) { kq = kn->kn_kq; mtx_enter(&kq->kq_lock); knote_activate(kn); mtx_leave(&kq->kq_lock); } } } /* * remove all knotes from a specified knlist */ void knote_remove(struct proc *p, struct kqueue *kq, struct knlist **plist, int idx, int purge) { struct knote *kn; MUTEX_ASSERT_LOCKED(&kq->kq_lock); /* Always fetch array pointer as another thread can resize kq_knlist. */ while ((kn = SLIST_FIRST(*plist + idx)) != NULL) { KASSERT(kn->kn_kq == kq); if (!purge) { /* Skip pending badfd knotes. */ while (kn->kn_fop == &badfd_filtops) { kn = SLIST_NEXT(kn, kn_link); if (kn == NULL) return; KASSERT(kn->kn_kq == kq); } } if (!knote_acquire(kn, NULL, 0)) { /* knote_acquire() has released kq_lock. */ mtx_enter(&kq->kq_lock); continue; } mtx_leave(&kq->kq_lock); filter_detach(kn); /* * Notify poll(2) and select(2) when a monitored * file descriptor is closed. * * This reuses the original knote for delivering the * notification so as to avoid allocating memory. */ if (!purge && (kn->kn_flags & (__EV_POLL | __EV_SELECT)) && !(p->p_kq == kq && p->p_kq_serial > (unsigned long)kn->kn_udata) && kn->kn_fop != &badfd_filtops) { KASSERT(kn->kn_fop->f_flags & FILTEROP_ISFD); FRELE(kn->kn_fp, p); kn->kn_fp = NULL; kn->kn_fop = &badfd_filtops; filter_event(kn, 0); mtx_enter(&kq->kq_lock); knote_activate(kn); knote_release(kn); continue; } knote_drop(kn, p); mtx_enter(&kq->kq_lock); } } /* * remove all knotes referencing a specified fd */ void knote_fdclose(struct proc *p, int fd) { struct filedesc *fdp = p->p_p->ps_fd; struct kqueue *kq; /* * fdplock can be ignored if the file descriptor table is being freed * because no other thread can access the fdp. */ if (fdp->fd_refcnt != 0) fdpassertlocked(fdp); LIST_FOREACH(kq, &fdp->fd_kqlist, kq_next) { mtx_enter(&kq->kq_lock); if (fd < kq->kq_knlistsize) knote_remove(p, kq, &kq->kq_knlist, fd, 0); mtx_leave(&kq->kq_lock); } } /* * handle a process exiting, including the triggering of NOTE_EXIT notes * XXX this could be more efficient, doing a single pass down the klist */ void knote_processexit(struct process *pr) { KERNEL_ASSERT_LOCKED(); knote_locked(&pr->ps_klist, NOTE_EXIT); /* remove other knotes hanging off the process */ klist_invalidate(&pr->ps_klist); } void knote_attach(struct knote *kn) { struct kqueue *kq = kn->kn_kq; struct knlist *list; MUTEX_ASSERT_LOCKED(&kq->kq_lock); KASSERT(kn->kn_status & KN_PROCESSING); if (kn->kn_fop->f_flags & FILTEROP_ISFD) { KASSERT(kq->kq_knlistsize > kn->kn_id); list = &kq->kq_knlist[kn->kn_id]; } else { KASSERT(kq->kq_knhashmask != 0); list = &kq->kq_knhash[KN_HASH(kn->kn_id, kq->kq_knhashmask)]; } SLIST_INSERT_HEAD(list, kn, kn_link); kq->kq_nknotes++; } void knote_detach(struct knote *kn) { struct kqueue *kq = kn->kn_kq; struct knlist *list; MUTEX_ASSERT_LOCKED(&kq->kq_lock); KASSERT(kn->kn_status & KN_PROCESSING); kq->kq_nknotes--; if (kn->kn_fop->f_flags & FILTEROP_ISFD) list = &kq->kq_knlist[kn->kn_id]; else list = &kq->kq_knhash[KN_HASH(kn->kn_id, kq->kq_knhashmask)]; SLIST_REMOVE(list, kn, knote, kn_link); } /* * should be called at spl == 0, since we don't want to hold spl * while calling FRELE and pool_put. */ void knote_drop(struct knote *kn, struct proc *p) { struct kqueue *kq = kn->kn_kq; KASSERT(kn->kn_filter != EVFILT_MARKER); mtx_enter(&kq->kq_lock); knote_detach(kn); if (kn->kn_status & KN_QUEUED) knote_dequeue(kn); if (kn->kn_status & KN_WAITING) { kn->kn_status &= ~KN_WAITING; wakeup(kn); } mtx_leave(&kq->kq_lock); if ((kn->kn_fop->f_flags & FILTEROP_ISFD) && kn->kn_fp != NULL) FRELE(kn->kn_fp, p); pool_put(&knote_pool, kn); } void knote_enqueue(struct knote *kn) { struct kqueue *kq = kn->kn_kq; MUTEX_ASSERT_LOCKED(&kq->kq_lock); KASSERT(kn->kn_filter != EVFILT_MARKER); KASSERT((kn->kn_status & KN_QUEUED) == 0); kqueue_check(kq); TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe); kn->kn_status |= KN_QUEUED; kq->kq_count++; kqueue_check(kq); kqueue_wakeup(kq); } void knote_dequeue(struct knote *kn) { struct kqueue *kq = kn->kn_kq; MUTEX_ASSERT_LOCKED(&kq->kq_lock); KASSERT(kn->kn_filter != EVFILT_MARKER); KASSERT(kn->kn_status & KN_QUEUED); kqueue_check(kq); TAILQ_REMOVE(&kq->kq_head, kn, kn_tqe); kn->kn_status &= ~KN_QUEUED; kq->kq_count--; kqueue_check(kq); } /* * Assign parameters to the knote. * * The knote's object lock must be held. */ void knote_assign(const struct kevent *kev, struct knote *kn) { if ((kn->kn_fop->f_flags & FILTEROP_MPSAFE) == 0) KERNEL_ASSERT_LOCKED(); kn->kn_sfflags = kev->fflags; kn->kn_sdata = kev->data; kn->kn_udata = kev->udata; } /* * Submit the knote's event for delivery. * * The knote's object lock must be held. */ void knote_submit(struct knote *kn, struct kevent *kev) { if ((kn->kn_fop->f_flags & FILTEROP_MPSAFE) == 0) KERNEL_ASSERT_LOCKED(); if (kev != NULL) { *kev = kn->kn_kevent; if (kn->kn_flags & EV_CLEAR) { kn->kn_fflags = 0; kn->kn_data = 0; } } } void klist_init(struct klist *klist, const struct klistops *ops, void *arg) { SLIST_INIT(&klist->kl_list); klist->kl_ops = ops; klist->kl_arg = arg; } void klist_free(struct klist *klist) { KASSERT(SLIST_EMPTY(&klist->kl_list)); } void klist_insert(struct klist *klist, struct knote *kn) { int ls; ls = klist_lock(klist); SLIST_INSERT_HEAD(&klist->kl_list, kn, kn_selnext); klist_unlock(klist, ls); } void klist_insert_locked(struct klist *klist, struct knote *kn) { KLIST_ASSERT_LOCKED(klist); SLIST_INSERT_HEAD(&klist->kl_list, kn, kn_selnext); } void klist_remove(struct klist *klist, struct knote *kn) { int ls; ls = klist_lock(klist); SLIST_REMOVE(&klist->kl_list, kn, knote, kn_selnext); klist_unlock(klist, ls); } void klist_remove_locked(struct klist *klist, struct knote *kn) { KLIST_ASSERT_LOCKED(klist); SLIST_REMOVE(&klist->kl_list, kn, knote, kn_selnext); } /* * Detach all knotes from klist. The knotes are rewired to indicate EOF. * * The caller of this function must not hold any locks that can block * filterops callbacks that run with KN_PROCESSING. * Otherwise this function might deadlock. */ void klist_invalidate(struct klist *list) { struct knote *kn; struct kqueue *kq; struct proc *p = curproc; int ls; NET_ASSERT_UNLOCKED(); ls = klist_lock(list); while ((kn = SLIST_FIRST(&list->kl_list)) != NULL) { kq = kn->kn_kq; mtx_enter(&kq->kq_lock); if (!knote_acquire(kn, list, ls)) { /* knote_acquire() has released kq_lock * and klist lock. */ ls = klist_lock(list); continue; } mtx_leave(&kq->kq_lock); klist_unlock(list, ls); filter_detach(kn); if (kn->kn_fop->f_flags & FILTEROP_ISFD) { kn->kn_fop = &dead_filtops; filter_event(kn, 0); mtx_enter(&kq->kq_lock); knote_activate(kn); knote_release(kn); mtx_leave(&kq->kq_lock); } else { knote_drop(kn, p); } ls = klist_lock(list); } klist_unlock(list, ls); } static int klist_lock(struct klist *list) { int ls = 0; if (list->kl_ops != NULL) { ls = list->kl_ops->klo_lock(list->kl_arg); } else { KERNEL_LOCK(); ls = splhigh(); } return ls; } static void klist_unlock(struct klist *list, int ls) { if (list->kl_ops != NULL) { list->kl_ops->klo_unlock(list->kl_arg, ls); } else { splx(ls); KERNEL_UNLOCK(); } } static void klist_mutex_assertlk(void *arg) { struct mutex *mtx = arg; (void)mtx; MUTEX_ASSERT_LOCKED(mtx); } static int klist_mutex_lock(void *arg) { struct mutex *mtx = arg; mtx_enter(mtx); return 0; } static void klist_mutex_unlock(void *arg, int s) { struct mutex *mtx = arg; mtx_leave(mtx); } static const struct klistops mutex_klistops = { .klo_assertlk = klist_mutex_assertlk, .klo_lock = klist_mutex_lock, .klo_unlock = klist_mutex_unlock, }; void klist_init_mutex(struct klist *klist, struct mutex *mtx) { klist_init(klist, &mutex_klistops, mtx); } static void klist_rwlock_assertlk(void *arg) { struct rwlock *rwl = arg; (void)rwl; rw_assert_wrlock(rwl); } static int klist_rwlock_lock(void *arg) { struct rwlock *rwl = arg; rw_enter_write(rwl); return 0; } static void klist_rwlock_unlock(void *arg, int s) { struct rwlock *rwl = arg; rw_exit_write(rwl); } static const struct klistops rwlock_klistops = { .klo_assertlk = klist_rwlock_assertlk, .klo_lock = klist_rwlock_lock, .klo_unlock = klist_rwlock_unlock, }; void klist_init_rwlock(struct klist *klist, struct rwlock *rwl) { klist_init(klist, &rwlock_klistops, rwl); }
14 2 2 1 1 1 2 6 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 /* $OpenBSD: nfs_vfsops.c,v 1.131 2024/05/12 09:09:39 jsg Exp $ */ /* $NetBSD: nfs_vfsops.c,v 1.46.4.1 1996/05/25 22:40:35 fvdl Exp $ */ /* * Copyright (c) 1989, 1993, 1995 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Rick Macklem at The University of Guelph. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95 */ #include <sys/param.h> #include <sys/conf.h> #include <sys/proc.h> #include <sys/vnode.h> #include <sys/lock.h> #include <sys/kernel.h> #include <sys/mount.h> #include <sys/swap.h> #include <sys/mbuf.h> #include <sys/dirent.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/systm.h> #include <sys/sysctl.h> #include <sys/queue.h> #include <netinet/in.h> #include <nfs/nfsproto.h> #include <nfs/nfsnode.h> #include <nfs/nfs.h> #include <nfs/nfsmount.h> #include <nfs/xdr_subs.h> #include <nfs/nfsdiskless.h> #include <nfs/nfs_var.h> #include <nfs/nfsm_subs.h> extern struct nfsstats nfsstats; extern int nfs_ticks; int nfs_sysctl(int *, u_int, void *, size_t *, void *, size_t, struct proc *); int nfs_checkexp(struct mount *, struct mbuf *, int *, struct ucred **); struct mount *nfs_mount_diskless(struct nfs_dlmount *, char *, int, struct vnode **, struct proc *p); int mountnfs(struct nfs_args *, struct mount *, struct mbuf *, const char *, char *, struct vnode **, struct proc *p); int nfs_quotactl(struct mount *, int, uid_t, caddr_t, struct proc *); int nfs_root(struct mount *, struct vnode **); int nfs_start(struct mount *, int, struct proc *); int nfs_statfs(struct mount *, struct statfs *, struct proc *); int nfs_sync(struct mount *, int, int, struct ucred *, struct proc *); int nfs_unmount(struct mount *, int, struct proc *); void nfs_reaper(void *); int nfs_vget(struct mount *, ino_t, struct vnode **); int nfs_vptofh(struct vnode *, struct fid *); int nfs_mountroot(void); void nfs_decode_args(struct nfsmount *, struct nfs_args *, struct nfs_args *); int nfs_fhtovp(struct mount *, struct fid *, struct vnode **); /* * nfs vfs operations. */ const struct vfsops nfs_vfsops = { .vfs_mount = nfs_mount, .vfs_start = nfs_start, .vfs_unmount = nfs_unmount, .vfs_root = nfs_root, .vfs_quotactl = nfs_quotactl, .vfs_statfs = nfs_statfs, .vfs_sync = nfs_sync, .vfs_vget = nfs_vget, .vfs_fhtovp = nfs_fhtovp, .vfs_vptofh = nfs_vptofh, .vfs_init = nfs_vfs_init, .vfs_sysctl = nfs_sysctl, .vfs_checkexp = nfs_checkexp, }; /* * nfs statfs call */ int nfs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p) { struct vnode *vp; struct nfs_statfs *sfp = NULL; struct nfsm_info info; struct nfsmount *nmp = VFSTONFS(mp); int error = 0, retattr; struct ucred *cred; u_quad_t tquad; info.nmi_v3 = (nmp->nm_flag & NFSMNT_NFSV3); info.nmi_errorp = &error; error = nfs_root(mp, &vp); if (error) return (error); cred = crget(); cred->cr_ngroups = 0; if (info.nmi_v3 && (nmp->nm_flag & NFSMNT_GOTFSINFO) == 0) (void)nfs_fsinfo(nmp, vp, cred, p); nfsstats.rpccnt[NFSPROC_FSSTAT]++; info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(info.nmi_v3)); nfsm_fhtom(&info, vp, info.nmi_v3); info.nmi_procp = p; info.nmi_cred = cred; error = nfs_request(vp, NFSPROC_FSSTAT, &info); if (info.nmi_v3) { if (nfsm_postop_attr(&info, &vp, &retattr) != 0) goto nfsmout; } if (error) { m_freem(info.nmi_mrep); goto nfsmout; } sfp = (struct nfs_statfs *) nfsm_dissect(&info, NFSX_STATFS(info.nmi_v3)); if (sfp == NULL) goto nfsmout; sbp->f_iosize = min(nmp->nm_rsize, nmp->nm_wsize); if (info.nmi_v3) { sbp->f_bsize = NFS_FABLKSIZE; tquad = fxdr_hyper(&sfp->sf_tbytes); sbp->f_blocks = tquad / (u_quad_t)NFS_FABLKSIZE; tquad = fxdr_hyper(&sfp->sf_fbytes); sbp->f_bfree = tquad / (u_quad_t)NFS_FABLKSIZE; tquad = fxdr_hyper(&sfp->sf_abytes); sbp->f_bavail = (quad_t)tquad / (quad_t)NFS_FABLKSIZE; tquad = fxdr_hyper(&sfp->sf_tfiles); sbp->f_files = tquad; tquad = fxdr_hyper(&sfp->sf_ffiles); sbp->f_ffree = tquad; sbp->f_favail = tquad; } else { sbp->f_bsize = fxdr_unsigned(int32_t, sfp->sf_bsize); sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks); sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree); sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail); sbp->f_files = 0; sbp->f_ffree = 0; sbp->f_favail = 0; } copy_statfs_info(sbp, mp); m_freem(info.nmi_mrep); nfsmout: vput(vp); crfree(cred); return (error); } /* * nfs version 3 fsinfo rpc call */ int nfs_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred, struct proc *p) { struct nfsv3_fsinfo *fsp; struct nfsm_info info; u_int32_t pref, max; int error = 0, retattr; nfsstats.rpccnt[NFSPROC_FSINFO]++; info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(1)); nfsm_fhtom(&info, vp, 1); info.nmi_procp = p; info.nmi_cred = cred; info.nmi_errorp = &error; error = nfs_request(vp, NFSPROC_FSINFO, &info); if (nfsm_postop_attr(&info, &vp, &retattr) != 0) goto nfsmout; if (error) { m_freem(info.nmi_mrep); goto nfsmout; } fsp = (struct nfsv3_fsinfo *)nfsm_dissect(&info, NFSX_V3FSINFO); if (fsp == NULL) goto nfsmout; pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref); if (pref < nmp->nm_wsize) nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1); max = fxdr_unsigned(u_int32_t, fsp->fs_wtmax); if (max < nmp->nm_wsize) { nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1); if (nmp->nm_wsize == 0) nmp->nm_wsize = max; } pref = fxdr_unsigned(u_int32_t, fsp->fs_rtpref); if (pref < nmp->nm_rsize) nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1); max = fxdr_unsigned(u_int32_t, fsp->fs_rtmax); if (max < nmp->nm_rsize) { nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1); if (nmp->nm_rsize == 0) nmp->nm_rsize = max; } pref = fxdr_unsigned(u_int32_t, fsp->fs_dtpref); if (pref < nmp->nm_readdirsize) nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) & ~(NFS_DIRBLKSIZ - 1); if (max < nmp->nm_readdirsize) { nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1); if (nmp->nm_readdirsize == 0) nmp->nm_readdirsize = max; } nmp->nm_flag |= NFSMNT_GOTFSINFO; m_freem(info.nmi_mrep); nfsmout: return (error); } struct nfs_diskless nfs_diskless; /* * Mount a remote root fs via. NFS. It goes like this: * - Call nfs_boot_init() to fill in the nfs_diskless struct * (using RARP, bootparam RPC, mountd RPC) * - hand craft the swap nfs vnode hanging off a fake mount point * if swdevt[0].sw_dev == NODEV * - build the rootfs mount point and call mountnfs() to do the rest. */ int nfs_mountroot(void) { struct vattr attr; struct mount *mp; struct vnode *vp; struct proc *procp; long n; int error; procp = curproc; /* XXX */ /* * Call nfs_boot_init() to fill in the nfs_diskless struct. * Side effect: Finds and configures a network interface. */ nfs_boot_init(&nfs_diskless, procp); /* * Create the root mount point. */ if (nfs_boot_getfh(&nfs_diskless.nd_boot, "root", &nfs_diskless.nd_root, -1)) panic("nfs_mountroot: root"); mp = nfs_mount_diskless(&nfs_diskless.nd_root, "/", 0, &vp, procp); printf("root on %s\n", nfs_diskless.nd_root.ndm_host); /* * Link it into the mount list. */ TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list); rootvp = vp; vfs_unbusy(mp); /* Get root attributes (for the time). */ error = VOP_GETATTR(rootvp, &attr, procp->p_ucred, procp); if (error) panic("nfs_mountroot: getattr for root"); n = attr.va_atime.tv_sec; #ifdef DEBUG printf("root time: 0x%lx\n", n); #endif inittodr(n); #ifdef notyet /* Set up swap credentials. */ proc0.p_ucred->cr_uid = ntohl(nfs_diskless.swap_ucred.cr_uid); proc0.p_ucred->cr_gid = ntohl(nfs_diskless.swap_ucred.cr_gid); if ((proc0.p_ucred->cr_ngroups = ntohs(nfs_diskless.swap_ucred.cr_ngroups)) > NGROUPS_MAX) proc0.p_ucred->cr_ngroups = NGROUPS_MAX; for (i = 0; i < proc0.p_ucred->cr_ngroups; i++) proc0.p_ucred->cr_groups[i] = ntohl(nfs_diskless.swap_ucred.cr_groups[i]); #endif /* * "Mount" the swap device. * * On a "dataless" configuration (swap on disk) we will have: * (swdevt[0].sw_dev != NODEV) identifying the swap device. */ if (swdevt[0].sw_dev != NODEV) { if (bdevvp(swapdev, &swapdev_vp)) panic("nfs_mountroot: can't setup swap vp"); printf("swap on device 0x%x\n", swdevt[0].sw_dev); return (0); } /* * If swapping to an nfs node: (swdevt[0].sw_dev == NODEV) * Create a fake mount point just for the swap vnode so that the * swap file can be on a different server from the rootfs. * * Wait 5 retries, finally no swap is cool. -mickey */ error = nfs_boot_getfh(&nfs_diskless.nd_boot, "swap", &nfs_diskless.nd_swap, 5); if (!error) { mp = nfs_mount_diskless(&nfs_diskless.nd_swap, "/swap", 0, &vp, procp); vfs_unbusy(mp); /* * Since the swap file is not the root dir of a file system, * hack it to a regular file. */ vp->v_type = VREG; vp->v_flag = 0; /* * Next line is a hack to make swapmount() work on NFS * swap files. */ swdevt[0].sw_dev = NETDEV; /* end hack */ nfs_diskless.sw_vp = vp; /* * Find out how large the swap file is. */ error = VOP_GETATTR(vp, &attr, procp->p_ucred, procp); if (error) printf("nfs_mountroot: getattr for swap\n"); n = (long) (attr.va_size >> DEV_BSHIFT); printf("swap on %s\n", nfs_diskless.nd_swap.ndm_host); #ifdef DEBUG printf("swap size: 0x%lx (blocks)\n", n); #endif return (0); } printf("WARNING: no swap\n"); swdevt[0].sw_dev = NODEV; return (0); } /* * Internal version of mount system call for diskless setup. */ struct mount * nfs_mount_diskless(struct nfs_dlmount *ndmntp, char *mntname, int mntflag, struct vnode **vpp, struct proc *p) { struct mount *mp; struct mbuf *m; int error; if (vfs_rootmountalloc("nfs", mntname, &mp)) panic("nfs_mount_diskless: vfs_rootmountalloc failed"); mp->mnt_flag |= mntflag; /* Get mbuf for server sockaddr. */ m = m_get(M_WAIT, MT_SONAME); bcopy(ndmntp->ndm_args.addr, mtod(m, caddr_t), (m->m_len = ndmntp->ndm_args.addr->sa_len)); error = mountnfs(&ndmntp->ndm_args, mp, m, mntname, ndmntp->ndm_args.hostname, vpp, p); if (error) panic("nfs_mountroot: mount %s failed: %d", mntname, error); return (mp); } void nfs_decode_args(struct nfsmount *nmp, struct nfs_args *argp, struct nfs_args *nargp) { int adjsock = 0; int maxio; #if 0 /* Re-bind if rsrvd port requested and wasn't on one */ adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT) && (argp->flags & NFSMNT_RESVPORT); #endif /* Also re-bind if we're switching to/from a connected UDP socket */ adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) != (argp->flags & NFSMNT_NOCONN)); nmp->nm_flag = (argp->flags & ~NFSMNT_INTERNAL) | (nmp->nm_flag & NFSMNT_INTERNAL); if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) { nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10; if (nmp->nm_timeo < NFS_MINTIMEO) nmp->nm_timeo = NFS_MINTIMEO; else if (nmp->nm_timeo > NFS_MAXTIMEO) nmp->nm_timeo = NFS_MAXTIMEO; } if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) nmp->nm_retry = MIN(argp->retrans, NFS_MAXREXMIT); if (!(nmp->nm_flag & NFSMNT_SOFT)) nmp->nm_retry = NFS_MAXREXMIT + 1; /* past clip limit */ if (argp->flags & NFSMNT_NFSV3) { if (argp->sotype == SOCK_DGRAM) maxio = NFS_MAXDGRAMDATA; else maxio = NFS_MAXDATA; } else maxio = NFS_V2MAXDATA; if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) { int osize = nmp->nm_wsize; nmp->nm_wsize = argp->wsize; /* Round down to multiple of blocksize */ nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1); if (nmp->nm_wsize <= 0) nmp->nm_wsize = NFS_FABLKSIZE; adjsock |= (nmp->nm_wsize != osize); } if (nmp->nm_wsize > maxio) nmp->nm_wsize = maxio; if (nmp->nm_wsize > MAXBSIZE) nmp->nm_wsize = MAXBSIZE; if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) { int osize = nmp->nm_rsize; nmp->nm_rsize = argp->rsize; /* Round down to multiple of blocksize */ nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1); if (nmp->nm_rsize <= 0) nmp->nm_rsize = NFS_FABLKSIZE; adjsock |= (nmp->nm_rsize != osize); } if (nmp->nm_rsize > maxio) nmp->nm_rsize = maxio; if (nmp->nm_rsize > MAXBSIZE) nmp->nm_rsize = MAXBSIZE; if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) { nmp->nm_readdirsize = argp->readdirsize; /* Round down to multiple of blocksize */ nmp->nm_readdirsize &= ~(NFS_DIRBLKSIZ - 1); if (nmp->nm_readdirsize < NFS_DIRBLKSIZ) nmp->nm_readdirsize = NFS_DIRBLKSIZ; } else if (argp->flags & NFSMNT_RSIZE) nmp->nm_readdirsize = nmp->nm_rsize; if (nmp->nm_readdirsize > maxio) nmp->nm_readdirsize = maxio; if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0 && argp->maxgrouplist <= NFS_MAXGRPS) nmp->nm_numgrps = argp->maxgrouplist; if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0 && argp->readahead <= NFS_MAXRAHEAD) nmp->nm_readahead = argp->readahead; if (argp->flags & NFSMNT_ACREGMIN && argp->acregmin >= 0) { if (argp->acregmin > 0xffff) nmp->nm_acregmin = 0xffff; else nmp->nm_acregmin = argp->acregmin; } if (argp->flags & NFSMNT_ACREGMAX && argp->acregmax >= 0) { if (argp->acregmax > 0xffff) nmp->nm_acregmax = 0xffff; else nmp->nm_acregmax = argp->acregmax; } if (nmp->nm_acregmin > nmp->nm_acregmax) nmp->nm_acregmin = nmp->nm_acregmax; if (argp->flags & NFSMNT_ACDIRMIN && argp->acdirmin >= 0) { if (argp->acdirmin > 0xffff) nmp->nm_acdirmin = 0xffff; else nmp->nm_acdirmin = argp->acdirmin; } if (argp->flags & NFSMNT_ACDIRMAX && argp->acdirmax >= 0) { if (argp->acdirmax > 0xffff) nmp->nm_acdirmax = 0xffff; else nmp->nm_acdirmax = argp->acdirmax; } if (nmp->nm_acdirmin > nmp->nm_acdirmax) nmp->nm_acdirmin = nmp->nm_acdirmax; if (nmp->nm_so && adjsock) { nfs_disconnect(nmp); if (nmp->nm_sotype == SOCK_DGRAM) while (nfs_connect(nmp, NULL)) { printf("nfs_args: retrying connect\n"); tsleep_nsec(&nowake, PSOCK, "nfscon", SEC_TO_NSEC(1)); } } /* Update nargp based on nmp */ nargp->wsize = nmp->nm_wsize; nargp->rsize = nmp->nm_rsize; nargp->readdirsize = nmp->nm_readdirsize; nargp->timeo = nmp->nm_timeo; nargp->retrans = nmp->nm_retry; nargp->maxgrouplist = nmp->nm_numgrps; nargp->readahead = nmp->nm_readahead; nargp->acregmin = nmp->nm_acregmin; nargp->acregmax = nmp->nm_acregmax; nargp->acdirmin = nmp->nm_acdirmin; nargp->acdirmax = nmp->nm_acdirmax; } /* * VFS Operations. * * mount system call * It seems a bit dumb to copyinstr() the host here and then * bcopy() it in mountnfs(), but I wanted to detect errors before * doing the sockargs() call because sockargs() allocates an mbuf and * an error after that means that I have to release the mbuf. */ int nfs_mount(struct mount *mp, const char *path, void *data, struct nameidata *ndp, struct proc *p) { int error; struct nfs_args *args = data; struct mbuf *nam; struct vnode *vp; char hst[MNAMELEN]; size_t len; u_char nfh[NFSX_V3FHMAX]; if (args && (args->flags & (NFSMNT_NFSV3|NFSMNT_RDIRPLUS)) == NFSMNT_RDIRPLUS) return (EINVAL); if (nfs_niothreads < 0) { nfs_niothreads = 4; nfs_getset_niothreads(1); } if (mp->mnt_flag & MNT_UPDATE) { struct nfsmount *nmp = VFSTONFS(mp); if (nmp == NULL) return (EIO); /* * When doing an update, we can't change from or to * v3. */ if (args) { args->flags = (args->flags & ~(NFSMNT_NFSV3)) | (nmp->nm_flag & (NFSMNT_NFSV3)); nfs_decode_args(nmp, args, &mp->mnt_stat.mount_info.nfs_args); } return (0); } if (args->fhsize < 0 || args->fhsize > NFSX_V3FHMAX) return (EINVAL); error = copyin(args->fh, nfh, args->fhsize); if (error) return (error); error = copyinstr(args->hostname, hst, MNAMELEN-1, &len); if (error) return (error); memset(&hst[len], 0, MNAMELEN - len); /* sockargs() call must be after above copyin() calls */ error = sockargs(&nam, args->addr, args->addrlen, MT_SONAME); if (error) return (error); args->fh = nfh; error = mountnfs(args, mp, nam, path, hst, &vp, p); return (error); } /* * Common code for mount and mountroot */ int mountnfs(struct nfs_args *argp, struct mount *mp, struct mbuf *nam, const char *pth, char *hst, struct vnode **vpp, struct proc *p) { struct nfsmount *nmp; struct nfsnode *np; struct vnode *vp; struct vattr attr; int error; if (mp->mnt_flag & MNT_UPDATE) { nmp = VFSTONFS(mp); /* update paths, file handles, etc, here XXX */ m_freem(nam); return (0); } else { nmp = malloc(sizeof(*nmp), M_NFSMNT, M_WAITOK|M_ZERO); mp->mnt_data = nmp; } vfs_getnewfsid(mp); nmp->nm_mountp = mp; nmp->nm_timeo = NFS_TIMEO; nmp->nm_retry = NFS_RETRANS; nmp->nm_wsize = NFS_WSIZE; nmp->nm_rsize = NFS_RSIZE; nmp->nm_readdirsize = NFS_READDIRSIZE; nmp->nm_numgrps = NFS_MAXGRPS; nmp->nm_readahead = NFS_DEFRAHEAD; nmp->nm_acregmin = NFS_MINATTRTIMO; nmp->nm_acregmax = NFS_MAXATTRTIMO; nmp->nm_acdirmin = NFS_MINATTRTIMO; nmp->nm_acdirmax = NFS_MAXATTRTIMO; mp->mnt_stat.f_namemax = MAXNAMLEN; memset(mp->mnt_stat.f_mntonname, 0, MNAMELEN); strlcpy(mp->mnt_stat.f_mntonname, pth, MNAMELEN); memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN); strlcpy(mp->mnt_stat.f_mntfromname, hst, MNAMELEN); memset(mp->mnt_stat.f_mntfromspec, 0, MNAMELEN); strlcpy(mp->mnt_stat.f_mntfromspec, hst, MNAMELEN); bcopy(argp, &mp->mnt_stat.mount_info.nfs_args, sizeof(*argp)); nmp->nm_nam = nam; nfs_decode_args(nmp, argp, &mp->mnt_stat.mount_info.nfs_args); nfs_ninit(nmp); TAILQ_INIT(&nmp->nm_reqsq); timeout_set_proc(&nmp->nm_rtimeout, nfs_timer, nmp); /* Set up the sockets and per-host congestion */ nmp->nm_sotype = argp->sotype; nmp->nm_soproto = argp->proto; /* * For Connection based sockets (TCP,...) defer the connect until * the first request, in case the server is not responding. */ if (nmp->nm_sotype == SOCK_DGRAM && (error = nfs_connect(nmp, NULL))) goto bad; /* * This is silly, but it has to be set so that vinifod() works. * We do not want to do an nfs_statfs() here since we can get * stuck on a dead server and we are holding a lock on the mount * point. */ mp->mnt_stat.f_iosize = NFS_MAXDGRAMDATA; error = nfs_nget(mp, (nfsfh_t *)argp->fh, argp->fhsize, &np); if (error) goto bad; vp = NFSTOV(np); error = VOP_GETATTR(vp, &attr, p->p_ucred, p); if (error) { vput(vp); goto bad; } /* * A reference count is needed on the nfsnode representing the * remote root. If this object is not persistent, then backward * traversals of the mount point (i.e. "..") will not work if * the nfsnode gets flushed out of the cache. Ufs does not have * this problem, because one can identify root inodes by their * number == ROOTINO (2). So, just unlock, but no rele. */ nmp->nm_vnode = vp; if (vp->v_type == VNON) vp->v_type = VDIR; vp->v_flag = VROOT; VOP_UNLOCK(vp); *vpp = vp; return (0); bad: nfs_disconnect(nmp); free(nmp, M_NFSMNT, sizeof(*nmp)); m_freem(nam); return (error); } /* unmount system call */ int nfs_unmount(struct mount *mp, int mntflags, struct proc *p) { struct nfsmount *nmp; struct vnode *vp; int error, flags = 0; nmp = VFSTONFS(mp); error = nfs_root(mp, &vp); if (error) return (error); if ((mntflags & MNT_FORCE) == 0 && vp->v_usecount > 2) { vput(vp); return (EBUSY); } if (mntflags & MNT_FORCE) flags |= FORCECLOSE; error = vflush(mp, vp, flags); if (error) { vput(vp); return (error); } /* * There are two references count to get rid of here: one * from mountnfs() and one from nfs_root() above. */ vrele(vp); vput(vp); vgone(vp); nfs_disconnect(nmp); m_freem(nmp->nm_nam); timeout_del(&nmp->nm_rtimeout); timeout_set_proc(&nmp->nm_rtimeout, nfs_reaper, nmp); timeout_add(&nmp->nm_rtimeout, 0); mp->mnt_data = NULL; return (0); } /* * Delay nfs mount point free until pending or sleeping timeouts have finished. */ void nfs_reaper(void *arg) { struct nfsmount *nmp = arg; free(nmp, M_NFSMNT, sizeof(*nmp)); } /* * Return root of a filesystem */ int nfs_root(struct mount *mp, struct vnode **vpp) { struct vnode *vp; struct nfsmount *nmp; int error; nmp = VFSTONFS(mp); vp = nmp->nm_vnode; vref(vp); error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if (error) { vrele(vp); return (error); } *vpp = vp; return (0); } /* * Flush out the buffer cache */ int nfs_sync(struct mount *mp, int waitfor, int stall, struct ucred *cred, struct proc *p) { struct vnode *vp; int allerror = 0; int empty, error, s; /* * Don't traverse the vnode list if we want to skip all of them. */ if (waitfor == MNT_LAZY) return (allerror); /* * Force stale buffer cache information to be flushed. */ loop: TAILQ_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) { /* * If the vnode that we are about to sync is no longer * associated with this mount point, start over. */ if (vp->v_mount != mp) goto loop; if (VOP_ISLOCKED(vp)) continue; s = splbio(); empty = LIST_EMPTY(&vp->v_dirtyblkhd); splx(s); if (empty) continue; if (vget(vp, LK_EXCLUSIVE)) goto loop; error = VOP_FSYNC(vp, cred, waitfor, p); if (error) allerror = error; vput(vp); } return (allerror); } /* * NFS flat namespace lookup. * Currently unsupported. */ int nfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) { return (EOPNOTSUPP); } /* * Do that sysctl thang... */ int nfs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { int rv; /* * All names at this level are terminal. */ if(namelen > 1) return ENOTDIR; /* overloaded */ switch(name[0]) { case NFS_NFSSTATS: if(!oldp) { *oldlenp = sizeof nfsstats; return 0; } if(*oldlenp < sizeof nfsstats) { *oldlenp = sizeof nfsstats; return ENOMEM; } rv = copyout(&nfsstats, oldp, sizeof nfsstats); if(rv) return rv; if(newp && newlen != sizeof nfsstats) return EINVAL; if(newp) { return copyin(newp, &nfsstats, sizeof nfsstats); } return 0; case NFS_NIOTHREADS: nfs_getset_niothreads(0); rv = sysctl_int(oldp, oldlenp, newp, newlen, &nfs_niothreads); if (newp) nfs_getset_niothreads(1); return rv; default: return EOPNOTSUPP; } } /* * At this point, this should never happen */ int nfs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) { return (EINVAL); } /* * Vnode pointer to File handle, should never happen either */ int nfs_vptofh(struct vnode *vp, struct fid *fhp) { return (EINVAL); } /* * Vfs start routine, a no-op. */ int nfs_start(struct mount *mp, int flags, struct proc *p) { return (0); } /* * Do operations associated with quotas, not supported */ int nfs_quotactl(struct mount *mp, int cmd, uid_t uid, caddr_t arg, struct proc *p) { return (EOPNOTSUPP); } /* * check export permission, not supported */ /* ARGUSED */ int nfs_checkexp(struct mount *mp, struct mbuf *nam, int *exflagsp, struct ucred **credanonp) { return (EOPNOTSUPP); }
1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 /* $OpenBSD: scsi_ioctl.c,v 1.67 2020/09/22 19:32:53 krw Exp $ */ /* $NetBSD: scsi_ioctl.c,v 1.23 1996/10/12 23:23:17 christos Exp $ */ /* * Copyright (c) 1994 Charles Hannum. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Charles Hannum. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Contributed by HD Associates (hd@world.std.com). * Copyright (c) 1992, 1993 HD Associates * * Berkeley style copyright. */ #include <sys/param.h> #include <sys/errno.h> #include <sys/systm.h> #include <sys/pool.h> #include <sys/device.h> #include <sys/fcntl.h> #include <scsi/scsi_all.h> #include <scsi/scsi_debug.h> #include <scsi/scsiconf.h> #include <sys/scsiio.h> #include <sys/ataio.h> int scsi_ioc_cmd(struct scsi_link *, scsireq_t *); int scsi_ioc_ata_cmd(struct scsi_link *, atareq_t *); const unsigned char scsi_readsafe_cmd[256] = { [0x00] = 1, /* TEST UNIT READY */ [0x03] = 1, /* REQUEST SENSE */ [0x08] = 1, /* READ(6) */ [0x12] = 1, /* INQUIRY */ [0x1a] = 1, /* MODE SENSE */ [0x1b] = 1, /* START STOP */ [0x23] = 1, /* READ FORMAT CAPACITIES */ [0x25] = 1, /* READ CDVD CAPACITY */ [0x28] = 1, /* READ(10) */ [0x2b] = 1, /* SEEK */ [0x2f] = 1, /* VERIFY(10) */ [0x3c] = 1, /* READ BUFFER */ [0x3e] = 1, /* READ LONG */ [0x42] = 1, /* READ SUBCHANNEL */ [0x43] = 1, /* READ TOC PMA ATIP */ [0x44] = 1, /* READ HEADER */ [0x45] = 1, /* PLAY AUDIO(10) */ [0x46] = 1, /* GET CONFIGURATION */ [0x47] = 1, /* PLAY AUDIO MSF */ [0x48] = 1, /* PLAY AUDIO TI */ [0x4a] = 1, /* GET EVENT STATUS NOTIFICATION */ [0x4b] = 1, /* PAUSE RESUME */ [0x4e] = 1, /* STOP PLAY SCAN */ [0x51] = 1, /* READ DISC INFO */ [0x52] = 1, /* READ TRACK RZONE INFO */ [0x5a] = 1, /* MODE SENSE(10) */ [0x88] = 1, /* READ(16) */ [0x8f] = 1, /* VERIFY(16) */ [0xa4] = 1, /* REPORT KEY */ [0xa5] = 1, /* PLAY AUDIO(12) */ [0xa8] = 1, /* READ(12) */ [0xac] = 1, /* GET PERFORMANCE */ [0xad] = 1, /* READ DVD STRUCTURE */ [0xb9] = 1, /* READ CD MSF */ [0xba] = 1, /* SCAN */ [0xbc] = 1, /* PLAY CD */ [0xbd] = 1, /* MECHANISM STATUS */ [0xbe] = 1 /* READ CD */ }; int scsi_ioc_cmd(struct scsi_link *link, scsireq_t *screq) { struct scsi_xfer *xs; int err = 0; if (screq->cmdlen > sizeof(struct scsi_generic)) return EFAULT; if (screq->datalen > MAXPHYS) return EINVAL; xs = scsi_xs_get(link, 0); if (xs == NULL) return ENOMEM; memcpy(&xs->cmd, screq->cmd, screq->cmdlen); xs->cmdlen = screq->cmdlen; if (screq->datalen > 0) { xs->data = dma_alloc(screq->datalen, PR_WAITOK | PR_ZERO); if (xs->data == NULL) { err = ENOMEM; goto err; } xs->datalen = screq->datalen; } if (ISSET(screq->flags, SCCMD_READ)) SET(xs->flags, SCSI_DATA_IN); if (ISSET(screq->flags, SCCMD_WRITE)) { if (screq->datalen > 0) { err = copyin(screq->databuf, xs->data, screq->datalen); if (err != 0) goto err; } SET(xs->flags, SCSI_DATA_OUT); } SET(xs->flags, SCSI_SILENT); /* User is responsible for errors. */ xs->timeout = screq->timeout; xs->retries = 0; /* user must do the retries *//* ignored */ scsi_xs_sync(xs); screq->retsts = 0; screq->status = xs->status; switch (xs->error) { case XS_NOERROR: /* probably rubbish */ screq->datalen_used = xs->datalen - xs->resid; screq->retsts = SCCMD_OK; break; case XS_SENSE: SC_DEBUG_SENSE(xs); screq->senselen_used = min(sizeof(xs->sense), sizeof(screq->sense)); memcpy(screq->sense, &xs->sense, screq->senselen_used); screq->retsts = SCCMD_SENSE; break; case XS_SHORTSENSE: SC_DEBUG_SENSE(xs); printf("XS_SHORTSENSE\n"); screq->senselen_used = min(sizeof(xs->sense), sizeof(screq->sense)); memcpy(screq->sense, &xs->sense, screq->senselen_used); screq->retsts = SCCMD_UNKNOWN; break; case XS_DRIVER_STUFFUP: screq->retsts = SCCMD_UNKNOWN; break; case XS_TIMEOUT: screq->retsts = SCCMD_TIMEOUT; break; case XS_BUSY: screq->retsts = SCCMD_BUSY; break; default: screq->retsts = SCCMD_UNKNOWN; break; } if (screq->datalen > 0 && ISSET(screq->flags, SCCMD_READ)) { err = copyout(xs->data, screq->databuf, screq->datalen); if (err != 0) goto err; } err: if (xs->data) dma_free(xs->data, screq->datalen); scsi_xs_put(xs); return err; } int scsi_ioc_ata_cmd(struct scsi_link *link, atareq_t *atareq) { struct scsi_xfer *xs; struct scsi_ata_passthru_12 *cdb; int err = 0; if (atareq->datalen > MAXPHYS) return EINVAL; xs = scsi_xs_get(link, 0); if (xs == NULL) return ENOMEM; cdb = (struct scsi_ata_passthru_12 *)&xs->cmd; cdb->opcode = ATA_PASSTHRU_12; if (atareq->datalen > 0) { if (ISSET(atareq->flags, ATACMD_READ)) { cdb->count_proto = ATA_PASSTHRU_PROTO_PIO_DATAIN; cdb->flags = ATA_PASSTHRU_T_DIR_READ; } else { cdb->count_proto = ATA_PASSTHRU_PROTO_PIO_DATAOUT; cdb->flags = ATA_PASSTHRU_T_DIR_WRITE; } SET(cdb->flags, ATA_PASSTHRU_T_LEN_SECTOR_COUNT); } else { cdb->count_proto = ATA_PASSTHRU_PROTO_NON_DATA; cdb->flags = ATA_PASSTHRU_T_LEN_NONE; } cdb->features = atareq->features; cdb->sector_count = atareq->sec_count; cdb->lba_low = atareq->sec_num; cdb->lba_mid = atareq->cylinder; cdb->lba_high = atareq->cylinder >> 8; cdb->device = atareq->head & 0x0f; cdb->command = atareq->command; xs->cmdlen = sizeof(*cdb); if (atareq->datalen > 0) { xs->data = dma_alloc(atareq->datalen, PR_WAITOK | PR_ZERO); if (xs->data == NULL) { err = ENOMEM; goto err; } xs->datalen = atareq->datalen; } if (ISSET(atareq->flags, ATACMD_READ)) SET(xs->flags, SCSI_DATA_IN); if (ISSET(atareq->flags, ATACMD_WRITE)) { if (atareq->datalen > 0) { err = copyin(atareq->databuf, xs->data, atareq->datalen); if (err != 0) goto err; } SET(xs->flags, SCSI_DATA_OUT); } SET(xs->flags, SCSI_SILENT); /* User is responsible for errors. */ xs->retries = 0; /* user must do the retries *//* ignored */ scsi_xs_sync(xs); atareq->retsts = ATACMD_ERROR; switch (xs->error) { case XS_SENSE: case XS_SHORTSENSE: SC_DEBUG_SENSE(xs); /* XXX this is not right */ case XS_NOERROR: atareq->retsts = ATACMD_OK; break; default: atareq->retsts = ATACMD_ERROR; break; } if (atareq->datalen > 0 && ISSET(atareq->flags, ATACMD_READ)) { err = copyout(xs->data, atareq->databuf, atareq->datalen); if (err != 0) goto err; } err: if (xs->data) dma_free(xs->data, atareq->datalen); scsi_xs_put(xs); return err; } /* * Something (e.g. another driver) has called us * with a scsi_link for a target/lun/adapter, and a scsi * specific ioctl to perform, better try. */ int scsi_do_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag) { SC_DEBUG(link, SDEV_DB2, ("scsi_do_ioctl(0x%lx)\n", cmd)); switch(cmd) { case SCIOCIDENTIFY: { struct scsi_addr *sca = (struct scsi_addr *)addr; if (!ISSET(link->flags, (SDEV_ATAPI | SDEV_UMASS))) /* A 'real' SCSI target. */ sca->type = TYPE_SCSI; else /* An 'emulated' SCSI target. */ sca->type = TYPE_ATAPI; sca->scbus = link->bus->sc_dev.dv_unit; sca->target = link->target; sca->lun = link->lun; return 0; } case SCIOCCOMMAND: if (scsi_readsafe_cmd[((scsireq_t *)addr)->cmd[0]]) break; /* FALLTHROUGH */ case ATAIOCCOMMAND: case SCIOCDEBUG: if (!ISSET(flag, FWRITE)) return EPERM; break; default: if (link->bus->sb_adapter->ioctl) return (link->bus->sb_adapter->ioctl)(link, cmd, addr, flag); else return ENOTTY; } switch(cmd) { case SCIOCCOMMAND: return scsi_ioc_cmd(link, (scsireq_t *)addr); case ATAIOCCOMMAND: return scsi_ioc_ata_cmd(link, (atareq_t *)addr); case SCIOCDEBUG: { int level = *((int *)addr); SC_DEBUG(link, SDEV_DB3, ("debug set to %d\n", level)); CLR(link->flags, SDEV_DBX); /* clear debug bits */ if (level & 1) SET(link->flags, SDEV_DB1); if (level & 2) SET(link->flags, SDEV_DB2); if (level & 4) SET(link->flags, SDEV_DB3); if (level & 8) SET(link->flags, SDEV_DB4); return 0; } default: #ifdef DIAGNOSTIC panic("scsi_do_ioctl: impossible cmd (%#lx)", cmd); #endif /* DIAGNOSTIC */ return 0; } }
489 489 467 43 43 399 145 487 134 134 95 45 133 133 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 /* $OpenBSD: ufs_inode.c,v 1.45 2024/02/03 18:51:58 beck Exp $ */ /* $NetBSD: ufs_inode.c,v 1.7 1996/05/11 18:27:52 mycroft Exp $ */ /* * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ufs_inode.c 8.7 (Berkeley) 7/22/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/vnode.h> #include <sys/mount.h> #include <sys/malloc.h> #include <sys/namei.h> #include <ufs/ufs/quota.h> #include <ufs/ufs/inode.h> #include <ufs/ufs/ufsmount.h> #include <ufs/ufs/ufs_extern.h> #ifdef UFS_DIRHASH #include <ufs/ufs/dir.h> #include <ufs/ufs/dirhash.h> #endif /* * Last reference to an inode. If necessary, write or delete it. */ int ufs_inactive(void *v) { struct vop_inactive_args *ap = v; struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); mode_t mode; int error = 0; #ifdef DIAGNOSTIC extern int prtactive; if (prtactive && vp->v_usecount != 0) vprint("ufs_inactive: pushing active", vp); #endif /* * Ignore inodes related to stale file handles. */ if (ip->i_din1 == NULL || DIP(ip, mode) == 0) goto out; if (DIP(ip, nlink) <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { if (getinoquota(ip) == 0) (void)ufs_quota_free_inode(ip, NOCRED); error = UFS_TRUNCATE(ip, (off_t)0, 0, NOCRED); DIP_ASSIGN(ip, rdev, 0); mode = DIP(ip, mode); DIP_ASSIGN(ip, mode, 0); ip->i_flag |= IN_CHANGE | IN_UPDATE; UFS_INODE_FREE(ip, ip->i_number, mode); } if (ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) { UFS_UPDATE(ip, 0); } out: VOP_UNLOCK(vp); /* * If we are done with the inode, reclaim it * so that it can be reused immediately. */ if (ip->i_din1 == NULL || DIP(ip, mode) == 0) vrecycle(vp, ap->a_p); return (error); } /* * Reclaim an inode so that it can be used for other purposes. */ int ufs_reclaim(struct vnode *vp) { struct inode *ip; #ifdef DIAGNOSTIC extern int prtactive; if (prtactive && vp->v_usecount != 0) vprint("ufs_reclaim: pushing active", vp); #endif ip = VTOI(vp); /* * Stop deferring timestamp writes */ if (ip->i_flag & IN_LAZYMOD) { ip->i_flag |= IN_MODIFIED; UFS_UPDATE(ip, 0); } /* * Remove the inode from its hash chain. */ ufs_ihashrem(ip); /* * Purge old data structures associated with the inode. */ cache_purge(vp); if (ip->i_devvp) { vrele(ip->i_devvp); } #ifdef UFS_DIRHASH if (ip->i_dirhash != NULL) ufsdirhash_free(ip); #endif ufs_quota_delete(ip); return (0); }
1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 /* $OpenBSD: mbuf.h,v 1.263 2024/04/14 20:46:27 bluhm Exp $ */ /* $NetBSD: mbuf.h,v 1.19 1996/02/09 18:25:14 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)mbuf.h 8.5 (Berkeley) 2/19/95 */ #ifndef _SYS_MBUF_H_ #define _SYS_MBUF_H_ #include <sys/queue.h> /* * Constants related to network buffer management. * MCLBYTES must be no larger than PAGE_SIZE (the software page size) and, * on machines that exchange pages of input or output buffers with mbuf * clusters (MAPPED_MBUFS), MCLBYTES must also be an integral multiple * of the hardware page size. */ #define MSIZE 256 /* size of an mbuf */ /* * Mbufs are of a single size, MSIZE, which includes overhead. An mbuf may * add a single "mbuf cluster" of size MCLBYTES, which has no additional * overhead and is used instead of the internal data area; this is done when * at least MINCLSIZE of data must be stored. */ #define MLEN (MSIZE - sizeof(struct m_hdr)) /* normal data len */ #define MHLEN (MLEN - sizeof(struct pkthdr)) /* data len w/pkthdr */ #define MAXMCLBYTES (64 * 1024) /* largest cluster from the stack */ #define MINCLSIZE (MHLEN + MLEN + 1) /* smallest amount to put in cluster */ #define M_MAXCOMPRESS (MHLEN / 2) /* max amount to copy for compression */ #define MCLSHIFT 11 /* convert bytes to m_buf clusters */ /* 2K cluster can hold Ether frame */ #define MCLBYTES (1 << MCLSHIFT) /* size of a m_buf cluster */ #define MCLOFSET (MCLBYTES - 1) /* Packet tags structure */ struct m_tag { SLIST_ENTRY(m_tag) m_tag_link; /* List of packet tags */ u_int16_t m_tag_id; /* Tag ID */ u_int16_t m_tag_len; /* Length of data */ }; /* * Macros for type conversion * mtod(m,t) - convert mbuf pointer to data pointer of correct type */ #define mtod(m,t) ((t)((m)->m_data)) /* header at beginning of each mbuf: */ struct m_hdr { struct mbuf *mh_next; /* next buffer in chain */ struct mbuf *mh_nextpkt; /* next chain in queue/record */ caddr_t mh_data; /* location of data */ u_int mh_len; /* amount of data in this mbuf */ short mh_type; /* type of data in this mbuf */ u_short mh_flags; /* flags; see below */ #ifndef __LP64__ u_int mh_pad; /* pad to 8-byte boundary */ #endif }; /* pf stuff */ struct pf_state_key; struct inpcb; struct pkthdr_pf { struct pf_state_key *statekey; /* pf stackside statekey */ struct inpcb *inp; /* connected pcb for outgoing packet */ u_int32_t qid; /* queue id */ u_int16_t tag; /* tag id */ u_int16_t delay; /* delay packet by X ms */ u_int8_t flags; u_int8_t routed; u_int8_t prio; u_int8_t pad[1]; }; /* pkthdr_pf.flags */ #define PF_TAG_GENERATED 0x01 #define PF_TAG_SYNCOOKIE_RECREATED 0x02 #define PF_TAG_TRANSLATE_LOCALHOST 0x04 #define PF_TAG_DIVERTED 0x08 #define PF_TAG_DIVERTED_PACKET 0x10 #define PF_TAG_REROUTE 0x20 #define PF_TAG_REFRAGMENTED 0x40 /* refragmented ipv6 packet */ #define PF_TAG_PROCESSED 0x80 /* packet was checked by pf */ #ifdef _KERNEL #define MPF_BITS \ ("\20\1GENERATED\2SYNCOOKIE_RECREATED\3TRANSLATE_LOCALHOST\4DIVERTED" \ "\5DIVERTED_PACKET\6REROUTE\7REFRAGMENTED\10PROCESSED") #endif /* record/packet header in first mbuf of chain; valid if M_PKTHDR set */ struct pkthdr { void *ph_cookie; /* additional data */ SLIST_HEAD(, m_tag) ph_tags; /* list of packet tags */ int64_t ph_timestamp; /* packet timestamp */ int len; /* total packet length */ u_int ph_rtableid; /* routing table id */ u_int ph_ifidx; /* rcv interface index */ u_int16_t ph_tagsset; /* mtags attached */ u_int16_t ph_flowid; /* pseudo unique flow id */ u_int16_t csum_flags; /* checksum flags */ u_int16_t ether_vtag; /* Ethernet 802.1p+Q vlan tag */ u_int16_t ph_mss; /* TCP max segment size */ u_int8_t ph_loopcnt; /* mbuf is looping in kernel */ u_int8_t ph_family; /* af, used when queueing */ struct pkthdr_pf pf; }; /* description of external storage mapped into mbuf, valid if M_EXT set */ struct mbuf_ext { caddr_t ext_buf; /* start of buffer */ void *ext_arg; u_int ext_free_fn; /* index of free function */ u_int ext_size; /* size of buffer, for ext_free_fn */ struct mbuf *ext_nextref; struct mbuf *ext_prevref; #ifdef DEBUG const char *ext_ofile; const char *ext_nfile; int ext_oline; int ext_nline; #endif }; struct mbuf { struct m_hdr m_hdr; union { struct { struct pkthdr MH_pkthdr; /* M_PKTHDR set */ union { struct mbuf_ext MH_ext; /* M_EXT set */ char MH_databuf[MHLEN]; } MH_dat; } MH; char M_databuf[MLEN]; /* !M_PKTHDR, !M_EXT */ } M_dat; }; #define m_next m_hdr.mh_next #define m_len m_hdr.mh_len #define m_data m_hdr.mh_data #define m_type m_hdr.mh_type #define m_flags m_hdr.mh_flags #define m_nextpkt m_hdr.mh_nextpkt #define m_pkthdr M_dat.MH.MH_pkthdr #define m_ext M_dat.MH.MH_dat.MH_ext #define m_pktdat M_dat.MH.MH_dat.MH_databuf #define m_dat M_dat.M_databuf /* mbuf flags */ #define M_EXT 0x0001 /* has associated external storage */ #define M_PKTHDR 0x0002 /* start of record */ #define M_EOR 0x0004 /* end of record */ #define M_EXTWR 0x0008 /* external storage is writable */ #define M_PROTO1 0x0010 /* protocol-specific */ /* mbuf pkthdr flags, also in m_flags */ #define M_VLANTAG 0x0020 /* ether_vtag is valid */ #define M_LOOP 0x0040 /* packet has been sent from local machine */ #define M_BCAST 0x0100 /* sent/received as link-level broadcast */ #define M_MCAST 0x0200 /* sent/received as link-level multicast */ #define M_CONF 0x0400 /* payload was encrypted (ESP-transport) */ #define M_AUTH 0x0800 /* payload was authenticated (AH or ESP auth) */ #define M_TUNNEL 0x1000 /* IP-in-IP added by tunnel mode IPsec */ #define M_ZEROIZE 0x2000 /* Zeroize data part on free */ #define M_COMP 0x4000 /* header was decompressed */ #define M_LINK0 0x8000 /* link layer specific flag */ #ifdef _KERNEL #define M_BITS \ ("\20\1M_EXT\2M_PKTHDR\3M_EOR\4M_EXTWR\5M_PROTO1\6M_VLANTAG\7M_LOOP" \ "\11M_BCAST\12M_MCAST\13M_CONF\14M_AUTH\15M_TUNNEL" \ "\16M_ZEROIZE\17M_COMP\20M_LINK0") #endif /* flags copied when copying m_pkthdr */ #define M_COPYFLAGS (M_PKTHDR|M_EOR|M_PROTO1|M_BCAST|M_MCAST|M_CONF|M_COMP|\ M_AUTH|M_LOOP|M_TUNNEL|M_LINK0|M_VLANTAG|M_ZEROIZE) /* Checksumming flags */ #define M_IPV4_CSUM_OUT 0x0001 /* IPv4 checksum needed */ #define M_TCP_CSUM_OUT 0x0002 /* TCP checksum needed */ #define M_UDP_CSUM_OUT 0x0004 /* UDP checksum needed */ #define M_IPV4_CSUM_IN_OK 0x0008 /* IPv4 checksum verified */ #define M_IPV4_CSUM_IN_BAD 0x0010 /* IPv4 checksum bad */ #define M_TCP_CSUM_IN_OK 0x0020 /* TCP checksum verified */ #define M_TCP_CSUM_IN_BAD 0x0040 /* TCP checksum bad */ #define M_UDP_CSUM_IN_OK 0x0080 /* UDP checksum verified */ #define M_UDP_CSUM_IN_BAD 0x0100 /* UDP checksum bad */ #define M_ICMP_CSUM_OUT 0x0200 /* ICMP/ICMPv6 checksum needed */ #define M_ICMP_CSUM_IN_OK 0x0400 /* ICMP/ICMPv6 checksum verified */ #define M_ICMP_CSUM_IN_BAD 0x0800 /* ICMP/ICMPv6 checksum bad */ #define M_IPV6_DF_OUT 0x1000 /* don't fragment outgoing IPv6 */ #define M_TIMESTAMP 0x2000 /* ph_timestamp is set */ #define M_FLOWID 0x4000 /* ph_flowid is set */ #define M_TCP_TSO 0x8000 /* TCP Segmentation Offload needed */ #ifdef _KERNEL #define MCS_BITS \ ("\20\1IPV4_CSUM_OUT\2TCP_CSUM_OUT\3UDP_CSUM_OUT\4IPV4_CSUM_IN_OK" \ "\5IPV4_CSUM_IN_BAD\6TCP_CSUM_IN_OK\7TCP_CSUM_IN_BAD\10UDP_CSUM_IN_OK" \ "\11UDP_CSUM_IN_BAD\12ICMP_CSUM_OUT\13ICMP_CSUM_IN_OK\14ICMP_CSUM_IN_BAD" \ "\15IPV6_NODF_OUT" "\16TIMESTAMP" "\17FLOWID" "\20TCP_TSO") #endif /* mbuf types */ #define MT_FREE 0 /* should be on free list */ #define MT_DATA 1 /* dynamic (data) allocation */ #define MT_HEADER 2 /* packet header */ #define MT_SONAME 3 /* socket name */ #define MT_SOOPTS 4 /* socket options */ #define MT_FTABLE 5 /* fragment reassembly header */ #define MT_CONTROL 6 /* extra-data protocol message */ #define MT_OOBDATA 7 /* expedited data */ #define MT_NTYPES 8 /* flags to m_get/MGET */ #include <sys/malloc.h> #define M_DONTWAIT M_NOWAIT #define M_WAIT M_WAITOK /* * mbuf allocation/deallocation macros: * * MGET(struct mbuf *m, int how, int type) * allocates an mbuf and initializes it to contain internal data. * * MGETHDR(struct mbuf *m, int how, int type) * allocates an mbuf and initializes it to contain a packet header * and internal data. */ #define MGET(m, how, type) m = m_get((how), (type)) #define MGETHDR(m, how, type) m = m_gethdr((how), (type)) /* * Macros for tracking external storage associated with an mbuf. */ #ifdef DEBUG #define MCLREFDEBUGN(m, file, line) do { \ (m)->m_ext.ext_nfile = (file); \ (m)->m_ext.ext_nline = (line); \ } while (/* CONSTCOND */ 0) #define MCLREFDEBUGO(m, file, line) do { \ (m)->m_ext.ext_ofile = (file); \ (m)->m_ext.ext_oline = (line); \ } while (/* CONSTCOND */ 0) #else #define MCLREFDEBUGN(m, file, line) #define MCLREFDEBUGO(m, file, line) #endif #define MCLISREFERENCED(m) ((m)->m_ext.ext_nextref != (m)) #define MCLADDREFERENCE(o, n) m_extref((o), (n)) #define MCLINITREFERENCE(m) do { \ (m)->m_ext.ext_prevref = (m); \ (m)->m_ext.ext_nextref = (m); \ MCLREFDEBUGO((m), __FILE__, __LINE__); \ MCLREFDEBUGN((m), NULL, 0); \ } while (/* CONSTCOND */ 0) /* * Macros for mbuf external storage. * * MEXTADD adds pre-allocated external storage to * a normal mbuf; the flag M_EXT is set. * * MCLGET allocates and adds an mbuf cluster to a normal mbuf; * the flag M_EXT is set upon success. */ #define MEXTADD(m, buf, size, mflags, freefn, arg) do { \ (m)->m_data = (m)->m_ext.ext_buf = (caddr_t)(buf); \ (m)->m_flags |= M_EXT | (mflags & M_EXTWR); \ (m)->m_ext.ext_size = (size); \ (m)->m_ext.ext_free_fn = (freefn); \ (m)->m_ext.ext_arg = (arg); \ MCLINITREFERENCE(m); \ } while (/* CONSTCOND */ 0) #define MCLGET(m, how) (void) m_clget((m), (how), MCLBYTES) #define MCLGETL(m, how, l) m_clget((m), (how), (l)) u_int mextfree_register(void (*)(caddr_t, u_int, void *)); #define MEXTFREE_POOL 0 /* * Move just m_pkthdr from from to to, * remove M_PKTHDR and clean flags/tags for from. */ #define M_MOVE_HDR(to, from) do { \ (to)->m_pkthdr = (from)->m_pkthdr; \ (from)->m_flags &= ~M_PKTHDR; \ SLIST_INIT(&(from)->m_pkthdr.ph_tags); \ (from)->m_pkthdr.pf.statekey = NULL; \ } while (/* CONSTCOND */ 0) /* * MOVE mbuf pkthdr from from to to. * from must have M_PKTHDR set, and to must be empty. */ #define M_MOVE_PKTHDR(to, from) do { \ (to)->m_flags = ((to)->m_flags & (M_EXT | M_EXTWR)); \ (to)->m_flags |= (from)->m_flags & M_COPYFLAGS; \ M_MOVE_HDR((to), (from)); \ if (((to)->m_flags & M_EXT) == 0) \ (to)->m_data = (to)->m_pktdat; \ } while (/* CONSTCOND */ 0) /* * Determine if an mbuf's data area is read-only. This is true for * non-cluster external storage and for clusters that are being * referenced by more than one mbuf. */ #define M_READONLY(m) \ (((m)->m_flags & M_EXT) != 0 && \ (((m)->m_flags & M_EXTWR) == 0 || MCLISREFERENCED(m))) /* * Arrange to prepend space of size plen to mbuf m. * If a new mbuf must be allocated, how specifies whether to wait. * If how is M_DONTWAIT and allocation fails, the original mbuf chain * is freed and m is set to NULL. */ #define M_PREPEND(m, plen, how) \ (m) = m_prepend((m), (plen), (how)) /* length to m_copy to copy all */ #define M_COPYALL 1000000000 #define MBSTAT_TYPES MT_NTYPES #define MBSTAT_DROPS (MBSTAT_TYPES + 0) #define MBSTAT_WAIT (MBSTAT_TYPES + 1) #define MBSTAT_DRAIN (MBSTAT_TYPES + 2) #define MBSTAT_COUNT (MBSTAT_TYPES + 3) /* * Mbuf statistics. * For statistics related to mbuf and cluster allocations, see also the * pool headers (mbpool and mclpool). */ struct mbstat { u_long m_drops; /* times failed to find space */ u_long m_wait; /* times waited for space */ u_long m_drain; /* times drained protocols for space */ u_long m_mtypes[MBSTAT_COUNT]; /* type specific mbuf allocations */ }; #include <sys/mutex.h> struct mbuf_list { struct mbuf *ml_head; struct mbuf *ml_tail; u_int ml_len; }; struct mbuf_queue { struct mutex mq_mtx; struct mbuf_list mq_list; u_int mq_maxlen; u_int mq_drops; }; #ifdef _KERNEL struct pool; extern long nmbclust; /* limit on the # of clusters */ extern int max_linkhdr; /* largest link-level header */ extern int max_protohdr; /* largest protocol header */ extern int max_hdr; /* largest link+protocol header */ void mbinit(void); void mbcpuinit(void); int nmbclust_update(long); struct mbuf *m_copym(struct mbuf *, int, int, int); struct mbuf *m_free(struct mbuf *); struct mbuf *m_get(int, int); struct mbuf *m_getclr(int, int); struct mbuf *m_gethdr(int, int); struct mbuf *m_inithdr(struct mbuf *); void m_removehdr(struct mbuf *); void m_resethdr(struct mbuf *); void m_calchdrlen(struct mbuf *); int m_defrag(struct mbuf *, int); struct mbuf *m_prepend(struct mbuf *, int, int); struct mbuf *m_pulldown(struct mbuf *, int, int, int *); struct mbuf *m_pullup(struct mbuf *, int); struct mbuf *m_split(struct mbuf *, int, int); struct mbuf *m_makespace(struct mbuf *, int, int, int *); struct mbuf *m_getptr(struct mbuf *, int, int *); int m_leadingspace(struct mbuf *); int m_trailingspace(struct mbuf *); void m_align(struct mbuf *, int); struct mbuf *m_clget(struct mbuf *, int, u_int); void m_extref(struct mbuf *, struct mbuf *); void m_pool_init(struct pool *, u_int, u_int, const char *); u_int m_pool_used(void); void m_extfree_pool(caddr_t, u_int, void *); void m_adj(struct mbuf *, int); int m_copyback(struct mbuf *, int, int, const void *, int); struct mbuf *m_freem(struct mbuf *); void m_purge(struct mbuf *); void m_copydata(struct mbuf *, int, int, void *); void m_cat(struct mbuf *, struct mbuf *); struct mbuf *m_devget(char *, int, int); int m_apply(struct mbuf *, int, int, int (*)(caddr_t, caddr_t, unsigned int), caddr_t); struct mbuf *m_dup_pkt(struct mbuf *, unsigned int, int); int m_dup_pkthdr(struct mbuf *, struct mbuf *, int); void m_microtime(const struct mbuf *, struct timeval *); static inline struct mbuf * m_freemp(struct mbuf **mp) { struct mbuf *m = *mp; *mp = NULL; return m_freem(m); } /* Packet tag routines */ struct m_tag *m_tag_get(int, int, int); void m_tag_prepend(struct mbuf *, struct m_tag *); void m_tag_delete(struct mbuf *, struct m_tag *); void m_tag_delete_chain(struct mbuf *); struct m_tag *m_tag_find(struct mbuf *, int, struct m_tag *); struct m_tag *m_tag_copy(struct m_tag *, int); int m_tag_copy_chain(struct mbuf *, struct mbuf *, int); void m_tag_init(struct mbuf *); struct m_tag *m_tag_first(struct mbuf *); struct m_tag *m_tag_next(struct mbuf *, struct m_tag *); /* Packet tag types */ #define PACKET_TAG_IPSEC_IN_DONE 0x0001 /* IPsec applied, in */ #define PACKET_TAG_IPSEC_OUT_DONE 0x0002 /* IPsec applied, out */ #define PACKET_TAG_IPSEC_FLOWINFO 0x0004 /* IPsec flowinfo */ #define PACKET_TAG_IP_OFFNXT 0x0010 /* IPv4 offset and next proto */ #define PACKET_TAG_IP6_OFFNXT 0x0020 /* IPv6 offset and next proto */ #define PACKET_TAG_WIREGUARD 0x0040 /* WireGuard data */ #define PACKET_TAG_GRE 0x0080 /* GRE processing done */ #define PACKET_TAG_DLT 0x0100 /* data link layer type */ #define PACKET_TAG_PF_DIVERT 0x0200 /* pf(4) diverted packet */ #define PACKET_TAG_PF_REASSEMBLED 0x0800 /* pf reassembled ipv6 packet */ #define PACKET_TAG_SRCROUTE 0x1000 /* IPv4 source routing options */ #define PACKET_TAG_TUNNEL 0x2000 /* Tunnel endpoint address */ #define PACKET_TAG_CARP_BAL_IP 0x4000 /* carp(4) ip balanced marker */ #define MTAG_BITS \ ("\20\1IPSEC_IN_DONE\2IPSEC_OUT_DONE\3IPSEC_FLOWINFO" \ "\4IPSEC_OUT_CRYPTO_NEEDED\5IPSEC_PENDING_TDB\6BRIDGE\7WG\10GRE\11DLT" \ "\12PF_DIVERT\14PF_REASSEMBLED\15SRCROUTE\16TUNNEL\17CARP_BAL_IP") /* * Maximum tag payload length (that is excluding the m_tag structure). * Please make sure to update this value when increasing the payload * length for an existing packet tag type or when adding a new one that * has payload larger than the value below. */ #define PACKET_TAG_MAXSIZE 80 /* Detect mbufs looping in the kernel when spliced too often. */ #define M_MAXLOOP 128 /* * mbuf lists */ #define MBUF_LIST_INITIALIZER() { NULL, NULL, 0 } void ml_init(struct mbuf_list *); void ml_enqueue(struct mbuf_list *, struct mbuf *); struct mbuf * ml_dequeue(struct mbuf_list *); void ml_enlist(struct mbuf_list *, struct mbuf_list *); struct mbuf * ml_dechain(struct mbuf_list *); unsigned int ml_purge(struct mbuf_list *); unsigned int ml_hdatalen(struct mbuf_list *); #define ml_len(_ml) ((_ml)->ml_len) #define ml_empty(_ml) ((_ml)->ml_len == 0) #define MBUF_LIST_FIRST(_ml) ((_ml)->ml_head) #define MBUF_LIST_NEXT(_m) ((_m)->m_nextpkt) #define MBUF_LIST_FOREACH(_ml, _m) \ for ((_m) = MBUF_LIST_FIRST(_ml); \ (_m) != NULL; \ (_m) = MBUF_LIST_NEXT(_m)) /* * mbuf queues */ #include <sys/atomic.h> #define MBUF_QUEUE_INITIALIZER(_maxlen, _ipl) \ { MUTEX_INITIALIZER(_ipl), MBUF_LIST_INITIALIZER(), (_maxlen), 0 } void mq_init(struct mbuf_queue *, u_int, int); int mq_push(struct mbuf_queue *, struct mbuf *); int mq_enqueue(struct mbuf_queue *, struct mbuf *); struct mbuf * mq_dequeue(struct mbuf_queue *); int mq_enlist(struct mbuf_queue *, struct mbuf_list *); void mq_delist(struct mbuf_queue *, struct mbuf_list *); struct mbuf * mq_dechain(struct mbuf_queue *); unsigned int mq_purge(struct mbuf_queue *); unsigned int mq_hdatalen(struct mbuf_queue *); void mq_set_maxlen(struct mbuf_queue *, u_int); #define mq_len(_mq) READ_ONCE((_mq)->mq_list.ml_len) #define mq_empty(_mq) (mq_len(_mq) == 0) #define mq_full(_mq) (mq_len((_mq)) >= READ_ONCE((_mq)->mq_maxlen)) #define mq_drops(_mq) READ_ONCE((_mq)->mq_drops) #endif /* _KERNEL */ #endif /* _SYS_MBUF_H_ */
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 /* $OpenBSD: libkern.h,v 1.37 2023/12/21 02:57:14 jsg Exp $ */ /* $NetBSD: libkern.h,v 1.7 1996/03/14 18:52:08 christos Exp $ */ /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)libkern.h 8.1 (Berkeley) 6/10/93 */ #ifndef __LIBKERN_H__ #define __LIBKERN_H__ #include <sys/types.h> #ifndef LIBKERN_INLINE #define LIBKERN_INLINE static __inline #define LIBKERN_BODY #endif LIBKERN_INLINE int imax(int, int); LIBKERN_INLINE int imin(int, int); LIBKERN_INLINE u_int max(u_int, u_int); LIBKERN_INLINE u_int min(u_int, u_int); LIBKERN_INLINE long lmax(long, long); LIBKERN_INLINE long lmin(long, long); LIBKERN_INLINE u_long ulmax(u_long, u_long); LIBKERN_INLINE u_long ulmin(u_long, u_long); LIBKERN_INLINE int abs(int); #ifdef LIBKERN_BODY LIBKERN_INLINE int imax(int a, int b) { return (a > b ? a : b); } LIBKERN_INLINE int imin(int a, int b) { return (a < b ? a : b); } LIBKERN_INLINE long lmax(long a, long b) { return (a > b ? a : b); } LIBKERN_INLINE long lmin(long a, long b) { return (a < b ? a : b); } LIBKERN_INLINE u_int max(u_int a, u_int b) { return (a > b ? a : b); } LIBKERN_INLINE u_int min(u_int a, u_int b) { return (a < b ? a : b); } LIBKERN_INLINE u_long ulmax(u_long a, u_long b) { return (a > b ? a : b); } LIBKERN_INLINE u_long ulmin(u_long a, u_long b) { return (a < b ? a : b); } LIBKERN_INLINE int abs(int j) { return(j < 0 ? -j : j); } #endif #ifdef NDEBUG /* tradition! */ #define assert(e) ((void)0) #else #define assert(e) ((e) ? (void)0 : \ __assert("", __FILE__, __LINE__, #e)) #endif #define __KASSERTSTR "kernel %sassertion \"%s\" failed: file \"%s\", line %d" #ifndef DIAGNOSTIC #define KASSERTMSG(e, msg, ...) ((void)0) #define KASSERT(e) ((void)0) #else #define KASSERTMSG(e, msg, ...) ((e) ? (void)0 : \ panic(__KASSERTSTR " " msg, "diagnostic ", #e, \ __FILE__, __LINE__, ## __VA_ARGS__)) #define KASSERT(e) ((e) ? (void)0 : \ __assert("diagnostic ", __FILE__, __LINE__, #e)) #endif #ifndef DEBUG #define KDASSERTMSG(e, msg, ...) ((void)0) #define KDASSERT(e) ((void)0) #else #define KDASSERTMSG(e, msg, ...) ((e) ? (void)0 : \ panic(__KASSERTSTR " " msg, "debugging ", #e, \ __FILE__, __LINE__, ## __VA_ARGS__)) #define KDASSERT(e) ((e) ? (void)0 : \ __assert("debugging ", __FILE__, __LINE__, #e)) #endif #define CTASSERT(x) extern char _ctassert[(x) ? 1 : -1 ] \ __attribute__((__unused__)) /* Prototypes for non-quad routines. */ void __assert(const char *, const char *, int, const char *) __attribute__ ((__noreturn__)); int bcmp(const void *, const void *, size_t); void bzero(void *, size_t); void explicit_bzero(void *, size_t); int ffs(int); int fls(int); int flsl(long); void *memchr(const void *, int, size_t); int memcmp(const void *, const void *, size_t); void *memset(void *, int c, size_t len); u_int32_t random(void); int scanc(u_int, const u_char *, const u_char [], int); int skpc(int, size_t, u_char *); size_t strlen(const char *); char *strncpy(char *, const char *, size_t) __attribute__ ((__bounded__(__string__,1,3))); size_t strnlen(const char *, size_t); size_t strlcpy(char *, const char *, size_t) __attribute__ ((__bounded__(__string__,1,3))); size_t strlcat(char *, const char *, size_t) __attribute__ ((__bounded__(__string__,1,3))); int strcmp(const char *, const char *); int strncmp(const char *, const char *, size_t); int strncasecmp(const char *, const char *, size_t); size_t getsn(char *, size_t) __attribute__ ((__bounded__(__string__,1,2))); char *strchr(const char *, int); char *strrchr(const char *, int); int timingsafe_bcmp(const void *, const void *, size_t); char *strnstr(const char *, const char *, size_t); #endif /* __LIBKERN_H__ */
21 21 3 3 3 21 21 21 21 17 17 21 21 20 21 21 21 15 21 21 14 7 21 18 3 9 12 11 10 11 244 244 60 60 60 25 17 8 25 25 25 25 17 8 17 8 20 19 19 174 94 21 78 77 46 23 23 1052 258 833 2 1048 7 81 80 56 17 6 17 17 17 17 17 15 15 15 15 15 15 21 6 15 14 14 67 54 12 9 5 84 84 15 32 50 49 24 13 15 2 3 4 3 1 58 58 41 31 50 48 52 28 28 28 23 28 10 2 6 3 19 18 17 4 3 3 5 3 3 12 12 12 21 21 8 13 21 30 30 9 9 20 231 4 468 15 31 15 423 529 144 423 8 9 1 3 5 5 8 5 5 4 4 5 2 452 71 3 7 3 60 3 3 204 234 1 1 1 1 1 1 1 6 10 1 15 7 13 3 13 8 15 3 11 4 12 3 5 10 14 1 8 3 4 2 1 6 5 6 3 1 1 1 1 2 1 1 2 1 1 3 1 1 1 1 9 1 2 1 1 4 1 1 1 8 8 1 1 1 1 1 1 3 47 12 213 60 13 307 17 14 300 17 71 25 12 6 2 7 17 1 1 1 1 1 3 1 1 1 1 6 1 25 4 4 4 17 3 13 14 7 17 6 4 14 4 21 21 51 1 49 50 51 7 24 1 1 22 15 7 22 22 19 4 16 17 16 7 6 1 2 2 2 6 6 1 2 2 1 2 1 3 3 1 1 3 4 2 2 76 41 1 50 6 6 1 4 1 2 1 5 3 3 3 35 36 37 38 2 2 8 8 4 6 1 8 6 3 21 15 53 13 12 1 61 85 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 /* $OpenBSD: if.c,v 1.718 2024/02/06 00:18:53 bluhm Exp $ */ /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 1980, 1986, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)if.c 8.3 (Berkeley) 1/4/94 */ #include "bpfilter.h" #include "bridge.h" #include "carp.h" #include "ether.h" #include "pf.h" #include "pfsync.h" #include "ppp.h" #include "pppoe.h" #include "if_wg.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/timeout.h> #include <sys/protosw.h> #include <sys/kernel.h> #include <sys/ioctl.h> #include <sys/domain.h> #include <sys/task.h> #include <sys/atomic.h> #include <sys/percpu.h> #include <sys/proc.h> #include <sys/stdint.h> /* uintptr_t */ #include <sys/rwlock.h> #include <sys/smr.h> #include <net/if.h> #include <net/if_dl.h> #include <net/if_types.h> #include <net/route.h> #include <net/netisr.h> #include "vlan.h" #if NVLAN > 0 #include <net/if_vlan_var.h> #endif #include <netinet/in.h> #include <netinet/if_ether.h> #include <netinet/igmp.h> #ifdef MROUTING #include <netinet/ip_mroute.h> #endif #include <netinet/tcp.h> #include <netinet/tcp_timer.h> #include <netinet/tcp_var.h> #ifdef INET6 #include <netinet6/in6_var.h> #include <netinet6/in6_ifattach.h> #include <netinet6/nd6.h> #include <netinet/ip6.h> #include <netinet6/ip6_var.h> #endif #ifdef MPLS #include <netmpls/mpls.h> #endif #if NBPFILTER > 0 #include <net/bpf.h> #endif #if NBRIDGE > 0 #include <net/if_bridge.h> #endif #if NCARP > 0 #include <netinet/ip_carp.h> #endif #if NPF > 0 #include <net/pfvar.h> #endif #include <sys/device.h> void if_attachsetup(struct ifnet *); void if_attach_common(struct ifnet *); void if_remove(struct ifnet *); int if_createrdomain(int, struct ifnet *); int if_setrdomain(struct ifnet *, int); void if_slowtimo(void *); void if_detached_qstart(struct ifqueue *); int if_detached_ioctl(struct ifnet *, u_long, caddr_t); int ifioctl_get(u_long, caddr_t); int ifconf(caddr_t); static int if_sffpage_check(const caddr_t); int if_getgroup(caddr_t, struct ifnet *); int if_getgroupmembers(caddr_t); int if_getgroupattribs(caddr_t); int if_setgroupattribs(caddr_t); int if_getgrouplist(caddr_t); void if_linkstate(struct ifnet *); void if_linkstate_task(void *); int if_clone_list(struct if_clonereq *); struct if_clone *if_clone_lookup(const char *, int *); int if_group_egress_build(void); void if_watchdog_task(void *); void if_netisr(void *); #ifdef DDB void ifa_print_all(void); #endif void if_qstart_compat(struct ifqueue *); /* * interface index map * * the kernel maintains a mapping of interface indexes to struct ifnet * pointers. * * the map is an array of struct ifnet pointers prefixed by an if_map * structure. the if_map structure stores the length of its array. * * as interfaces are attached to the system, the map is grown on demand * up to USHRT_MAX entries. * * interface index 0 is reserved and represents no interface. this * supports the use of the interface index as the scope for IPv6 link * local addresses, where scope 0 means no scope has been specified. * it also supports the use of interface index as the unique identifier * for network interfaces in SNMP applications as per RFC2863. therefore * if_get(0) returns NULL. */ struct ifnet *if_ref(struct ifnet *); /* * struct if_idxmap * * infrastructure to manage updates and accesses to the current if_map. * * interface index 0 is special and represents "no interface", so we * use the 0th slot in map to store the length of the array. */ struct if_idxmap { unsigned int serial; unsigned int count; struct ifnet **map; /* SMR protected */ struct rwlock lock; unsigned char *usedidx; /* bitmap of indices in use */ }; struct if_idxmap_dtor { struct smr_entry smr; struct ifnet **map; }; void if_idxmap_init(unsigned int); void if_idxmap_free(void *); void if_idxmap_alloc(struct ifnet *); void if_idxmap_insert(struct ifnet *); void if_idxmap_remove(struct ifnet *); TAILQ_HEAD(, ifg_group) ifg_head = TAILQ_HEAD_INITIALIZER(ifg_head); /* [N] list of interface groups */ LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners); /* [I] list of clonable interfaces */ int if_cloners_count; /* [I] number of clonable interfaces */ struct rwlock if_cloners_lock = RWLOCK_INITIALIZER("clonelk"); /* hooks should only be added, deleted, and run from a process context */ struct mutex if_hooks_mtx = MUTEX_INITIALIZER(IPL_NONE); void if_hooks_run(struct task_list *); int ifq_congestion; int netisr; struct softnet { char sn_name[16]; struct taskq *sn_taskq; }; #define NET_TASKQ 4 struct softnet softnets[NET_TASKQ]; struct task if_input_task_locked = TASK_INITIALIZER(if_netisr, NULL); /* * Serialize socket operations to ensure no new sleeping points * are introduced in IP output paths. */ struct rwlock netlock = RWLOCK_INITIALIZER("netlock"); /* * Network interface utility routines. */ void ifinit(void) { unsigned int i; /* * most machines boot with 4 or 5 interfaces, so size the initial map * to accommodate this */ if_idxmap_init(8); /* 8 is a nice power of 2 for malloc */ for (i = 0; i < NET_TASKQ; i++) { struct softnet *sn = &softnets[i]; snprintf(sn->sn_name, sizeof(sn->sn_name), "softnet%u", i); sn->sn_taskq = taskq_create(sn->sn_name, 1, IPL_NET, TASKQ_MPSAFE); if (sn->sn_taskq == NULL) panic("unable to create network taskq %d", i); } } static struct if_idxmap if_idxmap; /* * XXXSMP: For `ifnetlist' modification both kernel and net locks * should be taken. For read-only access only one lock of them required. */ struct ifnet_head ifnetlist = TAILQ_HEAD_INITIALIZER(ifnetlist); static inline unsigned int if_idxmap_limit(struct ifnet **if_map) { return ((uintptr_t)if_map[0]); } static inline size_t if_idxmap_usedidx_size(unsigned int limit) { return (max(howmany(limit, NBBY), sizeof(struct if_idxmap_dtor))); } void if_idxmap_init(unsigned int limit) { struct ifnet **if_map; rw_init(&if_idxmap.lock, "idxmaplk"); if_idxmap.serial = 1; /* skip ifidx 0 */ if_map = mallocarray(limit, sizeof(*if_map), M_IFADDR, M_WAITOK | M_ZERO); if_map[0] = (struct ifnet *)(uintptr_t)limit; if_idxmap.usedidx = malloc(if_idxmap_usedidx_size(limit), M_IFADDR, M_WAITOK | M_ZERO); setbit(if_idxmap.usedidx, 0); /* blacklist ifidx 0 */ /* this is called early so there's nothing to race with */ SMR_PTR_SET_LOCKED(&if_idxmap.map, if_map); } void if_idxmap_alloc(struct ifnet *ifp) { struct ifnet **if_map; unsigned int limit; unsigned int index, i; refcnt_init(&ifp->if_refcnt); rw_enter_write(&if_idxmap.lock); if (++if_idxmap.count >= USHRT_MAX) panic("too many interfaces"); if_map = SMR_PTR_GET_LOCKED(&if_idxmap.map); limit = if_idxmap_limit(if_map); index = if_idxmap.serial++ & USHRT_MAX; if (index >= limit) { struct if_idxmap_dtor *dtor; struct ifnet **oif_map; unsigned int olimit; unsigned char *nusedidx; oif_map = if_map; olimit = limit; limit = olimit * 2; if_map = mallocarray(limit, sizeof(*if_map), M_IFADDR, M_WAITOK | M_ZERO); if_map[0] = (struct ifnet *)(uintptr_t)limit; for (i = 1; i < olimit; i++) { struct ifnet *oifp = SMR_PTR_GET_LOCKED(&oif_map[i]); if (oifp == NULL) continue; /* * nif_map isn't visible yet, so don't need * SMR_PTR_SET_LOCKED and its membar. */ if_map[i] = if_ref(oifp); } nusedidx = malloc(if_idxmap_usedidx_size(limit), M_IFADDR, M_WAITOK | M_ZERO); memcpy(nusedidx, if_idxmap.usedidx, howmany(olimit, NBBY)); /* use the old usedidx bitmap as an smr_entry for the if_map */ dtor = (struct if_idxmap_dtor *)if_idxmap.usedidx; if_idxmap.usedidx = nusedidx; SMR_PTR_SET_LOCKED(&if_idxmap.map, if_map); dtor->map = oif_map; smr_init(&dtor->smr); smr_call(&dtor->smr, if_idxmap_free, dtor); } /* pick the next free index */ for (i = 0; i < USHRT_MAX; i++) { if (index != 0 && isclr(if_idxmap.usedidx, index)) break; index = if_idxmap.serial++ & USHRT_MAX; } KASSERT(index != 0 && index < limit); KASSERT(isclr(if_idxmap.usedidx, index)); setbit(if_idxmap.usedidx, index); ifp->if_index = index; rw_exit_write(&if_idxmap.lock); } void if_idxmap_free(void *arg) { struct if_idxmap_dtor *dtor = arg; struct ifnet **oif_map = dtor->map; unsigned int olimit = if_idxmap_limit(oif_map); unsigned int i; for (i = 1; i < olimit; i++) if_put(oif_map[i]); free(oif_map, M_IFADDR, olimit * sizeof(*oif_map)); free(dtor, M_IFADDR, if_idxmap_usedidx_size(olimit)); } void if_idxmap_insert(struct ifnet *ifp) { struct ifnet **if_map; unsigned int index = ifp->if_index; rw_enter_write(&if_idxmap.lock); if_map = SMR_PTR_GET_LOCKED(&if_idxmap.map); KASSERTMSG(index != 0 && index < if_idxmap_limit(if_map), "%s(%p) index %u vs limit %u", ifp->if_xname, ifp, index, if_idxmap_limit(if_map)); KASSERT(SMR_PTR_GET_LOCKED(&if_map[index]) == NULL); KASSERT(isset(if_idxmap.usedidx, index)); /* commit */ SMR_PTR_SET_LOCKED(&if_map[index], if_ref(ifp)); rw_exit_write(&if_idxmap.lock); } void if_idxmap_remove(struct ifnet *ifp) { struct ifnet **if_map; unsigned int index = ifp->if_index; rw_enter_write(&if_idxmap.lock); if_map = SMR_PTR_GET_LOCKED(&if_idxmap.map); KASSERT(index != 0 && index < if_idxmap_limit(if_map)); KASSERT(SMR_PTR_GET_LOCKED(&if_map[index]) == ifp); KASSERT(isset(if_idxmap.usedidx, index)); SMR_PTR_SET_LOCKED(&if_map[index], NULL); if_idxmap.count--; clrbit(if_idxmap.usedidx, index); /* end of if_idxmap modifications */ rw_exit_write(&if_idxmap.lock); smr_barrier(); if_put(ifp); } /* * Attach an interface to the * list of "active" interfaces. */ void if_attachsetup(struct ifnet *ifp) { unsigned long ifidx; NET_ASSERT_LOCKED(); if_addgroup(ifp, IFG_ALL); #ifdef INET6 nd6_ifattach(ifp); #endif #if NPF > 0 pfi_attach_ifnet(ifp); #endif timeout_set(&ifp->if_slowtimo, if_slowtimo, ifp); if_slowtimo(ifp); if_idxmap_insert(ifp); KASSERT(if_get(0) == NULL); ifidx = ifp->if_index; task_set(&ifp->if_watchdogtask, if_watchdog_task, (void *)ifidx); task_set(&ifp->if_linkstatetask, if_linkstate_task, (void *)ifidx); /* Announce the interface. */ rtm_ifannounce(ifp, IFAN_ARRIVAL); } /* * Allocate the link level name for the specified interface. This * is an attachment helper. It must be called after ifp->if_addrlen * is initialized, which may not be the case when if_attach() is * called. */ void if_alloc_sadl(struct ifnet *ifp) { unsigned int socksize; int namelen, masklen; struct sockaddr_dl *sdl; /* * If the interface already has a link name, release it * now. This is useful for interfaces that can change * link types, and thus switch link names often. */ if_free_sadl(ifp); namelen = strlen(ifp->if_xname); masklen = offsetof(struct sockaddr_dl, sdl_data[0]) + namelen; socksize = masklen + ifp->if_addrlen; #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) if (socksize < sizeof(*sdl)) socksize = sizeof(*sdl); socksize = ROUNDUP(socksize); sdl = malloc(socksize, M_IFADDR, M_WAITOK|M_ZERO); sdl->sdl_len = socksize; sdl->sdl_family = AF_LINK; bcopy(ifp->if_xname, sdl->sdl_data, namelen); sdl->sdl_nlen = namelen; sdl->sdl_alen = ifp->if_addrlen; sdl->sdl_index = ifp->if_index; sdl->sdl_type = ifp->if_type; ifp->if_sadl = sdl; } /* * Free the link level name for the specified interface. This is * a detach helper. This is called from if_detach() or from * link layer type specific detach functions. */ void if_free_sadl(struct ifnet *ifp) { if (ifp->if_sadl == NULL) return; free(ifp->if_sadl, M_IFADDR, ifp->if_sadl->sdl_len); ifp->if_sadl = NULL; } void if_attachhead(struct ifnet *ifp) { if_attach_common(ifp); NET_LOCK(); TAILQ_INSERT_HEAD(&ifnetlist, ifp, if_list); if_attachsetup(ifp); NET_UNLOCK(); } void if_attach(struct ifnet *ifp) { if_attach_common(ifp); NET_LOCK(); TAILQ_INSERT_TAIL(&ifnetlist, ifp, if_list); if_attachsetup(ifp); NET_UNLOCK(); } void if_attach_queues(struct ifnet *ifp, unsigned int nqs) { struct ifqueue **map; struct ifqueue *ifq; int i; KASSERT(ifp->if_ifqs == ifp->if_snd.ifq_ifqs); KASSERT(nqs != 0); map = mallocarray(sizeof(*map), nqs, M_DEVBUF, M_WAITOK); ifp->if_snd.ifq_softc = NULL; map[0] = &ifp->if_snd; for (i = 1; i < nqs; i++) { ifq = malloc(sizeof(*ifq), M_DEVBUF, M_WAITOK|M_ZERO); ifq_init_maxlen(ifq, ifp->if_snd.ifq_maxlen); ifq_init(ifq, ifp, i); map[i] = ifq; } ifp->if_ifqs = map; ifp->if_nifqs = nqs; } void if_attach_iqueues(struct ifnet *ifp, unsigned int niqs) { struct ifiqueue **map; struct ifiqueue *ifiq; unsigned int i; KASSERT(niqs != 0); map = mallocarray(niqs, sizeof(*map), M_DEVBUF, M_WAITOK); ifp->if_rcv.ifiq_softc = NULL; map[0] = &ifp->if_rcv; for (i = 1; i < niqs; i++) { ifiq = malloc(sizeof(*ifiq), M_DEVBUF, M_WAITOK|M_ZERO); ifiq_init(ifiq, ifp, i); map[i] = ifiq; } ifp->if_iqs = map; ifp->if_niqs = niqs; } void if_attach_common(struct ifnet *ifp) { KASSERT(ifp->if_ioctl != NULL); TAILQ_INIT(&ifp->if_addrlist); TAILQ_INIT(&ifp->if_maddrlist); TAILQ_INIT(&ifp->if_groups); if (!ISSET(ifp->if_xflags, IFXF_MPSAFE)) { KASSERTMSG(ifp->if_qstart == NULL, "%s: if_qstart set without MPSAFE set", ifp->if_xname); ifp->if_qstart = if_qstart_compat; } else { KASSERTMSG(ifp->if_start == NULL, "%s: if_start set with MPSAFE set", ifp->if_xname); KASSERTMSG(ifp->if_qstart != NULL, "%s: if_qstart not set with MPSAFE set", ifp->if_xname); } if_idxmap_alloc(ifp); ifq_init(&ifp->if_snd, ifp, 0); ifp->if_snd.ifq_ifqs[0] = &ifp->if_snd; ifp->if_ifqs = ifp->if_snd.ifq_ifqs; ifp->if_nifqs = 1; if (ifp->if_txmit == 0) ifp->if_txmit = IF_TXMIT_DEFAULT; ifiq_init(&ifp->if_rcv, ifp, 0); ifp->if_rcv.ifiq_ifiqs[0] = &ifp->if_rcv; ifp->if_iqs = ifp->if_rcv.ifiq_ifiqs; ifp->if_niqs = 1; TAILQ_INIT(&ifp->if_addrhooks); TAILQ_INIT(&ifp->if_linkstatehooks); TAILQ_INIT(&ifp->if_detachhooks); if (ifp->if_rtrequest == NULL) ifp->if_rtrequest = if_rtrequest_dummy; if (ifp->if_enqueue == NULL) ifp->if_enqueue = if_enqueue_ifq; #if NBPFILTER > 0 if (ifp->if_bpf_mtap == NULL) ifp->if_bpf_mtap = bpf_mtap_ether; #endif ifp->if_llprio = IFQ_DEFPRIO; } void if_attach_ifq(struct ifnet *ifp, const struct ifq_ops *newops, void *args) { /* * only switch the ifq_ops on the first ifq on an interface. * * the only ifq_ops we provide priq and hfsc, and hfsc only * works on a single ifq. because the code uses the ifq_ops * on the first ifq (if_snd) to select a queue for an mbuf, * by switching only the first one we change both the algorithm * and force the routing of all new packets to it. */ ifq_attach(&ifp->if_snd, newops, args); } void if_start(struct ifnet *ifp) { KASSERT(ifp->if_qstart == if_qstart_compat); if_qstart_compat(&ifp->if_snd); } void if_qstart_compat(struct ifqueue *ifq) { struct ifnet *ifp = ifq->ifq_if; int s; /* * the stack assumes that an interface can have multiple * transmit rings, but a lot of drivers are still written * so that interfaces and send rings have a 1:1 mapping. * this provides compatibility between the stack and the older * drivers by translating from the only queue they have * (ifp->if_snd) back to the interface and calling if_start. */ KERNEL_LOCK(); s = splnet(); (*ifp->if_start)(ifp); splx(s); KERNEL_UNLOCK(); } int if_enqueue(struct ifnet *ifp, struct mbuf *m) { CLR(m->m_pkthdr.csum_flags, M_TIMESTAMP); #if NPF > 0 if (m->m_pkthdr.pf.delay > 0) return (pf_delay_pkt(m, ifp->if_index)); #endif #if NBRIDGE > 0 if (ifp->if_bridgeidx && (m->m_flags & M_PROTO1) == 0) { int error; error = bridge_enqueue(ifp, m); return (error); } #endif #if NPF > 0 pf_pkt_addr_changed(m); #endif /* NPF > 0 */ return ((*ifp->if_enqueue)(ifp, m)); } int if_enqueue_ifq(struct ifnet *ifp, struct mbuf *m) { struct ifqueue *ifq = &ifp->if_snd; int error; if (ifp->if_nifqs > 1) { unsigned int idx; /* * use the operations on the first ifq to pick which of * the array gets this mbuf. */ idx = ifq_idx(&ifp->if_snd, ifp->if_nifqs, m); ifq = ifp->if_ifqs[idx]; } error = ifq_enqueue(ifq, m); if (error) return (error); ifq_start(ifq); return (0); } void if_input(struct ifnet *ifp, struct mbuf_list *ml) { ifiq_input(&ifp->if_rcv, ml); } int if_input_local(struct ifnet *ifp, struct mbuf *m, sa_family_t af) { int keepflags, keepcksum; uint16_t keepmss; #if NBPFILTER > 0 /* * Only send packets to bpf if they are destined to local * addresses. * * if_input_local() is also called for SIMPLEX interfaces to * duplicate packets for local use. But don't dup them to bpf. */ if (ifp->if_flags & IFF_LOOPBACK) { caddr_t if_bpf = ifp->if_bpf; if (if_bpf) bpf_mtap_af(if_bpf, af, m, BPF_DIRECTION_OUT); } #endif keepflags = m->m_flags & (M_BCAST|M_MCAST); /* * Preserve outgoing checksum flags, in case the packet is * forwarded to another interface. Then the checksum, which * is now incorrect, will be calculated before sending. */ keepcksum = m->m_pkthdr.csum_flags & (M_IPV4_CSUM_OUT | M_TCP_CSUM_OUT | M_UDP_CSUM_OUT | M_ICMP_CSUM_OUT | M_TCP_TSO); keepmss = m->m_pkthdr.ph_mss; m_resethdr(m); m->m_flags |= M_LOOP | keepflags; m->m_pkthdr.csum_flags = keepcksum; m->m_pkthdr.ph_mss = keepmss; m->m_pkthdr.ph_ifidx = ifp->if_index; m->m_pkthdr.ph_rtableid = ifp->if_rdomain; if (ISSET(keepcksum, M_TCP_TSO) && m->m_pkthdr.len > ifp->if_mtu) { if (ifp->if_mtu > 0 && ((af == AF_INET && ISSET(ifp->if_capabilities, IFCAP_TSOv4)) || (af == AF_INET6 && ISSET(ifp->if_capabilities, IFCAP_TSOv6)))) { tcpstat_inc(tcps_inswlro); tcpstat_add(tcps_inpktlro, (m->m_pkthdr.len + ifp->if_mtu - 1) / ifp->if_mtu); } else { tcpstat_inc(tcps_inbadlro); m_freem(m); return (EPROTONOSUPPORT); } } if (ISSET(keepcksum, M_TCP_CSUM_OUT)) m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK; if (ISSET(keepcksum, M_UDP_CSUM_OUT)) m->m_pkthdr.csum_flags |= M_UDP_CSUM_IN_OK; if (ISSET(keepcksum, M_ICMP_CSUM_OUT)) m->m_pkthdr.csum_flags |= M_ICMP_CSUM_IN_OK; /* do not count multicast loopback and simplex interfaces */ if (ISSET(ifp->if_flags, IFF_LOOPBACK)) { counters_pkt(ifp->if_counters, ifc_opackets, ifc_obytes, m->m_pkthdr.len); } switch (af) { case AF_INET: if (ISSET(keepcksum, M_IPV4_CSUM_OUT)) m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK; ipv4_input(ifp, m); break; #ifdef INET6 case AF_INET6: ipv6_input(ifp, m); break; #endif /* INET6 */ #ifdef MPLS case AF_MPLS: mpls_input(ifp, m); break; #endif /* MPLS */ default: printf("%s: can't handle af%d\n", ifp->if_xname, af); m_freem(m); return (EAFNOSUPPORT); } return (0); } int if_output_ml(struct ifnet *ifp, struct mbuf_list *ml, struct sockaddr *dst, struct rtentry *rt) { struct mbuf *m; int error = 0; while ((m = ml_dequeue(ml)) != NULL) { error = ifp->if_output(ifp, m, dst, rt); if (error) break; } if (error) ml_purge(ml); return error; } int if_output_tso(struct ifnet *ifp, struct mbuf **mp, struct sockaddr *dst, struct rtentry *rt, u_int mtu) { uint32_t ifcap; int error; switch (dst->sa_family) { case AF_INET: ifcap = IFCAP_TSOv4; break; #ifdef INET6 case AF_INET6: ifcap = IFCAP_TSOv6; break; #endif default: unhandled_af(dst->sa_family); } /* * Try to send with TSO first. When forwarding LRO may set * maximum segment size in mbuf header. Chop TCP segment * even if it would fit interface MTU to preserve maximum * path MTU. */ error = tcp_if_output_tso(ifp, mp, dst, rt, ifcap, mtu); if (error || *mp == NULL) return error; if ((*mp)->m_pkthdr.len <= mtu) { switch (dst->sa_family) { case AF_INET: in_hdr_cksum_out(*mp, ifp); in_proto_cksum_out(*mp, ifp); break; #ifdef INET6 case AF_INET6: in6_proto_cksum_out(*mp, ifp); break; #endif } error = ifp->if_output(ifp, *mp, dst, rt); *mp = NULL; return error; } /* mp still contains mbuf that has to be fragmented or dropped. */ return 0; } int if_output_mq(struct ifnet *ifp, struct mbuf_queue *mq, unsigned int *total, struct sockaddr *dst, struct rtentry *rt) { struct mbuf_list ml; unsigned int len; int error; mq_delist(mq, &ml); len = ml_len(&ml); error = if_output_ml(ifp, &ml, dst, rt); /* XXXSMP we also discard if other CPU enqueues */ if (mq_len(mq) > 0) { /* mbuf is back in queue. Discard. */ atomic_sub_int(total, len + mq_purge(mq)); } else atomic_sub_int(total, len); return error; } int if_output_local(struct ifnet *ifp, struct mbuf *m, sa_family_t af) { struct ifiqueue *ifiq; unsigned int flow = 0; m->m_pkthdr.ph_family = af; m->m_pkthdr.ph_ifidx = ifp->if_index; m->m_pkthdr.ph_rtableid = ifp->if_rdomain; if (ISSET(m->m_pkthdr.csum_flags, M_FLOWID)) flow = m->m_pkthdr.ph_flowid; ifiq = ifp->if_iqs[flow % ifp->if_niqs]; return (ifiq_enqueue(ifiq, m) == 0 ? 0 : ENOBUFS); } void if_input_process(struct ifnet *ifp, struct mbuf_list *ml) { struct mbuf *m; if (ml_empty(ml)) return; if (!ISSET(ifp->if_xflags, IFXF_CLONED)) enqueue_randomness(ml_len(ml) ^ (uintptr_t)MBUF_LIST_FIRST(ml)); /* * We grab the shared netlock for packet processing in the softnet * threads. Packets can regrab the exclusive lock via queues. * ioctl, sysctl, and socket syscall may use shared lock if access is * read only or MP safe. Usually they hold the exclusive net lock. */ NET_LOCK_SHARED(); while ((m = ml_dequeue(ml)) != NULL) (*ifp->if_input)(ifp, m); NET_UNLOCK_SHARED(); } void if_vinput(struct ifnet *ifp, struct mbuf *m) { #if NBPFILTER > 0 caddr_t if_bpf; #endif m->m_pkthdr.ph_ifidx = ifp->if_index; m->m_pkthdr.ph_rtableid = ifp->if_rdomain; counters_pkt(ifp->if_counters, ifc_ipackets, ifc_ibytes, m->m_pkthdr.len); #if NPF > 0 pf_pkt_addr_changed(m); #endif #if NBPFILTER > 0 if_bpf = ifp->if_bpf; if (if_bpf) { if ((*ifp->if_bpf_mtap)(if_bpf, m, BPF_DIRECTION_IN)) { m_freem(m); return; } } #endif if (__predict_true(!ISSET(ifp->if_xflags, IFXF_MONITOR))) (*ifp->if_input)(ifp, m); else m_freem(m); } void if_netisr(void *unused) { int n, t = 0; NET_LOCK(); while ((n = netisr) != 0) { /* Like sched_pause() but with a rwlock dance. */ if (curcpu()->ci_schedstate.spc_schedflags & SPCF_SHOULDYIELD) { NET_UNLOCK(); yield(); NET_LOCK(); } atomic_clearbits_int(&netisr, n); #if NETHER > 0 if (n & (1 << NETISR_ARP)) arpintr(); #endif if (n & (1 << NETISR_IP)) ipintr(); #ifdef INET6 if (n & (1 << NETISR_IPV6)) ip6intr(); #endif #if NPPP > 0 if (n & (1 << NETISR_PPP)) { KERNEL_LOCK(); pppintr(); KERNEL_UNLOCK(); } #endif #if NBRIDGE > 0 if (n & (1 << NETISR_BRIDGE)) bridgeintr(); #endif #ifdef PIPEX if (n & (1 << NETISR_PIPEX)) pipexintr(); #endif #if NPPPOE > 0 if (n & (1 << NETISR_PPPOE)) { KERNEL_LOCK(); pppoeintr(); KERNEL_UNLOCK(); } #endif t |= n; } NET_UNLOCK(); } void if_hooks_run(struct task_list *hooks) { struct task *t, *nt; struct task cursor = { .t_func = NULL }; void (*func)(void *); void *arg; mtx_enter(&if_hooks_mtx); for (t = TAILQ_FIRST(hooks); t != NULL; t = nt) { if (t->t_func == NULL) { /* skip cursors */ nt = TAILQ_NEXT(t, t_entry); continue; } func = t->t_func; arg = t->t_arg; TAILQ_INSERT_AFTER(hooks, t, &cursor, t_entry); mtx_leave(&if_hooks_mtx); (*func)(arg); mtx_enter(&if_hooks_mtx); nt = TAILQ_NEXT(&cursor, t_entry); /* avoid _Q_INVALIDATE */ TAILQ_REMOVE(hooks, &cursor, t_entry); } mtx_leave(&if_hooks_mtx); } void if_remove(struct ifnet *ifp) { /* Remove the interface from the list of all interfaces. */ NET_LOCK(); TAILQ_REMOVE(&ifnetlist, ifp, if_list); NET_UNLOCK(); /* Remove the interface from the interface index map. */ if_idxmap_remove(ifp); /* Sleep until the last reference is released. */ refcnt_finalize(&ifp->if_refcnt, "ifrm"); } void if_deactivate(struct ifnet *ifp) { /* * Call detach hooks from head to tail. To make sure detach * hooks are executed in the reverse order they were added, all * the hooks have to be added to the head! */ NET_LOCK(); if_hooks_run(&ifp->if_detachhooks); NET_UNLOCK(); } void if_detachhook_add(struct ifnet *ifp, struct task *t) { mtx_enter(&if_hooks_mtx); TAILQ_INSERT_HEAD(&ifp->if_detachhooks, t, t_entry); mtx_leave(&if_hooks_mtx); } void if_detachhook_del(struct ifnet *ifp, struct task *t) { mtx_enter(&if_hooks_mtx); TAILQ_REMOVE(&ifp->if_detachhooks, t, t_entry); mtx_leave(&if_hooks_mtx); } /* * Detach an interface from everything in the kernel. Also deallocate * private resources. */ void if_detach(struct ifnet *ifp) { struct ifaddr *ifa; struct ifg_list *ifg; int i, s; /* Undo pseudo-driver changes. */ if_deactivate(ifp); /* Other CPUs must not have a reference before we start destroying. */ if_remove(ifp); ifp->if_qstart = if_detached_qstart; /* Wait until the start routines finished. */ ifq_barrier(&ifp->if_snd); ifq_clr_oactive(&ifp->if_snd); #if NBPFILTER > 0 bpfdetach(ifp); #endif NET_LOCK(); s = splnet(); ifp->if_ioctl = if_detached_ioctl; ifp->if_watchdog = NULL; /* Remove the watchdog timeout & task */ timeout_del(&ifp->if_slowtimo); task_del(net_tq(ifp->if_index), &ifp->if_watchdogtask); /* Remove the link state task */ task_del(net_tq(ifp->if_index), &ifp->if_linkstatetask); rti_delete(ifp); #if NETHER > 0 && defined(NFSCLIENT) if (ifp->if_index == revarp_ifidx) revarp_ifidx = 0; #endif #ifdef MROUTING vif_delete(ifp); #endif in_ifdetach(ifp); #ifdef INET6 in6_ifdetach(ifp); #endif #if NPF > 0 pfi_detach_ifnet(ifp); #endif while ((ifg = TAILQ_FIRST(&ifp->if_groups)) != NULL) if_delgroup(ifp, ifg->ifgl_group->ifg_group); if_free_sadl(ifp); /* We should not have any address left at this point. */ if (!TAILQ_EMPTY(&ifp->if_addrlist)) { #ifdef DIAGNOSTIC printf("%s: address list non empty\n", ifp->if_xname); #endif while ((ifa = TAILQ_FIRST(&ifp->if_addrlist)) != NULL) { ifa_del(ifp, ifa); ifa->ifa_ifp = NULL; ifafree(ifa); } } splx(s); NET_UNLOCK(); KASSERT(TAILQ_EMPTY(&ifp->if_addrhooks)); KASSERT(TAILQ_EMPTY(&ifp->if_linkstatehooks)); KASSERT(TAILQ_EMPTY(&ifp->if_detachhooks)); #ifdef INET6 nd6_ifdetach(ifp); #endif /* Announce that the interface is gone. */ rtm_ifannounce(ifp, IFAN_DEPARTURE); if (ifp->if_counters != NULL) if_counters_free(ifp); for (i = 0; i < ifp->if_nifqs; i++) ifq_destroy(ifp->if_ifqs[i]); if (ifp->if_ifqs != ifp->if_snd.ifq_ifqs) { for (i = 1; i < ifp->if_nifqs; i++) { free(ifp->if_ifqs[i], M_DEVBUF, sizeof(struct ifqueue)); } free(ifp->if_ifqs, M_DEVBUF, sizeof(struct ifqueue *) * ifp->if_nifqs); } for (i = 0; i < ifp->if_niqs; i++) ifiq_destroy(ifp->if_iqs[i]); if (ifp->if_iqs != ifp->if_rcv.ifiq_ifiqs) { for (i = 1; i < ifp->if_niqs; i++) { free(ifp->if_iqs[i], M_DEVBUF, sizeof(struct ifiqueue)); } free(ifp->if_iqs, M_DEVBUF, sizeof(struct ifiqueue *) * ifp->if_niqs); } } /* * Returns true if ``ifp0'' is connected to the interface with index ``ifidx''. */ int if_isconnected(const struct ifnet *ifp0, unsigned int ifidx) { struct ifnet *ifp; int connected = 0; ifp = if_get(ifidx); if (ifp == NULL) return (0); if (ifp0->if_index == ifp->if_index) connected = 1; #if NBRIDGE > 0 if (ifp0->if_bridgeidx != 0 && ifp0->if_bridgeidx == ifp->if_bridgeidx) connected = 1; #endif #if NCARP > 0 if ((ifp0->if_type == IFT_CARP && ifp0->if_carpdevidx == ifp->if_index) || (ifp->if_type == IFT_CARP && ifp->if_carpdevidx == ifp0->if_index)) connected = 1; #endif if_put(ifp); return (connected); } /* * Create a clone network interface. */ int if_clone_create(const char *name, int rdomain) { struct if_clone *ifc; struct ifnet *ifp; int unit, ret; ifc = if_clone_lookup(name, &unit); if (ifc == NULL) return (EINVAL); rw_enter_write(&if_cloners_lock); if ((ifp = if_unit(name)) != NULL) { ret = EEXIST; goto unlock; } ret = (*ifc->ifc_create)(ifc, unit); if (ret != 0 || (ifp = if_unit(name)) == NULL) goto unlock; NET_LOCK(); if_addgroup(ifp, ifc->ifc_name); if (rdomain != 0) if_setrdomain(ifp, rdomain); NET_UNLOCK(); unlock: rw_exit_write(&if_cloners_lock); if_put(ifp); return (ret); } /* * Destroy a clone network interface. */ int if_clone_destroy(const char *name) { struct if_clone *ifc; struct ifnet *ifp; int ret; ifc = if_clone_lookup(name, NULL); if (ifc == NULL) return (EINVAL); if (ifc->ifc_destroy == NULL) return (EOPNOTSUPP); rw_enter_write(&if_cloners_lock); TAILQ_FOREACH(ifp, &ifnetlist, if_list) { if (strcmp(ifp->if_xname, name) == 0) break; } if (ifp == NULL) { rw_exit_write(&if_cloners_lock); return (ENXIO); } NET_LOCK(); if (ifp->if_flags & IFF_UP) { int s; s = splnet(); if_down(ifp); splx(s); } NET_UNLOCK(); ret = (*ifc->ifc_destroy)(ifp); rw_exit_write(&if_cloners_lock); return (ret); } /* * Look up a network interface cloner. */ struct if_clone * if_clone_lookup(const char *name, int *unitp) { struct if_clone *ifc; const char *cp; int unit; /* separate interface name from unit */ for (cp = name; cp - name < IFNAMSIZ && *cp && (*cp < '0' || *cp > '9'); cp++) continue; if (cp == name || cp - name == IFNAMSIZ || !*cp) return (NULL); /* No name or unit number */ if (cp - name < IFNAMSIZ-1 && *cp == '0' && cp[1] != '\0') return (NULL); /* unit number 0 padded */ LIST_FOREACH(ifc, &if_cloners, ifc_list) { if (strlen(ifc->ifc_name) == cp - name && !strncmp(name, ifc->ifc_name, cp - name)) break; } if (ifc == NULL) return (NULL); unit = 0; while (cp - name < IFNAMSIZ && *cp) { if (*cp < '0' || *cp > '9' || unit > (INT_MAX - (*cp - '0')) / 10) { /* Bogus unit number. */ return (NULL); } unit = (unit * 10) + (*cp++ - '0'); } if (unitp != NULL) *unitp = unit; return (ifc); } /* * Register a network interface cloner. */ void if_clone_attach(struct if_clone *ifc) { /* * we are called at kernel boot by main(), when pseudo devices are * being attached. The main() is the only guy which may alter the * if_cloners. While system is running and main() is done with * initialization, the if_cloners becomes immutable. */ KASSERT(pdevinit_done == 0); LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list); if_cloners_count++; } /* * Provide list of interface cloners to userspace. */ int if_clone_list(struct if_clonereq *ifcr) { char outbuf[IFNAMSIZ], *dst; struct if_clone *ifc; int count, error = 0; if ((dst = ifcr->ifcr_buffer) == NULL) { /* Just asking how many there are. */ ifcr->ifcr_total = if_cloners_count; return (0); } if (ifcr->ifcr_count < 0) return (EINVAL); ifcr->ifcr_total = if_cloners_count; count = MIN(if_cloners_count, ifcr->ifcr_count); LIST_FOREACH(ifc, &if_cloners, ifc_list) { if (count == 0) break; bzero(outbuf, sizeof outbuf); strlcpy(outbuf, ifc->ifc_name, IFNAMSIZ); error = copyout(outbuf, dst, IFNAMSIZ); if (error) break; count--; dst += IFNAMSIZ; } return (error); } /* * set queue congestion marker */ void if_congestion(void) { extern int ticks; ifq_congestion = ticks; } int if_congested(void) { extern int ticks; int diff; diff = ticks - ifq_congestion; if (diff < 0) { ifq_congestion = ticks - hz; return (0); } return (diff <= (hz / 100)); } #define equal(a1, a2) \ (bcmp((caddr_t)(a1), (caddr_t)(a2), \ (a1)->sa_len) == 0) /* * Locate an interface based on a complete address. */ struct ifaddr * ifa_ifwithaddr(const struct sockaddr *addr, u_int rtableid) { struct ifnet *ifp; struct ifaddr *ifa; u_int rdomain; NET_ASSERT_LOCKED(); rdomain = rtable_l2(rtableid); TAILQ_FOREACH(ifp, &ifnetlist, if_list) { if (ifp->if_rdomain != rdomain) continue; TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != addr->sa_family) continue; if (equal(addr, ifa->ifa_addr)) { return (ifa); } } } return (NULL); } /* * Locate the point to point interface with a given destination address. */ struct ifaddr * ifa_ifwithdstaddr(const struct sockaddr *addr, u_int rdomain) { struct ifnet *ifp; struct ifaddr *ifa; NET_ASSERT_LOCKED(); rdomain = rtable_l2(rdomain); TAILQ_FOREACH(ifp, &ifnetlist, if_list) { if (ifp->if_rdomain != rdomain) continue; if (ifp->if_flags & IFF_POINTOPOINT) { TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != addr->sa_family || ifa->ifa_dstaddr == NULL) continue; if (equal(addr, ifa->ifa_dstaddr)) { return (ifa); } } } } return (NULL); } /* * Find an interface address specific to an interface best matching * a given address. */ struct ifaddr * ifaof_ifpforaddr(const struct sockaddr *addr, struct ifnet *ifp) { struct ifaddr *ifa; const char *cp, *cp2, *cp3; char *cplim; struct ifaddr *ifa_maybe = NULL; u_int af = addr->sa_family; if (af >= AF_MAX) return (NULL); TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != af) continue; if (ifa_maybe == NULL) ifa_maybe = ifa; if (ifa->ifa_netmask == 0 || ifp->if_flags & IFF_POINTOPOINT) { if (equal(addr, ifa->ifa_addr) || (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))) return (ifa); continue; } cp = addr->sa_data; cp2 = ifa->ifa_addr->sa_data; cp3 = ifa->ifa_netmask->sa_data; cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; for (; cp3 < cplim; cp3++) if ((*cp++ ^ *cp2++) & *cp3) break; if (cp3 == cplim) return (ifa); } return (ifa_maybe); } void if_rtrequest_dummy(struct ifnet *ifp, int req, struct rtentry *rt) { } /* * Default action when installing a local route on a point-to-point * interface. */ void p2p_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt) { struct ifnet *lo0ifp; struct ifaddr *ifa, *lo0ifa; switch (req) { case RTM_ADD: if (!ISSET(rt->rt_flags, RTF_LOCAL)) break; TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (memcmp(rt_key(rt), ifa->ifa_addr, rt_key(rt)->sa_len) == 0) break; } if (ifa == NULL) break; KASSERT(ifa == rt->rt_ifa); lo0ifp = if_get(rtable_loindex(ifp->if_rdomain)); KASSERT(lo0ifp != NULL); TAILQ_FOREACH(lo0ifa, &lo0ifp->if_addrlist, ifa_list) { if (lo0ifa->ifa_addr->sa_family == ifa->ifa_addr->sa_family) break; } if_put(lo0ifp); if (lo0ifa == NULL) break; rt->rt_flags &= ~RTF_LLINFO; break; case RTM_DELETE: case RTM_RESOLVE: default: break; } } int p2p_bpf_mtap(caddr_t if_bpf, const struct mbuf *m, u_int dir) { #if NBPFILTER > 0 return (bpf_mtap_af(if_bpf, m->m_pkthdr.ph_family, m, dir)); #else return (0); #endif } void p2p_input(struct ifnet *ifp, struct mbuf *m) { void (*input)(struct ifnet *, struct mbuf *); switch (m->m_pkthdr.ph_family) { case AF_INET: input = ipv4_input; break; #ifdef INET6 case AF_INET6: input = ipv6_input; break; #endif #ifdef MPLS case AF_MPLS: input = mpls_input; break; #endif default: m_freem(m); return; } (*input)(ifp, m); } /* * Bring down all interfaces */ void if_downall(void) { struct ifreq ifrq; /* XXX only partly built */ struct ifnet *ifp; NET_LOCK(); TAILQ_FOREACH(ifp, &ifnetlist, if_list) { if ((ifp->if_flags & IFF_UP) == 0) continue; if_down(ifp); ifrq.ifr_flags = ifp->if_flags; (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq); } NET_UNLOCK(); } /* * Mark an interface down and notify protocols of * the transition. */ void if_down(struct ifnet *ifp) { NET_ASSERT_LOCKED(); ifp->if_flags &= ~IFF_UP; getmicrotime(&ifp->if_lastchange); ifq_purge(&ifp->if_snd); if_linkstate(ifp); } /* * Mark an interface up and notify protocols of * the transition. */ void if_up(struct ifnet *ifp) { NET_ASSERT_LOCKED(); ifp->if_flags |= IFF_UP; getmicrotime(&ifp->if_lastchange); #ifdef INET6 /* Userland expects the kernel to set ::1 on default lo(4). */ if (ifp->if_index == rtable_loindex(ifp->if_rdomain)) in6_ifattach(ifp); #endif if_linkstate(ifp); } /* * Notify userland, the routing table and hooks owner of * a link-state transition. */ void if_linkstate_task(void *xifidx) { unsigned int ifidx = (unsigned long)xifidx; struct ifnet *ifp; NET_LOCK(); KERNEL_LOCK(); ifp = if_get(ifidx); if (ifp != NULL) if_linkstate(ifp); if_put(ifp); KERNEL_UNLOCK(); NET_UNLOCK(); } void if_linkstate(struct ifnet *ifp) { NET_ASSERT_LOCKED(); if (panicstr == NULL) { rtm_ifchg(ifp); rt_if_track(ifp); } if_hooks_run(&ifp->if_linkstatehooks); } void if_linkstatehook_add(struct ifnet *ifp, struct task *t) { mtx_enter(&if_hooks_mtx); TAILQ_INSERT_HEAD(&ifp->if_linkstatehooks, t, t_entry); mtx_leave(&if_hooks_mtx); } void if_linkstatehook_del(struct ifnet *ifp, struct task *t) { mtx_enter(&if_hooks_mtx); TAILQ_REMOVE(&ifp->if_linkstatehooks, t, t_entry); mtx_leave(&if_hooks_mtx); } /* * Schedule a link state change task. */ void if_link_state_change(struct ifnet *ifp) { task_add(net_tq(ifp->if_index), &ifp->if_linkstatetask); } /* * Handle interface watchdog timer routine. Called * from softclock, we decrement timer (if set) and * call the appropriate interface routine on expiration. */ void if_slowtimo(void *arg) { struct ifnet *ifp = arg; int s = splnet(); if (ifp->if_watchdog) { if (ifp->if_timer > 0 && --ifp->if_timer == 0) task_add(net_tq(ifp->if_index), &ifp->if_watchdogtask); timeout_add_sec(&ifp->if_slowtimo, IFNET_SLOWTIMO); } splx(s); } void if_watchdog_task(void *xifidx) { unsigned int ifidx = (unsigned long)xifidx; struct ifnet *ifp; int s; ifp = if_get(ifidx); if (ifp == NULL) return; KERNEL_LOCK(); s = splnet(); if (ifp->if_watchdog) (*ifp->if_watchdog)(ifp); splx(s); KERNEL_UNLOCK(); if_put(ifp); } /* * Map interface name to interface structure pointer. */ struct ifnet * if_unit(const char *name) { struct ifnet *ifp; KERNEL_ASSERT_LOCKED(); TAILQ_FOREACH(ifp, &ifnetlist, if_list) { if (strcmp(ifp->if_xname, name) == 0) { if_ref(ifp); return (ifp); } } return (NULL); } /* * Map interface index to interface structure pointer. */ struct ifnet * if_get(unsigned int index) { struct ifnet **if_map; struct ifnet *ifp = NULL; if (index == 0) return (NULL); smr_read_enter(); if_map = SMR_PTR_GET(&if_idxmap.map); if (index < if_idxmap_limit(if_map)) { ifp = SMR_PTR_GET(&if_map[index]); if (ifp != NULL) { KASSERT(ifp->if_index == index); if_ref(ifp); } } smr_read_leave(); return (ifp); } struct ifnet * if_ref(struct ifnet *ifp) { refcnt_take(&ifp->if_refcnt); return (ifp); } void if_put(struct ifnet *ifp) { if (ifp == NULL) return; refcnt_rele_wake(&ifp->if_refcnt); } int if_setlladdr(struct ifnet *ifp, const uint8_t *lladdr) { if (ifp->if_sadl == NULL) return (EINVAL); memcpy(((struct arpcom *)ifp)->ac_enaddr, lladdr, ETHER_ADDR_LEN); memcpy(LLADDR(ifp->if_sadl), lladdr, ETHER_ADDR_LEN); return (0); } int if_createrdomain(int rdomain, struct ifnet *ifp) { int error; struct ifnet *loifp; char loifname[IFNAMSIZ]; unsigned int unit = rdomain; if ((error = rtable_add(rdomain)) != 0) return (error); if (!rtable_empty(rdomain)) return (EEXIST); /* Create rdomain including its loopback if with unit == rdomain */ snprintf(loifname, sizeof(loifname), "lo%u", unit); error = if_clone_create(loifname, 0); if ((loifp = if_unit(loifname)) == NULL) return (ENXIO); if (error && (ifp != loifp || error != EEXIST)) { if_put(loifp); return (error); } rtable_l2set(rdomain, rdomain, loifp->if_index); loifp->if_rdomain = rdomain; if_put(loifp); return (0); } int if_setrdomain(struct ifnet *ifp, int rdomain) { struct ifreq ifr; int error, up = 0, s; if (rdomain < 0 || rdomain > RT_TABLEID_MAX) return (EINVAL); if (rdomain != ifp->if_rdomain && (ifp->if_flags & IFF_LOOPBACK) && (ifp->if_index == rtable_loindex(ifp->if_rdomain))) return (EPERM); if (!rtable_exists(rdomain)) return (ESRCH); /* make sure that the routing table is a real rdomain */ if (rdomain != rtable_l2(rdomain)) return (EINVAL); if (rdomain != ifp->if_rdomain) { s = splnet(); /* * We are tearing down the world. * Take down the IF so: * 1. everything that cares gets a message * 2. the automagic IPv6 bits are recreated */ if (ifp->if_flags & IFF_UP) { up = 1; if_down(ifp); } rti_delete(ifp); #ifdef MROUTING vif_delete(ifp); #endif in_ifdetach(ifp); #ifdef INET6 in6_ifdetach(ifp); #endif splx(s); } /* Let devices like enc(4) or mpe(4) know about the change */ ifr.ifr_rdomainid = rdomain; if ((error = (*ifp->if_ioctl)(ifp, SIOCSIFRDOMAIN, (caddr_t)&ifr)) != ENOTTY) return (error); error = 0; /* Add interface to the specified rdomain */ ifp->if_rdomain = rdomain; /* If we took down the IF, bring it back */ if (up) { s = splnet(); if_up(ifp); splx(s); } return (0); } /* * Interface ioctls. */ int ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p) { struct ifnet *ifp; struct ifreq *ifr = (struct ifreq *)data; struct ifgroupreq *ifgr = (struct ifgroupreq *)data; struct if_afreq *ifar = (struct if_afreq *)data; char ifdescrbuf[IFDESCRSIZE]; char ifrtlabelbuf[RTLABEL_LEN]; int s, error = 0, oif_xflags; size_t bytesdone; unsigned short oif_flags; switch (cmd) { case SIOCIFCREATE: if ((error = suser(p)) != 0) return (error); KERNEL_LOCK(); error = if_clone_create(ifr->ifr_name, 0); KERNEL_UNLOCK(); return (error); case SIOCIFDESTROY: if ((error = suser(p)) != 0) return (error); KERNEL_LOCK(); error = if_clone_destroy(ifr->ifr_name); KERNEL_UNLOCK(); return (error); case SIOCSIFGATTR: if ((error = suser(p)) != 0) return (error); KERNEL_LOCK(); NET_LOCK(); error = if_setgroupattribs(data); NET_UNLOCK(); KERNEL_UNLOCK(); return (error); case SIOCGIFCONF: case SIOCIFGCLONERS: case SIOCGIFGMEMB: case SIOCGIFGATTR: case SIOCGIFGLIST: case SIOCGIFFLAGS: case SIOCGIFXFLAGS: case SIOCGIFMETRIC: case SIOCGIFMTU: case SIOCGIFHARDMTU: case SIOCGIFDATA: case SIOCGIFDESCR: case SIOCGIFRTLABEL: case SIOCGIFPRIORITY: case SIOCGIFRDOMAIN: case SIOCGIFGROUP: case SIOCGIFLLPRIO: error = ifioctl_get(cmd, data); return (error); } KERNEL_LOCK(); ifp = if_unit(ifr->ifr_name); if (ifp == NULL) { KERNEL_UNLOCK(); return (ENXIO); } oif_flags = ifp->if_flags; oif_xflags = ifp->if_xflags; switch (cmd) { case SIOCIFAFATTACH: case SIOCIFAFDETACH: if ((error = suser(p)) != 0) break; NET_LOCK(); switch (ifar->ifar_af) { case AF_INET: /* attach is a noop for AF_INET */ if (cmd == SIOCIFAFDETACH) in_ifdetach(ifp); break; #ifdef INET6 case AF_INET6: if (cmd == SIOCIFAFATTACH) error = in6_ifattach(ifp); else in6_ifdetach(ifp); break; #endif /* INET6 */ default: error = EAFNOSUPPORT; } NET_UNLOCK(); break; case SIOCSIFXFLAGS: if ((error = suser(p)) != 0) break; NET_LOCK(); #ifdef INET6 if ((ISSET(ifr->ifr_flags, IFXF_AUTOCONF6) || ISSET(ifr->ifr_flags, IFXF_AUTOCONF6TEMP)) && !ISSET(ifp->if_xflags, IFXF_AUTOCONF6) && !ISSET(ifp->if_xflags, IFXF_AUTOCONF6TEMP)) { error = in6_ifattach(ifp); if (error != 0) { NET_UNLOCK(); break; } } if (ISSET(ifr->ifr_flags, IFXF_INET6_NOSOII) && !ISSET(ifp->if_xflags, IFXF_INET6_NOSOII)) ifp->if_xflags |= IFXF_INET6_NOSOII; if (!ISSET(ifr->ifr_flags, IFXF_INET6_NOSOII) && ISSET(ifp->if_xflags, IFXF_INET6_NOSOII)) ifp->if_xflags &= ~IFXF_INET6_NOSOII; #endif /* INET6 */ #ifdef MPLS if (ISSET(ifr->ifr_flags, IFXF_MPLS) && !ISSET(ifp->if_xflags, IFXF_MPLS)) { s = splnet(); ifp->if_xflags |= IFXF_MPLS; ifp->if_ll_output = ifp->if_output; ifp->if_output = mpls_output; splx(s); } if (ISSET(ifp->if_xflags, IFXF_MPLS) && !ISSET(ifr->ifr_flags, IFXF_MPLS)) { s = splnet(); ifp->if_xflags &= ~IFXF_MPLS; ifp->if_output = ifp->if_ll_output; ifp->if_ll_output = NULL; splx(s); } #endif /* MPLS */ #ifndef SMALL_KERNEL if (ifp->if_capabilities & IFCAP_WOL) { if (ISSET(ifr->ifr_flags, IFXF_WOL) && !ISSET(ifp->if_xflags, IFXF_WOL)) { s = splnet(); ifp->if_xflags |= IFXF_WOL; error = ifp->if_wol(ifp, 1); splx(s); } if (ISSET(ifp->if_xflags, IFXF_WOL) && !ISSET(ifr->ifr_flags, IFXF_WOL)) { s = splnet(); ifp->if_xflags &= ~IFXF_WOL; error = ifp->if_wol(ifp, 0); splx(s); } } else if (ISSET(ifr->ifr_flags, IFXF_WOL)) { ifr->ifr_flags &= ~IFXF_WOL; error = ENOTSUP; } #endif if (ISSET(ifr->ifr_flags, IFXF_LRO) != ISSET(ifp->if_xflags, IFXF_LRO)) error = ifsetlro(ifp, ISSET(ifr->ifr_flags, IFXF_LRO)); if (error == 0) ifp->if_xflags = (ifp->if_xflags & IFXF_CANTCHANGE) | (ifr->ifr_flags & ~IFXF_CANTCHANGE); if (!ISSET(ifp->if_flags, IFF_UP) && ((!ISSET(oif_xflags, IFXF_AUTOCONF4) && ISSET(ifp->if_xflags, IFXF_AUTOCONF4)) || (!ISSET(oif_xflags, IFXF_AUTOCONF6) && ISSET(ifp->if_xflags, IFXF_AUTOCONF6)) || (!ISSET(oif_xflags, IFXF_AUTOCONF6TEMP) && ISSET(ifp->if_xflags, IFXF_AUTOCONF6TEMP)))) { ifr->ifr_flags = ifp->if_flags | IFF_UP; goto forceup; } NET_UNLOCK(); break; case SIOCSIFFLAGS: if ((error = suser(p)) != 0) break; NET_LOCK(); forceup: ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | (ifr->ifr_flags & ~IFF_CANTCHANGE); error = (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, data); if (error != 0) { ifp->if_flags = oif_flags; if (cmd == SIOCSIFXFLAGS) ifp->if_xflags = oif_xflags; } else if (ISSET(oif_flags ^ ifp->if_flags, IFF_UP)) { s = splnet(); if (ISSET(ifp->if_flags, IFF_UP)) if_up(ifp); else if_down(ifp); splx(s); } NET_UNLOCK(); break; case SIOCSIFMETRIC: if ((error = suser(p)) != 0) break; NET_LOCK(); ifp->if_metric = ifr->ifr_metric; NET_UNLOCK(); break; case SIOCSIFMTU: if ((error = suser(p)) != 0) break; NET_LOCK(); error = (*ifp->if_ioctl)(ifp, cmd, data); NET_UNLOCK(); if (error == 0) rtm_ifchg(ifp); break; case SIOCSIFDESCR: if ((error = suser(p)) != 0) break; error = copyinstr(ifr->ifr_data, ifdescrbuf, IFDESCRSIZE, &bytesdone); if (error == 0) { (void)memset(ifp->if_description, 0, IFDESCRSIZE); strlcpy(ifp->if_description, ifdescrbuf, IFDESCRSIZE); } break; case SIOCSIFRTLABEL: if ((error = suser(p)) != 0) break; error = copyinstr(ifr->ifr_data, ifrtlabelbuf, RTLABEL_LEN, &bytesdone); if (error == 0) { rtlabel_unref(ifp->if_rtlabelid); ifp->if_rtlabelid = rtlabel_name2id(ifrtlabelbuf); } break; case SIOCSIFPRIORITY: if ((error = suser(p)) != 0) break; if (ifr->ifr_metric < 0 || ifr->ifr_metric > 15) { error = EINVAL; break; } ifp->if_priority = ifr->ifr_metric; break; case SIOCSIFRDOMAIN: if ((error = suser(p)) != 0) break; error = if_createrdomain(ifr->ifr_rdomainid, ifp); if (!error || error == EEXIST) { NET_LOCK(); error = if_setrdomain(ifp, ifr->ifr_rdomainid); NET_UNLOCK(); } break; case SIOCAIFGROUP: if ((error = suser(p))) break; NET_LOCK(); error = if_addgroup(ifp, ifgr->ifgr_group); if (error == 0) { error = (*ifp->if_ioctl)(ifp, cmd, data); if (error == ENOTTY) error = 0; } NET_UNLOCK(); break; case SIOCDIFGROUP: if ((error = suser(p))) break; NET_LOCK(); error = (*ifp->if_ioctl)(ifp, cmd, data); if (error == ENOTTY) error = 0; if (error == 0) error = if_delgroup(ifp, ifgr->ifgr_group); NET_UNLOCK(); break; case SIOCSIFLLADDR: if ((error = suser(p))) break; if ((ifp->if_sadl == NULL) || (ifr->ifr_addr.sa_len != ETHER_ADDR_LEN) || (ETHER_IS_MULTICAST(ifr->ifr_addr.sa_data))) { error = EINVAL; break; } NET_LOCK(); switch (ifp->if_type) { case IFT_ETHER: case IFT_CARP: case IFT_XETHER: case IFT_ISO88025: error = (*ifp->if_ioctl)(ifp, cmd, data); if (error == ENOTTY) error = 0; if (error == 0) error = if_setlladdr(ifp, ifr->ifr_addr.sa_data); break; default: error = ENODEV; } if (error == 0) ifnewlladdr(ifp); NET_UNLOCK(); if (error == 0) rtm_ifchg(ifp); break; case SIOCSIFLLPRIO: if ((error = suser(p))) break; if (ifr->ifr_llprio < IFQ_MINPRIO || ifr->ifr_llprio > IFQ_MAXPRIO) { error = EINVAL; break; } NET_LOCK(); ifp->if_llprio = ifr->ifr_llprio; NET_UNLOCK(); break; case SIOCGIFSFFPAGE: error = suser(p); if (error != 0) break; error = if_sffpage_check(data); if (error != 0) break; /* don't take NET_LOCK because i2c reads take a long time */ error = ((*ifp->if_ioctl)(ifp, cmd, data)); break; case SIOCSIFMEDIA: if ((error = suser(p)) != 0) break; /* FALLTHROUGH */ case SIOCGIFMEDIA: /* net lock is not needed */ error = ((*ifp->if_ioctl)(ifp, cmd, data)); break; case SIOCSETKALIVE: case SIOCDIFPHYADDR: case SIOCSLIFPHYADDR: case SIOCSLIFPHYRTABLE: case SIOCSLIFPHYTTL: case SIOCSLIFPHYDF: case SIOCSLIFPHYECN: case SIOCADDMULTI: case SIOCDELMULTI: case SIOCSVNETID: case SIOCDVNETID: case SIOCSVNETFLOWID: case SIOCSTXHPRIO: case SIOCSRXHPRIO: case SIOCSIFPAIR: case SIOCSIFPARENT: case SIOCDIFPARENT: case SIOCSETMPWCFG: case SIOCSETLABEL: case SIOCDELLABEL: case SIOCSPWE3CTRLWORD: case SIOCSPWE3FAT: case SIOCSPWE3NEIGHBOR: case SIOCDPWE3NEIGHBOR: #if NBRIDGE > 0 case SIOCBRDGADD: case SIOCBRDGDEL: case SIOCBRDGSIFFLGS: case SIOCBRDGSCACHE: case SIOCBRDGADDS: case SIOCBRDGDELS: case SIOCBRDGSADDR: case SIOCBRDGSTO: case SIOCBRDGDADDR: case SIOCBRDGFLUSH: case SIOCBRDGADDL: case SIOCBRDGSIFPROT: case SIOCBRDGARL: case SIOCBRDGFRL: case SIOCBRDGSPRI: case SIOCBRDGSHT: case SIOCBRDGSFD: case SIOCBRDGSMA: case SIOCBRDGSIFPRIO: case SIOCBRDGSIFCOST: case SIOCBRDGSTXHC: case SIOCBRDGSPROTO: #endif if ((error = suser(p)) != 0) break; /* FALLTHROUGH */ default: error = pru_control(so, cmd, data, ifp); if (error != EOPNOTSUPP) break; switch (cmd) { case SIOCAIFADDR: case SIOCDIFADDR: case SIOCSIFADDR: case SIOCSIFNETMASK: case SIOCSIFDSTADDR: case SIOCSIFBRDADDR: #ifdef INET6 case SIOCAIFADDR_IN6: case SIOCDIFADDR_IN6: #endif error = suser(p); break; default: error = 0; break; } if (error) break; NET_LOCK(); error = ((*ifp->if_ioctl)(ifp, cmd, data)); NET_UNLOCK(); break; } if (oif_flags != ifp->if_flags || oif_xflags != ifp->if_xflags) { /* if_up() and if_down() already sent an update, skip here */ if (((oif_flags ^ ifp->if_flags) & IFF_UP) == 0) rtm_ifchg(ifp); } if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0) getmicrotime(&ifp->if_lastchange); KERNEL_UNLOCK(); if_put(ifp); return (error); } int ifioctl_get(u_long cmd, caddr_t data) { struct ifnet *ifp; struct ifreq *ifr = (struct ifreq *)data; char ifdescrbuf[IFDESCRSIZE]; char ifrtlabelbuf[RTLABEL_LEN]; int error = 0; size_t bytesdone; switch(cmd) { case SIOCGIFCONF: NET_LOCK_SHARED(); error = ifconf(data); NET_UNLOCK_SHARED(); return (error); case SIOCIFGCLONERS: error = if_clone_list((struct if_clonereq *)data); return (error); case SIOCGIFGMEMB: NET_LOCK_SHARED(); error = if_getgroupmembers(data); NET_UNLOCK_SHARED(); return (error); case SIOCGIFGATTR: NET_LOCK_SHARED(); error = if_getgroupattribs(data); NET_UNLOCK_SHARED(); return (error); case SIOCGIFGLIST: NET_LOCK_SHARED(); error = if_getgrouplist(data); NET_UNLOCK_SHARED(); return (error); } KERNEL_LOCK(); ifp = if_unit(ifr->ifr_name); if (ifp == NULL) { KERNEL_UNLOCK(); return (ENXIO); } NET_LOCK_SHARED(); switch(cmd) { case SIOCGIFFLAGS: ifr->ifr_flags = ifp->if_flags; if (ifq_is_oactive(&ifp->if_snd)) ifr->ifr_flags |= IFF_OACTIVE; break; case SIOCGIFXFLAGS: ifr->ifr_flags = ifp->if_xflags & ~(IFXF_MPSAFE|IFXF_CLONED); break; case SIOCGIFMETRIC: ifr->ifr_metric = ifp->if_metric; break; case SIOCGIFMTU: ifr->ifr_mtu = ifp->if_mtu; break; case SIOCGIFHARDMTU: ifr->ifr_hardmtu = ifp->if_hardmtu; break; case SIOCGIFDATA: { struct if_data ifdata; if_getdata(ifp, &ifdata); error = copyout(&ifdata, ifr->ifr_data, sizeof(ifdata)); break; } case SIOCGIFDESCR: strlcpy(ifdescrbuf, ifp->if_description, IFDESCRSIZE); error = copyoutstr(ifdescrbuf, ifr->ifr_data, IFDESCRSIZE, &bytesdone); break; case SIOCGIFRTLABEL: if (ifp->if_rtlabelid && rtlabel_id2name(ifp->if_rtlabelid, ifrtlabelbuf, RTLABEL_LEN) != NULL) { error = copyoutstr(ifrtlabelbuf, ifr->ifr_data, RTLABEL_LEN, &bytesdone); } else error = ENOENT; break; case SIOCGIFPRIORITY: ifr->ifr_metric = ifp->if_priority; break; case SIOCGIFRDOMAIN: ifr->ifr_rdomainid = ifp->if_rdomain; break; case SIOCGIFGROUP: error = if_getgroup(data, ifp); break; case SIOCGIFLLPRIO: ifr->ifr_llprio = ifp->if_llprio; break; default: panic("invalid ioctl %lu", cmd); } NET_UNLOCK_SHARED(); KERNEL_UNLOCK(); if_put(ifp); return (error); } static int if_sffpage_check(const caddr_t data) { const struct if_sffpage *sff = (const struct if_sffpage *)data; switch (sff->sff_addr) { case IFSFF_ADDR_EEPROM: case IFSFF_ADDR_DDM: break; default: return (EINVAL); } return (0); } int if_txhprio_l2_check(int hdrprio) { switch (hdrprio) { case IF_HDRPRIO_PACKET: return (0); default: if (hdrprio >= IF_HDRPRIO_MIN && hdrprio <= IF_HDRPRIO_MAX) return (0); break; } return (EINVAL); } int if_txhprio_l3_check(int hdrprio) { switch (hdrprio) { case IF_HDRPRIO_PACKET: case IF_HDRPRIO_PAYLOAD: return (0); default: if (hdrprio >= IF_HDRPRIO_MIN && hdrprio <= IF_HDRPRIO_MAX) return (0); break; } return (EINVAL); } int if_rxhprio_l2_check(int hdrprio) { switch (hdrprio) { case IF_HDRPRIO_PACKET: case IF_HDRPRIO_OUTER: return (0); default: if (hdrprio >= IF_HDRPRIO_MIN && hdrprio <= IF_HDRPRIO_MAX) return (0); break; } return (EINVAL); } int if_rxhprio_l3_check(int hdrprio) { switch (hdrprio) { case IF_HDRPRIO_PACKET: case IF_HDRPRIO_PAYLOAD: case IF_HDRPRIO_OUTER: return (0); default: if (hdrprio >= IF_HDRPRIO_MIN && hdrprio <= IF_HDRPRIO_MAX) return (0); break; } return (EINVAL); } /* * Return interface configuration * of system. List may be used * in later ioctl's (above) to get * other information. */ int ifconf(caddr_t data) { struct ifconf *ifc = (struct ifconf *)data; struct ifnet *ifp; struct ifaddr *ifa; struct ifreq ifr, *ifrp; int space = ifc->ifc_len, error = 0; /* If ifc->ifc_len is 0, fill it in with the needed size and return. */ if (space == 0) { TAILQ_FOREACH(ifp, &ifnetlist, if_list) { struct sockaddr *sa; if (TAILQ_EMPTY(&ifp->if_addrlist)) space += sizeof (ifr); else TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { sa = ifa->ifa_addr; if (sa->sa_len > sizeof(*sa)) space += sa->sa_len - sizeof(*sa); space += sizeof(ifr); } } ifc->ifc_len = space; return (0); } ifrp = ifc->ifc_req; TAILQ_FOREACH(ifp, &ifnetlist, if_list) { if (space < sizeof(ifr)) break; bcopy(ifp->if_xname, ifr.ifr_name, IFNAMSIZ); if (TAILQ_EMPTY(&ifp->if_addrlist)) { bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof(ifr)); if (error) break; space -= sizeof (ifr), ifrp++; } else TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { struct sockaddr *sa = ifa->ifa_addr; if (space < sizeof(ifr)) break; if (sa->sa_len <= sizeof(*sa)) { ifr.ifr_addr = *sa; error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); ifrp++; } else { space -= sa->sa_len - sizeof(*sa); if (space < sizeof (ifr)) break; error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof(ifr.ifr_name)); if (error == 0) error = copyout((caddr_t)sa, (caddr_t)&ifrp->ifr_addr, sa->sa_len); ifrp = (struct ifreq *)(sa->sa_len + (caddr_t)&ifrp->ifr_addr); } if (error) break; space -= sizeof (ifr); } } ifc->ifc_len -= space; return (error); } void if_counters_alloc(struct ifnet *ifp) { KASSERT(ifp->if_counters == NULL); ifp->if_counters = counters_alloc(ifc_ncounters); } void if_counters_free(struct ifnet *ifp) { KASSERT(ifp->if_counters != NULL); counters_free(ifp->if_counters, ifc_ncounters); ifp->if_counters = NULL; } void if_getdata(struct ifnet *ifp, struct if_data *data) { unsigned int i; *data = ifp->if_data; if (ifp->if_counters != NULL) { uint64_t counters[ifc_ncounters]; counters_read(ifp->if_counters, counters, nitems(counters), NULL); data->ifi_ipackets += counters[ifc_ipackets]; data->ifi_ierrors += counters[ifc_ierrors]; data->ifi_opackets += counters[ifc_opackets]; data->ifi_oerrors += counters[ifc_oerrors]; data->ifi_collisions += counters[ifc_collisions]; data->ifi_ibytes += counters[ifc_ibytes]; data->ifi_obytes += counters[ifc_obytes]; data->ifi_imcasts += counters[ifc_imcasts]; data->ifi_omcasts += counters[ifc_omcasts]; data->ifi_iqdrops += counters[ifc_iqdrops]; data->ifi_oqdrops += counters[ifc_oqdrops]; data->ifi_noproto += counters[ifc_noproto]; } for (i = 0; i < ifp->if_nifqs; i++) { struct ifqueue *ifq = ifp->if_ifqs[i]; ifq_add_data(ifq, data); } for (i = 0; i < ifp->if_niqs; i++) { struct ifiqueue *ifiq = ifp->if_iqs[i]; ifiq_add_data(ifiq, data); } } /* * Dummy functions replaced in ifnet during detach (if protocols decide to * fiddle with the if during detach. */ void if_detached_qstart(struct ifqueue *ifq) { ifq_purge(ifq); } int if_detached_ioctl(struct ifnet *ifp, u_long a, caddr_t b) { return ENODEV; } /* * Create interface group without members */ struct ifg_group * if_creategroup(const char *groupname) { struct ifg_group *ifg; if ((ifg = malloc(sizeof(*ifg), M_IFGROUP, M_NOWAIT)) == NULL) return (NULL); strlcpy(ifg->ifg_group, groupname, sizeof(ifg->ifg_group)); ifg->ifg_refcnt = 1; ifg->ifg_carp_demoted = 0; TAILQ_INIT(&ifg->ifg_members); #if NPF > 0 pfi_attach_ifgroup(ifg); #endif TAILQ_INSERT_TAIL(&ifg_head, ifg, ifg_next); return (ifg); } /* * Add a group to an interface */ int if_addgroup(struct ifnet *ifp, const char *groupname) { struct ifg_list *ifgl; struct ifg_group *ifg = NULL; struct ifg_member *ifgm; size_t namelen; namelen = strlen(groupname); if (namelen == 0 || namelen >= IFNAMSIZ || (groupname[namelen - 1] >= '0' && groupname[namelen - 1] <= '9')) return (EINVAL); TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) if (!strcmp(ifgl->ifgl_group->ifg_group, groupname)) return (EEXIST); if ((ifgl = malloc(sizeof(*ifgl), M_IFGROUP, M_NOWAIT)) == NULL) return (ENOMEM); if ((ifgm = malloc(sizeof(*ifgm), M_IFGROUP, M_NOWAIT)) == NULL) { free(ifgl, M_IFGROUP, sizeof(*ifgl)); return (ENOMEM); } TAILQ_FOREACH(ifg, &ifg_head, ifg_next) if (!strcmp(ifg->ifg_group, groupname)) break; if (ifg == NULL) { ifg = if_creategroup(groupname); if (ifg == NULL) { free(ifgl, M_IFGROUP, sizeof(*ifgl)); free(ifgm, M_IFGROUP, sizeof(*ifgm)); return (ENOMEM); } } else ifg->ifg_refcnt++; KASSERT(ifg->ifg_refcnt != 0); ifgl->ifgl_group = ifg; ifgm->ifgm_ifp = ifp; TAILQ_INSERT_TAIL(&ifg->ifg_members, ifgm, ifgm_next); TAILQ_INSERT_TAIL(&ifp->if_groups, ifgl, ifgl_next); #if NPF > 0 pfi_group_addmember(groupname); #endif return (0); } /* * Remove a group from an interface */ int if_delgroup(struct ifnet *ifp, const char *groupname) { struct ifg_list *ifgl; struct ifg_member *ifgm; TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) if (!strcmp(ifgl->ifgl_group->ifg_group, groupname)) break; if (ifgl == NULL) return (ENOENT); TAILQ_REMOVE(&ifp->if_groups, ifgl, ifgl_next); TAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next) if (ifgm->ifgm_ifp == ifp) break; if (ifgm != NULL) { TAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm, ifgm_next); free(ifgm, M_IFGROUP, sizeof(*ifgm)); } #if NPF > 0 pfi_group_delmember(groupname); #endif KASSERT(ifgl->ifgl_group->ifg_refcnt != 0); if (--ifgl->ifgl_group->ifg_refcnt == 0) { TAILQ_REMOVE(&ifg_head, ifgl->ifgl_group, ifg_next); #if NPF > 0 pfi_detach_ifgroup(ifgl->ifgl_group); #endif free(ifgl->ifgl_group, M_IFGROUP, sizeof(*ifgl->ifgl_group)); } free(ifgl, M_IFGROUP, sizeof(*ifgl)); return (0); } /* * Stores all groups from an interface in memory pointed * to by data */ int if_getgroup(caddr_t data, struct ifnet *ifp) { int len, error; struct ifg_list *ifgl; struct ifg_req ifgrq, *ifgp; struct ifgroupreq *ifgr = (struct ifgroupreq *)data; if (ifgr->ifgr_len == 0) { TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) ifgr->ifgr_len += sizeof(struct ifg_req); return (0); } len = ifgr->ifgr_len; ifgp = ifgr->ifgr_groups; TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) { if (len < sizeof(ifgrq)) return (EINVAL); bzero(&ifgrq, sizeof ifgrq); strlcpy(ifgrq.ifgrq_group, ifgl->ifgl_group->ifg_group, sizeof(ifgrq.ifgrq_group)); if ((error = copyout((caddr_t)&ifgrq, (caddr_t)ifgp, sizeof(struct ifg_req)))) return (error); len -= sizeof(ifgrq); ifgp++; } return (0); } /* * Stores all members of a group in memory pointed to by data */ int if_getgroupmembers(caddr_t data) { struct ifgroupreq *ifgr = (struct ifgroupreq *)data; struct ifg_group *ifg; struct ifg_member *ifgm; struct ifg_req ifgrq, *ifgp; int len, error; TAILQ_FOREACH(ifg, &ifg_head, ifg_next) if (!strcmp(ifg->ifg_group, ifgr->ifgr_name)) break; if (ifg == NULL) return (ENOENT); if (ifgr->ifgr_len == 0) { TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next) ifgr->ifgr_len += sizeof(ifgrq); return (0); } len = ifgr->ifgr_len; ifgp = ifgr->ifgr_groups; TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next) { if (len < sizeof(ifgrq)) return (EINVAL); bzero(&ifgrq, sizeof ifgrq); strlcpy(ifgrq.ifgrq_member, ifgm->ifgm_ifp->if_xname, sizeof(ifgrq.ifgrq_member)); if ((error = copyout((caddr_t)&ifgrq, (caddr_t)ifgp, sizeof(struct ifg_req)))) return (error); len -= sizeof(ifgrq); ifgp++; } return (0); } int if_getgroupattribs(caddr_t data) { struct ifgroupreq *ifgr = (struct ifgroupreq *)data; struct ifg_group *ifg; TAILQ_FOREACH(ifg, &ifg_head, ifg_next) if (!strcmp(ifg->ifg_group, ifgr->ifgr_name)) break; if (ifg == NULL) return (ENOENT); ifgr->ifgr_attrib.ifg_carp_demoted = ifg->ifg_carp_demoted; return (0); } int if_setgroupattribs(caddr_t data) { struct ifgroupreq *ifgr = (struct ifgroupreq *)data; struct ifg_group *ifg; struct ifg_member *ifgm; int demote; TAILQ_FOREACH(ifg, &ifg_head, ifg_next) if (!strcmp(ifg->ifg_group, ifgr->ifgr_name)) break; if (ifg == NULL) return (ENOENT); demote = ifgr->ifgr_attrib.ifg_carp_demoted; if (demote + ifg->ifg_carp_demoted > 0xff || demote + ifg->ifg_carp_demoted < 0) return (EINVAL); ifg->ifg_carp_demoted += demote; TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next) ifgm->ifgm_ifp->if_ioctl(ifgm->ifgm_ifp, SIOCSIFGATTR, data); return (0); } /* * Stores all groups in memory pointed to by data */ int if_getgrouplist(caddr_t data) { struct ifgroupreq *ifgr = (struct ifgroupreq *)data; struct ifg_group *ifg; struct ifg_req ifgrq, *ifgp; int len, error; if (ifgr->ifgr_len == 0) { TAILQ_FOREACH(ifg, &ifg_head, ifg_next) ifgr->ifgr_len += sizeof(ifgrq); return (0); } len = ifgr->ifgr_len; ifgp = ifgr->ifgr_groups; TAILQ_FOREACH(ifg, &ifg_head, ifg_next) { if (len < sizeof(ifgrq)) return (EINVAL); bzero(&ifgrq, sizeof ifgrq); strlcpy(ifgrq.ifgrq_group, ifg->ifg_group, sizeof(ifgrq.ifgrq_group)); if ((error = copyout((caddr_t)&ifgrq, (caddr_t)ifgp, sizeof(struct ifg_req)))) return (error); len -= sizeof(ifgrq); ifgp++; } return (0); } void if_group_routechange(const struct sockaddr *dst, const struct sockaddr *mask) { switch (dst->sa_family) { case AF_INET: if (satosin_const(dst)->sin_addr.s_addr == INADDR_ANY && mask && (mask->sa_len == 0 || satosin_const(mask)->sin_addr.s_addr == INADDR_ANY)) if_group_egress_build(); break; #ifdef INET6 case AF_INET6: if (IN6_ARE_ADDR_EQUAL(&(satosin6_const(dst))->sin6_addr, &in6addr_any) && mask && (mask->sa_len == 0 || IN6_ARE_ADDR_EQUAL(&(satosin6_const(mask))->sin6_addr, &in6addr_any))) if_group_egress_build(); break; #endif } } int if_group_egress_build(void) { struct ifnet *ifp; struct ifg_group *ifg; struct ifg_member *ifgm, *next; struct sockaddr_in sa_in; #ifdef INET6 struct sockaddr_in6 sa_in6; #endif struct rtentry *rt; TAILQ_FOREACH(ifg, &ifg_head, ifg_next) if (!strcmp(ifg->ifg_group, IFG_EGRESS)) break; if (ifg != NULL) TAILQ_FOREACH_SAFE(ifgm, &ifg->ifg_members, ifgm_next, next) if_delgroup(ifgm->ifgm_ifp, IFG_EGRESS); bzero(&sa_in, sizeof(sa_in)); sa_in.sin_len = sizeof(sa_in); sa_in.sin_family = AF_INET; rt = rtable_lookup(0, sintosa(&sa_in), sintosa(&sa_in), NULL, RTP_ANY); while (rt != NULL) { ifp = if_get(rt->rt_ifidx); if (ifp != NULL) { if_addgroup(ifp, IFG_EGRESS); if_put(ifp); } rt = rtable_iterate(rt); } #ifdef INET6 bcopy(&sa6_any, &sa_in6, sizeof(sa_in6)); rt = rtable_lookup(0, sin6tosa(&sa_in6), sin6tosa(&sa_in6), NULL, RTP_ANY); while (rt != NULL) { ifp = if_get(rt->rt_ifidx); if (ifp != NULL) { if_addgroup(ifp, IFG_EGRESS); if_put(ifp); } rt = rtable_iterate(rt); } #endif /* INET6 */ return (0); } /* * Set/clear promiscuous mode on interface ifp based on the truth value * of pswitch. The calls are reference counted so that only the first * "on" request actually has an effect, as does the final "off" request. * Results are undefined if the "off" and "on" requests are not matched. */ int ifpromisc(struct ifnet *ifp, int pswitch) { struct ifreq ifr; unsigned short oif_flags; int oif_pcount, error; NET_ASSERT_LOCKED(); /* modifying if_flags and if_pcount */ oif_flags = ifp->if_flags; oif_pcount = ifp->if_pcount; if (pswitch) { if (ifp->if_pcount++ != 0) return (0); ifp->if_flags |= IFF_PROMISC; } else { if (--ifp->if_pcount > 0) return (0); ifp->if_flags &= ~IFF_PROMISC; } if ((ifp->if_flags & IFF_UP) == 0) return (0); memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = ifp->if_flags; error = ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr)); if (error) { ifp->if_flags = oif_flags; ifp->if_pcount = oif_pcount; } return (error); } /* Set/clear LRO flag and restart interface if needed. */ int ifsetlro(struct ifnet *ifp, int on) { struct ifreq ifrq; int error = 0; int s = splnet(); struct if_parent parent; memset(&parent, 0, sizeof(parent)); if ((*ifp->if_ioctl)(ifp, SIOCGIFPARENT, (caddr_t)&parent) != -1) { struct ifnet *ifp0 = if_unit(parent.ifp_parent); if (ifp0 != NULL) { ifsetlro(ifp0, on); if_put(ifp0); } } if (!ISSET(ifp->if_capabilities, IFCAP_LRO)) { error = ENOTSUP; goto out; } NET_ASSERT_LOCKED(); /* for ioctl */ KERNEL_ASSERT_LOCKED(); /* for if_flags */ if (on && !ISSET(ifp->if_xflags, IFXF_LRO)) { if (ifp->if_type == IFT_ETHER && ether_brport_isset(ifp)) { error = EBUSY; goto out; } SET(ifp->if_xflags, IFXF_LRO); } else if (!on && ISSET(ifp->if_xflags, IFXF_LRO)) CLR(ifp->if_xflags, IFXF_LRO); else goto out; /* restart interface */ if (ISSET(ifp->if_flags, IFF_UP)) { /* go down for a moment... */ CLR(ifp->if_flags, IFF_UP); ifrq.ifr_flags = ifp->if_flags; (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq); /* ... and up again */ SET(ifp->if_flags, IFF_UP); ifrq.ifr_flags = ifp->if_flags; (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq); } out: splx(s); return error; } void ifa_add(struct ifnet *ifp, struct ifaddr *ifa) { NET_ASSERT_LOCKED_EXCLUSIVE(); TAILQ_INSERT_TAIL(&ifp->if_addrlist, ifa, ifa_list); } void ifa_del(struct ifnet *ifp, struct ifaddr *ifa) { NET_ASSERT_LOCKED_EXCLUSIVE(); TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list); } void ifa_update_broadaddr(struct ifnet *ifp, struct ifaddr *ifa, struct sockaddr *sa) { if (ifa->ifa_broadaddr->sa_len != sa->sa_len) panic("ifa_update_broadaddr does not support dynamic length"); bcopy(sa, ifa->ifa_broadaddr, sa->sa_len); } #ifdef DDB /* debug function, can be called from ddb> */ void ifa_print_all(void) { struct ifnet *ifp; struct ifaddr *ifa; TAILQ_FOREACH(ifp, &ifnetlist, if_list) { TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { char addr[INET6_ADDRSTRLEN]; switch (ifa->ifa_addr->sa_family) { case AF_INET: printf("%s", inet_ntop(AF_INET, &satosin(ifa->ifa_addr)->sin_addr, addr, sizeof(addr))); break; #ifdef INET6 case AF_INET6: printf("%s", inet_ntop(AF_INET6, &(satosin6(ifa->ifa_addr))->sin6_addr, addr, sizeof(addr))); break; #endif } printf(" on %s\n", ifp->if_xname); } } } #endif /* DDB */ void ifnewlladdr(struct ifnet *ifp) { #ifdef INET6 struct ifaddr *ifa; #endif struct ifreq ifrq; short up; NET_ASSERT_LOCKED(); /* for ioctl and in6 */ KERNEL_ASSERT_LOCKED(); /* for if_flags */ up = ifp->if_flags & IFF_UP; if (up) { /* go down for a moment... */ ifp->if_flags &= ~IFF_UP; ifrq.ifr_flags = ifp->if_flags; (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq); } ifp->if_flags |= IFF_UP; ifrq.ifr_flags = ifp->if_flags; (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq); #ifdef INET6 /* * Update the link-local address. Don't do it if we're * a router to avoid confusing hosts on the network. */ if (!ip6_forwarding) { ifa = &in6ifa_ifpforlinklocal(ifp, 0)->ia_ifa; if (ifa) { in6_purgeaddr(ifa); if_hooks_run(&ifp->if_addrhooks); in6_ifattach(ifp); } } #endif if (!up) { /* go back down */ ifp->if_flags &= ~IFF_UP; ifrq.ifr_flags = ifp->if_flags; (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq); } } void if_addrhook_add(struct ifnet *ifp, struct task *t) { mtx_enter(&if_hooks_mtx); TAILQ_INSERT_TAIL(&ifp->if_addrhooks, t, t_entry); mtx_leave(&if_hooks_mtx); } void if_addrhook_del(struct ifnet *ifp, struct task *t) { mtx_enter(&if_hooks_mtx); TAILQ_REMOVE(&ifp->if_addrhooks, t, t_entry); mtx_leave(&if_hooks_mtx); } void if_addrhooks_run(struct ifnet *ifp) { if_hooks_run(&ifp->if_addrhooks); } void if_rxr_init(struct if_rxring *rxr, u_int lwm, u_int hwm) { extern int ticks; memset(rxr, 0, sizeof(*rxr)); rxr->rxr_adjusted = ticks; rxr->rxr_cwm = rxr->rxr_lwm = lwm; rxr->rxr_hwm = hwm; } static inline void if_rxr_adjust_cwm(struct if_rxring *rxr) { extern int ticks; if (rxr->rxr_alive >= rxr->rxr_lwm) return; else if (rxr->rxr_cwm < rxr->rxr_hwm) rxr->rxr_cwm++; rxr->rxr_adjusted = ticks; } void if_rxr_livelocked(struct if_rxring *rxr) { extern int ticks; if (ticks - rxr->rxr_adjusted >= 1) { if (rxr->rxr_cwm > rxr->rxr_lwm) rxr->rxr_cwm--; rxr->rxr_adjusted = ticks; } } u_int if_rxr_get(struct if_rxring *rxr, u_int max) { extern int ticks; u_int diff; if (ticks - rxr->rxr_adjusted >= 1) { /* we're free to try for an adjustment */ if_rxr_adjust_cwm(rxr); } if (rxr->rxr_alive >= rxr->rxr_cwm) return (0); diff = min(rxr->rxr_cwm - rxr->rxr_alive, max); rxr->rxr_alive += diff; return (diff); } int if_rxr_info_ioctl(struct if_rxrinfo *uifri, u_int t, struct if_rxring_info *e) { struct if_rxrinfo kifri; int error; u_int n; error = copyin(uifri, &kifri, sizeof(kifri)); if (error) return (error); n = min(t, kifri.ifri_total); kifri.ifri_total = t; if (n > 0) { error = copyout(e, kifri.ifri_entries, sizeof(*e) * n); if (error) return (error); } return (copyout(&kifri, uifri, sizeof(kifri))); } int if_rxr_ioctl(struct if_rxrinfo *ifri, const char *name, u_int size, struct if_rxring *rxr) { struct if_rxring_info ifr; memset(&ifr, 0, sizeof(ifr)); if (name != NULL) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); ifr.ifr_size = size; ifr.ifr_info = *rxr; return (if_rxr_info_ioctl(ifri, 1, &ifr)); } /* * Network stack input queues. */ void niq_init(struct niqueue *niq, u_int maxlen, u_int isr) { mq_init(&niq->ni_q, maxlen, IPL_NET); niq->ni_isr = isr; } int niq_enqueue(struct niqueue *niq, struct mbuf *m) { int rv; rv = mq_enqueue(&niq->ni_q, m); if (rv == 0) schednetisr(niq->ni_isr); else if_congestion(); return (rv); } int niq_enlist(struct niqueue *niq, struct mbuf_list *ml) { int rv; rv = mq_enlist(&niq->ni_q, ml); if (rv == 0) schednetisr(niq->ni_isr); else if_congestion(); return (rv); } __dead void unhandled_af(int af) { panic("unhandled af %d", af); } struct taskq * net_tq(unsigned int ifindex) { struct softnet *sn; static int nettaskqs; if (nettaskqs == 0) nettaskqs = min(NET_TASKQ, ncpus); sn = &softnets[ifindex % nettaskqs]; return (sn->sn_taskq); } void net_tq_barriers(const char *wmesg) { struct task barriers[NET_TASKQ]; struct refcnt r = REFCNT_INITIALIZER(); int i; for (i = 0; i < nitems(barriers); i++) { task_set(&barriers[i], (void (*)(void *))refcnt_rele_wake, &r); refcnt_take(&r); task_add(softnets[i].sn_taskq, &barriers[i]); } refcnt_finalize(&r, wmesg); }
7 3 7 7 7 3 7 7 7 4 3 3 3 8 8 1 7 3 7 3 7 1 7 33 34 5 61 5 1 22 54 8 22 21 1 10 19 19 19 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 /* $OpenBSD: in6_ifattach.c,v 1.122 2023/07/09 19:06:48 bluhm Exp $ */ /* $KAME: in6_ifattach.c,v 1.124 2001/07/18 08:32:51 jinmei Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/socket.h> #include <sys/sockio.h> #include <sys/kernel.h> #include <sys/syslog.h> #include <crypto/sha2.h> #include <net/if.h> #include <net/if_var.h> #include <net/if_dl.h> #include <net/if_types.h> #include <net/route.h> #include <netinet/in.h> #include <netinet6/in6_var.h> #include <netinet/ip6.h> #include <netinet6/ip6_var.h> #include <netinet6/in6_ifattach.h> #include <netinet6/nd6.h> #ifdef MROUTING #include <netinet6/ip6_mroute.h> #endif void in6_get_rand_ifid(struct ifnet *, struct in6_addr *); int in6_get_hw_ifid(struct ifnet *, struct in6_addr *); void in6_get_ifid(struct ifnet *, struct in6_addr *); int in6_ifattach_loopback(struct ifnet *); #define EUI64_GBIT 0x01 #define EUI64_UBIT 0x02 #define EUI64_TO_IFID(in6) do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (0) #define EUI64_GROUP(in6) ((in6)->s6_addr[8] & EUI64_GBIT) #define EUI64_INDIVIDUAL(in6) (!EUI64_GROUP(in6)) #define EUI64_LOCAL(in6) ((in6)->s6_addr[8] & EUI64_UBIT) #define EUI64_UNIVERSAL(in6) (!EUI64_LOCAL(in6)) #define IFID_LOCAL(in6) (!EUI64_LOCAL(in6)) #define IFID_UNIVERSAL(in6) (!EUI64_UNIVERSAL(in6)) /* * Generate a random interface identifier. * * in6 - upper 64bits are preserved */ void in6_get_rand_ifid(struct ifnet *ifp, struct in6_addr *in6) { arc4random_buf(&in6->s6_addr32[2], 8); /* make sure to set "u" bit to local, and "g" bit to individual. */ in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */ in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */ /* convert EUI64 into IPv6 interface identifier */ EUI64_TO_IFID(in6); } /* * Get interface identifier for the specified interface. * * in6 - upper 64bits are preserved */ int in6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6) { struct sockaddr_dl *sdl; char *addr; size_t addrlen; static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; static u_int8_t allone[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; sdl = ifp->if_sadl; if (sdl == NULL || sdl->sdl_alen == 0) return -1; addr = LLADDR(sdl); addrlen = sdl->sdl_alen; switch (ifp->if_type) { case IFT_IEEE1394: case IFT_IEEE80211: /* IEEE1394 uses 16byte length address starting with EUI64 */ if (addrlen > 8) addrlen = 8; break; default: break; } /* get EUI64 */ switch (ifp->if_type) { /* IEEE802/EUI64 cases - what others? */ case IFT_ETHER: case IFT_CARP: case IFT_IEEE1394: case IFT_IEEE80211: /* look at IEEE802/EUI64 only */ if (addrlen != 8 && addrlen != 6) return -1; /* * check for invalid MAC address - on bsdi, we see it a lot * since wildboar configures all-zero MAC on pccard before * card insertion. */ if (bcmp(addr, allzero, addrlen) == 0) return -1; if (bcmp(addr, allone, addrlen) == 0) return -1; /* make EUI64 address */ if (addrlen == 8) memcpy(&in6->s6_addr[8], addr, 8); else if (addrlen == 6) { in6->s6_addr[8] = addr[0]; in6->s6_addr[9] = addr[1]; in6->s6_addr[10] = addr[2]; in6->s6_addr[11] = 0xff; in6->s6_addr[12] = 0xfe; in6->s6_addr[13] = addr[3]; in6->s6_addr[14] = addr[4]; in6->s6_addr[15] = addr[5]; } break; case IFT_GIF: /* * RFC2893 says: "SHOULD use IPv4 address as ifid source". * however, IPv4 address is not very suitable as unique * identifier source (can be renumbered). * we don't do this. */ return -1; default: return -1; } /* sanity check: g bit must not indicate "group" */ if (EUI64_GROUP(in6)) return -1; /* convert EUI64 into IPv6 interface identifier */ EUI64_TO_IFID(in6); /* * sanity check: ifid must not be all zero, avoid conflict with * subnet router anycast */ if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 && bcmp(&in6->s6_addr[9], allzero, 7) == 0) { return -1; } return 0; } /* * Get interface identifier for the specified interface. If it is not * available on ifp0, borrow interface identifier from other information * sources. */ void in6_get_ifid(struct ifnet *ifp0, struct in6_addr *in6) { struct ifnet *ifp; /* first, try to get it from the interface itself */ if (in6_get_hw_ifid(ifp0, in6) == 0) { nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n", ifp0->if_xname)); goto success; } /* next, try to get it from some other hardware interface */ TAILQ_FOREACH(ifp, &ifnetlist, if_list) { if (ifp == ifp0) continue; if (in6_get_hw_ifid(ifp, in6) == 0) goto success; } /* last resort: get from random number source */ in6_get_rand_ifid(ifp, in6); nd6log((LOG_DEBUG, "%s: interface identifier generated by random number\n", ifp0->if_xname)); success: nd6log((LOG_INFO, "%s: ifid: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", ifp0->if_xname, in6->s6_addr[8], in6->s6_addr[9], in6->s6_addr[10], in6->s6_addr[11], in6->s6_addr[12], in6->s6_addr[13], in6->s6_addr[14], in6->s6_addr[15])); } /* * ifid - used as EUI64 if not NULL, overrides other EUI64 sources */ int in6_ifattach_linklocal(struct ifnet *ifp, struct in6_addr *ifid) { struct in6_aliasreq ifra; struct in6_ifaddr *ia6; int error, flags; NET_ASSERT_LOCKED(); /* * configure link-local address. */ bzero(&ifra, sizeof(ifra)); strlcpy(ifra.ifra_name, ifp->if_xname, sizeof(ifra.ifra_name)); ifra.ifra_addr.sin6_family = AF_INET6; ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6); ifra.ifra_addr.sin6_addr.s6_addr16[0] = htons(0xfe80); ifra.ifra_addr.sin6_addr.s6_addr16[1] = htons(ifp->if_index); ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0; if ((ifp->if_flags & IFF_LOOPBACK) != 0) { ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0; ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1); } else if (ifid) { ifra.ifra_addr.sin6_addr = *ifid; ifra.ifra_addr.sin6_addr.s6_addr16[0] = htons(0xfe80); ifra.ifra_addr.sin6_addr.s6_addr16[1] = htons(ifp->if_index); ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0; ifra.ifra_addr.sin6_addr.s6_addr[8] &= ~EUI64_GBIT; ifra.ifra_addr.sin6_addr.s6_addr[8] |= EUI64_UBIT; } else in6_get_ifid(ifp, &ifra.ifra_addr.sin6_addr); ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6); ifra.ifra_prefixmask.sin6_family = AF_INET6; ifra.ifra_prefixmask.sin6_addr = in6mask64; /* link-local addresses should NEVER expire. */ ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; /* * XXX: Some P2P interfaces seem not to send packets just after * becoming up, so we skip p2p interfaces for safety. */ if (in6if_do_dad(ifp) && ((ifp->if_flags & IFF_POINTOPOINT) == 0)) ifra.ifra_flags |= IN6_IFF_TENTATIVE; error = in6_update_ifa(ifp, &ifra, in6ifa_ifpforlinklocal(ifp, 0)); if (error != 0) return (error); ia6 = in6ifa_ifpforlinklocal(ifp, 0); /* Perform DAD, if needed. */ if (ia6->ia6_flags & IN6_IFF_TENTATIVE) nd6_dad_start(&ia6->ia_ifa); if (ifp->if_flags & IFF_LOOPBACK) { if_addrhooks_run(ifp); return (0); /* No need to install a connected route. */ } flags = RTF_CONNECTED | RTF_MPATH; if ((ifp->if_flags & IFF_POINTOPOINT) == 0) flags |= RTF_CLONING; error = rt_ifa_add(&ia6->ia_ifa, flags, ia6->ia_ifa.ifa_addr, ifp->if_rdomain); if (error) { in6_purgeaddr(&ia6->ia_ifa); return (error); } if_addrhooks_run(ifp); return (0); } int in6_ifattach_loopback(struct ifnet *ifp) { struct in6_addr in6 = in6addr_loopback; struct in6_aliasreq ifra; KASSERT(ifp->if_flags & IFF_LOOPBACK); if (in6ifa_ifpwithaddr(ifp, &in6) != NULL) return (0); bzero(&ifra, sizeof(ifra)); strlcpy(ifra.ifra_name, ifp->if_xname, sizeof(ifra.ifra_name)); ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6); ifra.ifra_prefixmask.sin6_family = AF_INET6; ifra.ifra_prefixmask.sin6_addr = in6mask128; /* * Always initialize ia_dstaddr (= broadcast address) to loopback * address. Follows IPv4 practice - see in_ifinit(). */ ifra.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6); ifra.ifra_dstaddr.sin6_family = AF_INET6; ifra.ifra_dstaddr.sin6_addr = in6addr_loopback; ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6); ifra.ifra_addr.sin6_family = AF_INET6; ifra.ifra_addr.sin6_addr = in6addr_loopback; /* the loopback address should NEVER expire. */ ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; /* * We are sure that this is a newly assigned address, so we can set * NULL to the 3rd arg. */ return (in6_update_ifa(ifp, &ifra, NULL)); } /* * XXX multiple loopback interface needs more care. for instance, * nodelocal address needs to be configured onto only one of them. * XXX multiple link-local address case */ int in6_ifattach(struct ifnet *ifp) { /* some of the interfaces are inherently not IPv6 capable */ switch (ifp->if_type) { case IFT_BRIDGE: case IFT_ENC: case IFT_PFLOG: case IFT_PFSYNC: return (0); } /* * if link mtu is too small, don't try to configure IPv6. * remember there could be some link-layer that has special * fragmentation logic. */ if (ifp->if_mtu < IPV6_MMTU) return (EINVAL); if (nd6_need_cache(ifp) && (ifp->if_flags & IFF_MULTICAST) == 0) return (EINVAL); /* * Assign loopback address if this lo(4) interface is the * default for its rdomain. */ if ((ifp->if_flags & IFF_LOOPBACK) && (ifp->if_index == rtable_loindex(ifp->if_rdomain))) { int error; error = in6_ifattach_loopback(ifp); if (error) return (error); } switch (ifp->if_type) { case IFT_WIREGUARD: return (0); } /* Assign a link-local address, if there's none. */ if (in6ifa_ifpforlinklocal(ifp, 0) == NULL) { if (in6_ifattach_linklocal(ifp, NULL) != 0) { /* failed to assign linklocal address. bark? */ } } return (0); } /* * NOTE: in6_ifdetach() does not support loopback if at this moment. */ void in6_ifdetach(struct ifnet *ifp) { struct ifaddr *ifa, *next; struct rtentry *rt; struct sockaddr_in6 sin6; #ifdef MROUTING /* remove ip6_mrouter stuff */ ip6_mrouter_detach(ifp); #endif /* nuke any of IPv6 addresses we have */ TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrlist, ifa_list, next) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; in6_purgeaddr(ifa); if_addrhooks_run(ifp); } /* * Remove neighbor management table. Must be called after * purging addresses. */ nd6_purge(ifp); /* remove route to interface local allnodes multicast (ff01::1) */ bzero(&sin6, sizeof(sin6)); sin6.sin6_len = sizeof(struct sockaddr_in6); sin6.sin6_family = AF_INET6; sin6.sin6_addr = in6addr_intfacelocal_allnodes; sin6.sin6_addr.s6_addr16[1] = htons(ifp->if_index); rt = rtalloc(sin6tosa(&sin6), 0, ifp->if_rdomain); if (rt && rt->rt_ifidx == ifp->if_index) rtdeletemsg(rt, ifp, ifp->if_rdomain); rtfree(rt); /* remove route to link-local allnodes multicast (ff02::1) */ bzero(&sin6, sizeof(sin6)); sin6.sin6_len = sizeof(struct sockaddr_in6); sin6.sin6_family = AF_INET6; sin6.sin6_addr = in6addr_linklocal_allnodes; sin6.sin6_addr.s6_addr16[1] = htons(ifp->if_index); rt = rtalloc(sin6tosa(&sin6), 0, ifp->if_rdomain); if (rt && rt->rt_ifidx == ifp->if_index) rtdeletemsg(rt, ifp, ifp->if_rdomain); rtfree(rt); if (ifp->if_xflags & (IFXF_AUTOCONF6 | IFXF_AUTOCONF6TEMP)) ifp->if_xflags &= ~(IFXF_AUTOCONF6 | IFXF_AUTOCONF6TEMP); }
8 2 2 392 99 48 68 9 2801 2807 2798 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 /* $OpenBSD: subr_xxx.c,v 1.17 2019/05/17 03:53:08 visa Exp $ */ /* $NetBSD: subr_xxx.c,v 1.10 1996/02/04 02:16:51 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)subr_xxx.c 8.1 (Berkeley) 6/10/93 */ /* * Miscellaneous trivial functions, including many * that are often inline-expanded or done in assembler. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/conf.h> #include <sys/smr.h> /* * Unsupported device function (e.g. writing to read-only device). */ int enodev(void) { return (ENODEV); } /* * Unconfigured device function; driver not configured. */ int enxio(void) { return (ENXIO); } /* * Unsupported ioctl function. */ int enoioctl(void) { return (ENOTTY); } /* * Unsupported system function. * This is used for an otherwise-reasonable operation * that is not supported by the current system binary. */ int enosys(void) { return (ENOSYS); } /* * Return error for operation not supported * on a specific object or file type. */ int eopnotsupp(void *v) { return (EOPNOTSUPP); } /* * Generic null operation, always returns success. */ int nullop(void *v) { return (0); } struct bdevsw * bdevsw_lookup(dev_t dev) { return (&bdevsw[major(dev)]); } struct cdevsw * cdevsw_lookup(dev_t dev) { return (&cdevsw[major(dev)]); } /* * Convert a character device number to a block device number. */ dev_t chrtoblk(dev_t dev) { int blkmaj; if (major(dev) >= nchrdev || major(dev) >= nchrtoblktbl) return (NODEV); blkmaj = chrtoblktbl[major(dev)]; if (blkmaj == NODEV) return (NODEV); return (makedev(blkmaj, minor(dev))); } /* * Convert a block device number to a character device number. */ dev_t blktochr(dev_t dev) { int blkmaj = major(dev); int i; if (blkmaj >= nblkdev) return (NODEV); for (i = 0; i < nchrtoblktbl; i++) if (blkmaj == chrtoblktbl[i]) return (makedev(i, minor(dev))); return (NODEV); } /* * Check that we're in a context where it's okay to sleep. */ void assertwaitok(void) { if (panicstr || db_active) return; splassert(IPL_NONE); SMR_ASSERT_NONCRITICAL(); #ifdef DIAGNOSTIC if (curcpu()->ci_mutex_level != 0) panic("assertwaitok: non-zero mutex count: %d", curcpu()->ci_mutex_level); #endif }
2 2 2 2 2 2 2 2 2 2 265 266 89 89 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 /* $OpenBSD: ip_ipsp.c,v 1.278 2023/12/03 10:50:25 mvs Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr), * Niels Provos (provos@physnet.uni-hamburg.de) and * Niklas Hallqvist (niklas@appli.se). * * The original version of this code was written by John Ioannidis * for BSD/OS in Athens, Greece, in November 1995. * * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, * by Angelos D. Keromytis. * * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis * and Niels Provos. * * Additional features in 1999 by Angelos D. Keromytis and Niklas Hallqvist. * * Copyright (c) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, * Angelos D. Keromytis and Niels Provos. * Copyright (c) 1999 Niklas Hallqvist. * Copyright (c) 2001, Angelos D. Keromytis. * * Permission to use, copy, and modify this software with or without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or * modification of this software. * You may use this code under the GNU public license if you so wish. Please * contribute changes back to the authors under this freer than GPL license * so that we may further the use of strong encryption without limitations to * all. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR * PURPOSE. */ #include "pf.h" #include "pfsync.h" #include "sec.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/kernel.h> #include <sys/timeout.h> #include <sys/pool.h> #include <sys/atomic.h> #include <sys/mutex.h> #include <net/if.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/in_pcb.h> #include <netinet/ip_var.h> #include <netinet/ip_ipip.h> #if NPF > 0 #include <net/pfvar.h> #endif #if NPFSYNC > 0 #include <net/if_pfsync.h> #endif #if NSEC > 0 #include <net/if_sec.h> #endif #include <netinet/ip_ipsp.h> #include <net/pfkeyv2.h> #ifdef DDB #include <ddb/db_output.h> void tdb_hashstats(void); #endif #ifdef ENCDEBUG #define DPRINTF(fmt, args...) \ do { \ if (encdebug) \ printf("%s: " fmt "\n", __func__, ## args); \ } while (0) #else #define DPRINTF(fmt, args...) \ do { } while (0) #endif /* * Locks used to protect global data and struct members: * D tdb_sadb_mtx * F ipsec_flows_mtx SA database global mutex */ struct mutex ipsec_flows_mtx = MUTEX_INITIALIZER(IPL_SOFTNET); int tdb_rehash(void); void tdb_timeout(void *); void tdb_firstuse(void *); void tdb_soft_timeout(void *); void tdb_soft_firstuse(void *); int tdb_hash(u_int32_t, union sockaddr_union *, u_int8_t); int ipsec_in_use = 0; u_int64_t ipsec_last_added = 0; int ipsec_ids_idle = 100; /* keep free ids for 100s */ struct pool tdb_pool; /* Protected by the NET_LOCK(). */ u_int32_t ipsec_ids_next_flow = 1; /* [F] may not be zero */ struct ipsec_ids_tree ipsec_ids_tree; /* [F] */ struct ipsec_ids_flows ipsec_ids_flows; /* [F] */ struct ipsec_policy_head ipsec_policy_head = TAILQ_HEAD_INITIALIZER(ipsec_policy_head); void ipsp_ids_gc(void *); LIST_HEAD(, ipsec_ids) ipsp_ids_gc_list = LIST_HEAD_INITIALIZER(ipsp_ids_gc_list); /* [F] */ struct timeout ipsp_ids_gc_timeout = TIMEOUT_INITIALIZER_FLAGS(ipsp_ids_gc, NULL, KCLOCK_NONE, TIMEOUT_PROC | TIMEOUT_MPSAFE); static inline int ipsp_ids_cmp(const struct ipsec_ids *, const struct ipsec_ids *); static inline int ipsp_ids_flow_cmp(const struct ipsec_ids *, const struct ipsec_ids *); RBT_PROTOTYPE(ipsec_ids_tree, ipsec_ids, id_node_flow, ipsp_ids_cmp); RBT_PROTOTYPE(ipsec_ids_flows, ipsec_ids, id_node_id, ipsp_ids_flow_cmp); RBT_GENERATE(ipsec_ids_tree, ipsec_ids, id_node_flow, ipsp_ids_cmp); RBT_GENERATE(ipsec_ids_flows, ipsec_ids, id_node_id, ipsp_ids_flow_cmp); /* * This is the proper place to define the various encapsulation transforms. */ const struct xformsw xformsw[] = { #ifdef IPSEC { .xf_type = XF_IP4, .xf_flags = 0, .xf_name = "IPv4 Simple Encapsulation", .xf_attach = ipe4_attach, .xf_init = ipe4_init, .xf_zeroize = ipe4_zeroize, .xf_input = ipe4_input, .xf_output = NULL, }, { .xf_type = XF_AH, .xf_flags = XFT_AUTH, .xf_name = "IPsec AH", .xf_attach = ah_attach, .xf_init = ah_init, .xf_zeroize = ah_zeroize, .xf_input = ah_input, .xf_output = ah_output, }, { .xf_type = XF_ESP, .xf_flags = XFT_CONF|XFT_AUTH, .xf_name = "IPsec ESP", .xf_attach = esp_attach, .xf_init = esp_init, .xf_zeroize = esp_zeroize, .xf_input = esp_input, .xf_output = esp_output, }, { .xf_type = XF_IPCOMP, .xf_flags = XFT_COMP, .xf_name = "IPcomp", .xf_attach = ipcomp_attach, .xf_init = ipcomp_init, .xf_zeroize = ipcomp_zeroize, .xf_input = ipcomp_input, .xf_output = ipcomp_output, }, #endif /* IPSEC */ #ifdef TCP_SIGNATURE { .xf_type = XF_TCPSIGNATURE, .xf_flags = XFT_AUTH, .xf_name = "TCP MD5 Signature Option, RFC 2385", .xf_attach = tcp_signature_tdb_attach, .xf_init = tcp_signature_tdb_init, .xf_zeroize = tcp_signature_tdb_zeroize, .xf_input = tcp_signature_tdb_input, .xf_output = tcp_signature_tdb_output, } #endif /* TCP_SIGNATURE */ }; const struct xformsw *const xformswNXFORMSW = &xformsw[nitems(xformsw)]; #define TDB_HASHSIZE_INIT 32 struct mutex tdb_sadb_mtx = MUTEX_INITIALIZER(IPL_SOFTNET); static SIPHASH_KEY tdbkey; /* [D] */ static struct tdb **tdbh; /* [D] */ static struct tdb **tdbdst; /* [D] */ static struct tdb **tdbsrc; /* [D] */ static u_int tdb_hashmask = TDB_HASHSIZE_INIT - 1; /* [D] */ static int tdb_count; /* [D] */ void ipsp_init(void) { pool_init(&tdb_pool, sizeof(struct tdb), 0, IPL_SOFTNET, 0, "tdb", NULL); arc4random_buf(&tdbkey, sizeof(tdbkey)); tdbh = mallocarray(tdb_hashmask + 1, sizeof(struct tdb *), M_TDB, M_WAITOK | M_ZERO); tdbdst = mallocarray(tdb_hashmask + 1, sizeof(struct tdb *), M_TDB, M_WAITOK | M_ZERO); tdbsrc = mallocarray(tdb_hashmask + 1, sizeof(struct tdb *), M_TDB, M_WAITOK | M_ZERO); } /* * Our hashing function needs to stir things with a non-zero random multiplier * so we cannot be DoS-attacked via choosing of the data to hash. */ int tdb_hash(u_int32_t spi, union sockaddr_union *dst, u_int8_t proto) { SIPHASH_CTX ctx; MUTEX_ASSERT_LOCKED(&tdb_sadb_mtx); SipHash24_Init(&ctx, &tdbkey); SipHash24_Update(&ctx, &spi, sizeof(spi)); SipHash24_Update(&ctx, &proto, sizeof(proto)); SipHash24_Update(&ctx, dst, dst->sa.sa_len); return (SipHash24_End(&ctx) & tdb_hashmask); } /* * Reserve an SPI; the SA is not valid yet though. We use 0 as * an error return value. */ u_int32_t reserve_spi(u_int rdomain, u_int32_t sspi, u_int32_t tspi, union sockaddr_union *src, union sockaddr_union *dst, u_int8_t sproto, int *errval) { struct tdb *tdbp, *exists; u_int32_t spi; int nums; /* Don't accept ranges only encompassing reserved SPIs. */ if (sproto != IPPROTO_IPCOMP && (tspi < sspi || tspi <= SPI_RESERVED_MAX)) { (*errval) = EINVAL; return 0; } if (sproto == IPPROTO_IPCOMP && (tspi < sspi || tspi <= CPI_RESERVED_MAX || tspi >= CPI_PRIVATE_MIN)) { (*errval) = EINVAL; return 0; } /* Limit the range to not include reserved areas. */ if (sspi <= SPI_RESERVED_MAX) sspi = SPI_RESERVED_MAX + 1; /* For IPCOMP the CPI is only 16 bits long, what a good idea.... */ if (sproto == IPPROTO_IPCOMP) { u_int32_t t; if (sspi >= 0x10000) sspi = 0xffff; if (tspi >= 0x10000) tspi = 0xffff; if (sspi > tspi) { t = sspi; sspi = tspi; tspi = t; } } if (sspi == tspi) /* Asking for a specific SPI. */ nums = 1; else nums = 100; /* Arbitrarily chosen */ /* allocate ahead of time to avoid potential sleeping race in loop */ tdbp = tdb_alloc(rdomain); while (nums--) { if (sspi == tspi) /* Specific SPI asked. */ spi = tspi; else /* Range specified */ spi = sspi + arc4random_uniform(tspi - sspi); /* Don't allocate reserved SPIs. */ if (spi >= SPI_RESERVED_MIN && spi <= SPI_RESERVED_MAX) continue; else spi = htonl(spi); /* Check whether we're using this SPI already. */ exists = gettdb(rdomain, spi, dst, sproto); if (exists != NULL) { tdb_unref(exists); continue; } tdbp->tdb_spi = spi; memcpy(&tdbp->tdb_dst.sa, &dst->sa, dst->sa.sa_len); memcpy(&tdbp->tdb_src.sa, &src->sa, src->sa.sa_len); tdbp->tdb_sproto = sproto; tdbp->tdb_flags |= TDBF_INVALID; /* Mark SA invalid for now. */ tdbp->tdb_satype = SADB_SATYPE_UNSPEC; puttdb(tdbp); #ifdef IPSEC /* Setup a "silent" expiration (since TDBF_INVALID's set). */ if (ipsec_keep_invalid > 0) { mtx_enter(&tdbp->tdb_mtx); tdbp->tdb_flags |= TDBF_TIMER; tdbp->tdb_exp_timeout = ipsec_keep_invalid; if (timeout_add_sec(&tdbp->tdb_timer_tmo, ipsec_keep_invalid)) tdb_ref(tdbp); mtx_leave(&tdbp->tdb_mtx); } #endif return spi; } (*errval) = EEXIST; tdb_unref(tdbp); return 0; } /* * An IPSP SAID is really the concatenation of the SPI found in the * packet, the destination address of the packet and the IPsec protocol. * When we receive an IPSP packet, we need to look up its tunnel descriptor * block, based on the SPI in the packet and the destination address (which * is really one of our addresses if we received the packet! */ struct tdb * gettdb_dir(u_int rdomain, u_int32_t spi, union sockaddr_union *dst, u_int8_t proto, int reverse) { u_int32_t hashval; struct tdb *tdbp; NET_ASSERT_LOCKED(); mtx_enter(&tdb_sadb_mtx); hashval = tdb_hash(spi, dst, proto); for (tdbp = tdbh[hashval]; tdbp != NULL; tdbp = tdbp->tdb_hnext) if ((tdbp->tdb_spi == spi) && (tdbp->tdb_sproto == proto) && ((!reverse && tdbp->tdb_rdomain == rdomain) || (reverse && tdbp->tdb_rdomain_post == rdomain)) && !memcmp(&tdbp->tdb_dst, dst, dst->sa.sa_len)) break; tdb_ref(tdbp); mtx_leave(&tdb_sadb_mtx); return tdbp; } /* * Same as gettdb() but compare SRC as well, so we * use the tdbsrc[] hash table. Setting spi to 0 * matches all SPIs. */ struct tdb * gettdbbysrcdst_dir(u_int rdomain, u_int32_t spi, union sockaddr_union *src, union sockaddr_union *dst, u_int8_t proto, int reverse) { u_int32_t hashval; struct tdb *tdbp; union sockaddr_union su_null; mtx_enter(&tdb_sadb_mtx); hashval = tdb_hash(0, src, proto); for (tdbp = tdbsrc[hashval]; tdbp != NULL; tdbp = tdbp->tdb_snext) { if (tdbp->tdb_sproto == proto && (spi == 0 || tdbp->tdb_spi == spi) && ((!reverse && tdbp->tdb_rdomain == rdomain) || (reverse && tdbp->tdb_rdomain_post == rdomain)) && ((tdbp->tdb_flags & TDBF_INVALID) == 0) && (tdbp->tdb_dst.sa.sa_family == AF_UNSPEC || !memcmp(&tdbp->tdb_dst, dst, dst->sa.sa_len)) && !memcmp(&tdbp->tdb_src, src, src->sa.sa_len)) break; } if (tdbp != NULL) { tdb_ref(tdbp); mtx_leave(&tdb_sadb_mtx); return tdbp; } memset(&su_null, 0, sizeof(su_null)); su_null.sa.sa_len = sizeof(struct sockaddr); hashval = tdb_hash(0, &su_null, proto); for (tdbp = tdbsrc[hashval]; tdbp != NULL; tdbp = tdbp->tdb_snext) { if (tdbp->tdb_sproto == proto && (spi == 0 || tdbp->tdb_spi == spi) && ((!reverse && tdbp->tdb_rdomain == rdomain) || (reverse && tdbp->tdb_rdomain_post == rdomain)) && ((tdbp->tdb_flags & TDBF_INVALID) == 0) && (tdbp->tdb_dst.sa.sa_family == AF_UNSPEC || !memcmp(&tdbp->tdb_dst, dst, dst->sa.sa_len)) && tdbp->tdb_src.sa.sa_family == AF_UNSPEC) break; } tdb_ref(tdbp); mtx_leave(&tdb_sadb_mtx); return tdbp; } /* * Check that IDs match. Return true if so. The t* range of * arguments contains information from TDBs; the p* range of * arguments contains information from policies or already * established TDBs. */ int ipsp_aux_match(struct tdb *tdb, struct ipsec_ids *ids, struct sockaddr_encap *pfilter, struct sockaddr_encap *pfiltermask) { if (ids != NULL) if (tdb->tdb_ids == NULL || !ipsp_ids_match(tdb->tdb_ids, ids)) return 0; /* Check for filter matches. */ if (pfilter != NULL && pfiltermask != NULL && tdb->tdb_filter.sen_type) { /* * XXX We should really be doing a subnet-check (see * whether the TDB-associated filter is a subset * of the policy's. For now, an exact match will solve * most problems (all this will do is make every * policy get its own SAs). */ if (memcmp(&tdb->tdb_filter, pfilter, sizeof(struct sockaddr_encap)) || memcmp(&tdb->tdb_filtermask, pfiltermask, sizeof(struct sockaddr_encap))) return 0; } return 1; } /* * Get an SA given the remote address, the security protocol type, and * the desired IDs. */ struct tdb * gettdbbydst(u_int rdomain, union sockaddr_union *dst, u_int8_t sproto, struct ipsec_ids *ids, struct sockaddr_encap *filter, struct sockaddr_encap *filtermask) { u_int32_t hashval; struct tdb *tdbp; mtx_enter(&tdb_sadb_mtx); hashval = tdb_hash(0, dst, sproto); for (tdbp = tdbdst[hashval]; tdbp != NULL; tdbp = tdbp->tdb_dnext) if ((tdbp->tdb_sproto == sproto) && (tdbp->tdb_rdomain == rdomain) && ((tdbp->tdb_flags & TDBF_INVALID) == 0) && (!memcmp(&tdbp->tdb_dst, dst, dst->sa.sa_len))) { /* Check whether IDs match */ if (!ipsp_aux_match(tdbp, ids, filter, filtermask)) continue; break; } tdb_ref(tdbp); mtx_leave(&tdb_sadb_mtx); return tdbp; } /* * Get an SA given the source address, the security protocol type, and * the desired IDs. */ struct tdb * gettdbbysrc(u_int rdomain, union sockaddr_union *src, u_int8_t sproto, struct ipsec_ids *ids, struct sockaddr_encap *filter, struct sockaddr_encap *filtermask) { u_int32_t hashval; struct tdb *tdbp; mtx_enter(&tdb_sadb_mtx); hashval = tdb_hash(0, src, sproto); for (tdbp = tdbsrc[hashval]; tdbp != NULL; tdbp = tdbp->tdb_snext) { if ((tdbp->tdb_sproto == sproto) && (tdbp->tdb_rdomain == rdomain) && ((tdbp->tdb_flags & TDBF_INVALID) == 0) && (!memcmp(&tdbp->tdb_src, src, src->sa.sa_len))) { /* Check whether IDs match */ if (!ipsp_aux_match(tdbp, ids, filter, filtermask)) continue; break; } } tdb_ref(tdbp); mtx_leave(&tdb_sadb_mtx); return tdbp; } #ifdef DDB #define NBUCKETS 16 void tdb_hashstats(void) { int i, cnt, buckets[NBUCKETS]; struct tdb *tdbp; if (tdbh == NULL) { db_printf("no tdb hash table\n"); return; } memset(buckets, 0, sizeof(buckets)); for (i = 0; i <= tdb_hashmask; i++) { cnt = 0; for (tdbp = tdbh[i]; cnt < NBUCKETS - 1 && tdbp != NULL; tdbp = tdbp->tdb_hnext) cnt++; buckets[cnt]++; } db_printf("tdb cnt\t\tbucket cnt\n"); for (i = 0; i < NBUCKETS; i++) if (buckets[i] > 0) db_printf("%d%s\t\t%d\n", i, i == NBUCKETS - 1 ? "+" : "", buckets[i]); } #define DUMP(m, f) pr("%18s: " f "\n", #m, tdb->tdb_##m) void tdb_printit(void *addr, int full, int (*pr)(const char *, ...)) { struct tdb *tdb = addr; char buf[INET6_ADDRSTRLEN]; if (full) { pr("tdb at %p\n", tdb); DUMP(hnext, "%p"); DUMP(dnext, "%p"); DUMP(snext, "%p"); DUMP(inext, "%p"); DUMP(onext, "%p"); DUMP(xform, "%p"); pr("%18s: %d\n", "refcnt", tdb->tdb_refcnt.r_refs); DUMP(encalgxform, "%p"); DUMP(authalgxform, "%p"); DUMP(compalgxform, "%p"); pr("%18s: %b\n", "flags", tdb->tdb_flags, TDBF_BITS); /* tdb_XXX_tmo */ DUMP(seq, "%d"); DUMP(exp_allocations, "%d"); DUMP(soft_allocations, "%d"); DUMP(cur_allocations, "%d"); DUMP(exp_bytes, "%lld"); DUMP(soft_bytes, "%lld"); DUMP(cur_bytes, "%lld"); DUMP(exp_timeout, "%lld"); DUMP(soft_timeout, "%lld"); DUMP(established, "%lld"); DUMP(first_use, "%lld"); DUMP(soft_first_use, "%lld"); DUMP(exp_first_use, "%lld"); DUMP(last_used, "%lld"); DUMP(last_marked, "%lld"); /* tdb_data */ DUMP(cryptoid, "%lld"); pr("%18s: %08x\n", "tdb_spi", ntohl(tdb->tdb_spi)); DUMP(amxkeylen, "%d"); DUMP(emxkeylen, "%d"); DUMP(ivlen, "%d"); DUMP(sproto, "%d"); DUMP(wnd, "%d"); DUMP(satype, "%d"); DUMP(updates, "%d"); pr("%18s: %s\n", "dst", ipsp_address(&tdb->tdb_dst, buf, sizeof(buf))); pr("%18s: %s\n", "src", ipsp_address(&tdb->tdb_src, buf, sizeof(buf))); DUMP(amxkey, "%p"); DUMP(emxkey, "%p"); DUMP(rpl, "%lld"); /* tdb_seen */ /* tdb_iv */ DUMP(ids, "%p"); DUMP(ids_swapped, "%d"); DUMP(mtu, "%d"); DUMP(mtutimeout, "%lld"); pr("%18s: %d\n", "udpencap_port", ntohs(tdb->tdb_udpencap_port)); DUMP(tag, "%d"); DUMP(tap, "%d"); DUMP(rdomain, "%d"); DUMP(rdomain_post, "%d"); /* tdb_filter */ /* tdb_filtermask */ /* tdb_policy_head */ /* tdb_sync_entry */ } else { pr("%p:", tdb); pr(" %08x", ntohl(tdb->tdb_spi)); pr(" %s", ipsp_address(&tdb->tdb_src, buf, sizeof(buf))); pr("->%s", ipsp_address(&tdb->tdb_dst, buf, sizeof(buf))); pr(":%d", tdb->tdb_sproto); pr(" #%d", tdb->tdb_refcnt.r_refs); pr(" %08x\n", tdb->tdb_flags); } } #undef DUMP #endif /* DDB */ int tdb_walk(u_int rdomain, int (*walker)(struct tdb *, void *, int), void *arg) { SIMPLEQ_HEAD(, tdb) tdblist; struct tdb *tdbp; int i, rval; /* * The walker may sleep. So we cannot hold the tdb_sadb_mtx while * traversing the tdb_hnext list. Create a new tdb_walk list with * exclusive netlock protection. */ NET_ASSERT_LOCKED_EXCLUSIVE(); SIMPLEQ_INIT(&tdblist); mtx_enter(&tdb_sadb_mtx); for (i = 0; i <= tdb_hashmask; i++) { for (tdbp = tdbh[i]; tdbp != NULL; tdbp = tdbp->tdb_hnext) { if (rdomain != tdbp->tdb_rdomain) continue; tdb_ref(tdbp); SIMPLEQ_INSERT_TAIL(&tdblist, tdbp, tdb_walk); } } mtx_leave(&tdb_sadb_mtx); rval = 0; while ((tdbp = SIMPLEQ_FIRST(&tdblist)) != NULL) { SIMPLEQ_REMOVE_HEAD(&tdblist, tdb_walk); if (rval == 0) rval = walker(tdbp, arg, SIMPLEQ_EMPTY(&tdblist)); tdb_unref(tdbp); } return rval; } void tdb_timeout(void *v) { struct tdb *tdb = v; NET_LOCK(); if (tdb->tdb_flags & TDBF_TIMER) { /* If it's an "invalid" TDB do a silent expiration. */ if (!(tdb->tdb_flags & TDBF_INVALID)) { #ifdef IPSEC ipsecstat_inc(ipsec_exctdb); #endif /* IPSEC */ pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); } tdb_delete(tdb); } /* decrement refcount of the timeout argument */ tdb_unref(tdb); NET_UNLOCK(); } void tdb_firstuse(void *v) { struct tdb *tdb = v; NET_LOCK(); if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE) { /* If the TDB hasn't been used, don't renew it. */ if (tdb->tdb_first_use != 0) { #ifdef IPSEC ipsecstat_inc(ipsec_exctdb); #endif /* IPSEC */ pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); } tdb_delete(tdb); } /* decrement refcount of the timeout argument */ tdb_unref(tdb); NET_UNLOCK(); } void tdb_addtimeouts(struct tdb *tdbp) { mtx_enter(&tdbp->tdb_mtx); if (tdbp->tdb_flags & TDBF_TIMER) { if (timeout_add_sec(&tdbp->tdb_timer_tmo, tdbp->tdb_exp_timeout)) tdb_ref(tdbp); } if (tdbp->tdb_flags & TDBF_SOFT_TIMER) { if (timeout_add_sec(&tdbp->tdb_stimer_tmo, tdbp->tdb_soft_timeout)) tdb_ref(tdbp); } mtx_leave(&tdbp->tdb_mtx); } void tdb_soft_timeout(void *v) { struct tdb *tdb = v; NET_LOCK(); mtx_enter(&tdb->tdb_mtx); if (tdb->tdb_flags & TDBF_SOFT_TIMER) { tdb->tdb_flags &= ~TDBF_SOFT_TIMER; mtx_leave(&tdb->tdb_mtx); /* Soft expirations. */ pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT); } else mtx_leave(&tdb->tdb_mtx); /* decrement refcount of the timeout argument */ tdb_unref(tdb); NET_UNLOCK(); } void tdb_soft_firstuse(void *v) { struct tdb *tdb = v; NET_LOCK(); mtx_enter(&tdb->tdb_mtx); if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE) { tdb->tdb_flags &= ~TDBF_SOFT_FIRSTUSE; mtx_leave(&tdb->tdb_mtx); /* If the TDB hasn't been used, don't renew it. */ if (tdb->tdb_first_use != 0) pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT); } else mtx_leave(&tdb->tdb_mtx); /* decrement refcount of the timeout argument */ tdb_unref(tdb); NET_UNLOCK(); } int tdb_rehash(void) { struct tdb **new_tdbh, **new_tdbdst, **new_srcaddr, *tdbp, *tdbnp; u_int i, old_hashmask; u_int32_t hashval; MUTEX_ASSERT_LOCKED(&tdb_sadb_mtx); old_hashmask = tdb_hashmask; tdb_hashmask = (tdb_hashmask << 1) | 1; arc4random_buf(&tdbkey, sizeof(tdbkey)); new_tdbh = mallocarray(tdb_hashmask + 1, sizeof(struct tdb *), M_TDB, M_NOWAIT | M_ZERO); new_tdbdst = mallocarray(tdb_hashmask + 1, sizeof(struct tdb *), M_TDB, M_NOWAIT | M_ZERO); new_srcaddr = mallocarray(tdb_hashmask + 1, sizeof(struct tdb *), M_TDB, M_NOWAIT | M_ZERO); if (new_tdbh == NULL || new_tdbdst == NULL || new_srcaddr == NULL) { free(new_tdbh, M_TDB, 0); free(new_tdbdst, M_TDB, 0); free(new_srcaddr, M_TDB, 0); return (ENOMEM); } for (i = 0; i <= old_hashmask; i++) { for (tdbp = tdbh[i]; tdbp != NULL; tdbp = tdbnp) { tdbnp = tdbp->tdb_hnext; hashval = tdb_hash(tdbp->tdb_spi, &tdbp->tdb_dst, tdbp->tdb_sproto); tdbp->tdb_hnext = new_tdbh[hashval]; new_tdbh[hashval] = tdbp; } for (tdbp = tdbdst[i]; tdbp != NULL; tdbp = tdbnp) { tdbnp = tdbp->tdb_dnext; hashval = tdb_hash(0, &tdbp->tdb_dst, tdbp->tdb_sproto); tdbp->tdb_dnext = new_tdbdst[hashval]; new_tdbdst[hashval] = tdbp; } for (tdbp = tdbsrc[i]; tdbp != NULL; tdbp = tdbnp) { tdbnp = tdbp->tdb_snext; hashval = tdb_hash(0, &tdbp->tdb_src, tdbp->tdb_sproto); tdbp->tdb_snext = new_srcaddr[hashval]; new_srcaddr[hashval] = tdbp; } } free(tdbh, M_TDB, 0); tdbh = new_tdbh; free(tdbdst, M_TDB, 0); tdbdst = new_tdbdst; free(tdbsrc, M_TDB, 0); tdbsrc = new_srcaddr; return 0; } /* * Add TDB in the hash table. */ void puttdb(struct tdb *tdbp) { mtx_enter(&tdb_sadb_mtx); puttdb_locked(tdbp); mtx_leave(&tdb_sadb_mtx); } void puttdb_locked(struct tdb *tdbp) { u_int32_t hashval; MUTEX_ASSERT_LOCKED(&tdb_sadb_mtx); hashval = tdb_hash(tdbp->tdb_spi, &tdbp->tdb_dst, tdbp->tdb_sproto); /* * Rehash if this tdb would cause a bucket to have more than * two items and if the number of tdbs exceed 10% of the * bucket count. This number is arbitrarily chosen and is * just a measure to not keep rehashing when adding and * removing tdbs which happens to always end up in the same * bucket, which is not uncommon when doing manual keying. */ if (tdbh[hashval] != NULL && tdbh[hashval]->tdb_hnext != NULL && tdb_count * 10 > tdb_hashmask + 1) { if (tdb_rehash() == 0) hashval = tdb_hash(tdbp->tdb_spi, &tdbp->tdb_dst, tdbp->tdb_sproto); } tdbp->tdb_hnext = tdbh[hashval]; tdbh[hashval] = tdbp; tdb_count++; #ifdef IPSEC if ((tdbp->tdb_flags & (TDBF_INVALID|TDBF_TUNNELING)) == TDBF_TUNNELING) ipsecstat_inc(ipsec_tunnels); #endif /* IPSEC */ ipsec_last_added = getuptime(); if (ISSET(tdbp->tdb_flags, TDBF_IFACE)) { #if NSEC > 0 sec_tdb_insert(tdbp); #endif return; } hashval = tdb_hash(0, &tdbp->tdb_dst, tdbp->tdb_sproto); tdbp->tdb_dnext = tdbdst[hashval]; tdbdst[hashval] = tdbp; hashval = tdb_hash(0, &tdbp->tdb_src, tdbp->tdb_sproto); tdbp->tdb_snext = tdbsrc[hashval]; tdbsrc[hashval] = tdbp; } void tdb_unlink(struct tdb *tdbp) { mtx_enter(&tdb_sadb_mtx); tdb_unlink_locked(tdbp); mtx_leave(&tdb_sadb_mtx); } void tdb_unlink_locked(struct tdb *tdbp) { struct tdb *tdbpp; u_int32_t hashval; MUTEX_ASSERT_LOCKED(&tdb_sadb_mtx); hashval = tdb_hash(tdbp->tdb_spi, &tdbp->tdb_dst, tdbp->tdb_sproto); if (tdbh[hashval] == tdbp) { tdbh[hashval] = tdbp->tdb_hnext; } else { for (tdbpp = tdbh[hashval]; tdbpp != NULL; tdbpp = tdbpp->tdb_hnext) { if (tdbpp->tdb_hnext == tdbp) { tdbpp->tdb_hnext = tdbp->tdb_hnext; break; } } } tdbp->tdb_hnext = NULL; tdb_count--; #ifdef IPSEC if ((tdbp->tdb_flags & (TDBF_INVALID|TDBF_TUNNELING)) == TDBF_TUNNELING) { ipsecstat_dec(ipsec_tunnels); ipsecstat_inc(ipsec_prevtunnels); } #endif /* IPSEC */ if (ISSET(tdbp->tdb_flags, TDBF_IFACE)) { #if NSEC > 0 sec_tdb_remove(tdbp); #endif return; } hashval = tdb_hash(0, &tdbp->tdb_dst, tdbp->tdb_sproto); if (tdbdst[hashval] == tdbp) { tdbdst[hashval] = tdbp->tdb_dnext; } else { for (tdbpp = tdbdst[hashval]; tdbpp != NULL; tdbpp = tdbpp->tdb_dnext) { if (tdbpp->tdb_dnext == tdbp) { tdbpp->tdb_dnext = tdbp->tdb_dnext; break; } } } tdbp->tdb_dnext = NULL; hashval = tdb_hash(0, &tdbp->tdb_src, tdbp->tdb_sproto); if (tdbsrc[hashval] == tdbp) { tdbsrc[hashval] = tdbp->tdb_snext; } else { for (tdbpp = tdbsrc[hashval]; tdbpp != NULL; tdbpp = tdbpp->tdb_snext) { if (tdbpp->tdb_snext == tdbp) { tdbpp->tdb_snext = tdbp->tdb_snext; break; } } } tdbp->tdb_snext = NULL; } void tdb_cleanspd(struct tdb *tdbp) { struct ipsec_policy *ipo; mtx_enter(&ipo_tdb_mtx); while ((ipo = TAILQ_FIRST(&tdbp->tdb_policy_head)) != NULL) { TAILQ_REMOVE(&tdbp->tdb_policy_head, ipo, ipo_tdb_next); tdb_unref(ipo->ipo_tdb); ipo->ipo_tdb = NULL; ipo->ipo_last_searched = 0; /* Force a re-search. */ } mtx_leave(&ipo_tdb_mtx); } void tdb_unbundle(struct tdb *tdbp) { if (tdbp->tdb_onext != NULL) { if (tdbp->tdb_onext->tdb_inext == tdbp) { tdb_unref(tdbp); /* to us */ tdbp->tdb_onext->tdb_inext = NULL; } tdb_unref(tdbp->tdb_onext); /* to other */ tdbp->tdb_onext = NULL; } if (tdbp->tdb_inext != NULL) { if (tdbp->tdb_inext->tdb_onext == tdbp) { tdb_unref(tdbp); /* to us */ tdbp->tdb_inext->tdb_onext = NULL; } tdb_unref(tdbp->tdb_inext); /* to other */ tdbp->tdb_inext = NULL; } } void tdb_deltimeouts(struct tdb *tdbp) { mtx_enter(&tdbp->tdb_mtx); tdbp->tdb_flags &= ~(TDBF_FIRSTUSE | TDBF_SOFT_FIRSTUSE | TDBF_TIMER | TDBF_SOFT_TIMER); if (timeout_del(&tdbp->tdb_timer_tmo)) tdb_unref(tdbp); if (timeout_del(&tdbp->tdb_first_tmo)) tdb_unref(tdbp); if (timeout_del(&tdbp->tdb_stimer_tmo)) tdb_unref(tdbp); if (timeout_del(&tdbp->tdb_sfirst_tmo)) tdb_unref(tdbp); mtx_leave(&tdbp->tdb_mtx); } struct tdb * tdb_ref(struct tdb *tdb) { if (tdb == NULL) return NULL; refcnt_take(&tdb->tdb_refcnt); return tdb; } void tdb_unref(struct tdb *tdb) { if (tdb == NULL) return; if (refcnt_rele(&tdb->tdb_refcnt) == 0) return; tdb_free(tdb); } void tdb_delete(struct tdb *tdbp) { NET_ASSERT_LOCKED(); mtx_enter(&tdbp->tdb_mtx); if (tdbp->tdb_flags & TDBF_DELETED) { mtx_leave(&tdbp->tdb_mtx); return; } tdbp->tdb_flags |= TDBF_DELETED; mtx_leave(&tdbp->tdb_mtx); tdb_unlink(tdbp); /* cleanup SPD references */ tdb_cleanspd(tdbp); /* release tdb_onext/tdb_inext references */ tdb_unbundle(tdbp); /* delete timeouts and release references */ tdb_deltimeouts(tdbp); /* release the reference for tdb_unlink() */ tdb_unref(tdbp); } /* * Allocate a TDB and initialize a few basic fields. */ struct tdb * tdb_alloc(u_int rdomain) { struct tdb *tdbp; tdbp = pool_get(&tdb_pool, PR_WAITOK | PR_ZERO); refcnt_init_trace(&tdbp->tdb_refcnt, DT_REFCNT_IDX_TDB); mtx_init(&tdbp->tdb_mtx, IPL_SOFTNET); TAILQ_INIT(&tdbp->tdb_policy_head); /* Record establishment time. */ tdbp->tdb_established = gettime(); /* Save routing domain */ tdbp->tdb_rdomain = rdomain; tdbp->tdb_rdomain_post = rdomain; /* Initialize counters. */ tdbp->tdb_counters = counters_alloc(tdb_ncounters); /* Initialize timeouts. */ timeout_set_proc(&tdbp->tdb_timer_tmo, tdb_timeout, tdbp); timeout_set_proc(&tdbp->tdb_first_tmo, tdb_firstuse, tdbp); timeout_set_proc(&tdbp->tdb_stimer_tmo, tdb_soft_timeout, tdbp); timeout_set_proc(&tdbp->tdb_sfirst_tmo, tdb_soft_firstuse, tdbp); return tdbp; } void tdb_free(struct tdb *tdbp) { NET_ASSERT_LOCKED(); if (tdbp->tdb_xform) { (*(tdbp->tdb_xform->xf_zeroize))(tdbp); tdbp->tdb_xform = NULL; } #if NPFSYNC > 0 && defined(IPSEC) /* Cleanup pfsync references */ pfsync_delete_tdb(tdbp); #endif KASSERT(TAILQ_EMPTY(&tdbp->tdb_policy_head)); if (tdbp->tdb_ids) { ipsp_ids_free(tdbp->tdb_ids); tdbp->tdb_ids = NULL; } #if NPF > 0 if (tdbp->tdb_tag) { pf_tag_unref(tdbp->tdb_tag); tdbp->tdb_tag = 0; } #endif counters_free(tdbp->tdb_counters, tdb_ncounters); KASSERT(tdbp->tdb_onext == NULL); KASSERT(tdbp->tdb_inext == NULL); /* Remove expiration timeouts. */ KASSERT(timeout_pending(&tdbp->tdb_timer_tmo) == 0); KASSERT(timeout_pending(&tdbp->tdb_first_tmo) == 0); KASSERT(timeout_pending(&tdbp->tdb_stimer_tmo) == 0); KASSERT(timeout_pending(&tdbp->tdb_sfirst_tmo) == 0); pool_put(&tdb_pool, tdbp); } /* * Do further initializations of a TDB. */ int tdb_init(struct tdb *tdbp, u_int16_t alg, struct ipsecinit *ii) { const struct xformsw *xsp; int err; #ifdef ENCDEBUG char buf[INET6_ADDRSTRLEN]; #endif for (xsp = xformsw; xsp < xformswNXFORMSW; xsp++) { if (xsp->xf_type == alg) { err = (*(xsp->xf_init))(tdbp, xsp, ii); return err; } } DPRINTF("no alg %d for spi %08x, addr %s, proto %d", alg, ntohl(tdbp->tdb_spi), ipsp_address(&tdbp->tdb_dst, buf, sizeof(buf)), tdbp->tdb_sproto); return EINVAL; } #if defined(DDB) || defined(ENCDEBUG) /* Return a printable string for the address. */ const char * ipsp_address(union sockaddr_union *sa, char *buf, socklen_t size) { switch (sa->sa.sa_family) { case AF_INET: return inet_ntop(AF_INET, &sa->sin.sin_addr, buf, (size_t)size); #ifdef INET6 case AF_INET6: return inet_ntop(AF_INET6, &sa->sin6.sin6_addr, buf, (size_t)size); #endif /* INET6 */ default: return "(unknown address family)"; } } #endif /* DDB || ENCDEBUG */ /* Check whether an IP{4,6} address is unspecified. */ int ipsp_is_unspecified(union sockaddr_union addr) { switch (addr.sa.sa_family) { case AF_INET: if (addr.sin.sin_addr.s_addr == INADDR_ANY) return 1; else return 0; #ifdef INET6 case AF_INET6: if (IN6_IS_ADDR_UNSPECIFIED(&addr.sin6.sin6_addr)) return 1; else return 0; #endif /* INET6 */ case 0: /* No family set. */ default: return 1; } } int ipsp_ids_match(struct ipsec_ids *a, struct ipsec_ids *b) { return a == b; } struct ipsec_ids * ipsp_ids_insert(struct ipsec_ids *ids) { struct ipsec_ids *found; u_int32_t start_flow; mtx_enter(&ipsec_flows_mtx); found = RBT_INSERT(ipsec_ids_tree, &ipsec_ids_tree, ids); if (found) { /* if refcount was zero, then timeout is running */ if ((++found->id_refcount) == 1) { LIST_REMOVE(found, id_gc_list); if (LIST_EMPTY(&ipsp_ids_gc_list)) timeout_del(&ipsp_ids_gc_timeout); } mtx_leave (&ipsec_flows_mtx); DPRINTF("ids %p count %d", found, found->id_refcount); return found; } ids->id_refcount = 1; ids->id_flow = start_flow = ipsec_ids_next_flow; if (++ipsec_ids_next_flow == 0) ipsec_ids_next_flow = 1; while (RBT_INSERT(ipsec_ids_flows, &ipsec_ids_flows, ids) != NULL) { ids->id_flow = ipsec_ids_next_flow; if (++ipsec_ids_next_flow == 0) ipsec_ids_next_flow = 1; if (ipsec_ids_next_flow == start_flow) { RBT_REMOVE(ipsec_ids_tree, &ipsec_ids_tree, ids); mtx_leave(&ipsec_flows_mtx); DPRINTF("ipsec_ids_next_flow exhausted %u", start_flow); return NULL; } } mtx_leave(&ipsec_flows_mtx); DPRINTF("new ids %p flow %u", ids, ids->id_flow); return ids; } struct ipsec_ids * ipsp_ids_lookup(u_int32_t ipsecflowinfo) { struct ipsec_ids key; struct ipsec_ids *ids; key.id_flow = ipsecflowinfo; mtx_enter(&ipsec_flows_mtx); ids = RBT_FIND(ipsec_ids_flows, &ipsec_ids_flows, &key); if (ids != NULL) { if (ids->id_refcount != 0) ids->id_refcount++; else ids = NULL; } mtx_leave(&ipsec_flows_mtx); return ids; } /* free ids only from delayed timeout */ void ipsp_ids_gc(void *arg) { struct ipsec_ids *ids, *tids; mtx_enter(&ipsec_flows_mtx); LIST_FOREACH_SAFE(ids, &ipsp_ids_gc_list, id_gc_list, tids) { KASSERT(ids->id_refcount == 0); DPRINTF("ids %p count %d", ids, ids->id_refcount); if ((--ids->id_gc_ttl) > 0) continue; LIST_REMOVE(ids, id_gc_list); RBT_REMOVE(ipsec_ids_tree, &ipsec_ids_tree, ids); RBT_REMOVE(ipsec_ids_flows, &ipsec_ids_flows, ids); free(ids->id_local, M_CREDENTIALS, 0); free(ids->id_remote, M_CREDENTIALS, 0); free(ids, M_CREDENTIALS, 0); } if (!LIST_EMPTY(&ipsp_ids_gc_list)) timeout_add_sec(&ipsp_ids_gc_timeout, 1); mtx_leave(&ipsec_flows_mtx); } /* decrements refcount, actual free happens in gc */ void ipsp_ids_free(struct ipsec_ids *ids) { if (ids == NULL) return; mtx_enter(&ipsec_flows_mtx); /* * If the refcount becomes zero, then a timeout is started. This * timeout must be cancelled if refcount is increased from zero. */ DPRINTF("ids %p count %d", ids, ids->id_refcount); KASSERT(ids->id_refcount > 0); if ((--ids->id_refcount) > 0) { mtx_leave(&ipsec_flows_mtx); return; } /* * Add second for the case ipsp_ids_gc() is already running and * awaits netlock to be released. */ ids->id_gc_ttl = ipsec_ids_idle + 1; if (LIST_EMPTY(&ipsp_ids_gc_list)) timeout_add_sec(&ipsp_ids_gc_timeout, 1); LIST_INSERT_HEAD(&ipsp_ids_gc_list, ids, id_gc_list); mtx_leave(&ipsec_flows_mtx); } static int ipsp_id_cmp(struct ipsec_id *a, struct ipsec_id *b) { if (a->type > b->type) return 1; if (a->type < b->type) return -1; if (a->len > b->len) return 1; if (a->len < b->len) return -1; return memcmp(a + 1, b + 1, a->len); } static inline int ipsp_ids_cmp(const struct ipsec_ids *a, const struct ipsec_ids *b) { int ret; ret = ipsp_id_cmp(a->id_remote, b->id_remote); if (ret != 0) return ret; return ipsp_id_cmp(a->id_local, b->id_local); } static inline int ipsp_ids_flow_cmp(const struct ipsec_ids *a, const struct ipsec_ids *b) { if (a->id_flow > b->id_flow) return 1; if (a->id_flow < b->id_flow) return -1; return 0; }
15 7 11 5 5 5 4 1 3 10 2 8 45 1 1 3 39 10 1 9 10 30 29 29 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 /* $OpenBSD: cons.c,v 1.30 2022/07/02 08:50:41 visa Exp $ */ /* $NetBSD: cons.c,v 1.30 1996/04/08 19:57:30 jonathan Exp $ */ /* * Copyright (c) 1988 University of Utah. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: Utah $Hdr: cons.c 1.7 92/01/21$ * * @(#)cons.c 8.2 (Berkeley) 1/12/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/ioctl.h> #include <sys/tty.h> #include <sys/conf.h> #include <sys/vnode.h> #include <dev/cons.h> struct tty *constty = NULL; /* virtual console output device */ struct vnode *cn_devvp = NULLVP; /* vnode for underlying device. */ int cnopen(dev_t dev, int flag, int mode, struct proc *p) { dev_t cndev; if (cn_tab == NULL) return (0); /* * always open the 'real' console device, so we don't get nailed * later. This follows normal device semantics; they always get * open() calls. */ cndev = cn_tab->cn_dev; if (cndev == NODEV) return (ENXIO); #ifdef DIAGNOSTIC if (cndev == dev) panic("cnopen: recursive"); #endif if (cn_devvp == NULLVP) { /* try to get a reference on its vnode, but fail silently */ cdevvp(cndev, &cn_devvp); } return ((*cdevsw[major(cndev)].d_open)(cndev, flag, mode, p)); } int cnclose(dev_t dev, int flag, int mode, struct proc *p) { struct vnode *vp; if (cn_tab == NULL) return (0); /* * If the real console isn't otherwise open, close it. * If it's otherwise open, don't close it, because that'll * screw up others who have it open. */ dev = cn_tab->cn_dev; if (cn_devvp != NULLVP) { /* release our reference to real dev's vnode */ vrele(cn_devvp); cn_devvp = NULLVP; } if (vfinddev(dev, VCHR, &vp) && vcount(vp)) return (0); return ((*cdevsw[major(dev)].d_close)(dev, flag, mode, p)); } int cnread(dev_t dev, struct uio *uio, int flag) { /* * If we would redirect input, punt. This will keep strange * things from happening to people who are using the real * console. Nothing should be using /dev/console for * input (except a shell in single-user mode, but then, * one wouldn't TIOCCONS then). */ if (constty != NULL) return 0; else if (cn_tab == NULL) return ENXIO; dev = cn_tab->cn_dev; return ((*cdevsw[major(dev)].d_read)(dev, uio, flag)); } int cnwrite(dev_t dev, struct uio *uio, int flag) { /* * Redirect output, if that's appropriate. * If there's no real console, return ENXIO. */ if (constty != NULL) dev = constty->t_dev; else if (cn_tab == NULL) return ENXIO; else dev = cn_tab->cn_dev; return ((*cdevsw[major(dev)].d_write)(dev, uio, flag)); } int cnstop(struct tty *tp, int flag) { return (0); } int cnioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { int error; /* * Superuser can always use this to wrest control of console * output from the "virtual" console. */ if (cmd == TIOCCONS && constty != NULL) { error = suser(p); if (error) return (error); constty = NULL; return (0); } /* * Redirect the ioctl, if that's appropriate. * Note that strange things can happen, if a program does * ioctls on /dev/console, then the console is redirected * out from under it. */ if (constty != NULL) dev = constty->t_dev; else if (cn_tab == NULL) return ENXIO; else dev = cn_tab->cn_dev; return ((*cdevsw[major(dev)].d_ioctl)(dev, cmd, data, flag, p)); } int cnkqfilter(dev_t dev, struct knote *kn) { /* * Redirect output, if that's appropriate. * If there's no real console, return 1. */ if (constty != NULL) dev = constty->t_dev; else if (cn_tab == NULL) return (ENXIO); else dev = cn_tab->cn_dev; if (cdevsw[major(dev)].d_kqfilter) return ((*cdevsw[major(dev)].d_kqfilter)(dev, kn)); return (EOPNOTSUPP); } int cngetc(void) { if (cn_tab == NULL) return (0); return ((*cn_tab->cn_getc)(cn_tab->cn_dev)); } void cnputc(int c) { if (cn_tab == NULL) return; if (c) { (*cn_tab->cn_putc)(cn_tab->cn_dev, c); if (c == '\n') (*cn_tab->cn_putc)(cn_tab->cn_dev, '\r'); } } void cnpollc(int on) { static int refcount = 0; if (cn_tab == NULL) return; if (!on) --refcount; if (refcount == 0) (*cn_tab->cn_pollc)(cn_tab->cn_dev, on); if (on) ++refcount; } void nullcnpollc(dev_t dev, int on) { } void cnbell(u_int pitch, u_int period, u_int volume) { if (cn_tab == NULL || cn_tab->cn_bell == NULL) return; (*cn_tab->cn_bell)(cn_tab->cn_dev, pitch, period, volume); }
3 3 3 3 3 2 2 3 5 5 2 1 1 1 1 1 1 32 32 13 6 3 11 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 5 1 1 4 12 5 1 1 6 7 7 4 2 1 4 5 2 2 1 16 1 3 1 1 7 4 10 3 3 6 8 5 1 2 3 2 1 1 2 2 2 3 3 1 3 5 5 7 2 13 2 7 1 1 1 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 /* $OpenBSD: sysv_sem.c,v 1.63 2022/09/28 13:21:13 mbuhl Exp $ */ /* $NetBSD: sysv_sem.c,v 1.26 1996/02/09 19:00:25 christos Exp $ */ /* * Copyright (c) 2002,2003 Todd C. Miller <millert@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Sponsored in part by the Defense Advanced Research Projects * Agency (DARPA) and Air Force Research Laboratory, Air Force * Materiel Command, USAF, under agreement number F39502-99-1-0512. */ /* * Implementation of SVID semaphores * * Author: Daniel Boulet * * This software is provided ``AS IS'' without any warranties of any kind. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/sem.h> #include <sys/sysctl.h> #include <sys/malloc.h> #include <sys/pool.h> #include <sys/mount.h> #include <sys/syscallargs.h> #ifdef SEM_DEBUG #define DPRINTF(x) printf x #else #define DPRINTF(x) #endif int semtot = 0; int semutot = 0; struct semid_ds **sema; /* semaphore id list */ SLIST_HEAD(, sem_undo) semu_list; /* list of undo structures */ struct pool sema_pool; /* pool for struct semid_ds */ struct pool semu_pool; /* pool for struct sem_undo (SEMUSZ) */ unsigned short *semseqs; /* array of sem sequence numbers */ struct sem_undo *semu_alloc(struct process *); int semundo_adjust(struct proc *, struct sem_undo **, int, int, int); void semundo_clear(int, int); void seminit(void) { pool_init(&sema_pool, sizeof(struct semid_ds), 0, 0, PR_WAITOK, "semapl", NULL); pool_init(&semu_pool, SEMUSZ, 0, 0, PR_WAITOK, "semupl", NULL); sema = mallocarray(seminfo.semmni, sizeof(struct semid_ds *), M_SEM, M_WAITOK|M_ZERO); semseqs = mallocarray(seminfo.semmni, sizeof(unsigned short), M_SEM, M_WAITOK|M_ZERO); SLIST_INIT(&semu_list); } /* * Allocate a new sem_undo structure for a process * (returns ptr to structure or NULL if no more room) */ struct sem_undo * semu_alloc(struct process *pr) { struct sem_undo *suptr, *sutmp; if (semutot == seminfo.semmnu) return (NULL); /* no space */ /* * Allocate a semu w/o waiting if possible. * If we do have to wait, we must check to verify that a semu * with un_proc == pr has not been allocated in the meantime. */ semutot++; if ((suptr = pool_get(&semu_pool, PR_NOWAIT)) == NULL) { sutmp = pool_get(&semu_pool, PR_WAITOK); SLIST_FOREACH(suptr, &semu_list, un_next) { if (suptr->un_proc == pr) { pool_put(&semu_pool, sutmp); semutot--; return (suptr); } } suptr = sutmp; } suptr->un_cnt = 0; suptr->un_proc = pr; SLIST_INSERT_HEAD(&semu_list, suptr, un_next); return (suptr); } /* * Adjust a particular entry for a particular proc */ int semundo_adjust(struct proc *p, struct sem_undo **supptr, int semid, int semnum, int adjval) { struct process *pr = p->p_p; struct sem_undo *suptr; struct undo *sunptr; int i; /* * Look for and remember the sem_undo if the caller doesn't provide it. */ suptr = *supptr; if (suptr == NULL) { SLIST_FOREACH(suptr, &semu_list, un_next) { if (suptr->un_proc == pr) { *supptr = suptr; break; } } if (suptr == NULL) { if (adjval == 0) return (0); suptr = semu_alloc(p->p_p); if (suptr == NULL) return (ENOSPC); *supptr = suptr; } } /* * Look for the requested entry and adjust it * (delete if adjval becomes 0). */ sunptr = &suptr->un_ent[0]; for (i = 0; i < suptr->un_cnt; i++, sunptr++) { if (sunptr->un_id != semid || sunptr->un_num != semnum) continue; if (adjval == 0) sunptr->un_adjval = 0; else sunptr->un_adjval += adjval; if (sunptr->un_adjval != 0) return (0); if (--suptr->un_cnt == 0) { *supptr = NULL; SLIST_REMOVE(&semu_list, suptr, sem_undo, un_next); pool_put(&semu_pool, suptr); semutot--; } else if (i < suptr->un_cnt) suptr->un_ent[i] = suptr->un_ent[suptr->un_cnt]; return (0); } /* Didn't find the right entry - create it */ if (adjval == 0) return (0); if (suptr->un_cnt == SEMUME) return (EINVAL); sunptr = &suptr->un_ent[suptr->un_cnt]; suptr->un_cnt++; sunptr->un_adjval = adjval; sunptr->un_id = semid; sunptr->un_num = semnum; return (0); } void semundo_clear(int semid, int semnum) { struct sem_undo *suptr = SLIST_FIRST(&semu_list); struct sem_undo *suprev = NULL; struct undo *sunptr; int i; while (suptr != NULL) { sunptr = &suptr->un_ent[0]; for (i = 0; i < suptr->un_cnt; i++, sunptr++) { if (sunptr->un_id == semid) { if (semnum == -1 || sunptr->un_num == semnum) { suptr->un_cnt--; if (i < suptr->un_cnt) { suptr->un_ent[i] = suptr->un_ent[suptr->un_cnt]; i--, sunptr--; } } if (semnum != -1) break; } } if (suptr->un_cnt == 0) { struct sem_undo *sutmp = suptr; if (suptr == SLIST_FIRST(&semu_list)) SLIST_REMOVE_HEAD(&semu_list, un_next); else SLIST_REMOVE_AFTER(suprev, un_next); suptr = SLIST_NEXT(suptr, un_next); pool_put(&semu_pool, sutmp); semutot--; } else { suprev = suptr; suptr = SLIST_NEXT(suptr, un_next); } } } int sys___semctl(struct proc *p, void *v, register_t *retval) { struct sys___semctl_args /* { syscallarg(int) semid; syscallarg(int) semnum; syscallarg(int) cmd; syscallarg(union semun *) arg; } */ *uap = v; struct ucred *cred = p->p_ucred; int semid = SCARG(uap, semid); int semnum = SCARG(uap, semnum); int cmd = SCARG(uap, cmd); union semun arg, *uarg = SCARG(uap, arg); struct semid_ds sbuf; struct semid_ds *semaptr; unsigned short *semval = NULL, nsems; int i, ix, error; switch (cmd) { case IPC_SET: case IPC_STAT: case GETALL: case SETVAL: case SETALL: if ((error = copyin(uarg, &arg, sizeof(union semun)))) return (error); } if (cmd == IPC_SET) if ((error = copyin(arg.buf, &sbuf, sizeof(sbuf)))) return (error); DPRINTF(("call to semctl(%d, %d, %d, %p)\n", semid, semnum, cmd, uarg)); ix = IPCID_TO_IX(semid); if (ix < 0 || ix >= seminfo.semmni) return (EINVAL); again: if ((semaptr = sema[ix]) == NULL || semaptr->sem_perm.seq != IPCID_TO_SEQ(semid)) return (EINVAL); switch (cmd) { case IPC_RMID: if ((error = ipcperm(cred, &semaptr->sem_perm, IPC_M)) != 0) return (error); semaptr->sem_perm.cuid = cred->cr_uid; semaptr->sem_perm.uid = cred->cr_uid; semtot -= semaptr->sem_nsems; free(semaptr->sem_base, M_SEM, semaptr->sem_nsems * sizeof(struct sem)); pool_put(&sema_pool, semaptr); sema[ix] = NULL; semundo_clear(ix, -1); wakeup(&sema[ix]); break; case IPC_SET: if ((error = ipcperm(cred, &semaptr->sem_perm, IPC_M))) return (error); semaptr->sem_perm.uid = sbuf.sem_perm.uid; semaptr->sem_perm.gid = sbuf.sem_perm.gid; semaptr->sem_perm.mode = (semaptr->sem_perm.mode & ~0777) | (sbuf.sem_perm.mode & 0777); semaptr->sem_ctime = gettime(); break; case IPC_STAT: if ((error = ipcperm(cred, &semaptr->sem_perm, IPC_R))) return (error); memcpy(&sbuf, semaptr, sizeof sbuf); sbuf.sem_base = NULL; error = copyout(&sbuf, arg.buf, sizeof(struct semid_ds)); break; case GETNCNT: if ((error = ipcperm(cred, &semaptr->sem_perm, IPC_R))) return (error); if (semnum < 0 || semnum >= semaptr->sem_nsems) return (EINVAL); *retval = semaptr->sem_base[semnum].semncnt; break; case GETPID: if ((error = ipcperm(cred, &semaptr->sem_perm, IPC_R))) return (error); if (semnum < 0 || semnum >= semaptr->sem_nsems) return (EINVAL); *retval = semaptr->sem_base[semnum].sempid; break; case GETVAL: if ((error = ipcperm(cred, &semaptr->sem_perm, IPC_R))) return (error); if (semnum < 0 || semnum >= semaptr->sem_nsems) return (EINVAL); *retval = semaptr->sem_base[semnum].semval; break; case GETALL: nsems = semaptr->sem_nsems; semval = mallocarray(nsems, sizeof(arg.array[0]), M_TEMP, M_WAITOK); if (semaptr != sema[ix] || semaptr->sem_perm.seq != IPCID_TO_SEQ(semid) || semaptr->sem_nsems != nsems) { free(semval, M_TEMP, nsems * sizeof(arg.array[0])); goto again; } if ((error = ipcperm(cred, &semaptr->sem_perm, IPC_R))) goto error; for (i = 0; i < nsems; i++) semval[i] = semaptr->sem_base[i].semval; for (i = 0; i < nsems; i++) { error = copyout(&semval[i], &arg.array[i], sizeof(arg.array[0])); if (error != 0) break; } break; case GETZCNT: if ((error = ipcperm(cred, &semaptr->sem_perm, IPC_R))) return (error); if (semnum < 0 || semnum >= semaptr->sem_nsems) return (EINVAL); *retval = semaptr->sem_base[semnum].semzcnt; break; case SETVAL: if ((error = ipcperm(cred, &semaptr->sem_perm, IPC_W))) return (error); if (semnum < 0 || semnum >= semaptr->sem_nsems) return (EINVAL); if (arg.val > seminfo.semvmx) return (ERANGE); semaptr->sem_base[semnum].semval = arg.val; semundo_clear(ix, semnum); wakeup(&sema[ix]); break; case SETALL: nsems = semaptr->sem_nsems; semval = mallocarray(nsems, sizeof(arg.array[0]), M_TEMP, M_WAITOK); for (i = 0; i < nsems; i++) { error = copyin(&arg.array[i], &semval[i], sizeof(arg.array[0])); if (error != 0) goto error; if (semval[i] > seminfo.semvmx) { error = ERANGE; goto error; } } if (semaptr != sema[ix] || semaptr->sem_perm.seq != IPCID_TO_SEQ(semid) || semaptr->sem_nsems != nsems) { free(semval, M_TEMP, nsems * sizeof(arg.array[0])); goto again; } if ((error = ipcperm(cred, &semaptr->sem_perm, IPC_W))) goto error; for (i = 0; i < nsems; i++) semaptr->sem_base[i].semval = semval[i]; semundo_clear(ix, -1); wakeup(&sema[ix]); break; default: return (EINVAL); } error: free(semval, M_TEMP, nsems * sizeof(arg.array[0])); return (error); } int sys_semget(struct proc *p, void *v, register_t *retval) { struct sys_semget_args /* { syscallarg(key_t) key; syscallarg(int) nsems; syscallarg(int) semflg; } */ *uap = v; int semid, error; int key = SCARG(uap, key); int nsems = SCARG(uap, nsems); int semflg = SCARG(uap, semflg); struct semid_ds *semaptr, *semaptr_new = NULL; struct ucred *cred = p->p_ucred; DPRINTF(("semget(0x%x, %d, 0%o)\n", key, nsems, semflg)); /* * Preallocate space for the new semaphore. If we are going * to sleep, we want to sleep now to eliminate any race * condition in allocating a semaphore with a specific key. */ if (key == IPC_PRIVATE || (semflg & IPC_CREAT)) { if (nsems <= 0 || nsems > seminfo.semmsl) { DPRINTF(("nsems out of range (0<%d<=%d)\n", nsems, seminfo.semmsl)); return (EINVAL); } if (nsems > seminfo.semmns - semtot) { DPRINTF(("not enough semaphores left (need %d, got %d)\n", nsems, seminfo.semmns - semtot)); return (ENOSPC); } semaptr_new = pool_get(&sema_pool, PR_WAITOK | PR_ZERO); semaptr_new->sem_base = mallocarray(nsems, sizeof(struct sem), M_SEM, M_WAITOK|M_ZERO); if (nsems > seminfo.semmns - semtot) { error = ENOSPC; goto error; } } if (key != IPC_PRIVATE) { for (semid = 0, semaptr = NULL; semid < seminfo.semmni; semid++) { if ((semaptr = sema[semid]) != NULL && semaptr->sem_perm.key == key) { DPRINTF(("found public key\n")); if ((error = ipcperm(cred, &semaptr->sem_perm, semflg & 0700))) goto error; if (nsems > 0 && semaptr->sem_nsems < nsems) { DPRINTF(("too small\n")); error = EINVAL; goto error; } if ((semflg & IPC_CREAT) && (semflg & IPC_EXCL)) { DPRINTF(("not exclusive\n")); error = EEXIST; goto error; } if (semaptr_new != NULL) { free(semaptr_new->sem_base, M_SEM, nsems * sizeof(struct sem)); pool_put(&sema_pool, semaptr_new); } goto found; } } } DPRINTF(("need to allocate the semid_ds\n")); if (key == IPC_PRIVATE || (semflg & IPC_CREAT)) { for (semid = 0; semid < seminfo.semmni; semid++) { if ((semaptr = sema[semid]) == NULL) break; } if (semid == seminfo.semmni) { DPRINTF(("no more semid_ds's available\n")); error = ENOSPC; goto error; } DPRINTF(("semid %d is available\n", semid)); semaptr_new->sem_perm.key = key; semaptr_new->sem_perm.cuid = cred->cr_uid; semaptr_new->sem_perm.uid = cred->cr_uid; semaptr_new->sem_perm.cgid = cred->cr_gid; semaptr_new->sem_perm.gid = cred->cr_gid; semaptr_new->sem_perm.mode = (semflg & 0777); semaptr_new->sem_perm.seq = semseqs[semid] = (semseqs[semid] + 1) & 0x7fff; semaptr_new->sem_nsems = nsems; semaptr_new->sem_otime = 0; semaptr_new->sem_ctime = gettime(); sema[semid] = semaptr_new; semtot += nsems; } else { DPRINTF(("didn't find it and wasn't asked to create it\n")); return (ENOENT); } found: *retval = IXSEQ_TO_IPCID(semid, sema[semid]->sem_perm); return (0); error: if (semaptr_new != NULL) { free(semaptr_new->sem_base, M_SEM, nsems * sizeof(struct sem)); pool_put(&sema_pool, semaptr_new); } return (error); } int sys_semop(struct proc *p, void *v, register_t *retval) { struct sys_semop_args /* { syscallarg(int) semid; syscallarg(struct sembuf *) sops; syscallarg(size_t) nsops; } */ *uap = v; #define NSOPS 8 struct sembuf sopbuf[NSOPS]; int semid = SCARG(uap, semid); size_t nsops = SCARG(uap, nsops); struct sembuf *sops; struct semid_ds *semaptr; struct sembuf *sopptr = NULL; struct sem *semptr = NULL; struct sem_undo *suptr = NULL; struct ucred *cred = p->p_ucred; size_t i, j; int do_wakeup, do_undos, error; DPRINTF(("call to semop(%d, %p, %lu)\n", semid, SCARG(uap, sops), (u_long)nsops)); semid = IPCID_TO_IX(semid); /* Convert back to zero origin */ if (semid < 0 || semid >= seminfo.semmni) return (EINVAL); if ((semaptr = sema[semid]) == NULL || semaptr->sem_perm.seq != IPCID_TO_SEQ(SCARG(uap, semid))) return (EINVAL); if ((error = ipcperm(cred, &semaptr->sem_perm, IPC_W))) { DPRINTF(("error = %d from ipaccess\n", error)); return (error); } if (nsops == 0) { *retval = 0; return (0); } else if (nsops > (size_t)seminfo.semopm) { DPRINTF(("too many sops (max=%d, nsops=%lu)\n", seminfo.semopm, (u_long)nsops)); return (E2BIG); } if (nsops <= NSOPS) sops = sopbuf; else sops = mallocarray(nsops, sizeof(struct sembuf), M_SEM, M_WAITOK); error = copyin(SCARG(uap, sops), sops, nsops * sizeof(struct sembuf)); if (error != 0) { DPRINTF(("error = %d from copyin(%p, %p, %u)\n", error, SCARG(uap, sops), &sops, nsops * sizeof(struct sembuf))); goto done2; } /* * Loop trying to satisfy the vector of requests. * If we reach a point where we must wait, any requests already * performed are rolled back and we go to sleep until some other * process wakes us up. At this point, we start all over again. * * This ensures that from the perspective of other tasks, a set * of requests is atomic (never partially satisfied). */ do_undos = 0; for (;;) { do_wakeup = 0; for (i = 0; i < nsops; i++) { sopptr = &sops[i]; if (sopptr->sem_num >= semaptr->sem_nsems) { error = EFBIG; goto done2; } semptr = &semaptr->sem_base[sopptr->sem_num]; DPRINTF(("semop: semaptr=%x, sem_base=%x, semptr=%x, sem[%d]=%d : op=%d, flag=%s\n", semaptr, semaptr->sem_base, semptr, sopptr->sem_num, semptr->semval, sopptr->sem_op, (sopptr->sem_flg & IPC_NOWAIT) ? "nowait" : "wait")); if (sopptr->sem_op < 0) { if ((int)(semptr->semval + sopptr->sem_op) < 0) { DPRINTF(("semop: can't do it now\n")); break; } else { semptr->semval += sopptr->sem_op; if (semptr->semval == 0 && semptr->semzcnt > 0) do_wakeup = 1; } if (sopptr->sem_flg & SEM_UNDO) do_undos++; } else if (sopptr->sem_op == 0) { if (semptr->semval > 0) { DPRINTF(("semop: not zero now\n")); break; } } else { if (semptr->semncnt > 0) do_wakeup = 1; semptr->semval += sopptr->sem_op; if (sopptr->sem_flg & SEM_UNDO) do_undos++; } } /* * Did we get through the entire vector and can we undo it? */ if (i >= nsops && do_undos <= SEMUME) goto done; /* * No ... rollback anything that we've already done */ DPRINTF(("semop: rollback 0 through %d\n", i - 1)); for (j = 0; j < i; j++) semaptr->sem_base[sops[j].sem_num].semval -= sops[j].sem_op; /* * Did we have too many SEM_UNDO's */ if (do_undos > SEMUME) { error = ENOSPC; goto done2; } /* * If the request that we couldn't satisfy has the * NOWAIT flag set then return with EAGAIN. */ if (sopptr->sem_flg & IPC_NOWAIT) { error = EAGAIN; goto done2; } if (sopptr->sem_op == 0) semptr->semzcnt++; else semptr->semncnt++; DPRINTF(("semop: good night!\n")); error = tsleep_nsec(&sema[semid], PLOCK | PCATCH, "semwait", INFSLP); DPRINTF(("semop: good morning (error=%d)!\n", error)); suptr = NULL; /* sem_undo may have been reallocated */ /* * Make sure that the semaphore still exists */ if (sema[semid] == NULL || semaptr->sem_perm.seq != IPCID_TO_SEQ(SCARG(uap, semid))) { error = EIDRM; goto done2; } /* * The semaphore is still alive. Readjust the count of * waiting processes. */ if (sopptr->sem_op == 0) semptr->semzcnt--; else semptr->semncnt--; /* * Is it really morning, or was our sleep interrupted? * (Delayed check of tsleep() return code because we * need to decrement sem[nz]cnt either way.) */ if (error != 0) { error = EINTR; goto done2; } DPRINTF(("semop: good morning!\n")); } done: /* * Process any SEM_UNDO requests. */ if (do_undos) { for (i = 0; i < nsops; i++) { /* * We only need to deal with SEM_UNDO's for non-zero * op's. */ int adjval; if ((sops[i].sem_flg & SEM_UNDO) == 0) continue; adjval = sops[i].sem_op; if (adjval == 0) continue; error = semundo_adjust(p, &suptr, semid, sops[i].sem_num, -adjval); if (error == 0) continue; /* * Uh-Oh! We ran out of either sem_undo's or undo's. * Rollback the adjustments to this point and then * rollback the semaphore ups and down so we can return * with an error with all structures restored. We * rollback the undo's in the exact reverse order that * we applied them. This guarantees that we won't run * out of space as we roll things back out. */ for (j = i; j > 0;) { j--; if ((sops[j].sem_flg & SEM_UNDO) == 0) continue; adjval = sops[j].sem_op; if (adjval == 0) continue; if (semundo_adjust(p, &suptr, semid, sops[j].sem_num, adjval) != 0) panic("semop - can't undo undos"); } for (j = 0; j < nsops; j++) semaptr->sem_base[sops[j].sem_num].semval -= sops[j].sem_op; DPRINTF(("error = %d from semundo_adjust\n", error)); goto done2; } /* loop through the sops */ } /* if (do_undos) */ /* We're definitely done - set the sempid's */ for (i = 0; i < nsops; i++) { sopptr = &sops[i]; semptr = &semaptr->sem_base[sopptr->sem_num]; semptr->sempid = p->p_p->ps_pid; } semaptr->sem_otime = gettime(); /* Do a wakeup if any semaphore was up'd. */ if (do_wakeup) { DPRINTF(("semop: doing wakeup\n")); wakeup(&sema[semid]); DPRINTF(("semop: back from wakeup\n")); } DPRINTF(("semop: done\n")); *retval = 0; done2: if (sops != sopbuf) free(sops, M_SEM, nsops * sizeof(struct sembuf)); return (error); } /* * Go through the undo structures for this process and apply the adjustments to * semaphores. */ void semexit(struct process *pr) { struct sem_undo *suptr; struct sem_undo **supptr; /* * Go through the chain of undo vectors looking for one associated with * this process. Remember the pointer to the pointer to the element * to dequeue it later. */ supptr = &SLIST_FIRST(&semu_list); SLIST_FOREACH(suptr, &semu_list, un_next) { if (suptr->un_proc == pr) break; supptr = &SLIST_NEXT(suptr, un_next); } /* * If there is no undo vector, skip to the end. */ if (suptr == NULL) return; /* * We now have an undo vector for this process. */ DPRINTF(("process @%p has undo structure with %d entries\n", pr, suptr->un_cnt)); /* * If there are any active undo elements then process them. */ if (suptr->un_cnt > 0) { int ix; for (ix = 0; ix < suptr->un_cnt; ix++) { int semid = suptr->un_ent[ix].un_id; int semnum = suptr->un_ent[ix].un_num; int adjval = suptr->un_ent[ix].un_adjval; struct semid_ds *semaptr; if ((semaptr = sema[semid]) == NULL) panic("semexit - semid not allocated"); if (semnum >= semaptr->sem_nsems) panic("semexit - semnum out of range"); DPRINTF(("semexit: %p id=%d num=%d(adj=%d) ; sem=%d\n", suptr->un_proc, suptr->un_ent[ix].un_id, suptr->un_ent[ix].un_num, suptr->un_ent[ix].un_adjval, semaptr->sem_base[semnum].semval)); if (adjval < 0 && semaptr->sem_base[semnum].semval < -adjval) semaptr->sem_base[semnum].semval = 0; else semaptr->sem_base[semnum].semval += adjval; wakeup(&sema[semid]); DPRINTF(("semexit: back from wakeup\n")); } } /* * Deallocate the undo vector. */ DPRINTF(("removing vector\n")); *supptr = SLIST_NEXT(suptr, un_next); pool_put(&semu_pool, suptr); semutot--; } /* Expand semsegs and semseqs arrays */ void sema_reallocate(int val) { struct semid_ds **sema_new; unsigned short *newseqs; sema_new = mallocarray(val, sizeof(struct semid_ds *), M_SEM, M_WAITOK|M_ZERO); memcpy(sema_new, sema, seminfo.semmni * sizeof(struct semid_ds *)); newseqs = mallocarray(val, sizeof(unsigned short), M_SEM, M_WAITOK|M_ZERO); memcpy(newseqs, semseqs, seminfo.semmni * sizeof(unsigned short)); free(sema, M_SEM, seminfo.semmni * sizeof(struct semid_ds *)); free(semseqs, M_SEM, seminfo.semmni * sizeof(unsigned short)); sema = sema_new; semseqs = newseqs; seminfo.semmni = val; } const struct sysctl_bounded_args sysvsem_vars[] = { { KERN_SEMINFO_SEMUME, &seminfo.semume, SYSCTL_INT_READONLY }, { KERN_SEMINFO_SEMUSZ, &seminfo.semusz, SYSCTL_INT_READONLY }, { KERN_SEMINFO_SEMVMX, &seminfo.semvmx, SYSCTL_INT_READONLY }, { KERN_SEMINFO_SEMAEM, &seminfo.semaem, SYSCTL_INT_READONLY }, { KERN_SEMINFO_SEMOPM, &seminfo.semopm, 1, INT_MAX }, }; /* * Userland access to struct seminfo. */ int sysctl_sysvsem(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int error, val; if (namelen != 1) return (ENOTDIR); /* leaf-only */ switch (name[0]) { case KERN_SEMINFO_SEMMNI: val = seminfo.semmni; error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, &val, val, 0xffff); /* returns success and skips reallocation if val is unchanged */ if (error || val == seminfo.semmni) return (error); sema_reallocate(val); return (0); case KERN_SEMINFO_SEMMNS: /* can't decrease semmns or go over 2^16 */ return (sysctl_int_bounded(oldp, oldlenp, newp, newlen, &seminfo.semmns, seminfo.semmns, 0xffff)); case KERN_SEMINFO_SEMMNU: /* can't decrease semmnu or go over 2^16 */ return (sysctl_int_bounded(oldp, oldlenp, newp, newlen, &seminfo.semmnu, seminfo.semmnu, 0xffff)); case KERN_SEMINFO_SEMMSL: /* can't decrease semmsl or go over 2^16 */ return (sysctl_int_bounded(oldp, oldlenp, newp, newlen, &seminfo.semmsl, seminfo.semmsl, 0xffff)); default: return (sysctl_bounded_arr(sysvsem_vars, nitems(sysvsem_vars), name, namelen, oldp, oldlenp, newp, newlen)); } /* NOTREACHED */ }
5 5 1 1 2 70 46 24 17 10 10 74 31 2 3 13 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 /* $OpenBSD: if_loop.c,v 1.98 2023/12/29 11:43:04 bluhm Exp $ */ /* $NetBSD: if_loop.c,v 1.15 1996/05/07 02:40:33 thorpej Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 1982, 1986, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)if_loop.c 8.1 (Berkeley) 6/10/93 */ /* * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 * * NRL grants permission for redistribution and use in source and binary * forms, with or without modification, of the software and documentation * created at NRL provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgements: * This product includes software developed by the University of * California, Berkeley and its contributors. * This product includes software developed at the Information * Technology Division, US Naval Research Laboratory. * 4. Neither the name of the NRL nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the US Naval * Research Laboratory (NRL). */ /* * Loopback interface driver for protocol testing and timing. */ #include "bpfilter.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/errno.h> #include <sys/ioctl.h> #include <sys/time.h> #include <net/if.h> #include <net/if_var.h> #include <net/if_types.h> #include <net/netisr.h> #include <net/rtable.h> #include <net/route.h> #include <netinet/in.h> #ifdef INET6 #include <netinet/ip6.h> #endif #ifdef MPLS #include <netmpls/mpls.h> #endif #if NBPFILTER > 0 #include <net/bpf.h> #endif #define LOMTU 32768 int loioctl(struct ifnet *, u_long, caddr_t); void loopattach(int); void lortrequest(struct ifnet *, int, struct rtentry *); void loinput(struct ifnet *, struct mbuf *); int looutput(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); int lo_bpf_mtap(caddr_t, const struct mbuf *, u_int); int loop_clone_create(struct if_clone *, int); int loop_clone_destroy(struct ifnet *); struct if_clone loop_cloner = IF_CLONE_INITIALIZER("lo", loop_clone_create, loop_clone_destroy); void loopattach(int n) { if (loop_clone_create(&loop_cloner, 0)) panic("unable to create lo0"); if_clone_attach(&loop_cloner); } int loop_clone_create(struct if_clone *ifc, int unit) { struct ifnet *ifp; ifp = malloc(sizeof(*ifp), M_DEVBUF, M_WAITOK|M_ZERO); snprintf(ifp->if_xname, sizeof ifp->if_xname, "lo%d", unit); ifp->if_softc = NULL; ifp->if_mtu = LOMTU; ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST; ifp->if_xflags = IFXF_CLONED | IFXF_LRO; ifp->if_capabilities = IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4 | IFCAP_CSUM_TCPv6 | IFCAP_CSUM_UDPv6 | IFCAP_LRO | IFCAP_TSOv4 | IFCAP_TSOv6; ifp->if_bpf_mtap = lo_bpf_mtap; ifp->if_rtrequest = lortrequest; ifp->if_ioctl = loioctl; ifp->if_input = loinput; ifp->if_output = looutput; ifp->if_type = IFT_LOOP; ifp->if_hdrlen = sizeof(u_int32_t); if_counters_alloc(ifp); if (unit == 0) { if_attachhead(ifp); if_addgroup(ifp, ifc->ifc_name); rtable_l2set(0, 0, ifp->if_index); } else if_attach(ifp); if_alloc_sadl(ifp); #if NBPFILTER > 0 bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(u_int32_t)); #endif return (0); } int loop_clone_destroy(struct ifnet *ifp) { struct ifnet *p; unsigned int rdomain = 0; if (ifp->if_index == rtable_loindex(ifp->if_rdomain)) { /* rdomain 0 always needs a loopback */ if (ifp->if_rdomain == 0) return (EPERM); /* if there is any other interface in this rdomain, deny */ NET_LOCK_SHARED(); TAILQ_FOREACH(p, &ifnetlist, if_list) { if (p->if_rdomain != ifp->if_rdomain) continue; if (p->if_index == ifp->if_index) continue; NET_UNLOCK_SHARED(); return (EBUSY); } NET_UNLOCK_SHARED(); rdomain = ifp->if_rdomain; } if_detach(ifp); free(ifp, M_DEVBUF, sizeof(*ifp)); if (rdomain) rtable_l2set(rdomain, 0, 0); return (0); } int lo_bpf_mtap(caddr_t if_bpf, const struct mbuf *m, u_int dir) { /* loopback dumps on output, disable input bpf */ return (0); } void loinput(struct ifnet *ifp, struct mbuf *m) { int error; if ((m->m_flags & M_PKTHDR) == 0) panic("%s: no header mbuf", __func__); error = if_input_local(ifp, m, m->m_pkthdr.ph_family); if (error) counters_inc(ifp->if_counters, ifc_ierrors); } int looutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) { if ((m->m_flags & M_PKTHDR) == 0) panic("%s: no header mbuf", __func__); if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { m_freem(m); return (rt->rt_flags & RTF_BLACKHOLE ? 0 : rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); } /* * Do not call if_input_local() directly. Queue the packet to avoid * stack overflow and make TCP handshake over loopback work. */ return (if_output_local(ifp, m, dst->sa_family)); } void lortrequest(struct ifnet *ifp, int cmd, struct rtentry *rt) { if (rt && rt->rt_mtu == 0) rt->rt_mtu = LOMTU; } /* * Process an ioctl request. */ int loioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct ifreq *ifr; int error = 0; switch (cmd) { case SIOCSIFFLAGS: if (ISSET(ifp->if_xflags, IFXF_LRO)) SET(ifp->if_capabilities, IFCAP_TSOv4 | IFCAP_TSOv6); else CLR(ifp->if_capabilities, IFCAP_TSOv4 | IFCAP_TSOv6); break; case SIOCSIFADDR: ifp->if_flags |= IFF_RUNNING; if_up(ifp); /* send up RTM_IFINFO */ /* * Everything else is done at a higher level. */ break; case SIOCADDMULTI: case SIOCDELMULTI: break; case SIOCSIFMTU: ifr = (struct ifreq *)data; ifp->if_mtu = ifr->ifr_mtu; break; default: error = ENOTTY; } return (error); }
28 28 28 28 3 6 22 22 22 3 9 2 10 9 22 9 16 1 22 22 44 8 36 39 20 18 1 3 13 18 1 17 17 13 15 15 36 8 136 2 44 37 6 8 80 4 7 1 1 5 5 7 4 3 74 7 2 3 2 28 2 5 21 2 2 1 47 1 37 2 7 4 2 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 /* $OpenBSD: raw_ip6.c,v 1.184 2024/04/17 20:48:51 bluhm Exp $ */ /* $KAME: raw_ip6.c,v 1.69 2001/03/04 15:55:44 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 1982, 1986, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)raw_ip.c 8.2 (Berkeley) 1/4/94 */ #include "pf.h" #include <sys/param.h> #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/protosw.h> #include <sys/socketvar.h> #include <sys/errno.h> #include <sys/systm.h> #include <sys/sysctl.h> #include <net/if.h> #include <net/if_var.h> #include <net/route.h> #include <netinet/in.h> #include <netinet6/in6_var.h> #include <netinet/ip6.h> #include <netinet6/ip6_var.h> #ifdef MROUTING #include <netinet6/ip6_mroute.h> #endif #include <netinet/icmp6.h> #include <netinet/ip.h> #include <netinet/in_pcb.h> #include <netinet6/nd6.h> #include <netinet6/ip6protosw.h> #include <netinet6/raw_ip6.h> #if NPF > 0 #include <net/pfvar.h> #endif #include <sys/stdarg.h> /* * Raw interface to IP6 protocol. */ struct inpcbtable rawin6pcbtable; struct cpumem *rip6counters; const struct pr_usrreqs rip6_usrreqs = { .pru_attach = rip6_attach, .pru_detach = rip6_detach, .pru_lock = rip6_lock, .pru_unlock = rip6_unlock, .pru_locked = rip6_locked, .pru_bind = rip6_bind, .pru_connect = rip6_connect, .pru_disconnect = rip6_disconnect, .pru_shutdown = rip6_shutdown, .pru_send = rip6_send, .pru_control = in6_control, .pru_sockaddr = in6_sockaddr, .pru_peeraddr = in6_peeraddr, }; /* * Initialize raw connection block queue. */ void rip6_init(void) { in_pcbinit(&rawin6pcbtable, 1); rip6counters = counters_alloc(rip6s_ncounters); } int rip6_input(struct mbuf **mp, int *offp, int proto, int af) { struct mbuf *m = *mp; struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); struct inpcb *inp; SIMPLEQ_HEAD(, inpcb) inpcblist; struct in6_addr *key; struct sockaddr_in6 rip6src; uint8_t type; KASSERT(af == AF_INET6); if (proto == IPPROTO_ICMPV6) { struct icmp6_hdr *icmp6; IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, *offp, sizeof(*icmp6)); if (icmp6 == NULL) return IPPROTO_DONE; type = icmp6->icmp6_type; } else rip6stat_inc(rip6s_ipackets); memset(&rip6src, 0, sizeof(rip6src)); rip6src.sin6_family = AF_INET6; rip6src.sin6_len = sizeof(rip6src); /* KAME hack: recover scopeid */ in6_recoverscope(&rip6src, &ip6->ip6_src); key = &ip6->ip6_dst; #if NPF > 0 if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { struct pf_divert *divert; divert = pf_find_divert(m); KASSERT(divert != NULL); switch (divert->type) { case PF_DIVERT_TO: key = &divert->addr.v6; break; case PF_DIVERT_REPLY: break; default: panic("%s: unknown divert type %d, mbuf %p, divert %p", __func__, divert->type, m, divert); } } #endif SIMPLEQ_INIT(&inpcblist); rw_enter_write(&rawin6pcbtable.inpt_notify); mtx_enter(&rawin6pcbtable.inpt_mtx); TAILQ_FOREACH(inp, &rawin6pcbtable.inpt_queue, inp_queue) { KASSERT(ISSET(inp->inp_flags, INP_IPV6)); /* * Packet must not be inserted after disconnected wakeup * call. To avoid race, check again when holding receive * buffer mutex. */ if (ISSET(READ_ONCE(inp->inp_socket->so_rcv.sb_state), SS_CANTRCVMORE)) continue; if (rtable_l2(inp->inp_rtableid) != rtable_l2(m->m_pkthdr.ph_rtableid)) continue; if ((inp->inp_ipv6.ip6_nxt || proto == IPPROTO_ICMPV6) && inp->inp_ipv6.ip6_nxt != proto) continue; if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6) && !IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, key)) continue; if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6) && !IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6, &ip6->ip6_src)) continue; if (proto == IPPROTO_ICMPV6 && inp->inp_icmp6filt) { if (ICMP6_FILTER_WILLBLOCK(type, inp->inp_icmp6filt)) continue; } if (proto != IPPROTO_ICMPV6 && inp->inp_cksum6 != -1) { rip6stat_inc(rip6s_isum); /* * Although in6_cksum() does not need the position of * the checksum field for verification, enforce that it * is located within the packet. Userland has given * a checksum offset, a packet too short for that is * invalid. Avoid overflow with user supplied offset. */ if (m->m_pkthdr.len < *offp + 2 || m->m_pkthdr.len - *offp - 2 < inp->inp_cksum6 || in6_cksum(m, proto, *offp, m->m_pkthdr.len - *offp)) { rip6stat_inc(rip6s_badsum); continue; } } in_pcbref(inp); SIMPLEQ_INSERT_TAIL(&inpcblist, inp, inp_notify); } mtx_leave(&rawin6pcbtable.inpt_mtx); if (SIMPLEQ_EMPTY(&inpcblist)) { struct counters_ref ref; uint64_t *counters; rw_exit_write(&rawin6pcbtable.inpt_notify); if (proto != IPPROTO_ICMPV6) { rip6stat_inc(rip6s_nosock); if (m->m_flags & M_MCAST) rip6stat_inc(rip6s_nosockmcast); } if (proto == IPPROTO_NONE || proto == IPPROTO_ICMPV6) { m_freem(m); } else { int prvnxt = ip6_get_prevhdr(m, *offp); icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_NEXTHEADER, prvnxt); } counters = counters_enter(&ref, ip6counters); counters[ip6s_delivered]--; counters_leave(&ref, ip6counters); return IPPROTO_DONE; } while ((inp = SIMPLEQ_FIRST(&inpcblist)) != NULL) { struct mbuf *n, *opts = NULL; SIMPLEQ_REMOVE_HEAD(&inpcblist, inp_notify); if (SIMPLEQ_EMPTY(&inpcblist)) n = m; else n = m_copym(m, 0, M_COPYALL, M_NOWAIT); if (n != NULL) { struct socket *so = inp->inp_socket; int ret = 0; if (inp->inp_flags & IN6P_CONTROLOPTS) ip6_savecontrol(inp, n, &opts); /* strip intermediate headers */ m_adj(n, *offp); mtx_enter(&so->so_rcv.sb_mtx); if (!ISSET(inp->inp_socket->so_rcv.sb_state, SS_CANTRCVMORE)) { ret = sbappendaddr(so, &so->so_rcv, sin6tosa(&rip6src), n, opts); } mtx_leave(&so->so_rcv.sb_mtx); if (ret == 0) { m_freem(n); m_freem(opts); rip6stat_inc(rip6s_fullsock); } else sorwakeup(so); } in_pcbunref(inp); } rw_exit_write(&rawin6pcbtable.inpt_notify); return IPPROTO_DONE; } void rip6_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *d) { struct ip6_hdr *ip6; struct ip6ctlparam *ip6cp = NULL; struct sockaddr_in6 *sa6 = satosin6(sa); const struct sockaddr_in6 *sa6_src = NULL; void *cmdarg; void (*notify)(struct inpcb *, int) = in_rtchange; int nxt; if (sa->sa_family != AF_INET6 || sa->sa_len != sizeof(struct sockaddr_in6)) return; if ((unsigned)cmd >= PRC_NCMDS) return; if (PRC_IS_REDIRECT(cmd)) notify = in_rtchange, d = NULL; else if (cmd == PRC_HOSTDEAD) d = NULL; else if (cmd == PRC_MSGSIZE) ; /* special code is present, see below */ else if (inet6ctlerrmap[cmd] == 0) return; /* if the parameter is from icmp6, decode it. */ if (d != NULL) { ip6cp = (struct ip6ctlparam *)d; ip6 = ip6cp->ip6c_ip6; cmdarg = ip6cp->ip6c_cmdarg; sa6_src = ip6cp->ip6c_src; nxt = ip6cp->ip6c_nxt; } else { ip6 = NULL; cmdarg = NULL; sa6_src = &sa6_any; nxt = -1; } if (ip6 && cmd == PRC_MSGSIZE) { int valid = 0; struct inpcb *inp; /* * Check to see if we have a valid raw IPv6 socket * corresponding to the address in the ICMPv6 message * payload, and the protocol (ip6_nxt) meets the socket. * XXX chase extension headers, or pass final nxt value * from icmp6_notify_error() */ inp = in6_pcblookup(&rawin6pcbtable, &sa6->sin6_addr, 0, &sa6_src->sin6_addr, 0, rdomain); if (inp && inp->inp_ipv6.ip6_nxt && inp->inp_ipv6.ip6_nxt == nxt) valid = 1; /* * Depending on the value of "valid" and routing table * size (mtudisc_{hi,lo}wat), we will: * - recalculate the new MTU and create the * corresponding routing entry, or * - ignore the MTU change notification. */ icmp6_mtudisc_update((struct ip6ctlparam *)d, valid); in_pcbunref(inp); /* * regardless of if we called icmp6_mtudisc_update(), * we need to call in6_pcbnotify(), to notify path * MTU change to the userland (2292bis-02), because * some unconnected sockets may share the same * destination and want to know the path MTU. */ } in6_pcbnotify(&rawin6pcbtable, sa6, 0, sa6_src, 0, rdomain, cmd, cmdarg, notify); } /* * Generate IPv6 header and pass packet to ip6_output. * Tack on options user may have setup with control call. */ int rip6_output(struct mbuf *m, struct socket *so, struct sockaddr *dstaddr, struct mbuf *control) { struct in6_addr *dst; struct ip6_hdr *ip6; struct inpcb *inp; u_int plen = m->m_pkthdr.len; int error = 0; struct ip6_pktopts opt, *optp = NULL; int type; /* for ICMPv6 output statistics only */ int priv = 0; int flags; inp = sotoinpcb(so); priv = 0; if ((so->so_state & SS_PRIV) != 0) priv = 1; if (control) { if ((error = ip6_setpktopts(control, &opt, inp->inp_outputopts6, priv, so->so_proto->pr_protocol)) != 0) goto bad; optp = &opt; } else optp = inp->inp_outputopts6; if (dstaddr->sa_family != AF_INET6) { error = EAFNOSUPPORT; goto bad; } dst = &satosin6(dstaddr)->sin6_addr; if (IN6_IS_ADDR_V4MAPPED(dst)) { error = EADDRNOTAVAIL; goto bad; } /* * For an ICMPv6 packet, we should know its type and code * to update statistics. */ if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) { struct icmp6_hdr *icmp6; if (m->m_len < sizeof(struct icmp6_hdr) && (m = m_pullup(m, sizeof(struct icmp6_hdr))) == NULL) { error = ENOBUFS; goto bad; } icmp6 = mtod(m, struct icmp6_hdr *); type = icmp6->icmp6_type; } M_PREPEND(m, sizeof(*ip6), M_DONTWAIT); if (!m) { error = ENOBUFS; goto bad; } ip6 = mtod(m, struct ip6_hdr *); /* * Next header might not be ICMP6 but use its pseudo header anyway. */ ip6->ip6_dst = *dst; /* KAME hack: embed scopeid */ if (in6_embedscope(&ip6->ip6_dst, satosin6(dstaddr), optp, inp->inp_moptions6) != 0) { error = EINVAL; goto bad; } /* * Source address selection. */ { const struct in6_addr *in6a; error = in6_pcbselsrc(&in6a, satosin6(dstaddr), inp, optp); if (error) goto bad; ip6->ip6_src = *in6a; } ip6->ip6_flow = inp->inp_flowinfo & IPV6_FLOWINFO_MASK; ip6->ip6_vfc &= ~IPV6_VERSION_MASK; ip6->ip6_vfc |= IPV6_VERSION; #if 0 /* ip6_plen will be filled in ip6_output. */ ip6->ip6_plen = htons((u_short)plen); #endif ip6->ip6_nxt = inp->inp_ipv6.ip6_nxt; ip6->ip6_hlim = in6_selecthlim(inp); if (so->so_proto->pr_protocol == IPPROTO_ICMPV6 || inp->inp_cksum6 != -1) { struct mbuf *n; int off; u_int16_t *sump; int sumoff; /* compute checksum */ if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) off = offsetof(struct icmp6_hdr, icmp6_cksum); else off = inp->inp_cksum6; if (plen < 2 || plen - 2 < off) { error = EINVAL; goto bad; } off += sizeof(struct ip6_hdr); n = m_pulldown(m, off, sizeof(*sump), &sumoff); if (n == NULL) { m = NULL; error = ENOBUFS; goto bad; } sump = (u_int16_t *)(mtod(n, caddr_t) + sumoff); *sump = 0; *sump = in6_cksum(m, ip6->ip6_nxt, sizeof(*ip6), plen); } flags = 0; if (inp->inp_flags & IN6P_MINMTU) flags |= IPV6_MINMTU; /* force routing table */ m->m_pkthdr.ph_rtableid = inp->inp_rtableid; #if NPF > 0 if (inp->inp_socket->so_state & SS_ISCONNECTED && so->so_proto->pr_protocol != IPPROTO_ICMPV6) pf_mbuf_link_inpcb(m, inp); #endif error = ip6_output(m, optp, &inp->inp_route, flags, inp->inp_moptions6, &inp->inp_seclevel); if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) { icmp6stat_inc(icp6s_outhist + type); } else rip6stat_inc(rip6s_opackets); goto freectl; bad: m_freem(m); freectl: if (control) { ip6_clearpktopts(&opt, -1); m_freem(control); } return (error); } /* * Raw IPv6 socket option processing. */ int rip6_ctloutput(int op, struct socket *so, int level, int optname, struct mbuf *m) { #ifdef MROUTING int error; #endif switch (level) { case IPPROTO_IPV6: switch (optname) { #ifdef MROUTING case MRT6_INIT: case MRT6_DONE: case MRT6_ADD_MIF: case MRT6_DEL_MIF: case MRT6_ADD_MFC: case MRT6_DEL_MFC: if (op == PRCO_SETOPT) { error = ip6_mrouter_set(optname, so, m); } else if (op == PRCO_GETOPT) error = ip6_mrouter_get(optname, so, m); else error = EINVAL; return (error); #endif case IPV6_CHECKSUM: return (ip6_raw_ctloutput(op, so, level, optname, m)); default: return (ip6_ctloutput(op, so, level, optname, m)); } case IPPROTO_ICMPV6: /* * XXX: is it better to call icmp6_ctloutput() directly * from protosw? */ return (icmp6_ctloutput(op, so, level, optname, m)); default: return EINVAL; } } extern u_long rip6_sendspace; extern u_long rip6_recvspace; int rip6_attach(struct socket *so, int proto, int wait) { struct inpcb *inp; int error; if (so->so_pcb) panic("%s", __func__); if ((so->so_state & SS_PRIV) == 0) return (EACCES); if (proto < 0 || proto >= IPPROTO_MAX) return EPROTONOSUPPORT; if ((error = soreserve(so, rip6_sendspace, rip6_recvspace))) return error; NET_ASSERT_LOCKED(); if ((error = in_pcballoc(so, &rawin6pcbtable, wait))) return error; inp = sotoinpcb(so); inp->inp_ipv6.ip6_nxt = proto; inp->inp_cksum6 = -1; inp->inp_icmp6filt = malloc(sizeof(struct icmp6_filter), M_PCB, wait == M_WAIT ? M_WAITOK : M_NOWAIT); if (inp->inp_icmp6filt == NULL) { in_pcbdetach(inp); return ENOMEM; } ICMP6_FILTER_SETPASSALL(inp->inp_icmp6filt); return 0; } int rip6_detach(struct socket *so) { struct inpcb *inp = sotoinpcb(so); soassertlocked(so); if (inp == NULL) panic("%s", __func__); #ifdef MROUTING if (so == ip6_mrouter[inp->inp_rtableid]) ip6_mrouter_done(so); #endif free(inp->inp_icmp6filt, M_PCB, sizeof(struct icmp6_filter)); inp->inp_icmp6filt = NULL; in_pcbdetach(inp); return (0); } void rip6_lock(struct socket *so) { struct inpcb *inp = sotoinpcb(so); NET_ASSERT_LOCKED(); mtx_enter(&inp->inp_mtx); } void rip6_unlock(struct socket *so) { struct inpcb *inp = sotoinpcb(so); NET_ASSERT_LOCKED(); mtx_leave(&inp->inp_mtx); } int rip6_locked(struct socket *so) { struct inpcb *inp = sotoinpcb(so); return mtx_owned(&inp->inp_mtx); } int rip6_bind(struct socket *so, struct mbuf *nam, struct proc *p) { struct inpcb *inp = sotoinpcb(so); struct sockaddr_in6 *addr; int error; soassertlocked(so); if ((error = in6_nam2sin6(nam, &addr))) return (error); /* * Make sure to not enter in_pcblookup_local(), local ports * are non-sensical for raw sockets. */ addr->sin6_port = 0; if ((error = in6_pcbaddrisavail(inp, addr, 0, p))) return (error); mtx_enter(&rawin6pcbtable.inpt_mtx); inp->inp_laddr6 = addr->sin6_addr; mtx_leave(&rawin6pcbtable.inpt_mtx); return (0); } int rip6_connect(struct socket *so, struct mbuf *nam) { struct inpcb *inp = sotoinpcb(so); struct sockaddr_in6 *addr; const struct in6_addr *in6a; int error; soassertlocked(so); if ((error = in6_nam2sin6(nam, &addr))) return (error); /* Source address selection. XXX: need pcblookup? */ error = in6_pcbselsrc(&in6a, addr, inp, inp->inp_outputopts6); if (error) return (error); mtx_enter(&rawin6pcbtable.inpt_mtx); inp->inp_laddr6 = *in6a; inp->inp_faddr6 = addr->sin6_addr; mtx_leave(&rawin6pcbtable.inpt_mtx); soisconnected(so); return (0); } int rip6_disconnect(struct socket *so) { struct inpcb *inp = sotoinpcb(so); soassertlocked(so); if ((so->so_state & SS_ISCONNECTED) == 0) return (ENOTCONN); soisdisconnected(so); mtx_enter(&rawin6pcbtable.inpt_mtx); inp->inp_faddr6 = in6addr_any; mtx_leave(&rawin6pcbtable.inpt_mtx); return (0); } int rip6_shutdown(struct socket *so) { /* * Mark the connection as being incapable of further input. */ soassertlocked(so); socantsendmore(so); return (0); } int rip6_send(struct socket *so, struct mbuf *m, struct mbuf *nam, struct mbuf *control) { struct inpcb *inp = sotoinpcb(so); struct sockaddr_in6 dst; int error; soassertlocked(so); /* * Ship a packet out. The appropriate raw output * routine handles any messaging necessary. */ /* always copy sockaddr to avoid overwrites */ memset(&dst, 0, sizeof(dst)); dst.sin6_family = AF_INET6; dst.sin6_len = sizeof(dst); if (so->so_state & SS_ISCONNECTED) { if (nam) { error = EISCONN; goto out; } dst.sin6_addr = inp->inp_faddr6; } else { struct sockaddr_in6 *addr6; if (nam == NULL) { error = ENOTCONN; goto out; } if ((error = in6_nam2sin6(nam, &addr6))) goto out; dst.sin6_addr = addr6->sin6_addr; dst.sin6_scope_id = addr6->sin6_scope_id; } error = rip6_output(m, so, sin6tosa(&dst), control); control = NULL; m = NULL; out: m_freem(control); m_freem(m); return (error); } int rip6_sysctl_rip6stat(void *oldp, size_t *oldplen, void *newp) { struct rip6stat rip6stat; CTASSERT(sizeof(rip6stat) == rip6s_ncounters * sizeof(uint64_t)); counters_read(rip6counters, (uint64_t *)&rip6stat, rip6s_ncounters, NULL); return (sysctl_rdstruct(oldp, oldplen, newp, &rip6stat, sizeof(rip6stat))); } int rip6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { /* All sysctl names at this level are terminal. */ if (namelen != 1) return ENOTDIR; switch (name[0]) { case RIPV6CTL_STATS: return (rip6_sysctl_rip6stat(oldp, oldlenp, newp)); default: return (EOPNOTSUPP); } /* NOTREACHED */ }
439 439 31 6 422 441 440 439 30 3 423 434 434 433 435 276 278 279 278 568 163 630 683 66 566 680 65 162 631 85 85 86 3243 3241 313 1593 9 220 219 82 165 216 17 210 17 84 151 151 150 441 425 438 427 435 441 433 27 27 2 11 15 24 9 14 5 19 20 3 19 5 7 17 27 19 4 169 169 140 31 169 167 31 10 21 31 139 139 140 140 142 24 165 165 161 4 165 152 2 13 161 3 160 4 163 27 139 169 97 75 168 128 121 1 100 24 123 123 123 123 139 31 123 133 48 157 94 143 62 98 84 60 60 1 61 101 101 202 178 30 201 202 31 185 442 99 61 60 322 321 240 100 54 100 1984 1979 1988 1980 1 1 1 1 1 1 6482 6474 1 16 16 1 15 15 1 15 111 111 63 49 183 185 185 185 20 171 188 185 3 11 185 63 96 33 11 185 188 188 188 130 61 63 61 185 187 152 102 174 15 118 20 7 65 185 11 12 4 9 29 29 17 24 24 29 29 14 28 14 1 8 1 13 14 11 10 14 11 32 1 31 31 1 29 22 27 27 4 8 4 7 15 3 12 2 14 15 1 1 14 14 2 14 1 13 1 20 19 20 20 11 11 11 11 5 11 4 11 351 350 323 42 351 33 33 30 33 1 27 11 2 31 24 6 28 27 26 26 26 21 8 17 10 22 4 26 26 26 26 30 4 33 20 2 2 11 13 22 11 11 21 21 1 3 11 11 3 16 19 10 21 21 30 2 29 27 4 17 10 1883 1878 1886 1880 15 1877 16 1 15 10 13 1 13 10 8 15 16 2 11 10 14 13 14 11 11 11 11 11 11 11 39 1 36 37 28 34 3 36 35 29 21 24 24 9 9 4 9 4 3 5 30 12 2 177 291 165 166 437 19 438 440 287 6 175 12 428 235 84 164 234 164 83 235 233 241 239 242 32 238 235 235 229 32 186 14 14 14 3 8 3 8 4 7 10 4 11 3 8 14 5 9 2129 452 2 456 1896 24 2121 1950 1973 1996 2133 453 1893 1948 1972 63 64 58 58 671 2034 1896 150 101 3 3 1 2 2 3 3 427 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 /* $OpenBSD: uvm_map.c,v 1.328 2024/04/02 08:39:17 deraadt Exp $ */ /* $NetBSD: uvm_map.c,v 1.86 2000/11/27 08:40:03 chs Exp $ */ /* * Copyright (c) 2011 Ariane van der Steldt <ariane@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * * Copyright (c) 1997 Charles D. Cranor and Washington University. * Copyright (c) 1991, 1993, The Regents of the University of California. * * All rights reserved. * * This code is derived from software contributed to Berkeley by * The Mach Operating System project at Carnegie-Mellon University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)vm_map.c 8.3 (Berkeley) 1/12/94 * from: Id: uvm_map.c,v 1.1.2.27 1998/02/07 01:16:54 chs Exp * * * Copyright (c) 1987, 1990 Carnegie-Mellon University. * All rights reserved. * * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ /* * uvm_map.c: uvm map operations */ /* #define DEBUG */ /* #define VMMAP_DEBUG */ #include <sys/param.h> #include <sys/systm.h> #include <sys/acct.h> #include <sys/mman.h> #include <sys/proc.h> #include <sys/malloc.h> #include <sys/pool.h> #include <sys/sysctl.h> #include <sys/signalvar.h> #include <sys/syslog.h> #include <sys/user.h> #include <sys/tracepoint.h> #ifdef SYSVSHM #include <sys/shm.h> #endif #include <uvm/uvm.h> #ifdef DDB #include <uvm/uvm_ddb.h> #endif #include <uvm/uvm_addr.h> vsize_t uvmspace_dused(struct vm_map*, vaddr_t, vaddr_t); int uvm_mapent_isjoinable(struct vm_map*, struct vm_map_entry*, struct vm_map_entry*); struct vm_map_entry *uvm_mapent_merge(struct vm_map*, struct vm_map_entry*, struct vm_map_entry*, struct uvm_map_deadq*); struct vm_map_entry *uvm_mapent_tryjoin(struct vm_map*, struct vm_map_entry*, struct uvm_map_deadq*); struct vm_map_entry *uvm_map_mkentry(struct vm_map*, struct vm_map_entry*, struct vm_map_entry*, vaddr_t, vsize_t, int, struct uvm_map_deadq*, struct vm_map_entry*); struct vm_map_entry *uvm_mapent_alloc(struct vm_map*, int); void uvm_mapent_free(struct vm_map_entry*); void uvm_unmap_kill_entry(struct vm_map*, struct vm_map_entry*); void uvm_unmap_kill_entry_withlock(struct vm_map *, struct vm_map_entry *, int); void uvm_unmap_detach_intrsafe(struct uvm_map_deadq *); void uvm_mapent_mkfree(struct vm_map*, struct vm_map_entry*, struct vm_map_entry**, struct uvm_map_deadq*, boolean_t); void uvm_map_pageable_pgon(struct vm_map*, struct vm_map_entry*, struct vm_map_entry*, vaddr_t, vaddr_t); int uvm_map_pageable_wire(struct vm_map*, struct vm_map_entry*, struct vm_map_entry*, vaddr_t, vaddr_t, int); void uvm_map_setup_entries(struct vm_map*); void uvm_map_setup_md(struct vm_map*); void uvm_map_teardown(struct vm_map*); void uvm_map_vmspace_update(struct vm_map*, struct uvm_map_deadq*, int); void uvm_map_kmem_grow(struct vm_map*, struct uvm_map_deadq*, vsize_t, int); void uvm_map_freelist_update_clear(struct vm_map*, struct uvm_map_deadq*); void uvm_map_freelist_update_refill(struct vm_map *, int); void uvm_map_freelist_update(struct vm_map*, struct uvm_map_deadq*, vaddr_t, vaddr_t, vaddr_t, vaddr_t, int); struct vm_map_entry *uvm_map_fix_space(struct vm_map*, struct vm_map_entry*, vaddr_t, vaddr_t, int); int uvm_map_findspace(struct vm_map*, struct vm_map_entry**, struct vm_map_entry**, vaddr_t*, vsize_t, vaddr_t, vaddr_t, vm_prot_t, vaddr_t); vsize_t uvm_map_addr_augment_get(struct vm_map_entry*); void uvm_map_addr_augment(struct vm_map_entry*); int uvm_map_inentry_recheck(u_long, vaddr_t, struct p_inentry *); boolean_t uvm_map_inentry_fix(struct proc *, struct p_inentry *, vaddr_t, int (*)(vm_map_entry_t), u_long); /* * Tree management functions. */ static inline void uvm_mapent_copy(struct vm_map_entry*, struct vm_map_entry*); static inline int uvm_mapentry_addrcmp(const struct vm_map_entry*, const struct vm_map_entry*); void uvm_mapent_free_insert(struct vm_map*, struct uvm_addr_state*, struct vm_map_entry*); void uvm_mapent_free_remove(struct vm_map*, struct uvm_addr_state*, struct vm_map_entry*); void uvm_mapent_addr_insert(struct vm_map*, struct vm_map_entry*); void uvm_mapent_addr_remove(struct vm_map*, struct vm_map_entry*); void uvm_map_splitentry(struct vm_map*, struct vm_map_entry*, struct vm_map_entry*, vaddr_t); vsize_t uvm_map_boundary(struct vm_map*, vaddr_t, vaddr_t); /* * uvm_vmspace_fork helper functions. */ struct vm_map_entry *uvm_mapent_clone(struct vm_map*, vaddr_t, vsize_t, vsize_t, vm_prot_t, vm_prot_t, struct vm_map_entry*, struct uvm_map_deadq*, int, int); struct vm_map_entry *uvm_mapent_share(struct vm_map*, vaddr_t, vsize_t, vsize_t, vm_prot_t, vm_prot_t, struct vm_map*, struct vm_map_entry*, struct uvm_map_deadq*); struct vm_map_entry *uvm_mapent_forkshared(struct vmspace*, struct vm_map*, struct vm_map*, struct vm_map_entry*, struct uvm_map_deadq*); struct vm_map_entry *uvm_mapent_forkcopy(struct vmspace*, struct vm_map*, struct vm_map*, struct vm_map_entry*, struct uvm_map_deadq*); struct vm_map_entry *uvm_mapent_forkzero(struct vmspace*, struct vm_map*, struct vm_map*, struct vm_map_entry*, struct uvm_map_deadq*); /* * Tree validation. */ #ifdef VMMAP_DEBUG void uvm_tree_assert(struct vm_map*, int, char*, char*, int); #define UVM_ASSERT(map, cond, file, line) \ uvm_tree_assert((map), (cond), #cond, (file), (line)) void uvm_tree_sanity(struct vm_map*, char*, int); void uvm_tree_size_chk(struct vm_map*, char*, int); void vmspace_validate(struct vm_map*); #else #define uvm_tree_sanity(_map, _file, _line) do {} while (0) #define uvm_tree_size_chk(_map, _file, _line) do {} while (0) #define vmspace_validate(_map) do {} while (0) #endif /* * The kernel map will initially be VM_MAP_KSIZE_INIT bytes. * Every time that gets cramped, we grow by at least VM_MAP_KSIZE_DELTA bytes. * * We attempt to grow by UVM_MAP_KSIZE_ALLOCMUL times the allocation size * each time. */ #define VM_MAP_KSIZE_INIT (512 * (vaddr_t)PAGE_SIZE) #define VM_MAP_KSIZE_DELTA (256 * (vaddr_t)PAGE_SIZE) #define VM_MAP_KSIZE_ALLOCMUL 4 /* auto-allocate address lower bound */ #define VMMAP_MIN_ADDR PAGE_SIZE #ifdef DEADBEEF0 #define UVMMAP_DEADBEEF ((unsigned long)DEADBEEF0) #else #define UVMMAP_DEADBEEF ((unsigned long)0xdeadd0d0) #endif #ifdef DEBUG int uvm_map_printlocks = 0; #define LPRINTF(_args) \ do { \ if (uvm_map_printlocks) \ printf _args; \ } while (0) #else #define LPRINTF(_args) do {} while (0) #endif static struct mutex uvm_kmapent_mtx; static struct timeval uvm_kmapent_last_warn_time; static struct timeval uvm_kmapent_warn_rate = { 10, 0 }; const char vmmapbsy[] = "vmmapbsy"; /* * pool for vmspace structures. */ struct pool uvm_vmspace_pool; /* * pool for dynamically-allocated map entries. */ struct pool uvm_map_entry_pool; struct pool uvm_map_entry_kmem_pool; /* * This global represents the end of the kernel virtual address * space. If we want to exceed this, we must grow the kernel * virtual address space dynamically. * * Note, this variable is locked by kernel_map's lock. */ vaddr_t uvm_maxkaddr; /* * Locking predicate. */ #define UVM_MAP_REQ_WRITE(_map) \ do { \ if ((_map)->ref_count > 0) { \ if (((_map)->flags & VM_MAP_INTRSAFE) == 0) \ rw_assert_wrlock(&(_map)->lock); \ else \ MUTEX_ASSERT_LOCKED(&(_map)->mtx); \ } \ } while (0) #define vm_map_modflags(map, set, clear) \ do { \ mtx_enter(&(map)->flags_lock); \ (map)->flags = ((map)->flags | (set)) & ~(clear); \ mtx_leave(&(map)->flags_lock); \ } while (0) /* * Tree describing entries by address. * * Addresses are unique. * Entries with start == end may only exist if they are the first entry * (sorted by address) within a free-memory tree. */ static inline int uvm_mapentry_addrcmp(const struct vm_map_entry *e1, const struct vm_map_entry *e2) { return e1->start < e2->start ? -1 : e1->start > e2->start; } /* * Copy mapentry. */ static inline void uvm_mapent_copy(struct vm_map_entry *src, struct vm_map_entry *dst) { caddr_t csrc, cdst; size_t sz; csrc = (caddr_t)src; cdst = (caddr_t)dst; csrc += offsetof(struct vm_map_entry, uvm_map_entry_start_copy); cdst += offsetof(struct vm_map_entry, uvm_map_entry_start_copy); sz = offsetof(struct vm_map_entry, uvm_map_entry_stop_copy) - offsetof(struct vm_map_entry, uvm_map_entry_start_copy); memcpy(cdst, csrc, sz); } /* * Handle free-list insertion. */ void uvm_mapent_free_insert(struct vm_map *map, struct uvm_addr_state *uaddr, struct vm_map_entry *entry) { const struct uvm_addr_functions *fun; #ifdef VMMAP_DEBUG vaddr_t min, max, bound; #endif #ifdef VMMAP_DEBUG /* * Boundary check. * Boundaries are folded if they go on the same free list. */ min = VMMAP_FREE_START(entry); max = VMMAP_FREE_END(entry); while (min < max) { bound = uvm_map_boundary(map, min, max); KASSERT(uvm_map_uaddr(map, min) == uaddr); min = bound; } #endif KDASSERT((entry->fspace & (vaddr_t)PAGE_MASK) == 0); KASSERT((entry->etype & UVM_ET_FREEMAPPED) == 0); UVM_MAP_REQ_WRITE(map); /* Actual insert: forward to uaddr pointer. */ if (uaddr != NULL) { fun = uaddr->uaddr_functions; KDASSERT(fun != NULL); if (fun->uaddr_free_insert != NULL) (*fun->uaddr_free_insert)(map, uaddr, entry); entry->etype |= UVM_ET_FREEMAPPED; } /* Update fspace augmentation. */ uvm_map_addr_augment(entry); } /* * Handle free-list removal. */ void uvm_mapent_free_remove(struct vm_map *map, struct uvm_addr_state *uaddr, struct vm_map_entry *entry) { const struct uvm_addr_functions *fun; KASSERT((entry->etype & UVM_ET_FREEMAPPED) != 0 || uaddr == NULL); KASSERT(uvm_map_uaddr_e(map, entry) == uaddr); UVM_MAP_REQ_WRITE(map); if (uaddr != NULL) { fun = uaddr->uaddr_functions; if (fun->uaddr_free_remove != NULL) (*fun->uaddr_free_remove)(map, uaddr, entry); entry->etype &= ~UVM_ET_FREEMAPPED; } } /* * Handle address tree insertion. */ void uvm_mapent_addr_insert(struct vm_map *map, struct vm_map_entry *entry) { struct vm_map_entry *res; if (!RBT_CHECK(uvm_map_addr, entry, UVMMAP_DEADBEEF)) panic("uvm_mapent_addr_insert: entry still in addr list"); KDASSERT(entry->start <= entry->end); KDASSERT((entry->start & (vaddr_t)PAGE_MASK) == 0 && (entry->end & (vaddr_t)PAGE_MASK) == 0); TRACEPOINT(uvm, map_insert, entry->start, entry->end, entry->protection, NULL); UVM_MAP_REQ_WRITE(map); res = RBT_INSERT(uvm_map_addr, &map->addr, entry); if (res != NULL) { panic("uvm_mapent_addr_insert: map %p entry %p " "(0x%lx-0x%lx G=0x%lx F=0x%lx) insert collision " "with entry %p (0x%lx-0x%lx G=0x%lx F=0x%lx)", map, entry, entry->start, entry->end, entry->guard, entry->fspace, res, res->start, res->end, res->guard, res->fspace); } } /* * Handle address tree removal. */ void uvm_mapent_addr_remove(struct vm_map *map, struct vm_map_entry *entry) { struct vm_map_entry *res; TRACEPOINT(uvm, map_remove, entry->start, entry->end, entry->protection, NULL); UVM_MAP_REQ_WRITE(map); res = RBT_REMOVE(uvm_map_addr, &map->addr, entry); if (res != entry) panic("uvm_mapent_addr_remove"); RBT_POISON(uvm_map_addr, entry, UVMMAP_DEADBEEF); } /* * uvm_map_reference: add reference to a map * * => map need not be locked */ void uvm_map_reference(struct vm_map *map) { atomic_inc_int(&map->ref_count); } void uvm_map_lock_entry(struct vm_map_entry *entry) { if (entry->aref.ar_amap != NULL) { amap_lock(entry->aref.ar_amap); } if (UVM_ET_ISOBJ(entry)) { rw_enter(entry->object.uvm_obj->vmobjlock, RW_WRITE); } } void uvm_map_unlock_entry(struct vm_map_entry *entry) { if (UVM_ET_ISOBJ(entry)) { rw_exit(entry->object.uvm_obj->vmobjlock); } if (entry->aref.ar_amap != NULL) { amap_unlock(entry->aref.ar_amap); } } /* * Calculate the dused delta. */ vsize_t uvmspace_dused(struct vm_map *map, vaddr_t min, vaddr_t max) { struct vmspace *vm; vsize_t sz; vaddr_t lmax; vaddr_t stack_begin, stack_end; /* Position of stack. */ KASSERT(map->flags & VM_MAP_ISVMSPACE); vm_map_assert_anylock(map); vm = (struct vmspace *)map; stack_begin = MIN((vaddr_t)vm->vm_maxsaddr, (vaddr_t)vm->vm_minsaddr); stack_end = MAX((vaddr_t)vm->vm_maxsaddr, (vaddr_t)vm->vm_minsaddr); sz = 0; while (min != max) { lmax = max; if (min < stack_begin && lmax > stack_begin) lmax = stack_begin; else if (min < stack_end && lmax > stack_end) lmax = stack_end; if (min >= stack_begin && min < stack_end) { /* nothing */ } else sz += lmax - min; min = lmax; } return sz >> PAGE_SHIFT; } /* * Find the entry describing the given address. */ struct vm_map_entry* uvm_map_entrybyaddr(struct uvm_map_addr *atree, vaddr_t addr) { struct vm_map_entry *iter; iter = RBT_ROOT(uvm_map_addr, atree); while (iter != NULL) { if (iter->start > addr) iter = RBT_LEFT(uvm_map_addr, iter); else if (VMMAP_FREE_END(iter) <= addr) iter = RBT_RIGHT(uvm_map_addr, iter); else return iter; } return NULL; } /* * DEAD_ENTRY_PUSH(struct vm_map_deadq *deadq, struct vm_map_entry *entry) * * Push dead entries into a linked list. * Since the linked list abuses the address tree for storage, the entry * may not be linked in a map. * * *head must be initialized to NULL before the first call to this macro. * uvm_unmap_detach(*head, 0) will remove dead entries. */ static inline void dead_entry_push(struct uvm_map_deadq *deadq, struct vm_map_entry *entry) { TAILQ_INSERT_TAIL(deadq, entry, dfree.deadq); } #define DEAD_ENTRY_PUSH(_headptr, _entry) \ dead_entry_push((_headptr), (_entry)) /* * Test if memory starting at addr with sz bytes is free. * * Fills in *start_ptr and *end_ptr to be the first and last entry describing * the space. * If called with prefilled *start_ptr and *end_ptr, they are to be correct. */ int uvm_map_isavail(struct vm_map *map, struct uvm_addr_state *uaddr, struct vm_map_entry **start_ptr, struct vm_map_entry **end_ptr, vaddr_t addr, vsize_t sz) { struct uvm_addr_state *free; struct uvm_map_addr *atree; struct vm_map_entry *i, *i_end; if (addr + sz < addr) return 0; vm_map_assert_anylock(map); /* * Kernel memory above uvm_maxkaddr is considered unavailable. */ if ((map->flags & VM_MAP_ISVMSPACE) == 0) { if (addr + sz > uvm_maxkaddr) return 0; } atree = &map->addr; /* * Fill in first, last, so they point at the entries containing the * first and last address of the range. * Note that if they are not NULL, we don't perform the lookup. */ KDASSERT(atree != NULL && start_ptr != NULL && end_ptr != NULL); if (*start_ptr == NULL) { *start_ptr = uvm_map_entrybyaddr(atree, addr); if (*start_ptr == NULL) return 0; } else KASSERT(*start_ptr == uvm_map_entrybyaddr(atree, addr)); if (*end_ptr == NULL) { if (VMMAP_FREE_END(*start_ptr) >= addr + sz) *end_ptr = *start_ptr; else { *end_ptr = uvm_map_entrybyaddr(atree, addr + sz - 1); if (*end_ptr == NULL) return 0; } } else KASSERT(*end_ptr == uvm_map_entrybyaddr(atree, addr + sz - 1)); /* Validation. */ KDASSERT(*start_ptr != NULL && *end_ptr != NULL); KDASSERT((*start_ptr)->start <= addr && VMMAP_FREE_END(*start_ptr) > addr && (*end_ptr)->start < addr + sz && VMMAP_FREE_END(*end_ptr) >= addr + sz); /* * Check the none of the entries intersects with <addr, addr+sz>. * Also, if the entry belong to uaddr_exe or uaddr_brk_stack, it is * considered unavailable unless called by those allocators. */ i = *start_ptr; i_end = RBT_NEXT(uvm_map_addr, *end_ptr); for (; i != i_end; i = RBT_NEXT(uvm_map_addr, i)) { if (i->start != i->end && i->end > addr) return 0; /* * uaddr_exe and uaddr_brk_stack may only be used * by these allocators and the NULL uaddr (i.e. no * uaddr). * Reject if this requirement is not met. */ if (uaddr != NULL) { free = uvm_map_uaddr_e(map, i); if (uaddr != free && free != NULL && (free == map->uaddr_exe || free == map->uaddr_brk_stack)) return 0; } } return -1; } /* * Invoke each address selector until an address is found. * Will not invoke uaddr_exe. */ int uvm_map_findspace(struct vm_map *map, struct vm_map_entry**first, struct vm_map_entry**last, vaddr_t *addr, vsize_t sz, vaddr_t pmap_align, vaddr_t pmap_offset, vm_prot_t prot, vaddr_t hint) { struct uvm_addr_state *uaddr; int i; /* * Allocation for sz bytes at any address, * using the addr selectors in order. */ for (i = 0; i < nitems(map->uaddr_any); i++) { uaddr = map->uaddr_any[i]; if (uvm_addr_invoke(map, uaddr, first, last, addr, sz, pmap_align, pmap_offset, prot, hint) == 0) return 0; } /* Fall back to brk() and stack() address selectors. */ uaddr = map->uaddr_brk_stack; if (uvm_addr_invoke(map, uaddr, first, last, addr, sz, pmap_align, pmap_offset, prot, hint) == 0) return 0; return ENOMEM; } /* Calculate entry augmentation value. */ vsize_t uvm_map_addr_augment_get(struct vm_map_entry *entry) { vsize_t augment; struct vm_map_entry *left, *right; augment = entry->fspace; if ((left = RBT_LEFT(uvm_map_addr, entry)) != NULL) augment = MAX(augment, left->fspace_augment); if ((right = RBT_RIGHT(uvm_map_addr, entry)) != NULL) augment = MAX(augment, right->fspace_augment); return augment; } /* * Update augmentation data in entry. */ void uvm_map_addr_augment(struct vm_map_entry *entry) { vsize_t augment; while (entry != NULL) { /* Calculate value for augmentation. */ augment = uvm_map_addr_augment_get(entry); /* * Descend update. * Once we find an entry that already has the correct value, * stop, since it means all its parents will use the correct * value too. */ if (entry->fspace_augment == augment) return; entry->fspace_augment = augment; entry = RBT_PARENT(uvm_map_addr, entry); } } /* * uvm_mapanon: establish a valid mapping in map for an anon * * => *addr and sz must be a multiple of PAGE_SIZE. * => *addr is ignored, except if flags contains UVM_FLAG_FIXED. * => map must be unlocked. * * => align: align vaddr, must be a power-of-2. * Align is only a hint and will be ignored if the alignment fails. */ int uvm_mapanon(struct vm_map *map, vaddr_t *addr, vsize_t sz, vsize_t align, unsigned int flags) { struct vm_map_entry *first, *last, *entry, *new; struct uvm_map_deadq dead; vm_prot_t prot; vm_prot_t maxprot; vm_inherit_t inherit; int advice; int error; vaddr_t pmap_align, pmap_offset; vaddr_t hint; KASSERT((map->flags & VM_MAP_ISVMSPACE) == VM_MAP_ISVMSPACE); KASSERT(map != kernel_map); KASSERT((map->flags & UVM_FLAG_HOLE) == 0); KASSERT((map->flags & VM_MAP_INTRSAFE) == 0); splassert(IPL_NONE); KASSERT((flags & UVM_FLAG_TRYLOCK) == 0); /* * We use pmap_align and pmap_offset as alignment and offset variables. * * Because the align parameter takes precedence over pmap prefer, * the pmap_align will need to be set to align, with pmap_offset = 0, * if pmap_prefer will not align. */ pmap_align = MAX(align, PAGE_SIZE); pmap_offset = 0; /* Decode parameters. */ prot = UVM_PROTECTION(flags); maxprot = UVM_MAXPROTECTION(flags); advice = UVM_ADVICE(flags); inherit = UVM_INHERIT(flags); error = 0; hint = trunc_page(*addr); TAILQ_INIT(&dead); KASSERT((sz & (vaddr_t)PAGE_MASK) == 0); KASSERT((align & (align - 1)) == 0); /* Check protection. */ if ((prot & maxprot) != prot) return EACCES; /* * Before grabbing the lock, allocate a map entry for later * use to ensure we don't wait for memory while holding the * vm_map_lock. */ new = uvm_mapent_alloc(map, flags); if (new == NULL) return ENOMEM; vm_map_lock(map); first = last = NULL; if (flags & UVM_FLAG_FIXED) { /* * Fixed location. * * Note: we ignore align, pmap_prefer. * Fill in first, last and *addr. */ KASSERT((*addr & PAGE_MASK) == 0); /* Check that the space is available. */ if (flags & UVM_FLAG_UNMAP) { if ((flags & UVM_FLAG_STACK) && !uvm_map_is_stack_remappable(map, *addr, sz, (flags & UVM_FLAG_SIGALTSTACK))) { error = EINVAL; goto unlock; } if (uvm_unmap_remove(map, *addr, *addr + sz, &dead, FALSE, TRUE, (flags & UVM_FLAG_SIGALTSTACK) ? FALSE : TRUE) != 0) { error = EPERM; /* immutable entries found */ goto unlock; } } if (!uvm_map_isavail(map, NULL, &first, &last, *addr, sz)) { error = ENOMEM; goto unlock; } } else if (*addr != 0 && (*addr & PAGE_MASK) == 0 && (align == 0 || (*addr & (align - 1)) == 0) && uvm_map_isavail(map, NULL, &first, &last, *addr, sz)) { /* * Address used as hint. * * Note: we enforce the alignment restriction, * but ignore pmap_prefer. */ } else if ((prot & PROT_EXEC) != 0 && map->uaddr_exe != NULL) { /* Run selection algorithm for executables. */ error = uvm_addr_invoke(map, map->uaddr_exe, &first, &last, addr, sz, pmap_align, pmap_offset, prot, hint); if (error != 0) goto unlock; } else { /* Update freelists from vmspace. */ uvm_map_vmspace_update(map, &dead, flags); error = uvm_map_findspace(map, &first, &last, addr, sz, pmap_align, pmap_offset, prot, hint); if (error != 0) goto unlock; } /* Double-check if selected address doesn't cause overflow. */ if (*addr + sz < *addr) { error = ENOMEM; goto unlock; } /* If we only want a query, return now. */ if (flags & UVM_FLAG_QUERY) { error = 0; goto unlock; } /* * Create new entry. * first and last may be invalidated after this call. */ entry = uvm_map_mkentry(map, first, last, *addr, sz, flags, &dead, new); if (entry == NULL) { error = ENOMEM; goto unlock; } new = NULL; KDASSERT(entry->start == *addr && entry->end == *addr + sz); entry->object.uvm_obj = NULL; entry->offset = 0; entry->protection = prot; entry->max_protection = maxprot; entry->inheritance = inherit; entry->wired_count = 0; entry->advice = advice; if (flags & UVM_FLAG_STACK) { entry->etype |= UVM_ET_STACK; if (flags & (UVM_FLAG_FIXED | UVM_FLAG_UNMAP)) map->sserial++; } if (flags & UVM_FLAG_COPYONW) { entry->etype |= UVM_ET_COPYONWRITE; if ((flags & UVM_FLAG_OVERLAY) == 0) entry->etype |= UVM_ET_NEEDSCOPY; } if (flags & UVM_FLAG_CONCEAL) entry->etype |= UVM_ET_CONCEAL; if (flags & UVM_FLAG_OVERLAY) { entry->aref.ar_pageoff = 0; entry->aref.ar_amap = amap_alloc(sz, M_WAITOK, 0); } /* Update map and process statistics. */ map->size += sz; if (prot != PROT_NONE) { ((struct vmspace *)map)->vm_dused += uvmspace_dused(map, *addr, *addr + sz); } unlock: vm_map_unlock(map); /* * Remove dead entries. * * Dead entries may be the result of merging. * uvm_map_mkentry may also create dead entries, when it attempts to * destroy free-space entries. */ uvm_unmap_detach(&dead, 0); if (new) uvm_mapent_free(new); return error; } /* * uvm_map: establish a valid mapping in map * * => *addr and sz must be a multiple of PAGE_SIZE. * => map must be unlocked. * => <uobj,uoffset> value meanings (4 cases): * [1] <NULL,uoffset> == uoffset is a hint for PMAP_PREFER * [2] <NULL,UVM_UNKNOWN_OFFSET> == don't PMAP_PREFER * [3] <uobj,uoffset> == normal mapping * [4] <uobj,UVM_UNKNOWN_OFFSET> == uvm_map finds offset based on VA * * case [4] is for kernel mappings where we don't know the offset until * we've found a virtual address. note that kernel object offsets are * always relative to vm_map_min(kernel_map). * * => align: align vaddr, must be a power-of-2. * Align is only a hint and will be ignored if the alignment fails. */ int uvm_map(struct vm_map *map, vaddr_t *addr, vsize_t sz, struct uvm_object *uobj, voff_t uoffset, vsize_t align, unsigned int flags) { struct vm_map_entry *first, *last, *entry, *new; struct uvm_map_deadq dead; vm_prot_t prot; vm_prot_t maxprot; vm_inherit_t inherit; int advice; int error; vaddr_t pmap_align, pmap_offset; vaddr_t hint; if ((map->flags & VM_MAP_INTRSAFE) == 0) splassert(IPL_NONE); else splassert(IPL_VM); /* * We use pmap_align and pmap_offset as alignment and offset variables. * * Because the align parameter takes precedence over pmap prefer, * the pmap_align will need to be set to align, with pmap_offset = 0, * if pmap_prefer will not align. */ if (uoffset == UVM_UNKNOWN_OFFSET) { pmap_align = MAX(align, PAGE_SIZE); pmap_offset = 0; } else { pmap_align = MAX(PMAP_PREFER_ALIGN(), PAGE_SIZE); pmap_offset = PMAP_PREFER_OFFSET(uoffset); if (align == 0 || (align <= pmap_align && (pmap_offset & (align - 1)) == 0)) { /* pmap_offset satisfies align, no change. */ } else { /* Align takes precedence over pmap prefer. */ pmap_align = align; pmap_offset = 0; } } /* Decode parameters. */ prot = UVM_PROTECTION(flags); maxprot = UVM_MAXPROTECTION(flags); advice = UVM_ADVICE(flags); inherit = UVM_INHERIT(flags); error = 0; hint = trunc_page(*addr); TAILQ_INIT(&dead); KASSERT((sz & (vaddr_t)PAGE_MASK) == 0); KASSERT((align & (align - 1)) == 0); /* Holes are incompatible with other types of mappings. */ if (flags & UVM_FLAG_HOLE) { KASSERT(uobj == NULL && (flags & UVM_FLAG_FIXED) && (flags & (UVM_FLAG_OVERLAY | UVM_FLAG_COPYONW)) == 0); } /* Unset hint for kernel_map non-fixed allocations. */ if (!(map->flags & VM_MAP_ISVMSPACE) && !(flags & UVM_FLAG_FIXED)) hint = 0; /* Check protection. */ if ((prot & maxprot) != prot) return EACCES; if (map == kernel_map && (prot & (PROT_WRITE | PROT_EXEC)) == (PROT_WRITE | PROT_EXEC)) panic("uvm_map: kernel map W^X violation requested"); /* * Before grabbing the lock, allocate a map entry for later * use to ensure we don't wait for memory while holding the * vm_map_lock. */ new = uvm_mapent_alloc(map, flags); if (new == NULL) return ENOMEM; if (flags & UVM_FLAG_TRYLOCK) { if (vm_map_lock_try(map) == FALSE) { error = EFAULT; goto out; } } else { vm_map_lock(map); } first = last = NULL; if (flags & UVM_FLAG_FIXED) { /* * Fixed location. * * Note: we ignore align, pmap_prefer. * Fill in first, last and *addr. */ KASSERT((*addr & PAGE_MASK) == 0); /* * Grow pmap to include allocated address. * If the growth fails, the allocation will fail too. */ if ((map->flags & VM_MAP_ISVMSPACE) == 0 && uvm_maxkaddr < (*addr + sz)) { uvm_map_kmem_grow(map, &dead, *addr + sz - uvm_maxkaddr, flags); } /* Check that the space is available. */ if (flags & UVM_FLAG_UNMAP) { if (uvm_unmap_remove(map, *addr, *addr + sz, &dead, FALSE, TRUE, TRUE) != 0) { error = EPERM; /* immutable entries found */ goto unlock; } } if (!uvm_map_isavail(map, NULL, &first, &last, *addr, sz)) { error = ENOMEM; goto unlock; } } else if (*addr != 0 && (*addr & PAGE_MASK) == 0 && (map->flags & VM_MAP_ISVMSPACE) == VM_MAP_ISVMSPACE && (align == 0 || (*addr & (align - 1)) == 0) && uvm_map_isavail(map, NULL, &first, &last, *addr, sz)) { /* * Address used as hint. * * Note: we enforce the alignment restriction, * but ignore pmap_prefer. */ } else if ((prot & PROT_EXEC) != 0 && map->uaddr_exe != NULL) { /* Run selection algorithm for executables. */ error = uvm_addr_invoke(map, map->uaddr_exe, &first, &last, addr, sz, pmap_align, pmap_offset, prot, hint); /* Grow kernel memory and try again. */ if (error != 0 && (map->flags & VM_MAP_ISVMSPACE) == 0) { uvm_map_kmem_grow(map, &dead, sz, flags); error = uvm_addr_invoke(map, map->uaddr_exe, &first, &last, addr, sz, pmap_align, pmap_offset, prot, hint); } if (error != 0) goto unlock; } else { /* Update freelists from vmspace. */ if (map->flags & VM_MAP_ISVMSPACE) uvm_map_vmspace_update(map, &dead, flags); error = uvm_map_findspace(map, &first, &last, addr, sz, pmap_align, pmap_offset, prot, hint); /* Grow kernel memory and try again. */ if (error != 0 && (map->flags & VM_MAP_ISVMSPACE) == 0) { uvm_map_kmem_grow(map, &dead, sz, flags); error = uvm_map_findspace(map, &first, &last, addr, sz, pmap_align, pmap_offset, prot, hint); } if (error != 0) goto unlock; } /* Double-check if selected address doesn't cause overflow. */ if (*addr + sz < *addr) { error = ENOMEM; goto unlock; } KASSERT((map->flags & VM_MAP_ISVMSPACE) == VM_MAP_ISVMSPACE || uvm_maxkaddr >= *addr + sz); /* If we only want a query, return now. */ if (flags & UVM_FLAG_QUERY) { error = 0; goto unlock; } if (uobj == NULL) uoffset = 0; else if (uoffset == UVM_UNKNOWN_OFFSET) { KASSERT(UVM_OBJ_IS_KERN_OBJECT(uobj)); uoffset = *addr - vm_map_min(kernel_map); } /* * Create new entry. * first and last may be invalidated after this call. */ entry = uvm_map_mkentry(map, first, last, *addr, sz, flags, &dead, new); if (entry == NULL) { error = ENOMEM; goto unlock; } new = NULL; KDASSERT(entry->start == *addr && entry->end == *addr + sz); entry->object.uvm_obj = uobj; entry->offset = uoffset; entry->protection = prot; entry->max_protection = maxprot; entry->inheritance = inherit; entry->wired_count = 0; entry->advice = advice; if (flags & UVM_FLAG_STACK) { entry->etype |= UVM_ET_STACK; if (flags & UVM_FLAG_UNMAP) map->sserial++; } if (uobj) entry->etype |= UVM_ET_OBJ; else if (flags & UVM_FLAG_HOLE) entry->etype |= UVM_ET_HOLE; if (flags & UVM_FLAG_NOFAULT) entry->etype |= UVM_ET_NOFAULT; if (flags & UVM_FLAG_WC) entry->etype |= UVM_ET_WC; if (flags & UVM_FLAG_COPYONW) { entry->etype |= UVM_ET_COPYONWRITE; if ((flags & UVM_FLAG_OVERLAY) == 0) entry->etype |= UVM_ET_NEEDSCOPY; } if (flags & UVM_FLAG_CONCEAL) entry->etype |= UVM_ET_CONCEAL; if (flags & UVM_FLAG_OVERLAY) { entry->aref.ar_pageoff = 0; entry->aref.ar_amap = amap_alloc(sz, M_WAITOK, 0); } /* Update map and process statistics. */ if (!(flags & UVM_FLAG_HOLE)) { map->size += sz; if ((map->flags & VM_MAP_ISVMSPACE) && uobj == NULL && prot != PROT_NONE) { ((struct vmspace *)map)->vm_dused += uvmspace_dused(map, *addr, *addr + sz); } } /* * Try to merge entry. * * Userland allocations are kept separated most of the time. * Forego the effort of merging what most of the time can't be merged * and only try the merge if it concerns a kernel entry. */ if ((flags & UVM_FLAG_NOMERGE) == 0 && (map->flags & VM_MAP_ISVMSPACE) == 0) uvm_mapent_tryjoin(map, entry, &dead); unlock: vm_map_unlock(map); /* * Remove dead entries. * * Dead entries may be the result of merging. * uvm_map_mkentry may also create dead entries, when it attempts to * destroy free-space entries. */ if (map->flags & VM_MAP_INTRSAFE) uvm_unmap_detach_intrsafe(&dead); else uvm_unmap_detach(&dead, 0); out: if (new) uvm_mapent_free(new); return error; } /* * True iff e1 and e2 can be joined together. */ int uvm_mapent_isjoinable(struct vm_map *map, struct vm_map_entry *e1, struct vm_map_entry *e2) { KDASSERT(e1 != NULL && e2 != NULL); /* Must be the same entry type and not have free memory between. */ if (e1->etype != e2->etype || e1->end != e2->start) return 0; /* Submaps are never joined. */ if (UVM_ET_ISSUBMAP(e1)) return 0; /* Never merge wired memory. */ if (VM_MAPENT_ISWIRED(e1) || VM_MAPENT_ISWIRED(e2)) return 0; /* Protection, inheritance and advice must be equal. */ if (e1->protection != e2->protection || e1->max_protection != e2->max_protection || e1->inheritance != e2->inheritance || e1->advice != e2->advice) return 0; /* If uvm_object: object itself and offsets within object must match. */ if (UVM_ET_ISOBJ(e1)) { if (e1->object.uvm_obj != e2->object.uvm_obj) return 0; if (e1->offset + (e1->end - e1->start) != e2->offset) return 0; } /* * Cannot join shared amaps. * Note: no need to lock amap to look at refs, since we don't care * about its exact value. * If it is 1 (i.e. we have the only reference) it will stay there. */ if (e1->aref.ar_amap && amap_refs(e1->aref.ar_amap) != 1) return 0; if (e2->aref.ar_amap && amap_refs(e2->aref.ar_amap) != 1) return 0; /* Apparently, e1 and e2 match. */ return 1; } /* * Join support function. * * Returns the merged entry on success. * Returns NULL if the merge failed. */ struct vm_map_entry* uvm_mapent_merge(struct vm_map *map, struct vm_map_entry *e1, struct vm_map_entry *e2, struct uvm_map_deadq *dead) { struct uvm_addr_state *free; /* * Merging is not supported for map entries that * contain an amap in e1. This should never happen * anyway, because only kernel entries are merged. * These do not contain amaps. * e2 contains no real information in its amap, * so it can be erased immediately. */ KASSERT(e1->aref.ar_amap == NULL); /* * Don't drop obj reference: * uvm_unmap_detach will do this for us. */ free = uvm_map_uaddr_e(map, e1); uvm_mapent_free_remove(map, free, e1); free = uvm_map_uaddr_e(map, e2); uvm_mapent_free_remove(map, free, e2); uvm_mapent_addr_remove(map, e2); e1->end = e2->end; e1->guard = e2->guard; e1->fspace = e2->fspace; uvm_mapent_free_insert(map, free, e1); DEAD_ENTRY_PUSH(dead, e2); return e1; } /* * Attempt forward and backward joining of entry. * * Returns entry after joins. * We are guaranteed that the amap of entry is either non-existent or * has never been used. */ struct vm_map_entry* uvm_mapent_tryjoin(struct vm_map *map, struct vm_map_entry *entry, struct uvm_map_deadq *dead) { struct vm_map_entry *other; struct vm_map_entry *merged; /* Merge with previous entry. */ other = RBT_PREV(uvm_map_addr, entry); if (other && uvm_mapent_isjoinable(map, other, entry)) { merged = uvm_mapent_merge(map, other, entry, dead); if (merged) entry = merged; } /* * Merge with next entry. * * Because amap can only extend forward and the next entry * probably contains sensible info, only perform forward merging * in the absence of an amap. */ other = RBT_NEXT(uvm_map_addr, entry); if (other && entry->aref.ar_amap == NULL && other->aref.ar_amap == NULL && uvm_mapent_isjoinable(map, entry, other)) { merged = uvm_mapent_merge(map, entry, other, dead); if (merged) entry = merged; } return entry; } /* * Kill entries that are no longer in a map. */ void uvm_unmap_detach(struct uvm_map_deadq *deadq, int flags) { struct vm_map_entry *entry, *tmp; int waitok = flags & UVM_PLA_WAITOK; TAILQ_FOREACH_SAFE(entry, deadq, dfree.deadq, tmp) { /* Drop reference to amap, if we've got one. */ if (entry->aref.ar_amap) amap_unref(entry->aref.ar_amap, entry->aref.ar_pageoff, atop(entry->end - entry->start), flags & AMAP_REFALL); /* Skip entries for which we have to grab the kernel lock. */ if (UVM_ET_ISSUBMAP(entry) || UVM_ET_ISOBJ(entry)) continue; TAILQ_REMOVE(deadq, entry, dfree.deadq); uvm_mapent_free(entry); } if (TAILQ_EMPTY(deadq)) return; KERNEL_LOCK(); while ((entry = TAILQ_FIRST(deadq)) != NULL) { if (waitok) uvm_pause(); /* Drop reference to our backing object, if we've got one. */ if (UVM_ET_ISSUBMAP(entry)) { /* ... unlikely to happen, but play it safe */ uvm_map_deallocate(entry->object.sub_map); } else if (UVM_ET_ISOBJ(entry) && entry->object.uvm_obj->pgops->pgo_detach) { entry->object.uvm_obj->pgops->pgo_detach( entry->object.uvm_obj); } /* Step to next. */ TAILQ_REMOVE(deadq, entry, dfree.deadq); uvm_mapent_free(entry); } KERNEL_UNLOCK(); } void uvm_unmap_detach_intrsafe(struct uvm_map_deadq *deadq) { struct vm_map_entry *entry; while ((entry = TAILQ_FIRST(deadq)) != NULL) { KASSERT(entry->aref.ar_amap == NULL); KASSERT(!UVM_ET_ISSUBMAP(entry)); KASSERT(!UVM_ET_ISOBJ(entry)); TAILQ_REMOVE(deadq, entry, dfree.deadq); uvm_mapent_free(entry); } } /* * Create and insert new entry. * * Returned entry contains new addresses and is inserted properly in the tree. * first and last are (probably) no longer valid. */ struct vm_map_entry* uvm_map_mkentry(struct vm_map *map, struct vm_map_entry *first, struct vm_map_entry *last, vaddr_t addr, vsize_t sz, int flags, struct uvm_map_deadq *dead, struct vm_map_entry *new) { struct vm_map_entry *entry, *prev; struct uvm_addr_state *free; vaddr_t min, max; /* free space boundaries for new entry */ KDASSERT(map != NULL); KDASSERT(first != NULL); KDASSERT(last != NULL); KDASSERT(dead != NULL); KDASSERT(sz > 0); KDASSERT(addr + sz > addr); KDASSERT(first->end <= addr && VMMAP_FREE_END(first) > addr); KDASSERT(last->start < addr + sz && VMMAP_FREE_END(last) >= addr + sz); KDASSERT(uvm_map_isavail(map, NULL, &first, &last, addr, sz)); uvm_tree_sanity(map, __FILE__, __LINE__); min = addr + sz; max = VMMAP_FREE_END(last); /* Initialize new entry. */ if (new == NULL) entry = uvm_mapent_alloc(map, flags); else entry = new; if (entry == NULL) return NULL; entry->offset = 0; entry->etype = 0; entry->wired_count = 0; entry->aref.ar_pageoff = 0; entry->aref.ar_amap = NULL; entry->start = addr; entry->end = min; entry->guard = 0; entry->fspace = 0; vm_map_assert_wrlock(map); /* Reset free space in first. */ free = uvm_map_uaddr_e(map, first); uvm_mapent_free_remove(map, free, first); first->guard = 0; first->fspace = 0; /* * Remove all entries that are fully replaced. * We are iterating using last in reverse order. */ for (; first != last; last = prev) { prev = RBT_PREV(uvm_map_addr, last); KDASSERT(last->start == last->end); free = uvm_map_uaddr_e(map, last); uvm_mapent_free_remove(map, free, last); uvm_mapent_addr_remove(map, last); DEAD_ENTRY_PUSH(dead, last); } /* Remove first if it is entirely inside <addr, addr+sz>. */ if (first->start == addr) { uvm_mapent_addr_remove(map, first); DEAD_ENTRY_PUSH(dead, first); } else { uvm_map_fix_space(map, first, VMMAP_FREE_START(first), addr, flags); } /* Finally, link in entry. */ uvm_mapent_addr_insert(map, entry); uvm_map_fix_space(map, entry, min, max, flags); uvm_tree_sanity(map, __FILE__, __LINE__); return entry; } /* * uvm_mapent_alloc: allocate a map entry */ struct vm_map_entry * uvm_mapent_alloc(struct vm_map *map, int flags) { struct vm_map_entry *me, *ne; int pool_flags; int i; pool_flags = PR_WAITOK; if (flags & UVM_FLAG_TRYLOCK) pool_flags = PR_NOWAIT; if (map->flags & VM_MAP_INTRSAFE || cold) { mtx_enter(&uvm_kmapent_mtx); if (SLIST_EMPTY(&uvm.kentry_free)) { ne = km_alloc(PAGE_SIZE, &kv_page, &kp_dirty, &kd_nowait); if (ne == NULL) panic("uvm_mapent_alloc: cannot allocate map " "entry"); for (i = 0; i < PAGE_SIZE / sizeof(*ne); i++) { SLIST_INSERT_HEAD(&uvm.kentry_free, &ne[i], daddrs.addr_kentry); } if (ratecheck(&uvm_kmapent_last_warn_time, &uvm_kmapent_warn_rate)) printf("uvm_mapent_alloc: out of static " "map entries\n"); } me = SLIST_FIRST(&uvm.kentry_free); SLIST_REMOVE_HEAD(&uvm.kentry_free, daddrs.addr_kentry); uvmexp.kmapent++; mtx_leave(&uvm_kmapent_mtx); me->flags = UVM_MAP_STATIC; } else if (map == kernel_map) { splassert(IPL_NONE); me = pool_get(&uvm_map_entry_kmem_pool, pool_flags); if (me == NULL) goto out; me->flags = UVM_MAP_KMEM; } else { splassert(IPL_NONE); me = pool_get(&uvm_map_entry_pool, pool_flags); if (me == NULL) goto out; me->flags = 0; } RBT_POISON(uvm_map_addr, me, UVMMAP_DEADBEEF); out: return me; } /* * uvm_mapent_free: free map entry * * => XXX: static pool for kernel map? */ void uvm_mapent_free(struct vm_map_entry *me) { if (me->flags & UVM_MAP_STATIC) { mtx_enter(&uvm_kmapent_mtx); SLIST_INSERT_HEAD(&uvm.kentry_free, me, daddrs.addr_kentry); uvmexp.kmapent--; mtx_leave(&uvm_kmapent_mtx); } else if (me->flags & UVM_MAP_KMEM) { splassert(IPL_NONE); pool_put(&uvm_map_entry_kmem_pool, me); } else { splassert(IPL_NONE); pool_put(&uvm_map_entry_pool, me); } } /* * uvm_map_lookup_entry: find map entry at or before an address. * * => map must at least be read-locked by caller * => entry is returned in "entry" * => return value is true if address is in the returned entry * ET_HOLE entries are considered to not contain a mapping, ergo FALSE is * returned for those mappings. */ boolean_t uvm_map_lookup_entry(struct vm_map *map, vaddr_t address, struct vm_map_entry **entry) { vm_map_assert_anylock(map); *entry = uvm_map_entrybyaddr(&map->addr, address); return *entry != NULL && !UVM_ET_ISHOLE(*entry) && (*entry)->start <= address && (*entry)->end > address; } /* * Stack must be in a MAP_STACK entry. PROT_NONE indicates stack not yet * grown -- then uvm_map_check_region_range() should not cache the entry * because growth won't be seen. */ int uvm_map_inentry_sp(vm_map_entry_t entry) { if ((entry->etype & UVM_ET_STACK) == 0) { if (entry->protection == PROT_NONE) return (-1); /* don't update range */ return (0); } return (1); } int uvm_map_inentry_recheck(u_long serial, vaddr_t addr, struct p_inentry *ie) { return (serial != ie->ie_serial || ie->ie_start == 0 || addr < ie->ie_start || addr >= ie->ie_end); } /* * Inside a vm_map find the reg address and verify it via function. * Remember low and high addresses of region if valid and return TRUE, * else return FALSE. */ boolean_t uvm_map_inentry_fix(struct proc *p, struct p_inentry *ie, vaddr_t addr, int (*fn)(vm_map_entry_t), u_long serial) { vm_map_t map = &p->p_vmspace->vm_map; vm_map_entry_t entry; int ret; if (addr < map->min_offset || addr >= map->max_offset) return (FALSE); /* lock map */ vm_map_lock_read(map); /* lookup */ if (!uvm_map_lookup_entry(map, trunc_page(addr), &entry)) { vm_map_unlock_read(map); return (FALSE); } ret = (*fn)(entry); if (ret == 0) { vm_map_unlock_read(map); return (FALSE); } else if (ret == 1) { ie->ie_start = entry->start; ie->ie_end = entry->end; ie->ie_serial = serial; } else { /* do not update, re-check later */ } vm_map_unlock_read(map); return (TRUE); } boolean_t uvm_map_inentry(struct proc *p, struct p_inentry *ie, vaddr_t addr, const char *fmt, int (*fn)(vm_map_entry_t), u_long serial) { union sigval sv; boolean_t ok = TRUE; if (uvm_map_inentry_recheck(serial, addr, ie)) { ok = uvm_map_inentry_fix(p, ie, addr, fn, serial); if (!ok) { KERNEL_LOCK(); printf(fmt, p->p_p->ps_comm, p->p_p->ps_pid, p->p_tid, addr, ie->ie_start, ie->ie_end-1); p->p_p->ps_acflag |= AMAP; sv.sival_ptr = (void *)PROC_PC(p); trapsignal(p, SIGSEGV, 0, SEGV_ACCERR, sv); KERNEL_UNLOCK(); } } return (ok); } /* * Check whether the given address range can be converted to a MAP_STACK * mapping. * * Must be called with map locked. */ boolean_t uvm_map_is_stack_remappable(struct vm_map *map, vaddr_t addr, vaddr_t sz, int sigaltstack_check) { vaddr_t end = addr + sz; struct vm_map_entry *first, *iter, *prev = NULL; vm_map_assert_anylock(map); if (!uvm_map_lookup_entry(map, addr, &first)) { printf("map stack 0x%lx-0x%lx of map %p failed: no mapping\n", addr, end, map); return FALSE; } /* * Check that the address range exists and is contiguous. */ for (iter = first; iter != NULL && iter->start < end; prev = iter, iter = RBT_NEXT(uvm_map_addr, iter)) { /* * Make sure that we do not have holes in the range. */ #if 0 if (prev != NULL) { printf("prev->start 0x%lx, prev->end 0x%lx, " "iter->start 0x%lx, iter->end 0x%lx\n", prev->start, prev->end, iter->start, iter->end); } #endif if (prev != NULL && prev->end != iter->start) { printf("map stack 0x%lx-0x%lx of map %p failed: " "hole in range\n", addr, end, map); return FALSE; } if (iter->start == iter->end || UVM_ET_ISHOLE(iter)) { printf("map stack 0x%lx-0x%lx of map %p failed: " "hole in range\n", addr, end, map); return FALSE; } if (sigaltstack_check) { if (iter->protection != (PROT_READ | PROT_WRITE)) return FALSE; } } return TRUE; } /* * Remap the middle-pages of an existing mapping as a stack range. * If there exists a previous contiguous mapping with the given range * [addr, addr + sz), with protection PROT_READ|PROT_WRITE, then the * mapping is dropped, and a new anon mapping is created and marked as * a stack. * * Must be called with map unlocked. */ int uvm_map_remap_as_stack(struct proc *p, vaddr_t addr, vaddr_t sz) { vm_map_t map = &p->p_vmspace->vm_map; vaddr_t start, end; int error; int flags = UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_INHERIT_COPY, MADV_NORMAL, UVM_FLAG_STACK | UVM_FLAG_FIXED | UVM_FLAG_UNMAP | UVM_FLAG_COPYONW | UVM_FLAG_SIGALTSTACK); start = round_page(addr); end = trunc_page(addr + sz); #ifdef MACHINE_STACK_GROWS_UP if (end == addr + sz) end -= PAGE_SIZE; #else if (start == addr) start += PAGE_SIZE; #endif if (start < map->min_offset || end >= map->max_offset || end < start) return EINVAL; /* * UVM_FLAG_SIGALTSTACK indicates that immutable may be bypassed, * but the range is checked that it is contiguous, is not a syscall * mapping, and protection RW. Then, a new mapping (all zero) is * placed upon the region, which prevents an attacker from pivoting * into pre-placed MAP_STACK space. */ error = uvm_mapanon(map, &start, end - start, 0, flags); if (error != 0) printf("map stack for pid %d failed\n", p->p_p->ps_pid); return error; } /* * uvm_map_pie: return a random load address for a PIE executable * properly aligned. */ #ifndef VM_PIE_MAX_ADDR #define VM_PIE_MAX_ADDR (VM_MAXUSER_ADDRESS / 4) #endif #ifndef VM_PIE_MIN_ADDR #define VM_PIE_MIN_ADDR VM_MIN_ADDRESS #endif #ifndef VM_PIE_MIN_ALIGN #define VM_PIE_MIN_ALIGN PAGE_SIZE #endif vaddr_t uvm_map_pie(vaddr_t align) { vaddr_t addr, space, min; align = MAX(align, VM_PIE_MIN_ALIGN); /* round up to next alignment */ min = (VM_PIE_MIN_ADDR + align - 1) & ~(align - 1); if (align >= VM_PIE_MAX_ADDR || min >= VM_PIE_MAX_ADDR) return (align); space = (VM_PIE_MAX_ADDR - min) / align; space = MIN(space, (u_int32_t)-1); addr = (vaddr_t)arc4random_uniform((u_int32_t)space) * align; addr += min; return (addr); } void uvm_unmap(struct vm_map *map, vaddr_t start, vaddr_t end) { struct uvm_map_deadq dead; KASSERT((start & (vaddr_t)PAGE_MASK) == 0 && (end & (vaddr_t)PAGE_MASK) == 0); TAILQ_INIT(&dead); vm_map_lock(map); uvm_unmap_remove(map, start, end, &dead, FALSE, TRUE, FALSE); vm_map_unlock(map); if (map->flags & VM_MAP_INTRSAFE) uvm_unmap_detach_intrsafe(&dead); else uvm_unmap_detach(&dead, 0); } /* * Mark entry as free. * * entry will be put on the dead list. * The free space will be merged into the previous or a new entry, * unless markfree is false. */ void uvm_mapent_mkfree(struct vm_map *map, struct vm_map_entry *entry, struct vm_map_entry **prev_ptr, struct uvm_map_deadq *dead, boolean_t markfree) { struct uvm_addr_state *free; struct vm_map_entry *prev; vaddr_t addr; /* Start of freed range. */ vaddr_t end; /* End of freed range. */ UVM_MAP_REQ_WRITE(map); prev = *prev_ptr; if (prev == entry) *prev_ptr = prev = NULL; if (prev == NULL || VMMAP_FREE_END(prev) != entry->start) prev = RBT_PREV(uvm_map_addr, entry); /* Entry is describing only free memory and has nothing to drain into. */ if (prev == NULL && entry->start == entry->end && markfree) { *prev_ptr = entry; return; } addr = entry->start; end = VMMAP_FREE_END(entry); free = uvm_map_uaddr_e(map, entry); uvm_mapent_free_remove(map, free, entry); uvm_mapent_addr_remove(map, entry); DEAD_ENTRY_PUSH(dead, entry); if (markfree) { if (prev) { free = uvm_map_uaddr_e(map, prev); uvm_mapent_free_remove(map, free, prev); } *prev_ptr = uvm_map_fix_space(map, prev, addr, end, 0); } } /* * Unwire and release referenced amap and object from map entry. */ void uvm_unmap_kill_entry_withlock(struct vm_map *map, struct vm_map_entry *entry, int needlock) { /* Unwire removed map entry. */ if (VM_MAPENT_ISWIRED(entry)) { KERNEL_LOCK(); entry->wired_count = 0; uvm_fault_unwire_locked(map, entry->start, entry->end); KERNEL_UNLOCK(); } if (needlock) uvm_map_lock_entry(entry); /* Entry-type specific code. */ if (UVM_ET_ISHOLE(entry)) { /* Nothing to be done for holes. */ } else if (map->flags & VM_MAP_INTRSAFE) { KASSERT(vm_map_pmap(map) == pmap_kernel()); uvm_km_pgremove_intrsafe(entry->start, entry->end); } else if (UVM_ET_ISOBJ(entry) && UVM_OBJ_IS_KERN_OBJECT(entry->object.uvm_obj)) { KASSERT(vm_map_pmap(map) == pmap_kernel()); /* * Note: kernel object mappings are currently used in * two ways: * [1] "normal" mappings of pages in the kernel object * [2] uvm_km_valloc'd allocations in which we * pmap_enter in some non-kernel-object page * (e.g. vmapbuf). * * for case [1], we need to remove the mapping from * the pmap and then remove the page from the kernel * object (because, once pages in a kernel object are * unmapped they are no longer needed, unlike, say, * a vnode where you might want the data to persist * until flushed out of a queue). * * for case [2], we need to remove the mapping from * the pmap. there shouldn't be any pages at the * specified offset in the kernel object [but it * doesn't hurt to call uvm_km_pgremove just to be * safe?] * * uvm_km_pgremove currently does the following: * for pages in the kernel object range: * - drops the swap slot * - uvm_pagefree the page * * note there is version of uvm_km_pgremove() that * is used for "intrsafe" objects. */ /* * remove mappings from pmap and drop the pages * from the object. offsets are always relative * to vm_map_min(kernel_map). */ uvm_km_pgremove(entry->object.uvm_obj, entry->start, entry->end); } else { /* remove mappings the standard way. */ pmap_remove(map->pmap, entry->start, entry->end); } if (needlock) uvm_map_unlock_entry(entry); } void uvm_unmap_kill_entry(struct vm_map *map, struct vm_map_entry *entry) { uvm_unmap_kill_entry_withlock(map, entry, 0); } /* * Remove all entries from start to end. * * If remove_holes, then remove ET_HOLE entries as well. * If markfree, entry will be properly marked free, otherwise, no replacement * entry will be put in the tree (corrupting the tree). */ int uvm_unmap_remove(struct vm_map *map, vaddr_t start, vaddr_t end, struct uvm_map_deadq *dead, boolean_t remove_holes, boolean_t markfree, boolean_t checkimmutable) { struct vm_map_entry *prev_hint, *next, *entry; start = MAX(start, map->min_offset); end = MIN(end, map->max_offset); if (start >= end) return 0; vm_map_assert_wrlock(map); /* Find first affected entry. */ entry = uvm_map_entrybyaddr(&map->addr, start); KDASSERT(entry != NULL && entry->start <= start); if (checkimmutable) { struct vm_map_entry *entry1 = entry; /* Refuse to unmap if any entries are immutable */ if (entry1->end <= start) entry1 = RBT_NEXT(uvm_map_addr, entry1); for (; entry1 != NULL && entry1->start < end; entry1 = next) { KDASSERT(entry1->start >= start); next = RBT_NEXT(uvm_map_addr, entry1); /* Treat memory holes as free space. */ if (entry1->start == entry1->end || UVM_ET_ISHOLE(entry1)) continue; if (entry1->etype & UVM_ET_IMMUTABLE) return EPERM; } } if (entry->end <= start && markfree) entry = RBT_NEXT(uvm_map_addr, entry); else UVM_MAP_CLIP_START(map, entry, start); /* * Iterate entries until we reach end address. * prev_hint hints where the freed space can be appended to. */ prev_hint = NULL; for (; entry != NULL && entry->start < end; entry = next) { KDASSERT(entry->start >= start); if (entry->end > end || !markfree) UVM_MAP_CLIP_END(map, entry, end); KDASSERT(entry->start >= start && entry->end <= end); next = RBT_NEXT(uvm_map_addr, entry); /* Don't remove holes unless asked to do so. */ if (UVM_ET_ISHOLE(entry)) { if (!remove_holes) { prev_hint = entry; continue; } } /* A stack has been removed.. */ if (UVM_ET_ISSTACK(entry) && (map->flags & VM_MAP_ISVMSPACE)) map->sserial++; /* Kill entry. */ uvm_unmap_kill_entry_withlock(map, entry, 1); /* Update space usage. */ if ((map->flags & VM_MAP_ISVMSPACE) && entry->object.uvm_obj == NULL && entry->protection != PROT_NONE && !UVM_ET_ISHOLE(entry)) { ((struct vmspace *)map)->vm_dused -= uvmspace_dused(map, entry->start, entry->end); } if (!UVM_ET_ISHOLE(entry)) map->size -= entry->end - entry->start; /* Actual removal of entry. */ uvm_mapent_mkfree(map, entry, &prev_hint, dead, markfree); } pmap_update(vm_map_pmap(map)); #ifdef VMMAP_DEBUG if (markfree) { for (entry = uvm_map_entrybyaddr(&map->addr, start); entry != NULL && entry->start < end; entry = RBT_NEXT(uvm_map_addr, entry)) { KDASSERT(entry->end <= start || entry->start == entry->end || UVM_ET_ISHOLE(entry)); } } else { vaddr_t a; for (a = start; a < end; a += PAGE_SIZE) KDASSERT(uvm_map_entrybyaddr(&map->addr, a) == NULL); } #endif return 0; } /* * Mark all entries from first until end (exclusive) as pageable. * * Lock must be exclusive on entry and will not be touched. */ void uvm_map_pageable_pgon(struct vm_map *map, struct vm_map_entry *first, struct vm_map_entry *end, vaddr_t start_addr, vaddr_t end_addr) { struct vm_map_entry *iter; for (iter = first; iter != end; iter = RBT_NEXT(uvm_map_addr, iter)) { KDASSERT(iter->start >= start_addr && iter->end <= end_addr); if (!VM_MAPENT_ISWIRED(iter) || UVM_ET_ISHOLE(iter)) continue; iter->wired_count = 0; uvm_fault_unwire_locked(map, iter->start, iter->end); } } /* * Mark all entries from first until end (exclusive) as wired. * * Lockflags determines the lock state on return from this function. * Lock must be exclusive on entry. */ int uvm_map_pageable_wire(struct vm_map *map, struct vm_map_entry *first, struct vm_map_entry *end, vaddr_t start_addr, vaddr_t end_addr, int lockflags) { struct vm_map_entry *iter; #ifdef DIAGNOSTIC unsigned int timestamp_save; #endif int error; /* * Wire pages in two passes: * * 1: holding the write lock, we create any anonymous maps that need * to be created. then we clip each map entry to the region to * be wired and increment its wiring count. * * 2: we mark the map busy, unlock it and call uvm_fault_wire to fault * in the pages for any newly wired area (wired_count == 1). */ for (iter = first; iter != end; iter = RBT_NEXT(uvm_map_addr, iter)) { KDASSERT(iter->start >= start_addr && iter->end <= end_addr); if (UVM_ET_ISHOLE(iter) || iter->start == iter->end || iter->protection == PROT_NONE) continue; /* * Perform actions of vm_map_lookup that need the write lock. * - create an anonymous map for copy-on-write * - anonymous map for zero-fill * Skip submaps. */ if (!VM_MAPENT_ISWIRED(iter) && !UVM_ET_ISSUBMAP(iter) && UVM_ET_ISNEEDSCOPY(iter) && ((iter->protection & PROT_WRITE) || iter->object.uvm_obj == NULL)) { amap_copy(map, iter, M_WAITOK, UVM_ET_ISSTACK(iter) ? FALSE : TRUE, iter->start, iter->end); } iter->wired_count++; } /* * Pass 2. */ #ifdef DIAGNOSTIC timestamp_save = map->timestamp; #endif vm_map_busy(map); vm_map_unlock(map); error = 0; for (iter = first; error == 0 && iter != end; iter = RBT_NEXT(uvm_map_addr, iter)) { if (UVM_ET_ISHOLE(iter) || iter->start == iter->end || iter->protection == PROT_NONE) continue; error = uvm_fault_wire(map, iter->start, iter->end, iter->protection); } vm_map_lock(map); vm_map_unbusy(map); if (error) { #ifdef DIAGNOSTIC if (timestamp_save != map->timestamp) panic("uvm_map_pageable_wire: stale map"); #endif /* * first is no longer needed to restart loops. * Use it as iterator to unmap successful mappings. */ for (; first != iter; first = RBT_NEXT(uvm_map_addr, first)) { if (UVM_ET_ISHOLE(first) || first->start == first->end || first->protection == PROT_NONE) continue; first->wired_count--; if (!VM_MAPENT_ISWIRED(first)) { uvm_fault_unwire_locked(map, first->start, first->end); } } /* decrease counter in the rest of the entries */ for (; iter != end; iter = RBT_NEXT(uvm_map_addr, iter)) { if (UVM_ET_ISHOLE(iter) || iter->start == iter->end || iter->protection == PROT_NONE) continue; iter->wired_count--; } if ((lockflags & UVM_LK_EXIT) == 0) vm_map_unlock(map); return error; } if ((lockflags & UVM_LK_EXIT) == 0) { vm_map_unlock(map); } else { #ifdef DIAGNOSTIC if (timestamp_save != map->timestamp) panic("uvm_map_pageable_wire: stale map"); #endif } return 0; } /* * uvm_map_pageable: set pageability of a range in a map. * * Flags: * UVM_LK_ENTER: map is already locked by caller * UVM_LK_EXIT: don't unlock map on exit * * The full range must be in use (entries may not have fspace != 0). * UVM_ET_HOLE counts as unmapped. */ int uvm_map_pageable(struct vm_map *map, vaddr_t start, vaddr_t end, boolean_t new_pageable, int lockflags) { struct vm_map_entry *first, *last, *tmp; int error; start = trunc_page(start); end = round_page(end); if (start > end) return EINVAL; if (start == end) return 0; /* nothing to do */ if (start < map->min_offset) return EFAULT; /* why? see first XXX below */ if (end > map->max_offset) return EINVAL; /* why? see second XXX below */ KASSERT(map->flags & VM_MAP_PAGEABLE); if ((lockflags & UVM_LK_ENTER) == 0) vm_map_lock(map); /* * Find first entry. * * Initial test on start is different, because of the different * error returned. Rest is tested further down. */ first = uvm_map_entrybyaddr(&map->addr, start); if (first->end <= start || UVM_ET_ISHOLE(first)) { /* * XXX if the first address is not mapped, it is EFAULT? */ error = EFAULT; goto out; } /* Check that the range has no holes. */ for (last = first; last != NULL && last->start < end; last = RBT_NEXT(uvm_map_addr, last)) { if (UVM_ET_ISHOLE(last) || (last->end < end && VMMAP_FREE_END(last) != last->end)) { /* * XXX unmapped memory in range, why is it EINVAL * instead of EFAULT? */ error = EINVAL; goto out; } } /* * Last ended at the first entry after the range. * Move back one step. * * Note that last may be NULL. */ if (last == NULL) { last = RBT_MAX(uvm_map_addr, &map->addr); if (last->end < end) { error = EINVAL; goto out; } } else { KASSERT(last != first); last = RBT_PREV(uvm_map_addr, last); } /* Wire/unwire pages here. */ if (new_pageable) { /* * Mark pageable. * entries that are not wired are untouched. */ if (VM_MAPENT_ISWIRED(first)) UVM_MAP_CLIP_START(map, first, start); /* * Split last at end. * Make tmp be the first entry after what is to be touched. * If last is not wired, don't touch it. */ if (VM_MAPENT_ISWIRED(last)) { UVM_MAP_CLIP_END(map, last, end); tmp = RBT_NEXT(uvm_map_addr, last); } else tmp = last; uvm_map_pageable_pgon(map, first, tmp, start, end); error = 0; out: if ((lockflags & UVM_LK_EXIT) == 0) vm_map_unlock(map); return error; } else { /* * Mark entries wired. * entries are always touched (because recovery needs this). */ if (!VM_MAPENT_ISWIRED(first)) UVM_MAP_CLIP_START(map, first, start); /* * Split last at end. * Make tmp be the first entry after what is to be touched. * If last is not wired, don't touch it. */ if (!VM_MAPENT_ISWIRED(last)) { UVM_MAP_CLIP_END(map, last, end); tmp = RBT_NEXT(uvm_map_addr, last); } else tmp = last; return uvm_map_pageable_wire(map, first, tmp, start, end, lockflags); } } /* * uvm_map_pageable_all: special case of uvm_map_pageable - affects * all mapped regions. * * Map must not be locked. * If no flags are specified, all regions are unwired. */ int uvm_map_pageable_all(struct vm_map *map, int flags, vsize_t limit) { vsize_t size; struct vm_map_entry *iter; KASSERT(map->flags & VM_MAP_PAGEABLE); vm_map_lock(map); if (flags == 0) { uvm_map_pageable_pgon(map, RBT_MIN(uvm_map_addr, &map->addr), NULL, map->min_offset, map->max_offset); vm_map_modflags(map, 0, VM_MAP_WIREFUTURE); vm_map_unlock(map); return 0; } if (flags & MCL_FUTURE) vm_map_modflags(map, VM_MAP_WIREFUTURE, 0); if (!(flags & MCL_CURRENT)) { vm_map_unlock(map); return 0; } /* * Count number of pages in all non-wired entries. * If the number exceeds the limit, abort. */ size = 0; RBT_FOREACH(iter, uvm_map_addr, &map->addr) { if (VM_MAPENT_ISWIRED(iter) || UVM_ET_ISHOLE(iter)) continue; size += iter->end - iter->start; } if (atop(size) + uvmexp.wired > uvmexp.wiredmax) { vm_map_unlock(map); return ENOMEM; } /* XXX non-pmap_wired_count case must be handled by caller */ #ifdef pmap_wired_count if (limit != 0 && size + ptoa(pmap_wired_count(vm_map_pmap(map))) > limit) { vm_map_unlock(map); return ENOMEM; } #endif /* * uvm_map_pageable_wire will release lock */ return uvm_map_pageable_wire(map, RBT_MIN(uvm_map_addr, &map->addr), NULL, map->min_offset, map->max_offset, 0); } /* * Initialize map. * * Allocates sufficient entries to describe the free memory in the map. */ void uvm_map_setup(struct vm_map *map, pmap_t pmap, vaddr_t min, vaddr_t max, int flags) { int i; KASSERT((min & (vaddr_t)PAGE_MASK) == 0); KASSERT((max & (vaddr_t)PAGE_MASK) == 0 || (max & (vaddr_t)PAGE_MASK) == (vaddr_t)PAGE_MASK); /* * Update parameters. * * This code handles (vaddr_t)-1 and other page mask ending addresses * properly. * We lose the top page if the full virtual address space is used. */ if (max & (vaddr_t)PAGE_MASK) { max += 1; if (max == 0) /* overflow */ max -= PAGE_SIZE; } RBT_INIT(uvm_map_addr, &map->addr); map->uaddr_exe = NULL; for (i = 0; i < nitems(map->uaddr_any); ++i) map->uaddr_any[i] = NULL; map->uaddr_brk_stack = NULL; map->pmap = pmap; map->size = 0; map->ref_count = 0; map->min_offset = min; map->max_offset = max; map->b_start = map->b_end = 0; /* Empty brk() area by default. */ map->s_start = map->s_end = 0; /* Empty stack area by default. */ map->flags = flags; map->timestamp = 0; map->busy = NULL; if (flags & VM_MAP_ISVMSPACE) rw_init_flags(&map->lock, "vmmaplk", RWL_DUPOK); else rw_init(&map->lock, "kmmaplk"); mtx_init(&map->mtx, IPL_VM); mtx_init(&map->flags_lock, IPL_VM); /* Configure the allocators. */ if (flags & VM_MAP_ISVMSPACE) uvm_map_setup_md(map); else map->uaddr_any[3] = &uaddr_kbootstrap; /* * Fill map entries. * We do not need to write-lock the map here because only the current * thread sees it right now. Initialize ref_count to 0 above to avoid * bogus triggering of lock-not-held assertions. */ uvm_map_setup_entries(map); uvm_tree_sanity(map, __FILE__, __LINE__); map->ref_count = 1; } /* * Destroy the map. * * This is the inverse operation to uvm_map_setup. */ void uvm_map_teardown(struct vm_map *map) { struct uvm_map_deadq dead_entries; struct vm_map_entry *entry, *tmp; #ifdef VMMAP_DEBUG size_t numq, numt; #endif int i; KERNEL_ASSERT_LOCKED(); KERNEL_UNLOCK(); KERNEL_ASSERT_UNLOCKED(); KASSERT((map->flags & VM_MAP_INTRSAFE) == 0); vm_map_lock(map); /* Remove address selectors. */ uvm_addr_destroy(map->uaddr_exe); map->uaddr_exe = NULL; for (i = 0; i < nitems(map->uaddr_any); i++) { uvm_addr_destroy(map->uaddr_any[i]); map->uaddr_any[i] = NULL; } uvm_addr_destroy(map->uaddr_brk_stack); map->uaddr_brk_stack = NULL; /* * Remove entries. * * The following is based on graph breadth-first search. * * In color terms: * - the dead_entries set contains all nodes that are reachable * (i.e. both the black and the grey nodes) * - any entry not in dead_entries is white * - any entry that appears in dead_entries before entry, * is black, the rest is grey. * The set [entry, end] is also referred to as the wavefront. * * Since the tree is always a fully connected graph, the breadth-first * search guarantees that each vmmap_entry is visited exactly once. * The vm_map is broken down in linear time. */ TAILQ_INIT(&dead_entries); if ((entry = RBT_ROOT(uvm_map_addr, &map->addr)) != NULL) DEAD_ENTRY_PUSH(&dead_entries, entry); while (entry != NULL) { sched_pause(yield); uvm_unmap_kill_entry(map, entry); if ((tmp = RBT_LEFT(uvm_map_addr, entry)) != NULL) DEAD_ENTRY_PUSH(&dead_entries, tmp); if ((tmp = RBT_RIGHT(uvm_map_addr, entry)) != NULL) DEAD_ENTRY_PUSH(&dead_entries, tmp); /* Update wave-front. */ entry = TAILQ_NEXT(entry, dfree.deadq); } vm_map_unlock(map); #ifdef VMMAP_DEBUG numt = numq = 0; RBT_FOREACH(entry, uvm_map_addr, &map->addr) numt++; TAILQ_FOREACH(entry, &dead_entries, dfree.deadq) numq++; KASSERT(numt == numq); #endif uvm_unmap_detach(&dead_entries, UVM_PLA_WAITOK); KERNEL_LOCK(); pmap_destroy(map->pmap); map->pmap = NULL; } /* * Populate map with free-memory entries. * * Map must be initialized and empty. */ void uvm_map_setup_entries(struct vm_map *map) { KDASSERT(RBT_EMPTY(uvm_map_addr, &map->addr)); uvm_map_fix_space(map, NULL, map->min_offset, map->max_offset, 0); } /* * Split entry at given address. * * orig: entry that is to be split. * next: a newly allocated map entry that is not linked. * split: address at which the split is done. */ void uvm_map_splitentry(struct vm_map *map, struct vm_map_entry *orig, struct vm_map_entry *next, vaddr_t split) { struct uvm_addr_state *free, *free_before; vsize_t adj; if ((split & PAGE_MASK) != 0) { panic("uvm_map_splitentry: split address 0x%lx " "not on page boundary!", split); } KDASSERT(map != NULL && orig != NULL && next != NULL); uvm_tree_sanity(map, __FILE__, __LINE__); KASSERT(orig->start < split && VMMAP_FREE_END(orig) > split); #ifdef VMMAP_DEBUG KDASSERT(RBT_FIND(uvm_map_addr, &map->addr, orig) == orig); KDASSERT(RBT_FIND(uvm_map_addr, &map->addr, next) != next); #endif /* VMMAP_DEBUG */ /* * Free space will change, unlink from free space tree. */ free = uvm_map_uaddr_e(map, orig); uvm_mapent_free_remove(map, free, orig); adj = split - orig->start; uvm_mapent_copy(orig, next); if (split >= orig->end) { next->etype = 0; next->offset = 0; next->wired_count = 0; next->start = next->end = split; next->guard = 0; next->fspace = VMMAP_FREE_END(orig) - split; next->aref.ar_amap = NULL; next->aref.ar_pageoff = 0; orig->guard = MIN(orig->guard, split - orig->end); orig->fspace = split - VMMAP_FREE_START(orig); } else { orig->fspace = 0; orig->guard = 0; orig->end = next->start = split; if (next->aref.ar_amap) { amap_splitref(&orig->aref, &next->aref, adj); } if (UVM_ET_ISSUBMAP(orig)) { uvm_map_reference(next->object.sub_map); next->offset += adj; } else if (UVM_ET_ISOBJ(orig)) { if (next->object.uvm_obj->pgops && next->object.uvm_obj->pgops->pgo_reference) { KERNEL_LOCK(); next->object.uvm_obj->pgops->pgo_reference( next->object.uvm_obj); KERNEL_UNLOCK(); } next->offset += adj; } } /* * Link next into address tree. * Link orig and next into free-space tree. * * Don't insert 'next' into the addr tree until orig has been linked, * in case the free-list looks at adjacent entries in the addr tree * for its decisions. */ if (orig->fspace > 0) free_before = free; else free_before = uvm_map_uaddr_e(map, orig); uvm_mapent_free_insert(map, free_before, orig); uvm_mapent_addr_insert(map, next); uvm_mapent_free_insert(map, free, next); uvm_tree_sanity(map, __FILE__, __LINE__); } #ifdef VMMAP_DEBUG void uvm_tree_assert(struct vm_map *map, int test, char *test_str, char *file, int line) { char* map_special; if (test) return; if (map == kernel_map) map_special = " (kernel_map)"; else if (map == kmem_map) map_special = " (kmem_map)"; else map_special = ""; panic("uvm_tree_sanity %p%s (%s %d): %s", map, map_special, file, line, test_str); } /* * Check that map is sane. */ void uvm_tree_sanity(struct vm_map *map, char *file, int line) { struct vm_map_entry *iter; vaddr_t addr; vaddr_t min, max, bound; /* Bounds checker. */ struct uvm_addr_state *free; addr = vm_map_min(map); RBT_FOREACH(iter, uvm_map_addr, &map->addr) { /* * Valid start, end. * Catch overflow for end+fspace. */ UVM_ASSERT(map, iter->end >= iter->start, file, line); UVM_ASSERT(map, VMMAP_FREE_END(iter) >= iter->end, file, line); /* May not be empty. */ UVM_ASSERT(map, iter->start < VMMAP_FREE_END(iter), file, line); /* Addresses for entry must lie within map boundaries. */ UVM_ASSERT(map, iter->start >= vm_map_min(map) && VMMAP_FREE_END(iter) <= vm_map_max(map), file, line); /* Tree may not have gaps. */ UVM_ASSERT(map, iter->start == addr, file, line); addr = VMMAP_FREE_END(iter); /* * Free space may not cross boundaries, unless the same * free list is used on both sides of the border. */ min = VMMAP_FREE_START(iter); max = VMMAP_FREE_END(iter); while (min < max && (bound = uvm_map_boundary(map, min, max)) != max) { UVM_ASSERT(map, uvm_map_uaddr(map, bound - 1) == uvm_map_uaddr(map, bound), file, line); min = bound; } free = uvm_map_uaddr_e(map, iter); if (free) { UVM_ASSERT(map, (iter->etype & UVM_ET_FREEMAPPED) != 0, file, line); } else { UVM_ASSERT(map, (iter->etype & UVM_ET_FREEMAPPED) == 0, file, line); } } UVM_ASSERT(map, addr == vm_map_max(map), file, line); } void uvm_tree_size_chk(struct vm_map *map, char *file, int line) { struct vm_map_entry *iter; vsize_t size; size = 0; RBT_FOREACH(iter, uvm_map_addr, &map->addr) { if (!UVM_ET_ISHOLE(iter)) size += iter->end - iter->start; } if (map->size != size) printf("map size = 0x%lx, should be 0x%lx\n", map->size, size); UVM_ASSERT(map, map->size == size, file, line); vmspace_validate(map); } /* * This function validates the statistics on vmspace. */ void vmspace_validate(struct vm_map *map) { struct vmspace *vm; struct vm_map_entry *iter; vaddr_t imin, imax; vaddr_t stack_begin, stack_end; /* Position of stack. */ vsize_t stack, heap; /* Measured sizes. */ if (!(map->flags & VM_MAP_ISVMSPACE)) return; vm = (struct vmspace *)map; stack_begin = MIN((vaddr_t)vm->vm_maxsaddr, (vaddr_t)vm->vm_minsaddr); stack_end = MAX((vaddr_t)vm->vm_maxsaddr, (vaddr_t)vm->vm_minsaddr); stack = heap = 0; RBT_FOREACH(iter, uvm_map_addr, &map->addr) { imin = imax = iter->start; if (UVM_ET_ISHOLE(iter) || iter->object.uvm_obj != NULL || iter->protection != PROT_NONE) continue; /* * Update stack, heap. * Keep in mind that (theoretically) the entries of * userspace and stack may be joined. */ while (imin != iter->end) { /* * Set imax to the first boundary crossed between * imin and stack addresses. */ imax = iter->end; if (imin < stack_begin && imax > stack_begin) imax = stack_begin; else if (imin < stack_end && imax > stack_end) imax = stack_end; if (imin >= stack_begin && imin < stack_end) stack += imax - imin; else heap += imax - imin; imin = imax; } } heap >>= PAGE_SHIFT; if (heap != vm->vm_dused) { printf("vmspace stack range: 0x%lx-0x%lx\n", stack_begin, stack_end); panic("vmspace_validate: vmspace.vm_dused invalid, " "expected %ld pgs, got %d pgs in map %p", heap, vm->vm_dused, map); } } #endif /* VMMAP_DEBUG */ /* * uvm_map_init: init mapping system at boot time. note that we allocate * and init the static pool of structs vm_map_entry for the kernel here. */ void uvm_map_init(void) { static struct vm_map_entry kernel_map_entry[MAX_KMAPENT]; int lcv; /* now set up static pool of kernel map entries ... */ mtx_init(&uvm_kmapent_mtx, IPL_VM); SLIST_INIT(&uvm.kentry_free); for (lcv = 0 ; lcv < MAX_KMAPENT ; lcv++) { SLIST_INSERT_HEAD(&uvm.kentry_free, &kernel_map_entry[lcv], daddrs.addr_kentry); } /* initialize the map-related pools. */ pool_init(&uvm_vmspace_pool, sizeof(struct vmspace), 0, IPL_NONE, PR_WAITOK, "vmsppl", NULL); pool_init(&uvm_map_entry_pool, sizeof(struct vm_map_entry), 0, IPL_VM, PR_WAITOK, "vmmpepl", NULL); pool_init(&uvm_map_entry_kmem_pool, sizeof(struct vm_map_entry), 0, IPL_VM, 0, "vmmpekpl", NULL); pool_sethiwat(&uvm_map_entry_pool, 8192); uvm_addr_init(); } #if defined(DDB) /* * DDB hooks */ /* * uvm_map_printit: actually prints the map */ void uvm_map_printit(struct vm_map *map, boolean_t full, int (*pr)(const char *, ...)) { struct vmspace *vm; struct vm_map_entry *entry; struct uvm_addr_state *free; int in_free, i; char buf[8]; (*pr)("MAP %p: [0x%lx->0x%lx]\n", map, map->min_offset,map->max_offset); (*pr)("\tbrk() allocate range: 0x%lx-0x%lx\n", map->b_start, map->b_end); (*pr)("\tstack allocate range: 0x%lx-0x%lx\n", map->s_start, map->s_end); (*pr)("\tsz=%u, ref=%d, version=%u, flags=0x%x\n", map->size, map->ref_count, map->timestamp, map->flags); (*pr)("\tpmap=%p(resident=%d)\n", map->pmap, pmap_resident_count(map->pmap)); /* struct vmspace handling. */ if (map->flags & VM_MAP_ISVMSPACE) { vm = (struct vmspace *)map; (*pr)("\tvm_refcnt=%d vm_shm=%p vm_rssize=%u vm_swrss=%u\n", vm->vm_refcnt, vm->vm_shm, vm->vm_rssize, vm->vm_swrss); (*pr)("\tvm_tsize=%u vm_dsize=%u\n", vm->vm_tsize, vm->vm_dsize); (*pr)("\tvm_taddr=%p vm_daddr=%p\n", vm->vm_taddr, vm->vm_daddr); (*pr)("\tvm_maxsaddr=%p vm_minsaddr=%p\n", vm->vm_maxsaddr, vm->vm_minsaddr); } if (!full) goto print_uaddr; RBT_FOREACH(entry, uvm_map_addr, &map->addr) { (*pr)(" - %p: 0x%lx->0x%lx: obj=%p/0x%llx, amap=%p/%d\n", entry, entry->start, entry->end, entry->object.uvm_obj, (long long)entry->offset, entry->aref.ar_amap, entry->aref.ar_pageoff); (*pr)("\tsubmap=%c, cow=%c, nc=%c, stack=%c, " "prot(max)=%d/%d, inh=%d, " "wc=%d, adv=%d\n", (entry->etype & UVM_ET_SUBMAP) ? 'T' : 'F', (entry->etype & UVM_ET_COPYONWRITE) ? 'T' : 'F', (entry->etype & UVM_ET_NEEDSCOPY) ? 'T' : 'F', (entry->etype & UVM_ET_STACK) ? 'T' : 'F', entry->protection, entry->max_protection, entry->inheritance, entry->wired_count, entry->advice); free = uvm_map_uaddr_e(map, entry); in_free = (free != NULL); (*pr)("\thole=%c, free=%c, guard=0x%lx, " "free=0x%lx-0x%lx\n", (entry->etype & UVM_ET_HOLE) ? 'T' : 'F', in_free ? 'T' : 'F', entry->guard, VMMAP_FREE_START(entry), VMMAP_FREE_END(entry)); (*pr)("\tfspace_augment=%lu\n", entry->fspace_augment); (*pr)("\tfreemapped=%c, uaddr=%p\n", (entry->etype & UVM_ET_FREEMAPPED) ? 'T' : 'F', free); if (free) { (*pr)("\t\t(0x%lx-0x%lx %s)\n", free->uaddr_minaddr, free->uaddr_maxaddr, free->uaddr_functions->uaddr_name); } } print_uaddr: uvm_addr_print(map->uaddr_exe, "exe", full, pr); for (i = 0; i < nitems(map->uaddr_any); i++) { snprintf(&buf[0], sizeof(buf), "any[%d]", i); uvm_addr_print(map->uaddr_any[i], &buf[0], full, pr); } uvm_addr_print(map->uaddr_brk_stack, "brk/stack", full, pr); } /* * uvm_object_printit: actually prints the object */ void uvm_object_printit(struct uvm_object *uobj, boolean_t full, int (*pr)(const char *, ...)) { struct vm_page *pg; int cnt = 0; (*pr)("OBJECT %p: pgops=%p, npages=%d, ", uobj, uobj->pgops, uobj->uo_npages); if (UVM_OBJ_IS_KERN_OBJECT(uobj)) (*pr)("refs=<SYSTEM>\n"); else (*pr)("refs=%d\n", uobj->uo_refs); if (!full) { return; } (*pr)(" PAGES <pg,offset>:\n "); RBT_FOREACH(pg, uvm_objtree, &uobj->memt) { (*pr)("<%p,0x%llx> ", pg, (long long)pg->offset); if ((cnt % 3) == 2) { (*pr)("\n "); } cnt++; } if ((cnt % 3) != 2) { (*pr)("\n"); } } /* * uvm_page_printit: actually print the page */ static const char page_flagbits[] = "\20\1BUSY\2WANTED\3TABLED\4CLEAN\5CLEANCHK\6RELEASED\7FAKE\10RDONLY" "\11ZERO\12DEV\15PAGER1\21FREE\22INACTIVE\23ACTIVE\25ANON\26AOBJ" "\27ENCRYPT\31PMAP0\32PMAP1\33PMAP2\34PMAP3\35PMAP4\36PMAP5"; void uvm_page_printit(struct vm_page *pg, boolean_t full, int (*pr)(const char *, ...)) { struct vm_page *tpg; struct uvm_object *uobj; struct pglist *pgl; (*pr)("PAGE %p:\n", pg); (*pr)(" flags=%b, vers=%d, wire_count=%d, pa=0x%llx\n", pg->pg_flags, page_flagbits, pg->pg_version, pg->wire_count, (long long)pg->phys_addr); (*pr)(" uobject=%p, uanon=%p, offset=0x%llx\n", pg->uobject, pg->uanon, (long long)pg->offset); #if defined(UVM_PAGE_TRKOWN) if (pg->pg_flags & PG_BUSY) (*pr)(" owning thread = %d, tag=%s", pg->owner, pg->owner_tag); else (*pr)(" page not busy, no owner"); #else (*pr)(" [page ownership tracking disabled]"); #endif (*pr)("\tvm_page_md %p\n", &pg->mdpage); if (!full) return; /* cross-verify object/anon */ if ((pg->pg_flags & PQ_FREE) == 0) { if (pg->pg_flags & PQ_ANON) { if (pg->uanon == NULL || pg->uanon->an_page != pg) (*pr)(" >>> ANON DOES NOT POINT HERE <<< (%p)\n", (pg->uanon) ? pg->uanon->an_page : NULL); else (*pr)(" anon backpointer is OK\n"); } else { uobj = pg->uobject; if (uobj) { (*pr)(" checking object list\n"); RBT_FOREACH(tpg, uvm_objtree, &uobj->memt) { if (tpg == pg) { break; } } if (tpg) (*pr)(" page found on object list\n"); else (*pr)(" >>> PAGE NOT FOUND " "ON OBJECT LIST! <<<\n"); } } } /* cross-verify page queue */ if (pg->pg_flags & PQ_FREE) { if (uvm_pmr_isfree(pg)) (*pr)(" page found in uvm_pmemrange\n"); else (*pr)(" >>> page not found in uvm_pmemrange <<<\n"); pgl = NULL; } else if (pg->pg_flags & PQ_INACTIVE) { pgl = &uvm.page_inactive; } else if (pg->pg_flags & PQ_ACTIVE) { pgl = &uvm.page_active; } else { pgl = NULL; } if (pgl) { (*pr)(" checking pageq list\n"); TAILQ_FOREACH(tpg, pgl, pageq) { if (tpg == pg) { break; } } if (tpg) (*pr)(" page found on pageq list\n"); else (*pr)(" >>> PAGE NOT FOUND ON PAGEQ LIST! <<<\n"); } } #endif /* * uvm_map_protect: change map protection * * => set_max means set max_protection. * => map must be unlocked. */ int uvm_map_protect(struct vm_map *map, vaddr_t start, vaddr_t end, vm_prot_t new_prot, int etype, boolean_t set_max, boolean_t checkimmutable) { struct vm_map_entry *first, *iter; vm_prot_t old_prot; vm_prot_t mask; vsize_t dused; int error; KASSERT((etype & ~UVM_ET_STACK) == 0); /* only UVM_ET_STACK allowed */ if (start > end) return EINVAL; start = MAX(start, map->min_offset); end = MIN(end, map->max_offset); if (start >= end) return 0; dused = 0; error = 0; vm_map_lock(map); /* * Set up first and last. * - first will contain first entry at or after start. */ first = uvm_map_entrybyaddr(&map->addr, start); KDASSERT(first != NULL); if (first->end <= start) first = RBT_NEXT(uvm_map_addr, first); /* First, check for protection violations. */ for (iter = first; iter != NULL && iter->start < end; iter = RBT_NEXT(uvm_map_addr, iter)) { /* Treat memory holes as free space. */ if (iter->start == iter->end || UVM_ET_ISHOLE(iter)) continue; if (checkimmutable && (iter->etype & UVM_ET_IMMUTABLE)) { error = EPERM; goto out; } old_prot = iter->protection; if (old_prot == PROT_NONE && new_prot != old_prot) { dused += uvmspace_dused( map, MAX(start, iter->start), MIN(end, iter->end)); } if (UVM_ET_ISSUBMAP(iter)) { error = EINVAL; goto out; } if ((new_prot & iter->max_protection) != new_prot) { error = EACCES; goto out; } if (map == kernel_map && (new_prot & (PROT_WRITE | PROT_EXEC)) == (PROT_WRITE | PROT_EXEC)) panic("uvm_map_protect: kernel map W^X violation requested"); } /* Check limits. */ if (dused > 0 && (map->flags & VM_MAP_ISVMSPACE)) { vsize_t limit = lim_cur(RLIMIT_DATA); dused = ptoa(dused); if (limit < dused || limit - dused < ptoa(((struct vmspace *)map)->vm_dused)) { error = ENOMEM; goto out; } } /* only apply UVM_ET_STACK on a mapping changing to RW */ if (etype && new_prot != (PROT_READ|PROT_WRITE)) etype = 0; /* Fix protections. */ for (iter = first; iter != NULL && iter->start < end; iter = RBT_NEXT(uvm_map_addr, iter)) { /* Treat memory holes as free space. */ if (iter->start == iter->end || UVM_ET_ISHOLE(iter)) continue; old_prot = iter->protection; /* * Skip adapting protection iff old and new protection * are equal. */ if (set_max) { if (old_prot == (new_prot & old_prot) && iter->max_protection == new_prot) continue; } else { if (old_prot == new_prot) continue; } UVM_MAP_CLIP_START(map, iter, start); UVM_MAP_CLIP_END(map, iter, end); if (set_max) { iter->max_protection = new_prot; iter->protection &= new_prot; } else iter->protection = new_prot; iter->etype |= etype; /* potentially add UVM_ET_STACK */ /* * update physical map if necessary. worry about copy-on-write * here -- CHECK THIS XXX */ if (iter->protection != old_prot) { mask = UVM_ET_ISCOPYONWRITE(iter) ? ~PROT_WRITE : PROT_MASK; if (map->flags & VM_MAP_ISVMSPACE) { if (old_prot == PROT_NONE) { ((struct vmspace *)map)->vm_dused += uvmspace_dused(map, iter->start, iter->end); } if (iter->protection == PROT_NONE) { ((struct vmspace *)map)->vm_dused -= uvmspace_dused(map, iter->start, iter->end); } } /* update pmap */ if ((iter->protection & mask) == PROT_NONE && VM_MAPENT_ISWIRED(iter)) { /* * TODO(ariane) this is stupid. wired_count * is 0 if not wired, otherwise anything * larger than 0 (incremented once each time * wire is called). * Mostly to be able to undo the damage on * failure. Not the actually be a wired * refcounter... * Originally: iter->wired_count--; * (don't we have to unwire this in the pmap * as well?) */ iter->wired_count = 0; } uvm_map_lock_entry(iter); pmap_protect(map->pmap, iter->start, iter->end, iter->protection & mask); uvm_map_unlock_entry(iter); } /* * If the map is configured to lock any future mappings, * wire this entry now if the old protection was PROT_NONE * and the new protection is not PROT_NONE. */ if ((map->flags & VM_MAP_WIREFUTURE) != 0 && VM_MAPENT_ISWIRED(iter) == 0 && old_prot == PROT_NONE && new_prot != PROT_NONE) { if (uvm_map_pageable(map, iter->start, iter->end, FALSE, UVM_LK_ENTER | UVM_LK_EXIT) != 0) { /* * If locking the entry fails, remember the * error if it's the first one. Note we * still continue setting the protection in * the map, but it will return the resource * storage condition regardless. * * XXX Ignore what the actual error is, * XXX just call it a resource shortage * XXX so that it doesn't get confused * XXX what uvm_map_protect() itself would * XXX normally return. */ error = ENOMEM; } } } pmap_update(map->pmap); out: if (etype & UVM_ET_STACK) map->sserial++; vm_map_unlock(map); return error; } /* * uvmspace_alloc: allocate a vmspace structure. * * - structure includes vm_map and pmap * - XXX: no locking on this structure * - refcnt set to 1, rest must be init'd by caller */ struct vmspace * uvmspace_alloc(vaddr_t min, vaddr_t max, boolean_t pageable, boolean_t remove_holes) { struct vmspace *vm; vm = pool_get(&uvm_vmspace_pool, PR_WAITOK | PR_ZERO); uvmspace_init(vm, NULL, min, max, pageable, remove_holes); return (vm); } /* * uvmspace_init: initialize a vmspace structure. * * - XXX: no locking on this structure * - refcnt set to 1, rest must be init'd by caller */ void uvmspace_init(struct vmspace *vm, struct pmap *pmap, vaddr_t min, vaddr_t max, boolean_t pageable, boolean_t remove_holes) { KASSERT(pmap == NULL || pmap == pmap_kernel()); if (pmap) pmap_reference(pmap); else pmap = pmap_create(); uvm_map_setup(&vm->vm_map, pmap, min, max, (pageable ? VM_MAP_PAGEABLE : 0) | VM_MAP_ISVMSPACE); vm->vm_refcnt = 1; if (remove_holes) pmap_remove_holes(vm); } /* * uvmspace_share: share a vmspace between two processes * * - used for vfork */ struct vmspace * uvmspace_share(struct process *pr) { struct vmspace *vm = pr->ps_vmspace; uvmspace_addref(vm); return vm; } /* * uvmspace_exec: the process wants to exec a new program * * - XXX: no locking on vmspace */ void uvmspace_exec(struct proc *p, vaddr_t start, vaddr_t end) { struct process *pr = p->p_p; struct vmspace *nvm, *ovm = pr->ps_vmspace; struct vm_map *map = &ovm->vm_map; struct uvm_map_deadq dead_entries; KASSERT((start & (vaddr_t)PAGE_MASK) == 0); KASSERT((end & (vaddr_t)PAGE_MASK) == 0 || (end & (vaddr_t)PAGE_MASK) == (vaddr_t)PAGE_MASK); pmap_unuse_final(p); /* before stack addresses go away */ TAILQ_INIT(&dead_entries); /* see if more than one process is using this vmspace... */ if (ovm->vm_refcnt == 1) { /* * If pr is the only process using its vmspace then * we can safely recycle that vmspace for the program * that is being exec'd. */ #ifdef SYSVSHM /* * SYSV SHM semantics require us to kill all segments on an exec */ if (ovm->vm_shm) shmexit(ovm); #endif /* * POSIX 1003.1b -- "lock future mappings" is revoked * when a process execs another program image. */ vm_map_lock(map); vm_map_modflags(map, 0, VM_MAP_WIREFUTURE | VM_MAP_PINSYSCALL_ONCE); /* * now unmap the old program * * Instead of attempting to keep the map valid, we simply * nuke all entries and ask uvm_map_setup to reinitialize * the map to the new boundaries. * * uvm_unmap_remove will actually nuke all entries for us * (as in, not replace them with free-memory entries). */ uvm_unmap_remove(map, map->min_offset, map->max_offset, &dead_entries, TRUE, FALSE, FALSE); KDASSERT(RBT_EMPTY(uvm_map_addr, &map->addr)); /* Nuke statistics and boundaries. */ memset(&ovm->vm_startcopy, 0, (caddr_t) (ovm + 1) - (caddr_t) &ovm->vm_startcopy); if (end & (vaddr_t)PAGE_MASK) { end += 1; if (end == 0) /* overflow */ end -= PAGE_SIZE; } /* Setup new boundaries and populate map with entries. */ map->min_offset = start; map->max_offset = end; uvm_map_setup_entries(map); vm_map_unlock(map); /* but keep MMU holes unavailable */ pmap_remove_holes(ovm); } else { /* * pr's vmspace is being shared, so we can't reuse * it for pr since it is still being used for others. * allocate a new vmspace for pr */ nvm = uvmspace_alloc(start, end, (map->flags & VM_MAP_PAGEABLE) ? TRUE : FALSE, TRUE); /* install new vmspace and drop our ref to the old one. */ pmap_deactivate(p); p->p_vmspace = pr->ps_vmspace = nvm; pmap_activate(p); uvmspace_free(ovm); } #ifdef PMAP_CHECK_COPYIN p->p_vmspace->vm_map.check_copyin_count = 0; /* disable checks */ #endif /* Release dead entries */ uvm_unmap_detach(&dead_entries, 0); } /* * uvmspace_addref: add a reference to a vmspace. */ void uvmspace_addref(struct vmspace *vm) { KERNEL_ASSERT_LOCKED(); KASSERT(vm->vm_refcnt > 0); vm->vm_refcnt++; } /* * uvmspace_free: free a vmspace data structure */ void uvmspace_free(struct vmspace *vm) { KERNEL_ASSERT_LOCKED(); if (--vm->vm_refcnt == 0) { /* * lock the map, to wait out all other references to it. delete * all of the mappings and pages they hold, then call the pmap * module to reclaim anything left. */ #ifdef SYSVSHM /* Get rid of any SYSV shared memory segments. */ if (vm->vm_shm != NULL) shmexit(vm); #endif uvm_map_teardown(&vm->vm_map); pool_put(&uvm_vmspace_pool, vm); } } /* * uvm_share: Map the address range [srcaddr, srcaddr + sz) in * srcmap to the address range [dstaddr, dstaddr + sz) in * dstmap. * * The whole address range in srcmap must be backed by an object * (no holes). * * If successful, the address ranges share memory and the destination * address range uses the protection flags in prot. * * This routine assumes that sz is a multiple of PAGE_SIZE and * that dstaddr and srcaddr are page-aligned. */ int uvm_share(struct vm_map *dstmap, vaddr_t dstaddr, vm_prot_t prot, struct vm_map *srcmap, vaddr_t srcaddr, vsize_t sz) { int ret = 0; vaddr_t unmap_end; vaddr_t dstva; vsize_t s_off, len, n = sz, remain; struct vm_map_entry *first = NULL, *last = NULL; struct vm_map_entry *src_entry, *psrc_entry = NULL; struct uvm_map_deadq dead; if (srcaddr >= srcmap->max_offset || sz > srcmap->max_offset - srcaddr) return EINVAL; TAILQ_INIT(&dead); vm_map_lock(dstmap); vm_map_lock_read(srcmap); if (!uvm_map_isavail(dstmap, NULL, &first, &last, dstaddr, sz)) { ret = ENOMEM; goto exit_unlock; } if (!uvm_map_lookup_entry(srcmap, srcaddr, &src_entry)) { ret = EINVAL; goto exit_unlock; } dstva = dstaddr; unmap_end = dstaddr; for (; src_entry != NULL; psrc_entry = src_entry, src_entry = RBT_NEXT(uvm_map_addr, src_entry)) { /* hole in address space, bail out */ if (psrc_entry != NULL && psrc_entry->end != src_entry->start) break; if (src_entry->start >= srcaddr + sz) break; if (UVM_ET_ISSUBMAP(src_entry)) panic("uvm_share: encountered a submap (illegal)"); if (!UVM_ET_ISCOPYONWRITE(src_entry) && UVM_ET_ISNEEDSCOPY(src_entry)) panic("uvm_share: non-copy_on_write map entries " "marked needs_copy (illegal)"); /* * srcaddr > map entry start? means we are in the middle of a * map, so we calculate the offset to use in the source map. */ if (srcaddr > src_entry->start) s_off = srcaddr - src_entry->start; else if (srcaddr == src_entry->start) s_off = 0; else panic("uvm_share: map entry start > srcaddr"); remain = src_entry->end - src_entry->start - s_off; /* Determine how many bytes to share in this pass */ if (n < remain) len = n; else len = remain; if (uvm_mapent_share(dstmap, dstva, len, s_off, prot, prot, srcmap, src_entry, &dead) == NULL) break; n -= len; dstva += len; srcaddr += len; unmap_end = dstva + len; if (n == 0) goto exit_unlock; } ret = EINVAL; uvm_unmap_remove(dstmap, dstaddr, unmap_end, &dead, FALSE, TRUE, FALSE); exit_unlock: vm_map_unlock_read(srcmap); vm_map_unlock(dstmap); uvm_unmap_detach(&dead, 0); return ret; } /* * Clone map entry into other map. * * Mapping will be placed at dstaddr, for the same length. * Space must be available. * Reference counters are incremented. */ struct vm_map_entry * uvm_mapent_clone(struct vm_map *dstmap, vaddr_t dstaddr, vsize_t dstlen, vsize_t off, vm_prot_t prot, vm_prot_t maxprot, struct vm_map_entry *old_entry, struct uvm_map_deadq *dead, int mapent_flags, int amap_share_flags) { struct vm_map_entry *new_entry, *first, *last; KDASSERT(!UVM_ET_ISSUBMAP(old_entry)); /* Create new entry (linked in on creation). Fill in first, last. */ first = last = NULL; if (!uvm_map_isavail(dstmap, NULL, &first, &last, dstaddr, dstlen)) { panic("uvm_mapent_clone: no space in map for " "entry in empty map"); } new_entry = uvm_map_mkentry(dstmap, first, last, dstaddr, dstlen, mapent_flags, dead, NULL); if (new_entry == NULL) return NULL; /* old_entry -> new_entry */ new_entry->object = old_entry->object; new_entry->offset = old_entry->offset; new_entry->aref = old_entry->aref; new_entry->etype |= old_entry->etype & ~UVM_ET_FREEMAPPED; new_entry->protection = prot; new_entry->max_protection = maxprot; new_entry->inheritance = old_entry->inheritance; new_entry->advice = old_entry->advice; /* gain reference to object backing the map (can't be a submap). */ if (new_entry->aref.ar_amap) { new_entry->aref.ar_pageoff += off >> PAGE_SHIFT; amap_ref(new_entry->aref.ar_amap, new_entry->aref.ar_pageoff, (new_entry->end - new_entry->start) >> PAGE_SHIFT, amap_share_flags); } if (UVM_ET_ISOBJ(new_entry) && new_entry->object.uvm_obj->pgops->pgo_reference) { new_entry->offset += off; new_entry->object.uvm_obj->pgops->pgo_reference (new_entry->object.uvm_obj); } return new_entry; } struct vm_map_entry * uvm_mapent_share(struct vm_map *dstmap, vaddr_t dstaddr, vsize_t dstlen, vsize_t off, vm_prot_t prot, vm_prot_t maxprot, struct vm_map *old_map, struct vm_map_entry *old_entry, struct uvm_map_deadq *dead) { /* * If old_entry refers to a copy-on-write region that has not yet been * written to (needs_copy flag is set), then we need to allocate a new * amap for old_entry. * * If we do not do this, and the process owning old_entry does a copy-on * write later, old_entry and new_entry will refer to different memory * regions, and the memory between the processes is no longer shared. * * [in other words, we need to clear needs_copy] */ if (UVM_ET_ISNEEDSCOPY(old_entry)) { /* get our own amap, clears needs_copy */ amap_copy(old_map, old_entry, M_WAITOK, FALSE, 0, 0); /* XXXCDC: WAITOK??? */ } return uvm_mapent_clone(dstmap, dstaddr, dstlen, off, prot, maxprot, old_entry, dead, 0, AMAP_SHARED); } /* * share the mapping: this means we want the old and * new entries to share amaps and backing objects. */ struct vm_map_entry * uvm_mapent_forkshared(struct vmspace *new_vm, struct vm_map *new_map, struct vm_map *old_map, struct vm_map_entry *old_entry, struct uvm_map_deadq *dead) { struct vm_map_entry *new_entry; new_entry = uvm_mapent_share(new_map, old_entry->start, old_entry->end - old_entry->start, 0, old_entry->protection, old_entry->max_protection, old_map, old_entry, dead); return (new_entry); } /* * copy-on-write the mapping (using mmap's * MAP_PRIVATE semantics) * * allocate new_entry, adjust reference counts. * (note that new references are read-only). */ struct vm_map_entry * uvm_mapent_forkcopy(struct vmspace *new_vm, struct vm_map *new_map, struct vm_map *old_map, struct vm_map_entry *old_entry, struct uvm_map_deadq *dead) { struct vm_map_entry *new_entry; boolean_t protect_child; new_entry = uvm_mapent_clone(new_map, old_entry->start, old_entry->end - old_entry->start, 0, old_entry->protection, old_entry->max_protection, old_entry, dead, 0, 0); new_entry->etype |= (UVM_ET_COPYONWRITE|UVM_ET_NEEDSCOPY); /* * the new entry will need an amap. it will either * need to be copied from the old entry or created * from scratch (if the old entry does not have an * amap). can we defer this process until later * (by setting "needs_copy") or do we need to copy * the amap now? * * we must copy the amap now if any of the following * conditions hold: * 1. the old entry has an amap and that amap is * being shared. this means that the old (parent) * process is sharing the amap with another * process. if we do not clear needs_copy here * we will end up in a situation where both the * parent and child process are referring to the * same amap with "needs_copy" set. if the * parent write-faults, the fault routine will * clear "needs_copy" in the parent by allocating * a new amap. this is wrong because the * parent is supposed to be sharing the old amap * and the new amap will break that. * * 2. if the old entry has an amap and a non-zero * wire count then we are going to have to call * amap_cow_now to avoid page faults in the * parent process. since amap_cow_now requires * "needs_copy" to be clear we might as well * clear it here as well. * */ if (old_entry->aref.ar_amap != NULL && ((amap_flags(old_entry->aref.ar_amap) & AMAP_SHARED) != 0 || VM_MAPENT_ISWIRED(old_entry))) { amap_copy(new_map, new_entry, M_WAITOK, FALSE, 0, 0); /* XXXCDC: M_WAITOK ... ok? */ } /* * if the parent's entry is wired down, then the * parent process does not want page faults on * access to that memory. this means that we * cannot do copy-on-write because we can't write * protect the old entry. in this case we * resolve all copy-on-write faults now, using * amap_cow_now. note that we have already * allocated any needed amap (above). */ if (VM_MAPENT_ISWIRED(old_entry)) { /* * resolve all copy-on-write faults now * (note that there is nothing to do if * the old mapping does not have an amap). */ if (old_entry->aref.ar_amap) amap_cow_now(new_map, new_entry); } else { if (old_entry->aref.ar_amap) { /* * setup mappings to trigger copy-on-write faults * we must write-protect the parent if it has * an amap and it is not already "needs_copy"... * if it is already "needs_copy" then the parent * has already been write-protected by a previous * fork operation. * * if we do not write-protect the parent, then * we must be sure to write-protect the child. */ if (!UVM_ET_ISNEEDSCOPY(old_entry)) { if (old_entry->max_protection & PROT_WRITE) { uvm_map_lock_entry(old_entry); pmap_protect(old_map->pmap, old_entry->start, old_entry->end, old_entry->protection & ~PROT_WRITE); uvm_map_unlock_entry(old_entry); pmap_update(old_map->pmap); } old_entry->etype |= UVM_ET_NEEDSCOPY; } /* parent must now be write-protected */ protect_child = FALSE; } else { /* * we only need to protect the child if the * parent has write access. */ if (old_entry->max_protection & PROT_WRITE) protect_child = TRUE; else protect_child = FALSE; } /* protect the child's mappings if necessary */ if (protect_child) { pmap_protect(new_map->pmap, new_entry->start, new_entry->end, new_entry->protection & ~PROT_WRITE); } } return (new_entry); } /* * zero the mapping: the new entry will be zero initialized */ struct vm_map_entry * uvm_mapent_forkzero(struct vmspace *new_vm, struct vm_map *new_map, struct vm_map *old_map, struct vm_map_entry *old_entry, struct uvm_map_deadq *dead) { struct vm_map_entry *new_entry; new_entry = uvm_mapent_clone(new_map, old_entry->start, old_entry->end - old_entry->start, 0, old_entry->protection, old_entry->max_protection, old_entry, dead, 0, 0); new_entry->etype |= (UVM_ET_COPYONWRITE|UVM_ET_NEEDSCOPY); if (new_entry->aref.ar_amap) { amap_unref(new_entry->aref.ar_amap, new_entry->aref.ar_pageoff, atop(new_entry->end - new_entry->start), 0); new_entry->aref.ar_amap = NULL; new_entry->aref.ar_pageoff = 0; } if (UVM_ET_ISOBJ(new_entry)) { if (new_entry->object.uvm_obj->pgops->pgo_detach) new_entry->object.uvm_obj->pgops->pgo_detach( new_entry->object.uvm_obj); new_entry->object.uvm_obj = NULL; new_entry->etype &= ~UVM_ET_OBJ; } return (new_entry); } /* * uvmspace_fork: fork a process' main map * * => create a new vmspace for child process from parent. * => parent's map must not be locked. */ struct vmspace * uvmspace_fork(struct process *pr) { struct vmspace *vm1 = pr->ps_vmspace; struct vmspace *vm2; struct vm_map *old_map = &vm1->vm_map; struct vm_map *new_map; struct vm_map_entry *old_entry, *new_entry; struct uvm_map_deadq dead; vm_map_lock(old_map); vm2 = uvmspace_alloc(old_map->min_offset, old_map->max_offset, (old_map->flags & VM_MAP_PAGEABLE) ? TRUE : FALSE, FALSE); memcpy(&vm2->vm_startcopy, &vm1->vm_startcopy, (caddr_t) (vm1 + 1) - (caddr_t) &vm1->vm_startcopy); vm2->vm_dused = 0; /* Statistic managed by us. */ new_map = &vm2->vm_map; vm_map_lock(new_map); /* go entry-by-entry */ TAILQ_INIT(&dead); RBT_FOREACH(old_entry, uvm_map_addr, &old_map->addr) { if (old_entry->start == old_entry->end) continue; /* first, some sanity checks on the old entry */ if (UVM_ET_ISSUBMAP(old_entry)) { panic("fork: encountered a submap during fork " "(illegal)"); } if (!UVM_ET_ISCOPYONWRITE(old_entry) && UVM_ET_ISNEEDSCOPY(old_entry)) { panic("fork: non-copy_on_write map entry marked " "needs_copy (illegal)"); } /* Apply inheritance. */ switch (old_entry->inheritance) { case MAP_INHERIT_SHARE: new_entry = uvm_mapent_forkshared(vm2, new_map, old_map, old_entry, &dead); break; case MAP_INHERIT_COPY: new_entry = uvm_mapent_forkcopy(vm2, new_map, old_map, old_entry, &dead); break; case MAP_INHERIT_ZERO: new_entry = uvm_mapent_forkzero(vm2, new_map, old_map, old_entry, &dead); break; default: continue; } /* Update process statistics. */ if (!UVM_ET_ISHOLE(new_entry)) new_map->size += new_entry->end - new_entry->start; if (!UVM_ET_ISOBJ(new_entry) && !UVM_ET_ISHOLE(new_entry) && new_entry->protection != PROT_NONE) { vm2->vm_dused += uvmspace_dused( new_map, new_entry->start, new_entry->end); } } new_map->flags |= old_map->flags & VM_MAP_PINSYSCALL_ONCE; #ifdef PMAP_CHECK_COPYIN if (PMAP_CHECK_COPYIN) { memcpy(&new_map->check_copyin, &old_map->check_copyin, sizeof(new_map->check_copyin)); membar_producer(); new_map->check_copyin_count = old_map->check_copyin_count; } #endif vm_map_unlock(old_map); vm_map_unlock(new_map); /* * This can actually happen, if multiple entries described a * space in which an entry was inherited. */ uvm_unmap_detach(&dead, 0); #ifdef SYSVSHM if (vm1->vm_shm) shmfork(vm1, vm2); #endif return vm2; } /* * uvm_map_hint: return the beginning of the best area suitable for * creating a new mapping with "prot" protection. */ vaddr_t uvm_map_hint(struct vmspace *vm, vm_prot_t prot, vaddr_t minaddr, vaddr_t maxaddr) { vaddr_t addr; vaddr_t spacing; #ifdef __i386__ /* * If executable skip first two pages, otherwise start * after data + heap region. */ if ((prot & PROT_EXEC) != 0 && (vaddr_t)vm->vm_daddr >= I386_MAX_EXE_ADDR) { addr = (PAGE_SIZE*2) + (arc4random() & (I386_MAX_EXE_ADDR / 2 - 1)); return (round_page(addr)); } #endif #if defined (__LP64__) spacing = MIN(4UL * 1024 * 1024 * 1024, MAXDSIZ) - 1; #else spacing = MIN(1 * 1024 * 1024 * 1024, MAXDSIZ) - 1; #endif /* * Start malloc/mmap after the brk. */ addr = (vaddr_t)vm->vm_daddr + BRKSIZ; addr = MAX(addr, minaddr); if (addr < maxaddr) { while (spacing > maxaddr - addr) spacing >>= 1; } addr += arc4random() & spacing; return (round_page(addr)); } /* * uvm_map_submap: punch down part of a map into a submap * * => only the kernel_map is allowed to be submapped * => the purpose of submapping is to break up the locking granularity * of a larger map * => the range specified must have been mapped previously with a uvm_map() * call [with uobj==NULL] to create a blank map entry in the main map. * [And it had better still be blank!] * => maps which contain submaps should never be copied or forked. * => to remove a submap, use uvm_unmap() on the main map * and then uvm_map_deallocate() the submap. * => main map must be unlocked. * => submap must have been init'd and have a zero reference count. * [need not be locked as we don't actually reference it] */ int uvm_map_submap(struct vm_map *map, vaddr_t start, vaddr_t end, struct vm_map *submap) { struct vm_map_entry *entry; int result; if (start > map->max_offset || end > map->max_offset || start < map->min_offset || end < map->min_offset) return EINVAL; vm_map_lock(map); if (uvm_map_lookup_entry(map, start, &entry)) { UVM_MAP_CLIP_START(map, entry, start); UVM_MAP_CLIP_END(map, entry, end); } else entry = NULL; if (entry != NULL && entry->start == start && entry->end == end && entry->object.uvm_obj == NULL && entry->aref.ar_amap == NULL && !UVM_ET_ISCOPYONWRITE(entry) && !UVM_ET_ISNEEDSCOPY(entry)) { entry->etype |= UVM_ET_SUBMAP; entry->object.sub_map = submap; entry->offset = 0; uvm_map_reference(submap); result = 0; } else result = EINVAL; vm_map_unlock(map); return result; } /* * uvm_map_checkprot: check protection in map * * => must allow specific protection in a fully allocated region. * => map must be read or write locked by caller. */ boolean_t uvm_map_checkprot(struct vm_map *map, vaddr_t start, vaddr_t end, vm_prot_t protection) { struct vm_map_entry *entry; vm_map_assert_anylock(map); if (start < map->min_offset || end > map->max_offset || start > end) return FALSE; if (start == end) return TRUE; /* * Iterate entries. */ for (entry = uvm_map_entrybyaddr(&map->addr, start); entry != NULL && entry->start < end; entry = RBT_NEXT(uvm_map_addr, entry)) { /* Fail if a hole is found. */ if (UVM_ET_ISHOLE(entry) || (entry->end < end && entry->end != VMMAP_FREE_END(entry))) return FALSE; /* Check protection. */ if ((entry->protection & protection) != protection) return FALSE; } return TRUE; } /* * uvm_map_create: create map */ vm_map_t uvm_map_create(pmap_t pmap, vaddr_t min, vaddr_t max, int flags) { vm_map_t map; map = malloc(sizeof *map, M_VMMAP, M_WAITOK); uvm_map_setup(map, pmap, min, max, flags); return (map); } /* * uvm_map_deallocate: drop reference to a map * * => caller must not lock map * => we will zap map if ref count goes to zero */ void uvm_map_deallocate(vm_map_t map) { int c; struct uvm_map_deadq dead; c = atomic_dec_int_nv(&map->ref_count); if (c > 0) { return; } /* * all references gone. unmap and free. * * No lock required: we are only one to access this map. */ TAILQ_INIT(&dead); uvm_tree_sanity(map, __FILE__, __LINE__); vm_map_lock(map); uvm_unmap_remove(map, map->min_offset, map->max_offset, &dead, TRUE, FALSE, FALSE); vm_map_unlock(map); pmap_destroy(map->pmap); KASSERT(RBT_EMPTY(uvm_map_addr, &map->addr)); free(map, M_VMMAP, sizeof *map); uvm_unmap_detach(&dead, 0); } /* * uvm_map_inherit: set inheritance code for range of addrs in map. * * => map must be unlocked * => note that the inherit code is used during a "fork". see fork * code for details. */ int uvm_map_inherit(struct vm_map *map, vaddr_t start, vaddr_t end, vm_inherit_t new_inheritance) { struct vm_map_entry *entry, *entry1; int error = EPERM; switch (new_inheritance) { case MAP_INHERIT_NONE: case MAP_INHERIT_COPY: case MAP_INHERIT_SHARE: case MAP_INHERIT_ZERO: break; default: return (EINVAL); } if (start > end) return EINVAL; start = MAX(start, map->min_offset); end = MIN(end, map->max_offset); if (start >= end) return 0; vm_map_lock(map); entry = uvm_map_entrybyaddr(&map->addr, start); if (entry->end > start) UVM_MAP_CLIP_START(map, entry, start); else entry = RBT_NEXT(uvm_map_addr, entry); /* First check for illegal operations */ entry1 = entry; while (entry1 != NULL && entry1->start < end) { if (entry1->etype & UVM_ET_IMMUTABLE) goto out; if (new_inheritance == MAP_INHERIT_ZERO && (entry1->protection & PROT_WRITE) == 0) goto out; entry1 = RBT_NEXT(uvm_map_addr, entry1); } while (entry != NULL && entry->start < end) { UVM_MAP_CLIP_END(map, entry, end); entry->inheritance = new_inheritance; entry = RBT_NEXT(uvm_map_addr, entry); } error = 0; out: vm_map_unlock(map); return (error); } #ifdef PMAP_CHECK_COPYIN static void inline check_copyin_add(struct vm_map *map, vaddr_t start, vaddr_t end) { if (PMAP_CHECK_COPYIN == 0 || map->check_copyin_count >= UVM_MAP_CHECK_COPYIN_MAX) return; vm_map_assert_wrlock(map); map->check_copyin[map->check_copyin_count].start = start; map->check_copyin[map->check_copyin_count].end = end; membar_producer(); map->check_copyin_count++; } /* * uvm_map_check_copyin_add: remember regions which are X-only for copyin(), * copyinstr(), uiomove(), and others * * => map must be unlocked */ int uvm_map_check_copyin_add(struct vm_map *map, vaddr_t start, vaddr_t end) { if (start > end) return EINVAL; start = MAX(start, map->min_offset); end = MIN(end, map->max_offset); if (start >= end) return 0; vm_map_lock(map); check_copyin_add(map, start, end); vm_map_unlock(map); return (0); } #endif /* PMAP_CHECK_COPYIN */ /* * uvm_map_immutable: block mapping/mprotect for range of addrs in map. * * => map must be unlocked */ int uvm_map_immutable(struct vm_map *map, vaddr_t start, vaddr_t end, int imut) { struct vm_map_entry *entry, *entry1; int error = EPERM; if (start > end) return EINVAL; start = MAX(start, map->min_offset); end = MIN(end, map->max_offset); if (start >= end) return 0; vm_map_lock(map); entry = uvm_map_entrybyaddr(&map->addr, start); if (entry->end > start) UVM_MAP_CLIP_START(map, entry, start); else entry = RBT_NEXT(uvm_map_addr, entry); /* First check for illegal operations */ entry1 = entry; while (entry1 != NULL && entry1->start < end) { if (entry1->inheritance == MAP_INHERIT_ZERO) goto out; entry1 = RBT_NEXT(uvm_map_addr, entry1); } while (entry != NULL && entry->start < end) { UVM_MAP_CLIP_END(map, entry, end); if (imut) entry->etype |= UVM_ET_IMMUTABLE; else entry->etype &= ~UVM_ET_IMMUTABLE; entry = RBT_NEXT(uvm_map_addr, entry); } error = 0; out: vm_map_unlock(map); return (0); } /* * uvm_map_advice: set advice code for range of addrs in map. * * => map must be unlocked */ int uvm_map_advice(struct vm_map *map, vaddr_t start, vaddr_t end, int new_advice) { struct vm_map_entry *entry; switch (new_advice) { case MADV_NORMAL: case MADV_RANDOM: case MADV_SEQUENTIAL: break; default: return (EINVAL); } if (start > end) return EINVAL; start = MAX(start, map->min_offset); end = MIN(end, map->max_offset); if (start >= end) return 0; vm_map_lock(map); entry = uvm_map_entrybyaddr(&map->addr, start); if (entry != NULL && entry->end > start) UVM_MAP_CLIP_START(map, entry, start); else if (entry!= NULL) entry = RBT_NEXT(uvm_map_addr, entry); /* * XXXJRT: disallow holes? */ while (entry != NULL && entry->start < end) { UVM_MAP_CLIP_END(map, entry, end); entry->advice = new_advice; entry = RBT_NEXT(uvm_map_addr, entry); } vm_map_unlock(map); return (0); } /* * uvm_map_extract: extract a mapping from a map and put it somewhere * in the kernel_map, setting protection to max_prot. * * => map should be unlocked (we will write lock it and kernel_map) * => returns 0 on success, error code otherwise * => start must be page aligned * => len must be page sized * => flags: * UVM_EXTRACT_FIXPROT: set prot to maxprot as we go * Mappings are QREF's. */ int uvm_map_extract(struct vm_map *srcmap, vaddr_t start, vsize_t len, vaddr_t *dstaddrp, int flags) { struct uvm_map_deadq dead; struct vm_map_entry *first, *entry, *newentry, *tmp1, *tmp2; vaddr_t dstaddr; vaddr_t end; vaddr_t cp_start; vsize_t cp_len, cp_off; int error; TAILQ_INIT(&dead); end = start + len; /* * Sanity check on the parameters. * Also, since the mapping may not contain gaps, error out if the * mapped area is not in source map. */ if ((start & (vaddr_t)PAGE_MASK) != 0 || (end & (vaddr_t)PAGE_MASK) != 0 || end < start) return EINVAL; if (start < srcmap->min_offset || end > srcmap->max_offset) return EINVAL; /* Initialize dead entries. Handle len == 0 case. */ if (len == 0) return 0; /* Acquire lock on srcmap. */ vm_map_lock(srcmap); /* Lock srcmap, lookup first and last entry in <start,len>. */ first = uvm_map_entrybyaddr(&srcmap->addr, start); /* Check that the range is contiguous. */ for (entry = first; entry != NULL && entry->end < end; entry = RBT_NEXT(uvm_map_addr, entry)) { if (VMMAP_FREE_END(entry) != entry->end || UVM_ET_ISHOLE(entry)) { error = EINVAL; goto fail; } } if (entry == NULL || UVM_ET_ISHOLE(entry)) { error = EINVAL; goto fail; } /* * Handle need-copy flag. */ for (entry = first; entry != NULL && entry->start < end; entry = RBT_NEXT(uvm_map_addr, entry)) { if (UVM_ET_ISNEEDSCOPY(entry)) amap_copy(srcmap, entry, M_NOWAIT, UVM_ET_ISSTACK(entry) ? FALSE : TRUE, start, end); if (UVM_ET_ISNEEDSCOPY(entry)) { /* * amap_copy failure */ error = ENOMEM; goto fail; } } /* Lock destination map (kernel_map). */ vm_map_lock(kernel_map); if (uvm_map_findspace(kernel_map, &tmp1, &tmp2, &dstaddr, len, MAX(PAGE_SIZE, PMAP_PREFER_ALIGN()), PMAP_PREFER_OFFSET(start), PROT_NONE, 0) != 0) { error = ENOMEM; goto fail2; } *dstaddrp = dstaddr; /* * We now have srcmap and kernel_map locked. * dstaddr contains the destination offset in dstmap. */ /* step 1: start looping through map entries, performing extraction. */ for (entry = first; entry != NULL && entry->start < end; entry = RBT_NEXT(uvm_map_addr, entry)) { KDASSERT(!UVM_ET_ISNEEDSCOPY(entry)); if (UVM_ET_ISHOLE(entry)) continue; /* Calculate uvm_mapent_clone parameters. */ cp_start = entry->start; if (cp_start < start) { cp_off = start - cp_start; cp_start = start; } else cp_off = 0; cp_len = MIN(entry->end, end) - cp_start; newentry = uvm_mapent_clone(kernel_map, cp_start - start + dstaddr, cp_len, cp_off, entry->protection, entry->max_protection, entry, &dead, flags, AMAP_SHARED | AMAP_REFALL); if (newentry == NULL) { error = ENOMEM; goto fail2_unmap; } kernel_map->size += cp_len; /* Figure out the best protection */ if ((flags & UVM_EXTRACT_FIXPROT) && newentry->protection != PROT_NONE) newentry->protection = newentry->max_protection; newentry->protection &= ~PROT_EXEC; } pmap_update(kernel_map->pmap); error = 0; /* Unmap copied entries on failure. */ fail2_unmap: if (error) { uvm_unmap_remove(kernel_map, dstaddr, dstaddr + len, &dead, FALSE, TRUE, FALSE); } /* Release maps, release dead entries. */ fail2: vm_map_unlock(kernel_map); fail: vm_map_unlock(srcmap); uvm_unmap_detach(&dead, 0); return error; } /* * uvm_map_clean: clean out a map range * * => valid flags: * if (flags & PGO_CLEANIT): dirty pages are cleaned first * if (flags & PGO_SYNCIO): dirty pages are written synchronously * if (flags & PGO_DEACTIVATE): any cached pages are deactivated after clean * if (flags & PGO_FREE): any cached pages are freed after clean * => returns an error if any part of the specified range isn't mapped * => never a need to flush amap layer since the anonymous memory has * no permanent home, but may deactivate pages there * => called from sys_msync() and sys_madvise() * => caller must not have map locked */ int uvm_map_clean(struct vm_map *map, vaddr_t start, vaddr_t end, int flags) { struct vm_map_entry *first, *entry; struct vm_amap *amap; struct vm_anon *anon; struct vm_page *pg; struct uvm_object *uobj; vaddr_t cp_start, cp_end; int refs, imut = 0; int error; boolean_t rv; KASSERT((flags & (PGO_FREE|PGO_DEACTIVATE)) != (PGO_FREE|PGO_DEACTIVATE)); if (start > end || start < map->min_offset || end > map->max_offset) return EINVAL; vm_map_lock(map); first = uvm_map_entrybyaddr(&map->addr, start); /* Make a first pass to check for various conditions. */ for (entry = first; entry != NULL && entry->start < end; entry = RBT_NEXT(uvm_map_addr, entry)) { if (entry->etype & UVM_ET_IMMUTABLE) imut = 1; if (UVM_ET_ISSUBMAP(entry)) { vm_map_unlock(map); return EINVAL; } if (UVM_ET_ISSUBMAP(entry) || UVM_ET_ISHOLE(entry) || (entry->end < end && VMMAP_FREE_END(entry) != entry->end)) { vm_map_unlock(map); return EFAULT; } } vm_map_busy(map); vm_map_unlock(map); error = 0; for (entry = first; entry != NULL && entry->start < end; entry = RBT_NEXT(uvm_map_addr, entry)) { amap = entry->aref.ar_amap; /* top layer */ if (UVM_ET_ISOBJ(entry)) uobj = entry->object.uvm_obj; else uobj = NULL; /* * No amap cleaning necessary if: * - there's no amap * - we're not deactivating or freeing pages. */ if (amap == NULL || (flags & (PGO_DEACTIVATE|PGO_FREE)) == 0) goto flush_object; if (imut) { vm_map_unbusy(map); return EPERM; } cp_start = MAX(entry->start, start); cp_end = MIN(entry->end, end); amap_lock(amap); for (; cp_start != cp_end; cp_start += PAGE_SIZE) { anon = amap_lookup(&entry->aref, cp_start - entry->start); if (anon == NULL) continue; KASSERT(anon->an_lock == amap->am_lock); pg = anon->an_page; if (pg == NULL) { continue; } KASSERT(pg->pg_flags & PQ_ANON); switch (flags & (PGO_CLEANIT|PGO_FREE|PGO_DEACTIVATE)) { /* * XXX In these first 3 cases, we always just * XXX deactivate the page. We may want to * XXX handle the different cases more * XXX specifically, in the future. */ case PGO_CLEANIT|PGO_FREE: case PGO_CLEANIT|PGO_DEACTIVATE: case PGO_DEACTIVATE: deactivate_it: /* skip the page if it's wired */ if (pg->wire_count != 0) break; uvm_lock_pageq(); KASSERT(pg->uanon == anon); /* zap all mappings for the page. */ pmap_page_protect(pg, PROT_NONE); /* ...and deactivate the page. */ uvm_pagedeactivate(pg); uvm_unlock_pageq(); break; case PGO_FREE: /* * If there are multiple references to * the amap, just deactivate the page. */ if (amap_refs(amap) > 1) goto deactivate_it; /* XXX skip the page if it's wired */ if (pg->wire_count != 0) { break; } amap_unadd(&entry->aref, cp_start - entry->start); refs = --anon->an_ref; if (refs == 0) uvm_anfree(anon); break; default: panic("uvm_map_clean: weird flags"); } } amap_unlock(amap); flush_object: cp_start = MAX(entry->start, start); cp_end = MIN(entry->end, end); /* * flush pages if we've got a valid backing object. * * Don't PGO_FREE if we don't have write permission * and don't flush if this is a copy-on-write object * since we can't know our permissions on it. */ if (uobj != NULL && ((flags & PGO_FREE) == 0 || ((entry->max_protection & PROT_WRITE) != 0 && (entry->etype & UVM_ET_COPYONWRITE) == 0))) { rw_enter(uobj->vmobjlock, RW_WRITE); rv = uobj->pgops->pgo_flush(uobj, cp_start - entry->start + entry->offset, cp_end - entry->start + entry->offset, flags); rw_exit(uobj->vmobjlock); if (rv == FALSE) error = EFAULT; } } vm_map_unbusy(map); return error; } /* * UVM_MAP_CLIP_END implementation */ void uvm_map_clip_end(struct vm_map *map, struct vm_map_entry *entry, vaddr_t addr) { struct vm_map_entry *tmp; KASSERT(entry->start < addr && VMMAP_FREE_END(entry) > addr); tmp = uvm_mapent_alloc(map, 0); /* Invoke splitentry. */ uvm_map_splitentry(map, entry, tmp, addr); } /* * UVM_MAP_CLIP_START implementation * * Clippers are required to not change the pointers to the entry they are * clipping on. * Since uvm_map_splitentry turns the original entry into the lowest * entry (address wise) we do a swap between the new entry and the original * entry, prior to calling uvm_map_splitentry. */ void uvm_map_clip_start(struct vm_map *map, struct vm_map_entry *entry, vaddr_t addr) { struct vm_map_entry *tmp; struct uvm_addr_state *free; /* Unlink original. */ free = uvm_map_uaddr_e(map, entry); uvm_mapent_free_remove(map, free, entry); uvm_mapent_addr_remove(map, entry); /* Copy entry. */ KASSERT(entry->start < addr && VMMAP_FREE_END(entry) > addr); tmp = uvm_mapent_alloc(map, 0); uvm_mapent_copy(entry, tmp); /* Put new entry in place of original entry. */ uvm_mapent_addr_insert(map, tmp); uvm_mapent_free_insert(map, free, tmp); /* Invoke splitentry. */ uvm_map_splitentry(map, tmp, entry, addr); } /* * Boundary fixer. */ static inline vaddr_t uvm_map_boundfix(vaddr_t, vaddr_t, vaddr_t); static inline vaddr_t uvm_map_boundfix(vaddr_t min, vaddr_t max, vaddr_t bound) { return (min < bound && max > bound) ? bound : max; } /* * Choose free list based on address at start of free space. * * The uvm_addr_state returned contains addr and is the first of: * - uaddr_exe * - uaddr_brk_stack * - uaddr_any */ struct uvm_addr_state* uvm_map_uaddr(struct vm_map *map, vaddr_t addr) { struct uvm_addr_state *uaddr; int i; /* Special case the first page, to prevent mmap from returning 0. */ if (addr < VMMAP_MIN_ADDR) return NULL; /* Upper bound for kernel maps at uvm_maxkaddr. */ if ((map->flags & VM_MAP_ISVMSPACE) == 0) { if (addr >= uvm_maxkaddr) return NULL; } /* Is the address inside the exe-only map? */ if (map->uaddr_exe != NULL && addr >= map->uaddr_exe->uaddr_minaddr && addr < map->uaddr_exe->uaddr_maxaddr) return map->uaddr_exe; /* Check if the space falls inside brk/stack area. */ if ((addr >= map->b_start && addr < map->b_end) || (addr >= map->s_start && addr < map->s_end)) { if (map->uaddr_brk_stack != NULL && addr >= map->uaddr_brk_stack->uaddr_minaddr && addr < map->uaddr_brk_stack->uaddr_maxaddr) { return map->uaddr_brk_stack; } else return NULL; } /* * Check the other selectors. * * These selectors are only marked as the owner, if they have insert * functions. */ for (i = 0; i < nitems(map->uaddr_any); i++) { uaddr = map->uaddr_any[i]; if (uaddr == NULL) continue; if (uaddr->uaddr_functions->uaddr_free_insert == NULL) continue; if (addr >= uaddr->uaddr_minaddr && addr < uaddr->uaddr_maxaddr) return uaddr; } return NULL; } /* * Choose free list based on address at start of free space. * * The uvm_addr_state returned contains addr and is the first of: * - uaddr_exe * - uaddr_brk_stack * - uaddr_any */ struct uvm_addr_state* uvm_map_uaddr_e(struct vm_map *map, struct vm_map_entry *entry) { return uvm_map_uaddr(map, VMMAP_FREE_START(entry)); } /* * Returns the first free-memory boundary that is crossed by [min-max]. */ vsize_t uvm_map_boundary(struct vm_map *map, vaddr_t min, vaddr_t max) { struct uvm_addr_state *uaddr; int i; /* Never return first page. */ max = uvm_map_boundfix(min, max, VMMAP_MIN_ADDR); /* Treat the maxkaddr special, if the map is a kernel_map. */ if ((map->flags & VM_MAP_ISVMSPACE) == 0) max = uvm_map_boundfix(min, max, uvm_maxkaddr); /* Check for exe-only boundaries. */ if (map->uaddr_exe != NULL) { max = uvm_map_boundfix(min, max, map->uaddr_exe->uaddr_minaddr); max = uvm_map_boundfix(min, max, map->uaddr_exe->uaddr_maxaddr); } /* Check for exe-only boundaries. */ if (map->uaddr_brk_stack != NULL) { max = uvm_map_boundfix(min, max, map->uaddr_brk_stack->uaddr_minaddr); max = uvm_map_boundfix(min, max, map->uaddr_brk_stack->uaddr_maxaddr); } /* Check other boundaries. */ for (i = 0; i < nitems(map->uaddr_any); i++) { uaddr = map->uaddr_any[i]; if (uaddr != NULL) { max = uvm_map_boundfix(min, max, uaddr->uaddr_minaddr); max = uvm_map_boundfix(min, max, uaddr->uaddr_maxaddr); } } /* Boundaries at stack and brk() area. */ max = uvm_map_boundfix(min, max, map->s_start); max = uvm_map_boundfix(min, max, map->s_end); max = uvm_map_boundfix(min, max, map->b_start); max = uvm_map_boundfix(min, max, map->b_end); return max; } /* * Update map allocation start and end addresses from proc vmspace. */ void uvm_map_vmspace_update(struct vm_map *map, struct uvm_map_deadq *dead, int flags) { struct vmspace *vm; vaddr_t b_start, b_end, s_start, s_end; KASSERT(map->flags & VM_MAP_ISVMSPACE); KASSERT(offsetof(struct vmspace, vm_map) == 0); /* * Derive actual allocation boundaries from vmspace. */ vm = (struct vmspace *)map; b_start = (vaddr_t)vm->vm_daddr; b_end = b_start + BRKSIZ; s_start = MIN((vaddr_t)vm->vm_maxsaddr, (vaddr_t)vm->vm_minsaddr); s_end = MAX((vaddr_t)vm->vm_maxsaddr, (vaddr_t)vm->vm_minsaddr); #ifdef DIAGNOSTIC if ((b_start & (vaddr_t)PAGE_MASK) != 0 || (b_end & (vaddr_t)PAGE_MASK) != 0 || (s_start & (vaddr_t)PAGE_MASK) != 0 || (s_end & (vaddr_t)PAGE_MASK) != 0) { panic("uvm_map_vmspace_update: vmspace %p invalid bounds: " "b=0x%lx-0x%lx s=0x%lx-0x%lx", vm, b_start, b_end, s_start, s_end); } #endif if (__predict_true(map->b_start == b_start && map->b_end == b_end && map->s_start == s_start && map->s_end == s_end)) return; uvm_map_freelist_update(map, dead, b_start, b_end, s_start, s_end, flags); } /* * Grow kernel memory. * * This function is only called for kernel maps when an allocation fails. * * If the map has a gap that is large enough to accommodate alloc_sz, this * function will make sure map->free will include it. */ void uvm_map_kmem_grow(struct vm_map *map, struct uvm_map_deadq *dead, vsize_t alloc_sz, int flags) { vsize_t sz; vaddr_t end; struct vm_map_entry *entry; /* Kernel memory only. */ KASSERT((map->flags & VM_MAP_ISVMSPACE) == 0); /* Destroy free list. */ uvm_map_freelist_update_clear(map, dead); /* Include the guard page in the hard minimum requirement of alloc_sz. */ if (map->flags & VM_MAP_GUARDPAGES) alloc_sz += PAGE_SIZE; /* * Grow by ALLOCMUL * alloc_sz, but at least VM_MAP_KSIZE_DELTA. * * Don't handle the case where the multiplication overflows: * if that happens, the allocation is probably too big anyway. */ sz = MAX(VM_MAP_KSIZE_ALLOCMUL * alloc_sz, VM_MAP_KSIZE_DELTA); /* * Walk forward until a gap large enough for alloc_sz shows up. * * We assume the kernel map has no boundaries. * uvm_maxkaddr may be zero. */ end = MAX(uvm_maxkaddr, map->min_offset); entry = uvm_map_entrybyaddr(&map->addr, end); while (entry && entry->fspace < alloc_sz) entry = RBT_NEXT(uvm_map_addr, entry); if (entry) { end = MAX(VMMAP_FREE_START(entry), end); end += MIN(sz, map->max_offset - end); } else end = map->max_offset; /* Reserve pmap entries. */ #ifdef PMAP_GROWKERNEL uvm_maxkaddr = pmap_growkernel(end); #else uvm_maxkaddr = MAX(uvm_maxkaddr, end); #endif /* Rebuild free list. */ uvm_map_freelist_update_refill(map, flags); } /* * Freelist update subfunction: unlink all entries from freelists. */ void uvm_map_freelist_update_clear(struct vm_map *map, struct uvm_map_deadq *dead) { struct uvm_addr_state *free; struct vm_map_entry *entry, *prev, *next; prev = NULL; for (entry = RBT_MIN(uvm_map_addr, &map->addr); entry != NULL; entry = next) { next = RBT_NEXT(uvm_map_addr, entry); free = uvm_map_uaddr_e(map, entry); uvm_mapent_free_remove(map, free, entry); if (prev != NULL && entry->start == entry->end) { prev->fspace += VMMAP_FREE_END(entry) - entry->end; uvm_mapent_addr_remove(map, entry); DEAD_ENTRY_PUSH(dead, entry); } else prev = entry; } } /* * Freelist update subfunction: refill the freelists with entries. */ void uvm_map_freelist_update_refill(struct vm_map *map, int flags) { struct vm_map_entry *entry; vaddr_t min, max; RBT_FOREACH(entry, uvm_map_addr, &map->addr) { min = VMMAP_FREE_START(entry); max = VMMAP_FREE_END(entry); entry->fspace = 0; entry = uvm_map_fix_space(map, entry, min, max, flags); } uvm_tree_sanity(map, __FILE__, __LINE__); } /* * Change {a,b}_{start,end} allocation ranges and associated free lists. */ void uvm_map_freelist_update(struct vm_map *map, struct uvm_map_deadq *dead, vaddr_t b_start, vaddr_t b_end, vaddr_t s_start, vaddr_t s_end, int flags) { KDASSERT(b_end >= b_start && s_end >= s_start); vm_map_assert_wrlock(map); /* Clear all free lists. */ uvm_map_freelist_update_clear(map, dead); /* Apply new bounds. */ map->b_start = b_start; map->b_end = b_end; map->s_start = s_start; map->s_end = s_end; /* Refill free lists. */ uvm_map_freelist_update_refill(map, flags); } /* * Assign a uvm_addr_state to the specified pointer in vm_map. * * May sleep. */ void uvm_map_set_uaddr(struct vm_map *map, struct uvm_addr_state **which, struct uvm_addr_state *newval) { struct uvm_map_deadq dead; /* Pointer which must be in this map. */ KASSERT(which != NULL); KASSERT((void*)map <= (void*)(which) && (void*)(which) < (void*)(map + 1)); vm_map_lock(map); TAILQ_INIT(&dead); uvm_map_freelist_update_clear(map, &dead); uvm_addr_destroy(*which); *which = newval; uvm_map_freelist_update_refill(map, 0); vm_map_unlock(map); uvm_unmap_detach(&dead, 0); } /* * Correct space insert. * * Entry must not be on any freelist. */ struct vm_map_entry* uvm_map_fix_space(struct vm_map *map, struct vm_map_entry *entry, vaddr_t min, vaddr_t max, int flags) { struct uvm_addr_state *free, *entfree; vaddr_t lmax; KASSERT(entry == NULL || (entry->etype & UVM_ET_FREEMAPPED) == 0); KDASSERT(min <= max); KDASSERT((entry != NULL && VMMAP_FREE_END(entry) == min) || min == map->min_offset); UVM_MAP_REQ_WRITE(map); /* * During the function, entfree will always point at the uaddr state * for entry. */ entfree = (entry == NULL ? NULL : uvm_map_uaddr_e(map, entry)); while (min != max) { /* Claim guard page for entry. */ if ((map->flags & VM_MAP_GUARDPAGES) && entry != NULL && VMMAP_FREE_END(entry) == entry->end && entry->start != entry->end) { if (max - min == 2 * PAGE_SIZE) { /* * If the free-space gap is exactly 2 pages, * we make the guard 2 pages instead of 1. * Because in a guarded map, an area needs * at least 2 pages to allocate from: * one page for the allocation and one for * the guard. */ entry->guard = 2 * PAGE_SIZE; min = max; } else { entry->guard = PAGE_SIZE; min += PAGE_SIZE; } continue; } /* * Handle the case where entry has a 2-page guard, but the * space after entry is freed. */ if (entry != NULL && entry->fspace == 0 && entry->guard > PAGE_SIZE) { entry->guard = PAGE_SIZE; min = VMMAP_FREE_START(entry); } lmax = uvm_map_boundary(map, min, max); free = uvm_map_uaddr(map, min); /* * Entries are merged if they point at the same uvm_free(). * Exception to that rule: if min == uvm_maxkaddr, a new * entry is started regardless (otherwise the allocators * will get confused). */ if (entry != NULL && free == entfree && !((map->flags & VM_MAP_ISVMSPACE) == 0 && min == uvm_maxkaddr)) { KDASSERT(VMMAP_FREE_END(entry) == min); entry->fspace += lmax - min; } else { /* * Commit entry to free list: it'll not be added to * anymore. * We'll start a new entry and add to that entry * instead. */ if (entry != NULL) uvm_mapent_free_insert(map, entfree, entry); /* New entry for new uaddr. */ entry = uvm_mapent_alloc(map, flags); KDASSERT(entry != NULL); entry->end = entry->start = min; entry->guard = 0; entry->fspace = lmax - min; entry->object.uvm_obj = NULL; entry->offset = 0; entry->etype = 0; entry->protection = entry->max_protection = 0; entry->inheritance = 0; entry->wired_count = 0; entry->advice = 0; entry->aref.ar_pageoff = 0; entry->aref.ar_amap = NULL; uvm_mapent_addr_insert(map, entry); entfree = free; } min = lmax; } /* Finally put entry on the uaddr state. */ if (entry != NULL) uvm_mapent_free_insert(map, entfree, entry); return entry; } /* * MQuery style of allocation. * * This allocator searches forward until sufficient space is found to map * the given size. * * XXX: factor in offset (via pmap_prefer) and protection? */ int uvm_map_mquery(struct vm_map *map, vaddr_t *addr_p, vsize_t sz, voff_t offset, int flags) { struct vm_map_entry *entry, *last; vaddr_t addr; vaddr_t tmp, pmap_align, pmap_offset; int error; addr = *addr_p; vm_map_lock_read(map); /* Configure pmap prefer. */ if (offset != UVM_UNKNOWN_OFFSET) { pmap_align = MAX(PAGE_SIZE, PMAP_PREFER_ALIGN()); pmap_offset = PMAP_PREFER_OFFSET(offset); } else { pmap_align = PAGE_SIZE; pmap_offset = 0; } /* Align address to pmap_prefer unless FLAG_FIXED is set. */ if (!(flags & UVM_FLAG_FIXED) && offset != UVM_UNKNOWN_OFFSET) { tmp = (addr & ~(pmap_align - 1)) | pmap_offset; if (tmp < addr) tmp += pmap_align; addr = tmp; } /* First, check if the requested range is fully available. */ entry = uvm_map_entrybyaddr(&map->addr, addr); last = NULL; if (uvm_map_isavail(map, NULL, &entry, &last, addr, sz)) { error = 0; goto out; } if (flags & UVM_FLAG_FIXED) { error = EINVAL; goto out; } error = ENOMEM; /* Default error from here. */ /* * At this point, the memory at <addr, sz> is not available. * The reasons are: * [1] it's outside the map, * [2] it starts in used memory (and therefore needs to move * toward the first free page in entry), * [3] it starts in free memory but bumps into used memory. * * Note that for case [2], the forward moving is handled by the * for loop below. */ if (entry == NULL) { /* [1] Outside the map. */ if (addr >= map->max_offset) goto out; else entry = RBT_MIN(uvm_map_addr, &map->addr); } else if (VMMAP_FREE_START(entry) <= addr) { /* [3] Bumped into used memory. */ entry = RBT_NEXT(uvm_map_addr, entry); } /* Test if the next entry is sufficient for the allocation. */ for (; entry != NULL; entry = RBT_NEXT(uvm_map_addr, entry)) { if (entry->fspace == 0) continue; addr = VMMAP_FREE_START(entry); restart: /* Restart address checks on address change. */ tmp = (addr & ~(pmap_align - 1)) | pmap_offset; if (tmp < addr) tmp += pmap_align; addr = tmp; if (addr >= VMMAP_FREE_END(entry)) continue; /* Skip brk() allocation addresses. */ if (addr + sz > map->b_start && addr < map->b_end) { if (VMMAP_FREE_END(entry) > map->b_end) { addr = map->b_end; goto restart; } else continue; } /* Skip stack allocation addresses. */ if (addr + sz > map->s_start && addr < map->s_end) { if (VMMAP_FREE_END(entry) > map->s_end) { addr = map->s_end; goto restart; } else continue; } last = NULL; if (uvm_map_isavail(map, NULL, &entry, &last, addr, sz)) { error = 0; goto out; } } out: vm_map_unlock_read(map); if (error == 0) *addr_p = addr; return error; } boolean_t vm_map_lock_try_ln(struct vm_map *map, char *file, int line) { boolean_t rv; if (map->flags & VM_MAP_INTRSAFE) { rv = mtx_enter_try(&map->mtx); } else { mtx_enter(&map->flags_lock); if ((map->flags & VM_MAP_BUSY) && (map->busy != curproc)) { mtx_leave(&map->flags_lock); return (FALSE); } mtx_leave(&map->flags_lock); rv = (rw_enter(&map->lock, RW_WRITE|RW_NOSLEEP) == 0); /* check if the lock is busy and back out if we won the race */ if (rv) { mtx_enter(&map->flags_lock); if ((map->flags & VM_MAP_BUSY) && (map->busy != curproc)) { rw_exit(&map->lock); rv = FALSE; } mtx_leave(&map->flags_lock); } } if (rv) { map->timestamp++; LPRINTF(("map lock: %p (at %s %d)\n", map, file, line)); uvm_tree_sanity(map, file, line); uvm_tree_size_chk(map, file, line); } return (rv); } void vm_map_lock_ln(struct vm_map *map, char *file, int line) { if ((map->flags & VM_MAP_INTRSAFE) == 0) { do { mtx_enter(&map->flags_lock); tryagain: while ((map->flags & VM_MAP_BUSY) && (map->busy != curproc)) { map->flags |= VM_MAP_WANTLOCK; msleep_nsec(&map->flags, &map->flags_lock, PVM, vmmapbsy, INFSLP); } mtx_leave(&map->flags_lock); } while (rw_enter(&map->lock, RW_WRITE|RW_SLEEPFAIL) != 0); /* check if the lock is busy and back out if we won the race */ mtx_enter(&map->flags_lock); if ((map->flags & VM_MAP_BUSY) && (map->busy != curproc)) { rw_exit(&map->lock); goto tryagain; } mtx_leave(&map->flags_lock); } else { mtx_enter(&map->mtx); } if (map->busy != curproc) map->timestamp++; LPRINTF(("map lock: %p (at %s %d)\n", map, file, line)); uvm_tree_sanity(map, file, line); uvm_tree_size_chk(map, file, line); } void vm_map_lock_read_ln(struct vm_map *map, char *file, int line) { if ((map->flags & VM_MAP_INTRSAFE) == 0) rw_enter_read(&map->lock); else mtx_enter(&map->mtx); LPRINTF(("map lock: %p (at %s %d)\n", map, file, line)); uvm_tree_sanity(map, file, line); uvm_tree_size_chk(map, file, line); } void vm_map_unlock_ln(struct vm_map *map, char *file, int line) { KASSERT(map->busy == NULL || map->busy == curproc); uvm_tree_sanity(map, file, line); uvm_tree_size_chk(map, file, line); LPRINTF(("map unlock: %p (at %s %d)\n", map, file, line)); if ((map->flags & VM_MAP_INTRSAFE) == 0) rw_exit(&map->lock); else mtx_leave(&map->mtx); } void vm_map_unlock_read_ln(struct vm_map *map, char *file, int line) { /* XXX: RO */ uvm_tree_sanity(map, file, line); /* XXX: RO */ uvm_tree_size_chk(map, file, line); LPRINTF(("map unlock: %p (at %s %d)\n", map, file, line)); if ((map->flags & VM_MAP_INTRSAFE) == 0) rw_exit_read(&map->lock); else mtx_leave(&map->mtx); } void vm_map_busy_ln(struct vm_map *map, char *file, int line) { KASSERT((map->flags & VM_MAP_INTRSAFE) == 0); KASSERT(rw_write_held(&map->lock)); KASSERT(map->busy == NULL); mtx_enter(&map->flags_lock); map->busy = curproc; map->flags |= VM_MAP_BUSY; mtx_leave(&map->flags_lock); } void vm_map_unbusy_ln(struct vm_map *map, char *file, int line) { int oflags; KASSERT((map->flags & VM_MAP_INTRSAFE) == 0); KASSERT(map->busy == curproc); mtx_enter(&map->flags_lock); oflags = map->flags; map->busy = NULL; map->flags &= ~(VM_MAP_BUSY|VM_MAP_WANTLOCK); mtx_leave(&map->flags_lock); if (oflags & VM_MAP_WANTLOCK) wakeup(&map->flags); } void vm_map_assert_anylock_ln(struct vm_map *map, char *file, int line) { LPRINTF(("map assert read or write locked: %p (at %s %d)\n", map, file, line)); if ((map->flags & VM_MAP_INTRSAFE) == 0) rw_assert_anylock(&map->lock); else MUTEX_ASSERT_LOCKED(&map->mtx); } void vm_map_assert_wrlock_ln(struct vm_map *map, char *file, int line) { LPRINTF(("map assert write locked: %p (at %s %d)\n", map, file, line)); if ((map->flags & VM_MAP_INTRSAFE) == 0) { splassert(IPL_NONE); rw_assert_wrlock(&map->lock); } else MUTEX_ASSERT_LOCKED(&map->mtx); } #ifndef SMALL_KERNEL int uvm_map_fill_vmmap(struct vm_map *map, struct kinfo_vmentry *kve, size_t *lenp) { struct vm_map_entry *entry; vaddr_t start; int cnt, maxcnt, error = 0; KASSERT(*lenp > 0); KASSERT((*lenp % sizeof(*kve)) == 0); cnt = 0; maxcnt = *lenp / sizeof(*kve); KASSERT(maxcnt > 0); /* * Return only entries whose address is above the given base * address. This allows userland to iterate without knowing the * number of entries beforehand. */ start = (vaddr_t)kve[0].kve_start; vm_map_lock(map); RBT_FOREACH(entry, uvm_map_addr, &map->addr) { if (cnt == maxcnt) { error = ENOMEM; break; } if (start != 0 && entry->start < start) continue; kve->kve_start = entry->start; kve->kve_end = entry->end; kve->kve_guard = entry->guard; kve->kve_fspace = entry->fspace; kve->kve_fspace_augment = entry->fspace_augment; kve->kve_offset = entry->offset; kve->kve_wired_count = entry->wired_count; kve->kve_etype = entry->etype; kve->kve_protection = entry->protection; kve->kve_max_protection = entry->max_protection; kve->kve_advice = entry->advice; kve->kve_inheritance = entry->inheritance; kve->kve_flags = entry->flags; kve++; cnt++; } vm_map_unlock(map); KASSERT(cnt <= maxcnt); *lenp = sizeof(*kve) * cnt; return error; } #endif RBT_GENERATE_AUGMENT(uvm_map_addr, vm_map_entry, daddrs.addr_entry, uvm_mapentry_addrcmp, uvm_map_addr_augment); /* * MD code: vmspace allocator setup. */ #ifdef __i386__ void uvm_map_setup_md(struct vm_map *map) { vaddr_t min, max; min = map->min_offset; max = map->max_offset; /* * Ensure the selectors will not try to manage page 0; * it's too special. */ if (min < VMMAP_MIN_ADDR) min = VMMAP_MIN_ADDR; #if 0 /* Cool stuff, not yet */ /* Executable code is special. */ map->uaddr_exe = uaddr_rnd_create(min, I386_MAX_EXE_ADDR); /* Place normal allocations beyond executable mappings. */ map->uaddr_any[3] = uaddr_pivot_create(2 * I386_MAX_EXE_ADDR, max); #else /* Crappy stuff, for now */ map->uaddr_any[0] = uaddr_rnd_create(min, max); #endif #ifndef SMALL_KERNEL map->uaddr_brk_stack = uaddr_stack_brk_create(min, max); #endif /* !SMALL_KERNEL */ } #elif __LP64__ void uvm_map_setup_md(struct vm_map *map) { vaddr_t min, max; min = map->min_offset; max = map->max_offset; /* * Ensure the selectors will not try to manage page 0; * it's too special. */ if (min < VMMAP_MIN_ADDR) min = VMMAP_MIN_ADDR; #if 0 /* Cool stuff, not yet */ map->uaddr_any[3] = uaddr_pivot_create(MAX(min, 0x100000000ULL), max); #else /* Crappy stuff, for now */ map->uaddr_any[0] = uaddr_rnd_create(min, max); #endif #ifndef SMALL_KERNEL map->uaddr_brk_stack = uaddr_stack_brk_create(min, max); #endif /* !SMALL_KERNEL */ } #else /* non-i386, 32 bit */ void uvm_map_setup_md(struct vm_map *map) { vaddr_t min, max; min = map->min_offset; max = map->max_offset; /* * Ensure the selectors will not try to manage page 0; * it's too special. */ if (min < VMMAP_MIN_ADDR) min = VMMAP_MIN_ADDR; #if 0 /* Cool stuff, not yet */ map->uaddr_any[3] = uaddr_pivot_create(min, max); #else /* Crappy stuff, for now */ map->uaddr_any[0] = uaddr_rnd_create(min, max); #endif #ifndef SMALL_KERNEL map->uaddr_brk_stack = uaddr_stack_brk_create(min, max); #endif /* !SMALL_KERNEL */ } #endif
117 16 8 9 66 24 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 /* $OpenBSD: sysv_ipc.c,v 1.8 2015/03/14 03:38:50 jsg Exp $ */ /* $NetBSD: sysv_ipc.c,v 1.10 1995/06/03 05:53:28 mycroft Exp $ */ /* * Copyright (c) 1995 Charles M. Hannum. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Charles M. Hannum. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/ipc.h> #include <sys/systm.h> #include <sys/mount.h> #include <sys/vnode.h> /* * Check for ipc permission */ int ipcperm(struct ucred *cred, struct ipc_perm *perm, int mode) { if (mode == IPC_M) { if (cred->cr_uid == 0 || cred->cr_uid == perm->uid || cred->cr_uid == perm->cuid) return (0); return (EPERM); } if (vaccess(VNON, perm->mode, perm->uid, perm->gid, mode, cred) == 0 || vaccess(VNON, perm->mode, perm->cuid, perm->cgid, mode, cred) == 0) return (0); return (EACCES); }
1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 /* $OpenBSD: fuse_vfsops.c,v 1.47 2024/05/20 09:11:21 mvs Exp $ */ /* * Copyright (c) 2012-2013 Sylvestre Gallon <ccna.syl@gmail.com> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/file.h> #include <sys/filedesc.h> #include <sys/malloc.h> #include <sys/mount.h> #include <sys/pool.h> #include <sys/proc.h> #include <sys/specdev.h> #include <sys/stat.h> #include <sys/statvfs.h> #include <sys/sysctl.h> #include <sys/vnode.h> #include <sys/fusebuf.h> #include "fusefs_node.h" #include "fusefs.h" int fusefs_mount(struct mount *, const char *, void *, struct nameidata *, struct proc *); int fusefs_start(struct mount *, int, struct proc *); int fusefs_unmount(struct mount *, int, struct proc *); int fusefs_root(struct mount *, struct vnode **); int fusefs_quotactl(struct mount *, int, uid_t, caddr_t, struct proc *); int fusefs_statfs(struct mount *, struct statfs *, struct proc *); int fusefs_sync(struct mount *, int, int, struct ucred *, struct proc *); int fusefs_vget(struct mount *, ino_t, struct vnode **); int fusefs_fhtovp(struct mount *, struct fid *, struct vnode **); int fusefs_vptofh(struct vnode *, struct fid *); int fusefs_init(struct vfsconf *); int fusefs_sysctl(int *, u_int, void *, size_t *, void *, size_t, struct proc *); int fusefs_checkexp(struct mount *, struct mbuf *, int *, struct ucred **); const struct vfsops fusefs_vfsops = { .vfs_mount = fusefs_mount, .vfs_start = fusefs_start, .vfs_unmount = fusefs_unmount, .vfs_root = fusefs_root, .vfs_quotactl = fusefs_quotactl, .vfs_statfs = fusefs_statfs, .vfs_sync = fusefs_sync, .vfs_vget = fusefs_vget, .vfs_fhtovp = fusefs_fhtovp, .vfs_vptofh = fusefs_vptofh, .vfs_init = fusefs_init, .vfs_sysctl = fusefs_sysctl, .vfs_checkexp = fusefs_checkexp, }; struct pool fusefs_fbuf_pool; #define PENDING 2 /* FBT_INIT reply not yet received */ int fusefs_mount(struct mount *mp, const char *path, void *data, struct nameidata *ndp, struct proc *p) { struct fusefs_mnt *fmp; struct fusebuf *fbuf; struct fusefs_args *args = data; struct vnode *vp; struct file *fp; int error = 0; if (mp->mnt_flag & MNT_UPDATE) return (EOPNOTSUPP); if ((fp = fd_getfile(p->p_fd, args->fd)) == NULL) return (EBADF); if (fp->f_type != DTYPE_VNODE) { error = EINVAL; goto bad; } vp = fp->f_data; if (vp->v_type != VCHR) { error = EBADF; goto bad; } /* Only root may specify allow_other. */ if (args->allow_other && (error = suser_ucred(p->p_ucred))) goto bad; fmp = malloc(sizeof(*fmp), M_FUSEFS, M_WAITOK | M_ZERO); fmp->mp = mp; fmp->sess_init = PENDING; fmp->dev = vp->v_rdev; if (args->max_read > 0) fmp->max_read = MIN(args->max_read, FUSEBUFMAXSIZE); else fmp->max_read = FUSEBUFMAXSIZE; fmp->allow_other = args->allow_other; mp->mnt_data = fmp; vfs_getnewfsid(mp); memset(mp->mnt_stat.f_mntonname, 0, MNAMELEN); strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN); memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN); strlcpy(mp->mnt_stat.f_mntfromname, "fusefs", MNAMELEN); memset(mp->mnt_stat.f_mntfromspec, 0, MNAMELEN); strlcpy(mp->mnt_stat.f_mntfromspec, "fusefs", MNAMELEN); fuse_device_set_fmp(fmp, 1); fbuf = fb_setup(0, 0, FBT_INIT, p); /* cannot tsleep on mount */ fuse_device_queue_fbuf(fmp->dev, fbuf); bad: FRELE(fp, p); return (error); } int fusefs_start(struct mount *mp, int flags, struct proc *p) { return (0); } int fusefs_unmount(struct mount *mp, int mntflags, struct proc *p) { struct fusefs_mnt *fmp; struct fusebuf *fbuf; int flags = 0; int error; fmp = VFSTOFUSEFS(mp); if (mntflags & MNT_FORCE) flags |= FORCECLOSE; if ((error = vflush(mp, NULLVP, flags))) return (error); if (fmp->sess_init && fmp->sess_init != PENDING) { fbuf = fb_setup(0, 0, FBT_DESTROY, p); error = fb_queue(fmp->dev, fbuf); if (error) printf("fusefs: error %d on destroy\n", error); fb_delete(fbuf); } fmp->sess_init = 0; fuse_device_cleanup(fmp->dev); fuse_device_set_fmp(fmp, 0); free(fmp, M_FUSEFS, sizeof(*fmp)); mp->mnt_data = NULL; return (0); } int fusefs_root(struct mount *mp, struct vnode **vpp) { struct vnode *nvp; int error; if ((error = VFS_VGET(mp, FUSE_ROOTINO, &nvp)) != 0) return (error); nvp->v_type = VDIR; *vpp = nvp; return (0); } int fusefs_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg, struct proc *p) { return (EOPNOTSUPP); } int fusefs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p) { struct fusefs_mnt *fmp; struct fusebuf *fbuf; int error; fmp = VFSTOFUSEFS(mp); /* Deny other users unless allow_other mount option was specified. */ if (!fmp->allow_other && p->p_ucred->cr_uid != mp->mnt_stat.f_owner) return (EPERM); copy_statfs_info(sbp, mp); /* * Both FBT_INIT and FBT_STATFS are sent to the FUSE file system * daemon when it is mounted. However, the daemon is the process * that called mount(2) so to prevent a deadlock return dummy * values until the response to FBT_INIT init is received. All * other VFS syscalls are queued. */ if (!fmp->sess_init || fmp->sess_init == PENDING) { sbp->f_bavail = 0; sbp->f_bfree = 0; sbp->f_blocks = 0; sbp->f_ffree = 0; sbp->f_favail = 0; sbp->f_files = 0; sbp->f_bsize = 0; sbp->f_iosize = 0; sbp->f_namemax = 0; } else { fbuf = fb_setup(0, FUSE_ROOTINO, FBT_STATFS, p); error = fb_queue(fmp->dev, fbuf); if (error) { fb_delete(fbuf); return (error); } sbp->f_bavail = fbuf->fb_stat.f_bavail; sbp->f_bfree = fbuf->fb_stat.f_bfree; sbp->f_blocks = fbuf->fb_stat.f_blocks; sbp->f_files = fbuf->fb_stat.f_files; sbp->f_ffree = fbuf->fb_stat.f_ffree; sbp->f_favail = fbuf->fb_stat.f_favail; sbp->f_bsize = fbuf->fb_stat.f_frsize; sbp->f_iosize = fbuf->fb_stat.f_bsize; sbp->f_namemax = fbuf->fb_stat.f_namemax; fb_delete(fbuf); } return (0); } int fusefs_sync(struct mount *mp, int waitfor, int stall, struct ucred *cred, struct proc *p) { return (0); } int fusefs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) { struct vattr vattr; struct fusefs_mnt *fmp; struct fusefs_node *ip; struct vnode *nvp; int i; int error; retry: fmp = VFSTOFUSEFS(mp); /* * check if vnode is in hash. */ if ((*vpp = ufs_ihashget(fmp->dev, ino)) != NULLVP) return (0); /* * if not create it */ if ((error = getnewvnode(VT_FUSEFS, mp, &fusefs_vops, &nvp)) != 0) { printf("fusefs: getnewvnode error\n"); *vpp = NULLVP; return (error); } ip = malloc(sizeof(*ip), M_FUSEFS, M_WAITOK | M_ZERO); rrw_init_flags(&ip->ufs_ino.i_lock, "fuseinode", RWL_DUPOK | RWL_IS_VNODE); nvp->v_data = ip; ip->ufs_ino.i_vnode = nvp; ip->ufs_ino.i_dev = fmp->dev; ip->ufs_ino.i_number = ino; for (i = 0; i < FUFH_MAXTYPE; i++) ip->fufh[i].fh_type = FUFH_INVALID; error = ufs_ihashins(&ip->ufs_ino); if (error) { vrele(nvp); if (error == EEXIST) goto retry; return (error); } ip->ufs_ino.i_ump = (struct ufsmount *)fmp; if (ino == FUSE_ROOTINO) nvp->v_flag |= VROOT; else { /* * Initialise the file size so that file size changes can be * detected during file operations. */ error = VOP_GETATTR(nvp, &vattr, curproc->p_ucred, curproc); if (error) { vrele(nvp); return (error); } ip->filesize = vattr.va_size; } *vpp = nvp; return (0); } int fusefs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) { return (EINVAL); } int fusefs_vptofh(struct vnode *vp, struct fid *fhp) { return (EINVAL); } int fusefs_init(struct vfsconf *vfc) { pool_init(&fusefs_fbuf_pool, sizeof(struct fusebuf), 0, 0, PR_WAITOK, "fmsg", NULL); return (0); } extern int stat_fbufs_in, stat_fbufs_wait, stat_opened_fusedev; const struct sysctl_bounded_args fusefs_vars[] = { { FUSEFS_OPENDEVS, &stat_opened_fusedev, SYSCTL_INT_READONLY }, { FUSEFS_INFBUFS, &stat_fbufs_in, SYSCTL_INT_READONLY }, { FUSEFS_WAITFBUFS, &stat_fbufs_wait, SYSCTL_INT_READONLY }, { FUSEFS_POOL_NBPAGES, &fusefs_fbuf_pool.pr_npages, SYSCTL_INT_READONLY }, }; int fusefs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { return sysctl_bounded_arr(fusefs_vars, nitems(fusefs_vars), name, namelen, oldp, oldlenp, newp, newlen); } int fusefs_checkexp(struct mount *mp, struct mbuf *nam, int *extflagsp, struct ucred **credanonp) { return (EOPNOTSUPP); }
11 8 4 2 2 2 3 1 1 1 3 1 1 1 1 2 1 3 3 1 1 2 4 4 1 1 2 1 2 2 3 3 2 3 3 2 2 2 2 1 5 1 12 9 1 7 7 2 2 2 2 1 2 3 3 1 1 2 3 3 1 2 2 1 3 3 3 2 2 4 4 5 5 5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 /* $OpenBSD: if_pppx.c,v 1.128 2023/12/23 10:52:54 bluhm Exp $ */ /* * Copyright (c) 2010 Claudio Jeker <claudio@openbsd.org> * Copyright (c) 2010 David Gwynne <dlg@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/buf.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/device.h> #include <sys/conf.h> #include <sys/queue.h> #include <sys/pool.h> #include <sys/mbuf.h> #include <sys/errno.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <sys/vnode.h> #include <sys/event.h> #include <sys/mutex.h> #include <sys/refcnt.h> #include <net/if.h> #include <net/if_types.h> #include <netinet/in.h> #include <netinet/if_ether.h> #include <net/if_dl.h> #include <netinet/in_var.h> #include <netinet/ip.h> #include <netinet/ip_var.h> #ifdef INET6 #include <netinet6/in6_var.h> #include <netinet/ip6.h> #include <netinet6/nd6.h> #endif /* INET6 */ #include "bpfilter.h" #if NBPFILTER > 0 #include <net/bpf.h> #endif #include "pf.h" #if NPF > 0 #include <net/pfvar.h> #endif #include <net/ppp_defs.h> #include <net/ppp-comp.h> #include <crypto/arc4.h> #ifdef PIPEX #include <net/radix.h> #include <net/pipex.h> #include <net/pipex_local.h> #else #error PIPEX option not enabled #endif #ifdef PPPX_DEBUG #define PPPX_D_INIT (1<<0) int pppxdebug = 0; #define DPRINTF(_m, _p...) do { \ if (ISSET(pppxdebug, (_m))) \ printf(_p); \ } while (0) #else #define DPRINTF(_m, _p...) /* _m, _p */ #endif struct pppx_if; /* * Locks used to protect struct members and global data * I immutable after creation * K kernel lock * N net lock * m pxd_mtx */ struct pppx_dev { LIST_ENTRY(pppx_dev) pxd_entry; /* [K] */ int pxd_unit; /* [I] */ /* kq shizz */ struct mutex pxd_mtx; struct klist pxd_rklist; /* [m] */ struct klist pxd_wklist; /* [m] */ /* queue of packets for userland to service - protected by splnet */ struct mbuf_queue pxd_svcq; int pxd_waiting; /* [N] */ LIST_HEAD(,pppx_if) pxd_pxis; /* [K] */ }; LIST_HEAD(, pppx_dev) pppx_devs = LIST_HEAD_INITIALIZER(pppx_devs); /* [K] */ struct pool pppx_if_pl; struct pppx_dev *pppx_dev_lookup(dev_t); struct pppx_dev *pppx_dev2pxd(dev_t); struct pppx_if_key { int pxik_session_id; /* [I] */ int pxik_protocol; /* [I] */ }; struct pppx_if { struct pppx_if_key pxi_key; /* [I] must be first in the struct */ struct refcnt pxi_refcnt; RBT_ENTRY(pppx_if) pxi_entry; /* [K] */ LIST_ENTRY(pppx_if) pxi_list; /* [K] */ int pxi_ready; /* [K] */ int pxi_unit; /* [I] */ struct ifnet pxi_if; struct pppx_dev *pxi_dev; /* [I] */ struct pipex_session *pxi_session; /* [I] */ }; static inline int pppx_if_cmp(const struct pppx_if *a, const struct pppx_if *b) { return memcmp(&a->pxi_key, &b->pxi_key, sizeof(a->pxi_key)); } RBT_HEAD(pppx_ifs, pppx_if) pppx_ifs = RBT_INITIALIZER(&pppx_ifs); /* [N] */ RBT_PROTOTYPE(pppx_ifs, pppx_if, pxi_entry, pppx_if_cmp); int pppx_if_next_unit(void); struct pppx_if *pppx_if_find_locked(struct pppx_dev *, int, int); static inline struct pppx_if *pppx_if_find(struct pppx_dev *, int, int); static inline void pppx_if_rele(struct pppx_if *); int pppx_add_session(struct pppx_dev *, struct pipex_session_req *); int pppx_del_session(struct pppx_dev *, struct pipex_session_close_req *); int pppx_set_session_descr(struct pppx_dev *, struct pipex_session_descr_req *); void pppx_if_destroy(struct pppx_dev *, struct pppx_if *); void pppx_if_qstart(struct ifqueue *); int pppx_if_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); int pppx_if_ioctl(struct ifnet *, u_long, caddr_t); void pppxattach(int); void filt_pppx_rdetach(struct knote *); int filt_pppx_read(struct knote *, long); int filt_pppx_modify(struct kevent *, struct knote *); int filt_pppx_process(struct knote *, struct kevent *); const struct filterops pppx_rd_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_pppx_rdetach, .f_event = filt_pppx_read, .f_modify = filt_pppx_modify, .f_process = filt_pppx_process, }; void filt_pppx_wdetach(struct knote *); int filt_pppx_write(struct knote *, long); const struct filterops pppx_wr_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_pppx_wdetach, .f_event = filt_pppx_write, .f_modify = filt_pppx_modify, .f_process = filt_pppx_process, }; struct pppx_dev * pppx_dev_lookup(dev_t dev) { struct pppx_dev *pxd; int unit = minor(dev); LIST_FOREACH(pxd, &pppx_devs, pxd_entry) { if (pxd->pxd_unit == unit) return (pxd); } return (NULL); } struct pppx_dev * pppx_dev2pxd(dev_t dev) { struct pppx_dev *pxd; pxd = pppx_dev_lookup(dev); return (pxd); } void pppxattach(int n) { pool_init(&pppx_if_pl, sizeof(struct pppx_if), 0, IPL_NONE, PR_WAITOK, "pppxif", NULL); pipex_init(); } int pppxopen(dev_t dev, int flags, int mode, struct proc *p) { struct pppx_dev *pxd; pxd = malloc(sizeof(*pxd), M_DEVBUF, M_WAITOK | M_ZERO); if (pppx_dev_lookup(dev) != NULL) { free(pxd, M_DEVBUF, sizeof(*pxd)); return (EBUSY); } pxd->pxd_unit = minor(dev); mtx_init(&pxd->pxd_mtx, IPL_NET); klist_init_mutex(&pxd->pxd_rklist, &pxd->pxd_mtx); klist_init_mutex(&pxd->pxd_wklist, &pxd->pxd_mtx); LIST_INIT(&pxd->pxd_pxis); mq_init(&pxd->pxd_svcq, 128, IPL_NET); LIST_INSERT_HEAD(&pppx_devs, pxd, pxd_entry); return 0; } int pppxread(dev_t dev, struct uio *uio, int ioflag) { struct pppx_dev *pxd = pppx_dev2pxd(dev); struct mbuf *m, *m0; int error = 0; size_t len; if (!pxd) return (ENXIO); while ((m0 = mq_dequeue(&pxd->pxd_svcq)) == NULL) { if (ISSET(ioflag, IO_NDELAY)) return (EWOULDBLOCK); NET_LOCK(); pxd->pxd_waiting = 1; error = rwsleep_nsec(pxd, &netlock, (PZERO + 1)|PCATCH, "pppxread", INFSLP); NET_UNLOCK(); if (error != 0) { return (error); } } while (m0 != NULL && uio->uio_resid > 0 && error == 0) { len = ulmin(uio->uio_resid, m0->m_len); if (len != 0) error = uiomove(mtod(m0, caddr_t), len, uio); m = m_free(m0); m0 = m; } m_freem(m0); return (error); } int pppxwrite(dev_t dev, struct uio *uio, int ioflag) { struct pppx_dev *pxd = pppx_dev2pxd(dev); struct pppx_hdr *th; struct pppx_if *pxi; uint32_t proto; struct mbuf *top, **mp, *m; int tlen; int error = 0; size_t mlen; if (uio->uio_resid < sizeof(*th) + sizeof(uint32_t) || uio->uio_resid > MCLBYTES) return (EMSGSIZE); tlen = uio->uio_resid; MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == NULL) return (ENOBUFS); mlen = MHLEN; if (uio->uio_resid > MHLEN) { MCLGET(m, M_DONTWAIT); if (!(m->m_flags & M_EXT)) { m_free(m); return (ENOBUFS); } mlen = MCLBYTES; } top = NULL; mp = &top; while (error == 0 && uio->uio_resid > 0) { m->m_len = ulmin(mlen, uio->uio_resid); error = uiomove(mtod (m, caddr_t), m->m_len, uio); *mp = m; mp = &m->m_next; if (error == 0 && uio->uio_resid > 0) { MGET(m, M_DONTWAIT, MT_DATA); if (m == NULL) { error = ENOBUFS; break; } mlen = MLEN; if (uio->uio_resid >= MINCLSIZE) { MCLGET(m, M_DONTWAIT); if (!(m->m_flags & M_EXT)) { error = ENOBUFS; m_free(m); break; } mlen = MCLBYTES; } } } if (error) { m_freem(top); return (error); } top->m_pkthdr.len = tlen; /* Find the interface */ th = mtod(top, struct pppx_hdr *); m_adj(top, sizeof(struct pppx_hdr)); pxi = pppx_if_find(pxd, th->pppx_id, th->pppx_proto); if (pxi == NULL) { m_freem(top); return (EINVAL); } top->m_pkthdr.ph_ifidx = pxi->pxi_if.if_index; #if NBPFILTER > 0 if (pxi->pxi_if.if_bpf) bpf_mtap(pxi->pxi_if.if_bpf, top, BPF_DIRECTION_IN); #endif /* strip the tunnel header */ proto = ntohl(*(uint32_t *)(th + 1)); m_adj(top, sizeof(uint32_t)); NET_LOCK(); switch (proto) { case AF_INET: ipv4_input(&pxi->pxi_if, top); break; #ifdef INET6 case AF_INET6: ipv6_input(&pxi->pxi_if, top); break; #endif default: m_freem(top); error = EAFNOSUPPORT; break; } NET_UNLOCK(); pppx_if_rele(pxi); return (error); } int pppxioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) { struct pppx_dev *pxd = pppx_dev2pxd(dev); int error = 0; switch (cmd) { case PIPEXASESSION: error = pppx_add_session(pxd, (struct pipex_session_req *)addr); break; case PIPEXDSESSION: error = pppx_del_session(pxd, (struct pipex_session_close_req *)addr); break; case PIPEXSIFDESCR: error = pppx_set_session_descr(pxd, (struct pipex_session_descr_req *)addr); break; case FIONBIO: break; case FIONREAD: *(int *)addr = mq_hdatalen(&pxd->pxd_svcq); break; default: error = pipex_ioctl(pxd, cmd, addr); break; } return (error); } int pppxkqfilter(dev_t dev, struct knote *kn) { struct pppx_dev *pxd = pppx_dev2pxd(dev); struct klist *klist; switch (kn->kn_filter) { case EVFILT_READ: klist = &pxd->pxd_rklist; kn->kn_fop = &pppx_rd_filtops; break; case EVFILT_WRITE: klist = &pxd->pxd_wklist; kn->kn_fop = &pppx_wr_filtops; break; default: return (EINVAL); } kn->kn_hook = pxd; klist_insert(klist, kn); return (0); } void filt_pppx_rdetach(struct knote *kn) { struct pppx_dev *pxd = kn->kn_hook; klist_remove(&pxd->pxd_rklist, kn); } int filt_pppx_read(struct knote *kn, long hint) { struct pppx_dev *pxd = kn->kn_hook; MUTEX_ASSERT_LOCKED(&pxd->pxd_mtx); kn->kn_data = mq_hdatalen(&pxd->pxd_svcq); return (kn->kn_data > 0); } void filt_pppx_wdetach(struct knote *kn) { struct pppx_dev *pxd = kn->kn_hook; klist_remove(&pxd->pxd_wklist, kn); } int filt_pppx_write(struct knote *kn, long hint) { /* We're always ready to accept a write. */ return (1); } int filt_pppx_modify(struct kevent *kev, struct knote *kn) { struct pppx_dev *pxd = kn->kn_hook; int active; mtx_enter(&pxd->pxd_mtx); active = knote_modify(kev, kn); mtx_leave(&pxd->pxd_mtx); return (active); } int filt_pppx_process(struct knote *kn, struct kevent *kev) { struct pppx_dev *pxd = kn->kn_hook; int active; mtx_enter(&pxd->pxd_mtx); active = knote_process(kn, kev); mtx_leave(&pxd->pxd_mtx); return (active); } int pppxclose(dev_t dev, int flags, int mode, struct proc *p) { struct pppx_dev *pxd; struct pppx_if *pxi; pxd = pppx_dev_lookup(dev); while ((pxi = LIST_FIRST(&pxd->pxd_pxis))) { pxi->pxi_ready = 0; pppx_if_destroy(pxd, pxi); } LIST_REMOVE(pxd, pxd_entry); mq_purge(&pxd->pxd_svcq); klist_free(&pxd->pxd_rklist); klist_free(&pxd->pxd_rklist); free(pxd, M_DEVBUF, sizeof(*pxd)); return (0); } int pppx_if_next_unit(void) { struct pppx_if *pxi; int unit = 0; /* this is safe without splnet since we're not modifying it */ do { int found = 0; RBT_FOREACH(pxi, pppx_ifs, &pppx_ifs) { if (pxi->pxi_unit == unit) { found = 1; break; } } if (found == 0) break; unit++; } while (unit > 0); return (unit); } struct pppx_if * pppx_if_find_locked(struct pppx_dev *pxd, int session_id, int protocol) { struct pppx_if_key key; struct pppx_if *pxi; memset(&key, 0, sizeof(key)); key.pxik_session_id = session_id; key.pxik_protocol = protocol; pxi = RBT_FIND(pppx_ifs, &pppx_ifs, (struct pppx_if *)&key); if (pxi && pxi->pxi_ready == 0) pxi = NULL; return pxi; } static inline struct pppx_if * pppx_if_find(struct pppx_dev *pxd, int session_id, int protocol) { struct pppx_if *pxi; if ((pxi = pppx_if_find_locked(pxd, session_id, protocol))) refcnt_take(&pxi->pxi_refcnt); return pxi; } static inline void pppx_if_rele(struct pppx_if *pxi) { refcnt_rele_wake(&pxi->pxi_refcnt); } int pppx_add_session(struct pppx_dev *pxd, struct pipex_session_req *req) { struct pppx_if *pxi; struct pipex_session *session; struct ifnet *ifp; int unit, error = 0; struct in_ifaddr *ia; struct sockaddr_in ifaddr; /* * XXX: As long as `session' is allocated as part of a `pxi' * it isn't possible to free it separately. So disallow * the timeout feature until this is fixed. */ if (req->pr_timeout_sec != 0) return (EINVAL); error = pipex_init_session(&session, req); if (error) return (error); pxi = pool_get(&pppx_if_pl, PR_WAITOK | PR_ZERO); ifp = &pxi->pxi_if; pxi->pxi_session = session; /* try to set the interface up */ unit = pppx_if_next_unit(); if (unit < 0) { error = ENOMEM; goto out; } refcnt_init(&pxi->pxi_refcnt); pxi->pxi_unit = unit; pxi->pxi_key.pxik_session_id = req->pr_session_id; pxi->pxi_key.pxik_protocol = req->pr_protocol; pxi->pxi_dev = pxd; if (RBT_INSERT(pppx_ifs, &pppx_ifs, pxi) != NULL) { error = EADDRINUSE; goto out; } LIST_INSERT_HEAD(&pxd->pxd_pxis, pxi, pxi_list); snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d", "pppx", unit); ifp->if_mtu = req->pr_peer_mru; /* XXX */ ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST | IFF_UP; ifp->if_xflags = IFXF_CLONED | IFXF_MPSAFE; ifp->if_qstart = pppx_if_qstart; ifp->if_output = pppx_if_output; ifp->if_ioctl = pppx_if_ioctl; ifp->if_rtrequest = p2p_rtrequest; ifp->if_type = IFT_PPP; ifp->if_softc = pxi; /* ifp->if_rdomain = req->pr_rdomain; */ if_counters_alloc(ifp); if_attach(ifp); NET_LOCK(); if_addgroup(ifp, "pppx"); if_alloc_sadl(ifp); NET_UNLOCK(); #if NBPFILTER > 0 bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(u_int32_t)); #endif /* XXX ipv6 support? how does the caller indicate it wants ipv6 * instead of ipv4? */ memset(&ifaddr, 0, sizeof(ifaddr)); ifaddr.sin_family = AF_INET; ifaddr.sin_len = sizeof(ifaddr); ifaddr.sin_addr = req->pr_ip_srcaddr; ia = malloc(sizeof (*ia), M_IFADDR, M_WAITOK | M_ZERO); refcnt_init_trace(&ia->ia_ifa.ifa_refcnt, DT_REFCNT_IDX_IFADDR); ia->ia_addr.sin_family = AF_INET; ia->ia_addr.sin_len = sizeof(struct sockaddr_in); ia->ia_addr.sin_addr = req->pr_ip_srcaddr; ia->ia_dstaddr.sin_family = AF_INET; ia->ia_dstaddr.sin_len = sizeof(struct sockaddr_in); ia->ia_dstaddr.sin_addr = req->pr_ip_address; ia->ia_sockmask.sin_family = AF_INET; ia->ia_sockmask.sin_len = sizeof(struct sockaddr_in); ia->ia_sockmask.sin_addr = req->pr_ip_netmask; ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr); ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr); ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask); ia->ia_ifa.ifa_ifp = ifp; ia->ia_netmask = ia->ia_sockmask.sin_addr.s_addr; NET_LOCK(); error = in_ifinit(ifp, ia, &ifaddr, 1); if (error) { printf("pppx: unable to set addresses for %s, error=%d\n", ifp->if_xname, error); } else { if_addrhooks_run(ifp); } NET_UNLOCK(); error = pipex_link_session(session, ifp, pxd); if (error) goto detach; NET_LOCK(); SET(ifp->if_flags, IFF_RUNNING); NET_UNLOCK(); pxi->pxi_ready = 1; return (error); detach: if_detach(ifp); if (RBT_REMOVE(pppx_ifs, &pppx_ifs, pxi) == NULL) panic("%s: inconsistent RB tree", __func__); LIST_REMOVE(pxi, pxi_list); out: pool_put(&pppx_if_pl, pxi); pipex_rele_session(session); return (error); } int pppx_del_session(struct pppx_dev *pxd, struct pipex_session_close_req *req) { struct pppx_if *pxi; pxi = pppx_if_find_locked(pxd, req->pcr_session_id, req->pcr_protocol); if (pxi == NULL) return (EINVAL); pxi->pxi_ready = 0; pipex_export_session_stats(pxi->pxi_session, &req->pcr_stat); pppx_if_destroy(pxd, pxi); return (0); } int pppx_set_session_descr(struct pppx_dev *pxd, struct pipex_session_descr_req *req) { struct pppx_if *pxi; pxi = pppx_if_find(pxd, req->pdr_session_id, req->pdr_protocol); if (pxi == NULL) return (EINVAL); NET_LOCK(); (void)memset(pxi->pxi_if.if_description, 0, IFDESCRSIZE); strlcpy(pxi->pxi_if.if_description, req->pdr_descr, IFDESCRSIZE); NET_UNLOCK(); pppx_if_rele(pxi); return (0); } void pppx_if_destroy(struct pppx_dev *pxd, struct pppx_if *pxi) { struct ifnet *ifp; struct pipex_session *session; session = pxi->pxi_session; ifp = &pxi->pxi_if; refcnt_finalize(&pxi->pxi_refcnt, "pxifinal"); NET_LOCK(); CLR(ifp->if_flags, IFF_RUNNING); NET_UNLOCK(); pipex_unlink_session(session); if_detach(ifp); pipex_rele_session(session); if (RBT_REMOVE(pppx_ifs, &pppx_ifs, pxi) == NULL) panic("%s: inconsistent RB tree", __func__); LIST_REMOVE(pxi, pxi_list); pool_put(&pppx_if_pl, pxi); } void pppx_if_qstart(struct ifqueue *ifq) { struct ifnet *ifp = ifq->ifq_if; struct pppx_if *pxi = (struct pppx_if *)ifp->if_softc; struct mbuf *m; int proto; while ((m = ifq_dequeue(ifq)) != NULL) { proto = *mtod(m, int *); m_adj(m, sizeof(proto)); pipex_ppp_output(m, pxi->pxi_session, proto); } } int pppx_if_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) { struct pppx_if *pxi = (struct pppx_if *)ifp->if_softc; struct pppx_hdr *th; int error = 0; int pipex_enable_local, proto; pipex_enable_local = atomic_load_int(&pipex_enable); NET_ASSERT_LOCKED(); if (!ISSET(ifp->if_flags, IFF_RUNNING)) { m_freem(m); error = ENETDOWN; goto out; } #if NBPFILTER > 0 if (ifp->if_bpf) bpf_mtap_af(ifp->if_bpf, dst->sa_family, m, BPF_DIRECTION_OUT); #endif if (pipex_enable_local) { switch (dst->sa_family) { #ifdef INET6 case AF_INET6: proto = PPP_IPV6; break; #endif case AF_INET: proto = PPP_IP; break; default: m_freem(m); error = EPFNOSUPPORT; goto out; } } else proto = htonl(dst->sa_family); M_PREPEND(m, sizeof(int), M_DONTWAIT); if (m == NULL) { error = ENOBUFS; goto out; } *mtod(m, int *) = proto; if (pipex_enable_local) error = if_enqueue(ifp, m); else { M_PREPEND(m, sizeof(struct pppx_hdr), M_DONTWAIT); if (m == NULL) { error = ENOBUFS; goto out; } th = mtod(m, struct pppx_hdr *); th->pppx_proto = 0; /* not used */ th->pppx_id = pxi->pxi_session->ppp_id; error = mq_enqueue(&pxi->pxi_dev->pxd_svcq, m); if (error == 0) { if (pxi->pxi_dev->pxd_waiting) { wakeup((caddr_t)pxi->pxi_dev); pxi->pxi_dev->pxd_waiting = 0; } knote(&pxi->pxi_dev->pxd_rklist, 0); } } out: if (error) counters_inc(ifp->if_counters, ifc_oerrors); return (error); } int pppx_if_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr) { struct pppx_if *pxi = (struct pppx_if *)ifp->if_softc; struct ifreq *ifr = (struct ifreq *)addr; int error = 0; switch (cmd) { case SIOCSIFADDR: break; case SIOCSIFFLAGS: break; case SIOCADDMULTI: case SIOCDELMULTI: break; case SIOCSIFMTU: if (ifr->ifr_mtu < 512 || ifr->ifr_mtu > pxi->pxi_session->peer_mru) error = EINVAL; else ifp->if_mtu = ifr->ifr_mtu; break; default: error = ENOTTY; break; } return (error); } RBT_GENERATE(pppx_ifs, pppx_if, pxi_entry, pppx_if_cmp); /* * Locks used to protect struct members and global data * I immutable after creation * K kernel lock * N net lock * m sc_mtx */ struct pppac_softc { struct ifnet sc_if; dev_t sc_dev; /* [I] */ int sc_ready; /* [K] */ LIST_ENTRY(pppac_softc) sc_entry; /* [K] */ struct mutex sc_mtx; struct klist sc_rklist; /* [m] */ struct klist sc_wklist; /* [m] */ struct pipex_session *sc_multicast_session; struct mbuf_queue sc_mq; }; LIST_HEAD(pppac_list, pppac_softc); /* [K] */ static void filt_pppac_rdetach(struct knote *); static int filt_pppac_read(struct knote *, long); static int filt_pppac_modify(struct kevent *, struct knote *); static int filt_pppac_process(struct knote *, struct kevent *); static const struct filterops pppac_rd_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_pppac_rdetach, .f_event = filt_pppac_read, .f_modify = filt_pppac_modify, .f_process = filt_pppac_process, }; static void filt_pppac_wdetach(struct knote *); static int filt_pppac_write(struct knote *, long); static const struct filterops pppac_wr_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_pppac_wdetach, .f_event = filt_pppac_write, .f_modify = filt_pppac_modify, .f_process = filt_pppac_process, }; static struct pppac_list pppac_devs = LIST_HEAD_INITIALIZER(pppac_devs); static int pppac_ioctl(struct ifnet *, u_long, caddr_t); static int pppac_add_session(struct pppac_softc *, struct pipex_session_req *); static int pppac_del_session(struct pppac_softc *, struct pipex_session_close_req *); static int pppac_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); static void pppac_qstart(struct ifqueue *); static inline struct pppac_softc * pppac_lookup(dev_t dev) { struct pppac_softc *sc; LIST_FOREACH(sc, &pppac_devs, sc_entry) { if (sc->sc_dev == dev) { if (sc->sc_ready == 0) break; return (sc); } } return (NULL); } void pppacattach(int n) { pipex_init(); /* to be sure, to be sure */ } int pppacopen(dev_t dev, int flags, int mode, struct proc *p) { struct pppac_softc *sc, *tmp; struct ifnet *ifp; struct pipex_session *session; sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); sc->sc_dev = dev; LIST_FOREACH(tmp, &pppac_devs, sc_entry) { if (tmp->sc_dev == dev) { free(sc, M_DEVBUF, sizeof(*sc)); return (EBUSY); } } LIST_INSERT_HEAD(&pppac_devs, sc, sc_entry); /* virtual pipex_session entry for multicast */ session = pool_get(&pipex_session_pool, PR_WAITOK | PR_ZERO); session->flags |= PIPEX_SFLAGS_MULTICAST; session->ownersc = sc; sc->sc_multicast_session = session; mtx_init(&sc->sc_mtx, IPL_SOFTNET); klist_init_mutex(&sc->sc_rklist, &sc->sc_mtx); klist_init_mutex(&sc->sc_wklist, &sc->sc_mtx); mq_init(&sc->sc_mq, IFQ_MAXLEN, IPL_SOFTNET); ifp = &sc->sc_if; snprintf(ifp->if_xname, sizeof(ifp->if_xname), "pppac%u", minor(dev)); ifp->if_softc = sc; ifp->if_type = IFT_L3IPVLAN; ifp->if_hdrlen = sizeof(uint32_t); /* for BPF */; ifp->if_mtu = MAXMCLBYTES - sizeof(uint32_t); ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST; ifp->if_xflags = IFXF_CLONED | IFXF_MPSAFE; ifp->if_rtrequest = p2p_rtrequest; /* XXX */ ifp->if_output = pppac_output; ifp->if_qstart = pppac_qstart; ifp->if_ioctl = pppac_ioctl; if_counters_alloc(ifp); if_attach(ifp); if_alloc_sadl(ifp); #if NBPFILTER > 0 bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(uint32_t)); #endif sc->sc_ready = 1; return (0); } int pppacread(dev_t dev, struct uio *uio, int ioflag) { struct pppac_softc *sc = pppac_lookup(dev); struct ifnet *ifp = &sc->sc_if; struct mbuf *m0, *m; int error = 0; size_t len; if (!ISSET(ifp->if_flags, IFF_RUNNING)) return (EHOSTDOWN); m0 = mq_dequeue(&sc->sc_mq); if (m0 == NULL) { if (ISSET(ioflag, IO_NDELAY)) return (EWOULDBLOCK); do { error = tsleep_nsec(sc, (PZERO + 1)|PCATCH, "pppacrd", INFSLP); if (error != 0) return (error); m0 = mq_dequeue(&sc->sc_mq); } while (m0 == NULL); } m = m0; while (uio->uio_resid > 0) { len = ulmin(uio->uio_resid, m->m_len); if (len != 0) { error = uiomove(mtod(m, caddr_t), len, uio); if (error != 0) break; } m = m->m_next; if (m == NULL) break; } m_freem(m0); return (error); } int pppacwrite(dev_t dev, struct uio *uio, int ioflag) { struct pppac_softc *sc = pppac_lookup(dev); struct ifnet *ifp = &sc->sc_if; uint32_t proto; int error; struct mbuf *m; if (!ISSET(ifp->if_flags, IFF_RUNNING)) return (EHOSTDOWN); if (uio->uio_resid < ifp->if_hdrlen || uio->uio_resid > MAXMCLBYTES) return (EMSGSIZE); m = m_gethdr(M_DONTWAIT, MT_DATA); if (m == NULL) return (ENOMEM); if (uio->uio_resid > MHLEN) { m_clget(m, M_WAITOK, uio->uio_resid); if (!ISSET(m->m_flags, M_EXT)) { m_free(m); return (ENOMEM); } } m->m_pkthdr.len = m->m_len = uio->uio_resid; error = uiomove(mtod(m, void *), m->m_len, uio); if (error != 0) { m_freem(m); return (error); } #if NBPFILTER > 0 if (ifp->if_bpf) bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN); #endif /* strip the tunnel header */ proto = ntohl(*mtod(m, uint32_t *)); m_adj(m, sizeof(uint32_t)); m->m_flags &= ~(M_MCAST|M_BCAST); m->m_pkthdr.ph_ifidx = ifp->if_index; m->m_pkthdr.ph_rtableid = ifp->if_rdomain; #if NPF > 0 pf_pkt_addr_changed(m); #endif counters_pkt(ifp->if_counters, ifc_ipackets, ifc_ibytes, m->m_pkthdr.len); NET_LOCK(); switch (proto) { case AF_INET: ipv4_input(ifp, m); break; #ifdef INET6 case AF_INET6: ipv6_input(ifp, m); break; #endif default: m_freem(m); error = EAFNOSUPPORT; break; } NET_UNLOCK(); return (error); } int pppacioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) { struct pppac_softc *sc = pppac_lookup(dev); int error = 0; switch (cmd) { case FIONBIO: break; case FIONREAD: *(int *)data = mq_hdatalen(&sc->sc_mq); break; case PIPEXASESSION: error = pppac_add_session(sc, (struct pipex_session_req *)data); break; case PIPEXDSESSION: error = pppac_del_session(sc, (struct pipex_session_close_req *)data); break; default: error = pipex_ioctl(sc, cmd, data); break; } return (error); } int pppackqfilter(dev_t dev, struct knote *kn) { struct pppac_softc *sc = pppac_lookup(dev); struct klist *klist; switch (kn->kn_filter) { case EVFILT_READ: klist = &sc->sc_rklist; kn->kn_fop = &pppac_rd_filtops; break; case EVFILT_WRITE: klist = &sc->sc_wklist; kn->kn_fop = &pppac_wr_filtops; break; default: return (EINVAL); } kn->kn_hook = sc; klist_insert(klist, kn); return (0); } static void filt_pppac_rdetach(struct knote *kn) { struct pppac_softc *sc = kn->kn_hook; klist_remove(&sc->sc_rklist, kn); } static int filt_pppac_read(struct knote *kn, long hint) { struct pppac_softc *sc = kn->kn_hook; MUTEX_ASSERT_LOCKED(&sc->sc_mtx); kn->kn_data = mq_hdatalen(&sc->sc_mq); return (kn->kn_data > 0); } static void filt_pppac_wdetach(struct knote *kn) { struct pppac_softc *sc = kn->kn_hook; klist_remove(&sc->sc_wklist, kn); } static int filt_pppac_write(struct knote *kn, long hint) { /* We're always ready to accept a write. */ return (1); } static int filt_pppac_modify(struct kevent *kev, struct knote *kn) { struct pppac_softc *sc = kn->kn_hook; int active; mtx_enter(&sc->sc_mtx); active = knote_modify(kev, kn); mtx_leave(&sc->sc_mtx); return (active); } static int filt_pppac_process(struct knote *kn, struct kevent *kev) { struct pppac_softc *sc = kn->kn_hook; int active; mtx_enter(&sc->sc_mtx); active = knote_process(kn, kev); mtx_leave(&sc->sc_mtx); return (active); } int pppacclose(dev_t dev, int flags, int mode, struct proc *p) { struct pppac_softc *sc = pppac_lookup(dev); struct ifnet *ifp = &sc->sc_if; sc->sc_ready = 0; NET_LOCK(); CLR(ifp->if_flags, IFF_RUNNING); NET_UNLOCK(); if_detach(ifp); klist_free(&sc->sc_rklist); klist_free(&sc->sc_wklist); pool_put(&pipex_session_pool, sc->sc_multicast_session); pipex_destroy_all_sessions(sc); LIST_REMOVE(sc, sc_entry); free(sc, M_DEVBUF, sizeof(*sc)); return (0); } static int pppac_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { /* struct ifreq *ifr = (struct ifreq *)data; */ int error = 0; switch (cmd) { case SIOCSIFADDR: SET(ifp->if_flags, IFF_UP); /* XXX cry cry */ /* FALLTHROUGH */ case SIOCSIFFLAGS: if (ISSET(ifp->if_flags, IFF_UP)) SET(ifp->if_flags, IFF_RUNNING); else CLR(ifp->if_flags, IFF_RUNNING); break; case SIOCSIFMTU: break; case SIOCADDMULTI: case SIOCDELMULTI: /* XXX */ break; default: error = ENOTTY; break; } return (error); } static int pppac_add_session(struct pppac_softc *sc, struct pipex_session_req *req) { int error; struct pipex_session *session; error = pipex_init_session(&session, req); if (error != 0) return (error); error = pipex_link_session(session, &sc->sc_if, sc); if (error != 0) pipex_rele_session(session); return (error); } static int pppac_del_session(struct pppac_softc *sc, struct pipex_session_close_req *req) { struct pipex_session *session; mtx_enter(&pipex_list_mtx); session = pipex_lookup_by_session_id_locked(req->pcr_protocol, req->pcr_session_id); if (session == NULL || session->ownersc != sc) { mtx_leave(&pipex_list_mtx); return (EINVAL); } pipex_unlink_session_locked(session); pipex_rele_session(session); mtx_leave(&pipex_list_mtx); return (0); } static int pppac_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) { int error; if (!ISSET(ifp->if_flags, IFF_RUNNING)) { error = EHOSTDOWN; goto drop; } switch (dst->sa_family) { case AF_INET: #ifdef INET6 case AF_INET6: #endif break; default: error = EAFNOSUPPORT; goto drop; } m->m_pkthdr.ph_family = dst->sa_family; return (if_enqueue(ifp, m)); drop: m_freem(m); return (error); } static void pppac_qstart(struct ifqueue *ifq) { struct ifnet *ifp = ifq->ifq_if; struct pppac_softc *sc = ifp->if_softc; struct mbuf *m, *m0; struct pipex_session *session; struct ip ip; int rv; while ((m = ifq_dequeue(ifq)) != NULL) { #if NBPFILTER > 0 if (ifp->if_bpf) { bpf_mtap_af(ifp->if_bpf, m->m_pkthdr.ph_family, m, BPF_DIRECTION_OUT); } #endif switch (m->m_pkthdr.ph_family) { case AF_INET: if (m->m_pkthdr.len < sizeof(struct ip)) goto bad; m_copydata(m, 0, sizeof(struct ip), &ip); if (IN_MULTICAST(ip.ip_dst.s_addr)) { /* pass a copy to pipex */ m0 = m_copym(m, 0, M_COPYALL, M_NOWAIT); if (m0 != NULL) pipex_ip_output(m0, sc->sc_multicast_session); else goto bad; } else { session = pipex_lookup_by_ip_address(ip.ip_dst); if (session != NULL) { pipex_ip_output(m, session); pipex_rele_session(session); m = NULL; } } break; } if (m == NULL) /* handled by pipex */ continue; m = m_prepend(m, sizeof(uint32_t), M_DONTWAIT); if (m == NULL) goto bad; *mtod(m, uint32_t *) = htonl(m->m_pkthdr.ph_family); rv = mq_enqueue(&sc->sc_mq, m); if (rv == 1) counters_inc(ifp->if_counters, ifc_collisions); continue; bad: counters_inc(ifp->if_counters, ifc_oerrors); if (m != NULL) m_freem(m); continue; } if (!mq_empty(&sc->sc_mq)) { wakeup(sc); knote(&sc->sc_rklist, 0); } }
16 1 5 6 3 12 12 12 5 7 8 13 14 10 5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 /* $OpenBSD: kern_physio.c,v 1.49 2024/02/03 18:51:58 beck Exp $ */ /* $NetBSD: kern_physio.c,v 1.28 1997/05/19 10:43:28 pk Exp $ */ /*- * Copyright (c) 1994 Christopher G. Demetriou * Copyright (c) 1982, 1986, 1990, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_physio.c 8.1 (Berkeley) 6/10/93 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/buf.h> #include <sys/pool.h> #include <uvm/uvm_extern.h> /* * The routines implemented in this file are described in: * Leffler, et al.: The Design and Implementation of the 4.3BSD * UNIX Operating System (Addison Welley, 1989) * on pages 231-233. */ /* * Do "physical I/O" on behalf of a user. "Physical I/O" is I/O directly * from the raw device to user buffers, and bypasses the buffer cache. * * Comments in brackets are from Leffler, et al.'s pseudo-code implementation. */ int physio(void (*strategy)(struct buf *), dev_t dev, int flags, void (*minphys)(struct buf *), struct uio *uio) { struct iovec *iovp; struct proc *p = curproc; long done, todo; int error, i, s; struct buf *bp; if ((uio->uio_offset % DEV_BSIZE) != 0) return (EINVAL); error = 0; flags &= B_READ | B_WRITE; /* Create a buffer. */ s = splbio(); bp = pool_get(&bufpool, PR_WAITOK | PR_ZERO); /* [set up the fixed part of the buffer for a transfer] */ bp->b_vnbufs.le_next = NOLIST; bp->b_dev = dev; bp->b_error = 0; bp->b_proc = p; bp->b_flags = B_BUSY; splx(s); /* * [while there are data to transfer and no I/O error] * Note that I/O errors are handled with a 'goto' at the bottom * of the 'while' loop. */ for (i = 0; i < uio->uio_iovcnt; i++) { iovp = &uio->uio_iov[i]; while (iovp->iov_len > 0) { void *map = NULL; /* * [mark the buffer busy for physical I/O] * (i.e. set B_PHYS (because it's an I/O to user * memory), and B_RAW, because B_RAW is to be * "Set by physio for raw transfers.", in addition * to the "busy" and read/write flag.) */ CLR(bp->b_flags, B_DONE | B_ERROR); bp->b_flags |= (B_BUSY | B_PHYS | B_RAW | flags); /* [set up the buffer for a maximum-sized transfer] */ bp->b_blkno = btodb(uio->uio_offset); /* * Because iov_len is size_t (unsigned) but b_bcount is * long (signed), an overflow is possible. Therefore * limit b_bcount to LONG_MAX before calling the * provided minphys. */ if (iovp->iov_len > LONG_MAX) bp->b_bcount = LONG_MAX; else bp->b_bcount = iovp->iov_len; /* * [call minphys to bound the transfer size] * and remember the amount of data to transfer, * for later comparison. */ (*minphys)(bp); todo = bp->b_bcount; KASSERTMSG(todo >= 0, "minphys broken"); /* * [lock the part of the user address space involved * in the transfer] * Beware vmapbuf(); it clobbers b_data and * saves it in b_saveaddr. However, vunmapbuf() * restores it. */ error = uvm_vslock_device(p, iovp->iov_base, todo, (flags & B_READ) ? PROT_READ | PROT_WRITE : PROT_READ, &map); if (error) goto done; if (map) { bp->b_data = map; } else { bp->b_data = iovp->iov_base; vmapbuf(bp, todo); } /* [call strategy to start the transfer] */ (*strategy)(bp); /* * Note that the raise/wait/lower/get error * steps below would be done by biowait(), but * we want to unlock the address space before * we lower the priority. * * [raise the priority level to splbio] */ s = splbio(); /* [wait for the transfer to complete] */ while ((bp->b_flags & B_DONE) == 0) tsleep_nsec(bp, PRIBIO + 1, "physio", INFSLP); /* Mark it busy again, so nobody else will use it. */ bp->b_flags |= B_BUSY; /* [lower the priority level] */ splx(s); /* * [unlock the part of the address space previously * locked] */ if (!map) vunmapbuf(bp, todo); uvm_vsunlock_device(p, iovp->iov_base, todo, map); /* remember error value (save a splbio/splx pair) */ if (bp->b_flags & B_ERROR) error = (bp->b_error ? bp->b_error : EIO); /* * [deduct the transfer size from the total number * of data to transfer] */ KASSERTMSG(bp->b_resid <= LONG_MAX, "strategy broken"); done = bp->b_bcount - bp->b_resid; KASSERTMSG(done >= 0, "strategy broken"); KASSERTMSG(done <= todo, "strategy broken"); iovp->iov_len -= done; iovp->iov_base = (caddr_t)iovp->iov_base + done; uio->uio_offset += done; uio->uio_resid -= done; /* * Now, check for an error. * Also, handle weird end-of-disk semantics. */ if (error || done < todo) goto done; } } done: /* * [clean up the state of the buffer] */ s = splbio(); /* XXXCDC: is this necessary? */ if (bp->b_vp) brelvp(bp); splx(s); pool_put(&bufpool, bp); return (error); } /* * Leffler, et al., says on p. 231: * "The minphys() routine is called by physio() to adjust the * size of each I/O transfer before the latter is passed to * the strategy routine..." * * so, just adjust the buffer's count accounting to MAXPHYS here, * and return the new count; */ void minphys(struct buf *bp) { if (bp->b_bcount > MAXPHYS) bp->b_bcount = MAXPHYS; }
208 209 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 /* $OpenBSD: virtio_pci.c,v 1.37 2024/05/17 16:37:10 sf Exp $ */ /* $NetBSD: virtio.c,v 1.3 2011/11/02 23:05:52 njoly Exp $ */ /* * Copyright (c) 2012 Stefan Fritsch. * Copyright (c) 2010 Minoura Makoto. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> #include <sys/mutex.h> #include <dev/pci/pcidevs.h> #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> #include <dev/pci/virtio_pcireg.h> #include <dev/pv/virtioreg.h> #include <dev/pv/virtiovar.h> #define DNPRINTF(n,x...) \ do { if (VIRTIO_DEBUG >= n) printf(x); } while(0) /* * XXX: Before being used on big endian arches, the access to config registers * XXX: needs to be reviewed/fixed. The non-device specific registers are * XXX: PCI-endian while the device specific registers are native endian. */ #define MAX_MSIX_VECS 8 struct virtio_pci_softc; int virtio_pci_match(struct device *, void *, void *); void virtio_pci_attach(struct device *, struct device *, void *); int virtio_pci_attach_09(struct virtio_pci_softc *sc, struct pci_attach_args *pa); int virtio_pci_attach_10(struct virtio_pci_softc *sc, struct pci_attach_args *pa); int virtio_pci_detach(struct device *, int); void virtio_pci_kick(struct virtio_softc *, uint16_t); int virtio_pci_adjust_config_region(struct virtio_pci_softc *); uint8_t virtio_pci_read_device_config_1(struct virtio_softc *, int); uint16_t virtio_pci_read_device_config_2(struct virtio_softc *, int); uint32_t virtio_pci_read_device_config_4(struct virtio_softc *, int); uint64_t virtio_pci_read_device_config_8(struct virtio_softc *, int); void virtio_pci_write_device_config_1(struct virtio_softc *, int, uint8_t); void virtio_pci_write_device_config_2(struct virtio_softc *, int, uint16_t); void virtio_pci_write_device_config_4(struct virtio_softc *, int, uint32_t); void virtio_pci_write_device_config_8(struct virtio_softc *, int, uint64_t); uint16_t virtio_pci_read_queue_size(struct virtio_softc *, uint16_t); void virtio_pci_setup_queue(struct virtio_softc *, struct virtqueue *, uint64_t); int virtio_pci_get_status(struct virtio_softc *); void virtio_pci_set_status(struct virtio_softc *, int); int virtio_pci_negotiate_features(struct virtio_softc *, const struct virtio_feature_name *); int virtio_pci_negotiate_features_10(struct virtio_softc *, const struct virtio_feature_name *); void virtio_pci_set_msix_queue_vector(struct virtio_pci_softc *, uint32_t, uint16_t); void virtio_pci_set_msix_config_vector(struct virtio_pci_softc *, uint16_t); int virtio_pci_msix_establish(struct virtio_pci_softc *, struct pci_attach_args *, int, int (*)(void *), void *); int virtio_pci_setup_msix(struct virtio_pci_softc *, struct pci_attach_args *, int); void virtio_pci_free_irqs(struct virtio_pci_softc *); int virtio_pci_poll_intr(void *); int virtio_pci_legacy_intr(void *); int virtio_pci_legacy_intr_mpsafe(void *); int virtio_pci_config_intr(void *); int virtio_pci_queue_intr(void *); int virtio_pci_shared_queue_intr(void *); int virtio_pci_find_cap(struct virtio_pci_softc *sc, int cfg_type, void *buf, int buflen); #if VIRTIO_DEBUG void virtio_pci_dump_caps(struct virtio_pci_softc *sc); #endif enum irq_type { IRQ_NO_MSIX, IRQ_MSIX_SHARED, /* vec 0: config irq, vec 1 shared by all vqs */ IRQ_MSIX_PER_VQ, /* vec 0: config irq, vec n: irq of vq[n-1] */ }; struct virtio_pci_softc { struct virtio_softc sc_sc; pci_chipset_tag_t sc_pc; pcitag_t sc_ptag; bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; bus_size_t sc_iosize; bus_space_tag_t sc_bars_iot[4]; bus_space_handle_t sc_bars_ioh[4]; bus_size_t sc_bars_iosize[4]; bus_space_tag_t sc_notify_iot; bus_space_handle_t sc_notify_ioh; bus_size_t sc_notify_iosize; unsigned int sc_notify_off_multiplier; bus_space_tag_t sc_devcfg_iot; bus_space_handle_t sc_devcfg_ioh; bus_size_t sc_devcfg_iosize; /* * With 0.9, the offset of the devcfg region in the io bar changes * depending on MSI-X being enabled or not. * With 1.0, this field is still used to remember if MSI-X is enabled * or not. */ unsigned int sc_devcfg_offset; bus_space_tag_t sc_isr_iot; bus_space_handle_t sc_isr_ioh; bus_size_t sc_isr_iosize; void *sc_ih[MAX_MSIX_VECS]; enum irq_type sc_irq_type; }; const struct cfattach virtio_pci_ca = { sizeof(struct virtio_pci_softc), virtio_pci_match, virtio_pci_attach, virtio_pci_detach, NULL }; struct virtio_ops virtio_pci_ops = { virtio_pci_kick, virtio_pci_read_device_config_1, virtio_pci_read_device_config_2, virtio_pci_read_device_config_4, virtio_pci_read_device_config_8, virtio_pci_write_device_config_1, virtio_pci_write_device_config_2, virtio_pci_write_device_config_4, virtio_pci_write_device_config_8, virtio_pci_read_queue_size, virtio_pci_setup_queue, virtio_pci_get_status, virtio_pci_set_status, virtio_pci_negotiate_features, virtio_pci_poll_intr, }; static inline uint64_t _cread(struct virtio_pci_softc *sc, unsigned off, unsigned size) { uint64_t val; switch (size) { case 1: val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, off); break; case 2: val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, off); break; case 4: val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, off); break; case 8: val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, off + sizeof(uint32_t)); val <<= 32; val += bus_space_read_4(sc->sc_iot, sc->sc_ioh, off); break; } return val; } #define CREAD(sc, memb) _cread(sc, offsetof(struct virtio_pci_common_cfg, memb), \ sizeof(((struct virtio_pci_common_cfg *)0)->memb)) #define CWRITE(sc, memb, val) \ do { \ struct virtio_pci_common_cfg c; \ size_t off = offsetof(struct virtio_pci_common_cfg, memb); \ size_t size = sizeof(c.memb); \ \ DNPRINTF(2, "%s: %d: off %#zx size %#zx write %#llx\n", \ __func__, __LINE__, off, size, (unsigned long long)val); \ switch (size) { \ case 1: \ bus_space_write_1(sc->sc_iot, sc->sc_ioh, off, val); \ break; \ case 2: \ bus_space_write_2(sc->sc_iot, sc->sc_ioh, off, val); \ break; \ case 4: \ bus_space_write_4(sc->sc_iot, sc->sc_ioh, off, val); \ break; \ case 8: \ bus_space_write_4(sc->sc_iot, sc->sc_ioh, off, \ (val) & 0xffffffff); \ bus_space_write_4(sc->sc_iot, sc->sc_ioh, \ (off) + sizeof(uint32_t), (uint64_t)(val) >> 32); \ break; \ } \ } while (0) uint16_t virtio_pci_read_queue_size(struct virtio_softc *vsc, uint16_t idx) { struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc; uint16_t ret; if (sc->sc_sc.sc_version_1) { CWRITE(sc, queue_select, idx); ret = CREAD(sc, queue_size); } else { bus_space_write_2(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_SELECT, idx); ret = bus_space_read_2(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_SIZE); } return ret; } void virtio_pci_setup_queue(struct virtio_softc *vsc, struct virtqueue *vq, uint64_t addr) { struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc; if (sc->sc_sc.sc_version_1) { CWRITE(sc, queue_select, vq->vq_index); if (addr == 0) { CWRITE(sc, queue_enable, 0); CWRITE(sc, queue_desc, 0); CWRITE(sc, queue_avail, 0); CWRITE(sc, queue_used, 0); } else { CWRITE(sc, queue_desc, addr); CWRITE(sc, queue_avail, addr + vq->vq_availoffset); CWRITE(sc, queue_used, addr + vq->vq_usedoffset); CWRITE(sc, queue_enable, 1); vq->vq_notify_off = CREAD(sc, queue_notify_off); } } else { bus_space_write_2(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_SELECT, vq->vq_index); bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_ADDRESS, addr / VIRTIO_PAGE_SIZE); } /* * This path is only executed if this function is called after * the child's attach function has finished. In other cases, * it's done in virtio_pci_setup_msix(). */ if (sc->sc_irq_type != IRQ_NO_MSIX) { int vec = 1; if (sc->sc_irq_type == IRQ_MSIX_PER_VQ) vec += vq->vq_index; if (sc->sc_sc.sc_version_1) { CWRITE(sc, queue_msix_vector, vec); } else { bus_space_write_2(sc->sc_iot, sc->sc_ioh, VIRTIO_MSI_QUEUE_VECTOR, vec); } } } int virtio_pci_get_status(struct virtio_softc *vsc) { struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc; if (sc->sc_sc.sc_version_1) return CREAD(sc, device_status); else return bus_space_read_1(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_DEVICE_STATUS); } void virtio_pci_set_status(struct virtio_softc *vsc, int status) { struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc; int old = 0; if (sc->sc_sc.sc_version_1) { if (status == 0) { CWRITE(sc, device_status, 0); while (CREAD(sc, device_status) != 0) { CPU_BUSY_CYCLE(); } } else { old = CREAD(sc, device_status); CWRITE(sc, device_status, status|old); } } else { if (status == 0) { bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_DEVICE_STATUS, status|old); while (bus_space_read_1(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_DEVICE_STATUS) != 0) { CPU_BUSY_CYCLE(); } } else { old = bus_space_read_1(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_DEVICE_STATUS); bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_DEVICE_STATUS, status|old); } } } int virtio_pci_match(struct device *parent, void *match, void *aux) { struct pci_attach_args *pa; pa = (struct pci_attach_args *)aux; if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_OPENBSD && PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_OPENBSD_CONTROL) return 1; if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_QUMRANET) return 0; /* virtio 0.9 */ if (PCI_PRODUCT(pa->pa_id) >= 0x1000 && PCI_PRODUCT(pa->pa_id) <= 0x103f && PCI_REVISION(pa->pa_class) == 0) return 1; /* virtio 1.0 */ if (PCI_PRODUCT(pa->pa_id) >= 0x1040 && PCI_PRODUCT(pa->pa_id) <= 0x107f && PCI_REVISION(pa->pa_class) == 1) return 1; return 0; } #if VIRTIO_DEBUG void virtio_pci_dump_caps(struct virtio_pci_softc *sc) { pci_chipset_tag_t pc = sc->sc_pc; pcitag_t tag = sc->sc_ptag; int offset; union { pcireg_t reg[4]; struct virtio_pci_cap vcap; } v; if (!pci_get_capability(pc, tag, PCI_CAP_VENDSPEC, &offset, &v.reg[0])) return; printf("\n"); do { for (int i = 0; i < 4; i++) v.reg[i] = pci_conf_read(pc, tag, offset + i * 4); printf("%s: cfgoff %#x len %#x type %#x bar %#x: off %#x len %#x\n", __func__, offset, v.vcap.cap_len, v.vcap.cfg_type, v.vcap.bar, v.vcap.offset, v.vcap.length); offset = v.vcap.cap_next; } while (offset != 0); } #endif int virtio_pci_find_cap(struct virtio_pci_softc *sc, int cfg_type, void *buf, int buflen) { pci_chipset_tag_t pc = sc->sc_pc; pcitag_t tag = sc->sc_ptag; unsigned int offset, i, len; union { pcireg_t reg[8]; struct virtio_pci_cap vcap; } *v = buf; if (buflen < sizeof(struct virtio_pci_cap)) return ERANGE; if (!pci_get_capability(pc, tag, PCI_CAP_VENDSPEC, &offset, &v->reg[0])) return ENOENT; do { for (i = 0; i < 4; i++) v->reg[i] = pci_conf_read(pc, tag, offset + i * 4); if (v->vcap.cfg_type == cfg_type) break; offset = v->vcap.cap_next; } while (offset != 0); if (offset == 0) return ENOENT; if (v->vcap.cap_len > sizeof(struct virtio_pci_cap)) { len = roundup(v->vcap.cap_len, sizeof(pcireg_t)); if (len > buflen) { printf("%s: cap too large\n", __func__); return ERANGE; } for (i = 4; i < len / sizeof(pcireg_t); i++) v->reg[i] = pci_conf_read(pc, tag, offset + i * 4); } return 0; } #define NMAPREG ((PCI_MAPREG_END - PCI_MAPREG_START) / \ sizeof(pcireg_t)) int virtio_pci_attach_10(struct virtio_pci_softc *sc, struct pci_attach_args *pa) { struct virtio_pci_cap common, isr, device; struct virtio_pci_notify_cap notify; int have_device_cfg = 0; bus_size_t bars[NMAPREG] = { 0 }; int bars_idx[NMAPREG] = { 0 }; struct virtio_pci_cap *caps[] = { &common, &isr, &device, &notify.cap }; int i, j = 0, ret = 0; if (virtio_pci_find_cap(sc, VIRTIO_PCI_CAP_COMMON_CFG, &common, sizeof(common)) != 0) return ENODEV; if (virtio_pci_find_cap(sc, VIRTIO_PCI_CAP_NOTIFY_CFG, &notify, sizeof(notify)) != 0) return ENODEV; if (virtio_pci_find_cap(sc, VIRTIO_PCI_CAP_ISR_CFG, &isr, sizeof(isr)) != 0) return ENODEV; if (virtio_pci_find_cap(sc, VIRTIO_PCI_CAP_DEVICE_CFG, &device, sizeof(device)) != 0) memset(&device, 0, sizeof(device)); else have_device_cfg = 1; /* * XXX Maybe there are devices that offer the pci caps but not the * XXX VERSION_1 feature bit? Then we should check the feature bit * XXX here and fall back to 0.9 out if not present. */ /* Figure out which bars we need to map */ for (i = 0; i < nitems(caps); i++) { int bar = caps[i]->bar; bus_size_t len = caps[i]->offset + caps[i]->length; if (caps[i]->length == 0) continue; if (bars[bar] < len) bars[bar] = len; } for (i = 0; i < nitems(bars); i++) { int reg; pcireg_t type; if (bars[i] == 0) continue; reg = PCI_MAPREG_START + i * 4; type = pci_mapreg_type(sc->sc_pc, sc->sc_ptag, reg); if (pci_mapreg_map(pa, reg, type, 0, &sc->sc_bars_iot[j], &sc->sc_bars_ioh[j], NULL, &sc->sc_bars_iosize[j], bars[i])) { printf("%s: can't map bar %u \n", sc->sc_sc.sc_dev.dv_xname, i); ret = EIO; goto err; } bars_idx[i] = j; j++; } i = bars_idx[notify.cap.bar]; if (bus_space_subregion(sc->sc_bars_iot[i], sc->sc_bars_ioh[i], notify.cap.offset, notify.cap.length, &sc->sc_notify_ioh) != 0) { printf("%s: can't map notify i/o space\n", sc->sc_sc.sc_dev.dv_xname); ret = EIO; goto err; } sc->sc_notify_iosize = notify.cap.length; sc->sc_notify_iot = sc->sc_bars_iot[i]; sc->sc_notify_off_multiplier = notify.notify_off_multiplier; if (have_device_cfg) { i = bars_idx[device.bar]; if (bus_space_subregion(sc->sc_bars_iot[i], sc->sc_bars_ioh[i], device.offset, device.length, &sc->sc_devcfg_ioh) != 0) { printf("%s: can't map devcfg i/o space\n", sc->sc_sc.sc_dev.dv_xname); ret = EIO; goto err; } sc->sc_devcfg_iosize = device.length; sc->sc_devcfg_iot = sc->sc_bars_iot[i]; } i = bars_idx[isr.bar]; if (bus_space_subregion(sc->sc_bars_iot[i], sc->sc_bars_ioh[i], isr.offset, isr.length, &sc->sc_isr_ioh) != 0) { printf("%s: can't map isr i/o space\n", sc->sc_sc.sc_dev.dv_xname); ret = EIO; goto err; } sc->sc_isr_iosize = isr.length; sc->sc_isr_iot = sc->sc_bars_iot[i]; i = bars_idx[common.bar]; if (bus_space_subregion(sc->sc_bars_iot[i], sc->sc_bars_ioh[i], common.offset, common.length, &sc->sc_ioh) != 0) { printf("%s: can't map common i/o space\n", sc->sc_sc.sc_dev.dv_xname); ret = EIO; goto err; } sc->sc_iosize = common.length; sc->sc_iot = sc->sc_bars_iot[i]; sc->sc_sc.sc_version_1 = 1; return 0; err: /* there is no pci_mapreg_unmap() */ return ret; } int virtio_pci_attach_09(struct virtio_pci_softc *sc, struct pci_attach_args *pa) { struct virtio_softc *vsc = &sc->sc_sc; pcireg_t type; type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_MAPREG_START); if (pci_mapreg_map(pa, PCI_MAPREG_START, type, 0, &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_iosize, 0)) { printf("%s: can't map i/o space\n", vsc->sc_dev.dv_xname); return EIO; } if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_NOTIFY, 2, &sc->sc_notify_ioh) != 0) { printf("%s: can't map notify i/o space\n", vsc->sc_dev.dv_xname); return EIO; } sc->sc_notify_iosize = 2; sc->sc_notify_iot = sc->sc_iot; if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_ISR_STATUS, 1, &sc->sc_isr_ioh) != 0) { printf("%s: can't map isr i/o space\n", vsc->sc_dev.dv_xname); return EIO; } sc->sc_isr_iosize = 1; sc->sc_isr_iot = sc->sc_iot; return 0; } void virtio_pci_attach(struct device *parent, struct device *self, void *aux) { struct virtio_pci_softc *sc = (struct virtio_pci_softc *)self; struct virtio_softc *vsc = &sc->sc_sc; struct pci_attach_args *pa = (struct pci_attach_args *)aux; pci_chipset_tag_t pc = pa->pa_pc; pcitag_t tag = pa->pa_tag; int revision, ret = ENODEV; pcireg_t id; char const *intrstr; pci_intr_handle_t ih; revision = PCI_REVISION(pa->pa_class); switch (revision) { case 0: /* subsystem ID shows what I am */ id = PCI_PRODUCT(pci_conf_read(pc, tag, PCI_SUBSYS_ID_REG)); break; case 1: id = PCI_PRODUCT(pa->pa_id) - 0x1040; break; default: printf("unknown revision 0x%02x; giving up\n", revision); return; } sc->sc_pc = pc; sc->sc_ptag = pa->pa_tag; vsc->sc_dmat = pa->pa_dmat; #if defined(__i386__) || defined(__amd64__) /* * For virtio, ignore normal MSI black/white-listing depending on the * PCI bridge but enable it unconditionally. */ pa->pa_flags |= PCI_FLAGS_MSI_ENABLED; #endif #if VIRTIO_DEBUG virtio_pci_dump_caps(sc); #endif vsc->sc_ops = &virtio_pci_ops; if ((vsc->sc_dev.dv_cfdata->cf_flags & VIRTIO_CF_NO_VERSION_1) == 0 && (revision == 1 || (vsc->sc_dev.dv_cfdata->cf_flags & VIRTIO_CF_PREFER_VERSION_1))) { ret = virtio_pci_attach_10(sc, pa); } if (ret != 0 && revision == 0) { /* revision 0 means 0.9 only or both 0.9 and 1.0 */ ret = virtio_pci_attach_09(sc, pa); } if (ret != 0) { printf(": Cannot attach (%d)\n", ret); return; } sc->sc_devcfg_offset = VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI; sc->sc_irq_type = IRQ_NO_MSIX; if (virtio_pci_adjust_config_region(sc) != 0) return; virtio_device_reset(vsc); virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_ACK); virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER); printf("\n"); vsc->sc_childdevid = id; vsc->sc_child = NULL; config_found(self, sc, NULL); if (vsc->sc_child == NULL) { printf("%s: no matching child driver; not configured\n", vsc->sc_dev.dv_xname); goto fail_1; } if (vsc->sc_child == VIRTIO_CHILD_ERROR) { printf("%s: virtio configuration failed\n", vsc->sc_dev.dv_xname); goto fail_1; } if (virtio_pci_setup_msix(sc, pa, 0) == 0) { sc->sc_irq_type = IRQ_MSIX_PER_VQ; intrstr = "msix per-VQ"; } else if (virtio_pci_setup_msix(sc, pa, 1) == 0) { sc->sc_irq_type = IRQ_MSIX_SHARED; intrstr = "msix shared"; } else { int (*ih_func)(void *) = virtio_pci_legacy_intr; if (pci_intr_map_msi(pa, &ih) != 0 && pci_intr_map(pa, &ih) != 0) { printf("%s: couldn't map interrupt\n", vsc->sc_dev.dv_xname); goto fail_2; } intrstr = pci_intr_string(pc, ih); /* * We always set the IPL_MPSAFE flag in order to do the relatively * expensive ISR read without lock, and then grab the kernel lock in * the interrupt handler. */ if (vsc->sc_ipl & IPL_MPSAFE) ih_func = virtio_pci_legacy_intr_mpsafe; sc->sc_ih[0] = pci_intr_establish(pc, ih, vsc->sc_ipl | IPL_MPSAFE, ih_func, sc, vsc->sc_dev.dv_xname); if (sc->sc_ih[0] == NULL) { printf("%s: couldn't establish interrupt", vsc->sc_dev.dv_xname); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); goto fail_2; } } printf("%s: %s\n", vsc->sc_dev.dv_xname, intrstr); return; fail_2: config_detach(vsc->sc_child, 0); fail_1: /* no pci_mapreg_unmap() or pci_intr_unmap() */ virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_FAILED); } int virtio_pci_detach(struct device *self, int flags) { struct virtio_pci_softc *sc = (struct virtio_pci_softc *)self; struct virtio_softc *vsc = &sc->sc_sc; int r; if (vsc->sc_child != 0 && vsc->sc_child != VIRTIO_CHILD_ERROR) { r = config_detach(vsc->sc_child, flags); if (r) return r; } KASSERT(vsc->sc_child == 0 || vsc->sc_child == VIRTIO_CHILD_ERROR); KASSERT(vsc->sc_vqs == 0); virtio_pci_free_irqs(sc); if (sc->sc_iosize) bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_iosize); sc->sc_iosize = 0; return 0; } int virtio_pci_adjust_config_region(struct virtio_pci_softc *sc) { if (sc->sc_sc.sc_version_1) return 0; sc->sc_devcfg_iosize = sc->sc_iosize - sc->sc_devcfg_offset; sc->sc_devcfg_iot = sc->sc_iot; if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, sc->sc_devcfg_offset, sc->sc_devcfg_iosize, &sc->sc_devcfg_ioh) != 0) { printf("%s: can't map config i/o space\n", sc->sc_sc.sc_dev.dv_xname); return 1; } return 0; } /* * Feature negotiation. * Prints available / negotiated features if guest_feature_names != NULL and * VIRTIO_DEBUG is 1 */ int virtio_pci_negotiate_features(struct virtio_softc *vsc, const struct virtio_feature_name *guest_feature_names) { struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc; uint64_t host, negotiated; vsc->sc_active_features = 0; /* * We enable indirect descriptors by default. They can be switched * off by setting bit 1 in the driver flags, see config(8) */ if (!(vsc->sc_dev.dv_cfdata->cf_flags & VIRTIO_CF_NO_INDIRECT) && !(vsc->sc_child->dv_cfdata->cf_flags & VIRTIO_CF_NO_INDIRECT)) { vsc->sc_driver_features |= VIRTIO_F_RING_INDIRECT_DESC; } else if (guest_feature_names != NULL) { printf(" RingIndirectDesc disabled by UKC"); } /* * The driver must add VIRTIO_F_RING_EVENT_IDX if it supports it. * If it did, check if it is disabled by bit 2 in the driver flags. */ if ((vsc->sc_driver_features & VIRTIO_F_RING_EVENT_IDX) && ((vsc->sc_dev.dv_cfdata->cf_flags & VIRTIO_CF_NO_EVENT_IDX) || (vsc->sc_child->dv_cfdata->cf_flags & VIRTIO_CF_NO_EVENT_IDX))) { if (guest_feature_names != NULL) printf(" RingEventIdx disabled by UKC"); vsc->sc_driver_features &= ~VIRTIO_F_RING_EVENT_IDX; } if (vsc->sc_version_1) { return virtio_pci_negotiate_features_10(vsc, guest_feature_names); } /* virtio 0.9 only */ host = bus_space_read_4(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_DEVICE_FEATURES); negotiated = host & vsc->sc_driver_features; #if VIRTIO_DEBUG if (guest_feature_names) virtio_log_features(host, negotiated, guest_feature_names); #endif bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_GUEST_FEATURES, negotiated); vsc->sc_active_features = negotiated; if (negotiated & VIRTIO_F_RING_INDIRECT_DESC) vsc->sc_indirect = 1; else vsc->sc_indirect = 0; return 0; } int virtio_pci_negotiate_features_10(struct virtio_softc *vsc, const struct virtio_feature_name *guest_feature_names) { struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc; uint64_t host, negotiated; vsc->sc_driver_features |= VIRTIO_F_VERSION_1; /* notify on empty is 0.9 only */ vsc->sc_driver_features &= ~VIRTIO_F_NOTIFY_ON_EMPTY; CWRITE(sc, device_feature_select, 0); host = CREAD(sc, device_feature); CWRITE(sc, device_feature_select, 1); host |= (uint64_t)CREAD(sc, device_feature) << 32; negotiated = host & vsc->sc_driver_features; #if VIRTIO_DEBUG if (guest_feature_names) virtio_log_features(host, negotiated, guest_feature_names); #endif CWRITE(sc, driver_feature_select, 0); CWRITE(sc, driver_feature, negotiated & 0xffffffff); CWRITE(sc, driver_feature_select, 1); CWRITE(sc, driver_feature, negotiated >> 32); virtio_pci_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_FEATURES_OK); if ((CREAD(sc, device_status) & VIRTIO_CONFIG_DEVICE_STATUS_FEATURES_OK) == 0) { printf("%s: Feature negotiation failed\n", vsc->sc_dev.dv_xname); CWRITE(sc, device_status, VIRTIO_CONFIG_DEVICE_STATUS_FAILED); return ENXIO; } vsc->sc_active_features = negotiated; if (negotiated & VIRTIO_F_RING_INDIRECT_DESC) vsc->sc_indirect = 1; else vsc->sc_indirect = 0; if ((negotiated & VIRTIO_F_VERSION_1) == 0) { #if VIRTIO_DEBUG printf("%s: Host rejected Version_1\n", __func__); #endif CWRITE(sc, device_status, VIRTIO_CONFIG_DEVICE_STATUS_FAILED); return EINVAL; } return 0; } /* * Device configuration registers. */ uint8_t virtio_pci_read_device_config_1(struct virtio_softc *vsc, int index) { struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc; return bus_space_read_1(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, index); } uint16_t virtio_pci_read_device_config_2(struct virtio_softc *vsc, int index) { struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc; return bus_space_read_2(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, index); } uint32_t virtio_pci_read_device_config_4(struct virtio_softc *vsc, int index) { struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc; return bus_space_read_4(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, index); } uint64_t virtio_pci_read_device_config_8(struct virtio_softc *vsc, int index) { struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc; uint64_t r; r = bus_space_read_4(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, index + sizeof(uint32_t)); r <<= 32; r += bus_space_read_4(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, index); return r; } void virtio_pci_write_device_config_1(struct virtio_softc *vsc, int index, uint8_t value) { struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc; bus_space_write_1(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, index, value); } void virtio_pci_write_device_config_2(struct virtio_softc *vsc, int index, uint16_t value) { struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc; bus_space_write_2(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, index, value); } void virtio_pci_write_device_config_4(struct virtio_softc *vsc, int index, uint32_t value) { struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc; bus_space_write_4(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, index, value); } void virtio_pci_write_device_config_8(struct virtio_softc *vsc, int index, uint64_t value) { struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc; bus_space_write_4(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, index, value & 0xffffffff); bus_space_write_4(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, index + sizeof(uint32_t), value >> 32); } int virtio_pci_msix_establish(struct virtio_pci_softc *sc, struct pci_attach_args *pa, int idx, int (*handler)(void *), void *ih_arg) { struct virtio_softc *vsc = &sc->sc_sc; pci_intr_handle_t ih; if (pci_intr_map_msix(pa, idx, &ih) != 0) { #if VIRTIO_DEBUG printf("%s[%d]: pci_intr_map_msix failed\n", vsc->sc_dev.dv_xname, idx); #endif return 1; } sc->sc_ih[idx] = pci_intr_establish(sc->sc_pc, ih, vsc->sc_ipl, handler, ih_arg, vsc->sc_dev.dv_xname); if (sc->sc_ih[idx] == NULL) { printf("%s[%d]: couldn't establish msix interrupt\n", vsc->sc_dev.dv_xname, idx); return 1; } return 0; } void virtio_pci_set_msix_queue_vector(struct virtio_pci_softc *sc, uint32_t idx, uint16_t vector) { if (sc->sc_sc.sc_version_1) { CWRITE(sc, queue_select, idx); CWRITE(sc, queue_msix_vector, vector); } else { bus_space_write_2(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_SELECT, idx); bus_space_write_2(sc->sc_iot, sc->sc_ioh, VIRTIO_MSI_QUEUE_VECTOR, vector); } } void virtio_pci_set_msix_config_vector(struct virtio_pci_softc *sc, uint16_t vector) { if (sc->sc_sc.sc_version_1) { CWRITE(sc, config_msix_vector, vector); } else { bus_space_write_2(sc->sc_iot, sc->sc_ioh, VIRTIO_MSI_CONFIG_VECTOR, vector); } } void virtio_pci_free_irqs(struct virtio_pci_softc *sc) { struct virtio_softc *vsc = &sc->sc_sc; int i; if (sc->sc_devcfg_offset == VIRTIO_CONFIG_DEVICE_CONFIG_MSI) { for (i = 0; i < vsc->sc_nvqs; i++) { virtio_pci_set_msix_queue_vector(sc, i, VIRTIO_MSI_NO_VECTOR); } } for (i = 0; i < MAX_MSIX_VECS; i++) { if (sc->sc_ih[i]) { pci_intr_disestablish(sc->sc_pc, sc->sc_ih[i]); sc->sc_ih[i] = NULL; } } sc->sc_devcfg_offset = VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI; virtio_pci_adjust_config_region(sc); } int virtio_pci_setup_msix(struct virtio_pci_softc *sc, struct pci_attach_args *pa, int shared) { struct virtio_softc *vsc = &sc->sc_sc; int i; /* Shared needs config + queue */ if (shared && pci_intr_msix_count(pa) < 1 + 1) return 1; /* Per VQ needs config + N * queue */ if (!shared && pci_intr_msix_count(pa) < 1 + vsc->sc_nvqs) return 1; if (virtio_pci_msix_establish(sc, pa, 0, virtio_pci_config_intr, vsc)) return 1; sc->sc_devcfg_offset = VIRTIO_CONFIG_DEVICE_CONFIG_MSI; virtio_pci_adjust_config_region(sc); virtio_pci_set_msix_config_vector(sc, 0); if (shared) { if (virtio_pci_msix_establish(sc, pa, 1, virtio_pci_shared_queue_intr, vsc)) { goto fail; } for (i = 0; i < vsc->sc_nvqs; i++) virtio_pci_set_msix_queue_vector(sc, i, 1); } else { for (i = 0; i < vsc->sc_nvqs; i++) { if (virtio_pci_msix_establish(sc, pa, i + 1, virtio_pci_queue_intr, &vsc->sc_vqs[i])) { goto fail; } virtio_pci_set_msix_queue_vector(sc, i, i + 1); } } return 0; fail: virtio_pci_free_irqs(sc); return 1; } /* * Interrupt handler. */ /* * Only used without MSI-X */ int virtio_pci_legacy_intr(void *arg) { struct virtio_pci_softc *sc = arg; struct virtio_softc *vsc = &sc->sc_sc; int isr, r = 0; /* check and ack the interrupt */ isr = bus_space_read_1(sc->sc_isr_iot, sc->sc_isr_ioh, 0); if (isr == 0) return 0; KERNEL_LOCK(); if ((isr & VIRTIO_CONFIG_ISR_CONFIG_CHANGE) && (vsc->sc_config_change != NULL)) { r = (vsc->sc_config_change)(vsc); } r |= virtio_check_vqs(vsc); KERNEL_UNLOCK(); return r; } int virtio_pci_legacy_intr_mpsafe(void *arg) { struct virtio_pci_softc *sc = arg; struct virtio_softc *vsc = &sc->sc_sc; int isr, r = 0; /* check and ack the interrupt */ isr = bus_space_read_1(sc->sc_isr_iot, sc->sc_isr_ioh, 0); if (isr == 0) return 0; if ((isr & VIRTIO_CONFIG_ISR_CONFIG_CHANGE) && (vsc->sc_config_change != NULL)) { r = (vsc->sc_config_change)(vsc); } r |= virtio_check_vqs(vsc); return r; } /* * Only used with MSI-X */ int virtio_pci_config_intr(void *arg) { struct virtio_softc *vsc = arg; if (vsc->sc_config_change != NULL) return vsc->sc_config_change(vsc); return 0; } /* * Only used with MSI-X */ int virtio_pci_queue_intr(void *arg) { struct virtqueue *vq = arg; struct virtio_softc *vsc = vq->vq_owner; return virtio_check_vq(vsc, vq); } int virtio_pci_shared_queue_intr(void *arg) { struct virtio_softc *vsc = arg; return virtio_check_vqs(vsc); } /* * Interrupt handler to be used when polling. * We cannot use isr here because it is not defined in MSI-X mode. */ int virtio_pci_poll_intr(void *arg) { struct virtio_pci_softc *sc = arg; struct virtio_softc *vsc = &sc->sc_sc; int r = 0; if (vsc->sc_config_change != NULL) r = (vsc->sc_config_change)(vsc); r |= virtio_check_vqs(vsc); return r; } void virtio_pci_kick(struct virtio_softc *vsc, uint16_t idx) { struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc; unsigned offset = 0; if (vsc->sc_version_1) { offset = vsc->sc_vqs[idx].vq_notify_off * sc->sc_notify_off_multiplier; } bus_space_write_2(sc->sc_notify_iot, sc->sc_notify_ioh, offset, idx); }
50 50 21 19 11 30 30 30 7 15 10 15 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 /* $OpenBSD: mpls_output.c,v 1.29 2023/05/13 13:35:18 bluhm Exp $ */ /* * Copyright (c) 2008 Claudio Jeker <claudio@openbsd.org> * Copyright (c) 2008 Michele Marchetto <michele@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/mbuf.h> #include <sys/systm.h> #include <sys/socket.h> #include <net/if.h> #include <net/if_var.h> #include <net/route.h> #include <netmpls/mpls.h> #include <netinet/in.h> #include <netinet/ip.h> #ifdef INET6 #include <netinet/ip6.h> #endif #ifdef MPLS_DEBUG #define MPLS_LABEL_GET(l) ((ntohl((l) & MPLS_LABEL_MASK)) >> MPLS_LABEL_OFFSET) #endif u_int8_t mpls_getttl(struct mbuf *, sa_family_t); int mpls_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) { struct sockaddr_mpls *smpls; struct sockaddr_mpls sa_mpls; struct shim_hdr *shim; struct rt_mpls *rt_mpls; int error; u_int8_t ttl; if (rt == NULL || (dst->sa_family != AF_INET && dst->sa_family != AF_INET6 && dst->sa_family != AF_MPLS)) { if (!ISSET(ifp->if_xflags, IFXF_MPLS)) return (ifp->if_output(ifp, m, dst, rt)); else return (ifp->if_ll_output(ifp, m, dst, rt)); } /* need to calculate checksums now if necessary */ if (m->m_pkthdr.csum_flags & M_IPV4_CSUM_OUT) in_hdr_cksum_out(m, NULL); in_proto_cksum_out(m, NULL); /* initialize sockaddr_mpls */ bzero(&sa_mpls, sizeof(sa_mpls)); smpls = &sa_mpls; smpls->smpls_family = AF_MPLS; smpls->smpls_len = sizeof(*smpls); ttl = mpls_getttl(m, dst->sa_family); rt_mpls = (struct rt_mpls *)rt->rt_llinfo; if (rt_mpls == NULL || (rt->rt_flags & RTF_MPLS) == 0) { /* no MPLS information for this entry */ if (!ISSET(ifp->if_xflags, IFXF_MPLS)) { #ifdef MPLS_DEBUG printf("MPLS_DEBUG: interface not mpls enabled\n"); #endif error = ENETUNREACH; goto bad; } return (ifp->if_ll_output(ifp, m, dst, rt)); } /* to be honest here only the push operation makes sense */ switch (rt_mpls->mpls_operation) { case MPLS_OP_PUSH: m = mpls_shim_push(m, rt_mpls); break; case MPLS_OP_POP: m = mpls_shim_pop(m); break; case MPLS_OP_SWAP: m = mpls_shim_swap(m, rt_mpls); break; default: error = EINVAL; goto bad; } if (m == NULL) { error = ENOBUFS; goto bad; } /* refetch label */ shim = mtod(m, struct shim_hdr *); /* mark first label with BOS flag */ if (dst->sa_family != AF_MPLS) shim->shim_label |= MPLS_BOS_MASK; /* write back TTL */ shim->shim_label &= ~MPLS_TTL_MASK; shim->shim_label |= htonl(ttl); #ifdef MPLS_DEBUG printf("MPLS: sending on %s outshim %x outlabel %d\n", ifp->if_xname, ntohl(shim->shim_label), MPLS_LABEL_GET(rt_mpls->mpls_label)); #endif /* Output iface is not MPLS-enabled */ if (!ISSET(ifp->if_xflags, IFXF_MPLS)) { #ifdef MPLS_DEBUG printf("MPLS_DEBUG: interface not mpls enabled\n"); #endif error = ENETUNREACH; goto bad; } /* reset broadcast and multicast flags, this is a P2P tunnel */ m->m_flags &= ~(M_BCAST | M_MCAST); smpls->smpls_label = shim->shim_label & MPLS_LABEL_MASK; error = ifp->if_ll_output(ifp, m, smplstosa(smpls), rt); return (error); bad: m_freem(m); return (error); } u_int8_t mpls_getttl(struct mbuf *m, sa_family_t af) { struct mbuf *n; int loc, off; u_int8_t ttl = mpls_defttl; /* If the AF is MPLS then inherit the TTL from the present label. */ if (af == AF_MPLS) loc = 3; else { switch (*mtod(m, uint8_t *) >> 4) { case 4: if (!mpls_mapttl_ip) return (ttl); loc = offsetof(struct ip, ip_ttl); break; #ifdef INET6 case 6: if (!mpls_mapttl_ip6) return (ttl); loc = offsetof(struct ip6_hdr, ip6_hlim); break; #endif default: return (ttl); } } n = m_getptr(m, loc, &off); if (n == NULL) return (ttl); ttl = *(mtod(n, uint8_t *) + off); return (ttl); }
26 23 2 26 3 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 /* $OpenBSD: tcp_debug.c,v 1.32 2024/04/10 22:24:07 bluhm Exp $ */ /* $NetBSD: tcp_debug.c,v 1.10 1996/02/13 23:43:36 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 * * NRL grants permission for redistribution and use in source and binary * forms, with or without modification, of the software and documentation * created at NRL provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgements: * This product includes software developed by the University of * California, Berkeley and its contributors. * This product includes software developed at the Information * Technology Division, US Naval Research Laboratory. * 4. Neither the name of the NRL nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the US Naval * Research Laboratory (NRL). */ #ifdef TCPDEBUG /* load symbolic names */ #define PRUREQUESTS #define TCPSTATES #define TCPTIMERS #define TANAMES #endif #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/mutex.h> #include <sys/socket.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> #include <netinet/in_pcb.h> #include <netinet/ip_var.h> #include <netinet/tcp.h> #include <netinet/tcp_timer.h> #include <netinet/tcp_var.h> #include <netinet/tcp_debug.h> #include <netinet/tcp_fsm.h> #ifdef INET6 #include <netinet/ip6.h> #endif /* INET6 */ #ifdef TCPDEBUG #include <sys/protosw.h> #endif /* * Locks used to protect struct members in this file: * D TCP debug global mutex */ struct mutex tcp_debug_mtx = MUTEX_INITIALIZER(IPL_SOFTNET); #ifdef TCPDEBUG int tcpconsdebug = 0; #endif struct tcp_debug tcp_debug[TCP_NDEBUG]; /* [D] */ int tcp_debx; /* [D] */ /* * Tcp debug routines */ void tcp_trace(short act, short ostate, struct tcpcb *tp, struct tcpcb *otp, caddr_t headers, int req, int len) { #ifdef TCPDEBUG struct tcphdr *th; tcp_seq seq, ack; int flags; #endif int pf = PF_UNSPEC; struct tcp_debug *td; struct tcpiphdr *ti; struct tcpipv6hdr *ti6; mtx_enter(&tcp_debug_mtx); td = &tcp_debug[tcp_debx++]; ti = (struct tcpiphdr *)headers; ti6 = (struct tcpipv6hdr *)headers; if (tcp_debx == TCP_NDEBUG) tcp_debx = 0; td->td_time = iptime(); td->td_act = act; td->td_ostate = ostate; td->td_tcb = (caddr_t)otp; if (tp) { pf = tp->pf; td->td_cb = *tp; } else bzero((caddr_t)&td->td_cb, sizeof (*tp)); bzero(&td->td_ti6, sizeof(struct tcpipv6hdr)); bzero(&td->td_ti, sizeof(struct tcpiphdr)); if (headers) { /* The address family may be in tcpcb or ip header. */ if (pf == PF_UNSPEC) { switch (ti6->ti6_i.ip6_vfc & IPV6_VERSION_MASK) { #ifdef INET6 case IPV6_VERSION: pf = PF_INET6; break; #endif /* INET6 */ case IPVERSION: pf = PF_INET; break; } } switch (pf) { #ifdef INET6 case PF_INET6: #ifdef TCPDEBUG th = &ti6->ti6_t; #endif td->td_ti6 = *ti6; td->td_ti6.ti6_plen = len; break; #endif /* INET6 */ case PF_INET: #ifdef TCPDEBUG th = &ti->ti_t; #endif td->td_ti = *ti; td->td_ti.ti_len = len; break; default: headers = NULL; break; } } td->td_req = req; #ifdef TCPDEBUG if (tcpconsdebug == 0) goto done; if (otp) printf("%p %s:", otp, tcpstates[ostate]); else printf("???????? "); printf("%s ", tanames[act]); switch (act) { case TA_INPUT: case TA_OUTPUT: case TA_DROP: if (headers == NULL) break; seq = th->th_seq; ack = th->th_ack; if (act == TA_OUTPUT) { seq = ntohl(seq); ack = ntohl(ack); } if (len) printf("[%x..%x)", seq, seq+len); else printf("%x", seq); printf("@%x, urp=%x", ack, th->th_urp); flags = th->th_flags; if (flags) { char *cp = "<"; #define pf(f) { if (th->th_flags&TH_##f) { printf("%s%s", cp, #f); cp = ","; } } pf(SYN); pf(ACK); pf(FIN); pf(RST); pf(PUSH); pf(URG); printf(">"); } break; case TA_USER: printf("%s", prurequests[req]); break; case TA_TIMER: printf("%s", tcptimers[req]); break; } if (tp) printf(" -> %s", tcpstates[tp->t_state]); /* print out internal state of tp !?! */ printf("\n"); if (tp == NULL) goto done; printf("\trcv_(nxt,wnd,up) (%x,%lx,%x) snd_(una,nxt,max) (%x,%x,%x)\n", tp->rcv_nxt, tp->rcv_wnd, tp->rcv_up, tp->snd_una, tp->snd_nxt, tp->snd_max); printf("\tsnd_(wl1,wl2,wnd) (%x,%x,%lx)\n", tp->snd_wl1, tp->snd_wl2, tp->snd_wnd); done: #endif /* TCPDEBUG */ mtx_leave(&tcp_debug_mtx); }
4 11 7 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 /* $OpenBSD: exec_elf.c,v 1.186 2024/04/02 08:39:16 deraadt Exp $ */ /* * Copyright (c) 1996 Per Fogelstrom * All rights reserved. * * Copyright (c) 1994 Christos Zoulas * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* * Copyright (c) 2001 Wasabi Systems, Inc. * All rights reserved. * * Written by Jason R. Thorpe for Wasabi Systems, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed for the NetBSD Project by * Wasabi Systems, Inc. * 4. The name of Wasabi Systems, Inc. may not be used to endorse * or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/malloc.h> #include <sys/pool.h> #include <sys/mount.h> #include <sys/namei.h> #include <sys/vnode.h> #include <sys/core.h> #include <sys/exec.h> #include <sys/exec_elf.h> #include <sys/fcntl.h> #include <sys/ptrace.h> #include <sys/signalvar.h> #include <sys/pledge.h> #include <sys/syscall.h> #include <sys/mman.h> #include <uvm/uvm_extern.h> #include <machine/reg.h> #include <machine/exec.h> int elf_load_file(struct proc *, char *, struct exec_package *, struct elf_args *); int elf_check_header(Elf_Ehdr *); int elf_read_from(struct proc *, struct vnode *, u_long, void *, int); void elf_load_psection(struct exec_vmcmd_set *, struct vnode *, Elf_Phdr *, Elf_Addr *, Elf_Addr *, int *, int); int elf_os_pt_note_name(Elf_Note *); int elf_os_pt_note(struct proc *, struct exec_package *, Elf_Ehdr *, int *); int elf_read_pintable(struct proc *p, struct vnode *vp, Elf_Phdr *pp, u_int **pinp, int is_ldso, size_t len); /* round up and down to page boundaries. */ #define ELF_ROUND(a, b) (((a) + (b) - 1) & ~((b) - 1)) #define ELF_TRUNC(a, b) ((a) & ~((b) - 1)) /* * We limit the number of program headers to 32, this should * be a reasonable limit for ELF, the most we have seen so far is 12 */ #define ELF_MAX_VALID_PHDR 32 #define ELF_NOTE_NAME_OPENBSD 0x01 struct elf_note_name { char *name; int id; } elf_note_names[] = { { "OpenBSD", ELF_NOTE_NAME_OPENBSD }, }; #define ELFROUNDSIZE sizeof(Elf_Word) #define elfround(x) roundup((x), ELFROUNDSIZE) /* * Check header for validity; return 0 for ok, ENOEXEC if error */ int elf_check_header(Elf_Ehdr *ehdr) { /* * We need to check magic, class size, endianness, and version before * we look at the rest of the Elf_Ehdr structure. These few elements * are represented in a machine independent fashion. */ if (!IS_ELF(*ehdr) || ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || ehdr->e_ident[EI_DATA] != ELF_TARG_DATA || ehdr->e_ident[EI_VERSION] != ELF_TARG_VER) return (ENOEXEC); /* Now check the machine dependent header */ if (ehdr->e_machine != ELF_TARG_MACH || ehdr->e_version != ELF_TARG_VER) return (ENOEXEC); /* Don't allow an insane amount of sections. */ if (ehdr->e_phnum > ELF_MAX_VALID_PHDR) return (ENOEXEC); return (0); } /* * Load a psection at the appropriate address */ void elf_load_psection(struct exec_vmcmd_set *vcset, struct vnode *vp, Elf_Phdr *ph, Elf_Addr *addr, Elf_Addr *size, int *prot, int flags) { u_long msize, lsize, psize, rm, rf; long diff, offset, bdiff; Elf_Addr base; /* * If the user specified an address, then we load there. */ if (*addr != ELF_NO_ADDR) { if (ph->p_align > 1) { *addr = ELF_TRUNC(*addr, ph->p_align); diff = ph->p_vaddr - ELF_TRUNC(ph->p_vaddr, ph->p_align); /* page align vaddr */ base = *addr + trunc_page(ph->p_vaddr) - ELF_TRUNC(ph->p_vaddr, ph->p_align); } else { diff = 0; base = *addr + trunc_page(ph->p_vaddr) - ph->p_vaddr; } } else { *addr = ph->p_vaddr; if (ph->p_align > 1) *addr = ELF_TRUNC(*addr, ph->p_align); base = trunc_page(ph->p_vaddr); diff = ph->p_vaddr - *addr; } bdiff = ph->p_vaddr - trunc_page(ph->p_vaddr); /* * Enforce W^X and map W|X segments without X permission * initially. The dynamic linker will make these read-only * and add back X permission after relocation processing. * Static executables with W|X segments will probably crash. */ *prot |= (ph->p_flags & PF_R) ? PROT_READ : 0; *prot |= (ph->p_flags & PF_W) ? PROT_WRITE : 0; if ((ph->p_flags & PF_W) == 0) *prot |= (ph->p_flags & PF_X) ? PROT_EXEC : 0; /* * Apply immutability as much as possible, but not text/rodata * segments of textrel binaries, or RELRO or PT_OPENBSD_MUTABLE * sections, or LOADS marked PF_OPENBSD_MUTABLE, or LOADS which * violate W^X. * Userland (meaning crt0 or ld.so) will repair those regions. */ if ((ph->p_flags & (PF_X | PF_W)) != (PF_X | PF_W) && ((ph->p_flags & PF_OPENBSD_MUTABLE) == 0)) flags |= VMCMD_IMMUTABLE; if ((flags & VMCMD_TEXTREL) && (ph->p_flags & PF_W) == 0) flags &= ~VMCMD_IMMUTABLE; msize = ph->p_memsz + diff; offset = ph->p_offset - bdiff; lsize = ph->p_filesz + bdiff; psize = round_page(lsize); /* * Because the pagedvn pager can't handle zero fill of the last * data page if it's not page aligned we map the last page readvn. */ if (ph->p_flags & PF_W) { psize = trunc_page(lsize); if (psize > 0) NEW_VMCMD2(vcset, vmcmd_map_pagedvn, psize, base, vp, offset, *prot, flags); if (psize != lsize) { NEW_VMCMD2(vcset, vmcmd_map_readvn, lsize - psize, base + psize, vp, offset + psize, *prot, flags); } } else { NEW_VMCMD2(vcset, vmcmd_map_pagedvn, psize, base, vp, offset, *prot, flags); } /* * Check if we need to extend the size of the segment */ rm = round_page(*addr + ph->p_memsz + diff); rf = round_page(*addr + ph->p_filesz + diff); if (rm != rf) { NEW_VMCMD2(vcset, vmcmd_map_zero, rm - rf, rf, NULLVP, 0, *prot, flags); } *size = msize; } /* * Read from vnode into buffer at offset. */ int elf_read_from(struct proc *p, struct vnode *vp, u_long off, void *buf, int size) { int error; size_t resid; if ((error = vn_rdwr(UIO_READ, vp, buf, size, off, UIO_SYSSPACE, 0, p->p_ucred, &resid, p)) != 0) return error; /* * See if we got all of it */ if (resid != 0) return (ENOEXEC); return (0); } /* * rebase the pin offsets inside a base,len window for the text segment only. */ void elf_adjustpins(vaddr_t *basep, size_t *lenp, u_int *pins, int npins, u_int offset) { int i; /* Adjust offsets, base, len */ for (i = 0; i < npins; i++) { if (pins[i] == -1 || pins[i] == 0) continue; pins[i] -= offset; } *basep += offset; *lenp -= offset; } int elf_read_pintable(struct proc *p, struct vnode *vp, Elf_Phdr *pp, u_int **pinp, int is_ldso, size_t len) { struct pinsyscalls { u_int offset; u_int sysno; } *syscalls = NULL; int i, nsyscalls = 0, npins = 0; u_int *pins = NULL; if (pp->p_filesz > SYS_MAXSYSCALL * 2 * sizeof(*syscalls) || pp->p_filesz % sizeof(*syscalls) != 0) goto bad; nsyscalls = pp->p_filesz / sizeof(*syscalls); syscalls = malloc(pp->p_filesz, M_PINSYSCALL, M_WAITOK); if (elf_read_from(p, vp, pp->p_offset, syscalls, pp->p_filesz) != 0) goto bad; /* Validate, and calculate pintable size */ for (i = 0; i < nsyscalls; i++) { if (syscalls[i].sysno <= 0 || syscalls[i].sysno >= SYS_MAXSYSCALL || syscalls[i].offset > len) goto bad; npins = MAX(npins, syscalls[i].sysno); } if (is_ldso) npins = MAX(npins, SYS_kbind); /* XXX see ld.so/loader.c */ npins++; /* Fill pintable: 0 = invalid, -1 = allowed, else offset from base */ pins = mallocarray(npins, sizeof(u_int), M_PINSYSCALL, M_WAITOK|M_ZERO); for (i = 0; i < nsyscalls; i++) { if (pins[syscalls[i].sysno]) pins[syscalls[i].sysno] = -1; /* duplicated */ else pins[syscalls[i].sysno] = syscalls[i].offset; } if (is_ldso) pins[SYS_kbind] = -1; /* XXX see ld.so/loader.c */ *pinp = pins; pins = NULL; bad: free(syscalls, M_PINSYSCALL, nsyscalls * sizeof(*syscalls)); free(pins, M_PINSYSCALL, npins * sizeof(u_int)); return npins; } /* * Load a file (interpreter/library) pointed to by path [stolen from * coff_load_shlib()]. Made slightly generic so it might be used externally. */ int elf_load_file(struct proc *p, char *path, struct exec_package *epp, struct elf_args *ap) { int error, i; struct nameidata nd; Elf_Ehdr eh; Elf_Phdr *ph = NULL, *syscall_ph = NULL; u_long phsize = 0; Elf_Addr addr; struct vnode *vp; Elf_Phdr *base_ph = NULL; struct interp_ld_sec { Elf_Addr vaddr; u_long memsz; } loadmap[ELF_MAX_VALID_PHDR]; int nload, idx = 0; Elf_Addr pos; int file_align; int loop; size_t randomizequota = ELF_RANDOMIZE_LIMIT; vaddr_t text_start = -1, text_end = 0; NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, p); nd.ni_pledge = PLEDGE_RPATH; nd.ni_unveil = UNVEIL_READ; if ((error = namei(&nd)) != 0) { return (error); } vp = nd.ni_vp; if (vp->v_type != VREG) { error = EACCES; goto bad; } if ((error = VOP_GETATTR(vp, epp->ep_vap, p->p_ucred, p)) != 0) goto bad; if (vp->v_mount->mnt_flag & MNT_NOEXEC) { error = EACCES; goto bad; } if ((error = VOP_ACCESS(vp, VREAD, p->p_ucred, p)) != 0) goto bad1; if ((error = elf_read_from(p, nd.ni_vp, 0, &eh, sizeof(eh))) != 0) goto bad1; if (elf_check_header(&eh) || eh.e_type != ET_DYN) { error = ENOEXEC; goto bad1; } ph = mallocarray(eh.e_phnum, sizeof(Elf_Phdr), M_TEMP, M_WAITOK); phsize = eh.e_phnum * sizeof(Elf_Phdr); if ((error = elf_read_from(p, nd.ni_vp, eh.e_phoff, ph, phsize)) != 0) goto bad1; for (i = 0; i < eh.e_phnum; i++) { if ((ph[i].p_align > 1) && !powerof2(ph[i].p_align)) { error = EINVAL; goto bad1; } if (ph[i].p_type == PT_LOAD) { if (ph[i].p_filesz > ph[i].p_memsz || ph[i].p_memsz == 0) { error = EINVAL; goto bad1; } loadmap[idx].vaddr = trunc_page(ph[i].p_vaddr); loadmap[idx].memsz = round_page (ph[i].p_vaddr + ph[i].p_memsz - loadmap[idx].vaddr); file_align = ph[i].p_align; idx++; } } nload = idx; /* * Load the interpreter where a non-fixed mmap(NULL, ...) * would (i.e. something safely out of the way). */ pos = uvm_map_hint(p->p_vmspace, PROT_EXEC, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS); pos = ELF_ROUND(pos, file_align); loop = 0; for (i = 0; i < nload;/**/) { vaddr_t addr; struct uvm_object *uobj; off_t uoff; size_t size; #ifdef this_needs_fixing if (i == 0) { uobj = &vp->v_uvm.u_obj; /* need to fix uoff */ } else { #endif uobj = NULL; uoff = 0; #ifdef this_needs_fixing } #endif addr = trunc_page(pos + loadmap[i].vaddr); size = round_page(addr + loadmap[i].memsz) - addr; /* CRAP - map_findspace does not avoid daddr+BRKSIZ */ if ((addr + size > (vaddr_t)p->p_vmspace->vm_daddr) && (addr < (vaddr_t)p->p_vmspace->vm_daddr + BRKSIZ)) addr = round_page((vaddr_t)p->p_vmspace->vm_daddr + BRKSIZ); if (uvm_map_mquery(&p->p_vmspace->vm_map, &addr, size, (i == 0 ? uoff : UVM_UNKNOWN_OFFSET), 0) != 0) { if (loop == 0) { loop = 1; i = 0; pos = 0; continue; } error = ENOMEM; goto bad1; } if (addr != pos + loadmap[i].vaddr) { /* base changed. */ pos = addr - trunc_page(loadmap[i].vaddr); pos = ELF_ROUND(pos,file_align); i = 0; continue; } i++; } /* * Load all the necessary sections */ for (i = 0; i < eh.e_phnum; i++) { Elf_Addr size = 0; int prot = 0; int flags; switch (ph[i].p_type) { case PT_LOAD: if (base_ph == NULL) { flags = VMCMD_BASE; addr = pos; base_ph = &ph[i]; } else { flags = VMCMD_RELATIVE; addr = ph[i].p_vaddr - base_ph->p_vaddr; } elf_load_psection(&epp->ep_vmcmds, nd.ni_vp, &ph[i], &addr, &size, &prot, flags); /* If entry is within this section it must be text */ if (eh.e_entry >= ph[i].p_vaddr && eh.e_entry < (ph[i].p_vaddr + size)) { /* LOAD containing e_entry may not be writable */ if (prot & PROT_WRITE) { error = ENOEXEC; goto bad1; } epp->ep_entry = addr + eh.e_entry - ELF_TRUNC(ph[i].p_vaddr,ph[i].p_align); if (flags == VMCMD_RELATIVE) epp->ep_entry += pos; ap->arg_interp = pos; } if (prot & PROT_EXEC) { if (addr < text_start) text_start = addr; if (addr+size >= text_end) text_end = addr + size; } addr += size; break; case PT_PHDR: case PT_NOTE: break; case PT_OPENBSD_RANDOMIZE: if (ph[i].p_memsz > randomizequota) { error = ENOMEM; goto bad1; } randomizequota -= ph[i].p_memsz; NEW_VMCMD(&epp->ep_vmcmds, vmcmd_randomize, ph[i].p_memsz, ph[i].p_vaddr + pos, NULLVP, 0, 0); break; case PT_DYNAMIC: #if defined (__mips__) /* DT_DEBUG is not ready on mips */ NEW_VMCMD(&epp->ep_vmcmds, vmcmd_mutable, ph[i].p_memsz, ph[i].p_vaddr + pos, NULLVP, 0, 0); #endif break; case PT_GNU_RELRO: case PT_OPENBSD_MUTABLE: NEW_VMCMD(&epp->ep_vmcmds, vmcmd_mutable, ph[i].p_memsz, ph[i].p_vaddr + pos, NULLVP, 0, 0); break; case PT_OPENBSD_SYSCALLS: syscall_ph = &ph[i]; break; default: break; } } if (syscall_ph) { struct process *pr = p->p_p; vaddr_t base = pos; size_t len = text_end; u_int *pins; int npins; npins = elf_read_pintable(p, nd.ni_vp, syscall_ph, &pins, 1, len); if (npins) { elf_adjustpins(&base, &len, pins, npins, text_start); pr->ps_pin.pn_start = base; pr->ps_pin.pn_end = base + len; pr->ps_pin.pn_pins = pins; pr->ps_pin.pn_npins = npins; pr->ps_flags |= PS_PIN; } } vn_marktext(nd.ni_vp); bad1: VOP_CLOSE(nd.ni_vp, FREAD, p->p_ucred, p); bad: free(ph, M_TEMP, phsize); vput(nd.ni_vp); return (error); } /* * Prepare an Elf binary's exec package * * First, set of the various offsets/lengths in the exec package. * * Then, mark the text image busy (so it can be demand paged) or error out if * this is not possible. Finally, set up vmcmds for the text, data, bss, and * stack segments. */ int exec_elf_makecmds(struct proc *p, struct exec_package *epp) { Elf_Ehdr *eh = epp->ep_hdr; Elf_Phdr *ph, *pp, *base_ph = NULL, *syscall_ph = NULL; Elf_Addr phdr = 0, exe_base = 0, exe_end = 0; int error, i, has_phdr = 0, names = 0, textrel = 0; char *interp = NULL; u_long phsize; size_t randomizequota = ELF_RANDOMIZE_LIMIT; if (epp->ep_hdrvalid < sizeof(Elf_Ehdr)) return (ENOEXEC); if (elf_check_header(eh) || (eh->e_type != ET_EXEC && eh->e_type != ET_DYN)) return (ENOEXEC); /* * check if vnode is in open for writing, because we want to demand- * page out of it. if it is, don't do it, for various reasons. */ if (epp->ep_vp->v_writecount != 0) { #ifdef DIAGNOSTIC if (epp->ep_vp->v_flag & VTEXT) panic("exec: a VTEXT vnode has writecount != 0"); #endif return (ETXTBSY); } /* * Allocate space to hold all the program headers, and read them * from the file */ ph = mallocarray(eh->e_phnum, sizeof(Elf_Phdr), M_TEMP, M_WAITOK); phsize = eh->e_phnum * sizeof(Elf_Phdr); if ((error = elf_read_from(p, epp->ep_vp, eh->e_phoff, ph, phsize)) != 0) goto bad; epp->ep_tsize = ELF_NO_ADDR; epp->ep_dsize = ELF_NO_ADDR; for (i = 0, pp = ph; i < eh->e_phnum; i++, pp++) { if ((pp->p_align > 1) && !powerof2(pp->p_align)) { error = EINVAL; goto bad; } if (pp->p_type == PT_INTERP && !interp) { if (pp->p_filesz < 2 || pp->p_filesz > MAXPATHLEN) goto bad; interp = pool_get(&namei_pool, PR_WAITOK); if ((error = elf_read_from(p, epp->ep_vp, pp->p_offset, interp, pp->p_filesz)) != 0) { goto bad; } if (interp[pp->p_filesz - 1] != '\0') goto bad; } else if (pp->p_type == PT_LOAD) { if (pp->p_filesz > pp->p_memsz || pp->p_memsz == 0) { error = EINVAL; goto bad; } if (base_ph == NULL) base_ph = pp; } else if (pp->p_type == PT_PHDR) { has_phdr = 1; } } /* * Verify this is an OpenBSD executable. If it's marked that way * via a PT_NOTE then also check for a PT_OPENBSD_WXNEEDED segment. */ if ((error = elf_os_pt_note(p, epp, epp->ep_hdr, &names)) != 0) goto bad; if (eh->e_ident[EI_OSABI] == ELFOSABI_OPENBSD) names |= ELF_NOTE_NAME_OPENBSD; if (eh->e_type == ET_DYN) { /* need phdr and load sections for PIE */ if (!has_phdr || base_ph == NULL || base_ph->p_vaddr != 0) { error = EINVAL; goto bad; } /* randomize exe_base for PIE */ exe_base = uvm_map_pie(base_ph->p_align); /* * Check if DYNAMIC contains DT_TEXTREL */ for (i = 0, pp = ph; i < eh->e_phnum; i++, pp++) { Elf_Dyn *dt; int j; switch (pp->p_type) { case PT_DYNAMIC: if (pp->p_filesz > 64*1024) break; dt = malloc(pp->p_filesz, M_TEMP, M_WAITOK); error = vn_rdwr(UIO_READ, epp->ep_vp, (caddr_t)dt, pp->p_filesz, pp->p_offset, UIO_SYSSPACE, IO_UNIT, p->p_ucred, NULL, p); if (error) { free(dt, M_TEMP, pp->p_filesz); break; } for (j = 0; j < pp->p_filesz / sizeof(*dt); j++) { if (dt[j].d_tag == DT_TEXTREL) { textrel = VMCMD_TEXTREL; break; } } free(dt, M_TEMP, pp->p_filesz); break; default: break; } } } /* * Load all the necessary sections */ for (i = 0, pp = ph; i < eh->e_phnum; i++, pp++) { Elf_Addr addr, size = 0; int prot = 0; int flags = 0; switch (pp->p_type) { case PT_LOAD: if (exe_base != 0) { if (pp == base_ph) { flags = VMCMD_BASE; addr = exe_base; } else { flags = VMCMD_RELATIVE; addr = pp->p_vaddr - base_ph->p_vaddr; } } else addr = ELF_NO_ADDR; /* Static binaries may not call pinsyscalls() */ if (interp == NULL) p->p_vmspace->vm_map.flags |= VM_MAP_PINSYSCALL_ONCE; /* * Calculates size of text and data segments * by starting at first and going to end of last. * 'rwx' sections are treated as data. * this is correct for BSS_PLT, but may not be * for DATA_PLT, is fine for TEXT_PLT. */ elf_load_psection(&epp->ep_vmcmds, epp->ep_vp, pp, &addr, &size, &prot, flags | textrel); /* * Update exe_base in case alignment was off. * For PIE, addr is relative to exe_base so * adjust it (non PIE exe_base is 0 so no change). */ if (flags == VMCMD_BASE) exe_base = addr; else addr += exe_base; /* * Decide whether it's text or data by looking * at the protection of the section */ if (prot & PROT_WRITE) { /* data section */ if (epp->ep_dsize == ELF_NO_ADDR) { epp->ep_daddr = addr; epp->ep_dsize = size; } else { if (addr < epp->ep_daddr) { epp->ep_dsize = epp->ep_dsize + epp->ep_daddr - addr; epp->ep_daddr = addr; } else epp->ep_dsize = addr+size - epp->ep_daddr; } } else if (prot & PROT_EXEC) { /* text section */ if (epp->ep_tsize == ELF_NO_ADDR) { epp->ep_taddr = addr; epp->ep_tsize = size; } else { if (addr < epp->ep_taddr) { epp->ep_tsize = epp->ep_tsize + epp->ep_taddr - addr; epp->ep_taddr = addr; } else epp->ep_tsize = addr+size - epp->ep_taddr; } if (interp == NULL) exe_end = epp->ep_taddr + epp->ep_tsize; /* end of TEXT */ } break; case PT_SHLIB: error = ENOEXEC; goto bad; case PT_INTERP: /* Already did this one */ case PT_NOTE: break; case PT_PHDR: /* Note address of program headers (in text segment) */ phdr = pp->p_vaddr; break; case PT_OPENBSD_RANDOMIZE: if (ph[i].p_memsz > randomizequota) { error = ENOMEM; goto bad; } randomizequota -= ph[i].p_memsz; NEW_VMCMD(&epp->ep_vmcmds, vmcmd_randomize, ph[i].p_memsz, ph[i].p_vaddr + exe_base, NULLVP, 0, 0); break; case PT_DYNAMIC: #if defined (__mips__) /* DT_DEBUG is not ready on mips */ NEW_VMCMD(&epp->ep_vmcmds, vmcmd_mutable, ph[i].p_memsz, ph[i].p_vaddr + exe_base, NULLVP, 0, 0); #endif break; case PT_GNU_RELRO: case PT_OPENBSD_MUTABLE: NEW_VMCMD(&epp->ep_vmcmds, vmcmd_mutable, ph[i].p_memsz, ph[i].p_vaddr + exe_base, NULLVP, 0, 0); break; case PT_OPENBSD_SYSCALLS: if (interp == NULL) syscall_ph = &ph[i]; break; default: /* * Not fatal, we don't need to understand everything * :-) */ break; } } if (syscall_ph) { vaddr_t base = exe_base; size_t len = exe_end - exe_base; u_int *pins; int npins; npins = elf_read_pintable(p, epp->ep_vp, syscall_ph, &pins, 0, len); if (npins) { elf_adjustpins(&base, &len, pins, npins, epp->ep_taddr - exe_base); epp->ep_pinstart = base; epp->ep_pinend = base + len; epp->ep_pins = pins; epp->ep_npins = npins; p->p_p->ps_flags |= PS_PIN; } } phdr += exe_base; /* * Strangely some linux programs may have all load sections marked * writeable, in this case, textsize is not -1, but rather 0; */ if (epp->ep_tsize == ELF_NO_ADDR) epp->ep_tsize = 0; /* * Another possibility is that it has all load sections marked * read-only. Fake a zero-sized data segment right after the * text segment. */ if (epp->ep_dsize == ELF_NO_ADDR) { epp->ep_daddr = round_page(epp->ep_taddr + epp->ep_tsize); epp->ep_dsize = 0; } epp->ep_interp = interp; epp->ep_entry = eh->e_entry + exe_base; /* * Check if we found a dynamically linked binary and arrange to load * its interpreter when the exec file is released. */ if (interp || eh->e_type == ET_DYN) { struct elf_args *ap; ap = malloc(sizeof(*ap), M_TEMP, M_WAITOK); ap->arg_phaddr = phdr; ap->arg_phentsize = eh->e_phentsize; ap->arg_phnum = eh->e_phnum; ap->arg_entry = eh->e_entry + exe_base; ap->arg_interp = exe_base; epp->ep_args = ap; } free(ph, M_TEMP, phsize); vn_marktext(epp->ep_vp); return (exec_setup_stack(p, epp)); bad: if (interp) pool_put(&namei_pool, interp); free(ph, M_TEMP, phsize); kill_vmcmds(&epp->ep_vmcmds); if (error == 0) return (ENOEXEC); return (error); } /* * Phase II of load. It is now safe to load the interpreter. Info collected * when loading the program is available for setup of the interpreter. */ int exec_elf_fixup(struct proc *p, struct exec_package *epp) { char *interp; int error = 0; struct elf_args *ap; AuxInfo ai[ELF_AUX_ENTRIES], *a; ap = epp->ep_args; if (ap == NULL) { return (0); } interp = epp->ep_interp; /* disable kbind in programs that don't use ld.so */ if (interp == NULL) p->p_p->ps_kbind_addr = BOGO_PC; if (interp && (error = elf_load_file(p, interp, epp, ap)) != 0) { uprintf("execve: cannot load %s\n", interp); free(ap, M_TEMP, sizeof *ap); pool_put(&namei_pool, interp); kill_vmcmds(&epp->ep_vmcmds); return (error); } /* * We have to do this ourselves... */ error = exec_process_vmcmds(p, epp); /* * Push extra arguments on the stack needed by dynamically * linked binaries */ if (error == 0) { memset(&ai, 0, sizeof ai); a = ai; a->au_id = AUX_phdr; a->au_v = ap->arg_phaddr; a++; a->au_id = AUX_phent; a->au_v = ap->arg_phentsize; a++; a->au_id = AUX_phnum; a->au_v = ap->arg_phnum; a++; a->au_id = AUX_pagesz; a->au_v = PAGE_SIZE; a++; a->au_id = AUX_base; a->au_v = ap->arg_interp; a++; a->au_id = AUX_flags; a->au_v = 0; a++; a->au_id = AUX_entry; a->au_v = ap->arg_entry; a++; a->au_id = AUX_openbsd_timekeep; a->au_v = p->p_p->ps_timekeep; a++; a->au_id = AUX_null; a->au_v = 0; a++; error = copyout(ai, epp->ep_auxinfo, sizeof ai); } free(ap, M_TEMP, sizeof *ap); if (interp) pool_put(&namei_pool, interp); return (error); } int elf_os_pt_note_name(Elf_Note *np) { int i, j; for (i = 0; i < nitems(elf_note_names); i++) { size_t namlen = strlen(elf_note_names[i].name); if (np->namesz < namlen) continue; /* verify name padding (after the NUL) is NUL */ for (j = namlen + 1; j < elfround(np->namesz); j++) if (((char *)(np + 1))[j] != '\0') continue; /* verify desc padding is NUL */ for (j = np->descsz; j < elfround(np->descsz); j++) if (((char *)(np + 1))[j] != '\0') continue; if (strcmp((char *)(np + 1), elf_note_names[i].name) == 0) return elf_note_names[i].id; } return (0); } int elf_os_pt_note(struct proc *p, struct exec_package *epp, Elf_Ehdr *eh, int *namesp) { Elf_Phdr *hph, *ph; Elf_Note *np = NULL; size_t phsize, offset, pfilesz = 0, total; int error, names = 0; hph = mallocarray(eh->e_phnum, sizeof(Elf_Phdr), M_TEMP, M_WAITOK); phsize = eh->e_phnum * sizeof(Elf_Phdr); if ((error = elf_read_from(p, epp->ep_vp, eh->e_phoff, hph, phsize)) != 0) goto out1; for (ph = hph; ph < &hph[eh->e_phnum]; ph++) { if (ph->p_type == PT_OPENBSD_WXNEEDED) { epp->ep_flags |= EXEC_WXNEEDED; continue; } if (ph->p_type == PT_OPENBSD_NOBTCFI) { epp->ep_flags |= EXEC_NOBTCFI; continue; } if (ph->p_type != PT_NOTE || ph->p_filesz > 1024) continue; if (np && ph->p_filesz != pfilesz) { free(np, M_TEMP, pfilesz); np = NULL; } if (!np) np = malloc(ph->p_filesz, M_TEMP, M_WAITOK); pfilesz = ph->p_filesz; if ((error = elf_read_from(p, epp->ep_vp, ph->p_offset, np, ph->p_filesz)) != 0) goto out2; for (offset = 0; offset < ph->p_filesz; offset += total) { Elf_Note *np2 = (Elf_Note *)((char *)np + offset); if (offset + sizeof(Elf_Note) > ph->p_filesz) break; total = sizeof(Elf_Note) + elfround(np2->namesz) + elfround(np2->descsz); if (offset + total > ph->p_filesz) break; names |= elf_os_pt_note_name(np2); } } out2: free(np, M_TEMP, pfilesz); out1: free(hph, M_TEMP, phsize); *namesp = names; return ((names & ELF_NOTE_NAME_OPENBSD) ? 0 : ENOEXEC); } /* * Start of routines related to dumping core */ #ifdef SMALL_KERNEL int coredump_elf(struct proc *p, void *cookie) { return EPERM; } #else /* !SMALL_KERNEL */ struct writesegs_state { off_t notestart; off_t secstart; off_t secoff; struct proc *p; void *iocookie; Elf_Phdr *psections; size_t psectionslen; size_t notesize; int npsections; }; uvm_coredump_setup_cb coredump_setup_elf; uvm_coredump_walk_cb coredump_walk_elf; int coredump_notes_elf(struct proc *, void *, size_t *); int coredump_note_elf(struct proc *, void *, size_t *); int coredump_writenote_elf(struct proc *, void *, Elf_Note *, const char *, void *); extern vaddr_t sigcode_va; extern vsize_t sigcode_sz; int coredump_elf(struct proc *p, void *cookie) { #ifdef DIAGNOSTIC off_t offset; #endif struct writesegs_state ws; size_t notesize; int error, i; ws.p = p; ws.iocookie = cookie; ws.psections = NULL; /* * Walk the map to get all the segment offsets and lengths, * write out the ELF header. */ error = uvm_coredump_walkmap(p, coredump_setup_elf, coredump_walk_elf, &ws); if (error) goto out; error = coredump_write(cookie, UIO_SYSSPACE, ws.psections, ws.psectionslen, 0); if (error) goto out; /* Write out the notes. */ error = coredump_notes_elf(p, cookie, &notesize); if (error) goto out; #ifdef DIAGNOSTIC if (notesize != ws.notesize) panic("coredump: notesize changed: %zu != %zu", ws.notesize, notesize); offset = ws.notestart + notesize; if (offset != ws.secstart) panic("coredump: offset %lld != secstart %lld", (long long) offset, (long long) ws.secstart); #endif /* Pass 3: finally, write the sections themselves. */ for (i = 0; i < ws.npsections - 1; i++) { Elf_Phdr *pent = &ws.psections[i]; if (pent->p_filesz == 0) continue; #ifdef DIAGNOSTIC if (offset != pent->p_offset) panic("coredump: offset %lld != p_offset[%d] %lld", (long long) offset, i, (long long) pent->p_filesz); #endif /* * Since the sigcode is mapped execute-only, we can't * read it. So use the kernel mapping for it instead. */ if (pent->p_vaddr == p->p_p->ps_sigcode && pent->p_filesz == sigcode_sz) { error = coredump_write(cookie, UIO_SYSSPACE, (void *)sigcode_va, sigcode_sz, 0); } else { error = coredump_write(cookie, UIO_USERSPACE, (void *)(vaddr_t)pent->p_vaddr, pent->p_filesz, (pent->p_flags & PF_ISVNODE)); } if (error) goto out; coredump_unmap(cookie, (vaddr_t)pent->p_vaddr, (vaddr_t)pent->p_vaddr + pent->p_filesz); #ifdef DIAGNOSTIC offset += ws.psections[i].p_filesz; #endif } out: free(ws.psections, M_TEMP, ws.psectionslen); return (error); } /* * Normally we lay out core files like this: * [ELF Header] [Program headers] [Notes] [data for PT_LOAD segments] * * However, if there's >= 65535 segments then it overflows the field * in the ELF header, so the standard specifies putting a magic * number there and saving the real count in the .sh_info field of * the first *section* header...which requires generating a section * header. To avoid confusing tools, we include an .shstrtab section * as well so all the indexes look valid. So in this case we lay * out the core file like this: * [ELF Header] [Section Headers] [.shstrtab] [Program headers] \ * [Notes] [data for PT_LOAD segments] * * The 'shstrtab' structure below is data for the second of the two * section headers, plus the .shstrtab itself, in one const buffer. */ static const struct { Elf_Shdr shdr; char shstrtab[sizeof(ELF_SHSTRTAB) + 1]; } shstrtab = { .shdr = { .sh_name = 1, /* offset in .shstrtab below */ .sh_type = SHT_STRTAB, .sh_offset = sizeof(Elf_Ehdr) + 2*sizeof(Elf_Shdr), .sh_size = sizeof(ELF_SHSTRTAB) + 1, .sh_addralign = 1, }, .shstrtab = "\0" ELF_SHSTRTAB, }; int coredump_setup_elf(int segment_count, void *cookie) { Elf_Ehdr ehdr; struct writesegs_state *ws = cookie; Elf_Phdr *note; int error; /* Get the count of segments, plus one for the PT_NOTE */ ws->npsections = segment_count + 1; /* Get the size of the notes. */ error = coredump_notes_elf(ws->p, NULL, &ws->notesize); if (error) return error; /* Setup the ELF header */ memset(&ehdr, 0, sizeof(ehdr)); memcpy(ehdr.e_ident, ELFMAG, SELFMAG); ehdr.e_ident[EI_CLASS] = ELF_TARG_CLASS; ehdr.e_ident[EI_DATA] = ELF_TARG_DATA; ehdr.e_ident[EI_VERSION] = EV_CURRENT; /* XXX Should be the OSABI/ABI version of the executable. */ ehdr.e_ident[EI_OSABI] = ELFOSABI_SYSV; ehdr.e_ident[EI_ABIVERSION] = 0; ehdr.e_type = ET_CORE; /* XXX This should be the e_machine of the executable. */ ehdr.e_machine = ELF_TARG_MACH; ehdr.e_version = EV_CURRENT; ehdr.e_entry = 0; ehdr.e_flags = 0; ehdr.e_ehsize = sizeof(ehdr); ehdr.e_phentsize = sizeof(Elf_Phdr); if (ws->npsections < PN_XNUM) { ehdr.e_phoff = sizeof(ehdr); ehdr.e_shoff = 0; ehdr.e_phnum = ws->npsections; ehdr.e_shentsize = 0; ehdr.e_shnum = 0; ehdr.e_shstrndx = 0; } else { /* too many segments, use extension setup */ ehdr.e_shoff = sizeof(ehdr); ehdr.e_phnum = PN_XNUM; ehdr.e_shentsize = sizeof(Elf_Shdr); ehdr.e_shnum = 2; ehdr.e_shstrndx = 1; ehdr.e_phoff = shstrtab.shdr.sh_offset + shstrtab.shdr.sh_size; } /* Write out the ELF header. */ error = coredump_write(ws->iocookie, UIO_SYSSPACE, &ehdr, sizeof(ehdr), 0); if (error) return error; /* * If an section header is needed to store extension info, write * it out after the ELF header and before the program header. */ if (ehdr.e_shnum != 0) { Elf_Shdr shdr = { .sh_info = ws->npsections }; error = coredump_write(ws->iocookie, UIO_SYSSPACE, &shdr, sizeof shdr, 0); if (error) return error; error = coredump_write(ws->iocookie, UIO_SYSSPACE, &shstrtab, sizeof(shstrtab.shdr) + sizeof(shstrtab.shstrtab), 0); if (error) return error; } /* * Allocate the segment header array and setup to collect * the section sizes and offsets */ ws->psections = mallocarray(ws->npsections, sizeof(Elf_Phdr), M_TEMP, M_WAITOK|M_CANFAIL|M_ZERO); if (ws->psections == NULL) return ENOMEM; ws->psectionslen = ws->npsections * sizeof(Elf_Phdr); ws->notestart = ehdr.e_phoff + ws->psectionslen; ws->secstart = ws->notestart + ws->notesize; ws->secoff = ws->secstart; /* Fill in the PT_NOTE segment header in the last slot */ note = &ws->psections[ws->npsections - 1]; note->p_type = PT_NOTE; note->p_offset = ws->notestart; note->p_vaddr = 0; note->p_paddr = 0; note->p_filesz = ws->notesize; note->p_memsz = 0; note->p_flags = PF_R; note->p_align = ELFROUNDSIZE; return (0); } int coredump_walk_elf(vaddr_t start, vaddr_t realend, vaddr_t end, vm_prot_t prot, int isvnode, int nsegment, void *cookie) { struct writesegs_state *ws = cookie; Elf_Phdr phdr; vsize_t size, realsize; size = end - start; realsize = realend - start; phdr.p_type = PT_LOAD; phdr.p_offset = ws->secoff; phdr.p_vaddr = start; phdr.p_paddr = 0; phdr.p_filesz = realsize; phdr.p_memsz = size; phdr.p_flags = 0; if (prot & PROT_READ) phdr.p_flags |= PF_R; if (prot & PROT_WRITE) phdr.p_flags |= PF_W; if (prot & PROT_EXEC) phdr.p_flags |= PF_X; if (isvnode) phdr.p_flags |= PF_ISVNODE; phdr.p_align = PAGE_SIZE; ws->secoff += phdr.p_filesz; ws->psections[nsegment] = phdr; return (0); } int coredump_notes_elf(struct proc *p, void *iocookie, size_t *sizep) { struct elfcore_procinfo cpi; Elf_Note nhdr; struct process *pr = p->p_p; struct proc *q; size_t size, notesize; int error; KASSERT(!P_HASSIBLING(p) || pr->ps_single != NULL); size = 0; /* First, write an elfcore_procinfo. */ notesize = sizeof(nhdr) + elfround(sizeof("OpenBSD")) + elfround(sizeof(cpi)); if (iocookie) { memset(&cpi, 0, sizeof(cpi)); cpi.cpi_version = ELFCORE_PROCINFO_VERSION; cpi.cpi_cpisize = sizeof(cpi); cpi.cpi_signo = p->p_sisig; cpi.cpi_sigcode = p->p_sicode; cpi.cpi_sigpend = p->p_siglist | pr->ps_siglist; cpi.cpi_sigmask = p->p_sigmask; cpi.cpi_sigignore = pr->ps_sigacts->ps_sigignore; cpi.cpi_sigcatch = pr->ps_sigacts->ps_sigcatch; cpi.cpi_pid = pr->ps_pid; cpi.cpi_ppid = pr->ps_ppid; cpi.cpi_pgrp = pr->ps_pgid; if (pr->ps_session->s_leader) cpi.cpi_sid = pr->ps_session->s_leader->ps_pid; else cpi.cpi_sid = 0; cpi.cpi_ruid = p->p_ucred->cr_ruid; cpi.cpi_euid = p->p_ucred->cr_uid; cpi.cpi_svuid = p->p_ucred->cr_svuid; cpi.cpi_rgid = p->p_ucred->cr_rgid; cpi.cpi_egid = p->p_ucred->cr_gid; cpi.cpi_svgid = p->p_ucred->cr_svgid; (void)strlcpy(cpi.cpi_name, pr->ps_comm, sizeof(cpi.cpi_name)); nhdr.namesz = sizeof("OpenBSD"); nhdr.descsz = sizeof(cpi); nhdr.type = NT_OPENBSD_PROCINFO; error = coredump_writenote_elf(p, iocookie, &nhdr, "OpenBSD", &cpi); if (error) return (error); } size += notesize; /* Second, write an NT_OPENBSD_AUXV note. */ notesize = sizeof(nhdr) + elfround(sizeof("OpenBSD")) + elfround(ELF_AUX_WORDS * sizeof(char *)); if (iocookie && pr->ps_auxinfo) { nhdr.namesz = sizeof("OpenBSD"); nhdr.descsz = ELF_AUX_WORDS * sizeof(char *); nhdr.type = NT_OPENBSD_AUXV; error = coredump_write(iocookie, UIO_SYSSPACE, &nhdr, sizeof(nhdr), 0); if (error) return (error); error = coredump_write(iocookie, UIO_SYSSPACE, "OpenBSD", elfround(nhdr.namesz), 0); if (error) return (error); error = coredump_write(iocookie, UIO_USERSPACE, (caddr_t)pr->ps_auxinfo, nhdr.descsz, 0); if (error) return (error); } size += notesize; #ifdef PT_WCOOKIE notesize = sizeof(nhdr) + elfround(sizeof("OpenBSD")) + elfround(sizeof(register_t)); if (iocookie) { register_t wcookie; nhdr.namesz = sizeof("OpenBSD"); nhdr.descsz = sizeof(register_t); nhdr.type = NT_OPENBSD_WCOOKIE; wcookie = process_get_wcookie(p); error = coredump_writenote_elf(p, iocookie, &nhdr, "OpenBSD", &wcookie); if (error) return (error); } size += notesize; #endif /* * Now write the register info for the thread that caused the * coredump. */ error = coredump_note_elf(p, iocookie, &notesize); if (error) return (error); size += notesize; /* * Now, for each thread, write the register info and any other * per-thread notes. Since we're dumping core, all the other * threads in the process have been stopped and the list can't * change. */ TAILQ_FOREACH(q, &pr->ps_threads, p_thr_link) { if (q == p) /* we've taken care of this thread */ continue; error = coredump_note_elf(q, iocookie, &notesize); if (error) return (error); size += notesize; } *sizep = size; return (0); } int coredump_note_elf(struct proc *p, void *iocookie, size_t *sizep) { Elf_Note nhdr; int size, notesize, error; int namesize; char name[64+ELFROUNDSIZE]; struct reg intreg; #ifdef PT_GETFPREGS struct fpreg freg; #endif #ifdef PT_PACMASK register_t pacmask[2]; #endif size = 0; snprintf(name, sizeof(name)-ELFROUNDSIZE, "%s@%d", "OpenBSD", p->p_tid + THREAD_PID_OFFSET); namesize = strlen(name) + 1; memset(name + namesize, 0, elfround(namesize) - namesize); notesize = sizeof(nhdr) + elfround(namesize) + elfround(sizeof(intreg)); if (iocookie) { error = process_read_regs(p, &intreg); if (error) return (error); nhdr.namesz = namesize; nhdr.descsz = sizeof(intreg); nhdr.type = NT_OPENBSD_REGS; error = coredump_writenote_elf(p, iocookie, &nhdr, name, &intreg); if (error) return (error); } size += notesize; #ifdef PT_GETFPREGS notesize = sizeof(nhdr) + elfround(namesize) + elfround(sizeof(freg)); if (iocookie) { error = process_read_fpregs(p, &freg); if (error) return (error); nhdr.namesz = namesize; nhdr.descsz = sizeof(freg); nhdr.type = NT_OPENBSD_FPREGS; error = coredump_writenote_elf(p, iocookie, &nhdr, name, &freg); if (error) return (error); } size += notesize; #endif #ifdef PT_PACMASK notesize = sizeof(nhdr) + elfround(namesize) + elfround(sizeof(pacmask)); if (iocookie) { pacmask[0] = pacmask[1] = process_get_pacmask(p); nhdr.namesz = namesize; nhdr.descsz = sizeof(pacmask); nhdr.type = NT_OPENBSD_PACMASK; error = coredump_writenote_elf(p, iocookie, &nhdr, name, &pacmask); if (error) return (error); } size += notesize; #endif *sizep = size; /* XXX Add hook for machdep per-LWP notes. */ return (0); } int coredump_writenote_elf(struct proc *p, void *cookie, Elf_Note *nhdr, const char *name, void *data) { int error; error = coredump_write(cookie, UIO_SYSSPACE, nhdr, sizeof(*nhdr), 0); if (error) return error; error = coredump_write(cookie, UIO_SYSSPACE, name, elfround(nhdr->namesz), 0); if (error) return error; return coredump_write(cookie, UIO_SYSSPACE, data, nhdr->descsz, 0); } #endif /* !SMALL_KERNEL */
674 694 709 235 90 80 12 90 51 9 19 31 12 6 83 22 733 56 465 50 10 6 2 24 215 666 596 4 1 65 1 296 1 672 11 7 8 6 2 3 4 385 385 32 371 343 71 1 337 43 13 3 32 385 304 291 14 303 304 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 /* $OpenBSD: vfs_cache.c,v 1.58 2022/08/14 01:58:28 jsg Exp $ */ /* $NetBSD: vfs_cache.c,v 1.13 1996/02/04 02:18:09 christos Exp $ */ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)vfs_cache.c 8.3 (Berkeley) 8/22/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/vnode.h> #include <sys/lock.h> #include <sys/namei.h> #include <sys/errno.h> #include <sys/pool.h> /* * TODO: namecache access should really be locked. */ /* * For simplicity (and economy of storage), names longer than * a maximum length of NAMECACHE_MAXLEN are not cached; they occur * infrequently in any case, and are almost never of interest. * * Upon reaching the last segment of a path, if the reference * is for DELETE, or NOCACHE is set (rewrite), and the * name is located in the cache, it will be dropped. */ /* * Structures associated with name caching. */ long numcache; /* total number of cache entries allocated */ long numneg; /* number of negative cache entries */ TAILQ_HEAD(, namecache) nclruhead; /* Regular Entry LRU chain */ TAILQ_HEAD(, namecache) nclruneghead; /* Negative Entry LRU chain */ struct nchstats nchstats; /* cache effectiveness statistics */ int doingcache = 1; /* 1 => enable the cache */ struct pool nch_pool; void cache_zap(struct namecache *); u_long nextvnodeid; static inline int namecache_compare(const struct namecache *n1, const struct namecache *n2) { if (n1->nc_nlen == n2->nc_nlen) return (memcmp(n1->nc_name, n2->nc_name, n1->nc_nlen)); else return (n1->nc_nlen - n2->nc_nlen); } RBT_PROTOTYPE(namecache_rb_cache, namecache, n_rbcache, namecache_compare); RBT_GENERATE(namecache_rb_cache, namecache, n_rbcache, namecache_compare); void cache_tree_init(struct namecache_rb_cache *tree) { RBT_INIT(namecache_rb_cache, tree); } /* * blow away a namecache entry */ void cache_zap(struct namecache *ncp) { struct vnode *dvp = NULL; if (ncp->nc_vp != NULL) { TAILQ_REMOVE(&nclruhead, ncp, nc_lru); numcache--; } else { TAILQ_REMOVE(&nclruneghead, ncp, nc_neg); numneg--; } if (ncp->nc_dvp) { RBT_REMOVE(namecache_rb_cache, &ncp->nc_dvp->v_nc_tree, ncp); if (RBT_EMPTY(namecache_rb_cache, &ncp->nc_dvp->v_nc_tree)) dvp = ncp->nc_dvp; } if (ncp->nc_vp && (ncp->nc_vpid == ncp->nc_vp->v_id)) { if (ncp->nc_vp != ncp->nc_dvp && ncp->nc_vp->v_type == VDIR && (ncp->nc_nlen > 2 || (ncp->nc_nlen > 1 && ncp->nc_name[1] != '.') || (ncp->nc_nlen > 0 && ncp->nc_name[0] != '.'))) { TAILQ_REMOVE(&ncp->nc_vp->v_cache_dst, ncp, nc_me); } } pool_put(&nch_pool, ncp); if (dvp) vdrop(dvp); } /* * Look for a name in the cache. * dvp points to the directory to search. The componentname cnp holds * the information on the entry being sought, such as its length * and its name. If the lookup succeeds, vpp is set to point to the vnode * and an error of 0 is returned. If the lookup determines the name does * not exist (negative caching) an error of ENOENT is returned. If the * lookup fails, an error of -1 is returned. */ int cache_lookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp) { struct namecache *ncp; struct namecache n; struct vnode *vp; u_long vpid; int error; *vpp = NULL; if (!doingcache) { cnp->cn_flags &= ~MAKEENTRY; return (-1); } if (cnp->cn_namelen > NAMECACHE_MAXLEN) { nchstats.ncs_long++; cnp->cn_flags &= ~MAKEENTRY; return (-1); } /* lookup in directory vnode's redblack tree */ n.nc_nlen = cnp->cn_namelen; memcpy(n.nc_name, cnp->cn_nameptr, n.nc_nlen); ncp = RBT_FIND(namecache_rb_cache, &dvp->v_nc_tree, &n); if (ncp == NULL) { nchstats.ncs_miss++; return (-1); } if ((cnp->cn_flags & MAKEENTRY) == 0) { nchstats.ncs_badhits++; goto remove; } else if (ncp->nc_vp == NULL) { if (cnp->cn_nameiop != CREATE || (cnp->cn_flags & ISLASTCN) == 0) { nchstats.ncs_neghits++; /* * Move this slot to end of the negative LRU chain, */ if (TAILQ_NEXT(ncp, nc_neg) != NULL) { TAILQ_REMOVE(&nclruneghead, ncp, nc_neg); TAILQ_INSERT_TAIL(&nclruneghead, ncp, nc_neg); } return (ENOENT); } else { nchstats.ncs_badhits++; goto remove; } } else if (ncp->nc_vpid != ncp->nc_vp->v_id) { nchstats.ncs_falsehits++; goto remove; } /* * Move this slot to end of the regular LRU chain. */ if (TAILQ_NEXT(ncp, nc_lru) != NULL) { TAILQ_REMOVE(&nclruhead, ncp, nc_lru); TAILQ_INSERT_TAIL(&nclruhead, ncp, nc_lru); } vp = ncp->nc_vp; vpid = vp->v_id; if (vp == dvp) { /* lookup on "." */ vref(dvp); error = 0; } else if (cnp->cn_flags & ISDOTDOT) { VOP_UNLOCK(dvp); cnp->cn_flags |= PDIRUNLOCK; error = vget(vp, LK_EXCLUSIVE); /* * If the above vget() succeeded and both LOCKPARENT and * ISLASTCN is set, lock the directory vnode as well. */ if (!error && (~cnp->cn_flags & (LOCKPARENT|ISLASTCN)) == 0) { if ((error = vn_lock(dvp, LK_EXCLUSIVE)) != 0) { vput(vp); return (error); } cnp->cn_flags &= ~PDIRUNLOCK; } } else { error = vget(vp, LK_EXCLUSIVE); /* * If the above vget() failed or either of LOCKPARENT or * ISLASTCN is set, unlock the directory vnode. */ if (error || (~cnp->cn_flags & (LOCKPARENT|ISLASTCN)) != 0) { VOP_UNLOCK(dvp); cnp->cn_flags |= PDIRUNLOCK; } } /* * Check that the lock succeeded, and that the capability number did * not change while we were waiting for the lock. */ if (error || vpid != vp->v_id) { if (!error) { vput(vp); nchstats.ncs_falsehits++; } else nchstats.ncs_badhits++; /* * The parent needs to be locked when we return to VOP_LOOKUP(). * The `.' case here should be extremely rare (if it can happen * at all), so we don't bother optimizing out the unlock/relock. */ if (vp == dvp || error || (~cnp->cn_flags & (LOCKPARENT|ISLASTCN)) != 0) { if ((error = vn_lock(dvp, LK_EXCLUSIVE)) != 0) return (error); cnp->cn_flags &= ~PDIRUNLOCK; } return (-1); } nchstats.ncs_goodhits++; *vpp = vp; return (0); remove: /* * Last component and we are renaming or deleting, * the cache entry is invalid, or otherwise don't * want cache entry to exist. */ cache_zap(ncp); return (-1); } /* * Scan cache looking for name of directory entry pointing at vp. * * Fill in dvpp. * * If bufp is non-NULL, also place the name in the buffer which starts * at bufp, immediately before *bpp, and move bpp backwards to point * at the start of it. (Yes, this is a little baroque, but it's done * this way to cater to the whims of getcwd). * * Returns 0 on success, -1 on cache miss, positive errno on failure. * * TODO: should we return *dvpp locked? */ int cache_revlookup(struct vnode *vp, struct vnode **dvpp, char **bpp, char *bufp) { struct namecache *ncp; struct vnode *dvp = NULL; char *bp; if (!doingcache) goto out; TAILQ_FOREACH(ncp, &vp->v_cache_dst, nc_me) { dvp = ncp->nc_dvp; if (dvp && dvp != vp && ncp->nc_dvpid == dvp->v_id) goto found; } goto miss; found: #ifdef DIAGNOSTIC if (ncp->nc_nlen == 1 && ncp->nc_name[0] == '.') panic("cache_revlookup: found entry for ."); if (ncp->nc_nlen == 2 && ncp->nc_name[0] == '.' && ncp->nc_name[1] == '.') panic("cache_revlookup: found entry for .."); #endif nchstats.ncs_revhits++; if (bufp != NULL) { bp = *bpp; bp -= ncp->nc_nlen; if (bp <= bufp) { *dvpp = NULL; return (ERANGE); } memcpy(bp, ncp->nc_name, ncp->nc_nlen); *bpp = bp; } *dvpp = dvp; /* * XXX: Should we vget() here to have more * consistent semantics with cache_lookup()? */ return (0); miss: nchstats.ncs_revmiss++; out: *dvpp = NULL; return (-1); } /* * Add an entry to the cache */ void cache_enter(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) { struct namecache *ncp, *lncp; if (!doingcache || cnp->cn_namelen > NAMECACHE_MAXLEN) return; /* * allocate, or recycle (free and allocate) an ncp. */ if (numcache >= initialvnodes) { if ((ncp = TAILQ_FIRST(&nclruhead)) != NULL) cache_zap(ncp); else if ((ncp = TAILQ_FIRST(&nclruneghead)) != NULL) cache_zap(ncp); else panic("wtf? leak?"); } ncp = pool_get(&nch_pool, PR_WAITOK|PR_ZERO); /* grab the vnode we just found */ ncp->nc_vp = vp; if (vp) ncp->nc_vpid = vp->v_id; /* fill in cache info */ ncp->nc_dvp = dvp; ncp->nc_dvpid = dvp->v_id; ncp->nc_nlen = cnp->cn_namelen; memcpy(ncp->nc_name, cnp->cn_nameptr, ncp->nc_nlen); if (RBT_EMPTY(namecache_rb_cache, &dvp->v_nc_tree)) { vhold(dvp); } if ((lncp = RBT_INSERT(namecache_rb_cache, &dvp->v_nc_tree, ncp)) != NULL) { /* someone has raced us and added a different entry * for the same vnode (different ncp) - we don't need * this entry, so free it and we are done. */ pool_put(&nch_pool, ncp); /* we know now dvp->v_nc_tree is not empty, no need * to vdrop here */ goto done; } if (vp) { TAILQ_INSERT_TAIL(&nclruhead, ncp, nc_lru); numcache++; /* don't put . or .. in the reverse map */ if (vp != dvp && vp->v_type == VDIR && (ncp->nc_nlen > 2 || (ncp->nc_nlen > 1 && ncp->nc_name[1] != '.') || (ncp->nc_nlen > 0 && ncp->nc_name[0] != '.'))) TAILQ_INSERT_TAIL(&vp->v_cache_dst, ncp, nc_me); } else { TAILQ_INSERT_TAIL(&nclruneghead, ncp, nc_neg); numneg++; } if (numneg > initialvnodes) { if ((ncp = TAILQ_FIRST(&nclruneghead)) != NULL) cache_zap(ncp); } done: return; } /* * Name cache initialization, from vfs_init() when we are booting */ void nchinit(void) { TAILQ_INIT(&nclruhead); TAILQ_INIT(&nclruneghead); pool_init(&nch_pool, sizeof(struct namecache), 0, IPL_NONE, PR_WAITOK, "nchpl", NULL); } /* * Cache flush, a particular vnode; called when a vnode is renamed to * hide entries that would now be invalid */ void cache_purge(struct vnode *vp) { struct namecache *ncp; /* We should never have destinations cached for a non-VDIR vnode. */ KASSERT(vp->v_type == VDIR || TAILQ_EMPTY(&vp->v_cache_dst)); while ((ncp = TAILQ_FIRST(&vp->v_cache_dst))) cache_zap(ncp); while ((ncp = RBT_ROOT(namecache_rb_cache, &vp->v_nc_tree))) cache_zap(ncp); /* XXX this blows goats */ vp->v_id = ++nextvnodeid; if (vp->v_id == 0) vp->v_id = ++nextvnodeid; } /* * Cache flush, a whole filesystem; called when filesys is umounted to * remove entries that would now be invalid */ void cache_purgevfs(struct mount *mp) { struct namecache *ncp, *nxtcp; /* whack the regular entries */ TAILQ_FOREACH_SAFE(ncp, &nclruhead, nc_lru, nxtcp) { if (ncp->nc_dvp == NULL || ncp->nc_dvp->v_mount != mp) continue; /* free the resources we had */ cache_zap(ncp); } /* whack the negative entries */ TAILQ_FOREACH_SAFE(ncp, &nclruneghead, nc_neg, nxtcp) { if (ncp->nc_dvp == NULL || ncp->nc_dvp->v_mount != mp) continue; /* free the resources we had */ cache_zap(ncp); } }
6498 6497 6495 6498 6493 6490 6441 417 6513 6497 6431 6429 6398 112 1308 220 1134 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 /* $OpenBSD: syscall_mi.h,v 1.33 2024/04/01 12:00:15 deraadt Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_xxx.c 8.2 (Berkeley) 11/14/93 */ #include <sys/param.h> #include <sys/pledge.h> #include <sys/acct.h> #include <sys/syslog.h> #include <sys/tracepoint.h> #include <sys/syscall.h> #include <sys/signalvar.h> #include <uvm/uvm_extern.h> #ifdef KTRACE #include <sys/ktrace.h> #endif #include "dt.h" #if NDT > 0 #include <dev/dt/dtvar.h> #endif /* * Check if a system call is entered from precisely correct location */ static inline int pin_check(struct proc *p, register_t code) { extern char sigcodecall[], sigcoderet[], sigcodecall[]; struct pinsyscall *pin = NULL, *ppin, *plibcpin; struct process *pr = p->p_p; vaddr_t addr; int error = 0; /* point at start of syscall instruction */ addr = (vaddr_t)PROC_PC(p) - (vaddr_t)(sigcoderet - sigcodecall); ppin = &pr->ps_pin; plibcpin = &pr->ps_libcpin; /* * System calls come from the following places, checks are ordered * by most common case: * 1) dynamic binary: syscalls in libc.so (in the ps_libcpin region) * 2a) static binary: syscalls in main program (in the ps_pin region) * 2b) dynamic binary: sysalls in ld.so (in the ps_pin region) * 3) sigtramp, containing only sigreturn(2) */ if (plibcpin->pn_pins && addr >= plibcpin->pn_start && addr < plibcpin->pn_end) pin = plibcpin; else if (ppin->pn_pins && addr >= ppin->pn_start && addr < ppin->pn_end) pin = ppin; else if (PROC_PC(p) == pr->ps_sigcoderet) { if (code == SYS_sigreturn) return (0); error = EPERM; goto die; } if (pin) { if (code >= pin->pn_npins || pin->pn_pins[code] == 0) error = ENOSYS; else if (pin->pn_pins[code] + pin->pn_start == addr) ; /* correct location */ else if (pin->pn_pins[code] == (u_int)-1) ; /* multiple locations, hopefully a boring operation */ else error = ENOSYS; } else error = ENOSYS; if (error == 0) return (0); die: #ifdef KTRACE if (KTRPOINT(p, KTR_PINSYSCALL)) ktrpinsyscall(p, error, code, addr); #endif KERNEL_LOCK(); /* XXX remove or simplify this log() call after OpenBSD 7.5 release */ log(LOG_ERR, "%s[%d]: pinsyscalls addr %lx code %ld, pinoff 0x%x " "(pin%s %d %lx-%lx %lx) (libcpin%s %d %lx-%lx %lx) error %d\n", p->p_p->ps_comm, p->p_p->ps_pid, addr, code, (pin && code < pin->pn_npins) ? pin->pn_pins[code] : -1, pin == ppin ? "(Y)" : "", ppin->pn_npins, ppin->pn_start, ppin->pn_end, ppin->pn_end - ppin->pn_start, pin == plibcpin ? "(Y)" : "", plibcpin->pn_npins, plibcpin->pn_start, plibcpin->pn_end, plibcpin->pn_end - plibcpin->pn_start, error); p->p_p->ps_acflag |= APINSYS; /* Try to stop threads immediately, because this process is suspect */ if (P_HASSIBLING(p)) single_thread_set(p, SINGLE_UNWIND | SINGLE_DEEP); /* Send uncatchable SIGABRT for coredump */ sigabort(p); KERNEL_UNLOCK(); return (error); } /* * The MD setup for a system call has been done; here's the MI part. */ static inline int mi_syscall(struct proc *p, register_t code, const struct sysent *callp, register_t *argp, register_t retval[2]) { uint64_t tval; int lock = !(callp->sy_flags & SY_NOLOCK); int error, pledged; /* refresh the thread's cache of the process's creds */ refreshcreds(p); #ifdef SYSCALL_DEBUG KERNEL_LOCK(); scdebug_call(p, code, argp); KERNEL_UNLOCK(); #endif TRACEPOINT(raw_syscalls, sys_enter, code, NULL); #if NDT > 0 DT_ENTER(syscall, code, callp->sy_argsize, argp); #endif #ifdef KTRACE if (KTRPOINT(p, KTR_SYSCALL)) { /* convert to mask, then include with code */ KERNEL_LOCK(); ktrsyscall(p, code, callp->sy_argsize, argp); KERNEL_UNLOCK(); } #endif /* SP must be within MAP_STACK space */ if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p), "[%s]%d/%d sp=%lx inside %lx-%lx: not MAP_STACK\n", uvm_map_inentry_sp, p->p_vmspace->vm_map.sserial)) return (EPERM); if ((error = pin_check(p, code))) return (error); pledged = (p->p_p->ps_flags & PS_PLEDGE); if (pledged && (error = pledge_syscall(p, code, &tval))) { KERNEL_LOCK(); error = pledge_fail(p, error, tval); KERNEL_UNLOCK(); return (error); } if (lock) KERNEL_LOCK(); error = (*callp->sy_call)(p, argp, retval); if (lock) KERNEL_UNLOCK(); return (error); } /* * Finish MI stuff on return, after the registers have been set */ static inline void mi_syscall_return(struct proc *p, register_t code, int error, const register_t retval[2]) { #ifdef SYSCALL_DEBUG KERNEL_LOCK(); scdebug_ret(p, code, error, retval); KERNEL_UNLOCK(); #endif #if NDT > 0 DT_LEAVE(syscall, code, error, retval[0], retval[1]); #endif TRACEPOINT(raw_syscalls, sys_exit, code, NULL); userret(p); #ifdef KTRACE if (KTRPOINT(p, KTR_SYSRET)) { KERNEL_LOCK(); ktrsysret(p, code, error, retval); KERNEL_UNLOCK(); } #endif } /* * Finish MI stuff for a new process/thread to return */ static inline void mi_child_return(struct proc *p) { #if defined(SYSCALL_DEBUG) || defined(KTRACE) || NDT > 0 int code = (p->p_flag & P_THREAD) ? SYS___tfork : (p->p_p->ps_flags & PS_PPWAIT) ? SYS_vfork : SYS_fork; const register_t child_retval[2] = { 0, 1 }; #endif TRACEPOINT(sched, on__cpu, NULL); #ifdef SYSCALL_DEBUG KERNEL_LOCK(); scdebug_ret(p, code, 0, child_retval); KERNEL_UNLOCK(); #endif #if NDT > 0 DT_LEAVE(syscall, code, 0, child_retval[0], child_retval[1]); #endif TRACEPOINT(raw_syscalls, sys_exit, code, NULL); userret(p); #ifdef KTRACE if (KTRPOINT(p, KTR_SYSRET)) { KERNEL_LOCK(); ktrsysret(p, code, 0, child_retval); KERNEL_UNLOCK(); } #endif } /* * Do the specific processing necessary for an AST */ static inline void mi_ast(struct proc *p, int resched) { if (p->p_flag & P_OWEUPC) { KERNEL_LOCK(); ADDUPROF(p); KERNEL_UNLOCK(); } if (resched) preempt(); /* * XXX could move call to userret() here, but * hppa calls ast() in syscall return and sh calls * it after userret() */ }
1446 1448 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 /* $OpenBSD: uvm_unix.c,v 1.73 2024/01/17 22:22:25 kurt Exp $ */ /* $NetBSD: uvm_unix.c,v 1.18 2000/09/13 15:00:25 thorpej Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. * Copyright (c) 1991, 1993 The Regents of the University of California. * Copyright (c) 1988 University of Utah. * * All rights reserved. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: Utah $Hdr: vm_unix.c 1.1 89/11/07$ * @(#)vm_unix.c 8.1 (Berkeley) 6/11/93 * from: Id: uvm_unix.c,v 1.1.2.2 1997/08/25 18:52:30 chuck Exp */ /* * uvm_unix.c: traditional sbrk/grow interface to vm. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/resourcevar.h> #include <sys/vnode.h> #include <sys/mount.h> #include <sys/syscallargs.h> #include <uvm/uvm.h> /* * sys_obreak: set break */ int sys_obreak(struct proc *p, void *v, register_t *retval) { struct sys_obreak_args /* { syscallarg(char *) nsize; } */ *uap = v; struct vmspace *vm = p->p_vmspace; vaddr_t new, old, base; int error; base = (vaddr_t)vm->vm_daddr; new = round_page((vaddr_t)SCARG(uap, nsize)); if (new < base || (new - base) > lim_cur(RLIMIT_DATA)) return (ENOMEM); old = round_page(base + ptoa(vm->vm_dsize)); if (new == old) return (0); /* grow or shrink? */ if (new > old) { error = uvm_map(&vm->vm_map, &old, new - old, NULL, UVM_UNKNOWN_OFFSET, 0, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_INHERIT_COPY, MADV_NORMAL, UVM_FLAG_FIXED|UVM_FLAG_COPYONW)); if (error) { uprintf("sbrk: grow %ld failed, error = %d\n", new - old, error); return (ENOMEM); } vm->vm_dsize += atop(new - old); } else { uvm_unmap(&vm->vm_map, new, old); vm->vm_dsize -= atop(old - new); } return (0); } /* * uvm_grow: enlarge the "stack segment" to include sp. */ void uvm_grow(struct proc *p, vaddr_t sp) { struct vmspace *vm = p->p_vmspace; vm_map_t map = &vm->vm_map; int si; /* For user defined stacks (from sendsig). */ if (sp < (vaddr_t)vm->vm_maxsaddr) return; #ifdef MACHINE_STACK_GROWS_UP if (sp >= (vaddr_t)vm->vm_minsaddr) return; #endif vm_map_lock(map); /* For common case of already allocated (from trap). */ #ifdef MACHINE_STACK_GROWS_UP if (sp < (vaddr_t)vm->vm_maxsaddr + ptoa(vm->vm_ssize)) #else if (sp >= (vaddr_t)vm->vm_minsaddr - ptoa(vm->vm_ssize)) #endif goto out; /* Really need to check vs limit and increment stack size if ok. */ #ifdef MACHINE_STACK_GROWS_UP si = atop(sp - (vaddr_t)vm->vm_maxsaddr) - vm->vm_ssize + 1; #else si = atop((vaddr_t)vm->vm_minsaddr - sp) - vm->vm_ssize; #endif if (vm->vm_ssize + si <= atop(lim_cur(RLIMIT_STACK))) vm->vm_ssize += si; out: vm_map_unlock(map); } #ifndef SMALL_KERNEL #define WALK_CHUNK 32 /* * Not all the pages in an amap may be present. When dumping core, * we don't want to force all the pages to be present: it's a waste * of time and memory when we already know what they contain (zeros) * and the ELF format at least can adequately represent them as a * segment with memory size larger than its file size. * * So, we walk the amap with calls to amap_lookups() and scan the * resulting pointers to find ranges of zero or more present pages * followed by at least one absent page or the end of the amap. * When then pass that range to the walk callback with 'start' * pointing to the start of the present range, 'realend' pointing * to the first absent page (or the end of the entry), and 'end' * pointing to the page past the last absent page (or the end of * the entry). * * Note that if the first page of the amap is empty then the callback * must be invoked with 'start' == 'realend' so it can present that * first range of absent pages. */ int uvm_coredump_walk_amap(struct vm_map_entry *entry, int *nsegmentp, uvm_coredump_walk_cb *walk, void *cookie) { struct vm_anon *anons[WALK_CHUNK]; vaddr_t pos, start, realend, end, entry_end; vm_prot_t prot; int nsegment, absent, npages, i, error; prot = entry->protection; nsegment = *nsegmentp; start = entry->start; entry_end = MIN(entry->end, VM_MAXUSER_ADDRESS); absent = 0; for (pos = start; pos < entry_end; pos += npages << PAGE_SHIFT) { npages = (entry_end - pos) >> PAGE_SHIFT; if (npages > WALK_CHUNK) npages = WALK_CHUNK; amap_lookups(&entry->aref, pos - entry->start, anons, npages); for (i = 0; i < npages; i++) { if ((anons[i] == NULL) == absent) continue; if (!absent) { /* going from present to absent: set realend */ realend = pos + (i << PAGE_SHIFT); absent = 1; continue; } /* going from absent to present: invoke callback */ end = pos + (i << PAGE_SHIFT); if (start != end) { error = (*walk)(start, realend, end, prot, 0, nsegment, cookie); if (error) return error; nsegment++; } start = realend = end; absent = 0; } } if (!absent) realend = entry_end; error = (*walk)(start, realend, entry_end, prot, 0, nsegment, cookie); *nsegmentp = nsegment + 1; return error; } /* * Common logic for whether a map entry should be included in a coredump */ static inline int uvm_should_coredump(struct proc *p, struct vm_map_entry *entry) { if (!(entry->protection & PROT_WRITE) && entry->aref.ar_amap == NULL && entry->start != p->p_p->ps_sigcode && entry->start != p->p_p->ps_timekeep) return 0; /* * Skip ranges marked as unreadable, as uiomove(UIO_USERSPACE) * will fail on them. Maybe this really should be a test of * entry->max_protection, but doing * uvm_map_extract(UVM_EXTRACT_FIXPROT) * on each such page would suck. */ if (!(entry->protection & PROT_READ) && entry->start != p->p_p->ps_sigcode) return 0; /* Skip ranges excluded from coredumps. */ if (UVM_ET_ISCONCEAL(entry)) return 0; /* Don't dump mmaped devices. */ if (entry->object.uvm_obj != NULL && UVM_OBJ_IS_DEVICE(entry->object.uvm_obj)) return 0; if (entry->start >= VM_MAXUSER_ADDRESS) return 0; return 1; } /* do nothing callback for uvm_coredump_walk_amap() */ static int noop(vaddr_t start, vaddr_t realend, vaddr_t end, vm_prot_t prot, int isvnode, int nsegment, void *cookie) { return 0; } /* * Walk the VA space for a process to identify what to write to * a coredump. First the number of contiguous ranges is counted, * then the 'setup' callback is invoked to prepare for actually * recording the ranges, then the VA is walked again, invoking * the 'walk' callback for each range. The number of ranges walked * is guaranteed to match the count seen by the 'setup' callback. */ int uvm_coredump_walkmap(struct proc *p, uvm_coredump_setup_cb *setup, uvm_coredump_walk_cb *walk, void *cookie) { struct vmspace *vm = p->p_vmspace; struct vm_map *map = &vm->vm_map; struct vm_map_entry *entry; vaddr_t end; int refed_amaps = 0; int nsegment, error, isvnode; /* * Walk the map once to count the segments. If an amap is * referenced more than once than take *another* reference * and treat the amap as exactly one segment instead of * checking page presence inside it. On the second pass * we'll recognize which amaps we did that for by the ref * count being >1...and decrement it then. */ nsegment = 0; RBT_FOREACH(entry, uvm_map_addr, &map->addr) { /* should never happen for a user process */ if (UVM_ET_ISSUBMAP(entry)) { panic("%s: user process with submap?", __func__); } if (! uvm_should_coredump(p, entry)) continue; if (entry->aref.ar_amap != NULL) { if (entry->aref.ar_amap->am_ref == 1) { uvm_coredump_walk_amap(entry, &nsegment, &noop, cookie); continue; } /* * Multiple refs currently, so take another and * treat it as a single segment */ entry->aref.ar_amap->am_ref++; refed_amaps++; } nsegment++; } /* * Okay, we have a count in nsegment. Prepare to * walk it again, then invoke the setup callback. */ entry = RBT_MIN(uvm_map_addr, &map->addr); error = (*setup)(nsegment, cookie); if (error) goto cleanup; /* * Setup went okay, so do the second walk, invoking the walk * callback on the counted segments and cleaning up references * as we go. */ nsegment = 0; for (; entry != NULL; entry = RBT_NEXT(uvm_map_addr, entry)) { if (! uvm_should_coredump(p, entry)) continue; if (entry->aref.ar_amap != NULL && entry->aref.ar_amap->am_ref == 1) { error = uvm_coredump_walk_amap(entry, &nsegment, walk, cookie); if (error) break; continue; } end = entry->end; if (end > VM_MAXUSER_ADDRESS) end = VM_MAXUSER_ADDRESS; isvnode = (entry->object.uvm_obj != NULL && UVM_OBJ_IS_VNODE(entry->object.uvm_obj)); error = (*walk)(entry->start, end, end, entry->protection, isvnode, nsegment, cookie); if (error) break; nsegment++; if (entry->aref.ar_amap != NULL && entry->aref.ar_amap->am_ref > 1) { /* multiple refs, so we need to drop one */ entry->aref.ar_amap->am_ref--; refed_amaps--; } } if (error) { cleanup: /* clean up the extra references from where we left off */ if (refed_amaps > 0) { for (; entry != NULL; entry = RBT_NEXT(uvm_map_addr, entry)) { if (entry->aref.ar_amap == NULL || entry->aref.ar_amap->am_ref == 1) continue; if (! uvm_should_coredump(p, entry)) continue; entry->aref.ar_amap->am_ref--; if (refed_amaps-- == 0) break; } } } return error; } #endif /* !SMALL_KERNEL */
14 11 4 4 5 9 9 11 11 7 4 4 4 4 4 4 10 10 10 10 10 10 10 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 /* $OpenBSD: pckbc.c,v 1.55 2023/08/26 15:01:00 jmc Exp $ */ /* $NetBSD: pckbc.c,v 1.5 2000/06/09 04:58:35 soda Exp $ */ /* * Copyright (c) 1998 * Matthias Drochner. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/timeout.h> #include <sys/kernel.h> #include <sys/device.h> #include <sys/malloc.h> #include <sys/errno.h> #include <sys/queue.h> #include <machine/bus.h> #include <machine/cpu.h> #include <dev/ic/i8042reg.h> #include <dev/ic/pckbcvar.h> #include "pckbd.h" #if NPCKBD > 0 #include <dev/pckbc/pckbdvar.h> #endif #ifdef PCKBCDEBUG #define DPRINTF(x...) do { printf(x); } while (0); #else #define DPRINTF(x...) #endif /* descriptor for one device command */ struct pckbc_devcmd { TAILQ_ENTRY(pckbc_devcmd) next; int flags; #define KBC_CMDFLAG_SYNC 1 /* give descriptor back to caller */ #define KBC_CMDFLAG_SLOW 2 #define KBC_CMDFLAG_QUEUED 4 /* descriptor on cmdqueue */ u_char cmd[4]; int cmdlen, cmdidx, retries; u_char response[4]; int status, responselen, responseidx; }; /* data per slave device */ struct pckbc_slotdata { int polling; /* don't read data port in interrupt handler */ TAILQ_HEAD(, pckbc_devcmd) cmdqueue; /* active commands */ TAILQ_HEAD(, pckbc_devcmd) freequeue; /* free commands */ #define NCMD 5 struct pckbc_devcmd cmds[NCMD]; }; #define CMD_IN_QUEUE(q) (!TAILQ_EMPTY(&(q)->cmdqueue)) void pckbc_init_slotdata(struct pckbc_slotdata *); int pckbc_attach_slot(struct pckbc_softc *, pckbc_slot_t, int); int pckbc_submatch_locators(struct device *, void *, void *); int pckbc_submatch(struct device *, void *, void *); int pckbcprint(void *, const char *); struct pckbc_internal pckbc_consdata; int pckbc_console_attached; int pckbc_console; static struct pckbc_slotdata pckbc_cons_slotdata; static int pckbc_wait_output(bus_space_tag_t, bus_space_handle_t); static int pckbc_get8042cmd(struct pckbc_internal *); static int pckbc_put8042cmd(struct pckbc_internal *); static int pckbc_send_devcmd(struct pckbc_internal *, pckbc_slot_t, u_char); static void pckbc_poll_cmd1(struct pckbc_internal *, pckbc_slot_t, struct pckbc_devcmd *); void pckbc_cleanqueues(struct pckbc_internal *); void pckbc_cleanqueue(struct pckbc_slotdata *); void pckbc_cleanup(void *); void pckbc_poll(void *); int pckbc_cmdresponse(struct pckbc_internal *, pckbc_slot_t, u_char); void pckbc_start(struct pckbc_internal *, pckbc_slot_t); int pckbcintr_internal(struct pckbc_internal *, struct pckbc_softc *); const char *pckbc_slot_names[] = { "kbd", "aux" }; #define KBC_DEVCMD_ACK 0xfa #define KBC_DEVCMD_RESEND 0xfe #define KBC_DEVCMD_BAT_DONE 0xaa #define KBC_DEVCMD_BAT_FAIL 0xfc #define KBD_DELAY DELAY(8) static inline int pckbc_wait_output(bus_space_tag_t iot, bus_space_handle_t ioh_c) { u_int i; for (i = 100000; i; i--) if (!(bus_space_read_1(iot, ioh_c, 0) & KBS_IBF)) { KBD_DELAY; return (1); } return (0); } int pckbc_send_cmd(bus_space_tag_t iot, bus_space_handle_t ioh_c, u_char val) { if (!pckbc_wait_output(iot, ioh_c)) return (0); bus_space_write_1(iot, ioh_c, 0, val); return (1); } int pckbc_poll_data1(bus_space_tag_t iot, bus_space_handle_t ioh_d, bus_space_handle_t ioh_c, pckbc_slot_t slot, int checkaux) { int i; u_char stat; /* polls for ~100ms */ for (i = 100; i; i--, delay(1000)) { stat = bus_space_read_1(iot, ioh_c, 0); if (stat & KBS_DIB) { register u_char c; KBD_DELAY; CPU_BUSY_CYCLE(); c = bus_space_read_1(iot, ioh_d, 0); if (checkaux && (stat & KBS_AUXDATA)) { if (slot != PCKBC_AUX_SLOT) { DPRINTF("lost aux 0x%x\n", c); continue; } } else { if (slot == PCKBC_AUX_SLOT) { DPRINTF("lost kbd 0x%x\n", c); continue; } else if (stat & KBS_AUXDATA) { DPRINTF("discard aux data 0x%x\n", c); continue; } } return (c); } } return (-1); } /* * Get the current command byte. */ static int pckbc_get8042cmd(struct pckbc_internal *t) { bus_space_tag_t iot = t->t_iot; bus_space_handle_t ioh_d = t->t_ioh_d; bus_space_handle_t ioh_c = t->t_ioh_c; int data; if (!pckbc_send_cmd(iot, ioh_c, K_RDCMDBYTE)) return (0); data = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, t->t_haveaux); if (data == -1) return (0); t->t_cmdbyte = data; return (1); } /* * Pass command byte to keyboard controller (8042). */ static int pckbc_put8042cmd(struct pckbc_internal *t) { bus_space_tag_t iot = t->t_iot; bus_space_handle_t ioh_d = t->t_ioh_d; bus_space_handle_t ioh_c = t->t_ioh_c; if (!pckbc_send_cmd(iot, ioh_c, K_LDCMDBYTE)) return (0); if (!pckbc_wait_output(iot, ioh_c)) return (0); bus_space_write_1(iot, ioh_d, 0, t->t_cmdbyte); return (1); } static int pckbc_send_devcmd(struct pckbc_internal *t, pckbc_slot_t slot, u_char val) { bus_space_tag_t iot = t->t_iot; bus_space_handle_t ioh_d = t->t_ioh_d; bus_space_handle_t ioh_c = t->t_ioh_c; if (slot == PCKBC_AUX_SLOT) { if (!pckbc_send_cmd(iot, ioh_c, KBC_AUXWRITE)) return (0); } if (!pckbc_wait_output(iot, ioh_c)) return (0); bus_space_write_1(iot, ioh_d, 0, val); return (1); } int pckbc_is_console(bus_space_tag_t iot, bus_addr_t addr) { if (pckbc_console && !pckbc_console_attached && pckbc_consdata.t_iot == iot && pckbc_consdata.t_addr == addr) return (1); return (0); } int pckbc_submatch_locators(struct device *parent, void *match, void *aux) { struct cfdata *cf = match; struct pckbc_attach_args *pa = aux; if (cf->cf_loc[PCKBCCF_SLOT] != PCKBCCF_SLOT_DEFAULT && cf->cf_loc[PCKBCCF_SLOT] != pa->pa_slot) return (0); return (1); } int pckbc_submatch(struct device *parent, void *match, void *aux) { struct cfdata *cf = match; if (pckbc_submatch_locators(parent, match, aux) == 0) return (0); return ((*cf->cf_attach->ca_match)(parent, cf, aux)); } int pckbc_attach_slot(struct pckbc_softc *sc, pckbc_slot_t slot, int force) { struct pckbc_internal *t = sc->id; struct pckbc_attach_args pa; int found; pa.pa_tag = t; pa.pa_slot = slot; found = (config_found_sm((struct device *)sc, &pa, pckbcprint, force ? pckbc_submatch_locators : pckbc_submatch) != NULL); if ((found || slot == PCKBC_AUX_SLOT) && !t->t_slotdata[slot]) { t->t_slotdata[slot] = malloc(sizeof(struct pckbc_slotdata), M_DEVBUF, M_NOWAIT); if (t->t_slotdata[slot] == NULL) return 0; pckbc_init_slotdata(t->t_slotdata[slot]); if (!found && slot == PCKBC_AUX_SLOT) { /* * Some machines don't handle disabling the aux slot * completely and still generate data when the mouse is * moved, so setup a dummy interrupt handler to discard * this slot's data. */ pckbc_set_inputhandler(t, PCKBC_AUX_SLOT, NULL, sc, NULL); found = 1; } } return (found); } void pckbc_attach(struct pckbc_softc *sc, int flags) { struct pckbc_internal *t; bus_space_tag_t iot; bus_space_handle_t ioh_d, ioh_c; int haskbd = 0, res; u_char cmdbits = 0; t = sc->id; iot = t->t_iot; ioh_d = t->t_ioh_d; ioh_c = t->t_ioh_c; if (pckbc_console == 0) { timeout_set(&t->t_cleanup, pckbc_cleanup, t); timeout_set(&t->t_poll, pckbc_poll, t); } /* flush */ (void) pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, 0); /* set initial cmd byte */ if (!pckbc_put8042cmd(t)) { #if defined(__i386__) || defined(__amd64__) if (!ISSET(flags, PCKBCF_FORCE_KEYBOARD_PRESENT)) { pckbc_release_console(); return; } #endif printf("kbc: cmd word write error\n"); return; } /* * XXX Don't check the keyboard port. There are broken keyboard controllers * which don't pass the test but work normally otherwise. */ #if 0 /* * check kbd port ok */ if (!pckbc_send_cmd(iot, ioh_c, KBC_KBDTEST)) return; res = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, 0); /* * Normally, we should get a "0" here. * But there are keyboard controllers behaving differently. */ if (res == 0 || res == 0xfa || res == 0x01 || res == 0xab) { #ifdef PCKBCDEBUG if (res != 0) printf("kbc: returned %x on kbd slot test\n", res); #endif if (pckbc_attach_slot(sc, PCKBC_KBD_SLOT, 0)) { cmdbits |= KC8_KENABLE; haskbd = 1; } } else { printf("kbc: kbd port test: %x\n", res); return; } #else if (pckbc_attach_slot(sc, PCKBC_KBD_SLOT, 0)) { cmdbits |= KC8_KENABLE; haskbd = 1; } #endif /* 0 */ /* * Check aux port ok. * Avoid KBC_AUXTEST because it hangs some older controllers * (eg UMC880?). */ if (!pckbc_send_cmd(iot, ioh_c, KBC_AUXECHO)) { printf("kbc: aux echo error 1\n"); goto nomouse; } if (!pckbc_wait_output(iot, ioh_c)) { printf("kbc: aux echo error 2\n"); goto nomouse; } bus_space_write_1(iot, ioh_d, 0, 0x5a); /* a random value */ res = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_AUX_SLOT, 1); if (ISSET(t->t_flags, PCKBC_NEED_AUXWRITE)) { /* * The following code is necessary to find the aux port on the * oqo-1 machine, among others. However if confuses old * (non-ps/2) keyboard controllers (at least UMC880x again). */ if (res == -1) { /* Read of aux echo timed out, try again */ if (!pckbc_send_cmd(iot, ioh_c, KBC_AUXWRITE)) goto nomouse; if (!pckbc_wait_output(iot, ioh_c)) goto nomouse; bus_space_write_1(iot, ioh_d, 0, 0x5a); res = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_AUX_SLOT, 1); DPRINTF("kbc: aux echo: %x\n", res); } } if (res != -1) { /* * In most cases, the 0x5a gets echoed. * Some old controllers (Gateway 2000 circa 1993) * return 0xfe here. * We are satisfied if there is anything in the * aux output buffer. */ DPRINTF("kbc: aux echo: %x\n", res); t->t_haveaux = 1; if (pckbc_attach_slot(sc, PCKBC_AUX_SLOT, 0)) cmdbits |= KC8_MENABLE; } #ifdef PCKBCDEBUG else printf("kbc: aux echo test failed\n"); #endif #if defined(__i386__) || defined(__amd64__) if (haskbd == 0 && !ISSET(flags, PCKBCF_FORCE_KEYBOARD_PRESENT)) { if (t->t_haveaux) { if (pckbc_attach_slot(sc, PCKBC_KBD_SLOT, 1)) cmdbits |= KC8_KENABLE; } else { pckbc_release_console(); } } #endif nomouse: /* enable needed interrupts */ t->t_cmdbyte |= cmdbits; if (!pckbc_put8042cmd(t)) printf("kbc: cmd word write error\n"); } int pckbcprint(void *aux, const char *pnp) { struct pckbc_attach_args *pa = aux; if (!pnp) printf(" (%s slot)", pckbc_slot_names[pa->pa_slot]); return (QUIET); } void pckbc_release_console(void) { #if defined(__i386__) || defined(__amd64__) /* * If there is no keyboard present, yet we are the console, * we might be on a legacy-free PC where the PS/2 emulated * keyboard was elected as console, but went away as soon * as the USB controller drivers attached. * * In that case, we want to release ourselves from console * duties, unless we have been able to attach a mouse, * which would mean this is a real PS/2 controller * after all. */ if (pckbc_console != 0) { extern void wscn_input_init(int); pckbc_console = 0; wscn_input_init(1); } #endif } void pckbc_init_slotdata(struct pckbc_slotdata *q) { int i; TAILQ_INIT(&q->cmdqueue); TAILQ_INIT(&q->freequeue); for (i = 0; i < NCMD; i++) { TAILQ_INSERT_TAIL(&q->freequeue, &(q->cmds[i]), next); } q->polling = 0; } void pckbc_flush(pckbc_tag_t self, pckbc_slot_t slot) { struct pckbc_internal *t = self; (void) pckbc_poll_data1(t->t_iot, t->t_ioh_d, t->t_ioh_c, slot, t->t_haveaux); } int pckbc_poll_data(pckbc_tag_t self, pckbc_slot_t slot) { struct pckbc_internal *t = self; struct pckbc_slotdata *q = t->t_slotdata[slot]; int c; c = pckbc_poll_data1(t->t_iot, t->t_ioh_d, t->t_ioh_c, slot, t->t_haveaux); if (c != -1 && q && CMD_IN_QUEUE(q)) { /* we jumped into a running command - try to deliver the response */ if (pckbc_cmdresponse(t, slot, c)) return (-1); } return (c); } /* * set scancode translation on */ int pckbc_xt_translation(pckbc_tag_t self, int *table) { struct pckbc_internal *t = self; #ifdef __sparc64__ /* only pckbc@ebus on sparc64 uses this */ if ((t->t_flags & PCKBC_CANT_TRANSLATE) != 0) { /* Hardware lacks translation capability. Nothing to do! */ if (t->t_flags & PCKBC_FIXED_SET2) *table = 2; else /* PCKBC_FIXED_SET3 */ *table = 3; return (-1); } #endif if (t->t_cmdbyte & KC8_TRANS) return (0); t->t_cmdbyte |= KC8_TRANS; if (!pckbc_put8042cmd(t)) return (-1); /* read back to be sure */ if (!pckbc_get8042cmd(t)) return (-1); return (t->t_cmdbyte & KC8_TRANS) ? (0) : (-1); } static struct pckbc_portcmd { u_char cmd_en, cmd_dis; } pckbc_portcmd[2] = { { KBC_KBDENABLE, KBC_KBDDISABLE, }, { KBC_AUXENABLE, KBC_AUXDISABLE, } }; void pckbc_slot_enable(pckbc_tag_t self, pckbc_slot_t slot, int on) { struct pckbc_internal *t = (struct pckbc_internal *)self; struct pckbc_portcmd *cmd; cmd = &pckbc_portcmd[slot]; if (!pckbc_send_cmd(t->t_iot, t->t_ioh_c, on ? cmd->cmd_en : cmd->cmd_dis)) printf("pckbc_slot_enable(%d) failed\n", on); if (slot == PCKBC_KBD_SLOT) { if (on) timeout_add_sec(&t->t_poll, 1); else timeout_del(&t->t_poll); } } void pckbc_set_poll(pckbc_tag_t self, pckbc_slot_t slot, int on) { struct pckbc_internal *t = (struct pckbc_internal *)self; t->t_slotdata[slot]->polling = on; if (!on) { int s; /* * If disabling polling on a device that's been configured, * make sure there are no bytes left in the FIFO, holding up * the interrupt line. Otherwise we won't get any further * interrupts. */ if (t->t_sc) { s = spltty(); pckbcintr_internal(t, t->t_sc); splx(s); } } } /* * Pass command to device, poll for ACK and data. * to be called at spltty() */ static void pckbc_poll_cmd1(struct pckbc_internal *t, pckbc_slot_t slot, struct pckbc_devcmd *cmd) { bus_space_tag_t iot = t->t_iot; bus_space_handle_t ioh_d = t->t_ioh_d; bus_space_handle_t ioh_c = t->t_ioh_c; int i, c = 0; while (cmd->cmdidx < cmd->cmdlen) { if (!pckbc_send_devcmd(t, slot, cmd->cmd[cmd->cmdidx])) { printf("pckbc_cmd: send error\n"); cmd->status = EIO; return; } for (i = 10; i; i--) { /* 1s ??? */ c = pckbc_poll_data1(iot, ioh_d, ioh_c, slot, t->t_haveaux); if (c != -1) break; } switch (c) { case KBC_DEVCMD_ACK: cmd->cmdidx++; continue; /* * Some legacy free PCs keep returning Basic Assurance Test * (BAT) instead of something usable, so fail gracefully. */ case KBC_DEVCMD_RESEND: case KBC_DEVCMD_BAT_DONE: case KBC_DEVCMD_BAT_FAIL: DPRINTF("pckbc_cmd: %s\n", c == KBC_DEVCMD_RESEND ? "RESEND": "BAT"); if (cmd->retries++ < 5) continue; DPRINTF("pckbc_cmd: cmd failed\n"); cmd->status = ENXIO; return; case -1: DPRINTF("pckbc_cmd: timeout\n"); cmd->status = EIO; return; default: DPRINTF("pckbc_cmd: lost 0x%x\n", c); } } while (cmd->responseidx < cmd->responselen) { if (cmd->flags & KBC_CMDFLAG_SLOW) i = 100; /* 10s ??? */ else i = 10; /* 1s ??? */ while (i--) { c = pckbc_poll_data1(iot, ioh_d, ioh_c, slot, t->t_haveaux); if (c != -1) break; } if (c == -1) { DPRINTF("pckbc_cmd: no data\n"); cmd->status = ETIMEDOUT; return; } else cmd->response[cmd->responseidx++] = c; } } /* for use in autoconfiguration */ int pckbc_poll_cmd(pckbc_tag_t self, pckbc_slot_t slot, u_char *cmd, int len, int responselen, u_char *respbuf, int slow) { struct pckbc_devcmd nc; if ((len > 4) || (responselen > 4)) return (EINVAL); bzero(&nc, sizeof(nc)); memcpy(nc.cmd, cmd, len); nc.cmdlen = len; nc.responselen = responselen; nc.flags = (slow ? KBC_CMDFLAG_SLOW : 0); pckbc_poll_cmd1(self, slot, &nc); if (nc.status == 0 && respbuf) memcpy(respbuf, nc.response, responselen); return (nc.status); } /* * Clean up a command queue, throw away everything. */ void pckbc_cleanqueue(struct pckbc_slotdata *q) { struct pckbc_devcmd *cmd; #ifdef PCKBCDEBUG int i; #endif while ((cmd = TAILQ_FIRST(&q->cmdqueue))) { TAILQ_REMOVE(&q->cmdqueue, cmd, next); cmd->flags &= ~KBC_CMDFLAG_QUEUED; #ifdef PCKBCDEBUG printf("pckbc_cleanqueue: removing"); for (i = 0; i < cmd->cmdlen; i++) printf(" %02x", cmd->cmd[i]); printf("\n"); #endif /* * A synchronous command on the cmdqueue is currently owned by a * sleeping proc. The same proc is responsible for putting it * back on the freequeue once awake. */ if (cmd->flags & KBC_CMDFLAG_SYNC) continue; TAILQ_INSERT_TAIL(&q->freequeue, cmd, next); } } void pckbc_cleanqueues(struct pckbc_internal *t) { if (t->t_slotdata[PCKBC_KBD_SLOT]) pckbc_cleanqueue(t->t_slotdata[PCKBC_KBD_SLOT]); if (t->t_slotdata[PCKBC_AUX_SLOT]) pckbc_cleanqueue(t->t_slotdata[PCKBC_AUX_SLOT]); } /* * Timeout error handler: clean queues and data port. * XXX could be less invasive. */ void pckbc_cleanup(void *self) { struct pckbc_internal *t = self; int s; printf("pckbc: command timeout\n"); s = spltty(); pckbc_cleanqueues(t); while (bus_space_read_1(t->t_iot, t->t_ioh_c, 0) & KBS_DIB) { KBD_DELAY; (void) bus_space_read_1(t->t_iot, t->t_ioh_d, 0); } /* reset KBC? */ splx(s); } /* * Stop the keyboard controller when we are going to suspend */ void pckbc_stop(struct pckbc_softc *sc) { struct pckbc_internal *t = sc->id; timeout_del(&t->t_poll); pckbc_cleanqueues(t); timeout_del(&t->t_cleanup); } /* * Reset the keyboard controller in a violent fashion; normally done * after suspend/resume when we do not trust the machine. */ void pckbc_reset(struct pckbc_softc *sc) { struct pckbc_internal *t = sc->id; bus_space_tag_t iot = t->t_iot; bus_space_handle_t ioh_d = t->t_ioh_d, ioh_c = t->t_ioh_c; pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, 0); /* KBC selftest */ if (pckbc_send_cmd(iot, ioh_c, KBC_SELFTEST) == 0) return; pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, 0); (void)pckbc_put8042cmd(t); pckbcintr_internal(t->t_sc->id, t->t_sc); } /* * Pass command to device during normal operation. * to be called at spltty() */ void pckbc_start(struct pckbc_internal *t, pckbc_slot_t slot) { struct pckbc_slotdata *q = t->t_slotdata[slot]; struct pckbc_devcmd *cmd = TAILQ_FIRST(&q->cmdqueue); if (q->polling) { do { pckbc_poll_cmd1(t, slot, cmd); if (cmd->status) printf("pckbc_start: command error\n"); TAILQ_REMOVE(&q->cmdqueue, cmd, next); cmd->flags &= ~KBC_CMDFLAG_QUEUED; if (cmd->flags & KBC_CMDFLAG_SYNC) { wakeup(cmd); } else { timeout_del(&t->t_cleanup); TAILQ_INSERT_TAIL(&q->freequeue, cmd, next); } cmd = TAILQ_FIRST(&q->cmdqueue); } while (cmd); return; } if (!pckbc_send_devcmd(t, slot, cmd->cmd[cmd->cmdidx])) { printf("pckbc_start: send error\n"); /* XXX what now? */ return; } } /* * Handle command responses coming in asynchronously, * return nonzero if valid response. * to be called at spltty() */ int pckbc_cmdresponse(struct pckbc_internal *t, pckbc_slot_t slot, u_char data) { struct pckbc_slotdata *q = t->t_slotdata[slot]; struct pckbc_devcmd *cmd = TAILQ_FIRST(&q->cmdqueue); #ifdef DIAGNOSTIC if (!cmd) panic("pckbc_cmdresponse: no active command"); #endif if (cmd->cmdidx < cmd->cmdlen) { if (data != KBC_DEVCMD_ACK && data != KBC_DEVCMD_RESEND) return (0); if (data == KBC_DEVCMD_RESEND) { if (cmd->retries++ < 5) { /* try again last command */ goto restart; } else { DPRINTF("pckbc: cmd failed\n"); cmd->status = ENXIO; /* dequeue */ } } else { if (++cmd->cmdidx < cmd->cmdlen) goto restart; if (cmd->responselen) return (1); /* else dequeue */ } } else if (cmd->responseidx < cmd->responselen) { cmd->response[cmd->responseidx++] = data; if (cmd->responseidx < cmd->responselen) return (1); /* else dequeue */ } else return (0); /* dequeue: */ TAILQ_REMOVE(&q->cmdqueue, cmd, next); cmd->flags &= ~KBC_CMDFLAG_QUEUED; if (cmd->flags & KBC_CMDFLAG_SYNC) { wakeup(cmd); } else { timeout_del(&t->t_cleanup); TAILQ_INSERT_TAIL(&q->freequeue, cmd, next); } cmd = TAILQ_FIRST(&q->cmdqueue); if (cmd == NULL) return (1); restart: pckbc_start(t, slot); return (1); } /* * Put command into the device's command queue, return zero or errno. */ int pckbc_enqueue_cmd(pckbc_tag_t self, pckbc_slot_t slot, u_char *cmd, int len, int responselen, int sync, u_char *respbuf) { struct pckbc_internal *t = self; struct pckbc_slotdata *q = t->t_slotdata[slot]; struct pckbc_devcmd *nc; int s, isactive, res = 0; if ((len > 4) || (responselen > 4)) return (EINVAL); s = spltty(); nc = TAILQ_FIRST(&q->freequeue); if (nc) { TAILQ_REMOVE(&q->freequeue, nc, next); } splx(s); if (!nc) return (ENOMEM); bzero(nc, sizeof(*nc)); memcpy(nc->cmd, cmd, len); nc->cmdlen = len; nc->responselen = responselen; nc->flags = (sync ? KBC_CMDFLAG_SYNC : 0); s = spltty(); if (q->polling && sync) { /* * XXX We should poll until the queue is empty. * But we don't come here normally, so make * it simple and throw away everything. */ pckbc_cleanqueue(q); } isactive = CMD_IN_QUEUE(q); nc->flags |= KBC_CMDFLAG_QUEUED; TAILQ_INSERT_TAIL(&q->cmdqueue, nc, next); if (!isactive) pckbc_start(t, slot); if (q->polling) res = (sync ? nc->status : 0); else if (sync) { if ((res = tsleep_nsec(nc, 0, "kbccmd", SEC_TO_NSEC(1)))) { pckbc_cleanup(t); } else { /* * Under certain circumstances, such as during suspend, * tsleep() becomes a no-op and the command is left on * the cmdqueue. */ if (nc->flags & KBC_CMDFLAG_QUEUED) { TAILQ_REMOVE(&q->cmdqueue, nc, next); nc->flags &= ~KBC_CMDFLAG_QUEUED; } res = nc->status; } } else timeout_add_sec(&t->t_cleanup, 1); if (sync) { if (respbuf) memcpy(respbuf, nc->response, responselen); TAILQ_INSERT_TAIL(&q->freequeue, nc, next); } splx(s); return (res); } void pckbc_set_inputhandler(pckbc_tag_t self, pckbc_slot_t slot, pckbc_inputfcn func, void *arg, char *name) { struct pckbc_internal *t = (struct pckbc_internal *)self; struct pckbc_softc *sc = t->t_sc; if (slot >= PCKBC_NSLOTS) panic("pckbc_set_inputhandler: bad slot %d", slot); sc->inputhandler[slot] = func; sc->inputarg[slot] = arg; sc->subname[slot] = name; if (pckbc_console && slot == PCKBC_KBD_SLOT) timeout_add_sec(&t->t_poll, 1); } void pckbc_poll(void *v) { struct pckbc_internal *t = v; int s; s = spltty(); (void)pckbcintr_internal(t, t->t_sc); timeout_add_sec(&t->t_poll, 1); splx(s); } int pckbcintr(void *vsc) { struct pckbc_softc *sc = (struct pckbc_softc *)vsc; return (pckbcintr_internal(sc->id, sc)); } int pckbcintr_internal(struct pckbc_internal *t, struct pckbc_softc *sc) { u_char stat; pckbc_slot_t slot; struct pckbc_slotdata *q; int served = 0, data; /* reschedule timeout further into the idle times */ if (timeout_pending(&t->t_poll)) timeout_add_sec(&t->t_poll, 1); for(;;) { stat = bus_space_read_1(t->t_iot, t->t_ioh_c, 0); if (!(stat & KBS_DIB)) break; served = 1; slot = (t->t_haveaux && (stat & KBS_AUXDATA)) ? PCKBC_AUX_SLOT : PCKBC_KBD_SLOT; q = t->t_slotdata[slot]; if (!q) { /* XXX do something for live insertion? */ #ifdef PCKBCDEBUG printf("pckbcintr: no dev for slot %d\n", slot); #endif KBD_DELAY; (void) bus_space_read_1(t->t_iot, t->t_ioh_d, 0); continue; } if (q->polling) break; /* pckbc_poll_data() will get it */ KBD_DELAY; data = bus_space_read_1(t->t_iot, t->t_ioh_d, 0); if (CMD_IN_QUEUE(q) && pckbc_cmdresponse(t, slot, data)) continue; if (sc != NULL) { if (sc->inputhandler[slot]) (*sc->inputhandler[slot])(sc->inputarg[slot], data); #ifdef PCKBCDEBUG else printf("pckbcintr: slot %d lost %d\n", slot, data); #endif } } return (served); } int pckbc_cnattach(bus_space_tag_t iot, bus_addr_t addr, bus_size_t cmd_offset, int flags) { bus_space_handle_t ioh_d, ioh_c; int res = 0; if (bus_space_map(iot, addr + KBDATAP, 1, 0, &ioh_d)) return (ENXIO); if (bus_space_map(iot, addr + cmd_offset, 1, 0, &ioh_c)) { bus_space_unmap(iot, ioh_d, 1); return (ENXIO); } pckbc_consdata.t_iot = iot; pckbc_consdata.t_ioh_d = ioh_d; pckbc_consdata.t_ioh_c = ioh_c; pckbc_consdata.t_addr = addr; pckbc_consdata.t_flags = flags; timeout_set(&pckbc_consdata.t_cleanup, pckbc_cleanup, &pckbc_consdata); timeout_set(&pckbc_consdata.t_poll, pckbc_poll, &pckbc_consdata); /* flush */ (void) pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, 0); /* selftest? */ /* init cmd byte, enable ports */ pckbc_consdata.t_cmdbyte = KC8_CPU; if (!pckbc_put8042cmd(&pckbc_consdata)) { printf("kbc: cmd word write error\n"); res = EIO; } if (!res) { #if (NPCKBD > 0) res = pckbd_cnattach(&pckbc_consdata); #else res = ENXIO; #endif /* NPCKBD > 0 */ } if (res) { bus_space_unmap(iot, pckbc_consdata.t_ioh_d, 1); bus_space_unmap(iot, pckbc_consdata.t_ioh_c, 1); } else { pckbc_consdata.t_slotdata[PCKBC_KBD_SLOT] = &pckbc_cons_slotdata; pckbc_init_slotdata(&pckbc_cons_slotdata); pckbc_console = 1; } return (res); } struct cfdriver pckbc_cd = { NULL, "pckbc", DV_DULL };
2 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 /* $OpenBSD: kern_kthread.c,v 1.46 2021/11/26 04:42:13 visa Exp $ */ /* $NetBSD: kern_kthread.c,v 1.3 1998/12/22 21:21:36 kleink Exp $ */ /*- * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, * NASA Ames Research Center. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/kthread.h> #include <sys/proc.h> #include <sys/malloc.h> #include <sys/queue.h> int kthread_create_now; /* * Fork a kernel thread. Any process can request this to be done. * The VM space and limits, etc. will be shared with proc0. */ int kthread_create(void (*func)(void *), void *arg, struct proc **newpp, const char *name) { struct proc *p; int error; KERNEL_LOCK(); /* * First, create the new process. Share the memory, file * descriptors and don't leave the exit status around for the * parent to wait for. */ error = fork1(&proc0, FORK_SHAREVM|FORK_SHAREFILES|FORK_NOZOMBIE| FORK_SYSTEM, func, arg, NULL, &p); if (error) { KERNEL_UNLOCK(); return (error); } /* Name it as specified. */ strlcpy(p->p_p->ps_comm, name, sizeof p->p_p->ps_comm); KERNEL_UNLOCK(); /* All done! */ if (newpp != NULL) *newpp = p; return (0); } /* * Cause a kernel thread to exit. Assumes the exiting thread is the * current context. */ void kthread_exit(int ecode) { /* * XXX What do we do with the exit code? Should we even bother * XXX with it? The parent (proc0) isn't going to do much with * XXX it. */ if (ecode != 0) printf("WARNING: thread `%s' (%d) exits with status %d\n", curproc->p_p->ps_comm, curproc->p_tid, ecode); exit1(curproc, ecode, 0, EXIT_NORMAL); /* NOTREACHED */ } struct kthread_q { SIMPLEQ_ENTRY(kthread_q) kq_q; void (*kq_func)(void *); void *kq_arg; }; SIMPLEQ_HEAD(, kthread_q) kthread_q = SIMPLEQ_HEAD_INITIALIZER(kthread_q); /* * Defer the creation of a kernel thread. Once the standard kernel threads * and processes have been created, this queue will be run to callback to * the caller to create threads for e.g. file systems and device drivers. */ void kthread_create_deferred(void (*func)(void *), void *arg) { struct kthread_q *kq; if (kthread_create_now) { (*func)(arg); return; } kq = malloc(sizeof *kq, M_TEMP, M_NOWAIT|M_ZERO); if (kq == NULL) panic("unable to allocate kthread_q"); kq->kq_func = func; kq->kq_arg = arg; SIMPLEQ_INSERT_TAIL(&kthread_q, kq, kq_q); } void kthread_run_deferred_queue(void) { struct kthread_q *kq; /* No longer need to defer kthread creation. */ kthread_create_now = 1; while ((kq = SIMPLEQ_FIRST(&kthread_q)) != NULL) { SIMPLEQ_REMOVE_HEAD(&kthread_q, kq_q); (*kq->kq_func)(kq->kq_arg); free(kq, M_TEMP, sizeof(*kq)); } }
23 23 23 23 23 9 20 4 17 6 6 8 6 8 7 1 7 6 4 4 2 157 156 21 145 143 146 146 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 /* $OpenBSD: ufs_bmap.c,v 1.37 2021/12/12 09:14:59 visa Exp $ */ /* $NetBSD: ufs_bmap.c,v 1.3 1996/02/09 22:36:00 christos Exp $ */ /* * Copyright (c) 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ufs_bmap.c 8.6 (Berkeley) 1/21/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/buf.h> #include <sys/proc.h> #include <sys/vnode.h> #include <sys/mount.h> #include <sys/specdev.h> #include <ufs/ufs/quota.h> #include <ufs/ufs/inode.h> #include <ufs/ufs/ufsmount.h> #include <ufs/ufs/ufs_extern.h> /* * Bmap converts a the logical block number of a file to its physical block * number on the disk. The conversion is done by using the logical block * number to index into the array of block pointers described by the dinode. */ int ufs_bmap(void *v) { struct vop_bmap_args *ap = v; /* * Check for underlying vnode requests and ensure that logical * to physical mapping is requested. */ if (ap->a_vpp != NULL) *ap->a_vpp = VTOI(ap->a_vp)->i_devvp; if (ap->a_bnp == NULL) return (0); return (ufs_bmaparray(ap->a_vp, ap->a_bn, ap->a_bnp, NULL, NULL, ap->a_runp)); } /* * Indirect blocks are now on the vnode for the file. They are given negative * logical block numbers. Indirect blocks are addressed by the negative * address of the first data block to which they point. Double indirect blocks * are addressed by one less than the address of the first indirect block to * which they point. Triple indirect blocks are addressed by one less than * the address of the first double indirect block to which they point. * * ufs_bmaparray does the bmap conversion, and if requested returns the * array of logical blocks which must be traversed to get to a block. * Each entry contains the offset into that block that gets you to the * next block and the disk address of the block (if it is assigned). */ int ufs_bmaparray(struct vnode *vp, daddr_t bn, daddr_t *bnp, struct indir *ap, int *nump, int *runp) { struct inode *ip; struct buf *bp; struct ufsmount *ump; struct mount *mp; struct vnode *devvp; struct indir a[NIADDR+1], *xap; daddr_t daddr, metalbn; int error, maxrun = 0, num; ip = VTOI(vp); mp = vp->v_mount; ump = VFSTOUFS(mp); #ifdef DIAGNOSTIC if ((ap != NULL && nump == NULL) || (ap == NULL && nump != NULL)) panic("ufs_bmaparray: invalid arguments"); #endif if (runp) { /* * XXX * If MAXBSIZE is the largest transfer the disks can handle, * we probably want maxrun to be 1 block less so that we * don't create a block larger than the device can handle. */ *runp = 0; maxrun = MAXBSIZE / mp->mnt_stat.f_iosize - 1; } xap = ap == NULL ? a : ap; if (!nump) nump = &num; if ((error = ufs_getlbns(vp, bn, xap, nump)) != 0) return (error); num = *nump; if (num == 0) { *bnp = blkptrtodb(ump, DIP(ip, db[bn])); if (*bnp == 0) *bnp = -1; else if (runp) for (++bn; bn < NDADDR && *runp < maxrun && is_sequential(ump, DIP(ip, db[bn - 1]), DIP(ip, db[bn])); ++bn, ++*runp); return (0); } /* Get disk address out of indirect block array */ daddr = DIP(ip, ib[xap->in_off]); devvp = VFSTOUFS(vp->v_mount)->um_devvp; for (bp = NULL, ++xap; --num; ++xap) { /* * Exit the loop if there is no disk address assigned yet and * the indirect block isn't in the cache, or if we were * looking for an indirect block and we've found it. */ metalbn = xap->in_lbn; if ((daddr == 0 && !incore(vp, metalbn)) || metalbn == bn) break; /* * If we get here, we've either got the block in the cache * or we have a disk address for it, go fetch it. */ if (bp) brelse(bp); xap->in_exists = 1; bp = getblk(vp, metalbn, mp->mnt_stat.f_iosize, 0, INFSLP); if (bp->b_flags & (B_DONE | B_DELWRI)) { ; } #ifdef DIAGNOSTIC else if (!daddr) panic("ufs_bmaparray: indirect block not in cache"); #endif else { bp->b_blkno = blkptrtodb(ump, daddr); bp->b_flags |= B_READ; bcstats.pendingreads++; bcstats.numreads++; VOP_STRATEGY(bp->b_vp, bp); curproc->p_ru.ru_inblock++; /* XXX */ if ((error = biowait(bp)) != 0) { brelse(bp); return (error); } } #ifdef FFS2 if (ip->i_ump->um_fstype == UM_UFS2) { daddr = ((int64_t *)bp->b_data)[xap->in_off]; if (num == 1 && daddr && runp) for (bn = xap->in_off + 1; bn < MNINDIR(ump) && *runp < maxrun && is_sequential(ump, ((int64_t *)bp->b_data)[bn - 1], ((int64_t *)bp->b_data)[bn]); ++bn, ++*runp); continue; } #endif /* FFS2 */ daddr = ((int32_t *)bp->b_data)[xap->in_off]; if (num == 1 && daddr && runp) for (bn = xap->in_off + 1; bn < MNINDIR(ump) && *runp < maxrun && is_sequential(ump, ((int32_t *)bp->b_data)[bn - 1], ((int32_t *)bp->b_data)[bn]); ++bn, ++*runp); } if (bp) brelse(bp); daddr = blkptrtodb(ump, daddr); *bnp = daddr == 0 ? -1 : daddr; return (0); } /* * Create an array of logical block number/offset pairs which represent the * path of indirect blocks required to access a data block. The first "pair" * contains the logical block number of the appropriate single, double or * triple indirect block and the offset into the inode indirect block array. * Note, the logical block number of the inode single/double/triple indirect * block appears twice in the array, once with the offset into the i_ffs_ib and * once with the offset into the page itself. */ int ufs_getlbns(struct vnode *vp, daddr_t bn, struct indir *ap, int *nump) { daddr_t metalbn, realbn; struct ufsmount *ump; int64_t blockcnt; int i, numlevels, off; ump = VFSTOUFS(vp->v_mount); if (nump) *nump = 0; numlevels = 0; realbn = bn; if (bn < 0) bn = -bn; #ifdef DIAGNOSTIC if (realbn < 0 && realbn > -NDADDR) { panic ("ufs_getlbns: Invalid indirect block %lld specified", (long long)realbn); } #endif /* The first NDADDR blocks are direct blocks. */ if (bn < NDADDR) return (0); /* * Determine the number of levels of indirection. After this loop * is done, blockcnt indicates the number of data blocks possible * at the given level of indirection, and NIADDR - i is the number * of levels of indirection needed to locate the requested block. */ for (blockcnt = 1, i = NIADDR, bn -= NDADDR;; i--, bn -= blockcnt) { if (i == 0) return (EFBIG); blockcnt *= MNINDIR(ump); if (bn < blockcnt) break; } /* Calculate the address of the first meta-block. */ if (realbn >= 0) metalbn = -(realbn - bn + NIADDR - i); else metalbn = -(-realbn - bn + NIADDR - i); /* * At each iteration, off is the offset into the bap array which is * an array of disk addresses at the current level of indirection. * The logical block number and the offset in that block are stored * into the argument array. */ ap->in_lbn = metalbn; ap->in_off = off = NIADDR - i; ap->in_exists = 0; ap++; for (++numlevels; i <= NIADDR; i++) { /* If searching for a meta-data block, quit when found. */ if (metalbn == realbn) break; blockcnt /= MNINDIR(ump); off = (bn / blockcnt) % MNINDIR(ump); ++numlevels; ap->in_lbn = metalbn; ap->in_off = off; ap->in_exists = 0; ++ap; metalbn -= -1 + off * blockcnt; } #ifdef DIAGNOSTIC if (realbn < 0 && metalbn != realbn) { panic("ufs_getlbns: indirect block %lld not found", (long long)realbn); } #endif if (nump) *nump = numlevels; return (0); }
1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 /* $OpenBSD: radio.c,v 1.13 2022/04/06 18:59:27 naddy Exp $ */ /* $RuOBSD: radio.c,v 1.7 2001/12/04 06:03:05 tm Exp $ */ /* * Copyright (c) 2001 Maxim Tsyplakov <tm@oganer.net> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* This is /dev/radio driver for OpenBSD */ #include <sys/param.h> #include <sys/systm.h> #include <sys/errno.h> #include <sys/ioctl.h> #include <sys/fcntl.h> #include <sys/device.h> #include <sys/vnode.h> #include <sys/radioio.h> #include <sys/conf.h> #include <dev/audio_if.h> #include <dev/radio_if.h> #include <dev/radiovar.h> int radioprobe(struct device *, void *, void *); void radioattach(struct device *, struct device *, void *); int radiodetach(struct device *, int); int radioactivate(struct device *, int); int radioprint(void *, const char *); const struct cfattach radio_ca = { sizeof(struct radio_softc), radioprobe, radioattach, radiodetach, radioactivate }; struct cfdriver radio_cd = { NULL, "radio", DV_DULL }; int radioprobe(struct device *parent, void *match, void *aux) { struct audio_attach_args *sa = aux; return (sa->type == AUDIODEV_TYPE_RADIO) ? 1 : 0; } void radioattach(struct device *parent, struct device *self, void *aux) { struct radio_softc *sc = (void *) self; struct audio_attach_args *sa = aux; printf("\n"); sc->hw_if = sa->hwif; sc->hw_hdl = sa->hdl; sc->sc_dev = parent; } int radioopen(dev_t dev, int flags, int fmt, struct proc *p) { int unit; struct radio_softc *sc; unit = RADIOUNIT(dev); if (unit >= radio_cd.cd_ndevs || (sc = radio_cd.cd_devs[unit]) == NULL || sc->hw_if == NULL) return (ENXIO); if (sc->hw_if->open != NULL) return (sc->hw_if->open(sc->hw_hdl, flags, fmt, p)); else return (0); } int radioclose(dev_t dev, int flags, int fmt, struct proc *p) { struct radio_softc *sc; sc = radio_cd.cd_devs[RADIOUNIT(dev)]; if (sc->hw_if->close != NULL) return (sc->hw_if->close(sc->hw_hdl, flags, fmt, p)); else return (0); } int radioioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) { struct radio_softc *sc; int unit, error; unit = RADIOUNIT(dev); if (unit >= radio_cd.cd_ndevs || (sc = radio_cd.cd_devs[unit]) == NULL || sc->hw_if == NULL) return (ENXIO); error = EOPNOTSUPP; switch (cmd) { case RIOCGINFO: if (sc->hw_if->get_info) error = (sc->hw_if->get_info)(sc->hw_hdl, (struct radio_info *)data); break; case RIOCSINFO: if (!(flags & FWRITE)) return (EACCES); if (sc->hw_if->set_info) error = (sc->hw_if->set_info)(sc->hw_hdl, (struct radio_info *)data); break; case RIOCSSRCH: if (!(flags & FWRITE)) return (EACCES); if (sc->hw_if->search) error = (sc->hw_if->search)(sc->hw_hdl, *(int *)data); break; default: error = (ENOTTY); } return (error); } /* * Called from hardware driver. This is where the MI radio driver gets * probed/attached to the hardware driver */ struct device * radio_attach_mi(const struct radio_hw_if *rhwp, void *hdlp, struct device *dev) { struct audio_attach_args arg; arg.type = AUDIODEV_TYPE_RADIO; arg.hwif = rhwp; arg.hdl = hdlp; return (config_found(dev, &arg, radioprint)); } int radioprint(void *aux, const char *pnp) { if (pnp != NULL) printf("radio at %s", pnp); return (UNCONF); } int radiodetach(struct device *self, int flags) { /*struct radio_softc *sc = (struct radio_softc *)self;*/ int maj, mn; /* locate the major number */ for (maj = 0; maj < nchrdev; maj++) if (cdevsw[maj].d_open == radioopen) break; /* Nuke the vnodes for any open instances (calls close). */ mn = self->dv_unit; vdevgone(maj, mn, mn, VCHR); return (0); } int radioactivate(struct device *self, int act) { struct radio_softc *sc = (struct radio_softc *)self; switch (act) { case DVACT_DEACTIVATE: sc->sc_dying = 1; break; } return (0); }
1121 1119 46 46 46 46 45 545 588 587 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 /* $OpenBSD: uvm_anon.c,v 1.58 2024/04/06 10:59:52 mpi Exp $ */ /* $NetBSD: uvm_anon.c,v 1.10 2000/11/25 06:27:59 chs Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * uvm_anon.c: uvm anon ops */ #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/pool.h> #include <sys/kernel.h> #include <sys/atomic.h> #include <uvm/uvm.h> #include <uvm/uvm_swap.h> struct pool uvm_anon_pool; void uvm_anon_init(void) { pool_init(&uvm_anon_pool, sizeof(struct vm_anon), 0, IPL_MPFLOOR, PR_WAITOK, "anonpl", NULL); pool_sethiwat(&uvm_anon_pool, uvmexp.free / 16); } /* * uvm_analloc: allocate a new anon. * * => anon will have no lock associated. */ struct vm_anon * uvm_analloc(void) { struct vm_anon *anon; anon = pool_get(&uvm_anon_pool, PR_NOWAIT); if (anon) { anon->an_lock = NULL; anon->an_ref = 1; anon->an_page = NULL; anon->an_swslot = 0; } return anon; } /* * uvm_anfree_list: free a single anon structure * * => anon must be removed from the amap (if anon was in an amap). * => amap must be locked, if anon was owned by amap. * => we may lock the pageq's. */ void uvm_anfree_list(struct vm_anon *anon, struct pglist *pgl) { struct vm_page *pg = anon->an_page; KASSERT(anon->an_lock == NULL || rw_write_held(anon->an_lock)); KASSERT(anon->an_ref == 0); /* * Dispose of the page, if it is resident. */ if (pg != NULL) { KASSERT(anon->an_lock != NULL); /* * If the page is busy, mark it as PG_RELEASED, so * that uvm_anon_release(9) would release it later. */ if ((pg->pg_flags & PG_BUSY) != 0) { atomic_setbits_int(&pg->pg_flags, PG_RELEASED); rw_obj_hold(anon->an_lock); return; } pmap_page_protect(pg, PROT_NONE); if (pgl != NULL) { /* * clean page, and put it on pglist * for later freeing. */ uvm_lock_pageq(); uvm_pageclean(pg); uvm_unlock_pageq(); TAILQ_INSERT_HEAD(pgl, pg, pageq); } else { uvm_lock_pageq(); /* lock out pagedaemon */ uvm_pagefree(pg); /* bye bye */ uvm_unlock_pageq(); /* free the daemon */ } } else { if (anon->an_swslot != 0 && anon->an_swslot != SWSLOT_BAD) { /* This page is no longer only in swap. */ KASSERT(uvmexp.swpgonly > 0); atomic_dec_int(&uvmexp.swpgonly); } } anon->an_lock = NULL; /* * Free any swap resources, leave a page replacement hint. */ uvm_anon_dropswap(anon); KASSERT(anon->an_page == NULL); KASSERT(anon->an_swslot == 0); pool_put(&uvm_anon_pool, anon); } /* * uvm_anwait: wait for memory to become available to allocate an anon. */ void uvm_anwait(void) { struct vm_anon *anon; /* XXX: Want something like pool_wait()? */ anon = pool_get(&uvm_anon_pool, PR_WAITOK); pool_put(&uvm_anon_pool, anon); } /* * uvm_anon_pagein: fetch an anon's page. * * => anon must be locked, and is unlocked upon return. * => returns true if pagein was aborted due to lack of memory. */ boolean_t uvm_anon_pagein(struct vm_amap *amap, struct vm_anon *anon) { struct vm_page *pg; int rv; KASSERT(rw_write_held(anon->an_lock)); KASSERT(anon->an_lock == amap->am_lock); /* * Get the page of the anon. */ rv = uvmfault_anonget(NULL, amap, anon); switch (rv) { case VM_PAGER_OK: KASSERT(rw_write_held(anon->an_lock)); break; case VM_PAGER_ERROR: case VM_PAGER_REFAULT: /* * Nothing more to do on errors. * VM_PAGER_REFAULT means that the anon was freed. */ return FALSE; default: #ifdef DIAGNOSTIC panic("anon_pagein: uvmfault_anonget -> %d", rv); #else return FALSE; #endif } /* * Mark the page as dirty and clear its swslot. */ pg = anon->an_page; if (anon->an_swslot > 0) { uvm_swap_free(anon->an_swslot, 1); } anon->an_swslot = 0; atomic_clearbits_int(&pg->pg_flags, PG_CLEAN); /* * Deactivate the page (to put it on a page queue). */ pmap_clear_reference(pg); pmap_page_protect(pg, PROT_NONE); uvm_lock_pageq(); uvm_pagedeactivate(pg); uvm_unlock_pageq(); rw_exit(anon->an_lock); return FALSE; } /* * uvm_anon_dropswap: release any swap resources from this anon. * * => anon must be locked or have a reference count of 0. */ void uvm_anon_dropswap(struct vm_anon *anon) { KASSERT(anon->an_ref == 0 || rw_lock_held(anon->an_lock)); if (anon->an_swslot == 0) return; uvm_swap_free(anon->an_swslot, 1); anon->an_swslot = 0; } /* * uvm_anon_release: release an anon and its page. * * => anon should not have any references. * => anon must be locked. */ void uvm_anon_release(struct vm_anon *anon) { struct vm_page *pg = anon->an_page; struct rwlock *lock; KASSERT(rw_write_held(anon->an_lock)); KASSERT(pg != NULL); KASSERT((pg->pg_flags & PG_RELEASED) != 0); KASSERT((pg->pg_flags & PG_BUSY) != 0); KASSERT(pg->uobject == NULL); KASSERT(pg->uanon == anon); KASSERT(anon->an_ref == 0); uvm_lock_pageq(); pmap_page_protect(pg, PROT_NONE); uvm_pagefree(pg); uvm_unlock_pageq(); KASSERT(anon->an_page == NULL); lock = anon->an_lock; uvm_anon_dropswap(anon); pool_put(&uvm_anon_pool, anon); rw_exit(lock); /* Note: extra reference is held for PG_RELEASED case. */ rw_obj_free(lock); }
25 2 23 34 2 32 31 2 29 236 1148 60 620 553 68 180 73 40 57 52 54 1 70 67 49 40 68 74 66 50 34 169 46 44 44 44 37 43 54 48 22 3 52 38 48 34 62 49 45 40 40 55 49 43 57 75 1 48 58 36 16 5 8 31 9 19 5 17 50 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 /* $OpenBSD: bpf_filter.c,v 1.34 2020/08/03 03:21:24 dlg Exp $ */ /* $NetBSD: bpf_filter.c,v 1.12 1996/02/13 22:00:00 christos Exp $ */ /* * Copyright (c) 1990, 1991, 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from the Stanford/CMU enet packet filter, * (net/enet.c) distributed as part of 4.3BSD, and code contributed * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence * Berkeley Laboratory. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)bpf_filter.c 8.1 (Berkeley) 6/10/93 */ #include <sys/param.h> #include <sys/time.h> #ifndef _KERNEL #include <stdlib.h> #include <string.h> #include "pcap.h" #else #include <sys/systm.h> #endif #include <sys/endian.h> #ifdef _KERNEL extern int bpf_maxbufsize; #define Static #else /* _KERNEL */ #define Static static #endif /* _KERNEL */ #include <net/bpf.h> struct bpf_mem { const u_char *pkt; u_int len; }; Static u_int32_t bpf_mem_ldw(const void *, u_int32_t, int *); Static u_int32_t bpf_mem_ldh(const void *, u_int32_t, int *); Static u_int32_t bpf_mem_ldb(const void *, u_int32_t, int *); static const struct bpf_ops bpf_mem_ops = { bpf_mem_ldw, bpf_mem_ldh, bpf_mem_ldb, }; Static u_int32_t bpf_mem_ldw(const void *mem, u_int32_t k, int *err) { const struct bpf_mem *bm = mem; u_int32_t v; *err = 1; if (k + sizeof(v) > bm->len) return (0); memcpy(&v, bm->pkt + k, sizeof(v)); *err = 0; return ntohl(v); } Static u_int32_t bpf_mem_ldh(const void *mem, u_int32_t k, int *err) { const struct bpf_mem *bm = mem; u_int16_t v; *err = 1; if (k + sizeof(v) > bm->len) return (0); memcpy(&v, bm->pkt + k, sizeof(v)); *err = 0; return ntohs(v); } Static u_int32_t bpf_mem_ldb(const void *mem, u_int32_t k, int *err) { const struct bpf_mem *bm = mem; *err = 1; if (k >= bm->len) return (0); *err = 0; return bm->pkt[k]; } /* * Execute the filter program starting at pc on the packet p * wirelen is the length of the original packet * buflen is the amount of data present */ u_int bpf_filter(const struct bpf_insn *pc, const u_char *pkt, u_int wirelen, u_int buflen) { struct bpf_mem bm; bm.pkt = pkt; bm.len = buflen; return _bpf_filter(pc, &bpf_mem_ops, &bm, wirelen); } u_int _bpf_filter(const struct bpf_insn *pc, const struct bpf_ops *ops, const void *pkt, u_int wirelen) { u_int32_t A = 0, X = 0; u_int32_t k; int32_t mem[BPF_MEMWORDS]; int err; if (pc == NULL) { /* * No filter means accept all. */ return (u_int)-1; } memset(mem, 0, sizeof(mem)); --pc; while (1) { ++pc; switch (pc->code) { default: #ifdef _KERNEL return 0; #else abort(); #endif case BPF_RET|BPF_K: return (u_int)pc->k; case BPF_RET|BPF_A: return (u_int)A; case BPF_LD|BPF_W|BPF_ABS: A = ops->ldw(pkt, pc->k, &err); if (err != 0) return 0; continue; case BPF_LD|BPF_H|BPF_ABS: A = ops->ldh(pkt, pc->k, &err); if (err != 0) return 0; continue; case BPF_LD|BPF_B|BPF_ABS: A = ops->ldb(pkt, pc->k, &err); if (err != 0) return 0; continue; case BPF_LD|BPF_W|BPF_LEN: A = wirelen; continue; case BPF_LDX|BPF_W|BPF_LEN: X = wirelen; continue; case BPF_LD|BPF_W|BPF_RND: A = arc4random(); continue; case BPF_LD|BPF_W|BPF_IND: k = X + pc->k; A = ops->ldw(pkt, k, &err); if (err != 0) return 0; continue; case BPF_LD|BPF_H|BPF_IND: k = X + pc->k; A = ops->ldh(pkt, k, &err); if (err != 0) return 0; continue; case BPF_LD|BPF_B|BPF_IND: k = X + pc->k; A = ops->ldb(pkt, k, &err); if (err != 0) return 0; continue; case BPF_LDX|BPF_MSH|BPF_B: X = ops->ldb(pkt, pc->k, &err); if (err != 0) return 0; X &= 0xf; X <<= 2; continue; case BPF_LD|BPF_IMM: A = pc->k; continue; case BPF_LDX|BPF_IMM: X = pc->k; continue; case BPF_LD|BPF_MEM: A = mem[pc->k]; continue; case BPF_LDX|BPF_MEM: X = mem[pc->k]; continue; case BPF_ST: mem[pc->k] = A; continue; case BPF_STX: mem[pc->k] = X; continue; case BPF_JMP|BPF_JA: pc += pc->k; continue; case BPF_JMP|BPF_JGT|BPF_K: pc += (A > pc->k) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JGE|BPF_K: pc += (A >= pc->k) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JEQ|BPF_K: pc += (A == pc->k) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JSET|BPF_K: pc += (A & pc->k) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JGT|BPF_X: pc += (A > X) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JGE|BPF_X: pc += (A >= X) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JEQ|BPF_X: pc += (A == X) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JSET|BPF_X: pc += (A & X) ? pc->jt : pc->jf; continue; case BPF_ALU|BPF_ADD|BPF_X: A += X; continue; case BPF_ALU|BPF_SUB|BPF_X: A -= X; continue; case BPF_ALU|BPF_MUL|BPF_X: A *= X; continue; case BPF_ALU|BPF_DIV|BPF_X: if (X == 0) return 0; A /= X; continue; case BPF_ALU|BPF_AND|BPF_X: A &= X; continue; case BPF_ALU|BPF_OR|BPF_X: A |= X; continue; case BPF_ALU|BPF_LSH|BPF_X: A <<= X; continue; case BPF_ALU|BPF_RSH|BPF_X: A >>= X; continue; case BPF_ALU|BPF_ADD|BPF_K: A += pc->k; continue; case BPF_ALU|BPF_SUB|BPF_K: A -= pc->k; continue; case BPF_ALU|BPF_MUL|BPF_K: A *= pc->k; continue; case BPF_ALU|BPF_DIV|BPF_K: A /= pc->k; continue; case BPF_ALU|BPF_AND|BPF_K: A &= pc->k; continue; case BPF_ALU|BPF_OR|BPF_K: A |= pc->k; continue; case BPF_ALU|BPF_LSH|BPF_K: A <<= pc->k; continue; case BPF_ALU|BPF_RSH|BPF_K: A >>= pc->k; continue; case BPF_ALU|BPF_NEG: A = -A; continue; case BPF_MISC|BPF_TAX: X = A; continue; case BPF_MISC|BPF_TXA: A = X; continue; } } } #ifdef _KERNEL /* * Return true if the 'fcode' is a valid filter program. * The constraints are that each jump be forward and to a valid * code and memory operations use valid addresses. The code * must terminate with either an accept or reject. * * The kernel needs to be able to verify an application's filter code. * Otherwise, a bogus program could easily crash the system. */ int bpf_validate(struct bpf_insn *f, int len) { u_int i, from; struct bpf_insn *p; if (len < 1 || len > BPF_MAXINSNS) return 0; for (i = 0; i < len; ++i) { p = &f[i]; switch (BPF_CLASS(p->code)) { /* * Check that memory operations use valid addresses. */ case BPF_LD: case BPF_LDX: switch (BPF_MODE(p->code)) { case BPF_IMM: break; case BPF_ABS: case BPF_IND: case BPF_MSH: /* * More strict check with actual packet length * is done runtime. */ if (p->k >= bpf_maxbufsize) return 0; break; case BPF_MEM: if (p->k >= BPF_MEMWORDS) return 0; break; case BPF_LEN: case BPF_RND: break; default: return 0; } break; case BPF_ST: case BPF_STX: if (p->k >= BPF_MEMWORDS) return 0; break; case BPF_ALU: switch (BPF_OP(p->code)) { case BPF_ADD: case BPF_SUB: case BPF_MUL: case BPF_OR: case BPF_AND: case BPF_LSH: case BPF_RSH: case BPF_NEG: break; case BPF_DIV: /* * Check for constant division by 0. */ if (BPF_SRC(p->code) == BPF_K && p->k == 0) return 0; break; default: return 0; } break; case BPF_JMP: /* * Check that jumps are forward, and within * the code block. */ from = i + 1; switch (BPF_OP(p->code)) { case BPF_JA: if (from + p->k < from || from + p->k >= len) return 0; break; case BPF_JEQ: case BPF_JGT: case BPF_JGE: case BPF_JSET: if (from + p->jt >= len || from + p->jf >= len) return 0; break; default: return 0; } break; case BPF_RET: break; case BPF_MISC: break; default: return 0; } } return BPF_CLASS(f[len - 1].code) == BPF_RET; } #endif
10 111 492 18 2 3 2 2 3 452 19 98 98 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 /* $OpenBSD: sys_socket.c,v 1.65 2024/04/30 17:59:15 mvs Exp $ */ /* $NetBSD: sys_socket.c,v 1.13 1995/08/12 23:59:09 mycroft Exp $ */ /* * Copyright (c) 1982, 1986, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)sys_socket.c 8.1 (Berkeley) 6/10/93 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/file.h> #include <sys/proc.h> #include <sys/mbuf.h> #include <sys/protosw.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/fcntl.h> #include <net/if.h> const struct fileops socketops = { .fo_read = soo_read, .fo_write = soo_write, .fo_ioctl = soo_ioctl, .fo_kqfilter = soo_kqfilter, .fo_stat = soo_stat, .fo_close = soo_close }; int soo_read(struct file *fp, struct uio *uio, int fflags) { struct socket *so = (struct socket *)fp->f_data; int flags = 0; if (fp->f_flag & FNONBLOCK) flags |= MSG_DONTWAIT; return (soreceive(so, NULL, uio, NULL, NULL, &flags, 0)); } int soo_write(struct file *fp, struct uio *uio, int fflags) { struct socket *so = (struct socket *)fp->f_data; int flags = 0; if (fp->f_flag & FNONBLOCK) flags |= MSG_DONTWAIT; return (sosend(so, NULL, uio, NULL, NULL, flags)); } int soo_ioctl(struct file *fp, u_long cmd, caddr_t data, struct proc *p) { struct socket *so = (struct socket *)fp->f_data; switch (cmd) { case FIONBIO: break; case FIOASYNC: solock(so); mtx_enter(&so->so_rcv.sb_mtx); mtx_enter(&so->so_snd.sb_mtx); if (*(int *)data) { so->so_rcv.sb_flags |= SB_ASYNC; so->so_snd.sb_flags |= SB_ASYNC; } else { so->so_rcv.sb_flags &= ~SB_ASYNC; so->so_snd.sb_flags &= ~SB_ASYNC; } mtx_leave(&so->so_snd.sb_mtx); mtx_leave(&so->so_rcv.sb_mtx); sounlock(so); break; case FIONREAD: *(int *)data = so->so_rcv.sb_datacc; break; case FIOSETOWN: case SIOCSPGRP: case TIOCSPGRP: return sigio_setown(&so->so_sigio, cmd, data); case FIOGETOWN: case SIOCGPGRP: case TIOCGPGRP: sigio_getown(&so->so_sigio, cmd, data); break; case SIOCATMARK: *(int *)data = (so->so_rcv.sb_state & SS_RCVATMARK) != 0; break; default: /* * Interface/routing/protocol specific ioctls: * interface and routing ioctls should have a * different entry since a socket's unnecessary */ if (IOCGROUP(cmd) == 'i') return ifioctl(so, cmd, data, p); if (IOCGROUP(cmd) == 'r') return (EOPNOTSUPP); return pru_control(so, cmd, data, NULL); } return (0); } int soo_stat(struct file *fp, struct stat *ub, struct proc *p) { struct socket *so = fp->f_data; memset(ub, 0, sizeof (*ub)); ub->st_mode = S_IFSOCK; solock_shared(so); mtx_enter(&so->so_rcv.sb_mtx); if ((so->so_rcv.sb_state & SS_CANTRCVMORE) == 0 || so->so_rcv.sb_cc != 0) ub->st_mode |= S_IRUSR | S_IRGRP | S_IROTH; mtx_leave(&so->so_rcv.sb_mtx); if ((so->so_snd.sb_state & SS_CANTSENDMORE) == 0) ub->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH; ub->st_uid = so->so_euid; ub->st_gid = so->so_egid; (void)pru_sense(so, ub); sounlock_shared(so); return (0); } int soo_close(struct file *fp, struct proc *p) { int flags, error = 0; if (fp->f_data) { flags = (fp->f_flag & FNONBLOCK) ? MSG_DONTWAIT : 0; error = soclose(fp->f_data, flags); } fp->f_data = NULL; return (error); }
408 213 265 161 158 262 261 63 291 292 12 12 13 13 111 106 7 94 6 90 748 748 400 259 401 746 130 128 129 130 129 5 31 104 130 102 96 6 3 3 1 1 1 4 100 40 63 39 37 2 37 97 26 32 2 1 29 3 2 30 3 29 29 2 30 32 86 37 37 37 31 1 4 34 40 38 2 38 2 11 35 38 38 38 31 12 38 37 1 14 2 12 6 6 6 6 6 65 36 1 10 4 7 29 65 35 12 19 4 6 20 1 1 19 32 22 44 4 6 2 6 2 28 2 30 19 1 2 3 8 9 9 5 3 8 42 5 46 46 5 7 19 19 19 19 6 2 4 7 6 2 10 1 8 2 7 18 3 15 2815 2809 2793 183 176 18 5 176 5 201 1379 130 118 32 6 2 21 10 14 61 31 31 31 28 2 1 31 22 13 10 1 13 28 28 26 2 17 8 16 16 5 5 1 5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 /* $OpenBSD: ufs_vnops.c,v 1.162 2024/05/13 11:17:41 semarie Exp $ */ /* $NetBSD: ufs_vnops.c,v 1.18 1996/05/11 18:28:04 mycroft Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ufs_vnops.c 8.14 (Berkeley) 10/26/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/namei.h> #include <sys/resourcevar.h> #include <sys/kernel.h> #include <sys/fcntl.h> #include <sys/file.h> #include <sys/stat.h> #include <sys/buf.h> #include <sys/proc.h> #include <sys/mount.h> #include <sys/vnode.h> #include <sys/malloc.h> #include <sys/pool.h> #include <sys/dirent.h> #include <sys/lockf.h> #include <sys/event.h> #include <sys/specdev.h> #include <sys/unistd.h> #include <miscfs/fifofs/fifo.h> #include <ufs/ufs/quota.h> #include <ufs/ufs/inode.h> #include <ufs/ufs/dir.h> #include <ufs/ufs/ufsmount.h> #include <ufs/ufs/ufs_extern.h> #ifdef UFS_DIRHASH #include <ufs/ufs/dirhash.h> #endif #include <ufs/ext2fs/ext2fs_extern.h> #include <uvm/uvm_extern.h> int ufs_chmod(struct vnode *, int, struct ucred *); int ufs_chown(struct vnode *, uid_t, gid_t, struct ucred *); int filt_ufsread(struct knote *, long); int filt_ufswrite(struct knote *, long); int filt_ufsvnode(struct knote *, long); void filt_ufsdetach(struct knote *); /* * A virgin directory (no blushing please). */ static const struct dirtemplate mastertemplate = { 0, 12, DT_DIR, 1, ".", 0, DIRBLKSIZ - 12, DT_DIR, 2, ".." }; /* * Update the times in the inode */ void ufs_itimes(struct vnode *vp) { struct inode *ip; struct timespec ts; ip = VTOI(vp); if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) == 0) return; if (vp->v_mount->mnt_flag & MNT_RDONLY) goto out; #ifdef EXT2FS if (IS_EXT2_VNODE(ip->i_vnode)) { EXT2FS_ITIMES(ip); goto out; } #endif if ((vp->v_type == VBLK || vp->v_type == VCHR)) ip->i_flag |= IN_LAZYMOD; else ip->i_flag |= IN_MODIFIED; getnanotime(&ts); if (ip->i_flag & IN_ACCESS) { DIP_ASSIGN(ip, atime, ts.tv_sec); DIP_ASSIGN(ip, atimensec, ts.tv_nsec); } if (ip->i_flag & IN_UPDATE) { DIP_ASSIGN(ip, mtime, ts.tv_sec); DIP_ASSIGN(ip, mtimensec, ts.tv_nsec); } if (ip->i_flag & IN_CHANGE) { DIP_ASSIGN(ip, ctime, ts.tv_sec); DIP_ASSIGN(ip, ctimensec, ts.tv_nsec); ip->i_modrev++; } out: ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE); } /* * Create a regular file */ int ufs_create(void *v) { struct vop_create_args *ap = v; int error; error = ufs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode), ap->a_dvp, ap->a_vpp, ap->a_cnp); if (error == 0) VN_KNOTE(ap->a_dvp, NOTE_WRITE); return (error); } /* * Mknod vnode call */ int ufs_mknod(void *v) { struct vop_mknod_args *ap = v; struct vattr *vap = ap->a_vap; struct vnode **vpp = ap->a_vpp; struct inode *ip; int error; if ((error = ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode), ap->a_dvp, vpp, ap->a_cnp)) != 0) return (error); VN_KNOTE(ap->a_dvp, NOTE_WRITE); ip = VTOI(*vpp); ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; if (vap->va_rdev != VNOVAL) { /* * Want to be able to use this to make badblock * inodes, so don't truncate the dev number. */ DIP_ASSIGN(ip, rdev, vap->va_rdev); } /* * Remove inode so that it will be reloaded by VFS_VGET and * checked to see if it is an alias of an existing entry in * the inode cache. */ vput(*vpp); (*vpp)->v_type = VNON; vgone(*vpp); *vpp = NULL; return (0); } /* * Open called. * * Nothing to do. */ int ufs_open(void *v) { struct vop_open_args *ap = v; struct inode *ip = VTOI(ap->a_vp); /* * Files marked append-only must be opened for appending. */ if ((DIP(ip, flags) & APPEND) && (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE) return (EPERM); if (ap->a_mode & O_TRUNC) ip->i_flag |= IN_CHANGE | IN_UPDATE; return (0); } /* * Close called. * * Update the times on the inode. */ int ufs_close(void *v) { struct vop_close_args *ap = v; struct vnode *vp = ap->a_vp; if (vp->v_usecount > 1) ufs_itimes(vp); return (0); } int ufs_access(void *v) { struct vop_access_args *ap = v; struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); mode_t mode = ap->a_mode; /* * Disallow write attempts on read-only file systems; * unless the file is a socket, fifo, or a block or * character device resident on the file system. */ if (mode & VWRITE) { switch (vp->v_type) { int error; case VDIR: case VLNK: case VREG: if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); if ((error = getinoquota(ip)) != 0) return (error); break; case VBAD: case VBLK: case VCHR: case VSOCK: case VFIFO: case VNON: break; } } /* If immutable bit set, nobody gets to write it. */ if ((mode & VWRITE) && (DIP(ip, flags) & IMMUTABLE)) return (EPERM); if (vnoperm(vp)) { /* For VEXEC, at least one of the execute bits must be set. */ if ((mode & VEXEC) && vp->v_type != VDIR && (DIP(ip, mode) & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0) return EACCES; return 0; } return (vaccess(vp->v_type, DIP(ip, mode), DIP(ip, uid), DIP(ip, gid), mode, ap->a_cred)); } int ufs_getattr(void *v) { struct vop_getattr_args *ap = v; struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); struct vattr *vap = ap->a_vap; ufs_itimes(vp); /* * Copy from inode table */ vap->va_fsid = ip->i_dev; vap->va_fileid = ip->i_number; vap->va_mode = DIP(ip, mode) & ~IFMT; vap->va_nlink = ip->i_effnlink; vap->va_uid = DIP(ip, uid); vap->va_gid = DIP(ip, gid); vap->va_rdev = (dev_t) DIP(ip, rdev); vap->va_size = DIP(ip, size); vap->va_atime.tv_sec = DIP(ip, atime); vap->va_atime.tv_nsec = DIP(ip, atimensec); vap->va_mtime.tv_sec = DIP(ip, mtime); vap->va_mtime.tv_nsec = DIP(ip, mtimensec); vap->va_ctime.tv_sec = DIP(ip, ctime); vap->va_ctime.tv_nsec = DIP(ip, ctimensec); vap->va_flags = DIP(ip, flags); vap->va_gen = DIP(ip, gen); /* this doesn't belong here */ if (vp->v_type == VBLK) vap->va_blocksize = BLKDEV_IOSIZE; else if (vp->v_type == VCHR) vap->va_blocksize = MAXBSIZE; else vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize; vap->va_bytes = dbtob((u_quad_t) DIP(ip, blocks)); vap->va_type = vp->v_type; vap->va_filerev = ip->i_modrev; return (0); } /* * Set attribute vnode op. called from several syscalls */ int ufs_setattr(void *v) { struct vop_setattr_args *ap = v; struct vattr *vap = ap->a_vap; struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); struct ucred *cred = ap->a_cred; int error; long hint = NOTE_ATTRIB; u_quad_t oldsize; /* * Check for unsettable attributes. */ if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) || (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) || ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) { return (EINVAL); } if (vap->va_flags != VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); if (cred->cr_uid != DIP(ip, uid) && !vnoperm(vp) && (error = suser_ucred(cred))) return (error); if (cred->cr_uid == 0 || vnoperm(vp)) { if ((DIP(ip, flags) & (SF_IMMUTABLE | SF_APPEND)) && securelevel > 0) return (EPERM); DIP_ASSIGN(ip, flags, vap->va_flags); } else { if (DIP(ip, flags) & (SF_IMMUTABLE | SF_APPEND) || (vap->va_flags & UF_SETTABLE) != vap->va_flags) return (EPERM); DIP_AND(ip, flags, SF_SETTABLE); DIP_OR(ip, flags, vap->va_flags & UF_SETTABLE); } ip->i_flag |= IN_CHANGE; if (vap->va_flags & (IMMUTABLE | APPEND)) return (0); } if (DIP(ip, flags) & (IMMUTABLE | APPEND)) return (EPERM); /* * Go through the fields and update if not VNOVAL. */ if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); error = ufs_chown(vp, vap->va_uid, vap->va_gid, cred); if (error) return (error); } if (vap->va_size != VNOVAL) { oldsize = DIP(ip, size); /* * Disallow write attempts on read-only file systems; * unless the file is a socket, fifo, or a block or * character device resident on the file system. */ switch (vp->v_type) { case VDIR: return (EISDIR); case VLNK: case VREG: if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); break; default: break; } if ((error = UFS_TRUNCATE(ip, vap->va_size, 0, cred)) != 0) return (error); if (vap->va_size < oldsize) hint |= NOTE_TRUNCATE; } if ((vap->va_vaflags & VA_UTIMES_CHANGE) || vap->va_atime.tv_nsec != VNOVAL || vap->va_mtime.tv_nsec != VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); if (cred->cr_uid != DIP(ip, uid) && !vnoperm(vp) && (error = suser_ucred(cred)) && ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || (error = VOP_ACCESS(vp, VWRITE, cred, ap->a_p)))) return (error); if (vap->va_mtime.tv_nsec != VNOVAL) ip->i_flag |= IN_CHANGE | IN_UPDATE; else if (vap->va_vaflags & VA_UTIMES_CHANGE) ip->i_flag |= IN_CHANGE; if (vap->va_atime.tv_nsec != VNOVAL) { if (!(vp->v_mount->mnt_flag & MNT_NOATIME) || (ip->i_flag & (IN_CHANGE | IN_UPDATE))) ip->i_flag |= IN_ACCESS; } ufs_itimes(vp); if (vap->va_mtime.tv_nsec != VNOVAL) { DIP_ASSIGN(ip, mtime, vap->va_mtime.tv_sec); DIP_ASSIGN(ip, mtimensec, vap->va_mtime.tv_nsec); } if (vap->va_atime.tv_nsec != VNOVAL) { DIP_ASSIGN(ip, atime, vap->va_atime.tv_sec); DIP_ASSIGN(ip, atimensec, vap->va_atime.tv_nsec); } error = UFS_UPDATE(ip, 0); if (error) return (error); } error = 0; if (vap->va_mode != (mode_t)VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); error = ufs_chmod(vp, (int)vap->va_mode, cred); } VN_KNOTE(vp, hint); return (error); } /* * Change the mode on a file. * Inode must be locked before calling. */ int ufs_chmod(struct vnode *vp, int mode, struct ucred *cred) { struct inode *ip = VTOI(vp); int error; if (cred->cr_uid != DIP(ip, uid) && !vnoperm(vp) && (error = suser_ucred(cred))) return (error); if (cred->cr_uid && !vnoperm(vp)) { if (vp->v_type != VDIR && (mode & S_ISTXT)) return (EFTYPE); if (!groupmember(DIP(ip, gid), cred) && (mode & ISGID)) return (EPERM); } DIP_AND(ip, mode, ~ALLPERMS); DIP_OR(ip, mode, mode & ALLPERMS); ip->i_flag |= IN_CHANGE; if ((vp->v_flag & VTEXT) && (DIP(ip, mode) & S_ISTXT) == 0) (void) uvm_vnp_uncache(vp); return (0); } /* * Perform chown operation on inode ip; * inode must be locked prior to call. */ int ufs_chown(struct vnode *vp, uid_t uid, gid_t gid, struct ucred *cred) { struct inode *ip = VTOI(vp); uid_t ouid; gid_t ogid; int error = 0; daddr_t change; enum ufs_quota_flags quota_flags = 0; if (uid == (uid_t)VNOVAL) uid = DIP(ip, uid); if (gid == (gid_t)VNOVAL) gid = DIP(ip, gid); /* * If we don't own the file, are trying to change the owner * of the file, or are not a member of the target group, * the caller must be superuser or the call fails. */ if ((cred->cr_uid != DIP(ip, uid) || uid != DIP(ip, uid) || (gid != DIP(ip, gid) && !groupmember(gid, cred))) && !vnoperm(vp) && (error = suser_ucred(cred))) return (error); ogid = DIP(ip, gid); ouid = DIP(ip, uid); change = DIP(ip, blocks); if (ouid == uid) quota_flags |= UFS_QUOTA_NOUID; if (ogid == gid) quota_flags |= UFS_QUOTA_NOGID; if ((error = getinoquota(ip)) != 0) return (error); (void) ufs_quota_free_blocks2(ip, change, cred, quota_flags); (void) ufs_quota_free_inode2(ip, cred, quota_flags); (void) ufs_quota_delete(ip); DIP_ASSIGN(ip, gid, gid); DIP_ASSIGN(ip, uid, uid); if ((error = getinoquota(ip)) != 0) goto error; if ((error = ufs_quota_alloc_blocks2(ip, change, cred, quota_flags)) != 0) goto error; if ((error = ufs_quota_alloc_inode2(ip, cred , quota_flags)) != 0) { (void)ufs_quota_free_blocks2(ip, change, cred, quota_flags); goto error; } if (getinoquota(ip)) panic("chown: lost quota"); if (ouid != uid || ogid != gid) ip->i_flag |= IN_CHANGE; if (!vnoperm(vp)) { if (ouid != uid && cred->cr_uid != 0) DIP_AND(ip, mode, ~ISUID); if (ogid != gid && cred->cr_uid != 0) DIP_AND(ip, mode, ~ISGID); } return (0); error: (void) ufs_quota_delete(ip); DIP_ASSIGN(ip, gid, ogid); DIP_ASSIGN(ip, uid, ouid); if (getinoquota(ip) == 0) { (void) ufs_quota_alloc_blocks2(ip, change, cred, quota_flags | UFS_QUOTA_FORCE); (void) ufs_quota_alloc_inode2(ip, cred, quota_flags | UFS_QUOTA_FORCE); (void) getinoquota(ip); } return (error); } int ufs_ioctl(void *v) { #if 0 struct vop_ioctl_args *ap = v; #endif return (ENOTTY); } int ufs_remove(void *v) { struct vop_remove_args *ap = v; struct inode *ip; struct vnode *vp = ap->a_vp; struct vnode *dvp = ap->a_dvp; int error; ip = VTOI(vp); if (vp->v_type == VDIR || (DIP(ip, flags) & (IMMUTABLE | APPEND)) || (DIP(VTOI(dvp), flags) & APPEND)) { error = EPERM; goto out; } error = ufs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0); VN_KNOTE(vp, NOTE_DELETE); VN_KNOTE(dvp, NOTE_WRITE); out: return (error); } /* * link vnode call */ int ufs_link(void *v) { struct vop_link_args *ap = v; struct vnode *dvp = ap->a_dvp; struct vnode *vp = ap->a_vp; struct componentname *cnp = ap->a_cnp; struct inode *ip; struct direct newdir; int error; #ifdef DIAGNOSTIC if ((cnp->cn_flags & HASBUF) == 0) panic("ufs_link: no name"); #endif if (dvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE))) { VOP_ABORTOP(dvp, cnp); goto out2; } ip = VTOI(vp); if ((nlink_t) DIP(ip, nlink) >= LINK_MAX) { VOP_ABORTOP(dvp, cnp); error = EMLINK; goto out1; } if (DIP(ip, flags) & (IMMUTABLE | APPEND)) { VOP_ABORTOP(dvp, cnp); error = EPERM; goto out1; } ip->i_effnlink++; DIP_ADD(ip, nlink, 1); ip->i_flag |= IN_CHANGE; if ((error = UFS_UPDATE(ip, 1)) == 0) { ufs_makedirentry(ip, cnp, &newdir); error = ufs_direnter(dvp, vp, &newdir, cnp, NULL); } if (error) { ip->i_effnlink--; DIP_ADD(ip, nlink, -1); ip->i_flag |= IN_CHANGE; } pool_put(&namei_pool, cnp->cn_pnbuf); VN_KNOTE(vp, NOTE_LINK); VN_KNOTE(dvp, NOTE_WRITE); out1: if (dvp != vp) VOP_UNLOCK(vp); out2: vput(dvp); return (error); } /* * Rename system call. * rename("foo", "bar"); * is essentially * unlink("bar"); * link("foo", "bar"); * unlink("foo"); * but ``atomically''. Can't do full commit without saving state in the * inode on disk which isn't feasible at this time. Best we can do is * always guarantee the target exists. * * Basic algorithm is: * * 1) Bump link count on source while we're linking it to the * target. This also ensure the inode won't be deleted out * from underneath us while we work (it may be truncated by * a concurrent `trunc' or `open' for creation). * 2) Link source to destination. If destination already exists, * delete it first. * 3) Unlink source reference to inode if still around. If a * directory was moved and the parent of the destination * is different from the source, patch the ".." entry in the * directory. */ int ufs_rename(void *v) { struct vop_rename_args *ap = v; struct vnode *tvp = ap->a_tvp; struct vnode *tdvp = ap->a_tdvp; struct vnode *fvp = ap->a_fvp; struct vnode *fdvp = ap->a_fdvp; struct componentname *tcnp = ap->a_tcnp; struct componentname *fcnp = ap->a_fcnp; struct inode *ip, *xp, *dp; struct direct newdir; int doingdirectory = 0, oldparent = 0, newparent = 0; int error = 0; #ifdef DIAGNOSTIC if ((tcnp->cn_flags & HASBUF) == 0 || (fcnp->cn_flags & HASBUF) == 0) panic("ufs_rename: no name"); #endif /* * Check for cross-device rename. */ if ((fvp->v_mount != tdvp->v_mount) || (tvp && (fvp->v_mount != tvp->v_mount))) { error = EXDEV; abortit: VOP_ABORTOP(tdvp, tcnp); if (tdvp == tvp) vrele(tdvp); else vput(tdvp); if (tvp) vput(tvp); VOP_ABORTOP(fdvp, fcnp); vrele(fdvp); vrele(fvp); return (error); } if (tvp && ((DIP(VTOI(tvp), flags) & (IMMUTABLE | APPEND)) || (DIP(VTOI(tdvp), flags) & APPEND))) { error = EPERM; goto abortit; } /* * Check if just deleting a link name or if we've lost a race. * If another process completes the same rename after we've looked * up the source and have blocked looking up the target, then the * source and target inodes may be identical now although the * names were never linked. */ if (fvp == tvp) { if (fvp->v_type == VDIR) { /* * Linked directories are impossible, so we must * have lost the race. Pretend that the rename * completed before the lookup. */ error = ENOENT; goto abortit; } /* Release destination completely. */ VOP_ABORTOP(tdvp, tcnp); vput(tdvp); vput(tvp); /* * Delete source. There is another race now that everything * is unlocked, but this doesn't cause any new complications. * relookup() may find a file that is unrelated to the * original one, or it may fail. Too bad. */ vrele(fvp); fcnp->cn_flags &= ~MODMASK; fcnp->cn_flags |= LOCKPARENT | LOCKLEAF; if ((fcnp->cn_flags & SAVESTART) == 0) panic("ufs_rename: lost from startdir"); fcnp->cn_nameiop = DELETE; if ((error = vfs_relookup(fdvp, &fvp, fcnp)) != 0) return (error); /* relookup did vrele() */ vrele(fdvp); return (VOP_REMOVE(fdvp, fvp, fcnp)); } if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0) goto abortit; /* fvp, tdvp, tvp now locked */ dp = VTOI(fdvp); ip = VTOI(fvp); if ((nlink_t) DIP(ip, nlink) >= LINK_MAX) { VOP_UNLOCK(fvp); error = EMLINK; goto abortit; } if ((DIP(ip, flags) & (IMMUTABLE | APPEND)) || (DIP(dp, flags) & APPEND)) { VOP_UNLOCK(fvp); error = EPERM; goto abortit; } if ((DIP(ip, mode) & IFMT) == IFDIR) { error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc); if (!error && tvp) error = VOP_ACCESS(tvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc); if (error) { VOP_UNLOCK(fvp); error = EACCES; goto abortit; } /* * Avoid ".", "..", and aliases of "." for obvious reasons. */ if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') || dp == ip || (fcnp->cn_flags & ISDOTDOT) || (tcnp->cn_flags & ISDOTDOT) || (ip->i_flag & IN_RENAME)) { VOP_UNLOCK(fvp); error = EINVAL; goto abortit; } ip->i_flag |= IN_RENAME; oldparent = dp->i_number; doingdirectory = 1; } VN_KNOTE(fdvp, NOTE_WRITE); /* XXX right place? */ /* * When the target exists, both the directory * and target vnodes are returned locked. */ dp = VTOI(tdvp); xp = NULL; if (tvp) xp = VTOI(tvp); /* * 1) Bump link count while we're moving stuff * around. If we crash somewhere before * completing our work, the link count * may be wrong, but correctable. */ ip->i_effnlink++; DIP_ADD(ip, nlink, 1); ip->i_flag |= IN_CHANGE; if ((error = UFS_UPDATE(ip, 1)) != 0) { VOP_UNLOCK(fvp); goto bad; } /* * If ".." must be changed (ie the directory gets a new * parent) then the source directory must not be in the * directory hierarchy above the target, as this would * orphan everything below the source directory. Also * the user must have write permission in the source so * as to be able to change "..". We must repeat the call * to namei, as the parent directory is unlocked by the * call to checkpath(). */ error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc); VOP_UNLOCK(fvp); /* tdvp and tvp locked */ if (oldparent != dp->i_number) newparent = dp->i_number; if (doingdirectory && newparent) { if (error) /* write access check above */ goto bad; if (xp != NULL) vput(tvp); /* * Compensate for the reference ufs_checkpath() loses. */ vref(tdvp); /* Only tdvp is locked */ if ((error = ufs_checkpath(ip, dp, tcnp->cn_cred)) != 0) { vrele(tdvp); goto out; } if ((tcnp->cn_flags & SAVESTART) == 0) panic("ufs_rename: lost to startdir"); if ((error = vfs_relookup(tdvp, &tvp, tcnp)) != 0) goto out; vrele(tdvp); /* relookup() acquired a reference */ dp = VTOI(tdvp); xp = NULL; if (tvp) xp = VTOI(tvp); } /* * 2) If target doesn't exist, link the target * to the source and unlink the source. * Otherwise, rewrite the target directory * entry to reference the source inode and * expunge the original entry's existence. */ if (xp == NULL) { if (dp->i_dev != ip->i_dev) panic("rename: EXDEV"); /* * Account for ".." in new directory. * When source and destination have the same * parent we don't fool with the link count. */ if (doingdirectory && newparent) { if ((nlink_t) DIP(dp, nlink) >= LINK_MAX) { error = EMLINK; goto bad; } dp->i_effnlink++; DIP_ADD(dp, nlink, 1); dp->i_flag |= IN_CHANGE; if ((error = UFS_UPDATE(dp, 1)) != 0) { dp->i_effnlink--; DIP_ADD(dp, nlink, -1); dp->i_flag |= IN_CHANGE; goto bad; } } ufs_makedirentry(ip, tcnp, &newdir); if ((error = ufs_direnter(tdvp, NULL, &newdir, tcnp, NULL)) != 0) { if (doingdirectory && newparent) { dp->i_effnlink--; DIP_ADD(dp, nlink, -1); dp->i_flag |= IN_CHANGE; (void)UFS_UPDATE(dp, 1); } goto bad; } VN_KNOTE(tdvp, NOTE_WRITE); vput(tdvp); } else { if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev) panic("rename: EXDEV"); /* * Short circuit rename(foo, foo). */ if (xp->i_number == ip->i_number) panic("ufs_rename: same file"); /* * If the parent directory is "sticky", then the user must * own the parent directory, or the destination of the rename, * otherwise the destination may not be changed (except by * root). This implements append-only directories. */ if ((DIP(dp, mode) & S_ISTXT) && tcnp->cn_cred->cr_uid != 0 && tcnp->cn_cred->cr_uid != DIP(dp, uid) && DIP(xp, uid )!= tcnp->cn_cred->cr_uid && !vnoperm(tdvp)) { error = EPERM; goto bad; } /* * Target must be empty if a directory and have no links * to it. Also, ensure source and target are compatible * (both directories, or both not directories). */ if ((DIP(xp, mode) & IFMT) == IFDIR) { if (xp->i_effnlink > 2 || !ufs_dirempty(xp, dp->i_number, tcnp->cn_cred)) { error = ENOTEMPTY; goto bad; } if (!doingdirectory) { error = ENOTDIR; goto bad; } cache_purge(tdvp); } else if (doingdirectory) { error = EISDIR; goto bad; } if ((error = ufs_dirrewrite(dp, xp, ip->i_number, IFTODT(DIP(ip, mode)), (doingdirectory && newparent) ? newparent : doingdirectory)) != 0) goto bad; if (doingdirectory) { if (!newparent) { dp->i_effnlink--; } xp->i_effnlink--; } if (doingdirectory) { /* * Truncate inode. The only stuff left in the directory * is "." and "..". The "." reference is inconsequential * since we are quashing it. We have removed the "." * reference and the reference in the parent directory, * but there may be other hard links. The soft * dependency code will arrange to do these operations * after the parent directory entry has been deleted on * disk, so when running with that code we avoid doing * them now. */ if (!newparent) { DIP_ADD(dp, nlink, -1); dp->i_flag |= IN_CHANGE; } DIP_ADD(xp, nlink, -1); xp->i_flag |= IN_CHANGE; if ((error = UFS_TRUNCATE(VTOI(tvp), (off_t)0, IO_SYNC, tcnp->cn_cred)) != 0) goto bad; } VN_KNOTE(tdvp, NOTE_WRITE); vput(tdvp); VN_KNOTE(tvp, NOTE_DELETE); vput(tvp); xp = NULL; } /* * 3) Unlink the source. */ fcnp->cn_flags &= ~MODMASK; fcnp->cn_flags |= LOCKPARENT | LOCKLEAF; if ((fcnp->cn_flags & SAVESTART) == 0) panic("ufs_rename: lost from startdir"); if ((error = vfs_relookup(fdvp, &fvp, fcnp)) != 0) { vrele(ap->a_fvp); return (error); } vrele(fdvp); if (fvp == NULL) { /* * From name has disappeared. */ if (doingdirectory) panic("ufs_rename: lost dir entry"); vrele(ap->a_fvp); return (0); } xp = VTOI(fvp); dp = VTOI(fdvp); /* * Ensure that the directory entry still exists and has not * changed while the new name has been entered. If the source is * a file then the entry may have been unlinked or renamed. In * either case there is no further work to be done. If the source * is a directory then it cannot have been rmdir'ed; the IN_RENAME * flag ensures that it cannot be moved by another rename or removed * by a rmdir. */ if (xp != ip) { if (doingdirectory) panic("ufs_rename: lost dir entry"); } else { /* * If the source is a directory with a * new parent, the link count of the old * parent directory must be decremented * and ".." set to point to the new parent. */ if (doingdirectory && newparent) { xp->i_offset = mastertemplate.dot_reclen; ufs_dirrewrite(xp, dp, newparent, DT_DIR, 0); cache_purge(fdvp); } error = ufs_dirremove(fdvp, xp, fcnp->cn_flags, 0); xp->i_flag &= ~IN_RENAME; } VN_KNOTE(fvp, NOTE_RENAME); if (dp) vput(fdvp); if (xp) vput(fvp); vrele(ap->a_fvp); return (error); bad: if (xp) vput(ITOV(xp)); vput(ITOV(dp)); out: vrele(fdvp); if (doingdirectory) ip->i_flag &= ~IN_RENAME; if (vn_lock(fvp, LK_EXCLUSIVE) == 0) { ip->i_effnlink--; DIP_ADD(ip, nlink, -1); ip->i_flag |= IN_CHANGE; ip->i_flag &= ~IN_RENAME; vput(fvp); } else vrele(fvp); return (error); } /* * Mkdir system call */ int ufs_mkdir(void *v) { struct vop_mkdir_args *ap = v; struct vnode *dvp = ap->a_dvp; struct vattr *vap = ap->a_vap; struct componentname *cnp = ap->a_cnp; struct inode *ip, *dp; struct vnode *tvp; struct buf *bp; struct direct newdir; struct dirtemplate dirtemplate; int error, dmode; #ifdef DIAGNOSTIC if ((cnp->cn_flags & HASBUF) == 0) panic("ufs_mkdir: no name"); #endif dp = VTOI(dvp); if ((nlink_t) DIP(dp, nlink) >= LINK_MAX) { error = EMLINK; goto out; } dmode = vap->va_mode & 0777; dmode |= IFDIR; /* * Must simulate part of ufs_makeinode here to acquire the inode, * but not have it entered in the parent directory. The entry is * made later after writing "." and ".." entries. */ if ((error = UFS_INODE_ALLOC(dp, dmode, cnp->cn_cred, &tvp)) != 0) goto out; ip = VTOI(tvp); DIP_ASSIGN(ip, uid, cnp->cn_cred->cr_uid); DIP_ASSIGN(ip, gid, DIP(dp, gid)); if ((error = getinoquota(ip)) || (error = ufs_quota_alloc_inode(ip, cnp->cn_cred))) { pool_put(&namei_pool, cnp->cn_pnbuf); UFS_INODE_FREE(ip, ip->i_number, dmode); vput(tvp); vput(dvp); return (error); } ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; DIP_ASSIGN(ip, mode, dmode); tvp->v_type = VDIR; /* Rest init'd in getnewvnode(). */ ip->i_effnlink = 2; DIP_ASSIGN(ip, nlink, 2); /* * Bump link count in parent directory to reflect work done below. * Should be done before reference is create so cleanup is * possible if we crash. */ dp->i_effnlink++; DIP_ADD(dp, nlink, 1); dp->i_flag |= IN_CHANGE; if ((error = UFS_UPDATE(dp, 1)) != 0) goto bad; /* * Initialize directory with "." and ".." from static template. */ dirtemplate = mastertemplate; dirtemplate.dot_ino = ip->i_number; dirtemplate.dotdot_ino = dp->i_number; if ((error = UFS_BUF_ALLOC(ip, (off_t)0, DIRBLKSIZ, cnp->cn_cred, B_CLRBUF, &bp)) != 0) goto bad; DIP_ASSIGN(ip, size, DIRBLKSIZ); ip->i_flag |= IN_CHANGE | IN_UPDATE; uvm_vnp_setsize(tvp, DIP(ip, size)); memcpy(bp->b_data, &dirtemplate, sizeof(dirtemplate)); if ((error = UFS_UPDATE(ip, 1)) != 0) { (void)VOP_BWRITE(bp); goto bad; } /* * Directory set up, now install its entry in the parent directory. * * If we are not doing soft dependencies, then we must write out the * buffer containing the new directory body before entering the new * name in the parent. If we are doing soft dependencies, then the * buffer containing the new directory body will be passed to and * released in the soft dependency code after the code has attached * an appropriate ordering dependency to the buffer which ensures that * the buffer is written before the new name is written in the parent. */ if ((error = VOP_BWRITE(bp)) != 0) goto bad; ufs_makedirentry(ip, cnp, &newdir); error = ufs_direnter(dvp, tvp, &newdir, cnp, bp); bad: if (error == 0) { VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK); *ap->a_vpp = tvp; } else { dp->i_effnlink--; DIP_ADD(dp, nlink, -1); dp->i_flag |= IN_CHANGE; /* * No need to do an explicit VOP_TRUNCATE here, vrele will * do this for us because we set the link count to 0. */ ip->i_effnlink = 0; DIP_ASSIGN(ip, nlink, 0); ip->i_flag |= IN_CHANGE; vput(tvp); } out: pool_put(&namei_pool, cnp->cn_pnbuf); vput(dvp); return (error); } /* * Rmdir system call. */ int ufs_rmdir(void *v) { struct vop_rmdir_args *ap = v; struct vnode *vp = ap->a_vp; struct vnode *dvp = ap->a_dvp; struct componentname *cnp = ap->a_cnp; struct inode *ip, *dp; int error; ip = VTOI(vp); dp = VTOI(dvp); /* * Do not remove a directory that is in the process of being renamed. * Verify the directory is empty (and valid). Rmdir ".." will not be * valid since ".." will contain a reference to the current directory * and thus be non-empty. */ error = 0; if (ip->i_flag & IN_RENAME) { error = EINVAL; goto out; } if (ip->i_effnlink != 2 || !ufs_dirempty(ip, dp->i_number, cnp->cn_cred)) { error = ENOTEMPTY; goto out; } if ((DIP(dp, flags) & APPEND) || (DIP(ip, flags) & (IMMUTABLE | APPEND))) { error = EPERM; goto out; } /* * Delete reference to directory before purging * inode. If we crash in between, the directory * will be reattached to lost+found, */ dp->i_effnlink--; ip->i_effnlink--; if ((error = ufs_dirremove(dvp, ip, cnp->cn_flags, 1)) != 0) { dp->i_effnlink++; ip->i_effnlink++; goto out; } VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK); cache_purge(dvp); /* * Truncate inode. The only stuff left in the directory is "." and * "..". The "." reference is inconsequential since we are quashing * it. */ DIP_ADD(dp, nlink, -1); dp->i_flag |= IN_CHANGE; DIP_ADD(ip, nlink, -1); ip->i_flag |= IN_CHANGE; error = UFS_TRUNCATE(ip, (off_t)0, DOINGASYNC(vp) ? 0 : IO_SYNC, cnp->cn_cred); cache_purge(vp); #ifdef UFS_DIRHASH /* Kill any active hash; i_effnlink == 0, so it will not come back. */ if (ip->i_dirhash != NULL) ufsdirhash_free(ip); #endif out: VN_KNOTE(vp, NOTE_DELETE); vput(dvp); vput(vp); return (error); } /* * symlink -- make a symbolic link */ int ufs_symlink(void *v) { struct vop_symlink_args *ap = v; struct vnode *vp, **vpp = ap->a_vpp; struct inode *ip; int len, error; error = ufs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp, vpp, ap->a_cnp); if (error) { vput(ap->a_dvp); return (error); } VN_KNOTE(ap->a_dvp, NOTE_WRITE); vput(ap->a_dvp); vp = *vpp; ip = VTOI(vp); len = strlen(ap->a_target); if (len < ip->i_ump->um_maxsymlinklen) { memcpy(SHORTLINK(ip), ap->a_target, len); DIP_ASSIGN(ip, size, len); ip->i_flag |= IN_CHANGE | IN_UPDATE; } else error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0, UIO_SYSSPACE, IO_NODELOCKED, ap->a_cnp->cn_cred, NULL, curproc); vput(vp); return (error); } /* * Vnode op for reading directories. * * This routine converts the on-disk struct direct entries to the * struct dirent entries expected by userland and the rest of the kernel. */ int ufs_readdir(void *v) { struct vop_readdir_args *ap = v; struct uio auio, *uio = ap->a_uio; struct iovec aiov; union { struct dirent dn; char __pad[roundup(sizeof(struct dirent), 8)]; } u; off_t off = uio->uio_offset; struct direct *dp; char *edp; caddr_t diskbuf; size_t count, entries; int bufsize, readcnt, error; if (uio->uio_rw != UIO_READ) return (EINVAL); count = uio->uio_resid; entries = (uio->uio_offset + count) & (DIRBLKSIZ - 1); /* Make sure we don't return partial entries. */ if (count <= entries) return (EINVAL); /* * Convert and copy back the on-disk struct direct format to * the user-space struct dirent format, one entry at a time */ /* read from disk, stopping on a block boundary, max 64kB */ readcnt = min(count, 64*1024) - entries; auio = *uio; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_resid = readcnt; auio.uio_segflg = UIO_SYSSPACE; aiov.iov_len = readcnt; bufsize = readcnt; diskbuf = malloc(bufsize, M_TEMP, M_WAITOK); aiov.iov_base = diskbuf; error = VOP_READ(ap->a_vp, &auio, 0, ap->a_cred); readcnt -= auio.uio_resid; dp = (struct direct *)diskbuf; edp = &diskbuf[readcnt]; memset(&u, 0, sizeof(u)); /* * While * - we haven't failed to VOP_READ or uiomove() * - there's space in the read buf for the head of an entry * - that entry has a valid d_reclen, and * - there's space for the *entire* entry * then we're good to process this one. */ while (error == 0 && (char *)dp + offsetof(struct direct, d_name) < edp && dp->d_reclen > offsetof(struct direct, d_name) && (char *)dp + dp->d_reclen <= edp) { u.dn.d_reclen = roundup(dp->d_namlen+1 + offsetof(struct dirent, d_name), 8); if (u.dn.d_reclen > uio->uio_resid) break; off += dp->d_reclen; u.dn.d_off = off; u.dn.d_fileno = dp->d_ino; u.dn.d_type = dp->d_type; u.dn.d_namlen = dp->d_namlen; memcpy(u.dn.d_name, dp->d_name, u.dn.d_namlen); memset(u.dn.d_name + u.dn.d_namlen, 0, u.dn.d_reclen - u.dn.d_namlen - offsetof(struct dirent, d_name)); error = uiomove(&u.dn, u.dn.d_reclen, uio); dp = (struct direct *)((char *)dp + dp->d_reclen); } /* * If there was room for an entry in what we read but its * d_reclen is bogus, fail */ if ((char *)dp + offsetof(struct direct, d_name) < edp && dp->d_reclen <= offsetof(struct direct, d_name)) error = EIO; free(diskbuf, M_TEMP, bufsize); uio->uio_offset = off; *ap->a_eofflag = DIP(VTOI(ap->a_vp), size) <= off; return (error); } /* * Return target name of a symbolic link */ int ufs_readlink(void *v) { struct vop_readlink_args *ap = v; struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); u_int64_t isize; isize = DIP(ip, size); if (isize < ip->i_ump->um_maxsymlinklen) return (uiomove((char *)SHORTLINK(ip), isize, ap->a_uio)); return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred)); } /* * Lock an inode. If its already locked, set the WANT bit and sleep. */ int ufs_lock(void *v) { struct vop_lock_args *ap = v; struct vnode *vp = ap->a_vp; return rrw_enter(&VTOI(vp)->i_lock, ap->a_flags & LK_RWFLAGS); } /* * Unlock an inode. If WANT bit is on, wakeup. */ int ufs_unlock(void *v) { struct vop_unlock_args *ap = v; struct vnode *vp = ap->a_vp; rrw_exit(&VTOI(vp)->i_lock); return 0; } /* * Check for a locked inode. */ int ufs_islocked(void *v) { struct vop_islocked_args *ap = v; return rrw_status(&VTOI(ap->a_vp)->i_lock); } /* * Calculate the logical to physical mapping if not done already, * then call the device strategy routine. */ int ufs_strategy(void *v) { struct vop_strategy_args *ap = v; struct buf *bp = ap->a_bp; struct vnode *vp = bp->b_vp; struct inode *ip; int error; int s; ip = VTOI(vp); if (vp->v_type == VBLK || vp->v_type == VCHR) panic("ufs_strategy: spec"); if (bp->b_blkno == bp->b_lblkno) { error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL); if (error) { bp->b_error = error; bp->b_flags |= B_ERROR; s = splbio(); biodone(bp); splx(s); return (error); } if (bp->b_blkno == -1) clrbuf(bp); } if (bp->b_blkno == -1) { s = splbio(); biodone(bp); splx(s); return (0); } vp = ip->i_devvp; bp->b_dev = vp->v_rdev; VOP_STRATEGY(vp, bp); return (0); } /* * Print out the contents of an inode. */ int ufs_print(void *v) { #ifdef DIAGNOSTIC struct vop_print_args *ap = v; struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); printf("tag VT_UFS, ino %u, on dev %d, %d", ip->i_number, major(ip->i_dev), minor(ip->i_dev)); printf(" flags 0x%x, effnlink %d, nlink %d\n", ip->i_flag, ip->i_effnlink, DIP(ip, nlink)); printf("\tmode 0%o, owner %d, group %d, size %lld", DIP(ip, mode), DIP(ip, uid), DIP(ip, gid), DIP(ip, size)); #ifdef FIFO if (vp->v_type == VFIFO) fifo_printinfo(vp); #endif /* FIFO */ printf("\n"); #endif /* DIAGNOSTIC */ return (0); } /* * Read wrapper for special devices. */ int ufsspec_read(void *v) { struct vop_read_args *ap = v; /* * Set access flag. */ VTOI(ap->a_vp)->i_flag |= IN_ACCESS; return (spec_read(ap)); } /* * Write wrapper for special devices. */ int ufsspec_write(void *v) { struct vop_write_args *ap = v; /* * Set update and change flags. */ VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE; return (spec_write(ap)); } /* * Close wrapper for special devices. * * Update the times on the inode then do device close. */ int ufsspec_close(void *v) { struct vop_close_args *ap = v; struct vnode *vp = ap->a_vp; if (vp->v_usecount > 1) ufs_itimes(vp); return (spec_close(ap)); } #ifdef FIFO /* * Read wrapper for fifo's */ int ufsfifo_read(void *v) { struct vop_read_args *ap = v; /* * Set access flag. */ VTOI(ap->a_vp)->i_flag |= IN_ACCESS; return (fifo_read(ap)); } /* * Write wrapper for fifo's. */ int ufsfifo_write(void *v) { struct vop_write_args *ap = v; /* * Set update and change flags. */ VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE; return (fifo_write(ap)); } /* * Close wrapper for fifo's. * * Update the times on the inode then do device close. */ int ufsfifo_close(void *v) { struct vop_close_args *ap = v; struct vnode *vp = ap->a_vp; if (vp->v_usecount > 1) ufs_itimes(vp); return (fifo_close(ap)); } #endif /* FIFO */ /* * Return POSIX pathconf information applicable to ufs filesystems. */ int ufs_pathconf(void *v) { struct vop_pathconf_args *ap = v; int error = 0; switch (ap->a_name) { case _PC_LINK_MAX: *ap->a_retval = LINK_MAX; break; case _PC_NAME_MAX: *ap->a_retval = NAME_MAX; break; case _PC_CHOWN_RESTRICTED: *ap->a_retval = 1; break; case _PC_NO_TRUNC: *ap->a_retval = 1; break; case _PC_ALLOC_SIZE_MIN: *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_bsize; break; case _PC_FILESIZEBITS: *ap->a_retval = 64; break; case _PC_REC_INCR_XFER_SIZE: *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize; break; case _PC_REC_MAX_XFER_SIZE: *ap->a_retval = -1; /* means ``unlimited'' */ break; case _PC_REC_MIN_XFER_SIZE: *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize; break; case _PC_REC_XFER_ALIGN: *ap->a_retval = PAGE_SIZE; break; case _PC_SYMLINK_MAX: *ap->a_retval = MAXPATHLEN; break; case _PC_2_SYMLINKS: *ap->a_retval = 1; break; case _PC_TIMESTAMP_RESOLUTION: *ap->a_retval = 1; break; default: error = EINVAL; break; } return (error); } /* * Advisory record locking support */ int ufs_advlock(void *v) { struct vop_advlock_args *ap = v; struct inode *ip = VTOI(ap->a_vp); return (lf_advlock(&ip->i_lockf, DIP(ip, size), ap->a_id, ap->a_op, ap->a_fl, ap->a_flags)); } /* * Allocate a new inode. */ int ufs_makeinode(int mode, struct vnode *dvp, struct vnode **vpp, struct componentname *cnp) { struct inode *ip, *pdir; struct direct newdir; struct vnode *tvp; int error; pdir = VTOI(dvp); #ifdef DIAGNOSTIC if ((cnp->cn_flags & HASBUF) == 0) panic("ufs_makeinode: no name"); #endif *vpp = NULL; if ((mode & IFMT) == 0) mode |= IFREG; if ((error = UFS_INODE_ALLOC(pdir, mode, cnp->cn_cred, &tvp)) != 0) { pool_put(&namei_pool, cnp->cn_pnbuf); return (error); } ip = VTOI(tvp); DIP_ASSIGN(ip, gid, DIP(pdir, gid)); DIP_ASSIGN(ip, uid, cnp->cn_cred->cr_uid); if ((error = getinoquota(ip)) || (error = ufs_quota_alloc_inode(ip, cnp->cn_cred))) { pool_put(&namei_pool, cnp->cn_pnbuf); UFS_INODE_FREE(ip, ip->i_number, mode); vput(tvp); return (error); } ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; DIP_ASSIGN(ip, mode, mode); tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */ ip->i_effnlink = 1; DIP_ASSIGN(ip, nlink, 1); if ((DIP(ip, mode) & ISGID) && !groupmember(DIP(ip, gid), cnp->cn_cred) && !vnoperm(dvp) && suser_ucred(cnp->cn_cred)) DIP_AND(ip, mode, ~ISGID); /* * Make sure inode goes to disk before directory entry. */ if ((error = UFS_UPDATE(ip, 1)) != 0) goto bad; ufs_makedirentry(ip, cnp, &newdir); if ((error = ufs_direnter(dvp, tvp, &newdir, cnp, NULL)) != 0) goto bad; if ((cnp->cn_flags & SAVESTART) == 0) pool_put(&namei_pool, cnp->cn_pnbuf); *vpp = tvp; return (0); bad: /* * Write error occurred trying to update the inode * or the directory so must deallocate the inode. */ pool_put(&namei_pool, cnp->cn_pnbuf); ip->i_effnlink = 0; DIP_ASSIGN(ip, nlink, 0); ip->i_flag |= IN_CHANGE; tvp->v_type = VNON; vput(tvp); return (error); } const struct filterops ufsread_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, .f_detach = filt_ufsdetach, .f_event = filt_ufsread, }; const struct filterops ufswrite_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, .f_detach = filt_ufsdetach, .f_event = filt_ufswrite, }; const struct filterops ufsvnode_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, .f_detach = filt_ufsdetach, .f_event = filt_ufsvnode, }; int ufs_kqfilter(void *v) { struct vop_kqfilter_args *ap = v; struct vnode *vp = ap->a_vp; struct knote *kn = ap->a_kn; switch (kn->kn_filter) { case EVFILT_READ: kn->kn_fop = &ufsread_filtops; break; case EVFILT_WRITE: kn->kn_fop = &ufswrite_filtops; break; case EVFILT_VNODE: kn->kn_fop = &ufsvnode_filtops; break; default: return (EINVAL); } kn->kn_hook = (caddr_t)vp; klist_insert_locked(&vp->v_klist, kn); return (0); } void filt_ufsdetach(struct knote *kn) { struct vnode *vp = (struct vnode *)kn->kn_hook; klist_remove_locked(&vp->v_klist, kn); } int filt_ufsread(struct knote *kn, long hint) { struct vnode *vp = (struct vnode *)kn->kn_hook; struct inode *ip = VTOI(vp); /* * filesystem is gone, so set the EOF flag and schedule * the knote for deletion. */ if (hint == NOTE_REVOKE) { kn->kn_flags |= (EV_EOF | EV_ONESHOT); return (1); } #ifdef EXT2FS if (IS_EXT2_VNODE(ip->i_vnode)) kn->kn_data = ext2fs_size(ip) - foffset(kn->kn_fp); else #endif kn->kn_data = DIP(ip, size) - foffset(kn->kn_fp); if (kn->kn_data == 0 && kn->kn_sfflags & NOTE_EOF) { kn->kn_fflags |= NOTE_EOF; return (1); } if (kn->kn_flags & (__EV_POLL | __EV_SELECT)) return (1); return (kn->kn_data != 0); } int filt_ufswrite(struct knote *kn, long hint) { /* * filesystem is gone, so set the EOF flag and schedule * the knote for deletion. */ if (hint == NOTE_REVOKE) { kn->kn_flags |= (EV_EOF | EV_ONESHOT); return (1); } kn->kn_data = 0; return (1); } int filt_ufsvnode(struct knote *kn, long hint) { if (kn->kn_sfflags & hint) kn->kn_fflags |= hint; if (hint == NOTE_REVOKE) { kn->kn_flags |= EV_EOF; return (1); } return (kn->kn_fflags != 0); }
1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 /* $OpenBSD: ch.c,v 1.72 2023/04/11 00:45:09 jsg Exp $ */ /* $NetBSD: ch.c,v 1.26 1997/02/21 22:06:52 thorpej Exp $ */ /* * Copyright (c) 1996, 1997 Jason R. Thorpe <thorpej@and.com> * All rights reserved. * * Partially based on an autochanger driver written by Stefan Grefen * and on an autochanger driver written by the Systems Programming Group * at the University of Utah Computer Science Department. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgements: * This product includes software developed by Jason R. Thorpe * for And Communications, http://www.and.com/ * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/errno.h> #include <sys/ioctl.h> #include <sys/chio.h> #include <sys/device.h> #include <sys/malloc.h> #include <sys/pool.h> #include <sys/conf.h> #include <sys/fcntl.h> #include <scsi/scsi_all.h> #include <scsi/scsi_changer.h> #include <scsi/scsi_debug.h> #include <scsi/scsiconf.h> #define CHRETRIES 2 #define CHUNIT(x) (minor((x))) struct ch_softc { struct device sc_dev; /* generic device info */ struct scsi_link *sc_link; /* link in the SCSI bus */ int sc_picker; /* current picker */ /* * The following information is obtained from the * element address assignment page. */ int sc_firsts[4]; /* firsts, indexed by CHET_* */ int sc_counts[4]; /* counts, indexed by CHET_* */ /* * The following mask defines the legal combinations * of elements for the MOVE MEDIUM command. */ u_int8_t sc_movemask[4]; /* * As above, but for EXCHANGE MEDIUM. */ u_int8_t sc_exchangemask[4]; int flags; /* misc. info */ /* * Quirks; see below. */ int sc_settledelay; /* delay for settle */ }; /* sc_flags */ #define CHF_ROTATE 0x01 /* picker can rotate */ /* Autoconfiguration glue */ int chmatch(struct device *, void *, void *); void chattach(struct device *, struct device *, void *); const struct cfattach ch_ca = { sizeof(struct ch_softc), chmatch, chattach }; struct cfdriver ch_cd = { NULL, "ch", DV_DULL }; const struct scsi_inquiry_pattern ch_patterns[] = { {T_CHANGER, T_REMOV, "", "", ""}, }; int ch_move(struct ch_softc *, struct changer_move *); int ch_exchange(struct ch_softc *, struct changer_exchange *); int ch_position(struct ch_softc *, struct changer_position *); int ch_usergetelemstatus(struct ch_softc *, struct changer_element_status_request *); int ch_getelemstatus(struct ch_softc *, int, int, caddr_t, size_t, int); int ch_get_params(struct ch_softc *, int); int ch_interpret_sense(struct scsi_xfer *xs); void ch_get_quirks(struct ch_softc *, struct scsi_inquiry_data *); /* * SCSI changer quirks. */ struct chquirk { struct scsi_inquiry_pattern cq_match; /* device id pattern */ int cq_settledelay; /* settle delay, in seconds */ }; struct chquirk chquirks[] = { {{T_CHANGER, T_REMOV, "SPECTRA", "9000", "0200"}, 75}, }; int chmatch(struct device *parent, void *match, void *aux) { struct scsi_attach_args *sa = aux; struct scsi_inquiry_data *inq = &sa->sa_sc_link->inqdata; int priority; (void)scsi_inqmatch(inq, ch_patterns, nitems(ch_patterns), sizeof(ch_patterns[0]), &priority); return priority; } void chattach(struct device *parent, struct device *self, void *aux) { struct ch_softc *sc = (struct ch_softc *)self; struct scsi_attach_args *sa = aux; struct scsi_link *link = sa->sa_sc_link; /* Glue into the SCSI bus */ sc->sc_link = link; link->interpret_sense = ch_interpret_sense; link->device_softc = sc; link->openings = 1; printf("\n"); /* * Store our device's quirks. */ ch_get_quirks(sc, &link->inqdata); } int chopen(dev_t dev, int flags, int fmt, struct proc *p) { struct ch_softc *sc; int oldcounts[4]; int i, unit, error = 0; unit = CHUNIT(dev); if ((unit >= ch_cd.cd_ndevs) || ((sc = ch_cd.cd_devs[unit]) == NULL)) return ENXIO; /* * Only allow one open at a time. */ if (ISSET(sc->sc_link->flags, SDEV_OPEN)) return EBUSY; SET(sc->sc_link->flags, SDEV_OPEN); /* * Absorb any unit attention errors. We must notice * "Not ready" errors as a changer will report "In the * process of getting ready" any time it must rescan * itself to determine the state of the changer. */ error = scsi_test_unit_ready(sc->sc_link, TEST_READY_RETRIES, SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE); if (error) goto bad; /* * Get information about the device. Save old information * so we can decide whether to be verbose about new parameters. */ for (i = 0; i < 4; i++) { oldcounts[i] = sc->sc_counts[i]; } error = ch_get_params(sc, scsi_autoconf); if (error) goto bad; for (i = 0; i < 4; i++) { if (oldcounts[i] != sc->sc_counts[i]) { break; } } if (i < 4) { #ifdef CHANGER_DEBUG #define PLURAL(c) (c) == 1 ? "" : "s" printf("%s: %d slot%s, %d drive%s, %d picker%s, %d portal%s\n", sc->sc_dev.dv_xname, sc->sc_counts[CHET_ST], PLURAL(sc->sc_counts[CHET_ST]), sc->sc_counts[CHET_DT], PLURAL(sc->sc_counts[CHET_DT]), sc->sc_counts[CHET_MT], PLURAL(sc->sc_counts[CHET_MT]), sc->sc_counts[CHET_IE], PLURAL(sc->sc_counts[CHET_IE])); #undef PLURAL printf("%s: move mask: 0x%x 0x%x 0x%x 0x%x\n", sc->sc_dev.dv_xname, sc->sc_movemask[CHET_MT], sc->sc_movemask[CHET_ST], sc->sc_movemask[CHET_IE], sc->sc_movemask[CHET_DT]); printf("%s: exchange mask: 0x%x 0x%x 0x%x 0x%x\n", sc->sc_dev.dv_xname, sc->sc_exchangemask[CHET_MT], sc->sc_exchangemask[CHET_ST], sc->sc_exchangemask[CHET_IE], sc->sc_exchangemask[CHET_DT]); #endif /* CHANGER_DEBUG */ } /* Default the current picker. */ sc->sc_picker = sc->sc_firsts[CHET_MT]; return 0; bad: CLR(sc->sc_link->flags, SDEV_OPEN); return error; } int chclose(dev_t dev, int flags, int fmt, struct proc *p) { struct ch_softc *sc = ch_cd.cd_devs[CHUNIT(dev)]; CLR(sc->sc_link->flags, SDEV_OPEN); return 0; } int chioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) { struct ch_softc *sc = ch_cd.cd_devs[CHUNIT(dev)]; int error = 0; /* * If this command can change the device's state, we must * have the device open for writing. */ switch (cmd) { case CHIOGPICKER: case CHIOGPARAMS: case CHIOGSTATUS: break; default: if (!ISSET(flags, FWRITE)) return EBADF; } switch (cmd) { case CHIOMOVE: error = ch_move(sc, (struct changer_move *)data); break; case CHIOEXCHANGE: error = ch_exchange(sc, (struct changer_exchange *)data); break; case CHIOPOSITION: error = ch_position(sc, (struct changer_position *)data); break; case CHIOGPICKER: *(int *)data = sc->sc_picker - sc->sc_firsts[CHET_MT]; break; case CHIOSPICKER: { int new_picker = *(int *)data; if (new_picker > (sc->sc_counts[CHET_MT] - 1)) return EINVAL; sc->sc_picker = sc->sc_firsts[CHET_MT] + new_picker; break; } case CHIOGPARAMS: { struct changer_params *cp = (struct changer_params *)data; cp->cp_curpicker = sc->sc_picker - sc->sc_firsts[CHET_MT]; cp->cp_npickers = sc->sc_counts[CHET_MT]; cp->cp_nslots = sc->sc_counts[CHET_ST]; cp->cp_nportals = sc->sc_counts[CHET_IE]; cp->cp_ndrives = sc->sc_counts[CHET_DT]; break; } case CHIOGSTATUS: { struct changer_element_status_request *cesr = (struct changer_element_status_request *)data; error = ch_usergetelemstatus(sc, cesr); break; } /* Implement prevent/allow? */ default: error = scsi_do_ioctl(sc->sc_link, cmd, data, flags); break; } return error; } int ch_move(struct ch_softc *sc, struct changer_move *cm) { struct scsi_move_medium *cmd; struct scsi_xfer *xs; int error; u_int16_t fromelem, toelem; /* * Check arguments. */ if ((cm->cm_fromtype > CHET_DT) || (cm->cm_totype > CHET_DT)) return EINVAL; if ((cm->cm_fromunit > (sc->sc_counts[cm->cm_fromtype] - 1)) || (cm->cm_tounit > (sc->sc_counts[cm->cm_totype] - 1))) return ENODEV; /* * Check the request against the changer's capabilities. */ if ((sc->sc_movemask[cm->cm_fromtype] & (1 << cm->cm_totype)) == 0) return EINVAL; /* * Calculate the source and destination elements. */ fromelem = sc->sc_firsts[cm->cm_fromtype] + cm->cm_fromunit; toelem = sc->sc_firsts[cm->cm_totype] + cm->cm_tounit; /* * Build the SCSI command. */ xs = scsi_xs_get(sc->sc_link, 0); if (xs == NULL) return ENOMEM; xs->cmdlen = sizeof(*cmd); xs->retries = CHRETRIES; xs->timeout = 100000; cmd = (struct scsi_move_medium *)&xs->cmd; cmd->opcode = MOVE_MEDIUM; _lto2b(sc->sc_picker, cmd->tea); _lto2b(fromelem, cmd->src); _lto2b(toelem, cmd->dst); if (ISSET(cm->cm_flags, CM_INVERT)) SET(cmd->flags, MOVE_MEDIUM_INVERT); error = scsi_xs_sync(xs); scsi_xs_put(xs); return error; } int ch_exchange(struct ch_softc *sc, struct changer_exchange *ce) { struct scsi_exchange_medium *cmd; struct scsi_xfer *xs; int error; u_int16_t src, dst1, dst2; /* * Check arguments. */ if ((ce->ce_srctype > CHET_DT) || (ce->ce_fdsttype > CHET_DT) || (ce->ce_sdsttype > CHET_DT)) return EINVAL; if ((ce->ce_srcunit > (sc->sc_counts[ce->ce_srctype] - 1)) || (ce->ce_fdstunit > (sc->sc_counts[ce->ce_fdsttype] - 1)) || (ce->ce_sdstunit > (sc->sc_counts[ce->ce_sdsttype] - 1))) return ENODEV; /* * Check the request against the changer's capabilities. */ if (((sc->sc_exchangemask[ce->ce_srctype] & (1 << ce->ce_fdsttype)) == 0) || ((sc->sc_exchangemask[ce->ce_fdsttype] & (1 << ce->ce_sdsttype)) == 0)) return EINVAL; /* * Calculate the source and destination elements. */ src = sc->sc_firsts[ce->ce_srctype] + ce->ce_srcunit; dst1 = sc->sc_firsts[ce->ce_fdsttype] + ce->ce_fdstunit; dst2 = sc->sc_firsts[ce->ce_sdsttype] + ce->ce_sdstunit; /* * Build the SCSI command. */ xs = scsi_xs_get(sc->sc_link, 0); if (xs == NULL) return ENOMEM; xs->cmdlen = sizeof(*cmd); xs->retries = CHRETRIES; xs->timeout = 100000; cmd = (struct scsi_exchange_medium *)&xs->cmd; cmd->opcode = EXCHANGE_MEDIUM; _lto2b(sc->sc_picker, cmd->tea); _lto2b(src, cmd->src); _lto2b(dst1, cmd->fdst); _lto2b(dst2, cmd->sdst); if (ISSET(ce->ce_flags, CE_INVERT1)) SET(cmd->flags, EXCHANGE_MEDIUM_INV1); if (ISSET(ce->ce_flags, CE_INVERT2)) SET(cmd->flags, EXCHANGE_MEDIUM_INV2); error = scsi_xs_sync(xs); scsi_xs_put(xs); return error; } int ch_position(struct ch_softc *sc, struct changer_position *cp) { struct scsi_position_to_element *cmd; struct scsi_xfer *xs; int error; u_int16_t dst; /* * Check arguments. */ if (cp->cp_type > CHET_DT) return EINVAL; if (cp->cp_unit > (sc->sc_counts[cp->cp_type] - 1)) return ENODEV; /* * Calculate the destination element. */ dst = sc->sc_firsts[cp->cp_type] + cp->cp_unit; /* * Build the SCSI command. */ xs = scsi_xs_get(sc->sc_link, 0); if (xs == NULL) return ENOMEM; xs->cmdlen = sizeof(*cmd); xs->retries = CHRETRIES; xs->timeout = 100000; cmd = (struct scsi_position_to_element *)&xs->cmd; cmd->opcode = POSITION_TO_ELEMENT; _lto2b(sc->sc_picker, cmd->tea); _lto2b(dst, cmd->dst); if (ISSET(cp->cp_flags, CP_INVERT)) SET(cmd->flags, POSITION_TO_ELEMENT_INVERT); error = scsi_xs_sync(xs); scsi_xs_put(xs); return error; } /* * Copy a volume tag to a volume_tag struct, converting SCSI byte order * to host native byte order in the volume serial number. The volume * label as returned by the changer is transferred to user mode as * nul-terminated string. Volume labels are truncated at the first * space, as suggested by SCSI-2. */ static void copy_voltag(struct changer_voltag *uvoltag, struct volume_tag *voltag) { int i; for (i=0; i<CH_VOLTAG_MAXLEN; i++) { char c = voltag->vif[i]; if (c && c != ' ') uvoltag->cv_volid[i] = c; else break; } uvoltag->cv_volid[i] = '\0'; uvoltag->cv_serial = _2btol(voltag->vsn); } /* * Copy an element status descriptor to a user-mode * changer_element_status structure. */ static void copy_element_status(struct ch_softc *sc, int flags, struct read_element_status_descriptor *desc, struct changer_element_status *ces) { u_int16_t eaddr = _2btol(desc->eaddr); u_int16_t et; for (et = CHET_MT; et <= CHET_DT; et++) { if ((sc->sc_firsts[et] <= eaddr) && ((sc->sc_firsts[et] + sc->sc_counts[et]) > eaddr)) { ces->ces_addr = eaddr - sc->sc_firsts[et]; ces->ces_type = et; break; } } ces->ces_flags = desc->flags1; ces->ces_sensecode = desc->sense_code; ces->ces_sensequal = desc->sense_qual; if (desc->flags2 & READ_ELEMENT_STATUS_INVERT) ces->ces_flags |= READ_ELEMENT_STATUS_EXCEPT; if (desc->flags2 & READ_ELEMENT_STATUS_SVALID) { eaddr = _2btol(desc->ssea); /* convert source address to logical format */ for (et = CHET_MT; et <= CHET_DT; et++) { if ((sc->sc_firsts[et] <= eaddr) && ((sc->sc_firsts[et] + sc->sc_counts[et]) > eaddr)) { ces->ces_source_addr = eaddr - sc->sc_firsts[et]; ces->ces_source_type = et; ces->ces_flags |= READ_ELEMENT_STATUS_ACCESS; break; } } if (!(ces->ces_flags & READ_ELEMENT_STATUS_ACCESS)) printf("ch: warning: could not map element source " "address %ud to a valid element type\n", eaddr); } if (ISSET(flags, READ_ELEMENT_STATUS_PVOLTAG)) copy_voltag(&ces->ces_pvoltag, &desc->pvoltag); if (ISSET(flags, READ_ELEMENT_STATUS_AVOLTAG)) copy_voltag(&ces->ces_avoltag, &desc->avoltag); } /* * Perform a READ ELEMENT STATUS on behalf of the user, and return to * the user only the data the user is interested in (i.e. an array of * changer_element_status structures) */ int ch_usergetelemstatus(struct ch_softc *sc, struct changer_element_status_request *cesr) { struct changer_element_status *user_data = NULL; struct read_element_status_header *st_hdr; struct read_element_status_page_header *pg_hdr; caddr_t desc; caddr_t data = NULL; size_t size, desclen, udsize; int avail, chet, i, want_voltags; int error = 0; chet = cesr->cesr_type; want_voltags = (cesr->cesr_flags & CESR_VOLTAGS) ? 1 : 0; /* * If there are no elements of the requested type in the changer, * the request is invalid. */ if (sc->sc_counts[chet] == 0) return EINVAL; /* * Request one descriptor for the given element type. This * is used to determine the size of the descriptor so that * we can allocate enough storage for all of them. We assume * that the first one can fit into 1k. */ size = 1024; data = dma_alloc(size, PR_WAITOK); error = ch_getelemstatus(sc, sc->sc_firsts[chet], 1, data, size, want_voltags); if (error) goto done; st_hdr = (struct read_element_status_header *)data; pg_hdr = (struct read_element_status_page_header *) (st_hdr + 1); desclen = _2btol(pg_hdr->edl); dma_free(data, size); /* * Reallocate storage for descriptors and get them from the * device. */ size = sizeof(struct read_element_status_header) + sizeof(struct read_element_status_page_header) + (desclen * sc->sc_counts[chet]); data = dma_alloc(size, PR_WAITOK); error = ch_getelemstatus(sc, sc->sc_firsts[chet], sc->sc_counts[chet], data, size, want_voltags); if (error) goto done; /* * Fill in the user status array. */ st_hdr = (struct read_element_status_header *)data; pg_hdr = (struct read_element_status_page_header *) (st_hdr + 1); avail = _2btol(st_hdr->count); if (avail != sc->sc_counts[chet]) { error = EINVAL; goto done; } user_data = mallocarray(avail, sizeof(struct changer_element_status), M_DEVBUF, M_WAITOK | M_ZERO); udsize = avail * sizeof(struct changer_element_status); desc = (caddr_t)(pg_hdr + 1); for (i = 0; i < avail; ++i) { struct changer_element_status *ces = &(user_data[i]); copy_element_status(sc, pg_hdr->flags, (struct read_element_status_descriptor *)desc, ces); desc += desclen; } /* Copy array out to userspace. */ error = copyout(user_data, cesr->cesr_data, udsize); done: if (data != NULL) dma_free(data, size); if (user_data != NULL) free(user_data, M_DEVBUF, udsize); return error; } int ch_getelemstatus(struct ch_softc *sc, int first, int count, caddr_t data, size_t datalen, int voltag) { struct scsi_read_element_status *cmd; struct scsi_xfer *xs; int error; /* * Build SCSI command. */ xs = scsi_xs_get(sc->sc_link, SCSI_DATA_IN); if (xs == NULL) return ENOMEM; xs->cmdlen = sizeof(*cmd); xs->data = data; xs->datalen = datalen; xs->retries = CHRETRIES; xs->timeout = 100000; cmd = (struct scsi_read_element_status *)&xs->cmd; cmd->opcode = READ_ELEMENT_STATUS; _lto2b(first, cmd->sea); _lto2b(count, cmd->count); _lto3b(datalen, cmd->len); if (voltag) SET(cmd->byte2, READ_ELEMENT_STATUS_VOLTAG); error = scsi_xs_sync(xs); scsi_xs_put(xs); return error; } /* * Ask the device about itself and fill in the parameters in our * softc. */ int ch_get_params(struct ch_softc *sc, int flags) { union scsi_mode_sense_buf *data; struct page_element_address_assignment *ea; struct page_device_capabilities *cap; u_int8_t *moves, *exchanges; int big, error, from; data = dma_alloc(sizeof(*data), PR_NOWAIT); if (data == NULL) return ENOMEM; /* * Grab info from the element address assignment page (0x1d). */ error = scsi_do_mode_sense(sc->sc_link, EA_PAGE, data, (void **)&ea, sizeof(*ea), flags, &big); if (error == 0 && ea == NULL) error = EIO; if (error != 0) { #ifdef CHANGER_DEBUG printf("%s: could not sense element address page\n", sc->sc_dev.dv_xname); #endif /* CHANGER_DEBUG */ dma_free(data, sizeof(*data)); return error; } sc->sc_firsts[CHET_MT] = _2btol(ea->mtea); sc->sc_counts[CHET_MT] = _2btol(ea->nmte); sc->sc_firsts[CHET_ST] = _2btol(ea->fsea); sc->sc_counts[CHET_ST] = _2btol(ea->nse); sc->sc_firsts[CHET_IE] = _2btol(ea->fieea); sc->sc_counts[CHET_IE] = _2btol(ea->niee); sc->sc_firsts[CHET_DT] = _2btol(ea->fdtea); sc->sc_counts[CHET_DT] = _2btol(ea->ndte); /* XXX Ask for transport geometry page. */ /* * Grab info from the capabilities page (0x1f). */ error = scsi_do_mode_sense(sc->sc_link, CAP_PAGE, data, (void **)&cap, sizeof(*cap), flags, &big); if (error == 0 && cap == NULL) error = EIO; if (error != 0) { #ifdef CHANGER_DEBUG printf("%s: could not sense capabilities page\n", sc->sc_dev.dv_xname); #endif /* CHANGER_DEBUG */ dma_free(data, sizeof(*data)); return error; } bzero(sc->sc_movemask, sizeof(sc->sc_movemask)); bzero(sc->sc_exchangemask, sizeof(sc->sc_exchangemask)); moves = &cap->move_from_mt; exchanges = &cap->exchange_with_mt; for (from = CHET_MT; from <= CHET_DT; ++from) { sc->sc_movemask[from] = moves[from]; sc->sc_exchangemask[from] = exchanges[from]; } SET(sc->sc_link->flags, SDEV_MEDIA_LOADED); dma_free(data, sizeof(*data)); return 0; } void ch_get_quirks(struct ch_softc *sc, struct scsi_inquiry_data *inqbuf) { const struct chquirk *match; int priority; sc->sc_settledelay = 0; match = (const struct chquirk *)scsi_inqmatch(inqbuf, (caddr_t)chquirks, sizeof(chquirks) / sizeof(chquirks[0]), sizeof(chquirks[0]), &priority); if (priority != 0) { sc->sc_settledelay = match->cq_settledelay; } } /* * Look at the returned sense and act on the error to determine * the unix error number to pass back... (0 = report no error) * (-1 = continue processing) */ int ch_interpret_sense(struct scsi_xfer *xs) { struct scsi_sense_data *sense = &xs->sense; struct scsi_link *link = xs->sc_link; u_int8_t serr, skey; serr = sense->error_code & SSD_ERRCODE; skey = sense->flags & SSD_KEY; if (!ISSET(link->flags, SDEV_OPEN) || (serr != SSD_ERRCODE_CURRENT && serr != SSD_ERRCODE_DEFERRED)) return scsi_interpret_sense(xs); switch (skey) { /* * We do custom processing in ch for the unit becoming ready * case. in this case we do not allow xs->retries to be * decremented only on the "Unit Becoming Ready" case. This is * because tape changers report "Unit Becoming Ready" when they * rescan their state (i.e. when the door got opened) and can * take a long time for large units. Rather than having a * massive timeout for all operations (which would cause other * problems) we allow changers to wait (but be interruptible * with Ctrl-C) forever as long as they are reporting that they * are becoming ready. all other cases are handled as per the * default. */ case SKEY_NOT_READY: if (ISSET(xs->flags, SCSI_IGNORE_NOT_READY)) return 0; switch (ASC_ASCQ(sense)) { case SENSE_NOT_READY_BECOMING_READY: SC_DEBUG(link, SDEV_DB1, ("not ready: busy (%#x)\n", sense->add_sense_code_qual)); /* don't count this as a retry */ xs->retries++; return scsi_delay(xs, 1); default: return scsi_interpret_sense(xs); } default: return scsi_interpret_sense(xs); } }
3 3 3 3 4 1 1 1 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 /* $OpenBSD: kern_exit.c,v 1.221 2024/05/20 10:32:20 claudio Exp $ */ /* $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_exit.c 8.7 (Berkeley) 2/12/94 */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/time.h> #include <sys/resource.h> #include <sys/wait.h> #include <sys/vnode.h> #include <sys/malloc.h> #include <sys/resourcevar.h> #include <sys/ptrace.h> #include <sys/acct.h> #include <sys/filedesc.h> #include <sys/signalvar.h> #include <sys/sched.h> #include <sys/ktrace.h> #include <sys/pool.h> #include <sys/mutex.h> #ifdef SYSVSEM #include <sys/sem.h> #endif #include <sys/witness.h> #include <sys/mount.h> #include <sys/syscallargs.h> #include <uvm/uvm_extern.h> #include "kcov.h" #if NKCOV > 0 #include <sys/kcov.h> #endif void proc_finish_wait(struct proc *, struct proc *); void process_clear_orphan(struct process *); void process_zap(struct process *); void proc_free(struct proc *); void unveil_destroy(struct process *ps); /* * exit -- * Death of process. */ int sys_exit(struct proc *p, void *v, register_t *retval) { struct sys_exit_args /* { syscallarg(int) rval; } */ *uap = v; exit1(p, SCARG(uap, rval), 0, EXIT_NORMAL); /* NOTREACHED */ return (0); } int sys___threxit(struct proc *p, void *v, register_t *retval) { struct sys___threxit_args /* { syscallarg(pid_t *) notdead; } */ *uap = v; if (SCARG(uap, notdead) != NULL) { pid_t zero = 0; if (copyout(&zero, SCARG(uap, notdead), sizeof(zero))) psignal(p, SIGSEGV); } exit1(p, 0, 0, EXIT_THREAD); return (0); } /* * Exit: deallocate address space and other resources, change proc state * to zombie, and unlink proc from allproc and parent's lists. Save exit * status and rusage for wait(). Check for child processes and orphan them. */ void exit1(struct proc *p, int xexit, int xsig, int flags) { struct process *pr, *qr, *nqr; struct rusage *rup; struct timespec ts; int s; atomic_setbits_int(&p->p_flag, P_WEXIT); pr = p->p_p; /* single-threaded? */ if (!P_HASSIBLING(p)) { flags = EXIT_NORMAL; } else { /* nope, multi-threaded */ if (flags == EXIT_NORMAL) single_thread_set(p, SINGLE_EXIT); } if (flags == EXIT_NORMAL && !(pr->ps_flags & PS_EXITING)) { if (pr->ps_pid == 1) panic("init died (signal %d, exit %d)", xsig, xexit); atomic_setbits_int(&pr->ps_flags, PS_EXITING); pr->ps_xexit = xexit; pr->ps_xsig = xsig; /* * If parent is waiting for us to exit or exec, PS_PPWAIT * is set; we wake up the parent early to avoid deadlock. */ if (pr->ps_flags & PS_PPWAIT) { atomic_clearbits_int(&pr->ps_flags, PS_PPWAIT); atomic_clearbits_int(&pr->ps_pptr->ps_flags, PS_ISPWAIT); wakeup(pr->ps_pptr); } } /* unlink ourselves from the active threads */ mtx_enter(&pr->ps_mtx); TAILQ_REMOVE(&pr->ps_threads, p, p_thr_link); pr->ps_threadcnt--; pr->ps_exitcnt++; /* * if somebody else wants to take us to single threaded mode, * count ourselves out. */ if (pr->ps_single) { if (--pr->ps_singlecnt == 0) wakeup(&pr->ps_singlecnt); } if ((p->p_flag & P_THREAD) == 0) { /* main thread gotta wait because it has the pid, et al */ while (pr->ps_threadcnt + pr->ps_exitcnt > 1) msleep_nsec(&pr->ps_threads, &pr->ps_mtx, PWAIT, "thrdeath", INFSLP); } mtx_leave(&pr->ps_mtx); rup = pr->ps_ru; if (rup == NULL) { rup = pool_get(&rusage_pool, PR_WAITOK | PR_ZERO); if (pr->ps_ru == NULL) { pr->ps_ru = rup; } else { pool_put(&rusage_pool, rup); rup = pr->ps_ru; } } p->p_siglist = 0; if ((p->p_flag & P_THREAD) == 0) pr->ps_siglist = 0; kqpoll_exit(); #if NKCOV > 0 kcov_exit(p); #endif if ((p->p_flag & P_THREAD) == 0) { if (pr->ps_flags & PS_PROFIL) stopprofclock(pr); sigio_freelist(&pr->ps_sigiolst); /* close open files and release open-file table */ fdfree(p); cancel_all_itimers(); timeout_del(&pr->ps_rucheck_to); #ifdef SYSVSEM semexit(pr); #endif killjobc(pr); #ifdef ACCOUNTING acct_process(p); #endif #ifdef KTRACE /* release trace file */ if (pr->ps_tracevp) ktrcleartrace(pr); #endif unveil_destroy(pr); free(pr->ps_pin.pn_pins, M_PINSYSCALL, pr->ps_pin.pn_npins * sizeof(u_int)); free(pr->ps_libcpin.pn_pins, M_PINSYSCALL, pr->ps_libcpin.pn_npins * sizeof(u_int)); /* * If parent has the SAS_NOCLDWAIT flag set, we're not * going to become a zombie. */ if (pr->ps_pptr->ps_sigacts->ps_sigflags & SAS_NOCLDWAIT) atomic_setbits_int(&pr->ps_flags, PS_NOZOMBIE); } p->p_fd = NULL; /* zap the thread's copy */ /* Release the thread's read reference of resource limit structure. */ if (p->p_limit != NULL) { struct plimit *limit; limit = p->p_limit; p->p_limit = NULL; lim_free(limit); } /* * Remove proc from pidhash chain and allproc so looking * it up won't work. We will put the proc on the * deadproc list later (using the p_hash member), and * wake up the reaper when we do. If this is the last * thread of a process that isn't PS_NOZOMBIE, we'll put * the process on the zombprocess list below. */ /* * NOTE: WE ARE NO LONGER ALLOWED TO SLEEP! */ p->p_stat = SDEAD; LIST_REMOVE(p, p_hash); LIST_REMOVE(p, p_list); if ((p->p_flag & P_THREAD) == 0) { LIST_REMOVE(pr, ps_hash); LIST_REMOVE(pr, ps_list); if ((pr->ps_flags & PS_NOZOMBIE) == 0) LIST_INSERT_HEAD(&zombprocess, pr, ps_list); else { /* * Not going to be a zombie, so it's now off all * the lists scanned by ispidtaken(), so block * fast reuse of the pid now. */ freepid(pr->ps_pid); } /* * Reparent children to their original parent, in case * they were being traced, or to init(8). */ qr = LIST_FIRST(&pr->ps_children); if (qr) /* only need this if any child is S_ZOMB */ wakeup(initprocess); for (; qr != NULL; qr = nqr) { nqr = LIST_NEXT(qr, ps_sibling); /* * Traced processes are killed since their * existence means someone is screwing up. */ if (qr->ps_flags & PS_TRACED && !(qr->ps_flags & PS_EXITING)) { process_untrace(qr); /* * If single threading is active, * direct the signal to the active * thread to avoid deadlock. */ if (qr->ps_single) ptsignal(qr->ps_single, SIGKILL, STHREAD); else prsignal(qr, SIGKILL); } else { process_reparent(qr, initprocess); } } /* * Make sure orphans won't remember the exiting process. */ while ((qr = LIST_FIRST(&pr->ps_orphans)) != NULL) { KASSERT(qr->ps_oppid == pr->ps_pid); qr->ps_oppid = 0; process_clear_orphan(qr); } } /* add thread's accumulated rusage into the process's total */ ruadd(rup, &p->p_ru); nanouptime(&ts); if (timespeccmp(&ts, &curcpu()->ci_schedstate.spc_runtime, <)) timespecclear(&ts); else timespecsub(&ts, &curcpu()->ci_schedstate.spc_runtime, &ts); SCHED_LOCK(s); tuagg_locked(pr, p, &ts); SCHED_UNLOCK(s); /* * clear %cpu usage during swap */ p->p_pctcpu = 0; if ((p->p_flag & P_THREAD) == 0) { /* * Final thread has died, so add on our children's rusage * and calculate the total times */ calcru(&pr->ps_tu, &rup->ru_utime, &rup->ru_stime, NULL); ruadd(rup, &pr->ps_cru); /* * Notify parent that we're gone. If we're not going to * become a zombie, reparent to process 1 (init) so that * we can wake our original parent to possibly unblock * wait4() to return ECHILD. */ if (pr->ps_flags & PS_NOZOMBIE) { struct process *ppr = pr->ps_pptr; process_reparent(pr, initprocess); wakeup(ppr); } } /* just a thread? detach it from its process */ if (p->p_flag & P_THREAD) { /* scheduler_wait_hook(pr->ps_mainproc, p); XXX */ mtx_enter(&pr->ps_mtx); pr->ps_exitcnt--; if (pr->ps_threadcnt + pr->ps_exitcnt == 1) wakeup(&pr->ps_threads); mtx_leave(&pr->ps_mtx); } /* * Other substructures are freed from reaper and wait(). */ /* * Finally, call machine-dependent code to switch to a new * context (possibly the idle context). Once we are no longer * using the dead process's vmspace and stack, exit2() will be * called to schedule those resources to be released by the * reaper thread. * * Note that cpu_exit() will end with a call equivalent to * cpu_switch(), finishing our execution (pun intended). */ uvmexp.swtch++; cpu_exit(p); panic("cpu_exit returned"); } /* * Locking of this proclist is special; it's accessed in a * critical section of process exit, and thus locking it can't * modify interrupt state. We use a simple spin lock for this * proclist. We use the p_hash member to linkup to deadproc. */ struct mutex deadproc_mutex = MUTEX_INITIALIZER_FLAGS(IPL_NONE, "deadproc", MTX_NOWITNESS); struct proclist deadproc = LIST_HEAD_INITIALIZER(deadproc); /* * We are called from cpu_exit() once it is safe to schedule the * dead process's resources to be freed. * * NOTE: One must be careful with locking in this routine. It's * called from a critical section in machine-dependent code, so * we should refrain from changing any interrupt state. * * We lock the deadproc list, place the proc on that list (using * the p_hash member), and wake up the reaper. */ void exit2(struct proc *p) { mtx_enter(&deadproc_mutex); LIST_INSERT_HEAD(&deadproc, p, p_hash); mtx_leave(&deadproc_mutex); wakeup(&deadproc); } void proc_free(struct proc *p) { crfree(p->p_ucred); pool_put(&proc_pool, p); nthreads--; } /* * Process reaper. This is run by a kernel thread to free the resources * of a dead process. Once the resources are free, the process becomes * a zombie, and the parent is allowed to read the undead's status. */ void reaper(void *arg) { struct proc *p; KERNEL_UNLOCK(); SCHED_ASSERT_UNLOCKED(); for (;;) { mtx_enter(&deadproc_mutex); while ((p = LIST_FIRST(&deadproc)) == NULL) msleep_nsec(&deadproc, &deadproc_mutex, PVM, "reaper", INFSLP); /* Remove us from the deadproc list. */ LIST_REMOVE(p, p_hash); mtx_leave(&deadproc_mutex); WITNESS_THREAD_EXIT(p); KERNEL_LOCK(); /* * Free the VM resources we're still holding on to. * We must do this from a valid thread because doing * so may block. */ uvm_uarea_free(p); p->p_vmspace = NULL; /* zap the thread's copy */ if (p->p_flag & P_THREAD) { /* Just a thread */ proc_free(p); } else { struct process *pr = p->p_p; /* Release the rest of the process's vmspace */ uvm_exit(pr); if ((pr->ps_flags & PS_NOZOMBIE) == 0) { /* Process is now a true zombie. */ atomic_setbits_int(&pr->ps_flags, PS_ZOMBIE); } /* Notify listeners of our demise and clean up. */ knote_processexit(pr); if (pr->ps_flags & PS_ZOMBIE) { /* Post SIGCHLD and wake up parent. */ prsignal(pr->ps_pptr, SIGCHLD); wakeup(pr->ps_pptr); } else { /* No one will wait for us, just zap it. */ process_zap(pr); } } KERNEL_UNLOCK(); } } int dowait6(struct proc *q, idtype_t idtype, id_t id, int *statusp, int options, struct rusage *rusage, siginfo_t *info, register_t *retval) { int nfound; struct process *pr; struct proc *p; int error; if (info != NULL) memset(info, 0, sizeof(*info)); loop: nfound = 0; LIST_FOREACH(pr, &q->p_p->ps_children, ps_sibling) { if ((pr->ps_flags & PS_NOZOMBIE) || (idtype == P_PID && id != pr->ps_pid) || (idtype == P_PGID && id != pr->ps_pgid)) continue; p = pr->ps_mainproc; nfound++; if ((options & WEXITED) && (pr->ps_flags & PS_ZOMBIE)) { *retval = pr->ps_pid; if (info != NULL) { info->si_pid = pr->ps_pid; info->si_uid = pr->ps_ucred->cr_uid; info->si_signo = SIGCHLD; if (pr->ps_xsig == 0) { info->si_code = CLD_EXITED; info->si_status = pr->ps_xexit; } else if (WCOREDUMP(pr->ps_xsig)) { info->si_code = CLD_DUMPED; info->si_status = _WSTATUS(pr->ps_xsig); } else { info->si_code = CLD_KILLED; info->si_status = _WSTATUS(pr->ps_xsig); } } if (statusp != NULL) *statusp = W_EXITCODE(pr->ps_xexit, pr->ps_xsig); if (rusage != NULL) memcpy(rusage, pr->ps_ru, sizeof(*rusage)); if ((options & WNOWAIT) == 0) proc_finish_wait(q, p); return (0); } if ((options & WTRAPPED) && pr->ps_flags & PS_TRACED && (pr->ps_flags & PS_WAITED) == 0 && pr->ps_single && pr->ps_single->p_stat == SSTOP && (pr->ps_single->p_flag & P_SUSPSINGLE) == 0) { if (single_thread_wait(pr, 0)) goto loop; if ((options & WNOWAIT) == 0) atomic_setbits_int(&pr->ps_flags, PS_WAITED); *retval = pr->ps_pid; if (info != NULL) { info->si_pid = pr->ps_pid; info->si_uid = pr->ps_ucred->cr_uid; info->si_signo = SIGCHLD; info->si_code = CLD_TRAPPED; info->si_status = pr->ps_xsig; } if (statusp != NULL) *statusp = W_STOPCODE(pr->ps_xsig); if (rusage != NULL) memset(rusage, 0, sizeof(*rusage)); return (0); } if (p->p_stat == SSTOP && (pr->ps_flags & PS_WAITED) == 0 && (p->p_flag & P_SUSPSINGLE) == 0 && (pr->ps_flags & PS_TRACED || options & WUNTRACED)) { if ((options & WNOWAIT) == 0) atomic_setbits_int(&pr->ps_flags, PS_WAITED); *retval = pr->ps_pid; if (info != 0) { info->si_pid = pr->ps_pid; info->si_uid = pr->ps_ucred->cr_uid; info->si_signo = SIGCHLD; info->si_code = CLD_STOPPED; info->si_status = pr->ps_xsig; } if (statusp != NULL) *statusp = W_STOPCODE(pr->ps_xsig); if (rusage != NULL) memset(rusage, 0, sizeof(*rusage)); return (0); } if ((options & WCONTINUED) && (p->p_flag & P_CONTINUED)) { if ((options & WNOWAIT) == 0) atomic_clearbits_int(&p->p_flag, P_CONTINUED); *retval = pr->ps_pid; if (info != NULL) { info->si_pid = pr->ps_pid; info->si_uid = pr->ps_ucred->cr_uid; info->si_signo = SIGCHLD; info->si_code = CLD_CONTINUED; info->si_status = SIGCONT; } if (statusp != NULL) *statusp = _WCONTINUED; if (rusage != NULL) memset(rusage, 0, sizeof(*rusage)); return (0); } } /* * Look in the orphans list too, to allow the parent to * collect its child's exit status even if child is being * debugged. * * Debugger detaches from the parent upon successful * switch-over from parent to child. At this point due to * re-parenting the parent loses the child to debugger and a * wait4(2) call would report that it has no children to wait * for. By maintaining a list of orphans we allow the parent * to successfully wait until the child becomes a zombie. */ if (nfound == 0) { LIST_FOREACH(pr, &q->p_p->ps_orphans, ps_orphan) { if ((pr->ps_flags & PS_NOZOMBIE) || (idtype == P_PID && id != pr->ps_pid) || (idtype == P_PGID && id != pr->ps_pgid)) continue; nfound++; break; } } if (nfound == 0) return (ECHILD); if (options & WNOHANG) { *retval = 0; return (0); } if ((error = tsleep_nsec(q->p_p, PWAIT | PCATCH, "wait", INFSLP)) != 0) return (error); goto loop; } int sys_wait4(struct proc *q, void *v, register_t *retval) { struct sys_wait4_args /* { syscallarg(pid_t) pid; syscallarg(int *) status; syscallarg(int) options; syscallarg(struct rusage *) rusage; } */ *uap = v; struct rusage ru; pid_t pid = SCARG(uap, pid); int options = SCARG(uap, options); int status, error; idtype_t idtype; id_t id; if (SCARG(uap, options) &~ (WUNTRACED|WNOHANG|WCONTINUED)) return (EINVAL); options |= WEXITED | WTRAPPED; if (SCARG(uap, pid) == WAIT_MYPGRP) { idtype = P_PGID; id = q->p_p->ps_pgid; } else if (SCARG(uap, pid) == WAIT_ANY) { idtype = P_ALL; id = 0; } else if (pid < 0) { idtype = P_PGID; id = -pid; } else { idtype = P_PID; id = pid; } error = dowait6(q, idtype, id, SCARG(uap, status) ? &status : NULL, options, SCARG(uap, rusage) ? &ru : NULL, NULL, retval); if (error == 0 && *retval > 0 && SCARG(uap, status)) { error = copyout(&status, SCARG(uap, status), sizeof(status)); } if (error == 0 && *retval > 0 && SCARG(uap, rusage)) { error = copyout(&ru, SCARG(uap, rusage), sizeof(ru)); #ifdef KTRACE if (error == 0 && KTRPOINT(q, KTR_STRUCT)) ktrrusage(q, &ru); #endif } return (error); } int sys_waitid(struct proc *q, void *v, register_t *retval) { struct sys_waitid_args /* { syscallarg(idtype_t) idtype; syscallarg(id_t) id; syscallarg(siginfo_t) info; syscallarg(int) options; } */ *uap = v; siginfo_t info; idtype_t idtype = SCARG(uap, idtype); int options = SCARG(uap, options); int error; if (options &~ (WSTOPPED|WCONTINUED|WEXITED|WTRAPPED|WNOHANG|WNOWAIT)) return (EINVAL); if ((options & (WSTOPPED|WCONTINUED|WEXITED|WTRAPPED)) == 0) return (EINVAL); if (idtype != P_ALL && idtype != P_PID && idtype != P_PGID) return (EINVAL); error = dowait6(q, idtype, SCARG(uap, id), NULL, options, NULL, &info, retval); if (error == 0) { error = copyout(&info, SCARG(uap, info), sizeof(info)); #ifdef KTRACE if (error == 0 && KTRPOINT(q, KTR_STRUCT)) ktrsiginfo(q, &info); #endif } if (error == 0) *retval = 0; return (error); } void proc_finish_wait(struct proc *waiter, struct proc *p) { struct process *pr, *tr; struct rusage *rup; /* * If we got the child via a ptrace 'attach', * we need to give it back to the old parent. */ pr = p->p_p; if (pr->ps_oppid != 0 && (pr->ps_oppid != pr->ps_pptr->ps_pid) && (tr = prfind(pr->ps_oppid))) { pr->ps_oppid = 0; atomic_clearbits_int(&pr->ps_flags, PS_TRACED); process_reparent(pr, tr); prsignal(tr, SIGCHLD); wakeup(tr); } else { scheduler_wait_hook(waiter, p); rup = &waiter->p_p->ps_cru; ruadd(rup, pr->ps_ru); LIST_REMOVE(pr, ps_list); /* off zombprocess */ freepid(pr->ps_pid); process_zap(pr); } } /* * give process back to original parent or init(8) */ void process_untrace(struct process *pr) { struct process *ppr = NULL; KASSERT(pr->ps_flags & PS_TRACED); if (pr->ps_oppid != 0 && (pr->ps_oppid != pr->ps_pptr->ps_pid)) ppr = prfind(pr->ps_oppid); /* not being traced any more */ pr->ps_oppid = 0; atomic_clearbits_int(&pr->ps_flags, PS_TRACED); process_reparent(pr, ppr ? ppr : initprocess); } void process_clear_orphan(struct process *pr) { if (pr->ps_flags & PS_ORPHAN) { LIST_REMOVE(pr, ps_orphan); atomic_clearbits_int(&pr->ps_flags, PS_ORPHAN); } } /* * make process 'parent' the new parent of process 'child'. */ void process_reparent(struct process *child, struct process *parent) { if (child->ps_pptr == parent) return; KASSERT(child->ps_oppid == 0 || child->ps_oppid == child->ps_pptr->ps_pid); LIST_REMOVE(child, ps_sibling); LIST_INSERT_HEAD(&parent->ps_children, child, ps_sibling); process_clear_orphan(child); if (child->ps_flags & PS_TRACED) { atomic_setbits_int(&child->ps_flags, PS_ORPHAN); LIST_INSERT_HEAD(&child->ps_pptr->ps_orphans, child, ps_orphan); } child->ps_pptr = parent; child->ps_ppid = parent->ps_pid; } void process_zap(struct process *pr) { struct vnode *otvp; struct proc *p = pr->ps_mainproc; /* * Finally finished with old proc entry. * Unlink it from its process group and free it. */ leavepgrp(pr); LIST_REMOVE(pr, ps_sibling); process_clear_orphan(pr); /* * Decrement the count of procs running with this uid. */ (void)chgproccnt(pr->ps_ucred->cr_ruid, -1); /* * Release reference to text vnode */ otvp = pr->ps_textvp; pr->ps_textvp = NULL; if (otvp) vrele(otvp); KASSERT(pr->ps_threadcnt == 0); KASSERT(pr->ps_exitcnt == 1); if (pr->ps_ptstat != NULL) free(pr->ps_ptstat, M_SUBPROC, sizeof(*pr->ps_ptstat)); pool_put(&rusage_pool, pr->ps_ru); KASSERT(TAILQ_EMPTY(&pr->ps_threads)); sigactsfree(pr->ps_sigacts); lim_free(pr->ps_limit); crfree(pr->ps_ucred); pool_put(&process_pool, pr); nprocesses--; proc_free(p); }
6 1 2 2 1 3 5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 /* $OpenBSD: ip_gre.c,v 1.87 2023/12/15 00:24:56 bluhm Exp $ */ /* $NetBSD: ip_gre.c,v 1.9 1999/10/25 19:18:11 drochner Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Heiko W.Rupp <hwr@pilhuhn.de> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * decapsulate tunneled packets and send them on * output half is in net/if_gre.[ch] * This currently handles IPPROTO_GRE, IPPROTO_MOBILE */ #include "gre.h" #if NGRE > 0 #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/protosw.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/sysctl.h> #include <net/if.h> #include <net/if_var.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_gre.h> #include <netinet/ip_var.h> #include <netinet/in_pcb.h> #include <netinet/in_var.h> #ifdef PIPEX #include <net/pipex.h> #endif const struct pr_usrreqs gre_usrreqs = { .pru_attach = rip_attach, .pru_detach = rip_detach, .pru_bind = rip_bind, .pru_connect = rip_connect, .pru_disconnect = rip_disconnect, .pru_shutdown = rip_shutdown, .pru_send = gre_send, .pru_control = in_control, .pru_sockaddr = in_sockaddr, .pru_peeraddr = in_peeraddr, }; int gre_send(struct socket *so, struct mbuf *m, struct mbuf *nam, struct mbuf *control) { #ifdef PIPEX struct inpcb *inp = sotoinpcb(so); if (inp->inp_pipex) { struct sockaddr_in *sin4; const struct in_addr *ina_dst; ina_dst = NULL; if ((so->so_state & SS_ISCONNECTED) != 0) ina_dst = &inp->inp_laddr; else if (nam) { if (in_nam2sin(nam, &sin4) == 0) ina_dst = &sin4->sin_addr; } if (ina_dst != NULL) { struct pipex_session *session; session = pipex_pptp_userland_lookup_session_ipv4(m, *ina_dst); if(session != NULL) { m = pipex_pptp_userland_output(m, session); pipex_rele_session(session); } } if (m == NULL) { m_freem(control); return (ENOMEM); } } #endif return rip_send(so, m, nam, control); } #endif /* if NGRE > 0 */
146 147 4 79 56 65 86 19 217 217 7 65 143 53 187 152 64 115 311 24 132 111 395 126 311 24 1 23 359 358 2 3 13 175 13 4 4 4 3 1 42 43 39 4 1 2 381 686 619 290 38 38 38 38 7 28 43 23 22 20 18 22 23 5 15 31 31 23 17 5 31 31 5 5 31 43 43 13 39 1 37 31 37 85 85 71 37 60 24 75 10 85 61 33 72 69 3 1 41 24 3 60 2 59 8 65 60 4 65 38 18 20 33 18 24 71 70 70 12 69 7 36 36 37 37 22 37 22 25 34 42 40 33 30 43 42 40 33 41 33 13 33 35 36 23 13 24 38 29 18 38 23 23 19 23 21 23 23 9 6 6 6 6 38 38 38 8 7 8 4 1 2 1 64 83 3 1 2 2 2 2 2 1 11 90 85 11 3 41 2 2 29 30 24 30 30 2 15 29 29 30 29 11 18 6 2 10 10 16 45 35 50 60 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 /* $OpenBSD: route.c,v 1.436 2024/03/31 15:53:12 bluhm Exp $ */ /* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 1980, 1986, 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)route.c 8.2 (Berkeley) 11/15/93 */ /* * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 * * NRL grants permission for redistribution and use in source and binary * forms, with or without modification, of the software and documentation * created at NRL provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgements: * This product includes software developed by the University of * California, Berkeley and its contributors. * This product includes software developed at the Information * Technology Division, US Naval Research Laboratory. * 4. Neither the name of the NRL nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the US Naval * Research Laboratory (NRL). */ #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/timeout.h> #include <sys/domain.h> #include <sys/ioctl.h> #include <sys/kernel.h> #include <sys/queue.h> #include <sys/pool.h> #include <sys/atomic.h> #include <sys/mutex.h> #include <net/if.h> #include <net/if_var.h> #include <net/if_dl.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/ip_var.h> #include <netinet/in_var.h> #ifdef INET6 #include <netinet/ip6.h> #include <netinet6/ip6_var.h> #include <netinet6/in6_var.h> #endif #ifdef MPLS #include <netmpls/mpls.h> #endif #ifdef BFD #include <net/bfd.h> #endif /* * Locks used to protect struct members: * a atomic operations * I immutable after creation * L rtlabel_mtx * T rttimer_mtx */ #define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) /* Give some jitter to hash, to avoid synchronization between routers. */ static uint32_t rt_hashjitter; extern unsigned int rtmap_limit; struct cpumem *rtcounters; int rttrash; /* [a] routes not in table but not freed */ u_long rtgeneration; /* [a] generation number, routes changed */ struct pool rtentry_pool; /* pool for rtentry structures */ struct pool rttimer_pool; /* pool for rttimer structures */ int rt_setgwroute(struct rtentry *, const struct sockaddr *, u_int); void rt_putgwroute(struct rtentry *, struct rtentry *); int rtflushclone1(struct rtentry *, void *, u_int); int rtflushclone(struct rtentry *, unsigned int); int rt_ifa_purge_walker(struct rtentry *, void *, unsigned int); struct rtentry *rt_match(const struct sockaddr *, uint32_t *, int, unsigned int); int rt_clone(struct rtentry **, const struct sockaddr *, unsigned int); struct sockaddr *rt_plentosa(sa_family_t, int, struct sockaddr_in6 *); static int rt_copysa(const struct sockaddr *, const struct sockaddr *, struct sockaddr **); #define LABELID_MAX 50000 struct rt_label { TAILQ_ENTRY(rt_label) rtl_entry; /* [L] */ char rtl_name[RTLABEL_LEN]; /* [I] */ u_int16_t rtl_id; /* [I] */ int rtl_ref; /* [L] */ }; TAILQ_HEAD(rt_labels, rt_label) rt_labels = TAILQ_HEAD_INITIALIZER(rt_labels); /* [L] */ struct mutex rtlabel_mtx = MUTEX_INITIALIZER(IPL_NET); void route_init(void) { rtcounters = counters_alloc(rts_ncounters); pool_init(&rtentry_pool, sizeof(struct rtentry), 0, IPL_MPFLOOR, 0, "rtentry", NULL); while (rt_hashjitter == 0) rt_hashjitter = arc4random(); #ifdef BFD bfdinit(); #endif } int route_cache(struct route *ro, const struct in_addr *dst, const struct in_addr *src, u_int rtableid) { u_long gen; gen = atomic_load_long(&rtgeneration); membar_consumer(); if (rtisvalid(ro->ro_rt) && ro->ro_generation == gen && ro->ro_tableid == rtableid && ro->ro_dstsa.sa_family == AF_INET && ro->ro_dstsin.sin_addr.s_addr == dst->s_addr) { if (src == NULL || !ipmultipath || !ISSET(ro->ro_rt->rt_flags, RTF_MPATH) || (ro->ro_srcin.s_addr != INADDR_ANY && ro->ro_srcin.s_addr == src->s_addr)) { ipstat_inc(ips_rtcachehit); return (0); } } ipstat_inc(ips_rtcachemiss); rtfree(ro->ro_rt); memset(ro, 0, sizeof(*ro)); ro->ro_generation = gen; ro->ro_tableid = rtableid; ro->ro_dstsin.sin_family = AF_INET; ro->ro_dstsin.sin_len = sizeof(struct sockaddr_in); ro->ro_dstsin.sin_addr = *dst; if (src != NULL) ro->ro_srcin = *src; return (ESRCH); } /* * Check cache for route, else allocate a new one, potentially using multipath * to select the peer. Update cache and return valid route or NULL. */ struct rtentry * route_mpath(struct route *ro, const struct in_addr *dst, const struct in_addr *src, u_int rtableid) { if (route_cache(ro, dst, src, rtableid)) { uint32_t *s = NULL; if (ro->ro_srcin.s_addr != INADDR_ANY) s = &ro->ro_srcin.s_addr; ro->ro_rt = rtalloc_mpath(&ro->ro_dstsa, s, ro->ro_tableid); } return (ro->ro_rt); } #ifdef INET6 int route6_cache(struct route *ro, const struct in6_addr *dst, const struct in6_addr *src, u_int rtableid) { u_long gen; gen = atomic_load_long(&rtgeneration); membar_consumer(); if (rtisvalid(ro->ro_rt) && ro->ro_generation == gen && ro->ro_tableid == rtableid && ro->ro_dstsa.sa_family == AF_INET6 && IN6_ARE_ADDR_EQUAL(&ro->ro_dstsin6.sin6_addr, dst)) { if (src == NULL || !ip6_multipath || !ISSET(ro->ro_rt->rt_flags, RTF_MPATH) || (!IN6_IS_ADDR_UNSPECIFIED(&ro->ro_srcin6) && IN6_ARE_ADDR_EQUAL(&ro->ro_srcin6, src))) { ip6stat_inc(ip6s_rtcachehit); return (0); } } ip6stat_inc(ip6s_rtcachemiss); rtfree(ro->ro_rt); memset(ro, 0, sizeof(*ro)); ro->ro_generation = gen; ro->ro_tableid = rtableid; ro->ro_dstsin6.sin6_family = AF_INET6; ro->ro_dstsin6.sin6_len = sizeof(struct sockaddr_in6); ro->ro_dstsin6.sin6_addr = *dst; if (src != NULL) ro->ro_srcin6 = *src; return (ESRCH); } struct rtentry * route6_mpath(struct route *ro, const struct in6_addr *dst, const struct in6_addr *src, u_int rtableid) { if (route6_cache(ro, dst, src, rtableid)) { uint32_t *s = NULL; if (!IN6_IS_ADDR_UNSPECIFIED(&ro->ro_srcin6)) s = &ro->ro_srcin6.s6_addr32[0]; ro->ro_rt = rtalloc_mpath(&ro->ro_dstsa, s, ro->ro_tableid); } return (ro->ro_rt); } #endif /* * Returns 1 if the (cached) ``rt'' entry is still valid, 0 otherwise. */ int rtisvalid(struct rtentry *rt) { if (rt == NULL) return (0); if (!ISSET(rt->rt_flags, RTF_UP)) return (0); if (ISSET(rt->rt_flags, RTF_GATEWAY)) { KASSERT(rt->rt_gwroute != NULL); KASSERT(!ISSET(rt->rt_gwroute->rt_flags, RTF_GATEWAY)); if (!ISSET(rt->rt_gwroute->rt_flags, RTF_UP)) return (0); } return (1); } /* * Do the actual lookup for rtalloc(9), do not use directly! * * Return the best matching entry for the destination ``dst''. * * "RT_RESOLVE" means that a corresponding L2 entry should * be added to the routing table and resolved (via ARP or * NDP), if it does not exist. */ struct rtentry * rt_match(const struct sockaddr *dst, uint32_t *src, int flags, unsigned int tableid) { struct rtentry *rt = NULL; rt = rtable_match(tableid, dst, src); if (rt == NULL) { rtstat_inc(rts_unreach); return (NULL); } if (ISSET(rt->rt_flags, RTF_CLONING) && ISSET(flags, RT_RESOLVE)) rt_clone(&rt, dst, tableid); rt->rt_use++; return (rt); } int rt_clone(struct rtentry **rtp, const struct sockaddr *dst, unsigned int rtableid) { struct rt_addrinfo info; struct rtentry *rt = *rtp; int error = 0; memset(&info, 0, sizeof(info)); info.rti_info[RTAX_DST] = dst; /* * The priority of cloned route should be different * to avoid conflict with /32 cloning routes. * * It should also be higher to let the ARP layer find * cloned routes instead of the cloning one. */ KERNEL_LOCK(); error = rtrequest(RTM_RESOLVE, &info, rt->rt_priority - 1, &rt, rtableid); KERNEL_UNLOCK(); if (error) { rtm_miss(RTM_MISS, &info, 0, RTP_NONE, 0, error, rtableid); } else { /* Inform listeners of the new route */ rtm_send(rt, RTM_ADD, 0, rtableid); rtfree(*rtp); *rtp = rt; } return (error); } /* * Originated from bridge_hash() in if_bridge.c */ #define mix(a, b, c) do { \ a -= b; a -= c; a ^= (c >> 13); \ b -= c; b -= a; b ^= (a << 8); \ c -= a; c -= b; c ^= (b >> 13); \ a -= b; a -= c; a ^= (c >> 12); \ b -= c; b -= a; b ^= (a << 16); \ c -= a; c -= b; c ^= (b >> 5); \ a -= b; a -= c; a ^= (c >> 3); \ b -= c; b -= a; b ^= (a << 10); \ c -= a; c -= b; c ^= (b >> 15); \ } while (0) int rt_hash(struct rtentry *rt, const struct sockaddr *dst, uint32_t *src) { uint32_t a, b, c; if (src == NULL || !rtisvalid(rt) || !ISSET(rt->rt_flags, RTF_MPATH)) return (-1); a = b = 0x9e3779b9; c = rt_hashjitter; switch (dst->sa_family) { case AF_INET: { const struct sockaddr_in *sin; if (!ipmultipath) return (-1); sin = satosin_const(dst); a += sin->sin_addr.s_addr; b += src[0]; mix(a, b, c); break; } #ifdef INET6 case AF_INET6: { const struct sockaddr_in6 *sin6; if (!ip6_multipath) return (-1); sin6 = satosin6_const(dst); a += sin6->sin6_addr.s6_addr32[0]; b += sin6->sin6_addr.s6_addr32[2]; c += src[0]; mix(a, b, c); a += sin6->sin6_addr.s6_addr32[1]; b += sin6->sin6_addr.s6_addr32[3]; c += src[1]; mix(a, b, c); a += sin6->sin6_addr.s6_addr32[2]; b += sin6->sin6_addr.s6_addr32[1]; c += src[2]; mix(a, b, c); a += sin6->sin6_addr.s6_addr32[3]; b += sin6->sin6_addr.s6_addr32[0]; c += src[3]; mix(a, b, c); break; } #endif /* INET6 */ } return (c & 0xffff); } /* * Allocate a route, potentially using multipath to select the peer. */ struct rtentry * rtalloc_mpath(const struct sockaddr *dst, uint32_t *src, unsigned int rtableid) { return (rt_match(dst, src, RT_RESOLVE, rtableid)); } /* * Look in the routing table for the best matching entry for * ``dst''. * * If a route with a gateway is found and its next hop is no * longer valid, try to cache it. */ struct rtentry * rtalloc(const struct sockaddr *dst, int flags, unsigned int rtableid) { return (rt_match(dst, NULL, flags, rtableid)); } /* * Cache the route entry corresponding to a reachable next hop in * the gateway entry ``rt''. */ int rt_setgwroute(struct rtentry *rt, const struct sockaddr *gate, u_int rtableid) { struct rtentry *prt, *nhrt; unsigned int rdomain = rtable_l2(rtableid); int error; NET_ASSERT_LOCKED(); /* If we cannot find a valid next hop bail. */ nhrt = rt_match(gate, NULL, RT_RESOLVE, rdomain); if (nhrt == NULL) return (ENOENT); /* Next hop entry must be on the same interface. */ if (nhrt->rt_ifidx != rt->rt_ifidx) { struct sockaddr_in6 sa_mask; if (!ISSET(nhrt->rt_flags, RTF_LLINFO) || !ISSET(nhrt->rt_flags, RTF_CLONED)) { rtfree(nhrt); return (EHOSTUNREACH); } /* * We found a L2 entry, so we might have multiple * RTF_CLONING routes for the same subnet. Query * the first route of the multipath chain and iterate * until we find the correct one. */ prt = rtable_lookup(rdomain, rt_key(nhrt->rt_parent), rt_plen2mask(nhrt->rt_parent, &sa_mask), NULL, RTP_ANY); rtfree(nhrt); while (prt != NULL && prt->rt_ifidx != rt->rt_ifidx) prt = rtable_iterate(prt); /* We found nothing or a non-cloning MPATH route. */ if (prt == NULL || !ISSET(prt->rt_flags, RTF_CLONING)) { rtfree(prt); return (EHOSTUNREACH); } error = rt_clone(&prt, gate, rdomain); if (error) { rtfree(prt); return (error); } nhrt = prt; } /* * Next hop must be reachable, this also prevents rtentry * loops for example when rt->rt_gwroute points to rt. */ if (ISSET(nhrt->rt_flags, RTF_CLONING|RTF_GATEWAY)) { rtfree(nhrt); return (ENETUNREACH); } /* * If the MTU of next hop is 0, this will reset the MTU of the * route to run PMTUD again from scratch. */ if (!ISSET(rt->rt_locks, RTV_MTU) && (rt->rt_mtu > nhrt->rt_mtu)) rt->rt_mtu = nhrt->rt_mtu; /* * To avoid reference counting problems when writing link-layer * addresses in an outgoing packet, we ensure that the lifetime * of a cached entry is greater than the bigger lifetime of the * gateway entries it is pointed by. */ nhrt->rt_flags |= RTF_CACHED; nhrt->rt_cachecnt++; /* commit */ rt_putgwroute(rt, nhrt); return (0); } /* * Invalidate the cached route entry of the gateway entry ``rt''. */ void rt_putgwroute(struct rtentry *rt, struct rtentry *nhrt) { struct rtentry *onhrt; NET_ASSERT_LOCKED(); if (!ISSET(rt->rt_flags, RTF_GATEWAY)) return; /* this is protected as per [X] in route.h */ onhrt = rt->rt_gwroute; rt->rt_gwroute = nhrt; if (onhrt != NULL) { KASSERT(onhrt->rt_cachecnt > 0); KASSERT(ISSET(onhrt->rt_flags, RTF_CACHED)); --onhrt->rt_cachecnt; if (onhrt->rt_cachecnt == 0) CLR(onhrt->rt_flags, RTF_CACHED); rtfree(onhrt); } } void rtref(struct rtentry *rt) { refcnt_take(&rt->rt_refcnt); } void rtfree(struct rtentry *rt) { if (rt == NULL) return; if (refcnt_rele(&rt->rt_refcnt) == 0) return; KASSERT(!ISSET(rt->rt_flags, RTF_UP)); KASSERT(!RT_ROOT(rt)); atomic_dec_int(&rttrash); rt_timer_remove_all(rt); ifafree(rt->rt_ifa); rtlabel_unref(rt->rt_labelid); #ifdef MPLS rt_mpls_clear(rt); #endif if (rt->rt_gateway != NULL) { free(rt->rt_gateway, M_RTABLE, ROUNDUP(rt->rt_gateway->sa_len)); } free(rt_key(rt), M_RTABLE, rt_key(rt)->sa_len); pool_put(&rtentry_pool, rt); } struct ifaddr * ifaref(struct ifaddr *ifa) { refcnt_take(&ifa->ifa_refcnt); return ifa; } void ifafree(struct ifaddr *ifa) { if (refcnt_rele(&ifa->ifa_refcnt) == 0) return; free(ifa, M_IFADDR, 0); } /* * Force a routing table entry to the specified * destination to go through the given gateway. * Normally called as a result of a routing redirect * message from the network layer. */ void rtredirect(struct sockaddr *dst, struct sockaddr *gateway, struct sockaddr *src, struct rtentry **rtp, unsigned int rdomain) { struct rtentry *rt; int error = 0; enum rtstat_counters stat = rts_ncounters; struct rt_addrinfo info; struct ifaddr *ifa; unsigned int ifidx = 0; int flags = RTF_GATEWAY|RTF_HOST; uint8_t prio = RTP_NONE; NET_ASSERT_LOCKED(); /* verify the gateway is directly reachable */ rt = rtalloc(gateway, 0, rdomain); if (!rtisvalid(rt) || ISSET(rt->rt_flags, RTF_GATEWAY)) { rtfree(rt); error = ENETUNREACH; goto out; } ifidx = rt->rt_ifidx; ifa = rt->rt_ifa; rtfree(rt); rt = NULL; rt = rtable_lookup(rdomain, dst, NULL, NULL, RTP_ANY); /* * If the redirect isn't from our current router for this dst, * it's either old or wrong. If it redirects us to ourselves, * we have a routing loop, perhaps as a result of an interface * going down recently. */ #define equal(a1, a2) \ ((a1)->sa_len == (a2)->sa_len && \ bcmp((caddr_t)(a1), (caddr_t)(a2), (a1)->sa_len) == 0) if (rt != NULL && (!equal(src, rt->rt_gateway) || rt->rt_ifa != ifa)) error = EINVAL; else if (ifa_ifwithaddr(gateway, rdomain) != NULL || (gateway->sa_family == AF_INET && in_broadcast(satosin(gateway)->sin_addr, rdomain))) error = EHOSTUNREACH; if (error) goto done; /* * Create a new entry if we just got back a wildcard entry * or the lookup failed. This is necessary for hosts * which use routing redirects generated by smart gateways * to dynamically build the routing tables. */ if (rt == NULL) goto create; /* * Don't listen to the redirect if it's * for a route to an interface. */ if (ISSET(rt->rt_flags, RTF_GATEWAY)) { if (!ISSET(rt->rt_flags, RTF_HOST)) { /* * Changing from route to net => route to host. * Create new route, rather than smashing route to net. */ create: rtfree(rt); flags |= RTF_DYNAMIC; bzero(&info, sizeof(info)); info.rti_info[RTAX_DST] = dst; info.rti_info[RTAX_GATEWAY] = gateway; info.rti_ifa = ifa; info.rti_flags = flags; rt = NULL; error = rtrequest(RTM_ADD, &info, RTP_DEFAULT, &rt, rdomain); if (error == 0) { flags = rt->rt_flags; prio = rt->rt_priority; } stat = rts_dynamic; } else { /* * Smash the current notion of the gateway to * this destination. Should check about netmask!!! */ rt->rt_flags |= RTF_MODIFIED; flags |= RTF_MODIFIED; prio = rt->rt_priority; stat = rts_newgateway; rt_setgate(rt, gateway, rdomain); } } else error = EHOSTUNREACH; done: if (rt) { if (rtp && !error) *rtp = rt; else rtfree(rt); } out: if (error) rtstat_inc(rts_badredirect); else if (stat != rts_ncounters) rtstat_inc(stat); bzero((caddr_t)&info, sizeof(info)); info.rti_info[RTAX_DST] = dst; info.rti_info[RTAX_GATEWAY] = gateway; info.rti_info[RTAX_AUTHOR] = src; rtm_miss(RTM_REDIRECT, &info, flags, prio, ifidx, error, rdomain); } /* * Delete a route and generate a message */ int rtdeletemsg(struct rtentry *rt, struct ifnet *ifp, u_int tableid) { int error; struct rt_addrinfo info; struct sockaddr_rtlabel sa_rl; struct sockaddr_in6 sa_mask; KASSERT(rt->rt_ifidx == ifp->if_index); /* * Request the new route so that the entry is not actually * deleted. That will allow the information being reported to * be accurate (and consistent with route_output()). */ memset(&info, 0, sizeof(info)); info.rti_info[RTAX_DST] = rt_key(rt); info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; if (!ISSET(rt->rt_flags, RTF_HOST)) info.rti_info[RTAX_NETMASK] = rt_plen2mask(rt, &sa_mask); info.rti_info[RTAX_LABEL] = rtlabel_id2sa(rt->rt_labelid, &sa_rl); info.rti_flags = rt->rt_flags; info.rti_info[RTAX_IFP] = sdltosa(ifp->if_sadl); info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; error = rtrequest_delete(&info, rt->rt_priority, ifp, &rt, tableid); rtm_miss(RTM_DELETE, &info, info.rti_flags, rt->rt_priority, rt->rt_ifidx, error, tableid); if (error == 0) rtfree(rt); return (error); } static inline int rtequal(struct rtentry *a, struct rtentry *b) { if (a == b) return 1; if (memcmp(rt_key(a), rt_key(b), rt_key(a)->sa_len) == 0 && rt_plen(a) == rt_plen(b)) return 1; else return 0; } int rtflushclone1(struct rtentry *rt, void *arg, u_int id) { struct rtentry *cloningrt = arg; struct ifnet *ifp; if (!ISSET(rt->rt_flags, RTF_CLONED)) return 0; /* Cached route must stay alive as long as their parent are alive. */ if (ISSET(rt->rt_flags, RTF_CACHED) && (rt->rt_parent != cloningrt)) return 0; if (!rtequal(rt->rt_parent, cloningrt)) return 0; /* * This happens when an interface with a RTF_CLONING route is * being detached. In this case it's safe to bail because all * the routes are being purged by rt_ifa_purge(). */ ifp = if_get(rt->rt_ifidx); if (ifp == NULL) return 0; if_put(ifp); return EEXIST; } int rtflushclone(struct rtentry *parent, unsigned int rtableid) { struct rtentry *rt = NULL; struct ifnet *ifp; int error; #ifdef DIAGNOSTIC if (!parent || (parent->rt_flags & RTF_CLONING) == 0) panic("rtflushclone: called with a non-cloning route"); #endif do { error = rtable_walk(rtableid, rt_key(parent)->sa_family, &rt, rtflushclone1, parent); if (rt != NULL && error == EEXIST) { ifp = if_get(rt->rt_ifidx); if (ifp == NULL) { error = EAGAIN; } else { error = rtdeletemsg(rt, ifp, rtableid); if (error == 0) error = EAGAIN; if_put(ifp); } } rtfree(rt); rt = NULL; } while (error == EAGAIN); return error; } int rtrequest_delete(struct rt_addrinfo *info, u_int8_t prio, struct ifnet *ifp, struct rtentry **ret_nrt, u_int tableid) { struct rtentry *rt; int error; NET_ASSERT_LOCKED(); if (!rtable_exists(tableid)) return (EAFNOSUPPORT); rt = rtable_lookup(tableid, info->rti_info[RTAX_DST], info->rti_info[RTAX_NETMASK], info->rti_info[RTAX_GATEWAY], prio); if (rt == NULL) return (ESRCH); /* Make sure that's the route the caller want to delete. */ if (ifp != NULL && ifp->if_index != rt->rt_ifidx) { rtfree(rt); return (ESRCH); } #ifdef BFD if (ISSET(rt->rt_flags, RTF_BFD)) bfdclear(rt); #endif error = rtable_delete(tableid, info->rti_info[RTAX_DST], info->rti_info[RTAX_NETMASK], rt); if (error != 0) { rtfree(rt); return (ESRCH); } /* Release next hop cache before flushing cloned entries. */ rt_putgwroute(rt, NULL); /* Clean up any cloned children. */ if (ISSET(rt->rt_flags, RTF_CLONING)) rtflushclone(rt, tableid); rtfree(rt->rt_parent); rt->rt_parent = NULL; rt->rt_flags &= ~RTF_UP; KASSERT(ifp->if_index == rt->rt_ifidx); ifp->if_rtrequest(ifp, RTM_DELETE, rt); atomic_inc_int(&rttrash); if (ret_nrt != NULL) *ret_nrt = rt; else rtfree(rt); membar_producer(); atomic_inc_long(&rtgeneration); return (0); } int rtrequest(int req, struct rt_addrinfo *info, u_int8_t prio, struct rtentry **ret_nrt, u_int tableid) { struct ifnet *ifp; struct rtentry *rt, *crt; struct ifaddr *ifa; struct sockaddr *ndst; struct sockaddr_rtlabel *sa_rl, sa_rl2; struct sockaddr_dl sa_dl = { sizeof(sa_dl), AF_LINK }; int error; NET_ASSERT_LOCKED(); if (!rtable_exists(tableid)) return (EAFNOSUPPORT); if (info->rti_flags & RTF_HOST) info->rti_info[RTAX_NETMASK] = NULL; switch (req) { case RTM_DELETE: return (EINVAL); case RTM_RESOLVE: if (ret_nrt == NULL || (rt = *ret_nrt) == NULL) return (EINVAL); if ((rt->rt_flags & RTF_CLONING) == 0) return (EINVAL); KASSERT(rt->rt_ifa->ifa_ifp != NULL); info->rti_ifa = rt->rt_ifa; info->rti_flags = rt->rt_flags | (RTF_CLONED|RTF_HOST); info->rti_flags &= ~(RTF_CLONING|RTF_CONNECTED|RTF_STATIC); info->rti_info[RTAX_GATEWAY] = sdltosa(&sa_dl); info->rti_info[RTAX_LABEL] = rtlabel_id2sa(rt->rt_labelid, &sa_rl2); /* FALLTHROUGH */ case RTM_ADD: if (info->rti_ifa == NULL) return (EINVAL); ifa = info->rti_ifa; ifp = ifa->ifa_ifp; if (prio == 0) prio = ifp->if_priority + RTP_STATIC; error = rt_copysa(info->rti_info[RTAX_DST], info->rti_info[RTAX_NETMASK], &ndst); if (error) return (error); rt = pool_get(&rtentry_pool, PR_NOWAIT | PR_ZERO); if (rt == NULL) { free(ndst, M_RTABLE, ndst->sa_len); return (ENOBUFS); } refcnt_init_trace(&rt->rt_refcnt, DT_REFCNT_IDX_RTENTRY); rt->rt_flags = info->rti_flags | RTF_UP; rt->rt_priority = prio; /* init routing priority */ LIST_INIT(&rt->rt_timer); /* Check the link state if the table supports it. */ if (rtable_mpath_capable(tableid, ndst->sa_family) && !ISSET(rt->rt_flags, RTF_LOCAL) && (!LINK_STATE_IS_UP(ifp->if_link_state) || !ISSET(ifp->if_flags, IFF_UP))) { rt->rt_flags &= ~RTF_UP; rt->rt_priority |= RTP_DOWN; } if (info->rti_info[RTAX_LABEL] != NULL) { sa_rl = (struct sockaddr_rtlabel *) info->rti_info[RTAX_LABEL]; rt->rt_labelid = rtlabel_name2id(sa_rl->sr_label); } #ifdef MPLS /* We have to allocate additional space for MPLS infos */ if (info->rti_flags & RTF_MPLS && (info->rti_info[RTAX_SRC] != NULL || info->rti_info[RTAX_DST]->sa_family == AF_MPLS)) { error = rt_mpls_set(rt, info->rti_info[RTAX_SRC], info->rti_mpls); if (error) { free(ndst, M_RTABLE, ndst->sa_len); pool_put(&rtentry_pool, rt); return (error); } } else rt_mpls_clear(rt); #endif rt->rt_ifa = ifaref(ifa); rt->rt_ifidx = ifp->if_index; /* * Copy metrics and a back pointer from the cloned * route's parent. */ if (ISSET(rt->rt_flags, RTF_CLONED)) { rtref(*ret_nrt); rt->rt_parent = *ret_nrt; rt->rt_rmx = (*ret_nrt)->rt_rmx; } /* * We must set rt->rt_gateway before adding ``rt'' to * the routing table because the radix MPATH code use * it to (re)order routes. */ if ((error = rt_setgate(rt, info->rti_info[RTAX_GATEWAY], tableid))) { ifafree(ifa); rtfree(rt->rt_parent); rt_putgwroute(rt, NULL); if (rt->rt_gateway != NULL) { free(rt->rt_gateway, M_RTABLE, ROUNDUP(rt->rt_gateway->sa_len)); } free(ndst, M_RTABLE, ndst->sa_len); pool_put(&rtentry_pool, rt); return (error); } error = rtable_insert(tableid, ndst, info->rti_info[RTAX_NETMASK], info->rti_info[RTAX_GATEWAY], rt->rt_priority, rt); if (error != 0 && (crt = rtable_match(tableid, ndst, NULL)) != NULL) { /* overwrite cloned route */ if (ISSET(crt->rt_flags, RTF_CLONED) && !ISSET(crt->rt_flags, RTF_CACHED)) { struct ifnet *cifp; cifp = if_get(crt->rt_ifidx); KASSERT(cifp != NULL); rtdeletemsg(crt, cifp, tableid); if_put(cifp); error = rtable_insert(tableid, ndst, info->rti_info[RTAX_NETMASK], info->rti_info[RTAX_GATEWAY], rt->rt_priority, rt); } rtfree(crt); } if (error != 0) { ifafree(ifa); rtfree(rt->rt_parent); rt_putgwroute(rt, NULL); if (rt->rt_gateway != NULL) { free(rt->rt_gateway, M_RTABLE, ROUNDUP(rt->rt_gateway->sa_len)); } free(ndst, M_RTABLE, ndst->sa_len); pool_put(&rtentry_pool, rt); return (EEXIST); } ifp->if_rtrequest(ifp, req, rt); if_group_routechange(info->rti_info[RTAX_DST], info->rti_info[RTAX_NETMASK]); if (ret_nrt != NULL) *ret_nrt = rt; else rtfree(rt); membar_producer(); atomic_inc_long(&rtgeneration); break; } return (0); } int rt_setgate(struct rtentry *rt, const struct sockaddr *gate, u_int rtableid) { int glen = ROUNDUP(gate->sa_len); struct sockaddr *sa, *osa; int error = 0; KASSERT(gate != NULL); if (rt->rt_gateway == gate) { /* nop */ return (0); }; sa = malloc(glen, M_RTABLE, M_NOWAIT | M_ZERO); if (sa == NULL) return (ENOBUFS); memcpy(sa, gate, gate->sa_len); KERNEL_LOCK(); /* see [X] in route.h */ osa = rt->rt_gateway; rt->rt_gateway = sa; if (ISSET(rt->rt_flags, RTF_GATEWAY)) error = rt_setgwroute(rt, gate, rtableid); KERNEL_UNLOCK(); if (osa != NULL) free(osa, M_RTABLE, ROUNDUP(osa->sa_len)); return (error); } /* * Return the route entry containing the next hop link-layer * address corresponding to ``rt''. */ struct rtentry * rt_getll(struct rtentry *rt) { if (ISSET(rt->rt_flags, RTF_GATEWAY)) { KASSERT(rt->rt_gwroute != NULL); return (rt->rt_gwroute); } return (rt); } void rt_maskedcopy(struct sockaddr *src, struct sockaddr *dst, struct sockaddr *netmask) { u_char *cp1 = (u_char *)src; u_char *cp2 = (u_char *)dst; u_char *cp3 = (u_char *)netmask; u_char *cplim = cp2 + *cp3; u_char *cplim2 = cp2 + *cp1; *cp2++ = *cp1++; *cp2++ = *cp1++; /* copies sa_len & sa_family */ cp3 += 2; if (cplim > cplim2) cplim = cplim2; while (cp2 < cplim) *cp2++ = *cp1++ & *cp3++; if (cp2 < cplim2) bzero(cp2, cplim2 - cp2); } /* * allocate new sockaddr structure based on the user supplied src and mask * that is useable for the routing table. */ static int rt_copysa(const struct sockaddr *src, const struct sockaddr *mask, struct sockaddr **dst) { static const u_char maskarray[] = { 0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe }; struct sockaddr *ndst; const struct domain *dp; u_char *csrc, *cdst; int i, plen; for (i = 0; (dp = domains[i]) != NULL; i++) { if (dp->dom_rtoffset == 0) continue; if (src->sa_family == dp->dom_family) break; } if (dp == NULL) return (EAFNOSUPPORT); if (src->sa_len < dp->dom_sasize) return (EINVAL); plen = rtable_satoplen(src->sa_family, mask); if (plen == -1) return (EINVAL); ndst = malloc(dp->dom_sasize, M_RTABLE, M_NOWAIT|M_ZERO); if (ndst == NULL) return (ENOBUFS); ndst->sa_family = src->sa_family; ndst->sa_len = dp->dom_sasize; csrc = (u_char *)src + dp->dom_rtoffset; cdst = (u_char *)ndst + dp->dom_rtoffset; memcpy(cdst, csrc, plen / 8); if (plen % 8 != 0) cdst[plen / 8] = csrc[plen / 8] & maskarray[plen % 8]; *dst = ndst; return (0); } int rt_ifa_add(struct ifaddr *ifa, int flags, struct sockaddr *dst, unsigned int rdomain) { struct ifnet *ifp = ifa->ifa_ifp; struct rtentry *rt; struct sockaddr_rtlabel sa_rl; struct rt_addrinfo info; uint8_t prio = ifp->if_priority + RTP_STATIC; int error; KASSERT(rdomain == rtable_l2(rdomain)); memset(&info, 0, sizeof(info)); info.rti_ifa = ifa; info.rti_flags = flags; info.rti_info[RTAX_DST] = dst; if (flags & RTF_LLINFO) info.rti_info[RTAX_GATEWAY] = sdltosa(ifp->if_sadl); else info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr; info.rti_info[RTAX_LABEL] = rtlabel_id2sa(ifp->if_rtlabelid, &sa_rl); #ifdef MPLS if ((flags & RTF_MPLS) == RTF_MPLS) info.rti_mpls = MPLS_OP_POP; #endif /* MPLS */ if ((flags & RTF_HOST) == 0) info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; if (flags & (RTF_LOCAL|RTF_BROADCAST)) prio = RTP_LOCAL; if (flags & RTF_CONNECTED) prio = ifp->if_priority + RTP_CONNECTED; error = rtrequest(RTM_ADD, &info, prio, &rt, rdomain); if (error == 0) { /* * A local route is created for every address configured * on an interface, so use this information to notify * userland that a new address has been added. */ if (flags & RTF_LOCAL) rtm_addr(RTM_NEWADDR, ifa); rtm_send(rt, RTM_ADD, 0, rdomain); rtfree(rt); } return (error); } int rt_ifa_del(struct ifaddr *ifa, int flags, struct sockaddr *dst, unsigned int rdomain) { struct ifnet *ifp = ifa->ifa_ifp; struct rtentry *rt; struct mbuf *m = NULL; struct sockaddr *deldst; struct rt_addrinfo info; struct sockaddr_rtlabel sa_rl; uint8_t prio = ifp->if_priority + RTP_STATIC; int error; KASSERT(rdomain == rtable_l2(rdomain)); if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) { m = m_get(M_DONTWAIT, MT_SONAME); if (m == NULL) return (ENOBUFS); deldst = mtod(m, struct sockaddr *); rt_maskedcopy(dst, deldst, ifa->ifa_netmask); dst = deldst; } memset(&info, 0, sizeof(info)); info.rti_ifa = ifa; info.rti_flags = flags; info.rti_info[RTAX_DST] = dst; if ((flags & RTF_LLINFO) == 0) info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr; info.rti_info[RTAX_LABEL] = rtlabel_id2sa(ifp->if_rtlabelid, &sa_rl); if ((flags & RTF_HOST) == 0) info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; if (flags & (RTF_LOCAL|RTF_BROADCAST)) prio = RTP_LOCAL; if (flags & RTF_CONNECTED) prio = ifp->if_priority + RTP_CONNECTED; rtable_clearsource(rdomain, ifa->ifa_addr); error = rtrequest_delete(&info, prio, ifp, &rt, rdomain); if (error == 0) { rtm_send(rt, RTM_DELETE, 0, rdomain); if (flags & RTF_LOCAL) rtm_addr(RTM_DELADDR, ifa); rtfree(rt); } m_free(m); return (error); } /* * Add ifa's address as a local rtentry. */ int rt_ifa_addlocal(struct ifaddr *ifa) { struct ifnet *ifp = ifa->ifa_ifp; struct rtentry *rt; u_int flags = RTF_HOST|RTF_LOCAL; int error = 0; /* * If the configured address correspond to the magical "any" * address do not add a local route entry because that might * corrupt the routing tree which uses this value for the * default routes. */ switch (ifa->ifa_addr->sa_family) { case AF_INET: if (satosin(ifa->ifa_addr)->sin_addr.s_addr == INADDR_ANY) return (0); break; #ifdef INET6 case AF_INET6: if (IN6_ARE_ADDR_EQUAL(&satosin6(ifa->ifa_addr)->sin6_addr, &in6addr_any)) return (0); break; #endif default: break; } if (!ISSET(ifp->if_flags, (IFF_LOOPBACK|IFF_POINTOPOINT))) flags |= RTF_LLINFO; /* If there is no local entry, allocate one. */ rt = rtalloc(ifa->ifa_addr, 0, ifp->if_rdomain); if (rt == NULL || ISSET(rt->rt_flags, flags) != flags) { error = rt_ifa_add(ifa, flags | RTF_MPATH, ifa->ifa_addr, ifp->if_rdomain); } rtfree(rt); return (error); } /* * Remove local rtentry of ifa's address if it exists. */ int rt_ifa_dellocal(struct ifaddr *ifa) { struct ifnet *ifp = ifa->ifa_ifp; struct rtentry *rt; u_int flags = RTF_HOST|RTF_LOCAL; int error = 0; /* * We do not add local routes for such address, so do not bother * removing them. */ switch (ifa->ifa_addr->sa_family) { case AF_INET: if (satosin(ifa->ifa_addr)->sin_addr.s_addr == INADDR_ANY) return (0); break; #ifdef INET6 case AF_INET6: if (IN6_ARE_ADDR_EQUAL(&satosin6(ifa->ifa_addr)->sin6_addr, &in6addr_any)) return (0); break; #endif default: break; } if (!ISSET(ifp->if_flags, (IFF_LOOPBACK|IFF_POINTOPOINT))) flags |= RTF_LLINFO; /* * Before deleting, check if a corresponding local host * route surely exists. With this check, we can avoid to * delete an interface direct route whose destination is same * as the address being removed. This can happen when removing * a subnet-router anycast address on an interface attached * to a shared medium. */ rt = rtalloc(ifa->ifa_addr, 0, ifp->if_rdomain); if (rt != NULL && ISSET(rt->rt_flags, flags) == flags) { error = rt_ifa_del(ifa, flags, ifa->ifa_addr, ifp->if_rdomain); } rtfree(rt); return (error); } /* * Remove all addresses attached to ``ifa''. */ void rt_ifa_purge(struct ifaddr *ifa) { struct ifnet *ifp = ifa->ifa_ifp; struct rtentry *rt = NULL; unsigned int rtableid; int error, af = ifa->ifa_addr->sa_family; KASSERT(ifp != NULL); for (rtableid = 0; rtableid < rtmap_limit; rtableid++) { /* skip rtables that are not in the rdomain of the ifp */ if (rtable_l2(rtableid) != ifp->if_rdomain) continue; do { error = rtable_walk(rtableid, af, &rt, rt_ifa_purge_walker, ifa); if (rt != NULL && error == EEXIST) { error = rtdeletemsg(rt, ifp, rtableid); if (error == 0) error = EAGAIN; } rtfree(rt); rt = NULL; } while (error == EAGAIN); if (error == EAFNOSUPPORT) error = 0; if (error) break; } } int rt_ifa_purge_walker(struct rtentry *rt, void *vifa, unsigned int rtableid) { struct ifaddr *ifa = vifa; if (rt->rt_ifa == ifa) return EEXIST; return 0; } /* * Route timer routines. These routines allow functions to be called * for various routes at any time. This is useful in supporting * path MTU discovery and redirect route deletion. * * This is similar to some BSDI internal functions, but it provides * for multiple queues for efficiency's sake... */ struct mutex rttimer_mtx; struct rttimer { TAILQ_ENTRY(rttimer) rtt_next; /* [T] entry on timer queue */ LIST_ENTRY(rttimer) rtt_link; /* [T] timers per rtentry */ struct timeout rtt_timeout; /* [I] timeout for this entry */ struct rttimer_queue *rtt_queue; /* [I] back pointer to queue */ struct rtentry *rtt_rt; /* [T] back pointer to route */ time_t rtt_expire; /* [I] rt expire time */ u_int rtt_tableid; /* [I] rtable id of rtt_rt */ }; #define RTTIMER_CALLOUT(r) { \ if (r->rtt_queue->rtq_func != NULL) { \ (*r->rtt_queue->rtq_func)(r->rtt_rt, r->rtt_tableid); \ } else { \ struct ifnet *ifp; \ \ ifp = if_get(r->rtt_rt->rt_ifidx); \ if (ifp != NULL && \ (r->rtt_rt->rt_flags & (RTF_DYNAMIC|RTF_HOST)) == \ (RTF_DYNAMIC|RTF_HOST)) \ rtdeletemsg(r->rtt_rt, ifp, r->rtt_tableid); \ if_put(ifp); \ } \ } void rt_timer_init(void) { pool_init(&rttimer_pool, sizeof(struct rttimer), 0, IPL_MPFLOOR, 0, "rttmr", NULL); mtx_init(&rttimer_mtx, IPL_MPFLOOR); } void rt_timer_queue_init(struct rttimer_queue *rtq, int timeout, void (*func)(struct rtentry *, u_int)) { rtq->rtq_timeout = timeout; rtq->rtq_count = 0; rtq->rtq_func = func; TAILQ_INIT(&rtq->rtq_head); } void rt_timer_queue_change(struct rttimer_queue *rtq, int timeout) { mtx_enter(&rttimer_mtx); rtq->rtq_timeout = timeout; mtx_leave(&rttimer_mtx); } void rt_timer_queue_flush(struct rttimer_queue *rtq) { struct rttimer *r; TAILQ_HEAD(, rttimer) rttlist; NET_ASSERT_LOCKED(); TAILQ_INIT(&rttlist); mtx_enter(&rttimer_mtx); while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL) { LIST_REMOVE(r, rtt_link); TAILQ_REMOVE(&rtq->rtq_head, r, rtt_next); TAILQ_INSERT_TAIL(&rttlist, r, rtt_next); KASSERT(rtq->rtq_count > 0); rtq->rtq_count--; } mtx_leave(&rttimer_mtx); while ((r = TAILQ_FIRST(&rttlist)) != NULL) { TAILQ_REMOVE(&rttlist, r, rtt_next); RTTIMER_CALLOUT(r); pool_put(&rttimer_pool, r); } } unsigned long rt_timer_queue_count(struct rttimer_queue *rtq) { return (rtq->rtq_count); } static inline struct rttimer * rt_timer_unlink(struct rttimer *r) { MUTEX_ASSERT_LOCKED(&rttimer_mtx); LIST_REMOVE(r, rtt_link); r->rtt_rt = NULL; if (timeout_del(&r->rtt_timeout) == 0) { /* timeout fired, so rt_timer_timer will do the cleanup */ return NULL; } TAILQ_REMOVE(&r->rtt_queue->rtq_head, r, rtt_next); KASSERT(r->rtt_queue->rtq_count > 0); r->rtt_queue->rtq_count--; return r; } void rt_timer_remove_all(struct rtentry *rt) { struct rttimer *r; TAILQ_HEAD(, rttimer) rttlist; TAILQ_INIT(&rttlist); mtx_enter(&rttimer_mtx); while ((r = LIST_FIRST(&rt->rt_timer)) != NULL) { r = rt_timer_unlink(r); if (r != NULL) TAILQ_INSERT_TAIL(&rttlist, r, rtt_next); } mtx_leave(&rttimer_mtx); while ((r = TAILQ_FIRST(&rttlist)) != NULL) { TAILQ_REMOVE(&rttlist, r, rtt_next); pool_put(&rttimer_pool, r); } } time_t rt_timer_get_expire(const struct rtentry *rt) { const struct rttimer *r; time_t expire = 0; mtx_enter(&rttimer_mtx); LIST_FOREACH(r, &rt->rt_timer, rtt_link) { if (expire == 0 || expire > r->rtt_expire) expire = r->rtt_expire; } mtx_leave(&rttimer_mtx); return expire; } int rt_timer_add(struct rtentry *rt, struct rttimer_queue *queue, u_int rtableid) { struct rttimer *r, *rnew; rnew = pool_get(&rttimer_pool, PR_NOWAIT | PR_ZERO); if (rnew == NULL) return (ENOBUFS); rnew->rtt_rt = rt; rnew->rtt_queue = queue; rnew->rtt_tableid = rtableid; rnew->rtt_expire = getuptime() + queue->rtq_timeout; timeout_set_proc(&rnew->rtt_timeout, rt_timer_timer, rnew); mtx_enter(&rttimer_mtx); /* * If there's already a timer with this action, destroy it before * we add a new one. */ LIST_FOREACH(r, &rt->rt_timer, rtt_link) { if (r->rtt_queue == queue) { r = rt_timer_unlink(r); break; /* only one per list, so we can quit... */ } } LIST_INSERT_HEAD(&rt->rt_timer, rnew, rtt_link); TAILQ_INSERT_TAIL(&queue->rtq_head, rnew, rtt_next); timeout_add_sec(&rnew->rtt_timeout, queue->rtq_timeout); rnew->rtt_queue->rtq_count++; mtx_leave(&rttimer_mtx); if (r != NULL) pool_put(&rttimer_pool, r); return (0); } void rt_timer_timer(void *arg) { struct rttimer *r = arg; struct rttimer_queue *rtq = r->rtt_queue; NET_LOCK(); mtx_enter(&rttimer_mtx); if (r->rtt_rt != NULL) LIST_REMOVE(r, rtt_link); TAILQ_REMOVE(&rtq->rtq_head, r, rtt_next); KASSERT(rtq->rtq_count > 0); rtq->rtq_count--; mtx_leave(&rttimer_mtx); if (r->rtt_rt != NULL) RTTIMER_CALLOUT(r); NET_UNLOCK(); pool_put(&rttimer_pool, r); } #ifdef MPLS int rt_mpls_set(struct rtentry *rt, const struct sockaddr *src, uint8_t op) { struct sockaddr_mpls *psa_mpls = (struct sockaddr_mpls *)src; struct rt_mpls *rt_mpls; if (psa_mpls == NULL && op != MPLS_OP_POP) return (EOPNOTSUPP); if (psa_mpls != NULL && psa_mpls->smpls_len != sizeof(*psa_mpls)) return (EINVAL); if (psa_mpls != NULL && psa_mpls->smpls_family != AF_MPLS) return (EAFNOSUPPORT); rt->rt_llinfo = malloc(sizeof(struct rt_mpls), M_TEMP, M_NOWAIT|M_ZERO); if (rt->rt_llinfo == NULL) return (ENOMEM); rt_mpls = (struct rt_mpls *)rt->rt_llinfo; if (psa_mpls != NULL) rt_mpls->mpls_label = psa_mpls->smpls_label; rt_mpls->mpls_operation = op; /* XXX: set experimental bits */ rt->rt_flags |= RTF_MPLS; return (0); } void rt_mpls_clear(struct rtentry *rt) { if (rt->rt_llinfo != NULL && rt->rt_flags & RTF_MPLS) { free(rt->rt_llinfo, M_TEMP, sizeof(struct rt_mpls)); rt->rt_llinfo = NULL; } rt->rt_flags &= ~RTF_MPLS; } #endif u_int16_t rtlabel_name2id(const char *name) { struct rt_label *label, *p; u_int16_t new_id = 1, id = 0; if (!name[0]) return (0); mtx_enter(&rtlabel_mtx); TAILQ_FOREACH(label, &rt_labels, rtl_entry) if (strcmp(name, label->rtl_name) == 0) { label->rtl_ref++; id = label->rtl_id; goto out; } /* * to avoid fragmentation, we do a linear search from the beginning * and take the first free slot we find. if there is none or the list * is empty, append a new entry at the end. */ TAILQ_FOREACH(p, &rt_labels, rtl_entry) { if (p->rtl_id != new_id) break; new_id = p->rtl_id + 1; } if (new_id > LABELID_MAX) goto out; label = malloc(sizeof(*label), M_RTABLE, M_NOWAIT|M_ZERO); if (label == NULL) goto out; strlcpy(label->rtl_name, name, sizeof(label->rtl_name)); label->rtl_id = new_id; label->rtl_ref++; if (p != NULL) /* insert new entry before p */ TAILQ_INSERT_BEFORE(p, label, rtl_entry); else /* either list empty or no free slot in between */ TAILQ_INSERT_TAIL(&rt_labels, label, rtl_entry); id = label->rtl_id; out: mtx_leave(&rtlabel_mtx); return (id); } const char * rtlabel_id2name_locked(u_int16_t id) { struct rt_label *label; MUTEX_ASSERT_LOCKED(&rtlabel_mtx); TAILQ_FOREACH(label, &rt_labels, rtl_entry) if (label->rtl_id == id) return (label->rtl_name); return (NULL); } const char * rtlabel_id2name(u_int16_t id, char *rtlabelbuf, size_t sz) { const char *label; if (id == 0) return (NULL); mtx_enter(&rtlabel_mtx); if ((label = rtlabel_id2name_locked(id)) != NULL) strlcpy(rtlabelbuf, label, sz); mtx_leave(&rtlabel_mtx); if (label == NULL) return (NULL); return (rtlabelbuf); } struct sockaddr * rtlabel_id2sa(u_int16_t labelid, struct sockaddr_rtlabel *sa_rl) { const char *label; if (labelid == 0) return (NULL); mtx_enter(&rtlabel_mtx); if ((label = rtlabel_id2name_locked(labelid)) != NULL) { bzero(sa_rl, sizeof(*sa_rl)); sa_rl->sr_len = sizeof(*sa_rl); sa_rl->sr_family = AF_UNSPEC; strlcpy(sa_rl->sr_label, label, sizeof(sa_rl->sr_label)); } mtx_leave(&rtlabel_mtx); if (label == NULL) return (NULL); return ((struct sockaddr *)sa_rl); } void rtlabel_unref(u_int16_t id) { struct rt_label *p, *next; if (id == 0) return; mtx_enter(&rtlabel_mtx); TAILQ_FOREACH_SAFE(p, &rt_labels, rtl_entry, next) { if (id == p->rtl_id) { if (--p->rtl_ref == 0) { TAILQ_REMOVE(&rt_labels, p, rtl_entry); free(p, M_RTABLE, sizeof(*p)); } break; } } mtx_leave(&rtlabel_mtx); } int rt_if_track(struct ifnet *ifp) { unsigned int rtableid; struct rtentry *rt = NULL; int i, error = 0; for (rtableid = 0; rtableid < rtmap_limit; rtableid++) { /* skip rtables that are not in the rdomain of the ifp */ if (rtable_l2(rtableid) != ifp->if_rdomain) continue; for (i = 1; i <= AF_MAX; i++) { if (!rtable_mpath_capable(rtableid, i)) continue; do { error = rtable_walk(rtableid, i, &rt, rt_if_linkstate_change, ifp); if (rt != NULL && error == EEXIST) { error = rtdeletemsg(rt, ifp, rtableid); if (error == 0) error = EAGAIN; } rtfree(rt); rt = NULL; } while (error == EAGAIN); if (error == EAFNOSUPPORT) error = 0; if (error) break; } } return (error); } int rt_if_linkstate_change(struct rtentry *rt, void *arg, u_int id) { struct ifnet *ifp = arg; struct sockaddr_in6 sa_mask; int error; if (rt->rt_ifidx != ifp->if_index) return (0); /* Local routes are always usable. */ if (rt->rt_flags & RTF_LOCAL) { rt->rt_flags |= RTF_UP; return (0); } if (LINK_STATE_IS_UP(ifp->if_link_state) && ifp->if_flags & IFF_UP) { if (ISSET(rt->rt_flags, RTF_UP)) return (0); /* bring route up */ rt->rt_flags |= RTF_UP; error = rtable_mpath_reprio(id, rt_key(rt), rt_plen(rt), rt->rt_priority & RTP_MASK, rt); } else { /* * Remove redirected and cloned routes (mainly ARP) * from down interfaces so we have a chance to get * new routes from a better source. */ if (ISSET(rt->rt_flags, RTF_CLONED|RTF_DYNAMIC) && !ISSET(rt->rt_flags, RTF_CACHED|RTF_BFD)) { return (EEXIST); } if (!ISSET(rt->rt_flags, RTF_UP)) return (0); /* take route down */ rt->rt_flags &= ~RTF_UP; error = rtable_mpath_reprio(id, rt_key(rt), rt_plen(rt), rt->rt_priority | RTP_DOWN, rt); } if_group_routechange(rt_key(rt), rt_plen2mask(rt, &sa_mask)); membar_producer(); atomic_inc_long(&rtgeneration); return (error); } struct sockaddr * rt_plentosa(sa_family_t af, int plen, struct sockaddr_in6 *sa_mask) { struct sockaddr_in *sin = (struct sockaddr_in *)sa_mask; #ifdef INET6 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa_mask; #endif KASSERT(plen >= 0 || plen == -1); if (plen == -1) return (NULL); memset(sa_mask, 0, sizeof(*sa_mask)); switch (af) { case AF_INET: sin->sin_family = AF_INET; sin->sin_len = sizeof(struct sockaddr_in); in_prefixlen2mask(&sin->sin_addr, plen); break; #ifdef INET6 case AF_INET6: sin6->sin6_family = AF_INET6; sin6->sin6_len = sizeof(struct sockaddr_in6); in6_prefixlen2mask(&sin6->sin6_addr, plen); break; #endif /* INET6 */ default: return (NULL); } return ((struct sockaddr *)sa_mask); } struct sockaddr * rt_plen2mask(struct rtentry *rt, struct sockaddr_in6 *sa_mask) { return (rt_plentosa(rt_key(rt)->sa_family, rt_plen(rt), sa_mask)); } #ifdef DDB #include <machine/db_machdep.h> #include <ddb/db_output.h> void db_print_sa(struct sockaddr *); void db_print_ifa(struct ifaddr *); void db_print_sa(struct sockaddr *sa) { int len; u_char *p; if (sa == NULL) { db_printf("[NULL]"); return; } p = (u_char *)sa; len = sa->sa_len; db_printf("["); while (len > 0) { db_printf("%d", *p); p++; len--; if (len) db_printf(","); } db_printf("]\n"); } void db_print_ifa(struct ifaddr *ifa) { if (ifa == NULL) return; db_printf(" ifa_addr="); db_print_sa(ifa->ifa_addr); db_printf(" ifa_dsta="); db_print_sa(ifa->ifa_dstaddr); db_printf(" ifa_mask="); db_print_sa(ifa->ifa_netmask); db_printf(" flags=0x%x, refcnt=%u, metric=%d\n", ifa->ifa_flags, ifa->ifa_refcnt.r_refs, ifa->ifa_metric); } /* * Function to pass to rtable_walk(). * Return non-zero error to abort walk. */ int db_show_rtentry(struct rtentry *rt, void *w, unsigned int id) { db_printf("rtentry=%p", rt); db_printf(" flags=0x%x refcnt=%u use=%llu expire=%lld\n", rt->rt_flags, rt->rt_refcnt.r_refs, rt->rt_use, rt->rt_expire); db_printf(" key="); db_print_sa(rt_key(rt)); db_printf(" plen=%d", rt_plen(rt)); db_printf(" gw="); db_print_sa(rt->rt_gateway); db_printf(" ifidx=%u ", rt->rt_ifidx); db_printf(" ifa=%p\n", rt->rt_ifa); db_print_ifa(rt->rt_ifa); db_printf(" gwroute=%p llinfo=%p priority=%d\n", rt->rt_gwroute, rt->rt_llinfo, rt->rt_priority); return (0); } /* * Function to print all the route trees. */ int db_show_rtable(int af, unsigned int rtableid) { db_printf("Route tree for af %d, rtableid %u\n", af, rtableid); rtable_walk(rtableid, af, NULL, db_show_rtentry, NULL); return (0); } #endif /* DDB */
28 35 34 7 35 31 7 34 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 /* $OpenBSD: chacha_private.h,v 1.4 2020/07/22 13:54:30 tobhe Exp $ */ /* chacha-merged.c version 20080118 D. J. Bernstein Public domain. */ #include <sys/systm.h> typedef unsigned char u8; typedef unsigned int u32; typedef struct { u32 input[16]; /* could be compressed */ } chacha_ctx; #define U8C(v) (v##U) #define U32C(v) (v##U) #define U8V(v) ((u8)(v) & U8C(0xFF)) #define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF)) #define ROTL32(v, n) \ (U32V((v) << (n)) | ((v) >> (32 - (n)))) #define U8TO32_LITTLE(p) \ (((u32)((p)[0]) ) | \ ((u32)((p)[1]) << 8) | \ ((u32)((p)[2]) << 16) | \ ((u32)((p)[3]) << 24)) #define U32TO8_LITTLE(p, v) \ do { \ (p)[0] = U8V((v) ); \ (p)[1] = U8V((v) >> 8); \ (p)[2] = U8V((v) >> 16); \ (p)[3] = U8V((v) >> 24); \ } while (0) #define ROTATE(v,c) (ROTL32(v,c)) #define XOR(v,w) ((v) ^ (w)) #define PLUS(v,w) (U32V((v) + (w))) #define PLUSONE(v) (PLUS((v),1)) #define QUARTERROUND(a,b,c,d) \ a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \ c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \ a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \ c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); static const char sigma[16] = "expand 32-byte k"; static const char tau[16] = "expand 16-byte k"; static inline void hchacha20(u32 derived_key[8], const u8 nonce[16], const u8 key[32]) { int i; uint32_t x[] = { U8TO32_LITTLE(sigma + 0), U8TO32_LITTLE(sigma + 4), U8TO32_LITTLE(sigma + 8), U8TO32_LITTLE(sigma + 12), U8TO32_LITTLE(key + 0), U8TO32_LITTLE(key + 4), U8TO32_LITTLE(key + 8), U8TO32_LITTLE(key + 12), U8TO32_LITTLE(key + 16), U8TO32_LITTLE(key + 20), U8TO32_LITTLE(key + 24), U8TO32_LITTLE(key + 28), U8TO32_LITTLE(nonce + 0), U8TO32_LITTLE(nonce + 4), U8TO32_LITTLE(nonce + 8), U8TO32_LITTLE(nonce + 12) }; for (i = 20;i > 0;i -= 2) { QUARTERROUND( x[0], x[4], x[8],x[12]) QUARTERROUND( x[1], x[5], x[9],x[13]) QUARTERROUND( x[2], x[6],x[10],x[14]) QUARTERROUND( x[3], x[7],x[11],x[15]) QUARTERROUND( x[0], x[5],x[10],x[15]) QUARTERROUND( x[1], x[6],x[11],x[12]) QUARTERROUND( x[2], x[7], x[8],x[13]) QUARTERROUND( x[3], x[4], x[9],x[14]) } memcpy(derived_key + 0, x + 0, sizeof(u32) * 4); memcpy(derived_key + 4, x + 12, sizeof(u32) * 4); } static void chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits) { const char *constants; x->input[4] = U8TO32_LITTLE(k + 0); x->input[5] = U8TO32_LITTLE(k + 4); x->input[6] = U8TO32_LITTLE(k + 8); x->input[7] = U8TO32_LITTLE(k + 12); if (kbits == 256) { /* recommended */ k += 16; constants = sigma; } else { /* kbits == 128 */ constants = tau; } x->input[8] = U8TO32_LITTLE(k + 0); x->input[9] = U8TO32_LITTLE(k + 4); x->input[10] = U8TO32_LITTLE(k + 8); x->input[11] = U8TO32_LITTLE(k + 12); x->input[0] = U8TO32_LITTLE(constants + 0); x->input[1] = U8TO32_LITTLE(constants + 4); x->input[2] = U8TO32_LITTLE(constants + 8); x->input[3] = U8TO32_LITTLE(constants + 12); } static void chacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter) { x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0); x->input[13] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 4); x->input[14] = U8TO32_LITTLE(iv + 0); x->input[15] = U8TO32_LITTLE(iv + 4); } static void chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes) { u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; u8 *ctarget = NULL; u8 tmp[64]; u_int i; if (!bytes) return; j0 = x->input[0]; j1 = x->input[1]; j2 = x->input[2]; j3 = x->input[3]; j4 = x->input[4]; j5 = x->input[5]; j6 = x->input[6]; j7 = x->input[7]; j8 = x->input[8]; j9 = x->input[9]; j10 = x->input[10]; j11 = x->input[11]; j12 = x->input[12]; j13 = x->input[13]; j14 = x->input[14]; j15 = x->input[15]; for (;;) { if (bytes < 64) { for (i = 0;i < bytes;++i) tmp[i] = m[i]; m = tmp; ctarget = c; c = tmp; } x0 = j0; x1 = j1; x2 = j2; x3 = j3; x4 = j4; x5 = j5; x6 = j6; x7 = j7; x8 = j8; x9 = j9; x10 = j10; x11 = j11; x12 = j12; x13 = j13; x14 = j14; x15 = j15; for (i = 20;i > 0;i -= 2) { QUARTERROUND( x0, x4, x8,x12) QUARTERROUND( x1, x5, x9,x13) QUARTERROUND( x2, x6,x10,x14) QUARTERROUND( x3, x7,x11,x15) QUARTERROUND( x0, x5,x10,x15) QUARTERROUND( x1, x6,x11,x12) QUARTERROUND( x2, x7, x8,x13) QUARTERROUND( x3, x4, x9,x14) } x0 = PLUS(x0,j0); x1 = PLUS(x1,j1); x2 = PLUS(x2,j2); x3 = PLUS(x3,j3); x4 = PLUS(x4,j4); x5 = PLUS(x5,j5); x6 = PLUS(x6,j6); x7 = PLUS(x7,j7); x8 = PLUS(x8,j8); x9 = PLUS(x9,j9); x10 = PLUS(x10,j10); x11 = PLUS(x11,j11); x12 = PLUS(x12,j12); x13 = PLUS(x13,j13); x14 = PLUS(x14,j14); x15 = PLUS(x15,j15); #ifndef KEYSTREAM_ONLY x0 = XOR(x0,U8TO32_LITTLE(m + 0)); x1 = XOR(x1,U8TO32_LITTLE(m + 4)); x2 = XOR(x2,U8TO32_LITTLE(m + 8)); x3 = XOR(x3,U8TO32_LITTLE(m + 12)); x4 = XOR(x4,U8TO32_LITTLE(m + 16)); x5 = XOR(x5,U8TO32_LITTLE(m + 20)); x6 = XOR(x6,U8TO32_LITTLE(m + 24)); x7 = XOR(x7,U8TO32_LITTLE(m + 28)); x8 = XOR(x8,U8TO32_LITTLE(m + 32)); x9 = XOR(x9,U8TO32_LITTLE(m + 36)); x10 = XOR(x10,U8TO32_LITTLE(m + 40)); x11 = XOR(x11,U8TO32_LITTLE(m + 44)); x12 = XOR(x12,U8TO32_LITTLE(m + 48)); x13 = XOR(x13,U8TO32_LITTLE(m + 52)); x14 = XOR(x14,U8TO32_LITTLE(m + 56)); x15 = XOR(x15,U8TO32_LITTLE(m + 60)); #endif j12 = PLUSONE(j12); if (!j12) { j13 = PLUSONE(j13); /* stopping at 2^70 bytes per nonce is user's responsibility */ } U32TO8_LITTLE(c + 0,x0); U32TO8_LITTLE(c + 4,x1); U32TO8_LITTLE(c + 8,x2); U32TO8_LITTLE(c + 12,x3); U32TO8_LITTLE(c + 16,x4); U32TO8_LITTLE(c + 20,x5); U32TO8_LITTLE(c + 24,x6); U32TO8_LITTLE(c + 28,x7); U32TO8_LITTLE(c + 32,x8); U32TO8_LITTLE(c + 36,x9); U32TO8_LITTLE(c + 40,x10); U32TO8_LITTLE(c + 44,x11); U32TO8_LITTLE(c + 48,x12); U32TO8_LITTLE(c + 52,x13); U32TO8_LITTLE(c + 56,x14); U32TO8_LITTLE(c + 60,x15); if (bytes <= 64) { if (bytes < 64) { for (i = 0;i < bytes;++i) ctarget[i] = c[i]; } x->input[12] = j12; x->input[13] = j13; return; } bytes -= 64; c += 64; #ifndef KEYSTREAM_ONLY m += 64; #endif } }
39 39 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 /* $OpenBSD: strnlen.c,v 1.3 2019/01/25 00:19:26 millert Exp $ */ /* * Copyright (c) 2010 Todd C. Miller <millert@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/types.h> #include <lib/libkern/libkern.h> size_t strnlen(const char *str, size_t maxlen) { const char *cp; for (cp = str; maxlen != 0 && *cp != '\0'; cp++, maxlen--) ; return (size_t)(cp - str); }
11 4 1 9 1 197 198 600 601 1 24 551 1873 2046 2044 2047 505 1566 2043 225 113 29 1828 1447 198 198 198 520 1840 19 1459 1845 11 10 2 11 1 1847 1850 1852 1852 1331 1570 601 39 602 570 42 570 6 545 78 601 567 85 498 465 496 459 1567 1109 564 1568 535 39 497 86 65 3 26 3 49 17 1 65 65 1 2 2 49 4 24 520 8 1 9 1 1111 1121 543 1127 147 1 1434 1554 2 574 570 10 8 533 569 144 14 35 138 569 35 7 569 567 8 569 1886 68 1548 1119 540 537 1131 1796 2045 183 198 1950 68 1916 1913 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 /* $OpenBSD: uvm_fault.c,v 1.135 2023/09/05 05:08:26 guenther Exp $ */ /* $NetBSD: uvm_fault.c,v 1.51 2000/08/06 00:22:53 thorpej Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * from: Id: uvm_fault.c,v 1.1.2.23 1998/02/06 05:29:05 chs Exp */ /* * uvm_fault.c: fault handler */ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/percpu.h> #include <sys/proc.h> #include <sys/malloc.h> #include <sys/mman.h> #include <sys/tracepoint.h> #include <uvm/uvm.h> /* * * a word on page faults: * * types of page faults we handle: * * CASE 1: upper layer faults CASE 2: lower layer faults * * CASE 1A CASE 1B CASE 2A CASE 2B * read/write1 write>1 read/write +-cow_write/zero * | | | | * +--|--+ +--|--+ +-----+ + | + | +-----+ * amap | V | | ---------> new | | | | ^ | * +-----+ +-----+ +-----+ + | + | +--|--+ * | | | * +-----+ +-----+ +--|--+ | +--|--+ * uobj | d/c | | d/c | | V | +----+ | * +-----+ +-----+ +-----+ +-----+ * * d/c = don't care * * case [0]: layerless fault * no amap or uobj is present. this is an error. * * case [1]: upper layer fault [anon active] * 1A: [read] or [write with anon->an_ref == 1] * I/O takes place in upper level anon and uobj is not touched. * 1B: [write with anon->an_ref > 1] * new anon is alloc'd and data is copied off ["COW"] * * case [2]: lower layer fault [uobj] * 2A: [read on non-NULL uobj] or [write to non-copy_on_write area] * I/O takes place directly in object. * 2B: [write to copy_on_write] or [read on NULL uobj] * data is "promoted" from uobj to a new anon. * if uobj is null, then we zero fill. * * we follow the standard UVM locking protocol ordering: * * MAPS => AMAP => UOBJ => ANON => PAGE QUEUES (PQ) * we hold a PG_BUSY page if we unlock for I/O * * * the code is structured as follows: * * - init the "IN" params in the ufi structure * ReFault: (ERESTART returned to the loop in uvm_fault) * - do lookups [locks maps], check protection, handle needs_copy * - check for case 0 fault (error) * - establish "range" of fault * - if we have an amap lock it and extract the anons * - if sequential advice deactivate pages behind us * - at the same time check pmap for unmapped areas and anon for pages * that we could map in (and do map it if found) * - check object for resident pages that we could map in * - if (case 2) goto Case2 * - >>> handle case 1 * - ensure source anon is resident in RAM * - if case 1B alloc new anon and copy from source * - map the correct page in * Case2: * - >>> handle case 2 * - ensure source page is resident (if uobj) * - if case 2B alloc new anon and copy from source (could be zero * fill if uobj == NULL) * - map the correct page in * - done! * * note on paging: * if we have to do I/O we place a PG_BUSY page in the correct object, * unlock everything, and do the I/O. when I/O is done we must reverify * the state of the world before assuming that our data structures are * valid. [because mappings could change while the map is unlocked] * * alternative 1: unbusy the page in question and restart the page fault * from the top (ReFault). this is easy but does not take advantage * of the information that we already have from our previous lookup, * although it is possible that the "hints" in the vm_map will help here. * * alternative 2: the system already keeps track of a "version" number of * a map. [i.e. every time you write-lock a map (e.g. to change a * mapping) you bump the version number up by one...] so, we can save * the version number of the map before we release the lock and start I/O. * then when I/O is done we can relock and check the version numbers * to see if anything changed. this might save us some over 1 because * we don't have to unbusy the page and may be less compares(?). * * alternative 3: put in backpointers or a way to "hold" part of a map * in place while I/O is in progress. this could be complex to * implement (especially with structures like amap that can be referenced * by multiple map entries, and figuring out what should wait could be * complex as well...). * * we use alternative 2. given that we are multi-threaded now we may want * to reconsider the choice. */ /* * local data structures */ struct uvm_advice { int nback; int nforw; }; /* * page range array: set up in uvmfault_init(). */ static struct uvm_advice uvmadvice[MADV_MASK + 1]; #define UVM_MAXRANGE 16 /* must be max() of nback+nforw+1 */ /* * private prototypes */ static void uvmfault_amapcopy(struct uvm_faultinfo *); static inline void uvmfault_anonflush(struct vm_anon **, int); void uvmfault_unlockmaps(struct uvm_faultinfo *, boolean_t); void uvmfault_update_stats(struct uvm_faultinfo *); /* * inline functions */ /* * uvmfault_anonflush: try and deactivate pages in specified anons * * => does not have to deactivate page if it is busy */ static inline void uvmfault_anonflush(struct vm_anon **anons, int n) { int lcv; struct vm_page *pg; for (lcv = 0; lcv < n; lcv++) { if (anons[lcv] == NULL) continue; KASSERT(rw_lock_held(anons[lcv]->an_lock)); pg = anons[lcv]->an_page; if (pg && (pg->pg_flags & PG_BUSY) == 0) { uvm_lock_pageq(); if (pg->wire_count == 0) { pmap_page_protect(pg, PROT_NONE); uvm_pagedeactivate(pg); } uvm_unlock_pageq(); } } } /* * normal functions */ /* * uvmfault_init: compute proper values for the uvmadvice[] array. */ void uvmfault_init(void) { int npages; npages = atop(16384); if (npages > 0) { KASSERT(npages <= UVM_MAXRANGE / 2); uvmadvice[MADV_NORMAL].nforw = npages; uvmadvice[MADV_NORMAL].nback = npages - 1; } npages = atop(32768); if (npages > 0) { KASSERT(npages <= UVM_MAXRANGE / 2); uvmadvice[MADV_SEQUENTIAL].nforw = npages - 1; uvmadvice[MADV_SEQUENTIAL].nback = npages; } } /* * uvmfault_amapcopy: clear "needs_copy" in a map. * * => called with VM data structures unlocked (usually, see below) * => we get a write lock on the maps and clear needs_copy for a VA * => if we are out of RAM we sleep (waiting for more) */ static void uvmfault_amapcopy(struct uvm_faultinfo *ufi) { for (;;) { /* * no mapping? give up. */ if (uvmfault_lookup(ufi, TRUE) == FALSE) return; /* * copy if needed. */ if (UVM_ET_ISNEEDSCOPY(ufi->entry)) amap_copy(ufi->map, ufi->entry, M_NOWAIT, UVM_ET_ISSTACK(ufi->entry) ? FALSE : TRUE, ufi->orig_rvaddr, ufi->orig_rvaddr + 1); /* * didn't work? must be out of RAM. unlock and sleep. */ if (UVM_ET_ISNEEDSCOPY(ufi->entry)) { uvmfault_unlockmaps(ufi, TRUE); uvm_wait("fltamapcopy"); continue; } /* * got it! unlock and return. */ uvmfault_unlockmaps(ufi, TRUE); return; } /*NOTREACHED*/ } /* * uvmfault_anonget: get data in an anon into a non-busy, non-released * page in that anon. * * => Map, amap and thus anon should be locked by caller. * => If we fail, we unlock everything and error is returned. * => If we are successful, return with everything still locked. * => We do not move the page on the queues [gets moved later]. If we * allocate a new page [we_own], it gets put on the queues. Either way, * the result is that the page is on the queues at return time */ int uvmfault_anonget(struct uvm_faultinfo *ufi, struct vm_amap *amap, struct vm_anon *anon) { struct vm_page *pg; int error; KASSERT(rw_lock_held(anon->an_lock)); KASSERT(anon->an_lock == amap->am_lock); /* Increment the counters.*/ counters_inc(uvmexp_counters, flt_anget); if (anon->an_page) { curproc->p_ru.ru_minflt++; } else { curproc->p_ru.ru_majflt++; } error = 0; /* * Loop until we get the anon data, or fail. */ for (;;) { boolean_t we_own, locked; /* * Note: 'we_own' will become true if we set PG_BUSY on a page. */ we_own = FALSE; pg = anon->an_page; /* * Is page resident? Make sure it is not busy/released. */ if (pg) { KASSERT(pg->pg_flags & PQ_ANON); KASSERT(pg->uanon == anon); /* * if the page is busy, we drop all the locks and * try again. */ if ((pg->pg_flags & (PG_BUSY|PG_RELEASED)) == 0) return (VM_PAGER_OK); atomic_setbits_int(&pg->pg_flags, PG_WANTED); counters_inc(uvmexp_counters, flt_pgwait); /* * The last unlock must be an atomic unlock and wait * on the owner of page. */ if (pg->uobject) { /* Owner of page is UVM object. */ uvmfault_unlockall(ufi, amap, NULL); rwsleep_nsec(pg, pg->uobject->vmobjlock, PVM | PNORELOCK, "anonget1", INFSLP); } else { /* Owner of page is anon. */ uvmfault_unlockall(ufi, NULL, NULL); rwsleep_nsec(pg, anon->an_lock, PVM | PNORELOCK, "anonget2", INFSLP); } } else { /* * No page, therefore allocate one. */ pg = uvm_pagealloc(NULL, 0, anon, 0); if (pg == NULL) { /* Out of memory. Wait a little. */ uvmfault_unlockall(ufi, amap, NULL); counters_inc(uvmexp_counters, flt_noram); uvm_wait("flt_noram1"); } else { /* PG_BUSY bit is set. */ we_own = TRUE; uvmfault_unlockall(ufi, amap, NULL); /* * Pass a PG_BUSY+PG_FAKE+PG_CLEAN page into * the uvm_swap_get() function with all data * structures unlocked. Note that it is OK * to read an_swslot here, because we hold * PG_BUSY on the page. */ counters_inc(uvmexp_counters, pageins); error = uvm_swap_get(pg, anon->an_swslot, PGO_SYNCIO); /* * We clean up after the I/O below in the * 'we_own' case. */ } } /* * Re-lock the map and anon. */ locked = uvmfault_relock(ufi); if (locked || we_own) { rw_enter(anon->an_lock, RW_WRITE); } /* * If we own the page (i.e. we set PG_BUSY), then we need * to clean up after the I/O. There are three cases to * consider: * * 1) Page was released during I/O: free anon and ReFault. * 2) I/O not OK. Free the page and cause the fault to fail. * 3) I/O OK! Activate the page and sync with the non-we_own * case (i.e. drop anon lock if not locked). */ if (we_own) { if (pg->pg_flags & PG_WANTED) { wakeup(pg); } /* * if we were RELEASED during I/O, then our anon is * no longer part of an amap. we need to free the * anon and try again. */ if (pg->pg_flags & PG_RELEASED) { KASSERT(anon->an_ref == 0); /* * Released while we had unlocked amap. */ if (locked) uvmfault_unlockall(ufi, NULL, NULL); uvm_anon_release(anon); /* frees page for us */ counters_inc(uvmexp_counters, flt_pgrele); return (VM_PAGER_REFAULT); /* refault! */ } if (error != VM_PAGER_OK) { KASSERT(error != VM_PAGER_PEND); /* remove page from anon */ anon->an_page = NULL; /* * Remove the swap slot from the anon and * mark the anon as having no real slot. * Do not free the swap slot, thus preventing * it from being used again. */ uvm_swap_markbad(anon->an_swslot, 1); anon->an_swslot = SWSLOT_BAD; /* * Note: page was never !PG_BUSY, so it * cannot be mapped and thus no need to * pmap_page_protect() it. */ uvm_lock_pageq(); uvm_pagefree(pg); uvm_unlock_pageq(); if (locked) { uvmfault_unlockall(ufi, NULL, NULL); } rw_exit(anon->an_lock); return (VM_PAGER_ERROR); } /* * We have successfully read the page, activate it. */ pmap_clear_modify(pg); uvm_lock_pageq(); uvm_pageactivate(pg); uvm_unlock_pageq(); atomic_clearbits_int(&pg->pg_flags, PG_WANTED|PG_BUSY|PG_FAKE); UVM_PAGE_OWN(pg, NULL); } /* * We were not able to re-lock the map - restart the fault. */ if (!locked) { if (we_own) { rw_exit(anon->an_lock); } return (VM_PAGER_REFAULT); } /* * Verify that no one has touched the amap and moved * the anon on us. */ if (ufi != NULL && amap_lookup(&ufi->entry->aref, ufi->orig_rvaddr - ufi->entry->start) != anon) { uvmfault_unlockall(ufi, amap, NULL); return (VM_PAGER_REFAULT); } /* * Retry.. */ counters_inc(uvmexp_counters, flt_anretry); continue; } /*NOTREACHED*/ } /* * Update statistics after fault resolution. * - maxrss */ void uvmfault_update_stats(struct uvm_faultinfo *ufi) { struct vm_map *map; struct proc *p; vsize_t res; map = ufi->orig_map; /* * If this is a nested pmap (eg, a virtual machine pmap managed * by vmm(4) on amd64/i386), don't do any updating, just return. * * pmap_nested() on other archs is #defined to 0, so this is a * no-op. */ if (pmap_nested(map->pmap)) return; /* Update the maxrss for the process. */ if (map->flags & VM_MAP_ISVMSPACE) { p = curproc; KASSERT(p != NULL && &p->p_vmspace->vm_map == map); res = pmap_resident_count(map->pmap); /* Convert res from pages to kilobytes. */ res <<= (PAGE_SHIFT - 10); if (p->p_ru.ru_maxrss < res) p->p_ru.ru_maxrss = res; } } /* * F A U L T - m a i n e n t r y p o i n t */ /* * uvm_fault: page fault handler * * => called from MD code to resolve a page fault * => VM data structures usually should be unlocked. however, it is * possible to call here with the main map locked if the caller * gets a write lock, sets it recursive, and then calls us (c.f. * uvm_map_pageable). this should be avoided because it keeps * the map locked off during I/O. * => MUST NEVER BE CALLED IN INTERRUPT CONTEXT */ #define MASK(entry) (UVM_ET_ISCOPYONWRITE(entry) ? \ ~PROT_WRITE : PROT_MASK) struct uvm_faultctx { /* * the following members are set up by uvm_fault_check() and * read-only after that. */ vm_prot_t enter_prot; vm_prot_t access_type; vaddr_t startva; int npages; int centeridx; boolean_t narrow; boolean_t wired; paddr_t pa_flags; }; int uvm_fault_check( struct uvm_faultinfo *, struct uvm_faultctx *, struct vm_anon ***); int uvm_fault_upper( struct uvm_faultinfo *, struct uvm_faultctx *, struct vm_anon **, vm_fault_t); boolean_t uvm_fault_upper_lookup( struct uvm_faultinfo *, const struct uvm_faultctx *, struct vm_anon **, struct vm_page **); int uvm_fault_lower( struct uvm_faultinfo *, struct uvm_faultctx *, struct vm_page **, vm_fault_t); int uvm_fault(vm_map_t orig_map, vaddr_t vaddr, vm_fault_t fault_type, vm_prot_t access_type) { struct uvm_faultinfo ufi; struct uvm_faultctx flt; boolean_t shadowed; struct vm_anon *anons_store[UVM_MAXRANGE], **anons; struct vm_page *pages[UVM_MAXRANGE]; int error; counters_inc(uvmexp_counters, faults); TRACEPOINT(uvm, fault, vaddr, fault_type, access_type, NULL); /* * init the IN parameters in the ufi */ ufi.orig_map = orig_map; ufi.orig_rvaddr = trunc_page(vaddr); ufi.orig_size = PAGE_SIZE; /* can't get any smaller than this */ if (fault_type == VM_FAULT_WIRE) flt.narrow = TRUE; /* don't look for neighborhood * pages on wire */ else flt.narrow = FALSE; /* normal fault */ flt.access_type = access_type; error = ERESTART; while (error == ERESTART) { /* ReFault: */ anons = anons_store; error = uvm_fault_check(&ufi, &flt, &anons); if (error != 0) continue; /* True if there is an anon at the faulting address */ shadowed = uvm_fault_upper_lookup(&ufi, &flt, anons, pages); if (shadowed == TRUE) { /* case 1: fault on an anon in our amap */ error = uvm_fault_upper(&ufi, &flt, anons, fault_type); } else { struct uvm_object *uobj = ufi.entry->object.uvm_obj; /* * if the desired page is not shadowed by the amap and * we have a backing object, then we check to see if * the backing object would prefer to handle the fault * itself (rather than letting us do it with the usual * pgo_get hook). the backing object signals this by * providing a pgo_fault routine. */ if (uobj != NULL && uobj->pgops->pgo_fault != NULL) { KERNEL_LOCK(); rw_enter(uobj->vmobjlock, RW_WRITE); error = uobj->pgops->pgo_fault(&ufi, flt.startva, pages, flt.npages, flt.centeridx, fault_type, flt.access_type, PGO_LOCKED); KERNEL_UNLOCK(); if (error == VM_PAGER_OK) error = 0; else if (error == VM_PAGER_REFAULT) error = ERESTART; else error = EACCES; } else { /* case 2: fault on backing obj or zero fill */ error = uvm_fault_lower(&ufi, &flt, pages, fault_type); } } } return error; } /* * uvm_fault_check: check prot, handle needs-copy, etc. * * 1. lookup entry. * 2. check protection. * 3. adjust fault condition (mainly for simulated fault). * 4. handle needs-copy (lazy amap copy). * 5. establish range of interest for neighbor fault (aka pre-fault). * 6. look up anons (if amap exists). * 7. flush pages (if MADV_SEQUENTIAL) * * => called with nothing locked. * => if we fail (result != 0) we unlock everything. * => initialize/adjust many members of flt. */ int uvm_fault_check(struct uvm_faultinfo *ufi, struct uvm_faultctx *flt, struct vm_anon ***ranons) { struct vm_amap *amap; struct uvm_object *uobj; int nback, nforw; /* * lookup and lock the maps */ if (uvmfault_lookup(ufi, FALSE) == FALSE) { return EFAULT; } /* locked: maps(read) */ #ifdef DIAGNOSTIC if ((ufi->map->flags & VM_MAP_PAGEABLE) == 0) panic("uvm_fault: fault on non-pageable map (%p, 0x%lx)", ufi->map, ufi->orig_rvaddr); #endif /* * check protection */ if ((ufi->entry->protection & flt->access_type) != flt->access_type) { uvmfault_unlockmaps(ufi, FALSE); return EACCES; } /* * "enter_prot" is the protection we want to enter the page in at. * for certain pages (e.g. copy-on-write pages) this protection can * be more strict than ufi->entry->protection. "wired" means either * the entry is wired or we are fault-wiring the pg. */ flt->enter_prot = ufi->entry->protection; flt->pa_flags = UVM_ET_ISWC(ufi->entry) ? PMAP_WC : 0; flt->wired = VM_MAPENT_ISWIRED(ufi->entry) || (flt->narrow == TRUE); if (flt->wired) flt->access_type = flt->enter_prot; /* full access for wired */ /* handle "needs_copy" case. */ if (UVM_ET_ISNEEDSCOPY(ufi->entry)) { if ((flt->access_type & PROT_WRITE) || (ufi->entry->object.uvm_obj == NULL)) { /* need to clear */ uvmfault_unlockmaps(ufi, FALSE); uvmfault_amapcopy(ufi); counters_inc(uvmexp_counters, flt_amcopy); return ERESTART; } else { /* * ensure that we pmap_enter page R/O since * needs_copy is still true */ flt->enter_prot &= ~PROT_WRITE; } } /* * identify the players */ amap = ufi->entry->aref.ar_amap; /* upper layer */ uobj = ufi->entry->object.uvm_obj; /* lower layer */ /* * check for a case 0 fault. if nothing backing the entry then * error now. */ if (amap == NULL && uobj == NULL) { uvmfault_unlockmaps(ufi, FALSE); return EFAULT; } /* * for a case 2B fault waste no time on adjacent pages because * they are likely already entered. */ if (uobj != NULL && amap != NULL && (flt->access_type & PROT_WRITE) != 0) { /* wide fault (!narrow) */ flt->narrow = TRUE; } /* * establish range of interest based on advice from mapper * and then clip to fit map entry. note that we only want * to do this the first time through the fault. if we * ReFault we will disable this by setting "narrow" to true. */ if (flt->narrow == FALSE) { /* wide fault (!narrow) */ nback = min(uvmadvice[ufi->entry->advice].nback, (ufi->orig_rvaddr - ufi->entry->start) >> PAGE_SHIFT); flt->startva = ufi->orig_rvaddr - ((vsize_t)nback << PAGE_SHIFT); nforw = min(uvmadvice[ufi->entry->advice].nforw, ((ufi->entry->end - ufi->orig_rvaddr) >> PAGE_SHIFT) - 1); /* * note: "-1" because we don't want to count the * faulting page as forw */ flt->npages = nback + nforw + 1; flt->centeridx = nback; flt->narrow = TRUE; /* ensure only once per-fault */ } else { /* narrow fault! */ nback = nforw = 0; flt->startva = ufi->orig_rvaddr; flt->npages = 1; flt->centeridx = 0; } /* * if we've got an amap then lock it and extract current anons. */ if (amap) { amap_lock(amap); amap_lookups(&ufi->entry->aref, flt->startva - ufi->entry->start, *ranons, flt->npages); } else { *ranons = NULL; /* to be safe */ } /* * for MADV_SEQUENTIAL mappings we want to deactivate the back pages * now and then forget about them (for the rest of the fault). */ if (ufi->entry->advice == MADV_SEQUENTIAL && nback != 0) { /* flush back-page anons? */ if (amap) uvmfault_anonflush(*ranons, nback); /* * flush object? */ if (uobj) { voff_t uoff; uoff = (flt->startva - ufi->entry->start) + ufi->entry->offset; rw_enter(uobj->vmobjlock, RW_WRITE); (void) uobj->pgops->pgo_flush(uobj, uoff, uoff + ((vsize_t)nback << PAGE_SHIFT), PGO_DEACTIVATE); rw_exit(uobj->vmobjlock); } /* now forget about the backpages */ if (amap) *ranons += nback; flt->startva += ((vsize_t)nback << PAGE_SHIFT); flt->npages -= nback; flt->centeridx = 0; } return 0; } /* * uvm_fault_upper_lookup: look up existing h/w mapping and amap. * * iterate range of interest: * 1. check if h/w mapping exists. if yes, we don't care * 2. check if anon exists. if not, page is lower. * 3. if anon exists, enter h/w mapping for neighbors. * * => called with amap locked (if exists). */ boolean_t uvm_fault_upper_lookup(struct uvm_faultinfo *ufi, const struct uvm_faultctx *flt, struct vm_anon **anons, struct vm_page **pages) { struct vm_amap *amap = ufi->entry->aref.ar_amap; struct vm_anon *anon; boolean_t shadowed; vaddr_t currva; paddr_t pa; int lcv; /* locked: maps(read), amap(if there) */ KASSERT(amap == NULL || rw_write_held(amap->am_lock)); /* * map in the backpages and frontpages we found in the amap in hopes * of preventing future faults. we also init the pages[] array as * we go. */ currva = flt->startva; shadowed = FALSE; for (lcv = 0; lcv < flt->npages; lcv++, currva += PAGE_SIZE) { /* * dont play with VAs that are already mapped * except for center) */ if (lcv != flt->centeridx && pmap_extract(ufi->orig_map->pmap, currva, &pa)) { pages[lcv] = PGO_DONTCARE; continue; } /* * unmapped or center page. check if any anon at this level. */ if (amap == NULL || anons[lcv] == NULL) { pages[lcv] = NULL; continue; } /* * check for present page and map if possible. */ pages[lcv] = PGO_DONTCARE; if (lcv == flt->centeridx) { /* save center for later! */ shadowed = TRUE; continue; } anon = anons[lcv]; KASSERT(anon->an_lock == amap->am_lock); if (anon->an_page && (anon->an_page->pg_flags & (PG_RELEASED|PG_BUSY)) == 0) { uvm_lock_pageq(); uvm_pageactivate(anon->an_page); /* reactivate */ uvm_unlock_pageq(); counters_inc(uvmexp_counters, flt_namap); /* * Since this isn't the page that's actually faulting, * ignore pmap_enter() failures; it's not critical * that we enter these right now. */ (void) pmap_enter(ufi->orig_map->pmap, currva, VM_PAGE_TO_PHYS(anon->an_page) | flt->pa_flags, (anon->an_ref > 1) ? (flt->enter_prot & ~PROT_WRITE) : flt->enter_prot, PMAP_CANFAIL | (VM_MAPENT_ISWIRED(ufi->entry) ? PMAP_WIRED : 0)); } } if (flt->npages > 1) pmap_update(ufi->orig_map->pmap); return shadowed; } /* * uvm_fault_upper: handle upper fault. * * 1. acquire anon lock. * 2. get anon. let uvmfault_anonget do the dirty work. * 3. if COW, promote data to new anon * 4. enter h/w mapping */ int uvm_fault_upper(struct uvm_faultinfo *ufi, struct uvm_faultctx *flt, struct vm_anon **anons, vm_fault_t fault_type) { struct vm_amap *amap = ufi->entry->aref.ar_amap; struct vm_anon *oanon, *anon = anons[flt->centeridx]; struct vm_page *pg = NULL; int error, ret; /* locked: maps(read), amap, anon */ KASSERT(rw_write_held(amap->am_lock)); KASSERT(anon->an_lock == amap->am_lock); /* * no matter if we have case 1A or case 1B we are going to need to * have the anon's memory resident. ensure that now. */ /* * let uvmfault_anonget do the dirty work. * if it fails (!OK) it will unlock everything for us. * if it succeeds, locks are still valid and locked. * also, if it is OK, then the anon's page is on the queues. * if the page is on loan from a uvm_object, then anonget will * lock that object for us if it does not fail. */ error = uvmfault_anonget(ufi, amap, anon); switch (error) { case VM_PAGER_OK: break; case VM_PAGER_REFAULT: return ERESTART; case VM_PAGER_ERROR: /* * An error occurred while trying to bring in the * page -- this is the only error we return right * now. */ return EACCES; /* XXX */ default: #ifdef DIAGNOSTIC panic("uvm_fault: uvmfault_anonget -> %d", error); #else return EACCES; #endif } KASSERT(rw_write_held(amap->am_lock)); KASSERT(anon->an_lock == amap->am_lock); /* * if we are case 1B then we will need to allocate a new blank * anon to transfer the data into. note that we have a lock * on anon, so no one can busy or release the page until we are done. * also note that the ref count can't drop to zero here because * it is > 1 and we are only dropping one ref. * * in the (hopefully very rare) case that we are out of RAM we * will unlock, wait for more RAM, and refault. * * if we are out of anon VM we wait for RAM to become available. */ if ((flt->access_type & PROT_WRITE) != 0 && anon->an_ref > 1) { counters_inc(uvmexp_counters, flt_acow); oanon = anon; /* oanon = old */ anon = uvm_analloc(); if (anon) { anon->an_lock = amap->am_lock; pg = uvm_pagealloc(NULL, 0, anon, 0); } /* check for out of RAM */ if (anon == NULL || pg == NULL) { uvmfault_unlockall(ufi, amap, NULL); if (anon == NULL) counters_inc(uvmexp_counters, flt_noanon); else { anon->an_lock = NULL; anon->an_ref--; uvm_anfree(anon); counters_inc(uvmexp_counters, flt_noram); } if (uvm_swapisfull()) return ENOMEM; /* out of RAM, wait for more */ if (anon == NULL) uvm_anwait(); else uvm_wait("flt_noram3"); return ERESTART; } /* got all resources, replace anon with nanon */ uvm_pagecopy(oanon->an_page, pg); /* pg now !PG_CLEAN */ /* un-busy! new page */ atomic_clearbits_int(&pg->pg_flags, PG_BUSY|PG_FAKE); UVM_PAGE_OWN(pg, NULL); ret = amap_add(&ufi->entry->aref, ufi->orig_rvaddr - ufi->entry->start, anon, 1); KASSERT(ret == 0); /* deref: can not drop to zero here by defn! */ oanon->an_ref--; #if defined(MULTIPROCESSOR) && !defined(__HAVE_PMAP_MPSAFE_ENTER_COW) /* * If there are multiple threads, either uvm or the * pmap has to make sure no threads see the old RO * mapping once any have seen the new RW mapping. * uvm does it by inserting the new mapping RO and * letting it fault again. * This is only a problem on MP systems. */ if (P_HASSIBLING(curproc)) { flt->enter_prot &= ~PROT_WRITE; flt->access_type &= ~PROT_WRITE; } #endif /* * note: anon is _not_ locked, but we have the sole references * to in from amap. * thus, no one can get at it until we are done with it. */ } else { counters_inc(uvmexp_counters, flt_anon); oanon = anon; pg = anon->an_page; if (anon->an_ref > 1) /* disallow writes to ref > 1 anons */ flt->enter_prot = flt->enter_prot & ~PROT_WRITE; } /* * now map the page in . */ if (pmap_enter(ufi->orig_map->pmap, ufi->orig_rvaddr, VM_PAGE_TO_PHYS(pg) | flt->pa_flags, flt->enter_prot, flt->access_type | PMAP_CANFAIL | (flt->wired ? PMAP_WIRED : 0)) != 0) { /* * No need to undo what we did; we can simply think of * this as the pmap throwing away the mapping information. * * We do, however, have to go through the ReFault path, * as the map may change while we're asleep. */ uvmfault_unlockall(ufi, amap, NULL); if (uvm_swapisfull()) { /* XXX instrumentation */ return ENOMEM; } /* XXX instrumentation */ uvm_wait("flt_pmfail1"); return ERESTART; } /* * ... update the page queues. */ uvm_lock_pageq(); if (fault_type == VM_FAULT_WIRE) { uvm_pagewire(pg); /* * since the now-wired page cannot be paged out, * release its swap resources for others to use. * since an anon with no swap cannot be PG_CLEAN, * clear its clean flag now. */ atomic_clearbits_int(&pg->pg_flags, PG_CLEAN); uvm_anon_dropswap(anon); } else { /* activate it */ uvm_pageactivate(pg); } uvm_unlock_pageq(); /* * done case 1! finish up by unlocking everything and returning success */ uvmfault_unlockall(ufi, amap, NULL); pmap_update(ufi->orig_map->pmap); return 0; } /* * uvm_fault_lower_lookup: look up on-memory uobj pages. * * 1. get on-memory pages. * 2. if failed, give up (get only center page later). * 3. if succeeded, enter h/w mapping of neighbor pages. */ struct vm_page * uvm_fault_lower_lookup( struct uvm_faultinfo *ufi, const struct uvm_faultctx *flt, struct vm_page **pages) { struct uvm_object *uobj = ufi->entry->object.uvm_obj; struct vm_page *uobjpage = NULL; int lcv, gotpages; vaddr_t currva; rw_enter(uobj->vmobjlock, RW_WRITE); counters_inc(uvmexp_counters, flt_lget); gotpages = flt->npages; (void) uobj->pgops->pgo_get(uobj, ufi->entry->offset + (flt->startva - ufi->entry->start), pages, &gotpages, flt->centeridx, flt->access_type & MASK(ufi->entry), ufi->entry->advice, PGO_LOCKED); /* * check for pages to map, if we got any */ if (gotpages == 0) { return NULL; } currva = flt->startva; for (lcv = 0; lcv < flt->npages; lcv++, currva += PAGE_SIZE) { if (pages[lcv] == NULL || pages[lcv] == PGO_DONTCARE) continue; KASSERT((pages[lcv]->pg_flags & PG_RELEASED) == 0); /* * if center page is resident and not * PG_BUSY, then pgo_get made it PG_BUSY * for us and gave us a handle to it. * remember this page as "uobjpage." * (for later use). */ if (lcv == flt->centeridx) { uobjpage = pages[lcv]; continue; } /* * note: calling pgo_get with locked data * structures returns us pages which are * neither busy nor released, so we don't * need to check for this. we can just * directly enter the page (after moving it * to the head of the active queue [useful?]). */ uvm_lock_pageq(); uvm_pageactivate(pages[lcv]); /* reactivate */ uvm_unlock_pageq(); counters_inc(uvmexp_counters, flt_nomap); /* * Since this page isn't the page that's * actually faulting, ignore pmap_enter() * failures; it's not critical that we * enter these right now. */ (void) pmap_enter(ufi->orig_map->pmap, currva, VM_PAGE_TO_PHYS(pages[lcv]) | flt->pa_flags, flt->enter_prot & MASK(ufi->entry), PMAP_CANFAIL | (flt->wired ? PMAP_WIRED : 0)); /* * NOTE: page can't be PG_WANTED because * we've held the lock the whole time * we've had the handle. */ atomic_clearbits_int(&pages[lcv]->pg_flags, PG_BUSY); UVM_PAGE_OWN(pages[lcv], NULL); } pmap_update(ufi->orig_map->pmap); return uobjpage; } /* * uvm_fault_lower: handle lower fault. * */ int uvm_fault_lower(struct uvm_faultinfo *ufi, struct uvm_faultctx *flt, struct vm_page **pages, vm_fault_t fault_type) { struct vm_amap *amap = ufi->entry->aref.ar_amap; struct uvm_object *uobj = ufi->entry->object.uvm_obj; boolean_t promote, locked; int result; struct vm_page *uobjpage, *pg = NULL; struct vm_anon *anon = NULL; voff_t uoff; /* * now, if the desired page is not shadowed by the amap and we have * a backing object that does not have a special fault routine, then * we ask (with pgo_get) the object for resident pages that we care * about and attempt to map them in. we do not let pgo_get block * (PGO_LOCKED). */ if (uobj == NULL) { /* zero fill; don't care neighbor pages */ uobjpage = NULL; } else { uobjpage = uvm_fault_lower_lookup(ufi, flt, pages); } /* * note that at this point we are done with any front or back pages. * we are now going to focus on the center page (i.e. the one we've * faulted on). if we have faulted on the bottom (uobj) * layer [i.e. case 2] and the page was both present and available, * then we've got a pointer to it as "uobjpage" and we've already * made it BUSY. */ /* * locked: */ KASSERT(amap == NULL || rw_write_held(amap->am_lock)); KASSERT(uobj == NULL || rw_write_held(uobj->vmobjlock)); /* * note that uobjpage can not be PGO_DONTCARE at this point. we now * set uobjpage to PGO_DONTCARE if we are doing a zero fill. if we * have a backing object, check and see if we are going to promote * the data up to an anon during the fault. */ if (uobj == NULL) { uobjpage = PGO_DONTCARE; promote = TRUE; /* always need anon here */ } else { KASSERT(uobjpage != PGO_DONTCARE); promote = (flt->access_type & PROT_WRITE) && UVM_ET_ISCOPYONWRITE(ufi->entry); } /* * if uobjpage is not null then we do not need to do I/O to get the * uobjpage. * * if uobjpage is null, then we need to ask the pager to * get the data for us. once we have the data, we need to reverify * the state the world. we are currently not holding any resources. */ if (uobjpage) { /* update rusage counters */ curproc->p_ru.ru_minflt++; } else { int gotpages; /* update rusage counters */ curproc->p_ru.ru_majflt++; uvmfault_unlockall(ufi, amap, NULL); counters_inc(uvmexp_counters, flt_get); gotpages = 1; uoff = (ufi->orig_rvaddr - ufi->entry->start) + ufi->entry->offset; result = uobj->pgops->pgo_get(uobj, uoff, &uobjpage, &gotpages, 0, flt->access_type & MASK(ufi->entry), ufi->entry->advice, PGO_SYNCIO); /* * recover from I/O */ if (result != VM_PAGER_OK) { KASSERT(result != VM_PAGER_PEND); if (result == VM_PAGER_AGAIN) { tsleep_nsec(&nowake, PVM, "fltagain2", MSEC_TO_NSEC(5)); return ERESTART; } if (!UVM_ET_ISNOFAULT(ufi->entry)) return (EIO); uobjpage = PGO_DONTCARE; uobj = NULL; promote = TRUE; } /* re-verify the state of the world. */ locked = uvmfault_relock(ufi); if (locked && amap != NULL) amap_lock(amap); /* might be changed */ if (uobjpage != PGO_DONTCARE) { uobj = uobjpage->uobject; rw_enter(uobj->vmobjlock, RW_WRITE); } /* * Re-verify that amap slot is still free. if there is * a problem, we clean up. */ if (locked && amap && amap_lookup(&ufi->entry->aref, ufi->orig_rvaddr - ufi->entry->start)) { if (locked) uvmfault_unlockall(ufi, amap, NULL); locked = FALSE; } /* didn't get the lock? release the page and retry. */ if (locked == FALSE && uobjpage != PGO_DONTCARE) { uvm_lock_pageq(); /* make sure it is in queues */ uvm_pageactivate(uobjpage); uvm_unlock_pageq(); if (uobjpage->pg_flags & PG_WANTED) /* still holding object lock */ wakeup(uobjpage); atomic_clearbits_int(&uobjpage->pg_flags, PG_BUSY|PG_WANTED); UVM_PAGE_OWN(uobjpage, NULL); } if (locked == FALSE) { if (uobjpage != PGO_DONTCARE) rw_exit(uobj->vmobjlock); return ERESTART; } /* * we have the data in uobjpage which is PG_BUSY */ } /* * notes: * - at this point uobjpage can not be NULL * - at this point uobjpage could be PG_WANTED (handle later) */ if (promote == FALSE) { /* * we are not promoting. if the mapping is COW ensure that we * don't give more access than we should (e.g. when doing a read * fault on a COPYONWRITE mapping we want to map the COW page in * R/O even though the entry protection could be R/W). * * set "pg" to the page we want to map in (uobjpage, usually) */ counters_inc(uvmexp_counters, flt_obj); if (UVM_ET_ISCOPYONWRITE(ufi->entry)) flt->enter_prot &= ~PROT_WRITE; pg = uobjpage; /* map in the actual object */ /* assert(uobjpage != PGO_DONTCARE) */ /* * we are faulting directly on the page. */ } else { /* * if we are going to promote the data to an anon we * allocate a blank anon here and plug it into our amap. */ #ifdef DIAGNOSTIC if (amap == NULL) panic("uvm_fault: want to promote data, but no anon"); #endif anon = uvm_analloc(); if (anon) { /* * In `Fill in data...' below, if * uobjpage == PGO_DONTCARE, we want * a zero'd, dirty page, so have * uvm_pagealloc() do that for us. */ anon->an_lock = amap->am_lock; pg = uvm_pagealloc(NULL, 0, anon, (uobjpage == PGO_DONTCARE) ? UVM_PGA_ZERO : 0); } /* * out of memory resources? */ if (anon == NULL || pg == NULL) { /* * arg! must unbusy our page and fail or sleep. */ if (uobjpage != PGO_DONTCARE) { uvm_lock_pageq(); uvm_pageactivate(uobjpage); uvm_unlock_pageq(); if (uobjpage->pg_flags & PG_WANTED) wakeup(uobjpage); atomic_clearbits_int(&uobjpage->pg_flags, PG_BUSY|PG_WANTED); UVM_PAGE_OWN(uobjpage, NULL); } /* unlock and fail ... */ uvmfault_unlockall(ufi, amap, uobj); if (anon == NULL) counters_inc(uvmexp_counters, flt_noanon); else { anon->an_lock = NULL; anon->an_ref--; uvm_anfree(anon); counters_inc(uvmexp_counters, flt_noram); } if (uvm_swapisfull()) return (ENOMEM); /* out of RAM, wait for more */ if (anon == NULL) uvm_anwait(); else uvm_wait("flt_noram5"); return ERESTART; } /* * fill in the data */ if (uobjpage != PGO_DONTCARE) { counters_inc(uvmexp_counters, flt_prcopy); /* copy page [pg now dirty] */ uvm_pagecopy(uobjpage, pg); /* * promote to shared amap? make sure all sharing * procs see it */ if ((amap_flags(amap) & AMAP_SHARED) != 0) { pmap_page_protect(uobjpage, PROT_NONE); } #if defined(MULTIPROCESSOR) && !defined(__HAVE_PMAP_MPSAFE_ENTER_COW) /* * Otherwise: * If there are multiple threads, either uvm or the * pmap has to make sure no threads see the old RO * mapping once any have seen the new RW mapping. * uvm does it here by forcing it to PROT_NONE before * inserting the new mapping. */ else if (P_HASSIBLING(curproc)) { pmap_page_protect(uobjpage, PROT_NONE); } #endif /* dispose of uobjpage. drop handle to uobj as well. */ if (uobjpage->pg_flags & PG_WANTED) wakeup(uobjpage); atomic_clearbits_int(&uobjpage->pg_flags, PG_BUSY|PG_WANTED); UVM_PAGE_OWN(uobjpage, NULL); uvm_lock_pageq(); uvm_pageactivate(uobjpage); uvm_unlock_pageq(); rw_exit(uobj->vmobjlock); uobj = NULL; } else { counters_inc(uvmexp_counters, flt_przero); /* * Page is zero'd and marked dirty by uvm_pagealloc() * above. */ } if (amap_add(&ufi->entry->aref, ufi->orig_rvaddr - ufi->entry->start, anon, 0)) { uvmfault_unlockall(ufi, amap, uobj); uvm_anfree(anon); counters_inc(uvmexp_counters, flt_noamap); if (uvm_swapisfull()) return (ENOMEM); amap_populate(&ufi->entry->aref, ufi->orig_rvaddr - ufi->entry->start); return ERESTART; } } /* note: pg is either the uobjpage or the new page in the new anon */ /* * all resources are present. we can now map it in and free our * resources. */ if (amap == NULL) KASSERT(anon == NULL); else { KASSERT(rw_write_held(amap->am_lock)); KASSERT(anon == NULL || anon->an_lock == amap->am_lock); } if (pmap_enter(ufi->orig_map->pmap, ufi->orig_rvaddr, VM_PAGE_TO_PHYS(pg) | flt->pa_flags, flt->enter_prot, flt->access_type | PMAP_CANFAIL | (flt->wired ? PMAP_WIRED : 0)) != 0) { /* * No need to undo what we did; we can simply think of * this as the pmap throwing away the mapping information. * * We do, however, have to go through the ReFault path, * as the map may change while we're asleep. */ if (pg->pg_flags & PG_WANTED) wakeup(pg); atomic_clearbits_int(&pg->pg_flags, PG_BUSY|PG_FAKE|PG_WANTED); UVM_PAGE_OWN(pg, NULL); uvmfault_unlockall(ufi, amap, uobj); if (uvm_swapisfull()) { /* XXX instrumentation */ return (ENOMEM); } /* XXX instrumentation */ uvm_wait("flt_pmfail2"); return ERESTART; } if (fault_type == VM_FAULT_WIRE) { uvm_lock_pageq(); uvm_pagewire(pg); uvm_unlock_pageq(); if (pg->pg_flags & PQ_AOBJ) { /* * since the now-wired page cannot be paged out, * release its swap resources for others to use. * since an aobj page with no swap cannot be clean, * mark it dirty now. * * use pg->uobject here. if the page is from a * tmpfs vnode, the pages are backed by its UAO and * not the vnode. */ KASSERT(uobj != NULL); KASSERT(uobj->vmobjlock == pg->uobject->vmobjlock); atomic_clearbits_int(&pg->pg_flags, PG_CLEAN); uao_dropswap(uobj, pg->offset >> PAGE_SHIFT); } } else { /* activate it */ uvm_lock_pageq(); uvm_pageactivate(pg); uvm_unlock_pageq(); } if (pg->pg_flags & PG_WANTED) wakeup(pg); atomic_clearbits_int(&pg->pg_flags, PG_BUSY|PG_FAKE|PG_WANTED); UVM_PAGE_OWN(pg, NULL); uvmfault_unlockall(ufi, amap, uobj); pmap_update(ufi->orig_map->pmap); return (0); } /* * uvm_fault_wire: wire down a range of virtual addresses in a map. * * => map may be read-locked by caller, but MUST NOT be write-locked. * => if map is read-locked, any operations which may cause map to * be write-locked in uvm_fault() must be taken care of by * the caller. See uvm_map_pageable(). */ int uvm_fault_wire(vm_map_t map, vaddr_t start, vaddr_t end, vm_prot_t access_type) { vaddr_t va; int rv; /* * now fault it in a page at a time. if the fault fails then we have * to undo what we have done. note that in uvm_fault PROT_NONE * is replaced with the max protection if fault_type is VM_FAULT_WIRE. */ for (va = start ; va < end ; va += PAGE_SIZE) { rv = uvm_fault(map, va, VM_FAULT_WIRE, access_type); if (rv) { if (va != start) { uvm_fault_unwire(map, start, va); } return (rv); } } return (0); } /* * uvm_fault_unwire(): unwire range of virtual space. */ void uvm_fault_unwire(vm_map_t map, vaddr_t start, vaddr_t end) { vm_map_lock_read(map); uvm_fault_unwire_locked(map, start, end); vm_map_unlock_read(map); } /* * uvm_fault_unwire_locked(): the guts of uvm_fault_unwire(). * * => map must be at least read-locked. */ void uvm_fault_unwire_locked(vm_map_t map, vaddr_t start, vaddr_t end) { vm_map_entry_t entry, oentry = NULL, next; pmap_t pmap = vm_map_pmap(map); vaddr_t va; paddr_t pa; struct vm_page *pg; KASSERT((map->flags & VM_MAP_INTRSAFE) == 0); vm_map_assert_anylock(map); /* * we assume that the area we are unwiring has actually been wired * in the first place. this means that we should be able to extract * the PAs from the pmap. */ /* * find the beginning map entry for the region. */ KASSERT(start >= vm_map_min(map) && end <= vm_map_max(map)); if (uvm_map_lookup_entry(map, start, &entry) == FALSE) panic("uvm_fault_unwire_locked: address not in map"); for (va = start; va < end ; va += PAGE_SIZE) { if (pmap_extract(pmap, va, &pa) == FALSE) continue; /* * find the map entry for the current address. */ KASSERT(va >= entry->start); while (entry && va >= entry->end) { next = RBT_NEXT(uvm_map_addr, entry); entry = next; } if (entry == NULL) return; if (va < entry->start) continue; /* * lock it. */ if (entry != oentry) { if (oentry != NULL) { uvm_map_unlock_entry(oentry); } uvm_map_lock_entry(entry); oentry = entry; } /* * if the entry is no longer wired, tell the pmap. */ if (VM_MAPENT_ISWIRED(entry) == 0) pmap_unwire(pmap, va); pg = PHYS_TO_VM_PAGE(pa); if (pg) { uvm_lock_pageq(); uvm_pageunwire(pg); uvm_unlock_pageq(); } } if (oentry != NULL) { uvm_map_unlock_entry(oentry); } } /* * uvmfault_unlockmaps: unlock the maps */ void uvmfault_unlockmaps(struct uvm_faultinfo *ufi, boolean_t write_locked) { /* * ufi can be NULL when this isn't really a fault, * but merely paging in anon data. */ if (ufi == NULL) { return; } uvmfault_update_stats(ufi); if (write_locked) { vm_map_unlock(ufi->map); } else { vm_map_unlock_read(ufi->map); } } /* * uvmfault_unlockall: unlock everything passed in. * * => maps must be read-locked (not write-locked). */ void uvmfault_unlockall(struct uvm_faultinfo *ufi, struct vm_amap *amap, struct uvm_object *uobj) { if (uobj) rw_exit(uobj->vmobjlock); if (amap != NULL) amap_unlock(amap); uvmfault_unlockmaps(ufi, FALSE); } /* * uvmfault_lookup: lookup a virtual address in a map * * => caller must provide a uvm_faultinfo structure with the IN * params properly filled in * => we will lookup the map entry (handling submaps) as we go * => if the lookup is a success we will return with the maps locked * => if "write_lock" is TRUE, we write_lock the map, otherwise we only * get a read lock. * => note that submaps can only appear in the kernel and they are * required to use the same virtual addresses as the map they * are referenced by (thus address translation between the main * map and the submap is unnecessary). */ boolean_t uvmfault_lookup(struct uvm_faultinfo *ufi, boolean_t write_lock) { vm_map_t tmpmap; /* * init ufi values for lookup. */ ufi->map = ufi->orig_map; ufi->size = ufi->orig_size; /* * keep going down levels until we are done. note that there can * only be two levels so we won't loop very long. */ while (1) { if (ufi->orig_rvaddr < ufi->map->min_offset || ufi->orig_rvaddr >= ufi->map->max_offset) return FALSE; /* lock map */ if (write_lock) { vm_map_lock(ufi->map); } else { vm_map_lock_read(ufi->map); } /* lookup */ if (!uvm_map_lookup_entry(ufi->map, ufi->orig_rvaddr, &ufi->entry)) { uvmfault_unlockmaps(ufi, write_lock); return FALSE; } /* reduce size if necessary */ if (ufi->entry->end - ufi->orig_rvaddr < ufi->size) ufi->size = ufi->entry->end - ufi->orig_rvaddr; /* * submap? replace map with the submap and lookup again. * note: VAs in submaps must match VAs in main map. */ if (UVM_ET_ISSUBMAP(ufi->entry)) { tmpmap = ufi->entry->object.sub_map; uvmfault_unlockmaps(ufi, write_lock); ufi->map = tmpmap; continue; } /* * got it! */ ufi->mapv = ufi->map->timestamp; return TRUE; } /* while loop */ /*NOTREACHED*/ } /* * uvmfault_relock: attempt to relock the same version of the map * * => fault data structures should be unlocked before calling. * => if a success (TRUE) maps will be locked after call. */ boolean_t uvmfault_relock(struct uvm_faultinfo *ufi) { /* * ufi can be NULL when this isn't really a fault, * but merely paging in anon data. */ if (ufi == NULL) { return TRUE; } counters_inc(uvmexp_counters, flt_relck); /* * relock map. fail if version mismatch (in which case nothing * gets locked). */ vm_map_lock_read(ufi->map); if (ufi->mapv != ufi->map->timestamp) { vm_map_unlock_read(ufi->map); return FALSE; } counters_inc(uvmexp_counters, flt_relckok); return TRUE; /* got it! */ }

mknod(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff7b)
r1 = socket(0x1, 0x4001, 0x0)
r2 = dup(r1)
r3 = fcntl$dupfd(r2, 0x2, 0xffffffffffffffff)
close(r3)
r4 = socket(0x18, 0x2, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
setsockopt$sock_int(r3, 0xffff, 0x1023, &(0x7f0000000040), 0x4)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000500)={0x3, &(0x7f00000000c0)=[{}, {0x1, 0x0, 0x0, 0x2}, {0x6, 0x0, 0x0, 0xff}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0xff0a, 0x0, 0x37)


r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x0)
setsockopt(r1, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
getsockopt(r0, 0x29, 0xb, 0x0, 0x0)


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
madvise(&(0x7f00003e0000/0x1000)=nil, 0x1000, 0x0)
munmap(&(0x7f00003e1000/0x1000)=nil, 0x1000)
munmap(&(0x7f00003e0000/0x3000)=nil, 0x3000)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000))
socket$inet(0x2, 0x2, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {}, {0x2, 0x0, 0x0, 0x40804}]})
ioctl$DIOCMAP(0xffffffffffffffff, 0xc0106477, &(0x7f00000000c0)={0x0, r0})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000001c0)={0x0, 0x0, 0xfffffffffffffffe})
open(&(0x7f0000000100)='./file0\x00', 0x615, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)={0x3, 0x7fffffff})
r0 = kqueue()
kevent(r0, &(0x7f00000000c0), 0x30, 0x0, 0x57d, 0x0)
kevent(r0, 0x0, 0x0, &(0x7f0000000600), 0x2, 0x0)


mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
rename(&(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000f40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f00000007c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000001040)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mkdir(&(0x7f0000000180)='./file0\x00', 0x0)


r0 = openat$pf(0xffffffffffffff9c, &(0x7f0000000000), 0x8301, 0x0)
ioctl$TIOCSFLAGS(r0, 0x8004745c, &(0x7f0000000040)=0x9)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x2, &(0x7f0000000380)=[{0xb1, 0x0, 0x0, 0x800}, {0x8006}]})
syz_emit_ethernet(0x56, &(0x7f00000003c0)=ANY=[])


r0 = open$dir(&(0x7f0000000040)='./file0\x00', 0xae828e137847f62, 0x0)
setrlimit(0x1, &(0x7f0000000000)={0xfffffffffffffffd, 0xffffffffffffffff})
ftruncate(r0, 0x40000000007)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000140)="b1000504000004000000000007000000331c13fecea10500fef96ec0c72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a421020000ed710fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b1257aea8c500002002fbfe0c2300008abfba0900000008e371a3f8343732051ed6b71d89e0000405f8fffffe13000000", 0xb1, 0x0, 0x0, 0x0)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r0, 0x8210560b, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0})
r1 = openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_TERM(0xffffffffffffffff, 0x80045604, 0x0)
ioctl$VMM_IOC_RUN(r1, 0xc0205602, &(0x7f00000002c0)={0x1ff, 0x8, 0x0, 0x0, 0x0, 0x1, 0x4e})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000280)={0x3, &(0x7f0000000040)=[{0x1c}, {0x15}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000180)=ANY=[])


open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
r0 = open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
r1 = getpid()
ktrace(&(0x7f0000000280)='./file0\x00', 0x0, 0x928, r1)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r0, 0x0)
unveil(&(0x7f0000000280)='.\x00', &(0x7f00000002c0)='c\x00')


ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105727, &(0x7f0000000000)={&(0x7f0000000040)=[{}, {}], 0x2})
sysctl$hw(&(0x7f0000000000)={0x4, 0x1f}, 0x3, 0x0, 0x0, 0x0, 0x2)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
bind(r0, &(0x7f0000000080)=@un=@file={0x41a0805bbded0123, './file0\x00'}, 0x4)
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r1, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0x94739c02}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
madvise(&(0x7f00003e0000/0x1000)=nil, 0x1000, 0x0)


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r0 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000001000/0x3000)=nil)
shmat(r0, &(0x7f0000001000/0x3000)=nil, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000000)=[{&(0x7f0000001740)='r', 0x1}], 0x1)
msync(&(0x7f0000000000/0x3000)=nil, 0x3003, 0x4)


setrlimit(0x8, &(0x7f0000000040)={0x8, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047470, &(0x7f0000000280)=0x5)
readv(r0, &(0x7f0000000200)=[{&(0x7f0000000100)=""/176, 0xb0}], 0x1)
ioctl$TIOCSTOP(r0, 0x2000746f)
execve(0x0, 0x0, 0x0)


sysctl$net_inet_carp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x3}, 0x4, 0x0, 0x0, &(0x7f00000010c0)="e1008919", 0x4)


socket(0x0, 0x0, 0x0)
getuid()
setreuid(0x0, 0x0)
socket(0x0, 0x0, 0x0)
setreuid(0xee00, 0x0)
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x800000018, 0x2, 0x0)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
r0 = open(&(0x7f0000000180)='./file0\x00', 0x2, 0x0)
ioctl$FIONREAD(r0, 0x8020697a, &(0x7f0000000100))


poll(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f0000000100)={0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{}, {0x3c}, {0x6}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000480)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f00000001c0)=[{0x4c}, {0x61}, {0x810e}]})
syz_emit_ethernet(0x126f, &(0x7f0000000000)=ANY=[])


r0 = syz_open_pts()
ioctl$TIOCSTSTAMP(r0, 0x8008745a, &(0x7f00000002c0)={0x0, 0x7f})


socket(0x11, 0x3, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(r0, 0xc0206921, &(0x7f00000001c0))
select(0x40, &(0x7f0000000140), 0x0, &(0x7f0000000200)={0xffffffffffffffcf}, 0x0)
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x8020690c, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x1}, {0x2c}, {0x16}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f00000001c0)=ANY=[])


r0 = syz_open_pts()
r1 = getpgrp()
fcntl$lock(r0, 0x0, &(0x7f0000000440)={0x2, 0x0, 0x5, 0xfff, r1})
write(r0, &(0x7f0000000100)='@', 0x1)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000000)=0x9)
close(r0)
execve(0x0, 0x0, 0x0)
r2 = semget(0x1, 0x2, 0x389)
r3 = getuid()
setreuid(0xee00, r3)
setsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000500)={r1, r3, 0xffffffffffffffff}, 0xc)
semctl$GETNCNT(r2, 0x4, 0x3, &(0x7f0000000540)=""/189)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f00000000c0)=[{}, {0x3, 0x0, 0x0, 0x49}, {0x81, 0x0, 0x0, 0x1}]})
connect$unix(0xffffffffffffffff, &(0x7f0000000380)=@file={0x0, './file0\x00'}, 0xa)
sysctl$net_inet_divert(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1934, 0x0, 0x94e88e483d20a485)
syz_open_pts()
syz_open_pts()
syz_open_pts()
ioctl$WSKBDIO_GETMAP(0xffffffffffffffff, 0xc0105715, &(0x7f0000000000)={0x0, 0x0})
shmctl$IPC_STAT(0x0, 0x2, 0x0)
sysctl$hw(&(0x7f0000001980)={0x6, 0x17}, 0x2, 0x0, &(0x7f0000001a80), 0x0, 0x0)
r4 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
readv(r4, &(0x7f0000000400)=[{&(0x7f0000000280)=""/128, 0x80}, {&(0x7f0000000300)=""/217, 0xd9}], 0x2)
r5 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r6 = fcntl$dupfd(r5, 0x3, 0xffffffffffffffff)
ioctl$WSKBDIO_GETMAP(r6, 0x80047476, &(0x7f0000000180)={0x0, 0x0})
socket(0x11, 0x3, 0x0)


mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x5203)
open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b10005160000000000000000070000001a5113fecea10500fef96ecfc72fd3357a89583535673039d2d236acf20b7804be38164991f7c8cf5f882b2900e1aa5b23edebc8ef99a8ad491726fa8251e2f0ac3ebbc2feb3fda1139b672f4d3353eb06acdb35a069d7080000000000000000008904000000000022830cf41bed66f4f365ccdcf3e4999d9d", 0x89, 0x0, 0x0, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x100000040000002, 0xffffffffffffffff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendmsg$unix(r0, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x400, 0x10)
symlinkat(&(0x7f0000000000)='./file0\x00', r0, &(0x7f00000000c0)='./file0\x00')
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x462, 0x0)
sysctl$net_inet6_ip6(&(0x7f0000001f40)={0x4, 0x18, 0x29, 0x2b}, 0x4, &(0x7f0000001f80)="b96cfa23", &(0x7f0000002080)=0x4, &(0x7f00000020c0), 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x400, 0x0)
sysctl$net_inet6_ip6(&(0x7f0000000200)={0x4, 0x18, 0x29, 0x5}, 0x4, &(0x7f0000000240)="24dc2e8e608c5de6799730a8b7b155f2e154d37199f555c869f791f2e0255e821fa6c1c7610158f94a7e572d15cf985d3af9192b6a8cd69d2454df305fecf310bf852c3b895c7f9cdb60ff6605a33a76568c603a0fd46a6805819a4c4f65efd7405003b84d8ec5d6562f63de03bfcbdeb6e2e7990006d56f8ae6a02038dd6c51e62cfdf0b1301389b8d058ec6e8aa2cad08a9ded0164efb665d19afd7b4e7c9c4e954ac0a79eb79c9e21c8f6009c998512ff4a91944a718497611af35ecbe3ecda11b845eb388dcaa317f99d7e891f6806c06de5ebe6ddcc3a85eaaf", &(0x7f0000000340)=0xdc, &(0x7f0000000440)="e0463b5284ff404c7920691a699b53e762a92ec78fdc77fa5be289cff0be1d298bb32272ee57e77f6701a412cc113e1b204adaf8a4f5445ff370d7297ee1edec74b02a23fb087118d5faed59697acecb9d5db45b9af81128a2a9827ec1f1616bd39ce0b2af3b3b40186997fe141917b7d7f4d1937114da39c1d62f77b83b82c983342423a856b6251361acf501b855a7eb8d2a4673ef508ffbedd725fb7e119c82635402817b02b8de8954815d046cab42e1fb92e1349ec08cfc333afd2270d090a3accefaf207f3df8e79715add2966d9572a874f57d2266e8cc590552284424c67010ccbf6d0a94e324888e210a7bee9080df021891bfcc70c2b", 0xfb)
socket$unix(0x1, 0x1, 0x0)
semget(0x0, 0x1, 0x0)
getuid()
getgid()
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f0000000540)={0x10, 0x0, [{&(0x7f0000001000/0x2000)=nil, &(0x7f0000001000/0x3000)=nil, 0x2}, {&(0x7f0000000000/0x3000)=nil, &(0x7f0000001000/0x2000)=nil, 0x17e}, {&(0x7f0000001000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil, 0xfff}, {&(0x7f0000002000/0x3000)=nil, &(0x7f0000001000/0x3000)=nil, 0x9}, {&(0x7f0000002000/0x1000)=nil, &(0x7f0000ffc000/0x3000)=nil, 0x8001}, {&(0x7f0000002000/0x4000)=nil, &(0x7f0000ffd000/0x3000)=nil, 0x1}, {&(0x7f0000002000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil, 0x5}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000000000/0x1000)=nil, 0x675}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000001000/0x3000)=nil, 0x8000}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000000000/0x2000)=nil, 0x4}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000003000/0x4000)=nil, 0x9}, {&(0x7f0000003000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil, 0x1ff}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000000000/0x4000)=nil, 0x4}, {&(0x7f0000004000/0x4000)=nil, &(0x7f0000006000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ff9000/0x4000)=nil, 0x7e2}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ff9000/0x4000)=nil, 0x10000}], './file0\x00', 0x4})
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
open(0x0, 0x0, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000100)=[{0x1, 0x0, 0x2}, {0x14}, {0x6, 0x0, 0x2}]})
syz_emit_ethernet(0xe, &(0x7f00000000c0)=ANY=[])
select(0x40, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, 0x4000000000000000, 0x0, 0x0, 0x8000000000000000}, &(0x7f0000000040)={0x7fffffff, 0xfffffffffffffffe, 0x0, 0x0, 0xfffffffffffffffe, 0xffffffffffffffff, 0x0, 0x1}, 0x0, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f00000007c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000a40)='./file0\x00')
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f00000001c0)={0x3, &(0x7f0000000040)=[{0x60}, {0x28}, {0x4000006}]})
pipe(&(0x7f0000000400)={<r3=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r3, 0x80047476, &(0x7f0000000100)={0x0, 0x0})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000080)=[{0x81}, {0x64}, {0x8106}]})
syz_emit_ethernet(0xe, &(0x7f0000000100)=ANY=[])


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000980), 0xe8, 0x0)
r1 = fcntl$dupfd(r0, 0x3, 0xffffffffffffff9c)
poll(&(0x7f0000000080)=[{}, {r1, 0x51}], 0x2, 0x0)
poll(&(0x7f0000000380)=[{}, {r1, 0x14a}], 0x2, 0x0)


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000240)="ea00000100000000", 0xc)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
r1 = socket$inet(0x2, 0x2, 0x0)
close(r1)
r2 = socket$inet(0x2, 0x2, 0x0)
dup2(r0, r2)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000240)="ea02000000000000", 0x8)
setsockopt$inet_opts(r1, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0x8)


r0 = kqueue()
kevent(r0, &(0x7f0000000080)=[{{}, 0xfffffffffffffff9, 0xeb, 0x11}], 0x3eb8802, 0x0, 0x0, 0x0)


r0 = open(&(0x7f0000000480)='./file0\x00', 0x0, 0x4ebfac6bbaf7949)
writev(r0, &(0x7f00000000c0)=[{&(0x7f0000000080)='#!', 0x2}], 0x1)
sendto(r0, &(0x7f00000009c0)="280a77ec1445702b9c6797aed033f697c1336f3ce4b2d360ea0ed981662bb278f97523f2e49d5dce5632028758f7bb340b551582467d08e6dcbe58c2ffd4e1ba49426b930efa0de58d7d12b9a8c1853dc6936fc1b00c9831c692c22845864b5a0d7454e362aa8ed31923c082142216fe22657c1c76d9c1618d65f10df27373289415d1f3731d415ced818ba45ed0c30d764146f77a8b6d8361e73021a88c0f76ed05957a0f46d30752bac8a4d8b26ee69345688a15c77b61f416ef384189fa87446d078afbd4297de05cadd899693c7876267892ef96e7f886e6d2cd97ed9301598e1badb78812d9a833fecd068ab0ece7ab0796c95513daa9937f8da8c800b7a6851c66115a63b7ca5f7caf9035ef14662722a59e7ce7700b5d061f32b70b141d8ea7723ed1a7df05b852328713a6c54b6ebe0fa631c10098b0a3d596f1f2dea2be99210eff03e28535c895536c2a01c30f64a64ee35c115aa360adf618c9e9a5af2ef578e3cc2111895a284a9ef2b2a5b816d94f6290d962e607416a07799aea56fc13dd81b3f338e6c5dae5ac49889fe28bf5343fa53f0ea1b4ce2e02e8fb82f7ba0cf1d83bf0944fe04c093c742e449d3714ac7dcbd8621171e586ff83b77c6fa1ebf10924970a0f533bdfd33fa6683a7d6403bd5e986667bce1b64597c1e40ddd9fd5e39ab6bd04bb9a75567a3b6b90f2597bbef8668e37640357d6ebfc8d1c8e7c1339f629a20eed228202596ed56484705b3f39bf2ded9e02af8d5402ed16c3a56890948a23c28242b68cbca4277d284d20adde3afb3f1861eaeaced25941c1336e8dcdbfe718f2798ae26c64887f16b4bb75a20e25949d8e4618bf530c3bfc78ebbf0ff878f15131e1edaf8a1c15eb13a84c43b730eb0bc154fc17ec28c8aafa76ac30e60c646e5f38263b84efffd94390e56790b191a9c4aec66792ca0a7599f0422432bd205b5c8fb43fae8ff2b96a1889090282567826d3549682a2998199be3b51e4fb229485079cfea51cf88c18c5b26ab2fcfb1c45ae52fbd4bb392ef08145194c1af20b1bb179530e022b04572a4266fc9eed25632785cd6741000a01a04fc64a2156db3cb6c5bc7f42f5a6a4438f9aeb4092462fab7c8a9ddbddef804484bd191cdbc6386ceb05cb2865a8b23c50881a71f68f1a30498d1533432adfd63287866df90c1feb9ad6b57e60d78a898167775267a69a428b9912e9a4e5280e1f2c6d6da1432dc3352d257a2ee19af4d32f1a557e1084e8ec01cd18c4882ae54f2b486f821d92d4fbc2625be6d8502c37adc896b03a04502a04de428920e84394c7ecc67a26fc30d9c82ba22eb1c37d4c537ed61ece5274589de55ebee8324ee4ab1b8bdd7fc3c5c6073b3bb972d0fc4e15b4cb0263fe8c8036e8fc180b699978a6a398c1d502f1f7da9bb7472f632f278528eecec13a1d9975d606bd37f62f6633fa4c7f3a2f9f9bb412057814b77f6b27285b923b613c397c38eee3e198ad6826a4fa93cd2602eb22f2d75841f33da31d2481d8bc7c7e04acead805057e95d707461e2c900570aa85f8a6259da69ece9915bed1fd63f5d79764d10dddebc37fab0a854089289d9bf96f776e15416848df5a5b0ca4f3ba18371a3c3ed4492a885e53dcd7c1c610a491294a4011a8d8c389278788e4077ca2ce1ca31c1a46def9f694e1892ac4e7bd8f8d5d593ddc5de5a2ed8163086c15f02cd4669ea69c828c44cc70284faf3f24e2bafb4ad1907e919cdc06969fd3c0dcb32f03e6b4e87d2d35211939629b25c80426e7d55c9c4e01085834418683c8598aa5a62ce020a553594248492b50ee5d4804c8c02850803968b651c4a50d83351e56ab8712d3f2d050234bef1743fd3ade99307afca64b181a239f16d97c79fec0de2c0548c33857f038178df46ef6d112ae15dd5d30c0fbd3a6344490b78a3e11c6f9b1263df56418ba6b990db329b256d95a78b1207a5e6bec9dcc7035a42739d54d66ee5ac52561fb35214511dec0e46080e5f0119ab2a3cf496cf1f1109dbac56c741fe8db5f4af72194a8cfa253584c7c7ba7a3c8467049fc87246c4f81cf783243824cfc8a53108ec590cca24215a60247389b70b2a79a4a81ac379c41f1fb7e8375b7e0aada0c5e242874ce823f0e16db36e0202af6ccd1533eb2c629a747af08bd9f3016edcfd25b3eb65c91842dd357f05d6df9d23060169ba0a98b42a6c3b0f276352b55f494d0876ad48b71590f1e580e2108841b25aeeea4c33422dab23ce4961ef1bbb3e47519ca74549a77255c6978eabd7fde06d8c711076ba8196c4dd48c96f4f61f256e7330533e50163f0e69a5a81d8d744ca7fa49eca6ea45bd3b105f89a10265806af27221c71a112e8f5a2cfee34ae3d4f29ec3158aabbd66856386e8a1f9c2fcda71629c959660ea0a1bbdb6747408c81ef79ea739b72a5a5a666b237451f68a85b0c10849f147e74884ea94dbe4ae1c33b84be5da5c52e4d7916323ce0584720c47bddb2d6a3b3b902c4d7a69d16294432ca5179d9ee22b302215d917bfd755fb17256f55b605a1ede51a84d2036e32dbc853a78865ebcb7af473eab2c54259afc5dac48c463df195417008d1075b8b33a4484687bb753fc407d53c56299d55874a136dc85a0ab00ed93297274af0f56bf9e224fef940a4067c0ecb4400c8283128b66e507070d9949d54c6ffaa48e4ca7cf7657295fc9e51e15b76f840d86364eaf884cb3f1bbfb9e15c77a3c4a27c59e66b71e2a5471777529284ef1b6170c86094952839c09ac3b52481bb472d068c92fca0ae5c8f1211471122cf2fe0a1d6d22150fd1211a30b7be0c98e61eec2fabb55e9411f3eadd6a34a10f6d61ad06245960bc93bdc37d5e82b15c69d4ef064fe585a96f3d7b05b7808acc461f2f63d12cef86fea1b5dd3d4eb5c4a60bb5f796867a63fcee8482339e1a5d7e29234c2a86a95bc2f683304156425914c10c305e7611cb687c4c1664c211be3dd6680b4a773ca8695d15176a427003222fbf0933a103c14100a136dad094985f61c4c33215573a82ccc979463ea089e7560dec4d1d142b1f73321cc0bd37f1bf33e186c355082d7cca51bf6600363fb1466865208ae2ca6a6f158a450004e3357a91895245abf0c59cba380ef3c4f04ce223938da68003d42a50e6f504c1878da6c9c7abce63af1c59b9e7bb7ef2eaf437b879c20bec73a42cf4cb46a0482ccf4e159b56ddc1c04534dcd0702a12d5ad9ab0d6e255a21b686a2629b5bd0cd0f88992962c69aedf1f7dde1cb192f7c21cd2a11eedbba08af9a4475c43ff760ae41eb41103b71b09786b631cd0ecdbd8986ffc6ec0e8d45f20f143fc56738322a15be1c0bc2c28f86f2c354eeb3c78bec4572a9ad59be106968c102738c7e3fc00a78f708b9aa66f319b1f7f88832dc4cf429f81486c8ded994f7478c084e9ccde0ce10a49f965d88efe8c9623d13a487777f71bdb47cd73d4c0c6922cb9d5a8d9869eed065757787b0560031d7e72898244c1411774859b84cfed1208ebb814fccf65462ee48b871ae1c3aacc3174bc3c0be3718712258d0ed63ed7fd62ee86f88a7df7295a48a075502892e10e2a8466e703b3f20dfbfc24b6ac51f9a869149bc49736d03ba835a77216618bfdd8b153c8f26bb5e67484a8009ef28dd3cfeac016f00e3102bb71ac03d50f0a50886c29c03e6fd6524b3cfd6348cd4171ec394a456610b83195780cf47ea27f17dffd07906221a641d59835ea21eccf6608cecdf3cafbc7b512efa85c694d65fe9c9a07b6af1606f60e935dc62d530da2d0abfdf28eca07f1c850e41c7fc5cf02ddfe8dda4d3f706bb4ce54cb04e158458f682eef83319307e026d0f9d830d4acccf7d8989fd28e1a28a8791c3c4ae3b206c1fb5707f3667eaf18685e492350a9759f6b0abba263430f9afa4d0e8457f43333f01d92a6c69f4f9257508594d833a29fdd60ef9e820c14b30f8ada6da2e5e15fff086055f9adfeb188eefeab45cea8b5f6cf6814dd504f8c6008591b664d8566682d909e2a199580de51f84a6180bec4227890b21a1d765faea0cf1baf527d57aa3f6b853da8228061da33c8e7545799d3fb1c48766a4d0de2232e245f8be8c886aa268e9b4510e50613f6e38fc73815916f02b8a768400c83efa8bd3cec0970a8bbd7a2cd120f76feb0d2fe3fe97b790bfa514fa2ec40f9523818c63952358f4a7fab096ba96413ea8a19e02dc0f443cf498a58cd741e86b2e11110f8c898cdaf58091b7d24896a43988bc4de0186d6048ad8506ff45c4867dcc709b83a6643ac4c04f59bc92b9e8986e33255824cbabbe7396dee841314631df2b25eaddc8c167c4df5f5e9749fb86f9df7dc156f73a4b04987da8f49837165f107970de3a5755c05970968e75a6e23a3254ceb09b1624b9f27b04fa694671d29e5bd5017b74ea07fba0c52bdebbfd743a029d9d6e44eadf35d93399447470e2c3d615078e35e6b31fc842e9fe4800884aa22384d4c918905ec750fd9c8f5950684b74fa1f82c817d33bb52e9fc1068eeb30dc5482340e72bae05184f0cea477e14601c12c5ce721b098148544dedc0da97de095f3d2fbca1414b41319a0e1c76d946268fc2378a45421de063c6d32c3e871f9552a0844e7e00117bc7d72060eb8977bebd74c89344e04238554054d792960c9638f42df98b7561508770599e783b77d4fa6b9a3f18cc75debae40e3b4ed76f1ba5b524b64edc101e81edabf4aa71a9e2e76acaaca3bff679a7a1d1ca9951a10c9d4ea0310e68da1903d1976ca7fb19701ef9cf04f265b6ffe1fdf4fca202296fefe5182e3f01b62115bd769a44e6960b39c5ecbf03fd0b91eb1d2645a9720c1a166fb2c6801f4cc3ab0ffce913faf7a79ea56a22272ff60a90b81aeddf78157603d470bd33875121b2989cdf749e158b2cf262ac7c594627a8a0d71e006578b7b5f6b0daba8163ce4636710bf53a13c6d1e5d7564b4c966c2637ae050006908e4c21214a32ecba5decf7b68bd97b631905fb5c5bf14b2210e2c688035f1b72f327c97f19e2e7cc8321a7887daddbe842158373c8f2e71ed564720a638e960c7c28b9b51497d64094556dd52f5c479007d9451d3dc1bc009978c57637c9788320b8fbe5a30d13a452b20f8ea8c4419c1750399ab536aa2205a79d588a9f0d8d562adad10872e0f9da14450be7bef0aff5ebf651662434eb3ab0ce2d1492210c057ede863636de7c55156c83274d308fefbf8bcbb85d9978341e1923900e50d5f16900f10949d77f9c9ef7c534d38cc82d2d4274e0774fea1f1d726fe08f9e77ec6f6ba0560a0f92da7effaf035b71c5e1ab1461e2c74eb003b2d64ef5a617625103636edd32b04c60252bccb489b756427668a2ae7dfe4f944a0d50a54ed730bb3c56d287fa0663611ddd0df617cf2795b8f63b8a23642010d10f7863058be5477f4530251a4e28406f728e814cd4cc9c3e60440a66b5b6a46b388a03a66bdce2a85d938b3dd327c860a92661c1313730a5718f3a834f4c099316e7214ed0e7c51b7e33162a97fab986013bc0b616e277c1c519e9c4f8cfa4be12805abf1e1c55bb00aca03244536d286cc2d7863c03e360498b39e62d5823f6f7272c88fe4d1d3e5fbcca1137a28c15b585db8b27d0f4eb3805e36f00c7619a93f46746fceca8124570b3e23d70ffdc941cb4d725a9a1b25c1aa44315918df7a5355885578bdc516ddaf1f214025b03afbf52f", 0xfe0, 0x4, &(0x7f00000001c0)=@un=@file={0x0, './file0\x00'}, 0xa)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000180))
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
syz_open_pts()
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f0000000040)=[{0x0, 0x0, 0x2}, {0x6, 0xfc}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x33}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x10, 0x0, 0x37)
close(0xffffffffffffffff)
sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x13}, 0x4, 0x0, 0x0, &(0x7f0000000140), 0x0)
openat$pf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x2, 0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x37}, 0x4, &(0x7f0000000000)="71f91e3471ac0058bc5a91501d942400b5e1a0757cb9af769c7afec37082", &(0x7f0000000080)=0x56, 0x0, 0x2e)
r1 = socket(0x11, 0x3, 0x0)
sendto$unix(r1, &(0x7f00000000c0)="b10005136000009f050000002010000000000000cea10500fef96ecfc727d3357ae302b37b67ca1f2d61db7f4de57804be38164991f7c8cf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f4d335d223e7db3008b95665bc6fc2102000000720fd38bfbb770c1f5a872c881ea772ec5890405b3b9c2668396f4cd1257aea8c500002002fbfc0c2300008abfba0900000008e37f71a3f8343712051eeab71d89e000040381ecb664000000", 0xb1, 0x0, 0x0, 0x0)
syz_open_pts()
writev(0xffffffffffffffff, 0x0, 0x0)
syz_open_pts()
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
ioctl$TIOCSTAT(0xffffffffffffffff, 0x20007465, 0x0)
socket$inet(0x2, 0x0, 0x0)
sysctl$hw(0x0, 0x0, &(0x7f0000000380)='{', &(0x7f0000000180)=0x1, &(0x7f00000001c0), 0x0)
sysctl$kern(&(0x7f0000000080), 0x4000000000000004, 0x0, 0x0, 0x0, 0x0)


socket(0x0, 0x0, 0x0)
poll(&(0x7f0000000200)=[{}], 0x1, 0x87e)
r0 = open(&(0x7f0000001440)='./file0\x00', 0x615, 0x0)
ioctl$WSKBDIO_GETDEFAULTBELL(0xffffffffffffffff, 0x40105706, &(0x7f0000000040))
poll(&(0x7f0000000000)=[{}], 0x1, 0x8001)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x10, r0, 0x0)
ftruncate(r0, 0x25b3)
execve(0x0, 0x0, 0x0)


sysctl$hw(&(0x7f0000000000)={0x6, 0x2}, 0x2, 0x0, 0x0, &(0x7f00000002c0), 0x0)
syz_open_pts()
r0 = socket(0x18, 0x2, 0x0)
close(r0)
socket(0x800000018, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendmsg(0xffffffffffffffff, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socket(0x18, 0x1, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
sysctl$hw(&(0x7f0000000040)={0x6, 0xe}, 0x2, &(0x7f0000000080)="7178e230c23632c7fe2cbf2b1b8dedccdf0e474f72234651102310ebc843ed5297eee515382b5b5f59926c877b10fc287077a26ff9531d13afa0fdc8497b70a9ad8acc84b50e6db7a1a222d79c89274b3837a417c34a0bc3becebc1eed5b641407d4b746e7de21c19957d366b3fb32159eec63848ed1af589555df0d4ca15db2e73d48ed4a3961939c44819e01caa94d5eb11a90f7189c3dcb45e280865a160198312e3652c705eca9ab00e98bd175c70c86416c", &(0x7f0000000140)=0xb4, &(0x7f0000000200)="e48f9679650bbdb3a53d8963d84e0b573cdbedc5bdb12357c510ab7324edc27ddea802aa7e93f1ffdd3a9d152d72c867e6ca80e8cfe79b725b7cc5e5e91571b5319ec82f0c5957b2cb8aa97168bc82b0742ed2dd28bf97aeaef9cb61176a7c4e668fb635d869d02fbf83279c501b2abc34b3ea45e37b1fe6ee61b29f1a96861c4a200816343b3f4451", 0x89)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = kqueue()
kevent(r2, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r3 = socket(0x2, 0x3, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r4 = syz_open_pts()
close(r4)
syz_open_pts()
ioctl$FIOASYNC(r4, 0x80047469, &(0x7f00000000c0)=0x5)
execve(0x0, 0x0, 0x0)
ioctl$FIONREAD(r3, 0xc0206921, &(0x7f00000001c0))
r5 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r5, 0xc0206921, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)


select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
socket(0x1e, 0x3, 0x0)
socket(0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
ioctl$TIOCSTSTAMP(0xffffffffffffffff, 0x8008745a, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
openat$vnd(0xffffffffffffff9c, &(0x7f0000000200), 0x4a0, 0x0)
open(&(0x7f0000000180)='./file0\x00', 0x75f493fec6515f78, 0x0)
r0 = getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r0, 0x0, 0x3, 0x2, 0x100000000})
r1 = fcntl$getown(0xffffffffffffffff, 0x5)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0xb32, r1)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
pipe(&(0x7f0000000000))
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000180)=[{{}, 0xfffffffffffffff9, 0x9, 0x0, 0x0, 0x2}, {{}, 0x0, 0x0, 0x0, 0x0, 0x10}], 0x0, 0x0)
r2 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x10215, 0x0)
ioctl$VNDIOCSET(r2, 0x81946467, &(0x7f0000000180)={0x0, 0xffffffffffffffff, 0x0})


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f00000000c0)="b1000504000004000000000007000000331c13fecea10500fef96ec0c72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a421020000ed710fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b1257aea8c5000020e4fafe0c2300008abfba0900000008e371a3f8343732051ed6b71d89e0000405f8fffffe13000000", 0xb1, 0x0, 0x0, 0x0)


r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = kqueue()
open$dir(&(0x7f00000002c0)='./file0\x00', 0x200, 0x0)
r2 = open$dir(&(0x7f0000000200)='./file0\x00', 0x41, 0x0)
r3 = syz_open_pts()
sysctl$hw(&(0x7f0000000040)={0x6, 0x18}, 0x2, &(0x7f0000000080), 0x0, 0x0, 0x0)
close(r3)
r4 = syz_open_pts()
ioctl$TIOCSETD(r3, 0x8004741b, &(0x7f0000000000)=0x7)
close(r4)
getdents(0xffffffffffffff9c, 0x0, 0x0)
kevent(r1, &(0x7f0000000200)=[{{r2}, 0xfffffffffffffffc, 0x0, 0x20000000, 0x6}], 0x8001, &(0x7f0000000080)=[{{r0}, 0xfffffffffffffffc, 0x80, 0x4000000e, 0x0, 0x100000001}, {{r3}, 0xffffffffffffffff, 0x92, 0x40000000, 0x10009, 0x7f}], 0x400, 0x0)
openat$wskbd(0xffffffffffffff9c, &(0x7f0000000240), 0x1, 0x0)
setreuid(0xee00, 0x0)
r5 = getuid()
setreuid(0xee00, r5)
ioctl$WSKBDIO_SETDEFAULTKEYREPEAT(0xffffffffffffffff, 0x800c5709, &(0x7f0000000140))
r6 = openat$zero(0xffffffffffffff9c, &(0x7f00000000c0), 0x41, 0x0)
fcntl$lock(r6, 0x9, &(0x7f00000001c0)={0x2, 0x0, 0xfffffffffffffffe, 0x1000100000000})
ioctl$TIOCSETA(r6, 0x802c7414, 0x0)
fchdir(0xffffffffffffffff)
semop(0x0, &(0x7f0000000000)=[{0x2, 0xfff, 0x800}, {0x1, 0x4, 0x1000}, {0x2, 0x20, 0x1000}, {0x3, 0x3, 0x800}, {0x1, 0x5}], 0x5)
r7 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r7, 0x801169ac, &(0x7f00000001c0))
r8 = kqueue()
unveil(0x0, 0x0)
kevent(r8, &(0x7f0000000240)=[{{}, 0xfffffffffffffff9}, {{}, 0x0, 0x2}], 0x0, 0x0, 0xfffffffb, 0x0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000004c0), 0x2, 0x0)
writev(r0, &(0x7f0000000380)=[{&(0x7f0000000180)="e741a883cc60157a810468823ac987a7254eba680c54664b8a3b537273fff1c3d4ae6950f3d030e3dc1c729ce1bb4d0e7dec57876947d3d26f8d356150f6b052bd44cc7280c8724198c173f70a712dceccc05077889f297affadcde5f1ad9e2d5363aa93bb37c6c73e0f4f8ad07537aaf9bcf3cfd30353113487589d60233184c0fd43e9f38537079fa1f0d832f277395d0802b941d2040dc8b180d9fbdc6e39334ccf08067c7cdaec5fe52f5a1c9f211fa896ff7dac6b76218c8fa7f1536311341abb6206ffda9672f479bedcb7c67ecde88e3728cb5761b35435", 0xdb}, {&(0x7f00000005c0)='6', 0x1}], 0x2)
execve(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000140)=[{0x84}, {0xc0}, {0x4006}]})
syz_emit_ethernet(0x2a, &(0x7f00000000c0)=ANY=[])


mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x205b9b)
r0 = openat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x0, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000100)=[{{r0}, 0xfffffffffffffffe, 0xbf}], 0x0, 0x0, 0x0, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f0000000080), 0xfd, 0x0, 0x8002, 0x0)
kevent(r1, 0x0, 0x0, &(0x7f0000000400), 0x4, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000000)=[{0x1d}, {0x81}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000100)=ANY=[])


syz_emit_ethernet(0x3e, &(0x7f0000000040)=ANY=[@ANYBLOB="fd9339c0fa4d5fd01f461c930800450000300020000000019078e08400010000000005009078e0000001450000000000000000000000ffffffffac1400aa3486fd68c8e9f95a874fe7638712c2fe202e852aafcbbff7216e3df2ecdd5a7ecaaeb278ee7b1b7f55f10ae8d88950644b"])
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b100050460000000000000000010000000000000cea10500fef900000000d3357ae320b37b673039d2d236073705ae04be38164991f7c8cf5f882b297be1aa5b236deb51e2f0ac7ebbc257699a5f139b672f4d335d223e7d026ba8af630037282102000000720fd38bfbb770c1f5a872c881ea6e69e0bb7600000000000200361b1257aea8c5000020020000000000008abfba0900000008e371a3f8343712051eadb71d89e000040781e4b2c0", 0xad, 0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b100050400000400000000000700", 0xe, 0x0, 0x0, 0x0)
r0 = socket(0x11, 0x3, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
sendto$unix(r0, &(0x7f0000000000)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)


r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x6}, {0x2, 0x0, 0x0, 0x40804}]})
ioctl$DIOCMAP(0xffffffffffffffff, 0xc0106477, &(0x7f00000000c0)={0x0, r0})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


pipe(&(0x7f0000001440)={<r0=>0xffffffffffffffff})
writev(0xffffffffffffffff, &(0x7f0000000000)=[{&(0x7f0000000700)}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x2, 0x2, 0x0)
connect$unix(r1, &(0x7f0000000000), 0x10)
dup2(r0, r1)


r0 = dup2(0xffffffffffffffff, 0xffffffffffffffff)
poll(&(0x7f0000000080)=[{0xffffffffffffffff, 0xab6cc3d7ffaa0897}], 0x1, 0x0)
sysctl$vm(&(0x7f00000011c0)={0x2, 0x5}, 0x2, 0x0, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r0, 0x80085761, &(0x7f0000000000)={0x1, 0x9})
poll(&(0x7f00000000c0)=[{}, {r0}], 0x2, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
syz_emit_ethernet(0x4a, &(0x7f00000000c0)=ANY=[])
mknodat(r0, &(0x7f0000000080)='./file0\x00', 0x1, 0x0)
select(0x40, &(0x7f0000000040)={0xffffffffffffffff, 0x0, 0x3}, 0x0, 0x0, 0x0)
socket(0x2, 0x3, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x18, 0x1, 0x0)
setsockopt(r2, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


socket(0x13, 0x3, 0x0)
r0 = open(&(0x7f0000000080)='./file0\x00', 0x100, 0x80)
sysctl$machdep(&(0x7f0000000080)={0x7, 0x10}, 0x2, 0x0, 0x0, &(0x7f0000000200), 0x0)
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x1)
r2 = socket(0x2, 0x1, 0x0)
r3 = dup2(r2, r2)
shutdown(r3, 0x1)
sendto(r2, 0x0, 0x0, 0x404, 0x0, 0x0)
writev(r1, &(0x7f0000001480)=[{&(0x7f0000000100)="cc60d3d79a1a7122a5fb9de9ea6ca0b30fb2942ef7652736f10f86d45ae419b2ecf7af93d33b3de1f2c56c0d93da7484095d0d543baf7f0161a025c9c02a561f9a76d06f1eaec7d8df99d6c28b10fa891e47d6c3bba690a611889032ac7b3581d7c92d1c546e59764f069048316871794f0615dd4d8bb1057a61fb177be649004fb56a7d46c856a20d73f050bf29d58b803a676cc3761e8a47857f51d90a4465f9c605ab2829d78ea2571900", 0xac}, {&(0x7f0000000080)="b389e5ae", 0x4}, {&(0x7f0000000200)}, {&(0x7f0000000240)="2a5f4cd9b73c31d629e8d68e605e5940744ef138960b671d42c56f79fcb70549247e5504e02f85a6099eff9291731e94399a7e966e783d4073ecd5dc8e540f32190bb47050aee3907495ecf7708d1c295a0836f79ba03ea13db12836c2441989726ffbf7fd1da55bfe2caaf081a1ef55599935c0e60cb0866ee48d420b77a6e269bc30b2650349e16792252c6be8bcc6e9ce2b941299ab505e4779fa1960bb7cf924dcbc53c82e76bcd80731a694d12e8a139d8ecef6f5560939054b7842d25cd7396377f39bcfe2a2383feea17b87393cd892b90742631718b1877d8d83d5f66587e3e5b1e129433ead750143a4c51aa46e78e3b1a54a4634eea2846511719b1637b19ea8c96a95332abd69014f53e91a7319a36efb4052387dc6330aa00b5680142650e8dab5eb6b83ff7d0bbf1293338a8d3e8a6dcd7ed4916279eac230dda46e6fcdebe8a4c12d598883d9392da05791e153d905ce1930aebfc5dfc0fc22a88777c9fbc24c0b021189c3503466bf850f59e6649dd0b40d935ba155a9d7e065df6d90a500be9d7e1e77607d495898a8d6c9c48dda88533e75e760dceae91d670f97ebbe68b845c72eb698a9e0389b15cfe768cd4e524dbe939bc2d8363ae3b71a454a0a0378cd1f36565ab9d1b92263688195df65151ee9b8158c7a5280019a38f00ea05142b3cc832ece46e326e36a55d7a30f866ca97da61a3877612f0d9f23c052edf60a430d3a9acbae3d9f14f22f38a1eeac7df37ae17748a960b9e0d265bf6cdec73bd2a7b5f25035d845d936936cbfe6f013f8d7c73eba2bd9876ff6db3224e50e75c051979f4cdc41d28ea54e28f560fb0291cd6b6ba527e0f358ffa46b988f0bdbf801063d2024380071709ac00ed463e08fd1718a857b567d8b3eda143915e943d9530d25ed15743e117be375dc08e241328a53fa05b58c7c72a35d471a72706afce82b6c57eef81444269e06338bfd0af6f6ef6479dcc26aab0b10c7e58572aa507a69831d63c78c947cecda2c57bb8ae6b2ad7862d160b423de941be69928467db10ee4817536196ad0c5cc02a74ba1a1fb467e472f025f200846112b6b3efd298284d8c0cc498fb9203db18e48e34c137d1285120d809a774d56a62b3dbe8f202cb9cf18c33099f5b9651fc7ae41de53842f327fd40bcfaa601a791da1103351a64cc9815ff1f32cde6fbfe4c92f55a9aff41c055d4edce9c656ecd1becb9035bb8bd46cf47bca0dcb1848da94d05d1475c83a48c02f8f808597eaa9e88a4e4b12d0ef95458eeab115cb189fa7e368186bb68610af4651e27feab061c4ada46e8c12d6d33fe32cd40485b02120418a9aaba8f04c17ea1abdcb9e6801f5d8090c0780b3b5ae4382efbb64f62c825527b7e3d60ad9c73ba7f174ea7c7f2d155808052a0ef6ab2af85cf9a758a8c1227c85f2986fc06c5f54807968b18b6b5f9168d0b2de2728689d75f0efaedf79bd8bbbbc1d46b0f6072d46d46687bc92c0b16c4ad36c3fe4c7a2fde0cfec859052dd78d841464a6b4432342ea973bf18f1f5abd7b2fe7962faef39ff38bd88a40dbab0f8c08541e38efe924f9ec1addbd47362e349bfca42fd62cf18fef8db7d3cbf0b1733d37dcdae5b9c738b8426a1cfa205c9671870210508c614f256d199fb822613518b1a6fccfee08c48f0feae1ca4baaf0a02635282d4f630a8df115dc73e72d9f7b8feb4333b2c796f1d3f2cfb398ba1e9c81584185b8b578bac3c64d667da7d91062f0c2ccec0c9d09e0c15c62e7bc509c3204d054c22d4eac685626e48e25cff2fc382279d9cb941c2ca182b1f65b05ff05db880a37b1e7f9b3d8975558858352bbbea9213a885b7d43451230e0624403baa77839baa33ae92de771ca76319c2353e9f98ea8191fbb686aed6d08e87bcc2bb8084ae02fafbac1a0bba93f0f155fa2d7bc21bf77f116429c6a1373c34d080518b73481fcf012c0a9127e8f174695ccd4add75b026bf2935990d5cebc4e74b97ae67a414029252336880232635fce7ed7bf0b069e08e10f7e1cc4d2973dcd2ea0b63f9dc4f4c2db92e03c553afcb1060b12f6b9b4d1d799edceefdfafdae63ad797e400645c149b20f8a10af54db3289441499e122413495c7b32179ab6c274bbdf6dde48ce26f46f07ede9a314c1a73669ee8cb0d854c8a3206dcd4f532d36fa7affca1226962e20ca2c6ca0da1ab0848d23d6f198681911592815c080cead9fe6c81cf0d7ce3578978dbf1dc2f1902e51f740f95b02ebff4cf25ac8d28b8e16998f5e329e9a377a82b5bc227f77c2f1ad505286aac8618799c2363a2d07d229519370be62ef0dde6525df45a7b807759b9ba1c8557bdbecb429432c4e1a84094edda567f1245ba887686342d0a31b7dbe09bd2be75516b255d2bfad9337649e86a29b0a19e16b4059c7c45e9f81db6780af6487a11f9088ea265a99d6e95535e14fe839945f8f7da9bf9142dd12c305bd41bb392cae8eb81b28fda176d4b538f4ddaaed47913cd9149d934ca36879718bbd76a2d7ce11e6294398ea433af6cf53b951974ec96a9527178b6cbad3088a2e2dc75113fa88ede462e68b4d6b63020a45e94fbc6c3e6677d6cffee0e3bf606cd2d4b9fac89f91db8f3a1fb9f506708314249fa5c36912e3cb281acbdec3b080735ae24ebb4bca3c7900c21175435afbe5024a706e90f8ecf257c99cd8b67b5a9c2bdc2bb624201f55882349526f8faf463eecb183635db72a6aef5fa2048d97e6f6c513598f49158050df1efc6b13b8ae396cd6a905c26b94d1d50d361f10c0362a8c206c7dd553dd8b116694aa82ac029c64aa71b8a307793da12f93ce030d3c42443c37b91043687befb7968da97ffe91d45e4fd506ba4d9c5d7fe5ac7433fb6bb3ce471f59ade734d109d2093fa119827b65a360f2128e7e85ab494609b60d6e236ed8a72984f6c75652f5baa07e2e921365af2b819eef58343e65ffb45ba8580d62f5b8a9988f7176c1559f8ede3b1b92e0ff27978fc5225ed1512b605f1fd4fce46e768970b11a7b4802c93eb05a8571887cdc15f69929eadcd1f9d08ed2d6aab2997ffa2102c2d8983a78ad43779d03aa612ecbbdde634b14e980b176f04f99efad82a04001f34d6addb89e0ce629856f5ad401fed1a2c046e1fe18741b24d4253830af94a1defeecdf6f70b430e48d7b2e4ae2fb331322d96e1a361e4dcae1d0865e7ccc4aa58bcbb3ad1ce0b294437887e03088a6bb4c92c3044bb33d2a893975023ad979fb2f84d4842326cf058595398779116245c452e54989df0591238af63c5b187d18457f008f2759ae470282ee4640e92639a46915fb67f22967beb1f46736aa9c90df08f39ee481f6859f9eafdecd473bdc24ef3ad71b4c54dde360f2d550db18af7589c8107f29b0a713b65f039da10c2dc55e408ce75c77aba97c116ab078ed1467464fe4041668228316f0fff7c0e0f1a3cc47aae570182197cc3a030a4af7fe2d401b5a13d59b8fe55d48b0667b782cbf1c2e9e491167d87830bb25008aff93c4459a3ce9fd8655a542c6311d91ec6b6bd7935aba1cd01d10439f5e5a3883566c8538edb97c5d2a7c7533d415973729f52dc03134f3d777b7ad07c0f5b0d985ca48fde6cce9ec99f1223f476dcfbb5ef865a3f54459415b25e2031eeb469c83ac68fd77e59c6b6a4b9543a943c4461e47e94d038c63abf2734a3c0e99b95505e13af6cf7b66840dc60e96fb218436ea00b4a577c2effdba43e6adf97cb47c0ce606e87a7834dec04396c1e4f7df59ae5acedfd1d68c87e405fc5d788884686270cb08f0fb15fe8b11589792f9afc11152cd45f43fac6e758588cfaa88874267c3096bd689108bbb0296f3d182df7d46cf7e6b8bb923ba887443c3d2211785e364c1e55d4e9396d950e50cc11ba9a4da70a64f6acbbcd421183eb2c0521054c4f39650409e21a9d3b781725b0c38abce7b4615fa64a9cbf71a19f7e414279a7494d2e66e4e2b2d5ce7027109cfc763a9dcac37065ae80ec0cf3962deec0f9eba3bd7c514a9854ddec6542cf60a1e69cf5d1a73239633675d4ac1f3b0758e69d1d9fb8659f43f07ef6b0b2a7c9740649198b44f3272a8810d374b00c1d49b7f667ed538d89e91e5734f8d6e270aef0a406fcb4072497dd5f25b49d31cfd64f7af2d5b4df72b74c39a66f442ae61aebe1cdb96b660e3248dad3d05bfce3d8630902a565c3a7636220e0435679ce1c45367570dd08722ddfe7f1bf56c44bcab8ef2d0979eeaa569dade4ec34751833d455b31b55edcb9b64f3045725fcd3a08ce0c20b09a437133df5738092eba91430208814b4135b0a64331aff1847ca60426c91e96a029cff039b14462da6e5f9c545980b3712f7fa5f3958d92278194cf6b37ef76e91103d14db403956a7070d87afa81df227f2189926e1265a2872e9d64c64496083caff36dd3c27e961957acb86f0f9a3cbb5ddbb6bf9c62dc102d70d62eea969b1c2c5f42823f76827e918ffa77cc12ca8d31effd0b55529c496da762b6a95d43360ea4e811979ee316e143733f886a6eca5ac76746d4a302ec57b6b4af57c25631d7773243abd400d15274703154dfde2f1a63e075e4b22ed4516dd1496e3f7848bbf19e3215edda64140649d9b1a06975773d5dd0ca9c4bdfd5eb9fb6164aa659e2a8415098dd05496d0b2a20d966a4c9efefa964e007a3b731d3bad501fd21ca564c6155d893c3075c234af6378a12595d8a88ae0518350b75d57fb91b7610bfc3168f548a9a63432b49a9dbee2ee1a4ddd80255e2c655cc80d59d7e90e21fb090db6d59ef84c0becfda6bd01c5a806ce67bea77fdba62ba40e2114d31e6087ad67b28adc20d7cabe7911aa2db119cf5f43b2011bb92556e8e303a264f813764027fbec36f8248a667c766cfc12c80d96965f222d39b5f58a54b255d3b1eb4530952b6d251ff1f9a2cbc585d539704c8ea6884699ebc95d57cd1daef169da86cc10fe7300352e939c35bbe3104aea1b1c681f3e98be8fad7c91bb56724ffa794ea4ac7c4d51d4aad8e94087b4cdcab897e70558e6648ab42dfadab447735912af011fdbd9a47a4958b953b01d2e274449854cb7d4b44d88fb2db162b8dd664c7c32858c7714c69b838cb30b17e6a42ca760256c4c6da57ad5be955ca8c787262d8bd3f4a5f0170e70f92ee2ec9d227d066e41d0d4b640166b2f6937a66bc84506d102d3edac818b246954ba200a3057820da10b64ff99f016b42d90a29b43290d731ef23a72612d646f92acc05620068fd94edd12902197733cc9dbb55d95930ccc749c4a169b4b7056dba24f767da022eb01243353e1f4d0af2eb32e3feb331283ceab3e0112b37556749a701d11ada5cbe1b4c829fac46e12612679e47d4a066be939b886f0fdc2b4c5b4dd183ca025c5191ac67d7f992643333504da30e8300a0b40152671", 0xf12}], 0x4)
openat$bpf(0xffffffffffffff9c, 0x0, 0x2, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000580)={0x0, 0x0})
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, 0x0)
r4 = socket(0x18, 0x3, 0x0)
setsockopt(r4, 0x4, 0x0, &(0x7f0000000040), 0x0)
close(r4)
getsockname$inet(0xffffffffffffffff, &(0x7f00000000c0), &(0x7f0000000000)=0xc)
r5 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$VNDIOCCLR(r5, 0x80384601, &(0x7f0000000040)={&(0x7f0000000180)='./file0\x00', 0x4, &(0x7f00000001c0)='./file0\x00', 0x8})


open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r0 = socket(0x2, 0x1, 0x0)
r1 = dup(r0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
r3 = socket(0x2, 0x4001, 0x0)
r4 = dup(r3)
r5 = fcntl$dupfd(r4, 0x2, 0xffffffffffffffff)
close(r5)
r6 = socket(0x2, 0x2, 0x0)
connect$inet(r6, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r5, 0xffff, 0x1023, &(0x7f0000000040), 0x4)
shutdown(r6, 0x0)
shutdown(r2, 0x1)


syz_emit_ethernet(0x56, &(0x7f0000000080)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaaaabb86dd605682f90020000000000000000000b3ab1ec43b427bf600ff02000000000000000000000000000145000000b1"])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000280)={0x3, &(0x7f0000000200)=[{0x45}, {0x1c}, {0x8006}]})
syz_emit_ethernet(0x1db, &(0x7f00000007c0)=ANY=[])


setuid(0xffffffffffffffff)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0x31, 0x0, 0x0)


r0 = syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047460, &(0x7f00000000c0)=0x3)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x0, 0x7, 0x0, 0x0, "bd1331844e5b401532158b01004d9c602691cdcf"})
write(r0, &(0x7f0000000240)="f561325db04cafa4512e5736e365ec83b3cafe082b7b4436cd4c057f8ba5b08a4c719ec710b568ae0f7befd0ed09", 0x2e)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f000002f000/0xd000)=nil}, {&(0x7f0000060000/0x2000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000ffb000/0x4000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000053000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
mknod(0x0, 0x0, 0x0)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f00000000c0)={&(0x7f0000000000)='./file0\x00', 0x4, 0x0})


r0 = getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r0})
pipe(&(0x7f00000001c0)={<r1=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r1, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r2 = fcntl$getown(r1, 0x5)
ktrace(0x0, 0xe53a055dd4cd665d, 0xa24, r2)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x3, 0x0)
setsockopt(r0, 0x0, 0x2, &(0x7f0000000000)="834e005f", 0x4)


socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000002c0)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000040)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000100)=0xc)
writev(0xffffffffffffffff, &(0x7f00000002c0)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe2c63a56077123a276d3ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
fchownat(0xffffffffffffff9c, &(0x7f00000000c0)='.\x00', 0x0, r1, 0x0)


open$dir(0x0, 0x0, 0x0)
poll(&(0x7f0000001300)=[{}, {}], 0x2, 0x87e)
r0 = open(&(0x7f0000001440)='./file0\x00', 0x615, 0x0)
poll(&(0x7f0000000000)=[{}], 0x1, 0x8001)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x10, r0, 0x0)
socket(0x0, 0x0, 0x0)
ftruncate(r0, 0x25b3)
execve(0x0, 0x0, 0x0)


setegid(0xffffffffffffffff)
setegid(0x0)
mknod$loop(&(0x7f0000000080)='./file0\x00', 0x6000, 0x1)
lchown(0x0, 0x0, 0x0)
accept$unix(0xffffffffffffffff, &(0x7f0000000100)=@abs, &(0x7f0000000140)=0x8)
rename(&(0x7f0000000180)='./file0\x00', &(0x7f00000001c0)='./file0\x00')
r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000200), 0x1, 0x0)
ioctl$PCIOCREAD(r0, 0xc0107002, &(0x7f0000000240))
mlock(&(0x7f0000ffb000/0x2000)=nil, 0x2000)
shmdt(0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001ac0)={&(0x7f0000000500)=@file={0x1, './file0\x00'}, 0xa, 0x0, 0x0, 0x0, 0x0, 0x2}, 0x0)
openat$vmm(0xffffffffffffff9c, &(0x7f0000001b00), 0x0, 0x0)
socket(0x10, 0x6, 0x4)
connect$unix(0xffffffffffffffff, &(0x7f0000001b40)=@file={0x0, './file0/file0\x00'}, 0x10)
sendmmsg(0xffffffffffffffff, &(0x7f0000003080)={&(0x7f0000003040)={&(0x7f0000001b80)=@in={0x2, 0x2}, 0xc, &(0x7f0000002f40)=[{0x0}, {&(0x7f0000001e00)="14aa6a94d7c1e62517e89b2e4f4ff2b744701590f1d5177f4a60ebb7b72c4d9531ce58ffa597a505a674dc91a4316d97902d709b63d81d55cc4ebe8ee2792bd1eb3f8a72a2a0", 0x46}, {&(0x7f0000001e80)="b169682e54c477ff3c8843b856ecc5bdfda5579493b7303f468665c8e0b258ede6a73b43d1b0642e28748c9da6e84130b68113f905eb377fe1a8c395136808562039b6e45374cc2b0a389975c229e0edb90ec79186faecb4d66cb4f649f88c4b2b3f2c22436fb47c5f53c4caada0949a10dbd4b3109dcaebfdedcf56c7ebd0afb43dbc942ca0377d240edaf01fe2ed54a7e34cc2a6d5508ed662de423354ffa8fd4447b78e9c3e4ee2ba105290662b7c3421cf8b228d034703b053946f12646fe31454f88d634176ccdffad3d4f86a9a89445126185bbe385769d2d6048685285c39a8324c31497e217dea54f5dd020300cce4dc06e8a7a51d152ea9a9cce0366a9eafbf84fd99721a3e70bb51821387e3cb7f224a8374d50c81f0e36cd673b3c3805ef28b6938711a51d513894b5f56500e8ef51c222a6264ef8ec5aaf615a0909bc79278511f78511e54017aa21b1947e29f15a867bc8426e8dfaf1576fd530e669c950aab718f9f556b84303e93809a5fcac21ec13d3aed1636e9252546b8ffbab5755f646df8969a2ebef1e36acc86261bf80ef5336a181183114825be9357f6509444104e67a2944afc693681c1a6ea84624dbeda615a00dd030a9f34d7d4bd08a5de8c2155e025a0a229675dc058e61ca789dd93a0ed7dec2e67fbcddc6414c9928e5b8c81897f9be6c9d5b5792ff49c2bee6c44886e8177603756544bc074e672227e95fac5bcc04efa983aa46584e8c469ef917033016488a4ecb162d6d582c393601366ab23003a44588d2be0111590c0e468de09bf577b8765dc0488bea51f238cbd8e3b82455a146984f819bc6cb3d102c3c218135cc66d01f8cd83af10f3d91f67f90c6aa1359bda33fbf865fa304d3bebb716041e4c36892b7927d6a29b7283f065ae7ab4ddd26656fc3912b3ba6096e44ea0592f4226f93a8a063c0a6e6cda203ea3b286463a291278a11f87d68f30c525d4568a94f4f682ac01d30dc7d1023b3ab41ecb8ba39f3a44b3a9701842a8781e42b07c688ef91611fd157b4948c15bb8aec76e0b10545074bfb0d67068dfea62e367c2cf3bc97db3be76ab2bc72dbb26437fd308c763d3886d90ff09ff25c699ab18502f615f081eb8b97c7628ab665e502dd439810e873ba627fb9b1f51986bd07dfa04c1c980e964894362c10a62895bf4144c598a69ddd06c9aac07ca32dba4692bee27f59fef97c87bf0b06b74de0089cead498088dc9803d25b774ef5747afd4e0e0c0f8ef77b5758869985ac0509eb17a79796e07c88b6cbbebd9de555553d3f5ed3e707e69701a52b0c7f0e356df55aaae54213826ca551b3d6295e472682629cbc387c21df3eb4928200c0647b3fdbbbd288761d0bcb952c880f3c2951eb08f0b0e95739fe681ed07dafa00eb8716e6e4bf8c69d38190d8a3e7c2b73ca32d9b631cfe7a86a10451a81b7478cf62e632b05bc8a249d42d9f8e9a28e15272082dea8fb3aa8467535de95207aa6bf4bbb7997be1f6105d5610654bc4b53db3d5b3c354eeaeb4f70ba8af7abd322ea6c64c3da7743afdd01b432cf0693d10ad3554ba3add52952b7debd2b9dc5f79764b8268662990474808de5df41dca8df6511729afae35fb11bc665bb8bb4a0987a389266993a6f0891e7196a0163b6c561679e0d749a683b2ed5ef4b7b2b21d79a9853c858e020a303b4772ed0422748cabcc8abde1097317d992bd23d226bb1c8b7fd76f0337586da6e02cd6db8d669998b1144fe029ef3ae6608af7974eba305c8da5707e5914cb2237e6661fe4168e8b395688582ccd942877a645fbace26507813df434889c7f2e6d54b47dc1be380c2582287698bf8ab0aabfb25dc4333f2ac257ee240ed51b68e77860e3fbc563cb34a73aed01c76811eaac7af74fa1a4a496c9085c3aa9c25e1226ae10db68aac3b9f8c582a0226892c7c5f8a2cd650dedc1cae763642b951c0dee2f2377010e89419858f8051bdf0f7b59045a02cd5b49f938121368987adb6e5b753f6851e927ff95ce7839ef84cf3a824cc8bbfaad9aec02976526bd4d6dbddb97d56d08b0289bf49674878e91ef464e2a3af42b01777064934baa89a04d81079c8b19d6800d6c30d04e8aeccdf6008877a72c2c2804023a7257b8a54bf6c24a595ceca28e2649cc25eee7d92f1de2ffe75966b36c39298d87b07ee712bf55ea3c3a7e15188ed354c5c6427c77c8468d60cac575abe3c95e098a475568dd793ba384e2d2f3ce35d0fd51c3f556f860b27271df82dc5aafe42394b0836840b5c26f3233e2cf3007a3b782e2ebae24063d9b16e03e5eed8415c177cc844ff82161eee9f53f7d2bd8418e91e7cb8ef3056ff5d98f7bccc612bd8a4f086271ff64b71dc997c6a31f0d4e26c0d85fa4238ae918a75e1f182565970a097619fad7ec2aeb79d9593ff25516dfea0a422b393067b7f75ee3544291022e26bbcf87604d3a6be4b8fa8c28912012c946cc36169939c2e694a18a0923d5d4773f140b3f9ca0aeb303723291f4e98428db6b82aaeb89fd1b7a565c0362cf4a27f918047680c00409cde35f38c3e77e812396b0b57c89cc62e59a90886632680d1eb01367e51d68ee315f0e6cf8193e3369823bd96870c2f23f133f8163b64f46669f278eded6c256885e0e15a1284c505254abdff70bbe0c2498fa507e0be8402f520a1b78baab5cd5184a846fac8c6a275734fab7d3bfb31d346a3f83b6759d670334666b6643e1aef336f16d5d9a8c1670745c9befae6d7b3c6b39e8159a516aaaadb64a38f9e41ff8e2d22e3b19ba2bdeacc29de4cdb8dee746f1cd3c7a44159f6e29176f9b2ef85d6c95dae9fa23429adf02c941946eb214347550b3437b61c1a7a4721e693b487dc979aee24e0e66c3d335c1d9795aadb11d1e949c4eaad628c93086735f6a242a8ee807f933d1a68b075ab4bafaf834df5adf9d5733191ad3d441cd1904d6497597fcc93680e2f9dcb613f05cb4951a596310a77a60e6d8b5790e13c1cdaf94cd49794d89a5372f95ad0a8ec6303909f49737a338e8cb47751401ca33362c113d27cdb543c23abc971a40a8d97570c270fc13d27936d3bf9024be265b58928610f2900071083982cdfba518edd813748b5de6e580f25b0f7ec13a1f0b11d2403a7c62ddafa88d3d18ceb3e3d55fea226ed666e7efa2e63e7bd6ce248ccec2f85c031f335bce621fa48263891d391a9ac5238f5355390295b49a43b9e71b2c35653341b387742bcb05e5228d8ab5c74a50a32f10b8ebb42861abbf60bd4352b3ddb36225747648fcf151f9a83e7abe4d786d1fea262fff913dfb449520afb3e2c0f7fbffa01089d550ea7d7b8fff9987c37ebbc29dbdbff6f51c42c49f0fc8174ceb67fa2ba34c526b60548810ed37f5f0d0ac4897b19e5f340c3dda92c00e2c692d5b2f11ba1c61f82a809b86962bb6a1c58df01d40d0fad00eff6e01c7a6dfd0edf42d00aca055fb699d2ee94d97a5c59266565fc77ec8aa5cda8beb34607172a0ff0f31d154afbb5eb835dd07367b4a9aea7ec5efc7df4734476e9f3224f26ce346136449ca3d63668ea1d43febf7529b96c5a8e93565440afdd9dcfee81dd1b680dcfde14f730a01262368448668909f1b575dd8eec678cc2f6b876ed5c02d22c15a3a631792d52449a42e761239facf70aeafc89be86b2a7959336d631baa1e4809e459729a6030b496299f61c8273658bf431b724b7cf55c9be4bb3817414d2dae109c1483da3aee1c3df9bd79246b8ff438d679651b9be6d7d77b015274d8d8a58c696819568ec0e8d58b04dd7738baa2522ac4e04649e799906cef914eae8ec481003abda0f3ff5c2296d20032e1856e9df77565def98d5eec88e264ef4eeffffb86e71475b4eb90cc243e5508ba4437e80d18c9b3cd18eb7c0928739308402e30f0ac6ef997dd10e4000495ee80b5bf4a48096a62218cda0a66c5fcf9f29c07dde27bf360f923dbb1e063636bb89c11df48e0ce34342021353a94c0d5037cbaffdb1607952cb004bb618134a6940ab0fd109183699348c662f16e7e4d0a02dc6d11d8307adeb386925e08383f3961ad32e6ef2724b3faaba155c4c6fb68f9d0236ee67830af82d741bc0598ba606dd699c4c4763f999bab5f90ad9b3c9691047a81d37ac71544154295c879cf94c30ed58c0aa614ab13f198897dc5d573385ac2dc0025dac3b5779939e4b3100a711c7241073fd9f3b89e6bfabe1efbaadba101da49d0c623719e3c248ed3359b8787a189d62b10b39f7e60ca40977263d955e1f46f10f44458af8197cfda3921086d7f01eb7c6de8f5eed89adfd583d2adc65bfaadf4c3ff407627a21c8b9f5048fbdf4cbb26504b851f101251e6046ac7ddf323f89c2cec7a0d387ba5df5bcf7242aac7ba6d3bdc9b4f46d063fe27eca77f0ac75e04f9e8451cf64ee8b109d3cfbbb5a2872c4b68a880857a7bd9eeb0166f8e8259f9384ad752e037be555616c057b912355f34601b1a46177c32cb8bba9839a157999a793dca1171da986aad3530cd166a3e95306e7772b5a17288079eb76848167ae6c9414d80fa51a4fc3e227b7635278d1b275faa32d14125f03da881b896c4d16ab80ff6881973d28a7baf14878b3f657cacfb59193d86f3bc1e4113e119a33ca9e1ac650965a7c7d03d163b80b6e4b55aebddf90c61291e88b7f5897db9cf9c606d451875ba9b12c709413bcdd1507cee415e2d0f0a070bca8f403482b66130db3bdc41334e676aa05892bfdb0bedac5935d7e60650ff48e7abfda3334726a3f508fd7f5f4b76527eddabf1c70421b03686c24f83cc4be2b3a5ebad9e21a5f8256f445a60f8edd7928ad1e5b86f509e3d687c1c8d84f89358d2d1c032df19da8be464c68bd75c22c6c63cb7b8db34c13cd34f90bb7ff017a26d7992529546d50d48c700d57aedd0abf9b4d19e577f3b2ed164e29345b15d0df60e55ea5cbd583cae0ea156486a0b966e0442567d0cf46af6636f8735b4a0691b8029965af5f67ab0b24deed1b746987f1d169ffbbfb7e7bdd334fe872b7d3b0897d91790dcbf7910637722e1144918f9c467ca74e99980190ba11323c986cd92ba530607b216a05fef8a518ddd3ca75206f1ce68d171e46aaa4d0b73e5e9de79be84b44a2ce1e0a1d5597dd63b2879f0196cb52eb3849ceae7d61a3f20fa352ca407ec6508e5bf76fcf9e19047db42fc91baea4947f633aa7e547cc2def2425a58c509a10b7d7aa765b49833645452db157c87ed3c55b71733ab96efd5741f7e45377f06e02eb971f035efa430f9fb72193f44e9b1824da5c94c7b4154cc90b2593353f840a785f624551a51ab1773ce4dc7682fbbf1b847b854c8d27b258740f64de3be06a77d98b074e151de1f4d9e5c4d3000898b36e93834f380544f5e2736756ea666968128fb542f502c27ab6d840e1e3f1df7e6d8ba964874171486c18b8d0e9f564451901f93ca870644027cb731de457d2eb39ba8f8c7d881894ae865f81b71958b6390dfb3b2a33bc616e4b53f4b98ff87ddce9ae1caa6e4b3e06f89871674bb23f1d2036d80a551e7f3766861d93ce1e7370da3fbf3f8ac025a833124714b7a23221febb1a2e43d8f4ae50a33d0f75d64b3528d7c05878c4bf0407e58c3ae81215ea49692f70d425451bb600c4ba0c716b57bc174022b86e4afd71fa760ead1d6f182003a356928e75762a811a2b4867e100202b1ea12f503ea458e709681fa37e62d0e442c14f541fbc408af29287f437abd397bf4d179707cc730aed286d596d", 0x1000}, {&(0x7f0000002e80)="dafe160f04902f8c4ccddd18577f61b9ea9d0ad2a1db9b37e5acb975aa5f57a10eeb27fad728b03e1fa0b93c14ab4ff96c97f277f6f82964d8cc44be7ef75e997da8f1f1a08680ef5e3db298d4936c5ce3ade2076debecdccd0285878a83135cdc2dee00dadb4d7540bf01e4b3cfd8316915a3c1f8aadc97e799b4382471697f589d12543646184ff8d52cd6", 0x8c}], 0x4, &(0x7f0000002fc0)}}, 0x10, 0x0)
mlock(&(0x7f0000ffb000/0x3000)=nil, 0x3000)
ioctl$PCIOCGETROM(0xffffffffffffffff, 0xc0107005, 0x0)
ioctl$VT_GETACTIVE(0xffffffffffffffff, 0x40047607, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
close(r0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000a, &(0x7f0000000040)='\x00', 0x1)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000400), 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000200)={0x3, &(0x7f0000000700)=[{0x3}, {0x28}, {0x6, 0x0, 0x0, 0xfffffffe}]})
write(r0, &(0x7f0000000540)="76e5dead6f01f8607d2100000063", 0xe)


open$dir(&(0x7f0000000040)='./file0\x00', 0xae828e137847f62, 0x0)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x1, 0x0, 0x5)
bind(r0, &(0x7f0000000000), 0x10)
dup(r0)
r1 = socket(0x2, 0x1, 0x0)
connect$unix(r1, &(0x7f0000000000), 0x10)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x112, 0x0)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0xe8}})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x800000018, 0x1, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f0000000440)={&(0x7f00000000c0)={0x0, 0xffffffffffffffe3, &(0x7f0000000580), 0x0, 0x0}}, 0x10, 0x0, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = socket(0x800000018, 0x1, 0x0)
ioctl$PCIOCGETROM(0xffffffffffffffff, 0xc0107005, &(0x7f0000000080)={{}, 0x0, &(0x7f00000001c0)})
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x800008, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000004c0), 0x2, 0x0)
writev(r0, &(0x7f0000002100)=[{&(0x7f0000000700)="9b9b6d4c", 0x4}, {&(0x7f0000001100)="968ce1c69d9498126527e1ad5174636898ad874ffb39b42f574f4f4cbc90acc1eb117d7e3bf3d52de5d57a7f2ec5c0d23a134ee65c5f70eee9f43f9c71342063cfdf9eb60982d3ed95722aa70920bd1c6331d3e4e1891e80699e9058b7a39ae56ffa1c545b3dfa90cd36699a984bdaedff8dbf3d11d74e26036a7fc36b1f53740b772d7c7996271e18c83078e8d21903e3b374f634d48cd37e5d788d9dc9b1a5fdc4094f0307931dc693d646727c74325a288835bf83c9029b4f9fbc275c8ed723a954b542d3ac1e03143f3b9b9dfc4ba58695c2b8fc369391f84321f6922d19ff52774d77e9fa5da31ec4180e68a9ac2a24b4788e0d54cc485b1bc332349f35a212a64747978dfee5e025493fbcfd60f1aab1f6085ab1c461eb816699c3fc078d367ab0fd6a2c1afde3f1fd1071d5e7856e8c6f726efd37d9e615dbc457767041b51b63a5af8fbfa98b1bde28dbcfa9d698abb946f831ef786761b64412992b6242449fbe6ba627d64dbe611cca8bf596032a8383c693e0fd9da49f09d66b03f266190082f44d73", 0x188}], 0x2)
writev(r0, &(0x7f0000000100)=[{&(0x7f0000000140)="f546", 0x2}], 0x1)
execve(0x0, 0x0, 0x0)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x7})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000006, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0xc2, &(0x7f0000000480)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa86dd60000000008c0000fe350e28ef0900c08cfe24be00000000ff020000000000000000000000000001"])
r0 = socket(0x2, 0x1, 0x0)
listen(r0, 0x0)


open(0x0, 0x0, 0x0)
getppid()
setreuid(0xee00, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
setregid(0x0, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000424, r0)
setreuid(0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000000029, 0xc, &(0x7f0000000000)="ffdaf64c000000004f0527000000050000000000", 0x14)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f00000001c0)="24a5b03a7cf812d1", 0x8}], 0x1)
sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x13}, 0x4, 0x0, 0x0, &(0x7f00000001c0)="00020000000a", 0xfe93)
sysctl$net_inet_esp(&(0x7f0000000040)={0x4, 0x1e, 0x2, 0x1}, 0x4000000000000006, 0x0, 0x0, 0x0, 0x0)


shmctl$IPC_SET(0x0, 0x1, &(0x7f0000000000)={{0x0, 0xffffffffffffffff, 0xffffffffffffffff}, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2})
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x33}, 0x5, 0x0, 0x0, &(0x7f0000000000), 0x2e)


execve(0x0, &(0x7f0000000000)=[&(0x7f0000000100)='//\x00'], 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
chroot(&(0x7f0000000100)='./file0/file0\x00')
mkdir(&(0x7f0000000100)='./file0\x00', 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x5900)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
select(0x40, &(0x7f0000000080)={0xffffffffffffffff}, 0x0, 0x0, 0x0)
select(0x40, &(0x7f0000000040)={0x7fffffffffffffff}, 0x0, 0x0, 0x0)


mkdir(&(0x7f0000000180)='./file0\x00', 0x40)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
rename(&(0x7f0000000240)='./file1\x00', &(0x7f0000000200)='./file1\x00')
connect$unix(0xffffffffffffffff, &(0x7f00000001c0)=@abs={0x0, 0x0, 0x2}, 0x8)
sysctl$ddb(&(0x7f0000000000)={0x9, 0x5}, 0x2, &(0x7f00000002c0)="b151efd9ec9b99ce872e665d84241a5d2a4e39ba4a08d1bf87cccd2140583a0309001556c5561af91e1ee1ab99a2a20048472e6ea9041e8d9b0000103b2656be0b83e6bef50a085d22bd29ef0c0cf6a2cb4a0a4101060fc2091b6db2b007f42ac6888d87dbcd66b3604f7ebfcfd1d6cdb18ef112db4e84d61427299453b7842b00c6b5d02eeafced52087993a543d83d2800000000000000000000786175566f830605b2314e9959e1c9e03cafa2c9830196002152912948f7e57a8b53af5aae7a1e7e95c7c63bd3317327069d4a738724a546c3913bddb3627de8c368c628cf63c8a95da60648a8443a2b73950ccbdac6b0a03822112dca055742010f231f", &(0x7f0000000040)=0xff, 0xfffffffffffffffe, 0x0)
getpid()
pipe(0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
r1 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
fcntl$getown(r1, 0x5)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x9}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206923, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r2 = socket(0x18, 0x400000002, 0x0)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r3 = socket(0x18, 0x1, 0x0)
r4 = dup2(r2, r3)
sendmsg$unix(r4, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000934, r0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
clock_gettime(0x4, &(0x7f0000000140))


fchownat(0xffffffffffffffff, &(0x7f00000001c0)='./file0/file0\x00', 0xffffffffffffffff, 0x0, 0x0)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f00000001c0))


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x7ffffffffffffffe})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x3}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
r0 = socket(0x18, 0x2, 0x0)
close(r0)
socket(0x800000018, 0x1, 0x0)
mkdir(&(0x7f0000001140)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0xc5)
mknod(&(0x7f0000000240)='./file0\x00', 0x0, 0x0)
mknod$loop(0x0, 0x0, 0x1)
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000480), 0x0, 0x0)
ioctl$VNDIOCGET(r1, 0x41946472, &(0x7f0000000700)={'./file0\x00'})


syz_open_pts()
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
socketpair$unix(0x1, 0x5, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4", 0x3}], 0x1)
kevent(0xffffffffffffffff, &(0x7f0000000040)=[{{}, 0x0, 0x0, 0x0, 0x3}], 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11, 0x0, 0x2}, 0x4000000000000006, 0x0, 0x0, 0x0, 0x0)


setitimer(0x0, &(0x7f0000000100)={{0xffffffff}, {0x0, 0x5}}, &(0x7f0000000000))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000480)={0x3, &(0x7f0000000700)=[{0x35}, {0x30}, {0x6}]})
write(r0, &(0x7f0000000740)="76e5dead6f01f8607d2100000063", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
writev(r0, &(0x7f0000000000)=[{&(0x7f0000000280)="6b2b22a5dd5a160db6e5d91a0a9183486513e6e2cec886f996270943b11dfe5d5652761ebfd14b89b78ebc86c0c1837448c769c761b1c1eeaa2dbaff3cd6513cc77074172962c3d05772039cee7051fe4535bdc2bef18b3d1287384864b5f1a5e78591d42ad8c6cf8d683a65012045ddde7beaf2d029afd9086b71d9e98f14fa9bde013194313a616fa1fae87d32cb62143f4390d0c67933303e5f47d15d27b703709df0c5d425b900f1ba69f7a1d106fc18df0888358624f2f16b564407e1e86ae5574d349e66513cd9376b4b207badf0cac3ec4bb7687e23ebb218fe933137", 0xe0}, {&(0x7f0000000140)="95bbd7d7d111cf42397e2294eff3aabe25e25a2e60534dd8e198be817693205898e07aa28cbe339b1abb4aae52dae31e1af7130dec3461c030c7b06c11d1aa968673b12ec9452ad6382429", 0x4b}, {&(0x7f0000000380)="b7fd8e4219a786e9a41ff562a3f57309c5e9fafedbdfd44a5f88bccf0a67fcc92fd4a22393628b0342187e70962743bc87636815922ff6ea075f8db1dd20b363c4f2171381af2132004604b80f19642323ff106fb803ac3cfd404801ba244444ad721961a8caadcc6de3f8dccc810cc476b6e84d3156cb2684721bfc8bca56a78fa010dc36937438162022dfb00e46e4c8beddec9ebc3474770376de689251b243bc7036fec97b67eb3031835ac1670742fc3ae041a5edd1efec6176522595d442ac5d9750655df70dc9f820f234f8ab7da45f4203c98b6ddfd7670192e6ac8c1f0c3629a39fbb5f8a88aea50c9a2ca8029a2bbc7359e915201c29faf1b6fdca3902cf328ccf8d24b56df4039b2a0d7ec8e1cc1e014c08601555e4eca507c415168ec5fa1bf2d12ea1de650737ebd228ebd5b1fd39a11971dc5d230ff4de8d56a26a32319b8cc51df44b11abb03b7706d9e2b1e95f0a67b0ef8606c53c83622c8dea60c130a6aed9f6fd7d1e53f6ecb5b9c59b7c2578211fcf09d1692dcbc642813874d9d96f69525ecdd7d1ed30b2dc3964cbe9a20521dd737b2142248dedc1cebb8e079b78c5a0e550ed06f2632e30b47450a27160391d62d4ae634ebdd6a74bd3cd005a75d52c3036bebf9d0a290671337232bd0a664fb176c099f2f831108b852c94c827bc7dd9351c6fe27b5191e46d41d58ff5db9496f6d3cf21ba8af66befe5e325f17cd5c8381bbd2c293d2116cebea70a5ee05c67efeb17978b1eb83deec3264c62a05639f7eea36e1b9be46dae6f409da7b104c9bc99b0b589c5b54606ccc50a26d67a320d25d37c05af37ed28dde45f64d1eff42d6f3b61d4b62e046824cb90e5f30bd0e4e9aabaaf8d281587e93ca104f10d61b2cc878650c01c895ce82fdfb17b63374e7a689070874ea5ea4d0708d05a70b2ec7fb4f2a19376ce50784c99c43821237734315c88b010c0df2a460a48b4c2e12e52a72b36a8dba2ced6f86c1f2ca6015ab07be55a814c5d3320ff57259b5a9f4c334989f4b1b9a7820fa9c531437c70d45570a838ddfacf6972cb51fd9c33814f138401342d954d55a43f9f0a5cc7c5c8792e9189c2cdf2a6cf278812c36cc229af6ee2c2fd7fce74650f0d6855ee255f10dd4c90369b5c9c30c6f0d7cf7f2da1f8818a1aa7baf1a4d712df58063c8d7761a64ae132c85071c33f1ef43cf6975b0716897ad0e83abd5b6ab3ed89875de9300a666e537f10d086261899460961b5d18eb17ec4a3b7db81042e723392ecc7b903725878acf13b5922d1f82257c05b5e6e461dc729b9d71be993ceee4fbbc4982fef69a86d597f3ad757007428a82a3d70b4bfb43dfb21a15bedb821abbf5e4da59e18eb61a13e4afc718d3efcb0d3c3dd46ab9c0384d20dfa6ec077fa27761e217a3bd0ea1d726cb1aee70fb7f892177afd96f9acb65d700d43169d81846e5605e72f64e10a9ef715a0d828be9b742bc8eb67300da0bfa72a9c5e3ff3a380e84d780cc86fb341a6221973b70764e5f902d57da0c2218931f9eeac55a8b44910dafcdbab8c28327a6707bbed9d3361478261d4d79eb73555e8319bc9042fb2193340c69ce6b7f86466c99449f0764801c8958426906dd3f7d388b8ef80004f583fa94d633252261b1fabe077fc4f86776f8c380ebfb3be006448a7725465e52eda74f555b45297bb7b4e65bee27c2afff904a598acd67e4bcbbd4b0b450d91d4f71f42e7cac4e45d4260dfc6835e8ce6d3f55f3475be896d29aeecf1764a2b3b544ecefa42edd2d916cac9302ae7a62a11c30eb29e3b96bf0575e708332f2dc37302ada7ba8be1a47b56f8d97fb0d616813c8f0b06b0e0976334cc7f29194cef11226db38e41c1befe4f38b8de40d6ca72412ac56ff1c2ea6c545df028dbba56a23ab378702b935482f68ae0d6f8c8ce120f2a71f8e1cc721a716382b265ad8fd80c23a1ca44875dddfbf4078c2ede20fcf53d466b5a1c0871ce1f826f5086254d58cc1f832d9e9ae7aa58371d21f9d0e25a510755d72a38fa78b21c0474b02cc251bf005f3077fd1f58849d0ab06dfcb75544de9071ae016f68d7ec1bccad3565685724a87d5da4636403546cfade208676e4e69fa546e98cb59372b24b188f592c6e0b26b017ab3e21d044b2d1a899817215f7b31909bb6de4b919ecee7fd61a7b6b7b0c1e766d1605ea0fb15d6c9d7833b7eba2dc2c3c923477a499ddfd7bb59928f1ad44fadd08f173c92ffddd2936bcbf7038614ebb2dbec732df545ff744ae1215e3e25d7498536314e9baf2345338345f2ecd9ca19899940c64444eceb542730b7b96d8e212f29a221e2791757b3f3c304289ebb1fa3b3ae8ab0c162b9908beadf9ac013e21e58626e6554989fbcbf98e400c5e978994ff00ec6632d3cdbe05dd308751913fb665505065bb338e96295db89486602eba2289cdbcc9a03c7ef12b9588d614cb03b2c76363cd75cae98fe7927c74302d1b538355bc531ecad3da1638c5c066956d2d90c138c3881c913b2dbee4b07cf4e69425a99800830e77c7c94a4ad58409d3a39c9517ed78dac01418528a69412a61112f1c433263bdba1b81b0873a6e9d71fafb0225c4d17114ce9daf36b2238bf5e2ea145a38317704b6015e0a3a6486f7eff11a867e71bb5260b05179a163e9805c9743167e663701dfefea0f7217f7907213bd3a5bd00a454e7abb5c2d3c17df72c43c6a16a298e8f3cb710348ea0133f3182981d7896dc4ce2d9ebb976d937ed5ae02a1abecc4ae4369bad360e08d1474d6f9b43445e3f72ffebefcfa6c03a33818b6fdf5933fb138f3a23ff2635b22c2aeb7acddc6967ac45d86b29147e3ea852117ea891bcd9708121430165cda855270a44e8d35781bdb2fed63fdbbde478a3205716585d9db929a5e36e2d0d579839ed61694b7d85256573bf84c45ece1bfbe68424c53e132e5bc95af2fcda52eb67e2afb63b8daa1a1ba27f770c72331e3ad471bb51dfedf1ff54ec7e2f1455c3995bcbdf4baa48dfc6a1b67c6a8494010dce0995d99ec26ce6dcfc7e7b868d48f0df5afb4f699efec82cc174c054b6f340cf1bab5106a3336fbbfb639362d8aa8a1c119944c5f57582b2cc0bf76a8c866d36d88791c377fd9b10ffc3030c0f792be68f5d5ff24f90e72375774f8792221d81b4882ea885603aa9497df0c5e9dc6573f487270d37ce27a7d8ef1ed9f960b6dbbced777ce5527be0a87f1b22c69116c77617385e6c626491e73c7a0f0da863ed7d7225af47ef90bb73ff43d714498da97c1a5f41c02394a2fe496118af802515ba0b7d135ca7eebe0110d18499ea8232235b8173c701977380adf5ce8f9b10b3a7d192e8cb4b8da7fe85d053451c2a4e60ba3d1af390cdedaff43d7d7d982e32dbc4002326b5746b5f1ebd07becdca6f3cd123759003e21f73908111a7904ab50281272b1b5709c090685e977466a3732b58c272438d1e53272d9c42b1075bdfcfa4b0c511659b6366724466d98ba805aecf9346f98302b2ab15f19b01d8ed6d5e75b0d0004e8f881a96e6b89ec35de1376188d30d6d1be06c2d3f6ebd16102c256ea0a58c647547dc578f22093af34ef9358453b9c83c67aa1f484310217140d234d37342a2fe11d7e5355b465b17ff30c1c0551247cb808b1abf7e1aa5c4ed78d55e5a554f5db8a2247f1334da7bafd38664e4cfa27049d7159f003cec0c00dac5085af45822ea84f66bae23b69565ac8b3924a67e3a53d7da33c4dbe83c7164c907cac41d46a14bccf18505b7859fac274195588c3923f0236d7b13bab44e94021f3693fbdd3d02606ad3fd0f72ea6b4e1ed14526f98937acda91b5bf4b252e7d28a06442e1fad14631f2165a5327af0b4ef994d81741efc0f6d867d759a19b785e65b3e0500f21169c8ee3f2a848589ddf5fcec86b40fceafbadbbef82699c98682c066d2907540f801819472231c56a34a62b1f274143d3b21ba86671cbc68af8fc4154d93c3aad1b57bc4c08009e3227230429d66389277cd77d53eccc875f7a45c54cf114fe7bd0a95a7029c9649fd286187ce73697c0fe7883fbb6389d5b035a474b8318b8e24865a143b38218132374bd58fa0a270ef5795687a412d7c23a71043739be531ba1580e6981b89bc40ad7ee58c034fabcd5a1153acd3f9b293a9e4d374a3a44c1a7f765a5fce7aa1585d6383b7f5ddaf83efa6f1dc32abc0e26da1cc2cee80f18002fadd00dabdf5b881c41323081ff0eb3bf9a348d3eebbf3e65bf094366609cd8b59622468682befdfe7995ffd39fa238342f2eb7bac98fc8faa6d898fbb95b8260145f52adc25f0abbb914c04024f052411f6526f1d6763f461bb6828db3883a9ba7406c108b69d1e28f440784422c481d20a9a966765f02276193b1f10a7fe00b9adb45142e002277b2d13d6d423dea9dbf7aac4f2815456efa9dc4c39e26e2f7a3873aaf6e11aebd1273b32d3801356887129495b6fb966627bb6ac1ff5c5a4bc46e86d4d4a8174cc8dfc7c4c90299cc0dd3470a8dea1e60174c11725969d01a7b80daa0c6001e0a30bd71215fd3d1e4e361a6c7acb2607a3e6b25f454469652a104736fb5f532cd58571696b242dcec07da516264e7165c3987e38c5ee093c9671fc439562d4496f1e83d3399ce17ec705a70da9891f591ea56d2f2340a863543920922f8d8510e11a051d0a893fd381f5f74712afb0f7efeab1fa19666e2689b728cc60d257fc42e2308625eba609262f0f1f798e9df85d2ef4328aadebb2c1fd8e201f455aed0ffdce4aedbf62d9beb2d44d1ac963c38e4ebe8916cd245f3e4e1ac61b95ccb707e11df089750329b6e1543013a671de001fbafedca4368f1b49f2322d7ee2eaa9ffe2ef3e96c23d7afa12b0e344eeddc99b9f4b630a9bbf44c379cbbaa606026dd0e82a93347d2540621b977fbc96a5545c3d63a1398497338a6e3ceeac0372dc328654cf359bfecea45175b21e0764704920569b263aadb459992ed267fbf04a509bcde393481a8f4345f6f6290cb81ce3c12720541c57d826d322ae01e682dcd59a4bdfa72f4f54306ccc5312fb26dc0e08850e8a8b39b181cfb53dca31740a12f2d0ea05a167cad28a178853b9b2ecd6189790f277006c4b97774b696d8592bc2b2e2dae312da4ad783bb81cd4055a988d89e0a5e6631eb4ddb0730a751f55db53c0d81bf1355691bd382e7e8a2d73700af9290d1ebd9ebca25de6b1c599d34198fe21a0260899b6df5a971ea15903e41ef3963d977ceb2e4c5591e66c6a0add71736f41b476b6ee876c4c0efcf6ac4a1c210c0164f85db30d117899a868cc8f8e11e3b4900c095cd3caaba71366ee93dfa54a95da5845b7129fbf3493d3f16cc56ce7c5c2fa8ae8c9410c734dfc650c67c1648095f0d29ded5257f709b0c4f4f5d7255d726b8ef3934deed5088a688f35e090480d5a5f9c66682ba63fd0ab4e7874aa3b584bb75698f603af2ff40c884ab8bff44138d9c715207a5c9d28d06faa513471703e05145841006ac28c2a00eb4f6fd6118567c53fa8c83d2cb61f60b597121f79675816fcef5f2302640907d56c2746427aed7f5d1d0a857bcc0fa3f72fe5cf1745ecaddc1ceb84aa22c8c87423ac0c53e80628d6ff9ff20bb056d22f0cb3f916552ebf7c661ff5a9fab8c966874093a1f3c4d1b4a30118c604d7ca3aa696102b1ad9b2e320b7e978a987878e6bb51943ab55fb8e01488e91bc65d0821e3c0dd354535768f5e3ad115d6e90b82977828406bd04b383e71376bbcc4d37faf6", 0x1000}, {&(0x7f0000001380)="53ee346d0eed9d5e0c02589611a9f4a5f5fc2f81faf147e4bcefe405152c47dbfeb1111986320ab01acca4149be4e90ca450846b5dfe9f7a44a8562d4b080fd17c1fbd0b498615ba0b9297caa650c94965d8360642e7ed9f62c54ccaf79e2566b6d49292bbc46408c428e6c4219e592ae928cc39b990980c77fcd8c072c9ae0c4d7896e571c43768a2283b87215ccf84908424288558093cdef4f6a2d1de3af7957f648e1b73f86649e35c0fb1995c350a0c70ef719414ffd50b893ea332c9f784820ae3228c453975e1c364b3b4cdc9d77c0fcad1", 0xd5}], 0x4)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000240)={0x3, &(0x7f0000000100)=[{0xc}, {}, {0x6, 0x0, 0x0, 0xfffffffe}]})
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f00000000c0)={0x2, &(0x7f0000000100)=[{0x25}, {0x3c}]})
pwritev(0xffffffffffffffff, &(0x7f0000000080), 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
setitimer(0x1, &(0x7f0000000280), 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x2, 0x0)
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f0000000200)={0x3, &(0x7f00000001c0)=[{0x0, 0x2, 0x81}, {0x1000, 0x7b, 0x0, 0x2}, {0x400, 0x20, 0x40}]})
syz_emit_ethernet(0x2a, 0x0)
r3 = open$dir(&(0x7f0000000040)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000000)='./file0\x00', r3, &(0x7f0000000080)='./file0\x00')
linkat(r3, &(0x7f00000002c0)='./file0\x00', r3, &(0x7f0000000300)='.\x00', 0x0)
syz_emit_ethernet(0x2a, &(0x7f00000000c0)={@empty, @remote, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, @empty, @rand_addr}, @icmp=@mask_reply}}}})
r4 = openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$PCIOCREAD(r4, 0xc0187009, &(0x7f00000000c0))
r5 = kqueue()
kevent(r5, &(0x7f00000000c0), 0x7, 0x0, 0x80000001, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$TIOCMBIC(0xffffffffffffffff, 0x8004746b, &(0x7f0000000240))
syz_emit_ethernet(0x2a, &(0x7f0000000040)=ANY=[@ANYBLOB="aaaaaaaaaaaa00000000000080350001080006"])
writev(r0, &(0x7f0000000080), 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000580)={0x3, &(0x7f0000000540)=[{0x2d}, {0x3}, {0x6}]})
syz_emit_ethernet(0x7e, &(0x7f0000000280)=ANY=[])


openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000040)={0x7, 0x2, 0x3}, 0x3, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x31}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0xfffffffffffffda3)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
chmod(&(0x7f0000000080)='./file0\x00', 0x40)
writev(r0, &(0x7f0000000180)=[{&(0x7f00000001c0)='#!', 0x2}], 0x1)
writev(r0, &(0x7f0000000100)=[{&(0x7f0000000040)="20090000019c0a", 0x7}], 0x1)
r1 = semget$private(0x0, 0x3, 0x10)
semop(r1, &(0x7f0000000040)=[{0x2, 0x7a}], 0x1)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x6000, 0x202)
mknod(&(0x7f0000000200)='./bus\x00', 0x2000, 0x203)
r2 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x0, &(0x7f0000000240)})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000140)={0x0, &(0x7f0000000240)})
r3 = socket(0x1, 0x2, 0x0)
ioctl$KDGETLED(0xffffffffffffffff, 0x40044b41, 0x0)
ioctl$FIONREAD(r3, 0xc0106924, &(0x7f00000001c0))
fcntl$getown(0xffffffffffffffff, 0x5)
r4 = kqueue()
kevent(r4, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
fchdir(r3)
socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, &(0x7f00000001c0))
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r5, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000140)=[{0x1c}, {0x3c}, {0x6}]})
syz_emit_ethernet(0x127, &(0x7f0000000040)=ANY=[])
openat$zero(0xffffffffffffff9c, &(0x7f0000000280), 0x80, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0x3, 0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})


openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, &(0x7f0000000200)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
write(r0, 0x0, 0x0)
recvmmsg(r1, &(0x7f0000000880)={0x0}, 0x10, 0xc62, 0x0)
open(&(0x7f0000000140)='./file0\x00', 0x78e, 0x0)
socket(0x18, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x14a, &(0x7f00000008c0)={@random="69e1629b6164", @remote, [], {@ipv6={0x86dd, {0x0, 0x6, "6b9efb", 0x114, 0x50, 0x0, @rand_addr="cb69bc83c1677a656ab420666c3e2c6f", @rand_addr="82056be84b57021d3e9ceb4883c2cc10", {[@routing={0x0, 0x2, 0x0, 0x0, 0x0, [@remote={0xfe, 0x80, '\x00', 0x0}]}, @routing={0x0, 0xe, 0x0, 0x8, 0x0, [@local={0xfe, 0x80, '\x00', 0x0}, @ipv4={'\x00', '\xff\xff', @multicast1}, @empty, @loopback, @loopback, @local={0xfe, 0x80, '\x00', 0x0}, @remote={0xfe, 0x80, '\x00', 0x0}]}, @routing={0x61, 0x4, 0x0, 0x6, 0x0, [@loopback, @empty]}, @dstopts, @routing={0x70, 0x6, 0x0, 0x7, 0x0, [@ipv4={'\x00', '\xff\xff', @broadcast}, @rand_addr="1f209e25fee0794ec714c631ea455589", @empty]}, @hopopts], @tcp={{0x3, 0x2, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}}})
r2 = getpid()
ktrace(&(0x7f0000000280)='./file0\x00', 0x0, 0x928, r2)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000500)={0x0, 0x0, &(0x7f0000000480)=[{&(0x7f0000000380)='s', 0x1}], 0x100000000000038b}, 0x1)
execve(0x0, 0x0, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = socket(0x18, 0x3, 0x0)
utimensat(0xffffffffffffffff, &(0x7f0000000100)='./file1\x00', &(0x7f0000000180)={{0x1, 0xffffffffffffffff}, {0x0, 0xfff}}, 0x2)
setsockopt(r0, 0x1000000029, 0x27, &(0x7f0000000040)="5ab7736a", 0x4)
open$dir(&(0x7f0000000b80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x200, 0x0)
open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
socket$inet6(0x18, 0x3, 0x0)
open$dir(0x0, 0x0, 0x0)
open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
poll(&(0x7f00000000c0), 0x0, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r1 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000001680), 0x0, 0x0)
pipe(&(0x7f0000000240)={<r2=>0xffffffffffffffff})
ioctl$FIOASYNC(r2, 0x8004667d, &(0x7f0000000340))
openat$wsdisplay(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
r3 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
poll(&(0x7f00000003c0)=[{r3}], 0x1, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
fcntl$setown(0xffffffffffffffff, 0x6, 0x0)
getitimer(0x0, &(0x7f0000000140))
ioctl$WSMOUSEIO_GTYPE(r1, 0x40045720, &(0x7f00000022c0))
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
msgget$private(0x0, 0x0)
msgctl$IPC_RMID(0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206916, 0x0)


clock_getres(0x0, &(0x7f0000000000))
setreuid(0xee00, 0x0)
sysctl$net_inet_carp(&(0x7f0000000380)={0x4, 0x2, 0x70, 0x4}, 0x4, 0x0, 0x0, 0x0, 0x0)
getuid()
r0 = socket(0x2, 0x1, 0x0)
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x0, 0x10, r1, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f00000000c0)='./file0\x00', 0x21e)
chdir(&(0x7f0000000140)='./file0\x00')
symlink(&(0x7f0000000200)='./file2\x00', &(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
open(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
r2 = semget$private(0x0, 0x7, 0x3c0)
semop(r2, &(0x7f0000000080), 0x0)
rename(&(0x7f0000000540)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000080)='./file0\x00')
semctl$GETPID(r2, 0x3, 0x4, &(0x7f0000000240)=""/8)
semop(r2, &(0x7f0000000280)=[{0x1, 0x7, 0x1000}], 0x1)
semop(r2, &(0x7f00000002c0)=[{0x4, 0xffb, 0x1000}, {0x0, 0x420}, {0x1, 0x2, 0x1800}, {0x1, 0x1, 0x800}, {0x2, 0x204}, {}, {0x3, 0xfff8}, {0x2, 0x9, 0x800}, {0x4, 0x1, 0x1000}, {0x3, 0x7e7}], 0xa)
semop(r2, &(0x7f0000000280)=[{0x4, 0x94}, {0x0, 0x8400, 0x1000}, {0x1, 0x2, 0x400}, {0x3, 0x8, 0x800}, {0x3, 0x4, 0x1800}], 0x5)
semctl$IPC_RMID(r2, 0x0, 0x0)
chmod(&(0x7f0000000440)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2)
semctl$IPC_SET(r2, 0x0, 0x1, &(0x7f0000000140)={{0x1f, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0x10}})
r3 = getuid()
seteuid(0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000340)={{0x7, r3, 0xffffffffffffffff, 0x0, 0x0, 0x71, 0x400}, 0x5, 0x9, 0xfff})
semop(0x0, &(0x7f0000000040)=[{0x4, 0x3}], 0x1)
r4 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(r4, &(0x7f0000001580)=[{&(0x7f00000000c0)='\x00', 0xfffffeb0}], 0x1)
setsockopt(r0, 0x6, 0x10, 0x0, 0x0)


write(0xffffffffffffffff, 0x0, 0x0)
ioctl$TIOCSETD(0xffffffffffffffff, 0x8004741b, &(0x7f0000000000))
close(0xffffffffffffffff)
execve(0x0, 0x0, 0x0)
setsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
open$dir(&(0x7f0000000000)='./file0\x00', 0x200, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
getpgrp()
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000080)=[{0x84}, {0x3c}, {0x6}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])
semctl$GETNCNT(0x0, 0x0, 0x3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)


syz_emit_ethernet(0x52, &(0x7f0000000300)={@local, @local, [], {@ipv6={0x86dd, {0x0, 0x6, '\x00', 0x1c, 0x0, 0x0, @rand_addr="fe350e28ef0900c0f1ee24be00", @local={0xfe, 0x80, '\x00', 0x0}, {[@fragment={0x0, 0x0, 0x5}], @tcp={{0x1, 0x0, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}}})
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendto(r0, 0x0, 0x0, 0x0, 0x0, 0x0)
recvmsg(r1, &(0x7f0000002880)={&(0x7f00000014c0)=@in, 0xc, 0x0, 0x0, 0x0}, 0x0)
r2 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r2, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r2, 0x0)
r3 = socket$unix(0x1, 0x5, 0x0)
ioctl$SPKRTONE(0xffffffffffffffff, 0x80085301, &(0x7f0000000340)={0x9, 0x2})
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$WSMOUSEIO_SRES(0xffffffffffffffff, 0x80045721, 0x0)
getsockname$inet(0xffffffffffffffff, 0x0, 0x0)
r4 = socket(0x0, 0x1, 0x0)
connect$unix(r4, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETF(r5, 0x80104267, &(0x7f0000000040)={0x0, 0x0})
syz_emit_ethernet(0x26, 0x0)
connect$unix(r3, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
r6 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r6, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
open(&(0x7f0000000080)='./file0\x00', 0x200, 0x24)
close(r2)
sysctl$kern(&(0x7f0000000300)={0x2, 0x7}, 0x2, 0x0, 0x0, &(0x7f0000001440)='\x00\x00\x00\x00', 0x4)
socket(0x2, 0x3, 0x0)
open(&(0x7f0000000180)='./file0\x00', 0x75f493fec6515f78, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000380)=[{0x48}, {0x14}, {0x6}]})
syz_emit_ethernet(0xe, &(0x7f00000000c0)=ANY=[])


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, 0x0, 0x0)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{0x40, 0x0, 0xfc}, {0x61, 0x1}, {0x406}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
r1 = getpgrp()
r2 = geteuid()
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000080)={0x0, <r3=>0x0, <r4=>0x0}, 0xc)
r5 = semget$private(0x0, 0x4000000009, 0x82)
semop(r5, &(0x7f00000000c0)=[{0x1, 0xffff, 0xe5ce97ab354d96be}, {0x4, 0x4, 0x1800}, {0x3, 0x0, 0x1000}, {0x2, 0x6}], 0x4)
semctl$SETALL(r5, 0x0, 0x9, &(0x7f0000000040)=[0x7ff, 0x1000])
semop(r5, &(0x7f0000000180)=[{0x1, 0x1, 0x1000}, {0x2, 0x4, 0x1000}, {0x4, 0x3, 0x1000}], 0x3)
semctl$SETALL(r5, 0x0, 0x9, &(0x7f0000000240)=[0x7, 0x4, 0x7])
semctl$IPC_SET(r5, 0x0, 0x1, &(0x7f0000000380)={{0x9, r3, r4, r3, r4, 0x100, 0x5}, 0x2f8, 0xffffffffffffffff, 0x7})
setsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000d40)={r1, r2, r4}, 0xc)
ioctl$FIONREAD(0xffffffffffffffff, 0x4004667f, &(0x7f00000001c0))
r6 = socket(0x6, 0x2, 0x10)
socket(0x18, 0x2, 0x0)
connect$unix(r6, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x6}, 0x4, &(0x7f0000000080)="782843fd78aff20b168d643db9d963ee2cf373da5ae6f731b0beaa12fb0b10ad52cc6f5343059c914d55124bf28b62d75fc8fba54016e546f8dac706231883ae27cda049089da68a68466b636cbce943e2d3acb3b7f488a17d5d1992b426e39eb1271d9d2b9ea4937a44c1eeafe1b0af03e9a97704e35ade72e4c716dac87c1da7a0fe4f0db8c16b3af00e93673df3532c4e16f00dbe31838c0247f9d78e57cd11f34b59e13c4e8c1c097d265159e8bcc02cabb990b20043938617852b638bf3406c8a9e22f577ffb065f9b260bab5f805b9c8c24e7e612d7daf4b654ff59e9b08ec379489bc919985dc8c8ca98068ab11552684a1bd6e793d9c0e1fcdcf7d0f1e8771ef3c8311609f8657c7454bc3e84c32888dd585100e626d1cd74c7a3d8cfc6aad0592bdf7953d030895b8cfb96bfbf6fc8f353c95f28a4288574e2c0d6ce6e00ee12c5f71df38dee821331fba72379a43b75f49ef179a4a7cdd2c6d26b46e7587f78f46622d6f3b9ba1ee9c29b2cccbd36ab44de76f4b984f432a4fb64dd043be450a5d8816205486059e8fbe65172c13a1f141d2c182e54481c12028534f51b84881086360c89860efecae8cb0d01dd87d3aab650ba35a70d980812b474381054d2789c3a3b2523f4281edb4ec15d986b06034b8cd1c09ae258a01263fa4ff9100ef0176bfdab6408629a58ba32d3f3d4ba57685c65e547de9c1f88e2846aa2cdf757f94309ebbc6dc49fb02c0a732c97b65de8b9087fe3aa1af3419ea8c36fcb9712c6548c30992e677a48df75750e903c1887a3d18f9ed1caf2408fe681fdf9a97f31ef15d340aaed361a0da6e3edc01cea06a5a6f39f0f0c4ca98329a7b97bc66515406a4fe8736b6905c53a8e14fe1dd867813ec194d97acfe4a7b7f3b1f166f50df35c45de442cf8d271615cbe9fe5befa381f0e75aa91e213ee533b7761c3f97cc3b08ee48b03dab640b26fc05703c09aae0bee12a1515cf4d3ed8eeba031cde3edf4f654820ba30302f31ecf809308167358779681a0bfd0b5c8d1429936921a0f2bd2b9c15637e54528dbaef9ebf218502c222af181480739d9678991e87f403a1cfdb7bcf43a9b54e54f263bd9275c327b7b640f240d5ef432c31d0ec70dddd3cf680b19b5b642d1ea455f94a37d35ae3f70e6ee1db153f96e48ee573c05221ff19a585969c18cf19548fa38157066c5b8d6c53d77e5071be61df2d1885e00009e1c700353b87b3e56423086d41775fb673c0d6d4b0f41d58bd55e7e29fd51cb516f5af0566666a46727bcb545304436a774db5326fddfa0df623ad165ecccfdc5fd8098dc9d8937580776ed5652faf668584cb741d6360d381adf494b69e371a1b5a8318b23f82190aab586f51044e8a789fa8736f717d0172ef310367b99888890e7f07a9c9632289a1b61ad43be323d701ac5d368cd1a4a4450271a722824d9a23119cc7a13143ba6ff6d3caedffa6fb40b4fb506ef1f9d0593f8b465519757af6f8c2e0f5c2051cb2e2312128aafa45a4a63b9c81a3d11d3556e84bad9335993895988766b96cd621d98ae945198054978f478f2b4016c4806e1900ec360b1654499dd3801118f02b5b93f7117187071c68af6a55723f1b60dc7a9aa7c022c005a74d783eec74a8a659a86a191234ae03115f2a6f64d3655216624771f5a09e81fb88930fb7684bd3257cb6c8273f1550c9cd58620b2ef01833d527b93554650dba820579b708b4d08fd21b2fb1233469f13017fdbb015529c2c7bf313913e85ce27801978793cd5cee8df30b3a8970e4b79d29e8af96d9ffbdf5b1a077eb111fb2ea099a97f8a1a9b53f7a5103402fc538276b15df0a31757212b108cd4f0b44606f2c819d22e5c963700cad8ba0efe21003c0eb514f1946454b52c11b6825e1b909b9f1d4318b0dd31509d0b056574951a919fa0450e57040617eede7e85bcf66d2f044799409273d008fc313edc157478972c2c43d4ac117cb70d44d6708b8b7c4149773179415ab144df48ab8312fe78263b8d5d1028d1919fb8c192cda349aae77fa89b86209d36e68b4cc830cf25979d905ce184879ecaa5cb7d10806168505550b477052f985754d8770a8153be16b7622d2745e9cb32ea737e4c818e46f589682432e7c217e15cc029bb1609e8e5155fba57eb67a724c5ac3e79a6179728176bd5e2f0d48d422246107fc70dd94cf4e696d18a6963e6cddb16c1f9ab2deeb66ee2fe9b689e4c416009346eeb4b7d0e0aa82101117ccca29a53614ae6eeabacc230edbf1cf601a8736e5f269d23ff0968b9678768e7e7b388b1e4b7969e6184b4a3ebfbfdb430a4f7e94e22810cab741e13d49ee48b28455a8398de3b919277f35c7e1ef2df238f41bce930baef45446b868914cebfdf6c2e02a24f0c6c76ee91d25abf2dc18035f140d6dc3697b29d9b8114d38d023d45a9fbfe3d8558f2dfaea1dbe43a30ce3bccd3ed9246fc5f05ac74a63d12f73201c0da930aebc895aa963967a1bb7441e48b96c93cc2a4399c7fa55a9809383c687c2a33a335b2722610c63f151dcf628148202fdea2b47cae382ec4e48411efcdc5ab56c092b5f9a49057222e93668599b8fd5a0888ce2f6e821ef85137851a4f550137ba2d12cb867683d4f6cffa5bfd5632ea6f9660c13a37bbae7daaec512bafe22f7121cbc498a2d8338212ccdf8cd3ccc4d10b290522d2a556f3432edf5131ccd9f27897ff638de03231351b8bf31e0492870f4bdd913d185e127357845fa0f83f375c5b8ae461ae9f49e200007c77237816e4170e069ed6d0a1b333d97f146fd683c2a3c6c6e534d1a7576d1b2986e8c813a1fdf02efbe2868805b6f7db70a344692dc33da87cededf787c43c114a7c5db5f953fed137e34980834d140ab61e646c766d9bb9451b2b7b25401ec7a5445b02c8dd500272f25ac6a3d8753dfe58a091370319dd52bf23e48cdb66b834d02caa8eb97d6bc1b79d0bf9d640f918058ee84f8e478782b506ca6918e1da791017319312381b40ce7f4cadf4bff83bcfd90206be783d101abc830afd0ea73c1fb92d4a7ec0bb2f8452ace5f99abaa395b67ffef9df6405c140bf919f604f5a662bc54de595fa0bbef153bdf1ce16468f5f7975baf8afc21ac76b0884f007be002edc6b4b54e39dc9260831d9b3993e5bdb0ea545abb2ba7ad2ce65f3d8d158529267907e17d4dac9d3b6328fa265bd1fc703b54475f37b7a0179573946498859d40f586307992f0602bca767305a23eccb6a12604280a382a277421383054b8cea9b04390b373a69eeb88d5285b8b3a381e06bbbacfeb45ee6950772043211ebfaf78d8608c641f8ec46dbbeed2782d7db086314640395296948803bbadc9fe132419c892ac72ced4d0ff295716e04acb35cf4153848e18fd38d0c108608185b9e7bc6835cb06bd50f3094eabad44282e05be34413510251b2f6036b9343b7fd9e4f3e2e5851830e127844bbdec550822058e8197c0c8de0a5b14e09ff145930eee5ea46f5206b7098624769b09fe9dd7150983fd407cbd14b48c501668756032ce627ba687e68017e15ed35550a9e32550aff8fd195c51cfb08d1be72c07a4fa6d65f82d5b30bc98c84c0eb98e741b791205ae3476947be4ff4ccb7e3a78d9c03af812076d167743465ab2b82a7752210bd3ecaffe06c1c013615988c0c918bb723de6bda98e13ae6ec4c0f4d84e5665518bacb2e75b43ff0740b17c027a3e08dd46c51e59bf6deb9fc95944670eaf45da8bf28326fd258587250115d26a25faf7c2a4427bb3b3c468765715e7460c8fcc58ed050af6f8fc98c1bfba2efa46f3d6f0550afe518af6daccc5464bb4936e5ddcd75a5db1689c87b91268647d577c3c36b1034ccdafd2d53a60e022ae42232f5a46284054b17f3a35f5600fcbfa30acbdf58eb039c2e7e21425fcc0a1d1c732bd0071e7e4fb8b11fb55d84af60c9f792f08589ed54b660a90a9fd4c95fc9c92c814822a7cdd3249509c0e346e77083fc7bbfd6e5327db671ce70412203689ab8f52cd3215c3a329a6973fceafa1789a12b56afcaaa4fc233b5c7fe392c588f6c78545f5612f2b44e258248c5eeb965bd7bc2644d7bb6fca7db4b71e4146f4aa044aee2892ea9560c0028a991fdd59f51d1ba5f7cd9b100e5c4d5ca10da24400b27c742dc1a11d15df979b360605bb08a5b8796a2a85bd6a54af92335b78f7790736964350e71f7ede88721049c7b887266e84cd2b85399cb1112849af498c4b7d8a359164cbe8a29742c162a8682adf978f112efda4a58888e0a2a438faffefe0fe2a9ed655f14819ce5a37407bb5bb14a2858a17c623105cb8412e5319122dfac7c9207ce0a77beb2f9a42e0a4ebfa36376689e1866456bfeca60dd2468c11c2c5fc792c68db68b833507a725304ec2636dab4b32da502fdfbe8e9b1d4f1279310cfc64e7955893f238986888c32edeff4e076b1f9f778529be799a8d7fe9c090c33bac0bcbabb96fcef2ff70281ecbc0bb7059fd530ef13792c02eb40e92d", &(0x7f0000001080)=0xc88, &(0x7f00000010c0), 0x0)
sysctl$kern(&(0x7f0000000140)={0x1, 0x32}, 0x2, &(0x7f0000000180), 0x0, 0x0, 0x0)


mknodat(0xffffffffffffff9c, &(0x7f0000000100)='./file0\x00', 0x1000, 0x0)
openat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x1, 0x0)
setuid(0xffffffffffffffff)
ioctl$FIONREAD(r0, 0x8020697a, &(0x7f0000000100))


sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x12}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000000)={0x2, 0x5, 0x2}, 0x3, 0x0, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000040), 0x3, &(0x7f00000000c0)="d2fa771dfaedc416be08851c851dd66dadf7c56dd8ca69c641ccffe9009d0dc9d80c8e5018", &(0x7f0000000200)=0x25, &(0x7f0000000240)="5ffe97428cd7348210a28d6ace527385203c48a7e2a9a9d164ac592d2f2f4a84b1927af2d580ee24a1060ea1243b2e5db4ca5f6fd2fa41b44e24163394569c4edf0719adf41de61c52ad2c0617e2b0e8dda480b4945b041c464e0c102eb77264b9081a6e4416c4e766e5d9a64d079a3664f0aa10a1c66f2d137b51165b5bee4f0c10a8f7498a07a9fa78a7e4f1cd4959c5662f4e4c3a7bfe4d356bd85c0a2dcffe690c88e29072cba4aa64228765ce8328fa4fd895118e44885dc152942116dadb01904be11bec31f05509000000c9e4c6720c6d680c80881ceec17cb490519a64dfd9c30530b8c5c83abfd91b0a791cf731d2fecc822993095b45e0ef3668e153a35d2a9455239b204c66c4a992e462f0944749cb73e66f4bc458691ba474a1c83f0e8b55ae16770b36eaa48bbe176183adcfe20e8bcf46281cdf0e238f909aa0fa772f09203e02c874371e96336b433879ae649bb57c2567edcdd2c102d81bc0dff9864550f083ba465aadd93532808ec4a9b8cc1360ea4e3c770f61c25ef4c044", 0x182)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
geteuid()
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, 0x0)
write(r0, &(0x7f0000000080), 0x0)
msgctl$IPC_SET(0x0, 0x1, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x30}})
r1 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x1, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
r2 = socket(0x800000018, 0x1, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x1, "1a1116f0d0f700"})
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


open$dir(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
getpid()
msgsnd(0x0, &(0x7f0000000100)=ANY=[@ANYBLOB], 0xe1, 0x0)
socket(0x0, 0x0, 0x0)
close(0xffffffffffffffff)
openat$diskmap(0xffffffffffffff9c, 0x0, 0x80, 0x0)
r0 = shmget$private(0x0, 0x3000, 0x226, &(0x7f0000ffd000/0x3000)=nil)
r1 = getuid()
setreuid(0xee00, r1)
geteuid()
r2 = getuid()
setreuid(0x0, r2)
semget$private(0x0, 0x2, 0x490)
getgid()
getegid()
shmctl$IPC_SET(r0, 0x1, &(0x7f0000000240)={{0x9}, 0x0, 0x0, 0x0, 0x0, 0xf394, 0xff, 0x7})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000280)={0x3, &(0x7f0000000080)=[{0x48}, {0x1c}, {0x8006}]})
syz_emit_ethernet(0x1db, &(0x7f00000007c0)=ANY=[])


syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="0002"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000), 0x10)
listen(r0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x138, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
socket(0x0, 0x0, 0x0)
bind(0xffffffffffffffff, 0x0, 0x0)
r1 = socket(0x2, 0x1, 0x0)
fcntl$setstatus(r1, 0x4, 0x40)
r2 = getpgid(0x0)
fcntl$setown(r1, 0x6, r2)
connect$inet(r1, &(0x7f0000000000), 0x10)
shutdown(r1, 0x2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000100)=[{0x40}, {0x14}, {0x6}]})
syz_emit_ethernet(0xe, &(0x7f00000000c0)=ANY=[])


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x1a1e, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r0, 0x0)
nanosleep(&(0x7f0000000040), 0xfffffffffffffffe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000140)=[{0xc0}, {0x2c}, {0x6}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
syz_emit_ethernet(0xe, &(0x7f0000000040)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000280)=[{0x2c}, {0x44}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


mknod(&(0x7f00000000c0)='./bus\x00', 0x6000, 0x0)
open(&(0x7f0000000040)='./bus\x00', 0x10005, 0x0)


setrlimit(0x8, &(0x7f0000000040)={0x7, 0x200005})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000340)={0xfffff732, 0x0, 0x1, 0xdfdffbc1, "97115f33ba7d00fdff0104000000000000de00"})
writev(r0, &(0x7f0000000080)=[{&(0x7f0000000e40)="227f1580592497fee6cbccdf6a7f61ef80e455937d9e111d739c5768317e7e0b166e0f694c0f20a0303bb87542721fec0b953a6a037b4df5bea57e869e2f9aa26648f2212ef1a42a13ba6cc13f3e896ef459696c53e816aeceeca263fc515d1b7df2b7f56593dc74e5901f4ad75cb53267bbd2d6cbc97eeb27c89667b9a0f43ff7f72f67ed46cadf9e3233230b8feb95d2c4afb2da41e98a56b782496929c075cdeb49776f12f6d4dbec40e2caa9476abbe8b6692744e87f18e2233036408a97d7ae05ef1c83ffdc2c5df46d11a56fa0e6225144f927056f0c533c72c24e26da617f6cf4974b48af851255dced34f83d581048a98e8d0fe056d9824666116516e5416f4a2a8437ebb938e21bb9a606fc6b1fed851569b2db162caef9eeb204bd598ec227eba20295bb699968e70649a91360cf4246f263baa4c4d29637d985eb824063816401a949d6a155ecbfeeeed7146639ca47fb51676f20bf2583e495562dda4ad095c6121b053a5d4ef9515c47e32782b41c8080eaff435d3cb57b87557d319281e009b4d2b87c47fc8493ab0e433244f171173c1c7bd2522b9cc4960d6b2e7ae7e7c03bb64fc483ee370c3bb78bbd03229d2aead9ee8d4cd882466797a305def4f9077b34350206d5909ee06e5164be9334e3bb4b3cf05a4b2d1216408d2a0853143c592247479beec0cb681813d663934de4d4fd22c32cad316ed12fa877c0c2efd882f0687a2df4cb123e4dc046de7f3e2838a1ce4c904f8088bfe607e73d96b5e311c2febc22dd9f2b8ee3dd1367eba8438af4b4612979912a8e8412acef123cec20ca8edf593c62c91b8943b8615bcba897887eca828c1ff37411562ae692eedff937333b002aa4e4d3153a836ec76ea6e385b85ca38ecc785d72b6f391cfc33c20b125b7b89faed56792ebb79b96fc2eff72783602e52b1f361256355473e215414fd7e893926a25328a67d59acdd0fd6f09a3f12780409527b9aa42b268b57a9fd0690ed723353879cf5376dca9", 0x2d4}], 0x1)


connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x8)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x5})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1021, &(0x7f0000000000), 0x4)
setsockopt$inet_opts(r0, 0x0, 0xc, &(0x7f00000000c0)="eaff125c0000e909", 0x8)


msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000000)={{0x0, 0x0, 0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x561e}, 0x0, 0x0, 0xffffffffffffffff})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
sysctl$kern(&(0x7f0000002240), 0x2, 0x0, 0x0, 0x0, 0x0)
setitimer(0x0, &(0x7f0000000000), 0x0)


open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
syz_emit_ethernet(0x0, 0x0)
openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = socket(0x18, 0x2, 0x0)
connect$unix(r0, &(0x7f0000000000)=@abs={0x682eb13985c518e6, 0x7}, 0x8)
fcntl$setstatus(r0, 0x4, 0x40)
shutdown(r0, 0x1)
r1 = socket(0x18, 0x2, 0x0)
close(r1)
r2 = socket(0x18, 0x3, 0x0)
setsockopt(r2, 0x1000000029, 0x31, &(0x7f00000000c0)="b211d7170d816685c8e360f2fa41c1a0946988b272d2dd3dc90142a84231a746e337b372e93320cff6669cbe7868de45ed3fc33719ca6df71ecec8a918458b2c10a1f8c66653b276e180e9cb9b21f9982230f575295d48889c9a920796b2dd92fc8575680b37ba955d2c15e6d7c9198ed900ab006ddfb67869b51a2216114d1ece85f593e74035f5bc054eb1dbddf42a", 0x90)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x100000000000000, 0xffffffffffffffff})
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
writev(r2, &(0x7f0000001240)=[{&(0x7f0000000240)="f0a8468fa819ad5e71a8be585f2ae642a8278564317b78a3b743b3a68a64daa9a6f3c6f09bb877ebb5e695854113c37dae52b9a28acdc6c3de65edf75d107620028e9e3222034bfc22f12273ade2fea06ba00180b581b22d4bbf9030e7a702419e4555ba924b69970c80e8cad1ec74bdf0e4d012c4ddb0faac2fab4d1beadbc73d8e33c6f1b1730bcf1f6d37953b01037c6dbe2a0cfddb69afdee5092b3b460918d483aff973cc6c5aae0db223a8a79191dd28cbd40085800d363de83d507bbee66900f19f6ff46e3ff6fc16ff3e5e88368ffb2decd3077b6fd06468d1137c1df3c1c86939a408a7378a362ae3b2c2cecdad6d8dc50c6130a6b1e38d6abde93d47d04880143f8afec24b852554da94f94652c2a4b9c089b939ddf179a96a28243025d8c8eb5e626ae398b3b7c29c9ef49cf4907b99d23b214eaf9ee3f625ef247f205070b13b332f52ba64172fffbbd8fc6d12632798c98a3aea02126a56de88e199ffe4ff47556475341c04e34587ec6ddcc16420b6cfb04cc92fc491c1c46ba92d0e4e045389c3effc8cc6709e7658557ab28e21c315cb46edca8c092279500d61386ca707986ba2bf03a8e80b0029fbe1ab6f5a77233342f2d1f5b31e5f1768b0419ede2ab832f1d4ed64329fc3fb7dfa1edaace42f8479834a4d9dbae61b3c5be768ffd3f9035216dc6e684fad65d86a75e7912e8e18ea317c505380d9c954c31e5c05ee5ab8bec432a9f69bbd9c2d3ba50a08ec3d9d22b97bc1099c2b9cc27e3e0d72c74757225b898a985fd01f05179e2f31de5ab58368212288dd39050623ecf9e8808a69424c32c08f0200c7eebd8b76abd152164df103129d5291ac8043fcba7dd5f63a33f943623c509887af66fd315f77ea0da829daa768beef2edf33cd5c1c98a18496e24e71d8553e72bd63cf981bcb166828dcf4ead7e7be78e7f4acd4916cbf37bd6860776e07c2e4f00ee2edee5a35e32b33f0ea4fea4d9e6f519c3ebac30e2fb32abca3e128dc4ffb38c2067b8f2564629c21094f0e660189b1c1108c20f0ffa4e6bae0889ebd6389fa86f465db3da9e2371f07a9af58c53a5b196f5a5e9be9c7f8e3a0f9fb126ba77d8ef25c8a6e67eefcad70fa715aa4052d2c457afd5a7d941ecf7aff6824612bbdab2be07a43b72787c35a9e157dc4e0cd81d7d33985923fb99304d54bac07b374b1b2054a", 0x356}], 0x1)


kqueue()
listen(0xffffffffffffffff, 0x0)
openat$klog(0xffffffffffffff9c, &(0x7f0000001400), 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
syz_open_pts()
syz_open_pts()
ioctl$TIOCSETAW(0xffffffffffffffff, 0x802c7415, 0x0)
syz_open_pts()
socket$inet(0x2, 0x0, 0x0)
socket$inet(0x2, 0x8003, 0x0)
syz_emit_ethernet(0x2e, &(0x7f0000000000)=ANY=[@ANYBLOB="000000000000aaaaaaaaaabb810001000806004b08f905040086dbbbba595918e0000002aafffffffffffffe7f02"])
pipe(&(0x7f0000000040))
write(0xffffffffffffffff, 0x0, 0x0)
poll(0x0, 0x0, 0x0)
openat$pf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
r0 = socket$inet(0x2, 0x2, 0x0)
socket$inet(0x2, 0x0, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000380)=[{0x3}, {0x7c}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000080)=ANY=[])


mkdir(&(0x7f0000000100)='./file0\x00', 0x49)
setreuid(0xee00, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000015c0)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000000), 0x0)
setitimer(0x0, &(0x7f0000000000)={{0x7, 0x1}, {0x8, 0x200}}, &(0x7f0000000040))
sysctl$net_inet_gre(&(0x7f0000000000)={0x4, 0x2, 0x2f, 0x1}, 0x4, 0x0, 0x0, 0x0, 0x0)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r1, 0xc2585601, &(0x7f0000000040)={0x10, 0x0, [{&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ff7000/0x9000)=nil, 0x10000}, {&(0x7f0000ff8000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil, 0x3}, {&(0x7f0000ff7000/0x4000)=nil, &(0x7f0000ff7000/0x2000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ff8000/0x2000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff8000/0x4000)=nil, &(0x7f0000c00000/0x400000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000c74000/0x4000)=nil}, {&(0x7f0000ee7000/0x4000)=nil, &(0x7f0000eda000/0x2000)=nil}, {&(0x7f0000f0a000/0x2000)=nil, &(0x7f0000d2d000/0x3000)=nil}, {&(0x7f0000d50000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000d82000/0x2000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000dbe000/0x2000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000e40000/0x1000)=nil}, {&(0x7f0000dbd000/0x4000)=nil, &(0x7f0000c2e000/0x3000)=nil}, {&(0x7f0000ff5000/0x8000)=nil, &(0x7f0000dae000/0x4000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000c19000/0x3000)=nil}], './file0\x00'})
sysctl$net_inet_tcp(&(0x7f0000000440)={0x6, 0x18}, 0x4, &(0x7f0000000480), 0x0, 0x0, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
sysctl$net_inet_gre(&(0x7f00000000c0)={0x4, 0x2, 0x2f, 0x3}, 0x4, &(0x7f0000000100)="80815d97e5e9ec42557fbfa1b208d658d9983f117a859fd619a67026beff80585ebedf283df04854cf98e456c11215a266b3c48e70351ef02e", &(0x7f0000000140)=0x39, &(0x7f00000002c0)="3d5c4fb3856c4746eb2eb0", 0xb)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000002a40)={&(0x7f0000000000), 0x10, 0x0}, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000695000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f00005fd000/0x1000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ff7000/0x3000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000545000/0x1000)=nil}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000069d000/0x4000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ff8000/0x4000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f00002f6000/0x3000)=nil, &(0x7f0000ff3000/0x2000)=nil, 0x3}], './file0\x00'})
r2 = socket(0x2, 0x2, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000180)=[{&(0x7f0000000000)="9da8e3e9ed", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
dup2(r3, r2)
sendmsg$unix(r2, &(0x7f0000002a40)={0x0, 0xffffffffffffff89, 0x0, 0x6e, 0x0, 0x700000000000000}, 0x0)


syz_emit_ethernet(0x36, &(0x7f00000001c0)={@broadcast, @broadcast, [], {@ipv4={0x800, {{0x9, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @multicast1, {[@noop, @timestamp={0x44, 0xc, 0xb4, 0x0, 0xf, [{}, {}]}]}}, @icmp}}}})


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x0, 0x0, 0x0)
r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
fchown(r0, 0x0, 0xffffffffffffffff)
open(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
execve(0x0, 0x0, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
r0 = open(0x0, 0x0, 0x0)
mmap(&(0x7f0000028000/0x4000)=nil, 0x4000, 0x0, 0x10, r0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001480)={0x0, 0x0, 0x0, 0x0, &(0x7f0000001440)=[@cred={0x20}], 0x20}, 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffb000/0x3000)=nil)
syz_open_pts()
r1 = getegid()
socketpair$unix(0x1, 0x2, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000340)={{0x402, 0x0, r1, 0x0, 0x0, 0x0, 0x401}, 0x0, 0x7, 0x2})
msgctl$IPC_SET(0x0, 0x1, 0x0)
msync(&(0x7f0000001000/0x4000)=nil, 0x4000, 0x4)
sysctl$kern(&(0x7f0000000300)={0x1, 0x48}, 0x2, 0x0, 0x0, &(0x7f0000001440)='\x00\x00\x00\x00', 0x4)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
r1 = dup(r0)
setsockopt(r1, 0x1000000029, 0xc, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000180)=[{0x5}, {0x5c}, {0x6}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000340)={'tap', 0x0})
syz_emit_ethernet(0x36, &(0x7f0000000240)=ANY=[])


connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000140)='r\x00')
open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000140)=[{0x74}, {0x40}, {0x812e}]})
syz_emit_ethernet(0x2e, &(0x7f0000000280)=ANY=[])


sysctl$vfs_nfs(&(0x7f0000000000), 0x3, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$net_inet_icmp(&(0x7f0000000000)={0x4, 0x12}, 0x4, 0x0, 0x0, 0x0, 0x0)


pipe(&(0x7f0000000100)={<r0=>0xffffffffffffffff})
fcntl$setstatus(r0, 0x4, 0xc0)
r1 = getpid()
setreuid(0xee00, 0x0)
r2 = getuid()
setreuid(0x0, r2)
fcntl$setown(r0, 0x6, r1)
setreuid(0xee00, 0x0)
close(r0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000240)=[{0x7}, {0x84}, {0x4000006}]})
write(r0, &(0x7f0000000480)="deaccd1b96ad8d8975e4a7cea4b9", 0xe)


r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0xf02, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, 0x0)
r1 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r1, 0x0)
open(&(0x7f0000000300)='.\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
mmap(&(0x7f0000003000/0x1000)=nil, 0x1000, 0x2, 0x11, r0, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x3e, 0x0)
open(&(0x7f00000001c0)='./file0\x00', 0x0, 0x0)
r0 = openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
setreuid(0xee00, 0x0)
sysctl$net_pipex(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
munmap(&(0x7f0000ff7000/0x7000)=nil, 0x7000)
mquery(&(0x7f0000ffb000/0x2000)=nil, 0x2000, 0x2, 0x0, r0, 0x0)
open$dir(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
open(0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r2, 0x8080691a, &(0x7f0000000100))


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x39, &(0x7f0000000000)="5ab7776a", 0x4)


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
getsockopt(r0, 0x0, 0xb, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x400, 0x0)
utimes(0x0, 0xffffffffffffffff)
ioctl$BIOCGETIF(r0, 0x4020426b, &(0x7f0000000200)={""/16, @ifru_addr=@in6})
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = open(&(0x7f0000000040)='./file0\x00', 0x1, 0x129)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r3 = dup(r2)
ioctl$BIOCSRTIMEOUT(r2, 0x8010426d, &(0x7f0000000000)={0x0, 0x7})
ioctl$BIOCSBLEN(r3, 0xc0044266, &(0x7f0000000100))
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
syz_extract_tcp_res(0x0, 0x0, 0x0)
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)
fcntl$setflags(0xffffffffffffffff, 0x2, 0x0)
writev(r1, 0x0, 0x18)
readv(r3, &(0x7f0000000280)=[{&(0x7f0000000180)=""/15, 0xf}, {&(0x7f00000000c0)=""/26, 0x1a}, {&(0x7f0000000240)=""/49, 0x31}, {&(0x7f0000001480)=""/4108, 0x100c}], 0x4)
pwritev(r1, &(0x7f0000000380), 0x0, 0x2000000000000002)
truncate(&(0x7f0000000140)='./file0\x00', 0x30001)
r4 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r4, 0xc0106924, &(0x7f00000001c0))
sysctl$vfs_nfs(&(0x7f0000000000)={0xa, 0x2, 0x2}, 0x3, 0x0, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000000200)=ANY=[])
r5 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r5, 0xc0206937, &(0x7f0000000140))
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)


socket$inet6(0x18, 0x3, 0x0)
sysctl$net_inet_ip(&(0x7f00000005c0)={0x4, 0x11, 0x0, 0x15}, 0x4, 0x0, 0x0, 0x0, 0x0)
socket$unix(0x1, 0x5, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
sysctl$net_inet_ip(&(0x7f0000000280)={0x4, 0x2, 0x0, 0x2}, 0x4, &(0x7f00000002c0)="d843c3a86046b09ebc7abf5d42b54457b5b1a0d533518ec35a370d21f8971922f38c947e2ecde786aeb398c5ff160b7935206378de9ba441677c2e0f0619c1ae36488c533711c1e0b31bd3240bdec61ff88ffb9dc97c903ae32985844f9f69b3c1f8c311c02ee16ddd0f6065e063d1330c076a7122b679dd4604105dc44a718ac8e5e7e3ee15e16afe369a58b606e0c8ff757509fa7323130893", &(0x7f0000000380)=0x9a, &(0x7f00000003c0)="1637bc5108be8e37989c6b2435806f03286fdd8fa7a2967d806bbc0870ca70d950398ce3001e374961a36d40f50d3a2d", 0x30)
r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
writev(r0, &(0x7f00000000c0)=[{&(0x7f0000000400)="1913371a7464fd4f5a420c4fcecaf125779f43cb3f5bb4f0a59f3947abd5b4375a1b4778a2948a3e0e7aeb5a1750e9f58481cf1391b1088d3d404d9531144aa223745ae5f0c3d3f8f36d3d433fb342b0b14b8c6b28a6c4c187e58592c9b7ccedf9fac1b8290a6ac81df213bb92983b4d1716c45a8b1efdb117230033c3554d9a56e54274d728d99e1c9163c1111619dd7f72a3a7a3ad3cadbc82f1f604dee919b666d329ade6df06c9558bb560f39095d0bd9d4f8ab1805eaa706ac6f601c79942e6912e2578132f7bb6f17f0ee74202aeab12e3e0986ac686e20baf89e031f6f071a5211e528707302b2b983c9166efecd45c47ff61bbaee124096491c37ea14b692a0ef6b6513dcea55fdc958c54aee1b672c4bec4181a2c5a06474423", 0x11e}], 0x1)
writev(r0, &(0x7f0000000280)=[{&(0x7f0000000100)="96e9cf1c159fc25ac05e6f4c", 0xc}], 0x1)
execve(0x0, 0x0, 0x0)
socket(0x18, 0x1, 0x0)
pipe2(&(0x7f0000000540)={<r1=>0xffffffffffffffff}, 0x0)
ioctl$WSKBDIO_GETDEFAULTKEYREPEAT(r1, 0x400c570a, &(0x7f0000000580))
sysctl$net_inet_tcp(0x0, 0x0, &(0x7f0000000000)="9b1809ffffffffff", 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
sysctl$net_inet_ip(&(0x7f0000000240)={0x4, 0x2, 0x0, 0x15}, 0x4, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
socket(0x0, 0x0, 0x0)
r2 = socket(0x2, 0x2, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x1, &(0x7f0000000080)="0315f1d89ec5a317a9357682", 0xc)
open$dir(0x0, 0x0, 0x40)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
kqueue()
connect$unix(r2, &(0x7f0000000000), 0x10)
write(r2, &(0x7f00000000c0)="6bbc4044635cdfa0130442359ce30f1d6397d3e99e3a21cac54252de3f31068e94599964f0992fc4f57a21f3e43840110c5aedadf534eb754e43cfefbf30d1873b41d1b6db5ac9b567031f5f94e299e42815a09a0b895be4e6fbe32bbcc6eb773fd30096f35767d120948e67b7183f75f955cebe0ab31be9a3471867737ede7592cb85a0a3fa080000009b265adc3f46c7a4790853cbcce224abc7b30926aef1d2c9497b96374901fd3f0fa136327cedf27ab77a7bd690a931e870d6576296ea83f54541af73092ebe7575a3899854202d3ae7ed09d9cb3895d29f8722ad1fc4315f2c7a83cfba586bf6cf2b232222ba0315879fcc0c5c729cbafa39551ad6d7bf1fe58fefee90cd34bebbc4ba6faf759e1647ee8384574e91bb29d971700c1f0f2b3a27263a73328833bd4bc5577fd4521ff3ce1257081533ede709c175acf59272ef759399e20f7f3ebedcdb6485ae8b72228ef2a8172601ce45147783ee8e31631baab0f9836486f8e0acb23c55df91", 0x171)


mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
setreuid(0x0, 0xee01)
ioctl$FIONREAD(r0, 0x8028698c, &(0x7f0000000000))


writev(0xffffffffffffffff, &(0x7f00000012c0)=[{&(0x7f0000000100)="07bf850fd6d2691cb0cd2fc0a7fd31e85590e334bae49b3b6e3de857c12fd0c5d6b1cc70ec59768b7898e879332a9b9fcea8f791c469abb923da6cfe9b6d0adbeba1fe4a540a5d00f03ec945c47e8ded848f89e6db5fee11c2e3331dd15079f2c82247808aac362671211ed7f17b936892ffe8047d343010e32dbd5f686f5b3221a51d5a81ee6c371bc20cf630194b8e7675000211fdf5be99562ef4a86ba729bd945899a89ebc42552d2d2ab4dffc3b63a0f704f4aa1aee2c54d5b8e3712c3994983dcbce481fe5ef295b115a307c", 0xcf}], 0x1)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f00000001c0))


rename(&(0x7f0000000280)='./file0\x00', 0x0)
r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0xd6)
writev(r0, &(0x7f00000000c0)=[{&(0x7f0000000280)='#!', 0x10}, {&(0x7f0000000000)="8d6bb85551ec8430877ae32fe9bbe42cc8f2147a3eba8e1969f0435119cf4c071c8aee7ef2921be5d7d4796c5566c95989acb3d185587234186e96b8fde9ffac51de05a87b8b893e2abd154dd886eafbe03881d25b7b13b4c32227fc9e5a86a06f59f701322b3a109a13436e486b0a", 0x6f}], 0x2)
unveil(&(0x7f00000001c0)='./file0\x00', &(0x7f0000000200)='x\x00')
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


sysctl$vm_swapencrypt(0x0, 0x0, &(0x7f0000000140)="118bea625d95de8f92c010baed45ec4bf03ace254b57973bb6de7b1c90301e9d3b5e6fb6ffffffffffffffff76c775a2a4e0556565a830032eef776127fd247103c14ab0a1cea9b4593be484f46a02ea73e910d041c5777bd852e57d3248832b91d06fe47d126022a1654859149e9486306d2f11fb1cc826c42f81b0d114f8af4ceb029a5210bb6947464bf678ba1d64a2013131fedfe60443aa13e015b28a16ea924bf89ad45c006213a6d0e194b9abcb3ddfab0c", 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r0, 0xc0206921, &(0x7f00000001c0))
r1 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8040691a, &(0x7f00000001c0))


sysctl$net_inet_carp(&(0x7f0000000000)={0x4, 0x2, 0x6c}, 0x4, 0x0, 0x0, 0x0, 0x68)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}, 0x2e0, 0x8000})
r1 = socket(0x18, 0x3, 0xfc)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r1, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
r2 = semget$private(0x0, 0x1, 0x300)
semctl$GETZCNT(r2, 0x2, 0x7, 0x0)
semctl$GETVAL(r2, 0x0, 0x5, &(0x7f0000000440)=""/206)
semop(r2, &(0x7f00000000c0)=[{}, {0x1, 0x2ff}], 0x2)
r3 = socket(0x18, 0x2, 0x0)
r4 = socket(0x18, 0x2, 0x0)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
r5 = dup2(r3, r4)
setsockopt(r5, 0x1000000029, 0x23, &(0x7f00000000c0)="b211d7170d816684c8e360f2fa41c1a0946988b272d2dd3dc90142a84231a746e337b372e93320cff6669cbe7868de45ed3fc33719ca6df71ecec8a918458b2c10a1f8c66653b276e7aae9cb9b21f9982230f575295d48889c9a920796b2dd92fc8575680b37ba955d2c15e6d7c9198ed900ab006ddfb67869b51a2216114d1ece85f5", 0x83)
sendmsg(r4, &(0x7f00000002c0)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)
r6 = semget(0x1, 0x1, 0x0)
semctl$GETALL(r6, 0x0, 0x6, &(0x7f0000000080)=""/25)
socket(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000001c0)={0x42, &(0x7f0000000100)})
r7 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r7, 0xc0106924, &(0x7f00000001c0))
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x0, &(0x7f0000000140)})
socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x8080691a, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000140)=[{0x25}, {0x40}, {0x40e}]})
syz_emit_ethernet(0xe, &(0x7f0000000100)=ANY=[])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
sysctl$kern(&(0x7f0000000000)={0x3}, 0x6, 0x0, 0x0, 0x0, 0xfffffffffffffedf)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x2802)
socket(0x11, 0x3, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000080), 0x0)
ktrace(&(0x7f0000000100)='./bus\x00', 0x1, 0x4000010e, 0x0)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000180)={&(0x7f0000000200)=[{0x8}, {}], 0x2})


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
setrlimit(0x8, &(0x7f00000003c0)={0x7, 0x9})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f00000000c0)={0x0, 0x1, 0x1, 0x820351a, "090e4de6c508a4000800"})
writev(r0, &(0x7f0000000100)=[{&(0x7f0000001340)="accd938ff3f8c1cb68a96ce24fa3215ae3f23f6ec074a99c3067fcae9884d924a039e67683007555d75474dc27b205b892df904dfcbdb8a85e40c0c760eecaf17dcdbcb6bfc9be16d49836aa3c8decfa226ceb49187a08a5fa5cb4", 0x5b}], 0x1)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000004c0)={0x3, &(0x7f00000000c0)=[{}, {0x2, 0x0, 0x0, 0x1}, {0x83, 0x0, 0x0, 0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


r0 = socket(0x18, 0x2, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r1 = socket(0x18, 0x3, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r1, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmmsg(r0, &(0x7f0000000140)={0x0}, 0x10, 0x0)
dup2(r1, r0)


getuid()
kevent(0xffffffffffffff9c, &(0x7f0000000000)=[{{0xffffffffffffff9c}, 0x0, 0x0, 0x0, 0x9}], 0x0, 0x0, 0x0, 0x0)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000000)={0x0, 0x80000000004}, 0x10)
sysctl$kern(&(0x7f0000000000)={0x1, 0x42}, 0x6, 0x0, 0x0, 0x0, 0x0)


r0 = socket$inet(0x2, 0x3, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x1024, &(0x7f0000000080), &(0x7f0000000000)=0x4)


socket$inet(0x2, 0x4000, 0x3)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
r0 = open$dir(&(0x7f0000000040)='./file0\x00', 0x2, 0x0)
madvise(&(0x7f0000000000/0xc00000)=nil, 0xc00000, 0x2)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105727, &(0x7f0000000000)={&(0x7f00000003c0)=[{}, {}, {}], 0x3})
sysctl$kern(&(0x7f0000000000)={0x1, 0x3e}, 0x3, 0x0, 0x0, &(0x7f0000000040)="3944eb3f115f79037148fa0ddc3adf427d080000006ceb99ea265a4a19b2e72fd9cbb4db32e128db447c5e01000080d5fa1d9213ebefff7ad23b886bf325280bc040eac897a0d4168da6b6b75d146499e1ee9ddeb2d68e8d011a", 0xd)
utimensat(0xffffffffffffffff, 0x0, &(0x7f0000000180), 0x1)
r1 = socket(0x18, 0x2, 0x0)
close(0xffffffffffffffff)
socket(0x0, 0x0, 0x0)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f00000000c0)={0x0, 0xfffffffffffffffe}, 0x10)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x8)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
writev(r1, &(0x7f0000000440)=[{0x0}], 0x1)
pwritev(r0, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)


ioctl$BIOCSHDRCMPLT(0xffffffffffffffff, 0x80044275, &(0x7f0000000180)=0x1)
sysctl$vm_swapencrypt(&(0x7f0000000000), 0x3, 0x0, 0x0, &(0x7f0000000180), 0x4)
semget(0x1, 0x2, 0x144)


sysctl$net_inet_tcp(&(0x7f0000000400)={0x4, 0x2, 0x6, 0x12}, 0x4, 0x0, 0x0, &(0x7f0000000140), 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x0, 0x0})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0406938, 0x0)
r1 = msgget$private(0x0, 0x0)
msgrcv(0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$FIOASYNC(0xffffffffffffffff, 0x8004667d, 0x0)
open(0x0, 0x0, 0x0)
setreuid(0xee00, 0x0)
socketpair$unix(0x1, 0x0, 0x0, &(0x7f00000015c0)={<r2=>0xffffffffffffffff})
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000140)={0x0, 0x0, <r3=>0x0}, &(0x7f0000000040)=0xc)
setegid(r3)
setgroups(0x0, 0x0)
r4 = getuid()
setreuid(0xee00, r4)
r5 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
fchdir(r5)
writev(0xffffffffffffffff, 0x0, 0x0)
dup(0xffffffffffffffff)
r6 = dup2(0xffffffffffffffff, 0xffffffffffffffff)
msgsnd(r1, &(0x7f0000001540)=ANY=[@ANYRESHEX=r6], 0x32, 0x0)


sysctl$hw(&(0x7f0000000000)={0x4, 0x1}, 0x3, 0x0, 0x0, 0x0, 0x3)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000000)=0x3, 0x4)
mprotect(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x1)
sysctl$vfs_nfs(&(0x7f0000000000), 0x3, &(0x7f00000025c0), 0x0, 0x0, 0x0)


openat$wsdisplay(0xffffffffffffff9c, 0x0, 0x40, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
mknod(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0xc0}, {0x3}, {0x16}]})
write(r0, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xe)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r1 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r1, 0x80047308, &(0x7f00000001c0))
open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x64}, {0x5}, {0x8106}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])
writev(0xffffffffffffffff, &(0x7f00000001c0)=[{0x0}, {&(0x7f0000000040)}], 0x2)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140))
socket$inet(0x2, 0x1, 0x0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
r3 = open(&(0x7f00000002c0)='./bus\x00', 0x2, 0x0)
ioctl$WSMUXIO_INJECTEVENT(r3, 0x80185760, &(0x7f0000000140))


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
writev(r0, &(0x7f0000000000)=[{&(0x7f00000002c0)='Oo', 0x2}], 0x1)


r0 = kqueue()
kevent(r0, &(0x7f0000000200)=[{{}, 0xfffffffffffffff9, 0xc7, 0x10, 0x200000000000000}], 0x200020, 0x0, 0x0, 0x0)


syz_emit_ethernet(0x23bf, &(0x7f0000000100)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaabb86dd6085ceb2ff61000000000000000000000000000000000000ff020000000000000000000000000001001d000000000000010300000001e31dd3d88e1f8a59f12d913d98105d13d89788b69a72e34bcc921389d20a071b3f7a6b75bc7aa609b48143d932edbf6f0e881f67cd0d55956c7f26ac75f6a2a89056748b9249d0d36f8d3f0b931021c871c35786c46ababc7b51a4996ff063e6259fa3dac1259cec17067b4dda84e1dfd38e49f53f576fb7e1c6704bce1bf58f0938a19d9532"])
sendmmsg(0xffffffffffffffff, &(0x7f00000007c0)={&(0x7f0000000780)={0x0, 0x0, &(0x7f0000000440)=[{&(0x7f0000000180)="b860fe09625ee6793978a575faa1b6c6c1d6c2eca2950e663d39ab1be31a269a39fd7f97e41e178f37a79f00659c2ea9ac56733f7e4e4973c1e6b326c91343ea3b3f8c5c7b93d5fe30", 0x49}], 0x1, 0x0}}, 0x10, 0x0)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f00000001c0))


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x801869a3, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000700), 0x0, 0x0)
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x70e, 0x0)
mmap(&(0x7f000000f000/0x2000)=nil, 0x2000, 0x0, 0x8010, r1, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x0, 0x0})
ioctl$BIOCGFILDROP(r0, 0x40044278, &(0x7f00000000c0))
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000240))
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000002c0))
open$dir(&(0x7f0000000080)='.\x00', 0x0, 0x0)
r2 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r3 = fcntl$dupfd(r2, 0x3, 0xffffffffffffffff)
sysctl$net_inet6_ip6(&(0x7f0000000000), 0x40000000000000c8, 0x0, 0x0, 0x0, 0x0)
ioctl$FIONREAD(r3, 0x800c745b, &(0x7f0000000080))
sendto$unix(0xffffffffffffffff, &(0x7f0000000080)="e066fe71dd54c85048a6ae968c22233da611a6ad5fcdcc0da4f05e65380e7c4b38a7e8f79747fbf6778a2124e8310d6299fad15811fa56d3dafd663879a0e3a49d494c166da97165e69ea5b87139f65c8357ce80b37ee49321c89c49c79bd5ccf3a7c6f229d492f017366bd0356fd2c3dc6b27a7419141977b3add295b237297d0d578a7acdbfe2d9509729ff1a8687a2e3a41818466c5802d986dc210fea19a3636fdf6a0a5ff67eb73a775d184bf68c3637ddd3c58cadf78f01593bb86a0ed2afec8da739ed43d541e2a5df12e16d1a71ce14a6169717e65ff1c82db550717668dfe1e356e0797c0d5204613c21b75aad6d61c8d949c85f3fe007a1fc714d30fbe12dbb318c8aed8aa85abafe3242789a90936962bd1e9614df96644808f8db96d8f991d8e23f1866c74760b608fa5803478949940be967f756a296fa1f7be4aa1ebd53cd5977be50376ddde190161a722b2e7ea7f0c1b15b648bfb9634a2bed0424a0e29447e15b227ec9ae2f80fd54", 0x171, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r4 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r4, 0x8040691a, &(0x7f00000001c0))


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000180)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
r1 = open(&(0x7f0000000080)='./file0\x00', 0x8000, 0x5c887705c9df300b)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
socketpair$unix(0x1, 0x2, 0x0, 0x0)
msgsnd(0x0, &(0x7f0000000140)=ANY=[@ANYBLOB="0300000000000000a60d524ae979b5a3e111c8cac1b119e4db1e444c9d4eca7af32596137392f4cdc50d82caa6fa7ffd0da455fa2e9f5109d4ccbe9ddd5e3674e689a6714f0ac2ee9e36ae12821cff35f5866888d441f7c29189271982efb7cd9c94766d1c4be0efcbf44d5d0010dc9df78616b167b260dd96322bfbad5f46f92beb4126cf5ffee44ca5b5bdfcf14c9b3003f53d57d96bcceb3c014f4d7b36a32f1fdb2d7783fa77ede48c3db7299ec5e58a1348d1da9304dc8bf8200a241f24ffa673bd7cb93b55b31a3045a1501250df6302a6bbfdcb68febcf98e7aabab17c9e7408bccc3081d1feec2142247dcd0e3ab8a8ab390b2a70909b2f114aa2b6ff73741b6c4c953d4fd45a49aa77d"], 0x401, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {0x0, 0x0, 0x3b8}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffb000/0x3000)=nil, 0x400000000000}, {0x0, &(0x7f0000ffd000/0x1000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffa000/0x2000)=nil, 0x7}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x80, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000280)=[{0x20}, {0x4d}, {0x6, 0xed}]})
syz_emit_ethernet(0x36, &(0x7f0000000200)=ANY=[])
r3 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r3, 0xc2585601, &(0x7f0000000000)={0x1, 0x8000, 0x1, 0x0, 0x0})
bind$unix(0xffffffffffffffff, 0x0, 0x0)
connect$unix(r0, &(0x7f00000002c0)=@abs={0x0, 0x0, 0x0}, 0x8)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
r4 = socket$inet(0x2, 0x1, 0x0)
shutdown(r4, 0x1)
connect$inet(r4, &(0x7f0000000040)={0x2, 0x1}, 0xc)
getppid()
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
setreuid(0xee00, 0x0)
getsockopt$SO_PEERCRED(r4, 0xffff, 0x1022, &(0x7f0000000280), 0xc)
r5 = getuid()
chown(&(0x7f0000000140)='./file0\x00', r5, 0x0)
socket(0x20, 0x5, 0xff)
chmod(&(0x7f0000000200)='./file0\x00', 0x1a4)
getuid()
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000180)={0x2, &(0x7f00000000c0)=[{0x4000}, {0x5}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x2c}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0xfffffffffffffef1)
fchmodat(r1, &(0x7f0000000000)='./file0\x00', 0x100, 0x4)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r1, 0x80047460, &(0x7f00000000c0)=0x6)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000340)={0xffffffec, 0x0, 0x1ff, 0x0, "474fa4d9159e7fffffffffffffffff00000500"})
writev(r0, &(0x7f0000000300)=[{&(0x7f0000000680)="dd722286aaa50f2a1300184ab8d130077c906ce85cb422a4f2c62cbd29c72c46661b4cad2da173d40b5106dd414d1529058ea57c0b83a2b5cd54ee9cd215eb90eea8e58e81e972fc5235d1cf8d6a5c2243d2bbede201ec8e6828a616309345bbac0658713001c94c8313f478fcbe0f92027aefbb1856574e8f2ed7addb58f9d79ece0c9f5d948a1c5f0e5299550d2a052c4cf3b5c367dad1cdb6830a652b7314a08179a1eb7fa04f32aabdaa403b19758aa4965d925f79692a36c3c5db606fabc956ec9138fc4ece16cdcc4f3a70ff31ceb008a2b93478c5a11b8d18574a3c007bba7764560b38077129cbce81f8ac611fbe3531e715f59336f0", 0x11a}, {&(0x7f00000029c0)="471e49aab0fd752532784bf2515fa242320b4a6e6543ffda060eb842b843d370b936ddaa7f71a0a0c4074da827c862a93983c361dc12dc50305653dd84a6adfc8761f897b60c4dee402807473103485b4475c657ae5428aa89543eec1819c76b9eb1e5c1848e49a2a588ed0f6ac77d2106b8ed9b8e3bf7a033cdd96085e372fde5a0d0e2fa622a7e28febd0934ab925ca1366c58af7e3a8eb8ff419a564f33a00db68da6ec62572fd800b44ddb72a27d384d7c0f59283172e5cffa871fbf54d432e04803f306b4bdd17a8ae02f5634de7f261bf856f7b29c4a8c1f03004f7c52f2f9e6db563bdacf11a4312b36e471badb5937dffaad3492204b136b6c7af7e032a3ca5851a267482edd7e7d92ccb87a8b65d5673815b76e9c1698ae7b1f4b5f9abdf83dd28f7ec1cfb85b91f142276afac2efbe6ca1204a2ea66c34768fde97b6e3ec499757af16215bc8f51325d653dabd4ebd4845684b1610443d845a10cbd974b2019ab2aaa364b771cdc3278d4439b96185ed0c3859ea5a4baaa391506d5bbdceb7f20da251814d96c79c641c12dee3c6c3008dea5b63a8d17dd8d567ae2ef71e10eec7343ade58044f19d750017b393a9747caa8e97186fd10cecb761f0f78928e19f8ffb6b5dfb954d1d90140f6b15bad46f9b7aaaae4fbe2f6dadf2ac7fa305306410a426f3da1198dc24f11845142715e81157342de40463eaeb5787d1f552f98f7bc8ec1477f11332e37e3705530ef8c541edf935da193d01448768fbaafb47d5eb3f82bf3ed063b7827445eab5a8fcd7d99d53b0dde5df24f8b5786d8351244164630515bc0fed985baf297cf2da41ac75f2ba68e432552f11b1d722468ffbbbe6a9ac46102969d269c43d624e218459a8db1b21cfa29109698467a1764e1f68dacfd6038037273063b89f01f1eaac9cf5dd2a8d42b1b6e4a60a373d77a7cd04d7b2b836af003812130ab23f44fcc641672be8e1c451c69e042efb361fbbf25916d4e725e9567d74ced7dd8fc1421c9119932838f3f3f3744d6e7e1c79455107178e0a968ee2f8e893781613452e0d241d0c342b0d8f869c0625dc711f82fd4b6b1ed73f62b1cb9e12bedc5fa2eaf58c969a25dbbce9fd087036ac4b95924f64111ef591d3dd0e905f3c89cabb205ab30fbfe844af7ed55b8cb1a3d4486b0cba74dab7a6c381441630966b0bdb830bf78a9677c64c62c79d165ec9562277f4782108d08240bd5f20a6ba683478ba115732d06b05c0f7eb5e8853600ce62b5a8c45b5d690dadec6b380193096ad5d18217d8dba3cd6c7902519df26cdc69b60278e57e2e70ca3e40459e3b61c295c3c23899923cc8a8745e91ec0a20d6f6e97f0fbad67600e90844f6257ca914e6e8cb5dea58a8be0939f827b9493aa6b3072e6c631a801957dca35357b4caa78b94e3faccdb887ae5c705f53765787f4440a7077baf1c4700f1d0b9c2de9602a940fa7ca022737006fae730003b66588848a757801f811710a078d2c7f91b1f66a01dadebbcd4540034aac930bac2cdffb947b6726a3b266484b0a5c94f6b80b6e432e01b8f89bab377c3f7dc878605ed50277c066aaefc75fa5bb1b4d642c651b4d46561a4eaa9b7dcea3b81fb6133fb0900c86b58f99d634bf7dd2ce3e25a5e3033419a976a476ba03bf690876b3e7c19e8c847293663cc45febc4335c19a81837e61a38b0d71951c305b63105fc9c150822cd35df33f5e459bfbd4c22f03ee3c830cc06cf37029fa9edd3da0930df6dd76775a4b91ac307c4034b1a96859507dd68b3e0befab34c62704f7cb8c44245be25f265046787e67e835a05b5ac84ca95719c50acb616369d213a8753f91c1cfd168cb128109d8de46d5add8377a795259418a03afc15647e54fb9a9c0b0757611968e9424c2848ebde24a91ef14aed1fa1879b51b131fcd441302916164af8b9ae3ce8e86b5d66d58efe5a181b4b4451a911f64267c9b46815e1b79909bea47f5e555bac2287aa1e2de031da61439a739fbc6efa2f08bb804c2f76a28680b29d881ec1404a25cad03445d4045236e3b919130c38efd90451764a9d897e91ac9058feeacb0194788279c02e757eb6ad6c3af3283ba03bd142d2032d59191b89601df69297aa05c95339f70460a68df78f44e52fe19fd2633cddd261e86d11052f6bb0a6c7cb9e9750bc540588d2108e6937bf16218efeddcf9d540c13150b1cbb911f03c0ab569a760f88f518a26798c2dbcc074d18a43d106001ee87eeb81a8bebd5c0a1c069efa9a3c0384514b455871de72160f0a898983f547c211345555d976c795fc1b05ef8706f199930ba4aa083a0642ff8dafbe9d582a4bfa09fd5c9d9ab0a17b361d141849583798f73b08f5e1a2290ec35d256a1399c5eba5cd805dac65021606753c5dcd1262eadf4d3d0af31075cfb71a1fa4dfcce346327495b898fcdebf04f7ecf7cb3aeb9fe99dee2e6734d95667f532c3a997641a53f56a9f2e082c211d4fb5f15a04142fefc1ecd89b77d371e541988cc326dc848681c8413c778962e54324ef1113e7b908558eb49a4617de12d619d16ed5a0224f728a1367d9e5a1773488d7ce986fc4208c35d8797ee3ad33b007849d98225f8003f0048707512002078305b8aa8642cf695833fdc84bb551ccc5ff920790c976a727b7972fb88f8e7272bf2450a18a5eddac6f9e8093f75f85d702307b302a54da7612d34d874bd86cf6934a3162c6745c579d279d5f62d27d0263d2f319e70d6e4d9f8376c7eb93511b07b4a588da9977c899d761811535d4b94f605e74c79a6ae820d882972ba524720e8a814d98fb778e26d7fc235b5b4a794b1244ca878a3193d48321f601d009d810c6c63e7853fa2e66661eaa1dadd55378e8c42d7d3b18996dc4af7b76cd9344dde9046b00f2c2135a71000587f22b5a8999eaabd1d3d15b1ea247f630259afeb5d3552d8b8d25353a45ea93e85f8b62a909a329007cb78d1441a3f88409c9e4a7f5e3a38b3ff8f83e5786214f4635d5602cd6305853225b133e6a44059fc6d88a3fea95b2d15d3ba3a9fa47a77d6a6b48ffe582f23c2997be60db8b496007e6cf91820657a4e10732d3471f128ea972f6b233b04d481c1a14fa32ba6601cc183f675644652d66df2b119a85d1751cd5104f77b7bc30ef503e606c5e9d1b255cc040f9f27f6b447223271a8124da64c1cb39d57c5796571529d7787859787063c3a44addc1c392267477ad30ba5ff674eca98cb2e445d458dacc6835b192e933218b4baf0ccb78228c7e3a7e3290ed3824a9cd4a9e74887bac564fc0097edf2226c38489946ec2ffc2527c9d5e26575da74d376f8080f8c56442720cb038157cbcae1ed319c2688f298b1515dec5a155a7ced1682a0c083934b6e0e806936b25e674148f39ade1d6fa5a554856dcb9984660df0de4245b70a27c8e9cbedc06423ae06ea9a27f7102113c4388befa688c8468b4e2865a94e58f3a2568211911af2aa038767fb7a05018dc45e70c33c6cbab47f81fba0c551d775ac92a1343e8dcfa61f102159adc5eefbff463be23f2278c3c7123465ae1574671ae665a91d1f80cfd9b9cf0b3edf53cc637db4ad77bd436b6bd32ea2f1032aaea3e99c30b7afe299232664b5c0d6d2f3c4d7e6a854c38937fff124977b399fb0e1566245703fbc2a6f666451602af52a979ab1b54f82b346b8e0b13c5019783e4497e6e68ff68236e8bafc37baf5e2b83ec8fb9868b8d6481db9b0e315bd554d8078be2710a7e3fab3ad15aec2062aa34bc67da31edf4bed01fe5630a0800794150856ef0db6f6b9b8e6b9a0a5a96b68d0f77fc4a3eb04cdd0a6f26590d8643b535c89288de0f81670b3f227e53d33c155b74af56ef72db01d191c9a216b48e82214b87d30b510b95dcaaf01748f8c772a271a77eaf30dbe0e3e33e3f319bbfcb4a3dc4c609c2b90f42c8c82861142a8d90c0f40304c7aa40ade9e50cce01ef6f819edd17f0ba3c8cfa225f500f3c4344700f0ee0e18b4da149ee963aac4cce9c9bea9990e20c798d717f7e8eead7c015903a408919cf3498224efc9d2b2c87cb21d3248cb8bbcf7f484fcea6ec760e301403dd65ddeb12b02070f597d48a2a93b89e21a3baac18af30e8678754e8548e573a1ccfaa2f280cf6d845e368cdb9faf5c6e6ba5414b8425ab454260acb52f5dfafacc64e83bda30b0eeb92d0bed8289ac0af11c6fb5e6bb123318fe8361159ca138e34dd85de53d0354c2ab887891dfd62081a7bd5e7ef910a3eab78110ee3cb7828416b51b2eaa3c1ce4c87ea75550e614dadc1ea104a55662c8cfa8a8562b04142d8025309372c528d2a6df1c8235d0df14e4ff5b2da06b22e68e3b62da0855ce7de35578dd1a4e39b0134acb52fb46e86960c6e8453f6bcdced3ea35e8973999c0bc300590d8bb76e48ebb1b8d960e530496f7ceacb128126ccd0341202e99368f2bea76caa9f60ee728cb1337fdfd896604cc9d80e5863067d44176ccc030503c7771123246edb4e2c18c27a601b204ff769f47b9120cb6cd61e723bee4892bb7632a5101adee58880464e6d7a56bd8eaf9b744e18ab2f72f14853ce8a9bf0fb41c5b853473a9f2b7c3a06c0558c653c0f19e5ad8598b21c3118242a226c8d63bc4584d8b1f60f3aa607d4f41547abf2535f693a6903b0d7ed40553dcb28e23d7885cc0aab8b5d0ec81bb9b1de6f3685f70dcbe591163cd4f535ac144776304a06a9c4a508c9798d3039747fd0b739eb6a0081de61ddf5ee31dede9dcc77ad35f9397e1503032697bdd022e29dba0f58675600c420174e707e8bb379e03b7410bdda2f71eecfd92c667ab9191fd1eb82d7745c84849b5a9c7a6daf10838e1b1bdbd05cd8b8f0e4b0a8c732aea7794fd3a06262abb3067a55db9e9740084af2e16587a33504abef0004f86d6fd9197419869806c99dd29ab408c8961d1467cccbbec49f51b3f597412212b849665e251b8ff963daf701e7b7dbad236e47a975b9cb6653017c2fc8db2927f06a0e8a39465db10b6b92e80ac87c00bc291b2013fee8320e1601b7866d7bf94f41cf9be7bb6612457c1c7187bc79793eea40c7a648dec22159196f9b1b27c56af83efffeb967030cccbf849f617dc143b32a49c847cf3579a91fcc2ea8d8d49fadea5462228b079acbc3c4ed37e147568492defde75bbb5f38f172a578de7053d7d7ee2cc25fb38c0a77a0fe41101da85a9f7cb8cab82e012e2867365cd02622dec5f215b2284955afcf74ccd1ef4b25bb2141155b97a0bc7037", 0xe9e}], 0x2)
writev(r0, &(0x7f0000000000)=[{&(0x7f0000000440)="4b9af7fcfcd118266599d337f3ab2855c2484c2badc135683fabf4e02113e2651449f7c04cee40ab794bd047d3a99b65d75b1ecad12e9710e9a4a16efaff6a2405e1e1cde5f1756553", 0x49}], 0x1)


open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
getgroups(0x7, &(0x7f0000000000)=[0x0, 0xffffffffffffffff, 0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0x0, <r0=>0x0])
setregid(r0, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x4, 0x538, 0x0)
ktrace(&(0x7f0000000080)='./file0\x00', 0x2, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
r1 = accept$inet6(0xffffffffffffff9c, &(0x7f0000000180), &(0x7f00000001c0)=0xc)
r2 = accept$unix(0xffffffffffffffff, &(0x7f0000000240)=@file={0x0, ""/43}, &(0x7f00000002c0)=0x2d)
fcntl$dupfd(r1, 0xa, r2)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
r3 = dup(r0)
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f00000000c0)={0x0, &(0x7f0000000040)})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
open$dir(&(0x7f0000000000)='./file0\x00', 0x200, 0x0)
select(0x40, &(0x7f0000000500)={0x3fe, 0xffffffffffffffff}, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffff9c, &(0x7f0000000500)={0x0, 0x0, &(0x7f0000000300)=[{&(0x7f0000000040)="e36957d7d559d3e6e7e8cd053418f338e3fe7cbb1916900e5c433b400479152a3a8086a3975b1bdbb2410758faba1d884b05a479be81dd462fa622d98ee42563d32dfd8538171feab4f56ca1691c62", 0x4f}], 0x1, 0x0, 0x58}, 0x0)
r4 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSKBDIO_GETDEFAULTKEYREPEAT(r4, 0x400c570a, &(0x7f0000000080))
ioctl$WSKBDIO_GETENCODINGS(r4, 0xc0105715, &(0x7f0000000080))
unlink(&(0x7f0000000080)='./file0\x00')
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x100000000000000}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r5 = socket(0x18, 0x1, 0x0)
acct(&(0x7f0000000140)='./file0\x00')
open(&(0x7f0000000040)='./file0\x00', 0x205, 0x0)
open$dir(&(0x7f0000000200)='./file0\x00', 0x20, 0x0)
r6 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r6, 0x9, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x100000002})
setsockopt(r5, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


syz_emit_ethernet(0x9c, &(0x7f0000000000)=ANY=[@ANYBLOB="aaaaaaaaaaaaffffffffffff86dd600625000066000000000000001b0000000000000000c90500000000000000000000000000000001"])


ktrace(0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
sendmmsg(r0, &(0x7f0000000000)={0x0}, 0xfffffe32, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
syz_open_pts()
poll(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSETD(r1, 0x8004741b, &(0x7f0000000140)=0x7e10a2f)
setrlimit(0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r2 = socket(0x18, 0x2, 0x0)
close(r2)
r3 = socket(0x800000018, 0x2, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r4 = socket(0x18, 0x3, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r4, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
semop(0xffffffffffffffff, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
writev(r3, &(0x7f0000001140)=[{&(0x7f0000000140)="88bcbec1d4f5f45ff1b97d9a3842269301a8aa59f0e8a8d35901555d6ed3a413950a1d8c46bac7c10adb871acc7a432be467fc46d4ea1f098b14c76997eca135415e6979f9b415aaa0f1dd5160917b028f32fc3f17b14d432f8869ee0b51d4dbc4d9c7ab75edb1e8d21a03c2f96479ad4a82a1ab6a424389a85ff9ad2f8c87ace187844fab78f56bd41f2da37ab4ab2db2bb534f3c2d0eb4b5248fb543d6d2d9351bdf9db0dc5774dc33ed16a0e438148b9973a7d2883ed7b09b6f2fef1f4264cf0c0978a4acd89a4ba1d784048600f93fd56c47c9363af1254af9078fa955ff1237189606bf2fd8836cef3b9a98208c706156af20bf19e452aa1621a71650fc6633a7ed7cd3621f629a7ed48d1c71b9e4258370c1d7ebf33a7b48c5f77d5b003c692be84498b2a92dc51656916bfed0c9b51de1820eade3d6d3ad0cc80978d7e21646ada91b308570745d4991be774a295475947d414e3833162a9c4594a015f624d8c7a22911a5014dca00f089ae29386fd91e2b2e8fecb5a5311df8e4bcc023e77cca243888673077c0996cfcf82ca67b874e71b067dbfdc544a3025de232632ff3df3a4ff5dae1e9d9082ae4a7618988fa879f58ad58682d61a515b40571f69d3a67fffc0bb7974c09e5809265e1e5d2902632005589db84367d1b2ad161aead9bd00f9a88db7079b7682ac45abfb75a73ff1e1cb26f696b497b43ef0e2670c2538c3caffb476f6b97543fb664958d5ab707d9f39c5c85622518207d965dfc17aff3dc41a6aa6e442810e825c85f1553af68bd2c253c19d38492bc54372c506bb9c24cd080183cb73163b8d65f9d4aba8c6303d522ed45737372e7bc760006e716498971a03ff1b0b163df6b28a2bea07dc8af4afc6aa656aa39d4949d443456fc1fd8f2ef9ac73dc0fe973b10a027202d50b44442147cf7e158850e31398a10f48002875a07ccdb16a5357d5f7165606f0a91889225624ad7e45afebf6c3b50336f7551417f726bf05a098f624ff49848a5a94285b31791fa3972083e466869213c9f286b2aa90927b131c657841d02fdd8fe1d4e3eff002ffb3ffc9e90db96f723dc75908ea35682ea607b0499c0e36925157a87abe2df9b8674821a33a197d35cb3b28ee7fe5de7299f2176d633685f79291732ccf5684cb8b93d25da972ee9b627ed05a8a8090f1e2adde1a88ea71ad98266b4d3c353d8d87a09d2c5d0f2a7093666f48487c348008f59765a258958d7207565dbbb3a75a9e03a6b640be989c26061f42a30bdad3ba4d36567f951377e2e86d6c66e744988071013f2b76ecdd76be4c9b288d9407216fd595b8d00a472c251bf8d1ef7785c39d69355963d271133a22e94722d4bc76e0828f8dc146f5e9e053df725a489e83ec64f853670626ddd31aab52ad82a67356b34e5c2f0b793ec060369f0eeac2a0e14f9bab410e13827f4f83027d80859e0e75e2718d51e977c89cef9bc04fb979f65edfb37fb4a692120311ef8ebc51b19d963ff0632bd065c093c696b34da035370822584cf396e13b2f3a345add0767c13fddc340b2d08d3da5d6e14f285520e3803516be13357897dad243e5ba7188ede9e601f87f981fdd2c27ae7acdc687e26b77272d57d3518c71fd31fe44a5ecea99a81b8bb5147ee869d0efdb44f6a90dc00b6d2b313844eaf9f137d9fd8025f66ad5eac43d2d1ac8ed20e25fb4c282f8cfd5f42a3492ee36291b13ed05a57c7627851f5", 0x4d1}], 0x1)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000000)=[{0x4d}, {0x24}, {0x812e}]})
sysctl$hw(&(0x7f00000001c0)={0x6, 0xf}, 0x2, 0x0, 0x0, &(0x7f0000000280), 0x0)
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])
sysctl$net_inet6_icmp6(&(0x7f00000002c0)={0x4, 0x18, 0x3a, 0xb}, 0x4, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x7fffffff, 0x0, {0x0, 0x1}})


socket(0x0, 0x0, 0x0)
r0 = syz_open_pts()
readv(r0, &(0x7f00000012c0)=[{&(0x7f0000001200)=""/1, 0x1}], 0x1)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000200)={0x0, 0x0, 0x0, 0x0, "b07b1f660000000000002000"})
syz_open_pts()


rmdir(&(0x7f00000000c0)='.\x00')
ioctl$VNDIOCCLR(0xffffffffffffffff, 0x80384601, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
rmdir(&(0x7f0000000000)='./file0\x00')
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, 0x0)
r0 = socket(0x0, 0x0, 0x0)
socket$unix(0x1, 0x0, 0x0)
listen(0xffffffffffffffff, 0x3)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
socket$inet6(0x1e, 0x0, 0xff)
r1 = open(&(0x7f0000000280)='./file0\x00', 0x10, 0x0)
chmod(0x0, 0x0)
writev(r1, &(0x7f0000000180)=[{&(0x7f00000001c0)}], 0x1)
setrlimit(0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
getgroups(0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x20, 0x200}})
r2 = socket(0x18, 0x3, 0x7)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r2, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
r3 = socket(0x18, 0x1, 0x0)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2}})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f00000000c0)=[{}, {}, {0x0, 0x0, 0x0, 0xfffffffc}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sendmsg$unix(0xffffffffffffffff, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, 0x0, 0x28}, 0x0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000004c0), 0x2, 0x0)
writev(r0, &(0x7f0000000380)=[{&(0x7f0000000180)="e741a883cc60157a810468823ac987a7254eba680c54664b8a3b537273fff1c3d4ae6950f3d030e3dc1c729ce1bb4d0e7dec57876947d3d26f8d356150f6b052bd44cc7280c8724198c173f70a712dceccc05077889f297affadcde5f1ad9e2d5363aa93bb37c6c73e0f4f8ad07537aaf9bcf3cfd30353113487589d60233184c0fd43e9f38537079fa1f0d832f277395d0802b941d2040dc8b180d9fbdc6e39334ccf08067c7cdaec5fe52f5a1c9f211fa896ff7dac6b76218c8fa7f1536311341abb6206ffda9672f479bedcb7c67ecde88e3728cb5761", 0xd8}, {&(0x7f00000005c0)='6', 0x1}], 0x2)
execve(0x0, 0x0, 0x0)


r0 = socket$unix(0x1, 0x2, 0x0)
sendmsg(0xffffffffffffffff, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000280)=ANY=[@ANYRES8, @ANYRES16=r0], 0x280}, 0x0)
recvmmsg(r0, &(0x7f0000000000)={0x0}, 0x10, 0x0, 0x0)


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
shmctl$IPC_SET(0x0, 0x1, &(0x7f0000000000)={{0x0, 0xffffffffffffffff, 0xffffffffffffffff}, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2})
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x33}, 0x5, 0x0, 0x0, &(0x7f0000000000), 0x4)
select(0x40, &(0x7f0000000040)={0xffffffffffffffff, 0x0, 0x3}, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


r0 = syz_open_pts()
ioctl$TIOCSTOP(r0, 0x2000746f)
ioctl$TIOCSTOP(r0, 0x2000746f)


writev(0xffffffffffffffff, &(0x7f0000000400), 0x1000000000000165)
r0 = open$dir(&(0x7f0000000040)='.\x00', 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
sysctl$net_inet_ip(0x0, 0x0, &(0x7f0000000100)="d7a8aac106fa1bee91c724b89283c1477dab85e783af4189a1eaf5f6e8251b1147b330f604ff639b9acd6202c9d8b1aef98ce6eefe712df21386a1f60bf4faf9867326180248fad514768c9928b74275ea8724a797051b934fc1a46677c194747c86477c2b49408ac33a50bed4dcd8d719c8e887ac6d1dca49c9ce71f944ba6751c604f18a9ce52aacbefb7d860132e72fc06c9d8f338de4eb9883b149513237c92b275cc73a320f63183363303ff9c417b6ed3f78a83a50368c9b2ce613b854c0e9bbda45c3aac729211c0bc3f3973c541cb95fa6a6696859", 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x80286987, &(0x7f00000001c0))
r2 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x80286989, &(0x7f00000001c0))
r3 = socket$unix(0x1, 0x5, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r4, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{0x28}, {0x84}, {0x4000006, 0x0, 0x0, 0x3feffe}]})
write(r4, &(0x7f0000000180)="23009100007adb020317bdda2b7e", 0xe)
sysctl$net_inet_tcp(&(0x7f0000000080)={0x4, 0x2, 0x6, 0x17}, 0x57, &(0x7f00000006c0)="46422995", &(0x7f00000000c0)=0x4, &(0x7f0000000280), 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000380)={<r5=>0xffffffffffffffff})
setsockopt$sock_linger(r5, 0xffff, 0x80, &(0x7f0000000740)={0x1ff}, 0x8)
dup2(r3, r5)
socket$inet(0x2, 0x0, 0x0)
r6 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r6, 0x8020426c, &(0x7f0000000680)={'tap', 0x0})
ioctl$BIOCSETF(r6, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f00000000c0)=[{0x64}, {0x87}, {0x26}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
sysctl$net_inet_ip(0x0, 0x0, &(0x7f0000000100)="d7a8aac106fa1bee91c724b89283c1477dab85e783af4189a1eaf5f6e8251b1147b330f604ff639b9acd6202c9d8b1aef98ce6eefe712df21386a1f60bf4faf9867326180248fad514768c9928b74275ea8724a797051b934fc1a46677c194747c86477c2b49408ac33a50bed4dcd8d719c8e887ac6d1dca49c9ce71f944ba6751c604f18a9ce52aacbefb7d860132e72fc06c9d8f338de4eb9883b149513237c92b275cc73a320f63183363303ff9c417b6ed3f78a83a50368c9b2ce613b854c0e9bbda45c3aac729211c0bc3f3973c541cb9", 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(0xffffffffffffffff, 0x80286987, &(0x7f00000001c0))
r7 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r7, 0x80286989, &(0x7f00000001c0))
symlinkat(&(0x7f0000000200)='./file1\x00', r0, &(0x7f0000000080)='./file1\x00')
unlink(&(0x7f0000000140)='./file1\x00')


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000001340)={0x3, &(0x7f00000003c0)=[{0x87}, {0x60}, {0xe}]})
write(r0, &(0x7f00000006c0)="e506000000000000004aaed75a5a", 0xe)


r0 = socket$unix(0x1, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1002, &(0x7f0000000000), 0x4)
pipe(0x0)
fsync(0xffffffffffffffff)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000002c0)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
getsockopt$sock_int(r1, 0xffff, 0x800, &(0x7f0000000780), &(0x7f00000007c0)=0x4)
msgctl$IPC_SET(0x0, 0x1, 0x0)
ioctl$WSDISPLAYIO_USEFONT(0xffffffffffffffff, 0x80585750, 0x0)
r2 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
writev(r0, &(0x7f0000000140), 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x6381)
close(0xffffffffffffffff)
ioctl$VNDIOCSET(r2, 0xc0384600, &(0x7f0000000000)={&(0x7f00000000c0)='./file0\x00', 0xc9, 0x0})
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r3 = socket(0x1, 0x2, 0x0)
r4 = kqueue()
kevent(r4, &(0x7f00000000c0), 0x8, &(0x7f0000000140), 0x7f, 0x0)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r3, 0xc0286988, &(0x7f00000001c0))
syz_open_pts()
dup2(0xffffffffffffffff, 0xffffffffffffffff)
open(&(0x7f0000000100)='./bus\x00', 0x0, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504600000000000000007000000331c13fecea10500fef9ed06c72fd3357ae320b37b673039d2d236073705ae04be38164991f7accf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139b672f4d335d223e7d029d6ba8cc630037282102000000720f70c1f5a472c881ea6e69e0bb76d907c400000200361b1257aea8c5000020020000000000008abf0909", 0x91, 0x0, 0x0, 0x0)
nanosleep(&(0x7f0000000080), 0xfffffffffffffffe)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ff7000/0x3000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000604000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f000068f000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000691000/0x2000)=nil, &(0x7f0000ff8000/0x4000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil}], './file0\x00'})
r5 = socket(0x18, 0x2, 0x0)
close(r5)
socket(0x800000018, 0x1, 0x0)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
bind$unix(r0, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
connect$unix(r0, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
getpeername(r0, 0x0, &(0x7f0000000140))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x0, 0x0)
getuid()
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
geteuid()
getgid()
socket(0x0, 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r1 = socket(0x18, 0x3, 0x3a)
setsockopt(r1, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r1, 0x29, 0x66, &(0x7f0000000100)={0x0, 0x0, 0x0, 0x1}, 0xc)
r2 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000080)="eaef125c00000000", 0x8)
dup2(r0, r1)


r0 = socket$inet(0x2, 0x3, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x1003, &(0x7f00000002c0), &(0x7f0000000180)=0x4)


mknod(&(0x7f0000000000)='./bus\x00', 0x3a0914c44f7b202d, 0x504)
open(&(0x7f0000000040)='./bus\x00', 0x10005, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
socket$inet(0x2, 0x0, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x15, &(0x7f0000000240), 0x0)


mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x205b1a)
r0 = open(&(0x7f0000000080)='./bus\x00', 0x2, 0x0)
pwritev(r0, &(0x7f0000001840)=[{0x0, 0x5b}, {0x0}, {0x0}, {0x0, 0x4c}, {0x0}, {0x0}, {0x0}, {0x0}, {0x0}], 0x9, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000080)=[{0x1}, {0x34, 0x0, 0x0, 0x3}, {0x8106}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


r0 = open(&(0x7f0000001180)='./file0\x00', 0x0, 0x130)
mkdirat(r0, &(0x7f0000000340)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38/\x00', 0x0)
r1 = socket(0x2, 0x3, 0x0)
getsockopt(r1, 0x0, 0x0, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
mkdir(0x0, 0x0)
chdir(0x0)
symlink(0x0, 0x0)
semget$private(0x0, 0x0, 0x0)
rename(0x0, 0x0)
mlock(&(0x7f0000ffa000/0x4000)=nil, 0x4000)
munlock(&(0x7f0000ffc000/0x4000)=nil, 0x4000)


syz_extract_tcp_res$synack(0x0, 0x1, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{0x1, 0x0, 0x0, 0x1000}, {0x50}, {0x6}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x54da)
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
sendto$unix(0xffffffffffffff9c, &(0x7f0000000000)="b10005160000000000000000070000001a5113fecea10500fef96ecfc72fd3357a89583535673039d2d236acf20b7804be38164991f7c8cf5f882b2900e1aa5b23edebc8ef99a8ad491726fa8251e2f0ac3ebbc2feb3fda1139b672f4d3353eb06acdb35a069d7080000000000000000008904000000000022830cf41bed66f4f365ccdcf3e4999d9d20002002", 0x8d, 0x0, 0x0, 0x0)
sendmsg(0xffffffffffffffff, &(0x7f0000000240)={&(0x7f0000000080)=@in={0x2, 0x1}, 0xc, 0x0, 0x0, 0x0}, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x2000000000, 0xffffffffffffffff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendmsg$unix(r0, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x3, 0x1)
connect$unix(r0, &(0x7f0000000000), 0x10)
sendto$inet(r0, 0x0, 0x0, 0x0, 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{0x0, 0x10, 0x0, 0x201}, {0x7, 0x0, 0x80, 0x1}, {0xfbff, 0x0, 0xbd}]})
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000)=@un=@abs={0x0, 0xd}, 0x10)
listen(r0, 0x0)
r1 = socket(0x2, 0x1, 0x0)
connect$unix(r1, &(0x7f0000000000), 0x10)
listen(r0, 0x0)


r0 = syz_open_pts()
close(r0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000000)="ebffcbff13", 0x5)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x138, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x2, 0x2, 0x0)
r2 = semget$private(0x0, 0x4000000009, 0x82)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000380)={{0x7fffffff, 0x0, 0x0, 0x0, 0x0, 0x44, 0x7fc}, 0x80000000, 0x3, 0x0, 0x0, 0x7, 0x26c3, 0x1009, 0x2})
semop(r2, &(0x7f00000002c0)=[{0x0, 0x0, 0x1800}, {0x2, 0x1f}, {0x1, 0x4, 0x1800}, {0x0, 0xe5f1}, {0x0, 0xffd, 0x1000}, {0x4, 0x53, 0x1000}, {0x2, 0x2, 0x1000}, {0x2, 0x0, 0x800}, {0x2, 0xfffd}, {0x0, 0x9, 0x1800}], 0xa)
semop(r2, &(0x7f0000000440)=[{0x3, 0x0, 0x1c00}, {0x2, 0x95}, {0x0, 0x3ff, 0x400}, {0x0, 0xb10, 0x1800}], 0x4)
semctl$SETALL(r2, 0x0, 0x9, &(0x7f0000000040))
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000280)={<r3=>0x0, <r4=>0x0}, 0xc)
r5 = getgid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000140)={{0x4, r4, 0x0, 0x0, r5, 0x1, 0x8000}, 0x3fd, 0x2, r3, 0x0, 0x744, 0x3, 0xa, 0x2})
semctl$IPC_SET(r2, 0x0, 0x1, &(0x7f00000001c0)={{0x39c5, 0x0, 0x0, 0x0, r5, 0x5c, 0x101}, 0x40, 0x800, 0xff})
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000580)={0x0, 0x0, <r6=>0x0}, &(0x7f0000000240)=0xc)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f00000004c0)={<r7=>0x0}, 0xc)
shmctl$IPC_SET(0x0, 0x1, &(0x7f0000000500)={{0x1e, 0x0, r5, 0x0, r6, 0x0, 0x1}, 0x8, 0x4003, r7, 0x0, 0xfffffffffffffffc, 0x3, 0x81})
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000080)={<r8=>0x0}, &(0x7f0000000300)=0xc)
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000005c0)={{0xe6, 0x0, 0x0, 0x0, r5, 0x1, 0x7ff}, 0x9, 0x8, 0x0, r8, 0x3f4, 0x3, 0x7, 0x9})
setuid(0x0)
connect$unix(r1, &(0x7f0000000000), 0x10)
sendmsg$unix(r1, &(0x7f0000002a40)={0x0, 0x0, 0x0}, 0x0)
r9 = syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047466, &(0x7f0000000200)=0x5)
poll(&(0x7f0000000040)=[{}, {r0, 0x40}], 0x2, 0x0)
fchdir(r9)
ioctl$TIOCSBRK(r9, 0x2000747b)


syz_emit_ethernet(0x1c, 0x0)
poll(&(0x7f0000000200)=[{}], 0x1, 0x87e)
r0 = open(&(0x7f0000001440)='./file0\x00', 0x615, 0x0)
poll(&(0x7f0000000000)=[{}], 0x1, 0x8001)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x10, r0, 0x0)
ftruncate(r0, 0x25b3)
execve(0x0, 0x0, 0x0)


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)='\x00', 0x1}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
setsockopt$inet_opts(r0, 0x0, 0xd, 0x0, 0x0)


setreuid(0xee00, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x205310)
r0 = open(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000080)=[{}, {}], 0x2})
r1 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_GETPARAMS(r1, 0x80105727, &(0x7f00000000c0)={&(0x7f0000000140)=[{0x5}], 0x1})
fcntl$getown(r0, 0x5)
r2 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
getuid()
fchown(r2, 0x0, 0xffffffffffffffff)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
open$dir(&(0x7f0000000b80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x200, 0xad6570f09f9216f1)
r3 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000300)='./file0\x00', r3, &(0x7f0000000c80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f0000000dc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', r3, &(0x7f0000000ec0)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mkdirat(r3, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
symlinkat(&(0x7f0000000480)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', r3, &(0x7f0000000700)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000980)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000001280)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


sysctl$kern(0x0, 0x0, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afe", 0x0, 0x0, 0x0)
semop(0x0, &(0x7f0000000100), 0x0)
msgget(0x2, 0x710)
socketpair(0x1, 0x5, 0x0, &(0x7f0000000380)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r2 = socket(0x18, 0x0, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r3 = socket(0x18, 0x3, 0x0)
dup2(r3, r2)
connect$unix(r1, &(0x7f00000002c0)=@file={0x1, './file0\x00'}, 0xa)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000000), &(0x7f0000000080)=0xc)
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x6d4)
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x40000802)
r4 = open(&(0x7f0000000100)='./file0\x00', 0x8, 0x140)
ioctl$TIOCSETD(r4, 0x8004741b, &(0x7f0000000140)=0x7)
r5 = socket$unix(0x1, 0x1, 0x0)
connect$unix(r5, &(0x7f00000000c0)=@file={0x0, './bus/file0\x00'}, 0xe)
r6 = socket(0x11, 0x3, 0x0)
open$dir(&(0x7f0000000240)='./bus\x00', 0x400, 0x0)
getsockopt(r6, 0x11, 0x4, 0x0, 0x0)
close(r4)
sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000000)="9b1809ffffffffffffff7f473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6fd74c94d1b44", &(0x7f0000000040)=0x10011, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSDLT(r0, 0x8004427a, &(0x7f0000000000)=0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000001200)={0x3, &(0x7f0000000000)=[{0x24}, {0x80}, {0x8106}]})
syz_emit_ethernet(0x36, &(0x7f0000000240)=ANY=[])


rmdir(&(0x7f00000000c0)='.\x00')
ioctl$VNDIOCCLR(0xffffffffffffffff, 0x80384601, &(0x7f0000000080)={&(0x7f0000000000)='./file0\x00', 0xfff, &(0x7f0000000040)='./file0\x00', 0x8})
sysctl$kern(0x0, 0x0, 0x0, &(0x7f0000000440), 0x0, 0x0)
rmdir(&(0x7f0000000000)='./file0\x00')
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, 0x0)
r0 = socket(0x0, 0x0, 0x0)
r1 = socket$unix(0x1, 0x0, 0x0)
listen(r1, 0x0)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
socket$inet6(0x1e, 0x0, 0xff)
r2 = open(&(0x7f0000000280)='./file0\x00', 0x10, 0x0)
chmod(0x0, 0x0)
writev(r2, &(0x7f0000000180)=[{&(0x7f00000001c0)}], 0x1)
setrlimit(0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
getgroups(0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x20, 0x200}})
r3 = socket(0x18, 0x3, 0x7)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r3, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r4 = socket(0x18, 0x1, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
sysctl$kern(&(0x7f0000000040)={0x1, 0xa}, 0x2, 0x0, 0x0, &(0x7f0000001440)="cc", 0x1)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000100)={0x0, 0x0, 0x1, 0xfffffff7, "f546db7a3d1f691a1c0000000000d700"})
ioctl$TIOCSTOP(r1, 0x2000746f)
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)


sysctl$kern(&(0x7f00000000c0)={0x1, 0x3e}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


poll(0x0, 0x0, 0x0)
socket(0x18, 0x3, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000040), &(0x7f0000000100)=0xc)
r1 = socket(0x2, 0x4001, 0x0)
dup(r1)
ktrace(&(0x7f0000000280)='./file0\x00', 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x80206916, &(0x7f00000001c0))
r3 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000080), 0x2, 0x0)
ioctl$WSMOUSEIO_SCALIBCOORDS(r3, 0x81205724, &(0x7f0000000540)={0xffffffff, 0xffffffff, 0xffffffff, 0x56, 0x0, 0xbc, 0x80000000, 0x10, [{0x1257, 0x9, 0x1, 0x3}, {0x800, 0x3, 0x7, 0x2}, {0x9, 0x0, 0x406, 0x2}, {0x0, 0x3f, 0x9, 0xffffffc1}, {0x80, 0xfffffff8, 0x6, 0x6}, {0x25fe, 0x810, 0x10001, 0x4002}, {0x7, 0x800, 0x361, 0x2}, {0x3ff, 0xf7f0, 0x2, 0x4000000}, {0x101, 0x63, 0x1, 0x1}, {0x800, 0x1000, 0x0, 0x9}, {0x4, 0x4, 0x40}, {0x9, 0x101}, {0x155c, 0xfff, 0x8, 0xc73}, {0x7fff, 0xffffffff, 0x5, 0xfff}, {0x8, 0x14f9, 0x5, 0x7}, {0xbe01, 0x5ff, 0x4, 0xeb0}]})
r4 = socket(0x10, 0x4, 0x0)
listen(r4, 0x0)
mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
setreuid(0xee00, 0x0)
r5 = open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
r6 = getuid()
fchown(r5, r6, 0xffffffffffffffff)
setreuid(0x0, r6)
fchdir(r5)
close(r1)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000300)="9b0209c3eb987ab7fe4189c99e805e6e84d356960798a692992117d6728436ba1bd87f42e3303eac3846528d050712f838130efce33f523ba44765f5f6915b0227390ed95bd9dc6d4dc7e149d4d6d06a3f23616e773302d9cae75e39a5a11e32e0e6ebd635450b2eba540af7f2aa5dbfbdd900a0dad2b74f50acd76b5c567049ef436dbea0d7562f52950fa5ef6e84c513252ddd8680a944d5c2bd02adc7f1fe850c00000000000000062ab475cca257352828a76e5334be562995e894238b96ca5d4d3e670feac9b4e8aa9bef19525cb6f7e8570b2a374f1400041ed45bb7ad3fe963cb9a8bd949ee0fc6dbceb7d956015947b3e88aa810f8ed7cca10ff010000000000001345daa49507756f49775275ca390b94e85d5a95b8bdacb9429c25483a9275d0da3b561c6adc3c141f26a88016dd6b436218bdbdc9ac0a623855e941dc1872fcb045e0d9df1ecc6357ee21e2b0802cb60eec6add5e94723235f06715e7eecc3e0760c70e1dd7873e27142bbae1a7e44de453a073fe3426f334b80f043ba9136d57c799353d46dd81439b111a511a288bee5dfb2e353e3bb073e3342273216b07e49ca4df0fd2dbe9a8eb377010ee678aad0bd8e9fb7d82693a096344671843a1f2082612b0ff237c6e505ff5f5ba932954d73c630fdb791f833a1da5af0704f687e196f4f7859e071fc98111cc9024f790ce16ceaa7d0104e39789d9100000010000000000050000000000", &(0x7f00000002c0)=0x210, 0x0, 0x0)


syz_emit_ethernet(0x4f, &(0x7f00000001c0)={@local, @random="5dc7de2dcc96", [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x41, 0x0, 0x7733}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}, {"d1c2f0bfe2d0786ca28e44289f59aba04d62ff16e6bb47f1cd"}}}}}})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000001200)={0x3, &(0x7f0000000000)=[{0x24}, {}, {0x8106}]})
syz_emit_ethernet(0x36, &(0x7f0000000240)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
dup(r0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f00000000c0)={0x4, &(0x7f0000000240)=[{0x887}, {0x5c}, {0x4000006, 0x0, 0x0, 0x40000}, {0x1, 0x40, 0x9, 0x1}]})
write(r1, &(0x7f0000000100)="00a1f50e000000000000f9120000", 0xe)
r2 = socket(0x18, 0x400000002, 0x0)
setsockopt(r2, 0x1000000029, 0x2e, 0x0, 0x0)
getsockopt(r2, 0x29, 0x3d, 0x0, 0x0)
setsockopt(r2, 0x8, 0x0, &(0x7f0000000cc0)="e48bdba721c69546f85a53d9d640a2c8bb6e77e352534873d47ac8e3a89294825f6f524e8781c4340046f787639d221fec5f5199b954c1d486f02439b9d2b91a318622a275430096a580979b84c04118b65d9a273d855e658d833996811e94e6a9117a76f8b9939eb1841577087d235a4f6c3e09cb0cb375bd0037447fa5daf3cf970259600abc51d326001adefab0f656749166b5f2913cfee01845bbb472de878590d940bf53671c", 0xa9)
socketpair(0x6, 0x1, 0x4, &(0x7f0000000a00)={<r3=>0xffffffffffffffff})
connect$unix(r3, &(0x7f0000000c00)=@abs={0x0, 0x0, 0x0}, 0x8)
pipe(&(0x7f0000000040)={0xffffffffffffffff, <r4=>0xffffffffffffffff})
writev(r4, &(0x7f0000000280)=[{&(0x7f00000002c0)="547f5667bf2245c63c7236470b6c6dcff4a1499400000000000000218e6c070045badef27c9edb1941d7f2e8a7e74fa53604520fb47369de62326c5707071f8d206a70f8abfcfd2c60fd2d5fab483893018a504316f5b361b3fc2452826242ba4f5ca3d4fc7ce832d01a0748c14e896405757b2958075c6f066a9881d8bfbd986844dad2a62fca504b816f385e562d9e3dca43ae762ebccca567bfb249ec96caeb7fb32eb6c3abeb5435a3", 0xab}], 0x1)
dup(r4)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCGETIF(r1, 0x4020426b, &(0x7f0000000140))
socketpair(0x0, 0x4000, 0x6, &(0x7f0000000080)={0xffffffffffffffff, <r5=>0xffffffffffffffff})
fcntl$getflags(r5, 0x3)
getsockopt$sock_int(r5, 0xffff, 0x10, &(0x7f00000001c0), &(0x7f0000000200)=0x4)
munmap(&(0x7f0000001000/0x2000)=nil, 0x2000)
r6 = shmget$private(0x0, 0x1000, 0x0, &(0x7f0000003000/0x1000)=nil)
shmat(r6, &(0x7f0000002000/0x1000)=nil, 0x0)
munmap(&(0x7f0000002000/0x1000)=nil, 0x1000)
r7 = shmget$private(0x0, 0x1000, 0x0, &(0x7f0000003000/0x1000)=nil)
r8 = shmat(r7, &(0x7f0000002000/0x1000)=nil, 0x0)
shmdt(r8)
shmdt(r8)


r0 = socket(0x18, 0x1, 0x0)
ioctl$VNDIOCSET(0xffffffffffffffff, 0x41946465, 0x0)
sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000000)="9b1809ffffffffffffff7f473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6fd74c94d1b44", &(0x7f0000000040)=0x10011, 0x0, 0x0)
r1 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x10, 0x0)
mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x4, 0x10, r1, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x1)
ioctl$FIONBIO(r1, 0x8004667e, &(0x7f0000001180))
mprotect(&(0x7f0000ffb000/0x1000)=nil, 0x1000, 0x0)
ioctl$WSDISPLAYIO_GBURNER(0xffffffffffffffff, 0x400c5752, 0x0)
munmap(&(0x7f0000ffc000/0x1000)=nil, 0x1000)
shutdown(r0, 0x1)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff}})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7, 0x3}, 0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x1, 0x1, 0x0)
close(r2)
r3 = socket(0x18, 0x2, 0x0)
setsockopt(r3, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendto$inet(r2, &(0x7f0000000bc0)="2117cecd05058af5fbce692fb209c0a9047b41d6e3ae771b0ad4031990ec2e2dde0df1fdf6e6a6be5dd94d4f404a8a50ec891bd907fcf8cd4339a97014ee830ec9fb5289f68bd993ae017c359e2f2b656c164c662350cfd3dc778b43352b22c8bc6d9163fa7f245783877b4e079b27ae9b51327132faae536f9006c5d632ae323eb4fc169738c872d524c2cc8451eeef5aca89298580c2e9377d2e967a8e32c5352db2ae293fb6081ab052d1ef19c73c38f4ebdb48d8e2d08e865f9ce0cc5a45beb520e2f24582721811d7c25b3461f53e71f78f0104a532cefe4b2299d4c9196b2cf30629cbfc65a076962ca893ed597e1f55786b272f2d7ec734925f6f7f7c17dea858469f89e90f45ae03aefcd7906d950160f0a2206e16fc0ad156ce8c3bca6f8a55ab64a15cf548868d091d26c6cb0b000000000000067b04680f4b84734717c23165cb1a5557d6b75fc53c723deddea0e49c8776cbe8dcdfea616e86825bfb31f2b22f368aae1f287d3ddc0aa878bb1a13559b248d12bcce19914ef04299699fee55cb48ca16b7eecc0c4dc9ec7768afb4ce3638266fbad4b8de0d796ca7b0b57ac809608bddc34ddbf2dfd588d3628aa6783c41cbca4e7c9b4a94a67e050010ea1888e3757edb45c7dd184b4aa7c6601fc222f436f9e93a86ccba0b9a8f495840139999fe411afc67ef1bb6734d62a032ba20f695740993d3700849409940728e393b64aa6aa5ebd4caebd7832e3af32b6a9b77f70c4e168d5ac0f0a9f90bbe93dfdb0f017ddc752b08ec6d29f6b8886686e2132917a04fb3bfa11c5820406352788a1b4ec9486508bdf4a3053e02f8195ad4011a8272807ef271e59355bcaca5e9277d7299520c91f322178bfd9cd215a0294b415eb239b96a6b09e8b66ab911f9fb5981675f0b0f641c9fdcccb442a7eb4e998b03c02803ba8f5b93e7c9f1a53fa8cae728ecf072e80973e682f317d9cb97dd3d036907830714a791f665c684269c93c552459c8336724342d0387142e5c6dc530584a01bfa8b4a8affa4ddf7578a95c95abcb5bed8baa966651872dec1d582d17c6fb077f621e0eca00010ca7170281046c7db83ed38448234841cbb661c0cf331ca42cca0253195394e1ce570ed0d9008e31171c2bcb62f1af19abf97840ede00c8fe0f00d205d955e9bfb1328348b4a0adccf847adfa9a7875b8ce79a8b79a16fddbc4773d70bae3e75b3eb8e4bd105f31762e7bca015329561c9d480a95936fa42362607f5de2fa87f27d7a4286418f661771ac5cf9ce11ff861094933e5ffd6bc81b5ae88fe6f38ee5a77305a3f161bb20ed402ccd487288ae8e2db673b2c307d652e16f8bcfe2b4e6c90801228b5c2be7446011bd1f4d10781b204a2aa581215f2ed227b5dcab7026c70e2d90f30af451ac69c478c2f2af58ac2e90b104842f7594cc522750161b933ae722606094c94aa256cbaab34f2aa78907b33bf25fc262261893b64a83446e34444a918bce76921fe4ec70d85c996edf0864230779436add2bcd5646797331ad5931824ff8fd30ee2ab745533bf61c79d12818bcbd34803d0090ed93dbea03f20ade53223f02d1a6b04fc09ef5d612c6da30dbca5e75bed1ef6b73fb5ee7eafc78580b126fe4cf2c4ecda8539b83ee785f8e6c9de1de1ad612c8b5190e7451fe9bb0e207a86373860ffdedcde9eca7407c741f2664e23a125f25c023041e2d98b5ab290d05d098c974f9fa896bb4c987f35342813d96e451b06afa738a0621711779cc91058c30c34b71038190ed171100a8b994b333f70b3cc457608be4549854f87cd9f075a25d9e4039a9442df45ed2c45f63ca9c4d51b7fe5da01815afcd269a788e38fc4599985bd68782f58754fb209d970f6f928cab2f77707d3991c66a9d2e7ec42f014297d433bc5feb51f383db02febea974260f0aa3e5534cc18ee9fa395f8499b76e7544132218f8a66a0e16d284ed82ce72cbe1e5faed12bc82b3e8c0e4ad6fe6808da69b8eecf9a7818086360cdb6ef4d0fe54a6fe3d5a3420fba7420d4baed661840d632d8fc743cba7534bf8048327ebc380b8d0b4452b5f243a847e57da11b5dd6079ea7a21bb75a24b3e98b12832f849d2dbf5105e3143c97a94d1e7540790aea9390b731017b60555d9cafdcea78aabda58f70f76958b16b9991a50200037380a0dc9e83973824ec8ab3ce0c6c783cc290f1b5e2af7fc60f44fbc8fb1e0ad63741eaab19131d0185040f9af984314c04d3781f7a9bc95828c14a88b601bfb5023f16a1fd5e6bf561ba2b3ad3ac4ce95be2549d7f3263915e43c97c8094ccbf1babef210fad5c84125ed9821e6bfd0012b8f9667872ceab4a0a1a1fb7fa1b35f3bba42935cf1c5e7d7f03a27184d124ee4ec14011ea600b303d62f0a0b5c1e8743a7e2f559d4064814640041ccebd6f272a13f1893b94da9fa758bfbd629d83a1fada7c60b0690ff04e3f316ab0021505cd7d1641d34ceae5eae7d815481c6f2267678ffd791d1361875af012b1a5963c34880c40fb367e85d812d7155b78798a841e4b7b611ff35dffdfc8ae6805df82e12e815d1292d78d5b00c78903b7cc7b27bd027b1eb50a2758c52740390175de8a8b1d3024849e4e24686df5b7589c4cfc86f0fbad23d3b21c8db836c58c0a8837c4e746e3ab7cff593284f98620ece686977cb52f8fd74470634165b03c94e5ad707c0c8fb62b9b326946780572bd8b3118beedb280b51005ff04a0ee80cfedc05fcb39a1f72f919eb4143857fc7724b3a714a4a875997e9e4d3241bd155b120d98f2daa50be996978b007", 0x7c9, 0x0, 0x0, 0x0)
close(r1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000080)=[{0x6c}, {0x61}, {0xe6}]})
syz_emit_ethernet(0x3e, &(0x7f00000001c0)=ANY=[])


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f0000000080)={0x10, 0x0, [{&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffb000/0x5000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000800000/0x800000)=nil, &(0x7f0000d91000/0x4000)=nil}, {&(0x7f0000f56000/0x1000)=nil, &(0x7f00008fb000/0x2000)=nil}, {&(0x7f0000e4c000/0x4000)=nil, &(0x7f0000efd000/0x1000)=nil}, {&(0x7f0000cd3000/0x1000)=nil, &(0x7f0000862000/0x2000)=nil}, {&(0x7f0000d3d000/0x4000)=nil, &(0x7f0000aff000/0x1000)=nil}, {&(0x7f0000f6a000/0x2000)=nil, &(0x7f0000887000/0x4000)=nil}, {&(0x7f0000da1000/0x4000)=nil, &(0x7f0000b4b000/0x3000)=nil}, {&(0x7f0000e0f000/0x2000)=nil, &(0x7f0000e03000/0x3000)=nil, 0x100000001}, {&(0x7f0000c64000/0x14000)=nil, &(0x7f0000d93000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000bd7000/0x4000)=nil}, {&(0x7f0000913000/0x2000)=nil, &(0x7f0000c5e000/0x4000)=nil}], './file0\x00'})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106978, &(0x7f00000001c0))


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
openat$wskbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
poll(0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
socket(0x18, 0x3, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000000029, 0xb, &(0x7f0000000000)="ec000087", 0x4)
ioctl$WSKBDIO_COMPLEXBELL(0xffffffffffffffff, 0x80105702, &(0x7f0000000080)={0x1, 0x6, 0x400, 0x9})
r0 = dup(0xffffffffffffffff)
sysctl$vfs_ffs(&(0x7f0000000000)={0x4}, 0x3, 0x0, 0x0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSRTIMEOUT(r0, 0x8010426d, 0x0)
fcntl$setstatus(r1, 0x4, 0x4)
pipe2(0x0, 0x0)
ioctl$BIOCSBLEN(0xffffffffffffffff, 0xc0044266, &(0x7f0000000100))
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
syz_open_pts()
open(0x0, 0x8, 0x0)
ioctl$FIOSETOWN(0xffffffffffffffff, 0x8004667c, &(0x7f00000000c0))
setrlimit(0x5, 0x0)
syz_open_pts()
close(0xffffffffffffffff)
clock_gettime(0x3bd70b3292b7004, 0x0)


sysctl$net_inet6_icmp6(&(0x7f0000000080)={0x4, 0x18, 0x3a, 0x3}, 0x4, 0x0, 0x0, &(0x7f0000000440)="b3993782", 0x4)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg$unix(r1, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="28000000ffff000001"], 0x28}, 0x0)
recvmmsg(r0, &(0x7f0000000000)={0x0}, 0x10, 0x0, 0x0)
r2 = dup2(r0, r1)
read(r2, &(0x7f0000000040)=""/102, 0x66)


syz_emit_ethernet(0x17a, &(0x7f00000000c0)=ANY=[@ANYBLOB="f3a2a8908a86aaaaaaaaaabb86dd601ab5b600003c0000000000000000000000000000000000ff"])


recvmmsg(0xffffffffffffffff, 0x0, 0x2, 0x0, &(0x7f0000000100)={0x0, 0x301d0bcd})
writev(0xffffffffffffffff, &(0x7f0000000040), 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
r0 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x1, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$WSMUXIO_INJECTEVENT(r0, 0x80047476, &(0x7f0000000000))
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x18}, 0x4, &(0x7f0000000040), 0x0, &(0x7f0000000100), 0x0)
sysctl$net_inet_carp(&(0x7f0000000080)={0x4, 0x2, 0x70, 0x1}, 0x4, &(0x7f0000000140), &(0x7f00000000c0), &(0x7f0000000240), 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
chdir(0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x7}, {0x20}, {0x4000006, 0x0, 0x0, 0x7f}]})
write(r0, &(0x7f00000002c0)="c5449bc1708e16b9805a099e20a0", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000240)=[{0x87}, {0x4}, {0x3786}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])


mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x205b1a)
r0 = open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)
fcntl$setstatus(r0, 0x4, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = socket(0x11, 0x3, 0x0)
sysctl$vfs_ffs(&(0x7f0000000000)={0x4, 0x1, 0x5}, 0x3, 0x0, 0x0, 0x0, 0x0)
sendto$unix(r0, &(0x7f0000000280)="b1000501600000000000000007000000331c13fecea10500fef96ecfc72fd3357ae320b37b673039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa5b236deb51e2f0ac3ebbc2576b9a5f139b672f4d335d223e7d026ba8af630037002102000000720fd38bfbb770c1f5a872c881ea6e69e0bb76d907c400000200361b1257aea8c500002002fb00000000008ad20300000000ec1d89e000040781e4b2fff040ff00"/177, 0xb1, 0x4, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
r1 = socket(0x18, 0x0, 0x0)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f00000000c0)="ebb7111656fafbcbff13b9fd812eaa4e713048e6", 0x14)
setsockopt(r1, 0x1000000029, 0x0, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r1, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r2 = socket(0x18, 0x2, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r3 = socket(0x18, 0x3, 0x0)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r3, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
r4 = socket(0x18, 0x1, 0x0)
setsockopt(r4, 0x1000000000029, 0x3d, &(0x7f0000000380), 0x0)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
connect$unix(r2, &(0x7f00000001c0)=@file={0x1, './file0\x00'}, 0xa)
write(0xffffffffffffffff, 0x0, 0x0)
pipe(0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
r5 = getuid()
getpgid(0x0)
msgctl$IPC_SET(0xffffffffffffffff, 0x1, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000240)={0x0, <r6=>0x0}, 0xc)
setreuid(r5, r6)


ioctl$VMM_IOC_RUN(0xffffffffffffffff, 0xc2585601, &(0x7f0000000000)={0x0, 0x0, 0x1, 0x0, 0x0})
sysctl$vm(&(0x7f0000000000)={0x4, 0x1}, 0x3, &(0x7f0000000040)="c06d154be3aee5f8787f8b9cda7554335b763bb5deea5ccecb4d1b57a9f6fa18e47fc7b119db587e58811e666e84a806495b45c36164bd5b135280243ed0a01466056e93082876ba33ee8cf2b0b3907f236f38175101000000d7e39544aea098d19ee63d03cbf92380dbe904538135f09e408bbe17a54a364b04ee64b0ad54e6d4e38114ced38c328aff2e224239ba29eb0796e8c3e8344a2cd9e663bb21035ebf391872f3015c164556e4a5b966122c56edd85fc996f12fa1b92e47aa", 0x0, 0x0, 0xfffffffffffffd74)


syz_emit_ethernet(0x56, &(0x7f00000000c0)=ANY=[@ANYBLOB="89ffa23f3c252adb0070162e86dd6009000000200600030000000000000037f87c"])
r0 = socket(0x2, 0x2, 0x0)
r1 = socket(0x2, 0x400000000002, 0x0)
setsockopt(r1, 0x0, 0x21, &(0x7f0000000180)="b1f5d915", 0x4)
r2 = dup2(r1, r0)
setsockopt$sock_int(r2, 0xffff, 0x800, &(0x7f0000000040)=0x20, 0x4)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x2, 0x2, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)
bind(r0, &(0x7f0000000000), 0x10)
write(r3, 0x0, 0x0)
recvmmsg(r2, &(0x7f00000000c0)={0x0}, 0xfffffdfb, 0x1842, 0x0)


writev(0xffffffffffffffff, &(0x7f0000000ac0)=[{&(0x7f0000000000)="56ce011ab92f8ec534", 0x9}], 0x1)
r0 = socket$unix(0x1, 0x1, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f0000000000))


poll(0x0, 0x0, 0x0)
socket(0x18, 0x3, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000040), &(0x7f0000000100)=0xc)
r1 = socket(0x2, 0x4001, 0x0)
dup(r1)
ktrace(&(0x7f0000000280)='./file0\x00', 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x80206916, &(0x7f00000001c0))
r3 = socket(0x2, 0x1, 0x0)
listen(r3, 0x0)
close(r1)
r4 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
getsockopt$SO_PEERCRED(r1, 0xffff, 0x1022, &(0x7f0000000140), 0xc)
ioctl$VMM_IOC_RUN(r4, 0x8210560b, &(0x7f0000000000)={0x1, 0x0, 0x0, 0x0, 0x0})
sysctl$net_inet_tcp(0x0, 0x0, &(0x7f0000000100), 0x0, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000300)="9b0209c3eb987ab7fe4189c99e805e6e84d356960798a692992117d6728436ba1bd87f42e3303eac3846528d050712f838130efce33f523ba44765f5f6915b0227390ed95bd9dc6d4dc7e149d4d6d06a3f23616e773302d9cae75e39a5a11e32e0e6ebd635450b2eba540af7f2aa5dbfbdd900a0dad2b74f50acd76b5c567049ef436dbea0d7562f52950fa5ef6e84c513252ddd8680a944d5c2bd02adc7f1fe850c00000000000000062ab475cca257352828a76e5334be562995e894238b96ca5d4d3e670feac9b4e8aa9bef19525cb6f7e8570b2a374f1400041ed45bb7ad3fe963cb9a8bd949ee0fc6dbceb7d956015947b3e88aa810f8ed7cca10ff010000000000001345daa49507756f49775275ca390b94e85d5a95b8bdacb9429c25483a9275d0da3b561c6adc3c141f26a88016dd6b436218bdbdc9ac0a623855e941dc1872fcb045e0d9df1ecc6357ee21e2b0802cb60eec6add5e94723235f06715e7eecc3e0760c70e1dd7873e27142bbae1a7e44de453a073fe3426f334b80f043ba9136d57c799353d46dd81439b111a511a288bee5dfb2e353e3bb073e3342273216b07e49ca4df0fd2dbe9a8eb377010ee678aad0bd8e9fb7d82693a096344671843a1f2082612b0ff237c6e505ff5f5ba932954d73c630fdb791f833a1da5af0704f687e196f4f7859e071fc98111cc9024f790ce16ceaa7d0104e39789d9100000010000000000050000000000", &(0x7f00000002c0)=0x210, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x1, &(0x7f0000000540)=[{0xb1, 0x0, 0x0, 0xfffffffe}]})


sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000007, 0x0, 0x0, 0x0, 0x3d)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$net_inet6_ip6(&(0x7f0000000040), 0x5, 0x0, 0x0, &(0x7f0000000000), 0x2e)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd02)
r0 = open(&(0x7f0000000240)='./bus\x00', 0x0, 0x0)
r1 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
pwritev(r1, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
pread(r0, &(0x7f0000000040)="3cd15db7c30016", 0x50cc00, 0x0)


acct(&(0x7f0000000140)='./file0\x00')
open(&(0x7f0000000040)='./file0\x00', 0x205, 0x0)
open$dir(&(0x7f0000000200)='./file0\x00', 0x20, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x100000002})


mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
munmap(&(0x7f0000400000/0xc00000)=nil, 0xc00000)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000132000/0x3000)=nil, &(0x7f0000ff9000/0x4000)=nil, 0xc0400000}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f0000065000/0x2000)=nil, &(0x7f0000093000/0x1000)=nil}, {&(0x7f00001f0000/0x1000)=nil, &(0x7f000008a000/0x3000)=nil}, {&(0x7f000008f000/0x3000)=nil, &(0x7f00000b2000/0x1000)=nil}, {&(0x7f00001dc000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000087000/0x4000)=nil, &(0x7f000002a000/0x3000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000145000/0x2000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f000011a000/0x2000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000466000/0x3000)=nil}, {&(0x7f00000b1000/0x1000)=nil, &(0x7f0000145000/0x4000)=nil}, {0x0, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000087000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ff0000/0x10000)=nil}, {&(0x7f000008a000/0x2000)=nil, &(0x7f00002d7000/0x3000)=nil}], './file0\x00'})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000800), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r0, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0})


sysctl$kern(&(0x7f0000000000)={0xa, 0x51}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000000), 0x6, 0x0, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000140)=[{0x1d}, {0x1c}, {0x8126}]})
syz_emit_ethernet(0xe, &(0x7f0000000100)=ANY=[])


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = kqueue()
r2 = open$dir(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
r3 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
kevent(r1, &(0x7f00000002c0)=[{{r2}, 0xfffffffffffffffc, 0x63}, {{r3}, 0xfffffffffffffffc, 0x85}], 0x1f, 0x0, 0x3, 0x0)
close(r0)


msgctl$IPC_SET(0x0, 0x1, 0x0)
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc020699c, &(0x7f00000001c0))
connect$unix(0xffffffffffffffff, 0x0, 0x0)
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x200, 0x0)
fcntl$lock(r1, 0x8, &(0x7f0000000000)={0x0, 0x0, 0xfffffffffffffffe, 0x1000300010008, 0xffffffffffffffff})
openat$bpf(0xffffffffffffff9c, 0x0, 0x800, 0x0)
r2 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000000), 0x2, 0x0)
ioctl$SPKRTONE(r2, 0x80085301, &(0x7f0000000040)={0x0, 0x7})
openat$null(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$TIOCSETD(0xffffffffffffffff, 0x8004741b, &(0x7f0000000440))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
rename(&(0x7f0000000080)='./file0\x00', &(0x7f00000000c0)='./file0\x00')
mkdir(&(0x7f0000000080)='./file0\x00', 0x0)


r0 = socket(0x1e, 0x3, 0x0)
sendmsg$unix(r0, &(0x7f00000006c0)={0x0, 0x0, &(0x7f0000000700)=[{0x0}], 0x1}, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x5900)
close(0xffffffffffffffff)
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r1, 0xc0384600, &(0x7f00000000c0)={&(0x7f0000000000)='./file0\x00', 0x4, 0x0})


sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, 0x0)
mmap(&(0x7f0000726000/0x3000)=nil, 0x3000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
setrlimit(0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
madvise(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
getpid()
getsockopt$sock_cred(0xffffffffffffff9c, 0xffff, 0x1022, 0x0, 0x0)
setsockopt$inet6_MRT6_ADD_MIF(0xffffffffffffffff, 0x29, 0x66, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
r1 = dup(r0)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{0x30}, {0x28}, {0x46}]})
syz_emit_ethernet(0x36, &(0x7f0000000840)=ANY=[])


ioctl$VMM_IOC_WRITEREGS(0xffffffffffffffff, 0x8020560a, &(0x7f0000000040)={0x1, 0x0, 0x6})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000340), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$VMM_IOC_WRITEREGS(r0, 0xc0205609, &(0x7f0000000040))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000500)={0x3, &(0x7f00000000c0)=[{0x4}, {0x54}, {0x8106}]})
syz_emit_ethernet(0x62, &(0x7f00000008c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f00000001c0)=[{0x74}, {0x7}, {0x46}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = socket(0x18, 0x1, 0x0)
getsockopt(r0, 0x6, 0x8, 0x0, 0x0)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000029, 0x23, &(0x7f0000000080)="b6", 0x1)


mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
setreuid(0xee00, 0x0)
open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000015c0)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000300)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000040)=0xc)
setegid(0x0)
r2 = msgget$private(0x0, 0x604)
msgctl$IPC_RMID(r2, 0x0)
msgsnd(r2, &(0x7f00000002c0)=ANY=[@ANYBLOB="0000000000000000fbb2d30026d68ea90fe95c690000002800e40e16de108a0e5932d8"], 0xb, 0x800)
msgrcv(0x0, &(0x7f0000000140)={0x0, ""/188}, 0xc4, 0x3, 0x1400)
msgctl$IPC_SET(r2, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r1, 0x0, r1}, 0x8000000000000001, 0x80000000, 0x0, 0x0, 0x1})
socket(0x18, 0x1, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
recvmsg(0xffffffffffffffff, 0xffffffffffffffff, 0x0)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000001240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlink(&(0x7f0000000ac0)='./file0\x00', &(0x7f0000000e40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
setreuid(0xee00, 0x0)
r3 = open$dir(&(0x7f0000001240)='.\x00', 0x200, 0x0)
r4 = getuid()
fchown(r3, r4, 0x0)
utimensat(0xffffffffffffff9c, &(0x7f0000000040)='.\x00', &(0x7f0000000080)={{}, {0x0, 0xffffffffffffffff}}, 0x0)
rename(&(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000001680)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000001140)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000240)='./file2\x00')
symlink(&(0x7f0000000740)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000700)='./file0\x00')
r5 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSKBDIO_SETENCODING(r5, 0x80045710, &(0x7f00000000c0)=0x100)
select(0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETAF(r1, 0x802c7416, &(0x7f0000000000)={0x0, 0xffffff49, 0x3, 0x5bc, "225e00e8550900fa4ab1896c0000c100"})
writev(r0, &(0x7f0000000200)=[{&(0x7f0000000180)="d37f05c970c47013bc5c09", 0xb}], 0x1)


ftruncate(0xffffffffffffffff, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000000c0)=[{0x3d}, {0x44}, {0x8006}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])
sysctl$net_inet6_ip6(&(0x7f0000000080)={0x4, 0x18, 0x29, 0x35}, 0x4, 0x0, 0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f00000003c0)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000400)=0xc)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0x0, 0x0, 0x0, r1}, 0x0, 0x1})
getpeername(0xffffffffffffffff, 0xffffffffffffffff, &(0x7f00000010c0))
openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r2 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r3 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r3, 0xc0106924, &(0x7f00000001c0))
r4 = kqueue()
kevent(r4, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
ioctl$FIONREAD(r2, 0xc0406938, &(0x7f00000001c0))
preadv(0xffffffffffffffff, 0x0, 0x0, 0x0)
madvise(&(0x7f00003e1000/0x3000)=nil, 0x3000, 0x0)
preadv(0xffffffffffffffff, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000300)='./file0\x00', 0x2000, 0x6da)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x190)
r5 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r5, 0x8020699d, &(0x7f00000001c0))


r0 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
lseek(r0, 0x7, 0x0)
getdents(r0, &(0x7f0000000040)=""/4096, 0x1000)


r0 = getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r0})
setreuid(0xee00, 0x0)
r1 = getuid()
setreuid(0xee00, r1)
setpgid(0x0, 0x0)
setpgid(0x0, r0)
pipe(&(0x7f00000001c0)={<r2=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r2, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r3 = fcntl$getown(r2, 0x5)
ktrace(0x0, 0x1, 0x138, r3)


setrlimit(0x8, &(0x7f0000000000)={0xa, 0x12})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
writev(r0, &(0x7f00000024c0)=[{&(0x7f0000000240)}, {&(0x7f0000000300)="7a59c0aa14add6a5b3de6be3c948c46ed67ad44557f708cc5704995217874eca62ee50271b6be464fa7bb01c121c310a4380a642252df19f0e7f0ae4fb9a47bcac08a11750bcc7d9507f99670caf2e2e4972f9c679b94d655af0544846ca59835465b2e6d4a39d26c89b4dbe93028ccad0ee4d556f585413fbc1572622fbee0f275c65c07434b58b68ea9a876ddd8feba14c2e9a642c5e73610f4c5af2797bbd7d702752c534c51cd51f00b10f685155bf8913b31b4645673a46fd82372d0d4ff8c607ad9260160cb84b45bc55e7aa59072e5d1ec37f447b6984023d54236b42179bce2642ed12803835d4140d778603", 0xf0}], 0x2)
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f0000000040)=0xfffffffc)
write(r0, &(0x7f0000000140)="feaefb66d909ec4d0da82748ae558f245ae995f911f70b39a831eeedd542a30b7694924a16e8f2ce1d9139db272e810b8f995f554138f306b1fd4e8434ef6e1147a90209341f2f75777933d6736442abbcef8a037d285e3ba4be08806490e84b1e80d6067243dcae3471ef2cfe3db56b62125caab7e4f018cfaa9a82bea85d6180b05ed81f5d1ed9b1c0cfaf8853e69a519f1fbc9cbb12edb464f64a72e88182b24b3dc1c184fa5ef023000f541b075f1c4c91", 0xffb8)
execve(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCLOCK(r0, 0x20004276)
seteuid(0xffffffffffffffff)
ioctl$BIOCFLUSH(r0, 0x20004268)


syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000), 0x10)
r1 = dup(r0)
listen(r1, 0x0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
accept$inet(r0, 0x0, 0x0)
r3 = socket(0x2, 0x1, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)
r4 = dup(r3)
sendto$inet(r4, &(0x7f0000000100)="03c019b7e2399b388d3cc45f01364c934feea3d4c1fbf21dc5dab6090e154d84d22c5ff1da069dd0d4af159f8000000000000000c892a0", 0xff4c, 0x401, 0x0, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1023, &(0x7f0000000080), 0x4)
sendmmsg(r3, &(0x7f0000000240)={0x0}, 0x10, 0x0)


open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x144, r0)
r1 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r1, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, 0x0, 0x9}, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
close(0xffffffffffffffff)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x0, 0x0, 0x0)
r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
fchown(r0, 0x0, 0xffffffffffffffff)
open(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
execve(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, 0x0, 0x9}, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{}, 0xffffffffffffffff})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x45}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000001c0), &(0x7f0000000200)=0xfffffffffffffe50)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r1 = socket(0x2, 0x4, 0x0)
ioctl$FIONREAD(r1, 0xc0206923, &(0x7f00000001c0))
ioctl$FIONREAD(0xffffffffffffffff, 0x8004745d, &(0x7f0000000200))
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x8040691a, &(0x7f00000001c0))


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{}, {}, {0x1, 0x0, 0x0, 0xffffffff}]})
poll(&(0x7f0000000ac0)=[{0xffffffffffffff9c}], 0x20000000000000d7, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000007, 0x0, 0x0, 0x0, 0x3d)


sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000007, 0x0, 0x0, 0x0, 0x3d)
socket$unix(0x1, 0x5, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x2, 0x0, 0x20}, 0x4, &(0x7f0000000140)="09060000", &(0x7f00000006c0)=0x4, 0x0, 0x0)
r0 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r0, 0x802069db, &(0x7f00000001c0))
sysctl$net_inet_tcp(0x0, 0x0, &(0x7f0000000000)="9b1809ffffffffff", 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000100)=ANY=[])
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000001540), &(0x7f0000001580)=0xc)
r1 = socket(0x2, 0x3, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f0000000180)="e9f9f70f6107d8b5dd53f16d56365b1621aac234ebe6c1bd2d59fd9b210dfbd79abf195e451125ea9a331fc145a824b21123ce1441403d58e3f416e5ac4c4782a47ff995c981e64a52404e1f6f1f8b", 0x4f)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x8020697f, &(0x7f00000001c0))
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, 0x0)
ioctl$FIONREAD(r1, 0x8020699f, &(0x7f00000001c0))
getsockopt$sock_cred(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000100), &(0x7f0000001600)=0xc)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r3 = socket(0x18, 0x3, 0x3a)
setsockopt(r3, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r3, 0x29, 0x65, 0x0, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x59}, 0x2, &(0x7f0000000000)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec370", &(0x7f0000000140)=0x1b, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000240)={0x4, 0x2, 0x0, 0x15}, 0x4, 0x0, 0x0, 0x0, 0x0)
symlink(&(0x7f0000000ac0)='./file0\x00', &(0x7f0000000e40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000001140)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000800)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/file0\x00')
r4 = socket(0x2, 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x1, &(0x7f0000000080)="0315f1d89ec5a317a9357682", 0xc)
open$dir(0x0, 0x0, 0x40)


msgget(0x2, 0x2)
semctl$SETALL(0x0, 0x0, 0x9, &(0x7f0000000100)=[0x0, 0x9, 0x8000, 0x7, 0x1, 0x9, 0x5, 0x401])
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x400, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
sysctl$net_inet_icmp(&(0x7f0000000000), 0xb, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x4a, &(0x7f0000000000)={@broadcast, @broadcast, [], {@ipv4={0x800, {{0xa, 0x4, 0x0, 0x1, 0x3c, 0x0, 0x0, 0x0, 0x2c, 0x0, @broadcast, @multicast1, {[@timestamp={0x44, 0x14, 0xb, 0x1, 0x0, [{}, {[@multicast1]}, {}]}]}}, @tcp={{0x2, 0x2, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})
syz_emit_ethernet(0x36, &(0x7f0000000200)=ANY=[])
dup2(0xffffffffffffffff, 0xffffffffffffffff)
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0xc0206937, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000140)=[{0x81}, {0x28}, {0x16}]})
write(r0, &(0x7f00000001c0)="d9537abde93d050cdd16b13f742a", 0xe)


open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
r3 = socket(0x2, 0x4001, 0x0)
r4 = dup(r3)
r5 = fcntl$dupfd(r4, 0x2, 0xffffffffffffffff)
close(r5)
r6 = socket(0x2, 0x2, 0x0)
connect$inet(r6, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r5, 0xffff, 0x1023, &(0x7f0000000040), 0x4)
shutdown(r6, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1023, 0x0, 0x0)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f0000000180)='./file0\x00', 0x23f)
chdir(&(0x7f00000001c0)='./file0\x00')
symlink(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000100)='./file1\x00')
setuid(0xee01)
open$dir(&(0x7f0000000080)='./file0\x00', 0x400000002c2, 0x0)
rename(&(0x7f0000000280)='./file0\x00', &(0x7f0000000040)='./file1\x00')


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VMM_IOC_INTR(r0, 0x800c5606, &(0x7f0000000040)={0x5})


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2a, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047470, &(0x7f0000000280)=0x5)
readv(r0, &(0x7f0000000200)=[{&(0x7f0000000100)=""/185, 0xb9}], 0x1)
write(r0, &(0x7f0000000000)='E', 0xfffffc36)
setrlimit(0x0, 0x0)
syz_open_pts()
close(0xffffffffffffffff)
syz_open_pts()


sysctl$net_inet_carp(&(0x7f0000000280)={0x4, 0x2, 0x6, 0x2}, 0x4, 0x0, 0x0, &(0x7f0000000040), 0x0)


r0 = openat(0xffffffffffffff9c, &(0x7f0000000700)='./file0\x00', 0x200, 0x0)
r1 = openat$tty(0xffffffffffffff9c, &(0x7f00000002c0), 0x40, 0x0)
kevent(r0, &(0x7f0000000280)=[{{r0}, 0x6, 0x68, 0x40000000, 0xffffffffffffffff, 0x80}], 0x401, &(0x7f0000000300)=[{{r1}, 0xfffffffffffffffa, 0x78, 0x4, 0x91f}, {{r0}, 0xfffffffffffffffd, 0x82, 0x2, 0x80000000, 0x8000000000000001}, {{r0}, 0xffffffffffffffff, 0x80, 0x40, 0xfffffffffffff2e8, 0x40}, {{r0}, 0xfffffffffffffff9, 0x1a, 0x1, 0x1000, 0x9}, {{r0}, 0xfffffffffffffffa, 0x8, 0x80, 0x40, 0xfff}, {{}, 0xfffffffffffffffc, 0x9c, 0x2, 0x3f, 0x5}], 0x1, &(0x7f00000003c0)={0xfffffffffffffffa, 0x6})
r2 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x100, r2)
mknod(&(0x7f0000000200)='./file0\x00', 0x20, 0x1d4)
select(0x12, 0x0, 0x0, 0x0, &(0x7f0000000240))
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x16}, 0x2, 0x0, 0x0, &(0x7f0000001440)="cca410db", 0x4)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
socket(0x18, 0x2, 0x0)
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
readv(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f00000002c0)=""/50, 0x32}], 0x1)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1800000029"], 0x3e}, 0x0)
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)


ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000180)=[{}], 0x1})
sysctl$kern(&(0x7f00000000c0), 0x2, 0x0, 0x0, 0x0, 0x0)
r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$WSMOUSEIO_GETPARAMS(r0, 0x80105727, &(0x7f00000000c0)={0x0})


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000080)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendto$unix(r1, &(0x7f0000000300)="dd", 0x1, 0x0, 0x0, 0x0)
open$dir(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
r2 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000d38, r2)
r3 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, r3, 0x0)
recvfrom$unix(r0, &(0x7f0000000240)=""/183, 0xb7, 0x0, 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
getsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{}, {0x9}, {0x41ef}]})
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
select(0x40, &(0x7f0000000000), &(0x7f0000000040)={0x7ff}, 0x0, 0x0)
writev(r0, &(0x7f00000000c0)=[{&(0x7f0000000040)='#', 0x1}], 0x1)


openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
syz_extract_tcp_res(0x0, 0x0, 0x0)
mkdir(&(0x7f0000000640)='./file0\x00', 0x0)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
chdir(&(0x7f0000000240)='./file0\x00')
mkdir(&(0x7f00000001c0)='./file1\x00', 0x0)
setreuid(0x0, 0xee01)
mkdir(&(0x7f0000000100)='./file0\x00', 0x184)
rename(&(0x7f0000000340)='./file0\x00', &(0x7f0000000380)='./file1\x00')
chroot(&(0x7f0000000200)='./file0\x00')
r0 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmat(r0, &(0x7f0000001000/0x3000)=nil, 0x0)
r1 = semget$private(0x0, 0x1, 0x300)
semctl$GETZCNT(r1, 0x1, 0x7, &(0x7f0000000040)=""/92)
unveil(&(0x7f00000003c0)='./file0\x00', &(0x7f0000000400)='c\x00')
r2 = socket(0x2, 0x3, 0x0)
getsockopt(r2, 0x0, 0x16, 0x0, 0x0)
sysctl$machdep(&(0x7f00000002c0)={0x7, 0x1}, 0x5f, &(0x7f0000000940)="eca85a08f2b13f7f3ae9697fc4144e4ac0150b8979c379f02bde88473ab9ef1317f5dd3c8d47acf809017556627fe73e32f45fa656885e2f2e94c21e44491d92ec9538c58202fa807120584adccd6303fc0df5a44be6bca8cec0312ab377ab1ec6bb5d9fa1d4f20c229a227b81703858e91e7cc20f518a9c296f2fc7df1c78b4112fe4634440a08dd55d3c84f12ae1680b49b04fb2cf471725caa892078f48fcdabc6fe8b6213feb4aaed3b2a5ee9ee4cb2e223d20e6dc66ca2482d58e6b25717ddb22e8981702c50c0009a87b11f7571473491b76368771bb6f71f6000000e1d72b23215024c13000"/253, &(0x7f0000000300)=0xee, &(0x7f0000000440)="168c2c3c1e4914450ed8f36dec9b58bdcac0ff8e60964e5966c8f407a48f67ab36e671fab1e29c3920378f86a8958b202b11f9b5a071d4f9d9cc32bb1f201ff064707458762b4c09c349db4e5440510b4b59fe8c93116f11d3ad343a162dbaa8aeab89fafaf4d3ca1adce6c1721174eec6e363f30b8093338ddcb2df4a27ed28fd2f7c83d525099f3d6f0d2499153664c0cf10d1094989d207004f182eb14833547abd6b3d940e9516f1fb45c406214c3cf7f14bfa7cc79ba93f17fd0e0afb31ac5e2c", 0xc2)
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
r3 = open(&(0x7f0000000300)='./file0\x00', 0x400, 0x0)
open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
poll(&(0x7f00000000c0)=[{r3, 0x6e}], 0x1, 0x0)
semctl$SETVAL(r1, 0x1, 0x8, &(0x7f0000000140)=0x2)
ftruncate(0xffffffffffffffff, 0x0)
ioctl$SPKRTUNE(0xffffffffffffffff, 0x20005302, &(0x7f0000000600)={0x3ff, 0x3619})
syz_emit_ethernet(0xef, &(0x7f0000000680)=ANY=[@ANYBLOB="aaaaaaaaaaaa00000000000008004900c9a800000000ce009078e0000001ac1400aa44100603f0000000e0000001fffffffd4e204e20", @ANYRES32=0x41424344, @ANYRESDEC=r2, @ANYBLOB="71800000909b00011312be910375b6c2655af6e38cb8f9e8b69413103d4b3123f7230ff68e95b1b3db700001010402051e000000030000000400000009000000070000000200000081000001ff0000000f79c71882e51a81a29592af8769007f387fcb96b14771209ea6bee2f17319794a4d81b706e64df4a2e4f4d1443ac9e55811a1d4e0f86ed4acc67ac23b4c15c81717e8d149cb60f35bd9f232"])
sysctl$hw(&(0x7f0000000000)={0x6, 0x1c}, 0x2, &(0x7f00000002c0), 0x0, 0x0, 0x0)


openat$pci(0xffffffffffffff9c, 0x0, 0x0, 0x0)
poll(0x0, 0x0, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000380)=[{0x40}, {0x28}, {0x406}]})
syz_emit_ethernet(0x138, &(0x7f0000000500)=ANY=[])


r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000280), 0x1, 0x0)
ioctl$WSKBDIO_GETDEFAULTBELL(r0, 0x40105706, &(0x7f0000000000))
mmap(&(0x7f0000ffd000/0x1000)=nil, 0x1000, 0x0, 0x4011, r0, 0xffffffff)
open$dir(0x0, 0x0, 0x8)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCLOCK(r1, 0x20004276)
seteuid(0xffffffffffffffff)
ioctl$BIOCIMMEDIATE(r1, 0x80044270, &(0x7f0000000040))


syz_emit_ethernet(0x5e, &(0x7f0000000080)={@broadcast, @local, [], {@ipv6={0x86dd, {0x0, 0x6, '\x00\t\x00', 0x28, 0x0, 0x0, @rand_addr="6e1aa4058b74adad9a4e721f5b293380", @mcast2, {[@hopopts={0x0, 0x1, '\x00', [@pad1, @pad1, @ra]}], @icmpv6=@ndisc_ra}}}}})
openat$speaker(0xffffffffffffff9c, &(0x7f00000000c0), 0x8000, 0x0)
r0 = syz_open_pts()
close(r0)
writev(r0, &(0x7f0000000000)=[{&(0x7f0000000b80)="4b8572730e51a93601084c480dc1199dc57b2495e54e7209c4c7ad688b2768a5c2dc2606cb3396fe19b7684fece0172cf942aa0b7918b45b0efaf120cb28eabf16f7c5000b4159c5d1cc872d79ad1721703966da567664630f2106236f5650fdbfa8246401bb352764be4b6fa3ebc0b99a3665bc25216ba50581e8c9aff5a6691e97bedc672c5e8e3ed4bd372eb4db334603c9fb94a733c8f0455f4285c7b298e66cf9bebb66f447e2fa9afbb8108623ef393b169cbd255c6b3db0b76f90ed460706c5193c7b1f5066d2dbf51d6cd727629cd778450dcb36f693bb26b75e82299e4e39eeac9ae3122c7ddd1adc48621758141b0dca303454edf70ff1e66f574bfa184fe03fd13aadfdb7b196087edddc571ab8a8bf9d9676b2a22ba7e946a26377f29f53d461fbe5238b3ba135febe2821ce168c88fed545c6f82874285b00254d20ec65a168817dcd0157821d9c0c28d4790c62cbf67b6f71982c73fcbc5f943204b649b6313e879d2cd92c788aab06c014a89b3523de83b305e047a0d9ca6acb8bddb5de9aae120000f2eac0b8b83c9502f70f80a627d784037f333ed300c3a993e252ea24c9f5e1d12a5ab0ba3c0346992a80e1cb91283b459e5aeb7d2a03e0a55f27f2b0cacd8c62743f7ca5e9b0541d92a623ff7772df5ec5d228c087209b69c903b0b779defd39352daaffbc17424f5dd6480c80fb74ca117ef2a6870e590350b913d139afbc581ba6e2d87fd7a9b6e8d91b41afa9531e53a297e6474afc5c5e", 0x223}], 0x1)
r1 = open(&(0x7f0000000180)='./file0\x00', 0x80000000000206, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(r2, 0x81206919, &(0x7f00000001c0))
ioctl$BIOCGSTATS(r1, 0x4008426f, &(0x7f0000000040))
r3 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VMM_IOC_RESETCPU(r3, 0x82405605, &(0x7f0000000280)={0x2, 0x0, {[], [0x0, 0x0, 0xb, 0x334], [0xffffffffffffffff]}})
sysctl$kern(&(0x7f0000002340)={0x1, 0xa}, 0x2, &(0x7f0000002380)="d7", &(0x7f00000023c0)=0x1, &(0x7f0000002400), 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x4, 0x310, 0x0)
sendsyslog(&(0x7f0000000200)='%', 0x1, 0x0)
socket(0x2, 0x2, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f0000000180)=0x4)
write(r0, &(0x7f0000000e40)="7c84cf179279b50eda5dd1951a66d8f10524a063d2025ff0d27a44bc29bdcac27fcb7aaa95cb2000000000000000016a1f419a83d4275218a89d7a7803f069d851ff628dd309c40f6e3c932af00cb6219ae6e21d2c28d492cd5404b16dfa7174620593b1e8ad2ea49d2344c1a3b234ff0f1c70fd4252844a6e6ab7b8997bc55fa22ce951ee038d289078b95510b0f2473ce17991af3f8c322b496466f800d0ee339196de2b5ec2d8425c711d3f9e051eb055d45c693d7549712f5284a9fbca7d15c5bf1a9c8e3b3c1a43983056782e046c29e3d57082f7743b8bf6d994cd3c26c85609eaa11e6f7bc4000000000000000000000000000000006e0d79698d5b387dd67a41b709f6abf24bc4eb66e971fead50b6bb52080870daf9ce3992aa4675785c4e199c1e389a606930927e4942d7cf11a3e3d2d52f73f224ce10c839e0d7572d0518c8fbc90d5176d061b7093d481c912241d22ba85fbdf24d80e25433442c2e561beaec3c767ac1a33ca8f405f805c861cda71ca6502bd63142ae57c73796fdb2d65bdde3b30eb3b98fe124a39c9457d14def2a15c802cb264497b0b196aa12f7cc8b287c50ec07749486bdf08ff4cf2a182d9f37948930f8c2af08ef4854e1d38f7ccd8ed29562c0993c23b30c47b921d32886d577d79315857bf24b13", 0x1e0)


sysctl$net_pipex(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
symlinkat(0x0, 0xffffffffffffffff, &(0x7f0000001940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x0, 0x9, &(0x7f0000000040)="03000000", 0x4)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000001980), 0x4)
r1 = open(&(0x7f0000000280)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000028000/0x4000)=nil, 0x4000, 0x0, 0x10, r1, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
r2 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
pwritev(r2, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
open$dir(&(0x7f00000000c0)='./file1\x00', 0x0, 0xd)
r3 = open$dir(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
preadv(r3, &(0x7f00000012c0)=[{&(0x7f00000001c0)=""/224, 0xfffffdd5}], 0x1, 0x0)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
mlock(&(0x7f000053a000/0x2000)=nil, 0x2000)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x1}})
kevent(0xffffffffffffffff, &(0x7f0000000040)=[{}], 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)="03000000", 0x4)


r0 = socket(0x2, 0x4001, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x4, 0x0)
poll(&(0x7f0000000ac0)=[{0xffffffffffffff9c}], 0x20000000000000d7, 0x0)
poll(0x0, 0x0, 0x1000)
r2 = socket(0x2, 0x4001, 0x0)
r3 = dup(r2)
r4 = fcntl$dupfd(r3, 0x2, 0xffffffffffffffff)
close(r4)


mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f00000000c0)={&(0x7f0000000000)='./file0\x00', 0x4, 0x0})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = socket$inet(0x2, 0x16e9b72ebdb25f35, 0xb1)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
socket$inet(0x2, 0x1, 0x0)
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000100), &(0x7f0000000200)=0xc)
r2 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r2, &(0x7f00000000c0)=[{0x0}, {&(0x7f0000000780)=""/4096, 0x1000}, {&(0x7f00000003c0)=""/233, 0xe9}], 0x3, 0x0)
close(0xffffffffffffffff)
r3 = socket(0x11, 0x3, 0x0)
sendto$unix(r3, &(0x7f0000000300)="b10005010000009f0500000007010000331c13fece910b00fef96ecfc72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf5f882b2b7be1aa0500000051e2f0ad3ebbc257699a1f139b672f335c223e7d0c032bfa896443a42118210000720fd38bfb0000fd54c125191b1257aea8c500002002fbfe0c2300008abfba0902000000e371a3f8343712051eeab70800000000000000ffffffff001000"/177, 0xb1, 0x0, 0x0, 0x0)


openat$diskmap(0xffffffffffffff9c, 0x0, 0x20, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f0000000080)={&(0x7f0000000040)=[{}], 0x1})
sysctl$vm(&(0x7f0000000080)={0xa}, 0x3, 0x0, 0x0, 0x0, 0x0)
r0 = syz_open_pts()
fcntl$lock(r0, 0x8, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1000300800000})
open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
r1 = getpid()
ktrace(&(0x7f00000001c0)='./file0\x00', 0x0, 0x40000534, r1)
sysctl$net_inet_tcp(0x0, 0x0, &(0x7f00000000c0)="9b1809c3dd7d3f", 0x0, 0x0, 0x0)
r2 = socket(0x2, 0x2, 0x0)
dup2(0xffffffffffffffff, r2)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)


mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x2801)
pipe(&(0x7f0000000100)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
getppid()
r2 = getpid()
setpgid(0x0, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r2})
pipe(&(0x7f00000001c0)={<r3=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r3, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r4 = fcntl$getown(r3, 0x5)
fcntl$setown(r0, 0x6, r4)
r5 = fcntl$getown(r0, 0x5)
fcntl$setown(r1, 0x6, r5)
r6 = socket(0x2, 0x3, 0x2d)
r7 = dup(r6)
select(0xffffffffffffffd0, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r8 = socket(0x2, 0x3, 0x0)
r9 = dup(r7)
dup2(r9, r8)
connect$unix(r8, &(0x7f0000000000), 0x10)
writev(r9, &(0x7f0000000140)=[{0x0}], 0x1)


sysctl$net_inet_ip(&(0x7f00000002c0)={0x4, 0x2, 0x0, 0x25}, 0x4, &(0x7f0000000300)="e3cf", &(0x7f0000000140)=0x2, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x10, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000200)={0x2, &(0x7f0000000040)=[{0x15}, {}]})
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
r2 = dup(r1)
setsockopt(r2, 0x1000000000029, 0xd, &(0x7f0000000000)="ffdaf64c000000004f0527000000055e473e0000", 0x14)
syz_emit_ethernet(0x3e, &(0x7f0000000040)=ANY=[])
mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
r3 = open(&(0x7f00000001c0)='./file0\x00', 0x200, 0x0)
r4 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x80, 0x0)
ioctl$FIOSETOWN(r4, 0x80047476, 0x0)
setreuid(0xee00, 0x0)
sysctl$net_pipex(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
munmap(&(0x7f0000ff7000/0x7000)=nil, 0x7000)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mquery(&(0x7f0000ffd000/0x2000)=nil, 0x2000, 0x0, 0x0, 0xffffffffffffffff, 0x0)
syz_emit_ethernet(0x17a, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
setsockopt(r3, 0x1000000000029, 0xa, &(0x7f0000000040)="03000000", 0x4)
setsockopt(0xffffffffffffffff, 0x1000000000029, 0xd, 0x0, 0x0)
r5 = socket(0x18, 0x2, 0x0)
connect$unix(r5, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmsg(r5, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="10"], 0x10}, 0x0)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x100000000000000}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd31929648000000000000000000", 0x14)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbdf13b9fd812eaa4e713048e69931929648", 0x14)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x3})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x27}, 0x4, &(0x7f0000000000)="71f91e3471ac0058bc5a91501d942400b5e1a0757cb9af769c7afec37082", &(0x7f0000000080)=0x306, 0x0, 0x2e)
sysctl$kern(&(0x7f0000000040)={0x1, 0x34}, 0x2, &(0x7f0000000080)='G~i*', &(0x7f0000000100)=0x4, &(0x7f0000000140), 0x0)
r1 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1008, &(0x7f0000000040), 0x4)
r2 = socket(0x11, 0x4003, 0x0)
sendto$unix(r2, &(0x7f0000000000)="b1000504600000000000000007000000331c13fecea10500fef9ed06c72fd3357ae320b37b673039d2d236073705ae04be38164991f7accf5f882b297be1aad2236deb51e2f0ac3ebbc257699a5f139b672f4d335d223e7d029d6ba8af630037282102000000720f70c1f5a472c881ea6e69e0bb76d907c400000200361b1257aea8c5000020020000000000008abfba09001d89e0000000000000008000ff00000000090000000000000000000000f600", 0xb1, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000080)={0xffffffffffffffff, <r3=>0xffffffffffffffff})
sendmmsg(r3, &(0x7f0000000000)={0x0}, 0xfffffe32, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}, 0xad, 0xfffffffffffffffe, 0x7fffffffc})
r4 = socket(0x18, 0x3, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r4, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
close(0xffffffffffffffff)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r5 = socket(0x18, 0x1, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
shutdown(r5, 0x1)
r6 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r6, 0x80146952, &(0x7f00000001c0))
dup2(r1, r5)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x62, 0x0)
mknod(&(0x7f0000000040)='./file0\x00', 0x6000, 0xe02)
r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
pwritev(r0, &(0x7f0000000080)=[{0x0}], 0x1, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000040)={0x0, 0x80000001, 0x7fff, 0x40049f, "ec92281f0511f0210d2de8de1554010800ff0400"})
write(r0, &(0x7f0000000480)='\b', 0x1)


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
r2 = dup2(r1, r0)
setsockopt$inet_opts(r2, 0x0, 0x200000000000a, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000300), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000280)=[{0x74}, {0x4d}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000200)=ANY=[])


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x11, r0, 0x0)
ftruncate(r0, 0x8531)
writev(0xffffffffffffffff, &(0x7f00000026c0)=[{&(0x7f0000000400)="640493d78db6a9c1e335bb42b30c7b40a07b3baad98026cb156727aa65cfb18540954a46faf6cd689a437aff3f4961c4e46a834f6785f138abeced17229a790e349e6bd31df47a250b6311c17b41de694d02002d9c138fb5554471ad71a4e3b0c4a0f71fc4b1f3db02e683a852170340fa26d02f5dcb6c3772415d9b0c54258aba6ad66cd42dfd5163936af944020e200f6dad158fa90dfdd051d151c8c8cb6d711f408511a8c922ff7be9bf88fc6a18b3261c65ab46b32f89b7793b789d533f5dabd554659bcbb9e4082598016c9ffd443ad64a6c1384bebc4f0fa12ebee357f81c1bfbb7ff9c0bb5289f98184e590366ece692aac2a0f3fe55ae6072624ff0892d666934e9e7bb159ba7471e9ca862d48aa90c56e33b972e7ab5f15383b1e0bdc135ef14c4b638c9514366af346df10d2d11e3e82c7f98a731867165c536966e32790a098e86bc8c85d1d890537ee1a3b37a907cb151aa5b72801d9b213f04f59acc40bab4f2dfde876c2bc53ed02cd106d289a59310e0297a072b926369982acb409872a3a4325ed56f1d297bc8bbfb8f0a43f793ee9487a4492016350aa61cca26b86045d14a8f08e6f6d3e3be5520397612b66ebdf990efcf9ed9796836fa253dfa0389406ae25edb31abf6797596cf9b4a943972a4a19c43db1926c18bf15fc526127d1b04211fb4f4fe4c34dba511e8801a10008e54d343386c0c096641681899e65d2afea539fec10a2db4f07a06c7745c1005d0c2b1f020bd80e052df5a4969a40602d7b4350068968bae7ed03d05c9f0e7dd8940d1e37cfbf3370f5953261615197d350c60c2e3bdc186eff30d0700e608a4e08b2cac91f42275e3e6378a0747267335e017b5342a1662df7f3144a5c0e08008460631d2fb76c410c11c4dcc7f73fcab23a4794775f4284e02ad1ba71d64db4f1f4ced92b7a389fd596763283771b9faf89865c462f59e57a81cf8c3cbeffb268f00b6589ab79483f517583bc3a949c0df139721b6dcb9635dca559ac670c1b3ac3ffae886d18134df6d3b7078928ad5370c9687de2846d1f89f7455cf1f7bec56f3717cbdcab9a5fbe597f929e432ff093d92cb35d625bc8c5dcdc4df998db4b51f74775e5d6d119c505a2d0f27c9ead9e84af18c5d7e258cb6a4b57d28c5be27c3d72e277ae3a79bec39bdc88df392b2df6afcca55f79efb3fe6d0d8b50d7c8bbbc134450db20f1d5a773ce9cdc3b97b3274cb2e9c85496e9043e1eb83bda1b0960808b7dbf61fa0b420596976194a598a6ce1066867d13ed30035f8ff0ba3dcaa15df0cab8b96807cb82435a42067d4f1257de536842db0d3f7dfda891c146d79b600e6a2f994f2755cb278becfdaaefb2c7b976be36689c7a0feced48a723be73f29851f75e42e9d62c83d6aa220891c5c24634e8c7cc3eab033046727127a802dacbde8cf629c1f57d59ba0690af43ce944607c1fd9df72f74d67e7ddc2efd8dc6c459d0d1fe2ca57d14e20046f139050206dd8d203e0389aef6682cc6b861cc364184ee9708452dcb732992ce6dedbb8d57b5c5689b9836c54cdc91b4766f618d608d4bb380614d8cc2e03b3b3b5897ccb61f9fe2d16e5ced34cee9e856a6c52324c0eef64a4b7f9e8e7ed5a71d7b1fe9f94665ac75da67d114047ff5a1c3d0668d43d78c12565ea154f763418049e8dd3a1929b7fa4877c9e2cd984ab94818219a05b196b643adb3f064dbffd2b22ade017488178c5361a1c93f9c615e0e0cd28f25b7ca582d6942071cb7fae17b52eb41ead6e78914945802c19bac16c76ae14c7ed4be6e42713e8a4bd6220aadf458fa15b40777f94e223c596c7f80bab9584fcf4ff14f138adbbf7b1a7bdd686fa9249fe006aea38651e410fd4b1af0d79d7f1ee0cb2711ca81382f15804771da4a18d5f20e10ff9a7abd6ae8583d94f58769f3401526e517d963800c92485f9c24eac2d914895d4d9b866bbb769d22a00db29ce0b9a7d7112defb15d9776db55edf8fca337b1a496c7710acab8135aee0261a780ef6b39664469e33dab2398639d1becbdc74000b36c2ca5df2c0d3c5d3d3e054a2b8d91bc4656cf09300dd084cb0b625a587fba81cc6c2c3ef6f93342b65bc0e68222de6908492ac431f9f4dc1d3915a2cba79820c8c1f7c6e5c582d953b60a943eef44a6e7b244c808fb292f3944a4b1afbbadb06ed72c1d2cf9a60e02b319af032eddb475ae1947175f437262cefe05a89dc92367c8f8223e3a415b080b2bee22f084d00a289e42f5dcd0c31dc257d6bd09d214fad7aaa03d285a4ca618a5cc2bc0167ce424c40b879bfc294b9f2be0ee1c4669fe57d15c3b8fd626507ebb94d7313eda527d86a2bcaf9234a6eb4fcd2ecd218607961c7816094311a762d783ab7cef7009f103d938a5dee845b827001c87920ea3110b97b40a8525c41a57a03e389d9d864c57e10a849509135cdde81b89da8ee10540b76fe6c303a98bfa68a493ff59104b41c34c62092d3c0cc16d5c5c9abf7d0cc9206605ca6b69511091b512063985b03549573fbe60036cdfb28e77670e99b55a8f8151035ac93ef64b77f36951b0d3a31befef14741f874b313b66908f8da53a8a95255c16019876c85dd6070b2a8470f303b98d3c9ce2d203774794ecd2dbc43a69cd37c21f9c971634ff7b00af46adccaaeb1ca346bbdcad44151e38a94d91339c425554791adf2d3ff197221979625d2993ef7f4af06ec2438ab780ce737ac1bdbd873fa3b5cc0af43097b2be36bb9cbf87d39d3a7d54d5a49b176a3d74d95c06cd9b665248f84c27019f7b62232d9de01396aa0096f36c399b762913e207de7e3d24a2bbb04d879fe29b087ea262e82e4b3ca0fca62f222a592ab6ca1b1609e6a7500b8ed38db0d895c2df29604a64540e796787461ed7d1c5c562662b8f5146839cfbae18a6fb302033ad6558ce8a9d61d5de662b995ecb228535cddd02aa051321dadfd06dcd6409cf98d8a8697c7499f1695f173b427ff5f6cfdd224b66b89682d0e2978710e2bbfe7c9f2793cd2592ec7106c44e46c1d2bfe9d7cb53cac640f92f66506aefcc11c983e6c284a892dfc4b813771087baf9150eeb019ba0877afef77a66ee91b2c85ab1b95cc670ae9e80a4f20b8c8914c655828a68d6e8b509d479b5d04980a5bb17fb9ef17060f802f6e6f57e29d6587d6b8dc3438f592db639f718cc3bdaad6865d8a6aa94c47e1061cb8dfb8d7c54c168a29e8b1a78e1716ce413d429daaf09c924a7cde44eafc58fa5b3a5e3aa387a9465f024f7fe6ed9343d81dee65d106f635bbece1c99d5eb8ca0487c00c2851aaf24b2b6003e7150758f5a50943de2ba7b95710fa05f1c1e305dd7a14dba19feb94c9591d8cf724ef55aca7fb8e054763f7c80027b929666f6864db25a059859ca8831f9b7251e38eda5b00d0fc64a3b3460bd7ad733b9eac508a6a191a6465ca14729214d29cdfef5c6409a3f7e5db2044f836c049f5a14a78bea5c7a55e957a53d8d7d97203de65090319911c1788fc704d9382571d3d1bd2b35927d8d95b3f3b14930350ca34d577ff1d4ab69c7ef9f74f73590b8fd0d3574e7779e7f6564f9245c117c4272054015715a0671bcec7416d95a17da00b50e976168b9de75b673f6998119eb1c3b2bd1eebbf21aabc7e606991dc2e802058344d4854b1fe88688873db69c8ac70a9e4850960390a510231dc7159e3e89be0162258982be870d6135b0870986f66c19cf315552165fdccdd2acdff62cddeba67ca0e9578ab629d895a81f63c2262362a49ef4bd8a25dbf73fd100844496f40753d1496bdae8cf60f23db024ec56dbb594e9047ef5b005f579ff829dc1c3cf6844dd8bdcaf644481d171cec2bd25dce58a23617d5d11d7d44465214accb32a5767548fdfe3a428699ec03d02fbc2ccf1237ba07249af6f37ea83ddd8c7ec77f56ae7025c5662ecee8a8682d61823ec04bfebd6195147b016a28112821ad0f2aa32110dd31b38027f0e7fa042cce3e52ec467aaf95f998db202f819f201ee1322215018824a880755b94a2876e09e4c0cac01005ff8885e5f2f21c28b1aab38c62c33de0268521db2c198d19e7fafe69215465f6421b8503218f394d5a94c8601dd6514ff8a80f442ce07a4de65060229285b873667fa19859753c4b949ada2d3ab20afb732a4d4f0a9e5e13ef5a50c8361a465874e956464e201de1f30fa97398d3636ce88e479428b0bd8521010b92a22b4866c311593c101e3ed6169242c63334c7d6715a6dc50063e1c5658f590d0177464461a2ed8892719a770bcd687c597d51d46b89640b6610bc107a6b6d23e46052680aa18673", 0xc01}], 0x1)
r1 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r1, 0x0)
ioctl$VNDIOCGET(r0, 0xc4104603, &(0x7f00000027c0)={'./file1\x00'})
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x4)
msync(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x81}, {0x5}, {0x16}]})
write(r0, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xfef3)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$inet(0x2, 0x3, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x1003, 0x0, 0x0)


setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x1, &(0x7f0000000080)=[{0x8a}]})
r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000100), 0x80, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x1, &(0x7f0000000180)=[{0x1, 0x6, 0x9, 0x2}]})
sysctl$net_inet_ip(&(0x7f0000000080)={0x4, 0x2, 0x29}, 0x4, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x200000000000032f, &(0x7f0000000040)=[{}]})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x40, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000001440))
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
sysctl$kern(&(0x7f0000000040)={0x1, 0x32}, 0x2, 0x0, 0x0, &(0x7f0000001440)="cca410df", 0x4)
rename(&(0x7f0000000080)='./file0\x00', &(0x7f00000000c0)='./file0\x00')


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
r0 = getpid()
accept$unix(0xffffffffffffffff, 0x0, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x100, r0)
r1 = socket(0x18, 0x2, 0x0)
r2 = socket(0x800000018, 0x1, 0x0)
bind$unix(r2, &(0x7f0000000080)=@abs={0x0, 0x7}, 0x1c)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
bind$unix(0xffffffffffffffff, &(0x7f0000000180)=@file={0x0, './file0\x00'}, 0xa)
getrlimit(0x8, &(0x7f0000000340))
r3 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r3, 0x0)
setrlimit(0x3, &(0x7f0000000140))
mlockall(0x1)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x401})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000040)={0x0, 0x3, 0xfffffffe, 0xd2d, '\r\x00'})
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000480)='\r', 0x1}], 0x1)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000029, 0x3e, &(0x7f0000000000)="5ab7776a", 0x4)
r1 = socket$inet6(0x18, 0x3, 0x0)
dup2(r0, r1)
getsockopt(r1, 0x29, 0x3e, 0x0, 0x0)


openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = socket(0x2, 0x3, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
syz_emit_ethernet(0xe, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
ioctl$FIONREAD(0xffffffffffffffff, 0x4004667f, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="0002"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
socket(0x0, 0x0, 0x0)
bind(0xffffffffffffffff, 0x0, 0x0)
connect$unix(r0, &(0x7f0000000000), 0x10)
write(r0, &(0x7f0000000080)="04bdfa5d1d2873c63e3534825ba166e2fea9aec43050006123339a346f731573d8d508753f95b7688ad48b8cf6bbca325cebc37fc4e1dd543dbe2da6dd", 0xffea)


openat$zero(0xffffffffffffff9c, &(0x7f0000000380), 0x0, 0x0)
sysctl$hw(&(0x7f0000000000)={0x6, 0x14}, 0x2, 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet6_ip6(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
sysctl$vm(&(0x7f0000000540)={0x2, 0x1}, 0x2, 0x0, 0x0, 0x0, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
socket$unix(0x1, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$wskbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$WSKBDIO_SETENCODING(0xffffffffffffffff, 0x80045710, &(0x7f0000000080))
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(r0, &(0x7f0000001580)=[{&(0x7f00000000c0)='\x00', 0xfffffeb0}], 0x1)
r1 = socket(0x11, 0x3, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x40, 0x0, 0x0, 0x2}, {0x1d}, {0x8106}]})
setsockopt$sock_int(r1, 0xffff, 0x1002, &(0x7f0000000000)=0x1ff, 0x4)
sendto$unix(r1, &(0x7f0000000280)="b1000503000004000000020003000000331c13fecea10500fef96ec0c72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b1257aea8c500002002fbfe0c2300008abfba0900000008e371a3f8343712051eeab71d89e00004070000000013000000", 0xb1, 0x0, 0x0, 0x0)
r3 = socket$inet(0x2, 0x2, 0x0)
getsockopt$inet_opts(r3, 0x0, 0x13, 0x0, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x401300)
open(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)


mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
openat$wsdisplay(0xffffffffffffff9c, &(0x7f0000000300), 0x10000, 0x0)
ioctl$WSDISPLAYIO_LDFONT(0xffffffffffffffff, 0x8058574d, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x2, &(0x7f0000000100)=[{0x84}, {}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
r1 = open(&(0x7f0000000000)='./file0\x00', 0x14800, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$VNDIOCSET(0xffffffffffffffff, 0x81946467, &(0x7f0000000180)={0x0, 0x0, 0x0})
ktrace(0x0, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(r1, 0x80185760, &(0x7f0000000080)={0xce3, 0xfa8, {0x8, 0x3}})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ioctl$WSKBDIO_SETMODE(0xffffffffffffffff, 0x80045713, 0x0)
r2 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r2, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
setsockopt(r2, 0x0, 0x65, 0x0, 0x0)
r3 = socket$inet(0x2, 0x3, 0x3)
socket$inet(0x2, 0x49fd2a714ec58914, 0x8)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x100000000000003}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r4 = socket(0x18, 0x1, 0x0)
setsockopt(r4, 0x1000000029, 0x2e, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r4, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbdf13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt$inet_opts(r3, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
socket(0x6, 0x4, 0x7)
setsockopt(r3, 0x0, 0x6d, 0x0, 0x0)
ioctl$VNDIOCSET(r1, 0xc0384600, &(0x7f0000000140)={&(0x7f00000000c0)='./file0\x00', 0x4, &(0x7f0000000100)='./file0\x00', 0x8})


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x26, &(0x7f0000000000)='\a\x00wj', 0x4)


socket$inet(0x2, 0x0, 0x0)
socket$inet(0x2, 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, &(0x7f00000001c0)={0x0, 0x0, 0x0})
r0 = socket(0x1, 0x2, 0x0)
openat(0xffffffffffffffff, &(0x7f0000000000)='./file0\x00', 0x80, 0x0)
getpeername(0xffffffffffffffff, &(0x7f0000000080)=@in, &(0x7f00000000c0)=0xc)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x3a, &(0x7f0000000240)={@random="91a6e34dd8bb", @local, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x1, 0x0, @empty, @rand_addr, {[@timestamp={0x44, 0x1}]}}, @icmp=@timestamp}}}})
socket(0x2, 0x2, 0x0)
syz_emit_ethernet(0x138, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206919, &(0x7f00000001c0))


mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
sysctl$net_inet_tcp(&(0x7f0000000040), 0x8, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x32}, 0x2, 0x0, 0x0, &(0x7f0000001440)="cca410df", 0x4)
openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000040), 0x0)
pipe(0x0)
fsync(0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x200, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
dup(r0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
sysctl$kern(&(0x7f0000000040)={0x1, 0x9}, 0x2, &(0x7f00000000c0)="24b8b1ef", &(0x7f0000000100)=0x4, &(0x7f0000000140), 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
symlink(0x0, 0x0)
unveil(&(0x7f0000000100)='./file0\x00', &(0x7f0000000140)='c\x00')
r2 = semget$private(0x0, 0x3, 0xb7)
semctl$GETNCNT(r2, 0x0, 0x3, &(0x7f0000000240)=""/65)


sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, &(0x7f00000001c0)="86f4bb9cb7410114ad65c6bd1ec1811693e9bc83b5", 0x15)
ioctl$WSMUXIO_ADD_DEVICE(0xffffffffffffffff, 0x80085761, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000400)=[{}, {0xc0, 0x0, 0x0, 0x4}, {0x6}]})
syz_emit_ethernet(0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001280)={0x0, 0x0, &(0x7f0000001200)=[{&(0x7f0000000180)="bf3b684c5ae963b4567084e096cf973983b85e5df63e013eaa9405095e88157332b4f68e78e0793d3e30417acbf4419893cfd424b75262dc5ade2ab6278ab86672f9ed186987b8c19d9295a17b98020f6002", 0x52}], 0x1}, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0206925, &(0x7f00000001c0))
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x7})
r2 = syz_open_pts()
close(r2)
syz_open_pts()
ioctl$TIOCSETD(0xffffffffffffffff, 0x8004741b, &(0x7f0000000140)=0x7)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
socket(0x0, 0x0, 0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket$inet(0x2, 0x2, 0x0)
socket$inet(0x2, 0x2, 0x0)
dup2(0xffffffffffffffff, r3)
openat$diskmap(0xffffffffffffff9c, 0x0, 0x8, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f00000001c0)=[{&(0x7f0000000080)}], 0x1)
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x889, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x53})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000080)={0x7ffffffe, 0xfffffffd, 0xe3d458f, 0xffffffe8, "1500d67d005b860000e30000008000"})
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000300)="d06e494046b25e54be676d1999863e908452ec9732ee0b3ca291f0b82d22d0c618b663d20da051eab30bae2f3fc4fa4513a2b56506fcc4564d1a644491ca9b5a3b169904e0b0b5278220d72ea53d149e4794b512abbc061c9b99546ce6b6abdb314a1e7646272aabe1ef9c1bcdfbd03977520229683293769b3e90", 0x7b}, {&(0x7f0000000380)="f77bd727d7d95a9eeec9eb31591df85f8bf4ee3eb9205fa093987902ae48f978f6434f6178ae962270041524dec1ad4cf7acf7d52ac09bfd56c384240e5626e72d0ca81a44ae032d1bfd4c9ea27c954addea6d8a966b5bdcb9dbdd565c47ad7fbba862dd1261f9c5dff7713d2a5e804a5d27a1f16c1767049b4e21d8d7a34563bbd31c29c3d868", 0x87}, {&(0x7f0000000540)="cfc173f4233367fa2769a351b5b229468a347da5fdb6906008005f3d9e816ed5a66c4b1847f5a741e15108e08ac739d7fec283236e8cac673b321f9715fcf8ed21565166f92e8032a4e24a9b0ae81e33a8e6ff237249a3c4736b68ff37528d80a96b97ef9c127f2dcbf928b4d9d313274d28b00e1d3d331e4fb0716b79e2c0f4cb95585627956d1e018947ab7c9fed5ae6b1308fe0c408ffb45ce7476dfa03e350463ce9b00a7112d17dc33dcef5ce187b24ae7669105d54e17db063c6e7e9283efc2071c09e63c8fad855f80a621261d4fcbee692e15383aec45dbc5dcc38b54481", 0xe2}, {&(0x7f0000000640)="fd7999a2822133827e04627c2a1bffbd03dbace4d06e90b0eb6514911b3177174ccad5dc276db8ac478dc5a1669a31585e354d88080354d4eb30c852a20f822b62374109e34dbf709fd824d2313e016757b5f401c91edf2fdb79085e875b3fd14c8c6971555f1ee4374ee2b652bae4c99dc973ea95a8f0c8508c4c426d3db4f79c8f5ca559733bdae47d38d78d68b5b4c8e200d99a799e8cdfc1568cecaa5430e0e98355ac35c2c6fd24385c60f3b162ab0622e239fcd3ffbfc5888cef452d2758bd126019ed6408", 0xc8}, {&(0x7f00000009c0)="e1548f8818a5eee9afe56b3448207fafe162607e49af44da61257922a16803f9b7193aefd2b2af96f82bfd932d19b6461dd542c167e5bd5df064b1b8f3ca363b710f4cdb12511943a4879329403dd767f669fbb1d6a56c6ce773708922e74219a423f5e5198a2a9bd4a9932c681dfbe40e42ccc0e3f363df0eb0c986259a508e3dd4c414546adc139f6711164f30b1895e8ff9a6601930237a7efd51df01ccbefba568b52c4abd9780c8060f56ab76ee4cc4c533163c4a5b1a0edac0c9e76bf34458a48fbbe2f8f5aaaf8bea84efd45d5df6a93408b92441d764dd84dab05b3700981c1ba2ecc232bab41e7a89c35a2231954fe96d7e44e5f23268ab88b0628ed1eccb297a605140f1893dc3e62699fa430e2089b0cc7ec1fdd63293e4573dbde3ffb210f0b528279a55f10f7bf88f9867d61bc4367e2e4f835311aec3bdfa7b4f1c899fa8af52b761d3b4f8f5dc7a40ac84e1ca9e501f0f12bc02b8d8b7a7e8c54b4b78613a6b535610b16ca994a7e07c6c1ecd3a12958cad357d90ea4fb0dc3891f1901d9f502f17c4f54ac3e8151c8bb66e6797759e5e92a4c98e406a306e8d3a3bdd77cfa9e00ee0928e6d1178e30bc57b45dd9a0369df0e8ea875f1dcce4d82114d3b19911e464ad72d63d86997567c99ae7209a1689483d45d1bc3f03cb412eaabfd2798541d516c3c0b35f02d838d018d71020ba66a0897d5cd44a824c0fb093a7e166f0c357e7eaa19c664592b60497183ee9c2b256ec214514edc4ec2260ff9232a6a0ba0bf2cbf808fab6e9dcc8208bd2677ef24bf8e4d706fa9f2446df9fdfd33512d0e49db9e9d09eb22d30d2feab896135b4bb923eaf5dca05b953c0df96f8c3acef47df04bd95867884b25ca9428a614cd79cf3253d4ad8e5ff9b75cf180eaa88db8aac8abaaa195cdb27b535976dbfd4194c97ce815f924872cd89280b9b1b942e625cd0acb18d227d888eb1282e43c90547f69b575af2a1d0700aa95d00835d713723af6c671d6eb111a42f4419ff9a0ce10d0fcc8b466a66b1b90ed184f1d41d0a699248ecd4d4fcbaeb94bc52e4a13d21aa24c3dd7f4ebd2ec432dd72f9a8c6f7118ee814333f4e8852e1f77c871891b103f489184baa9b1d0f005537be346dbb059470426ab3a446c5b17b2476c42707e43076fdbc6ac06b9e825f47f5831a4433a1711ca91db889457667c4219446077f4644e0098bc0f9f36aa4a09d704e5887d0a118fd6e46ab5c6bdc5ed4e37a52711d5a217154a87fd36ba4950cdaf226bdeae4c6445f535147b936fae392ce1ca598c69a41ce4ea3b1afb08c8925e1548c171c48f39d10b0da230d0d8c0cbffe8dea6c17201977323014d4cee3792a005eb13491d8fa78926cee5a76594e30c91022545764e0f7c02ab609491cf1064c35a94e5ddd1f25dd9822863b6aeafe59a34da8fbf3cda8a068b301b6e0f59f365a9105eb6bb00b04e3120c7da99799bfd198de05e128076f9d36a3909e7b8d3f33ea321fb1b10254a7e630ef5e378c9b00e750bf562604c2f18593e4a9c8a93ddba4e3c5f094a39084659270026c23a3b18075cb9ee51d791cfd67ceb4e4ec3df220e2ab259c31d5810b998e635fc73a79dcf58eddd990a79aee9e82ff9eff6d1e691654e85b3170a05f3e0c140f16eb0b84f1df6578a632f1279c6c1dc4775bc68f79554c7f0f21926d3921c24de183833b74e65ebcf0d180711bd0aa7b548ef34b7fe29fb4cbd3db829f361bbb161d359c0c0d77d895fe6174ecf4ff34d8dd53cacc6db44008acf5b213b91d264d9e1ac6f8d0964fecaf05a3bd91cf994d5b2a400f261e6146375180e1457ff63d85d1a1fbf88d3c2005be30228fdb1acebd6f4dfffb749239ab9ee140a33a9b6c8a4f0065887a2872cb63897b22c36b41f62d49c4258442d0e067bdd87895e6ea43629f825314adb367c351e88c18d963352299a4b8fadd7d705b1469fee746a5f0327b492e45c0a930d5e64347c2c10acccefa1f504272206669061315472696d3ad9556d2cfa8c6dff2ffa7338f2e434a9c8c919aed1df1eba968ebbe0053cbf6a21b6f72d11d78f28c370dd692009669642444625495584d4d6ccff0b424cdc5ac5d6ce14738249f3f7027ac010de1c4082a52506cdb39dda7986fd087cd417e761a651e3c02e3ca5cb64e9cef0e8ac9b5270ffc7da700b6d202a149ae8f87db3596673f3f9593864c365fd4ce9a068c470643c4e305de8cf408a68bde0be3eeefb3a564dc6c625461983a5d9430d7a2338d5e3297a0060aede9b4e60db1c4e533c635c7f32ce339a36964c96e352d34e4687aee031fa29679dfdf9223b28944de009f85d1024d1aa70ea5086a6485d9da648afaef5815511706c5a18f4f5c0bb41fa96576474521fbfcfaccdde0547288816b476763394b45857fb99fb2d204db025830800a970ee91127a0a2fc81be1784b6950f02e30a0e25c56126594b003659b3224bf54ce33bdbefcf9fa391ec2ec2b2454c78b8d4fe7d8c3bab27f8fd58f9f9b7c9030e2b0543f47da50f19180dff6fa19d4b24862785e810eac0820df52a1d5ea96e888137ede35bc4f31e8b16b588f6e40b696f08db6c6b9fe4b73c285313cbad78f43001d0fd95b0a6e937a9bc2169a4e519681675414783d1def2692c5de482745f0baeab8b847f4b0cff2542fc5429395444ca84bed4bfabbafee6d051081a332560c6ac5fbabcf26fe882de0c04180abdebfbe7a1dfa3d6fec4da4fed0513521378da8239991cc135895588452da84737acdfc47590a3c833b7020ae47fe52acafcad2e119882f2f8049e7fcb530dfd7ae21353001ee748ecb43950b30c65b833c8e0417d883231260a0a55a9f5947c6ba5f95ef136e636873f71759571ee1358abd495a10b69fe628589fa94e6d5bafeb783f10204c160f5bb237d6230cf063db0cd355c7a217129e632499c61f3f1bbc5fdf7ee978092b8bae88396c03f189aa8ef20877d7971b8bf568aa37096d756abc861b1755302256f521eca6d6c88af662e651230560eab84197928cb9b833b210e5ff52a03f72642859c822be9bcbfa07b1a698d6eb63802052a95441de8c019697d283dc690d15f9c3832d8707a6f1f74264546108b792252387284a5196d01629f68374ad1b6794f8b40385a9b80db16348de3c5d10d182f8ce8f79f97c134dc8cb0454b0c37c6053df59c555b0811f0c85b7a836d22c728b44b92647b095adfb5f2fcd79e4cea29a3bb104ce99e5792e41bdf274aa90fb0eccd0cd5275e9e31445f40ce3bf33d97d22b14e17cb9d7c8bb91a4f1532f0d4fea127143b2004bd682a682d36c81603ff56bd86730e4f7a1edc77e4b128ed77d9ac8e348e7fd99166b6c2295727f01b950427c83a5026befccef56747", 0x967}], 0x5)
writev(r0, &(0x7f0000000500)=[{&(0x7f00000000c0)="acabcf121c66403989618f102986590fda96cd6ce3e6319bfbfa5f4e11792ff556376e0a66db2064e7fdd436d5e11d47b40f598865ae30e4577e64f3cea3db7406d3f30fcf81af59f08cd850e080468c406a2576d93a6e610ace0fe401b3af94886a9209a9552e5231c14d5842ce811ae17ac41ca78ffb36e5d9a788ac68443f49b920121df80a106ac6859fedff6187d880e9a8849805a46b28e6ef435d45e7e0343d939f21ef05ff3e31f9b2777b169b10c28b07dc4845ed10f14a549e3c0228e974f48b0b191f74acbb8c4b6b3514b384444d10c203a141c90bf928db", 0xde}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000140)=[{0x15}, {}, {0x16}]})
write(r0, &(0x7f00000001c0)="d9537abde93d050cdd16b13f742a", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f00000000c0)=[{0x54}, {0x35}, {0x46}]})
writev(r0, &(0x7f00000002c0)=[{&(0x7f0000000240)="e049e64ada6fa45d6bee0bf84a9e", 0xe}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x2c}, {0xc}, {0x6, 0x0, 0x0, 0xfffffffe}]})
write(r0, &(0x7f00000000c0)="76e5dead6f01f8607d2100000073", 0xe)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000340), 0x2, 0x0)
write(r0, &(0x7f00000003c0)="370baaddbc8de3e745c21763258cf21b26f9c14ae137ad404aa12a842274260c15e9072ef107064cb5bbc31fa207373188cc4f6e0b31cf2157d1c80cce06c3e2c5d63042b0c8aca477934fb28d0425889137bddf0fda373bfd492b1d432b9c9934237a3b03782b1689fd898c90d3ef7dcc3fcaeb0ae0fc2780b3114717b39d56de7b1f2073baf0fd17567baf846cedcaef966e2e2ea9", 0x96)
execve(0x0, 0x0, 0x0)


openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
setsockopt$inet6_MRT6_DEL_MFC(0xffffffffffffffff, 0x29, 0x69, &(0x7f0000000200)={{0x18, 0x3}, {0x18, 0x0, 0x3}}, 0x3c)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)


mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x8)
r0 = open(&(0x7f0000000440)='./bus\x00', 0x200, 0x100)
open(&(0x7f0000001700)='./file0\x00', 0x0, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x4, 0x450c)
r1 = open(&(0x7f00000002c0)='./bus\x00', 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(r1, 0x80185760, &(0x7f0000000080)={0x0, 0x0, {0x4}})
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
sysctl$net_inet_carp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x1}, 0x4, 0x0, 0x0, &(0x7f0000000000)="00028300", 0x4)
socket$inet(0x2, 0x1, 0x0)
listen(0xffffffffffffffff, 0x6)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)={0x3, 0x7fffffff})
syz_emit_ethernet(0x2e, &(0x7f0000000200)=ANY=[@ANYBLOB="aaaaaaaaaaaaffffffffffff0800460000200000000000019078ac1400bbe00000028303000009009078e10f46cf0a07a78a54a376d40c27ed11e00db0774c2acae1148576fe"])
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r3 = socket(0x11, 0x8000, 0x0)
sendto$unix(r3, &(0x7f0000000140)="b1000502000000000000000001010000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc256699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)
ioctl$BIOCIMMEDIATE(r0, 0x80044270, &(0x7f0000000180)=0x802)
r4 = dup(r2)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
syz_emit_ethernet(0xe, &(0x7f0000000200)=ANY=[])
select(0x40, &(0x7f0000000380)={0x3f}, 0x0, 0x0, 0x0)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
sysctl$net_inet_divert(&(0x7f0000000100), 0xb, &(0x7f0000000280)="a7c1290f17722447b2c63e743f6b379fa5267a394a5d94db9417b6982f519b111f61ad994119ba843799517c2ddf4c65594fb3b55a5fce717f619f904ce7b41e4296cf777a1db4747703440100000023e48310b779f9619c7642d6d7f500000000000000000000000000000000c37a11ae4dbe56deeb1ccae6d8e73f8976b460abc78bfdf1bf11c3ec2956f559e2ae95b19752a20f358e90edd96264cbc18906750f34e7e595d09e4e313414f688d6388b713904a7996cc92a328db185299eeabc8e35147498451c4a84a9d41bf693affdc27f4569379570f4", &(0x7f0000000180)=0x67, &(0x7f0000000640)="e2714be05c6a432bfcb43ba70e2bb9e6add925cf34d00e465191e199efee4898bfe502dcc0a3e3fd0cc0e7969055dcb470ddd2f263dfb8065cbf63d41b2a29e4f92695a2dae1e619ba2b0ccd1e605cd2827beb6ddaf6b579cccebb6d267a74d6af9f2cddd1eb38180245caf3e0f240c5f1ee52a05a63c446df6149316cc2e17b775698e9114250d85ec893fbd204889e5c3f37ee5894227fa7b36a2803d9c558953caa2452fff1bf82f49299d2fd07d8a464fd351d966782d21806ba5be9dc66d7dd572cdae3822888010771550dd55b3014876e2537e33b838b12b10d843be49e4cfc3b3f04a60088dd3cc3fbdc16864e028753d898f0bc0bd6e20f96274d743755332aebcec91d4f490000000000000000628c7c526f7de4f21b6260bacfe436d6eb63a96ded0b0f29cbc8ea2a7d2760b1fdf551506810d63132c72c14be5ffcc53ca339aea237797e863010f33b057982b6825dbdef1ce4425ae7d1234ad5cb69", 0xee)
open(&(0x7f00000002c0)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
link(0x0, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000000040)=ANY=[@ANYBLOB="aaaaaaaaaaaaffffffffffff86dd600625200000000000000000000000000100ffffac1400d0fe"])
socket(0x18, 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f00000004c0)=[{0x4}, {0x4}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000080)={0x10027ff8, 0x0, 0x81, 0x5773c544, "944c8f62b57be2df6707049c8bda98612c2100"})
writev(r0, &(0x7f0000000580)=[{&(0x7f0000000140)="b868b4e47ff0e57fb99bf049535c0a063153f6e2e3d7860f948f2bcfe59a04cb9f96ab8960e4f272127f555ca8", 0x2d}], 0x1)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000006c0), 0x1, 0x0)
writev(r0, &(0x7f0000000180)=[{&(0x7f0000000600)="b8502e", 0x3}, {&(0x7f0000001700)='.', 0x1}], 0x2)
execve(0x0, 0x0, 0x0)


kqueue()
kqueue()
sendmsg(0xffffffffffffffff, &(0x7f0000000800)={&(0x7f0000000040)=@in6={0x18, 0x1, 0x0, 0x4}, 0xc, 0x0, 0x0, 0x0, 0x3d0}, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
sendmsg(r0, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000001300)=[{&(0x7f0000000000)="f41f041e3a30", 0x6}], 0x1)
r0 = socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f0000000000))


pipe(0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1000100000001})
semctl$SETVAL(0x0, 0x2, 0x8, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x6, &(0x7f0000000080)="ae215599fed2fce97f573b9c553a0e622d29cd093849cd4fe42e0f5d2d06a4e744f0713d1fcaa1b8274dffd067d413ef9d2224d3fddc171f73a295b6ed18b3d0588be75e78a1d734e15bfe", 0x0, 0x0, 0xfffffffffffffd37)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x100, 0x0)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
ftruncate(r0, 0x8531)
setrlimit(0x6, &(0x7f00000000c0)={0x6})
sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x1c}, 0x4, 0x0, 0x0, &(0x7f0000001100), 0x4)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x8000000000000004})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{}, {0xdad}, {0x2, 0x0, 0x0, 0x3}]})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000006, 0x0, 0x0, 0x0, 0x0)


r0 = socket$inet(0x2, 0x8003, 0x0)
setsockopt(r0, 0x0, 0x1f, &(0x7f0000000340)="15337ac0", 0x4)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
r1 = socket(0x2, 0x3, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
setsockopt$inet_opts(r1, 0x0, 0x0, &(0x7f0000000040)="591fe53e848a2df0f282ad8ddfe55571740d57c69f75fc838a35631ea9f2ab5b6caa14e00c5b98957c580be18e5f", 0x2e)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r1, &(0x7f0000000000), 0x10)
write(r1, &(0x7f0000000240)="14bdfa5d1d34e2fecb284a6498307dcda9aec43050036123339a346f737850551408753f95b7688ad4c4e1dd5489e7bafc58d3e5823757ae8b630719ef187ccad995f13dbe19a6dd4e6902bd8297b0799b426aabe9fad9db6996571c6d9f8bb5d542c2148aa42be940970fe88d34d8f99afe7e7820237400000000008000000100"/138, 0xfc7e)


r0 = semget(0x0, 0x3, 0x0)
semctl$GETPID(r0, 0x0, 0x4, &(0x7f00000000c0)=""/198)
r1 = socket$inet(0x2, 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, 0x0)
r2 = kqueue()
kevent(r2, 0x0, 0x101, &(0x7f0000000180), 0x6, 0x0)
r3 = socket(0xc, 0x2, 0xfe)
ioctl$FIONREAD(r3, 0x80206913, &(0x7f00000001c0))
setsockopt$sock_int(r1, 0xffff, 0x1002, &(0x7f0000000000), 0x1)
setrlimit(0x5, &(0x7f00000002c0)={0x8, 0x1050})
syz_open_pts()
open(&(0x7f0000000240)='./file0\x00', 0x0, 0x0)
ioctl$TIOCCLRVERAUTH(0xffffffffffffffff, 0x2000741d)
shmget(0x0, 0x1000, 0xaaa8262b682905a6, &(0x7f0000ffc000/0x1000)=nil)
ioctl$BIOCGRTIMEOUT(0xffffffffffffffff, 0x4010426e, &(0x7f0000000080))
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r4 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r4, &(0x7f0000000000), 0x10)
write(r4, &(0x7f0000000240)="14bdfa5d1d34e2fecb284a6498307dcda9aec43050036123339a346f737850551408753f95b7688ad4c4e1dd5489e7bafc58d3e5823757ae8b630719ef187ccad995f13dbe19a6dd4e6902bd8297b0799b426aabe9fad9db6996571c6d9f8bb5d542c2148aa42be940970fe88d34d8f99a", 0x71)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x5}, {0x14}, {0x6}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b100050300000400000000000101000000000000cea10500fef96ec0c72fd3357ae30200007804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3eea3c57699a6443a42102000000720fd18b08fbb670c1f5a872c881ea6e2ec5890400000000008000361b1257aea8c500002002fbfe0c2300008abfba0900000008e371a3f8343732051eeab71d89e0000405f8ffffff13000000010000000000000000000000000000000000000000000008", 0xb1, 0x0, 0x0, 0x0)
kqueue()
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x80, 0x0)
ioctl$VNDIOCGET(r1, 0xc4104603, &(0x7f0000000040)={'./file0\x00', 0x1})
setreuid(0xee00, 0x0)
r2 = getuid()
r3 = open$dir(0x0, 0x0, 0x8)
r4 = getuid()
chown(&(0x7f0000000040)='./file0\x00', r4, 0xffffffffffffffff)
r5 = socket(0x2, 0x2, 0x0)
connect$unix(r5, &(0x7f0000000300), 0x10)
r6 = semget$private(0x0, 0x7, 0x3c0)
semop(r6, &(0x7f0000000180)=[{}, {0x4, 0xe6, 0x1800}, {0x0, 0xfd, 0x1000}, {0x1, 0x20}, {0x2, 0x0, 0x1800}, {0x4, 0x9e, 0x1000}, {0x2, 0xfffb, 0x1000}, {0x0, 0x40, 0x1000}, {0x3, 0x8, 0x1000}], 0x9)
r7 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r8 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r8, 0xc0106924, &(0x7f00000001c0))
r9 = kqueue()
kevent(r9, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
ioctl$FIONREAD(r7, 0xc020691b, &(0x7f0000000200))
semctl$SETALL(r6, 0x0, 0x9, &(0x7f00000004c0)=[0x0, 0x1001])
getsockopt$SO_PEERCRED(r5, 0xffff, 0x1022, &(0x7f0000000200)={0x0, <r10=>0x0, <r11=>0x0}, 0xc)
setreuid(r10, r4)
semctl$IPC_SET(r6, 0x0, 0x1, &(0x7f0000000240)={{0x8001, 0xffffffffffffffff, r11, 0xffffffffffffffff, 0x0, 0x40, 0x2}, 0x0, 0x9})
chown(0x0, r10, r11)
fchownat(r3, &(0x7f00000004c0)='./file0/file0\x00', r2, r11, 0x0)
setreuid(0x0, r2)
sysctl$net_inet6_ip6(&(0x7f0000000000)={0x4, 0x18, 0x29, 0x36}, 0x4, &(0x7f0000000080), 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000000c0))


syz_emit_ethernet(0x3e, &(0x7f0000000100)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa86dd60362f0000008000"/31])
msgsnd(0x0, &(0x7f0000000140)=ANY=[@ANYRES32=0x0], 0x401, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001280)={0x0, 0x0, &(0x7f0000001200)=[{&(0x7f0000000180)="bf", 0x1}], 0x1}, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0206925, &(0x7f00000001c0))
r1 = semget(0x1, 0x3, 0x0)
semctl$SETALL(r1, 0x0, 0x9, &(0x7f0000000040)=[0x6, 0x1000, 0xff7f, 0x0, 0x6, 0x8, 0x5, 0x400, 0xb265])
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil, 0x2}, {&(0x7f0000455000/0x3000)=nil, &(0x7f0000159000/0x2000)=nil, 0x800000000006}, {&(0x7f00008a7000/0x4000)=nil, &(0x7f0000690000/0x4000)=nil, 0x81}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil}, {&(0x7f000026a000/0x4000)=nil, &(0x7f0000604000/0x3000)=nil, 0xfffffffffffffffc}, {&(0x7f0000a31000/0x3000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f00002dc000/0x4000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f000032e000/0x800000)=nil, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000015000/0x3000)=nil, &(0x7f000015e000/0x2000)=nil}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil}], './file0\x00'})
socket$inet(0x2, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x2, &(0x7f0000000080), 0x0)
writev(0xffffffffffffffff, &(0x7f0000000300)=[{&(0x7f0000000140)="f005c71031c1c5f421277b09000000000000007a091a2f47be787538ec7a89ec5ed66daa731ddc384ecc690869a0aa2266affdf772d7a360ee0f15fa664f557bb45071fe9b6d9d28e6e2589000f6a64f370b9e336987d77b38f7aada5309e46a81e0e2efa087aa9f5f89934fdbd2ed96e7234b8972b273e810ca9962a8f461d3a05711a63027321ff62c", 0x8a}], 0x1)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000340)={<r2=>0xffffffffffffffff})
ioctl$FIONREAD(r2, 0xc0106924, &(0x7f00000001c0))
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
dup(r3)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000001280)={0x0, 0x0, &(0x7f0000001200)=[{&(0x7f0000000180)="bf3b684c5ae963b4567084e096cf973983b85e5df63e013eaa9405095e88157332b4f68e78e0793d3e30417acbf4419893cfd424b75262dc5ade2ab6278ab86672f9ed186987b8c19d9295a17b98020f6002", 0x52}], 0x1}, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x8020690e, &(0x7f00000001c0))


setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r0 = syz_open_pts()
close(r0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r1 = open(&(0x7f0000000140)='./file0\x00', 0x78e, 0x0)
r2 = getpid()
ktrace(&(0x7f0000000040)='./file0\x00', 0x0, 0x20, 0x0)
ktrace(&(0x7f0000000280)='./file0\x00', 0x0, 0x928, r2)
utimensat(0xffffffffffffffff, 0x0, &(0x7f0000000100), 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r1, 0x0)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000200)="f6", 0x1}], 0x1)


fcntl$setflags(0xffffffffffffffff, 0x2, 0x0)
kqueue()
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
fcntl$setown(r1, 0x6, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffe000/0x2000)=nil, 0x1000}, {0x0, 0x0, 0x3f}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {0x0, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffc000/0x2000)=nil}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {0x0, 0x0, 0x4000000002}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil, 0x8001}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffa000/0x2000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, 0x0, 0x4}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000ffd000/0x1000)=nil}], './file0\x00'})
openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
r2 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000340), 0x20, 0x0)
ioctl$VMM_IOC_RUN(r2, 0x8210560b, &(0x7f0000000000)={0x200001, 0x577, 0x1, 0x1ff, 0x0, 0xff, 0x4})
r3 = openat(0xffffffffffffffff, &(0x7f0000000100)='./file0\x00', 0x10000, 0x250)
close(r3)
mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x2000, 0x1192)
open$dir(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000240)={<r4=>0xffffffffffffffff, <r5=>0xffffffffffffffff})
dup2(r5, r4)
connect$unix(0xffffffffffffff9c, &(0x7f00000000c0)=@file={0x0, './file0\x00'}, 0xa)
seteuid(0x0)
r6 = getpid()
ktrace(0x0, 0x1, 0x40000930, r6)
ioctl$TIOCSTAT(r3, 0x20007465, &(0x7f0000000380))
open(&(0x7f0000000180)='./file0\x00', 0x80000000000206, 0x0)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000140), 0x782, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x82, 0x1)
open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
r7 = socket$inet(0x2, 0x3, 0x0)
r8 = socket(0x2, 0x1, 0x0)
getsockopt(r8, 0x6, 0x2, 0x0, 0x0)
sendmmsg(r7, &(0x7f0000000c40)={&(0x7f0000000c00)={&(0x7f00000002c0)=@in={0x2, 0x0}, 0xc, 0x0, 0x0, 0x0}, 0x10}, 0x10, 0x0)


r0 = socket(0x1e, 0x3, 0x0)
r1 = open(&(0x7f0000000280)='./bus\x00', 0x0, 0x0)
poll(&(0x7f0000000140)=[{r1, 0x4}], 0x1, 0x0)
close(r1)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000400)={0x0, &(0x7f00000003c0)})
r2 = openat$bpf(0xffffffffffffff9c, 0x0, 0x40, 0x0)
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f0000000600), 0xc)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000680), &(0x7f00000006c0)=0xc)
r3 = fcntl$getown(r0, 0x5)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000001440)={0xffffffffffffffff, <r4=>0xffffffffffffffff})
r5 = fcntl$getown(r4, 0x3)
setpgid(0x0, r5)
r6 = msgget$private(0x0, 0x20)
msgsnd(r6, &(0x7f00000004c0)={0x1, "9cfa0b55f5dfa44c224947f72892822564bea470b0d6ea9e67c08138a1eb15201308f3e430d738c5a02a5de8f9dc6d40f1213013e231c81de361eb80db5ee892e3a36abfc776db9f004060969f4f106d7be733572523f619c7bfb7dae3e7337c6223f07794950f4314d2b7dd818ddad7d892c893cfa9e7d5ceeb015bc9537f85ac9ca0ad0c07993ac97b4fc2dc14dd0cc0269d49e7e8aa8018487013b98b27bb381fd75b15"}, 0xad, 0x800)
r7 = geteuid()
getgroups(0x6, &(0x7f0000000100)=[0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff])
msgctl$IPC_SET(r6, 0x1, &(0x7f00000001c0)={{0x1ff, r7, 0x0, 0x0, 0xffffffffffffffff, 0x100, 0x2}, 0x2, 0x684, r5, 0x0, 0x0, 0x0, 0x8001, 0x9})
getgroups(0x2, &(0x7f0000000700)=[0xffffffffffffffff, <r8=>0x0])
geteuid()
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
sendmsg$unix(r0, &(0x7f00000008c0)={&(0x7f0000000000)=@abs={0x0, 0x0, 0x1}, 0x8, &(0x7f0000000540)=[{&(0x7f0000000040)="d7f7130955acdf6b18020261d7143e4a4b91765a8788cbbfdb2fd3cf01ea5b294c064c4a3ae46170779cae043eeed8505a67ebe4318cbfe5063eb77542639ee469677b035f6e514eb6b954bef74fc7f28953dbca5af31b98db615dda6340b7738c30c68eec37421dca79d52b0b59247503", 0x71}, {&(0x7f0000000200)="11b59ae8be75bc6d6544cabf00d648e0d942f34364e9c2f7f4372e70d03ec934456d3dfca11dfed02b4ce1825d4762afe0859205dd6aa87c8bbb733a37e2dfd9dd929be58f84e4057c47a759891667377e82d7a9a68da99dca7d287e6ae4794cdf75d535ec7b11b8289c1d6829defb7cc6dae0350beb4355b088a4f1cb9072ac988db1cf044b655b86d4c021d42f503664d73e0af021fc3cf7d6336a4afed0acfc2a5c91a726e735a90eb4c52c", 0xad}, {&(0x7f00000002c0)="9afc6c98dedf4cd33639321b8f983b347233072fa17f2bc6b8f493f726f8672107c2d30d3942cceb3acc187bcee2d725a680f070b8de0bfd56fba0f98f8d023bc751b37692cdbfe8fcd8f2ff7c736125f0f3781074a5b83f0bdd9412fc2a3973", 0x60}, {&(0x7f0000000380)="ea66b0f5aa986156d79852c596edae20f4bcedb782431180f4c98fb435baaab74bb6f74c155e43ae1fd779bdd2c67ef5e9f06200b8b570b86b12d181f6c5a196676d84dd93ea02b25f1c60442a31ccffe92cca37e5cfcc2ed354d2355464403f711cbbe67e1ebd42f41fc31b9a62637ae859051247ed78f5b12b1ecdee07eb3defe244c6f727f9f2b83d00157b6560ab68e7b04674071c7b3d2f9244b15cf653658999f9475a5410be720d0697f510e795aca4108fd73784051298f27219b6203ba147326fe9158b07872de34a61cfaa432624f84bc7ad4587616b14be79e4a6185c37fcfde05cc6322736b2", 0xec}, {&(0x7f0000000480)="6786f9bdfa640c3bec15acf807a138b57b8ce9a0aff746a8097ee0c90d26b729a8a35ef2e0bc38859899f563cc9bc2f908456abf7c3754f023368eb24d29f2270ffb1675f7235d3f1cf0121bdda695bd722d1861323f82e9b525a80f739ff495cde349f0e124f59ae237f2213daed3ad57bb5c660219c4a8a9c16e3a61ba386abc87187545fce6563cc5ccc96aa843ff2ef811d870f7c03a586a86600a49", 0x9e}], 0x5, &(0x7f0000000780)=[@rights={0x18, 0xffff, 0x1, [r1, r0]}, @rights={0x20, 0xffff, 0x1, [0xffffffffffffffff, r2, r0, r0]}, @rights={0x38, 0xffff, 0x1, [r0, r0, r0, r0, r0, r0, r0, 0xffffffffffffffff, r0]}, @cred={0x20, 0xffff, 0x0, r3, r7, r8}, @rights={0x20, 0xffff, 0x1, [0xffffffffffffff9c, r0, 0xffffffffffffffff]}, @cred={0x20, 0xffff, 0x0, 0xffffffffffffffff}], 0xd0, 0x409}, 0xc)
sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f00000000c0)="964b2e8c33c6b9184c54128f975fecf28b35a6b4fe6c2c7decb370e1ded56c32941e0b88ddd1b408c2570ee069d4b5d9fe2d8c0e0e6fcae82f887c519aef0e4f551a8da94ec5e94e8cc86014dcae87ce36ccfa7db954ba0ac2262672aa4264b2ec6ad65c12edb84ce1def64f79b40d76e2c7318805285dcb26b2adfb8bdfa599fa5d155b68e34a92a4e96829325b7b8acd8cb6c66aa407b4ff97282541ca92edef6fc0382c47bd1c63e463375341590f6a327092643b98a174e443c056da46158047e0b068975ba714199a52b4034fa4364e7304b31dd9dcaced366eb800389ecb0e1c41c6058bb7fa03702e8a03363bc593818269f64a0be94d29087369babc60ce10bc4c561f687122c1b20dd9f10518", 0x111)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x801169ac, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
socket(0x800000018, 0x2, 0x0)
openat$vmm(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
r1 = socket$unix(0x1, 0x5, 0x0)
r2 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r2, 0x80105728, &(0x7f0000000080)={&(0x7f0000000040)=[{0x24}, {}], 0x2})
r3 = dup2(r1, r1)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {}, {0x2, 0x0, 0x0, 0x40804}]})
ioctl$DIOCMAP(0xffffffffffffffff, 0xc0106477, &(0x7f00000000c0)={0x0, r3})
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
r5 = dup(r4)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r4, 0x80104267, &(0x7f0000000500)={0x0, &(0x7f00000000c0)})
syz_emit_ethernet(0x62, &(0x7f00000008c0)=ANY=[])
socket(0x2, 0x2, 0x0)
syz_extract_tcp_res$synack(&(0x7f0000000040), 0x1, 0x0)
r6 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000100), 0x100, 0x0)
close(r6)
r7 = socket(0x11, 0x3, 0x0)
sendto$unix(r7, &(0x7f0000000000)="b10005160000000000000000070000001a5113fecea10500fef96ecfc72fd3357a89583535673039d2d236acf20b7804be38164991f7c8cf5f882b2900e1aa5b23edebc8ef99a8ad491726fa8251e2f0ac3ebbc2feb3fda1139b672f4d3353eb06acdb35a069d7080000000000000000008904000000000022830cf41bed66f4f365ccdcf3e4999d9d20002002c5dbfad800ff0f00"/177, 0xb1, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000080)=[{}, {0x34, 0x0, 0x0, 0x3}, {0x8106}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x2, &(0x7f0000000000)=[{0x45}, {0x906}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)
r1 = socket(0x11, 0x3, 0x0)
setsockopt(r1, 0x11, 0x1, &(0x7f0000000140), 0x0)
kqueue()
kevent(0xffffffffffffffff, &(0x7f0000000040), 0x0, 0x0, 0x20, 0x0)
setsockopt$inet6_MRT6_ADD_MIF(0xffffffffffffffff, 0x29, 0x66, 0x0, 0x0)
r2 = socket(0x11, 0x3, 0x0)
getsockopt(r2, 0x11, 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r3 = socket(0x18, 0x3, 0x0)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r3, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
r4 = socket(0x18, 0x2, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


utimensat(0xffffffffffffff9c, &(0x7f0000000040)='.\x00', &(0x7f0000000080)={{0x0, 0xffffffffffffffff}, {0x0, 0xfffffffffffffffe}}, 0x0)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000000680)={0x0, 0x0, &(0x7f00000001c0)=[{0x0}, {0x0}, {&(0x7f00000002c0)}], 0x3}, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r1 = fcntl$dupfd(r0, 0x3, 0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$FIONREAD(r1, 0x8004745d, &(0x7f0000000200))
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0x8040691a, &(0x7f00000001c0))


r0 = socket$inet6(0x18, 0x3, 0x0)
getsockopt(r0, 0x29, 0x35, 0x0, 0x0)


syz_emit_ethernet(0x2e, &(0x7f0000000000)=ANY=[@ANYBLOB="000000000000aaaaaaaaaabb810001000806004b08f905040086dbbbba595918e0000002aafffffffffffffe7f02"])
syz_emit_ethernet(0x2e, &(0x7f0000000000)={@local, @empty, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @multicast1, {[@rr={0x7, 0x3, 0x7}]}}, @udp={{0x1, 0x3, 0x8}}}}}})


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, 0x0)
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$WSMOUSEIO_GETPARAMS(0xffffffffffffffff, 0x80105727, 0x0)
socket(0x0, 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
getuid()
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


open(&(0x7f0000001700)='./file0\x00', 0x70e, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
sysctl$net_inet_ip(&(0x7f00000000c0)={0x4, 0x1e, 0x2, 0x2}, 0x4, 0x0, 0x0, 0x0, 0x0)
socket(0x18, 0x1, 0x0)
shutdown(0xffffffffffffffff, 0x1)
close(0xffffffffffffffff)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r2 = socket(0x2, 0x2, 0x0)
r3 = socket$inet(0x2, 0x3, 0x0)
setsockopt(r3, 0x0, 0x3, &(0x7f0000000040), 0x0)
ioctl$FIONREAD(r2, 0xc0106924, &(0x7f00000001c0))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCPROMISC(r1, 0x20004269)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000080)=[{0x2}, {0x2}, {0x6, 0x0, 0x0, 0x6d7}]})
writev(r0, &(0x7f0000000000)=[{&(0x7f00000001c0)="d2bc78b52324b9a50c786b26", 0xc}], 0x1)
r4 = open$dir(&(0x7f0000000040)='./file0\x00', 0xa00, 0x0)
r5 = socket(0x2, 0x2, 0x0)
getsockname$unix(r5, &(0x7f0000000000)=@abs, &(0x7f0000000340)=0x8)
dup2(r4, r5)
mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x0, 0x810, r4, 0x0)
open$dir(&(0x7f0000000380)='./file0\x00', 0x1, 0x0)
ftruncate(0xffffffffffffffff, 0x0)
mmap(&(0x7f0000ffb000/0x1000)=nil, 0x1000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x2}, {0x4}, {0x6}]})
syz_emit_ethernet(0x17a, &(0x7f0000000380)=ANY=[])


mknod(0x0, 0x0, 0x0)
r0 = open(0x0, 0x0, 0x0)
accept$unix(0xffffffffffffffff, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
getsockopt$inet_opts(r1, 0x0, 0x15, 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
getpgid(0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
socket$inet(0x2, 0x2, 0x0)
r2 = socket$inet(0x2, 0x1, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1021, &(0x7f0000000000)=0x5, 0x4)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x8981, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105727, &(0x7f0000000100)={&(0x7f00000003c0)=[{0x2}, {}], 0x2})


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000100), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000580)={&(0x7f0000000000)=[{0x5}, {}], 0x2})


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ff3000/0x2000)=nil, 0x41000}, {&(0x7f0000538000/0x2000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f00001f5000/0x4000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ff3000/0xa000)=nil}, {&(0x7f0000ff2000/0x3000)=nil, &(0x7f0000ff9000/0x3000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f0000ffa000/0x4000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f00001f4000/0x2000)=nil}, {&(0x7f0000002000/0x1000)=nil, &(0x7f0000ff9000/0x6000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f000009f000/0x4000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000084000/0x1000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000161000/0x4000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
setsockopt(0xffffffffffffffff, 0x0, 0xa, &(0x7f0000000480), 0x0)
setsockopt(0xffffffffffffffff, 0x1000000029, 0xc, 0x0, 0x0)
mknod(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
sysctl$vm(0x0, 0x0, 0x0, &(0x7f0000000080), 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_RUN(0xffffffffffffffff, 0xc2585601, 0x0)
madvise(&(0x7f000008f000/0x3000)=nil, 0x3000, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {&(0x7f000002f000/0xd000)=nil}, {&(0x7f0000060000/0x2000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000ffb000/0x4000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000053000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0x0)
sysctl$kern(&(0x7f0000000200)={0x1, 0x11}, 0x2, &(0x7f0000000240), &(0x7f00000002c0), &(0x7f0000000300), 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
setitimer(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x802069b0, &(0x7f00000001c0))
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x0, 0x0)
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000080)={0x1, &(0x7f00000000c0)=[{0x64}]})
getitimer(0x0, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, 0x0, &(0x7f00000004c0), 0x0, 0x0)
getgroups(0x1, &(0x7f0000000140)=[0xffffffffffffffff])
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000001c0)=[{}, {0x0, 0x0, 0x0, 0x1}, {0x6}]})
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x8981, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x8020691f, &(0x7f00000001c0))


r0 = socket(0x2, 0x2, 0x0)
open$dir(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, 0x0)
r1 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r1, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f0000000000))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000000c0)=[{0xc0}, {0x7}, {0x6, 0x0, 0x0, 0x10001}]})
write(r0, &(0x7f0000000000)="76e5de0000010000000000000063", 0xe)


setrlimit(0x8, &(0x7f0000000000)={0x7, 0x12})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000440)={0x20007ff, 0x0, 0x7, 0x7ff, "01000000080000029bb82f36b921aab39b58505f"})
writev(r0, &(0x7f0000000180)=[{&(0x7f00000009c0)="714688c3aedce32d84628a599b646fcebc3f97fef14c64b465c657888acb0d4d10de9a40866529fe3b486823b437b7b99b6a5fc09b36567a6742830b345cb7055db8bb157a1b3f509d069e4220c73db1a608ef96982cd93bc34b929171d7b0fc7ed382aafb952e15b911ad84854b2e7ea7d04e2104c113c4e4178646e203b3ed98669e953e7d89affa57ff1774450d287e6ee9179911b74d63376539d3b8571714cbc82daab45bc34a83784ddeb2753ca43562784933b1043d997fe5e147962651925fec3fd0afa7d33f8180c1ca61c0ac3ab4516e17ec6d86d566ae000f4ddcc885480993edfaf8a6a300f424497b70599044202881b1c36661fffac5aa26df4dcaf5181aaaaf21de8ee04a1e56f6d1549f8155459cb78f1cd3d7f8b06a80a30bad47a54cace88b622454848cd31e9ee15be248e41319dbf524fb14ad22e4551a044266129e8c3bf7661f4564a61c521a16ac7b105567048a9b27711f805e64b390bb464ca6370162341fca5f121b5ac49a3a06f458b95eb7e142c0ed0ae062ef79d6ce3f5549bedc913c81a752523a057b811074227646c3903d5092d687099f6f0fa864a516511e780a90e2fbef704792616f7ee2feaefdb11864d49116068e5fea5c95762960f0687ef9bced13c74b9f80dc2ca03e5383d67d4ffce2f293c294013d922fea8ab685a08fca72f1da74be8a4577290fad05d704e894bda8f3a7ee41fc25a6610e07b36d85c0b9d1623949991cce1d773a3fab0a8ca4b5cde17d247b20f69fb784d12f2c6eb2c7dd5a7a43d194dd499acb506b3f4d724fdc88e713c864e2eb1ec91bc270717a27cda8590fc1c48df8282a9ec5686f9ef4c78e99a2da5a57f482ec6714f5c2d58f4e1ba34b8fac93b05b9cc7babca9966c602c395edbc06c1e57f4a62005f6f7a5c47ccc4e3a720595d0b0005f9c71de5e58aff3c191fc2bb473134d62d25e18d0872e118f05a7d43de1d99cb0097b6893f76e44c93c5c04acf8b7c0ab369eaf020fbdd7dc80ef1da83a0d7877af60fc6fdaab2eea35bf5ab65038aa82eef294090a7002acab9a4e497d4ec21cbf7447218a06a53cec35fad2ec5a317d24e39b0af94d280a668b30d7aa9ea787994ecc57e023f49935d8ec7ec44a79c12ccb5706757a1c3275ea37e20d3e5a38dd2d7d00a4a5e0c34d6582d742416e51606497eebf36182c34f1e693ae852b1abd361ba0061b734f28db6e3d1a07b87e0f87c694c51c2d1af81ff70f849fbf3e0da62d553359c8ebf0dc597b3bbdc01c3f487cb40a42871ca7c0d385fa4c19a235b219dbfadf800fb54c1092d1c7161fa50117fab172c69f3da25293b9fdaf74d3f2de77343bbecdd5524d0c3f440dbb7b688e84edbc097ed031b5bd0ab099026b24a99065ff36aeabbf446666169fb5f856b24faae027affaaae2d0fd13c8e8d380c81c12aadf11551040659a9bc6ccada1703792d19806ac6a18f881ea0c4ae1f974b11188ac1367fb0159379b072580553cdf1f2bc3757562782ad14821f71128ad499a380e1d6f081a226dc3c4fbc7a8a06fda18646a09c48e92854719733af42140e267245a285a9747a1b63898a07eefed023f640c6bf6f9e67759b2c20ab43c93754340a93beebfaf9456cfecacc06e0bb0ad9d9a80cd25f4478c29006ab198593cf255508189abf14f160f8913afd9e78454ee42d3424438bc6f8d7f8e43f5df884a15a0fa9597d47f2012a437a8812c92d7864d7a6902a8a807fec96511d5efb0271ae53e3c500db2b1d19ef963c96d0c314e7020b055151767763c26d7b50aff9da2b9ac265e55e44a759b47ec50504a243ae5b92a4d223e364cd048153467a5d69bd563b11611b0419543e891fb846ee8642d0284a43c67b012b7857cc4168b4d15f835cf19c9637bca0fe9a532b8b99ce4bab7be5197702fe0836f0fca2a76805550a003977aecb7c53e56d5ff1b8d0b718be5593142e6493dd1e76cd6cf10f7d89ae55874be30f11ade8e61bab20e9275b69473d1ccedee8eac192ac012b19070eaff02a56736b6de896401a0588f551e8941671d5a767a30cdc02e4fe002f8a3171e427f5e3f75ed9d0754d8bbfbb6650dc0f1a41c743f5f1f4b65fdb4865bc37729d3e43e6669243d12e2c5df313843c2a511c24a59cb530751133fc44d8d4103bd304226dd2e861c3d3dd1667dc53ddf5cfeba185294bf488d2663858b09f2103707368d664cf2c738d69a2224af556b07196e21c14943016791216183a5960fec47eb0b5306650b0e38cc6ef7b3fd10a318a016dc2c649e90b2c2446399ae39caf823ec3337fc8d25df465dfc0f8701bab8fc1865f901a637cb8610a33a1ed887e6b368dded6ebe26234cf5fbd36d4efc5d82450651e82b073cab54ea1cafe4beaf953e90b1e95655b99a9a2b15fb79af8e942baf4f2a187e854282bfb3af47e3d8aebf11af13d04baf1b521f66040e0d1728f6b8f238f85143e84efe3b60a0fb7fa03972432b0cdfb970ae6123f643454fc82ccb90698eefaa3b02d28688c44c51031161695566b62afac3193ccf15450169ff956aae1460331d5ab192653774f3d33a386538f7f10f53f65d12576c7939afde94651658d90ec54a493f9493a8572621d293e73d6431ff2e92d116b6c0425c0372c9428be2c343cb0c996ca936026e846052c7ab8ae1030d699e7e6763181a61237f0744a35947ec3497e4ebb2d1caac59fa3ce937334ff4f80767215d2b231a18f0a5f43beb3ad84210cca31d1627e5c1d161d1d139f564f1cfd766a30f46066e7034596520e3101a80669b7c460981e2748d81ee7ea1d08e313f94a1151b95084f81fa3d217f2c4af801e96782d559e7d3d0c75a0bf6f6e074f1f413cc4c8e2800f045369fcb213ed20df546ebb7fee2a91ace908f03ca57f110c92c69ac7a8c92361595060afcbbbc53ed57c460a8758307b56938ee1811169f2629191047799784845cefc3d952208980", 0x842}], 0x1)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000ffa000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f0000ffa000/0x4000)=nil}, {&(0x7f0000004000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ff9000/0x6000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffa000/0x1000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000006000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
kqueue()
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
socket(0x1, 0x2, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0xc0206921, &(0x7f00000001c0))
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x8020690c, &(0x7f00000001c0))


setrlimit(0x8, &(0x7f0000000000)={0xa, 0x12})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
writev(r0, &(0x7f0000002700)=[{&(0x7f0000000200)}, {&(0x7f0000000080)="a4d9edfa3bbd567b1fa17de56aed6dae0c2837a322e16b1e9a6dedaf15581b47a1542841f8e59f763c7e090ad978cba70d8e5188db108d17f77ae326059182fd5055d31f83ee403677a90507ac04e7eec6cad8bb5fb3b48c230a1c", 0x5b}, {&(0x7f0000000300)="d9ae5474faf8bed81c1f57097f602a6b26a96842ea1c41d16a3ae9623cf525ecb6d1aac6a6e5ae63011a7e86be30df6869b116b6d9738b2fe8de0a37f24a0f927042aa3d8a97dee4932f969fde777fd1b81fa4b06651206f457ca960de470643694d8c8a8737f363d457ea2c25d912857f29b0c73c32b012b91359b680a953b4be5c0eb6cd0e7282e4d1b74779b496d250d9b9c8fea69ba018d0ae449adf48b8b1224cde0139d951df8bf33d772724e32d850fc33ea7", 0xb6}], 0x3)
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f0000000040)=0xfffffffc)
write(r0, &(0x7f0000000140)="feaefb66d909ec4d0da82748ae558f245ae995f911f70b39a831eeedd542a30b7694924a16e8f2ce1d9139db272e810b8f995f554138f306b1fd4e8434ef6e1147a90209341f2f75777933d6736442abbcef8a037d285e3ba4be08806490e84b1e80d6067243dcae3471ef2cfe3db56b62125caab7e4f018cfaa9a82bea85d6180b05ed81f5d1ed9b1c0cfaf8853e69a519f1fbc9cbb12edb464f64a72e88182b24b3dc1c184fa5ef023000f541b075f1c4c91", 0xffb8)
socket(0x0, 0x0, 0x0)
setrlimit(0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
open$dir(0x0, 0x0, 0x0)
execve(0x0, 0x0, 0x0)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x8981, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000100)={&(0x7f0000000000)=[{}, {0x3}], 0x2})


r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc028698b, &(0x7f00000001c0))


open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$hw(&(0x7f0000001180)={0x7}, 0x2, 0x0, 0x0, 0x0, 0xffffffffffffffe7)


sysctl$vfs_nfs(&(0x7f0000000180)={0xa, 0x2, 0x2}, 0x3, &(0x7f0000000500)="e9d592d6", &(0x7f0000000240)=0x4, &(0x7f0000000600), 0x0)


mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0xc0e99db6de761f86, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
open$dir(&(0x7f0000000140)='./file0/file0\x00', 0x0, 0x0)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x1, 0x0)
ioctl$FIONREAD(r0, 0xc0106978, &(0x7f0000000140))


pwritev(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f00000005c0)="dc", 0x1}], 0x1, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x3e}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)


getgroups(0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
setegid(0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001a80)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x2, &(0x7f0000000340)=[{0x2c}, {0x6}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])
getgroups(0x6, &(0x7f00000001c0)=[0x0, 0x0, 0x0, 0x0, 0x0, 0x0])
semget$private(0x0, 0x0, 0x20)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
fchflags(0xffffffffffffffff, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x2, 0x3, 0x0)
connect$unix(r1, &(0x7f0000000000), 0x10)
sendmsg(r1, &(0x7f0000001ec0)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000140)=[{}, {0x8, 0xa}], 0x2})


sysctl$kern(&(0x7f0000000040)={0x1, 0xa}, 0x2, 0x0, 0x0, 0xffffffffffffffff, 0x0)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f00000000c0)={0x0, 0x0, 0xfffffffe, 0x0, "031ffe40630000000000ff00010400"})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
close(0xffffffffffffffff)
socket(0x0, 0x0, 0x0)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x3a)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r1, &(0x7f00000001c0)="00003226a4a9000064e7c803d2a423735d33a4dd", 0x14)


r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000000029, 0xe, &(0x7f00000000c0)='\x00\x00\x00\x00', 0x4)


mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x0)
msgsnd(0x0, &(0x7f00000000c0)=ANY=[@ANYRES16, @ANYRES32, @ANYRES64, @ANYRESHEX, @ANYRESDEC, @ANYRES16, @ANYRESHEX, @ANYRESHEX, @ANYRESOCT, @ANYBLOB="e2741b262760a83cd10dac54c942603d0aceb15f748d0f3b2e063f6a2449f3bb000000000000bc1cb7193bcb32a13cc5bfd47d70822bfea0e3575a132b52466c86315d796f6ba12269c87784253e81000000e8e6899dfa33c7fed5d17dd1002a5eeed5ebbe57a4ff9c6bf317671b2f5d1889900629b1747e3cf7ed9ed20500f20500f7ad3c6ce8238747571c9fd0c24945c80b6e"], 0x298, 0x0)
r0 = open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f00000001c0)={0x0, 0x0, 0x0, 0x100000004})
flock(r0, 0x2)
close(r0)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0xe8}})
r0 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x1000100000000})
r1 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


mkdir(&(0x7f0000000000)='./file0\x00', 0x100)
unveil(&(0x7f0000000280)='.\x00', &(0x7f00000002c0)='c\x00')
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000), 0x10)
r1 = dup(r0)
listen(r1, 0x0)
accept$inet(r0, 0x0, 0x0)
r2 = socket(0x2, 0x1, 0x0)
connect$unix(r2, &(0x7f0000000000)=@file={0x0, '\x00'}, 0x3)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000140)=[{0x7}, {0x4}, {0x6}]})
syz_emit_ethernet(0x127, &(0x7f0000000040)=ANY=[])


setreuid(0xee00, 0x0)
r0 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r1 = getuid()
fchown(r0, r1, 0x0)
r2 = getuid()
setreuid(0xee00, r2)
mkdirat(0xffffffffffffff9c, &(0x7f0000000340)='./file0\x00', 0x0)
renameat(0xffffffffffffff9c, 0x0, 0xffffffffffffff9c, 0x0)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000140)='r\x00')
open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)


r0 = semget$private(0x0, 0x4, 0x3c8)
semop(r0, &(0x7f0000001480)=[{0x3, 0x6}, {0x3, 0x2ff}, {0x1, 0x8, 0x1000}, {0x3, 0x1, 0xfb0bf9bc52962a4e}, {0x0, 0xfffd, 0x1000}, {0x1, 0x1, 0x3400}, {0x0, 0x9}, {0x3, 0x800, 0x1000}], 0x8)
semctl$SETALL(r0, 0x0, 0x9, &(0x7f00000002c0)=[0x3, 0xfff])
semctl$SETALL(r0, 0x0, 0x9, &(0x7f0000000140)=[0x6, 0x2080])
getegid()
getegid()
r1 = getuid()
syz_emit_ethernet(0x17a, &(0x7f00000004c0)=ANY=[@ANYBLOB="f3a2a8908a86aaaaaaaa8fbb86dd601ab5b6ffffffc200000000000000000000000000000000ff0200000000000000000000959c0001ae3c5815762ac3c36796cf0a27dd1a668622ab9396ac400311e6ff185835d3553cdd7e1d3558ea78632dab3c24fd6903b51be42b613969572f972a300bc17c60e99214bc93d05586c28717369b8a89d7bdfe15935c1dd11c658f60c284ad84cfcb04f553960b9cfce0f3cc447621ba57fc16e1759ff7df7e787657ecd80d7a9ed05ff166a418d6ad6dddbac4930ce73f6450e68d82df8c0097d4ddcd202e76044fe06c2addd49c33d583d1b0717383a0ac90fc263c60cae452a103fff490730cb5071c2d9252889155723da92fb4f1a266d98dc37fc4f8769fab233633b1bc6641866df9b507c6674d3fd6907694afb746ce7bd3b1"])
setreuid(0xee00, r1)
semctl$IPC_SET(r0, 0x0, 0x1, &(0x7f00000000c0)={{0x10000, 0x0, 0xffffffffffffffff, r1, 0x0, 0x181, 0x200}, 0x2, 0xd47, 0x7})
semctl$IPC_SET(r0, 0x0, 0x1, &(0x7f00000007c0)={{0x8001, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7}, 0xfffff7fffffffffd, 0x104, 0xfffffffffffffffa})
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r2 = socket(0x18, 0x3, 0x3a)
setsockopt(r2, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r2, 0x29, 0x66, &(0x7f00000003c0), 0x5)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000000)={0x0, 0x0, <r3=>0x0}, 0xc)
r4 = socket$inet(0x2, 0x2, 0x0)
getsockopt$sock_cred(r4, 0xffff, 0x1022, &(0x7f0000000180)={0x0, <r5=>0x0}, &(0x7f00000001c0)=0xc)
semctl$IPC_SET(r0, 0x0, 0x1, &(0x7f0000001240)={{0x8, 0x0, r3, r5, 0x0, 0x8, 0x9}, 0x3, 0x4d, 0x2})
r6 = open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
r7 = getegid()
sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x17}, 0x4, &(0x7f0000000100)="ed7cd8a6", &(0x7f0000000140)=0x4, 0x0, 0x0)
semop(r0, &(0x7f0000000080)=[{0x2, 0xb07, 0x3800}, {0x1, 0x5, 0x800}, {0x3}, {0x4, 0xff7e, 0x800}], 0x4)
sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x18}, 0x4, 0x0, 0x0, 0x0, 0x0)
getsockopt$SO_PEERCRED(r6, 0xffff, 0x1022, &(0x7f0000000000)={0x0, <r8=>0x0}, 0xc)
r9 = semget(0x0, 0x3, 0x0)
semctl$IPC_SET(r9, 0x0, 0x1, &(0x7f00000013c0)={{0x21, r8, r7, r8, 0x0, 0x2, 0x4}, 0x6, 0x8000000000000000, 0x7})
r10 = getegid()
semctl$IPC_SET(r0, 0x0, 0x1, &(0x7f0000000200)={{0x7, 0x0, 0xffffffffffffffff, r8, r10, 0x41}, 0xa, 0x2, 0x1})
syz_emit_ethernet(0x5e, &(0x7f0000000640)=ANY=[@ANYRESDEC])


sysctl$kern(&(0x7f00000000c0)={0x1, 0x40}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
select(0x40, &(0x7f00000000c0), 0x0, &(0x7f00000015c0), 0x0)


select(0x0, 0x0, 0x0, 0xfffffffffffffffe, 0x0)
syz_emit_ethernet(0x4e, 0x0)
syz_emit_ethernet(0x3e, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x80, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
rmdir(0x0)
r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000180), 0x1, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(r0, 0x80085762, &(0x7f0000000400))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x64}, {0x14}, {0x6}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
select(0x40, &(0x7f0000000100)={0xffffffffffffffff}, 0x0, 0x0, 0x0)
select(0x40, &(0x7f0000000000)={0x7fffffffffffffff}, 0x0, 0x0, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x462, 0x0)
r0 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r0, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
ioctl$FIONREAD(r0, 0xc0287533, &(0x7f0000000440))


pipe(&(0x7f0000000040))
poll(&(0x7f0000000080)=[{}], 0x1, 0x0)
r0 = kqueue()
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
r1 = open$dir(0x0, 0x80, 0x0)
pwritev(0xffffffffffffffff, &(0x7f0000000340)=[{&(0x7f0000000080)}], 0x1, 0x126)
truncate(&(0x7f0000000100)='./file0\x00', 0x30021)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000240)={0x0, 0x2000000001})
r2 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000240), 0x0)
r3 = socket$inet(0x2, 0x2, 0x0)
dup2(r2, r3)
setsockopt$inet_opts(r3, 0x0, 0x200000000000c, &(0x7f0000000200)="ea00000000000000", 0x8)
setsockopt$inet_opts(r3, 0x0, 0x0, &(0x7f0000000240), 0x0)
truncate(0x0, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x200)
open(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
dup2(r1, r0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x176, &(0x7f0000000040)=[{}, {}, {0x1}]})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000007, 0x0, 0x0, 0x0, 0x3d)


r0 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r0, 0x0)
r1 = socket$unix(0x1, 0x5, 0x0)
r2 = getpid()
fcntl$setown(r0, 0x6, r2)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
close(r0)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x1, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x0)
setsockopt(r1, 0x1000000029, 0x1a, &(0x7f0000000000)="5ab777a5", 0x4)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r0, 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{0x0, 0x0, 0x0, 0x8}, {0x7}, {0xbeff, 0xc1}]})
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000001c0)={0x3, &(0x7f0000000040)=[{0x5c}, {0x28}, {0x4000006, 0x0, 0x0, 0xfffffffc}]})
writev(r0, &(0x7f0000000240)=[{&(0x7f0000000340)="ebebfd510bbcdda9b489e9775d3e", 0xe}], 0x1)


syz_open_pts()
close(0xffffffffffffffff)
syz_open_pts()
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$TIOCDRAIN(0xffffffffffffffff, 0x2000745e)
r0 = openat$null(0xffffffffffffff9c, &(0x7f0000002f40), 0x0, 0x0)
readv(r0, &(0x7f00000002c0)=[{0x0}, {&(0x7f00000000c0)=""/128, 0x80}], 0x2)


sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x2b}, 0x4, 0x0, 0x0, &(0x7f0000000580), 0x0)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
socket(0x18, 0x3, 0x3a)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendmsg$unix(r0, &(0x7f0000000200)={0x0, 0x0, 0x0}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f00000004c0)=[{0xc}, {0x80}, {0x8106}]})
syz_emit_ethernet(0x2a, &(0x7f0000000300)=ANY=[])


r0 = socket$unix(0x1, 0x2, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f0000000000))


socket(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffff9c, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x2}, {0x9, 0x0, 0x0, 0xffffffff}]})
setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0xee00, r0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0xff0a, 0x0, 0x37)


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x100, r0)
getrlimit(0x0, &(0x7f0000001480))


msgsnd(0x0, 0x0, 0x14, 0x0)
r0 = geteuid()
geteuid()
r1 = getpgid(0x0)
r2 = semget$private(0x0, 0x4000000009, 0x82)
semop(r2, &(0x7f00000002c0)=[{0x3, 0xbf4e, 0x1800}, {0x2, 0x1f}, {0x1, 0x4, 0x1800}, {0x4, 0xe5f1}, {0x0, 0xffd, 0x1000}, {0x4, 0x53, 0x1000}, {0x2, 0x2, 0x1000}, {0x2, 0x0, 0x800}, {0x2, 0xfffd}, {0x0, 0x9, 0x1800}], 0xa)
semop(r2, &(0x7f0000000440)=[{0x3, 0x0, 0x1c00}, {0x2, 0x95}, {0x0, 0x3ff, 0x400}, {0x0, 0xb10, 0x1800}], 0x4)
semctl$SETALL(r2, 0x0, 0x9, &(0x7f0000000040))
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000280)={<r3=>0x0, <r4=>0x0}, 0xc)
r5 = getgid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000140)={{0x401, r4, 0x0, 0x0, r5, 0x8, 0x8000}, 0x3fd, 0x2, r3, r1, 0x744, 0x3, 0xa, 0x2})
semctl$IPC_SET(r2, 0x0, 0x1, &(0x7f00000001c0)={{0x39c5, 0x0, 0x0, 0x0, r5, 0x5c, 0x101}, 0x40, 0x800, 0xff})
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000580)={0x0, 0x0, <r6=>0x0}, &(0x7f0000000240)=0xc)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f00000004c0)={<r7=>0x0}, 0xc)
shmctl$IPC_SET(0x0, 0x1, &(0x7f0000000500)={{0x1e, 0x0, r5, 0x0, r6, 0x0, 0x1}, 0x8, 0x4003, r7, 0x0, 0xfffffffffffffffc, 0x3, 0x81})
r8 = geteuid()
r9 = getegid()
r10 = getpid()
r11 = getpid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x6, r0, r6, r8, r9, 0x10, 0x5}, 0x81, 0x9f25, r10, r11, 0x8, 0xfff, 0xffff, 0x1})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001300)={&(0x7f0000000000)=@abs={0x1, 0x0, 0x0}, 0x8, 0x0}, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r12 = socket(0x2, 0x2, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x1}, 0x2, &(0x7f0000000040)="1b7f", 0x0, &(0x7f00000000c0), 0x0)
sysctl$kern(&(0x7f0000000140)={0x1, 0x49}, 0x2, &(0x7f0000000180)="722c96fc75cb81e14deda33e1d57b5e5a255616bbc828ef9aa1d2e49df9f356873eb63766b39", &(0x7f00000001c0)=0x26, 0x0, 0x0)
sysctl$kern(&(0x7f0000000240)={0x1, 0x4d}, 0x2, 0x0, &(0x7f0000000380), 0x0, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x200, 0x0)
r13 = dup(r12)
setsockopt$inet_opts(r13, 0x0, 0x14, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000040), 0x20002, 0x0)
pwrite(r0, &(0x7f0000000100)="057c3e274cdb9f8ee55212dfa2555737a7ee6ff9b22e99eba4b808e724dc5a3253f9196811971aee179bf937aaac59f168ed4e544c924d714ac0032200aabac1760f8a2b76c2388aab5ca4ccc1c33ce6bb97af64cf5eadef178f2a1682a097a0c15d0acc5ed2c8cd93fc63c4c2e090b0d4df0157de3203c146c59c07351b125161640ce28076778321c389f3ed54c473e676fa8634e015a879975346258d2a9459f74728a9e9eaebf87f80694f1195c3e022551b31fc8f99dbf7bbc3", 0xbc, 0x7)
open(0x0, 0x0, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
r1 = openat$speaker(0xffffffffffffff9c, &(0x7f00000004c0), 0x2, 0x0)
writev(r1, &(0x7f0000000300)=[{&(0x7f00000003c0)="db489edba2bfdca1ea365559375db630a6b4ca8f6eaf0246910b199b0b8fa90dd578469659e5b4d7c7a17acf7d795dfef11edd188abd65cd12c928aa7353b1f27d0002181b50b91ee7a576e082a62cba8b8d60e1dc9e2c6947414153aba6936d737f", 0x62}], 0x1)
ioctl$TIOCCONS(0xffffffffffffffff, 0x80047462, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000000640)=ANY=[@ANYBLOB="c19648fbbc4c261c7d7c88d008004a1000280000000000009078000000000000000d0144100903000000007f00000100000000000000"])
open(&(0x7f0000000300)='.\x00', 0x0, 0x0)
pipe2(0x0, 0x4)
r2 = open$dir(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
mkdirat(r2, &(0x7f0000000340)='./file0\x00', 0x1a)
open(&(0x7f0000000040)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//../file0\x00', 0x0, 0x0)
r3 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r4, 0x80104267, 0x0)
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])
r5 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r6 = fcntl$dupfd(r5, 0x0, 0xffffffffffffffff)
ioctl$FIONREAD(r6, 0x800c745b, &(0x7f0000000080))
ioctl$WSMOUSEIO_SETPARAMS(r3, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000200)})
sysctl$kern(&(0x7f0000000000)={0x1, 0x16}, 0x2, &(0x7f00000002c0)="9336932503a6874c767ba2e4d26007d11eb4bb37ba116711048fa5be4d5a5b638336d87023ed85a1215ddb1292519b", &(0x7f0000000100)=0x2f, &(0x7f0000000380)="f1a38a5ee848d8d67fc1e5febd4292d62fd2841dd14722239e5093859645116ade6ab14e3eca8da8317344905104dd36809862f5a1c0824f7fa0a07f554779a7f16ea59824df97b26e7891fccc2b", 0xfffffffffffffc91)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
socket(0x6, 0x0, 0x6)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000080))
fcntl$setstatus(r3, 0x4, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x10180, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
getsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
symlinkat(0x0, 0xffffffffffffffff, 0x0)
sysctl$net_inet_gre(&(0x7f0000000000)={0x4, 0x2, 0x2f, 0x1}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0x0)
socket(0x18, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x81206919, 0x0)
openat$diskmap(0xffffffffffffff9c, 0x0, 0x2, 0x0)
ioctl$DIOCMAP(0xffffffffffffffff, 0xc0106477, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000000c0))
r2 = open(&(0x7f0000000200)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x615, 0x0)
getppid()
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x10, r2, 0x0)
ftruncate(r2, 0x8531)
r3 = msgget$private(0x0, 0x0)
msgsnd(r3, &(0x7f0000000d00)=ANY=[@ANYRESHEX], 0x401, 0x0)


sysctl$hw(&(0x7f0000001180)={0x7}, 0x2, 0x0, 0x0, 0x0, 0x0)
msgget$private(0x0, 0x0)
r0 = openat$null(0xffffffffffffff9c, 0x0, 0x1, 0x0)
openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x20000, 0x0)
mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
chdir(&(0x7f0000000240)='./file0\x00')
setreuid(0x0, 0xee01)
mkdir(&(0x7f0000000100)='./file1\x00', 0x0)
chflags(&(0x7f0000000040)='./file1\x00', 0x10000)
accept$unix(0xffffffffffffff9c, &(0x7f00000000c0)=@file={0x0, ""/519}, &(0x7f0000000300)=0x209)
r1 = openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f0000000080)={&(0x7f0000000040)=[{}, {0x22}], 0x2})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$WSMOUSEIO_GETPARAMS(r1, 0x80105727, &(0x7f0000000080)={0x0})
ioctl$WSKBDIO_GETMAP(r0, 0xc010570d, &(0x7f00000003c0)={0x4, &(0x7f0000000340)=[{0x9, 0x0, 0x4, 0x8, 0x9}, {0x14fa, 0x9, 0x2, 0x80, 0x5}, {0x7, 0x5, 0x6, 0x0, 0x6}, {0x1dac, 0x2, 0xfff8, 0x200, 0x1000}]})
r2 = semget$private(0x0, 0x2, 0x0)
semctl$GETPID(r2, 0x2, 0x4, &(0x7f0000000000)=""/4096)


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
sendmmsg(0xffffffffffffffff, &(0x7f00000007c0)={&(0x7f0000000780)={0x0, 0x1, &(0x7f0000000440)=[{&(0x7f0000000180)="a1b6c6c1d6c2eca2950e663d39ab1bae96ef58a3c18046e41e178f37a79f00659c2ea9ac56733f7e4e4973c1e6b33ac91343ea3b3f8c5c7b93d5c20ab4211791fe30", 0x42}], 0x0, 0x0}}, 0x10, 0x0)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f00000001c0))


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
r1 = socket(0x18, 0x2, 0x0)
r2 = socket(0x18, 0x2, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r3 = dup2(r1, r2)
setsockopt(r3, 0x1000000029, 0x23, &(0x7f00000000c0)="b211d7170d816684c8e360f2fa41c1a0946988b272d2dd3dc90142a84231a746e337b372e93320cff6669cbe7868de45ed3fc33719ca6df71ecec8a918458b2c10a1f8c66653b276e7aae9cb9b21f9982230f575295d48889c9a920796b2dd92fc8575680b37ba955d2c15e6d7c9198ed900ab006ddfb67869b51a2216114d1ece85f593e74035f5bc054eb1dbddf42a", 0x90)
sendmsg(r2, &(0x7f00000002c0)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
mmap(&(0x7f0000ffb000/0x4000)=nil, 0x4000, 0x6, 0x10, 0xffffffffffffffff, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r1 = dup(0xffffffffffffffff)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000140)={0x2, &(0x7f0000000040)=[{0x48}, {0x16}]})
syz_emit_ethernet(0x3e, &(0x7f0000000180)={@random="cd4b70d70fb9", @random="18d890276586", [], {@ipv6={0x86dd, {0x0, 0x6, "9f6b5e", 0x8, 0x0, 0x0, @empty, @loopback, {[], @udp={{0x1, 0x2, 0x8}}}}}}})
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000140)="67b5b992045c1a7733de71184dc12714990881d0d282bbbb82f88aee3375246d60d056448aeda248819c876f2c6e59c445667afca993a0516665954db86908d70836eed6da0b08d886dfd3ab4c442de33c74d0ff7946a83c180aed511af0d3eff58a00acff7ecc72afce9830fbd4edc05a5b077b39f6b4b7e961ce3c370f2f88a7bfe9e2762ddb30c131b1d20aa39f57ee", 0x91}], 0x1)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
dup2(r0, r0)
writev(0xffffffffffffffff, &(0x7f0000000440)=[{&(0x7f0000000180)="4dfb6b79951845e2cd9668618b36d93df01b8b7d45d0bc640ada53de1096c280bc3fe8a11c5aeea07cc0aca57612f97d4b101b5199f73cd5a5bb955d8f2ab8d018223f7b466cfec2b1a9fb56b65db7afa8570d748d5d8c08785882a940bd45d0984200a1bcd0fac462e146746296242e7342abce5beee86b92b0be65d3aef495a0ec7e2df79837fde3b44ac1773ffd11cf25", 0x92}], 0x1)
syz_emit_ethernet(0x12, &(0x7f0000000200)=ANY=[@ANYBLOB="aaaaaaaaaaaaffff0500ffff8847"])


sysctl$hw(&(0x7f0000000000)={0x6, 0xb}, 0x3, &(0x7f0000000140)="d5bd0d1d2d9ffee9de25ae000299278f439e7ba85cfc6828fac6bd2c4db863", &(0x7f0000000040)=0x74, 0x0, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000000), 0x0, 0x0, 0x0, 0x0)
r0 = socket(0x0, 0x3, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
sysctl$hw(&(0x7f0000000340)={0x6, 0x5}, 0x2, &(0x7f0000000600)="03ee840c2a8c096e53431b1f8cca932b17da5907293bb8e3c8ec3f0d099ba7a2a91c6ed6ace6d9673c7e7059d655cd99e2615c2436bcb6099aaf5f2c72a71f503956cb264c31fb37a3d6284a14f2150377f001a93ec2e502fbea4ca0dc79fcfbf5a2c9a2787a55ba25cbc868917f0bd4c9273a5cfd533ce86bad0f7da4eff55c6317280565ec9e17b9d7d85dee02cd5d5d15e48acfe485d2efd9cee8ff3c8eb3ed10d8fe68bcd00c88c13710e710f1ff396fa714df630ca538db72057d9931618bedd6a376b0ab0d853388e6e6d15c1f765a45b074a12b8da7a99273ab46a88016e9b7090ed7c37942d745cd3c6e9afe", &(0x7f0000000700)=0xf0, &(0x7f0000000740)="d1f839ac5cf19fd04dba6c0dbf68ca1fdf288b359001bb5dbb35a6c00bb1eb0c894854fdfb43fceb8a956ece264f96", 0x2f)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
setsockopt$inet6_MRT6_ADD_MFC(0xffffffffffffffff, 0x29, 0x68, &(0x7f0000000080)={{0x18, 0x1, 0x8, 0x7fffffff}, {0x18, 0x2, 0x6, 0x200}, 0x8, [0x8, 0x80, 0x0, 0x4, 0x60, 0x10000, 0xffff7cc0, 0x5]}, 0x3c)
writev(r0, &(0x7f0000000200)=[{&(0x7f00000001c0)="46976936d2ec8eeca52a55e836b2b79a842d9d3fa2da4be3c4051d2b2dcc978e994d8f80f79cc10335f6ae79", 0x2c}, {&(0x7f0000000500)="daa30f743ca7bb0455691f764caf006334a2c76ac9e8c8220560342b00b272f7290a50fa4fac686b89f0a18d10011688939843442a194923f2dfafa761291f215146e1eb12957f47db1213fe83f7770764eb233eefe74f87b61968757f60e1cc95ce452e054257a330ce87c9242785a58964424aa94231995f698ba68f71f29dcea2013e61c1173c846ec26cf026602f3fe24cedfbc1879e69945e863cd3e54f4858a937299a4bb290643085fa95e89b5ee160e8f784aed0fa26da169863efa225bbada9167d14bb1d71bd", 0xcb}, {&(0x7f00000002c0)="09bb3be752f154208975ba08d81eb95dba9bc13a1608c4ed9484dbf4356a6498286fa76910157020aab33ead493f8f2fdb70e2dcc40a3a1f9db08c6fc874f4c3fcfbeb2ad0c740594270ebb7e097444416e5a7198faba35afa0a81", 0x5b}], 0x3)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000780)={0x1, 0x9}, 0x2, &(0x7f00000007c0)="22c4d67167902fb46fcbb7c2aa129cc43f1bdb46166de147841b5ba81acac4bb59a7199b47d6de0e9317a83156f27193ece874749f58d8dff0d8f29c94eef52a1b275b088e84ba5b1816036f88fac0dc6489e2459ffec710a84a534eeafa7a426b430a337355e5e05d59aed39da5b8012ae07b196ed7", &(0x7f0000000840)=0x76, &(0x7f0000000880)="c409e8d66e1427ea932c3e1b0b5d197634a0ca118e56e1", 0x17)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
getsockopt(r1, 0x0, 0x9, 0x0, 0x0)


sysctl$net_inet_divert(&(0x7f0000000000)={0x4, 0x2, 0xf0, 0x1}, 0x4, 0x0, 0x0, 0x0, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
open$dir(&(0x7f0000000300)='.\x00', 0x0, 0x0)
open$dir(&(0x7f00000002c0)='.\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000001200)={<r0=>0xffffffffffffffff})
r1 = kqueue()
poll(&(0x7f0000000000)=[{}, {r0, 0x20}, {r1}], 0x2, 0xffdffffd)
shmat(0x0, &(0x7f0000ff5000/0x4000)=nil, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x42}, 0x6, 0x0, 0x0, 0x0, 0x0)


syz_emit_ethernet(0x3e, &(0x7f0000000040)={@local, @empty, [], {@ipv6={0x86dd, {0x0, 0x6, 'T\\\x00', 0x8, 0x0, 0x0, @local={0xfe, 0x80, '\x00', 0x0}, @local={0xfe, 0x80, '\x00', 0x0}, {[@fragment={0x2c, 0x0, 0x5}]}}}}})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCLOCK(0xffffffffffffffff, 0x20004276)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000140)=[{0x34, 0x0, 0x0, 0x1f}, {0x81}, {0xce}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


kevent(0xffffffffffffffff, &(0x7f0000000040)=[{{}, 0x0, 0x0, 0x0, 0x3}], 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11, 0x0, 0x2}, 0x6, &(0x7f0000000080), 0x0, 0x0, 0x0)


setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000000)="5ab7", 0x2)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xffffffffffffffff, 0x0, 0xffffffffffffffff})
sysctl$kern(&(0x7f0000000040), 0x7, 0x0, 0x0, 0x0, 0xfffffe88)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="fe"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0x9, &(0x7f0000000040)="00040080", 0x4)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


setrlimit(0x0, 0x0)
syz_emit_ethernet(0x3e, 0x0)
socket(0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000240)=[{0x64}, {0x54}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000280)=ANY=[])


r0 = socket(0x18, 0x0, 0x0)
fchmod(r0, 0x1e)
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000000c0)=[{0x8}, {0x2}, {0x8006, 0x5, 0x0, 0x2}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])
mknod(0x0, 0x2000, 0x0)
munmap(&(0x7f000000e000/0x400000)=nil, 0x400000)
shutdown(r0, 0x0)
r2 = socket$inet(0x2, 0x2, 0x0)
r3 = kqueue()
kevent(r3, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
socket(0xc, 0x0, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1002, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x3, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000680)={0x0, 0x0, &(0x7f00000001c0)=[{0x0}, {0x0}, {&(0x7f00000002c0)}], 0x3}, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(0xffffffffffffffff, 0x8004745d, &(0x7f0000000200))
r4 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r4, 0x8040691a, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000140)=[{0x5c}, {0x61}, {0x40e}]})
syz_emit_ethernet(0x2a, &(0x7f0000000200)=ANY=[])


openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r0 = socket$inet(0x2, 0x16e9b72ebdb25f35, 0xb1)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
socket$inet(0x2, 0x1, 0x0)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000100), &(0x7f0000000200)=0xc)
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r1, &(0x7f00000000c0)=[{0x0}, {&(0x7f0000000780)=""/4096, 0x1000}, {&(0x7f00000003c0)=""/233, 0xe9}], 0x3, 0x0)
close(0xffffffffffffffff)
r2 = socket(0x11, 0x3, 0x0)
sendto$unix(r2, &(0x7f0000000300)="b10005010000009f0500000007010000331c13fece910b00fef96ecfc72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf5f882b2b7be1aa0500000051e2f0ad3ebbc257699a1f139b672f335c223e7d0c032bfa896443a42118210000720fd38bfb0000fd54c125191b1257aea8c500002002fbfe0c2300008abfba0902000000e371a3f8343712051eeab70800000000000000ffffffff001000"/177, 0xb1, 0x0, 0x0, 0x0)


msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0xffffffffffffffff}})
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x0, 0x7}, 0x1c)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setrlimit(0x2, &(0x7f0000000080)={0x60000000, 0x60000000})
mmap(&(0x7f00006f6000/0x3000)=nil, 0x3000, 0x0, 0x10, r0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)


msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x106}})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x1, 0x4)
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x15d}})
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = socket(0x800000018, 0x1, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "1a1116f0d0f700"})
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000000)=[{0x4}, {0x28}, {0x206, 0x0, 0xfd}]})
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000080)="35b5c242413c1026089a59583cc3", 0xe}], 0x1)


open$dir(0x0, 0x0, 0x0)
poll(&(0x7f0000001300), 0x0, 0x87e)
r0 = open(&(0x7f0000001440)='./file0\x00', 0x615, 0x0)
poll(&(0x7f0000000000)=[{}], 0x1, 0x8001)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x10, r0, 0x0)
ftruncate(r0, 0x25b3)
execve(0x0, 0x0, 0x0)


open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
getuid()
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
syz_emit_ethernet(0x0, 0x0)
munmap(&(0x7f0000400000/0xc00000)=nil, 0xc00000)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
ftruncate(0xffffffffffffffff, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
unlink(&(0x7f0000000000)='./file0\x00')
ioctl$WSDISPLAYIO_USEFONT(r0, 0x80585750, &(0x7f00000002c0)={'./file0\x00', 0x10001, 0x400, 0x0, 0x1, 0x40, 0x9, 0x5, 0x2, 0x1, 0x8, 0x1})
r1 = socket$unix(0x1, 0x0, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
listen(r1, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x50}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0xfe10, 0x0, 0x37)
r3 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r3, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
openat$pf(0xffffffffffffff9c, &(0x7f0000000340), 0x400, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
select(0x40, &(0x7f0000000000), &(0x7f0000000040)={0x7fffffff}, 0x0, 0x0)
select(0x40, &(0x7f0000000180), &(0x7f00000001c0)={0xff}, 0x0, 0x0)
syz_emit_ethernet(0x3a, &(0x7f0000000000)=ANY=[@ANYBLOB="ffffffffffffffff"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r3, &(0x7f0000000000), 0x10)
write(r3, &(0x7f0000000240)="14bdfa5d1d34e2fecb284a6498307dcda9aec43050036123339a346f737850551408753f95b7688ad4c4e1dd5489e7bafc58d3e5823757ae8b630719ef187ccad995f13dbe19a6dd4e6902bd8297b0799b426aabe9fad9db6996571c6d9f8bb5d542c2148aa42be940970fe88d34d8f99afe7e7820237400000000008000000100"/138, 0xfc7e)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
r1 = dup(r0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
seteuid(0xffffffffffffffff)
setsockopt(r1, 0x1000000000029, 0xd, &(0x7f0000000000)="ffdaf64c000000004f0527000000055e473e0000", 0x14)


r0 = syz_open_pts()
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000280)=0x7)
kqueue()
r1 = syz_open_pts()
close(r1)
r2 = syz_open_pts()
ioctl$TIOCSETD(r1, 0x8004741b, &(0x7f0000000000)=0x7)
close(r2)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0xffffffffffff0000})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x3, 0x0)
r1 = socket(0x11, 0x3, 0x0)
r2 = dup2(r0, r1)
sendmsg$unix(r2, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r0, 0x80085761, &(0x7f00000000c0)={0x3, 0x5})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000400)=[{0x4c}, {0x3}, {0x812e}]})
syz_emit_ethernet(0x66, &(0x7f0000000000)=ANY=[@ANYRESHEX=r0])
r1 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000180), 0x1, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x20)
r2 = socket(0x1, 0x1, 0x0)
fcntl$setstatus(r2, 0x4, 0x40)
socket$inet(0x18, 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
syz_open_pts()
ioctl$WSMUXIO_REMOVE_DEVICE(r1, 0x80085762, &(0x7f0000000400)={0x3})


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x1100, 0xffffffffffffffff)
sysctl$kern(&(0x7f0000000040)={0x1, 0x45}, 0x2, &(0x7f0000000180)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b10689ca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d12727b1e1d0cc45c7ebd5df53fb588fd0245528fe5700a5868eaf74d373197fb657a56e99cdbddbb382ad676b756d4e8b5a81c9a624348f23ffd260bf5fd344a7a30bcf96e47800acc166910bfc34ce76252dd12fac3b10dd5719aa6e420f60e3d2cbb22f5b3a6f7fa3c909e4823cdc0cdf126bc29456035b9a44ff74d852ba5c", &(0x7f0000000080)=0x120, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952", 0x3c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
pwritev(0xffffffffffffffff, &(0x7f00000001c0)=[{&(0x7f00000005c0)="18d26cb474b5c9d53e0ffdba8c54fecc9031509b1623088cc3e85353a5586603eebda7eccfc5ced62c70a12fbffc2425f3f9e50317605792ea906ef56376aa499b9a909aff511ad2d63fc010ee2292f393b11d78e8bc095bbd866e81599df546afa16ce278edae371c4f16d4df85f4ba622daf27aa8a72", 0x77}], 0x1, 0xb3)


syz_open_pts()
sysctl$hw(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x27}, 0x4, &(0x7f0000000000)="71f91e3471ac0058bc5a91501d942400b5e1a0757cb9af769c7afec37082", &(0x7f0000000080)=0x306, 0x0, 0x2e)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB], 0x9}, 0x0)
open(0x0, 0x0, 0x0)
sendmsg(0xffffffffffffffff, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
recvmsg(0xffffffffffffffff, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
close(r0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
semget$private(0x0, 0x1, 0x3c0)
socket$inet(0x2, 0x2, 0x0)
sysctl$net_inet_tcp(&(0x7f00000002c0)={0x4, 0x2, 0x6, 0x15}, 0x4, 0x0, 0x0, &(0x7f00000003c0), 0x0)


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105727, &(0x7f0000000000)={&(0x7f00000003c0)=[{}, {}, {}], 0x3})
sysctl$kern(&(0x7f0000000000)={0x1, 0x45}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$vm_swapencrypt(&(0x7f0000000000), 0x3, 0x0, 0x0, &(0x7f0000001380)="01", 0x1)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000029, 0x3e, &(0x7f0000000000)="5ab7776a", 0x4)


open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x53e, r0)
clock_gettime(0x2, &(0x7f0000000040))


sysctl$vfs_ffs(&(0x7f0000000000)={0xa, 0x3, 0x13}, 0x3, 0x0, 0x0, 0x0, 0x0)
open$dir(&(0x7f0000000b80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x200, 0x0)
sysctl$vfs_ffs(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000300)='./file0\x00', r0, &(0x7f0000000c80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f0000000dc0)='./file0\x00', r0, &(0x7f0000000ec0)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mkdirat(r0, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
symlinkat(&(0x7f0000000fc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', r0, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000980)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000a80)='./file0\x00')
pipe(0xffffffffffffffff)
getpid()
ktrace(0x0, 0x0, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
unlink(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


r0 = syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f00000005c0)={0xffffffff, 0x0, 0x0, 0x0, "46606c8020bd61d5c8ef103ec3137aa4c22922ba"})
ioctl$TIOCMBIC(r0, 0x8004746b, &(0x7f0000000600))


sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000007, 0x0, 0x0, 0x0, 0x3d)
msgsnd(0x0, &(0x7f0000000140)=ANY=[@ANYBLOB="0300000000000000a60d524ae979b5a3e111c8cac1b119e4db1e444c9d4eca7af32596137392f4cdc50d82caa6fa7ffd0da455fa2e9f5109d4ccbe9ddd5e3674e689a6714f0ac2ee9e36ae12821cff35f5866888d441f7c29189271982efb7cd9c94766d1c4be0efcbf44d5d0010dc9df78616b167b260dd96322bfbad5f46f92beb4126cf5ffee44ca5b5bdfcf14c9b3003f53d57d96bcceb3c014f4d7b36a32f1fdb2d7783fa77ede48c3db7299ec5e58a1348d1f8200a241f24ffa673bd7cb93b55b31a3045a1501250df6302a6bbfdcb68febcf98e7aabab17c9e7683a114b35681c98d31a241159997fa2408bccc3081d1feec2142247dcd0e3ab8a8ab390b2a70909b2"], 0x401, 0x0)
msgget(0x1, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x3}, 0xc)
r1 = socket$inet6(0x18, 0x2, 0x0)
ioctl$VMM_IOC_READREGS(r1, 0xc028756b, &(0x7f0000000000))
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {0x0, 0x0, 0xffffffffffffffff}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
r2 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r2, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0xa5, 0x0, 0x0, 0x0, 0x4})
ioctl$VMM_IOC_RUN(r2, 0xc0205602, &(0x7f0000000280)={0x7, 0x0, 0x1, 0x8000, &(0x7f0000000d80)={{0x18, 0x81, 0x9, 0x0, 0x0, 0x6}, {[0x80000001, 0x7ff, 0x20000000006, 0x0, 0x0, 0x0, 0x0, 0x3, 0x2, 0x5, 0x800, 0x6, 0x9d4, 0x9, 0x7, 0x5, 0xfffffffffffffffd, 0x8000], [0x9, 0x105, 0x0, 0x0, 0x0, 0x7, 0x100000001, 0x0, 0x6, 0x7fff], [0xfff, 0xfffffffffffffffd, 0x401, 0x20, 0x80, 0x9], [0x209, 0x5, 0x8000000000000002, 0x40001, 0x5, 0xf4], [{0x2, 0x6, 0x42, 0x1}, {0x804, 0xf06, 0x9, 0x400000000000008}, {0x89d9, 0x6, 0x26, 0x1d}, {0x2, 0x3, 0x51e, 0x5}, {0x0, 0x0, 0x0, 0xfffffffffffffff9}, {}, {0x1f, 0x3}, {0x58c0, 0x0, 0x1001, 0x21}], {0x20, 0x5}, {0x3, 0xca, 0x700000, 0x8}}}, 0x0, 0x2})
r3 = msgget$private(0x0, 0x9d)
msgrcv(0x0, 0x0, 0x0, 0x0, 0x0)
writev(r2, 0x0, 0x0)
writev(r2, 0x0, 0x0)
msgsnd(r3, 0x0, 0x1008, 0x0)
msgsnd(0x0, 0x0, 0x68, 0x0)
munlock(&(0x7f0000ffc000/0x1000)=nil, 0x1000)
r4 = socket(0x0, 0x0, 0x0)
bind(r4, &(0x7f00000004c0), 0x10)
dup(r4)
msgget$private(0x0, 0x40)
msgctl$IPC_RMID(0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)


r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x10000, 0x0)
mmap(&(0x7f0000ff9000/0x4000)=nil, 0x4000, 0x0, 0x810, r0, 0xffff)
r1 = dup(r0)
getsockopt$SO_PEERCRED(r1, 0xffff, 0x1022, &(0x7f00000001c0)={<r2=>0x0}, 0xc)
getsockopt$SO_PEERCRED(r1, 0xffff, 0x1022, &(0x7f0000000200)={0x0, <r3=>0x0, <r4=>0x0}, 0xc)
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000240)={0x0, <r5=>0x0, <r6=>0x0}, &(0x7f0000000280)=0xc)
sendmsg$unix(r1, &(0x7f0000000300)={&(0x7f0000000040)=@file={0x0, './file0\x00'}, 0xa, &(0x7f0000000180)=[{&(0x7f0000000080)="5af3765ccb4b0d1a76b4b33f8748f21bda414ca6bc17cc2cf2007ee7cf06f40b02dea2eec668b4180917133c43ec3ea72534298e8b1b6412da4339871d823c35af5038a6c82c6372ca65363ad19180d4dde281abc39549a4bfe0760d7a2fbdb3bb30283e545db8f0564f99b3a85799c4d72e54ce997436ffc1d92c09eee85f3fb0cb4dd3c1d582ed8d96efc3bbbe996e79e6173d2d0ff3d49b7cbe9afa07cd131abe84c37f80a14efb4601752c19d68cccb9eda4fde275034c8e3b2a7311e4", 0xbf}, {&(0x7f0000000140)="07e73ea623e044c379", 0x9}], 0x2, &(0x7f00000002c0)=[@cred={0x20, 0xffff, 0x0, r2, r3, r6}], 0x20, 0x1}, 0x401)
r7 = getpgrp()
wait4(r7, &(0x7f0000000340), 0x8, &(0x7f0000000380))
write(r1, &(0x7f0000000440), 0x0)
shmget$private(0x0, 0x4000, 0x0, &(0x7f0000ffb000/0x4000)=nil)
getpid()
mlock(&(0x7f0000ffd000/0x1000)=nil, 0x1000)
setgid(0x0)
ioctl$KDMKTONE(0xffffffffffffffff, 0x20004b08, 0x0)
kqueue()
r8 = semget(0x2, 0x3, 0x200)
semctl$GETNCNT(r8, 0x0, 0x3, &(0x7f00000004c0)=""/202)
r9 = msgget$private(0x0, 0x1a9)
msgctl$IPC_SET(r9, 0x1, &(0x7f00000005c0)={{0xffff, r3, r4, r5, r4, 0x2, 0xf22}, 0x5, 0x0, r2, r2, 0x1, 0x3, 0xb0d5, 0x7})


writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
fcntl$setstatus(r0, 0x4, 0x40)
connect$inet(r0, &(0x7f0000000000), 0x10)
shutdown(r0, 0x2)


openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
select(0x40, &(0x7f0000000100)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
pipe(&(0x7f00000001c0)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
poll(&(0x7f0000000040)=[{r1}], 0x1, 0x3ff)
close(r0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
writev(r0, &(0x7f0000000680)=[{&(0x7f00000008c0)="1792521ead05da15e3c2ccec93df825c7d02daa327f929010b6cd686c359f7a41ca9be58503b073b97d5327051c4a56a28d1cf3026413141332e", 0x3a}], 0x1)
execve(0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x8})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f00000005c0)={0x0, 0x4b, 0x7, 0x599, "d8b5220d88f1155400"})
writev(r0, &(0x7f0000000080)=[{&(0x7f0000000a80)="f4a9a06f56a19573d9e28dadaca7ecd11be4e40fbe099fcee873695918140b3f20c77d6094d92e4e64c7e395d3bba68c06d837fd0e7b26d2510b9b3fd3358da52aaf8e01a421ca23bf8f8af07f04912b9c1c703abe3fab02bd257dfaa416c6f8f0783a107b3afcf4b5243a5767c20c468cf2ddd1f7d1a8528834d68aea82838c281673f46d169536fd4498f9a01636139d09ea4ef30e15bec8509d137d185c49e34d5b49d397b2591bab1986bdf7925b302f260912254af433a8aeeb5fa99fd25655839875cf39f0266089d159e3fbcfe9e9e99f6d13826988bcdb3891727859f2044d939033f121a8bc850cfcde21c026bfaa3a19e01b352f2b526bd47e895a33de36dd2aaf3409916be1839ca3a018aab3fa7ced425f425bee72939976c8c3dd05b47d62aaf86313f1c8e9941086016393f12c2ac53c6798cc7690c92b69c084e3fab86908664540551024820786a136c00deb655d53d98f02db78e1b790623cf04370ba8f9c2e1a4da5fdc66cae3b28299eedbc2f41956966c17b10f0c30fa83b4d12b38728584c3ad6b92b17e936773a06ea6257ee0fe396bad9ac145854734554e42871c422c72ad6e51b10789997a74ab1f163c215b45600eebcbebc0b53117cb0a568996513223bab162d0a3f14de5f55b678c53cbeb9d9ec8e2e7f5eb40bf22833640c0d158752d636afca64cf332d161eefcb1e05b3ddf55aa6f0631cc3442141687e9175a3c60ec218563bafac03753cf849478f77cf3de6432fc2bc2f25d1bf6a161fdf38bcd9e9c6b0fe8bf4e105cb922e26192f33497defa555ea3643bf11b40c2ded4fda0e76b7b7cd5c2078c9eb7df0b41ae71c70f3daca7a4bd730638cfbd12dbc1cb0881fce88ab4720ff0279595e85a283a7bd11d1acce03a58932c6eb7ea55c4dfc9537b77dcae7df385b8ed95a7963e77aa9efb9bd14e5053cab0c2d7bad9e6d863add3e40f470e4801223d474814744247afbe1086811d2b8c6ebee57773aeeae67b1c80448fe31e273824eba219aeaad252e9ab9335587d2cc6b4bafc28157b27a03c4421c679f5ae6364923d55db29bd0ef93f8adb12a7c01add149e6c91e399aecec02219342cd56468c5db13a248e26b762eaac903245794576e96fa719482821e11218aca6cf93e542d49edbbb704e4b6220a303d9887238bdb4d7e29e3b30289eb0cb1494705ca02de93c593fbaaf8dff12eaac92fda27920878120fc6ab81394f3752e45531ea6eb3d2c1c2eb049fee89266b1fc9e61ac71bd71776a6d3bce98d31061f4d1b4f803521672d3ddc6c1a07802aee298a264f41f9ace740bfcb1765bf4d4f3f0a1095f070ab07ae568f16da17ce4b3543ba2c0028ecfed42eae7a91d3092b0bf75f52c83c0defb6abe5774d8ad834b4496fbaaa6065c70a3d83c18d0306d5c7235245a5b92583c305f8f5b19b662bc838257fa6beaff3498b6e0672c9055fcdb6e6470e7fd3cc90cf659a9f756320ff372bfe0f171d475cfa553c2a1fe8bef88fbf1", 0x435}], 0x1)


ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105727, &(0x7f0000000000)={&(0x7f00000003c0)=[{}, {}, {}], 0x3})
sysctl$kern(&(0x7f0000000000)={0x1, 0x45}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$vm_swapencrypt(&(0x7f0000000000), 0x3, 0x0, 0x0, &(0x7f0000001380)="01", 0x1)


socket(0x0, 0x0, 0x6)
socketpair$unix(0x1, 0x2, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
openat$vnd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, 0x0)
r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000140), 0x782, 0x0)
pwritev(r0, 0x0, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000200)={0x1, &(0x7f00000001c0)=[{0x0, 0x0, 0x81}]})
syz_emit_ethernet(0x2a, 0x0)
r1 = open$dir(0x0, 0x0, 0x0)
symlinkat(&(0x7f0000000000)='./file0\x00', r1, &(0x7f0000000080)='./file0\x00')
r2 = openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$PCIOCREAD(r2, 0xc0187009, &(0x7f00000000c0))
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000140)={0x0, 0xfffffffffffffffb})
kevent(0xffffffffffffffff, 0x0, 0x7, 0x0, 0x0, 0x0)
r3 = open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
ioctl$TIOCMBIC(r3, 0x8004746b, 0x0)
sysctl$vfs_nfs(&(0x7f0000000200)={0xa, 0x2, 0x2}, 0x3, 0x0, 0x0, &(0x7f0000000000)="dcbf21de", 0x4)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
getrusage(0xffffffffffffffff, &(0x7f0000001180))


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
bind$unix(r0, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
chmod(&(0x7f0000000180)='./file0\x00', 0x23f)
setuid(0xee01)
connect$unix(r0, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


writev(0xffffffffffffffff, &(0x7f00000012c0)=[{&(0x7f00000001c0)="25fd26f0c2f6f8454eb4598cefd3a544b22bac827dfb6921cd320fabb353b6abd1bdf7a6dd432ca5295f892a5056cb9908d6095b22d9c0274f069fd0a76fa516008092282620fdb3582c7b29a74fc9a0628e26889677f0ab87054b774261de8656a080d103c0504abd02c0f742a4a5cddc2434f350c2d1e641ddfb5bd0cacc83eb73828ca3", 0x85}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
setsockopt$inet_opts(r1, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
dup2(r1, r0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00004100000000", 0x8)


syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000), 0x10)
r1 = dup(r0)
listen(r1, 0x0)
r2 = accept$inet(r0, 0x0, 0x0)
r3 = socket(0x2, 0x1, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)
r4 = dup(r3)
sendto$inet(r4, &(0x7f0000000100)="03c019b7e2399b388d3cc45f01364c934feea3d4c1fbf21dc5dab6090e154d84d22c5ff1da069dd0d4af159f8000000000000000c892a0", 0xff4c, 0x401, 0x0, 0x0)
readv(r2, &(0x7f0000000200)=[{0x0}], 0x1)


getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000140), &(0x7f0000000040)=0xc)
socket(0x11, 0x3, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x10080, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x2, &(0x7f0000000140)=[{0x4}, {0x34}]})
syz_emit_ethernet(0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
sendmsg$unix(r2, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000080)=ANY=[], 0x28}, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000040)={0x7, 0x2, 0x2, 0xa0000204}, 0x4, 0x0, 0x0, 0x0, 0x0)
r3 = semget$private(0x0, 0x4000000009, 0x82)
semop(r3, &(0x7f0000000680)=[{0x2, 0x9, 0x1000}], 0x1)
semctl$SETALL(r3, 0x0, 0x9, &(0x7f0000000400)=[0x7ff, 0xfffd])
geteuid()
semop(r3, &(0x7f0000000140)=[{0x4, 0x220}, {0x7}, {0x4, 0x9}, {0x3, 0x7}, {0x0, 0x5dc, 0x1000}, {0x2}, {0x1, 0x9c, 0x1800}, {0x0, 0x6, 0x1000}, {0x0, 0x8001}], 0x9)
semop(r3, &(0x7f00000002c0)=[{0x0, 0x3, 0xc00}], 0x1)
r4 = getgid()
semctl$IPC_STAT(r3, 0x0, 0x2, &(0x7f0000000540)=""/163)
getgroups(0x1, &(0x7f0000000840)=[r4])
mknod(0x0, 0x2000, 0x3200)
open$dir(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
munlock(&(0x7f0000002000/0x1000)=nil, 0xffffffffdfffdfff)
shmget$private(0x0, 0xc00000, 0x0, &(0x7f0000400000/0xc00000)=nil)
setsockopt(0xffffffffffffffff, 0xa9, 0x1000002f, &(0x7f0000000440)="2b6ac996f121ab4a8ece80a6f558ff57ab85e81c33cd146cb4560d48f74ac6d7dd1f197f30faa0e2c266c6a7d2657e5c12d41b73825e9b0a85f324f8fa9021540ee9cfbf34bf8a640ba809acbec5b59b7cccde897ff56ed575a9d06bca50160511f3997c47ec14d89cfef641d245d4a4b47c29f65af51e35dc5945ae259a84d67eb3355cfa7ae6b5d4b50df8813a081a7132a1a8d20500000000000000fdf58819f823ee6c09e05601556d53659a40157bc9", 0xdf)
recvmmsg(r1, &(0x7f0000000040)={0x0}, 0x10, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
bind(0xffffffffffffffff, &(0x7f0000000000)=@un=@abs={0x0, 0x0, 0x0}, 0x8)
close(r0)
sysctl$vfs_ffs(&(0x7f0000000580)={0x4, 0x1, 0x2}, 0x3, 0x0, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f00000002c0)=[{&(0x7f0000000080)="98e5eac907f9ccf7a251ceddcec7d6aa45cffe2c63a56077123a276d3ba4e9d10100000000000000a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000200)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
setsockopt$sock_int(r1, 0xffff, 0x1004, &(0x7f00000000c0)=0x8000, 0x4)
sendto(r0, &(0x7f0000000440)="df", 0xa, 0x0, 0x0, 0x0)
recvmsg(r1, &(0x7f0000000380)={0x0, 0x0, &(0x7f0000000040)=[{&(0x7f0000000100)=""/215, 0xd7}], 0x1, 0x0}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000180)=[{0x87}, {0x35}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f0000005c40)=ANY=[@ANYRES32=0x41424344])


socket(0x2, 0x2, 0x0)
r0 = socket(0x18, 0x2, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001600)={0x0, 0x0, 0x0, 0x0, &(0x7f0000002c40)=ANY=[@ANYBLOB="10000000ff"], 0x10}, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
openat(0xffffffffffffff9c, &(0x7f0000000140)='./file0\x00', 0x200, 0x0)
r3 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x53e, r3)
r4 = dup2(r2, r0)
recvmsg(r4, &(0x7f0000000280)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000240)=""/11, 0xb}, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
sendmmsg(r1, &(0x7f0000001600)={0x0}, 0x10, 0x0)
select(0x0, 0x0, 0x0, 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x100, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
r5 = openat$wsdisplay(0xffffffffffffff9c, &(0x7f0000000000), 0x20000, 0x0)
ioctl$WSDISPLAYIO_SMODE(r5, 0x8004574c, &(0x7f0000000040))
ioctl$VT_GETACTIVE(r5, 0x40047607, &(0x7f0000000080))
r6 = openat$wsdisplay(0xffffffffffffff9c, &(0x7f00000000c0), 0x20000, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(r6, 0x80085762, &(0x7f0000000100)={0x3, 0x2})
r7 = accept$inet6(0xffffffffffffff9c, 0x0, &(0x7f0000000140))
accept$inet6(r7, 0x0, &(0x7f0000000180))
preadv(r5, &(0x7f0000000680)=[{&(0x7f00000001c0)=""/112, 0x70}, {&(0x7f0000000240)=""/205, 0xcd}, {&(0x7f0000000340)=""/18, 0x12}, {&(0x7f0000000380)=""/231, 0xe7}, {&(0x7f0000000480)=""/200, 0xc8}, {&(0x7f0000000580)=""/222, 0xde}], 0x6, 0x1000)
ioctl$WSDISPLAYIO_SMODE(r5, 0x8004574c, &(0x7f0000000700)=0x2)
sysctl$hw(&(0x7f0000000740)={0x6, 0x3}, 0x2, &(0x7f0000000780)="e9b407fe1b18eb5af42b5cf0f0734339f6035d5a2eae38307cb705dc8dad8b4644c118631f0baf28ef30db7d5058e8d06046eaca7a34c87d444ed2bbd908dbc6f84533e95a507e1b18631803e948033d35d1c775f3b49895bdf7f657e9f91a4e846b56e364136e087f2c2515c811cd70305a8aa8dce8a4c94d7116c8780246dddeee0693b33ebe", &(0x7f0000000840)=0x87, &(0x7f0000000880), 0x0)
r8 = msgget(0x0, 0x10)
msgctl$IPC_RMID(r8, 0x0)
mmap(&(0x7f0000ffd000/0x2000)=nil, 0x2000, 0x4, 0x10, r7, 0x1)
r9 = semget$private(0x0, 0x4, 0x48)
semctl$GETALL(r9, 0x0, 0x6, &(0x7f0000000940)=""/135)
mknod(&(0x7f0000000a00)='./file0\x00', 0x2, 0x5)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x6381)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
poll(&(0x7f00000000c0)=[{r0, 0x6e}], 0x1, 0x0)
select(0x6c, &(0x7f0000000000), &(0x7f0000000040)={0xfffffffffffffffe}, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{0x6c}, {0x84}, {0x6}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


setrlimit(0x8, &(0x7f0000000040)={0x7, 0x50})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETAW(r1, 0x802c7415, &(0x7f0000000000)={0x29f57365, 0x0, 0x100001f, 0xffffffff, "8b050003000100787d902b56d864d3c3a3f4d3c9"})
writev(r0, &(0x7f00000013c0)=[{&(0x7f0000000240)="e35dbfeda71d80e5fa43a7683ebf074f330bd14903519d99401957f0a5d112adf0f7388c9bfa9c4496d0b78f7c1cfa8aec9dcc35204ac738cc8ce693bcfd2d7a97874115617f3ff5939a19e4fc06a51651ebe9f73dbb5bcf7667a21164ec882e89c1e3ea5ab46657b1096200aa773ad42623280cb88392e46ab068c67ad23813b135617603e66e2393b5aca44bd19edf041d2b5738b0e6d1c3b9dc67b23aae610512c4d0c10036028ad2e1dd1fc6ce9f80d467e9916b7efb0977945f229cc245a8526b1c2148ce321b47e23463b2790f89ce6301287997873500d08f19c7ba8e4609f7a396afca3ab7cb69318e1f876c4213478806b2700e78d961af0a5a8a7c4a973d8aaf635aaa873d8532fde2834bfb4218a1e985cfdda0ad28cd0dcbe666e7ee7d9996e3fb8c4c27f80ecc8bd3e6b64a72f659fec065cf954e8267300c4a4aaa8ad03ff7bee328e0da83634e2a8e018d67c0be51f78faefd207518de0f8f8ad364585ef996b72121ba54891334751b151d5564df556d9e4d8e600b0ebb6eac72fd88d58c67c5e3ee3e98e89aaed1b74e93e893ca6720b984a1ba0f8bf6815f4f8a8d5743819673e44f7b5ddf305bcc0fc8c3afa48b4fd82316bcf597b818748fd045346bd7f2caca69811aabd2cdcc32360bce9e0acbf98e943849ab2f946428218d83fc3a9cc03bf5b66a3e6d80ae7e47e03224be1b7626cd329f410fc5ae7d4e0e2fab30adef3057ead391a34470b5704ff362d628ff9324d50add8901029b190b292091c2acb88fddc6285fa9101692006ed749895dd65e7a4878089376f0d6abfd3a41dacaaef23c0289a2c6a1a0c85174ef070da190643e85c74d0eebc07b0edd3e36f2d355665f35202d439b5b1d67a9fb93d7d0791160269bc1256c54a1b94f0024eb3d55dc0a7d0598a80b78a71dd29cc43451c981fb9615154659f864f467d2c0fabad3699dc0b4a2476c4846c848b313f7fe15f6b367e60db91daffa237815fb3c593a24c0332f6bde3c9c9c88c8c65042a23291e35452bf83022ea93af13cc19e81a532e009e88a34b28f7f593e6acefe569da3a8f1189f7293724e09e0692648ee5703ecf96de190991567df7aada63a248390798796d64b97dcd19298c294f26fe2c7878783ec13cf669c4284c1a7c7c37c47a8a481b6a6b308ba29af39110055c607ec9acfe44ba6bd78dc5e6e48b9b42c5dfd968d05ed5ede2a78b4cf9a8e4b27c261210813495004626594ad1cd6a0fb22732a1c87143118f5b34ba487e0fec988deecf981776fdf4afbb80f66f4818cd8443b8a50e3539648e615907fed142b4ce44ac1a316d3c0b922455f626ef8da49817bd0442c1bd1a0a5c2de6a3519b86a7fc79c5b29ce3a045e02cd839a89e79b2fceef9d185039247115308c3330e1cb7a7e022477d296163c05585c7b222260416cff69ea843d1cd79dbf0041e3a518008721746c825b36fdad6bb8ff6b0414f884b186551f6a5b9b4b51a071048d05aa255963a37ecee7a030a38e8e80041a1033b618503bf0f3203fbf5e6802b833b2e711026424fae8ec4d6d55882623f9a72ea99593c9f5cca8888e1b38ea0b16318f39d176a2ce2e1eda8bf79a216ffccd3faa0916e46a0f8c852570c98f2fd9e99b8ac5972bc418648b942ee4b65c44d057f48df868468a4736f9ea30a273c8dacddd51f1831be7bdd61c9e217d786ad1ac98cf8fd74ecf96617c5235c35e3a7ea2a913df8838384aa055b53bae2b19901a88c1c87d70f4535e27b9c1f066f119346797a991f756f70eda64defcb1dd618f93497d70378b7e0fc553174f8bc021f60e47d632cb06658ab1b7fe57d9587fe795da911c7c7fae13a9a7113a8fc44828f090c2f2bcf324629b9343a3967059fce5dd66d12808d9ddf2410f34b2e424f8beebcbe0bb4a318a0dbeb405a56024ca868395d67303c95674b643e02a10f2140f3a2ea930d546562fc83fbb7a859dc7658568527460c7e06f7d667ce8f783502bbdd97c80ad944d2ced3346d6d87d6a513179a0e5edc79d9d9584abbe49de9f3b4034b5e023e8b67fb39e5c00715f68d3caafd0ad949b8c71abe94940da8bdabfe1209439b363447d52f230e5d1659b29be45f77dec84ef2836b4053609058a9c0031a7c76bac63c51c3a4dc8aa2ca3854aeb3fdade6b888ec8780a4995272333aa1c3d2959d1de71334bf2990d3cf13a3b62a7d370c944f5e6d0b7c259201c43bea9cc21da817c974331f9d6be9338c608e0fb172e0954eecfc3246e10ee5c205cb0fde8640e323a6e643194f4512362a86f08fd92e8f08b4fa1591ea6e8453ff306f10c71b0340e732147f52394a49b655a9904cc2097f6a0cdcdc124abf72b0903363a14906a6efdfd6a97f92a3a697cf9ca70a1ec53ab95efec7988bf8f6cb6557388d23a35f226bca8a565778834cf09298189ab77d1b79da9733200993a496d7effcc6e26840bcc58450e1936e4d5c58aa3c63989b446e12209cf6cef60c1e9090fe177181d0dec10490660fa17946877320fa2a54df5bfae16a3780af576cd062697b58826b046f1741b41bff2c3816b0dc0bb4d30a6f7a92c18b0e5051ac49be01d111ffa3194fbd05273a9de0b3b19c07539a935583397eaeff3facf7099d8520e3ce4b9cdcc7501d0a081a59dcce8886674d38651bdf0f2b6eb5f6b38db3a0f631d99a78aa67bb29d8d7d20d00f8270bb855adc20adb10b3e4c84345d57168c282fbb2b3944643d1a2190d592da2b3f14f283ac7d32b04fbbf1e925345db415a22cf9115f9b954c9e534613028cc9775128afec3507e7b8977a86c2637839fec7dfdb401173172f10fa661ea39ce2dec7acdea4ea88b54fc85e45f4bd52463837136576e78cb8fa873abe21da61cff7d77f15ada2b8aa5a28a69c3a4b4a499a1ac52158eb52bf1f760b4bd5a4477b9bc224263310f987cb00f501a11257bb1f710438a023d7dd7b91b3d9a34a114187640c3955ae36cb04d6dd10a90fb203856cd8fec56fa6fc4217937845bbb073b7bd96cbac32d7150b29f3d42bc2dbf6425944e507d14457fe2ea7269bcde0aeabd8a7137f784169d4d2bad03bc99c305df2371c9d0e1a83709e76128d15586e44967d1e8bef5eb3752c7642ed868fc3904d472cf110afc7a4a0df5491953d5b47fd92b748b3b8b93b35e3923919f3993a288637220d7dfc0a4d3c15ec1dfd7c061e5fd67b0ede343cda08256f22d9d7f66f311bdba1551fae7a02c8c1ed88c2e7248abffb66d40641b916a674764de9a2320d713b694a5d10d1b1db6b4375cbd2469297d8f695c5f2200f46954222474809e9a83200683e95e536dad7669dfb8158fab87f8245e0ace781149b8d542123ff7c2a4642bf7fd265d0f5a51286e412281225f4841dbda0ba2288ef12c2d70b6d46bd7bf3234b314de9e698ad2de9b6fda7758cff7b706fae14ac405f68c0ccbcf7a244147312bb487b98dc77e35da5979b6c75d1a504726399468327eeab7d817a36eb5764608416ae1cdfba6f18290421cd7eaf01a27d90004a8d6dd04cbe65973a41ef2e6b56c9b20463489b6355c0826358d0be893a57d2717343338aa535da8a0fc0721c4e5e6bdeb84a4d19ebe9f2de990e52a5daa06328fc1fa19d65131d9c1f96fb20a495ff29a80140c53bcbe1f9a7425002f58a58743fe37d7393b221d2a84b0ec4d6ec862ee93124010ef5e88d93bab5b807f42a2a982aadd53294be71a00c3a4068e6a5a2eefc5d4bf9a2152accffec19a878010b41ef5c21ffd7496b1046443d33ac05f72c378e5d99309379cd747aef4c264e8af8f0684c5aba36479863dcf6022287b7f652a1f025d8f64c507ae078e9995825a78e7a69ca7e9661dc1bcee71c06dcde01339aa569144c2668c26c6f8977eadadebbb0b1726dea289fc206ffd024b69c176d1b7b25667816b38358023d109aeece0079f9558cdc207172532e28b0695f86ccb27820235465796e73e848c5a05865480ddd673215e3ef49d5f745b9f4f5bd3a7ae99af7cb664fd84f3755882838429c9a7bedc1030307243f5b50329f44913c608492f3889de0877f4a9fde11f650c3081b704010c32fe9d964330abcec1720ed95fabd54b9d774127cf97e8d1a193ce6ff7d07145094175dfcea59546d4eb6bb2f67916f2161a60b365d43f29a3a4f7ed76782d9c67936b20fd4820126f196ebe9a55473b5c9de4489de843623454b74c5efa2033d8e0ffab2ddb98efe372d738c91dca38ae6fad86ea23f8eccf1c30aa613afd1c81a8c0e9dbd735d83870ba466ae19e376271a3375ade4d1f6fc802ee8381c08bd2b2696144bb9a97665b25d1e90f0f951f21777c692c1f6ed86757730fa9a593fbddecef7fef6e18012d46037e289009492f0eb5287460381628e86384e32320d567d43a601088c8c81defff03b70255cd3c6ae79b222a31388c4c605b96d7d985d53a3cea80abdca419ddcf405621eaad2818eb3059732b90bb9bd52a9185a7350d395b612f9a8361b5a0122cb5f01bc93e519538743cd9350cc2a4fe18964176d706ae122e371dbcc5f508ccc4f106c802fefba04fead99509e6c1e7e63c614c2041eac6f8427251fa3966d6804ccd03d7b29a22bdfc4cfed944f7364da48b4d02a370c1aa836bb038020a3d6a7289e3c947b5ac40bfd5673ef58fe21e5617bd904113698359cc8489e7053c12e6958380b9f7faea3de5005e01b279c2652d56dc0ff94cc6fa0f720211be04447c1c202294e586fe9d0c03bc285d2a5ccb19f5799efbc773de21bef7e0aab9fc648e591af8080b79cf65a8cfad8547c179096ce27f5d62a1c822adf3b3de7280ed3f706d13beb94496223124e7b44271b460df3a778d36dfa8df0f385a2584a747fa94b9f0beb3e3a32ebd2b6d5efe4ce6208e0d2406a8627885fd0b050bc426927449eedbb09c034dac29ed57bc1ccdc133f55599322c4c0eac5ba3d3366dcd21d9e89d481182bfd9e416106a314757d5560e79a7814fc7f4c1386a9c3b704d3fca95adc61944f0c42710a82578726af6da1d4efa44fddc632efed5fd9fe53959a2b5a1d8df0bacf58e213bd635ff6c46bf86832be7d393da1167e796dad0440b038cf462fa1d35b3b91bb2ac72e8f150fdb4f10c70bcbcd6c57cce02934ec8842d9b98a0e9ca14833de9b1e6742c8a784740c28c4cb3960135c0d", 0xe5e}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000000c0)=[{}, {0x44}, {0x8006}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmmsg(r1, &(0x7f0000000000)={0x0}, 0xfffffe32, 0x0)
getgroups(0x0, 0x0)
recvmsg(r0, &(0x7f0000000100)={0x0, 0x0, &(0x7f0000000080)=[{&(0x7f0000000180)=""/236}], 0x100000000000039d, 0x0, 0x28}, 0x0)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xffffffffffffffff, 0x0, 0xffffffffffffffff})
sysctl$kern(&(0x7f0000000040), 0x7, 0x0, 0x0, 0x0, 0xfffffe88)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0x9, &(0x7f0000000040)="00040080", 0x4)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
mprotect(&(0x7f0000ffe000/0x1000)=nil, 0x1000, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
r0 = open(&(0x7f0000000180)='./file0\x00', 0x70e, 0x0)
writev(r0, &(0x7f0000000240)=[{&(0x7f0000000040)='#', 0x1}], 0x1)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x3, 0x10, r0, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r1 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000001000/0x3000)=nil)
shmat(r1, &(0x7f0000001000/0x3000)=nil, 0x0)
mlockall(0x1)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x6)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000100)=[{0x60}, {0x81}, {0x6}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
r1 = socket(0x18, 0x2, 0x0)
close(r1)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0xfffffffffffffffe}], 0x0, 0x0, 0x0, 0x0)
r2 = socket(0x800000018, 0x2, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
writev(r1, &(0x7f00000004c0)=[{0x0}], 0x1)


r0 = open$dir(&(0x7f0000000040)='.\x00', 0x0, 0x0)
mknodat(r0, &(0x7f0000000000)='./file0\x00', 0x6000, 0x0)
faccessat(r0, &(0x7f0000000100)='./file0\x00', 0x4, 0x1)


sysctl$net_inet6_ip6(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ktrace(0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{}, {0x7}, {0xf7ff}]})
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f00000000c0)={&(0x7f0000000000)='./file0\x00', 0x4, 0x0})
r1 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r1, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(0xffffffffffffffff, 0x0)
accept(r1, 0x0, 0x0)
r2 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r2, &(0x7f00000002c0)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
execve(0x0, 0x0, 0x0)
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x0)
open(0x0, 0x0, 0x0)


socket(0x0, 0x1, 0x0)
r0 = socket(0x2, 0x3, 0x0)
r1 = socket(0x2, 0x2, 0x0)
r2 = dup(r1)
setsockopt$inet_opts(r2, 0x0, 0x22, &(0x7f0000000040)="fd0cc085", 0x4)
r3 = dup2(r2, r0)
sendto$unix(r3, 0x0, 0x0, 0x0, &(0x7f0000000140)=@abs={0x0, 0x0, 0x1}, 0x8)


sysctl$kern(0x0, 0x0, &(0x7f0000000240)="e889baa69e", 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$inet(0x2, 0x2, 0x0)
close(r0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000a, &(0x7f0000000000)="ea00005c00000000", 0x1)
setsockopt$inet_opts(r0, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0x8)


r0 = semget$private(0x0, 0x2, 0x621)
semctl$IPC_RMID(r0, 0x0, 0x0)
semop(r0, &(0x7f00000006c0)=[{0x4, 0x3f, 0x1800}, {0x4, 0xff, 0x1000}, {0x3, 0xe75, 0x800}, {0x4, 0xcc7, 0x400}, {0x2, 0x7f, 0x1c00}, {}], 0x6)


r0 = syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047460, &(0x7f00000000c0)=0x3)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x0, 0xffff, 0x0, 0x0, "bd1331844e5b401532158b01004d9c602691cdcf"})
write(r0, &(0x7f0000000240)="f561325db04cafa4512e5736e365ec83b3cafe082b7b4436cd4c057f8ba5b08a4c719ec710b568ae0f7befd0ed09", 0x2e)


sysctl$hw(&(0x7f0000000500)={0x6, 0x18}, 0x2, &(0x7f0000000000)="1c1d1332", &(0x7f0000000580)=0x4, 0x0, 0x0)


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)='\x00', 0x1}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
setsockopt$inet_opts(r0, 0x0, 0x9, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x2000, 0x2d87)
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
writev(r1, &(0x7f0000000180)=[{&(0x7f0000003380)="c0", 0x1}], 0x1)
writev(r0, &(0x7f00000008c0)=[{&(0x7f0000000080)='z', 0x1}], 0x1)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000040)={&(0x7f00000000c0)=[{}, {0x8}], 0x2})


mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000400), 0x0, 0x0)
preadv(r0, &(0x7f0000000080), 0x0, 0x0)
close(0xffffffffffffffff)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
r1 = socket(0x18, 0x1, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r2 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0106924, &(0x7f00000001c0))
ioctl$FIONREAD(r1, 0xc1206922, &(0x7f0000000100))


socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000440), 0x1, 0x0)
socket(0x0, 0x0, 0x0)
r1 = socket$inet6(0x18, 0x0, 0x0)
setsockopt$inet6_MRT6_ADD_MFC(r1, 0x29, 0x1a, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x6000, 0xe02)
r2 = socket(0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
syz_open_pts()
close(0xffffffffffffffff)
r3 = socket$inet(0x2, 0x3, 0x0)
getsockopt$inet_opts(r3, 0x0, 0x0, 0x0, 0x0)
poll(0x0, 0x0, 0x0)
openat$wsdisplay(0xffffffffffffff9c, 0x0, 0x0, 0x0)
writev(r2, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
r4 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$VNDIOCSET(r4, 0xc0384600, &(0x7f0000000140)={&(0x7f00000000c0)='./file0\x00', 0xcb, 0x0})
openat(0xffffffffffffff9c, 0x0, 0x40, 0x63)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000040), 0x8)
sendmmsg(0xffffffffffffffff, &(0x7f0000000080)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f00000002c0)=ANY=[], 0x18}}, 0x10, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
openat(0xffffffffffffffff, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(r0, 0x80085762, &(0x7f0000000040))


syz_emit_ethernet(0x36, &(0x7f0000000240)=ANY=[@ANYBLOB="ffffffffffffffffffffffff86dd6060626000000000fe8000000000052f5dac0000000000bbfe8000400000000000000000000000aab2f8b7d29beee6658e437483226b3e4de9c8b844dc5651c977a22774ebe8a4989446635360daf0f1ca08d5800a41"])
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x100000000000000, 0x10000000000001}})
r0 = socket(0x18, 0x1, 0x0)
close(r0)
socket(0x18, 0x2, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
mknod(&(0x7f0000000080)='./file0\x00', 0x6000, 0xe02)
recvmmsg(0xffffffffffffff9c, &(0x7f0000003cc0)={&(0x7f00000009c0)={&(0x7f00000001c0)=@in, 0xc, &(0x7f0000003c40)=[{&(0x7f0000000240)=""/3, 0x3}, {&(0x7f0000000580)=""/129, 0x81}, {&(0x7f0000000b40)=""/4096, 0x1000}, {&(0x7f0000001b40)=""/4096, 0x1000}, {&(0x7f0000002b40)=""/4096, 0x1000}, {&(0x7f0000000940)=""/122, 0x7a}, {&(0x7f0000003b40)=""/200, 0xc8}], 0x7, &(0x7f0000000280)=""/64, 0x40}, 0xbf6f}, 0x10, 0x821, &(0x7f0000003d00)={0x600000000000, 0x5})
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000a00), 0x0, 0x0)
readv(r1, &(0x7f0000000800)=[{&(0x7f0000000500)=""/120, 0x68}, {&(0x7f00000002c0)=""/122, 0x7a}, {&(0x7f0000000340)=""/228, 0xe4}, {&(0x7f0000000440)=""/102, 0x74}, {&(0x7f00000004c0)=""/62, 0x3e}, {&(0x7f0000000a40)=""/225, 0xec}, {&(0x7f0000000640)=""/242, 0xf2}, {&(0x7f0000000740)=""/142, 0x8e}], 0x8)
r2 = socket$inet(0x2, 0x4003, 0x0)
r3 = syz_open_pts()
close(r3)
ioctl$TIOCSETD(r3, 0x8004741b, &(0x7f00000000c0)=0x9)
r4 = openat(0xffffffffffffff9c, &(0x7f0000000180)='./file0\x00', 0x7fd600faffc9bf32, 0x0)
getsockname(r4, &(0x7f0000003d80)=@in, &(0x7f0000003e00)=0xc)
poll(&(0x7f0000000040)=[{}, {r4, 0x1}], 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x0, &(0x7f0000003d40)="06d8d1b81f3a6632510d154a7788e22c4fbc5227deb161aa30e68e070dce9ee3852d5c1a466c8b4492756c792fa7fe3532befd969cae2283e7", 0x39)
writev(r3, &(0x7f00000005c0)=[{&(0x7f0000000740)="725c8409679f313f04e4b9d42c3c87840bce82cdd178d6ed6a60862c0ec6c2efa1fffa6bc8e424931e23a9f3edb23850f45d360bd5ea818b41738cb92aadcee4d8b3400a1063dd91e935979dec31aaccb2cb5899ad1281ca57ce5eed2e6196c591f280f290f40361623853a6555485007cd1d82417488523ab00e83703eeaa96594999f5045941a0b7a270405e11557ddb9502b9a513bf0da7c552814269d3edbf5a65a973b9a2e71e3d1478a032f7422f8a0d1ff92589429f95ae780075f65ed3d4d7fc564ac6eb890cea7c046de94e9ef5297a1a6190831076bd70b9640c7b894baf78df076e3232d8159045b9f987d6a8d9353ac5c2257ffdcea15ac32c8696111eadacaa5960f704f8bd481a807777724cc4d646d0ec68d1228734d300e74105c9fbf82add6c8da38517c0f0f15d20dc228a2b9c3616731027b99b0a2e74cde07afb29fdb47013353c3fd88935aa944641eeac605d6dd23a8dd9e565c3187a86be9a4aef895e9d8e6d2fdc644a858a5d8907f60fd9db761281b977f3058f3e33e2f65b13ba640f536fd39dba38c0187e0e2a1716ab480fecb11d4f46f56cbabf76506774f4332d60afbffdc9244a7b3ee7ccd1fe86191ed4f74a4620116539957a785975621bac2cba5200c375c1cd1784cf23bbb56681b037e7c4d921dbb037ce546c561c3bb5eb0ca0d6a620ae87e5f66bb9f33cd79cd20e49ffe81695189d65b7c77d253b45917a0c4761a8c822401aeefe6dd13c9ee120b2d14b5a9a0db341407350933c1efb9f5c61dd7f91ace54e78b746b196d37ddb4742f25efa660be97cb2581311a94ecccd2da878a1d052e9e19a5b3cb854cd0a697b600e417817131266834ec8ce59669c9fa755641874f2877e6f82a88246815ae114b53fe2c0685ef2789b1b4f02cbac6645d7de427f3ef35938a4a499a7f05b054886ea8c7117bb3c99e003176ed9df7fe50b875e3ab206456bd5566c8007051482c9a01b5363fe1557213119070bfa39f1b71ffbf531fa0d929da5698c2c9286e9b5ce0b660d8829645c6c08f2f095f91a57fc70b3f173682b64c400086c4f0aaa94df08ed8f69245bdb5a15b14baf7bf72b451f25bc5fdd51c0c5d0f40a7a813dc07c9dfa3c7039c4585b49885d2420bb9af88f362e5ca203d3a3b2dc6b58c06d5908dd5b5d2e802578e46ee80e21003c7935a340412442747d920f78ef27905a2f0fb2efff968cf4bb33bd4d8a5384fcd886b4c4dbea593770b799f1e09b6fa08f966ae16feab25cdb104b075d424bd371d51b054b94fb288e0e2b76bc67b695baa5bebc7a68f00ea8b8d9d6e6c9e53af21a30cd5fc31c9a07b33da448bf4543fe850e1dd5fdf5cfca72e5dab0e36a5e0854fea45a590eef3297449bc082ee3e80f552ddec8c0dc7f7adf9d960c94cbfa9ce4d1990249fd4ad6c59b91040dbef8611bce60459e85c5f9125b0c769192ef40f1eefba6067aa75fa2e0cfc92cf8d5c65db999e16d43f6d6cf28a460b3ef7ff8d9421c9602cee2bda0b817021fe41964b305e8b9ab2be3e898fbf7c42ffe01ce1edd3c71622bcfd15b67d320e0917d191d209f709a268b0c324898437883922514fcddefd035d315a14de005c9ede97e539f5054f3aec738fb2394d4178ef323c7cb85a273064f3af8d274ea034a9cdd8e10582fdec0e3a385df843ea102f368bf8a89e15c42cc7fd85e33f6229f47c6b3143e0c6476a62d50ca341e7679aa816f901a5546c78774cb9663591f71f9eea1467034dd1a90a829a104727c8c61dc27491d146c4b26b9054ea346512d2aa363f64d5cdbe80d8c4db33998f25e777e44c6eec49c4bdb3cc122cb5dbece3cf106381eecfb789dc8f013a07358386ac575a0c94aba872e5d6f91e1dcdf4f3c60af3a1aaf2c4895b33ccfc176a3c553e07fe21d2f3c617833f92fc0e86ec93c024ce7c3deb72fd1712c7022dad05345cf0b78f69d55a622d81b72e03067449b5c04b8c3d17c25bb97ae27203201739d6271b6752a7520e90266b1d920eaed1f70f97d9e7da4da94862989b494fdcadde71182329c47269a149b14d1fd4443f3ee97bf73e2a097f60854b0f36c35f017a30300d2d39fdb822fcc7ec3fb188f73112f869ec57b04888c35417a8806569f5b9f060fbfe7560b735f85677febc836cdc7feefac1546d6a45673bb31aa004edda049f28f167c533156823f2ded3236c8502216ce2188e3099a6c20f1f3af437ceb5bedbfcbeea20212ac2bdf574037cff354799a1739f1fdeaf59e8698d9dc1132484c64ac771f6b4eddc3cf359c267fbed037bba5025a9a9ef596628b5e1a3de1489dda596e7f8461fc394fc3a6199378a55a53d14c7cf1f0bfe3a41fe73d749e215ec6a06ee36c5fb53930162ae840685a7020566919720e5e86091eecbb2e4e35ef009974abfffdfcaa95266ad3fb17a102ccb2c222cc5d23684a70e67918eb659f541883ad975634b6bd5a1f6e7b426355c68267147d435152db7a0ba33adca52901cbca3f716eba2b7dc2a3341d7be725ee70caf99142d3c40872ef30e64841d03beee1c6bef29a69ddd0e1c701e1ee4656f5cca9a40b9aa0b5a797b3a6587a775d85a8fdbe9ffdb54073ed8df4c35b80bada6c86cba3172e985bc91c6f090068d5d53df3073c8e4bffa3c37d40077f95184ca9f35d1e7866c62dad0a7b36ada4c3f7704f2bbd5a435520b84f106600358952e7377fa8027f81783e7b8f4441e014db0f99ec83e29cc2e34c47ecbeb8c08b1f4622102c213bdd056a1b58328579bc81cead0291cf46e4c24aeef8161204a6307ae5d86010c77ae87c39ef640e3e5872e59a4e4f4d53df9f1c327dd1bf471b89d42b5bce7666c830e781d031b78dcaf76b697b3f2c823dc8997caca87b12cddc604058fb134f2948a09a45afae836d051aef84b624c1184c76ddd895cc2480d3d4fa1b6ff606afddf894da02c4c1e62277ec6612cf85b9451aa8d33ce73ff2620e3532f00a85cb9713492d0ac31b6800d5efe6511a971a608286e45df8ac8e2cbbe2498ae7cff5fff2912d9a09febb949feb59ef5da653f864656a9d5d6bc65cea79d987ee5c370474252a6c43b00177f4f94a1bc3e1c6d1affe6ed3cddc074edcfd84e22269359ccf5d8a24fb1d6cf22ea160edfff061792bd9ca386a311ebeec593c083821c242ec78d040a3fc5e14bfff47c499509b20f21fb294ce521fa4ffd79afe32e163b6dc80d09f2085f78a6d407b1107b68ce31927ea3aa1e7d43400ed67c9b525912a73c7cad2977bbc4288503e5595b865842caba1f6a27b463f37d74ca81e6f420eb59fc94e35204d04817c405016b350cf3c63d73d588b444d46f52fc775ab0fb4f855757855f90bbca18f93ed2b88587ecb20b50420b18c32fa7732ca25231a09a178cf263e349b7ff36ae4e3f4c590e7c704830bd050f4783e43e6e480135debac1acdd504baf17f5aa919d74d2ed0248278f885fd0e9a6e0ec0ac614a5c3d9fee0f077f4ca3b14541e43a032e121cf91a0f6509ca135a16f58bcfe954b62e0e73a71067dd3e389f0e0806864b9d427a820ceee0763d4f455c2fa75a442ad8c9ac8163f484d32d1f3edc6b7d9af5d4b00eb93f896fbb953dac8d6cac4ce4bbe70e716a6fa45e79a2d1137f271099f7ec197bedece74dac272850c04f2d10a0e1ce1c1fa034fafe2bd976269a0bfdfe6e313361789550aa213fed4ac6c6def448411ca59ecb2382bfa6b2245c49a373a931950de09b23d56bfd0a7ab72c44d0f90910d063979dc6a7228f2d578b4d6f80d77a0e9b4abf18606a1ecadaea9493897c910757ddb6837c54a466b67a495868947f47b504f71d0fa48d99245d18c5e37dbf73cb91650f704de521b6f864ccc016d26d002bcad06d278b6f21c324121f9a37997f0875b7fa024f7b2d9fb8ae8263de347dd3939b2308d79ff4e28291c6afbc7932a077a5443ea64b6b3c1afc78c80b6531d08c220a1cb3be9de6c092941d98ee3aa6dcadc3ef1d6b5c9cae5de7c0c8a9d4a0c31d65fc0d1bb758d2ecd464e9bc81d945625c26702569afc841a2f170a0de02549fedf36474597b6fb4caef11d291fe8ceb1761ab0e428d43c20d703b474786af57839d1e8bd971dacde760fc77956c57665dcc2b50106f91d90da4bb0772eeddccfe7e6f374bb6dd4c2510a", 0xb8e}], 0x1)
dup(r3)
setsockopt$inet_opts(r2, 0x0, 0x6, &(0x7f0000000180)="99c300016bae3b53fb0b7051", 0x4)
getsockname$inet6(r0, &(0x7f0000003dc0), &(0x7f0000003e40)=0xc)
writev(r2, &(0x7f0000000200)=[{&(0x7f0000000000)="741693220c5b6189a4e45ee498d2756dfb0e9e4986cb196a5323d8fd9fef2d03f8cb57a8a7b5a547375fb4b308e849187741595c11dd5f59c4a08adc72848e6956056f6790e1379c3f394f86bb1712aea6a6a68310a12908b17379c5278fe07a075021a4b548f4ff84f4e4b37be1b610d5dc71795730b619d2f7f2826e624bee7bfc2ef6f6d18922022fc1188ea02b6820654804d25d2bf689a5d43a22f7f4f35278248e972b7795285746", 0xab}, {&(0x7f00000000c0)="4118a3d9e102ac9cb0e0b038d3f743512c5c8b30112c99a8eae151b0d2b264d282f6b7085f4a99bf135100fccfdb6088c45e22a47891a845644b5426e792e7c072bd6fde9a7898a0123317837d38fe463c52e145be75a0d358d3f3c632e8a1d8fff333456f7c1165306141cc6f2002bee67105f0daaadf979c2b3f9789c5cd8877ee0e7e1426fdc43f8f5d91068d7a2a277733f96cfeef1cb698057c2d2ff951e5921d65852a8c2ee61f93f1893d0bca5467d0dbd89c00851d5a309eabcc9ac7c47d30bb279745ca18778c103fc22e8dc218a2f12e290332ce31835b6563c7fd6bcf8b1b697f6a297c636baca143815d0f5a9f21e1d08044", 0xf8}], 0x2)
r5 = socket(0x6, 0x4000, 0x1f)
mquery(&(0x7f0000ffd000/0x3000)=nil, 0x3000, 0x4, 0x10, r5, 0x4)
open(&(0x7f0000000180)='./file0\x00', 0x0, 0x101)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000001})
r1 = open(&(0x7f0000001180)='./file0\x00', 0x0, 0x0)
flock(r1, 0x2)
r2 = open(&(0x7f0000000040)='./file0\x00', 0x205, 0x0)
fcntl$lock(r2, 0x8, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x1000300010008, 0xffffffffffffffff})


semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r0 = fcntl$dupfd(0xffffffffffffffff, 0xa, 0xffffffffffffffff)
ioctl$KDMKTONE(r0, 0x20004b08, &(0x7f0000000040)=0x6)
getrusage(0x0, 0x0)
ioctl$WSDISPLAYIO_DELSCREEN(r0, 0x80085754, &(0x7f0000000080)={0x6})
ioctl$BIOCSFILDROP(r0, 0x80044279, &(0x7f0000000000)=0x7)
r1 = socket(0x11, 0x3, 0x0)
sendto$unix(r1, &(0x7f0000000500)="9401050138a85a80b1b0782797888fd1f838a311000000000000b13886ca3849451ae3c3051020741038f5538551f30ce390500e08fecea11ea8fef96e4fc748e93f0b780486aebdbe781e4d8f5eef9187a869a4d3a4cbba982fd825582fe2aa7923ed00f4c8b2ca3ebbc259699a1f132e27acb5d62934e4fd89070000000000000070c1f5a872c88dff7cc53c894303b2a0a85ff3faa800000000009ec7ab3a34c29000000000000000000000000000002d7e4a5d76cc3f9cff2ed2243e56fa277603c5cc1e047326bcf6b67b75d00bf6ee330b6a80874b70559d9975ebd13da2447a78aa4b00cd0ba1870215607bb912e3d7325183ce69456b4b6ca927871c81672a54ec695c5bdeb842836656f917945cc076f87dc714dfe0aa2947252df350707b22884a7730cb6dba8742110fbe9ec7481885274387e0b1dbe5695122604819b0b2294b7b20726a5d4fcb44f62d00fabb2f247a166d8d79d05b8cc370f5c11db58aedca632a83acd58ff0ea0a3dca58ccb03cce466cda735017196ff346c32717397d6ec6952ec90de81ed297b2319e130f", 0x194, 0x0, 0x0, 0x0)
r2 = socket$inet(0x2, 0x8000, 0x5)
setsockopt$inet_opts(r2, 0x0, 0x0, &(0x7f00000000c0)="946a907e72a05cc93ccb8cb050c3cff7427c469e0cbe44daa2133db4cb4a5fb3f8c03990e9f473a41ac3dda5c325b87b47991b262114991c6831aaa79032e03247b08a73959d8f769edc87665ae126d8309e5c2abc6bdf35669cc5f1f29076d89e585d866110d47431339dfe6b8f5a8f144d915ce8c64bee3d653ddf72e4ecbd1a4c9709ec068a691bbbb5778379bd22c6cc8191fc0aec32a08b25b1ad8e4f5ba3d9a1909443b1767774fad58a4bba5d75129716fa949c389f8cb801e92fc115ed219b240750369c5c81af9685e03c47cd7ec8b8a7a40e8541f5d7270be219a87a4d3352c9de9bbd182259dcc383", 0xee)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r3 = shmget$private(0x0, 0x3000, 0x11c, &(0x7f0000ffa000/0x3000)=nil)
semget$private(0x0, 0x0, 0x0)
semctl$GETZCNT(r3, 0x0, 0xf, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x6000, 0xe06)
unveil(&(0x7f0000000040)='.\x00', &(0x7f0000000080)='r\x00')
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000080)=[{}, {}, {}], 0x3})
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x40, 0x0)


open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
r0 = open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
r1 = getpid()
ktrace(&(0x7f0000000280)='./file0\x00', 0x0, 0x928, r1)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r0, 0x0)
r2 = kqueue()
kevent(r2, 0x0, 0x0, 0x0, 0x0, &(0x7f00000001c0))


openat$zero(0xffffffffffffff9c, &(0x7f0000000980), 0xe8, 0x0)
ioctl$KDSETLED(0xffffffffffffffff, 0x20004b42, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1000300000001, 0xffffffffffffffff})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x1ff, 0x0, {0x0, 0x1}})
ioctl$FIONREAD(0xffffffffffffffff, 0x802069c7, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
r0 = socket(0x18, 0x4002, 0x0)
r1 = dup(r0)
setsockopt(r1, 0x1000000000029, 0xc, 0x0, 0x0)
socket(0x0, 0x3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x0, 0x0})
socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, &(0x7f00000001c0))
ioctl$FIONREAD(0xffffffffffffffff, 0xc1206951, &(0x7f0000000100))
ktrace(&(0x7f0000000100)='./file1\x00', 0x1, 0x104, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
r2 = socket(0x18, 0x1, 0x0)
setsockopt(r2, 0x1000000029, 0xc, &(0x7f0000002a80)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r2, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r2, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000240)={0x3, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x0, 0x2}, {0x6}]})
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f00000001c0)=[{0x14}, {0x60}, {0x8106}]})
syz_emit_ethernet(0x62, &(0x7f0000000140)=ANY=[])
r1 = socket(0x18, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = geteuid()
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000180)={0x0, <r3=>0x0}, &(0x7f0000000280)=0xc)
setreuid(r2, r3)
socket(0x2, 0x0, 0x0)
getegid()
ioctl$FIONREAD(0xffffffffffffffff, 0x802069b5, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
ioctl$BIOCGDIRFILT(0xffffffffffffff9c, 0x4004427c, 0x0)
mkdir(&(0x7f0000000200)='./file0\x00', 0x40)
socket(0x18, 0x2, 0x0)
select(0x0, 0x0, 0x0, 0x0, &(0x7f00000000c0))
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000740)={0xffffffffffffffff, <r4=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000380)=""/93, 0x5d}, 0x3f8d}, 0x10, 0x0, 0x0)
sendmmsg(r4, &(0x7f0000000080)={0x0}, 0x10, 0x0)
close(r4)
socket$inet6(0x1e, 0x0, 0x0)
pwritev(0xffffffffffffffff, &(0x7f0000000540)=[{0x0}], 0x1, 0x0)
sysctl$net_inet_ah(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)
r5 = semget(0x2, 0x4, 0x0)
semop(r5, &(0x7f0000000140)=[{0x3, 0x0, 0x1000}, {0x3}, {0x0, 0x5, 0x1000}], 0x3)


r0 = getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r0})
r1 = open(&(0x7f0000000180)='./file0\x00', 0x75f493fec6515f78, 0x0)
recvfrom(r1, &(0x7f0000000280)=""/160, 0xa0, 0x0, 0x0, 0x0)
pipe(&(0x7f00000001c0)={<r2=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r2, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r3 = fcntl$getown(r2, 0x5)
setreuid(0xee00, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x0, r3)
setreuid(0x0, 0x0)
ktrace(&(0x7f0000000140)='./file0\x00', 0x4, 0x1808, r3)


r0 = syz_open_pts()
r1 = getpgrp()
fcntl$lock(r0, 0x0, &(0x7f0000000440)={0x2, 0x0, 0x5, 0xfff, r1})
write(r0, &(0x7f0000000100)='@', 0x1)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000000)=0x9)
close(r0)
execve(0x0, 0x0, 0x0)
r2 = semget(0x1, 0x2, 0x389)
semctl$GETNCNT(r2, 0x4, 0x3, &(0x7f0000000540)=""/189)
syz_open_pts()
syz_open_pts()
syz_open_pts()
ioctl$WSKBDIO_GETMAP(0xffffffffffffffff, 0xc0105715, &(0x7f0000000000)={0x0, 0x0})
shmctl$IPC_STAT(0x0, 0x2, 0x0)
sysctl$hw(&(0x7f0000001980)={0x6, 0x17}, 0x2, 0x0, &(0x7f0000001a80), 0x0, 0x0)
r3 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r3, 0x80105728, &(0x7f0000000040)={&(0x7f00000000c0)=[{0x101}, {}], 0x2})
readv(r3, &(0x7f0000000400)=[{&(0x7f0000000280)=""/128, 0x80}, {&(0x7f0000000300)=""/217, 0xd9}], 0x2)
sysctl$kern(&(0x7f0000000080)={0x1, 0x14}, 0x2, &(0x7f0000000100)="4be966818942f3a3915d18d51e256e8ae310480289e9cf511af96a27dd007f4aca96ce009789358471e96f81ff8e8d4161780238c20db00c0eb222dcf514b35b5477fe5f96c4765639725ebfb4cc97942b21f13ed9fdd6", &(0x7f0000000180)=0x57, &(0x7f00000001c0)="0e424c305b9115e0bdd131ee905e20230f66cc4eec19a240509ec631f4ef375f2149bf0624fc7b2ef1de4c8eece80f45e3a8cb3fa2f2796e7beb73b15d250a5ee15e6f9dc48478e0ac1a464aba6c77f448777da39abb42bb4392c62fd5da3388d6981bc277bbeb85ee6cd6d4e58b7b317760c34d0ee2b64d9ce48f2d9a27b4c0a0fb134d16", 0x85)


sysctl$kern(&(0x7f0000000080)={0x1, 0x3d}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)
r0 = syz_open_pts()
openat$speaker(0xffffffffffffff9c, &(0x7f0000000140), 0x2, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1000300000000})
setreuid(0xee00, 0x0)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
setrlimit(0x0, &(0x7f0000000000)={0x1, 0x1})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$VMM_IOC_RUN(r1, 0x8020560a, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, 0x0})
r2 = getuid()
setreuid(0xee00, r2)
flock(r0, 0x1)


writev(0xffffffffffffffff, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000140)={0x3, &(0x7f0000000700)=[{0x1c}, {0x44}, {0x6}]})
write(r0, &(0x7f00000002c0)="0000003171f6b2b6a767df38ab0c", 0xe)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x1604)
open(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b10005136000009f05003e0800000000331c13fecea10500fef96ecfc72fd3357a068d02bc31a3a5673039d2d236acf20b7804be38164991f7cccf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f4d335c223e7d026ba8faff0037720fd38bfbb770c1f5a872c881e2772ec5a10400000000000000361b1257aea8c5d0002012000000000000880d6633c556ae9b287948a62310db415f779642cdcd71a3f8343712051e000000000000", 0xb1, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000140)=[{0x5c}, {0x64}, {0x40e}]})
syz_emit_ethernet(0x2a, &(0x7f0000000040)=ANY=[])


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000140)=[{0x3}, {0x2d}, {0x40e}]})
syz_emit_ethernet(0x103e, &(0x7f0000001980)=ANY=[])
munmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000)
r1 = socket(0x11, 0x3, 0x0)
sendto$unix(r1, &(0x7f00000000c0)="b1000502000000000000000003000000330002000000000000f96ecfc72fd3357ae320b37b673039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa5b236de351e2f0ac3ebbc257699a5f139b672f4d335d223e7d026ba8af630037382102000000720fd38bfbb770c1f5a8727781ea2e69e0bb76d907c400000000361b1257aea8c500002002fbff0c230000aabfba0900000008e371a304353712051eadb71d89e000040781e4b2ffffc00000", 0xb1, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x0)
r2 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000100)='./file0\x00', 0x1000, 0x0)
r3 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r4 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$DIOCMAP(r4, 0xc0106477, &(0x7f0000000200)={&(0x7f00000002c0)='./file0\x00', r3})
acct(&(0x7f0000000140)='./file0\x00')
socket(0x2, 0x0, 0x0)
r5 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r5, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000300)={0x1, &(0x7f00000000c0)=[{}, {0x1}]})
r6 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_GETPARAMS(r6, 0x80105727, &(0x7f00000000c0)={&(0x7f0000000080)=[{0x24}], 0x1})
ioctl$BIOCSRTIMEOUT(r2, 0x8010426d, &(0x7f0000000040)={0x2, 0x401})
minherit(&(0x7f0000fff000/0x1000)=nil, 0x1000, 0x2)
open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)
r7 = socket$inet(0x2, 0x3, 0x0)
dup2(r7, r5)


r0 = socket(0x18, 0x2, 0x0)
close(r0)
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x10205b1a)
open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)
select(0x40, &(0x7f0000000000), &(0x7f0000000040)={0x7fffffff}, 0x0, 0x0)
r1 = kqueue()
shmctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{0x3, 0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, 0x0, 0x0, 0xffffffffffffffff})
kevent(r1, &(0x7f0000000080), 0x3, 0x0, 0x7, 0x0)
close(r0)


r0 = open(&(0x7f0000001700)='./file0\x00', 0x70e, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
sysctl$net_inet_ip(&(0x7f00000000c0)={0x4, 0x1e, 0x2, 0x2}, 0x4, 0x0, 0x0, 0x0, 0x0)
r2 = socket(0x18, 0x1, 0x0)
shutdown(r2, 0x1)
bind$unix(r2, &(0x7f0000000000)=@abs={0x0, 0x0, 0x1}, 0x8)
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000080)=[{0x2}, {0x2}, {0x6, 0x0, 0x0, 0x6d7}]})
writev(r1, &(0x7f0000000000)=[{&(0x7f00000001c0)="d2bc78b52324b9a50c786b26df53", 0xe}], 0x1)
r3 = open$dir(&(0x7f0000000040)='./file0\x00', 0xa00, 0x0)
r4 = socket(0x2, 0x2, 0x0)
getsockname$unix(r4, &(0x7f0000000000)=@abs, &(0x7f0000000340)=0x8)
dup2(r3, r4)
mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x0, 0x810, r3, 0x0)
r5 = open$dir(&(0x7f0000000380)='./file0\x00', 0x1, 0x0)
ftruncate(r5, 0x91a1)
mmap(&(0x7f0000ffb000/0x1000)=nil, 0x1000, 0x4, 0x810, r0, 0x0)
r6 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000011000/0x2000)=nil, 0x2000, 0x4, 0x10, r6, 0x200)
write(r0, &(0x7f0000000000)="3832af5a5775acb1e5c643", 0xb)
writev(r0, &(0x7f0000001580)=[{&(0x7f0000000280)}, {&(0x7f00000000c0)="f8e21c198c33612b03d0a144a33b07dd950014de125ac4b1ceb21e00f55c5146f72415fb2fa7e4798e51ed4453a1a27e3c31944c13c188e08ba2ffe998c6d40abe1b7b728fb3c9c166a849f62cdd716d7bf39dfa84ab291fffa6dfcbabdd51d2df6ce285df849db7da946b9a9d8d2500784358d7922b2aa4dc7e2322f8235669caed77c5798f57bf4e7ce5dbbbdfaee7f0b356f724ff9bee5bb76ebbd538d287276b9630e55370dda88dcc4dc6bb09edfae88442aa85bdc7c77e4ea23cbeb9", 0xbf}, {&(0x7f00000004c0)="f713c4d5f33865c032e189907f732703f921f230c367713c9621d826a435c8a5a6b73c5e38fa6dfa1881b4c54c0fc8171a857a0f4c94ecd5be8ae63e33ecaa5f5ca33d62261c71e4a1500d6e0997d735817ed2ce00fdae0760868412852794ff57ced4e699a3e4df1d9ab3e0b03845f549d6c287cb0b4fe826261feb0bf0bf0997d07c068f9fa807e88467f85a543c458ddc1d578603f40078f2702898ff2cc93c0346049fe10e7c8e06981c8dbd8f5375d71a32e76ee5f79144ac3995bfbf7df2dd74912b45de529f7c0c0a95a2b25dc0dcd02db702caf8eaf14efcd34109d7cdcd191eb7dd383e1e34ae4ad2099265a80e1ab16aaff43ed5bec42b949fe273312c7aaed09daaf9bc4806fce6ea07691d610959168394cd250787937be3b9d9eb4fe5ac4c81154584d7554ada65294383e3db7080aa664f1e5b4426d2b3ac858b0de60f3b0d0826723edaf970e2e8f2a85bdb22abd6e3f4361b97466de4e19946b3e1002733f2cec3a74d831a08fe549fecaf409fb6506a39786d216fce0fb02724cea5a3e59883495129f08c5093fb1075657c1a6eb103cc995319165a499897d3d4426c82329be4f280c215dc52ce6cba3f7799ebf5cf056e923b1c775555287f9636ae5afd98c152ab54828beb9def5f59672e25ca897cbf7cb2e9614e8fae93bc3c0f3ce24f96a1cce3686edf96fdcd465c768f706369c2112d6ef401b5bc12d808282f298495950d4011705bc221191d2d05c7c1aa94aaa3bd6ba2bf403ca48875f04768e83e03af145fc8aa74e3d94ace308e2b9b024b9ed3997da2e8fd203e35101dc08f065245db65cf33271dd249b8b4f1acd91e7e4df5894870df056d31cf5b119715d5c0ac17b997e8dbbb39e4a467986f88f09bcef2b9e2aea40cdc4be83b0db068ebed3eb93038e62936a1331a398fbb560d30905ddc36aff09e4ed78b998b535353d9085db1ee90cb1769a2d4401a89932169040de9a9dba99d40a1d91b7ecb1269b94e4373616c9f2beb066242fd4223bfe03db6444294836d6b66e907d72cb20ee3b8d60625a6db6cccea4340033d5a4106ca64e294381c9943d2e53e850bff6a01df9feafd48768dd745c0760d26bac941cea200d0ed4da095aa4873e31a6126a0b539601dff801c0cd14078bb3f53d98cff835668a07842fcf801ac69cd49d0b19671dc2be24af717d2a9e5055b964ecb7eda7a48426554988119565fea6921247b34e091b18d410fc64752efdfbd1d5c5327fb736fd42aa1e630257cdef46045e6a858e3263188e74ccb92a15dcec33014116ddcbd72361cb16f2841b52d95e7290140c429574c797082627c7f896eeb1f76429288d77ef86ac90732e84d3b6fec1f0ee7fe7b964c81418f6be8048bd6dabe12821294c3fa90a947da808c75e9d0ca07d83da5f8d2e88057b9daf94c62fdce3150be3daf400f56c5739f214cc1c8df413463a4d7d9bb6cd13354116dfd3cfb16405371f5240df41b73a6e70d7496512eec6dddadfafdd96e3d6d9621a2539e9aaeacae13d849e07d5a0ad5f5a66f68f136ff9d4588596e911ccc360be1df0466dde19f5dcf1ffbd90f89f02c5b0c8f4ad50b637f71c686e118097f14c5e2e6d6a0d1ed31c985b78ebbd71dc1cd70b2efa6e852ad746f16be5118e140fe197f25facb2352c71c5de953316421090c7ae0a103db457fd56661d51bd4ace3ddb349b0a32fc47d48cc93fa9254491a02d90b2a6e4310629dd16277bbd8e90962a601bc8c0a57e235bc4f40d3d4f1c9900af6f9ac4836f715c93902308ebc0546ad01b6c9dbf3cf5e810caa0c2dd254bfaebdc11bd5a751154f704f06c18b51c7b1891dde00e478b2d7ea9d46becabc40b05c83df7f5cfc8650f25d9766c84b2bdb94c26fda4913e304b09af07c7ad9795ac34089197afe1b89e4bab54bdcbf0b51fc295299e1176e97f49c1c3737ea80c902ae546f76a390960900c95332fbfe0c5f3823abf829ba396afb7a3020c9ff4203d620eefa030afd72ce0eb1a9c150c61b901e2a4fa6761b7f8b9ae893d670f6ab0845c33a2470026345ea7f2fa0e487c222065773c6992bc64c3f3df92717bd45fa3ee43e8bc49bbb72b8b0b09c42fe4d7bfe98e5f693c24e416b1b1ecfb1ba8927ee15f1a4adc75eac0f970506dafee7b46be264e8673d0bef30c676e50686712a0d15556452c1fe8c337a18f2ca0241459999ce111b1c82589d41317770d6998799754d66ba4242d3a1d195a47a53326e18a279eda6ce2a73e90c4f991532b3d16768ad31943abe8a943cde77a8aaaa827e38598a54e1fc83dc010da49f4d8660ce2a729c8340cb49ae893474e6970a56201280d3211ebd3260d7c7c84c2df9cd16d0a5f6032877d8929bd3736799f0b08434c743e387587ca40357192942fd1b2d64b3a91507384cc2a6c972dbd6d48da8a3925a204a11ed3616db3c2f2f5dcd8585c9394d7b43d0cb5303db0eee5d16e870aec4425356938f797d214f32a435ceac0d540d51146623ab1a374fd7b5544b40dc0e02971b8f1031a11180ba9fea8fb062394ec81326c4dca953994f371559d2929e30e5bc90e07c951bccd62caf89a9fc6be37e943d31864a931d72932691f1578222098216a8939b26af714cdfb74e9a8eb7dfd05b01a612954616e87dad5b370cb3a0e5cab866909e25656cc557268a6ed9c43103446753d556286b6560b2a325736edd110779467524421ae9d57d461ad48909a015b022f2a3e0f068a75fe489fbb4c367540d744ccd2bd97ac9ff32e38cc7420dc780c3636b256c4fb40e7b224109a45484fa914a3cde8428fc1f4623f1294ada406811da488f6780797eaf8373b777bd00eb1d021e12c57d05e373b8c2b4226544393acee86bc2c2601d5284708dddaf4eb6828a2dfbe0fb1785654d1065dc050f40d1859943dda5420377fc6514145264bd04c111de4a76fa985d5739eb5874419119d81919512b486ea08f2e31bfff594f56fc4ea799813b8396054a81b591aeae9976249625b7c11b3601ccc3cf0021788c191cb741f69302bf89cdb12c1845d1595ba166ab055f2638a58b5b1dce4475dfc4abf0af04daae195d67b6427fe39d1ec1c857b1328c4f6aede8fffcf3ad6449372457b258d0559178c4b93f57a30000000078ae58b3238986c4c94b1e0fd52462b0f2853a7a27abff630c5253deb96e77e14634a57290a3ddcffad832b207305e07415c7d511f74b3abea8f0a59d45f849b0fc249b2cc2656401a30c6689c536310e586f02613c6678ca8daa05518295d600188899faae085972153121bea7c01b4f610622b0c3dc478a9e5dfa5679912af6ef533e6a85d9fab907ee8edbeb3680abd4f20d855c3aee14298e3ab7386a6d404fce4c218919836cb0031c381b568245585c9dfea93ddcacc256954cc9bc826a1ef6f89420d95dbec2531cd1534af5b921b231f984f558f09fd363f1641f531303c66eacdea127ec3cd321536688126de22cdb85afe99c0fa8f4e0dd55fb308614419a983f7be34d2aa83643d067f3e92634bf6cc908663aa7a8a1b57e6ed1d4c1f6e411e5acc242e92bafb2f0a22b9ab7866d89beee2d4fad43ff7aa04dd35a86f676e51e417ce202db075898c49e4aff31e8228f8462cffbf897d353bffa236077131fd5e9ae762653be52a85a8e5ced1aee1fc937a2cc5c5901c7689e1db8fb17cef66e6cbc369b72475ecfa1659611f53cdf5c322278c9bd3cd80af3d2ada333bbff1e7992dfeb4a1b5ff136a2766a2fe786a200794d4595d0e69c4b9e021bb9ade324e51e18bdd04b4cac634257edbdbc8fe839faeb3053f83f95da350eac04de31ff29eab8c57a4d0c052c48c377abd1c7c7b98acf4e76458cdf884b728abe59cb97c7625d917479003686272922ff546c1c9c9179073102e6a9c2cb7e31dbe69c410066527566b391f3294077ab4d5b0c001f7eae6f7ea6b2dbc5a8da6937863cb49532c0c1f2bf14f7b596eae6c28a6c5f5179ceb18a55ecd3dafd36a74bc6aa137cd6a8eafb10fb8af62aaa29914c384dc17085f43ab708a9c164cc39dcc8713ae9bab8bcd07ed9ac8a9558e3a9b0cf9c0ba2a4704c7e7bf9ec63db0a23a84945e60768b9d805abda7c3049267dc155f47ffc38a5eb6293e9ebe4bacfec3518b850b8395894f6e7195d0f6a499647fbed8b5ebf43b4cf9e7b06f91c4296b5ab1eb425217bec38ea4d1b367fecb03e5c6ca652551615ba0b5826b5624d3e0cee23eca58c725abe50e351d3600000000000000424b426b142bcb8e036102b9385357a4b53dc241266319f8bed2073d57b819a00f625d95827a1564c543e09fa29bd20700000000000000e339af734cd36165094dbc5b2c00510283bbb3c715ac9e832ae9466e7ce3644c7b4136b66a88fa279b78e519ca08f6a5ccafc910da321d5100469b193fdb7bad56c1c52a766875f683957fcac4b1f177fd51c5f5a9edf0118edb57f879507308837630cf24627cda8a5f35141bb595bd4af90c0398d974f92f6228c644e0afe7848d1d5adfc0e505b2d04926a5c6f8527060a82188cb65899b1fa318b039f4fe0ad1b117f7601dd413ceedea8c443de1fc8e9a3a8af5cc60f763daf3165bb420aad2f8234c4aeee9d39fb2243415aac7153e94d7d0bd1e8278d31f4ff636db60f00cde3ccab7bbf20558bb7c453a84076ae27f20eb5c4957c52d66072d55d53fa19b4001fc1b1e337f75a21c71d91958660be49410064fd78be36503eb3069b37515eaa90dd776679bba5d569de68091035f5ff51f2f99008cc2ce5152ea3b8aac46649fc19a34143be73e85856c97d63afd543d8d42b2c8228fb4abbc142c4be6abbeee9c6ee308ad7af3fc57478e22dceeeaec39c69a4a45190fe623d365f867", 0xd8a}], 0x3)
mlock(&(0x7f0000007000/0xc000)=nil, 0xc000)
connect$unix(0xffffffffffffff9c, 0x0, 0x1)
socket$inet(0x2, 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x200000000000a, &(0x7f0000000040)='\x00', 0x1)
dup(0xffffffffffffffff)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
connect$unix(0xffffffffffffffff, 0x0, 0x10)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000240)=[{0x20}, {0x50}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f00000001c0)=ANY=[])
openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x40, 0x0)
pipe(&(0x7f0000000280))
r1 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r1, 0x80105727, &(0x7f0000000000)={&(0x7f0000000040)=[{}, {0x8}], 0x2})
openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x1, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000340), 0x8000, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
sysctl$vm(&(0x7f0000000000)={0x7, 0x1}, 0x3, 0x0, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f0000000000)="08eae5ed7c0a80fd0f97d0034d1d780c8382fe47dc49792e4834fbcd15d3238d320090d82eb3b39f68f953e71517999072228b09065f17a19009124e00553f5cf3790e76bcbd7b7c101217b8dc8cfcf9df22e6003944b381c8614a96c4d6489351a25d0cab0c459ded91c357bff05bed744a01622ead6f7228981dc480f9410a902d82c524a9c5127e5e6a6dcc32741b7c599258af9d4cd1e6a9551e13aeacd9fa20fa475009edee2513595781bb908494bd716daa20975fe3691c1cb36920d3c55fffe72fc59c893b1bd6c815e2b972b5921181106180125218f9e1796c", 0xde}], 0x1)
syz_open_pts()
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {&(0x7f000002f000/0xd000)=nil}, {&(0x7f0000060000/0x2000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000039000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000053000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
r2 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
getitimer(0x0, &(0x7f0000000000))
ioctl$VMM_IOC_RUN(r2, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x9})


openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
open(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000013c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000040)=[{0x2}, {0x45}, {0x6}]})
syz_emit_ethernet(0x2a, &(0x7f0000000200)=ANY=[])


kevent(0xffffffffffffffff, &(0x7f0000000040)=[{{}, 0x0, 0x0, 0x0, 0x6}], 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x6, &(0x7f0000000080), 0x0, 0x0, 0x0)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = syz_open_pts()
syz_open_pts()
syz_open_pts()
fcntl$lock(r0, 0x7, &(0x7f0000000080))


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
writev(r0, &(0x7f0000000000)=[{&(0x7f00000005c0)="f4b533c408ae65ec81e1d08a3ea2700301aa3c44c4dffa2eb5be5bb2dd33000000000000afd5175b9213452ab5d84f6c9d0ce61d3b194791bfc27428a088311d09ec78df0fe8364e1e362a61e1b8b3fc61e568aa7c9df08f53ac77bb4312e6f79ee96148d019ee9bd31859a11c664b3e17c1898b694b1438417a4cdc427ccd5d6d17cf2b3a6de21a17fa54566323", 0x8e}, {&(0x7f0000000700)="a753506bdfab65e4da7a397b16da08a9beeeaa476a3171269b965fd027d2f46c0842aa1060348c554aa17c9be75639de34bf0676052f8093cd1bbd55d980cca2213b2a40b678d187adf77764e5e8390cdfc06165ad543c7299f4d2403527d5c0691dafbd74ebb6dd14bed9a9d2be0564228a9bf09c80ad96e13d90190566ba8f78cef018f217642b", 0x88}], 0x2)
execve(0x0, 0x0, 0x0)


sysctl$net_inet_ip(&(0x7f0000000080)={0x4, 0x2, 0x0, 0xc}, 0x4, 0x0, 0x0, 0x0, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt(r0, 0x0, 0x23, 0x0, 0x0)


setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2e, &(0x7f00000028c0)={@local, @broadcast, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x20, 0x0, 0x3, 0x0, 0x0, 0x0, @empty, @remote={0xac, 0x14, 0x0}, {[@ssrr={0x89, 0x3}]}}, @icmp=@mask_reply}}}})


open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7949)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
writev(r0, &(0x7f0000000280)=[{&(0x7f0000000000)='#!', 0x2}], 0x1)
write(r0, &(0x7f0000000180)="1e", 0x1)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, &(0x7f0000000040), 0x80, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000300)={0x1, &(0x7f00000000c0)=[{0x40, 0xff, 0xff, 0x4000000}, {0x1, 0x0, 0x0, 0xffffffff}]})
r1 = getegid()
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000140)={{0x8000, 0x0, 0x0, 0x0, r1, 0x88, 0x8}, 0x0, 0x0, 0x3f})
semctl$GETVAL(0x0, 0x2, 0x5, &(0x7f0000000440)=""/158)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000080)=[{}, {0x101}, {}], 0x3})
r2 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
r3 = semget$private(0x0, 0x1, 0xa0)
ioctl$WSMOUSEIO_SRES(r2, 0x80045721, &(0x7f00000001c0)=0x6)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x100000000000000}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r4 = socket(0x18, 0x2, 0x0)
setsockopt(r4, 0x1000000000029, 0xa, &(0x7f0000000100)='\x00\x00\x00\x00', 0x4)
r5 = socket(0x2, 0x3, 0x0)
dup2(r4, r5)
setsockopt(r5, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
semctl$GETVAL(r3, 0x3, 0x5, &(0x7f0000000100)=""/52)
ioctl$WSMOUSEIO_GETPARAMS(r2, 0x80105727, &(0x7f00000000c0)={&(0x7f0000000080)=[{0x25}], 0x1})
mknod(&(0x7f0000000200)='./bus\x00', 0x40, 0x3200)
r6 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
preadv(r6, &(0x7f0000000000)=[{&(0x7f0000000300)=""/241, 0xf1}], 0x1, 0x40000003)
setreuid(0xee00, 0x0)
kqueue()
r7 = msgget$private(0x0, 0xfffffffffffffffd)
msgsnd(r7, &(0x7f0000000340)=ANY=[@ANYRESHEX, @ANYBLOB="387ca878329cf6a8bb74386a2bbc030c9ae9129079742fd836e4ecd56609ad80529809c8f3f7c7055ecd423fc0caec7467f29de78aa0cfcb80a73372533f57ed63783f95db0ef4a291f4345e73ed45fe6dcccea00bc9963c829740208a57195b19ba8e0ccda99ce5bf32362a24f06160953ebd1e9188d3e5f9ac7b729c2dca89e860f15bf7dbd61d24025d9850d6623f336fcbef65d5d656a6f77791648640855b979fa7fa9dd45d5de1bb435957e469628831ce253e91c1f0e0be2a6017086304647d377ce55d4fbee87f30953421d32546c0"], 0x0, 0x0)


r0 = socket(0x1e, 0x3, 0x0)
sendmsg$unix(r0, &(0x7f00000006c0)={0x0, 0x0, &(0x7f0000000000)=[{&(0x7f0000000040)="7607d7710200005e004e2b1f00020000", 0x10}], 0x1}, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, 0x0, 0x1, 0x0)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB])
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
socketpair$unix(0x1, 0x0, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff})
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x5900)
r2 = open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
select(0x40, &(0x7f00000002c0)={0xfffffffffffffffc}, 0x0, 0x0, 0x0)
close(r2)
recvmmsg(r1, &(0x7f0000000480)={0x0}, 0x10, 0x0, &(0x7f0000000500)={0x200ffffc, 0xa})
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f00001f9000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {}, {0x0, &(0x7f0000ffb000/0x3000)=nil, 0x1}, {0x0, &(0x7f0000158000/0x3000)=nil}, {&(0x7f000003d000/0x1000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f00000c3000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000157000/0x1000)=nil}, {0x0, &(0x7f00001eb000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f00000e0000/0x1000)=nil, &(0x7f00000d8000/0x3000)=nil}, {&(0x7f00000ca000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0xfff}, {&(0x7f00000f8000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f000053f000/0x4000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
writev(0xffffffffffffffff, &(0x7f00000012c0)=[{0x0}], 0x1)
setrlimit(0x0, 0x0)
poll(0x0, 0x0, 0x0)
close(0xffffffffffffffff)
syz_emit_ethernet(0x36, &(0x7f0000000ac0)={@broadcast, @remote, [], {@ipv6={0x86dd, {0x0, 0x6, '`b`', 0x0, 0x0, 0x0, @remote={0xfe, 0x80, '\x00', 0x0}, @local={0xfe, 0x80, '\x00', 0x0}}}}})
syz_emit_ethernet(0x4a, 0x0)
ioctl$BIOCSRTIMEOUT(0xffffffffffffffff, 0x8010426d, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000080)=[{0x0}, {&(0x7f0000000040)=""/17, 0x11}], 0x2)
pipe(0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
ioctl$FIOSETOWN(0xffffffffffffffff, 0x8004667c, 0x0)
r3 = msgget$private(0x0, 0x0)
msgctl$IPC_SET(r3, 0x1, 0x0)


mkdir(&(0x7f0000000500)='./file0\x00', 0x0)
chmod(&(0x7f0000000180)='./file0\x00', 0x23f)
chdir(&(0x7f00000001c0)='./file0\x00')
r0 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
mkdir(&(0x7f0000000500)='./file0\x00', 0x0)
chmod(&(0x7f0000000180)='./file0\x00', 0x23f)
chdir(&(0x7f00000001c0)='./file0\x00')
setuid(0xee01)
mkdirat(r0, &(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x18c)
renameat(0xffffffffffffff9c, &(0x7f0000000600)='.\x00', r0, &(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
open(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000300)={0x2, &(0x7f00000000c0)=[{}, {0x4}]})
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x50}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x10, 0x0, 0x37)


setreuid(0x0, 0xee01)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x8000000000000001})
semctl$SETALL(0x0, 0x0, 0x9, &(0x7f0000000040)=[0x7ff])
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000401})
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r1, 0x9, &(0x7f0000000280)={0x2, 0x0, 0x1, 0x1000301010006})
r2 = open(&(0x7f0000000400)='./file0\x00', 0x0, 0x0)
fcntl$lock(r2, 0x9, &(0x7f0000000140)={0x1, 0x0, 0x2, 0x269000000, 0xffffffffffffffff})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r1 = socket(0x18, 0x3, 0x3a)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
r2 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
setreuid(0x0, 0xee01)
ioctl$TIOCEXCL(r2, 0x2000740d)
open$dir(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
setsockopt(r1, 0x29, 0x6c, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
select(0x40, &(0x7f0000000040)={0xffffffffffffffff, 0x0, 0x3}, 0x0, 0x0, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000280)='./file0\x00', 0x1000, 0x0)
r3 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r4 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
ioctl$DIOCMAP(r4, 0xc0106477, &(0x7f0000000080)={&(0x7f00000002c0)='./file0\x00', r3})
ktrace(&(0x7f0000000340)='./file0\x00', 0x0, 0x0, 0x0)
setreuid(0xee00, 0x0)
open$dir(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
setreuid(0xee00, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r5 = socket(0x18, 0x1, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
setsockopt(r5, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f0000000500)={&(0x7f0000000480)='./file0\x00', 0x56, 0x0, 0x3e})
r1 = socket$unix(0x1, 0x5, 0x0)
unveil(&(0x7f0000000040)='./file0\x00', &(0x7f0000000080)='x\x00')
bind$unix(r1, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
execve(0x0, 0x0, 0x0)


sysctl$ddb(&(0x7f0000000400)={0x9, 0x6}, 0x2, &(0x7f0000000340), 0x0, 0x0, 0x0)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
open(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r1, 0x8, &(0x7f0000000000)={0x0, 0x0, 0xfffffffffffffffd, 0x1000300010000, 0xffffffffffffffff})
faccessat(0xffffffffffffffff, &(0x7f0000000000)='./bus\x00', 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
fcntl$lock(r0, 0x8, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff})


r0 = syz_open_pts()
ioctl$TIOCSTOP(r0, 0x2000746f)
ioctl$TIOCSTOP(r0, 0x2000746f)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x12}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000000)={0x2, 0x5, 0x2}, 0x3, 0x0, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000040), 0x3, &(0x7f00000000c0)="d2fa771dfaedc416be08851c851dd66dadf7c56dd8ca69c641ccffe9009d0dc9d80c8e5018", &(0x7f0000000200)=0x25, &(0x7f0000000240)="5ffe97428cd7348210a28d6ace527385203c48a7e2a9a9d164ac592d2f2f4a84b1927af2d580ee24a1060ea1243b2e5db4ca5f6fd2fa41b44e24163394569c4edf0719adf41de61c52ad2c0617e2b0e8dda480b4945b041c464e0c102eb77264b9081a6e4416c4e766e5d9a64d079a3664f0aa10a1c66f2d137b51165b5bee4f0c10a8f7498a07a9fa78a7e4f1cd4959c5662f4e4c3a7bfe4d356bd85c0a2dcffe690c88e29072cba4aa64228765ce8328fa4fd895118e44885dc152942116dadb01904be11bec31f05509000000c9e4c6720c6d680c80881ceec17cb490519a64dfd9c30530b8c5c83abfd91b0a791cf731d2fecc822993095b45e0ef3668e153a35d2a9455239b204c66c4a992e462f0944749cb73e66f4bc458691ba474a1c83f0e8b55ae16770b36eaa48bbe176183adcfe20e8bcf46281cdf0e238f909aa0fa772f09203e02c874371e96336b433879ae649bb57c2567edcdd2c102d81bc0dff9864550f083ba465aadd93532808ec4a9b8cc1360ea4e3c770f61c25ef4c044", 0x182)
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r2 = geteuid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, r2, 0x0, 0x0, 0x0, 0xb2}})
seteuid(r2)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000001080)=[{0xe6c, 0x0, 0x0, 0x800}, {0xc, 0xff, 0x0, 0xffffffff}, {0x3, 0x1, 0x0, 0xfffffff8}]})
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000080)=[{0x3}, {0x54}, {0x40e}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
openat$tty(0xffffffffffffff9c, 0x0, 0x80, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000240)={0x0, 0x5})
r4 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)


munmap(&(0x7f0000001000/0x2000)=nil, 0x2000)
sysctl$hw(&(0x7f0000000000)={0x6, 0x18}, 0x2, 0x0, 0x0, &(0x7f00000010c0)="77099b75", 0x4)


socketpair$unix(0x1, 0x0, 0x0, 0x0)
ioctl$WSDISPLAYIO_GMODE(0xffffffffffffff9c, 0x4004574b, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000180)=[{0xc0, 0x0, 0x8d}, {0x3c}, {0x810e, 0x0, 0xff}]})
syz_emit_ethernet(0x26, &(0x7f00000002c0)=ANY=[])


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, &(0x7f00000001c0))
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
getrlimit(0x5, &(0x7f0000000180))
close(r0)
syz_open_pts()
ioctl$TIOCSETAW(0xffffffffffffffff, 0x802c7415, 0x0)
readv(0xffffffffffffffff, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r1 = socket(0x18, 0x1, 0x0)
r2 = socket(0x18, 0x1, 0x0)
r3 = socket(0x18, 0x3, 0x0)
ioctl$FIONBIO(r2, 0x8004667e, &(0x7f0000000080)=0x1)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r3, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
dup2(r2, r1)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


setrlimit(0x3, &(0x7f0000000000)={0x7fff, 0x100000})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x0, 0x2}]})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000000c0), &(0x7f0000000240)=0x5d)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x37}, 0x4, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3, 0x0, 0x2e)


r0 = socket(0x11, 0x3, 0x0)
shutdown(r0, 0x0)
sendto$unix(r0, &(0x7f00000004c0)="b1000504000004000000000007000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000022acf2047804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0e032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221505f4fcf668246c0900e1937c727a4bdb8d000008e371a3fc81000000", 0xb1, 0x0, 0x0, 0x0)


mknod(&(0x7f0000000280)='./bus\x00', 0x6000, 0x6d4)
open(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)


pipe(&(0x7f0000000100)={<r0=>0xffffffffffffffff})
select(0x40, &(0x7f0000000100), &(0x7f00000024c0)={0x1ff}, 0x0, 0x0)
open$dir(&(0x7f0000000000)='./file0\x00', 0x200, 0x0)
r1 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
pwritev(r1, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
r2 = socket$inet(0x2, 0x3, 0x0)
r3 = open$dir(&(0x7f0000000580)='./file0\x00', 0x40000400001803c1, 0x0)
ftruncate(r3, 0x80002)
recvmsg(r2, 0x0, 0x0)
readv(r2, 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, 0xffffffffffffffff, 0x0)
execve(0x0, 0x0, 0x0)
openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
close(r0)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b100050300000400000000000101000000000000cea50500fe0900c0cf2fd3357ae30266060000be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3eea3c57699a6443a42102000000720fd18b08fbb670c1f5a872c881ea6e2ec5e3c6471887247bbaa3a53426d93c0000008000361b1257aea8c500002002fbfe0c2300008abfba0900000008e371a3f8343732051eeab71d89e0000405f8ffffff130000000100"/177, 0xb1, 0x0, 0x0, 0x0)


r0 = dup(0xffffffffffffffff)
ioctl$WSMUXIO_INJECTEVENT(r0, 0x80185760, &(0x7f0000000000)={0x7fff, 0x4, {0xfffffffffffffffb, 0x797}})
ioctl$WSKBDIO_SETMODE(r0, 0x80045713, &(0x7f0000000040))
read(r0, &(0x7f0000000080)=""/101, 0x65)
mmap(&(0x7f0000ffd000/0x2000)=nil, 0x2000, 0x0, 0x12, r0, 0x928)
ioctl$VNDIOCGET(r0, 0xc4104603, &(0x7f0000000100)={'./file0\x00', 0x100, 0x8, 0x9d})
syz_emit_ethernet(0x136, &(0x7f0000000540)={@empty, @broadcast, [], {@ipv6={0x86dd, {0x1, 0x6, "07ea80", 0x100, 0x11, 0xfd, @mcast1, @loopback, {[@dstopts={0x1d, 0x3, '\x00', [@jumbo={0xc2, 0x4, 0x81}, @ra={0x5, 0x2, 0x1000}, @padn={0x1, 0x6, [0x0, 0x0, 0x0, 0x0, 0x0, 0x0]}, @padn={0x1, 0x4, [0x0, 0x0, 0x0, 0x0]}, @pad1]}, @fragment={0xc, 0x0, 0x8, 0x0, 0x0, 0x11, 0x64}, @routing={0x3a, 0x12, 0x0, 0x3b, 0x0, [@mcast2, @loopback, @loopback, @ipv4, @ipv4={'\x00', '\xff\xff', @rand_addr=0x80000001}, @ipv4={'\x00', '\xff\xff', @multicast1}, @empty, @remote={0xfe, 0x80, '\x00', 0x0}, @ipv4={'\x00', '\xff\xff', @remote={0xac, 0x14, 0x0}}]}, @routing={0x27, 0x2, 0x0, 0x0, 0x0, [@ipv4]}, @dstopts={0x29, 0x1, '\x00', [@ra={0x5, 0x2, 0x95}, @jumbo={0xc2, 0x4, 0x6}, @padn={0x1, 0x1, [0x0]}]}, @fragment={0x88, 0x0, 0x3f, 0x1, 0x0, 0x7, 0x68}]}}}}})
r1 = openat$pf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
fcntl$getown(0xffffffffffffffff, 0x5)
getuid()
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
geteuid()
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f0000000c80), 0xc)
sendmsg$unix(r1, 0x0, 0x0)
ioctl$LIOCSFD(0xffffffffffffffff, 0x80046c7f, 0x0)
fcntl$getown(0xffffffffffffffff, 0x5)
lstat(&(0x7f0000000d80)='./file0\x00', &(0x7f0000000dc0))
semget(0x0, 0x2, 0x41)
readv(r0, &(0x7f00000020c0)=[{0x0}, {&(0x7f0000000e80)=""/55, 0x37}, {&(0x7f0000000ec0)=""/251, 0xfb}, {&(0x7f0000000fc0)=""/245, 0xf5}, {&(0x7f00000010c0)=""/4096, 0x1000}], 0x5)
semget(0x2, 0x0, 0x0)
syz_open_pts()
minherit(&(0x7f0000ffd000/0x3000)=nil, 0x3000, 0x3)
r2 = msgget$private(0x0, 0x602)
msgctl$IPC_STAT(r2, 0x2, &(0x7f0000002140)=""/160)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000100)=[{0x20}, {0x2}, {0x6}]})
sysctl$hw(&(0x7f0000000000)={0x6, 0x11}, 0x2, 0x0, 0x0, &(0x7f0000000240), 0x0)
mprotect(&(0x7f00003fe000/0xc00000)=nil, 0xc00000, 0x0)
socketpair(0x18, 0x0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x802, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000080)=[{0x45}, {0x20}, {0x6, 0x0, 0x0, 0xfffbfffe}]})
write(r1, &(0x7f0000000000)="76a5dead0f01f8607d2100000063", 0xe)
socket$inet(0x2, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
pipe2(&(0x7f00000001c0), 0x10000)
mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x0)
mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0\x00', &(0x7f0000001380)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
open(&(0x7f0000000040)='./file0\x00', 0x1, 0x0)
rename(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000480)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
r2 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000040)='./file0\x00', r2, &(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f0000000000)='./file0\x00', r2, &(0x7f0000000200)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
unlink(&(0x7f0000000700)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


setrlimit(0x0, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$FIOASYNC(r0, 0x40047463, 0x0)


mkdirat(0xffffffffffffff9c, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000001240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlink(&(0x7f0000000ac0)='./file0\x00', &(0x7f0000000e40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000f40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000001140)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000240)='./file2\x00')
symlink(&(0x7f0000001340)='./file0\x00', &(0x7f0000001440)='./file0\x00')


pread(0xffffffffffffffff, &(0x7f0000000140)="6f61b7ef7ead776902483d35659a64e88dae40c40c02e5d54f4624bbd9117c6be4368741a4877bcf6f8f75aced9c0f9928aeeaab48b7d8b3e210f9f9e361544e9c3544e17a60fa470d190ab042e4af4fc6c09af967c10177d0e86ede02532f8cfe92b5eaa3c369b66d7aac10d1197c7dcc98f32962c28b9d649ee93656f091e93987144332e847063919a16cedf0960cebbd1f5992f00b0a69c4a9191a3a00b2e791a5ff29b25747ad4358bd9d14ebb68e16fd204e3539383b3b6d1df08b7a33b560dce269f65e50753a", 0xfffffffffffffce5, 0x125)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = syz_open_pts()
ioctl$TIOCMBIS(r1, 0x8004746c, &(0x7f0000000000)=0x187)
r2 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x10, 0x0)
ioctl$BIOCGBLEN(r2, 0x40044266, &(0x7f0000000080))
pipe2(&(0x7f00000000c0)={<r3=>0xffffffffffffffff, <r4=>0xffffffffffffffff}, 0x10000)
ioctl$TIOCCLRVERAUTH(r4, 0x2000741d)
r5 = openat$zero(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$TIOCSTOP(0xffffffffffffffff, 0x2000746f)
ioctl$TIOCGETD(0xffffffffffffffff, 0x4004741a, 0x0)
faccessat(0xffffffffffffffff, 0x0, 0x80, 0x2)
getsockopt$SO_PEERCRED(r4, 0xffff, 0x1022, &(0x7f0000001400)={0x0, <r6=>0x0, <r7=>0x0}, 0xc)
getegid()
sendmsg$unix(r0, &(0x7f0000001480)={&(0x7f0000000200)=@file={0x1, './file0/file0\x00'}, 0x10, &(0x7f00000013c0)=[{&(0x7f0000002d40)="c970d86ee917ae98c433c0c4f3c0ddfceae3b0abc8bc37b80b78b0d7666b43a9a64a6ebc10a534f4618d7b6cfced10197c89297da63ae19af3eb2e21d464e609d27a0d9d02752f5cc5fa66cfd952dfb2bee732cac4a8162e32e909359faceb16e90827f22c1734d02367ecd87cf552ffa6cde3266821b799270a919449f907b43bec1af1c88651a8965431189fa6", 0x8e}, {&(0x7f0000000300)="4742b261f15e771468bd4cde6458a2e7c543c3869a8cafa46d371397e445cf90f77cc174d7c45b429926afaade810c56cfbceb4ad9a683d4f576628f53a29521f52368b289b4891b1797c02c8fc3a82fdf9c56372a84bedd625b93694755d28bd35a", 0x62}, {&(0x7f0000000380)="ccf79a75fb275a80747e1f0682aa8393e8377ebae46f7fa5fdb8c37e8c37a1ab80fe49757327a584b1cbe1e15ee341346008bc40414868642a3ea1d82c5382d040c0f7980e04e1cd5654b6a13be01fc507779c6cb37a0f8a9c6f70d982558d2478b669fb36328d4c6b192d5a51a5d0e88187a71ed31996b8436de6650911331aab1cb50a406825622b0be76a39b61885f12409b7641d6495e8eed4579431d1e33aa2a00c3d7f8530e0d9c1f6c3302508461c3fa4975c98e8284dffeccfd775f6e44701317b357682dd370c67e963d726c4639fccf071c49d3bd32e0022d8efbc7e9edab02299f25b55762b38f4d0f3f9428a9e5320db34b3613b9cf142e12ec7a067afdecb963f1dcdb278d6bfffb3ab2ceb920be828becf28fcb2afb23bbec1b4e370b834b82f6982f194cc84777530671af2bb78ff4c1853e221507a5f7dac83264ba7ef9fc15b9a8119778cf9cabd2bcf219bc459ada5c16e26252a700630148740799f5c541e1866df49486b6c3cbd3ce92abf29f36a4956fcdd06196208a08cff57f53a85da62e9b7542219b7670e0caa30773c56357ca89410e8e0f0fa20e41038d839824a9fba68e1f597a60040009d07dc17d264e29ec0f3c087d83c37790649d9370984fe115527dffbefaac707aeee09f82bc8818304ef8e51858fc0ec6d3160396bcb5176c049f2eb5f416414f20bc9c13f3e5cb8bd6deb55c2527156f25b9fff3f8c554901e0b5c87cbb7645d5e6f1637a85ec5ea9f59834d777076f85b8bb920740db7fcc6f9bfd15644489d8e61ac40cd2ffa4e6b73536002aba82328a7ca48e10c082c2bda6b289026b6188a73a58e6172d2555736eafbb96b5c5451dc31eda2123e074a8d0ae04ee68934224e81e0251d6dce46b81e917ec3a06b25d5164ada4362a385bc0474dc2105dcc409f5e9fb01803c2e4a8a4eaf72705a5b935580aac8a3249cff107a5f872bd50c3b3e8c31eba0f94eb3783bb1eb6aafbd33a69643e7d0ff91199916f59c4de97da6270f04cf1e4775f3912159ac67c11ee562f5a56d368ee3ea6a7d776b4c9a4d24ec5cf54ba26ce557ac3cf99e30521308a4ef21f171dae809e105d096eb0fb8ab837e768da5536d0b82bbf60027876501c68e558bdf9c592586f5a9cdaa73b752a7f2f42140a7fee488bb993031e3afb7f0d2061492bdcda88293042b558d55365b158f04c5c74049fd5792a691b3f543e7a76b4c9a6fc1473225be78248d02e4681ed021dd69027e48e6fb8d2d84b77dd188884436ba869e2f71a7e072dc12a5c9e7d0187577bb3bb3ef4d1e95c04bbe061b93931317a4edd736215c649a16912e2fdcb1ab0587340f738ba80b236f0200707dc849959dc57a3bf795ba0d4bbfd2dd3ad957aedff2afb9910e6c3358d15e84a5236a9399979f07a24a770ad892bac65d7fe6879d61e97a1f85ac4027c0cd1106e0e2308c4ed20c40f99810cfd475db2d5bed8116f08774d948275fad4c2c2bce67a2f7c15cba7d58668b0668048473166dbc1e953e4deff1a8948d99caf964b81b9d55371daa7cc1ea8f62a03bdbf4b7d190699c82f4a7ba199a8b47452a43eae3a4d3d2acd1b90f0703f0231b8b8ff6312739b94494b99635708008bc04ec2c982e9462b25f9f3b441abbf663be9eb88292922de9fe321d40039b73ecfebaf3d834914226545405f3271033f14c678e65f86a5e9fe980a18db0c676487ec0421ac8f59292145e6a04dc2d71f0f2259deb86905dac56e90fa7f0dfd2620abd20ad8cdd5ae4778bea96eb204d5ebb4986355f88de23e64e7a12a4c29e3e13559ef0948386adec48f13b5ab88b565cfefca7ea20e3f47a93e7bba94554767ac9b2fe4b8eaab0078d1117219505c45b20eadcbf18fb527e1429b037a9ebdb0a39e05cfca008ffbbc54b3e42d1b28617eea05a8882bce35a940b023c926b552afdf629bc78737d88c53ea5294326dac390d1803701ef5558c7c9368e68f1e999e11bc5cd706f404a3e7740a927d2b0bf091d7d402d88eb6de8df6d27ba63e735c4a34b30503aa07d026d62cd68c1cef27dbfb9af84db4f7de6faa7a71c641b98a7a428c5b9b180b59808d60ab3aade675ef22f83cb63db891fdb9799939b53798a79c4961d2e8d1dfed9727413759c59dac5a61548090ec3b49a705726ee436a4edc994d0466b55a17aaeebcbb53cc6de0174a062bb7962167e0fc6eb9ba8bd6cab7464d77e66e30622991b8e5052753b5a30aad2b814a79988b8d5a8a665458f044457048b08a5a106e90cb103c96a157a9d6d48a01f269cb4af77e7aa27f972ecf928b04c18eef9b9d93130c66e1205859d3bac368faf2621d5604c69f52f692087487f85ea9d2a13e443cf67d866cb05ec7e462bebd203be70bce32f2dc156724aac2874b23583fc35ecfc7f64fdbed9643b4ccd33f58272bf7ee14bdfc12dd51549d8221bcf88cfdfe97ca37ffab9ed8cb628f0e463a5bcd7956137fbfba83f720c3e68dc37ab453f6438ff759e2220d0c56b3f72cbf3b4eed1de7f074574db30a37676e5d62d9b7b1909b182aaaf8b4d503aba440360ba55ba52303d29caffad03f98cddbe49b7cbd29d0aabcb164a64de6ab144d47300a2a718b470fe474532fd7f80ff8d6542f66bd97e911addf35a3ce5e7ca6c8d4330353694e4ffc30484e5a6b37ee3b6af695aff9c0ff6e93c6b9b37f093c12d74736e86772d1aae35695625583708813794efb0a9afa73e16eb78d735adcbdfc6165fe28d177c05d0d4b67fd626a726b6a39ed80b90acab5c1ad3d7f6a95c753320fe13b1d214dc21742cc284a6c0496cc554b14ef719ce45d98668cd77a74c1b38c6799b3c1d0b764a64bd1cf4884b19c76a138c42ec8c7f1374e4cc1fbac5a218bb0b7673d1e957d3d6c9164643f1cae0c45efa6f2f20707529f12a6ec445d716ede04b6b0d25f218a8eb52c69e84ed1a00f5ff16b318ecf7eaba37446fbc0230640b52424373b394c5b1528324c20b28e3df72790eaba1a6877e106d3bd60c4869d9beb53607a7882b83503d6ce63b2ffceb735bc30037a4e7a020169562c67654f6a85a7ca25da1421a9dd39ae3c78f01bfd9ec6874dedf3c0e3affd091390c3c9616ee3fac826ef004dfdb4fd1c8d2c862acf72cf6a23e1d579efdc35bd52e8a48ff040298a485cb1fefe4a2154f6450c581c4d7997a5c21635233cde11fcc11bea67e6039558d580b526ba1bb305f082e52020822f8f5908fa8eef747bcd6aa99404e995ed72c3be89701a2b7fb8f153b6f7432ab4e921fa4fc0bc9b6b148c2103dbc9c0536ba4e4b0cfaf79325c193905f4624fab1a84099d0b66b5b5b837b38f0fbbff28af83553966ff0b5fc67686481f165634379ff04241d77d8b0dc0663e6b7eeeadb451cfd63e69ad65126521b5c6964c155f7c2e6c8549d263bf6812c289c25c2ae3b9d737edf604d2e98135fa17471c7063c0bf45f72479b856ea7b630d734ada7dc5fbd0dc7641388a4e6bb2730cc3207bf53d7cf4c689302fe095d47abbb317b87e4d1d682b373c4302d2757f6ed3f0340bdbbb3b1121788beebc7f29c720c03d182799a5bb504750e7dbb6d4ebc7724ce658eb91d4a67d28f429546ce07d8f7af7467b64f15aeea5aaeb62aecfaf679aa033192f477d5d7f9a2c70d8351531f7a55a44bbc55367b05fa1107568ae2debc221bc3b44612cceb3a2fcd7c529a4415655c8d58028522c696087adc883e06ffdd0272513492cdb772dfd752dbbc361a43164b670f41b9753b01d215d85e600536466c272c72ed3e069d86698e57d9fde315ac66d88b403ceb8142dcb512ba98f5d5b7ed9b627e93a466a1e4e7245bcbed5d77843552c3694d1a303e83d6542e5a6f2a499d715bf17ea5705d3873ba3342a4153b33a4c3fee97cb80aabf3d5622805e76ce579e91926d681d4984be1465b5a8f4e95d9a6897ec4b45b1150eb3fdfbc786aecee11b2a494aaacfb3fe614d3446909ef133a9af2ee8c72c5aa161407136479aaebdc75a2adbb2c859f7b44caf3163409c73a28bf248be41cccb041dda8d7189e74038dc4a18f688fe07036c87487656f7672d41a8d31d59f4b8fd5a50e4b85a0bf5bcd5fd756143b606b42e7750415092f22e3f2e1540afd294f56be3f22141ec0897b8578bd6f1a0e18ae50434063bb513380cf65e4ab633f001997b3cb18c2340ebc74dc7d01ce3f0af0eb8c44a8a297c9e6f7255806482b9e5bd0127bee5ce52fc9cc34d11e285e1b702cbe56c51fef97ae0dda0fd51f8d6a7c190bf8b2616f9a442b1218ddcd592e73d6a7e447b91312fc78c84af29b9f88ec3abbcdd6e91a484e40ae9ce809b92d4afced83dd7e7493f86dccc576de02fe39eca291d29df21244f7399a47a44132fbe5dd9618ec6f1b0a9cfaa4a96c89df38ff7ea4284c918625f0b1c1fef11f9d32ba78038d1d1482804831f04be0b4afd5c58292d1cd4206b469605b39ad96fa043c5b5d61338a190a8489c3510ab40a6f7379697cebe029c5aa0065a65d1da3a4fa09fc774b99c6848d8dcf4751f9cb3ac914f88776873d6eb09ce23645a8556676240cce9de5fba4c5efb90640d53ee8f35edd793b704f3cc6cf7833c27f45e1711c7a8a30165b6aca9f4aa97d886352b798e682370d2d9e4b94449d2cf88b4d91c672d13ea2ab86c66deecdf088f224488e9580aa37a6b66319ac3217f66b754ab23f0228ac84966970ed1fbe5de888ba2736214ed966119edd2afde9993641dd01dec47660f1fcc0af43463b7aa45b01cd497b92d58842e01dce3cf44dd03b938ecc3902f21b04e9a40dd24fdd5f7def33e3ef7b2fc72715f2deeb8ac6c8821a2e8b82e508dcf9a2f5d321e4c4ab0117a0d5084c0fffbcb83fb649f086f8d5628aae73432509e8e936e482720e5e814dd2219beb4e268a251cf65f28c13093af507968fee85b57fbe2718181d57dfa74c2a9ac8df9b25b7c1c04f566ac17265ef774e6a95d53421e1bd9765d11d504219331984bb992e0e3870e65b89636b495f8fba1d46b8efc03303fa7dd2c1222015dde34064c5f2063446fbd0dfb78deb08d363818741e9ddcbc1ff55db5513b88c6a19ce8587651ca3a8e167edace144611ec5610e68773ecadb2498b54154f4cd6b4403311a51c0fd98d10a069ed7a02e515038ea4d2010a2a1069dc7c3a0af66165b5544a415bb2868d168c7c285b6a731161630f2734f4da69bdee8900b425ab002874f84cd3323c3d776217c091dfadb9c27868199cb75ce823d3cfbff85307b3fa04ca4bf99aab34d6a1104119fa505f3faf6ecf6ebc1568d613d797f516412246aa049cc4b8561c1f187cd9b956d223dd37a70336e53f6d0ea9711b8ba0c7735fc7d222fe4283c1379301b6d00e1d0a7c31113e1f6eb2cf605e84d000c98e7f712812d93e99e5668550339388470e2b7c1901f124101d4ab0934ce36c3d8e0671a867b0e56d54efe274a396c2570251d1b243c240f015e40c9fe22c85ad2c9424633e84d307304bdf4217a2a615bfa7f2e2df986c8afea77d98928e36089866bf3b345b361ab75d276047f284bd35638d62d9e1aacc9fa54c737404e283a094603ac921c6121fd7535624cbdeb6036f778966f40d82768278f10672c15e29284b9801aafab98599dd70a30b52871f41b6ed20ce359da77e83b3018d314ddd3fdb6e7796e4619b01f39ddc59b123a1c3084f86fd3fba8b7800e3c37ef05a2cdb70ed3763bb769b895d94a2467d154e3ab785d0bb0c3527053445f28303a330b9", 0xffb}, {&(0x7f0000001380)}], 0x4, &(0x7f0000001440), 0x0, 0x402}, 0x5)
fcntl$getflags(r3, 0x1)
openat(r4, &(0x7f00000014c0)='./file0\x00', 0x2, 0x8)
ioctl$BIOCLOCK(r4, 0x20004276)
chown(&(0x7f0000001500)='./file0\x00', r6, r7)
open$dir(&(0x7f0000001540)='./file0\x00', 0x1, 0x1c8)
ioctl$WSDISPLAYIO_LDFONT(r5, 0x8058574d, &(0x7f0000001580)={'./file0\x00', 0xc, 0x3, 0x9, 0x0, 0x6a2, 0x6805, 0x6, 0x1, 0x2, 0x3a8b, 0x5})
r8 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r8, 0x8080691a, &(0x7f0000000100))


syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaaaabb86dd605d34520030000000000000000000000000000000000000000000009f0500040000000000000001010090780000000060397772"])
writev(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe2c63a56077123a276d3ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')
syz_open_pts()


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x1, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x0)
setsockopt(r1, 0x1000000029, 0x1a, &(0x7f0000000000)="5ab777a5", 0x4)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r0, &(0x7f0000000180)="249f", 0x2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x40, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, 0x0)
syz_emit_ethernet(0x17a, 0x0)
socket(0x11, 0x3, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x1, 0x0)
socket(0x2, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x8020690c, 0x0)
syz_emit_ethernet(0x126f, &(0x7f00000000c0)=ANY=[@ANYBLOB="aaaaaaaaaaaa00000000000086dd609ded1a12390000c4a4e3434e58d025a6a8a81cf312b8befe8000000000000000000000000000aa00030000000000000101000101000401000401000103000000000100010200000000c7ab6f1eba08bf03d1805fce0ef2ab82f4a065245eccda108bec7cb23f632c993265a4cefeb77b1406d562a47d4b0054943553278b519ed107f62b5c352f8e68d83c1fd85b8e1083556d7fa2fc09a3e823fa940de6ef1b18ddb2a2dba0d2d9c1b44b20ed3a932a2c47f4f4d3e34ea1b67a607001a4541a87d5d347b5049b3444dc2b7abe3499079a5701e88493acb2eb1808e8b1f74311083f93341607915aa46325934e81b672d809cb6bc5f3d64480ba4db4432a67c2548e259fe7831f7c6dfe"])
sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f00000001c0)="55f8f5782087a072a82ec35f78d14780f518", 0x12)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc1206949, &(0x7f00000001c0))


socket(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r0, 0xc018696c, &(0x7f00000001c0))
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x3})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbdf13b9fd812eaa4e713048e69931929648", 0x14)
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0x8020699f, &(0x7f00000001c0))
getdents(0xffffffffffffffff, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)='\t\x00\x00\x00', 0x4)
r1 = dup(r0)
setsockopt(r1, 0x1000000000029, 0xd, &(0x7f0000000000)="ffdaff10aac6a28ac93e2eddc45c8454e486f64c", 0x14)


open(&(0x7f0000000280)='./file0\x00', 0x0, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
r2 = dup(r1)
recvmmsg(r2, &(0x7f0000000440)={&(0x7f00000000c0)={0x0, 0x0, &(0x7f0000000580)=[{0x0}, {0x0}, {&(0x7f0000000240)=""/90, 0x5a}], 0x3, 0x0}}, 0x10, 0x64, 0x0)
dup2(r0, r1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
writev(r1, &(0x7f0000000640)=[{&(0x7f0000000140)}], 0x1)


r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000440), 0x1, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000680)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
bind(r1, &(0x7f00000002c0), 0xa)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0115, './file0\x00'}, 0xa)
mkdir(&(0x7f0000000640)='./file0\x00', 0x0)
chmod(&(0x7f00000000c0)='./file0\x00', 0x21e)
chdir(&(0x7f0000000140)='./file0\x00')
symlink(&(0x7f0000000200)='./file2\x00', &(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
r2 = open(&(0x7f0000000180)='./file0\x00', 0x6d84b028b6b26ff2, 0x0)
r3 = semget$private(0x0, 0x7, 0x3c0)
semop(r3, &(0x7f0000000080), 0x0)
rename(&(0x7f0000000540)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000080)='./file0\x00')
semctl$GETPID(r3, 0x3, 0x4, 0x0)
semop(0x0, 0x0, 0x0)
semop(r3, &(0x7f00000002c0)=[{0x4, 0x0, 0x1000}, {0x0, 0x420}, {0x1, 0x2}, {0x0, 0x3, 0x800}, {0x2, 0x204}, {0x0, 0x4}, {0x3, 0xfff8}, {0x2, 0x9}, {0x4, 0x1, 0x1000}, {0x2, 0x7e7}], 0xa)
r4 = socket(0x18, 0x2, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000000029, 0xa, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
setsockopt(r4, 0x1000000000029, 0xa, &(0x7f0000000c40), 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000002540)={0x0, 0x0, 0x0}, 0x0)
r5 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000140), 0x1, 0x0)
ioctl$WSKBDIO_GETMAP(r5, 0x8010570e, &(0x7f00000001c0)={0x0, 0x0})
semop(r3, &(0x7f0000000100)=[{0x3, 0x801}, {0x2, 0x8}, {0x4, 0x4, 0x1800}, {0x3, 0x101}, {0x2, 0x3fd, 0x1800}, {0x0, 0xecb}], 0x6)
semctl$IPC_RMID(r3, 0x0, 0x0)
r6 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r6, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETF(r6, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000000)=[{0x50}, {0x45}, {0xe6, 0x2}]})
syz_emit_ethernet(0x138, &(0x7f0000000740)=ANY=[@ANYRESOCT=r3, @ANYRESOCT=r5, @ANYRES8=r2, @ANYRESHEX=r3, @ANYRES32=r0, @ANYRES32=r4])
chmod(&(0x7f0000000440)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2)
getuid()
getpeername(r1, 0x0, &(0x7f0000000300))


listen(0xffffffffffffffff, 0x0)
setregid(0x0, 0x0)
socket$unix(0x1, 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f0000000000)=@file={0x0, './file0\x00'}, 0xa)
chmod(0x0, 0x0)
chdir(0x0)
r0 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000100)=0x200000, 0x4)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
socket(0x1, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
getsockopt$sock_int(r1, 0xffff, 0x1, &(0x7f0000000100), &(0x7f0000000140)=0x4)
setsockopt$sock_int(r1, 0xffff, 0x1, &(0x7f0000000180), 0x4)
socket$unix(0x1, 0x1, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x4, 0x0, 0x0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
openat(0xffffffffffffff9c, 0x0, 0x0, 0x0)
readlinkat(0xffffffffffffffff, 0x0, 0x0, 0x0)
r2 = semget(0x2, 0x1, 0x0)
semop(r2, 0x0, 0x0)
clock_settime(0x2, 0x0)
pipe2(&(0x7f0000000000), 0x8000)
msgget(0x0, 0x0)
getuid()
connect$unix(r0, &(0x7f0000000000), 0x10)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000000)=[{0x3}, {0x7}, {0x812e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])


r0 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000140), 0x1, 0x0)
fcntl$getown(r0, 0x4)


r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$PCIOCWRITE(r0, 0xc0107003, &(0x7f0000000040))
semop(0x0, &(0x7f0000000100)=[{}, {0x0, 0x2fe}], 0x2)
sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000000)="9b1809ffffffffffffff7f473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6fd74c94d1b44", &(0x7f0000000040)=0x10011, 0x0, 0x0)


syz_emit_ethernet(0x20, &(0x7f0000000480)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaaaaaa88e7"])
syz_emit_ethernet(0xe, &(0x7f0000000480)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f00000000c0)=[{0x54}, {0x7}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])


r0 = openat$diskmap(0xffffffffffffff9c, 0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
ioctl$DIOCMAP(r0, 0xc0106477, &(0x7f0000000200)={&(0x7f00000002c0)='./file0\x00'})
close(0xffffffffffffffff)
acct(&(0x7f0000000140)='./file0\x00')
sysctl$hw(&(0x7f0000000240)={0x6, 0x10}, 0x2, 0x0, 0x0, 0x0, 0x0)
socket(0x2, 0x1, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r1 = socket(0x0, 0x0, 0x0)
setsockopt(r1, 0x1000000000029, 0xb, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
r2 = socket(0x18, 0x1, 0x0)
dup2(r1, r2)
setsockopt(r2, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e71", 0xc)
openat$wsmouse(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, 0x0)
socket(0x0, 0x0, 0x0)
accept$inet6(0xffffffffffffffff, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
readv(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x32, 0x0)
minherit(&(0x7f0000800000/0x800000)=nil, 0x802000000000, 0x0)
setrlimit(0x0, 0x0)
close(0xffffffffffffffff)
syz_open_pts()
syz_emit_ethernet(0x36, &(0x7f00000000c0)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @empty, @rand_addr=0xac14ffff}, @tcp={{0x0, 0x3, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000240)={0x5, &(0x7f0000000280)=[{0x35, 0x0, 0x2, 0x283d000}, {}, {}, {0xc0}, {0xfffe}]})
writev(r0, &(0x7f0000000500)=[{&(0x7f0000000000)="af18a64591749e07ad1273f580a0", 0xe}], 0x1)


getsockopt$sock_cred(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f00000005c0)={0x0, <r0=>0x0, <r1=>0x0}, &(0x7f0000000600)=0xc)
r2 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7949)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000015c0)={<r3=>0xffffffffffffffff})
getsockopt$sock_cred(r3, 0xffff, 0x1022, &(0x7f0000000000)={0x0, 0x0, <r4=>0x0}, &(0x7f0000000040)=0xc)
fchown(r2, 0x0, r4)
pipe2(&(0x7f0000001dc0), 0x0)
accept$inet6(0xffffffffffffff9c, &(0x7f0000001e00), &(0x7f0000001e40)=0xc)
r5 = socket(0x18, 0x2, 0x0)
setsockopt(r5, 0x1000000000029, 0xb, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
getsockopt(r5, 0x29, 0x9, 0x0, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0xa, 0xffffffffffffffff)
fcntl$dupfd(0xffffffffffffff9c, 0xa, 0xffffffffffffff9c)
socketpair(0x20, 0x4, 0x1, &(0x7f0000001e80))
r6 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r6, &(0x7f0000000380)=@file={0xd1653077bafa0115, '\x00'}, 0x3)
r7 = socket(0x2, 0x1, 0x0)
setsockopt(r7, 0x6, 0x4, &(0x7f0000000000)="695cdd27", 0x4)
connect$unix(r7, &(0x7f0000000c80), 0x10)
connect$unix(r7, &(0x7f00000023c0), 0x10)
pipe2(&(0x7f0000001ec0), 0x0)
r8 = socket(0x2, 0x2, 0x0)
connect$unix(r8, &(0x7f00000002c0), 0x10)
r9 = socket$unix(0x1, 0x2, 0x0)
ioctl$FIONREAD(r9, 0x80206979, &(0x7f0000000000))
sendmsg$unix(0xffffffffffffffff, &(0x7f0000002040)={&(0x7f0000000740)=@abs={0x1, 0x0, 0x2}, 0x8, &(0x7f0000000c00)=[{&(0x7f0000000780)}, {&(0x7f00000007c0)="290c66692d492020ad2f884b9372474312cc21848f8393e643e2666275723b8baeb5a5aceca4963db6ed44952611eb2ebb00704df0ab86326e9ad355c39a881c1d40c8f16026360b524d0938153844c552b268ef3a7d48f195604667ffb1a88a5995ea1c698917fbc435c27e0923ca01d03ada4b10923ba5aa59087b31ef532f96e58011e0eccaeda7021042ddb7f33f7680e8861115d0695bffe0514126e15b8593e01331990df09d40c77845a50581bc64feecad", 0xb5}, {0x0}, {&(0x7f00000008c0)="0c34994d54697930731a459953ad5b637a01662a92169af8816a55c35d251677401357a190a4cd7a4fd7bbe06b3612f8b0685537f50f84e83c91d35783e988497b0a7440e310a5713da2f08ea337cbee9dbf5ca5b6692bb3dddc23997c96c7c097f4c274f355ecd63edbb64820f107a01484662a4347e1cf1ef27bf3cf4aecb5890f3ed17d88155c4791979f1da826380433b27517d5b1553a1f8bd2803b82dfc2c2f62e5ad5ff", 0xa7}, {&(0x7f0000000980)="a79d47773ecc4ae4c038de7b3956903fdfdbd828f88ab4d3a894e737532df75d22e01d11f28b1aa0ead26bd5c838beef9d83e75c29f26725f9a425d23a6bafd9e6d59bc66bb786d6a74febace84ac955fe2aee27820aeecfd3681c8d8c01f4bce19c24f4714d4a7742c4183466ebf67e4e0a8980b36c", 0x76}, {&(0x7f0000000a00)='o', 0x1}, {&(0x7f0000000a80)="869e4ca576390efb030fbca19e0f414ddb74518f417763c7ec1029976994334bd2ed3f394b37e6b55f7c683fc728683b988048457f969c6535e920636d39e3b1f41a4e71abd307c2a316ce2c95e2dd9e50b878a0c1a82b6ce5ddc3ae79af2dec9313d1f1e95d", 0x66}, {&(0x7f0000000b80)="d05b6c90e8472b9df1ff185eb7e31f015047b9ce22ed6f0dade73ed0c30d95f694fc164b09299af6ee351a07884adbca9d0cd52139fe43ca888551fb4c037ee3801b521d7dc7dc627f1c5bdd58f3016df6e2fef457d858dceefce8c24f43110cb9df0300a348e8dcc26400bf", 0x6c}], 0x8, &(0x7f0000001f00)=ANY=[@ANYBLOB, @ANYRES32, @ANYRES32=0xffffffffffffff9c, @ANYRES32, @ANYRES32, @ANYRES32, @ANYRES32, @ANYRES32, @ANYRES32, @ANYRES32, @ANYRES32, @ANYRES32, @ANYBLOB='\x00\x00 \x00'], 0xb0, 0x401}, 0x1)
getgroups(0x64, &(0x7f0000000700)=[r1, r1, 0x0, r1])
r10 = getuid()
semctl$IPC_SET(0xffffffffffffffff, 0x0, 0x1, &(0x7f0000000680)={{0xb17, r0, 0x0, r10, 0xffffffffffffffff, 0x2, 0x8}, 0xffffffffffffffff, 0x80000001, 0x100000000})
pledge(0x0, &(0x7f0000000000)='tty   \x00\x02\x00!\a\x9bp^|#\xcbhl\x97\xa3_\xbc\x04\x9d!\xd9\x9f\x9f\xb4\x96\x13\x12\xe0\r\xe7\xb9E\xdf\xae\x96\x01\x00\x91\x0e\x17\x95 \x00Mj\x84+\xf0B\xaaY\xe1Q<\x19\x9f\xf6Yf\x9au^\xa0\xc9j\xdd-I\x01R\x00wY\x1d\xd7\f>Y\x06\"\xad\xb6\x88_\xeb\at\x91\xd3\xbf\xea\xdd\xb9\xf7@mJ\x0f\x90\xb34\xc5\xa9e\xa9\xf6\x1b\x8e\x05\x86\x91I\x8fC}~K\xd97\xc8\xb9ul\xaeu\xad\x9b\xaf\x04\xc4\x03\"F\x8f\xd5\xde\r\x8d\xa1\x00\xcc\xd7\xb6\xe1\xeb\xc1>\xb9\x9eQg\xc00]\xe3\xcd\x95\x86\f\x1f\xbd\t\xc8 \v\xb0, \xee\xa4\xa6\xb9a4\xe0\xbf\xa0\x1es\x01\xd1\xd8\xd5\xb8=\xdbd\xf0?=<l\x8c\x01\xe3\x05$\x1c\x04B\xa2\xa4P\x04\xcf\x87\xaa\x96i4\x14{/\xe6\x87\xdd\x8f\bz9$\x10_\xd8E\x93\x8f\xf5\x8au\xab\xf9)\xf5\xa6\xc7\xc8\xed\xb9\x1f:\x03K\xa2q\xe1\xd5\xdbUshx\xbe\\\x19\xda\xf8\xeb_W\xbb7\x00G\xbb\x1f\xe3\xd58\xf4:)\x10|r\x1e\x06p>\x8af\nn\xd4<\x00\xec\xe4^\x00\x00\x00\xca\x90L\x98\xc9gty\xce\xab\xd2\xa1\x85E\x00\x00\xd5\xab\x83\xda?w\x83\xbc\xcf\xd20(L&b\xed\x8c\x1d\x1a\x9fd\x99H\x9e\x82\x10\xea\x05\xe8A\xe3{\x8dE\x97\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-#\x92\xc0\x8a}W~\xd3\xa7?%\x9a\x1a\xdaC?\xc4#\xaa\x80)44\xb7,>\xd2l\xaaTU\xe2\xf9\"?\xf3\xb1\xee;\x04\xa7hN\r\xe4J\x02}kF\xaf\xf4\xbc\x98kD\xd4\xbdQ7O\xc6\x16#\xd5~j\x1f\xce\x11\x85}\xaa\n#\xad%I\xe1I\xa7\xade$\xbd?\x84\xd1\x8f\xea\xac\x1c\xac\xe8\xbe\xa9+\xed\x97\x16#\xd5}EJ\xb6B\x82~.\x92\xe4l\x02o{3Oag\xc2\xd0\x85\x80E\xc2\x8bB\xe3\x8c\x8d\xdea\x1f\xff\x83Y\xb3m\x03Y\x93\xf63\xba5\x8fF-\a\xcd\xc0\xacF\xfd>\xa2\x97\x1e\x85v@k\"\xc3\x02\xd1\x92\xe8\xf9\xef\r\x99\xba\xe2\xcb\xbfX\xe6\xbb\xd7\x1fiC\x1e\x89ZK\xe9X\x82\xa5gou\x04\x18\x02\x84\xd7\xf7\x01\xdc\xc4\xac\x8a\xeb`\x1d\x18Y$1\xbc\x05S\xc1\x94\x121\xd8;\xb7\x12\xa0\x1a\x8c\xe9\xa5U\xa5\xfc}[\xcc\xedJ\xd8\xa9\xba\xff\xf1Hj\x15u-\xd4\x927|\x05\x91\xfcr4(~\x97*rj\f\xbc\xaf\xb1\xc6\xc0\t\x8e\x1f,\xbd\xe6\xc4\x8b\xa2_8\xd4G)\xa2\xac\xc99\xaa\xa0?\x12\'z')
pledge(0x0, &(0x7f0000000300)='tty   \x00\x02\x00!\a\x9bp^|#\xcbhl\x97\xa3_\xbc\x04\x9d!\xd9\x9f\x9f\xb4\x96\x13\x12\xe0\r\xe7\xb9E\xdf\xae\x96\x01\x00\x91\x0e\x17\x95 \x00Mj\x84+\xf0B\xaaY\xe1Q<\x19\x9f\xf6Yf\x9au^\xa0\xc9j\xdd-I\x01R\x00wY\x1d\xd7\f>Y\x06\"\xad\xb6\x88_\xeb\at\x91\xd3\xbf\xea\xdd\xb9\xf7@mJ\x0f\x90\xb34\xc5\xa9e\xa9\xf6\x1b\x8e\x05\x86\x91I\x8fC}~K\xd97\xc8\xb9ul\xaeu\xad\x9b\xaf\x04\xc4\x03\"F\x8f\xd5\xde\r\x8d\xa1\x00\xcc\xd7\xb6\xe1\xeb\xc1>\xb9\x9eQg\xc00]\xe3\xcd\x95\x86\f\x1f\xbd\t\xc8 \v\xb0, \xee\xa4\xa6\xb9a4\xe0\xbf\xa0\x1es\x01\xd1\xd8\xd5\xb8=\xdbd\xf0?=<l\x8c\x01\xe3\x05$\x1c\x04B\xa2\xa4P\x04\xcf\x87\xaa\x96i4\x14{/\xe6\x87\xdd\x8f\bz9$\x10_\xd8E\x93\x8f\xf5\x8au\xab\xf9)\xf5\xa6\xc7\xc8\xed\xb9\x1f:\x03K\xa2q\xe1\xd5\xdbUshx\xbe\\\x19\xda\xf8\xeb_W\xbb7\x00G\xbb\x1f\xe3\xd58\xf4:)\x10|r\x1e\x06p>\x8af\nn\xd4<\x00\xec\xe4^\x00\x00\x00\xca\x90L\x98\xc9gty\xce\xab\xd2\xa1\x85E\x00\x00\xd5\xab\x83\xda?w\x83\xbc\xcf\xd20(L&b\xed\x8c\x1d\x1a\x9fd\x99H\x9e\x82\x10\xea\x05\xe8A\xe3{\x8dE\x97\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-#\x92\xc0\x8a}W~\xd3\xa7?%\x9a\x1a\xdaC?\xc4#\xaa\x80)44\xb7,>\xd2l\xaaTU\xe2\xf9\"?\xf3\xb1\xee;\x04\xa7hN\r\xe4J\x02}kF\xaf\xf4\xbc\x98kD\xd4\xbdQ7O\xc6\x16#\xd5~j\x1f\xce\x11\x85}\xaa\n#\xad%I\xe1I\xa7\xade$\xbd?\x84\xd1\x8f\xea\xac\x1c\xac\xe8\xbe\xa9+\xed\x97\x16#\xd5}EJ\xb6B\x82~.\x92\xe4l\x02o{3Oag\xc2\xd0\x85\x80E\xc2\x8bB\xe3\x8c\x8d\xdea\x1f\xff\x83Y\xb3m\x03Y\x93\xf63\xba5\x8fF-\a\xcd\xc0\xacF\xfd>\xa2\x97\x1e\x85v@k\"\xc3\x02\xd1\x92\xe8\xf9\xef\r\x99\xba\xe2\xcb\xbfX\xe6\xbb\xd7\x1fiC\x1e\x89ZK\xe9X\x82\xa5gou\x04\x18\x02\x84\xd7\xf7\x01\xdc\xc4\xac\x8a\xeb`\x1d\x18Y$1\xbc\x05S\xc1\x94\x121\xd8;\xb7\x12\xa0\x1a\x8c\xe9\xa5U\xa5\xfc}[\xcc\xedJ\xd8\xa9\xba\xff\xf1Hj\x15u-\xd4\x927|\x05\x91\xfcr4(~\x97*rj\f\xbc\xaf\xb1\xc6\xc0\t\x8e\x1f,\xbd\xe6\xc4\x8b\xa2_8\xd4G)\xa2\xac\xc99\xaa\xa0?\x12\'z')


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{0x14}, {0x3}, {0x16}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f0000000240)=ANY=[])


sysctl$kern(0x0, 0x0, &(0x7f0000000180)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b10689ca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d12727b1e1d0cc45c7ebd5df53fb588fd0245528fe5700a5868eaf74d373197fb657a56e99cdbddbb382ad676b756d4e", 0x0, 0x0, 0x0)
r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
r1 = dup(r0)
pwritev(r1, &(0x7f0000000140)=[{&(0x7f0000000580)="c6302c9c455c7be3d8598d3ac53af8", 0xf}], 0x1, 0x400)
writev(r1, &(0x7f0000000540)=[{&(0x7f0000000240)='<', 0x32}, {0x0}], 0x2)
execve(0x0, 0x0, 0x0)


sysctl$net_inet6_ip6(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x0, 0x0})
openat$speaker(0xffffffffffffff9c, 0x0, 0x2, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
msgsnd(0x0, &(0x7f0000000140)=ANY=[@ANYBLOB], 0x401, 0x0)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
mkdir(&(0x7f0000000040)='./file0\x00', 0x0)
mkdir(&(0x7f0000000240)='./file0/file1\x00', 0x0)
unveil(&(0x7f0000000000)='./file0\x00', &(0x7f00000001c0)='x\x00')
unveil(&(0x7f0000000340)='./file1\x00', &(0x7f0000000380)='r\x00')
unveil(&(0x7f0000000080)='./file0/file1\x00', &(0x7f00000000c0)='r\x00')
unveil(&(0x7f0000000200)='./file0/file1\x00', &(0x7f0000000280)='x\x00')
ioctl$VMM_IOC_TERM(r1, 0x80045604, &(0x7f00000002c0)={0x7})
bind$unix(0xffffffffffffffff, 0x0, 0xa)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
connect$inet(0xffffffffffffffff, 0x0, 0x0)
getppid()
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
chown(0x0, 0x0, 0x0)
getuid()
openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
socket(0xc, 0x4000, 0x0)


mknod(&(0x7f00000000c0)='./file0\x00', 0x2, 0xffff8000)
ktrace(&(0x7f0000000080)='./file0\x00', 0x0, 0x0, 0x0)
semop(0x0, &(0x7f0000000000)=[{0x2, 0x6, 0x1000}, {0x4, 0xfff}, {0x4, 0x9, 0x1000}, {0x2, 0x3, 0x1800}, {0x3, 0x8000}], 0x5)
r0 = socket(0x18, 0x400000002, 0x0)
mkdir(&(0x7f0000000000)='./file1\x00', 0x0)
setreuid(0x0, 0xee01)
chflags(&(0x7f0000000040)='./file1\x00', 0x0)
setsockopt(r0, 0x1000000029, 0x2e, 0x0, 0x0)
r1 = semget$private(0x0, 0x4, 0x83)
semop(r1, &(0x7f0000000340)=[{0x0, 0x7}, {0x0, 0x8, 0x800}], 0x2)
semctl$GETALL(r1, 0x0, 0x6, &(0x7f0000000040)=""/243)
getsockopt(r0, 0x29, 0x31, 0x0, 0x0)
utimensat(0xffffffffffffffff, 0x0, &(0x7f0000000180)={{}, {0x0, 0xffffffffffffffff}}, 0x1)


sysctl$net_inet_gre(&(0x7f0000000000)={0x4, 0x2, 0x2f, 0x1}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000440)={0x6, 0x18}, 0x4, &(0x7f0000000480), 0x0, 0x0, 0x0)
socket$inet(0x2, 0x2, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
r2 = dup2(r0, r1)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000001c0)=[{0x84}, {0x1}, {0x8106}]})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(0xffffffffffffffff, 0x8020699d, &(0x7f00000001c0))
sysctl$vfs_ffs(&(0x7f0000000000)={0x4, 0x1, 0x1}, 0x4, 0x0, 0x0, 0x0, 0x62)
setsockopt(0xffffffffffffffff, 0x1000000029, 0x28, &(0x7f0000000000)="5ab7776a", 0x4)
syz_emit_ethernet(0xba, &(0x7f0000000080)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaabb86dd600000000084000080000000000000000000000000000000ff020000000000000000000000000001"])


open(&(0x7f0000000280)='./file0\x00', 0x615, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
r0 = syz_open_pts()
writev(r0, &(0x7f0000000300)=[{&(0x7f0000000180)="98d926cc1c68bcafda73d24239c0ec64cb0f13f5df63fa33a13c37427233489492cb7aa9893eb485b2422794d5a835bd5ea43cc591eb21d9b52584162d5ecc8d9a3929ba91e5c40163dd1a3434dc9493de1a2a19b30280aa5868ca588773d1db052b7de16a22183e334af913fb8e87001ee8db03e1912fa380c9984c71c001bd449627f1be8f9ec9c7dc834e1194702c233664175a4d2a21d590fb3e0a2b6efba8afb59425ed19e7c6dde07f70f4a025a96645b9d7a3b9a395db39e70880f7bfb44ab4cbfe2880e593cf583cbee4ba33763347c7771ebe84f76cc72fcbc289da7881da17d6ed21bacf0dfecee5d8ed3a", 0xf0}, {&(0x7f0000000840)="c18d9e0ed9d500492e86bfa0c687ae90529a3065aa96d61d055eecefb3a069e5f21570eb75cdfc934972b07e23129331726780398ca9cabe8ec75df8cac5947810e4a42da307cad91082621d59802df13e3e6c8bd3de4d69279f674bdeb50c7ed969d2b3ac003b39df7e6f420460f62830824b3663fcc140ef60c7bf485ae2ed3601c41f3b72373a72d30bb2a11cbbecfb317ec60529f682adfc44eb1e67e47f0f67d302fb4ffc5c34cdf812fb55453afed7629d6ff817bf8978e60dfb83eef7fb1d36818e2b3581a691a23dc2bc494f5e916479bb9d795a68acc019a89f186c7a62d7a425190a4d9bf192c39b564907e8ad08c388e749a650099467e3c31938287d1226acf87f473e2c7113c360d7930693951192a941aeb30f0546a1bb4ebb5d9a5f13345e08beafe7c4e18368ef1e9a2f664fd1e85823e30fcf4935677d2022e42ac131ca346feedb2979288992240038f9b171bd3ec2dbeb3b34a4b63a976e8d47646699454059f31857e4b8dcd99b4225828d20d37e73a06bd30d1474ec07947c7fd79f3304b222a85c5213d58c7675b54ad17d9acb101b09c8104558817de653587c2bad0daf0cc8d28657909f11f52cd465d86a309011628bf015805fed00580df6d8c27046fc49c1132701cf611e3674b4d924487c3418a35caa974c31efc108f98536c5cc28ae7d5e3fc7092a0a01a16c029c595e3062bfe7d1ba616136d8299819e288b07b7890109379ad5d1596faec8ad9ffb732cc96bc29a5916ba94c39a76ee328b73407c5faeb701ab9851a44a704b6447d93a2f757b6b0b795b9edea463eaf88eea599aac1b74195f71005e5913ec90254c7c964aa63c254b29f46d28771066c499b8c02bb53468d319ff2f2fb3cb64a9f46e2cbf74d9eceee0b2d9b4f89b31cf0231e8ee6a146e75488cd0929a15dc1cb0f1b7221e68be6711aa259529c56aa4d733862493e3697bfea722636ca94d5ac1758a78892d66a08e4a8d9d5a11249ae005367ebe63db1e13836bb09b818b2d10ebc911cf51437d1253d71e7eb14961c87e7babf1796937eafb6c732ef07e4c11113cce542bed771fe0dfcf1685ed12656425d142d0cb938c3d34721b0d96c0097897314fe8a74ca94962525220b7f9059708e5305780323cf2207d720c84bd5774eaf641357eb7c912a405eb251523610573e4da0bd98649d7c76d290e40091830d7d6ddbef69120936b2dd1185082ec6da8cc482f7c9e747b1d97cc920ba7c4ee12dbe0a0ea32791b2275003fb653263276534e76b39fd545bfe83a8ad962bc06d54f564c268cb7e49fed35d114c9df58944fcb40a8c1e6acc1316905f329689a7dc1983d5a524074fd8c07c0beec8c46e3c60646c71ac2e6636f9a81f86ea19d4607b5fd345455eb70e5a3cbccad57a6a0ea5f1828aac86700fef82b724b12650f7001898147ad20732f2dffdb7f08ae3992475e2cfcc9ed373d55b99efe289e13373948cf9ba90d1c91fe3201f6949599c9a15ceeb9300084bff496b87b3a9fdcc39ea52aaf2e4d81c8d0de6947383f4acee2b1d82f67e339743fa0baf8298cf3f0f08011ece3dc71590b518957c09131d11e7884d7ea903233cb6103d3bfb5c97b669136273348158475ff2d7ee8313db192e24c82942d6592b064879f9d45a7f1ce49e01f3eb3fa23d33309b3bc56a2f0b37f9ba79d163db3d9d5f6613665934a7bf09bd2b653c53851cfda8cd228b63305f11064417f94b1577c6aa34ab90668afe335b7cd9c9b5c0acc410aa08a8bb02c14627cd1267e1b0b8fe88daf0ec8cf430d7f3a44fe0c2ab452d0498e988993537af58ffecf93efd87b5a9ce49326b2cfae0eab37577a814e8a548f035f1cd1ab0456e31f04cdb823896f12e25db7592ae4d9f11d072f03713e0880f9a63bde4d07ed159a9ab0a0b95f2a8a68750d9efad028f80037b2400a1cb3205c5f6e46d1cc23ae2a285e8c66921182c057d281c9b5b52e115cf29464736a097ab89b09d2e6c3632963c58780fabc74e3d3278ef7119a15a5482340b7c597e895112a820d97c039f706212322134c11e4842d80afba00cc3b08441ecc3a58e2ceef31eb69e88f104dc3eb91da5d679f6af504a6d3e033897f73e494e11ddf90d5c11c44ef53830b0d8d84d5e6d42f0d0175d9e1fc42a12a517113b3ec1049b7d6334e940ffbdf65d7062f6520a78c38d3fc6a11d0adcd45f4fc5b9ba08757e6e3d8592cf986b8d181aac7151346e8f62c4966c2cedf68bcce9ffa7173e026b6b983380671439fa2681e06172ee3891ae5f9264d67ce5f8a361db9eea084ce2338921754fd17ccf2d5477507f9991aebbe6f96979f9157ccbb46ca5cbe6888a6286a1173dea87ef53ea60ce73b2cfea4a9477c39af0d85f1b0bb2c9665fa41f4a42e920a30cf3101f8debc52f172bdc17589122b121f84b416685f2c74bb7b0cb326653bf92481fb5c7d3c0f8fc00e0898985a987ca01fb25863485190f7cc5fc0a8b697892072d7a6d506950968ad7cd67db2da8edf72b1cef7a15808e087eb53b4669d5197ea3e409f24fd99e271802d797dca849bce85b9ac4e8134fb346e619a3f6012e1121eb589adb3181b2aa29fea30f9102f4e867e2cf6c1d154418970a80982e7314c39e34cbaf5f16c6dc5c582528b13f08dd4906438ca79ff2d07b37f8c89b85d5e4e59d9fd925a0b21b2c65f54d6f2fbb3045a5fc8b3824e182e3adb3131abf67476d178feedd61d8b6b03efc34c68a8a99c0c5da98e2533ade85ae515b9318c13209c715be5e58074ba69b1cd8cda69b74139ab2eb67fb4931a10d3cfe3e745cdaeec74e4b5be864e4b5485a82ef1be5293585f11a082e9d978c133922d8f401339261dead95c4d6cb022e827adb92336281fda25ce6a9141328e010fc0625f1979b7e01ad37b45027c6f813516476254253684bde127e2d5306f6f54e7b303ac1c59a54e18deac9aaf5366310350567a8182aa2e8ec0e7abf063ac3f105c933a4c13f2f2ed96006152ff5a9a05d5886badaaf70097064b24340914265286f35654eacfd96971f62801042d915d2775a3434ab5659e19a1e2058b1f8c4e6dbbdd44bf1164dbfa7b343477919e001104a34306cbea72de0cd444fe4bf6348ff84b01ba0274c861ae4e83d171228d878116593e46500c7ab3b3ad4c7106baa4a76c9c88aeb3184f9a905189b77b5f753f0278f5b6c1a32e473c66a5760976d770a3913965464ccd718e72c03d7d413b1541c3f442b450c3ae3210eec4f2687cea253ef6cc3d17412862c6cb902c21eff7132fe2170c8f8ee641c592d4cd2e4ad95db0a272943da125fb7dd8b9f7c187c2c6047fa206df00aafc5b480a0dca23d33e2166994f27f76e54827e2676bdffdf450933c55afbde2debc50765e7eb9dbfc6bc4ccfe49a8977cb41bd86deaafe5579100129410e64a66489ab339db44e499468ccf8688da9344471ffbc189c7dac424b61b5d336304bf4b4ec712485415d3e868fb1b1ebdf3bc299d740c70a351ddcdb75e2cceeb78ea602036dfadaead5df60233bd8aa079c667a0c915809b667bbb6ec5162456667b8db2ccae91745f9a5e3f1e494a7c0b9a2405668b2722f710cafeee2e36b707b69d957e5f6aedd4e35de354028a9d148589bd2ac51ccd2243b6eda1582accbd432839a8b740367ada5ff94d6dcbb15cd21a64b3b03bedc9d6cb60fb42327178aaebca16ae787119b0bec226a8b631c7d5b2f437fa7b6fd69fb4dfb8c67a9c94890e2838de6e91d09490ce95e98c640d09a5b463c8c3f5de1e50d40fab10c8d5eb82aa1026e81beaa61d2c54f422faaff45b7ffec46ee0ab8db1702eb8729655534b81e2edc753fb7e8563e64937936a19ef41f7676fa1dbd0ae97d8058c826f37fdbadfda35dfd8b62b79b4f5c3ee4ef9fba2f94cb22508e292a1598c9f24be9a1e19988efb5b583ac6ac8413d5cb0aaac207ccadafa1bf93cbcbfec5762a4a50ea08c4cad427a6a82b6b263ab4519cf0f4b4a8a638e3fe3a77424855c935d84f5a51cd966f6743ec0c41d9d3dc2475c35cc3b05eaf9426a269bb6667a0af25233d71c54b1db3f702ea61b4600e0a8a60d6efa2eac129c535ef03ed6bb5f014e8e39e445e814912298f21a38a3a8d22c0f5c72afafc6d020292b13f5ee27bc92963d20135ac708bba2977fe538623278cc80e4a8d3e65474bee174cc2e52caa75a9db1fda66ac148ea31a042137e87c9d7b2de94dccc4484b12c1b896061a722669669f76204b9d46957a9621ad23fe2452d528c98a1a376ab73e0ec4db0e549793aedbd49096be4e6e6127e167336905b91ada2156d61f7cf1e10ab876da8b56f889191401c575a7fcc7e61c826ae774ed5f15356d250474608a97f5262d3cfc102a945554e641f43caa00d3f543fb3fef23664e31d5e2ff5ad157fd2a439f0375287142d30f2f85e28704b1e4ab4a4929a4fcec6d15c4c201d88feb1715c027f6544f0cd8960d221944057709c9769ea60e64602ba48dc8173179ce56f7d14afa9e7f6b30774762fcdf1f0a0f3f4de38e17823c227647561a25ba30c5fece1357dfbdc2fe5816060d15bf03f3ac025c6ae1d69a4a3d4cc86e5ce07fbdcc728ac5b30c57df9c59d81aa7aa45fa142417dbcc2f626bff69ed1aa426a7e9830f81cf63fc11e574c055960c3330bf8b02b01691724ab53c246fbe9d199a78bd86b4879b07a2745155a5e0d72b424ce0f37b97f0f188b5dd96233fd5cd729ef2a2e42fcd394a1546dc30ee14805be37526379e0976477a5cc8d39696379ff8b4dd1a5987b262aa8a10a9abdfe42dc934ed620a41d521e392a3fa50e04c7bdc2ffb3552ed6ed11314beef2d2713433cb305b4dc9efa88f0d6d085656299cfade118d0ef73a4d3c86f91990af00556f2ccba2d0eabfd2fff571ab01d6347bfba35638b555363a0f01a7831b7cf85c83a4f5ea402f9ca7eecc48e0509fa8174f30895e6fbae3f58e45c66dbea11e71a0de08c6852f0ae09c4e19feb8a59068dc0c43e87e9dc02dbd3f7b9936518f8accb110fd88f19f03b762dbfaf6ce3ce185d6901ac8c366cd9f6c9cac88ac3be5183f55a02e270e9d466bc9d6766996d315cbe075ce2376711d452232b9ed5f67b969d16f4ba5797c3654cb1936ffcd95b69380cbae57add07de38ab3735be789fd261ba963433a80839c907018bb6985b07558ae5ec2356d7e759399fc236fdcfe6c3a3e9946723dcf618891e7ac51c397178b016df71f34f6f31cb0d2f65358f12a92107f456c2d5a9ab6eec6a61ed2f9992cf30557fedd03e2fdcfc3722152c6b057e8c2f523fd0b6b4dc7a0a47ba9cdefb7755f95206a215f9e7a74a0f728a3e6aa63bf45f0f6bfd71257d0d64df3d12de2b8707d25bde800c449ccba96416cc0ea7cc9f6c1925511a4dd3b81f49bdaa992466b74cdcef938d33ccc42ce6c1c55fc56b8d62d0b716429239246b437c1df58020b6eec8c870c095b70f11df684680d5e329119ad2113e403ed0c47de0fea61ee658b6687c3826a1489fa22d98e76ce8234c58c4934402a869d44f58f15c591541323cd61d5a8e6fe7d9b6f8e43cfbd121d6ddac0bb47d7d797490a99cc288a8d2b6ceb23823d3487732fa2000ae97af4e1f55b86eab370561a467042d43efc37a8ea6b86c60b9541acb4f8fb76386f4d9722ba1d162e1292cdd849ef15b663ad07a9e2353e574a40aa21e8bf750e4af54f3f4daf679e57e4c09e4de206c563a95af9832d7db8e0a2f6e12bbd10acd0b393204015b359abc6100", 0x1000}, {&(0x7f0000000000)="4b2f99fc20020c0a3fca4c05a33de8830c093d276081cbc8b321923dc746a1", 0xfea4}, {&(0x7f0000001940)="46c01acdbbb5137d1e7c4a0c86505daa5ed31064f78caa10ab2010169e9f2c8408bec02ced6dc9cad1a657c87048f20d7eaeff48f1dfa9f8d50e2b6dba8a02e818745ab931bb5c0fca332d92a0dbe6b75bf7b21c103ddaf7f6d5815564dafd61b91fd4408a1297f484153ed406cabcc94f60d3c2be1c45564c5ed9c77f845e37796624e0c29ac9dd4c3ad0df4470973b1f2939b92639fa2be1294a992f883166a56b", 0xa2}, {&(0x7f0000000280)="a24358b3583def805ed8a91c4e6b0b4039d87d63294d921784d566b7740c568a39bb5295c9fd5d96a7566f3a1f1c07d78efe86f8ae37aff13667bbe0d063aa970ced6ce1fdc802882a9c81ec63da5484b5fe50cf", 0x54}], 0x5)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r1 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmat(r1, &(0x7f0000001000/0x3000)=nil, 0x0)
ioctl$VMM_IOC_RUN(0xffffffffffffffff, 0xc2585601, 0x0)
ktrace(0x0, 0x2, 0x0, 0x0)
unveil(&(0x7f0000000300)='./file0\x00', &(0x7f0000000380)='x\x00')
execve(0x0, 0x0, 0x0)


r0 = socket$inet(0x2, 0x8003, 0x0)
setsockopt(r0, 0x0, 0x1f, 0x0, 0x0)
ioctl$VMM_IOC_RUN(0xffffffffffffffff, 0xc2485607, &(0x7f0000000040)={0x5, 0x0, 0xfd, 0x0, 0x0})
socket(0x18, 0x2, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
mprotect(&(0x7f00004d2000/0x1000)=nil, 0x1000, 0x4)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0xffcc)
msgctl$IPC_SET(0x0, 0x1, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x3, 0x0, "01000000d000"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000040), 0x3, 0x0, 0x0, &(0x7f0000000080)="4f1d4c6344b80ed788b6a4515248df3aa745bb992c574ab4cdf5587145812eab4a988f7fafd7a01d99776d988908cd186b51f34f8c15ffa0c685ad4116c783959eff4278384b4000384dbb1c2aaeff10b4135529a1da6fda67c67469d954be811b25ec5521559154c586eefff122009f659cd3e27e98a3241495005f102d9101d158284c0ee3250aa7c11042330de22a299ab00894fdc9bac6042d", 0x4)


sysctl$hw(&(0x7f0000000100)={0x6, 0x8}, 0x2, 0x0, 0x0, 0x0, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
setregid(0x0, 0x0)
mknod(0x0, 0x0, 0x0)
socket$unix(0x1, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x8}, 0x0, 0x0, 0x4})
socket$inet(0x2, 0x0, 0x0)
r0 = msgget$private(0x0, 0x201)
msgrcv(r0, 0x0, 0x0, 0x2, 0x0)
msgsnd(r0, &(0x7f0000000040)=ANY=[@ANYBLOB="02"], 0x55, 0x800)
r1 = open$dir(&(0x7f0000000080)='./file0\x00', 0x40, 0x140)
writev(r1, &(0x7f00000001c0), 0x1)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
getpid()
mknod(&(0x7f0000000180)='./file0\x00', 0x8000, 0x4004e4)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mkdirat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x0)
faccessat(0xffffffffffffff9c, &(0x7f0000000140)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x205310)
open(&(0x7f0000000000)='./bus\x00', 0x1, 0x0)
syz_emit_ethernet(0x6e, 0x0)
sysctl$net_inet6_ip6(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
setreuid(0x0, 0xee01)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x8020690e, &(0x7f00000001c0))


r0 = socket(0x18, 0x3, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
write(r1, &(0x7f0000000400), 0x0)
recvmmsg(r0, &(0x7f0000000680)={0x0}, 0x10, 0x2, 0x0)
socket(0x0, 0x0, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000280)='./bus\x00', 0x1000, 0x5)
r2 = openat$zero(0xffffffffffffff9c, &(0x7f0000000140), 0x800, 0x0)
r3 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
ioctl$DIOCMAP(r3, 0xc0106477, &(0x7f0000000080)={&(0x7f00000002c0)='./file0\x00', r2})
close(r2)
execve(0x0, 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
sendto(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
r4 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x1, &(0x7f0000000100)=0x4, 0x4)
getsockname(r4, 0x0, &(0x7f0000000040))
r5 = socket$unix(0x1, 0x5, 0x0)
setsockopt$sock_int(r5, 0xffff, 0x1005, &(0x7f0000000000), 0x4)
close(0xffffffffffffffff)
mprotect(&(0x7f0000bdc000/0x1000)=nil, 0x1000, 0x0)
poll(0x0, 0x0, 0xffffffff)
execve(0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)


mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2010, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f00000019c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000480)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f00000006c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f00000005c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
unlink(&(0x7f0000000a80)='./file0\x00')
rename(&(0x7f00000007c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000a40)='./file0\x00')
mknod$loop(0x0, 0x2000, 0x1)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_LIST_DEVICES(0xffffffffffffffff, 0xc1045763, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
symlink(&(0x7f0000000e40)='./file0\x00', &(0x7f0000001080)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sysctl$vm(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
recvmsg(r0, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
mkdirat(0xffffffffffffff9c, 0x0, 0x0)


openat(0xffffffffffffff9c, &(0x7f0000000440)='./file0\x00', 0x103a42, 0x0)
acct(&(0x7f00000001c0)='./file0\x00')
acct(0x0)
openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f00000000c0), 0x1, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x8, 0x0)
poll(&(0x7f0000000180)=[{r0, 0x4}], 0x1, 0x0)
poll(&(0x7f0000000080), 0x0, 0x0)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000140), 0x100, 0x0)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000180), 0x8, 0x0)
r1 = socket$inet(0x2, 0x3, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x13, &(0x7f0000000000), 0x0)
r2 = socket(0x11, 0x3, 0x0)
poll(&(0x7f0000000000)=[{r2}, {r2}], 0x2, 0x0)
sendto$unix(r2, &(0x7f00000000c0)="b1000504000004000000000007000000331c13fecea10500fef96ec0c79f050000e30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba220f54f4fcf668246c0900e1937c727a4bdb8d000008e371a3f0343712", 0xb0, 0x0, 0x0, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_extract_tcp_res(0x0, 0x0, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r4, 0x80104267, &(0x7f0000000080)={0x2, &(0x7f00000004c0)=[{0x3}, {0x7c}]})
syz_emit_ethernet(0x1019, 0x0)
r5 = socket$inet(0x2, 0x8003, 0x0)
setsockopt(r5, 0x0, 0x0, 0x0, 0x0)
socket(0x18, 0x2, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0xffcc)
msgctl$IPC_SET(0x0, 0x1, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x3, 0x0, "01000000d000"})


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={0x0, 0x3f8d}, 0x10, 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r1 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r1)
recvmmsg(r0, &(0x7f0000000080)={&(0x7f0000000100)={&(0x7f0000000480)=@un=@file={0x0, ""/529}, 0x213, 0x0, 0x0, 0x0}}, 0x10, 0x1042, 0x0)


socket(0x0, 0x1, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000240)={0x3, &(0x7f00000000c0)=[{}, {0x1, 0x0, 0x0, 0x2}, {0x2}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0xff0a, 0x0, 0x37)


sysctl$hw(&(0x7f0000000240)={0x6, 0xa}, 0x2, &(0x7f0000000140), 0x0, 0x0, 0x0)
setreuid(0xffffffffffffffff, 0x0)
r0 = socket$inet(0x2, 0x0, 0x5)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x80, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSRTIMEOUT(0xffffffffffffffff, 0x8010426d, 0x0)
lseek(r0, 0x100, 0x2)
socket(0x0, 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000280)="e5ddd4a58f8b4af6777ed6e0863857d789a5aeb30b081d8003b05fde886c3df28c84f345ef9333f60de0051aa36ddf2ba9b332d2535cf2984d794a9b679ae193ad4a515e888f17dff25032335a64d994fe1c0bdda11fd07eb9a4ce94299060cf7064e8dd3b0e1d07c5069d0709547d6e9f68a3bbfccad1fabc5f1c23faa5b3c88433", 0x82)
symlink(0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
getpeername$unix(0xffffffffffffffff, 0x0, 0x0)
socket(0x10, 0x5, 0x1)
socketpair$unix(0x1, 0x0, 0x0, &(0x7f0000000180))
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
syz_open_pts()
close(0xffffffffffffffff)
syz_open_pts()
socket$inet(0x2, 0x2, 0x0)
sysctl$kern(&(0x7f0000001200)={0x1, 0x16}, 0x2, 0x0, 0x0, 0xfffffffffffffffe, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(0xffffffffffffffff, &(0x7f00000008c0)=[{&(0x7f00000009c0)="ec6af1225e5efb35bcc371fe5f2279ab7b237c8eb065eb3826fc2caca9965debba4bf1c787b41174632621a3d074f851818d888349ee3331561ed0349e22278576ba84838a22aad6adbd0c9cc80e9c7f148f56b9c0da9e722f5b94c7c39ef3c59039c87e7af3d1cda857ad8f371786d4032f4b573ed230210e1c2bc5059a5a4aec9b55317fb73be306a80b34872436118bea62cf17086c45c815d63217a22198060a20496f2ece3fdbc7f2316bc0bc1627142939c19619daff466a62f67212313e7c14cb03c0c4d199fe52b109a447e2e53b82cc13f1cb0d638b88495d7c5e1bfe3b2eab8763d0723d85d51a9b93304ea113c10560b8057e8fe0fe2b3d2ae0142d57d23648aacd33f01f00f32db5be16c859d8a1694c2f556bbfdc67301b21a37ccf98be4af125a05bce24abd0a8314b089729270dd5e58788f6575b340e3eaf5526dcd5d5db1d7cf85a45d4e90a", 0x14e}, {0x0}], 0x2)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000000)=0x9)
sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x0, "51fa6278e9e960b4dd89080863ab366d112be29e"})
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000280)=[{0xc}, {0x84}, {0x416}]})
syz_emit_ethernet(0x4e, &(0x7f0000001400)=ANY=[])


mknod(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{0x1c}, {0x4}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000100)=ANY=[])


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
select(0x40, &(0x7f00000000c0)={0x33b0}, 0x0, 0x0, 0x0)
r0 = openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$SPKRTONE(0xffffffffffffffff, 0x80085301, &(0x7f0000001540))
ioctl$VNDIOCGET(r0, 0xc4104603, &(0x7f0000000540)={'./file0\x00', 0x1, 0x3ff})
ioctl$WSMOUSEIO_SCALIBCOORDS(r0, 0x81205724, &(0x7f0000000240)={0xaf3, 0x9, 0x4, 0x8, 0x38356328, 0xfffffffb, 0x800, 0x10, [{0xba, 0x6, 0x40, 0x200}, {0x1ff, 0x8c7, 0x4, 0x20000000}, {0x80000001, 0xc2cd, 0x1cb5, 0x69b2}, {0xffffffff, 0x3ff, 0x100, 0x3}, {0x100, 0xda7, 0x0, 0x7}, {0x5, 0x6, 0xfff, 0x8001}, {0x101, 0x0, 0x8, 0x2}, {0x8000, 0x101, 0x1, 0x9e}, {0x1000, 0x0, 0x0, 0x7}, {0xbea, 0x7, 0x100, 0x7}, {0x6, 0x0, 0x10001, 0x6}, {0x7ff, 0x6, 0x800, 0x981808b8}, {0x8, 0x1ff, 0x9, 0x6}, {0x7fffffff, 0x8, 0x6e}, {0x6, 0x0, 0x0, 0x2}, {0xd3, 0x7}]})
r1 = socket(0x18, 0x1, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000001c0), &(0x7f0000000200)=0xfffffffffffffe50)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0206923, 0x0)
r3 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r4 = fcntl$dupfd(r3, 0x3, 0xffffffffffffffff)
ioctl$FIONREAD(r4, 0x8004745d, &(0x7f0000000200))
r5 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r5, 0xc0206922, &(0x7f00000001c0))
ioctl$FIONREAD(r1, 0xc018696c, &(0x7f00000001c0))
r6 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r6, 0x8020699f, &(0x7f00000001c0))


clock_getres(0x0, &(0x7f0000000000))
sysctl$hw(&(0x7f0000000000)={0x4, 0x1f}, 0x3, 0x0, 0x0, 0x0, 0x2)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
sysctl$vm_swapencrypt(&(0x7f0000000000), 0x3, 0x0, 0x0, &(0x7f0000001180)="2cb304c7", 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000240)=[{0x25}, {0x2d}, {0x6}]})
syz_emit_ethernet(0x1019, &(0x7f0000000400)=ANY=[])


sysctl$net_inet_etherip(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000000), 0x6, 0x0, 0x0, 0x0, 0x0)


r0 = open(&(0x7f0000001700)='./file0\x00', 0x70e, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)
mmap(&(0x7f000000e000/0x2000)=nil, 0x2000, 0x0, 0x10, r0, 0x0)
munmap(&(0x7f0000ffe000/0x1000)=nil, 0x1000)
munlock(&(0x7f000000d000/0x4000)=nil, 0x4000)


syz_emit_ethernet(0x2a, &(0x7f00000000c0)={@random="e532cd191953", @empty, [], {@arp={0x806, @ether_ipv4={0x1, 0x800, 0x6, 0x4, 0x0, @random="7d32533dbff5", @remote={0xac, 0x14, 0x0}, @broadcast, @local={0xac, 0x14, 0x0}}}}})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000280)=[{0x2c}, {0x20}, {0x40e}]})
syz_emit_ethernet(0x2a, &(0x7f00000001c0)=ANY=[])


clock_getres(0x3, &(0x7f0000000340))
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x20, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{0x74}, {0x1}, {0x46}]})
socketpair$unix(0x1, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000001180)="0600053feb31", 0x6, 0x0, 0x0, 0x0)


r0 = open(0x0, 0x80, 0x19)
r1 = dup2(r0, r0)
ioctl$TIOCSTART(r1, 0x2000746e)
ioctl$VT_GETSTATE(r0, 0x40067664, &(0x7f0000000040))
syz_emit_ethernet(0xe, &(0x7f00000002c0)={@broadcast, @local, [], {@generic={0x88a8}}})
r2 = openat$bpf(0xffffffffffffff9c, 0x0, 0x2, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000200)={0x0, &(0x7f0000000180)})
r3 = socket(0x18, 0x4000, 0x0)
setsockopt(0xffffffffffffff9c, 0x27, 0x9, &(0x7f0000000040)="03000000", 0x4)
dup(r3)
setsockopt(r3, 0x1000000000029, 0x0, &(0x7f0000000000), 0x0)
socket(0x11, 0x3, 0x0)
mknod(0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, 0x0)
r4 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r4, 0x80206919, &(0x7f00000001c0))


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
socket(0x18, 0x3, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(r1, 0xc0206921, &(0x7f00000001c0))
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x81}, {0x4c}, {0x16}]})
write(r2, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xfef3)
socket(0x2, 0x2, 0x0)
sysctl$hw(&(0x7f0000000000)={0x4, 0x1f}, 0x3, 0x0, 0x0, 0x0, 0x2)
mknod(&(0x7f00000000c0)='./file0\x00', 0x2000, 0x4302)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r3 = socket(0x18, 0x3, 0x3a)
setsockopt(r3, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r3, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0xb}, 0xc)
getsockopt$sock_timeval(r3, 0xffff, 0x1006, &(0x7f0000000000), &(0x7f00000000c0)=0x10)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x34}, 0x4, &(0x7f0000000080), 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x10000, 0x0)
r4 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x0, 0x0)
ioctl$VT_GETACTIVE(r4, 0xc1045763, &(0x7f0000000100))
mknod(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x1, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)


syz_emit_ethernet(0x4a, &(0x7f00000002c0)=ANY=[@ANYBLOB="ffffffffffff00000000000086dd60dbaf7700143a00fe80000000000000000000000000000000000000000000000000005d"])


mkdir(&(0x7f0000000500)='./file0\x00', 0x0)
chmod(&(0x7f0000000180)='./file0\x00', 0x23f)
chdir(&(0x7f00000001c0)='./file0\x00')
setuid(0xee01)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000100)='./file0\x00', 0x1, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f0000000040))


socketpair$unix(0x1, 0x1, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x800c745b, 0x0)
mknodat(0xffffffffffffff9c, 0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{}, 0xffffffffffffffff})
r0 = socket(0x0, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x18, 0x3, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f00004f7000/0x2000)=nil, &(0x7f0000604000/0x2000)=nil}, {&(0x7f00004f8000/0x1000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f000069c000/0x2000)=nil, &(0x7f0000915000/0x2000)=nil}, {&(0x7f00004f3000/0xa000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f0000690000/0x4000)=nil, &(0x7f0000242000/0x3000)=nil}, {&(0x7f0000ff2000/0xb000)=nil, &(0x7f0000ff2000/0x2000)=nil}, {&(0x7f000069c000/0x3000)=nil, &(0x7f0000ff2000/0x4000)=nil}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000604000/0x3000)=nil}, {&(0x7f00004b6000/0x2000)=nil, &(0x7f0000ff6000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f00002e1000/0xc00000)=nil}, {&(0x7f0000ff6000/0x4000)=nil, &(0x7f0000742000/0x4000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f00004f6000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil}, {&(0x7f0000ff9000/0x2000)=nil, &(0x7f0000ff7000/0x2000)=nil}, {&(0x7f0000818000/0x3000)=nil, &(0x7f0000605000/0x2000)=nil}], './file0\x00'})
r1 = openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r2 = openat$pci(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$PCIOCWRITE(r2, 0xc00c7007, &(0x7f0000000000)={{}, 0x1})
r3 = openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$PCIOCREAD(r3, 0xc00c7007, &(0x7f0000000100))
socket(0x2, 0x0, 0x0)
r4 = dup(0xffffffffffffffff)
fcntl$dupfd(r4, 0x0, 0xffffffffffffffff)
close(0xffffffffffffffff)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$VMM_IOC_INFO(r1, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r5 = syz_open_pts()
close(r5)
ioctl$TIOCSETA(r5, 0x802c7414, &(0x7f0000000000)={0x27ff5, 0x0, 0x1000081, 0x5773c545, "10267e7be2db67de208c8bfc612c3100"})
writev(r5, &(0x7f00000000c0), 0x0)
ioctl$FIONREAD(r0, 0x8040691a, &(0x7f00000001c0))


socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000000c0)={<r0=>0xffffffffffffffff})
recvfrom$unix(r0, &(0x7f00000000c0), 0x832f1f7d, 0x0, &(0x7f0000000000)=@abs, 0x2000c600)
shutdown(r0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000240)={0x3, &(0x7f0000000180)=[{0x2d}, {0x7}, {0x6, 0x0, 0x0, 0x80000003}]})
write(r1, &(0x7f0000000000)="1d0ff0af05eb3fc7552fffcded57b098df75804bf2bcb97a07fff3b9ead8ec0bdd2bd894876fdde8db402c1ce827d83720933320", 0x34)
write(r1, &(0x7f00000002c0)="fd9e5e000000000000eb09b338f5", 0xe)
r2 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000600), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r2, 0x80085761, &(0x7f0000000000)={0x1, 0x1})
ioctl$BIOCSDLT(r2, 0x8004427a, &(0x7f00000000c0))
close(r0)
r3 = syz_open_pts()
r4 = kqueue()
poll(&(0x7f0000000040)=[{r0, 0x4}], 0x1, 0x0)
kevent(r4, &(0x7f0000000180)=[{{r0}, 0xfffffffffffffffe, 0x1}], 0x8, 0x0, 0x0, 0x0)
dup2(r4, r3)
sysctl$kern(&(0x7f0000000000)={0x1, 0x49}, 0x9, 0x0, 0x0, 0x0, 0x3c)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1000300000001, 0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
r0 = socket(0x18, 0x4002, 0x0)
dup(r0)
setsockopt(0xffffffffffffffff, 0x1000000000029, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc1206951, 0x0)
ktrace(0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000002a80)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f00000000c0)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


socket(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f00000001c0))


write(0xffffffffffffffff, &(0x7f00000001c0)="d9537abde93d", 0x6)
sendmmsg(0xffffffffffffffff, &(0x7f00000007c0)={&(0x7f0000000780)={0x0, 0x0, &(0x7f0000000200)=[{&(0x7f0000000180)="b860fe09625ee6793978a575faa1b6c6c1d6c2eca2950efd7f97e41e178f37a79f00659c2e89ac56733f7e4e4973c1e600000000000000008c5c7b93d5c20ab4211791fe30", 0x45}], 0x1, 0x0}}, 0x10, 0x0)
r0 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f00000001c0))


r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x8028ca56d081abe6, 0x0)
r1 = socket(0x2, 0x3, 0x0)
r2 = dup(r0)
r3 = dup2(r2, r1)
write(r3, &(0x7f0000000180)="7f", 0x1)
pwritev(r0, &(0x7f0000000900)=[{&(0x7f0000000440)="d5", 0x1}], 0x1, 0x80000)


open(&(0x7f0000000180)='./file0\x00', 0x80000000000206, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r0)
r1 = socket(0x11, 0x3, 0x0)
sendto$unix(r1, &(0x7f0000000280)="b1", 0x1, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x80}, {0x50}, {0x6, 0x5}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
writev(r0, &(0x7f0000001480)=[{&(0x7f0000000080)="b3", 0x1}, {&(0x7f0000000200)}], 0x2)
open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)


mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
select(0x40, &(0x7f00000000c0), 0x0, &(0x7f00000015c0), 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x0, 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f00000001c0)=[{}, {}, {0x8001}]})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001780)={0x0, 0x0, &(0x7f0000001500)=[{&(0x7f00000001c0)="cac73ce119f42809f7c30824a593555ffe", 0x11}], 0x1, 0x0, 0xc8}, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r0, 0xc038694e, &(0x7f00000001c0))
syz_emit_ethernet(0x36, &(0x7f0000000200)=ANY=[])


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc1206949, &(0x7f00000001c0))


r0 = socket(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x80606949, &(0x7f00000001c0))
ioctl$FIONREAD(r0, 0x8218694a, &(0x7f00000001c0))
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x14, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
sysctl$vm(&(0x7f0000000140)={0x2, 0x9}, 0x2, 0x0, &(0x7f0000000100), 0x0, 0x0)
getpgrp()
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000380)={0x3, &(0x7f0000000140)=[{0xb1}, {}, {0x6}]})
syz_emit_ethernet(0xa2, &(0x7f0000000600)=ANY=[])
openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x8981, 0x0)
r3 = openat$tty(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$TIOCSETVERAUTH(r3, 0x8004741c, &(0x7f0000000080)=0xa)
getgroups(0xffffffffffffff84, 0x0)
r4 = semget$private(0x0, 0x4000000009, 0x82)
getegid()
semop(r4, &(0x7f0000000140)=[{0x4, 0x3, 0x1000}, {0x3}, {0x4, 0x201, 0x1000}, {0x3, 0x1000, 0x1000}, {0x0, 0x7a5}, {0x3, 0xff72, 0x3800}, {0x1, 0xdb, 0x800}, {0x0, 0x0, 0x800}, {0x3, 0xa, 0x1000}], 0x9)
getrlimit(0x7, &(0x7f0000000200))
semctl$IPC_RMID(r4, 0x0, 0x0)
semctl$IPC_SET(r4, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x7}, 0x0, 0x2, 0x10000000009})
syz_emit_ethernet(0x2e, &(0x7f0000000600)={@broadcast, @empty, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, @broadcast, @local={0xac, 0x14, 0x0}, {[@noop, @generic={0x89, 0x3, "a2"}]}}, @icmp=@echo={0x8, 0x0, 0x0, 0x443}}}}})


sendto(0xffffffffffffffff, 0x0, 0xfffffffffffffce0, 0x0, &(0x7f0000000080)=@in6={0x18, 0x3, 0x0, 0x1ff}, 0xc)
r0 = socket(0x800000018, 0x1, 0x0)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892}, 0x1c)
getsockname(r0, 0x0, &(0x7f0000000040))


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040))
setrlimit(0x8, &(0x7f00000000c0)={0x8})
setreuid(0xee00, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
writev(r0, &(0x7f0000000300)=[{&(0x7f0000000140)="f005c71031c1c5f421277b090000", 0xe}], 0x1)
r1 = getuid()
setreuid(0xee00, r1)
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000040)="03", 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x18, 0x2, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
r3 = dup(r2)
setsockopt(r3, 0x1000000000029, 0xd, 0x0, 0x0)
getpeername(0xffffffffffffffff, 0x0, 0x0)
socket(0x2, 0x0, 0x0)
setsockopt(0xffffffffffffff9c, 0x2a, 0x2e9, &(0x7f0000000040)="5ab7736a", 0x4)
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r4 = socket$inet(0x2, 0x2, 0x0)
getsockopt$sock_int(r4, 0xffff, 0x800, &(0x7f0000000080), &(0x7f00000000c0)=0x4)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x800, &(0x7f0000000000)=0x6, 0x4)
getpgrp()
syz_emit_ethernet(0x52, &(0x7f0000000340)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaabb86dd60000000001c000080000000000000000000000000000000ff02000000000000000000000000000100000000", @ANYRES32=0x41424344, @ANYRESHEX])
r5 = semget$private(0x0, 0x4, 0x108)
semctl$GETALL(r5, 0x0, 0x6, &(0x7f00000000c0)=""/158)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000003680)=ANY=[@ANYBLOB="aaaaaaaabb08004500002800681b0000009078ac1400aaac14002a0d000400"/41])
semctl$SETVAL(r5, 0x9960523362a3d0b9, 0x8, &(0x7f0000000200)=0xffffffff)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
open(&(0x7f0000000400)='.\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000100)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000240)=[{}, {}, {0x6}]})
recvmmsg(r1, &(0x7f00000002c0)={0x0}, 0x10, 0x0, &(0x7f00000003c0)={0x8, 0x101})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
chroot(&(0x7f00000000c0)='./file0\x00')
sendmsg(r0, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)
chown(0x0, 0x0, 0xffffffffffffffff)


sysctl$kern(&(0x7f00000008c0)={0x1, 0x48}, 0x2, &(0x7f0000000900)="840baaa1", &(0x7f0000000980)=0x4, &(0x7f00000009c0)="a8951432", 0x4)


ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105727, &(0x7f0000000000)={&(0x7f00000003c0)=[{}, {}, {}], 0x3})
sysctl$kern(&(0x7f0000000000)={0x1, 0x45}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
sysctl$vm_swapencrypt(&(0x7f0000000000), 0x3, 0x0, 0x0, &(0x7f0000001380), 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000580)={0x1, &(0x7f00000001c0)=[{0x2d}]})


mknod(&(0x7f0000000040)='./file0\x00', 0x2000, 0x2f9)
open$dir(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x1, &(0x7f00000000c0)=[{}]})
mknod(0x0, 0x0, 0x0)
r0 = open(&(0x7f0000000240)='./file0\x00', 0x0, 0x0)
sysctl$kern(&(0x7f0000000180)={0x1, 0x58}, 0x2, 0x0, 0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
minherit(&(0x7f0000003000/0x2000)=nil, 0x2000, 0x5)
accept(0xffffffffffffffff, 0x0, &(0x7f0000000140))
accept(r0, 0x0, 0x0)
sysctl$hw(&(0x7f0000000000)={0x6, 0xb}, 0x2, &(0x7f0000000140)="d5bd0d1d2d9ffee9de25ae00029927", &(0x7f0000000040)=0xf, 0x0, 0x0)
chmod(&(0x7f00000000c0)='./file0\x00', 0x21e)
getsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x15, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSDLT(r1, 0x8004427a, &(0x7f0000000040))
mknod(&(0x7f0000000100)='./bus\x00', 0x80, 0x80b)
open(&(0x7f0000000380)='./file0\x00', 0x200, 0x8f)
shmget(0x0, 0x2000, 0x9, &(0x7f0000001000/0x2000)=nil)


r0 = socket(0x11, 0x3, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x200, &(0x7f00000000c0), &(0x7f00000001c0)=0xffffff7d)


mkdir(&(0x7f0000000100)='./file0\x00', 0x49)
chdir(&(0x7f0000000080)='./file0\x00')
setreuid(0xee00, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000015c0)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000000)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000140)=0xc)
setegid(r1)
setgroups(0x0, 0x0)
r2 = getuid()
open$dir(&(0x7f0000000180)='./file0\x00', 0x200, 0x0)
setreuid(0xee00, r2)
unveil(&(0x7f00000001c0)='./file0\x00', &(0x7f0000000200)='x\x00')


open(0x0, 0x0, 0x0)
mprotect(&(0x7f00006c8000/0x3000)=nil, 0x3000, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0xd, 0x0)
minherit(&(0x7f0000ff4000/0x4000)=nil, 0x4000, 0x0)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd02)
r0 = open(&(0x7f0000000240)='./bus\x00', 0x0, 0x0)
pread(r0, &(0x7f0000001400)="ce", 0x1, 0x4)
mkdir(&(0x7f0000000300)='./file1\x00', 0x0)
open(&(0x7f0000000280)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000028000/0x4000)=nil, 0x4000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, 0x0)
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$WSMOUSEIO_GETPARAMS(0xffffffffffffffff, 0x80105727, 0x0)
socket(0x0, 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
getuid()
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x60001ff})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x27ff5, 0x0, 0x1000081, 0x5773c549, "102609307e7be2df67de208c8bda612c3100"})
writev(r0, &(0x7f00000001c0)=[{&(0x7f00000004c0)="2686280c27fbd3f957af6a133c50723d6068f496242e0889b119e49ab538e0ba11d80087577e8654332b9faaea40ed03f10b9f5519109554634493303e9b6c5969023f547cdbf23dbeda9d4bbed32f69cffadf90b850575e23b16a38a9e84e15e52cf4ea3b3c3a87b2266b5438080568382c91c26bef93f3fa5c6a674ef95228e42d0ad19fdd72fb5ca8", 0x8a}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f00000002c0)=[{0x84}, {0x4c}, {0x6, 0x0, 0x1}]})
syz_emit_ethernet(0x36, &(0x7f00000003c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000240)=[{0x2}, {0x3}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000280)=ANY=[])


setreuid(0xee00, 0x0)
r0 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r1 = getuid()
fchown(r0, r1, 0xffffffffffffffff)
r2 = getuid()
setreuid(0xee00, r2)
mkdirat(0xffffffffffffff9c, &(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0xa4)
renameat(0xffffffffffffff9c, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0xffffffffffffff9c, &(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
faccessat(r0, &(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x6, 0x0)


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r1 = fcntl$dupfd(r0, 0x3, 0xffffffffffffffff)
ioctl$FIONREAD(r1, 0x8020690c, &(0x7f0000000180))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000240)=[{0x5c}, {0x15}, {0x6}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x4})
r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$PCIOCREAD(r0, 0xc0107002, &(0x7f0000000040))
sysctl$kern(&(0x7f0000000040)={0x1, 0x3f}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0xfffffffffffffda3)


open(&(0x7f0000000180)='./file0\x00', 0x80000000000206, 0x0)
r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000140), 0x782, 0x0)
r1 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r1, 0x0)
r2 = dup(r0)
ioctl$SPKRTUNE(r2, 0x20005302, &(0x7f0000000100))


mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x2000d02)
open(&(0x7f0000000540)='./bus\x00', 0x0, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
ioctl$TIOCMBIC(r0, 0x8004746b, &(0x7f00000003c0))


mknod(0x0, 0x2000, 0x0)
getpid()
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, 0x0)
r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x39, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
socket(0x0, 0x3, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, &(0x7f00000001c0))
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x8020690c, &(0x7f00000001c0))
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
open(&(0x7f0000000600)='./file0\x00', 0x70e, 0x0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x0)
open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
select(0x40, &(0x7f0000000100)={0x0, 0x0, 0x0, 0xfffffffffffffffd, 0x0, 0x18000000000000, 0x1, 0x5}, &(0x7f0000000080)={0xce9, 0x0, 0x0, 0x0, 0x5}, 0x0, 0x0)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x2}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000080)='\x00\x00\x00\x00', 0x4)
r1 = socket(0x2, 0x3, 0x0)
dup2(r0, r1)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x6d4)
r1 = open(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)
ioctl$FIOASYNC(r1, 0x80047470, &(0x7f00000000c0)=0x400)
r2 = fcntl$dupfd(r1, 0x0, r0)
poll(&(0x7f00000001c0)=[{r2, 0x2}], 0x1, 0x0)
fcntl$getown(r1, 0x5)


sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0xc}, 0x4, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$net_inet_tcp(&(0x7f0000000040), 0x4, 0x0, 0x0, 0xfffffffffffffffe, 0x4)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
socket$inet(0x2, 0x2, 0x0)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1400000029"], 0x3e}, 0x0)
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)


socket(0x11, 0x0, 0x0)
openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f0000000500)={&(0x7f0000000480)='./file0\x00', 0x56, 0x0, 0x3e})
open$dir(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
pipe(&(0x7f00000001c0))
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, 0xffffffffffffffff, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
socket$unix(0x1, 0x0, 0x0)
unveil(0x0, 0x0)
execve(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETAF(r1, 0x802c7416, &(0x7f0000000100)={0x978b, 0x0, 0x3, 0x0, "bb08000100f1675910508b00"})
writev(r0, &(0x7f0000000500)=[{&(0x7f0000000a80)="945a1f6c1f4f70ae371c1d2d722b342611a5886241895f7207e483ab4eb138a3af9882c9738a7c3377adec31b9e748b5bd07ec995a8a8419e1a96a7fd73aff43a96532280c351b0998bef5bfff203070dcd88e84edf11d8220a8dbfe7ba651f52a3699a2c543cf8725ca8e84c20fb0a3706903ea6377b189c9b18696f55c1cc664f47b7012fe6add368512ea10a12846f37170a6bd87fe74514b4bf645e369ae39b4805d4ac521de7c0bdb666c295d05635eed7c2ae7ca1a942fae56492599620a0c5e5674877b5d8133b346601f5dc632f40a124feba78573c768c716065f428ec1594349b0b59731ed565f89b7b69cbe2c28396cd2725a06fe0b374ad829d6c7fcdcd1665ef2a5f9dda05d63dbb1a560480a140d5149aaa6d60dfa2be62038130306ed530e3daa8d6a937565f4ee548a75ca42c51c51c994b151f1d4ae2d1ad6452d920c5689351f959f2d04729d4447acc8ca6e0acab33d0149326a6201e043bd121bf7eac19eed37a283283011db2f79107d389d6f17e0abc91dcc8b621ffb6cf4921af74919d441c6d2a0a5dfe6567bd300b9d871d9481d05c6eb24286c2df6e701d4014996db0f646c39c1ea11bca0f9a07df44ac1000d", 0x1ba}], 0x1)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f00000000c0)=0x5)
writev(r0, &(0x7f0000000380)=[{&(0x7f0000000080)="e0", 0x1}, {&(0x7f0000000100)="6fa533b2eda506b781f8dbc069461641c8da6d2785be257e9335395711a3c7bb0641c680be122bb694db035c7ff596ddc06acd1ed5f884d1d7820bd4eb283ccca63a80435b8b57253e7fd0cb02d9ea1683186f1afd3976fcfcd3", 0x5a}, {&(0x7f0000000180)="c88483de365a5309893d38c4b4701e88a5f1d3a8e59c1f6f3790ceef13c83d3f54530552ecaeb64b69ed438e15ba62710e5e3231d50932b6d50934c3201e78970ac1b0a85527e0e1006b0cda673f8dd39b57b7643d24f61afa7cfc8683b59b741bac0d39438fe9727a8827bcb524eca9c32ec59f515d4ab671a0d3f2ca43e65ed3f69a860f304ef2f526391bd840ddc36e729d29c205f7bf7b1ae0abf525faa46cbc5ebb8599795cd4d742e70c750e4ce6d249c47e8e6a82cf9a7688df513b3f344c9bcf45e89f5ee16b01e6d8647c4129ee89d8ca4db3fe8e0abb687fb64d8140c71a1f36eb04", 0xe7}, {&(0x7f0000000280)="978f1d00f7e35bd3fd0202fdf9c0d9ccba091c2409a7f79b9e4abe9d5cf493163cb730aa61c9548a0f8519c778af0c2fc42937fbe082ac5f003b74c11c33b7cd46ccdc7fdf3649388e5865ae19b2f68dd87babc9995e727666def7155f4d7b37e145996a42cf89df895a60", 0x6b}, {&(0x7f0000000000)="b06bd2f306128f5c98b4f9af9495df0317cd4a579946d6d9b7e2d2fec6fe448e57aa46e17a268288e2d98e498e07c4ab931e43178557a5bcf7d2ac5f55577fe4943bb58cd47e701385", 0x49}], 0x5)


setrlimit(0x8, &(0x7f0000000200)={0x9, 0xc0})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r1, &(0x7f0000001480)=[{&(0x7f0000000280)="00000053f6953b578a5e78ba726a44164282fbdce59879e20721c0b25930ac15cad92b17987d6c70b9047f2d23cdb8b6d76cdb4acd0f01d102ca1b9624dcb92a3496a85cd3e9356c954d9ad25d87bbbfee51603c6f705bcd4ebc04feceea4a01bb7075d879a19cf6c8ca7a76f1a3377ba643b0b06bef67d736f39ab2dfaa21a7c9f74a537a67ea748b925d5c0db14f19b8643bb65a04e2a641830b2ef9ab4087e50c63959920d13ff13464ce1c18b643a71260860e0483ab217250cdcb121305c5c1b22a236c83d7b8d20dfc08bebe5664e1ea1eb7bb0814dd", 0xd9}, {&(0x7f0000001d00)="6156b89a6c15794f5426cf6a9a99b45b13564d6568f0610200e27d20182a400c7a9a8f0bf304294555b6b6cd19d32607b3754f4a88c97fe52899b92de96dbe32036c902694cbd0aaeda1b13395179e9aa22d5bb4ed975d8a585625759478115f4c4ea9fbe58382e00bad0ecc43529514d50fd81869975cce62c2e1a2520b63fd16166f35d4894abbed34c52f3e7e55be11106341ebcf1c65", 0x98}, {&(0x7f0000000380)="4266852a5bd711d4aa1bcdb84c1683023895f3c09dd09f6591cbc32693afd0b88a5a095acbc2a56dfe7b00631bbf4f1e0d5f97f7e6e6fa34e7a87f4928bdcaba0d83c8a2eb4036e617f903007224ea89dd9aec6f5b8a9b09b2593bf5a6bf21f0983e00000000000000000000000000000000ed7535a47ce1bd9d6e044370222d71e81d8cb355ec6f3d3dbe487352f0886fcd2a5a6470960cd614ac3aec14578c684d6e20dd82f1bd5fd29c321865cf155d4fb1667f1300000000eeb5681a51d1910abaaeea3cb6aa6f6b8075ac11889a339f163d310000000000bb63e9f36d03ea559f02ec6234e483532c08e076806e75b77b63edbcc2de0f21f6363b1674a0ea40502a5a2d8649ec4edc41dd9b290325f3539efaf80342ddf1721982285d6980a3bbc7408d98f69b84a4e938e4e4a36355024630c9d4ea46d617cb3b95c549058e27aff7b15eba5c0a8a67d80358b1e3d8a6618df7f66516901ed09853dc7955b2e20d6cb0eed9b9c6f91b8a4c69f2a92a2fec31d153422cf6d5678a6220fe68ff706d1e62dd616f46d50c5049367e24c7e01d66b9b82773f1", 0x19a}, {&(0x7f0000004a80)="e0707225df5da0a3cde8f30024830d8e0a6a680844e59fcfa5dde0a596d8cb2901b8b60f269bdffed86a45026e99759cd124180e6c72cdd068718d18c40fc74364f4efef980c177c9d13853ee6bd3efb6bdd04795f2e00eef893ba9db6c641724b4320eb59db72e821e00eacae80ac14ec93e79465b5dfe980b08c3e219e10a322fc6a99d984aa3a17ac3eb99a7d90cd400081b6b1e9c2e49f51572f7f000000000000002cf371ea6bd4c4ec685cb5f1e1944576a86ba1fb802e8228e5f58b56265448b08e1f2d780a33751c191bc1a169ff48b7256c2993e0bc717933110bd6383d6022fb98dde74b5ab0ecd85d1c8019b3b8c07c14da5e8c27dea1464f6fc6dfbdd6c0f4b271cd8e8de9884f86ed79b994b9ed88cf29836e05544d9b93bb7fc1e2c2c2fddcddc82f884d45aeb0ce7407d2577be2fe2f8098613ab2ad60b5032a13dd9d63a2407efe3fadd1846988c3a299fddc1186d14064c4aeeee77394eb10e65516559f522378718fd87e5514c8fe55366b2154c898a888dcbbde73ca9e0126d6ee8c27af7b9eda998ffa359f377ea61147a6c3197247f363596ad3d3d0d9282758b09339d02616828993b0855085ed4748e48c50f7dab9668a7dca419149596579bb01408b8f2afa2b4bada88efbc57b7a096065fe6cb148eaed8f3becd5c7287c19d8b8d9341c416f2716c7a6ebaff889cf1ce69c7f4bf117fe4aefad2a50526a28df87ac628879076fe3b857ea830f45cb702afb7c25a06abe4d2a754d0fb77ff30877884fda5755e1c1c02700bade0be10b3c75c0166e477992584dbe309f2136ef82f72391136424d14b3fe1c4ff4cf8ee3d4a30577aa377438a795ce1efe0fef1f6436644224f92b45b87ec346a63a4600abb2bbc572ea82333f56d942d0294230c7ea8cf24bcbab7de10a06fbf4b8a5e4bc88a0b4d676062a62d5042b5d88b0ab80962dfff7ad508e6580ec0e565541c713e4a854483788c4440ed3cb388bb2fcf71e33495d9729eaa4f3df7d9118ea8942720f5dfda14cc5e35cd1c648b1e295dd0984536f225043b7aa56f45b94959d83990e6050353c7681fd596fae2ad6b43b26aac3e6302691eb49a92ac075b0973cc230bf41a02ef123a80cf799a9cf2c472ab0b45cde3c980a092662b79a78e428b56b878c2c9d7d2f667205d07c040744781e9c27e32a133cbe9e219489d97bcae4b2ec4ec0839978daba24fa23bb89fa6edc2b1f929e127136e13d7ab140a240aec7006d0740d15ce77b028746549bb91bde24e341d6aaef7684082283943780105de76983bc8c5101001c3a3a5dfe282d11d70ba08237d0c23eecbdc4a0738dcd1d0e92649c64d1fc75f5d4b1ccd10cee6ed69f4f63f63d63b04a73fe9b0d95ec3d98d55429524a7d5dc83c878f9bff0744c3c3dac7513e665383d243302b985da0fb404dddbde640a4f389fa4c3fb9ea1c5f9d515a2ccc8f64c832aff4f136f99b4d917ed0c1cdede6ffe621e6cd136bc2d43fb680dff0c68099c9503f61d3640c8ab7e0e00fc4a83fb01f03024f4f5325c1fb55568bae34451d9363cdc81e46e97b1686ae29abc9b06c8b5c7e989d3ad961e7216588c01b58b29fb05c432a615d17a09e3adf06cdfdf3dd2283aaa8fc9399b7b1d83c595c27f27b0c43fa110727fa37634d748bad8737cf7e94fb2c07b9737c4576b58e746ff84bbc736f246a7a368af9bcc22ca05122b160c0382db54145a62832ab52e1db855a1b160ef5f619b49f1e02baac67b9b0e626ba6070806e70c82c2d7c3273cf8e90270481e7baa2b2b4dde1b355f71c38405ae3f4f20e53db5e1542091b7f01507410184c37574a9ac52e3d588311c12bec275849496e726f8190529c0a49a0e3e6f455202aaa85bd892385fe7109b119dc4b5f9d6f74b0d27e04b2b648769af58d288765be71b37989a5ac5ae732d9e2a12c722e285383500d13e00dc7d6a064a7b207427edd517b5d30ca905935dbffff61e10b84ca904e4b58ab3278b09d1a3af7e337f777393b93c0e84ae3eb61f87e8f1388622fa35fdd51868a3329cf2c05fcba3c7cbf6afe20466583fbb1a8fa5fefdef3f8340feeff8048a96a2bf7466dce009599d9290c3e091ddddbe3f2031ac6e4c5ae5cf7099f92dde452dbaea6df2ad42b0cf665b8e221206fec348a6e3a70de77d7f474b88e8d328009c8ee253caef981ae633705c28594d3da0ce0de71b21f1cf64ffa8a23f58164d60240e1252aa62de9da39247acc335c352a8724ee35770747b3baf2ad195811dd7b768054277f7e59984084c464d49d936d1c66f7eb006001104bb29906ed7a14ffd968315fcad150cae3d278da5c0b1c82a62da917c39114deddd5bdfbaec686968e8f1aae41a18121de00cb66e9cf95403ec3c47f9155482f2b586fdaa860ac2d3d47329b1d493480fa5c968f3908f56c3c4731df5baab9d67b7b2253e3965a783031979ab940db29a998af0ad8fb492a883a60df2b28462813f8030bf701ab0e779cbc175a7e8d60352352ebbad06f6f1fa8b7d642ce526043ea448fb8583f5ad9759a422a41e41d7b3a36f2fd3acbbf4ad53f4babb0028820093262d6b7953ac6f90c270364c31e7295ed15d106cee1285fe71b446abcf7dcf3c0e275e4426bd4e7a57e93e7cf73e1372510d8e6a2048ff8780eda3223277a03eacb710cddfe510169064edbce166244de18084dfe2508159f889a55a67f083c558a9b77f733daff67179a2322b53179e0079c92bd7aebaea9c5340f3ab4b7cc81d51803abd09fcc33392063c34ce1e1a0e675adfdd4a492f5a45e96d2da3d4533c9591bba11ee5a7f8552bba7cdc68932f8f4583e0c8f72b064fc249e1be449f1d4e6c8faa0010000000000000ed34660c399113ca2e1af84335086124e5880174e4db34d7e82a81ad779a2abb3f6de2d6e5ed9e08855396579362285f40c6aba7fac5766b30caa1b5a3ca31935a45e124040a29b974de1cff0eca1b1ba280228bafa33d26d87f77abb36415122a0cf24e1525228ccca1f6873e67bec443c6fc46790d2af8029bc97719078956a3d3c897faf5b19beccc2b37813351bb8a0964a5f8cde403f162d4035b6743fdf93830888e6d0927e68c924de1ee1e6eda7de8348196a0e240b4fd629338d977b497c315662ab60b84797b733a931741f0f7ae88e608a9dc73ce5f2b075af61b6acb61f8fd475ae504f97723326778a75a37474e1cf72de50206a2b6fe5bd566c1cbfa0eba48c19297ed0036090a7989ef743211924453e79ea244aa18c85170c9aef0f4047332f8b35b47776723379273f292200f4a95c5a19ecd42eba114c3f8cab75937ae571eefd7d79368272db2d2db75a1951fba103340a092a7f7a11e6ed7aede39b6992f2163fddcd8998b1a51ce55edd4991bcf242545192c5da99577e6362b1a26c98ebdd7353b0a1ad10b5736faf60273485d0b7d8f9c6dce6538e5e8dac1b564bcf788efd488490736c1cc354758e6d394c77561e47c8c5de55c824dcef6c2ebb6e9e2c734ea05b56b5017f2447a2634099c1b9b09e061f6747e663dd92e0dc5eafa5eccc7e8d161c1e79f30230bb07dba9894fa6af1c66592cbbff937c01747ce5ca6b356f54f141420e38ae84b8ef505cb8e5a20933c463f48a70983996b72219e31cefc8a9485f6f5451deb8686bf1551de5b549da221a014fa06222265932a5dbdcca51d053482d30798e805c6c65808d72cca8d8aff611be639e7af32a8e9e92b2b83d59a081b86a7704b92ba6ea48259a31175760354ca8733a53ada1537a123ba7dd87b55bce95c238e30f19092f9585e8dd9053bad2c51385afe012c2dbd3c277c9e6689e907b907748964f38b9576ff9b88ec5f1961cdbe845c7e096061686ce822e34a2228227e934803ede4b984ac3e4ef28f0c0e24e0893e70d7d0f668c7d38a14b3b2ff87cae2d1fcf1c8db5c32d02250145fbb20cfb8b279baa4a12526484bdfe4d36d49a82db857b82a0e11a315ea2e298bc8b8a69f4f7545008a440ace5b2654872f3f569269a1144e946c90f904e48ba061c1a615e8cde0a4194a567e86041ac9fa4b42553e19147ef3185fdbc685da9b439f02a6a34d8858eff5d762d4970488508f194b7af38590888c70d69b9eec79e53497645006ec6658dda11a7898ae96c8bc1a54b48470dbd840f0fc68799019b5b4137dc5de49af82d12ff2f50033ee8007c7d9ef1ebb3d60fddcb9239508a858df67e6ad3ffe23acf973db7421777a6a2f23ac58f599d88487ad8515808de09a0f59aaad6ecd7ba190bae74968c49b63451fd68cb2b835db73f7e341587aec98e7618b9836b8e851cb31ba1a2a86d52cf167279f850d811a0209a3d4a9c54055ba189eefa40ea10cd6458e1ba09979a3bafd21c5837fe11c264dea2f529ad2ed6d19849f2e8c0fad613478cb66a6724091e4b2c56588793813b44745eb97e688f382026c85e87124a66f542bdb99fb7fcd874d34985353e74a166a9f1ad64c305912b2b6ec1423c15788fa6b2194e2be021f1deb0f1b3d44b3313fbc9a38c290cede3cba47afcd98a4e50d019dfb64214d9c18448c375186ae9cbc7df4614ed4b9ef760c9808a5698c81b1542bb08e4fc82bfaa01be44d5cda756d4111192661807d4f0ae852777642019dd45d876e2c3bfc3f0486016b3d763cbd9d899b3e00c7d3001e94ed8515f0ec9b9f1ed7b8df767103ef964acb4281a59f5cebf08cc14e5f5166b9a77a43e8a3ea75c3a6a8e56eea86eb2c861fcbee63d44e60a2dc88c726b8149380aaaca89e83433c919c53754a64f9d8fee3049a5ab750eb8191f7676cdf3257c9e0c661921049962b800a299e5f5c002629bf053030203b5925b0f782c8bc5982546761b4256dd7c37a99de97f1187190f3a1068c86eb7c54cb3ba99052518ddff6c2f5a3601808ebccb435889a32b844d663330dd2231d55cec6a2e6f880ac93dc383f0323f33f66cce427475e117054827db2ddee05696992299131d9621d5041a596c3e72d7b018c813c5e1f698381000d3efe1cf189e2f749047bed3c6cff9184f22b4f3b6368e4ed839802f31394207395f8b3758f3c93f640734ebd122b52739a610d85092beeb06e47d32ddbdb1ff4ae18c696cdb93f8169f5980b01ac14ff66fdbc7efccf6f572a58e1a05efb444510edbd59cfef4ad12fe842483a3178cf9c81bb43e9213a7a49339d9a4d8150b5f253f938e91b3801252ca80230a9eb6a15c048cf10e068c6bccdc756d7fa1cce0b1cb147325b435cb504e5db48c32bc68f74a60b8baae0dae80bc4cb1cf4856802868817de6e7345ed493ce177a3dbbdec2690d590a23e3feb49554dac882dd8b70d8b7128d7ba1fcb715dc8b18a2bcfae0bf0a0bb557eb6eae8bad4ce3ee4246398e304188b1dcac6ef8f5e251db9c29e0ddd58abd191c5e2a961fa3e09fbf5a540c7687fefa036743134bf7008f66f484fe72a812844385fccf500123ddce1c3628c0826250f6e2dbe51bb7f525261f64bed241d3ce57b7da9f91e0d6cea8b3b249b461a3bd0372b2a76758de3113532ab8ddb3188cec04333d8d8930673fa753cdda63376e388d99a995642c7c43859ddc8bdde9101a7ebab17d4894f75dacde90fa971ed682fec74e25bd782a6c56d8e5fedd9ceafb8a71afdbeda2bc8c52047c4918c1ca24846c83e1b94fcbae7fb12d01f425e799de44da53c08a063e1ed1c47cc2fb55235c1b305afd000ef8f8cdd7a6234a37198b7bd8acf59a52c325b34f76cf5879128463d3948b4c401d9c8c8b1ebefe4405252612148a2fc80edd07131faae7998ab5e42519b9d536e4a", 0x1020}, {&(0x7f0000001540)="f286a84d365450931351d56a392f125053e372a5d738c37505db0309af2da86a2fb994a60b88c2d1b12db552a6c56314abef9b6b532015b4391f6421738d526a3c4905254667ff45ff720515bbb9e9803abae3f6c56a2119054f120fc0254eac0791fea04fc293d35a97e02dfc2b60dc5eb83364686fb7960fc4fc3dfa1dcb0bc1dd509003092b466336283c87db76ca57cc7b0ec75d90e34d356d6696aa10951cdbb4d415589474d7a00326ea53830bf3ba7fe924eb4f146802e79e7177e20f998dd2f99a7614716dfd2ddbee5cc8c83c422d2c3edc86555bfe1a04325009426b745134a4fa7ab813986a9eabe105a05374", 0xf2}, {&(0x7f0000000000)="fcc08cbdb3c54d40fc4c28d500eab996a057e82ea0f2018b538efafb69d3d143ab519ce9b7ffda20bcf2e3a8c037b71be2ddae827928d412c1c9a85def5ba42b7577146b901a", 0x46}, {&(0x7f0000001dc0)="9160123d76061585eaf66ae5661e9ef1dcb68a5ffeafff2953cf2e1d8a09ae56a62de6211d18c47e0f3491f0ea03e6790e5c82c2e7d1212652cfacc7743261bc7250207396761e126a9d84b718819d4edbd78a680b79e1459388cd1540571bc7b6b22be82fdc23a0dea1e96238ef53fb6547dc8aaeb3c796eb7be3628b9ce4b2ad3af54bb93a7b609ec98c4fd6e6f40b78a136ec58ac977c0f03880adda9eccffaab3d25acbd77ff269c9d99d2e3e1c9391c7ba8b006b705cab5266892846bbca602408217d66179330b08563d3a2d036050e08f5a632a2d9b8f4399eb7eba6d146046c29decb9837d0127d596bbf3fa47843a5cdf896c9f39db9bf43040c135b43dd710a612c93cbd250efd513478460b88afa894267d6d3b5caa4df2f742ff9f3e6be94897da6794576524701994971c7ef2dfed4f359e8504ee8e93001e9ff61410a2465cfddedb29910228dfc73c71e88be80ce1905310216847c784c3b3be3d4491d25c99901497a2c4856b2989ff73d183474a1870befe42a2236851fa6240071ab8abe4e31179c2f53e634e70a12583be24974f6f85153aa453611c0c8a03b2294a3b234c4ae161d9265cced961b0df5d4515c76984e5e4e15f50b23d890b2bfe7b6c30a6409a5b74fe5a4a8c036b93cd9fb91ea84271269c52f8222916306f23edd3000f7b41cc4b3a4e5fa88a5c2d7678f0227a3782b1f8d6864b7fd8c2e76eff5021235dc3aaf4995d721d6aabaacc97373a107af76ec2c2520e400fbc749f8dd479d0cf5da54c4a73e41270d0391963e0cb8542be65f43fb2538d605085c22bc116b371c9aa02811aa86bd54a65a4b6983168180a3be1560b526de700f1949bb32d5d9f38f6a5c6281624c6fcb44aa657468ffafafdc0637748df145f718082709de89edc894c517a0f7ee0835e1fde37ba18740263c5dbb872aaf3640c55df4ae91f1c4d8a6d060fd46d2cfe9928475da6c0d001f9e2777437a663cabc593f8aa84f3799263cfc27076568723a08221b4bd190a3d24bc7f9bf91698e19479435a59a8ca4fdc38005865d1e61eaaa9e4d71c99bca17b34045c700de76b4d90df4ff250341605ae4a680f6bdfe6ea5e6ff77bec1f6963c790519181faa2ec1a2f9b16d1b824dabfcef556e91ef4bce02b702146012f691ca05e0f873b793d6051c6448876a93fcaf32ad9b129aad644b9761508e0cbdda42424f5ca9ac5a0cb67fd5ef8d26078c16cf525df596a885bb192168ba4a86e99c0827b56331e6fce281bfdbe7601e6dd9f80e645d073e5fcfb80f23ed8d6a1c4c6f1a0593f126a47bdc15964106058ba5a3f5e3937e4d1936709df941849452f2c9c392aa70906c85e0edba5772c67f4ea0fe3719344d03a358fb664d793c4aa54e216aa56f8cf2b407ff5d4a529911af166a61b7ed4c3ddee3a52bb0c74950249d112f60d18b35e6c199bbaafda43d0f0e1e29b0bed4faeed45e840be722bfab97e30a01e8fdea1117a6b8581d6a9497c3921d84b377cd7bc1a1f3df421fa0a31f196c9f011339a202c77d552d5e30df29ad6a5463ed0bc728969bcb38626a82fab1855df909acb56dbbbe1338015737b460b9085379f144f08f4fe6fbe9c9df241061196a35365a34eaf0c65f97d15c811b98869c4a49ddae0601994d545d202d856fb5e3c96921e56b80ec978feb36f5daef50f995dc3cad442da07de75b97f810dce38413e8cc64ce3d32372a5b7b08ee898f5fbb37c4cb70e8b555322af7968013968ab4d07441409a43d6c68dc5b5cc02ed048e6a296f1f735fae1874c921c15dc6c4422c87c803c1783b344f60f90a3d2efafad2938d8269bda4df1bb247b482f36c1713859723951d31241fe7b3fc4b7c3bf11f055de8365b2b69328e5755fbab9dfb0b03205b72c16558ca2e98dc059fa5487c37ce89acb18613cc62486ce09e75a72a8be009793b00c74e9adc2b93471102f16e83cc9ef0ac2c2b7cb5aa757a5d51cd7f6336151beaf55eabd134a6e6b93593a151653837ed5d494a03bcf061d63d7a8e501973506642f68d6b2d490490cdc9980a624714008335f98caa71d22e8651849caa054b5c119dd154a80afd2ae95506728c0acf02eecd8887b821c764a2be51ba755b9db883a75748d3c20c2205fbdd1ad4ea848883642e27adf313fddfba60f314a80a463f056179643abd18bf0454dc13dd799d25c244460d8d2619238bb5aebe667fb38048d9dc84242dbcb17ecdb64170bb6b80fd710f597cc96d081da2ba082ea62605bb3388f43d1849f8b80ce8f8dadaefa84b0cf5e12c2a3db678dc0859bf927320cf765fedaaefad94d0da4ab50368105e4b5981feeb3edef40cf25780b6b00752e4839a1f3e0c3def6e5233db0490dc8ce93dedf0d44a05d2a132a3649eda3ab5da9e7762edd08b83a8cf2e7d253a78fdddc2c6ce97cbff41532692140ffd82bb4249328d01a9878e3f59d7159c493bec6184cd3d71e9213b4b6f70a7c26404ecde93e81e897e497f3b44ee04bf394cbe8540a49d31e33aa875b0c0e43e0c6af3035bc5b7992a08d8cf0b5a88f0e5b88b6da6de61c0d1b6289be8d9effcaadd6b62f47b7169092f07ac1b1469f52b4b2369fd2e0fae1bc43cc415586b11e4fcac1b4148d5e7417e3a0a0ba64973581546781ae2a069073a0a557ed02b2462a2f26ac44729308c2347f4a7d7032b521ff58a8d1b3f095c376216c44762c889ff33f4688ba61dd2f1da40892e49a0bc0ef08940af0352cd6393eb1aef2fe707b138ba8119f3907993810a70bc4f1625ee0618230b58016277b50f89d8a7b92601c697b9ee5915a8cdf0b0d6f23005bc29ad38f7f3a7085efa550ea390ec31873f999733b874242b1eb5dc9dd5a8deb0c14d37e250d98060bbc30e8b5e6155267b424cf16deea1c1b003407f1308f93e8fa0ed90fb3789c7b05a5c6cb65fd34df7555dc14ee95eebbb0b2f0d75e3bffe98aaf4eaad9d39ceabed5967907007aeaff27bb2d0f11cd021bf1adfea43f09a6860db43ee3be9e520399bfe1f4e53b9981ba8f27f1c5e81c63f5e3292ada5c1876436b1d2d5504ab0affda2663d82dfd368cf67113f6dc50db632cd05b71d340afda503c2076f8bdb0f7dfb915defc7c1c9231234ec1b9bc51c9fd412ca09d7b0fd44af63461ece300c5e13c97be28a46be7d7811b648aef748905a3edc10c9854c2019b8da98f39ddae20857a9e10c0e0d31d21732b4464e69a7427f947d0d1428d785238cbe29febfe78002738319659cecaf443da90ce463923c09849bcd23590513bf05b9a0030329d29422057bfad1e9201efde01056efb4338152a90f3958d92affc0d28026067b9fb53847c3eb773edc09361b824de631476c50a9536d3432204f02d55679966fdac3284f5a8e6bb1a0fa8765f1bdf044f58610340b4405c1865340ee14aa612738218e58822cea59b2233bde7f515dca110b5b69cd023c65fe76c05b3101d2cb8839179c19e1253eedd8aa49eec5e61a2344", 0x9b6}], 0x7)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000080)={0x7ffffffb, 0x0, 0x80000005, 0xfffffff8, "0100000063026d00000100000000000000777d00"})
writev(r0, &(0x7f0000002f40)=[{&(0x7f00000000c0)="8e78dbebae5d90546f15d52a70c0d6c01f58a61f32323c0794131b931fec61639d2f39a6047225d023e386c4556448c215cf2412d15d80dbf9f84b8741dd0b85594b84517605a7a7397ed4fb170e22d274b430934323f2f4fb5606ef5596615f1483c475b95ef23aea27e3b7a7c35f66ed518b4f97d9fa5945621a1173a9e1e34a3761486699739b5dd0f87a0d15ddb90c5f0b6935666ed373a8123f5a6167a180b5021fd0acff9d9731a5bd60e3ec94e2b7771d82937d6c7ff1b9422fdfbfa590964ca5b01b1ec5b60ef0bdd0be043b45cf8d18a5e672cff3c0aad2f41623f7ba3ba28c9b2419a3492b027f5169f1c7a49d496800dc3655536d", 0xfa}], 0x1)


syz_emit_ethernet(0x3e, &(0x7f00000003c0)=ANY=[@ANYBLOB="ffffffffffe0aaaaaaaaaabb86dd60b42f2f0008000000000000000000000000000000000001000000000000000009000000000000004e234e2100089078d2248e8cf8a589f852f57eca64cc663fd747b3944abb49b4ddcde9eb164b5da8a437ed91cf29a9b9c980f40df22fc7ce09c31e9e9d84f7a208c47d297984a1d2f8756a45db5eb7e0a89d9cf8ccf54c5dc73ab982c4b873184668b2c47d23a32d9bff1b1b45c646a6b11aa4a35a108f4dab6ce57165990540e44f3bcb9fbdd265d1150575cc0548488ad8384a68c9fa99f3f136352e19a9b63c6e879e7c654e8d1f43a2511f403794f487bf8144272c6d59deb53ef504303dcfa9ca6022f0e35d709a9ccead0441cc73d78fe18013846404bb2fd26249f9a50444dc1eb359558ba842"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setrlimit(0x0, 0x0)
setreuid(0xee00, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
writev(r0, &(0x7f0000000300)=[{&(0x7f0000000140)="f005c71031c1c5f421277b090000", 0xe}], 0x1)
r1 = getuid()
setreuid(0xee00, r1)
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000040), 0x0)
r2 = socket(0x18, 0x2, 0x0)
setsockopt(r2, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
r3 = dup(r2)
setsockopt(r3, 0x1000000000029, 0xd, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x27, 0x2e9, &(0x7f0000000040), 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r4 = socket$inet(0x2, 0x2, 0x0)
getsockopt$sock_int(r4, 0xffff, 0x800, &(0x7f0000000080), &(0x7f00000000c0)=0x4)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x800, &(0x7f0000000000)=0x6, 0x4)
getpgrp()
syz_emit_ethernet(0x52, &(0x7f0000000340)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaabb86dd60000000001c000080000000000000000000000000000000ff02000000000000000000000000000100000000", @ANYRES32=0x41424344, @ANYRES32=0x41424344, @ANYRESHEX])
r5 = semget$private(0x0, 0x4, 0x0)
semctl$GETALL(0x0, 0x0, 0x6, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000003680)=ANY=[@ANYBLOB="aaaaaaaabb08004500002800681b0000009078ac1400aaac14002a0d000400"/41])
semctl$SETVAL(r5, 0x9960523362a3d0b9, 0x8, &(0x7f0000000200)=0xffffffff)


socket$inet(0x2, 0x2, 0x0)
r0 = open(&(0x7f0000000200)='./file0\x00', 0x20, 0x92)
writev(r0, &(0x7f0000000280)=[{&(0x7f0000000400)="56cf5daafc6597872431ff6c668c28adc33a60651a078a116b3548a8be66444658a069b71e92feadcd7b3434dadfc4fc3fd4ef7525b58b0086932b0a93463511a8889f58073c33282b2afa1967c7908d4d0aea830b68a43711d6c4457ec4a41a772d6ae311730b7823d96ef1c25a7bae68954da1ffde05cf138758ef54d053a94bce1d28f7ea235a66647b6db6eda0d5e78db16b66fae3f13f", 0x99}], 0x1)
r1 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r2 = syz_open_pts()
fcntl$lock(r2, 0x9, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x60002fffffff7})
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x3, 0x10, r1, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x10000, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
r3 = socket$inet(0x2, 0x0, 0x80)
getsockopt$sock_timeval(r3, 0xffff, 0x1005, 0x0, 0x0)
wait4(0xffffffffffffffff, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
mknod(0x0, 0x0, 0x0)
open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
recvmsg(0xffffffffffffffff, 0x0, 0x0)
preadv(0xffffffffffffffff, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r4 = socket(0x2, 0x3, 0x0)
bind(r4, &(0x7f0000000000), 0x10)
pipe(0x0)
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r5, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000001c0)=[{0x3}, {0x30}, {0xe}]})


r0 = socket(0x18, 0x3, 0x0)
getsockopt(r0, 0x29, 0x2a, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0x1000081, 0x5773c545, "0000000100e2ff01000000000000c00700"})
writev(r0, &(0x7f00000000c0)=[{&(0x7f00000009c0)="1913371a7464fd4f5a420c4fcecaf125779f43cb3f5bb4f0a59f3947abd5b4375a1b4778a2948a3e0e7aeb5a1750e9f58481cf1391b1088d3d404d9531144aa223745ae5f0c3d3f8f36d3d433fb342b0b14b8c6b28a6c4c187e58592c9b7ccedf9fac1b8290a6ac81df213bb92983b4d1716c45a8b1efdb117230033c3554d9a56e54274d728d99e1c9163c1111619dd7f72a3a7a3ad3cadbc82f1f604dee919b666d329ade6df06c9558bb560f39095d0bd9d4f8ab1805eaa706ac6f601c79942e6912e2578132f7bb6f17f0ee74202aeab12e3e0986ac686e20baf89e031f6f071a5211e52870730", 0xe9}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000400)=[{0x50}, {0x5, 0x0, 0x2}, {0x812e}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
nanosleep(&(0x7f0000000040), &(0x7f00000000c0))
execve(0x0, 0x0, 0x0)


mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x0)
ioctl$TIOCCONS(0xffffffffffffffff, 0x80047462, &(0x7f0000000100)=0x207)
r0 = open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSFLAGS(r0, 0x8004745c, &(0x7f0000000000)=0x3a)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000300)={0x3, &(0x7f0000000180)=[{0xc0}, {0x44}, {0x12e6}]})
syz_emit_ethernet(0x3e, &(0x7f00000003c0)={@broadcast, @empty, [], {@ipv6={0x86dd, {0x0, 0x6, "042729", 0x8, 0x0, 0x0, @remote={0xfe, 0x80, '\x00', 0x0}, @loopback, {[], @udp={{0x1, 0x3, 0x8}}}}}}})


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
fcntl$dupfd(r0, 0x0, r0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000001c0)=[{0x44}, {0x6c}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000140)=ANY=[])
select(0x40, &(0x7f00000000c0)={0x33b0}, 0x0, 0x0, 0x0)
r2 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$SPKRTONE(r2, 0x80085301, &(0x7f0000001540))
ioctl$VNDIOCGET(r2, 0xc4104603, &(0x7f0000000540)={'./file0\x00', 0x1, 0x3ff, 0x10000})
ioctl$WSMOUSEIO_SCALIBCOORDS(r2, 0x81205724, &(0x7f0000000240)={0xaf3, 0x9, 0x4, 0x8, 0x38356328, 0xfffffffb, 0x800, 0x10, [{0xba, 0x6, 0x0, 0x200}, {0x1ff, 0x8c7, 0x4, 0x20000000}, {0x80000001, 0x0, 0x0, 0x69b2}, {0xffffffff, 0x3ff, 0x100, 0x3}, {0x100, 0x0, 0x1000, 0x7}, {0x5, 0x6, 0xfff, 0x8001}, {0x101, 0x5, 0x8, 0x2}, {0x8000, 0x101, 0x1, 0x9e}, {0x1000, 0x0, 0xb7, 0x7}, {0xbea, 0x7, 0x100, 0x7}, {0x6, 0xe7, 0x10001, 0x6}, {0x7ff, 0x6, 0x800, 0x981808b8}, {0x8, 0x1ff, 0x9, 0x6}, {0x7fffffff, 0x8, 0x6e, 0x5}, {0x6, 0x6, 0xfffffffa, 0x2}, {0xd3, 0x7, 0x8, 0x5}]})
socket(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x18, 0x1, 0x0)
r3 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r4 = fcntl$dupfd(r3, 0x3, 0xffffffffffffffff)
ioctl$FIONREAD(r4, 0x8004745d, &(0x7f0000000200))
r5 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r5, 0xc0206922, &(0x7f00000001c0))


execve(0x0, &(0x7f00000002c0)=[&(0x7f0000000100)='tap'], 0x0)
r0 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r0, 0xc028698a, &(0x7f0000000100))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000280)=[{0x80}, {0x81}, {0x812e}]})
syz_emit_ethernet(0x56, &(0x7f0000000000)=ANY=[])


sysctl$net_inet_udp(&(0x7f0000000040)={0x4, 0x2, 0x11, 0x5}, 0x4, 0x0, 0x0, &(0x7f0000000080), 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000240)=[{0x15}, {0x1c}, {0x6}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


r0 = open(&(0x7f0000000140)='./file0\x00', 0xf8e, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000240)={<r1=>0x0}, 0xc)
ktrace(&(0x7f0000000200)='./file1\x00', 0x0, 0x40000730, r1)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000200)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
sendto$unix(r2, &(0x7f00000013c0)="0270dd965d8628daaf9a5e7f99e559d0aed90670d87bfe09c870a2c41d270d551a5f2eaad4aa22c502a0b525ed4f33aa3cb443b37c06e09925f9aaaa90626a2a8378dc0a943406b166a4a6228fd34873a6905aa56c6a9cac6f58b66cabf083f83683c74f0f3050b96895319ced011c295471e9ca5e3ae2f92dfe0c90392a47ea53850627c249733f70e10c1a4d7acf7deb", 0x91, 0xc, 0x0, 0x0)
getpid()
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
mknod(&(0x7f00000000c0)='./file0\x00', 0x2000, 0x40000802)
r3 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000080), 0x10000, 0x0)
ioctl$VMM_IOC_CREATE(r3, 0xc2585601, &(0x7f0000000640)={0x10, 0x5, [{&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffb000/0x3000)=nil, 0xfffffffffffffffa}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000ffa000/0x1000)=nil, 0x10000000000006}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ff8000/0x4000)=nil, &(0x7f0000ffb000/0x1000)=nil, 0x6}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil, 0xfffd}, {&(0x7f0000ff9000/0x3000)=nil, &(0x7f0000ffc000/0x2000)=nil, 0x2}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000ff8000/0x3000)=nil, 0x9}, {&(0x7f0000ff9000/0x2000)=nil, &(0x7f0000ffa000/0x2000)=nil, 0x5}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000fff000/0x1000)=nil, 0x1f}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ff9000/0x1000)=nil, 0x3}, {&(0x7f0000ffa000/0x1000)=nil, &(0x7f0000fff000/0x1000)=nil, 0xfffffffe}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000ffa000/0x2000)=nil, 0x3}], './file0\x00', 0xb})
setrlimit(0x8, &(0x7f0000000000)={0xfffffffffffff853, 0x8000000000000001})
mknod(&(0x7f0000000280)='./file1\x00', 0x0, 0x6)
kevent(0xffffffffffffffff, &(0x7f0000000040)=[{{}, 0x0, 0x0, 0x0, 0x3}], 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x6, &(0x7f0000000080), 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000080), 0x1)
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f00000002c0), 0xc)
r4 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000180), 0x1, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(r4, 0x80085762, &(0x7f0000000400)={0x3})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x1, &(0x7f0000000340)=[{0x0, 0x80, 0x0, 0xfffffff8}]})
writev(0xffffffffffffffff, &(0x7f0000000500)=[{0x0}], 0x1)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
msgsnd(0x0, 0x0, 0x401, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0xa}, 0x7, &(0x7f0000000080), 0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f00000000c0)="b10005010000009f0500070107000000331c13fecea70500fef96ecfc72fd3357ae30200004e3039d2d236acf20bf404be01000000f7c8cf5f882b297be1aa0504000051e2f0ad3ebbc257699a1f139b672f335c22db830c032bfa896443c32118210000720fd38bfb0000fd54c125191b1257aea8c500001602fbfe0c2300008abfba0900000008e37193f8343712050500b71dc000090005080000fca65361ba84913f0100"/177, 0xb1, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x1000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffc000/0x1000)=nil}], './file0\x00'})
ioctl$PCIOCREAD(0xffffffffffffffff, 0xc0187009, 0x0)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r1, 0xc2585601, &(0x7f0000000000)={0x0, 0x0, 0x1, 0x0, 0x0})
socket$inet(0x2, 0x2, 0x0)
mmap(&(0x7f0000ffd000/0x2000)=nil, 0x2000, 0x0, 0x10, 0xffffffffffffffff, 0x1)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x462, 0x0)
writev(r2, &(0x7f0000000000), 0x0)
r3 = msgget$private(0x0, 0x208)
ioctl$VMM_IOC_INFO(r1, 0xc0185603, &(0x7f0000000300)={0x7b, 0x0, &(0x7f0000000280)=""/123})
ioctl$VMM_IOC_RUN(r1, 0xc0205602, &(0x7f0000000380)={0x0, 0x0, 0x81, 0x2, &(0x7f00000016c0)={{0x40, 0x40, 0x2, 0x7, 0x3f, 0x0, 0x800}, {[0x1, 0xff, 0xffffffffffff8000, 0xe000000000, 0x2, 0x9, 0x3, 0x1f4, 0x0, 0x0, 0xe7, 0x800, 0xfffffffffffffffc, 0x0, 0x7f, 0x7ff, 0x2ac, 0x1000], [0x0, 0x0, 0x0, 0x0, 0x3ff, 0x81, 0x3, 0x6, 0x623000000000000, 0x6], [0x7fffffffffffffff, 0x2, 0xfffffffffffffff8, 0x6, 0x10002, 0x1], [0x0, 0x0, 0x0, 0x6, 0x2, 0x429b], [{0x2, 0x1, 0x1}, {0x400, 0x4, 0x3ff, 0x7}, {0x200, 0x5, 0x9}, {0x8, 0x6, 0x1000, 0x800000006e}, {0x0, 0x4e9280ea}, {}, {0xfffa, 0x9d7, 0x2}, {0x9, 0xfffe, 0x5b, 0x1}], {0x2, 0x70, 0x6ba, 0x100}, {0x2, 0x3}}}})
msgrcv(r3, 0x0, 0x0, 0x0, 0x0)
msgsnd(r3, &(0x7f0000000600)=ANY=[@ANYBLOB="020000000000c5c4cf3025"], 0xb9, 0x0)
r4 = syz_open_pts()
close(r4)
ioctl$TIOCSETAF(r4, 0x802c7416, 0x0)


openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = getuid()
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
r1 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
open(&(0x7f0000000140)='./file0\x00', 0xf8e, 0x0)
r2 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r2)
r3 = socket(0x11, 0x3, 0x0)
sendto(r3, 0x0, 0x0, 0x0, &(0x7f0000000040)=@un=@abs={0x0, 0x0, 0x1}, 0x8)
writev(r1, &(0x7f0000000340)=[{&(0x7f0000000000), 0x2cfea}], 0x1000000000000013)
mknod(&(0x7f0000000000)='./bus\x00', 0x3a0914c44f7b202d, 0x0)
r4 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
ioctl$TIOCSETAF(r4, 0x802c7416, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x0, "247497496ed3ffa429fdb9102575e414229eb682"})
execve(0x0, 0x0, 0x0)
chown(0x0, r0, 0xffffffffffffffff)
open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)


setuid(0xffffffffffffffff)
pipe(&(0x7f00000000c0))
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000500)={0x3, &(0x7f00000000c0)=[{}, {0x1}, {0x6, 0x0, 0x0, 0xff}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0xff0a, 0x0, 0x37)


syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, &(0x7f00000000c0)=0xfffe, 0x4)
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000), 0x10)
r1 = dup(r0)
listen(r1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1002, &(0x7f00000000c0), 0x4)
r2 = socket(0x2, 0x1, 0x0)
connect$unix(r2, &(0x7f0000000000), 0x10)
write(r2, &(0x7f0000000080)="04bdfa5d1d2873c63e3534825ba166e2fea9aec43050006123339a346f731573d8d508753f95b7688ad48b8cf6bbca325cebc37fc4e1dd543dbe2da6dd", 0xffea)
close(r2)


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
socket(0x18, 0x3, 0x3a)
msgget(0x3, 0x11)
r0 = kqueue()
kevent(r0, &(0x7f0000000080)=[{}, {}, {{}, 0x0, 0x0, 0x0, 0x0, 0x7}, {{}, 0xfffffffffffffff9}], 0x101, &(0x7f0000000180), 0x6, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x2, 0x0)
sysctl$net_inet_udp(&(0x7f0000000240), 0x4, 0x0, 0x0, 0x0, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)


r0 = socket$unix(0x1, 0x2, 0x0)
close(r0)
socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x35, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCLOCK(r0, 0x20004276)
seteuid(0xffffffffffffffff)
ioctl$BIOCLOCK(r0, 0x20004276)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x2, &(0x7f0000000000)=[{0x30}, {0x16}]})
ioctl$BIOCSFILDROP(r0, 0x80044279, &(0x7f0000000100)=0x2)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
syz_emit_ethernet(0x62, &(0x7f00000001c0)=ANY=[@ANYRESOCT])


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000401})


openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000500), 0x1, 0x0)
r0 = open$dir(&(0x7f00000000c0)='.\x00', 0x0, 0x0)
mkdirat(r0, &(0x7f0000000100)='./file0\x00', 0x0)
mknodat(r0, &(0x7f0000000580)='./file0/file1\x00', 0x6000, 0x0)
getpeername$unix(0xffffffffffffffff, 0x0, &(0x7f0000000180))
listen(0xffffffffffffffff, 0x0)
bind(0xffffffffffffffff, 0x0, 0xa)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$pf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000500)={0x0, 0x0, &(0x7f0000000480)=[{&(0x7f0000000380)='s', 0x1}], 0x100000000000038b}, 0x1)
r1 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmat(r1, &(0x7f0000001000/0x3000)=nil, 0x0)
r2 = shmget$private(0x0, 0x4000, 0x1c0, &(0x7f0000001000/0x4000)=nil)
shmctl$IPC_STAT(r2, 0x2, &(0x7f0000001540)=""/4092)
madvise(&(0x7f0000001000/0x2000)=nil, 0x2000, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f0000000500)={0x0}, 0x10, 0x0, 0x0)
setreuid(0xee00, 0x0)
r3 = getuid()
sysctl$net_inet_tcp(&(0x7f0000000200)={0x4, 0x2, 0x6, 0x17}, 0x4, &(0x7f00000002c0), 0x0, 0x0, 0x0)
setuid(r3)
r4 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r5 = getuid()
fchown(r4, r5, 0x0)
utimensat(0xffffffffffffff9c, &(0x7f0000000040)='.\x00', &(0x7f0000000080)={{}, {0x0, 0xffffffffffffffff}}, 0x0)
select(0x40, &(0x7f0000000100), &(0x7f00000024c0)={0x1ff}, 0x0, 0x0)


r0 = socket(0x2, 0x1, 0x0)
fcntl$setstatus(r0, 0x4, 0x40)
listen(r0, 0x0)
shutdown(r0, 0x2)


mknod(&(0x7f0000000000)='./bus\x00', 0x3a0914c44f7b202d, 0x504)
r0 = open(&(0x7f0000000040)='./bus\x00', 0x10005, 0x0)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000080)=0x8)
open(&(0x7f0000000040)='./bus\x00', 0x10005, 0x0)


r0 = socket$inet(0x2, 0x3, 0x0)
setsockopt(r0, 0x0, 0x6, 0x0, 0x0)


r0 = socket(0x18, 0x3, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfc01}})
semop(0x0, &(0x7f0000000080)=[{}, {0x0, 0x2ff}], 0x2)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}, 0x0, 0x0, 0x0, 0x0, 0x8000000000000000})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x1, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = socket(0x800000018, 0x1, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "1a1116fbd0f700ff000000002000"})
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000000), 0x9401, 0x0)
ioctl$WSKBDIO_SETMAP(r0, 0x8010570e, &(0x7f0000000040)={0x0, 0xffffffffffffffff})


semctl$GETPID(0x0, 0x0, 0x4, 0x0)
r0 = semget(0x2, 0x1, 0x204)
semctl$SETVAL(r0, 0x1, 0x8, &(0x7f00000000c0)=0x1)
r1 = accept(0xffffffffffffffff, &(0x7f0000000100)=@in, &(0x7f0000000140)=0xc)
writev(0xffffffffffffffff, &(0x7f0000000340)=[{&(0x7f0000000180)="7592c96e67e13eafb7918d85b2f5906c95c410e1399ed033e14069790a45aa6743849e869925ec6a2364fb3bfee6c34bb6ad07f4cdfe7a5bb760ec72f68b9ea6a9c6f4e4dc747d7245f51300cd9a71fb742127605a4953ff986c3b15b367fce223ab414cb88f", 0x66}, {&(0x7f0000000200)="1094074a513c421fd891ad3170e701418c823ad671d1661f11f4f7697b673f8f9922f429caee5a1d803188db8f5c0cb9722e60859aab1f2f4ee8feb0cd866a83046d47d713b1a4040d024dea73502a9cff07397a547b4b2b35db67ff20ddea29bf4906d05cee17339ba442e951b67e5532debd5c0983fc18c6f7a4277d9bbab373496ea68414db4c262601cad0db8591", 0x90}, {&(0x7f00000002c0)="7f95a8d7aa210312bf9e1b90647b46d975788a240bf775adc24c01692567", 0x1e}, {&(0x7f0000000300)="9372dce5da30", 0x6}], 0x4)
semop(r0, &(0x7f0000000380)=[{0x0, 0x7f, 0x1000}, {0x4, 0x3f}, {0x1, 0x0, 0x1000}, {0x1}, {0x4, 0x81, 0x1000}, {0x1, 0x7f, 0x800}], 0x6)
semctl$IPC_STAT(r0, 0x0, 0x2, &(0x7f00000003c0)=""/133)
r2 = openat$pci(0xffffffffffffff9c, &(0x7f0000000480), 0x800, 0x0)
ioctl$FIOGETOWN(r2, 0x4004667b, &(0x7f00000004c0))
openat$wsdisplay(0xffffffffffffff9c, &(0x7f0000000500), 0x400, 0x0)
getgroups(0x1, &(0x7f0000000580)=[<r3=>0xffffffffffffffff])
getgroups(0x2, &(0x7f00000005c0)=[r3, 0x0])
ioctl$KDGETLED(0xffffffffffffffff, 0x40044b41, &(0x7f00000007c0))
r4 = getegid()
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000800)={<r5=>0x0, <r6=>0x0, <r7=>0x0}, &(0x7f0000000840)=0xc)
setregid(r4, r7)
ktrace(&(0x7f0000000880)='./file0\x00', 0x4, 0x200, r5)
sysctl$ddb(&(0x7f00000008c0)={0x9, 0x8}, 0x2, &(0x7f0000000900)="42d48272c98b74ad81ea102764b42fe7d383dfc6000c729a9813271eb5d65f093fb5f68b1df0203762d5490cbb67fe0948b753402dde0635f764221da3f62a86810c8f65e31d9468f94f55962125ed35c8033218b30d084e81f51c4749c981d810d3469ce047007adb8b7c45c394fbd9ef6feb8727b2f088f039fce688c862fa86714f0c018b2b49568d661f3cb62a4a0d16321d568f44e3218e3acb9ba06f13cfb68a60e33e4e89a5889a917ff9a758c1d1274eb349f4180b842c2d3ae536783f74e174015fc2e6ef9cd5034b34b08e1b73b7883da3f8716b90", &(0x7f0000000a00)=0xda, &(0x7f0000000a40)="3d1aacc0893570f27d7e4f733a4a53952faada13ec41b1b4fee7c7dd8e018e7f3e52d77d6e78a59c00f707a9b53ba05ee670ecd5", 0x34)
setsockopt$inet_opts(r1, 0x0, 0x0, &(0x7f0000000b40)="ea8c1deb9c6106ee6512d50120c58e96362012a422813f0acfa8c112fb1823ff8a1a71a7d96b50ab17077731faeade0991ea06f442ccc17841c0c54f46", 0x3d)
pwritev(r2, 0x0, 0x0, 0x601)
setsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
semop(r0, &(0x7f0000000e80)=[{}, {0x3, 0x85b, 0x1800}, {0x2, 0x3}, {0x0, 0x1f, 0x800}], 0x4)
r8 = semget$private(0x0, 0x0, 0x0)
semctl$IPC_SET(r8, 0x0, 0x1, &(0x7f0000000ec0)={{0x8105, r6, r7, r6, 0x0, 0x0, 0x81}, 0x5, 0x3, 0x4})
sysctl$ddb(&(0x7f0000000f40)={0x9, 0x2}, 0x2, &(0x7f0000000f80), 0x0, 0x0, 0x0)


open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
getgroups(0x7, &(0x7f0000000000)=[0x0, 0xffffffffffffffff, 0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0x0, <r0=>0x0])
setregid(r0, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x538, 0x0)
setgid(0x0)
ktrace(&(0x7f0000000080)='./file0\x00', 0x2, 0x0, 0x0)


r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x0)
setsockopt(r1, 0x1000000029, 0x31, &(0x7f00000000c0)="b211010001a0946996b272d2dd3dc90142a84231a746e337b372e93320dff6669cbe7868de45ed3fc33719ca6df71ecec8a918458b1010a1f8c66653b276e180e9cb9b21f9982230f575295d48889c9a920796b2dd92fc8575680b37ba955d2c15e6d7c9198ed900ab006ddfb67869b51a2216114d1e8e85f593e74035f5bc054eb1dbddf42a00"/144, 0x90)
r2 = socket(0x18, 0x1, 0x0)
dup2(r0, r2)
setsockopt(r2, 0x1000000029, 0x31, 0x0, 0x0)


setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0xee00, r0)
ktrace(0x0, 0x1, 0x138, 0x0)


r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000140), 0x1, 0x0)
r1 = dup2(r0, r0)
sysctl$net_inet_tcp(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)
ioctl$WSKBDIO_GETMAP(r1, 0xc0105715, &(0x7f0000000000)={0x0, &(0x7f0000000040)})


r0 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1023, &(0x7f0000000080), 0x2)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000000c0)={<r0=>0xffffffffffffffff})
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd02)
r1 = open(&(0x7f0000000240)='./bus\x00', 0x0, 0x0)
pread(r1, &(0x7f0000000040)="3cd15db7c30016", 0x50cc00, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
syz_open_pts()
accept$unix(r0, &(0x7f0000000100)=@file={0x0, ""/503}, &(0x7f0000000300)=0x1f9)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCLOCK(0xffffffffffffffff, 0x20004276)
r2 = msgget$private(0x0, 0x0)
pipe2(&(0x7f0000000000)={<r3=>0xffffffffffffffff}, 0x0)
msgsnd(r2, &(0x7f0000000240)=ANY=[@ANYRES32=r3, @ANYRES8], 0x401, 0x0)
msgsnd(r2, 0x0, 0x401, 0x0)
msgctl$IPC_RMID(r2, 0x0)
syz_emit_ethernet(0x3e, &(0x7f0000000140)=ANY=[])
mquery(&(0x7f0000ff4000/0x1000)=nil, 0x7f7fffffc000, 0x0, 0x0, 0xffffffffffffffff, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETWF(r4, 0x80104277, &(0x7f0000000080)={0x1, &(0x7f0000000000)=[{0x84}]})


socket$inet(0x2, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000080)=[{0x30}, {0x25}, {0x8106}]})
syz_emit_ethernet(0x2e, &(0x7f0000000280)=ANY=[])


madvise(&(0x7f0000000000/0x4000)=nil, 0x0, 0x5)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
r0 = open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
ioctl$TIOCDRAIN(r0, 0x2000745e)
close(0xffffffffffffffff)
open(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
select(0x40, &(0x7f0000000000), &(0x7f0000000040)={0x7ff}, 0x0, 0x0)
munmap(&(0x7f0000001000/0x2000)=nil, 0x2000)
sysctl$vm(&(0x7f0000000000)={0x2, 0x7}, 0x2, 0x0, 0x0, &(0x7f0000002280)="7d8d7a23", 0x4)
sysctl$vm(&(0x7f0000000040)={0x2, 0x7}, 0x2, 0x0, 0x0, 0x0, 0x0)
getsockname$inet(0xffffffffffffffff, 0x0, 0x0)
r1 = socket$inet6(0x18, 0x2, 0x0)
ioctl$VMM_IOC_READREGS(r1, 0xc028756b, &(0x7f0000000a40))


connect$inet(0xffffffffffffffff, 0x0, 0x0)
socket(0x2, 0x1, 0x0)
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000001140), 0x0, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4f}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)
ioctl$VMM_IOC_CREATE(r0, 0xc2585601, &(0x7f0000001180)={0xdead4110, 0x0, [{&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffa000/0x2000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffa000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff9000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000ff9000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}], '.\x00'})
socket(0x18, 0x3, 0x0)
socket(0x1, 0x1, 0x0)
socket(0x2, 0x3, 0x0)
pipe(&(0x7f00000000c0)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
poll(&(0x7f0000000000)=[{r1}], 0x1, 0x0)
dup2(r1, r2)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)='\x00', 0x1}], 0x1)
socket$inet(0x2, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x1000000000000000, 0x2}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt(0xffffffffffffffff, 0x1000000029, 0x2e, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(0xffffffffffffffff, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbdf13b9fd812eaa4e713048e69931929648", 0x14)
r3 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
setsockopt$inet_opts(r3, 0x0, 0xd, &(0x7f0000000240)="ea08000000000000", 0x8)


r0 = socket(0x2, 0x1, 0x0)
close(r0)
r1 = semget$private(0x0, 0x4000000009, 0x82)
semop(r1, &(0x7f0000000300)=[{0x3, 0x3, 0x800}, {0x3}, {0x4, 0x202, 0x1000}, {0x3, 0x1000, 0x1000}, {0x0, 0x7a5}, {0x3, 0xff72, 0x3800}, {0x4, 0xdb, 0x800}, {0x0, 0x1, 0x800}, {0x3, 0xa, 0x1000}, {0x0, 0x2a22, 0x1000}, {0x3, 0x95ce}, {0x2, 0x100}], 0xc)
semctl$IPC_RMID(r1, 0x0, 0x0)
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x7}, 0x7fffffff, 0x2, 0x10000000009})
setgroups(0x0, 0x0)
close(0xffffffffffffffff)
socket(0x0, 0x2, 0x2)
syz_open_pts()
r2 = openat$speaker(0xffffffffffffff9c, &(0x7f00000006c0), 0x1, 0x0)
writev(r2, &(0x7f00000001c0)=[{&(0x7f0000000080)='O', 0x1}], 0x1)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000200)={0xffffffffffffffff, <r3=>0xffffffffffffffff})
r4 = dup(r3)
ktrace(&(0x7f0000001d40)='./file0\x00', 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x4, &(0x7f00000003c0)=[{0x8a}, {0x3c1d, 0x82, 0x5, 0xfffffff8}, {0xfbc, 0x3, 0x81, 0x2}, {0x2, 0x81, 0x7f, 0x7ff}]})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x2, &(0x7f0000000100)=[{}, {}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
mkdir(&(0x7f0000000080)='./file0\x00', 0x0)
rename(&(0x7f0000000080)='./file0\x00', &(0x7f00000000c0)='./file0\x00')
openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
recvmmsg(r4, &(0x7f0000000440)={&(0x7f00000000c0)={0x0, 0x0, &(0x7f0000000580)=[{0x0}, {0x0}, {&(0x7f0000000240)=""/90, 0x5a}], 0x3, 0x0}}, 0x10, 0x0, 0x0)
dup2(0xffffffffffffffff, r4)
sysctl$net_inet_icmp(&(0x7f0000000040)={0x4, 0x2, 0x1, 0x6}, 0x4, &(0x7f0000000140)="72d0f80404ffeb45029415f90bf076419fda860b138d4ab409a5c3fafc17ba210c1828d3fb7a2fae166f8d7a27675e40dd2dab61d2204603b7c9827f14714be66c97c226b3c54c97e424e2341ec22a8a7e4992392097b352748bc4919bc07801fd48cf32953d", &(0x7f0000000080)=0x66, &(0x7f0000000700)="389db228b581552b8c9df870921360769fc803728193c457120b58bba2e3f35e18677813e972cb980169142951b74e850f6a4db76443c4cc78978ecb58cf6c62bbfa0070c0459abccce3fe835ca191838bde0c1b0ca10414986056db7b94e4a533524ff3655c050802f0b564c777bba962058dda99f3868b95a115d6396bdea39bb026daabac24b91ac91a30a220e2ae166634d1", 0x94)
execve(0x0, 0x0, 0x0)


setreuid(0x0, 0xee01)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0x37, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)


r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
r3 = socket(0x2, 0x4001, 0x0)
r4 = dup(r3)
r5 = fcntl$dupfd(r4, 0x2, 0xffffffffffffffff)
close(r5)
socket(0x2, 0x1, 0x0)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)
shutdown(r2, 0x2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x7c}, {0x1}, {0x16}]})
write(r0, &(0x7f00000001c0)="d9537abde93d050cdd16b13f742a", 0xe)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000180))
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(0xffffffffffffffff)
syz_open_pts()
writev(r0, &(0x7f0000000440), 0x0)
socket$inet(0x2, 0x2, 0x0)
sysctl$hw(&(0x7f0000000000)={0x6, 0x1c}, 0x2, &(0x7f0000000380)='{', &(0x7f0000000180)=0x1, &(0x7f00000001c0), 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x3e}, 0x4000000000000004, 0x0, 0x0, 0x0, 0x0)


open(&(0x7f0000000140)='./file0\x00', 0x78e, 0x0)
r0 = getpid()
ktrace(&(0x7f0000001d40)='./file0\x00', 0x0, 0x1720, r0)
clock_getres(0x2, &(0x7f0000000000))


pwritev(0xffffffffffffffff, &(0x7f0000000380)=[{&(0x7f00000003c0)}], 0x1, 0x0)
r0 = socket(0x11, 0x3, 0x0)
setsockopt$sock_timeval(r0, 0xffff, 0x1006, &(0x7f0000000000)={0x0, 0x9}, 0x10)
recvmmsg(r0, &(0x7f0000000280)={0x0}, 0x10, 0x0, 0x0)


openat$null(0xffffffffffffff9c, &(0x7f0000000080), 0x100, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
r0 = open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
ioctl$TIOCGETA(r0, 0x402c7413, &(0x7f0000000280))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000280), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x3}, {0x50}, {0x6}]})
syz_emit_ethernet(0x1b, &(0x7f0000000000)=ANY=[])


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RESETCPU(r0, 0x82405605, &(0x7f0000000780)={0x1, 0x0, {[], [0x0, 0x0, 0x0, 0xffffffffffffffff]}})


r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r0, 0x0, 0xffffffffffffffff)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={<r3=>0xffffffffffffffff, <r4=>0xffffffffffffffff})
r5 = dup2(r4, r3)
sendmsg$unix(r5, &(0x7f0000000240)={0x0, 0x0, 0x0}, 0x0)
sendmsg$unix(r4, &(0x7f0000000080)={&(0x7f0000000040)=@file={0x170, './file0\x00'}, 0xa, 0x0}, 0x0)
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f00000001c0)={0x2, &(0x7f0000000100)=[{0x80, 0x2f, 0x3a, 0x4c}, {0x9, 0xda, 0x74, 0x40000004}]})
socket(0x1, 0x2, 0x0)
munmap(&(0x7f0000ffe000/0x1000)=nil, 0x1000)
sysctl$net_inet_tcp(&(0x7f0000000140)={0x4, 0x1e, 0x2, 0x11}, 0x4, &(0x7f0000000280)="808f643b27da5db78de01ede1f377436b1f46482478cc0654aaa06d4b692531b72b62dafa435ceb97d2b0ffbc05bc906aa654bb4ae3384fe6f5b54eb996eacaf981c99c21304668118159259aa6ac357c90e2974b2e2bba73f4133a5d70d759d3c86801b4d07a6a9297151cc28e2dbd90de9418cee114caf8de15b81540bec2bacf4b8991b2fa225e6c000000000", 0x0, 0x0, 0x0)
socketpair(0x0, 0x4000, 0x0, &(0x7f0000000040)={<r6=>0xffffffffffffffff, <r7=>0xffffffffffffffff})
write(r6, &(0x7f0000000140)='W', 0x1)
fchflags(r7, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f00000001c0)={0xc8, 0xffffffffffffffff})
r8 = kqueue()
kevent(r8, &(0x7f0000000000), 0x1ff, 0x0, 0x89c, 0x0)
kevent(r8, 0x0, 0x0, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x0, &(0x7f00000000c0)})
ioctl$VMM_IOC_RUN(0xffffffffffffffff, 0xc2585601, 0x0)
r9 = socket(0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
socket(0x6, 0x5, 0x0)
setsockopt(r9, 0x0, 0x20003, 0x0, 0x0)
r10 = msgget$private(0x0, 0x0)
msgsnd(r10, &(0x7f0000000340)=ANY=[@ANYRES8, @ANYRESDEC=r2], 0x117, 0x0)


sysctl$kern(&(0x7f00000000c0)={0x1, 0x40}, 0x3, &(0x7f00000001c0)="71f91e3471ac00ffff5a91347c9965e27fdf84cf71049c7afec370825f99bd95376e6bfd3d6b0c9c7ae6bc7bc98f426f697b538edc4468cc5221a05f6ba7e5ea17a5334c99d1f50e00"/87, &(0x7f0000000080)=0x3414, 0x0, 0xfffffffffffffc84)


r0 = kqueue()
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{}, {}, {}, {{r0}, 0xffffffffffffffff, 0xa1}], 0x0, 0x0, 0x0, 0x0)
kevent(r0, &(0x7f0000000000), 0x1f, 0x0, 0xb66, 0x0)


r0 = kqueue()
ioctl$FIONBIO(r0, 0x8004667e, &(0x7f0000002840)=0x8)


getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000000)={0x0, <r0=>0x0, <r1=>0x0}, 0xc)
r2 = geteuid()
setreuid(r0, r2)
r3 = socket(0x6, 0x8000, 0x8)
setuid(r0)
flock(r3, 0xe)
r4 = getuid()
bind$inet(r3, 0x0, 0x0)
shmget(0x3, 0x2000, 0x80, &(0x7f0000ffd000/0x2000)=nil)
r5 = openat$wsdisplay(0xffffffffffffff9c, &(0x7f0000000140), 0x20, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(r5, 0x80085762, &(0x7f0000000180)={0x2, 0x800})
chown(0x0, r2, r1)
sendmsg$unix(r3, &(0x7f0000000900)={&(0x7f0000000200)=@abs={0xe0732d0efd3c9e2a, 0x0, 0x2}, 0x8, &(0x7f0000000580)=[{0x0}, {&(0x7f0000000400)}], 0x2}, 0x0)
r6 = msgget(0x0, 0x280)
r7 = getpgid(0x0)
msgctl$IPC_SET(r6, 0x1, &(0x7f0000000940)={{0xfffffffb, 0x0, r1, r4, r1, 0x2, 0x5ba}, 0x8, 0x100000001, r7, 0x0, 0x0, 0x2, 0x9c})


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000140), 0x782, 0x0)
pwritev(r0, &(0x7f0000000180)=[{&(0x7f0000000000)="3eb0114a8082b59df8c0ba936c49b36e215183b08860a53f27f0ebf494b5a2045885a78660f89508bba10deaedb593baebfeed4f6c771745717484f9708b5eb5ce56e49bcfa18ca5cf8f86faf423b1ffac1f64488f8993757e3c1cf0605681fea677cd0fcedb39f2009a2c8f30e88021f1ec07a7249f9d2495e9290074e060bbebb900000000106d6cf12a1e9bcd30da0fdbda2aa0fc32623533ad4110dbfe8531a184a1ea632709f7bc008841087440aa4080e8257986a010fe60bbe4409c491b8623676b3447550024275d75b3480f20af2e97ab10a97b2c5ead1d2c914ad636913b41", 0xe4}], 0x1, 0x0)
execve(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000280), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x2, &(0x7f0000000080)=[{}, {0x4}]})
sysctl$kern(&(0x7f0000000080)={0x1, 0x44}, 0x4000000000000004, 0x0, 0x0, 0x0, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x18, 0x0, 0x0)
msgget$private(0x0, 0x0)
msgsnd(0x0, 0x0, 0x14, 0x0)
sysctl$net_inet_ip(&(0x7f0000000080)={0x4, 0x2, 0x0, 0x23}, 0x4, &(0x7f00000000c0)="84f016906d89c4c0646fc70a77bc4e5eb974f56bcb76d88d22737879962ecb59e786820e5894", 0x0, 0x0, 0x0)
r2 = msgget$private(0x0, 0x0)
msgrcv(0x0, 0x0, 0x0, 0x0, 0x1800)
r3 = openat$wsmouse(0xffffffffffffff9c, 0x0, 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r3, 0x80105728, &(0x7f0000000200)={0x0})
socket(0x0, 0x3, 0x0)
msgsnd(r2, &(0x7f0000000040)={0x2, "1df33699fb72338397098e5454c10006154e15f1b31f789e96f76daee6c959cce4e33b0c92d52ab85c4a74f6cc35b548537157e49c12251bc6e2e9b5607bb96982"}, 0x49, 0x800)
msgrcv(r2, &(0x7f0000001b00)={0x0, ""/250}, 0x102, 0x0, 0x1800)
open(0x0, 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x1, &(0x7f00000000c0)=[{}]})
syz_emit_ethernet(0x138, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCLOCK(0xffffffffffffffff, 0x20004276)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
close(0xffffffffffffffff)
socket(0x0, 0x0, 0x0)
readv(0xffffffffffffffff, 0x0, 0x0)
mknod(0x0, 0x1, 0x5)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x4d}, {0x48}, {0x6}]})
chown(0x0, 0x0, 0x0)
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


setreuid(0xee00, 0x0)
r0 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r1 = getuid()
fchown(r0, r1, 0x0)
r2 = getuid()
setreuid(0xee00, r2)
r3 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r4 = getuid()
fchown(r3, r4, 0x0)


r0 = socket$inet(0x2, 0x4000, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000100)=[{0x54}, {0x14}, {0x6}]})
syz_emit_ethernet(0xe, &(0x7f00000000c0)=ANY=[])
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
getsockopt$sock_int(r0, 0xffff, 0x0, &(0x7f0000000080), 0x0)
r2 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x0, &(0x7f0000000100)=0x20000, 0x4)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1002, &(0x7f00000000c0), 0x4)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f0000000000)=@file={0x0, '\x00'}, 0x3)
write(r2, &(0x7f0000000080), 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r3 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r3, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000440)={0x0, 0x0, 0x0, 0x0, "090000006f000021000000450000000000000100"})
connect$unix(r3, &(0x7f0000000000), 0x10)
write(r3, &(0x7f0000000240)="14bdfa5d1d34e2fecb284a6498307dcda9aec43050036123339a346f737850551408753f95b7688ad4c4e1dd5489e7bafc58d3e5823757ae8b630719ef187ccad995f13dbe19a6dd4e6902bd8297b0799b426aabe9fad9db6996571c6d9f8bb5d542c2148aa42be940970fe88d34d8f99afe7e7820237400000000008000000100"/138, 0xfc7e)


pwritev(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f0000000040)=':\x00\x00', 0x3}], 0x1, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x3d}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)


r0 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r0, 0x0)
r1 = socket$unix(0x1, 0x5, 0x0)
ioctl$FIONBIO(r1, 0x8004667e, &(0x7f0000001400)=0x1)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
sysctl$net_inet_carp(0x0, 0x0, &(0x7f0000000040), 0x0, 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
pipe(&(0x7f0000000140)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
poll(&(0x7f0000000040)=[{r3, 0x1a4}], 0x1, 0x0)
fcntl$setstatus(r2, 0x4, 0xc0)
write(r3, &(0x7f00000002c0)="7c84cf179279b50eda5dd1951a661d2e3a20851082c188f8b3d8a063d2025ff0d27a44bc29bdcac27fcb7aaa95cb2007be22c5553cd2f66a1f419a83d4275218a89d7a7803f069d851ff628dd309c40f6e3c932af00cb6219ae6e21d2c28d492cd5404b16dfa627d93b1e8ad2ea49d2344c1a3b234bd6f1c70fd4252844a6e6ab7b8997bc55fa22ce951ee038d289078b95510b0f2473ce1348434f0ec4a885ee84fd08fc50f08ca7991af3f8c322b496466f804c4b700cc9391855bd0ee339196de2b5ec2d8425c711d3f9e051eb055d45c693d7549712f5284a9fbca7d15c5bf1a9c8e3b3c1a43983056782e046c29e3d57082f7743b8bf6d994cd3c26c85609eaa11e6f7bc4", 0xfffffdaf)
execve(0x0, 0x0, 0x0)
sysctl$hw(&(0x7f0000000bc0)={0x6, 0x6}, 0x2, &(0x7f0000000c00)="ce55e9e3", &(0x7f0000000cc0)=0x4, &(0x7f0000000d00), 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f00000000c0)=[{0x54}, {0x1}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])
r4 = socket(0x11, 0x3, 0x0)
setsockopt(r4, 0x11, 0x3, &(0x7f0000000340)="02000000", 0x4)
r5 = socket(0x11, 0x3, 0x0)
sendto$unix(r5, &(0x7f0000000000)="b10005016000009f05000000070000007d9113fecea10500fef96ecfc72fd3357a068da3a5673039d2d236acf20b7804be38164991f7cccf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f45335c223e7d026ba8af630037282118000000720fd38bfbb770c1f5a872c881e2772ec5a10400000000000000361b1257aea8c5d0002012fbff0c230000880d6633c556ae9be371a3f8343712051eeab71d89000407000000800420000000", 0xb1, 0x0, 0x0, 0x0)


r0 = kqueue()
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000300)=[{{}, 0xfffffffffffffff9, 0x41, 0x3, 0x80}], 0x0, 0x0)
kevent(r0, &(0x7f0000000140), 0xe4a, 0x0, 0xa9fa, 0x0)


pipe2(&(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff}, 0x0)
readv(r1, &(0x7f0000000280)=[{&(0x7f0000000040)=""/124, 0xfd00}], 0x10000000000001bc)
write(r0, &(0x7f00000000c0)="c3", 0xffffffed)
readv(r1, &(0x7f00000023c0)=[{&(0x7f00000003c0)=""/4096, 0x1000}], 0x1)


sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x34}, 0x4, 0x0, 0x0, &(0x7f0000000100), 0x0)


syz_emit_ethernet(0xe26, &(0x7f0000000100)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaa"])
r0 = kqueue()
kevent(r0, &(0x7f0000000080), 0x101, &(0x7f0000000140), 0xffff, 0x0)
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x80206979, &(0x7f00000001c0))


shmat(0xffffffffffffffff, &(0x7f0000ffe000/0x1000)=nil, 0x1000)
shmdt(0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000000)=[{0x40}, {0x60}, {0x5ce}]})
setrlimit(0x0, 0x0)
ioctl$WSDISPLAYIO_GETSCREENTYPE(0xffffffffffffffff, 0xc028575d, 0x0)
open(0x0, 0x0, 0x0)
syz_emit_ethernet(0x76, &(0x7f0000000140)=ANY=[])
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={0x0, 0x3f8d}, 0x10, 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{0x7}, {0x5e}, {0xcc6, 0x0, 0x0, 0x4}]})
syz_emit_ethernet(0x138, &(0x7f0000000180)=ANY=[])
setreuid(0xee00, 0x0)
r3 = getuid()
open$dir(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
r4 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r4)
getrusage(0x1, &(0x7f0000000000))
setreuid(0xee00, r3)
r5 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffb000/0x3000)=nil)
r6 = semget$private(0x0, 0x4, 0x70)
semop(r6, &(0x7f0000000000)=[{0x1, 0x5, 0x800}], 0x1)
shmctl$IPC_RMID(r5, 0x0)


setrlimit(0x8, &(0x7f0000000100)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f00000000c0)={0x0, 0x0, 0x8a38, 0x0, "07160a009cef01098b748200"})
writev(r0, &(0x7f0000000040)=[{&(0x7f0000000180)="9532e1276d71a275de262aeded3cf8436721999a927b32c34022e666e465c24e1a6b4d26f8809c1930f9c42042ffc677be820f7bf51d8f506a039da017a15835a53e88", 0x43}], 0x1)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
r2 = dup2(r1, r0)
ioctl$TIOCSETA(r2, 0x802c7414, &(0x7f0000000080)={0x7fffffff, 0x0, 0x1, 0x7ff, "2cf9892af9a590e4cb52e88608007673ca9e5fd7"})
poll(&(0x7f0000000000)=[{r2, 0x40}], 0x1, 0x0)


open(0x0, 0x0, 0x0)
ioctl$VNDIOCGET(0xffffffffffffffff, 0x41946472, 0x0)
r0 = socket$inet(0x2, 0x3, 0x0)
shutdown(r0, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000000480)={@local, @local, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @broadcast, @broadcast}, @tcp={{0x0, 0x3, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1021, &(0x7f0000000000), 0x1)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
syz_open_pts()
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000100)=[{0x5c}, {0x80}, {0x16}]})
setsockopt(r0, 0x3, 0x9, &(0x7f00000009c0)="ec1a2ced0272c0a46f84cf9afe9de85aad871e620244dc9c23d8938d556d688183fed6afff6dd0abe3c7f5550a6a07f1c1c64d8c2df9633676ae51b8ab120e0d2183d7859fcfcefd7e61c3bf23b61280b2999f0b2dc4bfccb8cc03f27f4318c7c72466dd149a4727151123c63bd723b9805353f32dbbbac3b4b8356409b8d11dc98d57dfc1559526bc083147a011265b07263eb8419083a12ae5e44f5fba906f534a16e492d7b025615dafafe1c400c23f2bfc74ab7b2e880c17f1b67c6674a552676503ac5c64fe21f042faced39243454a8499d6d95bfbd9644349d2f075ffcdd72a70360b27eda969bc741167958ad80f803d3ea897d79bb2540c9080e8bc21d3beafaa624d97fcd30d059c7d5deab07da8c3b699bc2d3168e3e9dabf200eed211e93be1d8cbcffd9da61e91db47d12934d462f2480e47810cc7792f13acab8e5b2517bb5dafaa9f43d446f03fb5aaa186a4f4d847276e442dacd630d9b2efd53eaec6609d8a160642d6196f83a05792af1d7132276f90de0670717e884be7a820bfb585cde1b8957118c1b2f87bbbc75124771b9a7c393ddb632bddabf4de34b57009b4daa8115d53615a77d0a9fc078332ad7b43fa723227043ba0e06a6bbecd45147f85ccb1761dbf8a1115aa0e16e1e7c727793781a6df99e6483f602d74612dde7d7e82336c5582e4d936c67d0eba0d70c1f8969f3c2844f3a9799818d39b6afaebc2f14429e70e0b08cffe748480bb60b3c73276aec725e7cf8af311120d9ddc8aeebf469d70414d5fe50e9210ee592d202109d7d40e030c66b6faf99fb915127b330926aa9afddafe384d2475d80843162218c15bfcc1cbb374ce774d7066dc10d28e1fab3ddd86a4b6849b61bb5ed3143a5fc7af4f183cfff79bd0450daf044e4cd59c0023572721fd94585c80f38f5bb9355c9da10bd9e2a3da83e94fbb11640b62524569cdae8d05a71e7825684c55b19624d18c8b559bf44d2c4275547c51edb55b847e8ab1bdec886f90fe0010d01bc10844dc6e5b0732f232d384de0d2079e50804cb59ab08bdefe2816ff536e6a7812081b14b8e8dd03bfb1e7d033aebc45eac7a27165133b5ad8ad8aad612adc453c2c3455ed472432524ead4cb812703b9418ade640310f3bf57c96bab0b623a9c558ad21d6044bfd1ec14b7e1c9efaefb90639b4f1975cf647bf1a39cffabf8acb45beb5405d97a0a6a5060c2ae67ffa1e5f23c4699a1822fd651d9abd067e3b5a49de9db8988a5a566ad4af740abdffa5d55455dba0837c8c5051970915c5c946698c79c863acea922b371a8aeecfb63d49071f7fc19a84e8c1a9e3483689b69b68ff2400e884fe58c5d16fbd8e9efc7ac67a795fad93c5befdb5ff696a3b18e8351f4f0094a09c4309050b385eeb1d456896d9e115372eec993f80bf9a79cb322e377e72746fd8c24980169ba018eb8de83f31bc36f27dc337e512a8e7ed63690c37e62b741ae116c581dcf45a86a75c9e082cf6fea1c413c16d2abe30a6e95502114b4ac32811133b8e74a1879e47e08bb1db6e6a70b2ce0a62238a3c2763e37b8b88ef8931de838175c9e78b29d4cd69b59f65cd5d7fe9eeb1bc18675aa6650ad18140614a4a331d3ffa626bf272a4324ef273b6e9747b64506782771a5b7ce5b5851c460f331687e2a2bebc455733ef196928ace87e31efabbc4bec0f5cccfc1624dab70d81f9bfc716a5565f6ab14e46d88e4b51cdb5747abea000339a766eb8fd485e2751c90ed7a6444e3894d8ea6b92c1206de6220b193e00f4f240e6207853780b52e06d8094f19600509ff088cb126642cee1bf44a005dcf6ba7b39a6b1f58a7b7bc541eb8d2cd7c7c2421bb1f5e3010a3ca1db25a583e9f617972ca964eddc6a2ec5f14c0e4dfcc6cff76aa1b7abfbd5a2263a293ae1e30cffb150fba06ac34c6d3064b5db95d14781112a85ecf19c2ae30a8b0e2fd7f3c3d0660001bea2e68affafce963a69ce88a2efbe12f012b3509c3fc6cad8efb18615b8cb515324f7beb30736c7e36d057d67d361b599a71d783c57f330c0b19d7e47109df2a55ac6c04d8e2437fcd5a3cbe62ebbefc17fbef3d90ae71659841d2491b9b48fecfe7019a6a7388a24efc95e00d870cbc3939eccdbb3a21aa6e0bb09177efe646434f56e0a00115a25a32cd0ab2f8aed3ff815128f3aa11664dd271fb6eb07efaccbfbea4127a691b45e937af23442b32010a31e4039c2f7eaf79713dfaa783b00f678a2a77fabe030dee2d4135dffc283450314991b5f31cccee775920125a1202a206bae646fba40d582fcf88d99902c5ca0b6ca316849c7837cbfaaeb1e626c1865b60cfacf0deb24317a6b2d04092eb5a1884f13703bc1f99a7472f8f2cf5d3bd6db61b07b543e797650cdf5437d2dc28f6871821299ea6ea92de04a4fed3e89314e56c0d969f9a83dc752157a53910a272440367cd6f3143dfd714b388d7102e0093e0d282610bbf0109736eb028160b45a8e220c88f2a667e3b97cbe2650dfdaae00f13a84bd659d01614a6d17cd8de1dded3cefbc1671903c2c782ba0121ab0239488f9692c0a34868a673a4dc73b174db7f79b2150545fc61569a2fab1696eca700a48999d2f45cfa8b795e3cdc216e588c98bc41f31d3d415fa7d7816fc5056f4079cf42263ce3814828af0b4866cef4c6ea910bf1dcc3d7731334a85b7d71b7b0c1df6769f4a3f02c69c13466e22a258e71f7590d41a491297d768f60b20d04e41607f89bdc0696cdc9aaa7b591178019cdab636218675011ef1e4e7f00ffc98d637ed2ebcb52a3e0bd03bdedab31558e2cf0840ed6b0e2d531739f5789527d30ecdb73fc29ddfec2f5e29a024527d4804d70015c24105c862883f27791f6861c4e9f0f5f823ceb71b3158ce6d581705f321fb355ae3e411fe3d1271944e2e6c1173ec92b93c776ae868ed1fd10e892d7b9e53ed4a2fc6403ef7274c3854bdf5ef81bf1119b35f9f8634668e4f36497d1224ee7a59385c4da61bf918c33020e69923b1684b017f039fe8bd702b0fe091961d01d14a8385241c7136bcb071ad16f3005d6e5398be71bae4545a29d518553d0308ed0db32ae97a029d09be10ca2203c8505473a92ea611595aaefa1fbaecad722d4e7133526a917ebad49bc4c0dd71571a8bb91d7e029bae1e4087a7d92e011fff70ab7c60155c6e3c544391c00f28efba2c7268d73b325c45ef9700e53b44498eb1da3710d7dfffbb647600b42dc359167a8b120ffa0cdfb601b6e190eb745ed45f9e250418060870e1ffbcaed7df5c1ba4732136f98c51cf1d98b88e64e8e86701cfb7aec3a376d9ef00da4c9756a2af0edd5ac6fd2c4079870092e2df0278746678fd6cdb5eac854668fd363bb897e153175a99a7bbbee987f9a11d5cd6563a23f8882df72f40fad7204ea4698bff4a0c06d10ded5f6a3972d3fe29a5b21450b2cd1aad2814b496bdc9f345239dd7a13733dc5be17f5ed05f1fa49893adc7e7822847be2924896f56ff5014c188a195901daa48d5f4823241408a112f8682173858f695af36e534d518a322e54bf7959fbbea7e27b270b4aa77e6eaa82f9d808f47bb7a6e129b53500f684f269bc4d34c7243a3ec72897b1576ef0250077990380001142eebf0c7a710b37a6723618c9114c96310e842e64b95141490a7e89d090f814f8a11c64747b3c08c9c32a028299fafa4dd21cc16fe417d22516f57b77150e22228856b67f2a769f4a7c9f26e6c8a46b4870db67af29e7f032a5cb4cd3c37fc6c97e4ce2f7ed5270d2fd0c2e8f35f6ff3165f1c60cbe5aa7c2008deec943bcc114ce486b671c690f3192772256a652db9335c7b42e5f4137058478c51fb6f8f2a02fd79769390408a32b75e2f3383a74a5d11e1fa9b66e0e1aade8973df14a2ce65462b3ee3b2eea1042fe4f16ad016674f948a405dab31f860e953e5a352e5d4f9294f7973bb4108ed7180f2f33876628cc86d494d70ca54fc99c812447fc5ad356a2c5d17da36cd73a8220549567f04afdd09304e4eeae17b8622d1380d75dfc07e25962add55243c8062150f71e7bc81e656b5df4898fbd0e6c0510260af8783dddd308dfff6abe6aa86d1438460dd2e083b6d1dd3385468059d510d918e5fba907d977aaf4d57e3867858405e6df5f9e9b4ebc836638cf61737c4b8ab0e32968c390b60a53241d3c2b8eccaee01c93d8c5d0eb703a970f5919bd89e67d10818e0e1c1abe32a4e29ef29df68550836e5c0e6006f35ae9d6088f18128bcb19f799d0cb91aea0a496caa299579b0228f2ecf7f9d11e1dc9453198096bf847d3f7c042a480a50f15495388a8a187fadc65357f9ae991753d5b5b559021a3af69f861538c3499e848bdc9d2f592feec89aa2b79c6e9ea2eb6554f6bf5a5d3fec2e3a9511df49f271cf2c731cc18d238b9c923033cf0e10c7fe53da01f15ccbeb56ce1c3aa7c54797be9794b90cc345049bf90c58f2a77d0146b3603abed244988fc91ecfe27ed14d9f77c9922e66d6f59f47fd77c82d8fc3deffcb238168c1adf706bf30fb9f89c300be973f6163674feb5362a2384ddec883b12a79293dad102a4fa9f450b521f75139e8ff0762e41c5915ce5ad4602ae654abddbc651665c2a01bb3f065d59743dd6e2370e5e197afc7ff96fdd89fc5662a524a97bdd045c26e74b586f164a2d4f5bbc53feafbec3eb19cf7470f3c1ec1499b218985f9a8a9afc4ccce8d3edaa2858c14e58c86c28554b16810d32a297f2f6a66100e6ed2bd2de0cdf680218d43f09538e7292b74a63bc2c4d66e8a7aead2b88058bf1372f784c6e1aaa68b4f18b46fd4ccf429d32d771e3b6688178f9b94585fa7fd8c89f33905266a6fcddd4a75eed56683155148476cd34f1e3168b2c9269a9bca3cdcb6b51d6c94a1a582b3005f61e033f24f7d2fde5d751044378494e67fe941c112eed2c8309330374489af2e37fcbcae9e8b3f328b171223ed756057d73a0d99f143d7ea9366d583ae82c9db2335fdc4845abb8acf9fb99b392339f5a6e72990efca455438a25e7ed10639ec0a3761acd10f00fbd1c33ef50e12ca87569edd52cdf456917db9f2f2676dea39c501f2db02df8f70abcc3ec2ec78020d7e960d483861fff2be212bbd3472ecd993fc8abf9062ebfc606b0861fd21970915cfa6ada9b42340ed0de0bf7bce800a430a713fc1394bdcc09044bdde25ce69c8d6e72f1f73b48d57ffaf269c1a783187b9d7eb542395f1a2940811b9439f6bae30c4c2018083dc7db29810a238df3c425b28eec77848e5503ca2b26c8107da60523cfedea54c4b19043a57dcf61b299f8cad87c5aee8df21233aad388b3d1068f6ce01462d555e026e95e3718ded29e906a0e48e908bd4615c9364478c8194ffa49dbe717c617bbbcb3e425f39e2d035074a90e0db1ea7f771ef3c4755b8636634750fbdfb5ea9ef22795fed5f4bb3875e01c16e270a24ec52191dd9bb19c8f62b18579ea3fa436110a2d505cae6267e6478a5f7ff6195ef96c0f0245ec4367050cccf82fed6a08352cfaa36f2dc5c4800cb92eb5a501a87fc49ff81c56aa294c90419e971fd18ab4dcf1e6064b1e24f555da9b473251c9e2a29d8a6cb84df429627a9a8810463e722b59654a9d8d852d75c39693d4248b2ec3d13fb74f15f95026f9be54c3f2a8ff6c7f2cb21f0dc", 0xfbe)
write(r1, &(0x7f00000001c0)="d9537abde93d050cdd16b13f742a", 0xe)
syz_emit_ethernet(0xd7, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0xc9, 0x0, 0x1}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x1, 0x0, 0x7, 0x4, 0x0, 0x0, 0x0, {[@generic={0x2, 0x6, "96c72963"}, @sack_perm={0x4, 0x2}]}}, {"d1c2f0bfe2d0786ca28e44289f59aba04d62ff16e6bb47f1cd981d0cf5f225560531db5a3a6c3cb3d5ac50e0eec7423f3ef5e3c4a13f81f14f843a32b529e4649b57d581159522ddf03a6cabf358af4e1ae7ab79a9aac6417859ae29d8de08ba3da1e6387381a61f166b78d7ae58ccd15a08555c8e7db3e261cbba4f565ff3567edfcacd1a43a2f80b44a3727c2f46723f3826d9842357f4d4"}}}}}})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000140)=[{}, {0x2}, {0x8001, 0x3f, 0x3, 0x7}]})
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r2 = syz_open_pts()
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x6381)
open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
r3 = socket(0x11, 0x3, 0x0)
sendto$unix(r3, &(0x7f0000000000)="b10005136000009f05003e0800000000331c13fecea10500fef96ecfc72fd3357a068d02bc31a3a5673039d2d236acf20b7804be38164991f7cccf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f4d335c223e7d026ba8faff0037720fd38bfbb770c1f5a872c881", 0x6f, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000000), 0x3, 0x0, 0x0, 0x0, 0x0)
close(r2)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
syz_open_pts()
ioctl$FIOASYNC(r2, 0x80047469, &(0x7f0000000040))
writev(0xffffffffffffffff, 0x0, 0x0)
readv(0xffffffffffffffff, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, 0x0)
sysctl$kern(0x0, 0x0, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1c, 0x0, 0x0)


mknod(&(0x7f0000000000)='./bus\x00', 0x3a0914c44f7b202d, 0x504)
r0 = open(&(0x7f0000000040)='./bus\x00', 0x10005, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$TIOCEXCL(r0, 0x2000740d)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)


sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x13}, 0x4, 0x0, 0x0, 0xfffffffffffffffe, 0xffffffa2)


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="c700100100000010", 0x8)
socket$inet(0x2, 0x2, 0x0)
socket(0x18, 0x3, 0x0)
sysctl$kern(&(0x7f0000000140)={0x1, 0x49}, 0x2, &(0x7f0000000180)="722c96fc75cb81e14deda33e1d57b5e5a255616bbc828ef9aa1d2e49df9f356873eb63766b3900b8a401969a", &(0x7f00000001c0)=0x2c, &(0x7f0000000200)="445b3bf608703b14cef80d8ac0b73ef5e277642e285fa85018509841c5be", 0x1e)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x5900)
r1 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
socket$inet(0x2, 0x2, 0x0)
close(0xffffffffffffffff)
r2 = socket(0x18, 0x2, 0x0)
setsockopt(r2, 0x1000000029, 0x4, &(0x7f0000000000)="5ab7", 0x2)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
r3 = syz_open_pts()
ioctl$FIOSETOWN(r3, 0x80047476, 0x0)
msgrcv(0x0, 0x0, 0x0, 0x0, 0x1800)
syz_emit_ethernet(0xa2, &(0x7f0000000600)=ANY=[@ANYBLOB="aaaaaaaaaabbaaaaaaaaaabb806d4942ac284463f454a0d78e1422d1e4c8dc984f9fcd616427695bc28e4f4fb208e0d6531b93ae0c0d2e2e0a3196930400f1b96629c1fc11c8c38aa6ea7b8f5393dbe271cae3dfba2c1d4f3e4141061eec7cb8dda7f56a89b0cb56d8ef706aa2197a408785653f3c78abfe32f499a515960a205c42b8b7ebf3b258f872dc3be997532a86b16d6b914d614f"])
sysctl$kern(&(0x7f00000006c0)={0x1, 0x14}, 0x2, &(0x7f0000000700)="0c691090fd04f87849f8c3827b0d7aa27976cb2395295bb820f2cf3825d6e8e1d52d4d543d2024e5f0ec61068250e0b277482348a53f5f0a810e011355017b7301ed05ec7a0ef90de7ceb87f56eebb2998be8805102983668afac5dc431997e0570952f6dedde7d65c3cd4223b0242e09b55d2a453439709d3c8d71fb2a7f4ac3a1a69c5a4124fc02df103d410029f035232", 0x0, &(0x7f0000000800), 0x0)
r4 = open(&(0x7f0000000900)='./file0\x00', 0x0, 0x184)
ioctl$TIOCSCTTY(0xffffffffffffffff, 0x20007461)
getsockopt$sock_cred(r4, 0xffff, 0x1022, 0x0, &(0x7f00000009c0))
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000a00), &(0x7f0000000a40)=0xc)
setgroups(0x4, &(0x7f0000000a80)=[0x0, 0x0, 0x0, 0x0])
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
readlinkat(0xffffffffffffffff, 0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = kqueue()
r2 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
kevent(r1, &(0x7f0000000280)=[{{r0}, 0xfffffffffffffffe, 0x10b}], 0x9, 0x0, 0x0, 0x0)
kevent(r1, 0x0, 0x0, 0x0, 0x7ff, 0x0)
kevent(r1, &(0x7f0000000080)=[{{r2}, 0xfffffffffffffffe, 0x8b}], 0x1, 0x0, 0xbe5, 0x0)
dup2(r2, r1)


mknod(&(0x7f0000000500)='./file0\x00', 0x1000, 0x0)
symlinkat(0x0, 0xffffffffffffff9c, &(0x7f0000000140)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/file0\x00')
r0 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x8020699d, &(0x7f00000001c0))
syz_emit_ethernet(0x126f, &(0x7f00000000c0)=ANY=[])


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f000050c000/0x2000)=nil}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000158000/0x3000)=nil}, {&(0x7f000003d000/0x1000)=nil, &(0x7f000064e000/0x4000)=nil}, {&(0x7f00007eb000/0x3000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000157000/0x1000)=nil}, {0x0, &(0x7f00001eb000/0x2000)=nil}, {0x0, &(0x7f0000770000/0x1000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f00000e0000/0x1000)=nil, &(0x7f000026f000/0x3000)=nil}, {&(0x7f000050a000/0x3000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f00000f8000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffe000/0x2000)=nil}], './file0\x00'})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0xa, &(0x7f0000000480)='\x00\x00\x00\x00', 0x4)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000340)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x1d}, {0x20}, {0x4000006, 0x0, 0x0, 0x8000}]})
writev(r0, &(0x7f0000001400)=[{&(0x7f0000000240)="e049c0d37348a45d6bee0bf84a9e", 0xe}], 0x1)


mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x4001, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
r2 = socket(0x2, 0x1, 0x0)
connect$unix(r2, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r1, 0xffff, 0x1023, &(0x7f0000000080), 0x4)
shutdown(r1, 0x0)
recvmsg(r1, &(0x7f00000007c0)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
socket(0x11, 0x3, 0x0)
r0 = socket(0x1, 0x1, 0xff)
r1 = socket(0x20, 0x8000, 0x0)
dup2(r1, r0)
sysctl$vfs_nfs(&(0x7f0000000040)={0x7, 0x4}, 0x3, 0x0, 0x0, 0x0, 0x0)
connect$unix(r0, &(0x7f0000000000)=@file={0x0, '\x00'}, 0x3)
socket(0x11, 0x1, 0x21)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x2, 0x0, 0x0, 0x0, 0x0, 0x2}, 0x20d)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
r2 = openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
getsockopt$sock_cred(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000500), &(0x7f0000000540)=0xc)
r3 = openat$pci(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$PCIOCREAD(r3, 0xc0107008, &(0x7f0000000540))
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
semget$private(0x0, 0xb974d795ab34cd7e, 0x800)
r4 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSTAT(r4, 0x20007465, 0x0)
r5 = socket$inet(0x2, 0x2, 0x0)
getsockopt$inet_opts(r5, 0x0, 0x21, 0x0, 0x0)
ioctl$VMM_IOC_INFO(r2, 0xc0185603, &(0x7f0000000000)={0x97, 0x0, &(0x7f0000000180)=""/151})
close(0xffffffffffffffff)
r6 = socket(0x800000018, 0x3, 0x0)
setsockopt$sock_int(r6, 0xffff, 0x1001, &(0x7f0000000000), 0x4)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmsg(0xffffffffffffffff, &(0x7f0000000280)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000040)=ANY=[@ANYRES64=r6], 0x11}, 0x5)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x100000000000000, 0x10000000000001}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
openat$wskbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xffffffffffffffff})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x100000000000000, 0x10000000000001}})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x0)
mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
link(&(0x7f0000000340)='./bus\x00', &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r1 = socket(0x18, 0x3, 0x3a)
r2 = dup2(r1, r1)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r1, &(0x7f0000000480)="b437ab93c964ca79", 0x8)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{}, {}, {0x5, 0x0, 0x0, 0x3}]})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000007, 0x0, 0x0, 0x0, 0x3d)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
sendmsg(r1, &(0x7f0000000380)={0x0, 0x0, 0x0, 0x0, &(0x7f0000001ac0)=[{0x10}], 0x10}, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
close(r1)
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)


sysctl$kern(&(0x7f0000000000)={0x2, 0x8}, 0x2, 0x0, 0x0, 0xffffffffffffffff, 0x4)
socket(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
getsockopt$sock_linger(0xffffffffffffffff, 0xffff, 0x80, 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x7}, 0xc)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000140)=[{0x84}, {0x84}, {0x812e}]})
syz_emit_ethernet(0x56, &(0x7f0000000340)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x2}, {0x14}, {0x6}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


r0 = syz_open_pts()
read(r0, &(0x7f0000000080)=""/179, 0xb3)
ioctl$TIOCSETAW(r0, 0x802c7415, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x0, "ae2f00000000000000000000000011000200"})
syz_open_pts()


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000540), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f00000001c0)=[{0x1}, {0x1}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000400)=ANY=[])


open$dir(&(0x7f00000000c0)='./file0\x00', 0xae828e137847f62, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
r0 = socket(0x1, 0x4, 0x0)
close(0xffffffffffffffff)
connect$inet(r0, &(0x7f0000000040)={0x2, 0x1}, 0xc)
r1 = socket(0x18, 0x3, 0x0)
setsockopt(r1, 0x1000000029, 0x31, &(0x7f00000000c0)="b211d7170d816685c8e360f2fa41c1a0946988b272d2dd3dc90142a84231a746e337b372e93320cff6669cbe7868de45ed3fc33719ca6df71ecec8a918458b2c10a1f8c66653b276e180e9cb9b21f9982230f575295d48889c9a920796b2dd92fc8575680b37ba955d2c15e6d7c9198ed900ab006ddfb67869b51a2216114d1ece85f593e74035f5bc054eb1dbddf42a", 0x90)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x100000000000000, 0xffffffffffffffff})
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
writev(r1, &(0x7f0000001680)=[{0x0}, {&(0x7f0000000480)="1e226e9f857bfbb543b630b09d09214468401a21e5fbe9c33132f860089d", 0x1e}, {&(0x7f00000004c0)="e9862d50cda1ad305321428d2c6ca9e1af202279139624dbe3961effe54a37ea5c864d2636c2d564c7601d7104578d25cc4020b73b2bbee0bb26d83a3ea41b62d1a08685a4bfb55fa55da76ce0a6dc52", 0x50}, {&(0x7f0000000680)}], 0x4)
setrlimit(0x1, &(0x7f0000000000)={0xfffffffffffffffd, 0xffffffffffffffff})
ftruncate(0xffffffffffffffff, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
getpid()
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r2 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0106924, &(0x7f00000001c0))
r3 = kqueue()
kevent(r3, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r4 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r4, 0xc0206921, &(0x7f00000001c0))
r5 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r5, 0x80206913, &(0x7f00000001c0))


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
mprotect(&(0x7f00003e0000/0x3000)=nil, 0x3000, 0x0)
open(&(0x7f0000000200)='./file0\x00', 0x70e, 0x0)
sysctl$vm(&(0x7f0000000300)={0x4}, 0x2, &(0x7f0000000040)="c06d154be3aee5f8787f8b9cda7554335b763bb5deea5ccecb4d1b57a9f6fa18e47fc7b119db587e58811e666e84a806495b45c36164bd5b135280243ed0a01466056e93082876ba33ee8cf2b0b3907f236f38175101000000d7e39544aea098d19ee63d03cbf92380dbe904538135f09e408bbe17a54a364b04ee64b0ad54e6d4e38114ced38c328aff2e224239ba29eb0796e8c3e8344a2cd9e663bb21035ebf391872f3015c164556e4a5b966122c56edd85fc996f12fa1b92e47aa", 0x0, 0x0, 0x0)
open$dir(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
r1 = getuid()
setreuid(0xee00, r1)
r2 = semget$private(0x0, 0x4, 0x0)
r3 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
getsockopt$sock_cred(r3, 0xffff, 0x1022, &(0x7f0000000100), &(0x7f0000000140)=0xc)
semop(0x0, &(0x7f00000000c0)=[{}, {0x3}, {0x4, 0x2}], 0x3)
semop(0x0, 0x0, 0x0)
getuid()
semctl$IPC_SET(r2, 0x0, 0x1, &(0x7f00000001c0)={{0x1fe}, 0x0, 0x0, 0x1})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$TIOCSETA(r3, 0x802c7414, &(0x7f0000000080)={0x8, 0x0, 0x0, 0x1603519, "1a000100", 0x3, 0x81})
writev(0xffffffffffffffff, &(0x7f0000000000)=[{0x0}], 0x1)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
msync(&(0x7f0000ffc000/0x2000)=nil, 0x2000, 0x3)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000100)='./file0\x00', 0x2000, 0x0)
link(&(0x7f0000000240)='./bus\x00', &(0x7f0000000280)='./file0\x00')
ktrace(&(0x7f00000002c0)='./bus\x00', 0x1, 0x0, 0x0)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000029, 0x3e, &(0x7f0000000000), 0x0)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x84000000000000})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x3a)
r2 = dup2(r1, r1)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r1, &(0x7f0000000240)="1287004ba50431a7", 0x8)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000400)=[{0x5c}, {0x7, 0x0, 0x0, 0x81}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f00000001c0)=ANY=[])


mknod(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, 0x0)
open(0x0, 0x0, 0x80)
socketpair(0x2, 0x3, 0x0, 0x0)
syz_open_pts()
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
syz_emit_ethernet(0xf0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
sysctl$vfs_nfs(&(0x7f00000000c0)={0xa, 0x2, 0x2}, 0x3, &(0x7f0000000240)="0003521e", &(0x7f0000000100)=0x64, &(0x7f0000001900), 0x4)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
sendmsg$unix(r0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="28000000ffff000001"], 0x28}, 0x0)
r1 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r1, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r1, 0x0)
r2 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r2, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
close(r1)


sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504000004000000400001000000331c13fecea10500fef96ec0c72fd3357ae30200004e301ac20008acf20b6604be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abeba221554f4e0f668246c09", 0x9d, 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000080))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
madvise(&(0x7f0000000000/0x1000)=nil, 0x1000, 0x4)
setitimer(0x0, &(0x7f0000000080), 0x0)


pipe(&(0x7f0000000100)={<r0=>0xffffffffffffffff})
fcntl$setstatus(r0, 0x4, 0xc0)
r1 = getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r1})
pipe(&(0x7f00000001c0)={<r2=>0xffffffffffffffff})
setreuid(0xee00, 0x0)
r3 = getuid()
setreuid(0xee00, r3)
ioctl$WSKBDIO_GETMAP(r2, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r4 = fcntl$getown(r2, 0x5)
fcntl$setown(r0, 0x6, r4)
close(r0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x4}, {0x24}, {0x6}]})
syz_emit_ethernet(0x62, &(0x7f0000001a00)=ANY=[])


mknod(&(0x7f00000000c0)='./file0\x00', 0x2000, 0x40000802)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000540)=0x8)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x0, 0x0)
ioctl$FIOSETOWN(r1, 0x80047476, &(0x7f0000000100)=0xffffe001)
setsockopt$inet6_MRT6_ADD_MIF(0xffffffffffffffff, 0x29, 0x32, 0x0, 0x0)
socket(0x18, 0x2, 0x0)
socket(0x800000018, 0x1, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000040)=[{{}, 0x0, 0x0, 0x0, 0x2}], 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x2, 0x0, 0x1e}, 0x4, 0x0, 0x0, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x0, 0x0)
socket$unix(0x1, 0x0, 0x0)
open(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
close(r0)


open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000401})
open(&(0x7f00000000c0)='./file0\x00', 0x20, 0x0)
r1 = open(&(0x7f0000000400)='./file0\x00', 0x0, 0x0)
fcntl$lock(r1, 0x9, &(0x7f0000000140)={0x0, 0x0, 0x4c0, 0x269000000, 0xffffffffffffffff})


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x54}, 0x3, &(0x7f0000000040)="71a9e40cc8274bc1e65a91501d162948b47ee3a7ebc26d211394a34b8e5f84cf51b59c7afec37082", &(0x7f0000000080)=0x2abd, 0x0, 0x37)


open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000300)={0x0, 0x0, 0x0, 0x100000001})
r1 = open(&(0x7f0000000040)='./file0\x00', 0x205, 0x0)
fcntl$lock(r1, 0x8, &(0x7f0000000000)={0x4, 0x0, 0x0, 0x1000300010008, 0xffffffffffffffff})
r2 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r2, 0x9, &(0x7f0000000140)={0x0, 0x0, 0xfff, 0x100000002})


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
r2 = dup2(r1, r0)
setsockopt$inet_opts(r2, 0x0, 0x24, &(0x7f0000000000), 0x0)


syz_emit_ethernet(0x3e, &(0x7f0000000400)=ANY=[@ANYBLOB="ffffffffffff00000000000086dd6004272900080000fe0000000000000000000000000000bb0000000000000000000000009d"])


pipe2(&(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff}, 0x10004)
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000180)="4dfb6b79951845e2cd9668618b36d93df01b8b7d45d0bc640ada53de1096c280bc3fe8a11c5aeea07cc0aca57612f97d4b101b5199f73cd5a5bb955d8f2ab8d018223f7b466cfec2b1a9fb56b65db7afa8570d748d5d8c08785882a940bd45d0984200a1bcd0fac462e146746296242e7342abce5beee86b92b0be65d3aef495a0ec7e2df79837fde3b44ac1773ffd11cf2531da", 0x94}], 0x1)
read(r1, &(0x7f0000000580)=""/147, 0x93)
write(r0, &(0x7f00000000c0)="c3", 0xffffffed)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000001600)={0x0, 0x0, 0x0, 0x0, &(0x7f0000002c40)=ANY=[@ANYBLOB="10000000ffff000001"], 0x10}, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000080)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmmsg(r0, &(0x7f0000001600)={0x0}, 0x10, 0x0)
readv(r1, &(0x7f0000000040)=[{0x0}], 0x1)


mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x28f2)
r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ioctl$FIONREAD(r0, 0xc0206921, &(0x7f00000001c0))


sendmsg$unix(0xffffffffffffffff, &(0x7f0000001280)={0x0, 0x0, &(0x7f0000001200)=[{&(0x7f0000000180)="bf3b684c5ae963b4567084e096cf973983b85e5df63e013eaa9405095e88157332b4f68e78e0793d3e30417acbf4419893cfd424b75262dc5ade2ab6278ab86672f9ed186987b8c19d9295a17b98020f6002", 0x52}], 0x1}, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x8040691a, &(0x7f00000001c0))


r0 = socket$inet(0x2, 0x8003, 0x0)
setsockopt(r0, 0x0, 0x7, &(0x7f0000000340)="15337ac0", 0x4)
setsockopt$sock_int(r0, 0xffff, 0x800, &(0x7f0000000000)=0x1, 0x4)
syz_emit_ethernet(0x2a, &(0x7f00000002c0)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, @multicast2}, @icmp=@echo}}}})


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
poll(&(0x7f0000000280)=[{r0, 0x4}], 0x1, 0x0)
close(r0)


syz_emit_ethernet(0x3e, &(0x7f00000000c0)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, @rand_addr, @multicast1}, @icmp=@parameter_prob={0xc, 0x0, 0x0, 0x0, 0x0, 0x0, {0x5, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, @multicast1, @multicast1}}}}}})
r0 = msgget$private(0x0, 0x10)
r1 = geteuid()
getegid()
geteuid()
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000040)={0x0, 0x0, <r2=>0x0}, 0xc)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000003c0)={<r3=>0x0}, &(0x7f0000000400)=0xc)
msgctl$IPC_SET(r0, 0x1, &(0x7f0000000100)={{0xa13, r1, 0x0, 0x0, r2, 0x1, 0xfff8}, 0x0, 0x1, 0xffffffffffffffff, r3, 0x0, 0x2, 0x0, 0x80})
writev(0xffffffffffffffff, &(0x7f00000001c0), 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000200)=[{0x40}, {0x50}, {0x6}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000000400)={0x0, 0x0, &(0x7f0000000080)=[{&(0x7f0000000180)="cf70770c0d6e80f391bb19656265c41dbf978bc8ef8f9c4c61decb06778c275ed5f70fff9371f1e7789cea6dd7768a2bf2e1a3b9964f606ae9f98c61b38d595303b8f29af43b7903151d6d610da3bb97b52d896feb0a9a1e917c89ec20b854157d7a67e8468615947f9903f6affcc36234407d72d527e7514e53d668cd96c5795a50dbf714313fa18f65de35968e6c1744ebc1a81ee87beb77bef9e84b047377255e3f21a21862b5acf40b49dbbd24ea82380a299266d9f5204d7c3f03c3ff802ae9a2c9f12137d5dff9b82c618267", 0xcf}], 0x1}, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000132000/0x3000)=nil, &(0x7f00000a0000/0x1000)=nil, 0x80400000}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f0000ff3000/0xa000)=nil, &(0x7f00001f0000/0x1000)=nil}, {&(0x7f00001f0000/0x1000)=nil, &(0x7f0000001000/0x1000)=nil}, {&(0x7f0000132000/0x4000)=nil, &(0x7f00000b2000/0x1000)=nil}, {&(0x7f0000083000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {0x0, &(0x7f000002a000/0x3000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000e58000/0x4000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil}, {&(0x7f0000091000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000001000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000132000/0x1000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000008a000/0x1000)=nil}, {0x0, &(0x7f0000092000/0x3000)=nil}], './file0\x00'})
openat$vmm(0xffffffffffffff9c, &(0x7f0000000800), 0x0, 0x0)
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000280), 0x8, 0x0)
mkdirat(0xffffffffffffff9c, &(0x7f0000000100)='./file0\x00', 0x0)
mkdirat(0xffffffffffffff9c, &(0x7f0000000000)='./file0/file0\x00', 0x0)
r1 = open$dir(&(0x7f0000000340)='./file0\x00', 0x0, 0x0)
r2 = open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
mkdirat(r2, &(0x7f0000000180)='./file0/file0\x00', 0x0)
renameat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', r1, &(0x7f0000000280)='./file0/file0/file0\x00')
ioctl$VMM_IOC_INFO(r0, 0xc0185603, &(0x7f0000000300)={0x0, 0x0, &(0x7f00000002c0)})


r0 = socket(0x2, 0x2, 0x0)
sendmsg(r0, &(0x7f00000006c0)={&(0x7f0000000040)=@in6={0x18, 0x0}, 0xc, 0x0, 0x0, &(0x7f0000000440)=ANY=[@ANYBLOB="700000000000000001000000040000001ffabe948d59ff2c7f787a833f7a38d7b02906b4f53e85ed59840c670605e89ca980ef57a676ba199564477743a4a978c0988dcb122338e9176f16a3333853a4438280bb41747cdf80198230df67af3a6dd3c4442e329642f6000000000000009800000000000000ffff00000600000042a4c4ea6c7687bf846ba318f4272a3d49222b3f339b5bf264229b959166b7e35d0cc61bcf156b1f95025fa8645019580f2f8439e9c6660c6411052fef1e21d66e45f5c37eaf2b940edc689f1b99034e1274861586a5011c409e8ff45da8cfb810e57b44faf11e54fff279021436e9b3b285aa4fec3c514febb8000000000000000100000005000000003b"], 0x258}, 0x0)


r0 = open(&(0x7f0000000140)='./file0\x00', 0xf8e, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000240)={<r1=>0x0}, 0xc)
ktrace(&(0x7f0000000200)='./file1\x00', 0x0, 0x40000730, r1)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000200)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x40000802)
r3 = open(&(0x7f0000000080)='./file0\x00', 0x70e, 0x0)
readv(r3, &(0x7f0000000040)=[{&(0x7f0000000100)=""/4096, 0x1000}], 0x1)
sendto$unix(r2, &(0x7f00000013c0)="0270dd965d8628daaf9a5e7f99e559d0aed90670d87bfe09c870a2c41d270d551a5f2eaad4aa22c502a0b525ed4f33aa3cb443b37c06e09925f9aaaa90626a2a8378dc0a943406b166a4a6228fd34873a6905aa56c6a9cac6f58b66cabf083f83683c74f0f3050b96895319ced011c295471e9ca5e3ae2f92dfe0c90392a47ea53850627c249733f70e10c1a4d7acf7deb", 0x91, 0xc, 0x0, 0x0)
getpid()
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
mknod(&(0x7f00000000c0)='./file0\x00', 0x2000, 0x40000802)
openat$vmm(0xffffffffffffff9c, &(0x7f0000000080), 0x10000, 0x0)
r4 = socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(r4, 0xc0206921, &(0x7f00000001c0))
mknod(&(0x7f0000000280)='./file1\x00', 0x0, 0x6)
kevent(0xffffffffffffffff, &(0x7f0000000040)=[{{}, 0x0, 0x0, 0x0, 0x3}], 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x6, &(0x7f0000000080), 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000080), 0x1)
openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f00000002c0), 0xc)
openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000180), 0x80, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000003c0))
r0 = socket(0x2, 0x8002, 0x0)
connect$unix(r0, &(0x7f0000000a80), 0x10)
getsockname$unix(r0, &(0x7f0000000000)=@abs, &(0x7f0000001200)=0x8)
r1 = socket(0x2, 0x1, 0x0)
bind(r1, &(0x7f0000000000), 0x10)
r2 = dup(r1)
listen(r2, 0x0)
r3 = socket(0x2, 0x1, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)
sysctl$vfs_fuse(&(0x7f00000000c0)={0xa, 0x12, 0x2}, 0x3, 0x0, &(0x7f0000000180), &(0x7f00000001c0), 0x0)
sendto$inet(r3, &(0x7f0000000100)="18", 0x1, 0x0, 0x0, 0x0)
recvmmsg(r3, &(0x7f0000000980)={&(0x7f0000000940)={&(0x7f0000000780), 0xc, 0x0, 0x0, 0x0}}, 0x10, 0x0, 0x0)
dup2(0xffffffffffffffff, r3)
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={0x0}, 0x10, 0x840, 0x0)
pipe(0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)
write(0xffffffffffffffff, &(0x7f0000000180)="83", 0x1)
poll(&(0x7f0000000400)=[{}], 0x1, 0xfffffffc)
execve(0x0, 0x0, 0x0)


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000080)=[{0x87}, {0x7c}, {0x6}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
pipe(&(0x7f0000000040)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
write(r2, &(0x7f0000000000)="af", 0x1)
r3 = getpid()
ioctl$BIOCSRTIMEOUT(r0, 0x8010426d, &(0x7f0000000480)={0x0, 0x47e224d5})
fcntl$setown(r1, 0x6, r3)
r4 = kqueue()
fcntl$getown(r4, 0x5)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
write(r1, &(0x7f0000000340), 0xd4e688a67930cd)
execve(&(0x7f00000000c0)='./file0\x00', &(0x7f00000003c0)=[&(0x7f0000000140)='/dev/bpf\x00', &(0x7f00000001c0)='tap', &(0x7f0000000200)='\\(.:\xa6#/)!#,,]-}*+(\'-[\x00', &(0x7f0000000280)='\x00', &(0x7f00000002c0)=']\\[^{.[\x00', &(0x7f0000000300)='/devu\xb3/bp', &(0x7f0000000340)='\x00', &(0x7f0000000380)='*:&\x00'], &(0x7f0000000440)=[&(0x7f0000000400)=':&)]\x00'])
close(r1)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x35})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r1, &(0x7f0000002040)=[{&(0x7f0000000700)='l', 0x1}], 0x1)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000080)={0x7ffffffb, 0x0, 0x80000005, 0xffffffff, "0100000063026d00000100000000000000777d00"})
writev(r0, &(0x7f0000002f40)=[{&(0x7f0000001e40)="8e78dbebae5d90546f15d52a70c0d6c01f58a61f32323c0794131b931fec61639d2f39a6047225d023e386c4556448c215cf2412d15d80dbf9f84b8741dd0b85594b84517605a7a7397ed4fb170e22d274b430934323f2f4fb5606ef5596615f1483c475b95ef23aea27e3b7a7c35f66ed518b4f97d9fa5945621a1173a9e1e34a3761486699739b5dd0f87a0d15ddb90c5f0b6935666ed373a8123f5a6167a180b5021fd0acff9d9731a5bd60e3ec94e2b7771d82937d6c7ff1b9422fdfbfa590964ca5b01b1ec5b60ef0bdd0be043b45cf8d18a5e672cff3c0aad2f41623f7ba3ba28c9b2419a3492b027f5169f1c7a49d496800dc3655536d25fd59b9cc0aa0d3bf78ad55f60a9ed41e1bb19b1c13d2d39a03a32123e8c58bbbd8603eaf87c9feff40795f8ef85e2c71683f9b14eefdc5e1d5c634c796cb911a58d83b20ec6e38ea7ffa40bfb8663e568765f8dd8d20143f82711d82d74b2d81b884ef21822818bd82a0920bb8c5b6e58e7aa743bc6b19728a785d2dd1b13ed5f5d3b903b3060c45f45802ae7c7b17cf2caa35d71ea86eda33fcff40bc22d55c804b946da28430427592d4178dd1694408c5d354f5ee480efdbcde222289063511a0f8dc2d674686be160347b81545049e76c44bd2df568eb1a2ca777e0c7df50943", 0x1dd}], 0x1)


pipe(&(0x7f0000000040)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
write(r0, &(0x7f0000000040), 0xfeea)
poll(&(0x7f00000000c0)=[{r0, 0x4}], 0x1, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0x0, 0xd163, 0xfffffffe, 0xfffffffb, "1a1116f0d0a607000000000000fffffffffff700"})
writev(r0, &(0x7f0000000500)=[{&(0x7f0000000e40)="cdb2ad61ad64f8cbd40672bca315e26911f5b4f347b8c792cbfdb4ef908b282b1ed47b7a5ca377cab5b3f8d8b8bbd5cb4877551bc2dc495e4939811216917a5a81aaacec7eba7d9bf6abb8f5cbf0119776986e3bd86301cf8043cae8b951c9249b702b41829c770fd7fc0d7ee34460d81fc75ec29a6dbdeb769a51f1df011e7bd192cb13e39597007789629dd923aa4ff1640b0a7030e67e804f49f656c1f4dd7dfd1fd46bea2e5049eff79936dee78ff55c9986233db6e20ec6295cc24cc54a673a57cf9691b910cce90dd0f573afa6dbfd886db6d8f4a56c11c0ae5af4855d478414039bb8dcb7d86cf9537f8abcdb0fd7e0abb38ec0556e495ea1667b6cd3353411fcf950bbbe9cb7f2fbeb34329c81357b6cdfa3788a6696845a0db16bdb406d4f090e671ef11b8890345ba2e7a094912be55f1f6f669a2cc489f9264c789e56dcaf7073659dcfabd5489feec768ac66484afd2e1b74eefbab6d1ecaa5c76e648461a3a5f5b0b1f8a0fe42e34e2516dae628457a2ed5b4b87c237d4ac63851379058dec7371dc6f51bb6bbe84e335d4509f242871066ef4b7d5cb5a93ad5acf8a118d6702db6f75cf49c232eb20eada800a4283fdebe0c2b5d721ddd9c93192cfa9b777e6eac6b08aac493d93813c17ab67cfb1d0207247feb37ecc3c2d57acba029ec1acd73895bc529a341657d7eca7c91b0cbd439c35b50047b95c7e5f67000286ca9d885e08a93d4c8fe7b6ae210675ad323c5e847d7ff5021fd0a75b75b648e3a3c99560698c93b9cba0a7727458539dd79ba5769ab18859adf9cebdfd680b857645b607bde6f5a414aca2e732baabecca7d4034544253d57ff6e951a59c8f5aff6faef7b60b74f830033b7bc2258cc196b37c0ae65e8318a6b0e6dfa925542ccbc45e488ad9135df52150fafa752523427268156470831473542cfdd0a3287acbf230611a741484dc741b06e1a337a7bd7408db8ab94adeded534e023b4835af38c28533e6b5d9027ed8ea8241a04eb5bb1aaa41b67eb5bbe447bcf989c6b1540aa68c8e9912931d7990861cc55a9612b33985d6115ad2984ec3d3511bea981fe37b9d9ee77cde1b1d28baf486e36224bc4290f62465228be64b09e656218d49e3a43adffeeb0d3392d254a7f5c4d1a3e67240c91a672ee10567c7472430221851fc3c4920f1b93192c362ff971057bbabc3bf82334717b9caa9d97f0500000000000000a40e876570ba383f1072899bf0cb96c5a7982880608500bbc500eedc74250c2c6733375c53493f9a44d3710ca3ff2677b4613b23df114d368b5b2bcab4668c57c2c699c5f52d2b8fa7200f9eee3526542fb6c7341201bd155f12f38eaf15f27bd7207088f18659aad7913b136928640130fd7076026e373d278b7db607f2ebd0cd5d41512fd96272b57114e5b14faf7ed02122fa0cc50de3d26e946cbeabdb9dad82674779fbb76f744a9da7cc8c7b42c7275a9d2749862c11637ff63ee83d2c6da2d3cff6eff5ce792f5aa00a5e5ab7db1bee945811be8b93b886a61eb2136ab53435a26a602cf0ea65959f961b78cdfaebc6f2f4ed1467fa2dd73db21cc3e7eedc1f9d9a543dae48d55218000fcbe0fcc7d370ad47ba89610e7cfe524b2f2500e4327e87f94f3c587f0a6604baaa4509e0ed8fc6fe62c43423705deb7a7fdece18bc9b9ebd80a878d5255a3ee0114a236a9a9d0a395269e7a68ea4b948fd1b0425b0b7b073b90c986046aa4bd16dbf9442583137576e8a3442a0a90dfc7ea7cdec4254ffb0ff6d1d7aa18c66af453d05f583c2a777e193b9ebb4e3c3bb82362b8f450000000056319aaf45dbd9df561985c2f4ff248f655c629eec26a576fe836875105841f3c7e290193a51b6d7d235a10cb816b3e97f942b84644696edf3c96e396825df2e83e62aca39e0a38824c488cd83663eb248db8385791b34ba604ad807", 0x56c}], 0x1)
writev(r0, &(0x7f00000003c0), 0x1d)
mknod(0x0, 0x0, 0x0)


mknod(&(0x7f0000000040)='./file0\x00', 0x6000, 0xe02)
open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
socket$unix(0x1, 0x5, 0x0)
r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000180), 0x1, 0x0)
ioctl$WSKBDIO_GETMAP(r0, 0xc010570d, &(0x7f00000001c0)={0x1, &(0x7f0000000240)=[{}]})
nanosleep(0x0, 0x0)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
setreuid(0xee00, 0x0)
r1 = getuid()
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
setreuid(r1, r1)
syz_emit_ethernet(0x66, &(0x7f00000017c0)={@random="1930f5ad7fe9", @remote, [], {@ipv6={0x86dd, {0x0, 0x6, "03dbde", 0x30, 0x0, 0x0, @ipv4, @loopback, {[], @icmpv6=@time_exceed={0x3, 0x0, 0x0, 0x0, '\x00', {0x0, 0x6, "823fa0", 0x0, 0x0, 0x0, @ipv4={'\x00', '\xff\xff', @loopback}, @loopback}}}}}}})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$TIOCSCTTY(0xffffffffffffffff, 0x20007461)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r2 = socket(0x2, 0x1, 0x0)
bind(r2, &(0x7f0000000000)=@un=@abs={0x0, 0xd}, 0x10)


mknod(&(0x7f00000000c0)='./file0\x00', 0x2000, 0x4301)
open$dir(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
dup2(r1, r0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000a, &(0x7f0000000000)="ea00005c00000000", 0x1)
setsockopt$inet_opts(r0, 0x0, 0xd, &(0x7f0000000240)="ea00fff100000000", 0x8)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x3}})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$VMM_IOC_INFO(r0, 0x8020560a, &(0x7f00000000c0)={0x0, 0x0, 0x0})


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000480)={0x0, &(0x7f0000000240)})
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
kqueue()
open$dir(&(0x7f0000000040)='./file0\x00', 0x80, 0x82)
open(&(0x7f0000000140)='./file0/file0\x00', 0x0, 0x0)
r1 = geteuid()
r2 = getuid()
setreuid(r2, r1)
setreuid(0xee00, r2)
r3 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x200100000001d, &(0x7f0000000000), 0x4)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000000)={<r4=>0x0}, &(0x7f00000000c0)=0xc)
r5 = semget$private(0x0, 0x7, 0x3c0)
semop(r5, &(0x7f0000000100)=[{0x3, 0x2, 0x800}, {0x1, 0x2ff}, {0x1, 0x0, 0x1000}, {0x3, 0x3ff, 0x1800}, {}, {0x3, 0x1, 0x3000}], 0x6)
semctl$SETALL(r5, 0x0, 0x9, &(0x7f00000002c0)=[0x3, 0xfff])
semctl$SETALL(r5, 0x0, 0x9, &(0x7f0000000380)=[0x0, 0x0])
r6 = getuid()
setreuid(0xee00, r6)
r7 = getpgid(r4)
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000001c0)={{0x3, 0x0, 0x0, r6, 0x0, 0x30, 0x6d}, 0x9, 0x7, r7, r7, 0xfffd, 0xb, 0x6, 0xbdbe})
semop(r5, &(0x7f0000000140), 0x0)
getrlimit(0xd, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x80, 0x200}, 0x3})
getrlimit(0x8, &(0x7f0000000040))
r8 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r8, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
write(r8, &(0x7f0000000000)="7696e5f3d1f18c37cea8615ac7cf", 0xe)
socket(0x18, 0x3, 0x0)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x200, 0x0)
getgroups(0x7, &(0x7f0000000040)=[<r1=>0xffffffffffffffff, 0x0, <r2=>0x0, <r3=>0x0, <r4=>0x0, <r5=>0x0, <r6=>0x0])
setregid(r5, r2)
setgroups(0x0, 0x0)
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f0000000380)={0x0, <r7=>0x0, <r8=>0x0}, 0xc)
setreuid(0xee00, 0x0)
semop(0x0, &(0x7f0000000080)=[{0x3, 0x2, 0x800}, {0x1, 0x2ff}, {0x3, 0x8, 0x1000}, {0x2, 0x3ff, 0x1800}, {0x0, 0x0, 0x1000}, {0x2, 0x6ff, 0x1400}, {0x0, 0x7ff, 0x800}], 0x7)
fchown(0xffffffffffffffff, r7, r1)
semctl$SETALL(0x0, 0x0, 0x9, &(0x7f00000002c0)=[0x3, 0xfff])
semctl$GETALL(0x0, 0x0, 0x6, &(0x7f0000000440)=""/248)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000001c0)={0x0, <r9=>0x0}, 0xc)
r10 = getuid()
setreuid(0xee00, r10)
setreuid(r10, r7)
r11 = semget(0x1, 0x1, 0x230)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000200)={{0x0, 0x0, 0x0, r10, r3, 0x182}, 0x6, 0x8000000000000000, 0x2f})
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x10200, 0x0, 0xffffffffffffffff, 0x0, r8, 0x44, 0xeb}, 0x2, 0xd47, 0x7})
semctl$IPC_SET(r11, 0x0, 0x1, &(0x7f0000000140)={{0x0, r10, 0x0, r9, r6, 0x62}, 0x6, 0x9, 0x4})
semctl$GETALL(0x0, 0x0, 0x6, &(0x7f0000000540)=""/240)
semctl$SETALL(0x0, 0x0, 0x9, &(0x7f0000000140))
semctl$IPC_SET(r11, 0x0, 0x1, &(0x7f0000000100)={{0x6, r7, r6, r7, r1, 0x20, 0x9}, 0xe41, 0x800, 0x1f})
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f0000000000), 0xc)
setegid(r3)
setregid(0x0, r4)
r12 = getuid()
setreuid(0xee00, r12)
execve(&(0x7f0000000580)='./file0\x00', 0x0, 0x0)
setegid(r6)


r0 = openat$pci(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$PCIOCGETROM(r0, 0xc0107004, &(0x7f0000000140)={{}, 0x0, 0x0})


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x1, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x0)
setsockopt(r1, 0x1000000029, 0x1a, &(0x7f0000000000)="5ab777a5", 0x4)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r0, &(0x7f0000000180)="24a608d334f68b1f26da3fb9a1e5e89f23bf1364", 0x14)


syz_emit_ethernet(0x6e, &(0x7f0000001340)={@broadcast, @empty, [], {@ipv6={0x86dd, {0x0, 0x6, '\x00o3', 0x38, 0x0, 0x0, @rand_addr="8a211dd1450021b07f5a1957de7400", @local={0xfe, 0x80, '\x00', 0x0}, {[@hopopts={0x33}], @icmpv6=@pkt_toobig={0x2, 0x0, 0x0, 0x0, {0x0, 0x6, '\x00', 0x0, 0x0, 0x0, @local={0xfe, 0x80, '\x00', 0x0}, @ipv4}}}}}}})


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
writev(r0, &(0x7f0000000100)=[{&(0x7f0000000240)='O8', 0x2}, {&(0x7f0000000040)='5', 0x1}], 0x2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000140)=[{0x5c}, {0x64}, {0x40e}]})
syz_emit_ethernet(0x2a, &(0x7f0000000040)=ANY=[])
mkdir(&(0x7f0000000040)='./file0\x00', 0x0)
getpeername(0xffffffffffffff9c, &(0x7f0000000000)=@in, &(0x7f0000000040)=0xc)
syz_emit_ethernet(0xd6, &(0x7f0000000080)={@local, @remote, [], {@generic={0x7030, "03760bfefc27fcf77f301ff68831f9737e3f6688ed37f1519546bf5d20913512cbb98bc3b406028dcd67ee5f3b728679cd2f30ca0473f2dea284ee0380651c1ce7346165fe125386421f0e3fd49dfe259b53d3b843cbc6e7739d9b0bbf55c3da4d558f61e857867565ab7bfb83d55e1dc6be639222a4ab59dc13f00e11b8fa3629ec108ea11b05ccd1d2e175a0a7451c23c3f9bf6c1bed60d8e801a381049da4894cd44158a495c4449e4891d85545b4337ca6bbe6026a9f3a319ef76e979e2b54ae86d66d397944"}}})
rename(&(0x7f0000000180)='./file0\x00', &(0x7f00000001c0)='./file0\x00')
r1 = semget(0x0, 0x1, 0x620)
semctl$SETVAL(r1, 0x4, 0x8, &(0x7f0000000200)=0x9)
socketpair(0x6, 0x5, 0x4, &(0x7f0000000240)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
connect$unix(r2, &(0x7f0000000280)=@abs={0x1, 0x0, 0x0}, 0x8)
r4 = socket(0x18, 0x8000, 0x6)
openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x8000, 0x0)
ioctl$TIOCSTAT(0xffffffffffffffff, 0x20007465, &(0x7f0000000300))
r5 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000340), 0x0, 0x0)
ioctl$TIOCGETA(r5, 0x402c7413, &(0x7f0000000380))
sendto(r4, 0x0, 0x0, 0x404, 0x0, 0x0)
socket$inet(0x2, 0x8000, 0x1)
socket(0x20, 0x1, 0x4)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000080))
r6 = syz_open_pts()
fcntl$lock(r6, 0x8, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1000300800000})
flock(r6, 0x1)
fcntl$lock(r6, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000001})
syz_open_pts()
syz_open_pts()
ioctl$DIOCMAP(r5, 0xc0106477, &(0x7f0000000500)={&(0x7f00000004c0)='./file0\x00', r3, 0x2})
r7 = accept$inet(r5, &(0x7f0000000540), &(0x7f0000000580)=0xc)
recvmsg(r7, &(0x7f00000008c0)={&(0x7f00000005c0)=@in, 0xc, &(0x7f0000000840)=[{&(0x7f0000000600)=""/141, 0x8d}, {&(0x7f00000006c0)=""/116, 0x74}, {&(0x7f0000000740)=""/253, 0xfd}], 0x3, &(0x7f0000000880)=""/19, 0x13}, 0x801)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0x9, 0x0, "37f6838cacb84fa967d1a0d0cd4f2b3001a68601"})
writev(r0, &(0x7f0000000200)=[{&(0x7f00000009c0)="8cca9916061bba936d3622583e4680b3f34adc", 0x13}], 0x1)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x7fffffff, 0x7ff, "fcdc81d0ee4a1466fcd1ce667f3e3fb6c4547a05"})
readv(r1, &(0x7f0000000180)=[{&(0x7f0000000100)=""/91, 0x5b}], 0x1)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x81286947, &(0x7f00000001c0))


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)
poll(&(0x7f0000000380)=[{}], 0x1, 0xffff)
r0 = socket(0x1, 0x1, 0x0)
r1 = dup2(r0, r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)


mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x0)
r0 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000180)={0x0, 0x0, 0xe150, 0x0, "32cd8b6abd39a5a7bc6a8811751c8b995f0407ff", 0x0, 0x3})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000080)=[{0x44}, {0x3d}, {0x8006}]})
syz_emit_ethernet(0x1db, &(0x7f00000007c0)=ANY=[])


mknod(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
r0 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0x1cc45f45, 0xffffffc3, "070000010000fbff00e6ff20a1ec7500"})
poll(&(0x7f0000000040)=[{r0, 0x1}], 0x1, 0x0)
socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000040)={{0x0, 0xffffffffffffffff}, 0x0, 0x100000000, 0x0, 0x0, 0x3})
sysctl$kern(&(0x7f0000000080)={0x1, 0x33}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)
sysctl$net_pipex(&(0x7f0000000000)={0x4, 0x23, 0x1}, 0x3, 0x0, 0x0, 0x0, 0xffffffffffffff17)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000000), 0x6, 0x0, 0x0, 0x0, 0x0)


sendmmsg(0xffffffffffffffff, &(0x7f00000007c0)={&(0x7f0000000780)={0x0, 0x0, &(0x7f0000000440)=[{&(0x7f0000000180)="b860fe09625ee6793978a575faa1b6c6c1d6c2eca2950e663d39ab1be31a269a39fd7f97e41e178f37a79f00659c2ea9ac56733f7e4e4973c1e6b326c91343ea3b3f8c5c7b93d5fe30", 0x49}], 0x1, 0x0}}, 0x10, 0x0)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f00000001c0))
openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{}, {}, {0x6, 0x0, 0x0, 0x85}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


r0 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x800, 0x0, 0x2f)


mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x5200)
r0 = open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
readv(r0, &(0x7f00000003c0)=[{&(0x7f0000002580)=""/4096, 0x1000}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000340), 0x0, 0x0)
ioctl$BIOCSBLEN(r0, 0xc0044266, &(0x7f0000000000)=0x80000000)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000080)=[{}, {}], 0x2})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b10005160000000000000000070000001a5113fecea10500fef96ecfc72fd3357a89583535673039d2d236acf20b7804be38164991f7c8cf5f882b2900e1aa5b23edebc8ef99a8ad491726fa8251e2f0ac3ebbc2feb3fda1139b672f4d3353eb06acdb35a069d7080000000000000000008904000000000022830cf41bed66f4f365ccdcf3e4999d9d20002002", 0x8d, 0x0, 0x0, 0x0)
sendmsg(0xffffffffffffffff, &(0x7f0000000240)={&(0x7f0000000080)=@in={0x2, 0x1}, 0xc, 0x0, 0x0, 0x0}, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
socket(0x18, 0x2, 0x0)
writev(0xffffffffffffffff, &(0x7f00000002c0), 0x0)
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x80206979, &(0x7f00000001c0))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x18, 0x1, 0x0)
close(r2)
r3 = socket(0x18, 0x2, 0x0)
setsockopt(r3, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
pread(0xffffffffffffffff, &(0x7f0000000140)="6f61b7ef7ead776902483d35659a64e88dae40c40c02e5d54f4624bbd9117c6be4368741a4877bcf6f8f75aced9c0f9928aeeaab48b7d8b3e210f9f9e361544e9c3544e17a60fa470d190ab042e4af4fc6c09af967c10177d0e86ede02532f8cfe92b5eaa3c369b66d7aac10d1197c7dcc98f32962c28b9d649ee93656f091e93987144332e847063919a16cedf0960cebbd1f5992f00b0a69c4a9191a3a00b2e791a5ff29b25747ad4358bd9d14ebb68e16fd204e3539383b3b6d1df08b7a33b560dce269f65e50753a", 0xfffffffffffffce5, 0x125)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendmsg$unix(r2, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)
fcntl$lock(0xffffffffffffff9c, 0x7, &(0x7f0000000280)={0x2, 0x1, 0xffffffffffffffff, 0x3, 0xffffffffffffffff})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f00000003c0)=[{0x4}, {0x4}, {}]})


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)='\x00', 0x1}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
dup2(r1, r0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000200)="ea00000100000000", 0x8)


setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0xee00, r0)
ktrace(0x0, 0x5, 0x40000424, 0xffffffffffffffff)
mprotect(&(0x7f0000ffc000/0x2000)=nil, 0x2000, 0x1)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
syz_emit_ethernet(0x388, &(0x7f0000000740)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa86dd60bd23ca03520100fe8000000000000000000000000000bbfe8000000000000000000000000000aa0400907800000002613e659fc000ff20ff010000000000000000000000000001fe8000000000000000000000000000bb700002206500000070100059000000000000000000000000000000000000000100000000000000000000ffff00000000c3a790633c2f18003a735f07e06386a7ff0100000000000000000000000000010000000000000000000000000000000100000000000000000000000000000001ff010000000000000000000000000001ff0200000000000000000000000000011d08000c00000000ff010000000000000000000000000001ff02000000000000000000000000000132967729da01c0285a5f4eafe8d8ad66000000000000000000000000000000013c00000000000000ff01000000000000c204fffffffe05020003000100000000e002000700000000000000000000000000000000000000001622000000000000000100c20400000b7608f36ba68f21d313c00da4cfa7f04c8e3cdf0a51e87e8d1274d6fc91d79b1a8162f73c5623f5c024a6c37e9d204aefdcddea6bfd6d9e31dafa402daa534fdd11161394a2021084223b603d526dbbaa0386808ad35bc1dab5d1c8ea6409541c11370f0f29891d42b3728783eff7f4c6b34674ab3328ec04281fccebf9ab69f50d2ed7ed17d52ee7a4279ca0a199b80418ac94b3391e4b41c928c934300fdfe4b32e69eb841fda7ac92503f03337bc0a1e01a06a7a379252c3640815a50a41fa793739cca5975a9b35b96be82f31c89743ad0a09926af67f196c63a079ce7797347c0af3669e52ed6aeebaedaf6239711a723041e3030502007f05020001c204000000010108000000000000000000005848ee5b65037cba171ac8df04bf1bf21829a904141aa5131f32fd98e3a658e24f936b7c20cf2874bda3dfad528490db12fe39c98dc8a736ef761a90d7360e672b70185d8ffb059b3636875558fe7ce0d8e777dffca154773c0890cb7301945034cf46bb2cb747267b0908381ec02e09fab42010a8bd92144e0201731db566d3d99da75badf61481866a4edef3ffadc1813fce3919232992bb62305e2d83c25b7aab445eac1342deefcd9e14e5ec87c583c5c86d97382578bb15742e7340ebcb05b4f10b0d7dc32a0e3f15d95f7c1378936ef8af44e87e689a4a5a06c17243ac569caa9f04cdcae37a29a66b68a9697fa6c7"])
recvmmsg(r1, &(0x7f0000000700)={&(0x7f0000000140)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000280)=""/126, 0x7e}, 0x3f8d}, 0x10, 0x801, 0x0)
setreuid(0x0, 0xee01)
r3 = fcntl$dupfd(r1, 0x0, r2)
socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x0, &(0x7f0000000080)="eaef125c00000000", 0x8)
mprotect(&(0x7f0000ffd000/0x3000)=nil, 0x3000, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x9, 0x0, 0x0)
recvmsg(r3, &(0x7f0000000540)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x3)
r4 = semget$private(0x0, 0x2, 0x110)
openat$tty(0xffffffffffffff9c, &(0x7f00000000c0), 0x200, 0x0)
semctl$GETALL(r4, 0x0, 0x6, &(0x7f0000003780)=""/4116)


writev(0xffffffffffffffff, &(0x7f00000012c0)=[{&(0x7f0000000000)="c2514bbf316e7fabc6fd17a135260f61611b8b0d214881a2", 0x18}], 0x1)
sysctl$kern(&(0x7f0000000000)={0x1, 0x42}, 0x6, 0x0, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000200)=[{0x15}, {0x45}, {0x8106}]})
syz_emit_ethernet(0x4e, &(0x7f0000000100)=ANY=[])


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chdir(&(0x7f0000000140)='./file0\x00')
mkdir(&(0x7f0000000040)='./file0\x00', 0x8)
chdir(&(0x7f0000000380)='./file0\x00')
r0 = open(&(0x7f00000002c0)='.\x00', 0x0, 0x0)
mkdirat(r0, &(0x7f0000000340)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38/\x00', 0x0)
mkdirat(r0, &(0x7f0000000440)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//file0\x00', 0x0)
unveil(&(0x7f00000004c0)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//file0\x00', &(0x7f00000000c0)='c\x00')
unveil(&(0x7f00000003c0)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38/\x00', &(0x7f0000000200)='x\x00')
setreuid(0xee00, 0x0)
r1 = getuid()
setreuid(0x0, r1)
unveil(&(0x7f0000000300)='./file1\x00', &(0x7f0000000340)='x\x00')


r0 = getppid()
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x4cf6)
r1 = open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r0, 0x0, 0x0, 0x1000000000000000})
getuid()
getuid()
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x40)
setreuid(0x0, 0x0)
setreuid(0xee00, 0x0)
getegid()
sysctl$kern(&(0x7f0000000040)={0x1, 0x41}, 0x2, &(0x7f0000000380), 0x0, 0x0, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, &(0x7f0000000100), 0x0)
getsockopt$SO_PEERCRED(r1, 0xffff, 0x1022, &(0x7f0000000000), 0xc)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001280)={0x0, 0x0, &(0x7f0000001200)=[{&(0x7f0000000180)="bf3b684c5ae963b4567084e096cf973983b85e5df63e013eaa9405095e88157332b4f68e78e0793d3e30417acbf4419893cfd424b75262dc5ade2ab6278ab86672f9ed186987b8c19d9295a17b98020f6002", 0x52}], 0x1}, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0206923, &(0x7f00000001c0))


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
syz_extract_tcp_res$synack(&(0x7f0000000000), 0x1, 0x0)
select(0x40, &(0x7f0000000040)={0x5, 0x400, 0x7, 0x0, 0x8, 0x1f, 0x6, 0x8}, &(0x7f0000000080)={0x7, 0x1000, 0xfc3b, 0x4, 0x4, 0x5, 0x6, 0x10001}, &(0x7f00000000c0)={0x4, 0x0, 0x3, 0xfffffffffffffffc, 0x80000001, 0x8000000000000000, 0x3, 0x4}, &(0x7f0000000100)={0x790, 0xfff})
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x8, 0x0)
r1 = kqueue()
kevent(r1, 0xffffffffffffffff, 0x3998, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000002c0)={0x3, &(0x7f0000000700)=[{}, {0x28}, {0x6}]})
write(r0, &(0x7f0000000540)="76e5dead6f01f8607d2100000063", 0xe)
accept$unix(0xffffffffffffff9c, &(0x7f0000000440)=@file={0x0, ""/34}, &(0x7f0000000680)=0x24)
r2 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
writev(r2, &(0x7f0000000580)=[{&(0x7f00000001c0)='N3-', 0x3}], 0x1)
openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$WSKBDIO_GETMAP(0xffffffffffffffff, 0x80047476, &(0x7f0000000200)={0x0, 0x0})
execve(0x0, 0x0, 0x0)
mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000a40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000001380)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000480)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f00000006c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000580)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000f80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000001080)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
chroot(&(0x7f0000000d00)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSFLAGS(r0, 0x8004745c, &(0x7f0000000100)=0x5)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x2, &(0x7f0000000000)=[{0x20, 0x0, 0x0, 0x10000}, {0x4e}]})
syz_emit_ethernet(0x138, &(0x7f00000000c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000280)={0x3, &(0x7f0000000000)=[{0x44}, {0x1c}, {0x8006}]})
syz_emit_ethernet(0x1db, &(0x7f00000007c0)=ANY=[])


socket$inet(0x2, 0x0, 0x0)
socket$inet(0x2, 0x2, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x1)
writev(r0, &(0x7f0000000000)=[{&(0x7f0000000100)="e0", 0x1}], 0x1)
msgctl$IPC_SET(0x0, 0x1, 0x0)
socket(0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = kqueue()
kevent(r2, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r3 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r3, 0xc0206921, &(0x7f00000001c0))
r4 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r4, 0x80206919, &(0x7f00000001c0))
r5 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r5, 0x8020690c, &(0x7f00000001c0))
pipe2(&(0x7f00000017c0), 0x4)
sysctl$vm(&(0x7f0000001640)={0x2, 0xb}, 0x2, &(0x7f0000001680)="200441655901f00801b9995d9b30cea5729b16f430fdf632f7a9bb0a28f1cf2c2b3f2728db5ca3a32765e2e9ce55430232651331586a98f5d6847b", &(0x7f00000016c0)=0x3b, &(0x7f0000001700)="553f6a68cb8d7a68ce5bf138735a55a5dce6426347d2ebb172ca8fc4dbeb01c371c7b737056a13933082130dc4e51ebc16070aaeb36cd7a3305a798754b23b685414c10b5b1524f262c160137772f1efdb09d5021c561df5fc84ed6ddaea6cc7c315e1c22a8adb0f096de23d8c1f79a39c7e77dc8999dfac49c2a36f36d229dd1c00308afeb0610360", 0x89)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
kqueue()
ioctl$FIOASYNC(r0, 0x80047470, &(0x7f0000000280)=0x1)
select(0x40, &(0x7f00000002c0)={0x7fffffffffffffff}, 0x0, 0x0, 0x0)


mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x5d4a)
mknod(&(0x7f0000000100)='./file0\x00', 0x1000, 0x0)
r0 = syz_open_pts()
execve(0x0, 0x0, 0x0)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000040))
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
socket(0x20, 0x0, 0x0)
socket(0x11, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x30)
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$VNDIOCSET(r1, 0xc0384600, &(0x7f0000000440)={&(0x7f0000000480)='./file0\x00', 0x57, 0x0, 0x40})


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x1, &(0x7f0000000280)=[{}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000080)='\x00\x00\x00\x00', 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000280)=[{0x2}, {0x3c}, {0x106}]})
syz_emit_ethernet(0x56, &(0x7f0000000000)=ANY=[])


writev(0xffffffffffffffff, &(0x7f0000000400), 0x1000000000000165)
mprotect(&(0x7f0000ffc000/0x1000)=nil, 0x1000, 0x0)
munmap(&(0x7f0000ffa000/0x4000)=nil, 0x4000)
madvise(&(0x7f0000ffd000/0x3000)=nil, 0x3000, 0x0)


r0 = socket(0x18, 0x1, 0x0)
listen(r0, 0x0)
shutdown(r0, 0x0)
select(0x40, &(0x7f0000000440)={0xffffffffffffffff}, 0x0, 0x0, 0x0)
select(0x7, &(0x7f00000002c0)={0xfffffffffffffffc}, 0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r1, &(0x7f0000000440)=[{&(0x7f0000000100)="ce94d0d4bf4cc8f53a62be7e5718419c62606c3c2f64058920994abc396d89fe5a6a585e4876eace845dfac59f2c98560115b9bb7e05065cc535201c9b63aae39561cccea07f98fb49e10e15978f7f4b95a383c6457e2495c93ecc518a6b74910a11e293005c2ac26a69bbe3d057f550809288761be9d8d37061d892df3bbe2897463b4a44ef7e376575795bd2dcc1334bf820fe51bd646ec3b38bd0aaf5513876d746b309e185222cd72009dbb1", 0xae}, {&(0x7f00000001c0)="a0dd3dad6ba1364904b8095e4870a1448d07addbc4a4b96123f41c8f169b9d89eb763a9430aedf9ed05e7bf4d88a68abd5f7b9ca37d50d58e6c0e4ee561f8c559c", 0x41}, {&(0x7f0000000240)="d730e75a2dd92cc75bdff300d7cb20fb49b20269edc625928226d4b2aed1e9218519e6e94caa280b171ec3768c6b9c3a28e0cfb0cc8e8f6c8ef98fb80044d1fa6cbf4abefd6c3ea4bb41a193212f8fa8d4d892df4f3aecfe7b5caadd5e0c4b3a55109d47f449c1f3b7723f9304439e1fe5982c8b49a40f00c97aef72ddff55516ecf9b59d7f79bc6cb3eff3a5a9f9c7c413982f77fce", 0x96}, {&(0x7f0000000300)="4e6d0a5d84141f4de9be76c8a1244bf3c73f62790372b3b760303a884cd706fc504049b47049f8ac88f5da512054ac4040c353256fd03fe7c227abbd2a759bbbf4c731f26543b0e0fd47c22263695e0cdb3d07d633ac4ff79c46d36a78152450f22257709922c0593c5c44c8e338907917ba559e761c65beb885bc540797fd1205d393af858d1b4f7c2348b39aca771be99a30a01f715d80d64d6d8062b408b92d9fb9ed00e84cead9", 0xa9}, {&(0x7f00000003c0)="d6116b9c687d7d0e93b57e22b6ca01c7da9e60a5e2f8a1675b1e8e36cf906227b91051e42a2b3fad32cb98034b4aff0573a0da3553d49fff417302246eb8c5d606de7c8ac8d559ca3b48cc3c3d53f8539d97c75e214014f3161ea2829effb8179c6915948de4cfd62c2594b748329f84dd39", 0x72}, {&(0x7f0000000c40)="5ce2e64049f1d74d2a6f07d9d6427b8d5a512b4871a5236ef25f9634f0aba191c156dc9c8bb918ba3389834f09b159e38c0e6c3caa332e1863bd3c7e35452040263527d58569b3655ffa5e3b220b768868f99d24a203467c683465d2bfeaa2b8595a32dc248706f40189755e65e06db349619b5c6052bf09de473cd029e113b87285a6dbb3a10c60751dcbfb578c9222d874b0a7ca1f22f73272c757c4688a29be1af7ab298daf0911f7daf4a2f94099e3d06c8756674039397d294d4b9278b9dcda10975350b1e93496aa2e7fb8f9f9ca610b9c7c9be3f41f855365726c751980d59e9b36b58b87fb506492415308ffb5614482bef27a157d4ef3039ae5713e6a43db22677ba4548f27e846d1f02509d16126855f2e8903d8731316da9fbd6bff37518199df74bec8ca5731fbbbeaa0cb1bf67819cdf29ab2b3573539b300c6eee992815bf71ded8e2c5f60c9280d5fa3a03899883cc9e4a0e74636421e5bb6d21d6ae71c4e8b3b56ba54ba7eff2a660b7eca021b0b4a2ea0beb3ebf921d435e53cc6de0d414f07cb01aba62f36bc50c049b9532aaa3d5333e095e120a77fb479490dd367245b7f3cfb55ffe73d7f447e5d901310e84534c666fe72f1b4fe132d9255f9a3a5e46481ed17f3c4677c12e97cf982f5d427fe57b4f95e3638e698b2b861f3e866756ffa925b65d00fd5f3978f685419586b5689c22a03f2e73601a11cbc6210f4c10a77a40803557f0f9c7d1875a7ba6ac7ef54959a89200644f9a9d1a39a88849d42c9ae79f193656792c5ca739a4dd61cc7b61b67eef859dd2ab5be31151a9b6bf153ca4fc14acd40e595c515b81513404f8c130a981393676a4289e1828b5f89f354a8c11d79bdabb608fe65db8c3fbd7d9aedef44662090ebbce81b55bb34c67eb7230ebd9c53046043517970123b59b3c4087fe0ec4f76e385e71e3ebcde109d4d921bb8ec9730e8ad176db0d6aea0c4b3a2cd15e98af5d99fb139b49a17dc47bd3cc464525f684874c8efb64c62afc2abbebd41d5d820ef989057ac2301349c1c22b051ebc85bbe0d635f2c120b5ea8e1c1e920ce5b38930d8e3b92e2c9627d4d64b7cdfc338019d10da412ca512efa88a0f25396cd38ec768eb0c9f86b53fb85fec3194219000e5ab46d1f356b78bdc81d14ec5e087ee8686466a94fd95e18181baea8420159928cf941f00795b0e94046ceeaa7bc0caa2871e77d33ba68d0777559db88399d39cb680e41b11463626767bf9cbd3629abee597fffbb00fd8548f11eea0050c15b07b3603423aece79310f5848709d1af34ad6d2d4672f29e8df23684809f9af1984be81a67b86c3b08594c95dd6474e020517fe8afe62e9f77f075d4c1413f0015869b355c0e5457d067127be8527954d853ba7fcf79b697ac45665ec779129e03851e382576055687cb203d0f96a7cd5081b36c7516e8b9ba337c0d15d4ea0b6f09ea14c7a28fd29e34cd7a981fb46aeac260747b8afb5b0e89f94b7bb12e022697010a59e1f6aabb07f5df95228b2b2c6bca85685abda734f2383e5fb33fc1578d0b98002bb2fe7da431fa18f7802faaf485c52e4c99f288e4849236ab75989c39e19a1e7faa9bc6511ff79e2cc32460b6e0297c54e572d10e159520124c9ee7561f4cdd6d8c8b4a1afe01744dd7a761a39c87bd08fa0224381d1a316b183afb8608fe8e8a77fb5fbe9bb7cdc7163f1a365400c06047a175946b2421b82fe56016bf38ac9bce084e46e4cc36ca5ffadea73bf6f898663fda0152ec4118a88d99ffeabba38514e2d824337513ced74aec75790a06167fea2fb986af06829532aec76cb0d75f1323e3e714caa5b53273f682a533c635770bb65a8b02909ea44bb769bdc53a96772616ea5e1698fdb0278b2c01c33a7d2bc86cd61d048c2aee7bf1625e9ba62e453bc343944524134c70aa4b3639b4964387c4b92101cd41092d307535b26a313c427c9809ce0f1a3a3d0187368110d3bf62eba282b4193e2da8dfa798d38023e0b1f4a25cdb75b800d3153dc0b43a634f0e1d04f5823189d7007705b29d0108179e068116c785f235cac219fddc2a25077f62a54c443b579aa2f5ab2a7f1216966e17f18e36f79442eecb0806aae8bc741287602594c132e0106604ba8e21e58ff940cf95e9f622b7dd3b072d313e961392e50eb8c414beb07f86d49fe0b2624188337c4f54138b62c5842ea00c96f5fe8b2459bbd61be4c557fa81b7f1321a8d4762c8d6635519e37caf71e97d4ef13e236b8d49258fab8bb3bc996437494fc3b3838d132c9b33f83efda4dec3a28ed7ff6f4f50aa1a0e1ebb7a846ffdec4468e1bc8233b92171bbe3ef90f9a14d559c3acc75e3857f3d1c50d402819063077e6a7ae18227e694595a04aa2d013e3ddb15b43ce0ac9eb589686020c5c0efed51ccb24eff1e79c1a971f50ccad0e9ab0a90729b235d62fb9ac1f4a3a41c5bd4c0cdd0829cea710e8bfb59e5c496c40789677c3d96be4944233a34ea44d4087547be3d7571a9d2a8ea41b3f28c67872be7a4316dd9d7450e5db35333f5abbbb681734170c6868b2afddaa5eae560410a13c71cae90611c3360c2dc43575ca8650e4cd20925e2a06bdf93ff3678b099a84a5758c5b5178c0d977d6c8a3d8d0253e416579f025ce466f6783925a36a4db939f36d0a3c29af306696f66a55a622c5b2cbd6841a066f5c72153e2fc8363353402f4c3794c447c5cd735d9d662447b47bb3152a8c7c732f54978ce5d5cc1d9ecfdb4097e60e52c5104abc6335d32f73799e69487204cfeb3623a3965a8a5723752685d350bc5f82eee9f72abf351215ed77288c592277ad389c593b24b4e00b47ac706346b618aea76ba2e2b954bab4c98e19d9191c765a174877f59e7f47577354c32307a323b9a95157768f9d7f9eb9fe2558356fd97ac91fdd51101fd0c335f4189dc4f1ee25dde375c059f776e7783bc8aad587f55f122bdae2fe40191c7785ad07ade725807c4598a9b4aa9619a19b26feafbb3a43dac28499bb6c1315f6c9251053271ba4d67d4cc91655dc9f416d7fac6e4fa50205fac5a666fcac1150d725925a25eb24b47ca6e6110a40c0aab2f812aaf9ee3b326ce5371ab51585e7e7406e401c280ee30130e11d1f1be142536863b481324af41dff8b36e8620772e8ddc9f29c02de96b0a8139436ceb01521b8b99c723e1b66ce8ae0dc0c9aae40b9ed0c01d85f940e0caedadb97cc5e65b29df28b2d5a61f8bc05dfe3f79295da7dcafa85b7d1ffb277693dc67e6c99142593c2417164dd2b9e5e224769387a3f3c9948a5a86b644ccdc3716d6bf491910686b58836006a1137d93a572e0f005ef4695f592ecc189957161fc706b550caa50b2ea170800fd2204825114bc68dcdd30900c5e4c987f73e067a357722a4894839eb96ee52097f7c682229576fe0665e0c000d7a7315d4e23e2d030f51aa5e22e04b750a81cab8a3a32fa6baa29b27f378ad2a26f775b8aef712b41d08f99c3f7642bb34732e771c36e45b6ad845e4bf6da48d53b198e1fa78553159ae14c3596ce7c051f884f3c4d06049c79a1eef51694d8de4380b8eb46be11523c1166165d4798884f7b42b8ae274a6e9369c39b64a7400dde26abcb52f3ba3136b0c2433b63d0f45930813661db3c81da1d1cf9a08e48ea10453c722c91d67598f15f167b8e27b2d459400a5f8f8364d773c4e0179cd7b90e4a7c5c41a828f11d2c89e68cd726bcf78e351015ca49f0e5e38a59dd802d1d52a39613996d7b290da708be32b3e609f6f92a7d48f169a163a68a8a1d5feed75042ffcf53cb229a03ed81c2ef8e197f2d99541afc52c6d1c1bd9200b2a8e32aa8b0e00515d67ca4cc454364ee21868646ad2483d38b28ed7330fc2b14fd979d6d949abc3e54d4a27fa19a3545bcbe43265b783a790df51dd7afefbe8ebc71dab86ad019abaf16a9a9834c1d76404376c1f7a7863fb76962aa9a8fda1c42485b083eac56c7c0f93b2da78efa21a0ef54328e678ac405614052aedf501fda8d9122429b8cb79b1fa86ddc70378439556bcbc6b124213a519f207cfdfde73cabadab143a0af70c480029becfedc0404eac602ed63cb940e8a11a7ad465963432a3dbf3b6aca4f13230ba7626e3950198446b255d7cf5bee30eb1b19ad153bd0d6dbf3bc506b55ec828eb7db7f2f676e34edef2557c63f93d038a09dcc858e5210641b72fc57cf9c23226ce68e3b39dc0ec2aa6d3e58767ea390da82274f5fb80d21fc62004ea77e29a18bcc47fcace6c7cbe058c603e60ea4aa185077bf54594667483aa9c1c493eeb377d911dc3460c1af764f50a4ba51ac1d35b0383a849e3b3ed1c8296f86af93af2445e873f48f5908defaf6fc40d76a7bf8bf285d46a752b6dc0ad0e10171bfb229ee3751f9be0ad19717ee893bb38994a5bd187cb5c1899ec84b2f8e3328c8db186925b457fc4fb28eecde932427bdb69ed593495014e2dd30cf9293074721f52ddbe0fc967288bd45c291888e1730d4ed670c672ddeca889a7988a0ecb347b0010c716607b6fe2c60045259538c39f9baf5ece8ecd2ff1995a4f97258cea5b2f13ef689f7fa1199577c8448fc6eaa715b0274563e0bb138fc1b96d520391f8e115675527dc0477cb494369f653194640a246e2deb8a5bcbfbdd4e02b61fbee372347f70a0fc5c1ffc89ea7eee31affa8ca7e44c6a670b5cad8690be0c84ae70616c0f2a42ecf2a60129f562120586c6bee6f7384d6e5632527abedc498aff5495ac0384293ad9c87e6fb261c0534f3aa125d723190769817ea8b2997a965e11c967848c80fd2d991930af1af4d9537284061ae9d8edbcd3ad44495a92c7da983f7e77ad4855580bb3b96bd2f92b5c4cd312dddea56f84bcd6fe8e0b3a88ae0e9bf0ef500c849b76f3bccbac4606b55f8fe0eae530c281af6010a3d32de38ed5d6b9d1f0edd7a901f6f9709d80d2d04d50379869dd2227d0d4b246d36c2f6a41e3b94bd47fc252639ec3eae2b361242a97ce6bb123549c4b29150f8c7bf7c04c3f7953d58c20683af153a38d9686486f714eba0dd2c1507792f8d1aa0b11541ce10ad31e287929b5b9dbdf173cb025790298ab5ed2500eff181178acd04ba7028306e3941f052a369b187ea4eafe3517b51d5b67ed6f9211f318318705af06c703c3020b93eaa6dfc0df4d6cfb26b383d20192091abc3c0f51329025ca988887b86c7a0f6921e68bce94409a21fd43d34767dbce54ab0c341694aa7d54a8ed763b1a74d79cb0311bc4c577b9ceb41d43bba46da511861353b2133b0ec51ed1cdb8a59532e18085009c4ea3d7fadb9a1dab79f33205c0a4e9c1998c87d4b2c80e1941342edc65ef7da3664ac4ea9cf447b8f02069a33a4afced1764c7a60b2135370924636821710c4f8b6e5318b5e18b422c6240b88b39fdeffac60c4c3c49499e77d8b1f7f45aa7f41731de08a592bf1f65611129d9b215d140a0ff404c3e36cf87eb291f29ccc3934ea0edee64afb136f134df1e7ad12613e91b34c4a9d1b74c349e0c64498f9eabdd872fb8b5a9837ee81f6c72af375456618d59f1999724ffd12be4e61d623d395694b23b416f376ebf94c76dbf5449068d709a251151d97f5aebf4f92e638aa3d8f66ac0a3e39e9c123d8def0631bfb4776ef2501cd5d6ab4020ee924f2f2c94613e3fd8289165c3c38f6e209e542254d59936afc573d99c23173b875ddc68933d7c75a320ffab20f72fe98e5112c66c3171754d889b803898403cfe3eb14ea9b8b3bac", 0x1000}, {&(0x7f0000001c40)="11611fe6525e9d0e11cf35e8c46a78bc835141d4018618d30f7608856ef2c89998126d1b5d42fc52f6a3aea9dfd72f776686b39d0d37c4d40e9bc3364507466c5f53b391e7dbb64f5d892db2cd5aeb0ef3a9ad6b0ff86a5d279b766b1cb1d0952f5f63260cdb4b112877d8792311cc28a9e420637e59c64e1202578ba0a171299bdab300e34f50c7a4ea20374fde253f24e5243b3dc97f5ff6175326b985a3906e6dac2c9549b405692d5500c19c77ae7519e2dd16885d6028f01e46a1913a0a7e84d594baace5e806f3496f8d860a049d24dd2f890071a22b6a57fbb33e3a8bb3167e17bd68381e2fd3daac12e80a73ab595cebc99cf7ce78be3fb40395acc5734a63d61c301927351e4b788d9a0191346ab54dfe5aafa6d2fc0db5957d0c5373228461310cd4b4eca83e85d09b72aa2eab555be1bb39d6895a50fc52af1baa07698d4ed1b2e692a685e73d96f71a9adcf29aea14ffeb7b47136f5f3d2b729f31bacdb8f4c397495cd3fc3a2ee0456a7cadea82a55286cb529c95b8037c3cbe1efff63200197b23631d124c8f6384dd211a8c44f27f1c8afc8ff8fe1e9ad938af37321622ebdbe09d87cb9f7156a11753b74d72712d429ec3429f518b1b35ae9df610a9070afea3c641c6be5f3b038907904223f590d0b97d6f3e6c24a37981ef9670530b7e45020b0374f94dc85bd18162d5cea9a3a1e35bbf3a86b75121f435cf313bdc2cb8f315eead65b5d0f3167976594dfb0e23e26e490249fb16b05ece6d609756e39cd5f42b9077b2edbba515a5963dd70fd35de7c47098b8e09524b9a0a9ee41f3e89f9aa072a4d4dc681f338b6c5c32bdc6d12e32c093224ca12cfbfbd8ed48b10dfd4b7dfb33c9b5e8f5f1728fcf3e0d96a6bf64596a2cf77add7deac848c4a1a57d6e0145758f33f4a345d29d036ac4ee89be26535753d6d0e431d5ab7420a9cf7a132941c55809a9cde25ca3410f8d48037c13f3e75041ebd177b7dd5a4dbc3f6b169bbbc2625843df93bd598f02cd5811a61ecd6760d1659f63ba902673465875a39da68d4a49e29e6614d2ad1d8ade3b195e2a2d7ff059ca3e2d8f6b175da90a10b1c0fb232eff970e17ad48c4398de1e434344ff6efda719a4e0a13f9e1f62ad5b7b88fcf061a4d82ab9ce998c885c83f4b2643b5ec786fbc94bc54a6102d0231c2708281c253417d168c728a38c1605dd955753a81a2db6a9762888d4be4fcef79ab4d2e24ddd696b149d648f858dff9583391b1d5085b1876d3c0db13c1834ffdea29069fa1a889d245a904fd782ed7bffd9824abddfb0dd2206fb55057950ea663ea4f6e70add6cbbfc0730b24168e82897ef1caa8da87af149704a6d6a5d7784d21c796ab687e623983add4889107ab54bf3f9e1762df89f05aa87ef1bb2eb86a5ccbe4af87b9f0ff83a690d154049c9bc428248291d5992bf498f96b7bc3e4fe9b842107ad818c9f00995afc6c4db0024b1759dc9d8e1ec0b452c2dd5422aaf2948bfa79e202dd7200a4ca9a73991424dd3248880ae4f3ffa768ddca90ccb345730c11bef9d1926266f847f389c26c4827d3a3b68811af51689f432cd74f0b3e0a462e971b51c3e45e97b12e5245f2c2a664de82ab43f7499fbae4cd4c0a8ad0e57e6c7b1e00aeb3aacfae70a947bf96a2099bc35b4832c0879dec9d12cf4963d2758ccb1187792e522c7c2285c7cf3a8636f19a6ca8afb80871800970948ab65234dac0994c167e53a49a4d960a30e379184173295246aafe255251f7934d20e3f233425c347c8d5a1e9707b0e1820fbe339bc9e05c65641f2c750ae47e4562f4cdd1f264ee78da3a82e1fce78eb6cc4fdd6ff27f645fe7edbdd8c51208097264a45b386f5be8aec382abd38372ef125265f099dc9d9303e647fc3f3e1140a26f2615e7ee1fb6a11c324619e4eff7e1c56466dbfd2761fe7ac3a152033a82676c55d33ac4a0bef815a22d24100c845b34fa219f326a5cd7de3f8ddb040afe8191ad7e2c0557e0e1e16840ad0d9831cd86d2f7dc38b2bd0359bbfdb1a26cb74218645ddd4172d5a54bbf5e4dfaec24bf9e53176835a8ea02bc9d117812ff731d68aa13c7301df1860001ca6003c9c71b67283c35d90f20d75a66661e9c94f459e918baeafdfb98f0affb9d8129b690e6458fd02e4f2e55ec43ab752c1656456c5f2ca448a0ab1c25d82b518b986707c354be76ac7a13020fdee15986d360dbd893e588d870e19ee395c1456acdbe5cc8b203bbbd17f94b4256417467013bdd4cdd37157753cd9d16a977185043daad05ca93a9a7bc874aab3a159dc2dcc9ed9265e66c145d8ac66297d4c00e9fb43dce7ec53271c8e360734bd87f8146bbff19e62f7303a210dd5c7ba8d90174182edbb4da358910f856884abf33d17ac0dea5da9790f1aeca1523fba0ae87740eb4df16bb1be6eef1c33d458eec369c062a2f05cceb33baf88c48996dcc63bd04c11a81472cbf0b28669140e5ce176a8d99ac9ad4a35a3688c3cba709d710655c2a966385dc153330bb1f8d9b98b051731a635cd25be1b6c95da718bfcdfbf3e591cba250c611f14f6425975935c120221e5af82e7f0ff9909255b4792fef90034355f1d559b12bb78b9c08e7133cfd1bdf40bbe54518f29487a660ed492449834b9b807801f5d4b931bd421e82fcce883da1d39c850d953462852d1b11855092953c6fd5d8eb78bd71b41f6f9ad216a827a172d9fda2ccb19124f6f6ab03f436cd527fd7c850a13514c4a378e71812b5bb9d01cac124a8c79973ba91d817c071a2a40941728d180fc88fe79cf2b2c2f6762135e9f6df86ace9d9e072b2fc4221615f2a266c1e9e16cf6a872748d06ebb8553c700733217ec0948fa8093dbaf9c5b1f7f92b0db0df48b1c86a4ba797c1c9e43fbc0621e8708d507dfece9939c7632b8b7733a9089a0cc19452937e0fa6602f976b618f72fe3d5652662b9388ae73e85823464581f1968ecbc1a97cc83855c2d6eabbf56adc3a73b98a6693cf28e0124d08b1395464880ca51d61a5f7b8ef0aac825c1a1a1f1df0ae894aa1a64d64c91604949ff219844416687a2e4e52c6a2922f8ad49cc17a0067664d967917271d9a52e97159b18f3e8666a5ead3ed182aa89944f1c1d3e4bbd3bbbc82bf2c0ba8531aa717dabf373d4885853b4e1ae04078a7655d017df716063a7aa9266ffc5f5e6675bbfc3e61f34b160f4f9b7413a488e9e2a0e2f7c724b126128bde99d963a2dfc89832a6d7454082d510e9c8e4136b60f835ea6221786bd342c2f8831fcb4fe16a6510f4b461b95cb22859ac6a63885a3a7f48915e86686118df5e4bc818440a37623209675154af57924c52494d95a268f9ae0e2e510f5932afd28ae1cc0b24bc1f28669e335d73156bbb00cf15df62b6cc95ea4ef998a1fd20d450c5a93fb8f36b2f0051777631e56ca3d823045bfdf594290b3eef8bb957633e828825bfe7baad80058b4a8ee89a1d68370b32cbeea468aa922be54d6af8ea7318a6d02238b8924d54ffb8edcbeb897b42f628e22b7b807b20e78a1ef9adda34776eb74dc6361ce8d899390cffe7ac13a8da138cfe4092870550b152b5d63e82f8593b91f57efcb44434016c3fa793b72a43a9804ef20324bc4e02fe5e145127f3e324b77299c9c6e6fb1ff23b0e7ee26fe52319ef4f62cfef825268e48c865a7fc25d15ff1c1450b597f6f8dcfe2fcb06a0f4884b3d58d1029df6f96ded129c02143136c0a029d8f6bff6bb5b00ca71ac6f11780156948fb5c70c321c0c5f331e3c5a9d130bcf66a2abd35c3c2ffcc744805d04a13876696c66a3ed91c56e1b17c08b37a2338795cf9a0aa135262fab94556f007bed2579ca7934c4e58c69365859483b8d27f8dd22aed10", 0xac3}], 0x7)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000040)={0xf66c, 0x0, 0x10001, 0x7f, "1c10260974612c330000fcff00"})
writev(r0, &(0x7f00000000c0)=[{&(0x7f00000009c0)="044a00b387e09f68566d4f21e4047fac7d7a7990c2db221643cb3465c53e1dcaf55fdac1a45b6d08d2b8be0f705cfbf316caf1f77c921b757708b43888baffb813ea7a6160c98471556366306595d5b3c0f8e1d787f69217a6cb78dc4576b9f70f83e87c8d8d3ee0e54711044d5a4998bd43ded6290e9b3bdeb17be371cf725f15554b41f82d94b1d83587a749ddc6a1c813331bbbf06c1cf0847fa0a8bf63bf2dee0519847c4e6a103ca1d8c2c92926544f2675a17657cf09d55fe37289c319e9a13a3c1a8d4b10b3c6f35e341e3563617b8739f3ede277fb0466a3bd1207b11f30126a4c10172af23aa8dc65d40ce1b8597692fc9021455ee50bd0c84783ffaaae3a9295f7cc5a85f946fd140b485d67169ee195b1412397511f934e8429bd5ba5a80e6dac8a7ed7cb8f85bb6c1ccd916a0f4e33886ecab5f7c77d060204546da44029def101a097281704df8ccbed2562ba063b4482618b9e2c69a4dc351a0111a939e87bcbbd7bf4a057b6c3700ceecd3f2ff2e878958226692abffd003f07695a2be7b9fa150deabad2ce3a3bb6ec50812f6b06aa75ae8320faa19ac8bca9688884b07b49d6a4e3f239fb8ab1bffff642acaa783680d97f08a2caf9b17335925b3944eaf9996a2deb3f2a3e5c4506c6a0f1ff17aeb01640db6d902bff1533f7ee33c6af797707e3b670b53b7f80491fc66a3fb401c64b8b8a6b0bcdd3ac80ed", 0x202}], 0x1)


kqueue()
r0 = socket$unix(0x1, 0x2, 0x0)
close(r0)
socket(0x6, 0x3, 0x5)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
sysctl$vm(&(0x7f0000000200)={0x4, 0x1}, 0x3, &(0x7f0000000240), 0x0, 0x0, 0x32)
r3 = socket(0x11, 0x3, 0x0)
sendto$unix(r3, &(0x7f00000001c0)="b10005", 0x3, 0x0, 0x0, 0x0)
writev(r2, &(0x7f0000000980)=[{&(0x7f0000000380)="80ecd993af8e500876c3890067a5", 0xe}], 0x1)
pwrite(r1, &(0x7f0000000140)="a1a5537ea29fb8c6386c0d25c172", 0xe, 0x0)
semctl$SETALL(0x0, 0x0, 0x9, 0x0)
semop(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x16, &(0x7f0000000040), 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
syz_emit_ethernet(0xe, &(0x7f0000000000)={@random="b5e100", @broadcast, [], {@generic={0x8848}}})


r0 = socket(0x18, 0x3, 0x0)
sendmmsg(0xffffffffffffff9c, &(0x7f0000000180)={&(0x7f0000000140)={&(0x7f0000000000)=@un=@file={0x0, './file0\x00'}, 0xa, &(0x7f0000000080)=[{&(0x7f0000000040)}], 0x1, 0x0}}, 0x10, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
ioctl$FIONREAD(r0, 0x8080691a, &(0x7f0000000100))


r0 = syz_open_pts()
ioctl$TIOCFLUSH(r0, 0x80047410, &(0x7f0000000040)=0x8)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x8060693f, &(0x7f00000001c0))


r0 = open(&(0x7f0000001700)='./file0\x00', 0x70e, 0x0)
mmap(&(0x7f000000e000/0x2000)=nil, 0x2000, 0x1, 0x10, r0, 0x0)
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
ftruncate(r1, 0x8531)
setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)


sysctl$net_inet_tcp(0x0, 0x0, &(0x7f0000000000), 0x0, 0x0, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x10, 0x0)
ioctl$WSDISPLAYIO_GBURNER(0xffffffffffffffff, 0x400c5752, 0x0)
munmap(&(0x7f0000ffc000/0x1000)=nil, 0x1000)
shutdown(0xffffffffffffffff, 0x1)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000240))
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000001c0)=[{}, {}, {0x6}]})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x8020691f, &(0x7f00000001c0))


sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x12}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000000)={0x2, 0x5, 0x2}, 0x3, 0x0, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000040), 0x3, &(0x7f00000000c0)="d2fa771dfaedc416be08851c851dd66dadf7c56dd8ca69c641ccffe9009d0dc9d80c8e5018", &(0x7f0000000200)=0x25, &(0x7f0000000240)="5ffe97428cd7348210a28d6ace527385203c48a7e2a9a9d164ac592d2f2f4a84b1927af2d580ee24a1060ea1243b2e5db4ca5f6fd2fa41b44e24163394569c4edf0719adf41de61c52ad2c0617e2b0e8dda480b4945b041c464e0c102eb77264b9081a6e4416c4e766e5d9a64d079a3664f0aa10a1c66f2d137b51165b5bee4f0c10a8f7498a07a9fa78a7e4f1cd4959c5662f4e4c3a7bfe4d356bd85c0a2dcffe690c88e29072cba4aa64228765ce8328fa4fd895118e44885dc152942116dadb01904be11bec31f05509000000c9e4c6720c6d680c80881ceec17cb490519a64dfd9c30530b8c5c83abfd91b0a791cf731d2fecc822993095b45e0ef3668e153a35d2a9455239b204c66c4a992e462f0944749cb73e66f4bc458691ba474a1c83f0e8b55ae16770b36eaa48bbe176183adcfe20e8bcf46281cdf0e238f909aa0fa772f09203e02c874371e96336b433879ae649bb57c2567edcdd2c102d81bc0dff9864550f083ba465aadd93532808ec4a9b8cc1360ea4e3c770f61c25ef4c044", 0x182)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r1 = geteuid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, r1, 0x0, 0x0, 0x0, 0xb2}})
seteuid(r1)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000001080)=[{0xe6c, 0x0, 0x0, 0x800}, {0xc, 0xff, 0x0, 0xffffffff}, {0x3, 0x1, 0x0, 0xfffffff8}]})
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000080)=[{0x3}, {0x54}, {0x40e}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
r3 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r3, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000005c0)=[{0x24}, {0x34, 0x0, 0x0, 0x4}, {0x16}]})
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000240)={0x0, 0x5})
r4 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{0x2c}, {0x40}, {0x4000006, 0x0, 0x0, 0x3feffe}]})
write(r0, &(0x7f0000000180)="23009100007adb020317bdda2b7e", 0xe)


socket(0x2, 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
socket(0x1, 0x2, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0x0, 0xffffffbf, "0000c6f26461c094f4ffffffff00"})
readv(r1, &(0x7f0000000280)=[{&(0x7f0000000600)=""/131, 0x83}], 0x1)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000e00), 0x0, 0x0)
close(r0)
fchown(r0, 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r1 = syz_open_pts()
close(r1)
syz_open_pts()
writev(r1, &(0x7f0000000440)=[{&(0x7f0000000380)="190d", 0x2}], 0x1)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
setitimer(0x2, &(0x7f0000000000), 0x0)
ktrace(0x0, 0x0, 0x40000934, 0x0)
open(0x0, 0x0, 0x0)
socket(0x10, 0x8000, 0x0)
socket(0x18, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000480)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
unlink(&(0x7f0000000a80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0}, 0x10, 0x802, 0x0)
connect(0xffffffffffffffff, &(0x7f00000000c0)=@in6={0x18, 0x0, 0x9, 0x80}, 0xc)
ioctl$BIOCSDIRFILT(r0, 0x8004427d, &(0x7f0000000100)=0x27)
socket(0x36, 0x4000, 0x1)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
sysctl$machdep(&(0x7f0000000080), 0x2, 0x0, 0x0, &(0x7f0000000200), 0x0)
socket$inet6(0x18, 0x0, 0x0)
getsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={<r1=>0xffffffffffffffff})
setsockopt$sock_int(r1, 0xffff, 0x2000, &(0x7f0000000080)=0x4, 0x4)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000700), 0x0, 0x0)
r3 = openat(0xffffffffffffff9c, &(0x7f0000000040)='.\x00', 0x0, 0x0)
mknodat(r3, &(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
truncate(&(0x7f0000000440)='./file0\x00', 0xffffffffffffb5ea)
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f0000000040)={0x0, 0x0})
ioctl$BIOCGFILDROP(r2, 0x40044278, &(0x7f0000000140))
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x4, 0x1100, 0xffffffffffffffff)
socket$inet6(0x18, 0x0, 0xff)
r4 = open(&(0x7f0000000040)='./file0\x00', 0x40, 0x4)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r4, 0x0)
nanosleep(&(0x7f0000000040), 0xfffffffffffffffe)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x8040691a, 0x0)
r5 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r5, 0xffff, 0x1021, &(0x7f0000000000)=0x5, 0x4)


r0 = syz_open_pts()
fcntl$lock(r0, 0x8, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1000300000000})
flock(r0, 0x0)
fcntl$lock(r0, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x6, 0x100000001})
close(0xffffffffffffffff)
syz_open_pts()
r1 = syz_open_pts()
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x2}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, &(0x7f0000000000)={<r2=>0xffffffffffffffff})
writev(r2, &(0x7f0000001100)=[{&(0x7f0000000100)}], 0x1)
openat$pci(0xffffffffffffff9c, &(0x7f0000001740), 0x0, 0x0)
accept$inet(0xffffffffffffffff, &(0x7f0000001780), &(0x7f00000017c0)=0xc)
sendmsg$unix(r2, &(0x7f0000001840)={&(0x7f0000001140)=@file={0x1, './file0\x00'}, 0xa, &(0x7f0000000cc0)=[{0x0}, {&(0x7f0000001400)}, {&(0x7f00000014c0)="da2e70e46985c94ec3790457957bda5a257c6f8faed17584d0f47961dc549175f1402d00474e01226c7dedc536f133676ce9f3ae3d7688c5a7872fb8edf11a7a853a9b0d9d53f03ccc3b2e5c8259143672b51b0b35a6b97045137e00ea1d8a76d71e065df73e19bc67f9ef4570e92be0c69947f978b0cfd1612aa61a3e411753167c08f15510b3c884dbe7e23d552af5d2e13f87b045", 0x96}, {&(0x7f0000000980)="1866abf92bd7a2107dae4a35d54b1381f73dadfa6ea5c72fd51e158f57deafb60b902570f3ab98083f2ccdddad366b6348b4f7d3ae0e943cdd4b0e559ac224be7e5706bfbfdd4d4a3a9ebaab9aedb0289d0d87b97f00d6e79dd01bfe3b39e9e81a40e27526af1efff1de7622beb143f20a85760ec40eca59f19d5f06e4a4ab2766c698b8509aeafd2ad65f69af388ebecb1793673b34aff22bed0daa308321c831b38bf2c6fa07eedfdf944aef12b9eb191a5c8fa103802a8fa7d9c4e4adc67afd51e29f19e8fb4f4bf78107092d28959b902224bac4a72417916045e2456829857680cd91e102d47b4041", 0xeb}, {&(0x7f0000000a80)="e5c05270b45bef7e2978c9c99ec5003f216393c471460e2db738f006bc51b1f32fa2f9411181a05e087865b4870763665f610b18cfafa53c7ced94ed802c20b61b9042bec103251209ecc868ad01be9dbcd0e592be30d9710f5ca43e8e21c55d1b4d3d4c8a700d47b3a5642097f172af6c0bbab9c6775f9938e0b1fac2fa149e5c3b945085a11119fe556ceb8bfd719b9bc5d82b0e31096416dbb42fc9e3a87456dd3a8980332b13", 0xa8}, {&(0x7f0000000b40)="ea9b8f392ac5ffb1523bfa1dda96ef2de1c71b15cc0b6d4279ed7e464c30c7b9dab007ff142f0f748368b135fb6318da581044528abb627a1511a7464b492be41bff1d50754ae1082c21a5cc62badad2a42e2b6736b980431ae526ba50f78060391fcb19fd7fedb9b3d434119f5ff00623ce251564798d4492994df23b1d9f48380e76a1eb311abc26f5c5cf1fbed8042dac44", 0x93}, {&(0x7f0000000c00)="e81e2e939c0d5b", 0x7}, {&(0x7f0000000c40)="029317cc5181822e85ed081d5ddaa4cb17430fd1c3f0856914f26fc6c1974d97c2ba9cf92db5b31e7f8de65fbea1b72367c9807a37bf7086c77fab4a137165263befcca854cc1d6f1d8f1a1c53e24133604d6c8b70298f7dfaf11fa2eda9f41a9d6c47d26ae48b08", 0x68}], 0x8}, 0x3)
connect$unix(0xffffffffffffffff, &(0x7f0000000000), 0x1)
r3 = socket(0x2, 0x3, 0x0)
bind(r3, &(0x7f0000000000), 0x10)
connect$unix(0xffffffffffffffff, &(0x7f0000000000), 0x1)
connect$unix(r3, &(0x7f0000000000), 0x10)
sendto$inet(r3, 0x0, 0x0, 0x0, 0x0, 0x0)
socket(0x18, 0x0, 0x0)
sysctl$hw(&(0x7f0000000140)={0x6, 0x9}, 0x2, 0x0, 0x0, 0x0, 0x0)
sendmsg$unix(r2, &(0x7f0000000580)={&(0x7f0000000100)=@file={0x1, './file0\x00'}, 0xa, 0x0, 0x0, &(0x7f0000000540)=[@rights={0x18, 0xffff, 0x1, [r1, 0xffffffffffffffff]}, @rights={0x18, 0xffff, 0x1, [0xffffffffffffffff]}], 0x30, 0x400}, 0x7)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000140)="b1000504000004000000000010000000331c13fecea10500fef96ec0c72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a421020000ed710fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b1257aea8c500002002fbfe0c2300008abfba0900000008e371a3f8343732051ed6b71d89e0000405f8ffffff13000000", 0xb1, 0x0, 0x0, 0x0)


r0 = socket(0x18, 0x1, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
ioctl$FIONREAD(r0, 0xc02069a5, &(0x7f0000000100))


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{}, {}, {0x4000006}]})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000006, 0x0, 0x0, 0x0, 0x0)


sysctl$vm_swapencrypt(&(0x7f0000000000)={0x2, 0x5, 0x2}, 0x3, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0xa}, 0x3, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000000), 0x6, 0x0, 0x0, 0x0, 0x0)


r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0x2e, 0x0, 0x0)
getsockopt(r0, 0x29, 0x32, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000040)=[{0x45}, {0x61}, {0x406}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000001180)={0x3, &(0x7f0000000000)=[{0x54}, {}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f00000000c0)=[{0x2d}, {0x30}, {0x6}]})
syz_emit_ethernet(0x1019, &(0x7f00000000c0)=ANY=[])


r0 = syz_open_pts()
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000000)=0x8)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCFLUSH(r1, 0x20004268)
fchownat(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCGDIRFILT(0xffffffffffffffff, 0x4004427c, 0x0)
mknod(&(0x7f0000000200)='./file0\x00', 0x10, 0xfffffebd)
r2 = getuid()
setreuid(0xee00, r2)
setuid(r2)
r3 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{}, {0x4f5, 0x0, 0x1}, {}]})
pipe(&(0x7f00000000c0)={<r4=>0xffffffffffffffff, <r5=>0xffffffffffffffff})
readv(r4, &(0x7f0000000000), 0x0)
select(0x0, 0x0, 0x0, 0x0, 0x0)
pledge(0x0, &(0x7f0000000000)='tty\x00\x00\x00!\a\x9bp^|#\xcbhl\x97\xaa\xe0\r\xe7\xb9E\xdf\x1d\x96\x01\x98/\x0e\x17\x95 \x95Mj\x84+\xf0B\xaaYu^\xa0\xc9j\xdd-I\x01R\x00wY\x1d\xd7\f>\x88_\xeb\at\x91\xd3\xbf\xea\xddt\xe0\bt\x06S,\xdbH\xa7-\xaaw\xcet\x044\xc5\xa9e\xa9\xf6\x1b,\x99\x8e\x05\x86\x91IsC}~K\xd97\xae\xb9u\x1c\xfc\xb4Nwl\xaeu\xad\x9b\xaf\x04\xc4\x03\"F\x8f\xd5\xde\r\x8d\xa1\x00\xcc\xd7\xb6\xe1\xeb\xc1>\xbd\t\xc8\x15\v\xb0, \xee\x9d\xb8\xbd\xfd4\xe0\xbf\xa0\x1es\x01=\xdbd\xf0?=<l\x8c\x01\xe3\x05$\x1c\x04B\xa2\xa4P\x04\xcf\x87\xaa\x96i4\x14{/\xe6\x87\x9d\x8f\bz9$\x10_\xd8E\x93\x8d\xf5\x8au\xab\xf9)\xf5\xa6\xc7\xc8\xed\xb9\x1f:\x03K\xa2\xdbx\xbe\\\x19\xdax\xeb_W\xbb\'\x00G\xbb\x1f\xe3\xd58\xf4:)\x10<r\x1e\x06p>\x8af\nn\xd4<\x00\xec\xe4^\x00\x00\x00\xca\x90L\x98\xc9gty\xce\xab\xd2\xa1\x85E\xe2\xa9\xd5\xab\x83\xda?w\x83\xbc\xcf\xd20(L&b\xed\x8c\x1d\x1a\x9fd\x99H\x9e\x82\x10\xea\x05\xe9A\xe3{\x8d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00zq\xdb\xee\xa1|`\xb4\xb5)t\x95S\xc5\xec\x10\xc7\r\xe4\xfb`R\xc5&\x9f\x90<\x81pc\x1a\xfa\xe1\xc3\x15$\xd2\xaa46\x8a`\xf0\xc5\x12\xe6\xd5\x9d\xb9%\xd8\xa8\xa6rN}\xe2\x9b\xb4\xfc=G\xc5\x03\x91\x86\xf5\r\x01\x00\x01\x00'/415)
syz_emit_ethernet(0x138, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
kevent(0xffffffffffffffff, &(0x7f0000000240)=[{{}, 0xfffffffffffffff9, 0x0, 0x1, 0x23, 0x1}, {{r3}, 0xfffffffffffffffb, 0x50, 0x4, 0x4, 0x1000}, {{r0}, 0xfffffffffffffffa, 0xf4, 0x4, 0x7f000000000000, 0x8}], 0x8, &(0x7f0000000340)=[{{}, 0xfffffffffffffffc, 0x8, 0xf0000000, 0x6, 0x5}, {{}, 0xfffffffffffffffb, 0x80, 0x1, 0x401, 0x5}, {{r5}, 0xfffffffffffffffa, 0x10, 0x0, 0x9, 0x5}, {{r4}, 0xfffffffffffffffd, 0x9, 0x8, 0x0, 0x48d4}, {{}, 0xfffffffffffffff9, 0x10, 0xf0000000, 0x9b, 0x5}], 0x1800000, &(0x7f0000000400)={0xcb, 0x4})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r6 = socket(0x2, 0x1, 0x0)
connect$unix(r6, &(0x7f0000000000), 0x10)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
open(&(0x7f0000000280)='./file0\x00', 0x615, 0x0)
r1 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x520, r1)
r2 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r2, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x0, 0x0})


open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
sysctl$net_inet_carp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x4}, 0x4, 0x0, 0x0, &(0x7f00000010c0)="f5c9594d", 0x4)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000040)="94c79bd261e1e88e83beb11c0a3e154df77b5335bd1667d9fd77c59297b3cad0ade427f63f2912518a179b7c207bc5ba040a20b5c36bfaca54e49900550bad2f165552f266a6b12d4900c56a22e814223e67a3fdf5ae19bcbb5d0a815015db8752d03d1b08f84b4976ec52d4a82598424ed3a6a523a3591db0e862a2f4dd1168cb17845fff1fb5df5535cae3e20e2bdb92138d0c1b0720e1c121ccb763f092cd5dcaa3d901", 0x2cfea}], 0x1000000000000238)


r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x31, &(0x7f00000000c0)="b211d7170d816685c8e360f2fa41c1a0946988b272d2dd3dc90142a84231a746e337b372e93320cff6669cbe7868de45ed3fc33719ca6df71ecec8a918458b2c10a1f8c66653b276e180e9cb9b21f9982230f575295d48889c9a920796b2dd92fc8575680b37ba955d2c15e6d7c9198ed900ab006ddfb67869b51a2216114d1ece85f593e74035f5bc054eb1dbddf42a", 0x90)
getsockopt(r0, 0x29, 0x31, 0x0, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206913, &(0x7f00000001c0))
geteuid()
socket(0x0, 0x0, 0x0)
pwrite(r0, 0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000380)="b1000504000004000000000003000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c03", 0x5a, 0x0, 0x0, 0x0)
socket$inet(0x2, 0x2, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
r1 = open(&(0x7f0000001480)='./file0\x00', 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$TIOCSETAF(r1, 0x802c7416, &(0x7f0000000180)={0x0, 0x0, 0x0, 0x0, "0700000000ed0c8800"})


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000280)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000340)=0xc)
mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
chroot(&(0x7f0000000100)='./file0/file0\x00')
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r1}})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4e}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000180)=0x66, 0x0, 0x27)


symlinkat(0x0, 0xffffffffffffff9c, &(0x7f0000000380)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/file0/file0\x00')
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000800)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000000), 0x2cfea}], 0x1000000000000013)
close(r0)
execve(0x0, 0x0, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
r1 = dup(r0)
setsockopt(r1, 0x1000000029, 0xa, &(0x7f0000000000), 0x0)


recvmmsg(0xffffffffffffffff, &(0x7f0000000200)={&(0x7f00000001c0)={0x0, 0x0, &(0x7f0000001880), 0x0, 0x0}}, 0x10, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r0, 0x80206980, &(0x7f00000001c0))


madvise(&(0x7f00003e0000/0x1000)=nil, 0x1000, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000240)=[{0x44}, {0x5c}, {0x6}]})
syz_emit_ethernet(0x2a, &(0x7f00000000c0)=ANY=[])


open(0x0, 0x0, 0x0)
getpid()
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x3, 0x0, 0x0, 0x2}, {0x45}, {0x16}]})
write(r0, &(0x7f0000000180)="7f23a3c23cce2575e1dd92c25683", 0xe)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x400000002, 0x0)
r2 = socket(0x18, 0x1, 0x0)
r3 = dup2(r1, r2)
sendmsg$unix(r3, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


r0 = socket(0x11, 0x3, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1002, &(0x7f0000000080), 0x4)
mknod(&(0x7f0000000000)='./bus\x00', 0x2000, 0x6380)
open(&(0x7f0000000280)='./bus\x00', 0x0, 0x0)
close(r0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000280), 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f00000001c0)='./file0\x00', 0x0, 0x0)
r1 = open(&(0x7f0000000080)='./file0\x00', 0x1, 0x0)
ioctl$VNDIOCSET(r1, 0xc0387200, &(0x7f0000000340)={0x0, 0x0, 0x0})
setitimer(0x0, 0x0, &(0x7f00000002c0))
r2 = getuid()
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000140)={{0x1, r2, 0xffffffffffffffff, 0x0, 0xffffffffffffffff, 0x7, 0x3ff}, 0x0, 0x0, 0x100000001})
msgrcv(0x0, 0x0, 0x0, 0x0, 0x0)
pipe(&(0x7f00000000c0))
sysctl$kern(&(0x7f0000000040), 0x1, 0x0, 0x0, 0x0, 0x0)
read(r0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
socket$inet(0x2, 0x3, 0x0)
close(0xffffffffffffffff)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000300)={0x3, &(0x7f0000000100)=[{0x25}, {}, {0x106}]})
syz_emit_ethernet(0x3e, 0x0)
ioctl$BIOCVERSION(0xffffffffffffffff, 0x40044271, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
shmctl$IPC_SET(0x0, 0x1, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r3 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r3, 0xc0106924, &(0x7f00000001c0))
r4 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r4, 0x8020699f, &(0x7f0000000100))


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040))
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000140)={0x0, 0x0, <r0=>0x0}, &(0x7f0000000080)=0xfffffffffffffde2)
openat$bpf(0xffffffffffffff9c, &(0x7f00000009c0), 0x0, 0x0)
fchdir(0xffffffffffffffff)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r0}})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
r1 = socket(0x18, 0x2, 0x0)
getsockname$inet(r1, &(0x7f0000000080), &(0x7f0000000040)=0xc)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x18, 0x3, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000080)={0x1, &(0x7f0000000000)=[{0x34, 0x0, 0x0, 0xf7d9}]})
ioctl$WSDISPLAYIO_DELSCREEN(0xffffffffffffffff, 0x80085754, &(0x7f00000001c0)={0x4, 0x1})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r4 = socket$inet(0x2, 0x2, 0x0)
r5 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r5, 0x0, 0x200000000000b, 0x0, 0x0)
dup2(0xffffffffffffffff, r4)
setsockopt$inet_opts(r4, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0x8)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r6 = socket(0x18, 0x2, 0x0)
r7 = dup2(r2, r6)
sendmsg$unix(r7, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4e}, 0x2, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71", &(0x7f0000000180)=0x15, 0x0, 0x0)
mlock(&(0x7f0000ff9000/0x4000)=nil, 0x4000)


r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x27, &(0x7f0000000000)="5ab7776a", 0x4)
setsockopt$sock_int(r0, 0xffff, 0x800, &(0x7f0000000180)=0x2, 0x4)
syz_emit_ethernet(0x52, &(0x7f0000000080)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaabb86dd60000000001c000080000000000000000000000000000000ff020000000000000000000000000001"])


pipe(&(0x7f00000000c0)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
write(r1, &(0x7f00000002c0)="04", 0x1)
write(r1, &(0x7f0000000040), 0xfeea)
readv(r0, &(0x7f0000000200)=[{&(0x7f0000000100)=""/198, 0xffffff0a}, {&(0x7f0000000240)=""/16, 0x10}, {&(0x7f0000000340)=""/212, 0x1b}, {&(0x7f0000000440)=""/225, 0xe1}], 0x4)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
writev(r0, &(0x7f00000000c0)=[{&(0x7f0000000000)="96e9cf1c0f9fc25ac05e6f4ca619d5d43e2ccd0abe6d02d16ed0cd5bd48a411a9682f3af122a4ebc7a021c6f87a74123", 0x30}], 0x1)
r1 = socket$inet(0x2, 0x3, 0x0)
getsockopt$sock_int(r1, 0xffff, 0x1025, &(0x7f0000000000), &(0x7f0000000040)=0x4)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000080), 0x140, 0x0)
mknod(&(0x7f0000000300)='./file0\x00', 0x2000, 0x6da)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$vnd(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
sysctl$net_inet6_ip6(&(0x7f0000000040), 0x9, &(0x7f0000000140)="d636cec111a88106f52ab4fa160045df5ef234d58e301c3edf15ae12a1c77e0250fb2cdf005364633722600ec45a46d737cc", 0x0, &(0x7f00000001c0)="84e5d0a669106f0d6388fec7acd5f15769ef612efa586579bd66f96359813fe0548b9785be4462a5e7a7d3c303c0c794d7eed9a446e1afc4985563641590aed39419bd55bd3496d7c3bdeaf9b29ca436f5c650623a67792f13a922aba80ead85aab8d0e12991f37de92da5ff7f000000000000887b5e0dffb3a6bf1edc12afb6fda07fe614518a906b40d2aae6c0b29c0ee9ce9e0b33a2d5bba9c522225dfcb2c0aa8b6bdf5b1b96a1b0ba7a71f11d61c72b5160e0ad444b20e9eff851f8d39b7e373abd38acdf4fcdc9f7c8619a8b2d2463efe1", 0xd4)
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0xffffffff, 0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff}, 0x0, 0x0, 0xffffffffffffffff, 0xffffffffffffffff})
msgget$private(0x0, 0x0)


r0 = socket$inet(0x2, 0x3, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
bind$unix(r2, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
bind$unix(r1, &(0x7f0000000200)=@file={0x0, './file0\x00'}, 0xa)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000280), 0x1043)
mknodat(0xffffffffffffff9c, &(0x7f0000000100)='./file0\x00', 0x2000, 0x0)
r3 = open$dir(&(0x7f0000000240)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38/\x00', 0x0, 0x0)
link(&(0x7f0000000340)='./bus\x00', 0x0)
ktrace(&(0x7f0000000180)='./file0\x00', 0x0, 0x0, 0x0)
getsockname(r0, &(0x7f00000001c0), 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSBLEN(0xffffffffffffffff, 0xc0044266, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x4, &(0x7f0000000000)=[{0x6, 0x5}, {0x80, 0x0, 0x3}, {0x2, 0x0, 0x2, 0x148}, {0x0, 0x0, 0x1, 0x400007b9}]})
r4 = open(0x0, 0x0, 0x0)
mkdirat(r4, &(0x7f00000003c0)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38/\x00', 0x0)
mkdirat(r4, &(0x7f0000000000)='./file0\x00', 0x0)
mkdirat(r3, 0x0, 0x2)
lseek(r1, 0x20959, 0x0)
r5 = semget$private(0x0, 0x1, 0x300)
semctl$GETZCNT(0x0, 0x4, 0x7, &(0x7f00000003c0)=""/96)
r6 = geteuid()
r7 = getgid()
semctl$IPC_SET(r5, 0x0, 0x1, &(0x7f0000000600)={{0xff, r6, 0x0, 0x0, r7, 0xb2}, 0x8, 0x0, 0x5})
semctl$GETVAL(r5, 0x0, 0x5, &(0x7f0000000440)=""/206)


setreuid(0xee00, 0x0)
r0 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r1 = getuid()
shmat(0xffffffffffffffff, &(0x7f0000ffa000/0x3000)=nil, 0x0)
fchown(r0, r1, 0xffffffffffffffff)
r2 = getuid()
setreuid(0xee00, r2)
ioctl$FIONREAD(r0, 0x4004667f, &(0x7f0000000000))
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040))
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x400000000})
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r3 = open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
r4 = dup(r3)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000540)={<r5=>0xffffffffffffffff})
getsockopt$sock_cred(r5, 0xffff, 0x1022, &(0x7f0000000100)={0x0, 0x0, <r6=>0x0}, &(0x7f0000000180)=0xc)
chown(&(0x7f0000000080)='./file0\x00', 0x0, r6)
pipe(&(0x7f0000000080)={0xffffffffffffffff, <r7=>0xffffffffffffffff})
getsockopt$sock_cred(r7, 0xffff, 0x1022, &(0x7f00000003c0)={<r8=>0x0, <r9=>0x0, <r10=>0x0}, &(0x7f0000000400)=0xc)
r11 = getuid()
r12 = getpgid(r8)
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000001c0)={{0x80, r9, 0x0, r11, r10, 0x0, 0x2}, 0x0, 0xfff, r12, r12, 0x10001, 0x8000, 0x6, 0xbdc2})
setegid(r10)
setgroups(0x2, &(0x7f0000000080)=[r6, r10])
lseek(r4, 0xfffffffffffffa3d, 0x0)
pipe2(&(0x7f0000000240), 0x0)
open(&(0x7f00000002c0)='./file0\x00', 0x3f54c03cb53f6294, 0x8)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4e}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000180)=0x23, 0x0, 0x27)


mknod(0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = socket(0x0, 0x2, 0x0)
mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x205b9a)
r1 = socket(0x2, 0x2, 0x0)
connect$unix(r1, &(0x7f0000000a80), 0x10)
r2 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x9, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000000)=[{{r2}, 0x0, 0x0, 0x1, 0x3, 0x100000000000000}], 0x0, 0x0, 0x0, 0x0)
r3 = socket(0x10, 0x1, 0x2)
setsockopt(r3, 0x11, 0x2, &(0x7f0000000000), 0x4)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x3, 0x0, "0100012d29fb000700000000098002005e00"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0x4, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0xfffffffffffffe37)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r4 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7949)
writev(r4, &(0x7f00000000c0)=[{&(0x7f0000000080)='#!', 0x2}], 0x1)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x800, 0x0)
kevent(r4, &(0x7f0000000200)=[{{r1}, 0xfffffffffffffffc, 0x1a, 0xf0000000, 0x7fb, 0x4}, {{r4}, 0xfffffffffffffffa, 0x4, 0x1, 0xffffffffffffffff}, {{r4}, 0xfffffffffffffffd, 0x40, 0xf0000000, 0x3, 0x5000000000}, {{}, 0xfffffffffffffffe, 0x0, 0xfffff, 0x3ff, 0x99c0}], 0x0, &(0x7f0000000280)=[{{r0}, 0xffffffffffffffff, 0x8, 0x1, 0x4, 0xf6}, {{r4}, 0xfffffffffffffff9, 0x0, 0x2, 0x8, 0x2d5375e0}, {{}, 0x0, 0x0, 0xfffff, 0xfffffffffffffc01, 0x19}, {{r1}, 0xffffffffffffffff, 0x5a, 0x4, 0x6, 0x80000001}, {{}, 0xffffffffffffffff, 0x12, 0xfffff, 0x1, 0x80}], 0x80000000, &(0x7f0000000440)={0x0, 0x8})
syz_emit_ethernet(0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
r5 = socket(0x2, 0x1, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$inet(r5, &(0x7f0000000000), 0x10)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b100050300000400000000000101000000000000cea10500fef96ec0c72fd3357ae30200007804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3eea3c57699a6443a42102000000720fd18b08fbb670c1f5a872c881ea6e2ec5890400000000008000361b1257aea8c500002002fbfe0c2300008abfba0900000008e371a3f8343732051eeab71d89e0000405f8ffffff13000000010000000000000000000000000000000000000000000008", 0xb1, 0x0, 0x0, 0x0)
kqueue()
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x80, 0x0)
ioctl$VNDIOCGET(r1, 0xc4104603, &(0x7f0000000040)={'./file0\x00', 0x1})
setreuid(0xee00, 0x0)
r2 = getuid()
open$dir(0x0, 0x0, 0x8)
r3 = getuid()
chown(0x0, 0x0, 0xffffffffffffffff)
r4 = socket(0x2, 0x2, 0x0)
connect$unix(r4, &(0x7f0000000300)=@file={0x1}, 0x2)
r5 = semget$private(0x0, 0x7, 0x3c0)
semop(r5, &(0x7f0000000180)=[{}, {0x0, 0xfd}, {0x1, 0x20}, {0x2, 0x0, 0x1800}, {0x4, 0x9e, 0x1000}, {0x2, 0xfffb, 0x1000}, {0x0, 0x40, 0x1000}, {0x3, 0x8, 0x1000}], 0x8)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r6 = socket(0x1, 0x3, 0x20)
ioctl$FIONREAD(r6, 0xc0106924, &(0x7f00000001c0))
r7 = kqueue()
kevent(r7, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc020691b, &(0x7f0000000200))
semctl$SETALL(r5, 0x0, 0x9, &(0x7f00000004c0)=[0x0, 0x1001])
getsockopt$SO_PEERCRED(r4, 0xffff, 0x1022, &(0x7f0000000200)={0x0, <r8=>0x0, <r9=>0x0}, 0xc)
setreuid(r8, r3)
semctl$IPC_SET(r5, 0x0, 0x1, &(0x7f0000000240)={{0x8001, 0xffffffffffffffff, r9, 0xffffffffffffffff, 0x0, 0x40, 0x2}, 0x0, 0x9})
chown(0x0, r8, r9)
fchownat(0xffffffffffffffff, 0x0, 0x0, r9, 0x0)
setreuid(0x0, r2)
sysctl$net_inet6_ip6(&(0x7f0000000000)={0x4, 0x18, 0x29, 0x36}, 0x4, &(0x7f0000000080), 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000000c0))


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
dup2(r0, r1)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0xffffdffc, 0x0, "fffffeff00"})
close(r0)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "00001800"})
close(r1)
syz_open_pts()


setpgid(0x0, 0xffffffffffffffff)
socket(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000600), 0x1, 0x0)
ioctl$BIOCVERSION(0xffffffffffffff9c, 0x40044271, &(0x7f0000000040))
minherit(&(0x7f0000ffc000/0x1000)=nil, 0x1000, 0x0)
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = open$dir(&(0x7f0000000140)='.\x00', 0x0, 0x0)
mkdirat(r0, &(0x7f0000000100)='./file0\x00', 0x0)
mknodat(r0, &(0x7f0000000580)='./file0/file1\x00', 0x6000, 0x0)
getpeername$unix(0xffffffffffffffff, 0x0, &(0x7f0000000180))
bind(0xffffffffffffffff, 0x0, 0xa)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$pf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000500)={0x0, 0x0, &(0x7f0000000480)=[{&(0x7f0000000380)='s', 0x1}], 0x100000000000038b}, 0x1)
r1 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmat(r1, &(0x7f0000001000/0x3000)=nil, 0x0)
shmget$private(0x0, 0x4000, 0x1c0, &(0x7f0000001000/0x4000)=nil)
shmctl$IPC_STAT(0x0, 0x2, 0x0)
madvise(&(0x7f0000001000/0x2000)=nil, 0x2000, 0x0)
r2 = getuid()
setuid(r2)
r3 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r4 = getuid()
fchown(r3, r4, 0x0)
utimensat(0xffffffffffffff9c, &(0x7f0000000040)='.\x00', &(0x7f0000000080)={{}, {0x0, 0xffffffffffffffff}}, 0x0)
open$dir(&(0x7f0000000000)='./file0/file1/file0\x00', 0x0, 0x0)


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
sysctl$kern(&(0x7f0000000000)={0x1, 0x4d}, 0x2, 0x0, 0x0, &(0x7f0000001440)='\x00\x00 \x00', 0x4)


r0 = socket$unix(0x1, 0x5, 0x0)
r1 = getppid()
fcntl$setown(r0, 0x6, r1)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ktrace(0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
r2 = socket(0x0, 0x0, 0x0)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, &(0x7f00000001c0))
r3 = kqueue()
kevent(r3, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r4 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r4, 0xc0206921, &(0x7f00000001c0))
r5 = socket(0x20, 0x4000, 0x0)
ioctl$FIONREAD(r5, 0x80206919, &(0x7f00000001c0))
socket(0x1, 0x8000, 0xfe)
ioctl$FIONREAD(r2, 0x8020690c, &(0x7f0000000180))
mprotect(&(0x7f0000314000/0x3000)=nil, 0x3000, 0x1)
clock_settime(0x100000000000000, &(0x7f0000000000))
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x8000, 0x0, 0x1, 0x0, "0100012d29fb00"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x3d}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85baa97981056ef1043f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0xd, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0x2)
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, &(0x7f00000001c0))
kqueue()


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r0, 0xc2585601, &(0x7f0000000340)={0x3, 0x0, [{&(0x7f00000a0000/0x1000)=nil, &(0x7f0000ffb000/0x4000)=nil, 0x10000}, {&(0x7f00000a7000/0x2000)=nil, &(0x7f0000ffe000/0x1000)=nil, 0x7f0000}, {&(0x7f000008e000/0x11000)=nil, &(0x7f0000090000/0x1000)=nil, 0x100000000}, {&(0x7f00000a7000/0x1000)=nil, &(0x7f000009a000/0x2000)=nil}, {&(0x7f00000a3000/0x2000)=nil, &(0x7f000009e000/0x2000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000091000/0x2000)=nil, &(0x7f00000a4000/0x3000)=nil}, {&(0x7f000009d000/0x4000)=nil, &(0x7f00000a6000/0x2000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000094000/0x3000)=nil}, {&(0x7f000009e000/0x1000)=nil, &(0x7f000009d000/0x2000)=nil}, {&(0x7f00000a6000/0x3000)=nil, &(0x7f00000a8000/0x4000)=nil}, {&(0x7f00000a1000/0x1000)=nil, &(0x7f00000a7000/0x2000)=nil}, {&(0x7f0000ff9000/0x1000)=nil, &(0x7f00000a4000/0x2000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000099000/0x1000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f00000a6000/0x2000)=nil}, {&(0x7f0000097000/0x1000)=nil, &(0x7f000009a000/0x2000)=nil}], './file0\x00'})


mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x412dff)
pwrite(0xffffffffffffffff, &(0x7f00000003c0)="062e", 0x2, 0x0)
r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x402, 0x0)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000000), 0x2cfea}], 0x1000000000000013)
munlockall()
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x2, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
r2 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSKBDIO_GETBACKLIGHT(r2, 0x400c5711, 0x0)
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000180)={0x4, &(0x7f0000000000)=[{}, {0x38}, {0x7, 0x0, 0x0, 0x104}, {0xffe, 0x0, 0x2d, 0x95}]})
write(r1, &(0x7f0000000200)="d81ad3d20cf7eb4e9be33b", 0xb)


setrlimit(0x0, 0x0)
syz_open_pts()
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = dup(r0)
ioctl$BIOCSRTIMEOUT(r0, 0x8010426d, &(0x7f0000000000)={0x0, 0x7})
ioctl$BIOCSBLEN(r1, 0xc0044266, &(0x7f0000000100))
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f00000001c0)={0x0, 0x0})
readv(r1, &(0x7f0000000080)=[{&(0x7f0000000180)=""/15, 0xf}, {&(0x7f0000000040)=""/17, 0x11}], 0x2)


r0 = getppid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0xffffffffffffffff}, 0x0, 0x0, r0})
pipe(&(0x7f0000000000)={<r1=>0xffffffffffffffff})
setreuid(0xee00, 0x0)
r2 = getuid()
setreuid(0xee00, r2)
ioctl$WSKBDIO_GETMAP(r1, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r3 = fcntl$getown(r1, 0x5)
ktrace(0x0, 0x5, 0x40001e50, r3)


syz_emit_ethernet(0x17a, &(0x7f0000000380)=ANY=[@ANYBLOB="f3a2a8908a86aaaaaaaaaabb86dd601ab5b60000000000000000000000000000000000000000ff020000000000000000000000000001001d000000000000040100c2"])


r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x3b, &(0x7f00000001c0)='\x00\x00\x00\x00', 0x4)


r0 = syz_open_pts()
ioctl$TIOCSTSTAMP(r0, 0x8008745a, &(0x7f00000007c0)={0x40})


setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0xee00, r0)
socket$inet(0x2, 0x2, 0x0)
socket$inet(0x2, 0x3, 0x2)
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
fcntl$dupfd(r1, 0x3, 0xffffffffffffffff)
syz_emit_ethernet(0x20, &(0x7f0000000180)={@local, @local, [], {@generic={0x88e7, "507a823524cfbb7771363081f7809acf47ec"}}})
openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r2 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x10215, 0x0)
ioctl$VNDIOCSET(r2, 0x81946467, &(0x7f0000000180)={0x0, 0x0, 0x0})
pwritev(0xffffffffffffffff, &(0x7f00000000c0)=[{&(0x7f0000000080)="c1", 0x1}], 0x1, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4e}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000180)=0x66, 0x0, 0x27)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000600)={0x0, 0x0, 0x0, 0x0, &(0x7f00000005c0)=ANY=[@ANYBLOB="10"], 0x10}, 0x0)
r3 = socket$unix(0x1, 0x5, 0x0)
socketpair(0x1, 0x0, 0x0, &(0x7f0000000380)={<r4=>0xffffffffffffffff})
getsockopt$sock_cred(r4, 0xffff, 0x1022, &(0x7f0000000000)={0x0, 0x0, <r5=>0x0}, &(0x7f0000000080)=0xc)
setregid(0x0, r5)
openat(0xffffffffffffff9c, &(0x7f0000001500)='./file0\x00', 0x222, 0xb3d2b0b5428267ec)
r6 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r6, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000000040)=[{}, {}, {0x4000006, 0x0, 0x0, 0x1}]})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000007, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(r6, 0x80104277, &(0x7f0000000000)={0x0, &(0x7f0000000040)})
write(0xffffffffffffffff, &(0x7f0000000280)="7f23a3c23cce2575e1dd92c25678", 0xe)
sendmmsg(r3, 0x0, 0x0, 0x0)


syz_emit_ethernet(0x32, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x9, 0x4, 0x0, 0x0, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, @empty, @empty, {[@noop, @timestamp={0x44, 0xc, 0x8, 0x0, 0x0, [{}, {}]}]}}}}}})


ktrace(&(0x7f0000001d40)='./file0\x00', 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000140), 0x1, 0x0)
r1 = dup2(r0, r0)
ioctl$WSKBDIO_GETMAP(r1, 0xc0105715, &(0x7f0000000000)={0x0, &(0x7f0000001f40)})


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x2, &(0x7f0000000000)=[{}, {0x28}]})
sysctl$hw(&(0x7f0000000000)={0x6, 0xb}, 0x2, &(0x7f0000000140)="d5bd0d1d2d9ffee9de1e5f443d056725ae", &(0x7f0000000040)=0x11, 0x0, 0x0)
r0 = fcntl$getown(0xffffffffffffffff, 0x3)
fcntl$lock(0xffffffffffffffff, 0x9, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, r0})
ioctl$VNDIOCCLR(0xffffffffffffffff, 0x80384601, &(0x7f0000000100)={&(0x7f0000000040)='./file0\x00', 0x1, &(0x7f0000000080)='./file0\x00', 0x8})
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
select(0x0, 0x0, 0x0, 0x0, &(0x7f0000000380)={0x7fffffffffffffff})
execve(0x0, 0x0, 0x0)
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaaaabb86dd605d34520030000000000000000000000000000000000000000000009f0500040000000000000001010090780000000060397772"])
r1 = socket$inet(0x2, 0x1, 0x0)
r2 = semget$private(0x0, 0x4, 0x8)
semctl$IPC_STAT(r2, 0x0, 0x2, &(0x7f0000000140)=""/125)
setsockopt$inet_opts(r1, 0x6, 0x1, &(0x7f0000000000), 0x0)
sysctl$hw(&(0x7f0000000500)={0x6, 0x18}, 0x2, &(0x7f0000000000)="1c1d1332", &(0x7f0000000580)=0x4, 0x0, 0x0)
r3 = socket$unix(0x1, 0x5, 0x0)
socket$inet(0x2, 0x1, 0x0)
setsockopt(r1, 0xd0acb0c3, 0x20, &(0x7f0000000480)="a3bffd9d9ee63d5b63015aecee9eca56ed7d4ff9214bfd225f01a2ce719655a07e8869e8e1eaf491ab7fef72bbddd214d78fa9fd755141ebf411231b1a92b74c81b2d6976d6bbc34e7f2db21cd6e27c4a5ddb69cd5f984538e2fe524b797c74b22dcf911c2d4f98e9275d13e00003a6c27027ce2bbc8f01c9234e1466d18c2145d2b511f298ee70f1f227d879a30c8e7f06d46326624b43061e00dc2d91315a164415f8d64b459ebccd2392b43bba1276b", 0xb1)
getsockopt$sock_timeval(r3, 0xffff, 0x1005, &(0x7f0000000340), &(0x7f0000000640)=0x10)
open$dir(&(0x7f0000000280)='./file0\x00', 0x2, 0x4)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f00000003c0)='r\x00')
accept$inet(r1, &(0x7f0000000440), &(0x7f00000001c0)=0x69)
link(&(0x7f00000006c0)='./file0\x00', &(0x7f0000000700)='./file0\x00')
sendmmsg(0xffffffffffffffff, &(0x7f0000000ec0)={0x0}, 0x10, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x4004667f, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000140)=[{0x1c}, {0x7}, {0x812e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


r0 = syz_open_pts()
syz_open_pts()
r1 = dup2(r0, r0)
syz_open_pts()
kqueue()
open$dir(0x0, 0x0, 0x0)
ioctl$TIOCSWINSZ(0xffffffffffffffff, 0x80087467, 0x0)
accept$unix(0xffffffffffffffff, 0x0, 0x0)
getdents(r1, 0x0, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140))
open(&(0x7f0000000340)='./file0\x00', 0x40, 0x1)
open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
mkdir(&(0x7f0000000300)='./file1\x00', 0x0)
r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x80, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000080)={{}, 0x0, 0x8, 0x400})
ioctl$PCIOCREAD(r0, 0xc0187009, &(0x7f00000000c0))
chroot(&(0x7f0000000240)='./file1\x00')
unveil(&(0x7f0000000280)='./file1\x00', &(0x7f0000000080)='c\x00')
r1 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000180), 0x80, 0x0)
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f00000002c0), &(0x7f0000000100)=0xc)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x802, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000240)={0x0, 0x5})
r2 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x2000, 0x2d87)
r3 = socket(0x11, 0x3, 0x0)
sendto$unix(r3, &(0x7f0000000000)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x400, 0x0, 0x0)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
r1 = socket(0x18, 0x2, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockopt(r1, 0x29, 0x2c, 0x0, 0x0)


msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{}, 0x0, 0x0, 0x0, 0x0, 0x8000000000000000})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x800000018, 0x1, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x0, &(0x7f0000000040)})
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = socket(0x18, 0x1, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


r0 = open(&(0x7f0000000100)='./file0\x00', 0x615, 0x0)
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
mknod$loop(&(0x7f0000000000)='./file0\x00', 0x0, 0x1)
fcntl$lock(r1, 0x9, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x1000300010008})
dup2(r0, r1)


openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000340)={&(0x7f00000003c0)=@abs={0x0, 0x0, 0x1}, 0x8, 0x0}, 0x0)
socket(0x2, 0x2, 0x0)
syz_open_pts()
syz_open_pts()
syz_open_pts()
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)
syz_open_pts()


mknod(&(0x7f0000000500)='./file0\x00', 0x1000, 0x0)
symlinkat(0x0, 0xffffffffffffff9c, &(0x7f0000000140)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/file0\x00')
open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x8020699d, &(0x7f00000001c0))
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
syz_emit_ethernet(0x7e, &(0x7f00000002c0)=ANY=[])


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x0, 0x1f}]})
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
pwritev(r0, &(0x7f0000000800)=[{&(0x7f0000000240)="eaa72825", 0x4}], 0x1, 0x3fffd)
sendmsg(0xffffffffffffff9c, &(0x7f0000000380)={&(0x7f0000000000)=@in={0x2, 0x2}, 0xc, &(0x7f0000000500)=[{&(0x7f0000000080)="c9777d04151cf5379168d599", 0xc}, {0x0}, {&(0x7f0000000180)="599829a7e35d50feebbd50a6b82aa98f31cbc19c715c9339fb9a5b63fea0c99517c6a8c415e2f8da5d3f97ed11f14062c14364652590d25a93081fd3fb075fc246d0aa9393f4b3a767caf14487e228f5e056e1d6b50934d3c35a6cb25039bd47fa3706c98407c2bca885e626142b9d2332459031de", 0x75}, {&(0x7f0000000280)="2dbadba001e777029cffa4c50e097be8c63ff9b5dcb94d86ef34528218c83a7225dfc1678301f8daf2edf069ca146ff6c62a635cb68b1741a2f161e220ac3d3c38931de41a015a26028553d4f059ad322d4da1ef5fdadfffacc200c0c980e30f61c975b7a51c43c96dfb489548ecb860284c2b4f38218b1edf181500c2d93075a87548bc84fa29009387b29c1eb0813b98759b7b7e44", 0x96}, {&(0x7f0000000340)="3623e5e69fea2593e2b52c933a659a534d3838a9074a9d561cae7b7cc979fd3a62648f367b314ef3fcc7ba6397f4b4d27a6dc90f4d54ff73b45a43ce", 0x3c}, {0x0}], 0x6, &(0x7f0000000580)=[{0x58, 0x1, 0x800, "7dce30a9170466abc814fda9b4e8873a7803e99f6ef631cc8d9475f682c99b14cdd078d175e1cb47ddbe6f7bec06b2ccbc557b2c856325b1075c60a8fd398258df"}, {0x30, 0xffff, 0x0, "33c5997ad07408a573e94b893bfbc21e0ec8b72d2f1d63e71e82562934"}, {0x10, 0xffff, 0x3}, {0x78, 0x1, 0x6a25, "4009ee5664120eede8c953b5114a0607549b98199556f324adc53f01cdc480dd929a6379c29c525797e9c33241db684b9486900cfe8e208242a086761bdac195a63c3f3b3e17e9e3658f3f4e928d4ba444f4fee9b95c8edd490f7a28c8252b1762"}, {0x10, 0x1, 0xfff}], 0x120}, 0x0)
open$dir(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
link(&(0x7f0000000480)='./file0\x00', &(0x7f0000000780)='./file0\x00')
r2 = dup(r1)
ioctl$BIOCSBLEN(r2, 0xc0044266, &(0x7f0000000100))
r3 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000180)={0xffffffffffffffff, <r4=>0xffffffffffffffff})
getsockopt$sock_cred(r4, 0xffff, 0x1022, &(0x7f00000000c0), &(0x7f0000000200)=0xc)
ioctl$WSMUXIO_ADD_DEVICE(r3, 0x80085761, &(0x7f0000000100)={0x3})
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSBLEN(r1, 0xc0044266, &(0x7f00000007c0)=0x7)
sysctl$net_inet_carp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x4}, 0x4, 0x0, 0x0, &(0x7f00000010c0)="f5c9594d", 0x4)
syz_emit_ethernet(0x3e, &(0x7f0000000ac0)={@broadcast, @remote, [], {@ipv6={0x86dd, {0x0, 0x6, '`b`', 0x8, 0x2c, 0x0, @loopback, @local={0xfe, 0x80, '\x00', 0x0}, {[@fragment]}}}}})
r5 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000280), 0x8, 0x0)
ioctl$VMM_IOC_INFO(r5, 0xc0185603, &(0x7f0000000300)={0x0, 0x0, &(0x7f00000002c0)})
r6 = openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$PCIOCREAD(0xffffffffffffffff, 0xc0187009, 0x0)
writev(r6, &(0x7f0000000d00)=[{&(0x7f0000000840)="24960d39871b50c5e9516693b4fa9070fbee92dc32d5dff163012eb566f9e79d723d614ce179835b3bcb7976e51bd0ea0414b1dd762d760b04127887be27501cb26e7629732a3a3c45a0335e1a4c85f0f7d40e6b8c53c7dfda997749b596c7da4d43c2f7e2ae5052fc8cb6447d03b461a43c204502550831fa93256348d8596680ad602ae66a371f7b045954e7ad45c45f502777771b7d32cb8896e895495a2d40", 0xa1}, {&(0x7f00000009c0)="5b7eff999335fa1952a639229a1f2c29eb2284db1aa9a7fbdb9b6ad6e84038721b4852f6ec949ae4a84baa6754c0591f2e0f4f5aa244df9a82b146b272983ccdf1b6e6ef184cc0fd23d612e2734f08288d2c47b90d8e1f9a720a2dbcf08c60847a02371273ebad539b3bff51d5bbb71d86e5951f59d34aaf629eb17786e88521cef77e4120157df7a7729bffca3a4154fc143de416af", 0x96}, {&(0x7f0000002100)="cf754d874d94cf01d0ac3fb8ecccf1b5a123da2760b89e1c62961a0199fabef2d386df71ad5ec1f9854c5d7a76e8c52895e44793c2c276b1d9af0e9fb93f7352ff8f6c8c521e7a4367f6d84ebffe4cf488abac8ca34d4279a75494fe7bd3c27bf9929a677f156b95c819046e8f3bcf9eb0bcb0c9f94a159630dddcee7eb60716e78d5a9b45d5abf69600ebd8245fd0f3c4835f0f68341b2ec7b249488193c293f16026a59fec52361b280fc191a0c41e12023a94462f2dab9d4d3c54fbb3b4e2566a4c244a6dd4acc6804c6eac67565e058117f9664d5430adbcf9dc1300d2d5701227ee8f9d025c64ca5fe48d7a551168cf1c9f0ee07d995d72cb915e93934b93b93ebf006c92861d5b1072c936290158166c893af775a96de0eb9851e553cf9b549e27d3743aa7d4ecb00c20a250ff30b2935eefe07e59aad5312cee986866092d08f0f0a4689b35dcefd023f682f496f1a93b49ff5e674e3b3b5f7eef86882f1b81d7cc8a64d49bc372abe4fc8c6cb0e199ba117a422af3d587f87a20bc3cc94e6f05f2abd5864f03af386c7d509b4be2a6ad417ff74615c22ad7fba83beb9c6c7f3aaad30a036eff256590d48aae278b45cff04a53a6f775473ed0e0fa6762f29cbc468ce1a043da1b2e0ae2a3cd2e17686ffa5c5048fccfa8d99af32163ec241c8a03930944bc0d4174de4a1345c01e66c2298feed7171ce8e5ca2399aee4b27e7e3ebf580382e2939988ddd4b36011b1e5329b6c5dc15fb00d87061a3fb056f3414f61c408f0ab4945af578e17dbcfc2467ef59d6a533f055571248e1079bd451f74c0d250b96f8e43a9106c81d02a49f9910e69ef84f86a8c5d6114526ae378f6d018012e148ef4282c70a527ac0a43e18f6ba6c76ab5c50ba6a3ef60f28f534718d373c877504ffde04049522011e131c7685caf365da26878dfcf4f2bb76ef9cbbcc25f3dee11e9d6479cc39649f82288ed4cb15803fea038534f8341c1f3c4e45be01bbffbe3d77a9f7fab2313bb95065b23117d20c899e412f88b5a88b2ad44a653e648e8a7cd396ae6e6e74b3485be1ec2d0f70656c308a1de04a5e7c306ae7cc50a0027dd7a858f41acb01e47c5ad6b6bf551bf378f4d3dc02b1dac35fb53074732dd0dcd5c75dd6420c1c7505a8ea39271c5e9875d46812dfe2902be52e380510135b22392cfc635f6e0955d54fff25a2fc28400ecd63c5bff3b0fea49662395874a956a33c286626d68d76db3ee45c26f0eff26460e7f3f417c4a311756c9137bb41bc1e6aef7a3201385ed4327972c1d9ea87d3e9649a6527f2901d2d63004928b262ec65efad46641d4f3b7f82924119a794e8fd95dd0ccdf1720c5acedc2e775cbaee39dc5bf0065db7c053e2786d3f046f45ef836dc48f99318ad41dce272152c58351635ad436d0136f42c3cec69a973bfa275745583526686df58c92231d01c6be79792500590eab6b4500222bd7f4765ad5b7ff6a39e4dda8d518f0baed06ced4171f00aee42851b3058a34f440186e7685096415144de5154ee98e84e7f065d66a759c6ee1d8fc4e8e1d258691d1e98edb5697519a95e139b1458f6dc12561e89caabf0bc11ecf41ce4d28057e6faa3f23addc613c45b18bc15b24db21a5845d59e9d971a103f91af0cf33467bab971330a3d071cde59a56203f9e8e58d2cec274e02cb777cc82292e0401f888af5b28b27734c3f49bacbc4d0fa58389f8fa17a007e847cd623f9b03153b52d9d3bd655868d25b190b92295d8b2effd234044d59e4188fc59dac5df169d8b18d0b895d015e685d9fbdbfa01b1ef9b2a57ba5c96ea1237eccd4b890ecca57b7a34cebda43ae71692c784ae9a10301ee2b8631fdf4cdb2a1ab75ae2e1e974a189ce9805d253697c6577f53360d6ab8a982ca95321d3377c299c78631072b068e055d6c96608865e6bd5e0957364a7dc5890fa991d7cf7152637f123c1077f4e479b49e56bc68ad60e6846e747242c055e65b45718d09ffd88da14b5a760a724139ca2b58b56cb9bc01ccf9175305ef56a1add4c40fa3f34e7b13bada4545d29aa6a8d18c263aa020686661188b676c76a1ef529751289e0b417b66dba0992696738c5d5b0fa3fbf01c7083a4f7a44ce69485f21854c2aad38377dfc4a2d04d08da6a07edb1e459307255bac9b101a30163efe7ef3cbea4cc6adee92f32bd60036a3a54a36f3bbde1704ee1135fb8f8df145e3b15b69f9e77c6e448aedc296030f29adc11816282423aecf0823bdcbe7b6b527cd1c0701ace966aee9609cc314340beb4cc99529bbcf902357bcd995e239fcc1bd61f8598bef568b94e67587645ca0f6a8f59d739bb473127f7551132e1eb4898a565cd179199484773feb737007e44d1ca7af12f041662c68a43f49f5a319f9085de51cb9b950e1b7734788c71388b2cb01aa6f59dd46c5d7c1fd4a3a3b008817e36d546614f27b83f65b37cdae65c1e86352d99ca5103072826d574584bf7d9b734d9259d04059b74743afab8822b9922bc254478b91dce0004415ea5db992c7cddde9bd10d048ed8ddb2fa2ba0cf18aa5671729968179b262ed830fa0c544204ab47838b53afe9e4289b0bc2a2c1c3838e88fab773691da629fb194274f6e8260599e257efe73af1ec148e4b76e4bf7e2038ddaa7c460af9a4f38ed6bee688236dccd15881a19312461540f1707ba65f8480feb53740526a516936a1dbfbfd5f4d0c78e520e56f368eaf29cfdb6ba5bdebfd836f10ec7e44eea760c9cb0386ef0df2b3b8dbac93ddb54a8294b79e36011e344888f99e6541c1b24e1580e22cf48f8bf9691ce6a87de414b92d684e5f4dd6d4463cf5ad9c3a72361953262bcdab8034f6177b9c5d7d329916ae1277509f13fe953769fd1cee8a63819c5666efa8c6bf73bf9c73f81345e6dbf55ebd2552b78e0ef4476e2d1a403a39ac1b035669d2f48cc414cee33bcf557ea47659bf51b897479ffbd754d1987571a05894ea1856296c8e3f532db0767703f3ac8ce49a1a6eda64bd9aa0fbf39f15e23b5ed3ec3cc505388965653da71506e9111389f75f1bae41a762c4f2db3ee4655fab815cff2308b5997fef2e83b1aa293cb80d7ec1df5eb3d21177ab034d1a8522484d763e06bc19c9ff7288111feaa1888fc0103199afbcbb01286177037e1250c3744586a6f33df1a2ecdcaa47f80814eb6176cbc93730aa34edfd9f27069465f0f3b50aee75df853d218af1b9368797f7f6489caf391c7a4226a171c1f3584db2fd3ef0ef9a2a458574416706e4ba2783270a4fcc4d482bf9e017e7f99a8c0dd02b5c280dff4e2c0fad82cdbd151ff829899b876cceddc71bf71a0133adcaac5000f42aee344b95974bc91c833e03cbe1b7a64d9aa215ac0d5331f1d52cdf9cc8f9c278b63fd7793c738eaefdcac6b144093a6daf6e6d40249b9415e80f034d6328353ed296f1f18156ed8de6f19727133f0fe5e9da7c1ea7260929acf41f2014ee0318a4373e9b0d1363cf91889179d1c67daf0bb1385fd4f9277b9ff6a98810a33ddd02f2216e4e237e76c804ee9df712f8c6755c3a8e441d3e35d0e9d3f4124aae8344be6826097b6c9cb8e6d2000bbedfa28e5d86bc038200325273018b2ed6f43b505814c91e1febec0456baf673b41b63397883c8aac745f3a52c659c4477a69639256a3ec467d42ca116f2ca5d2e02307e3ae4fbb83a1fc8e7004b3bc5c519c08d844a7a248939b327e1b031fcff24e2b015ae48a275c63c9e1f946abb9a7e55b15a3e999410a918cdca7b8cb21bb15077ba87459656b3c8d899d5da07addc2efa73733c33505ae9948c756cfcb4e0dc867292d94662ef630f874a2c013b8539426819df4c679c802da0a09c14aef871f318e4d94bf916f2e583b3f04dcdf342a4443a9dc512903c828907bd120802498b5499942330fead6b2d548a1f54121bdf3af5ba6d7290ffd00a169c01910c8dd2088089adb47ea9b74e092a5d71fcd66ea817863e8b93201cf3fb915b3f188deb0d0315f17f86ef6a26b77e6ac93ab266777a26b587618dfbad3140fdbb437fcd79cfaf1cb206fb33457cf3be0228e0a64dc0221d432bc8ff6ea843220e51b909a9fe8ca0c60afbb6702f633f2be0147cda5b23ccf3dcdd1158371781b5da3aa309762879ac0892a349c85bb81e43cf4fc5d686e3292460dde891ff53a33548fdd83a8f335d619e875f38d57de0dfcf10d2083a151f8f729103533be3b7891fdb680417227e5961ad0d3d7995d717aea1ca92214ccaa804bdbc34f7f9882ba2a111946f396928884b95c66ae55746e4e08d462aeb00cee5af024467c92f39fbf64b499cd076ac4df3ff3a3b7a14a9b0c510938d9d0174003248c7daf0cb20f8979707fc7f65f73316b68c1c44891c1b800c6b51496ff64ee448b4ae91639fb01ea0f5be33f3bd4267dfa1539bac4e983e359fd91a895ebfd2055588b29db4b74e3d09c3a41d757e4c00f9c72a2649a2111e730cac8cb20f42716693174a9f198d00a305fb02f781f976f48b9f384c13601d483a905dd8a9a9a6142579ba4ec20a34b18ec0f2e20b61292457c47d63c2cd38426f186d008970379125c4a2d39fd4cf1abaafeb4c2d82257e1ec6620d3a6a19f1a827db97273c2899ff9557379f6939102877f08370ae83864ca5d5a71616244dc7cf8442cd04b0f2c32fc623cd5783569c9dda73ce7cf92e55a34e688c64002a95f46cf6d9fe948b5eda6286acc9a9f9ef86a4045983e6391598e40dd53cc224dd0f1fa289cc2e73ae1446d2a77019a08e92480d616c48d2d402a37f6eeb045b5330d4e39d5c8e6bb2e4983a2090bebf3d8d9933160deb2fa30aaf74136f65c3384f373d9272479244f632b424bf2434648c336c1c35f9efd15c51fd0590f727588d6c80f32f3ac7f236e2b8199d2fbc54fc97590bff26a9d237a2aaf50fca56ded1fccbe16a096c566616267d7ccbb4e3252358c7099faac051a4b7407a2ff2e7be8cc85d75c93d0fd4a0acb043d0426b54306e4a710474420dd91677553fcff341ac6161694082e9efeb2ea4ee50b371152122da1c3d9670b3ff95449f5fbd7bbc1d4d04c1d025120d2c5e43e478174d045ddea3d72c0e2125f21138675bdb36ba2eb8c205c8ee329dc496bee6c1315e363797ee1f929968f55b3bc324b6448b9f512dbc63b0a09c034caf75aa34a12bd9ed22d79c96b9d5c79e48ff31344c4c4ef199656ec5b6207e2b980baa675232ae367a5458fe53e6de125e34311a757dc472825054faa88134ec021ba686b56b4c4aaef8d2d08e53ae857ae64f2cf8c6ee5b573b1144bf5c6fec69e932098dfafc477b17e263d0867cbfc8478befd8616fe732ab387032b21af0ce44411d35edfaa60ec1d47a44dc4820c40ccd8c1ad2c93cea17e08529fdfc5c9b10ac16ce8", 0xf00}, {&(0x7f00000004c0)="8d94e9a5751909751aadb02e5907dc21511dbf6e41e6d8dc12aa78223e4ff36fcb432bc7", 0x24}, {0x0}, {&(0x7f0000000c00)="5c54d0a8ff383dc21e23534657e98b5de1f2916cfe48c7f08f13a2aed4387d4702da826b3730aa169aed67b394ebf86179f810d78b26109a76b39a6502fdd392d12b709cd6293e3dca864ce5d90b691482e6161fd716e073a72422159d6184dd6f12d73abec3a7a788240ff691db17927e3f829f2c7990b91106afcfbcdf2bdfe581e2c4ef01fe38d96ddf22ed554aadbecca79d774b34b888e43c9c59d9e5db0f7bfc9fc56c6948a84838c77c56ca93c47710253b44b0cd326c278061b75e1e678bd8964f28a30c3e3110f881b9927a2d5b2e73af8e3eaab05d5802208ee4ac6133", 0xe2}], 0x6)
r7 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSKBDIO_SETBELL(r7, 0x40047477, 0x0)
syz_open_pts()


r0 = syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047460, &(0x7f00000000c0)=0x3)
r1 = dup(r0)
ioctl$BIOCGRTIMEOUT(r1, 0x4010426e, 0x0)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x1, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
open(&(0x7f0000000600)='./file0\x00', 0x70e, 0x0)
r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x25, &(0x7f0000000480)="5ab7776a", 0x4)
syz_emit_ethernet(0x4e, &(0x7f00000003c0)=ANY=[@ANYBLOB="aaaaaaaaaaaa7fd67572210786dd6007558300183701fe8000000000000000000000000000aaff020000000000000000000000000001"])
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x0)
open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
r1 = socket(0x11, 0x3, 0x0)
select(0x40, &(0x7f0000000100)={0x0, 0x0, 0x3, 0xfffffffffffffffd, 0x0, 0x18000000000000}, &(0x7f0000000080)={0xce9, 0x0, 0xfffffffffffffffc, 0x0, 0x400000}, 0x0, 0x0)
r2 = open(&(0x7f0000000080)='./file0\x00', 0x70e, 0x0)
mmap(&(0x7f000000f000/0x2000)=nil, 0x2000, 0x0, 0x10, r2, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
pwrite(r2, &(0x7f0000001500)="18", 0x1, 0xffff)
connect$unix(r1, &(0x7f0000000340)=@abs={0x0, 0x0, 0x1}, 0x8)
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000480)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x61}, {0x61}, {0xe}]})
write(r0, &(0x7f00000006c0)="e506000000000000004aaed75a5a", 0xe)
r1 = getuid()
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
setrlimit(0x0, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
pipe(&(0x7f00000001c0)={<r3=>0xffffffffffffffff, <r4=>0xffffffffffffffff})
getgid()
r5 = getuid()
setreuid(0x0, r5)
fchown(r4, r5, 0x0)
ioctl$KDENABIO(r3, 0x20004b3c)
setreuid(r5, r1)
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000004c0)=[{0x3}, {0x44, 0xfc}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000200)=ANY=[])
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
getpgid(0x0)
mknod(&(0x7f0000000000)='./bus\x00', 0x2000, 0x6380)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x6381)
open$dir(&(0x7f0000000e80)='./bus\x00', 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000280)={0x2, &(0x7f0000000240)=[{0x48, 0x0, 0x0, 0x2d3b}, {0x2006}]})
write(r0, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xe)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0xfffff5e7, 0x0, 0x7, 0xffffbff2, "1010264d007c260000000000000000e1ffffff00"})
writev(r0, &(0x7f0000000100)=[{&(0x7f00000009c0)="4a9ed65e2f444a9ec732bacbe026237622ad5dd37fe2cfb3a2289c9afef2523ce34ccba8196c838b64eda3838e69bbf95f059371811f3fff1d7384630f52315bc5aba7fc040353437cbfa6826a5914534f23da7d4ac8698d6945bd93dfb78e13ff8a25c901919cde9c0aadd833b0b37fc8afd99997fa5ca1", 0x78}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = dup(r0)
ioctl$BIOCSBLEN(r1, 0xc0044266, &(0x7f0000000100))
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
syz_extract_tcp_res(0x0, 0x0, 0x0)
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)
readv(r1, &(0x7f0000000080)=[{&(0x7f0000000180)=""/15, 0xf}, {0x0, 0x11}], 0x100000000000003a)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000004c0)=[{0x28}, {0x6c}, {0x8306}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000280)=[{0x1c}, {0x64}, {0x406}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)='\x00', 0x1}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
r1 = socket$inet(0x2, 0x2, 0x0)
dup2(r0, r1)
setsockopt$inet_opts(r1, 0x0, 0xa, 0x0, 0x0)


socket(0x0, 0x0, 0x0)
r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
pwritev(r0, &(0x7f00000002c0)=[{&(0x7f0000000180)='O3', 0x2}], 0x1, 0x0)


msgsnd(0x0, &(0x7f0000000140)=ANY=[@ANYBLOB="0300000000000000a60d524ae979b5a3e111c8cac1b119e4db1e444c9d4eca7af32596137392f4cdc50d82caa6fa7ffd0da455fa2e9f5109d4ccbe9ddd5e3674e689a6714f0ac2ee9e36ae12821cff35f5866888d441f7c29189271982efb7cd9c94766d1c4be0efcbf44d5d0010dc9df78616b167b260dd96322bfbad5f46f92beb4126cf5ffee44ca5b5bdfcf14c9b3003f53d57d96bcceb3c014f4d7b36a32f1fdb2d7783fa77ede48c3db7299ec5e58a1348d1da9304dc8bf8200a241f24ffa673bd7cb93b55b31a3045a1501250df6302a6bbfdcb68febcf98e7aabab17c9e7408bccc3081d1feec2142247dcd0e3ab8a8ab390b2a70909b2f114aa2b6ff73741b6c4c9"], 0x401, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x1000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffa000/0x2000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r0, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0})


socketpair(0x18, 0x0, 0x29, 0x0)


openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x1})
setsockopt$sock_timeval(0xffffffffffffff9c, 0xffff, 0x0, &(0x7f0000000000)={0x0, 0x2}, 0x10)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x42}, 0x6, 0x0, 0x0, 0x0, 0x0)


writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
r3 = socket(0x2, 0x2, 0x0)
r4 = socket(0x2, 0x4001, 0x0)
r5 = dup(r4)
r6 = fcntl$dupfd(r5, 0x2, 0xffffffffffffffff)
close(r6)
r7 = socket(0x2, 0x1, 0x0)
connect$unix(r7, &(0x7f0000000000), 0x10)
connect$inet(r3, &(0x7f0000000000), 0x10)


syz_emit_ethernet(0x52, &(0x7f0000000300)={@local, @local, [], {@ipv6={0x86dd, {0x0, 0x6, '\x00', 0x1c, 0x0, 0x0, @rand_addr="fe350e28ef0900c0f1ee24be00", @local={0xfe, 0x80, '\x00', 0x0}, {[@fragment={0x0, 0x0, 0x5}], @tcp={{0x1, 0x0, 0x41424344, 0x41424344, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x9}}}}}}})
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendto(r0, 0x0, 0x0, 0x0, 0x0, 0x0)
recvmsg(r1, &(0x7f0000002880)={&(0x7f00000014c0)=@in, 0xc, 0x0, 0x0, 0x0}, 0x0)
r2 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r2, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r2, 0x0)
r3 = socket$unix(0x1, 0x5, 0x0)
ioctl$SPKRTONE(0xffffffffffffffff, 0x80085301, &(0x7f0000000340)={0x9, 0x2})
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$WSMOUSEIO_SRES(0xffffffffffffffff, 0x80045721, 0x0)
getsockname$inet(0xffffffffffffffff, 0x0, 0x0)
r4 = socket(0x0, 0x1, 0x0)
connect$unix(r4, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETF(r5, 0x80104267, &(0x7f0000000040)={0x0, 0x0})
syz_emit_ethernet(0x26, 0x0)
connect$unix(r3, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
r6 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r6, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000200)="ea00000000000000", 0x8)
setsockopt$inet_opts(r0, 0x0, 0xb, 0x0, 0x0)


r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f00000013c0), 0x1, 0x0)
ioctl$WSKBDIO_COMPLEXBELL(r0, 0x4004570c, &(0x7f0000001400))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f00000008c0)=[{0x4d}, {0x87}, {0x6}]})
syz_emit_ethernet(0x62, &(0x7f0000000240)=ANY=[])


sysctl$vfs_fuse(&(0x7f0000000000)={0xa, 0xd}, 0x3, 0x0, 0x0, 0x0, 0x0)
select(0x0, 0x0, 0x0, 0xfffffffffffffffe, 0x0)
syz_emit_ethernet(0x4e, 0x0)
syz_emit_ethernet(0x3e, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
pipe(&(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
write(r1, &(0x7f0000000080)="c7", 0x1)
write(r0, &(0x7f0000000340), 0xd4e688a67930cd)
close(r0)
write(r1, &(0x7f0000000040), 0xfeea)
close(r1)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000200)={0x0, 0x0})
syz_emit_ethernet(0x3e, &(0x7f0000000140)=ANY=[])
ioctl$BIOCLOCK(0xffffffffffffffff, 0x20004276)
r2 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000180), 0x1, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(r2, 0x80085762, &(0x7f0000000400))


r0 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
close(r0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


r0 = socket(0x2, 0x1, 0x0)
r1 = dup(r0)
listen(r1, 0x0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
accept$inet(r0, 0x0, 0x0)
dup2(r0, r2)


getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000000), &(0x7f0000000040)=0xc)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000700)=[{0x54}, {0x2c, 0x0, 0x0, 0x3}, {}]})
getsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x1, &(0x7f00000000c0)=""/195, &(0x7f00000001c0)=0xc3)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)


r0 = kqueue()
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000180)=[{{r0}, 0xffffffffffffffff, 0xdcd8c4bc089e638d}], 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={<r1=>0xffffffffffffffff})
kevent(r0, &(0x7f0000000140)=[{{r1}, 0xfffffffffffffffe, 0x2c5d36d679bbffbf}], 0xe4a, 0x0, 0xa9fa, 0x0)
kevent(r0, 0x0, 0x0, 0x0, 0x9, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x1025, &(0x7f0000000100), &(0x7f0000000040)=0xfffffffffffffd96)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
ioctl$PCIOCREAD(0xffffffffffffffff, 0xc0107002, 0x0)
r1 = openat$speaker(0xffffffffffffff9c, &(0x7f00000006c0), 0x1, 0x0)
writev(r1, &(0x7f0000000300)=[{&(0x7f0000000400)='on', 0x2}], 0x1)
r2 = syz_open_pts()
getsockname$inet(r0, &(0x7f0000000080), &(0x7f00000000c0)=0xc)
ioctl$TIOCCONS(r2, 0x80047462, &(0x7f0000000000)=0x7)
r3 = openat$zero(0xffffffffffffff9c, &(0x7f0000001500), 0x0, 0x0)
fcntl$lock(r3, 0x9, &(0x7f0000000140)={0x0, 0x0, 0xfffffffffffffffe, 0x1000000000000, 0xffffffffffffffff})
syz_open_pts()
ioctl$TIOCSPGRP(r3, 0x40047477, &(0x7f0000000180))
syz_open_pts()
socket(0x11, 0x0, 0x0)
r4 = socket(0x0, 0x3, 0x0)
r5 = socket(0x1e, 0x3, 0x0)
shutdown(r5, 0x1)
setsockopt$sock_int(r5, 0xffff, 0x1001, &(0x7f0000000040), 0x4)
setsockopt(r4, 0x11, 0x0, 0x0, 0x0)
r6 = msgget$private(0x0, 0x0)
pipe2(0x0, 0x0)
msgsnd(r6, &(0x7f00000001c0)=ANY=[@ANYRES32, @ANYRESHEX=r4], 0x401, 0x0)
msgsnd(r6, &(0x7f0000000540)=ANY=[@ANYRESOCT, @ANYRES64, @ANYRES16=r6], 0x401, 0x0)
msgrcv(r6, &(0x7f0000000400)={0x0, ""/137}, 0xaf, 0x0, 0x1700)
r7 = syz_open_pts()
ioctl$TIOCCONS(r7, 0x80047462, &(0x7f0000000240)=0x2)
r8 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x40, 0x0)
pread(r8, &(0x7f0000000000)="2beba8c5bfaaff44b437dfbb000000", 0xf, 0x7fffffff)
listen(r0, 0x81)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000340), 0x0, 0x0)
ioctl$VMM_IOC_WRITEREGS(r0, 0x8020560a, &(0x7f0000000040)={0x1, 0x0, 0x3, {[0x400003, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1], [], [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8], [0x0, 0xfffffffffffffff7], [{0x0, 0x0, 0x0, 0x80000000}]}})
kevent(0xffffffffffffffff, &(0x7f0000000000)=[{{}, 0xfffffffffffffff9, 0x19}], 0x0, 0x0, 0x0, 0x0)
socket(0x10, 0x4, 0x4)
kqueue()
r1 = socket$inet(0x2, 0x1, 0x0)
listen(r1, 0x0)
shutdown(r1, 0x2)
close(r1)
socketpair(0x1, 0x5, 0x0, &(0x7f0000000380))
socket$unix(0x1, 0x1, 0x0)


setrlimit(0x8, 0x0)
syz_open_pts()
close(0xffffffffffffffff)
mknod(0x0, 0x10, 0xb7)
munmap(&(0x7f0000400000/0xc00000)=nil, 0xc00000)
getuid()
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000300)={0x2, &(0x7f00000000c0)=[{}, {0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x3d}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x10, 0x0, 0x37)
geteuid()
setitimer(0x0, 0x0, &(0x7f00000004c0))
openat$pf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)


r0 = socket$inet(0x2, 0x1, 0x0)
poll(&(0x7f0000000080)=[{r0, 0x4}, {r0, 0x4}], 0x2, 0x0)
open(&(0x7f0000000200)='./file0\x00', 0x80000000000206, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000040)={@broadcast, @broadcast, [], {@arp={0x8035, @ether_ipv4={0x1, 0x800, 0x6, 0x4, 0x0, @empty, @empty, @broadcast, @remote={0xac, 0x14, 0x0}}}}})
syz_emit_ethernet(0x2a, &(0x7f00000002c0)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, @multicast2}, @icmp=@echo}}}})
recvmmsg(0xffffffffffffffff, &(0x7f0000000040)={0x0}, 0x10, 0x0, 0x0)
shutdown(r0, 0x2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000100)=[{0x4d}, {0x15}, {0x6}]})
syz_emit_ethernet(0xe, &(0x7f00000000c0)=ANY=[])


getpid()
socket(0x18, 0x1, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000029, 0x2f, &(0x7f0000000000), 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
socket(0x0, 0x0, 0x0)
socket(0x0, 0x2, 0x0)
madvise(&(0x7f0000000000/0x4000)=nil, 0x0, 0x2)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, 0x0)
syz_extract_tcp_res(0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
setregid(0x0, 0x0)
setregid(0x0, 0xffffffffffffffff)
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000001140), 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r0, 0xc2585601, &(0x7f0000001180)={0xdead4110, 0x0, [{&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffa000/0x2000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffa000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff9000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000ff9000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}], '.\x00'})
mmap(&(0x7f0000ffd000/0x1000)=nil, 0xfffffffffffffffc, 0x0, 0x10, 0xffffffffffffffff, 0x0)
socket$inet(0x2, 0x0, 0x0)
syz_emit_ethernet(0xe, &(0x7f0000000000)={@remote, @remote})
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, &(0x7f0000000140))
setrlimit(0x0, 0x0)
sysctl$kern(0x0, 0x0, &(0x7f0000000340), 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{}, {0x74}, {0x812e}]})
syz_emit_ethernet(0x2a, &(0x7f0000000300)=ANY=[])


mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
sysctl$kern(&(0x7f0000000300)={0x2, 0x9}, 0x2, 0x0, 0x0, &(0x7f0000001440)="00000100", 0x4)


syz_emit_ethernet(0x3e, &(0x7f0000000100)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa86dd60362f0000008000000000000000000000000000000000bb60"])
msgsnd(0x0, &(0x7f0000000140)=ANY=[@ANYBLOB="0300000000000000a60d524ae979b5a3e111c8cac1b119e4db1e444c9d4eca7af32596137392f4cdc50d82caa6fa7ffd0da455fa2e9f5109d4ccbe9ddd5e3674e689a6714f0ac2ee9e36ae12821cff35f5866888d441f7c29189271982efb7cd9c94766d1c4be0efcbf44d5d0010dc9df78616b167b260dd96322bfbad5f46f92beb4126cf5ffee44ca5b5bdfcf14c9b3003f5"], 0x401, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001280)={0x0, 0x0, &(0x7f0000001200)=[{&(0x7f0000000180)="bf3b684c5ae963b4567084e096cf973983b85e5df6", 0x15}], 0x1}, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0206925, &(0x7f00000001c0))
r1 = semget(0x1, 0x3, 0x0)
semctl$SETALL(r1, 0x0, 0x9, &(0x7f0000000040)=[0x6, 0x1000, 0xff7f, 0x0, 0x6, 0x8, 0x5, 0x400, 0xb265])
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil, 0x2}, {&(0x7f0000455000/0x3000)=nil, &(0x7f0000159000/0x2000)=nil, 0x800000000006}, {&(0x7f00008a7000/0x4000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil}, {&(0x7f000026a000/0x4000)=nil, &(0x7f0000604000/0x3000)=nil}, {&(0x7f0000a31000/0x3000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f00002dc000/0x4000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f000032e000/0x800000)=nil, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000015000/0x3000)=nil, &(0x7f000015e000/0x2000)=nil}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil}], './file0\x00'})
socket$inet(0x2, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x2, &(0x7f0000000080), 0x0)
mprotect(&(0x7f0000ff3000/0x2000)=nil, 0x2000, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000300)=[{&(0x7f0000000140)="f005c71031c1c5f421277b09000000000000007a091a2f47be787538ec7a89ec5ed66daa731ddc384ecc690869a0aa2266affdf772d7a360ee0f15fa664f557bb45071fe9b6d9d28e6e2589000f6a64f370b9e336987d77b38f7aada5309e46a81e0e2efa087aa9f5f89934fdbd2ed96e7234b8972b273e810ca9962a8f461d3a05711a63027321ff62c", 0x8a}], 0x1)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000002c0)={<r2=>0xffffffffffffffff})
ioctl$FIONREAD(r2, 0xc0106924, &(0x7f00000001c0))
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x6012, 0xffffffffffffffff, 0x2)
setrlimit(0x0, &(0x7f0000000980))
kevent(0xffffffffffffffff, &(0x7f0000000040)=[{{}, 0x0, 0x0, 0x0, 0x3}], 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11, 0x0, 0x2}, 0x4, &(0x7f0000000140)="fa101824", 0x0, 0x0, 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
madvise(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x6)
r3 = getpid()
getsockopt$sock_cred(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000000)={<r4=>0x0}, &(0x7f0000000080)=0xc)
setsockopt$inet6_MRT6_ADD_MIF(0xffffffffffffffff, 0x29, 0x66, &(0x7f0000000380)={0x9, 0x0, 0xff, 0xb946, 0xf1b}, 0xc)
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
r6 = dup(r5)
ioctl$BIOCSETF(r6, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{0x2d}, {0x28}, {0x46}]})
syz_emit_ethernet(0x36, &(0x7f0000000840)=ANY=[])
setpgid(r3, r4)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x80146953, &(0x7f00000001c0))


openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x20, 0x0)
munmap(&(0x7f0000ffa000/0x3000)=nil, 0x3000)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
socket(0x11, 0x3, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
mknod(&(0x7f0000000280)='./bus\x00', 0x6000, 0x6d4)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2006, 0x4f4b)
open(0x0, 0x615, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000))
open(0x0, 0x200, 0x2)
socketpair$unix(0x1, 0x0, 0x0, &(0x7f0000000740)={<r1=>0xffffffffffffffff})
socket(0x18, 0x4001, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
r2 = open(&(0x7f0000001780)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSPGRP(r2, 0x40047477, 0x0)
listen(r1, 0x0)
r3 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$VNDIOCSET(r3, 0x20006473, 0x0)


sysctl$net_pipex(&(0x7f0000000000)={0x4, 0x22, 0x1}, 0x3, 0x0, 0x0, 0x0, 0x0)
sysctl$hw(&(0x7f0000000080)={0x6, 0x1}, 0x2, 0x0, 0x0, 0x0, 0x0)
socket(0x2, 0x2, 0x0)
r0 = openat$null(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
fcntl$lock(r0, 0x8, &(0x7f0000000100)={0x0, 0x0, 0x5, 0x100000000})
flock(r0, 0x1)
openat$null(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
syz_emit_ethernet(0x36, &(0x7f00000008c0)={@local, @local, [], {@ipv6={0x86dd, {0x0, 0x6, "054bc8", 0x0, 0x0, 0x0, @rand_addr="fea6c33fcf149110061d071ba4df80f0", @rand_addr="bc483e8c11a31ffb67769005dd0fbf29"}}}})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000340), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000240)=[{0x48}, {0x0, 0x0, 0x20}, {0x6}]})
syz_emit_ethernet(0x1019, &(0x7f0000000180)=ANY=[])


r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = kqueue()
open$dir(&(0x7f00000002c0)='./file0\x00', 0x200, 0x0)
r2 = open$dir(&(0x7f0000000200)='./file0\x00', 0x41, 0x0)
r3 = syz_open_pts()
sysctl$hw(&(0x7f0000000040), 0x2, &(0x7f0000000080), 0x0, 0x0, 0x0)
close(r3)
r4 = syz_open_pts()
ioctl$TIOCSETD(r3, 0x8004741b, &(0x7f0000000000)=0x7)
close(r4)
getdents(0xffffffffffffff9c, 0x0, 0x0)
kevent(r1, &(0x7f0000000200)=[{{r2}, 0xfffffffffffffffc, 0x0, 0x20000000, 0x6}], 0x8001, &(0x7f0000000080)=[{{r0}, 0xfffffffffffffffc, 0x80, 0x4000000e, 0x0, 0x100000001}, {{r3}, 0xffffffffffffffff, 0x92, 0x40000000, 0x10009, 0x7f}], 0x400, 0x0)
openat$wskbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
setreuid(0xee00, 0x0)
setreuid(0xee00, 0x0)
ioctl$WSKBDIO_SETDEFAULTKEYREPEAT(0xffffffffffffffff, 0x800c5709, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
semop(0x0, &(0x7f0000000000)=[{0x2, 0xfff, 0x800}, {0x0, 0x4, 0x1000}, {}, {0x2, 0x5}], 0x4)
r5 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r5, 0x801169ac, &(0x7f00000001c0))
pwrite(r3, &(0x7f0000000300)="d912bbe15522e832ca52da3f13cf3a2e2699068578517c653262aac0b99aba47b60835e31e31c0adfcaf80a9765d64f71fc80e36336c584449544b87f77450aecde45e0f96b5481f498c78831bd17e173c7c5637315cbc365edb40b3a7c3f089b2cef11e017f868a0fb6734f7ee2664206710e448c8d28ed39d11a5cd66df8e2e3791568b8cdd040b28ac06bb8dcb2a724182b1265403c97694581f5a57dfd4c47cf69e15382435f1a348489d80bde867d0b0366526e01ce4b907ae428fd37aa507d92e80b3a3861047444875ed5765bd8d05201cd702861717be26d348345c8bd91c0b1136651620d64c691bca9eba216e4336fe9f708e81d548b127c", 0xfd, 0x1)
r6 = kqueue()
munmap(&(0x7f0000001000/0x2000)=nil, 0x2000)
sysctl$kern(&(0x7f0000000300)={0x2, 0x9}, 0x2, 0x0, 0x0, &(0x7f0000001440)="00000100", 0x4)
unveil(0x0, 0x0)
kevent(r6, &(0x7f0000000240)=[{{}, 0xfffffffffffffff9}, {{}, 0x0, 0x2}], 0x0, 0x0, 0xfffffffb, 0x0)


semop(0x0, &(0x7f0000000040)=[{}, {}, {}, {}, {}, {}, {0x0, 0x0, 0x1800}], 0x7)
r0 = socket(0x11, 0x3, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504600000000000000007", 0xd, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
sendto$unix(r0, &(0x7f0000000000)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)


mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
mkdir(0x0, 0x0)
setreuid(0xee00, 0x0)
getuid()
chown(0x0, 0x0, 0xffffffffffffffff)
syz_emit_ethernet(0x3a, &(0x7f0000000100)={@local, @remote, [], {@ipv4={0x800, {{0x9, 0x4, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @multicast2, {[@timestamp={0x44, 0x10, 0x7, 0x3, 0x0, [{}, {}, {}]}]}}, @udp={{0x1, 0x3, 0x8}}}}}})


setuid(0xffffffffffffffff)
socket$inet(0x2, 0x3, 0x102)


open$dir(&(0x7f00000003c0)='./file0\x00', 0x400004000011830a, 0x0)
r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
r1 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
ioctl$SPKRTUNE(r0, 0x20005302, &(0x7f0000000280)={0x0, 0x8bd9})
r2 = open$dir(&(0x7f0000000100)='./file0\x00', 0x40000400001803c1, 0x0)
acct(0x0)
pwritev(r2, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r1, 0x0)
execve(0x0, 0x0, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000001380)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000480)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f00000006c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000580)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f00000007c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000a40)='./file0\x00')
link(&(0x7f0000000940)='./file0\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r1 = fcntl$dupfd(r0, 0x3, 0xffffffffffffffff)
writev(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f0000000200)='\n', 0x1}], 0x1)
ioctl$FIONREAD(r1, 0x8004745d, &(0x7f0000000200))


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
select(0x6c, &(0x7f0000000000), &(0x7f0000000040)={0xfffffffffffffffe}, 0x0, 0x0)
close(r0)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xffffffffffffffff, 0x0, 0xffffffffffffffff})
sysctl$kern(&(0x7f0000000040), 0x7, 0x0, 0x0, 0x0, 0xfffffe88)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0x9, &(0x7f0000000040)="00040080", 0x4)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r0, 0x0, 0x0)


r0 = socket(0x18, 0x400000002, 0x0)
getsockopt(r0, 0x29, 0x3d, 0x0, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000100))
open$dir(&(0x7f0000000180)='./file0/file0\x00', 0x100, 0x50)
open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
r0 = socket$inet(0x2, 0x2, 0x0)
sysctl$net_inet_icmp(&(0x7f00000005c0)={0x4, 0x2, 0x1, 0x5}, 0x4, &(0x7f0000000600), 0x0, &(0x7f0000000680), 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000080)="eaef125c000000", 0x7)
recvfrom(r0, &(0x7f0000000140)=""/186, 0xba, 0x1802, &(0x7f0000000040)=@in={0x2, 0x1}, 0xc)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
sysctl$net_inet_esp(&(0x7f0000000000)={0x4, 0x2, 0x32, 0x4}, 0x4, 0x0, 0x0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000180)={0x3, &(0x7f0000000700)=[{0x1c}, {0x81}, {0x6}]})
r2 = socket(0x18, 0x3, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r2, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x9}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
munmap(&(0x7f00005d9000/0x4000)=nil, 0x4000)
r3 = socket(0x18, 0x400000002, 0x0)
setsockopt(r3, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r4 = socket(0x18, 0x1, 0x0)
r5 = dup2(r3, r4)
sendmsg$unix(r5, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


r0 = open$dir(&(0x7f00000003c0)='./file0\x00', 0x400004000011830a, 0x0)
r1 = open$dir(&(0x7f00000002c0)='./file0\x00', 0x2, 0x0)
ftruncate(r1, 0x80002)
r2 = open$dir(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
preadv(r2, &(0x7f00000012c0)=[{&(0x7f00000001c0)=""/224, 0xfffffdd5}], 0x1, 0x0)
pwritev(r0, &(0x7f0000000340)=[{&(0x7f0000000080)='\x00', 0x8a8615b7}], 0x1, 0x126)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
r2 = dup(r1)
recvmmsg(r2, &(0x7f0000000440)={&(0x7f00000000c0)={0x0, 0x0, &(0x7f00000006c0)=[{0x0}, {0x0}, {0x0}, {&(0x7f0000000340)=""/87, 0x57}], 0x4, 0x0}}, 0x10, 0x64, 0x0)
r3 = dup2(r0, r1)
writev(r1, &(0x7f0000000080)=[{&(0x7f00000003c0)="ae", 0x1}], 0x1)
shutdown(r2, 0x0)
dup2(r3, r2)
execve(0x0, 0x0, 0x0)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f00000002c0)="b10005030000009f0500070107000000331c13fecea70500fef96ecfc72fd3357ae30200004e30ffd2d236acf20bf404be01000000f7c8cf5f882b297be1aa050400ce94e2f0ad3ebbc257029a1f139b672f335c22db830c032bfa896443c32118210000720fd38bfb0000fd54c125191b1257aea8c500001602fbfe0c2300008abfba0900000808f37193f8343712cc1100b71dc000090105000000000000001300"/177, 0xb1, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
syz_emit_ethernet(0x46, 0x0)
syz_emit_ethernet(0x36, 0x0)
socket(0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000001200)={0x1, 0x16}, 0x2, 0x0, 0x0, 0xfffffffffffffffe, 0xfffffffffffffe8e)
ktrace(0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000240)={0x2, &(0x7f0000000180)=[{0x2d, 0x0, 0x6}, {}]})
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x1000000029, 0x31, &(0x7f00000000c0)="b2116988b272d2dd3dc90142a84231a746e337b372e93320cff6669cbe7879de45ed3fc33719ca6dd678cec8a918458b2c10a1f8c66653b276e180e9cb9b21f9982230f575295d48889c9a920796b2dd92fc8575680b37ba955d2c15e6034b7daeb2273e89771aed96271a22d7c9198ed900ab006ddfb67869b51a2216114d1ece00"/144, 0x90)
ioctl$BIOCSDIRFILT(r0, 0x8004427d, &(0x7f0000000200)=0x6)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x2, 0x0)
socket(0x18, 0x2, 0x0)
sysctl$hw(0x0, 0x0, &(0x7f00000004c0)="001f03989dd49060e8", 0x0, 0x0, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f0000000040)={&(0x7f0000000000)=[{}], 0x1})
sysctl$kern(&(0x7f0000000040)={0x1, 0x59}, 0x3, 0x0, 0x0, &(0x7f0000000080)="4f1d4c6344b80ed788b6a4515248df3aa745bb992c574ab4cdf5587145812eab4a988f7fafd7a01d99776d988908cd186b51f34f8c15ffa0c685ad4116c783959eff4278384b4000384dbb1c2aaeff10b4135529a1da6fda67c67469d954be811b25ec5521559154c586eefff122009f659cd3e27e98a3241495005f102d9101d158284c0ee3250aa7c11042330de22a299ab00894fdc9bac6042d", 0xfffffc56)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x0, 0x0})
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x30}, 0x0, 0x0, 0x0, 0x0, 0x8000000000000000})
r2 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x1, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
r3 = socket(0x18, 0x2, 0x0)
close(r3)
r4 = socket(0x800000018, 0x1, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "1a1116f0d0f700"})
setsockopt$sock_int(r4, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r4, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000080)=[{0x30}, {0x20}, {0x8106}]})
syz_emit_ethernet(0x2e, &(0x7f0000000280)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000005c0)=[{0x5}, {0x3d}, {0x8016}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f00000001c0)=ANY=[])


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = syz_open_pts()
ioctl$TIOCSWINSZ(r0, 0x80087467, &(0x7f0000000100))


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
madvise(&(0x7f00003e0000/0x1000)=nil, 0x1000, 0x0)
munmap(&(0x7f00003e1000/0x1000)=nil, 0x1000)
minherit(&(0x7f00003e1000/0x2000)=nil, 0x2000, 0x0)


mprotect(&(0x7f00003b7000/0x1000)=nil, 0x1000, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000132000/0x3000)=nil, &(0x7f00000a0000/0x1000)=nil, 0x80400000}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f000008c000/0x2000)=nil, &(0x7f00001f0000/0x1000)=nil}, {&(0x7f00001f0000/0x1000)=nil, &(0x7f0000901000/0x3000)=nil}, {&(0x7f0000132000/0x4000)=nil, &(0x7f00000b2000/0x1000)=nil}, {&(0x7f000008a000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {0x0, &(0x7f000002a000/0x3000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000086000/0x3000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil}, {&(0x7f0000091000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000001000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000132000/0x1000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000008a000/0x1000)=nil}, {0x0, &(0x7f0000092000/0x3000)=nil}], './file0\x00'})
mprotect(&(0x7f0000145000/0x3000)=nil, 0x3000, 0x0)
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000800), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r0, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0})


r0 = socket(0x18, 0x0, 0x0)
setsockopt(r0, 0x1000000029, 0x28, &(0x7f0000000000)="5ab7776a", 0x4)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
socket(0x18, 0x2, 0x0)
socket$unix(0x1, 0x2, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
connect$unix(0xffffffffffffffff, &(0x7f0000000000)=@file={0x0, './file0\x00'}, 0xa)
sysctl$machdep(&(0x7f0000000080)={0x7, 0xf}, 0x2, 0x0, 0x0, &(0x7f0000001100), 0x2)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100))
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlink(&(0x7f0000000ac0)='./file0\x00', &(0x7f0000000e40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000f40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000300)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000200)='./file0\x00')
rename(&(0x7f00000007c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000001040)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mknod$loop(&(0x7f0000000440)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0xffffffffffff0000})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0xee00, r0)
socketpair(0x1, 0x5, 0x0, &(0x7f0000000380)={<r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000000)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000080)=0xc)
setregid(0x0, r2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f00000001c0)=[{}, {0x45}, {0x16}]})
writev(r0, &(0x7f0000000500)=[{&(0x7f0000000000)="af18a64591749e07ad1273f580a0", 0xe}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000480), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000140)=[{0x24}, {0x61}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000140)=[{0x20}, {0x2c}, {0x86}]})
syz_emit_ethernet(0x127, &(0x7f0000000040)=ANY=[])


syz_emit_ethernet(0x3a, &(0x7f0000000040)=ANY=[@ANYBLOB="ffffffff"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)="03000000", 0x4)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r0, 0xc0206921, &(0x7f00000001c0))
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x80206913, &(0x7f00000001c0))


sysctl$hw(&(0x7f0000000000)={0x6, 0x14}, 0x2, 0x0, 0x0, &(0x7f0000000100), 0x0)


socketpair$unix(0x1, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x4, &(0x7f0000000100)=[{0x25}, {0x1}, {0x3}, {0x6}]})
syz_emit_ethernet(0x127, &(0x7f0000000040)=ANY=[])


socket(0x0, 0x1, 0x0)
ioctl$VNDIOCSET(0xffffffffffffffff, 0x41946465, 0x0)
sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000000)="9b1809ffffffffffffff7f473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6fd74c94d1b44", &(0x7f0000000040)=0x10011, 0x0, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000240), 0x10, 0x0)
unveil(&(0x7f0000000280)='./file0/file0\x00', 0x0)
socket$inet(0x2, 0x1, 0x0)
getsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
setreuid(0xee00, 0x0)
getuid()
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x3, 0x0, 0x0, 0x0, 0x0, 0x60, 0x4}})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$VMM_IOC_INFO(r0, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})


r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x100000000000000, 0xffffffffffffffff})
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f00000000c0)="b211d7170d816685c8", 0x9)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


r0 = syz_open_pts()
readv(r0, &(0x7f00000012c0)=[{&(0x7f0000001200)=""/1, 0x1}], 0x1)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0xffffff9a, 0x0, "b07b1f660000000000002000"})
syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f00000000c0)={0x0, 0x0, 0xc25b, 0xfff, "9f7bfdbc3c8b3647d53e28c5062f8441c3c62a49"})


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
sysctl$net_inet_carp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
pipe(0x0)
poll(0x0, 0x0, 0x0)
fcntl$setstatus(0xffffffffffffffff, 0x4, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
sysctl$hw(0x0, 0x0, 0x0, &(0x7f0000000cc0), &(0x7f0000000d00), 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000180)=[{0x54}, {0x5}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])


r0 = accept$unix(0xffffffffffffff9c, &(0x7f0000000600)=@file={0x0, ""/4099}, &(0x7f0000000080)=0x1005)
setsockopt(r0, 0x0, 0x3f, 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r1 = getppid()
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r2=>0xffffffffffffffff})
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000100)={0x0, 0x0, <r3=>0x0}, &(0x7f0000000140)=0xc)
setregid(0x0, r3)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r4, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000080)=[{0x61}, {0x30}, {0x8106}]})
syz_emit_ethernet(0x7e, &(0x7f0000000400)=ANY=[])
getpid()
setregid(0x0, 0x0)
ktrace(&(0x7f0000000180)='./file0\x00', 0x4, 0x330, r1)


mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x0)
mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
link(&(0x7f0000000340)='./bus\x00', &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = dup2(r0, r0)
ioctl$FIONREAD(r1, 0x8020699d, &(0x7f00000001c0))


mknod(&(0x7f0000000040)='./file0\x00', 0x6000, 0xe02)
open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)={0x3, 0x7fffffff})
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
r0 = open(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
ioctl$TIOCGFLAGS(r0, 0x4004745d, &(0x7f00000002c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x30, 0x0, 0x158, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0, 0x1)
r2 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x0)
r3 = open(0x0, 0x0, 0x0)
close(r3)
r4 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r4, 0x6, 0x10, 0x0, 0x0)
setsockopt(r4, 0xd0b, 0x10, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
socket$inet(0x2, 0x1, 0x0)
setsockopt(r0, 0x7, 0x20f, &(0x7f0000000180)="00000001", 0x4)
pread(r2, &(0x7f0000000040)="16", 0x1, 0x400)
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r5, 0x80104277, &(0x7f00000002c0)={0x3, &(0x7f0000000400)=[{0x54}, {0x6c}, {0x6, 0x0, 0x0, 0xe00000}]})
writev(r5, &(0x7f0000000600)=[{&(0x7f0000000100)="ba2128", 0x3}, {&(0x7f0000000300)="7a9f30a344ddd8175e00c5", 0xb}], 0x2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000080)=[{0x84}, {0x74}, {0x8106}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


syz_emit_ethernet(0x46, &(0x7f0000000400)=ANY=[@ANYBLOB="7bca7e58f7cd00000000000086dd609f284400102b00fe8000000000000000000000000000bbfe8000000000000000000000000000bb2b002000000000004e214e23000890787149b751629772d3a59603a1537b836e44a0c2b670581b2fc56a5a68b4703cc3232f9d98ae816aa5f049cef81bd609c0d484033df5b56ed9d67f32f49a"])
clock_gettime(0x0, 0x0)
syz_open_pts()
msgget$private(0x0, 0x0)
pipe2(&(0x7f0000000000)={<r0=>0xffffffffffffffff}, 0x10004)
writev(r0, &(0x7f0000000180)=[{&(0x7f0000000280)="4dfb6b79951845e2cd9668618b36d93df01b8b7d45d0bc640ada53de1096c280bc3fe8a11c5a39a07cc0aca57612f97d4b101b5199f73cd5a5bb955d8f2ab8d018223f7b466cfec2b1a9fb56b65db7afa8570d748d5d8c08785882a940bd45d0984200a1bcd0fac462e146746296242e7342abce5beee86b92b0be65d3aef495a0ec7e2df79837fde3b44ac1773ffd11cf2531da", 0x94}], 0x0)
socket(0x11, 0x3, 0x0)
sysctl$net_inet_carp(&(0x7f0000000100)={0x4, 0x2, 0x6, 0x3}, 0x4, 0x0, 0x0, &(0x7f0000000340)="e100000067c60ea20c65db0d60e62a7316397d24f47f5237775d664bf2bad0d53686e4ff8018298ee00bd616877154e27172deaaf9ff74f8cc0cf83346bba5e18e7a0254eb310c2c8d75ff835a5e536ad407595d941c506192a328d7e9da31490b3484f2e5acc33864767135e4c14ae388f9336b5d4d083ec63e01ef9f07b46dfccf7d993b52b6aa7c2bb143735b0000000000000007f6274791f31bae29aa0000002e160d695b83cdf336f57847b5eb6c", 0xb1)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000000)=[{0x2}, {0x80, 0x0, 0x0, 0x8}, {0x8106}]})
ioctl$BIOCIMMEDIATE(r1, 0x80044270, &(0x7f0000000080))
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x4, 0x1100, 0xffffffffffffffff)


socket(0x0, 0x3, 0x3a)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "0100012d29fb000700000000098002005e00"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x4f}, 0x3, &(0x7f0000000440)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26010000005f8ce92bcefd3eceefabee7e3ebe6c7a36746af569ae94b5d1275a9807ef9e0dd96d5d22fcd1289c80d3135ee0d4ccf9cf3d6f8ce70202fcd0738c22516d797a6d4d4577073c00a40824e97f013e56d710915d35dfeb96c0edbd0fc1381ac8d1c3a91ad2d50588da310100000000000000a7c210e97256c8538d64f6ef4ee0513d784dcd7abd974898cd9876d750b23a36c756c3edf75a3d576af5f2a5edc217ca61ebb52a7692889975c180baac6798938ec34cd37b28436db93be49e1907dba3eec9a40afdf9058648e598fd163ba9361ccc99fb6ccd7068422c486a7eb35daa8a6cfbbc01269fe7088b3fd869af60bc0c60136c7717064a9d46c82544ca34442be10218d1fd37ba0603b4f2aec29fa14dba20301a961810d2094eb17e9f4d263cb6cddf913c915a11060c88fd5f3030febd07d4e57c9ae190725f3cc44f193a2f5fabdf894005e7b3280d96ec12d3af346a940924986ba166f3d97bc1db4eff", &(0x7f0000000080), &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0x4)
fchownat(0xffffffffffffffff, &(0x7f00000001c0)='./file0/file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0xffffffffffffffff, 0x0, 0x0)
sendmmsg(0xffffffffffffffff, &(0x7f00000007c0)={&(0x7f0000000780)={0x0, 0x0, &(0x7f0000000400)=[{&(0x7f0000000180)="b860fe09625ee6793978a575faa1b6c6c1d6c2eca2950e663d39ab1be31a269a39fd7f97e41e178f37a79f00659c2ea9ac56733f7e4e4973c1e6b33ac91343ea3b3f8c5c7b93d5c20ab4211791fe30", 0x4f}], 0x1, 0x0}}, 0x10, 0x0)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x81000300010008, 0xffffffffffffffff})
pwritev(r0, &(0x7f00000000c0)=[{&(0x7f0000000100)='mS', 0x2}, {&(0x7f0000000640)="a392c0fca4e0a9f8dbf1a3c1c72dfa163e52799a5290120b121fd63e09d6ba4a85ce98f177511d5a876af591dc44b43ec112edf8a7639b9548ac01d4fecadb58e195fd41fe51b8c16335c8c03edddbbc67d4eafb49a62faf488cfd7e7d17cbf021397c49dde6d2240fe5a8b2a6934c4d04a5c84cdef53b5aa72be7022c86f51e30ee08e0f34fda68b2df5849baf10a2df6c3098a2273ca464d7877a36f63de078bd77c89345a1bc6cc16bf53f02483784fe646ce076f4152f30b35827aeceb14a57af87b19f9fbac84cc6b7f0ecd6d27b507d878ba8748e1642db23936120d82dc5f151706a741239aac0a06fc9e944246a6c8", 0xf3}], 0x2, 0x3)
socket(0x2, 0x2, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = semget$private(0x0, 0x4, 0x3c8)
semop(r1, &(0x7f0000001480)=[{0x3, 0x6}, {0x3, 0x2ff}, {0x1, 0x8, 0x1000}, {0x0, 0xfffd, 0x1000}, {0x1, 0x1, 0x3400}, {0x0, 0x9}, {0x3, 0x800, 0x1000}], 0x7)
semctl$SETALL(r1, 0x0, 0x9, &(0x7f00000002c0)=[0x3, 0xfff])
semctl$SETALL(r1, 0x0, 0x9, &(0x7f0000000140)=[0x6, 0x2080])
getegid()
getegid()
r2 = getuid()
syz_emit_ethernet(0x17a, &(0x7f00000004c0)=ANY=[@ANYBLOB="f3a2a8908a86aaaaaaaa8fbb86dd601ab5b6ffffffc200000000000000000000000000000000ff0200000000000000000000959c0001ae3c5815762ac3c36796cf0a27dd1a668622ab9396ac400311e6ff185835d3553cdd7e1d3558ea78632dab3c24fd6903b51be42b613969572f972a300bc17c60e99214bc93d05586c28717369b8a89d7bdfe15935c1dd11c658f60c284ad84cfcb04f553960b9cfce0f3cc447621ba57fc16e1759ff7df7e787657ecd80d7a9ed05ff166a418d6ad6dddbac4930ce73f6450e68d82df8c0097d4ddcd202e76044fe06c2addd49c33d583d1b0717383a0ac90fc263c60cae452a103fff490730cb5071c2d9252889155723da92fb4f1a266d98dc37fc4f8769fab233633b1bc6641866df9b507c6674d3fd6907694afb746ce7bd3b1"])
setreuid(0xee00, r2)
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f00000000c0)={{0x10000, 0x0, 0xffffffffffffffff, r2, 0x0, 0x181, 0x200}, 0x2, 0xd47, 0x7})
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f00000007c0)={{0x8001, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7}, 0xfffff7fffffffffd, 0x104, 0xfffffffffffffffa})
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r3 = socket(0x18, 0x3, 0x3a)
setsockopt(r3, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r3, 0x29, 0x66, 0x0, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000180)={0x0, <r4=>0x0}, &(0x7f00000001c0)=0xc)
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f0000001240)={{0x8, 0x0, 0x0, r4, 0x0, 0x8, 0x9}, 0x0, 0x4d, 0x2})


poll(&(0x7f0000001300)=[{}, {}], 0x2, 0x87e)
r0 = open(&(0x7f0000001440)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x10, r0, 0x0)
ftruncate(r0, 0x25b3)
execve(0x0, 0x0, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
shmctl$IPC_SET(0x0, 0x1, &(0x7f0000000000)={{0xffffffff, 0x0, 0x0, 0xffffffffffffffff, 0x140}, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0xfffffffffffffffe})
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
open(0x0, 0x0, 0x104)
setreuid(0xee00, 0x0)
r0 = getuid()
chown(&(0x7f0000000140)='./file0\x00', r0, 0x0)
chmod(&(0x7f0000000200)='./file0\x00', 0x1a4)
setreuid(0xee00, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
r1 = socket$inet6(0x18, 0x2, 0x0)
setsockopt$inet6_MRT6_ADD_MFC(r1, 0x29, 0x25, 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r2 = msgget$private(0x0, 0x0)
msgsnd(r2, &(0x7f00000000c0)=ANY=[@ANYRES32], 0x1f, 0x800)
r3 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
setsockopt$inet6_MRT6_DEL_MFC(r1, 0x29, 0x69, &(0x7f0000000240)={{0x18, 0x1, 0x6, 0x2}, {0x18, 0x1, 0x4, 0x7ff}, 0x3f, [0xffffffff, 0x80, 0x1, 0x1, 0x823, 0x0, 0x1, 0x7fff]}, 0x3c)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x55421451)
open(&(0x7f00000002c0)='./bus\x00', 0x0, 0x0)
ioctl$WSMOUSEIO_SCALIBCOORDS(r3, 0x81205724, &(0x7f0000000300)={0x1, 0x100, 0x400, 0x9, 0x7f, 0xf4, 0x1, 0x10, [{0x6, 0x100, 0xff, 0x8}, {0x3a12, 0x5, 0x896, 0x8}, {0x5, 0x4, 0x762, 0xb4d1}, {0x7, 0x0, 0x98cc, 0xc7f9}, {0xc992fefa, 0x4, 0x2, 0x2}, {0xa0f5, 0x73e, 0x9, 0xfffffeff}, {0x3, 0x3, 0x7, 0x3}, {0x4, 0x5, 0xc53, 0xfffffffe}, {0x200, 0x40, 0x80, 0x20}, {0x6, 0x0, 0x9}, {0x5, 0x280, 0x3, 0x4}, {0x1, 0x0, 0x5, 0x10000}, {0x0, 0x4, 0x1000, 0x7fffffff}, {0x400, 0x2, 0x401, 0x5b38}, {0x6, 0x7f, 0x79db, 0x7fff}, {0x7f, 0x5, 0x80, 0x5}]})
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
writev(0xffffffffffffffff, &(0x7f00000000c0), 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)


mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5f1b)
open(&(0x7f0000000a80)='./file0\x00', 0x0, 0x0)


sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x18}, 0x4, &(0x7f0000000040), 0x0, &(0x7f0000000100), 0x0)


sysctl$vm(&(0x7f0000000000)={0x6, 0x5}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000000), 0x2, 0x0, 0x0, &(0x7f0000001440), 0x0)


r0 = socket(0x2, 0x2, 0x0)
getsockname$unix(r0, &(0x7f0000000000)=@abs, &(0x7f0000001200)=0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x2, 0x3, 0x0)
bind(r1, &(0x7f0000000000), 0x10)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000240)={0x3, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x0, 0x2}, {0x6}]})
socket(0x18, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x802069b5, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000934, 0x0)
open(0x0, 0x0, 0x0)
mkdir(&(0x7f0000000200)='./file0\x00', 0x40)
socket(0x18, 0x2, 0x0)
select(0x0, 0x0, 0x0, 0x0, &(0x7f00000000c0))
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000740)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000380)=""/93, 0x5d}, 0x3f8d}, 0x10, 0x0, 0x0)
sendmmsg(r0, &(0x7f0000000080)={0x0}, 0x10, 0x0)
close(r0)
socket$inet6(0x1e, 0x0, 0x0)
pwritev(0xffffffffffffffff, &(0x7f0000000540)=[{0x0}], 0x1, 0x0)
sysctl$net_inet_ah(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$vm(&(0x7f0000000000)={0x4, 0x2}, 0x7, &(0x7f0000000040)="c06d154be3aee5f8787f8b9cda7554335b763bb5deea5ccecb4d1b57a9f6fa18e47fc7b119db587e58811e666e84a806495b45c36164bd5b135280243ed0a01466056e93082876ba33ee8cf2b0b3907f236f38175101000000d7e39544aea098d19ee63d03cbf92380dbe904538135f09e408bbe17a54a364b04ee64b0ad54e6d4e38114ced38c328aff2e224239ba29eb0796e8c3e8344a2cd9e663bb21035ebf391872f3015c164556e4a5b966122c56edd85fc996f12fa1b92e47aa", 0x0, 0x0, 0xfffffffffffffe8f)
r1 = semget(0x2, 0x4, 0x300)
syz_open_pts()
semop(r1, &(0x7f0000000140)=[{0x3, 0x0, 0x1000}, {0x3, 0x0, 0x1000}, {0x2, 0x81, 0x1800}, {0x0, 0x5, 0x1000}], 0x4)


sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f00000001c0)="6b60e150687496805a31", 0xa)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f00000001c0))


getuid()
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001280)={0x0, 0x0, &(0x7f0000001200)=[{&(0x7f0000000180)="bf3b684c5ae963b4567084e096cf973983b85e5df63e013eaa9405095e88157332b4f68e78e0793d3e30417acbf4419893cfd424b75262dc5ade2ab6278ab86672f9ed186987b8c19d9295a17b98020f6002", 0x52}], 0x1}, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(r0, 0xc0206921, &(0x7f00000001c0))


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000180)="b1000504600000000000000007000000331c13fecea10500fef9ed06c72fd3357ae320b37b673039d2d236073705ae04be38164991f7accf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139b672f4d335d223e7d029d6ba8af630037282102000000720f70c1f5a472c881ea6e69e0bb76d907c400000200361b1257aea8c5000020020000000000008abfba09001d89f00100ffffffff008000ff00"/177, 0xb1, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSDLT(r0, 0x8004427a, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000180)={0x3, &(0x7f0000000080)=[{0x80}, {0x80}, {0x16}]})
write(r0, &(0x7f0000000140)="7f06000080ce25364aa1dbef75e1", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000700)=[{0xc}, {0x28}, {0x6, 0x0, 0x0, 0xfffffffe}]})
write(r0, &(0x7f0000000540)="76e5dead6f01f8607d2100000063", 0xe)


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
syz_emit_ethernet(0x4a, &(0x7f0000000040)={@broadcast, @local, [], {@ipv6={0x86dd, {0x0, 0x6, "cbe4c8", 0x14, 0x0, 0x0, @mcast2, @mcast1, {[], @tcp={{0x1, 0x2, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}}})
ioctl$FIONREAD(r0, 0xc0106978, &(0x7f0000000040))


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSPGRP(r0, 0x40047477, &(0x7f0000000540))


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xfffffffffffffffe, 0x0, 0xffffffffffffffff})
r0 = socket(0x10, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r3 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r3, 0xc0106924, &(0x7f00000001c0))
r4 = kqueue()
kevent(r4, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r5 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r5, 0x802069c5, &(0x7f00000001c0))
close(r2)
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)}], 0x1)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
r6 = socket$inet(0x2, 0x2, 0x0)
close(0xffffffffffffffff)
r7 = socket$inet(0x2, 0x2, 0x0)
dup2(0xffffffffffffffff, r7)
setsockopt$inet_opts(r7, 0x0, 0x200000000000c, &(0x7f0000000240)="ea020000", 0x4)
setsockopt$inet_opts(r6, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0x8)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000))
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
r8 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r8, 0x8020426c, &(0x7f0000001180)={'tap', 0x0})
ioctl$BIOCSETWF(r8, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{}, {0x48, 0x0, 0x0, 0x4}, {0x6}]})
write(r8, &(0x7f0000000180)="23009100007adb020317bdda", 0xc)


r0 = openat$pf(0xffffffffffffff9c, &(0x7f0000000000), 0x8000, 0x0)
fcntl$setstatus(r0, 0x4, 0x40)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCLOCK(r0, 0x20004276)
r1 = dup(r0)
seteuid(0xffffffffffffffff)
ioctl$TIOCSPGRP(r1, 0x40047477, &(0x7f0000000080))


openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
open(0x0, 0x0, 0x0)
kqueue()
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
sysctl$kern(&(0x7f00000000c0), 0x2, 0x0, 0x0, 0x0, 0x0)
mknod(0x0, 0x2000, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
sendmsg$unix(r0, 0x0, 0x0)
openat(0xffffffffffffff9c, 0x0, 0x0, 0x0)
setreuid(0xee00, 0x0)
openat(0xffffffffffffffff, 0x0, 0x0, 0x0)
getuid()
socket(0x2, 0x2, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0xb2}})
r1 = socket(0x18, 0x1, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r1, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
r2 = socket(0x18, 0x2, 0x0)
r3 = socket(0x18, 0x2, 0x0)
setsockopt(r3, 0x1000000000029, 0xa, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
dup2(r3, r2)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f00000000c0)={0x0, 0x1ff}, 0x10)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmsg(r2, &(0x7f0000000ec0)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)
r4 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r4, 0x0, 0x4, &(0x7f0000000000), 0x0)


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x3, 0x0, 0x0, 0x1}, 0xc)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000000), 0xc)


sysctl$net_inet_ah(&(0x7f0000000000)={0x4, 0x2, 0x33, 0x2}, 0x4, 0x0, 0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
sysctl$net_inet_ah(&(0x7f0000000240)={0x4, 0x2, 0x33, 0x1}, 0x4, &(0x7f0000000280)="75d916cf2a8090d0d290072b7767c8f7a230b04db693f2dc797b88aba8226f70943858b294786fb13c44dd389971784f6521d74eba620ed9a86f6b2763c00197499d1769407522ff1e3beaff5d826f2d87cd4e9ce9824d5639", 0x0, &(0x7f0000000340), 0x0)
mknodat(0xffffffffffffff9c, 0x0, 0x2000, 0x200)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f00000001c0)=[{0x14}, {0x84}, {0x8106}]})
syz_emit_ethernet(0x62, &(0x7f0000000140)=ANY=[@ANYRESDEC=r0, @ANYRESHEX=0x0, @ANYRES8=r0, @ANYRES8=r0, @ANYRESHEX=r0, @ANYRES8=r0])
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x8040691a, &(0x7f00000001c0))


r0 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000140)='x\x00')
unveil(&(0x7f0000000040)='./file0\x00', &(0x7f0000000080)='c\x00')


setrlimit(0x6, &(0x7f0000000980)={0x8, 0xad00})
syz_open_pts()
close(0xffffffffffffffff)
r0 = syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f00000002c0)={0x0, 0x0, 0x0, 0x0, "bb08000115f167591050c30abfa522f6919800"})
socket$inet(0x2, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
mprotect(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x2)
r1 = open(0x0, 0x0, 0x1)
writev(r1, 0x0, 0x0)
msgctl$IPC_SET(0x0, 0x1, 0x0)
socket(0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r2 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0106924, &(0x7f00000001c0))
r3 = kqueue()
kevent(r3, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r4 = socket(0x0, 0x3, 0x0)
ioctl$FIONREAD(r4, 0xc0206921, &(0x7f00000001c0))
r5 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r5, 0x80206919, &(0x7f00000001c0))
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000040)=0x2b0, 0x4)
r6 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r6, 0x8020690c, &(0x7f00000001c0))


r0 = open(&(0x7f0000000280)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000028000/0x4000)=nil, 0x4000, 0x0, 0x10, r0, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000280)=[{}, {}], 0x2})
r1 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_GETPARAMS(r1, 0x80105727, &(0x7f00000000c0)={&(0x7f0000000140)=[{0x100}], 0x1})
r2 = socket(0x2, 0x1, 0x0)
shutdown(r2, 0x0)
listen(r2, 0x0)
select(0x40, &(0x7f0000000000)={0xffffffffffffffff}, 0x0, 0x0, 0x0)
select(0x40, &(0x7f0000000180)={0x19}, 0x0, 0x0, 0x0)
r3 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VMM_IOC_INTR(r3, 0x800c5606, &(0x7f0000000040)={0x5})
setsockopt$inet6_MRT6_DEL_MFC(r2, 0x29, 0x69, &(0x7f0000000200)={{0x18, 0x3, 0x401, 0x4}, {0x18, 0x0, 0x3, 0x6}, 0x7, [0x8, 0xa6aa, 0x80000003, 0x4, 0x7, 0xfffffffe, 0x1, 0x9c6]}, 0x3c)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000132000/0x3000)=nil, &(0x7f00000a0000/0x1000)=nil, 0xc0400000}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f0000065000/0x2000)=nil, &(0x7f0000093000/0x1000)=nil}, {&(0x7f00001f0000/0x1000)=nil, &(0x7f000008a000/0x3000)=nil}, {&(0x7f000008f000/0x3000)=nil, &(0x7f00000b2000/0x1000)=nil}, {&(0x7f000008a000/0x4000)=nil, &(0x7f0000063000/0x3000)=nil}, {&(0x7f0000087000/0x4000)=nil, &(0x7f000002a000/0x3000)=nil}, {&(0x7f000008d000/0x4000)=nil, &(0x7f0000086000/0x3000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000001000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000132000/0x1000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000087000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f000008a000/0x2000)=nil, &(0x7f0000092000/0x3000)=nil}], './file0\x00'})
ioctl$WSMUXIO_LIST_DEVICES(0xffffffffffffffff, 0xc1045763, &(0x7f0000000040)={0x0, [{}, {}, {}, {}, {}, {}, {}, {0x0, 0xc8}]})
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)
r4 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000800), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r4, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0})


setitimer(0x1, &(0x7f0000001ac0)={{}, {0x1}}, 0x0)
setitimer(0x2, &(0x7f0000001dc0), 0x0)


r0 = socket$inet(0x2, 0x1, 0x0)
setsockopt$inet_opts(r0, 0x6, 0x1, 0x0, 0x0)


poll(0x0, 0x0, 0x0)
close(0xffffffffffffffff)
openat$speaker(0xffffffffffffff9c, 0x0, 0x2, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f00000005c0)="b107ea397682e68ba592222e26eb0e783affaa", 0x13, 0xa, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000), 0x2, &(0x7f0000000080)="71f91e3471ac0058bc5a91501d94a34b8e5f84cc42c3fbe6edf28f03055a7b8379c80000ff7f000000000000000000", &(0x7f0000000040)=0x2f, 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = open$dir(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')
fchdir(r0)
mkdir(&(0x7f0000000080)='./file0/file0\x00', 0x0)


open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
ktrace(&(0x7f0000000040)='./file0\x00', 0x4, 0x112, 0x0)
mprotect(&(0x7f0000000000/0x1000)=nil, 0x1000, 0x1)
select(0x40, &(0x7f0000000000), 0x0, &(0x7f0000000080), &(0x7f0000000100))


socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000000c0))
sysctl$net_inet6_icmp6(0x0, 0x0, &(0x7f0000000080)="65feaba9a71942a5", &(0x7f0000000100)=0x8, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000200)={0x4, 0x2, 0x6, 0x19}, 0x4, 0x0, 0x0, &(0x7f00000002c0)="e2420dc5", 0x4)
socket$inet(0x2, 0x3, 0x0)
mkdir(&(0x7f0000000240)='./file0\x00', 0x108)
setreuid(0xee00, 0x0)
r0 = getuid()
seteuid(r0)
chdir(&(0x7f0000000140)='./file0\x00')
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000180)=[{}, {}, {{}, 0x0, 0x0, 0x0, 0x20000000210}], 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x2, 0x0)
sysctl$kern(&(0x7f0000000040), 0x1, 0x0, 0x0, 0x0, 0x0)
r1 = socket(0x18, 0x3, 0x3a)
seteuid(r0)
setsockopt(r1, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MFC(r1, 0x29, 0x68, &(0x7f00000000c0), 0x5c)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{0x0, 0x0, 0x0, 0x402}, {0x2}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x33}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)


mkdirat(0xffffffffffffffff, &(0x7f00000001c0)='./file1\x00', 0x0)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f00000001c0))


mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x1010, 0xffffffffffffffff, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)


connect$unix(0xffffffffffffffff, 0x0, 0x0)
getsockname$inet(0xffffffffffffffff, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ecaca5cae2000140", 0x8)
mknod(0x0, 0x0, 0x0)
r1 = semget$private(0x0, 0x7, 0x3c0)
semop(r1, &(0x7f0000000180)=[{0x3, 0x43, 0x1800}, {0x1, 0xfffe, 0x1800}, {0x0, 0xfd, 0x1000}, {0x1, 0x20, 0x1800}, {0x2, 0x5, 0x1800}, {0x4, 0x9e}, {0x2, 0xfffb, 0x1000}, {0x0, 0x40, 0x3800}, {0x3, 0x8}], 0x9)
semctl$SETALL(r1, 0x0, 0x9, &(0x7f00000004c0)=[0x9, 0x1001])
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f0000000240)={{0x0, 0xffffffffffffffff, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x2}, 0x0, 0x2000000009, 0xe7})
semctl$GETNCNT(r1, 0x4, 0x3, &(0x7f0000000280)=""/108)
mprotect(&(0x7f00001bc000/0x1000)=nil, 0x1000, 0x5)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCVERSION(0xffffffffffffffff, 0x40044271, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000000)=[{0x5, 0x8}, {0x28}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000180)=ANY=[])
r3 = syz_open_pts()
sysctl$hw(&(0x7f0000000100)={0x6, 0x7}, 0x2, 0x0, 0x0, 0x0, 0x0)
ioctl$FIOASYNC(r3, 0x80047460, &(0x7f0000000000)=0x20)
socket$inet(0x2, 0x2, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x6381)
r0 = openat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x8, 0x4)
kevent(0xffffffffffffffff, &(0x7f0000000100)=[{{r0}, 0xfffffffffffffffe, 0xbf}], 0x0, 0x0, 0x0, 0x0)
r1 = kqueue()
r2 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r2, 0xc2485607, &(0x7f0000000040)={0x2, 0x0, 0x5c, 0x0, 0x0})
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000080)={0xfffffe03, 0x1f, 0xfff, 0x3505, "f54cb991d0b1db2a69d4ee281675ec6f3949d0a9", 0x8c, 0x9c})
syz_emit_ethernet(0x2e, &(0x7f0000000000)={@broadcast, @remote, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x1, 0x0, @remote={0xac, 0x14, 0x0}, @multicast1, {[@lsrr={0x83, 0x3}]}}, @icmp=@mask_request}}}})
kevent(r1, &(0x7f0000000080), 0xfd, 0x0, 0x8002, 0x0)
kevent(r1, 0x0, 0x0, &(0x7f0000000400), 0x4, 0x0)
r3 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f00000000c0), 0x40, 0x0)
close(r3)


mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x1012, 0xffffffffffffffff, 0x0)
utimes(0x0, &(0x7f0000000040))


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x0, "0100000000b0b9c136000000000000005009005b"})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x7, &(0x7f0000000180)="0f23ca2c46f903007c1be211c867c99d710339a5ac5c07000000b5cf9d33274f43803a6f9f609dd10254483f68de49c8f4e69df70d457a4ec40d461fbba00318e8ca5e5cc5cc354e1331fec148bf44ab64f40013b8478982b29012a51b442c992836d21ba42ee872ddca05bdcfe00835194b313313166710b55d20f7c9156a75eeff0a6254a76f2c8da3507903d37517f09e1d4eacdbf6b069c17b1b70687376469ac45425402537f1c4bdcbc59625b3820a63e262b9ce294365531457245c342e13231168de5821f9d892e93d34844691dbc03e6c20ac46f86335caff9091f13d66945ec6ebb6deeeab1a7ba80ca1d1431cea0a28ec383edf11", 0x0, 0x0, 0xd6b564e3a461cd30)


sysctl$net_inet_ip(&(0x7f0000000080)={0x4, 0x2, 0x0, 0x5}, 0x4, &(0x7f0000000140)="e33745e8", &(0x7f0000001680)=0x4, 0x0, 0x0)


sysctl$hw(&(0x7f0000000100)={0x6, 0x8}, 0x2, &(0x7f0000000180)="113da6949a21ae40f98efe56ceed6f0c1cb790d557", &(0x7f0000000200)=0x15, &(0x7f0000000240), 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(0xffffffffffffffff, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000401})
r0 = socket$inet6(0x18, 0x3, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x1021, &(0x7f0000001ac0), &(0x7f0000001b00)=0xffffffffffffff10)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r1 = getpid()
ioctl$WSDISPLAYIO_GETEMULTYPE(0xffffffffffffff9c, 0xc014575e, 0x0)
fcntl$setown(0xffffffffffffffff, 0x6, r1)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
r3 = getpid()
setpgid(0x0, 0x0)
pipe(0x0)
fcntl$setown(0xffffffffffffffff, 0x6, r3)
r4 = semget$private(0x0, 0x4000000009, 0x82)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000400)={0x2, &(0x7f0000000040)=[{0xed1, 0x41, 0x6, 0x80}, {0x3}]})
r5 = openat$zero(0xffffffffffffff9c, &(0x7f0000000180), 0x80, 0x0)
close(r5)
flock(r5, 0x0)
semop(r4, &(0x7f0000000300)=[{0x0, 0x6}, {0x4, 0x0, 0x1800}, {0x1, 0x0, 0x800}, {0x2, 0x1}, {0x2, 0x0, 0x1000}, {0x4, 0xfc0a, 0x1800}, {0x3}, {0x3, 0x5}, {0x4, 0xfff7, 0x800}, {0x3, 0x46a, 0x1800}, {0x2, 0x1}], 0xb)
semctl$SETALL(r4, 0x0, 0x9, &(0x7f00000001c0)=[0x0, 0x1, 0x7])
getegid()
madvise(&(0x7f0000000000/0x4000)=nil, 0x100000000000000, 0x0)
semctl$SETALL(0x0, 0x0, 0x9, &(0x7f0000000200)=[0x1, 0x4, 0x6])
semctl$IPC_RMID(r4, 0x0, 0x0)
kqueue()
ioctl$TIOCSETA(r2, 0x802c7414, &(0x7f0000000000)={0x0, 0x4, 0xffffff9a, 0x1c, "c07b00", 0x1})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
fcntl$lock(0xffffffffffffffff, 0x8, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x1000300010008, r1})


mknod(&(0x7f0000000000)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x1, 0x0)
ioctl$FIONREAD(r0, 0xc02069b6, &(0x7f00000004c0))


r0 = socket(0x18, 0x3, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x1007, 0x0, 0x0)


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r0)
r1 = kqueue()
writev(r1, &(0x7f0000000080)=[{0x0}], 0x1)


r0 = accept$unix(0xffffffffffffff9c, &(0x7f0000000400)=@file={0x0, ""/252}, &(0x7f0000000200)=0xfe)
writev(r0, &(0x7f0000000500)=[{&(0x7f0000000180)="83bc8e5b20b5fdf6c9042af45455ac959a51093e42b4908a5436af275aa9ce81a805e335d6d2dc9e6356b576194336c617f8809e6b2db94b11914242fff6b79238e790571751fe1015f7", 0x4a}], 0x1)
open$dir(&(0x7f0000000040)='./file0\x00', 0x300, 0x0)
ktrace(&(0x7f0000000540)='./file0\x00', 0x1, 0x40000730, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x3})
poll(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f0000000100)={0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000200)={0x7, &(0x7f00000002c0)=[{0x0, 0x4}, {0x80, 0xfd}, {}, {0x22, 0x80, 0x8, 0x1000}, {0xb133, 0xc0, 0x4, 0x1}, {0xb, 0x0, 0x26, 0x2}, {0x45a, 0x9, 0x1f, 0x4005}]})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x7fffffff, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000773000/0x4000)=nil, 0x4000, 0x4)
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x0, 0x0, &(0x7f0000000480)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x36}, 0x2, &(0x7f00000005c0)="71f91e3471ac0058bc5a91501d942400b5e1a0757cb9af769c7afec3708275147eab7674f538d19d78d4e174541cf9198d345191efadab0577d80100000000000000a0", &(0x7f0000000080)=0x43, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504000004000000000007000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000022acf2047804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0e032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4fcf668246c0900e1937c727a4bdb8d000008e37123fc", 0xad, 0x0, 0x0, 0x0)
socket(0x11, 0x3, 0x0)
mprotect(&(0x7f0000772000/0x4000)=nil, 0x4000, 0x5)
pipe(&(0x7f0000000080))


sysctl$net_inet6_icmp6(&(0x7f0000000000)={0x4, 0x18, 0x3a, 0xe}, 0x4, &(0x7f0000000040)="6f6262d48eee401774d945988a6d2764bcf8c91a423f76e67c86b45f3a004805f48fea66b730f186bea03974cc50af3a1fcfa27d36140225bf759e2281d802d8a756452d7b1ca5bcd25cc8881407c30592490c054590b4eaf45ce3311037c985e1813c49c70ff7ba97e45f8add817fefddf08b51d0e71fa5", &(0x7f0000000140)=0x78, &(0x7f0000000180)="74ad4986625bc4a80babf915b25b63787e2c13", 0x13)
semctl$SETALL(0x0, 0x0, 0x9, 0x0)
r0 = socket(0x2, 0x4001, 0x0)
ioctl$FIOASYNC(r0, 0x8004667d, &(0x7f0000000200)=0x20)
r1 = dup(r0)
fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
socket(0x18, 0x3, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r3 = socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(r3, 0xc0206921, &(0x7f00000001c0))
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r4, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x81}, {0x4c}, {0x16}]})
write(r4, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xfef3)
r5 = socket(0x2, 0x2, 0x0)
sysctl$hw(&(0x7f0000000000)={0x4, 0x1f}, 0x3, 0x0, 0x0, 0x0, 0x2)
sysctl$vfs_nfs(&(0x7f0000000000), 0x7, &(0x7f00000025c0), 0x0, 0x0, 0xffffffffffffff2d)
dup2(r3, r2)
r6 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000280), 0x1, 0x0)
ioctl$WSKBDIO_SETBACKLIGHT(r6, 0x800c5712, &(0x7f0000000040))
ioctl$FIONREAD(r5, 0x80206919, &(0x7f00000001c0))
r7 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r7, 0x8020690c, &(0x7f00000001c0))
open(&(0x7f0000000180)='./file0\x00', 0x80000000000206, 0x0)


r0 = socket(0x11, 0x3, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x8014695a, &(0x7f00000001c0))
setsockopt(r0, 0x11, 0x3, &(0x7f0000000340)="02000000", 0x4)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
kqueue()
kevent(0xffffffffffffffff, 0x0, 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x2, 0x0)
sysctl$vm(&(0x7f0000000140), 0x2, 0x0, 0x0, 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x58})
r3 = syz_open_pts()
close(r3)
syz_open_pts()
writev(r3, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0xc0185603, &(0x7f0000000500)={0xe9, 0x0, &(0x7f0000000400)=""/233})
ioctl$FIONREAD(r2, 0x80206919, &(0x7f00000001c0))
ioctl$VMM_IOC_RESETCPU(0xffffffffffffff9c, 0x82405605, &(0x7f0000000100)={0x0, 0x0, {[0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6], [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1ff, 0x0, 0x2], [], [], [{}, {}, {}, {0x0, 0x0, 0x0, 0x1000000000000}, {}, {}, {0x0, 0x0, 0x5}]}})
sysctl$net_inet_tcp(&(0x7f0000000080)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f00000000c0)="9b1809c3dd7d3f81670e53473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6fd74c94d1b44", &(0x7f0000000040)=0xfff9, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000300)={0x2, &(0x7f0000000000)=[{0x50}, {}]})
open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
r1 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x144, r1)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r2 = open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
sysctl$net_inet_carp(&(0x7f0000000040)={0x4, 0x2, 0x6}, 0x4, 0x0, 0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000000029, 0x0, &(0x7f0000000000), 0x0)
getpid()
utimensat(0xffffffffffffffff, 0x0, &(0x7f0000000100), 0x0)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x3, 0x10, r2, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f0000000540)={0x0}, 0x10, 0x801, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x14}, 0x4, 0x0, 0x0, &(0x7f00000010c0), 0x4)


semop(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x28, 0x0, 0x1}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})


sysctl$kern(&(0x7f0000000000)={0x1, 0x26}, 0x2, &(0x7f0000000040), 0x0, 0x0, 0x0)
r0 = socket$unix(0x1, 0x2, 0x0)
setsockopt(r0, 0x6, 0x40004, &(0x7f0000000100), 0x53)
r1 = semget$private(0x0, 0x3, 0x0)
semctl$GETVAL(r1, 0x0, 0x5, &(0x7f00000000c0)=""/268)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000080)={<r2=>0x0, <r3=>0x0}, 0xfffffffffffffe58)
r4 = msgget$private(0x0, 0x0)
ioctl$TIOCSTOP(0xffffffffffffffff, 0x2000746f)
writev(0xffffffffffffffff, 0x0, 0x0)
r5 = socket$unix(0x1, 0x2, 0x0)
writev(0xffffffffffffffff, &(0x7f00000001c0)=[{&(0x7f0000000180)="b1", 0x1}], 0x1)
mmap(&(0x7f0000000000/0x4000)=nil, 0x4000, 0x1, 0x4011, r5, 0xfffffffffffffffd)
ioctl$FIONREAD(r5, 0x80206979, &(0x7f0000000000))
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
sysctl$kern(&(0x7f0000002240), 0x2, 0x0, 0x0, 0x0, 0x0)
ioctl$FIOSETOWN(0xffffffffffffffff, 0x8004667c, 0x0)
close(0xffffffffffffffff)
msgrcv(r4, 0x0, 0x0, 0x2, 0x0)
semget(0x3, 0x4, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
socket(0x18, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc038694e, 0x0)
setuid(0xee01)
r6 = socket(0x0, 0xe006, 0x2d)
ioctl$FIONREAD(r6, 0x8020699b, &(0x7f00000001c0))
setsockopt$sock_cred(r5, 0xffff, 0x1022, &(0x7f0000000340)={r2, r3}, 0xc)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
sendto$unix(r5, &(0x7f0000000200)="a77b4c7e82248b7ea53ba5918a69ef5bcfdadc3bbb2f3edeab504d69227101a6a5752769a29f46428c5231f1bf6e84afcad6543d4e7a06cd4d79521669c0089027dea57788c6aa15604cffb8d09551c4728969bc33c551310d644a9e47dae9c356136ab18b2db09edc8ca359f4d52e3d0bb5b85ef99beeae4940961c9da4edf1a99e75bf1c7932f923b6ea6f816c629558b5384bd1f9c5ee97c86b1e185841abeb603d8bc2b160c67d967744d838581d06f0c4974473bce0fbf6d21d03226bc2c4da09c36efe9b23400fb565e3f022a9721c5060dd2a", 0xd6, 0xa, &(0x7f0000000300)=@file={0x1, './file0\x00'}, 0xa)
getgid()
msgctl$IPC_SET(r4, 0x1, 0x0)


ioctl$PCIOCWRITE(0xffffffffffffffff, 0xc00c7007, &(0x7f0000000000))
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x20000000000001ff, &(0x7f0000000080)})


semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
socketpair$unix(0x1, 0x1, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000080)=[{}, {}, {0x8106}]})
r0 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socket(0x800000018, 0x1, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
r1 = socket(0x800000018, 0x1, 0x0)
ioctl$PCIOCGETROM(0xffffffffffffffff, 0xc0107005, &(0x7f0000000080)={{}, 0x0, &(0x7f0000000040)})
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x800008, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000000), 0x2, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x2, &(0x7f0000000040)=[{0x20, 0x0, 0x3, 0x6}, {0x9, 0x6, 0x1f, 0x7f}]})
r1 = dup2(r0, r0)
ioctl$BIOCSDIRFILT(r1, 0x8004427d, &(0x7f00000000c0)=0xffffffff)
sysctl$hw(&(0x7f0000000100), 0x2, &(0x7f0000000140)="5ae981844fe8ba978e5e1b5858ed5da84609bf748050df04e048568b965001332e8db647bb5ee8cc659ae2ba3386766ba1be30788f4b3e6b9ffd2a8258c42f8c47c85352aeea3983d79367e2c1a2958bf2eded92262cbda534a6dbf4b91a6b4665b41f045fd0862ea39797965d626653d78d42f86fa2c29fc77e306a34fead04d03814d94955631129d76b0092809dc1eda390d2a193a28386129c7fa811dd6855e8625b2fd7a21f376ae41e6f6671ca72beafc0b910ea7911392079d58815518b72dca4b5e7be264aeff0126051e09a2ba95d52ca458e54cf4bc33bdfcc31ae4497ff98c7c1ade76cd7e8206d28fc31d77b203ffcc16b68f15776395b340bcdb1112a0aa0e857dbf6a7a57a56a2bcc51fb06c5af5ee5baacbef5180dac347b756d231625c50456a6df26d4e48bc1533d520866ca4491ea5551baa35dcbb1509892e1b1e0d3ad7c2be08e247feb1290acc6685d01202883f66974e408472ff438af8d4a2c02b3dbccda497323b4c0e686c4d651b6086032df33ad22225a0974e897efc49a799d9367f0841d3af644e1fa4564e44479e0edfc6fb57a4bc7ce057053865eced1c331c74e82529d8a864a8570aeaf3e454a345d11eefcd7ce66835a9d428b56a0e25f2bc0285a82e7e8c27df6223f746a91fef2a196946ff40ff4e3e2b3baffebcc760c3dc10ce91a60febda30b4a57360ceff6a6bec5dad9de731c3348da8475f55333987ff81c7c3b8537ea55a6c7943fb47843b6af781c97c8b5f0596b6d17f50f251faf568ee1f2433f24292a0e2e2376071feb656a7d0895e7c09a3af655e51f240bf62d20c3bfc9fb6f444128994bcd016d485b809052884f34eebd5b9cd9a179e82efa72ee11b464c4a6d55f3a02f1e0423302d833c7f3df52395207a495368c8d5f505a99b0c380cbaf78c94e6057833aa8a9a98dff195e7f7a9fd2f8022e6722ede19475108d344f2ca8b18abc167c34fddde4443eeca5d770f49c46b8346dd69b54c30e3393fc2eccd98572caded70ed6cbaa6db835c60f33c6d4ca9bb49c6951afcc79c01ecf1cefedd43a03f4e735f5bb9e06e0e65d43d8ce47c168006694e8a5bc41e6759ef73f546b931d9676d5a01d50adc1444c65a490f53376a4636754ecb496164a835bc5860fc60d3203e1536d43420ce69caf1db5a6290c9a4385a1f247fa40161da9c48a071d0c64349b7f8bd071708aeb0e1fee4fae070b377bc4edc5bc5ca483560a8e1c314776606f003ca6a759971197dacc9a5380b9c10727279ea996f555d7b90396a98eea983730bd2c1bea4956728d804c66ca8c38016f2894bc2e9befc6dc8bc00b7c0897dc16f628c479593cb19958bb756678f0c5a82182b52ac5b18c29270d0c8987781af8cdaedc731c3bdbf36753131632df5b2c11c1ef5fa27b3ae37830b5a8882451e3ad779a8f3072556baebf976bdb3369989336145176670be317039205b5125591b07412c54112e17285f54df239569f20230549704f3a7e95190b97327955fa0bc4e0b49afa3d3716c571dc3c097fc4ee4c87a430ba8997f974fbb318f331024b7ccc166d5c59567458fffc704ffca4938bf80bf6a87530a4d7828f628f4efe2b4d0a6d7512a4dcb167a601407c861fb58f1e98ea98cb4ab1e8eabdc997d9bc6c81a4974f7ec5f002bf597bb8a2e68e546170ebe5d5b89ab3a6299833cbf9706cffb8e7447dc0ce84281899ace5e0b6c689d44a88de1de396e882ce6746bb23c880555ab8fa17eade30db92430614d76b53575f9ff3d7eb54bcb5b36a996d8804d59fb108be21f5cac66042e41fbb123378229827b38f9f0e2d396bbdd81031478ce77500f74dd7f08f6dbbc6638bbdaa54bea7a6c16fefbb0808c02cc9483d6ada90bd7f464e7e3569d3975bded2b7a9c83ea0d36a171d24eaff85c1233f75808c53689a9dfe6256314653b38f8819b7f7ceb29bfc4388baefec1d82e7159cc1e439c950430e19d1aa1af933c5f6a3daefe310b7f86e7a62c13da343545de98d08d12b7f7737e8f06811e7481d1d7baea47be4bd5d288a7a09cc55dfed4e561a34d2e176d0e3d889034420936b47ce6e22ac159bc7c3db5c905950000d44f0e37d213de19a65f8a0213c0388384dd25b6739fc501ed1c0ee64da5a8cdb4d5584976f41a8f666556ba123703f92aacca09981ce4ce874fe718ac1ec4b7bebd2086c4c9be1547518f7c9929fd4ae9dc852ca32024ab283670f0d8be7433e7e848b493121b3e2ad53470e1b1ef30c14744f2cc9e06ffa7131f6762f8c2f8020b6651152bde145bf72cbd4826b51049cc808c690a4def199d17969c34c18d5d519da2c0a83f3aeddc60ea02dde56e98645cfc72daa189ab1a332dd415d7289cff268bba47e1ae53f753fd49d79bcb3294c2604ad11d6091f215dfc2b3aea892f58f87acad94106b3ace37a064ca5dc91d1e21230d999ec1198b00b92b6afe259631b6880212840a47532f2a1a9cc962d0a7002061bc6ace527e19aef05ab51e4ba63f00e797b160ed48037e082fd636991b705735517619129fb9539573c391317bc6980d63c1da709169a146ec23c32b25becb6c57a0f480c017a9809d69fd26658b824fb0c529d5197da9fdeed6805e9d7e2a8d1258bcdf21ffcb185b850941949eeedc29e91f04bf866c9039bda92643e87b97a6160e4cd9ff54030437135d454e04b91ac1cd99a60d72599afa4938f7e98c3b145639e88ce17605aa7af16f1105084acf06718e70d1674ad2c454179ba976c77d821f254603f5a6e9cec28a9c8796d47afd47b6562944fdeba62a2d750b72d56d5948f6e8cdf978933bb7953c62bdb911ca805f332cb04c67ca6963452fe79382996bb074670a5f4fe2a7faa03512d85830e85e59003822712b8dd936eefe4bbd693a088ee4c9db0703bc973c699e6ea260b3a1a2d4fb5dcb27407714a687f1c9e0fe8f3a97fea147c172d262f8d1a986fe007e82d3d8e103224722ddd82b47509de238bc672252caa2abd9a81472441c79bd12993336cf128632d44a2dbad2aab138061c6ba43047f87acaac08b239aded689dc87328524eee13998ae86f286542f83e897fcce68c82e291ec8afca7793e2b6d596e9265356bc13562dda40f49761990f6d2ca2942d4d0ba68b0d554dcd97a4ce38e2aabb6329b43170692e4c3939b5e4df25d068b49f8c7cf36b3b2105b36a9e0ebaadfe72ca01391ae3c5f42bce4b38d0841877504c98feeff77c942d690bfaebd3ea52a82766a5aeb073039e923fe3d1bb3e6cb03211c60e29c925c28a408402e499339d021dbb96076380c64793ea25bff665cf1be712d9da89a75d32852bf65b29b6baa911ad283598e1354517e9730c33297226ded61ddc0c2f9b18b2a3b3a6f5228013cc749ff49c4bb358b5dccedc8aa92a3b7ae9ae33a1e938522ca70beb291540a24a08977750adaa16e28b572f3c5bb4b1578250c3820ed8e1812bb337cbbbd0de17f0f16180e00351e4c6d2487edeb3ead55d350bacef8687ad917626304e7ecfb14a3e4477b6beb25544b38922ee3ca8fe0921bc0aca6912c416cbf4bf800d481f0b05b71c8084944c38a57f05559d99cb11999f90c65b34b5585f452144cc91b643865c7f44b62fbd6c2a4642774ed0c13f1f1bf812d80a0792782199e8df5319627d3b709eba41e8dd53aa7dccff0655d3d771988028cc3ac6b52a76631c55403a114302b33e1849cb9c9c4027d13a43150e55cb2befcb2ab7ed053355e24fca4db5f297d2c33b91a0f05167656e5997930e86dec246ed72e31c84b94d1d31acb5422d403fe91155c616e60fa52c7dc86995a21fb09da1ff0fc8e53f7e7026ef251505489bed0c6d579de85475e69e78993825b3488be48b780a4f399741e12f8838e236580306f9744bb93aafc62b7a81d551ef469d488eec7738ae01df66419c9024325ef9fcfb6c038a5d87be3666e7bac03eb0734b69d311dbd26c01a0ffe8fbda842827e444228501e94e91d8484140db9a3cec5aedf65ed501a5a0f30231984d58315c8dfed6b8588a5e886bc00cddb85c764224eff7880198f086f04f70c7ad65c45e74050b5adda1d6afa54430218dd7301c3a0325af76fee84f47dfe1c5716959ce1fbefc632b61f397f405c8677f285a6d03bfa4858984f4677c152daa7207a519dad798a302fa7868f444768fdbc4ad627e3d4c1130acba4e3e1af0af3e835505a59b721c0c1eb1955f0cfd011124d3a49fa020fe931ae489a303088dd461669141b14a5494e863c2bccaddbbdadb6eaa2fadf55f74de8b5200240209260f895d7fd3e60ba39462c326f8a26022231b408b18be93df463e65c63758493bb0320268123c2b90aa8656e70e34f4a8ba0abfd575ba58b540681e43127685b89258ef419f917f81b33e5eaf0c23ed9317c1442094bacb77d89796a766d5c3fa48e11a9e5d85669d57268a5211d9005863b0f913dc64507c126e6865e8da8ca0c29d5fc9a63d7be1fe3dc90076ff0dcd943163d5a2371e0d143146a16682f3e81de2ac45d1034f0356840acd4ffc9f32f2306144a19cc3297606dda93e55c9928ef2b5bc39d9e851688de4915319566a5a7320305d88775f61f0f15f9cc2ff98f3f80f4630907265f8794e1146118f6ca6a8540424dddf0de205a56f721cfb0c1ab48fffe5c4eb5f29faf92a79c9b418e69d3b5c8f9ccb4b121499a25c0db7a8be1017bdd2b6a6e8452cccde6f6f7e0c743c269dd01c8b6527fc77866f37173af0bd11b949c1738365068388c4f7d8650f3f917e3e16ca2d9392a4a04bac482ff201be3f9ca845290f86ce0d8f11a5f2aacc3c84617f51390968c77a4b1da394809b953d36616639caa446a0a739b616edbef83dc005027d97af30cb421f3c65fef0cf52bc6a8fa85b9c9d16be344b506e60078c4d6914d7f3ed744a3e0799f4f750b4764ffc6a64f025ac21d95fd3a0c29b3cc8d1e940d749a7d5b483189abfc42882df3cc0a3e942f9f50728044227e350fbbeeac62a076a6fe5533ee0839701b0832bacc7d0c9764af9e9e5f1f8bfb98d32cd4c070598096839042b28f8476dec42c6ceab98e9fcb76396af5d2eec7c62afc7ded149b1dccecfcfe6ed43ef63158dd7e824b163d8faa932542b11e299aaeccfbea946420ec716b79ace1dd7ee6cbf656439ba6e8056b99d42abce7b4b329cd6fe20778b57755cf555d84d5634bd244eb08d000bcf604fd5af3fb66daf40711ae79f26a691d8f769272ce2486fdcf097cf4f86c5bbf64e4cff3fb244273321540d77e2683ff24403ec722e944178fe5511a4066bfe8e3f96234e500da5f06490ea90787cd3588b84fc5600a63e1264e2f65dcb4f1502b85ca380d62ef1280e35065addb82a89ab5b9a2bfc500a9fa6dcc239d9708b752d354fde2385d772f524b86ff156c053e4384faf9487b27f397c9734686e15fe098c2d718352ba8e1ca05f460afadafe1700599ee612d47ba8e0585137423b1ae015d17659fa97b729a2a5b73293697e5a1b5f5f272ca729aad28499f8604d07e190714ed6f47529b94ef23f84dc7319f9059b0a448c8b52e06f8d9518ccb81443bc64d3d4c1925b4b046b4be227f836e6bf0cc67ab72ac0f9baec6b228bbd2561bc50ff91f178014b2eae996d2a58509689e9476fa455e572be0c52a0e1ff0dffc3158274d9507dfd6fc472ed0fc4c6087aa3c6d2e0a94b3daaf240da33211a0922bea27cee65365034f7f8db62ee45ddfa6befe6c52fb07aba9f95f32954c7a0599fe57c5ac0022be43", &(0x7f0000001140)=0x1000, &(0x7f0000001180)="e0fbf5b3ce9c31ad69bf9451122c4e17c6c75cd8823406722ff381b55e81bb205ebb28c94b831577b4d5d5961033f4df4dff53f14abc6d973c03a93b68258a1a2206e1ef6650d5bab1ae2c67a8670a8de6368401d581ed0a9d9f6e6d98a3201d8760c0cb9698644e0b7e087ea9b197183e6a09862b9e6b0ef3b1acf40d756e58b77e43aa9b8b347d7103333391cafbb12a1794ada1ea904521780a86422ad3142d3ecfc8a7ed7805e3766bf6868f7ed7111ede925b7c2aae6e2bc60ee83ee08674c0355ab62e8b98684bcbdfcc48eac60149ba7ba6a3", 0xd6)
ioctl$FIONREAD(r0, 0x4004667f, &(0x7f0000001280))
setsockopt$sock_int(r1, 0xffff, 0x800, &(0x7f00000012c0)=0x7fff, 0x4)
ioctl$FIONREAD(r0, 0x4004667f, &(0x7f0000001300))
r2 = accept(r0, &(0x7f0000001340)=@un=@file={0x0, ""/81}, &(0x7f00000013c0)=0x53)
mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000, 0x0, 0x2012, r2, 0x2)
shmget$private(0x0, 0x3000, 0x64, &(0x7f0000ffd000/0x3000)=nil)
r3 = msgget(0x1, 0x20c)
msgctl$IPC_STAT(r3, 0x2, &(0x7f0000001400)=""/212)
ioctl$BIOCVERSION(r0, 0x40044271, &(0x7f0000001500))
r4 = dup2(r1, r0)
ioctl$BIOCFLUSH(r4, 0x20004268)
ioctl$VMM_IOC_INFO(r0, 0xc0185603, &(0x7f0000001640)={0xcb, 0x0, &(0x7f0000001540)=""/203})
r5 = semget$private(0x0, 0x0, 0x20)
semctl$IPC_RMID(r5, 0x0, 0x0)
r6 = accept(r0, 0x0, &(0x7f0000001680))
write(r6, &(0x7f00000016c0)="4645e4b51634caa077668eeed357af77a1788e37a444dfdc75249f5f740962cab08782980248b14d18927f9defc76e356c3a87e25116f431ad542805c94a4918dd4d42fe1a272ee06847ca8d19916e7ffb67c2499c289f37aff10ead373fd410b6be11f30a7da3bd12e3bb0753c17d6541849a97c7d80c448d61f24bfccc0b2532ab01490773eb4d9bcca273484156692b8a445f44006d2fa3411f99768102177e9cb74d76bcbd3950ed2e3df5d60f3d63a8287b034c170c7e550cdfb5d49ad728023db3018f2b087eeac7636f40e33a25e96f1bf94378e2056c9430d339ac474da0ba5fe22408b772be2057929cba26e8a843abe5f5e65e1c74d6f5b148e7c91bcea20b8d1e53a24e3c39f746e7b6035411dc7d1a654049a9f6104086eb951a8128a42da2b2389188693114cecdc1e10e5a220ecc7fb9b4804b234a99a0f285c919dc727397376c3c339753d8de7787e8a5f42f761f0aa54b5ece5a0bf1a28c5d8dc33e734a97cbfdbdda4c8dbdb3944511743f7fa2e5ef89f1b003f11ac2c720bc2a3ee0e9e9b2a6e10281c2be8e935737a610f8d229482e93148f5bbdd41f97ff2c27a025847e7726693e7da83b8fd04b599fe954f8a4ac2970f26efb90e99b8d42f7f39400c9dabcaea6da3a741aed4a3bcb4ce928a92b647cdad57b8cc7c086c11d8d213b10083fb080e671b2af004251ca1cf9b6b1873f962086d40aaf80c779e25932dfe959cfdb93c9c11410849ac9c007a21b880b30f0587cc6e4d527ecf5a841269515cda6d46a9fcde5448b259c31f8567bba48ba71b3adeed57abd686a5d437d6fc6e20ef1de4b2c38be5253b9f0277676050d905961827b72becdcc5b0b6340c0810cda4ca1b1bb684405ecc4678353270df09c1d4f56f088641bc8a9768730f0fd81098f9fcb5f4f2f01a79e7c54d41b9707cfe6cccc0cd66ce09a36c03826b39190f9202e20c93ccf865948c84f405c347085d4a07e51b8f24de13e631c8d120b876830c4b3eb60d16d36250ad0ffd98d2acc08aa73e55fa7c6ef94423e3836c475ced8c51c2ce5b85105e6051efb50df5128d92602e889314bb890c886da32069eb57d8cf795116e58a9437c2e713f5e3f65af916864983d12c24eca5033aa9a72d39460985f010abe9608efecba099b8262d7a8a34b1432e545857f56000dee78681204506714be2201144f5229dc8c3bb904a32632f5548df55e460f7b19c54146889f48387fc6cfaa4a7570a38969781c1ad38d46d5e96caa19671abbe4b07622b1eb1d18d196bf3ed776f641e47049a5532940bde51948de1a12138c4157ca9e22beab4494be11d4c9ace042ccfeef5e532c1fc3569a5d4a97bc13e70c5af24ad2625d32e6fe03c120be06017c9bfc376b22de76b2808d987406f4b9b1806f2d4dca680179b7de6cff8c15678164578a5d3382f14b7db77d2c862aa379c805ba6757ce3e77597ca5577a1d7f7edf300fa8ec87877eadfb9ba036112e3a191bed0b89cbdd7f86874e8d9bb378ddd6ffefae69db2526c2917fb4961028ca12da33e2bd1a56fa15753710a1780db2942e0f8998d85a1795859ce36e823113355c174dce643b427aef56b566e92b0325f6329f04662c0da6b3c5528c9c06b957104c86b9a1728b600e09db12bd96762d6ae8d65edaf2928eff299b1af36608c77f3b839e55787c376c02cf41898a914ee823ffa43a1d02618b6ddf2deda0c4d8d83c0005e788075c8721b11a0f3bf4fdf70f992952e59602c7ad38a7eef6fffea58cd736822ea5b4282c15c9db0f51b94f55fa1ad73f6e5951152d38b3c8f8115e78b87efdbfc0d2d600467cc787d8e94ed95be5a88730c53abb087407308a054760d35cd8e858ece321a57035eabc65e523977f6f2b8445751c91ccd3e93c52a4d7b5ca96c1dd78c77785d39161071b3ab459e5a6a38746cd0600977baa14504aac9c802deac8703ec91811dfc290529a0ba9b533fc78553c3d20069a94c576f98a9238646737cc3dbbb53f46a5a13cb9e7f52a05b5a571a694883213cb84ef967ced26c6eeb0b58f1379ee44cff3438084dea9d14bcd092dcb49dfbca24fd39571c347dcb9e4d20bd5e250d1770a3cf5f30f8d4cbd727406a189ccd6f4eb6b1fa8fbb641237c55409e232fe9d36748a3f9b517f46747ee93423e29551c671b577114a55e6bfd7f2e1bc20d7a7fc7e870b2a4d841535a1d1d6ebc5a63d4e1ca34203cb9178e8634875b790e7584cb873db283b1d28b68e6855728992ae76a2b9333ee0080e9e262b275a8a633544e94dd020a37bbe23e94f5f3feb0760b2a0dd6a10b28231dfd04ec25801d16f98a4460f2982308ab97c40bdf00293f1adbab3fa6957492b28200a3c9d8d47e776ac466a7f46e5d8a29c84cf252c66711b77c6f9ca40f8000cb1aa8b7350040c560b3ff2014c681dd8336517281fc1f58044f5bcd5342e414c5bc5fe331320ac0c8460634752974ea6098975e617e568bce1b897badb000d71e817de2b346624c225654f507d5a9d3b27b7fdcb91796f19ae78326970b90719fb3f06384c7b3e66b503f57164ec360cc89ec0e48afae3f58a02470b78c6048b0e13fce88cc9558d1d8dace498e9fad904ee1bf0367057582711314e905e0783f91129a2003a87ba0b9808d4dc53fef433378e0ad5b6f2c66ad0c958008f77cb514943c6fc6374ef578e73286b4b054e337bff499884da1ffd1a5334f700c60987be6b0503614fb80c1ced725049f16f8f71c3595acbebbca0f9c1b728a2f3a02f140d1c5e3276f2df231c9814bb308479920a84eb1ab5416aa5f9ba042b04a4ec1ff698461beb0aa9f5b0483863e5d6902f980e9ccc6d036c1d0986dd991acb69d544d9ea824f7c787027fa6b266a549c5150614c612e73cb9d3411ccdc45988428ef8cafee689341b6b61d069575d7acc7e3942416a03ba01c1029ff208a832d85ecf5e1926b97c4d9334fe0449d2bdb682c89a5fc181c4f180d6848bb11b03d1ed04efec3a6cbe256ac82cdd6c2766d3d451c375201097f82b9533ac303c6e714e3aee27db3615d75fb16ec15c519ad2825196d39a1819299923eb9d4337886a9339030f0c19283d8428e521fb75471dd20e4a7b1e7e2714f5bdd7a6ee8279ab6dc4dbc9010d50a712a7532e6d6ecef8e43e823bee527c03933cf2a569b00c33bea0c665aa3599769df8bfa8ee480f59a10093c37b9a5bea46f0781639c15d0dcbd254684331959c69c506ca64ba750290a61306b9dc743623a78f26b331bff17c4a07558c729a3bd9e8079dab478fd9b510f4ea56ebd88fe9bfa4b57d1d19dab0b06c4c013349c036372c14dc6840ca37c04eb4a5f4d405c941e5fedb68533a98360ffdace3d718e787ac2e5e649682ada71b85ddd553414c02d4bd4e0bda57365819775c8b60d65041e4f70cfdc65b7f97e99d6733d63948173dce0a0c33d9a10b1d2c2c6cf0f3f7e3b18b4bd485692996a108848e8b3c516d2dc59a3b065ab8f312f3f7be38a8a24382169531b6f18b1a204bf667ba5c3d92af4aab228363355404b98ae3ca64361af0a2f94ce8cc2858291406aa073ea9ec68cb0986c3f50af136a7bffc5b2ac26bf5182c32b97942617f13240e4131b8dc50360467abb5d455893b76e6cea5ffa5f2422ffacbe09acafbb2a9a21dfad7792ab8e7f9098f433971b29a018b33936c46e312e71f135b997d331d37f51958a311bdc193069517d66872ac6c7cd7856ff44ba3242d6840adfd21e4e89daa5a03557087e7a6257a78a5020e11f0bfa31d6b2b1ac9d859907999847a178d22d9f034eca03fd6252bddb11056e3806a6e461b87a1c7c2b6a13b6bdeadf05d71c97c6e63a64ea5736e1982dc7543b4f5057e4a9aec000fdaac7c6932038eb7643dd6efb35304a2042c7942fb810b3f190dab540b9c45f405b4cb289fd2a30d638722b834da82b67b062b67352e2fe78b678f0e644051a49604546c5426e61051e79912e39aa6dd263d1e2a802074b554d80b0abda4d36090f45790788df2ea61e2f24a5bf23c2e8981612fa6e84218bbf296221801f653aa8fd7fded4df6ecd1240c837fa470f4ebe6af02c064b2d45ede5f6d75783696963b2bdc224e20a3a07e1495a77d6316a9b3470289947e24769362a100b717c15b356f62fceee7a1da7f48d3e84834a3890afcc69bb7c3d7c35905041055e1090ee5799256052be949ab5345f7eff4025becb03917c2840945f975aacdc73dd0531a8a9e5fb1c98401f7d93b99a6c7574533c5f3c5be646407a521cdfbb11a60229c1516a92e584587304b7a5e17cf1e9511d2f8540cc396044639ad030860ece011a734ecc4b96b39f99554a8a047ab5c89164863135f8eb2946ab0a714519869405d6921e8dad0f3e68756b5df273795e5f9101b5c5757207bd29544a7da0856e1aa753651f081c2a85b622c9fc5ec5d9bc67ebce9a820ae3c1925afb25de9374c65c326cea6e48c3b2e9672dd24ec6becc56652081cc6a3457056c5a24843b173affaac2bb278fbf0be1b88f9c0a70495a622fdfe791b3547c52be6cf6747fe22872fe3d3addd30676ac2c5a45c7621e44eec3fc381026eb89f9fe81c1c5d4308ead21d005f2f64484ee532b46d624bcbc08dad71a289281f630456627f21e8bfcd496edd4b863ef8d90e6e3b873f8c004d266d8dafc3b3ce4bd21b26da85c0d17db0a5456a356081b59c5451add35af99484a92f78af70b8442f41a9af2257d9f3494bf2cac3cc88831e04acb755c4e38259eb2c27f4de9e3b93f2fad42deb610d99e3be6abbdf4334066fc75d560f8149dfa466387ce851b7bfa27d435cf1b2081aa5a3fafa08484ffcc0569083275677e5e39a84fabc9845ec3b463eb4e0c27c3df445f37ea89590cc4901d0d2c412a355e3ef446e6b9212d71d7f4c6a36db92936ff3eb4a3f42ca45cf56c4522dae25489495a80cbc90d5e03afc3af3b14cc1713a5f662281824e471d4c32c5108b0b73679c24d6c3c6e94f9d4975c997ba2ebc7b94137d0870f24c4c8a06082be585680131b40fdf43fdea634f4596250592a42b9876f96f071442c10f293672710b94732a4faf2ed52b8264912201ede597f43673b47aa74af3ddd50801f5551dcdb907b057d269ed567fcf1e0cd9f2dafa2c874372af2529189aaac2196a3fbd5962a5a6546e0218f0370fcfb33d67b6b635a35ed272757da6605fea29a0e608fa6c2e0532ac8e72f9f61111eff9c485bf98cdbe6b77e144eefbcc627dd39adad2979a4c9c13fa7b2ad573240926b36e88daa7d4700616c6f43f76e36caa06fd5a4f7d1813998758677af72d3ffc9f93714b173b7a3447eb2647be5fe8a5df76b3137957260967f1d813e9668fe339c086b79f191520c681e272485df07a5e3edc2cbbf4b049c4cd9bd81cb4d2052bb314683cae0fe4764a06c38ebfc5667a74f1d267ac9be4b20fa7fd5ede6d6d3f5d432895d35ab3f77dbb5e36d2f46dcdae724566d9fcdd990a4e4a405429eab423663b96533695ca43fcc4ba575e99d9400067b93707257e71fc34c08548d93cbc6effa80fdbb5f0b7b54489bca30e37fc3b5f651c0d422ab9ade7090f0c807ad951465ef8c9fe351291fea3c867b3dd46deaac5f5b24a161cd7e0f6a0906935a873b65604077c562e82999cd17a18a8fc4e2c40df505958ce8697bcba3f5e5d0f1700f277121be2d65528d088b16752167855e69b3636cc8cd7618efc14c9675bb4a7596cd5ce9ff8be2214ba3854f6dd166aa6e48880b2d858fff295c82756", 0x1000)
getpid()
ioctl$VNDIOCCLR(r0, 0x80384601, &(0x7f0000002740)={&(0x7f00000026c0)='./file0\x00', 0x0, &(0x7f0000002700)='./file0\x00', 0x8})
getuid()
madvise(&(0x7f0000ffd000/0x2000)=nil, 0x2000, 0x3)
getsockopt$sock_int(r2, 0xffff, 0x80, &(0x7f0000002780), &(0x7f00000027c0)=0x4)
ktrace(&(0x7f0000002800)='./file0\x00', 0x2, 0x0, 0xffffffffffffffff)
getsockopt$SO_PEERCRED(r6, 0xffff, 0x1022, &(0x7f0000002840)={<r7=>0x0}, 0xc)
wait4(r7, 0x0, 0x8, 0x0)
sysctl$hw(&(0x7f0000002880)={0x6, 0x5}, 0x2, &(0x7f00000028c0)="4b4751e229f7be0a8b1c3919d6acbe91f3cef071d31997b58d1d9782f00b04629d479259f7b6cb32ec8c92601cb0a2598ed77366ee37a5d7742fb782a20f0bd0278e0a185cab730994476591694f0fe2cf5e32f28a1251c5d7fe2ee681e55b2566587c45052424a18edbcd663abf8275ec11af46135113177bbb88a4c40bd0aea33af34ef3f680cf49c9ce32461ee1ecc37eb7bd3e17eb9f46a718cee35e40cf24b1404f633340c748f3080a986edca693269b12e4781902b79b93e9a0a86e91ed674f5e8358d7360e3f14402bd975dd3e7f0270c5d9da6f9e5c5315b69827fbca042826e28ac31ad3ea64734fa64c8708e3a1c8177d2fd961de8bbc1fd96668f7903e4cd89c13e385d48f139bb157fa178f70e6b584abb687467a6fecca198b3f6513574acff730c0db67d7d71af5b886048328ac2d4b9675e8504db87b497c998e3f2c9df65d234870637808ebe9488c958eb328386063c0498cef4e0d5d46de0abe970e98557b7e85e637f58e66d5ffb89eda3ece2359b31fd9702fa1735fbccbbc743bc69c2a34529b7e445474055617f04a53fb72d7fecb636a03c0378ae911abf89c8e71436dcd3fd48922bd9dde3cb133c7754f229e9d1bd89249d62fbc0c7b82ae1aafe68f8ffc21e5b471d5eda20ea8cb5926762fcc6129fa642d6bbb54e9a9554d598d48f65c46aa7fc07dec9d4f47cc22794ea8e655935456a700d8048ca0add249a4248c1f4a85d1501aa4dcbd7019a7b87ae4dc98d9a4402f5045e83a34a05ea12597549f221c88574187aa53eed1a0d445bc17773c1e3470c4f2126df0730f44245ea347644da6fee8e97eba405cce6c8ab6fc2da762c3a53490de78b7abe642eb7ffa63629b0c9e5015cf7c92b1a54de2991507d742f9f1041d911195910a010fe54680f620d1fb01372f31abace19e1059ebd43e8e50249c9461304cf5c604061e645ccdba13a207e81c03360bee5349429bb3c0bae44823f55a82b758eb16ddfe6c04559814bfc2406c528fd4c2322aa11733c02cb662150fe1f0029f4c286f40fdfea848dc50f0e9731127c140eca03560c53fa5eb4ee42e2dedb37a0deac242b0f1ee0231fd3a2773177118c6d4003fb876c0f3f3633e81f33b40c8f1ddc7b9f91cc3b2191e6ed04759ff0e7bce4082eb6956ba43832246afd0367894baa72f218bc7e36bbc78a794db846da2e8a602e960663eb30ef67828ca92dc6fb1f25e450fc959babebdc400c52d3c569cca32f96a502db597ddb62926c661a8d60ebe01eddff138b27708a0b9bec3dca077f7369339716a4d9590765ccfa10904e680bd63dd297899b13122145885552ac550ab53aada175a8112a7b412ce616ad2ce28d2a84f21ba47dc9435c0867b45cafdd7dc34f70c747b8efde18e5570ec677c3d967815a1bbb92c002b44fd1123263ba368026880663a02946caeb63283596d74354f6262882c20e060b428c92f88605e898338d860ba46a3f6c58bc7ad638f3cd95b7464c951e0909c0799ef680d941b221727df85d9c2baf1ae4d68091636de3114d57ac070bf95f79d58f2e3628e85b4df1e8a6b947d34348856b7470d322234e5388fceb2d33598e43995e995cef71eb409890b04a6fe34668cdd7b341ed21b86d884f61e870a17f76636ee9325363e0b1361fca58975912dce0800fe1b3f9be0df705237134ab6b89e0e93bae3ae65c6a0cfad2990a9dabf3ec741a9bfb40deeb678686f508e3965b81c4404e8d6ff15a24025d8d9ee2ac6ca888a2b117dcefd06f20dababbfa98d6ff3814653517b24c83a3d4f1a5c4d210a0218428a987022160b874f5605ca779d097cc6f42135f033ab857e87a298b89f3fa72df465b42298f79ba1269932ca87bef14e7bc3fd0611d77ad933d1923b53c25fa80a92c36bf378d06f4cd3e2b2ef39083e77fc1ed6ff235fef9dac4871aa43b425137f73b6101bc5930894a54c4f2bb787c5a8e327d89ccd4fa60e7661d5175da38eebbbd0ce27f7db4c00fe42e15a1dfd1f8828d6c95ca63dce5840908b21de1eb4b0fd2176cfdaa43965faffcfb7ae03e87ba6d994ee66ca5fdedc93284f00f200f378bf805f8d712955d71616db9273a329043ba44e561f9977559b0e8e2a0306d5b5f14d55b82e7993aceea26bff8262a4b73f6854889d21078f4a9774da0103b72ea59d62eb6f722fb4d27634c869edde434b3a708d9af60b1899d807dc4aeec7c98411eef36212bc631e34e50aa405d199ab2e0d73299f0728883b74266e8b113b13a8cd90a6d95e15904d77e99a4c73952ceb59b3d203b98298e5739376b2ac4b813888507fcffd61713bd9cb15839c03ac8e70d50b36fe5a3114fc8f47c49f04578ca2eeaedf42160f513e25f1bfb103e2b05301b9953dae4babea7154dc509cfe508acc66d2c5f598826f846ca369901cabe26358d96dee51b617c4e1261d60df6962a13a00f8c2162812e5cfe91fa881488c6333705ebb63f4910fb046beb0ddc09a6dde29b06ebbd2fd22503944e1c9534afa41a40bc07bf6a36a1bc2fd8596b0ba8b9be8d8c02d582a2ebeb0697dcf754a8b7c194deff39ab8de871efbcdfac4a3dfdd283070d0b61d0cc421eedd6bc537c6cc503c832ea6be101b22d3cfa09e3cb81ee94894977cbcba79bf0735044de51dab03267f1f9266ba7433bd95ab3873a90ad8ce301fa161398897e79d7f2cbe06d72268b600b1e307c07a37bf9ca32912fca569c9e2f0054b0a0ac1a5162f067b217f727e6ad2b0e62f84821df65b80c24e8d77ef9e85b329e850fa279c22b07a69131b379fdb379497eb171fa03770756ced7eba3d7c6e9e8a8a0944397c37b24748775a982e85b573baa4ef77a93f68af336ea19cbe118f2e386e95793967d83b366940faddb01bd601366557992dee33a79e0a9032a5a6529668d719851785ea7ac46be87c591d2fb22828fe2e02bcb5d1f06305ce2c2c81b1223671481ac379557dcc7f5fe0201299d6e02bc07d65405ffd2b2699a64173c0d91337f426d9da2678922b0c57bebe30eeadd36639558fdab8f8f6545bcfa8527608cf1bc50d9f15f06709277eac284f616bae6d1f2018948686eae6bc880d9213e3eda91753b103cdf104561673d71b46d54de3c0ad547f9502cbe2bb4b32a219af08500f52c6070f10d411192adb959c7b5f24722f4a66748d7279a74c1834efc3ae110d7cac6a48b0ce3a0bb662298e61d1dc6ae5918a5f87abd653777525bd87a0caabf9feece2ba4c872f656b7fd56de60405cdaa002c02c369611dbe3f9153113afd85c7a095f0c1a7f687cc70f748407c265186e23ddb94fa6228064e5baa718a92352c138c545796dddd72406100f70cb5f9ec29c3399e7c813159577aa03375babf094b207822c904c103704670c3f27fc2c2b3e6a5eb563b166e27aebd221df2b56edccaac93ae32e2eda31f70cc73fba336d086c11e263442cd172dcd31e634ec705518b52da9f7d8abe062b3812961363cf998656ec0118f33df514a2233016bb17bffb595329c307eef38c5e77cf9192b95382fb2364aa1c2c2321ca81e2a4a52b21d753e568168c650f38b67d823092215332aa0d38615c024cea590d7578b650408c9595bbd83fbf842b4e3208df98676dc803f00b118b665a6718f967e6ee0c637cbdefafef909d55f318a82b06973465bd36c30468111d5b431c4772e6e9afd3cd5091ab0d6e3ab3ed254b0f342689ab5291369250c16e1d5db395ee4f02f566abd164e97583290bdd23a6164ee66a855b0aac76f57586c4860f5da776a3c871fce2245746ac99650acec25d9a7865f40cf7abfdbb49410da91b8e73674f8b49c0520ff4647dca4f7588dae4b744c6d803e4ed3ea6a9885f39aa8a8033c5cb48cc471c57ecfc0218d24b05c8890466974f609f0014483f4f808e1ad8a992f1bfc415630e272f1242ee189c83e42dfd938075bfade8efada33e1347e2bd50def063781b7475e3106f91c895184ac0bfa06d4ab15a7ef2515a74b05f27354019686b191592b8cae53e1069502c6c8d55453aa458647172df8980d4398ff5cd4bbf7290d78e6a8aaa037850d2e5dc0f8f984e8ac5c9125fba033de9dffaaf12f4b5402b143cf918beb4ebbdf3f2c8ef05b592e27786c5598c3e3ce0d37e72c8ffb981758a14e3cc74fb589dc1c2cfd4d7962b3c9846d7ab82440c2377f5a05bb13b49866589d4df4f511d19d6ee0229ebced3b82a230a09e57442ace486e55bf6ce6a2075395eedadff5b78c286ac5ef435a781bacdcedf76edfb042a212f76d101607a43cd3efe8a264c57bdd51c06ab5dd1b688a72af891ef160c8beb4af98f78e66b152d3896e5d8eb50a96b467cea55575f893467b3d82511c4f8abd36270aaf9c07484525df5eda8fc8ff0c9ee939c538e7dbfbee4fe16f8a24bf4c197af3ca9200c6ee0d672183ffe567a1217207e598fd948ea6cd7945c75d64bac2c401c3de4469df8d1d3e5516fe2bf930670bcb9402625b86f7325cde515ead0d55282738282671752bf8f56e51bea15a73eacf05479e225f127c8079000b8ac6fb8a4f6cce795b5026f6f695722ac1c3a0703cc7018c65b32ecad14a30815e1079097a048919fb62305b2a7f8c3237d5fe151c906a77aaed5b233feb910492a74c0e127dbd8f16a583481bccd51c4a9957aee091c780f06700c2331dacb152497407bbfd1aaed14f5380777e0f1333001d1835dd3a9cbc6c0f62f7365d0ed2111c5b6ac73a7762079ccba60279d81b03a09b00b98d088dc819d866bb3c52993bbae67a1c68ca4eec127ec3f95263022cf2b3fa258ddf54e9e79b02b77e103cae11793f674f44f2bfadc695ce19e210c5bdcbd66ff3eb5905a2c48a5b08727ffac7edbd5ded2eef0ad9d839f2e017268362a8d26cbe6f3d9f6dc4053806501b75156a13dc7e2d46cdff49018ea85ecb83c07f72fbc8609e56f159d494941c1cf00ef572ee0ad11df19e7d85b0895c104f6cd237a17cf66f9326132a38b6735fc6d0972d7532b8b3713d10ac1b08be02df20afc2db022b0acfcac40a534c302205ac0c4646ea64cde55d1194d18b8dd4f00562423da04a4e70a698ab45c77d69f36d03bb3d30cf8a974b0519845ec8d4c25477d48573176459757c7be9a58bd08914b6a2a5f560f8756b7e9de2998d1304f09701e2a7db79d70b03df8bb806139b238019ab786069c34676510d4e32780b5467ee38fa96bf3042ffe3e559d61837cf6d67ddb7391039647c54525a151168338c26a438e81c3eeb49625eb22d30a1762c3bd233ad7da5c0f0c3eb9fa7728d7dfb0211710dd4144645115ff362218f84835db665a8edbb95466fd3bf8e4d83fcda89755066571424fb5bd70f37696577940b60c8ee6b9b8b1b827bf658cdd2b19f9d74135518c5edbe8aad269384fd69701b91545d7b30c5c1597c7e0ef3c276e9d348d34f17fcaf2e5cc452ea9e4efa8066cc579bad7fcbd1173877fe5268098a9325b4dabde6ba8af1ab88f16f21d066f491158abce8a190495005ef242837f5476a25e6c8f9379f9c4a93ebd7870bac951b91792acd588282ee9eeb0730b3595e534735cc78253eacaf1c21439467be2e29af5d9d5cfbe9015cbd74d9b8d3d026f5e644012a11ca3890a5f450cb4faea98e6f86d52ebdae42b5c2b55923547151c8b287976541c3a842fbdc568406bc62525564cd82dadc132a410327de5b5af251a1bfae8f801fa178463e881471b93777a33f7131ed5dee3cef35bacc0e4901cad0058dd85f915488cc11cee23c", &(0x7f00000038c0)=0x1000, &(0x7f0000003900)="5a22180fef4c330bf216447ddc6be4f1f2b46d899a55ee999afe02b7e8d7de1af041b67a35dfe621633a0b213121e3c2c72fd393f609ceabd7c523ff36ffc6de684bfaf766a5f9698ad08fd09341f6bd1f5a86adabe3958127f4d1347e3b31cef3cc260bcc7028d768dcdde94de93565e0e9d16504c8496c08df74336f968e23d2cd177d3fc20b77f0e3980b3b44a24014b713d977d2a7e88efdee6e76761c55dfba", 0xa2)


syz_emit_ethernet(0x2e, &(0x7f0000001140)=ANY=[@ANYBLOB="0180c2000000aaaaaaaaaa00810000000806000108"])


r0 = socket(0x2, 0x2, 0x0)
getsockname$unix(r0, &(0x7f0000000000)=@abs, &(0x7f0000001200)=0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x29, 0xe, &(0x7f0000000000)="02000000", 0x4)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000000))
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x1ff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
socket(0x0, 0x0, 0x0)
shmctl$IPC_SET(0x0, 0x1, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x3a)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
r2 = socket(0x18, 0x2, 0x0)
r3 = dup2(r1, r2)
write(r3, &(0x7f0000000140)="0c398c088c93a3ccf8ea23045b766cd41e7991c7fbd4eaa11603876cbaea89c77c07e049fb603ae46d28a7874d5daac09ada48d35448d4abcd8cca749991285c7ade9b964cbbef22a7a5f185a30291308fbe3ba6eb39d2595d7cc05bebfe3be3a6c8ee37087d3bd3544f4d18a3437ea5d98d17e61df56e653e11a875d3d654c1340fc4afacf796d0e091197693e154fcdff4c0958ca215c0e71c0daa1dd071a84ee075a23d083fb92efa15651e955d4b3d3bd736830185328b974f43f553eb18e269386103f0a3fb65f1fae83a343b20f2e6aa4c6be16925f28c57670152e59556845e76ce7fba34e6cc3356b14920b0e6735b72185823a25ec04fe0902602a730ee377947871b749cc08ac498f347ae25b8190ea951a205d267bfa364cc575c1dc55eb08b1758c4e7d5e557a57ae84f8b0fb79b81157f31bb41368508abf76a02bada29c17e952d6efbb1fda650cb19d1eaf3edca69ff972ee63504c725bdd71a5bbffd9b416671dbcfa5572db125939132bb9d98e45cf827da0021e1c424c379259afac6efcd03c54eff682f75a15e24f65e6e9b392c0ceb8a279d3a4d67328fed41c4d1f648651aa4c2443452d2735a33c9d00d23fc1f18c7ba5c66f173c5715687380f43d4ed71542a4e0e7f49b7eec632a00e270e1efed20e6a17d082bbc0", 0x1e1)


r0 = socket(0x2, 0x2, 0x0)
setrlimit(0x0, &(0x7f00000000c0)={0x1})
openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r0, &(0x7f0000000000), 0x10)
setsockopt$inet_opts(r0, 0x0, 0x1, &(0x7f00000000c0)="9876d692a3ef9c7ab923a2f0", 0xc)
write(r0, &(0x7f0000000240)="14bdfa5d1d34e2fecb284a6498307dcda9aec43050036123339a346f737850551408753f95b7688ad4c4e1dd5489e7bafc58d3e5823757ae8b630719ef187ccad995f13dbe19a6dd4e6902bd8297b0799b426aabe9fad9db6996571c6d9f8bb5d542c2148aa42be940970fe88d34d8f99afe7e7820237400000000008000000100"/138, 0xfc7e)


ioctl$FIONREAD(0xffffffffffffffff, 0x802069c7, 0x0)
socket(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
pwritev(0xffffffffffffffff, &(0x7f0000000340)=[{&(0x7f0000000080)='\x00', 0x1}], 0x1, 0x126)
mkdir(0x0, 0x0)
chdir(&(0x7f0000000240)='./file0\x00')
mkdir(&(0x7f00000001c0)='./file1\x00', 0x0)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
socket(0x18, 0x3, 0x0)
r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000100)="b10005010000009f0500070007000000331c13fecea10500fef96ecfc72fd3357ae30200004e3039d2d236acf20bf404be01000000f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f335c22db830c032bfa896443c32118210000720fd38bfb0000fd54c125191b1257aea8c500002002fbfe0c2300008abfba0900000008e37193f8343712051eeab71dc000266c05080000fca65361ba84913f0100"/177, 0xb1, 0x0, 0x0, 0x0)
openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$PCIOCREAD(0xffffffffffffffff, 0xc0107002, 0x0)
syz_open_pts()
ioctl$TIOCSETAF(0xffffffffffffffff, 0x802c7416, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, "2cf748460adb56e8dd42caee5275882ceece40cf"})
syz_open_pts()
ioctl$TIOCSTART(0xffffffffffffffff, 0x2000746e)
socket$inet(0x2, 0x0, 0x0)
bind(0xffffffffffffffff, &(0x7f00000004c0)=@in={0x2, 0x2}, 0xc)
r1 = msgget$private(0x0, 0x460)
sysctl$vm(&(0x7f0000000000)={0x2, 0x8}, 0x2, &(0x7f00000001c0), 0x0, 0x0, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCIMMEDIATE(r2, 0x80044270, &(0x7f0000000180)=0x2)
r3 = dup(r2)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
syz_emit_ethernet(0xe, &(0x7f0000000100)=ANY=[@ANYBLOB="00001600"/14])
r4 = socket$inet(0x2, 0x3, 0x3d)
setsockopt$inet_opts(r4, 0x0, 0x1, &(0x7f00000000c0)="89144c0129ea94f77ea66ed006e3bc58e261c99a", 0x14)
sysctl$net_inet6_ip6(&(0x7f0000000000)={0x4, 0x18, 0x29, 0x34}, 0x4, &(0x7f0000000140), 0x0, &(0x7f0000000180), 0x0)
r5 = msgget$private(0x0, 0x244)
msgrcv(r5, 0x0, 0x1008, 0x0, 0x0)
msgctl$IPC_RMID(r1, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x8, 0x40)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000700), 0x0, 0x0)


r0 = socket(0x18, 0x2, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x8)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
r2 = kqueue()
kevent(r2, &(0x7f0000000180)=[{{r0}, 0xfffffffffffffffe, 0x1}], 0x8, 0x0, 0x0, 0x0)
dup2(r2, r1)
kevent(r2, 0x0, 0x0, 0x0, 0xffff, &(0x7f00000001c0))


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0xa, &(0x7f0000000040)='\t\x00\x00\x00', 0x4)
r2 = dup(r1)
dup2(r2, r0)
setsockopt(r0, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x881)
r0 = open$dir(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x801)
open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
r1 = syz_open_pts()
dup2(r1, r0)
open$dir(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
execve(0x0, 0x0, 0x0)


mkdir(0x0, 0x0)
mkdir(0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
sysctl$hw(&(0x7f0000001240)={0x6, 0x1a}, 0x2, 0x0, 0x0, 0x0, 0x0)
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
r1 = socket(0x18, 0x1, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = getuid()
r1 = getuid()
seteuid(r1)
syz_emit_ethernet(0x3e, &(0x7f00000000c0)=ANY=[@ANYBLOB="aaaaaaaaaaaa00000000000086dd6007a65d00080000fed7871358eb087d34e8a93239c1a0cb0000f8ffffffffffffff095cb70400002b"])
setreuid(r0, r1)
r2 = socket(0x18, 0x2, 0x0)
setsockopt(r2, 0x1000000000029, 0x0, &(0x7f0000000040)='\x00\x00\x00', 0x3)
r3 = socket(0x18, 0x1, 0x0)
dup2(r2, r3)
setsockopt(r3, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r4 = getuid()
setreuid(0xee00, r4)
r5 = socket(0x18, 0x2, 0x0)
close(r5)
openat$diskmap(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
fcntl$lock(r5, 0x8, &(0x7f00000001c0)={0x0, 0x0, 0x8000000000000000, 0x2000100000002})
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ff9000/0x4000)=nil, 0x1000}, {&(0x7f0000ff9000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f0000ffc000/0x1000)=nil}, {&(0x7f0000001000/0x2000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000002000/0x1000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f0000001000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x2000)=nil}], './file0\x00'})
r6 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000200)="03c076dbf6ab44454e57e1bdfcc6b0ba0f97d08d3cd6700ca6d6271210e960b8e583adcea6a7bf0d59344c9bb541", 0x2e)
ioctl$VMM_IOC_RUN(r6, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0})
r7 = socket(0x1, 0x1, 0x0)
ioctl$FIONREAD(r7, 0x8020697f, &(0x7f00000001c0))
sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f00000000c0)="964b2e8c33c6b9184c54128f975fecf28b35a6b4fe6c2c7decb370e1ded56c32941e0b88ddd1b408c2570ee069d4b5d9fe2d8c0e0e6fcae82f887c519aef0e4f551a8da94ec5e94e8cc86014dcae87ce36ccfa7db954ba0ac2262672aa4264b2ec6ad65c12edb84ce1def64f79b40d76e2c7318805285dcb26b2adfb8bdfa599fa5d155b68e34a92a4e96829325b7b8acd8cb6c66aa407b4ff97282541ca92edef6fc0382c47bd1c63e463375341590f6a327092643b98a174e443c056da46158047e0b068975ba714199a52b4034fa4364e7304b31dd9dcaced366eb800389ecb0e1c41c6058bb7fa03702e8a03363bc593818269f64a0be94d29087369babc60ce10bc4c561f687122c1b20dd9f10518", 0x111)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x0, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x801169ab, &(0x7f00000001c0))
r8 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r8, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})


recvmmsg(0xffffffffffffffff, 0x0, 0x2, 0x0, &(0x7f0000000100)={0x0, 0x301d0bcd})


r0 = socket(0x11, 0x3, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x1021, 0x0, 0x0)


syz_emit_ethernet(0x3e, &(0x7f0000000ac0)=ANY=[@ANYBLOB="ffff0000ffffaaaaaaaaaabb86dd6062626000082c00fe8000f2000000bbfe8000000000000000000000000000aa"])


syz_emit_ethernet(0x2e, 0x0)
openat$pf(0xffffffffffffff9c, 0x0, 0x8000, 0x0)
sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x25}, 0x4, &(0x7f0000000200), 0x0, 0x0, 0x0)
r0 = socket(0x2, 0x2, 0x0)
sendmsg$unix(r0, &(0x7f0000001a00)={&(0x7f0000000080)=@file={0x0, '\x00'}, 0x3, 0x0, 0x0, &(0x7f0000000180)=ANY=[], 0x18}, 0x0)
utimensat(0xffffffffffffffff, 0x0, 0x0, 0x0)
mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
getgroups(0x2, &(0x7f0000000140)=[0xffffffffffffffff, 0xffffffffffffffff])
r1 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
lseek(r1, 0x2, 0x0)
getdents(r1, &(0x7f0000000040)=""/4096, 0x1000)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
rename(&(0x7f0000000100)='./file0/file0\x00', &(0x7f00000003c0)='./file0/file0/../../file0\x00')
unveil(&(0x7f0000000300)='./file0/file0/..\x00', &(0x7f0000000400)='r\x00')
r2 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000240), 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x34}, 0x2, &(0x7f00000056c0)="8f45277c", &(0x7f00000057c0)=0x4, &(0x7f0000005800), 0x0)
getsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r3 = socket(0x11, 0x3, 0x0)
sendto$unix(r3, &(0x7f0000000000)="b10005136000009f05003e0800000000331c13fecea10500fef96ecfc72fd3357a068d02bc31a3a5673039d2d236acf20b7804be38164991f7cccf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f4d335c223e7d026ba8faff0037720fd38bfbb770c1f5a872c881e2772ec5a10400000000000000361b1257aea8c5d0002012000000000000880d6633c556ae9b287948a62310db415f779642cdcd71a3f8343712051e000000000000", 0xb1, 0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f00000000c0)=0x5)
readv(r1, &(0x7f0000000080)=[{&(0x7f00000009c0)=""/4109, 0x100d}], 0x1)
execve(0x0, 0x0, 0x0)


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
socket(0x18, 0x3, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(r1, 0xc0206921, &(0x7f00000001c0))
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x81}, {0x4c}, {0x16}]})
write(r2, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xfef3)
r3 = socket(0x2, 0x2, 0x0)
sysctl$hw(&(0x7f0000000000)={0x4, 0x1f}, 0x3, 0x0, 0x0, 0x0, 0x2)
sysctl$vfs_nfs(&(0x7f0000000000), 0x7, &(0x7f00000025c0), 0x0, 0x0, 0xffffffffffffff2d)
dup2(r1, r0)
r4 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000280), 0x1, 0x0)
ioctl$WSKBDIO_SETBACKLIGHT(r4, 0x800c5712, &(0x7f0000000040))
ioctl$FIONREAD(r3, 0x80206919, &(0x7f00000001c0))
r5 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r5, 0x8020690c, &(0x7f00000001c0))
open(&(0x7f0000000180)='./file0\x00', 0x80000000000206, 0x0)
openat$speaker(0xffffffffffffff9c, 0x0, 0x782, 0x0)
r6 = getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r6, 0x0, 0x0, 0xffffffffffffffff})
pipe(0x0)
r7 = fcntl$getown(0xffffffffffffffff, 0x5)
ktrace(&(0x7f0000000180)='./file0\x00', 0x0, 0xd30, 0x0)
ktrace(&(0x7f0000000680)='./file0\x00', 0x0, 0x28, r7)


mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x205310)
r0 = open(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)
close(r0)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000800)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
writev(r0, &(0x7f0000000100)=[{&(0x7f0000000040)="6838d827645be3eb8f216f8a86", 0xd}], 0x1)
close(r0)


open(&(0x7f0000000200)='./file1\x00', 0x0, 0x0)
r0 = socket$unix(0x1, 0x2, 0x0)
fcntl$lock(r0, 0xb, 0x0)
setreuid(0xee00, 0x0)
clock_gettime(0x33563686ec971794, 0x0)
socket(0x11, 0x3, 0xbf)
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x5900)
sysctl$net_inet_gre(&(0x7f0000000080)={0x4, 0x2, 0x2f, 0x3}, 0x4, &(0x7f00000003c0)="637972a6fce1afbb7ca53b375e65ed388c210886a8fcb04a5d8c810e4c6a8911ef0ace66e9f9bf0a812174a6146c75ed5b393a8b77f1bdf2a41c107d91512f6bce339a5f05309b445e0eac4cb5e579cf6dd3f671bafbe8062c90a0b800b5c6b087f8f040762e465b1380c91d271914ccfd34f987853dc649ff5e45fb68c7e7ede17688e0def437a059ede5dae913f09f083ebd9b6d3e313e52b500464685a4c9808a8fa1579740c885041badd636de9d85416d9371f6066c917b44a3ea7e381dba16e4d1f2069f13144f353893e16351afa81747a1870ce63528b2ff7f6a9da30300a47b77acc5ecccd481fdf31a0ecc3c6c15aef72e9504f83a27f08bb8d527390d78e1cf78ab7b1609aacf29c1f55bd55094046606a827e29f4a833d92ab055dfbf53175b762c4ed394fd41904a33bfc41e876ccbcfde4a5428ba6b6598bb92d7c1cc222e10043125f3482d0547d45f03f2efa5f0ca2d1db6a2a1b0f1ed30218f5fd3ebc0f9598794ca859f67a73782f1d38e944767c82bc387e657975a0090e8cf55a0118bbce176d7439c54c9a8e7cef177d5807bd20f723f75782ab9fa461066644ab8096fe3d13a264d04123e32907422fc97127c7d67eb77a77b222282ccd0df92e00", &(0x7f0000000100)=0x1c6, &(0x7f0000000240)="1fadace413b34f04da4a81f551ffaced8c57b9eae3c75f57f989ef4c0f23f0927086dc2fcef99651cdaadeb5ceab3e49226f98f7bf13d3e3acfe6132ba4cf929342f267801d238412466b5c79963ee3eb1cde4642683a97ab24a0e557ef77595f12eec0c7205499334a20181a5e41784a050454627fa1ea2d68b7277a37414e566212500c0cfec3cf032b3bb1cc44b58899a85e46f94c8e9cb767c4af6a971dbf303611d2bc175fb8450216e788682a42230f78898", 0xb5)
syz_open_pts()
dup2(0xffffffffffffffff, 0xffffffffffffffff)
r1 = open$dir(0x0, 0x0, 0x0)
r2 = kqueue()
kevent(r2, &(0x7f00000000c0)=[{{r1}, 0xffffffffffffffff, 0xb7c61f5c345976d}], 0x8, 0x0, 0x0, 0x0)
openat$diskmap(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r3 = dup2(0xffffffffffffffff, r2)
setsockopt(r3, 0x80000000, 0x10000006, &(0x7f0000000340), 0x0)
r4 = getuid()
r5 = kqueue()
r6 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
kevent(r5, 0x0, 0x5, 0x0, 0x9f, 0x0)
r7 = dup2(r6, r5)
chown(&(0x7f0000000180)='./file0\x00', r4, 0x0)
chmod(0x0, 0x0)
r8 = getuid()
seteuid(r8)
r9 = fcntl$getown(r7, 0x5)
getgroups(0x1, &(0x7f0000000140)=[0x0])
setsockopt$sock_cred(r7, 0xffff, 0x1022, &(0x7f00000000c0)={r9}, 0xc)
r10 = semget$private(0x0, 0x3, 0x80)
semctl$GETPID(r10, 0x2, 0x4, &(0x7f00000001c0)=""/2)


setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0xee00, r0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = kqueue()
kevent(r2, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x802069de, &(0x7f00000001c0))


r0 = kqueue()
kevent(r0, &(0x7f0000000080)=[{}, {}, {{}, 0x0, 0x0, 0x0, 0x0, 0x7}, {{}, 0xfffffffffffffff9}], 0x101, &(0x7f0000000180), 0x6, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0206923, &(0x7f00000001c0))
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x8040691a, &(0x7f00000001c0))


sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f0000001440)="cc", 0x1)
kqueue()
recvfrom(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
sysctl$kern(&(0x7f0000000040)={0x1, 0x32}, 0x2, 0x0, 0x0, &(0x7f0000001440)="cca410df", 0x4)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000300)={0x2, &(0x7f00000000c0)=[{}, {0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x3f}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x2000, 0x0, 0x2a)


unveil(&(0x7f0000000000)='./file1\x00', &(0x7f00000001c0)='x\x00')
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {}, {0x6, 0x0, 0x0, 0x85}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000240)="b100051300000000000000402120000000000000cea10500fef96ecf2ac72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf7f882b297be1aa0540000051e2f0ad3ebbc257699a1f139b672f335c223e7d0c032b0c8a6443a42118000000720fd38bfbb770c1f5a872c88106002ec589040000000c0000348a1b1257aea8c500002002fbfe0c2300008abfba0900afb7515871a3f8343712051eeab7196fcb050407000000c011200000", 0xb1, 0x0, 0x0, 0x0)


close(0xffffffffffffffff)
r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000040)=[{}, {0x26}], 0x2})
openat$vnd(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
syz_open_pts()
r1 = openat$pf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
fchmod(r1, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x2, 0x0, 0x1e}, 0x5, &(0x7f0000000140)="e33745e84d5ebfb9cc2f7fa3a7f7891721720e69dac610a4fb5eaf3e3c6e1d648a8ca6ebc70f949c442aee9dc79e2cd74f4e106f382caf01ada3bc4efb0f6bc50690e5d879fac2492f4a0491b1ea3359aa5c5164ad97ac7c3aaddd498c0f962f5167b69cfdc8287fc34b8138340e60c404a855858ea5fc", &(0x7f0000000000), 0x0, 0xfffffdfd)
syz_open_pts()
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
kqueue()
kevent(0xffffffffffffffff, &(0x7f00000000c0), 0x30, 0x0, 0x57d, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETWF(r2, 0x80104277, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$FIOGETOWN(r0, 0x4004667b, &(0x7f00000001c0))


syz_emit_ethernet(0x4e, &(0x7f0000000080)=ANY=[@ANYBLOB="8925000040002adb0070162e86dd60f6190000180600fe7fe0000000000000000000000000aaff"])


ioctl$TIOCGWINSZ(0xffffffffffffffff, 0x40087468, &(0x7f0000000000))
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000040)={<r0=>0x0, 0x0, <r1=>0x0}, 0xc)
fcntl$setown(0xffffffffffffffff, 0x6, r0)
mprotect(&(0x7f0000ff9000/0x4000)=nil, 0x4000, 0x7)
socketpair(0x21, 0x4000, 0x0, 0x0)
bind(0xffffffffffffffff, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
chown(&(0x7f0000000100)='./file0\x00', 0x0, r1)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000600)={&(0x7f00000001c0)=@abs={0x0, 0x0, 0x2}, 0x8, 0x0}, 0x0)
ioctl$TIOCSPGRP(0xffffffffffffffff, 0x40047477, &(0x7f0000000640))
r2 = kqueue()
r3 = dup(r2)
ioctl$TIOCSETA(r3, 0x802c7414, &(0x7f0000000680)={0x7f, 0xfffffd76, 0x75, 0x9, "2c63ad7996f1e758e5fd06a7cd67261a796926ba", 0x5, 0x6})
madvise(&(0x7f0000ff9000/0x4000)=nil, 0x4000, 0x4)
ioctl$VT_OPENQRY(r3, 0x40047601, &(0x7f00000006c0))
seteuid(0x0)
r4 = semget(0x3, 0x4, 0x0)
semctl$SETALL(r4, 0x0, 0x9, &(0x7f0000000700)=[0x11, 0x8])
minherit(&(0x7f0000ff8000/0x3000)=nil, 0x3000, 0x1)
msync(&(0x7f0000ff9000/0x3000)=nil, 0x3000, 0x0)
r5 = openat$zero(0xffffffffffffff9c, &(0x7f0000000740), 0x20000, 0x0)
openat$vmm(0xffffffffffffff9c, &(0x7f0000000780), 0x400, 0x0)
semget(0x0, 0x2, 0x40)
ioctl$BIOCSETF(r5, 0x80104267, &(0x7f0000000800)={0x5, &(0x7f00000007c0)=[{0x5, 0x2, 0x9, 0x94}, {0x4, 0x7, 0x6, 0x1}, {0x0, 0x9, 0x0, 0xce}, {0xe42, 0x1, 0xb7, 0x8}, {0x2, 0x4, 0x40, 0x1}]})
ioctl$BIOCSDIRFILT(r3, 0x8004427d, &(0x7f0000000840)=0x400)
socket(0x18, 0x4, 0x1f)
sysctl$machdep(&(0x7f0000000880), 0x2, &(0x7f00000008c0)="eb3616d53e26a0eb90bec6a698f0002f8019d15e", &(0x7f0000000900)=0x14, 0x0, 0x0)
r6 = accept(r3, &(0x7f0000001940)=@un=@file={0x0, ""/505}, &(0x7f0000001b40)=0x1fb)
sendmmsg(r6, &(0x7f0000001dc0)={&(0x7f0000001d80)={&(0x7f0000001b80)=@in6={0x18, 0x2, 0x7f, 0x3}, 0xc, &(0x7f0000001c00)=[{&(0x7f0000001bc0)="a1477c96843a4420c0a3be74ee98d765c9bd227b08f2ee5931354d213d64238a7229b2f238", 0x25}], 0x1, &(0x7f0000001c40)=[{0xf8, 0xffff, 0x4, "582094ef84a33cd5dc41fa7f7c819904eb3d75988f756a48dfb85b960256c915f4787e67480b6c3ef0f47c024597213e957b8b856e211a0abb16554cca74a5a44fe1dc7ad34b0cb34f197373310f1d6f2ef753df14522a3893fa299563e8f97c46105d38134743826fac22ba0369cd82cc8d9c019cd73c016e6c20acee68b2eb7639142034515d64d093bb3bd4bbc47f0a84b56da9954a4e4028c4a4ab64f912b482838094351ade70c59b0e61a33d21580342a9614691bba8fe2722b257ecf9e30cc978a8468d490f66e82abf49914c803d5a01616cef1f111fa1a411c3a90b70970496"}, {0x38, 0xffff, 0x4, "9bb42eb833a31b88b84f2579bf223708d4371cb557d342e18f4906201c41bce1e6fb02dae2"}], 0x130}, 0x7ff}, 0x10, 0x8)
msgctl$IPC_STAT(0x0, 0x2, &(0x7f0000001e00)=""/142)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0xfffffffe, 0x0, {0x0, 0x1}})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7, 0x3}, 0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x802, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
faccessat(0xffffffffffffffff, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x50}, {0x48}, {0x6}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x0, 0x0})
write(r0, &(0x7f00000003c0)="985fa7fbdf69aca69c9a97347864", 0xe)


mknod(0x0, 0x0, 0x0)
r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
writev(r0, &(0x7f0000000200)=[{&(0x7f0000000500)="2ffdffffff87f336fe9e57ef85e8d8ee96a3bb11dc364541b69a4014db20d8cf0077536187bde3f429e0d5fd23016d53c2", 0x31}], 0x1)
execve(0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)


open(&(0x7f0000000140)='./file0\x00', 0x78e, 0x0)
open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x1604)
open(&(0x7f0000000040)='./bus\x00', 0x0, 0x0)


mkdir(&(0x7f0000000080)='./file0\x00', 0x0)
chmod(&(0x7f0000000100)='./file0\x00', 0x43)
setreuid(0xee00, 0x0)
r0 = getuid()
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r2 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000540), 0x1, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x1, &(0x7f0000000180)=[{0x6c}]})
ioctl$WSKBDIO_GETMAP(r2, 0x8010570e, &(0x7f0000000180)={0x0, 0x0})
mkdir(&(0x7f0000000000)='./file0\x00', 0x10)
r3 = getuid()
chown(&(0x7f0000000180)='./file0\x00', r3, 0x0)
r4 = getuid()
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000000c0)={0xffffffffffffffff, <r5=>0xffffffffffffffff})
getsockopt$sock_cred(r5, 0xffff, 0x1022, &(0x7f0000000200)={<r6=>0x0, 0x0, <r7=>0x0}, &(0x7f0000000240)=0xc)
setregid(0xffffffffffffffff, r7)
setgroups(0x1, &(0x7f0000000040)=[r7])
setreuid(0x0, r4)
shmctl$IPC_SET(0x0, 0x1, &(0x7f0000000280)={{0x2, r3, r7, r0, r7, 0x4, 0x6}, 0x4, 0x20, r6, r6, 0x2, 0x100000001, 0x101})
chmod(&(0x7f0000000080)='./file0\x00', 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x5200)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0xc4)
r8 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r8, 0x6, 0xf, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000100), 0x0)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
pread(r1, &(0x7f0000000040)="16", 0x1, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{}, {}, {0x6}]})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000040)="03", 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$VMM_IOC_CREATE(r0, 0xc2585601, &(0x7f0000000040)={0x10, 0x0, [{&(0x7f0000001000/0x4000)=nil, &(0x7f0000003000/0x4000)=nil}, {&(0x7f0000005000/0x2000)=nil, &(0x7f0000006000/0x1000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000005000/0x3000)=nil}, {&(0x7f0000000000/0x1000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000002000/0x2000)=nil, &(0x7f0000002000/0x2000)=nil}, {&(0x7f0000000000/0x3000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {&(0x7f0000003000/0x2000)=nil, &(0x7f0000003000/0x4000)=nil}, {&(0x7f0000ff9000/0x2000)=nil, &(0x7f0000000000/0xc000)=nil}, {&(0x7f0000001000/0x1000)=nil, &(0x7f0000001000/0x3000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000001000/0x4000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000007000/0x4000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000003000/0x1000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000ff8000/0x2000)=nil, &(0x7f0000ff9000/0x3000)=nil}, {&(0x7f0000002000/0x4000)=nil, &(0x7f0000ff7000/0x4000)=nil}], './file0\x00'})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x6c}, {0xc0}, {0x8186}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x54}, {0x48}, {0x6}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])


mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x10205b1a)
r0 = open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)
mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x205b9a)
open(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
ioctl$TIOCCBRK(r0, 0x2000747a)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000001c0)=[{0x6c}, {0x4c}, {0x810e}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x35})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETD(r1, 0x8004741b, &(0x7f0000000080)=0x7)
writev(r0, &(0x7f0000000000)=[{&(0x7f0000000a80)="047cd7820a5bc856c5382e2b6ae71624d286b40939b5bc80448b081cb419604ea2319864131f8b45fcaf64663438a2e71a0f49fd6f881f90c242460a04fbe66f5dc19330a999357f06b8475ff8160849138012cec6e92ea3dbb7afb3b14503f81aad0a001882fc3f0b952102c3e871c0c7eaad7e0c2d776c7d257e05afc2a716f76441bfd414151e2c0f84ca13f4544e1c35e492d6305738ce3fbcee854a8a8362052bb86c00b8ffe7b9a0703d900282542eeb5f22e1c6a77406cf881a93d5dd4781c26df75632b1003b8a099d97d73bd28df3ee1fe6c1b345839fb94302e117c1c48aef9f01d18cd78bb5ff5652a82133e142e2eb6b04e3304653f2e301412479aabc43ae19444db034ca500eb712b36a53f5b1254bd4f00ddd408cb010abaab5a8ee13ba79b2ff3847eb35d880d4b472104be6168f206766a25a4b6b410770aa2210e008283f1fe1b88eb83a6cf8786dd67d8c98aaa10eec2e54c46ddde4341ef14a83a73d21c0cfca333cc18f813da3b765930fd6382926f99a267a554624b2ccdf77c40407f90ee27996ac2c4950b71310ba9de7259d608a3b1a435a91e5de956c2edde09bad72e0522fa980897120c8cd68ce7731fc07f85ae30265b90ad5d4cf6f25e1ceb08babb1966418d1228e4d2bf07f4075ddb54ffa98c9374829a58ac666788a1a5b0a4fa1b2f670ef0fce9de9b8edc891ddd05de804547bb4515a4b0c73a89baf9575fe2260e6efd92bcc242a3ee1d02e2d953ef04a108ced80e99d1da7008af9161709ea3515a17444d0d8c80d", 0x234}], 0x1)


poll(0x0, 0x0, 0x0)
syz_emit_ethernet(0x3e, &(0x7f00000009c0)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaa8eaaaaaa86dd60cb706500083b0035b282d55c8bf287fa1fd9a1724fe395ff020000000000000000000000000001"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
socket$inet(0x2, 0x0, 0x0)


kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000140)={0x4000, 0xfffffffffffffffb})
r0 = kqueue()
kevent(r0, &(0x7f00000000c0), 0x7, 0x0, 0x80000001, 0x0)


mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0, 0x1)
setrlimit(0x0, &(0x7f0000000000))
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
ioctl$FIONREAD(r0, 0x80146945, &(0x7f00000001c0))


mknod(&(0x7f0000000000)='./file0\x00', 0x6000, 0xf02)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x5, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x0, 0x0)
ioctl$FIONREAD(r2, 0xc0206921, &(0x7f00000001c0))
fcntl$dupfd(0xffffffffffffffff, 0xa, r1)
ioctl$FIONREAD(0xffffffffffffffff, 0x8004745d, 0x0)
ioctl$FIONREAD(r1, 0xc020691b, 0x0)
r3 = socket(0x1, 0x5, 0x0)
ioctl$VNDIOCGET(0xffffffffffffffff, 0xc4104603, 0x0)
ioctl$FIONREAD(r3, 0x80206979, &(0x7f00000001c0))
mmap(&(0x7f0000109000/0x4000)=nil, 0x4000, 0x1, 0x1010, 0xffffffffffffffff, 0x0)
pipe(0x0)
getppid()
mknod(0x0, 0x0, 0x0)
setreuid(0x0, 0x0)
getuid()
getuid()
setreuid(0xee00, 0x0)
unveil(&(0x7f00000000c0)='./file0/file0\x00', &(0x7f0000000080)='r\x00')


mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x3e61)
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x2000000000054})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000500)={0x0, 0x0, 0x0, 0x0, "bf4621ea5fc8fd2d6dfda3766485e63042041a32", 0x404})
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)
writev(r0, &(0x7f0000000000)=[{&(0x7f0000000300)="d4", 0x1}], 0x1)
read(r1, &(0x7f0000000140)=""/223, 0xdf)
readv(r1, &(0x7f0000000480)=[{&(0x7f0000000240)=""/157, 0x9d}], 0x1)


sysctl$ddb(&(0x7f0000000000)={0x9, 0x5}, 0x2, &(0x7f0000000100)="d7342cc3", &(0x7f0000000080)=0x4, &(0x7f00000001c0)='\x00\a\x00\x00', 0x4)


r0 = open$dir(&(0x7f0000000080)='.\x00', 0x0, 0x0)
getdents(r0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000040)={0x8, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047470, &(0x7f0000000280)=0x5)
readv(r0, &(0x7f0000000200)=[{&(0x7f0000000100)=""/176, 0xb0}], 0x1)
ioctl$TIOCSTOP(r0, 0x2000746f)
execve(0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
open(0x0, 0x0, 0x0)
getpid()
ktrace(0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
socket(0x800000018, 0x1, 0x0)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
select(0x40, &(0x7f0000000500)={0x3fc}, 0x0, 0x0, 0x0)
kqueue()
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)


r0 = open$dir(&(0x7f0000000040)='./file0\x00', 0xae828e137847f62, 0x0)
setrlimit(0x1, &(0x7f0000000000)={0xfffffffffffffffd, 0xffffffffffffffff})
ftruncate(r0, 0x20008002)
open(0x0, 0x0, 0x0)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x14}, 0x4, 0x0, 0x0, &(0x7f00000010c0), 0x4)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETAF(r1, 0x802c7416, &(0x7f0000000000)={0x0, 0xffffff49, 0x7, 0x5bc, "225e00d1554709aa0900fa4ab1896c04aec100"})
writev(r0, &(0x7f0000000200)=[{&(0x7f0000000180)="d37f05c970c47013bc5c09", 0xb}], 0x1)


pipe(&(0x7f0000000100)={<r0=>0xffffffffffffffff})
write(r0, &(0x7f0000000340), 0xd4e688a67930cd)
writev(r0, &(0x7f0000000180)=[{&(0x7f0000000000)="94", 0xffd0}], 0x4c)
socket(0x0, 0x0, 0x0)
close(r0)
pipe(&(0x7f0000000380))
execve(0x0, 0x0, 0x0)


r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x25, &(0x7f0000000480)="5ab7776a", 0x4)
syz_emit_ethernet(0x4e, &(0x7f00000003c0)=ANY=[@ANYBLOB="aaaaaaaaaaaa7fd67572210786dd6007558300183701fe8000000000000000000000000000aaff020000000000000000000000000001"])


open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000401})
open(&(0x7f00000000c0)='./file0\x00', 0x20, 0x0)
r1 = open(&(0x7f0000000400)='./file0\x00', 0x0, 0x0)
fcntl$lock(r1, 0x9, &(0x7f0000000140)={0x0, 0x0, 0x4c0, 0x269000000, 0xffffffffffffffff})
r2 = open(&(0x7f0000000bc0)='./file0\x00', 0x0, 0x0)
fcntl$lock(r2, 0x9, &(0x7f0000000080)={0x0, 0x0, 0x100, 0x1000100000000})
r3 = open(&(0x7f0000000bc0)='./file0\x00', 0x0, 0x0)
fcntl$lock(r3, 0x9, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1000100000000})


mknodat(0xffffffffffffff9c, &(0x7f0000000400)='./file0\x00', 0x2000, 0x0)
r0 = open(&(0x7f0000000380)='./file0\x00', 0x0, 0x0)
r1 = syz_open_pts()
ioctl$TIOCCONS(r1, 0x80047462, &(0x7f0000000080)=0x7)
ioctl$TIOCCONS(r0, 0x80047462, &(0x7f0000000100))


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
openat$vmm(0xffffffffffffff9c, &(0x7f0000000100), 0x20, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
madvise(&(0x7f00003e0000/0x3000)=nil, 0x3000, 0x4)
recvmsg(0xffffffffffffffff, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{0x0}], 0x1, 0x0}, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
sysctl$hw(&(0x7f0000000000)={0x6, 0x11}, 0x2, &(0x7f0000000100), 0x0, &(0x7f0000000240), 0x0)
socket$inet(0x2, 0x2, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(r1, 0x80104267, 0x0)
syz_emit_ethernet(0x2a, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000040), 0x3, &(0x7f0000000080)="397c9aca", &(0x7f0000000780)=0x4, 0x0, 0x0)
ioctl$VMM_IOC_RESETCPU(0xffffffffffffffff, 0x82405605, 0x0)


sysctl$ddb(&(0x7f0000000000)={0x9, 0x5}, 0x2, &(0x7f00000002c0)="b151efd9ec9b99ce872e665d84241a5d2a4e39ba4a08d1bf87cccd2140583a0309001556c5561af91e1ee1ab99a2a20048472e6ea9041e8d9b0000103b2656be0b83e6bef50a085d22bd29ef0c0cf6a2cb4a0a4101060fc2091b6db2b007f42ac6888d87dbcd66b3604f7ebfcfd1d6cdb18ef112db4e84d61427299453b7842b00c6b5d02eeafced52087993a543d83d2800000000000000000000786175566f830605b2314e9959e1c9e03cafa2c9830196002152912948f7e57a8b53af5aae7a1e7e95c7c63bd3317327069d4a738724a546c3913bddb3627de8c368c628cf63c8a95da60648a8443a2b73950ccbdac6b0a03822112dca055742010f231f68d646867dfbce6f70ac63782c3c6091cbb0efa9444d", &(0x7f0000000040)=0x54, 0xfffffffffffffffe, 0x4)


r0 = syz_open_pts()
ioctl$TIOCCONS(r0, 0x80047462, &(0x7f00000004c0)=0x1f)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$TIOCCONS(r0, 0x80047462, &(0x7f0000000280))


r0 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r0, 0x0)
accept(r0, 0x0, 0x0)
close(r0)
execve(0x0, 0x0, 0x0)


ftruncate(0xffffffffffffffff, 0x0)
sysctl$vfs_nfs(&(0x7f0000000040)={0x7}, 0x3, 0x0, 0x0, 0x0, 0xffffffffffffffa0)


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
sysctl$net_inet_udp(&(0x7f0000000240), 0x4, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240), 0xc)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000000)=[{0x4}, {0x4d}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


mkdir(&(0x7f0000000000)='./file1\x00', 0x101)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
recvfrom$unix(r0, 0x0, 0x0, 0x1803, &(0x7f0000000180)=@file={0x1, './file1\x00'}, 0xa)
pipe(&(0x7f0000000100)={<r1=>0xffffffffffffffff})
fcntl$setstatus(r1, 0x4, 0xc0)
r2 = getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r2})
pipe(&(0x7f00000001c0)={<r3=>0xffffffffffffffff})
socketpair$unix(0x1, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r4 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(r4, &(0x7f0000001580)=[{&(0x7f00000000c0)='\x00', 0xfffffeb0}], 0x1)
ioctl$WSKBDIO_GETMAP(r3, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
ioctl$BIOCGDLTLIST(0xffffffffffffffff, 0xc010427b, &(0x7f0000000300)={0x6, &(0x7f00000002c0)=[0x23e, 0x3, 0x8, 0x7f, 0x3, 0x800]})
r5 = fcntl$getown(r3, 0x5)
fcntl$setown(r1, 0x6, r5)
setpgid(0x0, r2)
close(r1)
chmod(&(0x7f00000000c0)='./file0\x00', 0x234)
chdir(&(0x7f0000000140)='./file0\x00')
mkdir(&(0x7f0000000280)='./file1\x00', 0x1ca)
setreuid(0x0, 0xee01)
unveil(&(0x7f0000000080)='./file1\x00', &(0x7f00000001c0)='x\x00')
rmdir(&(0x7f0000000040)='./file1\x00')


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000200)=[{0x61}, {0x81}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f00000001c0)=ANY=[])


r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x3d, 0x0, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x802069ad, &(0x7f00000001c0))
sysctl$hw(&(0x7f0000000040)={0x6, 0x1}, 0x2, &(0x7f0000000080)="80b5f33f55b1", &(0x7f0000001080)=0x6, 0x0, 0x0)
r1 = socket(0x2, 0x1, 0x0)
r2 = socket(0x2, 0x2, 0x0)
bind(r2, &(0x7f0000000340), 0xa)
connect$unix(r2, 0x0, 0x10)
accept$inet6(r1, &(0x7f0000000180), &(0x7f0000000200)=0xc)
setsockopt(0xffffffffffffffff, 0x0, 0x1ff, &(0x7f0000000240)="f48995a2232ab4007cddadcfa7b0000a363a178b95c99923b6d42955bae7f9d616de60421e9f49e222a50c1d143bd97dadd1d83fe243aef95815b0339443e26bf65406738cb2d3dea27ce6e7f4004a41b70297709f7776abb652c282ccc8c0557c0f9bd3f72cb33149637ec24c89ed786a2b0bfefc778f92693eaa8debe5ef2bbfa2212164f3057e5326e15f2e8f590d78ef9207c5c1d733a023f3c8af752e9cbf17df425efca64d25dd5d852522d3bb86dd02bbf79e5722c5da624472631496f1fdde5781f1ce3726ceab9d6c0594b3040873", 0xd3)
getsockname$unix(r2, &(0x7f0000000000)=@abs, &(0x7f0000001200)=0x8)
dup2(r2, r1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$inet(r1, &(0x7f0000000000), 0x10)
syz_emit_ethernet(0x36, &(0x7f0000000200)={@local, @broadcast, [], {@ipv6={0x86dd, {0x0, 0x6, "062500", 0x0, 0x2b, 0x0, @rand_addr="fe350e28ef0900c08cfe24be00", @loopback={0xfeffffff00000000}}}}})
sysctl$hw(&(0x7f0000000000)={0x6, 0x1b}, 0x2, &(0x7f0000000140), 0x0, 0x0, 0x0)
r3 = semget$private(0x0, 0x2, 0x110)
r4 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
pwritev(r4, &(0x7f0000000500)=[{&(0x7f0000000100)="6b0ecdda9e20ccb14209e0f584971e6be4", 0x11}], 0x1, 0x4)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x1, 0x10, r4, 0x0)
setitimer(0x0, &(0x7f0000000000), 0x0)
socket(0x6, 0x1, 0x1f)
semctl$GETPID(r3, 0x3, 0x4, &(0x7f0000000040)=""/40)


kqueue()
kqueue()
r0 = socket(0x2, 0x1, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
sendmsg(0xffffffffffffffff, &(0x7f0000000800)={&(0x7f0000000040)=@in6={0x18, 0x1, 0x0, 0x4}, 0xc, 0x0, 0x0, 0x0, 0x3d0}, 0x0)
close(r1)
socket(0x2, 0x2, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140)={<r2=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
sendmsg(r2, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)


r0 = socket(0x18, 0x1, 0x0)
listen(r0, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
shutdown(r0, 0x2)
mlock(&(0x7f0000ffa000/0x4000)=nil, 0x4000)
connect$unix(0xffffffffffffffff, &(0x7f0000004c40)=@file={0x0, './file0\x00'}, 0xa)
fchownat(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
mlock(&(0x7f0000ffb000/0x2000)=nil, 0x2000)
select(0x0, 0x0, &(0x7f0000004e00)={0x7d, 0x9, 0x5, 0x101}, 0x0, 0x0)
msync(&(0x7f0000fef000/0xe000)=nil, 0xe000, 0x0)
mkdirat(0xffffffffffffffff, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
r1 = socket(0x11, 0x3, 0x0)
r2 = socket(0x11, 0x3, 0x0)
setsockopt(r2, 0x11, 0x4, &(0x7f0000000340)="12000000", 0x4)
setsockopt(r2, 0x11, 0x1, &(0x7f0000000200)="12000001", 0x4)
sendto$unix(r1, &(0x7f0000000000)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)


r0 = socket(0x18, 0x3, 0x0)
getsockopt(r0, 0x29, 0x32, 0x0, 0x0)
r1 = socket$inet6(0x18, 0x2, 0x7)
setsockopt$sock_int(r1, 0xffff, 0x1007, &(0x7f0000000100)=0x2, 0x4)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f0000000000)={0x15f, &(0x7f0000001080)=[{0x280}, {0xc, 0x10}, {0x6, 0x0, 0x0, 0xfffffff8}]})
socket$inet(0x2, 0x1, 0x0)
socketpair$unix(0x1, 0x3, 0x0, &(0x7f00000000c0)={0xffffffffffffffff, <r3=>0xffffffffffffffff})
getsockopt$sock_cred(r3, 0xffff, 0x1022, &(0x7f0000001f80), &(0x7f0000000100)=0xc)
sysctl$net_inet_gre(&(0x7f0000000000)={0x7, 0x4}, 0x4, 0x0, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001880)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f00000003c0)="5080c5a97558d472b3d20fe4a61339bd547710cb16b1331906dee84e0746ad4a017eeafc6cd84f80da82744d47076311d447c0ad1580769294c53268547ffa2de45c1e30364fef08671030bb9ca9e5f071219824dbbffd53d83e2eded34241119e2dc17a", 0x64}, {0x0}, {&(0x7f0000000300)="7ea3f94ec9aea0cfec8e6958bff13adf333086d3c258d19367300f6a0a5398d749f0c24c3de285a28d9100e4532b0710cbce050e3162b8150acf29179cf07c3286e01de621182f7ed0229c571858cffb0e598a7b21d0621b7b", 0x59}], 0x3, 0x0, 0x0, 0x400}, 0xc01)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000080)={<r4=>0xffffffffffffffff})
sendmmsg(r4, &(0x7f0000001740)={0x0}, 0xfffffffffffffdf2, 0x0)
r5 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000140), 0x10, 0x0)
ioctl$DIOCMAP(r5, 0xc0106477, &(0x7f00000001c0)={&(0x7f0000000180)='./file0\x00', r5, 0x1})
r6 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000380), 0x0, 0x0)
ioctl$VNDIOCGET(r6, 0xc4104603, &(0x7f0000001a40)={'./file0\x00', 0xfffffbf9, 0x3})
bind$unix(r4, &(0x7f00000002c0)=@abs={0x1, 0x0, 0x1}, 0x8)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000240)={0x0, 0x5})
r7 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r7, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
write(r2, &(0x7f0000000200)="b1c05b5fb165120a4224a763037a", 0xe)
ioctl$BIOCVERSION(r2, 0x40044271, &(0x7f0000000080))
sysctl$vm(&(0x7f0000000000)={0x2, 0x6}, 0x2, 0x0, 0x0, &(0x7f0000002280), 0x0)
syz_emit_ethernet(0x62, &(0x7f00000004c0)=ANY=[@ANYBLOB="aaaaaaaaaaaaffffffffffff86dd6008000000000000008000000000000000002300000000aaff020000000000000000000000000001"])
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r8=>0xffffffffffffffff})
getsockopt$sock_int(r8, 0xffff, 0x200, 0x0, 0x0)
munmap(&(0x7f00000f2000/0x3000)=nil, 0x3000)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
r2 = dup(r1)
recvmmsg(r2, &(0x7f0000000440)={&(0x7f0000000040)={0x0, 0x0, &(0x7f0000000580)=[{0x0}, {0x0}, {&(0x7f0000000080)=""/91, 0x5b}], 0x3, 0x0}}, 0x9, 0x64, 0x0)
read(r2, &(0x7f0000000740)=""/247, 0xf7)
dup2(r0, r1)
writev(r1, &(0x7f0000000640)=[{&(0x7f0000000140)="90", 0x1}], 0x1)
execve(0x0, 0x0, 0x0)


r0 = socket(0x18, 0x5, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x4, 0x0, 0x0, 0x0, 0x0, 0x8}})
close(r0)
r1 = socket(0x0, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
close(0xffffffffffffffff)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504600000000000000007000000331c13fecea10500fef9ed06c72fd3357ae320b37b673039d2d236073705ae04be38164991f7accf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139b672f4d335d223e7d029d6ba8cc630037282102000000720f70", 0x69, 0x0, 0x0, 0x0)
r2 = socket(0x18, 0x2, 0x0)
close(r2)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x88}})
r3 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r3, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r3, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r4 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r4, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


writev(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f00000004c0)="4b218d114ca7cbdd5c6a2dddd227668e017145c65853de497dc18ddf59a105b91f005be73cf00b391289af5024c2f9cf6310c72a020000000000000058aca3f6d5198417cc8efbfc5f10962b93f535443a40f2a652c64a9f4902b2a6158afbb6aa56e29f471b4d49178f3a911b995aeb08ba2670518e0fbb081d7cbfe4263801f636f8fea45f8b795a1e56f731c5d3fccfaba7e3b986e61a5401ac0d6632fd4afb25b3360ee9f7acc74263a6a947479373bec6a3aa6e5f7397f9e40f86ded6c437e4f2ae29dd9dc958bba2860fa3719d01", 0x127}, {&(0x7f0000000940)="09a863a3f8ac3d2e85464928a39a2645cc5a38280e8bd539cb186068da27c2ccbb8fbf6aac14f732c6896d8c4ab8a6fe2a0c77dd44d40d297b1b2bdf23c28adaad0ab3952dd28ea934961de16729c53ee16f00403df41704afd3fcc77c8868ffe724e78fe42bec30a4daa06d6320db21592cdba666822ca53620d53e2ffc545b97a7d0515429d6b70d47b9d57c0f2c0c9683bcc00c3f0675cbbd778fa58ea7106f139eed2835b35dd3c2477cbd6b3670c168871a7b82e7d5658248ce0221da863797c7c55af453ee4ac4a4d139af4356144a05b9"}, {&(0x7f0000000300)="822fcd95d06b9b601225d7d830037e2c3f3489335396645d4ad8a602358bec2c77ff6b7d0d9a80585889edda8091ff5737709e32d9b898da7dc50722219747bbd13b4f1a5cd4bf192d554d997b84b8c9266c7b5032ff5716356d7c86c85b4ee7a8ba5f2b3b8a210c7bc2156531f73dfd77681c55e5aa26dbd9d7"}], 0x1)
r0 = socket$inet(0x2, 0x5, 0x0)
r1 = socket(0x20, 0x4, 0xff)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
setrlimit(0x0, 0x0)
syz_open_pts()
r2 = open(0x0, 0xa02, 0xc)
r3 = socket(0x0, 0x4, 0xc7)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
syz_emit_ethernet(0x138, 0x0)
r4 = msgget$private(0x0, 0x2e)
pipe2(0x0, 0x0)
setreuid(0xee00, 0x0)
r5 = getuid()
setreuid(0x0, r5)
r6 = socket(0x800000018, 0x2, 0x0)
r7 = socket(0x18, 0x1, 0x0)
setsockopt(r7, 0x29, 0xe, &(0x7f0000000000)="02000000", 0x4)
r8 = dup2(r7, r6)
listen(r6, 0x0)
msgsnd(0x0, &(0x7f0000000040)=ANY=[@ANYRES64=r4, @ANYRESOCT=r8, @ANYRES8=r3], 0x1f, 0x0)
msgsnd(r4, &(0x7f0000000140)=ANY=[@ANYRESDEC=r0, @ANYRES32=r0, @ANYRES8, @ANYRESOCT, @ANYRES16=r2], 0x401, 0x0)
msgsnd(0x0, 0x0, 0x401, 0x0)
msgrcv(r4, &(0x7f0000000380)={0x0, ""/140}, 0x94, 0x2, 0x0)
msgctl$IPC_RMID(r4, 0x0)
syz_emit_ethernet(0x3e, &(0x7f0000000140)=ANY=[])
msgsnd(r4, 0x0, 0x1008, 0x800)
pread(r1, &(0x7f0000000700)="a8e4d057c76b16a0d43d688b638c3f6b4aa6b300c044247cea755ddfc23febf6560ec616d35d73913460da77b1f5aad5b09dcedda9ba1cfde697fb6b53a0070abbdde901ede645e8704a53d4beaf1a8df6efac08f96d0eaf1c00b0d530643d6f4d77333ea5e7a30cf946a213105770b8721fba981fb4e63dbca0ae0f188604881c2f1684ce9394f1f1fee6e66be3dce9633e0d516409c4f2961976e5067eadcb6c2172418accbc5379197049ca5ff19fd4831865e10a7631bd2f431388ae7e431e43e07c4f4ff3315116246ff1dfc0e844c21b173395bdc0a4ed29a641a691d6c8773c9ec09501affb9c1805bac562d8e610cf6c42dbb9bad25d5a13cb21020888492d6e7eb9a8aa198a379919f480ce8ac278a27dedb22ec2ef61877ab54130", 0x120, 0x1ff)
mkdir(0x0, 0x0)
chroot(0x0)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x3})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbdf13b9fd812eaa4e713048e69931929648", 0x14)


open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000240), 0xc)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000280)=[{0x2}, {0x3c}, {0x106}]})
socket(0x18, 0x1, 0x0)
socket(0x2, 0x2, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}, 0xf8ffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000200)={&(0x7f00000001c0)={0x0, 0x0, &(0x7f0000001880), 0x0, 0x0}}, 0x10, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
syz_emit_ethernet(0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x8040691a, &(0x7f00000001c0))
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000000c0)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
ktrace(0x0, 0x5, 0x40001b00, 0x0)
recvfrom$unix(r1, &(0x7f00000000c0), 0x832f1f7d, 0x0, &(0x7f0000000000)=@abs, 0x2000c600)
sendto$unix(r2, 0x0, 0x0, 0x0, 0x0, 0x0)


preadv(0xffffffffffffffff, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x2, &(0x7f0000000080)=[{0x7}, {0x34, 0x0, 0x0, 0x3}]})
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r1 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
mknod(0x0, 0x2000, 0x40000802)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000180)=[{&(0x7f0000000000)="9da8e3e9ed", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x2, 0x2, 0x0)
syz_emit_ethernet(0x36, &(0x7f00000004c0)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa0800450008000000000000009078ffffffffffffffff4e204e23", @ANYRES16=r1, @ANYRES32=r0, @ANYBLOB="5000000090780000"])
syz_emit_ethernet(0x36, &(0x7f0000000140)={@local, @broadcast, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @multicast2, @multicast1}, @tcp={{0x2, 0x2, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})
r3 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x200000000000a, &(0x7f0000000040)='\x00', 0x1)
r4 = dup(r3)
dup2(r4, r2)
connect$unix(r2, &(0x7f0000000000), 0x10)
sendmsg$unix(r4, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x0, 0x0, 0x10}, 0x0)


mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
munmap(&(0x7f0000400000/0xc00000)=nil, 0xc00000)
minherit(&(0x7f000097d000/0x3000)=nil, 0x3000, 0x0)


mknod(&(0x7f00000000c0)='./file0\x00', 0x2000, 0x0)
r0 = open(&(0x7f00000002c0)='./file0\x00', 0x0, 0x1b0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000140)={<r2=>0x0, <r3=>0x0, <r4=>0x0}, &(0x7f0000000180)=0xc)
r5 = getgid()
fchownat(r0, &(0x7f0000000080)='./file0\x00', r3, r5, 0x6)
r6 = msgget$private(0x0, 0x180)
msgctl$IPC_SET(r6, 0x1, &(0x7f00000001c0)={{0x1, r3, r5, r3, r4, 0x150, 0x3ff}, 0x100000001, 0x0, r2, r2, 0xffffffffffffffff, 0x100, 0xa72, 0x4})
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000100)=[{0x80}, {0x15}, {0x6, 0x0, 0x0, 0x88f0}]})
r7 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r7, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
kevent(0xffffffffffffff9c, &(0x7f0000000000)=[{{}, 0x0, 0x0, 0x0, 0x7}], 0x0, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x49}, 0x6, 0x0, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
mknod(0x0, 0x0, 0x0)
pwritev(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f00000005c0)="dc", 0x1}], 0x1, 0x4)
sysctl$kern(&(0x7f0000000080)={0x1, 0x54}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)
r8 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
writev(r8, &(0x7f0000000180)=[{&(0x7f0000000b80)="601d18253536eb523e1f2a212ea4747ae8f772b254cef012e37495473e3b32e7c512c940458bccbea2a8c0b69c3a728ae071ffc1e631e3ead047975e63b99bb38c1fcaea9d1115a547ebbd7af0e790eb27e93059a9b00640bb1f0f9f2e130217dc46a1d1841c879b6783da32600644c83f164d0d6778c3e4fc7b164d43d11232547d6a65d26d9cdb9873cb57ec7c8603b1e30879c60f4c3bbb910b6dbcea8be0ff7ea6d5c33c54f396a9d1175e0da830ded24cc9f1efa4424c3be70fdd261d44b9bb4a918c", 0xc5}], 0x1)


openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000ffc000/0x4000)=nil, 0x4000, 0x0)
getuid()
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
setreuid(0xee00, 0x0)
r1 = socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000029, 0x24, &(0x7f0000000000)="5ab7776a", 0x4)
setsockopt$sock_int(r1, 0xffff, 0x800, &(0x7f0000000180)=0x2, 0x4)
syz_emit_ethernet(0x52, &(0x7f0000000080)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaabb86dd60000000001c000080000000000000000000000000000000ff020000000000000000000000000001"])
r2 = getuid()
setreuid(0xee00, r2)
r3 = getpid()
ktrace(0x0, 0x1, 0x4000072c, r3)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000140)={0x4, &(0x7f0000000180)=[{}, {0x60, 0x0, 0x0, 0x5}, {0x6, 0x4, 0x0, 0x4000003}, {0x2, 0x81, 0x2, 0x80000001}]})
write(0xffffffffffffffff, &(0x7f0000000000), 0x0)
ioctl$BIOCGDIRFILT(0xffffffffffffffff, 0x4004427c, &(0x7f0000000200))
semctl$IPC_RMID(0x0, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000080)={0x4, 0x2, 0x0, 0x1b}, 0x4, &(0x7f00000000c0)="84f0", 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
ftruncate(r0, 0xfffffffeffffffff)
mlock(&(0x7f0000007000/0xc000)=nil, 0xc000)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r0, 0xc1126939, &(0x7f00000001c0))


syz_emit_ethernet(0x46, &(0x7f0000000200)={@random="7bca7e58f7cd", @empty, [], {@ipv6={0x86dd, {0x0, 0x6, "9f2844", 0x10, 0x2b, 0x0, @remote={0xfe, 0x80, '\x00', 0x0}, @remote={0xfe, 0x80, '\x00', 0x0}, {[@fragment={0x2b, 0x0, 0x20}], @udp={{0x1, 0x3, 0x8}}}}}}})
clock_gettime(0x67f3248105b4e004, 0x0)
syz_open_pts()
r0 = msgget$private(0x0, 0x0)
msgsnd(0x0, 0x0, 0x401, 0x0)
msgsnd(0x0, 0x0, 0x14, 0x0)
socket$inet(0x2, 0x0, 0x0)
msgget$private(0x0, 0xfffffffffffffffd)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
mquery(&(0x7f0000ffd000/0x1000)=nil, 0xfbd510af000, 0x0, 0x0, 0xffffffffffffffff, 0x0)
setreuid(0x0, 0xee01)
msgrcv(r0, &(0x7f0000000380)={0x0, ""/201}, 0xd1, 0x1, 0x2000)


socket(0x11, 0x3, 0x0)
sysctl$vfs_nfs(&(0x7f0000000180)={0xa, 0x2, 0x2}, 0x3, &(0x7f0000000300)="e9d5", &(0x7f0000000240)=0x2, &(0x7f0000000600), 0x0)
r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
writev(r0, &(0x7f0000000580)=[{&(0x7f00000001c0)='N', 0x1}], 0x1)
socket(0x0, 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$VNDIOCSET(r1, 0xc0384600, &(0x7f0000000500)={&(0x7f0000000480)='./file0\x00', 0x56, 0x0, 0x3e})


socket(0x2, 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000000), 0x20, 0x0)
ioctl$VNDIOCCLR(r1, 0x80384601, &(0x7f00000000c0)={&(0x7f0000000040)='./file0\x00', 0x6, &(0x7f0000000080)='./file0\x00', 0x8})
r2 = kqueue()
kevent(r2, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x5, 0x0)
getrusage(0x0, &(0x7f0000000480))
getsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x1, 0x0, 0x0)
mlock(&(0x7f0000674000/0x1000)=nil, 0x1000)
socketpair(0x18, 0x4, 0x7, &(0x7f00000000c0)={0xffffffffffffffff, <r3=>0xffffffffffffffff})
connect$unix(r3, &(0x7f0000000040)=@abs={0x1, 0x0, 0x2}, 0x8)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206919, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r4, 0x80104267, &(0x7f0000000280)={0x3, &(0x7f0000000240)=[{0x5c}, {0x45}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000140)=ANY=[])


setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0x0, r0)
r1 = socket(0x800000018, 0x2, 0x0)
setreuid(0xee00, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{r1}, 0xfffffffffffffffe}], 0x0, 0x0, 0x0, 0x0)
r2 = socket(0x800000018, 0x2, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x1000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff9000/0x2000)=nil, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffa000/0x2000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


r0 = syz_open_pts()
write(r0, &(0x7f0000000100)='@', 0x1)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000000)=0x8)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000180)=0x2)
execve(0x0, 0x0, 0x0)


poll(0x0, 0x0, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
close(0xffffffffffffffff)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000180)=[{0x34, 0x0, 0x0, 0x4000400}, {0x61, 0x0, 0x0, 0x8}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{}, 0xfeffffffffffffff})
r0 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
pipe(0x0)
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0206923, &(0x7f00000001c0))
ioctl$FIONREAD(r0, 0x8040691a, &(0x7f00000001c0))


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
connect$unix(r0, &(0x7f0000000300)=@file={0xd1653077bafa0114, './file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00'}, 0xff)


r0 = syz_open_pts()
r1 = syz_open_pts()
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r2 = syz_open_pts()
syz_open_pts()
r3 = syz_open_pts()
poll(&(0x7f0000000040)=[{r0, 0x84}, {r1}, {r1, 0xe65dc00084cf4bdf}, {r1}, {r2}, {r3}], 0x6, 0x800)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}, 0x0, 0x100000000})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff7b)
socket(0x2, 0x4001, 0x0)
r1 = socket(0x18, 0x1, 0x0)
r2 = socket(0x18, 0x1, 0x0)
setsockopt(r2, 0x1000000029, 0x36, &(0x7f0000000040)="03000000", 0x4)
r3 = dup2(r2, r1)
r4 = dup(r3)
r5 = fcntl$dupfd(r4, 0x2, 0xffffffffffffffff)
close(r5)
r6 = socket(0x18, 0x2, 0x0)
connect$unix(r6, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
setsockopt$sock_int(r5, 0xffff, 0x1023, &(0x7f0000000040), 0x4)
r7 = socket(0x2, 0x2, 0x0)
r8 = dup2(r6, r7)
connect$inet(r6, &(0x7f0000000080)={0x2, 0x3}, 0xc)
setsockopt$sock_int(r8, 0xffff, 0x1023, 0x0, 0x0)
r9 = geteuid()
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000280)={0xffffffffffffffff, <r10=>0xffffffffffffffff})
getsockopt$sock_cred(r10, 0xffff, 0x1022, &(0x7f00000001c0)={0x0, 0x0, <r11=>0x0}, &(0x7f0000000000)=0xc)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r11}})
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r12 = syz_open_pts()
close(r12)
r13 = syz_open_pts()
ioctl$TIOCSETA(r13, 0x802c7414, &(0x7f0000000000)={0x3006ff, 0x7, 0x9, 0xd, "fabafa588fc0001000000010000000001000"})
writev(r12, &(0x7f0000000040)=[{&(0x7f0000000180)="8a9ce4036307187ac8b8804f20f81b83c8ba79d72cbd641e690ca7f75c9e2ad2a284af6a5bf164e818358fefe887e8f8e172d17799657f41aec12efc5febc0ff437185b8532117c1000000002d21797f5acfba4e465810d918cb3e1cf8f06937c71e0b39f64012ce974526e31d1937376a87872c0b286508f6d774d8f5100b51a3275ddb218a808a", 0x88}], 0x1)
fchown(0xffffffffffffff9c, r9, r11)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r0, 0xc2585601, &(0x7f0000000040)={0x10, 0x0, [{&(0x7f0000fa1000/0x2000)=nil, &(0x7f0000ffa000/0x3000)=nil, 0xa000}, {&(0x7f0000ff6000/0x9000)=nil, &(0x7f0000ffc000/0x1000)=nil, 0x18000000000}, {&(0x7f0000ff8000/0x2000)=nil, &(0x7f0000fef000/0x11000)=nil, 0x41ff4000}, {&(0x7f0000fef000/0x2000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000feb000/0x9000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ff2000/0x3000)=nil}, {&(0x7f0000feb000/0x4000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {&(0x7f0000ff0000/0x1000)=nil, &(0x7f0000fec000/0x1000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ff4000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f0000ff5000/0x4000)=nil, &(0x7f0000fea000/0x3000)=nil}, {&(0x7f0000fe9000/0xf000)=nil, &(0x7f0000fee000/0x12000)=nil}, {&(0x7f0000fea000/0x4000)=nil, &(0x7f0000ff6000/0x3000)=nil}, {&(0x7f0000f8b000/0x3000)=nil, &(0x7f0000c2b000/0x3000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000e35000/0x2000)=nil}], './file0\x00'})


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg(r1, &(0x7f0000001980)={0x0, 0xa, &(0x7f00000017c0)=[{&(0x7f00000005c0)="57931731cc275c29b1aed3194c6f37430ae48885be99e6b3178c33b1b52f8fa3020763ade3e8010e64c4eb1290ead2acd688118cbcb7a7198705d6301f3cdb2808d786b455db1f997546e8359481b1fe28", 0x51}, {&(0x7f0000000640)="aaff4c51883e004b5f89075a5ddd67f3227908132e2bbca76867b831115dd2fee04f802fa2035c2cdce42602ad61953030e0ebbdf951b204afb415cb2d7571951eeb", 0x42}, {&(0x7f0000000700)="b573975435f384a446acefe3a9c8435fc53be209a95faaa9e582cdd3c8a869899283ef37e7a1f35b03048a939cff0bc18e0e95a0", 0x34}, {&(0x7f0000000740)="9e4673eb165000ef76574090ce780f20f8b3e79fc550b83c59ae6a9ec6fd01a2e59aba4cc2c70ff2a43ae8a76577758607271189d73e487865d275ca686b14c7249ef2619b5f3d2c15c4a57f1c3a996c0883b491a712ac372d1291b0d5f5c7ead631680269803c3482f368433f4fcece46f6d75471dff907485ff9e2387b4176556545f30ed78986606d1978acd39b868a25527876e5cc072759a0554e03861ada163f81da92278fc73629d7dd0387d37a96dc697e8aabe0bcc153b25acbabe29a1647a5e0f5235b27dd78d2416cc009f872b8d6852aa75da7c7f82dadb665a0a80d2913a6bba7c27c8ce847210f4c3816c99e1a052f15fb31599895e397056f829b926e6a4ce87517672405d2d2d50159fecb1d1cd147cff8bf3ef7b6cc5153c400969f40ac355404a1272f154a2ad345b3941adffe2a46650748f324949f6b9f08dee388bf5d506b90032a033c80ef0f3951e85a9e699b0c2711f6514800127e02de69679da02ad79b49301f01c351e863f9ad1a5a157131f57e83f15bc9753ddf9acfb3650705aa38664a3acb9273427dc16ea5bdaba2d2d0a45d82905b2144230c069003187ebc56e84358566633fdc3174de59f7d3a1fb109d5ad66151390313ef5f18361dbfff99c7bba31515f387536e01a26dd58efa98f77fa04b803b4f8bf095ec32af2bc31cf528a8b1d59c322163d42d2784f2ae34519587fe14a18654acdbd098c42d8167f9a42442c359f63864f67bcffec24cb7def3347446b1f455c7b1d9d6b7c856b57932daa51f59a70f0794809ef95193f8430d974f5d4b9c78067e28767b4d9e8f67fdac688fa6fa492728088cb1fdf7925a30159501e35822468395b8ee0f24cb7df6f6068f8c565a2a4ba1fdaf9d9413a102d20a3a8eca2afbc752a4dbaac1a9de4fa66e2d19c4e69710dfcde6dd72002ceb64e93b71235df5dcee3e9c0667850c1981cfd63a4f8b5b4183d3a46904e07", 0x2bb}], 0x4, 0x0}, 0x0)
recvmsg(r0, &(0x7f0000000500)={&(0x7f0000000000)=@un=@abs, 0x8, &(0x7f0000000440)=[{&(0x7f0000000040)=""/113, 0x71}, {&(0x7f00000000c0)=""/151, 0x97}, {&(0x7f0000000180)=""/97, 0x61}, {&(0x7f0000000200)=""/253, 0xfd}, {&(0x7f0000000300)=""/120, 0x78}, {&(0x7f0000000380)=""/164, 0xa4}], 0x6, &(0x7f00000004c0)}, 0x8c0)


syz_emit_ethernet(0xba, &(0x7f0000000080)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaa"])
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x20001fffffffd})
r1 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
open$dir(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
r2 = kqueue()
kevent(r2, 0x0, 0x0, 0x0, 0x0, 0x0)
close(0xffffffffffffffff)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r3 = socket(0x18, 0x3, 0x3a)
setsockopt(r3, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r3, 0x29, 0x67, &(0x7f0000000140), 0xc)
syz_emit_ethernet(0x4a, &(0x7f00000000c0)=ANY=[@ANYRESDEC=0x0, @ANYRESOCT=r1])
msgget$private(0x0, 0x20)
pwritev(r1, &(0x7f0000000200)=[{&(0x7f0000000340)='>', 0x1}], 0x1, 0x0)
openat$vnd(0xffffffffffffff9c, &(0x7f0000000100), 0x8, 0x0)


ktrace(0x0, 0x0, 0x53e, 0x0)
nanosleep(&(0x7f0000000100), &(0x7f0000001740))
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000100), 0x1, 0x0)
fcntl$lock(r0, 0xb, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x80, 0x0)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000040))
open(0x0, 0x0, 0x0)
mknod(&(0x7f0000000180)='./bus\x00', 0x2000, 0xd01)
r2 = openat$vnd(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$VNDIOCSET(r2, 0xc0384600, &(0x7f0000000140)={&(0x7f00000000c0)='./bus\x00', 0x497, 0x0})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000040)=[{0x20}, {0x7c}, {0x1416}]})
syz_emit_ethernet(0x4e, &(0x7f0000000140)=ANY=[])


openat$diskmap(0xffffffffffffff9c, &(0x7f0000000000), 0x5de47d223fe74984, 0x0)
write(0xffffffffffffffff, &(0x7f0000000000)="24a608d334", 0x5)
r0 = socket$unix(0x1, 0x1, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f0000000000))
open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
semget$private(0x0, 0x1, 0x0)
sysctl$vm(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
listen(0xffffffffffffffff, 0x0)
pread(0xffffffffffffffff, 0x0, 0x0, 0x0)
mknod(0x0, 0x3a0914c44f7b202d, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$VNDIOCGET(r1, 0xc4104603, &(0x7f0000000540)={'./file0\x00'})


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f000002f000/0xd000)=nil}, {&(0x7f0000060000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000000000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ad4000/0x2000)=nil}, {&(0x7f000081b000/0xf000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000156000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f00004c1000/0x2000)=nil}, {&(0x7f0000148000/0x1000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
execve(0x0, &(0x7f00000002c0)=[&(0x7f0000000100)='tap'], 0x0)
r0 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r0, 0x8028698c, &(0x7f0000000100))


syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0x3, 0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
syz_emit_ethernet(0x4a, &(0x7f00000000c0)={@broadcast, @empty, [], {@ipv4={0x800, {{0xa, 0x4, 0x0, 0x0, 0x3c, 0x64, 0x0, 0x0, 0x0, 0x0, @empty, @empty, {[@timestamp={0x44, 0xc, 0x5, 0x1, 0x0, [{[@local={0xac, 0x14, 0x0}]}]}, @ra={0x94, 0x6}]}}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x1, 0x0)
connect$unix(r0, &(0x7f0000000000), 0x10)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1023, &(0x7f0000000080), 0x4)
shutdown(0xffffffffffffffff, 0x1)


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x7fff}, 0xc)


symlinkat(0x0, 0xffffffffffffff9c, &(0x7f0000000140)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/file0\x00')
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


close(0xffffffffffffffff)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x0, 0x0, 0x0)
r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
fchown(r0, 0x0, 0xffffffffffffffff)
open(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
execve(0x0, 0x0, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
r1 = socket$inet(0x2, 0x2, 0x0)
close(r1)
r2 = socket$inet(0x2, 0x2, 0x0)
dup2(r0, r2)
setsockopt$inet_opts(r1, 0x0, 0xd, &(0x7f0000000240), 0x0)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f00000000c0)='./file0\x00', 0x63)
setreuid(0xee00, 0x0)
r0 = getuid()
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000540)={<r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000100)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000180)=0xc)
chown(&(0x7f0000000080)='./file0\x00', 0x0, r2)
setreuid(0x0, r0)
chdir(&(0x7f0000000100)='./file0\x00')
unveil(&(0x7f0000000140)='./file0\x00', &(0x7f00000001c0)='c\x00')


mknodat(0xffffffffffffff9c, &(0x7f0000000100)='./file0\x00', 0x1000, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r1 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
ioctl$DIOCMAP(r1, 0xc0106477, &(0x7f0000000200)={&(0x7f00000002c0)='./file0\x00', r0})
close(r0)
acct(&(0x7f0000000140)='./file0\x00')


syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = dup(0xffffffffffffffff)
listen(r0, 0x0)
r1 = socket(0x2, 0x1, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x1, &(0x7f0000001340)="0315f1d89ec5a317a9357682", 0xc)
connect$unix(r1, &(0x7f0000000000), 0x10)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000002c0)={0x3, &(0x7f0000001080)=[{0x2c, 0x0, 0x0, 0x81}, {0x87, 0x0, 0x6}, {0x6, 0x0, 0x2, 0x3}]})
write(r0, &(0x7f0000000200)="b1c05b5fb165120a4224a763037a", 0xe)
ioctl$WSMUXIO_LIST_DEVICES(0xffffffffffffffff, 0xc1045763, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
r1 = socket$inet(0x2, 0x0, 0x80)
getsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000040), &(0x7f0000000080)=0x10)
wait4(0xffffffffffffffff, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
close(r2)
r3 = socket(0x18, 0x2, 0x0)
close(r3)
socket(0x18, 0x3, 0x0)
connect$unix(r3, 0x0, 0x0)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, 0x0, 0x3e}, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
mknod(0x0, 0x0, 0x0)
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, 0x0)
open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
recvmsg(0xffffffffffffffff, 0x0, 0x0)
preadv(0xffffffffffffffff, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r4 = socket(0x2, 0x3, 0x0)
bind(r4, &(0x7f0000000000), 0x10)


msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x95}})
r0 = socket(0x11, 0x3, 0x0)
setsockopt(r0, 0x11, 0x4, 0x0, 0x0)
r1 = socket(0x18, 0x1, 0x0)
getsockname$inet(r1, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
r2 = socket(0x2, 0x3, 0x0)
r3 = socket(0x18, 0x2, 0x0)
dup2(r3, r2)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{0x0, 0x0, 0x0, 0xfffffffd}, {0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x27}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x8)
r4 = socket(0x18, 0x1, 0x0)
close(r4)
sendmsg(0xffffffffffffff9c, &(0x7f0000000400)={&(0x7f0000000040)=@un=@abs={0x1, 0x0, 0x3}, 0x8, 0x0, 0x0, 0x0}, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r5 = socket(0x18, 0x2, 0x0)
setsockopt(r5, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


mknod(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
close(r2)
fsync(r2)
r3 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r3, 0xc0206921, &(0x7f00000001c0))
r4 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r4, 0xc0206923, &(0x7f00000001c0))
r5 = open$dir(&(0x7f0000000080)='./file0\x00', 0x402, 0x0)
writev(r5, &(0x7f0000000340)=[{}], 0x1)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
ftruncate(0xffffffffffffffff, 0xf869)
socket$unix(0x1, 0x5, 0x0)
shmget$private(0x0, 0x3000, 0x4, &(0x7f0000ffb000/0x3000)=nil)
r6 = semget$private(0x0, 0x7, 0x3c0)
semop(r6, &(0x7f0000000180)=[{0x3, 0x43, 0x1800}, {0x1, 0xfffe, 0x1800}, {0x0, 0xfd, 0x1000}, {0x1, 0x20, 0x1800}, {0x2, 0x5, 0x1800}, {0x4, 0x9e}, {0x0, 0x40, 0x3800}, {0x3, 0x8}], 0x8)
semctl$SETALL(r6, 0x0, 0x9, &(0x7f00000004c0)=[0x9, 0x1001])
semctl$IPC_SET(r6, 0x0, 0x1, &(0x7f0000000240)={{0x0, 0xffffffffffffffff, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x2}, 0x0, 0x2000000009, 0xe7})
semctl$GETNCNT(r6, 0x0, 0x3, &(0x7f0000000280)=""/108)
mprotect(&(0x7f00001bc000/0x1000)=nil, 0x1000, 0x5)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x200, 0x0)
ioctl$BIOCVERSION(0xffffffffffffffff, 0x40044271, 0x0)
r7 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r7, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})


mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x10205b1a)
open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)
mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x205b9a)
open(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)


setuid(0xffffffffffffffff)
r0 = getppid()
ktrace(0x0, 0x5, 0x40000d30, r0)


syz_open_pts()
dup(0xffffffffffffffff)
sysctl$kern(&(0x7f0000002480)={0x1, 0x4}, 0x2, 0x0, 0x0, 0x0, 0x0)
openat$pci(0xffffffffffffff9c, 0x0, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000340)={0x3, &(0x7f0000000240)=[{0x81}, {0x48}, {0xe6}]})
syz_open_pts()
syz_open_pts()
syz_open_pts()
syz_extract_tcp_res(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000300)={0x3, &(0x7f0000000140)=[{0x7}, {0x28}, {0x416}]})
openat$wsmuxmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
write(r0, &(0x7f00000001c0)="d9537abde93d050cdd16b13f742a", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000080)=[{0x45}, {0x3}, {0x8006}]})
syz_emit_ethernet(0x1db, &(0x7f00000007c0)=ANY=[])


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{}, {0xdad}, {0x2, 0x0, 0x0, 0x3}]})
syz_emit_ethernet(0x0, 0x0)
r0 = semget(0x3, 0x0, 0x0)
setreuid(0x0, 0xee01)
syz_extract_tcp_res$synack(&(0x7f0000000200), 0x1, 0x0)
r1 = socket(0x800000018, 0x1, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0xffffffffffffffff}})
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
semop(r0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
mkdir(0x0, 0x0)
mkdir(0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
setitimer(0x1, 0x0, 0xffffffffffffffff)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000040)})
sysctl$vm_swapencrypt(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000240)={0x1, 0x15}, 0x2, &(0x7f0000000340)="a7e469d0f86ae9ce2404f75e3d390fdd5897e1a326b83d313c4949470a38de26ebe276f4236b0bba4bff63dbee0bda112e6a867a3dc2b7cd6859be1e5835a34c5011eea1619a4e84d2088fc647dfd606b8741f654ba6229ff758869730e1214ee78f6f162602bd41e3c7", &(0x7f0000000300)=0x6a, &(0x7f0000000340), 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r2 = msgget$private(0x0, 0x0)
msgsnd(r2, &(0x7f0000000100)=ANY=[@ANYRES64], 0x107, 0x0)


open$dir(0x0, 0x80, 0xa7)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
fchownat(r0, &(0x7f0000000040)='./file0\x00', 0x0, 0x0, 0x6)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCGDIRFILT(r0, 0x4004427c, &(0x7f00000013c0))
connect$unix(0xffffffffffffffff, &(0x7f0000001640)=@abs={0x4c7159b78e7a23cd, 0x0, 0x1}, 0x8)
r1 = socket(0x2, 0x1, 0x0)
execve(0x0, 0x0, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x8, &(0x7f0000000200), 0x4)
syz_emit_ethernet(0xe, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000000)={0x6, 0xb, 0x2}, 0x5, &(0x7f0000000500), 0x0, 0x0, 0x0)


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
madvise(&(0x7f00003e0000/0x1000)=nil, 0x1000, 0x0)
msync(&(0x7f00003e0000/0x2000)=nil, 0x2000, 0x2)


r0 = socket(0x2, 0x2, 0x0)
connect$unix(r0, &(0x7f0000000a80), 0x10)
r1 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x9, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000000)=[{{r1}, 0x0, 0x0, 0x0, 0x3, 0x100000000000000}], 0x0, 0x0, 0x0, 0x0)
r2 = socket(0x11, 0x3, 0x0)
setsockopt(r2, 0x11, 0x2, &(0x7f0000000000), 0x4)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x3, 0x0, "0100012d29fb000700000000098002005e00"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0x4, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0xfffffffffffffe37)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r3 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7949)
writev(r3, &(0x7f00000000c0)=[{&(0x7f0000000080)='#!', 0x2}], 0x1)
write(r3, &(0x7f0000000040)="0920e80000007c60e1016745b65369db00000000ebbd07a90172c84c838b4278ad535c39413f308cbbaee4ffcb7f31dbd1562eb77b6a0a", 0x37)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
r4 = socket(0x2, 0x1, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$inet(r4, &(0x7f0000000000), 0x10)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100))
sendmsg(0xffffffffffffffff, &(0x7f0000000380)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000280)=ANY=[@ANYBLOB="10004a73e94e5c719158000000000000"], 0x10}, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
r0 = socket$inet(0x2, 0x2, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x1025, &(0x7f0000000100), &(0x7f0000000040)=0xfffffffffffffd96)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
ioctl$PCIOCREAD(0xffffffffffffffff, 0xc0107002, 0x0)
symlink(0x0, &(0x7f0000001440)='./file0\x00')
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
sysctl$kern(&(0x7f0000000300)={0x1, 0x9}, 0x2, 0x0, 0x0, &(0x7f0000001440)="00000100", 0x4)
writev(0xffffffffffffffff, &(0x7f0000000300)=[{&(0x7f0000000400)='on', 0x2}], 0x1)
r1 = syz_open_pts()
getsockname$inet(r0, &(0x7f0000000080), &(0x7f00000000c0)=0xc)
ioctl$TIOCCONS(r1, 0x80047462, &(0x7f0000000000)=0x7)
syz_open_pts()
syz_open_pts()


clock_getres(0x3, &(0x7f0000000340))
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x20, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{0x74}, {0x2}, {0x46, 0x0, 0x40}]})
r1 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
socketpair$unix(0x1, 0x0, 0x0, &(0x7f0000000380)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
setsockopt$sock_int(r3, 0xffff, 0x1004, &(0x7f0000001140), 0x4)
r4 = socket(0x11, 0x3, 0x0)
setsockopt(r4, 0x0, 0x4, &(0x7f0000000000), 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r1, 0x80105728, &(0x7f0000000080)={0x0})
select(0x40, &(0x7f0000000100)={0xfffffffffffffffd, 0x0, 0x0, 0x3, 0x0, 0x0, 0x1000000010}, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000001a80)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x0, 0x0})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
sysctl$net_inet_gre(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$vm(&(0x7f0000000000)={0x4, 0x2}, 0x7, &(0x7f0000000040)="c06d154be3aee5f8787f8b9cda7554335b763bb5deea5ccecb4d1b57a9f6fa18e47fc7b119db587e58811e666e84a806495b45c36164bd5b135280243ed0a01466056e93082876ba33ee8cf2b0b3907f236f38175101000000d7e39544aea098d19ee63d03cbf92380dbe904538135f09e408bbe17a54a364b04ee64b0ad54e6d4e38114ced38c328aff2e224239ba29eb0796e8c3e8344a2cd9e663bb21035ebf391872f3015c164556e4a5b966122c56edd85fc996f12fa1b92e47aa", 0x0, 0x0, 0xfffffffffffffe8f)
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
getrlimit(0x3, &(0x7f0000000240))
bind(0xffffffffffffffff, 0x0, 0x0)
open(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1004, &(0x7f0000000040), 0x4)
pwritev(0xffffffffffffffff, &(0x7f0000000080), 0x0, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x3d}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)
syz_extract_tcp_res(&(0x7f0000000000), 0x0, 0x0)
open(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000001c0)=[{0x54}, {0x81}, {0x8106}]})
syz_emit_ethernet(0x62, &(0x7f0000000140)=ANY=[])


getitimer(0x0, 0x0)
r0 = socket(0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
setrlimit(0x2, &(0x7f0000000980)={0x60000000, 0x60000000})
r1 = syz_open_pts()
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{0x5}, {0x81}, {0x8046}]})
syz_emit_ethernet(0x2a, &(0x7f00000000c0)=ANY=[])
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYRESHEX=r1], 0x9}, 0x0)
writev(0xffffffffffffffff, &(0x7f00000000c0)=[{&(0x7f0000000000)="8d6bb85551ec8430", 0x8}], 0x1)
r3 = socket(0x2, 0x1, 0x0)
pwritev(r3, 0x0, 0x0, 0x3)
ioctl$FIONREAD(r3, 0x80206979, &(0x7f0000000000))
close(r1)
r4 = syz_open_pts()
writev(r1, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)
ioctl$TIOCSETA(r4, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, "070000010000fbff00e6ff20a1ec7500"})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r5 = semget$private(0x0, 0x4, 0x42)
semctl$SETVAL(r5, 0x4, 0x8, &(0x7f0000000140)=0x2)
getsockopt$SO_PEERCRED(r3, 0xffff, 0x1022, &(0x7f0000000140)={0x0, <r6=>0x0}, 0xc)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000200)={0x0, 0x0, <r7=>0x0}, &(0x7f0000000240)=0xc)
getsockopt$SO_PEERCRED(r3, 0xffff, 0x1022, &(0x7f0000000940)={0x0, <r8=>0x0}, 0xc)
semctl$IPC_SET(r5, 0x0, 0x1, &(0x7f00000002c0)={{0xfffffff9, r6, r7, r8, 0x0, 0xa0, 0x2}, 0x80000000, 0x528})
getitimer(0x2, 0x0)
r9 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCGBLEN(r9, 0x40044266, &(0x7f0000000040))
ioctl$BIOCLOCK(r9, 0x20004276)
ioctl$FIOASYNC(r9, 0x8004667d, &(0x7f0000001600))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
r1 = shmget$private(0x0, 0x2000, 0x40, &(0x7f0000ffd000/0x2000)=nil)
r2 = getuid()
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000000c0)={0x0, 0x0, <r3=>0x0}, &(0x7f0000000140)=0xc)
r4 = geteuid()
r5 = getgid()
r6 = socket(0x1, 0x1, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r7 = socket(0x18, 0x3, 0x3a)
setsockopt(r7, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r7, 0x29, 0x66, &(0x7f0000000100)={0x0, 0x0, 0x78, 0x1, 0x7f}, 0xc)
r8 = socket$inet(0x2, 0x4002, 0x0)
r9 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r9, 0x0, 0x200000000000c, &(0x7f0000000080)="eaef125c00000000", 0x8)
dup2(r8, r7)
fcntl$setstatus(r6, 0x4, 0x40)
r10 = getpgid(0x0)
fcntl$setown(0xffffffffffffffff, 0x6, r10)
r11 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r11)
ktrace(&(0x7f0000000140)='./file0\x00', 0x0, 0x4, r11)
ktrace(&(0x7f0000000280)='./file0\x00', 0x4, 0x928, r11)
shmctl$IPC_SET(r1, 0x1, &(0x7f00000001c0)={{0x7, r2, r3, r4, r5, 0x0, 0x2}, 0x0, 0x0, r10, r11, 0x2, 0x1ff})
wait4(r11, &(0x7f0000000240), 0x12, &(0x7f0000000400))
mknod(&(0x7f0000000180)='./bus\x00', 0x2000, 0x0)
open(&(0x7f0000000040)='./bus\x00', 0x0, 0x0)
unlink(&(0x7f0000000080)='./bus\x00')
ioctl$BIOCSDIRFILT(r0, 0x8004427d, &(0x7f0000000000)=0x597c)


r0 = kqueue()
kevent(r0, &(0x7f0000000280)=[{{r0}, 0xffffffffffffffff, 0xf5}], 0x7f, 0x0, 0x0, 0x0)
r1 = open$dir(&(0x7f0000000140)='.\x00', 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f00000001c0)=[{{r1}, 0xfffffffffffffffe, 0x41}], 0x0, 0x0)
kevent(r0, &(0x7f0000000000), 0x400, 0x0, 0xdb74, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
socket(0x800000018, 0x2, 0x0)
openat$vmm(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
r0 = socket$unix(0x1, 0x5, 0x0)
r1 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r1, 0x80105728, &(0x7f0000000080)={&(0x7f0000000040)=[{0x24}, {}], 0x2})
dup2(r0, r0)
r2 = socket$inet(0x2, 0x3, 0x0)
select(0x40, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4000000000}, 0x0, 0x0, 0x0)
r3 = openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
open(0x0, 0x200, 0x0)
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f0000000300)={0x2, &(0x7f0000000140)=[{0x3, 0x0, 0x9, 0x3}, {0x2, 0x4, 0x4, 0x1ff}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x33}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x18, 0x0, 0x37)
r4 = semget$private(0x0, 0x2, 0x0)
seteuid(0xffffffffffffffff)
socket$unix(0x1, 0x5, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
mknod(0x0, 0x2000, 0x0)
r5 = socket$inet(0x2, 0x0, 0x0)
semctl$SETVAL(r4, 0x0, 0x8, &(0x7f0000000640)=0x5)
setsockopt$inet_opts(r5, 0x0, 0x0, &(0x7f0000000240), 0x0)
socketpair(0x2, 0x1, 0xc, &(0x7f0000000000))
socket$inet(0x2, 0x0, 0x3)
dup2(r3, 0xffffffffffffffff)
syz_emit_ethernet(0x3f, &(0x7f00000005c0)=ANY=[@ANYRESOCT=r3])
open(0x0, 0x80000000000206, 0x0)
r6 = syz_open_pts()
ioctl$TIOCSETAF(r6, 0x802c7416, &(0x7f0000000000)={0x0, 0x0, 0x6, 0x7ffffffa, "2cf748460adb56e8dd42caee5275882ceece40cf", 0x1, 0xfffffff8})
ioctl$TIOCSTART(r6, 0x2000746e)
writev(0xffffffffffffffff, 0x0, 0x0)


openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x100000001})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x7fffffff, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000480)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
getpid()
syz_open_pts()
close(0xffffffffffffffff)
syz_open_pts()
syz_open_pts()
syz_open_pts()
kqueue()
setsockopt(r0, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


r0 = open(&(0x7f0000000180)='./file0\x00', 0x80000000000206, 0x0)
openat$vnd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r1 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000140), 0x782, 0x0)
r2 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
pwritev(r0, &(0x7f00000013c0)=[{&(0x7f0000000040)="4c1bd723b95c87aa5deffcfb1b", 0xd}, {&(0x7f00000000c0)="4a466c4360792252488887857627e4dc7fef24678f221cbefe1412e71482", 0x1e}, {&(0x7f00000001c0)="603b4ee7952dc41e7e8581ac6db2b9672456422ae0d70835af487277b12342844c2093d86c5a18957d7a80869b6df3aa851bcf3c578ed18a9f9558eaf0e5cd7fb5be26fec9dd0a3aebda84", 0x4b}, {&(0x7f0000000240)="ab84bce2fcd310602305f3710b172ee12ec0440b0fdaeef03484a410c09b3cc1b8421f1565fc1535bd60e16222f512ab02d555f2f004e0258a7429d7307752e730af92ccab4ef09336c8cd04fd859c026d005d26d56f3fad0bd2f9", 0x5b}, {&(0x7f00000002c0)="8c8dc12105d8052c04051282fb566ff1e9654f6fc120ee19fb89eae7531745ee4069e5b9bb7a007cece70a1ff068c34b90c3", 0x32}], 0x5, 0x1)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r2, 0x0)
ioctl$SPKRTUNE(r1, 0x20005302, &(0x7f0000000100))


sendmsg$unix(0xffffffffffffffff, &(0x7f0000001280)={0x0, 0x0, &(0x7f0000001200)=[{&(0x7f0000000180)="bf", 0x1}], 0x1}, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r0 = syz_open_pts()
close(r0)
getrlimit(0x3, &(0x7f00000000c0))
syz_open_pts()
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)
sysctl$vm_swapencrypt(&(0x7f0000000000), 0x3, 0x0, 0x0, &(0x7f0000000180), 0x4)
setitimer(0x0, &(0x7f0000000000)={{0x8000000000000000}, {0xffffffff}}, 0x0)
r1 = dup(0xffffffffffffffff)
setsockopt(r1, 0x1000000000029, 0xd, &(0x7f0000000000)="ffdaf64c000000004f0527000000050000000000", 0x14)
syz_emit_ethernet(0x36, &(0x7f0000000000)={@local, @empty, [], {@ipv4={0x800, {{0x8, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @multicast1, {[@rr={0x7, 0xb, 0x7, [@broadcast, @multicast2]}]}}, @udp={{0x1, 0x3, 0x8}}}}}})


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
getrlimit(0x0, &(0x7f00000002c0))
sysctl$kern(&(0x7f0000000300)={0x1, 0xb}, 0x2, &(0x7f0000000340), 0x0, 0x0, 0x0)
close(r0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r1, 0x80047460, &(0x7f00000000c0)=0x6)
writev(0xffffffffffffffff, &(0x7f00000004c0), 0x0)
syz_emit_ethernet(0x3a, &(0x7f0000000400)={@broadcast, @broadcast, [], {@ipv4={0x800, {{0xb, 0x4, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x0, 0x0, @empty, @remote={0xac, 0x14, 0x0}, {[@generic={0x88, 0x2}, @timestamp={0x44, 0x14, 0xb, 0x1, 0x0, [{}, {[], 0x1ff}, {[@loopback]}]}]}}}}}})


r0 = socket(0x2, 0x3, 0x2f)
r1 = dup(r0)
setsockopt$inet_opts(r1, 0x0, 0x22, &(0x7f0000000040)="fd0cc085", 0x4)
sendmmsg(r1, &(0x7f0000000580)={&(0x7f0000000540)={&(0x7f0000000200)=@in6={0x18, 0x2}, 0xc, 0x0, 0x0, 0x0}, 0x40}, 0x10, 0x0)


r0 = kqueue()
kevent(r0, &(0x7f0000000140)=[{{}, 0xfffffffffffffff9, 0x2c5d36d679bbff3f, 0x0, 0x100000000000001}], 0xe4a, 0x0, 0xa9fa, 0x0)


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000140)={0x1, &(0x7f0000000240)=[{}]})
syz_emit_ethernet(0x60f, &(0x7f0000000080)=ANY=[@ANYBLOB="aaaaaaaaaaaaf8de7d15ee9c86dd60516d1405d90000fe80000000000000070000000000ffbbff0200000000000000000000000000012c1081"])


r0 = semget$private(0x0, 0x4, 0x404)
semctl$SETVAL(r0, 0x2, 0x8, &(0x7f0000000000)=0x8)
semctl$GETALL(r0, 0x0, 0x6, &(0x7f0000000040)=""/218)
semctl$IPC_RMID(r0, 0x0, 0x0)
semop(r0, &(0x7f0000000140)=[{0x0, 0x6, 0x98cc884036f67b2f}, {0x1, 0x65ea, 0x1800}, {0x2, 0x1000, 0x800}, {0x0, 0x9db, 0x800}, {0x3, 0x7, 0x1800}, {0x4, 0x8, 0x1800}, {0x3, 0x4, 0x1800}], 0x7)
semctl$GETVAL(r0, 0x0, 0x5, &(0x7f0000000180)=""/108)
semctl$GETALL(r0, 0x0, 0x6, &(0x7f0000000200)=""/83)
semctl$GETPID(r0, 0x1, 0x4, &(0x7f0000000280)=""/27)
semctl$IPC_STAT(r0, 0x0, 0x2, &(0x7f00000002c0)=""/4096)
semctl$GETNCNT(r0, 0x0, 0x3, &(0x7f00000012c0)=""/211)
semctl$IPC_RMID(r0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000013c0), 0x20000, 0x0)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000001440)={0x2, &(0x7f0000001400)=[{0x0, 0x8, 0x1, 0x401}, {0x99c, 0x6, 0x4, 0x1}]})
semctl$IPC_STAT(r0, 0x0, 0x2, &(0x7f0000001480)=""/57)
semctl$GETZCNT(r0, 0x1, 0x7, &(0x7f00000014c0)=""/48)
r2 = getuid()
setuid(r2)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000001500), 0x80, 0x0)
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000001580)={0x4, &(0x7f0000001540)=[{0x5, 0xb8, 0x0, 0x6}, {0x6d5d, 0x3c, 0x7, 0x8000}, {0x1, 0x7f, 0x1, 0xff}, {0x80, 0x2, 0x60, 0x4}]})
getuid()
semctl$SETVAL(r0, 0x0, 0x8, &(0x7f00000015c0)=0x1)
getrlimit(0x2, &(0x7f0000001600))
semctl$GETNCNT(0x0, 0x4, 0x3, &(0x7f0000001640)=""/4096)
mknod(&(0x7f0000002640)='./file0\x00', 0x8, 0xff)
r4 = syz_open_pts()
ioctl$TIOCSPGRP(r4, 0x40047477, &(0x7f0000002680))
socket(0x18, 0x4, 0x1f)
mknod(&(0x7f00000026c0)='./file0\x00', 0x2, 0xff)
semctl$GETALL(r0, 0x0, 0x6, &(0x7f0000002700)=""/4096)
fcntl$setstatus(0xffffffffffffffff, 0x4, 0x4)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x8000, 0x9)
getpid()
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
fcntl$setstatus(r1, 0x4, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000000)={0x6, 0xb, 0x2}, 0x5, &(0x7f0000000500), 0x0, 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x1, 0x10, 0xffffffffffffffff, 0x0)
r2 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0106924, &(0x7f00000001c0))
recvmmsg(r0, 0x0, 0x0, 0x1802, 0x0)
r3 = socket(0x11, 0x3, 0x0)
sendto$unix(r3, &(0x7f0000000280)="b1000503000004000000000003000000331c13fecea10500fef96ec0c72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b1257aea8c500002002fbfe0c2300008abfba0900000008e371a3f8343712051eeab71d89e00004070000000013000000", 0xb1, 0x8, 0x0, 0x0)
madvise(&(0x7f0000000000/0x4000)=nil, 0x0, 0x4)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f0000000c80)={&(0x7f0000000c40)={0x0, 0x0, &(0x7f0000000bc0)=[{&(0x7f00000000c0)=""/67, 0x43}], 0x1, 0x0}}, 0x10, 0x0, 0x0)
r4 = socket$inet(0x2, 0x3, 0x102)
sendmmsg(r4, &(0x7f0000000c40)={&(0x7f0000000c00)={&(0x7f00000002c0)=@in={0x2, 0x3}, 0xfffffffffffffc46, 0x0, 0x0, 0x0}, 0x10}, 0x10, 0x0)
getppid()
recvmsg(r3, &(0x7f0000000380)={0x0, 0x0, &(0x7f0000000100)=[{&(0x7f0000000180)=""/204, 0xcc}], 0x1, 0x0}, 0x0)
sendmsg(0xffffffffffffffff, &(0x7f0000000380)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)
dup(0xffffffffffffffff)
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)
syz_emit_ethernet(0x42, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x34, 0x0, 0x1}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x1, 0x0, 0x8, 0x4, 0x2, 0x0, 0x233, {[@timestamp={0x8, 0xa}, @generic={0x4, 0x2}]}}}}}}})
syz_extract_tcp_res$synack(&(0x7f0000000000), 0x1, 0x0)
socket(0x2, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)


r0 = open$dir(&(0x7f0000000040)='./file0\x00', 0xae828e137847f62, 0x0)
r1 = open$dir(&(0x7f00000003c0)='./file0\x00', 0x400004000011830a, 0x0)
pwritev(r1, &(0x7f0000000340)=[{&(0x7f0000000080)='\x00', 0x8a8615b7}], 0x1, 0x126)
truncate(&(0x7f0000000100)='./file0\x00', 0x3802c)
setrlimit(0x1, &(0x7f0000000000)={0xfffffffffffffffd, 0xffffffffffffffff})
ftruncate(r0, 0x40000000000)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000680)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f00000000c0)=[{0x81}, {0x4}, {0x26}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = syz_open_pts()
write(r0, &(0x7f0000000100)='@', 0x1)
ioctl$TIOCDRAIN(r0, 0x2000745e)
execve(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000040)=[{0x1, 0x0, 0x0, 0x800}, {0x40}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])


r0 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
setreuid(0xee00, 0x0)
r1 = getuid()
chown(&(0x7f0000000180)='./file0\x00', r1, 0xffffffffffffffff)
r2 = getuid()
setreuid(0x0, r2)
r3 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r3, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


mknod(&(0x7f0000000000)='./bus\x00', 0x2000, 0x2e00)
r0 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
r1 = fcntl$dupfd(r0, 0x0, r0)
ioctl$VNDIOCSET(r1, 0xc0384600, &(0x7f0000000100)={0x0, 0x0, 0x0})


open$dir(&(0x7f0000000040)='./file0\x00', 0xae828e137847f62, 0x0)
setrlimit(0x1, &(0x7f0000000000)={0xfffffffffffffffd, 0xffffffffffffffff})
truncate(&(0x7f00000001c0)='./file0\x00', 0x7fffffffffffffff)


kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000140)={0x0, 0x0, 0xfffffffe, 0x0, "100000002300000000000000000000000200"})
writev(r0, &(0x7f0000000180)=[{&(0x7f0000000240)="bb", 0x1}], 0x1)
close(r0)
syz_open_pts()
r1 = syz_open_pts()
writev(r1, &(0x7f0000000180)=[{0x0}], 0x1)
execve(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f00000002c0)=[{0x7c}, {0x5}, {0x6}]})
syz_emit_ethernet(0xa5, &(0x7f00000004c0)=ANY=[])


sysctl$kern(&(0x7f00000000c0)={0x1, 0x3d}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x2, &(0x7f0000000000)=[{}, {0x2}]})
sysctl$vm(&(0x7f0000000000)={0x4, 0x1}, 0x3, &(0x7f0000000040)="c06d154be3aee5f8787f8b9cda7554335b763bb5deea5ccecb4d1b57a9f6fa18e47fc7b119db587e58811e666e84a806495b45c36164bd5b135280243ed0a01466056e93082876ba33ee8cf2b0b3907f236f38175101000000d7e39544aea098d19ee63d03cbf92380dbe904538135f09e408bbe17a54a364b04ee64b0ad54e6d4e38114ced38c328aff2e224239ba29eb0796e8c3e8344a2cd9e663bb21035ebf391872f3015c164556e4a5b966122c56edd85fc996f12fa1b92e47aa", 0x0, 0x0, 0xfffffffffffffd74)


syz_emit_ethernet(0x3a, &(0x7f0000000280)={@local, @broadcast, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x1, 0x0, @remote={0xac, 0x14, 0x0}, @local={0xac, 0x14, 0x0}, {[@ssrr={0x89, 0x3}]}}, @icmp=@timestamp}}}})


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047470, &(0x7f0000000140)=0x2)
ioctl$FIOASYNC(r0, 0x80047460, &(0x7f00000000c0)=0x4)
readv(r0, &(0x7f0000000200)=[{&(0x7f0000002140)=""/4112, 0x1010}], 0x1)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000100)={0x0, 0x0, 0xffffffff, 0x45ed, "f5ff1d6714525fe4b57d050000001a00"})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000002c0)={0x1, &(0x7f0000000140)=[{0x14}]})
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)
execve(0x0, 0x0, 0x0)


sysctl$net_inet_ip(&(0x7f00000000c0)={0x4, 0x2, 0x0, 0xe}, 0x4, 0x0, 0x0, 0x0, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x802069b4, &(0x7f00000001c0))


setuid(0xee01)
r0 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = kqueue()
kevent(r2, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
ioctl$FIONREAD(r0, 0x8040691a, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000140)=[{0x2c}, {0x50}, {0x6}]})
write(r0, &(0x7f0000000000)="7696e5f3d1f18c37cea8615ac7cf", 0xe)
ioctl$TIOCEXCL(0xffffffffffffffff, 0x2000740d)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$diskmap(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$DIOCMAP(0xffffffffffffffff, 0xc0106477, 0x0)
semctl$GETPID(0x0, 0x0, 0x4, 0x0)
semctl$SETALL(0x0, 0x0, 0x9, 0x0)
syz_open_pts()
openat$pf(0xffffffffffffff9c, 0x0, 0x0, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
socket(0x2, 0x3, 0x0)
openat$vnd(0xffffffffffffff9c, &(0x7f0000000200), 0x4a0, 0x0)
open(&(0x7f0000000180)='./file0\x00', 0x75f493fec6515f78, 0x0)
getppid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0xb32, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
pipe(&(0x7f0000000000))
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040))
setreuid(0x0, 0xee01)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000200)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000240)=0xc)
setregid(0xffffffffffffffff, r1)
select(0x40, &(0x7f0000000040), 0x0, &(0x7f00000000c0), &(0x7f0000000100))
r2 = socket(0x18, 0x1, 0x0)
setsockopt(r2, 0x1000000029, 0x2b, &(0x7f0000000000)="8c74", 0x2)
sysctl$net_inet_ip(&(0x7f0000000080), 0x4, &(0x7f0000000140)="e33745e84d5ebfb9cc2f7fa3a7f7891721720e69dac610a4fb5e8c3e3c6e1d648a8ca6ebc70f949c442aee9dc79e2cd74f4e106f382caf01ada3bc4efb0f6bc50690e5492f4a0491b1ea3359aa5c5164ad97ac7c3aadca05fd9e9a8c0f962f5167b69cfdc8287fc34b8138340e60c404a855858ea5fc", &(0x7f0000000000)=0x10045, 0x0, 0x0)
r3 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x200100000001d, &(0x7f0000000600)="37ee5c233f6ca01cbea0e2b8b21b48af2ac4100555a53d775edf0f84689e45fb527c85525c828e9965b037ef7b7b10dc6bd8a816defd35778568d8c783d361818c23bf89fc50a22d831d89aed718773afe7ae1142b05070a07c5f6be79210ebe7abe6eb37627310b6a51f0b050d7cb8c092ca81f05be40b949fa", 0x7a)
getsockopt$sock_cred(r3, 0xffff, 0x1022, &(0x7f0000000000), &(0x7f00000000c0)=0xc)
r4 = semget$private(0x0, 0x4, 0x266)
semop(r4, &(0x7f00000005c0)=[{0x2, 0x2, 0x1000}], 0x1)
r5 = socket$inet(0x2, 0x4000, 0xbd)
setsockopt$inet_opts(r5, 0x0, 0x200100000001d, &(0x7f0000000600)="37ee5c233f6ca01cbea0e2b8b21b48af2ac4100555a53d775edf0f84689e45fb527c85525c828e9965b037ef7b7b10dc6bd8a816defd35778568d8c783d361818c23bf89fc50a22d831d89aed718773afe7ae1142b05070a07c5f6be79210ebe7abe6eb37627310b6a51f0b050d7cb8c092ca81f05be40b949fa", 0x7a)
getsockopt$sock_cred(r5, 0xffff, 0x1022, &(0x7f0000000000), &(0x7f00000000c0)=0xc)
r6 = semget$private(0x0, 0x4, 0x266)
semop(r6, &(0x7f00000005c0)=[{0x2, 0x2, 0x1000}], 0x1)
semctl$SETALL(r6, 0x0, 0x9, &(0x7f00000002c0)=[0x3, 0xfff])


setrlimit(0x8, &(0x7f0000000040)={0x7, 0x50})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETAW(r1, 0x802c7415, &(0x7f0000000000)={0x0, 0x0, 0x100001f, 0xffffffff, "8b05000300da0078c3a3f4d3c900"})
writev(r0, &(0x7f00000013c0)=[{&(0x7f0000000240)="e35dbfeda71d80e5fa43a7683ebf074f330bd14903519d99401957f0a5d112adf0f7388c9bfa9c4496d0b78f7c1cfa8aec9dcc35204ac738cc8ce693bcfd2d7a97874115617f3ff5939a19e4fc06a51651ebe9f73dbb5bcf7667a21164ec882e89c1e3ea5ab46657b1096200aa773ad42623280cb88392e46ab068c67ad23813b135617603e66e2393b5aca44bd19edf041d2b5738b0e6d1c3b9dc67b23aae610512c4d0c10036028ad2e1dd1fc6ce9f80d467e9916b7efb0977945f229cc245a8526b1c2148ce321b47e23463b2790f89ce6301287997873500d08f19c7ba8e4609f7a396afca3ab7cb69318e1f876c4213478806b2700e78d961af0a5a8a7c4a973d8aaf635aaa873d8532fde2834bfb4218a1e985cfdda0ad28cd0dcbe666e7ee7d9996e3fb8c4c27f80ecc8bd3e6b64a72f659fec065cf954e8267300c4a4aaa8ad03ff7bee328e0da83634e2a8e018d67c0be51f78faefd207518de0f8f8ad364585ef996b72121ba54891334751b151d5564df556d9e4d8e600b0ebb6eac72fd88d58c67c5e3ee3e98e89aaed1b74e93e893ca6720b984a1ba0f8bf6815f4f8a8d5743819673e44f7b5ddf305bcc0fc8c3afa48b4fd82316bcf597b818748fd045346bd7f2caca69811aabd2cdcc32360bce9e0acbf98e943849ab2f946428218d83fc3a9cc03bf5b66a3e6d80ae7e47e03224be1b7626cd329f410fc5ae7d4e0e2fab30adef3057ead391a34470b5704ff362d628ff9324d50add8901029b190b292091c2acb88fddc6285fa9101692006ed749895dd65e7a4878089376f0d6abfd3a41dacaaef23c0289a2c6a1a0c85174ef070da190643e85c74d0eebc07b0edd3e36f2d355665f35202d439b5b1d67a9fb93d7d0791160269bc1256c54a1b94f0024eb3d55dc0a7d0598a80b78a71dd29cc43451c981fb9615154659f864f467d2c0fabad3699dc0b4a2476c4846c848b313f7fe15f6b367e60db91daffa237815fb3c593a24c0332f6bde3c9c9c88c8c65042a23291e35452bf83022ea93af13cc19e81a532e009e88a34b28f7f593e6acefe569da3a8f1189f7293724e09e0692648ee5703ecf96de190991567df7aada63a248390798796d64b97dcd19298c294f26fe2c7878783ec13cf669c4284c1a7c7c37c47a8a481b6a6b308ba29af39110055c607ec9acfe44ba6bd78dc5e6e48b9b42c5dfd968d05ed5ede2a78b4cf9a8e4b27c261210813495004626594ad1cd6a0fb22732a1c87143118f5b34ba487e0fec988deecf981776fdf4afbb80f66f4818cd8443b8a50e3539648e615907fed142b4ce44ac1a316d3c0b922455f626ef8da49817bd0442c1bd1a0a5c2de6a3519b86a7fc79c5b29ce3a045e02cd839a89e79b2fceef9d185039247115308c3330e1cb7a7e022477d296163c05585c7b222260416cff69ea843d1cd79dbf0041e3a518008721746c825b36fdad6bb8ff6b0414f884b186551f6a5b9b4b51a071048d05aa255963a37ecee7a030a38e8e80041a1033b618503bf0f3203fbf5e6802b833b2e711026424fae8ec4d6d55882623f9a72ea99593c9f5cca8888e1b38ea0b16318f39d176a2ce2e1eda8bf79a216ffccd3faa0916e46a0f8c852570c98f2fd9e99b8ac5972bc418648b942ee4b65c44d057f48df868468a4736f9ea30a273c8dacddd51f1831be7bdd61c9e217d786ad1ac98cf8fd74ecf96617c5235c35e3a7ea2a913df8838384aa055b53bae2b19901a88c1c87d70f4535e27b9c1f066f119346797a991f756f70eda64defcb1dd618f93497d70378b7e0fc553174f8bc021f60e47d632cb06658ab1b7fe57d9587fe795da911c7c7fae13a9a7113a8fc44828f090c2f2bcf324629b9343a3967059fce5dd66d12808d9ddf2410f34b2e424f8beebcbe0bb4a318a0dbeb405a56024ca868395d67303c95674b643e02a10f2140f3a2ea930d546562fc83fbb7a859dc7658568527460c7e06f7d667ce8f783502bbdd97c80ad944d2ced3346d6d87d6a513179a0e5edc79d9d9584abbe49de9f3b4034b5e023e8b67fb39e5c00715f68d3caafd0ad949b8c71abe94940da8bdabfe1209439b363447d52f230e5d1659b29be45f77dec84ef2836b4053609058a9c0031a7c76bac63c51c3a4dc8aa2ca3854aeb3fdade6b888ec8780a4995272333aa1c3d2959d1de71334bf2990d3cf13a3b62a7d370c944f5e6d0b7c259201c43bea9cc21da817c974331f9d6be9338c608e0fb172e0954eecfc3246e10ee5c205cb0fde8640e323a6e643194f4512362a86f08fd92e8f08b4fa1591ea6e8453ff306f10c71b0340e732147f52394a49b655a9904cc2097f6a0cdcdc124abf72b0903", 0x690}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000240)=[{0x40}, {0x3}, {0xe}]})
syz_emit_ethernet(0x3e, &(0x7f0000000140)=ANY=[])


mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
unveil(&(0x7f0000000300)='./file0/file0\x00', &(0x7f00000002c0)='r\x00')
open(&(0x7f0000000140)='./file0/file0\x00', 0x611, 0x0)


r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f0000000000))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbdf13b9fd812eaa4e713048e69931929648", 0x14)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000240)=[{0x84}, {0x4}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f00000001c0)=ANY=[])


sysctl$kern(&(0x7f0000000040)={0x1, 0x18}, 0x2, &(0x7f00000000c0), 0x0, 0x0, 0x0)
r0 = socket$unix(0x1, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x40004, &(0x7f0000000100), 0x53)
r1 = msgget$private(0x0, 0x400)
writev(0xffffffffffffffff, 0x0, 0x0)
r2 = socket$unix(0x1, 0x2, 0x0)
writev(r0, &(0x7f0000000040), 0x0)
mmap(&(0x7f0000000000/0x4000)=nil, 0x4000, 0x1, 0x4011, r2, 0xfffffffffffffffd)
ioctl$FIONREAD(r2, 0x80206979, &(0x7f0000000000))
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
sysctl$kern(&(0x7f0000002240), 0x2, 0x0, 0x0, 0x0, 0x0)
ioctl$FIOSETOWN(0xffffffffffffffff, 0x8004667c, 0x0)
close(0xffffffffffffffff)
msgrcv(r1, 0x0, 0x0, 0x2, 0x0)
setuid(0xee01)
r3 = socket(0x0, 0xe006, 0x2d)
ioctl$FIONREAD(r3, 0x8020699b, &(0x7f00000001c0))
setsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000340), 0xc)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
sendto$unix(r2, &(0x7f0000000200)="a77b4c7e82248b7ea53ba5918a69ef5bcfdadc3bbb2f3edeab504d69227101a6a5752769a29f46428c5231f1bf6e84afcad6543d4e7a06cd4d79521669c0089027dea57788c6aa15604cffb8d09551c4728969bc33c551310d644a9e47dae9c356136ab18b2db09edc8ca359f4d52e3d0bb5b85ef99beeae4940961c9da4edf1a99e75bf1c7932f923b6ea6f816c629558b5384bd1f9c5ee97c86b1e185841abeb603d8bc2b160c67d967744d838581d06f0c4974473bce0fbf6d21d03226bc2c4da09c36efe9b23400fb565e3f022a9721c5060dd2a", 0xd6, 0xa, &(0x7f0000000300)=@file={0x1, './file0\x00'}, 0xa)
getgid()
msgctl$IPC_SET(r1, 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{0x5}, {0xc}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r1 = socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = kqueue()
kevent(r2, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r3 = socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0xa, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
setsockopt(r3, 0x1000000000029, 0xa, &(0x7f0000000040)="000001ad", 0x4)
r4 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r4, 0x8020697f, &(0x7f00000001c0))
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000240))
mknod(&(0x7f0000000180)='./file0\x00', 0x1000, 0x0)
r5 = open(&(0x7f0000000040)='./file0\x00', 0x1, 0x0)
r6 = open(&(0x7f0000000000)='./file0\x00', 0x2f2, 0x0)
ioctl$BIOCVERSION(r6, 0x40044271, &(0x7f00000000c0))
poll(&(0x7f0000000080)=[{r5, 0x7d}], 0x1, 0x0)


r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x24, &(0x7f0000000000)="5ab7776a", 0x4)
syz_emit_ethernet(0x4a, &(0x7f0000005c40)={@random="69e1629b6174", @remote, [], {@ipv6={0x86dd, {0x0, 0x6, "6b9efb", 0x14, 0x50, 0x0, @rand_addr="cb69bc83c1677a656ab420666c3e2c6f", @local={0xfe, 0x80, '\x00', 0x0}, {[], @tcp={{0x3, 0x2, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}}})


syz_emit_ethernet(0x6a, 0x0)
r0 = syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000000)={0x9, 0x800000, 0x80000000, 0xfffffffe, "cb00a6c8d30000000062ecff6a2129fe8d008500"})
write(r0, &(0x7f0000000200)="11d5fe656a", 0x5)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)
mprotect(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x82d)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000))
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f00000000c0)={0x0, 0x0})
sysctl$vm_swapencrypt(0x0, 0x0, &(0x7f0000000140)="118bea625d95de8f92c010baed45ec4bf03ace254b57973bb6de7b1c90301e9d3b5e6fb6ffffffffffffffff76c775a2a4e0556565a830032eef776127fd247103c14ab0a1cea9b4593be484f46a02ea73e910d041c5777bd852e57d3248832b91d06fe47d126022a1654859149e9486306d2f11fb1cc826c42f81b0d114f8af4ceb029a5210bb6947464bf678ba1d64a20131", 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x1, 0x2, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f00001d8000/0x4000)=nil, &(0x7f0000ff3000/0x2000)=nil}, {&(0x7f0000ff0000/0x10000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f000015f000/0x9000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ff3000/0xa000)=nil}, {&(0x7f0000ff2000/0x3000)=nil, &(0x7f000009f000/0x2000)=nil, 0x7ff}, {&(0x7f0000181000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f0000ff4000/0x4000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f00001f4000/0x2000)=nil}, {&(0x7f0000ff8000/0x1000)=nil, &(0x7f0000ff9000/0x6000)=nil, 0x4}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f000009f000/0x4000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000084000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000161000/0x4000)=nil, &(0x7f0000163000/0x1000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r2, 0xc0286988, &(0x7f00000001c0))


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
r0 = open(&(0x7f0000001780)='./file0\x00', 0x0, 0x0)
setreuid(0x0, 0xee01)
ioctl$TIOCSPGRP(r0, 0x40047477, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f00000000c0)={0x0, 0xfffffffd, 0x9, 0x20351e, "040000000208008900"})
writev(r0, &(0x7f0000000000)=[{&(0x7f00000019c0)="d78f4edc41a11aee361b850b6e47f3fb1d4a3e1927d7928af6432b7cd0847f121d6b2fe543c0ee96bc3a37ce892b7ea8a33d12079cdf0ab0c8b0a2b5589ada2b8855f92c05ab9af08a7d1039674064662a6dcc46b76dfa369542938f1bd501ef6d29dcccb5a088b2d72a6b1ca042e1c1af87ea0b34a19fd1a27ce943401cc1c80e915f52a98dc81140b69b3f0f0bb40c884630535387812300db72e913aa29b84993ba89d4e6a82c3c559cc774c9d0525aafeb14c12f18e1ee71bc707e4c0efd3afb7b6a29c49a07c8b5d2cc14b56d6d17ed6c6cd7002f55d4ef4c42582f21dd51a5e331b168ac36d22487581dc4b89b06ce796100dc5236e0d7e68132f6ed3ce820bc79f678cfd2e2b4b448868c017d6e3ad7a1151c26a8079bd3b17afb083d8152d139852ccf2ba99f706ec66cbe42a393dfe236c1b94b9e33e202abb74ea4224e96e0cdcfc48e61eb9369bfd2e461c23ba0ecda75bbe0f62abb7e67301d48808a71aa108842e0eb15d2c978dad3764b48f84f5685446ac2f0a452473e567c9cad46cef24942ca72eddd506b0862a2dbdbcac3822cad564486a02927cce70beed8980654156fc59b6fc64d34c3f327d27b5a66d3ae702fcb634d16c9395bed104df6a629c5efb6cbbdb351a80c5f451a9e31bc2bfed94193577e52d13bff2cd3ed5160f69f1cadcbd21d6ee99c5dc3f18c75d81efcb8392a0313ec83c542c6033e6cd731b041fdc1703d5f647c929ef2add480ad3e2904", 0x218}], 0x1)


getgroups(0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000140)=[{0x64}, {0x30, 0x0, 0x0, 0x7fff}, {0xc12e, 0x0, 0x0, 0x2}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


open(&(0x7f0000000000)='./file0\x00', 0x78e, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
r0 = getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r0})
pipe(&(0x7f00000001c0)={<r1=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r1, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r2 = fcntl$getown(r1, 0x5)
ktrace(0x0, 0xe53a055dd4cd665d, 0xa24, r2)


syz_emit_ethernet(0x2e, &(0x7f0000000080)={@local, @local, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x1d, 0x0, 0x0, 0x0, 0x1, 0x0, @remote={0xac, 0x14, 0x0}, @rand_addr, {[@lsrr={0x83, 0x3}]}}, @icmp=@info_request}}}})
syz_emit_ethernet(0x138, &(0x7f0000000080)=ANY=[@ANYRES64])
syz_extract_tcp_res(&(0x7f0000000000), 0x6, 0x0)


chmod(0x0, 0x0)
syz_open_pts()
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000440)={0x1, &(0x7f00000000c0)=[{}]})
socket(0x0, 0x0, 0x0)
getrusage(0x0, &(0x7f0000000200))


fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
close(0xffffffffffffffff)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000240)=[{0x2d}, {0x64}, {0x6, 0x0, 0x0, 0x7}]})
syz_emit_ethernet(0x1019, &(0x7f0000000400)=ANY=[])


r0 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r0, 0x0, 0x64, &(0x7f0000000240)="0100", 0x2)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1021, &(0x7f0000000000), 0x4)
setsockopt$inet_opts(r1, 0x0, 0xc, &(0x7f00000000c0)="eaff125c0000e909", 0x8)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f00000000c0)={0x0, 0x1ff, 0x7, 0x820351a, "090e4de6d311a692318c7e0002f9ffffff1800"})
writev(r0, &(0x7f0000000100)=[{&(0x7f0000000000)="86f9d1b8aab772d6bf81d4c84c5c11fe", 0x10}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCGBLEN(r0, 0x40044266, &(0x7f0000000040))
openat$tty(0xffffffffffffff9c, &(0x7f00000000c0), 0x80, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x6381)
mknod(&(0x7f0000000000)='./bus\x00', 0x2000, 0x6380)
r1 = open(&(0x7f0000000140)='./bus\x00', 0x100, 0x0)
r2 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x4)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
r3 = socket$inet(0x2, 0x2, 0x0)
close(r3)
r4 = socket$inet(0x2, 0x2, 0x0)
dup2(0xffffffffffffffff, r4)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00", 0x2)
dup2(r2, r1)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000880)={0x0, 0xcd, 0x1ff, 0xd2a, "871ff9bdca0d88e03a90d692080d51aae100"})
writev(r0, &(0x7f0000000180)=[{&(0x7f0000000080)="94c799e845e3728fe0395644c7c6f150860233efecf56fa2bb0f2999f4a251fe7da7cd83d68bac3f0d30ad393b4b2de3c6929edefb3add71c81743bcd8ec9a614d7e07dbacfff921bf04ef41e1e0271c41eeef3a0cd94991cb4f132dce21af098e390915c193a2439927299c3e43184e588171b9000d", 0x8e}], 0x1)


r0 = socket(0x2, 0x2, 0x0)
r1 = dup(r0)
setsockopt$inet_opts(r1, 0x0, 0x16, &(0x7f0000000040)="fd0cc085", 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000300)={0x3, &(0x7f0000000080)=[{0x14}, {0x81}, {0x6}]})
syz_emit_ethernet(0x26, &(0x7f0000000280)=ANY=[])


open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7949)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
writev(r0, &(0x7f0000000280)=[{&(0x7f0000000000)='#!', 0x2}], 0x1)
write(r0, &(0x7f0000000180)="1e", 0x1)
writev(r0, &(0x7f00000002c0)=[{&(0x7f0000000080)=' ', 0x1}, {&(0x7f00000014c0)="20a95ca8769c0a", 0x7}], 0x2)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000980)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x30}, {0x48}, {0x16}]})
write(r0, &(0x7f0000000180)="7f23a3c23cce2575e1dd92c25683", 0xe)


setsockopt$inet6_MRT6_ADD_MFC(0xffffffffffffffff, 0x29, 0x1a, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x6000, 0xe02)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socket$unix(0x1, 0x0, 0x0)
ioctl$BIOCFLUSH(0xffffffffffffffff, 0x20004268)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, &(0x7f0000000000))
getpid()
socket$inet(0x2, 0x0, 0x0)
getsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
poll(0x0, 0x0, 0x0)
openat$wsdisplay(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffff9c, 0xc2585601, &(0x7f00000001c0)={0x10, 0x60000000000, [{&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil, 0x44a1}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff5000/0x3000)=nil}, {&(0x7f0000ff0000/0x2000)=nil, &(0x7f0000ff6000/0x4000)=nil}, {&(0x7f0000ff4000/0x1000)=nil, &(0x7f0000ff5000/0x2000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff4000/0x1000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000fee000/0x3000)=nil, &(0x7f0000ff2000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000fed000/0x13000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000fed000/0x2000)=nil, 0xe7}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ff9000/0x4000)=nil, 0x5}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ff4000/0x4000)=nil, 0x2}, {&(0x7f0000ff2000/0x3000)=nil, &(0x7f0000ff6000/0x2000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000ff7000/0x1000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ff9000/0x2000)=nil, 0x9}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000fff000/0x1000)=nil, 0x958}], './file0\x00', 0x1})
writev(0xffffffffffffffff, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f0000000140)={&(0x7f00000000c0)='./file0\x00', 0x5, 0x0})


socket(0x18, 0x3, 0x0)
socketpair$unix(0x1, 0x1, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
r0 = socket(0x2, 0x0, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
r1 = semget(0x0, 0x4, 0x1)
semop(r1, &(0x7f0000000040)=[{0x1, 0xf000}, {0x3, 0x7fff, 0x800}, {0x1, 0x6}, {0x0, 0x2, 0x1800}, {0x0, 0x6}, {0x1, 0x3, 0x1400}], 0x6)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
r2 = socket$inet(0x2, 0x3, 0x0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x4f4b)
r3 = socket(0x18, 0x2, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}, 0x0, 0x0, 0x6})
r4 = socket(0x18, 0x3, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r4, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmmsg(r3, &(0x7f0000000140)={0x0}, 0x10, 0x0)
dup2(r4, r3)
r5 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
close(r5)
setsockopt$inet_opts(r2, 0x0, 0x9, &(0x7f0000000240)="ea000001", 0x4)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
syz_extract_tcp_res(&(0x7f0000000180), 0x8, 0x7)
dup2(r2, r0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000700), 0x8000, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206919, &(0x7f00000001c0))


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x802069b2, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000140)=[{0x15}, {0x44}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000140)=ANY=[])


open(&(0x7f0000000040)='./file0\x00', 0xfffe, 0x0)
setreuid(0xee00, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000000c0)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000000)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000080)=0xc)
chown(&(0x7f0000000200)='./file0\x00', 0x0, r1)
chmod(&(0x7f00000000c0)='./file0\x00', 0x21e)
r2 = getuid()
setreuid(0xee00, r2)
r3 = open$dir(&(0x7f0000000040)='.\x00', 0x0, 0x0)
faccessat(r3, &(0x7f0000000100)='./file0\x00', 0x4, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000001c0)=[{0x44}, {0x6c}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000140)=ANY=[])


close(0xffffffffffffffff)
syz_open_pts()
writev(0xffffffffffffffff, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(0x0, 0x0, 0x0, 0x0, &(0x7f0000000180), 0x0)
setitimer(0x0, &(0x7f0000000000)={{0x0, 0x20}, {0xffffffff, 0x7a}}, 0x0)
mkdirat(0xffffffffffffff9c, &(0x7f00000005c0)='./file0\x00', 0x0)
r0 = open(&(0x7f0000000300)='.\x00', 0x0, 0x0)
mkdirat(r0, &(0x7f0000000340)='./file1\x00', 0x0)
rename(0x0, 0x0)
rename(&(0x7f0000000380)='./file1\x00', &(0x7f00000003c0)='./file0\x00')


setrlimit(0x8, &(0x7f0000000980)={0x9, 0x51})
r0 = syz_open_pts()
close(r0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
syz_open_pts()
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000a80)={0x0, 0x0, 0x0, 0x0, "061500000000000000000000000000004000", 0x0, 0xfffffffe})
writev(r0, &(0x7f0000000040)=[{&(0x7f0000000140)='H', 0x1}], 0x1)


socket$inet(0x2, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x200000000000c, 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ftruncate(0xffffffffffffffff, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)
mlockall(0x1)
open(0x0, 0x0, 0x0)
mmap(&(0x7f0000ffb000/0x4000)=nil, 0x4000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
setrlimit(0x3, &(0x7f0000000000)={0x7fff, 0x100000})


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0206923, &(0x7f00000001c0))
r1 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x80206913, &(0x7f00000001c0))


openat$tty(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$TIOCSBRK(0xffffffffffffffff, 0x2000747b)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000380), 0x10, 0x0)
lseek(r0, 0xffffffffffffffff, 0x1)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd02)
r0 = open(&(0x7f0000000240)='./bus\x00', 0x0, 0x0)
pread(r0, &(0x7f0000000040)="3cd15db7c30016", 0x50cc00, 0x0)
socket$inet(0x2, 0x0, 0x0)
r1 = socket$inet(0x2, 0x0, 0x0)
dup2(r1, 0xffffffffffffffff)
socket(0x0, 0x3, 0x0)
close(0xffffffffffffffff)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
open(0x0, 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000240)=[{0x60}, {0x1d}, {0x6}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000080)={0x0, 0x3ff, 0x9fd, 0x88c, "43b2b0bf3e79036980220d348bba04ff4e629aa0"})
writev(r0, &(0x7f0000000740)=[{&(0x7f0000000200)="71994c1de376a629d07b09610817554b444e03bbccd179a857389f23c8a50b91a62a5453774c410d", 0x28}], 0x1)


getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
chown(0x0, 0x0, 0x0)
chmod(0x0, 0x0)
setreuid(0x0, 0xee01)
r0 = shmget$private(0x0, 0x2000, 0x0, &(0x7f0000ffd000/0x2000)=nil)
shmctl$IPC_SET(r0, 0x1, &(0x7f0000000480)={{}, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0xfffffffffffffffc})
shmctl$IPC_RMID(r0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000980)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
shmget$private(0x0, 0x3000, 0x1dd, &(0x7f0000002000/0x3000)=nil)
shmat(0x0, &(0x7f0000001000/0x3000)=nil, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x7}, {0x4c}, {0x16}]})
write(r0, &(0x7f0000000180)="7f23a3c23cce2575e1dd92c25683", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f00000001c0)=[{0x54}, {0x87}, {0x8106}]})
syz_emit_ethernet(0x62, &(0x7f0000000140)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000180)=[{0x84}, {}, {0x6, 0x0, 0x0, 0xffe}]})
write(r0, &(0x7f0000000200)="d81ad3d20cf7eb4e9be33bbd1a30", 0xe)
syz_emit_ethernet(0x2a, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
r1 = socket(0x18, 0x3, 0x0)
close(r1)
r2 = socket(0x18, 0x3, 0x0)
setsockopt(r2, 0x1000000029, 0x0, 0x0, 0x0)
socket(0x11, 0x3, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r3 = socket(0x18, 0x3, 0x0)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7, 0x3}, 0x8)
getsockname$inet(r3, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
openat$vmm(0xffffffffffffff9c, &(0x7f0000000040), 0x20000, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
getpgid(0x0)
setgid(0x0)
rename(0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socket(0x0, 0x8000, 0x1)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x3}, {0x6}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0xffcc)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)
clock_settime(0x100000000000000, &(0x7f0000000040))
sysctl$net_inet_ip(&(0x7f00000001c0)={0x4, 0x12, 0x0, 0x23}, 0x982dec9bbccf05f9, &(0x7f0000000080)="8a8b3a0ec308aa65da413e78de0f43bc6ac34740b24886df93b2fd3ef33f633206f35226fcca84d1a3a8a889b420e280963d9a0f52e15475057900000000000000074dd57012c9c84c6995bd3665f7b0aa8afd48f408ce58844dd46a3bbe565c918cd845b69d8306e2477c253055bbb0dee951233f77921c8490e1a1bb3dda41165e82b971c997308f6c2b44a1a651b0b7f4f9f4a1b9247bc0186db5ec4271704db0d3d5641a3c954e728eec12120fa1e5e6a925c8fd2bcc00313c48", 0x0, 0x0, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
open(&(0x7f0000000180)='./file0\x00', 0x200, 0x0)
ktrace(&(0x7f00000000c0)='./file0\x00', 0xdd81e9da1aeb7b67, 0x40000034, 0xffffffffffffffff)


r0 = socket(0x18, 0x3, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1002, &(0x7f0000000180), 0x4)
syz_emit_ethernet(0x52, &(0x7f0000000080)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaabb86dd60000000001c000080000000000000000000000000000000ff020000000000000000000000000001"])


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
getpeername(r0, 0x0, &(0x7f0000000140))


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x0, 0x1f}]})
r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$PCIOCREAD(r0, 0xc0187009, &(0x7f00000000c0))


open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1, &(0x7f0000000040), 0x4)
r1 = dup(r0)
listen(r1, 0x0)


mknod(&(0x7f0000000040)='./file0\x00', 0x2000, 0x3200)
r0 = open$dir(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
preadv(r0, &(0x7f0000000000)=[{&(0x7f00000002c0)=""/82, 0x52}], 0x1, 0xffffffffffffffff)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
getrlimit(0x4, &(0x7f00000002c0))
sysctl$kern(&(0x7f0000000300)={0x1, 0x15}, 0x2, &(0x7f00000001c0)="d96882714f14db9b40948a8dad7f3052ecb86e60717bafe17a02d504b9c25f07ddddbcce19eeb71678ddbc32fdc2bfb7b00ddeae216825", 0x0, 0x0, 0x0)
close(r0)
r1 = syz_open_pts()
writev(r0, &(0x7f00000004c0)=[{&(0x7f0000000100)="97"}], 0x1)
writev(r0, &(0x7f0000000080)=[{&(0x7f00000009c0)="f941a3733444576b14802158e256a7c16dc37b02eeb94800591b3877b0cde7017caf7d0d3b7541f5d48364442828d19d7685a70ba71fed3158848f9a68bd6f3352d64a21c612e6eaad50cb9e4c8b43773f5f9b43a8aa980dbfd9502b6a34ee4976ad67f2d3d6919c36634a9eed8cbe26d0f87d897cbc091fc32cb21b559dd035fbe6b7765fcef72ca9d31451d6007b61d4e89ec015c7ecf401e9e98cdf9c5c5b1351644720d29c24dd2e9e017f85a12141e44ba2f260339f24381d113c634d9918daec904b75eac711a04c56ee5d4a9149185e2437d8d58e31245fdc52a0f0dfac13288b27ef57616ba55dac691005180d8d67799b5bbee3f7666657b024d2fee10e5be80a28c57f67186765dbe2ea606b620102d062cfee03d1f9410fc4115a1b90c347d103042ea3505f7f900c1ef1be52100394308863e0c555972d3214a0cb62a40b73a050f43ee3bb16c0f3a3ba4853c8bac0678f2477be6abe93e886b17c0538854cd7db840c46c5e1aa86d276ed94148a3553a70a0465a8aba7a9cea676e42c9b8b76e2164ede57d979cc8d20072f410b409ac8363ca7c47c9c884daf9e47f02ffa48d4b8a196ca10432b6a16e55ff8235a3709ae6da6918513832f1b81d6f10d29931a84665eede5643098edd8177e0d201467927b9137aa22441a9bb15e9a290a7989e3121e6daf028920d7833e0d14fb6b504d230e988e6e9fd8b278e4737c7d5641d258a534be01ac889cf64a3766c19f4f3adce393c70fa0aca2d777a519cda3e2e8465eab78249be23596ecab815fb89f1f998c28d84bfa776ecbe80e7cf7a460e147c881a338f5f8cb4ba6d12822b73bb75d6b845f96acfb9cfbebc7fdff17d3a3a499174c153aaaf375f807273f94d8349f44be75ae91874f266ba1500076497b8e69a9d0d47947452b1df0d3ba78a83a9add79bf96e8ffe0f75250081e2685758608461008e0008c0e398b99da93559392f1c235443174e1c34d52ccfaebd34011b7447f12d1a90013fe5f6eca33b2ddb118794282356694d3908edddc1841116590e30eab9ea6ee834f1eb0f0f66d8bcdfcaa4d4b5ee43428e7862de797902d7bc21017130fc01a97c38665ddb0f5650a76b770214f45a176e3da83dbab6660db293a82255a32f6bb359cddf2a231140ca63afd18157b8f48bf78d271b71a0ac5f73992e9501285fc3261aad7b5875748ad2032c70bf3d9daa68fdb50e836a2d0c5d06041810c66fffded9860ce05d6759edb26112695c5833840d92b44c37b84fec34e82cd8345a1366f358088da2940e300d602e81913a7d02963730b6de71d56f43ab33aa34733bf0c1070ad4afd34f0c6d9f98e927d91", 0x3c1}], 0x1)
ioctl$WSKBDIO_SETBACKLIGHT(0xffffffffffffffff, 0x800c5712, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
sendmmsg(0xffffffffffffffff, &(0x7f00000007c0)={&(0x7f0000000780)={0x0, 0x0, &(0x7f0000000440), 0x0, 0x0}}, 0x10, 0x0)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x3a, &(0x7f0000000440)=ANY=[@ANYRESHEX=0x0, @ANYRESDEC=r0, @ANYRESHEX, @ANYRESHEX=r1, @ANYRES32=r0, @ANYRES16])
open(&(0x7f0000000180)='./file0\x00', 0x70e, 0x0)
syz_emit_ethernet(0x138, &(0x7f00000003c0)=ANY=[@ANYBLOB="4767f39f460a8b3ba0280d1e252d4533ac70030b3fe044dcf801084955e3e91fd52479d8b14eaafeed2fd5eedc2f6c95d8e830895edc323a78d56cf282171ca5be0ac424f3a74c80fbcb71e7ea", @ANYRES64=r0, @ANYRES64=r0])
mprotect(&(0x7f0000ff3000/0xd000)=nil, 0xd000, 0x0)
semget(0x3, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socket$inet(0x2, 0x2, 0x0)
mkdir(0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x10000, 0x0)
setitimer(0x1, 0x0, 0xffffffffffffffff)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, 0x0)


open(&(0x7f0000000180)='./file0\x00', 0x200, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000424, r0)
r1 = getpid()
ktrace(0x0, 0x1, 0x4000072c, r1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000001c0)=[{0x64}, {0x45}, {0x6}]})
syz_emit_ethernet(0x62, &(0x7f00000006c0)=ANY=[])


open$dir(&(0x7f0000001680)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
setsockopt$sock_linger(0xffffffffffffffff, 0xffff, 0x80, &(0x7f0000000080)={0x2e49}, 0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
mkdir(&(0x7f0000000080)='./file0/file0\x00', 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)


sysctl$ddb(&(0x7f0000000000)={0x9, 0x2}, 0x2, &(0x7f0000000040)="c79b9758", &(0x7f0000000080)=0x4, &(0x7f00000001c0)='\x00\x00\x00\x00', 0x4)


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open$dir(&(0x7f00000003c0)='./file0\x00', 0x400004000011830a, 0x0)
lseek(r0, 0x0, 0x0)


mknod(&(0x7f0000000000)='./bus\x00', 0x3a0914c44f7b202d, 0x504)
r0 = open(&(0x7f0000000040)='./bus\x00', 0x10005, 0x0)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f00000002c0)=0x9)
open(&(0x7f0000000040)='./bus\x00', 0x10005, 0x0)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RESETCPU(r0, 0x82405605, &(0x7f0000000780)={0x1, 0x0, {[], [0x1, 0x0, 0x0, 0xffffffffffffffff, 0x0, 0x20, 0x8]}})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
write(0xffffffffffffffff, &(0x7f0000000200)="b1", 0x1)
ioctl$WSMUXIO_LIST_DEVICES(0xffffffffffffffff, 0xc1045763, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
r1 = socket$inet(0x2, 0x0, 0x80)
getsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000040), &(0x7f0000000080)=0x10)
wait4(0xffffffffffffffff, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
close(r2)
socket(0x6, 0x3, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmsg(r2, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, 0x0, 0x3e}, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
recvmsg(0xffffffffffffffff, &(0x7f00000025c0)={0x0, 0x0, &(0x7f0000002540)=[{&(0x7f0000000600)=""/4094, 0xffe}], 0x1, 0x0}, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x2, 0x3, 0x2)
bind(r3, &(0x7f0000000000), 0x10)


r0 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r0, 0x0)
r1 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)={0x3, 0x7fffffff})
r2 = kqueue()
kevent(r2, &(0x7f00000000c0), 0x30, 0x0, 0x57d, 0x0)
accept(r0, 0x0, 0x0)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
setrlimit(0x0, &(0x7f0000000000)={0x1, 0xfffffffffffffffe})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$VMM_IOC_RUN(r0, 0x8020560a, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, 0x0})


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x2b, &(0x7f0000000000)="8c740b72", 0x4)


sysctl$hw(&(0x7f0000000040)={0x6, 0xb}, 0x3, &(0x7f0000000080)="b5a7e6307d6404fdf0a44412bf79948b20765a98d09fe79a90f2745ea113c888285fc2595f647d9f36964bdd6a97e90f76d24ae7dde149dee988dbda643c77b814c53e5f8e94272758dc98e657455f580daa176f380588142e92f4aa7847afac5b26bc2a3a635b7be6213263aa1adf6ebb1850dac7903f000000c4e70bb9a7a69eb06f9556182e3e3f5e98128bc58ef147ca0919f67de46ba61208a4232eeed6556f5f85b7b9a889d97b60118804b817f303957efe7b010a85", &(0x7f0000000280)=0xb9, &(0x7f0000000180)="1dbd06084921068fa87365ae", 0xc)
chflagsat(0xffffffffffffffff, 0x0, 0x0, 0x55b3b3b89a53c133)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$FIONREAD(r1, 0x80206979, &(0x7f00000000c0))
mkdir(&(0x7f0000000940)='./file0\x00', 0x0)
r2 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r2, 0x0, 0x5, 0x0, 0x0)
open(&(0x7f0000000240)='./file0/file0\x00', 0x100, 0x0)
rename(0x0, 0x0)
r3 = socket(0x0, 0x0, 0x0)
setsockopt(r3, 0x1000000029, 0x2e, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x822, {0x10000, 0xfffffffffffffffe}})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000001440))
geteuid()
getgroups(0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})


r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r0, 0x80085761, &(0x7f00000000c0)={0x3, 0x1})


setitimer(0x0, &(0x7f0000000100)={{0xffffffff}}, &(0x7f00000001c0))


r0 = open(&(0x7f0000001180)='./file0\x00', 0x615, 0x0)
writev(r0, &(0x7f0000001480)=[{&(0x7f0000000100)="cc60d3d79a1a7122a5fb9de9ea6ca0b30fb2942ef7652736f10f86d45ae419b2ecf7af93d33b3de1f2c56c0d93da7484095d0d543baf7f0161a025c9c02a561f9a76d06f1eaec7d8df99d6c28b10fa891e47d6c3bba690a611889032ac7b3581d7c92d1c546e59764f069048316871794f0615dd4d8bb1057a61fb177be649004fb56a7d46c856a20d73f050bf29d58b803a676cc3761e8a47857f51d90a4465f9c605ab2829d78ea2571900", 0xac}, {&(0x7f0000000080)="b389e5ae", 0x4}, {&(0x7f0000000200)="5f6a8de84b4c523a583f91557c748a02cda4cedf13579996073843ec5cbabaadcec85d62a8a897a78307f3d2c30eea6356105ec8aaba86930f1aed0b3d111d", 0x3f}, {&(0x7f0000000240)="2a5f4cd9b73c31d629e8d68e605e5940744ef138960b671d42c56f79fcb70549247e5504e02f85a6099eff9291731e94399a7e966e783d4073ecd5dc8e540f32190bb47050aee3907495ecf7708d1c295a0836f79ba03ea13db12836c2441989726ffbf7fd1da55bfe2caaf081a1ef55599935c0e60cb0866ee48d420b77a6e269bc30b2650349e16792252c6be8bcc6e9ce2b941299ab505e4779fa1960bb7cf924dcbc53c82e76bcd80731a694d12e8a139d8ecef6f5560939054b7842d25cd7396377f39bcfe2a2383feea17b87393cd892b90742631718b1877d8d83d5f66587e3e5b1e129433ead750143a4c51aa46e78e3b1a54a4634eea2846511719b1637b19ea8c96a95332abd69014f53e91a7319a36efb4052387dc6330aa00b5680142650e8dab5eb6b83ff7d0bbf1293338a8d3e8a6dcd7ed4916279eac230dda46e6fcdebe8a4c12d598883d9392da05791e153d905ce1930aebfc5dfc0fc22a88777c9fbc24c0b021189c3503466bf850f59e6649dd0b40d935ba155a9d7e065df6d90a500be9d7e1e77607d495898a8d6c9c48dda88533e75e760dceae91d670f97ebbe68b845c72eb698a9e0389b15cfe768cd4e524dbe939bc2d8363ae3b71a454a0a0378cd1f36565ab9d1b92263688195df65151ee9b8158c7a5280019a38f00ea05142b3cc832ece46e326e36a55d7a30f866ca97da61a3877612f0d9f23c052edf60a430d3a9acbae3d9f14f22f38a1eeac7df37ae17748a960b9e0d265bf6cdec73bd2a7b5f25035d845d936936cbfe6f013f8d7c73eba2bd9876ff6db3224e50e75c051979f4cdc41d28ea54e28f560fb0291cd6b6ba527e0f358ffa46b988f0bdbf801063d2024380071709ac00ed463e08fd1718a857b567d8b3eda143915e943d9530d25ed15743e117be375dc08e241328a53fa05b58c7c72a35d471a72706afce82b6c57eef81444269e06338bfd0af6f6ef6479dcc26aab0b10c7e58572aa507a69831d63c78c947cecda2c57bb8ae6b2ad7862d160b423de941be69928467db10ee4817536196ad0c5cc02a74ba1a1fb467e472f025f200846112b6b3efd298284d8c0cc498fb9203db18e48e34c137d1285120d809a774d56a62b3dbe8f202cb9cf18c33099f5b9651fc7ae41de53842f327fd40bcfaa601a791da1103351a64cc9815ff1f32cde6fbfe4c92f55a9aff41c055d4edce9c656ecd1becb9035bb8bd46cf47bca0dcb1848da94d05d1475c83a48c02f8f808597eaa9e88a4e4b12d0ef95458eeab115cb189fa7e368186bb68610af4651e27feab061c4ada46e8c12d6d33fe32cd40485b02120418a9aaba8f04c17ea1abdcb9e6801f5d8090c0780b3b5ae4382efbb64f62c825527b7e3d60ad9c73ba7f174ea7c7f2d155808052a0ef6ab2af85cf9a758a8c1227c85f2986fc06c5f54807968b18b6b5f9168d0b2de2728689d75f0efaedf79bd8bbbbc1d46b0f6072d46d46687bc92c0b16c4ad36c3fe4c7a2fde0cfec859052dd78d841464a6b4432342ea973bf18f1f5abd7b2fe7962faef39ff38bd88a40dbab0f8c08541e38efe924f9ec1addbd47362e349bfca42fd62cf18fef8db7d3cbf0b1733d37dcdae5b9c738b8426a1cfa205c9671870210508c614f256d199fb822613518b1a6fccfee08c48f0feae1ca4baaf0a02635282d4f630a8df115dc73e72d9f7b8feb4333b2c796f1d3f2cfb398ba1e9c81584185b8b578bac3c64d667da7d91062f0c2ccec0c9d09e0c15c62e7bc509c3204d054c22d4eac685626e48e25cff2fc382279d9cb941c2ca182b1f65b05ff05db880a37b1e7f9b3d8975558858352bbbea9213a885b7d43451230e0624403baa77839baa33ae92de771ca76319c2353e9f98ea8191fbb686aed6d08e87bcc2bb8084ae02fafbac1a0bba93f0f155fa2d7bc21bf77f116429c6a1373c34d080518b73481fcf012c0a9127e8f174695ccd4add75b026bf2935990d5cebc4e74b97ae67a414029252336880232635fce7ed7bf0b069e08e10f7e1cc4d2973dcd2ea0b63f9dc4f4c2db92e03c553afcb1060b12f6b9b4d1d799edceefdfafdae63ad797e400645c149b20f8a10af54db3289441499e122413495c7b32179ab6c274bbdf6dde48ce26f46f07ede9a314c1a73669ee8cb0d854c8a3206dcd4f532d36fa7affca1226962e20ca2c6ca0da1ab0848d23d6f198681911592815c080cead9fe6c81cf0d7ce3578978dbf1dc2f1902e51f740f95b02ebff4cf25ac8d28b8e16998f5e329e9a377a82b5bc227f77c2f1ad505286aac8618799c2363a2d07d229519370be62ef0dde6525df45a7b807759b9ba1c8557bdbecb429432c4e1a84094edda567f1245ba887686342d0a31b7dbe09bd2be75516b255d2bfad9337649e86a29b0a19e16b4059c7c45e9f81db6780af6487a11f9088ea265a99d6e95535e14fe839945f8f7da9bf9142dd12c305bd41bb392cae8eb81b28fda176d4b538f4ddaaed47913cd9149d934ca36879718bbd76a2d7ce11e6294398ea433af6cf53b951974ec96a9527178b6cbad3088a2e2dc75113fa88ede462e68b4d6b63020a45e94fbc6c3e6677d6cffee0e3bf606cd2d4b9fac89f91db8f3a1fb9f506708314249fa5c36912e3cb281acbdec3b080735ae24ebb4bca3c7900c21175435afbe5024a706e90f8ecf257c99cd8b67b5a9c2bdc2bb624201f55882349526f8faf463eecb183635db72a6aef5fa2048d97e6f6c513598f49158050df1efc6b13b8ae396cd6a905c26b94d1d50d361f10c0362a8c206c7dd553dd8b116694aa82ac029c64aa71b8a307793da12f93ce030d3c42443c37b91043687befb7968da97ffe91d45e4fd506ba4d9c5d7fe5ac7433fb6bb3ce471f59ade734d109d2093fa119827b65a360f2128e7e85ab494609b60d6e236ed8a72984f6c75652f5baa07e2e921365af2b819eef58343e65ffb45ba8580d62f5b8a9988f7176c1559f8ede3b1b92e0ff27978fc5225ed1512b605f1fd4fce46e768970b11a7b4802c93eb05a8571887cdc15f69929eadcd1f9d08ed2d6aab2997ffa2102c2d8983a78ad43779d03aa612ecbbdde634b14e980b176f04f99efad82a04001f34d6addb89e0ce629856f5ad401fed1a2c046e1fe18741b24d4253830af94a1defeecdf6f70b430e48d7b2e4ae2fb331322d96e1a361e4dcae1d0865e7ccc4aa58bcbb3ad1ce0b294437887e03088a6bb4c92c3044bb33d2a893975023ad979fb2f84d4842326cf058595398779116245c452e54989df0591238af63c5b187d18457f008f2759ae470282ee4640e92639a46915fb67f22967beb1f46736aa9c90df08f39ee481f6859f9eafdecd473bdc24ef3ad71b4c54dde360f2d550db18af7589c8107f29b0a713b65f039da10c2dc55e408ce75c77aba97c116ab078ed1467464fe4041668228316f0fff7c0e0f1a3cc47aae570182197cc3a030a4af7fe2d401b5a13d59b8fe55d48b0667b782cbf1c2e9e491167d87830bb25008aff93c4459a3ce9fd8655a542c6311d91ec6b6bd7935aba1cd01d10439f5e5a3883566c8538edb97c5d2a7c7533d415973729f52dc03134f3d777b7ad07c0f5b0d985ca48fde6cce9ec99f1223f476dcfbb5ef865a3f54459415b25e2031eeb469c83ac68fd77e59c6b6a4b9543a943c4461e47e94d038c63abf2734a3c0e99b95505e13af6cf7b66840dc60e96fb218436ea00b4a577c2effdba43e6adf97cb47c0ce606e87a7834dec04396c1e4f7df59ae5acedfd1d68c87e405fc5d788884686270cb08f0fb15fe8b11589792f9afc11152cd45f43fac6e758588cfaa88874267c3096bd689108bbb0296f3d182df7d46cf7e6b8bb923ba887443c3d2211785e364c1e55d4e9396d950e50cc11ba9a4da70a64f6acbbcd421183eb2c0521054c4f39650409e21a9d3b781725b0c38abce7b4615fa64a9cbf71a19f7e414279a7494d2e66e4e2b2d5ce7027109cfc763a9dcac37065ae80ec0cf3962deec0f9eba3bd7c514a9854ddec6542cf60a1e69cf5d1a73239633675d4ac1f3b0758e69d1d9fb8659f43f07ef6b0b2a7c9740649198b44f3272a8810d374b00c1d49b7f667ed538d89e91e5734f8d6e270aef0a406fcb4072497dd5f25b49d31cfd64f7af2d5b4df72b74c39a66f442ae61aebe1cdb96b660e3248dad3d05bfce3d8630902a565c3a7636220e0435679ce1c45367570dd08722ddfe7f1bf56c44bcab8ef2d0979eeaa569dade4ec34751833d455b31b55edcb9b64f3045725fcd3a08ce0c20b09a437133df5738092eba91430208814b4135b0a64331aff1847ca60426c91e96a029cff039b14462da6e5f9c545980b3712f7fa5f3958d92278194cf6b37ef76e91103d14db403956a7070d87afa81df227f2189926e1265a2872e9d64c64496083caff36dd3c27e961957acb86f0f9a3cbb5ddbb6bf9c62dc102d70d62eea969b1c2c5f42823f76827e918ffa77cc12ca8d31effd0b55529c496da762b6a95d43360ea4e811979ee316e143733f886a6eca5ac76746d4a302ec57b6b4af57c25631d7773243abd400d15274703154dfde2f1a63e075e4b22ed4516dd1496e3f7848bbf19e3215edda64140649d9b1a06975773d5dd0ca9c4bdfd5eb9fb6164aa659e2a8415098dd05496d0b2a20d966a4c9efefa964e007a3b731d3bad501fd21ca564c6155d893c3075c234af6378a12595d8a88ae0518350b75d57fb91b7610bfc3168f548a9a63432b49a9dbee2ee1a4ddd80255e2c655cc80d59d7e90e21fb090db6d59ef84c0becfda6bd01c5a806ce67bea77fdba62ba40e2114d31e6087ad67b28adc20d7cabe7911aa2db119cf5f43b2011bb92556e8e303a264f813764027fbec36f8248a667c766cfc12c80d96965f222d39b5f58a54b255d3b1eb4530952b6d251ff1f9a2cbc585d539704c8ea6884699ebc95d57cd1daef169da86cc10fe7300352e939c35bbe3104aea1b1c681f3e98be8fad7c91bb56724ffa794ea4ac7c4d51d4aad8e94087b4cdcab897e70558e6648ab42dfadab447735912af011fdbd9a47a4958b953b01d2e274449854cb7d4b44d88fb2db162b8dd664c7c32858c7714c69b838cb30b17e6a42ca760256c4c6da57ad5be955ca8c787262d8bd3f4a5f0170e70f92ee2ec9d227d066e41d0d4b640166b2f6937a66bc84506d102d3edac818b246954ba200a3057820da10b64ff99f016b42d90a29b43290d731ef23a72612d646f92acc05620068fd94edd12902197733cc9dbb55d95930ccc749c4a169b4b7056dba24f767da022eb01243353e1f4d0af2eb32e3feb331283ceab3e0112b37556749a701d11ada5cbe1b4c829fac46e12612679e47d4a066be939b886f0fdc2b4c5b4dd183ca025c5191ac67d7f992643333504da30e8300a0b40152671", 0xf12}], 0x4)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x11, r0, 0x0)
setrlimit(0x0, &(0x7f00000000c0))
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x4)
ioctl$PCIOCWRITE(0xffffffffffffffff, 0xc0107003, &(0x7f0000000080))
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000100)=[{0x84}, {0x44}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504000004000000000003000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac5000010000000000000008abfba221554f4e0f668246c0900000008e371a3f8343712051eea04", 0xac, 0x0, 0x0, 0x0)
setsockopt$sock_linger(0xffffffffffffffff, 0xffff, 0x80, &(0x7f0000000080), 0x8)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r1, &(0x7f0000000040)=[{&(0x7f0000000380)="079facfaaed69aea4dc561c3b736feac0a2a76087be8b904ddc6f90b66e0f69b6dfba683b348224cf0ccc2a39b0f79389a2bd9b211424a22ca014b9231e253e257706c75b3f320166475c72455021edf575fab8b5d65b8d261c87c3ccc4e784ea7462f3723edabb8e26d27acb1797e2ef4db27270a", 0xffffff01}], 0x1)
pwrite(0xffffffffffffffff, &(0x7f0000000480)="103924d891c20d1c", 0x8, 0x0)
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)


msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x30}, 0x0, 0x0, 0x0, 0x0, 0x8000000000000000})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
close(r1)
r2 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x1, 0x4)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
r4 = socket(0x2, 0x1, 0x0)
ioctl$FIONBIO(r4, 0x8004667e, &(0x7f0000000080)=0x4)
r5 = dup(r4)
listen(r5, 0x0)
accept$unix(r5, 0x0, 0x0)
link(&(0x7f00000000c0)='./bus\x00', &(0x7f0000000100)='./file0\x00')
unlink(&(0x7f0000000080)='./bus\x00')
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


r0 = semget$private(0x0, 0x2, 0x621)
semctl$IPC_RMID(r0, 0x0, 0x0)


syz_emit_ethernet(0x2e, &(0x7f0000000180)={@local, @local, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x1, 0x0, @remote={0xac, 0x14, 0x0}, @rand_addr, {[@ssrr={0x89, 0x3}]}}, @generic="0eeb12dd0743bebf"}}}})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f00000002c0)=[{0x7c}, {0x3d}, {0x812e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socket(0x2, 0x0, 0x0)
r0 = openat$null(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
getdents(r0, 0x0, 0x0)
socketpair(0x1, 0x1, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
write(r1, &(0x7f0000000140)='W', 0x1)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0))
pipe(&(0x7f00000001c0)={<r3=>0xffffffffffffffff})
r4 = fcntl$getown(r3, 0x5)
ktrace(&(0x7f0000000180)='./file0\x00', 0x0, 0xd30, r4)
recvmsg(r2, &(0x7f0000000f40)={0x0, 0x0, &(0x7f0000000e80)=[{&(0x7f0000003780)=""/4121, 0x1019}], 0x1, 0x0}, 0x1042)
close(r1)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {}, {0x8}]})
sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x3}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x8028ca56d081abe6, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)={0x3, 0x7fffffff})
r1 = kqueue()
kevent(r1, &(0x7f0000000080), 0x7ff, 0x0, 0xc0000000, 0x0)
pwritev(r0, &(0x7f0000000900)=[{&(0x7f0000000440)="d5", 0x1}], 0x1, 0x0)


openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


r0 = kqueue()
kevent(0xffffffffffffffff, &(0x7f0000000140)=[{{}, 0xfffffffffffffff9, 0xd, 0x13}], 0x0, 0x0, 0x0, 0x0)
kevent(r0, &(0x7f0000000040), 0x20, 0x0, 0xffffffff, 0x0)
kevent(r0, &(0x7f0000000040), 0x100, 0x0, 0x8000, 0x0)


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
r1 = msgget(0x3, 0x11)
sysctl$net_inet_udp(&(0x7f0000000240), 0x4, 0x0, 0x0, 0x0, 0x0)
r2 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
msgsnd(r1, &(0x7f00000002c0)={0x1, "10ee20dcedc36657f7fd03dc4d7f8da54329a1d0aad976c8d29de7ace0fb86e24b28d91f650bcae0e939f439df94a10ff08a4e15fd3ea168627e1b4aea403d35107c3e32631cc7e89ed0e766d31701f79c0f0dc416f21eb14ed4f1d0a0105c52e2e7d9cb4f5d82bc83b882667f218e23c46809f223a0ce416d2f24d79a01d5fff008abb98cfa911f0022ecc43c7f1f339a9780ad0ee5dd9ed963a2dd70d7bd2ac057ec3c8661b074be11bb062f8c8f85e877696fbf238226e7c8224fc79fbc2a4f5d0da06e8a458f4c234a42716e9954980af6657cd393fe19ab0e3a"}, 0xe4, 0x0)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
r3 = socket(0x11, 0x3, 0x0)
sendto$unix(r3, &(0x7f0000000000)="b1000513000000000000000004000000000013fecea10500fef96ecf2ac72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf7f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f335c223e7d0c", 0x59, 0x0, 0x0, 0x0)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x3}, 0xc)
close(r0)
open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0xd6)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
msgrcv(r1, &(0x7f00000000c0)={0x0, ""/142}, 0x96, 0x3, 0x1000)
r4 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x2)
poll(&(0x7f0000000200)=[{r4, 0x4}], 0x1, 0x0)
r5 = openat$wsdisplay(0xffffffffffffff9c, 0x0, 0x80, 0x0)
ioctl$WSDISPLAYIO_GETSCREEN(r5, 0xc0245755, &(0x7f0000000040)={0x1, './file0\x00', './file0\x00'})
execve(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
symlinkat(0x0, 0xffffffffffffffff, &(0x7f0000000080)='./file0\x00')
open(&(0x7f00000000c0)='./file0\x00', 0x200, 0x0)
r6 = open(&(0x7f0000000280)='./file0\x00', 0x0, 0x0)
fcntl$lock(r6, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000401})
open$dir(&(0x7f0000000240)='./file0\x00', 0x20, 0x0)
r7 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r7, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000080)=[{0x5c}, {0x3}, {0x8106}]})
open(&(0x7f0000000100)='./file0\x00', 0x6d0, 0x0)


socket(0x2, 0x4, 0x10)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f00000009c0)="4890526e5b4f426b22ce504dec8264b9d7023381d0ce7e3b030bcd6ffac1d38bd40908d4ab0118e3776dd6b4f602c213dc8dd4bd059bcd367ef291c3ffd6f77904c2cbbd104130d6bb519c9fe7ac0d2e8e26f7e2511a0d2cf74755dd287307a126f82dcc8052774b1977f842a2a66b57a1cc834559579792cdba2d64b72fafc76c4bb8cd7c0d552978dd2e729c95e54fc7b1cbb115268719d99fc8208fc182b7acc12c87d65875355512adebe0820c3ae09fcab8644cf54d7376797137f1ed55aa6105a40ee771dd804664933968d9400d9a661a2a558e283737fd60374abbac113518f938fc8d51849dd9f6c0832cc14e56d4152c492e770c86d9eda829de0080fadc05f0abcaac6c3b8c672f88649122d53dd8f03a3a37a24f4e601d9b81e19358fcdb1bda1f715534eb07220dafd471aebfaa1c6317837466a691ba949677a4ba6b94bcb44e7bda754ed1af49f6399e5792423350c96d2a11ab84e664fac0daede7ff47f2a18652d3d8b7644845f0ae4d400cb8fb5afdac4e8291065703b983eb793c9b901bc9da9e8a9e74ba5fe21539fa7d2268e98a814abd3a6312a9ec7d51d8eae5d89612bff6ba1934ea612799577215cf950b7b84d1e45bb5aab0bade45bdd86f868557df5a45e5a46fa2ba730460fdb72a783a4c2a0160271e0985e2578c7bab13b0ca825762a460c4521531ae243eff8bdb8ee4993d438a6c6689c7aa4e769955b2b9ccf5f0b40330c3a3e7dcc6d51c3d8aaad107e304483e90ebbcf778a8d37f26e6bb4b25d88559c1adf0398cadf422adeb6a5d67b994fdc9266762b475557c8edaab1603455443c8a97d7d2cbfdd57bb528478e702470d253ecaf0c6ed9176bcec3b7a5e97074b1ed2c20e6eb7cdc62da5922042d37938d319fab622ec0ed1dfd26a83037994c96ae04658a97ed868c79abb6b6289746b3463a5e1f60bbe533fa4db1ee9a5e67040381275332905f3058e5a15d4e28d3b8b871fc723f26846e025f37d14860221025187618b172f071852120dbefd1453370e062cd2dc0a0d54f1187a9d9df60d6ed137ad09a1a1322c8a6a4b78f265e37bfed65d35fb9675c130a091841ec696a746289262b2c28fa3252f466728a6f1856e05ec80d5bc8d1b0a", 0x328}], 0x1)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000000)=0x9)
fcntl$dupfd(r1, 0xa, r1)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f00000001c0)={0x3, &(0x7f0000000080)=[{0x20}, {0x44}, {0x6, 0x0, 0x0, 0x40}]})
write(r2, &(0x7f0000000280)="ce4aa4a25043cb02aadf8701f131", 0xe)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x0, "51fa6278e9e960b4dd89080863ab366d112be29e"})
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
chdir(&(0x7f0000000240)='./file0\x00')
mkdir(&(0x7f00000001c0)='./file1\x00', 0x0)
chmod(&(0x7f00000000c0)='./file1\x00', 0x13)
setreuid(0x0, 0xee01)
mkdir(&(0x7f0000000100)='./file0\x00', 0x0)
rename(&(0x7f0000000180)='./file1\x00', &(0x7f0000000200)='./file0\x00')


setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r0 = syz_open_pts()
close(r0)
socket(0x18, 0x3, 0x0)
r1 = open(&(0x7f0000000140)='./file0\x00', 0x78e, 0x0)
r2 = getpid()
ktrace(&(0x7f0000000040)='./file0\x00', 0x0, 0x20, 0x0)
ktrace(&(0x7f0000000280)='./file0\x00', 0x0, 0x928, r2)
utimensat(0xffffffffffffffff, 0x0, &(0x7f0000000100), 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r1, 0x0)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000200)="f6", 0x1}], 0x1)


mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
r0 = open(&(0x7f0000001180)='./file0\x00', 0x615, 0x0)
writev(r0, &(0x7f0000001480)=[{&(0x7f0000000100)="cc60d3d79a1a7122a5fb9de9ea6ca0b30fb2942ef7652736f10f86d45ae419b2ecf7af93d33b3de1f2c56c0d93da7484095d0d543baf7f0161a025c9c02a561f9a76d06f1eaec7d8df99d6c28b10fa891e47d6c3bba690a611889032ac7b3581d7c92d1c546e59764f069048316871794f0615dd4d8bb1057a61fb177be649004fb56a7d46c856a20d73f050bf29d58b803a676cc3761e8a47857f51d90a4465f9c605ab2829d78ea2571900", 0xac}, {&(0x7f0000000080)="b389e5ae", 0x4}, {&(0x7f0000000200)="5f6a8de84b4c523a583f91557c748a02cda4cedf13579996073843ec5cbabaadcec85d62a8a897a78307f3d2c30eea6356105ec8aaba86930f1aed0b3d111d", 0x3f}, {&(0x7f0000000240)="2a5f4cd9b73c31d629e8d68e605e5940744ef138960b671d42c56f79fcb70549247e5504e02f85a6099eff9291731e94399a7e966e783d4073ecd5dc8e540f32190bb47050aee3907495ecf7708d1c295a0836f79ba03ea13db12836c2441989726ffbf7fd1da55bfe2caaf081a1ef55599935c0e60cb0866ee48d420b77a6e269bc30b2650349e16792252c6be8bcc6e9ce2b941299ab505e4779fa1960bb7cf924dcbc53c82e76bcd80731a694d12e8a139d8ecef6f5560939054b7842d25cd7396377f39bcfe2a2383feea17b87393cd892b90742631718b1877d8d83d5f66587e3e5b1e129433ead750143a4c51aa46e78e3b1a54a4634eea2846511719b1637b19ea8c96a95332abd69014f53e91a7319a36efb4052387dc6330aa00b5680142650e8dab5eb6b83ff7d0bbf1293338a8d3e8a6dcd7ed4916279eac230dda46e6fcdebe8a4c12d598883d9392da05791e153d905ce1930aebfc5dfc0fc22a88777c9fbc24c0b021189c3503466bf850f59e6649dd0b40d935ba155a9d7e065df6d90a500be9d7e1e77607d495898a8d6c9c48dda88533e75e760dceae91d670f97ebbe68b845c72eb698a9e0389b15cfe768cd4e524dbe939bc2d8363ae3b71a454a0a0378cd1f36565ab9d1b92263688195df65151ee9b8158c7a5280019a38f00ea05142b3cc832ece46e326e36a55d7a30f866ca97da61a3877612f0d9f23c052edf60a430d3a9acbae3d9f14f22f38a1eeac7df37ae17748a960b9e0d265bf6cdec73bd2a7b5f25035d845d936936cbfe6f013f8d7c73eba2bd9876ff6db3224e50e75c051979f4cdc41d28ea54e28f560fb0291cd6b6ba527e0f358ffa46b988f0bdbf801063d2024380071709ac00ed463e08fd1718a857b567d8b3eda143915e943d9530d25ed15743e117be375dc08e241328a53fa05b58c7c72a35d471a72706afce82b6c57eef81444269e06338bfd0af6f6ef6479dcc26aab0b10c7e58572aa507a69831d63c78c947cecda2c57bb8ae6b2ad7862d160b423de941be69928467db10ee4817536196ad0c5cc02a74ba1a1fb467e472f025f200846112b6b3efd298284d8c0cc498fb9203db18e48e34c137d1285120d809a774d56a62b3dbe8f202cb9cf18c33099f5b9651fc7ae41de53842f327fd40bcfaa601a791da1103351a64cc9815ff1f32cde6fbfe4c92f55a9aff41c055d4edce9c656ecd1becb9035bb8bd46cf47bca0dcb1848da94d05d1475c83a48c02f8f808597eaa9e88a4e4b12d0ef95458eeab115cb189fa7e368186bb68610af4651e27feab061c4ada46e8c12d6d33fe32cd40485b02120418a9aaba8f04c17ea1abdcb9e6801f5d8090c0780b3b5ae4382efbb64f62c825527b7e3d60ad9c73ba7f174ea7c7f2d155808052a0ef6ab2af85cf9a758a8c1227c85f2986fc06c5f54807968b18b6b5f9168d0b2de2728689d75f0efaedf79bd8bbbbc1d46b0f6072d46d46687bc92c0b16c4ad36c3fe4c7a2fde0cfec859052dd78d841464a6b4432342ea973bf18f1f5abd7b2fe7962faef39ff38bd88a40dbab0f8c08541e38efe924f9ec1addbd47362e349bfca42fd62cf18fef8db7d3cbf0b1733d37dcdae5b9c738b8426a1cfa205c9671870210508c614f256d199fb822613518b1a6fccfee08c48f0feae1ca4baaf0a02635282d4f630a8df115dc73e72d9f7b8feb4333b2c796f1d3f2cfb398ba1e9c81584185b8b578bac3c64d667da7d91062f0c2ccec0c9d09e0c15c62e7bc509c3204d054c22d4eac685626e48e25cff2fc382279d9cb941c2ca182b1f65b05ff05db880a37b1e7f9b3d8975558858352bbbea9213a885b7d43451230e0624403baa77839baa33ae92de771ca76319c2353e9f98ea8191fbb686aed6d08e87bcc2bb8084ae02fafbac1a0bba93f0f155fa2d7bc21bf77f116429c6a1373c34d080518b73481fcf012c0a9127e8f174695ccd4add75b026bf2935990d5cebc4e74b97ae67a414029252336880232635fce7ed7bf0b069e08e10f7e1cc4d2973dcd2ea0b63f9dc4f4c2db92e03c553afcb1060b12f6b9b4d1d799edceefdfafdae63ad797e400645c149b20f8a10af54db3289441499e122413495c7b32179ab6c274bbdf6dde48ce26f46f07ede9a314c1a73669ee8cb0d854c8a3206dcd4f532d36fa7affca1226962e20ca2c6ca0da1ab0848d23d6f198681911592815c080cead9fe6c81cf0d7ce3578978dbf1dc2f1902e51f740f95b02ebff4cf25ac8d28b8e16998f5e329e9a377a82b5bc227f77c2f1ad505286aac8618799c2363a2d07d229519370be62ef0dde6525df45a7b807759b9ba1c8557bdbecb429432c4e1a84094edda567f1245ba887686342d0a31b7dbe09bd2be75516b255d2bfad9337649e86a29b0a19e16b4059c7c45e9f81db6780af6487a11f9088ea265a99d6e95535e14fe839945f8f7da9bf9142dd12c305bd41bb392cae8eb81b28fda176d4b538f4ddaaed47913cd9149d934ca36879718bbd76a2d7ce11e6294398ea433af6cf53b951974ec96a9527178b6cbad3088a2e2dc75113fa88ede462e68b4d6b63020a45e94fbc6c3e6677d6cffee0e3bf606cd2d4b9fac89f91db8f3a1fb9f506708314249fa5c36912e3cb281acbdec3b080735ae24ebb4bca3c7900c21175435afbe5024a706e90f8ecf257c99cd8b67b5a9c2bdc2bb624201f55882349526f8faf463eecb183635db72a6aef5fa2048d97e6f6c513598f49158050df1efc6b13b8ae396cd6a905c26b94d1d50d361f10c0362a8c206c7dd553dd8b116694aa82ac029c64aa71b8a307793da12f93ce030d3c42443c37b91043687befb7968da97ffe91d45e4fd506ba4d9c5d7fe5ac7433fb6bb3ce471f59ade734d109d2093fa119827b65a360f2128e7e85ab494609b60d6e236ed8a72984f6c75652f5baa07e2e921365af2b819eef58343e65ffb45ba8580d62f5b8a9988f7176c1559f8ede3b1b92e0ff27978fc5225ed1512b605f1fd4fce46e768970b11a7b4802c93eb05a8571887cdc15f69929eadcd1f9d08ed2d6aab2997ffa2102c2d8983a78ad43779d03aa612ecbbdde634b14e980b176f04f99efad82a04001f34d6addb89e0ce629856f5ad401fed1a2c046e1fe18741b24d4253830af94a1defeecdf6f70b430e48d7b2e4ae2fb331322d96e1a361e4dcae1d0865e7ccc4aa58bcbb3ad1ce0b294437887e03088a6bb4c92c3044bb33d2a893975023ad979fb2f84d4842326cf058595398779116245c452e54989df0591238af63c5b187d18457f008f2759ae470282ee4640e92639a46915fb67f22967beb1f46736aa9c90df08f39ee481f6859f9eafdecd473bdc24ef3ad71b4c54dde360f2d550db18af7589c8107f29b0a713b65f039da10c2dc55e408ce75c77aba97c116ab078ed1467464fe4041668228316f0fff7c0e0f1a3cc47aae570182197cc3a030a4af7fe2d401b5a13d59b8fe55d48b0667b782cbf1c2e9e491167d87830bb25008aff93c4459a3ce9fd8655a542c6311d91ec6b6bd7935aba1cd01d10439f5e5a3883566c8538edb97c5d2a7c7533d415973729f52dc03134f3d777b7ad07c0f5b0d985ca48fde6cce9ec99f1223f476dcfbb5ef865a3f54459415b25e2031eeb469c83ac68fd77e59c6b6a4b9543a943c4461e47e94d038c63abf2734a3c0e99b95505e13af6cf7b66840dc60e96fb218436ea00b4a577c2effdba43e6adf97cb47c0ce606e87a7834dec04396c1e4f7df59ae5acedfd1d68c87e405fc5d788884686270cb08f0fb15fe8b11589792f9afc11152cd45f43fac6e758588cfaa88874267c3096bd689108bbb0296f3d182df7d46cf7e6b8bb923ba887443c3d2211785e364c1e55d4e9396d950e50cc11ba9a4da70a64f6acbbcd421183eb2c0521054c4f39650409e21a9d3b781725b0c38abce7b4615fa64a9cbf71a19f7e414279a7494d2e66e4e2b2d5ce7027109cfc763a9dcac37065ae80ec0cf3962deec0f9eba3bd7c514a9854ddec6542cf60a1e69cf5d1a73239633675d4ac1f3b0758e69d1d9fb8659f43f07ef6b0b2a7c9740649198b44f3272a8810d374b00c1d49b7f667ed538d89e91e5734f8d6e270aef0a406fcb4072497dd5f25b49d31cfd64f7af2d5b4df72b74c39a66f442ae61aebe1cdb96b660e3248dad3d05bfce3d8630902a565c3a7636220e0435679ce1c45367570dd08722ddfe7f1bf56c44bcab8ef2d0979eeaa569dade4ec34751833d455b31b55edcb9b64f3045725fcd3a08ce0c20b09a437133df5738092eba91430208814b4135b0a64331aff1847ca60426c91e96a029cff039b14462da6e5f9c545980b3712f7fa5f3958d92278194cf6b37ef76e91103d14db403956a7070d87afa81df227f2189926e1265a2872e9d64c64496083caff36dd3c27e961957acb86f0f9a3cbb5ddbb6bf9c62dc102d70d62eea969b1c2c5f42823f76827e918ffa77cc12ca8d31effd0b55529c496da762b6a95d43360ea4e811979ee316e143733f886a6eca5ac76746d4a302ec57b6b4af57c25631d7773243abd400d15274703154dfde2f1a63e075e4b22ed4516dd1496e3f7848bbf19e3215edda64140649d9b1a06975773d5dd0ca9c4bdfd5eb9fb6164aa659e2a8415098dd05496d0b2a20d966a4c9efefa964e007a3b731d3bad501fd21ca564c6155d893c3075c234af6378a12595d8a88ae0518350b75d57fb91b7610bfc3168f548a9a63432b49a9dbee2ee1a4ddd80255e2c655cc80d59d7e90e21fb090db6d59ef84c0becfda6bd01c5a806ce67bea77fdba62ba40e2114d31e6087ad67b28adc20d7cabe7911aa2db119cf5f43b2011bb92556e8e303a264f813764027fbec36f8248a667c766cfc12c80d96965f222d39b5f58a54b255d3b1eb4530952b6d251ff1f9a2cbc585d539704c8ea6884699ebc95d57cd1daef169da86cc10fe7300352e939c35bbe3104aea1b1c681f3e98be8fad7c91bb56724ffa794ea4ac7c4d51d4aad8e94087b4cdcab897e70558e6648ab42dfadab447735912af011fdbd9a47a4958b953b01d2e274449854cb7d4b44d88fb2db162b8dd664c7c32858c7714c69b838cb30b17e6a42ca760256c4c6da57ad5be955ca8c787262d8bd3f4a5f0170e70f92ee2ec9d227d066e41d0d4b640166b2f6937a66bc84506d102d3edac818b246954ba200a3057820da10b64ff99f016b42d90a29b43290d731ef23a72612d646f92acc05620068fd94edd12902197733cc9dbb55d95930ccc749c4a169b4b7056dba24f767da022eb01243353e1f4d0af2eb32e3feb331283ceab3e0112b37556749a701d11ada5cbe1b4c829fac46e12612679e47d4a066be939b886f0fdc2b4c5b4dd183ca025c5191ac67d7f992643333504da30e8300a0b40152671", 0xf12}], 0x4)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x11, r0, 0x0)
r1 = geteuid()
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040))
fchown(r0, r1, 0x0)
sysctl$net_inet_etherip(&(0x7f0000000000)={0x4, 0x2, 0x61, 0x3}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0x0)
mkdir(0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, 0x0)
r2 = socket$inet(0x2, 0x2, 0x0)
r3 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
dup2(r3, r2)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00004100000000", 0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt$inet_opts(r2, 0x0, 0x0, &(0x7f0000001200)="ea000001000000cfcf3360", 0xb)
r4 = socket(0x18, 0x2, 0x0)
close(r4)
r5 = socket(0x18, 0x2, 0x0)
close(r5)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0x0, 0x0, 0x0, 0x40}], 0x0, 0x0, 0x0, 0x0)
r6 = socket(0x800000018, 0x2, 0x0)
setsockopt$sock_int(r6, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r6, &(0x7f00000011c0)=@abs={0x1f95d27d48731892, 0x7, 0x0}, 0x8)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ff7000/0x3000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil, 0x40}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000604000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f00004f6000/0x3000)=nil, 0x10000}, {&(0x7f0000ff7000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000529000/0x4000)=nil, &(0x7f0000563000/0x3000)=nil}, {&(0x7f0000691000/0x2000)=nil, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil, 0x1000}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil}], './file0\x00'})
connect$unix(r5, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sysctl$kern(&(0x7f0000000300)={0x1, 0x9}, 0x2, 0x0, 0x0, &(0x7f0000001440)="00000100", 0x4)


syz_open_pts()
ioctl$TIOCCBRK(0xffffffffffffffff, 0x2000747a)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = socket(0x2, 0x4001, 0x0)
dup(r0)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
close(0xffffffffffffffff)
getsockname$inet(0xffffffffffffffff, 0x0, 0x0)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
sendmmsg(0xffffffffffffffff, &(0x7f0000000140)={0x0}, 0x10, 0x0)
r1 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x4, &(0x7f0000000100), 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000080)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
close(r2)
socket$inet(0x18, 0x3, 0x102)
sendmsg$unix(r2, &(0x7f0000002e80)={&(0x7f00000001c0)=@file={0x0, '\x00'}, 0x3, 0x0}, 0x0)
open(0x0, 0x0, 0x0)


writev(0xffffffffffffffff, &(0x7f00000001c0)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe1463a52077dc0d00003ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')
syz_open_pts()


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f0000000180)='./file0\x00', 0x23f)
chdir(&(0x7f00000001c0)='./file0\x00')
mknod$loop(&(0x7f00000000c0)='./file2\x00', 0x6000, 0x0)
setuid(0xee01)
rmdir(&(0x7f0000000300)='./file2\x00')


r0 = getppid()
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000100)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000140)=0xc)
setregid(0x0, r2)
open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
r3 = getpid()
ktrace(&(0x7f0000000280)='./file0\x00', 0x0, 0x938, r3)
setregid(0x0, 0x0)
ktrace(&(0x7f0000000180)='./file0\x00', 0x4, 0x330, r0)


mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x412dff)
r0 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
preadv(r0, &(0x7f0000001440)=[{&(0x7f00000001c0)=""/131, 0x83}, {&(0x7f0000000440)=""/4096, 0x1000}], 0x2, 0x0)


openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000200)={0x3, &(0x7f0000000100)=[{0x34, 0x0, 0x0, 0x3}, {0x15}, {0x6, 0x0, 0x0, 0x101}]})
write(r0, &(0x7f0000000080)="2300110000fa4000805a099e20a0", 0xe)


openat$speaker(0xffffffffffffff9c, 0x0, 0x1, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
r0 = open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
poll(&(0x7f00000000c0)=[{r0, 0x6e}], 0x1, 0x0)
select(0x40, &(0x7f0000000180), 0x0, 0x0, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$FIOSETOWN(0xffffffffffffffff, 0x80047308, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r1 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f00000005c0), 0x80, 0x0)
getsockopt$sock_timeval(r1, 0xffff, 0x1006, &(0x7f0000000600), &(0x7f0000000640)=0x10)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r2 = socket(0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
getpid()
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000480), &(0x7f00000004c0)=0xc)
getsockopt$SO_PEERCRED(r2, 0xffff, 0x1022, &(0x7f0000000500), 0xc)
r3 = getpid()
r4 = msgget$private(0x0, 0x0)
msgctl$IPC_SET(r4, 0x1, &(0x7f0000002f80)={{}, 0x0, 0xff, r3, 0x0, 0x7fffffff})


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "ff000000ff597bd600"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000040), 0x3, 0x0, 0x0, &(0x7f0000000180)="76b0353a558bf248c78c8502fcf9fd08fa1588f254df98bdc2703864ecc0ce3671c0907259201eb7cb962ee12d9706a2d4177565da48e3cdade50516597f477ca5ea18253c1441678346ddaa98e46b28e2226a296c0fd773959eaad9d65d33cdbf523a06ed457ed3e00f52851f90c14f54ec03a2a5ff8d88b9", 0x79)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCLOCK(r0, 0x20004276)
seteuid(0xffffffffffffffff)
ioctl$BIOCGBLEN(r0, 0x40044266, &(0x7f0000000040))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000140)=[{0x74}, {0x61}, {0x812e}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x8, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{0x15}, {0x2}, {0x8106}]})
syz_emit_ethernet(0x3e, &(0x7f0000000040)=ANY=[])
mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
unveil(&(0x7f0000000080)='./file0/file0/../../file1\x00', &(0x7f0000000100)='r\x00')
r1 = open(&(0x7f00000001c0)='./file0\x00', 0x200, 0x0)
r2 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x80, 0x0)
ioctl$FIOSETOWN(r2, 0x80047476, 0x0)
setreuid(0xee00, 0x0)
sysctl$net_pipex(&(0x7f0000000000), 0x3, 0x0, 0x0, 0x0, 0xffffffca)
munmap(&(0x7f0000ff7000/0x7000)=nil, 0x7000)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
mquery(&(0x7f0000ffd000/0x2000)=nil, 0x2000, 0x2, 0x0, r1, 0x0)
syz_emit_ethernet(0x17a, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
getpid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0xb2}, 0x0, 0x0, 0x0, 0xffffffffffffffff})
r3 = socket(0x18, 0x2, 0x0)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmsg(r3, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="10"], 0x10}, 0x0)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000132000/0x3000)=nil, &(0x7f00000a0000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f0000ff3000/0xa000)=nil, &(0x7f00001f0000/0x1000)=nil}, {&(0x7f00001f0000/0x1000)=nil, &(0x7f0000001000/0x1000)=nil}, {&(0x7f0000132000/0x4000)=nil, &(0x7f00000b2000/0x1000)=nil}, {&(0x7f0000083000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {0x0, &(0x7f000002a000/0x3000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000e58000/0x4000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil}, {&(0x7f0000091000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000001000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000132000/0x1000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000008a000/0x1000)=nil}, {0x0, &(0x7f0000092000/0x3000)=nil}], './file0\x00'})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x8000000000000001})
semctl$SETALL(0x0, 0x0, 0x9, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x70e, 0x0)
mmap(&(0x7f0000010000/0x3000)=nil, 0x3000, 0x0, 0xa012, r0, 0x0)


socket$inet(0x2, 0x2, 0x0)
pipe(&(0x7f0000000040))
syz_open_pts()
syz_open_pts()
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000080)=[{0x14}, {0xc}, {0x8106}]})
syz_emit_ethernet(0x2a, &(0x7f0000000300)=ANY=[])
r1 = socket(0x20, 0x4, 0x0)
dup(r1)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
setegid(0xffffffffffffffff)
r2 = msgget$private(0x0, 0x0)
r3 = socket(0x11, 0x3, 0x6)
sendto$unix(r3, &(0x7f0000000500)="94010516000000000000002797888fd1f838a311000000000000b13886ca3849451ae3c3051020741038f5538551f30ce390500e08fecea11ea8fef96e4fc748e93f0b780486aebdbe781e4d8f5eef9187a869a4d3a4cbba982fd825582fe223ed00f4c8b2ca3ebbc259699a1f132e27acb5d62934e4fd89070000000000000070c1f5a872c88dff7cc53c894303b2a0a85ff3faa800000000009ec7ab3a34c29000000000000000000000000000002d7e4a5d76cc3f9cff2ed2243e56fa277603c5cc1e047326bcf6b67b75d00bf6ee330b6a80874b70559d9975ebd13da2447a78aa4b00cd0ba1870215607bb912e3d7325183ce69456b4b6ca927871c81672a54ec695c5bdeb842836656f917945cc076f87dc714dfe0aa2947252df350707b22884a7730cb6dba8742110fbe9ec7481885274387e0b1dbe5695122604819b0b2294b7b20726a5d4fcb44f62d00fabb2f247a166d8d79d05b8cc370f5c11db58aedca632a83acd58ff0ea0a3dca58ccb03cce466cda735017196ff346c32717397d6ec6952ec90de81ed297b2509e130f0000", 0x194, 0x0, 0x0, 0x0)
setuid(0xffffffffffffffff)
r4 = socket(0x18, 0x2, 0x0)
setsockopt(r4, 0x1000000000029, 0x40, &(0x7f0000000040)='X\x00\x00\x00', 0x4)
msgrcv(r2, &(0x7f0000000000)={0x0, ""/43}, 0x33, 0x2, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000140)=[{0x1c}, {0x1}, {0x6}]})
syz_emit_ethernet(0x127, &(0x7f0000000040)=ANY=[])


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
mquery(&(0x7f00003df000/0x3000)=nil, 0x3000, 0x0, 0x0, 0xffffffffffffffff, 0x0)


mknod(&(0x7f00000000c0)='./file0\x00', 0x2000, 0x40000802)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000540)=0x8)
getsockname(r0, &(0x7f0000000280)=@un=@file={0x0, ""/254}, &(0x7f0000000200)=0x100)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x16, &(0x7f0000000000), 0x0)
open$dir(0x0, 0x40000400001803c1, 0x0)
open$dir(&(0x7f0000000180)='./file0\x00', 0x2, 0x0)
r2 = getuid()
getgroups(0x9, &(0x7f00000001c0)=[0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff, <r3=>0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff])
chown(&(0x7f0000000140)='./file1\x00', r2, r3)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105727, &(0x7f0000000000)={&(0x7f00000000c0)=[{}, {}, {}, {}], 0x4})
sysctl$kern(&(0x7f0000000000)={0x1, 0x45}, 0x3, 0x0, 0x0, &(0x7f0000000040)="3944eb3f115f79037148fa0ddc3adf427d080000006ceb99ea265a4a19b2e72fd9cbb4db32e128db447c5e01000080d5fa1d9213ebefff7ad23b886bf325280bc040eac897a0d4168da6b6b75d146499e1ee9ddeb2d68e8d011a", 0x5a)
r4 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x1021, &(0x7f0000000000)=0x5, 0x4)
setsockopt$inet_opts(r4, 0x0, 0xd, &(0x7f0000000240)="ea0200000000ffe6", 0x8)
socket(0x2, 0x1, 0x0)


ioctl$FIOASYNC(0xffffffffffffffff, 0x80047460, &(0x7f00000000c0)=0x406)
syz_emit_ethernet(0x36, &(0x7f0000000440)=ANY=[@ANYRES64])
recvmmsg(0xffffffffffffffff, &(0x7f0000000c80)={&(0x7f0000000c40)={0x0, 0x0, &(0x7f0000000bc0)=[{&(0x7f00000000c0)=""/67, 0x43}], 0x1, 0x0}, 0x4}, 0x10, 0x0, 0x0)
socket(0x2, 0x5, 0x0)
syz_emit_ethernet(0x138, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{0x2000}, {}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x2, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f", 0x0, 0x0, 0x0)
sendmmsg(0xffffffffffffffff, &(0x7f00000007c0)={&(0x7f0000000780)={0x0, 0x0, &(0x7f0000000140)=[{&(0x7f0000000180)="b860fe09625ee6793978a575faa1b6c6c1d6c2eca2950e663d39ab1be31a269a39fd7f97e41e178f37a79f00659c2ea9ac56733f7e4e4973c1e6b33ac91343ea3b3f8c5c7b93d5c20ab4211791fe", 0x4e}, {0x0}], 0x2, 0x0}}, 0x10, 0x0)
socket(0x0, 0x0, 0x0)
mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x202)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
link(0x0, 0x0)
ktrace(&(0x7f0000000180)='./file0\x00', 0x0, 0x0, 0x0)
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))


socket(0x800000018, 0x1, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
socket$inet(0x2, 0x2, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0xb, 0x54})
syz_open_pts()
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
select(0x40, &(0x7f0000000100), &(0x7f00000024c0)={0x1ff}, 0x0, 0x0)


open$dir(0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000001680)={0x1, 0xa}, 0x2, &(0x7f00000016c0)="1f", &(0x7f00000017c0)=0x1, &(0x7f0000001800)="0c2fa4104b6d7ea6f45936680015b295e404f997312c1e7b36b8c754554383a176005c23005531f61ff6da5822313d04a7a8879e3830ee335f7ce67ce00a8290bee6aaa27a9a0848f824aa628937512eeaa3be2cf4e080019e5d0f410297433a09a01591308b296d84012e60f55d750c54d68a8066fd324843d4dd064414437a01f616f0b908d82ac2a46e0042d2fbbc8df4146624d90b5a36f7dc45da720d895660d8da21717d22d11e5c03d6373dfd6a93cbdbaa2bb04286231e97f65c313b865ceb318a570a242fd76c9a5e20fbed3d8601e0df4a28b5c969a358428d2e96cdec62b8da89472d90ab03ae83c5de4ae50b977fdb7344c999d28dca30d50f1f", 0x100)


r0 = syz_open_pts()
fcntl$lock(r0, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x7ffffffe, 0x100000001})
fcntl$lock(r0, 0x8, &(0x7f0000000040)={0x0, 0x0, 0x1000000000000000, 0x1000300000002})


mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000400), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
madvise(&(0x7f00000ab000/0x800000)=nil, 0x800000, 0x6)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000040)=[{0xb1}, {0x4c}, {0x812e}]})
syz_emit_ethernet(0x5e, &(0x7f0000000040)=ANY=[])


setuid(0xffffffffffffffff)
r0 = socket(0x18, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x80206982, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000580)={0x3, &(0x7f0000000540)=[{0x2c}, {0x2d}, {0x6}]})
syz_emit_ethernet(0x7e, &(0x7f0000000040)=ANY=[])


r0 = socket$unix(0x1, 0x5, 0x0)
r1 = getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r1})
setreuid(0xee00, 0x0)
r2 = getuid()
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSDLT(0xffffffffffffffff, 0x8004427a, 0x0)
r3 = socket(0x18, 0x2, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r4 = socket(0x18, 0x3, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r4, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r5 = getgid()
r6 = getegid()
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000200)={{0x6, r2, r5, r2, r6, 0x8, 0x5d24}, 0x80000001, 0x179, 0x1})
sendmmsg(r3, &(0x7f0000000140)={0x0}, 0x10, 0x0)
sysctl$net_inet_ip(&(0x7f0000000140)={0x4, 0x2, 0x0, 0x25}, 0x4, 0x0, 0x0, &(0x7f0000000040), 0x0)
setreuid(0xee00, r2)
setpgid(0x0, 0x0)
setpgid(0x0, r1)
pipe(&(0x7f00000001c0)={<r7=>0xffffffffffffffff, <r8=>0xffffffffffffffff})
ioctl$WSMOUSEIO_SETPARAMS(r8, 0x80105728, &(0x7f0000000040)={0x0})
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
fcntl$getown(r7, 0x5)
ktrace(0x0, 0x1, 0x138, 0x0)
setsockopt$sock_timeval(r0, 0xffff, 0x1006, &(0x7f0000000980)={0xffffffffffffffff}, 0x10)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000002a40)={&(0x7f0000000000)=@file={0x0, '\x00'}, 0x3, 0x0}, 0x0)
r0 = socket(0x2, 0x2, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sendmsg$unix(r0, &(0x7f0000002a40)={0x0, 0xffffffffffffff89, 0x0, 0x6e}, 0x0)


r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSKBDIO_COMPLEXBELL(r0, 0x80045713, &(0x7f0000000040))


r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0xf02, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, 0x0)
r1 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f000000b000/0x1000)=nil, 0x1000, 0x5, 0x10, r1, 0x0)
mmap(&(0x7f0000001000/0x3000)=nil, 0x3000, 0x1, 0x2012, r0, 0x0)
mmap(&(0x7f0000003000/0x1000)=nil, 0x1000, 0x2, 0x11, r0, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)
munmap(&(0x7f0000000000/0x4000)=nil, 0x4000)


mknod(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
poll(&(0x7f0000000ac0)=[{0xffffffffffffff9c}], 0x20000000000000d7, 0x0)
poll(&(0x7f0000000200)=[{}, {}], 0x20000000000000b0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x1, &(0x7f00000000c0)=[{0x0, 0x0, 0x4, 0xfffffffd}]})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x80, 0x200}, 0x0, 0x7f})
getpid()
pipe(0x0)
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, 0x0, 0x0)
setsockopt(r1, 0x1000000029, 0x2f, &(0x7f0000000000)="0f0f0000", 0x4)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x181, 0x200}})
socket(0x6, 0x2, 0x8)
socket(0x6, 0x5, 0x0)
socket(0x18, 0x0, 0x0)
r2 = open$dir(&(0x7f0000000200)='./file0\x00', 0x80, 0x108)
fchown(r2, 0x0, 0xffffffffffffffff)
r3 = socket(0x11, 0x3, 0xc1)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000000140)=ANY=[])
ioctl$FIONREAD(0xffffffffffffffff, 0x8080691a, &(0x7f00000001c0))
close(0xffffffffffffffff)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040))
sendto$unix(r3, &(0x7f0000000040)="b100050400000400000000000101000000000000cea10500fef96ec0c72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b1257aea8c500002018fbfe0c2300008abfba0900000008e371a3f83437320501eab71d89e0000405f8ffffff13000000", 0xb1, 0x0, 0x0, 0x14)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000300)=[{0x2}, {0x64}, {0x26}]})
syz_emit_ethernet(0x3e, &(0x7f0000000000)=ANY=[])


ktrace(&(0x7f0000000140)='./file0/file0\x00', 0x4, 0x40000008, 0x0)
open$dir(0x0, 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
readv(r0, &(0x7f0000000100), 0x100000000000001d)
write(r0, &(0x7f0000000000)="e6", 0x1)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000340)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
r1 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$DIOCMAP(r1, 0xc0106477, &(0x7f00000001c0)={&(0x7f0000000180)='./file0\x00', r0})


setuid(0xffffffffffffffff)
pipe(&(0x7f00000000c0))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setreuid(0xee00, 0x0)
r0 = geteuid()
setuid(r0)
r1 = getuid()
setreuid(r1, r1)
r2 = semget$private(0x0, 0x2, 0x490)
geteuid()
r3 = getgid()
r4 = getegid()
semctl$IPC_SET(r2, 0x0, 0x1, &(0x7f0000000140)={{0x8000, r1, r3, 0x0, r4, 0x88, 0x8}})


mkdirat(0xffffffffffffff9c, &(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000340)={0x0, 0x0, 0x0, 0x100000001})
r1 = open(&(0x7f0000000040)='./file0\x00', 0x205, 0x0)
fcntl$lock(r1, 0x8, &(0x7f0000000000)={0x4, 0x0, 0xfffffffffffffffe, 0x1000300010008, 0xffffffffffffffff})
r2 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r2, 0x9, &(0x7f0000000140)={0x0, 0x0, 0xfff, 0x100000002})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000040)=[{0x30, 0x0, 0x3}, {0x2}, {0x8106, 0xe0}]})
syz_emit_ethernet(0x138, &(0x7f0000000300)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
fchdir(0xffffffffffffffff)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x15}, {0x81}, {0x8106}]})
syz_emit_ethernet(0x2a, &(0x7f0000000300)=ANY=[])


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
syz_open_pts()
socket$inet(0x2, 0x0, 0x0)
r0 = open(0x0, 0x70e, 0x1)
writev(r0, &(0x7f0000000000)=[{&(0x7f0000000100)="e0", 0x1}], 0x1)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x100}})
socket(0x18, 0x2, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000000040)=[{}, {}, {0x4}]})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000007, 0x0, 0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000080))
r1 = socket(0x2, 0x4000, 0x7)
bind$unix(r1, 0x0, 0x0)
socket(0x18, 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r2 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0106924, &(0x7f00000001c0))
r3 = kqueue()
kevent(r3, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, &(0x7f00000001c0))
r4 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r4, 0x80206919, &(0x7f00000001c0))


r0 = socket(0x18, 0x2, 0x0)
open(&(0x7f0000000280)='./file0\x00', 0x615, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7dabb, 0x0)
sendmsg$unix(r0, &(0x7f0000000440)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000040)=ANY=[], 0x25}, 0x0)


r0 = syz_open_pts()
fcntl$lock(r0, 0x8, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1000300000000})
flock(r0, 0x1)
flock(r0, 0x3)
fcntl$lock(r0, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000001})


r0 = accept$unix(0xffffffffffffff9c, &(0x7f0000000080), &(0x7f0000000180)=0x28)
r1 = getpgid(0x0)
fcntl$lock(r0, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0xffffffffffff0000, r1})
sendto$unix(r0, &(0x7f0000000140)="c60467087662f692bce9b2a712082da993b75613e9adb4b419752a8609de085292d270d8c37167b5b22a7d82e7625adca93cfc8f2b5d784f7f2b6197ca49c25360fd2b14df8deaf4e97d51d9fc5d1a2fe69d34e244a9433a173621870102f1063f68a0c977cb2dabb7d39aeb557f6ce498e76eb548e5f38d98d7822f3a6cf4a5a7dccba8e76b50125347d4299c8d9df5e2dd63aab8f9d3bf10ae4a2ead87c3c6c1cf0b7328007a17b46f2bf85b4aad0c28e497cc5bee23a6939bb819a6596dbf7293e519726188c971f666d0f8451b7f8ab4794c5fba5fed51655138aaeedaea110ceb5414c513fc77dc5f3d8c8f8d33548f124a0b93a170f9", 0xf9, 0xa, &(0x7f0000000080)=@file={0x0, './file0\x00'}, 0xa)
open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r2 = open(&(0x7f0000000100)='./file0\x00', 0x8, 0xf2)
fcntl$lock(r2, 0x8, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x4100030001000b})
sysctl$net_inet_divert(&(0x7f0000000000)={0x4, 0x2, 0xf0}, 0x4, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f00000fc000/0xe000)=nil, 0xe000, 0x2)
sysctl$kern(&(0x7f0000000000)={0x3}, 0x6, 0x0, 0x0, 0x0, 0xfffffffffffffedf)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x5cda)
r3 = socket(0x18, 0x2, 0x0)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r4 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x1023, &(0x7f0000000040)=0x3, 0x4)
select(0x7, &(0x7f00000002c0)={0xfffffffffffffffc}, 0x0, 0x0, 0x0)
open$dir(&(0x7f0000000040)='./file0\x00', 0x800, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x412dff)
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, &(0x7f0000000440)={&(0x7f0000000280)='./bus\x00', 0x1000, &(0x7f00000002c0)='./bus\x00', 0x6})
r5 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
recvmsg(0xffffffffffffffff, &(0x7f00000025c0)={0x0, 0x0, &(0x7f0000002540)=[{&(0x7f0000001480)=""/4090, 0xffa}], 0x1, 0x0}, 0x0)
preadv(r5, &(0x7f0000000300)=[{&(0x7f00000000c0)=""/104}, {&(0x7f0000000140)=""/192}, {&(0x7f0000000340)=""/175}, {&(0x7f0000000000)=""/18}], 0x10000000000002b8, 0x0)
fchmod(r5, 0x40)
r6 = socket(0x18, 0x3, 0x0)
close(r6)


open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
ktrace(&(0x7f0000001d40)='./file0\x00', 0x0, 0x1720, 0x0)
socket(0x11, 0x3, 0x0)
open(&(0x7f0000000180)='./file0\x00', 0x70e, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
r1 = socket(0x18, 0x2, 0x0)
r2 = socket(0x18, 0x2, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
dup2(r1, r2)
sendmsg(r2, &(0x7f00000002c0)={0x0, 0x0, &(0x7f00000001c0)=[{&(0x7f0000000080)="8a07fc059328491804424a11b2fa028d6cdea11cc55e5eea3e712fd225f505867123b7f479d6809197b7abb245a6a90d101904863d6e9a"}, {&(0x7f0000000180)="02c1e20a2e0ce81d339ed28b04a60d52cda2b3c86ad335e799f27a1597941910"}, {&(0x7f0000001300)="349409068a157a5d1cd1898fdd78cf8ebee5129ab0adf53061d63d4e70ae40ab544d00f5ca6775ae4f9c1076db79108ccedc8e3783e2a86cfc619429c6ab373acab96b35e818ce5154edd20e074dbe033ba9c2af6527497f77063821ec83053996276228d6d5dbc7c13718ca1113bea34ab01fc2932518b5cf93c3a051aade6f26347a74540c310eceaf2304da2d4c37d7b6d0666a67ea50ecf1d2fb7336a52f08695592437406e2ad9d4c9ffbd260dce6a9eff53832111728a7b100fe85beeae0825a2adc97dc1d3eee31d6e482e19f50d8f03b7e92621c09de112e7663521ecb604ad3c5f7902647371e116514953405a10bc3bc5a010d9eacb8f4ede38de585066aaa8ee9dd4886ca2cad43144bd0f3c0809f05382fe0b1b018cd0a1bc3b61c0dadfbc11e7939b47897df90a75084cd4fe203623abc7bd607a2ebc5e8ff0a933cb3498567a9a2941a063d86e263090c95ef9faf103139fa509fd5c76a0652b1e2234816e854812ccac047dad28403551275abee2de74a226ffd6dadbf7b5f550c7f46fab2e11be5af4fc7bbfcbe42885f9d90ebf01523a97dc84416bb4cb755cb7d3268ca6242aa1e0c8bee4bc0efd34a28485acf30427cda6125bd71de4b53a615105e19bab53514e8b1c6f59461cb0c3b4cbb0eb88d3da0534d20a665096e396278f7d4e0789588f420df9b7025f9dec8d2f4deab15687d69a056537b44723c2c12bfc1ed2a57b6b1fa3fff9587e81272484babaf3ca670099edc163a40d67931a457fab205604347d078bc6069602a1ec600475be8d3e0beb8e2528a5bb3d937ff37000c487f7d14f5b8689bc77566719be278e2bf3a293417498c34989d159b7ab42a6d4e0a83df7d4e96f8c537c47cd3f50c19b5576a1830f51b7dd8505607401263dc37e733e5d9e6be4c4a3ce3430228a21ede7d7ad81572f33688fcf39585a9b94169107b8cd092d5bf8861177be35ab14ada48e240f90ff38556173573fe1e3697f27a94a472397b1528fc7269a83576ce8a49f9b4395ba565bb9645818f58ec1d863c61a52d7a6dde3cbf3ea0ccdfe225cd696783685784ca798e4f700c47fbc159b2b41c6573b63061ee61326545d0d815d209b6b07ffde9750a423d4ee028c8ed2ad847ed21bdb58a19c6b4af36b916bbe47272bd33cbdb2bcaaafde3be906ea31ff2f123cc77868ffcbe9cf359390daaf4377101d8454e20cddf100084c0c0688a67d6772c945d27581eb4a1b2e40b1ffe2351ea98114d14d2e4bf3df16e45ce2def4aa9d845a04a27325a697acedfb23e891eabc1e6c8df87f02dc96ad245b3f884b75ff7d6fc421eeb924595daf33bbab051533a9927706a845f92cbae3277a4092a1acc93f7db688de0622c0680b96178015232b5db6a347bb8635b1792b43998c0703519e7ed1a34d66c806e10c70405a6bbe9c62433083d7108974224d0eb76f271b317749ec4b797cadc773d3d3314d9dad7510283080372917e00860d29baba7ca6145fb582468ef85d98b5068d7d25679386c723c47b3fac841731ab44d8935159a4f0d40a937df2c26aa6d6208992487648bcf8cc29d05cb447636561a532b0006ecd363340285cab33fc67d99305b38e66d533a089c20c9c64e96c6246f3c9a6f97bad3ef1abc0854d5619aeeba72cfb62a053245e32916987175e2f527ed6145dad3d46f98b10414c9180dc2c9b01eb2b6e9a58b96547700329febf9a2d9fe9325e5e35e758559ee4648ae2bd392036496b473270cdf3c6083d67ed4752e8107fff174d787ee1067af50f2e12ad33636ca1e3e1b0b98026c1d7214390d53990a84e864b8320cbb9e21d6db32b700265386e8bd338b6b601736ab8d1d8871356ec79fef672aba8074d8acf07def315220bcff5fb03d5e7e57b1ff26732ab9fd571c2876265481f8eaae49b13c840ead6231e7f237a9fc4ed83c3588a3dee05fea7aaaa5aff8e152c8d5c356e1756b2aeeae4d778718f08847421263f2080267144f1eefa5539f8c5b320cddfd4042795822545583bd56951f3f0760b9f0f74a481f29d11c1518bca77320b96a154571c627d7b1d57f910d002b51be7b2a4c7964953c6b80d5b182b7b2227211084c6b036473143f5244ac3e3b392792c661166d694927a8cd948c2a5bb7bf10cf314cfd85f86077b41e9b34c2dee93e671a50a5fafbfcf73f64f5a1afc92d194e310d3b819b90bab16ec7aec59c176dd463c955c14d718b49ae2bc812dcc30d32ab9c83156ae7aafd507bf9901c367c84e292f0af9ea29d2705655f54223f80eee9466faa5cbc4d46ddf62b37acf12063af4024ac1e336bb457b3c2bc0f66c6418c657012bb3aecc900c16b39b86f02894fcc60da0661d0669eda1397aaea4658813ad3868b6693a02be0ff75f64a672255dcc85562fd9d52d97d3f7c911ff9de786bd607abfc6e21d06d22edc93b1c95155c5e998b1bc45b3a544cd698eaeec65322d6b7df4507b19f77d15e8856d15da2abf2be48523eeb5a9971afc617e215861740629b9f0ac1e42d0d904ebcd70e207717c16a57f938b823644cc091a2fe85dd066538318bc2cff34cd4231164ea06300b4d1de763b7eb0fe7c8600a44647e6a760eaf9e91a1482bc3a39c749a426f990db81b5a930d614fbb295d1edda9be352961685b4cd477f3db580f04ee59f27c27f212efb82089f2d71d6951bec7146efa7e392cff3776eb2d10021255a749859a082a265e43eb60896029b6af3ee4e68c02ce2e150045d856fbfca1bb1599169f492722de75dfb81ea0579a9789a1b1a964f534feea3e62d670bd4be55f84a932f644aab077bff3fa9c110224b4e381965f4a9af2e13d7771f5a77498a74deab9de3c759723c6fade4713cc1f857069d889107018d95fde366a43b7b4237e9b903e49b8c21c7ff6aeef833fd79a35c84eb60b3bbbff67ea6243fb214d54de7e276ab39ccb0c5e40489635a44c5aec4978470f068e4c264531b921ed2212f6a06a675da2607968b13984e502068e24427aea33d1647b906124490bd4e9133adb014bfe71a98de1a37566e8c9c65d119131b41980c41be9dfb4149ef4ab6ce2ec81c731466f9ad409f097f7bd0fb6134325b64ea6ab40d6dc001802c6dda494343aae424f1d0e46b582a3a849f8891bb44e4c4a47967db604643cd3c34eff4d646db8dbcb867b4fae8581bb9a14f620efd2fb654733f04420ce010de178c38ef719414990e3742c00fdfd5c3b14c4883d50a0289397fcf08f503134a12ef8f2bfd669a91a5e813535d5d256b1d98490a1795979664dd768de802a0b479b11ee72aee7a0fa021f224ea2418902d2dcccafccafb194ea7db8410e80f8648f96f46df94e5ee12c146366a7dd483caf164ff430a91434b090f07082a3ecee4acea1889f4b7be6cffa58a7f0c4c0af20af88630c9d0ebe64e65204c4da50fef9c19a3f88a57c0480abe449ea08791d5f217b927b13787962234e708e9aea67461d6e2e9db8b3afe6666a33eaedc1c0fc07160705a3098f2394f2220d91b89693eb0533b6512bf27820608d11cd8e928a636e37e296d5cb030d567cce87a411416e7bcae80d21b38b2f50cd80f7b7ad205dba1af9e76f6e91395c830cfaaf0750bddb278687d2f70977b50f3fb7dbdc3ac0aaac14dbae97f49cf40ba6832e4c016e3dd397ce0429ee0ddb637a913c200c7e9384d1f97293db4f86943449b621aa10b7868df92558b8b1788688225d07ea0000cce709ce67ba7be299d0fb950c602da1d0228a61d65130879f6015d3b4787096f04e9a8737d627d4cafbfbe60df40f1dafcdc029d9bab336aaab0a8e9d49e61b127687bbfa40b6e126031be5ab2045c1d5f9d8c5d8f2dae487f5639ce0f57a5fe908d18a282b86c78e8cf6b2bad426d22742f414b30d05386788e65b8ee3b58c36f7cfd1e01e51f02491a0c239ff7d4fefff13dd3565e7075714b634a3c764a1a17126a3ccf451fb60e593be9551b481e4c93c268c6ce7feef26b54497907c721963c0cf6964bf7c194c137b2acb78350854f0a72503444b799d622d3342224e10cefd05381a222e99648882a4f39b65bcc62b8a6618075084819074dae6325e1826a68ccd45b940d8b7bcd38c00ecbfe72690142cf8ffa1b86c37ad7e80f0cf2b39abe0afbdca0f17c97b6d7ec666f335e7ef848946f876870c74fec8dac0beda5f8f5514476304452b936f0e343e440460d578d80eb42d99034b5894b16049f28f1e0d7679f35b672bd241d7bf96f2ef2484b85a12743eb8434da5e35a6c99eeb451b289a96f0a0d41e9d555508de504ec63c4628c02abea2d0ace115b7b1fcaf3679d4f68b45785e1ff2d7ab135834f5a34d69a336e95e64eb754ba9c67cb9787c2cb4a115f09fc70ef5bd87295b0287a8fb33789d53c9de6daa6058e29b017af3acbaa3269c109f131737e91cded362de0a080577affaf912c25a302ada66f94358a1baf648a5d8f20a7d588b159e49ff9ad9634fac8708093990e5cab88d4b2c52818c9fcfb584b9a83bedccec466e94dc5cebd892d89b9059b69ed69ebd52f5a736fd8dd8caac0c296a8e992473cc374d81dd5cff98c7788ab590e450b3b0e2f3d3353e14dfe849847b8b263407c7ce0e45ea70192bb7d0f96ca5846973189abbc9e71f73f2ab4395ba9e2681c67aeee2b6d3ce009b517c0872f3b6b906b9ca86e15196d38aef602a5ee671d511993c940802a4d3c4cf98ee012f5111e9c10e46cf2110afd22ed016238e16e8f1e9bac75c84f59b692e2cc6e4f9e0edca7e85c7fd19989f9de4ea904a572de19af3b8c70319139c0d5c035e54ad3436f6e5cc1bda4e252dbe5335fc1776794926fabbab1e7039e43b112c3b83841fadabda56f531245b1140483fbbe548691b3ddc569fa2b5d156698ca78cdc5d11aef9363fe85eff0dc2292024bba9f055316b1f0b9c08b7729620e4b459d7ceb47ba6de350421dc71698b1494b14bc35be2c21cb125c36230599ba362206d8b9819e8a186d90a218b6195c26ea7e6d215b8c7f210e350396e87e3b9fa302366a91327be7040272d04125355876cecb6d8f6ff13115806cc946f63bfa4ea7675eb11fd027a13fca8375b4682f4b669fb9f7f04320d93e7f665fb3307092e4bc958b4d33604e262f374956f87cc811becd7313c91bbcbefbd4356426d90cca601092a90d16c8dbd8e5e8cfa2d4fdb0a6706682c993336be10378492a9c980a5def332c2a3266f4c3460d9ac4a06eac3addf223454d6896ece7824efadf29f14c8e36b9631891143c952e1f67ca3de76f93ce410d74147eed5af08bb3ce37eebd3cbbb2baf77ad57ffff186f13ee31b263e452c4a6780e677188f872944d2496167ce92eef6f33b16232e6de544c9d0d3a77df877c7ee3c4e2b464fd261c2446bc71d20bbd9947e1de113933efe365bebd8b1de05f0cf11d842c9cd9cbe03dfdd0068ba7e207e48d44e17458ac4420769ca9f3d9cc11bffe6cc16313167b605cee6513989fedd77b076a57a6779cc3cc724b1e2fc219bab630f310e7ec903e74d2a6deeb06179c1d8690ce46a398eeb318d61ac4cd66758f6262235b931c510a5b78f02a3ae00258cebf0ab362c0ec0fbcc6e41b7c6b83f441cfc907d811eae3a39aaaa0b91bd3a3066d1508da3e3df742a97e5e4ff88c2a56655f3efadbf78cab2f32caddf31b9513036e5cf038fbf5641cf1b6e75a961d91e43b299b4e72b6d210902c1a9ca933c282c941b14f336dff31bac5848f12e982b99b7285e128fb000000000000c6159beeddf2165aa1fe5374321ee849bb33733832fb16632ece8fedb7b06d7d2b0159b2c9a85907ca47be9e7c17bacdb2ab0fb592945fa51be18ace572681be61"}], 0x43, 0x0}, 0x0)


sysctl$hw(&(0x7f00000002c0)={0x7, 0x6}, 0x2, &(0x7f00000000c0)="f0", &(0x7f0000000000)=0x1, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f00000004c0)="4b218d114ca7cbdd5c6a2dddd227668e017145c65853de497dc18ddf59a105b91f005be73cf00b391289af5024c2f9cf6310c72a6df943cb04d89cd258aca3f6d5198417cc8efbfc5f10962b93f535443a40f2a652c64a9f4902b2a6158afbb6aa56e29f471b4d49178f3a22cd669126ba919570518e0fbb081d7cbfe4263801f636f8fea45f8b795a1e56f731c5d3fccfaba7e3b986e61a5401ac0d6632fd4afb25b3360ee9f7acc74263a6a947479373bec6a3aa6e5f7397f9e40f86ded6c437e4f2ae29dd9dc958bba2860fa3719d01", 0xd1}], 0x1)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
open(0x0, 0xa02, 0xc)
socket(0x0, 0x4, 0xc7)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
syz_emit_ethernet(0x138, 0x0)
r0 = msgget$private(0x0, 0x0)
msgsnd(r0, &(0x7f00000005c0)=ANY=[@ANYBLOB="0100000000000000bcff98a66a978da027ee68af00d1ed8f0f2b77e5ae7529b162945aaeba93ab1e0a8cefa732522d95550700000010c638dddce23c10ed7a5f245f42212612be75f87e545d03990554eb20558e0648dce5fc980663c99a08ef466c008f1c560b69f47f0c4582164954b7a099f6b0aafe43e1c76cc297349f151bb74e67e0591109b060702ee5b49d098e4bcfe6a5938dddb6b40715ea48817d5b8d8795c0fd67554723f6b51f7abed257871b35afdf329dded2b4374086e2b362f7"], 0x19, 0x800)
msgsnd(r0, &(0x7f0000000240)=ANY=[@ANYRES32], 0x401, 0x0)
msgctl$IPC_RMID(r0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
getsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
open$dir(0x0, 0x200, 0x0)
symlinkat(0x0, 0xffffffffffffffff, &(0x7f0000000c80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
sysctl$net_inet_gre(&(0x7f0000000000)={0x4, 0x2, 0x2f, 0x1}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0x0)
socket(0x18, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x81206919, 0x0)
openat$diskmap(0xffffffffffffff9c, 0x0, 0x2, 0x0)
ioctl$DIOCMAP(0xffffffffffffffff, 0xc0106477, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000000c0)={<r1=>0xffffffffffffffff})
setitimer(0x3, 0x0, 0x0)
getsockopt$sock_cred(r1, 0xffff, 0x1022, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
chown(0x0, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
dup(0xffffffffffffffff)
open(0x0, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
r2 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
getppid()
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x10, r2, 0x0)
ftruncate(r2, 0x8531)
r3 = msgget$private(0x0, 0x282)
msgsnd(r3, &(0x7f0000000d00)=ANY=[@ANYRESHEX], 0x401, 0x0)


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
mlock(&(0x7f0000ffb000/0x3000)=nil, 0x3000)
munmap(&(0x7f0000fff000/0x1000)=nil, 0x1000)
mlock(&(0x7f0000ffc000/0x3000)=nil, 0x3000)
shmget(0x2, 0x3000, 0x410, &(0x7f0000ffb000/0x3000)=nil)
poll(0x0, 0x0, 0x0)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0x41946465, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
select(0x0, 0x0, 0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r0, &(0x7f0000000040)=[{&(0x7f0000000080)='\x00', 0x1}], 0x1)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0xfffffffa, 0xffffffc1, "ff8b7482000080800000006906243c00"})
close(r0)
ioctl$FIONREAD(r1, 0x4004667f, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = dup(r0)
ioctl$BIOCSRTIMEOUT(r0, 0x8010426d, &(0x7f0000000000)={0x0, 0x7})
ioctl$BIOCSBLEN(r1, 0xc0044266, &(0x7f0000000100))
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
syz_extract_tcp_res(0x0, 0x0, 0x0)
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)
fcntl$setflags(0xffffffffffffffff, 0x2, 0x0)
writev(0xffffffffffffffff, 0x0, 0xfffffffffffffcf4)
readv(r1, &(0x7f0000000080)=[{&(0x7f0000000180)=""/15, 0xf}, {&(0x7f0000000040)=""/17, 0x11}], 0x2)


setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0xee00, r0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = kqueue()
kevent(r2, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x8020699f, &(0x7f00000001c0))


openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000400)=[{0x5c}, {0x3c}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
fcntl$lock(0xffffffffffffffff, 0x9, &(0x7f00000000c0)={0x0, 0x0, 0x83fe})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000080)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvfrom$inet6(0xffffffffffffffff, &(0x7f0000000040)=""/30, 0x1e, 0x3, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
shutdown(r1, 0x0)
sendmsg(r0, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x9}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x400000002, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, 0x0, 0x0)
r2 = socket(0x18, 0x1, 0x0)
r3 = dup2(r1, r2)
sendmsg$unix(r3, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000600), 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000200)={0x4, 0x2, 0x6, 0x14}, 0x4, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
close(0xffffffffffffffff)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x0, &(0x7f0000000040)})


r0 = socket(0x18, 0x1, 0x0)
listen(r0, 0x0)
accept$unix(r0, 0x0, 0x0)
shutdown(r0, 0x2)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd02)
r1 = open(&(0x7f0000000240)='./bus\x00', 0x0, 0x0)
pread(r1, &(0x7f0000000040)="3cd15db7c30016", 0x50cc00, 0x0)
madvise(&(0x7f000023d000/0x3000)=nil, 0x3000, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x33}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)
r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$PCIOCREAD(r1, 0xc0187009, &(0x7f00000000c0))
ioctl$PCIOCREAD(r1, 0xc0187009, &(0x7f00000000c0))
write(r0, &(0x7f00000005c0)="89", 0x1)
r2 = socket(0x2, 0x2, 0x0)
r3 = dup(r2)
ioctl$PCIOCREAD(r1, 0xc0107002, &(0x7f00000017c0))
sysctl$kern(&(0x7f0000000340)={0x1, 0x17}, 0x2, &(0x7f00000004c0)="000346df11dc9fb31a3cd1ff8abc2db41dbacfc6b2480ca941dfe40aef74b23ceb6a8ff07084483416dd1bf09f35082bdf1457a73d5bbbdf95580c0c46a6166ece9f61629c6343ae350b", &(0x7f0000000380)=0x4a, &(0x7f0000000540)="90cbee49f524bd66eeb0ea1545298c43b6e301a798d51aa3c94cb9e2501eaef408dd9b17600b83e13a3390cdbfb2f2643baccca7873a5206cb76382763faee6e6dd42e761f614ffd74e4f205eddc622db079fe7da3e850ef5a6838ac63f44da042babb2809b8974330bd79", 0x6b)
setsockopt$inet_opts(r3, 0x0, 0x24, &(0x7f0000000040)="fd0cc085", 0x4)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000040)={{0xffffff67, 0x0, 0x0, 0x0, 0x0, 0x4b, 0xb046}, 0x6, 0xb19, 0x0, 0x0, 0x4, 0x9, 0x9, 0x3})
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000000), &(0x7f00000000c0)=0xc)
sysctl$kern(&(0x7f0000000140)={0x1, 0x23}, 0x2, &(0x7f0000000180)="9e7bc98c60806a1f79b9ab5cb189fdfb887ef1370d33f8fc058759e979722176d17990d23f207fe7d1b56a081f44e0cd9564df28dcbfea356d4f4d1db255d867dc13050faea27c741e406ed7ae94a26b989acbc16f5fc45fe13bddb9f28a32fb7a3696fc9c4cdc8012c0f9c916254926bf805e54ffdd7b76a74df53b229b50b3edcaad55631437b27285665db67275a1e52dd196a093530b3762eb1137245609586c482e4def146f9693fda559889edb488bd0812db38ecc961bdbc9c73b1115fbcfbe0e62e3f99fb459864e6deb92f54a1a82efe671d32bba", &(0x7f0000000300)=0xd9, &(0x7f00000003c0)="abbef1d3cf4c36bc597cab8217ba8402c753ab763c62946a210b6a88dcb0635dee719e979c87c4ab8b33cec2beb87cfc97328c8e864c0c06a258ca8cd1c35faad0c89e72fc5311196bc7c956eacb793211cc46b17da3b05481c646b24c670eacd1e0889a3d0486ae3a007bad24ecfcbdf98919af55c2161b52c5cedfab17ccd43d6984d5bde3e4ddf0bf96cb951d1c1a90512dfcd78ec07079b5af497d2806d66c73042f48934673a642031a6a6d4fb405271406f49d47050c59b9da9be1fa3adabb19c4e832d54906b33100f854d5ee", 0xd0)
r4 = semget$private(0x0, 0x7, 0x3c0)
semop(r4, &(0x7f0000000280)=[{0x3, 0x5, 0x800}, {0x1, 0x2ff, 0x1000}, {0x0, 0x8, 0x1000}, {0x2, 0x3ff, 0x812242ee9a8c2935}, {0x0, 0x0, 0x1000}, {0x2, 0x6ff, 0x1400}, {0x0, 0x7ff, 0x1000}], 0x7)
semctl$SETALL(r4, 0x0, 0x9, &(0x7f00000002c0)=[0x3, 0xfff])
sysctl$kern(&(0x7f0000000640)={0x1, 0x3b}, 0x2, &(0x7f0000000680)="9a995e5cb942517347a486ed84fa72ea5c1fb3adc68ee4955c57dc0a9925312561ee769f42eff520f47f23e860e24b5e182b72dcdcfc0ed9c9e5730bc5d53912179fb8edffb4ef60fe85035f683e8fa03c84aab3b3966e865ff2b40155c03eda0ba39f1faa21b4c8d76f58351c966089cb7b5b82165647f5998db6fb08724b00a17aeb71aa4c00dbd08dc816e7913a8c4790ccf6cecced247e20d3697f5c880662", &(0x7f0000000740)=0xa1, &(0x7f0000000780)="fe50cf8f532022be7a1092aeb93b6554ca6b2c71c2d533d7dbd4e6c4bbfce146ad5affe038da2a62bc0b76d172bfbf328751f0b4ac8afe7170cb882fc17c24f19903bc4a3d4568775754ff632f5600a20d8354b6e1f205c73f14e6197b686b8f5fd70afdcf2dd441f3b9659b4615337b74a7ff30409a808f233c63fe4bebc0f3d828fe67c63c026093a204e692b3d0797f65a9cd011d2bf47338a075afd1f972feb1b7a2c0e4ec6570ac5c9a44ff4ebb1e29e833825a2f174dfd9b45b4fd1e305440107ae09eff1925d94b9226734839f920778a7004633ed52b7157967a611be7459dab10674443af6c2d1675e0a4fbc31017afcb3ce76ede0dd84ff332480b68d667d4b4327f86ddf00215224de9baa09464f95de2227df27790cf775fe1d6b5194c42137833fd9ebe9a8878c5c6392942ac172cebdac5ab49e4368e9ecf2908a9b65765168d9a17b445d15b9b209f0976e9360a50384c3a078a85d09a9afe63598937e047f06473603dfa730f1f4b48232b3d459c95ca701d2965b027124a2b52b93be033ebc1ab6ffa4c5162ad839aab0a07b2decaab889d9a47259809a5be3b1acde2a5d03b25d4dc870971895a5e3ec6d74ccd613c2f1146f6f8a1b8900d92718cb96fde2a8a3859bbf961c3ac14ea9c6856eb38254b4a3b3908c6b5382f1915f6ad5864458933449cc973565e29c00f831e1c2d197dc284cdce62e059ea230e9cb32aa525fe7e4a5df9a7e5de79ee355988b5873fc5b8fba6b441f80a6f696cd35192ffb8de7b430b2bf975381eabb2d9f90f81a6489f5f1573ea70123a041339df42d26b0038907403846d9c172d28d72bce95e9221e1678d52fbb1ef0d9063c562d0eb35dccb643c036ee656a8fcb4c0c141fcc395a25f8f75456cda64704641770ff52d5e6ee9c257059999b1c0666c5dea45c8d349ebbc87554468657f5484c1b5622008801ca9d263b172913f2fbc0e86d104f0ced58f07401e932683b9605210f55f595ac8d0b2c1c2d380cc2b2273aff0266ed37a5a6b9549cd5135163a5584bcbc74f31cdedd83f359dd8e61614d84dd87e2aa9f36dc3e5550fe162cf670b819ec6da5cc9cc1c1efe82d35790f6e341f32299c4fe5a17d73a1e8a6916f888cfac19104b2219fd7bf22be6f3ddd8b4d1d4e34fd3d9868c155d7ebc56c3413d52301276b6d5f518e6332251b4de76c7b0b079d98784a74b8fd5727e01dd09aa5573d9253438c6beea5bb354d2631e79ab002aed9c2da2a10ca47eb6d2dec54011bd8ad3e29dbebd8e7f10525f304ff136aa9bba1d7c3bf499624352746b7c5378bc10d306fa57e9155ebd708d0098856790298a0dd16438259e70b24bd343b04ce0718c06606810c0490d5da581339aeb80731ffb5db41e76487ff248a2e512fbab7261398808533cef47df1a03426f04d46862975666f67efe70b7a6c9bbe41373ac5bb2b365f61d4393d6b8af9dc947b0af0dd1556a85ad2b91f35f1000d50dcc2b7c55bd5f1ec4eb24bbf2bf0130ad1af7554953e9cf36ab0c40dda0363dfa5b0827eb9c4cdcea3e1d8d3f74df6f57d0f397438438d571d15730ed68081bedae2fc336812c8d2a09c4a8d88a9291ea1a2bd5cce97abfc959c51f2823f61e31897c6df9c72718da2a4f3090cbed46e65a5deae856882ecfc884238b3e73225d36e32b2f2001a891b18f6c299f3a123d9bda274bdb2913080537c3ace42ea738c55ddfcece07539d8f2e3bfe57e7627c863a9685fdb5bedd669011c2bdf132edc16761bc20cd0eb8126485580e818a6f89e0101d02fd5c9ac3463c28661f9891055c692d347da10da71162b366b229f5637f9ab3a22867e04faccf6cbdd0ad1f3d455c9bdc8186b2e63753a5864affd874b96221fb76b4ba99fe751e97184dfc746a2822362c2804d384f357f17983157885b21b595f3232fa207f5da77f600d1dab4f6010a156d4f4a4aec1e44b4a0e1048f3c2919903c749932dbfd112623e032a76f8e5e7f6b1f440b8fc00d8c8f215d950477f543c7558e6a5f3d1084077f9d113bfde6f6e62f11a3901010624d3d7106ab0d66c917e0330904933498f8516c10f60119a136fbb590a27cb5dd9a762b2f90c717014f71c45001ac398f92007591d3443ba433eedb9ef4111ae27dc887b84def7156771fb64d8f1d461f946805ce60a74eb13bb5733d43dc1ec8728ba8f6a3b926da2407e595c35f717ff0966ef86fa1bb2e8b0edad51509f58bc2d925d41ba50faf8cf32d880f68b9946aa4ad5f3ea294fb2a30279197961071c2165d7017f892daa27748b2abd13d68df7c1d4376681507d76c5d1d82efb70c711bd2b7ca4ca964f8165e704bfc1ba5916398c9db022af5defeb0486ecc001bf7d365874cae1b51da1be351d59323ed223fb3dc5ec945c3f7b93e6261ad2415f116a911598f7b3e040b92207a10a1df3d3029b46ecdc63969a42ac081bdcc533aab1ec8df8dbd0646d34db822e1ee98f6324d0abc1348a4a3e474cd5cc08097e547df14274bc728a0cc310442eb5340c5ebfb4aba5e0a0a61800688d772be79e9521a8a7c23487f318f21bdfb96b68244c869a5e3843e50b326fba57b41d59948544fc7584b0da904f41fe6f0f42d1457d94f31961875eb20a33b8318e771509d08a5bf2f5e885ea75ea3fa27f98f998217ece0436fd2b3b5139d73e916f3ccbf0765b87da8ee830cc23943e96ffa88f045719c65926514836b9b88d8a0ac192cdd09cad9927d66af7ee61231d050efe34e85f7babf70ab9f026b18c0fd2b6534ba8ad581e4cc68e399b1344cd9a334e7dbdb9f125394d88d4e468e3ecec542b041cf65dd785e02bdf2e706bd92d3f0437d528e573dfd28258adedd88306e6dca43c74172b167000a225ec40a7d44980782590b121e32bd47b26fc124635d907e46e2a648111711eaa4991b1c1c1bb6db5573008b95c47f6ae72fc43ab16451087fe80a7cfa857dd277870d51b4c177a9bdf6230b93ef4187d08314081be6aaecef918d21176efcfae6e0ca905f0715b892c716567e0fc4041a9be7c636b1f2253b1e90a96a3a06cb9ab960d35a86e4631e0fd56a38d77991e7a74e5ddefbbd5216298d316541e207b0f39ae1924506cdda3c387d7e9d97a6c7107db8425212f630be9df04d8a1312e7c506e9fe560ad151fe014d96fc93d530a74413f3d61440ca9395ebcbb89cfedbce827a5a7456b6490baa77f87e2cf17e4b45d2cdbedbc3a8f4af3c728fc74408eca460bc1d909d8e20261ab8755ec93884b0713e8345beb0a3a28a8d4c36c8e9d2e9d1c6429ad0a7fb51741e5a70c605651ac8e86f5661ea2e428e489c0b42b8af42a6195a6a83557aa41db5af39624744d3cdd24cb6cf78d21d6ed2bc900db8e4d60f6b5cac86e82a4bdb3b11c08d016fc83d5ed8e067d31d43399efd314335d8877e7cb906ca9ee10224d7cafd2db74024a2b8f3cf38b2e5581077d1dc7da1ce98427af343869157cf95b750629543340c7262e2d21f73896b8705cd34f64ab1387747ebd43ae321020dc3013f36a05bae1dddcb0502471a7baa2c19f9660e8480a41e8cd669b256f92840e04bf88a64a73316639133b003e53ce56f1dabd7908d2623ad922a59a0bf5ead1e1ed9af11ad919c11525b2853a20ae72168e87a6cc18a14637b218a5fb6062f65d9850f6811b8a708f2dc901dc8c9c2111873ad1c22bdacd8b2c3b47875707b60c19621862773147714be5a96fd6574c5a95bb11b4f51127a54491883e43ba19004427d8a09496d0bdae3799e626ce25cfc65161c8be45905a445dad3a8d90e1e6828630a0348e2ddc176a2995dfcba459d64a4b491d974309d8d2ed5e0ec0fb969bcf0c5d6b42925e023282e88d704a45b59860dd46b7978ab74d689efd986c9d15f8222776f294a111f5973ca6c47c9ccd9e0013f08a4c22e23122c84a481a5bbd11d5ce26f9fcbeefc833f986e6a32f80cec255639882d317b7ff88153ca8d05d4bc4548df7846a3c2d8f7910ce8c030f69ea60babf796f2a44929a148f78b06999fce80c56028a435b5103b81cebc64b54391e26c2d0dcf3be83a85c147ff0286bef2eef06c88ac6bc853a4f80042b4ca72d5e6d390b51492de70b1b5dac38ed1d0718c8de4682904eccb1e7187e858fe25676bcf8bf7dc82decb0270c7631301da20e56453bf778e742d61f175196110c7b5b01c934d5116f156b713abe3b7e4a9887274262af0165f4c44c3a89fc72291d6d53210c5bcc85d6409b3f8d5216cc95e4b233469d07e9219b38ec6c80d17281990f4283004aff05ba8a23734f7741a14b3e80c73fad1087a3cfc865e135dafb59f6d62e352705442d55fcedcd83b30e897b91c5a3ca4f4db7f87210f834085f4bc90bb5c7196e3daf5640e1806d1524cc3e976fca949beb4d3cd62f0e1152e20629f424692569cbe488c621ab4ef19ead4f8dfce418f4fcd776b30559aea174c1902ae0ea2f60c87b242061f1c53ec206782f4e3003cf6808b98e733bc094ea20b90e15f89a354a2c13de7516d6856471002d87ec46c90a794c491dfd6c01e0cde823d06833c06f9addd6236bf8296ef28d493a80bbbbdeebc2bd9453f690ff8d994ee7a74089a3387e653bce234acab10323debb92656bfd0ec00e53a378945329438d8bfbb424af2c19d2ee070112b6283c1f9a6b7395e5852f7d499ac28bbfe2818a9f129b6f9564ca5e01b14237669b88343167aaeed29d9f42a366e4905541131b7df032ee4b4f641025f0572fd63e5dacc6bdb1abe473d3dcaf1e6e2815578ab952fbb66436955731ed20e620080026b21431596352cb2cf5a17a10470145d160139b177c12141f8362a573f601b815951d17bedad849b123715ab09f7dc6f29e787596697c98313eddd4bc7cf677bc995954ec390249ffa4c06b0fa38a33d1097baaca71678dcc3945695b2fd0d4b1ad9624b9fabe1ae2016f122588dc2b989b84ada3c6fa496ff58271fea8c76bdfd178f50d3a8a50fcebcab079c186a9c2a0a6e97f16930985f23f714686eb98653a06723d8a43c67dafe4fb825d147f5d12300a80de061f436afb94334ab20145318b04075fbbd0edc7d12bceb08a87a8e301b63eea8a112af2596ffbc8438888b0236612ce2637bce4e19772f13f19c15ef6c6c26b3507e72354f1c0b967951eca6762825933fefb3867c71b4016df2f5bda1a7686b84fb9fa7955899ac3930a742a63e8ce75842417b86a04bfbf0c6ddcae8c556e31192b3191867f7cdd1436bc331461e3a653c8404f30b6c3a6ea9c25bec320d1c1c96aabf2b20abdf3182fb52270a7a1e81a9225e8e6dd1dc0fab59bddf6ed341fde7cd3c6aed52c010b7ac99f5316ac7f88bdabb6165b1e62d681d86bae403a4e68c513c15014ebc1b431afe770f4f962dc26835f4052146f0e68cd6dc6e1d76819e9e8a80e6974ea5ebaddceece96ca1c3b397608b94c1e300e9ec7215a73fde210bbbeb1cf57fb3ae66637667223bf94b207e96d1044ef2871513acd78ac1fb3f0aaaebe3aa28197b385cc96a5ca7f0648430bd177c7f9ce81fbddd02d218bdfe5dfce9aafe81dc9e1461c38408482458915c605de6dedcd6af88655d51331ed9954908109adafd1db934995f373ae204f6da50ffaf94d368cd88b8e9789779fd84b5603650bfc3cc9cb0571826729ceebf0b2503f90c02c478435039edb9b6089ef5cb5bddded5d590d2b29cd1c57dd002ed2e764d52f2f3aaf23e35bd9245b1c69b7f729352961f6fdb2d58e742834e0c857ed1f39f", 0x1000)
r5 = getuid()
sysctl$kern(&(0x7f00000018c0)={0x1, 0x36}, 0x2, &(0x7f0000001900)="da7411c1ea13d888a6abb67da17a01d8670315c2d4cdcbe9447d3b34cb0791c245ceaea949f9693a134ac7d49b1da2ea184f7f8864a2abf4d20cc46b6a2dcf926d2977723e944cad038de91e0200000000000000aeddd2edda0db558955e09eca1bf05000000dca18ec4de8836c9543ccf2eff", &(0x7f0000001840)=0x73, &(0x7f0000001780)="1651af6318404cee8b0b7f4001040000002e5d52", 0x14)
chown(&(0x7f0000000040)='./file0\x00', r5, 0xffffffffffffffff)
semctl$SETALL(0x0, 0x0, 0x9, &(0x7f0000000600)=[0x7, 0x401, 0x95, 0x1, 0x5])


r0 = open$dir(&(0x7f00000003c0)='./file0\x00', 0x400004000011830a, 0x0)
pwritev(r0, &(0x7f0000000340)=[{&(0x7f0000000080)='\x00', 0x8a8615b7}], 0x1, 0x126)
mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chdir(&(0x7f0000000240)='./file0\x00')
mkdir(&(0x7f00000001c0)='./file1\x00', 0x0)
chmod(&(0x7f00000000c0)='./file1\x00', 0x13)
setreuid(0x0, 0xee01)
mkdir(&(0x7f0000000100)='./file0\x00', 0x0)
rename(&(0x7f0000000180)='./file1\x00', &(0x7f0000000200)='./file0\x00')
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
syz_open_pts()
r2 = socket$inet(0x2, 0x3, 0x0)
getsockopt$sock_cred(r2, 0xffff, 0x1024, 0x0, 0x0)
ioctl$VMM_IOC_RESETCPU(r1, 0x82405605, &(0x7f0000000780)={0x1, 0x0, {[], [0x1, 0x0, 0x0, 0xffffffffffffffff], [0x0, 0x0, 0x0, 0x0, 0x0, 0xfffffffffffffffe], [], [{}, {}, {}, {0x0, 0x0, 0x0, 0x7fffffffffffffff}]}})
ioctl$VT_OPENQRY(0xffffffffffffffff, 0x40047601, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
r3 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r3, 0x0, 0x1f, &(0x7f00000000c0), 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
bind(0xffffffffffffffff, &(0x7f0000000440), 0xa)
r4 = socket$unix(0x1, 0x2, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f00000002c0)={&(0x7f0000000280)={&(0x7f0000000080)=@in6, 0xc, &(0x7f0000000200)=[{&(0x7f0000000140)=""/184, 0xb8}], 0x1, &(0x7f0000000240)=""/33, 0x21}, 0x8}, 0x10, 0x3, &(0x7f0000000300)={0x9, 0x400})
r5 = dup2(r4, 0xffffffffffffffff)
connect$unix(r5, &(0x7f0000000000)=@file={0xd1653077bafa0115, './file0\x00'}, 0xa)
ioctl$WSDISPLAYIO_LSFONT(r5, 0xc058574e, 0x0)
syz_emit_ethernet(0x0, 0x0)
r6 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x100, r6)


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040))
writev(0xffffffffffffffff, &(0x7f00000001c0)=[{0x0}, {&(0x7f0000000040)}], 0x2)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r0, 0x80206982, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000240)=[{0x3}, {0x64}, {0x6}]})
syz_emit_ethernet(0x1019, &(0x7f0000000400)=ANY=[])


sendmsg(0xffffffffffffffff, 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x4, 0x1100, 0xffffffffffffffff)
getrusage(0x0, &(0x7f00000002c0))


sysctl$net_inet6_icmp6(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
semget$private(0x0, 0x1, 0x208)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
openat$wskbd(0xffffffffffffff9c, &(0x7f0000000a00), 0x80, 0x0)


socket(0x0, 0x3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x0, 0x4}]})
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000180)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000000c0), &(0x7f0000000200)=0xc)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x37}, 0x4, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x19a, 0x0, 0x2e)
socket$inet(0x2, 0x2, 0x0)
mknod(0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
setrlimit(0x0, 0x0)
syz_open_pts()
semctl$SETALL(0x0, 0x0, 0x9, &(0x7f00000004c0))
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000240)={{0x0, 0xffffffffffffffff, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x2}, 0x0, 0x2000000009, 0xe7})
semctl$GETNCNT(0x0, 0x0, 0x3, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000000)=[{0x5, 0x8}, {0x28}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000180)=ANY=[])
syz_open_pts()


sysctl$net_inet_ip(0x0, 0x0, &(0x7f0000000100)="d7a8aac106fa1bee91c724b89283c1477dab85e783af4189a1eaf5f6e8251b1147b330f604ff639b9acd6202c9d8b1aef98ce6eefe", 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
sendto$inet(0xffffffffffffffff, &(0x7f00000000c0)="6c25a03ae7b27b4e7fc0924a22334b9b619f09f993c214bf34de94ee6f878793a443c48892901b940ff2189ae976bd635aa66dd55818d1ca20a7f88c2ad799df41ea701f32e36ab928f0ea3b00ddc5613e3590c04b342a5ec356d4f406e612653d7338e1b59ec0f00de4b65b3f18", 0x6e, 0x0, 0x0, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
socket(0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socket$inet(0x18, 0x0, 0x0)
dup(0xffffffffffffffff)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{}, {0x9}, {0xf7ff, 0x0, 0x0, 0x3}]})
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r0 = syz_open_pts()
close(r0)
getrlimit(0x3, &(0x7f00000000c0))
syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000100)={0x978c, 0x0, 0x1, 0x100, "bb08001000fc014c674f8b000000080000000060"})
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f00000000c0)=[{0x40}, {0x1}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
socket(0x20, 0x4000, 0x2)
open$dir(&(0x7f0000001480)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x1, 0x1f)
ktrace(&(0x7f0000001340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2, 0x40000530, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x8, 0x48)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)='\x00', 0x1}], 0x1)
setrlimit(0x8, 0x0)
syz_open_pts()
getrlimit(0x6, &(0x7f0000000440))
r1 = socket$unix(0x1, 0x1, 0x0)
shutdown(r1, 0x0)
mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x6000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
syz_extract_tcp_res(&(0x7f0000000680), 0x6, 0x196)
rename(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000480)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f00000006c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000580)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
unlink(&(0x7f0000000a80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f00000007c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000a40)='./file0\x00')
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0\x00', &(0x7f0000000e40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000600)='./file0\x00', &(0x7f0000000f40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


utimes(0x0, &(0x7f0000000040)={{0x40000000000000, 0x4000002000000004}})
r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r1 = socket$unix(0x1, 0x2, 0x0)
r2 = semget$private(0x0, 0x4, 0x3c8)
semop(r2, &(0x7f0000001480)=[{0x3, 0x6}, {0x3, 0x2ff}, {0x1, 0x8, 0x1000}, {0x3, 0x1, 0xfb0bf9bc52962a4e}, {0x0, 0xfffd, 0x1000}, {0x1, 0x1, 0x3400}, {0x0, 0x9}, {0x3, 0x800, 0x1000}], 0x8)
semctl$SETALL(r2, 0x0, 0x9, &(0x7f00000002c0)=[0x3, 0xfff])
semctl$SETALL(r2, 0x0, 0x9, &(0x7f0000000140)=[0x6, 0x2080])
r3 = getegid()
r4 = getegid()
getgroups(0x6, &(0x7f00000003c0)=[<r5=>0x0, 0x0, r3, <r6=>r4, 0x0, <r7=>0x0])
r8 = getuid()
setreuid(0xee00, r8)
semctl$IPC_SET(r2, 0x0, 0x1, &(0x7f00000000c0)={{0x10000, 0x0, 0xffffffffffffffff, r8, 0x0, 0x181, 0x200}, 0x2, 0xd47, 0x7})
semctl$IPC_SET(r2, 0x0, 0x1, &(0x7f00000007c0)={{0x8001, 0x0, 0x0, 0x0, r6, 0x0, 0x7}, 0xfffff7fffffffffd, 0x104, 0xfffffffffffffffa})
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000000)={0x0, 0x0, <r9=>0x0}, 0xc)
r10 = getpid()
getpgid(r10)
r11 = getuid()
semctl$IPC_SET(0xffffffffffffffff, 0x0, 0x1, &(0x7f0000000200)={{0x9, r11, r7, 0xffffffffffffffff, 0xffffffffffffffff, 0x90}, 0x9, 0x1, 0x3f})
shmctl$IPC_SET(0x0, 0x1, &(0x7f00000014c0)={{0x9faa, r8, r3, r8, 0x0, 0x100, 0x101}, 0xfffffffc, 0x8f, 0x0, r10, 0x6, 0x2, 0xb1})
r12 = socket$inet(0x2, 0x2, 0x0)
getsockopt$sock_cred(r12, 0xffff, 0x1022, &(0x7f0000000180)={0x0, <r13=>0x0}, &(0x7f00000001c0)=0xc)
semctl$IPC_SET(r2, 0x0, 0x1, &(0x7f0000001240)={{0x8, 0x0, r9, r13, r5, 0x8, 0x9}, 0x3, 0x4d, 0x2})
fchown(r1, 0x0, r9)
ioctl$PCIOCREAD(r0, 0xc0107002, &(0x7f0000000040))


open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r0 = socket(0x2, 0x3, 0x0)
r1 = socket(0x2, 0x2, 0x0)
r2 = dup(r1)
setsockopt$inet_opts(r2, 0x0, 0x22, &(0x7f0000000040)="fd0cc085", 0x4)
r3 = dup2(r2, r0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r0, &(0x7f0000000000), 0x10)
writev(r3, &(0x7f0000000200)=[{0x0}], 0x1)


getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000040), &(0x7f0000000100)=0xc)
writev(0xffffffffffffffff, &(0x7f00000002c0)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe2c63a56077123a276d3ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
symlink(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000100)='.\x00')
openat$zero(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSDIRFILT(r0, 0x8004427d, &(0x7f0000000a00)=0xd57)
syz_emit_ethernet(0x26, &(0x7f00000001c0)=ANY=[])


socket(0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x1c, 0x0)
poll(&(0x7f0000000200)=[{}], 0x1, 0x87e)
r0 = open(&(0x7f0000001440)='./file0\x00', 0x615, 0x0)
poll(&(0x7f0000000000)=[{}], 0x1, 0x8001)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x10, r0, 0x0)
ftruncate(r0, 0x25b3)
execve(0x0, 0x0, 0x0)


r0 = open$dir(&(0x7f00000003c0)='./file0\x00', 0x400004000011830a, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, 0x0, 0x28}, 0x0)
pwritev(r0, &(0x7f0000000340)=[{&(0x7f0000000080)='\x00', 0x1}], 0x1, 0x0)
preadv(r0, &(0x7f0000000000), 0x1000000000000098, 0x0)


open$dir(&(0x7f00000002c0)='./file0\x00', 0x200, 0x0)
r0 = getpid()
ktrace(&(0x7f00000001c0)='./file0\x00', 0x0, 0x0, r0)
getrusage(0xffffffffffffffff, &(0x7f0000000340))


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000180)={<r0=>0xffffffffffffffff})
open(&(0x7f0000000200)='./file0\x00', 0x200, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000100)={<r1=>0x0}, &(0x7f0000000040)=0x2)
ktrace(&(0x7f00000000c0)='./file0\x00', 0x0, 0x1008, r1)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140))
open(&(0x7f0000000340)='./file0\x00', 0x40, 0x1)
open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
mkdir(&(0x7f0000000300)='./file1\x00', 0x0)
r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x80, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000080)={{}, 0x0, 0x8, 0x400})
ioctl$PCIOCREAD(r0, 0xc0187009, &(0x7f00000000c0))
chroot(&(0x7f0000000240)='./file1\x00')
unveil(&(0x7f0000000280)='./file1\x00', &(0x7f0000000080)='c\x00')
r1 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000180), 0x80, 0x0)
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f00000002c0), &(0x7f0000000100)=0xc)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x802, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000240)={0x0, 0x5})
r2 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x2000, 0x2d87)
r3 = socket(0x11, 0x3, 0x0)
setsockopt(r3, 0x11, 0x1, &(0x7f0000000200)="4b000001", 0x4)
sendto$unix(r3, &(0x7f0000000000)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x400, 0x0, 0x0)
getpgid(0x0)
socket(0x11, 0x3, 0x0)
socket(0x2, 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r4 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r4, 0xc0106924, &(0x7f00000001c0))
sysctl$vfs_nfs(&(0x7f0000000000)={0xa, 0x4, 0x2}, 0x3, &(0x7f0000000340), 0x0, 0x0, 0x0)
r5 = kqueue()
kevent(r5, &(0x7f0000000100), 0x101, &(0x7f0000000180), 0x6, 0x0)


socket$inet6(0x1e, 0x0, 0xff)
r0 = open(&(0x7f0000000280)='./file0\x00', 0x10, 0x2)
chmod(&(0x7f0000000080)='./file0\x00', 0x40)
writev(r0, &(0x7f0000000180)=[{&(0x7f00000001c0)='#!', 0x2}], 0x1)
setrlimit(0x0, &(0x7f0000000000)={0xffffffffffffff9c})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x0, 0x0})
connect$unix(0xffffffffffffffff, &(0x7f0000000000), 0x1)
getgroups(0x3, &(0x7f0000000240)=[0x0, 0x0, <r1=>0xffffffffffffffff])
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, r1, 0x20, 0x200}})
r2 = socket(0x18, 0x3, 0x7)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r2, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000080)=[{}, {0x5}, {0x6}]})
syz_emit_ethernet(0x26, &(0x7f0000000280)=ANY=[])
r4 = socket(0x18, 0x1, 0x0)
mknod(&(0x7f0000002380)='./file0\x00', 0x2000, 0x4270)
openat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x0, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
readv(0xffffffffffffffff, 0x0, 0x0)
ktrace(0x0, 0x4, 0xd27d43220c7df9b, 0x0)
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r5, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x4}, {0x7}, {0x8016}]})
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000000440)={'tap', 0x0})
syz_emit_ethernet(0x17a, &(0x7f00000008c0)=ANY=[])
kevent(0xffffffffffffff9c, &(0x7f0000000000)=[{{}, 0x0, 0x0, 0x0, 0x7}], 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x2, &(0x7f0000000000)=[{}, {0x6, 0x0, 0x0, 0xfffffffd}]})
sysctl$kern(&(0x7f0000000000)={0x1, 0x42}, 0x6, 0x0, 0x0, 0x0, 0x0)


getpeername$unix(0xffffffffffffffff, 0x0, 0x0)
listen(0xffffffffffffffff, 0x0)
bind(0xffffffffffffffff, 0x0, 0xa)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$pf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000500)={0x0, 0x0, &(0x7f0000000480)=[{&(0x7f0000000380)='s', 0x1}], 0x100000000000038b}, 0x1)
shmget$private(0x0, 0x3000, 0x5f, &(0x7f0000ffa000/0x3000)=nil)
shmat(0x0, &(0x7f0000001000/0x3000)=nil, 0x0)
r0 = shmget$private(0x0, 0x4000, 0x0, &(0x7f0000001000/0x4000)=nil)
shmctl$IPC_STAT(r0, 0x2, &(0x7f0000001540)=""/4092)
madvise(&(0x7f0000001000/0x2000)=nil, 0x2000, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f0000000500)={0x0}, 0x10, 0x0, 0x0)
r1 = getuid()
sysctl$net_inet_tcp(&(0x7f0000000200)={0x4, 0x2, 0x6, 0x17}, 0x4, &(0x7f00000002c0), 0x0, 0x0, 0x0)
setuid(r1)
mknod$loop(&(0x7f0000000080)='./file0\x00', 0x110, 0x1)
r2 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f00000000c0), 0x200, 0x0)
bind(r2, &(0x7f0000000100)=@un=@file={0x0, './file0\x00'}, 0xa)
r3 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000140), 0xae341575a1a762ad, 0x0)
syz_emit_ethernet(0x115, &(0x7f00000001c0)={@local, @random="3a577d02ccbc", [{[], {0x8100, 0x7, 0x0, 0x1}}], {@ipv4={0x800, {{0x14, 0x4, 0x1, 0x5, 0x103, 0x68, 0x800, 0x8, 0x62, 0x0, @local={0xac, 0x14, 0x0}, @multicast2, {[@ra={0x94, 0x6, 0x168}, @generic={0x44, 0xd, "e12893362abe3a3b001c7e"}, @generic={0x7, 0xb, "f0bd479fabd9f9d5ba"}, @ra={0x94, 0x6, 0xffffffff}, @timestamp={0x44, 0x14, 0x9, 0x3, 0x9, [{[], 0x5}, {[@empty], 0x266}, {[], 0x80000000}]}, @end, @end, @end]}}, @udp={{0x2, 0x2, 0x8}, {"e9df3856684cd7806d3db77333cb45568fb92a7d174add72fc0c3b3f50b9b872d952ec419b1c94206c457ef2fa5569fb6355436d046cc20ffdfcbf907d64583b12cdb1e30ec6ee709eb5470bae1846da863f8b9f2905e51140b2120004051e7ec938688e807f1c391214a11c7fb1a743cd8bded5cc0ce3b3d24347943f12c92320e7fbea420f6eaf087eca2939fca322193db76a972f38f465638fa92b9b903b380c89dd05db16314e6889"}}}}}})
sendto$inet(r3, &(0x7f0000000300), 0x0, 0x9, &(0x7f0000001300)={0x2, 0x1}, 0xc)
shmat(0xffffffffffffffff, &(0x7f0000ffa000/0x3000)=nil, 0x2000)


r0 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
socket$inet(0x2, 0x3, 0x0)
close(0xffffffffffffffff)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000300)={0x3, &(0x7f0000000100)=[{0x25}, {}, {0x106}]})
syz_emit_ethernet(0x3e, 0x0)
ioctl$BIOCVERSION(0xffffffffffffffff, 0x40044271, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x42}, 0x6, 0x0, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
shmctl$IPC_SET(0x0, 0x1, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r2, 0x8020699f, &(0x7f0000000100))


r0 = socket$inet(0x2, 0x1, 0x0)
setsockopt$sock_timeval(r0, 0xffff, 0x1006, &(0x7f0000000080)={0x0, 0x4}, 0x10)
getsockopt$sock_timeval(r0, 0xffff, 0x1006, &(0x7f0000000000), &(0x7f0000000040)=0x10)
sysctl$vm(&(0x7f0000000000)={0x4, 0x2}, 0x7, &(0x7f0000000040)="c06d154be3aee5f8787f8b9cda7554335b763bb5deea5ccecb4d1b57a9f6fa18e47fc7b119db587e58811e666e84a806495b45c36164bd5b135280243ed0a01466056e93082876ba33ee8cf2b0b3907f236f38175101000000d7e39544aea098d19ee63d03cbf92380dbe904538135f09e408bbe17a54a364b04ee64b0ad54e6d4e38114ced38c328aff2e224239ba29eb0796e8c3e8344a2cd9e663bb21035ebf391872f3015c164556e4a5b966122c56edd85fc996f12fa1b92e47aa", 0x0, 0x0, 0xfffffffffffffe8f)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
writev(r0, &(0x7f0000000200)=[{&(0x7f00000014c0)="b78a673adf407b1a615f7b0cefcbaae1deee2db8c0a39e78cb9e7842dade5b0289dd462481d2f7086861942434c3459f91d45c48ca1283285d0f8cff1719972dd4e29f627a68c4faff243c839d6c7feb3bca329b172b83f4bc7e84f45d21754bc413ecbadd57191f8bd1cd61a9854f42c6695af839362ab8a907b4cde80e74afd65de994a34c9465147390a07ad76ccb98de184fdd98c479380c272de4184a1072fde680cebd19fc857c6ea3c37d4b878cba0d15434741e27e866cac8f4862ad786c571698aeb0c93c31ea608096fe9a8667994e54b2b5ef2e48ac65764a69ef91eee660951880d5428563fcfb6dee07f419033d0dceb8d800671a93654a54753d1cbe0a517b7489163ce0ad02703a59b64de8c85cc4d838a19f3a77735d7048a8e54ca3cae4a472ce68d59b73ff05c875be6e8958ecc84844a3ea077b1f828e9db731c560f50d0a97618a04df98e9420d480085c0cdd086decef9e01b00fc5bd7d129018429539cf1f096e8a3784300048967a3294410ffc467809dad39c9bf3e851b2aa4106af9d77f783d5bd1674d2c81b10d276e8ea78fd87ed33055c797c096a2d8394975dc1d1f5a89be7a4a6758954b0df5b8c30b05c95c71d212f644fa0fe005fe162339ece8c1705ca69a50ffe8920f5b9db7691b99429b7196061c4b2fc51dcea3f54264a137fee796a716798827091408842f36511611fd355351dfded485a60849fcde62f2867d245361cca123c2d70ee4d9b7e495b5f67cea778f952bf0c00f7892dc3f7e4875f3ff01db85baa4f4337cda169de63e43c7e5393f1599ebcb089a96bf25c8bf8e6ee1dbc2fde6753048ecb222580087695deca0cc7583e0c53ce832e55adae9acc5e2db49048ae9a522a11f3b693270c6ff7bccde4bade876214d7960588cb461f3d85a939acee63c2738c808647f8f57f3fe3b30cbe42b75eb698ecbcc5b1c40b0410261f232ba04bc3d315aa214b7ab33c50e7b455028640fd84eddd32b05f72155bdae5508193b28cecc40a0b5a97ed05571aee87d355cef03cbdcac3abd72dd629ffa637ea2b5931c2d4f8ccf1c1632a71a136009f5c72d0409aba4f4d98f48bde00becf317cce8ebc8824b0e81cfe0d1cccd23b8bb7087d8200aa244154cf51671df28e480a276ffa6da88a5f493dfe391f0c2e54fbd7409bf607999e1ac32ced9524352a7b983e19afdd9b92d0ae2e41ef8810738f1a5d202ef020603f7a3b6a3eeb53ee0a49d748ad220d14d471c0d8ac196a855cd49946f881105a66fcbc7f18b4dd505d53e69921d4b6007d4e3817512c55f2fdb4a31cf2a92685e2840350c843051a5f94672475cc5ad771d3d0b18d38af3b6e358592e22f18ab730ee34ca97e2e97a6d750e9cb65d71d93ec0e19343c97fac29a621a64cb8de117be61e82f25ff5a5a4eb9792a35b806a12397422359d3cb8ec2b6f3a4da9158e97619a00b05f6dffae8a390ad30816c7ec868cb8f0ebf2f12eef22d7b043bb6b286a30d0b56033135928f1f3ba4d3db6ac521161a0a446b22497b9644812868c8b3af55c1a18cbfa5841a43f10768b96170083aeb727c8f9af0380bffdf06036525e44b0bf1c44de46d57e89e785b8fc7fe21b463919a5fef01c3051ca50684741471ee90f7b3a9c884a24ab0d6e50496d540507062439a00e70d429b8e50bee76b5bf4473f93b9078c8fd53282a1ad2bb15e10281071016e1e17857a137ae593cff19541d5e7399d984779598556250b6acba121645cb5f9bbbee6ff44211d2cd171b752e11afbbd4616e2a0acb4835047a224e4ed78a6b900d79635fff77c11a543bd614685740752a5dcadc6161c0c15d6f15460088d10e86d916deff0d0ee941443b0df8052e1afcbb627866ed3a3b7edbdeb933968f035cf4cea0f50baf930ef10cc51f47fb4641c508f0182e9dbe335409bc230d93285d4b50e304501bdfd4e18e9bab3f94e19acb020b0b723017232b12d477d7b5661ef6892b2c9a04f29553fb6f1d9a4875efc30bda7045fb2624d90eabf5cbf71191098425a650fd7b3c2e584b59cbf224ef0ad202711315d15ad4b8c57b312c354acbec562e2d127672b8cfb7bfe7b5b4566b4b777385f6754a89daebc5b441e26df400a69efcd11c7e9d4660eb4ba19e054d0bbb554ae5b64e8d2d3a8d418b06063198bd732a71763986a67f9f7c84b20255d6290c7694fe266c0f60081f3b99ce597fbb671991aef52807f72f7af6461d228f734fd84ccfcad587048da52fd43ca3071b567769205900ce3dafd83a7a9bef972a205f1ee9083027a901d83326b57b12b206a6c6fe593404692922bc1d61681e58facb3ca16c8dd17a8d9d6d8304727c46c6769b9a47f4e072088b31dd5812b1d669e2475703f7f49fb5d0bedf2e530b1d60fcd0351c81f32677f02339b5d019fab03d67fdfeebe67f13527af6a4af07c363a86574150b94d40a5a7802b3d4b2710e2aacf492b8f2e95dbed7d1e5a7369be0bac63d9333995625613d8c0719016ff7e769262286a36a998b5911732e05f1c644c09a75930026761eb953035a59c3d746e686583c07ad90b65d652b5af70ed765b393177b896ed4a1f8c01164f1d41db8cf3d69083e4dc38e15b1358d17d28521a563ea3f0399b44979914366aed3648c7ce342a84fa5c81a6948f4ff4e97a1e17a7225de459001424d5d8480587413c767236e6e7a04f1fb3142f778461e6608b57ee6a79aca7fbbb76a3f66ebe23400b2197525ae1408978f8dd226b2a6e21976554810bc14e7b016ffa43744234cfebb0489263e17340a18818405b41e4bcb1c3cdf8d8691bea83415c2a7ba133694bf899f27df0cabbfc197f93c00df0c121d42488d270f84a533c795f081a6e0dbe1eb16a2df8f211d72ce958b3ea8bff462a6557ad1fc368cb0491b46317704dc151a6e2d597c58a353031eefb087f1eabc583f28f3c695456ab3d176d26a93cddbfd1df2664e22168466b4110b8fd0efd44edbb0682998642c1bff41486d1c6bd8f4f1187a91da3f4f7fc2db2421fed503b669e927ee224dcc6c9ecb285b0e36e0a0de343f4db03cdb1cb6033bbf8da5765d4b7665a97fe8424e6586ec95f6b2d87f546dac286faf8ff40d4782415a9e210c1a43635dec42122a7c6a51d30600027e8670babeed1ad7cc7bb7e94bca12fc14388e8f683af0287ae9a35eafea876d89c9b107132f2c2c38883eee808ad12e067e809ae897dd9d19a9aa1369c1536a213a3d2ddce04284611aa10ee2a3b111fe6c09c8567f4556289faf86eee526f261913bfae54fb18254f82309951f6a502b25030163d6d0a506d8d161bfb29edf4e11311150846d17505b0811b2255a0b6e31b7488bb05fa28b7fb68002773a16f7d47e1b02b5f276a04905320fb1dd054d88f23ef1b0949352d91b9ffc67e45b5bf27197b7a480b3f7c795d9ffc0c1caf81b68a314efa9fdec81a8d859775de3e0658ac32938959978db7d5972b79c16c2bf58076071e840d25bbb1be6ced78164b469e92c78558b0729cb01f2b48072275dcb00bb013a785b4dd32bfd1331366b83b39281636b331ff22fc1c4b89f065330647b87cfe7966b9f732123813ceba42c2c94a27f276a6f405c50f58238a9b231f652148df74229995fc55be05fb59b24ab21fd6198c6db2e54cdd2ba0263d1ee17cdb98d83c744fcb2364029def4f053050fad2397679e43d8b06dd2cfe028dc384195f5b834ac40dcaef18e0645211010466aa9232e3817bd5e40f7dae16b72a67b518e653b92e67a7c37ecc7f7747be16e97940398b24189a390e6243d9b83e6372cfd0f34856e99006ccd9bbfe8ea82b6c52a7310b1fe8c38a9494cabbe90ceb35c8e65b099b924ea76dd8f9108da3aeae2a0c06703ae7fdd19bcd18deb4ddc580b7a44c229d251260f299521515c9d19b1f8dc572f5f8893b8a3898f81e1e85d1269a6b998a6dfc4b777901f5ac1dc8cea365fdba3b321b57cc1a34905e8908a80e59252e7d9912f56f685b63023ebb53f2f65c4bee082ab8f6ddd73ee29b4135bed8912b07e8c04b859288b2c82f52bfce5babc4f83eb33c11157e57370ededa78bc1b11148574172c13cf01b65091521d87a1a4f4e4fbf51a39f05b22bd967c6af004bcee79eac4467e93b73a76c8bca0210ba33b5f00f9ca23df21d787d454567390a7083a348552ec5724ecc9536bc9914608f8d7f4c25c6d80af19f330e6725cdff8f687f8fafe45f43803dabd0694e0405f99eec339c53e3dd19fa192b9a763312411f4d7b44fd182d805de494fd8c2d3c89bfab51e7d1f48d3db900b1085af5c9d8d738e20a168769f50ba41295a7031e9516ff517c548e52deb2c83dfdd37732365fce0883534307fe6fd1bd02d670997bb2db84e4d768ad14fc24a6b679a8c111920c80bec1a448f7a2bc3676c620a905df3f51bc57607cbb90fe7cfbe37b265bc2a50eb5fefdfc11a0048f6dcef530f26e994dc4aa6bee2112b71ea2181ba4b3ae13aa9fb0593a295d4cd6c95f76db7923b5706746cabb298b7425194eca55b7e6ec30387a972d4523872b68ddcfd84e4834101b250fed4f870d2a2c74cdc1a06c3b71db2c0cfa1b02e69db78a5405164dc6bf8689c5cbb526b9fd5fcf8996eb731b2420634b5759fa69b0c09d0ee554cbc2de62683bb3b1669411910dc0b2aa23bf181f8391dc78bf70c6db7c6aa7c8650fe12b56c146fac3bf00a0fa589cd8b901752e0be5962d199cabdebd3a7ae1b53ce7c555e12f54dac7dd3747999a6ccdd9ebad79f8ba0ab115d59f93d1d7209925c52347502529dfffce9f1c80b94fe4a4f7c84c76bb3d981de8b35abe1fd97d7721d0584703e4a22a85740020dd0a839def4349619b120dc7f74d07dcd985355aa2187d244864de70a8c45371275a06276dca8fd1f63e1fb6700bd40a19d9a219ad4290600a9e32112eb6298ee121a58aa6d257152a53589c2e03a78e1c10f02b8c147b31bf26f46aad4db8d622edb5fa0b2670c5397322b28400708abd4cdb83b7c75d5668cfd63fae18f9a87e69f714180c27db897f469c51aaa66d4f3f2a70e5dff88d837babcdd7eba97bfa0f47f4bfc68b9a4183a594294ea500513bc5ed9dc811e9fe914745372112cf7c992f3181e5dd83618c396ec56964842259181fc0bca10736730a621e2f945da9ae597c2fdbabb14531cef29476a33b16cf4f35214c569f556d06d61abb2a8df47fa886fb7413604572b55f2c5ce59a9c8fe60882c7acf6769836b47d71f5c9ed6b91b61864bcc51bea2014e76fe5fc77079957e3c52b0b8d873d9cb25387fa65db7eb0cfab3f8c71aba2c17efdac5a804fbaf24e513e45373c0b773f471e4b41cb239acb3d6db55b1d72cb330cc4935046a3256151f02cefc4e748ccd2cac541a3380bbc325e8a9b8c5702a88ce8d2f6c79d082f3d1b152a118d71c9c678680ebc7a9b4b11ebf2a8856249856240af9248d6067b498c5750683da2f4f8d83bebc556e90d01136942f9faf805d42ff724475c0d93e9209034c7214a00d229172e4619303f444e7e7ff5e4d03e9a9a3c250fbe3ba8869cf1ab09f1cf938fce4013cfd0c5642c31edcc6e0ab1b4d8f6a56eaabc8f4b505643b4203a939774f57f066a69d1b5fbc0660027ae0b531142cdea879057da60b4e2effbe9eeb404ef9e4c5bac911f2f3be64926a5254f0c12a7d4e3539f8027f3427114d528367f1d896504edaa3597b2da58450302c54624f8d07725c6b34861b519398e1b90867eebee566d11f0f123e76b0e7a5853", 0x1000}, {&(0x7f00000002c0)="9ee4bce64d4c926928ce9d85b9d21ac9f39b5143da8653466883adbc7470559578fee707afc643ab189def0f963d38629c4742e12dec0ec5cb721bc1a264839587c7490db16a577c391939a911fe7cae611b5b7419bbc5aa107a6473f5a63f795659b6fe0f37d1d1fa2bc3bbbce715944b6c037e013421de75519e1a1e388f207b", 0x81}], 0x2)
r1 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x3, 0x10, r1, 0x0)
sysctl$ddb(&(0x7f0000000000)={0x9, 0x5}, 0x2, 0x0, 0x0, &(0x7f0000001080), 0x4)


syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x3, 0x0)
connect$unix(r0, &(0x7f0000000000), 0x10)
sendmsg(r0, &(0x7f0000001ec0)={0x0, 0x0, 0x0, 0xfffffffffffffec0, 0x0}, 0x0)
sendmsg$unix(r0, &(0x7f0000001800)={0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = dup(r0)
ioctl$BIOCSRTIMEOUT(r0, 0x8010426d, &(0x7f0000000000)={0x0, 0x7})
ioctl$BIOCSBLEN(r1, 0xc0044266, &(0x7f0000000100))
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
readv(r1, &(0x7f0000000080)=[{&(0x7f0000000180)=""/15, 0xf}, {&(0x7f0000000040)=""/17, 0x11}], 0x2)


setrlimit(0x0, &(0x7f0000000040))
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0xc0206921, &(0x7f00000001c0))
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0xc0206922, &(0x7f00000001c0))


r0 = syz_open_pts()
ioctl$TIOCSTSTAMP(r0, 0x8008745a, &(0x7f00000006c0)={0xfef8})


r0 = socket(0x2, 0x1, 0x0)
getsockname(r0, 0x0, &(0x7f0000000180))


openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = kqueue()
kevent(r2, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
setreuid(0xee00, 0x0)
r3 = getuid()
setreuid(0xee00, r3)
r4 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r4, 0x8020690c, &(0x7f00000001c0))
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
ioctl$WSMUXIO_ADD_DEVICE(0xffffffffffffffff, 0x80085761, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f0000000000), 0x1)
r5 = socket(0x2, 0x2, 0x0)
recvmsg(0xffffffffffffffff, &(0x7f00000002c0)={0x0, 0x0, &(0x7f0000003b00)=[{0x0}], 0x1, 0x0}, 0x0)
r6 = socket(0x2, 0x400000000002, 0x0)
setsockopt(r6, 0x0, 0x21, &(0x7f0000000180)="b1f5d915", 0x4)
r7 = dup2(r6, r5)
setsockopt$sock_int(r7, 0xffff, 0x800, &(0x7f0000000040), 0x4)
bind(r5, &(0x7f0000000000), 0x10)
r8 = socket(0x2, 0x8002, 0x0)
write(r8, 0x0, 0x0)
recvmmsg(r7, &(0x7f0000000080)={0x0}, 0x10, 0x2, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000000)=[{0x50}, {0x34, 0x0, 0x0, 0x3}, {0x9106}]})
syz_emit_ethernet(0x138, &(0x7f0000000080)=ANY=[])


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000140)="67b5b992045c1a7733de71184dc12714990881d0d282bbbb82f88aee3375246d60d056448aeda248819c876f2c6e59c445667afca993a0516665954db86908d70836eed6da0b08d886dfd3ab4c442de33c74d0ff7946a83c180aed511af0d3eff58a00acff7ecc72afce9830fbd4edc05a5b077b39f6b4b7e961ce3c370f2f88a7bfe9e2762ddb30c131b1d20aa39f57ee", 0x91}], 0x1)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = dup2(r0, r0)
ioctl$FIONREAD(r1, 0x8020699d, &(0x7f00000001c0))
writev(0xffffffffffffffff, &(0x7f0000000440)=[{&(0x7f0000000180)="4dfb6b79951845e2cd9668618b36d93df01b8b7d45d0bc640ada53de1096c280bc3fe8a11c5aeea07cc0aca57612f97d4b101b5199f73cd5a5bb955d8f2ab8d018223f7b466cfec2b1a9fb56b65db7afa8570d748d5d8c08785882a940bd45d0984200a1bcd0fac462e146746296242e7342abce5beee86b92b0be65d3aef495a0ec7e2df79837fde3b44ac1773ffd11cf25", 0x92}], 0x1)
syz_emit_ethernet(0x12, &(0x7f0000000200)=ANY=[@ANYBLOB="aaaaaaaaaaaaffff0500ffff8847"])


open(&(0x7f0000000180)='./file0\x00', 0x80000000000206, 0x0)
ktrace(&(0x7f0000000280)='./file0\x00', 0x3, 0x40000530, 0x0)


open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
getpid()
recvmmsg(0xffffffffffffffff, &(0x7f0000000080)={0x0}, 0x10, 0x1800, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x3f8d}, 0x10, 0x0, 0x0)
sendmmsg(0xffffffffffffffff, &(0x7f0000000080)={0x0}, 0x10, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x1, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000100)=[{0x1c}, {}, {0x60}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])
ioctl$FIONREAD(r0, 0x808c694e, &(0x7f00000001c0))
sysctl$vm(&(0x7f00000000c0)={0x6}, 0x2, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x3, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000080)='\x00\x00\x00', 0x3)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000140))
clock_settime(0x100000000000000, &(0x7f0000000040))
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000000)={0x1000, 0x8000000000000000}, 0x10)
recvfrom$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$VT_SETMODE(0xffffffffffffffff, 0x80087602, 0x0)
socket(0x20, 0x2, 0x2)
kqueue()
connect$unix(0xffffffffffffffff, &(0x7f0000000280)=@abs={0x1, 0x0, 0x3}, 0x8)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
sendmmsg(r2, &(0x7f0000000000)={0x0}, 0xfffffe32, 0x0)
recvmsg(r1, &(0x7f0000000100)={0x0, 0x0, &(0x7f0000000080)=[{&(0x7f0000000180)=""/250, 0xfa}], 0x1, 0x0}, 0x840)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000003c0)={0x2, &(0x7f0000000140)=[{0x24}, {}]})
syz_emit_ethernet(0xe, &(0x7f0000000100)=ANY=[])
dup2(r0, r0)
select(0x40, &(0x7f0000000100)={0x10a, 0x0, 0x0, 0x0, 0x0, 0xfffffffffffffffd, 0x10000000000000, 0xab2}, 0x0, 0x0, 0x0)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$VMM_IOC_WRITEREGS(r1, 0x82485608, &(0x7f0000000180)={0x6, 0x0, 0x9, {[0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9], [], [0x0, 0x8, 0x4], [], [{}, {}, {0x0, 0x0, 0x7f}, {}, {}, {}, {0x0, 0x0, 0x7}], {}, {0x0, 0xfffffeff}}})
sysctl$net_inet6_ip6(&(0x7f0000000000)={0x4, 0x1e}, 0x4, &(0x7f0000000140), 0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, &(0x7f00000001c0))
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000500)={0x3, &(0x7f00000000c0)=[{0x4, 0x0, 0x20}, {0x54}, {0x8106}]})
syz_emit_ethernet(0x62, &(0x7f00000008c0)=ANY=[])


msgsnd(0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="00000000000000008d136a159619f3b2cc907f318c2ccfacbef4800b150f4f71e3acddb0ebe041f23bb6d441da4607c3beaac250b0cf9d1be0d5dc884f29306df18b414384cf9365c4114ec1018421c73f4172c70bf2e3c733d6ef7b9b99e8c58920f774f264e6ebdd9207a863d32a696a92792ee9a66e51f0a8907b7f25984419ec8985dba5919bec757d9f206820f74fc7b54614fb9cb5b9cde2a55fd568fdd22648bf3ba3b5d1afbf9724fcbccc6a3ff2a23b8dfb840c22d5cf52187291f89d183c7802"], 0xe1, 0x0)
r0 = socket(0x18, 0x2, 0x0)
close(r0)
openat$diskmap(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
fcntl$lock(r0, 0x7, &(0x7f00000001c0)={0x0, 0x0, 0x7ffffffffffffffd})


socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000000c0)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
recvmsg(r2, &(0x7f0000000100)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000180)=""/225, 0x11e}, 0x0)
sendmsg(r1, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r3=>0xffffffffffffffff, <r4=>0xffffffffffffffff})
recvmsg(r4, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=""/236, 0xec}, 0x0)
sendmsg(r3, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000008c0)={<r5=>0xffffffffffffffff, <r6=>0xffffffffffffffff})
recvmsg(r6, &(0x7f0000000340)={0x0, 0x0, 0x0, 0x0, &(0x7f00000024c0)=""/236, 0xec}, 0x0)
sendmsg(r5, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)
r7 = socket(0x2, 0x1, 0x0)
r8 = fcntl$dupfd(r7, 0x2, 0xffffffffffffffff)
close(r8)
fcntl$dupfd(r0, 0x0, r0)


socket(0x1, 0x2, 0x0)
setrlimit(0x8, 0x0)
r0 = syz_open_pts()
close(r0)
ioctl$TIOCSETAW(r0, 0x802c7415, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000140)=[{0x0}], 0x1)
r1 = socket(0x18, 0x1, 0x0)
setuid(0xee01)
setreuid(0xffffffffffffffff, 0xee00)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_icmp(0x0, 0x0, 0x0, &(0x7f0000000240), &(0x7f0000000280), 0x0)
ktrace(&(0x7f0000000300)='./file0\x00', 0x0, 0x530, 0x0)
pipe(&(0x7f0000000080)={<r2=>0xffffffffffffffff})
r3 = open(0x0, 0x0, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000240)=[{0x0}], 0x1)
dup2(r3, r2)
execve(0x0, 0x0, 0x0)
ioctl$FIONBIO(r1, 0x8004667e, &(0x7f0000000080)=0x1)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(0xffffffffffffffff, 0x0, 0x0)


r0 = socket(0x2, 0x1, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
socket$inet(0x2, 0x2, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r3=>0xffffffffffffffff, <r4=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
recvmsg(r4, &(0x7f0000000100)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000180)=""/225, 0x11e}, 0x800)
sendmsg(r3, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x4, 0x0, "0100dd2d018000000000005e00"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x3d}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000040), 0x3, 0x0, 0x0, &(0x7f0000000080)="4f1d4c6344b80ed788b6a4515248df3aa745bb992c574ab4cdf5587145812eab4a988f7fafd7a01d99776d988908cd186b51f34f8c15ffa0c685ad4116c783959eff4278384b4000384dbb1c2aaeff10b4135529a1da6fda67c67469d954be811b25ec5521559154c586eefff122009f659cd3e27e98a3241495005f102d9101d158284c0ee3250aa7c11042330de22a299ab00894fdc9bac6042d", 0x4)


openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
open(0x0, 0x0, 0x51)
socket(0x18, 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
r0 = open(0x0, 0x80000000000206, 0x0)
writev(r0, &(0x7f0000000280)=[{0x0}], 0x1)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000540)={<r1=>0xffffffffffffffff})
ioctl$VMM_IOC_RUN(0xffffffffffffffff, 0xc0205602, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x2}, 0x4, 0x0, 0x0, &(0x7f0000000280), 0x4)
getsockopt$sock_cred(r1, 0xffff, 0x1022, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
sysctl$net_inet_carp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x3a, &(0x7f0000000100)={@local, @remote, [], {@ipv4={0x800, {{0x9, 0x4, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @multicast2, {[@timestamp={0x44, 0x10, 0x7, 0x3, 0x0, [{}, {}, {}]}]}}, @udp={{0x1, 0x3, 0x8}}}}}})


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r0, 0xc018696c, &(0x7f00000001c0))
r1 = socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(r1, 0x8020699f, &(0x7f00000001c0))
sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f00000001c0)="55f8f5782087a072a82ec35f78d14780f518", 0x12)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc1206949, &(0x7f00000001c0))


socket(0x0, 0x4, 0x0)
r0 = dup2(0xffffffffffffffff, 0xffffffffffffffff)
ioctl$TIOCSTSTAMP(0xffffffffffffffff, 0x8008745a, &(0x7f0000000000)={0xffffffff})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000680)={'tap', 0x0})
ioctl$WSMOUSEIO_SCALIBCOORDS(r0, 0x81205724, &(0x7f0000000240)={0x1f, 0x7, 0x3, 0x8, 0x4, 0x0, 0xfffffffc, 0x10, [{0x8, 0x5, 0x0, 0x4}, {0x9, 0xfffff800, 0x0, 0xffffff80}, {0x2, 0x0, 0x2, 0x20}, {0x597, 0x101, 0x1, 0xfffffff9}, {0xd48, 0x8, 0x7}, {0x6, 0x2, 0x8, 0x8}, {0x3, 0x0, 0x0, 0x2e7e}, {0x0, 0x3, 0x100ce, 0x8000}, {0x5, 0x80, 0x80000000, 0x95}, {0xffffff42, 0x6, 0x5, 0x80}, {0x0, 0x9, 0xfffffffb, 0x6fa1}, {0x5, 0x0, 0x0, 0x10000}, {0x4, 0x676d, 0x6}, {0x4, 0x8000, 0x7, 0xba94}, {0x8, 0x7, 0x6, 0x9d}, {0x60000000, 0x5, 0x4, 0x200}]})
setgroups(0x0, 0xffffffffffffffff)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff}, 0xe0ffffffffffffff})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x0, 0x0})
getpid()
writev(0xffffffffffffffff, &(0x7f00000001c0)=[{0x0}, {0x0}], 0x2)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x11, 0x3, 0x0)
sendto$unix(r1, &(0x7f0000000000)="b1000513000000000000000004000000000013fecea10500fef96ecf2ac72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf7f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f335c223e7d0c032bfa896443a41c18000000720fd38bfbb770c1f5a872c88106002ec5890400000000000000361b1257aea8c500002002fbfe0c2300008abfba0900000008e371a3f8343712051eeab7196fcbd80407000000c011200000", 0xb1, 0x0, 0x0, 0x0)
r2 = socket(0x2, 0x2, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(0xffffffffffffffff, 0x8040691a, 0x0)
ioctl$FIONREAD(r2, 0x8040691a, &(0x7f00000001c0))


sysctl$net_inet_ah(&(0x7f0000000000)={0x4, 0x1e, 0x2}, 0x6, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0xa}, 0x7, &(0x7f0000000080), 0x0, 0x0, 0x0)


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000440)={0x1, &(0x7f0000000100)=[{0x15, 0x0, 0x0, 0xfffffffd}]})
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504000004000000000003000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac5000010000000000000008abfba221554f4e0f668246c09", 0x9d, 0x0, 0x0, 0x0)
msgctl$IPC_SET(0x0, 0x1, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r1, &(0x7f0000000040)=[{&(0x7f0000000380)="079facfaaed69aea4dc561c3b736feac0a2a76087be8b904ddc6f90b66e0f69b6dfba683b348224cf0ccc2a39b0f79389a2bd9b211424a22ca014b9231e253e257706c75b3f320166475c72455021edf575fab8b5d65b8d261c87c3ccc4e784ea7462f3723edabb8e26d27acb1797e2ef4db27270a", 0xffffff01}], 0x1)
pwrite(0xffffffffffffffff, &(0x7f0000000480)="103924d891c20d1c", 0x8, 0x0)
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)


open(&(0x7f0000000180)='./file0\x00', 0x200, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x53e, r0)
stat(&(0x7f0000000040)='./file0\x00', &(0x7f0000001280))


sendmsg(0xffffffffffffffff, 0x0, 0x0)
open(0x0, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(0xffffffffffffffff, 0x80085761, &(0x7f00000000c0)={0x3})
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, 0x0)
r1 = openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(r1, 0x80085762, 0x0)
mknod(0x0, 0x0, 0x0)
r2 = socket(0x18, 0x2, 0x0)
setsockopt(r2, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
r3 = dup(r2)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt(r3, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r3, 0x1000000000029, 0xd, &(0x7f0000000000)="ffdaf64c000000004f0527000000055e473e0000", 0x14)


select(0x0, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000140)=[{0x40}, {0x2c}, {0x40e}]})
syz_emit_ethernet(0x103e, &(0x7f0000001980)=ANY=[])


syz_open_pts()
r0 = open(&(0x7f0000000200)='.\x00', 0x0, 0x2)
r1 = getpid()
ktrace(&(0x7f0000000040)='./file0\x00', 0x0, 0x106, 0x0)
ktrace(&(0x7f0000000280)='./file0\x00', 0x4, 0x928, r1)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r0, 0x0)
r2 = openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$PCIOCWRITE(r2, 0xc0107003, 0x0)
semop(0x0, &(0x7f0000000100)=[{}, {0x0, 0x2fe}], 0x2)
semctl$GETALL(0x0, 0x0, 0x6, &(0x7f0000000140)=""/169)
socket(0x0, 0x0, 0x0)
rmdir(0x0)
sysctl$vm(&(0x7f0000000140)={0x2, 0x9}, 0x2, 0x0, &(0x7f0000000100), 0x0, 0x0)
getpgrp()
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x1e56)
acct(&(0x7f0000001240)='./file0\x00')
openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x10, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f00000002c0), 0x1, 0x0)
openat$tty(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$TIOCSETVERAUTH(0xffffffffffffffff, 0x8004741c, &(0x7f0000000080)=0x2)
getgroups(0x85ed0e3098300e08, 0x0)
r3 = semget$private(0x0, 0x4000000009, 0x82)
semop(r3, &(0x7f0000000240)=[{0x3, 0x100, 0x1000}, {0x3, 0x4, 0x1800}, {0x3, 0xfff9}], 0x3)
setsockopt(0xffffffffffffffff, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x2}, {0x54}, {0x40e}]})
syz_emit_ethernet(0x7e, &(0x7f0000000400)=ANY=[])


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x0, &(0x7f0000000100)})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0x0, 0x0, 0x0, 0x40}], 0x0, 0x0, 0x0, 0x0)
socket(0x800000018, 0x2, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmsg(r0, &(0x7f0000000280)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000300)=[{0x10}], 0x10}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
r1 = open(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
setreuid(0xee00, 0x0)
r2 = getuid()
setreuid(0x0, 0x0)
r3 = semget$private(0x0, 0x0, 0x490)
r4 = getgid()
r5 = getegid()
semctl$IPC_SET(r3, 0x0, 0x1, &(0x7f0000000140)={{0x8000, r2, r4, 0x0, r5, 0x88, 0x8}, 0x8001, 0x1f, 0x3f})
setreuid(0xee00, r2)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x50}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x10, 0x0, 0x37)
r6 = msgget$private(0x0, 0xfffffffffffffffd)
msgsnd(r6, &(0x7f0000000040)=ANY=[@ANYRESHEX, @ANYRESDEC], 0x0, 0x0)
msgrcv(r6, &(0x7f0000000340)={0x0, ""/204}, 0xd4, 0x0, 0x1000)
writev(r1, &(0x7f0000000080)=[{0x0}], 0x1)
writev(0xffffffffffffffff, &(0x7f00000002c0)=[{&(0x7f00000014c0)=' ', 0x1}], 0x1)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x2a, 0x0)
openat$diskmap(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
r7 = socket$inet6(0x18, 0x3, 0x0)
getsockopt(r7, 0x29, 0x38, 0x0, 0x0)
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x205b1a)
open(&(0x7f0000000080)='./bus\x00', 0x2, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x1, &(0x7f0000000700)=[{}]})
sysctl$kern(0x0, 0x0, 0x0, &(0x7f0000000180), &(0x7f00000001c0)=')', 0x1)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000200)={0x2, &(0x7f0000000380)=[{0x20}, {0x15}]})
r2 = socket(0x11, 0x3, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1002, &(0x7f00000000c0)=0x80, 0x4)
sendto$unix(r2, &(0x7f0000000000), 0x0, 0x0, 0x0, 0x0)
setrlimit(0x7, &(0x7f0000000000)={0x0, 0xfffffffffffffffc})
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x0, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x462, 0x0)
writev(r4, &(0x7f0000002500)=[{&(0x7f0000000080)="ebebfd510bbcd3a9b489e989c1", 0xd}], 0x1)
munmap(&(0x7f0000ffb000/0x2000)=nil, 0x2000)
mlock(&(0x7f0000ffd000/0x2000)=nil, 0x2000)
minherit(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x3)
ioctl$BIOCGRSIG(r4, 0x40044273, &(0x7f0000000200))
ioctl$BIOCGDIRFILT(r3, 0x4004427c, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
r5 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r5, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
sendmsg(0xffffffffffffffff, 0x0, 0x0)
sendmmsg(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, 0x0)
getsockopt(r5, 0x0, 0x9, 0x0, 0x0)


r0 = socket$inet(0x2, 0x8003, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x800, &(0x7f0000000000)=0x10000, 0x4)
syz_emit_ethernet(0x2a, &(0x7f00000002c0)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, @multicast2}, @icmp=@echo}}}})


openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
ioctl$WSMUXIO_ADD_DEVICE(0xffffffffffffffff, 0x80085761, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x1}, 0xc)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x67, &(0x7f0000000000), 0xc)
socket(0x20, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, 0x0)
r1 = socket(0x0, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, 0x0)
ioctl$WSDISPLAYIO_GBURNER(0xffffffffffffffff, 0x400c5752, &(0x7f00000002c0))
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x0, 0x0})


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x100000001})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x7fffffff, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg$unix(r1, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="28000000ffff000001"], 0x28}, 0x0)
recvmmsg(r0, &(0x7f0000000000)={&(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000080)}}, 0x10, 0x0, 0x0)


mmap(&(0x7f0000400000/0xc00000)=nil, 0xc00000, 0x2, 0x1011, 0xffffffffffffffff, 0x0)
mknod(&(0x7f00000000c0)='./file0\x00', 0x2000, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000540))
madvise(&(0x7f000074c000/0x3000)=nil, 0x3000, 0x0)
mmap(&(0x7f0000400000/0xc00000)=nil, 0xc00000, 0x0, 0x1011, 0xffffffffffffffff, 0x0)


msgget(0x0, 0x230)


r0 = open(&(0x7f0000000480)='./file0\x00', 0x200, 0x0)
sysctl$kern(&(0x7f00000007c0)={0x1, 0x9}, 0x2, &(0x7f0000000800), 0x0, 0x0, 0x0)
r1 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r1)
writev(r0, &(0x7f0000001800)=[{&(0x7f0000000140)="d2b1e9633181279df8a50e2499aed473bfd846354b83f3f3afff2a7485301e8b3a355fa3815589d2e484f0d7ea935eedec2d447b9fc39bcd6aa9de968b19be1e737501a4d79a43ac14dde4eb55a5101ea57ac404fb93c9bf035141d9f9a17f4ef0d7370cc5d942d3cb1198e34d7f1bab4e32a9712f7518f388a25e60eea2058b57d5c339f0f1be6e963748ab26e56b04d11f814d7af3c5aa3d887cd8017a848c36590e19239e603efab132935400e9f08d3cc90155a06b20f57ea696f42651fdec533e29378b1e54f0bc300fd6479ddf", 0xd0}, {&(0x7f0000000240)="dd59ad87eaed56c981b3a3c57c326ff4e61d949e0c4c01a606e77bce23e0118ec75c3f06f2c8271e63a3e8b30567cff55c05ac15207cfede133b50a842603b16eeb2f1a351c913e767730281f29ab63736c0ac315513727b280b41ea83bcd86c811f2d280328c6a1db531fc17c8993eb170e4bc0144863dd63f416723c33128f8d0db75396bc68d0f1678a9409fea635bce52d188054570879cb6df96ca08414c16692f705d2cafae7424e1dfc790e6060fde846957705711b25f11483ef4cfb5b43a8431c3cb6b33a5dec2a3be375a1431f6521d42944ed5cfd99d82d", 0xdd}, {&(0x7f0000000380)="8b5c42c7d7318c20f54beaaae1a57a77324ee9c0336dd9465906b5d941a913d2a81e92c1f4ecd7008f5ed00990c2a6f7a3033e22212fa73b41039f0ef49444f026c1a5f5258c125285fa838972fc8d58ab3cb841c4fe243a170725fb3c448c9cd8915fad8e68251e4c15d46b3923fbb6336afe7787c604dacd84f770d11fb1aab14519054a821e3e1208bd478553a67c1b030ba693568286462b3864fe82fbad3afa00115bbf34ed187634e645ee1d76c10e35544b3bca8d6a9f3bfd54e244db8040d820c87f7ecc8ea9e9f934a100279516f065db89c2a2e47aa03b092abe8a002498b5", 0xe4}, {&(0x7f00000004c0)="9cfd34e31087f9f0f1d2f6865457f921a108df6e0bd0b6a77a9cd7e92525266a1de6fd7de7c8049b3baa649e1692e9c96f6e756695f9134feba7a867dc48d5cc3935fc0b4031166d4dc399dd00582c35832775c9d4da", 0x56}, {&(0x7f0000000540)="7296c8e860aaac803cbc882b454ea35d14c521e3f0d6bfa6a785e47317afc68fae4ba8d83642a5ba2f3d5923e88f82b5d363afb39e4a9834f493b3b405d501d90fe1f2e865de8f868e714a73a3401497c746e426514b2924258dd7e12797e26dd85a09fe6fba75e6292fdf3ecbce7758b3e60f208e599e4828681e764780040c29b3b2861d5f2332016c212d980a1a7b9b2c712e333afba7d7cf936db50c0d8247c33ff38da12b9ef5043c1dc59d15d5994be5acfe131dba9113a720449a887eff89491c10c0ca12089374770a76eb645fc9f069797c2ee3e954f7e9884c195da13c5ca4e85ce4b1b1bc92630f0874afe98feefd", 0xf4}, {&(0x7f0000000800)="e75f27108f307e12c8906bdcf93d0ee06fe013a005b850518713d7b79d11a497087ed694b59074332eba568cf9147cf6b5f19130c5199127f9dd970bdb460f89fec1e4179acdfc622bd36625a4a0764a2893c49d4477abcda4dd4d0314180d1ad1892d7f3f07e7313b586c3b0ab3639eae1fa9174addb5ef8daa919ccdfc94f58ced4f2b1b82576a50ea12949d89b478ea5efdd3589a42363876272b3a4c2239f0b6f8ddf24d49b4cbc1b531bbb152790eb0941719c15c892986526ad34a102872ca2e683b9fc04b4fcf995d406c32013530c5faec0e62104a8c34de9558db4d35b24490c8594e526ca438eab8e9f849bd8dd24e2b8a8974ae7392a1382eabffc92c52f89c8dce9274d482459f3cabea441b42389889206fe4be17bf34f35eb0e94f4f1f70bc5fcaed5efdfcdcc37cc27e06fbbe5cba2cafdd93596c1fe2deeb642a57272ad8687dcea1457454b01249befacd2548b13a4925c4b1677dd0d5f9729d5c9978f4ba9f3f3aa53663bfc58d568d1259c48daa4545007a502ce0730a4534031c2ef9a4449dd95269d210a14f24ca467213ab050c3eb39ac632e822e96d7e11b1d92d9b1c4619690f9018dca8c761016b803361e07c11a6dc8207da779f9b87763fb0a3ca62848f51d98ec0f651a1a96c33091719fe36dfbaeb9a0b7b2a9e4f3c416d126e39fd3fbbfcf47c0d4ea1d47228d273caed9816661ef3e5a0218c21400338980cbb72b3852fd95a4af4cd686fbd3aa2a32bbfb92f43b35a657b57c2627d32129f6e6e0834d0f5be71b97cc3c729e6a7c42ab74e667659f260abd3fde446a9d3895119effe557cc6909d21bdba37324c18675e9042c9a2f7f9a8e50b5d55c6c403da91a1aaa48cb045da853d6251c84542b317f243480857cd0b2c22c8e938c1d8ff9c8d7365a9d728fbd765c936c0209d2235e52eafe299a01009e1e13f0f0d30e0a5d93e66a8324a7c321c562884fa3ff9941c7e289e32ad32f5e1407367649c39e94db08fe6a5889648b3d153f4a03174f3205d4d6d834ce4a1ccc4ef8b74670311ca7d44a012f5d92772a7d684a44ae5612879081e2e6dc4467ec7bf72873f8ba3c9d218706cf350b6a43a0160c2c2920edc86d03f02cd142335a30f7e85f173c51cf99c76b490954152af70df435c2ca34d9e8dac43f324fd0c8c217838136962a1064f6fa3afed7e21296fd01d82fde3bb272c007b8fbcef195a4705c4c0edeaa32f7f748d3b14eb1da4e67636a9c1f250d69e033c999429a5ad1eb19333a0b014cf06c5cad5d406ea7e8215e89e6b5809ad5644943c5353fe8fa19f3eef3f67aa39dfc12b579bde2e2a937a5933f5910c560f3ba1a4e7d9cb944ae324397a9fca803ded2b893b454ea5ce1dacaa9db339799002f0eabd9a65e1cbf8393d0ac75df36defbca8162a13e06ff498b21b9dd7fd6566897f74ead94bd572a0eb644e71b991e4c7f6cfc6b2fefa21520351317f4cd9f2e70b8ed82ce3eba52a2546215fb5159035536fbd8f69ad2697842853800894a7f1de2ee57d941d834e7d596b5e499309ba9195f870355e954326ac7fc9bff9350fc43c0ebe256208dcd8f4b069ea01874a705d245fd694eaa9f080a619e7e2d9d90993d74d9ad6f815a518ca2621cb5c74f61658f0cf94c576bdeaee178a29f82576a9d1eb3127569f39b85b565e291dd4325d100d35c1eeb7a64ecfaa73dcd6bbd43da73b84f0577d33c4963cb1e2c0817c2a253b1d5c8f25d7516de2138994ba36b65d0d37de8ff6ab462b279e22682bebc222639ba2ec965b73f0f60dd50690cdb1f70c53f07d247857f4dc3ea698b106b1904002cfcfb29a7f81cc9957c491faebb00625665fbd8cec9fe20f337e7b7d5441aa80d78bd79f19677fad2398dd19f53c827ef4218d9a95f3d1c4a8a69cca05a08d5319c1ce33de82e46668c1767fd813c02fa7e5d4cec97651e12f66285f7be048c08525ca6ee6d037392a03545e9392c86e551adc1db69da0b55d97696f4ae687be7a1a5442486568b3ce0e4f98f422e41247cdd9df208cf466f9cca713f4cafb5a0245d99c1c7382835ea5ad9021776a553b86afa490f2ff29e86912d0bf5b4b22fa27013f26156cdab41f5a15a5d0d35acff0c3c688653ce8d9546a8f3da1db904dc62e62044fd87ee2b7a57e3ec0b1043ae1dcd5c31d29d5ce015e2babe022a0cd49b0190a644aeb7a483d98df7d248be6f4092c394a010a86824dcc3f3956d54312095b402619721223693917b923757811c8e267765aec9ce041f344091cf2738cd4a9386df1362a322611b5dfec62c5b9ac3282503b764b2fb745458b12bb50fae9260049c22bd41771b737a7c33466b04a119045864cca5f57c41c23fb7595ec9e047036a6345c4f759855c77ba442c898aeada7aefbbc89a0e491645743a78bf4855fe94cee9c0891e321b3f05d62de1ecd4d855e830ba9160ab5814dff40e477304ba9d9e103c272a6a70df5221a10cc19094c3738372916706e969f672045adaeb49fef66e1feca136029d203e7ed00e6bd5bae029cb7e9028f4cf673f3f2872aa46d9105ac8ad59bd3e76413f84b7d75b047162dabfbc468be1b9b811b0ccb5a9a1b5e8b9e41b903294d71356439be4f8668c53cdb3d0f2b5b7a54c6620e6d3cd25d832ff22dadf2eb515c0c6f97052c9d14ab97cfdb38d7a2f6e1bc3177532cb34fe9923bdc2aa2f64bb0791a0e86d5c5e258f6a94f94c6f9e1279bbf3d5063780ff2aae5a7794c009ea2ef97238734f841fa4fdbf91a7b39e21b946611fb7630920e16bd330879f85294fe297b59bdfcb1cb7c54c4680cc46a7376822d4d049e84bf88866007a99c7eefa31a1c012dcdec5f37786c32bd8c2fcc703c6f52157e72ff054686c20a9253a8e735f925cd3aa906e9338911bfde5c83d549c0891c5a3fdf0ca749470b79f9a231f9a296171ca397796fbf5a95f61e095e3af98aa38a1d22ca4d05116a3891756a71ded254bfd70437df09d0f7a405ddbffc929bc39f5fe6a7f380bc4eec0d7f8ea73ee43059fc335230505959d20df12a5620b11090e8ff25e00d741755c681c7b03aa48d76b559701589a96adc4c21f38b246ac6fcde556a191389ac7f1d57a0ac881fb7dad2fb8f8a269abe551c90157c6bccbfa1e9782581010bcf5a2544e14e13447dc66c09594674794d040b0de4f912a25a07bedc9f93c67ca0b4879ed926cd3ede4a25d089e8dd2424cd98f3858fb82171647420bc86ee05878508d30e38d41effbc2d6ebc8ee76b536eea974f72297f84b78698a2f2c56c3372cfb9e6b4678dd6a1b8c3eab6bd54fd8cc7f9e31570d3e2c1f5859a3ce26501a3ec40246e061293efc15559f463757f00d8f995b01f8c87f3af3de535a91c31207709c4acfc79591e4d61825edd834b9be28072802e68889eea01e0dc06ec2c403720ea75d3966158a616ab21a5753232f0489cd47c953ea8d440f7b1cf8cd3b74e81852d4a74f12fc11a31a8293fe427d3e3b9af19c4f2155e02eebd3719860fb12900ad829869d34d814800b9d9adc63ce17559a23ff8ccb0fe443670176f99b48428f37fe8673d5fb486ef278c7581dc225e177631b7ed3dcfb631612924c36f888ba816ed19b35ec3fcb5a0693e69a09c3920344b4e92cb432bf0966064a502e9c0cbcce67b358202ec675ad2319ee6453c14016b2c5b60414a4abe67f07b7c6a13ff169ea1ce202cfe076e9ff2316f5c7c93c11b9106efc79ce0b66d08d3a9c02e8ed5edc730fa98706e4769fb8da44c52853618d399fd5a08cca6e9fd443e137a151746842c3564719f379ce24a49955ae3ff76207e7a7163b1320faec4a75bba7ba6d05416ad0b200082c731d9950d7d18c80d135015690eb164782bf2a6628af7934a1eee49b1333f1691ec9301dc7f215e922852d373615575d02e74470492b0fd2fb5ad262014cde0daf4bcbaa8104d5d46e44693c9ce9978d40b92d97dcfe6372e0c89e9cd59dccc207f41548404f775d58f022c8344fdc170c463ad82ea4c64b212ba9b2489a069e4646fb3e7e2d36d27ee3a122295b3e3fa86b83dc06c0a53dfb6512cea2a286fe234896f02facc20880215efddb3ed0cf524fa047e9551b1c0d8be74ac55834b09dcf36af832570e5aa44dc99c8b36db7bdbca478b01b9120dba8c5ce810c620a476c53e2129ebe8f9087ab2cfa05304393fcf8a6d0461f69366e2d4d466c627b21086bd3d0cd9072dc403539241ca1db3e7a9e25aba7991222c61b198c7ec35af140e7319e3b9601ce808f0298e3a2b42d123b3eb5252b7c0eacf687e9407cba8031fbce4d80e453cd88aee1dd2e45ab392423e40d55bc14e75a661c472f8d85dfbdf75922ce8ab29446a8cd78a91f5522f306a5431878fdfa9dc837484fdd76e36014523db8c8c5c7fc2b9e05bfab7d97e19f4dbdb61bbd5644def9812bd3f587c62db9bd7e33b0acdf321e21b8b5294a5a311fbaa10b93a3c61d8eb9354564a5ec5963e9ec99d0053a302a09cece4afafdfdc2bc4ff3e89902750b503e5080c19c110849f02253f681acda733ce2d111ff32f5121408989c829a7b0d60ef2f76aaf2b0701c57d889a56a971b41c342f85b947ebcbe1c6cf5ebe9cc401893319418cf634dff09265bb2abbba656ed532f45221ed2efbffe5481d6d61c8c5d60d8d1bb90ece51c9d83f6541cb2fc616796cab7b765f7edf9a5285960f1e54ab8c8c2750bb599e69d59f8b0f6f76d6700450a142008abf32c9188d1bbf16a122e2e5300dea769019b8317c4fe5caface06e27d05d7d3d9bc4209a5e3cead3bd5ac9538c1042839a8a01cf717bd318a914beb55dfaa810f114894b6c17bbfe7abd1d5f92816f220e6483c69e51ce854c41bad0c47818b027bafbaeec88b4006d1481f62c7befe31262cc4a24ae668e7e08ec556817c8ef2e2db919405f7cfa2b1629a8ff52a1e41c98c9eb7065a9de20317f16e2dc159b28656460f02fff400261123f0b27943da3c6b1d275b27fadd040ee48917f7eef2fd4cf11812cc8085124cf732734bd917f5075ffbed0db4cdfe15dc1888bd70c5e530bb1339a792577927002ae8874f67aca39da618d7d93c0893366f820a35ebc095365023d65bab858512c3bb26baebdc1bd208b6aaf941e4f305991b5f3d2e50048899fae4ec95a2d2259e62dde6191694ccf8c2b5b208ef67eed4799760ea871d467dbc89b60ae88d2b61e80c922d3855b2208e4b0cb53adb02404e5a9d81ff8f25c0de6a1abfc2fa1cf22f230e175ffb7274ce2386f8e04f61133ea220b9078b79b33a5ca4a83f5df1a0f2595fcafdafcfb277208321365706ac8aa03ad87c05ee77a299aef42d62dd88adcc8af6b2d9f948af9fecd9b0d5f1ff1b76798164cc936ddd5f0d02e91ed0f40db6fa13316667bfbf459bae97323f2784948b63a1bd3007acc41ca7c468c508208983ed4d80876485eec3c787fee04715b46916360b623a6a19600c554a1f2ca461fac7507cc0f20b894531dd79d734b1ea21b9d024393f697e6fd04f710fbea8eab107068f6ac9652aab030f0f7da115c25cc5b369196207e1095e947c8f3e8fd335c9bf27a855ed325f270f382e6d6173ccc5f651e3cee0a5ec2f971f0c0f2ac5eab73a300b75a6a864e9c5a47822ca03fdca5968a055437c5f5ba47688231867dbc95a238391716ce736f32ab3d04a746871139166902d36082ff20b502ec37dc02121b86fd3948bed7310da6e250a38cf06a66dc8c2d4f0a6bd21cf38b8be19a8a0ad286fdd544646ee91ae75", 0x1000}, {&(0x7f0000000700)="a9dcefc3fa6cb78ee84d1032c23451a2d654ef4074376149a720beb6d7f2c9793c0943948f8a6479efead9aaee92c1598ea5825432be6265f6651b3ad336249253f8144294d2bf8b0e587dd5ac4b7f8a0117c13020264d1e4b6de52c89977c18b09738c1a3a471f881242a0f396628652a0969510f323ae11d12f1caeb1148c5bef65ff677cc2c49dde5ac21fce9941b5ea8e0c8599978dae7d0239c", 0x9c}], 0x7)
recvmmsg(0xffffffffffffffff, &(0x7f0000000080)={&(0x7f0000000100)={&(0x7f00000006c0), 0x213, 0x0, 0x0, 0x0}}, 0x10, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000340)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
sendmmsg(r2, &(0x7f0000000080)={0x0}, 0x10, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000080)="eaef125c00000000", 0x8)
r1 = socket$inet(0x2, 0x3, 0x0)
r2 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000080)="eaef125c00000000", 0x8)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000000)="ea00000100000000", 0x8)
dup2(r1, r2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000340), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000240)=[{0x60}, {0x28}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000140)=ANY=[])


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x1000000029, 0x1a, &(0x7f0000000000)="5ab777a5", 0x4)


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
madvise(&(0x7f00003e0000/0x1000)=nil, 0x1000, 0x0)
munmap(&(0x7f00003e1000/0x1000)=nil, 0x1000)
madvise(&(0x7f00003e1000/0x2000)=nil, 0x2000, 0x0)


sendmmsg(0xffffffffffffffff, &(0x7f0000000180)={&(0x7f0000000200)={0x0, 0x0, &(0x7f0000000240), 0x0, 0x0}}, 0x10, 0x0)
r0 = socket(0x800000018, 0x4002, 0x0)
recvmmsg(r0, &(0x7f0000000180)={0x0}, 0x10, 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r1, 0xc1206925, &(0x7f0000000100))
mknod(&(0x7f0000000000)='./bus\x00', 0x2000, 0x6380)
r2 = msgget$private(0x0, 0x0)
msgsnd(r2, 0x0, 0x11, 0x800)
msgsnd(r2, &(0x7f00000006c0)=ANY=[@ANYBLOB="0300000000000000bc597b8a7110cfcfb630f8fce91c8815cdb3170494422f94d3ca7b7e6e85277277ed8b80324a3721ef9788207334532be3f0940418dfc357ad34a8ff249bd5640720a0ef96857717d47c739a7105b1f5e3f02c84cacb4f83921ee9801773dfb84f3afbcfacf7b467bf6b551d8e905c883ef3bb3011e829e5ddce4e243de033ed1ad495516771cab6167098bc69fe5984b6280e3fc97b2d624151901511c550e6d5d4ec"], 0xa9, 0x0)
msgrcv(r2, &(0x7f00000007c0), 0x90, 0x3, 0x0)
msgsnd(r2, &(0x7f0000000200)={0x3, "3e93e03e4a1078596fa9ae9b10eeffb1de39b25b9d3d33bbe7b950d7dc29878932edba74eda7797007ecebfef8842b3a5fa5c78d0956166d10810778df94d88c335d138d853ae10be913eb9b61b092062cbe5dcb2e663b81508a201bbdc0bc2bb1894ba3ad75ec649749b456b23180f0dc62e3985119a973761722f2e77cbbbc5257b118ad4737edf9aa91b5a107713c26fab3f34009faa067d2c8bb68b5ab834768013f2332aa4550e8de7592025840aea99d12ca418d3197fc89050d1946c0d4923d14e48c"}, 0xce, 0x800)
msgsnd(r2, &(0x7f0000000100)=ANY=[@ANYBLOB="0000000000000000674a4c49dfc6f7a22f72d83d3ae8f96bfa463ff933a3f3b011d9f18297555096416fac49553e4b04770d128dbb2686e91fa2f5a6d1b55de2c8e1475f21a35cf5f21628006c261945531a74f1e5e4000000808a66a901cfdb13ebb65d00dd"], 0x66, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x6381)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x58}, 0x2, &(0x7f0000000100)="71f91e34", &(0x7f0000000180)=0x4, 0x0, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
write(r3, &(0x7f0000000540)="76e5dead6f01f8607d2100000063", 0xe)
open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffff9c, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x3, 0x0, 0x0, 0x4}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x31}, 0x4, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


setrlimit(0x8, &(0x7f0000000980)={0xb, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000080)={0xf669, 0x0, 0x7d, 0x5577c513, "21110000f1ac7e000000000080000000ff00"})
writev(r0, &(0x7f00000004c0)=[{&(0x7f00000000c0)="bf0909b98732e43ae0ee63c33dd9cb7de67102649ec14a5cde", 0x19}], 0x1)


open(&(0x7f0000000280)='./file0\x00', 0x0, 0x0)
r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0xd6)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)
writev(r0, &(0x7f00000000c0)=[{&(0x7f0000000280)='#!', 0x10}, {&(0x7f0000000000)="8d6bb85551ec8430877ae32fe9bbe42cc8f2147a3eba8e1969f0435119cf4c071c8aee7ef2921be5d7d4796c5566c95989acb3d185587234186e96b8fde9ffac51de05a87b8b893e2abd154dd886eafbe03881d25b7b13b4c32227fc9e5a86a06f59f701322b3a109a13436e486b0a", 0x6f}], 0x2)
execve(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)


mknodat(0xffffffffffffff9c, &(0x7f0000000280)='./file0\x00', 0x1000, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r1 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
ioctl$DIOCMAP(r1, 0xc0106477, &(0x7f0000000080)={&(0x7f00000002c0)='./file0\x00', r0})
close(r1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
open(&(0x7f00000002c0)='./bus\x00', 0x2, 0x0)


r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000100)=0x7)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
semop(0x0, 0x0, 0x0)
shmctl$IPC_STAT(0x0, 0x2, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r2 = shmget$private(0x0, 0x3000, 0x1dd, &(0x7f0000002000/0x3000)=nil)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000040)=[{0x28}, {}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])
shmat(r2, &(0x7f0000001000/0x3000)=nil, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r3=>0xffffffffffffffff})
recvmmsg(r3, &(0x7f0000000480)={0x0}, 0x10, 0x0, &(0x7f0000000500)={0x2007fffc, 0xa})
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
kqueue()
r4 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r4, 0x0, 0x6, &(0x7f0000000000)='\x00', 0x1)
mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x40005d4a)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x3, 0x0, 0x0, 0x0, 0x0, 0x60, 0x1}})
r5 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$VMM_IOC_INFO(r5, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
sysctl$net_inet_ah(&(0x7f00000003c0), 0x6, 0x0, 0x0, 0x0, 0xfffffffffffffeb6)


sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x17}, 0x4, 0x0, 0x0, 0x0, 0x15)
sysctl$vm_swapencrypt(&(0x7f0000000040)={0x6, 0x1b, 0x2}, 0x5, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x3f}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0xfffffffffffffda3)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000140)=[{0x1}, {0x60}, {0x6, 0x0, 0x0, 0x4200003}]})
write(r0, &(0x7f0000000000)="7696e5f3d1f18c37cea8615ac7cf", 0xe)


open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f00000001c0)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe1463a52077dc0d00003ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')
open(&(0x7f0000000000)='./file0\x00', 0x2f2, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000004c0)=[{0x2}, {0x44}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000200)=ANY=[])


acct(0x0)
openat$vnd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
dup(0xffffffffffffffff)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{0x40}, {0xc0}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


sysctl$kern(&(0x7f0000000040), 0x2, 0x0, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000040)="03000000", 0x4)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
socket(0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
close(0xffffffffffffffff)
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047466, &(0x7f0000000200))


sysctl$net_inet_icmp(&(0x7f0000000100)={0x4, 0x2, 0x1, 0x7}, 0x4, 0x0, 0x0, 0x0, 0x0)


mprotect(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000000c0)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000300)=0xc)
r2 = socket(0x11, 0x3, 0x0)
sendto$unix(r2, &(0x7f0000000000)="b1000503000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)
r3 = socket$unix(0x1, 0x2, 0x0)
getsockopt$sock_int(r3, 0xffff, 0x200, &(0x7f0000000040), &(0x7f0000000000)=0x4)
mknodat(0xffffffffffffff9c, &(0x7f0000000400)='./file0\x00', 0x2000, 0x0)
r4 = open(&(0x7f0000000180)='./file0\x00', 0x10, 0x12)
fcntl$setstatus(r4, 0x4, 0x4)
mknod(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
ioctl$TIOCSETA(0xffffffffffffff9c, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "0100dd2dfa7f0000000400"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x4f}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000040), 0x3, 0x0, 0x0, &(0x7f0000000080)="4f1d4c6344b80ed788b6a4515248df3aa745bb992c574ab4cdf5587145812eab4a988f7fafd7a01d99776d988908cd186b51f34f8c15ffa0c685ad4116c783959eff4278384b4000384dbb1c2aaeff10b4135529a1da6fda67c67469d954be811b25ec5521559154c586eefff122009f659cd3e27e98a3241495005f102d9101d158284c0ee3250aa7c11042330de22a299ab00894fdc9bac6042d", 0x4)
pipe(&(0x7f0000000100)={<r5=>0xffffffffffffffff})
fcntl$setstatus(r5, 0x4, 0xc0)
r6 = getppid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r1, 0x0, 0x0, 0x64}, 0x0, 0x0, r6})
pipe(&(0x7f0000000140)={<r7=>0xffffffffffffffff})
setreuid(0xee00, 0x0)
r8 = getuid()
setreuid(0x0, r8)
ioctl$WSKBDIO_GETMAP(r7, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x8000000000000000, 0x8000000000000001})
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000003c0)={<r9=>0x0}, &(0x7f0000000400)=0xc)
r10 = semget$private(0x0, 0x7, 0x3c0)
semop(r10, &(0x7f0000000700)=[{0x3, 0x4}, {0x2, 0x2ff}, {0x3, 0x8, 0x800}, {0x3, 0x3ff, 0x1800}, {0x0, 0x0, 0x1800}, {0x2, 0x6ff, 0x1400}, {0x0, 0x7ff, 0x1800}], 0x7)
ktrace(&(0x7f0000000340)='./file0\x00', 0x4, 0x0, r9)
semop(0x0, &(0x7f0000000280)=[{0x3, 0x1f}, {0x4, 0x3f}, {0x0, 0x2}], 0x3)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000140)={&(0x7f0000000100)=[{}, {0x5}], 0x2})


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x2, &(0x7f0000000080)=[{}, {0x5, 0x0, 0x0, 0x7}]})
sysctl$kern(&(0x7f0000000080)={0x1, 0x31}, 0x4000000000000004, 0x0, 0x0, 0x0, 0x0)
sysctl$hw(&(0x7f0000000480)={0x6, 0x1b}, 0x2, &(0x7f00000004c0), 0x0, 0x0, 0x0)
sysctl$hw(&(0x7f0000000000)={0x6, 0x13}, 0x2, &(0x7f0000000040)="b1319386b7539d2263000e8c061dd6879145d16a92fc41d3269976816db0ce7d02a414da28b4e6d34c7cbd1b90ef96bfcdaad43b8a2ca966b6596dfc3fd25239b10d04a1553024565f984d9ce16cb0a1faad5de8cd2c049fac2d3aebd8bfcc00ce75142c15ed7176a3ce4e0c556cf542a075e88df0036425917032e9b2c803bfa9a51c52ea71337aa4b18254d6ccc83209b78e35ad612c9d3ae1262985eaa24e9d4909dc2e582cc1e248dd2a6ce285fd4440229489d66f6cac757d5a75f09e7b953e76ee18c058a343494ee921a21ba9a27b69", &(0x7f00000001c0)=0xd3, &(0x7f0000000140)="d43764d4ff4af8dabac8559764b355a30f9e5902a339376732b3ff3f", 0x1c)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x808c694d, &(0x7f00000001c0))
mknod(&(0x7f0000000080)='./file0\x00', 0x0, 0xe02)
open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
pledge(0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000040), 0x2, 0x0, 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r1 = socket(0x18, 0x3, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r1, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x1, 0x1, 0x0)
r3 = socket(0x18, 0x2, 0x0)
setsockopt(r3, 0x1000000000029, 0xa, &(0x7f0000000040)='\t\x00\x00\x00', 0x4)
r4 = dup(r3)
setsockopt(r4, 0x1000000000029, 0xd, &(0x7f0000000000)="ffdaff10aac6a28ac93e2eddc45c8454e486f64c", 0x14)
close(r2)
r5 = socket(0x18, 0x2, 0x0)
setsockopt(r5, 0x1000000000029, 0x2a, &(0x7f0000000040), 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r2, 0x0, 0x0)
r6 = msgget$private(0x0, 0x0)
msgctl$IPC_STAT(r6, 0x2, 0x0)


syz_emit_ethernet(0x3e, &(0x7f0000000300)={@local, @remote, [], {@ipv4={0x800, {{0xa, 0x4, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @multicast2, {[@timestamp={0x44, 0x14, 0xf, 0x3, 0x0, [{}, {}, {[@multicast2]}]}]}}, @udp={{0x1, 0x3, 0x8}}}}}})


r0 = kqueue()
r1 = syz_open_pts()
kevent(r0, &(0x7f0000000640)=[{{r1}, 0xfffffffffffffffe, 0x3f}], 0x8008, 0x0, 0x0, 0x0)
syz_open_pts()
syz_open_pts()
kevent(r0, 0x0, 0x0, &(0x7f0000000280), 0x6c, 0x0)


msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0xa2}})
r0 = socket(0x18, 0x3, 0x0)
pwritev(r0, &(0x7f0000000180)=[{&(0x7f0000000240)="e006b531abceb495afdc8b5a64b2c9185b90c0e23c9eed1429c3a041f83532377bff100eafcb0d410f32e015d2d8b264ef19424e450ae24dcada8d12e0497fc04ebcb0abf66c55849b63ab837c2a600d1fcc4672bc5da2e77f5bdb693362274a9a62c2a01f10707e10d41ecf5fffe2a317b60a241b2e3aea4d37ecdfb8bfc51b6082984863c3dde57540864adef3ceeb8311460b8ee37ba3ac0f10d518085701aba20a8c6a30cf2a78af72bcdb4f9266ef127cc39a106a395960aeed8dcfd47305f91bbd2afcd3e84b14ad9f037e94ba14dd11c752f3a1aad78e65efdc357d6845cd529115e710be43548be843f214ac2c4fa750126dad9972ef081f763801c79b2085a0c28961c7ecbf1c27d1c605f3ecb9d8e3649790441971d4575bed82f30bdc88ac95bf85e2f2a8d5cac1f7fdad09c9a0f8bce35450df1ac6b897a60f1b939f1c9f5b9dcf1b34a477b7fa7cdd98d584683657d7981c84c0bddfc69d7c703a4d083b3cf8c000b632be4e61713a6c66e135e9427dfe2492ecb75a2b459a07e0a689cf8bd249298efb2fe68f88e4573d2580dbb9a1c45db5588a408d5234b107c203a2d90bf4f500adb675d1dd4237237bd3169ed66715629f0f657cded64f7af73239df9716bbe37f0ad8c450b42eda4ba8069abf70884392f66fa6888cbf108a24507f00a19531d624d5bcc75a5731db9b8179cf2f5616d7fe94e8dcf993b17613551e60edeebbbf647e5e9aa576d7d672d66e3d6befc0c47acace57e8dd4980f2a9b0a68fb1bf70d68dc4f5f3fb71bdc4a0aa1d6dbe8c2ed4fdfe6983188db9c755717dce8beacbef46c7f4ad9ed23d19fd652559e88095448b4698a6bd9f8ab614050c6d48f90f1b21928fb6d700fa3044d9290ceac45773b68493a9b66c76efe4b44fbe0e5673018a32deaa8a2123f5cfda6e1f13031c0d0f300e493314eed077480f2560c061dc076bed5f537d4e35bfff7bf37350dc16e9d8f928dd99e61cf2260e5477e9816f6f655e82ed05851c4e671a8163f3cf5fc2988a6c14b173930bc978a4e5c8c9ddd56374730fd15795b333fba44da442ac3cdd13c905f93c6705b148faa8068993d9e37a43e9a62d3aad65889a474e69adf14e320dab70f2939cd24125b6036e647d496212fcba5b47459d5151673f245fb3c2425d38c8c34ed987badcb113171717f01216af67340ad9c21e17417af3eb657fc8bb49bf58dedb87c7ec45a79cbc15524c8b9276776d1aab955086bacd67770f1483c1b489a7c5035e0bff929a2134ad8140b2800c6eabc808a09e291c2c993142f93d2a3dc2516caa8954b87ad3088c0da71eb77c24284ee02baa217e41a2a5e75e9aa1858971b7c07ca9a50f2b775b13668fbecfcf5e6f2533e764a1db9ab5006662938f54a821b143105f22b6ee4b7ce2a93a314e4dac8ed65a3e53096a2797257bd1d4fa6fbe27f0a5fa5bb77d1a1f4aed81cd5205dc195d5d4816ee10b8b9c9bde0d9671a457b447ec7594171420360e8f618f92e5c43ca6848fadd0b05d5222386dfabc7463fe7833e63fa1b7a1c998f136445c7a9b611f38911abfff4e9a6c7267a89283aaf0cd200de7249ff243f9320312e4c19f2b6ad0a21678a6d3a29d51369211dc13b4610f6905a2b6c0210f47f782951e3711d972e66971f9e319ace6c4761e02997938b6a1863f48ddfe0cc7b443b2776c6920ae9fc061aa032ca46a86e912a34bb2924ba3da0d3325cbf5f94d2ca629ac4aa400019c5af0b04c9d205aeb484ae2e33895b662c0e785f8a8786885e2f1740c4472d6d31e6fd94aff6980aa8975dd2ef97bb1a5b745887eba3c90693f9eab19b41811144907642fde4d39dc07914319147deb785546f3ba6ce43fd28cf35c7df374e261bd9fbae18115b8a24c2a70129923126cf407f79e5f37a1c92dec2ea8c8bc5ea9fd72e432293cb7a6af610a35e187c1ceb8f7938d24cf56127eeb1d4f75b3badcfc07c0ccfaf86b4ce018e3ea8ba1b6f9fb0ed7f37e4305aafbf6f13a3863556431d6dc93ad9b8ce51b00cc02330af457e8732b4e10102772123fe40d80e7e567ee2bc4928a0245a1fc2ef620c3aa6a61258672cc541be16883dc08541e3f221b4afe7b51d73e83c97cec1a6c43ddb224d73314bb749df74597c8d4ecd5da687ff5e51729db5c548d9cbd9a0947cc10075bdf4a5b26773bd33f777887c1015fcbd005cb7218c2953774bba675b4050ac889fa3dcd1bbb4a3fb309f4719f5e8ba513a54d59e3a5e98a6498079d73e5904156756dd585243aad8d0517d5b68e63b91f7d8a5f4b7c7748c5006b28f87e67d68baf77930a3601e8047106d00a62e6b2da34943f5b3255c7c6d6af553beb47d1f11c4dcf5c6c77fe22a4558a7f1b4f87aa4860fa2bec3db21f5fe5696e1e92f72be3a06584d3dfd95fa671eb3ac425b447371d87b077b8c9f5cd30b12d9ecf0a07d07fcdc48d153a639b5a50f165c0e317f929101d8aae0334978069538744c4c20b1f8aa9deb118e7b40df3df2a37241eba4cb1a24914055831320da37750a7b8c3d323e19f900704f916caa7e79c81b15f0bfec5ad504e767b3a0ad374db6cfef5c1b16b65ff4b6121064a85c59165c94a46cafd7696827a95ed3d0745c15c8ca9adf5d24c3bcc7bd8945c005ab8beb13fc05d4f05dec4135a34015178242b0ea7ec348bdbe5b6e7602a1f411982b0ddefcf45d034020989478a2b4de5db4bf9ddfef1239b14d2cb234492ca1e5d0561ac0dcee5051eb428a2b6eebd8178339fa1d6b031dda55bae4df8be15ccb8906a1015c9924c8a8f4a69dc63730c92deabeab43247169a37b5031ca674d87bbb11c8ad7ab63fc9f5535775d5f2b86fbbe1fffc975313359a0a35c1c8cca8fb86abae9ecd1636b3dc29b3b6410ed3722fa749f85cc1d9bb36453c3ec2e588df3ec38d665d2637319c35fb29da651248c208242b500aa715e41a7ecf5849f580166b7a57a8ffef3f7c277b8d4a1837ea78a8ddf5bb68e4cc3e5b4f82c3077fc5b731a3c3894226d9d88a15d1ec282052049e0b9ae6d48ad90e3b9be20512b1340420da1a050721135a729de5ee245be21cab0bbceaf12a63c5037db91979d98afee14737d2a70d15796ac2b0c8786a6fb38adf8182e32fa2abc930887d6d214a97a119f1222cb9267a6c0966f13c8d93343fe1a3200fa4249ef04139e6c659bf7d13301a1f74acee610e54584891ccaa6cd75f97f9e73e2dfca9a8d1e4f142300a0452ea287390d544f9ef9f3fd76f90176a4c1423a0e60013729b9ef1152487c956c4c1b8d47a93a0f385fd5c51b492e71f434b3aea3b61a527805c2b4025f560cb313438eab8ba4a7baae812ef8eca52217af50177a1081720357f6c645f6c0932e59fa8047cfa146f8d5d263a58178e8b04c7b528d23dded1a0d089d3b4a2136399fa509424d95f7975a6c579fe1e32f9f29b757af66c748b78d86ba3c5b1ab56f1d6ba6197acee5af0aac06f4b3617a89f3d0a1ed2d991420f1eb113211920f34b3cd098b1e3c5f60d41d9e5914c593f9d5e8d0e02601dea9618b80abf3e71240f27836411adadd68a6c87cca195b94b02314daa898fa98452e72266fec21c18d51e7d0f05f2569f50978f767975dfabeb131bf628ec8382f2adb4fc9ff00a278015b6602b755a7d5eff01fda7f333a41b0718df7eb258b4002c6224dd6fa4afbcce016ab430c4fc9d665ed3afd1e750b7c8975c1042b4704d73b4cbdb0575f0c0481b383b8d21cae6767e3fe67f03433b426171bfa33f509e4042bf1996eb0be161fdec5a6e63d9fb7b35ac1c76aa378ef9f507aa08f3de48cde0cb0a1479bd41ab8b54aa6293f008c2f0938e3e5a895cad3f9f3dc5f82dedb3a23024f267cb6c288f30f8ab53a723fb36d17535b72c8e22015b71c02f51e802548b29957d2349a255be116ce2abc0743d03fcdbe98ce0fa28add7d6b12b9fa3e66157a086f082e4e84acff2ea6c351b6f8cc6a25cebaa6801aca1a1bb8717de04b0b10126f9ad0d3fd52c93588cf9e3da329fd43ffbdaa0255a94ca65abb735c56bad251673ce2a7bc5bddfb0ad1c58ce2edf3a46f437b6b53f98a0da6dce82679113b9e63a4ad04c2831554ca41f8d4b245be27fb214e3e901384effbd69d78b92c7afd5d814f426dc0560a6c54deaa1f741f0b63e571c5c395dff95f43626cb6b918d41db7bc7d4adb1f4849ec66bad7f855c35f4b243233c5cc192c96f65274fff87714028f4b1bc994235858b03fe0a57a38d7c931151616ec78cf477bdcefb7388a95116dec63624d1399508ad7c42995c9f6fbecf1d4c1a85f86b842c17f2c5a822db539b5bc05ab621a1c6600321977f49263d8d03bb145144f98af63e9095f79598187b00c38077a7b8d8f1b3a5fd0a40c4483a0b42353a7deea5b1fe996101083f236e0436f842a0e0183f0266f1567018b50bd4f545576403943ebfbcf0fb531c12b4b5bb31ef403b055e08d116e365c14d66d66514b4e83f41c479db246619ffd7cb54147692bc5eac7bd53395fb53e0df2dc3958e6e14b6e1b01f7f66e69072fc5877006a12fc236a94fa6b3d88ddf9a40323e4f06674d2028b278884fb5cf63ccd8b5eb98e8c793feda51dcf02daac928a66616fd8a2c3d5cdc307a142bf6eee810dabcfd2a1787fbd59eb722dc0284b1bd6704f18af7262f96886670319e10b3a23b7beae85f12e74bfa63110217f88933a999652e41f5578a03823ff3ab55ebcbdfc66680868e4c1c7b3d65d1423ca29d67283afd99fcb2d7cdd3b6a3d8a669de81cbf27e64e52e2b5eb655a8de9294c0bec0da96e3083fe906a178856f2fd9d5694e83fb3992f03bb866f5dd70d742451676cfd7668090a0eb9e24ded02ce8d3c03086d41e2132c0719bf5451e4affd15f8dedc3e639461d77258ac6f120b4ae371754f0b210fbfeefeb9adead829b1981fa14480bab5c2260e2523b318d9e03b554a3d1a846f5daf836b04bd61ea15cec39db93bf650cb706cbd94daef90b9667bc2069de0be87c504f85771068b3aba5bab55c6d79f3b18eb68b4094bf02fc99864d3b775de1078fde29d07cc243e6680794177f56655c4bf3da2505a743a4fd3dbcbd86f234382f7dba17bcdd6a01e2cc3e36c8016b3bd4b3c7fae2af2805ffb53cd44d23d47700639dad9ec5973ea02a2a7836a6a7ae57b939825e184851c66923f5b3490972027d950ae847ff1486af63d293e9f6d94517e04e5ff7874e7e1df14b64f59cca00bc42302254cc9df714d865bf79411b5782ab7937552b4341e3b7fcc46a296d8d8d8c8c5142de04038c8d952af5fcf6cefea1cca0d9cdf6cc9fee18f8618bea34cf18ae5007fb055401a326c6c58e938c3e984f4952d3e3a35565a07e87225ff16681185aa0d645ef4d9e6bd8fa0ddf72bfb98ca7d6f023b247ea789316c99a6566446bdad5f1404b9fed9b5c9f10598fdf93f933499af8d200f05cab7d31b6393b2085ef2d4ea9bafac7e9fbe2ce65b343a9b105a4ed45bedff656bdc3d609f3f790ca7e946d8f0af14034fb7db95cdd71953bbe5267d3b98a128a8a1ef2a21269bb507ae74cf1ea2b9864eb0bd30cf54270405fd413dedbed2fe961e0067116aae8228a0194ef77b81b8a4716cc6a9eb7601bd68b334e69e9923c4beea5a0d2ac2b890ccc16e9031c7a9b0504532f0f0612fbbc2b1747538688c7281a31b55dc3dc11a3e21fe46d9c7655988902778858aee8da39dbbb36dbd6c148f885ff2e8184b7994924327091184bd9c5a59a857b2d72390f4f0d5d43", 0x1000}], 0x1, 0x2d2)
r1 = socket(0x11, 0x3, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1002, &(0x7f0000000000), 0x4)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0x0, 0x0, 0xffffffffffffffff, 0x0, 0x6, 0x2}})
connect$unix(r0, &(0x7f0000000140)=@abs={0x1, 0x0, 0x3}, 0x8)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x100}, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7fffffffffffffff})
r2 = socket(0x18, 0x1, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r3 = socket(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r3, 0x8040691a, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2e, &(0x7f0000000080)={@random="b1d3bd0a0c02", @broadcast, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x1, 0x0, @remote={0xac, 0x14, 0x0}, @multicast1, {[@lsrr={0x83, 0x3}]}}, @icmp=@info_request}}}})
symlink(0x0, &(0x7f0000001240)='./file1\x00')
open$dir(0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r4 = open(&(0x7f0000000480)='./file0\x00', 0x382, 0x0)
poll(&(0x7f0000001840)=[{r4, 0x40}], 0x1, 0x0)
rename(&(0x7f00000001c0)='./file0\x00', &(0x7f0000000200)='./file1\x00')
r5 = semget$private(0x0, 0x4, 0x1e)
semctl$GETNCNT(r5, 0x0, 0x3, &(0x7f0000000000)=""/4094)
r6 = socket$unix(0x1, 0x5, 0x0)
setsockopt$sock_int(r6, 0xffff, 0x10, &(0x7f0000000040), 0x0)
semctl$GETALL(r5, 0x0, 0x6, &(0x7f0000001000)=""/229)
semctl$GETPID(r5, 0x0, 0x4, &(0x7f0000000000)=""/13)


kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f00000001c0)={0xc8, 0xffffffffffffffff})
r0 = kqueue()
kevent(r0, &(0x7f0000000000), 0x1ff, 0x0, 0x89c, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f00000000c0)=[{0x6c}, {0x1c, 0x4}, {0x16, 0x2}]})
syz_emit_ethernet(0x3e, &(0x7f0000000300)=ANY=[])


setreuid(0xee00, 0x0)
getuid()
sysctl$hw(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
setrlimit(0x0, 0x0)
r0 = syz_open_pts()
getgroups(0x0, &(0x7f0000000040))
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, "000086fffffffffffffffd00"})
ioctl$FIONREAD(r0, 0x4004667f, &(0x7f0000000080))
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x83fe})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x2, 0x0, 0x1d}, 0x4, &(0x7f0000000280)="217ee6b45887c517e50e14d5c409e6ecec4e3a0ccb073656ffcaaab32777d30cbb02f813d6d0babbb78add37483794ed6e65e60528119aba449a79566e0c15237b1c4d2b8bd97170ffce97226c4c830e651acca9faab2cbf54731299364a48941750f93b11c4edbbcfa88acc5a151c5208ba496e3b993994a486afd3eedf98ffcec1620d8eb91054a9c7f4bb2b58b0c91ebc9db5421d85b0dc2ec3", &(0x7f0000000100)=0x9b, &(0x7f0000000140)="6b2c25889af8f66013", 0x9)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
dup(0xffffffffffffffff)
r1 = socket(0x18, 0x2, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = socket(0x18, 0x1, 0x0)
dup2(r1, r2)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendmsg$unix(r2, &(0x7f0000000540)={0x0, 0x0, 0x0}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f00000000c0)=[{0x24}, {0x7c}, {0x16}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x2a, &(0x7f00000001c0)=ANY=[])


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
syz_emit_ethernet(0x1b, &(0x7f0000000000)=ANY=[@ANYBLOB="fffd640000000000000000000a"])
sysctl$kern(&(0x7f0000000000)={0x6, 0xb}, 0x5, 0x0, 0x0, 0x0, 0x0)


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x13}, 0x4, 0x0, 0x0, &(0x7f00000010c0), 0x210)


pwritev(0xffffffffffffffff, &(0x7f00000001c0)=[{&(0x7f0000000200)="18d26cb474b5c9d53e0ffdba8c54fecc9031509b1623088cc3e85353a5586603eebda7eccfc5ced62b70a12fbffc2425f3f9e50317605792ea906ef56376aa499b9a909aff511ad2d6", 0x49}], 0x1, 0x0)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000080)="eaef125c00000000", 0x8)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)


pipe(&(0x7f0000000100)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
r2 = getppid()
r3 = getpid()
setpgid(0x0, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r3})
pipe(&(0x7f00000001c0)={<r4=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r4, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r5 = fcntl$getown(r4, 0x5)
fcntl$setown(r0, 0x6, r5)
r6 = fcntl$getown(r0, 0x5)
fcntl$setown(r1, 0x6, r6)
setpgid(0x0, r2)


sysctl$vm_swapencrypt(&(0x7f00000002c0)={0x2, 0x5, 0x3}, 0x3, 0x0, 0x0, 0x0, 0x0)


r0 = open(&(0x7f00000001c0)='./file0\x00', 0x2e1, 0x0)
r1 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
pwritev(r1, &(0x7f0000000600)=[{&(0x7f00000000c0)="95", 0x1}], 0x1, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x1, 0x10, r1, 0x0)
openat(0xffffffffffffffff, &(0x7f0000000100)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0, 0x2015, r0, 0x0)
msync(&(0x7f0000ffa000/0x4000)=nil, 0x4000, 0x6)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000000)=[{0x44}, {0x34, 0x0, 0x0, 0x3}, {0x9106}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x3, "cfe4ef0d51a8f12514cfc9f3cb5e53f617f969ef"})
sysctl$kern(&(0x7f0000000080)={0x1, 0x37}, 0x4000000000000004, 0x0, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f00000001c0)=[{0x50}, {0x61}, {0x810e}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000140)=[{0x1c}, {0x2c}, {0x6}]})
syz_emit_ethernet(0x127, &(0x7f0000000040)=ANY=[])


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x45}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000000c0)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
recvfrom$unix(r0, &(0x7f00000000c0), 0x832f1f7d, 0x0, &(0x7f0000000000)=@abs, 0x2000c600)
sendto$unix(r1, 0x0, 0x0, 0x0, 0x0, 0x0)


sysctl$vm(&(0x7f0000000340)={0x2, 0x7}, 0x2, &(0x7f0000000700)="6130c04bad66b8ba9155080015b060a398ce5ec38c746295e5d5baf497ea23c95b04dbabb0ccb9c7f3a50a84064d1565f1a92ff4ab8dc6f2c089e1bfcec221", 0x0, &(0x7f0000000240), 0x0)
open(&(0x7f0000000040)='./file0\x00', 0xfffe, 0x51)
r0 = socket(0x18, 0x0, 0x0)
shutdown(r0, 0x1)
ioctl$VMM_IOC_RUN(0xffffffffffffffff, 0xc0205602, &(0x7f0000000300)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000040)={{}, {[], [], [], [], [], {}, {0x0, 0x0, 0x0, 0x9}}}, 0x0, 0x7f})
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x2}, 0x4, 0x0, 0x0, &(0x7f0000000280), 0x4)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000100), &(0x7f0000000180)=0xc)
r1 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000240)="ea00000100000000", 0xc)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
r3 = socket$inet(0x2, 0x2, 0x0)
close(r3)
r4 = socket$inet(0x2, 0x2, 0x0)
dup2(r2, r4)
setsockopt$inet_opts(r3, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0x8)
sendto$inet(0xffffffffffffffff, &(0x7f0000000640), 0x0, 0x0, &(0x7f0000000440)={0x2, 0x1}, 0xc)


syz_open_pts()
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{}, {}, {0x7, 0x0, 0x0, 0x7fffffff}]})
r0 = socket$unix(0x1, 0x2, 0x0)
semget$private(0x0, 0x4, 0x0)
socketpair$unix(0x1, 0x5, 0x0, 0x0)
mprotect(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r1 = msgget$private(0x0, 0x0)
msgrcv(r1, &(0x7f0000000b40), 0xa6, 0x0, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x6000, 0x5200)
fcntl$dupfd(0xffffffffffffffff, 0x0, r0)
msgsnd(r1, &(0x7f0000000340)=ANY=[@ANYBLOB="02"], 0xe1, 0x0)
ioctl$FIOASYNC(0xffffffffffffffff, 0x8004667d, &(0x7f0000000180)=0x2a)
open(&(0x7f00000001c0)='./file1\x00', 0x2, 0x20)
open(0x0, 0x80, 0x40)
writev(0xffffffffffffffff, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
socket(0x2, 0x1, 0x0)
r2 = open(&(0x7f0000000100)='./file0\x00', 0x20000, 0x1ae)
fcntl$lock(r2, 0x8, 0x0)
r3 = socket(0x18, 0x2, 0x0)
setsockopt(r3, 0x1000000000029, 0xb, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
setsockopt(r3, 0x1000000029, 0x36, 0x0, 0x0)
getitimer(0x2, 0xfffffffffffffffe)
r4 = socket(0x2, 0x0, 0x0)
connect$unix(r4, &(0x7f0000000000), 0x10)


r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x800000018, 0x3, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x120}})
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
syz_emit_ethernet(0x5e, &(0x7f0000000080)={@broadcast, @local, [], {@ipv6={0x86dd, {0x0, 0x6, '\x00\t\x00', 0x28, 0x0, 0x0, @rand_addr="6e1aa4058b74adad9a4e721f5b293380", @mcast2, {[@hopopts={0x0, 0x1, '\x00', [@pad1, @pad1, @ra]}], @icmpv6=@ndisc_ra}}}}})
openat$speaker(0xffffffffffffff9c, &(0x7f00000000c0), 0x8000, 0x0)
open(&(0x7f0000000180)='./file0\x00', 0x80000000000206, 0x0)
socket$inet(0x2, 0x8003, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd, 0x0, 0x4}, 0x0, 0x0, 0x0)
mkdir(0x0, 0x0)
setreuid(0x0, 0xee01)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000002c0)={<r2=>0xffffffffffffffff})
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f00000000c0)={<r3=>0x0, <r4=>0x0}, &(0x7f0000000040)=0xc)
r5 = msgget$private(0x0, 0x397)
msgrcv(r5, 0x0, 0x0, 0x0, 0x0)
msgctl$IPC_SET(r5, 0x1, &(0x7f0000000340)={{0x80000001, r4, 0x0, r4, 0x0, 0x2, 0x9}, 0x7ff, 0x0, r3, r3, 0xffffffffffffffff, 0x7})
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0xffffffffffffffff}})
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmsg(r0, &(0x7f0000000280)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000300)=[{0x10}], 0x10}, 0x0)


nanosleep(&(0x7f0000000080)={0x0, 0x40000000000000}, 0xfffffffffffffffe)
r0 = socket(0x18, 0x2, 0x0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r1, 0x80047460, &(0x7f00000000c0)=0xffffffff)
ioctl$FIOASYNC(r1, 0x80047460, &(0x7f0000000200))
close(r0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x88}, 0x4})
r2 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r2, &(0x7f0000000040)=@abs={0x0, 0x7, 0x1}, 0x8)
socket(0x800000018, 0x1, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(0xffffffffffffffff, &(0x7f0000000080), &(0x7f0000000000)=0xfffffffffffffe22)
r3 = socket(0x18, 0x2, 0x0)
getsockname$inet(r3, &(0x7f0000000080), &(0x7f0000000040)=0xc)
r4 = socket(0x18, 0x2, 0x0)
r5 = socket(0x800000018, 0x1, 0x0)
bind$unix(r5, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
setreuid(0xee00, 0x0)
r2 = getuid()
setreuid(0x0, r2)
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x802069b5, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000100)=[{0x2}, {0x4c, 0x0, 0x0, 0x1}, {0x8016}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = syz_open_pts()
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001280)={0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x400}, 0x40c)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
sysctl$kern(&(0x7f0000000700)={0x1, 0x32}, 0x4e, 0x0, 0x0, &(0x7f0000001440)="cca410df", 0x4)
writev(r0, &(0x7f0000000540)=[{&(0x7f0000000240)}, {0x0}, {0x0}], 0x3)
syz_open_pts()
syz_open_pts()
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000040), &(0x7f0000000180)=0xc)
ioctl$FIONBIO(r0, 0x8004667e, &(0x7f0000000340)=0x8)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f0000000080)={&(0x7f0000000040)=[{}, {}], 0x2})
setsockopt$inet_opts(r1, 0x0, 0x200100000001d, 0x0, 0x0)
r2 = msgget$private(0x0, 0x0)
getsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x14, 0x0, 0x0)
msgsnd(r2, &(0x7f0000000100)=ANY=[@ANYRES64=r1], 0x107, 0x0)
msgrcv(r2, &(0x7f0000003c00), 0x1013, 0x3, 0x0)
setrlimit(0x3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r3 = socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(r3, 0x8020691f, 0x0)
r4 = socket(0x0, 0x4, 0x1f)
setsockopt(r4, 0x0, 0x0, &(0x7f00000000c0)="1f72685f91520713aa032f9fa732f8eb53073ab7090c077a4c0dbdb95e9d4a092034b4b7075c8cec0599a089f6dcc7760f86b7dca0983ef85f", 0x39)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)


r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r1 = socket(0x18, 0x3, 0x0)
setsockopt(r1, 0x1000000000029, 0x9, &(0x7f0000000080)="01000000", 0x4)
close(r1)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r2 = socket(0x2, 0x2, 0x0)
bind(r2, &(0x7f0000000000), 0x10)
connect$unix(r2, &(0x7f0000000000), 0x10)
accept$unix(r0, 0x0, &(0x7f0000000100))
bind(0xffffffffffffffff, &(0x7f0000000000), 0x10)
syz_emit_ethernet(0x86, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x78, 0x0, 0x1}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x1, 0x0, 0x7, 0x4, 0x0, 0x0, 0x0, {[@generic={0x0, 0x6, "96c72963"}]}}, {"d1c2f0bfe2d0786ca28e44289f59aba04d62ff16e6bb47f1cd981d0cf5f225560531db5a3a6c3cb3d5ac50e0eec7423f3ef5e3c4a13f81f14f843a32b529e4649b57d581159522dd"}}}}}})
setreuid(0xee00, 0x0)
r3 = getuid()
setreuid(0x0, r3)
sysctl$net_inet_tcp(&(0x7f0000000140)={0x4, 0x1e, 0x2, 0x1}, 0x4, &(0x7f0000000300), 0x0, 0x0, 0x0)
pipe2(&(0x7f0000000200)={0xffffffffffffffff, <r4=>0xffffffffffffffff}, 0x10004)
readlinkat(r4, &(0x7f0000000240)='./file0\x00', &(0x7f0000000280)=""/117, 0x75)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x2, &(0x7f0000000080)=[{}, {0x3, 0x0, 0x0, 0x7}]})
sysctl$kern(&(0x7f0000000080)={0x1, 0x31}, 0x4000000000000004, 0x0, 0x0, 0x0, 0x0)
r5 = socket$inet(0x2, 0x1, 0x0)
ioctl$BIOCSETF(0xffffffffffffff9c, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000180)=[{0x2, 0x1, 0xf0, 0x9}, {0xfffe, 0x80, 0x1b, 0x8}, {0x3, 0x0, 0x2, 0x4}]})
setsockopt$sock_int(r5, 0xffff, 0x2000, 0x0, 0x0)
r6 = semget(0x0, 0x4, 0x7d8)
semctl$IPC_RMID(r6, 0x0, 0x0)
semctl$IPC_RMID(r6, 0x0, 0x0)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
bind$unix(r0, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
connect$unix(r0, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
close(r0)


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x2, &(0x7f0000000040)=[{}, {0x3}]})
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0x2, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0x4)


ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x0, 0x0, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x5200)
open(0x0, 0x40, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000140))
r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
close(r0)
open(0x0, 0x80000000000206, 0x0)
chmod(&(0x7f0000000080)='./file0\x00', 0x0)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
socket$inet(0x2, 0x1, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x10, 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x64, 0x0, 0x0)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x7fffffff, 0x0, {0x0, 0x3}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
close(r0)


syz_emit_ethernet(0x1a, &(0x7f0000000040)={@broadcast, @broadcast, [], {@arp={0x8035, @ether_ipv4={0x1, 0x800, 0x6, 0x4, 0x0, @empty, @empty, @broadcast, @loopback}}}})
r0 = socket$inet(0x2, 0x8003, 0x0)
setsockopt(r0, 0x0, 0x7, &(0x7f0000000340)="15337ac0", 0x4)
syz_emit_ethernet(0x2a, &(0x7f00000002c0)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, @multicast2}, @icmp=@echo}}}})
syz_emit_ethernet(0x7e, &(0x7f00000002c0)=ANY=[])
recvmmsg(r0, &(0x7f0000000040)={0x0}, 0x10, 0x0, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x10000, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
r0 = socket$inet(0x2, 0x0, 0x80)
getsockopt$sock_timeval(r0, 0xffff, 0x1005, 0x0, 0x0)
wait4(0xffffffffffffffff, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
mknod(0x0, 0x0, 0x0)
open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
recvmsg(0xffffffffffffffff, 0x0, 0x0)
preadv(0xffffffffffffffff, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x2, 0x3, 0x0)
bind(r1, &(0x7f0000000000), 0x10)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000080)=[{0x40}, {0x34, 0x0, 0x0, 0x3}, {0x8106}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


sysctl$kern(&(0x7f0000000040)={0x1, 0x54}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0x2, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0x4)


r0 = socket(0x11, 0x3, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x2000, &(0x7f0000000080)=0x4, 0x4)
setrlimit(0x8, &(0x7f0000000980)={0x9, 0x100000001})
r1 = syz_open_pts()
close(r1)
syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000040)={0x0, 0xffd, 0xfffffffe, 0xd2d, "8717f9050700000000000090d692480d51aa8000"})
writev(0xffffffffffffffff, &(0x7f0000000280)=[{&(0x7f0000000000)="f90b94074f9cfa606f36130794f73c16284d0d", 0x13}], 0x1)
pread(r0, 0x0, 0x0, 0x0)
r2 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
fcntl$lock(r2, 0x8, 0xfffffffffffffffe)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r3 = getpid()
getpid()
ktrace(0x0, 0x0, 0x0, r3)
setuid(0xee01)
ktrace(0x0, 0x5, 0x22, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0)=@file={0x0, '\x00'}, 0x3, 0x0}, 0x0)
r4 = socket(0x800000018, 0x2, 0x0)
bind$unix(r4, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
sendto$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)
r5 = msgget$private(0x0, 0x1c)
r6 = getpid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0xffffffffffffffff}, 0x0, 0x0, 0x0, r6, 0xfffffffffffffffe})
msgctl$IPC_SET(r5, 0x1, &(0x7f0000000200)={{0x4, 0x0, 0x0, 0xffffffffffffffff, 0x0, 0x80, 0x80}, 0x0, 0x0, r6, 0x0, 0xffffffff, 0x2, 0x80000001})


setrlimit(0x8, 0x0)
msgctl$IPC_STAT(0x0, 0x2, &(0x7f0000000340)=""/104)
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x8004745d, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000400)=[{0x4c}, {0x25}, {0x812e}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])
sendmsg$unix(0xffffffffffffffff, &(0x7f0000002a40)={&(0x7f0000000000), 0x10, 0x0}, 0x0)
socket(0x0, 0x0, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd, 0x10000000000}, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f0000000440)={0x10, 0x1, [{&(0x7f0000695000/0x3000)=nil, &(0x7f0000079000/0x1000)=nil}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000242000/0x3000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f000065b000/0x1000)=nil}, {&(0x7f0000675000/0x4000)=nil, &(0x7f00006bd000/0x1000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f000006b000/0x3000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x20}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f00000ad000/0x4000)=nil}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000604000/0x3000)=nil, 0x80000000}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f00004f6000/0x3000)=nil, 0x400}, {&(0x7f00005a6000/0x2000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f00000ca000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000009000/0x3000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000ffc000/0x1000)=nil}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil}], './file0\x00'})
socket$inet(0x2, 0x3, 0x0)
r2 = socket(0x2, 0x3, 0x0)
msgsnd(0x0, &(0x7f0000000080)=ANY=[@ANYBLOB="01002fe6db5000f4818f1b86adaee2f2513b3469ba1d635756940900000000b145bda75e239c26ca387ff7cc3be75c916f4fc428a104f8416bcc48ece359e4f57a1411aa84a0bfe4104eb07a4b01fa8b7e710b2b5f6dff18961bfdb0aeba6c09880f8fc414f5c3b4bae058be4dcb515c7bead0ca3c31c169b58008e0c6d747567778e48b12506032df5f413f3fb5cfdd1a5ea5183cba6cf95f0ab2692d0000000000"], 0x67, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
pipe(&(0x7f00000002c0))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r2, &(0x7f0000000000), 0x10)
connect$inet(r2, &(0x7f0000000040)={0x2, 0x1}, 0xc)


r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r0, 0x80085761, &(0x7f00000000c0)={0x2})


writev(0xffffffffffffffff, 0x0, 0x0)
kqueue()
msgctl$IPC_SET(0x0, 0x1, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f00000001c0)=[{0x81}, {0x24}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


pledge(0x0, &(0x7f0000000080)='-!\x00')


r0 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
setrlimit(0x8, 0x0)
close(0xffffffffffffffff)
syz_open_pts()
sysctl$net_inet_tcp(&(0x7f0000000080)={0x4, 0x2, 0x6, 0x16}, 0x4, &(0x7f0000000340)="f317095cc5d422ea6bc00b059f7e1ea0d814005db8b737ff004f5de2749ea7097cbd8addcd95649c55a4df4d4bc4fff44408a28a7ded9b72e7e9c594788c5316c3c2ccddb0aff6e7fd96bb6a236dd5a5d509c4d6c934f2390e157fa8a1d0cb0310b76573146ffa32be83c39251f4fcbb559d816047cd645274c5c95636cd3f8460a73aaa490ea6978de9f55f4933e1ba5da368e5fe4ffbaf2a7dff36e3ac48827b01b537e5470977fc0b9506153a024286f5ddcb", &(0x7f0000000100)=0xb4, &(0x7f0000000480)="c1dec858544040db9dd274d08f203549f5a2d33dcae44c4ecf8c39c603ef3c9f4230709c9e63a98fbe82ea12062c619b7465dc7a9b8e9e115766adaa7c932ca0c67f27e9682bfd9d93af06740c1ffa4e3fdcfa446994ff635ab45ff00a5ada9458cb49165b6655751f698f85e9fc9856c32a530d8f44820f677507c16c54fec44d49b7", 0x83)
setsockopt$sock_linger(r0, 0xffff, 0x80, &(0x7f00000000c0)={0x0, 0xffffffff}, 0x8)
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
sysctl$vfs_nfs(&(0x7f0000000000)={0xa, 0x4}, 0x3, &(0x7f0000000040), 0x0, 0x0, 0x0)
r2 = kqueue()
openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
kevent(r2, &(0x7f0000000100), 0x101, &(0x7f0000000180), 0x6, 0x0)
ioctl$FIONREAD(r0, 0x8040691a, &(0x7f00000001c0))


mknod(&(0x7f0000000040)='./file0\x00', 0x6000, 0xe02)
mknod(&(0x7f0000000040)='./bus\x00', 0x6000, 0xe02)
open(&(0x7f0000000040)='./bus\x00', 0x0, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
openat$vnd(0xffffffffffffff9c, &(0x7f0000002340), 0x1, 0x0)


openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
open(&(0x7f0000000140)='./file0\x00', 0x200, 0x11)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCPROMISC(r0, 0x20004269)
r2 = socket(0x2, 0x2, 0x0)
dup2(r2, r0)


sysctl$net_inet6_ip6(&(0x7f0000000000)={0x4, 0x18, 0x29, 0x33}, 0x4, &(0x7f0000000080)="d767b2742c1f1b1761b8f5a59e71e317d7d5add1987defda1dbcef26f26cbb5ce6a3241bc2f8422b7900ad53aa60aa389da8e2a4f9fd011d60f0ef6aeffff9a6e3fb8104310ac20fb64707910f45cac4a1d73470ad840b01e6ea38a2fce1141bb0e591681a3ed4a717eb62d148035c052087f04aee124c75", &(0x7f0000000100)=0x78, &(0x7f0000000140)="65b81128cf2800a9d110afd727da9ca726026a8707116412d170b645891d8133f142954cd9c2dbb6ef2a046cd4d57ee3a4c5acb36fb4f67d0995f5ff32e63450634b0ad3b394f9df2e84b52c96e9c20100000000000000e1aeb875952c87f3045e2a24b3769a57e17e7be2a8e89a21f265aef687addc", 0x76)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x2e}, 0x4, &(0x7f0000000200)="61220607207af80f398c5a6510a59038c962561c860964964d21114e86f782a18115203b3163884d2e3148bc93d6fa2076bbde93fc27aad0212f8d616b2f3bfe46cdbe863201b4cdc066bf834517c1bd38c526e04eb26e7e22330bb1a4446e1befcbd04fd7763dac6583febc4bacbc2ab7f3fac7ce71cb990de50302e670848276d59e096600756d15aa5b030df1392691b18ddcd7f6ab8c22260872bf628208cae70372c6b88139dd98962de9316ad98a70b4f51326c678ddec6da9c88aa0db2d028dde7067f2002b3603e4964ed706619094d1006e3db46b85860a6021afd908bdabfa0e33a4516fe4305be8a58eebd956d8e9", &(0x7f0000000300)=0xf4, &(0x7f0000000340)="0de906d61385f0db1d70f4ffe74507db1f4d442d0e36e6", 0x17)
syz_open_pts()
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x101, 0x200}, 0x400})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, 0x0, 0x0)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r1 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000004840), 0x1001, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r1, 0x80105728, &(0x7f00000048c0)={&(0x7f0000004880)=[{0x20}, {0x1}], 0x2})
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
sysctl$net_inet_divert(&(0x7f0000000000)={0x4, 0x18}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x55}, 0x3, 0x0, 0x0, &(0x7f0000001300), 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r2 = socket(0x18, 0x3, 0x0)
connect$unix(r2, &(0x7f0000000180)=@abs={0x1, 0x0, 0x2}, 0x8)
getsockname$inet(r2, &(0x7f0000000380), &(0x7f00000003c0)=0xc)
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
socket(0x18, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
r3 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000040), 0x800, 0x0)
ioctl$VMM_IOC_INFO(r3, 0xc0185603, &(0x7f0000000080)={0xb4, 0x0, &(0x7f0000000140)=""/180})


openat$bpf(0xffffffffffffff9c, &(0x7f0000000400), 0x0, 0x0)
socket(0x11, 0x3, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
open(0x0, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, 0x0)
sysctl$vm(0x0, 0x0, 0x0, &(0x7f0000000340), 0x0, 0x0)
ioctl$TIOCSTSTAMP(0xffffffffffffffff, 0x8008745a, &(0x7f0000000000)={0xffffffff})
ioctl$WSKBDIO_SETKEYREPEAT(0xffffffffffffffff, 0x800c5707, &(0x7f00000000c0))
ioctl$FIONREAD(0xffffffffffffffff, 0x8040691a, &(0x7f00000001c0))
r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x400, 0x0)
writev(r0, &(0x7f0000000580)=[{&(0x7f00000001c0)}], 0x1)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0x0, 0x0, 0xffffffffffffffff}, 0xffffffffffffffff})
r1 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r1, 0x8040691a, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000040)=[{0x2c}, {0x2}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000300)=ANY=[])


r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x28, &(0x7f0000000000)="5ab7776a", 0x4)
syz_emit_ethernet(0xba, &(0x7f0000000300)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaabb86dd600000000084000080000000000000000000000000000000ff020000000000000000000000000001"])


r0 = socket$inet(0x2, 0x2, 0x0)
getsockopt(r0, 0x0, 0x8, 0x0, 0x0)
r1 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r1, 0x0, 0x64, 0x0, 0x0)
r2 = socket(0x0, 0x3, 0x0)
sendto$unix(r2, &(0x7f0000000180), 0x0, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$WSKBDIO_SETMAP(0xffffffffffffffff, 0x8010570e, &(0x7f0000000080)={0x9, &(0x7f0000000180)=[{0x8, 0x401, 0xb0, 0x5, 0x5}, {0x0, 0x9, 0x1, 0x1000, 0x1}, {0x7, 0xdb8, 0x1}, {0x8001, 0xfffb, 0x1000, 0x101, 0x8}, {0x0, 0x200, 0x3, 0x4}, {0x0, 0x8, 0x7, 0x5, 0x4}, {0xffff, 0xb53, 0x9, 0xcb, 0xe386}, {0x3f, 0x4, 0x1, 0x4, 0xff81}, {0x7, 0x81, 0xf800, 0x8, 0x8d10}]})
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x2e, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140)={<r3=>0xffffffffffffffff})
mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
rmdir(&(0x7f00000001c0)='./file0/file0/..\x00')
r4 = accept$inet6(r2, &(0x7f0000000100), &(0x7f0000000200)=0xc)
accept$inet6(r4, &(0x7f0000000000), &(0x7f0000000040)=0xc)
socket(0x1, 0x3, 0x3)
shutdown(r3, 0x2)
r5 = syz_open_pts()
ioctl$TIOCSETD(r5, 0x8004741b, &(0x7f00000002c0)=0x8)
syz_open_pts()
syz_open_pts()
r6 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
lseek(r6, 0x0, 0x2)
getsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)


sysctl$net_mpls(&(0x7f0000000240)={0x6, 0xb, 0x1}, 0x5, 0x0, 0x0, 0x0, 0x0)


open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x3, 0x10, r0, 0x8000000000000000)
poll(&(0x7f0000000ac0)=[{0xffffffffffffff9c}], 0x20000000000000d7, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000140)=[{0x1c}, {0x3c}, {0x6}]})
syz_emit_ethernet(0x127, &(0x7f0000000040)=ANY=[])


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000240)={0x3, &(0x7f00000000c0)=[{}, {0x1, 0x0, 0x0, 0x1}, {0x6}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0xff0a, 0x0, 0x37)


mkdir(&(0x7f0000000040)='./file0\x00', 0x0)
mkdir(&(0x7f0000000100)='./file0/file1\x00', 0x0)
unveil(&(0x7f0000000180)='./file0/file1\x00', &(0x7f00000001c0)='x\x00')
unveil(&(0x7f0000000140)='.\x00', &(0x7f00000002c0)='r\x00')
unveil(&(0x7f0000000300)='./file0\x00', &(0x7f0000000380)='x\x00')
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000140)=[{0x5}, {0x80}, {0x416}]})
syz_emit_ethernet(0x4e, &(0x7f0000000140)=ANY=[])


msgget$private(0x0, 0x0)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
setreuid(0x0, 0xee01)
r0 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmctl$IPC_SET(r0, 0x1, &(0x7f0000000000)={{0x0, 0x0, 0x0, 0x0, 0x140}, 0x0, 0x0, 0x0, 0xffffffffffffffff})
shmat(r0, &(0x7f0000001000/0x3000)=nil, 0x3000)
madvise(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x6)


open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
open(0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000401})
open(&(0x7f00000000c0)='./file0\x00', 0x20, 0x0)
open(&(0x7f0000000400)='./file0\x00', 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000140)=[{0x4d}, {0x34, 0x0, 0xb8, 0x1f}, {0xce, 0x1}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000380)}], 0x1)
mknod(0x0, 0x0, 0x0)
r0 = open(&(0x7f0000000280)='./bus\x00', 0x0, 0x0)
syz_emit_ethernet(0x3a, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x2c}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, {[@sack_perm={0x4, 0x2}, @sack={0x5, 0x2}]}}}}}}})
syz_emit_ethernet(0x4de, &(0x7f0000000000)=ANY=[@ANYBLOB="aaaaaaaaaaaa9cd7361987d486dd60ecea6604a80000fe8000000000000089750e6b000000aaff020000000000000000000000000001"])
ioctl$FIOASYNC(0xffffffffffffffff, 0x80047460, 0x0)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x0, "0d0e5012c3842ffcc300"})


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
r1 = socket(0x2, 0x1, 0x0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
r3 = socket(0x1, 0x1, 0x0)
accept$unix(r3, 0x0, 0x0)


semget$private(0x0, 0x1, 0x220)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000004c0)=[{0x2c}, {0x3d}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])
pipe(&(0x7f0000000000)={<r1=>0xffffffffffffffff})
poll(&(0x7f0000000080)=[{r1}], 0x1, 0x101)
execve(0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000100)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
select(0x40, &(0x7f0000000280)={0x10374}, 0x0, 0x0, 0x0)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f00000000c0)={0x0, 0x0, 0x8a38, 0x0, "ffff09009cef01098b748200"})
writev(r0, &(0x7f0000001380)=[{&(0x7f0000000040)='c', 0x1}], 0x1)
r2 = dup2(r1, r0)
ioctl$TIOCSETA(r2, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x7ff, "2cf9892af9a590e4cb52e88608007673ca9e5fd7"})


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
msgget$private(0x0, 0x88)
getrlimit(0x8, &(0x7f0000000040))
chmod(&(0x7f0000000180)='./file0\x00', 0x0)
r0 = openat$vnd(0xffffffffffffff9c, 0x0, 0x100, 0x0)
r1 = kqueue()
getdents(0xffffffffffffffff, 0x0, 0x0)
kevent(r1, &(0x7f0000000200)=[{{r0}, 0xfffffffffffffffc}], 0x8001, &(0x7f00000001c0), 0x400, 0x0)
r2 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000100), 0x400, 0x0)
setreuid(0xee00, 0x0)
r3 = getuid()
setreuid(0xee00, r3)
ioctl$WSKBDIO_SETDEFAULTKEYREPEAT(r2, 0x800c5709, 0x0)
r4 = openat$zero(0xffffffffffffff9c, 0x0, 0x41, 0x0)
fcntl$lock(r4, 0x9, &(0x7f00000001c0)={0x2, 0x1, 0xfffffffffffffffe, 0x1000100000000})
ioctl$TIOCSETA(r4, 0x802c7414, 0x0)
fchdir(r2)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
semget(0x1, 0x2, 0x389)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
sysctl$vm_swapencrypt(&(0x7f0000000000)={0x2, 0x5, 0x2}, 0x3, &(0x7f0000000380)="f9332a8065153d62eee22f72a6e579c872efe2bf2ff1efedb88ac4d8312a86340df6b706a5cc9746cdea8e010da87e2cc0f66c07a6456619cd4286b0271ab4de1a7a06a00794c4fde755cc14306bfd61ec5d22aa143e0485c04f946f3a0573862fc050662f8e9aa342fd58d99de6c2d999046e13aaac016e72fc0e48777dbbe3985f05b24df7a09f3fe35ab6634a14f810cae4bb08885c7e80b5432e6647892cb7aa5c76cab8c6836d437515b8d78348cefedbd070d531a95e8687f00e3a9645a8a920189f4f116827c3eff83d8d8243256eb631838f93acb83f5c16574981479229e1882ce95f013f11b8ad489c4ded377d72e8442bc58ae3055d4865c4214897ade41c606cd74526c67dbbb4b2acf37b369cf27a72da422ab28e6bf84a30bacdc79fccc900372cfc6cf4719c8fb5fe2771a7e798a3d47fa51be4f814612a09036799cc8180348a339a57afc6f8b99a046cd4de20bd1a9a410f2b89c81d7dad2855908b3cf6a5f1c348011ce7e846c9a6043b2fc36eaa8568517eef4afcf3c9e2b9c25b25791bd2c298275c95e9b780bb3febf11fb66b6443ff47fb0879748c0e1d8a256865e19863c9191655bae481d96fce4815933ff9b03309896495d4dd62a8d6c97267a9db48e4bdc810e4d588a85620e1ce02c783219e9ed804f4cadebb37a921fb668afa4f1af31943a52ebd1abef496f23232f4423ed6e670295b9abad96fa1b1f05ca76bed339e16f676d232ce64be74a7068d81dd12c85a2972dc5e5f0ff28c355f60ef0f17bb23f06e72a31774eeaee68f346ab5c548b8cf47c5ebfa9e4f87bd8ced1fd1e4911263d6675e1d0cd2d71d32d293c2930f101c72b2cd2eec39f35e1f097d7181d26e42e5f09d0b14c07c2ce35d7c872033466e1d53bf5d0be0fb5ab4776ff6528b97c928b3bf4ec068a08b92e91448494f7749c8d2fbc1e0f386e3b352ba1014776705da60e930c89e636ceaa2e8f839541bc941134229d6fdd6af3681f7080ca770266e6ee1d1bb807673d51cd8562d3546ccc86ee8ad096ed86ea207677c54022218ecdaa8a0f2b2a957e50aaf92485960cdd1e5687634bf4fb8b69f37b8538ebdf372299895a9df76e29abb2ef2de42d8ac3c1f7b52e7040d860f2e5170d65056dd6d974a149193811fe217a04b266f04a538009c859fa0d80ee7cf4622630ee506bc7e425de3e27b4d4770f37d1a4a5634ab6d14433a6d3eae625898107e48c2bd10eee8692167abcea04abb0bdc7a1d9ffcb2b73cd7dec0b458e0ca71f8bdc3fc6c44c56744a384d0da599354ef67edc2d22c1b591a42e9d516c6846bf8104830e4cc3ecf9f00b0a07ef561e699dd95e4b303b57abb0595085eadeaea15213d6292e7187e59996b80359ed376f857a464ef5027a32ce0f9924698b400b2c21efe4d83aed49e282544d2e606ae785c7c96a5fbf832c55b188bf048d4c9a99e14444faa5536bf4a528eb266d24141b72491d1d5d16e5f1c4720bee29febbbef27ad35e4769c33b506d50931ccef48da4420bb29cff4358cf90c19313193656a14326252bf911b91d30a032a0d1d08d33740a07757b1fe94d2d7f5b25d271b3041cd06de3c7901af14443ce336aad9d972349a6e4df85cad9c0a2e905ad3c6006a8b11a0ca2b2b86c450e8c3968fbab18c0ac1583f64b7cc6010bdfa2b78e602cbc329304a272bf15f1ba8a988177b092cbae2b1fa2b09935fd0a9fb66e3b8081f7ad5500eca3a38317966db350b1d5c8f5ab65245235f55f41ff8a49526029021cc18af9ee80ccd6b8c7c5be0fe502a0ce7d048458ec7240cd8968cf61b26df6257f78f2bc0d129c7032dd9410d1ec468555792d42b3496fa8910a96fdfe9b2de92ffb2a68deed5901c3c9639cc2001bbef1c1d927f0b0c24a9dc71ae21f26bf331fa64c9c2a6dfe4de16c9c47aecc537e618cbc9f4506b4a8aaa3be261abc6c7a969380c019175766d9223a53b69f3dc7dec8230237d0e3524728d530cfb2fb6dfcce483de8bdecc7e22cfdb8042caa5a28cad2569cc0394ac202fe6f99e9fb7498804b622463219a880b17745c23c3677313e7484956a9fc27441ba07603dc73ca8cb1b1b92b562ff1b6507435dd5a71c2d8c8de6a8faec8a5a304c2ec8e058fc9f7cb98ac6e325cf798bf9858eef52f3f93309b92bf5a3825200c6d90e985af0b40e18e58f78c58bcef8728ff8bbc4155aac09e7c6663226b118c3562f5b26fa3d6f102ec59f162f27e31f67378d16cee32756d26de868d6b4f197ec8f3fff0872caf231a73050f78fe21f267e6e01982cf3978e1dbf6ad527ea936e19010987916e01883ea3f9fcf17d7c2418cf57987e3ba66b1dd8953450320e602a90a11162631e64d984e43f563f7d9ce73f5071089bd8b86b85eae6b0536240ea57fd08f54b3e41fba00e97d62d4ceecdd5df58c0e0b5b4b619090f5bded89376030a3d556db77534aaaedca5abec93e0d27261abf6c377c92fc0918f7639ce44c861b8bcf7b8b86c6c4bd54ef0c006df55eb1a54dee0705627f3e3c9a404df8759b37c24445b34ab8a114b2bdb1742e33a523da2ae3a2278ee496f8735dc2b971735996569774420f8e09801e623e1b2bfb5dd4c83937083babf0fd4bd0a21f8585a2e7e821062a0d975e43195f0e7169b27cf51b858b956b409e78485fd4605e0c5f92758b468b8e5c297ae69f8b23281576119659a351e392c0aa6605c65d6f762574b25c89541aef4d2cb89fe2f61e680bd2ff4e22970fd2dc0b004606f07da714ad5d25e7f984f6400b075ce4f06223d16d3be408fac462ab8d3b88ef8b5957f4990cde1472a2d869c32001a42865281f7bf8691358469ce2169f9b7e7c296b23e452ed54f5695ade2606bf67b98e96bed66e16184bc01186b0434ea5ea6979f741e0a0026a270cf749541eac61bbed1e4ba98c9f09e4b4c868ce5e27880aa77fb09becaccd7dbed64d58e793a003e346325f24f1f3f0c823ac84d15ecc20bbb5459060d5953a98a399bcd4398114b4c5461873c3b58435bc7e5f86ffe7f718bdbde699de7321b3fd7e0f715f602caf520a631407acfea0b74b071bf280d597c95d12a9460d5356854eec6c894f2edc5467fa1f8367eaa84a9c462758d6f61eef38821258a5ac1f5bda3cf2adede09739e3e6c617b3f02248ceb44e3e75010a9ce84d5467f32a6431c354fdda7c80c2dfd853739ff1fbf61d6ce416145d22864e35adeeb6ab968a82460e6959f261208bada1ee740d4407c5e36c2ace1d396f26039a5235d25ca99ef995123b73386ef5f54d4bfb73fac7f2b536dd460ca26fb2752720dfd9a4d27f2317879c24af20b23f2cd3694fb976c7dda0e5cbd0261f7f05adeabbc8c8ae1d12a8954f541ad26103339776481478d54de9fadcbf1c4c77198bcbce7c56a8f87a3fd3b5239d2af2e8a188c16d57b8bc60dbc22ac0e38635b8a1d756072af820c5bd35372e7c336c818649a181a95453d11f8e8c0ec4d1b43c98f049810f38fb63fb44a8b2996303fabe0db7b3e63a87943a11630bea4029bf6f2d51961029ad3f5e4f61669a871c3341e0b65b85eb0ea7c92b5b39e2a6479234ecd7bad14922d60cd71c32b53e694d83c085b68e7295828c0569d79985dde8c389e7f9039412dd40412b20310acc61e7935cfa350836ca82849d84cb3cf802d361be9e4c649b22c6daf5bb34c1dbbade3a79267696f90ece95f3c59fc315151c71c8c2aa979cce8d18af5a76d4f5ed2bb6367bda5f5e60515e7fa8ce022451b346019d551bc2295c866c889c3a9820a61ad5b3312f11b6d8575bbfdb0ceb8ec54e463f1c3e0605486f622eb429b894ed93cb46cf5ea4b5a70c0157ea21890cf26beeec1a4cee00a5590f90b39a17dca05ca5cdc6cbb74afaeb3cafdb5710ea948c80e977d3b8870589718fab4c4a8cc376ca5036c764a45b50c0370e53d43edc87ee09a20b29eb04526a8a16371e31a1b854c2532be568fd55be0241a466eb5fdc7621c5da5cc28539f34a6ec369b4aedb4de82b5c52c71b7ec62c2addf309b65f86775e76cb8bb85cf11e57ab155b866363ba9469d18f38db28283182f7799984e61fa0f8dcf778288864f61b70b703908f1cca608b08f94b35d8b9ace8804f518883156948f3728cc1b807c40771adbeca0c6557c0f906a2930ef85eafcf4185f48a85a052294e648bfae08d4c08522e8e0fb5e40bb6fb144f984e333f567f995c93f4ec615d4ae6501c2a5b34bca468a3f354ff9ac80b72082bed3aa393a86ed90c76bf45e72ea01ec9cace3fb27355e9d8a224348449305a5505e104ec54297de548679d11e9827f3c7a7ae55a787e09975df5dc497990613f5bda73a731fb3953fb5e9fd0bda6184775559f14e917905c5c5d7e86e3e845ed8a8882d8e200715e01d88ba1167ce550b3470134fa6cab0c626d1e94b71396e3c4af3d4a385e2e44f3b73fde66451ded569ac08b4a1f4b6482367b690cd1f021ead3f44440fb8992a0dd3dcb5a147b76e3860ed0239c5bcd8b4c23cb7810119ce50fd6ead36c5d0661007a87c3fc5dc7c0c4098e09baac6b117ebf10cf423a1bcdf5a2587a2ae128a742a288df9a6eb67d34105b1ca61536e3535cc2abba9f2e2e4ebce7f2a606091f1718e75e680a9456855b49be8e120a2b88761e4e7a6fe9d6a64d0500c9950606b8398cf3bb6f0e8ece75f2802f604d43fd2d342deada696df377d7b6575a23e44c068192793124c963a71403d7b9002fb2a99acbea45e3ae864033a169f1183014d484005577f139d515464fac50a815667ce6f1d6b3e3b48775ddcce8765d179c5822e7119dad2ad2d0eef29d208170d9203d2424476f81cd762067b041114edf0900a2f02c5ef54498a31f9ed3b4eef3a4594a1040a644d69fc52fba13aa4456d7ec28692e6937fa6b5d5e4716e170328fb362fc249f4ac83d9312efca4d63fe76273957a720373ebcb5e90937bb99325babd40563285355c45fbca5393a902c46df4f7d72a6f235b05a96bca27b50e0002f99e17702f306449ccfb308a7ba8db1b482ca75507712beaf239ed94aea126f24a14343ad41be14f58becb35529a54a682a7e0704c4a2b01c306a5abf237f041203aaa51e5f7d075f82dcd42fbf65a9c84aeab400b1de48b3998b42933c74a92db46aba7dd23eb1796fbd91a91fb288666971132e5e99e1fe5bd67fd452f3e5c1b34850f9779e8a12ea3be12bd000b9ddd34c6bccb520d26f37f81cad6ebd65ece8e8eda6e7782d7aa380ecd58d7a94cac62f70f3ed560b8a21dab6761762eb8f0fbf5ce3087534a3bb7c8c0aa8a000f5f880d98b2a1b4387b26e545c83ef677309397991f43b730da1729bd898d70da5c05f7c46ae6225e7ec0872b476c3f7beef610a57b6c91093b6e3c3037bdb67c42be7b937c6fc845e577c1e1a2669ae7106bce63356197b38ca14c7709d9cab4ebf0ff9b0e15209319ba113a6a88667f622c9ac3553718ab2c2367379c64c66627a1e4f0ba3bac6c5dda4e70fb82573e832aac48ab70ed3597d2e91594b75f19cd91379393c582131a8dffad5963ce6a65143ea8121d6619855b60a54106975884ae47d2a6d2eb28dea933c00de799b85c829301a42f56483c939104cb24331663250da178c0cce6d170439024c0a5196a17a13258b6323d872a837de126f85d2a09d5c77c5e9643730dbfdfce3d8ed351a4fe05b48a03bbb47f37fa33b8ce00a7335886ee68cde929c85277adc4d2047c600f5c12d3e2755920fb2c71b5eb020280dca424212266edac", &(0x7f0000000040)=0x1000, &(0x7f0000000080)="b8edac04076f400049fa74e21b972189c90d7c8bddd1d7212cf543201d060b2e9387f5422385d06a5b1c5e6d4dbb3c2ff55b763a5609e7b13cc217f64a1c459d66bf043f1113201f8479678e64c918d69ea06a2b80b3b9d65be06f846797b6bb", 0x60)
r1 = socket(0x11, 0x3, 0x0)
bind$unix(r1, &(0x7f0000001380)=@file={0x0, './file0\x00'}, 0xa)
mknodat(0xffffffffffffff9c, &(0x7f00000000c0)='./file0\x00', 0x2000, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x4, &(0x7f00000003c0)=[{0x2}, {}, {}, {0x1, 0x2, 0x1, 0x3f8000}]})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000007, 0x0, 0x0, 0x0, 0x0)
r2 = socket$inet(0x2, 0x2, 0x0)
getsockopt(r2, 0x0, 0x9, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
r3 = openat$zero(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
fchownat(r3, &(0x7f0000000040)='./file0\x00', 0x0, 0x0, 0x6)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
r4 = socket(0x2, 0x1, 0x0)
execve(0x0, 0x0, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x8, &(0x7f0000000200)=0x6, 0x4)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r5, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000100)=[{0x45}, {0x5}, {0x6}]})
sysctl$vm_swapencrypt(&(0x7f0000000000)={0x6, 0xb, 0x2}, 0x5, &(0x7f0000000500), 0x0, 0x0, 0x0)


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000180)={0x2, &(0x7f0000000240)=[{}, {0x1}]})
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
setsockopt$inet_opts(r0, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0xc)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000002c0), 0x1, 0x0)
writev(r0, &(0x7f00000003c0)=[{&(0x7f0000000400)="cf440b874f6c27a05baa06a3b936442edc", 0x11}], 0x1)
execve(0x0, 0x0, 0x0)


setrlimit(0x0, &(0x7f0000000980)={0x0, 0x54})
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x412dff)
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, &(0x7f0000000440)={0x0, 0x1000, 0x0})
r0 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
preadv(r0, &(0x7f0000000300)=[{&(0x7f00000000c0)=""/104}, {&(0x7f0000000140)=""/192}, {&(0x7f0000000340)=""/175}, {&(0x7f0000000000)=""/18}], 0x10000000000002b8, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000001180)=[{0x7}, {0x7}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f00000000c0)=ANY=[])


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000100)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
r2 = dup2(r1, r0)
poll(&(0x7f0000000080)=[{r2}], 0x1, 0x0)
poll(&(0x7f00000000c0)=[{r0}], 0x1, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x0, 0x2}]})
r0 = socket(0x18, 0x2, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0xfffffffffffffffe}], 0x0, 0x0, 0x0, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x81, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
close(r0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
syz_emit_ethernet(0x3e, &(0x7f00000009c0)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa86dd60cb706503003b0035b282d55c8b0488fa1f01eb6b0de395ff020000000000000000000000000001"])


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000004c0), 0x2, 0x0)
writev(r0, &(0x7f00000006c0)=[{&(0x7f00000009c0)="a3e77fdb7f7280d33e32f2023dd6fb2381ccf5c1bdb6a7cbb7a877e7a504287dd749a2ca08efa0d9bab347031e3f6dace81c5025f9b5521a6af58e721c64d6a141fcc1ae59b495f993c2509d3f69999dad195c773942bc8e1fe10416b78f4870cff409dcd24d3ed8676e0f8be75ef5fc9b2506f1ce87d5c8c5c159d767d262236a07d4c38593b98c2b4c3e", 0x8b}], 0x1)
execve(0x0, 0x0, 0x0)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
setreuid(0xee00, 0x0)
r0 = getuid()
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000340)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000140)=0xc)
chown(&(0x7f0000000200)='./file0\x00', 0x0, r2)
setreuid(0x0, r0)
chdir(&(0x7f0000000240)='./file0\x00')


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000600), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000000)={&(0x7f0000000040)=[{}, {0x21}], 0x2})


sendto$unix(0xffffffffffffffff, &(0x7f0000000180)="8f0ec34b5999bd6ae65ccd6a4f94b931c46db1676f9d80cc731fc642bbe214939d6417615c308ae214031c74bf3642d76aae725700064dc822d011867ed9b089133e89f9200abee655f4018c59f57bd497223c181fb38e5ba5a6492d538ce6c9e15ae47f7b2585f631774eb70a2bdac1ba257a70ac8bb6616d8caf6e69f7eea7d1e2de33d3a18119089347b286beb4a47925543d7a882be99b7e577095d8a04af02bb955f5ddcafafac51808671d5c877bf03c0ee5ecf788c40ca36468ba5d7ed5af55abef673ef757f86517e67047", 0xcf, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ff3000/0x2000)=nil, 0x41000}, {&(0x7f0000538000/0x2000)=nil, &(0x7f0000ffa000/0x3000)=nil, 0x200000000}, {&(0x7f00001f5000/0x4000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ff3000/0xa000)=nil}, {&(0x7f0000ff2000/0x3000)=nil, &(0x7f0000ff9000/0x3000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f0000ffa000/0x4000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000002000/0x1000)=nil, &(0x7f0000ff9000/0x6000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f000009f000/0x4000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000084000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffa000/0x2000)=nil}, {&(0x7f0000161000/0x4000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000280), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r0, 0xc2585601, &(0x7f0000000000)={0x2, 0x0, 0x1, 0x0, 0x0})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
r2 = dup(r0)
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000140)={0x2, &(0x7f0000000000)=[{0x48}, {0x16}]})
syz_emit_ethernet(0x3e, &(0x7f0000000180)=ANY=[@ANYBLOB="cd"])


open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
r0 = open(&(0x7f0000000bc0)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000080)={0x0, 0x0, 0x100, 0x1000100000000})


pipe(&(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
fcntl$setstatus(r0, 0x4, 0xc0)
r2 = getppid()
fcntl$setown(r0, 0x6, r2)
write(r1, &(0x7f00000002c0)="7c84cf179279b50eda5dd1951a661d2e3a20851082c188f8b3d8a063d2025ff0d27a44bc29bdcac27fcb7aaa95cb2007be22c5553cd2f66a1f419a83d4275218a89d7a7803f069d851ff628dd309c40f6e3c932af00cb6219ae6e21d2c28d492cd5404b16dfa627d93b1e8ad2ea49d2344c1a3b234bd6f1c70fd4252844a6e6ab7b8997bc55fa22ce951ee038d289078b95510b0f2473ce1348434f0ec4a885ee84fd08fc50f08ca7991af3f8c322b496466f804c4b700cc9391855bd0ee339196de2b5ec2d8425c711d3f9e051eb055d45c693d7549712f5284a9fbca7d15c5bf1a9c8e3b3c1a43983056782e046c29e3d57082f7743b8bf6d994cd3c26c85609eaa11e6f7bc4", 0xfffffdaf)
execve(0x0, 0x0, 0x0)


writev(0xffffffffffffffff, &(0x7f00000002c0)=[{&(0x7f0000000000)="6b78fb3e55824866e782e223", 0xc}], 0x1)
writev(0xffffffffffffffff, &(0x7f0000000340)=[{&(0x7f0000000000)="798af17a69acad16912c30", 0xb}], 0x1)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f0000000000))


r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x6, 0x2, &(0x7f0000000380), 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000040)={0x0, 0x7, 0x7, 0x200499, "d88c28fa8797f9bdca0988d15554000900"})
writev(r0, &(0x7f0000000000)=[{&(0x7f0000000380)="7e746376ecb3f4b7c3b9648dde9d8c13de18b9e215c4a9cac7034ab89ebf86868d83590bbbc0d90ba99e59ac2ac3a2812db4a42c910ec132c100ff7f737c911d105ade6f74489113b68abf53fec3be6aeb96d1dd0b41272e9a67087a7fbcf181a77e72520b7622324acd62aee319cf3e29c7534ed4beb03e67ea8902030d8222e539564932f2040000000000003e8baddb5ec102383f95df148f2944152806cfcb731235c9b66b30ab00daec0ec87a189a8d240141070000008de968692f4a942984cd03000000000000000b17e13cd9b51d0900000000000000005dee44094817f0371f5dbed0a1360ec95a7ca9c35fc7a4b4053392eb7600f107f3c4337737a7040ea2322bb3d97fb26b218f86637f46c1f649194828bf85b1b5b3504eb7595c53cace06191b6ef66778617ea9c2500ac0fb51a8acd0a28900775565e90a8948d4e135bfa9443ec80e200809736e36f1d2e6fa70a18a645e191e81307c4247050fa07b160471f7d67efa0573046f92e7fe688a048af645668782b094e610876461dc7435dfb23e4275fabb9d24e24ce323f21527f027c6e818c045ea2a9586fd7105e89570d8c33a8455b1d62781d6563c7a2ad57df0f649ce8bc440e8c26693b45319867472884620e65344b01d2eb8eee502324af03719f08a077ee9d57ceae9510c0158899b4d44322006e94fbc6319aa9ed42caf4a1ead787952832b97057a4611a83d721cc389a134bacfc1253f157052ae6b56dfe53c018d74b21085537a7c00d29411a83460a50b4cd94d26542a626f87eceac528b523c3cf047b70b6699c456b9a4d90a2f3b0968809", 0x24e}], 0x1)


r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$PCIOCWRITE(r0, 0xc00c7007, &(0x7f0000000000)={{}, 0x1})
r1 = openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$PCIOCREAD(r1, 0xc00c7007, &(0x7f0000000100))
sysctl$net_inet_ip(&(0x7f00000005c0)={0x4, 0x2, 0x0, 0x10}, 0x4, &(0x7f0000000600)="e09c0f90", &(0x7f00000006c0)=0x4, 0x0, 0x0)
mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)


r0 = socket(0x11, 0x3, 0x0)
r1 = fcntl$dupfd(r0, 0x0, r0)
sendto$unix(r1, &(0x7f0000000200)="b1000503000004000000000007000000331c13fecea10500fef96ec0c72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa05000000512f4d335c223e02000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b1257aea8c500002002fbfe0c2300008abfba0900000008e371a3f8343712051eeab71d89e00004070000000013000000000000000000000000000000007c24baff36c89ea4e8dcccdc07b4b0369de8daf9ba735004fb54729a7776e033decbff9e81c456937b3dafd21f23e411c4707e55c4c38cfcb48db4874d7cd82f6baa0ae9d25a7f26948eb936bd3bec5600"/257, 0xb1, 0x404, 0x0, 0x10)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
r2 = dup(r1)
recvmmsg(r2, &(0x7f0000000440)={&(0x7f00000000c0)={0x0, 0x0, &(0x7f00000006c0)=[{0x0}, {0x0}, {0x0}, {&(0x7f0000000340)=""/87, 0x57}], 0x4, 0x0}}, 0x10, 0x64, 0x0)
r3 = dup2(r0, r1)
writev(r1, &(0x7f0000000080)=[{&(0x7f00000003c0)="ae", 0x1}], 0x1)
shutdown(r2, 0x2)
dup2(r3, r2)
execve(0x0, 0x0, 0x0)


shmget(0x1, 0x2000, 0x600, &(0x7f0000ffe000/0x2000)=nil)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000002c0)={0x3, &(0x7f0000000080)=[{0x81}, {0x54}, {0x16}]})
write(r0, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xfef3)


openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r0 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
clock_getres(0x4, &(0x7f0000000080))
connect$unix(r0, &(0x7f0000000000), 0x10)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x1, 0x0, 0x0)
syz_open_pts()
write(r0, &(0x7f0000000240)="14bdfa5d1d34e2fecb284a6498307dcda9aec43050036123339a346f737850551408753f95b7688ad4c4e1dd5489e7bafc58d3e5823757ae8b630719ef187ccad995f13dbe19a6dd4e6902bd8297b0799b426aabe9fad9db6996571c6d9f8bb5d542c2148aa42be940970fe88d34d8f99afe7e7820237400000000008000000100"/138, 0xfc7e)
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f00000000c0)="b10005136000009f0000000000070000001c130500000000fef96ecfc72fd3357ae380b37b673039d2d236acf60b7804be78164991f7c8cf5f882b297be1aa5b23edeb51e2f0ac3ebbc215000000eeffffff028ea8af630037282102000000720fd38bfbb770c1f572c881ea772ec592040000000000ff0c2300008abfba0900000008e371a3f8343712051eeab71d89e0442c5e52000080042000"/177, 0xb1, 0x0, 0x0, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x32}, 0x2, &(0x7f0000000100)="71f91e34", &(0x7f0000000080)=0x4, 0x0, 0x0)
mknod(&(0x7f0000000300)='./file0\x00', 0x2000, 0x6da)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
sendmsg$unix(r0, 0x0, 0x0)
openat(0xffffffffffffff9c, 0x0, 0x0, 0x0)
setreuid(0xee00, 0x0)
openat(0xffffffffffffffff, 0x0, 0x0, 0x0)
r1 = getuid()
ioctl$KDSETLED(0xffffffffffffffff, 0x20004b42, &(0x7f0000000140)=0x7)
setreuid(0xee00, r1)
r2 = socket(0x2, 0x2, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
getsockname$inet(0xffffffffffffffff, 0x0, &(0x7f0000000000))
syz_emit_ethernet(0x36, &(0x7f0000000000)=ANY=[@ANYBLOB="ffffffffffffffff"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
bind(r2, &(0x7f0000000000), 0x10)


syz_open_pts()
setrlimit(0x8, &(0x7f0000000980)={0x7})
syz_open_pts()
r0 = accept$inet(0xffffffffffffffff, 0x0, &(0x7f0000000180))
setsockopt$sock_int(r0, 0xffff, 0x1, &(0x7f0000000300)=0x1, 0x4)
setreuid(0xee00, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x53}, 0x2, &(0x7f0000000100), 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x800, 0x0)
open(0x0, 0x0, 0x0)
ktrace(0x0, 0x0, 0x0, 0x0)
mmap(&(0x7f0000ffa000/0x4000)=nil, 0xfffffffffffffffb, 0x0, 0x10, 0xffffffffffffffff, 0x0)
madvise(&(0x7f00001c8000/0x4000)=nil, 0x4000, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
msgget(0x1, 0x380)


mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f00000000c0)={&(0x7f0000000000)='./file0\x00', 0x4, 0x0})
rename(&(0x7f0000000280)='./file0\x00', &(0x7f00000002c0)='./file1\x00')
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
execve(0x0, 0x0, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x1, 0x0)
close(r1)
r2 = socket(0x18, 0x2, 0x0)
setsockopt(r2, 0x1000000000029, 0x3f, &(0x7f0000000040)="00fb6c4f", 0x4)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r1, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{0x1c}, {0x1d}, {0x16}]})
syz_emit_ethernet(0x6e, &(0x7f00000001c0)=ANY=[])


r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSKBDIO_GETBACKLIGHT(r0, 0x40045700, 0x0)


syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x3, 0x0)
bind(r0, &(0x7f0000000000)=@un=@file={0x0, '\x00'}, 0x3)


setitimer(0x0, &(0x7f0000000000)={{0x7, 0x1}, {0x8, 0x200}}, &(0x7f0000000040))
sysctl$net_inet_gre(&(0x7f0000000000)={0x4, 0x2, 0x2f, 0x1}, 0x4, 0x0, 0x0, 0x0, 0x0)
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r0, 0xc2585601, &(0x7f0000000040)={0x10, 0x0, [{&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ff7000/0x9000)=nil, 0x10000}, {&(0x7f0000ff8000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil, 0x3}, {&(0x7f0000ff7000/0x4000)=nil, &(0x7f0000ff7000/0x2000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ff8000/0x2000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff8000/0x4000)=nil, &(0x7f0000c00000/0x400000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000c74000/0x4000)=nil}, {&(0x7f0000ee7000/0x4000)=nil, &(0x7f0000eda000/0x2000)=nil}, {&(0x7f0000f0a000/0x2000)=nil, &(0x7f0000d2d000/0x3000)=nil}, {&(0x7f0000d50000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000d82000/0x2000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000dbe000/0x2000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000e40000/0x1000)=nil}, {&(0x7f0000dbd000/0x4000)=nil, &(0x7f0000c2e000/0x3000)=nil}, {&(0x7f0000ff5000/0x8000)=nil, &(0x7f0000dae000/0x4000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000c19000/0x3000)=nil}], './file0\x00'})
sysctl$net_inet_tcp(&(0x7f0000000440)={0x6, 0x18}, 0x4, &(0x7f0000000480), 0x0, 0x0, 0x0)
socket$inet(0x2, 0x2, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
r2 = kqueue()
dup2(r1, r2)
sysctl$net_inet_gre(&(0x7f00000000c0)={0x4, 0x2, 0x2f, 0x3}, 0x4, &(0x7f0000000100)="80815d97e5e9ec42557fbfa1b208d658d9983f117a859fd619a67026beff80585ebedf283df04854cf98e456c11215a266b3c48e70351ef02e", &(0x7f0000000140)=0x39, &(0x7f00000002c0)="3d5c4fb3856c4746eb2eb0", 0xb)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000002a40)={&(0x7f0000000000), 0x10, 0x0}, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000695000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f00005fd000/0x1000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ff7000/0x3000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000545000/0x1000)=nil}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000069d000/0x4000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ff8000/0x4000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f00002f6000/0x3000)=nil, &(0x7f0000ff3000/0x2000)=nil, 0x3}], './file0\x00'})
r3 = socket(0x2, 0x2, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000180)=[{&(0x7f0000000000)="9da8e3e9ed", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r4 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
dup2(r4, r3)
sendmsg$unix(r3, &(0x7f0000002a40)={0x0, 0xffffffffffffff89, 0x0, 0x6e, 0x0, 0x700000000000000}, 0x0)
sendmsg$unix(r3, &(0x7f0000002a40)={0x0, 0x0, 0x0, 0x40}, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
getrlimit(0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)


mknod(&(0x7f00000000c0)='./file0\x00', 0x2000, 0x0)
r0 = open(&(0x7f00000002c0)='./file0\x00', 0x0, 0x0)
ioctl$TIOCMSET(r0, 0x8004746d, &(0x7f0000000000))


socket(0x0, 0x3, 0x0)
open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
dup(0xffffffffffffffff)
r0 = socket$inet(0x2, 0x8003, 0x0)
setsockopt(r0, 0x0, 0x7, &(0x7f0000000340)="15337ac0", 0x4)
syz_emit_ethernet(0x2a, &(0x7f00000002c0)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, @multicast2}, @icmp=@echo}}}})


syz_emit_ethernet(0x416, &(0x7f0000000300)=ANY=[@ANYBLOB="c7e052ea36fbffffffffffff86dd60826e0303e0000500000000000000000e14fc11cd3f6420ff020000000000000000000000000001890090"])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x15}, {0x80}, {0x4000006, 0x0, 0x0, 0x7f}]})
write(r0, &(0x7f00000002c0)="c5449bc1708e16b9805a099e20a0", 0xe)


getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x36)
getpgid(0xffffffffffffffff)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000200)={0x0, 0x7fffffff, 0xfffffff8, 0x0, "09000000ffffffff080400"})
writev(r1, &(0x7f00000009c0)=[{&(0x7f0000000540)="cb57592b74376d685a62fd536a9991923156b767bf2561610f208517f035187a587887ed21c82f1e465e306d231b7098dd1b86b62aa6fe5a5d949ff1df78f2628fde8ce891b831af635a8660e9a509a19e32cc272b4d94c483296d3a8095", 0x5e}], 0x1)
writev(r0, &(0x7f0000000740)=[{&(0x7f0000000040)="dd", 0x1}], 0x1)
syz_open_pts()


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$SPKRTONE(r0, 0x80085301, &(0x7f0000000080))


r0 = getpgid(0x0)
setpgid(r0, 0x0)


r0 = socket(0x18, 0x2, 0x0)
r1 = dup(r0)
setsockopt(r1, 0x1000000000029, 0xb, &(0x7f0000000080), 0x4)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000000), 0x0)


syz_emit_ethernet(0x42, &(0x7f0000000640)={@broadcast, @empty, [], {@ipv4={0x800, {{0x8, 0x4, 0x0, 0x0, 0x34, 0x0, 0x0, 0x0, 0x0, 0x0, @local={0xac, 0x14, 0x0}, @local={0xac, 0x14, 0x0}, {[@timestamp={0x44, 0xc, 0xa0, 0x0, 0x0, [{[@rand_addr]}]}]}}, @icmp=@timestamp}}}})


r0 = kqueue()
kevent(r0, 0x0, 0x0, 0x0, 0x8, 0x0)
execve(0x0, 0x0, 0x0)


r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
setreuid(0x0, 0xee01)
ioctl$WSKBDIO_SETDEFAULTBELL(r0, 0x80105705, &(0x7f0000000080))


r0 = kqueue()
r1 = syz_open_pts()
kevent(r0, &(0x7f0000000640)=[{{r1}, 0xffffffffffffffff, 0x71}], 0x8008, 0x0, 0x0, 0x0)
syz_open_pts()
syz_open_pts()
kevent(r0, 0x0, 0x0, &(0x7f0000000280), 0x6c, 0x0)


getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000040)={<r0=>0x0, <r1=>0x0, <r2=>0x0}, 0xc)
ktrace(&(0x7f0000000000)='./file0\x00', 0x2, 0x40000020, r0)
socketpair(0x6, 0x2, 0xfe, &(0x7f0000000080)={<r3=>0xffffffffffffffff})
shutdown(r3, 0x0)
setsockopt$sock_cred(r3, 0xffff, 0x1022, &(0x7f00000000c0)={r0, r1, r2}, 0xc)
r4 = open$dir(&(0x7f0000000100)='./file0\x00', 0x8000, 0x180)
mknodat(r4, &(0x7f0000000140)='./file1\x00', 0x2000, 0x1)
recvfrom$unix(r3, &(0x7f0000000180)=""/234, 0xea, 0x3040, &(0x7f0000000280)=@abs={0x0, 0x0, 0x1}, 0x8)
r5 = accept$inet6(r3, 0x0, &(0x7f00000002c0))
r6 = getpgid(r0)
fcntl$lock(r5, 0x8, &(0x7f0000000300)={0x3, 0x0, 0xffffffffffffffff, 0xfffffffffffffffd, r6})
socket(0x21, 0x4000, 0x40)
r7 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000340), 0xc0, 0x0)
ioctl$WSKBDIO_GETBELL(r7, 0x40105704, &(0x7f00000003c0))


syz_emit_ethernet(0x49, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x3b}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, {[@sack_perm={0x4, 0x2}, @sack={0x5, 0x2}]}}, {"d1c2f0bfe2d0786ca28e44289f59ab"}}}}}})
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106978, &(0x7f0000000040))


open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0xb29bd8c4a9e09185)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
writev(r0, &(0x7f0000000280)=[{&(0x7f0000000000)='#!', 0x2}], 0x1)
writev(r0, &(0x7f0000000080)=[{&(0x7f0000002540)="19af1c0c1e5eb664227eebc46add329414c4d8e18e2b0884bed6b78e0b1ef6c5df9323bc41e735352e310cada713bb31d5975394e7e1d5eae70b6d1e71ef0748fd597d6a55491b43fd42de12090a", 0x4e}], 0x1)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


mknod$loop(&(0x7f0000000000)='./file0\x00', 0x2000, 0x1)
link(0x0, 0x0)
rename(0x0, 0x0)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000140)='r\x00')
rename(&(0x7f00000007c0)='./file0\x00', 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f00000000c0)=[{0x1}, {0x0, 0x0, 0x0, 0x8001}, {0x406}]})
syz_emit_ethernet(0x36, &(0x7f0000000400)=ANY=[])
minherit(&(0x7f0000ffc000/0x4000)=nil, 0x4000, 0x0)
r1 = socket(0x18, 0x2, 0x0)
msgctl$IPC_STAT(0x0, 0x2, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x1, 0x0, 0x83fe, 0x4000000})
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000100), 0x200, 0x0)
fcntl$setstatus(r2, 0x4, 0x0)
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f0000000380)={0x1, &(0x7f0000000340)=[{0x0, 0x0, 0x4}]})
socket(0x11, 0x3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x3}]})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000180), &(0x7f0000000280)=0xc)
socket(0x20, 0x4001, 0x0)
socket(0x18, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0x8020560a, &(0x7f00000002c0)={0x10, 0x0, [{&(0x7f0000ff3000/0x4000)=nil, &(0x7f0000fef000/0x4000)=nil}, {&(0x7f0000165000/0x2000)=nil, &(0x7f00001e6000/0x1000)=nil}, {&(0x7f0000787000/0x4000)=nil, &(0x7f000011c000/0x3000)=nil}, {&(0x7f00005bd000/0x4000)=nil, &(0x7f0000fee000/0x3000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000268000/0x2000)=nil}, {&(0x7f0000328000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000075b000/0x3000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000760000/0x3000)=nil, &(0x7f0000ff2000/0x4000)=nil}, {&(0x7f0000fec000/0x14000)=nil, &(0x7f0000ff9000/0x1000)=nil}, {&(0x7f0000ff9000/0x2000)=nil, &(0x7f0000fef000/0x1000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000729000/0x2000)=nil}, {&(0x7f0000ff5000/0x4000)=nil, &(0x7f0000ff6000/0x1000)=nil}, {&(0x7f0000ff8000/0x2000)=nil, &(0x7f000075c000/0x3000)=nil}, {&(0x7f0000432000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil}], './file0\x00'})
mknodat(0xffffffffffffff9c, &(0x7f0000000280)='./file0\x00', 0x1000, 0x0)
r3 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r4 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
ioctl$DIOCMAP(r4, 0xc0106477, &(0x7f0000000080)={&(0x7f00000002c0)='./file0\x00', r3})
close(0xffffffffffffff9c)
execve(0x0, 0x0, 0x0)
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaaaabb86dd605d34520030000000000000000000000000000000000000000000009f05000400000000000000010100"])
socket$unix(0x1, 0x2, 0x0)


seteuid(0xffffffffffffffff)
open(0x0, 0x0, 0x0)
munmap(&(0x7f0000fec000/0x14000)=nil, 0x14000)
r0 = shmget$private(0x0, 0x4000, 0x7a4, &(0x7f000055b000/0x4000)=nil)
shmat(r0, &(0x7f0000ff5000/0x4000)=nil, 0x0)
shmctl$IPC_RMID(r0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000100)=[{0x2}, {0x24}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000000)=ANY=[])


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f00000000c0)={0x0, 0x0, 0xfffffffe, 0x0, "031ffe40630000000000ff00010400"})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x100000000000000, 0x10000000000001}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x3a)
r2 = dup2(r1, r1)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r1, &(0x7f0000000100)="00003226a4a9000064e7", 0xa)


r0 = open(0x0, 0x0, 0x0)
mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0, 0x10, r0, 0x3)
msync(&(0x7f0000ffa000/0x4000)=nil, 0x4000, 0x6)
bind$unix(0xffffffffffffffff, &(0x7f0000000280)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
connect$unix(0xffffffffffffffff, &(0x7f0000000000)=@file={0x0, './file0\x00'}, 0xa)
sysctl$machdep(&(0x7f0000000080)={0x7, 0xf}, 0x2, 0x0, 0x0, &(0x7f0000001100), 0x2)
socketpair$unix(0x1, 0x6, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
connect$unix(r1, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x51, &(0x7f0000000580)=ANY=[@ANYBLOB="ffffffffffffffffffffffff81002b0008004600003f000000000000907800000000e0000001440400004e204e20", @ANYRES32=0x41424344, @ANYRES32=0x41424344, @ANYBLOB="5000000090780000e21e0c5244389204004c046bea010100003d99"])
syz_emit_ethernet(0x0, 0x0)
semop(0x0, &(0x7f0000000580), 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlink(&(0x7f0000000ac0)='./file0\x00', &(0x7f0000000e40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000f40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000300)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000200)='./file0\x00')
rename(&(0x7f00000007c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000001140)='./file2\x00')
mknod$loop(&(0x7f0000000440)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)


syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaaaabb86dd605d34520030000000000000000000000000000000000000000000009f05000400000000000000010100907800000000603977"])
open$dir(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')


mkdir(&(0x7f0000000500)='./file0\x00', 0x0)
chmod(&(0x7f0000000180)='./file0\x00', 0x23f)
chdir(&(0x7f00000001c0)='./file0\x00')
setuid(0xee01)
r0 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
mkdirat(r0, &(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x18c)
mkdirat(0xffffffffffffff9c, &(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x180)
renameat(0xffffffffffffff9c, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', r0, &(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000a, &(0x7f0000000040)='\x00', 0x1)
r2 = dup(r1)
dup2(r1, r0)
connect$unix(r0, &(0x7f0000000000), 0x10)
sendmsg$unix(r2, &(0x7f0000000240)={0x0, 0x0, 0x0}, 0x0)


sysctl$kern(&(0x7f0000000000)={0x1, 0x32}, 0x2, 0x0, 0x0, 0xffffffffffffffff, 0x4)


mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x412dff)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f0000000000)={&(0x7f00000000c0)='./file0\x00', 0xcd, 0x0})
ioctl$VNDIOCCLR(r0, 0x80384601, &(0x7f0000000980)={0x0, 0x0, 0x0})


open(&(0x7f0000000200)='./file0\x00', 0x70e, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x101}})
getuid()
socket(0x18, 0x1, 0x0)
msgget(0x0, 0x80)
msgget$private(0x0, 0x90)
mknod(0x0, 0x0, 0x0)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x21, 0x0, 0x0)
r1 = accept(0xffffffffffffffff, 0x0, &(0x7f0000000140))
open$dir(&(0x7f0000000300)='./file0\x00', 0x200, 0x7a545d2d1c0a6712)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0xa, 0x0, {0x300000002}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$net_inet_tcp(&(0x7f0000000000), 0x4, 0x0, 0x0, &(0x7f0000000100), 0x1d)
r2 = msgget$private(0x0, 0xfffffffffffffffc)
r3 = openat$zero(0xffffffffffffff9c, &(0x7f0000001500), 0x0, 0x0)
fcntl$lock(r3, 0x9, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x1000000000000, 0xffffffffffffffff})
r4 = openat$zero(0xffffffffffffff9c, &(0x7f0000000540), 0x0, 0x0)
getsockname$unix(r4, 0x0, &(0x7f0000001380)=0x1fa)
msgsnd(0x0, 0x0, 0x17, 0x0)
recvmsg(0xffffffffffffffff, 0x0, 0x0)
msgget$private(0x0, 0x0)
msgsnd(0x0, 0x0, 0x0, 0x0)
msgrcv(0xffffffffffffffff, 0x0, 0xcc, 0x0, 0x0)
msgsnd(0x0, &(0x7f0000000080)=ANY=[@ANYRES64=0x0, @ANYRES8=r2], 0x0, 0xbf6ce03ba1750aab)
msgsnd(r2, &(0x7f0000001180)=ANY=[@ANYBLOB, @ANYRES64=r1, @ANYRES16], 0x1af, 0x0)


r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0xae828e137847f62, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
setrlimit(0x1, &(0x7f0000000000)={0xfffffffffffffffd, 0xffffffffffffffff})
ftruncate(r0, 0x20008002)
r1 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r1)
r2 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x1, 0x0)
r3 = accept$inet(0xffffffffffffff9c, &(0x7f0000000200), &(0x7f0000000240)=0xc)
getsockname$inet(r3, &(0x7f0000000280), &(0x7f00000002c0)=0xc)
pwritev(r2, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x800, 0x0)
kevent(r4, 0x0, 0x0, 0x0, 0x0, 0x0)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x8000000000000000, 0x8000000000000001})
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000003c0)={<r0=>0x0, 0x0, <r1=>0x0}, &(0x7f0000000400)=0xc)
r2 = semget$private(0x0, 0x7, 0x3c0)
semop(r2, &(0x7f0000000700)=[{0x3, 0x4}, {0x2, 0x2ff}, {0x3, 0x8, 0x800}, {0x3, 0x3ff, 0x1800}, {0x0, 0x0, 0x1800}, {0x2, 0x6ff, 0x1400}, {0x1, 0x7ff, 0x1800}], 0x7)
ktrace(&(0x7f0000000340)='./file0\x00', 0x4, 0x0, r0)
semop(0x0, &(0x7f0000000280)=[{0x3, 0x1f}, {0x4, 0x3f}, {0x0, 0x2, 0x800}], 0x3)
semctl$SETALL(r2, 0x0, 0x9, &(0x7f00000002c0)=[0x87fc, 0x9b7])
setreuid(0xee00, 0x0)
r3 = getpgid(r0)
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000001c0)={{0x80, 0x0, 0x0, 0x0, r1, 0x30, 0x2}, 0x800000009, 0x3ff, r3, r3, 0x10001, 0x7, 0x6, 0xbdc0})
semctl$GETALL(r2, 0x0, 0x6, &(0x7f0000000440)=""/248)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000001c0)={0x0, <r4=>0x0, <r5=>0x0}, 0xc)
r6 = getuid()
setreuid(0xee00, r6)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000200)={{0x0, 0x0, 0xffffffffffffffff, r6, r5, 0x2}, 0x7c, 0x0, 0x6})
semctl$IPC_SET(r2, 0x0, 0x1, &(0x7f00000000c0)={{0x10200, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x44, 0xeb}, 0x2, 0xd47, 0x7})
semctl$IPC_SET(r2, 0x0, 0x1, &(0x7f0000000140)={{0x0, 0x0, 0x0, r4, r5}, 0x6, 0x0, 0x4})
semctl$GETALL(r2, 0x0, 0x6, &(0x7f0000000540)=""/240)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={0xffffffffffffffff, <r7=>0xffffffffffffffff})
getsockopt$sock_cred(r7, 0xffff, 0x1022, &(0x7f0000000680)={0x0, 0x0, <r8=>0x0}, &(0x7f0000000380)=0xa)
setegid(r8)
semctl$SETALL(r2, 0x0, 0x9, &(0x7f0000000140))
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000640)={0x0, 0x0, {0x0, 0xffffffffffff0cfb}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r9 = socket(0x18, 0x1, 0x0)
openat$wskbd(0xffffffffffffff9c, &(0x7f0000000080), 0x2, 0x0)
dup2(r9, r9)
setsockopt(r9, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r9, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r9, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


sysctl$kern(&(0x7f0000000040)={0x1, 0x55}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0xfde0, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c89960289bd7a07e488774592496856ca7b78060998608c2f952e43bc0bf11555c94cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a260458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000050000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7177f92cf061ad125ca670353b45d53a000000b3dea22d6027625614b12183721f98686e472b70b560f7021f567adf4d00"/230, 0x4)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x8})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000300)={0x0, 0xfb, 0x7, 0x599, "d8b507040008000000000000000000ddff00"})
writev(r0, &(0x7f0000000080)=[{&(0x7f0000000a80)="f4a9a06f56a19573d9e28dadaca7ecd11be4e40fbe099fcee873695918140b3f20c77d6094d92e4e64c7e395d3bba68c06d837fd0e7b26d2510b9b3fd3358da52aaf8e01a421ca23bf8f8af07f04912b9c1c703abe3fab02bd257dfaa416c6f8f0783a107b3afcf4b5243a5767c20c468cf2ddd1f7d1a8528834d68aea82838c281673f46d169536fd4498f9a01636139d09ea4ef30e15bec8509d137d185c49e34d5b49d397b2591bab1986bdf7925b302f260912254af433a8aeeb5fa99fd25655839875cf39f0266089d159e3fbcfe9e9e99f6d13826988bcdb3891727859f2044d939033f121a8bc850cfcde21c026bfaa3a19e01b352f2b526bd47e895a33de36dd2aaf3409916be1839ca3a018aab3fa7ced425f425bee72939976c8c3dd05b47d62aaf86313f1c8e9941086016393f12c2ac53c6798cc7690c92b69c084e3fab86908", 0x146}], 0x1)


munmap(&(0x7f0000001000/0x2000)=nil, 0x2000)
r0 = shmget$private(0x0, 0x1000, 0x0, &(0x7f0000003000/0x1000)=nil)
r1 = shmat(r0, &(0x7f0000002000/0x2000)=nil, 0x0)
munmap(&(0x7f0000002000/0x1000)=nil, 0x1000)
shmat(r0, &(0x7f0000002000/0x1000)=nil, 0x0)
shmdt(r1)


r0 = syz_open_pts()
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000140)=[{}, {}, {0x6, 0x0, 0x0, 0xffffffff}]})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
r1 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
getdents(r1, &(0x7f0000001180)=""/4096, 0x1000)
getdents(r1, &(0x7f0000000180)=""/4096, 0x1000)
ioctl$TIOCMGET(r0, 0x4004746a, &(0x7f0000002180))
ioctl$WSMOUSEIO_GETPARAMS(0xffffffffffffffff, 0x80105727, &(0x7f0000000140)={&(0x7f0000000040)})
socket(0x2, 0x2, 0x0)
r2 = socket(0x11, 0x3, 0x0)
sendto$unix(r2, &(0x7f0000000140)="b1000501600000000000000007000000330002000000000000f96ecfc72fd3357ae320b37b673039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa5b236de351e2f0ac3ebbc257699a5f139b672f4d335d223e7d026ba8af630037282102000000720fd38bfbb770c1f5a872c881ea6e69e0bb76d907c400000000361b1257aea8c500002002fbff0c2300008abfba0900000008e371a3f8343712051eadb71d89e000040781e4b2feff000000", 0xb1, 0x0, 0x0, 0x0)


r0 = socket(0x18, 0x2, 0x0)
r1 = socket(0x18, 0x2, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = dup2(r0, r1)
setsockopt(r2, 0x1000000029, 0x23, &(0x7f00000000c0)="b211", 0x2)


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000934, r0)
madvise(&(0x7f0000000000/0x1000)=nil, 0x1000, 0x4)
clock_gettime(0x2, &(0x7f0000000280))


sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x20}, 0x4, 0x0, 0x0, &(0x7f0000000100), 0x0)


sysctl$hw(&(0x7f0000000000)={0x6, 0x11}, 0x2, &(0x7f0000000100)="bbff2eba542c0580fa35632749b009ade26bd2094189ebdb4acfdd2cecc44d53d0d82cd69aaed3e5672f35b151", &(0x7f0000000200)=0x2d, &(0x7f0000000240), 0x0)
socket$inet(0x2, 0x2, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x47}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000080)=[{}, {}, {0x8106}]})
ioctl$BIOCSDIRFILT(0xffffffffffffffff, 0x8004427d, 0x0)
syz_emit_ethernet(0x2a, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
syz_open_pts()
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r1 = socket$unix(0x1, 0x2, 0x0)
semget$private(0x0, 0x4, 0x0)
socketpair$unix(0x1, 0x5, 0x0, 0x0)
mprotect(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r2 = msgget$private(0x0, 0x0)
msgrcv(r2, &(0x7f0000000b40), 0xa6, 0x0, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x6000, 0x5200)
fcntl$dupfd(0xffffffffffffffff, 0x0, r1)
msgsnd(r2, &(0x7f0000000340)=ANY=[@ANYBLOB="02"], 0xe1, 0x0)
ioctl$FIOASYNC(0xffffffffffffffff, 0x8004667d, &(0x7f0000000180)=0x2a)
open(&(0x7f00000001c0)='./file1\x00', 0x2, 0x20)
open(0x0, 0x80, 0x40)
writev(0xffffffffffffffff, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
socket(0x18, 0x1, 0x0)
open(&(0x7f0000000100)='./file0\x00', 0x20000, 0x1ae)


kqueue()
ioctl$TIOCSETAW(0xffffffffffffffff, 0x802c7415, 0x0)
syz_open_pts()
r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f00000001c0), 0x1, 0x0)
fcntl$setown(r0, 0x6, 0x0)
ioctl$TIOCDRAIN(r0, 0x2000745e)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000100)={0x1, 0x1, 0x0, 0x3c39, 0x3ff}, 0xc)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000080)=[{}, {}], 0x2})
ioctl$WSMOUSEIO_GETPARAMS(0xffffffffffffffff, 0x80105727, &(0x7f00000000c0)={&(0x7f0000000200)=[{}, {0x26}], 0x2})
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
r1 = open(0x0, 0x615, 0x0)
writev(r1, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
r2 = socket(0x0, 0x0, 0x0)
r3 = socket(0x0, 0x0, 0x0)
r4 = dup2(r2, r3)
sendmsg$unix(r4, 0x0, 0x0)
ioctl$WSMOUSEIO_SRES(0xffffffffffffff9c, 0x80045721, 0x0)
syz_emit_ethernet(0xee, 0x0)


mknod(0x0, 0x0, 0x0)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
sysctl$vm(0x0, 0x0, &(0x7f0000000040)="c06d154be3aee5f8787f8b9cda7554335b763bb5deea5ccecb4d1b57a9f6fa18e47fc7b119db587e58811e666e84a806495b45c36164bd5b135280243ed0a01466056e93082876ba33ee8cf2b0b3907f236f38175101000000d7e39544aea098d19ee63d03cbf92380dbe904538135f09e408bbe17a54a364b04ee64b0ad54e6d4e38114ced38c328aff2e224239ba29eb0796e8c3e8344a2cd9e663bb", 0x0, 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f00000000c0)={&(0x7f0000000000)='./file0\x00', 0x4, 0x0})


r0 = socket(0x11, 0x5, 0x0)
open$dir(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
open$dir(&(0x7f00000000c0)='./file0\x00', 0x2, 0x2)
getsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000300), 0x0)
sysctl$kern(&(0x7f0000000000)={0xa, 0x4b}, 0x2, &(0x7f0000000680), 0x0, 0x0, 0x0)
mknod(&(0x7f0000000040)='./file0\x00', 0x2950, 0x0)
openat$vnd(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, 0x0)
open$dir(&(0x7f0000000080)='.\x00', 0x0, 0x0)
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x200, 0x0)
fcntl$dupfd(r1, 0x3, r0)
sysctl$net_inet6_ip6(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000080), 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
socketpair(0x10, 0x4001, 0x7, &(0x7f0000000380))
openat$bpf(0xffffffffffffff9c, 0x0, 0x10220, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000000)=[{&(0x7f00000009c0)=""/4096}], 0x3e)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000002a40)={&(0x7f0000000000), 0x10, 0x0}, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
r2 = socket(0x2, 0x2, 0x0)
connect$unix(r2, &(0x7f0000000000), 0x10)
sendmsg$unix(r2, &(0x7f0000002a40)={0x0, 0x0, 0x0}, 0x0)


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000280)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000340)=0xc)
mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
r2 = socket$inet(0x2, 0x8003, 0x0)
setsockopt(r2, 0x0, 0x1e, &(0x7f0000000340)="15337ac0", 0x4)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
r3 = socket(0x2, 0x3, 0x0)
setsockopt$sock_int(r3, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r3, &(0x7f0000000000), 0x10)
write(r3, 0x0, 0x0)
chroot(&(0x7f0000000100)='./file0/file0\x00')
r4 = open$dir(&(0x7f0000000080)='\x00', 0x200, 0x40)
mknodat(r4, &(0x7f0000000140)='./file0/file0\x00', 0x1000, 0x7f)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r1}})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4e}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000180)=0x66, 0x0, 0x27)


munmap(&(0x7f0000001000/0x2000)=nil, 0x2000)
r0 = shmget$private(0x0, 0x1000, 0x0, &(0x7f0000003000/0x1000)=nil)
shmat(r0, &(0x7f0000002000/0x1000)=nil, 0x0)
msync(&(0x7f0000002000/0x4000)=nil, 0x4000, 0x1)


setrlimit(0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = dup(r0)
ioctl$BIOCSRTIMEOUT(r0, 0x8010426d, &(0x7f0000000000)={0x0, 0x7})
ioctl$BIOCSBLEN(r1, 0xc0044266, &(0x7f0000000100))
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f00000001c0)={0x0, 0x0})
readv(r1, &(0x7f0000000080)=[{&(0x7f0000000180)=""/15, 0xf}, {&(0x7f0000000040)=""/17, 0x11}], 0x2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000300), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f00000003c0)=[{0x2d}, {0x14}, {0x8106}]})
syz_emit_ethernet(0x3e, &(0x7f00000002c0)=ANY=[])


open$dir(&(0x7f0000000b80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x200, 0x0)
r0 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
r1 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000300)='./file0\x00', r1, &(0x7f0000000c80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mkdirat(r1, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
symlinkat(&(0x7f0000000700)='./file0\x00', r1, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f0000000dc0)='./file0\x00', r0, &(0x7f0000000ec0)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000980)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000a80)='./file0\x00')
unlink(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x0)


openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r0 = socket(0x18, 0x3, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000000)="ebffcbff13fd812eaa4e7130", 0xc)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f0000000000))


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000180))
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)
socket$inet(0x2, 0x2, 0x0)
select(0x40, &(0x7f0000000000), &(0x7f0000000040)={0x7ff}, 0x0, 0x0)


openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r0 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000440)={0x101, 0x0, 0x0, 0x0, "01000000000000000100"})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r0, &(0x7f0000000000), 0x10)
setsockopt$inet_opts(r0, 0x0, 0x1, &(0x7f0000000440)="9876d692a3ef9c7ab923a2f0", 0xc)
write(r0, &(0x7f0000000240)="14bdfa5d1d34e2fecb284a6498307dcda9aec43050036123339a346f737850551408753f95b7688ad4c4e1dd5489e7bafc58d3e5823757ae8b630719ef187ccad995f13dbe19a6dd4e6902bd8297b0799b426aabe9fad9db6996571c6d9f8bb5d542c2148aa42be940970fe88d34d8f99afe7e7820237400000000008000000100"/138, 0xfc7e)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x41, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000280)={0x6, &(0x7f0000000340)=[{0x25, 0x0, 0x3}, {}, {}, {}, {0x1d}, {0x6}]})
write(r0, &(0x7f0000000200)="d81ad3d20cf7eb4e9be33bbd1a30", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x61}, {0x3}, {0x6}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000200)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000008c0)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
recvmsg(r3, &(0x7f0000000340)={0x0, 0x0, 0x0, 0x0, &(0x7f00000024c0)=""/236, 0xec}, 0x0)
sendmsg(r2, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)
close(r1)
r4 = fcntl$dupfd(r0, 0x0, r3)
dup2(r4, r1)


open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7949)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
writev(r0, &(0x7f0000000280)=[{&(0x7f0000000000)='#!', 0x2}], 0x1)
write(r0, &(0x7f0000000180)="1e", 0x1)
writev(r0, &(0x7f00000002c0)=[{&(0x7f0000000080)=' ', 0x1}, {&(0x7f0000000300)="092060000152c9f100628a0a", 0xc}], 0x2)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x4001, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
r2 = socket(0x2, 0x1, 0x0)
connect$unix(r2, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r1, 0xffff, 0x1023, &(0x7f0000000080), 0x4)
shutdown(r1, 0x0)
select(0x40, &(0x7f0000000000), 0x0, 0x0, 0x0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000480), 0x1, 0x0)
writev(r0, &(0x7f0000000900)=[{&(0x7f0000000240)='E', 0x1}], 0x1)


openat$vnd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x2, 0x0, 0x20}, 0x4, 0x0, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
socket(0x18, 0x3, 0x3a)
sysctl$net_inet_ip(&(0x7f00000001c0)={0x4, 0x2, 0x0, 0x1b}, 0x4, &(0x7f00000014c0)="70c34227", &(0x7f0000000400)=0x4, &(0x7f00000004c0), 0x0)


r0 = socket$inet(0x1e, 0x3, 0x0)
setrlimit(0x0, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0xf66c, 0x0, 0x10001, 0x7f, "1c10260974612c330000fcff00"})
getpeername(r0, 0x0, &(0x7f0000000040))
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000340), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$VMM_IOC_WRITEREGS(r1, 0xc0205609, &(0x7f0000000040))


open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
pwritev(r0, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
r1 = open$dir(&(0x7f0000000580)='./file0\x00', 0x40000400001803c1, 0x0)
r2 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, r2, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
ftruncate(r1, 0x80002)


r0 = open(&(0x7f0000000300)='./file0\x00', 0x400, 0x0)
poll(&(0x7f00000000c0)=[{r0, 0x6e}], 0x1, 0x0)
syz_emit_ethernet(0x46, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, 0x0)
r2 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r2, 0x80105728, &(0x7f0000000100)={&(0x7f00000002c0)=[{0x2, 0x20007ff}, {0x3}], 0x2})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000200)={0x0, 0x0})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x100000001})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x7fffffff, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x18, 0x1, 0x0)
setsockopt(r3, 0x1000000029, 0xc, &(0x7f0000000480)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r3, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
getpid()
ioctl$WSKBDIO_SETMODE(0xffffffffffffffff, 0x80045713, &(0x7f0000002380))
setsockopt(r3, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


pipe2(&(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff}, 0x0)
dup2(r1, r0)
r2 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r3, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{0x2c}, {0x81}, {0x4000006, 0x0, 0x0, 0x3feffe}]})
r4 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
pwritev(r4, &(0x7f0000000080)=[{&(0x7f00000000c0)="bd", 0x1}], 0x1, 0x40000)
r5 = socket$inet6(0x18, 0x3, 0x0)
r6 = fcntl$dupfd(r4, 0x0, r5)
r7 = getegid()
semop(0x0, &(0x7f0000000040)=[{0x4, 0x5}, {0x7, 0x0, 0xc00}, {0x0, 0x9, 0x1800}, {0x3, 0x4, 0x1800}, {0x0, 0x5df, 0x1000}, {0x0, 0x0, 0x1000}, {0x1, 0x9, 0x1800}, {0x4, 0x6, 0x1000}, {0x2, 0x8001, 0x800}], 0x9)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x200, 0x0, r7, 0x0, 0x0, 0x88, 0x7}, 0x6, 0x6000000, 0x8000})
poll(&(0x7f0000000700)=[{0xffffffffffffffff, 0x40}, {0xffffffffffffffff, 0x80}, {r6, 0x1}, {r6, 0x80}], 0x4, 0x3)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001c40)={&(0x7f0000000100), 0xa, &(0x7f0000001b40)=[{&(0x7f0000000940)="51386a25d65c435d14bcfa92182ed5e8b253287f7273a2f03a932bd5e66eda9ea938f2c45fa46bc23499cfc4b290f02b97059f54ba87d7e28a67e40c461b2fc8d96ba8a85152d584b3d1ca8971818431a73a250195129b9ee682366ba5ce6973be7082dc7ea3062fb7cf0502eba53fb773625a3504927a54a142fca055d69052e8b7e83f55fa143db15fb943104fee291c33db4ab2a1972bd7e3a62c34babd0d24dee76f49dbb188d0a0fcb1f5a8790d65faf8536848c878cbd4e3c64ba522b7a10fb732a24c0578d456c95f7ce3d3240070d0b2a9f16c152bd21234000c186e9d0fb6085bb316cafe869da28a483810e373ee0d7f89e763945987b7baa471dc2761d3af886536723aace80ee622df86099973984f174db66369086265e8a224878736fe66cd3d1c8fa06eb68e6dc6846122afa8305ee60e4483248272a5a12454f7e977e31344a20655473d1a328e1925ea4bf5de4d7cdb6e6350f8b1194ee950e3b4127136c263560c8f15eee64592a418e5d8ea3cb4dea6297af70a3552ae3c75ce440db72b6572c7e50a857e3d0c77681d441125b030fff845869988401a2fb696376e9413b1294fd7665fe0d09c87fb293333385cf38b23bb73b54b38ef026df91e17538ed08e9f9b9952b0a8fb257887bc6ed3e93a43ebe6af82c64f4c138e12a6b00080eef20335f03773fe7ecc89aadbbeb2dc155dff475c3da2cf1e88edc7d103647c8908372a76feb38d0168197a64107193733ea362ff8330b03bd5bc8a387ae703b67ddd84ebbe8558f90c63151ab3815fb011b88bfd9bb947ea6dbe24536339a77f7dbc08c353c1ea8df3ab855e9aad6f3ef9ab02fa92d89bdf529010215121ab919769f568268701013d786226861327fcf682e17583c885efcb97dd457d55ffe97875ee2c87fb61e9b3dcc988cbe599b5cd57d32c26b446177820116f96e7aa6402ca81b6071ebae75555b82b490a32f9335fbb7d35c8538e0c0ad7a8d63a6813c29026a618f402ab515da2fdb191a830128b3ff070e30390b20db8ddb682109a99fd2ef6ff71ef6c7fefd8c447472b57d298306aabf581225cb4f8f3b76f3aadb55ab03d05b6b034188141301acbdc475decfd751b206b2f111f4b1cb116e968ca0802dee25755b1aca56e3429e7fc2e88901285f7d7f4f508c26b70cdc94b5d37af5b1546d4ca2b5e5bcba3dd4a9c3bd80473c368c49e11eec75a0dc4d020aaeae1b9e91c725ea479c5295f399fd80efba0cb5b51c9ab89897477c9f4c430b79d653870e34a4de7117b3f0da36464436c9df860d2291fb6e19d53ad9b0f87a00b1594ee5fb4ce6c01c315efbd13c318c752c233d056070acb096829620b6d8905c375a9637a5bf8a7f2e3c2e58b190e3d3c8730dc6ba23f211fa1b0b4dcf71af7f895c46fadf07af8d052c90367b30f92de84c87e3f8b1f22152647595bf855a7a9ff8f4a7b92081e86e82c2c1362c6d071cd65883da6b3a212a05883a99c6be6f8855026c31c91a899dcb9ef9a502d54b0b785a531a3683fbe4c1f34a9d5ee32be804af9f655c07fb29e2922aadea95c7f0b99b815f35218252dcf0859d3a573037a7276f6c6062b692b6a7e58445e4e4de03d19cdae346104fea3463c5655ec808c8ae0aac2b7ec9e8e2a4b5375426f2863d3292b34baa536cea2474be3e10075614b22bcb7126166fced5a0b4d804b0d0f26c7fa9420fc11e5671068a55a81bdbbe9bbd15745832e30ee3d8908640be738f972e86a268f85376017e47491832b690f2b3d54561ceaa86d954e92c571cb25bb79b5c4689a0940e8b1aeccb6da14948be73927e074db4170518b552cb5622634589e099e13f62fbe6794272456f717e65a8ae9f711440f51ea2bd9aef626e9f5342a54cf9f6076933c0034e92b82a6b6f6959d2357188394676001a88762282b3f7a18b17578a656985d5794030dbc104f684a0bd45955479ae5a0309171799593e226d7267685dc8168c00e66502bc2946e7e5adacf38278a426bdfe5fe058461d4a0ca7a570f5cf497b1acf1ca3ea9a7f456931670daabede487bce57438c910c0cea5d9bb74c0be7bb6386205f62b99269f0de626711f06e976a0fb4d180db2665ae0b9fbf725b36e40a5ca43571c43bfd07ca1ce92dbc47b28e12f7c8c3b394bf435f46f97447c1dee9dda05b9846f4822c62cb0f8fdfc74c694089d4864e1ef43f2eadc05a37bbe155bef2a0c8aafb396b091f6b8144a80a26461dd27f351fdca0a17b3f5c42de146d1a78beb58a324a54c9ff12a7afbf00fc7c7af4b25f682b4c0397d5fdcf060b6a85287f273a6d18336385da4d269fb232805d073444ef61cec1e74b1d9f13650872917c19f59af73ce7002307576d29614be1ed6d0f437d7be1926ef6dd060319d9d6648fe7ab7951f7c19813107d2400e2bfd63f7be9a466fb8433fe204c089fac05fe6afc0d7c7f90e0426f21903d90485434310f9475a0012e5c9b85b5c3e632088d8f9b7741e477e4826427929b0b0ce2d178147787a75b26f71da27a85d285690c8aef8f05d559cf05df24fca9e3aabe92c807e03691fd711170965a1cf4751c48603363934c6211bcb422d8323204228237e731ad92535c856cff9bf122690caed5331a653e6f5bf208b12c0a7b79ccc46640e678c3f55e0dadb28c7a6eadb5c3b325e1d63289b7aedb068458c6b0b79bb4a11b070962d671c0c66911f791f1db7cdcf37ee2d312dc59b05cae546ad130df6caad7e122fe7966d75abbbc29765d5cc66925b2ed69dba56ced209b800c691887993690a97236f198f5e67431ce80eb36009a61bc80e8bdac8a5f11b6c39f57991e7afed7094e1a85bd9114054b105d77f77a134d04a0c54fac73b2462260c39ce583f999f8da41ad92bd6a17b0dd6be759e0b90e68c1b5fbeae65429d8f59d96fc696371110b11c6d06020040a215c5a61e11504549301ef2dc42cb956ad1396a9119edc218407fb16e29ed639a44673e43967bf4c8a41b4b21a041a21c05269e26dc47558c039ca8015e81bd5651b6ad302db8f04eddd650ef5baf8724c11d21a1104e05a01e696f7da07c9617046bfea761018de57c668c09f68157471109ca994105e026f1f37d4b9b8dd2986bb01a6ffa1e035a62915e84728371e38acb4f1a5294ac357aabb6847b5b3ff2393859fcc9a1673cf6d915b3876c148f2c5ca97cf5c58f7ae87c11182c1b322ed94e2905b61ff0a109577af2eed05f2a82fa0f5635bb5bbfb8ddb42c65d98aab2486f16377bcb220bfabed1939019fde059559bc0dc4d4266f201f47a925a2843f1ab037c0a53c3703ca1f470a884383b30e0d011e24350e018c7b304062536d6389ae89d89835e85bbaa8611ef71a7a1b8cdfb8b949ea66a2cbc4a84af7d16bcafd17fc7b7837b37f5367463b0a6bead6d0b9165005ca075743782036ad740e27f85656683169d1e34ced929de3a4b9967785d8cd96cae4b575259f2f864c459a42af1d8036c500b104b32403375a19fd7917a7af50fedd368a59046f4de0ac15e8e9b343ee0f9ae6e2f043ef86d5fb3c4be8c993f70983485d6b352da689cb5cfc9398aa26f25416ed47f75fda2e3f24a3fca817e507870e7e0335b4863634f7e88c6a840c59161686afbde565a01b339d195a6e0edf223a4f0a545d55eaad92659f00d7d6d25f0038c51162155f97fdd1016025303a1de05ea431885f39495b3386af36ef6f4162fc53b655a2885fa731e1ed227826da0234e57e039904f139912aeb499fd506c560792aebe7872b443ac4ae338c88e8cfed596a467cac80b07deecb66954efb264920baebcc174647918970442a4aaa5094ba1680017de921d5bb1c53c15f6eff0096c6e0d2a3526c39688b65d6c3c99d5a0512a6c18dabcfaaaa45609f9edcb48679b5b4f671a1c93789fa01488e2e03566091bf869ed9673bf349cb20dc85ead56661b685ed9ad42695d59d8a4de4489339e284317399f03e13f7c61b3f69186c0375b92569c0004702dfff3142d3c1cc0a2a192557da538c9ae3fbd64bd5fb4f0291c072e4170a3ce294c56650badc1250f22d954338e627d6b78015d143755a509202e78abb436b89bc6a91ae271e1728b990df4dade6989559a9d598e686ef4e1e80a2780987934e37af1dc54526e5a823508d6bc746f57184536fc48cb3ef3463f28aff608fbd7f0def9ba45087a17a611d3e397bcff61b62097912a564f8f6d80e9a7b9975008e74653e280239c4a9e0beb13d6d4f8435e4049d89421c04a0411c11ac647c89c1fa4a2aa7f6202ca6b06229049999208ef22c6a19727af1e9fe7463403551ed13c0e0950491fb107495e802ca88dd8444150b638bffe9fcb83d1ade4b701308e6c247c5f875f4727172c399d27ea8e9fa46ce0ecb28b6b10ffab1ee2094253b562dda055a933266842f384a3e41139ed48cbbb8bb66a82309b0cd5bd468dbe3cfee9d879de0c278900418381c82a4d0d50ec8c3a7c4adced40d1e30fa804b00f2046889f8d2359043ac746a500b6f2694250d817cc67debf60b39af256998475596b58d8da4ea5721bdc32cd35b93156cb5fc5edd074cdb58cf03a59de1adb1e33ddb2f5415da4977f972138cb52b9febd7143b44ed63b3ef95c846dd81a8143269718d865930766fe7bdc9915ce26b54288f9925cd4041e6917d796f4c2b2390d21c76146a07340869fff24d610a0c0966823f04049292d754678b5437c24610aaeccf2c2959ee0e5effa88a1a1bbe4d4662e6a2acfc6e272668353a9cb632e4fb8f5d3ccf7f1643ce804fc788d01985224eb78a446899c83bb426e51368a9737217099d04fae1068de240f5c5a6eeda9609ddf1b64dc5ee492a82f81cc9a7b0d43f0a976991b8f8ee32760b4e0de5e3eedab35ef3223722041e59815b4852bb5a8c5e3c59d8cede23a07de70b906fffd5ac87d103ff3bea23a54de817c61dd1d746ab85fc1e7594e8ae51538379420b8d137315da042968f79ceb1d134879d79bf4d9806ad20bd73f22330d2376199986d93519394965da6171bd29211a627844c334eaad6fbaa203d0b6f53f4246869a4b2f1c7963fd0d16047b8cc26198816fa5aa423ec93b739606a4f9a4bbf72b14477511482dfa2f2a70ab0d06a3dcb8987109dcc2d9a31f894f6dced4bd44241066a9cfb6c06814b832c0851976e3d965b752488655dc2eb03d7faec397adbf7fd5a3088600b31e216b2db008cd8cb1215b0152e528be38b1e2fd01a105c3ed7ee30a334d1aa1b3aadc530b308a6313bef33446915aa6675a4f5d9b94f91cdf771248c5e47de27fab7f75e5c3ee5f5d9c5d4968937c8f40035cc1cf8ce89c2b9a9bee7033caf382b219a9d19e836b4773160b464b6b48d5dd62edf68c3add9ee51d71a0fe56c81710ee489ca66bccb04e1366da04916a229d8d4518bd36871775a2a13b3688c78aa5a96d97a2f1258461c9a044f6c2daf780299030b7624d7095aae997a5f1b8d03bdce426a1b8ed609ca2cdcf41be9ce1ecf30208f071f804483297d71c04c0349c03beb9faf84e1641877b13d6ebc8d213ab7f228f25804a5ca5bc57da182c31963c92b6700aa857ab4e02cc62740e121dcaf648cbc61bd31308feae4f544fe4a1e61d99b7d3eabf7cdb1fd9b2635e7034f9a4dcdb490f8561757e79af2b23e21c803470033d6c8ff680af4cbfc6846f62eb743a8bb2c9f666794effb5586ad96b8555dd993398716ba4325701ecc3e1b52924f8df846759212675ff68838d4df436e3483edff5372b435a", 0x1000}, {&(0x7f0000001940)="35ecb78ed6532d156aa25cd6e56ada407b8ec7eb755cdeda085f5e20289e59ab1db0ff0100000000000097d5df7b491f2bd1f36fe9079dbb527439d2bb0718a699fe52aa1d232252ea3dc87c1c4447d7a6c40453f8fdfb407fe86270a3f476d3f9dfd68f37428428a7efef06e7fa20168cc2373b3537726835bc9e20604af95ca43982c9d7fceca87fb3451de4c188f273d9340eb5f257fc06fa2526abd69a1b7716a2f57fbd52be23753db4be04b0fceb659989fe00"/205, 0xcd}, {&(0x7f0000001a40)="e5a5db8f9c7d081863ea5168cc342873911bbc6886f6e35c21175475d78072a39f6dbd093455834397264d566d075a0feae89c51d178425bbe6d4973093e475b4ce06b2d7399428d7207ffa63e78e669807eea89ba01447b06a2fb4c915c684d2ed0c9e3c81b757d2c6fc9a31b2be691f508", 0x72}, {&(0x7f0000001ac0)="d3de56cf1f06d50f2aaa33c8d9e63b0b8f72696ba087a0adbf9882c9368b97c2da5aaa695fdf6ab753cd0e624c6e72eb9bef21c5e0b203b49ab751cb790967c0efa4d2983c9ad99e8cebd8e7c79f1c61d7f060c9d25e6cefa209963d912c84d1c86e", 0x62}], 0x4, &(0x7f0000001e40)=ANY=[@ANYBLOB="1800000000000000ffff000001000000", @ANYRES32, @ANYRES32, @ANYBLOB="3000000000000000ffff000001000000", @ANYRES32, @ANYRES32, @ANYRES32=0xffffffffffffff9c, @ANYRESDEC, @ANYBLOB="000000002000000000000000ffff000000000000", @ANYRES32, @ANYRES8, @ANYRES32, @ANYBLOB='\x00\x00\x00k'], 0x68, 0x40c}, 0x4)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f0000000080)={&(0x7f0000000040)=[{0x100, 0xfffffff8}, {0x82, 0xfff}, {0x24}], 0x3})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000002c0)={'tap', 0x0})
ftruncate(r6, 0x10000)
ioctl$BIOCSDLT(r6, 0x8004427a, &(0x7f0000000240)=0x828dfa19)
write(r3, &(0x7f0000000180)="23009100007adb020317bdda2b7e", 0xe)
read(r3, &(0x7f0000000340)=""/249, 0xf9)
ioctl$WSKBDIO_SETENCODING(r2, 0x80045710, &(0x7f0000000200)=0x1000)
write(r2, &(0x7f0000000040)="374463e3ddd7edc99ececb1e802aba4f8fd4d8eb5a6d236ba56489a07022714cf79e3cff5af40c02de6e", 0x2a)
ioctl$TIOCGTSTAMP(r0, 0x4010745b, &(0x7f0000000000))
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000280)={0x1, &(0x7f0000000140)=[{0x0, 0x0, 0x2, 0x4}]})
pwritev(r1, &(0x7f0000000800)=[{&(0x7f0000000440)="cdc7509a3ff0c6e231d04c8c5b3ed6abda42de32a184b91337fc8ce5de6abdc7b56d73ba61c92a9eca226bf7f64806cfce8c3f774d2e5fb2081c71b5d24cd5574405c90c6f00d98838941b0ff6f45e70a74efb9522951b56a6e4820d8337de5b6c77da6a2c119c240d0be70ea34cc1e27449a844", 0x74}, {&(0x7f00000004c0)="21b424995df5b9908b7111e22f42fe937ba0577463c7ae183e799ec47ae40715e0838d27e1ff3af9121b24a6dcf0a2283217c77de1c53c6e3e999f3d5197047833865d2348531da24f03710226564a64d0de30c43c79a8f7b36f2aa6441c1268ff4786bc39031d72c8d2ec268a26b1cbae1f6eaf406dcb", 0x77}, {&(0x7f00000001c0)="2a1a1e25d2da0316a6081890beb612520569c4e228bd2b3235bc91b943e2465e7fe7ba0a8d72b662500da2be2eda221df6", 0x31}, {&(0x7f0000000540)="7464a0f7f8dd0a2fc062cfa81f3919321018e2053811e443d488618ae9e223d3dcc74b2d05c3ef1f79f94679be85d47188a294ec9c5e1c28e02da640302e6c59b4fd1c88ddc787", 0x47}, {0x0}, {&(0x7f0000000780)="8d229c6fc2f549b8298b9ab34d3cc44e9ca5401d3ac031ae28740ba6259730b05b08a2816aec3672371431690c9a0af797c36ff870f1c3b89b90cb5f990f3b8c33e72a76c4cca0a158ab5f0e077d30bb2b6e31b38aede61bfb30756ebf3d64cf2e7aeeb92871baa46a93dbbc2318d6e79fcf", 0x72}], 0x6, 0x1)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd01)
r8 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
preadv(r8, &(0x7f0000000300)=[{&(0x7f00000000c0)=""/104, 0x68}], 0x1, 0x8000000000000000)
writev(0xffffffffffffffff, &(0x7f0000000000)=[{0x0}], 0x1)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x33}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0xca})
r0 = syz_open_pts()
close(r0)
ioctl$TIOCSTSTAMP(0xffffffffffffffff, 0x8008745a, 0x0)
r1 = socket(0x0, 0x3, 0x0)
setsockopt(0xffffffffffffffff, 0x11, 0x2, &(0x7f0000000000), 0x4)
r2 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x100, 0x0)
pread(r2, &(0x7f0000000040)="fbd46e49855e67c3a2d12747d2ca2663bfe5d4366a2159097dc3a7f629b8fc732809fb465aaa0581396ccc5352439a132381a0808229e157e7d9ce79a04431adb5830586038c1540a0ab57", 0x4b, 0x7)
fcntl$setflags(r0, 0x2, 0x0)
mmap(&(0x7f0000ffa000/0x3000)=nil, 0x3000, 0x0, 0x1010, r2, 0x100000001)
socketpair(0x0, 0x4, 0x81, &(0x7f0000000140)={0xffffffffffffffff, <r3=>0xffffffffffffffff})
openat(0xffffffffffffff9c, 0x0, 0x0, 0x176)
poll(0x0, 0x0, 0x0)
openat$wskbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$WSKBDIO_BELL(0xffffffffffffffff, 0x20005701)
sysctl$net_inet6_ip6(0x0, 0x0, &(0x7f0000001200), 0x0, &(0x7f0000001280)="56b4d208c978004dd3c37cb8f9de4a5833d910edbce299377d77807aebfdf70b4c9d0076b6dc40f8cd12947286f0457c3a717b6d5825950f443524eec8d110a24e8f5fad71a17842f6c8ce9f0fcab92ce8cbdb72884001408769a6c9075751996a7c22d32b9926785a223fb2913b4b9d73e8c3a0470663b8a67362db995223542461cc659e6fe2b959dfce0e23cd2d6c976e0dc6ef1f11573b90b7daf640873ee5a04787606db1a0917c2325d23c656fd8", 0xb1)
getsockname$unix(r3, &(0x7f0000001340)=@file={0x0, ""/45}, &(0x7f0000001380)=0x2f)
msgget$private(0x0, 0x188)
getuid()
getsockopt$SO_PEERCRED(r3, 0xffff, 0x1022, &(0x7f00000015c0)={0x0, <r4=>0x0, <r5=>0x0}, 0xc)
getpgid(0x0)
sysctl$kern(&(0x7f0000001680)={0x1, 0x28}, 0x2, &(0x7f00000016c0), 0x0, 0x0, 0x0)
semop(0x0, &(0x7f00000018c0)=[{0x0, 0x8, 0x1800}], 0x1)
syz_open_pts()
execve(0x0, &(0x7f0000000280), &(0x7f0000000300)=[&(0x7f0000001b00)='\x00', &(0x7f00000002c0)=':\x00'])
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, r4, r5}, 0xffffffffffffffff, 0x80000000000000})
setsockopt$sock_int(r1, 0xffff, 0x1002, &(0x7f0000000080), 0x4)
socket(0x2, 0x2, 0x0)
syz_open_pts()


r0 = socket(0x11, 0x3, 0x0)
r1 = socket(0x0, 0x2, 0x0)
connect$unix(r1, &(0x7f0000000000), 0x10)
r2 = socket(0x2, 0xa000, 0xfe)
r3 = socket(0x18, 0x2, 0x0)
socket$unix(0x1, 0x1, 0x0)
r4 = getpgid(0xffffffffffffffff)
r5 = getuid()
setreuid(0x0, r5)
getsockopt$SO_PEERCRED(r3, 0xffff, 0x1022, &(0x7f0000000040)={0x0, 0x0, <r6=>0x0}, 0xc)
setsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000001c0)={r4, r5, r6}, 0xc)
open$dir(&(0x7f0000000640)='.\x00', 0x0, 0x0)
r7 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r7, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r7, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f00000004c0)=[{0x2c}, {0x14}, {0x8306}]})
connect$unix(r2, &(0x7f0000000200)=@abs={0x0, 0x0, 0x1}, 0x8)
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x5143)
r8 = open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSFLAGS(r8, 0x8004745c, &(0x7f0000000080))
r9 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000180), 0x20, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r9, 0x80105728, &(0x7f0000000380)={&(0x7f0000000340)=[{0x20, 0x4}, {0x0, 0x5}], 0x2})
sendto$unix(r0, &(0x7f00000000c0)="b100051300000000000000400020000000000000cea10500fef96ecf2ac72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf7f882b297be1aa0540000051e2f0ad3ebbc257699a1f139b672f335c223e7d0c032b0c8a6443a42118000000720fd38bfbb770c1f5a872c88106002ec589040000000c000000361b1257aea8c500002002fbfe0c2300008abfba0900afb7515871a3f8343712051eeab7196fcbd80407000000c011200000", 0xb1, 0x0, 0x0, 0x0)
msgget$private(0x0, 0x60)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x5900)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
select(0x40, &(0x7f0000000140), 0x0, &(0x7f0000000200)={0xffffffffffffffcf}, 0x0)


open$dir(&(0x7f0000000240)='./file0\x00', 0x200, 0x0)
r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x1, 0x0)
pwritev(r0, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
sysctl$kern(&(0x7f0000000300)={0x2, 0x9}, 0x2, 0x0, 0x0, &(0x7f0000001440)="00000100", 0x4)


r0 = getppid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0xffffffffffffffff}, 0x0, 0x0, r0})
pipe(&(0x7f0000000180)={<r1=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r1, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r2 = fcntl$getown(r1, 0x5)
ktrace(0x0, 0x1, 0xf32, r2)


sysctl$kern(&(0x7f0000000000)={0x1, 0x9}, 0x2, 0x0, 0x0, 0xffffffffffffffff, 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000000c0)=[{0x3d}, {0x81}, {0x8006}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


unveil(0x0, 0x0)
unveil(0x0, &(0x7f0000000080)='r\x00')


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x10000})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000040)={0x0, 0x5, 0xfffffc16, 0xfffffffc, "0afff5ff7a095aeba1d76ff218aabc86001800"})
writev(r0, &(0x7f0000000840)=[{&(0x7f00000009c0)="1bf882c147063c80d3488dee7e157281374a68073ada17b27df1dfc9c9925c1f027c3b7b1a05319351cdc65fe93981dca900f55c48b50ab333662aee276b0ef9f188aa82ac19a7fb379eb4962f2d58dc2dc1127a173c751c812fd90ce41a14a56114322da257feb94d5189149508c957e47792c556a256c713d069c243858eab22bbc73660d8629969a253ab4105462c267e2a0f55481be0d308a8db18f4f8f293917cb5d1fe74f4a6c3be6babc58636de9017cf524849359c1a4c36d06821f99c211b7435ac690f4288f743374477e8b49be85e6d164b592d1091c16b241a0a7eb1c760f3f69ec542ac169d3ca0e4d4184a935f0465e41df1d1ead15fab9c6d893c922fe7ccc85b5f6e843e9bd257525ea4603d41f647350541e5ede6c68b51f0749545aa67b931b241e491369beb2b8cb7663ce5e20d5159e7efa0540fc7c2bdd5247867313e9e506bcd09", 0x14c}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
syz_open_pts()
r1 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$SPKRTONE(r1, 0x80085301, &(0x7f0000001540))
close(0xffffffffffffffff)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000100)=[{0x44}, {0x24}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000400)=[{0x5c}, {0x5}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x412dff)
ioctl$VNDIOCGET(r1, 0xc4104603, &(0x7f0000000540)={'./file0\x00', 0x1, 0x3ff, 0x10000})
r3 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
poll(&(0x7f0000000500)=[{r3, 0x1}], 0x1, 0x0)
select(0x40, &(0x7f0000000040), &(0x7f0000000080)={0x7}, 0x0, 0x0)


openat$diskmap(0xffffffffffffff9c, &(0x7f0000000000), 0x5de47d223fe74984, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
r0 = socket$unix(0x1, 0x1, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f0000000000))
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$VNDIOCGET(r1, 0xc4104603, &(0x7f0000000540)={'./file0\x00'})


ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f0000000080)={&(0x7f0000000040)=[{}, {0x0, 0x80}], 0x2})
sysctl$vm_swapencrypt(&(0x7f0000000040)={0x7, 0x2, 0x2}, 0x4, &(0x7f0000000140)="118bea625d95de8f92c010baed45ec4bf03ace254b57973bb6de7b1c90301e9d3b5e6fb6ffffffffffffffff76c775a2a4e0556565a830032eef776127fd247103c14ab0a1cea9b4593be484f46a02ea73e910d041c5777bd852e57d3248832b91d06fe47d126022a1654859149e9486306d2f11fb1cc826c42f81b0d114f8af4ceb029a5210bb6947464bf678ba1d64a2013131fedfe60443aa13e015b28a16ea924bf89ad45c006213a6d0e194b9abcb3ddfab0c69b8c280bfc9c11f26026f6231b5e725921be8b099", 0x0, 0x0, 0xfffffffffffffd2a)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
r1 = getpid()
ktrace(&(0x7f0000001d40)='./file0\x00', 0x0, 0x1720, r1)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x4a, 0x0)
r2 = socket(0x2, 0x4001, 0x0)
r3 = dup(r2)
r4 = fcntl$dupfd(r3, 0x2, 0xffffffffffffffff)
close(r4)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r5 = socket(0x2, 0x2, 0x0)
socket(0x0, 0x0, 0x0)
r6 = dup(r3)
r7 = fcntl$dupfd(r6, 0x2, 0xffffffffffffffff)
close(r7)
r8 = socket(0x2, 0x2, 0x0)
connect$unix(r8, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r7, 0xffff, 0x1023, &(0x7f0000000040), 0xe0)
connect$inet(r5, &(0x7f0000000000), 0x10)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000180)=[{0x60}, {0x20}, {0x206}]})
write(r0, &(0x7f0000000000)="7696e5f3d1f18c37cea8615ac7cf", 0xe)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, "1a013bf0ff00"})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x8000000000000001})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


r0 = socket(0x2, 0x3, 0x0)
getsockopt(r0, 0x0, 0x67, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000200)="8b8c7e5e4a7966dfcde82b0abb", 0xd}], 0x1)
sysctl$net_pipex(&(0x7f0000000000)={0x4, 0x22, 0x2}, 0x3, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2a, 0x0)
clock_gettime(0x2, &(0x7f0000000200))
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0x400, 0x0, 0xffffdffc, 0xffffffbf, "ff000000000000000100"})
close(r0)
poll(&(0x7f0000000040)=[{r1, 0x1}], 0x1, 0x0)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x1, 0x0, "0e5f68cdd75751147708cb211e0202c5bf74de60"})
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
close(r1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000400), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000280)=[{0x4}, {0x15}, {0x812e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])


ioctl$BIOCSETWF(0xffffffffffffff9c, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x3}, {0x6, 0x0, 0x0, 0xbe}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0xfffffffffffffe59)
sendmmsg(0xffffffffffffffff, &(0x7f00000007c0)={&(0x7f0000000780)={0x0, 0x0, &(0x7f0000000400)=[{&(0x7f0000000180)="b860fe09625ee6793978a575faa1b6c6c1d6c2eca2950e663d39ab1be31a269a39fd7f97e41e178f37a79f00659c2ea9ac56733f7e4e4973c1e6b33ac91343ea3b3f8c5c7b93d5c20ab4211791fe30", 0x4f}], 0x1, 0x0}}, 0x10, 0x0)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f00000001c0))


rmdir(&(0x7f00000000c0)='.\x00')
ioctl$VNDIOCCLR(0xffffffffffffffff, 0x80384601, &(0x7f0000000080)={&(0x7f0000000000)='./file0\x00', 0xfff, &(0x7f0000000040)='./file0\x00', 0x8})
sysctl$kern(0x0, 0x0, 0x0, &(0x7f0000000440), 0x0, 0x0)
rmdir(&(0x7f0000000000)='./file0\x00')
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x0)
r1 = socket$unix(0x1, 0x5, 0x0)
listen(r1, 0x0)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x7}, 0xc)
syz_emit_ethernet(0x3a, &(0x7f00000000c0)={@random="ff96430b7a73", @empty, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x20, 0x0, @multicast1, @broadcast, {[@rr={0x7, 0x3, 0x4}, @noop]}}, @tcp={{0x0, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})
r2 = openat$wsdisplay(0xffffffffffffff9c, &(0x7f0000000100), 0x800, 0x0)
write(r2, &(0x7f0000000140)="92691a49faca4eaefa78779eb702082343300bd350a39fd23411bb625e216664facf9469bcbd1f", 0x27)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b1000504000004000000000007000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4fcf668246c0900e1937c727a4bdb8d000008e371a3f834371205", 0xb1, 0x0, 0x0, 0x0)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000100)="b10005016000009f0500000007000000001813fecea10500fef96ecfc72fd3357ae302b37b673039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f4d335c223e7d026ba8af630037282102000000720fd38bfbb770c116a972c881ea772ec5890400000000ff0000361b1257aea8c500002002fbff0c2300008a09000000000008e37195f8343712051eeab71d89e00004070000008004200000", 0xb1, 0x0, 0x0, 0x0)


setreuid(0xee00, 0x0)
mknod(&(0x7f0000000040)='./file0\x00', 0x6000, 0xe02)
r0 = open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
r1 = getuid()
seteuid(r1)
readv(r0, &(0x7f0000000000)=[{&(0x7f0000000240)=""/183, 0x82}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x60}, {0x4c}, {0x157e}]})
writev(r0, &(0x7f00000002c0)=[{&(0x7f0000000340)="ebebfd510bbcd3a9b489e989c14f", 0xe}], 0x1)


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
dup2(r1, r0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt$inet_opts(r0, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0x8)


r0 = socket(0x18, 0x3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
ioctl$FIONREAD(r0, 0x80606955, &(0x7f0000000100))


pipe2(&(0x7f0000000200)={0xffffffffffffffff, <r0=>0xffffffffffffffff}, 0x0)
ioctl$KDGETLED(r0, 0x4b31, 0x0)


open$dir(&(0x7f0000000040)='./file0\x00', 0x300, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
select(0x40, &(0x7f0000000100), &(0x7f00000024c0)={0x1ff}, 0x0, 0x0)
ktrace(&(0x7f0000000300)='./file0\x00', 0x0, 0x530, 0x0)


open$dir(&(0x7f00000003c0)='./file0\x00', 0x400004000011830a, 0x0)
setreuid(0xee00, 0x0)
r0 = getuid()
chown(&(0x7f0000000180)='./file0\x00', r0, 0xffffffffffffffff)
r1 = getuid()
setreuid(0x0, r1)
chmod(&(0x7f0000000080)='./file0\x00', 0x2ea)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{0x4}, {0x61}, {0x8086}]})
syz_emit_ethernet(0x1db, &(0x7f00000007c0)=ANY=[])


sysctl$kern(&(0x7f0000000000)={0x1, 0xa}, 0x2, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x0, 0x0})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbdf13b9fd812eaa4e713048e69931929648", 0x14)


r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
r1 = socket(0x18, 0x3, 0x0)
close(r1)
r2 = socket(0x800000018, 0x2, 0x0)
ioctl$TIOCSETA(0xffffffffffffff9c, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x7ffffe, 0x0, "1a05227955686f00"})
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000100)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = dup2(r1, r0)
sendmsg$unix(r3, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0x8020560a, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000280)='./file0\x00', 0x1000, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r1 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
ioctl$DIOCMAP(r1, 0xc0106477, &(0x7f0000000080)={&(0x7f00000002c0)='./file0\x00', r0})
close(r0)
r2 = socket$unix(0x1, 0x5, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000040)=[{0x103, 0x5}, {0x82, 0xffffffff}], 0x2})
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
mmap(&(0x7f0000000000/0x4000)=nil, 0x4000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
clock_settime(0xffffffffffffffff, &(0x7f0000000140)={0x0, 0x1})
socket(0x0, 0x1, 0x0)
r3 = dup(0xffffffffffffffff)
listen(r3, 0x0)
socket(0x0, 0x1, 0x0)
r4 = socket$inet(0x2, 0x1, 0x0)
getsockopt$sock_int(r4, 0xffff, 0x1004, 0x0, 0x0)
fcntl$dupfd(r2, 0x0, 0xffffffffffffffff)
close(0xffffffffffffffff)
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
syz_emit_ethernet(0x138, 0x0)
mprotect(&(0x7f0000761000/0x2000)=nil, 0x2000, 0x1)
r5 = msgget$private(0x0, 0x0)
msgrcv(r5, 0x0, 0x0, 0x2, 0x1000)
msgctl$IPC_STAT(r5, 0x2, &(0x7f0000000240)=""/56)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000300)={0x20000316, &(0x7f00000000c0)=[{}, {0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x3e}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1, 0x0, 0x37)
r0 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r0, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
r1 = socket(0x2, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCLOCK(0xffffffffffffffff, 0x20004276)
seteuid(0xffffffffffffffff)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
listen(r1, 0x401)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b10005016000009f0500060003000000331c13fecea10500fef96ecfc72fd3357af302b37b673039d2d236acf20b7804be382249d1f7c8cf5f88882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f4d335c223e7d026ba8af6300372821", 0x62, 0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504000004000000000007", 0xd, 0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000001})
r2 = socket(0x11, 0x3, 0x0)
sendto$unix(r2, &(0x7f0000000000)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)
ioctl$FIONREAD(r0, 0xc0207534, &(0x7f0000000440))
r3 = semget$private(0x0, 0x2, 0x119)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r4, 0x80104267, &(0x7f0000000380)={0x3, &(0x7f0000000200)=[{0x800, 0x1, 0x9, 0x7fffffff}, {0x9, 0x2, 0x7, 0x200}, {0x7ff, 0xc0, 0x4, 0x9}]})
semctl$SETALL(r3, 0x0, 0x9, &(0x7f0000000000)=[0x1, 0x4, 0x6529])
pwritev(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f00000005c0)="dc", 0x1}], 0x1, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
setrlimit(0x8, &(0x7f0000000980)={0x6, 0x51})
r5 = syz_open_pts()
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r6 = dup2(r5, r5)
close(r6)
r7 = syz_open_pts()
ioctl$TIOCSETA(r7, 0x802c7414, &(0x7f0000000880)={0x0, 0x10000043, 0x5, 0xa7bb, "d8f1f9bdca0d8300"})


open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
r0 = open(&(0x7f0000000280)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000401})
open$dir(&(0x7f0000000240)='./file0\x00', 0x20, 0x0)
open(&(0x7f0000000100)='./file0\x00', 0x6d0, 0x0)


setrlimit(0x0, 0x0)
syz_open_pts()
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ktrace(0x0, 0x5, 0x40000500, 0xffffffffffffffff)
dup(0xffffffffffffffff)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
msgget$private(0x0, 0x0)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b1000502000000000000000007000000330002000000000000f96ecfc72fd3357ae320b37b673039d2d236acf20b7804be38164991f7c8cf5fd72b297be1aa5b236de351e2f0ac3ebbc257699a5f139b672f4d335d223e7d026ba8af630037382102000000720fd38bfbb770c1f5a8727781ea2e69e0bb76d907c400000000361b1257aea8c500002002fbff0c230000aabfba09008007000000a30435376012051eadb71d89e000040781e4b2ffff1300", 0xb1, 0x0, 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000240)={0x2, &(0x7f00000000c0)=[{0x0, 0x0, 0x0, 0x2}, {0x6, 0x0, 0x0, 0x8002}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x2, &(0x7f0000000100), &(0x7f0000000080), 0x0, 0x0)
getgid()
close(0xffffffffffffffff)
socket(0x0, 0x0, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
fcntl$getown(0xffffffffffffffff, 0x3)
ioctl$BIOCLOCK(r0, 0x20004276)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x66, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
pipe(0x0)
mprotect(&(0x7f0000ffe000/0x1000)=nil, 0xffffffffdf001fff, 0x0)
open(0x0, 0x0, 0x0)
minherit(&(0x7f00006b5000/0x2000)=nil, 0x2000, 0x0)
msgctl$IPC_SET(0x0, 0x1, 0x0)
open(0x0, 0x0, 0x0)
r1 = open$dir(&(0x7f0000000040)='./file0\x00', 0x40000400001803c1, 0x0)
sysctl$net_inet_divert(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
acct(&(0x7f00000000c0)='./file0\x00')
pwritev(r1, 0x0, 0x0, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
r2 = dup(r1)
recvmmsg(r2, &(0x7f0000000440)={&(0x7f00000000c0)={0x0, 0x0, &(0x7f00000006c0)=[{0x0}, {0x0}, {0x0}, {&(0x7f0000000180)=""/98, 0x62}], 0x4, 0x0, 0xfffffdd0}}, 0x10, 0x66, 0x0)
r3 = dup2(r0, r1)
writev(r1, &(0x7f0000000080)=[{&(0x7f00000003c0)="ae", 0x1}], 0x1)
shutdown(r2, 0x0)
dup2(r3, r2)
execve(0x0, 0x0, 0x0)


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x67, &(0x7f0000000240)={0x7fff}, 0xc)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000080)=[{0x24}, {0xc}, {0x8106}]})
syz_emit_ethernet(0x2a, &(0x7f0000000300)=ANY=[])


write(0xffffffffffffffff, &(0x7f0000000000)="7696e5f3d1f18c37", 0x8)
r0 = socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f0000000000))


setrlimit(0x8, &(0x7f0000000980)={0xb, 0x4e})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f00000000c0)=0x5)
writev(r0, &(0x7f0000000080), 0x2)
write(r0, 0x0, 0x0)
execve(0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000100)={0x978d, 0x9, 0x1, 0x9, "bb08000100f1675910508b00000000004000"})
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f0000000300)={{}, 0x0, 0x0, 0x0, 0x0, 0x4})
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)


open(&(0x7f0000000480)='./file0\x00', 0x200, 0x4ebfac6bbaf796d)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
writev(r0, &(0x7f0000000080)=[{&(0x7f00000001c0)='#!', 0x2}, {&(0x7f0000000200)='\n', 0x1}], 0x2)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000280)="b1000501600000000000000007000000331c13fecea10500fef96ecfc72fd3357ae320b37b673039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa5b236deb51e2f0ac3ebbc2576b9a5f139b672f4d335d223e7d026ba8af630037002102000000720fd38bfbb770c1f5a872c881ea6e69e0bb76d907c400000200361b1257aea8c500002002fb00000000008ad20300000000ec1d89e000040781e4b2fff040ff00"/177, 0xb1, 0x0, 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x46, 0x56})
r1 = syz_open_pts()
close(r1)
pipe(&(0x7f0000000100)={<r2=>0xffffffffffffffff})
close(r2)
r3 = kqueue()
openat$null(0xffffffffffffff9c, 0x0, 0x0, 0x0)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r4 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmat(r4, &(0x7f0000001000/0x3000)=nil, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
mknod(&(0x7f0000000080)='./file0\x00', 0x1, 0x7fffffff)
setreuid(0x0, 0xee01)
r5 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmctl$IPC_SET(r5, 0x1, &(0x7f0000000000)={{0x0, 0x0, 0x0, 0x0, 0x140}, 0x0, 0x0, 0x0, 0xffffffffffffffff})
shmat(r5, &(0x7f0000001000/0x3000)=nil, 0x3000)
kevent(0xffffffffffffffff, 0x0, 0x800, &(0x7f00000006c0)=[{{r1}, 0xffffffffffffffff, 0x8a}], 0x0, 0x0)
kevent(r3, &(0x7f0000000340)=[{{r1}, 0xfffffffffffffffe, 0x1b}], 0x203, 0x0, 0xfffffffd, 0x0)
r6 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r6, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
r7 = dup(r6)
ioctl$BIOCSETF(r7, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000200)=[{0x35}, {0x45}, {0x7e}]})
syz_emit_ethernet(0x10a2, &(0x7f0000000280)=ANY=[])
connect$unix(0xffffffffffffffff, 0x0, 0x0)
getsockname(0xffffffffffffffff, 0x0, 0x0)


r0 = open$dir(&(0x7f0000000080)='.\x00', 0x0, 0x0)
mknodat(r0, &(0x7f0000000140)='./file0\x00', 0x2000, 0x59be)
open(&(0x7f0000000500)='./file0\x00', 0x0, 0x0)


faccessat(0xffffffffffffffff, &(0x7f0000000000)='./bus\x00', 0x0, 0x0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x7fffffff)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)


open$dir(0x0, 0x0, 0x0)
r0 = syz_open_pts()
readv(r0, &(0x7f00000012c0)=[{&(0x7f0000001200)=""/1, 0x1}], 0x1)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0xffffff9a, 0x0, "b07b1f660000000000002000"})
syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "0fdb00000000000000060004000000000800"})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = dup(r0)
ioctl$BIOCSBLEN(r1, 0xc0044266, &(0x7f0000000100))
openat$vnd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
syz_extract_tcp_res(0x0, 0x0, 0x0)
ioctl$FIONBIO(r0, 0x8004667e, &(0x7f0000000340)=0x200)
readv(r1, &(0x7f0000000080)=[{&(0x7f0000000180)=""/15, 0xf}, {&(0x7f0000000040)=""/17, 0x11}], 0x2)


writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
sysctl$hw(&(0x7f0000000000)={0x6, 0x6}, 0x2, &(0x7f0000000040), 0x0, 0x0, 0x0)
r0 = msgget$private(0x0, 0x282)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000080)={<r1=>0xffffffffffffffff})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x2, &(0x7f0000000080)=[{}, {0x4, 0x0, 0x0, 0x20}]})
sysctl$kern(&(0x7f0000000080)={0x1, 0x44}, 0x4000000000000004, 0x0, 0x0, 0x0, 0x0)
r2 = openat$wsmuxmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$KDGKBMODE(r2, 0x40044b06)
openat$null(0xffffffffffffff9c, &(0x7f0000000240), 0x8000, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x0, 0x0)
open(&(0x7f00000001c0)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
dup(0xffffffffffffffff)
poll(0x0, 0xfffffffffffffd9d, 0x3)
setreuid(0x0, 0xee01)
msgctl$IPC_STAT(0x0, 0x2, &(0x7f00000003c0)=""/153)
rename(0x0, &(0x7f00000000c0)='./file0\x00')
mkdir(&(0x7f0000000080)='./file0\x00', 0x0)
getsockopt$sock_int(r1, 0xffff, 0x8, &(0x7f0000000400), &(0x7f0000000440)=0x4)
msgrcv(r0, &(0x7f0000000200), 0x6e, 0x1, 0x0)


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000080)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendto$unix(r1, 0x0, 0x0, 0x8, 0x0, 0xfffffffffffffd4e)
recvfrom$unix(r0, &(0x7f0000001380)=""/72, 0x48, 0x802, 0x0, 0x0)


semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x8040691a, 0x0)
syz_emit_ethernet(0xe, 0x0)
setsockopt$sock_linger(0xffffffffffffffff, 0xffff, 0x80, 0x0, 0x0)
readv(0xffffffffffffffff, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
socket(0x0, 0x0, 0x0)
mknod(&(0x7f0000000040)='./file0\x00', 0x6000, 0xe02)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
chown(0x0, 0xffffffffffffffff, 0x0)
r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
setreuid(0xee00, 0x0)
r1 = getuid()
setreuid(0xee00, r1)
pwritev(r0, &(0x7f0000000080)=[{&(0x7f00000003c0)="1f", 0x1}], 0x1, 0x0)


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000200)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000240)=0xc)
setregid(0xffffffffffffffff, r1)
setgroups(0x0, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x200, 0x3ca420e3e2583708)


socket(0x18, 0x2, 0x0)
r0 = socket(0x18, 0x2, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1023, &(0x7f0000000000)=0x3, 0x4)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
socket(0x18, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(r2, 0xc0206921, &(0x7f00000001c0))
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r3, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x81}, {0x4c}, {0x16}]})
write(r3, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xfef3)
socket(0x2, 0x2, 0x0)
sysctl$hw(&(0x7f0000000000)={0x4, 0x1f}, 0x3, 0x0, 0x0, 0x0, 0x2)
mknod(&(0x7f00000000c0)='./file0\x00', 0x2, 0x4302)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r4 = socket(0x18, 0x3, 0x3a)
setsockopt(r4, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r4, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0xb}, 0xc)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x34}, 0x4, &(0x7f0000000080), 0x0, 0x0, 0x0)


writev(0xffffffffffffffff, &(0x7f0000000140)=[{&(0x7f0000000000)='\x00\x00\x00\t', 0x4}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x2, 0x0)
bind(r0, &(0x7f0000000000), 0x10)
setreuid(0xee00, 0x0)
r1 = getuid()
setreuid(0xee00, r1)
r2 = socket(0x2, 0x2, 0x0)
bind(r2, &(0x7f0000000000), 0x10)


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x14}, 0x4, 0x0, 0x0, &(0x7f00000010c0), 0x4)


setitimer(0x0, &(0x7f0000000200)={{}, {0x0, 0x7}}, 0x0)
getitimer(0x0, 0x0)


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(&(0x7f00000000c0)='./file0\x00', 0x4, 0x330, 0x0)
r0 = socket(0x2, 0x2, 0x0)
sendmsg$unix(r0, &(0x7f0000001a00)={&(0x7f0000000080)=@file={0x0, '\x00'}, 0x3, 0x0, 0x0, &(0x7f0000000180)=ANY=[], 0x18}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000140)=[{0x84}, {}, {0x40e}]})
syz_emit_ethernet(0x103e, &(0x7f0000001980)=ANY=[])


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x59}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0xe5, 0x0, 0x0, "43b2b0bf3e79036980220d348bba04ff4e629aa0"})
writev(0xffffffffffffffff, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xb, 0x0, 0x39)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x2})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x27}, 0x4, &(0x7f0000000000)="71f91e3471ac0058bc5a91501d942400b5e1a0757cb9af769c7afec37082", &(0x7f0000000080)=0x306, 0x0, 0x2e)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB], 0x9}, 0x0)
open(0x0, 0x0, 0x0)
sendmsg(r0, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)
socketpair$unix(0x1, 0x1, 0x0, 0x0)
recvmsg(0xffffffffffffffff, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r1 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
close(r1)
openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x10, 0x0)
r2 = kqueue()
r3 = socket$inet(0x2, 0x3, 0x0)
kevent(r2, &(0x7f0000000080)=[{{r3}, 0xffffffffffffffff, 0x5}, {{r3}, 0xffffffffffffffff, 0x4d, 0x1}], 0x200, 0x0, 0x0, 0x0)
socket$inet(0x2, 0x2, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x16}, 0x2, 0x0, 0x0, &(0x7f0000001440), 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
r1 = dup(r0)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000200)=[{0x35}, {0x45}, {0x7e}]})
syz_emit_ethernet(0x10a2, &(0x7f0000000280)=ANY=[])


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg$unix(r1, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="28000000ffff000001"], 0x28}, 0x0)
recvmsg(r0, &(0x7f0000000780)={0x0, 0x0, &(0x7f0000000180)=[{&(0x7f0000000280)=""/194, 0xc2}], 0x1, 0x0}, 0x42)
recvmmsg(r0, &(0x7f0000000040)={0x0}, 0x10, 0x842, 0x0)
execve(0x0, 0x0, 0x0)


sysctl$net_inet6_ip6(&(0x7f0000000000)={0x4, 0x18, 0x29, 0x7}, 0x4, &(0x7f0000000140), 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$net_inet_tcp(&(0x7f0000000000), 0x4, 0x0, 0x0, &(0x7f00000010c0), 0x4)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {0x0, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {}, {0x0, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffc000/0x1000)=nil}], './file0\x00'})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r0, 0x8210560b, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0})
sysctl$vm(&(0x7f0000000200)={0x2, 0x9}, 0x2, &(0x7f0000000240)="71a097", &(0x7f0000000340)=0x3, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0xb, 0x4e})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f00000000c0)=0x5)
writev(r0, &(0x7f0000000080)=[{&(0x7f0000000180)="fcffc883bc080089", 0x8}, {&(0x7f0000000000)='E', 0x1}, {&(0x7f0000000040)="b647d115dc2a4b", 0x7}], 0x3)


mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x1e57)
r0 = open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
readv(r0, &(0x7f00000003c0)=[{&(0x7f0000002580)=""/4086, 0xff6}], 0x1)
open$dir(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
execve(0x0, 0x0, 0x0)


mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x205310)
r0 = open(&(0x7f0000000000)='./bus\x00', 0x10000, 0x20)
poll(&(0x7f0000000180)=[{r0}], 0x1, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}, 0xff, 0x0, 0x3})
connect$unix(0xffffffffffffffff, 0x0, 0x0)
getsockname$inet(0xffffffffffffffff, 0x0, &(0x7f0000000000))
connect(0xffffffffffffffff, &(0x7f00000001c0)=@in={0x2, 0x0}, 0xc)
socket(0x2, 0x3, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000002a40)={0x0, 0x0, 0x0}, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x80146950, &(0x7f00000001c0))
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
sysctl$kern(&(0x7f0000000040), 0x1, 0x0, 0x0, 0x0, 0x0)
r2 = socket(0x18, 0x3, 0x3a)
setsockopt(r2, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MFC(r2, 0x29, 0x68, &(0x7f00000000c0), 0x5c)


connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
r0 = socket(0x2, 0x1, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f0000000180)={0x10, 0x0, [{&(0x7f00000a6000/0x3000)=nil, &(0x7f000059d000/0x4000)=nil, 0x4}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ffb000/0x4000)=nil, 0x80}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f000009b000/0x1000)=nil, 0x80}, {&(0x7f00002ff000/0x9000)=nil, &(0x7f00002cf000/0x2000)=nil, 0x8000000000000003}, {&(0x7f0000163000/0x1000)=nil, &(0x7f0000ffa000/0x3000)=nil, 0x6}, {&(0x7f000018d000/0x2000)=nil, &(0x7f000027f000/0x4000)=nil, 0xffffffff}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000374000/0x11000)=nil, 0x7}, {&(0x7f00001cd000/0xf000)=nil, &(0x7f00001cc000/0x2000)=nil, 0x5}, {&(0x7f00002ff000/0x1000)=nil, &(0x7f0000664000/0x3000)=nil, 0x80000000}, {&(0x7f00007ef000/0x2000)=nil, &(0x7f00004ca000/0x2000)=nil, 0x5b4}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000027000/0x3000)=nil}, {&(0x7f000012d000/0x3000)=nil, &(0x7f0000456000/0x2000)=nil, 0x100000001}, {&(0x7f00006f6000/0x1000)=nil, &(0x7f0000ff9000/0x4000)=nil, 0x300000}, {&(0x7f0000488000/0x1000)=nil, &(0x7f00004fc000/0x1000)=nil}, {&(0x7f0000394000/0x4000)=nil, &(0x7f00000af000/0x2000)=nil, 0x2c}, {&(0x7f000037c000/0x3000)=nil, &(0x7f00007b6000/0x1000)=nil}], './file0\x00', 0xffffffc1})
execve(0x0, 0x0, 0x0)
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x1000000000029, 0x3d, &(0x7f0000000040)="00000080", 0x4)
getsockopt(r1, 0x10000, 0x3b, 0x0, 0x0)
fchmod(r1, 0x18)
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
connect$unix(r0, &(0x7f0000000000), 0x10)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000100)=[{0x4}, {0x4c}, {0x8016}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x138, &(0x7f00000009c0)=ANY=[])


mprotect(&(0x7f0000ffe000/0x1000)=nil, 0x1000, 0x0)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x2b}, 0x4, &(0x7f0000000080), 0x0, 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x205b9a)
close(0xffffffffffffffff)
r0 = socket(0x18, 0x3, 0x0)
getsockopt$inet_opts(r0, 0x29, 0x65, 0x0, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000016c0)={&(0x7f0000000100)=@in6, 0xc, &(0x7f00000015c0)=[{&(0x7f0000000140)=""/32, 0x20}, {&(0x7f0000000200)=""/141, 0x8d}, {&(0x7f00000002c0)=""/4096, 0x1000}, {&(0x7f00000012c0)=""/92, 0x5c}, {0x0}, {&(0x7f0000001480)}, {&(0x7f00000014c0)=""/2, 0x2}, {&(0x7f0000001500)=""/152, 0x98}], 0x8, 0x0}}, 0x10, 0x0, &(0x7f0000001740))
execve(0x0, 0x0, 0x0)
mmap(&(0x7f0000fff000/0x1000)=nil, 0x1000, 0x0, 0x1812, 0xffffffffffffffff, 0x0)
socket(0x0, 0x0, 0x0)
r1 = socket$inet(0x2, 0x0, 0x0)
setsockopt(r1, 0x0, 0x7, &(0x7f0000000340)="15337ac0", 0x4)
pwritev(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f0000000240)="62dc", 0x2}], 0x1, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x3d}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
setrlimit(0x8, &(0x7f0000000980)={0x9, 0x54})
r3 = syz_open_pts()
close(r3)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000200)={0x0, 0x0, 0x4000c1, 0xfffffffd, "1026307e7be2df67de20888bda64612c3100"})
writev(0xffffffffffffffff, &(0x7f0000000500)=[{&(0x7f00000019c0)="6ec5ca9e2bd47c36bdb16672890ef460c5a5f0492241e8302528ee8d57ad6f3a0dc1302f5970945a0b7f3b1758cc7d843decf8ab98095f63509ed1e4ff59a98a7a0fe804b9ba039516e73de795b16ffc1a87eeee6e8a8be1fcd08bc29d266391fb343705af655984161ab3dd4c7c38b5c3b14ac9a8b5dd397439ebc60af2d3e0fcfd4d4c08c2339c87d1af47bcaf542622a9b4ffb2aa7eb23f727bb49368730051418bad8372c5c52f639ffc3cb0c6c2231e38fff3295ca9581af8b47636e016e2b69bd01ee7b7992d7b2b2868ea82ffbf4f17d393e60baf83cb8048dc4ec176fbb85b3d98d9b98ab56620fbb2caf135ecb58770229e27a824d43a1a5c074efea8c03ee7594801ce74459d42025b9b81cee42942cc6533ede133ba604c5d65d841f82381c42431fb5d8c671e40b8c05e67088472dbce478060ee19a39a5101b722e37cb55ab1c5cea5f147d01a8ae9b5c1ed01596e3c58bed4b5348d6561e5eea453f14f200ecaf66c47678fe3e12bd9874ea598493b728329aa3ea87b147274d74fed7b613b1582cc7b20253b73ef6d5fb6dd72972d2c8618400cd149ec2dc1cbddbc44740a19bf21231ffa0d51ece74b214d4d5ceae3c18d72332f1db59526b448ed2e3f21ec5fe8256715c8aff805eb26b710314a3b32f328068942fce6e44f2f8f54b1d22b1de46a40ae6cd67ae04d140415d25757f9051571f8c92b34ab1a88cd13b8c371cc23518842d9911d2c16a3e795b9f4cf4dd8650d1727eae1ca74ae2b7b9c4a6a4e50299c76e8fae16f7c7350cf93e0baca453efdd1d2ce60362b95fb7bac2a45b16455322193aece7366525459d3a4d33ba81680e0d82a1decb42d668178c4ab1d8872e008099b1f975416dc00", 0x274}], 0x1)
r4 = socket(0x18, 0x2, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
connect$unix(r4, &(0x7f0000000140)=@file={0x0, './file0\x00'}, 0xa)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
mlockall(0x1)
munlock(&(0x7f0000ffb000/0x4000)=nil, 0x4000)


open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x5, &(0x7f0000000040)=[{0x24, 0x0, 0x4}, {0x4f5, 0x0, 0x1}, {0x416}, {0x0, 0xfe, 0x1f, 0x9}, {0x1, 0xaa}]})
r1 = socket(0x2, 0x1, 0x0)
r2 = dup(r1)
setsockopt$sock_int(r2, 0xffff, 0x1004, &(0x7f0000000180), 0x4)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
mkdir(&(0x7f0000000040)='./file0\x00', 0x0)
setuid(0xffffffffffffffff)
unveil(&(0x7f0000000200)='./file0/file1\x00', &(0x7f0000000280)='x\x00')
syz_open_pts()
syz_open_pts()
socket(0x2, 0x2, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
pipe(&(0x7f00000000c0)={<r3=>0xffffffffffffffff, <r4=>0xffffffffffffffff})
readv(r3, &(0x7f0000000000)=[{&(0x7f0000000380)=""/143, 0x8f}], 0x1)
dup2(r4, r3)
r5 = semget$private(0x0, 0x2, 0x81)
semctl$IPC_RMID(r5, 0x0, 0x0)
kqueue()
execve(0x0, 0x0, 0x0)
select(0x40, &(0x7f0000000180)={0x0, 0x0, 0x0, 0x0, 0x3f}, &(0x7f00000001c0)={0xff}, 0x0, 0x0)
syz_emit_ethernet(0x138, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r6 = socket(0x2, 0x1, 0x0)
connect$unix(r6, &(0x7f0000000000), 0x10)


r0 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
chmod(&(0x7f00000000c0)='./file0\x00', 0x63)
setreuid(0xee00, 0x0)
r1 = getuid()
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000540)={<r2=>0xffffffffffffffff})
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000100)={0x0, 0x0, <r3=>0x0}, &(0x7f0000000180)=0xc)
chown(&(0x7f0000000080)='./file0\x00', 0x0, r3)
setreuid(0x0, r1)
unveil(&(0x7f0000000140)='./file0\x00', &(0x7f00000001c0)='c\x00')


openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x21)
writev(r0, &(0x7f0000000400)=[{&(0x7f0000000180)="9c0b291fec6a", 0x6}], 0x1)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
mprotect(&(0x7f0000ffc000/0x4000)=nil, 0x4000, 0x0)
getuid()
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000001c0)={0x0, <r2=>0x0}, 0xc)
setreuid(0xee00, r2)
r3 = socket(0x18, 0x3, 0x0)
setsockopt(r3, 0x1000000029, 0x24, &(0x7f0000000000)="5ab7776a", 0x4)
setsockopt$sock_int(r3, 0xffff, 0x800, &(0x7f0000000180)=0x2, 0x4)
syz_emit_ethernet(0x52, &(0x7f0000000080)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaabb86dd60000000001c000080000000000000000000000000000000ff020000000000000000000000000001"])
r4 = getuid()
setreuid(0xee00, r4)
r5 = getpid()
ktrace(0x0, 0x1, 0x4000072c, r5)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000140)={0x4, &(0x7f0000000180)=[{}, {0x60, 0x0, 0x0, 0x5}, {0x6, 0x4, 0x0, 0x4000003}, {0x2, 0x81, 0x2, 0x80000001}]})
write(0xffffffffffffffff, &(0x7f0000000000)="7696e5f3d1f18c", 0x7)
acct(&(0x7f0000000280)='./file0\x00')
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r6 = semget$private(0x0, 0x4, 0x128)
semctl$IPC_RMID(r6, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000080)={0x4, 0x2, 0x0, 0x1b}, 0x4, &(0x7f00000000c0)="84f0", 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
ftruncate(r1, 0xfffffffeffffffff)
mlock(&(0x7f0000007000/0xc000)=nil, 0xc000)


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
ioctl$FIOASYNC(r0, 0x8004667d, &(0x7f0000002d00)=0x9)
sysctl$kern(&(0x7f0000000040)={0x1, 0x59}, 0x3, 0x0, 0x0, &(0x7f0000000080)="4f1d4c6344b80ed788b6a4515248df3aa745bb992c574ab4cdf5587145812eab4a988f7fafd7a01d99776d988908cd186b51f34f8c15ffa0c685ad4116c783959eff4278384b4000384dbb1c2aaeff10b4135529a1da6fda67c67469d954be811b25ec5521559154c586eefff122009f659cd3e27e98a3241495005f102d9101d158284c0ee3250aa7c11042330de22a299ab00894fdc9bac6042d", 0xfffffc56)
mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x162226d0)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r1 = getpid()
fcntl$setown(r0, 0x6, r1)
shutdown(r0, 0x1)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
sysctl$net_inet_divert(&(0x7f0000000000)={0x4, 0x2, 0xf0}, 0x4, 0x0, 0x0, 0x0, 0x0)
r2 = socket(0x18, 0x2, 0x0)
setsockopt(r2, 0x1000000000029, 0x9, &(0x7f0000000080)="03000000", 0x4)
r3 = dup(r2)
ioctl$BIOCGETIF(r3, 0x4020426b, &(0x7f00000001c0)={""/16, @ifru_broadaddr=@un=@file={0x0, ""/62}})
setsockopt(r3, 0x1000000029, 0xc, 0x0, 0x0)
sysctl$vm(&(0x7f0000000000)={0x4, 0x2}, 0x4, &(0x7f0000000040)="c06d154be3aee5f8787f8b9cda7554335b763bb5deea5ccecb4d1b57a9f6fa18e47fc7b119db587e58811e666e84a806495b45c36164bd5b135280243ed0a01466056e93082876ba33ee8cf2b0b3907f236f38175101000000d7e39544aea098d19ee63d03cbf92380dbe904538135f09e408bbe17a54a364b04ee64b0ad54e6d4e38114ced38c328aff2e224239ba29eb0796e8c3e8344a2cd9e663bb21035ebf391872f3015c164556e4a5b966122c56edd85fc996f12fa1b92e47aa", 0x0, 0x0, 0xfffffffffffffe8f)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000480), 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r4, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000140)=[{0x28}, {0x74}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])
sendmsg(0xffffffffffffffff, 0x0, 0x0)
open(0x0, 0x800, 0x60)
r5 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r5, 0x80085761, &(0x7f00000000c0)={0x3})
r6 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000180), 0x1, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(r6, 0x80085762, &(0x7f0000000400)={0x3})


openat(0xffffffffffffff9c, &(0x7f0000000700)='./file0\x00', 0x200, 0x0)
openat$tty(0xffffffffffffff9c, &(0x7f00000002c0), 0x40, 0x0)
open(&(0x7f00000004c0)='./file0\x00', 0x80000000000206, 0xb)
chmod(&(0x7f0000000180)='./file0\x00', 0x23f)
setuid(0xee01)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x100, r0)


openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x1, 0x0)
r1 = dup(r0)
r2 = socket(0x2, 0x1, 0x0)
connect$unix(r2, &(0x7f0000000000), 0x10)
dup2(r1, r2)
execve(0x0, 0x0, 0x0)


r0 = socket$inet(0x2, 0x3, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x8, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x2, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, 0x0)
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000240)={0x2, &(0x7f0000000200)=[{0x81, 0x81, 0x0, 0x2}, {0x4}]})
writev(r1, &(0x7f0000000080)=[{&(0x7f00000001c0)="a065af7f1f000000000000", 0xb}], 0x1)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x40, 0x0)
open$dir(0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000), 0x2, 0x0, 0x0, 0x0, 0x0)
r2 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000140), 0x1, 0x0)
r3 = dup2(r2, r2)
ioctl$WSKBDIO_GETMAP(r3, 0xc0105715, &(0x7f0000000000)={0x0, &(0x7f0000000040)})
open$dir(0x0, 0x0, 0x0)
getuid()
r4 = socket(0x2, 0x2, 0x0)
r5 = getpid()
sendmsg$unix(r4, &(0x7f0000000440)={&(0x7f0000000000)=@abs={0x0, 0x0, 0x0}, 0x8, 0x0, 0x0, &(0x7f00000003c0)=ANY=[@ANYBLOB="14000000000000000700000000000000", @ANYRES32=r5, @ANYBLOB], 0x30}, 0x0)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
getsockopt(r0, 0x29, 0xa, 0x0, 0x0)


mknod(&(0x7f0000000000)='./bus\x00', 0x2000, 0x6380)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x6381)
r0 = open(&(0x7f0000000200)='./file0\x00', 0x102, 0x0)
open(&(0x7f0000000140)='./bus\x00', 0x0, 0x0)
writev(r0, &(0x7f0000000180)=[{0x0}], 0x1)


setregid(0xffffffffffffffff, 0xffffffffffffffff)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
r1 = socket(0x18, 0x2, 0x0)
getsockname$inet(r1, &(0x7f0000000080), &(0x7f0000000000)=0xfffffffffffffe22)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x18, 0x3, 0x0)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
sysctl$vm(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socket(0x2, 0x7, 0x8)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x20, 0x0)
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mkdirat(0xffffffffffffff9c, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
mkdirat(0xffffffffffffff9c, &(0x7f00000005c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
symlink(0x0, 0x0)
unlink(&(0x7f00000002c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
connect$unix(r2, &(0x7f0000000000)=@abs={0x682eb13985c518e6, 0x7, 0x1}, 0x8)
openat(0xffffffffffffff9c, &(0x7f00000006c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x8000, 0x0)
r3 = socket(0x800000018, 0x1, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}, 0x0, 0x8000000000000000})
bind$unix(r3, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
r4 = semget$private(0x0, 0x2, 0x86)
semget$private(0x0, 0x0, 0x84)
semctl$GETALL(r4, 0x0, 0x6, &(0x7f0000001240)=""/4096)
sendmsg$unix(r2, &(0x7f0000001700)={0x0, 0x0, 0x0, 0x0, 0x0, 0xfffffffffffffe4c}, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000140)=[{0x5}, {0x25}, {0x6}]})
syz_emit_ethernet(0x127, &(0x7f0000000200)=ANY=[@ANYRESOCT, @ANYRES32, @ANYRESOCT=r2, @ANYBLOB="465015d4a8f32e2b72c72c904caf69358226793ff1715a40755bfa88f79df678f2061c8face14f975011f0af789bee19780d6404f926050cd259bbfb14eda5864942"])
syz_emit_ethernet(0x0, 0x0)
socket(0x18, 0x0, 0x0)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "01000000d000"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x54}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000040), 0x3, 0x0, 0x0, &(0x7f0000000080)="4f1d4c6344b80ed788b6a4515248df3aa745bb992c574ab4cdf5587145812eab4a988f7fafd7a01d99776d988908cd186b51f34f8c15ffa0c685ad4116c783959eff4278384b4000384dbb1c2aaeff10b4135529a1da6fda67c67469d954be811b25ec5521559154c586eefff122009f659cd3e27e98a3241495005f102d9101d158284c0ee3250aa7c11042330de22a299ab00894fdc9bac6042d", 0x4)


sysctl$kern(&(0x7f0000001380)={0x1, 0xa}, 0x2, &(0x7f00000013c0)="03", &(0x7f0000001400)=0x1, &(0x7f0000001440), 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
sysctl$net_inet_carp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x2}, 0x4, 0x0, 0x0, &(0x7f00000010c0)="e1000000", 0x4)
r1 = syz_open_pts()
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000200)="8b8c7e5e4a7966dfcde82b0abb", 0xd}], 0x1)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0x400, 0x0, 0xffffdffc, 0xffffffbf, "ff000000000000000100"})
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r2=>0xffffffffffffffff})
recvmmsg(r2, &(0x7f0000000180)={0x0}, 0x10, 0x0, &(0x7f0000000500)={0x2007fffc, 0xa})
munmap(&(0x7f000000e000/0x400000)=nil, 0x400000)
close(r0)
poll(&(0x7f0000000040)=[{r1, 0x1}], 0x1, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
r4 = socket$inet(0x2, 0x2, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f00000001c0), 0x80, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x200000000000a, &(0x7f0000000000)="ea00005c00000000", 0x1)
setsockopt$inet_opts(r4, 0x0, 0xb, &(0x7f0000001500)='\t', 0x1)
ioctl$TIOCGETD(r1, 0x4004741a, &(0x7f0000000100))
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000080)=[{0x5}, {0x34, 0x0, 0x0, 0x3}, {0x8106}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "0e5f68cdd75751147708cb211e0202c5bf74de60"})
close(r1)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
ioctl$WSDISPLAYIO_GMODE(0xffffffffffffff9c, 0x4004574b, 0x0)
execve(0x0, 0x0, 0x0)
r2 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1, &(0x7f0000000240)=0x5, 0x4)
mknod(&(0x7f0000000040)='./file0\x00', 0x6000, 0xe02)
mknod(&(0x7f0000000000)='./bus\x00', 0x3a0914c44f7b202d, 0x504)
open(&(0x7f0000000040)='./bus\x00', 0x10005, 0x0)
ioctl$TIOCSETD(0xffffffffffffffff, 0x8004741b, &(0x7f0000000080)=0x7)
open(&(0x7f0000000040)='./bus\x00', 0x10005, 0x0)
r3 = open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
readv(r3, &(0x7f00000001c0)=[{&(0x7f0000000140)=""/5, 0x5}], 0x1)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000001440)={0xffffffffffffffff, <r4=>0xffffffffffffffff})
r5 = fcntl$getown(r4, 0x3)
setpgid(0x0, r5)
r6 = socket(0x18, 0x3, 0x0)
setsockopt(r6, 0x1000000029, 0x2a, 0x0, 0x7)
fcntl$setstatus(0xffffffffffffffff, 0x4, 0x0)
r7 = msgget$private(0x0, 0x0)
msgctl$IPC_SET(r7, 0x1, &(0x7f00000001c0)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}, 0x2, 0x0, r5, 0x0, 0x5e, 0x100000001, 0x8001, 0x9})
getsockopt$sock_linger(r1, 0xffff, 0x80, &(0x7f0000000040), &(0x7f0000000080)=0x8)
shutdown(r2, 0x2)
getpeername(r0, &(0x7f0000003840)=@un=@file={0x0, ""/57}, &(0x7f0000003880)=0x3b)


mknod(&(0x7f0000000180)='./file0\x00', 0x1000, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x1, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x2f2, 0x0)
poll(&(0x7f0000000080)=[{r0, 0x7d}], 0x1, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x2e92994837ed377e, 0x0)


syz_extract_tcp_res(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x11a}})
r0 = socket(0x18, 0x1, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
wait4(0x0, 0x0, 0x0, 0x0)
r1 = getgid()
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
getgroups(0x0, 0x0)
setregid(0xffffffffffffffff, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x5, 0x0, 0x0, 0x0, r1, 0x0, 0x7}})
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000140)=0xc)
syz_open_pts()
socket(0x0, 0x0, 0x0)
r2 = socket(0x18, 0x1, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
r1 = dup(r0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r1, 0x1000000000029, 0xd, &(0x7f0000000000)="ffdaf64c000000004f0527000000055e473e0000", 0x14)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
syz_emit_ethernet(0x4e, &(0x7f0000000280)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa86dd60004b0000182b00fe8000"/37])
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])
r1 = semget(0x0, 0x3, 0xc530b8543b69d24c)
semctl$GETVAL(0x0, 0x0, 0x5, 0x0)
shutdown(0xffffffffffffffff, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x802069c7, &(0x7f0000000240))
sendmsg$unix(r0, 0x0, 0x0)
setreuid(0xee00, 0x0)
semop(r1, &(0x7f0000000180)=[{0x4}, {0x3, 0x0, 0x1000}, {0x1, 0x5, 0x800}, {0x4, 0x800, 0x1000}], 0x4)
getuid()
open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffff9c, 0x80104277, &(0x7f00000000c0)={0x2, &(0x7f0000000080)=[{}, {0x3, 0x0, 0x0, 0x44}]})
sysctl$kern(&(0x7f0000000080)={0x1, 0x31}, 0x4000000000000004, 0x0, 0x0, 0x0, 0x0)
r3 = socket(0x18, 0x3, 0x0)
setsockopt$inet6_MRT6_ADD_MIF(0xffffffffffffffff, 0x29, 0x67, 0x0, 0x0)
preadv(0xffffffffffffffff, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r4 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r4, 0xc0106924, &(0x7f00000001c0))
ioctl$FIONREAD(r3, 0xc1206951, &(0x7f0000000100))


r0 = shmget$private(0x0, 0x4000, 0x0, &(0x7f0000ffc000/0x4000)=nil)
shmctl$IPC_RMID(r0, 0x0)
shmctl$IPC_SET(r0, 0x1, &(0x7f0000001240))


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x2})
r0 = socket(0x18, 0x3, 0x0)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xc)
r1 = socket(0x1, 0x1, 0x0)
close(r1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
socket(0x18, 0x1, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


r0 = open$dir(&(0x7f0000000040)='./file0\x00', 0xae828e137847f62, 0x0)
setrlimit(0x1, &(0x7f0000000000)={0xfffffffffffffffd, 0xffffffffffffffff})
ftruncate(r0, 0x20008002)
r1 = open$dir(&(0x7f0000000580)='./file0\x00', 0x40000400001803c1, 0x0)
ftruncate(r1, 0x20000064)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x100, 0x0)


socket(0x0, 0x0, 0x0)
connect$inet(0xffffffffffffffff, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000001140), 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r0, 0xc2585601, &(0x7f0000001180)={0xdead4110, 0x0, [{&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffa000/0x2000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffa000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff9000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000ff9000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}], '.\x00'})


r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000440), 0x1, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
bind(r1, &(0x7f0000000080)=@in6={0x18, 0x2, 0x3, 0x5}, 0xc)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0115, './file0\x00'}, 0xa)
mkdir(&(0x7f0000000640)='./file0\x00', 0x0)
chmod(&(0x7f00000000c0)='./file0\x00', 0x21e)
chdir(&(0x7f0000000140)='./file0\x00')
symlink(&(0x7f0000000200)='./file2\x00', &(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
open(&(0x7f0000000180)='./file0\x00', 0x6d84b028b6b26ff2, 0x0)
r2 = semget$private(0x0, 0x7, 0x3c0)
semop(r2, &(0x7f0000000080), 0x0)
rename(&(0x7f0000000540)='./file0\x00', &(0x7f00000006c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
semctl$GETPID(r2, 0x3, 0x4, &(0x7f0000000680)=""/8)
semop(r2, &(0x7f0000000280)=[{0x1, 0x7, 0x1000}], 0x1)
semop(r2, &(0x7f00000002c0)=[{0x4, 0x1, 0x1000}, {0x0, 0x420}, {0x1, 0x2}, {0x0, 0x3, 0x800}, {0x2, 0x2}, {0x0, 0x4}, {0x2, 0xfff8, 0x800}, {0x2, 0x49}, {0x4, 0x1, 0x1000}, {0x2, 0x7e7, 0x1000}], 0xa)
r3 = socket(0x18, 0x2, 0x0)
setsockopt(r3, 0x1000000000029, 0xa, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
setsockopt(r3, 0x1000000000029, 0xa, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000002540)={0x0, 0x0, 0x0}, 0x0)
r4 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000140), 0x1, 0x0)
ioctl$WSKBDIO_GETMAP(r4, 0x8010570e, &(0x7f00000001c0)={0x0, 0x0})
semop(r2, &(0x7f0000000100)=[{0x3, 0x801}, {0x2, 0x8}, {0x4, 0x1, 0x1800}, {0x3, 0x101}, {0x2, 0x3fd, 0x1800}, {0x0, 0xecb}], 0x6)
semctl$IPC_RMID(r2, 0x0, 0x0)
chmod(&(0x7f0000000440)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2)
getuid()
getpeername(r1, 0x0, &(0x7f0000000300))
fcntl$setstatus(r0, 0x4, 0x0)
clock_getres(0x7, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
mkdir(&(0x7f0000000180)='./file0\x00', 0x0)


ioctl$BIOCSFILDROP(0xffffffffffffffff, 0x80044279, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x5d4a)
mkdir(&(0x7f0000000040)='./file1\x00', 0x0)
mkdir(&(0x7f0000001540)='./file1/file0\x00', 0x0)
r0 = open$dir(&(0x7f0000000440)='./file1\x00', 0x0, 0x0)
r1 = openat(r0, &(0x7f0000000100)='./file0\x00', 0x0, 0x0)
unlinkat(r0, &(0x7f00000001c0)='./file0\x00', 0x8)
unveil(&(0x7f0000000140)='./file1\x00', &(0x7f0000000080)='c\x00')
openat(r1, &(0x7f0000000200)='./file1\x00', 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000200)="10", 0x1}], 0x1)
r2 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
getsockopt(r2, 0x0, 0x9, 0x0, 0x0)
open$dir(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)


r0 = syz_open_pts()
close(r0)
setrlimit(0x8, &(0x7f0000000980)={0xb, 0x54})
syz_open_pts()
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)


setuid(0xee01)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x8020699b, &(0x7f00000001c0))


r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000140), 0x1, 0x0)
ioctl$FIOSETOWN(r0, 0x8004667c, &(0x7f0000002900))


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
chdir(&(0x7f0000000240)='./file0\x00')
setreuid(0x0, 0xee01)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000080)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
bind$unix(r0, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
chmod(&(0x7f0000000280)='./file0\x00', 0x0)
r1 = socket$unix(0x1, 0x2, 0x0)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140))
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000100)=[{0x60}, {0xc0}, {0x2006}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f0000000080)={&(0x7f0000000100)={&(0x7f0000000740)=@un=@file={0x0, ""/559}, 0x231, 0x0, 0x0, 0x0}}, 0x10, 0x0, 0x0)
sysctl$net_inet_etherip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$vm(&(0x7f0000000000)={0x4, 0x2}, 0x2, &(0x7f0000000040), 0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f0000000140)="d820866700020000b876a16034c1f4e27679b78aecf8a8ded96987544ca9c5475e8a9fe042140900006f6aff03b422cb01e30ee863a9000500eb1400800000fb000000000000000000008000f63a5caa8932e5fce76307dc71a0047172d8674225a1bf069049f83479ecbed5934c12b1873d92d95753961367aab6b249a70fdff70bb6b8329cd2900a0a73ddd2adce6ad0e46d29a0fc", 0x96)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x18, 0x2, 0x0)
getpeername$unix(0xffffffffffffffff, &(0x7f0000000300)=@file={0x0, ""/257}, &(0x7f0000000440)=0x103)
ioctl$FIONREAD(r1, 0xc0206981, &(0x7f00000001c0))
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f0000000100)={0x10, 0x0, [{&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {&(0x7f0000198000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000433000/0x3000)=nil}, {&(0x7f0000626000/0x2000)=nil, &(0x7f0000686000/0x1000)=nil}, {&(0x7f0000da9000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000e0a000/0x2000)=nil, &(0x7f0000c17000/0x3000)=nil}, {&(0x7f0000b64000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil, 0xffff}, {&(0x7f00000da000/0x400000)=nil, &(0x7f00008bf000/0x1000)=nil}, {&(0x7f00008bf000/0x3000)=nil, &(0x7f0000af4000/0x13000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000601000/0x3000)=nil, &(0x7f0000b08000/0x1000)=nil}, {&(0x7f000064c000/0x2000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {&(0x7f0000633000/0x3000)=nil, &(0x7f0000518000/0x3000)=nil}], './file0\x00'})
socket(0x18, 0x1, 0x0)
r2 = socket$unix(0x1, 0x2, 0x0)
connect$unix(r2, &(0x7f0000000000)=@file={0xd1653077bafa0115, './file0\x00'}, 0x3)
r3 = socket(0x1, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r3, 0xc020699c, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x2, &(0x7f0000000080)=[{0x25}, {0x40e}]})
connect$unix(0xffffffffffffffff, 0x0, 0x0)
openat$null(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
rename(&(0x7f0000000080)='./file0\x00', &(0x7f00000000c0)='./file0\x00')


r0 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
lseek(r0, 0x2, 0x0)
getdents(r0, &(0x7f0000000040)=""/4096, 0x1000)


r0 = open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
r1 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
writev(r1, &(0x7f0000000340)=[{&(0x7f0000000000), 0x2cfea}], 0x1000000000000013)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x3, 0x10, r0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ff3000/0x2000)=nil, 0x41000}, {&(0x7f0000538000/0x2000)=nil, &(0x7f0000ffa000/0x3000)=nil, 0x200000000}, {&(0x7f00001f5000/0x4000)=nil, &(0x7f0000162000/0x4000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ff3000/0xa000)=nil}, {&(0x7f0000ff2000/0x3000)=nil, &(0x7f0000ff9000/0x3000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f0000ffa000/0x4000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f00001f4000/0x2000)=nil}, {&(0x7f0000002000/0x1000)=nil, &(0x7f0000ff9000/0x6000)=nil}, {&(0x7f0000ff6000/0x8000)=nil, &(0x7f000009f000/0x4000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000084000/0x1000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000161000/0x4000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00', 0x2})
r2 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000280), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r2, 0xc2585601, &(0x7f0000000000)={0x2, 0x0, 0x1, 0x0, 0x0})
setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)


shmctl$SHM_UNLOCK(0x0, 0x4)
r0 = shmget$private(0x0, 0x3000, 0xe79, &(0x7f0000ffd000/0x3000)=nil)
shmctl$IPC_STAT(r0, 0x2, &(0x7f00000000c0)=""/226)
shmctl$IPC_RMID(r0, 0x0)
sync()
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
shmctl$IPC_RMID(r0, 0x0)


writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(0xffffffffffffffff, 0x0, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
r3 = socket(0x2, 0x1, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)
r4 = dup(r3)
sendto$inet(r4, 0x0, 0x0, 0x0, 0x0, 0x0)
write(0xffffffffffffffff, &(0x7f0000000040)="04", 0xff9a)
setsockopt$sock_int(r2, 0xffff, 0x1023, &(0x7f0000000080), 0x4)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
close(0xffffffffffffffff)
syz_open_pts()
select(0x40, &(0x7f0000000000), 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000480)={0x4, &(0x7f00000000c0)=[{0x48, 0x0, 0x0, 0x24}, {0xc, 0x2}, {}, {0x6, 0x0, 0x72}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000140)=[{0x2}, {0x2d}, {0x40e}]})
syz_emit_ethernet(0x103e, &(0x7f00000001c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000300), 0x0, 0x0)
mknod(&(0x7f0000000000)='./bus\x00', 0x2000, 0x6380)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x6381)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
syz_open_pts()
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
syz_open_pts()
open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)
r1 = open(&(0x7f0000000240)='./file0\x00', 0x0, 0x0)
dup2(r0, r1)


r0 = socket(0x2, 0x2, 0x0)
sendmsg$unix(r0, &(0x7f0000001a00)={&(0x7f0000000380)=@file={0x0, '\x00'}, 0x3, 0x0, 0x0, &(0x7f0000000300)=ANY=[@ANYBLOB='\x00u'], 0x18}, 0x0)


openat$null(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaabb08004500001c0000000300ff9078ac1400bbffffffff4e214e22000890785fa4ae59e92892d0216c0582"])
syz_emit_ethernet(0x22, &(0x7f0000000080)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x14, 0x0, 0x1, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @broadcast}}}}})
sysctl$kern(&(0x7f0000000080), 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
mkdir(&(0x7f0000000080)='./file0/file0\x00', 0x0)
rename(&(0x7f0000000080)='./file0\x00', &(0x7f00000000c0)='./file0\x00')


r0 = semget$private(0x0, 0x3, 0x1)
semctl$GETNCNT(r0, 0x0, 0x3, &(0x7f0000000000)=""/240)
sysctl$net_inet_ipip(&(0x7f0000000100), 0x4, &(0x7f0000000140)="fa7f538e09f5b7fc2865b5c5", &(0x7f0000000180)=0xc, &(0x7f00000001c0)="d252ff025cdebc7c9b6cce9cc11a8165dc031e2289b1dd2e9d2ba83f952e729b38bed07acd476ca9e566d6d3f0ea0378efb2fc2aee7541e3d62699743d011fb3d9679c059ecbda936c388f72bf7d68d682acdbd16f88c2faec10b326cc127be35ce141498819111011422817041c133ef98217769f3a5a1a0f87b9238eac14b82ca97dfa812a171dcbe7bca817f73825beda0626a57fc798a7f7d7e14a2eeafeca7cf451bef7e477157a901a62d0af546ad825a6047298a3cca2fa5eb93943f0", 0xc0)
r1 = geteuid()
r2 = msgget(0x1, 0x200)
msgrcv(r2, &(0x7f0000000280)={0x0, ""/202}, 0xd2, 0x3, 0x1000)
msgrcv(r2, &(0x7f0000000380)={0x0, ""/4096}, 0x1008, 0x3, 0x1800)
link(&(0x7f00000013c0)='./file0\x00', &(0x7f0000001400)='./file0\x00')
semctl$IPC_RMID(r0, 0x0, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000001440), 0x8, 0x0)
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f00000014c0)={0x5, &(0x7f0000001480)=[{0x1f, 0x24, 0x9, 0x6}, {0x5, 0x4, 0x8, 0xffffff67}, {0x8, 0x1f, 0xc3, 0x5}, {0x9b6, 0x7, 0x32, 0xad48}, {0xfe01, 0x1, 0x5, 0x6}]})
utimes(&(0x7f0000001540)='./file0/file0\x00', &(0x7f0000001580)={{0x8000, 0x3}, {0x7f, 0x40}})
ioctl$BIOCGETIF(r3, 0x4020426b, &(0x7f00000015c0)={""/16, @ifru_vnetid})
openat$diskmap(0xffffffffffffff9c, &(0x7f0000001600), 0x0, 0x0)
ioctl$DIOCMAP(0xffffffffffffffff, 0xc0106477, &(0x7f0000001680)={&(0x7f0000001640)='./file0/file0\x00', 0xffffffffffffffff, 0x1})
sysctl$kern(&(0x7f00000016c0), 0x2, &(0x7f0000001700)='/', 0x0, &(0x7f0000001780), 0x0)
ioctl$WSKBDIO_GETBACKLIGHT(0xffffffffffffffff, 0x400c5711, 0x0)
r4 = semget$private(0x0, 0x4, 0x282)
semop(r4, &(0x7f00000018c0)=[{0x4, 0x1, 0x400}, {0x4, 0xfff9}, {0x2, 0x6, 0x1800}, {0x3, 0x1, 0x1800}, {0x2, 0x0, 0x1000}, {0x4, 0x1}, {0x1, 0x1f, 0x1000}], 0x7)
ioctl$VNDIOCCLR(0xffffffffffffffff, 0x80384601, &(0x7f0000001980)={0x0, 0x9, 0x0})
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000019c0)={0x0, 0x0, <r5=>0x0}, 0xc)
setsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000001a00)={0xffffffffffffffff, r1, r5}, 0xc)
msgctl$IPC_RMID(0x0, 0x0)
clock_getres(0x4, 0x0)
semctl$SETALL(r2, 0x0, 0x9, &(0x7f0000001a80)=[0x81, 0x1])
munmap(&(0x7f0000ffb000/0x2000)=nil, 0x2000)
open$dir(0x0, 0x20920, 0x0)


r0 = socket(0x1, 0x2, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x1002, &(0x7f00000000c0), &(0x7f0000000100)=0x4)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
writev(r0, &(0x7f0000000580)=[{&(0x7f00000001c0)='P', 0x1}], 0x1)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
select(0x40, &(0x7f00000000c0)={0x33b0}, 0x0, 0x0, 0x0)
r0 = openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$SPKRTONE(0xffffffffffffffff, 0x80085301, &(0x7f0000001540))
ioctl$VNDIOCGET(r0, 0xc4104603, &(0x7f0000000540)={'./file0\x00', 0x1, 0x3ff})
ioctl$WSMOUSEIO_SCALIBCOORDS(r0, 0x81205724, &(0x7f0000000240)={0xaf3, 0x9, 0x4, 0x8, 0x38356328, 0xfffffffb, 0x800, 0x10, [{0xba, 0x6, 0x40, 0x200}, {0x1ff, 0x8c7, 0x4, 0x20000000}, {0x80000001, 0xc2cd, 0x0, 0x69b2}, {0xffffffff, 0x3ff, 0x100, 0x3}, {0x100, 0xda7, 0x1000, 0x7}, {0x5, 0x6, 0xfff, 0x8001}, {0x101, 0x5, 0x8, 0x2}, {0x8000, 0x101, 0x1, 0x9e}, {0x1000, 0x0, 0xb7, 0x7}, {0xbea, 0x0, 0x100, 0x7}, {0x6}, {0x7ff, 0x6, 0x800, 0x981808b8}, {0x8, 0x1ff, 0x9, 0x6}, {0x7fffffff, 0x8, 0x6e}, {0x6, 0x0, 0x0, 0x2}, {0xd3, 0x7}]})
r1 = socket(0x18, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0206923, &(0x7f00000001c0))
r3 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
fcntl$dupfd(r3, 0x3, 0xffffffffffffffff)
ioctl$FIONREAD(r1, 0xc018696c, &(0x7f00000001c0))
r4 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r4, 0x8020699f, &(0x7f00000001c0))


faccessat(0xffffffffffffffff, &(0x7f0000000000)='./bus\x00', 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x4001, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
r2 = socket(0x2, 0x1, 0x0)
connect$unix(r2, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r1, 0xffff, 0x1023, &(0x7f0000000080), 0x4)
select(0x40, &(0x7f0000000000), 0x0, 0x0, 0x0)


recvmmsg(0xffffffffffffffff, &(0x7f0000000080)={&(0x7f0000000100)={&(0x7f00000006c0)=@un=@file={0x0, ""/529}, 0x213, 0x0, 0x0, 0x0}}, 0x10, 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = getpid()
ktrace(&(0x7f00000000c0)='./file0\x00', 0x0, 0x40000630, r0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x3f8d}, 0x10, 0x0, 0x0)
sendmmsg(r2, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r2, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
close(r2)
recvfrom$unix(r1, 0x0, 0x0, 0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0xfffffffa, 0x0, "0000c6f26461c094f4ffffffff00"})
readv(r1, &(0x7f0000000280)=[{&(0x7f0000000480)=""/131, 0x83}], 0x1)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
writev(r0, &(0x7f00000001c0)=[{&(0x7f00000002c0)='j', 0x1}], 0x1)


open(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000300), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f00000000c0)=[{0xc}, {0x87}, {0x6, 0x0, 0x0, 0xfffffffd}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x6e, &(0x7f0000000000)=ANY=[])


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x401})
r0 = syz_open_pts()
writev(0xffffffffffffffff, &(0x7f0000000180)=[{&(0x7f0000000000)="9da8e3e9ed", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
setuid(0xffffffffffffffff)
sysctl$net_inet_esp(&(0x7f0000000040)={0x4, 0x1e, 0x2, 0x1}, 0x4000000000000006, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x2, 0x2, 0x0)
bind(r1, &(0x7f0000000000), 0x10)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
socket$inet(0x2, 0x2, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xffffffffffffffff, 0x0, 0xffffffffffffffff})
sysctl$kern(&(0x7f0000000040), 0x7, 0x0, 0x0, 0x0, 0xfffffe88)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r2 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
poll(&(0x7f00000000c0)=[{r2, 0x6e}], 0x1, 0x0)
r3 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
writev(r3, &(0x7f0000000000)=[{&(0x7f0000000300)="c1", 0x1}], 0x1)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
dup(r0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
socket(0x18, 0x1, 0x0)
connect$unix(r1, &(0x7f0000000000), 0x10)
writev(r1, &(0x7f00000003c0)=[{0x0}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = dup(r0)
ioctl$BIOCSBLEN(r1, 0xc0044266, &(0x7f0000000100))
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCIMMEDIATE(r0, 0x80044270, &(0x7f00000000c0)=0x4)
readv(r1, &(0x7f0000000080)=[{&(0x7f0000000180)=""/15, 0xf}, {&(0x7f0000000040)=""/17, 0x11}], 0x2)
syz_emit_ethernet(0x42, &(0x7f0000000380)=ANY=[])
ioctl$BIOCSHDRCMPLT(r1, 0x80044275, &(0x7f0000000340)=0x8000)


sysctl$vfs_nfs(&(0x7f0000000380)={0xa, 0x11}, 0x3, &(0x7f0000000800)="15161665a565b678efcc1a16e750e50147e95193ee4a52bc22714f2d99406ed9e0046419cf774346a78b91f34134423ca6df2ee7e11498de3dd4ee42273a30c6221164bc556c759101a63dfd9a07da07c07c55632baa5f242d7aa5e0d7bce28d2bd5710c7cd74a77f4ddcdd98bbbb925fd0000000000a0c5b566e95cffd51dd54778f017805664c5222303ba4097947fdf6c8f6c89d172d855f83b18c1f2ddbe1f158b1305cf56c8030b73e0a97c164dba9af2df834846be2ec32e933527614df040bfa999b6eff82215b3768fe1947d3fafafa52d2e71c0b8782b7ba56af6ca070356cd633c34c22bdd9ca355290c3a46bc7487fecf09c65251b3516f00853822191627e6356313aa5aeff007467b9301a9049c8559f14e43b4028404ce30f9e683d7b2b3c55da53e4951756143a590eeed8f8f2e0de32bc1e63802c846a2c4474eb81df6fe04f246b2de4c0331166e9b25", 0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000780), &(0x7f00000007c0)=0xc)
pipe(&(0x7f0000000080)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f00000003c0)={<r2=>0x0, <r3=>0x0, <r4=>0x0}, &(0x7f0000000400)=0xc)
r5 = semget$private(0x0, 0x7, 0x3c0)
semop(r5, &(0x7f0000000180)=[{0x4, 0x3f, 0x1000}, {0x1, 0x9684}], 0x2)
semop(r5, &(0x7f0000000140)=[{0x3, 0x2, 0x800}, {0x2, 0x6}, {0x3, 0x8}, {0x2, 0x3ff, 0x800}, {0x1, 0xfffd, 0x1000}, {0x2, 0x6ff, 0x1400}, {0x0, 0x7ef, 0x1000}], 0x7)
sysctl$net_inet_tcp(&(0x7f00000001c0)={0x4, 0x2, 0x6, 0x14}, 0x4, &(0x7f0000000300), 0x0, 0x0, 0x0)
semctl$SETALL(r5, 0x0, 0x9, &(0x7f00000002c0)=[0x3, 0xfff])
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000280), &(0x7f0000000300)=0xc)
r6 = getuid()
r7 = getpgid(r2)
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000001c0)={{0x80, r3, 0x0, r6, r4, 0x0, 0x2}, 0x0, 0xfff, r7, r7, 0x10001, 0x8000, 0x6, 0xbdc2})
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f0000000580), 0x62)
setrlimit(0x0, &(0x7f0000000040)={0x7fffffffffffffff, 0x7fffffffffffffff})
semctl$GETALL(r5, 0x0, 0x6, &(0x7f0000000440)=""/248)
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f0000000240)={0x0, <r8=>0x0}, 0xc)
setreuid(r6, r8)
semctl$IPC_SET(r5, 0x0, 0x1, &(0x7f00000000c0)={{0x10200, 0x0, 0xffffffffffffffff, r6, 0x0, 0x44, 0xeb}, 0x2, 0x8, 0x7})
getegid()
accept$unix(0xffffffffffffffff, &(0x7f00000029c0), &(0x7f0000001800)=0xffb)
open$dir(&(0x7f0000000340)='./file0\x00', 0x2, 0x42)
socketpair(0x6, 0x8000, 0x38, 0x0)
setegid(r4)
kevent(0xffffffffffffff9c, &(0x7f0000000000)=[{{}, 0x0, 0x0, 0x0, 0x7}], 0x0, 0x0, 0x0, 0x0)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000000)={0x0, 0x100000001}, 0x10)
sysctl$kern(&(0x7f0000000000)={0x1, 0x42}, 0x6, 0x0, 0x0, 0x0, 0x0)
r9 = socket$inet6(0x18, 0x3, 0x0)
getsockopt(r9, 0x29, 0x28, 0x0, 0x0)
socket(0x11, 0x3, 0x0)


writev(0xffffffffffffff9c, &(0x7f0000000440)=[{&(0x7f00000001c0)="a0dd3dad6ba1364904b8095e4870a1448d", 0x11}], 0x1)
mknod(&(0x7f0000000500)='./file0\x00', 0x1000, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x8020699d, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x2, &(0x7f0000000700)=[{0x40, 0x0, 0x0, 0x1ff}, {0x6}]})
write(r0, &(0x7f0000000740)="76e5dead6f01f8607d2100000063", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000140)=[{0x25}, {0x50}, {0x812e}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ff3000/0x2000)=nil, 0x41000}, {&(0x7f0000538000/0x2000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f00001f5000/0x4000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ff3000/0xa000)=nil}, {&(0x7f0000ff2000/0x3000)=nil, &(0x7f0000ff9000/0x3000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f0000ffa000/0x4000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f00001f4000/0x2000)=nil}, {&(0x7f0000002000/0x1000)=nil, &(0x7f0000ff9000/0x6000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000002000/0x1000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000084000/0x1000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000161000/0x4000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000480)='\x00\x00\x00\x00', 0x4)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000280), 0x0)
mknod(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
sysctl$vm(&(0x7f0000000000)={0x6, 0x6}, 0x2, &(0x7f0000000040)="279857da", &(0x7f0000000080)=0x4, 0x0, 0x0)
ioctl$VMM_IOC_RUN(0xffffffffffffffff, 0xc2585601, &(0x7f0000000000)={0x2, 0x0, 0x0, 0x0, 0x0})
madvise(&(0x7f000008f000/0x3000)=nil, 0x3000, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {&(0x7f000002f000/0xd000)=nil}, {&(0x7f0000060000/0x2000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000ffb000/0x4000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000053000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0x0)
setitimer(0x0, &(0x7f0000001280)={{}, {0xfff}}, 0x0)
getitimer(0x1, &(0x7f0000000200))
sysctl$net_inet_tcp(&(0x7f0000000380)={0x4, 0x2, 0x6, 0x4}, 0x4, &(0x7f00000003c0)="c8bd43d44825c3b0173d3d45ff9dd63fc9a2ba92d573894998af54a28d6ae2f19f9c66b772ebdf436e6f56abde496c2ec08fdb9500fa4890216827407db9e68d95f899ec98113bd9eb53b8591f526ef4d7b72812c7e5d853b04d2a1c7a7bda397ea27389956470593a5ccf8dd4e394bc9af772bcabb316e5c000dceb511f675c9abe06bd4911c32d84de962e4d58cfae9c219e435c46a756ab2c4040659810baa700d7366513b752c7809f79e8ab949b061871d6d74fc36d034187edef3dbcd2bf52450393832a2179aef2c1a69bce8d7e1c56d144bf0f81daad34b7d23cfb510ff5db9accca785305081423a598839a2861472141afa2", &(0x7f00000004c0)=0xf7, &(0x7f0000000500), 0x0)
getgroups(0x1, &(0x7f0000000140)=[0xffffffffffffffff])
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000001c0)=[{}, {0x0, 0x0, 0x0, 0x1}, {0x6}]})
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x8981, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x8020691f, &(0x7f00000001c0))


clock_getres(0x0, &(0x7f0000000000))
sysctl$hw(&(0x7f0000000000)={0x4, 0x1f}, 0x3, 0x0, 0x0, 0x0, 0x2)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
sysctl$vm_swapencrypt(&(0x7f0000000000), 0x3, 0x0, 0x0, &(0x7f0000001380), 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{0x0, 0x0, 0x0, 0x8000000}, {0x5}, {0xefff, 0xc1}]})
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x3c, 0x40000000000002}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbdf13b9fd812eaa4e713048e69931929648", 0x14)


sendmsg$unix(0xffffffffffffff9c, &(0x7f0000000500)={0x0, 0x0, &(0x7f0000000300)=[{&(0x7f0000000040)="e86957d7d559d3e6e7e8cd053418f338e3fe7cbb1916900e5c433b400479152a3a8086a3975b1bdbb2410758faba1d884b05a479be81dd462fa622d98ee4252dfd", 0x41}], 0x1}, 0x0)
r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSKBDIO_GETENCODINGS(r0, 0xc0105715, &(0x7f0000000080))


socketpair$unix(0x1, 0x0, 0x0, 0x0)
getsockname(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
ioctl$TIOCSTOP(0xffffffffffffffff, 0x2000746f)
open$dir(&(0x7f00000000c0)='.\x00', 0x0, 0x0)
kqueue()
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
socket(0x18, 0x2, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r0 = open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {}, {0x2, 0x0, 0x0, 0x40804}]})
ioctl$DIOCMAP(0xffffffffffffffff, 0xc0106477, &(0x7f00000000c0)={0x0, r0})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x1, &(0x7f0000000140)=[{}]})
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$WSMOUSEIO_SCALIBCOORDS(0xffffffffffffffff, 0x81205724, 0x0)
madvise(&(0x7f000031b000/0x6000)=nil, 0x6000, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket$inet(0x2, 0x2, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x8020699f, &(0x7f00000001c0))
setsockopt$inet_opts(r2, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r0 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmat(r0, &(0x7f0000001000/0x3000)=nil, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffc000/0x3000)=nil, 0x1000}, {&(0x7f0000ff9000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffc000/0x1000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f0000ffc000/0x1000)=nil}, {&(0x7f0000003000/0x2000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x2000)=nil}], './file0\x00'})
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r1, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0, 0x1000})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x1, &(0x7f00000000c0)=[{0x4c}]})
mprotect(&(0x7f00003fe000/0xc00000)=nil, 0xc00000, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000132000/0x3000)=nil, &(0x7f00000a0000/0x1000)=nil, 0x80400000}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f000008c000/0x2000)=nil, &(0x7f00001f0000/0x1000)=nil}, {&(0x7f00001f0000/0x1000)=nil, &(0x7f0000001000/0x1000)=nil}, {&(0x7f0000132000/0x4000)=nil, &(0x7f00000b2000/0x1000)=nil}, {&(0x7f000008a000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {0x0, &(0x7f000002a000/0x3000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000e58000/0x4000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil}, {&(0x7f0000091000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000001000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000132000/0x1000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000008a000/0x1000)=nil}, {0x0, &(0x7f0000092000/0x3000)=nil}], './file0\x00'})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000800), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r1, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0})
r2 = socket(0x11, 0x3, 0x0)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f000002f000/0xd000)=nil}, {&(0x7f0000060000/0x2000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f000000f000/0x2000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f000000f000/0x4000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000053000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {&(0x7f000012f000/0x1000)=nil, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r3 = socket(0x18, 0x3, 0x3a)
setsockopt(r3, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r3, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x1}, 0x38)
r4 = socket$inet6(0x18, 0x2, 0x0)
ioctl$VMM_IOC_READREGS(r4, 0xc028756b, &(0x7f0000000000))
r5 = socket(0x11, 0x3, 0x0)
shutdown(r5, 0x586c01c4486dce6c)
ioctl$FIONREAD(r2, 0x8020690e, &(0x7f00000001c0))
r6 = socket(0x18, 0x3, 0x0)
r7 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
open(0x0, 0x0, 0x0)
select(0x0, 0x0, 0x0, 0x0, 0x0)
r8 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r8, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
ioctl$BIOCSETF(r7, 0x80104267, &(0x7f0000000440)={0x3, &(0x7f0000000140)=[{0x3c, 0x0, 0x0, 0xffffffff}, {0x81}, {0x40e}]})
setsockopt$inet6_MRT6_ADD_MFC(r6, 0x29, 0x1a, &(0x7f00000000c0), 0x5c)
r9 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r9, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x6c}, {0xc}, {0x8186}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000132000/0x3000)=nil, &(0x7f00000a0000/0x1000)=nil, 0x80400000}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f000008c000/0x2000)=nil, &(0x7f00001f0000/0x1000)=nil}, {&(0x7f00001f0000/0x1000)=nil, &(0x7f0000001000/0x1000)=nil}, {&(0x7f0000132000/0x4000)=nil, &(0x7f00000b2000/0x1000)=nil}, {&(0x7f000008a000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {0x0, &(0x7f000002a000/0x3000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000086000/0x3000)=nil, 0x1000}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil}, {&(0x7f0000091000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000001000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000132000/0x1000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000008a000/0x1000)=nil}, {0x0, &(0x7f0000092000/0x3000)=nil}], './file0\x00', 0x4})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r0 = open(0x0, 0x0, 0x0)
open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000401})
open(0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
syz_emit_ethernet(0xe, 0x0)
socket$unix(0x1, 0x0, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
bind(0xffffffffffffffff, 0x0, 0xa)
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x6, 0x4, 0x0, 0x0)
connect$unix(r1, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
chown(0x0, 0x0, 0x0)
chmod(0x0, 0x0)
setreuid(0x0, 0xee01)
r2 = shmget$private(0x0, 0x2000, 0x0, &(0x7f0000ffd000/0x2000)=nil)
shmctl$IPC_SET(r2, 0x1, &(0x7f0000000480)={{}, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0xfffffffffffffffc})
shmctl$IPC_RMID(r2, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000080)=[{0x24}, {0x7}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])


openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x2, &(0x7f00000001c0)=[{}, {0x6}]})
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r1 = socket(0x2, 0x1, 0x0)
bind(r1, &(0x7f0000000000), 0x10)
r2 = dup(r1)
listen(r2, 0x0)
r3 = accept$inet(r1, 0x0, 0x0)
r4 = socket(0x2, 0x1, 0x0)
connect$unix(r4, &(0x7f0000000000), 0x10)
r5 = dup(r4)
sendto$inet(r5, &(0x7f0000000100)="03c019b7e2399b388d3cc45f01364c934feea3d4c1fbf21dc5dab6090e154d84d22c5ff1da069dd0d4af159f8000000000000000c892a0", 0xff4c, 0x401, 0x0, 0x0)
readv(r3, &(0x7f0000000200)=[{0x0}], 0x1)


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x2, 0x0)
ioctl$FIONREAD(r0, 0x4004667f, &(0x7f0000000000))


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
unveil(&(0x7f0000000040)='./file0\x00', &(0x7f0000000080)='c\x00')
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


r0 = socket(0x2, 0x2, 0x0)
connect$unix(r0, &(0x7f0000000000), 0x10)
socket(0x2, 0xa000, 0xfe)
socket(0x18, 0x2, 0x0)
r1 = socket$unix(0x1, 0x1, 0x0)
r2 = open$dir(&(0x7f0000000640)='.\x00', 0x0, 0x0)
mknodat(r2, &(0x7f0000000040)='./file0\x00', 0x2000, 0x3ff)
r3 = socket$inet(0x2, 0x3, 0x0)
setsockopt(r3, 0x0, 0x3, 0x0, 0x0)
open$dir(&(0x7f0000000000)='./file0\x00', 0x80, 0x0)
setsockopt$sock_cred(r1, 0xffff, 0x1021, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
r4 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000180), 0x20, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r4, 0x80105728, &(0x7f0000000380)={&(0x7f0000000340)=[{0x20, 0x4}, {0x0, 0x5}], 0x2})


mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000300)='./file0/file0\x00', 0x0)
r0 = open$dir(&(0x7f0000000140)='./file0/file0\x00', 0x0, 0x0)
unveil(&(0x7f0000000080)='./file0/file0/../../file1\x00', &(0x7f0000000100)='r\x00')
mkdirat(r0, &(0x7f00000000c0)='./file0/file0/../../file1\x00', 0x0)


r0 = syz_open_pts()
flock(r0, 0x6)
r1 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
fcntl$setstatus(r1, 0x4, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
close(0xffffffffffffffff)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0xfffffffe, 0x0, "1a0001ad09fbda89b967688339204900"})
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
pwritev(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f0000000140)="a6", 0x1}], 0x1, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x59}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)
r2 = socket(0x18, 0x3, 0x3a)
setsockopt(r2, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r2, 0x29, 0x66, &(0x7f0000000100)={0x0, 0x1, 0x0, 0x5, 0x20003}, 0xc)
socket$unix(0x1, 0x1, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000240)={0x2, &(0x7f00000000c0)=[{}, {0x1, 0x0, 0x0, 0x2}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0xff0a, 0x0, 0x37)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000280)={0x1, &(0x7f0000000000)=[{0x44, 0x5}]})
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504600000000000000007000000331c13fecea10500fef96ecfc72fd3357ae3200000000039d2d236073705ae04be38164991f7c8cf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139b672f4d335d223e7d026ba8af630037282102000000720fd38bfbb7700900a872c881ea7fb53bd676d907c400000200361b1257aea8c5000020020000000000008abfba0900000008e371", 0x9a, 0x0, 0x0, 0x0)
socket(0x11, 0x3, 0x0)
socket$inet(0x2, 0x0, 0x0)
r0 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x0, &(0x7f0000000100)=0x20000, 0x4)
unlink(&(0x7f00000001c0)='./file0\x00')
select(0x40, &(0x7f0000000000)={0xffeffffffffffffd, 0x0, 0x0, 0x0, 0x0, 0xfffffffffffffffd}, 0x0, 0x0, 0x0)
mkdir(&(0x7f0000000100)='./file0\x00', 0x49)
setreuid(0xee00, 0x0)
r1 = getuid()
getuid()
chown(&(0x7f0000000200)='./file0\x00', r1, 0xffffffffffffffff)
unveil(&(0x7f00000000c0)='./file0/file0\x00', &(0x7f0000000080)='r\x00')
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r0, &(0x7f0000000000), 0x10)
sysctl$hw(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
r2 = open$dir(0x0, 0x0, 0x9)
linkat(0xffffffffffffffff, &(0x7f00000000c0)='./file1\x00', r2, &(0x7f0000000140)='./file0\x00', 0x5929d53439ccc69f)
getsockname$unix(0xffffffffffffffff, &(0x7f0000000000)=@abs, &(0x7f0000001200)=0x8)
write(r0, &(0x7f0000000240)="14bdfa5d1d34e2fecb284a6498307dcda9aec43050036123339a346f737850551408753f95b7688ad4c4e1dd5489e7bafc58d3e5823757ae8b630719ef187ccad995f13dbe19a6dd4e6902bd8297b0799b426aabe9fad9db6996571c6d9f8bb5d542c2148aa42be940970fe88d34d8f99afe7e7820237400000000008000000100"/138, 0xfc7e)
syz_emit_ethernet(0x1db, &(0x7f00000007c0)=ANY=[])
r3 = msgget$private(0x0, 0x208)
msgrcv(r3, 0x0, 0x0, 0x3, 0x0)
msgsnd(r3, &(0x7f0000000680)={0x3, "f7a8619f869a25f34420e4a75c92fd8ec1bae4c13e77be23fdf4b604bdd2438f1e889be0cbaef22d628beff1c7ffb6b1b0fecab04618b2ab5f5412ac6220b41dd5f473c9e933d7be137297790205d1db5b8ce197543d024540244b162eb840d98f05cdb607f30eba59aeba32817b9c48cbf7a281eaa52e5dc39d0f1dc41b08982da065351c8a3c281ba6de6f305d3c51122f4dff5a81712f8ccc488982caa94173dd7a145459592b4330eb19f38e4f3e5596619697ffa5cf2339585978460fef093658503c92e0b7484fb1b7011eade73834a999764e15a34aef86fe6f2b811a6e7424ad95e3ae176bf4039f98b5b832c22e8118358bf102148a842568be8c591a483e1d8c85be0eb1f0482569ea44688f105a2c01e96d95344dd87cda1aa1ab7f4dbf58f8ccac0c9086890b4d1be30ee5be863b11e970822b8327acfc60cdb00e6a428cb187b1d88233a6e7597fcf587e368a11ba01c44aedd6a4848ff7e7db7061cf8673f09645a4f5d0a1bfffdb0a1b7e9be95c962ca72eb66319a4ae3a623852d540ee0db54dfaa439f269d10122e8cd03b46f509816cbb580f8fa228f9b18e3a35728a1d25b8adb04d6cb72f9fc1b156433008b471871c9f90d66d736277a1471841e73b5b6c97449d0d0d6981da8af6f56640412ee800a475bda7c1c1ae779091a4ad81024d4b7fa354daa1ef2746fa158cae5af7be2c90f7da21d2388e7e81be076e4fc6a67c757b6539e5609369855c637e8f47d7d0172fb57b0bc4e8fec89e9d5ab4eb01890225d207ee93e3486338eced5fe22e1f8c2e2ce0047e7f2aa74d95b0789b35cdcceafb277e9e3332466582d970d0279e58de51e13dcc601e0d611ace0f4086ad17d01178d86a89554220efe321394395bfa8e74028ef992b75e67984ec38f321da82a195a60eb6103021b58a1b914a10d509c131defd6175c96ede8470fab89632e83fecbfeeb28fa7af7952be6137fd6f1328e0c4b8902e8cc6c270f45a0c62bfc7b890220011f1d955c294dd17953d9910debd96ec5bd0ee48ce1a12c2d955e7977b816ce2e493478649cbc079cf11c407dfff7eb92cfee83f6b22410f3accde3030cf15b781e487fb2df1cb31fa3bf20cffc628e603f8ee89159179f3ccd2fb9741a0497f48238860037ea4e999f9e8e9189a19857b35934c9717cec6a16e5975a9887320a1673c2a9654c099d3ee002366e3fd1042b7141f2ddeba5bff3c20af6d0637c6cd65b0cd7fb1a752856434e571cb83806f655ad1bdaaa3ea31bc26747aa571174b819f26f5008d1ee125acaa48be70b6e56a38fb4a2097a3b4847f5aa1ce2766d0da16d51eeac92fc812de7bd7be5a66f4cf780eee72c708a095078b0326a1767079ed2280254b774572945a029c3655953f45d8469de9acc1d8dcbfadeedfc5792c1c254dd79b8f8e31657739a48b2e712ec8ca0056e179177f5f30ceff9f407a834228481f93c81bca6db49da4219d68d90cd9e2695d27d94ed90f1a6947f370fafe54d956c061f47158a93f1361e7e6d8c53d1d8470f235099d4db3ba7940cc754b2feae21f8ce3425623977bb0f19f33153398d61b67165959755d4c448089c813778dbd26923c065be62a78db10c596045e18349ca8eb878a16ed505f66c8d2ae37bf0d9cc1f9bdda53547f13f031f2cf34d77dabc2ecbe0097d1c74ca3e92bcfcbd4bb00cf321d52d13bef8a8784de3b31a32e2b5fdceff2ffe4a028e3cc36f057e20fbc0aae603deecb3c164a91e66056a77c5e3ea92ff545efa89afc65d560fb62523f33bda6e29de18cec413b329afaa9bec24415b1199553f9833dae18ce421cbec819768692782193b82f6f074a04a94c79a03acb821644cfb4438f322ecf7ebf80f265625fa7cca145a3d45f33bc6efc2999b7ec18d43aabf6568b3e5f1ef8ddfe3003f9116d4d3273964fb4a4a6423be14a49c17296e2bd3342e6272e4335641815a31866594b7632588968512918f7a0f375279d9d9663e813444df607ccbd2e26a2d47092a106e5da9c6c1f355f8dc43e20433373dbd7afc5577e2d658998078fa0ecd1777bcee79f6afd4aedaa8f16fffb62cccfd773b657fd459bbae34a80b0b401c574bb683098491708ae0285e9edb6d4d4b8844c4351cc310d5567348b4f6445ca4df4506f8056aec0bb2c09f5f3b82cf1846c18f3bd1b5217b9d572ee9a66e43ce153be6087fd2627bcb4d3c778be7e0195aec30a28a95c29da29f4b3cf12df2584a28b154972c51a656d685c42db42220d969c76becff0748183fa7ba7cb1d534278b5ca777553f86f75da5715bf5339e06cdc72ee2981ecfcc5d5f3fd04a776004b144a9c1be30110bc929be1647c2770b29379a34377cd3a8fd959a564cdd0dca0f85bdeec097b039c4daf53304022345d2a57a24fd78c0a176f0ab7808666daef9cd94ef87ca1b64ba50f2dd90a622eb3c04f61678e74c8aac12152f65758e738a2847bedf193b3ef8ff37c484e28b2d51adef97af75ec7bb9f57d3ab81283937a84c85449b65e4d302f767fd64dd9c05410448ac166aa5762cc938011afe3d63e690789b5683bad800d2bb7a59e411918c922cbeed8e09bc70ee65d8ec6cdcd1b50dac1f09b2d14688335cef0815053d3d777b1ee3c08cc79cac19f9bde0038a72edb1e16aeb2e30564e8158e4b2b74c0be378803396051e3df3cd9c41db5b7414fbe1e5639696393f763ec896cdbadfff57c9de4ab28fc03d950143b423e421f8374df287342c26a97311918d921b78a74ee71d4b1873e19a7db35c41bd6f66c0c09766f47dde3608b95478f31d598822dfbf7626bfe72a53cab2463f53bda4f618d8d9b8a78dc05bc4967a93e4ef5b20c5c8c9d40950711da69650b8e0c9c9bae56b659a3cae457fdd7826ef050400d76d93f361f0ff8cda82a854cedc595afcd07f35f70405248d2cc4aaddead5a12a4e8dbe370176f568b196cd4fde9f89c214eb43c79b809f966ea53aad94e1191516d9dd2c6f1a05d1c79792b95619559cbdce29ef9efc86cd806446eb324c1c7e3009040914c0a11ee0a57585d60665ac83e09ea7e05ae8d5a6b24bade77a1e8e4d953e0f3dc08aecfe990dee1b6045e538da9ef8b01fe82c70604365b1ba8098b7074e7708c826a2514e2ee4d01ac1431ec43b05ba8e5e38a03d0686221a3bd9aeea2953e143b43a05be0bef03686dc2cefba277376c89b6452f2e6db006511e995c5096e3376729f139645b7095e7b70fb1d244e795ae2060e6e672ed3df4116d3542f194540d50376e0e9db9e490ea266600a5283c948c086ba2c6fd9019aa5e37fdaabfaed655d0231bf3b5138835962c8f41eaf0f6e8d4f9d4e602a3aa58cb8fd2929f472ff77a0a2652e6dc9955aa6b654301322d0d39c4fc70456b5a59e569e4848515295005917f4528a632bcf6cb5f97b3ecc173da6b0f59a76782f7c942de1cb1accbc74b7f9ea87ab92f2c2a5caee0e08448be49eda122f3589dbd6057be6f7577bc84367a1e23794c3d7e4aa8622995492e6523aa22e1ac1c26b4bb9ef7c11ac8bc52064c7ed1d1a63f37bb944dbfea2a732a68ce54c9a9d357c59cad365507079a1eb788e35251d20e986c8be394c319e0ea3b82b6f666e93d369e1d0ceab8c9202bd3bd3893d2440eb4a8c429c0cfda5cc6a4a0512be7321760a99c8cc09c42806f3e4e9b06749286228337f095387ffa9aec5ab700e310445e0e500088a26c0ead8f25a2b5bfcc5e9fc4211a0f30e4c70d6f90f92b56f7a3f6f99ddd56328e1cbfb59e93d8c9a0583ac91b50e899b9a24624a06f5a1ad9d0714aa502510eb945830a97baddf93139a7d30d1a69ad51432a6c762d339993de45f607790e0af6561045ec96f73c48f55b8b8a375d5bfc453cf87d55506f95ca6d775ea186ea46680f0aa93ff8e801b8ba955a46e81c03ae630451fa564bf0247cdcf9938b80751771c376bc7029efb890903b95e664ef241a7f0afe951cd27ac59fab02ec5ce9bc32286a778711382c4bfac912b77906f1d058da436abe1e1dadaed2181b0474145284b09f54845504e65c4c13b43d1608c58e6cac5b0cd5b12f8ed3ced3dcaf99fbc440b62796cac7440fd094e82e408c7f8465a89ff3a3ddcbc50712be534e34fe6b7e2ea31ff7d1da5d0a32f582d70a151b58558178d35aa662b6c61097600f826930a4147da30f669dc9f6ed5205a22a7cef7dbd81a39a0527b5afb9b0dd48bd3492d9141022f978a15b4a8a4027f39fd5425cec5296a2dac5701ebc62755c4ace67b28e069252b138c6e66573bbca327a1a02e7607af981fd63670894e7dae9e2a2fa751f7b2c4ed97bea840fc933516f6499afc8c7ad28e85e9b0b6e11735a948d2e77e14a40b56e01d4a8357b4eefec5b4c139337fce7eaf28a3d703559082cc7ac2500ed45d931fc92024587ae8d20d97a3937dc1aa18392911abbd734c05e71befe2d1b6e2dbb626891edbd89d58e7b472d10d3f155510cbb4db15e7c503ccd097ad3f268868ffec7e298b004e9aecc9a15e537587b66e9cacf4813464853b66eda240f05ddee635c0e80920afbdd20418734b1f10dc6ae52a94960a321402f953d79e0335e2641b4d09e87dab85e2dce300bc429f3167eb18d085ce7a92e692b269cbac17bf61668a87604bb70eb3dc1dd57d7139d663b27f51eb93ec4da24f80c18aa12dc9f17dd1469d80247601fe69418edb112565289e57a65d9893df66bc5f8ce2338a32fabe6f7a35e6bd7e9ed9e1daba7b8141f88beee9d8a59992c4424255be2923231daa6412e986d5a172df815356a12c2d57812775cf961f3ed49a428f07caadd19790609eff1a3cb5d16cbd097d0fdc8be5ec57ba9ffb23ff60258554d1fec2e73b43454b33ec52a7027c798f1a01768a819cc56ad02899a3e211e6afa1db4b78aae07e550e8c4b4f0016bafd52e94b1ad3738be2a8dcf4c9357d841fc0600ee6b9680f9d5e03796e8cf98e157abf8654900182ed38646268cd0ee27dd9e86fd597444641261f30173ea9409f7513432cc36f018858724b18f524f80673db1675d2889fab0e3bbb457e279afa2af4a823ec19de1a29546ea3923f6c70256627d90dcca1d6df5bedb9ad2ce5caba8e8a8b1ec1e5c53ee2cd39a77e430606ce08f0a74fc7aa8c004639c03b4af2edde005a93a7f8e1c187b00548c3d633184439ead5987dbbabe58d68d8d026bc61964f96814d7277d4a8630f9d4f816115d4f0f9d568440ba89ec0d7c19959052250adeb8b13469bdbb5b9cd6a528a4dedae203faaa5f53f53a2353147758fa75ab9147589569df1a11374673ee3e870e02da072a3f24f637f01c4a83b078ac4341670da9a947df66261cf4a063938b49ee3be72d2b98c823bd2502c0a2c6258058f560c828cc57aa6ac5a9605e1ea30fc54f978edab79213716454f31687018175045fb9f671eaade233eb49856c69d300d58c471f5015cc6af374a8692fbae1057ce12f2de526f5171417f6b17f792e179f0f016a522317c4d95aa577cfbb440dc31ba6ff93b5a97d9a395ba82c5eb1fb6cf7d2bd94479053789ae6e8951b2453daa61892c3edb533ec5f325385d08f0ecc84a55f1c7a85d912701e97e2a3cdd9716e985c4521cb04130851a03ee172e4673cb95ef263021b1562baceba6e1ef19dc78c0d21bc4d672e009cb89049772078aac06e9f49c0cdec945d4fced6580bcb9865efbadee5ea20124cec15b5cc3f7feac1de0e0b0e2b509d1c680c952b5146d3f0f98245dabd576323df0db0333510800ec"}, 0x1008, 0x800)


setrlimit(0x8, &(0x7f0000000980)={0xb, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0xf66f, 0x0, 0x9, 0x5577c532, "3cff8b7e08002b4600005900da64612c3300"})
writev(r0, &(0x7f00000004c0)=[{&(0x7f00000000c0)="bf0909b98732e43ae0ee63c33dd9cb7de67102649ec14a5cde", 0x19}], 0x1)


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
open$dir(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x1, 0x0)
fcntl$lock(r0, 0x7, &(0x7f0000000000))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000240)=[{0x60}, {0x25}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000140)=ANY=[])


r0 = socket(0x2, 0x4001, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x1, &(0x7f0000000040)="ee08665d19ac14d5e5134876f197a7728420aef6171504b1c3d4b3830c921bf0817a0000040000006a89dbdf", 0x2c)
getsockopt(r0, 0x0, 0x8, 0x0, 0x0)


mkdir(&(0x7f0000000040)='./file0\x00', 0x0)
unveil(&(0x7f0000000280)='.\x00', &(0x7f00000002c0)='r\x00')
chdir(&(0x7f0000000140)='./file0\x00')
unveil(&(0x7f0000000000)='./file0\x00', &(0x7f0000000080)='x\x00')
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)


pipe(0x0)
syz_open_pts()
syz_open_pts()
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x42, 0x400}, 0x3, 0x9, 0x0, 0x0, 0x6, 0x5, 0x4})
r0 = socket(0x18, 0x1, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
r1 = socket(0x18, 0x2, 0x1)
sysctl$hw(&(0x7f0000000040)={0x6, 0x1}, 0x2, &(0x7f0000000080)="80b5f33f55b1", &(0x7f0000001080)=0x6, &(0x7f00000010c0), 0x0)
r2 = socket(0x18, 0x2, 0x0)
setsockopt(r2, 0x1000000000029, 0xa, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
r3 = dup2(r2, r1)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f00000000c0)={0x0, 0x1ff}, 0x10)
sendmsg(r2, &(0x7f0000000ec0)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f00000000c0)={0x4, &(0x7f0000000180)=[{0xffff, 0x7, 0x2, 0x5}, {0x4, 0x8, 0x3, 0x1e}, {0x7, 0x1, 0x81, 0x3fc}, {0x1ff, 0x7, 0x4, 0x7}]})
syz_emit_ethernet(0x2a, &(0x7f0000000300)=ANY=[])
setegid(0xffffffffffffffff)
r4 = msgget$private(0x0, 0x0)
setuid(0xffffffffffffffff)
setsockopt(0xffffffffffffffff, 0x1000000000029, 0x40, &(0x7f0000000040)='X\x00\x00\x00', 0x4)
msgrcv(r4, &(0x7f0000000140)={0x0, ""/50}, 0x3a, 0xa8878760cb89a2fc, 0x1000)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
r5 = socket(0x1, 0x1, 0xfb)
ioctl$FIONREAD(r5, 0xc0287533, &(0x7f00000001c0))
accept$unix(r5, &(0x7f0000000000)=@file={0x0, ""/72}, &(0x7f0000000080)=0x4a)
open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
mmap(&(0x7f0000ffc000/0x2000)=nil, 0x2000, 0x6, 0x6010, 0xffffffffffffffff, 0x0)


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x1, 0x0)
ioctl$FIOSETOWN(r0, 0x8004667c, &(0x7f0000000080)=0x6)


pipe2(&(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff}, 0x0)
r2 = socket(0x18, 0x2, 0x0)
setgid(0xffffffffffffffff)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000380)={<r3=>0xffffffffffffffff})
getsockopt$sock_cred(r3, 0xffff, 0x1022, &(0x7f0000000280)={0x0, 0x0, <r4=>0x0}, &(0x7f0000000340)=0xc)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r4}})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4e}, 0x2, &(0x7f00000004c0)="71f91e3471ac0058bc6e91501d0200000000000000b59c7afec370825c8bace20edd09039c646ac19bb2f12974d31c5bd43529be92425c1affc2121e5b41e58491577103a322d4e26cf8e4cbb0d61ad1394bbefbabcb0d4061043aaeb6c20e6d61280a21f73284bfabb39797102175bb35bc32da658823f2a2", &(0x7f0000000180)=0x79, 0x0, 0x0)
close(r2)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0xfffffffffffffffe}], 0x0, 0x0, 0x0, 0x0)
r5 = socket(0x800000018, 0x2, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0xb0}, 0x5})
r6 = socket(0x18, 0x1, 0x0)
connect$unix(r6, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r6, &(0x7f00000000c0), &(0x7f0000000200)=0xc)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x1006, &(0x7f00000000c0)={0x0, 0x1ff}, 0x10)
setsockopt$sock_int(r5, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r5, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
r7 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r7, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r7, 0x80104267, &(0x7f0000000480)={0x3, &(0x7f0000000240)=[{0x54}, {0x20}, {0x6}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)
r8 = socket$inet6(0x18, 0x3, 0x0)
getsockopt(r8, 0x3a, 0x12, 0x0, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
writev(r2, &(0x7f0000000440)=[{&(0x7f0000000300)="6da1e6d4735a7336824e669f241e3440b4fcf35c735d8c6a509c932e0d9392dd5c719d7e54e259fd0b57798b46404488c1f31d703bf4918ef7a9f34dcc98b63c7043029a076c98290dcac78650c0bc16d7dba2779bb202ec4977f06e8f3a520ce8abacb562a5e20df450add474275029379c57cdd240927e5756affc0077f978e3966d54d8870adf117fe707a9d949dd27c8544d04a8d2b3a581ede61cfdaa82605eda31245495529fc8b8057e1ecdf4e75f0285e8529a0cd3c42ffc0616cf7258b79c45528d7def759c70cfff9ec142d8fc1bb0cffe108dbedf1612c622514b9c0d26e4ac40a2d9e3747175d553ae797627b9c7c8ba52616bcdcdce0b865777cba34c4a1a271a606a413cd7c647b9a52252d0896fdc3c49d72ea735544b0fba745bfb953124e4a71f", 0x129}], 0x1)
write(r0, &(0x7f0000000340)="97", 0x1)
select(0x40, &(0x7f0000000140)={0xffffffffffffffff, 0x7}, 0x0, 0x0, 0x0)
read(r1, &(0x7f00000000c0)=""/127, 0x7f)


select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x1, 0x0)
connect$unix(r0, &(0x7f0000000000), 0x10)


r0 = socket(0x18, 0x1, 0x79)
r1 = kqueue()
kevent(r1, &(0x7f0000000000)=[{{r0}, 0xfffffffffffffff8, 0x80, 0x1, 0x0, 0x6}], 0x7fff, &(0x7f0000000040)=[{{r0}, 0xfffffffffffffffb, 0x607329598ee0cd16, 0x80000082, 0x0, 0x8}, {{r0}, 0xfffffffffffffff9, 0x8, 0x1, 0x1ff, 0x2}, {{r0}, 0xfffffffffffffffb, 0x20, 0x20000000, 0x8, 0x2}, {{r0}, 0xffffffffffffffff, 0xb8, 0xfffff, 0x5, 0xbfb}], 0x8, &(0x7f00000000c0)={0x8, 0x5})
r2 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000100), 0x400, 0x0)
ioctl$WSMOUSEIO_SETMODE(r2, 0x80045726, 0x0)
readv(0xffffffffffffffff, 0x0, 0x0)
r3 = openat$zero(0xffffffffffffff9c, &(0x7f00000003c0), 0x8000, 0x0)
fcntl$setflags(r3, 0x2, 0x1)
r4 = semget(0x3, 0x1, 0x2)
semctl$SETVAL(r4, 0x0, 0x8, &(0x7f0000000400))
semctl$SETVAL(0x0, 0x1, 0x8, &(0x7f0000000440)=0x9)
ioctl$WSKBDIO_SETENCODING(0xffffffffffffffff, 0x80045710, &(0x7f0000000480)=0x4)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000004c0)={0x0, <r5=>0x0}, &(0x7f0000000500)=0xc)
setsockopt$sock_cred(r3, 0xffff, 0x1022, &(0x7f0000000540)={0xffffffffffffffff, r5, 0xffffffffffffffff}, 0xc)
getsockopt$SO_PEERCRED(r3, 0xffff, 0x1022, &(0x7f0000000580)={0x0, <r6=>0x0, <r7=>0x0}, 0xc)
r8 = openat$bpf(0xffffffffffffff9c, &(0x7f00000005c0), 0x40, 0x0)
fchown(r8, r6, r7)
r9 = semget$private(0x0, 0x2, 0x4b)
semctl$GETZCNT(r9, 0x1, 0x7, &(0x7f0000000600)=""/205)


seteuid(0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r0, 0x81206919, &(0x7f00000001c0))


ftruncate(0xffffffffffffffff, 0x0)
setrlimit(0x0, &(0x7f0000000000)={0x0, 0x1})
openat(0xffffffffffffffff, &(0x7f0000000300)='./file0\x00', 0x0, 0x0)
r0 = socket(0x11, 0x3, 0x0)
recvmmsg(r0, &(0x7f0000000440)={&(0x7f00000000c0)={0x0, 0x0, &(0x7f0000000580)=[{0x0}, {0x0}, {&(0x7f0000000000)=""/96, 0x53}], 0x3, 0x0}}, 0xb, 0x0, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
r1 = socket(0x11, 0x3, 0x0)
sendto$unix(r1, &(0x7f0000000000)="b1000502000000000000000001010000331c13fecea10500fef96ec0c72fd3355ae30200004e3003000000acf20b7804bec256699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5aa0410210000008700361b4cc702fac500002021fbfa0c0f00008abf3a2271a3f834371205d3660400"/177, 0xb1, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000340)={0x3, &(0x7f0000000140)=[{0x14}, {0x44}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000140)=ANY=[])


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
dup2(r1, r0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000a, &(0x7f0000000000)="ea00005c00000000", 0x1)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x60}, {0x1}, {0x1006, 0x0, 0x80}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
openat$vmm(0xffffffffffffff9c, &(0x7f0000000100), 0x20, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
madvise(&(0x7f00003e0000/0x3000)=nil, 0x3000, 0x4)
recvmsg(0xffffffffffffffff, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{0x0}], 0x1, 0x0}, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
msgsnd(0x0, 0x0, 0x401, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0xa}, 0x7, &(0x7f0000000080), 0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f00000000c0)="b10005010000009f0500070107000000331c13fecea70500fef96ecfc72fd3357ae30200004e3039d2d236acf20bf404be01000000f7c8cf5f882b297be1aa0504000051e2f0ad3ebbc257699a1f139b672f335c22db830c032bfa896443c32118210000720fd38bfb0000fd54c125191b1257aea8c500001602fbfe0c2300008abfba0900000008e37193f8343712050500b71dc000090005080000fca65361ba84913f0100"/177, 0xb1, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x1000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffc000/0x1000)=nil}], './file0\x00'})
ioctl$PCIOCREAD(0xffffffffffffffff, 0xc0187009, 0x0)
r2 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r2, 0xc2585601, &(0x7f0000000000)={0x0, 0x0, 0x1, 0x0, 0x0})
socket$inet(0x2, 0x2, 0x0)
mmap(&(0x7f0000ffd000/0x2000)=nil, 0x2000, 0x0, 0x10, 0xffffffffffffffff, 0x1)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x462, 0x0)
writev(r3, &(0x7f0000000000), 0x0)
r4 = msgget$private(0x0, 0x208)
ioctl$VMM_IOC_INFO(r2, 0xc0185603, &(0x7f0000000300)={0x7b, 0x0, &(0x7f0000000280)=""/123})
ioctl$VMM_IOC_RUN(r2, 0xc0205602, &(0x7f0000000380)={0x0, 0x0, 0x81, 0x2, &(0x7f00000016c0)={{0x40, 0x40, 0x2, 0x7, 0x3f, 0x0, 0x800}, {[0x1, 0xff, 0xffffffffffff8000, 0xe000000000, 0x2, 0x9, 0x3, 0x1f4, 0x0, 0x0, 0xe7, 0x800, 0xfffffffffffffffc, 0x0, 0x7f, 0x7ff, 0x2ac, 0x1000], [0x0, 0x0, 0x0, 0x0, 0x3ff, 0x81, 0x3, 0x6, 0x623000000000000, 0x6], [0x7fffffffffffffff, 0x2, 0xfffffffffffffff8, 0x6, 0x10002, 0x1], [0x0, 0x0, 0x0, 0x6, 0x2, 0x429b], [{0x2, 0x1, 0x1}, {0x400, 0x4, 0x3ff, 0x7}, {0x200, 0x5, 0x9}, {0x8, 0x6, 0x1000, 0x800000006e}, {0x0, 0x4e9280ea}, {}, {0xfffa, 0x9d7, 0x2}, {0x9, 0xfffe, 0x5b, 0x1}], {0x2, 0x70, 0x6ba, 0x100}, {0x2, 0x3}}}})
msgrcv(r4, 0x0, 0x0, 0x0, 0x0)
msgsnd(r4, &(0x7f0000000600)=ANY=[@ANYBLOB="020000000000c5c4cf3025"], 0xb9, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000340)={0x3, &(0x7f0000000240)=[{0x7, 0x0, 0x0, 0x9}, {0x64}, {0x3786, 0x0, 0x0, 0x36}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCLOCK(r0, 0x20004276)
setuid(0xffffffffffffffff)
ioctl$BIOCGRSIG(r0, 0x40044273, &(0x7f0000001700))


syz_open_pts()
flock(0xffffffffffffffff, 0x0)
flock(0xffffffffffffffff, 0x0)
syz_open_pts()
socket(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
msgctl$IPC_SET(0x0, 0x1, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
pwritev(r0, &(0x7f0000000380)=[{&(0x7f0000000440)="e9", 0x1}], 0x1, 0x3fffd)
r1 = open$dir(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
preadv(r1, &(0x7f00000004c0)=[{&(0x7f00000000c0)=""/99, 0xfffffd23}], 0x1, 0x0)
sendmsg(0xffffffffffffffff, 0x0, 0x0)
r2 = open(&(0x7f0000000080)='./file1\x00', 0x200, 0x0)
mmap(&(0x7f0000011000/0x2000)=nil, 0x2000, 0x0, 0x10, r2, 0x0)
mprotect(&(0x7f000000e000/0x4000)=nil, 0x4000, 0x3)
mlock(&(0x7f000000f000/0x4000)=nil, 0x4000)


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
socket(0x18, 0x3, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(r1, 0xc0206921, &(0x7f00000001c0))
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x81}, {0x4c}, {0x16}]})
write(r2, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xfef3)
r3 = socket(0x2, 0x2, 0x0)
sysctl$hw(&(0x7f0000000000)={0x4, 0x1f}, 0x3, 0x0, 0x0, 0x0, 0x2)
mprotect(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x1)
sysctl$vfs_nfs(&(0x7f0000000000), 0x7, &(0x7f00000025c0), 0x0, 0x0, 0xffffffffffffff2d)
dup2(r1, r0)
r4 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000280), 0x1, 0x0)
ioctl$WSKBDIO_SETBACKLIGHT(r4, 0x800c5712, &(0x7f0000000040))
ioctl$FIONREAD(r3, 0x80206919, &(0x7f00000001c0))
r5 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r5, 0x8020690c, &(0x7f00000001c0))


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
setreuid(0xee00, 0x0)
r0 = getuid()
chown(&(0x7f0000000180)='./file0\x00', r0, 0xffffffffffffffff)
r1 = getuid()
setreuid(0x0, r1)
chmod(&(0x7f0000000080)='./file0\x00', 0x2ea)
chdir(&(0x7f0000000100)='./file0\x00')
mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0xc0e99db6de761f86, 0x0)
open(&(0x7f0000000200)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x615, 0x0)
socket(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
rename(&(0x7f00000007c0)='./file0\x00', &(0x7f0000001040)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


preadv(0xffffffffffffffff, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000080)=[{0xc}, {0x34, 0x0, 0x0, 0xffffffff}, {0x8106}]})
syz_emit_ethernet(0x3e, &(0x7f0000000040)=ANY=[])


sysctl$hw(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x80, 0x0)
mkdir(&(0x7f0000000080)='./file1\x00', 0x0)
chmod(&(0x7f00000000c0)='./file0\x00', 0x63)
setreuid(0xee00, 0x0)
r0 = getuid()
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000580)={0x0, 0x0, <r3=>0x0}, &(0x7f0000000140)=0xc)
chown(&(0x7f0000000200)='./file0\x00', 0x0, r3)
setreuid(r0, r0)
chdir(&(0x7f0000000100)='./file0\x00')
mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0xc0e99db6de761f86, 0x0)
symlink(&(0x7f0000001340)='./file0\x00', &(0x7f0000001440)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f00000007c0)='./file0\x00', &(0x7f0000001040)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
setgid(0xffffffffffffffff)
readv(0xffffffffffffffff, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x0, 0x0)
setrlimit(0x0, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
getsockopt$sock_int(r2, 0xffff, 0x4, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000000)=[{&(0x7f00000005c0)}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r4 = socket(0x2, 0x1, 0x0)
bind(r4, &(0x7f0000000000), 0x10)


r0 = getpid()
setpgid(0x0, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r0})
pipe(&(0x7f00000001c0)={<r1=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r1, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r2 = fcntl$getown(r1, 0x5)
r3 = getppid()
setpgid(0x0, r3)
ktrace(0x0, 0x5, 0x128, r2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000000c0)=[{0x80}, {}, {0x8006}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x7fffffff, 0x0, {0x0, 0x3}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
getsockname(r0, &(0x7f0000000040)=@in6, &(0x7f0000000080)=0xc)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
close(r0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000080)=[{0x28}, {0x1}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000000)={0x3006ff, 0x0, 0x0, 0x0, "fabafa588fc0001000000010000000001000"})
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x3}, 0xc)
r1 = socket$inet6(0x18, 0x2, 0x0)
ioctl$VMM_IOC_READREGS(r1, 0xc028756b, &(0x7f0000000000))
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f00000003c0)="9b180bc3eb987aa9feb13ec99e805e6e840100780e03c231000000000004000000000036ba1bd82e86322c3eac80280712f838130e1f1f5504e927bd1269fce149d400d06a3f23616e77006e8836ed3d315eef8c826effff000000000000ebd669ecdb15cec53342366139d11a5ab5024d227a976f7a5334d900a0dad2b74f0100005d95dcbbc5cb3c72d000260526a3a80855f3c394639e29c5132580a944d5c26a625e7878005f2ab435cca257352828a76e53dea859ba346a762995e89423058a5c6318950bdcd08b9eca5d4d3eb5892ab3b4e8aa9b05000000e70000008324a00d2f5019383919525cb6f7e8574b2a374f07231b157d5bb7ad3b045c4724150d16e304c7bff16bceb7d956e658478f4df2f36557a1d9d9108d733338d72634935376f8a49507756f497752a2f8fd0559dcf6bdacf9429c25483a9275182602000000e3034868d0da3b5618eadc3c48796e5e35754771436218bdbdc9e20a623855e941dc0d72fc433aef100000006201788ce2b8802cb60eec6add5e94345f0bfb3428e95dcbe305c1e97dcf7025b78cad2cc1a0d0d787d2c9b93e27142bbafe3426f334b80f043ba9136d57eb4c353d46dd8143fa85d9b11f7475a7ad310c93df4effff00003e3bb073e334270f1db496d7679378ffffffffe6f4588f7966917a0b5ec8909db98323dbd668fb7dc5693a090e94691e8d000000368f29c86344671843a1f208261a720fdb791f83", &(0x7f0000000040)=0x210, 0x0, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000080)="eaef125c00000000", 0x8)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240), 0x0)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
sysctl$net_inet_esp(&(0x7f0000000000)={0x4, 0x2, 0x32, 0x4}, 0x4, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000180)={0x3, &(0x7f0000000700)=[{0x1c}, {0x81}, {0x6}]})
r1 = socket(0x18, 0x3, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r1, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x9}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x18, 0x400000002, 0x0)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r3 = socket(0x18, 0x1, 0x0)
r4 = dup2(r2, r3)
sendmsg$unix(r4, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {0x0, &(0x7f0000ffc000/0x4000)=nil, 0x4}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {}, {0x0, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffc000/0x1000)=nil}], './file0\x00'})
r0 = socket(0x18, 0x3, 0x3a)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000001200)=[{0x40, 0x0, 0x0, 0x1}, {0x1c}, {0x6, 0x0, 0x4}]})
writev(r1, &(0x7f0000000140)=[{&(0x7f0000000080)="35b5c242413c102608", 0x9}], 0x1)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
connect$unix(r0, &(0x7f0000000240)=@file={0x1, './file0\x00'}, 0xa)
r2 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r2, 0x8210560b, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0, 0xfffe})


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000240)={0x2, &(0x7f00000000c0)=[{}, {0x1, 0x0, 0x0, 0x2}, {0x6, 0xff}]})
r0 = socket(0x18, 0x0, 0x0)
socket(0x18, 0x3, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
sendto$unix(r0, &(0x7f0000000280)="8f18740aa1b84260041f5dc831ea51e492aa2c2f28bc5a4ff0d6ffd6e6e085911af659b02f32aeeb0cb44fba362d4306538739d8333e993e53320744880a90b64c29b2492fb20888b3c68d943a217d26e138c8492dde6d9b6b78e3e2834c97108856ca719b29158cad3ec68d1ffae7868b939e30c278b19bd120e51459e4609ccf50be9c3a37e9ce6b9e4983692380be4312e65af347aafe2610a4554ce077864bacebc14af9cf31c32b758eff21481407ddd9328607775a43258a5782644126c7efcb4576f1be189b0309c104b8cea1481766459850936eee03f4ce6e11042c0afad0f602d88201688647410016e1a6eef6", 0xf2, 0x404, &(0x7f0000000140)=@abs={0x0, 0x0, 0x2}, 0x8)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
sysctl$net_inet_ip(&(0x7f0000000300)={0x4, 0x2, 0x0, 0x25}, 0x4, &(0x7f00000013c0), 0x0, &(0x7f0000001480), 0x0)
setitimer(0x1, &(0x7f0000000280)={{0x2, 0x4}, {0x20, 0x9}}, &(0x7f00000002c0))
r2 = getuid()
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000140)={{0x1, r2, 0xffffffffffffffff, 0x0, 0xffffffffffffffff, 0x7, 0x3ff}, 0x0, 0x0, 0x100000001})
r3 = msgget$private(0x0, 0x54a)
msgrcv(r3, 0x0, 0x0, 0x0, 0x1400)
pipe(&(0x7f00000000c0)={<r4=>0xffffffffffffffff, <r5=>0xffffffffffffffff})
ioctl$FIOASYNC(r4, 0x8004667d, &(0x7f0000000140)=0x400)
fcntl$setflags(r5, 0x2, 0x1)
dup2(r4, r5)
read(r5, &(0x7f00000004c0)=""/203, 0xcb)
msgsnd(r3, &(0x7f0000001540)=ANY=[@ANYBLOB="02000000000040006d1d5fcb28d9fc2efd00080000006b5723bc77a73f2c7432a505995139959fe8249fcf0bc5a47faa0000"], 0x32, 0x0)
msgrcv(r3, &(0x7f00000001c0)={0x0, ""/14}, 0x16, 0x3, 0x800)
socket(0x1, 0x2, 0x0)
sysctl$vm(&(0x7f0000000200)={0x4}, 0x3, &(0x7f0000000040), 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x1a9}})
setreuid(0x0, 0xee01)
r6 = socket(0x18, 0x2, 0x0)
close(r6)
r7 = socket(0x800000018, 0x1, 0x0)
bind$unix(r7, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x3, 0x0)
connect$unix(r0, &(0x7f0000000000), 0x10)
sendto$unix(r0, 0x0, 0x0, 0x14, &(0x7f00000000c0)=@file={0x0, './file0\x00'}, 0xa)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f0000000140)=[{0x14}, {0x16}]})
write(r0, &(0x7f00000001c0)="d9537abde93d050cdd16b13f742a", 0xe)


ktrace(0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000140)={0x3, &(0x7f00000001c0)=[{0x7}, {0x3d, 0x0, 0x1}, {0x0, 0x0, 0x0, 0x7}]})
write(r0, &(0x7f0000000540)="76e5dead6f01f8607d2100000063", 0xe)
socket$inet(0x2, 0x2, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f00000002c0)='./file0/file0/..\x00', 0x0, 0x0)
r1 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
setitimer(0x0, 0x0, 0xffffffffffffffff)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000200)=[{0x0, 0x81}, {}, {0x80, 0x8c}], 0x3})
sysctl$vm_swapencrypt(&(0x7f0000000040)={0x7, 0x2, 0x2}, 0x3, &(0x7f0000000140), 0x0, 0x0, 0x0)
ioctl$WSMOUSEIO_GETPARAMS(r1, 0x80105727, &(0x7f0000000080)={0x0})
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
socket(0x18, 0x2, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
kqueue()
sysctl$hw(0x0, 0x0, 0x0, &(0x7f0000000000), 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f00000004c0)="4b218d114ca7cbdd5c6a2dddd227668e017145c65853de497dc18ddf59a105b91f005be73cf00b391289af5024c2f9cf6310c72a6df943cb04d89cd258aca3f6d5198417cc8efbfc5f10962b93f535443a40f2a652c64a9f4902b2a6158afbb6aa56e29f471b4d49178f3a22cd669126ba919570518e0fbb081d7cbfe4263801f636f8fea45f8b795a1e56f731c5d3fccfaba7e3b986e61a5401ac0d6632fd4afb25b3360ee9f7acc74263a6a947479373bec6a3aa6e5f7397f9e40f86ded6c437e4f2ae29dd9dc958bba2860fa3719d01", 0xd1}], 0x1)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
open(0x0, 0xa02, 0xc)
socket(0x0, 0x4, 0xc7)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
syz_emit_ethernet(0x138, 0x0)
r2 = msgget$private(0x0, 0x0)
msgsnd(r2, &(0x7f00000005c0)=ANY=[@ANYBLOB="0100000000000000bcff98a66a978da027ee68af00d1ed8f0f2b77e5ae7529b162945aaeba93ab1e0a8cefa732522d95550700000010c638dddce23c10ed7a5f245f42212612be75f87e545d03990554eb20558e0648dce5fc980663c99a08ef466c008f1c560b69f47f0c4582164954b7a099f6b0aafe43e1c76cc297349f151bb74e67e0591109b060702ee5b49d098e4bcfe6a5938dddb6b40715ea48817d5b8d8795c0fd67554723f6b51f7abed257871b35afdf329dded2b4374086e2b362f7"], 0x19, 0x800)
msgsnd(r2, &(0x7f0000000240)=ANY=[], 0x401, 0x800)
msgctl$IPC_RMID(r2, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000380)=[{0x20}, {}, {0x9006}]})
syz_emit_ethernet(0x56, &(0x7f00000000c0)=ANY=[])


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x35})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETD(r1, 0x8004741b, &(0x7f0000000140)=0x7)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
openat$diskmap(0xffffffffffffff9c, 0x0, 0x0, 0x0)
writev(r0, &(0x7f0000000100)=[{&(0x7f00000009c0)="8a29e29a863bf3d9349ef6e169488cea77bd55a00689bffc55da9f9bbaedadef5fe55c98134b439974b873468fbf58b27013b1d604ed13c664231eb0ccccdfa6570c043272fb296a2f125405088e18b72b437c26461497ad9405c6dcf297a0a9aa4ac9429042f4b24abec18a8b955a5caedbbdfdd3f57a70e8536c04d115f142082772e6512999cf99eabd1b1f84c8fa8cd47811c5dfa4ed9ea3ab92402abc3efb80c49eb7e373d92c76cb22da8cf546a947f112bc5dbeb03c89f72555ebb70034d486149f28b05da48864cbf2f7c5adc8f51e0c7f1de4408786f4159c42ac1411ee68d1eef5e1cc7c54cbb07e30124c0bf2548976b189347ad325cfc2a2494c71737b3163698895fee2ebdc4d85ad544659faafd27174e0c84d1a538c7b2c9df23323815df69f8dac0f0093b80b0bd1283d40848032f592373eb5d268efc5424418b0352a2ef31cb5eb68052ee6faa2a3ec67c55bbc933766e8d057ec92996cf05c877edcdac3fb20b7592c4a77c8df317619d5030352ce21067ddcc7186b01c64bed7cbaa249ad242cc627f4880d5ee8aab1dc3b27fc4b1887fc105d9deb87714ff263d1d4c37395242b9f5d87ac89100a512c4777e9c254b6d8bf4c6a168828d16dd4b5dc930117e7d6fb9ed6f7880ec306371718011c03169c2bdb0ebf530cc3772384f5013d86df463b4bcb2e5860863e3911a82010cd16fab2fc3c3c79b3193288c75e5f97d1320cb8cd882264b02369786616764d7b44871f84a5c7b7b082574bc120ab8745e4547e5c711a91a34c912d9924fa4ef6e5a45e852f7e3a79b42abef3ecf054a4bc727daf15d324cb9c871f401c13a0d5d794693ded5f85cb8687ee004f96c8d65cc93a9f797d112945fd8e079bd619d5bf53141af86628c48d0e2d20469dc786944c0c9c1fcbdc147722f169cd68aed042dd93f3d42f646becdd24d865912b5e6d8c049e765417caed753877698257795c011d37fd3157d4da4de26e3c29338116406355a6c6c563e6ce41ca2f4d7c5484eca7108f18ffb081aa5761b0e89b07c131bbb0a3084c2884d43d0329e2", 0x2f7}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f00000000c0)=[{0xc0}, {0x28}, {0x6}]})
syz_emit_ethernet(0x127, &(0x7f0000000040)=ANY=[])


r0 = kqueue()
kevent(r0, 0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff)


setreuid(0xee00, 0x0)
r0 = getuid()
seteuid(r0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = kqueue()
kevent(r2, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x80206919, &(0x7f00000001c0))


r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000100)=0x7)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
semop(0x0, 0x0, 0x0)
shmctl$IPC_STAT(0x0, 0x2, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r2 = shmget$private(0x0, 0x3000, 0x1dd, &(0x7f0000002000/0x3000)=nil)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000040)=[{0x28}, {0x25}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])
shmat(r2, &(0x7f0000001000/0x3000)=nil, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r4=>0xffffffffffffffff})
recvmmsg(r4, &(0x7f0000000480)={0x0}, 0x10, 0x0, &(0x7f0000000500)={0x2007fffc, 0xa})
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
kqueue()
r5 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r5, 0x0, 0x6, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x40005d4a)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x3, 0x0, 0x0, 0x0, 0x0, 0x60, 0x1}})
r6 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$VMM_IOC_INFO(r6, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})


mknodat(0xffffffffffffff9c, &(0x7f0000000400)='./file0\x00', 0x2000, 0x0)
r0 = syz_open_pts()
ioctl$TIOCCONS(r0, 0x80047462, &(0x7f0000000080)=0x7)
open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
select(0x40, &(0x7f0000000000), &(0x7f0000000040)={0x7fffffff}, 0x0, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x4002, 0x0)
dup2(r1, r0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000a, &(0x7f0000000000)="ea00005c00000000", 0x1)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea000001", 0x8)


utimes(0x0, &(0x7f0000000040)={{0x8000000000000000, 0x4000000000000004}})
r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$PCIOCREAD(r0, 0xc0107002, &(0x7f0000000040))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f00000001c0)=[{0x48}, {0x2}, {0x16}]})
writev(r0, &(0x7f0000000500)=[{&(0x7f0000000000)="af18a64591749e07ad1273f580a0", 0xe}], 0x1)


openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x1, &(0x7f00000000c0)=[{}]})
r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$PCIOCREAD(r0, 0xc0187009, &(0x7f00000000c0))


syz_open_pts()
mlockall(0x0)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$VNDIOCCLR(r0, 0x80106468, &(0x7f0000000b80)={0x0, 0x0, 0x0})


readlink(&(0x7f0000000040)='./file0\x00', &(0x7f00000000c0)=""/29, 0x1d)
open(&(0x7f0000000080)='./file0\x00', 0x70e, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x8, &(0x7f0000000280)={0x3, 0x0, 0xfffffffffffffffd, 0x100000001})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
openat$wskbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
poll(0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
socket(0x18, 0x3, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000000029, 0xb, &(0x7f0000000000)="ec000087", 0x4)
ioctl$WSKBDIO_COMPLEXBELL(0xffffffffffffffff, 0x80105702, &(0x7f0000000080)={0x1, 0x6, 0x400, 0x9})
dup(0xffffffffffffffff)
sysctl$vfs_ffs(&(0x7f0000000000)={0x4}, 0x3, 0x0, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
clock_gettime(0x3bd70b3292b7004, 0x0)


setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0x0, r0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x801169ac, &(0x7f00000001c0))


r0 = socket$unix(0x1, 0x5, 0x0)
getsockopt$sock_cred(r0, 0xffff, 0x1004, &(0x7f0000001840)={<r1=>0x0}, &(0x7f0000001880)=0xc)
getpgid(r1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000080)=[{0x2}, {0x1}, {0x6, 0x0, 0x0, 0x6d7}]})
writev(r0, &(0x7f0000000000)=[{&(0x7f00000001c0)="d2bc78b52324b9a50c786b26df53", 0xe}], 0x1)


openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
open$dir(&(0x7f0000000b80)='./file0\x00', 0x200, 0x0)
r0 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000300)='./file0\x00', r0, &(0x7f0000000c80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f0000000dc0)='./file0\x00', r0, &(0x7f0000000ec0)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mkdirat(r0, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
symlinkat(&(0x7f0000000fc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', r0, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000980)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000a80)='./file0\x00')
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
unveil(&(0x7f00000000c0)='.\x00', &(0x7f0000000180)='c\x00')


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x802069b5, &(0x7f00000001c0))
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000934, 0x0)
open(0x0, 0x0, 0x0)
r1 = socket(0x18, 0x2, 0x0)
dup2(0xffffffffffffffff, r1)
r2 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, r2, 0x0)
select(0x0, 0x0, 0x0, 0x0, &(0x7f00000000c0))
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000740)={0xffffffffffffffff, <r3=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000380)=""/93, 0x5d}, 0x3f8d}, 0x10, 0x0, 0x0)
sendmmsg(r3, &(0x7f0000000080)={0x0}, 0x10, 0x0)
close(r3)
socket$inet6(0x1e, 0x3, 0x0)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
pwritev(0xffffffffffffffff, &(0x7f0000000540)=[{&(0x7f0000000580)='F', 0x1}, {&(0x7f0000000180)='O3', 0x2}], 0x2, 0x0)
sysctl$net_inet_ah(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$vm(&(0x7f0000000000)={0x4, 0x2}, 0x7, &(0x7f0000000040)="c06d154be3aee5f8787f8b9cda7554335b763bb5deea5ccecb4d1b57a9f6fa18e47fc7b119db587e58811e666e84a806495b45c36164bd5b135280243ed0a01466056e93082876ba33ee8cf2b0b3907f236f38175101000000d7e39544aea098d19ee63d03cbf92380dbe904538135f09e408bbe17a54a364b04ee64b0ad54e6d4e38114ced38c328aff2e224239ba29eb0796e8c3e8344a2cd9e663bb21035ebf391872f3015c164556e4a5b966122c56edd85fc996f12fa1b92e47aa", 0x0, 0x0, 0xfffffffffffffe8f)
r4 = semget(0x2, 0x4, 0x300)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r5 = syz_open_pts()
close(r5)
ioctl$FIOASYNC(r5, 0x80047469, &(0x7f00000000c0)=0x5)
semop(r4, &(0x7f0000000140)=[{0x3, 0x0, 0x1000}, {0x3, 0x0, 0x1000}, {0x2, 0x81, 0x1800}, {0x0, 0x5, 0x1000}], 0x4)


pipe(&(0x7f0000000080)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
readv(r0, &(0x7f0000000040)=[{&(0x7f00000000c0)=""/71, 0x47}], 0x1)
ioctl$FIONBIO(r1, 0x8004667e, &(0x7f0000000000)=0x28)
write(r1, &(0x7f0000000140)="7809c19da343e772a2932d123663fc3f799ab839912c849335c4b5180ccfd18bebe717f026f321fe20156972a6c733c8e6c749c79039c17a11484ca79b478ebb53c7ec722ec8412af4716875d06c1f0869fa940e93cf4cb16dafd4aebc3ea43792289a60f58639914682b8f21eec34e62a3cc2386654280cc7aff972dfe0fd9d9bca88dbe31287f7f66f1c4b7b96ceb9749b279996b3c31396fa90d07c51842f4837bf4d5cd1c4fe8cca5cdb3421366879a8d3b4ac75784f51b9daa15b53770c43f33e24da6329227dcb55ca6379b04f252e05f75806a768967bc27c77e74d3521e536cb842187ebfb95babf18766db5a0b66ec9393cf148fd2b97b4713fbda6c92514198275cf811a970efebb36fa4ed309901fe65ca954d632d2bf79657431f207916df4a0751c63daad9baf5ade77b2593bd3ebec50a6a24427f9998c85b880d7498c674056d627d384286e76826582500ca05f900235cb8f40595a9ed7fdef9658f112d8478d6a77263c6a3fe7d2b97aee9d015b19e5a78ad2e52823a5bebb7d0a15546677e5372c78bfc0c4190b5b39bfaf3c64641c805e78205a9caf92d5b59fae4700000000000000000000000000fc9ff1e9c0ea1639d567ac4c385379e1bd7b31110665f6923d", 0xfffffe8c)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000140), 0x782, 0x0)
pwritev(r0, &(0x7f00000000c0)=[{&(0x7f0000000440)="3eb0114a8082b59df8c0ba93b08860a53f27f0ebf494b5a2045885a78660f89508bba10deaedb593baebfeed4f6c", 0x2e}, {&(0x7f0000000180)="36d69f4c7afcb720b1db87b715601b9788a46cae312cc36428bc9121b68e39c8e99235dccb0e3a90f039aa6b1246462cf98dc729c6a72e5095c564a468fc4b118ebe3661b593655791a1691b5805fbe9832b8b232e43c5751fec4dd59a60267f2b698406a129298d77cedf90b103679db0d1bb76985a891d5672c280b6fb6c94d6656f8be8b9f3296044a3069a1c3219fa404ee6e7fe827d821e938bbeaae1a2a070ee61ec30b60e21feade4165549e8b759a282e0044bd99b885471e81fa2b2d8cce01f06ae43f3e16cf726748055ce3807448edf4be3aac12e8f398fb4dcc3e5f2078c33e497361d77f45e90bacc84977191b6bae3400995c35effa32fd8c3db96743e9b94224bb93910a259743baf6239c04432", 0x115}], 0x2, 0x0)
execve(0x0, 0x0, 0x0)


open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x2, 0xb0)
pwritev(r0, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
open$dir(&(0x7f0000000580)='./file0\x00', 0x40000400001803c1, 0x0)
r1 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x5)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, r1, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
syz_emit_ethernet(0x3a, &(0x7f0000000100)={@local, @remote, [], {@ipv4={0x800, {{0x9, 0x4, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @multicast2, {[@timestamp={0x44, 0x10, 0x7, 0x3, 0x0, [{}, {}, {}]}]}}, @udp={{0x1, 0x3, 0x8}}}}}})


openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
open$dir(&(0x7f0000000b80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x200, 0x0)
r0 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000300)='./file0\x00', r0, &(0x7f0000000c80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f0000000dc0)='./file0\x00', r0, &(0x7f0000000ec0)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mkdirat(r0, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
symlinkat(&(0x7f0000000fc0)='./file0\x00', r0, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000980)='./file1\x00', 0x0)
syz_emit_ethernet(0x138, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
unveil(&(0x7f00000000c0)='.\x00', &(0x7f0000000180)='c\x00')
mkdir(&(0x7f0000000000)='./file0\x00', 0x0)


mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x1, 0x0)
setreuid(0x0, 0xee01)
ioctl$FIONREAD(r0, 0x8028698c, &(0x7f0000000000))


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff})
recvmmsg(r0, &(0x7f0000000000)={&(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000340)}}, 0x10, 0x1001, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000040)=[{0x2d}, {0x7c}, {0x9106}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x20}, {0x34, 0x0, 0x0, 0x800008}, {0x8186}]})
syz_emit_ethernet(0xe, &(0x7f00000000c0)={@broadcast, @remote})


open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000040)="94c79bd261e1e88e83beb11c0a3e154df77b5335bd1667d9fd77c59297b3cad0ade427f63f2912518a179b7c207bc5ba040a20b5c36bfaca54e49900550bad2f165552f266a6b12d4900c56a22e814223e67a3fdf5ae19bcbb5d0a815015db8752d03d1b08f84b4976ec52d4a82598424ed3a6a523a3591db0e862a2f4dd1168cb17845fff1fb5df5535cae3e20e2bdb92138d0c1b0720e1c121ccb763f092cd5dcaa3d901", 0x2cfea}], 0x1000000000000238)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206925, 0x0)
r0 = semget(0x1, 0x0, 0x0)
semctl$SETALL(r0, 0x0, 0x9, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, 0x0)
socket$inet(0x2, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000ff3000/0x2000)=nil, 0x2000, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, &(0x7f00000001c0))
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x6012, 0xffffffffffffffff, 0x2)
setrlimit(0x0, &(0x7f0000000980))
kevent(0xffffffffffffffff, &(0x7f0000000040)=[{{}, 0x0, 0x0, 0x0, 0x3}], 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11, 0x0, 0x2}, 0x4, &(0x7f0000000140)="fa101824", 0x0, 0x0, 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
madvise(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x6)
getpid()
getsockopt$sock_cred(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000000), &(0x7f0000000080)=0xc)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
r2 = dup(r1)
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{0x2c, 0x0, 0x0, 0xffeffffb}, {0x28}, {0x46, 0x3}]})
syz_emit_ethernet(0x36, &(0x7f0000000840)=ANY=[])
setpgid(0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x9})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r0, &(0x7f0000000580)=[{&(0x7f0000000080)='o', 0x1}], 0x1)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, "fadd2109969a3c812426344f0ca0b3ede703e3e0"})
readv(r1, &(0x7f0000000600), 0x10000000000002a5)
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
setitimer(0x0, &(0x7f0000000040)={{0xffffffff, 0x6}, {0xffffffff}}, 0x0)
utimensat(0xffffffffffffff9c, &(0x7f00000000c0)='./file0\x00', &(0x7f0000000100)={{0x8000, 0x8000000000000001}, {0x1, 0x6}}, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x33}, 0x6, 0x0, 0x0, 0x0, 0x0)


mknod(&(0x7f0000000280)='./bus\x00', 0x2000, 0xf19)
r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
r1 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
r2 = semget(0x1, 0x2, 0x304)
semctl$IPC_RMID(r2, 0x0, 0x0)
ioctl$WSKBDIO_SETDEFAULTKEYREPEAT(r1, 0x800c5709, &(0x7f00000000c0)={0x5, 0x9e75, 0x6})
ioctl$WSKBDIO_GETBELL(r1, 0x40105704, &(0x7f0000000100))
ioctl$SPKRTUNE(0xffffffffffffff9c, 0x20005302, &(0x7f0000000140)={0x5, 0x8})
ioctl$SPKRTONE(r0, 0x80085301, &(0x7f0000000080))
r3 = open(&(0x7f00000002c0)='./bus\x00', 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x138, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000002a40)={&(0x7f0000000000), 0x10, 0x0}, 0x0)
r4 = socket(0x2, 0x2, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000695000/0x3000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f00005fd000/0x1000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f00006a7000/0x1000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f0000218000/0x4000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f00002e5000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000376000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000041d000/0x1000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ff8000/0x4000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil, 0x3}], './file0\x00'})
getsockopt$SO_PEERCRED(r3, 0xffff, 0x1022, &(0x7f0000000300), 0xc)
ioctl$SPKRTUNE(r3, 0x20005302, &(0x7f0000000340)={0x9, 0x3})
writev(0xffffffffffffffff, &(0x7f0000000180)=[{&(0x7f0000000000)="9da8e3e9ed", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
open$dir(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r5 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r5, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
dup2(r5, r4)
sendmsg$unix(r4, &(0x7f0000002a40)={0x0, 0xffffffffffffff89, 0x0, 0x6e, 0x0, 0x700000000000000}, 0x0)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000240)="b1000504600000000000000007000000331c13fecea10500fef9ed06c7afd3357ae320b37b673039d2d236073705ae04be38164991f7accf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139b672f4d335d223e7d029d6ba8af630037282102000000720f70c1f5a472c881ea6e69e0bb76d907c400000200361b1257aea8c5000020020000000000008abfba09001d01800000ffffffff008000ff00"/177, 0xb1, 0x0, 0x0, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
close(r0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="9dd6981f1c370d89d86a1420", 0xc)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000002a40)={&(0x7f0000000000), 0x10, 0x0}, 0x0)
r0 = socket(0x2, 0x2, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffb}, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000695000/0x3000)=nil, &(0x7f00002ab000/0x4000)=nil}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000675000/0x4000)=nil, &(0x7f00006bd000/0x1000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f000006b000/0x3000)=nil, &(0x7f0000ff2000/0x2000)=nil}, {&(0x7f000026c000/0x2000)=nil, &(0x7f000007f000/0x1000)=nil}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000604000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f00000ca000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000009000/0x3000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000ffc000/0x1000)=nil}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil, 0x2}], './file0\x00'})
r1 = socket$inet(0x2, 0x3, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt$inet_opts(r1, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
dup2(r1, r0)
sendmsg$unix(r0, &(0x7f0000002a40)={0x0, 0xffffffffffffff89, 0x0, 0x6e}, 0x0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000000), 0x10000, 0x0)
munmap(&(0x7f0000400000/0xc00000)=nil, 0xc00000)
r1 = open(&(0x7f0000000000)='./file0\x00', 0x200, 0x0)
socket(0x1, 0x3, 0x3d)
mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0, 0x10, r1, 0x0)
r2 = syz_open_pts()
ioctl$TIOCSETD(r2, 0x8004741b, &(0x7f0000000100)=0x9)
ioctl$TIOCSETA(r2, 0x802c7414, &(0x7f0000000040)={0x9, 0x4, 0x1ff, 0x5, "5ca88b7b30195df95b34dd0746008fae10345476", 0x9, 0x2})
writev(r0, &(0x7f0000000340)=[{&(0x7f00000003c0)="601f939b0152d7a2242a5ec8a39aa3ece636351fc12c306773a842fc54c83c17f564f073a9f302e1e6e213c555fbe14f37dc8c8b0db2be99e3898edb8ae3d0f27b00a9ce86e45fe92fe678d70bac6fa35c742cafb38cd10543b653dd4a8d4f8d0a7ebd3639c905bf8e913f6b22272b011cf541f5adf2e17e35", 0x79}], 0x1)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000400)=[{0x4d, 0x0, 0x0, 0x8}, {0x5}, {0x812e}]})
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r4 = socket(0x18, 0x3, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r4, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
r5 = socket(0x18, 0x2, 0x0)
r6 = socket(0x18, 0x2, 0x0)
connect$unix(r5, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r7 = dup2(r5, r6)
setsockopt(r7, 0x1000000029, 0x23, &(0x7f00000000c0)="b211d7170d816684c8e360f2fa41c1a0946988b272d2dd3dc90142a84231a746e337b372e93320cff6669cbe7868de45ed3fc33719ca6df71ecec8a918458b2c10a1f8c66653b276e7aae9cb9b21f9982230f575295d48889c9a920796b2dd92fc8575680b37ba955d2c15e6d7c9198ed900ab006ddfb67869b51a2216114d1ece85f593e74035f5bc054eb1dbddf42a", 0x90)
sendmsg(r6, &(0x7f00000002c0)={0x0, 0x0, &(0x7f0000000900)=[{&(0x7f0000000340)="2f32cb043c8beed71b0498c45f4ba93b7a1c0fc07d77f1d6ff4dc50c27f3c1b2c4318089710c28bcd42e8fe1a4d3c664f775ee0f6846918a2d82ab9fd9d34e513020889dbe0e360a985f180acd8cf86f525bdc2bdc09ef64043ace6c84ee23b112e81ddbc21399cf0586bd47b6cd81d8f775b4cf094df33adcf6371b7fcb7389b80439d38e40136ce393a2c1597b", 0x8e}, {&(0x7f0000000400)="2086430dde82e4939c26f47e51e00ae81cc63ad9224dc8a024964bf48d4c5c08e05f2ea3b18c505f991b784d55a8732379e7bc225b02d98063c1df1d29b96612faf38fce7ac3af40fa90aa3f7c788138a9b93865d63718355e16cd03e1af700843962d6939169f639a62bb36ee2ed867c0305c74c7db77b8f6fa1d1d047fedf97a727e23aa92616032495bc12e87fca91dfe67958e8157928209118c0dd650ebae568774da3e6edd6f03d9f2173d7e0b0838e1e9fbf4eab532388a42c156e0100989a94a6faba01464cdf09e1f5d19c0bf49c4a336221d547f02", 0xda}, {&(0x7f0000000500)="bd81a02be3cd84f2dfb4a5377a20877d2ce8a17efc2eea640d0cfe49e641b9d80e4e85decb509713c2809d0a5281665aa12126e34cb009340a9edc3c442bf2039ff72658a4a7064eae9a61699d90ba78873c4a95401eaf493764c6c741ac98003f7589c0f5bf918aabf8e1f1d51a47924161e508f0ea160d2a3e2f71eef445f66406cb4e8aebc859acd7ddc6c9e22adf93a6b8fda8e9f1c5e1e97877235fc412a36a4fea59b211ccebe017f8c37ca34686da5751ec366321d67c8e3590c19e044227f0fc5194e872c6d21d9784dc5c5b5069cf9126edb56372293eb0bae772963077c9877a99d66905f768df4db9", 0xee}, {&(0x7f0000000600)="8613dc0dc5353947c6a5ac292c3b475bd736d07fc63b940d226a1a8c29c2f3a182b220b554daacafb3e335191ff34de1235d8f8d65747cee3b8eaae8bf1508293f6f0d7c8a5fce1e5adfb6141f0d5fca", 0x50}, {&(0x7f0000001480)="0e29b9f8980fd9aaa9c91915b4b2e0443466bb9f1db4211fb0535d3b507eb1ff65496ba283145bfde3c1770b8af779c2948300a4f68e8c84b22f96c84d1b816b4cfec999f2bedb56666d4525004c229188630e15214dfc7412bd6f763c9c87172c4b9b7d15418393ef71b46c86c6e437a77c0e14a66c44d9d7e1a55dac98d44be1bbb027d016761edfd03e17857ad0a934b76a1f8bfc31336487bd0bcb59ac66bf9027cb03d5c4a06bf1d6a06e9838fae3ee61b1e0bdee63fd6bbe318d4a00865b3170c79ba7f9ee08eb5bc34404f534371454bdec9fa5742b183798438c3008a8292f181a8c23e70f0c3730cbed2b967176616867a46dc7342b806ce93a48f8b7c6fa0a6f32bfada6b23e6b798bb3c6c6b260dc15ed8edb79dbb7d79655ddc311b8599a54c3eb9c3f37d18a24f1fcae2d50ae78af825e413f9d99865a10d645122b96c3259498de05198a38e974ffce1c5533d337cffb20815870e51d26a5c6388eb2bcb083b69904cc36f7b38732c736db95d3e2dc09c53f8771f3e20f86d9f73806b90c875d1af41e74e6be92a1c535f7c9db660088641224c6", 0x19b}], 0x5, 0x0}, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r0 = socket(0x18, 0x2, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000080)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
r2 = dup2(r1, r0)
getsockopt$sock_int(r2, 0xffff, 0x1021, 0x0, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000140)={0x2, &(0x7f0000000100)=[{}, {0x6}]})
syz_emit_ethernet(0xe, 0x0)
r4 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x80, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r4, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000080)=[{0x0, 0x3}, {0x45, 0xfffffffb}, {0x0, 0x80000001}, {}, {0x43, 0x2}], 0x5})
sysctl$net_inet_ipip(&(0x7f0000000680), 0x4, &(0x7f00000006c0), 0x0, 0x0, 0x0)


r0 = openat$pf(0xffffffffffffff9c, &(0x7f0000001440), 0x0, 0x0)
fcntl$lock(r0, 0x7, &(0x7f0000002640)={0x0, 0x0, 0xffeffffffffffffe})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000140)=[{0x1}, {0x2d}, {0x16}]})
write(r0, &(0x7f0000000100)="d9537abde93d050cdd16b13f742a", 0xe)


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
r1 = socket$inet(0x2, 0x2, 0x0)
close(r1)
r2 = socket$inet(0x2, 0x3, 0x0)
dup2(r0, r2)
syz_open_pts()
writev(0xffffffffffffffff, &(0x7f0000000240)=[{0x0}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt$inet_opts(r1, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0x8)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x1, 0x0, 0x0, 0x3}]})
setuid(0xffffffffffffffff)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x37}, 0x4, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x10, 0x0, 0x2e)
select(0x40, &(0x7f00000002c0)={0xfffffffffffffffa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80000001}, 0x0, 0x0, 0x0)
ioctl$BIOCSBLEN(r0, 0xc0044266, &(0x7f0000000040))
ioctl$FIOASYNC(r0, 0x8004667d, &(0x7f0000000140)=0x6)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
syz_emit_ethernet(0xe, &(0x7f0000000180)=ANY=[])
r1 = openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$SPKRTUNE(r1, 0x20005302, 0x0)
syz_emit_ethernet(0x12, &(0x7f0000000300)=ANY=[])


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
socket(0x18, 0x2, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f00000000c0)=""/49, 0x31}], 0x1)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1800000029"], 0x3e}, 0x0)
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)


faccessat(0xffffffffffffffff, &(0x7f0000000000)='./bus\x00', 0x0, 0x0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd02)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0x41946465, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000000)=[{0x48}, {0x20}, {0x8186}]})
syz_emit_ethernet(0x10a2, &(0x7f0000000080)=ANY=[])


openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040))
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x3}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


sysctl$kern(&(0x7f0000000000)={0x1, 0x47}, 0x4000000000000003, 0x0, 0x0, &(0x7f0000000140)="d820866700020000b876a16034c1f4e27679b78aecf8a8ded96987544ca9c5475e8a9fe042140900006f6aff03b422cb01e30ee863a9000500eb1400800000fb000000000000000000008000f63a5caa8932e5fce76307dc71a0047172d8674225a1bf069049f83479ecbed5934c12b1873d92d95753961367aab6b249a70fdff70bb6b8329cd2900a0a73ddd2adce6ad0e46d29a0fc7e238b92171971199fa988", 0x60)


ioctl$WSMUXIO_LIST_DEVICES(0xffffffffffffffff, 0xc1045763, &(0x7f0000000040)={0x0, [{}, {}, {}, {}, {}, {}, {}, {0x0, 0xc8}, {0x3}]})
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
write(r0, &(0x7f0000000140)="76e5dead6f01f8607d2100000063", 0xe)


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000640)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000080)=ANY=[@ANYBLOB="18000000ffff000001"], 0x18}, 0x0)
sendmmsg(r0, &(0x7f0000000480)={0x0}, 0x10, 0x0)
shutdown(r1, 0x0)


r0 = socket(0x18, 0x1, 0x0)
syz_emit_ethernet(0x32, &(0x7f0000000100)={@local, @broadcast, [], {@ipv4={0x800, {{0x7, 0x4, 0x0, 0x0, 0x24, 0x0, 0x0, 0x0, 0x1, 0x0, @remote={0xac, 0x14, 0x0}, @remote={0xac, 0x14, 0x0}, {[@ra={0x94, 0x6, 0x3}]}}, @icmp=@echo_reply}}}})
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
sysctl$net_inet6_ip6(&(0x7f0000000000)={0x4, 0x18, 0x29, 0x2b}, 0x4, &(0x7f0000000140)="cbf5e512c90affffff7f169774d0", 0x0, &(0x7f0000001140), 0x0)
mknod(&(0x7f0000000180)='./file0\x00', 0x2000, 0x202)
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0xb}, 0x2, 0x0, 0x0, &(0x7f0000000080), 0x0)
msgctl$IPC_SET(0x0, 0x1, 0x0)
sysctl$net_inet_ip(&(0x7f00000001c0), 0x4000000b, 0x0, 0x0, 0x0, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ktrace(0x0, 0x0, 0x14, 0x0)
open(0x0, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
ioctl$VNDIOCSET(r1, 0xc0384600, &(0x7f0000000000)={&(0x7f00000000c0)='./file0\x00', 0xcb, 0x0})
semctl$SETALL(0x0, 0x0, 0x9, 0x0)
clock_getres(0x0, 0xfffffffffffffffe)
sysctl$vm_swapencrypt(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
r2 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mmap(&(0x7f0000ffb000/0x2000)=nil, 0x2000, 0x2, 0x2812, 0xffffffffffffffff, 0x6)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000000)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40001104, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000040)="03000000", 0x4)


r0 = kqueue()
kevent(r0, &(0x7f0000000000), 0x1ff, 0x0, 0x89c, 0x0)
setuid(0xee01)
r1 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmctl$IPC_SET(r1, 0x1, &(0x7f0000000140)={{0x0, 0x0, 0x0, 0xffffffffffffffff, 0x140}})
shmctl$IPC_STAT(r1, 0x2, &(0x7f0000002040)=""/4083)


openat$bpf(0xffffffffffffff9c, &(0x7f00000003c0), 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10})
openat$vnd(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
socket(0x11, 0x3, 0x0)
r1 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x100, r1)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f0000000600)={&(0x7f0000000500)='./file\x00', 0x276, &(0x7f0000000540)='./file0/file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x81})
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r2 = openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r3 = getpid()
ktrace(&(0x7f0000000140)='./file0\x00', 0x1, 0x1424, r3)
fcntl$lock(r2, 0x8, &(0x7f0000000640)={0x3, 0x2, 0x8, 0x401, r3})
ioctl$FIOASYNC(0xffffffffffffffff, 0x8004667d, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)='\x00', 0x1}], 0x1)
r4 = socket$inet(0x2, 0x2, 0x0)
r5 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r5, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
dup2(r5, r4)
setsockopt$inet_opts(r4, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0x8)
setsockopt$inet_opts(r5, 0x0, 0xd, &(0x7f0000000240)="ea08000000000000", 0x8)


r0 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
setuid(0xffffffffffffffff)
fchmod(r0, 0x0)


r0 = kqueue()
kevent(0xffffffffffffffff, &(0x7f0000000280)=[{{r0}, 0xffffffffffffffff, 0xf5}], 0x0, 0x0, 0x0, 0x0)
r1 = open$dir(&(0x7f0000000140)='.\x00', 0x0, 0x0)
kevent(r0, 0x0, 0x0, &(0x7f00000001c0)=[{{r1}, 0xfffffffffffffffe, 0x41}], 0x2, 0x0)
kevent(r0, &(0x7f0000000000), 0x400, 0x0, 0xdb74, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000080)=[{0x7}, {0x1d}, {0x8006}]})
syz_emit_ethernet(0x1db, &(0x7f00000007c0)=ANY=[])


setuid(0xffffffffffffffff)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0xa, &(0x7f0000000480)='\x00\x00\x00\x00', 0x4)
setsockopt(r0, 0x1000000029, 0xd, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000100)=[{0x14}, {0x28}, {0x16}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f00000001c0)=ANY=[])


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000040)={&(0x7f0000000100)=[{0x3}, {}], 0x2})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x20}, {0x1}, {0x8186}]})
syz_emit_ethernet(0x4e, &(0x7f00000005c0)=ANY=[])


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x80000000})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
ftruncate(r1, 0x9)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x10, r1, 0x0)
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f0000000040)=0xfffffffc)
write(r0, &(0x7f0000000140)="feaefb66d909ec4d0da82748ae558f245ae995f911f70b39a831eeedd542a30b7694924a16e8f2ce1d9139db272e810b8f995f554138f306b1fd4e8434ef6e1147a90209341f2f75777933d6736442abbcef8a037d285e3ba4be08806490e84b1e80d6067243dcae3471ef2cfe3db56b62125caab7e4f018cfaa9a82bea85d6180b05ed81f5d1ed9b1c0cfaf8853e69a519f1fbc9cbb12edb464f64a72e88182b24b3dc1c184fa5ef023000f541b075f1c4c91", 0xffb8)


r0 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r0, 0x0)
accept(r0, 0x0, 0x0)
close(r0)
r1 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r1, &(0x7f00000002c0)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


writev(0xffffffffffffff9c, &(0x7f0000000440)=[{&(0x7f00000001c0)="a0dd3dad6ba1364904b8095e4870a1448d", 0x11}], 0x1)
mknod(&(0x7f0000000500)='./file0\x00', 0x1000, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x1e, 0x3, 0x0)
poll(&(0x7f0000000140), 0x0, 0x0)
close(0xffffffffffffffff)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000400)={0x0, &(0x7f00000003c0)})
openat$bpf(0xffffffffffffff9c, 0x0, 0x40, 0x0)
getsockopt$SO_PEERCRED(r1, 0xffff, 0x1022, 0x0, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000680), 0x0)
fcntl$getown(r1, 0x5)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
r2 = fcntl$getown(0xffffffffffffffff, 0x3)
setpgid(0x0, r2)
msgsnd(0x0, &(0x7f00000004c0)=ANY=[], 0xad, 0x0)
geteuid()
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$FIONREAD(r0, 0x8020699d, &(0x7f00000001c0))


open(&(0x7f0000000000)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`\x00', 0x200, 0x0)
r0 = openat$diskmap(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$DIOCMAP(r0, 0xc0106477, &(0x7f0000000080)={&(0x7f0000000040)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`\x00', r0})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000240)=[{0x4}, {0x64}, {0x6}]})
syz_emit_ethernet(0x1019, &(0x7f0000000400)=ANY=[])


r0 = open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x3, 0x10, r0, 0x0)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
sysctl$kern(&(0x7f0000002240), 0x2, 0x0, 0x0, 0x0, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r0, 0x8020690c, &(0x7f00000001c0))


pipe(&(0x7f0000000080)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
readv(r0, &(0x7f0000000040)=[{&(0x7f00000000c0)=""/71, 0x47}], 0x1)
write(r1, &(0x7f0000000140)='x', 0x1)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {0x0, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {&(0x7f000062f000/0x1000)=nil}, {0x0, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000742000/0x4000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffc000/0x1000)=nil}], './file0\x00'})
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x0, &(0x7f0000001200)})
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000080)="35b5c242413c102608", 0x9}], 0x1)
setsockopt(0xffffffffffffffff, 0x29, 0x6c, &(0x7f0000000040), 0x4)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r1, 0x8210560b, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0, 0xfffe})


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
chdir(&(0x7f0000000240)='./file0\x00')
rename(0x0, 0x0)
setreuid(0x0, 0xee01)
mkdir(&(0x7f0000000100)='./file1\x00', 0x0)
chflags(&(0x7f0000000040)='./file1\x00', 0x0)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
syz_emit_ethernet(0x4e, 0x0)
sendto(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f00000001c0)={&(0x7f0000000100)='./bus\x00', 0x5, 0x0})


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
r3 = socket(0x2, 0x2, 0x0)
sysctl$hw(&(0x7f0000000500)={0x6, 0x1c}, 0x2, 0x0, 0x0, 0x0, 0x0)
dup2(r1, r2)
setsockopt(0xffffffffffffffff, 0x6, 0x4, &(0x7f0000001100)="26b80000", 0x4)
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
connect$unix(r3, &(0x7f0000000000), 0x10)


mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x412dff)
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, &(0x7f0000000440)={&(0x7f0000000280)='./bus\x00', 0x1000, &(0x7f00000002c0)='./bus\x00', 0x6})
r0 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
recvmsg(0xffffffffffffffff, &(0x7f00000025c0)={0x0, 0x0, &(0x7f0000002540)=[{&(0x7f0000000600)=""/4094, 0xffe}], 0x1, 0x0}, 0x0)
preadv(r0, &(0x7f0000000300)=[{&(0x7f00000000c0)=""/104}, {&(0x7f0000000140)=""/192}, {&(0x7f0000000340)=""/175}, {&(0x7f0000000000)=""/18}], 0x10000000000002b8, 0x0)


ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x2801)
r0 = open(&(0x7f0000000280)='./bus\x00', 0x0, 0x0)
close(r0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x2, &(0x7f0000000040)=[{0x20, 0x0, 0x0, 0x3f}, {0x6}]})
syz_emit_ethernet(0x40, &(0x7f0000000180)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaaaaaa080600000000060e0000aaaaaaaaaabb2fc407306cadfdf36747f3408698ffffffffffffbcb544a6377eb25c9db9ba9485fdffa2"])
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
mknod(&(0x7f00000003c0)='./file0\x00', 0x8000, 0x0)
pipe(&(0x7f00000000c0))
mknod(&(0x7f0000000280)='./file1\x00', 0xc102, 0x9e5f)
r2 = semget(0x1, 0x7, 0x0)
semctl$IPC_STAT(r2, 0x0, 0x2, &(0x7f0000000480)=""/251)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
open$dir(&(0x7f0000000400)='./file0\x00', 0x0, 0x0)
r3 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
readv(r3, &(0x7f0000000380)=[{&(0x7f00000000c0)=""/183, 0xb7}], 0x1)
open(&(0x7f0000000040)='./file1\x00', 0x0, 0x13a)
r4 = open$dir(&(0x7f0000000440)='./file0\x00', 0x10000, 0x191)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
syz_emit_ethernet(0x66, &(0x7f0000000080)=ANY=[@ANYBLOB="ffffffffffff000000000000000000000000ffff"])
socket(0x6, 0x3, 0x4)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000340), 0x10, 0x0)
r5 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r6 = fcntl$dupfd(r5, 0x3, 0xffffffffffffffff)
ioctl$FIONREAD(r6, 0x4004667f, &(0x7f00000000c0))
fchdir(r4)
fsync(r1)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r6, 0x80104267, &(0x7f0000000580)={0x3, &(0x7f0000000180)=[{0x20, 0xc1}, {0x0, 0x0, 0x80}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000380)=ANY=[])
ioctl$BIOCLOCK(r1, 0x20004276)
sysctl$net_inet_icmp(&(0x7f0000000100), 0x4, &(0x7f00000007c0)="e11ee67e3e829d763a8877315c94edde4cc34fdc0ba8cb3057d3af14daeeb6bd15d63bb8ee4816b74cfb942603dee2bbb8597632e81b9fc0d2cc5bf612193a1a32607694e94db3a9d3c9645ee438c8d4e66c372a850a18b836c51753609b09b3eb64fd42c7b3b005abc11648171955132afefe4bf98020c07f7b3b2eb24a34725b02bceddc86f7dc17a7091728a502c79626b93bd26fee85ccc0b67f8ef4a075c6e5f77b57252aa7", 0x0, &(0x7f0000000680)="b22fae7408267b252dfa8b074ddb88581e0ad4887752dc049eef80d214505f5e30c1a25e3afb63e475cf891d7e190fc00dc768e15843bdc2ea71e849b06c001686f0a8e049f22e4fdc0fbb22872e04fb5d1d5d0f374e483f2cd79f9a1a1a9e823fee58b237f813db81d5d86ac40000000000000000000010000000000000e9c795eef92b380a7e1ee9da53ea9725d2796ce2f9f80b7502e79ea421b938b4bb99f46a4f3508795f1f5e3dc13e44f8bd6864d7e82f1011b145ddb2edfa724643dbdf5129affa6e392225a49977f99b857524fa6025f06dc20544c83cebab2b0825d75ec02c90048d4549b1efb28df0283ec4dca5e89eedc4e456320ad6d85bc3a90d12fdd87c369732fe6647aca8c32229be19eb50cdde03be26dd90ccf029989bd5", 0x121)


r0 = socket$unix(0x1, 0x1, 0x0)
read(r0, 0x0, 0x0)


mmap(&(0x7f0000000000/0x4000)=nil, 0x4000, 0x1, 0x9412, 0xffffffffffffffff, 0x0)
clock_settime(0xffffffffffffffff, &(0x7f0000000140))
r0 = socket(0x2, 0x1, 0x0)
r1 = dup(r0)
listen(r1, 0x0)
r2 = socket(0x2, 0x1, 0x0)
r3 = socket$inet(0x2, 0x1, 0x0)
getsockopt$sock_int(r3, 0xffff, 0x10, &(0x7f0000000000), &(0x7f0000000080)=0xca555f06cd31e785)
r4 = fcntl$dupfd(r2, 0x0, r3)
close(r4)
r5 = socket(0x2, 0x1, 0x0)
connect$unix(r5, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r4, 0xffff, 0x1023, &(0x7f0000000080), 0x4)
r6 = msgget$private(0x0, 0x0)
accept(r4, 0x0, &(0x7f0000000100))
msgrcv(r6, 0x0, 0x0, 0x2, 0x1000)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000000), &(0x7f0000000040)=0xc)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000080), &(0x7f00000000c0)=0xc)
msgctl$IPC_STAT(r6, 0x2, &(0x7f0000000240)=""/56)


mknodat(0xffffffffffffff9c, &(0x7f0000000100)='./file0\x00', 0x1000, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r1 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$DIOCMAP(r1, 0xc0106477, &(0x7f0000000200)={&(0x7f00000002c0)='./file0\x00', r0})
close(r0)
acct(&(0x7f0000000140)='./file0\x00')


setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0xee00, r0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x80206913, &(0x7f00000001c0))


sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
openat$pci(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x1046, 0x0)
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{0x80}, {0x7c}, {0x16}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f0000000080)=ANY=[])


mknod(&(0x7f0000000040)='./file0\x00', 0x2000, 0x3200)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
readv(r0, &(0x7f0000000300)=[{&(0x7f00000000c0)=""/169, 0xa9}], 0x1)
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaaaabb86dd605d3452003000000000000000000000040000000020000000000000000500040000000000000001010090780000000060397772"])
mprotect(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x1)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f00000001c0)=[{0x48}, {0x5}, {0x16}]})
writev(r0, &(0x7f0000000500)=[{&(0x7f0000000000)="af18a64591749e07ad1273f580a0", 0xe}], 0x1)


open$dir(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r0)
socketpair(0x1, 0x1, 0x0, &(0x7f0000000140))
pipe(&(0x7f00000001c0))
ktrace(0x0, 0x0, 0x0, 0x0)
r1 = syz_open_pts()
read(r1, &(0x7f0000000080)=""/179, 0xb3)
r2 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r2, 0x0)
recvmsg(0xffffffffffffffff, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
write(r1, &(0x7f0000000140)="7f23a3c2", 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000700), 0x0, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x0, 0x0})
ioctl$BIOCGFILDROP(r0, 0x40044278, &(0x7f00000000c0))
r1 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
getpgrp()
r2 = msgget$private(0x0, 0x421)
r3 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r5 = dup(r3)
pwritev(r5, &(0x7f0000000140)=[{&(0x7f0000000580)="c6302c9c455c7be3d8598d3ac53af8e7574f36a8db981ae2d8854330fd7f9fc4ba71ba88b9ff297ff033cc3a3dd93a7e60391b1e6b1d20ad08c2a031eb04353f", 0x40}], 0x1, 0x400)
writev(r5, &(0x7f0000000540)=[{&(0x7f0000000240)='<', 0x1}, {0x0}], 0x2)
ioctl$BIOCSETF(r5, 0x80104267, &(0x7f0000000680)={0x6, &(0x7f0000000180)=[{0xdd01, 0x0, 0xfe, 0x5}, {0x101, 0x3, 0x1f, 0x62c}, {0xab46, 0x6c, 0x0, 0xfffffffc}, {0x81, 0x20, 0x7f, 0x6}, {0x8000, 0x9, 0xcd, 0x9}, {0x3800, 0x7, 0x5, 0x80000000}]})
execve(0x0, 0x0, 0x0)
sendmmsg(r1, &(0x7f0000000f40)={&(0x7f0000000e80)={&(0x7f00000006c0)=@in6={0x18, 0x0, 0x800, 0x1}, 0xc, &(0x7f0000000d80), 0x0, &(0x7f0000000d40)=ANY=[@ANYRESDEC=r4], 0x2d8}, 0x3a}, 0x10, 0x0)
pwritev(r3, &(0x7f00000001c0)=[{&(0x7f00000005c0)="18d26cb474b5c9d53e0ffdba8c54fecc9031509b1623088cc3e85353a5586603eebda7eccfc5ced62c70a12fbffc2425f3f9e50317605792ea906ef56376aa499b9a909aff511ad2d63fc010ee2292f393b11d78e8bc095bbd866e81599df546afa16ce278edae371c4f16d4df85f4ba622daf27aa8a728453bc4e93539080b8d73936bf6499780255943ab4ebd03bdae91f09e60447e17e0e21bf2dbd2c39", 0x9f}], 0x1, 0xb3)
sendto$unix(0xffffffffffffffff, &(0x7f00000002c0)="24dee952f632c9420a7cd9fca5de24bd829f736b202b2d441c77b4f7af183491e9354e6cf57a87b7f80438757d97844b796202813edb49144fe538a092b496ad8ba2ec3e2b614899035deaff09d7140f33ac4ea319626ebe123943c5cfa79a63799b8bd9d159da862bd8770c307f085fe6b5eccbb3b06b06ddc154567641601c414c56f022b77bbce0c1b6b5a420bfb75242d472045e56b3b4e2e299a125a1592295f6815e37401cea0313c779733c190a283312d45ce8290a596bc38a3b050ad1416e60e259b88f3ffcd57f42b7a5ad6ce648e90fa932786fe35c247aa1515b076dfc460dde2f58", 0xe8, 0x404, &(0x7f00000003c0)=@abs={0x1, 0x0, 0x0}, 0x8)
msgget$private(0x0, 0x480)
msgrcv(r2, 0x0, 0x0, 0x3, 0x0)
execve(&(0x7f0000000c80)='./file0\x00', &(0x7f0000000780)=[&(0x7f0000000cc0)='/dev/speaker\x00', &(0x7f0000000d00)='\x10', &(0x7f0000000a40)='%\x92%:{\xbe}&.#,\'\x00', &(0x7f0000000980)='~0[\x1b\by`@\xf0/\x8f\xa2&\xcc\x92', &(0x7f0000000dc0)='\x00\x00\x00\x00', &(0x7f0000000e00)='\x01\x00\x00\x00\x00\x00\x00\x00aker\x00', &(0x7f0000000e40)='/Xev/bp\xdcL'], &(0x7f00000009c0)=[&(0x7f0000000a80)='\xab\xec:\xd2\xdf\x92\xb78%(\n4\xf4O\v|\x00'/30, &(0x7f0000000f00)='*/}\x00', &(0x7f0000000740)='\x18\x15\x0e\nr\x15\x15N\xf3\x97[,B\x93', &(0x7f0000000a00)='\xeb\xec\xbc\xd1\'Phq\xc8\xc8\xa8\xaa\xb7\xf0\xa5\x1d-\xbe\xa4X\xb2\xc3\xc7\xe5\xc9\x1fd7\x1b]n\x91\x9dvtl\xa2\xcd\xed'])
msgsnd(r2, &(0x7f0000001340)=ANY=[@ANYBLOB="0300000000000000b370fb802a993a89140cfbb2a769f96527923c9b5dff2b4f03b94ef09aa699e7a69ed7aa4f73ffcbb7d1e59e3a93ba357fc00b9dc8d264817210a91befe0d63fe4549f77a8be0f23ca6afb74c0d25948a54f5a221da2f60b4bba5672c95125fdda33c2780a7957930660edb6686fb2d929cc202b128081656db0320eca690045b6c51241f9be647697960874a6fb1f718e060081e2ad7407611c1d94b2ffffffffffffff7f0f8c590fe7a0129239ffa3737c792ba98a97e8ae521ace9a9d0dcdce2d13180aea0bb2e533df90f87735af2a09b944fbf6e54cea4410dbe01b9fc087c888f5395418b0308912d849841ea99f523caaeebb4c4efc40a5f9b5c85af84bf2bd55765efa0f7abd5f38e7075a25e8628b7f6a6f5b15c1d2e93d39bf683bf2397704a8cde4d58cf5bfd781c4225b57226686c5816230b422457433e28bc3e69d3b1324f31f6b472987cde8071a8565eb4b727fa4fa0434e2f1641b85992b21fa161d31b561763b9d4075679ad325fc0a6c3159ac448edeb1acd6198a54a5409e84"], 0xed, 0x800)
pipe(&(0x7f0000000040))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f00000004c0)=[{0x2c}, {0x4}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
getsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
ioctl$TIOCCONS(0xffffffffffffffff, 0x80047462, &(0x7f0000000000))
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000)=@un=@abs={0x0, 0xd}, 0x10)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
r1 = getuid()
r2 = getuid()
setreuid(0xee00, r2)
setreuid(r1, r2)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000400)=[{0x4c}, {0x2}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])


r0 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000680), 0x0, 0x0)
close(r0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
ioctl$DIOCMAP(r0, 0x40047477, &(0x7f0000000080)={0x0})


getitimer(0x0, 0x0)
socket(0x0, 0x0, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
openat$pci(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000280)={0x3, &(0x7f00000000c0)=[{0x7}, {0x81}, {0x8046}]})
syz_emit_ethernet(0x2a, &(0x7f00000000c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f00000001c0)=[{0x50}, {0x6c}, {0x810e}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


sysctl$machdep(&(0x7f0000000000)={0x7, 0x10}, 0x2, &(0x7f0000000040)="c9c151552a49d74e", &(0x7f0000001040)=0x8, &(0x7f0000001080), 0x0)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f00002c5000/0x800000)=nil}, {0x0, &(0x7f0000ffb000/0x3000)=nil, 0x1000000}, {0x0, &(0x7f0000158000/0x3000)=nil}, {&(0x7f000003d000/0x1000)=nil, &(0x7f0000388000/0x1000)=nil}, {&(0x7f00007eb000/0x3000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000157000/0x1000)=nil}, {0x0, &(0x7f00001eb000/0x2000)=nil}, {0x0, &(0x7f0000202000/0x2000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f00000e0000/0x1000)=nil, &(0x7f00000d8000/0x3000)=nil}, {&(0x7f00000ca000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f00000f8000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
r3 = socket(0x2, 0x2, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
connect$unix(r3, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r2, 0xffff, 0x1023, &(0x7f0000000040), 0xe0)


openat$speaker(0xffffffffffffff9c, 0x0, 0x1, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
r0 = open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
poll(&(0x7f00000000c0)=[{r0, 0x6e}], 0x1, 0x0)
select(0x40, &(0x7f0000000180)={0xffffffffffffffff}, 0x0, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000200)={0x4, 0x2, 0x6, 0x19}, 0x4, 0x0, 0x0, 0x0, 0x0)
ioctl$FIOSETOWN(0xffffffffffffffff, 0x80047308, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x8, 0x0)
r1 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f00000005c0), 0x80, 0x0)
getsockopt$sock_timeval(r1, 0xffff, 0x1006, &(0x7f0000000600), &(0x7f0000000640)=0x10)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r2 = socket(0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
getpid()
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000480), &(0x7f00000004c0)=0xc)
getsockopt$SO_PEERCRED(r2, 0xffff, 0x1022, &(0x7f0000000500), 0xc)
r3 = getpid()
r4 = fcntl$getown(0xffffffffffffffff, 0x5)
r5 = msgget$private(0x0, 0x0)
msgctl$IPC_SET(r5, 0x1, &(0x7f0000002f80)={{}, 0x0, 0xff, r3, r4, 0x7fffffff, 0xa, 0x2000000100000001, 0x7})


syz_emit_ethernet(0x4e, 0x0)
writev(0xffffffffffffffff, &(0x7f00000002c0)=[{&(0x7f0000000400)}], 0x1)
pipe(0x0)
kevent(0xffffffffffffff9c, &(0x7f0000000000)=[{{0xffffffffffffff9c}, 0x0, 0x0, 0x0, 0x9}], 0x0, 0x0, 0x0, 0x0)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000000)={0x0, 0x80000000005}, 0x10)
sysctl$kern(&(0x7f0000000000)={0x1, 0x42}, 0x6, 0x0, 0x0, 0x0, 0x0)


mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)={0x3, 0x7fffffff})
r0 = kqueue()
kevent(r0, &(0x7f0000000040), 0x30, 0x0, 0x57d, 0x0)
kevent(r0, 0x0, 0x0, &(0x7f0000000600), 0x2, 0x0)


syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000), 0x10)
r1 = dup(r0)
listen(r1, 0x0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
accept$inet(r0, 0x0, 0x0)
r3 = socket(0x2, 0x1, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)
r4 = dup(r3)
sendto$inet(r4, &(0x7f0000000240)="03c019b7e2399b388d3cc45f01364c934fe5a3d4c1fbf21dc5dab6090e154d84d22c5ff1da069dd0d4af159fe9dfcef73c67", 0x32, 0x0, 0x0, 0x0)
getsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
write(r3, &(0x7f0000000040)="04", 0xff9a)
syz_emit_ethernet(0x12a, &(0x7f0000000240)=ANY=[@ANYBLOB, @ANYRES32=0x41424344, @ANYRES32=0x41424344])
symlinkat(0x0, 0xffffffffffffffff, 0x0)
symlinkat(&(0x7f0000000dc0)='./file0\x00', 0xffffffffffffffff, 0x0)
mkdir(0x0, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f00000000c0), 0x0, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, 0x0)
r5 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_INFO(r5, 0xc0185603, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1023, &(0x7f0000000080), 0x4)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "28b77c09b87aa57800080017d0d2000010001c00"})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x800000018, 0x3, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000))
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x18, 0x1, 0x0)
close(r2)
r3 = socket(0x18, 0x3, 0x0)
r4 = dup2(r0, r3)
setsockopt(r4, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000140)=[{0xc0}, {0xc}, {0x6}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f0000000240)=ANY=[])


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000040)=[{}, {}, {0x7, 0x0, 0x0, 0xffff33c4}]})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x6, &(0x7f0000000080)="ae215599fed2fce97f573b9c553a0e622d29cd093849cd4fe42e0f5d2d06a4e744f0713d1fcaa1b8274dffd067d413ef9d2224d3fddc171f73a295b6ed18b3d0588be75e78a1d734e15bfe", 0x0, 0x0, 0xfffffffffffffd37)


socketpair$unix(0x1, 0x2, 0x0, 0x0)
msgsnd(0x0, &(0x7f0000000140)=ANY=[@ANYBLOB="0300000000000000a60d524ae979b5a3e111c8cac1b119e4db1e444c9d4eca7af32596137392f4cdc50d82caa6fa7ffd0da455fa2e9f5109d4ccbe9ddd5e3674e689a6714f0ac2ee9e36ae12821cff35f5866888d441f7c29189271982efb7cd9c94766d1c4be0efcbf44d5d0010dc9df78616b167b260dd96322bfbad5f46f92beb4126cf5ffee44ca5b5bdfcf14c9b3003f53d57d96bcceb3c014f4d7b36a32f1fdb2d7783fa77ede48c3db7299ec5e58a1348d1da9304dc8bf8200a241f24ffa673bd7cb93b55b31a3045a1501250df6302a6bbfdcb68febcf98e7aabab17c9e7408bccc3081d1feec2142247dcd0e3ab8a8ab390b2a70909b2f114aa2b6ff73741b6c4c953d4fd45a49aa77d"], 0x401, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {0x0, 0x0, 0x3b8}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x1000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffa000/0x2000)=nil, 0x7}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000280)=[{0x7c}, {0x4d}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000200)=ANY=[])
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r1, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0})
bind$unix(0xffffffffffffffff, 0x0, 0xa)
connect$unix(0xffffffffffffffff, &(0x7f00000016c0), 0xa)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
r2 = socket$inet(0x2, 0x1, 0x0)
shutdown(r2, 0x1)
connect$inet(r2, &(0x7f0000000040)={0x2, 0x1}, 0xc)
r3 = getppid()
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
setreuid(0xee00, 0x0)
getsockopt$SO_PEERCRED(r2, 0xffff, 0x1022, &(0x7f0000000280), 0xc)
r4 = getuid()
chown(&(0x7f0000000140)='./file0\x00', r4, 0x0)
socket(0x20, 0x5, 0xff)
chmod(&(0x7f0000000200)='./file0\x00', 0x1a4)
r5 = getuid()
setreuid(0xee00, r5)
ktrace(&(0x7f0000000040)='./file0\x00', 0x0, 0x2, 0x0)
fcntl$lock(0xffffffffffffffff, 0x7, &(0x7f0000000140)={0x3, 0x2, 0x6d, 0x0, r3})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000180)={0x2, &(0x7f00000000c0)=[{}, {0x5}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x2c}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0xfffffffffffffef1)
syz_emit_ethernet(0x2a, &(0x7f0000000040)={@local, @remote, [], {@arp={0x8035, @ether_ipv4={0x1, 0x800, 0x6, 0x4, 0x2, @local, @empty, @empty, @remote={0xac, 0x14, 0x0}}}}})


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0xf66c, 0x0, 0x7fffffff, 0x4777c543, "1c102609307e7be2df67de202a72da64612c3300"})
writev(r0, &(0x7f00000003c0)=[{&(0x7f00000001c0)="e16f18f4c574c1c3617a5f6fc6d78b97e55b791b98da9d7c387dc1834a72e0a279d998a1e1404266b6b996cbedd28e4f3f56124dee37308c37aed1c3c4d1976c9858acc8593d6e3e65fd6c02aba7b383919fc21d22584543b38687111db9fd34da121f4fe17f3b2b0869210ccfa6a2d1fe40a0a65ffc09", 0x77}], 0x1)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
r0 = socket(0x2, 0x3, 0x0)
r1 = socket(0x18, 0x3, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
dup2(r1, r0)
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
write(r0, &(0x7f0000001680)="04bdfa5d1d2873c63e3534825ba166e2fea9aec43050006123339a346f731573d8d508753f95b7688ad48b8cf6bbca325cebc37fc4e1dd543dbe2da6dd", 0x1001c)


setgid(0xffffffffffffffff)
setgroups(0x0, 0x0)
setreuid(0x0, 0xee01)
close(0xffffffffffffffff)
syz_open_pts()


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000500)={0x3, &(0x7f00000000c0)=[{0x87}, {0x74}, {0x8106}]})
socketpair$unix(0x1, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x62, &(0x7f00000008c0)=ANY=[])


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x205310)
r0 = open(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)
poll(&(0x7f0000000100)=[{r0, 0x40}], 0x1, 0x0)
close(r0)
chmod(&(0x7f00000000c0)='./file0\x00', 0x63)
setreuid(0xee00, 0x0)
r1 = open(&(0x7f0000000040)='./file0\x00', 0xfffe, 0x0)
ioctl$KDSETLED(0xffffffffffffffff, 0x20004b42, &(0x7f0000000080)=0x4)
syz_open_pts()
ioctl$TIOCSETAW(r1, 0x802c7415, &(0x7f0000000140)={0x0, 0x0, 0xfffffffc, 0x40000000, "d9c71d75463c8d2213137fd1447a6c893e868ffc", 0x7})
syz_open_pts()
r2 = msgget$private(0x0, 0x0)
open(0x0, 0x0, 0xae)
sysctl$hw(&(0x7f0000000100)={0x6, 0xf}, 0x2, 0x0, 0x0, 0x0, 0x0)
ktrace(&(0x7f0000000040)='./file0\x00', 0x4, 0x6000043e, 0xffffffffffffffff)
open(&(0x7f0000000180)='./file0\x00', 0x80, 0x0)
symlinkat(&(0x7f0000000dc0)='./file0\x00', 0xffffffffffffffff, &(0x7f0000000ec0)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
msgsnd(r2, &(0x7f0000000100)=ANY=[@ANYBLOB], 0x8, 0x0)


select(0xfffffd4c, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, 0x1000000, 0x0, 0xdec5}, 0x0, 0x0, 0x0)
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r0, 0xc2585601, &(0x7f0000000000)={0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000700)=[{0x54}, {0x2c}, {0x6, 0x0, 0x0, 0xfffffffe}]})
write(r0, &(0x7f0000000540)="76e5dead6f01f8607d2100000063", 0xe)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f000051c000/0x3000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f00004c4000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000158000/0x3000)=nil}, {&(0x7f000003d000/0x1000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f00000c3000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000157000/0x1000)=nil}, {0x0, &(0x7f00001eb000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000268000/0x4000)=nil}, {&(0x7f00000e0000/0x1000)=nil, &(0x7f00000d8000/0x3000)=nil}, {&(0x7f00000ca000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f00000f8000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
r0 = socket(0x18, 0x2, 0x0)
getsockname$inet(r0, &(0x7f0000000080), &(0x7f0000000040)=0xc)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x3, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r2 = socket(0x18, 0x2, 0x0)
r3 = dup2(r1, r2)
sendmsg$unix(r3, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x5d4a)
r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
close(r0)


syz_emit_ethernet(0x2e, &(0x7f00000003c0)={@local, @local, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x1, 0x0, @empty, @local={0xac, 0x14, 0x0}, {[@timestamp={0x44, 0x4}]}}, @icmp=@echo}}}})


symlink(&(0x7f00000004c0)='./file0\x00', &(0x7f0000000500)='./file0\x00')
readlink(&(0x7f0000001700)='./file0\x00', &(0x7f0000001740)=""/34, 0x22)


r0 = socket(0x1e, 0x3, 0x0)
sendmsg$unix(r0, &(0x7f00000006c0)={0x0, 0x0, &(0x7f0000000000)=[{&(0x7f0000000040)="7607d771020000004e2b1f0000000000", 0x10}], 0x1}, 0x0)


mknodat(0xffffffffffffff9c, &(0x7f0000000240)='./file0\x00', 0x1, 0x0)
r0 = syz_open_pts()
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000100)={0x6, 0x0, 0x0, 0x6, "3378b74a4eddc026dc813187e906385e4a7d5626", 0x14, 0xffffff81})
r1 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r1, 0x802069c3, &(0x7f00000001c0))
open(&(0x7f0000000380)='./file0\x00', 0x0, 0x0)
r2 = getuid()
chown(&(0x7f0000000000)='./file0\x00', r2, 0x0)
r3 = getuid()
semget$private(0x0, 0x1, 0xd7)
getsockopt$sock_cred(0xffffffffffffff9c, 0xffff, 0x1022, 0x0, 0x0)
chown(0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
open$dir(&(0x7f0000000180)='./file0\x00', 0x80, 0xe5)
r4 = socket(0x11, 0x3, 0x0)
sendto$unix(r4, &(0x7f0000000000)="b10005040000000000000000071000001a5113fecea10500fef96ecfc72fd3357a89583535613ab4cb56355df50b7804be38164991f7c8cf7a4f2b297be1aa5b22abeb51e2f0ac3ebbc2feb3fda1139b672f4d3353eb067e7335a079d7080000000000000000008904000000000022830cf4571bed66f4007fccdcf3e4999d9d20002002c5dbfad800000008e371a3f8340012051e0000000000000200"/177, 0xb1, 0x60a, 0x0, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000280)={{0x3, r3, 0x0, 0x0, 0x0, 0x0, 0x3}, 0xd1, 0x0, 0x0, 0x0, 0x4000000000007128, 0x7, 0x843, 0x8001})
r5 = semget(0x1, 0x1, 0x280)
recvfrom$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
getuid()
semctl$IPC_SET(r5, 0x0, 0x1, 0x0)
socket(0x18, 0x1, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x50}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)
socketpair(0x10, 0x5, 0x0, &(0x7f0000000380))


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)="03000000", 0x4)
setsockopt(r0, 0x1000000000029, 0xd, 0x0, 0x0)


sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000400)='./file0\x00', 0x2000, 0x0)
open(&(0x7f0000000380)='./file0\x00', 0x0, 0x0)
r0 = syz_open_pts()
ioctl$TIOCCONS(r0, 0x80047462, &(0x7f0000000080)=0x7)
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x0, 0xffffffffffffffff)


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
mmap(&(0x7f0000ffa000/0x3000)=nil, 0x3000, 0x0, 0x11, r0, 0x0)


setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)
munmap(&(0x7f0000ffe000/0x1000)=nil, 0x1000)


r0 = open(&(0x7f00000001c0)='./file0\x00', 0x2e1, 0x0)
mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0, 0x2015, r0, 0x0)
msync(&(0x7f0000ffa000/0x4000)=nil, 0x4000, 0x6)


mknod(&(0x7f0000000280)='./file0\x00', 0x1100, 0x0)
open(&(0x7f0000000180)='./file0\x00', 0x80000000000206, 0x0)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
ioctl$FIOSETOWN(r0, 0x8004667c, &(0x7f0000000100)=0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000001080)=[{0xc0}, {0x4c}, {0xfffe}]})
syz_emit_ethernet(0xe, &(0x7f0000001100)=ANY=[])


mknod(&(0x7f0000000000)='./file0\x00', 0x6000, 0xe02)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
close(r0)


open(0x0, 0x0, 0x0)
r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
acct(&(0x7f0000000140)='./file0\x00')
sysctl$net_inet_divert(&(0x7f0000000000)={0x4, 0x18, 0x102, 0x3}, 0x4, 0x0, 0x0, 0x0, 0x0)
pwritev(r0, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)


mkdir(&(0x7f0000000100)='./file0\x00', 0x49)
chdir(&(0x7f0000000080)='./file0\x00')
setreuid(0xee00, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000015c0)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000000)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000040)=0xc)
setegid(r1)
setgroups(0x0, 0x0)
r2 = getuid()
setreuid(0xee00, r2)
unveil(&(0x7f00000001c0)='./file0\x00', &(0x7f0000000200)='x\x00')


setrlimit(0x6, &(0x7f00000000c0))
mprotect(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x4)
mlockall(0x1)
munlock(&(0x7f0000ffb000/0x4000)=nil, 0x4000)


socket(0x2, 0x1, 0x0)
getsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x0, 0x0)
close(0xffffffffffffffff)
open(0x0, 0x0, 0x0)
syz_emit_ethernet(0x0, 0x0)
fcntl$setstatus(0xffffffffffffffff, 0x4, 0x40)
shutdown(0xffffffffffffffff, 0x1)
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x0)
setsockopt(r1, 0x1000000029, 0x31, &(0x7f00000000c0)="b211d7170d816685c8e360f2fa41c1a0946988b272d2dd3dc90142a84231a746e337b372e93320cff6669cbe7868de45ed3fc33719ca6df71ecec8a918458b2c10a1f8c66653b276e180e9cb9b21f9982230f575295d48889c9a920796b2dd92fc8575680b37ba955d2c15e6d7c9198ed900ab006ddfb67869b51a2216114d1ece85f593e74035f5bc054eb1dbddf42a", 0x90)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x100000000000000, 0xffffffffffffffff})
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
writev(r1, &(0x7f0000001240)=[{&(0x7f0000000240)="f0a8468fa819ad5e71a8be585f2ae642a8278564317b78a3b743b3a68a64daa9a6f3c6f09bb877ebb5e695854113c37dae52b9a28acdc6c3de65edf75d107620028e9e3222034bfc22f12273ade2fea06ba00180b581b22d4bbf9030e7a702419e4555ba924b69970c80e8cad1ec74bdf0e4d012c4ddb0faac2fab4d1beadbc73d8e33c6f1b1730bcf1f6d37953b01037c6dbe2a0cfddb69afdee5092b3b460918d483aff973cc6c5aae0db223a8a79191dd28cbd40085800d363de83d507bbee66900f19f6ff46e3ff6fc16ff3e5e88368ffb2decd3077b6fd06468d1137c1df3c1c86939a408a7378a362ae3b2c2cecdad6d8dc50c6130a6b1e38d6abde93d47d04880143f8afec24b852554da94f94652c2a4b9c089b939ddf179a96a28243025d8c8eb5e626ae398b3b7c29c9ef49cf4907b99d23b214eaf9ee3f625ef247f205070b13b332f52ba64172fffbbd8fc6d12632798c98a3aea02126a56de88e199ffe4ff47556475341c04e34587ec6ddcc16420b6cfb04cc92fc491c1c46ba92d0e4e045389c3effc8cc6709e7658557ab28e21c315cb46edca8c092279500d61386ca707986ba2bf03a8e80b0029fbe1ab6f5a77233342f2d1f5b31e5f1768b0419ede2ab832f1d4ed64329fc3fb7dfa1edaace42f8479834a4d9dbae61b3c5be768ffd3f9035216dc6e684fad65d86a75e7912e8e18ea317c505380d9c954c31e5c05ee5ab8bec432a9f69bbd9c2d3ba50a08ec3d9d22b97bc1099c2b9cc27e3e0d72c74757225b898a985fd01f05179e2f31de5ab58368212288dd39050623ecf9e8808a69424c32c08f0200c7eebd8b76abd152164df103129d5291ac8043fcba7dd5f63a33f943623c509887af66fd315f77ea0da829daa768beef2edf33cd5c1c98a18496e24e71d8553e72bd63cf981bcb166828dcf4ead7e7be78e7f4acd4916cbf37bd6860776e07c2e4f00ee2edee5a35e32b33f0ea4fea4d9e6f519c3ebac30e2fb32abca3e128dc4ffb38c2067b8f2564629c21094f0e660189b1c1108c20f0ffa4e6bae0889ebd6389fa86f465db3da9e2371f07a9af58c53a5b196f5a5e9be9c7f8e3a0f9fb126ba77d8ef25c8a6e67eefcad70fa715aa4052d2c457afd5a7d941ecf7aff6824612bbdab2be07a43b72787c35a9e157dc4e0cd81d7d33985923fb99304d54bac07b374b1b2054a", 0x356}], 0x1)


ftruncate(0xffffffffffffffff, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r1 = socket(0x1, 0x1, 0x0)
close(r1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x18, 0x1, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
open(0x0, 0x0, 0x0)
shutdown(r2, 0x1)
ioctl$WSDISPLAYIO_USEFONT(0xffffffffffffffff, 0x80585750, 0x0)
socket$unix(0x1, 0x0, 0x0)
chdir(&(0x7f0000000140)='./file0\x00')
setreuid(0xee00, 0x0)
mkdir(&(0x7f0000000040)='./bus\x00', 0x5c)
chdir(&(0x7f0000000380)='./file0\x00')
r3 = getuid()
mkdir(&(0x7f0000000100)='./bus\x00', 0x0)
setreuid(0xee00, r3)
unveil(&(0x7f0000000280)='./file0\x00', &(0x7f0000000080)='x\x00')
unveil(&(0x7f00000000c0)='./bus\x00', &(0x7f00000001c0)='c\x00')
writev(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe2c63a56077123a276d3ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
kevent(0xffffffffffffff9c, &(0x7f00000001c0)=[{}, {{}, 0xfffffffffffffffb, 0x48, 0x80}, {{}, 0xfffffffffffffff8, 0x1c, 0x0, 0x1fc, 0x8}], 0x0, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
mknod(0x0, 0x0, 0x0)
pwritev(r0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x54}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)
r1 = msgget$private(0x0, 0x0)
msgrcv(0x0, 0x0, 0x3b, 0x0, 0x0)
msgrcv(r1, &(0x7f0000000b40), 0xa6, 0x0, 0x0)
r2 = open(0x0, 0x0, 0x0)
r3 = open(0x0, 0x0, 0x0)
writev(r3, &(0x7f0000000180)=[{&(0x7f0000000b80)="601d18253536eb523e1f2a212ea4747ae8f772b254cef012e37495473e3b32e7c512c940458bccbea2a8c0b69c3a728ae071ffc1e631e3ead047975e63b99bb38c1fcaea9d1115a547ebbd7af0e790eb27e93059a9b00640bb1f0f9f2e130217dc46a1d1841c879b6783da32600644c83f164d0d6778c3e4fc7b164d43d11232547d6a65d26d9cdb9873cb57ec7c8603b1e30879c60f4c3bbb910b6dbcea8be0ff7ea6d5c33c54f396a9d1175e0da830ded24cc9f1efa4424c3be70fdd261d44b9bb4a918c", 0xc5}], 0x1)
writev(r2, &(0x7f0000000540)=[{&(0x7f0000000100)="3f4892d9d6989eba44342c610c2de7591e37206918d4a9", 0x17}, {&(0x7f00000002c0)}, {0x0}, {0x0}, {&(0x7f00000009c0)="6fac7694b56bbaff041839439e5877f2c0fef4fcb751148e7858caa503ffb0b8b7162e842daba061044669a2f2113924c7f1a31b21f422f2b912a1a614b70ce402bf945a21caaef31c6607945bd50a6bb6", 0x51}], 0x5)
sysctl$net_inet_ip(&(0x7f0000000000), 0x5, 0x0, 0x0, 0x0, 0x45)
r4 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_INFO(r4, 0xc0285602, 0x0)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
msgrcv(r1, &(0x7f0000001500)={0x0, ""/4096}, 0x1008, 0x0, 0x1400)
msgsnd(r1, &(0x7f0000000500)=ANY=[@ANYBLOB], 0x11, 0x0)


r0 = kqueue()
kevent(r0, &(0x7f0000000200)=[{{}, 0xfffffffffffffff9, 0xc7, 0x1, 0x200000000000000}], 0x200020, 0x0, 0x0, 0x0)


sysctl$vm(&(0x7f0000002e40)={0x2, 0x9}, 0x2, &(0x7f0000002e80)="8d1ee271", &(0x7f0000002f40)=0x4, &(0x7f0000002f80)="81627e41", 0x4)
sysctl$vm(&(0x7f0000000000)={0x2, 0x7}, 0x2, &(0x7f0000000040), 0x0, &(0x7f0000000180)="23e6139a508b7f724d62714ff6fb6c2783cf45eb14c32a85e3d84a7c70b13a2f7bbf5b76f377c6a9bb30d39e0432b05a622e36f345f2ccb09abc5cf10597aff54e33d96a41aaef646b61bde30bb91cee92333c1a7aff29a1de43acd037f9c598f78bf9edb6ecbe580902fb68305a5f187a8cb73656f84d378cd03d954da126c3d3e22e6a1012dc62334979aa0817147ca1aacbe53cd9deaefcf0bf21a3f2cfc746aef3870e02d997be0a8eb4bce82eae87db94541069d320defff192c928b8cb66d437620f293c0814", 0xc9)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x0, 0x0})
r0 = socket(0x0, 0x2, 0x0)
open(0x0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r2 = dup(r1)
ioctl$BIOCSBLEN(r2, 0xc0044266, &(0x7f0000000100))
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
madvise(&(0x7f0000000000/0x4000)=nil, 0x0, 0x0)
syz_emit_ethernet(0x4f, &(0x7f0000000400)=ANY=[])
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f0000000100)={0x10, 0x0, [{&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000af2000/0xf000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {&(0x7f00008e3000/0x4000)=nil, &(0x7f0000f52000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000826000/0x1000)=nil}, {&(0x7f00005f5000/0x4000)=nil, &(0x7f000093c000/0x2000)=nil}, {&(0x7f0000da9000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000e0a000/0x2000)=nil, &(0x7f0000648000/0x2000)=nil}, {&(0x7f0000b64000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f000062b000/0xf000)=nil, &(0x7f00004df000/0x4000)=nil}, {&(0x7f00004e0000/0x4000)=nil, &(0x7f0000af4000/0x13000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000b04000/0x3000)=nil}, {&(0x7f0000ecf000/0x3000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f000064c000/0x2000)=nil, &(0x7f0000c2c000/0x2000)=nil}, {&(0x7f0000c2a000/0x2000)=nil, &(0x7f0000518000/0x3000)=nil}], './file0\x00'})
r3 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r3, 0xc028698d, &(0x7f00000001c0))
r4 = syz_open_pts()
r5 = syz_open_pts()
readv(r5, &(0x7f00000012c0), 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000004c0)={'tap', 0x0})
sysctl$hw(&(0x7f0000000100)={0x6, 0x13}, 0x2, 0x0, 0x0, 0x0, 0x0)
ioctl$TIOCSETAF(r4, 0x802c7416, &(0x7f0000000080)={0x0, 0x0, 0x0, 0xfff, "0fdb000000000000000600000000000000d900", 0x0, 0xffff})
syz_extract_tcp_res(0x0, 0x0, 0x0)
ioctl$FIONREAD(r1, 0x4004667f, &(0x7f00000001c0))
ioctl$WSKBDIO_SETBELL(0xffffffffffffffff, 0x80105703, &(0x7f0000000140)={0x0, 0x0, 0x9, 0x20003fd})
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
ioctl$FIONREAD(0xffffffffffffffff, 0x8080691a, &(0x7f0000000100))
sysctl$vm(&(0x7f0000000280)={0x2, 0x4}, 0x2, &(0x7f00000002c0)="b87dfdc7ee8f1fb5997f83ba5c39fb195f333d702d7c26203d3a889c55ddce33f59b1ed9b64efa8443467ea6134de5b03c1813c7d335208cace34c96e8a4001e3fb38176f4508c7f79138b119f65dec6314b99677f1a631f850e36b0818dc347851d6c286faddc0efccf1ad68d5f1c0b164c8c85a31c37632e73c315f45762164ceb5e9dae55de71908f788e4d2dd1c3de5fcf6fa8f59a87d74c5916f4ab8857aef40f01994c7b876dc003a80fdf65aef37cfe2bc6925b679c2fd2aafe9c13159f59e65e2e22f91885cb31ca13e981d805e79982c9da468d8b73", &(0x7f00000003c0)=0xda, &(0x7f0000000400)="8031c971b987d7466c0b492a6fd0b3c576aa4733b470ff080a2d60a6f8b96b20fc8f85b589dfb2857b2e828be01878fc313226f15dc856f36ecf0a4c2bd93d6c1f781843b4d9193c2dae039b78e00c6c41869e71ac3c53da00c3a54d2b5d3fda3d3397f612181bf860d745661d3c779961dce33146c3084b69aa975cc2a59c754767826106a3b3687173de497466a05a11844a496e20525fcd470a110577352e5713d4279207bfaf", 0xa8)


socket(0x2, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
writev(0xffffffffffffffff, &(0x7f0000000380), 0x0)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r1 = geteuid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, r1, 0x0, r1, 0x0, 0xa2}})
seteuid(r1)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000001080)=[{0xe6c, 0x0, 0x0, 0x800}, {0xc, 0xff, 0x0, 0xffffffff}, {0x3, 0x1, 0x0, 0xfffffff8}]})
r2 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r2, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r2, 0x0)
r3 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r3, &(0x7f00000001c0)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd, 0x0, 0x0, 0x9}, 0x0, 0x0, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd, 0x5, 0xffffffffffffffff, 0x0, 0x0, 0x8, 0x0, 0x1}, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000680)=[{&(0x7f0000000400)="ad39ac35f7160deacfcba483759e7358bb64c9089f7d8163b4683da4f38706e81c2f23f035f4f68c3378edfe6dcd6fae83ceb6f1ed6038df7ed121170f75353009687927abe3a1fc8a7f6d820cd8274164dd9a6bb262fbbadf09e1b41b1015c073a189653894a547367abcb61b35108d188927b5", 0x74}, {&(0x7f0000001fc0)="dd4cfd9a598de72b89800d552df1699062bc752729490fb282baeb1942dead2966eac9f336816db69fe70897340e0a4f95e740f673ab2de0d730de3fb00765db162f5db015bb81eacf0a9005e5659d48f63d365da9400eb0486d660fef33c0bb4b17ddb83ed743dd81dc3079a65cd039a282f25e043ca0e921ba26804466bc0ab8fc8eda3ac83694c5d0c2e70affca3068ac565247d79209997043de63728b235b92fe021961f86e5f22ce5c3971c29a49baa12879eab5e86c732f4d9a4b754821be4e9d55241e194201e543a256c5f555001a47c36c9fa245aef749ccd7e849a3900c9b728fa28a3375bd901e0adfafc38a4ae6f9ca80b3329a0ced985d9be5cf3d3f320e120167cd4078b499b48afc9e8c6afefc988a6a6337e7572bb04ebb13f0b72c441074badd1f64670cdf9f44fc3693876a462338968ff49588b2ecd8f2558354f48d98c39c99a4d52a1efe9ef01c3a87af7520810a0f427636ee37546b6e1b2aae9b2aba838dd9a9c286ec546e5f659421f8456d4a6279d69657c7da1851eab676c3452f9deddb568a63765582bbfcd6918404f0a139470942b9294a5a3d353aa625fd051f8aa22fb6f56ad1ec715ea3dc18f172fd1257e968ba63ec30931b3ad6b397ebe08381191c66eff9bdbf31a658baed26b9bf8349f80b9469e9dd060263f2908fd739a5837c45c5e7b77000ba1e4146937894ae9c0ff02cf7bf39bf7bf06144a85f153b097817ca1df1a8648097ecac6d1a303b3394a3963f17afa22a719e22efa3f7dc2f8ea56d05d649014544cd3729ea6d1724d0901efcdb8859833f64c2dce7b78cd2113862ace63bb665345941488dc689ec680872dbebedb6941497a0a90218646f68a07e9911e1964573be4dac746ea61b886fb0523e38529b168eaee45552faade5a1a65cc159475d62a3a31c5f7b2c8b5def3e8d84df6c1191126ed3fb313e2c6fdf012087909ade7bb5d546728699916377b1b6e9ca299d7b1ff5734f2e8bfd4638f4056e23f21f77769db8a60603c57fd970a7f64b9a6c6f8f4eb3f67ba78e49c23bfc163f2f4ddaf5fc29ff1b1708f508682179b5731a1b16afa6b647f1e70ed18a75b160623965a549b11b8e63d654ed5febdc4046baa5b505ef6e0074dd895998ec3f31f665961041679e9a40a90676ef1095e2e474d5e7586b9ea7fe352faf40e186266f524dbf18f576f4a5252fad1e31e9256ec57735c10e89067b23a1f304106755ebb32c9f0204e1e9709020b65b928ac80dda56e8782acbd8d6b3fa27b4ac88d2c0bde23ac645744ae88260d27998b244ad3ceafa663fb6045057a95b8e2eaabf671c87b19479e23da8751aa6346d8ea3bb497aa57058d34c2f5c184fcb20154e5f4b95c08d40d6c80421550d120d5659da68e3bca63ba6815c8e29f62ef363f2222cf0737fefec3e85e947720d953a4b7ad673d7fb1bb4a24bcefd60d95492d8594f330d88acb90e3059a271bebb09cc9b38edfc9029349ca7803c43e61dab0ee79e7492dcbfaff2496ce91ec382c945345a5827a018a1431ebdeecc5da680969c02b51b7bd1004c440e265ba7ff1b46a25fb39268770ab2fd1d3df9cb0fd94ea605b124a2dc3fc4390fc637321bbf0a805d514f8fa5fbbd19fe368dbb31db8c0d52a88e116398e3fda64419249035e155ff21a416adfd001cf9bbc27f5fd469aae1962c43f3063ff1b95f1c377a1c60537bb3285b969147ac10159840454e24e92f07c751e5c67a68b8cbc8a2095868ea75d944a5e393d075eac2fb6ad4669eb63d0b87d805b6d20cb97e6783b2d2d004b33f5f467b212b6af5c848929426d42af58b481e6da24e33ae45ae16c21fbb76d46f2981d7da440c779296762cdefcec12af8bb5363038622759adebdc68467a562ec346d33b5680932f241ad9c2f9930e505450a034b94c13c656edd75bf4b1b81864c23218f13452e0b1d158607d800705fd4383066d88510b9de5a7501f094cbab71311dcb3a2c3685f23714db66f176e92b72e403c672075259d5114c000e33900fab00b97192d5685faabb6a534a3bf399a8da1a2264ba6d9f36985422f2217583acdf9816292ac632c9fcf0814801bb52c3c8001d8ccc7712acb0e5cff3f1780f21dbe9c2d62e07f752bdc1825ccb0a089192d7b53d6bd3c931d1814dba13872c78e0a0729b6140c962d7139ec8b65d4d829b8caa1849cfcb52138e11ea49bfca1f1b9d1aa4bfe10ce2b117f060b94fc6957a0df666184a5a3cd85b964d0cf55c65bb88cc68b1d87a04fcf8a736bc9aeb33311c03fc8053cba54253ccf06e64b7005427f884973a0ab7fb0b543e4c5a1107b40494ad6c39e6cda25fbb66d0496277720adedc595f1ba91b637be7ede9777c304261f8be12be1edb68110c83e0eab59725efa55ecd2cb1ee8b1c2b5feb5d1fafd4fa53f89fd8416f15904e73527b1a43f9fc0634571e9cdb72c47e047b9347a92339028cade7feca94f6565d0aa5b27fa9a000e5982a206571caea7ce28e38a00bb43717c0410aa0d32184771c64e871a4a740e983c9b6786c3f571cd7c66cdcefbc189d24b86b38ec5b59fb3c16b6a7064dab61ddc4204452210256cede1686c218a7614a01a2794fbf4e04f39dffc2716c9295cef790a6c3cf67058a75b7d2dc54644f3a139731fd33eb2ca1029d55e7bb6071198d1e02950325b4f04b81253762ecdf88a63cb3b2689b20d4679eac04cc0dd6d3acb4bd6120e65f8b9cd57b082d5467281ce23d8318ded41256ab21984b94eb0fc04a3e6498f601d8eaee012be72c0acd9aa27129969db1ac1e7eaec31a286f05a56e59372610ae579abb712c8f1cb002a1939edc17802985acb112d35f6f888ee4fcca31966d3f887d89b6461ba7533f7d3b7c658ffe8a7c8d9ef2219e999f676afc65041d6d8810b53f02940951be88ca521aab5e50cc90849604f308d6dedffeb56bba246d155dffdec6b4930a22848a85060446127a55e0b9f0599846af58acbf640bac7a581d9530c777aec8766f00d921e47de2fe220366584577c5a518acfabad0b5fa487a239e19fff005204c7b909c247f5cd58f0f672e4fec22cdec7b5744a41321eaf779e19ca26ad4582100751043be3ddbbbe1485e3760ef2ce12d09ead4b9c579bf5587c73584dbf8a6a502ae0b65076ab8d94f05f9a08e66158585adc567d2f7c2b3c2733360866245c347ce14ae065a00cf1cb65008d86bdbabccf71ac3f579a0f1ecf384dc1d72469db054eb3e1a4e2a4e04afa5fb7a648fe16bb68890efe9d79c3d63ec85972977b8da12055290c0032af938feaa3db8cd25a5d4df2962cc6fe82db93df59584b6cec94a62108167bb007f7866c578a24cb4f006c0feb305089e90b5b480b006f0534d8295802386bcf606d56ec8984c30258935513b9acab49ee056046e14fa6d83d5e7162ab1365f20daa467ab61e2f46cbff2cd36d61ba395962936e74d6cdf9ef4a6f3f2281578e73c52f94500a34fb1a738dfbac3c85163c424a29bb02940886f071ecfe6667c5cbb7f829605e585c4b7a7a12129f7b64a0e7668d680070c423938165098b76f516fc74f31475a0f0a80b8fefafd91f6d63a14e3a4700088cdd9401ff99817c05c13754f29b71d3290dc24fde14fe339084f3096c20647ff2262955d26429bf8564af08e14e49cced612114815f0e85abe9c25c80b5a406a60b471ec5f52e87920fb01089d8e2469b398fad0cf5019d544c6c5940e18a82f88215586bf793f829780b2544e202771fcc851aff308343bfc08aaeec077211692302493b2083b4f4a93d36eeb3ce4e912ef900b73401f363de79f3771cde67d8972b448efb13c0c5d85efc18d96a6098ef2f0437e4a35bab9beb401b1bb6fb418e39bb6c2a8f5cbc7cc09ac6840c8c63b433fcd0918509a1a76ab7f97c652512660ec26fdf6a9071d685e629ba47c826386ed5b383b903140fe02322389686a841ac4672cd6b9833f247185d2c1513d82a8bdf9d563577d5813590a1b226db2453ed799f54c08cc881e38e115381bcd84d0280d302e154fbad97e6104773a6016a426bf4e6ff1b76774ec2e907725ec2767df35e1c8f3ea56148fdd161fc4c22a187438eb1d7a57e9f46cc11e7298998b4eb9e6769950dbb00b7d37fb6797e04c0ecda430b30b5f3534f7452c794446bc770f4e067e78137d03c1c8f46ff3b3b26d41b09cdafb1fa5b64e54a0241aab6d8033a30be4c9da9d133a7081948709571198706705073bc19f1d7caa0deb853d5e34d7518d5d84ac1dd077b152be4cac12596a8e3f777164cede56d17acabf11292e12fd19aa3e9d46af45aff8740b770a8adf835db4776da3e74732d6d92a11ccfa8f2af5381d4763d71d35fc01d99c99b78dd04befb428c795ef0000a82279fcdff8b3fcf242cb0e871f612c345e06cce68895f78d76af7218bfa86e7634e0df9321bcd056d7e17c68909ea0fff3c56777c8ddf999400ddb63a9943342659e4f165588de5682a72a8b3ec75661cafc109bd0390291a716b089822c98367e026d56e395290dc9fb5afd02af6cd3a50b3e636e90fef7a91e8e1c5f5718d9b74cad3e1100a6b04fd67b4a5c6d584392ccc316f32c4b77616b5f777890b90673c1a8c18b88ab30f3346c7dede3cb248dc561f1e6ef8cdca8187f7cbbb4964bd13c3c2dccaa9d65a55903f65024c7f84421d5620dd4391607c48d082cdc4602030e675df919c9086e2611b5a8f2a28af20dad73bd2820b0ffe951004f6e0ec24d1ccc56c09620d60a2ad4372db56261de835613ddff6d041fbb296112c3edae97e4f4182ec42628de64a1a44c4900c8fa4fb546c0086653960c62f23b61efde829c73614d2c3566e15356d58ecbf1f5979475e90ba181aadea0e00ba066e323f69b241dcbfe4e424c8095119df956f84d12391c954396d0653ee7899d89d5590b0cda74453794d95dcd9e5b326f2beaf3cfc0e6293e8b0eaa44434c68cf05f1ced176b98d9c7d17376cd89762e0289952829f5cf23e93fa76383bb1aa672811e0f4d4aff86557a049abda48712ba849fe3e8decbaa795bd1b5ba758a6743f6355c465886de29e03b32b0efd99b1634f691496e7b4fe10f4da0d439e6fa6ee37b8403274c53a85a56d1db9c8b1a22c5b6e6f7626d5000da24ac9092b18a8701172f7a16910e7a9aba1565a6f011b37e925a26fc3ab7c88ad86825be8e713122aeac73a4471b530839af9d380283763c96b1c540131891be99fb8f945e58f74246f84747e9d08a3d475ed37ff7ccc9b413ab381bcb3c38bb4f1cea954ba0c7f8be91ca56ac975aa6ec1d1a778183e79c91e627493524ed0d4d7292147ef65b1817942d6266f07951da5c4cf7203bf30c0fddf7d56e2902e243de7f66ab3fb16969bbfd972e22b3c5df5d1254e61074acd2d1f583340e76d00bed7c839af9a056f96ab7c9efd6167e59396a5f3c60eb7c23028db58a4b959ff6f0292879e42c7d71111d61270503f1439467b31723adb6bfd1a32295452072dbdec9a657d47fdfd879a8d42c16275a30b4ebf594fe0a0b4434869bf4d4a0da1602e6e874b472d3ae79cf068ed6484f6d3a847f4eb999e1428883af76c9276306cebfa22fe36f9b0e627731497626f161463e016fb47e142b7b5a8526e0a0cb38f9f4e5ab35a6b33262edba080e9ec6a299362e59dcac579dbae5375633fc9306b24d3e2da080d0c5591d3c1cf87a5b2283dfea003e15b5915ff2be1c7e0a273ce85c07fd8f6e3276c11fd495530e26ab4d2f994640af363b8d4dc7", 0x1000}, {&(0x7f00000004c0)="ba19ced6ab2c8366045d9f7939d7ad5c0bace5d22faa8cb74f92f679195dd88601229d6d30eb2cbf076a3b6d268f521c0816c479a0567c6ec2a69b06ed841045ab54c74f81598aa4cbc60c1ca3a9ebbf250d998350b912591fc3c058747ea672f910ea2a765cd8f53f678b8c0c791db5db0cc7f2bf848ae96865f7e74b5570e695ef41736a7abd9d156546b0d0021f", 0x8f}, {&(0x7f0000000140)="e16b4bbc51a8258105c5e4824a504b9df2d8f08cf7b59544a692eb93a17a5be09e9fe4f65fb3390e595e2872d098772ec758c5a08b", 0x35}, {&(0x7f0000000280)="000000000000050000000000", 0xc}, {&(0x7f0000000340)="3643a4eb50c2a4dd17818a9a3054adb71456b1173d43f8815badd8a6dc8fa7bc51850f6854d3c74381deaeddea10ce0e5d4295e27b390d396ec806", 0x3b}, {&(0x7f0000000600)="470e7bd83345572f1420f8eb84e9ae5dc4baaa7d3ef9512506a4cfe4c059df09d62a615d6f948e6cdf39cee56210dc50913560e6962a24e008e5d87da333350f38d52508671b3692cd36769cbb9050b11fbbcb12891c1d4a596853897a8a", 0x5e}], 0x7)
socket$inet(0x2, 0x1, 0x0)
socketpair$unix(0x1, 0x3, 0x0, &(0x7f00000000c0)={<r4=>0xffffffffffffffff})
getsockopt$sock_cred(r4, 0xffff, 0x1022, 0x0, 0x0)
getsockopt$sock_timeval(r4, 0xffff, 0x1006, &(0x7f0000000380), &(0x7f00000002c0)=0x10)
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x100, 0x0)
ioctl$BIOCSETF(r5, 0x80104267, &(0x7f0000000000)={0x4, &(0x7f0000000080)=[{0x824}, {0x34, 0x0, 0x2, 0x4}, {0x16}, {0x1f34, 0x8, 0x3, 0x81}]})
fchownat(0xffffffffffffffff, &(0x7f00000003c0)='./file0\x00', 0x0, 0x0, 0x2)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
kevent(0xffffffffffffffff, 0x0, 0xffffffff, 0x0, 0x6, &(0x7f0000000240)={0x0, 0x5})
r6 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r6, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)


socketpair(0x1, 0x5, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff})
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
getpeername(r0, 0xffffffffffffffff, &(0x7f00000010c0))


r0 = socket(0x18, 0x2, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001600)={0x0, 0x0, 0x0, 0x0, &(0x7f0000002c40)=ANY=[@ANYBLOB="10000000ffff000001"], 0x10}, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000080)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
r3 = dup2(r2, r0)
recvmsg(r3, &(0x7f0000000200)={0x0, 0x0, 0x0, 0x0, &(0x7f00000004c0)=""/11, 0xb}, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000001c0), &(0x7f0000000200)=0xfffffffffffffe50)
execve(0x0, 0x0, 0x0)
sendmmsg(r1, &(0x7f0000001600)={0x0}, 0x10, 0x0)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$inet(0x2, 0x1, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x40, 0x0, 0x0)


mknod(&(0x7f0000000180)='./file0\x00', 0x2000, 0x202)
r0 = open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000ffc000/0x1000)=nil, 0x1000, 0x5, 0x10, r0, 0x0)


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x67, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCLOCK(r0, 0x20004276)
seteuid(0xffffffffffffffff)
ioctl$BIOCGSTATS(r0, 0x4008426f, &(0x7f0000000880))


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000006c0), 0x1, 0x0)
writev(r0, &(0x7f0000000380)=[{0x0}], 0x1)
execve(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffff9c, 0x80104277, 0x0)
socket$unix(0x1, 0x0, 0x0)
msync(&(0x7f0000952000/0x2000)=nil, 0x87abbe8d1cc6ad9, 0x0)
r1 = getpgid(0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x4)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYRES8=r1])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
sysctl$kern(&(0x7f0000002240)={0x1, 0x3a}, 0x2, 0x0, 0x0, 0x0, 0x0)
setitimer(0x0, &(0x7f0000000000), 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
munmap(&(0x7f0000000000/0x1000)=nil, 0x7f7fffffc000)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r2 = socket(0x2, 0x1, 0x0)
shutdown(r2, 0xffffffffffffffff)
recvmmsg(r2, &(0x7f0000000240)={0x0}, 0x10, 0x1, 0x0)
pipe(&(0x7f0000000040))
syz_open_pts()
syz_open_pts()
getsockname$inet(0xffffffffffffffff, &(0x7f0000000140), &(0x7f0000000180)=0xc)
setegid(0xffffffffffffffff)
r3 = msgget$private(0x0, 0xb)
setuid(0xffffffffffffffff)
setgid(0x0)
msgrcv(r3, 0x0, 0x0, 0x0, 0x0)


sysctl$kern(&(0x7f0000000000)={0xa}, 0x3, 0x0, 0x0, 0x0, 0x0)


sendmsg(0xffffffffffffffff, 0x0, 0x0)
sysctl$net_inet6_icmp6(&(0x7f0000000000), 0x7, &(0x7f0000000040)="d69096f07ed81b37a5ffa907803c4f016100555e83b8b1e695fa115f93f0861077b79f272cb3ff83d3f4d4f787e83d790882e7685abaa4f6cdf5c7ddbae09180620d7f0fde156573635eb29e36d8c5e607e76d24bb1a965f857142f6f655fd9a3d2ae72e8f31e7a05ea4b1337d2b7c86f1f12c", 0x0, 0x0, 0x0)
pwritev(0xffffffffffffffff, 0xffffffffffffffff, 0x58, 0x0)
mknod(0x0, 0x0, 0x0)
mknod$loop(0x0, 0x0, 0x1)
link(0x0, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
setuid(0xee01)
socket(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))


r0 = socket$inet(0x2, 0x3, 0x2)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
r1 = openat$speaker(0xffffffffffffff9c, &(0x7f00000006c0), 0x1, 0x0)
writev(r1, &(0x7f0000000040)=[{&(0x7f0000000100)="147d75e4b7faf289ece28c1cad2429e26d2dc5059aff289c7bfe2a6ce4577f70e6a32d1228aab96ec314f471c0b36e19d5f94063a80c1f73327baa8a72e5b8df512d8bd69ca60784688104d8eb1a76a0c0c14d334b70bedcbcd434a6a0c37b0437e623a6ccbe719e14473ce1a47e7ecfc60b8cbfcb0d1fac8ebe45f77e2eda", 0x7f}], 0x1)
execve(0x0, 0x0, 0x0)
semctl$SETALL(0x0, 0x0, 0x9, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0x4, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0xfffffffffffffe37)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r2 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7949)
writev(r2, &(0x7f00000000c0)=[{&(0x7f0000000080)='#!', 0x2}], 0x1)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x800, 0x0)
kevent(r2, &(0x7f0000000200)=[{{}, 0xfffffffffffffffc, 0x1a, 0xf0000000, 0x7fb, 0x1000}, {{r2}, 0xfffffffffffffffa, 0x4, 0x1, 0xffffffffffffffff}, {{r2}, 0xfffffffffffffffd, 0x40, 0x20000000, 0x3, 0x5000000000}, {{}, 0xfffffffffffffffe, 0xb2, 0xfffff, 0x3ff, 0x99c0}], 0x0, &(0x7f0000000280)=[{{}, 0x0, 0x0, 0x2, 0x8, 0x2d5375e0}, {{}, 0x0, 0x41, 0xfffff, 0xfffffffffffffc01, 0x19}, {{}, 0x0, 0x5a, 0x4, 0x1000000000000a, 0x80000001}, {{}, 0xffffffffffffffff, 0x12, 0xfffff, 0x1, 0x80}], 0x80000000, &(0x7f0000000440)={0x0, 0x200000000008})
syz_emit_ethernet(0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
r3 = socket(0x2, 0x1, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$inet(r3, &(0x7f0000000000), 0x10)
r4 = accept$inet(r0, &(0x7f0000000000), &(0x7f0000000040)=0xc)
writev(r4, &(0x7f00000001c0)=[{&(0x7f0000000080)="01"}], 0x1)
setsockopt$inet_opts(r0, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x40001ff, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
dup2(r1, r0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240), 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000000c0))
sysctl$net_inet_tcp(&(0x7f0000000200)={0x4, 0x2, 0x6, 0x19}, 0x4, 0x0, 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0xffffffffffffffff}})
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000640)={0x0, 0x0, 0x0, 0x0, &(0x7f00000000c0)=ANY=[@ANYBLOB="18000000ffff000001"], 0x18}, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = socket(0x800000018, 0x1, 0x0)
ioctl$PCIOCGETROM(0xffffffffffffffff, 0xc0107005, &(0x7f0000000080)={{}, 0x0, &(0x7f0000000040)})
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x800008, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000000c0)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sysctl$net_inet6_icmp6(0x0, 0x0, &(0x7f0000000080)="65feaba9a71942a5", &(0x7f0000000100)=0x8, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
select(0x40, &(0x7f0000000100), &(0x7f00000024c0), 0x0, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
dup2(r0, r1)


r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r3 = socket(0x2, 0x2, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
connect$unix(r3, &(0x7f0000000000), 0x10)
r4 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x1023, &(0x7f0000000040), 0xe0)
r5 = socket(0x2, 0x4001, 0x0)
r6 = dup(r5)
r7 = fcntl$dupfd(r6, 0x2, 0xffffffffffffffff)
close(r7)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000280), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{0x40}, {}, {0xcc6}]})
syz_emit_ethernet(0x138, &(0x7f00000004c0)=ANY=[])


r0 = socket$inet(0x2, 0x4, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x80, &(0x7f0000000280), &(0x7f0000000200)=0x4)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
ioctl$PCIOCREAD(0xffffffffffffffff, 0xc0107002, 0x0)
openat$speaker(0xffffffffffffff9c, &(0x7f00000006c0), 0x1, 0x0)
getsockname$inet(r0, &(0x7f0000000080), &(0x7f00000000c0)=0xc)
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000001500), 0x0, 0x0)
fcntl$lock(r1, 0x9, &(0x7f0000000140)={0x0, 0x0, 0xfffffffffffffffe, 0x1000000000000, 0xffffffffffffffff})
r2 = socket(0x0, 0x3, 0x0)
socket(0x0, 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
ioctl$WSKBDIO_SETENCODING(r1, 0x80045710, &(0x7f0000000040)=0x83f9)
r3 = msgget$private(0x0, 0x0)
msgsnd(r3, &(0x7f00000001c0)=ANY=[@ANYRES32, @ANYRESHEX=r2], 0x401, 0x0)
msgsnd(r3, &(0x7f0000000540)=ANY=[@ANYRESOCT, @ANYRES64, @ANYRES16=r3], 0x401, 0x0)
msgrcv(r3, &(0x7f0000000400)={0x0, ""/137}, 0xaf, 0x0, 0x1700)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x60}, {0xc}, {0x157e}]})
writev(r0, &(0x7f00000002c0)=[{&(0x7f0000000340)="ebebfd510bbcd3a9b489e989c14f", 0xe}], 0x1)


sysctl$net_inet_ip(&(0x7f00000000c0)={0x4, 0x2, 0x0, 0x11}, 0x4, 0x0, 0x0, 0x0, 0x52)
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
open(&(0x7f0000000180)='./file0\x00', 0x80000000000206, 0x0)


pwritev(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f00000005c0)="dc", 0x1}], 0x1, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = open(&(0x7f0000000240)='./bus\x00', 0x0, 0x0)
pread(r0, &(0x7f0000000040)="3cd15db7c30016", 0x50cc00, 0x0)
ioctl$WSDISPLAYIO_LSFONT(r0, 0xc058574e, &(0x7f0000000100))
sysctl$net_inet_udp(&(0x7f0000000000)={0x2, 0x4}, 0x2, 0x0, 0x0, 0x0, 0x0)
r1 = socket(0x18, 0x2, 0x0)
msgctl$IPC_STAT(0x0, 0x2, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x83fe})
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = socket(0x2, 0x2, 0x0)
r3 = dup(r2)
setsockopt$inet_opts(r3, 0x0, 0x14, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
r4 = fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffff9c)
close(0xffffffffffffffff)
mquery(&(0x7f00004ef000/0x2000)=nil, 0x2000, 0x0, 0x0, r4, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, &(0x7f0000000000))
setsockopt(r1, 0x1000000029, 0x3e, &(0x7f0000000000)="674cd6e5", 0x4)
writev(r1, &(0x7f0000000080)=[{0x0}], 0x1)


mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x205b1a)
r0 = open(&(0x7f0000000080)='./bus\x00', 0x2, 0x0)
pwritev(r0, &(0x7f0000001840)=[{0x0}, {0x0}, {0x0}, {0x0}, {0x0}, {0x0}, {0x0}, {0x0}, {0x0}], 0x9, 0x57)
sysctl$kern(&(0x7f0000000300)={0x1, 0x16}, 0x2, &(0x7f0000000340)="0e", &(0x7f0000000400)=0x1, &(0x7f0000000800), 0x0)
poll(0x0, 0x0, 0x0)
setitimer(0x2, &(0x7f0000000000)={{}, {0xffffffff}}, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_RUN(0xffffffffffffffff, 0xc0205602, &(0x7f0000000140)={0xb6e, 0x5, 0x5e, 0x6, &(0x7f0000000300)={{0xfb, 0x7f, 0x2, 0x93, 0x4, 0x7, 0x2}, {[0x0, 0x0, 0x0, 0x101, 0x4, 0x9, 0x20, 0x201, 0x5, 0x1520, 0x80, 0x7f, 0x2, 0x1, 0xfffffffffffffb7b, 0x0, 0xa9, 0x2000000003], [], [0x3, 0x7, 0x3, 0x2, 0xd72c, 0x10], [0x80000000, 0x2f9, 0x7, 0x0, 0x0, 0x2], [{0x0, 0x77000, 0xfffffffe, 0x7}, {}, {}, {}, {0x1f, 0x8, 0xe76}, {0x0, 0x8, 0x289a, 0x4}, {0x20, 0x277a, 0x7, 0x15ea5bf3}, {0x9, 0x22, 0x6}], {0x800, 0x4, 0xfffffeff, 0x4003}, {0x4, 0x7f}}}, 0x0, 0x2d})
accept$inet(0xffffffffffffffff, 0x0, 0x0)
getsockname(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r2 = socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc018696c, &(0x7f00000001c0))
open(&(0x7f0000000940)='./file0/../file0\x00', 0x0, 0x0)
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000340), &(0x7f00000003c0)=0xc)
readv(r1, &(0x7f0000000ac0)=[{0x0, 0xb39f21312f496fd4}, {&(0x7f0000000080)=""/31, 0x1f}], 0x2)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000100)={0x2, &(0x7f0000000000)=[{0x45, 0x0, 0xff}, {0x906}]})
syz_extract_tcp_res(0x0, 0xfffffffe, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
socket(0x18, 0x2, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f00000002c0)=""/50, 0x32}], 0x1)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1800000029"], 0x3e}, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000100)="10", 0x1}], 0x1)
execve(0x0, 0x0, 0x0)


socket$inet6(0x18, 0x3, 0x0)
r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x39, &(0x7f0000000000)="5ab7776a", 0x4)
syz_emit_ethernet(0x4e, &(0x7f0000000140)=ANY=[@ANYBLOB="aaaaaaaaaaaa7fd67572210786dd6007558300183701fe8000000000000000000000000000aaff020000000000000000000000000001"])
r1 = socket(0x11, 0x3, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x3, 0x0, "0100012d29fb000700000000098002005a00"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x45}, 0x3, &(0x7f0000000180)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b10689ca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d12727b1e1d0cc45c7ebd5df53fb588fd0245528fe5700a5868eaf74d373197fb657a56e99cdbddbb382ad676b756d4e8b5a81c9a624348f23ffd260bf5fd344a7a30bcf96e47800acc166910bfc34ce76252dd12fac3b10dd5719aa6e420f60e3d2cbb22f5b3a6f7fa3c909e4823cdc0cdf126bc29456035b9a44ff74d852ba5c", &(0x7f0000000080)=0xaa, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0xffffff25)
sendto$unix(r1, &(0x7f00000002c0)="b10005010000009f0500070107000000331c13fecea70500fef96ecfc72fd3357ae30200004e30ffd2d236acf20bf404be01000000f7c8cf5f882b297be1aa050400ce94e2f1ad3ebbc257699a1f139b672f335c22db830c032bfa896443c32118210000720f00000000000080012519b40057aea8c500001602fbfe0c2300008abfba09a214cc8adfbfba11ce00000808e37193f8343f00000000b71dc00009000500"/177, 0xb1, 0x0, 0x0, 0x0)


mknod(0x0, 0x2000, 0x0)
open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
mkdirat(0xffffffffffffff9c, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x2, 0x1}, 0x4, 0x0, 0x0, &(0x7f0000000080), 0x0)
munmap(&(0x7f000000e000/0x400000)=nil, 0x400000)
sysctl$ddb(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = socket(0x0, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0206923, &(0x7f00000001c0))
ioctl$FIONREAD(0xffffffffffffffff, 0x8040691a, &(0x7f00000001c0))
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b", 0x50, 0x0, 0x0, 0x0)
r1 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1023, &(0x7f0000000040), 0xe0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0x0, 0x0, 0xffffffffffffffff, 0x0, 0x42}, 0xfeffffffffffffff})
socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
kqueue()
socket(0x0, 0x0, 0x0)
syz_emit_ethernet(0x3e, 0x0)
r2 = socket$inet(0x2, 0x1, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1021, &(0x7f0000000000)=0x5, 0x4)


dup(0xffffffffffffffff)
clock_getres(0x3, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
r0 = socket(0x0, 0x4000, 0xfd)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x46, &(0x7f0000000140)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa860600cb54650010000000000000000031ea000000000000000000000000000000000000ffffac1400aa00000005000000004e214e2200089078"])
lstat(&(0x7f0000000000)='./file0\x00', &(0x7f0000000280))
openat$zero(0xffffffffffffff9c, &(0x7f0000000200), 0x20, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x33}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x14, 0x0, 0x37)
r1 = socket$inet(0x2, 0x2, 0x0)
ioctl$FIONBIO(r0, 0x8004667e, &(0x7f0000000300)=0xfffffffb)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00fd6500000000", 0x8)
r2 = socket$inet(0x2, 0x5, 0x3)
close(r2)
socket$inet(0x2, 0x2, 0x0)
pipe(&(0x7f00000001c0))
socket(0x2, 0x0, 0x0)
socket$unix(0x1, 0x5, 0x0)
recvfrom$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
sysctl$net_inet_ipip(&(0x7f0000000000)={0x4, 0x2, 0x4, 0x1}, 0x4, &(0x7f0000000080), 0x0, &(0x7f0000000440), 0x0)
setitimer(0x0, 0xfffffffffffffffe, 0x0)
semget$private(0x0, 0x7, 0x3c0)
sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x2, 0xc}, 0x4, 0x0, 0x0, &(0x7f0000000080), 0x0)
socket(0x0, 0x3, 0xfc)
open(&(0x7f0000000040)='./file0\x00', 0xfffe, 0x51)
setreuid(0xee00, 0x0)
openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})


sysctl$vm_swapencrypt(&(0x7f0000000000)={0x2, 0x5, 0x3}, 0x3, &(0x7f0000000040), 0x0, 0x0, 0x0)


pipe(&(0x7f00000001c0)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
poll(&(0x7f0000000040)=[{r1, 0x40}], 0x1, 0x0)
close(r0)
readv(r1, &(0x7f0000000240)=[{0x0}], 0x1)


open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
fsync(r0)


syz_emit_ethernet(0x4e, &(0x7f00000003c0)=ANY=[@ANYBLOB="aaaaaaaaaaaa7fd67572210786dd6007558300183701fe8000000000000000000000000000aaff020000000000000000000000000001"])
syz_emit_ethernet(0x56, &(0x7f00000003c0)=ANY=[])


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f0000000040)=0xfffffbfc)
writev(r0, &(0x7f0000001b00)=[{0x0}], 0x1)
writev(r0, &(0x7f0000000280)=[{&(0x7f0000000240)='\t', 0x1}], 0x1)
readv(r1, &(0x7f0000000640)=[{&(0x7f0000000600)=""/9, 0x9}], 0x1)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETAW(r0, 0x802c7415, &(0x7f0000000000)={0x0, 0x0, 0x9, 0x6bf, "28113bb1e6648a1a267bc03b7a447ab255dcd9f0"})
readv(r1, &(0x7f0000000040)=[{&(0x7f00000000c0)=""/121, 0x79}], 0x1)
writev(r0, &(0x7f00000003c0)=[{&(0x7f0000000140)="1392b87236beea9f6599a696e755366a99f04aa4d4c9e1501498f84827eed7d089f820a31c222f4b1080463fcdd5b9687775d12fdfa86e4ae337c535595fe99e398cec150eca9e07e52340641489d3ccf5149726be94", 0x56}, {&(0x7f00000001c0)="a65932cf587178fe7f68b7edf185eb2c9cfacad5fbd65d2c74427837fac2d462387d1c279c6eb20c38475c78821107140a2807e49e4c5835949fa841716ec4c62a5fac807e945cb22092b27a512d36beeeef523d5e6538", 0x57}], 0x2)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
socket(0x18, 0x2, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f00000002c0)=""/50, 0x32}], 0x1)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1800000029"], 0x3e}, 0x0)
execve(0x0, 0x0, 0x0)


socket(0x0, 0x0, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
pwritev(r0, &(0x7f0000000380)=[{&(0x7f0000000440)="e9", 0x1}], 0x1, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000240)=[{0x81}, {0x84}, {0x6}]})
syz_emit_ethernet(0x2a, &(0x7f00000000c0)=ANY=[])


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
r0 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
r1 = getpid()
fcntl$setown(r0, 0x6, r1)
fcntl$setown(r0, 0x6, 0x0)


mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETAF(r1, 0x802c7416, &(0x7f0000000100)={0x978b, 0x0, 0x7fff, 0x80a19f, "14000000000000714543e43382069400"})
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x0, 0x0)
pipe(&(0x7f0000000100))
pipe(&(0x7f0000000200)={<r0=>0xffffffffffffffff})
fcntl$setstatus(r0, 0x4, 0xc0)
r1 = kqueue()
socket$inet(0x2, 0x1, 0x0)
kqueue()
socket$inet(0x2, 0x2, 0x0)
socket$inet(0x2, 0x2, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140))
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000080)={<r2=>0xffffffffffffffff})
openat$pf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
openat$pf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000080))
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000080))
r3 = fcntl$dupfd(r2, 0x0, r1)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000240)=[{{r3}, 0xfffffffffffffffa, 0x95}], 0x0, 0x0)
kevent(r1, &(0x7f00000001c0), 0x9, 0x0, 0x9, 0x0)
r4 = getpid()
fcntl$setown(r0, 0x6, r4)
close(r0)


sysctl$kern(&(0x7f0000000080), 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)
r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
mkdir(&(0x7f0000000000)='./file2\x00', 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x2, 0x2, 0x0)
connect$inet(r3, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r2, 0xffff, 0x1023, &(0x7f0000000040), 0x4)
select(0x2, 0x0, &(0x7f0000000040), &(0x7f0000000080), &(0x7f00000000c0))


r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$PCIOCWRITE(r0, 0xc00c7006, &(0x7f0000000300)={{0x0, 0x5}})


r0 = socket(0x18, 0x3, 0x0)
openat$wskbd(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f0000000000))
open(0x0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
ftruncate(r1, 0x0)
r2 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x8000, 0x0)
r3 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r3, 0x801169ab, &(0x7f00000001c0))
mquery(&(0x7f0000ffa000/0x3000)=nil, 0x3000, 0x2, 0x0, r1, 0x7f)
ioctl$WSDISPLAYIO_LSFONT(r2, 0xc058574e, &(0x7f0000000500))
getpid()
ioctl$WSMOUSEIO_SRES(r2, 0x80045721, &(0x7f0000000cc0)=0x3f)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000740), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000100)=[{0x3}, {0x80}, {0x8016}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x4e, &(0x7f00000004c0)=ANY=[])


r0 = fcntl$dupfd(0xffffffffffffffff, 0x2, 0xffffffffffffffff)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000180)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0xfffe, 0x0)
setreuid(0xee00, 0x0)
chmod(&(0x7f00000000c0)='./file0\x00', 0x21e)
r3 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r4 = dup(r3)
faccessat(r4, &(0x7f0000000040)='./file0\x00', 0x2, 0x0)
r5 = socket$inet6(0x18, 0x3, 0x0)
r6 = kqueue()
kevent(r6, &(0x7f0000000340)=[{{r5}, 0xfffffffffffffffe, 0x7b}], 0x9, 0x0, 0x0, 0x0)
shutdown(r5, 0x2)
dup2(0xffffffffffffffff, r0)
recvmsg(r2, &(0x7f0000000200)={0x0, 0x0, 0x0, 0x0, &(0x7f00000004c0)=""/251, 0xfb}, 0x0)
sendmsg(r1, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)


open(&(0x7f0000000280)='./file0\x00', 0x615, 0x0)
open$dir(&(0x7f00000000c0)='./file0\x00', 0x20, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
execve(0x0, 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000040)=[{}, {}, {0x7, 0x0, 0x0, 0xffff33c4}]})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x6, &(0x7f0000000080)="ae215599fed2fce97f573b9c553a0e622d29cd093849cd4fe42e0f5d2d06a4e744f0713d1fcaa1b8274dffd067d413ef9d2224d3fddc171f73a295b6ed18b3d0588be75e78a1d734e15bfe", 0x0, 0x0, 0xfffffffffffffd37)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x2)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000300)={0x2, &(0x7f00000000c0)=[{}, {0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4e}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x2000, 0x0, 0x37)
pwritev(r0, &(0x7f0000000540)=[{&(0x7f0000000140)="9a1a99fa3a8b90c7c99a1ede4b4cbd0b", 0x10}, {&(0x7f0000000180)="764d2b8fb0fd322a725f3b11ee", 0xd}, {&(0x7f00000002c0)="335748b44523c169b48c1f7a091865986fac85de14512947979c930269b04319a8df71801a6b6c13a8f093beb77d5c9b09acb99bdc6dcfe421efec8515bed8f047c86b19ebbd2a85b2ad9f5c3a6bdbb678a587d1bc1931498ea12ed5a07c5892770bbf899bb26e1e7dc1c64dda1e0081565d39f4a4242116d86c43eb37cd016a9a01841dadcc1f9e069673a4888ded00f2e0e3a62f6613cf4d1c8552e2425c06f6fbcdf7a1efafbabb71825997a030ca040f79eba046e67a5a44ad165589703eedb7", 0xc2}, {&(0x7f00000001c0)="d0457de4d20f5631b5bed4b1c8609b01377ddcf5d475", 0x16}, {&(0x7f0000000200)="8be2a49de9a41b06cdf5c4433c4585cab1f65212a137fc1e46596efd6dc448fa3dac979bcef807c1898f732b720a4652ada2282998c41f06cab64a4e522d04969432b30051d639379aa2c0ff5411ad2a5d577f3629fed5b8c2026f5799fd5f", 0x5f}, {&(0x7f00000003c0)="4834e754551d0ce5f65875c7b0d7874b562661070a08", 0x16}, {&(0x7f0000000400)="3c706a6c6b4486a5536edf85f3123a0c09c6c0aea00423c078310917887bba03a10f40a89d0defe1d8908c3c5970ba7b9fab6266b86629809662c5484fe5b1da2ac0a66b72e0a2b085db03bb8b2c2e570878ead35492008369559b340a6a0f10ea307272e634a75aaa4aaffc829122cacf4eb2d955baf51e015fcf7f5a3d92fa04b73109", 0x84}, {&(0x7f00000004c0)="bc03e05797de56df504cf2192d132928b8e92d812c2f916ab7201e619b7814220c2142998eba1432370304f565da5eeeb13665026018fef5b71c4638dde3cd48bc19eca588d2091f69fe304ac54e0e5325da5475942732106d32a165acc7c458920ac6f0c86fd7a14ebc15", 0x6b}], 0x8, 0x1)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000001240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
sysctl$net_inet_udp(&(0x7f0000000240)={0x4, 0x2, 0x11, 0x2}, 0x4, 0x0, 0x0, 0x0, 0x0)
r1 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
r2 = socket$inet(0x2, 0x2, 0x0)
r3 = socket$inet(0x2, 0x2, 0x0)
dup2(r3, r2)
setsockopt$inet_opts(r3, 0x0, 0x200000000000a, &(0x7f0000000000)="ea00005c00000000", 0x1)
setsockopt$inet_opts(r2, 0x0, 0xd, &(0x7f0000000240)="ea00fff100000000", 0x8)
ioctl$WSKBDIO_COMPLEXBELL(r1, 0x8004570b, &(0x7f0000000180))
symlink(&(0x7f0000000ac0)='./file0\x00', &(0x7f0000000e40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000f40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000300)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000200)='./file0\x00')


r0 = socket$inet(0x2, 0x4, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x80, &(0x7f0000000280), &(0x7f0000000200)=0x4)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
ioctl$PCIOCREAD(0xffffffffffffffff, 0xc0107002, 0x0)
openat$speaker(0xffffffffffffff9c, &(0x7f00000006c0), 0x1, 0x0)
getsockname$inet(r0, &(0x7f0000000080), &(0x7f00000000c0)=0xc)
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000001500), 0x0, 0x0)
fcntl$lock(r1, 0x9, &(0x7f0000000140)={0x0, 0x0, 0xfffffffffffffffe, 0x1000000000000, 0xffffffffffffffff})
syz_open_pts()
ioctl$TIOCSPGRP(r1, 0x40047477, &(0x7f0000000180))
syz_open_pts()
socket(0x11, 0x0, 0x0)
r2 = socket(0x0, 0x3, 0x0)
socket(0x0, 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
r3 = msgget$private(0x0, 0x5)
pipe2(0x0, 0x0)
msgsnd(r3, &(0x7f00000001c0)=ANY=[@ANYRES32, @ANYRESHEX=r2], 0x401, 0x0)
msgsnd(r3, &(0x7f0000000540)=ANY=[@ANYRESOCT, @ANYRES64, @ANYRES16=r3], 0x401, 0x0)
msgrcv(r3, &(0x7f0000000400)={0x0, ""/137}, 0xaf, 0x0, 0x1700)
r4 = syz_open_pts()
ioctl$TIOCCONS(r4, 0x80047462, &(0x7f0000000240)=0x2)
r5 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x40, 0x0)
pread(r5, &(0x7f0000000000)="2beba8c5bfaaff44b437dfbb000000", 0xf, 0x7fffffff)
listen(r0, 0x81)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000340)=[{0x20}, {0x15}, {0x46}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f00000000c0)=[{0x6c}, {0x5c}, {0x406}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


getgroups(0x3, &(0x7f0000000180)=[0x0, 0x0, 0xffffffffffffffff])
mknod(&(0x7f0000000040)='./file0\x00', 0x2000, 0x3200)
r0 = open$dir(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
preadv(r0, &(0x7f0000000140)=[{&(0x7f00000000c0)=""/86, 0x63}], 0x1000000000000138, 0x0)


mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x205b9a)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
writev(r0, &(0x7f0000000240)=[{&(0x7f0000000280)="a8034e3fdd86480e82b02009", 0xc}], 0x1)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x60, 0x0)
r0 = socket(0x11, 0x3, 0x0)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000240), 0x80, 0x0)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r1, 0xc2585601, &(0x7f0000000340)={0x10, 0x0, [{&(0x7f00000a0000/0x1000)=nil, &(0x7f0000ffb000/0x4000)=nil, 0x10000}, {&(0x7f00000a7000/0x2000)=nil, &(0x7f0000ffe000/0x1000)=nil, 0x7f0000}, {&(0x7f000008e000/0x11000)=nil, &(0x7f0000090000/0x1000)=nil, 0x8000100000000}, {&(0x7f00000a7000/0x1000)=nil, &(0x7f000009a000/0x2000)=nil}, {&(0x7f00000a3000/0x2000)=nil, &(0x7f000009e000/0x2000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000091000/0x2000)=nil, &(0x7f00000a4000/0x3000)=nil}, {&(0x7f000009d000/0x4000)=nil, &(0x7f00000a6000/0x2000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {&(0x7f000009e000/0x1000)=nil, &(0x7f000009d000/0x2000)=nil}, {&(0x7f00000a6000/0x3000)=nil, &(0x7f00000a8000/0x4000)=nil}, {&(0x7f00000a1000/0x1000)=nil, &(0x7f00000a7000/0x2000)=nil}, {&(0x7f0000ff9000/0x1000)=nil, &(0x7f00000a4000/0x2000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000099000/0x1000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f00000a6000/0x2000)=nil}, {&(0x7f0000097000/0x1000)=nil, &(0x7f000009a000/0x2000)=nil}], './file0\x00'})
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
setrlimit(0x0, &(0x7f0000000980))
r2 = syz_open_pts()
syz_open_pts()
syz_open_pts()
fsync(r2)
sendto$unix(r0, &(0x7f0000000000)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)='\x00', 0x1}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
setsockopt$inet_opts(r0, 0x0, 0x200000000000b, &(0x7f0000000080)="02", 0x1)


open(0x0, 0x0, 0x0)
ktrace(0x0, 0x0, 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
r0 = socket(0x18, 0x2, 0x0)
r1 = dup(r0)
setsockopt(r1, 0x1000000000029, 0xb, &(0x7f0000000080), 0x4)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000000)="00020000", 0x4)
r2 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x6}, {0x2, 0x0, 0x0, 0x40804}]})
ioctl$DIOCMAP(0xffffffffffffffff, 0xc0106477, &(0x7f00000000c0)={0x0, r2})
acct(0x0)
getpeername(r1, &(0x7f0000000040)=@un=@abs, &(0x7f0000000140)=0x8)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


mkdir(&(0x7f0000000100)='./file0\x00', 0x0)
r0 = socket(0x2, 0x1, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
open$dir(&(0x7f00000001c0)='./file0\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
recvmsg(r3, &(0x7f0000000340)={0x0, 0x0, 0x0, 0x0, &(0x7f00000024c0)=""/236, 0xec}, 0x0)
chroot(&(0x7f0000000180)='./file0\x00')
sendmsg(r2, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])
syz_emit_ethernet(0x62, &(0x7f00000002c0)=ANY=[@ANYRESOCT, @ANYRES32])
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000240)=[{0x5d}, {0x54}, {0x46}]})
getpid()
r0 = socket(0x2, 0x2, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000180)={0x2, &(0x7f0000000040)=[{0x28}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r2 = open(&(0x7f0000000080)='./file0\x00', 0x1, 0xc8)
ioctl$WSDISPLAYIO_SMODE(r2, 0x8004574c, &(0x7f00000000c0)=0x2)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r0, &(0x7f0000000000), 0x10)
write(r0, &(0x7f0000000240)="14bdfa5d1d34e2fecb284a6498307dcda9aec43050036123339a346f737850551408753f95b7688ad4c4e1dd5489e7bafc58d3e5823757ae8b630719ef187ccad9", 0x41)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000040)={0x0, 0x1ff, 0x20000083, 0x5773c5bc, "80347e7bc3cd7eb6000000000000000800"})
ioctl$TIOCMSET(r1, 0x8004746d, &(0x7f0000000000)=0xfffffc2a)
writev(r0, &(0x7f0000000080)=[{&(0x7f00000009c0)="cf63fccf005a9d45f0faeb23d96a696f7f77b151fedf96d63ec5e7849472043594136a3c55b6e45944ff6352b1ae2458fd167d6b88735e2026b14a996199855664308a3381a03ae6b87504842cc8b97f7c5478fbadda28cb7d5853e85d0572db4742fc6a38be642f2efd295033b0ca09a5d66ff9400ec29d8b8b62dc1d103c1ab61a18c34afa29011665318709e8160a29bd293b9e9efadef1a44e7a103293bff34d22d491e1b86fe3121401e4e224568214658676e4b8fe6660792497fd669c4c9068e34d5d4fe090ddee32bd9798a5f6b3cac4a9875e80fecdefc78e3d28b1b918da35f29b7f8b8c7b05712212ed0253e877a287de9bd0515d6086324550abb36a4696e175a2cfbec1be567f48a50ce561b4122cff8acce1b20259509a594515e1723d26d17a92bdce80cff01cfa84894c5ebde76657bd6f254b6de2d0dc8311201a369cbfea72e1853b4b24815860e146f18059eb258c48d66709556c927d6905e783dd5fbdda17412e4ad065311360757e954f2b601087cf21373e38dfcf1e3cc8967ea2850a17aff2ab5e3ab3faa477048d790b8ee5cdc1920df54bb2caa135b78133c0b48af99d13c21b5d055ade0bcc56ae7417e20255ffb7faa4e74a0763ecfd6ffe07fd969b008597fadd3eb609332b46b273404342a63a0f211680a8cb43c79249520c67418d73d34ac6e5becf5f1d01cdd85e053bbfe29d25b3391a558dc2a9910ff2f2f24ad5d8bba251e0129895be87d8fe27b1d2826e650d8fec1a56b0a430de1995d61363c15684ed682b1b92bff7c086cc078e645b00d11303adbafe9e47fe43cb392ea10e47c6aace9c93aa04082ddff2d49f8500e29b27c3", 0x261}], 0x1)
r2 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r3 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$DIOCMAP(r3, 0xc0106477, &(0x7f0000000200)={&(0x7f00000002c0)='./file0\x00', r2})
close(r2)
bind$unix(r2, &(0x7f00000000c0)=@abs={0x0, 0x0, 0x1}, 0x8)


ioctl$TIOCMBIS(0xffffffffffffffff, 0x8004746c, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
pwrite(0xffffffffffffffff, 0x0, 0x0, 0x0)
r0 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000140), 0x1, 0x0)
ioctl$TIOCCDTR(0xffffffffffffffff, 0x20007478)
ioctl$TIOCSETAW(0xffffffffffffffff, 0x802c7415, 0x0)
getpeername$inet(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x0, 0x0)
open(0x0, 0x0, 0x0)
fcntl$getown(r0, 0x5)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
mknod(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000700)=[{0x7, 0x0, 0x0, 0x400}, {0x2c}, {0x6, 0x0, 0x0, 0x100000}]})
write(r0, &(0x7f0000000740)="76e5dead6f01f8607d2100000063", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{0x30}, {0x3c}, {0x16}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f0000000080)=ANY=[])


r0 = socket(0x18, 0x3, 0x0)
getsockopt(r0, 0x29, 0x36, 0x0, 0x0)


mkdir(&(0x7f0000000100)='./file0\x00', 0x49)
setreuid(0xee00, 0x0)
r0 = getuid()
chown(&(0x7f0000000040)='./file0\x00', r0, 0xffffffffffffffff)
r1 = open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
fchdir(r1)
mkdir(&(0x7f0000000100)='./file0\x00', 0x0)
r2 = getuid()
setreuid(0xee00, r2)
rmdir(&(0x7f0000000080)='./file0\x00')


r0 = socket(0x11, 0x3, 0x0)
symlink(&(0x7f0000000100)='./file0\x00', &(0x7f0000000140)='./file0\x00')
sendto$unix(r0, &(0x7f0000000400)="b1000504600000000000000007000000331c13fecea10500fef9ed06c72fd3357ae320b37b673039d2d236073705ae04be38164991f7accf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139bb9a70e41f78eb96a05672f4d335d223e7d029d6ba8af630037282102000000720f70c1f5a472c881ea6e69e0bb76d907c400000200361b1257aea8c500002002000000000000aabfba09001d89e001e2ffffffffff7f00ff00"/186, 0xb1, 0x400, 0x0, 0xffffffffffffff3f)
read(0xffffffffffffffff, &(0x7f0000000240)=""/226, 0xe2)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x1, 0x2, 0x0)
r2 = socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0xb, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
getpeername$unix(r1, &(0x7f0000000c40)=@file={0x0, ""/4089}, &(0x7f0000000200)=0xffb)
r3 = socket(0x18, 0x1, 0x0)
dup2(r2, r3)
r4 = syz_open_pts()
r5 = syz_open_pts()
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f00000000c0)={0x0, 0x1ff}, 0x10)
r6 = socket(0x18, 0x2, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
setsockopt(r6, 0x1000000029, 0x3f, &(0x7f0000000040)="674cd6e5", 0x4)
writev(r6, &(0x7f0000000080)=[{0x0}], 0x1)
ioctl$TIOCOUTQ(r5, 0x40047473, &(0x7f0000000180)=0x6)
syz_open_pts()
fcntl$lock(r4, 0x9, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x20002fffffffa})
setsockopt(r3, 0xffff, 0x4, &(0x7f00000008c0)="fde5ec306dd4980c98b9789dd458a5a71e08d80473d8ca5533d6dce7a50e32a597f963b83dfb4e312f841b2e40b65cda6d8cbb9509e6d7bd24e1e293830eeb6fbf7accab8d85000000c029740496824a737c5e718e7e50d6bc1e3eb1ced929e4108ad2049cd200e5d0fdd7c39e72c369e43c69004c5d7e35f08c0d6258f0391d68739257d6dca392c9fe0422ace96abadf03f2bdd0fdff097da5ad16a84b7ec194b9d3377d2f74de9d312a58559fc7ac84446c34ab88680beb4340b949cc9b127ca5ea9cc73c431fcc1dea7352f7f8d50ac74f7275ce92e62585190ab88c63d807f16900d1f59e48456eca6450ef709168e39bffae6bd6add589330db5ea0d02fb2142f453177b8fd31204fa04ac0c6d2b9e311d1aa126c819ca648bd2ab17b4496ed65cf367b3fcbc54984c05b72044dba2c79e29d15725585845005d1fffadd1d826fa25addcd47615707988ba4fe4698d35d6a1386542e19f630fd8697cf70c56838c9094165cd0c04758be94ff045bcc6094fea750d2c54017c513b81c51032a3de594576465667fb453cb7718d80010da864c970df98b2834f4ad05ae507f0ad918e46e8a6d655285391130d7e80941cb79ff87cb1e7a592c46cda8301d51f873fbccc2501cb7347aebe991ba1e82a54c38c7fc17839cb516e58a114c6840283c6a6bc259e32d1481c8a2d0d5d245275f7e16fc92bd08930cc03c2d395431591f03cdb31dc58ea5cef9b7b83eee88b22bdfbbe767a7e6e09b7635450b5a32cdb278928f7e6dde2374b05c9527381659ef190b5f1fcbd5b56b8a77e2f8324fb98676b0b5c510e6333354868645708687f1fdb8637418e6688a8d60d61197d65de3b11658b014881a2a7c9aae229d9da66ea249634c3ed140b407c8ae9264706172942d6e45d5cb55c4d21bf01649f6cd3f285a0c34a98947b1fe71c7b6dae00e41a8e9d0c783e10a7c4400379906f8bb55afdc9cf7b9183bd6b3727be206e43f97989e561ac8f36d2068cde3601ef5ceab9d3ea53ccbd471e6911a2afacdf5a67614ff3c5c742141beaf5c32407c36cd4fac53c800000000b6c361af044573f24a46e71a3671caf41ed03181cc1e758a495bf48892caa340cd0ce005f8949d4b5928a3d8f427f54909704acef10c1529dc0eef35e3c1f1defdab96e44ade2100e1ed9cfdea4d1c3898bbf7a5cea2cfa24cf7edad227b", 0xffffffffffffffde)
r7 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r7, 0x80105727, &(0x7f00000000c0)={&(0x7f0000000000)=[{0x101}], 0x1})
r8 = socket(0x11, 0x3, 0x0)
sendto$unix(r8, &(0x7f0000000000)="b10005016000009f05000000070000007d9113fecea10500fef96ecfc72fd3357a068da3a5673039d2d236acf20b7804be38164991f7cccf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f45335c223e7d026ba8af630037282118000000720fd38bfbb770c1f5a872c881e2772ec5a10400000000000000361b1257aea8c5d0002012fbff0c230000880d6633c556ae9be371a3f8343712051eeab71d89000407000000800420000000", 0xb1, 0x0, 0x0, 0x0)


mknod(0x0, 0x0, 0x0)
r0 = syz_open_pts()
readv(r0, &(0x7f00000012c0)=[{&(0x7f0000001200)=""/1, 0x1}], 0x1)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0xffffff9a, 0x0, "b07b1f660000000000002000"})
syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000040)={0x0, 0x0, 0xfffffffc, 0x0, "0fdbff0100000000000000000000ffbfffff00"})


r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0x1b, 0x0, 0x0)


syz_emit_ethernet(0x36, &(0x7f0000000240)={@broadcast, @remote, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @empty, @multicast2=0xe000ffff}, @tcp={{0x0, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})
ktrace(0x0, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x1)
ioctl$FIONREAD(0xffffffffffffffff, 0x4004667f, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
setsockopt$sock_int(r0, 0xffff, 0x2000, &(0x7f0000000080)=0x4, 0x4)
writev(r0, &(0x7f0000002cc0)=[{&(0x7f0000000440)="bdbeba69e195e2e41f7e98", 0xb}, {&(0x7f0000000480)="e0961267527edfec3cd84bfdbf5a8f0de6a7dbaf6e31f0434d679d0f7d9f4668039209d744fc15753f3eda3b9291a3c1f2c247be62c0e3b00728cd6c34aa09f786d4d37a769b9f5f4eb1ac484a319acfd81da82a6d45acd7a270961970fef5cd35f715cfd2331f0b30a4e1fbf6c8a7e82abf9d2565e11de1fc66f5c95a8931ef04771354103dd288030564b7576ebb549ac7057b1fa9464eda41fde389a328566098e9dbfceec1102442dcee05a7fa1f20c4f373a7b8dccd65", 0xb9}, {&(0x7f0000000200)="7a8d4c47680e2d3e197379a72af0f843728001f1c33e8d0c4c36fdb4e8968b4eca5d8b910f3b7d15ee128b7767d32e17b6ee9ce11e1b2b725c1ea8b7886c3f89ef5a1a8069917c07c272e1866896eb481c31b74f0d978749907450001c955f01ca5e30b2ed698d0bcd13ab2a4343a2608c287494f79a13ad2282a43d303213afd0a0f53e831d2b240d4eab92f9379daac5231f80ab55a0cd4b1715d527bf08ebcf6d8bad750d30e9cbce8fcf01", 0xad}], 0x3)
shutdown(r1, 0x0)


pwritev(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f0000000040)='+KV', 0x3}], 0x1, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x2c}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)


mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x0)
setreuid(0xee00, 0x0)
r0 = getuid()
chown(&(0x7f0000000040)='./file0\x00', r0, 0xffffffffffffffff)
setreuid(0x0, r0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x0, 0x0)


mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
minherit(&(0x7f0000002000/0x4000)=nil, 0x4000, 0x3)


ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105727, &(0x7f0000000000)={&(0x7f00000003c0)=[{}, {}, {}], 0x3})
sysctl$kern(&(0x7f0000000000)={0x1, 0x45}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
sysctl$vm_swapencrypt(&(0x7f0000000000), 0x3, 0x0, 0x0, 0x0, 0x0)


sysctl$net_inet_tcp(0x0, 0x0, &(0x7f0000000540)="9b1809c3eb987ab7feb13ec99e805e6e84d3569607987c0d00000001000036ba1bd87f42e3003eac3846520d050712f838130efce149d4d6d06a3f23616e778c826e0c1f59734a32e0ccebd635450b2eba540af7f290e42d34d900a0dad2b74f50acd76b5c567049ef436dbea0d7612752950fa5ef6eff03000000000000a944d5c2bdbff4f06a852ab475cca25735282896ca5d4d3e670feac9b4e8aa9bef193b90163de8570b2a374f1408341ed45bb703eb63cb9a8bd949ee8fc6dbceb7ed7cca108d739a38d726341f1345daa49507756f49775275ca390bb9400000003a9275d0da3b56186adc3c141f939800000000000018bdbdc9ac0a623855e941dc", &(0x7f0000000000)=0x100, 0x0, 0x0)
getpid()
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x100000000000000})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000000)=[{0x48}, {0x30}, {0x8186}]})
syz_emit_ethernet(0x10a2, &(0x7f0000000080)=ANY=[])


pipe(0x0)
pipe(&(0x7f0000000300)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
faccessat(0xffffffffffffffff, &(0x7f0000000340)='./file0\x00', 0x101, 0x0)
close(r0)
fchmod(r0, 0x0)
getpeername(r0, &(0x7f00000002c0)=@in6, &(0x7f0000000300)=0xc)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
syz_open_pts()
getgid()
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
syz_open_pts()


ioctl$BIOCIMMEDIATE(0xffffffffffffffff, 0x80044270, 0x0)
dup(0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
syz_emit_ethernet(0x138, 0x0)
socket(0x2, 0x3, 0x0)
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x0)
r0 = open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f00000001c0)={0x0, 0x0, 0x0, 0x100000004})
flock(r0, 0x2)
close(r0)
syz_emit_ethernet(0xe, &(0x7f0000000100)={@local, @remote})


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x6381)
r0 = openat(0xffffffffffffff9c, &(0x7f0000000340)='./file0\x00', 0x0, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000100)=[{{r0}, 0xfffffffffffffffe, 0xbf}], 0x0, 0x0, 0x0, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f0000000080), 0xfd, 0x0, 0x8002, 0x0)
kevent(r1, 0x0, 0x0, &(0x7f0000000400), 0x4, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000040)=[{}, {}, {0x3, 0x0, 0x0, 0x3}]})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000007, 0x0, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x1, &(0x7f0000000080)=[{0x1c}]})


pledge(0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
ioctl$TIOCCONS(0xffffffffffffffff, 0x80047462, &(0x7f0000000000))
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x3, 0x3)
bind(r0, &(0x7f0000000000)=@un=@abs={0x0, 0xd}, 0x10)


sysctl$net_inet_tcp(&(0x7f0000000040), 0x4, 0x0, 0x0, 0x0, 0x0)
poll(0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x37}, 0x4000000000000008, 0x0, 0x0, 0x0, 0x0)
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_INFO(r0, 0xc0285602, &(0x7f0000000080)={0x0, 0x0, 0x0})


getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
ioctl$BIOCLOCK(0xffffffffffffffff, 0x20004276)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
setreuid(0x0, 0xee01)
r0 = shmget$private(0x0, 0x2000, 0x0, &(0x7f0000ffc000/0x2000)=nil)
shmctl$IPC_SET(r0, 0x1, &(0x7f0000000000)={{0x0, 0x0, 0x0, 0x0, 0x140}, 0x0, 0x0, 0x0, 0xffffffffffffffff})
shmctl$IPC_STAT(r0, 0x2, &(0x7f00000014c0)=""/144)
pwritev(0xffffffffffffffff, &(0x7f0000001200)=[{0x0}, {&(0x7f00000001c0)="14f16b0bf3ea8ff3de12938731a2dbde6dc95abd35643c3466bf379694ce87d3613b8ead6110c538b0e6b9de46d85d14f5a9c865b9d1d604a7355a67db896b9d1e9b1ba97cec020bf81395878a9b9a5aba6aa80e55e071b36b0b4efb02f9cdad5738c0a4be6f34c308f82230a430d14487c3654ac49b7cdbf4a6f1c39e667d6e343ecf91a81d7b467ba5ea061a836a86ab88894912f8658f79da79fade5482a2af6a868d2e7f57a7155b760af1936d7d36a7e119f9f7c295443d48dbad8be7684be0f553ab455339cc01cc76b9f12789fcda04026cdce4efeae37138a28bac99a73905ce470f66990ca59e0bfba957a509b5df36e719de398f10a7ec4eae3fc0ebcf10b7eeef5a17308e551583aaa24bc857559a9ca7281feb937c4ee7a56ea27dbfc9fc0c7ce2d1edcae17f10b6adfeecad923af50adba8388538fa360721f3631b18966940adcb49c45d972447cd3fd7d74ed0d48e7d8bd30c35ba4e515054ba4988383f8c523a4ba2125a80cfb4ad633eae51262f30bcdcc8fae62f9b1d4bf6d66331b453a5a61b0c79c47af76b151182ea83dbe9c5f27875e7e1e46bd89f09fced9c39d192c6bdbae26a6a633d4ac5de8e5af71e944c7d823c63bcc7b0de2651ba6df42e554ff8866dfba7006e4470e4dca84548003ddbf596602920f954231d02355ac6bd98da4441352069616be940013e696f3e8eca8b77cfba561169c69b639657cb0414162d01eecaa0c1441ab9fb5e62e4e792f59647f0a699e5cca12ee2eac8abd5f751d6559c0ce5db61cf7db5c2ff7c4ce81168807b1f17f6070b5148d77f0c37d25324e3c45356973a89d34bb5fe8922a41c5b78b39586b5e13043e341ba64825c9d6793665c2a30be1e1507be9c7cc1b8fa8239a72808a216e9f1eb0f62eb67e0a396a640bf8caf13f5be3b1c038b584ddb7674544de5958ab02d2b6670def5bd060dfd717c7ec5930ab10a437daa84fed10cb5e4643811958286824dc92ce29c44a0b3e0948d0b37a28c9c7e09710a49f6ea4a0b62256ea3833f7584c6c08f7be2c5fcb1e394a7a4ddad67152dc0553673533e208aa30c11d570cd2fbec01753ea4195696227d34711a8b45d8d196148515e08af79b1080c250f0da7a4b61eb393c10c01e1cd23e2a6a5304fc6ad9abfdbc20ff727b87e829bd54cfcd26615588eb0747c2477bdffbdea8730f05e46c7e3fa1032739216830a9a8b3aa558a052327271fc5e37d17e3885dd7fe8e3836df01ab57b0ccaccad7de812133b7f4dae83dc02495dd6068fc37c2ce11a3e949f65dc91dd48e180132f0e54a55db057a211390d989c1a246d61fefd00f5ee69c8c93bc74bc3cdd380dc93ea4acfcfe5cfa0e46635b318e674d430d8a97cfae9be653e86e37bb1d9010d05be51d2af1726566faec403ce3a7f256ec3516e8bb207f1c9a7e11cbc34b0a1ca49a0e6c08613f155bea984c8edd2ef64cac54e520c95d626a552301206fa99cc16a98ce2695acfbf5ab0afe8f679f101b752f0a4f3f9a929213621db2247ffa9da8b15834674031df83061892368c29c13b56c10f4e0e4067f2ed236e1849b2180dffcf5725cf4e4e9dbd334d6303d05f9ed1e8cea96e97a631796440473ac1b6fa52bbddad54445b6c160e72c9b2b33ab128f87685e160357216153de12e00c53abee5210e8c449a0e433e01b09e67bc4522e7f5574fd8aeda21f51fb55b0443fb764774a072f5da22475f38bf195e35286c69187e052da8b8f3e562ecf66bf3f3a95e3da8c540c7f466f2bc5cfc04922c2dc2afcf39ccac4fcaa9958ebad51d5332f6349b915ef3b235fe24f3e61ab0dc64b6abe581fa63a23e2955e6f5872b194f130ee51358a0739e03c4aa886364b1f1b962c604519cabdd51e8b79b866867e127f20d5bea6db05cbc880fff467be084c6bbabac8423e83d36d9af9d890ccd1768364de217a6fe256a67ef32c507f0ef95e3dc4bbfd94628cdc41fb3f4aac9da33c407e57f57b45e5b927ab18dd6a3653c57cb697533dde7adf69c871772f7d78a5e0f60f8a7f7c991f539bfc673c44093419f4e2d57c14764a6325a471b56aabcfd188e66f874cdaf1cf34da8dc4289ae8e43a22e5d9aeef41a009daa8f78d06143f0bbc5423e96644e5f24b93a15a7829834068e5e9c827f03ef4de15ee807333cc0e2ca9636017cf06bae9aa52ca21992b12f4dd3afff133622cd14bf6dd96313a5f3c85dced3bc80a32a0311b2e8edaef5490bc6d82eaba3d58ae44871ece32bc82cff3dece8b109db0e77cb7f509c587129f6587f7c1ff7821ca3d08a5c8d37eab1087ebc24bc140895da3551b2382193b05c6cda0f55ca117c043f90bf062b80d8316ad444b835632fdf79d9c429736eaa8792c9d2007002654f26880b9993a7fd390849e679d472c65842d9b8d6d85c5fd8fb952b27ba3efbc7d4638397c900ed9ccb04f484c7aa12b9d5fd3f69665ba0349861d90de647c4f4a33efe675bd2980d8a63a961cddcc3c85ba87156e73560e1376853d4456c5fe9e3f8fac8911488a09ca1da843f9256fa2681dffc8a7ca981a4c82b21224b6fe2961b7416ca15b709702b0f27d25f81024d2bc6f1d118c39c8151a446a9771f2e06bb011696743601002ddaeb08afea1d1076448cb25584c94f08868e4fc4b02bcafe758527e9d01db89e7d9103edacdd8045410872b9d524aaacd58aa3099fb0f37464b12d44ec50cffaddc4005284e0c6214a21cc2fd264ed38262d6fc0e998476af1c626df590837ef865a107f48e13fab5eb745303c11213570c029620bc3156a31ff14ca73f6c7110f9316fd03f3b8c3f9677404c0b6d2f3d2c8a48baebd83b03103714bdb07e8e6cd7b7897c59b98086b5622b557cbdb7211900e54e446c02322cf66582e18e9010a490df532d3ae348c3c57ef41e061d40670c699d96250c13edd1518e39206626738247ff43c352fc9f26a7c3404a46f2f29387ffa007b2d9d1ae28cee15db17b5f295ce204933ae4da95a9cf2949d829cdeda4681390517a9815d95202aff507576e9ee5f55487d1818465737b3bda7b1a3c3d0f26c4b69b854ae768232f37e69663dcd1ca173dc6213a66640b338fea681a98b36dd52a31475e9f92f1051d5e930087e48b51797f75a3740d5b177b3ff7dec2d13296b9c3886a20638aadd45f184d8cf4c3124c7a26382c516e0c0c676c9a49301439477ca24f84c362b8b17ac082bd46b288757d9a4721bd36dd1baf73d8dede6ec1393a1fefe2ffe5005c1fbe602c4ad3710790a0b2bb62119be1438c48809bd174731cc454d357c0ce56668de2ad943bf6f903a9538c54d8c03ef705d8fe964977b238715d4f279ce784dc0fcf5fc3845a8ec747440537e257e3eebfb6ef5b814323e66eebdd33d9f367816dc713140b7bad51423fe0726c4e32a8197c249d0f570bc83e22e0d60b7deccdf93f344d34f98125b897d72131384a7b512dd4ceb136c74f2f887ec6750e103e9af2183984743a73fd6db7ec27e18d85428f4b89a13b38d2d2f44175e8e4fe545035b990a937eac94bb40873ad357b2d0949e68803fa59988cfa87f25e6dbae9a771c2973c764ee999654dab12353b1350bd9156ca283891df073cb140b4d581507acd6df2697725ae73f2a411f85869215580e97b29152781ec5afacf83abda74fb19bfd75eb4099405a0dfc4ef0c82f0d69d986c76f90a3abe103dd2662c15af8f545850c9fd679b9db2cce553089ddcf51ea32f878dbbbdadc7e7c67267877f9e0a1d96658ce7abece0fc3af634cf8dd665a939178e9a2294ce1a92d275a62b607b68606153abefe5e521205170de60803ed455e6d252d4e165b87fe2b4a9a5ae10d962eb1ba1e4d958a8104d37de2c3f5b2bc9d5eed288d6bfba9c1de8e5f3e17540de280db9573868bcb1c36019908d45df545fd27014321d2ca2e51c1190e61ab09f40c07ad3f35f9325ed58220340252f6d66a8964839f83eb02f94cf13d8a11da744a8ae35541597c9bcf4cd60134c0004ab2cff90cfd77d52e65871b6ad4943fcc8a33c60ae3ec807dceb1875bd2b2df91edb565918c903977669cc05ae1c4f21e2f393515c7b461aee16a0ee8e6dc31a8a041d577d9c98cd4272c7fd093ff21537172e6e7910d982a7b5f3d0ff3adc910981513b7f43a1cb905dc1b23a6aa09f321b38edaee8a6dbd0ca7b7e2af7c5df1399c4083e0d8208a42d80aec043c32fe4ad1a97d919471062d073609509921d85d1898dc20c319c78cea5a53f5366a67726311269492c09cec60261187e8597eaf14bdb370e733a9e905958c5db79d8d5848b07eb544e64ec616d3f65b5cce66790f00252bad4a1352cf2151b7aa9a3a7d9a503ff2520203eb4d75f5f624358e0167ba276cafd7cc811440219a4f538ee7477b4984284b3cd1361ba9c354d3e55603037e8a19c36c1c5938a375567a4480774bca6c4db39d28aba899704e7785973d39b8d0ebcfbf070671abbfb5f2c91afb2904a22ad9125ab941d7ef3bb1b2b5f991ac874e05c2d8229efeabf123a45131556dc5e0890d7134e974fd3d7", 0xca0}, {&(0x7f00000011c0)="be726452419a0504d0dfe96076cb4f8aa3", 0x11}], 0x3, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000640), 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x0, 0x10, 0xffffffffffffffff, 0x0)


openat$diskmap(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)={0x3, 0x7fffffff})
r0 = kqueue()
kevent(r0, &(0x7f00000000c0), 0x30, 0x0, 0x57d, 0x0)
kevent(r0, 0x0, 0x0, &(0x7f0000000600), 0x2, 0x0)


mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
syz_open_pts()
dup2(0xffffffffffffffff, 0xffffffffffffffff)
r0 = open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSCTTY(r0, 0x20007461)


syz_emit_ethernet(0x4a, &(0x7f0000000100)={@broadcast, @broadcast, [], {@ipv6={0x86dd, {0x0, 0x6, "a12011", 0x14, 0x0, 0x0, @loopback, @loopback, {[], @tcp={{0x3, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}}})


r0 = syz_open_pts()
writev(r0, &(0x7f0000000100)=[{&(0x7f0000001480)="8740916af0ae10f928a6139c7cc5e05aec968a659b4ac2da09114ba110e6f3a470ee8bd5eddc517d0559237b3ebe6feb49c9db3d0556322ec6259d6c48c9c50be6541fb25d2e23b434883a33849fa11f396988fe1ee7ec75785bf3f98e6cb36c103e1d4bee9b9625bc104e8ab06f57643993e9745070ebfc281ba1a7ecf9c923a2b2492dd57c73dc7c6595ad9b0dccad9c93d08382d00501e9702929efdd4ec2553e4ade6fd8a59c4dd5aa1fd3a5653ff0dff647c586971ae3f444a7625c199adcf89d60feefa4849c094356f4be262bc0", 0xd1}, {&(0x7f0000000080)="c1d94d6d515617f03ceb719f031004cde2369cb5763f22f99287b02b1dc79630ad590c7a60fc014bca48ce5926b1993e160724c5a54abcf922174b80aba37fc834645fc2b6baba3876ee4cc35d80db6a86fe758f396febacf0e0d3f17872168200000000000000", 0x67}, {&(0x7f00000074c0)="fc64176c0b802e25950411939bfd2ae5b14c3875cb1f5bf9899b9bf4b63fd13755bd230decbb3ec46764a6bc3ef546641ae18f8622b2366396ef39d509bea3781ccafba6b8483891e839c46429643c9d0ba602515016951cac4a8717fbd74ba940cf2f41e4cf08b5bc118e3bd55586e610e9f82366c2f58326ccdeedf0115cc10900da8616f0cd6668874cba26a5a2715e61ca7100f01ef655205f741ef8f9717fd94f30668f9b1553cd4d83689cf8e71a87d7eaa64ecb429fb6802016d8ceb1bae978d5621e789d506bc16f295aba7bf78c81831e834a99411ee00b8d96d3148b39adc3af01138e405f585b78d4519bc207706cf0fe59e619bac71df86b8b4f71d665d5a4231b911e47e7e8d8e9abcb5fc22c3725940d9b06420deb62e6307e45e8d9139bae4506ca10dc2c5ea7eee2317d6436aa69801e1f53fb3121da40093f24f3db2733982a0806dec4abf79af5f621231f22f706a77d32029fa22fba6eccd2cba0bd98e05b27929ea7ca59066e5d75576975686ea9d5f57b1739f33d735b8945ec1cf42fa9f0360bfb39dfadf3e7c6102910c65f25cba11a362f77158e6e867c6b19edeae719f7d2a9a2f4746c4dfc3ee4dd029c67c3f0611e06eb6dfee903f70114962b1905f5f5cafe86b1734d08be22f436c3dddc414ab8b6eee05196da81c62b81e063331d177d6c8b8678992842f01aa4bf39ba016635bb3aad9e09145e875d2ceacb851dcacceadba12705e71687cf37abcbbdf1f441f45349a7cdef9e74067fbabf354458140f278b7b3b3f0af05f1c59e9869244408c215da99c69f352835768437ca02f65b72050d043ae0f9fcb070789a37a1d609d401c96590d8e2f9f501d9bac8ec59e9dcc156cba044797bf199269f6c28755e79c915b2c81824424b32dd50e7cb1b90c80585755eb0f679e5358c598290b15b9dc58cabde26cc9714958485e8f05449a6b15203470d8cd82af0a9731a00fce80ed9db53b7d3d23b3e6b75978522b36738dd17de8e1275dc40a1a51e6e3e2e6dc5b47bb74288ed412c19c2c6428fb715d59603fb3614c82b7497735849392357565fd0552e858a980b5b913060884cfd2b422c826e1ff05d6286f8a82063de1a5b98c5c117dbd79a647d4fb377f601d9cafce41344f72bcf75118fbde1550e5abe33c17b4e902baf172ab9a48dfeebd14ddbd20b00dd5e450dc3d81fe44bd28d14370c1a7a883b4c2e69926d18a62f54a490c7c598545b3c4adec23ddb97a2785ce4b5b549418e345051f5c7ad2efe6fcd57ec2d990b72caea5d24c2909add3944d8a977b48c6379b367e60cc77edb60c53d14eece1018fc178f0d57a612fa87354dae1f300119565630a3129d048da27875cfa2a93e7b28b228f05000000000000002c072dcd4452f3b30a88f1df1cc58a4e2f8185519f9b72e768cd7f5e2be972e8cec62fcd656fa130902d563d3429ead24a0191cd36ab1d1d7d0368268aba3fb20bcb1de2139b0142757f77d13c67562dda64d0a0b1af6a25b03c8237170c7c01651cb5159e3dd8b44c19f692bc71315bd53ff7d91d5eb1ab659caf15a9f7c17cc6350e9532113ba8c39fc910a803736b75a9bd2f53ec6eb25717c5cc574894f0d96bf8fa4c337e6d216736ce894f1049879a5e8477ff9fefa6efbe137c075a7e1b2bcde33b8316e94eec586f65f4e41dcd468be7923fa3c021dbe9d78bf729ea2b5c7a11a1e0de149c6440ffcc7588c094e63a97d0aff7cc00f4b1262f76b8e3897cadd70c66b8f89e0900ad76e68308551817956b98aab94c33930698f81d540c12ed4fc3e8f3ba45f8d3c3f997ff931d3f9efc4f14793862313d24be22c7a00dc73fb4801d637695cf2f9f9a188bbd9aedf37ba71db5532859625dad97af11a103f2a5b2734c9689d938f394716cbcb4c66837cce7b50d39e0ab2c08216e36adbe97a05ad218c4b26e207fe75e198aa2a734146b5a81c52ac9dcaab66190cf7cf26636d69ac069e9d678e3680617d62528deb4f29d4c7a4c37b71b796d8c27fe709d1876e9aa393885de7c2859c47a2e2800b23418c198e792aa8040a864a6c476c940aa79d8c991ac3edf22d403a543b0a12ed54fcd01f256de68859bc0e31428fe1dddd6ce5446d3e4972304f47abc1a33da86b1390521a7b7d442c3711b849ddf4e30a2160b85c3214a13ecc96b40ee147d103bd9c934a6277b374d71e0861d503462b31fab623279174c457ec1cba1aef23fa3acf0c5893895c94b18b8c4c7ba37ce9ad1c0db1a387e2238e6de9226559240255ab463083763dd07593b82e393cea76e18463b8f1ddf56f3f3b9383e8bce4c77ef95c81a94ab3926102555c08a47af6c9cf745a29a19110d8e6a334c9318e540bf70a66b0d90f0e5077df2da3e7cf2ca52999442c9738dabc86266f54aba77289410d5e79b8873ead68baf3dbd32c36fc08437b0a35283b313da5082a61c2c182c30e057789528b7c5dd103babee6154bdee69282468b795e5487e73ad751d7cc6754405e6609e7d820fa58afd6e5e9c9a88f279161cc827e03e610f84718dd36238e66f9bad413cd6f4c7baffb65dee50762d74a6f4f0c00e05c7c0b521e35a7f1f9f1358a88d0428073e7979bb59f89b4afac637ae7b4d546ed1db5d26d078541df36f21d077408cf3f18076197a34df9fac37cc31fbdc9a767a20e0e3e321a67a7778b3db011d94018178f20cebb0ee8564f7b92fc3c5e4aa12493c316565c0c550a80048b0c11f306e26f1468c31d6494ade5fa2015da1bc435b120a63a8d88b793f6fd295fce27620fe96a48c8fed467ef66782e68d747933e451288d4535eb4d135b5ab4138390cdb6b87cb7ec811506593ae19c3f8dea05eff09d8cadcf092520449ed644bde3b91b8c245fc8b6fefb22810eba63f7b138a63c31861f34811b9cf957c52dcda4b42b502feb669df4e4254ebe8145e11aa569e9d5052af042cc0cdd2b8fb1a4232ec5de92f8b2afc6f383aa7bad827fe5227153ff6c92fdbcf2b29a7971ec68d80bb02a8dc9e684dae115b934bd40abcce105fe865554fd1346d3b2037e6cbd2093cb55439602cd08adf190002180df60a3306a32af98a1b30f9d8c837bdc7ea872cd810acc36259bdf89262280979fb256c3b8326be6e63a5282423ca95a9823a0d72aba787cee131b971fc5c688b51ab5accde21b7c24b56113a2a0a9f6b3c93abd2b01952a3c7a8de82c6d67427eb6dc60cf9ebc775d288114e92bc6a4bc7fc5436be367de46634cef94d1499ea624d903d5034cf3d98ce696aaf5f890eea7eef5d800a147a46b32bfef7d0ad9071d275b487c4717967d4b5cba76754722f25651574a29c219596af17595c175f92296dc3bfc0ebe27f3ccdae448f92f92256f1fe0b19b061bf03609cf63a0522bc9e89022b7612b1f6b497cc2fb7194357287e1bb5c75a5ca2a88ecc8a2c38d7284e148ec389d16226d1c069a1d044a881dd91cebc32b4be39b7a474c08d0cf4a4f84d0f451822053190a00599e620c8a9133cddd33664a8692711eb33d1944d0134480ba0ddc1ff6658ccf7321e25a8a3692a8b9b8930a0289ad1b4266668da1c51376ee906655ef8d228e30dd2e8672edddcea65bd093c0a807e0b6ea88686000dbd84ecf8b406ac0a2bbc229cd2b15c7236fa862923a3a57824d1891836c0a228b401e6646d632f17f8e19a3918e69d4d4dfd7ff69c82d9dd6863e57b6023127e147eee3f8f9cc3f7aaf904bd97f58b23d2300fed7c4bc22154ee89eacf1e1cacbab5167d1d088368d2f6094916ef7e0f438bf0d1efe1f0390983b444052aedbdb70b7c18766e797376518585368b1a04ac0dbe4eb4cdd15f0c68147a0842faa08d54d14c0bef538a856ffae5dbd3807fb352ec43417de0ed96c9731533287635dcc66232231aad66564de99c35110a928a3571ccf94a1c2ba2d66fdda695134be1226399ebe42e43514939480bbc68bf1ce1649b0b075ce38c9b096001142b6ce122a491d6044208c01d70592c74b7a548558c18189b28246ca74f052c4dfb7ef9c6b25eec187363644dfb742b4908350c0d9acfb80e60f454635a37e9477c7f1aeb1c0b105fc7282f66b4d2b56c23f5c192f0f80d9ea7fa431b613264d8e9d51a3b9c044e12f9b98d0c0a4acf2ae753cbbf57cad6b6e988b1e3b3cb50725b47c6b604b0eb08b6345052c33bbe084a1c05288acfad9cd4d8a477c86bce9a2133fa9f0d50f7b7732a99fca6fdeb75e71183ede1c786110200290e72265bfe9577244b2f1c0a5ab1480614d528dc9d7518ee6b92ec6e6bf1c5b47adcad26167331644a9f13ad4de2adf944a51c005b434cf385973426f8d8d34bae487e603db1aa4fcce70e713bdff5f6b968dc9665bc8493f31dd8736a51533d08192136fe641dfe054cbe364e33db9d9722da9e5cee1409db7ae8b544f29fc4abace47a8097f10734e0a8a290659fc2214aeddd14b376ff88e68aa396d5d735dceba1cb7962cfffed4f2394e05ff47c7a15e76b987c9f5d4f0d151c74e39bd2410de0af2c8e066bb490e203ef9d86d60fe133c1fd0525253f19ea2c4b3bc8b274c1b16b4d950e03a0218f8d4592600c86b7d2181ae5f3655f7d973bb6c58fe754b1cd6af87e6a8a66e3fb109cf0701f6c9a72f84be095a02dced3501f859f05cd10514152fbfe9c54cd1871a4e70bca60788afbdad4549070a2b39da580ed56ec065a9172ebc0a1d4d1a3137a835e3346842451e0ad650d3c00387c622966cf69deac051cab995af63540f310d0b7a116a45e324190ee537fd236085269e6b1fd64d96fa198cf367d6566cce38853d90de3b890e34fb4e27bcffbafff73f22adb815ec4105f64a9a41acc9ef5af95e4a6361816831eab257c0567bebd04cc9bbb8f3225570776560f9de93d9fe857e9ddb52929a7519a14068448f074e3e1ea2047ca8b3e7c1000313a2a39f3735b3f6747771d9f3366a104a82f2e253fd57b6db91cab01eff02ef163bbaa3570428bc19f70e8424c3a19d221baa1fa25b253d327fae55383b74bb4deb9dc0643e5f1d8f8de598b6ef12727246ab5468d8b8392cc47252d1edee39dd1aa6b00d02ad9fdd9e1c078947fbe939c57b4258abc6cb56ce022e767d1b02c481a933dba3f7ba492bb397a358a04ede2a3ace4d685227dc3ca64b5730528e2837f73eaf0532b57197534b2ee8c44ddb19c6f95b6c3f2218c43e6529d8f71c97a31378ff56aab93b827c47094e367c77c9e36e048dcadfdc76d167aa11cb0623a4ba5f298a253ce861d8f037b1141d0e8532e202fbcf386b23fb9c1a868cef4bf36d95604b60337d03cbd0ea57b98f6bbedc11fcaa9382b1902f0805f2343e0283d0f8e19ac5f915524b517a14d3f3c0670309dd1529399b24e9d7658a7febac4359a3f810bb23506e9f7ea78b8e6559f0b0517cef65ab38a641bfe9962a148b6a1a047a68a123b64e4520b10742e61251d612090a77f8bbb44da4ed31ed6928ebcf4b4959a190728552c038d17ff8eff982a18dcbffc9bf5d40e2578c1dec206544883f0a0e5ab08cfa5390a0385dba6112504c8474f31a1aaf8108390611670c506f2f3fa0a8645de3493c79abb8201f6a350f6c4d48a3fbd346019efe9ad086fbf0797f9f3425c09bea768f48c82a8329e0fe94aafb897f5cf17c2b19eb737b536b68408bae73f5322f9768ad48ef06f265d583f819496a45d1c735f1fb3b35ad360b5af5f7e432f960f2b84af5957d6fa144ab557dec38a7bcc9e075cdd15441028f5bb2048ca514aad53881fde631d7cd45d0adf6918f92f8cf9328dce59ee764ecf66ddb8273df21bd1658285b5ff9b0d9123eacf17766e1b90fb559a9b73ccecbd065ef380c3642f643149176000000000000", 0x1048}, {&(0x7f0000000300)="f506cb648246bf1278dd08f28fe78630e6d923a98034f653a774977d4c6e02d21f94b580fe6420b4f6580fcdfe2d178fcf1084d20b72a76f97d41021da8bfcace48db9e6c506e88f57a5f60000aebdd672d1b9503cf062806bcd51b6005b4bc8347977dbd4f38ebb282ed77836c2e15762cc25b5a52fb533578916a382b4e66597944971642105008f19042fd56714e22fa142f505bdd43668d03c6a9754d5a70ec79a76a7ffa88246ca9231f51833295ceea6c0be4ba6c40100010000000000285176ab796c68a64447149722a07bfe3025048ec64f68f5f829c9082ea855f64ece2dc9c53d447f1f4d1444c1b50f729db09918ed059834507c8cc20cce0e2a7660d7e191788685d632768e152c8611301ff86388d650d7889021847b6fe4ebe04ef81f8bebe2fe5c037de50941ee97ef0ce52d1057fd44356fb47af146b1ee170b16c9fc866e25b81d2c49679c4436f65cc79559d08563a53458d7f9cb9a4603baecafac1b03d3688072690ceaea00c3cc6fa2f858e67058cb22cfd541878604037c1b48057d1ba505de81b34c026e5b9ca67ff5c5848b12a71f825909d3b20370f8064474e6e2ad64d366f432835d9a3f8017173d3a3fea03655342c30302c45d14a4", 0x1c4}, {&(0x7f0000002400)="fe9033ccbaad61f7433b1e22decb417ed9157861122052fa245292372238c903223fd7e34fa91af60af776668c59c6587b7039c95245d8072697735793769ea1edddc40b554959cba67c71cb0bf21ac81e710022c1d8e630491b93dccb8bda4178f4043a74aed8a762a373b25a5b088f8544ec027ef2bc803d349cc5b24e20fdb169c41ea3b2c4d53ad16eb59aa371bebe6d994fdc982c69e73edfc428de6dddfd8452043743fd5f931e2787cad9e57cf616da9dd1abf3434a31c36bc90cdff936fa60e40f8b921ab2976a52b186272a92a9f768752e09c7cb35cf00d27878f3a7b7c025d6d142406a62b5d9a19efce77a7b54de7603826293e743b0a082168b12e6be94de36d5459820369965df8dfc7e89fa4ed03415021bfa89634290d38365eb664e731b2ac9f2e006dfdb1069b76c4a2ba72f9803bb877d7cc927c42a46506b69bb6bdf10d8d1e5f4b33aeb03bc8d0e4209939453682656096c1f9c925226d8d213720e5d5b246436425ed3c4e053e00155a9a4ee794fc70157fb96d5b447a56456388d5e09c8e130700bb3ed1e9882f0c00e1d31640a5f92099f1032b987e8f0c22fda2cd66571be3cb6a50a87c971ffa56f9f84880e071359b7624292c5e51ccd02a72feb5c949b083d9042d1f4722f0d1b1ae6871196c963b3a43e72202727660ab9d95f45b86d76bc9b58edc0790b0127662cf545f790743992a4c8ceaab79f86581a352234e06538e029a52d1ae44d7b6566bb1ebbcab6ce5b323471160747bcd2073580d07a88c76345c9dc86b85a7c8b4df15ae2ab3f51439f38c8f11c3619d6089a90989f57552471b71335f922a14bcbf968288aeaa90c55014cc0dafdb6f58c97a34479e738601b6c679e39e533c40982adb69b587a28d7e6202bc350fec39bf970c62e8db0c2ef5024816fb69c119484a03b38c4e7aa55dbfc5d8d450968e9d7e07b2b9dfbb9d9502a870bb29b160b75f2f84d8ac790e7827bcdab74544847e62c81b96eb5c0f1c7d7b2e89bc0be276c20f9594d575d8ef43ab890d3c0dff020597f4b63062463fce0b97604ff3623c09e257c95552a795671137d434525c5c0136d7f5b4d1e0e9bdfa947894b799b6467e5a0aa7217d9609f8efff3d90e801952880e7c3cf686c5dd697e7d75c69ad36a4fd14d004056ec819cac8f2cbfccb8540fbc4cdd4e2a1ab41ccf93399c389c82d3483fda6baf839dd1c9d859769064199ec2efca3609d48b470faa32ccf8a7912da8bb780be48057ceedad015e8efc63b4957768e4e043304bd2f2e9027e2277ed905552db083fbc8e3cda96ace9666a95ee73afea66e2e93f6721da5dd00f2ee9e84b3a8e0cff29fd9b7dc1f97130d9283aac5d8b713a627d23541842c197ad2dd9b5058a75396d3c0920291ec8f04e51696501457b26762b799ff0f143fa80eb88eb7339deeae5d17ca6de2b0c88315c61333b5fb142c770b8ede2c9add3c826c736be90b1d481fc774a307a65f8f802eddd3ab4e9cdd2cf9c1a0ebf9692b01cecc1207a68a6ec04d088374e25df8bd7c68ee9592e17668c9ed4f559b411afe583f6de8216f9c56cbc55eb53d15bd06339801f0311dd9d811f453ec032ae1fe455904bfd6a7aea928ecc7d390178780cb5701fbdd5c107102869394e4fe9de0ef3e7ba081da8344d82ebc8f19d0fba1645e579c3931b74b5b0de2662a5528ef480987f04ecb3a3c33c1d1766f47353a7d120ac55fa749e62e3cf42ca7b1fe67581b5d53472916526cd2217b33b325ddcbb8977f4db9abadcf2a532bda3682b8715500f5620788403708207d9c82476ab8984a54d890972f08318bdeaa1fe817fe628c422e22d1072e40c362aafda5582957cf7af5789876997370858e785f25250453ac9a8248663a25cf9fee0ef11fc7ff2e6847748606308cfbf5a0fc404086d1cb962af9f2be3d0e3f9bb19c77f2e40d115ed1df5a20cf507cf87b83840700dab98f864b16c9c75f853bed984372e609186d1c248e4690f0392180c6bc84a5ab6b075aa565db3a054280506a4f99b5bd135e523d2c404e1bb87018e1fe203561f51294630ec3e8e0a55b6c6bff050e44acf88d977fbb36e6eea0f0e86a0fb634a2c91d552428b10e42dd1c6dfd37cecea99b578a2dd3819b62496d6b220ee310d657f349728f7b789521c230dfe1afac43a763909b7eb254adfd8e8f70e5ff7c312b14cb3070d6e45112e1a7b27bc2c44b4355d45aa33c7fd4ff8c15d072e379a066ce9c5c5908ac056d04835d65bb7528ab6f01f4fff03924d3df961db9ae7f32cc56e5c19dd09e7facbe34021653ba87c6aa47710e3d1b3aca78fe1ee4665fe62c6c29ef21a5726823480b13b2e4d486081c5378008b683b8e9508aa124f0810cef77af4db4f14652b8f798438ed8430fde8d10e3fc8895addc17b5897c9139534bdee83e8059cd0f595c5e821c8375236306e4b20b83ccca8765e6a445e12f473903c309897feca7eb888793566b82070152dd636af449327dbaa5edc663a7f2b75dadf05f23e1a8c1a590c965d4abd1f89ba84dd9d5ddebf76eb2027eb379c9262addcdf3093cb1d44b3c9fe080a3190d25eb16eadcb0108d4d01f0a971017926c7c36b7755dfb18b2a1f39c3b8af8ee206a3a1b835bc7ef93973bdecabc7a9aa2e7422bf810b6b1662700d641f8d40b5cee04d9df5c7d29cca64c0088effcb5e98b4eaf5f007dd5c81e46383c25caeb950490889515f7e69ba72038c74881109a54b9b2365b08299d962862016d7058337d8125683b1a0617cfca0b0aa91a5bf7eb8f4b3df8150c7a497e3ca4ea727704181f534882954c7929dcf90c81c6e881472802704d78aa40c9d1404d767000a82e72c198d1104b45750d1ed0c1cf8b258b09003bf1c4f3921b3414897998c158922b1d11babe336e188931f8526d5182988e7dbe32a94b1b75e03e6c98202a29e25903b61f34cc05bec37022aac34ee5f677626cf0982d76c207ddc930bb7f1c9a5fb842e7a75873e4a0d6bd11e2fc2792f9a584187d8a207388eb7b1e63de3b4e55f480a61e3540e70cf0428323e8d69d6eebbe306f5ed17f220ed4c423529a442e8b1f340ff9eba89139b1ec9c9977e15da924aa730c69f91cebbdefe3e0128f44b9eb5b3ee7bfab4fd6e14439c73df51b51c3d7e7c84a19d62dc5927fc4a378f9cc5678b29dfa993dd49c9b06ee90f339b4c5a0a5dd579cecc1cd8289d34bf947b37aabdc0db2eadc10585e35678b9cf9c1e5fdfcafc4c9bdfaa301cfa86c33bac19986df967eeab30d382eae56afec7a30b9e2a05409563a41795a889dbfcdb946aa7adb1fa975ba4e41511bc0666a8ae0f2809dfd447ee42a38531ae86cbc3d26b7002873c7d5ae7e18385c3149eb9051f66d73b1a1707b0e117a217ca6bc70870362d7f475509b741307b0d67c082d86884bc362f90ad504fa8413f64787fc1ca6cf39443ee079b92efc568fded0fba3d90a4cb2abdf44dcc4aacabd03b20ce104fc9a1693a5c7d7a8287a96c764bb4ccaa21ca51eb07191cfb54f96a542defaae3101b47e862a5f0dc258594ff21858dcd44e8abc40d17a0a6786abe3317bdedabd97417487d5a40a5e93143805ab7e1e82d56993db4ced8dc8b668e50cb2520cf004046f8ed4b8a3cd6dc793fb7ef8b9ae9359dfed2757f7aa95b26ebf3fc2b34f3f297de64f46c3304309d4e7d0398413251be97ac607b4b161b3eee93c13b212cbd362518dc4fc07ee406375cc69288c03ba8f0bea27e7a0f9b4c374f8b20cb4a0e1ca3ab273508ecbb405252a2eb9acade37a659ef80c3331dab8c51be3a5cd17c911cc8b07afbdc309fccefa690d4eecb01646ce42e9ea6b731a3e894e9b7062b0974cb601eea796f25ffd6790f98286ca8a2c8142e60c06a5d52d593bf2e8d76d8c1ba0c414e3ae2624042e8d3b1d9fd323a094ff233114e29d7e7d278cdcce3a234d8a835696f10e9d40daa0895dc9f14a91638393fe3eb5938cbf96d94d7a8514e3a23e21b78ff46e006e8639f4c85e2e45bc9a5b138201308dc7d5617c4c9de30dc1b3f30e8936b5a873f563691c96c66ab81cc95d139f032cab4ae56020d7f6b59b2e65fa28ed40e8ab2211beb280ad205c20d6bbb04a742e3755f0082282a53219224695f7a9914db5b2a4bd08aa38047c3bddd91c8b71ce6bd4a994bc576934a3d0591803a84533b61e6433ba6c3805e6b36acaa63fc629e5b16925b2a485b4b4d68b461bb56eba808fbc0f320431125ad77c10244dbec0746af3d176fc1b1590a", 0xbd9}], 0x5)


sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x4}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000040)={0x7, 0x2, 0x2}, 0x4000000000000076, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x31}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0xfffffffffffffda3)


syz_emit_ethernet(0x4a, &(0x7f0000001480)={@broadcast, @empty, [], {@ipv6={0x86dd, {0x0, 0x6, "fcc91d", 0x14, 0x0, 0x0, @local={0xfe, 0x80, '\x00', 0x0}, @ipv4={'\x00', '\xff\xff', @rand_addr}, {[], @tcp={{0x0, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}}})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000300)={0x3, &(0x7f0000000000)=[{0x50}, {0x44}, {0xe6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f0000000200)='./file0\x00', 0x102, 0x0)
r1 = getpid()
fcntl$setown(r0, 0x6, r1)
fcntl$setown(r0, 0x6, r1)


mknod(&(0x7f0000000280)='./bus\x00', 0x2000, 0xf19)
open(&(0x7f00000002c0)='./bus\x00', 0x0, 0x0)


r0 = getuid()
setreuid(0x0, 0x0)
r1 = semget$private(0x0, 0x0, 0x0)
r2 = getgid()
r3 = getegid()
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f0000000140)={{0x8000, r0, r2, 0x0, r3, 0x88, 0x8}, 0x8001, 0x1f, 0x3f})
setreuid(0xee00, r0)
sysctl$kern(&(0x7f00000000c0), 0x2, 0x0, 0x0, 0x0, 0x0)
r4 = msgget$private(0x0, 0x0)
msgsnd(r4, &(0x7f0000000040)=ANY=[@ANYRESHEX, @ANYRESDEC], 0x0, 0x0)
semctl$GETZCNT(0x0, 0x4, 0x7, &(0x7f00000003c0)=""/96)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000001c0)={0x0, <r5=>0x0, <r6=>0x0}, &(0x7f0000000200)=0xc)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000240)={{0x85, r0, r3, r5, r6, 0x180, 0x8}, 0x80000002, 0x47, 0x39dec56c})
msgrcv(r4, &(0x7f0000000340)={0x0, ""/204}, 0xd4, 0x0, 0x1000)
writev(0xffffffffffffffff, &(0x7f0000000080)=[{0x0}], 0x1)
writev(0xffffffffffffffff, &(0x7f00000002c0)=[{&(0x7f00000014c0)=' ', 0x1}], 0x1)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x2a, 0x0)
openat$diskmap(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
r7 = socket$inet6(0x18, 0x3, 0x0)
getsockopt(r7, 0x29, 0x38, 0x0, 0x0)
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x205b1a)
open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)


syz_emit_ethernet(0x5e, &(0x7f0000000080)=ANY=[@ANYBLOB="ffffffffffffbe2c6050b8fb86dd60fecf0c0028000000000000c7f100000000ffffe0000001ff"])


sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f0000001440)="cc", 0x1)
kqueue()
recvfrom(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
syz_emit_ethernet(0x66, &(0x7f0000000100)=ANY=[@ANYBLOB="aaaaaaaaaaaaffffffffffff86dd60aa862000302c000000000007000000000000000000050000000000000008"])
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x2b}, 0x4, &(0x7f0000000380)="3998a035", &(0x7f0000000080)=0x4, 0x0, 0x0)
ioctl$TIOCSTOP(0xffffffffffffffff, 0x2000746f)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000240)=[{0x7}, {0x84}, {0x4000006, 0x0, 0x0, 0x3fefff}]})
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
r1 = open(&(0x7f00000002c0)='./bus\x00', 0x2, 0x0)
poll(&(0x7f0000000040)=[{r1, 0x40}], 0x1, 0x0)
ioctl$WSMUXIO_INJECTEVENT(r1, 0x80185760, &(0x7f0000000140))
r2 = openat(0xffffffffffffff9c, &(0x7f00000003c0)='./file0\x00', 0x200, 0x2)
syz_emit_ethernet(0x3e, &(0x7f00000009c0)={@local, @local, [], {@ipv6={0x86dd, {0x0, 0x6, "cb7065", 0x8, 0x3b, 0x0, @rand_addr="35b282d55c8bf287fa1f01eb6b0de395", @mcast2, {[], @udp={{0x1, 0x2, 0x8}}}}}}})
poll(&(0x7f0000000000)=[{r2, 0x80}], 0x1, 0x7)
write(r0, &(0x7f0000000180), 0x0)
fcntl$setflags(r0, 0x2, 0x1)
open$dir(&(0x7f00000000c0)='.\x00', 0x0, 0x0)
kqueue()
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r3 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r3, 0xc0106924, &(0x7f00000001c0))
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000100), 0x8, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r4 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)


mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x4428)
open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000140)={0x0, 0x0})
syz_emit_ethernet(0x2e, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000680)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f00000000c0)=[{0x81}, {0x4}, {0x26}]})
syz_emit_ethernet(0x416, &(0x7f0000000300)=ANY=[@ANYBLOB="c7e052ea36fbffffffffffff86dd60826e0303e0000000000000000000000e14fc11cd3f6420ff0200000000000000000000000000018900907800000000ff01000000000000000000000000000100000000000000000000ffffe0000001180615bd7b6947fadae9d755ecfe59049c5e0e7cde530fd1de6b16d39a4266c7bc6116d31145454f733e8e0f085dbb0e0b6b5d967b0011df1df3ba48b6a1dfc04f9d6e87f8a4d6fe57aaf935b737a2e4536f55d42043399dcad4f52b7a5d7ffc5a13bb8cd94c23c17b8945251b67dac433546f1b2dd30ea4abad00dabb53a52d7d7d4e945d51feca0cd9ed0fb0b83ea3bbe277da0c5ea9f3d14ad104a88fe58e84138c9768dd21f7a6787b3b6500176c1a28322ee05dc0c88ab62b7d8a447daa952346bd53dba216271ce987fa745c8c14460acf70d21b8eeb733e8269778ea0968755bf2e154f4d44216055aa8f8532f878deadecd4b01d5ce8bb1fb3c781f60cb6aae91358398ad4285ece760cb736f2fa62e06f01ba17a5ac9dd54879bbf4b0587d2c546035b89f44119b51f1d6c5557e4300a69d60d5df61bdfcd5710d1606ea019d2ef7691ba3b00ab210c690ec3beac234d9ddca4f4c9ccea4b1db71c8423c5655e7531742f7c80207c4adba067fc9f91b1998b9986fb1126182c5d663528aae6141af2b4ebeb8df28ea25f4e4b418c71752dc6909c1ba3c19533c5e304fcc83f8bce20512c677aa917835bbb4fd125af9515834707e380e60cb0ec35a8bcb291cdbdc998b840edcd826f690d44f507909bdcb8ae73c6e45da12998de14d3911c8c78b6eb385d002c580793b4d94775190692eae4cbf5da2ec45775e58d2365fd083078977e438f62a05aba8d22a8b367413100d653d6cb88cf4b6258055f06a8e6bfbdc084d767bba8c09e8191364668ebd5db97a4c56bca32c1fbdf39d165a97f7936de001b05fa9ad26b0cab0344365ce1e1918d0e131d0f4fe788916afb32acf3946c167dbac4baf0fb33710989840b56f4386724e08c48af7604619a79c1701c329542b34e8e5992689a8efa458364e5a7adcbbf712ece8eae8374fe2af72512aec60e7cdc57824ca7ee0789f122b75e032c0f1cc6736532ecab63bb9a1a0e0153677a7011f1a7a16c472659a88ddf0325f160281cc619001094aeb22de1fe5457bc44e346d488f91ab70f64f5db8f3c809293334ab695083053adcb8c6f7fe8ea3f2827e38948bd1be59d3e9a1d6df37b9802720b56f5b05beb041dae556fdddec142ce65e4a88895af77765ee958e29bdf8eabd7ac561d2e3b78d15cefb408ec62193948fedab10efd0441ffd55347c308514b873726707f9688140ef48f7b902f766f1f88b9985cb11892f4350434d55721f8e34ffa1ac0248d287437f4b7d5af5d418e8e737ff363cb40c38660d576b27d659c2c0e01e83000000000000000000"])


msgsnd(0x0, 0x0, 0x401, 0x0)
syz_emit_ethernet(0x2a, &(0x7f00000002c0)={@local, @remote, [], {@arp={0x8035, @ether_ipv4={0x1, 0x800, 0x6, 0x4, 0x4, @local, @broadcast, @broadcast, @remote={0xac, 0x14, 0x0}}}}})


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
r0 = open(&(0x7f00000002c0)='./bus\x00', 0x2, 0x0)
poll(&(0x7f0000000040)=[{r0, 0x40}], 0x1, 0x0)
poll(&(0x7f0000000000)=[{}], 0x2000000000000078, 0x0)
ioctl$WSMUXIO_INJECTEVENT(r0, 0x80185760, &(0x7f0000000140))


mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0, 0x2015, 0xffffffffffffffff, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r0 = openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
getsockopt$sock_cred(r0, 0xffff, 0x1022, 0x0, &(0x7f0000000280))
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
msgsnd(0x0, 0x0, 0x0, 0x0)
msgget$private(0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r1 = syz_open_pts()
close(r1)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
kqueue()
open$dir(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSWINSZ(r1, 0x80087467, &(0x7f0000000200))


mknod(&(0x7f0000000000)='./file0\x00', 0x2100, 0x5f00)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x0, 0x0)


mkdir(&(0x7f0000000200)='./file0\x00', 0x0)
chroot(&(0x7f0000000340)='./file0\x00')
setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0x0, r0)
writev(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe2c63a56077123a276d3ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000180)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
connect$unix(r0, &(0x7f0000000040)=@file={0x0, './file0\x00'}, 0xa)
sendmsg$unix(0xffffffffffffffff, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="28000000ffff000001"], 0x28}, 0x0)
sendmmsg(r0, &(0x7f00000000c0)={&(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x3}, 0x10, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
socket(0x2, 0x2, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = getppid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0xffffffffffffffff}, 0x0, 0x0, r0})
pipe(&(0x7f0000000000)={<r1=>0xffffffffffffffff})
setpgid(0x0, r0)
ioctl$WSKBDIO_GETMAP(r1, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r2 = fcntl$getown(r1, 0x5)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r3=>0xffffffffffffffff})
getsockopt$sock_cred(r3, 0xffff, 0x1022, &(0x7f0000000100)={0x0, 0x0, <r4=>0x0}, &(0x7f0000000140)=0xc)
setregid(0x0, r4)
r5 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000424, r5)
setregid(0x0, r4)
ktrace(&(0x7f0000000180)='./file0\x00', 0x0, 0x40000d16, r2)


setrlimit(0x0, &(0x7f0000000980))
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
setrlimit(0x0, &(0x7f0000000980))
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
setrlimit(0x0, &(0x7f0000000980))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000380)=[{0x40, 0xfc}, {0x7c, 0x0, 0x2}, {0x6}]})
ioctl$BIOCVERSION(r0, 0x40044271, &(0x7f0000000080))
syz_emit_ethernet(0x3e, &(0x7f0000000080)=ANY=[])
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140))
setrlimit(0x8, &(0x7f0000000980)={0x42})
syz_open_pts()
getrlimit(0x0, 0x0)
close(0xffffffffffffffff)
syz_open_pts()
ioctl$TIOCSETAW(0xffffffffffffffff, 0x802c7415, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x6bf, "28113bb1e6648a1a267bc03b7a447ab255dcd9f0"})
readv(0xffffffffffffffff, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
ktrace(&(0x7f00000001c0)='./file0\x00', 0x4, 0xd27d43220c7cd9f, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r1 = socket(0x18, 0x1, 0x0)
r2 = socket(0x18, 0x1, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1, &(0x7f0000001240)=0x6, 0x4)
r3 = socket(0x18, 0x3, 0x0)
ioctl$FIONBIO(r2, 0x8004667e, &(0x7f0000000080)=0x1)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r3, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
dup2(r2, r1)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


r0 = open$dir(&(0x7f0000000100)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000140)='./file1\x00', r0, &(0x7f0000000d80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f0000000480)='./file0\x00', r0, &(0x7f0000000180)='./file1\x00')
r1 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000000)='./file0\x00', r1, &(0x7f0000000200)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
unlink(&(0x7f0000000800)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000e80)='./file1\x00', &(0x7f0000000f80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


sysctl$kern(&(0x7f00000000c0)={0x1, 0x5a}, 0x3, &(0x7f0000000100)="71f95f84cf71b59c7afec37582", &(0x7f0000000080)=0x2, 0x0, 0x37)


r0 = socket(0x11, 0x3, 0x0)
r1 = socket(0x18, 0x2, 0x0)
close(r1)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0x0, 0x0, 0x0, 0x40}], 0x0, 0x0, 0x0, 0x0)
r2 = socket(0x800000018, 0x2, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ff7000/0x3000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000604000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000691000/0x2000)=nil, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil}], './file0\x00'})
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r3 = openat$wsdisplay(0xffffffffffffff9c, &(0x7f00000002c0), 0x10000, 0x0)
ioctl$WSDISPLAYIO_GVIDEO(r3, 0x40045744, &(0x7f0000000340))
sendmsg(r1, &(0x7f0000000280)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000300)=[{0x10}], 0x10}, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b1000513000000000000000004000000000013fecea10500fef96ecf2ac72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf7f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f335c223e7d0c032bfa896443a42102000000720fd38bfbb770c1f5a872c88106002ec5890400000000000000361b1257aea8c500002002fbfe0c2300008abfba0900000008e371a3f8343712051eeab7196fcbd80407000000c011200000", 0xb1, 0x0, 0x0, 0x0)
r4 = msgget$private(0x0, 0x0)
msgsnd(r4, &(0x7f0000000580)=ANY=[@ANYBLOB="0300000000000000a60d524ae979b5a3e111c8cac1b119e4db1e444c9d4eca7af32596137392f4cdc50d82caa6fa7ffd0da455fa2e9f5109d4ccbe9ddd5e3674e689a6714f0ac2ee9e36ae12821cff35f5866888d441f7c29189271982efb7cd9c94766d1c4be0efcbf44d5d0010dc9df78616b167b260dd96322bfbad5f46f92beb4126cf5ffee44ca5b5bdfcf14c9b30ccf53d57d96bcceb3c014f4d7b36a32f1fdb2d7783fa77ede48c3db7299ec5e58a1348d1da9304dc8bf8200a241f24ffa673bd7cb93b55b31a3045a1501250df6302a6bbfdcb68febcf98e7aabab17c9e7408bccc3081d1feec2142247dcd0e3ab8a8ab390b2a70909b2f114aa2b6ff73741b6c4c953d4fd45a49aa77d02ae571e60a547d96c4f47fe003bddaa93c475fa2861d500bc87ce5ad627cad71b844204951bdf08bff52b0053e7c98eccef58037f102fd969ec0c86278c4aacf316066c99d2c1a8415b13b998a42770e27686f66e6c7f60bb6eff7269102c25d993ed50c8cb59f6e5f8f3846234adc730b0a742293f76d27d6f2146b96aca091af572bca375bd49ac31918f698ea537fa89c068aad9075d04c153d398394ec17cb7ac66a5cb7f3934912fa391d695a3ef005be3dbdc94e8a8e8b2b92831afeb584ecf26280acd16e2ef1f213d483629ae5906b87844abb013a841439ffc4ab753d050f4d95032ff214a99e06f454cf8e5fd84dc8da0ee9819823ec630a9baa1e508a8d3328502547d272f43a8c729981ff71ba480b37b001a0ea99f62e73c2855ee7ac4350c36ab5cbf2f81853268328d13ea00b1cded0631b42636f539ef64a38344f712a0780639a44be8686603811edd13c3874ec1301d9945978c43bf065ff79fccb884643b5e4dc4ab05764e092f2dc53d54fc3c58dfc7db513cdfe397c8017d017e182ef27f80384a683fa1ecaba56def0f28f07e1aff1f964a7aec1a29c116602900857c0191e77240e7867294428ef5cf8e69e994893fb3e4833a114cf76acbfb2e95d5df3a3983c4df26fc0dd01e167dfee54393ec78805a83f02b2250d32c760e2f251e266feabecb8797245e7a819df60e37e63acdd9c5e4ae1b91af3f3eaa31415e5e6ac94b3945633fa32d6402a92dffa156a443cb0fe58bc13f47c3232bc88d25fb5e6f31be5d6fbf96e93b0e67388a37237cddb983e238f383b2d00800000099d496e2a5329b157345bfe0a6f492e669a1e02cb1a288bdafb09631da2013f1636b89de7b7ce1d04ea044431d42f0ab585d1897fb1c1d40d30c6b3148b3e8d7646c2e43bc18846d18eaef9ac1db4c0300e4c95c8e1bf3e67e9570ded56d1e08b38b194002997c6a14ee2cb8fc581d84e8b0af591722e829afb20a140b64e885d4487fe0abeb5640dd860a4116fd8cbeff648571330c8547e97d555a6580512b19af967d393d28da7461b0daaf5f569e56208cf619f1748fc4554e4970cbda93bf96331f901f00fdab2544a05701cf8e1f6bfae5dbfa444291fbaa9eca6d81c34c6be540888df1162b4f6665265defa30ed9fb8294284f934fa90f3cf414696e31d34f467ead405bee81fda3a6b292a40dd37bd04ae1f81605da8ef62c450bd58525ab30b60b150a9367e200000000000000000000000000008a35ebd5f5a07ed8988f0b892b379e9fc79500b34e0376c1e9b6ea18aab7f2032d8654d7525a1681f0fc9ab5c05e7310b36ee518e7af205cf08dd1430ae38e7beb8424999c69860e8d325ad196a660854254be99a583c4c4aa77af7228e35535e8523394cda4d1632f6542a3b27d735f77e257a5572e6daf02b1a4b950b0ea220cf4e7734d6db76e0e659479c4008eed9b006d579e2cc9ac09fe5eee80645a"], 0x401, 0x0)
msgsnd(r4, &(0x7f0000002b40)=ANY=[@ANYRESDEC=r4], 0x14, 0x0)
msgrcv(r4, 0x0, 0x0, 0x0, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
socket$inet6(0x1e, 0x3, 0x0)
fchmodat(0xffffffffffffffff, 0x0, 0x8, 0xe)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
open(0x0, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
socket(0x18, 0x1, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
sysctl$net_inet_divert(&(0x7f0000000000)={0x4, 0x1e, 0x2}, 0x4, 0x0, 0x0, &(0x7f00000000c0), 0x0)
r2 = open(&(0x7f00000000c0)='./file1\x00', 0x0, 0x0)
mkdirat(r2, &(0x7f00000001c0)='./file1\x00', 0x0)
renameat(r2, &(0x7f0000000140)='./file1\x00', 0xffffffffffffff9c, &(0x7f0000000180)='./file1\x00')
getsockname(r2, &(0x7f00000000c0)=@in6, &(0x7f0000000100)=0xc)
r3 = dup(r1)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
syz_extract_tcp_res$synack(&(0x7f0000002b80), 0x1, 0x0)
sysctl$hw(&(0x7f0000000640)={0x6, 0xd}, 0x2, &(0x7f0000000680), 0x0, 0x0, 0x0)
sysctl$hw(&(0x7f0000000240)={0x6, 0xa}, 0x2, &(0x7f0000000280)="c76bb2d5d5194c0fb70d95adb8af1d73bfbc1e3d35b1fd725caa1dd4da602a606b317f28fdc175233579ea6f32", &(0x7f00000002c0)=0x2d, &(0x7f0000000300)="7e64c4c7c04d5688bca64ca819ac2b070aca6b1f12b5214cfae9b8cbbdeb714ee7", 0x21)
socket$inet(0x2, 0x0, 0x0)
pread(r0, &(0x7f0000000040)="16", 0x1, 0x400)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VMM_IOC_INTR(r0, 0x800c5606, &(0x7f0000000040)={0x5, 0xffff})


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
chmod(&(0x7f0000000080)='./file0\x00', 0x40)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000380)='#!', 0x3e}], 0x1)
writev(r0, &(0x7f0000000100)=[{&(0x7f0000000280)="a8034e3fdd86480e82b020090000019c0a", 0x11}], 0x1)
execve(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
syz_open_pts()
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x8020699b, 0x0)
getpid()
ktrace(0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
fcntl$setown(0xffffffffffffffff, 0x6, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0xff, 0x0)
execve(0x0, 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x4d}, {0x50}, {0x6}]})
syz_emit_ethernet(0x1b, &(0x7f0000000000)=ANY=[])


sysctl$vfs_nfs(&(0x7f00000000c0)={0xa, 0x2, 0x2}, 0x3, &(0x7f00000001c0), 0x0, 0x0, 0x0)
fcntl$getflags(0xffffffffffffffff, 0x0)
shmget$private(0x0, 0xc00000, 0x0, &(0x7f0000400000/0xc00000)=nil)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
mkdir(0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x14}, {0x7}, {0x6}]})
syz_emit_ethernet(0x66, &(0x7f0000000180)=ANY=[])


r0 = accept$inet6(0xffffffffffffff9c, 0x0, &(0x7f0000000000))
getsockopt(r0, 0x8000, 0x101, &(0x7f0000000040)=""/139, &(0x7f0000000100)=0x8b)
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000140), 0x1, 0x0)
ioctl$FIONREAD(r1, 0x4004667f, &(0x7f0000000240))
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
fcntl$setstatus(0xffffffffffffffff, 0x4, 0x4)
r2 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000a80), 0x0, 0x0)
close(r2)


mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
r0 = open(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x42})
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r1 = socket(0x18, 0x3, 0x3a)
setsockopt(r1, 0x29, 0x6c, &(0x7f0000000040), 0x4)
socket(0x2, 0x2, 0x0)
setsockopt(0xffffffffffffffff, 0x11, 0x3, &(0x7f0000000340)="02", 0x1)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
socket(0x2, 0x2, 0x0)
sysctl$vm(&(0x7f0000000140), 0x2, 0x0, 0x0, 0x0, 0x0)
setrlimit(0x0, 0x0)
setsockopt$inet6_MRT6_DEL_MFC(r1, 0x29, 0x69, &(0x7f0000000200)={{0x18, 0x1}, {0x18, 0x1}}, 0x5c)
r2 = syz_open_pts()
ioctl$TIOCSETA(r2, 0x802c7414, &(0x7f0000000240)={0x10001, 0x501, 0x10001, 0x3f, "1cf0e06a9985afdae77176e265dcf03c6350b7a6", 0xffff8001, 0x4})
sysctl$net_inet_icmp(&(0x7f0000000000)={0x4, 0x12}, 0x4, 0x0, 0x0, 0x0, 0x0)
close(r2)
r3 = syz_open_pts()
writev(r2, &(0x7f0000000040), 0x0)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000200)={0x0, 0x0, 0x0, 0xff7fffbe, "ff8974820000a08000000000000000000100", 0x0, 0x20000})
close(r2)
ioctl$FIONREAD(r3, 0x4004667f, 0x0)
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000001240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlink(&(0x7f0000000ac0)='./file0\x00', &(0x7f0000000e40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000f40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000001140)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000001540)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


mknodat(0xffffffffffffff9c, &(0x7f00000000c0)='./file0\x00', 0x2000, 0x4401)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x1000300010008})
open(&(0x7f00000002c0)='./file0\x00', 0x710, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x20, 0x0)
open(&(0x7f0000000140)='./file0\x00', 0x20, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000001e00)={@broadcast, @random="2a9dafffe435", [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x1, 0x0, @remote={0xac, 0x14, 0x0}, @remote={0xac, 0x14, 0x0}}, @udp={{0x0, 0x3, 0x8}}}}}})
execve(0x0, 0x0, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
r0 = open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
r1 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSETAW(r1, 0x802c7415, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x0, "254dfc210b4aa916fbd5f000"})
ioctl$TIOCSETAW(r0, 0x802c7415, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x0, "4dc8cf7e75b57dc84118a5647f8bb76a3efa1ae9"})


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000004c0), 0x2, 0x0)
writev(r0, &(0x7f0000000300)=[{&(0x7f00000003c0)="db489edba2bfdca1ea365559375db630a6b4ca8f6eaf0246910b199b0b8fa90dd578469659e5b4d7c7a17acf7d795dfef11edd188abd65cd12c928aa7353b1f27d0002181b50b91ee7a576e082a62cba8b8d60e1dc9e2c6947414153aba6936d737f", 0x62}], 0x1)
execve(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000001200)=[{0x50}, {0x1c}, {0x6}]})
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000080)="35b5c242413c1026089a59583cc3", 0xe}], 0x1)


mprotect(&(0x7f0000000000/0x1000)=nil, 0x1000, 0x1)
select(0x40, &(0x7f0000000000), &(0x7f0000001140), &(0x7f0000000080), &(0x7f0000000100))


r0 = socket(0x2, 0x1, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x0, 0xffffffffffffffff, 0x0)
syz_emit_ethernet(0x4e, 0x0)
syz_emit_ethernet(0x3e, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x80, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
rmdir(0x0)
r1 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000180), 0x1, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(r1, 0x80085762, &(0x7f0000000400))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
r1 = openat$speaker(0xffffffffffffff9c, &(0x7f00000006c0), 0x1, 0x0)
writev(r1, &(0x7f0000000140)=[{&(0x7f0000000100)="4e7c0fcd79828f259645745435362e", 0xf}], 0x1)
execve(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000000)={0x0, 0x0})
write(0xffffffffffffffff, 0x0, 0x0)
pipe(0x0)
msgget$private(0x0, 0x0)
msgrcv(0x0, 0x0, 0x0, 0x0, 0x0)
setrlimit(0x0, 0x0)
r2 = syz_open_pts()
close(r2)
sendto$unix(0xffffffffffffffff, &(0x7f0000000300)="fd17d9df6248d7e2c14935f0809711f721f2f943", 0x14, 0x2, &(0x7f0000000340)=@file={0x0, './file0\x00'}, 0xa)
r3 = syz_open_pts()
select(0x40, &(0x7f0000000280)={0x10374}, 0x0, 0x0, 0x0)
ioctl$TIOCSETA(r3, 0x802c7414, 0x0)
writev(r2, &(0x7f0000001380)=[{&(0x7f0000000040)='c', 0x1}], 0x1)
r4 = dup2(r3, r2)
ioctl$TIOCSETA(r4, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x7ff, "1ff952e88608007673ca9e5fd700"})
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
setreuid(0x0, 0xee01)
shmget$private(0x0, 0x1000, 0x0, &(0x7f0000002000/0x1000)=nil)


open$dir(0x0, 0x0, 0x0)
mkdirat(0xffffffffffffffff, 0x0, 0x0)
unlinkat(0xffffffffffffffff, 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f0000000640)=[{{r0}, 0x7ffffffffffffff7, 0x1}], 0x6, 0x0, 0x6, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = socket(0x18, 0x3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
ioctl$FIONREAD(r0, 0xc1206951, &(0x7f0000000100))


open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0206923, &(0x7f00000001c0))


mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
mkdir(&(0x7f00000002c0)='./file1\x00', 0x0)
unveil(&(0x7f0000000080)='./file0/file0/../../file1\x00', &(0x7f0000000100)='r\x00')
unveil(&(0x7f0000000280)='./file0/file0\x00', &(0x7f00000001c0)='r\x00')
unveil(&(0x7f0000000040)='./file0\x00', &(0x7f0000000080)='c\x00')


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000400)=[{0x34, 0x0, 0x0, 0x40000000}, {}, {0x806}]})
write(r0, &(0x7f0000000000)="7696e5f3d1f18c37cea8615ac7cf", 0xe)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x881)
r0 = open$dir(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x801)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r1 = syz_open_pts()
dup2(r1, r0)
r2 = open(&(0x7f0000000280)='./bus\x00', 0x0, 0x0)
ioctl$TIOCFLUSH(r2, 0x80047410, &(0x7f00000003c0))
execve(0x0, 0x0, 0x0)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
getgroups(0x0, &(0x7f0000000000))
setregid(0x0, 0x0)
r1 = getppid()
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f0000000200)={0x0, <r2=>0x0}, 0xc)
r3 = socket$inet(0x2, 0x5, 0x0)
r4 = open(0x0, 0xa02, 0xc)
socket(0x0, 0x4, 0xc7)
r5 = msgget$private(0x0, 0x2e)
r6 = socket(0x800000018, 0x2, 0x0)
r7 = socket(0x18, 0x1, 0x0)
setsockopt(r7, 0x29, 0xe, &(0x7f0000000000)="02000000", 0x4)
dup2(r7, r6)
msgsnd(r5, &(0x7f0000000140)=ANY=[@ANYRESDEC=r3, @ANYRES32=r3, @ANYRES8, @ANYRESOCT, @ANYRES16=r4], 0x401, 0x0)
msgrcv(r5, &(0x7f0000000380)={0x0, ""/140}, 0x94, 0x2, 0x0)
msgctl$IPC_RMID(r5, 0x0)
msgsnd(r5, 0x0, 0x1008, 0x800)
msgctl$IPC_SET(r5, 0x1, &(0x7f0000000140)={{0x0, 0x0, 0x0, r2, 0x0, 0xdc, 0xe9e2}, 0xff, 0x200, r1, r1, 0x3, 0x3, 0x8, 0x2})
pipe(&(0x7f00000001c0)={<r8=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r8, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r9 = fcntl$getown(r8, 0x5)
setreuid(0xee00, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0xb32, r9)
syz_emit_ethernet(0x2a, &(0x7f0000000040)=ANY=[@ANYBLOB="ffffffffffffffffffffffff80350001"])
setreuid(0x0, 0x0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000140), 0x782, 0x0)
pwritev(r0, &(0x7f0000000240)=[{&(0x7f0000000000)='m', 0x1}], 0x1, 0x0)


open$dir(&(0x7f0000000b80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x200, 0x0)
r0 = open$dir(&(0x7f0000000280)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000300)='./file0\x00', r0, &(0x7f0000000c80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f0000000dc0)='./file0\x00', r0, &(0x7f0000000ec0)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f00000000c0)='./file0\x00', r0, &(0x7f00000001c0)='./file0\x00')
open$dir(&(0x7f0000000040)='./file1\x00', 0x200, 0x0)
mkdirat(r0, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
symlinkat(&(0x7f0000000040)='./file0\x00', r0, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
open(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
rename(&(0x7f0000000980)='./file1\x00', &(0x7f0000000100)='./file0\x00')
r1 = socket(0x2, 0x1, 0x0)
sendmsg(r1, &(0x7f0000000380)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000180)=ANY=[@ANYBLOB="1000000000"], 0x10}, 0x401)
r2 = socket(0x1, 0x1, 0x0)
close(r2)
socket(0x18, 0x2, 0x0)
sendto(r2, 0x0, 0x0, 0x0, &(0x7f0000000100)=@un=@abs={0x0, 0x0, 0x3}, 0x8)
r3 = socket(0x800000018, 0x2, 0x0)
r4 = socket(0x18, 0x1, 0x0)
r5 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000100), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r5, 0x80105727, &(0x7f0000000040)={&(0x7f0000000000)=[{}, {0x20}], 0x2})
setsockopt(r4, 0x29, 0xe, &(0x7f0000000000)="02000000", 0x4)
dup2(r4, r3)
listen(r3, 0x0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x881)
open$dir(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
syz_emit_ethernet(0xe, 0x0)
open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
acct(&(0x7f0000000000)='./bus\x00')


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x8981, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105727, &(0x7f0000000100)={&(0x7f0000000300)=[{}, {0x2}], 0x2})


sendto(0xffffffffffffffff, 0x0, 0x0, 0x0, &(0x7f0000000080)=@in6={0x18, 0x3, 0x0, 0x1001ff}, 0xc)
r0 = socket(0x800000018, 0x1, 0x0)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892}, 0x1c)
setsockopt$sock_int(r0, 0xffff, 0x1, &(0x7f0000000100)=0x4, 0x4)
getsockname(r0, 0x0, &(0x7f0000000040))


open(&(0x7f0000000040)='./file0\x00', 0xfffe, 0x0)
setreuid(0xee00, 0x0)
socketpair$unix(0x1, 0x2, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, &(0x7f0000000080))
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
setrlimit(0x0, 0x0)
syz_open_pts()
close(0xffffffffffffffff)
r1 = socket(0x18, 0x3, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r1, &(0x7f0000000080), &(0x7f0000000000)=0xfffffffffffffe22)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x800000018, 0x2, 0x0)
bind$unix(r2, &(0x7f0000000080)=@abs={0x0, 0x7}, 0x1c)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000280), 0x6c, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x1}, {0x4d}, {0x16}]})
write(r0, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xfef3)
ioctl$BIOCGDLTLIST(r0, 0xc010427b, &(0x7f00000001c0)={0x2, &(0x7f0000000180)=[0x3, 0x7]})
r1 = socket(0x11, 0x3, 0x0)
sendto$unix(r1, &(0x7f00000000c0)="b10005166000009f050000002010000000000000cea10500fef96ecfc727d3357ae302b37b67ca1f2d61db7f4de57804be38164991f7c8cf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f4d335d223e7db3008b95665bc6fc2102000000720fd38bfbb770c1f5a872c881ea772ec5890405b3b9c2668396f4cd1257aea8c500002002fbfc0c2300008abfba0900000008e37f71a3f8343712051eeab71d89e000040381ecb664000000", 0xb1, 0x0, 0x0, 0x0)


r0 = syz_open_pts()
ioctl$FIONBIO(r0, 0x8004667e, &(0x7f00000020c0)=0xd8d)
writev(0xffffffffffffffff, &(0x7f00000024c0)=[{0x0}, {&(0x7f00000010c0)="07c842338e6e146c6a6a29cca892124da6a63201af451d863c8edd4bdf881813129e2b9c23d5cf19db014bae25a12d9b5af290d5ecef0016b507884371b465856a3117ac0b86ef85879dafd5f70b74a51c9484464e74ae0ba22e29b0925c1d52168c5600e397d81bd3812aa0a4d3ba4bdf95de5479d80a5ae76448fa53f3", 0x7e}, {&(0x7f0000001040)="3b7faaa2cb5abb869175", 0xa}, {&(0x7f0000001200)="e36f84b7a4dc7addfd6afd6a98f0e0ea790ff229baaffce1ce2ef09eae3dc70f920001f25085a14c6b8c612467edce316eca3a3de78e0c9483f349f126dca657fbef1056082d2654286602da34d3cf4d33e5584515637009bfad3e5b026e60e5902fd60a19d9938ec6e392448661e0056076e5d0b9f0e913c7", 0x79}, {&(0x7f0000001280)="4249aeca0542351f545f1cc0f4d023b0e9e81307263720c32a41a826efd68897709611e9092c7f5715a7f8cd56d26da1bd69973647064e227bd20f8c06f83c4291cdb5e5a53013fcc429ef1d53b19c9152ff5d2910486248a84552e8bceb327d5efb10d807ac2aaafa0b6d84af9f746702839443a30d5d92944b5f6a035ca26e6edfce7d850c5b19fb8b2af3929e1fed357ad97c6fae95007b5f2812030c17c541b3f505b2de11ed8ca5121cc6a6353f04ea9954addaa6e914b15e69a717c30995d529c87bb16f56dd0adc88", 0xcc}, {&(0x7f0000001380)="9b9ccb2e9c8fa227124dd10f58c1f558dde9b636262e49fba6575ffdd70694c58e514e4aeccfbbe3eb00f3e05cd1f9720058f2cb4a2f2c1e78e207968f45c85d02eac9853da75122bd376871bbeb91f4f87f02c41553d55cc1f1c69c9bb7c5c37798864c19724d9e34bd9b112ae403def39042f135e51dfe5a9620efa4114d46b1f09c70e40e55c2701a173f7b735495346a6ed3de53b1ed3603f324e7c611640a88b9e2742001ff1ee692850929bf0ce84ac35c378d9b498cdf76321c49b97164681b4ce2a439065bf2a4df3688adaf5a592e89cef845fb669186b859a4", 0xde}, {&(0x7f0000002540)="b708d4dbc5a89b549f64c5e586e2634722079331b57ab4f033f8092a43e5327d90aa4c1dfa86ecee017fd637449b0654dac645110b1459cbefc8ae0cc2be5ff1cec9a0af362173b5565440cc06f63273cc185edd63d0ae3470a13f4ce8321edaed27233a14696a0506ee9c1a838eb984df9120812db7a82aea5ebc9921ee6b29cc4f50f7faab1a722562cf5b49f520c6e6f86bdd484858b70e502ad70e77486455704852accbedb84a8033b652cd1a89fa9f677527447517cf37d7334c96047f1d7d76f91574741777ac1a13be4fa8d4a199a3eca19f5915c5df5fdcdc9661c952e2faa33edbbdc45eef03391585fc02321e00f112b836cb84e2c132e8253e0259b6579a175b8ea3abe36f7544d6c57b95c8e0db87ef5395600ce97584fa4a65cbb64b373f120d483b93620c87e554a05c5e28d129559fe77a2b7368d564893bceb442b5bfa114d52b17dab218da83a1a4c3cf538e470eff5b687007723b35375e656d0cb709bac2e5ce0be664ac3cb3b017f09feb84c04810e377b18e622a56500d2db02354caf5fcfab67e8e7acb55df03757e41f55272d12239d6ef0e84721431e43a982c3458aaeeacfbd18078a15721ba787fca44cfc0e110797fafd0045280dd0ec74901ac7f40f2c3c4418f8481e192c9cf723566dd1447d2d982c7415beeb3153a3fd416b0d70943e0ba8af10c4417e0c03d3554e54e9314865b37ed9fa3020f47d52851e2c35e34867d59a9712c95ab4b04919297cfcb3686a9e14d34783d01dd870d3927e516123591e3942927eed8d2899eedbe6eb0abc6f84abdbca841cc0b30b1928c5962fb1585bee36958823afbba07a65be3707ef935743ba9789e94fc299cae64204ef6e9d683573ef19723876bf9eebbeff94ecc9629cc5dfc34ea25d873c1c8e61abc4d94b6041c961e39c57d20b9beaa06793cee6b9a1e80b2ab9fb4aba8c612ef3fcc2182508a730e480b4660a5fae93b942eef5b66c87b5bcfe2e9d04abe5cfb93083934af9673010ac66f74ec0a3cda14b1306a5bd3d2d98d74eae55ac8ad6f90c7f948ad39c7cbfb5e92f7e267daae17bb281fdf615496c3acadf580d51805e5e2a1e4318d06182953bcecf888b9f7aacb8bfc7727e726ab1fc01c093eb1e389852f7d83e7d864dfa1369cd31887c2f2a8965a367723ca2db3904efddcc1a7c531c3fb7ddbbd9a548542fb35744d8c4a2154881799c1f29a96895eb289ca58b554beb109048a5426834fbffcbb4d96d2f1343c4e0e8928d73595b335811dfc81342136862b86ce5e40c4bfeded3b4ef020d7cf85b85e4bdedad9534bd1985c1f54c08f0f5eedd341f3aeb406103619627a0159e0b6f880c552c509467305d09f416aa20b7db91a4654a232e12d350e89f5328f84bdc324255f906570e6c1ba688e7d854a5f49501a83c75cb77d02835f9f4b6c5dde1e02632792eba1d113d67f9833c976001ccc158ef07db561e5928495b2a637b26a15e07255696c397b7cbbec5a0f7e58b9b1f61e5527fa1d8683bc0c4c70d9719aed9f1f754d4daa21cba2ad3387667a8e048b6ae9e4334c70d62e2069b09a20ddcce229ae94ddf8d28212c87afef9442f6d3e9f271bf5815500df5e360ce681418b32ae9188e7e2d160cb64d4c86575fc62fb60d48272a331c9c37a7edef32f6c52d98ef1564b4750366476deba38dd3b994699e17fae2f42165654c8fc3988fd81d06a8f5c18275f2d0338fd5998d24d1b07304cb4c4366d549c366b370008b2a43f1ec764fac748f25c1eac37ab1adbfce9a37f4a231bed3af757fa17a4cb12f4f0cf2e6f22c96c415081219cf7d1ed670eaa8837e68b0ca8046ff39992f25becaeff5f3a3b125d799abdca623cabb474db50e74274a8138f2eec57b6e350314726e003b0f0a78d164bb554f9aaa13c954b311657b427583986cacd12e9bb1052b0395f69ba4c5156b8cf059a3da13906209f16a61c97f07d4d9dc5f125e06bda8cffbb315aa764df860edcb9f3bee6212d694b64a16ea4c40961be0a3f894029168baed25f344bf7fb8675fcb9b0cac0d81c8a26cb99d39a57b9fef654fad0d62fd0f793097988f76b1506d200c4dd23051f298c1766bd311e37744b6721fb25519ce48135e233ee88be6cf16386d711e404deb5513516391233ed31f00966bad6c2f6cb1bbb780c8fb7e70976929f53e79e83358059e2cebc51da0252ef51b2b9d4b3cfabec5bacea6f12ff174b0ca240513140687121e76fcd4c4e1fffcfd9d36cb6582935627c1eac72a1152ca14ccaed3cba2df22becb59722b2d8c9a3a0bdde1db829c8fdd8d1ba944312068826e0a0b615cb9fded6ec6a753d4da7b61979760882df9813ab6aa8ad444ade9261f8e226b54ee02b20ebd27eb62b8dac8540a2b6980fc33947713ce92585ce8dcb94ff70e21ecf0a7a176436101c967cacea86b0671f9e1ce663d2b7f83b83670f7556ecec155e7a6756a121ec5442500fd296a7106fe8c78995f200dac16484f785251f562467abf669079c5f21cfd9b19fd65b2afca16c7baff1ed260f2ca2ad54b742a5fb5dd2cf6158b4209273146fbd77fa9c5cdf86e507b9aa72d4a00b58e3058877051840f8e255a71208caf04bc008b52b08b0637e051b05f869fbfbb87d53b6d97416705ad318c4166c2721911bf95c5f839a337b6dd7341983c630b14a4516034336710247c55327356ef2362540daf22828197994b6cdb1e8011c926a60b87c2af3274298c15e91957b25b842fc92165cdcf776d640cc29576822f8b756fa6bc068fcbf113e4ed3e195203e04f4682a2e6f26c2491dff74b1569c9d4b002ccdfe101b698429c4dcd9a75ef30e30884793793d0075335b14ab3a637d781dfb497f13add0eb54fd3f64018d9a8234f77e8a705ea77cdf035510eb90b1cd2afd26c3d03cc434aee84220e002d27d4b4b4b1f83553de4682ab4e46f96198ee70312031a11a41d7c051294d0c55cf5c786bd5a3807c9b64f460a99dfdbd4509ebd06601fea76b1f24df502cfb6d27b731fd295ec23ff11ba213aa80b7a09309f2eddb86669f0cd47d98608d479e985fe14c1ef9fe25b7159c56b7342103387568143644a0f8847e104ecb1b7dbf0fe20b8e2b28d6f45ee0a6373be37c8f0a57eb6bf0988c8ad0ef8f2a5f2fa08e0d6d50e2333be40ce79a68261d969bc01debb0933ca0d46122dbf5a4c1c6870151454830c6512bb8511326e0fbb6b0856d635e6d727be9a29d3f4e986a157c0a3202fb50a0cb85a1e0cd57a820ef2cd2199f316164d94ea760bb3ef20eb8d977b377e921dc4dfb7a097eca723c587ef78296a3860aa99ebacdf05547ef7347e68b036f872fbcaa3a7961d57c77618c74b82141eab25052e71d053af68da73917bababc9baa8cc9a9a689f195d22a47c0a8abe191a3068bb8557c6dbb3adbd7a38802b3c8abc3e4b70a977baae27132d5cee0e761ada3098c5b0196ccd35638ed13b3d8189f3c8c814a34cd96ee7ad705844b5fa2df923e7435db221cf9bdfc8e4e902de395a3d0335844211766b22ac5325edd8525aa5c08893cdcdb8d0cb9fe141b9ae325ce387dac8fa71424e38fada76cdd1ad008d55534770c3038be1234a52684c43b31f357169a01d40eec45078fa1a9a757308786c5d5ba85b182f30d215021e4585735733930b28a176882ae37c644b902de0493bc95bc880ca247bfda8b1b1ccdae89a60df3a1900b95ab2f786ac7f7786a89a8ffc935dbbc904b24a7f7a92a81b84adab50d4a8bf536a255fa5a8d18c8be591cf4850e2393d2477fa56d509389e86a6a0ed827ac02344d6091f843d3fa4cde269edaf8a4e7eec70222475ccd053e2f94f14f72306ad1038de70f844e2a9dd3f7a07f142db3d9e7feccc638790191c23f9fe7feccadb15e8f98418df969fc32dd07d5ec91a4be40b32523aaec8f23c0032e2583940fbe0ff2737c2fc127c6b6ccebbcde723fa2929f8fa2faf833b6fd3435eaae3813a53d1c8c9092755cb7bcc44695c45103af7a4274d093ece33b3d7f112e0bd81c5d4300e8d1f36e953cb8684f3ee584409e69d3f38ff71b1a3e9665b6d376a84ebd37a51338e88d98b74116e55c8c1bb5879fed2263bb78b2fe1c7a76476166bae96254c3e9690e03d05fab95f3ff4944cebe65ddd37c5966c428528bcef74a7c12c9ca0658e36b4d1893285a5420072f5a1ad873f18f63809", 0xba8}], 0x7)
mprotect(&(0x7f00006c8000/0x3000)=nil, 0x3000, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
preadv(0xffffffffffffffff, 0x0, 0x0, 0x0)
minherit(&(0x7f0000ff4000/0x4000)=nil, 0x4000, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
setsockopt$sock_linger(0xffffffffffffffff, 0xffff, 0x80, &(0x7f0000000080), 0x8)
mknod(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = kqueue()
kevent(r2, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r3 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r3, 0xc0206921, &(0x7f00000001c0))
r4 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r4, 0x80206916, &(0x7f00000001c0))


shmget$private(0x0, 0x2000, 0x400, &(0x7f0000ffe000/0x2000)=nil)
open$dir(&(0x7f0000000080)='./file0\x00', 0x10, 0x1)
linkat(0xffffffffffffffff, &(0x7f0000000040)='./file0\x00', 0xffffffffffffffff, 0x0, 0x0)
r0 = shmget(0x0, 0x4000, 0x600, &(0x7f0000ffc000/0x4000)=nil)
shmctl$IPC_STAT(r0, 0x2, 0x0)
truncate(0x0, 0x0)
msgget$private(0x0, 0x0)
msgsnd(0x0, 0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
getuid()
getegid()
getegid()
setgroups(0x0, 0x0)
chmod(0x0, 0x0)
shmctl$SHM_LOCK(0x0, 0x3)
shmget(0x0, 0x3000, 0x0, &(0x7f0000ffd000/0x3000)=nil)


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$DIOCMAP(0xffffffffffffffff, 0xc0106477, &(0x7f0000000200)={&(0x7f00000002c0)='./file0\x00', r0})
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r1 = socket(0x18, 0x3, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r1, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
r2 = socket(0x18, 0x2, 0x0)
r3 = socket(0x18, 0x2, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
dup2(r2, r3)
sendmsg(r3, &(0x7f00000002c0)={0x0, 0x0, &(0x7f00000001c0)=[{&(0x7f0000000080)="8a07fc059328491804424a11b2fa028d6cdea11cc55e5eea3e712fd225f505867123b7f479d6809197b7abb245a6a90d101904863d6e9a"}, {&(0x7f0000000180)="02c1e20a2e0ce81d339ed28b04a60d52cda2b3c86ad335e799f27a1597941910"}, {&(0x7f0000001300)="349409068a157a5d1cd1898fdd78cf8ebee5129ab0adf53061d63d4e70ae40ab544d00f5ca6775ae4f9c1076db79108ccedc8e3783e2a86cfc619429c6ab373acab96b35e818ce5154edd20e074dbe033ba9c2af6527497f77063821ec83053996276228d6d5dbc7c13718ca1113bea34ab01fc2932518b5cf93c3a051aade6f26347a74540c310eceaf2304da2d4c37d7b6d0666a67ea50ecf1d2fb7336a52f08695592437406e2ad9d4c9ffbd260dce6a9eff53832111728a7b100fe85beeae0825a2adc97dc1d3eee31d6e482e19f50d8f03b7e92621c09de112e7663521ecb604ad3c5f7902647371e116514953405a10bc3bc5a010d9eacb8f4ede38de585066aaa8ee9dd4886ca2cad43144bd0f3c0809f05382fe0b1b018cd0a1bc3b61c0dadfbc11e7939b47897df90a75084cd4fe203623abc7bd607a2ebc5e8ff0a933cb3498567a9a2941a063d86e263090c95ef9faf103139fa509fd5c76a0652b1e2234816e854812ccac047dad28403551275abee2de74a226ffd6dadbf7b5f550c7f46fab2e11be5af4fc7bbfcbe42885f9d90ebf01523a97dc84416bb4cb755cb7d3268ca6242aa1e0c8bee4bc0efd34a28485acf30427cda6125bd71de4b53a615105e19bab53514e8b1c6f59461cb0c3b4cbb0eb88d3da0534d20a665096e396278f7d4e0789588f420df9b7025f9dec8d2f4deab15687d69a056537b44723c2c12bfc1ed2a57b6b1fa3fff9587e81272484babaf3ca670099edc163a40d67931a457fab205604347d078bc6069602a1ec600475be8d3e0beb8e2528a5bb3d937ff37000c487f7d14f5b8689bc77566719be278e2bf3a293417498c34989d159b7ab42a6d4e0a83df7d4e96f8c537c47cd3f50c19b5576a1830f51b7dd8505607401263dc37e733e5d9e6be4c4a3ce3430228a21ede7d7ad81572f33688fcf39585a9b94169107b8cd092d5bf8861177be35ab14ada48e240f90ff38556173573fe1e3697f27a94a472397b1528fc7269a83576ce8a49f9b4395ba565bb9645818f58ec1d863c61a52d7a6dde3cbf3ea0ccdfe225cd696783685784ca798e4f700c47fbc159b2b41c6573b63061ee61326545d0d815d209b6b07ffde9750a423d4ee028c8ed2ad847ed21bdb58a19c6b4af36b916bbe47272bd33cbdb2bcaaafde3be906ea31ff2f123cc77868ffcbe9cf359390daaf4377101d8454e20cddf100084c0c0688a67d6772c945d27581eb4a1b2e40b1ffe2351ea98114d14d2e4bf3df16e45ce2def4aa9d845a04a27325a697acedfb23e891eabc1e6c8df87f02dc96ad245b3f884b75ff7d6fc421eeb924595daf33bbab051533a9927706a845f92cbae3277a4092a1acc93f7db688de0622c0680b96178015232b5db6a347bb8635b1792b43998c0703519e7ed1a34d66c806e10c70405a6bbe9c62433083d7108974224d0eb76f271b317749ec4b797cadc773d3d3314d9dad7510283080372917e00860d29baba7ca6145fb582468ef85d98b5068d7d25679386c723c47b3fac841731ab44d8935159a4f0d40a937df2c26aa6d6208992487648bcf8cc29d05cb447636561a532b0006ecd363340285cab33fc67d99305b38e66d533a089c20c9c64e96c6246f3c9a6f97bad3ef1abc0854d5619aeeba72cfb62a053245e32916987175e2f527ed6145dad3d46f98b10414c9180dc2c9b01eb2b6e9a58b96547700329febf9a2d9fe9325e5e35e758559ee4648ae2bd392036496b473270cdf3c6083d67ed4752e8107fff174d787ee1067af50f2e12ad33636ca1e3e1b0b98026c1d7214390d53990a84e864b8320cbb9e21d6db32b700265386e8bd338b6b601736ab8d1d8871356ec79fef672aba8074d8acf07def315220bcff5fb03d5e7e57b1ff26732ab9fd571c2876265481f8eaae49b13c840ead6231e7f237a9fc4ed83c3588a3dee05fea7aaaa5aff8e152c8d5c356e1756b2aeeae4d778718f08847421263f2080267144f1eefa5539f8c5b320cddfd4042795822545583bd56951f3f0760b9f0f74a481f29d11c1518bca77320b96a154571c627d7b1d57f910d002b51be7b2a4c7964953c6b80d5b182b7b2227211084c6b036473143f5244ac3e3b392792c661166d694927a8cd948c2a5bb7bf10cf314cfd85f86077b41e9b34c2dee93e671a50a5fafbfcf73f64f5a1afc92d194e310d3b819b90bab16ec7aec59c176dd463c955c14d718b49ae2bc812dcc30d32ab9c83156ae7aafd507bf9901c367c84e292f0af9ea29d2705655f54223f80eee9466faa5cbc4d46ddf62b37acf12063af4024ac1e336bb457b3c2bc0f66c6418c657012bb3aecc900c16b39b86f02894fcc60da0661d0669eda1397aaea4658813ad3868b6693a02be0ff75f64a672255dcc85562fd9d52d97d3f7c911ff9de786bd607abfc6e21d06d22edc93b1c95155c5e998b1bc45b3a544cd698eaeec65322d6b7df4507b19f77d15e8856d15da2abf2be48523eeb5a9971afc617e215861740629b9f0ac1e42d0d904ebcd70e207717c16a57f938b823644cc091a2fe85dd066538318bc2cff34cd4231164ea06300b4d1de763b7eb0fe7c8600a44647e6a760eaf9e91a1482bc3a39c749a426f990db81b5a930d614fbb295d1edda9be352961685b4cd477f3db580f04ee59f27c27f212efb82089f2d71d6951bec7146efa7e392cff3776eb2d10021255a749859a082a265e43eb60896029b6af3ee4e68c02ce2e150045d856fbfca1bb1599169f492722de75dfb81ea0579a9789a1b1a964f534feea3e62d670bd4be55f84a932f644aab077bff3fa9c110224b4e381965f4a9af2e13d7771f5a77498a74deab9de3c759723c6fade4713cc1f857069d889107018d95fde366a43b7b4237e9b903e49b8c21c7ff6aeef833fd79a35c84eb60b3bbbff67ea6243fb214d54de7e276ab39ccb0c5e40489635a44c5aec4978470f068e4c264531b921ed2212f6a06a675da2607968b13984e502068e24427aea33d1647b906124490bd4e9133adb014bfe71a98de1a37566e8c9c65d119131b41980c41be9dfb4149ef4ab6ce2ec81c731466f9ad409f097f7bd0fb6134325b64ea6ab40d6dc001802c6dda494343aae424f1d0e46b582a3a849f8891bb44e4c4a47967db604643cd3c34eff4d646db8dbcb867b4fae8581bb9a14f620efd2fb654733f04420ce010de178c38ef719414990e3742c00fdfd5c3b14c4883d50a0289397fcf08f503134a12ef8f2bfd669a91a5e813535d5d256b1d98490a1795979664dd768de802a0b479b11ee72aee7a0fa021f224ea2418902d2dcccafccafb194ea7db8410e80f8648f96f46df94e5ee12c146366a7dd483caf164ff430a91434b090f07082a3ecee4acea1889f4b7be6cffa58a7f0c4c0af20af88630c9d0ebe64e65204c4da50fef9c19a3f88a57c0480abe449ea08791d5f217b927b13787962234e708e9aea67461d6e2e9db8b3afe6666a33eaedc1c0fc07160705a3098f2394f2220d91b89693eb0533b6512bf27820608d11cd8e928a636e37e296d5cb030d567cce87a411416e7bcae80d21b38b2f50cd80f7b7ad205dba1af9e76f6e91395c830cfaaf0750bddb278687d2f70977b50f3fb7dbdc3ac0aaac14dbae97f49cf40ba6832e4c016e3dd397ce0429ee0ddb637a913c200c7e9384d1f97293db4f86943449b621aa10b7868df92558b8b1788688225d07ea0000cce709ce67ba7be299d0fb950c602da1d0228a61d65130879f6015d3b4787096f04e9a8737d627d4cafbfbe60df40f1dafcdc029d9bab336aaab0a8e9d49e61b127687bbfa40b6e126031be5ab2045c1d5f9d8c5d8f2dae487f5639ce0f57a5fe908d18a282b86c78e8cf6b2bad426d22742f414b30d05386788e65b8ee3b58c36f7cfd1e01e51f02491a0c239ff7d4fefff13dd3565e7075714b634a3c764a1a17126a3ccf451fb60e593be9551b481e4c93c268c6ce7feef26b54497907c721963c0cf6964bf7c194c137b2acb78350854f0a72503444b799d622d3342224e10cefd05381a222e99648882a4f39b65bcc62b8a6618075084819074dae6325e1826a68ccd45b940d8b7bcd38c00ecbfe72690142cf8ffa1b86c37ad7e80f0cf2b39abe0afbdca0f17c97b6d7ec666f335e7ef848946f876870c74fec8dac0beda5f8f5514476304452b936f0e343e440460d578d80eb42d99034b5894b16049f28f1e0d7679f35b672bd241d7bf96f2ef2484b85a12743eb8434da5e35a6c99eeb451b289a96f0a0d41e9d555508de504ec63c4628c02abea2d0ace115b7b1fcaf3679d4f68b45785e1ff2d7ab135834f5a34d69a336e95e64eb754ba9c67cb9787c2cb4a115f09fc70ef5bd87295b0287a8fb33789d53c9de6daa6058e29b017af3acbaa3269c109f131737e91cded362de0a080577affaf912c25a302ada66f94358a1baf648a5d8f20a7d588b159e49ff9ad9634fac8708093990e5cab88d4b2c52818c9fcfb584b9a83bedccec466e94dc5cebd892d89b9059b69ed69ebd52f5a736fd8dd8caac0c296a8e992473cc374d81dd5cff98c7788ab590e450b3b0e2f3d3353e14dfe849847b8b263407c7ce0e45ea70192bb7d0f96ca5846973189abbc9e71f73f2ab4395ba9e2681c67aeee2b6d3ce009b517c0872f3b6b906b9ca86e15196d38aef602a5ee671d511993c940802a4d3c4cf98ee012f5111e9c10e46cf2110afd22ed016238e16e8f1e9bac75c84f59b692e2cc6e4f9e0edca7e85c7fd19989f9de4ea904a572de19af3b8c70319139c0d5c035e54ad3436f6e5cc1bda4e252dbe5335fc1776794926fabbab1e7039e43b112c3b83841fadabda56f531245b1140483fbbe548691b3ddc569fa2b5d156698ca78cdc5d11aef9363fe85eff0dc2292024bba9f055316b1f0b9c08b7729620e4b459d7ceb47ba6de350421dc71698b1494b14bc35be2c21cb125c36230599ba362206d8b9819e8a186d90a218b6195c26ea7e6d215b8c7f210e350396e87e3b9fa302366a91327be7040272d04125355876cecb6d8f6ff13115806cc946f63bfa4ea7675eb11fd027a13fca8375b4682f4b669fb9f7f04320d93e7f665fb3307092e4bc958b4d33604e262f374956f87cc811becd7313c91bbcbefbd4356426d90cca601092a90d16c8dbd8e5e8cfa2d4fdb0a6706682c993336be10378492a9c980a5def332c2a3266f4c3460d9ac4a06eac3addf223454d6896ece7824efadf29f14c8e36b9631891143c952e1f67ca3de76f93ce410d74147eed5af08bb3ce37eebd3cbbb2baf77ad57ffff186f13ee31b263e452c4a6780e677188f872944d2496167ce92eef6f33b16232e6de544c9d0d3a77df877c7ee3c4e2b464fd261c2446bc71d20bbd9947e1de113933efe365bebd8b1de05f0cf11d842c9cd9cbe03dfdd0068ba7e207e48d44e17458ac4420769ca9f3d9cc11bffe6cc16313167b605cee6513989fedd77b076a57a6779cc3cc724b1e2fc219bab630f310e7ec903e74d2a6deeb06179c1d8690ce46a398eeb318d61ac4cd66758f6262235b931c510a5b78f02a3ae00258cebf0ab362c0ec0fbcc6e41b7c6b83f441cfc907d811eae3a39aaaa0b91bd3a3066d1508da3e3df742a97e5e4ff88c2a56655f3efadbf78cab2f32caddf31b9513036e5cf038fbf5641cf1b6e75a961d91e43b299b4e72b6d210902c1a9ca933c282c941b14f336dff31bac5848f12e982b99b7285e128fb000000000000c6159beeddf2165aa1fe5374321ee849bb33733832fb16632ece8fedb7b06d7d2b0159b2c9a85907ca47be9e7c17bacdb2ab0fb592945fa51be18ace572681be61"}], 0x43, 0x0}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000100)=[{0x2d}, {0x4d}, {0x6}]})
write(r0, &(0x7f0000000000)="7696e5f3d1f18c37cea8615ac7cf", 0xe)


socket(0x11, 0x3, 0x0)
r0 = open(&(0x7f0000000180)='./file0\x00', 0x70e, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r1 = socket(0x18, 0x3, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r1, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
r2 = socket(0x18, 0x2, 0x0)
r3 = socket(0x18, 0x2, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
dup2(r2, r3)
sendmsg(r3, &(0x7f00000002c0)={0x0, 0x0, &(0x7f00000001c0)=[{&(0x7f0000000080)="8a07fc059328491804424a11b2fa028d6cdea11cc55e5eea3e712fd225f505867123b7f479d6809197b7abb245a6a90d101904863d6e9a"}, {&(0x7f0000000180)="02c1e20a2e0ce81d339ed28b04a60d52cda2b3c86ad335e799f27a1597941910"}, {&(0x7f0000001300)="349409068a157a5d1cd1898fdd78cf8ebee5129ab0adf53061d63d4e70ae40ab544d00f5ca6775ae4f9c1076db79108ccedc8e3783e2a86cfc619429c6ab373acab96b35e818ce5154edd20e074dbe033ba9c2af6527497f77063821ec83053996276228d6d5dbc7c13718ca1113bea34ab01fc2932518b5cf93c3a051aade6f26347a74540c310eceaf2304da2d4c37d7b6d0666a67ea50ecf1d2fb7336a52f08695592437406e2ad9d4c9ffbd260dce6a9eff53832111728a7b100fe85beeae0825a2adc97dc1d3eee31d6e482e19f50d8f03b7e92621c09de112e7663521ecb604ad3c5f7902647371e116514953405a10bc3bc5a010d9eacb8f4ede38de585066aaa8ee9dd4886ca2cad43144bd0f3c0809f05382fe0b1b018cd0a1bc3b61c0dadfbc11e7939b47897df90a75084cd4fe203623abc7bd607a2ebc5e8ff0a933cb3498567a9a2941a063d86e263090c95ef9faf103139fa509fd5c76a0652b1e2234816e854812ccac047dad28403551275abee2de74a226ffd6dadbf7b5f550c7f46fab2e11be5af4fc7bbfcbe42885f9d90ebf01523a97dc84416bb4cb755cb7d3268ca6242aa1e0c8bee4bc0efd34a28485acf30427cda6125bd71de4b53a615105e19bab53514e8b1c6f59461cb0c3b4cbb0eb88d3da0534d20a665096e396278f7d4e0789588f420df9b7025f9dec8d2f4deab15687d69a056537b44723c2c12bfc1ed2a57b6b1fa3fff9587e81272484babaf3ca670099edc163a40d67931a457fab205604347d078bc6069602a1ec600475be8d3e0beb8e2528a5bb3d937ff37000c487f7d14f5b8689bc77566719be278e2bf3a293417498c34989d159b7ab42a6d4e0a83df7d4e96f8c537c47cd3f50c19b5576a1830f51b7dd8505607401263dc37e733e5d9e6be4c4a3ce3430228a21ede7d7ad81572f33688fcf39585a9b94169107b8cd092d5bf8861177be35ab14ada48e240f90ff38556173573fe1e3697f27a94a472397b1528fc7269a83576ce8a49f9b4395ba565bb9645818f58ec1d863c61a52d7a6dde3cbf3ea0ccdfe225cd696783685784ca798e4f700c47fbc159b2b41c6573b63061ee61326545d0d815d209b6b07ffde9750a423d4ee028c8ed2ad847ed21bdb58a19c6b4af36b916bbe47272bd33cbdb2bcaaafde3be906ea31ff2f123cc77868ffcbe9cf359390daaf4377101d8454e20cddf100084c0c0688a67d6772c945d27581eb4a1b2e40b1ffe2351ea98114d14d2e4bf3df16e45ce2def4aa9d845a04a27325a697acedfb23e891eabc1e6c8df87f02dc96ad245b3f884b75ff7d6fc421eeb924595daf33bbab051533a9927706a845f92cbae3277a4092a1acc93f7db688de0622c0680b96178015232b5db6a347bb8635b1792b43998c0703519e7ed1a34d66c806e10c70405a6bbe9c62433083d7108974224d0eb76f271b317749ec4b797cadc773d3d3314d9dad7510283080372917e00860d29baba7ca6145fb582468ef85d98b5068d7d25679386c723c47b3fac841731ab44d8935159a4f0d40a937df2c26aa6d6208992487648bcf8cc29d05cb447636561a532b0006ecd363340285cab33fc67d99305b38e66d533a089c20c9c64e96c6246f3c9a6f97bad3ef1abc0854d5619aeeba72cfb62a053245e32916987175e2f527ed6145dad3d46f98b10414c9180dc2c9b01eb2b6e9a58b96547700329febf9a2d9fe9325e5e35e758559ee4648ae2bd392036496b473270cdf3c6083d67ed4752e8107fff174d787ee1067af50f2e12ad33636ca1e3e1b0b98026c1d7214390d53990a84e864b8320cbb9e21d6db32b700265386e8bd338b6b601736ab8d1d8871356ec79fef672aba8074d8acf07def315220bcff5fb03d5e7e57b1ff26732ab9fd571c2876265481f8eaae49b13c840ead6231e7f237a9fc4ed83c3588a3dee05fea7aaaa5aff8e152c8d5c356e1756b2aeeae4d778718f08847421263f2080267144f1eefa5539f8c5b320cddfd4042795822545583bd56951f3f0760b9f0f74a481f29d11c1518bca77320b96a154571c627d7b1d57f910d002b51be7b2a4c7964953c6b80d5b182b7b2227211084c6b036473143f5244ac3e3b392792c661166d694927a8cd948c2a5bb7bf10cf314cfd85f86077b41e9b34c2dee93e671a50a5fafbfcf73f64f5a1afc92d194e310d3b819b90bab16ec7aec59c176dd463c955c14d718b49ae2bc812dcc30d32ab9c83156ae7aafd507bf9901c367c84e292f0af9ea29d2705655f54223f80eee9466faa5cbc4d46ddf62b37acf12063af4024ac1e336bb457b3c2bc0f66c6418c657012bb3aecc900c16b39b86f02894fcc60da0661d0669eda1397aaea4658813ad3868b6693a02be0ff75f64a672255dcc85562fd9d52d97d3f7c911ff9de786bd607abfc6e21d06d22edc93b1c95155c5e998b1bc45b3a544cd698eaeec65322d6b7df4507b19f77d15e8856d15da2abf2be48523eeb5a9971afc617e215861740629b9f0ac1e42d0d904ebcd70e207717c16a57f938b823644cc091a2fe85dd066538318bc2cff34cd4231164ea06300b4d1de763b7eb0fe7c8600a44647e6a760eaf9e91a1482bc3a39c749a426f990db81b5a930d614fbb295d1edda9be352961685b4cd477f3db580f04ee59f27c27f212efb82089f2d71d6951bec7146efa7e392cff3776eb2d10021255a749859a082a265e43eb60896029b6af3ee4e68c02ce2e150045d856fbfca1bb1599169f492722de75dfb81ea0579a9789a1b1a964f534feea3e62d670bd4be55f84a932f644aab077bff3fa9c110224b4e381965f4a9af2e13d7771f5a77498a74deab9de3c759723c6fade4713cc1f857069d889107018d95fde366a43b7b4237e9b903e49b8c21c7ff6aeef833fd79a35c84eb60b3bbbff67ea6243fb214d54de7e276ab39ccb0c5e40489635a44c5aec4978470f068e4c264531b921ed2212f6a06a675da2607968b13984e502068e24427aea33d1647b906124490bd4e9133adb014bfe71a98de1a37566e8c9c65d119131b41980c41be9dfb4149ef4ab6ce2ec81c731466f9ad409f097f7bd0fb6134325b64ea6ab40d6dc001802c6dda494343aae424f1d0e46b582a3a849f8891bb44e4c4a47967db604643cd3c34eff4d646db8dbcb867b4fae8581bb9a14f620efd2fb654733f04420ce010de178c38ef719414990e3742c00fdfd5c3b14c4883d50a0289397fcf08f503134a12ef8f2bfd669a91a5e813535d5d256b1d98490a1795979664dd768de802a0b479b11ee72aee7a0fa021f224ea2418902d2dcccafccafb194ea7db8410e80f8648f96f46df94e5ee12c146366a7dd483caf164ff430a91434b090f07082a3ecee4acea1889f4b7be6cffa58a7f0c4c0af20af88630c9d0ebe64e65204c4da50fef9c19a3f88a57c0480abe449ea08791d5f217b927b13787962234e708e9aea67461d6e2e9db8b3afe6666a33eaedc1c0fc07160705a3098f2394f2220d91b89693eb0533b6512bf27820608d11cd8e928a636e37e296d5cb030d567cce87a411416e7bcae80d21b38b2f50cd80f7b7ad205dba1af9e76f6e91395c830cfaaf0750bddb278687d2f70977b50f3fb7dbdc3ac0aaac14dbae97f49cf40ba6832e4c016e3dd397ce0429ee0ddb637a913c200c7e9384d1f97293db4f86943449b621aa10b7868df92558b8b1788688225d07ea0000cce709ce67ba7be299d0fb950c602da1d0228a61d65130879f6015d3b4787096f04e9a8737d627d4cafbfbe60df40f1dafcdc029d9bab336aaab0a8e9d49e61b127687bbfa40b6e126031be5ab2045c1d5f9d8c5d8f2dae487f5639ce0f57a5fe908d18a282b86c78e8cf6b2bad426d22742f414b30d05386788e65b8ee3b58c36f7cfd1e01e51f02491a0c239ff7d4fefff13dd3565e7075714b634a3c764a1a17126a3ccf451fb60e593be9551b481e4c93c268c6ce7feef26b54497907c721963c0cf6964bf7c194c137b2acb78350854f0a72503444b799d622d3342224e10cefd05381a222e99648882a4f39b65bcc62b8a6618075084819074dae6325e1826a68ccd45b940d8b7bcd38c00ecbfe72690142cf8ffa1b86c37ad7e80f0cf2b39abe0afbdca0f17c97b6d7ec666f335e7ef848946f876870c74fec8dac0beda5f8f5514476304452b936f0e343e440460d578d80eb42d99034b5894b16049f28f1e0d7679f35b672bd241d7bf96f2ef2484b85a12743eb8434da5e35a6c99eeb451b289a96f0a0d41e9d555508de504ec63c4628c02abea2d0ace115b7b1fcaf3679d4f68b45785e1ff2d7ab135834f5a34d69a336e95e64eb754ba9c67cb9787c2cb4a115f09fc70ef5bd87295b0287a8fb33789d53c9de6daa6058e29b017af3acbaa3269c109f131737e91cded362de0a080577affaf912c25a302ada66f94358a1baf648a5d8f20a7d588b159e49ff9ad9634fac8708093990e5cab88d4b2c52818c9fcfb584b9a83bedccec466e94dc5cebd892d89b9059b69ed69ebd52f5a736fd8dd8caac0c296a8e992473cc374d81dd5cff98c7788ab590e450b3b0e2f3d3353e14dfe849847b8b263407c7ce0e45ea70192bb7d0f96ca5846973189abbc9e71f73f2ab4395ba9e2681c67aeee2b6d3ce009b517c0872f3b6b906b9ca86e15196d38aef602a5ee671d511993c940802a4d3c4cf98ee012f5111e9c10e46cf2110afd22ed016238e16e8f1e9bac75c84f59b692e2cc6e4f9e0edca7e85c7fd19989f9de4ea904a572de19af3b8c70319139c0d5c035e54ad3436f6e5cc1bda4e252dbe5335fc1776794926fabbab1e7039e43b112c3b83841fadabda56f531245b1140483fbbe548691b3ddc569fa2b5d156698ca78cdc5d11aef9363fe85eff0dc2292024bba9f055316b1f0b9c08b7729620e4b459d7ceb47ba6de350421dc71698b1494b14bc35be2c21cb125c36230599ba362206d8b9819e8a186d90a218b6195c26ea7e6d215b8c7f210e350396e87e3b9fa302366a91327be7040272d04125355876cecb6d8f6ff13115806cc946f63bfa4ea7675eb11fd027a13fca8375b4682f4b669fb9f7f04320d93e7f665fb3307092e4bc958b4d33604e262f374956f87cc811becd7313c91bbcbefbd4356426d90cca601092a90d16c8dbd8e5e8cfa2d4fdb0a6706682c993336be10378492a9c980a5def332c2a3266f4c3460d9ac4a06eac3addf223454d6896ece7824efadf29f14c8e36b9631891143c952e1f67ca3de76f93ce410d74147eed5af08bb3ce37eebd3cbbb2baf77ad57ffff186f13ee31b263e452c4a6780e677188f872944d2496167ce92eef6f33b16232e6de544c9d0d3a77df877c7ee3c4e2b464fd261c2446bc71d20bbd9947e1de113933efe365bebd8b1de05f0cf11d842c9cd9cbe03dfdd0068ba7e207e48d44e17458ac4420769ca9f3d9cc11bffe6cc16313167b605cee6513989fedd77b076a57a6779cc3cc724b1e2fc219bab630f310e7ec903e74d2a6deeb06179c1d8690ce46a398eeb318d61ac4cd66758f6262235b931c510a5b78f02a3ae00258cebf0ab362c0ec0fbcc6e41b7c6b83f441cfc907d811eae3a39aaaa0b91bd3a3066d1508da3e3df742a97e5e4ff88c2a56655f3efadbf78cab2f32caddf31b9513036e5cf038fbf5641cf1b6e75a961d91e43b299b4e72b6d210902c1a9ca933c282c941b14f336dff31bac5848f12e982b99b7285e128fb000000000000c6159beeddf2165aa1fe5374321ee849bb33733832fb16632ece8fedb7b06d7d2b0159b2c9a85907ca47be9e7c17bacdb2ab0fb592945fa51be18ace572681be61"}], 0x43, 0x0}, 0x0)
close(0xffffffffffffffff)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000240)={0x2, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x0, 0x3}]})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000180)={0xffffffffffffffff, <r4=>0xffffffffffffffff})
getsockopt$sock_cred(r4, 0xffff, 0x1022, &(0x7f00000000c0), &(0x7f0000000200)=0xc)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x37}, 0x4, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x19a, 0x0, 0x2e)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x2012, r0, 0x0)
r5 = socket$inet(0x2, 0x3, 0x0)
getsockopt$sock_int(r5, 0xffff, 0x20, 0x0, 0x0)
open$dir(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r6 = getpid()
ktrace(&(0x7f0000000080)='./file0\x00', 0x0, 0x40000530, r6)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r7=>0xffffffffffffffff})
sendmmsg(r7, &(0x7f0000000000)={0x0}, 0xfffffe32, 0x0)
mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x205b9a)
open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)


sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b10005016000009f0500060003000000331c13fecea10500fef96ecfc72fd3357af302b37b673039d2d236acf20b7804be", 0x31, 0x0, 0x0, 0x0)
r0 = socket(0x11, 0x3, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
sendto$unix(r0, &(0x7f0000000000)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
getrusage(0x1, 0xfffffffffffffffe)


openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
open(0x0, 0x200, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x0, 0x0})
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x53e, 0x0)
writev(0xffffffffffffffff, &(0x7f00000001c0)=[{0x0}, {&(0x7f0000000040)}], 0x2)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r0, 0x80206982, &(0x7f00000001c0))


kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0xfffffffffffffffe}], 0x0, 0x0, 0x0, 0x0)
r0 = socket(0x800000018, 0x2, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
getsockname(r0, 0x0, &(0x7f0000000040))


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x802069dd, &(0x7f00000001c0))


ktrace(0x0, 0x0, 0x0, 0x0)
r0 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0206923, &(0x7f00000001c0))
ioctl$FIONREAD(r0, 0x8040691a, &(0x7f00000001c0))


open(&(0x7f0000000140)='./file0\x00', 0xf8e, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r0)
poll(0x0, 0x0, 0x101)
execve(0x0, 0x0, 0x0)


open$dir(&(0x7f0000000040)='./file0\x00', 0x300, 0x0)
ktrace(&(0x7f0000000300)='./file0\x00', 0x4, 0x530, 0x0)
pipe(&(0x7f0000000080)={<r0=>0xffffffffffffffff})
r1 = open(&(0x7f0000000340)='./file0\x00', 0x0, 0x0)
readv(r0, &(0x7f00000000c0)=[{&(0x7f0000000100)=""/115, 0x73}], 0x1)
dup2(r1, r0)
execve(0x0, 0x0, 0x0)


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106978, &(0x7f0000000040))


bind$unix(0xffffffffffffffff, &(0x7f0000000040)=@abs={0x0, 0x0, 0x3}, 0x8)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
pipe(&(0x7f00000001c0)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
openat(0xffffffffffffffff, 0x0, 0x0, 0x0)
poll(&(0x7f0000000040)=[{r2, 0x40}, {r2}, {r2}], 0x3, 0x3ff)
close(r1)
r3 = open$dir(&(0x7f0000000080)='./file0\x00', 0x402, 0x0)
writev(r3, &(0x7f0000000800)=[{&(0x7f0000000400)='S', 0x1}], 0x1)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, r0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
clock_settime(0x100000000000000, &(0x7f0000000040))


seteuid(0xffffffffffffffff)
sysctl$net_inet6_ip6(&(0x7f0000000000)={0x4, 0x18, 0x29, 0x36}, 0x4, 0x0, 0x0, 0x0, 0x0)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x50}, 0x2, 0x0, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_INFO(r0, 0xc0205609, &(0x7f00000000c0)={0x0, 0x0, 0x0})


mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000001240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlink(&(0x7f0000000ac0)='./file0\x00', &(0x7f0000000e40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000f40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000300)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000200)='./file0\x00')
shmat(0x0, &(0x7f0000ffa000/0x3000)=nil, 0x2000)
rename(&(0x7f0000001140)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000001540)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlink(&(0x7f0000000280)='./file0\x00', &(0x7f0000001440)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f00000007c0)='./file0\x00', &(0x7f0000001040)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
ktrace(&(0x7f0000000000)='./bus\x00', 0x2, 0x0, 0xffffffffffffffff)
mkdir(0x0, 0x0)
chmod(0x0, 0x3a)
chown(&(0x7f0000000040)='./file1\x00', 0x0, 0x0)
chmod(0x0, 0x13)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, 0xffffffffffffffff, 0x0)
linkat(0xffffffffffffffff, &(0x7f0000000440)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0xffffffffffffffff, &(0x7f0000000800)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x4)
kqueue()
sysctl$vm(&(0x7f0000000000)={0x4, 0x1}, 0x3, &(0x7f0000000040)="c06d154be3aee5f8787f8b9cda7554335b763bb5deea5ccecb4d1b57a9f6fa18e47fc7b119db587e58811e666e84a806495b45c36164bd5b135280243ed0a01466056e93082876ba33ee8cf2b0b3907f236f38175101000000d7e39544aea098d19ee63d03cbf92380dbe904538135f09e408bbe17a54a364b04ee64b0ad54e6d4e38114ced38c328aff2e224239ba29eb0796e8c3e8344a2cd9e663bb21035ebf391872f3015c164556e4a5b966122c56edd85fc996f12fa1b92e47aa", 0x0, 0x0, 0xfffffffffffffd74)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x10000, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0xd, 0x0)
minherit(&(0x7f0000ff4000/0x4000)=nil, 0x4000, 0x0)
setreuid(0x0, 0xee01)
mkdir(&(0x7f0000000100)='./file0\x00', 0x184)
rename(&(0x7f00000003c0)='./file1\x00', 0x0)


r0 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000080)={0x0, 0x7, 0x0, 0xfffffffc, "92ba517131756eb31ae6a3b564cdb5c06ace4978"})
ioctl$TIOCSTAT(r0, 0x20007465, 0x0)


mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x6000, 0x33c81182)
r0 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000080)={0x7, 0x40, 0x10001, 0x5, "a531d4f1228e14e7a29853ab9f88ea52708dab38", 0xe70, 0x8})
r1 = syz_open_pts()
close(r1)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0x27ff8, 0x0, 0x1000081, 0x5773c545, "102609307e7be2df67de208c8bda612c3100"})
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
mknod(&(0x7f0000000200)='./file0\x00', 0x2000, 0x0)
setreuid(0xffffffffffffffff, 0x0)
setreuid(0xee00, 0x0)
lstat(&(0x7f0000000140)='./file0\x00', &(0x7f00000016c0))
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, &(0x7f00000002c0)={&(0x7f0000000240)='./file0\x00', 0x0, &(0x7f0000000280)='./file0\x00', 0x8})
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x40000802)
r3 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSETD(r3, 0x8004741b, &(0x7f0000000140)=0x7e10a2f)
r4 = openat$speaker(0xffffffffffffff9c, &(0x7f00000006c0), 0x1, 0x0)
writev(r4, &(0x7f0000000000)=[{0x0}], 0x1)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000340))
r5 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x100, 0x0)
ioctl$VNDIOCCLR(r5, 0x80384601, &(0x7f0000000100)={&(0x7f0000000080)='./file0\x00', 0x0, &(0x7f00000000c0)='./file0\x00', 0x8})


r0 = open(&(0x7f0000000280)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000028000/0x4000)=nil, 0x4000, 0x1, 0x10, r0, 0x0)


r0 = semget$private(0x0, 0x3, 0x10)
semop(r0, &(0x7f0000000040)=[{0x2, 0x7a}], 0x1)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x6000, 0x202)
mknod(&(0x7f0000000200)='./bus\x00', 0x2000, 0x203)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x0, &(0x7f0000000240)})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000140)={0x0, &(0x7f0000000240)})
r2 = socket(0x1, 0x2, 0x0)
ioctl$KDGETLED(0xffffffffffffffff, 0x40044b41, 0x0)
ioctl$FIONREAD(r2, 0xc0106924, &(0x7f00000001c0))
fcntl$getown(0xffffffffffffffff, 0x5)
r3 = kqueue()
kevent(r3, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
fchdir(r2)
socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, &(0x7f00000001c0))
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
openat$zero(0xffffffffffffff9c, &(0x7f0000000280), 0x80, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0x3, 0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
r4 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r4, 0x8020690e, &(0x7f00000001c0))


r0 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = kqueue()
kevent(r2, &(0x7f0000000100), 0x101, &(0x7f0000000180), 0x6, 0x0)
ioctl$FIONREAD(r0, 0x80206910, &(0x7f00000001c0))


setrlimit(0x0, 0x0)
syz_open_pts()
close(0xffffffffffffffff)
msgctl$IPC_SET(0x0, 0x1, 0x0)
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f0000000080), &(0x7f0000000000)=0xfffffffffffffe22)
r1 = socket$inet(0x2, 0x2, 0x0)
getsockopt$inet_opts(r1, 0x0, 0x17, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x800000018, 0x2, 0x0)
bind$unix(r2, &(0x7f0000000080)=@abs={0x0, 0x7}, 0x1c)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000006c0), 0x1, 0x0)
writev(r0, &(0x7f0000000180)=[{&(0x7f0000000600)="b8502e", 0x3}, {&(0x7f0000001700)='.N', 0x2}], 0x2)
execve(0x0, 0x0, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x0, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x412dff)
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, &(0x7f0000000440)={&(0x7f0000000280)='./bus\x00', 0x1000, &(0x7f00000002c0)='./bus\x00', 0x6})
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000080)='./file0\x00', 0x0, 0x0, r0)
r1 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
preadv(r1, &(0x7f0000000300)=[{&(0x7f00000000c0)=""/104}, {&(0x7f0000000140)=""/192}, {&(0x7f0000000340)=""/175}, {&(0x7f0000000000)=""/18}], 0x10000000000002b8, 0x0)


mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x0)
sysctl$net_inet6_icmp6(0x0, 0x0, 0x0, 0x0, &(0x7f0000000140), 0x0)
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x8020697a, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_open_pts()
syz_emit_ethernet(0x3e, 0x0)
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x800000018, 0x3, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, 0x0, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmsg(r0, &(0x7f0000000280)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000300)=ANY=[@ANYBLOB="11"], 0x11}, 0x0)
open(0x0, 0x0, 0x0)


sysctl$vm(&(0x7f0000000100)={0x2, 0x7}, 0x2, &(0x7f0000000040)="ed161c14", &(0x7f0000000080)=0x4, &(0x7f00000001c0), 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r0, 0x80206949, &(0x7f00000001c0))
socketpair$unix(0x1, 0x0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
r2 = dup(r1)
r3 = accept$unix(r2, 0x0, &(0x7f00000001c0))
getsockname$unix(r3, &(0x7f0000000100)=@abs, &(0x7f0000000140)=0x8)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x80}, {0x50}, {0x6, 0x5}]})
r4 = open(&(0x7f0000000300)='.\x00', 0x0, 0x0)
preadv(r4, &(0x7f00000001c0)=[{0x0}], 0x1, 0xffffffff80000000)
r5 = socket(0x18, 0x2, 0x0)
close(r5)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x1ff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r6 = socket(0x18, 0x1, 0x0)
close(r6)
socket(0x18, 0x3, 0x0)
connect$unix(r6, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
connect$unix(r5, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


socket(0x2, 0x3, 0x0)
open(&(0x7f0000000180)='./file0\x00', 0x75f493fec6515f78, 0x0)
r0 = getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r0})
pipe(&(0x7f00000001c0)={<r1=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r1, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r2 = fcntl$getown(r1, 0x5)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0xb32, r2)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
pipe(&(0x7f0000000000))
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040))
select(0x40, &(0x7f0000000040), 0x0, &(0x7f00000000c0), &(0x7f0000000100))


r0 = socket(0x18, 0x1, 0x0)
socket(0x0, 0x0, 0x0)
getsockopt(r0, 0x29, 0xb, 0x0, 0x0)


mknod(&(0x7f0000000000)='./bus\x00', 0x3a0914c44f7b202d, 0x504)
r0 = open(&(0x7f0000000040)='./bus\x00', 0x0, 0x0)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000080)=0x7)


socketpair$unix(0x1, 0x2, 0x0, 0x0)
recvmsg(0xffffffffffffffff, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
recvmsg(0xffffffffffffffff, 0x0, 0x0)
socket(0x2, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
mlock(&(0x7f0000ffc000/0x3000)=nil, 0x3000)
sendmmsg(0xffffffffffffffff, &(0x7f0000000180)={&(0x7f0000000140)={&(0x7f0000000000)=@un=@abs={0x0, 0x0, 0x0}, 0x8, &(0x7f00000000c0), 0x0, 0x0}}, 0x10, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


kevent(0xffffffffffffffff, &(0x7f0000000040)=[{{}, 0x0, 0x0, 0x0, 0x2}], 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x2, 0x0, 0x1e}, 0x5, &(0x7f0000000080)="e33745e84d5ebfb9cc2f7fa3a7f7891721720e69dac610a4fb5eaf3e3c6e1d648a8ca6ebc70f949c442aee9dc79e2cd74f4e1092a2aeba2fbbe28c42903bbf6c161c6f382caf01ada3bc4efb0f6bc50690e5d879fac2492f4a0491b1ea3359aa5c5164ad97ac7c3aaddd498c0f962f5167b69cfdc8287fc34b8138340e60c404a855a58ea5fca343265bc1ed6bd51cd0eef26db847abb2e7b21442c0", &(0x7f0000000000)=0x1e, 0x0, 0xfffffdfd)


r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x41, &(0x7f0000000040)="04000000", 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000900)={0x3, &(0x7f0000000040)=[{0x14}, {0x14}, {0x6}]})
syz_emit_ethernet(0x103e, &(0x7f0000001980)=ANY=[])


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{}, {0x7, 0x0, 0x81}, {0xffff, 0x0, 0xfd}]})
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


ioctl$TIOCCONS(0xffffffffffffffff, 0x80047462, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000000640)=ANY=[@ANYBLOB="c19648fbbc4c261c7d7c88d008004a1000280000000000009078000000000000000d0144100903000000007f00000100000000000000"])
open(&(0x7f0000000300)='.\x00', 0x0, 0x0)
pipe2(0x0, 0x4)
r0 = open$dir(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
mkdirat(r0, &(0x7f0000000340)='./file0\x00', 0x1a)
open(&(0x7f0000000040)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//../file0\x00', 0x0, 0x0)
r1 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])
openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
ioctl$FIONREAD(0xffffffffffffffff, 0x800c745b, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, 0x0)
sysctl$kern(0x0, 0x0, &(0x7f00000002c0)="9336932503a6874c767ba2e4d26007d11eb4bb37ba116711048fa5be4d5a5b638336d87023ed85a1215ddb1292519b", &(0x7f0000000100)=0x2f, &(0x7f0000000380)="f1a38a5ee848d8d67fc1e5febd4292d62fd2841dd14722239e5093859645116ade6ab14e3eca8da8317344905104dd36809862f5a1c0824f7fa0a07f554779a7f16ea59824df97b26e7891fccc2b", 0x4e)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
socket(0x6, 0x2, 0x6)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000080))
dup2(0xffffffffffffffff, 0xffffffffffffffff)
fcntl$setstatus(r1, 0x4, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
mknod(&(0x7f0000000000)='./bus\x00', 0x3a0914c44f7b202d, 0x504)
open(&(0x7f00000002c0)='./bus\x00', 0x0, 0x0)
execve(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x9})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)
dup2(r0, r1)
readv(r1, &(0x7f0000000400)=[{&(0x7f0000001780)=""/4096, 0x1000}], 0x1)
readv(r1, &(0x7f0000000040)=[{&(0x7f0000002780)=""/4096, 0x1000}], 0x1)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
chdir(&(0x7f0000000240)='./file0\x00')
mkdir(&(0x7f00000001c0)='./file1\x00', 0x0)
syz_emit_ethernet(0x66, &(0x7f0000000000)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa86dd6036e28200303b0000000000000000000000000000ff020000000000000000000000000001"])
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000540)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000140)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000080)=0xc)
chown(&(0x7f0000000040)='./file1\x00', 0x0, r1)
chmod(&(0x7f00000000c0)='./file1\x00', 0x13)
setreuid(0x0, 0xee01)
mkdir(&(0x7f0000000100)='./file0\x00', 0x184)
r2 = socket$inet(0x2, 0x3, 0x2)
r3 = socket(0x18, 0x2, 0x0)
setsockopt(r3, 0x1000000000029, 0x9, &(0x7f0000000140)="03000000", 0x4)
r4 = dup(r3)
setsockopt(r4, 0x1000000000029, 0xb, &(0x7f0000000080), 0x4)
sendmsg(r4, &(0x7f0000001740)={&(0x7f00000002c0)=@un=@file={0x0, './file0\x00'}, 0xa, &(0x7f0000001580)=[{&(0x7f0000000300)="150547320827093c2e0311f472c94d0efc371606ea4f9eaec5fd820ef365b43acd0a9ac53d37521a35e7a003875438729e8e987fc8605a04d7e059d18d717b6a2fcebea03d6a49ea9709771f94f8c8055cd112770b2f38ebe5ab24f9e8d4da", 0x5f}, {&(0x7f0000000440)="4fd70be3f2f3260c8480534bdfa4e4cd220d69a6049eba17e9b49d3e90b6219bfc575205f3ef9be62598eb669737c520f462ec208dc88e2ad8d8d7acd1ba685d1878f1", 0x43}, {&(0x7f0000000380)="a48387759b92021c0ff6f4ed8552b0e3", 0x10}, {&(0x7f00000004c0)="088612897373ab76613b2fe3126da2a55ec0953d47c73942ff2f588109a8177b53e1b4f64d4b0a3c18624ceae0bdabc166", 0x31}, {&(0x7f0000000580)="ed5e7553ff5e6973cd187531d0602de149ffc55760034de2d0c53fdd2d14be584f48f41e95d46fefa9c6c54a90d39bf599e80951dad56d58ba6638931ce1869ab7b74f885050b3c565e09270933ff458473511bf32cc7fd5cf0fb4f6b2f36c51a4734140e4d7c00f486d67300c853a683dc1a458b5ec840bae028df2088773320026d4826b9081c85ada70d015e7ffed27e84da8895503ac540af36a41b216fa0169ea28d0903ab67d18ffaa7a16a627e6aacee1d20086d28d6fe832d4f95b23a7cc80ab26504e23a6edfebaf8188d3aa0f60a916e2d3144baca37a01a83895be5dd9568d2fcd9417f997c8fe37b1a43947fc370bbb7bc141533e24dd8e83f83ec7f1685041747dcb4f270a2d627491dcee1310db20a4256925f29eb6e2522936c6b7b098967c735155e242115f37a9364011d4e1fe094ed68229b88197335db8bf2023b7c4566602cfce3d27ba6cf7330ef15b603b36b8367132f91631b1fbb3695f8435d986708be67c3e96dd4c6cb66aaba73490be0fd3e4b7e5ba3d5d3486575d8ab43048a32d0ac849be56e3bae000ac099bfa3e39bfd417a74586920718bb581cc71eaaf08843564c4f8b32d802acf288b653bd9244e868f1e3e72dfab83b7bc45ed013971b83894e21aa9d4f2d6ea1c57b609434149b2717f0d43f7311e6e1817fa1431d0fed1b4eb3e58143f7d81daedbad8f0c8dd65be157a49135208b474255cdb4585a33f0bbb2585baf9ec49978f7640f85881377ae53e692a652cc5d61e9304bb262e4391317281ae950718e1dd44b84bd9a3b70383e1ab30c15a9e441d7e78619e957f9eef6acd6a8227952e1a9dc82f471dd8bd4a17cfcdbdd1a64215156c26399bdc4400f290fc69bbfbed5946aa7a38cefe44f1fd2c2c16145bc84f47b9fa8ac303960f2f3eca6c316ec6b280b15d45990840a17d6c08f2654f9211e97368497c8fb10db34cc267a79c75b399f1c07e17382c16b76505d1f36b0f0c62264b2292b6b79ba478db1d6d28107232710ce774452b9d698edbd418aa6c88e737d19d1bba8286660d311f196c17a26cfec086daf13cf69e545315a968a9ab7df58f6de0dd0f382c2170f9fcd7964626e3aed2f58c71e0b580a861c66cf4bde0c4639e467ff272fecba3ca5c3757454cc54976f165e4abb5fbdd93739c80b4da1dfacb732047e6fffceec5411d0effd53b8d76d178cd76d8a95156013d1a3331e5a4e3398e7a947160ed9b9f02b4f41f58c3b998c4c8b325142469d4370576c00edf9096f21f5ae478bf901732aae830dca662ad5e8caf836419565f33aa43f7e7118a417ddbbb474cdf39e27b0695c554f6d05cac201528d308f9fd9fe0d24c01fa7fe5da2299ea7e316c7baede59174323896d10125a7077c1409245d35477bca4dc94f9e1100ba53cdbded9432c2bcbd3cfdf952edaf0877fbdd59b38888d1c0745bb3eb535aacbd47de5d1f30ee6571addf470fc4eab0ccdf4b1b91c83475f55660b896e8c8989737e4ce2c4abc62305ad50b8feffb6f6fcc238744e52597d954748a5512204c93b5b144d893b8ccae6d8303135c230124ef679b5436bdb1ac030b5dd34f2fb92a33da099cd91732a3e261bb374b9fd9bc61961752148f9db7ef1fc29f63b35d3a92b81b6154a2f0ce783489a7601051539192e5c502861917a3ce24b4ef67dede640eb8e4d480b272e2f62ffc7f38b140ab0df24901c02eb8d91ada0ac12a5253cc4f5eaf8267cc739c87d2acb20c5169445c744fd261212cde68d041f41993be4f2af59f85305d4013de5d49a5e7d1498a12b71eb2d9f9414505e90a3e227b3ee265a4a4fd17a4d9a1e7ee7556c9aaf9dc7e9f5dd56343179ac94ab0ba0c686293a1dc22c4ff45447c9ac3626d81a655e8c28b96aace298c12167d33f650de715162e4f17bb501a047038859bef7658dfe5c3bef807301c38c7b5406a61e4a10c4bcd0ffb6a4f89edb5bc27bdea73a4f469aa9556ae55d7c884a50d257284a1662251b8ba6d0d42526f57e0d5ab3712671dc8026bef682ad75ba38f8175fef4da7a373d5b2564ee084cb4afc2269fce44e87e06c17f2db00a67bedd94385378b0a9b39419b074c5a526567654d227ca8e11fbfb61b9345c57d0bb9d85b09885a7ac78722d2e03b8757b4519b4a2a5b2914325599cf03b175f43bac08fe1ab5c4d7a1c3207b082956471fc7fa5cbb52fadebc63a1c9bd274cc80f9a0813feacc1b1975c84ef59a57bae7bca6067c1887c7bb80f016a30b9831dcc28d47327d57413c666ce59677b667a0b795ae30ec8ca5eab167d8a4d7585fbfafeeba45bb4bd5c4b6b7ccde5e4af92d37b18f166db196bd05ea9343c9a4f0f93f2bb44774e723404c6f401dd15b84193da40ddb6880649f979f0a14eba38a9a14a802d975736e7c6a523df8ba4f02088cd852b1884cea54307ba93740241fbe29e9a2beb8420ce4814c9734a96bd6251a329692d41a92111ed4dc138bf3b7a14f4cb189a6d1f60fc7104590c51cdf9f6b319e8bc5d29fd608c89b8ebf7df457c6931031908cf37dd173a1a8176946c14382b31bf6b50d2d9fad4e099c10271112a9924bf0f2f3a2d5bf6198620c3d4aabc4c147567f12e35e73ef6008683e47ebdce79fb7fc79761479441b780cd616b05decc44616f96dae519a852a8c06c6315a78d5e3dbb2ff34003953f27276dda7045a55f45913bfba940e0110d7f78ed94352559c97ecb37f31398797116e9c2f6603cfadd2734cfab61b23b6937debed7c091ac37d9692efae5b5b2fef13c220af9879315458323a63596e14f316b749f73a36529498b8642be5f8c12edadce5e7d41662adacb77ad8faed0c72f07c3340a51a343b3de3c9d941ea56dd620e8224f8e99b0deebf123300adbb9d77822feca79c7fa04dd71464eeff7dc8caa90789b9b0ffd474728492f3cf5822d1049fd7bb0793a65fc0c1b85dc3cf41367d88667bb9167f03ee9d367996f4b9ddf8e7307559ccfe2c8a558ba2f2197de383619f7f8d5249409fd0b16a7f32d75091d7403f98209391169fb5011c1b8ffd0245d6262d0490c6793a509c0cc8bff36f7e2844452210728987088aa859cabeb434dfbf6adc64526da395d54520c8ee302a77988126ee0ed9b8df4d93d91e3334819bacf6a6686848fac85333b38eaec2b1daf554c407190eea0741b8b90e204e69d80da8e8e8519da3f76eaf9db12719079a2f48fd85edf826baf6cc48908c2d20401c0e9b98dad483d3ee2c8de07877b785fe6e5c0a8a5811502bbbfcbda5045b829d2fe96af47d52bd9b2f239d86f393aa4772f20bb9f5bf1cc79c3b2f48ec3735698f2225b77e949ecbe8b687e385ca39ef218a0c8fcbffe3c73eb3d359482a85bc3b2b6cd43453f01a61700dd5aa1672d1101946c71212725981e9799993138b5b354d2ec130c3eebf9d2c42a10facd8221720f7339c389be8fe18050a9e343f709ac534f3d1fc766992119712aa911c7f776756da67e6e8b14e52f7de9e8d163bdf98205bbd2b53657720dfe4648ff97090d159689c49331b46a5296c56c70c30e9add7c7d3a3f809518fb09cf991bb2daa3fd49cd1cfdd7f06c00b4d57800b69dd1a71d2e7af41ddac5fc57c79a92a5be08c322bca83de2e1d1ca1a3992750fe30c3b43cc5bb6bbe3fae1375eefc95b8f0c3812258a937b65c5dfd7a6cdb67c0aa1f9fc234ceb90ad30f2bac7b2cdc509ecb5f098157d68821c6199666aac3228b2f78cca1fe009082db2b558934d2223bdb7843e89941ef982a3ab7dd33d022d0e58db94ca50541b2a4ba7e386ace92efdcacee82e920b18fdf63c029752791399624e6d1d3b132dcb8f6fef1cfa9993d98f1bf485d9f69820ff41a744a10a9d1c1a8f5ab195168e426a289b6dfcdaf5c722936fb722c7080071de22a3bb527752198d2a2ece53fe3069898eb7e0b5152fa20604edc2da1621c4e64d1d950250a0e92423f66a522a0ceae3c78ce188c90cb294b8ac7fcd5b7ca93fafe1556200148f47b2592d711e1abca6354741ca4c338dcc326cdfd23774dcf61dfc6093da0d9151ec55018e6530e841781060bafbe300d98e9eec48652649b58cdbc49ebec36a5338c54450315023f904deba9317e95bad1ddf12abb8d40812fb00bd2010ba5d0f695a634701336b02d4a877b4315dc9f8378696ca27ce2eca7b56ed45eb515942a8320b5096816c2e88b6264491c4525f0e6b49bf0e5b0123e28778be5c5a96d2612397700d98fe59e31e61b21c21788ba081d72d2515ec0359c413b02fc8a3359f9e932ca9cc3a82d8e025ecd486d54340b3dd5e458e91037cd2aefa51787edf15dc545bfb2fa2ff8f5ed58c78d61e9fa292818f37497ad4dca8f0af825b027e676de2c74f597aff889f786e7f25bb090c459ae1eb70a18202b60a406519bffb0661fd64fb327eac9f39af3b47c7575e6eea2cf1ea75f5cdc978d70e8c92f02f5472bcc70e518e01502f71729771e6170b76b82621fb6a5d8b89deadaf533d27f8d49af696aa0b66f2c46c3c3c58dc8299fcc5c91ce11b01d09b1482562b49fd351317340b1a78e68d492bf7229141e15825aa9d6d082ad28934e85f0799511c7eee7441ecc10059b73fa99c7c03eec55bf5329102b1346c2d20108ec0650d0d55f0d5e25760cdcf8a06bd42adfa979b6431a9bc1a9ff83d1a3b69497636c532608bc6fb19d4ee7010776c42c3e0846364efc2ec7cfa715a34306972a88355694137a90fd191620642d973e676a4ee62259a24ead7c137ad9333e1ffb088a2d537daa98922450a3039f36b2f70071fb4e8c93c1396c018cbba244c0fec30fb7b54d93c56fed569bd4aab01a00b4f37a8dbc4400843b7812de2a581819726b9987028e7c640eea1af94dd441ad12d1f6f84c8a6d27b7390295353683649ddbac8d79b7b3b0a05229322315600756704c88c115b8c6a44d005c241d7daca9cf48aa6ac85dbfd90f12fa133d8004853366efb819a2d25e4d40b6a646fca56d913482fcf4c43c46db41914a4d441dc9a5d3493eccafdb0763b3926775ca893f73d4fcd7f82303d86be80e340800b0dd895c3adaa3ad5562af8d1079925c89d6ab2e586fc6fd0757b445478a5e275a4211ef5eb2864de15bd94cbda568993bf29ea8e00c8b6deb70244009dc920b67685dbe3990528ff17b3588712e8fdcc97eee635914d15273339bfa81a9fb0b4d5fac09e0dd668739079ba46563b4a83fb1dbd9f06be9b9f51bea709cd6b03f0a7423fb5ee0b0ac346f270b455af1db934812825d1823da204ea203f62f29ea00da13c19a3049d65a0ffc2fc0bf94fd2a36586594b38e869dde856202543b47f5ca0a3fff16ed2b7d767ee8cb98fe17763757b2f33968820d7315bd6cfc6a09c13235bbd44f5986924df6f84a429372a7d26878257bb10c618396cb872427e7f39d5e89575681cff38585947c5db9f87945ef504b211ec17965684b000b125a1cc7c201eeab98d7281b9e761749924b2daa13e74f6c10abc4ee37d2ec28799278e46b55ebfaa74d16eaf3f5e4bf702a6fd3bc83c6f500042c4063378fe8f3bb1ad2c424b2564399221b493f3d8740269483b6411c5b6e63a05027ffd1fca11c138d97fe3293ba96350995c4a4dbf6ab4895a27678097943d185132bab7c0ce9dc0544610ef0d95c4622db5ea63af028ae0f92c80f2ef5b8c3b1aad0d971d995b11db1e621d8b412c116f1648c5b6c55b9606492428e93513a68907835a0daab2a472e50ff7ea68f3a4775aaf2a280cfa79cdfc3348b", 0x1000}, {&(0x7f0000000500)="e577291c5fa39ac8171ef13a3a3378b0ae83f2efa5a2d391c2e509f320b440a8039880a8bade", 0x26}], 0x6, &(0x7f0000001600)=[{0x30, 0x0, 0x6, "c7a51ef24707b8c7aefc45fde36fd51e045c2fc1648eb014d37e5c261b1cec"}, {0x100, 0xffff, 0x1, "b9672de31dab2582d3022aecc02107f830f65d69a35566dccd74b022447c91c5001c9379534bf0d66090c99cae9a68a67214f3a2a84fbe7a9de5a43995dc0eb235770bbd01a507594a9fa037e75d14a553db07cb986abf060d845a3a58d567ca689e75df434d90e11d5c07a1463e875a1973a675b52fc05f550f338e1a19468df6a2520b91aa2dac878d3a3d9a77c9dd5cc372f33ac7c16173d6d2277b6ef43dc98b682258c6dedd4a6cda1c8c81aaba5e79f37e615d19221438e8b15dcdd1217db3a5c8c0d056351085462bec979e9b02e51fe04b32b627ec6419a6d254f6d55f9f1871e7d1643584111b5d"}], 0x130}, 0x3)
recvfrom$inet(r3, &(0x7f0000001780)=""/216, 0xd8, 0x40, &(0x7f0000001880)={0x2, 0x1}, 0xc)
r5 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(r5, &(0x7f00000001c0)=[{&(0x7f0000000180)="b16eb2717f42aff12668150f150612", 0xf}], 0x1)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x4}, 0x4, &(0x7f0000000040)="bb703057", &(0x7f0000000080)=0x4, 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x1, 0x10, r5, 0x0)
mknodat(r5, &(0x7f0000000200)='./file0\x00', 0x40, 0x1)
setsockopt$inet_opts(r2, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
setsockopt(r2, 0x0, 0x69, 0x0, 0x0)
rename(&(0x7f00000003c0)='./file1\x00', &(0x7f0000000400)='./file0\x00')
openat$vmm(0xffffffffffffff9c, &(0x7f0000000180), 0x200, 0x0)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f0000000100)={0x10, 0x0, [{&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000626000/0x2000)=nil, &(0x7f000093c000/0x2000)=nil}, {&(0x7f0000da9000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000e0a000/0x2000)=nil, &(0x7f0000c17000/0x3000)=nil}, {&(0x7f0000b64000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f000062b000/0xf000)=nil, &(0x7f00008bf000/0x1000)=nil}, {&(0x7f00008bf000/0x3000)=nil, &(0x7f0000af4000/0x13000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000601000/0x3000)=nil, &(0x7f0000b08000/0x1000)=nil}, {&(0x7f000064c000/0x2000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {&(0x7f0000633000/0x3000)=nil, &(0x7f0000518000/0x3000)=nil}], './file1\x00'})
r0 = socket(0x1, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0xc0286988, &(0x7f00000001c0))


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f00001a9000/0x2000)=nil, &(0x7f00001bf000/0x3000)=nil}, {&(0x7f000018e000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f000078b000/0x3000)=nil, &(0x7f0000093000/0x1000)=nil}, {&(0x7f0000334000/0x1000)=nil, &(0x7f000008a000/0x3000)=nil}, {&(0x7f0000066000/0x1000)=nil, &(0x7f0000133000/0x1000)=nil}, {&(0x7f000008a000/0x4000)=nil, &(0x7f000013e000/0x2000)=nil}, {&(0x7f0000323000/0x4000)=nil, &(0x7f000002a000/0x3000)=nil}, {&(0x7f000008d000/0x4000)=nil, &(0x7f0000089000/0x4000)=nil, 0x80000000}, {&(0x7f000056d000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil}, {&(0x7f0000136000/0x1000)=nil, &(0x7f0000027000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f00005c8000/0x1000)=nil, &(0x7f0000ffa000/0x4000)=nil}, {0x0, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000249000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000100000/0x5000)=nil, &(0x7f0000092000/0x3000)=nil}], './file0\x00'})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, &(0x7f00000000c0)=0x2, 0x4)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$VMM_IOC_INFO(r0, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
writev(r0, &(0x7f00000002c0)=[{&(0x7f00000004c0)='L5', 0x2}], 0x1)


semget$private(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000004c0)=[{0x30}, {0x3d}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[@ANYRES64=0x0, @ANYBLOB, @ANYRESDEC, @ANYBLOB, @ANYRES8=r0])
poll(0x0, 0x0, 0x101)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
setregid(0xffffffffffffffff, 0x0)


mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
chroot(&(0x7f0000000300)='./file0/file0\x00')
unveil(&(0x7f0000000040)='./file0/file0/../file0\x00', &(0x7f00000000c0)='x\x00')
open$dir(&(0x7f0000000100)='./file0/file0/..\x00', 0xb26102061c041bb9, 0x0)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000000)={0x0, 0x0, 0x80000})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
r1 = socket(0x18, 0x1, 0x0)
dup2(r0, r1)
setsockopt(r1, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000100)=[{0x40}, {0x3c, 0x4}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f00000001c0)=ANY=[])
kevent(0xffffffffffffffff, &(0x7f0000000000)=[{{}, 0xfffffffffffffff9, 0x19}], 0x0, 0x0, 0x0, 0x0)
r1 = socket(0x10, 0x4, 0x4)
r2 = kqueue()
kevent(0xffffffffffffffff, &(0x7f0000000180)=[{{}, 0xfffffffffffffff9, 0x5, 0x10}], 0x0, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f00000003c0)=[{{r2}, 0xffffffffffffffff}, {{r1}, 0xfffffffffffffffc, 0x80, 0x4, 0x1, 0xfffffffffffffff7}, {{r0}, 0xfffffffffffffffa, 0x8, 0x80000002, 0x9}, {{r1}, 0xfffffffffffffffa, 0x88, 0x1, 0x8000000000000001, 0x6}, {{r2}, 0xfffffffffffffffa, 0x2, 0x4, 0x7f, 0x20}], 0x0, 0x0)
socketpair(0x1, 0x5, 0x0, &(0x7f0000000380)={0xffffffffffffffff, <r3=>0xffffffffffffffff})
connect$unix(r3, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x6d4)
mknod(&(0x7f0000000200)='./bus/file0\x00', 0xc000, 0x81)
r4 = open(&(0x7f0000000100)='./file0\x00', 0x8, 0x140)
ktrace(&(0x7f0000000280)='./bus\x00', 0x0, 0x40000200, 0xffffffffffffffff)
r5 = socket(0x2, 0x400000000002, 0x0)
setsockopt(r5, 0x0, 0x21, &(0x7f0000000180)='\x00\x00\x00\x00', 0x4)
open(&(0x7f0000000040)='./bus\x00', 0x800, 0x0)
ioctl$TIOCSETD(r4, 0x8004741b, &(0x7f0000000140)=0x7)
r6 = socket$unix(0x1, 0x1, 0x0)
connect$unix(r6, &(0x7f00000000c0)=@file={0x0, './bus/file0\x00'}, 0xe)
socket(0x11, 0x3, 0x0)
r7 = semget$private(0x0, 0x7, 0x3c0)
semop(r7, &(0x7f0000000100)=[{}, {0x3, 0x3ff, 0x1800}, {0x2}, {0x2, 0x201}], 0x4)
semctl$GETPID(r7, 0x3, 0x4, &(0x7f0000000200))
semop(r7, &(0x7f0000000200), 0x0)
r8 = semget$private(0x0, 0x0, 0x104)
semctl$IPC_SET(r8, 0x0, 0x1, &(0x7f00000005c0)={{0x8005, 0x0, 0xffffffffffffffff, 0x0, 0xffffffffffffffff, 0x40}, 0x0, 0x5, 0xffffffffffffffba})
semop(r7, &(0x7f0000000280)=[{0x4, 0x1}, {0x2, 0x8400, 0x1000}, {0x1, 0x4, 0x400}, {0x3, 0x8, 0x1000}, {0x3, 0x4, 0x800}], 0x5)


sysctl$vm_swapencrypt(&(0x7f0000002700)={0x7, 0x2, 0x1}, 0x3, &(0x7f0000000100), 0x0, 0x0, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
fcntl$dupfd(r0, 0x0, r1)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f00000002c0)={0x3, &(0x7f0000001080)=[{0x2d, 0x0, 0x0, 0x81}, {0x87, 0x0, 0x6}, {0x6, 0x0, 0x2}]})
write(r2, &(0x7f0000000200)="b1c05b5fb165120a4224a763037a", 0xe)


r0 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r0, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
setsockopt(r0, 0x0, 0x6d, 0x0, 0x0)


r0 = socket(0x18, 0x1, 0x0)
listen(r0, 0x0)
accept$unix(r0, 0x0, 0x0)
shutdown(r0, 0x0)
execve(0x0, 0x0, 0x0)
accept$unix(0xffffffffffffffff, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000040)={0x0, 0xffffffff, 0x80000001, 0x60451d, "1a0c0109020400"})
writev(r0, &(0x7f0000000080)=[{&(0x7f00000000c0)="f2d98d803406fd3f3ae5de618b17e9c1863bd9118a145f9927f34224a70b765f5806ae62f1ceb57a7b93f96e8e8dc14b12f84c4831d1d73185fab7287794eeabb85c67aecbdc7e3b26d4e0960bf6856696a6b425ecd390f200df7bf5c8130233405cd8380398effd73af2948c02fc62f8a9361f8b7e8e0ae77a11789fac5b770be9346f42a68b0c6c8968e1168dacf63730a99da1e9a73951895db801b8504", 0x9f}], 0x1)


sysctl$hw(&(0x7f0000000040)={0x6, 0x17}, 0x2, &(0x7f00000001c0), 0x0, 0x0, 0x0)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
chmod(&(0x7f0000000080)='./file0\x00', 0x40)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000300)='#!', 0x2}], 0x1)
writev(r0, &(0x7f0000000240)=[{&(0x7f0000000280)="a8034e3fdd86480e82b020090000019c0a", 0x11}], 0x1)
execve(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
setsockopt$sock_timeval(r0, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
writev(r0, &(0x7f0000000040)=[{&(0x7f00000001c0)="47717961f890b16b8f740b7d2bd68ebeb02eec8ffc36f59cabd1c25caf2f127010b0df16c23e06fe7b4d20a4f93c6e22c08a7d26ec491b7ff004abf1ee4b752cf073e05996f0728ad21c4e9d9cce8156639c755c783327059f2853c4117b68e35732dac348829d46687a54198365be627c306ad8f1ae4adde82913459fcd1026217a325c65f8381da06d5dcb033ea5b2997a1db4c19e99027549db84c5e81be0ab2a34de3e432b21b1350cfdb0bad618c19b7bd41267d962acdeca14a4a269bdb524b8bab059de759ecd68c5a1920b77668d7bd35ae67741cd2e464913a374c09ab0703c38d7570291f776ed10713afaf7f2e149b39bce1f38933ece1cebe3b60d8932baa2472c8da35743392eeabb3ea6e10b48eda82091f10a583afb014b5708c96e747721878427156fbc43e7adc28dd95a9b1c6a484c1346ef777eadf0de765b6310bdfd6b8f98065022cd90e4bdaffd249051c5b539836ad3be222c142f4d7a77ab0cc93b254fe0d919c26ebf2c3ffe9481aaf81f8dcdc76e6db8490679a3f9400a5bb447962ab490e918e069c06c2ae8700b0cca429c8e83db76dba386fc0f4b0c82b6f540e478c4578465272b9b57264f486c94aeca3f698ddee60bca26554986e07c89e0cbb6e222132f39e80d56b9a645f7dd92b2282b8ff9d806ccbbee8ac5485056203abe0d7d2e290ea517c27f697e3dfe2bdfbd23c3e64e0c379df306c691aaa2b9ac0afb4b711421daba5c40360e0aa9d341b2af18163a8601c7e79f987249c28fa05321f7c2688db0e43a573dc84224de8763331ea85ab58cb4575de6aee9e5745714e4641f433d1325c07d2b8daaa0085d4d9e73aa945d2b2f285f1d21023044ae8fe7fe95b1eac55e3a0974e10166e7f6123d8848d4decfdc1f1456bfb0f79adaed6c68a9266cc603211f2c547633389ad6a57e358d0c5a344d847e617d969c5feb2c20aaf7310622716bc43fa9bb9569383dd5d2ec497f5e761b6fd2e6b2fd291e59ecf39c4888fb902d3b342b59710adffc81ef23565b6240b21e9e7e147d000ff42ece9f8b9f47d8a34b64e253cb6a1542d2654a0abad04ca0bdadaa5faf60ebbbd47ebc66cdd219c8182e6a0d4f98771e9feedad1d7ff7216f18fec7f48a0aa7851aa21b1ec8f43bbfa7eea8b8fbee69d359a3729286054778f141f45b5d6fd514390e355ac7f95a111817d091e0795e2005003f94b9d577b2073ba37445fa186cd5e65d3040d3a704cc54194224f06cae200e109f28ecdae819569868efc66cf8070f5976ca937ba31c107fc0be1ca65eb159a05e3216732dd29c005cc3eebf8730f194abb5859ded64316b71a0633aa4e4cbe277e819a1d788e7ace0b754251ff439119887ef2f7c568f1737fc5988c1136f916ec813b9b88ef7cc184269ac8146158e4c2864ab1be2b69c1b10c83eb6b0a712587af92e42501592238442e6cc7378d76a511f69be929425929efc9799aba8a868d231b9fa994b74bd9067b9932cf27c2df2db8185ce86d7f3171cb3a712ab1ee6dda1908034ad50ac54ecb63cc5fa8dc40eadfbdf6cd124b2473fac137929c1af3a0855c32bc2437b62803e1531572deb3a8dd8e892a1c8d79f70fba9d07e5679aebadd2e39688d1347570fe8c4b8d91ed2de50a77c3b9480ef12f8578db26824cc4061d681aa77b531fc52f842e53ad2aa39f93c087cac96319dc5fa3086d4579e4b776ffd8745b65aaed313f00378386b98b0eff7af562c51db3ca99d32261f5a79349b6755f8c4e6d31003538a2bf1a0ea168f0ff22b45c5acc19fea16eb3190f0ac9123bc105209d38a395633b7848f91b5723cebdef8b7081033fb4810dd41b2c666dd0dc3f824849b66c360312821d5157d4d4ed2955b802fc895625822520e0d6b7dafdeb7f4065fa0810b55035457d656de69da074db919dc9166962ad8c8b9d6ba12cc2ac0f2fce3ff3f869ec0c699e8a9dc974cf2e47a2cf2de749dd26bfce1e75a9652e246f6064beb8d1f6dda6a751cd22188f1a13a699c374b6f241a5751e96086f1e0b4273155b31d201e265179fe624c583e901c67f88289e4b821fbf067abf0f2905a0a9be09db7153b354043c406d97aa6c74d0322109291253670da36801835e2cec343b8f6b8f0b2c62c40abe716a6d19d21c15cf3d85e182417f92b005eff248533f2818ec2a0b73ede00d29f3dc0c534786f0548abaf9e21693e59e9dc865cdc18047d0cd098bc613f1ce5e445c041ad45aec654df094bdb9d9465096724ff081175ee23be80870d19e01209baff7032bd00479353dffc82aa366c608d5e4a34758d5568c0e74a42775c7adfa55b27589c989c97a858c08ac123342e8a37a4bc77a71f6efc777953e1bb78bf4dbd6fa5ee08a15ac25ac10e6aaf126d7e8665a7edf0542a0b4a0d2ff9b4231e22de319cd7905b1752573873f97d3c41ddaee86cb54dbf166db462910a8ea2308380638bf3db0a370755c0086379bc412a10c1b6a001bc0b2f657f75dded05db00f748db164106111b753114acbdfb13ac5893248574b697d6829801501065d796808cfa7f647955d660ec3e9edb982855886fa85868727d7117385f0160edb0062e518985b546a32c3b11e0fca662dea92c9361b09938e2567fe3626a9d96904f3cc1b097fb8cc9555f8123ae3dac326bc4c2fa7c13340f17d361a1f4e7124b6944666a7860c5663612aa00a9446a3ed7d9dfb2cf6008ddcfca3dd5f80e7216b3e5b7c4750d1977915e7576cf6f6b476741b3cf466f14066e26b2a7553908fc74cc3f7f847f56ea54e402c6f6a3c6ff48e3d12e70d6dfe1b6232dc25c9359d38ed0835289a81c33b430206f72e1e9488365c769924fc6974675303a7d805bedca2bb1fc203c49076a437fc6c7c75d9cccf1bb701c6bf42331299b829eab10377bdae8af8c7df7307c8ea48401b7cc66ca26ea97965ff2306b01a63c8262e261930c4facab7a89051e964db92937e0f5e5f8ed24dd3eabff93df013e31a89d89857ab9b5330d9d01307e93fb5b859de58f73b205b3197a5f6a1c8e6f3470dcea0330f93b69715befbeb604dae05ed0eec1b6108e6ee57d960ef273e91d9f28afff2987256185b4d7d70ba5cb7a6d07d93bb2edc94a6330d7f8185b8f66e1792646d77470cf9e0277d66aa96cddb1a9965acef0b50cd9d827d19f268a2371837c5a704c6db71d6e783a86bdeee580c1d40b238d0b09a91718ab2d94121aeba136f5e31bb56243aa98f21773aad99ffdca643fc3affc846654416763797afad5707afe8e83107783567a79ad950fdaecede654479dfd4b9454f4ef1fbf12b3f84ff73db2ee72a09709862b1a09b64ea40c7264b2ffbe6785a86a8e1c2ba63f02f1fd2ec3f365d34fc774c4f3adfc2cbc39d228af4f39e9a56383d88ff41bc15d34761c6e216a3c6f50b0564b2d3acc99327262d951a3dbeedd06f715063bde0ee71d233f9633b588a9d110e3708f807dd1dc928b37be9a681b57ca7e005910fd4705fd6375b4d73c8627794bf9cd1323d4eb09c1e094039d2a5b481c9e53fffd02dab1296925c2301e3a8b9fdfde8da05b463a230bcdbfeb3e32786cb5ed57a775c9c2f7f2181320a87720a4537186330878b9a25224864a18bfb4bec8d3e28c7296a3bf481f536ebb38543e6a1d41ea2e544c2d0f59e0593989983bfa3859ae7bbe79b6d146097f4895154e92910bfc7bb5be97552e3937dd7ec665879a022c7e283460e33bf76eeffbea44e3f2f3dbdff3a8aee06f69f680f1105782490c543814bad82bcd211a11f2385c81abe828276b60a3f4816c6cda525682dd801d2e3c3eb21f74dc2cd0fd7354a03e4e2cd3e4dffa481cd4efa51c88d25f15191d09f34c9657be455baba899fbc5d995f6f67ccac803269f3f269692a5e8707aaa0d2715e4452b51fff34be050130cfd24eeceb8eb3f985ea3683f10be64bd6ef72daf74cd5f94818287b249e833d712f530d328a78c326548eb18c0d2a01b44eaac79dffd3a71f026fe207359119c8a8d78d7318758bc21f77b404a5eee51dba0be449e90a9d41cc85893b03777218afa3db99f3b84b08a6d222a762927698e4232e26ec1740998d8c239f4e2614f2787cc80bdfbd45d67924bb0576f53bfded87446de723bbf57f2b060fa9ea5576d35ea4a8c5c58c56751860f0111e77f3594281f552e4f16951875f3057c60391c24299090f1b1cdec51d53b8b8f70466d512ec113a3fdade014b729e17c704b31d556dc1bebd581a7eabf3f7119efd19ae33b7c9928f97d630e8fd6ecedc3133d13dc7f99ef45f8f740ccfa32f5565edafc0bfbe1f881734de74d395ff42ee44decd90a320ff51e2ef9adef7cb7e89cf8004c46d09c2d410991df12920cdc7d3e78cf8783a1ddce858d5149688ff7658c879043986af07e8e6215b5cbea2ebcdf8bfbf47ec1ac779408069b0c1ced6489226ff77c973d9cd3ab05994b1a8ca8efc14abb9c1123988fe2e171eeb3ab4521a3fa63247d43e3a0d64d741485c97101c8f6d882fb8185afb12c4a093698dda10ba1a8b4432d9edee6aa1b144fb4887b321fedddfc737d4fdcf5e4c96b03fa3b38a251d4f1d4edc54b31c125c073634a49211279b2846d17e6a5a83a390ec957960d6b96e41792b2b1fcb167dd9b9bb9c31a96dd3d2d8ad9cfd8e23d7fbb43305b400b31a9641215d84e404ee323a47bbed0dbf62a056662f303c60bbf09480147d0259099ce3a69da9237db32818e83fe8d071ed3b2cc70203861b88a7d47173bafd57bc8dd3fbe88d931997b8ce49a7b46593ed7f34f21f6a1266430a79db40d2b70c1ce562dfa2bba40834ff40059c9f5989f08c992e5cec3d66bfb35d1938c3b2aa8d69313cf8e0364db004025d29a8b3bfa8d2965eb2c1697d2f2e7a511b00d85793ccfae5e0844ec81706813c7eec540d43903b7fbf10120344ba932cabe148eaf51f61c461206fac72aaa2b8207c9505da95f3c70010b99207980423bce8fff94a571ec5fd857a046df906bff41d099c7ffb98ef438b0fdc35f4cd12fe1e26fc52c53c2a34fc2ee5e9da8c77769fbe0fce3774073fb13c9dfcf3990f59a7ff47ff3d7f57b1a1ce5428c0a4b1d5823fc11661b6625290a1341bb142c61bf6b2630084125caf007255f8b9daa6ae3ab39c4b1b1d4808b830c36ffca67d096773841b04b41367f20012a9314e57a8d076d70b6dc8517a80b37087bdcec10a600d624cc49d324b4d165d34878644a6313bedc8695289110c76be4d275dcad62ee2396eb0bb7d7f0e1e281f1bfc7211db47c5715a453a6549351097ee4e13637d641d811d5d753019a5c3ac0e498f41579b0afc2ea85ff3783f5ae727fdbcf8c6aedcd919cf002cd85101ef9fa821b329712eb162b119d8c1250d6dfbd4177a0ea94dcf58e8865ae43d54d77d7c8134fcfb06c3899a39f99348c495297d3f029cbd0e2d1c13c9ba5bc399a433283da26ace9a6f450ffdc20b2572e414551d12ab3cae02908ce1811da61f0ed46ddef8c5648635d832af5a3d234950adede05aafedce328c3d7acdedbd1ff6a944616b1626d625716ae343a453bb033db263d5aa297f73ef1465fb9dfd67989fa50eaadad1fa9e788b9f35d2699e0408f8f9fea489f87a9c653b17a5260e771b70047f3bc1cfb9a3a2dae79275613399f63c45c8e764aad33ae7f509526910d7f4eab3bc0754a91a4cba616d80657609288253f30228742e6ba04029c6ef5eea842665ab8556af707782c29655813069f0c4218c8004fbab48919e27893d14ee", 0x1000}, {&(0x7f0000000000)="ce1ced", 0x3}, {&(0x7f00000011c0)="a8966ce8820e6baa27627de7f025254efb5a6840bb6f37e19dbc97a197a320e414d974edca31a957e426a16418f28e0a0c833c0f926bebd4493b1b47bba99a80cf6d91fadc14dce76bfc1ec1b74b710267ab88220d23dc24648019bfbb05a6937c2b0a8aba128fb89d086a5e2614a4c91b8511f87b7ba7ef87e6156b40e1295166f59cd21918db66c1045c3dd27eb0d53ba0a8276158dfaea734b240d41397e46ef34869950b1d99796cf2c0ddd46db609cce8a41e9382f09e0dbca0f3d27225b568a979d926df98fe4bc01e5318464d980877cbb4ecfd4d", 0xd8}, {&(0x7f00000012c0)="e0ca92c6b77dacb7e81316bcb55a5548e5f4076beef790e0bf759c2cdc019f6951f25f40e6addbd337202b62029bd067eb9d0a3b7f09c13c30959158fbeb7efe87e41fcd84427499c327e26cf4d9636a747ab1732111ed2a75dc69daca0a0e97d0157ba3a7e3cda84a7c8e40024e58e56817149220dab4abe6d259905d1c68f8248541e6abfcfaf44db836a01c26003d27ecd8196f4ed7eea32eed3acd5b08d705ce6b23a28c27aa84dd8fd1c5013322c36ed16d0bd3839cbbe1ee86b95e8669e273aab05f3078c4f1770f45c00956228072615112b25bb1675f3f4f7e059092c8e54e3e51f9ad20a3a85c45e5c649363c13e2e6d8205265101278cced42d91dbbbdcca4e6836a7215d0bde4f74c723d875a67f802ce22d3c55f2f87c1349616179e98a945d5890541f20f926821ca86cefcc59928dbb72d3d48f8204db657d7bc95b857f5e17742a1a79eb9da4fde8027fc128a6ec56c3b89211266935a84e9c124eb28f5e3a843aba6465a9eec978e9ccbc1c434450a57e65e6bc692061c74d24521ed3ab7479d2df53d04b8c0994fe94aaa90e206653aafbcef173ed8bea1d5ca0cbd2e49c2c5b9d5d7451ff3fc6cf0f75c762f25c8373df0c8641b011c7bde6d09513d78657d79cfbdd6f2b67d47202ee4ad170bb89bd1145433a9402216dd8619f5cd3dbce66b79eef8ed876feeb8dc8a185ad70ba69b1f504bccccdbb5771d3d344ccebd257f29eddf8df29e16ef396da1df872b92d46eaf6c8c2bfeb3119bf24c66f5178b68d07dc9012d2756f3eb0c4eb312bd2e24d475003176de6a79a16eeb4f908531066428901e9977762bd4db05effe5842f78da4ec878edebf4bb9c3ca071b7c544e9fdec7c1e8a26addc88fd92085c367b948d2225c3d55e880fb0ca7721019427711c16e61636d0811dd80a0f6fcf37732be4d39ef37bf213309182fd257a028629228e4f1a243331c863e2ece1b7338a223b0a2502d8bcd826c9a0459fcce12b4cb30cab273e68492f2ff292cf2234b4fd2601bf25aafa2cc621490a912ff065308b5715aaa7e4a02b6a08944a52c601458b4bc53f55f75bd24ff2da4828290832bf1164d00ee9f23498b4808d06b79066dafa73d135c818a9aeacdd2584b1d0ae3b37075e34d7e2672ec05fec2a67eeba720fcce91c0ef3c422a5e48603261d6801a5bc67bac1a7e5c87470ca2f695447f3015d3f7b73233f879c2885a706e12b4729b38facb661ab2b2c5992aee41b47e279ffc58feba087572d4afa98b055ac8da3b4326c324e446953583293d568a70310f24b93a299dc93476826d3e951ed1782788ceb8e61e469386f43e92294a74f9bb3e768b055707af3311775e1fdee87d4e8ee7bc27984430cf496454b4712091c3d1cfe7b9cab3df39e1738f51408dd718dc8caa98ec76f2f6970f4caec24320f34a184b53140f73ced2076be536ec9ed3b04f61506c199b2e526dbabf804b8f0c17697bcd0c2d9bc8c16e4ee449c444a15eba5b7daf6f4802d88af41d315f165db098f92b053f68ba42bba812f8da9f0d833e8079ccc75b85355406cd8126cce727a2302438bc90d415c9c776bf325ebe08720ea76ca19a594ab4ec44dcc121fec736addd010cfe18bbb0b65712314828cc23aef2a515c425e76dd7afdad0c80cb122903dc55332e4c6085b44bab30150a89b2f66fe79cf2374daaf3622c2bd00b5678d039fe1109ba27092e1c9283cbaa4e0e069cde6e0cfb9d5df1767b10ad98ce4cf3d23a5eba2df62a6ccc6328ef3263ed7f9964a54d636d5ebc2108ec6c64f9baedea105a6c44e3737af41eb2711958d4b67d9523d42ea463f0d09e68eee013c1de4bc071df42b21806e8bb116427ffeee0dbf0c57c7bae5b99eb7a9e036fc0d5c27dfc4fff215d8914826e7d071072ee2fbe2a5c9ac606f1bbd6bad96f202e3b33d9dccf40008b7e48af9723c19e71541546dc30499a58142cee36fd99bd264f39841576f6cb196d1f727903197e115b5d34fee11fddb622ea1fe322d16ba8c13eb35d0740d8519ceae30f42b8e875e3c0f994d9b3e86bc9e9fc3eac9d4485fce635e773b587ee449c1eb945ef6fa81cda7b652a6a9c690b2475ff0c73812a39ae9de3fbb8f7945da3ae042ec4e004f08b483b8db6fcc1db9313cf841b3ac616874c3cbc0d643746a099488b54f950781cc24358c9a03e06182243aa765872192a36e89864eba49661ef687341cd5bd63b528edd667587fd6f18f1d74e71267b8b8c19f45383b4a37fa2b8ec1bcc3a6a6499ed1bb97016287538b46db1a8a5282f70a56749bb3cb5452aa098047426433205738fb476dc27765d6897e548363e24e81088bc607f3658b92271137562de2a307895a48f6a6b403563eeee22fda41bb13b7a954b88474267b9e3fb1553a05dfb29156aa618ce74fd4fcdc5231b88274cb2a21b1084e325ed122a9d14757063a05f8d1860c6a2926830c93262ca85ecfb4b56b61597ce7c578a818945cc19640ffa365a2fc50f4b50aa84f9d70908dcd08b69da178276173e43d49ea4fdcc767ee92ef34b1f3ab8ccc51896bb6220b21ae34d12e0b96c12aab60f54b46678a60894f5840249960cdcf0160c000a5fa875b1490b6caff4b9c231d109b26e9604f0316767b0d260d4788f25511577185474f449609ce3911c83fb35770a8d6ba5c4a48985ee2f3d85e3838f782835f48f027742d2668ed310216edcbfe537171a25ad8d046acc1911d34735e0d45b355c167077b6f2088eedaea27aff51112d62360dc6409c3d441dfd3129141940978a3aba6915f624616e0c11116c468730cf037d0c3c7324a1c16cdabbe7b363bef48917464821cde6251b7b5a3743be27baebec6b246c4881ee6f7a5bed2206fadcb1173b0ebbbcbff25aa3537d6fbad9f261ba3f4245d17c7255ead12914a1d3f25df2aea6d19fbb596212b4783ec83cac27354de97bebedd211b729908eee05168a045dfd185ffd34010bc4f6110095a7e4036835cd38330889565d0bcfc8f5e231ac3ecb9f07830a1d03e41ea19d83ea97ddbdf99e92fbb3502e618de923a7929e5d09752a74812cfe56d55cc3fe71571ddfddc86a63fdfc11f8bd5dd650b2a3242a0110b91e3bbbdabf62f21b4ebfdf393229e7dd1a7db7a20c5423a489409e079d57717d51826ebe85459d4a6c729cfdca6edfe22d9abed6a40669a274ac18ef9c396caba98d6af3edee215a818def7d2ebbc5b29d0e1b88fa598d34f7c9d8e66671b6bca38af9a853657140d264e5f5c681d1277a31bd3228687688e7e226a503d54fc7290759848077f59e85157441db0b0f7d8432138a3b451742b4b537f77deb63814a68355c93407f5c98421500c05e7dc2279b4dde95f5ac0f19dd76234ddd7fc8435f615c5de4f2098c4f74db60af89ead9c05fcf35aa9f80d25f9ecde4f09ea2fab5a6696f7325f461c9a03783e10bbec0816e2d0462d5672396e71856db4a685f2db03de3026fcc7c65a2d48b81c1f329e2b44af0108869339334c38292c6db6e26f1b2d7836ea1002f054281233590aae765e24e0d6dc33efb7504409cd56ec54dcc1da353fb90b98ed1c67c90a438b4cb50b229dec27c8fdda46ff4e5adde317aacce03f9aaae625a0fe6aca71de400c1783ac1678eb1d86c9fa06edc77f588e84dce5384aefdb9b6f5a3b130487478ea642430682b694d899e9b98233ccd53a94d8ee46298d57a7f911452a247ac0328d7afb88072764775032c3bcf0a3a7219e5e132036556e91c4f206290135134b5a55c2d770993dd8ead677a0771299623227273add967bd7e76c41bce6c8a80dcc75d930ff213f97853b48581095babf49269e20a73e5fccb8aea709ca8729b67a7168afed238b26ea75f135720d976240fc83f1eb225ed1e3b02717c3159d721872014657c824892cd624bf65dba21c7d5bcc79ad16c34960954e20907495cb15fc4daf13a4c436cb2fbd78d59c264709610251bfa113c6f16d699ecb2c84bf91cb922279e33ef00619d3e2e246f766f800d806ea1fb34655a5a1f4ece959047bee1d4bd2713a9d2a681dd1debe1f1d3ee521261c2bce73d06cd575dd5c9db7f3247d871a790af43560796096efb370cd12b1529c144eb3d6ad9ae1ce6846c3f5c0e59b89c4d490fc142f5b2674c588e3a25c413159ea941c088727984f55ba9bd6dc79af09e2ce565e4bf8f5fa6f2b6296aae026c9a661e791402f35330f6e9d3286f8e199dc372eec8c7f054fbc20cb4050b8cf86e88373a07fe9d31fa99d5f33562ce9f94758bec1ff3101f3c0f7d9af6934a59de5bf8ca414357b51e3b8fe4da2f9d01f5032bae50302c6166771cef42c74abda6b1f6314e8da97083a528cb8620ad752db46122997950b820ff4dabf43c80c89e52e442f2c073cecf46ec51de1afe21e0e6b969aaf6f4ad83d35c656245c04de0a28ba91322814690ad52960820e4ee429a9bad0ba3053c0744884d3641831009faaf3a02aea3fd6fccbf37a282a3eba9b17aedc9a616027f7cba0dbf92f8a656043ea372833e26d036ccb27a9dff7c631847ed58abaf46e8aea93891c050607b0dce09c897072b62dfca65e1eb1088b40f693ab4e31d3dd55aecdb053bc4e4f2aa02934168eb4199a17758e17c0510d5ed25aea41f6fc6c81dcc4876e34c364d12ec5ff7ee6faaa008d6db3e06955e5356afbd4fd25cb35112dde9d6d493830eb08e062efcd8af0cce1e337a419983701559454495ae72f6a7a4e0fa94e2c3624bef73a415aaba9f52766db059b913113110469ef91e3de0971c991968ec5a6676e01e4ba3fe4e0a4523213053701c915d557770a07c43bb113372bb241b061ab1b17246e865cd77f061316f6defb6ff0a6c4c7830d30363df5cbcb801349f200f0bd4fd0874bba2b73babd26cca1c5028aac080906f2028b4152ed4dc50bc63902f0534b671792257d0f1110377f10fce63c59fd1f5f2626fb0e57b0bbc6563e17a32e8c1d9a1aa04a6fb24bdc8123e027b559903c037aa17ebad1d048193ca17bdae112d94651271cb2a0001d3da633278d10f774e169d6622318940633fb461dfb3c043258dba4ae5f65954fe215671af46de1f51d4610982233ef749f80ba74f6133e1c7991cccaaea53c9348738fe280f66c434d6ca1ced7d00fab3876f19fb6199f6be3c69708bf6c8b67ad15d8215404e781554b5273475e87b0126de879e94051a210ff8d3dcc99358a948ba7be44aeb979096bcc5ac557df0368e19d34d6f1cec0fa25a40212ac7a6331575d978b6cbf1b6089f0f1c9de1a2bababedbd1cde311e70fdd7b4a2d4fc9baa3470f4d2ab839e288cdaaa51732942371ebbef8667433cf55cf119753781ef75616eedf43e90ed4491e5402568e2d641e266cb5fdd8d72aa06e76da563b1c70e4bc12051649c0747d03cbba5cfa60625ed8213c416806a2a0f657cc141c99d9174f1dac84a6dd70fad8972", 0xf26}], 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = dup(r0)
ioctl$BIOCSBLEN(r1, 0xc0044266, &(0x7f0000000100))
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCIMMEDIATE(r0, 0x80044270, &(0x7f00000000c0)=0x4)
syz_extract_tcp_res(0x0, 0x0, 0x0)
readv(r1, &(0x7f0000000080)=[{&(0x7f0000000180)=""/15, 0xf}, {&(0x7f0000000040)=""/17, 0x11}], 0x2)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b1000513000000000000000012000000000013fecea10500fef96ecf2ac72fd3357ae30200004e3039cf7f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f336443a42118000000720fd38bfbb770c1f5a872c88106002ec589040000000c000000361b1257aea8c500002002fbfe0c2300008abfba0900000008e371a3f8343712051eeab7196fcbd80407000000c0112000"/177, 0xb1, 0x0, 0x0, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000080)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
r2 = kqueue()
r3 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x17, 0x0, 0x0)
kevent(r2, &(0x7f0000000100)=[{{r1}, 0xfffffffffffffffe, 0x49, 0xfffff, 0x10000000}], 0x9, 0x0, 0x0, 0x0)
recvfrom$unix(r0, &(0x7f0000000140)=""/142, 0x8e, 0x0, 0x0, 0xffffffffffffff71)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
syz_open_pts()
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r4 = syz_open_pts()
close(r4)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
setreuid(0x0, 0xee01)
open$dir(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
close(r4)
syz_open_pts()
writev(0xffffffffffffffff, &(0x7f0000002040)=[{&(0x7f0000000700)="6c0135", 0x3}, {&(0x7f0000001d00)="6156b89a6c15794f5426cf6a9a99b45b13564d6568f0610200e27d20182a400c7a9a8f0bf304294555b6b6cd19d32607b3754f4a88c97fe52899b92de96dbe32036c902694cbd8aaeda1b13395179e9aa22d5bb4ed975d8a585625759478115f4c4ea9fbe58382e00bad0ecc43529514d50fd81869975cce62c2e1a2520b63fd16166f35d4894abbed34c52f3e7e55be11106341ebcf1c65", 0x98}, {&(0x7f0000000900)="d09f6591cbc30693afd0b88a5a095acbc2a56dfe7b00631bbf4fdf760bdb5ce6c02523c5057fa75fcb6b520094262d6b81f8fb491e0d5f97f7e6e6fa34e3a87f4928bdcaba0d83c8a2f9b2297224ea89dd9aec6f5b8a9b09b2593bf5a6bf21f0983e", 0x62}, {&(0x7f0000002f80)="e0707225df5da0a3cde8f30024830d8e0a6a680844e59fcfa5dde0a596d8cb2901b8b60f269bdffed86a45026e99759cd124180e6c72cdd068718d18c40fc74364f4efef980c177c9d13853ee6bd3efb6bdd04795f2e00eef893ba9db6c641724b4320eb59db72e821e00eacae80ac14ec93e79465b5dfe980b08c3e219e10a322fc6a99d984aa3a17ac3eb99a7d90cd400081b6b1e9c2e49f51572faa4aea239b26ccce2cf371ea6bd4c4ec685cb5f1e1944576a86ba1fb802e8228e5f58b56265448b08e1f2d780a33751c191bc1a169ff48b7256c2993e0bc717933110bd6383d6022fb98dde74b5ab0ecd85d1c8019b3b8c07c14da5e8c27dea1464f6fc6dfbdd6c0f4b271cd8e8de994b9ed88cf29836e05544d9b93bb7fc1e2c2c2fddcddc82f884d45aeb0ce7407d2577be2fe2f8098613ab2ad60b5032a13dd9d63a2407efe3fadd1846988c3a299fddc1186d14064c4aeeee77394eb10e65516559f522378718fd87e5514c8fe55366b2154c898a888dcbbde73ca9e0126d6ee8c27af7b9eda998ffa359f377ea61147a6c3197247f363596ad3d3d0d9282758b09339d02616828993b0855085ed4748e48c50f7dab9668a7dca419149596579bb01408b8f2afa2b4bada88efbc57b7a096065fe6cb148eaed8f3becd5c7287c19d8b8d9341c416f2716c7a6ebaff889cf1ce69c7f4bf117fe4aefad2a50526a28df87ac628879076fe3b857ea830f45cb702afb7c25a06abe4d2a754d0fb77ff30877884fda5755e1c1c02700bade0be10b3c75c0166e477992584dbe308f2136ef82f72391136424d14b3fe1c4ff4cf8ee3d4a30577aa377438a795ce1efe0fef1f6436644224f92b45b87ec346a63a4600abb2bbc572ea82333f56d942d0294230c7ea8cf24bcbab7de10a06fbf4b8a5e4bc88a0b4d676062a62d5042b5d88b0ab80962dfff7ad508e6580ec0e565541c713e4a854483788c4440ed3cb388bb2fcf71e33495d9729eaa4f3df7d9118ea8942720f5dfda14cc5e35cd1c648b1e2c5dd0984536f225043b7aa56f45b94959d83990e6050353c7681fd596fae2ad6b43b26aac3e6302691eb49a92ac075b0973cc230bf41a02ef123a80cf799a9cf2c472ab0b45cde3c980a092662b79205d07c040744781e9c27e32a133cbe9e219489d97bcae4b2ec4ec0839978daba24fa23bb89fa6edc2b1f929e127136e13d7ab140a240aec7006d0740d15ce77b028746549bb91bde24e341d6aaef7684082283943780105de76983bc8c5101001c3a3a5dfe282d11d70ba08237d0c23eecbdc4a0738dcd1d0e92649c64d1fc75f5d4b1ccd10cee6ed69f4f63f63d63b04a73fe9b0d95ec3d98d55429524a7d5dc83c878f9bff0744c3c3dac7513e665383d243302b985da0fb404dddbde640a4f389fa4c3fb9ea1c5f9d515a2ccc8f64c832aff4f136f99b4d917ed0c1cdede6ffe621e6cd136bc2d43fb680dff0c68099c9503f61d3640c8ab7e0e00fc4a83fb01f03024f4f5325c1fb55568bae34451d9363cdc81e46e97b1686ae29abc9b06c8b5c7e989d3ad961e7216588c01b58b29fb05c432a615d17a09e3adf06cdfdf3dd2283aaa8fc9399b7b1d83c595c27f27b0c43fa110727fa37634d748bad8737cf7e94fb2c07b9737c4576b58e746ff84bbc736f246a7a368af9bcc22ca05122b160ca182db54145a62832ab52e1db855a1b160ef5f619b49f1e02baac67b9b0e626ba6070806e70c82c2d7c3273cf8e90270481e7baa2b2b4dde1b355f71c38405ae3f4f20e53db5e1542091b7f01507410184c37574a9ac52e3d588311c12bec275849496e726f8190529c0a49a0e3e6f455202aaa85bd892385fe7109b119dc4b5f9d6f74b0d27e04b2b648769af58d288765be71b37989a5ac5ae732d9e2a12c722e285383500d13e00dc7d6a064a7b207427edd517b5d30ca905935dbffff61e10b84ca904e4b58ab3278b09d1a3af7e337f777393b93c0e84ae3eb61f87e8f1388622fa35fdd51868a3329cf2bb1a8fa5fefdef3f8340feeff8048a96a2bf7466dce009599d9290c3e091ddddbe3f2031ac6e4c5ae5cf7099f92dde452dbaea6df2ad42b0cf665b8e221206fec348a6e3a70de77d7f474b88e8d328009c8ee253caef981ae633705c28594d3da0ce0de71b21f1cf64ffa8a23f58164d60240e1252aa62de9da39247acc335c352a8724ee35770747b3baf2ad195811dd7b768054277f7e59984084c464d49d936d1c66f7eb006001104bb29906ed7a14ffd968315fcad150cae3d278da5c0b1c82a62da917c39114deddd5bdfbaec686968e8f1aae41a18121de00cb66e9cf95403ec3c47f9155482f2b586fdaa860ac2d3d47329b1d493480fa5c968f3908f56c3c4731df5baab9d67b7b2253e3965a783031979ab940db29a998af0ad8fb492a883a60df2b28462813f8030bf701ab0e779cbc175a7e8d60352352ebbad06f6f1fa8b7d642ce526043ea448fb8583f5ad9759a422a41e41d7b3a36f2fd3acbb63c4d59a719300c9820093262d6b7953ac6f90c270364c31e7295ed15d106cee1285fe71b446abcf7dcf3c0e275e4426bd4e7a57e93e7cf73e1372510d8e6a2048ff8780eda3223277a03eacb710cddfe510169064edbce166244de18084dfe2508159f889a55a67f083c558a9b77f733daff67179a2322b53179e0079c92bd7aebaea9c5340f3ab4b7cc81d51803abd09fcc33392063c34ce1e1a0e675adfdd4a492f5a45e96d2da3d4533c9591bba11ee5a7f8552bba7cdc68932f8f4583e0c8f72b064fc249e1be449f1d4e6c8faab0b83cf3b6f79639ed34660c399113ca2e1af84335086124e5880174e4db34eee82a81ad779a2abb3f6de2d6e5ed419d855396579362285f40c6aba7fac5766b30caa1b5a3ca31935a45e124040a29b974de1cff0eca1b1ba280228bafa33d26d87f77abb36415122a0cf24e1525228ccca1f6873e67bec443c6fc46790d2af8029bc97719078956a3d3c897faf5b19beccc2b37813351bb8a0964a5f8cde403f162d4035b6743fdf93830888e6d0927e68c924de1ee1e6eda7de8348196a0e240b4fd629338d977b497c315662ab60b84797b733a931741f0f7ae88e608a9dc73ce5f2b075af61b6acb61f8fd475ae504f97723326778a75a37474e1cf7aeebc8baa20f2168d566c1cbfa0eba48c19297ed0036090a7989ef743211924453e79ea244aa18c85170c9aef0f4047332f8b35b47776723379273f292200f4a95c5a19ecd42eba114c3f8cab75937ae571eefd7d79368272db2d2db75a1951fba103340a092a7f7a11e6ed7aede39b6992f2163fddcd8998b1a51ce55edd4991bcf242545192c5da99577e6362b1a26c98ebdd7353b0a1ad10b5736faf60273485d0b7d8f9c6dce6538e5e8dac1b564bcf788efd488490736c1cc354758e6d394c77561e47c8c5de55c824dcef6c2ebb6e9e2c734ea05b56b5017f2447a2634099c1b9b09e061f6747e663dd92e0dc5eafa5eccc7e8d161c1e79f30230bb07dba9894fa6af1c66592cbbff937c01747ce5ca6b356f54f141420e38ae84b8ef505cb8e5a20933c463f48a70983996b72219e31cefc8a9485f6f5451deb8686bf1551de5b549da221a014fa06222265932a5dbdcca51d053482d30798e805c6c65808d72cca8d8aff611be639e7af32a8e9e92b2b83d59a081b86a7704b92ba6ea48259a31175760354ca8733a53ada1537a123ba7dd87b55bce95c238e30f19092f9585e8dd9053bad2c51385afe012c2dbd3c277c9e6689e907b907748964f38b9576ff9b88ec5f1961cdbe845c7e096061686ce822e34a2228227e934803ede4b984ac3e4ef28f0c0e24e0893e70d7d0f66847d38a14b3b2ff87cae2d1fcf1c8db5c32d02250145fbb20cfb8b279baa4a12526484bdfe4d36d49a82db857b82a0e11a315ea2e298bc8b8a69f4f7545008a440ace5b2654872f3f569269a1144e946c90f904e48ba061c1a615e8cde0a4194a567e86041ac9fa4b42553e19147ef3185fdbc685da9b439f02a6a34d8858eff5d762d4970488508f194b7af38590888c70d69b9eec79e53497645006ec6658dda11a7898ae96c8bc1a54b48470dbd840f0fc68799019b5b4137dc5de49af82d12ff2f50033ee8007c7d9ef1ebb3d60fddcb9239508a858df67e6ad3ffe23acf973db7421777a6a2f23ac58f599d88487ad8515808de09a0f59aaad6ecd7ba190bae74968c49b63451fd68cb2b835db73f7e341587aec98e7618b9836b8e851cb31ba1a2a86d52cf167279f850d811a0209a3d4a9c54055ba189eefa40ea10cd6458e1ba09979a3bafd21c5837fe11c264dea2f529ad2ed6d19849f2e8c0fad613478cb66a6724091e4b2c56588793813b44745eb97e688f382026c85e87124a66f542bdb99fb7fcd874d34985353e74a166a9f1ad64c305912b2b6ec1423c15788fa6b2194e2be021f1deb0f1b3d44b3313fbc9a38c290cede3cba47afcd98a4e50d019dfb64214d9c18448c375186ae9cbc7df4614ed4b9ef760c9808a5698c81b1542bb08e4fc82bfaa01be4807d4f0ae852777642019dd45d876e2c3bfc3f0486016b3d763cbd9d899b3e00c7d3001e94ed8515f0ec9b9f1ed7b8df767103ef964acb4281a59f5cebf08cc14e5f5166b9a77a43e8a3ea75c3a6a8e56eea86eb2c861fcbee63d44e60a2dc88c726b8149380aaaca89e83433c919c53754a64f9d8fee3049a5ab750eb8191f7676cdf3257c9e0c661921049962b800a299e5f5c002629bf053030203b5925b0f782c8bc5982546761b4256dd7c37a99de97f1187190f3a1068c86eb7c54cb3ba99052518ddff6c2f5a3651808ebccb435889a32b844d663330dd2231d55cec6a2e6f880ac93dc383f0323f33f66cce427475e117054827db2ddee05696992299131d9621d5041a596c3e72d7b018c813c5e1f698381000d3efe1cf189e2f749047bed3c6cff9184f22b4f3b6368e4ed839802f31394207395f8b3758f3c93f640734ebd122b52739a610d85092beeb06e47d32ddbdb1ff4ae18c696cdb93f8169f5980b01ac14ff66fdbc7efccf6f572a58e1a05efb444510edbd59cfef4ad12fe842483a3178cf9c81bb43e9213a7a49339d9a4d8150b5f253f938e91b3801252ca80230a9eb6a15c048cf10e068c6bccdc756d7fa1cce0b1cb147325b435cb504e5db48c32bc68f74a60b8baae0dae80bc4cb1cf4856802868817de6e7345ed493ce177a3dbbdec2690d590a23e3feb49554dac882dd8b70d8b7128d7ba1fcb715dc8b18a2bcfae0bf0a0bb557eb6eae8bad4ce3ee4246398e304188b1dcac6ef8f5e251db9c29e0ddd58abd191c5e2a961fa3e09fbf5a540c7687fefa036743134bf7008f66f484fe72a812844385fccf500123ddce1c3628c0826250f6e2dbe51bb7f525261f64bed241d3ce57b7da9f91e0d6cea8b3b249b461a3bd0372b2a76758de3113532ab8ddb3188cec04333d8d8930673fa753cdda63376e388d99a995642c7c43859ddc8bdde9101a7ebab17d4894f75dacde90fa971ed682fec74e25bd782a6c56d8e5fedd9ceafb8a71afdbeda2bc8c52047c4918c1ca24846c83e1b94fcbae7fb12d01f425e799de44da53c08a063e1ed1c47cc2fb55235c1b305afd000ef8f8cdd7a6234a37198b7bd8acf59a52c325b34f76cf5879128463d3948b4c401d9c8c8b1ebefe4405252612148a2fc80edd07131faae799833abda290e8e1b423af9c93307cf4cd3c77dd2", 0x1000}, {&(0x7f0000000000)="f286a84d365450931351d56a392f125053e372a5", 0x14}, {&(0x7f0000001b80)="09b3a74bcc4c28d5", 0x8}, {&(0x7f0000003f80)="9160123d76061585eaf66ae5661e9ef1dcb68a5ffeafff2953cf2e1d8a09ae56a62de6211d18c47e0f3491f0ea03e6790e5c82c2e7d1212652cfacc7743261bc7250207396761e126a9d84b718819d4edbd78a680b79e1459388cd1540571bc7b6b22be82fdc23a0dea1e96238ef53fb6547dc8aaeb3c796eb7be3628b9ce4b2ad3af54bb93a7b609ec98c4fd6e6f40b78a136ec58ac977c0f03880adda9eccffaab3d25acbd77ff269c9d99d292846bbca602408217d66179330b08563d3a2d036050e08f5a632a2d9b8f4399eb7eba6d146046c29decb9837d0127d596bbf3fa47843a5cdf896c9f39db9bf43040c135b43dd710a612c93cbd250efd513478460b88afa894267d6d3b5caa4df2f742ff9f3e6be94897da6794576524701994971c7ef2dfed4f359e8504ee8e93001e9ff61410a2465cfddedb29910228dfc73c71e88be80ce1905310216847c784c3b3be3d4491d25c99901497a2c4856b2989ff73d183474a1870befe42a2236851fa6240071ab8abe4e31179c2f53e634e70a12583be24974f6f85153aa453611c0c8a03b2294a3b234c4ae161d9265cced961b0df5d4515c76984e5e4e15f50b23d890b2bfe7b6c30a6409a5b74fe5a4a8c036b93cd9fb91ea84271269c52f8222916306f23edd3000f7b41cc4b3a4e5fa88a5c2d7678f0227a3782b1f8d6864b7fd8c2e76eff5021235dc3aaf4995d721d6aabaacc97373a107af76ec2c2520e400fbc749f8dd479d0cf5da54c4a73e41270d0391963e0cb8542be65f43fb2538d605085c22bc116b371c9aa02811aa86bd54a65a4b6983168180a3be1560b526de700f1949bb32d5d9f38f6a5c6281624c6fcb44aa657468ffafafdc0637748df145f718082709de89edc894c517a0f7ee0835e1fde37ba18740263c5dbb872aaf3640c55df4ae91f1c4d8a6d060fd46d2cfe9928475da6c0d001f9e2777437a663cabc593f8aa84f3799263cfc27076568723a08221b4bd190a3d24bc7f9bf91698e19479435a59a8ca4fdc38005a55d1e61eaaa9e4d71c99bca17b34045c700de76b4d90df4ff250341605ae4a680f6bdfe6ea5e6ff77bec1f6963c790519181faa2ec1a2f9b16d1b824dabfcef556e91ef4bce02b702146012f691ca05e0f873b793d6051c6448876a93fcaf32ad9b129aad644b9761508e0cbdda42424f5ca9ac5a0cb67fd5ef8d26078c16cf525df596a885bb192168ba4a86e99c0827b56331e6fce281bfdbe7601e6dd9f80e645d073e5fcfb80f23ed8d6a1c4c6f1a0593f126a47bdc15964106058ba5a3f5e3937e4d1936709df941849452f2c9c392aa70906c85e0edba5772c67f4ea0fe3719344d03a358fb664d793c4aa54e216aa56f8cf2b407ff5d4a529911af166a61b7ed4c3ddee3a52bb0c74950249d112f60d18b35e6c199bbaafda43d0f0e1e29b0bed4faeed45e840be722bfab97e30a01e8fdea1117a6b8581d6a9497c3921d84b377cd7bc1a1f3df421fa0a31f196c9f011339a202c77d552d5e30df29ad6a54a02d0bc728969bcb38626a82fab1855df909acb56dbbbe1338015737b460b9085379f144f08f4fe6fbe9c9df241061196a35365a34eaf0c65f97d15c811b98869c4a49ddae0601994d545d202d856fb5e3c96921e56b80ec978feb36f5daef50f995dc3cad442da07de75b97f810dce38413e8cc64ce3d32372a5b7b08ee898f5fbb37c4cb70e8b555322af7968013968ab4d07441409a43d6c68dc5b5cc02ed048e6a296f1f735fae1874c921c15dc6c4422c87c803c1783b344f60f90a3d2efafad2938d8269bda4df1bb247b482f36c1713859723951d31241fe7b3fc4b7c3bf11f055de8365b2b69328e5755fbab9dfb0b03205b2e98dc059fa5487c37ce89acb18613cc62486ce09e75a72a8be009793b00c74e9adc2b93471102f16e83cc9ef0ac2c2b7cb5aa757a5d51cd7f6336151beaf55eabd134a6e6b93593a151653837ed5d494a03bcf061d63d7a8e501973506642f68d6b2d490490cdc9980a624714008335f98caa71d22e8651849caa054b5c119dd154a80afd2ae95506728c0acf02eecd8887b821c764a2be51ba755b9db883a75748d3c20c2205fbdd1ad4ea848883642e27adf313fddfba60f314a80a463f056179643abd18bf0454dc13dd799d25c244460d8d2619238bb5aebe667fb38048d9dc84242dbcb17ecdb64170bb6b80fd710f597cc96d081da2ba082ea62605bb3388f43d1849f8b80ce8f8dadaefa84b0cf5e12c2a3db678dc0859bf927320cf765fedaaefad94d0da4ab50368105e4b5981feeb3edef40cf25780b6b00752e4839a1f3e0c3def6e5233db0490dc8ce93dedf0d44a05d2a132a3649eda3ab5da9e7762edd08b83a8cf2e7d253a78fdddc2c6ce97cbff41532692140ffd82bb4249328d01a9878e3f59d7159c493bec6184cd3d71e9213b4b6f70a7c26404ecde93e81e897e497f3b44ee04bf394cbe8540a49d31e33aa875b0c0e43e0c6af30350c5b7992a08d8cf0b5a88f0e5b88b6da6de61c0d1b6289be8d9effcaadd6b62f47b7169092f07ac1b1469f52b4b2369fd2e0fae1bc43cc415586b11e4fcac1b4148d5e7417e3a0a0ba64973581546781ae2a069073a0a557ed02b2462a2f26ac44729308c2347f4a7d7032b521ff58a8d1b3f095c376216c44762c889ff33f4688ba61dd2f1da40892e49a0bc0ef08940af0352cd6393eb1aef2fe707b138ba8119f3907993810a70bc4f1625ee0618230b58016277b50f89d8a7b92601c697b9ee5915a8cdf0b0d6f23005bc29ad38f7f3a7085efa550ea390ec31873f999733b874242b1eb5dc9dd5a8deb0c14d37e250d98060bbc30e8b5e6155267b424cf16deea1c1b003407f1308f93e8fa0ed90fb3789c7b05a5c6cb65fd34df7555dc14ee95eebbb0b2f0d75e3bffe98aaf4eaad9d39ceabed5967907007aeaff27bb2d0f11cd021bf1adfea43f09a6860db43ee3be9e520399bfe1f4e53b9981ba8f27f1c5e81c63f5e3292ada5c1876436b1d2d5504ab0affda2663d82dfd368cf67113f6dc50db630cd05b71d340afda503c2076f8bdb0f7dfb915defc7c1c9231234ec1b9bc51c9fd412ca09d7b0fd44af63461ece300c5e13c97be28a46be7d7811b648aef748905a3edc10c9854c2019b8da98f39ddae20857a9e10c0e0d31d21732b4464e69a7427f947d0d1428d785238cbe29febfe78002738319659cecaf443da90ce463923c09849bcd23590513bf05b9a0030329d29422057bfad1e9201efde01056efb4338152a90f3958d92affc0d28026067b9fb53847c3eb773edc09361b824de631476c50a9536d3432204f02d55679966fdac3284f5a8e6bb1a0fa8765f1bdf044f58610340b4405c1865340ee14aa612738218e58822cea59b2233bde7f515dca110b5b69cd023c65fe76c05b3101d2cb8839179c19e1253eedd8aa49eec5e61a234404b5050d3ae406b39ef356a61b9b70ff362dacc91ac18bd993d3411624b33516f5ce027fd14b98b71a127f100d0cd7bc06650ffd79b5acbfd6ac8acedd641151f765effd984de0d56aff18d939839671669b2f46ceaaf178b40652aa0830a4d01899721f7ec0f80745a021c2f3ec6ae4c2aa9c94bb13f46cd5ae8790b3da1c0399de2f2832c9ddc7265cdb6564934420b3dae8a9d18b929f23ebf03603a3504894e9091122598eb58a97d6455c7290a8c1762596b926a00ef0c38559b91682e3bc67defa7bfbadd8834f154c195cfa545a5d2b61a1c70f70b22ba920d96e9d1be18cf02d20d506505c098a6cabc45b81120a18bf7dee36f092917cf01bb1b5cc29b1047abc682d28c28f692860e4397298be4d20b52c63221220b995054d2d1ea4f8b51000cc93612add83f113c6197398d4a16a4f385dd825df203540da118fda3b6f0ca27c77b32f6288994bd8f56e41be27b820aa82ccf105c535790d95617a3d4c2c8a7e0d379682375e081bf920b2a2df309cf6d1ae50f39769534d2a47f48b30e9b4d5cbce04c84b6173bc31c6e4a5ed3d5905e0107c6daa440ca612d99ec1ee118156af1f5e4de9b01d83a5c4ccad4fa6fdd29dcb5f967b3ad7987b14448f9a7e9bcde6a5c791c789838caaa5e93761b0e49c1aaab894a505004dde4dfd6a97833accc7d0423352b09c7923d563a47767", 0xb96}], 0x7)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x7ffffffb, 0x0, 0x80000005, 0xffffffff, "0100000063026d00000100000000000000777d00"})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000440)={0x3, &(0x7f0000000100)=[{0x15, 0x0, 0x0, 0xfffffffd}, {0x6c}, {0x8016}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x4e, &(0x7f0000000100)=ANY=[])


r0 = socket(0x11, 0x3, 0x0)
connect$inet(r0, &(0x7f0000000040)={0x2, 0x3}, 0xc)
socket(0x2, 0x1, 0x0)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000001140), 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r1, 0xc2585601, &(0x7f0000001180)={0xdead4110, 0x0, [{&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffa000/0x2000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffa000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff9000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000ff9000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}], '.\x00'})
socket(0x18, 0x3, 0x0)
socket(0x1, 0x1, 0x0)
socket(0x2, 0x3, 0x0)
pipe(&(0x7f00000000c0)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
poll(&(0x7f0000000000)=[{r2}], 0x1, 0x0)
dup2(r2, r3)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)='\x00', 0x1}], 0x1)
r4 = socket$inet(0x2, 0x2, 0x0)
r5 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r5, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
dup2(r5, r4)
setsockopt$inet_opts(r4, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt$inet_opts(r5, 0x0, 0xd, &(0x7f0000000240)="ea08000000000000", 0x8)
select(0x40, &(0x7f00000000c0), 0x0, &(0x7f0000000240)={0x3ff}, 0x0)


mknod(&(0x7f0000000280)='./file0\x00', 0x1000, 0x0)
r0 = open(&(0x7f0000000080)='./file0\x00', 0x2, 0x0)
flock(r0, 0x2)
close(r0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
mkdir(0x0, 0x0)
mkdir(0x0, 0x0)
sysctl$vm(&(0x7f0000000000), 0x2, &(0x7f0000000040)="4219ce856fba52e78b3eba169e0a7db3092064cefa600a50dc6cf22a15d5ccf231fbd43785db4873c7e506c67ceb6865523b4c480a27565c40db8c63225859df53a5af91a4dc9df3025bcae48d871627f5e80da1c08f4b4fc16b2acad8e33acc2ba525d304c8b34d1b71fb3a130c584c623d44f10acfc10ee4a6aa98733f02800e5abfba34372b14c6dc66923a2b0caa5b0b538ed862c19c1b3114baa1f34ae3d666ddeeb23197990801d95c7db09417cd39a3807e9183ef5c73c50781ed7b4b9f2d9f7b26b308df6b80fdd83c44fece78b9d65859eb7df1a1e4ed9d1b83b45f739515d781305b03b4a608be", &(0x7f0000000140)=0xec, &(0x7f0000000180)="dc65f3526719a8365df416e9bc158c38b91d605be780379970f6d55faacbfa1efd3ee72045c176ca069202fd4b54135f94f0a3745b1a451943d43e13b0cea3f85fe3f902c4e3493ff3bfddec6885c1f7a65b6d73dd45367976787b9eb0c888f7f75d5629", 0x64)
sysctl$vm(&(0x7f0000000200)={0x2, 0xc}, 0x2, &(0x7f0000000240)="71a097870b73cc56b67074c06ee4f3189166a17c8942148620b55abc39e5a57705c6d074fa2af250f09405d72cba4aa6b8d163f99d6cf13401ef645af29a3a7fc4c383c9ecb911658d607a4929d0f8e861c6c117fc42ba28aa7ab4ee5dd8fb7947afdba40842ea73d077acafb1e5908f961a54abd18162fe19f7d378e32d63d8606b370f2a5e83a1fd299069b47f33a57be9320b9a0b7c722cd6ce8fabe3299ccb6892f38d7b08fe246eff3957cd981945a260e7196c54a6d484d1ae039c174d94c653b878317b00916a724c0ccb85e5439c7934b27a280c987aa950cb284562ab778075b5b25592e34679a6b72478", &(0x7f0000000340)=0xef, 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000440), 0x200, 0x0)


recvmmsg(0xffffffffffffffff, &(0x7f0000000200)={&(0x7f00000001c0)={0x0, 0x0, &(0x7f0000001880), 0x0, 0x0}}, 0x10, 0x0, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, &(0x7f0000001380)="c523c085fbd20ca7a5372b77e3b6b6b74e32d75f6c99d762a37aa412604954afab1a941717ef009f206016620a6fdc7db3513d0265848121a51d7e723257c8dc88c17059d621539e7fc09d84277fe81a278ca8ac795d89d8b77ffdeae05f5cd76e92bb770efa5c6cdfea1757b3b4addb84d9070935f4bc8044a40cf073441d5bc321fac46f29b6d7e92f43c915470df80f73c7849f3bf68cd318702d1e69fa0aa93d2a5a4cb3382e80b1aacdad092b3c0ebd73281062361aee3cdbae588841534994d33a9164bab0025e34e5adc9b362bb99b3a7b2e21180b9d8ea6bdf5eaae2a7084e21ed5729979efe203c81ae91b029c08c69aa1bc7391a415aa20417d2a1a442d9c762849190d92c87879e236facf4c2e8439b577461e66a287320f8de97902f074a8f13cf6296ebd05b7cb4850853378f50d330339deb4a4ef9ad41be0c046cfeed560d7c0d50d629c2284a25a332ecae137ad16693c144f9e9317836a1a99d23ba10b69b583d945aa51c56dea590da2bb55861a3099996fede9e9cca2ee78782b019bab2356e1543d6d3fcd3b276033bf970ef693f080f02e5f2dda4e8c649117f5096d1da44253918a04bbd42ad26d04999c71531147823727428f73a81d3f2e4cce3176e9792d73c75ea60648ec4746f7f1cb7e94cc3e788d8bd323ccd0fc2ecfe12d019fef2851adb124b302d8101d13ed769831e0e76da5c5f2d6776cc79c8dad51d61a55f953bd405a3d78c090448429b211aef40aae390c570f87753dbc7da4c42863700f5f0653ceeb50562ea0f3dd93551447313c47cf1ce04d8eaa6ded5d93371aac4dfc9a6e96246f8a7c8084dff544af22a3ef06ba58febc7f371a9e587780bcaedbcdc9fe72f85d481fd9053e8183fd2e2a6bbee71068abf24f242a55800c36aaff9094e7b1a7e7f258ae8359adc5752ed87752d9bd95c74e75d121bc48ee900a5942965dbf8cb746ff68bddda6e885a41101977fc232bd5699edf43f634f51c2cd0d62621047b1388dc28d988645c12a4834b81934624868889e39836f3a018908dfdcfe6b641af95936127f59ea4326f1fa483d61cf46d58dc4e857605ea34c8dc23e3889c3b25e9f48a2b11ef0c9d810eedc41559ec6c604396adfd4b2479242557ac43282c922afb8daaebccfb5f226cd44f101e95bd5384d7676771d44f64b095720da2f8c5645451fa9c124eb20567e3e0788a0789d26e2b8cdf902e767ab1dd14db5283adaf370d015ae85e76f260ddd57e7fbfb5dbcc8ca3234aaf2aa33d226f747959c14e75c672d8f5eb0db8a8a64a0c871fea7e13e0f5b1a82c2e7cafb0bf533e0c4822fad8e38157502ef98ec6a19c7da169982907417832ac1db4e72c7056a1b306001ef640e7ffcd8c1b0a6f73f150eb039639f6e38bbed372567b56485545bd27c182fad30276fbb01b767fda73ce7c8ac114e4f7f9d0e2c96b87bfef4018c91a3ea176159aa81a63573a504cdbc21d0f17cec16e437f879f75bd84d8257ae8b1e0d0c3b265e798e760acfe15de80f63b5416faa07b04cbede53c48e69a414c17bf25c2afd0eb8fe3c53f0cf5a07518c53e2d2e2618fdb8ae48413be9834f17118e1bb1c6aef97f6e215d41a385d4c9d78977115943e1205f6be3c619c4338422a0eb0a66d9748f233e67b9133d795244682d4a9fa649a0b0ec824e8fad5380c6b38661e04afb9b576d6c1b554e3e0500bacce05f5c8d213debd62eadd122512366287cef5ab8058ec36fd69d77e061d8f942c34f41aa6a7d852459ea8d70d0118d7e6e91bfe311c0facba8f221b1baa485d39dbe61ec76a14445dc5bd23f43eb804cf1be66812a24d985ffbc126cee33b91de56c4990c446332d61725056d6a5eb40a749d29f922c22c03f171f49", 0x53f)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r0, 0x80206980, &(0x7f00000001c0))


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = kqueue()
r1 = open$dir(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
kevent(r0, &(0x7f00000002c0)=[{{r1}, 0xfffffffffffffffc, 0x63}], 0x1f, 0x0, 0x0, 0x0)


pipe(&(0x7f00000000c0)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
dup2(r0, r1)
select(0x40, &(0x7f0000000000), &(0x7f0000000040)={0x7fffffff}, 0x0, 0x0)
read(r1, 0x0, 0x0)


sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f00000001c0)="55f8f5782087a072a82ec35f78d14780f518", 0x12)
pwrite(0xffffffffffffffff, &(0x7f0000000140)="a1070016060000c6386c7f000000", 0xe, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
getpid()
sysctl$vm_swapencrypt(&(0x7f0000000040), 0x3, &(0x7f00000000c0), 0x0, 0x0, 0x0)
msgget(0x0, 0x704)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc1206949, &(0x7f00000001c0))


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
writev(0xffffffffffffffff, &(0x7f00000000c0)=[{&(0x7f0000000280)="8d6b", 0x2}], 0x1)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x33}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000180)=0x66, 0x0, 0x27)
r0 = syz_open_pts()
close(r0)
syz_open_pts()
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)
r1 = kqueue()
kevent(r1, &(0x7f0000000140)=[{{r0}, 0xfffffffffffffffe, 0x55}], 0xc8b5, 0x0, 0x0, 0x0)


syz_open_pts()
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000040)=[{0x84}, {0x24}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


mknod(0x0, 0x20, 0x0)
sysctl$net_pipex(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = open(&(0x7f0000000280)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000028000/0x4000)=nil, 0x4000, 0x0, 0x10, r0, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
r1 = socket(0x2, 0x2, 0x0)
r2 = dup(r1)
setsockopt$inet_opts(r2, 0x0, 0x13, &(0x7f0000000040)="fd0cc085", 0x4)
openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x87}, {0x48}, {0x6}]})
syz_emit_ethernet(0x1b, &(0x7f0000000000)=ANY=[])
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
r4 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
pwritev(r4, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
r5 = open$dir(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
preadv(r5, &(0x7f00000012c0)=[{&(0x7f00000001c0)=""/224, 0xfffffdd5}], 0x1, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x0, 0x0)
open(0x0, 0x0, 0x0)


r0 = socket$inet(0x2, 0x8003, 0x0)
setsockopt(r0, 0x0, 0x7, 0x0, 0x0)


ioctl$FIONREAD(0xffffffffffffffff, 0x8020690e, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, 0x0)
socket(0x0, 0x0, 0x0)
sysctl$net_inet_ip(0x0, 0x0, &(0x7f00000014c0), 0x0, 0x0, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)
mprotect(&(0x7f0000ffc000/0x4000)=nil, 0x4000, 0x2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000200)={0x3, &(0x7f0000000100)=[{0x3d}, {0x15}, {0x6, 0x0, 0x0, 0x8101}]})
write(r0, &(0x7f0000000080)="2300110000fa4000805a099e20a0", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000004c0)=[{0x2c}, {0x45}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
chdir(&(0x7f0000000240)='./file0\x00')
setreuid(0x0, 0xee01)
rename(&(0x7f00000003c0)='.\x00', &(0x7f0000000400)='.\x00')


pipe(&(0x7f00000000c0)={<r0=>0xffffffffffffffff})
fcntl$setstatus(r0, 0x4, 0xc0)
r1 = kqueue()
r2 = socket$inet(0x2, 0x1, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140)={<r3=>0xffffffffffffffff})
r4 = openat$null(0xffffffffffffff9c, &(0x7f0000000280), 0x100, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f00000002c0)=[{{r4}, 0xfffffffffffffffa, 0x83, 0x0, 0xe7, 0x5d3f}, {}], 0x20, 0x0)
r5 = fcntl$dupfd(r2, 0x0, r3)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000240)=[{{r5}, 0xfffffffffffffffa, 0x95}], 0x0, 0x0)
kevent(r1, &(0x7f00000001c0), 0x9, 0x0, 0x9, 0x0)
r6 = getpid()
fcntl$setown(r0, 0x6, r6)
close(r0)


sysctl$vm(0x0, 0x0, &(0x7f0000000040)="c06d154be3aee5f8", 0x0, 0x0, 0x0)
syz_open_pts()
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x1, 0x0)
r1 = socket(0x18, 0x2, 0x0)
close(r1)
connect$unix(r1, &(0x7f0000000000)=@abs={0x682eb13985c518e6, 0x7}, 0x8)
r2 = openat(0xffffffffffffff9c, &(0x7f0000000440)='./bus/file0\x00', 0x80, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil, 0x1}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ff7000/0x3000)=nil, 0xd8}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil, 0x3}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000604000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000691000/0x2000)=nil, &(0x7f0000ff8000/0x4000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil, 0x9}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil}], './file0\x00'})
r3 = socket(0x800000018, 0x1, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}, 0x0, 0x8000000000000000})
bind$unix(r3, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
r4 = semget$private(0x0, 0x2, 0x86)
semget$private(0x0, 0x7, 0xb)
semctl$GETALL(r4, 0x0, 0x6, &(0x7f0000001240)=""/4096)
sysctl$hw(&(0x7f0000000200)={0x6, 0x18}, 0x2, 0x0, 0x0, &(0x7f0000000140)="01000000", 0x4)
ioctl$VNDIOCSET(r2, 0xc0384600, &(0x7f00000003c0)={&(0x7f0000000340)='./bus/file0\x00', 0x5, &(0x7f0000000380)='./file0\x00', 0x8})
writev(0xffffffffffffffff, &(0x7f0000000300)=[{&(0x7f0000000140)="f005c71031c1c5f421277b09000000000000007a091a2f47be787538ec7a89ec5ed66daa731ddc384ecc690869a0aa2266affdf772d7a360ee0f15fa664f557bb45071fe9b6d9d28e6e2589000f6a64f370b9e336987d77b38f7aada5309e46a81e0e2efa087aa9f5f89934fdbd2ed96e7234b8972b273e810ca9962a8f461d3a05711a63027321ff62c", 0x8a}], 0x1)
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x4e, 0x0)
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x10000, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r6=>0xffffffffffffffff})
connect$unix(r0, &(0x7f00000002c0)=@file={0x0, './bus/file0\x00'}, 0xe)
socket$inet6(0x18, 0x3, 0x0)
ioctl$FIONREAD(r6, 0xc0106924, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000400), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000000)=[{0x20}, {0x2}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000340)=ANY=[])


sendmsg$unix(0xffffffffffffffff, &(0x7f0000002640)={&(0x7f00000013c0), 0xa, 0x0}, 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
minherit(&(0x7f0000003000/0x2000)=nil, 0x2000, 0x5)
r0 = accept(0xffffffffffffffff, 0x0, &(0x7f0000000140))
accept(r0, &(0x7f00000002c0)=@in, &(0x7f0000000340)=0xc)
sysctl$hw(&(0x7f0000000000)={0x6, 0xb}, 0x2, &(0x7f0000000140)="d5bd0d1d2d9ffee9de25ae00029927", &(0x7f0000000040)=0xf, 0x0, 0x0)
chmod(&(0x7f00000000c0)='./file0\x00', 0x21e)
getsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x15, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSDLT(r1, 0x8004427a, &(0x7f0000000040))
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
mknod(&(0x7f0000000100)='./bus\x00', 0x80, 0x80b)
open(&(0x7f0000000380)='./file0\x00', 0x200, 0x8f)
unlink(&(0x7f0000000080)='./bus\x00')
sysctl$kern(&(0x7f0000000300)={0x2, 0x7}, 0x2, 0x0, 0x0, &(0x7f0000001440), 0x0)
fchmod(0xffffffffffffffff, 0x0)
shmget(0x0, 0x2000, 0x9, &(0x7f0000001000/0x2000)=nil)


r0 = socket(0x2, 0x4001, 0x0)
mknod(&(0x7f0000000000)='./bus\x00', 0x3a0914c44f7b202d, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
r2 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
poll(&(0x7f0000000ac0)=[{0xffffffffffffff9c}], 0x20000000000000d7, 0x0)
poll(0x0, 0x0, 0x1000)
close(r2)


syz_emit_ethernet(0x2e, &(0x7f0000000140)={@broadcast, @remote, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x1, 0x0, @local={0xac, 0x14, 0x0}, @multicast2, {[@lsrr={0x83, 0x3}]}}, @icmp=@generic={0x8, 0x0, 0x0, "e10f46cf"}}}}})


nanosleep(&(0x7f0000000080)={0x204}, &(0x7f0000000040))
open$dir(&(0x7f00000000c0)='./file0\x00', 0xae828e137847f62, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r0)
execve(0x0, 0x0, 0x0)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chflagsat(0xffffffffffffff9c, &(0x7f0000000140)='./file0\x00', 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000004c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000280)=[{0x48}, {0x25}, {0x9106}]})
syz_emit_ethernet(0x42, &(0x7f0000000640)=ANY=[])


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000480)={0x0, &(0x7f0000000240)})
pipe2(&(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff}, 0x0)
readv(r1, &(0x7f0000000280)=[{&(0x7f0000000040)=""/124, 0xfd00}], 0x10000000000001bc)
write(r0, &(0x7f00000000c0)="c3", 0xffffffed)


mkdir(&(0x7f0000000100)='./file0\x00', 0x49)
chdir(&(0x7f0000000340)='./file0\x00')
setreuid(0xee00, 0x0)
r0 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r1 = getuid()
fchown(r0, r1, 0xffffffffffffffff)
r2 = getuid()
open$dir(&(0x7f0000000180)='./file0\x00', 0x200, 0x0)
setreuid(0xee00, r2)
unveil(&(0x7f00000001c0)='./file0\x00', &(0x7f0000000200)='x\x00')


r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x20000, 0x0)
ioctl$VNDIOCGET(r0, 0xc4104603, &(0x7f0000000180)={'./file0\x00', 0x8, 0x0, 0x6})
openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
mknod(&(0x7f0000000080)='./file0\x00', 0x6000, 0xe02)
r1 = open(&(0x7f0000000180)='./file0\x00', 0x200, 0x10c)
poll(&(0x7f0000000100)=[{r1, 0x4}], 0x1, 0x0)
close(r1)
openat$speaker(0xffffffffffffff9c, &(0x7f00000004c0), 0x2, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1", 0x1, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x1, &(0x7f0000000280)=[{}]})
mmap(&(0x7f0000689000/0x3000)=nil, 0x3000, 0x1, 0x3010, 0xffffffffffffffff, 0xaa8f)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000680), 0x2, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
mkdir(&(0x7f0000000080)='./file0/file0\x00', 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x1, &(0x7f0000000140)=[{0x4}]})
syz_emit_ethernet(0x4a, &(0x7f00000000c0)=ANY=[])
r2 = syz_open_pts()
ioctl$TIOCCONS(r2, 0x80047462, &(0x7f0000000040)=0x10001)
r3 = socket$inet6(0x18, 0x2, 0x0)
ioctl$VMM_IOC_READREGS(r3, 0xc028756b, &(0x7f0000000000))
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x36}, 0x4, &(0x7f0000000080)="ab157888df3ccd154815a7bde7b1e1b4", &(0x7f0000000140)=0x10, 0x0, 0x0)
pread(r0, &(0x7f00000005c0)="320d5eafc5c8098f315da5d422c7db6fe31351ceb38e5065f6e203497ecf0ad57d820d54210dfff8668f43ad55702275e271c7d7405ce268ee3ffc2e90d062b6f14a2d29ff646e1ef137df4d40b22ee532d3297dea90e859c4a91f9f840e10b4de3956bc0beda56dc595c587139af6a09c5b21e9d5a33ac64a44", 0x7a, 0xffffffffffff7fff)


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x4, 0x1100, 0xffffffffffffffff)
getrusage(0x0, &(0x7f0000001500))


mknod(&(0x7f0000000000)='./bus\x00', 0x2000, 0x6380)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x6381)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
open$dir(&(0x7f0000000e80)='./bus\x00', 0x0, 0x0)
read(r0, &(0x7f0000000440)=""/153, 0x99)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000180)=[{0x3}, {0x5c}, {0x6}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000340)={'tap', 0x0})
syz_emit_ethernet(0x36, &(0x7f0000000240)=ANY=[])


r0 = socket(0x2, 0x1, 0x0)
r1 = dup(r0)
syz_extract_tcp_res$synack(&(0x7f0000000040)={0x41424344, <r2=>0x41424344}, 0x1, 0x0)
syz_emit_ethernet(0x14b, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x13d, 0x0, 0x1}, @tcp={{0x2, 0x1, r2, 0x41424344, 0x1, 0x0, 0x13, 0x4, 0x2, 0x0, 0x233, {[@generic={0x2, 0xd, "96c729637cae4fa49c1558"}, @sack_perm={0x4, 0x2}, @sack={0x5, 0x1a, [0x4, 0x0, 0x40000001, 0xde5, 0x2, 0xffffffff]}, @timestamp={0x8, 0xa, 0xb018, 0x8}, @generic={0x4, 0x2}]}}, {"d1c2f0bfe2d0786ca28e44289f59aba04d62ff16e6bb47f1cd981d0cf5f225560531db5a3a6c3cb3d5ac50e0eec7423f3ef5e3c4a13f81f14f843a32b529e4649b57d581159522ddf03a6cabf358af4e1ae7ab79a9aac6417859ae29d8de08ba3da1e6387381a61f166b78d7ae58ccd15a08555c8e7db3e261cbba4f565ff3567edfcacd1a43a2f80b44a3727c2f46723f3826d9842357f4d467cb2e24ed586547d107e74cfe46502dde741762fe8ad6742200cf5fd16fcdadae4fd744b730286383e0444647e948151cb63c5c12b79f75a37762e3f013f189799eb699"}}}}}})
syz_extract_tcp_res$synack(&(0x7f0000000000)={0x41424344, <r3=>0x41424344}, 0x1, 0x0)
syz_emit_ethernet(0x1306, &(0x7f0000000040)={@broadcast, @local, [], {@ipv6={0x86dd, {0x7, 0x6, "cbe4c8", 0x12d0, 0x1d, 0xff, @empty, @mcast1, {[@dstopts={0x8, 0x1, '\x00', [@jumbo={0xc2, 0x4, 0x9}, @pad1]}, @routing={0x29, 0x8, 0x0, 0xff, 0x0, [@empty, @remote={0xfe, 0x80, '\x00', 0x0}, @remote={0xfe, 0x80, '\x00', 0x0}, @mcast2]}, @hopopts={0x61, 0x30, '\x00', [@generic={0x80, 0xb9, "44f94a03e6d05b56744bcc7494d65765677243e390522f36c6cacc615a14090a256af3332438d8c9bb7cc463117d53e055d8e29afd6532b77ca0ee825ca79c29d4f6fc4fdc53b2fbe01214ed2abd027f318c6bac4de360e8e1ba7e6c6f6fa5a8578593a59b3b1293fbca9e68d8a2ca2ca61bae879d04f2131246ab47592cb9f86d0fb14ccccf81a44239a82869c3b2f2184e908da082304e2d027380863a933fb3074b863ebd1ebfe230f779b0690c1592bac268c69d50b4c9"}, @padn={0x1, 0x6, [0x0, 0x0, 0x0, 0x0, 0x0, 0x0]}, @generic={0x1, 0xb5, "f2948f44e98cddc438b2d875924ac0c4e1822c87128c404ca7aff2d8f209b34e461cc21a3186058cc534158ef208df8fd74db74ec6d03d1a41c6e35d4292620a6840df072ea66f26441480e845659eba6fe78373a9d03d145eec08f57056de13c0a96214ba7347561bef6722326e4160f31c10d3320601a44bf2cc17a7b80db5f2fcb72d3a02139ba4d9516ddf86ef7845dc31f3ba02db94aab85147f777ea83c857acf26a810cb747a5a8de295b7a898e69069166"}, @pad1, @padn={0x1, 0x7, [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]}]}, @routing={0x0, 0x12, 0x0, 0x0, 0x0, [@rand_addr="1a47c3d9ecf6d9e681110e71aa428bd4", @mcast2, @ipv4={'\x00', '\xff\xff', @loopback}, @empty, @ipv4={'\x00', '\xff\xff', @multicast1}, @mcast2, @loopback, @mcast2, @local={0xfe, 0x80, '\x00', 0x0}]}, @hopopts={0x5, 0x3, '\x00', [@padn={0x1, 0x6, [0x0, 0x0, 0x0, 0x0, 0x0, 0x0]}, @jumbo={0xc2, 0x4, 0x7fffffff}, @ra={0x5, 0x2, 0xffff}, @pad1, @enc_lim={0x4, 0x1, 0x9}]}], @tcp={{0x1, 0x3, r2, r3, 0x1, 0x0, 0xa, 0x0, 0x0, 0x0, 0x7, {[@md5sig={0x13, 0x12, "270689750c172377a96c7793bae952b2"}]}}, {"25519b9bf62d4104ebffa0129a45c74375c7da5af43a77565503e7df9cad892673f22f8a175241ad5a65e438baeef3dd91a797e6abc24ee0f61e74c940daa6cd941c981cc0b3ecf8ce512e2133a242b5c562d672dfcde899c9b0e3351a69b0302dc6dc9b0826850b2a094cbb794ed13e8d0ba7d51e9e895f8a4c58845e9c477ecfd462c2729625e28d28416ef10cbb78d6a2e44eeeccef4c515594890b6aaea10df999d60c23f243737724779122b4601524b5e926e08aba131b09cea33580d1066580da17e9df243ff5384758c44f8237905330412e3b3b35df85acc22ae1d2d71755d8010b289f33a91c65ef3181003767d22a2a10a2e69a75a09f6a76df96f651474886a59973477e2060cff855e15ccdfae50b135843fadfa16c6931d26fb37d3078ea825b97ae5c81dea9e2b3c4ce83482615776df2f9629bbe1a7bb8324f78eff85051389ea3130b006e04d04fdefaa311e3e74b33884f4d4db272f30836b52bb545ee57a1510a6afadd46da758fe3a3561e066ea6b3761963ab57add771a4e2f2de77556d5ec0366942783c401f4590cf4b08182c3455159f52d6c8c5c419f11d36efdded8b209b3104e826eb1e58cf3aeda05fd34921017896c6912abf2218cd89f903968fb383f8c9da00e5ff2b427600856fe5f57bf1b68b5c5143aae714fac59f626346e93a72d15d0c0d98820c886ce1ccd5cc9c08ab22c39e2c70cd52fa2f3a9f776862c2304c72c3297ea89968b4aebea7292655f7dd1d773c30d0b73586d7e049b494ad3dc3db6c14518b8d56b343dae39ff1f4abe6a18adb8f3568b3ee8fc3d319523482cb418141a75c8f1270fabeaf325dfd5eb39934f5a07a969a3e24ec36332961e8927ab668cf110f1ff0bd44aca538ea07a7666d4e68bf6ebba95fb3c90b97aed3529e343f7e088a8eb52c584c8bd28a7743e946d05cb86150823701e67d63774842958b8e289b8cd1ea1f88a79e6f55b59ab51853b1faf3d86173ab8adc96dd7ac768041e3566f8376b12598ee3e738e2941159cfb961eeb50c2568fc0d37e9e3c346d427e68e3603c6b5ecb3b8da7345dc7fff1907325818ac5f253f4cf1139acdd623b45025b779dab9f4b29372306666cc43c98efe82b15194d3fe9c616daebb2d9fafcc8401f964c11316293a417067a5ad442ba7638e61dce30d8cbc57e4dd68a1c243615f93c490765e48baf29ef8aad87793eea516b8096e052e52bdcc57097a91c29b5fa2ad9668e615d596cb1965ea69e6ff89faa24c54f209261693e95a2b3cd2b0e584321651ac2ba756c94e0ad184b76e01dae0edcbfb5f97d3f87b143925cb00ca4438ce6b8935cbb02aba359dc2435351d2bf42c1d9b1096933fc752aa836555111decf1a5f00f6fa88d1754076c21859d6afc17fb84f19517a5bd05179154a3039bd25529d5123d63cb98b0c9941d8ab6df2a4a377d4540b782d026b1d72d76c46b80c326f614e69aa605f00e2d669f34073de508466176afa4067b142f5d1758237c179c97a8e18f80a0d714996e17ec699c625590063ac12cd74b346c63730d0702db1afaa956779a87b95128f965c8fce6408dec00beb3e11bcd456202d5759c577b0972b834a9be9cf45ab617ad1e6798ee01d7bc3125aa686793cf573563d3e7c30f4e4fed2fd357436ba713a64d313f6e96bff5f29210bd04c79e1478171d59e9dfd595cf58792b009da9f619a086925049eb397b342a4719e6dd35373428f03ee66119c10119a6ac49267a411fb71929826f6afca4c2706b4be7e4da60e03070d0b8bd9909564a1a1ad32769bb371bf0cd000c96b19d245193435cda9968c7a4c42e6290aa62e46551c1865afcdba64960f053ec93112657e3649cea15f53cc6d336c9ef9fe0b9a366ba3e38681a89fbd87006372db3fdf3457d8cce4457c857ade3473a98992cc8eba781f50dd2f956dfea0bd30354fcb2fe63746103648c2169b50f171510b54866355a2dea9ee99764df8993106c9897e122f627435a88da40a57bd337aff54cba5e35902b81a2189bdb03be2af66d6367a1cd1ce29648a553225f1fe22cce348df67865d3a7b43a3cb5016294c900d41cc75ff03479fd10c1a734962cda78fdb846d5d4d158ee4f6f78d282ffa6cc5a796434c284311c33ec3cd4c781957f88a6c2d7f2887fcce026da25fd20ba99ec66caefcbbd481dc48419bb0f3264e70075d88879f69d84e54fe4b505d071c59ee8c726a778e9cd4c39706ffc79aa652db414ea2a55020d384bc4dbd1954cf5c134cb6d41d44a7fa3c0faad69f2b664b7976308339d7ea1ffc4e3340ecd68bfdea0092e56609e96204ce4c0a6890954fae06502a87831499477db2bbebb2b8bd967b34ca25166a6762f0dc10923c133ad315f3ae290dfccee6a46e03d000efb29b92dd132a73e6cbd0335218b48b2bfbe9c61178609c8d6d69163e10300fdea039680dbfe023b12cdacf4f9bb2131cd6b8a34747e57dd580ee88dd86a3095421cbd0f8c49b8b91bfd8daf56025646ea38019d1a8203c39fb2e3d22f76e84e9a4726cb4aff1fd2699cc5bca98e664bcb27865ce480524fa867bfcd94ff39797eddedbb0fcc92f6dc6b5669a5c61f771e0ec56318365e82034fbba46d04beea15b115a8ef5b1a8582dde1096dd527df5700a45c251878e04b3ca3dd815f072708080ae44da19c6513761e3783de71a1de11a036542b3206e80710a0d153b7bf61386f8d5f189db5081ccb31bacb9f64cef283a5fbb4cceb628ee62534eecd11b4891abe2d8f4a59276ac1a18178c63cd7d6d13b12df1590953c970f1824d04565be2200d21afa95fa309ba07b0623b6364038f0bec68cebc2879d36880a17b9d9ae8e805bb7d8e0a7a8b46461001a35d20c6ae2afb7cb5ac1b7c8916d80f8b3ba51d9dea9fd185c78f2e542f20193b673283daf212e96d40c9651c72f3e47771fd7fee65d28fa4f607a0ef453c1d9a2772714b39fe11581363be428ec956cdbd18772fa259c777ab5ff7c807bfeaa3e72cc73fdab77dad775b9a816f68e9fb1cbcddb8427d26096a4df566edcb3b3fe278de0936e443f214a635ad33d54503730c6e8d6eddd04ff531177809d4b0e2cdd255d49a7a42a9aed53e1970340189535f3bdf0e7c00f3c8f3379839f379521d94bfc12f1cafdfc58fc5e05a04ee1861b77d00f91837dbbb0e21167b5a13e2540561324b94a5c443a620bc75f2621af8fae038593002d2351e1856e3fabcb5b570b0db962ec8795cf11ff9491611f056f8b2a4c2546e62807d4fcea1cb633a87246b2e154b3c5ef230a56c655f30f8dba19a9199d2359b991a99b4b72507014d2aa0c6354b4f6525e48f7d75e94571bcf2436a10d48aa317ec3eb4a2b42ec5703e3148d8c3960172da9c1ac07543d44759987beecbb4a34743b7641955cda5ae9422ab0047a22090e649ceb5e163d32cc0548f050013b0b8c90ccf0994cdb6e45f629f10d3c6f084f1ec5e4855c3513ddf2de4ca4c239bd78de5d4f7c3b2f7fa5da5fe31960a04a6933010ad2965ead39e43039c49e2011626723d1e411f0bfa7bbbe342ac39a55b2d182f2bb7d50af6dafd3724d46ff5450f5a3c682fe9ae0921353ff3a5feb9fa24806ba5cfccd8fd471c92b48bd45bf0090b3710d679df6dc40c64d1b4ae77b54aee4051efcfba9669457850c5f59b02fbebac1cc79a935ddf30a57d01a1f1c313ed013459a1a49b3512a682b2d95adfb02ad58e778ca39283a16e658c8a37bf9376548db240696a8edb1ce8a9485d90a12ecc3bd9b0ab06cb338a8dd738f46dac5f2a58fecd3fa32d83877e90ec982830d58f0ad27b8a459d0c8d8d17592714770c9b995f628bcf5b8f05f9d84b72507cbaf31e33f8aa7d051e079b47f99af7720f543de0beceb3d716e77c57a075519cf91edce9684862b1a77ae7df3bf7a74bd3a51363459217680829c112fc2fd773a52103dc99a2dd4bae98b2677e1eca8429ca7069b83c0e450044bcf499c7ac32bcb95f1e22e96cbc094bae636a99eab5e9663cfeeeda97ebc4057c098f6986d760699a65d123c0f89c900df589384223b7609f7fe2938e3d1889d67fd4d610db69d1fbf10e57154b11a9d54a2c354bfea974eca068e39c442764c2d4ee0bb40e621720f0edc78ed6bcf16824073b8e350e932b6bd18c4ca05ccd5dc373d20e066017505fff1a6943f4b9d2cdf5117db7ae4a785044387d89081c6218bb7013522baf50c725d3c901a467c88fd9be4ced967a6962073f0416810cd34fea41ddaed728aa0a866d63d583162e1e78305c9a6aafff3fbc9408b740ad7afb90f3c1b41bdd3ae11929f2790719fd87038020c3d1ee76c62ed7820a2f79e4d50256abb058218e2360b29ab44332dbc7f83f5add426ae3c409f688b0c0a594916480c05df307a85b0ae95652cf06b2b6aeea979e078c206f70c7fdbd2fc0657deacf489c5f2090882eecb4c47d0b2fd438cefa90470ea1c7ca0c9e31dec634a9a61d3e5736ba4a657fd5a7a8a9f918704ca455a24fb407efab8331d34f0db65dc00a377ae12b5bc6ff2f6c7d46d9ceffb436e5fc079570f1049b507cea766cab28d5c1a88d3dc205f3d6bb1ff76da8ec4f7a048aa7b96290319061a41d8c1011ed695f7bb9d253190d0d0b38a10fe40c4357ed3dd930277849299ae65c01a71ab6a061312a75827bca02321444cec5d323a46bce50b43d9c6ce985817e00f148f953fddab6f0216f71acdda012cbc0de70f9c9ba0495024cf2148ab09bc0897b3c4adc54fb1f534b0c6ca72f2aa885cf880ccb9402076aeeee21515f7c9019aee5855e3dc00a68ba124d13ac56e128e49bb5537267d08a48c53c31b5083900c89be501b74aa62dc4b137c9a87d8c299e4391d327be72b9394017c16bae2602a7dad27cb50cea1ad8136b7bcd645d023f95022deeda81aa3d598e6c84071c59a2d6c4124ecd03877f4819e76225bfc198e174d36b1c79de2ae88f1be383ba4297f7048967a1c7a94f58c0661e9586b1184c7c9e6d0ee43d25a65aad6705fed257de525d4e5529902792b36d8e9f2fcf9d2c3458107ca3c5c7b4488b3a31a7e6814437f7977ea17c627035ea29e94790ca07454194541f5228ae76c25eade51aab1f4ea8a1e3af9f88b955e90dc6cade02ac99e54604fb5f10df1523e8dda4a416c34ac1e6713ce88418e09b597879171c2e0648302c36d19792955843253ab72b3b4665ab93f5f3ebfb5ff075e7e300f908f6c244212d6b37ba39e78a4e121e8e1e03eec62f67cdc3239669907161dcb092727183422d5a8aa01028ab8ec9daec0ede9e8d0f6a0ad8290e52ea9036f09271d155595d6ecb518ce74bc528596967b520cb092567df5d008f38c4dc9c2b8e3c4da7d81ca9b754d38a94b62b4ce3712383f680986aab3c5412d7f441d4fe878ec34e65e3c61a94c2e32f58050cdbf772eddce64d3ea8b99d6f6783a8da9436fb48c19e50e031aef2d1da08b6fa587d3466c0fa66a8395f35baae636d91f15e020c8c81d10a27e9b2543c460f6ee595a30dca0fbc86762a12122a68b7a278c7ba2f18119aaed9556e9d62195a6ac210702be0ff204ea543446f356a0ee618282504016a419542e5ff850f8c35715f3d43e44bbe63757878a362691232d3e2a69be997f1ce9955bce475f6e6208a0fc136f0b0318eaae86dd8b4bd7e8cb6ae75a26150065e99b3cf155bc45a2490ff8c7772889f008b327d885690c85252f8acf988488a7cdea12075c1fbe7ebdf440660b902b3c33681cac04f57f8132d"}}}}}}})
listen(r1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1023, 0x0, 0x0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
writev(r0, &(0x7f0000000440)=[{&(0x7f00000004c0)='P5', 0x2}], 0x1)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xfffffffffffffffe, 0x0, 0xffffffffffffffff})
r0 = socket(0x18, 0x1, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x8, 0x51})
r1 = syz_open_pts()
close(r1)
syz_open_pts()
r2 = kqueue()
kevent(r2, &(0x7f0000000040)=[{{r1}, 0xfffffffffffffffc, 0x1}], 0x3, 0x0, 0x8, 0x0)
syz_emit_ethernet(0x2e, &(0x7f0000000400)={@local, @broadcast, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x1, 0x0, @remote={0xac, 0x14, 0x0}, @remote={0xac, 0x14, 0x0}, {[@lsrr={0x83, 0x3}]}}, @icmp=@echo_reply}}}})
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


kevent(0xffffffffffffffff, &(0x7f00000001c0)=[{{}, 0xfffffffffffffff9, 0xc7}], 0x0, 0x0, 0x0, 0x0)
r0 = kqueue()
sysctl$net_inet_tcp(&(0x7f0000000140), 0x4, 0x0, 0x0, 0x0, 0x0)
kevent(r0, &(0x7f0000000140)=[{{}, 0xfffffffffffffff9, 0x2c5d36d679bbffbf}], 0xe4a, 0x0, 0xa9fa, 0x0)
kevent(r0, 0x0, 0x0, &(0x7f00000001c0), 0x9, 0x0)


r0 = shmget$private(0x0, 0x1000, 0x0, &(0x7f0000ffc000/0x1000)=nil)
munmap(&(0x7f0000ffb000/0x4000)=nil, 0x4000)
shmat(r0, &(0x7f0000ffd000/0x1000)=nil, 0x0)
shmat(r0, &(0x7f0000ffc000/0x4000)=nil, 0x0)
shmat(r0, &(0x7f0000ffb000/0x3000)=nil, 0x0)
mlock(&(0x7f0000ffb000/0x3000)=nil, 0x3000)
mmap(&(0x7f0000ff9000/0x4000)=nil, 0x4000, 0x0, 0x1810, 0xffffffffffffffff, 0x0)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0xa, &(0x7f0000000040)='\t\x00\x00\x00', 0x4)
r2 = dup(r1)
dup2(r2, r0)
setsockopt(r0, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


socket(0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
sync()


setrlimit(0x6, &(0x7f00000000c0))
open(&(0x7f0000000100)='./file0\x00', 0x70e, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x100, r0)
r1 = socket(0x800000018, 0x1, 0x0)
r2 = socket(0x18, 0x2, 0x0)
r3 = socket(0x800000018, 0x1, 0x0)
bind$unix(r3, &(0x7f0000000080)=@abs={0x0, 0x7}, 0x1c)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
bind$unix(r1, &(0x7f0000000180)=@file={0x0, './file0\x00'}, 0xa)
r4 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r4, 0x0)
setrlimit(0x3, &(0x7f0000000140))
mlockall(0x1)


r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f0000000280)={0x0, 0xcb, 0x0})


r0 = kqueue()
r1 = kqueue()
poll(&(0x7f0000000000)=[{r1, 0x1}], 0x1, 0x0)
kevent(r1, &(0x7f0000000080)=[{{}, 0xfffffffffffffff9, 0x6b, 0x11}], 0x3eb8802, 0x0, 0x0, 0x0)
dup2(r0, r1)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000180)={0x2, &(0x7f00000000c0)=[{0x4000}, {0x5}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x2c}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0xfffffffffffffef1)


minherit(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0)
munmap(&(0x7f0000ffd000/0x1000)=nil, 0x1000)
mquery(&(0x7f0000ffd000/0x2000)=nil, 0x2000, 0x0, 0x0, 0xffffffffffffffff, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
mknod(&(0x7f0000000000)='./file0\x00', 0x1000, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
setreuid(0x0, 0xee01)
open(&(0x7f0000000080)='./file0\x00', 0x1, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f0000000100))


mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
rename(&(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000f40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
lstat(&(0x7f0000001340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
rename(&(0x7f0000001140)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000240)='./file2\x00')
symlink(&(0x7f0000001b80)='./file0\x00', &(0x7f0000001440)='./file0\x00')
unveil(&(0x7f0000000440)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000100)='r\x00')


r0 = open(&(0x7f0000000080)='./file1\x00', 0x200, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x9, &(0x7f00000000c0)=[{0x9, 0x0, 0x40, 0xe1}, {0x1}, {0xff, 0xc7, 0x1, 0x7fffffff}, {0x1, 0x6, 0x1}, {0x1, 0x6, 0xc}, {0x1ff, 0x4, 0x4, 0x40}, {0x5, 0x6, 0x69, 0x7}, {0x9a11, 0x1, 0xfe, 0x6}, {0x5, 0x20, 0x0, 0x1}]})
mmap(&(0x7f000000f000/0x1000)=nil, 0x1000, 0x0, 0x10, r0, 0x0)
r1 = socket(0x18, 0x3, 0x0)
r2 = syz_open_pts()
ioctl$TIOCSETD(r2, 0x8004741b, &(0x7f00000001c0)=0x8)
execve(0x0, 0x0, 0x0)
ioctl$TIOCSETD(r2, 0x8004741b, &(0x7f0000000040))
execve(0x0, 0x0, 0x0)
setsockopt(r1, 0x1000000029, 0x24, &(0x7f0000000000)="5ab7776a", 0x4)
mlock(&(0x7f000000f000/0x4000)=nil, 0x4000)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000280), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{0x40}, {0x4}, {0xcc6}]})
syz_emit_ethernet(0x138, &(0x7f00000004c0)=ANY=[])


sysctl$hw(&(0x7f0000000000)={0x6, 0x1c}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
sysctl$kern(&(0x7f0000000000), 0x2, 0x0, 0x0, &(0x7f0000001440), 0x0)


sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x12}, 0x4, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$net_inet_tcp(&(0x7f0000000040), 0x4, 0x0, 0x0, 0xfffffffffffffffe, 0x4)


pipe(&(0x7f0000000100)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
pipe(&(0x7f00000000c0)={<r1=>0xffffffffffffffff})
fcntl$setstatus(r1, 0x4, 0xc0)
r2 = kqueue()
r3 = socket$inet(0x2, 0x1, 0x0)
socket$inet(0x2, 0x1, 0x0)
kqueue()
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000080)={0xffffffffffffffff, <r4=>0xffffffffffffffff})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140)={<r5=>0xffffffffffffffff})
setsockopt$inet_opts(r3, 0x0, 0x1, &(0x7f0000000380), 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000080))
r6 = openat$pf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
r7 = openat$pf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000080))
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000080))
r8 = accept$inet6(r0, 0x0, &(0x7f0000000000))
r9 = openat$null(0xffffffffffffff9c, &(0x7f0000000280), 0x100, 0x0)
r10 = socket(0x18, 0x2, 0x0)
setsockopt(r10, 0x1000000029, 0x38, 0x0, 0x0)
kevent(r7, &(0x7f00000001c0)=[{{r6}, 0xfffffffffffffffd, 0xc0, 0x2, 0x5, 0x99}, {{r8}, 0xfffffffffffffffe, 0x28, 0x20000000, 0x9, 0x9}, {{r1}, 0xfffffffffffffffa, 0x8, 0x40, 0x689}], 0x20, &(0x7f00000002c0)=[{{r9}, 0xfffffffffffffffa, 0x83, 0x2, 0xe7, 0x5d3f}, {{r4}, 0xfffffffffffffffe, 0x24, 0x2, 0x1, 0x1000}, {{r10}, 0xfffffffffffffff8, 0x40, 0x40000000, 0x1, 0xcf6a}, {{r5}, 0xfffffffffffffff8, 0x22, 0x8, 0x1000, 0x1000000}], 0x20, 0x0)
r11 = fcntl$dupfd(r3, 0x0, r5)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000240)=[{{r11}, 0xfffffffffffffffa, 0x95}], 0x0, 0x0)
kevent(r2, &(0x7f00000001c0), 0x9, 0x0, 0x9, 0x0)
r12 = getpid()
kevent(r2, 0x0, 0x0, &(0x7f0000000000), 0x2, 0x0)
fcntl$setown(r1, 0x6, r12)
close(r1)


r0 = socket(0x0, 0x0, 0x0)
getuid()
setreuid(0xee00, 0x0)
getgid()
geteuid()
r1 = socket(0x0, 0x3, 0x0)
connect$unix(r1, 0x0, 0x0)
getsockname$inet(r1, 0x0, &(0x7f0000000000))
getpgrp()
getsockname$unix(r0, &(0x7f0000000100)=@file={0x0, ""/72}, &(0x7f0000000200)=0x4a)
geteuid()
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000080), 0xc)
r2 = semget$private(0x0, 0x4000000009, 0x82)
semop(r2, &(0x7f00000000c0)=[{0x1, 0xffff, 0xe5ce97ab354d96be}, {0x4, 0x4}, {0x3, 0x0, 0x1000}, {0x4, 0x4}], 0x4)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
r3 = socket(0x800000018, 0x1, 0x0)
bind$unix(r3, &(0x7f0000000080)=@abs={0x1f95d27d48731892}, 0x1c)
setsockopt$sock_int(r3, 0xffff, 0x1021, &(0x7f00000000c0)=0x5, 0x4)
semctl$SETALL(r2, 0x0, 0x9, &(0x7f0000000040)=[0x7ff, 0x1000])
semop(r2, &(0x7f0000000180)=[{0x1, 0x1, 0x1000}, {0x2, 0x4, 0x1000}, {0x4, 0x3, 0x1000}], 0x3)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x31}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)


socketpair$unix(0x1, 0x1, 0x0, 0x0)
open(&(0x7f0000000180)='./file0\x00', 0x20000, 0x4ebfac6bbaf796c)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000001180)={0x3, &(0x7f0000000040)=[{0x4}, {0x48}, {0x6}]})
syz_emit_ethernet(0x7e, &(0x7f00000002c0)=ANY=[])
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCLOCK(r1, 0x20004276)
seteuid(0xffffffffffffffff)
ioctl$BIOCGDIRFILT(r1, 0x4004427c, &(0x7f0000000080))
r2 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
writev(r2, &(0x7f0000000080)=[{&(0x7f0000000000)='#!', 0x2}, {&(0x7f0000000040)="18", 0x1}], 0x2)
r3 = msgget$private(0x0, 0x0)
msgctl$IPC_RMID(r3, 0x0)


open$dir(&(0x7f0000000000)='./file0\x00', 0xf02, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, 0x0)
open(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
close(0xffffffffffffffff)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x2, 0x2, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCPROMISC(r0, 0x20004269)


ioctl$KDSETLED(0xffffffffffffffff, 0x20004b42, 0x0)
syz_open_pts()
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000200)=[{0x4}, {0x40}, {0x812e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])


socket(0x11, 0x3, 0x0)
socket(0x11, 0x3, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0x0, 0x0, 0xffffffffffffffff}, 0xfffffffffffffffc})
socket(0x0, 0x0, 0x0)
r0 = socket(0x18, 0x0, 0x0)
getsockopt(r0, 0x29, 0x31, 0x0, 0x0)
socket(0x2, 0x2, 0x0)
sysctl$net_inet6_icmp6(&(0x7f0000000580)={0x4, 0x18, 0x3a, 0x3}, 0x4, &(0x7f00000005c0), 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x42, 0x0)
syz_emit_ethernet(0xe, &(0x7f0000000100)=ANY=[])
syz_emit_ethernet(0x26, &(0x7f0000000280)=ANY=[])
r1 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSKBDIO_SETMAP(r1, 0x8010570e, &(0x7f0000000040)={0x19be, &(0x7f0000000080)=[{}, {}, {}]})
ioctl$WSKBDIO_SETENCODING(r1, 0x80045710, &(0x7f0000000100))


setuid(0xffffffffffffffff)
r0 = socket(0x1, 0x1, 0x0)
fcntl$setstatus(r0, 0x4, 0x40)
r1 = getpgid(0x0)
fcntl$setown(r0, 0x6, r1)
shutdown(r0, 0x0)


r0 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r0, &(0x7f0000000000), 0x10)
write(r0, &(0x7f0000000240)="14bdfa5d1d34e2fecb284a6498307dcda9aec43050036123339a346f737850551408753f95b7688ad4c4e1dd5489e7bafc58d3e5823757ae8b630719ef187ccad995f13dbe19a6dd4e6902bd8297b0799b426aabe9fad9db6996571c6d9f8bb5d542c2148aa42be940970fe88d34d8f99afe7e7820237400000000008000000100"/138, 0xffe8)


symlinkat(0x0, 0xffffffffffffff9c, &(0x7f0000000380)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/file0/file0\x00')
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


sendmsg$unix(0xffffffffffffffff, &(0x7f0000001280)={0x0, 0x0, &(0x7f0000001200)=[{&(0x7f0000000180)="bf3b684c5ae963b4567084e096cf973983b85e5df63e013eaa9405095e88157332b4f68e78e0793d3e30417acbf4419893cfd424b75262dc5ade2ab6278ab86672f9ed186987b8c19d9295a17b98020f6002", 0x52}], 0x1}, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206913, &(0x7f00000001c0))


select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x3, 0x0)
bind(r0, &(0x7f0000000000), 0x10)
r1 = socket(0x2, 0x3, 0x0)
connect$unix(r1, &(0x7f0000000000), 0x10)
writev(r1, &(0x7f0000000980)=[{0x0}], 0x1)


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f00000003c0), 0x5)


r0 = socket(0x18, 0x3, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000000)="ebffcbff13fd812eaa4e7130", 0xc)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f0000000000))


ioctl$WSMUXIO_LIST_DEVICES(0xffffffffffffffff, 0xc1045763, 0x0)
poll(0x0, 0x0, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
dup(0xffffffffffffffff)
syz_open_pts()
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x138, 0x0)
mknod(0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x3, 0x0, 0x0, 0x0, 0x0, 0x60, 0x1}})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VMM_IOC_INFO(r0, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})


sysctl$net_inet_tcp(&(0x7f0000000000)={0x7}, 0x4, &(0x7f0000000300), 0x0, 0x0, 0x0)


mknod(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$unix(0x1, 0x2, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x100, &(0x7f0000000200), &(0x7f0000000000)=0x4)


socketpair$unix(0x1, 0x1, 0x0, 0x0)
openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
mknod(&(0x7f0000000300)='./file0\x00', 0x2000, 0x6da)
setreuid(0x0, 0x0)
r0 = semget$private(0x0, 0x2, 0x490)
getegid()
semctl$IPC_SET(r0, 0x0, 0x1, &(0x7f0000000140))
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
getitimer(0x0, 0x0)
socket(0x0, 0x0, 0x0)
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r1, 0xc0384600, &(0x7f00000000c0)={&(0x7f0000000000)='./file0\x00', 0x3, 0x0})


fcntl$dupfd(0xffffffffffffffff, 0x3, 0xffffffffffffffff)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
msync(&(0x7f0000001000/0x4000)=nil, 0x4000, 0x0)
sysctl$kern(&(0x7f0000000300)={0x1, 0x48}, 0x2, 0x0, 0x0, &(0x7f0000001440)='\x00\x00', 0x2)
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000)=@un=@abs={0x0, 0xd}, 0x10)
setsockopt(r0, 0x6, 0x8, &(0x7f0000000100)="77b3d8fa", 0x4)
listen(r0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x1}, {0x6, 0x0, 0x0, 0x5}]})
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(r1, 0x80104267, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)
r2 = socket(0x2, 0x1, 0x0)
connect$unix(r2, &(0x7f0000000000), 0x10)
sendto$inet(r2, &(0x7f0000000100)="18", 0xffffff36, 0x195a05e282d6161, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
accept(r0, &(0x7f0000000040)=@in6, &(0x7f0000000080)=0xc)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r3, 0x80104277, &(0x7f00000000c0)={0x1, &(0x7f0000000080)=[{}]})
write(0xffffffffffffffff, 0x0, 0x0)
ioctl$TIOCSPGRP(0xffffffffffffffff, 0x40047477, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
ioctl$BIOCSDLT(0xffffffffffffffff, 0x8004427a, &(0x7f00000001c0)=0x20)
syz_emit_ethernet(0x56, &(0x7f00000003c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000080)=[{0x7}, {0x34, 0x0, 0x0, 0x3}, {0x8106}]})
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r1 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
mknod(0x0, 0x2000, 0x40000802)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000180)=[{&(0x7f0000000000)="9da8e3e9ed", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x2, 0x2, 0x0)
syz_emit_ethernet(0x36, &(0x7f00000004c0)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa0800450008000000000000009078ffffffffffffffff4e204e23", @ANYRES16=r1, @ANYRES32=r0, @ANYBLOB="5000000090780000"])
syz_emit_ethernet(0x36, &(0x7f0000000140)={@local, @broadcast, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @multicast2, @multicast1}, @tcp={{0x2, 0x2, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})
mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x1e5f)
open(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
r3 = socket$inet(0x2, 0x2, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r4, 0x80104267, &(0x7f0000000540)={0x3, &(0x7f00000001c0)=[{0x30}, {0x61}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
setsockopt$inet_opts(r3, 0x0, 0x200000000000a, &(0x7f0000000040)='\x00', 0x1)
r5 = dup(r3)
dup2(r5, r2)
connect$unix(r2, &(0x7f0000000000), 0x10)
sendmsg$unix(r5, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x0, 0x0, 0x10}, 0x0)


r0 = open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
r1 = open$dir(&(0x7f0000001640)='./file0\x00', 0x2, 0x0)
writev(r1, &(0x7f0000000400)=[{&(0x7f0000000300)='k', 0x1}], 0x1)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x3, 0x10, r0, 0x0)
r2 = open$dir(&(0x7f0000000000)='./file0\x00', 0x40000400001803c1, 0x0)
pwritev(r2, &(0x7f00000002c0)=[{&(0x7f0000000340)="bc", 0x1}], 0x1, 0x52e5)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x14}, 0x4, 0x0, 0x0, &(0x7f00000010c0), 0x4)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
chdir(0x0)
mkdir(0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000540)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000140)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000080)=0xc)
chown(&(0x7f0000000040)='./file1\x00', 0x0, r1)
mkdir(&(0x7f0000000100)='.\x00', 0xc)
chmod(&(0x7f00000000c0)='./file1\x00', 0x13)
setreuid(0x0, 0xee01)
rename(&(0x7f0000000180)='./file1\x00', &(0x7f0000000200)='./file0\x00')
unveil(&(0x7f0000000340)='./file0\x00', &(0x7f0000000380)='r\x00')


r0 = socket$inet(0x2, 0x1, 0x0)
listen(r0, 0x85)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)={0x3, 0x7fffffff})
syz_emit_ethernet(0x2e, &(0x7f0000000080)={@local, @broadcast, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x1, 0x0, @remote={0xac, 0x14, 0x0}, @multicast2, {[@lsrr={0x83, 0x3}]}}, @icmp=@generic={0x9, 0x0, 0x0, "e10f46cf"}}}}})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r2 = socket(0x11, 0x3, 0x0)
sendto$unix(r2, &(0x7f0000000140)="b1000502000000000000000001010000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc256699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)
shutdown(r2, 0x2)
socket(0x20, 0x8000, 0x1)
ioctl$BIOCIMMEDIATE(r1, 0x80044270, &(0x7f0000000180)=0x2)
sysctl$vm_swapencrypt(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
r4 = socket(0x2, 0x3, 0x3)
bind(r4, &(0x7f0000000000), 0x10)
connect$unix(r4, &(0x7f0000000000), 0x10)
mknod(&(0x7f0000000000)='./bus\x00', 0x3a0914c44f7b202d, 0x504)
r5 = open(&(0x7f0000000040)='./bus\x00', 0x10005, 0x0)
ioctl$TIOCSETD(r5, 0x8004741b, &(0x7f0000000080)=0x7)
open(&(0x7f0000000040)='./bus\x00', 0x10005, 0x0)
sendto$inet(r4, 0x0, 0x0, 0x0, 0x0, 0x0)
r6 = socket(0x18, 0x1, 0x0)
setsockopt(r6, 0x1000000029, 0x2f, &(0x7f0000000200)="591d1fbbb3a60e297007be3ea71d10eff387c3b2c0daca30502b3ba380d5753835710865243d4e1ad38d285421160be5e10f2884eae9ac5e528e1a962c153b416dd08eaf2494ebf2f8edc8b4859a6ebad83449ac3bd7ad5948", 0x59)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
r7 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000600), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r7, 0x80105728, &(0x7f0000000680)={&(0x7f0000000640)=[{0xd0, 0x40000006}, {0x47, 0x80}], 0x2})
r8 = syz_open_pts()
fcntl$lock(r8, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000001})
syz_open_pts()


syz_open_pts()
syz_open_pts()
syz_open_pts()
pipe(&(0x7f0000000840))
syz_open_pts()
select(0x40, &(0x7f0000000040), 0x0, &(0x7f0000000140)={0xab6}, 0x0)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000002c0)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
ioctl$FIONBIO(r0, 0x8004667e, &(0x7f0000000080))
bind$unix(r0, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x881)
open$dir(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x801)
acct(&(0x7f0000000040)='./file0\x00')
execve(0x0, 0x0, 0x0)


open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r0 = open(&(0x7f00000001c0)='./file0\x00', 0x800, 0x182)
fcntl$getown(r0, 0x5)
mknod(&(0x7f0000000000)='./file0\x00', 0xa8de2e185b4a57e6, 0x0)
r1 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r1, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000040)=[{}, {0x101, 0xa}], 0x2})
setitimer(0x1, &(0x7f0000000000)={{}, {0x200}}, 0x0)
r2 = syz_open_pts()
syz_open_pts()
ioctl$TIOCSETAF(r2, 0x802c7416, &(0x7f0000000180)={0x0, 0x0, 0xfffffffd, 0xfffffff5, "f546db7a3d1f691a1c0000000000d700"})
writev(r2, &(0x7f0000000440)=[{0x0}], 0x1)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r3 = getegid()
getgroups(0x1, &(0x7f0000000240)=[r3])
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000800)="9b0209c3eb987ab7fe4189c99e805e6e84d356960798a692992117d672a736ba1bd857feb09901fe0dcee53766797f42e3303eac3846528d050712f838130efce33f523ba44765f5f6915b0227390ed95bd9dc6d4dc7e149d4d6d06a3f23616e773302d9cae75e39a5a11e32e0e6ebd635450b2eba540af7f2aa5dbfbdd900a00800000050acd76b5c567049ef436dbea0d7562f52950fa5ef6e84c513252ddd8680a944d5c2bd021cc793994922dfc10000000000062ab475cca257352828a76e5314be5629235c0febeff57cab95e894238b96ca5d4d3e670fea610c00009bef19525cb6f7e8570b2a374f1400041ed45bb7ad3fe963cb9a8bd949ee0fc6dbceb7d956015947b3e88aa810f8ed7cca10ff010000000000001345daa49507756faf775275ca390b94e85d5a95b8bdacb9429c25483a9275d0da3b561c6adc3ca67845c3386ce33141141f26a88016dd6b436218bdbdc9ac0a623855e941dc1872fcb045e0d9df1ecc6357ee21e2b0802cb60eec6add5e94723235f06715e7eecc3e0760c70e1dd7873e27142bbae1a7e44de453a073fe3426f334b80f043ba9136d57c799353d46dd81439b111a511a288bee5dfb2e353e3bb073e3342273216b07e49ca4df0fd2dbe9a8eb377010ee678a0900d8c7fb7d82693a096344671843a1f2082612b0ff237c6e505ff5f5ba932954d73c630fdb791f833a1da5af0704f687e196f4f7859e071ec98111cc9024f790ce16ceaa7d0104e39789d91000009a5bec77c992c792eb013621a86709cf57acd9981f947115f608227da8c54d8aa668931edd0b599b3d8cf5a8438ae08c1f70483223c3ba38088fb2e65a51edfed44c55a4d734bb553d642ca2bcdd1a08378317dc8f787469c3b3", &(0x7f00000002c0)=0x27b, 0x0, 0x0)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
r1 = socket(0x18, 0x2, 0x0)
close(r1)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0xfffffffffffffffe}], 0x0, 0x0, 0x0, 0x0)
r2 = socket(0x800000018, 0x2, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
writev(r1, &(0x7f00000004c0)=[{0x0}], 0x1)


sysctl$net_pipex(&(0x7f0000000000)={0x4, 0x22, 0x2}, 0x3, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2a, 0x0)
clock_gettime(0x2, &(0x7f0000000200))


syz_emit_ethernet(0x32, &(0x7f0000000000)=ANY=[@ANYBLOB="aaaaaaaaaaaab024964c63a4080047000024000000000000907cac1400bbac1400aa07033289030400004e234e2000089078"])
r0 = getppid()
fcntl$lock(0xffffffffffffffff, 0x8, &(0x7f0000000040)={0x3, 0x2, 0x5e9, 0x81, r0})
open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
r1 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
r2 = socket(0x10, 0x1, 0x2)
r3 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000140), 0x782, 0x0)
pwritev(r3, &(0x7f0000000240)=[{&(0x7f0000000000)='m%', 0x2}], 0x1, 0x0)
execve(0x0, 0x0, 0x0)
ioctl$WSMOUSEIO_GTYPE(r1, 0x40045720, &(0x7f0000000400))
setsockopt(r2, 0x11, 0x2, &(0x7f0000000000), 0x4)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x3, 0x0, "0100012d29fb000700000000098002005e00"})
sysctl$kern(&(0x7f0000000040), 0x2, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f", &(0x7f0000000080)=0x99, 0x0, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, 0x0, &(0x7f0000000240), &(0x7f0000000280)="1b5c780988cd98f0452ae7c52b4bcdf163e730c485ae29552c3d180d14268c0b8e77e749cde92377ed5c9c3d7696fe9f4938409829", 0x35)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, 0x0)
r4 = getuid()
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000180)={<r5=>0x0}, &(0x7f00000001c0)=0xc)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000002c0)={{0x7, 0x0, 0x0, r4, 0xffffffffffffffff, 0x115, 0x4}, 0x5, 0x3, r0, r5, 0x9, 0x7fff, 0x8000000000000000, 0x800})
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
sysctl$net_inet_esp(&(0x7f0000000000), 0xa, &(0x7f0000000040)="82338798", &(0x7f0000000100)=0x4, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x800, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
r6 = socket(0x2, 0x1, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$inet(r6, &(0x7f0000000000), 0x10)


syz_emit_ethernet(0x42, &(0x7f00000000c0)={@broadcast, @empty, [], {@ipv4={0x800, {{0x8, 0x4, 0x0, 0x0, 0x34, 0x0, 0x0, 0x0, 0x0, 0x0, @empty, @empty, {[@timestamp={0x44, 0xc, 0x6, 0x1, 0x0, [{[@local={0xac, 0x14, 0x0}]}]}]}}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000003c0)=[{0x44}, {0x25}, {0x6}]})
syz_emit_ethernet(0x62, &(0x7f00000006c0)=ANY=[])


unveil(0x0, 0x0)
mkdirat(0xffffffffffffffff, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
r0 = shmget$private(0x0, 0x4000, 0x0, &(0x7f000055b000/0x4000)=nil)
seteuid(0xffffffffffffffff)
shmctl$IPC_RMID(r0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000240)=[{0x5c}, {0x35}, {0x6}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x37a, 0x83, 0xffffffff, 0x9, "6d2b000001000000000000002000002000"})
writev(r0, &(0x7f0000000040)=[{&(0x7f0000000080)="590e495b1ad2a14423c0fe6a9ba42f", 0xf}], 0x1)
writev(r1, &(0x7f00000001c0)=[{&(0x7f0000000240)="cfbb251e606bea41ad417032985e05b5725bb9a5a4201587136fda2dd727e5f62dde5a3a4482bc0b9d8726d0da46c1d908ab108ea9ec76e02493a12c1b64b1ae00f41186a7b024d2ddf2ae9d3a377c239387d08393adaed08cb632e6959c", 0x5e}, {&(0x7f0000003640)="60bbad4238f79f3fab424ca4a0c38f34f352c7d5c7b6743ba59aca5b10b7f12be1cfa323ff58d0f57283e760788123b4a989048b3e3733dc8e3463a3713b8e03e9be10b3f7c76b830225cc80a4a30e8bf4756fae56321aa3894ab69fc4e85a1a97cbe34dd09282ac10309c3e29b703b897fcdd82d8fc7688ba2cd139ef3f333ac048fac12ed769c375952c24e6676579a90c4f13d6d4531fac3cc94239d932935ae6f55541b41f24406ca41656dd8e889a023526bff0d9e951b2b4d175be8134e3b76491bf204272a534386e4d2ec00bc5b7ecc8375079c2ea5526d6154677d5e2de08d01460cc71b57ac1ab20f6debbb381f3d5952ffa3c413b9c44011fe3eca5714c9e995577c26fa6f4be9cef41e86953f7a67ba4033192ec930ee4a875fd8a2d9e7945f75868255b00c1d5487217f32d2db516fd24a770974859d3e0af7c1368405afacce6876add8c4dda7d84bb1c19850919c6c474260ca663513190f2b732650031fe7abf0498f7fe749be7e9e6ac101382aa72a6a5d13564dcec299fabf7ff328c3d4d7d6bd36dc6249e363c908d6f9b04f61d174a046dd542d71c2ef30a39fbb19573b4f2e16c51520aa99f770b838d7cac545aceed9295c8cacc2be13c08f5ea75691d965e82a6a9cbe553e86d25489b4fc730f2a7712b64df3762913d0afb06179df17b755883b27600d2c8943dd88c3a7e2cdd9fbc6eec90287719b93766304ed49f5d57c3afb3dc4cba148b67797cf390bc442bb29245c2bf1b2f2a2dff528c32ad1e09cdb8a285d491613bdb9f6e567e00184a2ddeb383e6ac4f6f51c13de680b8551e67d41005c645180a9522bab67a29c0617dcbf91dca295be0a8b9fd6c8e9a3bdc81e109ecfbeb026e2391e101a29dbf5d69ec70f783476268cfc5bd0baefee4dc0512f3114fcd10e685021b4a4e0075323ff1c94a6bb7e0339bfa8f7a66cc6d7c1e115f8d8ebbf2db6553927d78c1848463196183a7e8c92e0e3c257889d633cb631b4ff59c051a216f43b532702b4b6ec7451b3ef70a3a50d29ff2a79fdb06c6fb91d8a0a8799b6b6f9d56ed0cf3322f957dc31e1a1729a622c6738e6fa4eccdc51ad158e4852c2bf585910a37266e35103072791d279abe6535f07d9affc005cd85d21bf36450cc4e1d0245e0e2ff195ab6706a0cf0003ac8337adaf54ed5923f9a2e4245e6f03823c1f3f26269f3f3f26cb664a92e773178e9d0b51f1aba3a05337c5387245d009e2187cfeb658a7fe98619a1e769883a6ac7f9c01e3e35e20f7675901ee6c2e2b31f952d35d8f2a38d6236514080ce02d2b8de01801a6e4d0588d0663db5c154ee8cd913e07043ef8045ee57dc97520c3d7c597c82d7b4486c8d94d94191e7971e2ea868304007799447fd1953fb8103afdbffb934ece4527b8797a9ebd69510bee9df749c3e68f5ce9b84d5662032c9a1fed49f81e7886cbe9122ac339f72c7e93e927f628ee59d83c6c13420e0fbfb27ce84d4b8d2035488f99d97c1b87661ef58dd62a9fedef7685ec2dc16f97ceebeca935bc8925900ec234bad42982a7e67a5d33648e1defd0a585365a97535c5d78018b7a2164540ae07f81dde252208eebd15834764dc7a56345da952d9b090aebd2a54888deb5e104bc2f54155c0063a8211269ed2c21b8f5ee6c6515bcc429a093dfd0146deb9e8a56dcc73fb36492c92195ccd793738776168791f3a224fee2a695af5e95d3fdb82b312e9bd98f4aafdd9c268f3cf3790cff6649efe9d9595030aad7b24515746a52e821c6f458000240e3eaafd364f095bbb33a47b50fbdc2c66fe86fbcbf7b1c077e929f89eab8b268338b8e26a2f5587c031e95917fc9e1c0af59ab183810104000077d6126b26733c4b1ad311fb5ec3496f36b460153df51fd8f3829e877104ca327a6ce688e1f1f928d98bb1731715ca6d74b5279923547399511939c382368449eb3a806ceb299241f0104b56702080154578e3883edf3baf82076aaa002950500ea3a6ffadb1020b3787a7451580b5cee54190883ab55c0674746401b6bea12bad4293f0048efba066f539d1269e0a16fbeb2daf33fd47387688b43d6bf4b4f09d7c3bc07175f954c07f6946c5f4249b7b71f802bca3bdf8019dd6deae065f154a61e151b42b3040866dc7deba7df66f03ea721787e2268e58194b3cd8d9c1f9e965cf3e87b53f466fcaea4b3c9f1853807b05db27e4a206106c2bd7bde96102c3d0f0362b46853a36a12b18c9a0b83b2bf8dac247252c7138fe258c82f66d3446cbc41fff1d6abb165c776d23f6d93053ad368787b6907b1061f86f053ac2fe0ce77d10d8b5d3d52736b6bd89446aa529e636a83b70fe4a6e3a72e52e13f364d44f0db842cebbdad2e01b41e4ae61ffd309c30666498b9164c9410dca9d90879369602ef8670fc0f82e0deba5e753726e5909234aa1e2086b711d459db6ab35e7d81ebce83c1df31b6c48808f9d52020a72c99e07ca4e0de97e9bca82e2abde799287e966f03b783285cdca5ccac3b9653d94ccb17017a37b5af22832876427b0842849696a39349faaa03ef3078f51c39e4153e1330bb5be69f1103530cc09c5cef0b201111970b0d901a70af9dfa4bca6b34dff016066863936f3005f87f971bdf723d4aa71c8dee65564d66f6e4e2fe83e2a11b097c6a14b651bf1b7e253282e9adf0229f158c1ad0bef485e7a904df7c56cab5724e31b2de2ab6d87abb85a5b7174e27c3c515c1b77bc181d25eec397987deef62ed117c800f434664ce870d7d3f580d330147355c369e6564f049ea833cda2ae8fa9e34ca1a63dbf2117f5a5dd530e85224ff495035e35ae0201a608593401611fa631faa7f8029707fc0333c219acab704dbb9b80a7010989f1f3fa4856cea880c4b3e8e2d43fd12fc46f23dfc079f30407a80956938e27c0354d4f8e3e455497e9679cf2d8b57bbccdbdb75331f15e6fcc26346346d0b59913cfbaf38b2d73091b2c5497f9a8a8d0be52c205c89860e2b11bb16976796d2766b3efb36626bf1d894fc00ce4bcefbbab2608aa37137680d64e568bab8abba22d8fc846ed607e2fcd80a64f11ffb589514e3758c72f7c485a0e62b21de20fb2c481fa14aca0db56fe998247e9f41643b171b904cdc4babb4dd03533bc0b90deba0b66b103492d0ab79b2ae63e79484ebf0ad96b32da892ba082991f77ce7475dea0390f837df5bbca8a64934d722912d651b3c09b02bd3cf2874d3c8ca66496db05c6392963383cd417fca84a4492901d5a532941bede6878f2c0d387bc93439e1e79472a625bfc6f78c54ef44a395da80e6c0b777a6348b356fb3f6b594ac2fee5287b9313a556a3597c69ec3ba1fa1ef3c46c6135fbe78fb739af045d0c0ed99cfede95d7eadb381cd160f3bc34efff00ec4c417e49675c8b6b1f2c3e3f3f66c0db57c468fc7f7a48ff7aeedfa6814e5a0bdf5946f7018558c990e3ce934456b27c6a082481791de85712a334e5efe61e5863647299afe3157d5b815c9935512473ede307e8a546b32c3a85cc65a71a2f9cf4d89cb6d0451789ff6d47cd64448dff7a2cd03a11adf2ffb94618e50221ab6a9718d56dea31af92318f53bb874171f3f34c07b2d9bcbafd944cb02ada658ea094972fc68e21cbef4d884cc594671146ddaa3843fccd56af84aaf0047b2484a24c3b04b067a00dd89a097aaefea71f187e0581fa01a102056b8d26f4cb6900eeb26c860eeead7201fd2d9f2383ce5ec4f330d059dba708ab3eb6ad6662a168c3be14e226791a7d7168495b5826c8b57ba819ff359c984de9daec5273a2853675756a9422ef0ba8bc08961b333d7bf702db9dab08fdca1db9ab42fe80fdbbd020a4d0bb1335df43a8749bf3f5f1d3a30e130e8b7b43e7f78cfe32d0b324e1dbdf151b73cf2f93a7315b080573b4b819e4264526d30f987493d1597ca97f82279cb23eaeca4ebe4ece55b8e09a2deb15c2ae49898f71b7f5694e7e6089ee434c01d1ad586e63dc05e7074be8db1019dfd6ef54a10831c0fc551bed0ae5e40b3585bcbc4b71537f4a4b6b4f355598c897adb5228db77002a2cb148d90c7ea8a4e83af590b48342a053a4240a4239c16ae937fcfc7da372f6b506a761f60f70a8af108914e4aa0050a64a7ae2f73b557eba12166224f32f095e0b91b9f0a75a83ebdf96e59878af7948c553437147187aeb2088910ebc5498711a9443715523140636311999297b504cdbe084e0c5a99b9aeb57bbb974c51b0a49c30cfe2f5f2bfef509258f2d7cf5217b83c710f1ae4bd33a47d17f349779221203baf87c10fc3f93e6c3d2859676104769fedc10032fe91a5d6c027e7371560728a9dcf814b44792721e23973873550ebab1795da12b73ae5d895feb51709406dd3b18ff53fb5d3af8b0b714e484afbc262ba6f2a720ab0b18cf75d1f457e04928334377644332fc58a8f77e91f95d45b684818095b7e41cfb60be405ee289986f36b7e892bb7422aae9656fb031eb9d9b63bb4c70851689c40d54a17f7b48f0f97b3ab9739f937dd251689ef40c92fea33c99db294c1bcc27b695a288cfdff197c28027e7276611f8f97fe98384a843e4968bae4b1f63393346a753aa06042836b6eb1adc25d78c298a234b1cac319edf789f6abaa6d67094fc7f48b24b92d030baf14955159339d38a006fef1349bb73b6fec03b9119f97ea753bf376210c467520eb7cd052a36161eaf5062be089fc657f8fa2245a5887b29c26216a143382bb5e3b77b6f2cc5559a8c4915c496548734666470f24dc19d65f1a0ac2dc1b553f0c3af1510fbcee5f57461b6d14d3bd721e62238c06e2784f1a012fde89e352bbf2365b565d50ee27246fc00bd62fe46ece7b976802a697ccb7c717f85839a6e39b20bffd8e0e25e7b128c962421fde44ed4b742fe7af596add878c920cdebc7afbb42800177016cdc39d852dc64040be9fc5182c05f530e669ce2d0489b5fb5ea95fc56fa3fec5e27e0b7a450507f0b3de240899647fdfe5e7d52546aa7c358d02fe9fea6767d662d651ec1fb10e613b1f219c440362bcad23654f8602dddfef51c21e431c75b0317d0df0f843df1495817a85367e081e1df83647b7d07dbacc4874816214aaeae0a574f57381cc70f4cb782034c9974a6c4cf23c247e69a0f7fa08750b08634957ffb8826bc753bb42000c6df0e2b493ae873f7d30ce865d5a419fae68052d035a898d89642f748e6a50cc491290422983000800004b430396fec4bb4d3cb232a23e051061f31b9c6152c692caad3f9a1c44d06e4766d4a3137c638fa75eac3ae9e1c6a6226667470592040fa642e72722b1c98badc64d33ab3d28f1cf6f30a4c63d65d14bbd626c3612716817d83f3f9a2d96022fd5159fa45e765d02d141a4f66ed715ef7695b0ff2bb59360a729e23fbdffdee91fcb8b8a3d9e9312a522f153acbc9e9a0b412747a936731577b0a91aa6b8ae503bc74a83462f3ce2ae41a1c152a9000ad0bd7443c2f41fefc91efab2d43099aea185d7200861c97a6787cfea734be370bf36a510e4fdc186aa9f4dbe92f32fa3770dc8db2d7cdcbf9344157da48d6a5ebacbebddeae4c408c08de0a081aaf79d98b230eda6c8823cdfe59bd148b736d02f94b64afc46d3df29558891bc48c8ec7d485aa99c4417a1879c9ff1625f3e821b2347c176a0ef958ad7fc54eb10a53005b922393cee5a6cf7300f4c9171d462ddabbc0227d491f37606fc5c8e545d2a85634608000000000000000000000000000000364a78e1d1d1e8f5c1c5f854d92fd2d832f29620ec1e9e8f6cca4f", 0x1014}, {&(0x7f00000009c0)="25fd26f0c2f6f8454eb459827dfb6921cd320fabb353b6abd1bdf7a6dd432ca5295f892a5056cb9908d6095b22d9c0274f069fd0a76fa516143c92282620fdb3582c7b29a74fc9a0628e26889677f0ab87054b774261de8656a080d103c0504abd02c0f742a4a5cddc2434f350c2d1e64e9f25f7d20341ddfb5bd0cacc83eb73828ca34a56b3b35bc8b2610eb4eb453adb749734526c46d9b2ab6d8614761de8c384dcb53ad08cb1527152db4272ad88493fb38f40398b5a000034fa551a4b2630e0900d08787e89612408f5c38d3185a17475d4a4942473058501ebaf20d02af3d8c60a5f48c3a9a6755836a8fdf1899b5bd43910f6d4f751a123c587ee70642588691f113749045b6abdcf3db86e647324bf25b37e3c2cc4c1e1464d5b356097378f0ad8860e4468552ee97b612dd1c29015fbc2bb362f3ba161e64e4739e080ed7439645b5209d44475bbae79006aa70b987a873c7180fa32988ce3fa24907bbae057634b9375ee778fc5292fd9a9bf70f2f654b773bec290c771bae649022fded51fd770fd6f58b4a8dc1fbc504f3357929f79893aa5e2cfcf29b2adba3c84bdd7b9b6781fafee04027e459268e80a3526634e889e6a166e811e3dbf3f88d5f3939bbe77d38806a3be958f088b364aff49c4e0ddf54b8f00890c52731b1681743fce56bebf135603daa64c74b80caa8e5a793bf0f659190ac2edc99b7c13f6fefc1228934e5c43772936352251dda437b4579dadf606a98feec406db368b7a01fbbf7ec7f3a1ea81669eb813bb29ae94d90785d31cca24ae7cb776f054c42988b115b5befca984fec1442fbb7275d32ed818261759c2e7cd06397ba28bd1162302e11a7e6bd53a478cc67ebeb913a5fbd49fbf848917d8d241fddf73a075da83e2b6db447bf9ee2e3e2c543fb1c67a3de15218f147520019ef263a15abb18bbedefde3da0deb0607a6d1f1b8613a1786e4d972c065d800000000", 0x2bc}, {&(0x7f00000002c0)="e041bac6e222cda5a8a83a629eb6514522c599cee99c1c36bf1a6bc1303e5e1af2c7d6ef7e7a04f1ec148d49241dd0881538a2afc2faf893f9dfa86f68f0f3f25c0bc65341263ac9ac9d46c0f4257d89bc3db24110867d5653d7bfbe294fd3c8f7d0da9f05529ae206849560ac6666403704762cd5c286b039df3ed0e2aa6f15488dfe95d5b74aefce77e0afee5ddd2876e6cf2d4619b88ea57677837ad4273acd0fea7a92", 0xa5}, {&(0x7f0000000100)="6973b3b7b5f516f850b75a28715b10f7ad8042b6ad24befe4129af5d2f4165f2a214c533a7f59cebdfe071af14f8fc14b9d792c9c83e6b98efb49b3f4ad8f456696d252dc98388c1e1d14bf2fced5de86ab55c2a3e0199c24c232e3965832a8b339aa0cb61dde68a23b8d6b17ccb00b359556b51a4bdc4bcd900000000000000000000000000000000000000ddd15b875073981307fec6ab86", 0x99}], 0x5)
writev(r0, &(0x7f00000004c0)=[{&(0x7f00000029c0)="7b0503584ce8d2ce7fde9e5d801a23ea2b6979ecc844084c073000b4809a5180fdaffb5e0ae0d9f4cddd3f40a84400508657dc115d65d679ac86e2401d295fd33c96679b22911981b7f2b74fa91476f4fad3563c23c7edea5a5f4683a85a165d76b0dce05b843f379608a96bc2c5d201679acff1bbba1e46eaec7b32678997f651eabfaa08b61659f3474ca5feb3442f78b3ada6b54d1b173086e363010d65d6afda5da875d835b5eabebe8ae60c30895434c23b575878c5373add15a616c28317d955070cc7e28ab6b1ff76e4f6bed742420b07d297fb9cd6f06809f8c22547b515872342ea597a5394049845f42b3b97a20c308a5cb45d3c08b4f64821b9078aaa76312d0277d9ae7cd484b85a4c7d28663537be3e24ff6868f17d16aec1e49345a8c4b5b3cb314c40208c6633af6dc2dfa17badef99f179c53fd06163b1149ed0d6377f6b463dae3ffce81dd31f87cee66a958b85d49f69e5da1582e93743dbecedd2667a8766abd88895048c20f30d0b6635fd4cf603d01e22e79b7f145ba37fdbdfa914544e6aa499e988df5ec70926111777d3898a4175190daff7cac90043a46a2b22bc3b185af2b4e3d0b217f6c92d0b852660790c06a9f5076e9808b947adaac219c31c24ee613629455410739acc0a3b8cb9cc507611fb1474996bf338c74cb0bb44c17edf276edb84a52d7dc768b303a3bb3a56a415bb73d3a5cda8a7e753788155923baed1017dc08c52fe86240bf109704cd3fd7bff10627752988eb75c8e89f13efe9f0dc899adffcb7074a523d819ac2bf24eca8379e9efa19020f9380dfb6499fbe2f79a95cd0c0d6d90f97e8c39e75f789213f36282dd9a8cd23fb67d5e54537d07435b30a5d462ad54d8b5166ec68f96ac8d0830550c1da2086a7115d740c3e1105fcb2b9ccf9ab280913944808d01d54ce4b613e7b39b5d71c234a89154407df8c4c32226ecc59c577fc832180d179b5fde9a0ef92e28c7d3a98990c45ef782b5716cbada6fffa288396864e05fad09a020c8c0c13ba6fa3344d5c152e5ac149c1c10ae59a4111fa1de7d99cbd375476143287b405a5408da70dd8b3858a6f9142ffbc7a45cf9016ae23facf0478dcd19c477173f43a42b538d30d2d39327fdd27360f6ce39b995a3968af48a25c82e67a8068abff4b5e0f797e80d3293ffbff6e70f77a42486449d518395c159a1a2b0d83fbc4ed496b7e4c22780031396dc4c16cb4dae000600c209fdf5a25ebcbc6f85590af28968a755198e68e1a012d0b738f33cdfc2cefd43841761afc9ba8920e1c12eddb06d6b88b710a48bbd3b40d2340289326f8282c7064eb97c30be26580e47ac5969c7b18a29e642ba7fb8ef23f4e2262eed3c342e09a7d587c82f16a49d0debce35137e7e68e37db92ec952a289a8a81f8845cd0c4abba94adc27222daacc087923a554c40c0aa05607ecd0391627f92d58511d35e6f503ecb165aca20936695fad1641af15a4586f0c6b7b2e50edbd6c4fb73ef75ec9bd8ca0e49e0fcd88d58f3a2df25df04646394ba3a856d5848a30ed717c48ab9a8cc96ceaa4d4b15be21c71cc2e2cf0c905ea54955073b2560049a1d31cdcefb330f150e693584c262ec5019895b81f9786e7e15c5cca371f0709bdfadc4d79f1a7150c92619a3ab2dc2b8153eff67b9113c648c49c80bb768e3bea1efe6506444a8ceb36ce54c6978567ccfb54c17e84ad0ed0aec569b33eec80bc161c8a3f3f55094916647c2c2438324b8f459fa01f7e164aa93f766fc9a9ba69e8930fb7ad640aba041636589d905cbae5b68f41f24cfe8a591fe6f1ccf2f43ebffcd48d3e23ad6da34baed3242127562024c7bf77b962e4331b1e0ec411d95f4f9f7b177a85b71d150b9bf710aef8124aea83cd1f1ba339b480ba1f7ce179a15acfd1da8a1219ae9205eb7e50c5e485f54cec2636d3e46f65fed3d079ff3f167337106b9db94c7722ae14ebca9544edcc27aa0dc287c4184db906b942f4687f973c2b431321acaf10c404d0c2defbbf9ef2743687243b14cc8948a9b25601b2c5f0407a11536d67ea7575c077c563d1a102c08c87485d22c882e4201446856ecdbe5dbf73270bcb8d1e4bc3bd3076e8646c3618a821f61c19cd9d706804fa0149d3c9b701ce47d0d4c920379ea65a27d4704b205c382146fbd64a39e2cfffde3cadbddefa6e7dbcb1b12e2d9d265cbcf04926bacff8a2655cc74091f9530e638b4e2e6e94fe8191fad8b82cf99246edddce075e9433b4816fb89544a02f373ddf57343f7669f8ca5be22b8728f5041ff61edbdb7ae019057ecc1b12777e1d35a32a32e22a2385491c08080a3ad9ac5557224db5c30cc6b7f351fe02a836e5fb2bc48674ca4e27a8b65d878e8ed12e9671f42d72894c6d4f576699895af3cb6d3ce79d0fc2509025b9a13aa38bcfc8cde0f1e1097ffba802b75e27cbc0c16636ee7ef273bd799844b620ce0a4fd9481e0486ddf5465a09682757556acac7ee70c5b2e627c0bd2e887db4084f4d94854ef03f4f5bcac7170c6d548597c6d991782539778f6be82457144f9ce2bf4a9cfb33fd2b428b093e2c821a656c1a1ee373d97a89660fd942b8cad9f365c92c9f9da92aef4eedab492ad0704882d5b4fc2e80ed86b4c29fedb897a61132d5fcea1df46f98278b74f452ea42d3f7791c34c41bcbab19fe284dbd512d9f40339fd43d5a6aeaaa9b8c07b9653b16cc1b1438fcf4d23ac73a7b2adcc38e490fb1a14930e6af91a58f6e87dc28717d03700873886542cfb784a2fa005443e5ea4e3f78c0b9290dd4e2a7c0f6248d71b4a3cbe53c05f15d7ec3cc73cab1cc49f16104ae325e988bb5fa8191e6fdbdd910ffb758df5b2fc9f017f20a192c2c281849c6868d6339e86d4bfbd2fb12c65dbba64e464b3f30ba60af382f0182e215fd5c29ab327be6c6ffd8c80becdaf870b02845b969ba90bd9f6997d4cb4acddd229d900648df0f92318805f55c8668495c69c42ee87172e1f01c357b1df4f1a8e7292fdbd09fcb0ee2ede4e5e88ee2e0f302d5db26cab14e93950931a5041870711ed5d9240e42857b11a08eaa8491be999341035f8c88d87ea81c1d02911e67105f620116cafc30cefaeffc9a9458d3e93ee8df29871bee070f8839e3be54f8a5f9752769a7401e49979ea879cc70555d686c741bebec0b37f767f1dcff2c97ac8d50213d5e52a7208b8984661cb0cef2284700daf6e40c560322294843854c67e22d4dcad488a1523c84426180c6b5830b1433c3740048abbedc218b9c4d6ae98b6f1c273d203a3a5c573ae75faaaed5bec26099b16d598378700dc20ca803bf8a7063bdf0978603fa7200fc23a038a8e98b01cbfac63753efb68e73108fb896f1ef121e28c0ceacb83341e87179886ec0baa8010a175b79cb113cf9382bc49f3e9ed10e24f6f3da9cd436b3c069858a8f0149b29e98a895555459598378f788c633dfac8a7cd6c629f147ee73daa03dc45b90810450b0f36de8a79340a58ba9e62805d39920427a7c04db2325924b72c12e3a423453591c72e55bf9a76cb089fd3daacf85d696a6c3ff21561816f9b3c0c64d160f9819e29cb66547f565bf7f947177e789888a9cc48bfe52bac189bc6f55b6b20da33f25f5378496a466b104c284d5edec82d42b527ed345180e010eb570ab22189a9ffd06cf22ecb3a99b10da6cf5be313c2354040a570b7fe6b90276e350beedb9889df5048c2c284cb9816e70196405e333834fc1b2a13a6d4a5fe5373b514fe3207de4e835c4cb8776e5976bed23e7d0163342d6fe16f2a9dbede4f7088b9fe2955d7171a081809e8c221b954929c231ca309b4ab0e0c1cdd5604cf41b501f6b6cf3fba50e3be01bc1ca6ca02c304c13339dd853d1367621998d7ec24fd085e7b3d883adaadf3c95036a489b524985bace6bbd0090e08b650644cb009d36575e543fc3e101b3747f275815c1dd1812406714d19950f9a0c94ffe67739bff0277909a25fd6ebca6b366823296bf5ef22bedd7c49db15007fac31a70379fc1daf7b9cc93445bd372b0ba8f5ed6ae0a74bfbb2a868a363f9c819cc457db46eba23e9226762e529b90cb4e9b30c4ad24468e0cc52138660df3decfc596a2338d654e8ff160704d4eeea557d5ce025e7872891d7cd51fcf956e7a5c34a7f8059e9141548fa450990abff568655d48b5f82225e58fd0716dc422b84675ae1c6144eff985b9e72abec0707a64c6505f134411ed1825273c8e80b5688a828415a23647a78d", 0xbd2}], 0x1)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x81}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
madvise(&(0x7f0000000000/0x1000)=nil, 0x1000, 0x4)
setitimer(0x0, &(0x7f0000000080), 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000001c0)=[{0x14}, {0x1}, {0x106}]})
syz_emit_ethernet(0x1046, &(0x7f0000001e80)=ANY=[])


ioctl$WSMUXIO_LIST_DEVICES(0xffffffffffffffff, 0xc1045763, &(0x7f0000000040)={0x0, [{}, {}, {}, {}, {}, {}, {}, {0x0, 0xc8}, {0x3}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {0x1}]})
socket(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x2, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$WSMUXIO_LIST_DEVICES(0xffffffffffffffff, 0xc1045763, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x80206979, &(0x7f00000001c0))
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
sysctl$vm(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r3=>0xffffffffffffffff, <r4=>0xffffffffffffffff})
recvmsg(r4, &(0x7f0000000100)={0x0, 0x0, &(0x7f0000000640)=[{&(0x7f00000006c0)=""/86, 0x56}], 0x1, 0x0}, 0x0)
dup2(r3, r4)
execve(0x0, 0x0, 0x0)
socket(0x20, 0x8000, 0xfa)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mkdirat(0xffffffffffffff9c, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
mkdirat(0xffffffffffffff9c, &(0x7f00000005c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
symlink(&(0x7f0000000440)='./file1\x00', &(0x7f0000000800)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r5, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000040)=[{0x1c}, {0x7c}, {0x1416}]})
syz_emit_ethernet(0x4e, &(0x7f0000000140)=ANY=[])
unlink(&(0x7f0000000300)='.\x00')
openat(0xffffffffffffff9c, &(0x7f0000000040)='.\x00', 0x800, 0x4)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
sendmsg(0xffffffffffffffff, 0x0, 0x0)
open(0x0, 0x0, 0x0)
r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r0, 0x80085761, &(0x7f00000000c0)={0x3})
r1 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000180), 0x1, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(r1, 0x80085762, &(0x7f0000000400)={0x3})


munmap(&(0x7f0000001000/0x2000)=nil, 0x2000)
sysctl$kern(&(0x7f0000000300)={0x2, 0x8}, 0x2, 0x0, 0x0, &(0x7f0000001440)="00000100", 0x4)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
setreuid(0xee00, 0x0)
r0 = getuid()
chown(&(0x7f0000000180)='./file0\x00', r0, 0xffffffffffffffff)
r1 = getuid()
setreuid(0x0, r1)
chdir(&(0x7f0000000100)='./file0\x00')


close(0xffffffffffffffff)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
fchown(0xffffffffffffffff, 0x0, 0x0)
r0 = socket(0x18, 0x1, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
ioctl$FIONREAD(r0, 0xc1206922, &(0x7f0000000100))


open(&(0x7f0000000180)='./file0\x00', 0x80000000000206, 0x0)
r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000140), 0x782, 0x0)
r1 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
r2 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
pwritev(r2, &(0x7f0000000980)=[{&(0x7f00000009c0)="bef8cb3f2eeb69327bda2399257586c85f8cefa70855f499b4383006c19fad5c66da7c765d82f65db27072960f7476c2dcd2f582f5555debddfd103a4283ccd9cc32b37962678d341d729ff5280356c0c618f5bc7a267bd97f50385d879ca412b901a927549007e0d044510861d1bd0b9b9fc1e1d2015d2008c6027d8df1ddff0716349dfb73d0dbcdcce1efbb35984f9ae47246adc55831eac3a07bd836e40cf739f4791cb7a0dc03286281de2c24fe200d799ebb27e04bef355032bdacd02806f2a86013b46b8ba8c0e246b9332a254b64a4302903ab3ef49184d280fc9b3cab708cd7b2d4aeea701856d916d72e1ac02fcd2ecc4202089112a4945740e35deafb8d00bf", 0x105}], 0x1, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r1, 0x0)
r3 = dup(r0)
ioctl$SPKRTUNE(r3, 0x20005302, &(0x7f0000000100))


r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000140), 0x10011, 0x0)
poll(&(0x7f0000000180)=[{r0, 0x14d}], 0x1, 0x0)


execve(0x0, &(0x7f00000002c0)=[&(0x7f0000000100)='tap'], 0x0)
r0 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r0, 0xc028698b, &(0x7f0000000100))


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, 0x0)
r0 = socket(0x18, 0x0, 0x3a)
r1 = msgget(0x3, 0x11)
sysctl$net_inet_udp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r2 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x9, &(0x7f0000000240), 0x0)
msgsnd(r1, &(0x7f00000002c0)={0x1, "10ee20dcedc36657f7fd03dc4d7f8da54329a1d0aad976c8d29de7ace0fb86e24b28d91f650bcae0e939f439df94a10ff08a4e15fd3ea168627e1b4aea403d35107c3e32631cc7e89ed0e766d31701f79c0f0dc416f21eb14ed4f1d0a0105c52e2e7d9cb4f5d82bc83b882667f218e23c46809f223a0ce416d2f24d79a01d5fff008abb98cfa911f0022ecc43c7f1f339a9780ad0ee5dd9ed963a2dd70d7bd2ac057ec3c8661b074be11bb062f8c8f85e877696fbf238226e7c8224fc79fbc2a4f5d0da06e8a458f4c234a42716e9954980af6657cd393fe19ab0e3a"}, 0xe4, 0x0)
setsockopt(r0, 0x29, 0x0, 0x0, 0x0)
r3 = socket(0x11, 0x3, 0x0)
sendto$unix(r3, &(0x7f0000000000)="b1000513000000000000000004000000000013fecea10500fef96ecf2ac72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf7f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f335c223e7d0c032bfa896443a41002000000720fd38bfbb770c1f5a872c88106002ec5890400000000000000361b1257aea8c500002002fbfe0c2300008abfba0900000008e371a3f8343712051eeab7196fcbd80407000000c011200000", 0xb1, 0x0, 0x0, 0x0)
setsockopt$inet6_MRT6_ADD_MIF(0xffffffffffffffff, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x3}, 0xc)
open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0xd6)
mknod(&(0x7f0000000280)='./file0\x00', 0x0, 0x0)
msgrcv(r1, &(0x7f00000000c0)={0x0, ""/142}, 0x96, 0x3, 0x1000)
r4 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x2)
poll(&(0x7f0000000200)=[{r4, 0x4}], 0x1, 0x0)
r5 = openat$wsdisplay(0xffffffffffffff9c, 0x0, 0x80, 0x0)
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000001c0)={{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2}, 0x0, 0xfff, 0x0, 0x0, 0x10001, 0x8000, 0x6})
setegid(0x0)
setgroups(0x2, &(0x7f0000000080)=[0x0, 0x0])
getpgid(0x0)
r6 = getpid()
ktrace(&(0x7f0000001d40)='./file0\x00', 0x0, 0x0, r6)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000400)={{0x4, 0x0, 0x0, 0x0, 0x0, 0x5, 0x8000}, 0x0, 0x0, 0x0, r6, 0xdbf, 0xc54, 0x28, 0x7ff})
ioctl$WSDISPLAYIO_GETSCREEN(r5, 0xc0245755, &(0x7f0000000040)={0x1, './file0\x00', './file0\x00'})
execve(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)


lseek(0xffffffffffffffff, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000240)=[{0x44}, {0x35}, {0x6}]})
syz_emit_ethernet(0x2a, &(0x7f00000000c0)=ANY=[])
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x200, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000200)=[{0x4c}, {0x7}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000200)=ANY=[])


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140))
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000280)={0x0, 0x0, 0x0, 0x1000301010006})
open(&(0x7f00000000c0)='./file0\x00', 0x20, 0x0)
r1 = open(&(0x7f0000000400)='./file0\x00', 0x0, 0x0)
fcntl$lock(r1, 0x9, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x269000000, 0xffffffffffffffff})


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000380)=[{{r0}, 0xfffffffffffffffe, 0x21}], 0x0, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f0000000040), 0x30, 0x0, 0x57d, 0x0)
kevent(r1, 0x0, 0x0, &(0x7f0000000600), 0x2, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000140)=[{0x81}, {0x34, 0x0, 0x0, 0x3fffffff}, {0x6, 0x0, 0x0, 0x10004}]})
write(r0, &(0x7f0000000000)="7696e5f3d1f18c37cea8615ac7cf", 0xe)


r0 = socket$inet(0x2, 0x1, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x8, &(0x7f0000000000), &(0x7f0000000040)=0xfffffffffffffe9c)


r0 = socket(0x2, 0x1, 0x0)
r1 = dup(r0)
setsockopt(r1, 0x6, 0x8, &(0x7f0000000380)="8a68e043", 0x4)


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = getppid()
r1 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000424, r1)
ktrace(&(0x7f0000000180)='./file0\x00', 0x4, 0x330, r0)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$inet(0x18, 0x3, 0x102)
r1 = dup(r0)
sendmsg$unix(r1, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105727, &(0x7f0000000000)={&(0x7f0000000040)=[{0x22}, {}], 0x2})


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x8981, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105727, &(0x7f00000001c0)={&(0x7f0000000040)=[{}, {0x23}], 0x2})


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f000033a000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil, 0x41000}, {&(0x7f00004d0000/0x4000)=nil}, {&(0x7f000035f000/0x1000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000225000/0x3000)=nil, &(0x7f00006ef000/0x4000)=nil}, {&(0x7f0000412000/0x3000)=nil, &(0x7f0000769000/0x1000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f00004ec000/0x4000)=nil}, {&(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f00006fd000/0x1000)=nil}, {&(0x7f0000136000/0x2000)=nil, &(0x7f00006e7000/0x4000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f00006c8000/0x4000)=nil}, {&(0x7f00007e7000/0x2000)=nil, &(0x7f0000386000/0x3000)=nil}, {&(0x7f000002a000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f00002ac000/0x4000)=nil}, {&(0x7f00001b2000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f00007f6000/0x1000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {&(0x7f0000668000/0x1000)=nil, &(0x7f0000310000/0x2000)=nil}], './file0\x00'})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
setrlimit(0x0, &(0x7f0000000000)={0x1, 0x1})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$VMM_IOC_RUN(r0, 0xc2585601, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, 0x0})


r0 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
mkdirat(0xffffffffffffff9c, &(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
renameat(r0, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', r0, &(0x7f0000000240)='.\x00')


mknod(&(0x7f0000000140)='./file0\x00', 0x8000, 0xd02)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x100, 0x0)
lseek(0xffffffffffffffff, 0x2, 0x1)
setsockopt$inet_opts(0xffffffffffffff9c, 0x0, 0x0, 0x0, 0x0)
socket(0x2, 0x0, 0x0)
socket(0x2, 0x1, 0x2)
socket(0x18, 0x2, 0x0)
socket$unix(0x1, 0x0, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
open(0x0, 0x0, 0x0)
open$dir(&(0x7f0000000640)='.\x00', 0x0, 0x0)
mknodat(0xffffffffffffffff, &(0x7f0000000040)='./file0\x00', 0x2000, 0x3ff)
openat(0xffffffffffffffff, &(0x7f0000000080)='./file0\x00', 0x0, 0x4)
r0 = socket$inet(0x2, 0x3, 0x0)
setsockopt(r0, 0x0, 0x3, 0x0, 0x0)
open$dir(&(0x7f0000000000)='./file0\x00', 0x80, 0x0)
shutdown(0xffffffffffffffff, 0x1)
ioctl$TIOCMSET(0xffffffffffffff9c, 0x8004746d, &(0x7f0000000180)=0x3)
socket(0x18, 0x3, 0x0)
sysctl$net_inet_esp(&(0x7f0000000000)={0x4, 0x2, 0x2, 0x1}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0xa}, 0x7, &(0x7f0000000080), 0x0, 0x0, 0x0)
setregid(0xffffffffffffffff, 0xffffffffffffffff)
madvise(&(0x7f0000ffb000/0x1000)=nil, 0xffffffffdf004fff, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x1, 0x0)
setsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1021, 0x0, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000180), 0x20, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000380)={0x2, &(0x7f0000000180)=[{0xb1}, {0x16}]})
syz_emit_ethernet(0xa2, &(0x7f0000000600)=ANY=[])


mknod(&(0x7f0000000000)='./bus\x00', 0x3a0914c44f7b202d, 0x0)
r0 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000180)={0x0, 0x0, 0x0, 0x0, "32cd8b6abdc8a5508471050000000010000407ff", 0x800000, 0xee5})


r0 = syz_open_pts()
writev(r0, &(0x7f00000001c0)=[{&(0x7f0000000580)="7659aeb94832406f050635f0b67c483a24febaee4d9c497b7e5f0bf12b7225efb6f6c869e646ecfa588c53283c4dd3ed77706f3868cacea799a3bdfb42db706563dca286f58274eac945d5ffe9054ffd5b7724b408516b9ed309d4751896dd052cc4977fb3194274891c0663318fc47757be95bdc22a02114abcba148730246ce5aa4f5d217faa6438f9fa2c0e0b7ab697a8d63f824aefa5064bf87f22d6cfd97dca4d46f07c6ad783dcc1a919ba8409ff0f1be654c2b62f0ca1a4087d6d8940691f19a5ba", 0xfffffe5b}], 0x1)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, "1582ab1203b31000"})
ioctl$TIOCFLUSH(r0, 0x80047410, &(0x7f0000000100))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000240)=[{0x5c}, {0x16}, {0x6}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x6, &(0x7f0000000080), 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, 0x0)
open$dir(&(0x7f0000000080)='.\x00', 0x0, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000001c0)=[{}, {}, {0x6}]})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x8020691f, &(0x7f00000001c0))


open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
getgroups(0x0, &(0x7f0000000000))
setregid(0x0, 0x0)
setgid(0x0)
r0 = getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r0})
pipe(&(0x7f00000001c0)={<r1=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r1, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r2 = fcntl$getown(r1, 0x5)
setreuid(0xee00, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0xb32, r2)
setreuid(0x0, 0x0)
r3 = getegid()
setegid(r3)
ktrace(&(0x7f0000000080)='./file0\x00', 0x2, 0x0, 0x0)


r0 = socket$inet(0x2, 0x3, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x1, &(0x7f0000000000)="6228951c7f85b0b56aab81b6e533fbeeb0254b38b4984076233bc43918963438e600"/44, 0x2c)


r0 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r0, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
setsockopt(r0, 0x0, 0x65, 0x0, 0x0)


r0 = open(&(0x7f00000001c0)='./file0\x00', 0x8382, 0x0)
writev(r0, &(0x7f0000001480)=[{&(0x7f0000000100)="cc60d3d79a1a7122a5fb9de9ea6ca0b30fb2942ef7652736f10f86d45ae419b2ecf7af93d33b3de1f2c56c0d93da7484095d0d543baf7f0161a025c9c02a561f9a76d06f1eaec7d8df99d6c28b10fa891e47d6c3bba690a611889032ac7b3581d7c92d1c546e59764f069048316871794f0615dd4d8bb1057a61fb177be649004fb56a7d46c856a20d73f050bf29d58b803a676cc3761e8a47857f51d90a4465f9c605ab2829d78ea2571900", 0xac}, {&(0x7f0000000080)="b389", 0x2}, {&(0x7f0000000200)="5f6a8de84b4c523a583f91557c748a02cda4cedf13579996073843ec5cbabaadcec85d62a8a897a78307f3d2c30eea6356105ec8aaba86930f1aed0b3d111d", 0x3f}, {&(0x7f0000000240)="2a5f4cd9b73c31d629e8d68e605e5940744ef138960b671d42c56f79fcb70549247e5504e02f85a6099eff9291731e94399a7e966e783d4073ecd5dc8e540f32190bb47050aee3907495ecf7708d1c295a0836f79ba03ea13db12836c2441989726ffbf7fd1da55bfe2caaf081a1ef55599935c0e60cb0866ee48d420b77a6e269bc30b2650349e16792252c6be8bcc6e9ce2b941299ab505e4779fa1960bb7cf924dcbc53c82e76bcd80731a694d12e8a139d8ecef6f5560939054b7842d25cd7396377f39bcfe2a2383feea17b87393cd892b90742631718b1877d8d83d5f66587e3e5b1e129433ead750143a4c51aa46e78e3b1a54a4634eea2846511719b1637b19ea8c96a95332abd69014f53e91a7319a36efb4052387dc6330aa00b5680142650e8dab5eb6b83ff7d0bbf1293338a8d3e8a6dcd7ed4916279eac230dda46e6fcdebe8a4c12d598883d9392da05791e153d905ce1930aebfc5dfc0fc22a88777c9fbc24c0b021189c3503466bf850f59e6649dd0b40d935ba155a9d7e065df6d90a500be9d7e1e77607d495898a8d6c9c48dda88533e75e760dceae91d670f97ebbe68b845c72eb698a9e0389b15cfe768cd4e524dbe939bc2d8363ae3b71a454a0a0378cd1f36565ab9d1b92263688195df65151ee9b8158c7a5280019a38f00ea05142b3cc832ece46e326e36a55d7a30f866ca97da61a3877612f0d9f23c052edf60a430d3a9acbae3d9f14f22f38a1eeac7df37ae17748a960b9e0d265bf6cdec73bd2a7b5f25035d845d936936cbfe6f013f8d7c73eba2bd9876ff6db3224e50e75c051979f4cdc41d28ea54e28f560fb0291cd6b6ba527e0f358ffa46b988f0bdbf801063d2024380071709ac00ed463e08fd1718a857b567d8b3eda143915e943d9530d25ed15743e117be375dc08e241328a53fa05b58c7c72a35d471a72706afce82b6c57eef81444269e06338bfd0af6f6ef6479dcc26aab0b10c7e58572aa507a69831d63c78c947cecda2c57bb8ae6b2ad7862d160b423de941be69928467db10ee4817536196ad0c5cc02a74ba1a1fb467e472f025f200846112b6b3efd298284d8c0cc498fb9203db18e48e34c137d1285120d809a774d56a62b3dbe8f202cb9cf18c33099f5b9651fc7ae41de53842f327fd40bcfaa601a791da1103351a64cc9815ff1f32cde6fbfe4c92f55a9aff41c055d4edce9c656ecd1becb9035bb8bd46cf47bca0dcb1848da94d05d1475c83a48c02f8f808597eaa9e88a4e4b12d0ef95458eeab115cb189fa7e368186bb68610af4651e27feab061c4ada46e8c12d6d33fe32cd40485b02120418a9aaba8f04c17ea1abdcb9e6801f5d8090c0780b3b5ae4382efbb64f62c825527b7e3d60ad9c73ba7f174ea7c7f2d155808052a0ef6ab2af85cf9a758a8c1227c85f2986fc06c5f54807968b18b6b5f9168d0b2de2728689d75f0efaedf79bd8bbbbc1d46b0f6072d46d46687bc92c0b16c4ad36c3fe4c7a2fde0cfec859052dd78d841464a6b4432342ea973bf18f1f5abd7b2fe7962faef39ff38bd88a40dbab0f8c08541e38efe924f9ec1addbd47362e349bfca42fd62cf18fef8db7d3cbf0b1733d37dcdae5b9c738b8426a1cfa205c9671870210508c614f256d199fb822613518b1a6fccfee08c48f0feae1ca4baaf0a02635282d4f630a8df115dc73e72d9f7b8feb4333b2c796f1d3f2cfb398ba1e9c81584185b8b578bac3c64d667da7d91062f0c2ccec0c9d09e0c15c62e7bc509c3204d054c22d4eac685626e48e25cff2fc382279d9cb941c2ca182b1f65b05ff05db880a37b1e7f9b3d8975558858352bbbea9213a885b7d43451230e0624403baa77839baa33ae92de771ca76319c2353e9f98ea8191fbb686aed6d08e87bcc2bb8084ae02fafbac1a0bba93f0f155fa2d7bc21bf77f116429c6a1373c34d080518b73481fcf012c0a9127e8f174695ccd4add75b026bf2935990d5cebc4e74b97ae67a414029252336880232635fce7ed7bf0b069e08e10f7e1cc4d2973dcd2ea0b63f9dc4f4c2db92e03c553afcb1060b12f6b9b4d1d799edceefdfafdae63ad797e400645c149b20f8a10af54db3289441499e122413495c7b32179ab6c274bbdf6dde48ce26f46f07ede9a314c1a73669ee8cb0d854c8a3206dcd4f532d36fa7affca1226962e20ca2c6ca0da1ab0848d23d6f198681911592815c080cead9fe6c81cf0d7ce3578978dbf1dc2f1902e51f740f95b02ebff4cf25ac8d28b8e16998f5e329e9a377a82b5bc227f77c2f1ad505286aac8618799c2363a2d07d229519370be62ef0dde6525df45a7b807759b9ba1c8557bdbecb429432c4e1a84094edda567f1245ba887686342d0a31b7dbe09bd2be75516b255d2bfad9337649e86a29b0a19e16b4059c7c45e9f81db6780af6487a11f9088ea265a99d6e95535e14fe839945f8f7da9bf9142dd12c305bd41bb392cae8eb81b28fda176d4b538f4ddaaed47913cd9149d934ca36879718bbd76a2d7ce11e6294398ea433af6cf53b951974ec96a9527178b6cbad3088a2e2dc75113fa88ede462e68b4d6b63020a45e94fbc6c3e6677d6cffee0e3bf606cd2d4b9fac89f91db8f3a1fb9f506708314249fa5c36912e3cb281acbdec3b080735ae24ebb4bca3c7900c21175435afbe5024a706e90f8ecf257c99cd8b67b5a9c2bdc2bb624201f55882349526f8faf463eecb183635db72a6aef5fa2048d97e6f6c513598f49158050df1efc6b13b8ae396cd6a905c26b94d1d50d361f10c0362a8c206c7dd553dd8b116694aa82ac029c64aa71b8a307793da12f93ce030d3c42443c37b91043687befb7968da97ffe91d45e4fd506ba4d9c5d7fe5ac7433fb6bb3ce471f59ade734d109d2093fa119827b65a360f2128e7e85ab494609b60d6e236ed8a72984f6c75652f5baa07e2e921365af2b819eef58343e65ffb45ba8580d62f5b8a9988f7176c1559f8ede3b1b92e0ff27978fc5225ed1512b605f1fd4fce46e768970b11a7b4802c93eb05a8571887cdc15f69929eadcd1f9d08ed2d6aab2997ffa2102c2d8983a78ad43779d03aa612ecbbdde634b14e980b176f04f99efad82a04001f34d6addb89e0ce629856f5ad401fed1a2c046e1fe18741b24d4253830af94a1defeecdf6f70b430e48d7b2e4ae2fb331322d96e1a361e4dcae1d0865e7ccc4aa58bcbb3ad1ce0b294437887e03088a6bb4c92c3044bb33d2a893975023ad979fb2f84d4842326cf058595398779116245c452e54989df0591238af63c5b187d18457f008f2759ae470282ee4640e92639a46915fb67f22967beb1f46736aa9c90df08f39ee481f6859f9eafdecd473bdc24ef3ad71b4c54dde360f2d550db18af7589c8107f29b0a713b65f039da10c2dc55e408ce75c77aba97c116ab078ed1467464fe4041668228316f0fff7c0e0f1a3cc47aae570182197cc3a030a4af7fe2d401b5a13d59b8fe55d48b0667b782cbf1c2e9e491167d87830bb25008aff93c4459a3ce9fd8655a542c6311d91ec6b6bd7935aba1cd01d10439f5e5a3883566c8538edb97c5d2a7c7533d415973729f52dc03134f3d777b7ad07c0f5b0d985ca48fde6cce9ec99f1223f476dcfbb5ef865a3f54459415b25e2031eeb469c83ac68fd77e59c6b6a4b9543a943c4461e47e94d038c63abf2734a3c0e99b95505e13af6cf7b66840dc60e96fb218436ea00b4a577c2effdba43e6adf97cb47c0ce606e87a7834dec04396c1e4f7df59ae5acedfd1d68c87e405fc5d788884686270cb08f0fb15fe8b11589792f9afc11152cd45f43fac6e758588cfaa88874267c3096bd689108bbb0296f3d182df7d46cf7e6b8bb923ba887443c3d2211785e364c1e55d4e9396d950e50cc11ba9a4da70a64f6acbbcd421183eb2c0521054c4f39650409e21a9d3b781725b0c38abce7b4615fa64a9cbf71a19f7e414279a7494d2e66e4e2b2d5ce7027109cfc763a9dcac37065ae80ec0cf3962deec0f9eba3bd7c514a9854ddec6542cf60a1e69cf5d1a73239633675d4ac1f3b0758e69d1d9fb8659f43f07ef6b0b2a7c9740649198b44f3272a8810d374b00c1d49b7f667ed538d89e91e5734f8d6e270aef0a406fcb4072497dd5f25b49d31cfd64f7af2d5b4df72b74c39a66f442ae61aebe1cdb96b660e3248dad3d05bfce3d8630902a565c3a7636220e0435679ce1c45367570dd08722ddfe7f1bf56c44bcab8ef2d0979eeaa569dade4ec34751833d455b31b55edcb9b64f3045725fcd3a08ce0c20b09a437133df5738092eba91430208814b4135b0a64331aff1847ca60426c91e96a029cff039b14462da6e5f9c545980b3712f7fa5f3958d92278194cf6b37ef76e91103d14db403956a7070d87afa81df227f2189926e1265a2872e9d64c64496083caff36dd3c27e961957acb86f0f9a3cbb5ddbb6bf9c62dc102d70d62eea969b1c2c5f42823f76827e918ffa77cc12ca8d31effd0b55529c496da762b6a95d43360ea4e811979ee316e143733f886a6eca5ac76746d4a302ec57b6b4af57c25631d7773243abd400d15274703154dfde2f1a63e075e4b22ed4516dd1496e3f7848bbf19e3215edda64140649d9b1a06975773d5dd0ca9c4bdfd5eb9fb6164aa659e2a8415098dd05496d0b2a20d966a4c9efefa964e007a3b731d3bad501fd21ca564c6155d893c3075c234af6378a12595d8a88ae0518350b75d57fb91b7610bfc3168f548a9a63432b49a9dbee2ee1a4ddd80255e2c655cc80d59d7e90e21fb090db6d59ef84c0becfda6bd01c5a806ce67bea77fdba62ba40e2114d31e6087ad67b28adc20d7cabe7911aa2db119cf5f43b2011bb92556e8e303a264f813764027fbec36f8248a667c766cfc12c80d96965f222d39b5f58a54b255d3b1eb4530952b6d251ff1f9a2cbc585d539704c8ea6884699ebc95d57cd1daef169da86cc10fe7300352e939c35bbe3104aea1b1c681f3e98be8fad7c91bb56724ffa794ea4ac7c4d51d4aad8e94087b4cdcab897e70558e6648ab42dfadab447735912af011fdbd9a47a4958b953b01d2e274449854cb7d4b44d88fb2db162b8dd664c7c32858c7714c69b838cb30b17e6a42ca760256c4c6da57ad5be955ca8c787262d8bd3f4a5f0170e70f92ee2ec9d227d066e41d0d4b640166b2f6937a66bc84506d102d3edac818b246954ba200a3057820da10b64ff99f016b42d90a29b43290d731ef23a72612d646f92acc05620068fd94edd12902197733cc9dbb55d95930ccc749c4a169b4b7056dba24f767da022eb01243353e1f4d0af2eb32e3feb331283ceab3e0112b37556749a701d11ada5cbe1b4c829fac46e12612679e47d4a066be939b886f0fdc2b4c5b4dd183ca025c5191ac67d7f992643333504da30e8300a0b40152671", 0xf12}], 0x4)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x0, 0x10, r0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x80206979, &(0x7f00000001c0))


r0 = open$dir(&(0x7f00000003c0)='./file0\x00', 0x400004000011830a, 0x0)
pwritev(r0, &(0x7f0000000340)=[{&(0x7f0000000080)='\x00', 0xfcaa}], 0x1, 0x126)
truncate(&(0x7f0000000100)='./file0\x00', 0x30021)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
setitimer(0x0, &(0x7f0000000000)={{0x100000000}}, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = dup(r0)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
socket(0x18, 0x2, 0x0)
ioctl$TIOCSETAF(0xffffffffffffffff, 0x802c7416, &(0x7f0000000100)={0x0, 0x0, 0x0, 0x0, "bb08000100f1675910812cc900"})
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f0000000300)=""/47, 0x2f}], 0x1)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1400000029"], 0x3e}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f00000001c0)=[{0xc}, {0x44}, {0x8126}]})
syz_emit_ethernet(0x4a, &(0x7f00000001c0)=ANY=[])


r0 = openat$null(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
preadv(r0, &(0x7f0000000440)=[{&(0x7f0000000140)=""/89, 0x59}, {&(0x7f0000000200)=""/85, 0x55}, {&(0x7f0000000040)=""/31, 0x1f}, {&(0x7f0000000280)=""/93, 0x5d}, {&(0x7f00000000c0)=""/50, 0x32}, {&(0x7f0000000300)=""/41, 0x29}, {&(0x7f0000000340)=""/164, 0xa4}, {&(0x7f0000001940)=""/57, 0x39}], 0x8, 0x2427)
fcntl$lock(r0, 0x9, &(0x7f0000000100)={0x0, 0x0, 0x0, 0x100000000})
dup(r0)
r1 = openat$null(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
r2 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r2, 0x6, 0x2, &(0x7f0000000000)="c772b2db", 0x4)
r3 = getpgrp()
fcntl$lock(r2, 0x9, &(0x7f0000001900)={0x1389abbbccbcabf3, 0x1, 0x63d5e250, 0x5a, r3})
fcntl$lock(r1, 0x9, &(0x7f0000000100)={0x1, 0x2, 0x80000000, 0x2fffffffe})
fcntl$lock(r0, 0x9, &(0x7f0000000000)={0x2, 0x0, 0x200, 0x1})
r4 = openat$null(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
pipe(&(0x7f00000004c0)={<r5=>0xffffffffffffffff})
accept$inet(r5, &(0x7f0000000500), &(0x7f0000000540)=0xc)
fcntl$lock(r4, 0x8, &(0x7f0000000100)={0x2, 0x0, 0x7, 0x100000000, 0xffffffffffffffff})
r6 = openat$null(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
fcntl$lock(r6, 0x8, &(0x7f0000000100)={0x0, 0x0, 0x7, 0x2fffffffe, 0xffffffffffffffff})
socket$inet(0x2, 0x0, 0x0)
r7 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
r8 = semget(0x3, 0x2, 0x10)
semctl$SETALL(r8, 0x0, 0x9, &(0x7f0000000400)=[0xe57f, 0x8001])
ioctl$VMM_IOC_RUN(r7, 0xc2485607, &(0x7f0000000040)={0x2, 0x0, 0x0, 0x0, 0x0})


writev(0xffffffffffffffff, &(0x7f0000000300)=[{&(0x7f0000000180)="98d926cc1c68bcafda73d24239c0ec64cb0f13f5df63fa33a13c37427233489492cb7aa9893eb485b2422794d5a835bd5ea43cc591eb21d9b52584162d5ecc8d9a39", 0x42}], 0x1)
r0 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f00000001c0))


madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000))
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
sysctl$vm_swapencrypt(&(0x7f0000000000)={0x6, 0xb, 0x1}, 0x3, 0x0, 0x0, 0x0, 0x0)
sysctl$hw(&(0x7f0000000000)={0x4, 0x1}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
sysctl$vm_swapencrypt(&(0x7f0000000000), 0x3, 0x0, 0x0, 0x0, 0x0)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x3}, 0xc)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x34}, 0x4, &(0x7f0000000080), 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x400, 0x0)
socket(0x11, 0x3, 0x0)
r1 = socket(0x1, 0x1, 0xff)
r2 = socket(0x20, 0x8000, 0x0)
dup2(r2, r1)
sysctl$vfs_nfs(&(0x7f0000000040)={0x7, 0x4}, 0x3, 0x0, 0x0, 0x0, 0x0)
connect$unix(r1, &(0x7f0000000100)=@abs={0x0, 0x0, 0x3}, 0x8)
socket$inet(0x2, 0x2, 0x0)
r3 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x200000000000b, &(0x7f00000000c0)='\x00', 0x1)
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000480), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x2c}, {0x35}, {0x46}]})
syz_emit_ethernet(0x3e, &(0x7f0000000d40)={@local, @random="94ea09066dbd", [], {@ipv6={0x86dd, {0x0, 0x6, "db8344", 0x8, 0x0, 0x0, @rand_addr="135e80f1d38ddba80b9e61dd0c575a88", @local={0xfe, 0x80, '\x00', 0x0}, {[], @udp={{0x0, 0x2, 0x8}}}}}}})


r0 = socket$inet(0x2, 0x1, 0x0)
listen(r0, 0x0)
shutdown(r0, 0x2)
close(r0)


socket(0x11, 0x3, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x8014695a, &(0x7f00000001c0))
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
kqueue()
kevent(0xffffffffffffffff, 0x0, 0x101, &(0x7f0000000180), 0x6, 0x0)
r1 = socket(0x2, 0x2, 0x0)
sysctl$vm(&(0x7f0000000140), 0x2, 0x0, 0x0, 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x58})
r2 = syz_open_pts()
close(r2)
sysctl$net_inet_etherip(&(0x7f00000002c0), 0x8, &(0x7f0000000580)="342b35f6fe9d7dffdc84ad82f1d3038f54d36689dcbaf12918d3fe750f3e38c07ff663434b78e054f78ae59750cde76d4e7a7c200bfda1064060a3e742cf0d64f0a1cda3d7367c0b9f53b16fefb530f0632503c7fa815f4d867abf74807e86d6212a40575f817f6b4ea91535071678f266334235a1d3bf4a04b961cf9e12e167f9ea968d18d199229be6a273e49313808c92531c1d10e0472f654ccd2d82790251e8744ede89da931b48c9f76e00cc62ba0efdb264ac4eb72cda86d5a1de5a289e7738f4819cd8261400bf82a935f60a4a6c02abbf516b0107550226b0cad36279fe66f2d1", 0x0, 0x0, 0x37)
syz_open_pts()
writev(r2, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)
ioctl$BIOCSETWF(0xffffffffffffff9c, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x3}, {0x6, 0x0, 0x0, 0xbe}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0xfffffffffffffe59)
sendmmsg(0xffffffffffffffff, &(0x7f00000007c0)={&(0x7f0000000780)={0x0, 0x0, &(0x7f0000000400)=[{&(0x7f0000000180)="b860fe09625ee6793978a575faa1b6c6c1d6c2eca2950e663d39ab1be31a269a39fd7f97e41e178f37a79f00659c2ea9ac56733f7e4e4973c1e6b33ac91343ea3b3f8c5c7b93d5c20ab4211791fe30", 0x4f}], 0x1, 0x0}}, 0x10, 0x0)
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x80206979, &(0x7f00000001c0))
r4 = shmget$private(0x0, 0x1000, 0x10, &(0x7f0000ffe000/0x1000)=nil)
shmctl$IPC_STAT(r4, 0x2, &(0x7f0000000540)=""/173)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0xc0185603, &(0x7f0000000500)={0xe9, 0x0, &(0x7f0000000400)=""/233})
ioctl$FIONREAD(r1, 0x80206919, &(0x7f00000001c0))
ioctl$VMM_IOC_RESETCPU(0xffffffffffffff9c, 0x82405605, &(0x7f0000000100)={0x0, 0x0, {[0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6], [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1ff, 0x0, 0x2], [], [], [{}, {}, {}, {0x0, 0x0, 0x0, 0x1000000000000}, {}, {}, {0x0, 0x0, 0x5}]}})
sysctl$net_inet_tcp(&(0x7f0000000080)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f00000000c0)="9b1809c3dd7d3f81670e53473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6fd74c94d1b44", &(0x7f0000000040)=0xfff9, 0x0, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000800)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000000), 0x2cfea}], 0x1000000000000013)
close(r0)
execve(0x0, 0x0, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000000)=[{0x5}, {0x28}, {0x6, 0x0, 0x0, 0xfffffffc}]})
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000080)="35b5c242413c1026089a59583cc3", 0xe}], 0x1)


sysctl$vfs_ffs(&(0x7f0000000000)={0x4}, 0x3, 0x0, 0x0, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000000)=0x7, 0x4)
mprotect(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x1)
sysctl$vfs_nfs(&(0x7f0000000000), 0x7, &(0x7f00000025c0), 0x0, 0x0, 0xffffffffffffff2d)


mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x2801)
open(&(0x7f0000000280)='./bus\x00', 0x0, 0x0)


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{}, {}, {0x6, 0x0, 0x0, 0x3}]})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x6, &(0x7f0000000080)="ae215599fed2fce97f573b9c553a0e622d29cd093849cd4fe42e0f5d2d06a4e744f0713d1fcaa1b8274dffd067d413ef9d2224d3fddc171f73a295b6ed18b3d0588be75e78a1d734e15bfe", 0x0, 0x0, 0xfffffffffffffd37)


mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
r1 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
writev(r1, &(0x7f0000000340)=[{&(0x7f0000000000), 0x2cfea}], 0x1000000000000013)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x0, 0x10, r0, 0x0)


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000003c0)={0x0, &(0x7f0000000140)})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{0x0, 0x0, 0x0, 0x9}, {0x2, 0x0, 0x0, 0x80000000}, {0x9}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0xfffffffffffffe59)
mknod(&(0x7f0000000000)='./file0\x00', 0x1, 0x6381)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(r0, 0x80185760, &(0x7f0000000080)={0xc4a2, 0x80, {0xffffffffffff0000}})
socket$inet6(0x18, 0x0, 0x0)
setrlimit(0x0, &(0x7f0000000980)={0x7})
r1 = syz_open_pts()
close(r1)
r2 = syz_open_pts()
ioctl$TIOCSETA(r2, 0x802c7414, &(0x7f0000000000)={0xfffff5e7, 0x0, 0x7, 0xffffbff2, "1010264d007c260000000000000000e1ffffff00"})
writev(0xffffffffffffffff, 0x0, 0x0)
getsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1000, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
syz_emit_ethernet(0xe, 0x0)
mknodat(r0, &(0x7f00000001c0)='./file0\x00', 0x2000, 0x0)
msgget(0x1, 0x408)
msgsnd(0x0, 0x0, 0x9, 0x0)
r3 = semget$private(0x0, 0x7, 0x0)
semop(r3, &(0x7f0000000200)=[{}, {0x3, 0x3ff, 0x1800}, {0x1}, {0x4, 0x201}], 0x4)


r0 = syz_open_pts()
close(r0)
msgget$private(0x0, 0x342)
dup(0xffffffffffffffff)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
socket(0x2, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
semctl$SETALL(0x0, 0x0, 0x9, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f00007a5000/0x3000)=nil, 0x20000000000000}, {&(0x7f000096f000/0x1000)=nil, &(0x7f0000ffb000/0x4000)=nil, 0x9}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil, 0x10000000000}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000000000/0xc00000)=nil}, {&(0x7f0000a31000/0x3000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f00002dc000/0x4000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f000032e000/0x800000)=nil, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000015000/0x3000)=nil, &(0x7f000015e000/0x2000)=nil}, {&(0x7f0000893000/0x1000)=nil, &(0x7f0000487000/0x2000)=nil, 0x400000000000000}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil}], './file0\x00'})
socket$inet(0x2, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x2, &(0x7f0000000080), 0x0)
mprotect(&(0x7f0000ff3000/0x2000)=nil, 0x2000, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000300)=[{&(0x7f0000000140)="f005c71031c1c5f421277b09000000000000007a091a2f47be787538ec7a89ec5ed66daa731ddc384ecc690869a0aa2266affdf772d7a360ee0f15fa664f557bb45071fe9b6d9d28e6e2589000f6a64f370b9e336987d77b38f7aada5309e46a81e0e2efa087aa9f5f89934fdbd2ed96e7234b8972b273e810ca9962a8f461d3a05711a63027321ff62c", 0x8a}], 0x1)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000002c0)={<r1=>0xffffffffffffffff})
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
getuid()
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x25}, 0x4, 0x0, 0x0, 0x0, 0x0)
utimensat(0xffffffffffffffff, 0x0, 0x0, 0x0)
pipe2(0x0, 0x0)
socket$inet(0x2, 0x0, 0xee)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000240), 0x0)
getsockopt(0xffffffffffffffff, 0x0, 0x20000009, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x1e, 0x2, 0x2}, 0x4, &(0x7f0000000400)="1d8331ff33152496caf57a91d237244f1e40016fd209e1cd1b2b99c03ae8daa6d7c12de17f2b8614faaa52c2d738b671f9c8ef454055de625c19bbac379eabb2c1013084762426547b8a4728c41d93b7b8abcb3cfbbbadb4a7af6c00356689e6a0ca7c0f486ef7ca0441", 0x0, 0x0, 0x0)
openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)


r0 = syz_open_pts()
syz_open_pts()
syz_open_pts()
open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
socket(0x1, 0x2, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x2, 0x1, 0x0)
connect$unix(r1, &(0x7f0000000000), 0x10)
close(r0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000080)=[{0x84}, {0x2}, {0x8106}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


listen(0xffffffffffffffff, 0x0)
select(0x0, 0x0, 0x0, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x20000000000, 0x0, 0x0, 0x0, 0xfffbffffffffffff}, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))
open(0xfffffffffffffffe, 0x0, 0x0)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000000600)={0x0, 0x0, 0x0, 0x0, &(0x7f00000005c0)=ANY=[@ANYBLOB="10000000ffff000001"], 0x10}, 0x0)
r0 = socket$unix(0x1, 0x5, 0x0)
sendmmsg(r0, &(0x7f0000000600)={0x0}, 0x10, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000001080)=[{0x1}, {0xc}, {0x6, 0x0, 0x0, 0xfffffff8}]})
write(r0, &(0x7f0000000200)="b1c05b5fb165120a4224a763037a", 0xe)


r0 = socket$inet(0x2, 0x3, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x6b, 0x0, 0x0)


sysctl$vfs_ffs(&(0x7f0000000000)={0xa, 0x3, 0x13}, 0x3, 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
open$dir(&(0x7f0000000b80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x200, 0x0)
sysctl$vfs_ffs(&(0x7f0000000480)={0xa, 0x1, 0xa}, 0x3, &(0x7f0000000800)="7c8c784b291bb34857f4d3d63c37aa5ea17de3e8e4be8bb7ccfee94dec01962b09698aae", &(0x7f0000000840)=0x24, &(0x7f0000000ac0)="8da96749c33c0f", 0x7)
r0 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000300)='./file0\x00', r0, &(0x7f0000000c80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f0000000dc0)='./file0\x00', r0, &(0x7f0000000ec0)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mkdirat(r0, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
symlinkat(&(0x7f0000000700)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', r0, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000980)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000a80)='./file0\x00')
rmdir(&(0x7f00000001c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
pipe(&(0x7f0000000100)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
getpid()
ktrace(&(0x7f00000001c0)='./file0\x00', 0x0, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
unlink(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
unlink(&(0x7f0000000880)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
unlink(&(0x7f0000000080)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000d80)='./file0\x00', &(0x7f0000000180)='./file1\x00')
r2 = openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x8, 0x0)
getdents(r1, &(0x7f0000000fc0)=""/202, 0xca)
ioctl$PCIOCWRITE(r2, 0xc00c7006, &(0x7f0000000300)={{0x0, 0x1}})
openat$vnd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000080)={0x4, 0x2, 0x0, 0x25}, 0x4, &(0x7f0000000140)="e33745e84d5ebfb9cc2f7fa3a7f7891721720e69dac610a4fb5e8c3e3c6e1d648a8ca6ebc70f949c442aee9dc79e2cd74f4e106f382caf01ada3bc4efb0f6bc50690e5492f4a0491b1ea3359aa5c5164ad97ac7c3aadca05fd9e9a8c0f962f5167b69cfdc8287fc34b8138340e60c404a855858ea5fc", &(0x7f0000000000)=0x10045, 0x0, 0x0)
r3 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x200100000001d, &(0x7f0000000600)="37ee5c233f6ca01cbea0e2b8b21b48af2ac4100555a53d775edf0f84689e45fb527c85525c828e9965b037ef7b7b10dc6bd8a816defd35778568d8c783d361818c23bf89fc50a22d831d89aed718773afe7ae1142b05070a07c5f6be79210ebe7abe6eb37627310b6a51f0b050d7cb8c092ca81f05be40b949fa", 0x7a)
getsockopt$sock_cred(r3, 0xffff, 0x1022, &(0x7f0000000000), &(0x7f00000000c0)=0xc)
r4 = semget$private(0x0, 0x4, 0x266)
semop(r4, &(0x7f00000005c0)=[{0x2, 0x2, 0x1000}], 0x1)
socket$inet(0x2, 0x3, 0xc0)


semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000300)="b100050160000000ff01000007000000330002000000000000f96ecfc72fd3357ae320b37b673039d2d236acf20b7804be0600aa5b236de351e2f0139b672f4d335d223e7d026ba8af636aa9003728210200001b720fd38bfbb770c1f5a872c881eaee69e0bb76d907c400000000361bf6c8cd6d25c95aad79c76619f0ba57aea8c500002002fbff0c2300008abf0900004008e371a3f8343794ab1e0000000000000000000000000000000000f4bf25f8722661af706669198b78fccc703b7a81dd82265ac31a", 0xc7, 0x0, 0x0, 0x0)
msgsnd(0x0, &(0x7f0000000040)=ANY=[@ANYBLOB="02000000000000001df33699fb723383"], 0x55, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x3f}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0xfffffffffffffda3)
r1 = socket$inet(0x2, 0x2, 0x0)
mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
mknodat(0xffffffffffffff9c, &(0x7f00000002c0)='./file0/file0/..\x00', 0x0, 0x0)
ioctl$WSMOUSEIO_GETPARAMS(0xffffffffffffffff, 0x80105727, &(0x7f0000000080)={0x0})
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r2 = msgget$private(0x0, 0x0)
socket$inet(0x2, 0x1, 0x0)
getsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
msgsnd(r2, &(0x7f0000000100)=ANY=[@ANYRES64=r1], 0x107, 0x0)
msgrcv(r2, &(0x7f0000003c00), 0x1013, 0x3, 0x0)
setrlimit(0x8, &(0x7f0000000000)={0x6, 0x200})
msgctl$IPC_RMID(r2, 0x0)
r3 = socket(0x18, 0x2, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r3, &(0x7f0000000080), &(0x7f0000000000)=0xffffffffffffffc6)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
socket(0x18, 0x1, 0x0)
openat$null(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0x40000802)
open(0x0, 0x0, 0x0)


dup(0xffffffffffffffff)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
dup(0xffffffffffffffff)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
execve(0x0, 0x0, 0x0)
mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x205b9b)
r0 = openat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x0, 0x0)
poll(&(0x7f00000000c0)=[{}, {r0, 0x4}], 0x2, 0x0)
select(0x2f, &(0x7f0000000040), &(0x7f0000000080)={0x4000000000000008}, 0x0, 0x0)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd02)
open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0x81946466, &(0x7f0000000040)={0x0, 0x0, 0x0})


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80146959, &(0x7f00000001c0))


r0 = socket(0x18, 0x3, 0x0)
getsockname$inet(r0, &(0x7f0000000080), &(0x7f0000000000)=0xfffffffffffffe22)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x800000018, 0x2, 0x0)
bind$unix(r1, &(0x7f0000000080)=@abs={0x0, 0x7}, 0x1c)


sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x2}, 0x4, &(0x7f0000000080)="9b1809ff", &(0x7f0000000040)=0x4, 0x0, 0x0)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
chmod(&(0x7f0000000080)='./file0\x00', 0x40)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000380)='#!', 0x2}], 0x1)
writev(r0, &(0x7f0000000100)=[{&(0x7f00000003c0)}], 0x1)
open(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r1 = socket(0x1, 0x2, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f0000000080)={0x10, 0x0, [{&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffb000/0x5000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000c66000/0x1000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000d91000/0x4000)=nil}, {&(0x7f0000f56000/0x1000)=nil, &(0x7f00008fb000/0x2000)=nil}, {&(0x7f0000e4c000/0x4000)=nil, &(0x7f0000efd000/0x1000)=nil}, {&(0x7f0000cd3000/0x1000)=nil, &(0x7f0000862000/0x2000)=nil}, {&(0x7f0000d3d000/0x4000)=nil, &(0x7f0000aff000/0x1000)=nil}, {&(0x7f0000f6a000/0x2000)=nil, &(0x7f0000887000/0x4000)=nil}, {&(0x7f0000da1000/0x4000)=nil, &(0x7f0000b4b000/0x3000)=nil}, {&(0x7f0000e0f000/0x2000)=nil, &(0x7f0000e03000/0x3000)=nil}, {&(0x7f0000c64000/0x14000)=nil, &(0x7f0000d93000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000d40000/0x3000)=nil}, {&(0x7f0000913000/0x2000)=nil, &(0x7f0000c5e000/0x4000)=nil}], './file0\x00'})
r2 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0106978, &(0x7f00000001c0))
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000132000/0x3000)=nil, &(0x7f00001bf000/0x3000)=nil, 0xc0400000}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f0000001000/0x2000)=nil, &(0x7f0000093000/0x1000)=nil}, {&(0x7f0000334000/0x1000)=nil, &(0x7f000008a000/0x3000)=nil}, {&(0x7f0000066000/0x1000)=nil, &(0x7f0000133000/0x1000)=nil}, {&(0x7f000008a000/0x4000)=nil, &(0x7f000013e000/0x2000)=nil}, {&(0x7f0000323000/0x4000)=nil, &(0x7f000002a000/0x3000)=nil}, {&(0x7f000008d000/0x4000)=nil, &(0x7f0000089000/0x4000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000027000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffa000/0x4000)=nil}, {0x0, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000249000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000100000/0x5000)=nil, &(0x7f0000092000/0x3000)=nil}], './file0\x00'})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000800), 0x0, 0x0)
r1 = syz_open_pts()
ioctl$TIOCCONS(r1, 0x80047462, &(0x7f0000000240)=0xc)
ioctl$VMM_IOC_RUN(r0, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0})


mkdir(&(0x7f0000000500)='./file0\x00', 0x0)
chmod(&(0x7f0000000180)='./file0\x00', 0x23f)
chdir(&(0x7f00000001c0)='./file0\x00')
r0 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
mkdirat(r0, &(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
mkdirat(r0, &(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
renameat(0xffffffffffffff9c, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', r0, &(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000140)={0x0, 0xfffffffffffffffb})
r0 = kqueue()
kevent(r0, &(0x7f00000000c0), 0x7, 0x0, 0x80000001, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x7, 0x0, 0x80000001, 0x0)
close(r0)


sysctl$hw(&(0x7f00000000c0)={0x7, 0xf}, 0x2, 0x0, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x1, &(0x7f0000000080)=[{0x34}]})


socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000000c0)={<r0=>0xffffffffffffffff})
sendmsg$unix(r0, &(0x7f0000001280)={0x0, 0x0, &(0x7f0000000440)=[{&(0x7f0000000100)="de7a022065cd6a454bb319cb2527f3c54b315461030856506f307270f54c5e1d1c681387532d3fdeaa94427c2a6825e7f887a52561d4ec1241f216afdf205490", 0x40}, {&(0x7f0000000180)="bf3b684c5ae963b4567084e096cf973983b85e5df63e013eaa9405095e88157332b4f68e78e0793d3e30417acbf4419893cfd424b75262dc5ade2ab6278ab86672f9ed186987b8c19d9295a17b", 0x4d}, {&(0x7f00000003c0)="abc202f19ff056d11695a1d44340c59742248ad3111df8e0e6b22543cd675ba8bd0dc14042b5162fa8402ca3d414fbc25fecc7d09f4addf7f734766898992a474eba83f87703322cac720791f8fa45d861c11ed55de1479aef0c5f7631b34cd2ce", 0x61}, {&(0x7f0000000780)="60ac101744c5712a328c101125276227c811e5379b54a4de38dab3bb8079ea5d2f3b84e700a42d70fa6ea15bd1d8a60bc2c533fe160d9680d8c68d0955f522a78c83f8318277641f3c1cf9c387fb8b588d6eb8441d5683af2690e3b3792721aedccec0ea9a82d2ffd4132a82dcf7333987cbb8e6d0a6d9077f310ea31a64507d66cb8c", 0x83}], 0x4, &(0x7f0000001240)=ANY=[@ANYBLOB="18000000ffff000001"], 0x18}, 0x0)


sysctl$net_inet_esp(&(0x7f0000000140)={0x4, 0x22, 0x32, 0x3}, 0x4, &(0x7f00000000c0)="00d5a153fcbb42fc4b67223b8998951ab3b14275d4e6ad8093870566ef975560ce0487b6598e5caef3d4356f70e7a206056d354d9a3d0fe05929ab2c2a202f222317b63e024efaffffffffffffffbe2fe466041419f69ee3b6bb16d91f26559ff54a2cae377653a35b52e2f85d33e009a106adfff5bc74bd", 0x0, 0x0, 0x0)
syz_emit_ethernet(0x36, 0x0)
socket$inet(0x2, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
r0 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
ioctl$FIONREAD(0xffffffffffffffff, 0x4004667f, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="0002"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r1 = socket(0x2, 0x1, 0x0)
bind(r1, &(0x7f0000000000), 0x10)
listen(r1, 0x0)
connect$unix(r0, &(0x7f0000000000), 0x10)
write(r0, &(0x7f0000000080)="04bdfa5d1d2873c63e3534825ba166e2fea9aec43050006123339a346f731573d8d508753f95b7688ad48b8cf6bbca325cebc37fc4e1dd543dbe2da6dd", 0xffea)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
openat$vnd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x6c}, {0x2c}, {0x6}]})
syz_emit_ethernet(0x62, &(0x7f0000000480)=ANY=[])
mknod(&(0x7f0000000040)='./file0\x00', 0x6000, 0xe02)
r2 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
pwritev(r2, &(0x7f0000000080)=[{&(0x7f0000000480)="1f", 0x1}], 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000700)=[{0x2}, {0x2c}, {0x6, 0x0, 0x0, 0xfffffffe}]})
write(r0, &(0x7f0000000540)="76e5dead6f01f8607d2100000063", 0xe)


r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
pwritev(r0, &(0x7f0000000380)=[{&(0x7f0000000440)="e9", 0x1}], 0x1, 0x3fffd)
truncate(&(0x7f0000000140)='./file0\x00', 0x30001)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)


setreuid(0xee00, 0x0)
r0 = getuid()
setuid(r0)
r1 = syz_open_pts()
fcntl$getown(r1, 0x5)


r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r0, 0x80085761, &(0x7f00000000c0)={0x3})
ioctl$WSKBDIO_GETDEFAULTKEYREPEAT(r0, 0x400c570a, &(0x7f0000000000))
r1 = open(0x0, 0x200, 0x0)
getpid()
utimensat(r1, &(0x7f0000000140)='./file0\x00', &(0x7f00000001c0)={{0x6, 0x7fffffff}, {0x1000, 0x1}}, 0x0)


r0 = socket(0x2, 0x3, 0x0)
socket(0x11, 0x3, 0x0)
open$dir(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
r1 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
getsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000300), 0x0)
sysctl$kern(&(0x7f0000000000)={0xa, 0x4b}, 0x2, 0x0, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000040)='./file0\x00', 0x2950, 0x0)
openat$vnd(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
socket(0x0, 0x1, 0x0)
sysctl$kern(0x0, 0x0, 0x0, &(0x7f0000000080), 0x0, 0x0)
pwritev(r1, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
socket(0x10, 0x0, 0x0)
syz_emit_ethernet(0x1db, &(0x7f00000007c0)=ANY=[])
r2 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
utimensat(0xffffffffffffff9c, &(0x7f0000000040)='.\x00', &(0x7f0000000080)={{0x0, 0xffffffffffffffff}, {0x0, 0xffffffffffffffff}}, 0x0)
r3 = socket$inet(0x2, 0x3, 0x0)
r4 = open$dir(&(0x7f0000000580)='./file0\x00', 0x40000400001803c1, 0x0)
ftruncate(r4, 0x80002)
recvmsg(r3, &(0x7f0000000500)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000400)=""/220, 0xdc}, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r2, 0x0)
execve(0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
connect$unix(r0, &(0x7f0000000280)=@abs={0x0, 0x0, 0x3}, 0x8)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x800, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
pwrite(r0, 0x0, 0x0, 0x0)
sysctl$hw(&(0x7f0000000040)={0x6, 0x12}, 0x2, 0x0, &(0x7f0000000140), &(0x7f0000000280)="f9e2f7b365ec5b6cb4011aea2f3ec01f918319dfd0acbda6720d5eb874d79f78178bb79d0f4a00000000000000009c36", 0x30)
sysctl$hw(&(0x7f0000000000)={0x6, 0xc}, 0x2, &(0x7f00000000c0), &(0x7f0000000100), &(0x7f0000000180)="1d34f1ea20630ae366188c9fb998a0ad7d02751277f665ed375a84e9d6dcdc488662f374bb1cdee94947d2f474731c6bf9439bca85be8c8c9914bf4ebad8c6cb5737ff84", 0x44)
pipe(&(0x7f0000000200))
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
r1 = open(&(0x7f0000000000)='./bus\x00', 0x2, 0xfc)
r2 = socket(0x2, 0x2, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001280)={0x0, 0x0, &(0x7f0000001200)=[{&(0x7f0000000180)="bf3b684c5ae963b4567084e096cf973983b85e5df63e013eaa9405095e88157332b4f68e78e0793d3e30417acbf4419893cfd424b75262dc5ade2ab6278ab86672f9ed186987b8c19d9295a17b98020f60", 0x51}], 0x1}, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r2, 0x8020699b, &(0x7f00000001c0))
read(0xffffffffffffffff, &(0x7f0000000180)=""/198, 0xc6)
ioctl$WSMUXIO_INJECTEVENT(r1, 0x80185760, &(0x7f0000000140))
setsockopt(r2, 0x0, 0x6, &(0x7f0000000040)="46647713d7e556403406bd67f36ea665", 0x10)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
open$dir(&(0x7f0000000b80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x200, 0x0)
r3 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000300)='./file0\x00', r3, &(0x7f0000000c80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f0000000dc0)='./file0\x00', r3, &(0x7f0000000ec0)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mkdirat(r3, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
symlinkat(&(0x7f0000000700)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', r3, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000980)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000a80)='./file0\x00')


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000001080)=[{0x5}, {0x50, 0x2, 0xfc}, {0xfffe}]})
syz_emit_ethernet(0xe, &(0x7f0000001100)=ANY=[])


r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
r1 = socket(0x18, 0x2, 0x0)
close(r1)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0xfffffffffffffffe}], 0x0, 0x0, 0x0, 0x0)
r2 = socket(0x800000018, 0x2, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
writev(r1, &(0x7f00000004c0)=[{0x0}], 0x1)


sysctl$kern(&(0x7f0000000000)={0x1, 0x58}, 0x2, &(0x7f0000000140)="1139a509", &(0x7f0000000180)=0x4, &(0x7f00000001c0), 0x0)


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = getppid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r0})
pipe(&(0x7f0000000400)={<r1=>0xffffffffffffffff})
setpgid(0x0, 0x0)
setpgid(0x0, r0)
ioctl$WSKBDIO_GETMAP(r1, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r2 = fcntl$getown(r1, 0x5)
ktrace(&(0x7f0000000180)='./file0\x00', 0x4, 0xd30, r2)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
pwritev(r0, &(0x7f0000000100)=[{&(0x7f0000000280)="69ec9d36a20f582b4e741017d6c5bf86166479f989871d451fe15c11652b", 0x1e}], 0x1, 0x0)
execve(0x0, 0x0, 0x0)
setegid(0x0)


sendmmsg(0xffffffffffffffff, &(0x7f00000007c0)={&(0x7f0000000780)={0x0, 0x0, &(0x7f0000000440)=[{&(0x7f0000000180)="b860fe09625ee6793978a575faa1b6c6c1d6c2eca2950e663d39ab1be31a269a39fd7f97e41e178f37a79f00659c2ea9ac56733f7e4e4973c1e6b326c91343ea3b3f8c5c7b93d5", 0x47}], 0x1, 0x0}}, 0x10, 0x0)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f00000001c0))


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000100)="b10005016000009f0000000000070000001c130500000000fef96ecfc72fd3357ae380b37b673039d2d236acf60b7804be78164991f7c8e750882b297be1aa5b23edeb51e2f0ac3ebbc215000000eeffffff028ea8af630037282102000000720fd38b000000000000361b12578ea8c500002002fbff0c2300008abfba0900000008e371a3f8343712051eeab71d89e0442c5e52000080042000"/177, 0xb1, 0x0, 0x0, 0xfffffffffffffede)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000000c0)={0x0, <r1=>0x0}, &(0x7f00000001c0)=0xc)
mknod(&(0x7f0000000000)='./bus\x00', 0x2000, 0x2cff)
open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
mprotect(&(0x7f0000521000/0x1000)=nil, 0x1000, 0x2)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r2 = socket(0x18, 0x3, 0x0)
setreuid(0xee00, 0x0)
r3 = getuid()
socketpair$unix(0x1, 0x0, 0x0, 0x0)
recvmsg(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000200)={0x0, &(0x7f0000000040)})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11, 0x0, 0x57}, 0x4, 0x0, 0x0, 0x0, 0xfffffffffffffe64)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r4 = msgget$private(0x0, 0x74d)
msgrcv(r4, 0x0, 0x1008, 0x0, 0x0)
msgrcv(r4, &(0x7f00000003c0)={0x0, ""/230}, 0xee, 0x0, 0x0)
msgctl$IPC_RMID(r4, 0x0)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
setreuid(0xee00, r3)
setsockopt(r2, 0x1000000029, 0x35, &(0x7f0000000000), 0x0)
syz_emit_ethernet(0x0, 0x0)
ioctl$FIONBIO(0xffffffffffffffff, 0x8004667e, &(0x7f0000000080))
seteuid(r1)
r5 = socket(0x11, 0x3, 0x0)
getsockopt(r5, 0x5, 0xbe4, &(0x7f0000000240)=""/39, &(0x7f0000000280)=0x27)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)='\x00', 0x1}], 0x1)
r6 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r6, 0x0, 0x0, &(0x7f00000002c0), 0x0)


open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
open(&(0x7f0000000100)='./file0\x00', 0x615, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x1000300010008})


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040))
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
recvmsg(0xffffffffffffffff, &(0x7f0000000100)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000180)=""/225, 0x11e}, 0x0)
sendmsg(0xffffffffffffffff, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
recvmsg(r1, &(0x7f0000000100)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)
close(r1)
sendmsg(r0, &(0x7f0000000380)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)


sysctl$vm_swapencrypt(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
r0 = getppid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0xffffffffffffffff}, 0x0, 0x0, r0})
pipe(&(0x7f0000000180)={<r1=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r1, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r2 = fcntl$getown(r1, 0x5)
ktrace(0x0, 0x1, 0xf32, r2)


r0 = syz_open_pts()
syz_open_pts()
setrlimit(0x8, &(0x7f0000000980)={0xb, 0x200400000000062})
syz_open_pts()
kqueue()
select(0x40, &(0x7f0000000000)={0xffffffffffffffff}, 0x0, 0x0, 0x0)
close(r0)


mkdir(&(0x7f0000000080)='./file0\x00', 0x0)
chmod(&(0x7f00000000c0)='./file0\x00', 0x63)
setreuid(0xee00, 0x0)
r0 = getuid()
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000580)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000140)=0xc)
chown(&(0x7f0000000200)='./file0\x00', 0x0, r2)
setreuid(0x0, r0)
chdir(&(0x7f0000000100)='./file0\x00')
mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0xc0e99db6de761f86, 0x0)
symlink(&(0x7f0000001340)='./file0\x00', &(0x7f0000001440)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f00000007c0)='./file0\x00', &(0x7f0000001040)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


getuid()
setreuid(0xee00, 0x0)
setpgid(0x0, 0x0)
setpgid(0x0, 0x0)
pipe(0x0)
ioctl$WSKBDIO_GETMAP(0xffffffffffffffff, 0x80047476, 0x0)
fcntl$getown(0xffffffffffffffff, 0x5)
ktrace(0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x33}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)


r0 = socket$inet(0x2, 0x3, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
setsockopt$inet_opts(r0, 0x0, 0x200000000000b, &(0x7f0000000080), 0x0)


sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
sysctl$net_inet6_ip6(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
sysctl$vfs_nfs(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
setitimer(0x2, &(0x7f0000000000)={{0x0, 0xfffffffffffffffd}, {0x5}}, 0x0)
accept$inet(0xffffffffffffff9c, &(0x7f0000000000), &(0x7f0000000040)=0xc)
getuid()
r0 = msgget$private(0x0, 0x0)
msgsnd(r0, &(0x7f0000000440)=ANY=[@ANYBLOB="000000000012000042fee188507af9149e61f61f53aaf3757ccb78896d3c837f925dc9db9108ae5e024eab385884d1d263bf23f6b047f237b3044cae340a3113198d0989c5bd76407c38f806e8f98e4e785567c23e5d0560e086fa607be55619c73ae912ec6b79ace314ffb9ff1be677be050beecd6bfe2e5449aee9b4e74dd9fd5a9fe72c37d7cebd8f0e4d766264d3c71de6d9c2d09ed3d2192220aca447f80c0a4df648ccc961660c9a475d12361a624646494b44f0dba28594a94b73fb8b7eb30574e0a9856ad8709d3459ec012de499f444d85c0a87f4bc140812221d78096d7d642600f9def393dcf631a1d4ecd9a4ba64"], 0x11, 0x800)
msgsnd(r0, &(0x7f00000006c0)=ANY=[@ANYBLOB="0300000000000000bc597b8a7110cfcfb630f8fce91c8815cdb3170494422f94d3ca7b7e6e85277277ed8b80324a3721ef9788207334532be3f0940418dfc357ad34a8ff249bd5640720a0ef96857717d47c739a7105b1f5e3f02c84cacb4f83921ee9801773dfb84f3afbcfacf7b467bf6b551d8e905c883ef3bb3011e829e5ddce4e243de033ed1ad495516771cab6167098bc69fe5984b6280e3fc97b2d624151901511c550e6d5d4ec5f930c0dcec4366ceb87"], 0xa9, 0x0)
msgrcv(r0, &(0x7f00000007c0), 0x90, 0x3, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000300)=""/117, 0x75}}, 0x10, 0x0, 0x0)
socket(0x1, 0x2, 0x80)
recvmsg(0xffffffffffffffff, &(0x7f0000000540)={0x0, 0x0, &(0x7f00000002c0)=[{&(0x7f0000000100)=""/152, 0x98}], 0x1, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
socket$inet(0x2, 0x4, 0x7)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000200))
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000380)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
recvmsg(r2, &(0x7f0000000340)={0x0, 0x0, 0x0, 0x0, &(0x7f00000024c0)=""/236, 0xec}, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x2802)
writev(0xffffffffffffff9c, 0x0, 0x0)
r3 = socket(0x0, 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
r4 = kqueue()
r5 = open$dir(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
kevent(r4, &(0x7f00000002c0)=[{{r5}, 0xfffffffffffffffc, 0x63}], 0x1f, 0x0, 0x0, 0x0)
ioctl$FIONREAD(r3, 0x80206979, &(0x7f0000000000))


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f00000000c0)=0x5)
writev(r0, &(0x7f0000000380)=[{&(0x7f0000000440)="e0", 0x1}, {&(0x7f0000000100)="6fa533b2eda506b781f8dbc069461641c8da6d2785be257e9335395711a3c7bb0641c680be122bb694db035c7ff596ddc06acd1ed5f884d1d7820bd4eb283ccca63a80435b8b57253e7fd0cb02d9ea1683186f1afd3976fcfcd3", 0x5a}, {&(0x7f0000000180)="c88483de365a5309893d38c4b4701e88a5f1d3a8e59c1f6f3790ceef13c83d3f54530552ecaeb64b69ed438e15ba62710e5e3231d50932b6d50934c3201e78970ac1b0a85527e0e1006b0cda673f8dd39b57b7643d24f61afa7cfc8683b59b741bac0d39438fe9727a8827bcb524eca9c32ec59f515d4ab671a0d3f2ca43e65ed3f69a860f304ef2f526391bd840ddc36e729d29c205f7bf7b1ae0abf525faa46cbc5ebb8599795cd4d742e70c750e4ce6d249c47e8e6a82cf9a7688df513b3f344c9bcf45e89f5ee16b01e6d8647c4129ee89d8ca4db3fe8e0abb687fb64d8140c71a1f36eb04", 0xe7}, {&(0x7f0000000280)="978f1d00f7e35bd3fd0202fdf9c0d9ccba091c2409a7f79b9e4abe9d5cf493163cb730aa61c9548a0f8519c778af0c2fc42937fbe082ac5f003b74c11c33b7cd46ccdc7fdf3649388e5865ae19b2f68dd87babc9995e727666def7155f4d7b37e145996a42cf89df895a60", 0x6b}, {&(0x7f0000000300)="b06bd2f306128f5c98b4f9afd495df0317cd4a579946d6b7d7e2d2fec6fe448e57aa462682e2d98e498e07c4ab931e43178557a5bcf7d2ac5f55577fe4943bb58cd47e701385ced5", 0x48}], 0x5)


socket(0x0, 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
syz_emit_ethernet(0x52, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
setreuid(0xee00, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, 0x0)
shmget(0x0, 0x4000, 0x0, &(0x7f0000ffb000/0x4000)=nil)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd02)
r0 = open(&(0x7f0000000540)='./bus\x00', 0x0, 0x0)
pread(r0, &(0x7f0000000000)="2beba8c5bfaaff44b437dfbb000000", 0x50cc3a, 0x80000000)


r0 = socket(0x18, 0x1, 0x0)
listen(r0, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
shutdown(r0, 0x2)
poll(&(0x7f0000000ac0)=[{0xffffffffffffff9c}], 0x20000000000000d7, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
getsockopt(r1, 0x0, 0xb, 0x0, 0x0)
open$dir(&(0x7f0000000b80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x200, 0x0)
r2 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000300)='./file0\x00', r2, &(0x7f0000000c80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f0000000dc0)='./file0\x00', r2, &(0x7f0000000ec0)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mkdirat(r2, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
symlinkat(&(0x7f0000000800)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', r2, &(0x7f0000000fc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000980)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000a80)='./file0\x00')


fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
ioctl$WSKBDIO_GETMAP(0xffffffffffffffff, 0x80047476, 0x0)
socket(0x0, 0x0, 0x0)
sysctl$vfs_ffs(&(0x7f0000000100)={0x4}, 0x3, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
r0 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
r1 = getpid()
clock_getres(0x2, 0x0)
fcntl$setown(r0, 0x6, r1)
fcntl$setown(r0, 0x6, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x9, 0x51})
r2 = syz_open_pts()
close(r2)
syz_open_pts()
writev(r2, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)
writev(r2, &(0x7f0000000040)=[{&(0x7f0000000240)="00fb", 0x2}], 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlink(&(0x7f0000000180)='./file0\x00', &(0x7f0000000280)='./file0\x00')
link(&(0x7f0000001240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlink(&(0x7f00000004c0)='./file0\x00', &(0x7f0000000e40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000600)='./file0\x00', &(0x7f0000000f40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f00000001c0)={0xc8, 0xffffffffffffffff})
r0 = open(&(0x7f0000000280)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000028000/0x4000)=nil, 0x4000, 0x0, 0x10, r0, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
r1 = socket(0x0, 0x0, 0x0)
dup(r1)
openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
r2 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
pwritev(r2, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
r3 = open$dir(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
preadv(r3, &(0x7f00000012c0)=[{&(0x7f00000001c0)=""/224, 0xfffffdd5}], 0x1, 0x0)


syz_emit_ethernet(0x61, &(0x7f00000002c0)=ANY=[@ANYRES16, @ANYRES64, @ANYRES32, @ANYRES32])
fcntl$setstatus(0xffffffffffffffff, 0x4, 0xc0)
r0 = getpid()
pipe(&(0x7f00000001c0)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
r3 = fcntl$getown(r1, 0x5)
fcntl$setown(0xffffffffffffffff, 0x6, r3)
open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
sysctl$hw(&(0x7f0000000040)={0x6, 0x13}, 0x2, &(0x7f0000000080)="c59bcbc2b136ae61", &(0x7f00000000c0)=0x8, 0x0, 0x0)
r4 = getgid()
r5 = getuid()
setreuid(0x0, r5)
fchown(r2, r5, r4)
accept(0xffffffffffffff9c, &(0x7f00000001c0)=@in6, &(0x7f0000000200)=0xc)
r6 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r7 = dup(r6)
ioctl$BIOCSBLEN(r2, 0xc0044266, &(0x7f0000000280)=0x1)
ioctl$BIOCSETIF(r6, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
syz_emit_ethernet(0x37, &(0x7f0000000200)=ANY=[])
readv(r7, &(0x7f0000000000)=[{&(0x7f0000000140)=""/26, 0x1a}, {&(0x7f0000000040)=""/17, 0x11}], 0x2)
mkdir(&(0x7f0000000100)='./file0\x00', 0x100)
getpgid(r0)
r8 = socket(0x11, 0x3, 0xc1)
sendto$unix(r8, &(0x7f0000000040)="b100050400000400000000000101000000000000cea10500fef96ec0c72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b1257aea8c500002018fbfe0c2300008abfba0900000008e371a3f83437320501eab71d89e0000405f8ffffff13000000", 0xb1, 0x0, 0x0, 0x14)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000001c0)=[{0x61}, {0x48}, {0x6}]})
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[])


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x100000000000000}})
socket(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x400000002, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r2 = socket(0x18, 0x1, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r3, 0x80104277, &(0x7f0000000c40)={0x3, &(0x7f0000000c80)=[{0x7c}, {0x2d}, {0x6, 0x0, 0x0, 0xfffffffd}]})
writev(r3, &(0x7f0000000140)=[{&(0x7f0000000080)="35b5c242413c1026089a59583cc3", 0xe}], 0x1)
r4 = dup2(r1, r2)
sendmsg$unix(r4, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


select(0x0, 0x0, 0x0, 0x0, 0xfffffffffffffffe)


open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
r0 = open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
r1 = getpid()
ktrace(&(0x7f0000000280)='./file0\x00', 0x0, 0x928, r1)
utimensat(0xffffffffffffffff, 0x0, &(0x7f0000000180)={{}, {0x0, 0x1ff}}, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
utimensat(0xffffffffffffffff, 0x0, &(0x7f0000000100), 0x0)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000380)={&(0x7f0000000340)=[{0x24, 0x10000}, {}], 0x2})


open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r0 = socket(0x11, 0x3, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1003, &(0x7f0000000080)=0x8000040, 0x4)
setrlimit(0x8, &(0x7f0000000980)={0x9, 0x100000001})
r1 = syz_open_pts()
close(r1)
syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000040)={0x2, 0x10000fdd, 0xffeefffe, 0x3, "8717f9050700000000000090d692480d51aa8000", 0xfffffff8, 0x9})
writev(0xffffffffffffffff, &(0x7f0000000280), 0x0)
pread(0xffffffffffffffff, 0x0, 0x0, 0x0)
openat$vnd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0xfffffffffffffffe)
open(0x0, 0x0, 0x0)
getpid()
getpid()
ktrace(0x0, 0x0, 0x0, 0x0)
setuid(0xee01)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
r2 = msgget$private(0x0, 0x0)
r3 = getpid()
msgctl$IPC_SET(r2, 0x1, &(0x7f0000000200)={{}, 0x0, 0x0, r3, 0x0, 0x0, 0x0, 0x80000001})


socket(0x2, 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x9, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000000)=[{{}, 0x0, 0x11, 0x0, 0x2}], 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
shmctl$IPC_SET(0x0, 0x1, 0xfffffffffffffffe)
setreuid(0xee00, 0x0)
getuid()
setreuid(0xee00, 0x0)
socket(0x0, 0x0, 0x0)
dup(0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(0xffffffffffffffff, 0x802069c1, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
syz_emit_ethernet(0x126f, &(0x7f00000000c0)=ANY=[@ANYBLOB="aaaaaaaaaaaa00000000000086dd609ded1a12390000c4a4e3434e58d025a6a8a81cf312b8befe8000000000000000000000000000aa00030000000000000101000101000401000401000103000000000100010200000000c7ab6f1eba08bf03d1805fce0ef2ab82f4a065245eccda108bec7cb23f632c993265a4cefeb77b1406d562a47d4b0054943553278b519ed107f62b5c352f8e68d83c1fd85b8e1083556d7fa2fc09a3e823fa940de6ef1b18ddb2a2dba0d2d9c1b44b20ed3a932a2c47"])
sysctl$net_inet_ip(&(0x7f00000000c0)={0x4, 0x2, 0x0, 0x1b}, 0x4, &(0x7f0000000100)="3d7a1499", &(0x7f0000000140)=0x4, &(0x7f0000000180), 0x4)
fcntl$dupfd(0xffffffffffffffff, 0xa, 0xffffffffffffffff)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc1206949, &(0x7f0000000100))


setrlimit(0x8, &(0x7f0000000980)={0x42})
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000140))
r0 = kqueue()
kevent(r0, &(0x7f00000000c0), 0x7, 0x0, 0x80000001, 0x0)
r1 = syz_open_pts()
sysctl$vm(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r2 = openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mprotect(&(0x7f00006c8000/0x3000)=nil, 0x3000, 0x6)
r3 = openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
preadv(r3, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfe}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/230, 0xe6}], 0x3, 0x1)
syz_open_pts()
setsockopt(0xffffffffffffffff, 0x1000000000029, 0xa, &(0x7f0000001980), 0x0)
close(r3)
syz_open_pts()
r4 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000040), 0x80, 0x0)
ioctl$FIONBIO(r4, 0x8004667e, &(0x7f00000003c0)=0xb1)
minherit(&(0x7f0000ff4000/0x4000)=nil, 0x4000, 0x0)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000400)={0x3, 0x40, 0x20, 0x3, "8e6c7995cdb074b089d14449dab4619fb923b70b", 0x3f})
ioctl$VMM_IOC_INFO(r2, 0xc0185603, &(0x7f0000000000)={0x97, 0x0, &(0x7f0000000180)=""/151})
close(r1)
r5 = socket(0x11, 0x3, 0x0)
sendto$unix(r5, &(0x7f00000000c0)="b1000501600000000000000007000000331c13fecea10500fef96ecfc72fd3357ae320b37b673039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139b672f4d335d223e7d026ba8af630037282102000000720fd38bfbb770c1f5a872c881ea6e69e0bb76d907c400000200361b1257aea8c500002002fb00000000008abfba09000000ec29dff8f8343712051eadb71d89e000040781e4b2fff040ff00", 0xb1, 0x0, 0x0, 0x0)


sysctl$net_inet_tcp(&(0x7f0000000400)={0x4, 0x2, 0x6, 0x12}, 0x4, 0x0, 0x0, &(0x7f0000000140), 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
r0 = msgget$private(0x0, 0x0)
msgrcv(0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$FIOASYNC(0xffffffffffffffff, 0x8004667d, 0x0)
open(0x0, 0x0, 0x0)
setreuid(0xee00, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000015c0)={<r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000140)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000040)=0xc)
setegid(r2)
setgroups(0x0, 0x0)
r3 = getuid()
setreuid(0xee00, r3)
r4 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
fchdir(r4)
writev(0xffffffffffffffff, 0x0, 0x0)
dup(0xffffffffffffffff)
msgsnd(r0, &(0x7f0000001540)=ANY=[@ANYRESHEX], 0x32, 0x0)


r0 = socket(0x18, 0x2, 0x0)
dup(r0)
r1 = socket$inet(0x2, 0x2, 0x0)
sendmmsg(r1, 0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000000029, 0x0, 0x0, 0x0)
r2 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x6}, {0x2, 0x0, 0x0, 0x40804}]})
ioctl$DIOCMAP(0xffffffffffffffff, 0xc0106477, &(0x7f00000000c0)={0x0, r2})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)
chdir(0x0)


mknod(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x1, &(0x7f0000000000)=[{0x0, 0x0, 0xc0}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
clock_settime(0x100000000000000, &(0x7f0000000000))
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000180)={<r0=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
mprotect(&(0x7f0000c57000/0x1000)=nil, 0x1000, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, 0x0)
syz_emit_ethernet(0x56, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x52, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r1 = msgget$private(0x0, 0x0)
msgrcv(r1, 0x0, 0x0, 0x0, 0x0)
msgrcv(r1, &(0x7f0000000140)={0x0, ""/12}, 0x14, 0x0, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x5200)
ioctl$FIOASYNC(r0, 0x8004667d, &(0x7f0000000300))
open(&(0x7f0000000040)='./file0\x00', 0x2, 0x138)
r2 = open(&(0x7f0000000480)='./file0\x00', 0x80, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
msgsnd(r1, &(0x7f00000000c0)=ANY=[@ANYRES32=<r3=>r0], 0xb9, 0x0)
r4 = open(0x0, 0x1, 0x0)
readv(r2, &(0x7f00000003c0)=[{&(0x7f0000002580)=""/4096, 0x1000}], 0x1)
preadv(r4, &(0x7f0000001540)=[{&(0x7f0000000080)=""/189, 0xbd}], 0x1, 0x1000)
r5 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r5, 0xffff, 0x1004, &(0x7f00000002c0), 0x1)
msgsnd(r1, &(0x7f00000004c0)=ANY=[@ANYRES32=r3, @ANYRESDEC=r4], 0x0, 0x800)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$wskbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(r0, &(0x7f0000001580)=[{&(0x7f00000000c0)='\x00', 0xfffffeb0}], 0x1)


r0 = socket$inet(0x2, 0x4000, 0x0)
setsockopt(r0, 0x0, 0x7, &(0x7f0000000340)="15337ac0", 0x4)
syz_emit_ethernet(0x2a, &(0x7f0000000480)=ANY=[@ANYBLOB="ff7800edd6e89f4368b5d068502559340956bb85c85e33e991571a4d2eeb98f588fb4a20818a67c355cc8a0cc9fb3b6e9add1a7ebe0c3cb23b7053d9849b3345de71eb9fa64f517833139efc48d022dde659949c0dbc1165ddf93147eaca1bb238430216d3707012d4d699839409fcfa177cbb7060753933d82c35fcac7b409ffc96570de27b1aaf93190bc895a2a224d4f38d9acc344021f14101b0617fc21e21789110fed42bcf7154bef718e0651f62a06fe8c1a2993b27c39d77be6c9abc83c457872f1e147802d98d9884ba3c95c3814f1117d4ebb7119724206775b877d121bda7202555580f9f645ab25c6e6a4ac9274fd96a299b391679b3dc262117eeabe7cb8f6602d60c30cbd2b20137671d7f342b195e2d740ba9d72d0090a38592a7ad0f8847e3ec5322361e31e425d5b7c1b94004d8cc2f02923c780f9646418608ff1999218549cdcc21d5323ccf242643265943fae794ec0bfb"])
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x2, 0x0)
mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x1, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f00000000c0)={0x6, &(0x7f0000000340)=[{0x25, 0x0, 0x3}, {}, {}, {}, {0x20}, {0x6}]})
write(r1, &(0x7f0000000200)="d81ad3d20cf7eb4e9be33bbd1a30", 0xe)
chroot(&(0x7f0000000100)='./file0/file0\x00')
r2 = semget$private(0x0, 0x4, 0x1)
semctl$SETVAL(r2, 0x0, 0x8, &(0x7f00000002c0)=0xff)
rename(&(0x7f00000001c0)='./file0/file0/..\x00', &(0x7f0000000280)='./file0\x00')
connect$unix(0xffffffffffffffff, &(0x7f0000000140)=@file={0x0, './file0/file0\x00'}, 0x10)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
r4 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x200000000000c, &(0x7f0000000080)="eaef125c00000000", 0x8)
setsockopt$inet_opts(r4, 0x0, 0xd, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000240)={0x0, 0x5})
r5 = socket(0x11, 0x3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x3e}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)
syz_extract_tcp_res$synack(&(0x7f0000000300), 0x1, 0x0)
sendto$unix(r5, &(0x7f0000000180)="b1000501600000000000000007000000331c13fecea10500fef96ecfc72fd3357ae320b37b673039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139b672f4d335d223e7d026ba8af630037282102000000720fd38bfbb770c1f5a872c881ea6e69e0bb76d907c400000200361b1257aea8c500002002fb00000000008abfba09000000ec29dff8f8353712051eadb71d89e000040781e4b2ffe040ff0008254842899ff2ef932e811f29902bd41c00", 0xb1, 0x406, 0x0, 0x3c)
r6 = socket$inet(0x2, 0x3, 0x7)
setsockopt$inet_opts(r6, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)


socket(0x2, 0x2, 0x0)
open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
r0 = socket$unix(0x1, 0x5, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {}, {0x2}]})
ioctl$DIOCMAP(0xffffffffffffffff, 0xc0106477, &(0x7f00000000c0)={0x0, r0, 0x1})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


r0 = kqueue()
kevent(0xffffffffffffffff, &(0x7f0000000140)=[{{r0}, 0xffffffffffffffff, 0x4b}], 0x0, 0x0, 0x0, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f0000000140), 0x8f, 0x0, 0x0, 0x0)
r2 = kqueue()
kevent(r2, &(0x7f0000000140), 0x8f, 0x0, 0x0, 0x0)
kevent(r1, &(0x7f0000000340)=[{{r0}, 0xffffffffffffffff, 0x2}], 0x8, 0x0, 0x9, 0x0)
open$dir(&(0x7f0000000040)='.\x00', 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
sysctl$net_inet_ip(0x0, 0x0, &(0x7f0000000100)="d7a8aac106fa1bee91c724b89283c1477dab85e783af4189a1eaf5f6e8251b1147b330f604ff639b9acd6202c9d8b1aef98ce6eefe712df21386a1f60bf4faf9867326180248fad514768c9928b74275ea8724a797051b934fc1a46677c194747c86477c2b49408ac33a50bed4dcd8d719c8e887ac6d1dca49c9ce71f944ba6751c604f18a9ce52aacbefb7d860132e72fc06c9d8f338de4eb9883b149513237c92b275cc73a320f63183363303ff9c417b6ed3f78a83a50368c9b2ce613b854c0e9bbda45c3aac729211c0bc3f3973c541cb95fa6a6696859", 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(0xffffffffffffffff, 0x80286987, &(0x7f00000001c0))
r3 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x80286989, &(0x7f00000001c0))


shmdt(0x0)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000000))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
r1 = socket(0x18, 0x1, 0x0)
dup2(r0, r1)
setsockopt(r1, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{0x1d}, {0x15}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000100)=ANY=[])


sysctl$vfs_fuse(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
getsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x10205b1a)
r0 = open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)
mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x205b9a)
open(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
sendto(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet6_ip6(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
munmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000)
ioctl$FIONREAD(0xffffffffffffffff, 0x8020699f, 0x0)
mknod(0x0, 0x2000, 0x205b9a)
close(0xffffffffffffffff)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
close(r0)


sysctl$net_inet_tcp(&(0x7f0000000140)={0x4, 0x1e, 0x2}, 0x3, &(0x7f0000000300), 0x0, 0x0, 0x0)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x2, 0x0)
writev(r0, &(0x7f0000000200)=[{&(0x7f00000000c0)}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
ktrace(0x0, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f00000001c0)=[{0x0}, {&(0x7f0000000040)}], 0x2)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r1, 0x80206982, &(0x7f00000001c0))
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000000)={0x0, 0x0})
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
getsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, &(0x7f00000001c0))
kqueue()
socket(0x2, 0x4001, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x5900)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x10, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{0x80}, {0x3}, {0x8006}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])


sendmsg$unix(0xffffffffffffffff, &(0x7f0000002640)={&(0x7f0000000280)=@abs={0x0, 0x0, 0x2}, 0x8, 0x0, 0x0, 0x0, 0xffdf}, 0x19)
mprotect(&(0x7f0000004000/0x1000)=nil, 0x1000, 0x2)
minherit(&(0x7f0000003000/0x2000)=nil, 0x2000, 0x5)
r0 = accept(0xffffffffffffffff, 0x0, &(0x7f0000000140))
accept(r0, 0x0, &(0x7f0000000200))
unlink(&(0x7f0000000240)='./file0\x00')
r1 = socket(0x11, 0x3, 0x0)
sendto$unix(r1, &(0x7f0000000040)="b10005010000009f0500070007000000331c13fecea1050180f96ecfc72fd3357ae30200064e303900000000f20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f335c223e7d0c032bfa896443a42118210000720fd38bfb0000fd54c125191b1257aea8c500002002fbfe0c2300008abfba0900000008e371a3f83437ba12051eeab71d89e2000403080000c01120000000000000000000000000000000000080a3bf25dbd602652c3a53228e5e282956d926f8d8fac8bacd39507c279713439c94ce04335414a39c87356b9750c89fbaa4bca316d8d22683ba375a0af1f7395a3cf5828f91bd8429a52bed00241358b290ced939913f04c47d27121bc5326738b5f33f44a093116e700c8cd43e6df83a59a0706e6650cd7e2b1e151737e3364a91c2049056f83785dad31e0086f8a7d91f6e869df6a974f028d49fd7b3f93e4bee2983a272c74865f2d954aeb477b39680d111e8b06c8979f32e14fc61852b1a7ba51f06c43cf12f268991e9d90097c7152ea779", 0xb1, 0x0, 0x0, 0xff5d)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x18}, 0x4, 0x0, 0x0, 0x0, 0x0)


sysctl$hw(&(0x7f0000000000)={0x7, 0x5}, 0x2, &(0x7f0000000040)="e087fe23", &(0x7f0000000080)=0x4, 0x0, 0x0)


sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504000004000000000007000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000022acf2047804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0e032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4fcf668246c0900e1937c727a4bdb8d000008e37123fc", 0xad, 0x0, 0x0, 0x0)
r0 = socket(0x11, 0x3, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sendto$unix(r0, &(0x7f0000000000)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)


syz_emit_ethernet(0x36, &(0x7f0000000040)={@local, @local, [], {@arp={0x806, @generic={0x0, 0x0, 0x6, 0x4, 0x0, @random="91ec390e72ae", "b8904bc4", @random="960bc221e4d8", "83494b0ef33bf29864c5d9fd6b2135f5"}}}})


openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
recvmmsg(0xffffffffffffff9c, &(0x7f0000000540)={&(0x7f0000000500)={&(0x7f0000000080)=@in, 0xc, 0x0, 0x0, 0x0}}, 0x10, 0x0, 0x0)
madvise(&(0x7f0000ffc000/0x4000)=nil, 0x4000, 0x0)
dup(0xffffffffffffffff)
openat$vnd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
listen(0xffffffffffffffff, 0x0)
ioctl$VNDIOCGET(0xffffffffffffffff, 0xc4104603, 0x0)
shmctl$IPC_RMID(0xffffffffffffffff, 0x0)
ftruncate(0xffffffffffffffff, 0x0)
clock_getres(0x0, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)
munlock(&(0x7f000000f000/0x2000)=nil, 0x2000)
mlockall(0x1)
munlock(&(0x7f000000f000/0x4000)=nil, 0x4000)


r0 = msgget$private(0x0, 0x0)
msgrcv(0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$FIOASYNC(0xffffffffffffffff, 0x8004667d, 0x0)
setreuid(0xee00, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000140)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000200)=0xc)
setegid(r2)
setgroups(0x0, 0x0)
r3 = getuid()
setreuid(0xee00, r3)
fchdir(0xffffffffffffffff)
writev(0xffffffffffffffff, 0x0, 0x0)
dup(0xffffffffffffffff)
msgsnd(r0, &(0x7f0000001540)=ANY=[@ANYRESHEX], 0x32, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0xa3a363b2fc9d96a9, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x4, 0x1100, 0xffffffffffffffff)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000200)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
write(r0, &(0x7f0000000040)="ed", 0x1)
recvmmsg(r1, &(0x7f0000000880)={&(0x7f0000000840)={0x0, 0x0, &(0x7f0000000ac0)=[{&(0x7f0000000240)=""/217, 0xd9}], 0x1, 0x0}}, 0x10, 0xc62, 0x0)
open(&(0x7f0000000140)='./file0\x00', 0x78e, 0x0)
r2 = getpid()
ktrace(&(0x7f0000000280)='./file0\x00', 0x0, 0x928, r2)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000500)={0x0, 0x0, &(0x7f0000000480)=[{&(0x7f0000000380)='s', 0x1}], 0x100000000000038b}, 0x1)
execve(0x0, 0x0, 0x0)


madvise(&(0x7f0000537000/0x1000)=nil, 0x1000, 0x2)
r0 = socket$inet(0x2, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
getpid()
fcntl$getown(r0, 0x5)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000080)={0x1, &(0x7f0000000000)=[{}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
socket(0x0, 0x1, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000000), 0x0)
close(0xffffffffffffffff)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
ioctl$WSDISPLAYIO_USEFONT(r0, 0x80585750, &(0x7f00000002c0)={'./file0\x00', 0x10001, 0x400, 0x0, 0x1, 0x40, 0x9, 0x5, 0x2, 0x1, 0x8, 0x1})
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
listen(0xffffffffffffffff, 0x0)
sysctl$kern(0x0, 0x0, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94", 0x0, 0x0, 0x0)
r1 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
openat$pf(0xffffffffffffff9c, &(0x7f0000000340), 0x20000, 0x0)
open(0x0, 0x2, 0x0)
syz_emit_ethernet(0x3a, &(0x7f0000000000)=ANY=[@ANYBLOB="ffffffffff"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r1, &(0x7f0000000000), 0x10)
write(r1, &(0x7f0000000240)="14bdfa5d1d34e2fecb284a6498307dcda9aec43050036123339a346f737850551408753f95b7688ad4c4e1dd5489e7bafc58d3e5823757ae8b630719ef187ccad995f13dbe19a6dd4e6902bd8297b0799b426aabe9fad9db6996571c6d9f8bb5d542c2148aa42be940970fe88d34d8f99afe7e7820237400000000008000000100"/138, 0xfc7e)


syz_emit_ethernet(0x46, &(0x7f0000000200)=ANY=[@ANYBLOB="aaaaaaaaaaaa00000000000086dd60004b0000102b00fe8000000000000000000000000000bb607ba243b19d8e9ea241f577704405a533"])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000000340)=[{0x14}, {0x64}, {0x4000006, 0x0, 0x0, 0x7f}]})
write(r0, &(0x7f00000002c0)="c5449bc1708e16b9805a099e20a0", 0xe)


r0 = socket(0x18, 0x1, 0x0)
openat$klog(0xffffffffffffff9c, &(0x7f0000001400), 0x0, 0x0)
shutdown(r0, 0x0)
recvmmsg(r0, &(0x7f0000001380)={0x0}, 0x10, 0x0, 0x0)
recvmmsg(r0, &(0x7f0000000700)={0x0}, 0x10, 0x2, 0x0)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000000)={0x0, 0x0, 0xfffffffffdfffffc, 0x1000300010008})


mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x1e5f)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
open(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, &(0x7f00000001c0)={0x0, 0x0, 0x0})
syz_emit_ethernet(0x36, &(0x7f0000000240)={@broadcast, @remote, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @multicast2=0xe000ffff}, @tcp={{0x0, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})
r0 = open(&(0x7f0000000140)='./file0\x00', 0x78e, 0x0)
r1 = getpid()
ktrace(&(0x7f0000000280)='./file0\x00', 0x0, 0x928, r1)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000500)={0x0, 0x0, &(0x7f0000000480)}, 0x1)
ioctl$FIONREAD(r0, 0x4004667f, &(0x7f0000000040))


r0 = openat$pf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f00000001c0)={0x0})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSDLT(r0, 0x8004427a, &(0x7f0000000000))


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000000)="e000000000000000", 0x8)


sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
openat$tty(0xffffffffffffff9c, &(0x7f0000000040), 0x80, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x2e, 0x0, 0x0)
getsockopt(r0, 0x29, 0x23, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
syz_emit_ethernet(0xe26, &(0x7f0000000100)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaa"])
r1 = kqueue()
kevent(r1, &(0x7f0000000080), 0x101, &(0x7f0000000140), 0xffff, 0x0)
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0x80206979, &(0x7f00000001c0))
socket(0x2, 0x0, 0x0)
r3 = socket(0x2, 0x3, 0x0)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000180), 0x8000, 0x0)
socket(0x2, 0x1, 0x5)
write(0xffffffffffffffff, 0x0, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)
sendto$inet(r3, &(0x7f0000000680)="cbc7fe96b6eb2bba76d2b9449899032f66add755a3d40ffe5ef0ec3fdaf327d90b1acccf8e98a3b17ae78fa871945803d25ac0e8aa28ba36e5c0fa29dfa01dcba45aef9981d87a708124cc90aff908b3b82a5c30e4eb828fcd1873d8a18ed6dddf67bd182b445bfab4e8aa3d199c8ad5f40d356f2157cd6dcdbb402e12d5dc72c06e301deddade58d790447f11f742d6dd363ef3c817d8764529d912a63922211422423137ada36b0160541117788dfbfc8c010916851918e47edecc3872869580f200b54703831613b92d0bcb62de48b5452a9bbb38a543c220b5893a24b8257cfb1df405a7d4e5af8c137b6be0cd16465676cbea5306eccd64089185178fe1a4b85e290cf38fbd18e6feb1c2e8fe835b272ed7d51a2a0b869f4477768a472c7d1500d287ce447b6c3a42b2bc48d9a0d99b642c13588291db22223e03c4e3b83723f98ad576113f00000000000000cc2e0c2d358502eaf53840782b331c91795ab90596dd5bf52301bfe0a5ff6eba19d0806ae31235db3338f7a7eb24b8fdd87e50e6c46e1f17d882f7eb62dfd1be51f933122dda5607645cbbd7d5c98facfcde1ac920b5bd21f29b7dc73a516b4e06479a8db06b59c33adaecd04dc38be752f4ed90761f3e3b241beb9fb2f7aab924dc03ef0892ef62e86c8d50ab60d88f2096a76c7524efe2df0021d16cc5849103433d4fbe53574ab97cc21ea5cba077f5bc683ed1f6dfd101a8f53ab8abed8a9c492cbf4e1e06e872e6c96abb9325f7237af4584098b7b89e94362877be33e7d90e848cae3d99eff9e7859e2268c5b8cda5a6269d16f98799f91e1afe1e480681583f4d55ecf7fe571d9c09eb83942da3e421b0bc60c7f18510c5374bf727310ea86bec5a5313eee5d961e2f2dc9b37b3a1ce7fe4b3de3794964c55dc50aba6ad1948d20f67b8e68cbe71dc1c9d8e02c75c2e81d4dddfa4657988b4af9744265199a8a48169963b12f2fa24e426024ac9969e1e348fd57a8adc277127e9fac5e640960991e9a6e0e1097f96979c711f2580c94140431d952b72cfd2f773deab68ec07bb56464aaa7e6bbeb325575f92ef8a05ee247e2273b6e31904f1b9f440db0d65ea198d7418859d9e0130e99eed40e34db0d661d834f43e48a8b271d94f92dfb3999b03b86d41d9b8ef4df3ba51dcdfb559725ecaad6b64c853b569be3c83b7f9ac136b7a02181e10aefca3d6a72f8d4ccf0a6dd3f5b01a059b8d47aac30478fe4cbb42000c69fb9b0c63c80d27049677af67c68e56a1a1223a82cc780063c6fa5010bfd60075975b300d1374a431828f5921e5e64f1da40f28a94baabc374c5e19770c1d58cf9895192e0a504abd2ef59ec7830e95a9cd0ccba54f0a1580a4c9d715dc7afa3287b5a5c20dad69e5fe1818007d4c85b19f5a78caaaca4c762ce426fc1818e724d76eaeecc194936889dfa2391d809c16cd72054eb208cbebb3c4e0daf4cbe6fe9e350df18130137e163280d5b83f6bc33fc27b041ff130dda3ccb93d260d380d845fde501fe6fd3f74beb3ba6c6f7ef1d200002c9cb10da82699311b9003954de25984bbf43bb51c54b8a1a24d24e02e94b97a5ae92e73f05c4c9aee115645dc7a84c12fb23ece3df8d13fe473fa9fa09f2312ca97b0e735882325ed01b5873d274044a2478445a609ed98670a476ffa94b2594f561af5fd70cfe44618e33d6cb9aefbac3d784da059fd1b7a3ffea36894d0e011563c5ff3291b4ff2da71f36f0bafffa74086bdb64f24ad8af4130f907fdc92f66db45a822dd02880b863d844227c761658ac91a9a5aeb803dcbc7e60ad8c1e4531e7e52d112d600bd059938f10f1572c50fdd1618ad1f96fb06f56c3260f5df6ec461653141fc36a7c98207443d55917763e17b1a7e40dfd5bbb39aadd5656522eca4fea463014f90517eeeaaf8602538b2fa197ad15bdaf3e04ba7967e64b3eb03416c3813fd22e1666a97dcd95e963f8d66e563e0d22fcc6464b84242237320802f0adf0926d439de03c78598e710684e88cc7eae195cb1feab26c2dd588ae618408fd9fb60003e20c608e0a42aefd26fd4a3c9058367029fd2f372c", 0x5c9, 0x0, 0x0, 0x0)


sysctl$hw(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
setrlimit(0x0, 0x0)
syz_open_pts()
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000280)=[{0x44}, {0x15}, {0x812e}]})
syz_emit_ethernet(0x56, &(0x7f0000000000)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000140)=[{0x1d}, {0x2c}, {0x86}]})
syz_emit_ethernet(0x127, &(0x7f0000000040)=ANY=[])


write(0xffffffffffffffff, 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x1, &(0x7f00000000c0)=[{}]})
r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$PCIOCREAD(r0, 0xc0187009, &(0x7f00000000c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = dup(r0)
ioctl$BIOCSBLEN(r1, 0xc0044266, &(0x7f0000000100))
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
readv(r1, &(0x7f0000000000)=[{&(0x7f0000000180)=""/15, 0xf}, {&(0x7f0000000040)=""/17, 0x11}], 0x2)
execve(0x0, 0x0, 0x0)


r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
mkdir(&(0x7f0000000000)='./file2\x00', 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x2, 0x2, 0x0)
fcntl$setstatus(r3, 0x4, 0x40)
shutdown(r3, 0x0)
connect$inet(r3, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r2, 0xffff, 0x1023, &(0x7f0000000040), 0x4)


r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f00000000c0)={0x0, 0x0, 0xfffffffe, 0x0, "031ffe40630000000000ff00010400"})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
r1 = socket(0x18, 0x3, 0x0)
close(r1)
socket(0x800000018, 0x2, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = dup2(r1, r0)
sendmsg$unix(r2, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


pipe2(&(0x7f0000000000)={0xffffffffffffffff, <r0=>0xffffffffffffffff}, 0x0)
poll(&(0x7f00000001c0)=[{r0}], 0x1, 0x0)
read(r0, 0x0, 0x0)


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x2, &(0x7f0000000200)=[{0x74}, {0x6}]})
setrlimit(0x5, &(0x7f0000000980))
syz_open_pts()
r0 = socket$inet6(0x18, 0x2, 0x0)
ioctl$VMM_IOC_READREGS(r0, 0xc028756b, &(0x7f0000000a40))
socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
symlink(&(0x7f0000000180)='./file0\x00', &(0x7f00000001c0)='./file0\x00')
syz_emit_ethernet(0x52, &(0x7f0000000080)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaabb86dd60000000001c0000800000000000"])
mknod(&(0x7f0000000040)='./file0\x00', 0x2000, 0x3200)
r1 = open$dir(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
preadv(r1, &(0x7f0000000000)=[{&(0x7f00000000c0)=""/99, 0x63}], 0x1, 0xffffffffffffffff)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, &(0x7f0000000000))
syz_emit_ethernet(0x2e, &(0x7f00000010c0)={@broadcast, @remote, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x1, 0x0, @multicast2, @multicast1, {[@lsrr={0x83, 0x3}]}}, @icmp=@info_reply}}}})


r0 = socket(0x18, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
listen(r0, 0x0)
setreuid(0xee00, 0x0)
accept$unix(r0, 0x0, 0x0)
shutdown(r0, 0x0)
execve(0x0, 0x0, 0x0)
setuid(0xffffffffffffffff)
poll(0x0, 0x0, 0xfffb)
syz_open_pts()


syz_emit_ethernet(0x2e, &(0x7f0000000580)={@broadcast, @random="f600000eee7f", [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x1, 0x0, @broadcast, @remote={0xac, 0x14, 0x0}, {[@rr={0x7, 0x3}]}}, @icmp=@mask_reply}}}})


recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
sysctl$hw(&(0x7f0000000280)={0x6, 0x6}, 0x2, 0x0, 0x0, &(0x7f00000003c0), 0x0)
recvfrom$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
getgid()
msgget$private(0x0, 0x0)
r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
writev(r0, &(0x7f0000000580)=[{&(0x7f00000001c0)='N3', 0x2}], 0x1)
ioctl$SPKRTONE(r0, 0x80085301, &(0x7f0000000080)={0x4})
fchmodat(0xffffffffffffffff, 0x0, 0x0, 0x0)
getgroups(0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)


sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x9}, 0x4, 0x0, &(0x7f0000000000), 0x0, 0x0)
setrlimit(0x8, 0x0)
syz_open_pts()
sysctl$kern(0x0, 0x0, &(0x7f0000000040), 0x0, 0x0, 0x0)
r0 = socket$unix(0x1, 0x2, 0x0)
setsockopt(r0, 0x6, 0x40004, &(0x7f0000000100), 0x53)
r1 = msgget$private(0x0, 0x408)
ioctl$TIOCSTOP(0xffffffffffffffff, 0x2000746f)
writev(0xffffffffffffffff, &(0x7f0000000280), 0x0)
mknod(0x0, 0x0, 0x5c4a)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x4}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x3e}, 0x2, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec370", &(0x7f0000000080)=0x1b, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000000)="9b1809ffffffffffffff7f473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6fd74c94d1b44", &(0x7f0000000040)=0x10011, 0x0, 0x0)
sysctl$kern(&(0x7f0000002240), 0x2, 0x0, 0x0, 0x0, 0x0)
ioctl$FIOSETOWN(0xffffffffffffffff, 0x8004667c, 0x0)
close(0xffffffffffffffff)
msgrcv(r1, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
msgctl$IPC_SET(r1, 0x1, 0x0)


sysctl$kern(&(0x7f0000000000)={0xa, 0x6}, 0x7, &(0x7f0000000080), 0x0, 0x0, 0x0)


setpgid(0x0, 0x0)
r0 = getppid()
setpgid(0x0, r0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000100)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000140)=0xc)
setregid(0x0, r2)
r3 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000424, r3)
setregid(0x0, 0x0)
r4 = getppid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r4})
pipe(&(0x7f0000000400)={<r5=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r5, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r6 = fcntl$getown(r5, 0x5)
ktrace(&(0x7f0000000180)='./file0\x00', 0x0, 0xd30, r6)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000240)=[{0x4c}, {0x2d}, {0x40e}]})
syz_emit_ethernet(0xe, &(0x7f0000000100)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x15}, {0x40}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000200)=ANY=[])


sysctl$kern(&(0x7f0000000180)={0x1, 0xb}, 0x2, 0x0, 0x0, 0x0, 0x12)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000100)=[{0x40}, {0x6c}, {0x8016}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x4e, &(0x7f0000000100)=ANY=[])


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1000300000001, 0xffffffffffffffff})
semctl$SETALL(0x0, 0x0, 0x9, &(0x7f0000000040)=[0x7ff])
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x40001ff, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
writev(r0, &(0x7f0000000680)=[{&(0x7f0000000040)="1792521ead05da15e3d8ccecff0f82757d02daa327f929010b6cd686c359f7a41ca9be5850c29cd999c6a3f3af213cad7b3b071b97d532b06500ddc9c4e22f49062c0500827a24fd741d566128d1cf303c413141332e47", 0x57}], 0x1)
execve(0x0, 0x0, 0x0)


open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
sendmsg(r0, &(0x7f0000000e00)={0x0, 0x0, &(0x7f0000000a80)=[{0x0}, {0x0}, {0x0}, {0x0}, {0x0}, {0x0}, {0x0}, {0x0}, {0x0}], 0x9, 0x0}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCGDLTLIST(r0, 0xc010427b, &(0x7f0000000040)={0x0, 0x0})
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x6381)
openat(0xffffffffffffff9c, 0x0, 0x0, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mknod(&(0x7f00000000c0)='./file0\x00', 0x2000, 0x4301)
open$dir(&(0x7f00000000c0)='./file0\x00', 0x10, 0x0)
pipe2(0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$hw(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
setrlimit(0x0, 0x0)
r1 = shmget$private(0x0, 0x2000, 0x0, &(0x7f0000ffc000/0x2000)=nil)
setgid(0xffffffffffffffff)
setgroups(0x0, 0x0)
setuid(0xee01)
shmctl$IPC_STAT(r1, 0x2, 0x0)
fcntl$setown(0xffffffffffffffff, 0x6, 0x0)


open(&(0x7f0000000180)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x800, 0x4ebfac6bbaf7969)
r0 = socket(0x800000018, 0x1, 0x0)
select(0x0, 0x0, &(0x7f0000000080)={0x0, 0x0, 0x100000000000000}, 0x0, 0x0)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffff9c, 0x80185760, &(0x7f0000000000)={0xa, 0x0, {0xe00000002}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000000)={0x6}, 0x5, 0x0, 0x0, 0x0, 0x0)


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000280)="a8034e3fdd86", 0x6}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)


r0 = kqueue()
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
kevent(0xffffffffffffffff, &(0x7f0000000140)=[{{r2}, 0xffffffffffffffff, 0x882919ab1cb74ec9, 0x91}], 0x0, 0x0, 0x0, 0x0)
kevent(r0, &(0x7f0000000100), 0x7a, 0x0, 0xffffffff, 0x0)
writev(r1, &(0x7f0000000400)=[{&(0x7f0000000240)="83", 0x1}], 0x1)


ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, 0x0)
r0 = socket$inet6(0x18, 0x3, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x0, 0x0, 0x0)
socket(0x2, 0x2, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x2, 0x0, &(0x7f0000000080), &(0x7f0000000340), 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, 0x0)
socket$inet(0x2, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
socket$unix(0x1, 0x1, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
shmget$private(0x0, 0xa000, 0x400, &(0x7f0000ff3000/0xa000)=nil)
r2 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
r3 = open(0x0, 0x0, 0x30)
writev(0xffffffffffffffff, 0x0, 0x0)
open(0x0, 0x0, 0x0)
setuid(0xee01)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r4 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r4, 0xc1126939, &(0x7f00000001c0))
sysctl$net_inet_ip(&(0x7f00000000c0)={0x4, 0x2, 0x0, 0x16}, 0x4, 0x0, 0x0, 0x0, 0x0)
ioctl$SPKRTUNE(r2, 0x20005302, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
socket(0x11, 0x4, 0xfc)
ioctl$WSMOUSEIO_SRES(r3, 0x80045721, &(0x7f00000000c0))
r5 = semget$private(0x0, 0x7, 0x3c0)
semctl$SETALL(r5, 0x0, 0x9, &(0x7f0000000340))
semop(r5, &(0x7f0000000180), 0x0)
semctl$GETALL(r5, 0x0, 0x6, &(0x7f0000001200)=""/40)


mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x412dff)
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, &(0x7f0000000440)={&(0x7f0000000280)='./bus\x00', 0x1000, &(0x7f00000002c0)='./bus\x00', 0x6})
r0 = open(&(0x7f0000000400)='./file0\x00', 0x0, 0x0)
r1 = socket(0x18, 0x1, 0x0)
open$dir(&(0x7f0000000040)='./file0\x00', 0x300, 0x0)
ktrace(&(0x7f0000000300)='./file0\x00', 0x4, 0x530, 0x0)
getsockname(r1, &(0x7f0000001280)=@un=@file={0x0, ""/4092}, &(0x7f00000000c0)=0xffe)
recvmsg(0xffffffffffffffff, &(0x7f00000025c0)={0x0, 0x0, &(0x7f0000002540)=[{&(0x7f0000000600)=""/4094, 0xffe}], 0x1, 0x0}, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff})
ioctl$WSMUXIO_INJECTEVENT(r0, 0x80185760, &(0x7f0000000000)={0x1ff, 0xb6, {0x100000ffe}})
ioctl$FIONREAD(0xffffffffffffffff, 0x802069c7, 0x0)
socket(0x0, 0x4002, 0x2a)
socket(0x0, 0x3, 0x0)
socket(0x0, 0x0, 0x0)
r2 = open$dir(0x0, 0x400004000011830a, 0x0)
pwritev(r2, &(0x7f0000000340)=[{&(0x7f0000000080)='\x00', 0x1}], 0x1, 0x126)
mkdir(0x0, 0x0)
chdir(&(0x7f0000000240)='./file0\x00')
mkdir(&(0x7f00000001c0)='./file1\x00', 0x0)
setreuid(0x0, 0x0)
mkdir(&(0x7f0000000100)='./file1\x00', 0x0)
rename(&(0x7f0000000180)='./file1\x00', &(0x7f0000000200)='./file0\x00')
open(&(0x7f0000000040)='./bus\x00', 0x0, 0x26)
r3 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
syz_open_pts()
socket$inet(0x2, 0x1, 0x0)
ioctl$VMM_IOC_RESETCPU(r3, 0x82405605, &(0x7f0000000780)={0x1, 0x0, {[0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x635b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7], [0x1, 0x0, 0x0, 0x0, 0x0, 0x100000, 0x10726728], [0x0, 0x0, 0x0, 0x0, 0x0, 0xfffffffffffffffe], [0x3], [{0x6, 0x0, 0x400}, {}, {0xc22}, {0x0, 0x0, 0x0, 0x7ffffffffffffffc}, {0x4, 0x200}], {0x0, 0xfffffffc}, {0x0, 0x0, 0x0, 0x20}}})


mknod(&(0x7f0000000200)='./file0\x00', 0x2000, 0x287e)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
poll(&(0x7f0000000080)=[{r0, 0x27}], 0x1, 0x0)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000100)=[{0x15}, {0xc0}, {0x6, 0x0, 0x0, 0x88f0}]})
write(0xffffffffffffffff, &(0x7f0000000280)="ce4aa4a25043cb02aadf8701f131", 0xe)
r0 = semget$private(0x0, 0x7, 0x3c0)
semop(r0, &(0x7f0000000100)=[{0x3, 0xa, 0x800}, {0x1, 0x2ff}, {0x1, 0x8, 0x1000}, {0x3, 0x3ff, 0x1800}, {0x2}, {0x2, 0x201, 0x3000}], 0x6)
semctl$GETPID(r0, 0x3, 0x4, &(0x7f0000000240)=""/8)
semop(r0, &(0x7f0000000200)=[{0x3, 0x0, 0x800}, {0x1, 0x100, 0x800}, {0x0, 0x1}, {0x4, 0x49, 0x400}, {0x0, 0x8, 0x1800}], 0x2aaaaaaaaaaaab5f)
semop(r0, &(0x7f00000002c0)=[{0x4, 0xfff, 0x1000}, {0x0, 0x420, 0x1000}, {0x1, 0x106, 0x1800}, {0x0, 0x3, 0x800}, {0x0, 0x200}, {0x0, 0x4, 0x800}, {0x2, 0xfff8}, {0x2, 0x7}, {0x4, 0x1, 0x1000}, {0x3, 0x7e7, 0x800}], 0xa)
semop(r0, &(0x7f0000000280)=[{0x4, 0x1}, {0x2, 0x8400, 0x1000}, {0x1, 0x2, 0x400}, {0x3, 0x8, 0x1000}, {0x3, 0x4, 0x800}], 0x5)
semctl$IPC_SET(r0, 0x0, 0x1, &(0x7f0000000140)={{0x1f, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0x10, 0x8}, 0x8, 0x0, 0x5})
r1 = getuid()
seteuid(r1)
semctl$IPC_SET(r0, 0x0, 0x1, &(0x7f0000000340)={{0x7, r1, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x400}, 0x5, 0x9, 0xfff})
sendmsg$unix(0xffffffffffffffff, &(0x7f00000004c0)={&(0x7f0000000680), 0x3, &(0x7f0000000140)=[{&(0x7f0000000100)="b22a0a870740d41bf7c3b211942c0ffce62bd812c505f7714c77ac91488b11b3c3ce6977131433601ab708429f", 0x2d}], 0x1, &(0x7f0000000380)=ANY=[@ANYBLOB="2000000000000000ffff000000000000", @ANYRES32=0x0, @ANYRES32=0x0, @ANYRES32=0x0, @ANYBLOB="000000002800000000000000ffff000001000000", @ANYRES32, @ANYRES32, @ANYRES32, @ANYRES8, @ANYRES32, @ANYBLOB="000000002000000000000000ffff000000000000", @ANYRES32=0x0, @ANYRES32=0x0, @ANYRES32=0x0, @ANYBLOB="000000002800000000000000ffff000001000000", @ANYRES32, @ANYRES32, @ANYRES32=0xffffffffffffff9c, @ANYRES32, @ANYRES32, @ANYBLOB="000000003000000000000000ffff000001000000", @ANYRES32, @ANYRES32, @ANYRES32, @ANYRES32, @ANYRES32, @ANYRES32, @ANYRES32, @ANYRES32, @ANYBLOB="2800000000000000ffff000001000000", @ANYRES32, @ANYRES32, @ANYRES32, @ANYRES32, @ANYRES32, @ANYBLOB="000000002000000000000000ffff000000000000", @ANYRES32=0x0, @ANYRES32=r1, @ANYRES32, @ANYBLOB='o\x00\x00\x00'], 0x108}, 0x1)
getgroups(0x9, &(0x7f0000000080)=[<r2=>0x0, 0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0xffffffffffffffff])
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000180)={{0x78f, 0x0, 0x0, r1, r2, 0x18, 0x1}, 0xc000000000000, 0x1, 0xffffffffffffffc0})
r3 = getgid()
r4 = fcntl$getown(0xffffffffffffff9c, 0x5)
r5 = getuid()
setreuid(0xee00, r5)
r6 = semget$private(0x0, 0x7, 0x3c0)
semop(r6, &(0x7f0000000280)=[{0x3, 0x5, 0x800}, {0x1, 0x2ff, 0x1000}, {0x0, 0x8, 0x1000}, {0x2, 0x3ff, 0x812242ee9a8c2935}, {0x0, 0x0, 0x1000}, {0x2, 0x6ff, 0x1400}, {0x0, 0x7ff, 0x1000}], 0x7)
semctl$SETALL(r6, 0x0, 0x9, &(0x7f00000002c0)=[0x3, 0xfff])
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000000)={0x0, 0x0, <r7=>0x0}, &(0x7f0000000040)=0xc)
semctl$IPC_SET(r6, 0x0, 0x1, &(0x7f0000000080)={{0xc04c, 0x0, 0xffffffffffffffff, r5, r7, 0x220, 0x7ff}, 0xfffffffffffffffb, 0x2, 0x7fffffff})
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f00000013c0)={0x0, 0x0, <r8=>0x0}, 0xc)
r9 = socket(0x18, 0x3, 0x3a)
setsockopt(r9, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r9, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x1}, 0xc)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001480)={&(0x7f0000000040)=@abs={0x1, 0x0, 0x0}, 0x8, &(0x7f00000012c0)=[{&(0x7f0000000100)="fdd519921130e99e6cf84e4b7df3b2d39adc0a10e88c757ec31d7d95fe", 0x1d}, {&(0x7f0000000140)="7f95b08be4d6e65467951033ab39e40b6b953c862f8aa25e9bd0cb9e7442c7cc79589db772e03d762fa7a19a2a0c0ae474f30500ac1415ef87edd82db4eb8ff96d03acd5010fd535b5067f13cb58a3015e9e84f75f0896874c7f2768fc5756384895e331070b809edeb22767645b24d73acf0e7fea060c5c09", 0x79}, {&(0x7f00000001c0)="50ba169b93c37e92232665b4d0f262f9b407e4f15e5f9736502c", 0x1a}, {&(0x7f0000000200)="db7722b9ac02ac5e30c9a6b7054a8040f64ad1f0f87b5780241d243c2804", 0x1e}, {&(0x7f0000000240)="f0267c18f8418cd72b5e8debc452124951f62735de3a004b13f15043b9d86a1e369e9b52e9c0caac8e19907db823d68458aa13b3cecb3268099d8d911271acc6f4ebfd7b6195235a714c3254e0ea493ba8e1c7ce262b17f9494e9d9f61d86b8f5a4fdd502124c6fdd4b6a9d6f54709b62546fa13d08cebde6a1b7ac3f6218be4a1a72a1da62adede3876b31840b8e0dba8e2eb5835f727e2e1e9f1a35066fc7740d5df28090e3ec4a1291a338644ce8745af0232927e70910c2e69cae62825c0402774be19db1cef1e67669e0996f138eb467e973f1a30219d18bec3ed1857f5d3f26e9a0c537a6fa65a66fa86de3a0765e348a7387802a725f1a02c30ffd16d885422a70a5bf08382293ff3ef0ffacdd5a911b8283c8b5d756eceb7e6c74649b124354aec8d4bd121c28e5310a1b03c309b3b67c20c36587a318b6b9561847422c0f368b309080d118a0689a0f9a4324c90b3ae8cb00b084133a24d1815c52af9903e0128b79a9968f47a8f8bc7709e3b364c104cae40dbd1a49a21007380669c00c32b31cd6205707c4b6461631ada301f9adcf04106e8ee2003289703d65e70a6c728d2b58cd86ec6c0d8f7b8fb0cabeb0fc33475a37b4ad1b4bc9222149925baf2c9fe0cd70e497f0fa74015d0c65b6b337fa38dcf22efca7b7c8d9084c966a0320d91ad1eddf69e2794f9a21ed7099f4b129b6bf2ff670563fc82d35e626f623b9fdf800de6d92cfc21cb0fb1f8d5ecaf467f452bfe026c2f4b4ff91c4de825632754bc0009f09995336cb6baa942662c1a3b4bede30772efea572e7d275ee9483d14213cffff3137d5ecd657cf4512b96fbf332d26324db20bea54b39558c8a9abf018883767cf1e67a02a5e172021c61d3b2802ad8bb9383368f6e6a63dd78936d0175acff561225344d6f8d910afb392f663366ca2fd0d5dd50d290ec52d9afc72149c78352174e312e03e7e3f3875ed53e9aed6260b6521b06248565b893c30e8fa737831f4a8a9039cd83ae01fcec256eaea4129c44205c8ccf9726e8688daa9816b0899a2e3bb346e6c2cac51f86805b98fffc7e84177faf51a5eace8c85420d92f93298139ea40505ba4117194cd1e50121a1442f7e34af0cff11f4aaac8229c344966690a38e24132079466bda34285dd9e21af5c824cc3ac8e9bb000396db6ba933d6e6d75c99235e30ba79080b516c862f1a05e68d4bd43e02367b9c3cbafb7af4f7140a21ae422883e6981d1e87b76fea63586052fe6730f3c566cb2ab87f9236f1a0d48d519321641783f4b420770d50181cdb7b4c94b1a9a0417679bff7147f6a987ae567a40759f79dc27ad7e1dddabd86e8cf8d80b380f7e399da4ed8317cba09bf1e82000848ca89989df28d5441dcc15a81d8402743ba34bff90b8ef5bbd7428a469e2a629910963781cb0695a289ccb7abf0bccdcd37479cb1d9192fdc687c03930f601c54abcacfccac4547a65dd3ecc0c55ea805f033b93daf55e5b9924e937f81ab72b5c53c94d55f1be2314e1e698c9660b98a8c7744f516063d43c484355256a9ab62de6c29ca460b52199a16aef4928f4a54546467001c2fca18feec12a7786b618ccd3ae3908f6aeba1c7ebd909b36320aaea291d68ee98567973b69f2bce990b5766871a7fd986a01965f0565775240910089b5536d7e0770063957ba8e0c98912c5374d79ac925a394a8b472020a0f993e4824cd4035b584adc93f0eb756f02c5ad59b75c6a69b0ed103d403e8cfc73d5b15de6aa03af8cba63f1f5a7f155e1324ef364162c6249259cbd2feb193f16c572c06d58db9289e7b9d80de5bfe8a0c154861cdb5cc68b8092ca9719b784d5d4f87ed94f63d3d866e0d874269e490cba02dc5917ec537871fdc2ab204f28d26b1e52e72cfc1f958c6f79d1b063593b7e9a1307909e1602abd7ec03e4b40c9479ff53be375d4f4dfa3d28bab40a4cc0517da1464c013dd11e486d10b1b4777d663779bd0d53c40142427b6a0d1cd3ec7716c45d45b6b87a617f3beb5b668782b6677a1df5eb82ba86f03d5cef7ac354c38910a6b6a35e1f81165a12c78d1ecbcf9e6163f8652787415d54acf5724934e02c01a0c49b6335bb934ce6ef52a662c83c68846fcbfca0b29de4baa1c1be609b69b612071110ff94c74f7d423ca30f8183c56d140d40d1a3ce0792979f20990e53453b354aa96d377ea2a79b66637998a4ee606bb38e33359a41e92929cfcd905e810cdbdcc825a5283b6a4c76c59cc6eec2c56496d20f4fc48809394aa1b1f2f155d4b22381c22f592725c26d312662c636c4d0b9bdf27b27db7f0344d0614044cf205a8ca4e59bce19f97002b252b09526eee5a1e6f7636cebec926d273d42a2cc5f1c2946055f60abf8006dc65e68fe5bc9735be3fc3ef5a49e320501fa6122913453f14dac449daf31ef7eb527b927e010b2d67d770e6d28f19b22eeab98fa7201f36350c95f2d265e605892e41f09497a8f6ce1ecb9723268a5885e0dd94f46e85de67c1606a2e43c3fd5dace6936befce9f78811632a32f85e0bc5c5d4b8c13f19a6577a2c3f1527c33898b48d9090193e9092e449db6f9e1cfa692916e26c4acad5647b5372ea706615ada58efe352b108b697289a71dd35ba257f7dbca42d8f1c6e0079c0ce4732268516734b35ebeb044bd798c07570cd5bb0df27af8d30211a7354e8535bef536981aa559bf1e1e842e650bc674423087c91f6c659cee4ecb391a68f536081c2bbb4f825b9589e94b2bcec274d9325c6b599944f87bf5fc57896e9fc42b0989523ea98be9c4d0d891a33f37d97d48534c3c3f16956a6e3c11f0b79bcf6b7deaa612a044d302b78f55c764931bca97236b34351a0ae3669f2147d7435be55d9ddf3d0b0475535d4cc3e0a0f31643ffd3b6f33a9e4779dd659048170927cd4cfa756cc79554362cb9a4413da8d770ec0a9a0c6d88e08f3164b4a1d64e8786b24ee0c36d31558f66cc06b7761709383d8c421476390f35104c4c218afe39d91460100ea1d97b913766e632a883c5a3af7c1243016fba89fe93f959b1e4e82ebee2734924a69769593ec59fea7ad8c71ed82ef665bb03dacbf9eb4c440a3401de8ea74d65d65b285242e5ad485a3d7d3f3156cd7d3283a17a4c1cdcedfe1babff04c99c700c0b2f40c6b6157bd9c7af9a1cde229ff9c0b8e52b553688db05e366c8560e8effabcc4953de08e81af8ab481057dd4fe2f79f61c3b89bdcc3f3b7c297913192ae0866acd9eb1534164900839fa2e1376c370687b13e018ce590b575ef427c2ae3c6379a904c1dbf157650bee82d6418509fd648101cf51a8cd5fdcf4c533cf08c8229f9c0d1969e8fc0b9ef67c73ed14670ac67c4b282dd8cc9fd746d521ce2ef6fbe320a43c432ee287cc1626bd5d476923cd0410d4dbcc4c2eadb62b4ab078ef05aa33d248c3dfbc057bcdbecdc723b8903a414142a1b3dedc33784edcc9be4b94905dc7554cedda141e53a30ff453190ae014419c5a4e46721f061a9b834b1f5d2502a90ca566a0572a8d4bfc79efaf4ee31526dfb53f10f76a4c0a4f8d7e9b8eec77959ba325f4f4813fe91756af48c9a0b148ce871dd50f0b773cb976f9b887188acef876e419d36142df13a869b29fe53046359b508314289e5ce5c6d213107df19547d396652e908b21b8182b05e2463bc80f3a97e70f44b650acdb8fb6347659dd7819826576d213a809846fb6ff8b92b08a8d9fa751e57cea4d2434699dde92bb55385f3c0b9c12b508cbb2a594d23c2425add6aab757746df337b28bcbef674923ae68435aee5757f1233e81e31cf57eefadac57282969d9f5a1dd7baffdfbadb8a4124761b4f799963f59b29c98541fdf04308b6b5b20548d2d8c0d2d804f786b2497a8806ae02b4bb27ef3be466498442bf4e98b4551c2dd46e36544e2cf6f248663cc82e4ec3c70aa3ebc474d8b2c5adc466612dd6bb4bf75bc62ceeece0b1d542bf5a80321e3138d9e34cf2cda589dd7579fd8c3addca713691ba6ac51919df237cb7db5f68186e462dda1633344fed483f49c9b16ec0aa713e8ca78841c5691e9229c90493324ab0a08ac50b1e39a4459bde1a04b27c23465f521cd2a4404ccf12fb08adfaafdc4e7a5d219f272d424916b9469903978b707161f3dd7fe0017053bb6a5d94aae7940b0ef4cf1379acc7cc7204fb48b27faeb60217f290ee8d7a9b8f61ea6ddc70a08e7422c4823da9170b11ea78a1967c4365595bc3d91630ee7b7578281deb1d596b0da319123533770c55637952bdbc3a2849ef119ad5b24e7f96558041f8901ff73a085231210d8643f00fa33c8052ff6d24da414e07848b75b8565807ba8138fc742e3306a666b9b9d14af1ebd665facfc59d2d5e7fd0478aec9660eaa5596c3b7ffbcd33046dd032e35cabf450f057ff1c918f9cee824c87876dc842e43b9f0dd887bc152a37466f92e13cc03aa1e639221371fa9597f5d2c1f247f5fcf2be604db51135fe0544f06584ee7c470cfd7f822c3af39466a8abffc208a4852a4bdea5c5a05e73898fe14806df586253d2f7426492a69511c31f29a33f7bd0f96b1ebecb430b49c877ffb9d7209f402fc73a5c6d4e89e5b3acd7c4d315d93e41a6aca28d2e1633f39b99e0fcbef74156360619f427bb4d2bc7bcbb3ae8e874e194485a19370085a077c0f23ce32fac0667caf709b32dcb7231fc6f4f794ca085fe2926ba2c4f3e4a8d322b6a5b90ea83520bc47925b9b8ffd141b08f5da696fe5526a42be6a1a12f2ed03f41b28ecf139fc0799cf2bf8b6a9a98613210730f04dc2c73e544453ab2f8ada55e19043a3ff1bbfcc5787dea7cf690ffc4ff7e091485233befb90bd81b01e36f0cd00277238478db02ce2b0521720cdbb4ecf6ea9d3ac795b5608ad0dca5e275a130c94f0668c8762e0765c7822ba9ba4caa11a312f46dcc5d72cc5aeaada1293e55abaf2748cd3b817f834808eb72f867d1d06b9eaa145beb847bcc3eda562e5de6bd54aeb318908ffd1e17a44756f43e8159eed551350ae917a15804e839b1a6839b5823a7a6605cba258e004bf732ecaacfa04c94ebedcb9bf0d6d27d43d6d7e11fc8f3eb5784fa8342802cb602ba538836ae33ee5fbeed8b6afd300c36a539e21b52d126af05c5b6bc63ffaeb525cf93ab2edf1ac9c8dbde13cd01be9a98047ea0c60e61f106c5234bd9c628b1040d65d395633c65ea2fcc2ed49426c7ebe1a0d5e3f3d44ac0694e38ec1f95fe89dfe7756bd36f04649835c298e554655987b94df7329c476915524f1d2d642d403df414f4ee144150323331ad0df1be8af71cd4b3994c16814e58185440cd7f93613442ae5d8796824cb76d889d0940f7d6d428dd690e2c4096ef18d264eada2827026be7907d68de30de609797958f5dc396f3bdc1dca3a99d8fbcb32b2411ece1225494c3326671a367f3ee05fff5de637beaef6786f1593c4581b483ba4216fcb12f517f909dd4b310c7362bb6a6ff794ad99ce449f853d698d886b4ecb7718e12570cf72980b84cd64c6cebc0a0e218ff3fb196aa11d38c09a985fefe1dea11412f26c43798bb2314619656f8542b6fae4056e77ef0ef0fe9852ea5d5d757499847d4392a8876a70aff580affd5403c6ea6990ba3d8a16757b13d338db5a779fac842c36f002cad6a8d0205db198b69423e54f69a0106c8a01dae939ef1738a7515f938cc77f64a4a303366343c7c7373ab7632d652a95077cc8f0a99e505e4ddceb6183093e1a121bff57857508b58e051624068f38", 0x1000}, {&(0x7f0000001240)="5f2c3415fdbf7e54a06a23fa9011c69da9750cc4d50429cc18bdd906de7e126a00cc978e85da033e779897bd2ecdda811c08ee9d8affdaa05ce1488311dc1c1286b8d82aae580c329beee2954e16b87e0ed7efeae6df5197a7ab49d89dd7262545ca8e2f38d9ce89f7", 0x69}], 0x6, &(0x7f0000001400)=[@cred={0x20}, @cred={0x20, 0xffff, 0x0, 0x0, r1, r3}, @cred={0x20, 0xffff, 0x0, r4, r5, r8}, @rights={0x18, 0xffff, 0x1, [r9]}], 0x78, 0x202}, 0x6)
sysctl$hw(&(0x7f0000000000)={0x6, 0x19}, 0x2, &(0x7f0000000080)="6cc0dc01", &(0x7f00000000c0)=0x4, 0x0, 0x0)


socket(0x0, 0x0, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
pwritev(r0, &(0x7f0000000380)=[{&(0x7f0000000440)="e9", 0x1}], 0x1, 0x3fffd)
truncate(&(0x7f0000000000)='./file0\x00', 0x2)


mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x1000)
acct(&(0x7f0000000140)='./file0\x00')


socket(0x800000018, 0x1, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0xffffffffffffffff}})
socket(0x0, 0x0, 0x0)
close(0xffffffffffffffff)
socket(0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, 0x0)
openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
munmap(&(0x7f0000ffa000/0x3000)=nil, 0x3000)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0x20006473, 0x0)


r0 = socket(0x800000018, 0x3, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1000, &(0x7f0000000000)=0x4000007, 0x4)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x120}})
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
syz_emit_ethernet(0x12a, &(0x7f0000000240)=ANY=[@ANYBLOB="b96d9900533a8f943f3614ef86dd6000000000f4000080000000000000000000000000000000ff020000000000000000000000000001"])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x4}, {0x20}, {0x6, 0x0, 0x0, 0xfff}]})
writev(r0, &(0x7f0000000980)=[{&(0x7f0000000380)="80ecd993af8e500876c3890067a5", 0xe}], 0x1)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
syz_extract_tcp_res$synack(&(0x7f0000000000), 0x1, 0x0)
select(0x40, &(0x7f0000000040)={0x0, 0x0, 0x7, 0x0, 0x8, 0x1f, 0x6, 0x8}, &(0x7f0000000080)={0x7, 0x1000, 0xfc3b, 0x4, 0x4, 0x0, 0x6, 0x10001}, &(0x7f00000000c0)={0x4, 0x0, 0x3, 0xfffffffffffffffc, 0x80000001, 0x8000000000000000, 0x3, 0x4}, &(0x7f0000000100)={0x790, 0xfff})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x8, 0x0)
r0 = kqueue()
kevent(r0, 0xffffffffffffffff, 0x3998, 0x0, 0x0, 0x0)
close(0xffffffffffffffff)
mknod(&(0x7f0000000000)='./file0\x00', 0x6000, 0xe02)
open(0x0, 0x0, 0x0)
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
r2 = socket(0x11, 0x3, 0x0)
sendto$unix(r2, &(0x7f0000000100)="b1000504000004020000000001400000331c13fecea10500fef96ec72fd3357ae30200004e3003000004be38166a91f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d1b5c223e7d0c032bfa8970c1f505002021fbfa0c0f00008abfa1221554f4e0f668246c0900000008e371a3f8343712051eea040000000000de653a1163386e7ef42eb062dc165c8ac01c367ab984af52ec07e748d7ed4c61313835c63f11553b26c58e5c086ba952dd9850a5d17bac31917b481064294eef1caaf6f3ec6f4c7fe252464996961b9a5235a0de3164dcf8b7848e06413a8857e22422905e38112ac8e0d80144f1305e5597d2863af7e44c4fe3d66de1b19b5809a4641ffa14d52f4ed1b65e000049d73bcb496c416c51a6abcd97aac8c601d973470359a118d6865bf147233514ab846168af80b2fcab8e48bf0e53afac7641fd0261d7c16aa67d4b4de3440500548c4bcb5f830dd6b5fd2325243f7f4bac915250adcc508d59580bb7c97bb953ccf446c248c60d468880861706c7bda320cc1969032d00b30000000000000000", 0xb1, 0x6, 0x0, 0xff7c)
r3 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, 0x0)
ioctl$BIOCSETF(r3, 0x80104267, 0x0)
syz_emit_ethernet(0x4a, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x11, r1, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
munmap(&(0x7f0000000000/0x3000)=nil, 0x3000)
sysctl$vfs_nfs(&(0x7f0000000380)={0xa, 0x11}, 0x3, &(0x7f0000000800)="15161665a565b678efcc1a16e750e50147e95193ee4a52bc22714f2d99406ed9e0046419cf774346a78b91f34134423ca6df2ee7e11498de3dd4ee42273a30c6221164bc556c759101a63dfd9a07da07c07c55632baa5f242d7aa5e0d7bce28d2bd5710c7cd74a77f4ddcdd98bbbb925fd0000000000a0c5b566e95cffd51dd54778f017805664c5222303ba4097947fdf6c8f6c89d172d855f83b18c1f2ddbe1f158b1305cf56c8030b73e0a97c164dba9af2df834846be2ec32e933527614df040bfa999b6eff82215b3768fe1947d3fafafa52d2e71c0b8782b7ba56af6ca070356cd633c34c22bdd9ca355290c3a46bc7487fecf09c65251b3516f00853822191627e6356313aa5aeff007467b9301a9049c8559f14e43b4028404ce30f9e683d7b2b3c55da53e4951756143a590eeed8f8f2e0de32bc1e63802c846a2c4474eb81df6fe04f246b2de4c0331166e9b25", 0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000780), &(0x7f00000007c0)=0xc)
pipe(&(0x7f0000000080)={0xffffffffffffffff, <r4=>0xffffffffffffffff})
getsockopt$sock_cred(r4, 0xffff, 0x1022, &(0x7f00000003c0), &(0x7f0000000400)=0xc)
r5 = semget$private(0x0, 0x7, 0x3c0)
semop(r5, &(0x7f0000000180)=[{0x4, 0x3f, 0x1000}, {0x1, 0x9684}], 0x2)
semop(r5, &(0x7f0000000140)=[{0x3, 0x2, 0x800}, {0x2, 0x6}, {0x2, 0x3ff, 0x800}, {0x1, 0xfffd, 0x1000}, {0x2, 0x6ff, 0x1400}, {0x0, 0x7ef, 0x1000}], 0x6)
sysctl$net_inet_tcp(&(0x7f00000001c0)={0x4, 0x2, 0x6, 0x14}, 0x4, &(0x7f0000000300), 0x0, 0x0, 0x0)
semctl$SETALL(r5, 0x0, 0x9, &(0x7f00000002c0)=[0x3, 0xfff])
getsockopt$sock_cred(r4, 0xffff, 0x1022, &(0x7f0000000280), &(0x7f0000000300)=0xc)
getuid()


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chdir(&(0x7f0000000140)='./file0\x00')
setreuid(0xee00, 0x0)
mkdir(&(0x7f0000000040)='./file0\x00', 0x5c)
chdir(&(0x7f0000000380)='./file0\x00')
r0 = getuid()
mkdir(&(0x7f0000000100)='./bus\x00', 0x0)
setreuid(0xee00, r0)
unveil(&(0x7f0000000280)='./file0\x00', &(0x7f0000000080)='x\x00')
unveil(&(0x7f00000000c0)='./bus\x00', &(0x7f00000001c0)='c\x00')
writev(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe2c63a56077123a276d3ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')


socket(0x0, 0x0, 0x0)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
fcntl$lock(r0, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4, &(0x7f0000000080)="ae215599fed2fce97f573b9c553a0e622d29cd093849cd4fe42e0f5d2d06a4e744f0713d1fcaa1b8274dffd067d413ef9d2224d3fddc171f73a295b6ed18b3d058", 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x1, &(0x7f0000000080)=[{0x1ff}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
mkdir(&(0x7f0000000080)='./file0\x00', 0xf0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{0x45}, {0x64}, {0x836}]})
syz_emit_ethernet(0x138, 0x0)
open(0x0, 0x400, 0x3a)
r2 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)


mknod(0x0, 0x0, 0x0)
socket(0x18, 0x1, 0x4)
mkdir(&(0x7f0000000100)='./file0\x00', 0x0)
socketpair$unix(0x1, 0x0, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
r2 = accept$unix(r0, &(0x7f0000000280)=@abs, &(0x7f0000000300)=0x8)
sendmsg$unix(r2, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000400)=ANY=[@ANYRES8=r1], 0x9}, 0xc)
chroot(0x0)
openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000140)=ANY=[@ANYBLOB="00000000000000000000000008060001080006040008ffffffffffff7f00000100000000e3cd60de0066d661a35b000000007fff42f05fee55"])
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r3 = socket(0x1, 0x2, 0x0)
sendto$inet(0xffffffffffffffff, &(0x7f00000000c0)="6c25a03ae7b27b4e7fc0924a22334b9b619f09f993c214bf34de94ee6f878793a443c48892901b940ff2189ae976bd635aa66dd55818d1ca20a7f88c2ad799df41ea701f32e36ab928f0ea3b00ddc5613e3590c04b342a5ec356d4f406e612653d7338e1b59ec0f00de4b65b3f18", 0x6e, 0xab7930ffa8ff6f6d, 0x0, 0x0)
ioctl$FIONREAD(r3, 0xc0106924, &(0x7f00000001c0))
r4 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r4, 0x8080691a, &(0x7f0000000100))


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r0, 0xc0206921, &(0x7f00000001c0))
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x8040691a, &(0x7f00000001c0))


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x4, 0x1100, 0xffffffffffffffff)
getrusage(0xffffffffffffffff, &(0x7f0000001500))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000005c0)=[{0x5}, {0x74}, {0x16}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x7e, &(0x7f0000000400)=ANY=[])


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETAF(r1, 0x802c7416, &(0x7f0000000240)={0x0, 0x0, 0x13, 0x0, "5238f0980ba4b3c8b9129c9e242fd505aac10fe3"})
poll(&(0x7f0000000180)=[{r1, 0x1}], 0x1, 0x0)
writev(r0, &(0x7f00000001c0)=[{&(0x7f0000000080)="536186db8d1f7787522ed0aed7c6889cee96f819992fdb353d1d1a014cfa22cd77ceaebf78091295a09007d59e7953edf8ab77149cb01367db7d4948fdaac3532e78e2032cbd628df8599f808e366013f789d49bb9c2a802994e11523e233bdb399b016ccf7f7638b3af6c623cb247740b0679b7e0123372ac3672cc4b7bd662b154dc32e845ba7aa807b9403a9d4c06d96c52b15dec6dd20a", 0x99}], 0x1)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000140)={0x0, 0x0, 0xfffffffc, 0xb51a, "1a2198b59b58505f40edabfaffffece900"})
writev(r0, &(0x7f0000000900)=[{&(0x7f0000001a80)="415d1d50caf913d67b66975cb99b", 0xe}], 0x1)


socket(0x0, 0x0, 0x0)
listen(0xffffffffffffffff, 0x0)
socket$inet(0x2, 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffff9c, 0x0, 0x200000000000c, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r1 = socket(0x1, 0x1, 0x0)
close(r1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x18, 0x1, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
shutdown(r2, 0x1)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff})
getsockopt$sock_int(r0, 0xffff, 0x1002, &(0x7f00000004c0), &(0x7f0000000180)=0xfffffffffffffe3b)


rename(0x0, 0x0)
sendto(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
close(0xffffffffffffffff)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000140)=[{0x4d}, {0x80}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000240)=ANY=[])


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
getsockopt(r0, 0x0, 0xa, 0x0, 0x0)


sysctl$net_inet_ip(&(0x7f0000000080)={0x4, 0x2, 0x0, 0x1a}, 0x4, &(0x7f0000000200), 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCLOCK(r0, 0x20004276)
seteuid(0xffffffffffffffff)
ioctl$BIOCSRTIMEOUT(r0, 0x8010426d, &(0x7f0000000040))


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x100000000000000}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000080)='\x00\x00\x00\x00', 0x4)
r1 = socket(0x2, 0x3, 0x0)
dup2(r0, r1)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x881)
open$dir(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000100)='./file0\x00', 0x20, 0x2)
kevent(0xffffffffffffffff, &(0x7f0000000180)=[{{}, 0xfffffffffffffffe, 0x90, 0x1, 0x2, 0x5}], 0x101, &(0x7f0000000180), 0xffff, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000001240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlink(&(0x7f0000000ac0)='./file0\x00', &(0x7f0000000e40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000f40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000300)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000200)='./file0\x00')
rename(&(0x7f0000001140)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000001540)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlink(&(0x7f0000000280)='./file0\x00', &(0x7f0000001440)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f00000007c0)='./file0\x00', &(0x7f0000001040)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x11, r0, 0x0)
ftruncate(r0, 0x8531)
writev(0xffffffffffffffff, &(0x7f00000026c0)=[{&(0x7f0000000400)="640493d78db6a9c1e335bb42b30c7b40a07b3baad98026cb156727aa65cfb18540954a46faf6cd689a437aff3f4961c4e46a834f6785f138abeced17229a790e349e6bd31df47a250b6311c17b41de694d02002d9c138fb5554471ad71a4e3b0c4a0f71fc4b1f3db02e683a852170340fa26d02f5dcb6c3772415d9b0c54258aba6ad66cd42dfd5163936af944020e200f6dad158fa90dfdd051d151c8c8cb6d711f408511a8c922ff7be9bf88fc6a18b3261c65ab46b32f89b7793b789d533f5dabd554659bcbb9e4082598016c9ffd443ad64a6c1384bebc4f0fa12ebee357f81c1bfbb7ff9c0bb5289f98184e590366ece692aac2a0f3fe55ae6072624ff0892d666934e9e7bb159ba7471e9ca862d48aa90c56e33b972e7ab5f15383b1e0bdc135ef14c4b638c9514366af346df10d2d11e3e82c7f98a731867165c536966e32790a098e86bc8c85d1d890537ee1a3b37a907cb151aa5b72801d9b213f04f59acc40bab4f2dfde876c2bc53ed02cd106d289a59310e0297a072b926369982acb409872a3a4325ed56f1d297bc8bbfb8f0a43f793ee9487a4492016350aa61cca26b86045d14a8f08e6f6d3e3be5520397612b66ebdf990efcf9ed9796836fa253dfa0389406ae25edb31abf6797596cf9b4a943972a4a19c43db1926c18bf15fc526127d1b04211fb4f4fe4c34dba511e8801a10008e54d343386c0c096641681899e65d2afea539fec10a2db4f07a06c7745c1005d0c2b1f020bd80e052df5a4969a40602d7b4350068968bae7ed03d05c9f0e7dd8940d1e37cfbf3370f5953261615197d350c60c2e3bdc186eff30d0700e608a4e08b2cac91f42275e3e6378a0747267335e017b5342a1662df7f3144a5c0e08008460631d2fb76c410c11c4dcc7f73fcab23a4794775f4284e02ad1ba71d64db4f1f4ced92b7a389fd596763283771b9faf89865c462f59e57a81cf8c3cbeffb268f00b6589ab79483f517583bc3a949c0df139721b6dcb9635dca559ac670c1b3ac3ffae886d18134df6d3b7078928ad5370c9687de2846d1f89f7455cf1f7bec56f3717cbdcab9a5fbe597f929e432ff093d92cb35d625bc8c5dcdc4df998db4b51f74775e5d6d119c505a2d0f27c9ead9e84af18c5d7e258cb6a4b57d28c5be27c3d72e277ae3a79bec39bdc88df392b2df6afcca55f79efb3fe6d0d8b50d7c8bbbc134450db20f1d5a773ce9cdc3b97b3274cb2e9c85496e9043e1eb83bda1b0960808b7dbf61fa0b420596976194a598a6ce1066867d13ed30035f8ff0ba3dcaa15df0cab8b96807cb82435a42067d4f1257de536842db0d3f7dfda891c146d79b600e6a2f994f2755cb278becfdaaefb2c7b976be36689c7a0feced48a723be73f29851f75e42e9d62c83d6aa220891c5c24634e8c7cc3eab033046727127a802dacbde8cf629c1f57d59ba0690af43ce944607c1fd9df72f74d67e7ddc2efd8dc6c459d0d1fe2ca57d14e20046f139050206dd8d203e0389aef6682cc6b861cc364184ee9708452dcb732992ce6dedbb8d57b5c5689b9836c54cdc91b4766f618d608d4bb380614d8cc2e03b3b3b5897ccb61f9fe2d16e5ced34cee9e856a6c52324c0eef64a4b7f9e8e7ed5a71d7b1fe9f94665ac75da67d114047ff5a1c3d0668d43d78c12565ea154f763418049e8dd3a1929b7fa4877c9e2cd984ab94818219a05b196b643adb3f064dbffd2b22ade017488178c5361a1c93f9c615e0e0cd28f25b7ca582d6942071cb7fae17b52eb41ead6e78914945802c19bac16c76ae14c7ed4be6e42713e8a4bd6220aadf458fa15b40777f94e223c596c7f80bab9584fcf4ff14f138adbbf7b1a7bdd686fa9249fe006aea38651e410fd4b1af0d79d7f1ee0cb2711ca81382f15804771da4a18d5f20e10ff9a7abd6ae8583d94f58769f3401526e517d963800c92485f9c24eac2d914895d4d9b866bbb769d22a00db29ce0b9a7d7112defb15d9776db55edf8fca337b1a496c7710acab8135aee0261a780ef6b39664469e33dab2398639d1becbdc74000b36c2ca5df2c0d3c5d3d3e054a2b8d91bc4656cf09300dd084cb0b625a587fba81cc6c2c3ef6f93342b65bc0e68222de6908492ac431f9f4dc1d3915a2cba79820c8c1f7c6e5c582d953b60a943eef44a6e7b244c808fb292f3944a4b1afbbadb06ed72c1d2cf9a60e02b319af032eddb475ae1947175f437262cefe05a89dc92367c8f8223e3a415b080b2bee22f084d00a289e42f5dcd0c31dc257d6bd09d214fad7aaa03d285a4ca618a5cc2bc0167ce424c40b879bfc294b9f2be0ee1c4669fe57d15c3b8fd626507ebb94d7313eda527d86a2bcaf9234a6eb4fcd2ecd218607961c7816094311a762d783ab7cef7009f103d938a5dee845b827001c87920ea3110b97b40a8525c41a57a03e389d9d864c57e10a849509135cdde81b89da8ee10540b76fe6c303a98bfa68a493ff59104b41c34c62092d3c0cc16d5c5c9abf7d0cc9206605ca6b69511091b512063985b03549573fbe60036cdfb28e77670e99b55a8f8151035ac93ef64b77f36951b0d3a31befef14741f874b313b66908f8da53a8a95255c16019876c85dd6070b2a8470f303b98d3c9ce2d203774794ecd2dbc43a69cd37c21f9c971634ff7b00af46adccaaeb1ca346bbdcad44151e38a94d91339c425554791adf2d3ff197221979625d2993ef7f4af06ec2438ab780ce737ac1bdbd873fa3b5cc0af43097b2be36bb9cbf87d39d3a7d54d5a49b176a3d74d95c06cd9b665248f84c27019f7b62232d9de01396aa0096f36c399b762913e207de7e3d24a2bbb04d879fe29b087ea262e82e4b3ca0fca62f222a592ab6ca1b1609e6a7500b8ed38db0d895c2df29604a64540e796787461ed7d1c5c562662b8f5146839cfbae18a6fb302033ad6558ce8a9d61d5de662b995ecb228535cddd02aa051321dadfd06dcd6409cf98d8a8697c7499f1695f173b427ff5f6cfdd224b66b89682d0e2978710e2bbfe7c9f2793cd2592ec7106c44e46c1d2bfe9d7cb53cac640f92f66506aefcc11c983e6c284a892dfc4b813771087baf9150eeb019ba0877afef77a66ee91b2c85ab1b95cc670ae9e80a4f20b8c8914c655828a68d6e8b509d479b5d04980a5bb17fb9ef17060f802f6e6f57e29d6587d6b8dc3438f592db639f718cc3bdaad6865d8a6aa94c47e1061cb8dfb8d7c54c168a29e8b1a78e1716ce413d429daaf09c924a7cde44eafc58fa5b3a5e3aa387a9465f024f7fe6ed9343d81dee65d106f635bbece1c99d5eb8ca0487c00c2851aaf24b2b6003e7150758f5a50943de2ba7b95710fa05f1c1e305dd7a14dba19feb94c9591d8cf724ef55aca7fb8e054763f7c80027b929666f6864db25a059859ca8831f9b7251e38eda5b00d0fc64a3b3460bd7ad733b9eac508a6a191a6465ca14729214d29cdfef5c6409a3f7e5db2044f836c049f5a14a78bea5c7a55e957a53d8d7d97203de65090319911c1788fc704d9382571d3d1bd2b35927d8d95b3f3b14930350ca34d577ff1d4ab69c7ef9f74f73590b8fd0d3574e7779e7f6564f9245c117c4272054015715a0671bcec7416d95a17da00b50e976168b9de75b673f6998119eb1c3b2bd1eebbf21aabc7e606991dc2e802058344d4854b1fe88688873db69c8ac70a9e4850960390a510231dc7159e3e89be0162258982be870d6135b0870986f66c19cf315552165fdccdd2acdff62cddeba67ca0e9578ab629d895a81f63c2262362a49ef4bd8a25dbf73fd100844496f40753d1496bdae8cf60f23db024ec56dbb594e9047ef5b005f579ff829dc1c3cf6844dd8bdcaf644481d171cec2bd25dce58a23617d5d11d7d44465214accb32a5767548fdfe3a428699ec03d02fbc2ccf1237ba07249af6f37ea83ddd8c7ec77f56ae7025c5662ecee8a8682d61823ec04bfebd6195147b016a28112821ad0f2aa32110dd31b38027f0e7fa042cce3e52ec467aaf95f998db202f819f201ee1322215018824a880755b94a2876e09e4c0cac01005ff8885e5f2f21c28b1aab38c62c33de0268521db2c198d19e7fafe69215465f6421b8503218f394d5a94c8601dd6514ff8a80f442ce07a4de65060229285b873667fa19859753c4b949ada2d3ab20afb732a4d4f0a9e5e13ef5a50c8361a465874e956464e201de1f30fa97398d3636ce88e479428b0bd8521010b92a22b4866c311593c101e3ed6169242c63334c7d6715a6dc50063e1c5658f590d0177464461a2ed8892719a770bcd687c597d51d46b89640b6610bc107a6b6d23e46052680aa18673", 0xc01}], 0x1)
msync(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x2)
getgroups(0x1, &(0x7f00000003c0)=[0x0])
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
r1 = socket$inet(0x2, 0x2, 0x0)
close(r1)
r2 = socket$inet(0x2, 0x2, 0x0)
dup2(r0, r2)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000200)="ea000000000000", 0x7)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000240)="ea02000000000000", 0x8)
setsockopt$inet_opts(r1, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0x8)


open(&(0x7f0000000480)='./file0\x00', 0x200, 0x0)
r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSKBDIO_SETMAP(r0, 0x8010570e, &(0x7f0000000040)={0x19be, &(0x7f0000000080)=[{}, {}, {}]})
r1 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r1)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
sendto(r2, 0x0, 0x0, 0x0, 0x0, 0x0)
recvmsg(r3, &(0x7f0000002880)={&(0x7f00000014c0)=@in, 0xc, 0x0, 0x0, 0x0}, 0x0)


r0 = socket(0x2, 0x3, 0x0)
getsockopt(r0, 0x10000000, 0xcb, 0x0, 0x0)
r1 = socket(0x18, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
connect$unix(r1, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001280)={0x0, 0x0, &(0x7f0000001200)}, 0x0)
setrlimit(0x0, 0x0)
r2 = syz_open_pts()
close(r2)
getrlimit(0x0, 0x0)
syz_open_pts()
writev(0xffffffffffffffff, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394", 0x1a}], 0x1)
sysctl$vm_swapencrypt(&(0x7f0000000000), 0x3, 0x0, 0x0, &(0x7f0000000180), 0x4)
syz_emit_ethernet(0x36, &(0x7f0000000000)={@local, @empty, [], {@ipv4={0x800, {{0x8, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @multicast1, {[@rr={0x7, 0xb, 0x7, [@broadcast, @multicast2]}]}}, @udp={{0x1, 0x3, 0x8}}}}}})


socketpair(0x0, 0x0, 0x0, 0x0)
r0 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
munmap(&(0x7f0000001000/0x2000)=nil, 0x2000)
setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)
munlock(&(0x7f0000ffe000/0x2000)=nil, 0x2000)


mprotect(&(0x7f0000ffc000/0x1000)=nil, 0x1000, 0x0)
minherit(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x3)
rename(&(0x7f0000000300)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
r0 = openat$null(0xffffffffffffff9c, &(0x7f0000002f40), 0x0, 0x0)
readv(r0, &(0x7f00000002c0)=[{0x0}, {0x0}, {&(0x7f00000000c0)=""/128, 0x80}], 0x3)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000000)=[{0x60}, {0x80}, {0x8106}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x0, 0x0})
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$KDSETLED(0xffffffffffffffff, 0x20004b42, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1000300000001, 0xffffffffffffffff})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x1ff, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000002a80)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[])
syz_emit_ethernet(0x32, 0x0)


open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
ktrace(&(0x7f0000001d40)='./file0\x00', 0x0, 0x1720, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x2011, r0, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f0000000200)={0x0}, 0x10, 0x0, 0x0)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000600), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000680)={&(0x7f0000000080)=[{0x100}, {}], 0x2})


sysctl$kern(&(0x7f0000000040)={0x1, 0xb}, 0x2, &(0x7f0000000080)="b9c855a3", &(0x7f00000000c0)=0x4, &(0x7f0000000100), 0x0)


sysctl$net_inet_etherip(&(0x7f0000000000)={0x4, 0x2, 0x61, 0x2}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0x0)
mkdir(0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, 0x0)
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
sendmsg(r1, &(0x7f0000000840)={&(0x7f0000000380)=@in6={0x18, 0x1, 0x9, 0x7f}, 0xc, &(0x7f00000004c0)=[{&(0x7f00000003c0)="72ea465ba731b8a227b222d7ceed9302a20806e94247a0a85b4ca865b15a869eee0edccd413e32678585ab80b3841b7f3c694c7dfe4a6ac375ad90a8337671466f1cf0e5f7ec96ef243f3c31c798ddaaafcceec30f55508658e170b93ddab7ce44ae36edae95cf7f98e77c37a1079c6514571cbefe9528c72471138aecbb49116c78b83766af2ec609d1eb35dd892f4b987ca97e23a6bf3322ff209a40563a57c0e5334a68fa0e8606283306419981e0cb95f2ccca67aacec7d54efbe0a236fbd4524301f71226c314df45010758dea2becd6ea924372f8d47428e347e5bf63ce63708b5114c22b1deb814233672c81df204df", 0xf3}], 0x1, &(0x7f0000000c80)=ANY=[@ANYBLOB="7000000000000000ffff000000000400f65909bff56f69d87641406eed3dfd15f8ab95ccc3edaca9a8ab9a98477d39db7ec91e62395f5aecb55079b0c0d1b95306b25065ee65d7a24f745820668a7e28c4864c711d982316a1e79ebfbd22172c90ed814333fe8c259b939766e6000000c000000000000000010000000900000014a2e7159adaaa270b34e5083d2d8daacc9708076d2add98928c4694d70e31a9d5b32df82d0970c7f8099c3786aa928beb821fc090d60273f15d5122dcb39b8a526103e92e2a71a36eaccf1261e09bc588fc3b94e70b841ad43f00c1113e5ee8e0a7cf8b57b23499c6031e7181753551e27abd4d6f8900697a7ca2039b3362f456613bf0a5c6c26dc480a6406c234dce646e5d80e600cfdfa73778dadd366333710d000000003000000000000000010000000100008043b9e2987270f3d10ee10e7b63faf97a90184f203ea0a0285200000000000000a800000000000000ffff0000d400000056e2d82e083e3e9aa8b83854595345ae2164b60f7259308d91b0950273ec94b2fcd6253f47736285f9e9960f40bfdaf938c692f9bd07987020789936e70226467094132f7718bb8c89aa1a01de0a44df41d1a657655ba16e9f4fdfe3e9ee93231c9ab7cb27b4e7586e80b240df2061782c39f36cc31a40c3e6f9b552a59a7e6bb4f3957981579f70d4777638b7838792635b0c7d98a5000068000000000000000100000003000000fe51618420cfa38c4dbc19f2ded006207d8191892004bbd2dd5b5b18953fbf5b4976aceff6730519282137b83f9b2ed5084eadd61eda87daafd5b189a73468201b5ed7e9251f639534138ee6b26307cfa2fd3a139c158c0068000000000000000100000006000007000000fa86d9ac41a1880abc152fad63133b1e8b3d2d51b3c81dca8ec68dae08b858a0a880ceeae20ba90333c414d85e221458a6b2474936b85941dacc9fe8386714ac473662a3cf39221607d2de882a7c627765e8483f0404ea37add8abf95ebf2d8288c5c94e6c09037e4c5b95c30d30c0eb91d2cb6a11cb87524ea5f1ea8a3ce3a3e060798fc1ad774401acb9bb07d3f28c0a33e64480ca08e86b233257db7ccced60ab187b08bdfc413cd6c2bd14d3c8ab5edb49ebed349a694e04f477cd9371af283ed517aa48dfc92c21543e2cfea48e19b890728d99d508fa0951112815eca5e70f002ded4409a958b649fe90ca6580e3ba7c"], 0x2d8}, 0x4)
close(r1)
r2 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(r2, &(0x7f0000000400)=[{&(0x7f0000000180)="9c0b291fec6a5560c6011c38", 0xc}], 0x1)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x1, 0x10, r2, 0x0)
r3 = socket$unix(0x1, 0x1, 0x0)
ioctl$FIONREAD(r3, 0x80206979, &(0x7f0000000000))
ioctl$BIOCGBLEN(0xffffffffffffff9c, 0x40044266, &(0x7f0000000540))
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0x0, 0xd, 0x40, 0x40}], 0x0, 0x0, 0x0, 0x0)
socket(0x800000018, 0x2, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000180))
socket$inet(0x2, 0x3, 0x102)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000280)=[{0x4d}, {0x35}, {0x9106}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{0x84}, {0x28}, {0x4000006, 0x0, 0x0, 0x3feffe}]})
write(r0, &(0x7f0000000180)="23009100007adb020317bdda2b7e", 0xe)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x4e, 0x0)
openat$vnd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x0, 0x4}]})
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000000c0), 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
kqueue()
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x81}, {0x3}, {0x16}]})
write(r1, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xfef3)


r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x0, r0)
close(r2)
mkdir(&(0x7f0000000000)='./file2\x00', 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x2, 0x2, 0x0)
r4 = getpgrp()
fcntl$setown(r2, 0x6, r4)
fcntl$setstatus(r2, 0x4, 0x44)
connect$inet(r3, &(0x7f0000000000), 0x10)


mkdir(0x0, 0x49)
socketpair$unix(0x1, 0x0, 0x0, &(0x7f00000015c0))
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000000), &(0x7f0000000140)=0xc)
setitimer(0x0, &(0x7f0000000000)={{0x7}, {0x8, 0x200}}, &(0x7f0000000040))
sysctl$net_inet_gre(&(0x7f0000000000)={0x4, 0x2, 0x2f, 0x1}, 0x4, 0x0, 0x0, 0x0, 0x0)
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r0, 0xc2585601, &(0x7f0000000040)={0x10, 0x0, [{&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ff7000/0x9000)=nil, 0x10000}, {&(0x7f0000ff8000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil, 0x3}, {&(0x7f0000ff7000/0x4000)=nil, &(0x7f0000ff7000/0x2000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ff8000/0x2000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff8000/0x4000)=nil, &(0x7f0000c00000/0x400000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000c74000/0x4000)=nil}, {&(0x7f0000ee7000/0x4000)=nil, &(0x7f0000eda000/0x2000)=nil}, {&(0x7f0000f0a000/0x2000)=nil, &(0x7f0000d2d000/0x3000)=nil}, {&(0x7f0000d50000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000d82000/0x2000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000dbe000/0x2000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000e40000/0x1000)=nil}, {&(0x7f0000dbd000/0x4000)=nil, &(0x7f0000c2e000/0x3000)=nil}, {&(0x7f0000ff5000/0x8000)=nil, &(0x7f0000dae000/0x4000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000c19000/0x3000)=nil}], './file0\x00'})
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
mknod(0x0, 0x1ffa, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
sysctl$net_inet_gre(&(0x7f00000000c0)={0x4, 0x2, 0x2f, 0x3}, 0x4, &(0x7f0000000100)="80815d97e5e9ec42557fbfa1b208d658d9983f117a859fd619a67026beff80585ebedf283df04854cf98e456c11215a266b3c48e70351ef02e", &(0x7f0000000140)=0x39, &(0x7f00000002c0)="3d5c4fb3856c4746eb2eb0", 0xb)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000002a40)={&(0x7f0000000000), 0x10, 0x0}, 0x0)
chmod(&(0x7f0000000300)='./file0\x00', 0xd0)
r1 = socket(0x2, 0x2, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000180)=[{&(0x7f0000000000)="9da8e3e9ed", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sendmsg$unix(r1, &(0x7f0000002a40)={0x0, 0xffffffffffffff89, 0x0, 0x6e, 0x0, 0x700000000000000}, 0x0)
sendmsg$unix(r1, &(0x7f0000002a40)={0x0, 0x0, 0x0, 0x40}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
r1 = dup(r0)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000000)=[{0x30}, {0x30}, {0x46}]})
syz_emit_ethernet(0x36, &(0x7f0000000840)=ANY=[])


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
r1 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
writev(r1, &(0x7f0000000340)=[{&(0x7f0000000000), 0x2cfea}], 0x1000000000000013)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x3, 0x10, r0, 0x0)
utimensat(r1, &(0x7f0000000200)='./file1\x00', &(0x7f0000000240)={{0x10000, 0x7ff}, {0x1ff, 0x1ff}}, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x41000}, {}, {0x0, &(0x7f0000002000/0x2000)=nil}, {}, {&(0x7f0000134000/0x4000)=nil, &(0x7f00001fb000/0x3000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {0x0, &(0x7f0000086000/0x3000)=nil}, {0x0, &(0x7f00001f0000/0x4000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f00001d5000/0x2000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {0x0, &(0x7f0000092000/0x3000)=nil}], './file0\x00'})
r2 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r2, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0})
fcntl$setown(0xffffffffffffffff, 0x6, 0xffffffffffffffff)
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931", 0x11)
ioctl$WSMOUSEIO_SETMODE(0xffffffffffffffff, 0x80045726, &(0x7f0000000040)={0x1})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x1ff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x1, 0x5, 0x0)
close(r3)
r4 = socket(0x18, 0x2, 0x0)
setsockopt(r4, 0x1000000000029, 0x9, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
setsockopt(r4, 0x1000000029, 0x2e, 0x0, 0x0)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sysctl$kern(&(0x7f00000000c0), 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0xff0a, 0x0, 0x37)
r5 = socket(0x800000018, 0x2, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
bind$unix(r5, &(0x7f00000002c0)=@abs={0x1f95d27d48731892, 0x0, 0x2}, 0x8)
mlockall(0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
r2 = dup2(r0, r1)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000001c0)=[{0x81}, {0x7}, {0x8106}]})
syz_emit_ethernet(0x4a, &(0x7f0000000200)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000500)={0x1, &(0x7f00000000c0)=[{0x54}]})


r0 = dup(0xffffffffffffffff)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000000)={<r1=>0x0, <r2=>0x0, <r3=>0x0}, 0xc)
fchown(r0, 0x0, r3)
r4 = shmget(0x2, 0x1000, 0x102, &(0x7f0000fff000/0x1000)=nil)
shmctl$IPC_SET(r4, 0x1, &(0x7f0000000040)={{0x1000, r2}, 0x0, 0x0, r1, r1, 0x101, 0x80000000, 0x22})
r5 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r5, 0x80085761, &(0x7f0000000540)={0x2, 0x8})


r0 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r0, 0x0)
r1 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
r2 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r2, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)={0x3, 0x7fffffff})
kevent(0xffffffffffffff9c, &(0x7f0000000040)=[{{}, 0x0, 0x0, 0x0, 0x7}], 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11, 0x0, 0x2}, 0x6, &(0x7f0000000080), 0x0, 0x0, 0x0)
r3 = open(&(0x7f0000000180)='./file0\x00', 0x1, 0x0)
r4 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
fcntl$setstatus(r4, 0x4, 0x0)
ioctl$FIONREAD(r3, 0x8028698c, &(0x7f0000000100))
ioctl$WSMOUSEIO_SRES(r3, 0x80045721, &(0x7f0000000040)=0x8)
r5 = kqueue()
kevent(r5, &(0x7f00000000c0), 0x30, 0x0, 0x57d, 0x0)
accept(0xffffffffffffffff, 0x0, 0x0)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
syz_emit_ethernet(0x3e, &(0x7f0000000000)={@broadcast, @remote, [], {@ipv6={0x86dd, {0x0, 0x6, "b42f2f", 0x8, 0x0, 0x0, @loopback, @ipv4={'\x00', '\xff\xff', @rand_addr}, {[], @udp={{0x3, 0x1, 0x8}}}}}}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt(r0, 0x29, 0xa, &(0x7f0000000000)="ebffcbff2bb9fd812eaa4e710100000000000000", 0x4)


socket(0x11, 0x3, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000007, 0x0, 0x0, 0x0, 0x0)


r0 = socket(0x2, 0x2, 0x81)
getsockopt(r0, 0x0, 0x1f, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000280)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
recvfrom$unix(r1, &(0x7f00000000c0), 0x832f1f7d, 0x0, &(0x7f0000000000)=@abs, 0x2000c600)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
sendto$unix(r2, 0x0, 0x0, 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
socket(0x18, 0x1, 0x0)
r3 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r4 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r4, 0xc0206923, &(0x7f00000001c0))
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105727, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x45}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$vm_swapencrypt(&(0x7f0000000000), 0x3, 0x0, 0x0, &(0x7f0000001380)="01", 0x1)
ioctl$FIONREAD(r3, 0x8040691a, &(0x7f00000001c0))


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
ioctl$TIOCCONS(r0, 0x80047462, &(0x7f0000000180)=0x3)
r1 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
ioctl$TIOCCONS(r1, 0x80047462, &(0x7f0000000080))


r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
close(0xffffffffffffffff)
ioctl$WSKBDIO_BELL(r0, 0x20005701)
r1 = open(&(0x7f00000003c0)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`/file0\x00', 0x0, 0x44)
r2 = openat$diskmap(0xffffffffffffff9c, &(0x7f00000000c0), 0x1, 0x0)
ioctl$DIOCMAP(r0, 0xc0106477, &(0x7f0000000400)={&(0x7f00000001c0)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`\x00', r1, 0x3})
socket(0x11, 0x0, 0x0)
r3 = socket(0x2, 0x2, 0x0)
setsockopt(r3, 0x8, 0xa, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000640)="e7000000000000000000000000e75e509ce7b7cf356a4de200000000000000009de4ac84e83dbfaf94fee6010001000000000025b7d90000000000000000000000f44ed17b386d5e03cb61532a5d96e6c0c36c804388bae5456189353ecee60437df2bfd4e3768a7edc5883d66871f9a8d8d2038c5ccdcd5ba851126f8db3185c342068cf0674e9427f4c0e85ee0701d888b7d52835f743b", 0x98)
r4 = socket(0x0, 0x0, 0x0)
shutdown(r4, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1001, 0x0, 0x0)
r5 = msgget$private(0x0, 0x0)
pipe2(&(0x7f0000000000), 0x0)
msgsnd(r5, &(0x7f00000000c0)=ANY=[@ANYRES32], 0x1f, 0x800)
select(0x40, &(0x7f0000000280)={0x0, 0x6a, 0x40, 0x7fffffffffffffff, 0x80000000}, 0x0, 0x0, 0x0)
msgsnd(r5, &(0x7f0000000700)=ANY=[@ANYRESOCT, @ANYRESOCT=r2, @ANYRES16], 0x401, 0x0)
msgsnd(r5, &(0x7f0000000540)=ANY=[@ANYRES16], 0x401, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80606941, &(0x7f00000001c0))
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
msgrcv(r5, &(0x7f00000002c0)={0x0, ""/206}, 0xd6, 0x3, 0x1000)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x10, 0xffffffffffffffff, 0x0)
ftruncate(0xffffffffffffffff, 0x25b3)
execve(0x0, 0x0, 0x0)
sysctl$vm(&(0x7f0000000180)={0x2, 0x7}, 0x2, &(0x7f0000000580)="ef5f4a75", &(0x7f0000000240)=0x4, &(0x7f0000000480)="a2d1051da24d8d644ff50d138c6c203a8dd9a580577dfe7012cb783182d05f867f2e1aec0954827c812a1bb306a15d81f87c3cb99c317f63cc19b029277ba17a67d014c57c4c120440c0cc54ca299b9b5b822c642774eb5f64", 0x59)
r6 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
preadv(r6, &(0x7f0000000080), 0x54, 0x8)
madvise(&(0x7f00003e0000/0x3000)=nil, 0x3000, 0x4)
syz_emit_ethernet(0x49, &(0x7f0000000000)=ANY=[@ANYRES16, @ANYRES32=0x41424344, @ANYRES32=0x41424344, @ANYBLOB="f8d8090083169b60ee289f7daba600000000"])


mknod$loop(0x0, 0x0, 0x1)
open(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
setrlimit(0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_DEL_MFC(r0, 0x29, 0x69, &(0x7f0000000200)={{0x18, 0x1}, {0x18, 0x1}}, 0x5c)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x53})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIONREAD(r0, 0x4004667f, &(0x7f00000002c0))


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000180), 0x1, 0x0)
ioctl$WSKBDIO_GETMAP(r0, 0xc010570d, &(0x7f00000001c0)={0x1, &(0x7f0000000240)=[{}]})


openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000100)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000240)=[{}, {}, {}]})
recvmmsg(r1, &(0x7f00000002c0)={0x0}, 0x10, 0x0, &(0x7f00000003c0)={0x8, 0x101})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
chroot(&(0x7f00000000c0)='./file0\x00')
sendmsg(r0, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)


syz_emit_ethernet(0x2e, 0x0)
openat$pf(0xffffffffffffff9c, 0x0, 0x8000, 0x0)
sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x25}, 0x4, &(0x7f0000000200), 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
open(0x0, 0x10, 0x0)
utimensat(0xffffffffffffffff, 0x0, 0x0, 0x0)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240), 0x0)
getsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r1 = socket(0x11, 0x3, 0x0)
sendto$unix(r1, &(0x7f0000000000)="b10005136000009f05003e0800000000331c13fecea10500fef96ecfc72fd3357a068d02bc31a3a5673039d2d236acf20b7804be38164991f7cccf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f4d335c223e7d026ba8faff0037720fd38bfbb770c1f5a872c881e2772ec5a10400000000000000361b1257aea8c5d0002012000000000000880d6633c556ae9b287948a62310db415f779642cdcd71a3f8343712051e000000000000", 0xb1, 0x0, 0x0, 0x0)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
r1 = dup(r0)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


setreuid(0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000400)=[{0x4c}, {0x2}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])


sysctl$kern(&(0x7f00000000c0)={0x1, 0x55}, 0x4, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x4d, 0x0, 0x2e)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000280)={&(0x7f0000000240)=[{}, {0x20}], 0x2})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x1}, {0x20}, {0x4000006, 0x0, 0x0, 0x48001}]})
writev(r0, &(0x7f0000001400)=[{&(0x7f0000000240)="e049c0d37348a45d6bee0bf84a9e", 0xe}], 0x1)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
socket(0x18, 0x2, 0x0)
sysctl$kern(0x0, 0x0, &(0x7f0000000100)="71f91e3471ac00cb5c656358bc5a91501d94", 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000400), 0x1000000000000165)
open$dir(&(0x7f0000000040)='.\x00', 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
sysctl$net_inet_ip(0x0, 0x0, &(0x7f0000000100)="d7a8aac106fa1bee91c724b89283c1477dab85e783af4189a1eaf5f6e8251b1147b330f604ff639b9acd6202c9d8b1aef98ce6eefe712df21386a1f60bf4faf9867326180248fad514768c9928b74275ea8724a797051b934fc1a46677c194747c86477c2b49408ac33a50bed4dc21030000e887ac6d1dca49c9ced83a4827665105c9f18a9ce52aacbefb7d860132e72fc06c9d8f338de4eb9883b149513237c92b275cc73a320f63183363303ff9c417b6ed3f78a83a50368c9b2ce613b854c0e9bbda45c3aac729211c0bc3f3973c541cb95fa6a6696859", 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x2, 0x0)
r3 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x80286989, &(0x7f00000001c0))


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x400000002, 0x0)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r1 = socket(0x18, 0x1, 0x0)
r2 = dup2(r0, r1)
sendmsg$unix(r2, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


mkdir(0x0, 0x0)
chmod(0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
dup2(r0, r1)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0xffffdffc, 0x0, "ffff09008700"})
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "00001800", 0x0, 0x7})


recvfrom$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x1, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f00000002c0))


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
write(r1, &(0x7f0000000140)="7f23a3c2", 0xffffff89)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000140)=[{}, {0x50}, {0x812e}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b100050300000400000000002001000000000000cea10500fef96ec0c72fd3357ae30200007804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3eea3c57699a6443a42102000000720fd18b08fbb670c1f5a872c881ea6e2ec589040018", 0x62, 0x0, 0x0, 0x0)
r0 = socket(0x11, 0x3, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sendto$unix(r0, &(0x7f0000000000)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000380)=[{0x3d}, {0x7c}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000080)=ANY=[])


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000004c0), 0x2, 0x0)
writev(r0, &(0x7f0000000400)=[{&(0x7f0000000240)="61db1fc4224ee6774376076cd64335d83ae7c58d3e5e1f5c0d412785a866432e2e", 0x21}], 0x1)
execve(0x0, 0x0, 0x0)


pwrite(0xffffffffffffffff, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(0x0, 0x0, &(0x7f0000000100)="d7a8aac106fa1bee91c724b89283c1477dab85e783af4189a1eaf5f6e8251b1147b330f604ff639b9acd6202c9d8b1aef98ce6eefe", 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
sendto$inet(0xffffffffffffffff, &(0x7f00000000c0)="6c25a03ae7b27b4e7fc0924a22334b9b619f09f993c214bf34de94ee6f878793a443c48892901b940ff2189ae976bd635aa66dd55818d1ca20a7f88c2ad799df41ea701f32e36ab928f0ea3b00ddc5613e3590c04b342a5ec356d4f406e612653d7338e1b59ec0f00de4b65b3f18", 0x6e, 0x0, 0x0, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000140)=[{0x60}, {0x5c}, {0x6, 0x0, 0x0, 0x4000003}]})
write(r0, &(0x7f0000000000)="7696e5f3d1f18c37cea8615ac7cf", 0xe)


r0 = open(&(0x7f0000000080)='./file1\x00', 0x200, 0x0)
mmap(&(0x7f000000f000/0x1000)=nil, 0x1000, 0x0, 0x10, r0, 0x0)
mlock(&(0x7f000000f000/0x4000)=nil, 0x4000)


shmget$private(0x0, 0x3000, 0x0, &(0x7f0000fef000/0x3000)=nil)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
setsockopt$inet_opts(r0, 0x0, 0x200000000000b, &(0x7f0000000080)="02", 0x1)
r1 = open(&(0x7f0000000200)='./file0\x00', 0x800, 0xbf035c924f7afc22)
ioctl$FIOASYNC(0xffffffffffffffff, 0x80047460, &(0x7f00000000c0)=0x406)
ioctl$TIOCOUTQ(r1, 0x40047473, &(0x7f0000000340))
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x9})
r2 = syz_open_pts()
close(r2)
r3 = syz_open_pts()
writev(r2, &(0x7f0000000180)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c", 0x1d}, {&(0x7f0000002780)="4d2d55aab3d6856cf29adaf309a5d6dedef6b210c896beafe1fea5a872cbb97dca61ad83254112f868c318205686445d889efc0fcaf644ca6f6bf805a125d0357c5d2ecc63823a14b7a476cc8e5ac77bb249bdf6023fb75347e08a3a45091582c86154ab169e91874e1ca17ff3cf90a4d56cfdb53af9b85be175b43134bbc6de63db5a2c3f5fea15dfb60641d62e80c3b0d2bf765716b97bb219e36d72a488fd02f9d8689a9fe8f71d244489757b27ad65a52f4ff6ec0fb109757f37c8c05e6b882cbc2a1cdb3843acde914cfeff5a60f883eada0a178116a844e59ef259d6fa647d87aacd4b6f7440769f6e392a9ca7aba39c0efe7dfdc265de7cdd66b3e8a084e6cc27703b72ae48b58e178d9d8510ebd947fcd8410f49eb1f0af6cef634db4eacd9f11d4c37355014923fb0161ee09c39f0aab98bf85c5ead5e128d8571d6b562cddb0f24512dede55fb0a64a3ce12dc04ea04352a1c23b729b2880b2540bb2ace46e466e05d2bafbb19d945765366487ffc4c051a538d372f972604ed0c948c16ff6bc552cf70861a366085273d8987bf2c731d81c7ac3574418bf2f32132cd28f8a48d38229fb9ed7aaef8d8ff0e13cab55f96bb9f5f1ee4d9f033724078c19ad5e378ee900d170bee1bd782a3c9e60b6e9a17f5cf32f68fd65b34fa24cbf32cbccb58c4e5f9992a684260c6ec9b067f7c98877d4d2aefd0111a8e73b220603a690df04b6d093c569cd4119e5a3bebeed9ab1d1d6aa2cccfee6d58fe8882ea1190fc8d69cbdae67fe458e04b8f626c5ae3bdddc090078c2210fc3d0378048a997c1b2675b22295744d609ef50ab686ddaeddc01b84868699116b7b40b890e826a0276c8bf935d1566a5ce5791330165bdad05051ee6d15fa323694ed52f97110b2405d24a0efceb9350f9a5ac586745d03aec01209c620167458cd888f035c647564a6becd31e3924d37287aae45ceac991caff27ca0a86d91db4040f575136e7c1f48af30811936d406e94dcfa738acfe857f0e9cb7685a2f29c84568e17f98cf6488c953caa36aad4943413521e7fa822e26f0801797c001828af0a71c388d09168716ef1f7f387768ccf95a0c735539d7deeb6bf4613fd328d9f846dcf7ae80a75e9148388bd18fce630efe10c187c242649ec44029406f19f64ff1c74ad707b864c50497718315a396077e224e4b7963eb029c100a535aa89f18fd49135944a294faf01fdf6801fb43dc5f663567f4244", 0x375}], 0x2)
dup2(r2, r3)
readv(r3, &(0x7f0000000600)=[{&(0x7f0000003780)=""/4111, 0x100f}], 0x1)
recvmmsg(r1, &(0x7f0000000580)={&(0x7f00000001c0)={0x0, 0x0, &(0x7f0000000400)=[{&(0x7f0000000100)=""/74, 0x4a}, {&(0x7f0000000040)=""/29, 0x1d}, {&(0x7f0000000280)=""/153, 0x99}, {&(0x7f00000009c0)=""/4096, 0x1000}, {&(0x7f0000000380)=""/125, 0x7d}], 0x5, &(0x7f0000000480)=""/222, 0xde}, 0xff}, 0x10, 0x802, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, 0x0)


socketpair$unix(0x1, 0x0, 0x0, &(0x7f00000004c0)={<r0=>0xffffffffffffffff})
sendmsg$unix(r0, &(0x7f0000000180)={0x0, 0x0, &(0x7f0000000140)=[{&(0x7f0000000080)="e5", 0x1}], 0x1}, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x2802)
writev(0xffffffffffffff9c, &(0x7f0000001300)=[{&(0x7f0000000000)="19f3b0b3b875dbbb0f7263bb2830", 0xe}], 0x1)
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x80206979, &(0x7f0000000000))
r2 = socket(0x11, 0x3, 0x0)
socket$inet(0x2, 0x0, 0x0)
ktrace(&(0x7f0000000100)='./bus\x00', 0x2, 0x4000010e, 0xffffffffffffffff)
socket(0x1, 0x4001, 0x80)
getsockopt$sock_int(r0, 0xffff, 0x80, &(0x7f00000000c0), &(0x7f00000001c0)=0x4)
connect$unix(r2, &(0x7f0000000000)=@abs={0x0, 0x0, 0x0}, 0x8)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000480)={0x0, <r4=>0x0}, &(0x7f0000000600)=0xc)
r5 = getegid()
chown(&(0x7f0000000500)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', r4, r5)
r6 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
ioctl$VNDIOCGET(r6, 0xc4104603, &(0x7f0000000000)={'./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0xffffffff, 0x8, 0xfffffffffffffffd})
recvfrom$unix(r0, &(0x7f0000000640)=""/180, 0xb4, 0x800, &(0x7f0000000700)=@abs={0x1, 0x0, 0x0}, 0x8)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x601, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, 0x0)
kqueue()
open$dir(&(0x7f0000000040)='./file0\x00', 0x300, 0x0)
ktrace(&(0x7f0000000100)='./file1\x00', 0x1, 0x400, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
bind$unix(r1, &(0x7f0000000140)=@file={0xd19450564dee018c, './file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00'}, 0xff)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xfffffffffffffffe, 0x0, 0xffffffffffffffff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname(0xffffffffffffffff, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
poll(&(0x7f0000000140)=[{0xffffffffffffffff, 0x1b5}], 0x1, 0x0)
ioctl$BIOCPROMISC(0xffffffffffffffff, 0x20004269)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
socket(0x18, 0x1, 0x0)
r2 = socket(0x18, 0x2, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000080)=[{0x6c}, {0x34, 0x0, 0x0, 0x3}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


r0 = semget$private(0x0, 0x3, 0x10)
semop(r0, &(0x7f0000000040)=[{0x4, 0xfffe, 0x1000}, {0x2, 0x7a, 0x1800}], 0x2)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100))
mknod(&(0x7f0000000080)='./file0\x00', 0x6000, 0x202)
r1 = open(&(0x7f0000000bc0)='./file0\x00', 0x0, 0x0)
mknod(&(0x7f0000000200)='./bus\x00', 0x2000, 0x203)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x25}, {0x81}, {0x16}]})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r3 = socket(0x1, 0x2, 0x0)
ioctl$KDGETLED(0xffffffffffffffff, 0x40044b41, 0x0)
ioctl$FIONREAD(r3, 0xc0106924, &(0x7f00000001c0))
fcntl$getown(0xffffffffffffffff, 0x5)
r4 = kqueue()
kevent(r4, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
fchdir(r3)
r5 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r5, 0xc0206921, &(0x7f00000001c0))
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0x3, 0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
r6 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r6, 0x8020690e, &(0x7f00000001c0))


openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
socket(0x2, 0x3, 0x0)
open$dir(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
getgroups(0x2, &(0x7f0000000180)=[<r1=>0x0, 0x0])
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000280)={{0x3, 0x0, r1, 0x0, 0x0, 0x22}, 0x1})
sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r2 = kqueue()
ioctl$FIONBIO(r2, 0x8004667e, &(0x7f0000000000))
r3 = dup2(r0, r0)
socket(0x1, 0x5, 0x5)
r4 = socket(0x2, 0x1, 0x0)
setsockopt(r4, 0x6, 0x8, &(0x7f0000000140), 0x0)
setitimer(0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000300)="800f000000000000000000000024a8a4f4a4905fa2b0c36bc75c31ffa6f3d946bc4a42fd9917413164e9c129e0c6b0d923fe1764e82ed0404960d4260ffd05e4c54f52a1cbdae4f9b1b874875eee3f557feab57e188937bc22e1eb80bed6c05069bffd6179f2750e486b8f014cf47fd0023d2d19ed3231b382b8f07cd7df988abbdc4f13fb808ccb11fbfc1a9b522d46005d8f06b6b4187e2c72d17a5eaf359e9022dfb5676f50506eb5f51e0b44be12b75cdbe6e523362e740e1af9e846e8d74eede322ecbba599b11f545e3ac7b4a91ca17fc74719a72ce748d47cb96dffd16df7b4fa250fcc9fff00be69cdc2e3229f1e987ca23a0ea7707637c6f78f5871e7c1214f04693409d14700ad4826c1771041475840f408cd7933c2f4ba7a87f766337e31d82b9e754f818237a22b", 0x12e}], 0x1)
socket$inet(0x2, 0x2, 0x0)
r5 = socket$inet(0x2, 0x2, 0x0)
mknod(&(0x7f0000000540)='./file0\x00', 0x2000, 0x177d)
open$dir(&(0x7f0000000040)='./file0\x00', 0x200, 0xd1)
setsockopt$inet_opts(r5, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
write(r3, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
ioctl$WSKBDIO_GETMAP(r3, 0x80047476, &(0x7f0000000100)={0x0, 0x0})


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000080)="eaef125c00000000", 0x8)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea000001", 0x4)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f00000000c0)={0x1000, 0xebd, 0xfffffffe, 0x0, "031ffe40630000000000ff00010400"})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
close(0xffffffffffffffff)
socket(0x18, 0x3, 0x3a)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = syz_open_pts()
close(r1)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r2 = syz_open_pts()
close(r2)
r3 = syz_open_pts()
ioctl$TIOCSETD(r3, 0x8004741b, &(0x7f0000000080)=0x8)
writev(r2, &(0x7f00000001c0)=[{&(0x7f0000000100)="791c965780508f54dbcb129a9b6934991cba070d2e0c2f19ce57fdf185dff047b76f5bce561cfa080860c2905c9d57ef9df88eecb44cc27bf73a964b794a1daba7ac8742bea32f4d23e71ae0658372c558d41ee20902ae", 0xff81}], 0x1)
writev(r1, &(0x7f0000000700)=[{&(0x7f0000000080)='4', 0x1}], 0x1)
r4 = socket(0x18, 0x3, 0x3a)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r4, &(0x7f00000001c0)="00003226a4a9000064e7c803d2a423735d33a4dd", 0x14)


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0xb32, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x4, 0x1100, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r0, 0x0)
nanosleep(&(0x7f0000000040), 0xfffffffffffffffe)


r0 = getppid()
ktrace(0x0, 0x5, 0x40000d30, r0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000100)={0x2, &(0x7f0000000080)=[{}, {0x2}]})
sysctl$kern(&(0x7f0000000080)={0x1, 0x31}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)
r1 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r1, 0x80085761, &(0x7f00000000c0)={0x3})
ioctl$WSKBDIO_GETDEFAULTKEYREPEAT(r1, 0x400c570a, &(0x7f0000000000))
recvfrom(r1, &(0x7f00000001c0)=""/249, 0xf9, 0x1000, &(0x7f0000000080)=@un=@file={0x1, './file0\x00'}, 0xa)
r2 = kqueue()
read(r2, 0x0, 0x0)
r3 = open(&(0x7f0000000180)='./file0\x00', 0x200, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f00000002c0)={'tap', 0x0})
getpid()
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r4, 0x80104267, &(0x7f0000000580)={0x3, &(0x7f0000000540)=[{0x2d}, {0x2c}, {0x6}]})
r5 = shmget$private(0x0, 0x1000, 0x0, &(0x7f0000003000/0x1000)=nil)
shmat(r5, &(0x7f0000002000/0x2000)=nil, 0x0)
shmctl$IPC_RMID(0x0, 0x0)
shmget(0x1, 0x2000, 0x0, &(0x7f0000ffe000/0x2000)=nil)


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f00000001c0)={0x4, 0x2, 0x6, 0x4}, 0x4, &(0x7f00000002c0)="2740ebde30795566e295cc4fd7fe3d271ad0e3f4a0d97d53214de2a3dd042af605e5fd0afce3a42c12ce4c665fe597bec03bc29315b0b90b24de291db13e00ceba8c9b3944069d26d0074a59659b1342e0c7800bb05f33586418822ac01520e59b2f62ebca1ba7fcb7ceb580a7bab05dad8713ec84c829a7e6813b00560430744526751fef7d2f611f7ba021fa92fa4d31e64731b431c9c9456c221259a718f8", 0x0, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000140)={0x4, 0x2, 0x6, 0x16}, 0x4, &(0x7f0000000380)="4c7c460ac8e53ed6ef1bd755fa1b2c100dc5fbacc99cfd7df4766850a12b62faacfaad0aa6d29d9774c969122097367b7873c5e49bbae5142870cafdde95408953", &(0x7f0000000180)=0x41, &(0x7f0000000400)="8d844925fae507af0ee3", 0xa)
openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = socket$unix(0x1, 0x5, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x0, 0x5012, 0xffffffffffffffff, 0x3)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140))
bind$unix(r1, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
r2 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
poll(&(0x7f0000000080), 0x0, 0x0)
fcntl$setflags(0xffffffffffffffff, 0x2, 0x0)
fcntl$setown(r2, 0x6, 0x0)
listen(r1, 0x0)
r3 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r3, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
r4 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r4, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


r0 = kqueue()
sendmsg$unix(0xffffffffffffffff, &(0x7f00000004c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000340)=[@rights={0x10}], 0x10}, 0x0)
kevent(r0, &(0x7f0000000200), 0x400, 0x0, 0xdb74, 0x0)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)='\t\x00\x00\x00', 0x4)
r1 = dup(r0)
setsockopt(r1, 0x1000000000029, 0xc, &(0x7f0000000000)="ffdaff10aac6a28ac93e2eddc45c8454e486f64c", 0x14)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0xc0206921, &(0x7f00000001c0))
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x8020690e, &(0x7f00000001c0))


syz_emit_ethernet(0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000180)=[{0x2d}, {0x1c}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x2000, 0x2d87)
r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
kevent(0xffffffffffffffff, &(0x7f00000000c0)=[{{r0}, 0xffffffffffffffff, 0xb7c61f5c345976d}], 0x0, 0x0, 0x0, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x7, 0x0, 0x0, 0x0)
close(r1)


sync()
r0 = msgget$private(0x0, 0x0)
r1 = shmget(0x1, 0x1000, 0x0, &(0x7f0000ffc000/0x1000)=nil)
shmat(0x0, &(0x7f0000ffc000/0x4000)=nil, 0x2000)
msgctl$IPC_STAT(r0, 0x2, &(0x7f0000000000)=""/166)
shmctl$SHM_UNLOCK(0x0, 0x4)
r2 = shmget$private(0x0, 0x3000, 0xe79, &(0x7f0000ffd000/0x3000)=nil)
shmctl$IPC_STAT(r2, 0x2, &(0x7f00000000c0)=""/226)
shmctl$SHM_UNLOCK(0x0, 0x4)
shmctl$IPC_RMID(r2, 0x0)
sync()
r3 = openat$vmm(0xffffffffffffff9c, &(0x7f00000001c0), 0x80, 0x0)
semop(0xffffffffffffffff, &(0x7f0000000200)=[{0x4, 0x8000, 0x1000}, {0x3, 0x1}, {0x3, 0x1, 0x1000}, {0x2, 0x9, 0x1800}, {0x0, 0xffa2}, {0x0, 0x7fff, 0x1800}], 0x6)
ioctl$VMM_IOC_RUN(r3, 0xc0205602, &(0x7f00000004c0)={0xffff, 0x7, 0x0, 0xb6a, &(0x7f0000000240)={{0x20, 0x6, 0x4}, {[0x7, 0x9, 0x7fffffff, 0x6, 0x7, 0x4, 0x800000000000000, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x8fc4, 0x1, 0x7fffffffffffffff], [0x4, 0x80000000000, 0x7, 0x5, 0x401, 0x800, 0x7fffffffffffffff, 0x43, 0x4, 0x401], [0x4, 0xcfc, 0x8, 0x1000, 0xa394f14, 0x8001, 0x3], [0x1ff, 0x100000001, 0x1f, 0x6, 0x6, 0x3], [{0x100, 0x8, 0xffffff00, 0x81}, {}, {0x6, 0x3, 0x0, 0x6}, {0x5, 0x400, 0x101, 0xffffffffffff0061}, {0x6, 0x0, 0x7818, 0x4}, {0x4, 0x5, 0x5, 0x361f}, {0x3, 0xdd9, 0x9, 0x4b45}, {0xfff7, 0x4, 0x6, 0xffffffffffff4acd}], {0x4, 0x56f, 0x8}, {0x5, 0x1, 0x401, 0x6}}}, 0x5, 0x80})
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000500)={<r4=>0x0, 0x0, <r5=>0x0}, 0xc)
r6 = geteuid()
r7 = getegid()
shmctl$IPC_SET(r1, 0x1, &(0x7f0000000540)={{0x2, 0xffffffffffffffff, r5, r6, r7, 0x13, 0x9}, 0x7, 0x1, 0x0, 0xffffffffffffffff, 0x9, 0x5})
semctl$SETVAL(0xffffffffffffffff, 0x0, 0x8, 0x0)
shmctl$IPC_RMID(r2, 0x0)
ktrace(&(0x7f0000000600)='./file0\x00', 0x0, 0x40000130, r4)
r8 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000640), 0x80, 0x0)
ioctl$BIOCSRSIG(r8, 0x80044272, &(0x7f0000000680)=0x7a6)
geteuid()
shmctl$IPC_STAT(0x0, 0x2, &(0x7f00000006c0)=""/80)
socket(0x12, 0x0, 0x0)
shmat(r2, &(0x7f0000ffc000/0x2000)=nil, 0x2000)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000002c0)={0x3, &(0x7f0000000000)=[{0x2d, 0x0, 0x0, 0x84}, {0x81, 0x6, 0x6}, {0x6, 0x0, 0x2}]})
write(r0, &(0x7f0000000200)="b1c05b5fb165120a4224a763037a", 0xe)


getpgrp()
r0 = socket(0x11, 0x3, 0x0)
setsockopt(r0, 0x11, 0x1, &(0x7f0000000200), 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))


socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000003c0))
mkdir(&(0x7f0000000000)='./file0\x00', 0xad)
setreuid(0xee00, 0x0)
r0 = getuid()
chown(&(0x7f0000000180)='./file0\x00', r0, 0x0)
r1 = geteuid()
r2 = getuid()
r3 = getuid()
seteuid(r3)
setreuid(r2, r1)
setreuid(0xee00, r2)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000040)='r\x00')
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000240)={{0x4, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0x80, 0x4f6}, 0x1, 0x8, 0x8})
r4 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x200100000001d, &(0x7f0000000000), 0x4)
getsockopt$sock_cred(r4, 0xffff, 0x1022, &(0x7f0000000000)={<r5=>0x0}, &(0x7f00000000c0)=0xc)
semop(0x0, &(0x7f0000000080)=[{0x2, 0xb13}, {0x2, 0x2000, 0x800}, {0x1, 0x1, 0x1000}, {0x2, 0x8, 0x400}, {0x2, 0x6, 0x1000}], 0x5)
semctl$IPC_RMID(0x0, 0x0, 0x0)
r6 = semget$private(0x0, 0x7, 0x3c0)
semop(r6, &(0x7f0000000100)=[{0x3, 0x2, 0x800}, {0x1, 0x2ff}, {0x1, 0x8, 0x1000}, {0x3, 0x3ff, 0x1800}, {}, {0x2, 0x1, 0x3000}], 0x6)
semctl$SETALL(r6, 0x0, 0x9, &(0x7f00000002c0)=[0x3, 0xfff])
semctl$SETALL(r6, 0x0, 0x9, &(0x7f0000000380)=[0x0, 0x0])
r7 = getuid()
setreuid(0xee00, r7)
r8 = getpgid(r5)
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000001c0)={{0x3, 0x0, 0x0, r7, 0x0, 0x30, 0x6d}, 0x9, 0x7, r8, r8, 0xfffd, 0xb, 0x6, 0xbdbe})
semctl$IPC_SET(r6, 0x0, 0x1, &(0x7f00000000c0)={{0x10000, 0x0, 0xffffffffffffffff, r7, 0x0, 0x0, 0x200}, 0x2, 0xd47, 0x7})
setreuid(r1, r3)
getuid()
semctl$IPC_SET(r6, 0x0, 0x1, &(0x7f0000000000)={{0x1, 0xffffffffffffffff, 0x0, r2, 0x0, 0x80, 0x6}, 0x0, 0x3ff})


setreuid(0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x2, 0x0, 0x5}, 0x4, 0x0, 0x0, &(0x7f0000000100), 0x0)
socket(0x1, 0x1, 0x20)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000400)=[{0xc}, {}, {0x812e}]})
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x8218694a, &(0x7f00000001c0))
getsockname$inet(0xffffffffffffffff, &(0x7f0000000180), 0x0)
rmdir(0x0)
sysctl$vm(&(0x7f0000000140)={0x2, 0x9}, 0x2, 0x0, &(0x7f0000000100), 0x0, 0x0)
getpgrp()
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x8981, 0x0)
r5 = openat$tty(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$TIOCSETVERAUTH(r5, 0x8004741c, &(0x7f0000000080)=0x2)
getgroups(0xffffffffffffff84, 0x0)
r6 = semget$private(0x0, 0x4000000009, 0x82)
getegid()
semop(r6, &(0x7f0000000140)=[{0x0, 0x3, 0x1000}, {0x3}, {0x4, 0x201, 0x1000}, {0x3, 0x1000, 0x1000}, {0x0, 0x7a5}, {0x3, 0xff72, 0x3800}, {0x1, 0xdb, 0x800}, {0x0, 0x0, 0x800}, {0x3, 0xa, 0x1000}], 0x9)
semctl$IPC_RMID(r6, 0x0, 0x0)
sysctl$hw(&(0x7f0000000040)={0x6, 0x14}, 0x2, &(0x7f00000002c0), 0x0, 0x0, 0x0)
semctl$IPC_SET(r6, 0x0, 0x1, &(0x7f0000000280)={{0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x22, 0x7}, 0x5, 0x2, 0x10000000009})
sysctl$vm(&(0x7f0000000200)={0x2, 0x5}, 0x2, &(0x7f00000012c0)="8fac714587d07766129cce54d92228b1861695bf930d6d13fbc9a01a1660d12216a2474be212abbf22268777e56b274f67a41c7f21c81ca87eb58a79adcbd2225372fc96278a98e335a5baad06fac7e5625a6d43e02985c9e73c27e7adecc30f1ed3df5803a3517d000e5ce8687a7f170d2018ae6759b486bf0d2df888e34409690046ccd5ffaeab22bed43fe91761c766d50669798e58cf6f1a3859bdcca068a5e89f770118201ead6f0973b616bef051c3c879ba04b6027bc7b3dbfef7c98d237a8d8f91f3372f3bf47af8fe9a3b6bd646898ef1fb2c27a8131fe3714508ca3e5804fcc99da6e145ae71d83452341f2db2c8552e4828e2b50a9ab51474dcd747f84ed35a65dd46d1cedb8c16fcd979a9c19354d971e716d8df572db7d889f0ec31d0b82255d8ef62ffdda33e09e97f51f0089825519be70c92b7f8e344e13a276e35e059a1a30b73619993f79096d6d983e72b35194fdb2c568a93b9b99dd6a665782f5faba5c3401012ae4fc30028037194b2f52ffd1d43535d38990b98d1c1730f21c1fa02db90292bbb710f570c640506df69ce6143dee8929517363921adc57e8b7effa3f1245d94b5670373905f1d995ee1690a4d23d17d1e90344f2ec2972c3d079667fffc2ff3b876ee8f118fc6e0e26c5d2a4afccea8adfbe328ca4b638568ca7344a739f152d9c80c57179a3f6494fdffc56ef748608e47b4f179f91bcc514d6955183aff20c6da2638bde3f91fae70a00d0a76acc08e892d5e094d207ee3e861f334ae64c7d19b1009456397479d82e377f1c3d7708b4a9796db7738e162302103fb82a4fdd4a80ac2ed8d5490dcbad6e98d11c70afedaa15a26834bc96ffbac806277faab63b5e26a24ed3b240c3dcdbfa18ce02a290f20e617ca4bbc77c5a0ee1f44cbca43a3c15b0075def231eadda280911ba3d8874331aa7f619c2e6a01b297e898959990de1c9c7b1b095eb504c98a2d4b4442a12a1292633e759c0132e60a5b80bae599104c5d4fdb469396bb1c260d2a277c9cbbf8f911d693b5e21b094d08d00e92c55dab8fa051ccfff72243b4c2714b10a66874fcff39b766ad1e1d73de01bc17a505a4433dc1948755036cd1e0eedb1ebea4b35c377189b0a2a7d049fef1a5bf28c5983450d7ae6fdf15899c47ce483817a3da479d6893103b28c5bc9f34b0a4de7fb7c48e408e10ab5903b9061c59124884e10ae6dc27ea42971cba5ced5321fab31a03e816a0a3e0e2c35941cf28623c3fd35755bdf4476115bd21a06a846932f89f3707d3e3e2c86187fbb2fcc4ae8884fc826fabbe4cd38de916e22bae9a681e1a0b2e668cd148badddeee722c4f522eb5c301f34b690a5bc8099a40f99306a2531503f7f16bcbfe50295db9b854f132e10ed05efc088d9997ad5038e6988bf3c75dfe18b6fc84445ee7359a6626c8ff7e59541edd4bff9a1467115727b2131af8d31a999898cfb76b41445c1f4c4bf53467db69ff9b1dbd036900d4a6510d4eb642231854f60eccf1cc18a69ea0a3518fe497d53f78e324bcc28d9aa810456fbb748702fc91100097bc0400c3f759d0f8b0df5a91db7900713db826e333388141c504058a978b4fa293661c7bdd4e58bd682466fa8804d41771bd09a1c372458437ee9d5b762ad80680f910f6cf01c8d31770e9351403cc5d0a9fafd06cb84b7189d7ff877923bc1bfbdded29883bc3449d56f7d5877dc81c55d999d6e131bd52a2ff26ff8836c9fc55eac56908b4ecb91d60c06fb60bba1e94f528fc5b164c3256ecc38fe6e6301929c8f3116ddcbd9e47be9a4621fd36dc4780cb33f604e59bfa745e7d934fc82542b25599c9dd26ac5b1190359acab5c2c6c1ff41b95c9852834321fc95573ae310932750430c0547c818b6cd3611171afa9d273864fd4ee02f3664d5379b26d87f34d8ab4e79b96cbaae3e68aab02e7376bdc01868fdfe13357174e1e7dfe5d1512c9345a1d8ebdd78368eb62c3f5c99a0840bdca4a2e78c0e3fd2d6da9d8e705f3f0641b9664d8d219f82ae969fef95a6b4a9b5d44eb88c6157fef9e16d07856326f9c119f099565765fee9c9113f7677e8310e233c56c72cb4f69ab66a41215e2402fc12210514a860f36d619df3ea9dbf6e2e9b015424c0f044a3381893b5d191b9d685e012cfa101ab106374cf46fc54768d7a8bf6c8cdad4a6c8edbdb15cabaac1a8624baa89ceebfc787ee18d1c082ace9a06b303bb05303fb01991adf1f80795432eb3da623e23f298a2eefe733487ac0dc36d46346e0cfb2527b70ff4f95044d01647ca8354e13afd4d1b08de9d65c8abf69718d865346d737621b6fb8d2dd0d645d3166ee9e700fffa4e24ed125d3e552ef8e2e01908b84c5f93029b24723ac7ff531cb24e47f4bbafe5a51fefae717862821c115249c13be9637ac99a778a10fa447686cbce9da73e2de453d8a092df99a325f5a5df0957519b4d3dd94640f5c7bfabeeb93ae7f9f8a81b3df67c5c56f58a53c0346bb6a973aa474e3aeb53e2f63d46c94aa2658a604769d558161268ed0529ca6a08824331f8fcb24e97dffc93dd0931fc583d1ea57f830ef64908e4c44775da7c3ed48fd50eb6dbb85ebb59e8d244d9c71c2b906bbb8afd4477cd56a7f1e9492e6722610bb4819af275ae89c9ad51b21e127f0b08957b77f1ac9fa52e6ff761c93cba7ff9cf7f2403e702567e515cd9f1789e0a2ed24e230b8149669fcb0b5a9109b06673988f2e2f97616f258375647b75ec295dc132bc7d98088aaced6610188b9b6e7e0d7d986d6a536904094dc70548c46c3ec0aae6a5abfe19f0db87cdae09ed0b958b33071d1cfab05e578aa96e8141cd4d1b25558e87009b1430808fdbe6a891d2efbe0f2e6a97e2cbce5c7dc85f4520a87cf4b288d648a8ce7f036c493a308c5ae89d9c44f427a172827aa02a58a5236739507b356f7a13c1f05fd471660393c2b795654f160a3af515820bd9b304fe5f13b892d2ab386b6f2b1e53ee014fbd2997189408e1d02b67d4fbf963df6d59bdf02456d26b4d4749363a3c96c4db6cb8b9f22712c344f1f0c8e9c65dc5b5395176eb775ed2810919821c520a2128b7abdcc4462aa0c4682a7a2d397e83a26355620bc3b5db9524dc7bc7e361669b03d05db62c0cb2782ec27760cb015378e87976ec0b0e26165a002cd1b30b62bc4a9df5cc3814867233fd173a71b4bf09d759ca7855544b6229b9413793b216dd91505fb659c7c95f0fee30e2dec7c092487787ff9dadafd30a74e7efaeb7898b3e9423468f3a12f732ed3505df3ad6d16eaa4f3c764ce7c3c1549878207f23b006bea46739c1865541c36ddf190f69600c4bdde58be1ab7d0fb548e5c667906c8898a651f37e268e3ea8b5f468f6538bbff4937c70aa2b4acd30819f6601e622af42aaa262eeb267e12442782684c3e380dc3bb8e8701bb81939769355f532458a48184293c60a2c69db6e5bd37e35c1847326ca18cdf8076c6a03c34ba090f4ae17d6fd0e3954556ed22e3dd605e06193a95bc5b7d89c67968ec9e93a07bbc372a7f89afff2008c94ab5cf6d32ba97cdb1cdc28d7b95dfd120ef861cb7b75258d6fd8f897fcb5aa97bd3ea5b30", &(0x7f0000000240)=0xa00, &(0x7f0000000280), 0x0)
semctl$GETALL(0x0, 0x0, 0x6, &(0x7f00000004c0)=""/195)
close(r2)


socketpair$unix(0x1, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
syz_emit_ethernet(0x2a, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000080)=[{0x87}, {0x1d}, {0x6}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


write(0xffffffffffffffff, 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0xfffffffa, 0x9fe0, "0000c6f26461c094f4ffffffff00"})
writev(r0, &(0x7f00000007c0)=[{&(0x7f0000000380)="82", 0x1}], 0x1)


pwritev(0xffffffffffffffff, &(0x7f0000000380)=[{&(0x7f0000000440)="e9", 0x1}], 0x1, 0x0)
mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x412dff)
r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x402, 0x0)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000000), 0x2cfea}], 0x1000000000000013)


r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCGDLTLIST(0xffffffffffffffff, 0xc010427b, 0x0)
r1 = msgget$private(0x0, 0x21)
msgrcv(r1, &(0x7f00000000c0)={0x0, ""/219}, 0xe3, 0x0, 0x800)
socket$unix(0x1, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x20, 0x0, 0x0)
msgrcv(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
bind(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000340)={0x1, &(0x7f0000000300)=[{}]})
r2 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000380), 0x10, 0x0)
open(&(0x7f0000000500)='./file0\x00', 0x80, 0x18)
r3 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000540), 0x40, 0x0)
ioctl$VNDIOCSET(r3, 0xc0384600, &(0x7f0000000600)={&(0x7f0000000580)='./file0\x00', 0x0, 0x0})
ioctl$VNDIOCCLR(0xffffffffffffffff, 0x80384601, 0x0)
r4 = msgget$private(0x0, 0x1c3)
msgsnd(r4, &(0x7f0000000700)={0x2, "488ab02cfe22618f9643b170d1746e7d694dd6e5aa7f7a8f8bb319cab9df6122106e66f1b047d01e7bdf6cc93f33a38917eebb2d928cbd1baeb82923021617d6b6b7e9ca549a55ffb7c0ee0d08a05d054a0e3d7370a388f12f5d7585f8228ed6591c9b7c3493827563bcd1a2700226e22f13bdfbcda0f3330787a67dc4a1ba7a2f88742d847423118eb05ebc01cb780ccee86a25035f1e578189116c460a81ff9f740b1ffd084d889718794589e7ae80e0774a3632e0a89a86c7152aec5796a4a4d80d4162cab50bf0f29cf5b13492f89e6f504a467218ba8ac1a6dcdb1fea8ab8dc431a92fba87daef5db4d9f4b08eb89113cce96352911ba"}, 0x101, 0x0)
dup2(r2, r3)
ioctl$BIOCVERSION(r2, 0x40044271, &(0x7f0000000900))
sysctl$net_inet_tcp(&(0x7f0000000940)={0x4, 0x2, 0x6, 0x14}, 0x4, &(0x7f0000000980)="4ab823624f59ba58b0446f39cbc408d981f7821ff83278400e53c251d5fa3a4ac7fdb1077a3d26a7", &(0x7f00000009c0)=0x28, &(0x7f0000000a00)="d9a2f4e24ed75b0d29ed2265757e5b3dfa0fba95a2f146d41598f94c00f879812fd760aeaabdfec9f894d6dd60d7bc99fc7bff23396820aa6f183e248ef7453bff2d0b81dc03f2f967eb81286c55ebf53c93ddf5bde784899d2bf74586a2a765f5fa5d95ea77ef37c21cf8486b67d3d9a12dbbdf03b5363647b09ee6c77b475d7cbe24f8905c11869e5d182f8a8e2d07ee762497812997fbebd5eaf8ff40cedf47260a5c787bdc864f35d64bd5d5a0f2290b42af3ec1582b43578e98356d92b7b3b58adfa7d99340fb4e05f9e5dee8612509d332", 0xd4)
r5 = getuid()
setreuid(r5, 0x0)
socket$inet(0x2, 0x0, 0x0)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
shmctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x140}})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x3a)
r2 = dup2(r0, r1)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendmsg$unix(r2, &(0x7f0000000bc0)={0x0, 0x0, 0x0}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000440)={0x3, &(0x7f0000000100)=[{0x7}, {0x6c}, {0x8016}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x4e, &(0x7f0000000300)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000000c0)=[{0x40}, {0x5}, {0x8006}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])


openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0xc0185603, 0x0)
close(0xffffffffffffffff)
syz_open_pts()
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000001140)=[{0x60}, {0x3c, 0x0, 0x0, 0xfffffffe}, {0x6}]})
syz_emit_ethernet(0x5e, &(0x7f0000000040)=ANY=[])


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
r0 = open(&(0x7f00000002c0)='./bus\x00', 0x2, 0x0)
read(r0, &(0x7f0000000180)=""/191, 0xbf)
ioctl$WSMUXIO_INJECTEVENT(r0, 0x80185760, &(0x7f0000000040))


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, 0xfffffffffffffffb})
pipe(&(0x7f00000001c0)={<r0=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r0, 0x80047476, &(0x7f0000000100)={0x0, 0x0})


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000244, &(0x7f0000000040)=[{0x6, 0x3, 0x6, 0xfffffffc}]})
r0 = socket(0x1, 0x2, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x1e57)
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
open$dir(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x3, 0x0)
r3 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
mkdir(&(0x7f00000000c0)='./file0\x00', 0xc3)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r4, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{0x3}, {0x2}, {0x46}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
ioctl$WSMOUSEIO_GTYPE(r3, 0x40045720, &(0x7f0000000080))
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r5, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000140)=[{0x40}, {0x2c}, {0x40e}]})
fcntl$getown(r2, 0x5)
ioctl$FIONREAD(r2, 0x8020699f, &(0x7f00000001c0))


mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x0, 0x0, 0x0)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd02)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
write(r0, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xfef3)


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
setsockopt(r0, 0x1000000000029, 0xa, 0x0, 0x0)


r0 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0xfffffffa, "75e261fe528b2a334ba26da9d53ea6b078b68581"})
ioctl$TIOCSTAT(r0, 0x20007465, 0x0)


sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000240)=[{}, {0x3}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000140)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = dup(r0)
ioctl$BIOCSBLEN(r1, 0xc0044266, &(0x7f0000000100))
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])
readv(r1, &(0x7f0000000080)=[{&(0x7f0000000180)=""/15, 0xf}, {&(0x7f0000000040)=""/17, 0x11}], 0x2)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, 0x0)
syz_emit_ethernet(0x42, &(0x7f0000000380)=ANY=[])


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x4}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x27}, 0x4, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x50, 0x0, 0x2e)


r0 = socket$inet(0x2, 0x3, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x8, 0x0, 0x0)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x4)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000240)={0x2, &(0x7f0000000200)=[{0x81, 0x81, 0x0, 0x2}, {0x4}]})
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0xe5, 0x0, 0x0, "43b2b0bf3e79036980220d348bba04ff4e629aa0"})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r1, 0x1000000029, 0xb, 0x0, 0x39)


shmctl$SHM_LOCK(0x0, 0x3)
setrlimit(0x0, 0x0)
syz_open_pts()
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ktrace(0x0, 0x0, 0x40000500, 0xffffffffffffffff)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
msgget$private(0x0, 0x20)
openat(0xffffffffffffff9c, &(0x7f0000000440)='./file0\x00', 0x103a42, 0x0)
acct(&(0x7f00000001c0)='./file0\x00')


setrlimit(0x8, &(0x7f0000000980)={0x46, 0x56})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSTOP(r1, 0x2000746f)
ioctl$FIOASYNC(r0, 0x80047460, &(0x7f00000000c0)=0x9)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000180)={0x0, 0x0, 0x8001f7e, 0x808, "e730344861d011912be21d8f20905687a710ff00"})
writev(r0, &(0x7f0000000080)=[{&(0x7f0000000100)='>', 0x1}], 0x1)


sysctl$kern(0x0, 0x0, &(0x7f00000000c0)="c507a7c52de3aef8ea5922d792a516fea6f9e1715575872671c23f7f9a853b2a1dd0b69cff64ff108398e35aa4ace104cfa110c78a68f2ab9ceb441353e6292c3632b053da33e64207e3db45be34c9f84a519bffffffff9a9872a9c00032776f21e23e0315cc313674c27bc684808e7e2b514c51982f0f20d870e3add3ebfb9864e41ee706", 0x0, 0x0, 0x0)
r0 = open(&(0x7f0000000200)='./file0\x00', 0x200, 0x0)
fcntl$lock(r0, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000001})
r1 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
fcntl$lock(r1, 0x9, &(0x7f0000000140)={0x0, 0x0, 0x20003, 0x2000269000000})
r2 = open(&(0x7f0000000200)='./file0\x00', 0x210, 0x0)
fcntl$lock(r2, 0x9, &(0x7f00000001c0)={0x0, 0x0, 0x0, 0x100000004})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{0x3}, {0xc}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


socket$inet6(0x18, 0x3, 0x0)
r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x41, &(0x7f0000000040)="0400", 0x2)
syz_emit_ethernet(0x4e, &(0x7f0000000140)=ANY=[@ANYBLOB="aaaaaaaaaaaa7fd67572210786dd6007558300183701fe8000000000000000000000000000aaff020000000000000000000000000001"])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{0x7c}, {0x20}, {0x16}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f0000000080)=ANY=[])


sysctl$hw(&(0x7f0000000500)={0x6, 0x14}, 0x2, &(0x7f0000000540)="1c1d1332506c030f", &(0x7f0000000580)=0x8, 0x0, 0x0)
sysctl$hw(&(0x7f0000000180)={0x6, 0x3}, 0x2, &(0x7f00000001c0)="90cb55a661b973835a2b266aeb8d375424f5b0deed9f1055509c0280c3fe63f8b1965025b325ee5c080000000000000098ce461470f447ff0d3f786c0d68c6a60446c2215afbff2a5a6467ee795a2fc9a21a81000000199d931120c70e2311444fcf042b20f7f0da76d7c4", &(0x7f0000000240)=0x6b, &(0x7f0000000300)="eb0c7a490ffa686e0a711bb3ae5761115949d95a897957ebdaf803396da731a81bae4fc9b202b7e234ac5a6830f3d851d6077ace74d957e5263fce89c664a31821d05ba75219bea920d03f94bca52d0dd9347ad5cb2047ad175c294651f9d8cff2b8617b15615ac72a867e51a241d73cc261f7ccd691a2c41cff569073ee28e761249312b8d9abcf61215dfdf3a56f908ee8a96308b33327544e3dbb8bcf8d6d7854e634b4b1a98d0a53043e7bf81d6e7718e81baf4eb51c15a3bc404b1260aaa28a46368ef76d4ddcb8178fec1e934e6e00867d0d5e13553b97854cfe93b11579c65260b95b330650d255ecf63903d5ecad8e81bda7dda607e43d1d", 0xfc)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
syz_emit_ethernet(0x2e, &(0x7f0000000180)={@local, @broadcast, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x1, 0x0, @remote={0xac, 0x14, 0x0}, @remote={0xac, 0x14, 0x0}, {[@ssrr={0x89, 0x3}]}}, @icmp=@info_reply={0x10, 0x0, 0x0, 0x0, 0x634}}}}})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000400)=[{0x34, 0x0, 0x0, 0x4}, {0x54}, {0x6, 0x0, 0x0, 0x23a}]})
write(r0, &(0x7f0000000000)="7696e5f3d1f18c37cea8615ac7cf", 0xe)


r0 = open(&(0x7f0000000000)='./file0\x00', 0x200, 0x0)
r1 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(r1, &(0x7f0000000000)=[{&(0x7f0000000100)="b2", 0x1}], 0x1)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x1, 0x10, r1, 0x0)
setrlimit(0x2, &(0x7f0000000080)={0x60000000, 0x60000000})
mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x2, 0x10, r0, 0x0)


sysctl$net_mpls(&(0x7f00000000c0)={0x8}, 0x3, 0x0, 0x0, 0x0, 0x0)
r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$PCIOCGETROM(r0, 0xc0107005, &(0x7f00000000c0)={{}, 0x0, 0x0})


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000280)={0x0, 0x0, 0x0, 0x1000301010006})
r1 = open(&(0x7f0000000bc0)='./file0\x00', 0x0, 0x0)
fcntl$lock(r1, 0x9, &(0x7f0000000080)={0x0, 0x0, 0x100, 0x1000100000000})
open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000140)=[{}, {0x3, 0xab, 0x80}, {0xa, 0x0, 0x4, 0x400004}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x11a}})
r0 = socket(0x18, 0x1, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r1 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r1, 0x0, 0x64, &(0x7f0000000180)="004308ae2deac70f5150ba32e79d54b2edcb00000000000000", 0x19)
setrlimit(0x1, &(0x7f0000000000)={0x8000, 0x100000})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x0, &(0x7f00000000c0)})
socketpair$unix(0x1, 0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
r2 = getgid()
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
getgroups(0x0, 0x0)
setregid(0xffffffffffffffff, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x5, 0x0, 0x0, 0x0, r2, 0x89, 0x7}, 0x40000000000000})
sysctl$vm_swapencrypt(&(0x7f0000000040)={0x6, 0x1b}, 0x3, &(0x7f0000000280), 0x0, 0x0, 0x0)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000140)=0xc)
socket(0x6, 0x2, 0x0)
r3 = socket(0x18, 0x1, 0x0)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


r0 = open$dir(&(0x7f00000000c0)='.\x00', 0x0, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f0000000140)=[{{r0}, 0xfffffffffffffffc, 0x21, 0x2}], 0x9, 0x0, 0x0, 0x0)
symlinkat(&(0x7f0000000400)='./file0/../file0\x00', r0, &(0x7f0000000440)='./file0\x00')
kevent(r1, 0x0, 0x0, &(0x7f0000000040), 0x554a, 0x0)


getsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1, &(0x7f0000000100), 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
getuid()
getuid()
ioctl$KDGKBMODE(0xffffffffffffff9c, 0x40044b06)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x56, 0x0)
openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x0, 0x0)
ioctl$BIOCGFILDROP(0xffffffffffffffff, 0x40044278, 0x0)
setreuid(0x0, 0x0)
sysctl$vm(&(0x7f0000002880)={0x2, 0xc}, 0x2, &(0x7f00000028c0), 0x0, 0x0, 0x0)


r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0x36, &(0x7f0000000000), 0x0)


pipe(&(0x7f0000000080)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
poll(&(0x7f00000000c0)=[{r0, 0x4}], 0x1, 0x0)
write(r0, &(0x7f0000000140)="04", 0x1)
getpid()
setpgid(0x0, 0x0)
sysctl$net_inet_divert(&(0x7f0000000000)={0x4, 0x2, 0x102, 0x3}, 0x4, 0x0, &(0x7f0000001040), &(0x7f0000002440), 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
ioctl$TIOCNXCL(0xffffffffffffffff, 0x2000740e)
chflags(0x0, 0x0)
r1 = msgget$private(0x0, 0x0)
msgsnd(r1, &(0x7f0000000d00)=ANY=[@ANYRESHEX], 0x401, 0x0)
msgsnd(r1, &(0x7f0000000340)=ANY=[], 0x401, 0x800)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
writev(r0, &(0x7f0000000040)=[{&(0x7f0000000140)="cc60d3d79a1a7122a5fb9de9ea6ca0b30fb2942ef7652736f10f86d45ae419b2ecf7af93d33b3de1f2c56c0d93da7484095d0d543baf7f0161a025c9c02a561f9a76d06f1eaec7d8df99d6c28b10fa891e47d6c3bba690a611889032ac7b3581d7c92d1c546e59764f069048316871794f0615dd4d8bb1057a61fb177be649004fb56a7d46c856a20d73f050bf29d58b803a676cc3761e8a47857f51d90a4465f9c605ab2829d78ea2571910", 0xac}, {&(0x7f0000000080)="b30000659336dee4f0a3c1e1e4c3364ba1a4a09fa27a970fe766", 0x1a}, {&(0x7f0000000200)="5ff08de84b4c523a583f9155df135799960704000000babaadcec85d62a9a897a78307f3d2c30eea6356105ec8aaba86930f1aed0b0000000000", 0x3a}, {&(0x7f0000000240)="2a5f4cd9b73c31d629e8d68e605e5940744ef138960b671d42c56f79fcb70549247e5504e02f85a6099eff9291731e94399a7e966e783d4073ecd5dc8e540f32190bb47050aee3907495ecf7708d1c295a0836f79ba03ea13db12836c2441989726ffbf7fd1da55bfe2caaf081a1ef55599935c0e60cb0866ee48d420b77a6e269bc30b2650349e16792252c6be8bcc6e9ce2b941299ab505e4779fa1960bb7cf924dcbc53c82e76bcd80731a694d12e8a139d8ecef6f5560939054b7842d25cd7396377f39bcfe2a2383feea17b87393cd892b90742631718b1877d8d83d5f66587e3e5b1e129433ead750143a4c51aa46e78e3b1a54a4634eea2846511719b1637b19ea8c96a95332abd69014f53e91a7319a36efb4052387dc6330aa00b5680142650e8dab5eb6b83ff7d0bbf1293338a8d3e8a6dcd7ed4916279eac230dda46e6fcdebe8a4c12d598883d9392da05791e153d905ce1930aebfc5dfc0fc22a88777c9fbc24c0b021189c3503466bf850f59e6649dd0b40d935ba155a9d7e065df6d90a500be9d7e1e77607d495898a8d6c9c48dda88533e75e760dceae91d670f97ebbe68b845c72eb698a9e0389b15cfe768cd4e524dbe939bc2d8363ae3b71a454a0a0378cd1f36565ab9d1b92263688195df65151ee9b8158c7a5280019a38f00ea05142b3cc832ece46e326e36a55d7a30f866ca97da61a3877612f0d9f23c052edf60a430d3a9acbae3d9f14f22f38a1eeac7df37ae17748a960b9e0d265bf6cdec73bd2a7b5f25035d845d936936cbfe6f013f8d7c73eba2bd9876ff6db3224e50e75c051979f4cdc41d28ea54e28f560fb0291cd6b6ba527e0f358ffa46b988f0bdbf801063d2024380071709ac00ed463e08fd1718a857b567d8b3eda143915e943d9530d25ed15743e117be375dc08e241328a53fa05b58c7c72a35d471a72706afce82b6c57eef81444269e06338bfd0af6f6ef6479dcc26aab0b10c7e58572aa507a69831d63c78c947cecda2c57bb8ae6b2ad7862d160b423de941be69928467db10ee4817536196ad0c5cc02a74ba1a1fb467e472f025f200846112b6b3efd298284d8c0cc498fb9203db18e48e34c137d1285120d809a774d56a62b3dbe8f202cb9cf18c33099f5b9651fc7ae41de53842f327fd40bcfaa601a791da1103351a64cc9815ff1f32cde6fbfe4c92f55a9aff41c055d4edce9c656ecd1becb9035bb8bd46cf47bca0dcb1848da94d05d1475c83a48c02f8f808597eaa9e88a4e4b12d0ef95458eeab115cb189fa7e368186bb68610af4651e27feab061c4ada46e8c12d6d33fe32cd40485b02120418a9aaba8f04c17ea1abdcb9e6801f5d8090c0780b3b5ae4382efbb64f62c825527b7e3d60ad9c73ba7f174ea7c7f2d155808052a0ef6ab2af85cf9a758a8c1227c85f2986fc06c5f54807968b18b6b5f9168d0b2de2728689d75f0efaedf79bd8bbbbc1d46b0f6072d46d46687bc92c0b16c4ad36c3fe4c7a2fde0cfec859052dd78d841464a6b4432342ea973bf18f1f5abd7b2fe7962faef39ff38bd88a40dbab0f8c08541e38efe924f9ec1addbd47362e349bfca42fd62cf18fef8db7d3cbf0b1733d37dcdae5b9c738b8426a1cfa205c9671870210508c614f256d199fb822613518b1a6fccfee08c48f0feae1ca4baaf0a02635282d4f630a8df115dc73e72d9f7b8feb4333b2c796f1d3f2cfb398ba1e9c81584185b8b578bac3c64d667da7d91062f0c2ccec0c9d09e0c15c62e7bc509c3204d054c22d4eac685626e48e25cff2fc382279d9cb941c2ca182b1f65b05ff05db880a37b1e7f9b3d8975558858352bbbea9213a885b7d43451230e0624403baa77839baa33ae92de771ca76319c2353e9f98ea8191fbb686aed6d08e87bcc2bb8084ae02fafbac1a0bba93f0f155fa2d7bc21bf77f116429c6a1373c34d080518b73481fcf012c0a9127e8f174695ccd4add75b026bf2935990d5cebc4e74b97ae67a414029252336880232635fce7ed7bf0b069e08e10f7e1cc4d2973dcd2ea0b63f9dc4f4c2db92e03c553afcb1060b12f6b9b4d1d799edceefdfafdae63ad797e400645c149b20f8a10af54db3289441499e122413495c7b32179ab6c274bbdf6dde48ce26f46f07ede9a314c1a73669ee8cb0d854c8a3206dcd4f532d36fa7affca1226962e20ca2c6ca0da1ab0848d23d6f198681911592815c080cead9fe6c81cf0d7ce3578978dbf1dc2f1902e51f740f95b02ebff4cf25ac8d28b8e16998f5e329e9a377a82b5bc227f77c2f1ad505286aac8618799c2363a2d07d229519370be62ef0dde6525df45a7b807759b9ba1c8557bdbecb429432c4e1a84094edda567f1245ba887686342d0a31b7dbe09bd2be75516b255d2bfad9337649e86a29b0a19e16b4059c7c45e9f81db6780af6487a11f9088ea265a99d6e95535e14fe839945f8f7da9bf9142dd12c305bd41bb392cae8eb81b28fda176d4b538f4ddaaed47913cd9149d934ca36879718bbd76a2d7ce11e6294398ea433af6cf53b951974ec96a9527178b6cbad3088a2e2dc75113fa88ede462e68b4d6b63020a45e94fbc6c3e6677d6cffee0e3bf606cd2d4b9fac89f91db8f3a1fb9f506708314249fa5c36912e3cb281acbdec3b080735ae24ebb4bca3c7900c21175435afbe5024a706e90f8ecf257c99cd8b67b5a9c2bdc2bb624201f55882349526f8faf463eecb183635db72a6aef5fa2048d97e6f6c513598f49158050df1efc6b13b8ae396cd6a905c26b94d1d50d361f10c0362a8c206c7dd553dd8b116694aa82ac029c64aa71b8a307793da12f93ce030d3c42443c37b91043687befb7968da97ffe91d45e4fd506ba4d9c5d7fe5ac7433fb6bb3ce471f59ade734d109d2093fa119827b65a360f2128e7e85ab494609b60d6e236ed8a72984f6c75652f5baa07e2e921365af2b819eef58343e65ffb45ba8580d62f5b8a9988f7176c1559f8ede3b1b92e0ff27978fc5225ed1512b605f1fd4fce46e768970b11a7b4802c93eb05a8571887cdc15f69929eadcd1f9d08ed2d6aab2997ffa2102c2d8983a78ad43779d03aa612ecbbdde634b14e980b176f04f99efad82a04001f34d6addb89e0ce629856f5ad401fed1a2c046e1fe18741b24d4253830af94a1defeecdf6f70b430e48d7b2e4ae2fb331322d96e1a361e4dcae1d0865e7ccc4aa58bcbb3ad1ce0b294437887e03088a6bb4c92c3044bb33d2a893975023ad979fb2f84d4842326cf058595398779116245c452e54989df0591238af63c5b187d18457f008f2759ae470282ee4640e92639a46915fb67f22967beb1f46736aa9c90df08f39ee481f6859f9eafdecd473bdc24ef3ad71b4c54dde360f2d550db18af7589c8107f29b0a713b65f039da10c2dc55e408ce75c77aba97c116ab078ed1467464fe4041668228316f0fff7c0e0f1a3cc47aae570182197cc3a030a4af7fe2d401b5a13d59b8fe55d48b0667b782cbf1c2e9e491167d87830bb25008aff93c4459a3ce9fd8655a542c6311d91ec6b6bd7935aba1cd01d10439f5e5a3883566c8538edb97c5d2a7c7533d415973729f52dc03134f3d777b7ad07c0f5b0d985ca48fde6cce9ec99f1223f476dcfbb5ef865a3f54459415b25e2031eeb469c83ac68fd77e59c6b6a4b9543a943c4461e47e94d038c63abf2734a3c0e99b95505e13af6cf7b66840dc60e96fb218436ea00b4a577c2effdba43e6adf97cb47c0ce606e87a7834dec04396c1e4f7df59ae5acedfd1d68c87e405fc5d788884686270cb08f0fb15fe8b11589792f9afc11152cd45f43fac6e758588cfaa88874267c3096bd689108bbb0296f3d182df7d46cf7e6b8bb923ba887443c3d2211785e364c1e55d4e9396d950e50cc11ba9a4da70a64f6acbbcd421183eb2c0521054c4f39650409e21a9d3b781725b0c38abce7b4615fa64a9cbf71a19f7e414279a7494d2e66e4e2b2d5ce7027109cfc763a9dcac37065ae80ec0cf3962deec0f9eba3bd7c514a9854ddec6542cf60a1e69cf5d1a73239633675d4ac1f3b0758e69d1d9fb8659f43f07ef6b0b2a7c9740649198b44f3272a8810d374b00c1d49b7f667ed538d89e91e5734f8d6e270aef0a406fcb4072497dd5f25b49d31cfd64f7af2d5b4df72b74c39a66f442ae61aebe1cdb96b660e3248dad3d05bfce3d8630902a565c3a7636220e0435679ce1c45367570dd08722ddfe7f1bf56c44bcab8ef2d0979eeaa569dade4ec34751833d455b31b55edcb9b64f3045725fcd3a08ce0c20b09a437133df5738092eba91430208814b4135b0a64331aff1847ca60426c91e96a029cff039b14462da6e5f9c545980b3712f7fa5f3958d92278194cf6b37ef76e91103d14db403956a7070d87afa81df227f2189926e1265a2872e9d64c64496083caff36dd3c27e961957acb86f0f9a3cbb5ddbb6bf9c62dc102d70d62eea969b1c2c5f42823f76827e918ffa77cc12ca8d31effd0b55529c496da762b6a95d43360ea4e811979ee316e143733f886a6eca5ac76746d4a302ec57b6b4af57c25631d7773243abd400d15274703154dfde2f1a63e075e4b22ed4516dd1496e3f7848bbf19e3215edda64140649d9b1a06975773d5dd0ca9c4bdfd5eb9fb6164aa659e2a8415098dd05496d0b2a20d966a4c9efefa964e007a3b731d3bad501fd21ca564c6155d893c3075c234af6378a12595d8a88ae0518350b75d57fb91b7610bfc3168f548a9a63432b49a9dbee2ee1a4ddd80255e2c655cc80d59d7e90e21fb090db6d59ef84c0becfda6bd01c5a806ce67bea77fdba62ba40e2114d31e6087ad67b28adc20d7cabe7911aa2db119cf5f43b2011bb92556e8e303a264f813764027fbec36f8248a667c766cfc12c80d96965f222d39b5f58a54b255d3b1eb4530952b6d251ff1f9a2cbc585d539704c8ea6884699ebc95d57cd1daef169da86cc10fe7300352e939c35bbe3104aea1b1c681f3e98be8fad7c91bb56724ffa794ea4ac7c4d51d4aad8e94087b4cdcab897e70558e6648ab42dfadab447735912af011fdbd9a47a4958b953b01d2e274449854cb7d4b44d88fb2db162b8dd664c7c32858c7714c69b838cb30b17e6a42ca760256c4c6da57ad5be955ca8c787262d8bd3f4a5f0170e70f92ee2ec9d227d066e41d0d4b640166b2f6937a66bc84506d102d3edac818b246954ba200a3057820da10b64ff99f016b42d90a29b43290d731ef23a72612d646f92acc05620068fd94edd12902197733cc9dbb55d95930ccc749c4a169b4b7056dba24f767da022eb01243353e1f4d0af2eb32e3feb331283ceab3e0112b37556749a701d11ada5cbe1b4c829fac46e12612679e47d4a066be939b886f0fdc2b4c5b4dd183ca025c5191ac67d", 0xf01}], 0x4)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x11, r0, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x4)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
kevent(0xffffffffffffffff, &(0x7f0000000040)=[{}], 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)="000001ad", 0x4)


sysctl$net_inet6_ip6(&(0x7f0000000180)={0x4, 0x18, 0x29, 0x36}, 0x4, &(0x7f0000000a00)="1091fb7d1209aaa39ef08443", &(0x7f0000000200)=0xc, 0x0, 0x0)
openat$null(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ftruncate(0xffffffffffffffff, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000000c0)=[{0x3d}, {0x44}, {0x8006}]})
socket(0x800000018, 0x1, 0x0)
r1 = open(0x0, 0x0, 0x0)
r2 = socket(0x2, 0x4001, 0x0)
r3 = dup(r2)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
listen(0xffffffffffffffff, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x1, &(0x7f0000000040)=[{}]})
write(0xffffffffffffffff, &(0x7f0000000000)="76e5de000001", 0x6)
r4 = fcntl$dupfd(r3, 0x2, 0xffffffffffffffff)
sendmmsg(r1, &(0x7f0000000780)={&(0x7f0000000740)={&(0x7f0000000100)=@un=@file={0x1, './file0\x00'}, 0xa, &(0x7f0000000140)=[{0x0}, {&(0x7f00000003c0)="64fa5f80b22f42022f75df3424913fabd75d707549c3e6ba19f933a71c84ef0f0be26e2644f6937cf2dfe0d4ef7e06167bd8f44c0ebd4bed63a96564a878daaadd805b6f84aefe5f0b603a03989d6c0adb001453e34654fc4966a53a910618b20ad981e4f7de551aedff05d378f7d5c1014d9fe0d1a79e81db9e031a9afd2f00e141cf1caa8e3ba6c3b150e344d9d563c9d77455dbb2c5180dbdd935dd8194", 0x9f}], 0x2, 0x0}}, 0x10, 0x11)
r5 = socket$inet(0x2, 0x3, 0x0)
setsockopt$inet_opts(r5, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
setsockopt$inet_opts(r5, 0x0, 0x200000000000b, &(0x7f00000007c0)='y', 0x1)
close(r4)
r6 = socket(0x2, 0x2, 0x0)
dup2(r3, r4)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
setsockopt$inet_opts(r2, 0x0, 0x1, &(0x7f0000000040)="ee08665d19ac14d5e5134876f197a7728420aef6171504b1c3d4b3830c921bf0817a0000040000006a89dbdf", 0x2c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
connect$unix(r6, &(0x7f0000000000), 0x10)


madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
socketpair(0x1, 0x2, 0x0, &(0x7f0000001640)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
recvmmsg(r0, &(0x7f0000001dc0)={0x0}, 0x10, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000040), 0x0)
r1 = syz_open_pts()
ioctl$TIOCSETAF(r1, 0x802c7416, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x0, "226fcf009fe10000000080000000000000010010"})
read(r1, &(0x7f0000000100)=""/140, 0x8c)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
bind(r2, &(0x7f00000002c0), 0xa)
connect$unix(r2, &(0x7f0000000000)=@file={0xd1653077bafa0115, './file0\x00'}, 0xa)
mkdir(&(0x7f0000000640)='./file0\x00', 0x0)
chdir(&(0x7f0000000140)='./file0\x00')
symlink(&(0x7f0000000200)='./file2\x00', &(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
open(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
r3 = semget$private(0x0, 0x3, 0x3c0)
semop(r3, &(0x7f0000000080), 0x0)
rename(0x0, 0x0)
semctl$GETPID(r3, 0x3, 0x4, &(0x7f0000000680)=""/8)
semop(r3, &(0x7f0000000280)=[{0x1, 0x7, 0x1000}], 0x1)
semop(r3, &(0x7f00000002c0)=[{0x4, 0x0, 0x1000}, {0x0, 0x420}, {0x1, 0x2}, {0x0, 0x3, 0x800}, {0x2, 0x204}, {0x0, 0x4}, {0x3, 0xfff8}, {0x2, 0x9}, {0x4, 0x1, 0x1000}, {0x2, 0x7e7}], 0xa)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000002540)={0x0, 0x0, &(0x7f00000001c0)=[{&(0x7f00000000c0)}], 0x1}, 0x0)
ioctl$WSKBDIO_GETMAP(0xffffffffffffffff, 0x8010570e, &(0x7f00000001c0)={0x0, 0x0})
r4 = socket(0x11, 0x3, 0x0)
sendto$unix(r4, &(0x7f0000000500)="94010504000000000000002797888fd1f838a311000000000000b13886ca3849451ae3c3051020741038f5538551f30ce390500e08fecea11ea8fef96e4fc748e93f0b780486aebdbe781e4d8f5eef9187a869a4d3a4cbba982fd825582fe223ed00f4c8b2ca3ebbc259699a1f132e27acb5d62934e4fd89070000000000000070c1f5a872c88dff7cc53c894303b2a0a85ff3faa800000000009ec7ab3a34c29000000000000000000000000000002d7e4a5d76cc3f9cff2ed2243e56fa277603c5cc1e047326bcf6b67b75d00bf6ee330b6a80874b70559d9975ebd13da2447a78aa4b00cd0ba1870215607bb912e3d7325183ce69456b4b6ca927871c81672a54ec695c5bdeb842836656f917945cc076f87dc714dfe0aa2947252df350707b22884a7730cb6dba8742110fbe9ec7481885274387e0b1dbe5695122604819b0b2294b7b20726a5d4fcb44f62d00fabb2f247a166d8d79d05b8cc370f5c11db58aedca632a83acd58ff0ea0a3dca58ccb03cce466cda735017196ff346c32717397d6ec6952ec90de81ed297b2509e130f0000", 0x194, 0x0, 0x0, 0x0)
semop(r3, 0x0, 0x0)
semctl$IPC_RMID(r3, 0x0, 0x0)
chmod(&(0x7f0000000440)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2)
sendto$unix(0xffffffffffffff9c, &(0x7f0000000000)="ebee9e278c8a999d224d249bcbb3fb55ae81bc9ad41669760783dc4a7bdcf500701e550e1b231119ffebffcb", 0x2c, 0x1, &(0x7f0000000040)=@abs={0x0, 0x0, 0x0}, 0x8)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x1, 0x3)
ioctl$FIONREAD(r0, 0x80206913, &(0x7f00000001c0))
setreuid(0xee00, 0x0)
r1 = geteuid()
r2 = socket(0x11, 0x3, 0x0)
sendto$unix(r2, &(0x7f0000000380)="b1000504000004000000000003000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac5000010000000000000008abfba221554f4e0f668266c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)
seteuid(r1)
setuid(r1)
r3 = getuid()
seteuid(r3)
r4 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x200100000001d, &(0x7f0000000000), 0x4)


socket$inet(0x2, 0x0, 0x0)
socket$inet(0x2, 0x8003, 0x0)
syz_emit_ethernet(0x2e, &(0x7f0000000000)=ANY=[@ANYBLOB="000000000000aaaaaaaaaabb810001000806004b08f905040086dbbbba595918e0000002aafffffffffffffe7f02"])
openat$pf(0xffffffffffffff9c, &(0x7f0000000100), 0x8000, 0x0)
r0 = socket$inet(0x2, 0x2, 0x0)
socket$inet(0x2, 0x0, 0x0)
r1 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7960)
writev(r1, &(0x7f0000000000)=[{&(0x7f0000000180)="7f37ce070000003d965a1564287bafc1d6d531c28c4a7eaa13e5232a74bba3779ca27b8e0d00000004fe8a4cc330bb35350cb60a9a374aa8a836289681106692", 0x40}], 0x1)
execve(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
setsockopt$inet_opts(r0, 0x0, 0xd, &(0x7f0000000280)="cb0000011c00a500779857d8", 0xc)
sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x25}, 0x4, &(0x7f0000000200), 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
open(0x0, 0x10, 0x0)
utimensat(0xffffffffffffffff, 0x0, 0x0, 0x0)
openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)


r0 = syz_open_pts()
close(r0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r1 = socket(0x18, 0x3, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r1, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
r2 = socket(0x18, 0x2, 0x0)
r3 = socket(0x18, 0x2, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r4 = dup2(r2, r3)
setsockopt(r4, 0x1000000029, 0x23, 0x0, 0x0)
writev(r0, &(0x7f00000000c0)=[{0x0}], 0x1)


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg$unix(r1, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="28000000ffff000001"], 0x28}, 0x0)
recvmsg(r0, &(0x7f0000000180)={0x0, 0x0, &(0x7f0000000640)=[{&(0x7f00000001c0)=""/23, 0x17}], 0x1, 0x0}, 0x42)
recvmmsg(r0, &(0x7f0000000040)={0x0}, 0x10, 0x0, 0x0)
r2 = socket$inet(0x2, 0x2, 0x0)
dup2(r2, r1)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000002c0), 0x1, 0x0)
writev(r0, &(0x7f0000000080)=[{&(0x7f00000005c0)="cf4436e04f6ad215e58d0b874f6c9e5a79ca8ce690e500000000000000005504e216a287305658114633b220e5e87a90d6f66aa77753d063174a351540bfb8314f42eb2c2c34f552eb3942f178bb7f1b9ec7a35066b89bba63c8796e9a0d983cc1d321f5de29f68fc6d19c1ba64dcae60a611c425c18100114a23c120eea1b27d44fdbf40e30e7d305000037f6e05e3dfe00f6a3753519eaada49c644e8262dd3fd19d394891826335c0900164fb0010000000000000f48bbfdbcde3eb50ec5ebe6aa4be512a1cf6f51b000000985f93000000000000000000000000000000000000000081331d0d801bf941a557f13e1a834c1862a548a0c98c8686d460ce79f36f79bc5d9b1f47ab5cdaa9406227436b04261bcba28c1989d923e9124ced16e0ef35a98cd91b9925dfdab7dd44e145ae4e8a7adbfe93ec7f51ce59beb87573323adf3d219c9ff755548cc934aeb149992b9718212ab9e2944a9c1979cfe14745b781fc6bf2a55a56ffcb023940d3120db806b4f52c9a9eade5a5a972866020f181251c124e34e3a83c58179adb50211fedc568f8d620f4ace7d74d27994b7e50c5030b9b4db77980f9f8322b180b6f633520d87af3efe2cd2bb6f0ef01285ae840a139ad8eb843738d5f69d16c5c0dc59436209720569471f5f6cd9f6329c09604ebf98c2cb2eb48445c07f81c68cc50bb05abf8d88a0a5cce64ba81d44633", 0x200}], 0x1)
execve(0x0, 0x0, 0x0)


mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x0)
r0 = open(&(0x7f0000000280)='./bus\x00', 0x0, 0x0)
close(r0)
r1 = socket$inet(0x2, 0x2, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
setsockopt$inet_opts(r1, 0x0, 0x200000000000a, &(0x7f0000000000)="ea00005c00000000", 0x1)
setsockopt(r0, 0x0, 0xd, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000440)={0x3, &(0x7f0000000100)=[{0x15, 0x0, 0x0, 0xfffffffd}, {0x6c}, {0x8016}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000002c0)={<r1=>0xffffffffffffffff})
pwritev(0xffffffffffffffff, &(0x7f0000000200), 0x0, 0x0)
sysctl$hw(&(0x7f0000000000)={0x9, 0x6}, 0x2, 0x0, 0x0, &(0x7f00000010c0), 0x4)
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f00000000c0)={<r2=>0x0, <r3=>0x0}, &(0x7f0000000040)=0xc)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
kqueue()
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r4, 0x80104267, 0x0)
syz_emit_ethernet(0x4a, 0x0)
sysctl$hw(&(0x7f0000000000)={0x6, 0x5}, 0x2, 0x0, 0x0, 0x0, 0x0)
r5 = msgget$private(0x0, 0x397)
msgrcv(r5, &(0x7f00000007c0), 0x8, 0x3, 0x1800)
msgrcv(r5, 0x0, 0x0, 0x3, 0x0)
msgsnd(r5, &(0x7f0000000d00)=ANY=[@ANYRESHEX], 0x401, 0x0)
msgctl$IPC_SET(r5, 0x1, &(0x7f0000000340)={{0x80000001, r3, 0x0, r3, 0x0, 0x2, 0x9}, 0x7ff, 0xffffffff00000000, r2, r2, 0xffffffffffffffff, 0x7, 0x12c, 0x3})
syz_emit_ethernet(0x4e, &(0x7f0000000100)=ANY=[])


mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
unveil(&(0x7f0000000040)='./file0/file0/../file0\x00', &(0x7f00000000c0)='x\x00')
unveil(&(0x7f0000000000)='./file0\x00', &(0x7f00000001c0)='x\x00')
unveil(&(0x7f0000000340)='./file1\x00', &(0x7f0000000380)='r\x00')
unveil(&(0x7f0000000080)='./file0/file1\x00', &(0x7f00000000c0)='r\x00')


writev(0xffffffffffffffff, 0x0, 0x0)
r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSKBDIO_SETENCODING(r0, 0x80045710, &(0x7f00000000c0)=0x2000208)
syz_emit_ethernet(0x3e, &(0x7f0000000040)={@empty, @broadcast, [], {@ipv6={0x86dd, {0x0, 0x6, "6aa63f", 0x8, 0x2b, 0x35, @remote={0xfe, 0x80, '\x00', 0x0}, @ipv4={'\x00', '\xff\xff', @local={0xac, 0x14, 0x0}}, {[@fragment={0x16, 0x0, 0x40, 0x1, 0x0, 0x3, 0x67}]}}}}})
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000240)={0x0, 0x2000000001})
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
r2 = socket$inet(0x2, 0x2, 0x0)
dup2(r1, r2)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000200)="ea00000000000000", 0x8)
socket(0x18, 0x1, 0x0)
open$dir(&(0x7f0000000580)='./file0\x00', 0x40000400001803c1, 0x0)
r3 = open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
poll(&(0x7f00000000c0)=[{r3, 0x6e}], 0x1, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000080), 0x10, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
close(r3)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000240)="ea02000000000000", 0x8)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0xa}, 0x2, 0x0, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0xc0185603, 0x0)
ioctl$VMM_IOC_RUN(0xffffffffffffffff, 0xc0205602, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
setrlimit(0x0, &(0x7f0000000040)={0xfffffffffffffffe, 0x5})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f00000000c0)=0x5)
writev(r0, &(0x7f0000000500)=[{&(0x7f0000000440)="fde0", 0x2}], 0x1)
readv(r1, &(0x7f0000000000)=[{&(0x7f00000009c0)=""/4096}], 0x3e)


setrlimit(0x0, &(0x7f0000000000)={0x60000000, 0x80000001})
syz_open_pts()
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
msgsnd(0x0, &(0x7f0000000100)=ANY=[], 0xe1, 0x0)
openat$diskmap(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x7, &(0x7f00000001c0)={0x0, 0x0, 0x7ffffffffffffffd})
clock_getres(0x0, &(0x7f0000000000))
sysctl$kern(&(0x7f0000000000)={0x3, 0x1}, 0x3, 0x0, 0x0, 0x0, 0xfffffffffffffedf)
mkdir(&(0x7f0000000100)='./file0\x00', 0x0)
r0 = socket(0x2, 0x1, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
open(&(0x7f0000000200)='./file0\x00', 0x38101, 0x0)
close(r1)
r2 = open$dir(&(0x7f00000001c0)='./file0\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140))
r3 = syz_open_pts()
ioctl$TIOCOUTQ(r3, 0x40047473, &(0x7f0000000040))
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f00000004c0)=ANY=[@ANYRESDEC, @ANYRESOCT=r2, @ANYBLOB], 0x9, 0xb}, 0x0)
socket(0x18, 0x2, 0x0)
r4 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_INFO(r4, 0xc0185603, &(0x7f0000000000)={0x97, 0x0, &(0x7f0000000340)=""/151})


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f0000000140)=@file={0x0, './file0\x00'}, 0xa)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
r1 = socket(0x18, 0x2, 0x0)
socket(0x0, 0x0, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x200, 0x0)
pwritev(r0, &(0x7f0000001640)=[{&(0x7f0000000040)}, {&(0x7f0000000140)="0838b76b0beea217648bd137954b62368ea3a76cce7052b508a9d9e79b483594e7e0bd3b87894a48783294e7dd277b3e63be179f7dad5c2b57f45c937f55d28a7ce078311135b67b78f30a9e3b210f89b9ea2a773c260cdf8ea39c93f8a5e47b2e68085a5f91199e168b5714f7e581eaf38bfdf314444d22e8ab1ffe17407504779715952dd4de16c2b15a1aa5283211209395ae9a12b78173317f199c3367c868e2f9111b492d7a74cda9b6325a2f29298b27dcd5680691d9a72a75a19b4a4bd50ef71ad8b9efc9e802fcdee01553243fbd2cc4d9be2c4812e2e2902c695cbbe7482e4d3690a98e089f13b1587ef40d1fbb0ba18fdf93140b240230474474b1eefa3bfc784820a31ae6ed02028259aa0d7bef7e7255aaef45f9ecb555c486ab8cb294b261fdb42f4e288079ec034753f66e46efea21073668713ee5b390f4db99f6315a8204c6db74997e67784a558954b840c8e199345406211e21364da01d55ca389da72af166ff9987a3e296cac2af4f51c5b58bbb6133ab83276b0fefd8fc0043b7b51d69c07e497c80584e27843174b640828011ed5898ff81da19e31fed537a93e78a2ad5d06a54c18539ba0363a33405bd188c8b92f9964a8fe8dd1923ecc7faf10dea620cbdf739765a19be05b0879f7ac74da7ef7c8a7d3a7831779c2059a3ea6d167471324eb2c9befead994d11b470477325cb0dbbf31fa199d33e19e7b17dd93a0a136d1c623173baa167fee53a4f7ed17f8a84729ee9d503cf459e880c630070734e39cf77f4988dbe6f6cc28a2b50b578ff03da86bb9f549de2f57c8f3a9bd97f4838b8c935098cadcad976a0496ada6ec509b74897a7f25ec10c244cb783b099e0d759b36c98832fc1fd36070efae0fa0fd88022ec172ab2a26c8bd84effd33493c892604ee74d539614a0c0641149c1b4dbddfcd62bd8a464aaa6c77639fb8ae163363aa3eaa39c0a18cab6baf469b9786cfd4c6769b4e96c6cfd9396d7b6a216e90d8e2f10d3d0a420dfdc3e3e2fd30d2cbc0e79eb5e91551b46b57459dd10594a9730a56d8a520b31cef3b5a2ef8aa6f14cebe63187668f935f2dfd9dc2e8f375c3ed4d4fcbc25e65f6bc1a836b13b23de2bdfd7cbf90af5f18bef33e48b982876353b33dfa428d716362ca8f48825531c9fbe0515474079ebaf81bd4debe1812b43305afac7358ed960c6eceb0e4a44b68000ea9ba7ba705d5efe96a0df454b20cbacaf151ffdab18b96a16273f692cc8dae77f2430fe155af9804c22a2e2290526d26336b2020e85c76fa55363ba5d2ad46f143c3e749c86e22c42bedbe5a324355472cb52d5ca5738861ab8d02acff846d874308f86742b672e1ab5a6952000fe0e3322b6438be31b31f5138ea4e9910799d1fe9cfd1e7d895faa8feae1d8aad145ca17090050c5cc835864736a858cb7149888d77a585c5b67ee077bff4fab3d124a035ea09c4981d458a2854e189c052d52a68eeaf2660e7ca04e678d1a9775917173ac54037fe938540e638350d049ecbe4b49663e6144ed0e104bab5a3e493badefeedc219522a408ff9aacbd305d4d49f82ea8d409f14e5a9d9c352c0ae9a74c94b22798c3f256dbaea9879c750f68fcdc0969e63bdee9611d5c22f6143824605b1b37ca3e0dae8b93a2931fd160d0c7ad04e169c789711d3d57f735e9be2507ef08dc0c069b88d9f99b2c8127adbfc398a763980f12a0c11446dda05b2f1060a73c9f59d4ac46cc1a66a41d322fcf80de4ced1c4977fb3f385ccb3e1fa5f60ea727fe471a83da64469b38afa8783403445d43aacd4d3013110289adf926f5cec2597906f3c7faae899f02bf2471a3ad889a15707582ef4fc2c3f3def17ef63a9fb0c0e8f029f26fad7f4a48db7f14576a88fe086ed72ec63503f82cc3daa0c5537bfc831dacaf0bf6caaab018fcac441458e80214650c70277ed1f8ec053239f62e15084fdba9751bd8b01357eac163459fa82914b3264b5736d1fdc1a043389104d0801c6887edf942bf4f95d24d39b7ab851369cfbaec677533ce6301cbcb8ee293cada8e766c1b87acadc5eaa8c0bf9979296af52229a93ee65d5cc45cc4d396428c517938d7f07d73968b32ae44a1a551fa4354e8696efc9fa9440482f642e04b62d3a91d5e92f2b9e6027eca323d1bc4752946d689402c4e5ce4fceaff561a17aad34357e8e33bc271f4d1ab364e58cda46e11d2b0551ecf03bd32a4d663cc25f88ba77802ce77bd94e69b50f4c79ccf4e624fd4724a9f47e52a21392b506ae9c3d4f23f93399f9984e3e87339acddc458de859aa687f60a55ed2b36bf92c4e52183f8bdaf0565977dfe1967e8b8e1107b06bc7be7ec98e34788e96c450f999328025d0734aeda97a247be5e9e81f73341d50966a829949cfd88c1702d2883cd1a460dd8ba870422642ba05bb3fa37b6adbc18e903f850a3a7877d373d72d7224d1bb1c0d0d320cb5b5cb5b128de4d7c8e6b3aea4634237387deafa3096fd96f8ff7f1d07c1c020c611a14cc300b244a02ec54b64ab68a3893a43776a93b1927cb00b210c0146cbd760a94c083a6c9b226cd84047c3fb0ec1da105324262dda2a240a4eded16f93bf1237cb3831340d86f6086d6a05f89a5cd3adca9f82cc5d3e9c23cb41b1d833ef05d5e248d78a415a70105054095c34d92abd9a7458315d4b810c93414358aa52ed790d8cf59b8356aa473388073094498ecf443f79989ca00a4f91c296726e1cec69d30c6de0da2020f31134c48a6f76b7ce873b20a7e8a50fe74056d62d444b5ea251584860095e18f428e0039690d0e795dea51d21f300679559df4ecb863fb9258d07ccd2b00470041fd2817a52e9cfbafee523daecd98e6f328d398e363096a1be95aa4e4fcd95fb2ee47f14fc06f72d5e05b12aeef148162b0d1d25337fe8e4cf82642b43282b032dbb9ff0aca0a3a5769a419f94603aff65bf4f9a35767504f59d3f7b4c7f5f7391e4ce9a6927005b67306635ea3bc088de579a3197fa83bf50ee713e14b0d20a8c5f4376be023ed485d8aa7904ef8ea68fdf88c68353264470fe59e50ca32d9e3798923048e62518c673c9b7fb0b1122c7606f8209e2b243de91b8468d83c40797b66b8bf1c0be00fb89131b7c186f43ed45cdbd22beb43f012108fced758e6891a8d537d2a21d110d4b8497b2219da4ce19375d0d70b27d1369332e29a46b2f54d7a8dd00fece4fe9de016505312940776ac02af47664b5a3e605970f092924d9b526825d0ebdada4901de720f32e7386d755c13b3ec1fde89ea92d94cab3d6a66b922760abf6bb57a6b0d75015e448103aeeaca5626bffb8037e18677a14e8a4c90286d3b2616f358b9bd5744cff7d7a53a5ef617bc94c1e68e2abd519000cec89bf3dbad13efb2ae49f04bac5bbf3168ea60e4d1eab8bdcbf44459b71c8cfed52da97885d637969962c341031ae7b7d090726ef5b1ef150f7a7d63ef2147f8dcd5809dedd907de3605d168429a78f49488e9e7af695a148d3135576ed28bf98f6a101974d7b4fb35a5366486e8121aad5008089c01c2b9d02e608ed5d69d12cd549cba69c40f6bd8d02d0cf33f4fdf1eb4917f9ec68a15c56bedb8525253b743bf530a1ac44ebf0c38eed3d1ff1697bb0e36acebcb10f06ecf1264638e856548a6de69222d49fa205bf9d2dfc600cb6f436186719d084c3237860dbc01a041a92b54095751c6ae5dcde6bf1f5ea4775de5738b769531f04dfdaeaa30a472d62f967a2f659a82751cf92d19d1e2f2c190aaef2bca3b60d7e8e0fe32ce5c8e9afb67e52aff1c421251d5fd9a5d6702d8f3cec0f0dfd625917a81279b470a43f604ca4714df0b78521b72d9212ff7af2d627fef004629de16b559f72c7573433ef8dbe4da1b9cb1b7af24c18440593b79e21bd2554bd92eb4d0c405f09750db9b93d054966afd8e29e66bae113fe7f31319b5853ae59df1f8876d38f53943b8bb35c763ad7b8ec642b70713bf4f469128142f918ee55eb450cf9bf7b62cb88821250e7b60deccdbf5a8b83a448e4dcb6708be77a56449fe709d634e841982bb5e45fd136173569ba63c4897d910501916fdabca9b6f92abf51ea74ed751a1ac3fc9c60b5467517f7b022c7fbded17dce04b7bba3e1b75691c5fafd279b50f5d698ab310f9eb35f0db42e6660f8112dd9249e6223b41af07d25a336c654babe15f791c2bfc26e6c97e5b27e86c5b3ee1f93053b06ed173cd5ed046202ac130b677b9664b9c1425dc7c50a595937834a4ac1959c0c6b4c44a7dbbe37e8890cd4800a79b84583b837fb827a415091b8f18bc2c163f5a584a129da463df9d3277d0cfe8aa437303ed6c380e68c58b9fb2384d342fbf0316d5a34373ec6e8281cb401082344906669a59ea05f5f07eae4ed325713d071762a176bc140937001b1b5098cb9578e16963b5d740ca7031c35961ca02e76cb2280d7c61022a00ea3b74175cd640a5d56fae41b82e0d7b10d66849573df072f71f7841de3a1490d34c628d158719d4dc5b557f99684972a23fc5cabcbcec499286f3822312c8f41201215476bd9def798d085d559030f28bc3e0134f34fc97a29158e7177c09d21900de05019fba8325f953e8ea580d5ff21dc4025712a88215d774fdb56d5ed863eff6cfa013fe74bfd306e69c53a98ddbefa3a64bcf689c542e5124fa494f3f5c036f852d76633b1e55c0ac3e007d950f84e1a5434fd7aa899cd1f41191f5853afed2e1312928f9caafc88d42784570bedbcd45222c648994ef855f2abe0bf697df89ea66f5d5c37214e0cb6d27c22a76f81e3e6a4e50c05e7f6b6c3d3489cfb9758c0497816684d830fe40237825d94030cc9c3b8c77df8b34140f114415b3a7d95e996e55a95141b3fb6dea9674591f1117d985d40ecf492659d61d0cb6dd9c34eb1400a9d05dbce92299be6baaa214721a48422288395f1c38fd6c0cdf18443d701fed054040fef410c3e933ebb7bf30edbe408d49e89eab6260489a2a7714f17b3d8d1a33927d5bc85040abc35e6976cd9919863639c65eead930dfb01ec987d1032f57fb64b34af7df701221bb9a8ae558b58136c20c82232f8c7420a866304b595ea98b73cebf795e44c72788fd6f938f0a8ae9ffbe9efa463935e6ce118c23cdeccda0bcb5286f4d76dec3051216f836068d35302bcc278e7fd1075f6ceec8ee171491c3c43beba36a95fa055f6bbdc948c73079abade441c41fd6a86b1b70dd2e6fd57e36258e0e0517349461e6ac841a9b6cc0c3e32aa781f3cd74743a71a0a51b4ce028bcdc2126d77ce890f596b516e8168285ba65939bd86c94dd8899772e92c86d98fd5de12b6977ffeebc76c75ddd7837607745ff0e0dc4bef411be03456a522643e41afbd8821cccb6dacc27ea7953c62970ddeb6309afe55f9adb4446a765bfb6cebc407971d23be2a99b10381befae061c320f4b89e44acc788ff6e860045ccb607b0d7799d412c62a32926bf73b914b43bd3ecb93af9b78f43f4392f90f99c2b5858699e2b3c2bdb5326f9d555a04db165d5986c61e1f1871ac15bc79b85385ec68658efd6606e44e940c2dfebf2b50a6300d35501b34f4324ceef271c10b29743b26ba098095842850a30982f96a6dbb74b8bc011dcc73ebd11389e06eded5b4be97df542e346c9268ebeef5ebab6f94190955a097266e1", 0xfc0}, {&(0x7f0000001140)="1bac710bf5c0a9c470dbbc46779d31d66ced0b4cbffcc184d488a166952c98825885ceea216d02b333731938baa36d074324893082dc0b3a79210f9143157cfbc9f99a8ed1393fdda9ef20902368d48c9d922c5f8bd9ec66659f18d5a8ec851c798ca1d5fc2e5cd6bb881a89a0dda5196f34bc4e5a90bf4e9bf95cc472f97e2a5b9727ddac9f484d45ce918a497c14779dc717f9a13ca646ca0d79211b7f64d60ba3fae92ccf8fb978f162fd36c21e790bf108a9b0d333e68d6b38b2335708ff080b9bfe75b3773af5fa5f6821", 0xcd}, {&(0x7f0000001240)}, {&(0x7f0000001280)="89ca7b5ce98f26a2cc846874334d914a8792fbb118659d58f1675c1508099c802bd1603772442f6db1e41bc906f2444525818cee0f", 0x35}, {&(0x7f0000001300)="5b46ec7d3d06942390055b319cafef6f78a844193dd8ad3f03f88e994a4fe08384885d436f59ef06da736c02981c231475ff35e1129f4c2c19b50172550b6838ebdd25bf679c203e9d15acdb187f8c02873f8520ce3db6440796634351faa54471073855744178392cacf1ac4e0168fc1a5ae3ea17f81de515912a6770362b22bdedd97d9b741ae8eafac1a5617686cd3ba94a", 0x93}, {&(0x7f00000013c0)}, {&(0x7f0000001540)="24328becaa50abdacdb0bfdc1d01f600e3e0b87676945d1069714c13cb23cde576afa17fe50ecb914c6d9cdf9323aa790a60bf8c0d872234a5d0c19fedacc09b75c9bfcac78bb30df4aa67eba4", 0x4d}], 0x8, 0x3f)
socketpair(0x18, 0x2, 0xd2, &(0x7f0000001700)={<r1=>0xffffffffffffffff})
bind(r1, &(0x7f0000001740)=@in={0x2, 0x0}, 0xc)
r2 = fcntl$dupfd(r0, 0x0, r1)
ioctl$VMM_IOC_RUN(r2, 0xc0205602, 0x0)
r3 = openat$vmm(0xffffffffffffff9c, &(0x7f0000001b00), 0x0, 0x0)
ioctl$VMM_IOC_TERM(r3, 0x80045604, &(0x7f0000001b40)={0x4})
ioctl$VMM_IOC_TERM(r3, 0x80045604, &(0x7f0000001b80)={0xb058})
pipe(&(0x7f0000001bc0)={0xffffffffffffffff, <r4=>0xffffffffffffffff})
poll(&(0x7f0000001c00)=[{r4, 0x2}, {r2, 0x2}], 0x2, 0x6b)
openat$bpf(0xffffffffffffff9c, &(0x7f0000001c40), 0x10, 0x0)
ioctl$VMM_IOC_RUN(r3, 0xc0205602, &(0x7f0000002100)={0x5, 0x0, 0x1, 0x0, &(0x7f0000001e80)={{0x0, 0x0, 0x4, 0x1, 0xc0, 0xd208, 0x4}, {[0x0, 0x0, 0x0, 0x7, 0x4, 0xc08, 0x8, 0x20d, 0x9, 0x22, 0x8000, 0x6, 0xffffffff, 0x8d, 0x3, 0x8da, 0x100000001, 0xfffffffffffff880], [0x0, 0x10001, 0xe9c, 0x0, 0x12a, 0x100000000, 0x4, 0xfa86, 0x5, 0x4], [0x0, 0xffffffff, 0x3, 0x8, 0x0, 0x8, 0x3], [0x17f, 0x7, 0x0, 0x6a, 0x2, 0x6], [{0x4, 0x8, 0x80000001}, {0x0, 0x0, 0x0, 0x7}, {0x8000, 0x0, 0x1, 0xf1f4}, {0x8000, 0x40000, 0x1, 0x4169}, {0x1, 0x3, 0x4, 0x80000001}, {0x819f, 0x5, 0xf238, 0xc4e}, {0x3ff, 0x2, 0x400, 0x101}, {0x9, 0x80000000}], {0xffff, 0x40, 0x0, 0x6}, {0x4, 0x80, 0xfffffffd}}}, 0x48b1, 0xe})
sysctl$hw(&(0x7f0000002140)={0x6, 0x16}, 0x2, &(0x7f0000002180)="6e0c48d0078a893846870f0e62f1854a67bf47da6b4e5be20e45bc61d8b9c71b3510b49fbcb13326545e690c7961d09d8631f4c8d73fd99091a31f8a3e8247151e12257447ccd1ae0249b7a2e531d89bb6db1963aad859b7a0d6", &(0x7f0000002200)=0x5a, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000002340)={<r5=>0x0}, 0x0)
fcntl$lock(r4, 0x9, &(0x7f00000023c0)={0x2, 0x1, 0x8, 0x6, r5})
getsockopt$inet_opts(r2, 0x0, 0x0, 0x0, &(0x7f00000024c0))
ioctl$TIOCSTSTAMP(0xffffffffffffffff, 0x8008745a, 0x0)
connect$unix(r4, &(0x7f0000002540)=@file={0x1, './file0\x00'}, 0xa)
ioctl$BIOCSRTIMEOUT(r4, 0x8010426d, &(0x7f0000002580)={0x88, 0x3})
sysctl$hw(&(0x7f00000025c0), 0x2, &(0x7f0000002600)="b7d3e0daa7304f56f4b5bdb9c1fe3d3e868c6e938ec44df8f9b37448ec221cbb89f2a957fe523877047480c5d06b06ac4a983a771c7f1412d7b8f6a6cbbd31d6af47a4a41e29c40132a41a74feaebac7bdde771b98d3d0833a3602d07b21106f4c86c088b1d156c5b1527ec455527e7ffd12db9b5ffcdc95b7ec06d266147a430ad203b717bd38", &(0x7f00000026c0)=0x87, &(0x7f0000002700)="86e19bba8b8e08d1bdff148c3feb06aebf1f6be87a1829f6b01329dec6ac10b18f590750227b8f88dfff782c471ad4e481915e50693b832e742131e3e0f191e16c3c6d46dd75d927ef114ae51fbba4befa223ed1c39a6b737e16314e6e0dc8d5ba0237e29bf2fd5333e4e5cedd1617f3b840b9be1751ab6ba10da9aba7f6e19d84d018ff50ec376aef6e5735246efc22203345c695527e329f2996815d426892e0f067376f32f03c94a5719309edef54d1a4efc9457dbde4327a94d836f739eb7b441b8ac48e96b9f9db474d46a77401dec5033985e1e23491a373900b997addaa3478b691563f1dc61044247cad837e71b602d93148bdb9c5e15c0141a3949a58ad329d8b6a331596b875186e487f53ca8a526ee55ab22b09a92f70811581d8b23582ae17961d01bef5a76eeb777340d2860fcb7b57afed73ebfaa9b238166f7f70d05e93e990e314f7de7d5034a466df816c8d436662d0b0f218ef65bf6c61385d52ef3b726f134e01facf19633b492443097c61703140192b05ab44588b30f0380b6e1051fdf55eab5d089a68d8de8883986fc6526701e904de11912cc6392f1a5b2856ef6dea8b94e0037396614349e6921399a185f83bfbd81fcc4c2929107471f31cc2a030bca58780b332540d4d05fcef6b9f35c7084fd0fc0b0069733e1c4c8fa8186fa7828a9c270554869dfa65bd6b5fe95491563d14b9a5427def841d019b13a8653dcdd7b815f8e86f52cc2e5d79412f895cd997eb1a32e2462e0e914830e501f286fc8ce366735291a2e82281086e9f48ef5884a6f9edafccc6bf528322a617b6abc909a3e6b0849f2ae9c37aa3624b014d1ca728b975bcd42b487b3bf71c4b3820d0c57e58da6c6d2c81a346cd0865691f2678e0c07b2a14caa22b932cf8f1f8103f91574dc6193c0cc24e8974a9947f7217908e3ef92b4a441bf5ca76e49f79561333e9fecd35ebc15b6eeb1fc2c263eb01bce24e113c6c1c4580c92e0597f5b9dd21c9b535e43fe169c9328844c72d413e65502e7794cfd8dd66044ddca20a25356085f56b07228aa683e3e2e2264b0ed1180bf9696de6668e629c2c9d4f25e836c7d11ea794964e9374e64718d08d97b862afef0c31d4ea96e8b92207d8e8823821e531c2a7e325f411cbcd12c83584296f1ceeffee2f3bd661d8125eadbc0eff9da823a7712e3e7dc22bb46a64d07b8d260be58a451ef7d81b60050d9560970592c09601f5109eb69ae92051ce7742c9ff35006e5b44206103515d6426672715cee7cb37ef6be750b2f70f84a7de6cfc3a3b0a85dc88bc7d93ad1d5e39789469f50dde739d9229c587830ddd47702a492b234fbd3a97231fae5e279232d5b2edfb8bfbb24c8690604ffd2b9e36d70fe4e3cd0e0dc114301a753743da42bc8bec9c6eeb974f73585c75d6ca9f43a4f32914711722324152a402ac3ad15011d6a2b11b7f90cbb1304d217535ce234861e40fe69d6ad1bea6c205670209b9014a3d40e36321613e22ef93d724c13d9ff1d2081ef0322b1a224141a173e6816fb70ec5962243858b2aa094cc38fcb33f134c14564d652560b35b7e5d3f5dd0a29d53463b03cdf997eb263595a23597f13a2ff0acf27848231e30fecbce22445474cead65a852fffe2c42e20bc0fcac15bfabbcc8d57b04b62a39d4d49d263a52a8759f20ec8e25077280f7360f685f86943c92af839a48c8dba5007e9f59156840efc883fdbb2b6618c6657c678dfb51fb2bcebc0726c71729bcf47cf51c974716a03c3094274aced77fa3eae1d859b5d41c7bdb6716e1938e4e26ecbb6a199ab72713123e4c0df39dc08f226ffc353b129285002cbcfde8f6b016507bccc4dc2683aec51c81aab22870f58eabc936fb40af8d6f5af7f13a1c88f4e1b3c7cb62d55258fe8af854b5c1a625238399319041d019bf008f29ec1a8c3dc16988229c76da1d32fee2fc74f42742c57610ea685aff03354834a1e42ed3e0589c7a1e1a2a5c14226f995c6d182ffccbdd9757c87de3eb9c6496823ad58d1bf56a6db9bb155c54df6f46aa4233ec65883f02f6b6e0ce8184aa31ad1cdf8de0fd44a5c9f78c26fc28b078abe77e758e21d06dd157324025c8f259ff4bc71b18c3e08df52367ca129af4f691af68dbb303009cfb034350dc46b671b0074b6a2cc0491a50ed1fc9295a4e05a90b5815d134c902db44e3e24a62d079e330124b1fb7b5a2d1e7290e1e81b379428e4846ad41eeb2a4d3c00951bdd3dd96dbcc9da83968ee86c2e8dc1e7906a96a4996925ebe81f76bbe8beac46f20bc39a659c4525ff5d3ab0733f2eb9950cb415a393b0173908dd0838086c1bb9dcfa1a237f98f44ce301234a59ae36657a973c3d3c2aa0419da1a0fed327a05549ab47eaf59d06fb15e070fd6437a0ddfea22acdb695a53f21eadcd0729b3a24595a75d9eb24aa4e510a5940a260a8452a4c9984315238332dc9704267dd3eea1f99cc9187d405d4314c24526dfa5cd1bf1582b8daa26d8c08ca2b5ce2392e815f9acbce83cb051293befa479e371c8d5db78228742a13c29a8a1e429b179acf597ce84b05994708ede6b1c34ab66481dfbdffbf778c78645b0f3cd13f8ca26a77a906b4a3cc2a35e86f9ba74fd3ae5e41dac6e5a6f878a11c2a35ade63b7858fe83cf897bd7e19299a9123e69efd03bc2db0d667e9e6c25b2b0fbd9ab8f318554db4380b4f8b7d405469f6072f4bde3c4881c9132d883a0e052b52e4330a3d5e48e48f4cc7a35ecce53cf062463104fda9507524d47d5409e3ee48e0f0037a9d09d63c39192bc4db14ba23a7255cb284410a9b85e078c0b4d078ff940d5c52b9f388f76b236dc0fd50f6c1603b9f4288fe67b4f814481ef49bdd4029127b0a649d2c2db9a99f91467a48b7112203022fbf3be0a94ec4f05420f1cf72fb681cfa82f857b06840e6e1f2a02d0b25da2a25a07e4dfa3f7a64de5f369e5c597458a21c47a6170f3ca7133bd35b972692be1d3929f847fe40c33f5a8a3d0b5044f0569525f7d98730d0a461b0c22408be068b39f4950e69f2471c04df74063001cd7ca05ec22286a19b642d1339ccb939a69197dcfd7eb9917a2fe427290058ec1ebcd2234e66bc66f02994c8132f02ac10e6c8927b22aa86245538a4c8da26b551c1374fa93977347328b4ea223bcb895346de6310783b8cbc51ac983ba969e0fa8125e44195142547f0c7051d9a7774b3fc2db75cb91627869a1860e3f4db40f4dd3d7d170ec983fa7dfbabb383a3205af5874a079714fc91aff3474fe1c5c44897d61dda92f3f2aa00f9b4fcf67d7fbac0c31b3b6dd3eb73c278f6c6aade147b23c16997ca3b9cbe79a1a55d7d01278f4afa48d5513ee7fc34b6f0a27e290ea7b7c9f51234f85069fe2ffe03207d1919cccfb7ac3a7ac35a794546da749db5b39e59bea5eea3da8026882013206d781ec95b9c553bea0ce74c58fa263196dfe12122032639415cf000289f9c273b3ed13c68417ebeee4678b3ccefa677e7883cf923c12a38a0c4b0bfe75b8a67d72a727f710eb693203a909e377285da2fe4dfa1fa176e6004b8cd10baa39f6af5471d4303eff86e1d4f334c1c19e950a4b4d3fce0bd03245d74f46bd608c22925df3e9d2db2a2ec8b1d8cdd6c438ba4861ebd63cbc38320c2d8d8a66a17ef753e77498aa172a2bb0ab3a77a78f9480953cf39ad49bb865eda93e9c4b83a56024a219d798b7662ab1359915a56e1ce6ff90b8c2c7627027ef0cf2d767c6e02c5812b3d67f3aa9e60f9e8a489f0fe71ff8999149cc42667147a60a54c197352004ec7da531ca7b8e46908b9df5c267c6d94c61b3b1002b3657792202220b3914cc355fc1a4a1a4a257a049b4a8b66abec6b2c9566615f1a05efbfebda638f13af35ed1475eeb8d0932be7e1b59e5c61ba68a4a612dd33313d35bb9ebdb1713e3e13d576767df79527f17ee7b138e4a3f8571403f0665155b4d50e78c8152f48ecfcb59b9b8e5bdfaeab81ca2c109ee2e9df76a075edd7ec1920ff4541c88e7f572eda659cc7dc3cbead7e2a843ea5c1585538f96f6fe307b6e051a46f7f9594c07e06cb6665a5749d86612e01249c2e31423ffedaf7a2842b2f0dd78c050a657290540113777dbe167a827f21bdcc4fc78acac31484ce3c9253a3e89d3eecf5ee7e435ad7b7ff933bffee231e43e01e3114caeb9bbdb471f48128815a85baa37e9423101583e553f14d73c7d712c232bb5a6b0dc6105d4f4275e303ca488f87280685f8641e0e9994c8493831203d04b164e88c6e3493a7746dab0d69d6b2", 0xbe6)
r6 = socket(0x6, 0x5, 0x2)
ioctl$FIONBIO(r6, 0x8004667e, &(0x7f0000003740))
ioctl$WSKBDIO_SETMAP(0xffffffffffffff9c, 0x8010570e, &(0x7f0000003800)={0x8, &(0x7f0000003780)=[{0x1, 0x0, 0x0, 0x0, 0x80}, {0xa74, 0x3, 0x7ff, 0x6, 0xb4}, {0x0, 0x9, 0x9, 0x6, 0x3}, {0x40, 0x2, 0x9, 0x0, 0x7}, {0x2, 0x100, 0x5, 0x6, 0x6}, {0x3, 0x558a, 0x0, 0x7, 0x4}, {0xfeff, 0x40, 0x1, 0xfff, 0x7}, {0x800, 0x3ff, 0x0, 0x9, 0x100}]})
ioctl$VT_RELDISP(r2, 0x20007604, 0x0)
r7 = openat$wsdisplay(0xffffffffffffff9c, &(0x7f0000003880), 0x0, 0x0)
ioctl$VT_GETMODE(r7, 0x40087603, &(0x7f00000038c0))


r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSKBDIO_SETMAP(r0, 0x8010570e, &(0x7f00000000c0)={0x1, &(0x7f0000000040)=[{}]})


mknod(&(0x7f0000000000)='./file0\x00', 0x2100, 0x5f00)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$VMM_IOC_RUN(r0, 0xc0205602, &(0x7f0000000480)={0x0, 0x0, 0x0, 0x0, 0x0})


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000280)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg$unix(r1, &(0x7f0000000ac0)={0x0, 0x0, 0x0}, 0x8)
readv(r0, &(0x7f00000008c0)=[{&(0x7f0000000040)=""/235, 0xeb}], 0x1)


openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
socketpair(0x1, 0x1, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
write(r0, &(0x7f0000000340)="38c344d08db0e1391e89142d173b05d32264bd5fd9f127", 0x17)
r2 = fcntl$dupfd(r1, 0x0, r0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000440)={&(0x7f00000000c0)=@abs={0x0, 0x0, 0x0}, 0x8, 0x0}, 0x0)
writev(r0, &(0x7f00000004c0)=[{&(0x7f0000000180)="18345e5fb8de11ff09622c03d2efee7358836aaeaa580fbed001637148d70ecb143e41c66b43c5c6113b3446679834f4a37b4dc718a61fe3920f135d6f7900cf9393b1ad44a2a3e673ad9ed27e5898ab850da0f0", 0x54}, {&(0x7f0000000280)="41951012587bbe9a05fd7ff77c33d41fd29e6b3c4652c1c1a73768371e78175ec3767bdd91e3", 0x26}], 0x2)
recvmmsg(r2, &(0x7f00000003c0)={0x0}, 0x10, 0x2, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000100)=[{0x44}, {0x45}, {0x6}]})
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCLOCK(0xffffffffffffffff, 0x20004276)
syz_emit_ethernet(0x2a, &(0x7f00000001c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x2, &(0x7f0000000040)=[{}, {0x9d}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
socket(0x18, 0x2, 0x0)
socket$inet(0x2, 0x2, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r1 = socket(0x18, 0x3, 0x3a)
setsockopt(r1, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r1, 0x29, 0x68, 0x0, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x1000, 0xffffffff)
r2 = socket(0x2, 0x2, 0x0)
connect$unix(r2, &(0x7f0000000a80), 0x10)
getsockname$unix(r2, &(0x7f0000000000)=@abs, &(0x7f0000001200)=0x8)
r3 = socket(0x2, 0x1, 0x0)
bind(r3, &(0x7f0000000000), 0x10)
socket(0x6, 0x8000, 0x9)
r4 = dup(r1)
listen(r4, 0x0)
r5 = socket(0x2, 0x1, 0x0)
connect$unix(r5, &(0x7f0000000000), 0x10)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
r6 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(r6, &(0x7f0000001580)=[{&(0x7f00000000c0)='\x00', 0xfffffeb0}], 0x1)


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x4002, 0x0)
dup2(r1, r0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000a, &(0x7f0000000000)="ea00005c00000000", 0x1)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea000001", 0x4)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x6381)
open(0x0, 0x0, 0x0)
ktrace(0x0, 0x0, 0x0, 0xffffffffffffffff)
getrusage(0x0, 0x0)
r0 = openat(0xffffffffffffff9c, 0x0, 0x0, 0x4)
open(&(0x7f0000000040)='./bus\x00', 0x0, 0x0)
unlink(&(0x7f0000000080)='./bus\x00')
kevent(0xffffffffffffffff, &(0x7f0000000100)=[{{r0}, 0xfffffffffffffffe, 0xbf}], 0x0, 0x0, 0x0, 0x0)
kqueue()
setrlimit(0x0, 0x0)
r1 = syz_open_pts()
close(0xffffffffffffffff)
r2 = syz_open_pts()
writev(r1, 0x0, 0x0)
dup2(r1, r2)
readv(r2, &(0x7f0000000400)=[{&(0x7f0000001780)=""/4096, 0x1000}], 0x1)
readv(r2, &(0x7f0000000040)=[{0x0}], 0x1)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_RUN(0xffffffffffffffff, 0xc2485607, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$TIOCSETAF(0xffffffffffffffff, 0x802c7416, 0x0)
syz_emit_ethernet(0x2e, 0x0)
openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)


sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x6381)
r0 = open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
poll(&(0x7f00000000c0)=[{r0, 0x6e}], 0x1, 0x0)
close(r0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
syz_emit_ethernet(0x3e, 0x0)
msgsnd(0x0, 0x0, 0x401, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
mknod(0x0, 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000001c0)=[{0x60}, {0x5}, {0x106}]})
syz_emit_ethernet(0x36, &(0x7f0000000200)=ANY=[])


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000280)="b1000503000004000000000003000000331c13fecea10500fef96ec0c72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b1257aea8c500002002fbfe0c2300008abfba0900000008e371a3f8343712051eeab71d89e00004070000000013000000", 0xb1, 0x8, 0x0, 0x0)
recvmsg(r0, &(0x7f0000000380)={0x0, 0x0, &(0x7f0000000100)=[{&(0x7f0000000180)=""/204, 0xcc}], 0x1, 0x0}, 0x8c2)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0, 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$BIOCSRTIMEOUT(r0, 0x8010426d, &(0x7f0000000040))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000340)={0x1, &(0x7f0000000240)=[{0x48, 0x0, 0x0, 0xfffffffd}]})


open$dir(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000080)='./file0\x00', 0x0, 0x40000530, r0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
sendmmsg(r2, &(0x7f0000000000)={0x0}, 0xfffffe32, 0x0)
recvmsg(r1, &(0x7f0000000100)={0x0, 0x0, &(0x7f0000000080)=[{&(0x7f0000000180)=""/236}], 0x100000000000039d, 0x0, 0x28}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f00000000c0)=[{0x4c}, {0x40}, {0x8006}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000080)=[{0x15}, {0xc}, {0x8106}]})
syz_emit_ethernet(0x2a, &(0x7f0000000300)=ANY=[])


sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000513fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f", 0x43, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0xb, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000080)={0xf669, 0x0, 0x7d, 0x5577c513, "3c00000000000000000600060000ea02f1ac7e00"})
writev(r0, &(0x7f00000004c0)=[{&(0x7f00000000c0)="bf0909b98732e43ae0ee63c33dd9cb7de67102649ec14a5cde", 0x19}], 0x1)


socketpair$unix(0x1, 0x1, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
dup(0xffffffffffffffff)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000240)={0x3, &(0x7f00000000c0)=[{}, {0x1, 0x0, 0x0, 0x2}, {0x2}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0xff0a, 0x0, 0x37)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000200)=[{0x50}, {0xc}, {0x406}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000000)=[{0xc0}, {0x24}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000002c0)={0x3, &(0x7f0000000400)=[{0x5}, {0x6c}, {0x6, 0x0, 0x0, 0xe00004}]})
writev(r0, &(0x7f0000000600)=[{&(0x7f0000000100)="ba2128", 0x3}, {&(0x7f0000000300)="7a9f30a344ddd8175e00c5", 0xb}], 0x2)


getsockopt$sock_cred(0xffffffffffffff9c, 0xffff, 0x1022, 0x0, &(0x7f0000000180))
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0x0, 0x0, 0xffffffffffffffff, 0x0, 0xd0, 0x3}, 0x7fffffffffffffff})
r0 = socket(0x2, 0x2, 0x0)
getppid()
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000000), &(0x7f0000000040)=0xc)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000080), &(0x7f00000000c0)=0xc)
sysctl$hw(&(0x7f0000000000)={0x6, 0x6}, 0x2, &(0x7f0000000040), 0x0, 0x0, 0x0)
r1 = msgget$private(0x0, 0x282)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000080)={<r2=>0xffffffffffffffff})
getsockopt$sock_int(r2, 0xffff, 0x8, &(0x7f0000000400), &(0x7f0000000440)=0x4)
msgrcv(r1, 0x0, 0x0, 0x1, 0x0)
msgsnd(r1, &(0x7f0000000d00)=ANY=[@ANYRESHEX], 0x401, 0x0)
r3 = socket(0x2, 0x3, 0x0)
getsockopt(r3, 0x0, 0x64, 0x0, 0x0)
mlock(&(0x7f0000800000/0x800000)=nil, 0x800000)
minherit(&(0x7f0000ffd000/0x1000)=nil, 0x1000, 0x0)
munmap(&(0x7f0000ffa000/0x4000)=nil, 0x4000)
getsockopt(0xffffffffffffffff, 0x9, 0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x80, 0x0)
syz_emit_ethernet(0xe, &(0x7f0000000040)=ANY=[])
close(0xffffffffffffffff)
r4 = socket$unix(0x1, 0x5, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x1, &(0x7f0000000040), 0x1)
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x4ebfac6bbaf7959)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
r5 = socket(0x18, 0x2, 0x0)
r6 = socket(0x18, 0x2, 0x0)
dup2(r5, r6)


setreuid(0xee00, 0x0)
r0 = syz_open_pts()
fchflags(r0, 0x0)


socket(0x0, 0x0, 0x0)
kqueue()
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
semop(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{}, {0x9}, {0xf7ff}]})
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


mknod(&(0x7f0000000500)='./file0\x00', 0x1000, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000001c0)=[{}, {}, {0x6, 0x9}]})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
sendto$inet(0xffffffffffffffff, &(0x7f00000000c0)="6c25a03ae7b27b4e7fc0924a22334b9b619f09f993c214bf34de94ee6f878793a443c48892901b940ff2189ae976bd635aa66dd55818d1ca20a7f88c2ad799df41ea701f32e36ab928f0ea3b00ddc5613e3590c04b342a5ec356d4f406e612653d7338e1b59ec0f00de4b65b3f18", 0x6e, 0xab7930ffa8ff6f6d, 0x0, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r2, 0x8080691a, &(0x7f0000000100))
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r3 = socket(0x1, 0x2, 0x0)
r4 = openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSRTIMEOUT(r4, 0x8010426d, &(0x7f0000000140)={0xffffffffffffffff, 0x2})
ioctl$FIONREAD(r3, 0x8020691f, &(0x7f00000001c0))
socket(0x6, 0x2, 0x1f)
r5 = dup2(r0, r0)
ioctl$FIONREAD(r5, 0x8020699d, &(0x7f00000001c0))


r0 = socket$inet(0x2, 0x8003, 0x0)
setsockopt(r0, 0x0, 0x7, &(0x7f0000000340)="15337ac0", 0x4)
syz_emit_ethernet(0x2a, &(0x7f0000000040)={@broadcast, @broadcast, [], {@arp={0x8035, @ether_ipv4={0x1, 0x800, 0x6, 0x4, 0x0, @empty, @empty, @broadcast, @remote={0xac, 0x14, 0x0}}}}})
syz_emit_ethernet(0x2a, &(0x7f00000002c0)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, @multicast2}, @icmp=@echo}}}})
recvmmsg(r0, &(0x7f0000000040)={0x0}, 0x10, 0x0, 0x0)


r0 = open(&(0x7f0000000140)='./file0\x00', 0x78e, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, r0, 0x0)
utimensat(0xffffffffffffffff, 0x0, &(0x7f0000000100), 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
connect$unix(0xffffffffffffffff, &(0x7f0000000000), 0x1)
r1 = socket(0x2, 0x3, 0x0)
connect$unix(r1, &(0x7f0000000280)=@abs={0x1, 0x0, 0x3}, 0x8)
bind(r1, &(0x7f0000000000), 0x10)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{0x30}, {0x7c}, {0x16}]})
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f0000000080)=ANY=[])
r3 = semget$private(0x0, 0x4000000009, 0x28c)
semop(r3, &(0x7f00000000c0)=[{0x1, 0xffff, 0xe5ce97ab354d96be}, {0x4, 0x4, 0x1800}, {0x3, 0x0, 0x1000}, {0x2, 0x6}], 0x4)
open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETF(r4, 0x80104267, &(0x7f0000000140)={0x2, &(0x7f0000000100)=[{0x3d, 0x0, 0xff}, {}]})
r5 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r5)
connect$unix(r1, &(0x7f0000000300)=@abs={0x1, 0x0, 0x2}, 0x8)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000380)={0x0, 0x0, &(0x7f0000000840)=[{0x0}, {0x0}], 0x2, 0x0, 0x0, 0x400}, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000200)={0xffffffffffffffff, <r6=>0xffffffffffffffff})
sendmmsg(r6, &(0x7f0000000240)={0x0}, 0x10, 0x0)
semctl$SETALL(r3, 0x0, 0x9, &(0x7f0000000040)=[0x0, 0x1000])
semop(r3, &(0x7f0000000180)=[{0x1, 0x1, 0x1800}, {0x2, 0x4, 0x1000}], 0x2)
r7 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r7, 0x80105728, &(0x7f0000000100)={&(0x7f00000000c0)=[{0x24, 0x7ff}], 0x1})
semctl$SETALL(r3, 0x0, 0x9, &(0x7f0000000240)=[0x7, 0x4, 0x7])
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000380)={{0x9, 0x0, 0x0, 0x0, 0x0, 0x100, 0x5}, 0x2f8, 0xffffffffffffffff, 0x7})


setrlimit(0x8, &(0x7f0000000100)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f00000000c0)={0x0, 0x0, 0x8a38, 0x0, "ffff09009cef01098b748200", 0x0, 0x2})


r0 = kqueue()
kevent(r0, &(0x7f0000000000)=[{{r0}, 0xfffffffffffffff9, 0xcb}, {{r0}, 0xfffffffffffffff9}, {{r0}, 0xfffffffffffffff9, 0x2}], 0x89e4, 0x0, 0xfffffffb, 0x0)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10})
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
r2 = socket(0x11, 0x3, 0x0)
r3 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x100, r3)
ioctl$VNDIOCSET(r1, 0xc0384600, &(0x7f0000000600)={&(0x7f0000000500)='./file\x00', 0x276, &(0x7f0000000540)='./file0/file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x81})
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r4 = openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r5 = getpid()
ktrace(&(0x7f0000000140)='./file0\x00', 0x4, 0x1424, r5)
fcntl$lock(r4, 0x8, &(0x7f0000000640)={0x3, 0x2, 0x8, 0x401, r5})
ioctl$FIOASYNC(0xffffffffffffffff, 0x8004667d, 0x0)
ioctl$VNDIOCCLR(r0, 0x80384601, &(0x7f0000000b80)={0x0, 0x0, 0x0})
ioctl$VMM_IOC_RUN(0xffffffffffffffff, 0xc0205602, 0x0)
mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f0000000100)={&(0x7f0000000080)='./file0\x00', 0xf3cf, 0x0})
openat$vnd(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sendmsg$unix(r2, &(0x7f0000001300)={0x0, 0x9, &(0x7f0000001100)=[{0x0}], 0x1, &(0x7f0000001200)=[@rights={0x28, 0xffff, 0x1, [0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff]}, @cred={0x20}, @cred={0x20}, @rights={0x20, 0xffff, 0x1, [0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff]}, @rights={0x28, 0xffff, 0x1, [0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff]}], 0xb0}, 0x0)


semctl$GETZCNT(0x0, 0x0, 0x7, &(0x7f0000000280)=""/141)
socket(0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
msgget$private(0x0, 0x0)
syz_emit_ethernet(0xf9, &(0x7f00000003c0)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaaaabb86dd6000000000c3000000000000000000000000000000000000ff0200000000000000000000000000013c01000000000000000100c2"])
accept$unix(0xffffffffffffffff, &(0x7f0000000140)=@file={0x0, ""/264}, &(0x7f0000000040)=0x10a)
openat$null(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
rename(&(0x7f0000000080)='./file0\x00', &(0x7f00000000c0)='./file0\x00')
mkdir(&(0x7f0000000080)='./file0\x00', 0x0)


mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0xc0e99db6de761f86, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
setrlimit(0x0, &(0x7f0000000980))
syz_open_pts()
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
socket(0x11, 0x3, 0x0)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
chdir(&(0x7f0000000240)='./file0\x00')
mkdir(&(0x7f00000001c0)='./file1\x00', 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000540)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000140)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000080)=0xc)
chown(&(0x7f0000000040)='./file1\x00', 0x0, r1)
setreuid(0x0, 0xee01)
mkdir(&(0x7f0000000100)='./file0\x00', 0x184)
rename(&(0x7f00000003c0)='./file0\x00', &(0x7f0000000400)='./file1\x00')


open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r0 = socket(0x2, 0x1, 0x0)
r1 = dup(r0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
r3 = socket(0x2, 0x4001, 0x0)
r4 = dup(r3)
r5 = fcntl$dupfd(r4, 0x2, 0xffffffffffffffff)
close(r5)
r6 = socket(0x2, 0x2, 0x0)
connect$inet(r6, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r5, 0xffff, 0x1023, &(0x7f0000000040), 0x4)
shutdown(r2, 0x1)
select(0x40, &(0x7f0000000000), 0x0, 0x0, 0x0)


pwritev(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f00000005c0)="dc", 0x1}], 0x1, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x31}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)


writev(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x3e, &(0x7f0000000040)={@local, @broadcast, [], {@ipv6={0x86dd, {0x0, 0x6, "6aa63f", 0x8, 0x2b, 0x0, @remote={0xfe, 0x80, '\x00', 0x0}, @loopback={0x4}, {[@dstopts={0x3c}]}}}}})
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000240)={0x0, 0x2000000001})
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
r1 = socket$inet(0x2, 0x2, 0x0)
dup2(r0, r1)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000200)="ea00000000000000", 0x8)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000240)="ea02000000000000", 0x8)


r0 = socket(0x2, 0x1, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000180)=[{&(0x7f0000000000)="9da8e3e9ed", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r0, &(0x7f0000000000), 0x10)


sysctl$net_inet_esp(&(0x7f0000000000)={0x4, 0x2, 0x2, 0x2}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0xa}, 0x7, &(0x7f0000000080), 0x0, 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
ioctl$TIOCCONS(r0, 0x80047462, &(0x7f0000000080))


r0 = socket$unix(0x1, 0x1, 0x0)
syz_emit_ethernet(0x3e, &(0x7f0000000000)=ANY=[@ANYBLOB="aaaaaaaaaabb"])
ioctl$FIONREAD(r0, 0x80206979, &(0x7f0000000000))


madvise(&(0x7f0000000000/0x4000)=nil, 0x0, 0x6)


write(0xffffffffffffffff, &(0x7f0000000200), 0x0)
mknod(&(0x7f00000000c0)='./file0\x00', 0x2000, 0x40000802)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSETD(0xffffffffffffffff, 0x8004741b, &(0x7f0000000080))
close(r0)


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
openat$pf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
getpid()
ktrace(0x0, 0x0, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
getuid()
socketpair$unix(0x1, 0x0, 0x0, 0x0)
getsockopt(r0, 0x0, 0x9, 0x0, 0x0)


sysctl$net_pipex(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = open(&(0x7f0000000280)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000028000/0x4000)=nil, 0x4000, 0x0, 0x10, r0, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
mkdirat(0xffffffffffffffff, &(0x7f0000000340)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38/\x00', 0x0)
mkdirat(0xffffffffffffffff, &(0x7f0000000000)='./file0\x00', 0x0)
mkdirat(0xffffffffffffffff, &(0x7f0000000440)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//file0\x00', 0x0)
r1 = open(&(0x7f0000000040)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//../file0\x00', 0x0, 0x0)
r2 = fcntl$dupfd(r1, 0x0, 0xffffffffffffffff)
renameat(r2, 0x0, 0xffffffffffffffff, 0x0)
rename(&(0x7f0000000540)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//../file0\x00', &(0x7f00000005c0)='./file0/file0\x00')
rename(&(0x7f0000000100)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//file0\x00', &(0x7f0000000180)='./file0\x00')
recvmsg(r1, &(0x7f0000000a00)={&(0x7f0000000b40), 0xff, &(0x7f0000000940)=[{&(0x7f00000001c0)=""/114, 0x72}, {&(0x7f0000000640)=""/202, 0xca}, {&(0x7f00000003c0)=""/76, 0x4c}, {&(0x7f0000000740)=""/88, 0x58}, {&(0x7f00000000c0)=""/20, 0x14}, {&(0x7f00000002c0)=""/48, 0x30}, {&(0x7f00000007c0)=""/145, 0x91}, {&(0x7f0000000880)=""/181, 0xb5}], 0x8, &(0x7f00000009c0)=""/8, 0x8}, 0x40)
openat(r1, &(0x7f0000000240)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38/\x00', 0x200, 0xd2)
r3 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
pwritev(r3, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x40, 0x0)
ftruncate(0xffffffffffffffff, 0x80002)
r4 = open$dir(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
preadv(r4, &(0x7f00000012c0)=[{&(0x7f00000001c0)=""/224, 0xfffffdd5}], 0x1, 0x0)


open$dir(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
r0 = getpid()
r1 = getppid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r1})
setpgid(0x0, 0x0)
setpgid(0x0, r1)
pipe(&(0x7f00000001c0)={<r2=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r2, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r3 = fcntl$getown(r2, 0x5)
setreuid(0xee00, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0xb32, r0)
setreuid(0x0, 0x0)
ktrace(&(0x7f0000000140)='./file0\x00', 0x4, 0x1808, r3)


r0 = kqueue()
mknodat(0xffffffffffffff9c, &(0x7f0000000100)='./file0\x00', 0x1000, 0x0)
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
dup2(r1, r0)
r2 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$DIOCMAP(r2, 0xc0106477, &(0x7f0000000200)={&(0x7f00000002c0)='./file0\x00', r1})
close(r1)
acct(&(0x7f0000000140)='./file0\x00')


setrlimit(0x8, &(0x7f0000000040)={0x7, 0x200004})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
r1 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7817)
writev(r1, &(0x7f00000006c0)=[{&(0x7f0000000280)='#!', 0x2}], 0x1)
write(r1, &(0x7f0000000040)="ac9e8912f67a663f57d04797092009e3ffffff5c2a591c97413fb5df308cbbae80e4ffca2eb764174b53ffec3d63876a0a", 0x31)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000500)={0x0, 0x0, &(0x7f0000000480)=[{&(0x7f0000000380)='s', 0x1}], 0x100000000000038b}, 0x1)
r0 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmat(r0, &(0x7f0000001000/0x3000)=nil, 0x0)
r1 = shmget$private(0x0, 0x4000, 0x0, &(0x7f0000001000/0x4000)=nil)
shmctl$IPC_STAT(r1, 0x2, &(0x7f0000002540)=""/4093)
madvise(&(0x7f0000001000/0x2000)=nil, 0x2000, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f0000000500)={0x0}, 0x10, 0x0, 0x0)


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r0 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000001000/0x3000)=nil)
shmat(r0, &(0x7f0000001000/0x2000)=nil, 0x0)
writev(0xffffffffffffffff, &(0x7f00000026c0)=[{0x0}], 0x1)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x4)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
writev(r0, &(0x7f00000001c0)=[{&(0x7f0000000200)="96e9cf1c159fc25ac05e6f4c", 0xc}, {&(0x7f0000000400)="80212b33d5bf044a8118234e8f6c72a6545b37055b678d659ed0c420cf608c089d546b4fd2b7582e04ba40e635c1c0925eb10dbf253e19df0b316685bc2a9ba5efc705e867720ad2e7fd1d5d106cd267f12476e33cd526195deda57e5b795f29c98daf7f3573c3c0a6fe2c366033e9137846efcec42c4ec10c54a8d918d237a6966c3cc9cc2ba1beaabf951557a830ec3be80d4a570588f4e31b7ec4504c802c11d74aa53a444b8edbbe87c17494935daef64522e4603f2c100687bfde9225c526fee4b4e491114e76dbd9e85459c6d624158047e545146024e1f73552e71d5cc4b8280235562a9d06a6b19344844f30e6e00730c8bf9709ebc56d994695824dc7203786837b37fb4898668f56253406aee25c941164b9971a06edd70dbf92004b04a191ddeace8abcdac1efdeafac7251598357d41506472f2e32c2228cc6fdc35d31530f7a38aafb789a9cbec73c37434a99589b110be20994ae179f51ae9d52045cbcf6667d0000000000000000000000e8c9f75eb018ca4fb09d2c6a5042d888d7f4822ee3c62f088f63", 0x18c}], 0x2)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
execve(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000002c0)={0x3, &(0x7f0000000400)=[{0x5c}, {0x6c}, {0x6, 0x0, 0x0, 0xe00000}]})
writev(r0, &(0x7f0000000600)=[{&(0x7f0000000100)="ba2128", 0x3}, {&(0x7f0000000300)="7a9f30a344ddd8175e00c5", 0xb}], 0x2)


r0 = kqueue()
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000300)=[{{}, 0xfffffffffffffff9, 0x41, 0x3, 0xffffffff00000000}], 0x0, 0x0)
kevent(r0, &(0x7f0000000140), 0xe4a, 0x0, 0xa9fa, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000140)=[{0x80}, {0xc0}, {0x4006}]})
syz_emit_ethernet(0x2a, &(0x7f00000000c0)=ANY=[])


open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
open(&(0x7f0000000100)='./file0\x00', 0x615, 0x0)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x1000300010008})


kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0206923, &(0x7f00000001c0))
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x8020690e, &(0x7f00000001c0))


r0 = socket(0x800000018, 0x2, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892}, 0x1c)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg(0xffffffffffffffff, 0x0, 0x0)
close(0xffffffffffffffff)
mmap(&(0x7f0000000000/0x4000)=nil, 0x4000, 0x1, 0x9412, 0xffffffffffffffff, 0x0)
clock_settime(0xffffffffffffffff, &(0x7f0000000140))
socket(0x2, 0x1, 0x0)
dup(0xffffffffffffffff)
listen(0xffffffffffffffff, 0x0)
socket(0x0, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
getsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x10, &(0x7f0000000000), &(0x7f0000000080)=0xca555f06cd31e785)
r2 = msgget$private(0x0, 0x2)
msgrcv(r2, 0x0, 0x0, 0x0, 0x1000)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000000)={<r3=>0x0}, &(0x7f0000000040)=0xc)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000080)={<r4=>0x0}, &(0x7f00000000c0)=0xc)
getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x1c00, r4)
msgctl$IPC_SET(r2, 0x1, &(0x7f0000000180)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x40}, 0x0, 0x0, r3, r3, 0x4, 0xfc9, 0x3, 0x3ff})
msgctl$IPC_STAT(r2, 0x2, &(0x7f0000000240)=""/56)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
sendmsg(0xffffffffffffffff, 0x0, 0x0)
nanosleep(0xffffffffffffffff, 0x0)
bind$unix(r1, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f00000000c0)={0x4, 0x2, 0x0, 0xe}, 0x4, 0x0, 0x0, 0x0, 0x0)


open(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{}, {0x7, 0x7f, 0xfd}, {0xfffe, 0xfd}]})
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000380)=[{0x40, 0xfc}, {0x7c, 0x0, 0x2}, {0x6}]})
ioctl$BIOCVERSION(r0, 0x40044271, &(0x7f0000000080))
syz_emit_ethernet(0x3e, &(0x7f0000000080)=ANY=[])
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140))
setrlimit(0x8, &(0x7f0000000980)={0x42})
r1 = syz_open_pts()
getrlimit(0x0, 0x0)
close(0xffffffffffffffff)
ioctl$TIOCSPGRP(r1, 0x40047477, &(0x7f0000000180))
r2 = syz_open_pts()
ioctl$TIOCSETAW(r2, 0x802c7415, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x6be, "28113bb1e6648a1a267bc03b7a447ab255dcd9f0", 0xfffffffe})
readv(0xffffffffffffffff, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
ktrace(&(0x7f00000001c0)='./file0\x00', 0x4, 0xd27d43220c7cd9f, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r3 = socket(0x18, 0x1, 0x0)
r4 = socket(0x18, 0x1, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x1, &(0x7f0000001240)=0x6, 0x4)
r5 = socket(0x18, 0x3, 0x0)
ioctl$FIONBIO(r4, 0x8004667e, &(0x7f0000000080)=0x1)
connect$unix(r5, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r5, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r0, &(0x7f0000000180)=[{&(0x7f0000000280)="14cac7f0eccd95c9e2f88b57e0226fc7a6778cff51fddf183edac0e7484a0fcc541976e3f92dd7af64a2c1e30b06129f992e8086abdc19940a428ab80a1684dd36797b249c416e6d1f11b7f8af0a34fddf5a1665ec40ebfbd551bb9abf2f69b201f87106353c6cf25988b135a124988d0a00", 0x72}], 0x1)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0xffffdffc, 0xffffffbb, "ffff090000001400000000006a00"})
close(r0)
poll(&(0x7f0000000240)=[{r1, 0x68}], 0x1, 0x0)


writev(0xffffffffffffffff, 0x0, 0x0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)
poll(&(0x7f0000000380)=[{}], 0x1, 0xffff)
r0 = socket(0x1, 0x1, 0x0)
r1 = dup2(r0, r0)
mknod(&(0x7f0000000000)='./file0\x00', 0x1ffa, 0x0)
r2 = open(&(0x7f00000001c0)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000180)='./file0\x00', 0x40, 0x103)
ioctl$VNDIOCSET(r2, 0xc0387200, &(0x7f0000000340)={0x0, 0x0, 0x0})
r3 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r3)
r4 = msgget$private(0x0, 0x0)
pipe2(&(0x7f0000000000), 0x0)
msgctl$IPC_RMID(r4, 0x8000000)


sysctl$net_inet_tcp(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047470, &(0x7f0000000280)=0x5)
readv(r0, &(0x7f0000000200)=[{&(0x7f0000000100)=""/185, 0xb9}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
write(r0, &(0x7f0000000000)='E', 0xfffffc36)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000132000/0x3000)=nil, &(0x7f00001bf000/0x3000)=nil, 0xc0400000}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f0000001000/0x2000)=nil, &(0x7f0000093000/0x1000)=nil}, {&(0x7f0000334000/0x1000)=nil, &(0x7f000008a000/0x3000)=nil}, {&(0x7f0000066000/0x1000)=nil, &(0x7f0000133000/0x1000)=nil}, {&(0x7f000008a000/0x4000)=nil, &(0x7f000013e000/0x2000)=nil}, {&(0x7f0000323000/0x4000)=nil, &(0x7f000002a000/0x3000)=nil}, {&(0x7f000008d000/0x4000)=nil, &(0x7f0000089000/0x4000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000027000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffa000/0x4000)=nil}, {0x0, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000249000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000100000/0x5000)=nil, &(0x7f0000092000/0x3000)=nil}], './file0\x00'})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000800), 0x0, 0x0)
r1 = syz_open_pts()
ioctl$TIOCCONS(r1, 0x80047462, &(0x7f0000000240)=0xc)
syz_open_pts()
ioctl$VMM_IOC_RUN(r0, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0})


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x25, &(0x7f0000000000)="5ab7776a", 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000240)=[{0x5}, {0x1d}, {0x6}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x101, 0x200}, 0x400})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, 0x0, 0x0)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0)=@file={0x1}, 0x2, 0x0, 0x0, 0x0, 0x0, 0x1}, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000040), 0x800, 0x0)
ioctl$VMM_IOC_INFO(r1, 0xc0185603, &(0x7f0000000080)={0xb4, 0x0, &(0x7f0000000140)=""/180})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x18, 0x400000002, 0x0)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r3 = socket(0x18, 0x1, 0x0)
r4 = dup2(r2, r3)
sendmsg$unix(r4, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x404)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
setuid(0xffffffffffffffff)
mkdir(0x0, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
recvmsg(0xffffffffffffffff, 0x0, 0x0)
sendmsg(0xffffffffffffffff, 0x0, 0x0)
recvfrom(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
unveil(&(0x7f0000000000)='./file0\x00', &(0x7f00000001c0)='r\x00')
unveil(&(0x7f0000000080)='./file0/file1\x00', 0x0)
unveil(&(0x7f0000000200)='./file0/file1\x00', &(0x7f0000000280)='x\x00')
ioctl$BIOCLOCK(r0, 0x20004276)
seteuid(0x0)
ioctl$BIOCGDLTLIST(r0, 0xc010427b, &(0x7f0000000180)={0x0, &(0x7f0000000140)})


r0 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
close(r0)
socket$unix(0x1, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000040)={0x0, 0x0, <r3=>0x0}, &(0x7f0000000080)=0xc)
chown(&(0x7f0000000280)='./file0\x00', 0x0, r3)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
setreuid(0x0, 0xee01)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000100), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105727, &(0x7f0000000380)={&(0x7f00000002c0)=[{0x88}], 0x1})


setitimer(0x1, &(0x7f0000000200)={{}, {0x0, 0x86ac}}, 0x0)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x19})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000100)='\x00\x00\x00\x00', 0x4)
r1 = socket(0x2, 0x3, 0x0)
dup2(r0, r1)
setsockopt(r1, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff1ab9fd8193aa46713048e6993192b248", 0x14)


sendto$unix(0xffffffffffffffff, &(0x7f0000000140)="b1000504000004000000000007000000331c13fecea10500fef96ec0c72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a421020000ed710fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b1257aea8c500002002fbfe0c2300008abf", 0x92, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000500)='./file0\x00', 0x1000, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = dup2(r0, r0)
ioctl$FIONREAD(r1, 0x8020699d, &(0x7f00000001c0))


seteuid(0xffffffffffffffff)
r0 = syz_open_pts()
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000100)=0x9)


symlink(&(0x7f0000000100)='./file0\x00', &(0x7f0000000140)='./file0\x00')
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
read(0xffffffffffffffff, &(0x7f0000000540)=""/226, 0xe2)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x1, 0x2, 0x0)
r1 = socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0xb, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
getpeername$unix(r0, &(0x7f0000000c40)=@file={0x0, ""/4089}, &(0x7f0000000200)=0xffb)
r2 = socket(0x6, 0x18006, 0x0)
dup2(r1, r2)
syz_open_pts()
syz_open_pts()
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f00000000c0)={0x0, 0x1ff}, 0x10)
socket(0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000040), 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$VNDIOCCLR(0xffffffffffffffff, 0x80384601, &(0x7f00000004c0)={&(0x7f0000000180)='./file0\x00', 0x6, &(0x7f0000000380)='./file1\x00', 0x8})
ioctl$TIOCOUTQ(0xffffffffffffffff, 0x40047473, 0x0)
syz_open_pts()
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x1, 0x0)
r3 = socket(0x11, 0x3, 0x0)
sendto$unix(r3, &(0x7f0000000000)="b10005016000009f05000000070000007d9113fecea10500fef96ecfc72fd3357a068da3a5673039d2d236acf20b7804be38164991f7cccf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f45335c223e7d026ba8af630037282118000000720fd38bfbb770c1f5a872c881e2772ec5a10400000000000000361b1257aea8c5d0002012fbff0c230000880d6633c556ae9be371a3f8343712051eeab71d89000407000000800420000000", 0xb1, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{0x34, 0x0, 0x0, 0x20000000}, {0x3}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000100)=ANY=[])


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
sendto(0xffffffffffffffff, 0x0, 0xfffffffffffffce0, 0x0, &(0x7f0000000080)=@in6={0x18, 0x3, 0x0, 0x1ff}, 0xc)
r0 = socket(0x800000018, 0x1, 0x0)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892}, 0x1c)
setsockopt$sock_int(r0, 0xffff, 0x1, &(0x7f0000000100)=0x4, 0x4)
getsockname(r0, 0x0, &(0x7f0000000040))
r1 = socket$unix(0x1, 0x5, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1005, &(0x7f0000000000), 0x4)
close(0xffffffffffffffff)
syz_open_pts()
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f00000006c0)={0x0, 0x20, 0x0, 0xfffffff7, "ffff0d000300ef01018b00690200000000000400"})
mprotect(&(0x7f0000bdc000/0x1000)=nil, 0x1000, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x20530c)
writev(0xffffffffffffffff, &(0x7f0000000880)=[{&(0x7f00000001c0)="44ac", 0x2}], 0x1)
poll(0x0, 0x0, 0xffffffff)
execve(0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x3e, &(0x7f0000000100)={@local, @remote, [], {@ipv4={0x800, {{0xa, 0x4, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @multicast2, {[@noop, @timestamp={0x44, 0x10, 0x7, 0x3, 0x0, [{}, {}, {}]}]}}, @udp={{0x1, 0x3, 0x8}}}}}})


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
open(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f0000000000)={&(0x7f00000000c0)='./file0\x00', 0xc9, 0x0})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000280)={0x3, &(0x7f0000000240)=[{0x4d}, {0x7}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000240)=ANY=[])


r0 = open(&(0x7f0000000100)='./file0\x00', 0x615, 0x0)
fcntl$setstatus(r0, 0x4, 0x0)


mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x0)
open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)
mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x205b9a)
open(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
select(0x40, &(0x7f0000000100), 0x0, &(0x7f0000000200)={0xffffffffffffffd3}, 0x0)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f00000000c0)="b100051300000000000000402020000000000000cea10500fef96ecf2ac72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf7f882b297be1aa0540000051e2f0ad3ebbc257699a1f139b672f335c223e7d0c032b0c8a6443a42118000000720fd38bfbb770c1f5a872c88106002ec589040000000c000000361b1257aea8c500002002fbfe0c2300008abfba0900afb7515871a3f8343712051eeab7196fcbd80407000000c011200000", 0xb1, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000002c0)=[{0x60}, {0x45}, {0x836}]})
syz_emit_ethernet(0x36, &(0x7f00000001c0)=ANY=[])


r0 = open(&(0x7f0000000080)='./file0\x00', 0x70e, 0x0)
writev(r0, &(0x7f0000000280)=[{&(0x7f0000000400)="56cf5daafc6597872431ff6c668c28adc33a60651a078a116b3548a8be66444658a069b71e92feadcd7b3434dadfc4fc3fd4ef7525b58b0086932b0a93463511a8889f58073c33282b2afa1967c7908d4d0aea830b68a43711d6c4457ec4a41a772d6ae311730b7823d96ef1c25a7bae68954da1ffde05cf138758ef54d053a94bce1d28f7ea235a66647b6db6eda0d5e78db16b66fae3f13f", 0x99}], 0x1)
r1 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x3, 0x10, r1, 0x0)
pipe(&(0x7f00000000c0)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
ioctl$FIOASYNC(r2, 0x8004667d, &(0x7f0000000140)=0x400)
poll(&(0x7f0000000000)=[{r2}], 0x1, 0x0)
dup2(r2, r3)
read(r3, 0x0, 0x0)
sendto(0xffffffffffffffff, 0x0, 0x0, 0x0, &(0x7f0000000080)=@in6={0x18, 0x3, 0x0, 0x1001ff}, 0xc)
r4 = socket(0x800000018, 0x1, 0x0)
bind$unix(r4, &(0x7f0000000080)=@abs={0x1f95d27d48731892}, 0x1c)


sysctl$vm_swapencrypt(&(0x7f0000000000)={0x6, 0xb}, 0x3, &(0x7f0000000040), 0x0, 0x0, 0x0)


symlink(&(0x7f0000001340)='./file0\x00', &(0x7f0000001440)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
kqueue()
dup(0xffffffffffffffff)
syz_extract_tcp_res$synack(&(0x7f0000000100), 0x1, 0x0)
getpgrp()
shmctl$IPC_SET(0xffffffffffffffff, 0x1, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000140)=[{0x74}, {0x5c}, {0x812e}]})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000200)={0x9, &(0x7f00000000c0)=[{0x9dab, 0x40}, {0x5, 0x3e, 0x0, 0x100}, {0x2, 0x6, 0x2, 0xaa}, {0x1f, 0x40, 0x0, 0x8}, {0x800, 0x0, 0x9, 0x7}, {0x101, 0x1f, 0x3f, 0xff}, {0x4, 0x6, 0xfc}, {0x7, 0x1, 0x9, 0x2}, {0xac9, 0x4, 0x61}]})
r2 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r2, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
ioctl$FIONREAD(r2, 0xc0207534, &(0x7f0000000440))
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x2, &(0x7f00000004c0)=[{0x30}, {0x44}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])
syz_extract_tcp_res$synack(&(0x7f0000000040), 0x1, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x7, 0x0, 0x80000001, 0x0)
r3 = kqueue()
kqueue()
kevent(r3, 0x0, 0x0, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, &(0x7f00000002c0), 0x7, 0x0, 0x80000001, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x47}, 0x4000000000000003, 0x0, 0x0, &(0x7f0000000140)="d820866700020000b876a16034c1f4e27679b78aecf8a8ded96987544ca9c5475e8a9fe042140900006f6aff03b422cb01e30ee863a9000500eb1400800000fb000000000000000000008000f63a5caa8932e5fce76307dc71a0047172d8674225a1bf069049f83479ecbed5934c12b1873d92d95753961367aab6b249a70fdff70bb6b8329cd2900a0a73ddd2adce6ad0e46d29a0fc7e238b92171971199fa988", 0x60)
kqueue()
kevent(r3, 0x0, 0x0, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000280)=[{0x84}, {0x35}, {0x812e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])


open(&(0x7f0000000000)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`\x00', 0x200, 0x0)
r0 = openat$diskmap(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
r1 = socket(0x0, 0x0, 0x0)
mmap(&(0x7f0000400000/0xc00000)=nil, 0xc00000, 0x0, 0x1011, 0xffffffffffffffff, 0x0)
mprotect(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x5)
mmap(&(0x7f0000400000/0xc00000)=nil, 0xc00000, 0x0, 0x1011, 0xffffffffffffffff, 0x0)
shutdown(r1, 0x1)
ioctl$FIOASYNC(r0, 0x8004667d, &(0x7f0000000080)=0x7)
setsockopt$sock_int(r1, 0xffff, 0x1001, 0x0, 0x0)
r2 = msgget$private(0x0, 0x8)
pipe2(&(0x7f0000000000), 0x0)
msgsnd(r2, &(0x7f00000000c0)=ANY=[@ANYRES32=<r3=>0xffffffffffffffff], 0x1f, 0x800)
select(0x40, &(0x7f0000000040)={0x10374, 0x6a, 0x2, 0x0, 0x0, 0x0, 0x0, 0xff}, 0x0, 0x0, 0x0)
msgsnd(r2, &(0x7f0000000200)=ANY=[@ANYBLOB, @ANYRESOCT=r3], 0x401, 0x800)
msgsnd(r2, 0x0, 0x401, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f00001a5000/0x1000)=nil, 0x1000, 0x0)
msgrcv(r2, &(0x7f0000000400)={0x0, ""/137}, 0xaf, 0x0, 0x0)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB])
writev(0xffffffffffffffff, 0x0, 0x0)
close(0xffffffffffffffff)
r4 = syz_open_pts()
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, "fadd2109969a3c812426344f0ca0b3ede703e3e0"})
readv(r4, &(0x7f0000000600), 0x10000000000002a5)
mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x0)
r5 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSETA(r5, 0x802c7414, &(0x7f00000001c0)={0x0, 0x7c, 0x0, 0x208, "1a0001ad090201070000200007791dcebf00", 0xccf3, 0xffff})


msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000040)={{}, 0x0, 0x0, 0x0, 0x0, 0x1})
sysctl$kern(&(0x7f0000000080)={0x1, 0x31}, 0x4000000000000004, 0x0, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{0x3c}, {0x16}]})
socket(0x18, 0x0, 0x0)
r1 = socket$inet6(0x18, 0x3, 0x0)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
recvmmsg(0xffffffffffffffff, &(0x7f0000000400)={&(0x7f0000000200)={0x0, 0x0, &(0x7f0000000300), 0xa, 0x0}}, 0x10, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000280)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
sendmmsg(r2, &(0x7f0000000240)={0x0}, 0x10, 0x1a)
setsockopt$inet6_MRT6_ADD_MFC(r1, 0x29, 0x1a, 0x0, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x37}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)
mknod(&(0x7f0000000000)='./file0\x00', 0x6000, 0xe02)
r3 = open(&(0x7f0000000200)='./file0\x00', 0x80, 0x0)
readv(r3, &(0x7f00000001c0)=[{&(0x7f0000000140)=""/5, 0x5}], 0x1)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x5900)
open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)


r0 = socket$inet6(0x18, 0x3, 0x0)
getsockopt(r0, 0x29, 0x38, 0x0, 0x0)


sysctl$net_inet_etherip(&(0x7f0000000000)={0x4, 0x2, 0x61, 0x2}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0x0)
mkdir(0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, 0x0)
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000080), 0x8, 0x0)
bind(r1, &(0x7f0000000140)=@un=@file={0x0, './file0/file0\x00'}, 0x10)
r2 = socket(0x18, 0x2, 0x0)
sendmsg(r2, &(0x7f0000000840)={&(0x7f0000000380)=@in6={0x18, 0x1, 0x9, 0x7f}, 0xc, &(0x7f00000004c0)=[{&(0x7f00000003c0)="72ea465ba731b8a227b222d7ceed9302a20806e94247a0a85b4ca865b15a869eee0edccd413e32678585ab80b3841b7f3c694c7dfe4a6ac375ad90a8337671466f1cf0e5f7ec96ef243f3c31c798ddaaafcceec30f55508658e170b93ddab7ce44ae36edae95cf7f98e77c37a1079c6514571cbefe9528c72471138aecbb49116c78b83766af2ec609d1eb35dd892f4b987ca97e23a6bf3322ff209a40563a57c0e5334a68fa0e8606283306419981e0cb95f2ccca67aacec7d54efbe0a236fbd4524301f71226c314df45010758dea2becd6ea924372f8d47428e347e5bf63ce63708b5114c22b1deb814233672c81df204df", 0xf3}], 0x1, &(0x7f0000000c80)=ANY=[@ANYBLOB="7000000000000000ffff000000000400f65909bff56f69d87641406eed3dfd15f8ab95ccc3edaca9a8ab9a98477d39db7ec91e62395f5aecb55079b0c0d1b95306b25065ee65d7a24f745820668a7e28c4864c711d982316a1e79ebfbd22172c90ed814333fe8c259b939766e6000000c000000000000000010000000900000014a2e7159adaaa270b34e5083d2d8daacc9708076d2add98928c4694d70e31a9d5b32df82d0970c7f8099c3786aa928beb821fc090d60273f15d5122dcb39b8a526103e92e2a71a36eaccf1261e09bc588fc3b94e70b841ad43f00c1113e5ee8e0a7cf8b57b23499c6031e7181753551e27abd4d6f8900697a7ca2039b3362f456613bf0a5c6c26dc480a6406c234dce646e5d80e600cfdfa73778dadd366333710d000000003000000000000000010000000100008043b9e2987270f3d10ee10e7b63faf97a90184f203ea0a0285200000000000000a800000000000000ffff0000d400000056e2d82e083e3e9aa8b83854595345ae2164b60f7259308d91b0950273ec94b2fcd6253f47736285f9e9960f40bfdaf938c692f9bd07987020789936e70226467094132f7718bb8c89aa1a01de0a44df41d1a657655ba16e9f4fdfe3e9ee93231c9ab7cb27b4e7586e80b240df2061782c39f36cc31a40c3e6f9b552a59a7e6bb4f3957981579f70d4777638b7838792635b0c7d98a5000068000000000000000100000003000000fe51618420cfa38c4dbc19f2ded006207d8191892004bbd2dd5b5b18953fbf5b4976aceff6730519282137b83f9b2ed5084eadd61eda87daafd5b189a73468201b5ed7e9251f639534138ee6b26307cfa2fd3a139c158c0068000000000000000100000006000007000000fa86d9ac41a1880abc152fad63133b1e8b3d2d51b3c81dca8ec68dae08b858a0a880ceeae20ba90333c414d85e221458a6b2474936b85941dacc9fe8386714ac473662a3cf39221607d2de882a7c627765e8483f0404ea37add8abf95ebf2d8288c5c94e6c09037e4c5b95c30d30c0eb91d2cb6a11cb87524ea5f1ea8a3ce3a3e060798fc1ad774401acb9bb07d3f28c0a33e64480ca08e86b233257db7ccced60ab187b08bdfc413cd6c2bd14d3c8ab5edb49ebed349a694e04f477cd9371af283ed517aa48dfc92c21543e2cfea48e19b890728d99d508fa0951112815eca5e70f002ded4409a958b649fe90ca6580e3ba7c"], 0x2d8}, 0x4)
r3 = socket(0x18, 0x2, 0x0)
getsockopt(r3, 0x29, 0xa, 0x0, 0x0)
close(r2)
r4 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(r4, &(0x7f0000000400)=[{&(0x7f0000000180)="9c0b291fec6a5560c6011c38", 0xc}], 0x1)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x1, 0x10, r0, 0xffffffffffffffff)
r5 = socket$unix(0x1, 0x1, 0x0)
ioctl$FIONREAD(r5, 0x80206979, &(0x7f0000000000))
socket$inet(0x2, 0x3, 0x102)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000140)=[{0x74}, {0x4}, {0x812e}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


r0 = socket$inet6(0x18, 0x4003, 0x0)
getsockopt(r0, 0x29, 0x4, 0x0, 0x0)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000580), &(0x7f0000000140)=0xc)
syz_emit_ethernet(0x4e, &(0x7f0000000280)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa86dd60004b0000182b00fe8000000000000000000000000000bb607ba243b19d8e9ea241f577704405b63a01"])
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])
r1 = semget(0x0, 0x3, 0xc530b8543b69d24c)
semctl$GETVAL(0x0, 0x0, 0x5, 0x0)
shutdown(0xffffffffffffffff, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x802069c7, &(0x7f00000001c0))
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
setreuid(0xee00, 0x0)
semop(r1, &(0x7f0000000180)=[{0x4}, {0x3, 0x0, 0x1000}, {0x1, 0x5, 0x800}, {0x4, 0x800, 0x1000}], 0x4)
getuid()
open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffff9c, 0x80104277, &(0x7f00000000c0)={0x2, &(0x7f0000000080)=[{}, {0x3, 0x0, 0x0, 0x44}]})
sysctl$kern(&(0x7f0000000080)={0x1, 0x31}, 0x4000000000000004, 0x0, 0x0, 0x0, 0x0)
r3 = socket(0x18, 0x3, 0x0)
setsockopt$inet6_MRT6_ADD_MIF(0xffffffffffffffff, 0x29, 0x67, 0x0, 0x0)
preadv(0xffffffffffffffff, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r4 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r4, 0xc0106924, &(0x7f00000001c0))
ioctl$FIONREAD(r3, 0xc1206951, &(0x7f0000000100))
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x18, 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f00000002c0)=[{0x20}, {0x61}, {0x812e}]})
syz_emit_ethernet(0x17a, &(0x7f0000000000)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, 0x0)
syz_emit_ethernet(0x138, 0x0)
ioctl$BIOCSBLEN(r0, 0xc0044266, &(0x7f00000000c0)=0x10001)
clock_settime(0xffffffffffffffff, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x2, &(0x7f0000000280)=[{}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f00000002c0)=ANY=[@ANYRES8, @ANYRES32=r1, @ANYRES8])
msgsnd(0x0, &(0x7f0000000040)=ANY=[@ANYBLOB="02000000000000001df33699fb723383"], 0x55, 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000040)={0x7, 0x2, 0x2}, 0x4, &(0x7f0000000140)="118bea625d95de8f92c010baed45ec4bf03ace254b57973bb6de7b1c90301e9d3b5e6fb6ffffffffffffffff76c775a2a4e0556565a830032eef776127fd247103c14ab0a1cea9b4593be484f46a02ea73e910d041c5777bd852e57d3248832b91d06fe47d126022a1654859149e9486306d2f11fb1cc826c42f81b0d114f8af4ceb029a5210bb6947464bf678ba1d64a2013131fedfe60443aa13e015b28a16ea924bf89ad45c006213a6d0e194b9abcb3ddfab0c69b8c280bfc9c11f26026f6231b5e725921be8b099", 0x0, 0x0, 0xfffffffffffffd2a)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x0, &(0x7f00000000c0)})
sysctl$kern(&(0x7f0000000040)={0x1, 0x47}, 0x3, &(0x7f0000000100)="71f91e3471ac00cb5c656358bc5a91501d94a34b8e5f84cf71b59c7afec370608bd11afd2c011d106d2e5cb2d3435b82", &(0x7f0000000080)=0x3447, 0x0, 0x37)
ioctl$WSMOUSEIO_GETPARAMS(0xffffffffffffffff, 0x80105727, &(0x7f0000000080)={0x0})
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{}, 0x8001})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0xc0206921, &(0x7f00000001c0))
r3 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r3, 0x8040691a, &(0x7f00000001c0))
r4 = msgget$private(0x0, 0x0)
r5 = socket$inet(0x2, 0x1, 0x0)
getsockopt$inet_opts(r5, 0x0, 0x14, 0x0, 0x0)
msgsnd(r4, &(0x7f0000000100)=ANY=[@ANYRES64], 0x107, 0x0)
msgrcv(r4, &(0x7f0000003c00), 0x1013, 0x3, 0x0)
setrlimit(0x8, 0x0)
msgctl$IPC_RMID(r4, 0x0)


sysctl$net_inet6_ip6(&(0x7f0000002c00)={0x4, 0x18, 0x29, 0x7}, 0x4, &(0x7f0000002c40), 0x0, &(0x7f0000002d00), 0x0)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000140)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0xffffffffffffffff}})
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x101}})
socket(0x1, 0x1, 0x0)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0x37, &(0x7f0000000040), 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
socket$inet(0x2, 0x0, 0x0)
close(0xffffffffffffffff)
socket$inet(0x2, 0x0, 0x0)
r1 = msgget$private(0x0, 0x0)
msgsnd(r1, &(0x7f0000001540)=ANY=[@ANYBLOB="02000000000040006d1d5fcb28d9fc2efd0008000000000000b8f707aff57432a505995139959fe8249fcfeb969ee0027f"], 0x32, 0x0)


socket(0x6, 0x3, 0x0)
sysctl$net_inet_carp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x3}, 0x4, 0x0, 0x0, &(0x7f00000010c0)="e1000000", 0x4)
sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x17}, 0x4, 0x0, 0x0, 0x0, 0x15)
sysctl$vm_swapencrypt(&(0x7f0000000040)={0x6, 0x1b, 0x3}, 0x3, 0x0, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)
ioctl$WSKBDIO_GETDEFAULTBELL(0xffffffffffffffff, 0x40105706, &(0x7f0000000180))
sysctl$kern(&(0x7f0000000040)={0x1, 0x3f}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0xfffffffffffffda3)
setreuid(0xee00, 0x0)
getuid()
r0 = semget$private(0x0, 0x1, 0x4ee)
semop(r0, &(0x7f0000000340), 0x0)
semop(r0, &(0x7f0000000140), 0x2aaaaaaaaaaaaddb)
mknod(0x0, 0x6000, 0x6da)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
dup2(r2, r1)
shutdown(r1, 0x1)
poll(&(0x7f0000000080), 0x0, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
semctl$SETALL(r0, 0x0, 0x9, &(0x7f0000000040))


syz_emit_ethernet(0x3e, &(0x7f0000000540)={@local, @broadcast, [], {@ipv6={0x86dd, {0x0, 0x6, "062500", 0x8, 0x0, 0x0, @rand_addr="00000000001b00", @loopback={0xfeffffff00000000}, {[@fragment={0x2b}]}}}}})


r0 = socket$unix(0x1, 0x1, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
r1 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
open(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
mprotect(&(0x7f0000ffe000/0x1000)=nil, 0x1000, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
mprotect(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x4)
mlockall(0x1)
munlock(&(0x7f0000ffb000/0x4000)=nil, 0x4000)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000000), 0x2cfea}], 0x1000000000000013)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ff3000/0x2000)=nil, 0x41000}, {&(0x7f0000538000/0x2000)=nil, &(0x7f000013e000/0x2000)=nil}, {&(0x7f00001f5000/0x4000)=nil, &(0x7f0000162000/0x4000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ff3000/0xa000)=nil}, {&(0x7f0000ff2000/0x3000)=nil, &(0x7f0000ff9000/0x3000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f0000ffa000/0x4000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f00001f4000/0x2000)=nil}, {&(0x7f0000002000/0x1000)=nil, &(0x7f0000ff9000/0x6000)=nil}, {&(0x7f0000054000/0x4000)=nil, &(0x7f000009f000/0x4000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000084000/0x1000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000161000/0x4000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
socket(0x0, 0x3, 0x0)
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r1, 0xc0384600, &(0x7f00000000c0)={&(0x7f0000000000)='./file0\x00', 0x3, 0x0})
r2 = socket(0x2, 0x3, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt$sock_int(r2, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
writev(r0, &(0x7f00000000c0)=[{&(0x7f0000000140)="63ce8397fe14de743c233fe65a15d3c117ca01612bdaec8abcd1b6583c075659e673844d7b640e7fd94439859267fa22190223a0746984fb40799865302519eec2943faa9810054bcf7387c8676d70848b3a7dc7a5a77f6ea7f1ca5e5d4cdd6985afe3672b", 0x65}], 0x1)
execve(0x0, 0x0, 0x0)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000180)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x81206919, &(0x7f00000001c0))


setitimer(0x0, &(0x7f0000003a40)={{}, {0x0, 0x10000}}, 0x0)
getitimer(0x0, &(0x7f0000003c40))


mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x412dff)
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, &(0x7f0000000440)={&(0x7f0000000280)='./bus\x00', 0x1000, &(0x7f00000002c0)='./bus\x00', 0x6})
r0 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
recvmsg(0xffffffffffffffff, &(0x7f00000025c0)={0x0, 0x0, &(0x7f0000002540)=[{&(0x7f0000001480)=""/4090, 0xffa}], 0x1, 0x0}, 0x0)
preadv(r0, &(0x7f0000000300)=[{&(0x7f00000000c0)=""/104}, {&(0x7f0000000140)=""/192}, {&(0x7f0000000340)=""/175}, {&(0x7f0000000000)=""/18}], 0x10000000000002b8, 0x0)
fchmod(r0, 0x40)
r1 = socket(0x18, 0x3, 0x0)
setsockopt(r1, 0x1000000029, 0x26, &(0x7f0000000000)="5ab7776a", 0x4)
close(r1)
setsockopt(r1, 0xfffffff8, 0x7ff, &(0x7f0000000480)="2ac4310fdd8ee9d1ba160fa33bb09b1d2a7a7dfcb12e73e54a912b32e32705cfce67c7216048d2d79285d69468a9c98173c04c5d85746d905d461e2e8f757424d9d838c3569f12286a636e347bafc5f95c5d5df4ccfd9b8a62f1428a2f2b09fd325fd7b8e9f52aa37162", 0x6a)
fcntl$dupfd(r0, 0x0, r1)
r2 = socket(0x10, 0x4000, 0xff)
setsockopt(r2, 0x1000000029, 0x26, &(0x7f0000000000)="5ab7776a", 0x4)
socketpair(0x6, 0x4, 0x80, &(0x7f0000000580))
openat$wsdisplay(0xffffffffffffff9c, &(0x7f00000005c0), 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x200, &(0x7f0000000200)=0x5, 0x4)
fcntl$dupfd(r0, 0x0, r1)


mknod(0x0, 0x20, 0x0)
sysctl$net_pipex(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = open(&(0x7f0000000140)='./file0\x00', 0x10080, 0xe185c418b29b5ec7)
mknod(&(0x7f0000000040)='./file0\x00', 0x2000, 0x3)
r1 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0xa8)
r2 = fcntl$dupfd(r1, 0x0, r1)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r3 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r3)
r4 = socket(0x11, 0x3, 0x0)
getpeername$unix(r4, 0x0, &(0x7f0000001140))
ioctl$VNDIOCSET(r2, 0xc0384600, &(0x7f0000000100)={0x0, 0x0, 0x0})
mmap(&(0x7f00001eb000/0x3000)=nil, 0x3000, 0x0, 0x11, r0, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
kevent(r0, 0x0, 0xf21, 0x0, 0x0, 0x0)
open$dir(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
fchmodat(r1, &(0x7f0000000240)='./file0\x00', 0x50, 0x2)
pwritev(r2, &(0x7f0000000440), 0x0, 0x100)
r5 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
ftruncate(r5, 0x80002)
open$dir(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
preadv(0xffffffffffffff9c, 0x0, 0xfffffffffffffe16, 0x0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
open(&(0x7f0000000180)='./bus\x00', 0x2, 0xc1)
openat$speaker(0xffffffffffffff9c, &(0x7f00000002c0), 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000100)={0x2, &(0x7f00000000c0)=[{}, {0x1, 0x0, 0x0, 0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x37}, 0x4, &(0x7f0000000000)="71f91e3471ac0058bc5a91501d942400b5e1a0757cb9af769c7afec37082", &(0x7f0000000080)=0x7, 0x0, 0x2e)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
syz_emit_ethernet(0x2a, &(0x7f0000000140)=ANY=[@ANYBLOB="00000000000000000000000008060001080006040008ffffffffffff7f00000100000000e3"])
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


sysctl$net_inet6_ip6(&(0x7f0000000000)={0x4, 0x18, 0x29, 0x2b}, 0x4, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
sysctl$net_inet_tcp(&(0x7f0000000000), 0x4, 0x0, 0x0, &(0x7f00000010c0), 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x64}, {0xc0}, {0x8186}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


syz_emit_ethernet(0x46, &(0x7f0000000080)=ANY=[@ANYBLOB="aaaaaaaaaaaaffffffffffff86dd606aa63f00102b00fe8000000000000000000000000000bb0000000000000004000000000000000133102a"])


mknod(&(0x7f0000000080)='./file0\x00', 0x6000, 0x202)
mknod(&(0x7f0000000200)='./bus\x00', 0x6000, 0x0)
link(0x0, &(0x7f0000000100)='./file0\x00')
r0 = accept(0xffffffffffffff9c, &(0x7f0000000040)=@in6, &(0x7f0000000080)=0xc)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000200), &(0x7f00000001c0)=0xc)
sendmmsg(0xffffffffffffffff, &(0x7f0000000080)={0x0}, 0x10, 0x0)
r1 = dup2(0xffffffffffffffff, 0xffffffffffffffff)
sendto$unix(r1, 0x0, 0x0, 0x0, 0x0, 0x0)
connect(0xffffffffffffffff, 0x0, 0x0)
setpgid(0x0, 0x0)
socket(0x0, 0x0, 0x0)
dup(0xffffffffffffffff)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
close(0xffffffffffffffff)
socket(0x0, 0x0, 0x0)
ioctl$WSDISPLAYIO_LSFONT(0xffffffffffffffff, 0xc058574e, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000000)={<r2=>0x0, <r3=>0x0, <r4=>0x0}, 0xc)
getpid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000003c0)={{0x6, r3, r4, 0x0, r4, 0x0, 0xfffb}, 0x2, 0x0, 0x0, r2})
getgroups(0x0, 0x0)
getgid()
r5 = msgget$private(0x0, 0x0)
msgrcv(r5, 0x0, 0x0, 0x3, 0x0)
msgsnd(r5, &(0x7f0000001340)=ANY=[@ANYBLOB="03"], 0xed, 0x800)
utimes(&(0x7f0000000440)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000040)={{0x0, 0x5}, {0x5, 0x1}})


r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
r3 = socket(0x18, 0x1, 0x0)
listen(r3, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1023, &(0x7f0000000040), 0x4)


sysctl$kern(&(0x7f0000000040), 0x2, 0x0, 0x0, 0x0, 0x0)
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
syz_emit_ethernet(0x36, &(0x7f0000000040)={@local, @local, [], {@ipv6={0x86dd, {0x0, 0x6, "36e282", 0x0, 0x3b, 0x0, @local={0xfe, 0x80, '\x00', 0x0}, @local={0xfe, 0x80, '\x00', 0x0}}}}})
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
r2 = socket(0x2, 0x3, 0x0)
dup2(r1, r2)
setsockopt$sock_int(r2, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
write(r2, &(0x7f0000001680)="04bdfa5d1d2873c63e3534825ba166e2fea9aec43050006123339a346f731573d8d508753f95b7688ad48b8cf6bbca325cebc37fc4e1dd543dbe2da6dd", 0x1001c)
sysctl$kern(&(0x7f0000000000)={0x1, 0x52}, 0x2, 0x0, 0x0, 0x0, 0x0)
setsockopt$inet6_MRT6_ADD_MFC(r0, 0x29, 0x68, &(0x7f00000000c0), 0x3c)
r3 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000040), 0x200, 0x0)
r4 = socket(0x1, 0x1, 0x0)
close(r4)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendto$inet(r4, 0x0, 0x0, 0x0, 0x0, 0x0)
r5 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x800, 0x0)
r6 = openat$diskmap(0xffffffffffffff9c, &(0x7f00000000c0), 0x80, 0x0)
poll(&(0x7f0000000100)=[{r3, 0x20}, {r4, 0x108}, {r5, 0x4}, {0xffffffffffffff9c, 0x80}, {r6, 0x8}], 0x5, 0x6)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={<r7=>0xffffffffffffffff})
r8 = socket(0x1, 0x1, 0x0)
setsockopt$sock_int(r8, 0xffff, 0x1023, 0x0, 0x0)
setsockopt$sock_int(r7, 0xffff, 0x1001, &(0x7f0000000200)=0x2000000, 0x4)


recvmsg(0xffffffffffffffff, 0x0, 0x0)
r0 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r0, 0x0)
r1 = socket$unix(0x1, 0x5, 0x0)
ioctl$SPKRTONE(0xffffffffffffffff, 0x80085301, &(0x7f0000000340)={0x9, 0x2})
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$WSMOUSEIO_SRES(0xffffffffffffffff, 0x80045721, 0x0)
getsockname$inet(0xffffffffffffffff, 0x0, 0x0)
r2 = socket(0x20, 0x641cabeb310322a6, 0xb)
connect$unix(r2, 0x0, 0x0)
syz_emit_ethernet(0x26, 0x0)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
r3 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r3, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
r4 = open(&(0x7f0000000080)='./file0\x00', 0x200, 0x24)
close(r0)
sysctl$kern(&(0x7f0000000300)={0x2, 0x7}, 0x2, 0x0, 0x0, &(0x7f0000001440)='\x00\x00\x00\x00', 0x4)
ioctl$BIOCGRSIG(r4, 0x40044273, &(0x7f0000000100))
socket(0x2, 0x3, 0x0)
open(&(0x7f0000000180)='./file0\x00', 0x75f493fec6515f78, 0x0)


r0 = accept$inet(0xffffffffffffffff, &(0x7f0000000040), &(0x7f00000000c0)=0xc)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{0x0, 0x0, 0x0, 0x3}, {0x9}, {0x2, 0x0, 0x0, 0x2}]})
r2 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r2, 0x8080691a, &(0x7f0000000100))
bind(r0, &(0x7f0000000140)=@in={0x2, 0x2}, 0xc)
r3 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r3, 0x80105728, &(0x7f0000000100)={&(0x7f0000000080)=[{0x8b, 0x55a}, {0x81, 0x1e}, {0x84}], 0x3})
getpeername$inet(r0, &(0x7f0000000180), &(0x7f00000001c0)=0xc)


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)


mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x5d4a)
r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
getpid()
setitimer(0x2, &(0x7f0000000300)={{}, {0x2}}, &(0x7f0000000340))
close(r0)


pread(0xffffffffffffffff, &(0x7f0000000000)="aa8791a3a6f2d293050731", 0xb, 0x0)
r0 = socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f0000000000))


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, &(0x7f00000001c0))
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
syz_open_pts()
ioctl$TIOCSETAW(0xffffffffffffffff, 0x802c7415, 0x0)
readv(0xffffffffffffffff, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x1, 0x0)
r1 = socket(0x18, 0x1, 0x0)
r2 = socket(0x18, 0x3, 0x0)
ioctl$FIONBIO(r1, 0x8004667e, &(0x7f0000000080)=0x1)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r3 = semget$private(0x0, 0x0, 0x204)
semop(r3, &(0x7f0000000040)=[{0x2, 0x3, 0x1400}, {0x4, 0x1, 0x1000}, {0x1, 0x2, 0x1000}, {}, {0x4, 0x8, 0x1800}, {0x1, 0x0, 0x1800}], 0x6)
getsockname$inet(r2, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
dup2(r1, r0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


r0 = socket(0x2, 0x2, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
sendmsg$unix(r0, &(0x7f0000001a00)={&(0x7f0000000080)=@file={0x0, '\x00'}, 0x3, 0x0, 0x0, &(0x7f0000000040)=ANY=[@ANYBLOB="14"], 0x18}, 0x0)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
r1 = dup(r0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x100000000000000}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt(r1, 0x1000000000029, 0xd, &(0x7f0000000000)="ffdaf64c000000004f0527000000055e473e0000", 0x14)


r0 = kqueue()
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x100, 0x0)
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000180)={0x0, 0x0})
sysctl$net_inet_icmp(&(0x7f0000000040), 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x4f}, 0x3, 0x0, 0x0, &(0x7f0000000080)="4f1d4c6344b80ed788b6a4515248df3aa745bb992c574ab4cdf5587145812eab4a988f7fafd7a01d99776d988908cd186b51f34f8c15ffa0c685ad4116c783959eff4278384b4000384dbb1c2aaeff10b4135529a1da6fda67c67469d954be811b25ec5521559154c586eefff122009f659cd3e27e98a3241495005f102d9101d158284c0ee3250aa7c11042330de22a299ab00894fdc9bac6042d", 0xfffffc56)
pipe(&(0x7f0000000100)={<r2=>0xffffffffffffffff})
fcntl$setstatus(r2, 0x4, 0xc0)
r3 = getppid()
getegid()
r4 = msgget$private(0x0, 0x0)
msgrcv(r4, &(0x7f00000000c0)={0x0, ""/113}, 0x79, 0x0, 0x1000)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r5=>0xffffffffffffffff})
getsockopt$sock_cred(r5, 0xffff, 0x1022, &(0x7f0000000040)={0x0, 0x0, <r6=>0x0}, &(0x7f0000000080)=0xc)
msgctl$IPC_SET(r4, 0x1, &(0x7f0000000200)={{0xc57, 0x0, r6, 0x0, 0x0, 0x8, 0xac7}, 0x5, 0x5, 0x0, r3, 0xf0, 0x8000800000000000, 0x2, 0x20})
kevent(r0, 0x0, 0x0, 0x0, 0x8, &(0x7f00000001c0)={0x100000000000001})
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000000)={<r7=>0x0}, 0xc)
fcntl$setown(r0, 0x6, r7)
mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x412dff)
r8 = open(&(0x7f0000001700)='./file0\x00', 0x70e, 0x0)
write(r8, &(0x7f0000000000), 0x0)
clock_settime(0x100000000000000, &(0x7f0000000040))
kevent(0xffffffffffffff9c, &(0x7f0000000180), 0x10001, 0x0, 0x2000, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000140)=[{}, {0x3}, {0xff8}]})
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


syz_emit_ethernet(0x3e, &(0x7f00000000c0)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaaaabb86dd60b42f2f000800000000000000000004000000000000000100000000000000000000ffff"])


r0 = syz_open_pts()
syz_open_pts()
syz_open_pts()
fchmod(r0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x1, &(0x7f0000000100)=[{0xa9b8}]})


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETAW(r0, 0x802c7415, &(0x7f0000000000)={0x0, 0x0, 0x9, 0x6bf, "28113bb1e6648a1a267bc03b7a447ab255dcd9f0"})
readv(r1, &(0x7f0000000140)=[{&(0x7f00000000c0)=""/121, 0xb3}], 0x1000000000000203)
writev(r0, &(0x7f00000001c0)=[{&(0x7f00000009c0)="b40e30d66e380ed50e611a2dcfc8ad2fd6685ae0a88d6761264811845bcdfa9a052faaa5218153357fd1b8b7ee2518ee43394dc98e3c57cc33efdd18ad94b040ae134d78d34943c5c675701bb9d50eb990ab2cccb836f6711b4bd77d36e63cf60660b9affee686a8ce9130b06473a2c66ff37b8b919ed66dc0bef0d7c25e9b76cda9faed2c4a9ebce5e6f082d1a69d6d81968043d66f72507d99eadb920c9b7b0b5ccdd7927153783c8c7b6424aaea5002d4ce9a6b79e7c3d98aaefde99ca17e56ff0810da6ae1e4540786d3836feb97cfb35b7713e915f56d84ecb2d770713c2da17a81c158330274cb7be1d4753ea5caab967847d6bc91c1e0048224ce66d45f7d706fc777cbaa91f5f95725fb6be8b5dc9216373c3c27c1f6363fdf69ace4ed645617a72f19428768fd10d81f93fb15369cf167db686a56307870b8c03002a5f086c6cabc1d9789cb5c255db0261347b9cc2b48219b05ddb9a4f7d784e3bd6f83b974eca59cc2656f1ef8eba9228d2ba8ac5b55cce87bb14427de8379be352b62458912aee6a2f20be60ffab17724010fef3ba48002cb616a08b7d4e1949a3de6f34639f3b2c4e00ec615f31407a2e71f5302cdd3f0ce78e0e4d39212fed5cc15cb91cf7c79138e6ddaebc936", 0x1ce}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000000)=[{0x3}, {0x84}, {0x8106}]})
syz_emit_ethernet(0x62, &(0x7f00000000c0)=ANY=[])


sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504600000000000000007000000331c13fecea10500fef96ecfc72fd3357ae3200000000039d2d236073705ae04be38164991f7c8cf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139b672f4d335d223e7d026ba8af630037282102000000720fd38bfbb7700900a872c881ea7fb53bd676d907c400000200361b1257aea8c5000020020000000000008abfba0900000008e371a3f8343712051eadb71d89e000040781e41a80", 0xad, 0x0, 0x0, 0x0)
r0 = socket(0x11, 0x3, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
sendto$unix(r0, &(0x7f0000000000)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
bind$unix(r0, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
connect$unix(r0, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
connect$unix(r2, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r3=>0xffffffffffffffff})
connect$unix(r3, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
connect$unix(r0, &(0x7f00000000c0)=@file={0x0, './file0\x00'}, 0xa)


syz_extract_tcp_res$synack(&(0x7f0000000100), 0x1, 0x0)
syz_extract_tcp_res$synack(&(0x7f0000000200), 0x1, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000280), 0x10000, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x1, &(0x7f0000000000)=[{0x1, 0xbd, 0x2, 0x2}]})
sysctl$vm_swapencrypt(&(0x7f0000000040)={0x6, 0x1b, 0x1}, 0x3, &(0x7f0000000040), 0x0, 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
getppid()
pipe(&(0x7f0000000000))
mknod(&(0x7f0000000340)='./file1/file0\x00', 0x2000, 0x287e)
open(&(0x7f0000000380)='./file0\x00', 0x80, 0x0)
rename(&(0x7f0000000140)='./file0\x00', &(0x7f0000000000)='./file1/file0\x00')
open(&(0x7f0000000080)='./file0\x00', 0x8203, 0x0)
syz_open_pts()
r1 = socket(0x0, 0x3, 0x0)
setsockopt(r1, 0x1000000029, 0x0, 0x0, 0x0)
ioctl$WSDISPLAYIO_ADDSCREEN(0xffffffffffffffff, 0x80245753, &(0x7f0000000240)={0x4, './file1\x00', './file1/file0\x00'})
getsockopt(r1, 0x29, 0x2e, 0x0, 0x0)
socket$inet(0x2, 0x6, 0x81)
select(0x40, &(0x7f0000000440), 0x0, 0x0, 0x0)
r2 = openat$vnd(0xffffffffffffff9c, 0x0, 0x80, 0x0)
writev(r2, &(0x7f0000000200)=[{&(0x7f00000000c0)="9385c627db7ab718657a54f5563f3f428e628d6941fe0a43907b7c0f0dddf61e4bae2535ee7d412464fb35d253983decf64ba48e9ef4cace8d7b049a85936214695ebe694b23c244349818f3acd2a7", 0x4f}, {&(0x7f0000000140)="a1182787549b50171e4c6489a005778eeade0770f28ea06d6c386203c6a50a073475e5eb52aa98f40cd92271801445e75b39a8461f96e4674bf1111a310b621f02289d1d64f0139fb3785cf31249f5ba48d84fad0b26394984a7a5146ff1a9712d9355530a1c66178a38cbb0fccf4b923a1332522242331e8604299b2e0478667ecd5a06bc4e6362364d1d85618012e95508b16535169f3e6bddc039f9", 0x9d}, {}], 0x3)
sysctl$net_inet_tcp(&(0x7f0000000080)={0x4, 0x2, 0x6, 0x12}, 0x4, &(0x7f00000000c0), 0x0, 0x0, 0x0)
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0xc0106924, &(0x7f00000001c0))


r0 = socket(0x18, 0x400000002, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000029, 0x6, 0x0, 0x0)
getsockopt(r0, 0x29, 0x31, 0x0, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x6000, 0x404)
open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
getpid()
geteuid()
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x1000000029, 0x33, &(0x7f0000000080)="b6", 0x1)
getegid()
geteuid()
getegid()
getuid()
pipe2(&(0x7f0000000380)={<r2=>0xffffffffffffffff}, 0x0)
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f0000000340)={0x2, &(0x7f00000003c0)=[{0x7, 0x4, 0x0, 0xffffffff}, {0x8, 0x4, 0x7f, 0x2}]})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x100000000000000, 0xffffffffffffffff})
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x287e)
open(&(0x7f0000000000)='./file0\x00', 0x8000, 0x2)
ioctl$WSDISPLAYIO_SMODE(0xffffffffffffffff, 0x8004574c, &(0x7f0000000040)=0x1)
r3 = socket$inet(0x2, 0x1, 0x0)
r4 = dup(r3)
setsockopt(r4, 0x0, 0x5, &(0x7f0000000500)='\x00\x00\x00\x00', 0x4)
sendmsg(r1, &(0x7f0000000800)={&(0x7f0000000300)=@un=@file={0x0, './file0\x00'}, 0xa, &(0x7f0000000540)=[{0x0}, {&(0x7f00000004c0)="31d7dd12", 0x4}], 0x2, 0x0}, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f0000000100)={0x10, 0x0, [{&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {&(0x7f0000198000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000433000/0x3000)=nil}, {&(0x7f0000626000/0x2000)=nil, &(0x7f000093c000/0x2000)=nil}, {&(0x7f0000da9000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000e0a000/0x2000)=nil, &(0x7f0000c17000/0x3000)=nil}, {&(0x7f0000b64000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f00000da000/0x400000)=nil, &(0x7f00008bf000/0x1000)=nil}, {&(0x7f00008bf000/0x3000)=nil, &(0x7f0000af4000/0x13000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000601000/0x3000)=nil, &(0x7f0000b08000/0x1000)=nil}, {&(0x7f000064c000/0x2000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {&(0x7f0000633000/0x3000)=nil, &(0x7f0000518000/0x3000)=nil}], './file0\x00'})
syz_open_pts()
r5 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r5, 0xc028698d, &(0x7f00000001c0))


r0 = socket(0x11, 0x3, 0x0)
poll(&(0x7f0000000000)=[{r0}, {r0}], 0x2, 0x0)
sendto$unix(r0, &(0x7f00000000c0)="b1000504000004000000000007000000331c13fecea10500fef96ec0c79f050000e30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba220f54f4fcf668246c0900e1937c727a4bdb8d000008e371a3f034371205", 0xb1, 0x0, 0x0, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
r1 = socket$inet(0x2, 0x2, 0x0)
close(r1)
r2 = socket$inet(0x2, 0x2, 0x0)
dup2(r0, r2)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00040000000000", 0x8)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000200)="ea00000000000000", 0x8)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000240)="ea02000000000000", 0x8)
setsockopt$inet_opts(r1, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0x8)


setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSTOP(r0, 0x2000746f)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000040)={0x0, 0xffffffff, 0x9, 0x203519, "28b7e60ab87aa57800000000d0d2000000001c00"})
writev(r0, &(0x7f0000000740)=[{&(0x7f0000000380)="4b8572730e51a93601084c480dc1199dc57b2495e54e7209c4c7ad688b2768a5c2dc2606cb3396fe19b7684fece0172cf942aa0b7918b45b0efaf120cb28eabf16f7c5000b4159c5d1cc872d79ad1721703966da567664630f2106236f5650fdbfa8246401bb352764be4b6fa3ebc0b99a3665bc25216ba50581e8c9aff5a6691e97bedc672c5e8e3ed4bd372eb4db334603c9fb94a733c8f0455f4285c7b298e66cf9bebb66f447e2fa9afbb8108623ef393b169cbd255c6b3db0b76f90ed460706c5193c7b1f5066d2dbf51d6cd727629cd778450dcb36f693bb26b75e82299e4e39eeac9ae3122c7ddd1adc48621758141b0dca303454edf70ff1e66f574bfa184fe0e6003aadfdb7b196087edddc571ab8a8bf9d9676b2a22ba7e946a26377f29f53d461fbe5238b3ba135febe2821ce168c88fed545c6f82874285b00254d20ec65a168817dcd0157821d9c0c28d4790c62cbf67b6f71982c73fcbc5f943204b649b6313e879d2cd92c788aab06c014a89b3523debb0451a3a5f559d06bcb8bddb5de9aae120000f2eac0b8b83c9502f70f80a627d784037f333ed300c3a993e252", 0x1a4}], 0x1)


open(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000440)={0x2, &(0x7f00000000c0)=[{}, {0x0, 0x80}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4f}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8efdb4cf71c37082", &(0x7f0000000000)=0x2, 0x0, 0x37)


r0 = open(&(0x7f0000000200)='./file0\x00', 0x20, 0x92)
writev(r0, &(0x7f0000000280)=[{&(0x7f0000000400)="56cf5daafc6597872431ff6c668c28adc33a60651a078a116b3548a8be66444658a069b71e92feadcd7b3434dadfc4fc3fd4ef7525b58b0086932b0a93463511a8889f58073c33282b2afa1967c7908d4d0aea830b68a43711d6c4457ec4a41a772d6ae311730b7823d96ef1c25a7bae68954da1ffde05cf138758ef54d053a94bce1d28f7ea235a66647b6db6eda0d5e78db16b66fae3f13f", 0x99}], 0x1)
r1 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r2 = syz_open_pts()
fcntl$lock(r2, 0x9, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x60002fffffff7})
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x3, 0x10, r1, 0x0)
pipe(&(0x7f00000000c0)={<r3=>0xffffffffffffffff, <r4=>0xffffffffffffffff})
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r5, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000001c0)=[{0x3}, {0x30}, {0xe}]})
write(r5, &(0x7f00000003c0)="800000000000147d795000007d21", 0xe)
ioctl$FIOASYNC(r3, 0x8004667d, &(0x7f0000000140)=0x400)
poll(&(0x7f0000000000)=[{r3}], 0x1, 0x0)
r6 = socket(0x18, 0x1, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000001c0)={0x0, 0x0, 0x0, 0x2000100000002})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r6, 0x801169ab, &(0x7f00000001c0))
dup2(r3, r4)
r7 = syz_open_pts()
fcntl$lock(r7, 0xb, 0x0)
sendto(0xffffffffffffffff, 0x0, 0x0, 0x0, &(0x7f0000000080)=@in6={0x18, 0x3, 0x0, 0x1001ff}, 0xc)
ioctl$BIOCGFILDROP(r5, 0x40044278, &(0x7f0000000100))
socket(0x800000018, 0x1, 0x0)
bind$unix(r3, &(0x7f0000000180)=@file={0x1, './file0\x00'}, 0xa)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000080), 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000000)=[{0x15}, {0x15}, {0x6}]})
syz_emit_ethernet(0x66, &(0x7f0000000180)=ANY=[])


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000006c0), 0x1, 0x0)
writev(r0, &(0x7f0000000080)=[{&(0x7f00000001c0)='O', 0x1}, {&(0x7f0000001600)='L', 0x1}], 0x2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000480), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x6c}, {0x24}, {0x6}]})
syz_emit_ethernet(0x6e, &(0x7f0000000000)=ANY=[])


fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504600000000000000007000000331c13fecea10500fef96ecfc72fd3357ae3200000000039d2d236073705ae04be38164991f7c8cf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139b672f4d335d223e7d026ba8af630037282102000000720fd38bfbb7700900a872c881ea7fb53bd676d907c400000200361b1257aea8c5000020020000000000008abfba0900000008e371a3f8343712051eadb71d89e000040781e41a80e363", 0xaf, 0x0, 0x0, 0x0)
socket(0x11, 0x3, 0x0)
socket$inet(0x2, 0x0, 0x0)
r0 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
unlink(&(0x7f00000001c0)='./file0\x00')
select(0x40, &(0x7f0000000000)={0xffeffffffffffffd, 0x0, 0x0, 0x0, 0x0, 0xfffffffffffffffd}, 0x0, 0x0, 0x0)
mkdir(&(0x7f0000000100)='./file0\x00', 0x49)
setreuid(0xee00, 0x0)
r1 = getuid()
getuid()
chown(&(0x7f0000000200)='./file0\x00', r1, 0xffffffffffffffff)
setreuid(0xee00, r1)
unveil(&(0x7f00000000c0)='./file0/file0\x00', &(0x7f0000000080)='r\x00')
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r0, &(0x7f0000000000), 0x10)
sysctl$hw(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
r2 = open$dir(0x0, 0x0, 0x9)
linkat(0xffffffffffffffff, &(0x7f00000000c0)='./file1\x00', r2, &(0x7f0000000140)='./file0\x00', 0x5929d53439ccc69f)
write(r0, &(0x7f0000000240)="14bdfa5d1d34e2fecb284a6498307dcda9aec43050036123339a346f737850551408753f95b7688ad4c4e1dd5489e7bafc58d3e5823757ae8b630719ef187ccad995f13dbe19a6dd4e6902bd8297b0799b426aabe9fad9db6996571c6d9f8bb5d542c2148aa42be940970fe88d34d8f99afe7e7820237400000000008000000100"/138, 0xfc7e)


syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
accept$inet(0xffffffffffffffff, &(0x7f0000001780), &(0x7f00000017c0)=0xc)
r0 = socket(0x2, 0x3, 0x0)
bind(r0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
connect$unix(r0, &(0x7f0000000000), 0x10)
sendto$inet(r0, 0x0, 0x0, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCLOCK(r0, 0x20004276)
seteuid(0xffffffffffffffff)
ioctl$BIOCGETIF(r0, 0x4020426b, 0x0)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r0, 0xc2585601, &(0x7f00000001c0)={0x10, 0x0, [{&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x8000}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffb000/0x3000)=nil, 0x80000000}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000ffa000/0x4000)=nil}, {&(0x7f0000ffa000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ffc000/0x1000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ff9000/0x3000)=nil}, {&(0x7f0000ff9000/0x3000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f0000ff9000/0x3000)=nil, &(0x7f0000ffa000/0x1000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {&(0x7f0000ff8000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000ff8000/0x4000)=nil, &(0x7f0000ffa000/0x4000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffa000/0x1000)=nil, &(0x7f0000ffd000/0x2000)=nil}], './file0\x00'})


sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = socket$inet(0x2, 0x2, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f0000000080)={&(0x7f0000000040)=[{}, {}], 0x2})
setsockopt$inet_opts(r0, 0x0, 0x200100000001d, 0x0, 0x0)
r1 = msgget$private(0x0, 0x0)
getsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x14, 0x0, 0x0)
msgsnd(r1, &(0x7f0000000100)=ANY=[@ANYRES64=r0], 0x107, 0x0)
msgrcv(r1, &(0x7f0000003c00), 0x1013, 0x3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
setrlimit(0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r2 = socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(r2, 0x8020691f, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
r3 = socket(0x0, 0x1, 0x0)
setsockopt(r3, 0x0, 0x0, &(0x7f0000000000), 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0xc7a}})
connect$unix(0xffffffffffffffff, 0x0, 0x0)
close(0xffffffffffffffff)
utimes(0x0, &(0x7f0000000040)={{0x8000000000000004, 0x4000000000000004}})
r4 = openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$PCIOCREAD(r4, 0xc0107002, &(0x7f0000000040))


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b10005010000009f0500070107000000331c13fecea70500fef96ecfc72fd3357ae30200004e30ffd2d236acf20bf404be01000000f7c8cf5f882b290008aa050400ce94e2f0ad3ebec257699a1f139b672f335c22db830c032bfa896443c32118210000720fd38bfb0000fd54c125191b1257aea8c500001602fbfe0c2300008abfd9adf071da68f24a83ba0900000808f37193f8343712cc1100b71dc000090105000000000000001300000000000000", 0xb1, 0x0, 0x0, 0x0)


readv(0xffffffffffffffff, &(0x7f0000000200)=[{&(0x7f0000000100)=""/185, 0xb9}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket$inet(0x2, 0x8003, 0x0)
getsockopt$sock_linger(r0, 0xffff, 0x80, &(0x7f0000000040), &(0x7f0000000200)=0x8)


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000000)=[{}, {0x0, 0x0, 0x40}, {0x6}]})
sysctl$kern(&(0x7f0000000000)={0x1, 0x42}, 0x6, 0x0, 0x0, 0x0, 0x0)


socket$inet(0x2, 0x2, 0x9)
mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
r0 = socket$unix(0x1, 0x5, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x1000, &(0x7f0000000040), &(0x7f0000000400)=0xfffffffffffffff6)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2006, 0x0)
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000480)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
bind$unix(r0, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
seteuid(0xffffffffffffffff)
r1 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
setreuid(0xee00, 0x0)
r0 = getuid()
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000580)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000140)=0xc)
chown(&(0x7f0000000200)='./file0\x00', r0, r2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x1}, {0x48}, {0x16}]})
write(r0, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xfef3)


setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0x0, r0)
r1 = socket(0x800000018, 0x2, 0x0)
r2 = socket(0x18, 0x1, 0x0)
setsockopt(r2, 0x29, 0xe, &(0x7f0000000000)="02000000", 0x4)
r3 = dup2(r2, r1)
ioctl$KDGETLED(r3, 0x40044b41, &(0x7f0000000080)=0x1)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000040)={0x0, 0x0, <r4=>0x0}, &(0x7f0000000180)=0xc)
chown(&(0x7f0000000080)='./file0\x00', 0x0, r4)
r5 = socket(0x2, 0x2, 0x0)
connect$unix(r5, &(0x7f0000000300), 0x10)
r6 = semget$private(0x0, 0x7, 0x3c0)
semop(r6, &(0x7f0000000180)=[{0x0, 0x43, 0x1800}, {0x4, 0xe6, 0x1800}, {0x0, 0xfd, 0x1000}, {0x1, 0x9, 0x1800}, {0x2, 0x5, 0x1800}, {0x4, 0x9e, 0x1000}, {0x2, 0xfffb, 0x1000}, {0x0, 0x40, 0x1000}, {0x3, 0x8, 0x1000}], 0x9)
semctl$SETALL(r6, 0x0, 0x9, &(0x7f00000004c0)=[0x9, 0x1001])
getsockopt$SO_PEERCRED(r5, 0xffff, 0x1022, &(0x7f0000000200)={0x0, 0x0, <r7=>0x0}, 0xc)
semctl$IPC_SET(r6, 0x0, 0x1, &(0x7f0000000240)={{0x8001, 0xffffffffffffffff, r7, 0xffffffffffffffff, 0x0, 0x40, 0x2}, 0x0, 0x9, 0xe7})
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000200)={{0x3, 0x0, r4, 0x0, r7, 0xa, 0x8}, 0x1, 0x1, 0x5})
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000000c0)={0x0, 0x0, <r8=>0x0}, &(0x7f0000000040)=0xc)
r9 = semget(0x0, 0x0, 0x470)
r10 = getuid()
semctl$IPC_SET(r9, 0x0, 0x1, &(0x7f0000000100)={{0x2, 0x0, r8, r10, r8, 0xf26605a7c7776b73, 0x3}, 0x10001, 0x6, 0x8})
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000000c0)={0x0, <r11=>0x0}, 0xc)
getsockopt$sock_cred(r3, 0xffff, 0x1022, &(0x7f0000000100)={0x0, 0x0, <r12=>0x0}, &(0x7f0000000140)=0xc)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={<r13=>0xffffffffffffffff})
getsockopt$sock_cred(r13, 0xffff, 0x1022, &(0x7f0000000100)={0x0, 0x0, <r14=>0x0}, &(0x7f0000000140)=0xc)
chown(&(0x7f0000000140)='./file0\x00', 0xffffffffffffffff, r14)
semctl$IPC_SET(r9, 0x0, 0x1, &(0x7f0000000180)={{0x8, r11, r12, r0, r14, 0x42, 0x6}, 0xd45f, 0xffffffffa034dcb1, 0x1})
setsockopt$sock_int(r1, 0xffff, 0x1, &(0x7f0000000040)=0x7, 0x4)
listen(r1, 0x3)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000180)={<r0=>0xffffffffffffffff})
open(&(0x7f0000000200)='./file0\x00', 0x200, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
r1 = socket$unix(0x1, 0x2, 0x0)
sendmsg(r1, &(0x7f0000000880)={&(0x7f0000000000)=@in6={0x18, 0x2}, 0xc, &(0x7f0000000500)=[{&(0x7f0000000300)="04ee1220a39d7e607c22524941bc1e655012816e01b31c94e0b973973eb7ab413e7efab02b7eb3ead79ddf455daf6423befdf55551a58322ffca19a5fcc6687a3d47168886092104c0c1dfc0074c82d707a7a9f09313953c3c9c3cb060f62c8dc864914e7f184dfca58acba52ab674a0ed4b1a6baf48", 0x76}, {&(0x7f00000000c0)="e5bbc8e6ea26c4a2c2339abbcadd2848ad683bce7b6a651528cf23a18e1d17c0b79fcc0ba4c21c4529b6effa638c926f12409dc212af3fd9f9a2b79288b50f01cec927dbb52d2da427d7ec08fb7b93ba2db6deda06d03a41d3258c901e8c9bc59aa88c1e383d2ebecc07eda7e754c3bd06b3335c0ca323229ef090e28a241fcc4dccbb751b292f5ab5334580da2e161590cb3c1b92d70a45e3a2fbbae0732287983bb6bc8df2a77417a3c3558d5b7c632f0cd37382229275b640fb8c1702beb96458b4182752adbab4b4263676845b2a6d845e2e36fba221e31ff02afbbefddc698be60bf84f76d0a62c5a1dc785d092b0591ef9e31d6b9a21", 0xf9}, {0x0}, {&(0x7f00000003c0)="740ed1910a1ceca37276b561d44ad5825b936decdb10551130c9ebe6debec110f4fea5fe0e5b7d76bc0000a1ba27afcff139ca81f1fcc45e8b71997aeb1c4393a16d7361e3e9a2e04e6398d2545d02aa69141300006e11ead78cb0ba78cb411c9242479f9d0c6b9bfc209f7fa3b216f3a363abeec71dd20f6c9b31", 0x7b}, {&(0x7f0000000900)="7f91fc41919f21aed5ddabec99491a3e560e7289c134b689d4693471159330d45bf6ed99e925497919c07afeea00ab0612c67c36e0572afa0d395e40727014fa4e5e05a4b6", 0x45}, {&(0x7f00000004c0)="0212b2fb88fe80a75143936a2232fdac9a9d48641474c5a45e7a4d48aaf03b6f25ff154680b78aa421", 0x29}], 0x6, &(0x7f0000000700)=[{0x20, 0x1, 0x0, "0fe24e05dccc752cc8"}, {0xc8, 0xffff, 0x0, "f351fe518620ba1ec0933d07222a353fef6b8b48192f3dc3f5f488ca5ef329494d2ca6d80435bb3cc514ba85bf8bb07d53686a3a0dca59360180ca5c46ef40e1209d41eca72a4884a515185357b5fa41edf1154b5c5fca8a2d128b72b9680511ca1fc5888f75c46264a3096b8f2867b82001f46ebd030a4520dde29069f1602e17002884bdd53df524e5e34c1da1b44b601e2837821e248d556ff925ae0e9f958f37e86d8980a0f2aa4abb28323a3d697a"}, {0x90, 0x0, 0x0, "0f5db35e05f26636fb2c302eaf57b8c87dff269d4b23ebc6a547dd45088f943a4484fe1cbcedb2829d048b5317f13995df9dd9a71cec09a3b3de7e860986cb83feaa4d5cb01f1f5b8c3b777944183f6f2cee2c59838f0394a9495c7dd3e667f871163ef9490d2b95ac80cd91142e2a709c86627fa8e5547f0e"}], 0x178}, 0x0)
ioctl$FIONBIO(r1, 0x8004667e, &(0x7f00000008c0)=0xb24)
execve(0x0, 0x0, 0x0)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000100)={<r2=>0x0}, &(0x7f0000000040)=0x2)
openat$wsdisplay(0xffffffffffffff9c, &(0x7f0000000580), 0x20000, 0x0)
ktrace(&(0x7f00000000c0)='./file0\x00', 0x0, 0x1008, r2)


r0 = socket(0x18, 0x2, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x100, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{0x64}, {}, {0x46}]})
syz_emit_ethernet(0xba, &(0x7f0000000080)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{0x64}, {0x2d}, {0x46}]})
syz_emit_ethernet(0xba, &(0x7f0000000080)=ANY=[])


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
recvmmsg(0xffffffffffffffff, &(0x7f0000000040)={&(0x7f00000000c0)={0x0, 0x0, &(0x7f0000000580)=[{0x0}, {0x0}, {&(0x7f0000000240)=""/90, 0x5a}], 0x3, 0x0}}, 0x10, 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x0)
r2 = dup2(r1, r1)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendmsg$unix(r1, &(0x7f0000000580)={0x0, 0xa, 0x0}, 0x0)


ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000080)=[{}, {}], 0x2})
r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_GETPARAMS(r0, 0x80105727, &(0x7f00000000c0)={&(0x7f0000000200)=[{}, {0x7}], 0x2})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x6, &(0x7f0000000340)=[{0x25, 0x0, 0x3}, {}, {}, {}, {0x25}, {0x6}]})
write(r0, &(0x7f0000000200)="d81ad3d20cf7eb4e9be33bbd1a30", 0xe)


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
munlock(&(0x7f00003e1000/0x1000)=nil, 0x1000)


open(&(0x7f0000000040)='./file0\x00', 0xfffe, 0x0)
setreuid(0xee00, 0x0)
chmod(&(0x7f00000000c0)='./file0\x00', 0x21e)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000000c0)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000000)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000080)=0xc)
chown(&(0x7f0000000100)='./file0\x00', 0x0, r1)
r2 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r3 = dup(r2)
faccessat(r3, &(0x7f0000000040)='./file0\x00', 0x2, 0x0)


r0 = socket(0x11, 0x3, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x40, &(0x7f0000000000), 0x3)


sysctl$vm(&(0x7f0000000380), 0x2, &(0x7f0000000340), 0x0, &(0x7f0000000240), 0x0)
open(&(0x7f0000000040)='./file0\x00', 0xfffe, 0x51)
r0 = socket(0x18, 0x0, 0x0)
shutdown(r0, 0x1)
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000280)=[{0x0}], 0x1)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000540)={<r1=>0xffffffffffffffff})
ioctl$VMM_IOC_RUN(0xffffffffffffffff, 0xc0205602, &(0x7f0000000300)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000040)={{}, {[], [], [], [], [], {}, {0x0, 0x0, 0x0, 0x9}}}, 0x0, 0x7f})
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x2}, 0x4, 0x0, 0x0, &(0x7f0000000280), 0x4)
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000100), &(0x7f0000000180)=0xc)
r2 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
socket(0x800000018, 0x1, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000132000/0x3000)=nil, &(0x7f00001bf000/0x3000)=nil, 0xc0400000}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f0000001000/0x2000)=nil, &(0x7f0000093000/0x1000)=nil}, {&(0x7f0000334000/0x1000)=nil, &(0x7f000008a000/0x3000)=nil}, {&(0x7f0000066000/0x1000)=nil, &(0x7f0000133000/0x1000)=nil}, {&(0x7f000008a000/0x4000)=nil, &(0x7f000013e000/0x2000)=nil}, {&(0x7f0000323000/0x4000)=nil, &(0x7f000002a000/0x3000)=nil}, {&(0x7f000008d000/0x4000)=nil, &(0x7f0000089000/0x4000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000027000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffa000/0x4000)=nil}, {0x0, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000249000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000100000/0x5000)=nil, &(0x7f0000092000/0x3000)=nil}], './file0\x00'})
openat$vmm(0xffffffffffffff9c, &(0x7f0000000800), 0x0, 0x0)
ioctl$TIOCCONS(0xffffffffffffffff, 0x80047462, &(0x7f0000000240)=0xc)
syz_open_pts()


semget$private(0x0, 0x1, 0x220)
sysctl$net_mpls(&(0x7f0000000000)={0x6, 0xb, 0xfffffffe}, 0x3, 0x0, 0x0, 0x0, 0xfffffffffffffe64)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
openat$vmm(0xffffffffffffff9c, &(0x7f0000000100), 0x1, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000004c0)=[{0x2c, 0x0, 0x0, 0x8}, {0x3d, 0x0, 0x11}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])
pipe(&(0x7f0000000000)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
poll(&(0x7f0000000080)=[{r1}], 0x1, 0x101)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r3=>0xffffffffffffffff, <r4=>0xffffffffffffffff})
r5 = dup(r4)
writev(0xffffffffffffffff, &(0x7f00000002c0)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe2c63a56077123a276d3ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
r6 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r6, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r6, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{0x5c}, {0xc}, {0x40e, 0x0, 0x0, 0x3}]})
syz_emit_ethernet(0xe, &(0x7f0000000100)=ANY=[])
mkdir(&(0x7f0000000080)='./file0/file0\x00', 0x0)
rename(&(0x7f0000000080)='./file0\x00', &(0x7f00000000c0)='./file0\x00')
recvmmsg(r5, &(0x7f0000000440)={&(0x7f00000000c0)={0x0, 0x0, &(0x7f00000006c0)=[{0x0}, {0x0}, {0x0}, {&(0x7f0000000340)=""/87, 0x57}], 0x4, 0x0}}, 0x10, 0x64, 0x0)
dup2(r3, r4)
writev(r4, &(0x7f0000000080)=[{&(0x7f00000003c0)="ae", 0x1}], 0x1)
shutdown(r5, 0x2)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
execve(0x0, 0x0, 0x0)
ioctl$WSDISPLAYIO_GBURNER(r2, 0x400c5752, &(0x7f00000001c0))


openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f0000000c80)={&(0x7f0000000c40)={0x0, 0x0, &(0x7f0000000bc0)=[{&(0x7f00000000c0)=""/67, 0x43}], 0x1, 0x0}}, 0x10, 0x0, 0x0)
r0 = socket$inet(0x2, 0x3, 0x102)
sendmmsg(r0, &(0x7f0000000c40)={&(0x7f0000000c00)={&(0x7f00000002c0)=@in={0x2, 0x3}, 0xfffffffffffffc46, 0x0, 0x0, 0x0}, 0x10}, 0x10, 0x0)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x8981, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000100)={&(0x7f0000000080)=[{}, {0x6}], 0x2})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000180)=[{0x34, 0x0, 0x0, 0x40000000}, {0x1c}, {0x6}]})
syz_emit_ethernet(0x7e, &(0x7f00000002c0)=ANY=[])


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x0, 0xffffffffffffffff)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
poll(&(0x7f0000000180)=[{r0, 0x1}], 0x1, 0x0)
select(0x40, &(0x7f0000000040)={0xffffffffffffffff}, 0x0, 0x0, 0x0)


sysctl$kern(&(0x7f0000000040), 0x4000000000000379, 0x0, 0x0, 0x0, 0xfffffffffffffed2)
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_DEL_MFC(r0, 0x29, 0x69, 0x0, 0x0)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x461, 0x0)
fcntl$getown(r0, 0x5)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1000300000001, 0xffffffffffffffff})
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc1206951, 0x0)
ktrace(0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f00000000c0)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x2, 0x0, 0x1b}, 0x4, 0x0, 0x0, &(0x7f0000000200), 0x0)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
r0 = socket(0x18, 0x2, 0x0)
r1 = socket(0x18, 0x2, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = dup2(r0, r1)
setsockopt(r2, 0x1000000029, 0x23, &(0x7f00000000c0)="b211d7170d816684c8e360f2fa41c1a0946988b272d2dd3dc90142a84231a746e337b372e93320cff6669cbe7868de45ed3fc33719ca6df71ecec8a918458b2c10a1f8c66653b276e7aae9cb9b21f9982230f575295d48889c9a920796b2dd92fc8575680b37ba955d2c15e6d7c9198ed900ab006ddfb67869b51a2216114d1ece85f593e74035f5bc054eb1dbddf42a", 0x90)
sendmsg(r1, &(0x7f00000002c0)={0x0, 0x0, &(0x7f0000000900), 0x0, 0x0}, 0x0)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg$unix(r1, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="28000000ffff000001"], 0x28}, 0x0)
recvmsg(r0, &(0x7f0000000780)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x42)


mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x2000, 0x0)
unveil(&(0x7f0000000280)='.\x00', &(0x7f00000002c0)='c\x00')
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x1}, 0xc)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1000100000001})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000340)={0x3, &(0x7f0000000240)=[{0x40}, {0x45}, {0xe6}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f0000000200)='./file0\x00', 0x102, 0x0)
r1 = getpid()
fcntl$setown(r0, 0x6, r1)
fcntl$setown(r0, 0x6, 0x0)


r0 = socket(0x2, 0x2, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x205310)
r1 = open(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)
poll(&(0x7f00000001c0)=[{r1, 0x46}], 0x1, 0x0)
poll(&(0x7f0000000140)=[{r0}], 0x1, 0x0)


r0 = socket$unix(0x1, 0x2, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b8", 0x1}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
getsockopt$sock_int(r0, 0xffff, 0x2000, &(0x7f0000000200), &(0x7f0000000000)=0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000480)={0x3, &(0x7f0000000200)=[{0x4c}, {0xc}, {0x6}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f00000000c0)=[{{r0}, 0xffffffffffffffff, 0xb7c61f5c345976d}], 0xc, 0x0, 0x0, 0x0)
kevent(r1, &(0x7f0000000180), 0x81, &(0x7f0000000200)=[{{r0}, 0xfffffffffffffffc, 0xe1}], 0x8, 0x0)
r2 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
dup2(r2, r1)


socketpair$unix(0x1, 0x0, 0x0, 0x0)
sysctl$net_inet6_icmp6(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
chdir(0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x2}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x33}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x1, &(0x7f0000000080)="0315f1d89ec5a317a9357682", 0xc)
setsockopt$inet_opts(r0, 0x0, 0x1, &(0x7f0000000240)="ea000001", 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000040)=[{0x1c}, {0x7c}, {0x1416}]})
syz_emit_ethernet(0x4e, &(0x7f0000000140)=ANY=[])


sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r0, 0xc2485607, &(0x7f0000000100)={0x2, 0x0, 0x9, 0x0, 0x0})


openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
getuid()
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0xf8e, 0x0)
r1 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r1)
r2 = socket(0x11, 0x3, 0x0)
sendto(r2, 0x0, 0x0, 0x0, &(0x7f0000000040)=@un=@abs={0x0, 0x0, 0x1}, 0x8)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000000), 0x2cfea}], 0x1000000000000013)
mknod(&(0x7f0000000000)='./bus\x00', 0x3a0914c44f7b202d, 0x0)
r3 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r4 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r4, 0xc0106924, &(0x7f00000001c0))
r5 = kqueue()
kevent(r5, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
setreuid(0xee00, 0x0)
r6 = getuid()
setreuid(0x0, r6)
r7 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r7, 0x802069b5, &(0x7f00000001c0))
ioctl$TIOCSETAF(r3, 0x802c7416, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x0, "247497496ed3ffa429fdb9102575e414229eb682"})
execve(0x0, 0x0, 0x0)


setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000000)="ebffff132f", 0x5)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x2, &(0x7f0000000200)=[{}, {}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x3, 0x0)
connect$unix(r0, &(0x7f0000000000), 0x10)
r1 = dup(r0)
setsockopt$inet_opts(r1, 0x0, 0x15, &(0x7f0000000080)='\x00\x00\x00\x00', 0x4)
write(r0, 0x0, 0x0)


setitimer(0x0, &(0x7f0000000200)={{0x0, 0x9}, {0xffffffff}}, 0x0)
getitimer(0x0, 0x0)
setitimer(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000240)=[{0x14}, {0x1d}, {0x8106}]})
syz_emit_ethernet(0x3e, &(0x7f0000000180)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000280)=[{0x7c}, {0x35}, {0x9106}]})
syz_emit_ethernet(0x4a, &(0x7f0000000000)=ANY=[])


ioctl$WSDISPLAYIO_SMODE(0xffffffffffffffff, 0x8004574c, &(0x7f0000000040)=0x2)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x2, 0x0)
r1 = dup(r0)
setsockopt$inet_opts(r1, 0x0, 0x13, &(0x7f0000000040)="fd0cc085", 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000200)=[{0x1}, {0x6c}, {0x806}]})
syz_emit_ethernet(0x36, &(0x7f00000001c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000680)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f00000000c0)=[{0x1c}, {0x84}, {0x26}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


open(&(0x7f0000000100)='./file0\x00', 0x70e, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x520, r0)
r1 = socket(0x800000018, 0x1, 0x0)
r2 = socket(0x800000018, 0x1, 0x0)
bind$unix(r2, &(0x7f0000000080)=@abs={0x0, 0x7}, 0x1c)
bind$unix(r1, &(0x7f0000000080)=@abs={0x0, 0x7}, 0x8)
select(0x40, &(0x7f0000000500)={0x3fc}, 0x0, 0x0, 0x0)
r3 = kqueue()
kevent(r3, &(0x7f0000000000), 0x400, 0x0, 0xdb74, 0x0)


sysctl$net_inet_ip(&(0x7f0000000080)={0x4, 0x2, 0x0, 0x5}, 0x4, &(0x7f00000000c0)="bfd038e0", &(0x7f0000000180)=0x4, &(0x7f00000001c0), 0x0)


open(0x0, 0x0, 0x0)
getppid()
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
sysctl$hw(&(0x7f0000000000)={0x6, 0xb}, 0x3, 0x0, 0x0, &(0x7f00000001c0), 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000540)={0x3, &(0x7f00000001c0)=[{}, {0x61}, {0x8106}]})
writev(0xffffffffffffffff, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sysctl$net_inet_divert(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r1 = socket(0x18, 0x1, 0x0)
r2 = socket(0x18, 0x3, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r2, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
unveil(&(0x7f0000000000)='./file2\x00', &(0x7f0000000040)='c\x00')
unveil(&(0x7f0000000140)='./file0\x00', &(0x7f0000000180)='x\x00')
unveil(&(0x7f0000000280)='./file1\x00', &(0x7f00000002c0)='c\x00')
r3 = socket$inet(0x2, 0x2, 0x0)
r4 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
setsockopt$inet_opts(r3, 0x0, 0x200000000000b, &(0x7f0000000180)="33b62b53cc518098fb586f8654ccabac394a21176475c8d7abbfe85ea97a60556ed1667c65fed0fa826e806391cd8e9611cb35b5bf15aa52dbd36706438c08bb429a98cae4a5b7d9a392f26dd5293c0ff1f72ebc06c427cd49468f", 0x1)
unveil(&(0x7f0000000340)='./file3\x00', &(0x7f0000000380)='r\x00')
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000800)
open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x4, 0x0, 0x0, 0xfffffffc}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x27}, 0x2, &(0x7f0000000100), 0x0, 0x0, 0x0)
kqueue()
open$dir(0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCGDIRFILT(0xffffffffffffffff, 0x4004427c, &(0x7f0000000180))
openat(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = shmget$private(0x0, 0x1000, 0x0, &(0x7f0000ffc000/0x1000)=nil)
munmap(&(0x7f0000ffb000/0x4000)=nil, 0x4000)
shmat(r0, &(0x7f0000ffd000/0x1000)=nil, 0x0)
shmat(r0, &(0x7f0000ffa000/0x4000)=nil, 0x0)


socket(0x20, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x24, &(0x7f0000000140)="5ab7776a89fbe691f5dc4ba3b8a64e800b096303c860ecba5540261d1d4f7c51471b4798c620376b14690170dc082195b1c237c4d53699555ab679467a1b20c9934981e07203c70000000000", 0x4c)
syz_emit_ethernet(0x3e, &(0x7f0000000140)=ANY=[@ANYBLOB])
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
r0 = socket(0x18, 0x3, 0x0)
getsockopt(r0, 0x29, 0x32, 0x0, 0x0)
socket$inet6(0x18, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1008, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x1, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000001080)=[{0x80}, {0xc}, {0x6, 0x0, 0x0, 0xfffffff8}]})
socket$inet(0x2, 0x1, 0x0)
socketpair$unix(0x1, 0x3, 0x0, &(0x7f00000000c0)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
r3 = socket(0x11, 0x3, 0x0)
setsockopt(r3, 0x11, 0x3, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r4 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$BIOCGRTIMEOUT(0xffffffffffffffff, 0x4010426e, 0x0)
ioctl$VMM_IOC_RUN(r4, 0xc2485607, &(0x7f0000000040)={0x2, 0x0, 0x0, 0x0, 0x0})
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000001f80), &(0x7f0000000100)=0xc)
sysctl$net_inet_gre(&(0x7f0000000000)={0x7, 0x4}, 0x4, 0x0, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001880)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f00000003c0)="5080c5a97558d472b3d20fe4a61339bd547710cb16b1331906dee84e0746ad4a017eeafc6cd84f80da82744d47076311d447c0ad1580769294c53268547ffa2de45c1e30364fef08671030bb9ca9e5f071219824dbbffd53d83e2eded34241119e2dc17a", 0x64}, {0x0}, {&(0x7f0000000300)="7ea3f94ec9aea0cfec8e6958bff13adf333086d3c258d19367300f6a0a5398d749f0c24c3de285a28d9100e4532b0710cbce050e3162b8150acf29179cf07c3286e01de621182f7ed0229c571858cffb0e598a7b21d0621b7b", 0x59}], 0x3, 0x0, 0x0, 0x400}, 0xc01)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000080)={<r5=>0xffffffffffffffff})
sendmmsg(r5, &(0x7f0000001740)={0x0}, 0xfffffffffffffdf2, 0x0)
r6 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000380), 0x0, 0x0)
ioctl$VNDIOCGET(r6, 0xc4104603, &(0x7f0000001a40)={'./file0\x00', 0xfffffbf9, 0x3})
kevent(0xffffffffffffffff, 0x0, 0x7, 0x0, 0x0, &(0x7f0000000240)={0x0, 0x5})
r7 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r7, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)


open$dir(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r0)
socketpair(0x1, 0x1, 0x0, &(0x7f0000000140))
pipe(&(0x7f00000001c0))
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0xb32, 0x0)
r1 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r1, 0x0)
recvmsg(0xffffffffffffffff, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
r1 = dup(r0)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{0x2c}, {0x24}, {0x46}]})
syz_emit_ethernet(0x36, &(0x7f0000000840)=ANY=[])


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {0x0, &(0x7f0000363000/0x2000)=nil, 0x2000000000}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000191000/0x1000)=nil}, {&(0x7f000003d000/0x1000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f00000c3000/0x4000)=nil, &(0x7f0000ffa000/0x4000)=nil}, {&(0x7f0000157000/0x1000)=nil}, {0x0, &(0x7f00001eb000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f00000e0000/0x1000)=nil, &(0x7f00000d8000/0x3000)=nil}, {&(0x7f00000ca000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f00000f8000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r0, 0xc2585601, &(0x7f0000000000)={0x7, 0x0, 0x0, 0x0, 0x0})


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x0, &(0x7f0000000100)})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
write(0xffffffffffffffff, 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980))
mknod(0x0, 0x0, 0x0)
shmctl$IPC_SET(0x0, 0x1, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
setsockopt$inet6_MRT6_ADD_MFC(0xffffffffffffffff, 0x29, 0x25, 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
msgget$private(0x0, 0x0)
msgsnd(0x0, 0x0, 0x1f, 0x0)
open(0x0, 0x0, 0x0)
setsockopt$inet6_MRT6_DEL_MFC(0xffffffffffffffff, 0x29, 0x69, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000001200)={0x1, 0x9}, 0x2, &(0x7f0000000440)="06a3f7b9", &(0x7f00000001c0)=0x4, &(0x7f0000001340)="fa6b2e39", 0x4)


r0 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x138, 0x0)
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000100)={0x4, &(0x7f00000000c0)=[{0x7, 0x8, 0x3, 0x8}, {0x2, 0x1, 0x1f, 0x9}, {0x5, 0x3, 0x8, 0x9}, {0x5, 0x9, 0x20, 0x10001}]})
write(0xffffffffffffffff, 0x0, 0x0)
r2 = accept(0xffffffffffffffff, &(0x7f0000000140)=@in6, &(0x7f0000000180)=0xc)
mmap(&(0x7f0000ffc000/0x4000)=nil, 0x4000, 0x4, 0x1010, r2, 0x9)
r3 = syz_open_pts()
ioctl$TIOCGWINSZ(r3, 0x40087468, &(0x7f0000000a80))
openat$bpf(0xffffffffffffff9c, 0x0, 0x100c0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r4 = syz_open_pts()
ioctl$TIOCSETD(r4, 0x8004741b, &(0x7f0000000080))
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
bind(r0, &(0x7f0000000000), 0x10)


ktrace(0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000040)=[{0x1, 0x0, 0x0, 0x8}, {0x28, 0x0, 0x0, 0x800}, {0x6, 0x0, 0x0, 0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000300)=ANY=[])


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x6381)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
poll(&(0x7f00000000c0)=[{r0, 0x6e}], 0x1, 0x0)
select(0x7, &(0x7f00000002c0)={0xfffffffffffffffc}, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f00000002c0)=[{0xc0}, {0x4}, {0x6, 0x0, 0x0, 0x88f0}]})
write(r0, &(0x7f0000000280)="ce4aa4a25043cb02aadf8701f131", 0xe)


mkdir(&(0x7f0000000040)='./file0\x00', 0x0)
unveil(&(0x7f0000000280)='.\x00', &(0x7f00000002c0)='c\x00')
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x10001, "28b77c09b87aa57800080017d0d2000010001c00"})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x800000018, 0x3, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x18, 0x1, 0x0)
close(r2)
r3 = socket(0x18, 0x3, 0x0)
r4 = dup2(r0, r3)
setsockopt(r4, 0x1000000029, 0x2e, 0x0, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


mknod(&(0x7f00000000c0)='./file0\x00', 0x2000, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000540))
r1 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x2, 0x0, r1)
r2 = socket$inet(0x2, 0x2, 0x0)
r3 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x0, &(0x7f0000000080), 0x0)
dup2(r3, r2)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000240), 0x0)
setsockopt$inet_opts(r2, 0x0, 0xd, &(0x7f00000000c0)="ea001d0100004865f88ac400", 0xc)
madvise(&(0x7f000074c000/0x3000)=nil, 0x3000, 0x0)
mmap(&(0x7f0000400000/0xc00000)=nil, 0xc00000, 0x0, 0x1011, 0xffffffffffffffff, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000200)={0x0, 0x5, 0x7ff, 0x820351f, "1a0e4de6d30aa624d13e000002f9ffffff00"})
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000dc0)="accd938ff3f8c1cb68a96ce24fa3215ae3f23f6ec074a99c3067fce67683007555d75474dc27b205b892df904dfcbdb8a85e40c0c760eecaf17dcdbcb6bfc9be16d49836aa3c8decfa226ceb49187a08a5fa5cb4b4f5aa097dfb66297a40fb214d6ecaf6e75e566cf32def06eeb9a5769734cc32cb87eb6c9a20075e63632be5cf312d1b489bd181198bba3e89ab290861e75b8f29d91a9a260fd315ed5ccf4b8c528e18044f50f23625ad6a438262684f2ea7df09eaf3d9efc1e0f93eaa878ddf8f8fbc72556b0ed74138815ec05db3431d0b6b969bf397135b0191dfcbddd954a220638f53e8700fb4be45eed98b313d27c147d41413bdc26b34f7ea207197d96aff5dba1b4667d734fbcb2c42ed7e2dff6bf921b7d9f81523a7a7997123c1f08432aa780b3488eb7992032735f27a35ff4a0be33259fa4c5745d7154a30450ef70223b8170ae45613f0fef84dbf73fa7202352008c66f2d4dc2a5aba56593053474e987bd1e3e24f55bac9349f6198dd88c7ee90207dc610d7777f052c4378b485c40000000000000000147808b799e64a610ee1854ff981cad716ebf58332d97f4cbcdd956be069d6700f043d549c4c7a8173795bb97f1f2e5ddce84177c687dd8d713c0bbc3bb3eaa29d8ceeee24c070aeca398185a34f0e35d9b98b6d40257b77320e6be5d99604488e5baf58f87ed9610fa7de1971690f066ead45f052e44657ae04e30435aefcdd5bebcee4646920a580215d97873b8f3ba9707703df196d6e233b8d3498a3d7ef88e4acbbe89ec69e353f495c28c77cf04cbd2227f0056bcb6153d35d5f0ba307660965aaa95f84f2eb377818fac2d8cdd7576712e6b58959108c3c91e900463d9517839f486fef54052312a018ec716b690868965d9018228ae50feed53e50decccc8a73914b2fa625443cbb1f9040922a9a5c14c41ff5270026ce511b657e66b8843588fdd6924e0c6f04542081f176fa6eaa089feb972b29533fbe41131ee062a3d4f0d63c6d445cb41afc2b174e420c00c9b20aed3f27686c49f76be981cc82dccc6d11d9e29398daba0fde6448a4deacd1684b8610830370951f684725f3bf33c6378097d9557b106fb9b87dd513524ed63ce503086e348c3f5d2b61e3f819a27962db04602e4b975f055a74a9a313cac56365425df00f7aff526a15755a8586ef2850e543f2cc6cafc7ac3c94561b38758a27eaa0b0df01eab797acc9f23b7e075cee8869efc693dbe944ad3f1e10651e433153ed7ed5675d8d29affeb3eec8201be65230d655b074b4b4498bc2337fc0eb63016d6b27a5e2821c4e902016f6919bbbe443473", 0x3b4}], 0x1)
writev(r0, &(0x7f00000000c0)=[{&(0x7f00000009c0)="a3edc594e259cee99c7b369f8c140697af4361bbfa0ab6d0aa68750360838ce25fc4e2b657cfcb7f089d79f04eb507bc64f175e1eed9a836c6dd7e6655e1b075f28755602d17c464b466d287a196800c0e6ad73198f2866a7a1d7aec6e524f40ddaddd92bed81f9c73c7e7c3d6ca30b9943987b256090d023e3d48c1a071776492e7c1608fbc5c28b54dde269211b96966e9f92ac2a23ff6bd153f0c456b96094a2be0ea8db697a83d017335010dc3a150f1e684c005a7130b942403bcf9505180060b228291676bb46150c7383cba4d41a0ea4f3055b4c4f3faba33beb731e29e0ce861b286cc02b3ea19f88a5a9c020de43dad6f1e45d7f7f60aa4bf9cd3cf350a58b574da56aeec33e0dd73728cd148146cff7c65097c7dee5d9cb843ffa3833f27640ce8d89b428de319627df1875f85682d34a772de75744d47e676bfa7d308008d531946bdd07d576a6a44a6131e0ba3e79b3ecd566a0c043af5fd34bf459dac5af8179fd27bf994f41fb7cf2f12ff6bdc1e3160bcde3e6cce50cebfdc62d79437f8d84b85c797179844f95eff926a9a2b95110267df8a69e81274fc86030e06e2d0d01c7d639104ef4e815c0f1b1c8fc21df38f97b90ff492d8bc8efcb6108087123d3d6d2227467b200e42a1acd16fc991447fd8accf859019ddb376cc4aac7ae9319ebfdb7153531bb320dbd61c8f53d324c2275461ef943c9b87c8b96838ffae739557413030b43effd5b282596d163e8899783732ec3de664fe97ee3e643629ee763a4f6fef73fd5a80850739d5d79ada3b858e5de02ead142c48af427aa482faaf8b17c7866db3aa2e4718aead55fc06f5e9ab961239c4382d438e55ab2ffca1d67c9accc8fe44abcdde27baa00dde85f9fe975db0ecc3ea37d7cc8befba9226eec5ae531f5ba7f90486bae03ee919a94d3e0d1df845af085e136665f13cc2161d11d2b7bb02db99de76a37efa75342010f92b0123c3c86e1dcfd602df668d4dac24d040c34b9ce6becd39ffd220f98aa2cff1dc4a51916096c513183be5ae093af03711098af8055687a1eb6534ecae8e5056b98d7bf0a7a6f44eda87f9257aa1b14038d88d948bdeb36a3509a3ad2a2f3c1a92ef9b885d66dcef50a7556b884916392cedefe9c2c8d2a782216c460a877963517064212f52b5e11d8c7485ab50097657fb542795051d536bf76880424456d667a0d88fba6e91035f671ebb65876289551b7d1e094c8c7a8f6c881dd6f1b1ff0f58231350d8f38cd3f28bf3bff5437a979d2fcf42dffe97ee0a00000000000000000000000000000000000000000000000000000000006efc4a7ede6e2d760b167506c717791de200be4392b070fc70d59f187d84c4cebda77b7435729d356f3c3e4a9514c0bfd087c27af76ce91cd6f6ff7bbb1ce479f6153ffd0f1c3c", 0x3f7}, {&(0x7f00000005c0)="7475891395c965576f262715e4fca7b123f96dc200860fb436cbe2554b79bf7a630460c8ac72ec1afc73d18973b11a2b9563f80253f4ca1b0cc71405cd897ea4578e40935d647d576f45394728ef2761bf37dcd10b012a6383e54cb585a9228b00000000000000", 0x67}], 0x2)
writev(r0, &(0x7f00000000c0), 0x1)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
chmod(&(0x7f0000000080)='./file0\x00', 0x40)
writev(r0, &(0x7f0000000180)=[{&(0x7f00000001c0)='#!', 0x2}], 0x1)
writev(r0, &(0x7f0000000100)=[{&(0x7f0000000040)="20090000019c0a", 0x7}], 0x1)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


setreuid(0xee00, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000015c0)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000000)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000140)=0xc)
setegid(r1)
setgroups(0x0, 0x0)
r2 = getuid()
setreuid(0xee00, r2)
unveil(&(0x7f00000001c0)='./file0\x00', &(0x7f0000000200)='x\x00')


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f00000000c0)="b10005136000009f050000b10010000000000000cea10500fef96ecfc727d3357ae302b37b67ca1f2d61db7f4de57804be38164991f7c8cf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f4d335d223e7db3008b95665bc6fc2118000000720fd38bfbb770c1f5a872c881ea772ec5890405b3b9c2668396f4cd1257aea8c500002002fbfc0c2300008abfba0900000008e37f71a3f8343712051eeab71d89e000040381ecb664000000", 0xb1, 0x0, 0x0, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f00000001c0)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe1463a52077dc0d00003ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x0, 0x0)


socket(0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
ioctl$TIOCSTSTAMP(0xffffffffffffffff, 0x8008745a, &(0x7f0000000000)={0xffffffff})
r0 = socket(0x11, 0x3, 0x0)
setsockopt(r0, 0x11, 0x2, &(0x7f0000000000), 0x4)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{}, 0xffffffffffffffff})
setsockopt$sock_int(r0, 0xffff, 0x1002, &(0x7f0000000080), 0x4)
r1 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r1, 0x8040691a, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000300), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{0x4d}, {0x2}, {0x246}]})
syz_emit_ethernet(0xe, &(0x7f0000000380)=ANY=[])


open$dir(&(0x7f00000003c0)='./file0\x00', 0x400004000011830a, 0x0)
r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
r1 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
ioctl$SPKRTUNE(r0, 0x20005302, &(0x7f0000000280)={0x0, 0x8bd9})
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, r1, 0x0)
execve(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000240)=[{0x3d}, {0x64}, {0x6}]})
syz_emit_ethernet(0x1019, &(0x7f0000000400)=ANY=[])


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
pipe(&(0x7f0000000000)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
dup2(r1, r0)


sysctl$hw(&(0x7f0000000100)={0x6, 0x13}, 0x2, 0x0, 0x0, &(0x7f0000000280), 0x0)


sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x19}, 0x40000000000000b8, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$net_inet_tcp(&(0x7f0000000040), 0x4, 0x0, 0x0, 0xfffffffffffffffe, 0x4)


mlockall(0x0)
munlock(&(0x7f000000f000/0x2000)=nil, 0x2000)
mlockall(0x0)
munlock(&(0x7f000000f000/0x4000)=nil, 0x4000)
openat(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
open(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
getpid()
ktrace(0x0, 0x0, 0x0, 0x0)
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, 0x0)
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$VNDIOCCLR(r0, 0x80106468, &(0x7f0000000b80)={0x0, 0x0, 0x0})
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x59}, 0x6, 0x0, 0x0, 0x0, 0x0)


mlock(&(0x7f0000ffa000/0x4000)=nil, 0x4000)
writev(0xffffffffffffffff, &(0x7f0000000080)=[{0x0}, {0x0}], 0x2)
sendto(0xffffffffffffffff, 0x0, 0xfffffffffffffce0, 0x0, &(0x7f0000000080)=@in6={0x18, 0x3, 0x0, 0x1ff}, 0xc)
socket(0x800000018, 0x1, 0x0)
r0 = semget$private(0x0, 0x7, 0x3c0)
semctl$GETPID(r0, 0x3, 0x4, &(0x7f0000000680)=""/8)
semop(r0, &(0x7f0000000280)=[{0x1, 0x7, 0x1000}], 0x1)
semop(r0, &(0x7f00000002c0)=[{}, {0x0, 0x3, 0x800}, {0x2, 0x204}, {0x4, 0x4}, {0x3, 0xfff8}, {}, {0x2, 0x7e7}], 0x7)
semctl$IPC_RMID(0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x81, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x1, 0x200}})
r1 = socket(0x18, 0x3, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r1, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
r2 = socket(0x2, 0x3, 0x0)
r3 = socket(0x18, 0x2, 0x0)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
dup2(r3, r2)
setsockopt$sock_int(r2, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
write(r2, &(0x7f0000001680)="04bdfa5d1d2873c63e3534825ba166e2fea9aec43050006123339a346f731573d8d508753f95b7688ad48b8cf6bbca325cebc37fc4e1dd543dbe2da6dd", 0x1001c)
mlock(&(0x7f0000ffb000/0x2000)=nil, 0x2000)


r0 = socket(0x18, 0x3, 0x0)
r1 = dup2(r0, r0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
kevent(0xffffffffffffffff, &(0x7f0000000180)=[{{}, 0xffffffffffffffff, 0x21}], 0x1f, 0x0, 0x0, 0x0)
openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000000), 0x80, 0x0)


r0 = socket(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x80606949, &(0x7f00000001c0))
ioctl$FIONREAD(r0, 0x8218694a, &(0x7f00000001c0))
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x14, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
sysctl$vm(&(0x7f0000000140)={0x2, 0x9}, 0x2, 0x0, &(0x7f0000000100), 0x0, 0x0)
getpgrp()
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000380)={0x3, &(0x7f0000000140)=[{0xb1}, {0x0, 0x0, 0xfe}, {0x6}]})
syz_emit_ethernet(0xa2, &(0x7f0000000600)=ANY=[])
openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x8981, 0x0)
r3 = openat$tty(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$TIOCSETVERAUTH(r3, 0x8004741c, &(0x7f0000000080)=0xa)
getgroups(0xffffffffffffff84, 0x0)
r4 = semget$private(0x0, 0x4000000009, 0x82)
getegid()
semop(r4, &(0x7f0000000140)=[{0x4, 0x3, 0x1000}, {}, {0x4, 0x201, 0x1000}, {0x3, 0x1000, 0x1000}, {0x0, 0x7a5}, {0x3, 0xff72, 0x3800}, {0x1, 0xdb, 0x800}, {0x0, 0x0, 0x800}, {0x3, 0xa, 0x1000}], 0x9)
getrlimit(0x7, &(0x7f0000000200))
semctl$IPC_RMID(r4, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
syz_emit_ethernet(0x0, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x2100, 0x5f00)
r0 = open(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})


mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x2029ff)
open(&(0x7f0000000280)='./bus\x00', 0x0, 0x0)


r0 = syz_open_pts()
ioctl$TIOCSTOP(r0, 0x2000746f)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f00000000c0)={0x0, 0x0, 0xfffffffe, 0x0, "030000a63f000000000000380700000085c6e5ff"})
syz_open_pts()


syz_emit_ethernet(0x56, &(0x7f0000000080)={@local, @empty, [], {@ipv6={0x86dd, {0x0, 0x6, "fa5c00", 0x20, 0x0, 0x0, @local={0xfe, 0x80, '\x00', 0x0}, @local={0xfe, 0x80, '\x00', 0x0}, {[@hopopts={0x0, 0x2, '\x00', [@pad1, @enc_lim, @jumbo, @jumbo]}]}}}}})


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r1 = fcntl$dupfd(r0, 0x0, r0)
write(r1, &(0x7f0000000140)='p', 0x1)
poll(&(0x7f0000000200)=[{r1, 0x4}], 0x1, 0x0)
select(0x40, &(0x7f0000000000)={0x9}, 0x0, 0x0, 0x0)


flock(0xffffffffffffffff, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
ktrace(0x0, 0x0, 0x0, 0x0)
r0 = openat$null(0xffffffffffffff9c, &(0x7f0000002f40), 0x0, 0x0)
readv(r0, &(0x7f00000002c0)=[{0x0}, {&(0x7f00000000c0)=""/120, 0x78}], 0x2)


socket(0x2, 0x2, 0x0)
shmctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{0x3, 0x0, 0xffffffffffffffff, 0xffffffffffffffff}})
r0 = kqueue()
kevent(r0, 0x0, 0x0, 0x0, 0x7, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x26}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
kevent(r0, 0x0, 0x0, 0x0, 0x9, &(0x7f0000000040))
kevent(r0, &(0x7f0000000000), 0x29f, 0x0, 0x8001, 0x0)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b1000502000000000000000001010000331c13fecea10500fef96ec0c72fd3355ae30200004e3003000000acf20b7804bec256699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5aa0400210000008700361b4cc702fac500002021fbfa0c0f00008abf3a2271a3f834371205d3660400"/177, 0xb1, 0x0, 0x0, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
r3 = socket(0x2, 0x2, 0x0)
r4 = socket(0x2, 0x4001, 0x0)
r5 = dup(r4)
r6 = fcntl$dupfd(r5, 0x2, 0xffffffffffffffff)
close(r6)
r7 = socket(0x2, 0x1, 0x0)
connect$unix(r7, &(0x7f0000000000), 0x10)
connect$inet(r3, &(0x7f0000000000), 0x10)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000200)="8b8c7e5e4a7966dfcde82b0abb", 0xd}], 0x1)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0x400, 0x0, 0xffffdffc, 0xffffffbf, "ff000000000000000100"})
close(r0)
poll(&(0x7f0000000040)=[{r1, 0x1}], 0x1, 0x0)
close(r1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000003c0)=[{0x64}, {0x25}, {0x6}]})
syz_emit_ethernet(0x62, &(0x7f00000006c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCVERSION(r0, 0x40044271, &(0x7f0000000040))
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000001080)=[{}, {0x4c}, {0xfffe}]})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
setregid(0x0, 0x0)
fchown(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f00000001c0)=[{0x2d}, {0x74}, {0x6}]})
syz_emit_ethernet(0x1019, &(0x7f0000000400)=ANY=[])


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x0, &(0x7f0000000400)})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
rename(0x0, 0x0)
rename(0x0, 0x0)
syz_emit_ethernet(0x1db, 0x0)
sendmsg(0xffffffffffffffff, 0x0, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x2000000000, 0xffffffffffffffff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
socket(0x18, 0x2, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendmsg$unix(r0, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


sysctl$kern(&(0x7f00000000c0)={0x1, 0x55}, 0x3, &(0x7f0000000100)="82f91e3471ac0058bc5a91501d400000005f84cf6fd2dc448a25952e", &(0x7f0000000000)=0x72, 0x0, 0x63)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f0000000100)={&(0x7f0000000000)='./file0\x00', 0x80000001, 0x0})


sysctl$kern(&(0x7f0000005680)={0x1, 0x34}, 0x2, &(0x7f00000056c0)="8f45277c", &(0x7f00000057c0)=0x4, &(0x7f0000005800), 0x0)


socket(0x11, 0x0, 0x0)
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x10205b1a)
sysctl$kern(&(0x7f0000000040)={0x1, 0x44}, 0x3, 0x0, 0x0, &(0x7f0000000180)="76b0353a558bf248c78c8502fcf9fd08fa1588f254df98bdc2703864ecc0ce3671c0907259201eb7cb962ee12d9706a2d4177565da48e3cdade50516597f477ca5ea18253c1441678346ddaa98e46b28e2226a296c0fd773959eaad9d65d33cdbf523a06ed457ed3e00f52851f90c14f54ec03a2a5ff8d88b9", 0x79)
r0 = open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x205b9a)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
readv(r0, &(0x7f0000000380)=[{&(0x7f0000000200)=""/84, 0x54}], 0x1)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{}, {}, {0x6, 0x0, 0x0, 0x3}]})
socket$inet6(0x18, 0x0, 0x29)
socket(0x0, 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x1, 0x0, 0x0)
getsockopt(0xffffffffffffffff, 0x8, 0x2b, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x80, 0x0)
open(&(0x7f0000000100)='./file0\x00', 0x40, 0x40)
ioctl$BIOCSETIF(r1, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x1, &(0x7f0000000080)=[{}]})
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r2=>0xffffffffffffffff})
setsockopt$sock_int(r2, 0xffff, 0x20, &(0x7f0000000080), 0x0)
syz_emit_ethernet(0x52, &(0x7f0000000080)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa86dd60000000001c2b00fe350e28ef0900c08cfe24be00000000fe8000"/50, @ANYRES32=0x41424344, @ANYRES32=0x41424344, @ANYBLOB="d8f74e28"])
r3 = socket(0x18, 0x2, 0x0)
sysctl$net_mpls(&(0x7f0000000140)={0x4, 0x21, 0x3}, 0x3, &(0x7f0000000180)="d2c686312aee42798b19a2f8d8e168a39c6515ec501b24d09bfad365514c93c8ddd8bff3ea97f402d528fd5c9369627e4932dddef2d5e5d2c7f57efc0bd38d7ba022178911edfebe823ff75a630e21a8850677b120a9f0b72be2f205d398411cc2bb9d5dc00859bdc411f04374e2113f624c665f65cf9b1cc357c4999d3edb2868e82583dca2d666ea5c1977b15dd5b940a1876952b6388aa293da1e66cab549a6887fc977706ac6a88e857d155349af9727dca3480d0b087efeddb955c751f3337d452993002e56018eea3b679220b320f80ea5739f0da59e17ea65ee1bd8f7870ca9d43efc2f3425970a2028845503a17402988484e9d283ee81f2a8960a0ebfbd155b67d44e3a14581068a2b807f6a6d74345c4a52ebee8953c493ae505809399d2a1fc84f445006f84545fb148d95ce4ccceefb6e39e3d02870f39dc2e4ed11ae66de97ada1756e044bd41256e7acd59b5287091a5d8b0755c0bff4f23e970c2f1041b02d09fa07245027cb9f1f95c573b37336f6dd918a34534ff6251a2d877016a449f87334b6911f2858b4d1eefb221e5be381740891007b7a1d5ac118102ac1ffe4dbff93deef0db024539fd7e6720ea2c823c872815934ea81b38f4147d49c61b6fba85d2bb9b8977c9195090a543d8180df3fa91ad8e252eaf75add42a2a849db55db767e71321403a9cae24801cead1d47e117f1dc76825847e37b0c36a1a5953ab3e7052e7415ca48d60ef1025b88bc21c4bcfb29caea4b7158defc329d66eb032119cabbc07bd05baf7ce92f7bf4fa3f8f06a92e8b96bc9524594bab84e76d79d0860fd2e4d6d7e9ba489cf52ef9fc0b8fb0fe037b6d540414141538be017b30a30f1536d35ed67f2c04e85af412040d36b9974d8964f1081ced21c4a25ce2772430216ffd89e62e19bd4b655f33f29714f28ca651dc51207ee41073b33d2bcf69980806a6ac6c27e3117f9b4cdc9ee05eadb30f4c4734461fcb91cc4e0f28540019818580831b95a9b407addae95b78b7edc965539c753f28138b528207aee73dd57ab2540830468b64f5c937c3bd63f004a41057aecf5834237a349945b3c9a26a0049bddbc6f34155e8d67b327655b293c4d0b3d08ae97c0dd343ab8b9b9191ed9baed0441c46a3685fd699d757b55d0288711ab2296fc4203776735bc7ed71d8775b3103dc1cdf4ba97523cd25faa21f7e2f0d7e4778c5b629e2bb9c3eefbcc531f49da6edc37e81884984f864571f3c62e9ca81bf2e7855a2127abc61585d3db1dc8374797e9deb39eeb3adbb2c5af468a2539b4cdb0b3b6ba233e6e1a41c82f6c87a742348dd447f72fabc57895a70edc8c6ab9eaaceef409fdd0cf998da55c2032707d653ebe53f454f750605f58a4de4d586a835b331242e5214e1dead7e7ed88dbc41472e2335a9be759912ffdee5e63c7162f16e9b9fb7c92cafbcf7dee3b1c08bf25f202a9578d761697c3c23b335343f8f5634893a7538222e1ea2de4d8d6830721ff2766210c53c5acb4aacc67df1cb4b7723f60b0820652d332bcb73ca851e5bf4421c3206239093a90573b4fded995bcf87eb724b1ac8f7d9d1a73de234d7b71d87b6b8757b67ce039ca7ef0ceed92846926ac415a07ffb8570e9f823659aed5eab61851e1774ebe05f066c3d634019adc7e996bed611279bb26ad75d793b750713a8208a9c3ff261650a867225de78475cf28d2d7475fcfa887fa7c1279d1acaafa74a34a1e10a305271a34b68280ff3310db9e19231fc2a4626fa4b6ecba4c1f30e96735254bbf6c13a14d0a4eedcc02b3e96f8d6da34f2bb07e58c8298994612de36dc84581d0e5aaade2ff904d2121ac1f6e3880fc56985cdb943b85fd5390a4c37156e839ae5fc7c43a119ed6f9a337dd8e42874138890b55f2a862211c6dc29cf32dbddc92d37dfebdb6944669027cc50db4bd75a461315cd62c9a48c9d2560b1fd8d811eaa6da687f1c2cfc1232b5afa63f107096fe12856cf510b2fcbaef2315ded08355898095b02e59f0aa18ee2e7f869df526dc8d651ad314f5ce8e9615eca7bfc0bc9bb2089e4cbc0b43abd3d8adc26db1faf26a70f241913a1e6c8d53c0225d8dd0c36fb596252d6cb932041c9c4e11339676e044e26cfe196adde7afc6d8f5d5e572eaec95de6bb96affd5eb0da6a43f8c879c8029f54d827ba14aaa191b52e539f63a8c0ac2821335835636e13e98df0f7642cae0537df58be075a0736689e15baf3d3a29eca6085887a2e6a892a406248547b44d15d6b348dcd79279759b197136776ab8b9be92370627be1886f8b9ab0fc1b91bc576ba396cabd35283cb5439669c64af192590ac1265fe5fa1fab9fc188bb33f02234efb3a98d7bcf905bd2540cb7a6489a9c7253c1a9fa51b31a3b51241bc3e01141834ccdb0f90b990d8867e17dd43f369d1ed4c46bbc699373d5ed70e912cebc82de3bf165b30643e4debc5715b3ee0d316a44518cfaec72216e4df62f2ebf0d30357704a55fd139dd03987dda31b176d98f5e877529c28ea6f910b1f60c42895bb2aa482dd95d0a5ca55dc3003a386dcd1f84ac91d81607a228ec0f1b69f83942fbe30f8f981ff4e3be43690778162d47c299bbb13ba96864c85be1ee2f116a7f22789710a1ccdde6472372795bf9c02a3b5fcc5461fe619eb4421b4d032e24352f364ea95875d07c89e56bda4b9ab1297dbe58b1a0cd38022ed954231a03416792050d5d75548dba919c3ddc5c5ddd81df133182719433b3e463196bd22c7aac635e8d80ecd63f8c3773310ff73d3487d1ab191e8c44d2e3439b7daed0ade3c33a3445865939eaa22e4393f8dae58e7da60996ebd9b41d5d44cfe4ade504f92d0d093682dae7f4a779f6474132044e07d1b459ecadc9b09c4acc6edf7772f0c3b268cfd63fa5ce9a60a4414bdad8033d966fe7d309f0282a0bdbf4c224534c0fb3e869e8a3fdfed4be5fe7587dcccf04d61c24d95489233e5b2c57b73e37f7b3e5a104b82ecb06c6bbe70aab3c15ccf12f1fd747eb0c00c6aec0eb7508a0d1f7e4400a6df6172cc52e27faebe93b5f678d64a9bcbd31f3d163ee1209ef836a19e785086fe8095b4dcd12bd06c1e463d6f01c3367d6afa4eff2f61782ada9b9021f9c8c5919db45dac74be9b4f77e15ae1cd5ca6f094c51ca4d339ec2cc4e98d82eac684e46c8fa2689bd61c8a06306fe8450942b7068e58a73b70ec7f8fd1a6e315f9702bb6a0fefa151878af67f916b80ceb330e49df23008ae121b315345d154af7552e836c739042c3a430eae100fa876c48c3fc3199487e19d540a975ae16987d5aae94de506d662f1a8b02194a644156554c5261f5d22a48f06177afcf47bdab184aa8e6626c6c8f69968a50177127d263e8aad61ffd77ddd06edc5617fab774da094f558b62471d115ad767de17c90e1d2840dc955b12d3354d4228e4b4a9cf431dca225b224dce58a100cdb3cb3a3364419506e13a9af00ec182c53965f872cd534a485ec13656f637c6dd3e461dbf0fe578b7a0a2cd288fce31ba334e46b7f12d4e9c8dbbfa91dda5d7d781696776e190b7ecb190fede08bcbf1da98f381ae09700e138716a1836b15c68ee98162e208a6ff1df452bacd59b7712c04ca0e5f9007242a39a349be095865db278c6dbe0197cb2a0ad471db0ae0f2614a43ee0d1db62a7547e81bda6839991500fb0073af5ef69b39d6bb10e6bda95e91bf8aa8404cc9dd995379e5c11a5582deb8d5c76f4e6b2aa0f335986e1c6978c3efe24355d44947d2a418b9b7eef0f307df935a47a0cd1f64922933f578f98631c9d67985d072e277b59885a111932754677f6648cb0fd070de7c8423c217c0c0edc85b650f102729fab44a4cf1e52d82b626df17d1357b24bcfeda68144e55c8346c39e7157450a82217ce7238327320a98e282c54d8bb3cc9c1b2fd6dc7975f9baee7461266cc983bbce4a2602fc8cab536f984a914ee067d3e343104ded89e760dbbfbe3fcc9d5304c6fb4c7cd1f48da847d58ec68fe777d321c7a57e14df9d3e4bbf4da91e1a3b8464a7b7de7e0f5aad8097d86aba4e8fee6e3d36553f7465082032f096ee64c9b5e4607665f14ef6062cb9cde3ef9e637758527145036d77e3e28bf9615a42edd2d78a71c2c69114ab46e8328fdedcfb4317cc44f39e26c8fa53e338585c3f5c783d1e4270dafda473f3b3eabffd0051c34ae9d2c1e97a33f28f410c73136a749c515ecd8c38ee33e03f6d602711ffea7d7cb38026354c8f9f3c7741d39ebaf968e1487ee923fd259164ecde4deca01d5557c9294b68dcdcd9dcff4de7a8ad009bf5bd30a39044af2d1f2f0a6807a66373ca90cdec3b61851e20c2e392f00f16bdca1a09ee8c33a6a670c13876df6f6b7c93942d06b01f3a459a75232b544be108b1c69f7d007e47131fdc773a5baf181a8c2066d4880e47748d1897b9a22cb9a82420999f43d78a9329aba1e175338f758b80d888253defdcff2d2b108689d2fe58edd8cff87b3452c3fc07ac02078a0a82869a97d76bd0f47d224ad9e35c5db9ea9b65d543add6d03448d3a20cfaab0d86a8f9d85af5f54ff7f78088989238ef1f5b8f2aeed50790688427be1d229ece223224641977ec58169cb2f5a43b417619faa39056b345c543b78312c9e7dc8da838d7164d409b8c2ac2f30d7467faa5b069e35cc1ae53d23d68b04beeb695c8dd31deacaf9e2035e36f200cdba751a81899ae20c466c4f2109ed63a453cdf04644c5fef4b0f7a6a45e1187d806190e863b6185539bbb81dc75fc2afde20e7fd3787a318f2fa3935888102e303de6be764b22363613361b70dd8aae69a0aff9ceb356d86282b386653e7ea6e7fc9375671d8fda97cb3e636b18ef3bbf7fd5df3c6fd6cedaf95ba7f1210a526c73d8ceeb2396419a73118518c558d0428734accf621f0a549a9b5f70325dfc106d5af8f6efc0dea2751fb2108c5db6f26fc0a914291a1939865b8ea1b62e681010bf4765993f5ebf62d233340482b90d1a07f59425ded41b61fad99a87b0fe052256019aceba9b113f2b38f401581f10dc52b458f822acdd6f5a0e2144adbc3b56352e627aabe179be27f5fa34496320cc524cd5c98c0e46c54060069517175f53fa4c04ce23582ed70a1df56242f051d9db7e7b28d0280311694941d15466b5cdebcddba682a335da228586592ea098a66523578329f5fc5e651827af06a9bf6b1c7c9b7f524fabacfd1a9278b5ecaddeb45cbeb9fdfadc9b7f881abd5b94806d9060eba657a6d6cf6a8da5b8a4a00d5df58180e190eec28eea6a669240f3031e21b6eec90c0347dd43cdfa2a50754f5964a3b0f46853228162dfb4f34d562f9f8fb627f1a609a0eccb87ce6230ee8898b1577fcf32bcc56c722a0558b220fed2f5a69f4a83330ef8df0e2e17c1e1cdafd33e7c2a5c303a60941aa87c09d1a8446b54ba11fad18a3de8509673b09f9e5543175194b0fd78e873a96fc553a3b6d4e3b3dc7ff281697b21949b7ed643a5dd1cc4cf923f882c388fccca14a31a36d1843675096e9c32f85e8d2fdcd603521f1a6990e9815dad27ed80cc7869fc5b1dc0e6acf265263c689d96120512bb0d7d5b52c1516e56f09353a168a4008de2c6dd4a98203f4186981d5c0e16e859768eed63e965d7e6d68a52c315c5e6e4edf41c7bccb317d6f2089a6b37e140ba93a307e06a45a17e85fb53a90c78d13871d2dedbc130cf002e50f4cdf8a42efcc6056ebc15feb080f30c84ccb8d8c4ad5261579c8b1610dd2fe6f18ae", &(0x7f0000001180)=0xffe, 0x0, 0x0)
dup2(r3, 0xffffffffffffffff)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r4 = socket(0x11, 0x3, 0x0)
getsockopt(r4, 0x0, 0x1, 0x0, 0x0)
socket(0x6, 0x4, 0x3f)
syz_emit_ethernet(0x22, &(0x7f0000000140)=ANY=[])
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r5 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r5, 0xc0106924, &(0x7f00000001c0))


mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)


ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f00000000c0), 0x20, 0x0)
readv(r1, &(0x7f00000001c0), 0x0)
mknod(&(0x7f0000000040)='./file0\x00', 0x6000, 0xe02)
sysctl$net_inet6_icmp6(&(0x7f0000000000)={0x7, 0x2, 0x2, 0xa0000000}, 0x4, 0x0, 0x0, 0x0, 0x0)
openat$null(0xffffffffffffff9c, &(0x7f0000000040), 0x80, 0x0)
openat$pci(0xffffffffffffff9c, &(0x7f0000000080), 0x80, 0x0)
openat$wsdisplay(0xffffffffffffff9c, &(0x7f0000000100), 0x80, 0x0)
socketpair(0x10, 0x0, 0x9b, &(0x7f0000000440))
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000002c0)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000280)={0x0, 0x0, <r3=>0x0}, &(0x7f0000000240)=0xc)
setregid(0x0, r3)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
r4 = semget$private(0x0, 0x5, 0x0)
semop(r4, &(0x7f0000000100)=[{0x4, 0x72, 0x1800}, {0x0, 0x0, 0x1800}], 0x2)
r5 = openat$bpf(0xffffffffffffff9c, 0x0, 0x8082, 0x0)
ioctl$BIOCFLUSH(r5, 0x20004268)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r6 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r6, 0x80206916, &(0x7f00000001c0))
socket(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x2, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x5cda)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
r1 = syz_open_pts()
fcntl$lock(r1, 0x9, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1000300000000})
flock(r1, 0x3)
flock(r1, 0x1)
syz_open_pts()
syz_open_pts()
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000140)=[{0x20}, {0x2c}, {0x86}]})
r2 = socket(0x2, 0x1, 0x0)
dup(r2)
syz_extract_tcp_res$synack(&(0x7f0000000040)={0x41424344, <r3=>0x41424344}, 0x1, 0x0)
syz_emit_ethernet(0xa6, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x98, 0x0, 0x1}, @tcp={{0x2, 0x1, r3, 0x41424344, 0x1, 0x0, 0x13, 0x4, 0x2, 0x0, 0x233, {[@generic={0x2, 0xd, "96c729637cae4fa49c1558"}, @sack_perm={0x4, 0x2}, @sack={0x5, 0x1a, [0x4, 0x0, 0x40000001, 0xde5, 0x2, 0xffffffff]}, @timestamp={0x8, 0xa, 0xb018, 0x8}, @generic={0x4, 0x2}]}}, {"d1c2f0bfe2d0786ca28e44289f59aba04d62ff16e6bb47f1cd981d0cf5f225560531db5a3a6c3cb3d5ac50e0eec7423f3ef5e3c4a13f81f1"}}}}}})


r0 = syz_open_pts()
write(r0, &(0x7f0000000100)='@', 0x1)
mlock(&(0x7f0000ff9000/0x4000)=nil, 0x4000)
setreuid(0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x2, 0x0, 0x5}, 0x4, 0x0, 0x0, &(0x7f0000000100), 0x0)
r1 = dup(0xffffffffffffffff)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040))
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000240)={0x2, &(0x7f00000000c0)=[{0x1}, {0x6, 0x0, 0x0, 0x8002}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x2, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d", &(0x7f0000000080)=0xd, 0x0, 0x0)
fcntl$setstatus(r0, 0x4, 0x80)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000000)=0x8)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000180)=0x2)
execve(0x0, 0x0, 0x0)


r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7949)
writev(r0, &(0x7f00000003c0)=[{&(0x7f0000000380)='#!i', 0x3}], 0x1)
writev(r0, &(0x7f0000000100)=[{&(0x7f0000000040)=' ', 0x1}, {&(0x7f00000004c0)="407fb506fae6e1dec095983d06062ba449e33c9d068c415d513fc5af94da5b5062728d50e619fcf232780fb06b89234a8d2d104ac8be64b194806d43d0113e933db09cac75fefdba347c022783b3131ee835daee550378e4191b1e6926f46680b3ce713b148a0546bb942f3c1f1a0394dd0a", 0x72}], 0x2)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x10, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{0x40}, {0x81}, {0x8006}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


r0 = kqueue()
r1 = syz_open_pts()
kevent(r0, &(0x7f0000000640)=[{{r1}, 0xffffffffffffffff, 0x3f}], 0x8008, 0x0, 0x0, 0x0)
syz_open_pts()
kevent(r0, 0x0, 0x0, 0x0, 0x6c, 0x0)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{}, 0xffffffffffffffff})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r1 = fcntl$dupfd(r0, 0x3, 0xffffffffffffffff)
ioctl$FIONREAD(r1, 0x8004745d, &(0x7f0000000200))
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x8040691a, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000000c0)=[{0x7}, {0x5}, {0x8006}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x4f}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x4}, {0x2c}, {0x83c6}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f00000001c0)=ANY=[])


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x1, 0x0)
close(r1)
r2 = socket(0x18, 0x3, 0x3a)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r2, &(0x7f00000001c0)="00003226a4a90000", 0x8)


r0 = getuid()
r1 = semget$private(0x0, 0x7, 0x3c0)
semctl$SETALL(r1, 0x0, 0x9, &(0x7f0000000380)=[0x400, 0x1, 0x8, 0x6, 0xc65])
semop(r1, &(0x7f0000000100)=[{0x3, 0xe, 0x1000}, {0x4, 0x303}, {0x1, 0x8, 0x1000}, {0x3, 0x7f, 0x1800}, {0x2, 0x1, 0x800}, {0x2, 0x202, 0x3000}], 0x6)
semctl$IPC_RMID(r1, 0x0, 0x0)
r2 = msgget$private(0x0, 0x597)
msgrcv(r2, &(0x7f0000000500), 0x1008, 0x0, 0x800)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000000)={<r3=>0x0, <r4=>0x0, <r5=>0x0}, 0xc)
r6 = getpid()
fcntl$setown(0xffffffffffffffff, 0x6, r6)
msgctl$IPC_SET(r2, 0x1, &(0x7f00000003c0)={{0x6, r4, r5, r4, r5, 0x7, 0xfffc}, 0x2, 0x7ff, r6, r3, 0xff, 0x5e, 0x2, 0xffffffffffffff81})
getgroups(0x1, &(0x7f00000004c0)=[r5])
r7 = getgid()
msgctl$IPC_SET(r2, 0x1, &(0x7f00000000c0)={{0x86, 0x0, r7, 0x0, r5, 0x175, 0xfbfb}, 0x5ddf, 0x5, r6, r3, 0xb8, 0x10000, 0x9, 0x401})
msgrcv(0x0, &(0x7f0000002500), 0xbc, 0x2, 0x1000)
getgroups(0x4, &(0x7f00000002c0)=[0x0, <r8=>0x0, 0x0, 0xffffffffffffffff])
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f0000000300)={{0x1, r0, r5, r0, r8, 0xb9, 0x3}, 0xfffffffffffffffb, 0x3ff, 0x6})
r9 = getegid()
chown(&(0x7f00000001c0)='./file0\x00', r0, r9)
mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x4003487)
r10 = open$dir(&(0x7f0000000240)='./file0\x00', 0x0, 0x0)
renameat(r10, &(0x7f0000000200)='./file1\x00', r10, &(0x7f0000000280)='./file0\x00')
r11 = accept$inet(0xffffffffffffffff, &(0x7f0000000000), &(0x7f0000000040)=0xc)
symlink(&(0x7f0000000080)='./file0\x00', &(0x7f00000000c0)='./file0\x00')
sendto$inet(r11, &(0x7f0000000100)="ee598539830f398c120aaa3886579eea1b584580c33c758bdd0f4ff15f7c55a3f9d4360548a798a52648b63d4a43e6", 0x2f, 0x0, &(0x7f0000000180)={0x2, 0x2}, 0xc)
sendto(r11, &(0x7f0000000080), 0x0, 0x8, 0x0, 0x0)


mknod(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000040)=[{0x84}, {0x64}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


socket(0x2, 0x0, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x27}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)
r0 = socket(0x2, 0x4001, 0x0)
dup(r0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
setsockopt(r1, 0x0, 0xb, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r2 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0106924, &(0x7f00000001c0))


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x2}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x2c}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000003c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCPROMISC(r0, 0x20004269)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
r2 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCPROMISC(r1, 0x20004269)
dup2(r2, r1)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x10001, "28b77c09b87aa57800080017d0d2000010001c00"})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x800000018, 0x3, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000))
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x18, 0x1, 0x0)
close(r2)
r3 = socket(0x18, 0x3, 0x0)
r4 = dup2(r0, r3)
setsockopt(r4, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


r0 = socket(0x2, 0x4001, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
r3 = socket(0x2, 0x4001, 0x0)
r4 = dup(r3)
r5 = fcntl$dupfd(r4, 0x2, 0xffffffffffffffff)
close(r5)
r6 = socket(0x2, 0x2, 0x0)
connect$unix(r6, &(0x7f0000000000), 0x10)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
sendmmsg(r2, &(0x7f0000001600)={0x0}, 0x10, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000002200)={0x3, &(0x7f00000000c0)=[{0x64}, {0x1}, {0x26}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


mknod(&(0x7f0000000080)='./file0\x00', 0x6000, 0xe02)
r0 = socket(0x2, 0x1, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
open$dir(&(0x7f00000001c0)='./file0\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
recvmsg(r3, &(0x7f0000000340)={0x0, 0x0, 0x0, 0x0, &(0x7f00000024c0)=""/236, 0xec}, 0x0)
chroot(&(0x7f0000000740)='.\x00')
sendmsg(r2, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)


r0 = socket(0x18, 0x3, 0x55)
munmap(&(0x7f0000fff000/0x1000)=nil, 0x1000)
mlock(&(0x7f0000ffc000/0x3000)=nil, 0x3000)
sendmmsg(0xffffffffffffff9c, &(0x7f0000000180)={&(0x7f0000000140)={&(0x7f0000000000)=@un=@file={0x0, './file0\x00'}, 0xa, &(0x7f00000000c0), 0x0, 0x0}}, 0x10, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
open(0x0, 0x0, 0x0)
ioctl$TIOCDRAIN(0xffffffffffffffff, 0x2000745e)
openat(0xffffffffffffffff, &(0x7f0000000240)='./file0\x00', 0x20000, 0x100)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000140)={0x1, &(0x7f0000000040)=[{}]})
ioctl$FIONREAD(r0, 0x8080691a, &(0x7f0000000100))


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
pwritev(r0, &(0x7f0000000200)=[{&(0x7f0000000340)='T', 0x1}], 0x1, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000300)={0x2, &(0x7f00000000c0)=[{}, {0x2}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x33}, 0x3, &(0x7f00000001c0)="71f91e3471a9cf71b59c7a13c3708200000000000000000000000000e5ae232f3fabfe3d2e6d9512dbb57fdc6ace01fd7fbb1f7b2568f410315911bf52da3f488bc1f2a3e0cadb9eedf77c2c540716de919e923c57d69d484b81698ee9011d40f1844e4fca8e9d84ba99bc1797e279d8c3b94a7961c482003e2038819f8724ef1fbfc75d94c14d0a1541a9b58ef2f33b4739f874b20dcdbab4b8", &(0x7f0000000080)=0x24, 0x0, 0x37)


writev(0xffffffffffffffff, &(0x7f0000000080)=[{0x0}, {&(0x7f0000000040)="18", 0x1}], 0x2)
sendto(0xffffffffffffffff, 0x0, 0xfffffffffffffce0, 0x0, &(0x7f0000000080)=@in6={0x18, 0x3, 0x0, 0x1ff}, 0xc)
r0 = socket(0x800000018, 0x1, 0x0)
r1 = semget$private(0x0, 0x7, 0x3c0)
semctl$GETPID(r1, 0x3, 0x4, &(0x7f0000000680)=""/8)
semop(r1, &(0x7f0000000280)=[{0x1, 0x7, 0x1000}], 0x1)
semop(r1, &(0x7f00000002c0)=[{0x3, 0x0, 0x1000}, {0x0, 0x420}, {0x1, 0x2}, {0x0, 0x3, 0x800}, {0x2, 0x204}, {0x4, 0x4}, {0x3, 0xfff8}, {0x4}, {0x2, 0x7e7}], 0x9)
semctl$IPC_RMID(r1, 0x0, 0x0)
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f00000000c0)={{0x81, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x1, 0x200}})
r2 = socket(0x18, 0x3, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r2, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
r3 = socket(0x2, 0x3, 0x0)
r4 = socket(0x18, 0x2, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
dup2(r4, r3)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x8020699d, 0x0)
setsockopt$sock_int(r3, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
write(r3, &(0x7f0000001680)="04bdfa5d1d2873c63e3534825ba166e2fea9aec43050006123339a346f731573d8d508753f95b7688ad48b8cf6bbca325cebc37fc4e1dd543dbe2da6dd", 0x1001c)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892}, 0x1c)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x8000, 0x9)
getpid()
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
fcntl$setstatus(r0, 0x4, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000000)={0x6, 0xb, 0x2}, 0x5, &(0x7f0000000500), 0x0, 0x0, 0x0)
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))


syz_open_pts()
sysctl$vm_swapencrypt(&(0x7f0000000000)={0x2, 0x5, 0x1}, 0x3, 0x0, 0x0, 0x0, 0x0)
r0 = syz_open_pts()
syz_open_pts()
syz_open_pts()
fchown(r0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000140)={0x3, &(0x7f0000000300)=[{0x6c, 0x0, 0x0, 0x7}, {0x187}, {0x6, 0x0, 0x0, 0x3cf}]})
writev(r1, &(0x7f0000000200)=[{&(0x7f0000000280)="d4b7d60c5988049c34b79bbc713f", 0xe}], 0x1)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x40, 0x0)
ioctl$BIOCLOCK(r2, 0x20004276)
open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0xc0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
socket(0x1, 0x2, 0x0)
socket(0x0, 0x2, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x2, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
r4 = socket(0x2, 0x1, 0x0)
connect$unix(r4, &(0x7f0000000000), 0x10)


openat$pci(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x401, 0x0)
poll(0x0, 0x0, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x2802)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
ktrace(0x0, 0x0, 0x0, 0xffffffffffffffff)
r0 = open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206919, 0x0)
ioctl$FIONREAD(r0, 0x8020690c, &(0x7f0000000300))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000001c0)=[{0x61}, {0x45}, {0x6}]})
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[])


mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x2000, 0x2d87)
r0 = open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
poll(&(0x7f00000000c0)=[{r0, 0x6e}], 0x1, 0x0)
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$TIOCSETAW(r0, 0x802c7415, &(0x7f00000002c0)={0x1, 0x8, 0x200, 0x80000001, "8fa663743c76f203baf02385a0423dd4a6314e1f", 0x36, 0x200})
preadv(r1, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfe}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000003c0)=""/252, 0xfc}], 0x3, 0x2)
madvise(&(0x7f00003e0000/0x1000)=nil, 0x1000, 0x0)
read(0xffffffffffffffff, &(0x7f0000000100)=""/140, 0x8c)
close(r0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000200)={0x0, 0x7fffffff, 0xfffffff8, 0xba, "09000000ffffffff080400"})
writev(r0, &(0x7f0000000000)=[{&(0x7f00000000c0)="8eaa3d81bcbc69da31d9f2db845e699a5e1dc6c7525a7b8fc37d856d13787d4f9e98fc239d0700d9fe320900000000000000feb42f75458af17c80f091f3d429f9b8349a9b978df26c58379f9b9092eb4e437c30fa1bcc2953888e5650d53b520b4414b193522a04d43e18061aa7b8aeaad170b6322b57243c2f1446bf095f593bdb61c767af1d547c7cd2953e08", 0x8e}], 0x1)
writev(r1, &(0x7f0000000340)=[{&(0x7f00000001c0)="bcecd49fb34c4163da02acb93304ff92ad96605ea07d6b02", 0x18}, {&(0x7f0000000240)="274b70af46e7b060122548a2cbf3e1b63523ee48635c58ceeadb4310fd9c120fc38dbeadf887cae9137a70df8151b917449cf17d04f813d2df9c6cd43a52db464e5988fa6dabc1354ce152c19408", 0x4e}], 0x2)
writev(r1, &(0x7f00000009c0)=[{&(0x7f0000000540)="cb57592b74376d685a62fd536a9991923156b767bf2561610f208517f035187a587887ed21c82f1e465e306d231b7098dd1b86b62aa6fe5a5d949ff1df78f2628fde8ce891b831af635a8660e9a509a19e32cc272b4d94c483296d3a8095b47a3763ea09", 0x64}], 0x1)
writev(r0, &(0x7f0000000740)=[{&(0x7f0000000040)="dd29dba176aee93db105199908", 0xd}], 0x1)
execve(0x0, 0x0, 0x0)


open(&(0x7f0000000180)='./file0\x00', 0x200, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x53e, r0)
sysctl$net_inet_ip(0xfffffffffffffffe, 0x5, 0x0, 0x0, 0x0, 0xfffffffffffffea8)


pwritev(0xffffffffffffff9c, &(0x7f0000001100)=[{&(0x7f0000000000)="fb797cbcbb67260bc7fffd224f6be8ce76cb853e378efe929fbcd352b889269eb85f228a54c5f8ac503fac932d39dfce8b1f5111e9c67d70caa27731cb544cae9a181336f2262ddab1d5626496df645dd071ed2226bf7cb06c810ea956494291c4539b59dd29cfca97df91f019afe9aa3fdfe7d43e5c8c683f016576cb933822f40779749e6eadac4557d52c7a3c049d4dd6d1e36059063f08250fbe06c1ebae60b0b06d212d80e100e29d1b00b08c21c6c444f0e19de37b9dcfe059f4e1f105c96850f9c1ab09e00e2a83ca4658967a945b5e76a7a50f71dace17d15a4c8302", 0xe0}, {&(0x7f0000000100)="235e65f44eecad3dbaa7a0a59b799f64e529f8b1f2664bc1f92da802fc1b6a6aa697dc6876493a2d5d48cbe13cdd32e856bcbbb66f94808e0341b927dd7505a395d628c486fa2f5e039628e8543d0be24b4a58ef983eadd3becaa2fdec947476d8267aca0b340263dbeffa0f839d5ca51e98ab4da2e20f23c9eb569a554b728efbf89c2183220a10037ecd2a7b339a3183beaa4f13b8e7888018b223d7688391ecc79da5b7fae05294436fde437ac56d687d5b8f5793e29837327eb64549b8a3de9a7d9f6b33a861e8fc817469f51c2a7f47250a4e8b5166b5ee6963dacef0fd0267f86dd53a26f740040f028ea42f9e9ee793129ec82ab06677941510d70678d43a46852e85c1f4b0cc4948b0a8e4b58827a35c6ca4150a6c6f025554ee8a24db08400f43db5ff8419c03b8cb6b2252a548077cc82d20d7e06216cc3ce6df7494ee3ba0077c52391f9d2e6714deade4335a7c4330271bb1b369c5b33113d1d050fa4f4fb1434ec3979b531f09fc71bd561e6de1a2a1654447ce5adb0bfc1a196186bfb615a2e0317235d4251120d0b1c589f62ec040f55dc88da46be2da55248648b7579f53647ab5baf880aef6b9947ab2440d705a72111ee9901d795b8dfb608eaa36402cf5462e1696db87b637dbc99d162d0ced4152b8313e1239bc917607a816f0a12e1c428065d813a3b9b5c43b5ff461acd6a09cc2d43c32f7951da33c0c953f57f59e562aa27c3262e6a9e9d92e40858e53957ffb72b8f8a9605852d7b6a7845c4e41300b1dfb241c19327a0679ecbbac13bbb8ed238d088233bc1b135151e78bf2b1ea1d39f891609845551b3afdac7ad59423946c2030d75021d042994ecb2fde65d559530e602dd178b7fa48ac42b5fd0548f0409d4f3b746617553287e42addcec38d13af97b93ee470d51d3d2e4b9530e3732c5cb19a17c46687ee4d7d28f09ff8f3f175f9a9edbca16ede384f954d27234557b7e414226d92baf57c4f4273be4d0118f813bbd601ac940bdc4d184f50bf3285b1ec26fa4532d365be9a4f16fd45d0855bba46d3ee1434b1f829a889b69d5b3288af7c264ba18cd805ac5c8c2935e032b27facbc038620979becd33a8ed589a959c27c1a8a878456ceacb937b57d7c7ce621edc58ad899fcc0f610aeb5f71f7481d5f20d1635e2fee6c2f5d20afbbcfc261cadb1d15a03a763f0b0b5a21762b24e086967111a8f62bf2c323bc944f0deb5d0d9bb05a9f8e6f5bb6f44e9d1455ba9634eb7f554c03b57ef1d15f547e4f3f968bb5dc70c605daf4f114ab4ae25a4dfec7e98b2785e10bd44ab9dcf5080a194719047fbf8c004317ea543a15362b8a5a70c7bbe0d9bbe2dea93e410bebe9976c1e186e0c3b127d61ff0a8b7051c5bf4040fd5ef623254c1f2eff980c3f407aac30df7ab0abbca947fda4574c6d275f13d959cf8755dec08987c0d046b5753b337a536bac654d1e67607cf9e471e704f2cdb3ab86315cbcedc19c881bcec2084e178b3f553249b84da9afa896daebb8f1fde7e3c9181b0ed62252df0355cf788248fa8d25195d6609398956fcdcff92f1db1ca540d6799e6bbe54e0ccdb9dee4b0ef1351eb49d0e84e80c8bbc5b6a8d65e31320ddc5f9f6a5209b174f4ef4080c67c8131fbcdadf60402d8cde36a71fc7b9b7779db5db2453a42c235d2e71e364084c3eeceb25cbd37193fc063bca1d16bc1b1183e920fcf605c0a19fba77018d2788533b9554801e3e7982c00ff5ce8b136489e36f6380c01fdbf6b4519cbf3ad42f446c57f6f820d8820dcf3f051b844dad25d32f80948bd6f793e67b8486f9b2b523d6753963c9ee5a33149c30f38c75a12c875bbd12028e9c51ca06016840b03dde64d6ef218e72b6988b4419e0cabdbbee5c9b9e335d3f1983f5af20a75d5f3cd93714379da95ebdbcb4b68e5a7044bdb495e2a9b82bc20c2ca4fff8278dbdab55175a50286b9f57324957613a061cb799bd542177ca185354537419dcac324bc0aa7d920967b01bea99469701672d392b613fab46fecd60dd38ae0908ea92c6dd17d82c1a2f5f0e4da97843527a0a796de7e317288f073e383b0417272ab26c75b102488ca3fa446dc5f5650d366896dd9f3f4ad371ef8dddf11f4f8c5a30ffe54fe94a5881e4cb26e91e9f9b77146f46ca5d63db32eaa57705c9584c3488cd5ca1d372a88ed0111cca01f5def7b16ea5fd9268180cf82f662efe23ad1194e3ad6799d92f011d0a1cb39fc541a94e0f34019a130e407e0ac2d7cbbeb6119a286c8a1944e621019655e12d0e4480a71ec42f05d4b1257a2ef47239f1b1c4c3a06a19e2f1011898bbf09e9c04fae54159318674073df9f82773011b6fbf41914c1cdbf70c6f2179c0fa2f4f3d0bda942604e8b57c682bba8f1f4068cf295a51aa5e44cea5a48088246daa2830fae3f74817a3817697c8744fcb2937569e616b3f981274e19c009b82ea83a5917d0a3dd34a3baaf8fdad3f1193acb9fd71750e7bb68a6a1eab13af7c6c04a83f074601a89d9b2b0d9e0cae1818455b01f393c3534c31f019375cd6d6bbb2dfe67ef85faa4135c2d078ae5f71b0c7310382f670149a3b52127656868aff7624ccbec0761ec71cdb2a994eed13ce6e404ef025d8827b8c088243d6c27bda01dce74303bec00b9c1abdc0bd28a57cc175a3f7f745daf53968799e9f8fbd3380a32d7e3765f037b5d6f5039fa4fa85f69ff455ab231fce08659585b0a090a2b71afc3a6cfd7fa8b87a3a69ae3afdc6995ff68a6b076d5d19105315b6d96733d5ceb33f6e08164040ee76d1668ca4d95da25fcea89f5c6f6203b9d2272fb699228a616cab18f4ecec43fcbbb463efd66ead723dbf460e8db7ddb460adb929bada43cb549ebe29ecf625a11d78848ca51a0db119aa1ceec075b7452ced0afbb18098bd7bfe1d313b2f4918a83e8b0f11cfc9f7012164c55b438e5f7472e2bd47a63c4e49eb9d4da3d976259455e4547c0eb5b116efb05b6ea05723ac7e0a03fcecfddbc604951f5cc8ffd3c52e8c4981935a191bcbc11b61ef0eb33c90ce456f7ec744abb965ebc88791807686cee5dc31b4503f031b1357d18ef60620a9c1ae15bbe1ad93ba5711582b73e603bb73687e65d10dd4955a09c1fd505b6b3490eee397a4773189cb9c62fdd1888fe5cde96dd77087f31e62202331ff9f7a228d3365629d451001d0d2d36941b3ca5e92b7a49239b30df725d0e3f8a31e25755e0f259bb94cc1d54ae7433435d01b2cd86a13996d15b6491c6ebb9bca21a59ce226dd5b08a510e2248251ec4f0da13cd614f8e7271ed73da553b010d52933b17592c75146f13f04af01064c7bfcb3848669f193adc3486753d80df8214933c25059243dccf728985de699bde5304a86124957fef17f9957d1414ce227209c0537fc5189d9116b76125134bf77618c127f1ca0824a4b2bcdf0172a9a17d6fd11be5c010e6310b521d22022fc1834e344782ffe64bc17762635e329ea7f4ab88f85754555b8e4cc9490e6248fbe0d8400a16254978f9bcd1c7f0504dc8c61084d295e9c9b45a7ede356180728459f4464b873d359b848683fdfe94868fef2546b0159d290cca6a08dafde4b1e524159134bf76f1c2624543f226407a649fca98260be28d6c8db2dcc895d5d327d30be4a664fd92d29b1346d4196961bbe763d67c6089f6a43d237dc1a9197accc998d2397e430399f06473d8266debabd19b5dd4f50adbcf84c7172544a0dbf0599cdb0777a66d54767140768c3addeead24b3647a2e2056aff8cca93008a559a65abab2707c6588afa7620c165df8423ea54495a2548fedc35e87961d99d402e7dcb518dcd11b21552d11090828756a8964ef731652dca3ab0ac9572fed2fdbfadc6f20128df5e7184b5e8067ff4e7bc5edbc9702029a9434901a8d4f6a68553133ffe296b02ecca58b2f14b27a70d3e76390612ce3fb5075c02cf513804bc5ef2add7d38fcfb3ae914bfa9771db9b79cd85ea023f8f039367ae2fcb9551d92ed9e2776bce85995ecbf98ffcbc9f5cc1e7633b8dcba2766249b3053024ffd7cf88d4c02f6a9ad91d51d96dad0e8a3abaf21eeb32bd8ff98650db8224c59b149ac8468e3762fa1ad2be858de10fe5c7e0ab26afe754c56f7a58593899cabfecec9c0f114b308a0924422d221e43116f8ede27213dee590d59b9ff2521d7a25b80d77edaa35bc8f6b2249d3c417fc1be9962301bbab20adeb94dfb2f073a407c96e32c513089541f39d4187dd6bfe10a1e4ba30eee62a2a86fdcfac8393b3f6c4948715ad610a273e46f0701b00f90be6c4024ee5a2a6975fd8f8a95217e23bf4221baa1260132ebcc7d7238a27b1274070772334d18e578986b25ece0bbf189a8fdce374c56d71eaf50841d34c061ee4a37171bc5f869cb414cbf4fa7f3e4d4ec164c1bbf51256aceda7992ee889deeca23e3d629f20b578fbdef794be82cdc8c04055ad291d9b61dea800df62c6be501345aa74c6039c2f5f08b1edb4e3253089ef59cefb071ff10bec5aacf2fe66e5319f3d529ea9addeb6c1e47c3b5ffddf90bf1bf057e27f80390f7718c00825f6536b4be3b4118c1433396f1864f2ed7585722b78611874245cd4553f2a5092b4ed2296404229ebf0ec6aebb7e61158b6fc9f6da06a4cb2da2e60dbc2e18cf5356ad81db702f1f8ea9ccd868db4d4fcf3c27a1b2bb6bec8ec8ce901b27a8d4cc558118ec1653db7dac6902e5378568d221ddf9835c1c7756fd4e532c6cd5a3bde884b74e5775f01a57a0f96913db55b4f17a254076d8d53424044e0a774ef1134b151c6ee9ef162cc6c199dacaf344ece177fbb765e9a5a9e8cbb876fb178396aa11fe078a61957d2dbc0a5ba348058acef3bbc675c209988eef8077cb6a9b043a7bda83689236e438d3b405cfcf07a5f727da134fb4c3a82fb4c9cb464df0aac007f7247c8567be48ef132c4717151d27bbc4fc11256beb7fc8b187f17c171f827f070a0c5b8101aaaf05ef2ea281e5b75df374948e3bc3012bf8ccfe9fd0945986fb24c86fb214e7920b3f83d064503ad57835273925c1a3470929e8ad0bd9216c435c74b64a95ccb3eda74568256baf81e259756a631541c4e6e995288f871dd4dce7f60ec4e723e8168c679c41fcf669df9d6f09f9e4896ea2b968b499c20526588f6ae04ed2b3ae996f789b0e333505c642602cdae2aa38fa3c45ed774be453ab48d04b524e150eb89932eca13c9468494a6e518044cda1d94f2c05264fc1e60f71cedf9d4ad54e3f387ba04f771a868789e48e0cf5beb266a28e5dbdc1d9db0e04054b0c53560f3e05b3632a7cbed562c9c6563b8598d8fd1958a2fc26518263115c5af851dbfad79cc633cf2fbe881bf6ca8e5a91b06049d51f0510e4ffab331d6f3f5c172f2f63bc72ee6dd9a05b45f092f057c5a5ef138730163fd996ef93b376400a68f54a389f69078454305423d96dfc0890631217e04c5e83744dd8e5e67c141971dbf070655abaa3ff5104aed39cb12c67cd21a444a536ef989a88355fbc7e8893b151d78e06b873c5f9a6e913fb477f079153b9b1185d5763c45de1dc964b9a775bad2e31c1bebf9919ede7075547925f8c683b157ed69a89b15ba6a0c06e7be7e5c70afd1a71ca27b9e726865aa403b14f1348a6777cc39a9c36e57178fabac3b7588d3195c34a9f49d59263edbaf4f52f0e86291d4709c48ebceced3b6bc35941a32490515e3dcb1a0d48d8d365f377416c72a3076148099b890b7489017293757466199416bb0", 0x1000}], 0x2, 0x4)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000001140)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
connect$unix(r1, &(0x7f0000001180)=@abs={0x1, 0x0, 0x0}, 0x8)
fsync(r1)
r2 = socket$inet(0x2, 0x3, 0x7)
sendto$inet(r2, &(0x7f00000011c0)="4ef0da", 0x3, 0x40f, &(0x7f0000001200)={0x2, 0x3}, 0xc)
r3 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000001240), 0x80, 0x0)
ioctl$FIONREAD(r3, 0x4004667f, &(0x7f0000001280))
getsockopt$sock_cred(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f00000012c0)={<r4=>0x0, <r5=>0x0, <r6=>0x0}, &(0x7f0000001300)=0xc)
setuid(r5)
lchown(&(0x7f0000001340)='./file0\x00', r5, r6)
getsockopt$sock_int(r1, 0xffff, 0x1001, &(0x7f0000001380), &(0x7f00000013c0)=0x4)
ioctl$WSMUXIO_ADD_DEVICE(r3, 0x80085761, &(0x7f0000001400)={0x2})
shutdown(r3, 0x0)
writev(0xffffffffffffff9c, &(0x7f00000017c0)=[{&(0x7f0000001440)="2b13185b008905279559e43dd54fcb194d32f0d1f3ef2f51e72bf4ff90a03d7a7b905be73ae3cd7f74b4ebba090fb2ae250a5879dffa1298f07b860b0d8b57094fe5356d862902312eff285f73145ec26f46741e884e31addd3bdde863d8b09feae2d24e0580344614608b1904779a1d2640daa8b84e9f87d380fd13407751943987ddaafd58eef2", 0x88}, {&(0x7f0000001500)="f80ce13794e004ba3b333f6055ebcc9c0bf164a0181206d6304ff58cc4cdc579b146bf31d5f915e54f32e0a01c633ac934b35761349e4c7bf66c1f966166159c2c6504de36f475daca206dfdb8d137b507b3cdcbca7e17dfe40a6e20cca629e3281fbf7ebe7a9c981596e1928e0a584335df4571e26871c258a2d76372661d8e5a1081b1999ab1e98f97456823f1f9138cb39021ae35681dea6391cd9fc73ca519f85723eed268f904824f9e378c7a9ca939657f6180cd26faf57e6c7afd9abcc11ffec0e171c6b26e1749985a49beabd49be89d32dbcc7b1e1225a858ecb9ea2d3a54c01231be53", 0xe8}, {&(0x7f0000001600)="4f0319ca1dc0ad1faae4223b23b65959222c1409df3587563f7bc5b09b5e44b6e9a53b73a311306328982d216f6abd01db47820df914c8b0f34cb8b93f690e696c88ec2e7063bc9250e77fde681cc8889d5b6bf15c81d7cfc485d5564eec63a0957964b50577605c94f19f21591f784382d65f1bb627b18f19a2bad1cccfbc6f32b741da154568bc459240cb350abd770d6857987c45f38bed2ce5199addacc6a7984f0a7b6116c971618b2d8d79fdf2afdf97618e224f76b98de3da7d7bc042ff2b7029df927d73866c18ee753313bb5d2f91371fcbfea3ee869c9c1062efd6a5d592673228371e87ecf58921b2f81c", 0xf0}, {&(0x7f0000001700)="2dfc80246601ea64cc9d6e0d41768f84e1b87bcd77ce3ca28ca68d526470c4b7058426d05fcecfee7ab503b06cf213a89b14ecc1de608e61fa1e218746e717a564d216268f2697dfa240f7b8efafb98360f55ced7850dd2e8a0745ea43b081e9774775da57b076285a86216a671071db68059df82864fd0cb2014b44519378054dae125897f074f6595d8d5ed8986da2fb27a78c52a82ca890021cc44833ff7dba8b5c049a923ea7261a67eb5d9471a220cc309c", 0xb4}], 0x4)
recvfrom$inet(r3, &(0x7f0000001800)=""/174, 0xae, 0x0, &(0x7f00000018c0)={0x2, 0x0}, 0xc)
poll(&(0x7f0000001900)=[{r3, 0x2}, {r0, 0x10}, {r0, 0x10}], 0x3, 0xd6cd)
ioctl$VMM_IOC_RUN(r3, 0xc0205602, &(0x7f0000001bc0)={0x5, 0x0, 0x9, 0x4e, &(0x7f0000001940)={{0x7, 0xf4, 0xff, 0x39, 0x4, 0x2, 0x7}, {[0xfff, 0x5, 0x8000000000000001, 0xf32, 0xfffffffffffffffc, 0x72, 0x40, 0x0, 0x100, 0xff, 0x7, 0x0, 0x4, 0x500000, 0x0, 0x7, 0x2, 0x7ff], [0x3, 0x0, 0x7fffffffffffffff, 0x2, 0x25, 0x7, 0x8, 0xff, 0x8000000000000000], [0x0, 0x0, 0x0, 0x0, 0xa1f, 0x8, 0x2], [0x2, 0x5, 0x3788e49a, 0x0, 0x4], [{0x0, 0x80, 0xffffffff}, {0x1, 0x1, 0x1, 0x19da}, {0x4, 0x401, 0x200, 0x2}, {0xfe6, 0x3, 0x2, 0x9}, {0x2, 0x1, 0x4, 0x5}, {0x0, 0x0, 0x7f, 0x2}, {0x4, 0x3f, 0x6, 0x6}, {0x200, 0xfff, 0x1, 0xfffffffffffffff8}], {0x4, 0x8001, 0x3, 0xfffffffffffffffd}, {0x4, 0x8001, 0x5, 0x782}}}, 0x2})
setuid(r5)
fsync(r1)
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000001c40)={0x0, <r7=>0x0}, &(0x7f0000001c80)=0xc)
lchown(&(0x7f0000001c00)='./file0\x00', r7, r6)
getdents(r3, &(0x7f0000001cc0)=""/167, 0xa7)
syz_extract_tcp_res$synack(&(0x7f0000001d80), 0x1, 0x0)
getegid()
sysctl$kern(&(0x7f0000001dc0)={0x0}, 0x0, &(0x7f0000001e00)="ee99844d4ee8cc0c8122aa48d74012562957242df8da24670179bccf57e75852a45ba5b8a90d74575b662f9326e5492da2a602a05c311de6d1cebce061b2b7cb33e4991923387d0a940a95742fbec3923f761d1881e1a4e93602a78502c9a976d1bcf678ddbc4b0c218fca9f6beb3b9ea33c527f8db95914b1f13fc212d1de345d4fa11ec394e02c251a188d0134b82d1a1bee6c2bbd4a2f9e7c6a802a7ade51db65", &(0x7f0000001ec0)=0xa2, &(0x7f0000001f00)="aaf329f94ee38b641e9a00fdc0d069f77ddb717ef67d85ab3bde25755006f490d2708d0c8d572914bfbc09f56938503c3c5f4a0542beff4e1e69a4541015b5cc800ada1b4f851d1487944949042854b5f3d660f344dccb9630d718f6af637033188ede6ddc18f340cba02eb14de7e48be3b3ac095330b9c8aae460c7249847cae4e2620beb4e4a4e03f1a325c53d7265a402c928a5eb54aa0757cda2aa1c00e62fba514260f982dc93", 0xa9)
fcntl$dupfd(r3, 0xa, r1)
r8 = semget$private(0x0, 0x1, 0x73c)
semctl$GETALL(r8, 0x0, 0x6, &(0x7f0000001fc0)=""/238)
fcntl$setown(r3, 0x6, r4)


setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
r1 = kqueue()
kevent(r1, &(0x7f0000000640)=[{{r0}, 0xfffffffffffffffe, 0x3f}], 0x8008, 0x0, 0x0, 0x0)
kevent(r1, 0x0, 0x0, &(0x7f0000000280), 0x6c, 0x0)


r0 = getppid()
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000015c0)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
fcntl$setown(r1, 0x6, r0)
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r0})
pipe(&(0x7f00000001c0)={<r2=>0xffffffffffffffff})
fcntl$setown(r2, 0x6, r0)
ioctl$WSKBDIO_GETMAP(r2, 0x80047476, &(0x7f0000000100)={0x0, 0x0})


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
setgroups(0x1, &(0x7f00000012c0)=[0x0])


open$dir(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x2, &(0x7f0000000080)=[{0x3c}, {0x6}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])


syz_open_pts()
close(0xffffffffffffffff)
syz_open_pts()
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
ioctl$FIONBIO(0xffffffffffffffff, 0x8004667e, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff, 0x0)
syz_emit_ethernet(0x4e, 0x0)
syz_emit_ethernet(0x3e, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
rmdir(0x0)
openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000280)={0x3, &(0x7f0000000040)=[{0x1c}, {0x5}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000180)=ANY=[])


open(0x0, 0x0, 0x0)
select(0x0, 0x0, 0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
select(0x0, 0x0, 0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000040)=[{0x30}, {0xc0, 0xdb}, {0x6}]})
syz_emit_ethernet(0x2a, &(0x7f00000000c0)=ANY=[])


open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
acct(&(0x7f0000000140)='./file0\x00')
acct(&(0x7f0000000040)='./file0\x00')


sysctl$net_inet_tcp(0x0, 0x0, &(0x7f0000000100)="e4", 0x0, 0x0, 0x0)
socket(0x2, 0x2, 0x0)
r0 = socket(0x2, 0x1, 0x0)
r1 = socket$inet(0x2, 0x1, 0x0)
getsockopt$sock_int(r1, 0xffff, 0x10, &(0x7f0000000000), &(0x7f0000000080)=0xca555f06cd31e785)
r2 = fcntl$dupfd(r0, 0x0, r1)
close(r2)
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
getpgrp()
r3 = socket(0x2, 0x1, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r2, 0xffff, 0x1023, &(0x7f0000000080), 0x4)
r4 = dup(r0)
listen(r4, 0x0)
select(0x40, &(0x7f0000000100), 0x0, 0x0, 0x0)
shutdown(r4, 0x0)


r0 = socket(0x2, 0x2, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r0, &(0x7f0000000000), 0x10)
write(r0, &(0x7f0000000140)="14bdfa5d1d34e2fecb284a6498307dcda93b91ccef7d2ad9049baec43050036123339a346f737850541408753f95b7688ad4c4e1dd5489e7bafc58d3e5823757ae8b630719ef187ccad995f13dbe19a6dd4e6902bd8297b0799b426aabe9fad9db6996571c6d9f8bb5d542c2148aa42be940970fe88d34d8f99afe7e78202374000000000080000001000000000000000000", 0x92)


connect$unix(0xffffffffffffffff, 0x0, 0x0)
getsockname$inet(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCGETIF(0xffffffffffffffff, 0x4020426b, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f0000000200)={&(0x7f00000001c0)={0x0, 0x0, &(0x7f0000001880), 0x0, 0x0}}, 0x10, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r0, 0x81206919, &(0x7f00000001c0))
socket(0x0, 0x0, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x0, 0x7}, 0x1c)
r1 = socket$inet(0x2, 0x3, 0x0)
getsockopt(r1, 0x0, 0x2, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
r2 = socket(0x18, 0x2, 0x0)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
close(r2)
shmat(0xffffffffffffffff, &(0x7f0000ffb000/0x4000)=nil, 0x2000)
r3 = socket(0x18, 0x3, 0x0)
setsockopt(r3, 0x1000000029, 0x31, &(0x7f00000000c0)="b211d7170d816685c8e360f2fa41c1a0946988b272d2dd3dc90142a84231a746e337b372e93320cff6669cbe7868de45ed3fc33719ca6df71ecec8a918458b2c10a1f8c66653b276e180e9cb9b21f9982230f575295d48889c9a920796b2dd92fc8575680b37ba955d2c15e6d7c9198ed900ab006ddfb67869b51a2216114d1ece85f593e74035f5bc054eb1dbddf42a", 0x90)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0))
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
writev(r3, &(0x7f0000000180)=[{0x0}, {&(0x7f00000004c0)="a29228fcd8b93635bd8ce9b958fc56277452f4bd7372ef7f9829fc5f04ee9a4d4ea18cc39157341d5fe84d07c6346de0ed85913a3b2dc3083e3275bdba233d65aa00e5416ced2bdb35a2d0d7544e2886598fa027e0c681635e3c5902497ab520a51f694a457dec3eb0bdc737408f856cc9f41d12255d5f77658faf335ab0f25a7330b20d57d9936f2909c4a030a1b3122001ddd6607e740f00000000000017a7699073d9497074bd10a6112e2acaefbdd2e9ff71c4292c082da70a15ff0100009734ef5d2b2a7fa4f3403567b0e6f0d862015f8ad2d31268a9b957a4850accf9615634f6d247a2c9e338c18ab3da458c4312986966ab546f0ad48961f323906ea0fe454b2b9932a94ad1d8d7e2bf3ffc5a48b0127c8b417b678d35193bfd50d740eb93219b6d77f57ac3051d459ba41d2c07ed2504b967d66d4692d9654f85821a44333a73c58f163431c692da984a52561aa97c729feb9fa6144263b28733c857188b16e584429f1148e112b3", 0x16d}], 0x2)


sysctl$hw(&(0x7f0000000000), 0x2, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x3}, {0x87}, {0x6}]})
syz_emit_ethernet(0x26, &(0x7f0000000280)=ANY=[])


sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x13}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(&(0x7f00000001c0)={0x6, 0x1b, 0x2}, 0x400000000000000d, 0x0, 0x0, 0x0, 0x5a)
sysctl$kern(&(0x7f0000000040)={0x1, 0x3f}, 0x2, 0x0, 0x0, 0x0, 0x0)
r0 = socket(0x18, 0x1, 0x0)
shutdown(r0, 0x1)
shutdown(0xffffffffffffffff, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, 0x0)
socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x6c, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
mknod(0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
bind$unix(r1, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
getsockname$unix(r1, 0x0, &(0x7f00000000c0))
r2 = open(0x0, 0x81, 0x80)
mknod(0x0, 0x2000, 0x0)
ioctl$TIOCSTOP(0xffffffffffffffff, 0x2000746f)
getsockopt$SO_PEERCRED(r2, 0xffff, 0x1022, &(0x7f0000000080), 0xc)
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f00000000c0), &(0x7f0000000100)=0xc)
ioctl$TIOCFLUSH(0xffffffffffffffff, 0x80047410, &(0x7f0000000540)=0x81)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000300)="9b0209c3eb987ab7fe4189c99e805e6e84d356960798a692992117d6728436ba1bd87f42e3303eac3846528d050712f838130efce33f523ba44765f5f6915b0227390ed95bd9dc6d4dc7e149d4d6d06a3f23616e773302d9cae75e39a5a11e32e0e6ebd635450b2eba540af7f2aa5dbfbdd900a0dad2b74f50acd76b5c567049ef436dbea0d7562f52950fa5ef6e84c513252ddd8680a944d5c2bd02adc7f1fe850c00000000000000062ab475cca257352828a76e5334be562995e894238b96ca5d4d3e670feac9b4e8aa9bef19525cb6f7e8570b2a374f1400041ed45bb7ad3fe963cb9a8bd949ee0fc6dbceb7d956015947b3e88aa810f8ed7cca10ff010000000000001345daa49507756f49775275ca390b94e85d5a95b8bdacb9429c25483a9275d0da3b561c6adc3c141f26a88016dd6b436218bdbdc9ac0a623855e941dc1872fcb045e0d9df1ecc6357ee21e2b0802cb60eec6add5e94723235f06715e7eecc3e0760c70e1dd7873e27142bbae1a7e44de453a073fe3426f334b80f043ba9136d57c799353d46dd81439b111a511a288bee5dfb2e353e3bb073e3342273216b07e49ca4df0fd2dbe9a8eb377010ee678aad0bd8e9fb7d82693a096344671843a1f2082612b0ff237c6e505ff5f5ba932954d73c630fdb791f833a1da5af0704f687e196f4f7859e071fc98111cc9024f790ce16ceaa7d0104e39789d9100000010000000000050000000000", &(0x7f00000002c0)=0x210, 0x0, 0x0)


mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x10205b1a)
open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)
mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x205b9a)
open(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
select(0x40, &(0x7f0000000080)={0xffffffffffffffff}, 0x0, 0x0, 0x0)


pledge(0x0, &(0x7f00000000c0)='\x00')
open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7817)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000080)=[{0x2d}, {0x5c}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000300)=ANY=[])


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f00000001c0)={0x0, 0x0, 0xeffffffffffffffb, 0x10002fffffffc, 0xffffffffffffffff})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000040)=[{0x34, 0x0, 0x0, 0x10000}, {0x7}, {0x40e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000000)=ANY=[])


r0 = socket(0x11, 0x0, 0x0)
sendto$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x10205b1a)
r1 = open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)
accept$unix(0xffffffffffffffff, 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x205b9a)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
readv(r1, &(0x7f0000000380)=[{&(0x7f0000000200)=""/87, 0x57}], 0x1)


kqueue()
unveil(&(0x7f0000000280)='./file0/file0\x00', 0x0)
r0 = socket$inet(0x2, 0x1, 0x0)
getsockopt(r0, 0x0, 0x22, 0x0, 0x0)
setreuid(0xee00, 0x0)
r1 = getuid()
chown(&(0x7f0000000180)='./file0\x00', r1, 0xffffffffffffffff)
getuid()
r2 = socket$inet(0x2, 0x1, 0x0)
getsockopt(r2, 0x6, 0x10, 0x0, 0x0)
fchmod(r2, 0x0)
fcntl$setflags(0xffffffffffffffff, 0x2, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
setreuid(0xee00, 0x0)
r3 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000000c0)={0x0, 0x0, <r4=>0x0}, &(0x7f0000000100)=0xc)
fchown(r3, 0x0, r4)
syz_emit_ethernet(0x5e, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
getrusage(0x0, &(0x7f00000002c0))


mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
r0 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$WSDISPLAYIO_DELFONT(r0, 0x8058574f, &(0x7f0000000280)={'./file0\x00'})
pipe(&(0x7f0000000000)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
readv(r1, &(0x7f0000000380)=[{&(0x7f0000000280)=""/236, 0xec}], 0x1)
write(r2, 0x0, 0x0)
syz_extract_tcp_res$synack(&(0x7f0000000040)={0x41424344, <r3=>0x41424344}, 0x1, 0x0)
syz_emit_ethernet(0x14b, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x13d, 0x0, 0x1}, @tcp={{0x2, 0x1, r3, 0x41424344, 0x1, 0x0, 0x13, 0x4, 0x2, 0x0, 0x233, {[@generic={0x2, 0xd, "96c729637cae4fa49c1558"}, @sack_perm={0x4, 0x2}, @sack={0x5, 0x1a, [0x4, 0x0, 0x40000001, 0xde5, 0x2, 0xffffffff]}, @timestamp={0x8, 0xa, 0xb018, 0x8}, @generic={0x4, 0x2}]}}, {"d1c2f0bfe2d0786ca28e44289f59aba04d62ff16e6bb47f1cd981d0cf5f225560531db5a3a6c3cb3d5ac50e0eec7423f3ef5e3c4a13f81f14f843a32b529e4649b57d581159522ddf03a6cabf358af4e1ae7ab79a9aac6417859ae29d8de08ba3da1e6387381a61f166b78d7ae58ccd15a08555c8e7db3e261cbba4f565ff3567edfcacd1a43a2f80b44a3727c2f46723f3826d9842357f4d467cb2e24ed586547d107e74cfe46502dde741762fe8ad6742200cf5fd16fcdadae4fd744b730286383e0444647e948151cb63c5c12b79f75a37762e3f013f189799eb699"}}}}}})


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f0000000040)=0xfffffbfc)
writev(r0, &(0x7f0000000000), 0x100000000000023f)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x3, 0x0, 0x0, 0x0, 0x0, 0x60, 0x4}})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$VMM_IOC_INFO(r0, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
sysctl$net_pipex(&(0x7f0000000000)={0x4, 0x22, 0x1}, 0x3, 0x0, 0x0, 0x0, 0x0)
r0 = socket(0x18, 0x1, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000100)=[{0x14}, {0x28}, {0x16}]})
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f00000001c0)=ANY=[])
setreuid(0xee00, 0x0)
r2 = getuid()
setuid(r2)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
r4 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000200), 0x180c0, 0x0)
ioctl$VMM_IOC_RUN(r4, 0xc0205602, &(0x7f0000000680)={0x9, 0x0, 0x2, 0x100, &(0x7f0000000400)={{0xa2, 0x1, 0x9, 0x1, 0x5, 0x92a7, 0xfffffffb}, {[0x81, 0x2, 0x2, 0x401, 0x10001, 0x9, 0x0, 0x7fff, 0x10001, 0x3a4211d4, 0x80, 0x1, 0x8428, 0xffff, 0x3, 0x101, 0x7, 0xaf51], [0x6, 0x80000000, 0xf6a4, 0x2, 0x7, 0x4b13, 0x7, 0x7, 0x8001, 0x100], [0x2, 0xd42, 0x3f, 0x1, 0x78, 0x7, 0x101], [0x4, 0x40, 0x0, 0x100000001, 0x4, 0x1], [{0x8001, 0x0, 0x0, 0x60dc}, {0x0, 0x0, 0x0, 0x8}, {0x101, 0xff}, {0x40, 0x7fff, 0x0, 0x3}, {0x2, 0x8, 0x401, 0x81}, {0x4, 0x6, 0x2, 0x401}, {0x9, 0x40, 0xffffff80, 0xffffffffffffff7f}, {0x417, 0x80000000, 0x2, 0x3}], {0x1, 0x2, 0x0, 0x3}, {0xae9, 0xfffffff9, 0x7c, 0x7}}}, 0x7fff, 0x3})
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETWF(r3, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x1d}, {0x24}, {0x286}]})
write(0xffffffffffffffff, &(0x7f0000000180)="c5449bc1708e16b9805a099e20a0", 0xe)
setsockopt(r0, 0x1000000029, 0x35, &(0x7f0000000040)="03000000", 0x4)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000000)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}, 0x0, 0x0, 0xffffffffffffffff})
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
sysctl$kern(&(0x7f0000001200), 0x2, &(0x7f0000000440), 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x1, &(0x7f00000000c0)=[{}]})
sysctl$kern(&(0x7f0000000100)={0x1, 0x56}, 0x2, &(0x7f0000000280), &(0x7f00000001c0), &(0x7f0000000380)="8bb2be1a9be807bd4743ff0e5a1e3f1ab674486d457907256ffd2f833159c7611eb06be0d010d86fc61feac68b1210e845de1912d972000b8814f0cfc84fa61e290120663452092be165f32c30d245ddfa0bfa2d9a6ee850a18a10c40cc03988db173a94800b05ffbcfb", 0x6a)
msgget$private(0x0, 0x0)
r5 = socket(0x2, 0x1, 0x0)
close(r5)
r6 = semget$private(0x0, 0x4000000009, 0x0)
semctl$IPC_RMID(r6, 0x0, 0x0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000004c0), 0x2, 0x0)
writev(r0, &(0x7f0000002100)=[{&(0x7f0000001100)="968ce1c69d9498126527e1ad5174636898ad874ffb39b42f574f4f4cbc90acc1eb117d7e3bf3d52de5d57a7f2ec5c0d23a134ee65c5f70eee9f43f9c71342063cfdf9eb60982d3ed95722aa70920bd1c6331d3e4e1891e80699e9058b7a39ae56ffa1c545b3dfa90cd36699a984bdaedff8dbf3d11d74e26036a7fc36b1f53740b772d7c7996271e18c83078e8d21903e3b374", 0x93}], 0x1)
execve(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000400), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000080)=[{0xc}, {0x2}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000340)=ANY=[])


r0 = socket$inet6(0x18, 0x2, 0x0)
syz_emit_ethernet(0x4e, &(0x7f0000000000)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaabb86dd6000000000180000000000000000000000000000000000000000000000000000000000000001"])
ioctl$VMM_IOC_READREGS(r0, 0xc050756a, &(0x7f0000000000))


fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000080)=[{0x3d}, {0x7}, {0x8186}]})
syz_emit_ethernet(0x10a2, &(0x7f0000000080)=ANY=[])


close(0xffffffffffffffff)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r0 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r0, 0x0)
r1 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
getpeername$unix(r1, 0x0, &(0x7f0000000140))


ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000080)=[{}, {}], 0x2})
r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_GETPARAMS(r0, 0x80105727, &(0x7f00000000c0)={&(0x7f0000000200)=[{}, {0x26}], 0x2})


writev(0xffffffffffffffff, &(0x7f0000000500)=[{&(0x7f00000000c0)="ac", 0x1}], 0x1)
open$dir(&(0x7f0000000040)='./file0\x00', 0x300, 0x0)
ktrace(&(0x7f0000000300)='./file0\x00', 0x4, 0x530, 0x0)
pipe(&(0x7f0000000080)={<r0=>0xffffffffffffffff})
r1 = open(&(0x7f0000000340)='./file0\x00', 0x0, 0x0)
readv(r0, &(0x7f0000000240)=[{&(0x7f0000000100)=""/103, 0x73}, {&(0x7f0000000380)=""/120}], 0x1000000000000239)
dup2(r1, r0)
execve(0x0, 0x0, 0x0)


r0 = socket$unix(0x1, 0x2, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
sendmsg$unix(r0, &(0x7f0000000080)={&(0x7f0000000040)=@file={0x170, './file0\x00'}, 0xa, 0x0}, 0x0)


r0 = socket(0x18, 0x1, 0x0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0xa, &(0x7f0000000040)='\t\x00\x00\x00', 0x4)
r2 = dup(r1)
dup2(r2, r0)
setsockopt(r0, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


setrlimit(0x8, &(0x7f0000000980)={0x8, 0x20})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000080)={0xf66c, 0x0, 0x9, 0x5577c533, "3c107dae307e08002b4600000000da64612c3300"})
writev(r0, &(0x7f0000000540)=[{&(0x7f0000000700)="bf0909b98732e43ae0ee63c33dd9cb7de67102649ec14a5cded53919ae073ec3840470c82e4e6e321625a3b8aea50ed102f865ac1f5533a8164d4293c71442b6439133b700dc7e", 0x47}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000003c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{0x20}, {0x87}, {0x106}]})
syz_emit_ethernet(0x36, &(0x7f0000001300)=ANY=[])


r0 = socket(0x18, 0x1, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1, &(0x7f0000002700)=0xffffffff, 0x4)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


r0 = kqueue()
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
kevent(0xffffffffffffffff, &(0x7f0000000140)=[{{r2}, 0xffffffffffffffff, 0x882919ab1cb74ec9, 0x91, 0x9}], 0x0, 0x0, 0x0, 0x0)
kevent(r0, &(0x7f0000000100), 0x7a, 0x0, 0xffffffff, 0x0)
writev(r1, &(0x7f0000000400)=[{&(0x7f0000000240)="83", 0x1}], 0x1)


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x68, 0x0, 0x0)


sysctl$net_inet_ah(&(0x7f00000003c0), 0x6, 0x0, 0x0, 0x0, 0xfffffffffffffeb6)


ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, 0x0)
syz_emit_ethernet(0x1f, &(0x7f0000000240)=ANY=[@ANYBLOB="aaaaaaaaaaaaffffffffffff8848"])


mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x205b1a)
open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)
open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
r2 = dup2(r0, r1)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0xffffdffc, 0x0, "ffff09008700"})
close(r0)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "00001800"})
close(r1)
mknod(&(0x7f00000002c0)='./file0\x00', 0x2000, 0x5200)
setsockopt$inet_opts(r2, 0x0, 0x0, &(0x7f0000000140)="3b8746d3177012c43393a7023865979f47d02e81b2e79e91789ac532e97c76c02f6ed8f6e1bfc9f552d3940a6adb6c35ae18f30aaf01cfe5130515d3f65dd3072e074331ca6e8ad3ec9616a8914476836a4f8efbd6c8d694bb0a9d0572c7b0aecafc110034f970ed48b91d03b82daa92b40f048bea3a1646fe751935abf1a086c0772abb10b2df17664ea382b9dca4f75ca9c84fb96e5c35eb70e2e90f74b9cb8c91f7444514f963029319d573a5eeb0b2c960adac69042dddbd3285e92f848387f4145d0670", 0xc6)
r3 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
poll(&(0x7f00000000c0)=[{r3, 0x6e}, {r3, 0x40}], 0x2, 0x0)
syz_open_pts()
r4 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000180), 0x1, 0x0)
r5 = dup2(r4, r4)
ioctl$WSKBDIO_GETMAP(r5, 0x40047477, 0x0)


r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0xf02, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, 0x0)
r1 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r1, 0x0)
mmap(&(0x7f0000001000/0x3000)=nil, 0x3000, 0x1, 0x2012, r0, 0x0)
mmap(&(0x7f0000003000/0x1000)=nil, 0x1000, 0x2, 0x11, r0, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)
munmap(&(0x7f0000000000/0x4000)=nil, 0x4000)


socket(0x18, 0x2, 0x0)
sysctl$vm_swapencrypt(0x0, 0x0, &(0x7f0000000140)="118bea625d95de8f92c010baed45ec4bf03ace254b57973bb6de7b1c90301e9d3b5e6fb6ffffffffffffffff76c775a2a4e0556565a830032eef776127fd247103c14ab0a1cea9b4593be484f46a02ea73e910d041c5777bd852e57d3248832b91d06fe47d126022a1654859149e9486306d2f11fb1cc826c42f81b0d114f8af4ceb029a5210bb6947464bf678ba1d64a2013131fedfe60443aa13", 0x0, 0x0, 0x0)
syz_emit_ethernet(0x126f, &(0x7f00000000c0)=ANY=[@ANYBLOB="aaaaaaaaaaaa00000000000086dd609ded1a12390000c4a4e3434e58d025a6a8a81cf312b8befe8000000000000000000000000000aa00030000000000000101000101000401000401000103000000000100010200000000c7ab6f1eba08bf03d1805fce0ef2ab82f4a065245eccda108bec7cb23f632c993265a4cefeb77b1406d562a47d4b0054943553278b519ed107f62b5c352f8e68d83c1fd85b8e1083556d7fa2fc09a3e823fa940de6ef1b18ddb2a2dba0d2d9c1b44b20ed3a932a2c47f4f4d3e34ea1b67a607001a4541a87d5d347"])
sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f00000001c0)="55f8f5782087a072a82ec35f78d14780f518", 0x12)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc1206949, &(0x7f00000001c0))
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
syz_open_pts()
pipe(&(0x7f0000000840)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
r3 = kqueue()
setsockopt$sock_int(r0, 0xffff, 0x10, &(0x7f0000000200)=0x4, 0x4)
dup2(r3, r1)
select(0x40, &(0x7f0000000040), 0x0, &(0x7f0000000140)={0xab6}, 0x0)
r4 = geteuid()
r5 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000000c0)={<r6=>0x0, 0x0, <r7=>0x0}, &(0x7f0000000100)=0xc)
fchown(r5, 0x0, r7)
fchownat(r2, &(0x7f0000000080)='./file0\x00', r4, r7, 0x0)
setsockopt(0xffffffffffffffff, 0x8, 0x6, &(0x7f0000000040), 0x0)
mprotect(&(0x7f0000ffd000/0x2000)=nil, 0x2000, 0x5)
r8 = socket$inet(0x2, 0x1, 0x0)
fcntl$setown(r1, 0x6, r6)
setsockopt(r8, 0x0, 0x4, &(0x7f0000000000)='\x00\x00\x00', 0x3)


syz_emit_ethernet(0x40, &(0x7f0000000000)={@local, @broadcast, [], {@ipv6={0x86dd, {0x0, 0x6, "6aa63f", 0xa, 0x2b, 0x0, @remote={0xfe, 0x80, '\x00', 0x0}, @rand_addr="6877ba6ef075da9ec197be1e1741a892", {[@dstopts={0x33}], @generic="0170"}}}}})


ftruncate(0xffffffffffffffff, 0x0)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ff3000/0x2000)=nil, 0x41000}, {&(0x7f0000538000/0x2000)=nil, &(0x7f0000ffa000/0x3000)=nil, 0x200000000}, {&(0x7f00001f5000/0x4000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ff3000/0xa000)=nil}, {&(0x7f0000ff2000/0x3000)=nil, &(0x7f0000ff9000/0x3000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f0000ffa000/0x4000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f00001f4000/0x2000)=nil}, {&(0x7f0000002000/0x1000)=nil, &(0x7f0000ff9000/0x6000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f000009f000/0x4000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000084000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000161000/0x4000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000280), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r0, 0xc2585601, &(0x7f0000000000)={0x2, 0x0, 0x1, 0x0, 0x0})


r0 = socket(0x11, 0x3, 0x0)
getsockopt(r0, 0x11, 0x2, 0x0, 0x0)


r0 = open$dir(&(0x7f00000003c0)='./file0\x00', 0x400004000011830a, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, 0x0)
r1 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, r1, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
pwritev(r0, &(0x7f0000000340)=[{&(0x7f0000000080)='\x00', 0x8a8615b7}], 0x1, 0x126)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000140)=[{0x64}, {0x60}, {0x812e}]})
r1 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1023, &(0x7f0000000080), 0x2)
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x18, 0x1, 0x0)
setrlimit(0x8, &(0x7f0000000200)={0x9, 0xc0})
r4 = syz_open_pts()
close(r4)
r5 = syz_open_pts()
writev(r5, &(0x7f0000001480)=[{0x0}], 0x1)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
setsockopt(r3, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r3, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r3, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


openat$vmm(0xffffffffffffff9c, &(0x7f0000000800), 0x0, 0x0)
syz_extract_tcp_res(0x0, 0x0, 0x0)
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)
ioctl$VMM_IOC_READREGS(0xffffffffffffffff, 0xc028756b, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0xc0206921, &(0x7f00000001c0))
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0xc0206923, &(0x7f00000001c0))
r4 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000200), 0x20000, 0x0)
ioctl$VMM_IOC_RUN(r4, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0})


socket(0x0, 0x0, 0x0)
getsockname$inet(0xffffffffffffffff, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000002}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x400000002, 0x0)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r1 = socket(0x18, 0x1, 0x0)
r2 = dup2(r0, r1)
sendmsg$unix(r2, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


mknod(&(0x7f0000000040)='./file0\x00', 0x2000, 0x3200)
r0 = open$dir(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
preadv(r0, &(0x7f0000000000)=[{&(0x7f00000000c0)=""/99, 0x63}], 0x1, 0x200000002)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x0, &(0x7f00000000c0)})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x45}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
syz_emit_ethernet(0x20, &(0x7f0000000480)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaaaaaa88e71b"])
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000002f00)={0x2, &(0x7f0000002ec0)=[{0x1}, {0x6}]})
socketpair$unix(0x1, 0x2, 0x0, 0x0)
getuid()
getgroups(0x2, &(0x7f0000001500)=[0x0, 0xffffffffffffffff])
getpid()
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000001540), &(0x7f0000001580)=0xc)
getsockopt$sock_cred(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f00000015c0), &(0x7f0000001600)=0xc)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x65, 0x0, 0x0)


ioctl$WSKBDIO_GETDEFAULTKEYREPEAT(0xffffffffffffffff, 0x400c570a, 0x0)
semctl$GETPID(0x0, 0x0, 0x4, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000080)=[{0x40}, {0x40}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


sysctl$net_inet_ah(&(0x7f0000000000)={0x4, 0x1e, 0x2}, 0x6, 0x0, 0x0, 0x0, 0x0)
sysctl$vm(&(0x7f0000000000)={0x4, 0x2}, 0x7, &(0x7f0000000040)="c06d154be3aee5f8787f8b9cda7554335b763bb5deea5ccecb4d1b57a9f6fa18e47fc7b119db587e58811e666e84a806495b45c36164bd5b135280243ed0a01466056e93082876ba33ee8cf2b0b3907f236f38175101000000d7e39544aea098d19ee63d03cbf92380dbe904538135f09e408bbe17a54a364b04ee64b0ad54e6d4e38114ced38c328aff2e224239ba29eb0796e8c3e8344a2cd9e663bb21035ebf391872f3015c164556e4a5b966122c56edd85fc996f12fa1b92e47aa", 0x0, 0x0, 0xfffffffffffffe8f)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000001180)={0x3, &(0x7f0000000040)=[{0x80}, {0x48}, {0x6}]})
syz_emit_ethernet(0x7e, &(0x7f00000002c0)=ANY=[])


getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x50}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0xfe10, 0x0, 0x37)
ioctl$WSMUXIO_LIST_DEVICES(0xffffffffffffffff, 0xc1045763, &(0x7f0000000040)={0x0, [{}, {}, {}, {}, {}, {}, {}, {0x0, 0xc8}, {0x3}]})
mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x0)
rename(&(0x7f0000000280)='./file0\x00', &(0x7f00000002c0)='./file1\x00')
mknod(&(0x7f0000000280)='./file1\x00', 0x0, 0x0)
r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0xd6)
writev(r0, &(0x7f00000000c0)=[{&(0x7f0000000280)='#!', 0x10}, {&(0x7f0000000000)="8d6bb85551ec8430877ae32fe9bbe42cc8f2147a3eba8e1969f0435119cf4c071c8aee7ef2921be5d7d4796c5566c95989acb3d185587234186e96b8fde9ffac51de05a87b8b893e2abd154dd886eafbe03881d25b7b13b4c32227fc9e5a86a06f59f701322b3a109a13436e486b0a", 0x6f}], 0x2)
execve(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
open$dir(&(0x7f0000000240)='./file1\x00', 0x8, 0xa8)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))


r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000540), 0x1, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x1, &(0x7f0000000180)=[{0x6c}]})
ioctl$WSKBDIO_GETMAP(r0, 0xc010570d, &(0x7f0000000180)={0x0, 0x0})


pwritev(0xffffffffffffffff, &(0x7f0000000340)=[{0x0}], 0x1, 0x0)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000300)={<r0=>0xffffffffffffffff})
mkdir(&(0x7f0000000080)='./file0\x00', 0x0)
chmod(&(0x7f00000000c0)='./file0\x00', 0x63)
setreuid(0xee00, 0x0)
r1 = getuid()
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r2=>0xffffffffffffffff})
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000580)={0x0, 0x0, <r3=>0x0}, &(0x7f0000000140)=0xc)
chown(&(0x7f0000000200)='./file0\x00', 0x0, r3)
setreuid(0x0, r1)
chdir(&(0x7f0000000100)='./file0\x00')
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000001c0)={0x0, 0x0, <r4=>0x0}, &(0x7f0000000000)=0xc)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r4}})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4e}, 0x3, &(0x7f0000000100)="71f95f84cf71b59c7afec37582", &(0x7f0000000080)=0x2, 0x0, 0x37)


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
socket$inet(0x2, 0x3, 0x2)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
semctl$SETALL(0x0, 0x0, 0x9, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0x4, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0xfffffffffffffe37)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r2 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7949)
writev(r2, &(0x7f00000000c0)=[{&(0x7f0000000080)='#!', 0x2}], 0x1)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x800, 0x0)
kevent(r2, &(0x7f0000000200)=[{{}, 0xfffffffffffffffc, 0x18, 0xf0000000, 0x7fb, 0x4}, {{r1}, 0xfffffffffffffffa, 0x4, 0x1, 0xffffffffffffffff}, {{r2}, 0xfffffffffffffffd, 0x40, 0xf0000000, 0x3, 0x5000000000}, {{}, 0xfffffffffffffffe, 0x0, 0xfffff, 0x403, 0x99c4}], 0x4, &(0x7f0000000280)=[{{}, 0x0, 0x0, 0x2, 0x8, 0x2d5375e0}, {{}, 0x0, 0x41, 0x0, 0xfffffffffffffc01, 0x19}, {{}, 0xffffffffffffffff, 0x0, 0x40000000, 0x10000000000006, 0x80000001}, {{}, 0xffffffffffffffff, 0x12, 0xfffff, 0x1, 0x80}], 0x80000000, &(0x7f0000000440)={0x0, 0x8})
syz_emit_ethernet(0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
r3 = socket(0x2, 0x1, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$inet(r3, &(0x7f0000000000), 0x10)


pipe(&(0x7f0000000100)={<r0=>0xffffffffffffffff})
fcntl$setstatus(r0, 0x4, 0xc0)
r1 = getpid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r1})
setpgid(0x0, 0x0)
pipe(&(0x7f00000001c0)={<r2=>0xffffffffffffffff})
setreuid(0xee00, 0x0)
r3 = getuid()
setreuid(0x0, r3)
ioctl$WSKBDIO_GETMAP(r2, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r4 = fcntl$getown(r2, 0x5)
fcntl$setown(r0, 0x6, r4)
setreuid(0xee00, 0x0)
close(r0)


sysctl$ddb(0x0, 0x0, &(0x7f00000002c0)="b151efd9ec9b99ce872e665d84241a5d2a4e39ba4a08d1bf87cc", 0x0, 0xfffffffffffffffe, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
recvmmsg(0xffffffffffffffff, &(0x7f00000002c0)={0x0}, 0x10, 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffff9c, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x2}, {0x9, 0x0, 0x0, 0xffffffff}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0xff0a, 0x0, 0x37)


pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000000)=[{}, {0x0, 0x0, 0x40}, {0x6}]})
sysctl$kern(&(0x7f0000000000)={0x1, 0x42}, 0x6, 0x0, 0x0, 0x0, 0x0)


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)
kqueue()
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x0, 0x3ff, 0xfffffffe, 0x0, "000000000000e140668afb7c18390000002000"})
syz_open_pts()
ioctl$TIOCSTAT(r0, 0x20007465, 0x0)


r0 = socket(0x800000018, 0x3, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x100, &(0x7f0000000000), 0x3)


mkdirat(0xffffffffffffff9c, &(0x7f0000000040)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
symlinkat(&(0x7f0000000540)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0xffffffffffffff9c, &(0x7f0000000140)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/file0\x00')
readlink(&(0x7f0000000380)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/file0\x00', 0x0, 0x0)


socket(0x2, 0x2, 0x0)
r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
mmap(&(0x7f0000ffe000/0x1000)=nil, 0x1000, 0x2, 0x10, r0, 0x0)
ioctl$WSMOUSEIO_GTYPE(r0, 0x40045720, &(0x7f0000000000))
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x6000, 0x416)
open$dir(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f0000000680)={0x0})
msgctl$IPC_SET(0x0, 0x1, 0x0)
socket$unix(0x1, 0x0, 0x0)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
listen(0xffffffffffffffff, 0x0)
socket$unix(0x1, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r1, 0xc0305602, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x0, 0x0})


fsync(0xffffffffffffffff)
mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x5d4a)
r0 = kqueue()
r1 = openat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x0, 0x0)
kevent(r0, 0x0, 0x0, &(0x7f0000000580), 0x65, 0x0)
mprotect(&(0x7f0000002000/0x1000)=nil, 0x1000, 0x0)
r2 = accept$inet(0xffffffffffffffff, 0x0, 0x0)
sendto$inet(0xffffffffffffffff, 0x0, 0x0, 0x1, 0x0, 0x0)
fcntl$setflags(0xffffffffffffffff, 0x2, 0x0)
ioctl$VT_OPENQRY(0xffffffffffffffff, 0x40047601, 0x0)
poll(&(0x7f0000000000)=[{}, {0xffffffffffffffff, 0x10}, {r2, 0x1}, {0xffffffffffffffff, 0x20}, {r2, 0x40}, {r2, 0x4}, {r2, 0x80}], 0x7, 0xf6d)
socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x15, 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(r1, 0x80085762, &(0x7f0000000c00)={0x3, 0xffffffff})
ioctl$BIOCSETIF(r1, 0x8020426c, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xffffffffffffffff})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x100000000000000, 0x10000000000001}})
connect$unix(0xffffffffffffffff, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x60}, {0x2c}, {0x6}]})
syz_emit_ethernet(0x62, &(0x7f00000006c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x7c}, {0x60}, {0x812e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000080)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
bind$unix(r0, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
setegid(0x0)
setreuid(0x0, 0xee01)
r1 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


socket$inet(0x2, 0x0, 0x0)
sysctl$net_inet_ip(0x0, 0x0, &(0x7f0000000100)="d7a8aac106fa1bee91c724b89283c1477dab85e783af4189a1eaf5f6e8251b1147b330f604ff639b9acd6202c9d8b1aef98ce6eefe712df21386a1f60bf4faf9867326180248fad514768c9928b74275ea8724a797051b934fc1a46677c194747c86477c2b49408ac33a50bed4dcd8d719c8e887ac6d1dca49c9ce71f944ba6751c604f18a9ca85cd10748825e5e32e72fc06c9d8f338de4eb9883b149513237c92b275cc73a320f63183363303ff9c417b6ed3f78a83a50368c9b2ce613b854c0e9bbda45c3aac729211c0bc3f3973c541cb95fa6a6696859", 0x0, 0x0, 0x0)
sendto(0xffffffffffffffff, 0x0, 0x0, 0x0, &(0x7f0000000080)=@in6={0x18, 0x3, 0x0, 0xffffffff}, 0xc)
r0 = socket(0x800000018, 0x1, 0x0)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892}, 0x1c)
setsockopt$sock_int(r0, 0xffff, 0x1, &(0x7f0000000100)=0x4, 0x4)
getsockname(r0, 0x0, &(0x7f0000000040))
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
setreuid(0xee00, 0x0)
r2 = getuid()
setreuid(r2, 0xffffffffffffffff)
mknod(&(0x7f0000000000)='./file0\x00', 0x6000, 0xe02)
r3 = open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
readv(r3, &(0x7f00000001c0)=[{&(0x7f0000000140)=""/18, 0x12}], 0x1)
preadv(r3, &(0x7f0000001540)=[{&(0x7f0000000080)=""/189, 0xbd}], 0x1, 0x1000)
r4 = kqueue()
kevent(0xffffffffffffffff, &(0x7f0000000280)=[{{r4}, 0xffffffffffffffff, 0xf5}], 0x0, 0x0, 0xfffffffc, 0x0)
r5 = fcntl$getown(r1, 0x5)
fcntl$setown(r1, 0x6, r5)
r6 = open$dir(&(0x7f0000000000)='./file0\x00', 0x80, 0x28c)
kevent(r4, 0x0, 0x0, &(0x7f00000001c0)=[{{r6}, 0xfffffffffffffffe, 0x41}], 0x2, 0x0)
kevent(r4, &(0x7f0000000000), 0x400, 0x0, 0xdb74, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r1, 0x80286987, &(0x7f00000001c0))


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
pwritev(r0, &(0x7f0000000080)=[{0x0}], 0x1, 0xfffffffffffffffd)


mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
rename(&(0x7f0000000100)='./file0/file0\x00', &(0x7f00000003c0)='./file0/file0/../../file0\x00')
unveil(&(0x7f0000000300)='./file0/file0/..\x00', &(0x7f0000000400)='r\x00')


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
poll(&(0x7f00000000c0)=[{r1, 0x45}], 0x1, 0x0)
close(r0)
poll(&(0x7f0000000040)=[{r1, 0x5}], 0x1, 0x0)


kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000300)=[{{}, 0xfffffffffffffff9, 0x41}], 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
kevent(0xffffffffffffffff, &(0x7f0000000140)=[{{r0}, 0xfffffffffffffffe, 0x2c5d36d679bbffbf}], 0x0, 0x0, 0x0, 0x0)
r2 = kqueue()
r3 = kqueue()
r4 = dup(r3)
kevent(0xffffffffffffffff, &(0x7f00000003c0)=[{{r4}, 0xffffffffffffffff, 0xc5}], 0x0, 0x0, 0x0, 0x0)
utimensat(0xffffffffffffffff, 0x0, &(0x7f0000000100)={{0x0, 0xfffffffffffffffe}}, 0x0)
kevent(r3, &(0x7f00000000c0), 0x138, 0x0, 0xffffffff, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000180)=[{{r2}, 0xffffffffffffffff, 0xdcd8c4bc089e638d}], 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={<r5=>0xffffffffffffffff})
kevent(r2, &(0x7f0000000140), 0xe4a, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000200)=[{{r5}, 0xfffffffffffffff9, 0x1}], 0x0, 0x0)
r6 = kqueue()
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f00000000c0)=[{{r6}, 0xffffffffffffffff, 0x6f}], 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000080)=[{{r1}, 0xfffffffffffffffe, 0x87}], 0x0, 0x0)
kevent(r6, &(0x7f0000000080), 0xe4a, 0x0, 0xa9fa, 0x0)
kevent(r6, 0x0, 0x0, &(0x7f00000001c0), 0x9, 0x0)


r0 = syz_open_pts()
readv(r0, &(0x7f00000012c0)=[{&(0x7f0000001200)=""/1, 0x1}], 0x1)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0xffffff9a, 0x0, "00000000f800"})
syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x0, "0fdbff0100000000000000000000ffbfffff00"})


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000132000/0x3000)=nil, &(0x7f00000a0000/0x1000)=nil, 0x80400000}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f000008c000/0x2000)=nil, &(0x7f00001f0000/0x1000)=nil}, {&(0x7f00001f0000/0x1000)=nil, &(0x7f0000001000/0x1000)=nil}, {&(0x7f0000132000/0x4000)=nil, &(0x7f00000b2000/0x1000)=nil}, {&(0x7f000008a000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {0x0, &(0x7f000002a000/0x3000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000086000/0x3000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil}, {&(0x7f0000091000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000001000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000132000/0x1000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000008a000/0x1000)=nil}, {0x0, &(0x7f0000092000/0x3000)=nil}], './file0\x00'})
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x4}, 0x4, &(0x7f0000000040), 0x0, &(0x7f0000000100), 0x0)
r0 = openat$pf(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = socket(0x18, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$FIONREAD(r2, 0x81206919, &(0x7f0000000100))
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x0, 0x0)
ioctl$BIOCGHDRCMPLT(r3, 0x40044274, &(0x7f0000000080))
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x8000000000000004})
semctl$SETALL(0x0, 0x0, 0x9, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
r4 = socket(0x18, 0x1, 0x0)
setsockopt(r4, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r4, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000280)={0x2, &(0x7f0000000000)=[{0x1c, 0x0, 0x1f}, {0x6}]})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
semctl$GETNCNT(0x0, 0x0, 0x3, &(0x7f0000000240)=""/65)
bind(r0, &(0x7f0000000240)=@in6={0x18, 0x2}, 0xc)
ioctl$VMM_IOC_RUN(0xffffffffffffffff, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0})
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)


r0 = open$dir(&(0x7f00000004c0)='./file0\x00', 0x200, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f0000000040)=[{{r0}, 0xfffffffffffffffc, 0x47}], 0x40, 0x0, 0x0, 0x0)
lchown(&(0x7f0000000240)='./file0\x00', 0xffffffffffffffff, 0xffffffffffffffff)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x6, &(0x7f0000000340)=[{0x25, 0x0, 0x3}, {}, {}, {}, {0x60}, {0x6}]})
write(r0, &(0x7f0000000200)="d81ad3d20cf7eb4e9be33bbd1a30", 0xe)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000180)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000001c0)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000000)=0xc)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r1}})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4e}, 0x3, &(0x7f0000000100)="71f95f84cf71b59c7afec37582", &(0x7f0000000080)=0x2, 0x0, 0x37)


sendto$unix(0xffffffffffffffff, &(0x7f00000000c0)="b100051300000000000000402020000000000000cea10500fef96ecf2ac72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf7f882b297be1aa0540000051e2f0ad3ebbc257699a1f139b672f335c223e7d0c032b0c8a6443a42118000000720fd38bfbb770c1f5", 0x6e, 0x0, 0x0, 0x0)
symlinkat(0x0, 0xffffffffffffff9c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f00000001c0)=[{}, {}, {0x840}]})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x8020699d, &(0x7f00000001c0))
r1 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000140)="67b5b992045c1a7733de71184dc12714990881d0d282bbbb82f88aee3375246d60d056448aeda248819c876f2c6e59c445667afca993a0516665954db86908d70836eed6da0b08d886dfd3ab4c442de33c74d0ff7946a83c180aed511af0d3eff58a00acff7ecc72afce9830fbd4edc05a5b077b39f6b4b7e961ce3c370f2f88a7bfe9e2762ddb30c131b1d20aa39f57ee", 0x91}], 0x1)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = dup2(r1, r1)
ioctl$FIONREAD(r2, 0x8020699d, &(0x7f00000001c0))


socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000000c0)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
recvmsg(r2, &(0x7f0000000100)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000180)=""/225, 0x11e}, 0x0)
sendmsg(r1, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r3=>0xffffffffffffffff, <r4=>0xffffffffffffffff})
recvmsg(r4, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=""/236, 0xec}, 0x0)
sendmsg(r3, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000100)={0x7, 0x54})
fcntl$dupfd(r0, 0x0, r0)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
r1 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
poll(&(0x7f0000000180)=[{r1, 0x4}], 0x1, 0x0)
ioctl$TIOCSTOP(r0, 0x2000746f)
r2 = open(&(0x7f0000001180)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSTART(r2, 0x2000746e)


mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x8)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc018696c, &(0x7f00000001c0))
r0 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r0, 0x8020699f, &(0x7f00000001c0))
syz_emit_ethernet(0x1fc1, &(0x7f0000002580)={@broadcast, @empty, [], {@ipv6={0x86dd, {0x0, 0x6, "dc8ed6", 0x1f8b, 0x2c, 0x0, @local={0xfe, 0x80, '\x00', 0x0}, @empty, {[@dstopts={0x0, 0x14, '\x00', [@generic={0x5, 0x86, "6a10b232ffbae714aeddf833ecf35cb76bf9eeea60b90b6fe9c11510ab38020760ae21d8c77979a1ab08b58a3108a14f38ba2fbcc18be06e698518f1deb78243f6f7dde2508fa2e217215eb73d6ffc5fd55ca8d7934b705d6c7964dab01d1ee9c7931c61c73ff49827fb484076e603c61df6e36077c3b2c46076860464de7557609d88d2c9d3"}, @enc_lim, @enc_lim={0x4, 0x1, 0xff}, @padn={0x1, 0x7, [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]}, @enc_lim={0x4, 0x1, 0x1}, @ra={0x5, 0x2, 0x6}, @enc_lim={0x4, 0x1, 0xff}]}, @routing={0x2b, 0x2, 0x0, 0x0, 0x0, [@ipv4={'\x00', '\xff\xff', @rand_addr=0x103ffffe}]}, @routing={0x1d, 0x8, 0x0, 0x6, 0x0, [@local={0xfe, 0x80, '\x00', 0x0}, @mcast2, @ipv4={'\x00', '\xff\xff', @loopback}, @rand_addr="b75d12fec39a66ba3c45c779ecbcb8f0"]}, @routing={0x0, 0x8, 0x0, 0x9, 0x0, [@ipv4, @loopback, @remote={0xfe, 0x80, '\x00', 0x0}, @rand_addr="f84aee7952f580a951353e3c247a3ba2"]}, @hopopts={0xff, 0x1c1, '\x00', [@generic={0x9b, 0xe00, "26ccaaf43ad51bcd8a4203319d1edff1ba5c80b7bd10656ec0d7ae904d29e239b8783edbc88edb813d61bd0568837ea7763e05a85c6736310089d5e9fb28f4bd80a41e6e60c7867df876da6d442d62be84855ac6862ee9ad8867c37bf1dab263d0421bf08ddac9431e17fe673e39b920d300ab171e18705071d1bc62e1bf85516e662fa9541f803fbb36b4fc0a2547241abd7e38d3634f72a9138678e0c883ed994a83d259b8758f58f99d3c37525d8a69100ec594f3af94c0cb8e8cfdcc9034b2bbd6f98f8a3b976dd069338d77686073333e3463711aa834934bc46546f1c8bcb18e37b64184e7fe40e0d2ea0ef52075a17d6a748a8abbe03a8743cb6c687c6cca76b72901b55f393bae5101ec6d6beec9723eb918bb1aa919193557e76cf9cc43d571ac44ee3d450bfc0e1ac159dde9576cac702f435c5d45bdcbc793319bb9ff77273e42e8bc9c103c07e9b60f086c5d9c515b54243ee8f265c5cdfd38d2a7469a6b71be30f10e36899b426b53530ed8f7a521957b197cd846bb28c919278a59189df5d69bb34769af9eb37161676890c4e6e7c41bdf1518df8c905696a591942258e9f182393a3d2fe83f1fbc1b159593c4483fbb3cad4fddfeb3fb0521ebdf971329736806f55d546055d10380c66767540124d299184e458bb981194a11e58c4fdca96db7eb4fe4bcb10ab7b27e54dc2346ee0b5f02dc4c24ddf7d60c8ed3d58ad1433a119bcf102fd11203eec99bd9ac728d9443009bde192981c9d2f1b25344698696cdf9dab743f535a56a2bb63cdb41f8c8efc6b5b307ae130b47573b4ced55c164819882c0f86ed765f6a5f9669800640f2e814d6d2983150535d51752d6277621ae80eb2302e4adeef22e28fd587bd62df0c8bdc7d6c525a40ccb4cb3bf34fd17b87b3adeaf3ea77190668f0175042c079b3d1c52aac7a72fe20c86fe25ae6e411455f08523b9f2141a2beb5ba886d39f0aa1fdb821c3f2838c5e3086209e1283d953abb61b376d1cd92297f6b52c9ac3dad8b1c03620db2271e7f610bc7481638ed0cd4b50b101a634078f1e5fb22b1b17ca72c8c48435f751fd022635dbbc7e64589f1884763b813f1c9d986a7d80d7fadc2a5b0efc6147b5a99f946937ae24021469ce6c9091e13d062fe7b7b6832eca61459e1c8ae6fe621bbaeef21cc6e0c62fa7889e15a33381e8d4a5c177df7c44bb20c58b65d754d2c01bb08f99b5c4496a2f9e6f15f080f4ff47550beee290cac899217aea50a6bb360399aa9c691472fcc4cce2971e038e6338f923ef775975fe3906a54270422b8fddb740b7ece9a4ab79243c60d7af9c3fa8d85979d3ac2a06bab55321f2c4bb61c557cc67b7c4ad412a99fb8d1745916555d5a8b61a2cffb29966dfe55195a6323a34ec8cc74e0a44875074a881438a01acddf880906079a6af59dca647a737c829e8075134655654fa5a08e340500de690c76f7496f82bb3369ecc7f7c5c6d1eb4b1c2dde686cc58318ab1dfffe20e1c11f4958d09473d5059f588eea9dbf322927ec360243b1a1a4501502741997db6f8dd35e12825e2a27bcb6695ebb0c254be5e7704b2f01813cc50979e68c61d6d9ac8221c2df9c4e44848c7f0dfc272a7538bbf9185b08aa47fdd17b090bad27173dedba26458db28b0cb7af5a3655ac9b0254fe453f9f2f7be31757da766e724f675b7a4c61b6af119a3a751660c84b3927e00d09a822d1529bd9a0110e5f3e35e1ed2a394a88c6b08005e21322311de19150aa5cdd2a73a9048a58657e1fb3534af381894628b279631171bd7634f1100d18c66c2a5b6692cd313ceba62d22323d26fdaf03f06530d1c1dfa67cdae3d6db16582f8704bd76a51d5399b557e04146add5da1c05f7e1968aa8d0270c9042dcd6916f097170a9caaa78a94dde28341f231ef7c3b068ce30986851f929680dc2db8f15f8c7e82bb0042a1172acd60ed29dbf7dbadcd426fda4cf9e51e70bd0203ffd0412f0d2eb3b4d958d21cc9a28e0a4143c05011cf439c68fdaef2d68c6066fba1832a8782b04ee11d29244e2e6f719d2f6198b413bc4a974cd17a2703d4860f6d6910859a9089b997d15a0ccc099d6de260654ac637a4a7eaa7cb1cf67d08bb3bb706a55037ea987d24c0874ad83d0481ff43d1e040368b15c98271d9ec74662501380e054bd292eeca73a3f7ea5a4a5f12ecab711f7ff4059376c3987af039279e9e8031ec08a9343ff9320413166780aef722e43e493726ce4188b93800f6a5acac04e6ce8d102cd08d7275e2254efa776a3ec7637850ee31cca60c6b48436654d29000e6ebedc6d62c7927474ca24fe98b40b421877fbefd84488112b007c27ea806ffcd21ba4bdbf33a81b2979009177e8067243ba28334c63f5c21516b657eda6a56d194c4a9972ba8ce69954723c766cd034d17e3cdceeb790c8de775502079ac806354e90012efe7c1cbf7a33d672df4cee35879985a44015f58c92ef293eb0acaa44e5438a5793d8fd558ab1f94922f551cb1df3be37f8a37702722587bf13a9012b5b3337bb1a6684fa4192d416c2927a8f324f8fb4f273575ea2ae5e23f02d52eb98005eb865a22b64d93cdcf2a0989324b29db5851d74b1a1dbb35525532b32de3cf8e08ca77bc6971198a0737d39b17e5a9e7901f9f72476f8b109f2dd36a9a77470b5103efcadfda2234a65b259d1d04e55494846ae7d9adce9ac03562ab06f6c11b147c885debef0da882dd26206778aebcbca5f8684f1bae81a12f891c11cbc537601749804e5240e7a184664e60571ae43c2eab85fc2286a6b045e9880490b8fbf79b4c663569de51feedbc1c5bb04dce1e82ade9c5cbc7e46d755ca882bcb04cb524e6906a9a0cef42a5bb4e670c4c032a7b069df5d1f92f4a1c15dfa3fdce086031adfaa80d5683f12f04f7dbaa0285ada2b47bee5e12823dc606bab0618af553071b30d3e3cd8b4a2c063979d6a428d0077dd82b71884bd4747b4073cac94d9cdf9bb0891e9fba79243672e9b8f999107aa36430d0961bc2153d1f6eaad4745b341689cd91cf9efd4b9ef3e98f7cda82149b6aba1802c1d3278c12a5c639254dc6897dfd412d7c92e21aa0f43d1d8f5d9c36c15ee194b95487c3f4ae77a47e4a2e1bdb8e9e1626ebdff6ed9562b9f7030724b4c892b995ba31854d394d1ef111b656f3d19e727031f1fa0a0f834eb680401c5e163d2b5dfa04ed893e15fb29c259045f8156d5df63eedc80e4253fe513f48007e1d5008ac9adfb8de32bb6e42ed34970333cf4c195182062f786cb9cf4d93e3be11e5e76fd9eb0684bc4aa157494648072919c79b03294e9122afae53a556773fa02d5607654f7ab88ce0e49a20e965330d7911dde03c998f25306accd26160bd8ab771aacb3b449289dec744ab7e2f2084afed888ec3de51292a3d0c3826a8c73f777b1deff20cdad6a946761dd3752b74ee6d1ecddb0bf5ecfa291772512a39ab97780d2c4964784c4cc265ad4589f32786c9cf12823dbda575f359de9a1624a1aafb553bf499164dc6e0afaf3d1038febc75ff0e0cea2521fa1b2767b9e2fa0a03933a6939c0001d09e6332089e074e24e5ae3a20255501ecd2b8cfbbc1547b30d7760eec0aee4baa5da0fc5c74ce5a22bda10f30fb5be5fd10f312da594593bae3a5077ea024f3af82c238403f74a4c06f5c64b9ba0b189993c898227e294c3a7509ee0cda17a6c377af0920e5d10d06f1180532a25eb7d5d139c4a8ac8c242a06dc39f3e36c96c05c66de7b20bf192e2e684ab0aa8ff32a229917fe33d0511bcd3c9e8ea6ee479d88f6d8dfb33d6f4083c1dee4389aa35193656fdfb563c44099ba45681e248a271c3e7012d59bc23973f0a4093780007d5ddda1fe38896fc9932eb22e479286afcbba69b4726ef41ab8ac00f2b33321e1b7f01f965e8b1b91ad9a867df274698b45ee79fff89b70cd1ccb16c034913e1f60fcff68cafde9e3de3a35fe15d3cda66b1de6eb974ff29156c35605daa05005a160a720113d6113b877d3957d35a903ee21a968ce2be4052b14960188b0a742650203549f56b1cf1d6a615242f82114c355219c82ff7f2119d9f7cb8dbe3de5a88aa38927c7a60d90bbc601bf858a6eb9000d0e18dfc918eb9bf45a55daf3615d513f1db601dd77a52c06fa18f6549d40972e7c7fa562ed957e6e3378b9184282c24c3f52ad3f45a0fa16d58fc169b29a35740632e53a565e77bd0f00107790d4ea65871dad4639541fa359525f1dedf2a79584f041d36ea11b1bef145a24297f8f3dd440e6666bcb96ab21bf609eb54819ce57e916da01639978363d51430c1dbc148ba29254e74eef8fac07b8550b45bbd05708fc75557fcf6259daf02a2cdb0906874ee16aa147aa839f963e7cbf109c547823a0292872a857a238d0544ab6649c47986ecb1d39d1a833028a8146a5980ba25ced7a977d588a86a743e5f4cc9311e3f1fe2f579828c602b9d8689a85a4e6185881ea63afa0ebc25da4839a61cbdb6753ac9aacbef31a957e4989752496927f925ac24dd40ae5c1063190e765d8baaca5cbe0d8f7838b494b1e7c90f18ce3321060b3315ea62cb93347963aec5ede2092560f4132986aa17b96d1d4f7b365854637dc75a29ed04ee9458a408609a6c855425ca1aa3faac2dd5cf7ad1f576ef011af27e92daa7be4bc63b1311bb7f883baad5674bba801965ac779604b8ecee92764ccc8d8f2f8c72c0836b3e8e7b909e078c5088432feaaeb609ff6e745bd79f643fc224e489d37d3b71f34b02f32b2043e32d6c3f8264a16a15b9a39306494e3093ce8e94f91ddc541a9e142a401d59f46d059d2b357a05974ea5111b37ea832e390861bee2da0a20add0afb2cc5f756b995a2db823569f806a872bb0b34a99238b2c5c055f4a346268bef7827ea31d54429dfb7355d28ba2845543c87753cac25edfab1ee4f18088803251a95150bf9b76e44ec25a7ec3fbeb54f3afa6df7005c6ffbdd27f2c07b6ff72f2537d11b8724ae82a1a999e9453de3cad8b485266db72ff11f1873227cf69e7a706c96c09e"}, @padn={0x1, 0x5, [0x0, 0x0, 0x0, 0x0, 0x0]}]}], @tcp={{0x0, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x9, 0x0, 0x8000, 0x0, 0x4, {[@generic={0x0, 0x9, "d537f64106a86b"}, @mss={0x2, 0x4, 0x3ff}]}}, {"b4a5c6cc5fbc5cd3be63c5502a30fab727766ef673f6612afc6818d6f5a4be5cd23c8395b00c613d52bb1dc44855e254d594dfecccf933bc2faa02d739a04fd917ea5b18cf61db05c1e1973a06362408adb1c12497a9cda638ab4496d947398f377f086ae1fc12014933f825c7fed73ad1d399f7b6acd6668747403bd7dcfdab2de58b35e6bbdf53822450edc3cc4d1596afab2a1f0aae2981ca99f6777fd49ebee4fb49be6aadc0eb82c04b0dbecbc5a0f629ab7783f724405bc49fdb8bb2072a2e316a2307829bfcf13f6c4ebd0a96ac116755e25cef663ee0ac63b88262e4fb86cf8f9fbf4a132664d25c336631c7441d552601a5025d02e387ebebf6d6b45570c0f7dea262486216ccda32d30691c540c614d72dd7cc22f943941b1bb675571fcc3c7602002ef32ec561f983e516e6ab286f4421cad21b38c5bc98ae164a623ba5c80a1e69f3cecb420cb2db05ca9aa0eba4103e90811887b79c076d26086796ae8f66b3d6f6ecd178ca2d1500529b7ae0676f69ef15590c45045290b31567df7c1c27cb9a3f3909618840d5e8c8d5f4bbea599226ea9000d50bfbb78e7cc4927e691f8983a68b852d508b1980b6cc7e666f77485a1ae49a32e66a59fde26544a8f73c4911afcbc9977c75004c456e3177946d2312b9412b6a6c5e9f1d21c08c7cfcd8a579e3d339b46d5246b045011599253da8c07e60c4cf9acdc93e91d88ed8c31e851c77521644479984b73a6f0097c5112dbd7144217e861d4c206d385b094307afe268ca2ad778143f187940005264300e8b47fae100e348c36b3dad01bd6c77a5cb9ead58d769f05056de088111dcbf4c25115f445d8f0a7cb9ba70606d4b606c114fe4ddd8e1cc02244e7fd68d2286c7ded35f04a76e6fec71d28e1e0f9074d1a741d076d18e5935e489aa46cb48165b87c9e93be19a2990ae00b3310c8b4c3497e7cb283bdc4120bf3b2d85b71513ed2fbc52cf1b0798c4a9b836d4e8486b894aa44ddcc0f9e54194cfb6fe3c5fa412af99f70c056f5972ab792bf9675e504d7695de92192d39acb4b4d06bb69c0786cffbad6c2f2ced27e56e2afc5f5890ea69ac01200fdc58998edf88023a504716aa5cd317b51fd34c8ce169a06abbcd93c8ba62838dcd4428e2cd7ea0b1eb9ff7162049778e8ffb762414000f90f1247a22b1abcc3d344a7a8ab05a0228bf117903cd813543c35fc704ac4ec979ef7e219488272c1e8f63110d7ffa36754479373933492871f3fc83777c6e4b13042486f6d1012566a1f15403587db78e54b13ea3c27a96326a3c6f8047c4500fd6677f4f55952c4893752e5a49a19fd51dc9dcb6af6f82c44249682927d2dc141dc9e9e41c8ecb9a491c98164432163c58b25a9fa3b193e013899857fbaf321b632a3e51e8a358944544413b816ee6e4c0f076370795b49d15e5c72879464ed5d6258b2d5a80dbbdbb466eddb1ec916cd7a1eb054d4633077936567cf42431f9769958c675266a932b1f1f92fb12e035d8dedf4d09e6cdf0ec6c6249a259fa9d8a9118dae95afee4e0d6abbc252a9934cd9ae4f982757b670afd890c633e32c647452df156e4c67ddd47160173ace68e8a1c3c93d9a9a6b33cdc837e46db03797df45ba0045e21a0853315fdb77dc1b04313afcef1b20208af645c91b05a3b2305fa7ddc511a51ff23ba924d89c9d52dce228c90ae99f3bc53102fe8cba90eea368ada2c9b8d486491456db6a8fe60fe9ae5a7bd4320363909368e6ba56342a6b029599c701a83213a486e2102427b7b32beb2083b2484f3bdd5f342eeb37a7130f5885e0330d190df35a50256fefe64e9c35548802a9ce2557ff0261486d5d9d761eb8f5329072dedbbcb2532f360909d8948f2bd822bd9ec9ecb99bef47a3f862555742c9c00fa2a9821161a0e0f97a411601387558a2ad107bb1ae62289f2c5b80390faa38558bfa38c68946579830d5def8ac46d99e55029d4f76a1417a15b1ee5f7f65d3673f764bf50fce78cef19740a7ce97bedb19cfc572afdc60db2d5be356079bef0365329ef0cecb382fa357ffd4b5e865d155feabf3e9c5242c4acf0b714b8dbb8831f641eaee3011f53646dc30e75c3fe3b6115bcea25f411642221dc79bf6886d72a5d39e6e95cf19658eecd1b16064ced5da9c9b6e6525151e2b10d089e686c1869ec303ce48d88983b0dab37cd86f513d9475ecdd432131b2ed3a871d64cc5e5feee9634592ac22e8c32008f41e60a1ab78612c6d4640fc3badcdb31951616711e2ed94d07a4d93a2ffc5d5c0ae03915dff1c19a5d69e3e5bc303fba946212457140e56d07788e6193b0be50d72eabff8f161f808cc65ef01c662465b02f01c40570bccf0a4a49f0803b6befddc34d23df59ae62aaf7851780314ef3d7e75fcd8748b97c5497fbdb4db9b7b8d6f525fa33dc35524b1f79ca406370542f24043b5d75eb33eb83e1cce1e88390be5e8ef45fa3e36489e77b9c47c00dc76d9664846f77127467e6a45578d1efcd2bc171353b87efea402480f691d6cb1e3668066fa7f0f7527fbc8020746f41bca29124c02898d4fbe6f278be22163946c515ea865847fe07cb3430ae01d590eb920d86ce1c8d593b979bd17358e5ce70a9c407446325a815084fe041826ce516561a09d4471171c70082160a2fb75b608ddb70184a84f418995bcdcda91178c0e5304567c56166f9f3dc5265c27f3f117ade5b98ba5a3b5273ec56fc796458e1e7dc08ee62d0097ac4848acf16d6b0988bddbd77bc016fc870b98e2a29e045d649611231d54262a09fdd89c094504ab25b5c4de59ec044c9b7c4a286282fed34c1c90a5464316d554702253deac6e07aedf4d185591ff3e04c16d69411523df7435a480081c6a1103b74997913ad32698c1bf7c55f2b93db9dc31fb5758f2129a5947e6559662e94a5c1802c112c84f9975a1544244747b7fd0546dc2ce624af0ac3514c9b153123fbdd9953cfdd4e4f5419e4b12c5673429888322a612501e577f6b165ee2cdc8e675aa1c3f29074837ec23272c0774e5554891a5218dbef28e782ef4a60a951c94aac76fba051834f0caa1644555b96bf24b50ade97c30f81f785f8131fcd2010b683b011d85496edf7fe4d271c3c1e111f9dbfb9cc7333bb78c4f39d697d9bcc32549f4b5a689bd9395ba78371bbaf69182d3f1d7152a122e1075bdcfbbd41d19015b4beec4c959d63c38d0fc5210177a091f2a57956b6bd3d3b18b1df07819ed8d12e56c6604614dea228cf483a43f5a83650e633cb65095eb1162ba1947ddefa178d5f19e6e3504ea9cfdbda45991a17878d621495bc4258264f75e708acd19e78a28e9c39ae92466e48c1c3ae899809a0331124bfab7a10c64f20381c40b467187fc3002c44384d7d665855e57f5b4ae77a1532344d1615a3825b0b95733448cc473d685222b43ed20848915eb01dfe7b5a77d1303d155c937932d1af972d5bf52963c36634b845ffca5c39c7e2295f97c4337ebd6bec0801d294398e031e9335a8ef7127d4c097e9dd3d215d9635280021495dd328810a7ec36ce5d8b5a3466a93019cb1631c003ca016363710b4bee6122e23442e7d7a6cb1f0e0cf9bc5fc2a61087b2aee419bfab3d4b34fd0f15767fb57370b368f76f0d4fe12abdae2d332f7e4377e7ec165ac97b4ebe65e34a39d9db68f061ba51a58fe340d489be11c3cc47829f40faa372aaba994dbe8f8e8750cb3e1d930f1ed8e6fca8764bfc40da21946bf56293796078bae4bccf8de7786cef5532156eacccbe3c0bf8479241ccb148c41b62ee4712ae7a7a3534c703a8fa974238d012c78901ea45ec282acfb98ce2a55207f922e4144a68845f12fb68e208a88c54bacaff664b88815554a83005ab6c4f341eaaf3a74930c87e358a7ae88c0ca6150bb4287333de77327e0e19efbc19be022352c20c319c87b98d95951482bc5ab325ba1f94fbfe45747c7376ff7ea82b932267cc794ce2cfee0ba62bbe42d7cafe567068e971c524f1b0246f7b256bfd3e570eb1d7446b9c115f310124f6836d8a05fc8c18993722cb8ee4a585b890225a47e68a867c4560ebf3b730fe23ecfdfb24ce64fdc8bb01579c0ca16ccd21327ee0f94155eb804ca5a67fb5d894d12245f87e8ad332d42c8aaf3f505e6e8db3672a4949ca7be05599e91abaa2e2821fef8860ac19fcfaf4f25ebe9dd1d46aed11f489bc151e153e75b8c4c2ea9f3e9009b90587d617cc2c9f95848365220b7cdfd9929154fba9e0770a032fe168deb110a568d329680287fbc2c25efebf012ec168f8e4bcfc49c9891255c3c16cdf2d8f67ec9a65394c860a8f3cf82b40c92f964775a6b558986c780a75efca376a8eda63a274f5ccd5c301c73f00baa5655516f7c50e3ccb97ae884430267400f29e854f0efaf8a591e6e655c5da314ec1999f5a19c69d8bfca82e176d45c867ece30a21eeb19984893f1d3bc66d4185e68be214e4799238fda8107d127c66e03de4ab7640069137063dfad2d99f341c0cb90e5c53480611f14a0fd4e9093bb75eef7db8cfc93d1b506a03bbbcd7023571d30a92fb0b66a34aa98470e60f591fe20dec30cd70a8bd94612ac682f6675684912373298e42bad48bba871df172ba5420db7ca650dd60e3f182c8d6c468b584319f67b8175da39d475f0f7bbce630e7d14198f20acef2d871e448cbd2b666bee726a24bf0d4cdcdab9905f82ef0c3dd2dda5136dbf24de9edc1104a8b8b36769e9d855759ce268554088c42279cb75b7a50db1048321b42da2c865e2fe29dcf04b1e8111b2c852d4b648beada6cfd9984bf5969bec28bc17124919e5cc47083801561ee67fe7c54673ac36784a01940d4d2527dcdfb675def5834dc8d91c2ed7c4baa38174afcd3279d2bd40e95b78996befae86bd13d44ccc8e48a6eb1cbd9b93764434645727c3c5dcaecab0aef237d07d8f7f8c411a49235812242cc8a4260eee582235c290a3a179a8c6b8b3878da99a20dfcb126e76f3ae9d76c5ff07dcb4b14c670dcbdb68dda9d8389a6fac563c9f013d21448989f960d9d4d81511e09d5cb450718e4315e2ab91ba671e506c8902c3a2218a0fa6d312d895d410c30acf77cf29bd7ac2e50f7d4403be459e79734066880c1d0be8116caeb30d69dd61ce349bfcd348bd4cbfc725a2f9cc1bb4e7cae727644790b37daa184062b261d3fdc34f02f075af8398b9a8158943f0f6de3c7e6d424c43f663e79d4123a157e67cca750aa998315d623986b509e945162cb4aa520bcecd3c97d5306054d575128e0d8c175e7dde572d4263a42c6aebee3db2615dcdadea1997824282e30e16b1581ec429a21c1b9c51f47fd89330a6efdd72eec136a5267050ce139b07797f18736fcfa040eb260e73423e30323beeffb741aedf39c2d17ca39977485cf28dddff6c50b7a755ee21d007c1cf66d735f0a4aa33bfdc4ad555c24bdaf730d06863a3bb9aa8ceced3ca4e45f2f0c17a52d0c29adddcffccb9da129de98a8e1689b76fefc1db6246f180d908277d171ce7f17b5d5447ec01cfdc914b85510865ba8e1f0b8af57341214a43dc2c074c9f843f7810300f26cf138c959d6161c9f0acd9ce34b21a50aba1847f2809160c9858fcf32ecef92b5dc6d326c81c84dee5da9135adc55c1a5ea284845582d6302d6ec10725a878401a94f0a0472830ec35a2ec455c98e14593f45ec6cefa8d84781b64d680fba3df18fa111f9fbd59f4c1086baa81f4637003d8a0430e0efcf68012eb0821f5"}}}}}}})


sysctl$kern(&(0x7f0000000000)={0x1, 0x47}, 0x3, &(0x7f0000000080)="b9d55a65edf95074454cbeef747750212b261340975c61c98fc44606f6c84c8106c596189f2824da6ce26ef22601faa932f8506c338734f736b71fe63c3db1e9d4ed2ce08ee7f16195ac49fb6ee8486b47aae9157492458d108d0fcface1392fdf88be327280a9ccb04d81e8c6efb7ee", &(0x7f0000000100)=0x70, 0x0, 0x0)
ioctl$TIOCSETA(0xffffffffffffff9c, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x3, 0x0, "01000000d000"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000040), 0x3, 0x0, 0x0, &(0x7f0000000080)="4f1d4c6344b80ed788b6a4515248df3aa745bb992c574ab4cdf5587145812eab4a988f7fafd7a01d99776d988908cd186b51f34f8c15ffa0c685ad4116c783959eff4278384b4000384dbb1c2aaeff10b4135529a1da6fda67c67469d954be811b25ec5521559154c586eefff122009f659cd3e27e98a3241495005f102d9101d158284c0ee3250aa7c11042330de22a299ab00894fdc9bac6042d", 0x4)


r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x800, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300))
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, 0x0}}, 0x10, 0x0, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
setsockopt(0xffffffffffffffff, 0x4, 0x77, &(0x7f0000000040), 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
socket(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
setsockopt$inet6_MRT6_ADD_MIF(0xffffffffffffffff, 0x29, 0x66, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
syz_emit_ethernet(0x381, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
close(0xffffffffffffffff)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f0000000240)={0x0, 0x219c, 0xffffffffffffffff})


r0 = socket$inet6(0x1e, 0x0, 0x2)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x8, 0x0)
shutdown(r0, 0x2)
sysctl$kern(&(0x7f0000000040), 0x2, 0x0, 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x8, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r1 = socket(0x18, 0x3, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
getsockname$inet(r1, 0x0, &(0x7f0000000000))
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x1, 0x1, 0x0)
close(r2)
r3 = socket(0x18, 0x2, 0x0)
setsockopt(r3, 0x1000000000029, 0x2a, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
mknodat(0xffffffffffffff9c, &(0x7f0000000400)='./file0\x00', 0x2000, 0x0)
syz_open_pts()
getuid()
r4 = getuid()
writev(r0, &(0x7f0000000280)=[{&(0x7f0000000140)="07f04111f163833ff790a8a8e2e8560c2a71ebd72b778672b065e531c57bde7ee015219cd39e14ea15220dd600198d0f99860fffb8220b7abb4b081673555f27ea8ebef4fc8eb5077023b664e4919b674399e5d073e25f9edd089db94c75c090efdb4ba80ab4492af0e3b37334926cc46ec07c71fe3d527e1aa306a23f7529c5f6bb5d3f3acc08d7730413c1c55d5db314745c994792a8146b57b20aea48f1930bc742283e38ed551f3898fe27e46b64f11730660c24725e1c6f8093c50352021d26bd69e47cba5c92ee67d2", 0xcc}, {&(0x7f0000000240)="437651ffc323f9efda259590e069", 0xe}], 0x2)
r5 = getegid()
chown(&(0x7f0000000080)='./file0\x00', r4, r5)
r6 = socket(0x18, 0x1, 0x0)
connect$unix(r6, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r7 = socket$inet6(0x18, 0x3, 0x0)
getsockopt(r7, 0x29, 0x67, 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
r8 = msgget$private(0x0, 0x0)
msgsnd(r8, &(0x7f0000001b40)=ANY=[@ANYBLOB="0000000000000000d577a0f1b55d40de92ce05f2148950092f35d5ade543c2e4251bcb32f02a4bff9dd478c1be726a51e302e16c6477cafe3be5feddb3802341be47d5788ea28fe01bcabbc896e693a2dc9c2719a5a7cc02b129a218cce33a7d4f2484a641ed0df6a538e610a3578a7f44126f69a8d99974556a9f33c2689450ecccc386c5b02de7fba562a34e7f102c4f861d62d4dc76ede826d2c00e4ee6d1f68d2af2b9d42a6c0bb375d3b57d9730009e0e9ee912b7196f0022f1c82528e471eea347dd45b0ad7655a5cf3a7fea1b1a0d35b50b490cc27624261977a7b11d9b0a440860644050e8b67c0d4921f2ee950a4bf5507e43d1dcf6ab60d77e4e904664e6d7d93009752264ab69bf744dba4095b9c3d0091e84a8d0497343f033c5ec94bb4017643e3c6c13e01006084beaf2e1a2b3bf"], 0x135, 0x800)


r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)="03000000", 0x4)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000180), 0x0)


setitimer(0x0, &(0x7f0000000000)={{}, {0x748d}}, 0x0)
setitimer(0x0, &(0x7f0000000300)={{}, {0x0, 0xa}}, 0x0)


setrlimit(0x8, &(0x7f0000000040)={0x7, 0x200005})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000380)={0xfffff732, 0x0, 0x1, 0xdfdffbc5, "97115f55ba7d00fdff0104000000000000de00"})
writev(r0, &(0x7f0000000640)=[{&(0x7f0000000e40)="e13fa9212931d8ee6352c725c85a25122308b30ad9a5965d2c913e3c4f454e00198c9ebeb7806cbcf3a69928bdf899c1a1ebab7b526fc163e0bb30d52a9488e5cee5730cac687f868e2284c92de346b34d7c3a42644a591b3e7f97520d78df583e1b6d86cd2174ebde17d373037a36f36acb1541c91ff86e1ec85a23330afce9060a87f904092a7ba4d5004807383537eb2f306eed2efc0341063d9766ab2ef5e326fe2dfd8cfeaeb76bfacfd6fcaf2f3a3d0dc1d3bc7886701653f44af4e719bb242fd3f93d53970e3412273470b80f997987988fe2bed79ab67e39955486fb9046949ab9d562fa10042a5956acc4367ef930fce1ab0b43315772240d84e84470cc4eb08deeea115b350811d287253a41e6af8aee35ae3501443994ad2af8a8ae6e9eeae2ab91da38975f0edfb8a26ba377c4cd2d173424eb2d3751a8fe28627f431d5a44f0a1fa0afa89fd495e9ab357b9b194becbf033a48592c28e3d37da4b16e18373554c0702e02548c20b91776d70847ad220b8096e091be9dd100451f0bada5d1e17ff2c8c4ef1984ad8e8947d60884948a47e883390c5e62cca6375003ec2a5ebd85124be5b8fc71652aefb8d40b244399987bbf78e4e2e79a298102e9da27512b6c2934925c062615898b1ce6c3a0d0dd683a5a4aa4059b4b2c830f4392a7462f41b43c7624783b9170b86e05480f36bcb225e9bb724677d0e0e85daa9ed84aa4a9b5d649cde0f2bc46a12085cede985ac43c78959539392ebdcf3a98c5f17de7c8fd23d1fe2c81d5cf42620097923dd308949f847491ac3df2fff386a44568b06f3d622f818e0a2598fc5a0929a3389364c10e5342e2feb25997cf300dadac696ba54866bab5a1db34f5be2fe21bb2809b37899411d758d100baa040c2e3bfb3edcabaf0832d8e177d1a53d9b352ccde07bdfe8bc241b2cd3bdb679f16c34b2c72a0daab859f2c9727db1f13b8127f044f38fa355ae9d3ff5abec16fbc68065ad8565d3ca0152a9b09602db43df6c950b25e05ba449f46c5e429ebc56653e163852287aa5f34892eae9b45f25a818a35ff75d4905f9ad2fe70cefacde817e806a79dac99687fa632c3e48c2e86bc14122d00b73b791290412de26363830e726d84451fc9c8087034afa766d3024eefa9c532989bb58771ca358846db4a333f93f2b994d23a1a0c68815aef9696626029749242d941d25658b9e0092ee4228227447a746ee4501b71060da63a38bc90f74ccbb99bf005885155bfec981e80367b9e3ec10f850fd2e307caf22c8d95c532f63c8d9e659dbd709d951e95af57a1c6edb85da71ba6e7ac78715702b852b00a3fbcf923c7ae830014cc9c8d3bef47c3d4cf56fc99e70a8d16d195c9b7598a01db6f46fefb4de63ad0187bcb5a1fd839437b12e4c3c94cc54f2bfff45a0aee394c085b8408b1f13f65fe9f322ca94f0f484b5b8d9cd1000dde39a2f5f23bb170726716818c4019dfc3d6ce6655e7d7703b61a313319f3829dc4ad9271453dbeaa7ee8fc3df53539cc7aeeb097a587e316e01b8cd03f128f282938d9eda70efe1b9ec751728a1eafd40df058e6ee11709df4adc10ca349ead09ea75c80d7c8d4663bd0009981d7ec94040967c2ba69459f4609db7b881db5793b7b0743a5c633f003dc335a1214dc5d2fb419671e6562460685c1f1c7fc3567cf79e3838e7eb1697ec0ba09a1a59314447a164b064bc2baf8823b3e97989b7f5c2fc7e98fe6fd30b6e5378c3f2c81b47c71268bd770d77dc965fca2c8955534533e23f2e26edefe731f6e536869678a0b6bb16c7a53760ea26b3d1233549290a751247549bbd9e383280b66770d06accafa95f6df88689d6df93b696b6db134ff19b0c5d1f3889ce412be7b278651c43b8103f8b05b7610d3f88def8687202281da1459af49e7db732a21857e6ffa9b17d6175b6b287878f5685dd96cee4bed1dcfd8c3a72f3441a968645236a85cc8f6d5df8c67fea118b7386d81208521e60a723a8bb1b40699c9cfc534f3a5c10dfea830aa769e055f8a5100d4fad99cf10b281d808d21fdac6b3419df172d87d367616726abb0f3f810c5aeff0a59b6f3efa71da21416c08e7691413b961dadf67e25b0b0ecf6a0e11cc6de87896d5cfd639e3a00e72ba03b45a24c557d9f9f2f863c99186dffdcb9844d9128c1e330ee9f7b9737987af672dd34a7b8fa6355df5a6f24e369c6f825d9f3f1a9d720de73c527960a8f7fa61f91dde8ef47ce1bb3bbbcce51c35587c04e135ffb10f4db43843bc7a3a793f037958c39190f997d7f0c75fddfed9f3d6b912c03ee967f4dde3647363a16832f9fe95d8022da0aeb8859033436401f33ea5bdb9c7e46b8452075894624ca26a81f01b37562b75a529cd5ba09e01394cbe6b555a0054682ceeb46d796d8b975baa326dcc38af3a9ada9e2630f0c91febff25a2d41bd2801fd257bc3e13fef7f162fc9115e30d7f6edbbfd5669d70b5ab50698510dca584b96e9728569557620e6a4be4f21f19b65ca8bb27d0558654a71a7c007941351b2066ea96ac027971e685b793e5633ce54f77469b6c69d835a35eef418733f5095e3b10e2158b3ca67f6af0b107f31d559d45ae4ebb26d7b67fc6f848d7fb1859d036ff2deafb1bfa153fbe0bc66c764787ee6af35a841f61da192a2d39e6c6da12a25d131ea479ac783c1939c937bfb9c2b17d8cb3e15c37f209c9825c7ec908c3eeaa10ac8062ac9bb18fd1a57c405977c81a27881f78040367c188fa3fbead77dd477e913b829fa6f3e10d6da1e74411ee6c25d32020032edb00c84b52f793e96cb79ba27b73bc53f695abf80776584caf4fb5a50493d9098ce6736937eb6f9dcf72d37e21a8c12f47ed55d8500701a599592a330e0f47c7f70f5be241bca3757d6b4d0fe937a63f6dddbdae7ac40d9866dd011906bd78a177920283e618c8548e61c8658dbb343e9ab803653095cfe8c61d7bfd144aa6b491376e997099e325638f91eeb99981ca24212d1e3fc5024cd89ab8bf71cb09c5ad84972e527aa95661e62466c40bced907fc74a8c99cfc3808494f514540d93ec5cb485466a9bd90ff03e6ed6cd95699eb27981150fbaab3ff9a6705b8b5bb28a092b5c1567b8e0da00bc6a1c298a7177cc0851a8b3956857894a74c801586765006b14c5709dc11f542df897488530d1d60e8ca68f3964c7f0ceaef168d66fb09a44f73dc62faaa53f7d417f1a70e6af9982dd994ad80996b2b23718f5af58f9a9d37663cc833e059f6c287be955ae1fa64cb84917c578e1393ac3dc90913956500a1c970fad3eff0131b2507febeeb9e08b7e5916577a41453d855e6435694981fc8d00ac55f3e7ffe640144864900f076297da336e69bd09b6fe7751e30ac3624aa6e534af569376f36cb28f3b19f8d416a0a5b47ca20ad0d429e3f09af2dc84973a89dd2eb2758fa5eca9dfbb0442f86d34b61cc47034f4dcf0dc523592d9223ff9329aacbd1a31d855211b2dafad6ac691237adf36c7893664ac13462c041aa0a6bd1655bf8d28bb35bb63c8dc29", 0x9d5}], 0x1)


mlock(&(0x7f0000ffd000/0x1000)=nil, 0x1000)
pipe2(&(0x7f00000000c0)={0xffffffffffffffff, <r0=>0xffffffffffffffff}, 0x0)
shmctl$SHM_LOCK(0x0, 0x3)
setreuid(0xffffffffffffffff, 0xffffffffffffffff)
minherit(&(0x7f0000ffc000/0x4000)=nil, 0x4000, 0x1)
sysctl$hw(&(0x7f0000000100)={0x6, 0xd}, 0x2, &(0x7f0000000140), 0x0, &(0x7f0000001180)="c59a8dff2d1901506e2d91b523c5314a351b3b070b6f3043e890e69279d0968b3c884ae0b1714ae33e32fdfc2b7eaae2268297", 0x33)
connect$unix(r0, &(0x7f0000001280)=@abs={0x0, 0x0, 0x0}, 0x8)
shmctl$IPC_STAT(0x0, 0x2, &(0x7f00000012c0)=""/95)
r1 = getpgid(0xffffffffffffffff)
ktrace(0x0, 0x0, 0x1954, r1)
r2 = msgget$private(0x0, 0x441)
msgrcv(r2, &(0x7f0000000440)={0x0, ""/254}, 0x106, 0x0, 0x800)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000001140), 0x0, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, 0x0)
r1 = openat$wsmouse(0xffffffffffffff9c, 0x0, 0x1, 0x0)
chdir(&(0x7f0000000140)='./file0\x00')
r2 = open(&(0x7f0000000040)='./file1\x00', 0x0, 0x0)
mkdirat(r2, &(0x7f00000001c0)='./file1\x00', 0x0)
renameat(r2, &(0x7f0000000140)='./file1\x00', 0xffffffffffffff9c, &(0x7f0000000340)='./file1\x00')
ioctl$WSMOUSEIO_GETPARAMS(r1, 0x80105727, 0x0)
ioctl$VMM_IOC_CREATE(r0, 0xc0285602, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffa000/0x2000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffa000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff9000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000ff9000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff8000/0x4000)=nil, &(0x7f0000ff8000/0x3000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}], '.\x00'})


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x2a, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000280)={0x3, &(0x7f0000000340)=[{0x45}, {0xc}, {0x8126}]})
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB])


r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x28, &(0x7f0000000000)="5ab7776a", 0x4)
syz_emit_ethernet(0xba, &(0x7f0000000300)=ANY=[@ANYBLOB="aaaaaaaaaaaaaa00aaaaaabb86dd600000000084810000000000000000000000000000000000ff020000000000000000000000000001"])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000000c0)=[{0x3d}, {0x2}, {0x8006}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])


mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x205b9a)
r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
writev(r0, &(0x7f00000000c0)=[{0x0}], 0x1)


kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
r1 = socket(0x2, 0x2, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])
r3 = socket$inet(0x2, 0x3, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x1, &(0x7f0000000240)="01000000", 0x4)
r4 = dup2(r2, r1)
openat(r4, &(0x7f00000000c0)='./file0/file0\x00', 0x20000, 0x140)
r5 = socket$inet(0x2, 0x3, 0x0)
dup2(r5, r3)
ioctl$FIONREAD(r1, 0xc0206923, &(0x7f00000001c0))
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000a40)={<r6=>0xffffffffffffffff})
r7 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCIMMEDIATE(r7, 0x80044270, 0x0)
dup(r7)
ioctl$BIOCGFILDROP(r7, 0x40044278, &(0x7f0000000080))
getsockopt$SO_PEERCRED(r6, 0xffff, 0x1022, &(0x7f0000000a80)={0x0, <r8=>0x0, <r9=>0x0}, 0xc)
chown(&(0x7f0000000c00)='./file0\x00', r8, r9)
seteuid(r8)
r10 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
fcntl$dupfd(r10, 0x3, 0xffffffffffffffff)
ioctl$FIONREAD(r0, 0x8020690e, &(0x7f00000001c0))


socket$inet6(0x18, 0x4, 0x29)


r0 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
getdents(r0, &(0x7f0000001180)=""/4096, 0x1000)
open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
r1 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
writev(r1, &(0x7f0000000340)=[{&(0x7f0000000040)="94c79bd261e1e88e83beb11c0a3e154df77b5335bd1667d9fd77c59297b3cad0ade427f63f2912518a179b7c207bc5ba040a20b5c36bfaca54e49900550bad2f165552f266a6b12d4900c56a22e814223e67a3fdf5ae19bcbb5d0a815015db8752d03d1b08f84b4976ec52d4a82598424ed3a6a523a3591db0e862a2f4dd1168cb17845fff1fb5df5535cae3e20e2bdb92138d0c1b0720e1c121ccb763f092cd5dcaa3d901", 0x2cfea}], 0x10000000000001fc)


ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, 0x0)
r0 = socket$inet6(0x18, 0x3, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x0, 0x0, 0x0)
socket(0x2, 0x2, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x2, 0x0, &(0x7f0000000080), &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458b", 0x69)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x1}, {0x4c}, {0x16}]})
write(r1, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xfef3)
r2 = syz_open_pts()
ioctl$TIOCGFLAGS(r2, 0x4004745d, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
syz_emit_ethernet(0x4a, 0x0)
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000000)=[{0x20}, {0x84}, {0x8106}]})
socket(0x0, 0x3, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x5cda)
ioctl$BIOCGBLEN(r1, 0x40044266, &(0x7f0000000200))
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r4 = socket(0x11, 0x3, 0x0)
sendto$unix(r4, &(0x7f00000000c0)="b1000504600000000000000007000000331c13fecea10500fef96ecfc72fd3357ae320b37b673039d2d236073705ae04be38164991f7c8cf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139b672f", 0x52, 0x2, 0x0, 0x0)
sysctl$hw(&(0x7f0000000000)={0x6, 0xf}, 0x2, &(0x7f0000000080)="1d6306b4eefe033a28a8c4804f12fd236729a090", &(0x7f0000000180)=0x14, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f0000000000)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe2c63a56077123a276d3ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0xffffffffffffff7b}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
mkdirat(0xffffffffffffffff, &(0x7f0000000040)='./file0\x00', 0x0)


pwrite(0xffffffffffffffff, &(0x7f0000000000)="326813522e7749cd418cc01bea6a35", 0xf, 0x0)
writev(0xffffffffffffffff, &(0x7f0000001300)=[{&(0x7f0000000000)="f4", 0x1}], 0x1)
r0 = socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f0000000000))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000140)=[{0x20}, {0x2d}, {0x86}]})
syz_emit_ethernet(0x127, &(0x7f0000000040)=ANY=[])


syz_emit_ethernet(0x22, &(0x7f0000000080)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @broadcast}}}}})


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff, 0x192}, 0xe0ffffffffffffff})
socket(0x2, 0x2, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001280)={0x0, 0x0, &(0x7f0000001200)=[{&(0x7f0000000180)="bf3b684c5ae963b4567084e096cf973983b85e5df63e013eaa9405095e88157332b4f68e78e0793d3e30417acbf4419893cfd424b75262dc5ade2ab6278ab86672f9ed186987b8c19d9295a17b98020f6002", 0x52}], 0x1}, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
setrlimit(0x8, &(0x7f0000000980)={0x7})
r0 = open(0x0, 0x611, 0x0)
openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r0, 0xc2585601, &(0x7f0000000040)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000ff6000/0x9000)=nil, &(0x7f0000ffc000/0x1000)=nil}, {&(0x7f0000ff8000/0x2000)=nil, &(0x7f0000fef000/0x11000)=nil}, {&(0x7f0000ff4000/0x1000)=nil, &(0x7f0000ffb000/0x3000)=nil, 0x4}, {&(0x7f0000fec000/0x4000)=nil, &(0x7f0000feb000/0x9000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ff2000/0x3000)=nil}, {&(0x7f0000feb000/0x4000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {&(0x7f0000ff9000/0x1000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {&(0x7f0000ff0000/0x1000)=nil, &(0x7f0000fec000/0x1000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ff4000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000f8c000/0x3000)=nil}, {&(0x7f0000fe9000/0xf000)=nil, &(0x7f0000fee000/0x12000)=nil}, {&(0x7f0000fea000/0x4000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000fee000/0x10000)=nil, &(0x7f0000c2b000/0x3000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000e35000/0x2000)=nil}], './file0\x00'})
ioctl$PCIOCREAD(r0, 0xc0187009, &(0x7f00000002c0))
r1 = syz_open_pts()
close(r1)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f00000004c0)={0x94, 0x4, 0x2, 0xd29, "87170abe000288f115e03a90d692480d45aa00", 0x0, 0x2})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
open(0x0, 0x0, 0x0)
r2 = openat$wskbd(0xffffffffffffff9c, 0x0, 0x1, 0x0)
r3 = dup(r2)
ioctl$WSKBDIO_SETMODE(r3, 0x80045713, &(0x7f0000000400)=0x1)
chdir(0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000080), 0xc)
r4 = semget$private(0x0, 0x4000000009, 0x51f)
semop(r4, &(0x7f0000000280)=[{0x2, 0xffff, 0xe5ce97ab354d96be}, {0x0, 0x4, 0x1800}, {0x0, 0x0, 0x1000}, {0x0, 0x6, 0x1800}, {0x2, 0x8001, 0x800}, {0x2, 0x101, 0x1800}], 0x6)
semop(r4, &(0x7f0000000440)=[{0x3, 0x7}, {0x1, 0x3, 0x1800}, {0x2, 0x8, 0x1000}, {0x4, 0x9, 0x1000}, {0x0, 0x7, 0x800}, {0x3, 0x3f}], 0x6)
sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000000)="9b1809ffff0504000000000000c484e0e745e10411ef7f0abdbc34fe42021588dc8fe44f4b76c769e3e1836e4185727d5938c9e1479d2dea800dabe4", &(0x7f0000000040)=0x10011, 0x0, 0x44)
ioctl$BIOCSETWF(r3, 0x80104277, &(0x7f0000000340)={0x0, &(0x7f0000000300)})
sysctl$kern(0x0, 0x0, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1c, 0x0, 0x0)


ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, 0x0)
dup(0xffffffffffffffff)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x40b, &(0x7f0000000100)=@abs={0x0, 0x0, 0x0}, 0x8)
mknod(&(0x7f0000000000)='./bus\x00', 0x6000, 0x504)
open(&(0x7f0000000040)='./bus\x00', 0x10005, 0x0)
sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x26}, 0x4, 0x0, 0x0, 0x0, 0x0)
getsockname$inet(0xffffffffffffffff, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
sysctl$net_inet_divert(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
setitimer(0x0, &(0x7f0000000140)={{0x0, 0xffffffffffffff7f}}, 0x0)
mknod(0x0, 0x0, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
readv(r0, &(0x7f0000000300)=[{&(0x7f00000000c0)=""/169, 0xa9}], 0x1)
getitimer(0x0, 0x0)
accept$unix(0xffffffffffffffff, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)


sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x6}, 0x4, &(0x7f00000006c0), 0x0, 0x0, 0x0)
r0 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r0, 0x0, 0x20, &(0x7f0000000140)="caddf7f2", 0x4)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f00000006c0)={0x0, &(0x7f0000000640)})
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000500)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000300)={0x2, &(0x7f00000002c0)=[{0x0, 0x4, 0x41, 0x3ff}, {0x3366, 0x0, 0x85, 0xa}]})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000700)=[{0x4, 0x0, 0x20, 0x57cb}, {0x30}, {0x6, 0x40, 0x2, 0xfffffffe}]})
write(r1, &(0x7f0000000740)="76e5dead6f01f8607d21000000630fb49c097a5e1161dcb79d2875e718bdef21a4a826f8b07da3a0c664e0af29a67d70e14a47ff6e05ccd1f7d32fbc127ca73ce233404872674eab226837f4b01d39751b9f5e1acf5d6dca454a73500622b962eb56f63c35a72f21f7162ccd0417c5c82e1c44c9506fad549535cab88725c92e4ea9cdbba98eeadd9a6ea51ee0d7544694e864e4372e9f53cd8fcc652d228e63c215dc9abe8c7532f70c40f9d3f39c12660ba62e5e609c076ca577740ed8a41df5fe", 0xc2)
r2 = fcntl$dupfd(r1, 0xa, r1)
r3 = socket$unix(0x1, 0x1, 0x0)
ioctl$FIONREAD(r3, 0x80206979, &(0x7f0000000000))
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000200)=[{0x1, 0x7, 0xe1, 0x7f}, {0xf2c, 0x7f, 0x8, 0x6}, {0x401, 0x2, 0xf7, 0xac26}]})
ioctl$BIOCGDIRFILT(r1, 0x4004427c, &(0x7f00000001c0))
r4 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000040), 0x80, 0x0)
r5 = openat$null(0xffffffffffffff9c, &(0x7f0000000140), 0x8000, 0x0)
poll(&(0x7f0000000180)=[{r2, 0x40}, {r4, 0x1}, {r2, 0x1}, {0xffffffffffffffff, 0x80}, {r5}, {r1, 0x4}], 0x6, 0x86)
write(r3, &(0x7f00000003c0)="3077e6edbf450f7eabd90769d9940e199feaa2cef90946b88f3abbdc7f5ab082ffb65659bded969dbb809d082be965c9ade7b37f80034ce92c0606f55bccfe53d46b7146ab112ee62a55a6617368ded70cc2e781eb61653f6c30f170551c3c46d2edf2d207f41b777a71e88cbdea70cda96d58b25b5f7cf6945bb4f7df6b6ea8493db2c5ffb09d883e5d797e5c004783726b0d4a9ea37241c51304ff804551859fcd4b3499fbba", 0xa7)
dup2(r3, r1)
r6 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r6, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000100)={0x0, &(0x7f0000000280)})
writev(r6, &(0x7f0000001840)=[{&(0x7f00000002c0)="f51949d26c5d4829ae18eed44492", 0xe}], 0x1)
kevent(0xffffffffffffffff, &(0x7f0000001300)=[{{r0}, 0xfffffffffffffff8, 0x80, 0x2, 0x8001}, {{}, 0xfffffffffffffffa, 0x0, 0xf0000000, 0x5, 0x36c}, {{r5}, 0xfffffffffffffffb, 0x7, 0x40000000, 0x2, 0x1000}], 0x2, &(0x7f0000001380)=[{{}, 0xfffffffffffffffc, 0x8, 0x40000000, 0x7, 0x2}, {{r1}, 0xfffffffffffffffa, 0x31, 0x1, 0x10000, 0x2}, {{}, 0xfffffffffffffff8, 0x20, 0xf0000000, 0x8, 0x6}, {{}, 0xfffffffffffffffd, 0x0, 0xf0000000, 0x1, 0x584}, {{}, 0xfffffffffffffff9, 0x80, 0x4, 0x4, 0x8000}, {{r6}, 0xffffffffffffffff, 0x20, 0x8, 0x7, 0x6}, {{}, 0xfffffffffffffffb, 0x30, 0x20, 0x4, 0x400000000}, {{}, 0xfffffffffffffff9, 0x42, 0x8, 0x4, 0x7}], 0x6, &(0x7f0000000100)={0x68, 0x4})
fcntl$dupfd(r6, 0x0, 0xffffffffffffffff)
pwrite(r1, &(0x7f0000000540)="aba0b1a2829ba57a5be56fb0dbb2c4614b9afbc55bb96b78a44d8b12eca65653e203f85b0478721da0824b284afa02825010bec072a5c2ce3a555d7152a738d0783d6c68052b65c09e474474c209415f792a6b48ca84b8bf22a1a3148628a67864f9faecf0e5fe20a2299ba270278b75a1a229ae9cb0b69df15929b18a094fbaa577d988d34b32bbd9f66a1b70e897e33c33be4c951d63e6457c9fdd93ecbff4e378fd0c96a63f51ee9988e00359e22293b8e977de5eb81c387ea63596f8d473c2ecdfed0d3b0c50639a8704bc22200e30b1cdb641783902930acb8e3c926a890e1c55d9", 0xe4, 0x10001)


sysctl$net_inet_tcp(&(0x7f0000000400)={0x4, 0x2, 0x6, 0x12}, 0x4, 0x0, 0x0, &(0x7f0000000140), 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
sysctl$kern(&(0x7f00000000c0), 0x2, 0x0, 0x0, 0x0, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
sysctl$hw(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x0, 0x0})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0406938, &(0x7f00000001c0))
sysctl$net_inet_ip(&(0x7f0000000300)={0x4, 0x2, 0x0, 0x25}, 0x4, &(0x7f0000000440), 0x0, 0x0, 0x0)
getuid()
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
r1 = msgget$private(0x0, 0x0)
msgrcv(0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$FIOASYNC(0xffffffffffffffff, 0x8004667d, 0x0)
open(0x0, 0x0, 0x0)
setreuid(0xee00, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000015c0)={<r2=>0xffffffffffffffff})
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000140)={0x0, 0x0, <r3=>0x0}, &(0x7f0000000040)=0xc)
setegid(r3)
setgroups(0x0, 0x0)
r4 = getuid()
setreuid(0xee00, r4)
r5 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
fchdir(r5)
writev(0xffffffffffffffff, 0x0, 0x0)
dup(0xffffffffffffffff)
r6 = dup2(0xffffffffffffffff, 0xffffffffffffffff)
msgsnd(r1, &(0x7f0000001540)=ANY=[@ANYRESHEX=r6], 0x32, 0x0)


sysctl$net_inet_ip(&(0x7f0000000080)={0x4, 0x2, 0x0, 0x25}, 0x4, &(0x7f0000000300)="e3", &(0x7f0000000140)=0x1, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{0x15}, {0x2}, {0x8106}]})
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
r2 = dup(r1)
setsockopt(r2, 0x1000000000029, 0xd, &(0x7f0000000000), 0x0)
syz_emit_ethernet(0x3e, 0x0)
mkdir(0x0, 0x0)
mkdir(0x0, 0x0)
unveil(0x0, 0x0)
open(&(0x7f00000001c0)='./file0\x00', 0x200, 0x0)
r3 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x80, 0x0)
ioctl$FIOSETOWN(r3, 0x80047476, 0x0)
setreuid(0xee00, 0x0)
sysctl$net_pipex(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
munmap(&(0x7f0000ff7000/0x7000)=nil, 0x7000)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mquery(&(0x7f0000ffd000/0x2000)=nil, 0x2000, 0x0, 0x0, 0xffffffffffffffff, 0x0)
syz_emit_ethernet(0x17a, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
getpid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0xb2}, 0x0, 0x0, 0x0, 0xffffffffffffffff})
r4 = socket(0x18, 0x2, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmsg(r4, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="10"], 0x10}, 0x0)


msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}})
r0 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1000, &(0x7f0000000000)=0x1, 0x4)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
r1 = socket(0x800000018, 0x1, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x7, "1a1116f0d0f700000000dfccf42200"})
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
socket(0x18, 0x2, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
writev(r0, &(0x7f00000007c0)=[{0x0}], 0x1)


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000140)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000080)=0xfffffffffffffde2)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r1}})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4e}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000180)=0x6, 0x0, 0x27)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt(0xffffffffffffffff, 0x0, 0x2, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
read(0xffffffffffffffff, &(0x7f0000000240)=""/226, 0xe2)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000340)=[{}, {0x15}, {0x46}]})
setrlimit(0x0, 0x0)
r1 = syz_open_pts()
close(r1)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x8})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000180)={0x0, 0xdcd, 0x5, 0xd2e, "0d88f900000400"})
writev(r0, &(0x7f0000000280)=[{&(0x7f0000000040)="f6172e7dafc43a808697a6a98df10abc73132e7149c4fbdeb82ac5de45e49811006915b57aa9420c3d960700013b06c8cec30555650f3ab78ce91c0cdd126b2870cefa740e14b904", 0xfffffeb7}], 0x1)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000002a40)={&(0x7f0000000000)=@file={0x0, '\x00'}, 0x3, 0x0}, 0x0)
socket(0x18, 0x4000, 0x0)
sysctl$hw(&(0x7f0000001180)={0x7, 0xf}, 0x2, 0x0, 0x0, 0x0, 0xffffffffffffffe7)
r1 = msgget$private(0x0, 0x0)
chdir(0x0)
setreuid(0x0, 0xee01)
r2 = syz_open_pts()
close(r2)
mknod(&(0x7f0000000000)='./bus\x00', 0x2000, 0x2e00)
r3 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
r4 = fcntl$dupfd(r3, 0x0, r3)
ioctl$VNDIOCSET(r4, 0xc0384600, &(0x7f0000000100)={0x0, 0x0, 0x0})
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000000)={0xf66c, 0x0, 0x7fffffff, 0x4777c53f, "1c192609307e7be2df67de200000d964612c3300"})
sysctl$net_inet_ip(&(0x7f0000000300)={0x4, 0x2, 0x0, 0x19}, 0x4, &(0x7f0000000340)="d4", &(0x7f0000000380)=0x1, 0x0, 0x0)
mkdir(0x0, 0x0)
chflags(&(0x7f0000000040)='./file1\x00', 0x0)
accept$unix(0xffffffffffffff9c, &(0x7f00000002c0)=@file={0x0, ""/503}, &(0x7f00000000c0)=0x1f9)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f0000000080)={&(0x7f0000000140)=[{}, {0x8b, 0x9}, {0x25, 0x83}], 0x3})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
socket(0x18, 0x2, 0x0)
msgctl$IPC_STAT(r1, 0x2, &(0x7f0000000000))


getrlimit(0x5, &(0x7f00000000c0))
openat$zero(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
msgget$private(0x0, 0x1c2)
writev(0xffffffffffffffff, &(0x7f0000000400), 0x1000000000000165)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000003c0)={0x2, &(0x7f0000000180)=[{}, {0x40e}]})
syz_emit_ethernet(0xe, 0x0)
open(&(0x7f00000001c0)='./file0\x00', 0x2e1, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x800, &(0x7f0000000040), 0x4)
pwritev(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f00000005c0)="dc", 0x1}], 0x1, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x3d}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)
r1 = open(0x0, 0x0, 0x0)
ioctl$TIOCCONS(r1, 0x80047462, 0x0)
socketpair$unix(0x1, 0x5, 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
open(0x0, 0x0, 0x0)
ioctl$TIOCSTOP(0xffffffffffffffff, 0x2000746f)
open(0x0, 0x0, 0x4)
writev(0xffffffffffffffff, &(0x7f0000000040), 0x0)
syz_emit_ethernet(0x12, &(0x7f0000000200)=ANY=[@ANYBLOB="abaaaaaaaaaaffffffffdfff8847"])


kqueue()
r0 = kqueue()
openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
kevent(r0, &(0x7f0000000040)=[{{}, 0xfffffffffffffffd}, {{}, 0xfffffffffffffffe}, {{0xffffffffffffff9c}, 0xfffffffffffffffa}, {{0xffffffffffffff9c}, 0xfffffffffffffffb, 0x11}, {{}, 0xfffffffffffffffb}], 0x9, 0x0, 0xe9ea, &(0x7f00000002c0))
accept$unix(0xffffffffffffff9c, &(0x7f0000000180)=@file={0x0, ""/260}, &(0x7f0000000300)=0x106)
r1 = kqueue()
r2 = openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
kqueue()
kevent(r1, &(0x7f0000000040)=[{{0xffffffffffffff9c}}, {{0xffffffffffffff9c}, 0x0, 0x0, 0x10}, {{r2}, 0xfffffffffffffffe}], 0x9, 0x0, 0xe9ea, &(0x7f00000002c0)={0x0, 0x3})
r3 = kqueue()
r4 = openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
kevent(r3, &(0x7f0000000040)=[{{}, 0xfffffffffffffffd}, {{}, 0xfffffffffffffffe, 0x0, 0x0, 0x1}, {{0xffffffffffffff9c}, 0xfffffffffffffff8}, {{0xffffffffffffff9c}, 0xfffffffffffffffb, 0x11}, {{}, 0xfffffffffffffffb}, {{0xffffffffffffff9c}, 0xfffffffffffffffa, 0xd5, 0x10}, {{r4}, 0xfffffffffffffffe, 0x82}], 0x9, 0x0, 0xe9ea, &(0x7f00000002c0))
r5 = msgget$private(0x0, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x6000, 0x100)
execve(&(0x7f0000000000)='./file0\x00', &(0x7f0000000280)=[&(0x7f0000000040)='-,^[/..[:\x00', &(0x7f0000000100)='-^!/[(-[\x00', &(0x7f0000000140)='://.]))&{(\x00', &(0x7f0000000180)='(#\x00', &(0x7f00000001c0)='\x00', &(0x7f0000000200)=':$-\xb7\x00', &(0x7f0000000240)='-k%-.\xae]$\x00'], &(0x7f00000003c0)=[&(0x7f00000002c0)='#{@@\x00', &(0x7f0000000300)='\\(\\-+\x00', &(0x7f0000000340)='!-)*\x00', &(0x7f0000000380)=')\x00'])
open(&(0x7f0000000180)='./file0\x00', 0x200, 0x0)
setuid(0xee01)
stat(&(0x7f0000000040)='./file0\x00', &(0x7f0000000100))
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x5}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r6 = socket(0x18, 0x2, 0x0)
setsockopt(r6, 0x1000000000029, 0xb, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
socket(0x18, 0x1, 0x0)
msgrcv(r5, &(0x7f0000001540), 0x1008, 0x2, 0x800)


mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x2882)
syz_emit_ethernet(0x2a, &(0x7f0000000040)=ANY=[@ANYBLOB="ffffffffffffffffffffffff8035000108000604000100000000000000000000ffffffffffffac1400ab"])
r0 = accept$inet(0xffffffffffffffff, &(0x7f0000000240), &(0x7f00000002c0)=0xc)
getsockname$inet(r0, &(0x7f0000000300), &(0x7f0000000340)=0xc)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000100)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0xfffffffc, 0x0, 0x7f, 0x203519, "28e54600000600000000000000d2000010001c00"})
writev(r1, &(0x7f0000000b40)=[{&(0x7f0000000640)="9b9431a5d715597f32c28150472c5c4a26761d657e140316ea35d282feeeaf745cf3e4bf90e1903276332cfaaa820fef61ff3e48cec7057ad907ac1df25524bd150d15c304380f7ae3170b2fcd5a74731b6cbd17fb8136e5287c0b7bbe6cb39417d25bd833815ebef001deb672d80fa0f8bc6801187cd337803948baa7e34f56701b2180ddedf8852feae4274e0609bf128cf397f3118bd46b571a30d94e3d900dc6702897682e301f", 0xffffffd6}, {&(0x7f00000022c0)="874efc64a16404b3dc9c5bce1a5ecabc9ad87a2c628890d6c0144206d4f104d9344df375dfd3bb105ae821f98218363f92fa5e9c05234d33d0a8d963888d8822f30019a93c93d85f62e363a3eee977e582890dacc2371a48a4431bd985409647e571a93d2a66e5b7f67ff0c6fa6dd62af727a8200ecc56044fc7d427e40ae2086abd08e51d7b88e9dd4f2f9b44b3e969212e9d954795f6c302de6406b45beeb8f5a34ad8acf5ae86909381263bdee8839a61832d6b11df3dcebcbfd8f73f3da2e026766309eec290c2427714cfa2f92495293de2c336949475c17a49469a7b6d7d237ddfb60b74ef5f99682e18887d3bc75cfce8150b94974af2204d42c994b8910d5fd06b7bd9ab57e26310ac63c59cda6de93302b7e1812811086a2ee2ee23e61b77a6d519b43ddfe016f394ae0a2751d8b420fce01e9dda4c2a43b5318afb3b6b9e9f99d71684bfaf02ed0327a58d5049b8b62e28239022820778336a5ddba0c4c7960d4998b7e8c10e5bc641ee6fe80d267590de91d2b6b50e879119ca15c7f70420506fe54a6c5537a486e83ebbcb7e95af437eefbf299a6c2c9fb95b9983374fe6a743c52828761bfba9f79f6850214ce56ddd9a859bea12b3e8bc2e30aff6aba9a488775d52d1d2a90ec9c23c908f9bd356eead53715274ee47fc9ca4a7a5189fe1027e625b7a3b5350f2b76ec2a1e192eccbce78286f134c4523b74a953bd01754d2238f1880d748c9f55eab8aede59252ca39caad3598d6e9bc03bd59426501afd5ee61ba70ccb04e7e385f3e089c5493ce9ee428c30865f9bec095fbbc30cf50d52e5b2ee7139a6b4c99b82c5a07cb4411f2a0d19174c70e508c2cdb4cad591a33db002d7d5121d6fd26f8b31af12a1e9d2058cb2bc8e34ccb1b23bddb8306484cefecbbd8ae919fc8595c0f25940a449ea2b6f345b8bf320e0a31bbe427d2431bdd52a28d3e5b15169fde2390e3121dc18b6a6c4450a03c3f3f84d9fa5f774c529591058bb00d21bfe726575817b975fb8dc62427f9b7b4f0d22cfa9975b84eded78aa3a0edb9a13165bed3443b5f35d8c68041c081f0af3eabac120d7a8e879b525f0ca9954f2a2ea752ab18683c283410f14bd859ce8806983fd20050ef80155afb0c254a6878e3e099e796242938446a642234ba124bcaecb683bbe7526007befe7d90f120ed76f987f2f8a445dae46c794d4e345564ff042bc68c2b72461ebd498235a1212bd3ed669ac480b011fbb4041136e88003c5210d142ac0c643d3db0039e21e5d9157f26cfc71fb7fe767e9c938e51b64c22ac394c8aec52ee25a226265f632bce7d79c5b7b749b56fa67ac00d5aa0571c573f23fa3ea26f15cb679742c7b9f17e22aae2892006fef55dd244c4613134227ebd4af1e5c7867295b45f91b5bcc7fa0f3ac9daa8f49b9363e9e01250fcc8d72fdcae8f6222ae3a2fb01eef75cbb2ae84ea7fcce5ef3e86c2221ed491f5d7e0b595f574857c20cc49f9162c31e8267984a4328ce6dd4a6de2e68cb4e811391651588873eff36062bb6a7c5df5e870a050338af57644ed41e2e80e66d91dd3744a5c18ec2c30ff917fd7485f92597fe4bc3ab8e18ac1f7d3c80e86a7f1b0b8bdd2f9146a900c63085ff5c6e74dee637fe3c255f16b07f5395e2b803c44147171b52ecee292c414c5415c317b14b8086b15ce3efefcf790a3fd4faf3f3dabe410c730477a829ceb589d567d97e26ccdc6fec6ca5599414458f7c0f459ff45eece2fe4d6b031507b83c44cadf24f5a4b30a8048e4d5b267bc06cc12393fd31bfe8eab256881d2618dd41491418e636be2a412dbed78da3448a52e666d3348fdf76928d380f62dd63f3a01b32679f92d7e3df380b6af601037085266b68abcd636586a763dc244252385b5b80b6c3c3ab5c3cad35bcc7a5f6bdef137e886604f3649b1af4abcd2f3d56f708e8d9003e00866ecf76da72bff382d28efc05d53f31f05e3027d8f699c9f93967bf590c984836ebec878ddcd29fe74f0647fa32ef13201ebf2a81bfd02df5b53e13594b662358e14d9dfe6cd721b31c18e1165e6a1e586b688a97b1a41c028fc1e7d2895fbe915fada9f3c28d9dfb13eda790f67a6d0a190fa80d01a5b58196a7d4827be51f043d56a49ddff95ee20260e02c53f5967ddce1510939ae04916282e782f728f02d62a06a0dc1d285cf4811566eb93d5305696517fd89fcb90fe1ea392e9d35fe02218506581661d2b1d5f4df93a8c3b556912a29e1328c739934d4c8112563c7629040721cd0bfd5c6123b7de1b39c9adb28eb3c97df75d0266dfe02f45428a3785f0ad7ea9b0ba5ff7915ed7aded81ec61c54340c46938c4d7bf8bb2dfe0ba8b69480cd1ea64107acefb62ca76a35be999f646077813d455b51bb643de2a39f7353a9a4a0d69d2200edc3a4fc671eda7db4fa39ca2f6c68a19a5468836fde4eda83145a0569a987e4011679d993420d918a640839f02595fdf0eac4e57f69fa50cc6f01030506df03ad16d418a6fd66c4230c494761e4be904e33dbf4e46c60ac4c0bd04df0da41f1d111c2252edb39c76dba2aec9abd2b2325b5b948db76f451dc23bab13ede45a0d0d63428748bf42de7084547b881f5a70e73e72efdf4046d6b1f677507ae5ce05a5878b542e55ca224e6c89f32e98d270f3644541861b6dbf8e7c2ca3b23f0230cc4d13774339f45f5871a4ac7ff0f460abb7d7d0da6bbedfe27cf2a0d4a140163d76156fb51612f5df85ce150f8795308707ce06b1581fb46d511281d77eb346ec043ca42d6182a8e484571c003f42909c69ca52a77a5493d3bc4ac7a12ef4b20966a4db291cead1abaed40af33a2b15bc06f7671eb88e97e11f1d51c901ce4f448d4f7d4828a190fe6f0b0e3330c9441b0602f7eda564811b0fab62e83a7cab92f4a3a6f02b4dc14c6a391f21cdcc1c3c8f45b74dd7c896507aded7a38b84f00cd56afb338711d617420cc56e45fec58a568a01d938031749b9625310773f807eea04b248461d14ebc2891131c4fcf6341db6fee4312bf428ef49a61c8b8c53865950d917b77203110d54cb6f433e20d45e36e6d6235c0db0bef30acaab0d53aea5f1640c2fd5d182808f1b680e348e63bf886cab2c3f17fd0053da136be9b9e7652207d05e0bad6736cf0aded9e493271b4a7e2f64e77355632e07d75f37d3ef7317b8d393dc19d61481b4006505b33dbb458496b48533de7c99391a6d092777867c9bc3085185dde89731261eb6ea05876c7ab7405ddb2a487c74e0533ea57e6bcd74e59480b424b8b1a129725422f11b2aa08aded47e06edc1d4b7a00edd83da2979d827f06fd7d41ae131036a929d5b2c619bd993d8c627735c335f80cf33cbe0fad7467b33dcde30809ffa7b22be3e394a79530bded2f0a296b650e20d13566fa4b181a70696d7b9f479cebde8af1ae708495dd4343fbc2142b0ca514b8416e67ea61902cc9204397c2a241bf5922094d0a4530587c7f9d10a003714da15ef14b7c1754e8e8386f48272e6dcdc1e2da7a9233d1e992994da824ae10ab1e03b938db824c43fe5f90fadf7ccbfe28ac644f2239273be96c9b55655417c4329532afb9aa9aa65b9ad92a8c0af9e902e458d2df4e2bcbed6f06a6fafd965a3ee422c99dc39e8426081647cb322e4db0f49bd74ee392854716f7f52cf1d245d8896f753bd75b0802ddbf7b40fe3b5cae47b41473166bed18ff525e3e2ff52ae20edd8758a3c699247d235a68dfca39cd635c3ce9f3cc79642874018bb1ca50e1662e42976c61457480c0fc464826d1e9d580ebd7c7a17f88175af5c80febfc9be1a161a8f5a33ec774c829087af8fdca10e18bfb7a9314c86f45849f369a49ae097d3dc17c267f149510b02cefc2d48f7ccedf8e8ed6a777dcd2d100dff3a63366f06be6095412fa67e604ac68802de10172269b1143175fed804d95905206e877c2b5122f863f53f26e41e648acfdf03b2bfd627dac0a7660c87a614a96986f5514d5d8cff8f24f5a6fa4948946c8cbf38c05bfec4ad3da68e893cdbeaf5d34f26019108ca53fe69f22480b8d5d06118cd1a8d0842a88efdc6141121180b2c516016044f82eb9cba26264b0199e958368c688fb5e81794dac44716facba22107a3a9a86220f0ec4ef428698a0f3e972941036f084b441a4509e1c7647260f0f8c7d1e6e46ceaefcd9b56e060ea915c24ea7bb1f42333fa14eaa9b5ef087ec2a88209ef0532dc0d2ab675f7446e8b63d819e24c3022a03ae1ebe8c153b00a419f67719f7990f3014e37c2a6dfcae8e97d1d774f1b35ca81ecc8c0111418d386f5f696c883b3e1c47937542efe74fbb38f1b4dd0a4287f2bef1030e5557964e5ce1769804b7669442d5a8ef98df18588b39cfa709baa98b9b8d029452a53454cc752c6787fc3049237b63c80089bcd809a941924247c88eac81e4879c13419fab443c8b536b3a8613b906ed4c1c0a93972de8e0ae60c41c28d2495d525663cd89a622645c99e2b77163f40fa38dea7b16ac51898e28a74625cce47f886af6cc62d2094c0e4b8cb72f53cbdf0ab193d446c3a0e024da33e79e4f37e39e0b399b14afd6006ed5eb57acc499036b293a454f86b50a82bcdc91f956ace3013e97ca2c5bd435812457ae946f1b04d44c1cfa899ad25ee1a91897576fe9442a49e93a603943706aa4f2141cd6e5848c0a4f475950db64d72b40067b8d1814797a30edb4a62f864930c19c97dfa13ffe283c25cb2bc0f526db6eee7115a6b9bf8c754bbf7ba5b5b06dcda3f37181af0cd2c325564eabc778db138026b3c8f9586290a54fcc6e53b1d8772c710ad3cad0491131cad7419f090f65a0e6dc336837d2b469e8bbf3c1a0a76303769886dde6a91f2fb115bbe240977dbd106a07b1ce52eb2f6d86b5621623589de54804fffcd5710859448ae9d028d46c8380a4edf09b6458ea5823e5e853940f8a00a3f80d2ca0bd03eb28d16ee05f28f3e13608a02", 0xdd2}], 0x2)
writev(r0, &(0x7f0000001480)=[{&(0x7f0000000140)="b8dc7ad66d6d45a4c1f168647c2ce4e83f2eb13e4980057b4fee8ed93efef125ef3d6f4ece8c5de164086a4d86da79b1614138b36c5aec12d75a8e4dbdcbfeeabae21a3758613214bdbec5a3c9c45e5696a373965c936aac1f9c966cd787168ba0a9db085be31f9881be6667228783638366d46d81d55dc0a755bbaf07ceea03c566595430a112105e30e329dbdd32c1d81a49355a4bfafe38c81be6dd52f4b28c7c99926e0b1e193b227489d98ef36cb6b7e4c3cfd7695f6b2fae0d84413d1ab504685b4ca0bc2e98f2d723ce0b20b5ae8c205858e7b83829bf53566bdf0f0aa340d9722b536dd1b88f3d4e6bf118b113f544529c2807", 0xf7}], 0x1)


mknod(&(0x7f0000000000)='./file0\x00', 0x2100, 0x5f00)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x1, 0x0)
ioctl$VMM_IOC_RUN(r0, 0xc0205602, &(0x7f0000000480)={0x0, 0x0, 0x0, 0x0, 0x0})


mkdir(0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg$unix(r1, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="28000000ffff000001"], 0x28}, 0x0)
recvfrom$unix(r0, &(0x7f0000000180)=""/225, 0xe1, 0x40, 0x0, 0x0)
r2 = socket$inet(0x2, 0x2, 0x0)
dup2(r2, r1)


r0 = socket(0x2, 0x740943300570c72a, 0x0)
setsockopt(r0, 0x11, 0x3, &(0x7f0000000340)="02000000", 0x4)
setsockopt(r0, 0x11, 0x0, &(0x7f0000000200)="12000001", 0x4)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(r1, 0xc0206921, &(0x7f00000001c0))
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x2, 0x0)
r2 = socket(0x2, 0x2, 0x0)
r3 = socket$inet(0x2, 0x3, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x1, &(0x7f0000000240), 0x0)
r4 = socket$inet(0x2, 0x3, 0x0)
dup2(r4, r4)
ioctl$FIONREAD(r2, 0xc0206923, &(0x7f00000001c0))
r5 = fcntl$dupfd(0xffffffffffffffff, 0x3, 0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$FIONREAD(r5, 0x8004745d, &(0x7f0000000200))
socket(0x2, 0x2, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000240)="ea00000100000000", 0xc)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r6 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r6, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
r7 = socket$inet(0x2, 0x2, 0x0)
close(r7)
r8 = socket$inet(0x2, 0x2, 0x0)
dup2(r6, r8)
setsockopt$inet_opts(r7, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0x8)


socket(0x11, 0x3, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504600000000000000007000000331c13fecea10500fef9ed06c72fd3357ae320b37b673039d2d236073705ae04be38164991f7accf5f882b297be1aad2236deb51e2f0ac3ebbc257699a5f139b672f4d335d223e7d029d6ba8af630037282102000000720f70c1f5a472c881ea6e69e0bb76d907c400000200361b1257aea8c5000020020000000000008a", 0x8e, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
sendmsg$unix(r0, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
kqueue()


clock_getres(0x2, 0xfffffffffffffffe)


sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000040), 0x3, &(0x7f0000000080)="397c9aca", &(0x7f0000000780)=0x4, 0x0, 0x0)
ioctl$VMM_IOC_RESETCPU(0xffffffffffffffff, 0x82405605, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000680)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000100)=[{0x7, 0x4, 0x5}, {0x2, 0x0, 0x0, 0xffffff81}, {0x26}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
r2 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSKBDIO_SETMODE(r2, 0x80045713, &(0x7f0000000200))


mknod(&(0x7f00000000c0)='./bus\x00', 0x2006, 0x4f4b)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x615, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
rename(&(0x7f00000007c0)='./file0\x00', &(0x7f0000001040)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
sysctl$kern(&(0x7f0000000040)={0x1, 0x55}, 0x3, 0x0, 0x0, 0x0, 0xfffffdc4)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000))
open(0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000740)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
r3 = socket(0x18, 0x4001, 0x0)
listen(r1, 0x5)
r4 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$VNDIOCSET(r4, 0x20006473, 0x0)
r5 = open$dir(&(0x7f0000000200)='./bus\x00', 0x0, 0x0)
r6 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x20000, 0x0)
r7 = openat$zero(0xffffffffffffff9c, &(0x7f0000001440), 0xe8, 0x0)
r8 = fcntl$dupfd(r7, 0x3, 0xffffffffffffffff)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$FIOASYNC(r8, 0x8004667d, &(0x7f0000000000))
r9 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r9, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r9, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000400)=[{0x4, 0x0, 0x0, 0x2}, {0xc0}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f0000000340)=ANY=[@ANYRES8=r9, @ANYRES16=r6, @ANYRES8=r3, @ANYRES8=r2])
ioctl$BIOCGBLEN(r6, 0x40044266, &(0x7f0000000080))
mknod(&(0x7f0000000000)='./bus/file0\x00', 0x2, 0x202)
ioctl$FIOASYNC(r5, 0xc0104304, &(0x7f00000001c0)=0x20000002)
ioctl$TIOCSETVERAUTH(r0, 0x8004741c, &(0x7f0000000240)=0x4)


r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x24, &(0x7f0000000000)="5ab7776a", 0x4)
setsockopt$sock_int(r0, 0xffff, 0x800, &(0x7f0000000180)=0x2, 0x4)
syz_emit_ethernet(0x4a, &(0x7f0000000480)={@random="69e1629b6174", @remote, [], {@ipv6={0x86dd, {0x0, 0x6, "6b9efb", 0x14, 0x50, 0x0, @rand_addr="cb69bc83c1677a656ab420666c3e2c6f", @local={0xfe, 0x80, '\x00', 0x0}, {[], @tcp={{0x3, 0x2, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}}})
recvmmsg(r0, &(0x7f0000000640)={0x0}, 0x10, 0x2, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000400)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000300)=[{0x81}, {0x20}, {0x4000006}]})
writev(r0, &(0x7f0000001400)=[{&(0x7f0000000240)="e049c0d37348a45d6bee0bf84a9e", 0xe}], 0x1)


setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000000), 0x10, 0x0)
ioctl$WSKBDIO_SETMODE(r1, 0x80045713, &(0x7f0000000040)=0x1)
syz_open_pts()
r2 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r2, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
ioctl$BIOCLOCK(0xffffffffffffffff, 0x20004276)
seteuid(0xffffffffffffffff)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
listen(0xffffffffffffffff, 0x401)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)
ioctl$FIONREAD(r2, 0xc0207534, &(0x7f0000000440))


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
shmget$private(0x0, 0x3000, 0x0, &(0x7f0000002000/0x3000)=nil)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000040)=[{0x5}, {0x25}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f00000002c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{0x81}, {0x6c}, {0x6}]})
syz_emit_ethernet(0x52, &(0x7f00000003c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
setreuid(0xee00, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000015c0)={<r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000000)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000040)=0xc)
ioctl$BIOCGDLTLIST(0xffffffffffffffff, 0xc010427b, &(0x7f0000000180)={0x2, &(0x7f0000000100)=[0x1000, 0x7]})
openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000000), 0x80, 0x0)
r3 = msgget$private(0x0, 0x2)
msgsnd(0x0, 0x0, 0x401, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x19}, 0x4, &(0x7f0000000080), 0x0, &(0x7f0000000500), 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
setegid(r2)
setgroups(0x0, 0x0)
r4 = getuid()
setreuid(0x0, r4)
msgctl$IPC_STAT(r3, 0x2, &(0x7f0000000200)=""/86)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000200)=[{0x61}, {0x84}, {0x6}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


msgsnd(0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="00000000000000008d136a159619f3b2cc907f318c2ccfacbef4800b150f4f71e3acddb0ebe041f23bb6d441da4607c3beaac250b0cf9d1be0d5dc884f29306df18b414384cf9365c4114ec1018421c73f4172c70bf2e3c733d6ef7b9b99e8c58920f774f264e6ebdd9207a863d32a696a92792ee9a66e51f0a8907b7f25984419ec8985dba5919bec757d9f206820f74fc7b54614fb9cb5b9cde2a55fd568fdd22648bf3ba3b5d1afbf9724fcbccc6a3ff2a23b8dfb840c22d5cf52187291f89d183c7802"], 0xe1, 0x0)
r0 = socket(0x18, 0x2, 0x0)
close(r0)
openat$diskmap(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f00000001c0)={0x0, 0x0, 0x7ffffffffffffffd, 0x2000100000002})


sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x11}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000000)={0x2, 0x5, 0x2}, 0x3, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0xa}, 0x3, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000000), 0x6, 0x0, 0x0, 0x0, 0x0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
writev(r0, &(0x7f0000000580)=[{&(0x7f00000001c0)='N3', 0x2}], 0x1)


r0 = socket$inet(0x2, 0x1, 0x0)
setsockopt$sock_timeval(r0, 0xffff, 0x1005, &(0x7f0000000080)={0x0, 0x4}, 0x10)
getsockopt$sock_timeval(r0, 0xffff, 0x1006, &(0x7f0000000000), &(0x7f0000000040)=0x10)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
sysctl$hw(&(0x7f0000000200)={0x6, 0x18}, 0x2, 0x0, 0x0, &(0x7f0000000140)="54728965", 0x4)
setrlimit(0x5, &(0x7f0000000980))
syz_open_pts()
r2 = socket(0x18, 0x3, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
shutdown(r2, 0x0)
syz_emit_ethernet(0x52, &(0x7f0000000080)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaabb86dd60000000001c000080000000000000000000000000000000ff020000000000000000000000000001"])
pwritev(0xffffffffffffffff, &(0x7f0000000340), 0x0, 0x0)
sysctl$kern(&(0x7f0000000380)={0x2, 0x8}, 0x2, 0x0, 0x0, &(0x7f0000001440), 0x0)
setreuid(0xee00, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, &(0x7f0000000000))
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
mprotect(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x4)
r3 = shmget(0x0, 0x4000, 0x1, &(0x7f0000ffb000/0x4000)=nil)
shmat(r3, &(0x7f0000ffc000/0x4000)=nil, 0x0)
r4 = syz_open_pts()
fsync(r4)


sysctl$net_inet_ipip(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x1e, 0x3, 0x0)
write(r0, &(0x7f0000000000)="2deaaec43f0c0f6b3a1eb2f74da1ef10", 0x10)


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)='\x00', 0x1}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
r1 = socket$inet(0x2, 0x2, 0x0)
dup2(r0, r1)
setsockopt$inet_opts(r1, 0x0, 0xc, &(0x7f0000000240), 0x0)


mmap(&(0x7f0000ffa000/0x3000)=nil, 0x6e75b37dbfff, 0x0, 0x1010, 0xffffffffffffffff, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x5, &(0x7f0000000340)=[{}, {}, {}, {0x20, 0x0, 0x0, 0x1}, {0x6}]})
write(r0, &(0x7f0000000200)="d81ad3d20cf7eb4e9be33bbd1a30", 0xe)


syz_emit_ethernet(0x4e, &(0x7f0000000100)={@local, @local, [], {@ipv6={0x86dd, {0x0, 0x6, '\x00K\x00', 0x18, 0x2b, 0x0, @remote={0xfe, 0x80, '\x00', 0x0}, @rand_addr="607ba243b19d8e9ea241f577704405b6", {[@dstopts={0x3a, 0x1, '\x00', [@generic={0x0, 0x6, "f9972bfa0eeb"}]}, @routing={0x88}]}}}}})


openat$speaker(0xffffffffffffff9c, &(0x7f00000004c0), 0x2, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000fff000/0x1000)=nil, 0xfffffffffffffff7, 0x0, 0x10, 0xffffffffffffffff, 0x9)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x6, &(0x7f0000000040)=[{0x800, 0x20, 0x40, 0x1}, {0x80, 0x2, 0x80, 0x7f26}, {}, {0x7ff, 0x0, 0x0, 0xfff}, {0x3, 0x8, 0x81}, {0x0, 0x0, 0x0, 0xfffffff8}]})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
syz_emit_ethernet(0x3e, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x40, 0x88)
kqueue()
syz_open_pts()
readv(0xffffffffffffffff, &(0x7f0000000000)=[{&(0x7f00000009c0)=""/4096}], 0x3e)
setrlimit(0x2, &(0x7f00000000c0)={0x60000000, 0x60000000})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000002a40)={&(0x7f0000000000), 0x10, 0x0}, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x2, 0x2, 0x0)
connect$unix(r1, &(0x7f0000000000), 0x10)
sendmsg$unix(r1, &(0x7f0000002a40)={0x0, 0x0, 0x0}, 0x0)


r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0xae828e137847f62, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
setrlimit(0x1, &(0x7f0000000000)={0xfffffffffffffffd, 0xffffffffffffffff})
ftruncate(r0, 0x20008002)
r1 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r1)
r2 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x1, 0x0)
pwritev(r2, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)


sendmsg(0xffffffffffffffff, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x0, 0x0, 0x280}, 0x0)
open(0x0, 0x0, 0x0)
r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r0, 0x80085761, &(0x7f00000000c0)={0x3})
r1 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000180), 0x1, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(r1, 0x80085762, &(0x7f0000000400)={0x3})
msgctl$IPC_SET(0x0, 0x1, 0x0)
seteuid(0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x0)
munmap(&(0x7f0000000000/0x3000)=nil, 0x3000)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
listen(0xffffffffffffffff, 0x0)
socket$unix(0x1, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x40, &(0x7f0000000180)=ANY=[])
open(&(0x7f0000000300)='./file0\x00', 0x0, 0x9)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
socket$inet(0x2, 0x3, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x800c745b, 0x0)
mknodat(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socket(0x0, 0x2, 0x0)
r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$PCIOCWRITE(r0, 0xc00c7007, &(0x7f0000000000)={{}, 0x1})


setrlimit(0x0, 0x0)
select(0x40, &(0x7f0000000280)={0x10374}, 0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
link(0x0, &(0x7f0000001380)='./file0\x00')
rename(0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x0, 0x0)
ioctl$BIOCSRTIMEOUT(r0, 0x8010426d, 0x0)
syz_emit_ethernet(0x46, &(0x7f0000000180)={@broadcast, @random="ac566789c541", [], {@ipv4={0x800, {{0x9, 0x4, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, @broadcast, @broadcast, {[@timestamp={0x44, 0x10, 0x7, 0x1, 0x0, [{[@rand_addr]}, {}]}]}}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})


setrlimit(0x8, &(0x7f0000000040)={0x7, 0x200005})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000380)={0xfffff732, 0x0, 0x1, 0xdfdffbc4, "97115f33ba7d00fdff0104000000000000de00"})
writev(r0, &(0x7f0000000e00)=[{&(0x7f0000000000)="8a790538f39456d084543880083267c4d808c19e4e915c29", 0x18}], 0x1)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000004c0), 0x10202, 0x0)
writev(r0, &(0x7f0000000080)=[{&(0x7f0000000500)='B', 0x1}], 0x1)
execve(0x0, 0x0, 0x0)


r0 = kqueue()
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x0, &(0x7f00000000c0)})
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000000c0)={<r2=>0x0, 0x0, <r3=>0x0}, &(0x7f0000000100)=0xc)
setregid(0x0, r3)
setpgid(0x0, r2)
fcntl$lock(r0, 0x7, &(0x7f0000000080)={0x1, 0x0, 0xfff, 0x2})
kevent(r0, &(0x7f0000000000)=[{{r1}, 0xffffffffffffffff, 0x1}], 0x8, 0x0, 0x0, 0x0)
r4 = dup2(r0, r1)
ioctl$WSDISPLAYIO_GETSCREENTYPE(r4, 0xc028575d, &(0x7f0000000240)={0xa8, 0x8, './file0\x00', 0x400, 0x6, 0x81, 0x7fffffff})


r0 = socket$inet6(0x18, 0x3, 0x0)
getsockopt(r0, 0x29, 0x27, 0x0, 0x0)
socket$inet(0x2, 0x2, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f0000000280)=[{{r1}, 0xfffffffffffffffb, 0x10b, 0x2}], 0x9, 0x0, 0x7fffffff, 0x0)


sysctl$kern(&(0x7f0000000280)={0x1, 0x44}, 0x3, &(0x7f00000003c0)="8b5ea54a413c745995d4a95b979bb64d0541e6a50849f2861cc5f3e014d9ea6bba61da747d3cd9a068b38d0bb67a985e46184f42a6c16a68078392dee63af6e601c0865da92ccdbbf8b85cb74d593a4d771ba5adb1403ae15565ef56d99f35fcc544e7a02a6c038ad8350c06a67bb9150e72e4f7e3084bf8a8cd1f65c4f707722236a4bc53e00f6e41aaea38a0c4e09508e1e439d617879713ed556c9f38b1213fe3ebb3d05a1fb9af890b38975b0a67fee19a5840f6e655d79e6d8596f328b0a7315e826f5b2d2ef536e5c9fa3e6af4a8c312e71e7da86dd5ea55f5a6a153b43941fab0217cbe2a5fbfc598f2f1bdd630558d225116d927d6d4c600418246ac0b6dde68455e73bcbe8a3d", &(0x7f00000002c0)=0x12, &(0x7f0000000300)="6675ce01f40d6aca4f5b680c7e17a4db799bb2480f1b4e922dd582704df696f66891b95981f7d920436699f59f5bcdb142bd08777d3dfee17dabe90c8f0d3defb72a65e0583485bfd0ab622d2267677a928d2d3d84731c57b234e88df06caf4fee4aa32022541c8c057f1c601f54d25fec982caee472cbce44bb86c6d5b25c6ba673915108c6f254cc12f9287a60000fbbf686386e3e", 0x96)


syz_emit_ethernet(0x14, &(0x7f0000000f00)={@local, @empty, [], {@generic={0x8863, "470c82e418d7"}}})


r0 = socket(0x2, 0x3, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r0, &(0x7f0000000000)=@file={0x0, '\x00'}, 0x3)


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ioctl$FIONREAD(r0, 0x40047307, &(0x7f0000000080))


mmap(&(0x7f0000400000/0xc00000)=nil, 0xc00000, 0x0, 0x1011, 0xffffffffffffffff, 0x0)
r0 = msgget$private(0x0, 0x282)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000100)={0x3b, 0x0})
munmap(&(0x7f0000ffa000/0x4000)=nil, 0x4000)
open(&(0x7f0000000200)='./file0\x00', 0x230, 0x0)
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x64d1)
open$dir(&(0x7f0000000000)='./bus\x00', 0x2, 0x0)
sysctl$machdep(&(0x7f0000000000)={0x7, 0x1}, 0x2, &(0x7f0000000040)="60ec01e9ccc902469b4c43c3de981de8937a043cd2933c5f5e97c1fc6a271b4377016ef7dd4cf9324639bb89d081f3d781", &(0x7f0000000140)=0x31, &(0x7f0000000180), 0x0)
mmap(&(0x7f0000557000/0x2000)=nil, 0x2000, 0x0, 0x2dbe387c4417487e, 0xffffffffffffffff, 0x22f2f052)
mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0, 0x1012, 0xffffffffffffffff, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r1 = syz_open_pts()
close(r1)
r2 = syz_open_pts()
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000200)={0x0, 0x0, 0x0, 0x0, "346c47518d19fabf00f17abafaf7281dadba071d"})
ioctl$TIOCSETAF(r2, 0x802c7416, &(0x7f0000000100)={0x978b, 0x0, 0x41, 0x80a19f, "bb08000100f1675910812cc900"})
writev(r1, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r3 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r3, 0x0, 0x0)
r4 = socket(0x0, 0x0, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r4, 0x0, 0x0)
setreuid(0xee00, 0x0)
seteuid(0x0)
msgsnd(r0, 0x0, 0x1f, 0x0)


r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x80)
pwritev(r0, &(0x7f0000000380), 0x0, 0x3fffd)
open$dir(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
mknod(&(0x7f0000000300)='./file0\x00', 0x2000, 0x40006da)
r1 = open(&(0x7f0000000000)='./file0\x00', 0x100, 0x2)
ioctl$WSDISPLAYIO_LSFONT(r0, 0xc058574e, &(0x7f0000000340))
accept(0xffffffffffffffff, &(0x7f0000000400)=@un=@abs, &(0x7f0000000080)=0xfffffffffffffeeb)
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, 0x0)
mmap(&(0x7f0000ffc000/0x1000)=nil, 0x1000, 0x1, 0x2013, 0xffffffffffffff9c, 0x0)
open(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000001440)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x0, &(0x7f00000000c0)})
ioctl$BIOCSETWF(0xffffffffffffff9c, 0x80104277, &(0x7f0000000140)={0x4, &(0x7f0000000000)=[{0xff, 0x3, 0x5, 0x9}, {0x7, 0xac, 0x13, 0x1f}, {0x9, 0x0, 0x7, 0x7ff}, {0xa5b, 0x0, 0x7, 0x7}]})
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETWF(r3, 0x80104277, &(0x7f0000000200)={0x1, &(0x7f00000001c0)=[{0x7, 0x7, 0x7}]})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000440), &(0x7f0000000540)=0xc)
ioctl$BIOCSETWF(r3, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x15}, {0x20}, {0x4000006, 0x0, 0x0, 0x7f}]})
write(r3, &(0x7f0000000180)="c5449bc1708e16b9805a099e20a0", 0xe)
ioctl$BIOCPROMISC(r3, 0x20004269)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r4, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000002c0)=[{}, {0x1}, {0x6, 0x0, 0x0, 0x80000025}]})
write(r4, &(0x7f0000000100)="94e15358337d0900000000000000", 0xe)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f00000005c0)={0x2, &(0x7f0000000580)=[{0x4, 0xbe, 0x1, 0x4}, {0x8000, 0x7f, 0x2, 0x10001}]})
write(r2, &(0x7f0000000700)="c662e62071cf5e85539afa5e908352635cb3ac14e156887afe0b9763fd9f8e97de6b77283bcdb27337a6d7b9afa27d6e8584c649ec438ce2bd0ca61d1c7c0979b42d2553c1ed9a5a5c6bbcf6886b0db63765ac576179b293715fbee78602409c60d39a23", 0x64)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000200)={<r5=>0xffffffffffffffff})
getsockopt$sock_cred(r5, 0xffff, 0x1022, &(0x7f00000000c0), &(0x7f0000000100)=0xc)


r0 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000180), 0x3a8, 0x0)
fcntl$lock(r0, 0x7, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000200)=[{0x14}, {0x45}, {0x8106}]})
syz_emit_ethernet(0x3e, &(0x7f0000000280)=ANY=[])


mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x5200)
r0 = open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)={0x3, 0x7fffffff})
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x30, 0x0, 0x57d, 0x0)
dup2(r0, r1)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
sysctl$kern(&(0x7f0000000040), 0x36, 0x0, 0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xfffffffffffffffe})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0x3f, &(0x7f0000000040)="00fb6c4f", 0x4)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendto(r1, 0x0, 0x0, 0x0, 0x0, 0x0)


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, 0x0)
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, 0x0, 0x0)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x3, 0x0, 0x0, 0x1}, 0xc)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x10281, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x1, 0x0, 0x0, 0x1}, {0x6, 0x0, 0x0, 0x7fff}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0xff0a, 0x0, 0x37)
ioctl$BIOCSETWF(r1, 0x80104277, 0x0)
write(r1, &(0x7f0000000540)="76e5dead6f01f8", 0x7)
ioctl$BIOCGDLTLIST(r1, 0xc010427b, &(0x7f0000000180)={0x4, &(0x7f0000000140)=[0x0, 0xee, 0xfff, 0x1]})


r0 = socket(0x2, 0x2, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f0000000180)=[{{r0}, 0xfffffffffffffffe, 0xc9, 0x1}], 0x3, 0x0, 0x0, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r0, &(0x7f0000000000), 0x10)


semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
open(0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x58}, 0x2, &(0x7f0000000140)="1139a509", &(0x7f0000000180)=0x4, &(0x7f00000001c0), 0x0)
socket(0x2, 0x3, 0x0)
syz_emit_ethernet(0x6a, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x5c, 0x0, 0x8}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x1, 0x0, 0x12, 0x4, 0x2, 0x0, 0x233, {[@generic={0x0, 0xd, "96c729637cae4fa49c1558"}, @sack_perm={0x4, 0x2}, @sack={0x5, 0x16, [0x0, 0x0, 0x0, 0x0, 0xffffffff]}, @timestamp={0x8, 0xa, 0xb018, 0x8}, @generic={0x4, 0x2}]}}}}}}})


symlink(&(0x7f0000000900)='.\x00', &(0x7f0000000240)='./file0\x00')
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ktrace(0x0, 0x0, 0x0, 0xffffffffffffffff)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x3a, 0x0)
syz_emit_ethernet(0x0, 0x0)
semop(0x0, 0x0, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000300)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000200)='./file0\x00')


sysctl$ddb(&(0x7f0000000000)={0x9, 0x4}, 0x2, &(0x7f00000002c0)="b151efd9ec9b99ce872e665d84241a5d2a4e39ba4a08d1bf87cccd2140583a0309001556c5561af91e1ee1ab99a2a20048472e6ea9041e8d9b0000103b2656be0b83e6bef50a085d22bd29ef0c0cf6a2cb4a0a4101060fc2091b6db2b007f42ac6888d87dbcd66b3604f7ebfcfd1d6cdb18ef112db4e84d61427299453b7842b00c6b5d02eeafced52087993a543d83d2800000000000000000000786175566f830605b2314e9959e1c9e03cafa2c9830196050000002948f7e57a8b53af5aae7a1e7e95c7c63bd3317327069d4a738724a546c3913bddb3627de8c368c628cf63c8a95da60648a8443a2b73950ccbdac6b0a03822112dca055742010f231f68d646867dfbce6f70ac63782c3c6091cbb0efa9444d", &(0x7f0000000040)=0x57, 0xfffffffffffffffe, 0x4)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0xfffff5e7, 0x0, 0x7, 0xffffbff7, "1010264d007c260000000000000000e1ffffff00"})
writev(r0, &(0x7f0000000100)=[{&(0x7f00000009c0)="4a9ed65e2f444a9ec732bacbe026237622ad5dd37fe2cfb3a2289c9afef2523ce34ccba8196c838b64eda3838e69bbf95f059371811f3fff1d7384630f52315bc5aba7fc040353437cbfa6826a5914534f23da7d4ac8698d6945bd93dfb78e13ff8a25c901919cde9c0aadd833b0b37fc8afd99997fa5ca1", 0x78}], 0x1)


clock_getres(0x2, &(0x7f0000000040))


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
setsockopt(r0, 0x0, 0x9, 0x0, 0x2a)


r0 = socket$inet(0x2, 0x3, 0x0)
select(0x40, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4000000000}, &(0x7f0000000040)={0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3ff}, 0x0, 0x0)
r1 = openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x200, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000300)={0x1, &(0x7f00000000c0)=[{0x3, 0x0, 0x0, 0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x33}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x18, 0x0, 0x37)
r2 = semget$private(0x0, 0x2, 0x0)
seteuid(0xffffffffffffffff)
socket$unix(0x1, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
mknod(0x0, 0x2000, 0x0)
r3 = socket$inet(0x2, 0x0, 0x0)
semctl$SETVAL(r2, 0x3, 0x8, &(0x7f0000000640)=0x5)
setsockopt$inet_opts(r3, 0x0, 0x0, &(0x7f0000000240), 0x0)
socketpair(0x2, 0x1, 0x0, &(0x7f0000000000))
socket$inet(0x2, 0x0, 0x3)
dup2(r1, 0xffffffffffffffff)
syz_emit_ethernet(0x3f, &(0x7f00000005c0)=ANY=[@ANYRESOCT=r1])
open(0x0, 0x80000000000206, 0x0)
r4 = syz_open_pts()
ioctl$TIOCSETAF(r4, 0x802c7416, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x7ffffffe, "2cf748460adb56e8dd42caee5275882ceece40cf"})
ioctl$TIOCSTART(r4, 0x2000746e)
writev(0xffffffffffffffff, 0x0, 0x0)
recvfrom(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
msgget$private(0x0, 0x14a)
socket(0x18, 0x3, 0x3a)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000140), 0x782, 0x0)
pwritev(r0, &(0x7f0000000240)=[{&(0x7f0000000000)='m%', 0x2}], 0x1, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
dup2(r1, r0)
setsockopt$inet_opts(r0, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0x8)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000580)={0x3, &(0x7f0000000540)=[{0x2c}, {0x3}, {0x6}]})
syz_emit_ethernet(0x7e, &(0x7f0000000280)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000200)=[{0x5}, {0x1c}, {0x812e}]})
syz_emit_ethernet(0x2a, &(0x7f0000000240)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000080)=[{0x20}, {0x54}, {0x40e}]})
syz_emit_ethernet(0x138, &(0x7f0000000400)=ANY=[])


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
bind$unix(r0, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
setreuid(0x0, 0xee01)
r1 = socket$unix(0x1, 0x2, 0x0)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


r0 = socket(0x2, 0x1, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x1, &(0x7f0000000600)="ee08665d19ac0004e5134876f197a7728420aef6171504b1c3d4b38304921bf0817a0000040000006a89dbdf", 0x2c)


r0 = socket$inet(0x2, 0x3, 0x0)
r1 = socket$inet(0x2, 0x3, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000080)="eaef125c00000000", 0x8)
r2 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000080)="eaef125c00000000", 0x8)
dup2(r0, r2)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$SPKRTUNE(r0, 0x20005302, 0x0)


syz_emit_ethernet(0x2e, &(0x7f0000000080)={@local, @local, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x1, 0x0, @remote={0xac, 0x14, 0x0}, @rand_addr, {[@lsrr={0x83, 0x3}]}}, @icmp=@info_request}}}})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
fcntl$setown(r0, 0x6, 0x0)


shmat(0x0, &(0x7f0000002000/0x1000)=nil, 0x0)
clock_gettime(0x4, &(0x7f0000000140))
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
sendto$inet(0xffffffffffffffff, &(0x7f00000000c0)="6c25a03ae7b27b4e7fc0924a22334b9b619f09f993c214bf34de94ee6f878793a443c48892901b940ff2189ae976bd635aa66dd55818d1ca20a7f88c2ad799df41ea701f32e36ab928f0ea3b00ddc5613e3590c04b342a5ec356d4f406e612653d7338e1b59ec0f00de4b65b3f18", 0x6e, 0x0, 0x0, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))
syz_open_pts()


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x5}, {0x61}, {0xe}]})
write(r0, &(0x7f00000006c0)="e506000000000000004aaed75a5a", 0xe)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000000029, 0x3d, &(0x7f0000000040)="00000080", 0x4)
getsockopt(r0, 0x29, 0x3d, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x6, &(0x7f0000000340)=[{0x2d, 0x0, 0x3}, {}, {}, {}, {0x4}, {0x6}]})
write(r0, &(0x7f0000000200)="d81ad3d20cf7eb4e9be33bbd1a30", 0xe)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000004c0), 0x10202, 0x0)
writev(r0, &(0x7f0000000040)=[{&(0x7f0000000080)='f', 0x1}], 0x1)
execve(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x1, &(0x7f0000000140)=[{0x2c9}]})


mknodat(0xffffffffffffff9c, &(0x7f0000000100)='./file0\x00', 0x1000, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
pwritev(r0, &(0x7f0000000380)=[{0x0}], 0x1, 0x0)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000280)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000000c0), &(0x7f0000000180)=0xc)
r1 = socket(0x18, 0x1, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
r2 = open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
ioctl$TIOCMBIS(r2, 0x8004746c, &(0x7f0000000180)=0x7)
sysctl$net_inet_udp(&(0x7f0000000000)={0x2, 0x4}, 0x4, 0x0, 0x0, 0x0, 0xfffffffffffffda6)
setsockopt(r1, 0x1000000029, 0x1b, &(0x7f0000000340)="a1f89d7677b323062931f643fc256e832f90b1521986f1ebdfba235fac986c9f4b951de715164c1800345551ca8da585ebbc1bab1e7088451cb4d961119b1c59ece7c6b6a5c10555051e5c93032b4eb5890eefc248c08c01c303727a457bf443fcf949fc0fe7f0c63d11e4e0a55bd300438a9e994eca6a31a6b98a28587e241acdf290f39f7b6c3b1d76c437f7f0951468a65934099984b028ac7561bec7f3", 0x9f)
socket$unix(0x1, 0x0, 0x0)
openat$speaker(0xffffffffffffff9c, &(0x7f00000004c0), 0x2, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
pipe(&(0x7f0000000080))
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r3 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(r3, &(0x7f0000001580)=[{&(0x7f00000000c0)='\x00', 0xfffffeb0}], 0x1)


msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000040)={{}, 0x0, 0x0, 0x0, 0x0, 0x1})
sysctl$kern(&(0x7f0000000080)={0x1, 0x27}, 0x4000000000000004, 0x0, 0x0, 0x0, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x4e, 0x0)
openat$vnd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x0, 0x4}]})
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000000c0)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000180)=0xc)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x37}, 0x4, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3, 0x0, 0x2e)
kqueue()
setgid(r1)
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x2801)
r2 = open(&(0x7f0000000280)='./bus\x00', 0x0, 0x0)
poll(&(0x7f0000000140)=[{r2, 0x4}], 0x1, 0x0)
close(r2)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x7}, {0x28}, {0x6}]})
syz_emit_ethernet(0x62, &(0x7f00000006c0)=ANY=[])
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000240)=[{0x61}, {0x54}, {0x46}]})
getpid()
r3 = socket(0x2, 0x2, 0x0)
socketpair(0x2, 0x3, 0x106, &(0x7f0000000040))
setsockopt$sock_int(r3, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r3, &(0x7f0000000000), 0x10)
write(r3, &(0x7f0000000240)="14bdfa5d1d34e2fecb284a6498307dcda9aec43050036123339a346f737850551408753f95b7688ad4c4e1dd5489e7bafc58d3e5823757ae8b630719ef187ccad995f13dbe", 0x45)
r4 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VMM_IOC_RESETCPU(r4, 0x82405605, &(0x7f0000000740)={0x80, 0x0, {[0x0, 0x800], [0x0, 0x0, 0x4000000000, 0x0, 0x0, 0x0, 0x1000000000000000], [0x0, 0x0, 0x0, 0x0, 0x79], [], [{}, {}, {0x2}, {}, {}, {}, {0x0, 0x2}], {0x0, 0x0, 0x20}, {0x0, 0x0, 0x2}}})


r0 = socket(0x2, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt$sock_int(r0, 0xffff, 0x1, &(0x7f0000000200), 0x4)
connect$unix(r0, &(0x7f0000000000), 0x10)


r0 = socket(0x2, 0x1, 0x0)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000000)="b886b4e47f", 0xfffffffffffffee7}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r1 = socket(0x2, 0x1, 0x0)
bind(r1, &(0x7f0000000000), 0x10)
listen(r1, 0x0)
connect$unix(r0, &(0x7f0000000000), 0x10)
write(r0, &(0x7f0000000080)="04bdfa5d1d2873c63e3534825ba166e2fea9aec43050006123339a346f731573d8d508753f95b7688ad48b8cf6bbca325cebc37fc4e1dd543dbe2da6dd", 0xffea)
shutdown(r0, 0x2)


r0 = socket(0x18, 0x2, 0x0)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000380)=0xffffffffffffff24)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
r1 = socket(0x18, 0x1, 0x0)
dup2(r0, r1)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000200)={&(0x7f00000001c0)=[{}, {0x22}], 0x2})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{0x3d}, {0x84}, {0x4000006}]})
write(r0, &(0x7f0000000180)="23009100007adb020317bdda2b7e", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
r2 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCPROMISC(r1, 0x20004269)
dup2(r2, r1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000100)=[{0x44}, {0x2}, {0x6}]})
r1 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000100)={0x0, <r2=>0x0, <r3=>0x0}, &(0x7f0000000140)=0xc)
setreuid(0xee00, 0x0)
r4 = getuid()
setreuid(0xee00, r4)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r5 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r5, 0x80286987, &(0x7f00000001c0))
r6 = semget$private(0x0, 0x4000000009, 0x82)
semop(r6, &(0x7f00000000c0)=[{0x4, 0x0, 0xe5ce97ab354d96be}, {0x5, 0x2, 0x800}, {0x3, 0x4}, {0x4, 0x2}], 0x4)
semop(r6, &(0x7f0000000440)=[{0x2, 0x0, 0x1000}, {0x0, 0x9}, {}, {0x0, 0xfeff, 0x800}], 0x4)
r7 = semget(0x3, 0x3, 0x20)
semctl$SETALL(r7, 0x0, 0x9, &(0x7f0000000180))
r8 = getuid()
chown(&(0x7f0000000040)='./file0\x00', r8, 0xffffffffffffffff)
semctl$IPC_SET(r6, 0x0, 0x1, &(0x7f00000003c0)={{0xff, r8, r3, r2, r3, 0x2, 0x20}, 0x0, 0xffffffff})
semctl$GETNCNT(r6, 0x0, 0x3, &(0x7f0000000240)=""/4096)
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])


syz_emit_ethernet(0x11f, &(0x7f0000000280)=ANY=[@ANYBLOB="ffffffffffff00000000000086dd605af6a400200000e1403605dd3b845a85a7a49610787775ff0200000000000000000000000000010000c204"])


syz_open_pts()
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
pwritev(r0, &(0x7f00000007c0)=[{&(0x7f0000000500)="419590b6c16b49c5", 0x8}], 0x1, 0x3fff9)
r1 = open$dir(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
preadv(r1, &(0x7f00000004c0)=[{&(0x7f00000000c0)=""/99, 0xfffffd23}], 0x1, 0x0)


setrlimit(0x8, &(0x7f0000000040)={0x7, 0x200004})
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={0x0, 0x3f8d}, 0x10, 0x0, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, 0x0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000002c0)={<r2=>0xffffffffffffffff})
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000440)={<r3=>0x0, <r4=>0x0, <r5=>0x0}, &(0x7f0000000040)=0xc)
r6 = msgget$private(0x0, 0x397)
msgrcv(r6, &(0x7f0000000280)={0x0, ""/9}, 0x6, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x54}, 0x6, 0x0, 0x0, 0x0, 0x0)
msgrcv(r6, 0x0, 0x0, 0x3, 0x1000)
msgsnd(r6, &(0x7f0000000d00)=ANY=[@ANYRESHEX], 0x401, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{}, {0x54}, {0x6}]})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000400)={&(0x7f0000000240)=@abs={0x0, 0x0, 0x1}, 0x8, &(0x7f00000003c0)=[{&(0x7f0000000300)="e04a4ec7ba1b31556484481ee23d", 0xe}, {&(0x7f00000004c0)="db4b1cb0dc17087226d5a89d4a24b94dc40e72adfe2597b4c3f9f71fa182726e3319bc10e54e8d5933ec8ec5d96ac4e330bdc542b6490e6b9a03bf2f4b8b7ea282643837d6b631794a94c748e47234642b88c18fec97247eb33fd6464d6a659fd398bbb88fd882cd4c7ac288f71aac325a33fb51bb87c13d51638bc93cdee3d89c01f65afdbe396643e5718eeb533cc674b1afa4da7795a66f7dc89e6b65c3d16f84fbb59a6363606c8c4c510d70fc933325ec8abec2079ef6ac70d244c26192dbec08ba81a9cef2e0044cfd7451ed20e961d957", 0xd4}], 0x2, &(0x7f0000000940)=ANY=[@ANYBLOB="2000000000000000ffff000000000000", @ANYRES32=r3, @ANYRES32=r4, @ANYRES32=r5, @ANYBLOB="000000001800000000000000ffff000001000000", @ANYRES32=r1, @ANYRES32=r1, @ANYBLOB="1000000000000000ffff0000010000002000000000000000ffff000001000000", @ANYRES32, @ANYRES32, @ANYBLOB="2000000000000000ffff000001000000", @ANYRES32=r0, @ANYRES32, @ANYRES32=0xffffffffffffff9c, @ANYBLOB="000000002000000000000000ffff000000000000", @ANYRES32=r3, @ANYRES32=r4, @ANYRES32=r5, @ANYBLOB="000000002000000000000000ffff000000000000", @ANYRES32=r3, @ANYRES32=r4, @ANYRES32=r5, @ANYBLOB="00000000c0254f4e583b179616bd222ba722eed6f0eb9d2da25d36dc7c89839c9cde794583d5f3ce0e516eef0ae15012373982b46ee48110ba85d7fd0d7b7da7638270b51becd86cffe11aacfe57db403b50a81cc22e"], 0xc8, 0x1}, 0x9)
msgctl$IPC_SET(r6, 0x1, &(0x7f0000000340)={{0x80000001, 0x0, 0x0, r4, 0x0, 0x2, 0x9}, 0x7ff, 0xffffffff00000000, 0x0, 0x0, 0xffffffffffffffff, 0x7, 0x12c, 0x3})
wait4(0xffffffffffffffff, &(0x7f00000000c0), 0x3, &(0x7f0000000140))
getrlimit(0x4, &(0x7f0000000200))
r7 = syz_open_pts()
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={<r8=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000640)={0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x1}, 0x0)
recvmsg(0xffffffffffffffff, &(0x7f0000000100)={0x0, 0x0, &(0x7f0000000640), 0x0, 0x0}, 0x1840)
sendmmsg(r8, &(0x7f0000000480)={0x0}, 0x10, 0x0)
close(r7)
syz_open_pts()
r9 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7817)
writev(r9, &(0x7f00000006c0)=[{&(0x7f0000000280)='#!', 0x2}], 0x1)
write(r9, &(0x7f0000000040)="ac9e8912e07a6657d047b31baa1c85d7cd36e5a9ce0d64e77adbcea12009e3ffffff5c2a591c97413fb5db308cbbae", 0x2f)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000280)={0x3, &(0x7f0000000240)=[{0x48}, {0x4c}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000240)=ANY=[])


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
chdir(&(0x7f0000000240)='./file0\x00')
mkdir(&(0x7f00000001c0)='./file1\x00', 0x0)
setreuid(0x0, 0xee01)
mkdir(&(0x7f0000000100)='./file0\x00', 0x184)
rename(&(0x7f0000000340)='./file0\x00', &(0x7f0000000380)='./file1\x00')
ioctl$BIOCSRTIMEOUT(0xffffffffffffffff, 0x8010426d, &(0x7f0000000200)={0x8, 0x100})
rename(&(0x7f0000000080)='./file1\x00', &(0x7f0000000540)='./file0\x00')
r0 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmat(r0, &(0x7f0000001000/0x3000)=nil, 0x0)


mkdir(&(0x7f0000000040)='./file0\x00', 0x0)
mkdir(&(0x7f0000000740)='./file0/file1\x00', 0x0)
unveil(&(0x7f0000000000)='./file0\x00', &(0x7f00000001c0)='x\x00')
chroot(&(0x7f0000000100)='./file0/file1\x00')
unveil(&(0x7f0000000340)='./file1\x00', &(0x7f0000000380)='r\x00')
unveil(&(0x7f0000000080)='./file0/file1\x00', &(0x7f00000000c0)='r\x00')


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0xb, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
r2 = socket(0x18, 0x1, 0x0)
dup2(r1, r2)
setsockopt(r2, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r3 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x889, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r3, 0x80105728, &(0x7f0000000040)={&(0x7f0000000000)=[{0x23}, {}], 0x2})
r4 = socket(0x18, 0x400000002, 0x0)
accept$inet6(r4, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x2)
readv(0xffffffffffffffff, &(0x7f0000002d40)=[{&(0x7f0000000240)=""/134, 0x86}, {&(0x7f00000019c0)=""/61, 0x3d}, {&(0x7f0000000100)=""/45, 0x2d}, {0x0}, {0x0}, {&(0x7f0000002cc0)=""/85, 0x55}], 0x6)
syz_emit_ethernet(0x32, &(0x7f0000000200)=ANY=[@ANYBLOB="ffff000688480200000000000009aabb33050000000ecac5230e99fb17d156febe778800"/50])
minherit(&(0x7f0000800000/0x800000)=nil, 0x802000000000, 0x0)
setrlimit(0x8, 0x0)
close(0xffffffffffffffff)
syz_open_pts()
syz_emit_ethernet(0x36, &(0x7f00000000c0)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @empty, @rand_addr=0xac14ffff}, @tcp={{0x0, 0x3, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})
ioctl$BIOCIMMEDIATE(r3, 0x80044270, &(0x7f0000000140)=0x4)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f00000000c0)=[{0x64}, {0x54}, {0x4000006, 0x0, 0x0, 0xfffffffd}]})
writev(r0, 0x0, 0x0)


setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)
munlock(&(0x7f0000ffc000/0x1000)=nil, 0x1000)
munlock(&(0x7f0000ffc000/0x4000)=nil, 0x4000)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x100000000000000, 0x10000000000001}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendmsg$unix(r0, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


mprotect(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x0)
munmap(&(0x7f0000ffd000/0x1000)=nil, 0x1000)
msync(&(0x7f0000800000/0x800000)=nil, 0x800000, 0x6)


r0 = socket(0x11, 0x3, 0x0)
setsockopt(r0, 0x11, 0x1, &(0x7f0000000200)="12000001", 0x4)
sendto$unix(r0, &(0x7f00000003c0)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
getpid()
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x100000000000000})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000040)=[{0x20}, {0x64}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = socket(0x18, 0x3, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f0000000180)=[{{r0}, 0xfffffffffffffffa, 0xc1}, {{r0}, 0xfffffffffffffffb}], 0x5, 0x0, 0x9, 0x0)


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$vnd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
accept$unix(0xffffffffffffff9c, 0x0, 0x0)
getpid()
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000440)={0x3, &(0x7f0000000240)=[{0x2}, {0x5}, {0x812e}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000080)='\x00\x00\x00\x00', 0x4)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r2 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0106924, &(0x7f00000001c0))
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
write(r3, &(0x7f0000000140)="7f23a3c2", 0x4)


socket(0x11, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f00000005c0), 0x0, 0x0)
flock(0xffffffffffffffff, 0x0)
flock(0xffffffffffffffff, 0x0)
syz_open_pts()
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
r0 = open(&(0x7f0000000080)='./file1\x00', 0x200, 0x0)
r1 = socket(0x1, 0x5, 0x0)
r2 = dup2(r1, r1)
ioctl$BIOCSHDRCMPLT(r2, 0x20006601, 0x0)
mmap(&(0x7f0000011000/0x2000)=nil, 0x2000, 0x0, 0x10, r0, 0x0)
mprotect(&(0x7f000000e000/0x4000)=nil, 0x4000, 0x3)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000080)=[{0x3d}, {0x7}, {0x8186}]})
mkdir(&(0x7f0000000300)='./file0\x00', 0x0)
socket$unix(0x1, 0x1, 0x0)
mlock(&(0x7f000000f000/0x4000)=nil, 0x4000)


r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0x25, &(0x7f0000000000), 0x0)


socket(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x1, 0x0, 0x0, 0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x37}, 0x4, &(0x7f0000000000)="71f91e3471ac0058bc5a91501d942400b5e1a0757cb9af769c7afec37082", &(0x7f0000000080)=0x56, 0x0, 0x2e)
mknod(&(0x7f00000000c0)='./bus\x00', 0x1000, 0x7ff)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000080)=[{0x28}, {0x3}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])
r1 = open(&(0x7f0000000180)='./file1\x00', 0x2, 0x4)
open(&(0x7f0000000000)='./file0\x00', 0x200, 0x20)
unveil(&(0x7f0000000080)='.\x00', &(0x7f0000000000)='x\x00')
open$dir(&(0x7f0000000140)='./file0\x00', 0x1, 0x0)
setsockopt(r1, 0xddf, 0x83, &(0x7f0000000100)="0141db7dbed4cd630668eafb115f0892dccb7c7ac9e70c9d4d02f72dc3b82db9f82d1aa987b77ec88d433dedb32e8495e50fb1acd897716cbde4d7bdbbcb06c1675546a552f3842f2cb031d386f0af4962032b693d8865fb3fb47ea17bd9121de385ea64b9d802a5b7f2a2bca0decd", 0x6f)
mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
socket(0x2, 0x0, 0x4)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
r2 = kqueue()
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
open(0x0, 0x80, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000680)={<r3=>0xffffffffffffffff})
sendmmsg(r3, 0x0, 0x0, 0x0)
poll(0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, r2)
r4 = socket(0x0, 0x3, 0x0)
ioctl$FIONREAD(r4, 0x80206979, &(0x7f00000001c0))
fcntl$dupfd(0xffffffffffffffff, 0x0, r4)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
close(r1)
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f0000000040)=0xfffffffc)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000001a00)=0x5)
writev(r0, &(0x7f0000000080)=[{0x0}], 0x1)
writev(r0, &(0x7f0000000240)=[{0x0}], 0x1)


mknod(&(0x7f0000000500)='./file0\x00', 0x1000, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x80206910, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{}, {0xc}, {0x40e}]})
syz_emit_ethernet(0xe, &(0x7f0000000100)=ANY=[])


syz_emit_ethernet(0x4e, &(0x7f0000000500)=ANY=[@ANYBLOB="8925000040002adb0070162e86dd60f6190000180600fe8000000000000000000000000000aaff"])


setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(r0, 0xffffffffffffffff)
mknod(&(0x7f0000000000)='./file0\x00', 0x6000, 0xe02)
r1 = open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
readv(r1, &(0x7f00000001c0)=[{&(0x7f0000000140)=""/18, 0x12}], 0x1)
preadv(r1, &(0x7f0000001540)=[{&(0x7f0000000080)=""/189, 0xbd}], 0x1, 0x1000)


r0 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000001000/0x3000)=nil)
setreuid(0xee00, 0x0)
r1 = getuid()
setreuid(0x0, r1)
shmat(r0, &(0x7f0000001000/0x3000)=nil, 0x0)


r0 = socket(0x18, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x81206919, &(0x7f0000000100))


setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)='4', 0x1}], 0x1)
r1 = kqueue()
kevent(r1, &(0x7f0000000640)=[{{r0}, 0xffffffffffffffff, 0x3f}], 0x8008, 0x0, 0x0, 0x0)
kevent(r1, 0x0, 0x0, &(0x7f0000000280), 0x6c, 0x0)


mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
getpid()
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
r0 = socket(0x18, 0x2, 0x0)
bind$unix(r0, &(0x7f0000000100)=@abs={0x0, 0x0, 0x1}, 0x8)
r1 = socket(0x2, 0x2, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
r2 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
setsockopt$inet_opts(r2, 0x0, 0x200000000000a, &(0x7f00000000c0), 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
setsockopt(0xffffffffffffffff, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
setsockopt(0xffffffffffffffff, 0x1000000029, 0xc, &(0x7f0000000080), 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
bind(r1, &(0x7f0000000000), 0x10)


r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r0, 0x80085761, &(0x7f00000000c0)={0x3})
r1 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000180), 0x1, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(r1, 0x80085762, &(0x7f0000000400)={0x3})


setsockopt(0xffffffffffffff9c, 0x4, 0x80000000, &(0x7f0000000080)="9a355e7e63420f9ada1c646027a90f340c5d8fa6d0ebde0b3de23ecefe0866cf28a2b00e8a084af81d3c41d7f8d0ac778b2a450e95748d111654c23733ad6ad34289d5e81fd7f24c24b7065ce2c1330aa6d122b5661dd9858060116b26719d0996dbd43152ed8c396ed6a31019e27f8f1371be4cf99757708077d682eced72d2091c1b912324205c567f7539aface5", 0x8f)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x36)
getpgid(0xffffffffffffffff)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000200)={0x0, 0x8, 0xfffffff8, 0x0, "09000000ffffffff080400"})
mknod(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = kqueue()
kevent(r2, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r3 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r3, 0xc0206921, &(0x7f00000001c0))
r4 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r4, 0x80206916, &(0x7f00000001c0))


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000040)='./file0\x00', 0x2000, 0x20)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x200, 0x4ebfac6bbaf796d)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
socket(0x2, 0x0, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
close(0xffffffffffffffff)
open$dir(0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, &(0x7f0000000140)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
recvmsg(r1, &(0x7f0000000340)={0x0, 0x0, 0x0, 0x0, &(0x7f00000024c0)=""/236, 0xec}, 0x0)
chroot(&(0x7f0000000740)='.\x00')
openat$vnd(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$TIOCCONS(r0, 0x80047462, &(0x7f0000000080)=0x1)


mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
open$dir(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
read(r0, &(0x7f0000000100)=""/192, 0xc0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd02)
r1 = open(&(0x7f0000000080)='./bus\x00', 0x20000, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
mmap(&(0x7f0000429000/0x1000)=nil, 0x1000, 0x2, 0x6010, r2, 0xbf)
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000140)={0x4c, &(0x7f0000000040)=[{0x2}, {}, {}]})
syz_emit_ethernet(0xe, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x2, &(0x7f0000000040)=[{0x44}, {0x6}]})
ioctl$BIOCGBLEN(0xffffffffffffffff, 0x40044266, &(0x7f0000000200))
ftruncate(r1, 0x3)
syz_extract_tcp_res$synack(&(0x7f0000000480), 0x1, 0x0)
socket(0x18, 0x2, 0x0)


mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0, 0x0)
syz_emit_ethernet(0x46, &(0x7f0000000080)=ANY=[@ANYBLOB="500004"])
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0xfffffffa, 0xffffffbf, "0000c6f26461c094f4ffffffff00"})
readv(r1, &(0x7f0000000280)=[{&(0x7f0000000480)=""/131, 0x83}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{}, {}, {0x6}]})
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000040)="03", 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x0, 0x0})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000), 0x10)
r1 = dup(r0)
listen(r1, 0x0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
accept$inet(r1, 0x0, 0x0)
r3 = socket(0x2, 0x1, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)
r4 = dup(r3)
sendto$inet(r4, &(0x7f0000000240)="03", 0x1, 0x1, 0x0, 0x0)
write(r3, &(0x7f0000000040)="04", 0xff9a)
setsockopt$sock_int(r2, 0xffff, 0x1023, &(0x7f0000000080), 0x4)


sysctl$hw(&(0x7f0000000240)={0x6, 0x10}, 0x2, 0x0, 0x0, 0x0, 0x0)


munmap(&(0x7f0000ffd000/0x1000)=nil, 0x1000)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
flock(0xffffffffffffffff, 0x0)
flock(0xffffffffffffffff, 0x0)
syz_open_pts()
mknod(0x0, 0x0, 0x0)
r0 = open(&(0x7f0000000080)='./file1\x00', 0x200, 0x0)
mmap(&(0x7f0000011000/0x2000)=nil, 0x2000, 0x0, 0x10, r0, 0x0)
mprotect(&(0x7f000000e000/0x4000)=nil, 0x4000, 0x3)
mlock(&(0x7f000000f000/0x4000)=nil, 0x4000)


mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x412dff)
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, &(0x7f0000000440)={&(0x7f0000000280)='./bus\x00', 0x1000, &(0x7f00000002c0)='./bus\x00', 0x6})
r0 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
recvmsg(0xffffffffffffffff, &(0x7f00000025c0)={0x0, 0x0, &(0x7f0000002540)=[{&(0x7f0000003640)=""/4100, 0x1004}], 0x1, 0x0}, 0x0)
preadv(r0, &(0x7f0000000300)=[{&(0x7f00000000c0)=""/104}, {&(0x7f0000000140)=""/192}, {&(0x7f0000000340)=""/175}, {&(0x7f0000000000)=""/18}], 0x10000000000002b8, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
open(0x0, 0x0, 0x0)
mmap(&(0x7f00000a7000/0x9000)=nil, 0x9000, 0x1, 0x10, 0xffffffffffffffff, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
mlockall(0x1)
fchmod(0xffffffffffffffff, 0xd6)
r1 = socket(0x18, 0x3, 0x0)
setsockopt(r1, 0x1000000029, 0x0, &(0x7f0000000000)="5ab7776a", 0x4)
close(0xffffffffffffffff)
setsockopt(r1, 0xfffffff8, 0x7ff, &(0x7f0000000480)="2ac4310fdd8ee9d1ba160fa33bb09b1d2a7a7dfcb12e73e54a912b32e32705cfce67c7216048d2d79285d69468a9c98173c04c5d85746d905d461e2e8f757424d9d838c3569f12286a636e347bafc5f95c5d5df4ccfd9b8a62f1428a2f2b09fd325fd7b8e9f52aa37162", 0x6a)
fcntl$dupfd(r0, 0x0, r1)
r2 = socket(0x10, 0x4000, 0x0)
setsockopt(r2, 0x1000000029, 0x26, &(0x7f0000000200)="5ab7776a", 0x4)
pipe(&(0x7f0000000040)={<r3=>0xffffffffffffffff})
ioctl$FIOSETOWN(r3, 0x80047308, &(0x7f0000000000))
pipe(&(0x7f0000000040)={<r4=>0xffffffffffffffff, <r5=>0xffffffffffffffff})
r6 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, 0x0, &(0x7f0000000a40), &(0x7f0000000a80), 0x0)
fcntl$dupfd(r5, 0x0, r4)
ioctl$BIOCSETIF(r6, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETWF(r6, 0x80104277, &(0x7f0000000280)={0x3, &(0x7f00000000c0)=[{0xc}, {0x5}, {0x6, 0x0, 0x0, 0xffffffff}]})
mmap(&(0x7f0000fff000/0x1000)=nil, 0x1000, 0x2, 0x13, r6, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r0, 0xc2485607, &(0x7f0000000300)={0x2, 0x0, 0x7, 0x0, 0x0})


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000080)={<r0=>0xffffffffffffffff})
r1 = syz_open_pts()
fcntl$lock(r1, 0x8, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1000300800000})
flock(r1, 0x1)
fcntl$lock(r1, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000001})
syz_open_pts()
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
r2 = socket(0x18, 0x3, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r2, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
r3 = socket(0x18, 0x2, 0x0)
r4 = getpgrp()
fcntl$lock(0xffffffffffffffff, 0x8, &(0x7f00000000c0)={0x2, 0x1, 0xfffffffffffffffe, 0x10000000f2, r4})
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000100)={0x0, <r5=>0x0}, &(0x7f0000000140)=0xc)
r6 = getuid()
r7 = geteuid()
setreuid(r6, r7)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000040)={0x0, 0x0, <r8=>0x0}, &(0x7f0000000140)=0xc)
r9 = socket(0x18, 0x1, 0x0)
setsockopt(r9, 0x1000000029, 0x2f, 0x0, 0x0)
fchown(r9, r6, r8)
setsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000180)={r4, r5, r8}, 0xc)
close(r3)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0xfffffffffffffffe}], 0x0, 0x0, 0x0, 0x0)
r10 = socket(0x800000018, 0x2, 0x0)
setsockopt$sock_int(r10, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r10, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
writev(r3, &(0x7f00000004c0)=[{0x0}], 0x1)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x4000000000000000, 0xffffffffffffffff})
ioctl$TIOCGETD(0xffffffffffffffff, 0x4004741a, &(0x7f00000001c0))
openat$wsdisplay(0xffffffffffffff9c, &(0x7f0000000080), 0x20040, 0x0)
openat$wsdisplay(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000140), 0x1, 0x0)
r1 = dup2(r0, r0)
ioctl$WSKBDIO_GETMAP(r1, 0xc0105715, &(0x7f0000000000)={0x0, &(0x7f0000001f40)})
ioctl$WSMUXIO_INJECTEVENT(r1, 0x80185760, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x1, 0x1, 0x0)
r3 = syz_open_pts()
ioctl$TIOCSETVERAUTH(r3, 0x8004741c, &(0x7f0000000040)=0x5)
close(r2)
r4 = socket(0x18, 0x1, 0x0)
setsockopt(r4, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
dup(0xffffffffffffffff)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x2, 0x0)
r1 = dup(r0)
setsockopt$inet_opts(r1, 0x0, 0x13, &(0x7f0000000040)="fd0cc085", 0x4)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
r1 = dup(r0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt(r1, 0x1000000000029, 0xd, &(0x7f0000000000)="ffdaf64c000000004f0527000000055e473e0000", 0x14)


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
madvise(&(0x7f00003e0000/0x1000)=nil, 0x1000, 0x0)
munmap(&(0x7f00003e1000/0x1000)=nil, 0x1000)
msync(&(0x7f00003e0000/0x4000)=nil, 0x4000, 0x6)


open(&(0x7f0000000000)='./file0\x00', 0x200, 0x0)
writev(0xffffffffffffffff, &(0x7f00000001c0)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe1463a52077dc0d00003ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x0, 0x0)


msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000040)={{}, 0x0, 0x0, 0x0, 0x0, 0x2})
sysctl$kern(&(0x7f0000000080)={0x1, 0x33}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
getgid()
fchownat(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000100)=[{0x80}, {0x15}, {0x6, 0x0, 0x0, 0x88f0}]})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
pwritev(r0, &(0x7f0000000240)=[{&(0x7f0000000300)="2e2af00c2089c52b1f8674e45d5e", 0xe}], 0x1, 0x0)


open$dir(&(0x7f0000000000)='./file0\x00', 0xf02, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, 0x0)
r0 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f000000b000/0x1000)=nil, 0x1000, 0x5, 0x10, r0, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
fcntl$setstatus(0xffffffffffffffff, 0x4, 0xc0)
r2 = getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r2})
setreuid(0xee00, 0x0)
getuid()
setreuid(0xee00, 0x0)
ioctl$WSKBDIO_GETMAP(0xffffffffffffffff, 0x80047476, 0x0)
fcntl$getown(0xffffffffffffffff, 0x5)
setpgid(0x0, 0x0)
setpgid(0x0, 0x0)
close(0xffffffffffffffff)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000180)={0x4, &(0x7f0000000240)=[{0x6c, 0xfd, 0x3}, {0x50, 0x10, 0x0, 0x25}, {0x9, 0x68}, {0x89e, 0x14, 0x1, 0x5}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x3, 0x2f)
r1 = dup(r0)
setsockopt$inet_opts(r1, 0x0, 0x22, &(0x7f0000000040)="fd0cc085", 0x4)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x2, 0x3, 0x0)
r3 = dup(r1)
dup2(r3, r2)
connect$unix(r2, &(0x7f0000000000), 0x10)
sendto$inet(r1, &(0x7f00000001c0)="5e1351d18b9da08c", 0x8, 0x0, 0x0, 0x0)


r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x2b, 0x28, &(0x7f0000000040)="5ab7776a", 0x4)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b0e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r1 = socket(0x2, 0x1, 0x0)
bind(r1, &(0x7f0000000000), 0x10)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000001280)={0x0, 0x0, &(0x7f0000001200)=[{&(0x7f0000000180)="bf3b684c5ae963b4567084e096cf973983b85e5df63e013eaa9405095e88157332b4f68e78e0793d3e30417acbf4419893cfd424b75262dc5ade2ab6278ab86672f9ed186987b8c19d9295a17b98020f6002", 0x52}], 0x1}, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(r0, 0x8020690c, &(0x7f00000001c0))


sysctl$machdep(&(0x7f0000000080)={0x7, 0xf}, 0x2, 0x0, 0x0, 0x0, 0x0)


r0 = socket(0x2, 0x2, 0x0)
connect$unix(r0, &(0x7f0000000380), 0x10)
getsockname$unix(r0, &(0x7f0000000000)=@abs, &(0x7f0000001200)=0x8)
r1 = socket(0x2, 0x1, 0x0)
bind(r1, &(0x7f0000000000), 0x10)
r2 = dup(r1)
listen(r2, 0x0)
setsockopt(r1, 0x6, 0x1, &(0x7f0000000680)="15acbc2c", 0x4)
r3 = socket(0x2, 0x1, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)
r4 = socket(0x18, 0x1, 0x0)
r5 = dup2(r4, r4)
r6 = fcntl$dupfd(r5, 0x2, 0xffffffffffffffff)
close(r6)
accept$inet(r1, 0x0, 0x0)
setsockopt$sock_int(r6, 0xffff, 0x100, &(0x7f0000000140)=0x401, 0x4)
sendmsg$unix(r3, &(0x7f00000000c0)={0x0, 0x0, &(0x7f0000000100)=[{&(0x7f0000000740)="fe", 0x1}, {&(0x7f0000000180)='Q', 0x1}], 0x2}, 0x401)
setsockopt$sock_int(r6, 0xffff, 0x1023, &(0x7f0000000080), 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{0x1}, {0x3c}, {0x6}]})
syz_emit_ethernet(0x52, &(0x7f0000000300)=ANY=[])


ioctl$WSKBDIO_GETDEFAULTKEYREPEAT(0xffffffffffffffff, 0x400c570a, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000480), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000140)=[{0x40}, {0x74}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])


clock_getres(0x0, &(0x7f0000000000))
setuid(0xffffffffffffffff)
ioctl$PCIOCREAD(0xffffffffffffffff, 0xc0107002, 0x0)
openat$speaker(0xffffffffffffff9c, 0x0, 0xb6596b9bc0836dc, 0x0)
sysctl$net_inet_tcp(&(0x7f00000001c0)={0x4, 0x2, 0x6, 0x3}, 0x4, &(0x7f00000002c0), 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000300)=[{&(0x7f0000000400)}], 0x1)
r0 = socket(0x0, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x3a, 0x0)
syz_emit_ethernet(0x138, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
connect$unix(r0, &(0x7f0000000000), 0x10)
write(r0, &(0x7f0000000240)="14bdfa5d1d34e2fecb284a6498307dcda9aec43050036123339a346f737850551408753f95b7688ad4c4e1dd5489e7bafc58d3e5823757ae8b630719ef187ccad995f13dbe19a6dd4e6902bd8297b0799b426aabe9fad9db6996571c6d9f8bb5d542c2148aa42be940970fe88d34d8f99afe7e782023740000000000800000010000000000000000", 0x88)
sysctl$kern(&(0x7f0000000040)={0x1, 0x59}, 0x3, 0x0, 0x0, &(0x7f0000000080)="4f1d4c6344b80ed788b6a4515248df3aa745bb992c574ab4cdf5587145812eab4a988f7fafd7a01d99776d988908cd186b51f34f8c15ffa0c685ad4116c783959eff4278384b4000384dbb1c2aaeff10b4135529a1da6fda67c67469d954be811b25ec5521559154c586eefff122009f659cd3e27e98a3241495005f102d9101d158284c0ee3250aa7c11042330de22a299ab00894fdc9bac6042d", 0xfffffc56)
getitimer(0x0, 0x0)
semget$private(0x0, 0x4, 0x42)
ioctl$TIOCCONS(0xffffffffffffffff, 0x80047462, 0x0)
r1 = openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x7, &(0x7f0000000140)={0x0, 0x0, 0xfffffffffffffffe, 0x0, 0xffffffffffffffff})
syz_open_pts()
ioctl$TIOCSPGRP(r1, 0x40047477, &(0x7f0000000180))
syz_open_pts()
socket(0x11, 0x7ffd, 0x0)
r2 = msgget$private(0x0, 0x0)
msgrcv(r2, 0x0, 0x0, 0x0, 0x1700)


socket(0x2, 0x2, 0x0)
shmctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{0x3, 0x0, 0xffffffffffffffff, 0xffffffffffffffff}})
r0 = kqueue()
kevent(r0, 0x0, 0x0, 0x0, 0x7, 0x0)
sysctl$kern(&(0x7f0000000040), 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
kevent(r0, 0x0, 0x0, 0x0, 0x9, &(0x7f0000000040))
kevent(r0, &(0x7f0000000000), 0x29f, 0x0, 0x8001, 0x0)


ioctl$TIOCSETD(0xffffffffffffffff, 0x8004741b, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$FIOSETOWN(0xffffffffffffffff, 0x80047476, &(0x7f0000000100)=0xffffe001)
r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f00000000c0)={0x0, 0x0, 0xfffffffe, 0x0, "031ffe40630000000000ff00010400"})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
r1 = socket(0x18, 0x3, 0x0)
close(r1)
r2 = socket(0x800000018, 0x2, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "1a05227955686f43a3207fae210b8591073300"})
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000100)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = dup2(r1, r0)
sendmsg$unix(r3, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000680)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x1, &(0x7f00000000c0)=[{0x64}]})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
syz_emit_ethernet(0x52, &(0x7f0000000080)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa86dd60000000001c2b00fe350e28ef0900c08cfe24be00000000fe80000000000000000000", @ANYRES32=0x41424344, @ANYRES32=0x41424344])
ioctl$BIOCSETIF(r1, 0x8020426c, 0x0)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f00000001c0)={0x0, 0x0})
syz_emit_ethernet(0x10a2, &(0x7f0000000080)=ANY=[])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
r2 = socket(0x18, 0x1, 0x0)
setsockopt(r2, 0x1000000029, 0x0, 0x0, 0x0)
ioctl$BIOCLOCK(r0, 0x20004276)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000a, &(0x7f0000000000)="ea00005c00000000", 0x1)
setsockopt$inet_opts(r0, 0x0, 0xb, &(0x7f0000001500)='\t', 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x1d}, {0x5}, {0x8106}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
r1 = socket$inet(0x2, 0x2, 0x0)
dup2(r0, r1)
r2 = open(&(0x7f0000000140)='./file0\x00', 0x78e, 0x0)
ktrace(&(0x7f0000000040)='./file0\x00', 0x0, 0x20, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000200)="ea00000000000000", 0x8)


ioctl$TIOCSETA(0xffffffffffffff9c, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "0100dd2dfa7f0000000400"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x4f}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000040), 0x3, 0x0, 0x0, &(0x7f0000000080)="4f1d4c6344b80ed788b6a4515248df3aa745bb992c574ab4cdf5587145812eab4a988f7fafd7a01d99776d988908cd186b51f34f8c15ffa0c685ad4116c783959eff4278384b4000384dbb1c2aaeff10b4135529a1da6fda67c67469d954be811b25ec5521559154c586eefff122009f659cd3e27e98a3241495005f102d9101d158284c0ee3250aa7c11042330de22a299ab00894fdc9bac6042d", 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000001380)=[{0x3}, {0x24}, {0x6}]})
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])


setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0xee00, r0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x7fffffff, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


setuid(0xffffffffffffffff)
r0 = socket(0x800000018, 0x1, 0x0)
select(0x0, 0x0, &(0x7f0000000080)={0x0, 0x0, 0x100000000000000}, 0x0, 0x0)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


r0 = socket$inet(0x2, 0x3, 0x0)
setsockopt(r0, 0x0, 0x3, &(0x7f0000000040)="8f73e7cd", 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000080)=[{0x5}, {0x44}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000300)=ANY=[])


r0 = kqueue()
pipe(&(0x7f0000000240)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
kevent(r0, &(0x7f00000002c0)=[{{r1}, 0xfffffffffffffff7, 0xa5}], 0x7, 0x0, 0x8, 0x0)


setrlimit(0x0, 0x0)
r0 = syz_open_pts()
close(r0)
ioctl$TIOCSETAW(0xffffffffffffffff, 0x802c7415, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f0000000080)=[{{r0}, 0xfffffffffffffffe, 0x41}], 0x8000, 0x0, 0x0, 0x0)
r2 = socket(0x18, 0x2, 0x0)
unveil(&(0x7f0000000040)='./file0\x00', &(0x7f0000000080)='c\x00')
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f0000000180), 0x0)
syz_emit_ethernet(0x36, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x28, 0x0, 0x1}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
r3 = dup(r2)
setsockopt(r3, 0x1000000000029, 0x2b, 0x0, 0x0)
clock_getres(0x0, &(0x7f0000000000))
setreuid(0xee00, 0x0)
sysctl$net_inet_carp(&(0x7f0000000380)={0x4, 0x2, 0x70, 0x4}, 0x4, 0x0, 0x0, 0x0, 0x0)
getuid()
socket(0x2, 0x1, 0x0)
r4 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x0, 0x10, r4, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f00000000c0)='./file0\x00', 0x21e)
chdir(&(0x7f0000000140)='./file0\x00')
symlink(&(0x7f0000000200)='./file2\x00', &(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
open(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)


open(&(0x7f0000001700)='./file0\x00', 0x70e, 0x0)
mmap(&(0x7f000000e000/0x2000)=nil, 0x2000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
open(0x0, 0x0, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x0, 0x10, 0xffffffffffffffff, 0x7fffffff)
setrlimit(0x6, &(0x7f00000000c0))
kqueue()
open$dir(&(0x7f0000000240)='./file0\x00', 0x8400, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x4}, 0x4, 0x0, 0x0, &(0x7f0000000040)="1fd1", 0x2)
r0 = socket(0x0, 0x3, 0x0)
setsockopt(r0, 0x11, 0x0, 0x0, 0x0)
r1 = socket(0x2, 0x3, 0x0)
getsockopt(r1, 0x0, 0x68, 0x0, 0x0)
r2 = openat$tty(0xffffffffffffff9c, &(0x7f0000000140), 0x20000, 0x0)
ioctl$TIOCSDTR(r2, 0x20007479)
r3 = msgget$private(0x0, 0x0)
msgsnd(r3, &(0x7f00000001c0)=ANY=[@ANYRES32], 0x401, 0x0)
msgsnd(r3, 0x0, 0x401, 0x800)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x4000000000000000, 0xffffffffffffffff})
mkdir(&(0x7f0000000040)='./file0\x00', 0x0)
setreuid(0xee00, 0x0)
getuid()
r0 = socket(0x800000018, 0x2, 0x0)
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x29, 0xe, 0x0, 0x0)
dup2(r1, r0)
ioctl$KDGETLED(0xffffffffffffffff, 0x40044b41, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000040)={0x0, 0x0, <r2=>0x0}, 0x0)
chown(0x0, 0x0, 0x0)
r3 = socket(0x2, 0x2, 0x0)
connect$unix(r3, &(0x7f0000000380), 0x10)
r4 = semget$private(0x0, 0x7, 0x3c0)
semctl$IPC_SET(r4, 0x0, 0x1, &(0x7f0000000240)={{0x8001, 0xffffffffffffffff, 0x0, 0xffffffffffffffff, 0x0, 0x40, 0x2}, 0x0, 0x9, 0xe7})
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000200)={{0x3, 0x0, r2, 0x0, 0x0, 0xa, 0x8}, 0x1, 0x1, 0x5})
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000000c0), &(0x7f0000000040)=0xc)
semget(0x0, 0x0, 0x470)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047470, &(0x7f0000000140)=0x2)
ioctl$FIOASYNC(r0, 0x80047460, &(0x7f00000000c0)=0x4)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000380)={0x0, 0x0, 0x0, 0x0, "469523e4b4b406ac5b1496c683f258819f499464"})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000a40)=[{0x45}, {0x84}, {0x16}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000100)=[{}, {0x28}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000480)={'tap', 0x0})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSFILDROP(r1, 0x80044279, &(0x7f0000000100)=0x2)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
syz_emit_ethernet(0x62, &(0x7f0000000180)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x1d}, {0x7c}, {0x8106}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])


socket$unix(0x1, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000300)={0x3, &(0x7f0000001780)=[{0x44}, {0x3}, {0x16}]})
write(r0, &(0x7f00000001c0)="d9537abde93d050cdd16b13f742a", 0xe)


sysctl$net_inet6_icmp6(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)
getgroups(0x3, &(0x7f0000000180)=[0x0, 0x0, 0xffffffffffffffff])
mknod(&(0x7f0000000200)='./file0\x00', 0x20, 0x3202)
open$dir(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
sysctl$net_inet6_icmp6(&(0x7f0000000280)={0x4, 0x18, 0x3a, 0xe3df110dcefbd52d}, 0x4, &(0x7f00000002c0)="cfc1048c6317244b0e4433c6bcd4beb239b4c381afe492a34e9fe1292e37afb268fd35de0f5f65b8fb3bf782ff40f3856fbc0a917bba8b5d116a111b1dce15f9e07454d91b82066fab0287ba58ff7ced43ba176d45cc", &(0x7f0000000340)=0x56, &(0x7f0000000400)="2704ba67a009fa6e31b25321a82ff4ea67c2e185bb0ccea0a17ba6535a00182519301fc7e2634db114cf879b23978c108710ab06276de8b1a16ffffc7973ac3635cb6c0fe5da884c2e2a315cff44f5ca69c1516ac6dd086e22cb925940f68cf06612081a0fbcc150e6e1efdfd2a37b3274a30864cf26decdaa38c79186745a4f1741bfa7e8f562d606f51e1568ce0b93ae0886cd67282a4ac5ec7154fed731544ba1f8d041be7c4afd90d6a2ec4db48345b4e93a938e62d42a37a8e88768f5f60c620f3d3b958f9c0ec9532149ad67f3bbf6f0c930ad", 0xd6)
socket(0x18, 0x1, 0x0)
ioctl$VNDIOCSET(0xffffffffffffffff, 0x41946465, 0x0)
sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000000)="9b1809ffffffffffffff7f473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6", &(0x7f0000000040)=0x36, 0x0, 0x0)
r0 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x10, 0x0)
mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x4, 0x10, r0, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x1)
ioctl$BIOCGBLEN(r0, 0x40044266, &(0x7f0000000240))
ioctl$FIONBIO(r0, 0x8004667e, 0x0)
mprotect(&(0x7f0000ffb000/0x1000)=nil, 0x1000, 0x0)
ioctl$WSDISPLAYIO_GBURNER(0xffffffffffffffff, 0x400c5752, 0x0)
munmap(&(0x7f0000ffc000/0x1000)=nil, 0x1000)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff}})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7, 0x3}, 0x8)
close(0xffffffffffffffff)
wait4(0x0, 0x0, 0x1b, &(0x7f0000000000))
write(0xffffffffffffffff, &(0x7f00000000c0), 0x0)
r1 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f00000001c0), 0x1, 0x0)
fcntl$setown(r1, 0x6, 0x0)
ioctl$TIOCDRAIN(r1, 0x2000745e)
close(r0)


write(0xffffffffffffffff, &(0x7f00000001c0)="f864e6de6074dac482", 0x9)
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106978, &(0x7f00000001c0))


syz_emit_ethernet(0x66, &(0x7f0000000080)=ANY=[@ANYBLOB="ffffffffffff000000000000000000000000ffff"])
r0 = socket(0x18, 0x3, 0x0)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892}, 0x1c)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
writev(0xffffffffffffffff, &(0x7f0000000140)=[{&(0x7f0000000500)="7182052190a8db37c2", 0x9}], 0x1)
recvmsg(r1, &(0x7f0000000100)={0x0, 0x0, &(0x7f0000000640)=[{&(0x7f00000006c0)=""/86, 0x56}], 0x1, 0x0}, 0x0)
sendmmsg(r0, &(0x7f0000000480)={0x0}, 0x10, 0x0)


r0 = kqueue()
kevent(r0, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206923, &(0x7f00000001c0))
socket(0x2, 0x2, 0x0)
sysctl$net_pipex(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
mmap(&(0x7f0000028000/0x4000)=nil, 0x4000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(0x0, 0x0, &(0x7f0000000140)="118bea625d95de8f92c010baed45ec4bf03ace254b57973bb6de7b1c90301e9d3b5e6fb6ffffffffffffffff76c775a2a4e0556565a830032eef776127fd247103c14ab0a1cea9b4593be484f46a02ea73e910d041c5777bd852e57d3248832b91d06fe47d126022a1654859149e9486306d2f11fb1cc826c42f81b0d114f8af4ceb029a5210bb6947464bf678ba1d64a2013131fedfe60443aa13e015b28a16ea924bf89ad45c", 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x80286987, &(0x7f00000001c0))


r0 = open(&(0x7f0000001180)='./file0\x00', 0x0, 0x130)
mkdirat(r0, &(0x7f0000000340)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38/\x00', 0x0)
r1 = socket(0x2, 0x3, 0x0)
getsockopt(r1, 0x0, 0x1e, 0x0, 0x0)
open$dir(&(0x7f0000000000)='.\x00', 0x20000, 0x0)
mkdir(&(0x7f0000000000)='./file1\x00', 0x0)
chmod(&(0x7f00000000c0)='./file2\x00', 0x290)
chdir(&(0x7f0000000140)='./file0\x00')
symlink(&(0x7f0000001140)='./file2\x00', &(0x7f0000000340)='./file1\x00')
open(0x0, 0x0, 0x133)
r2 = semget$private(0x0, 0x7, 0x3c0)
rename(&(0x7f00000010c0)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38/\x00', &(0x7f0000001080)='./file1\x00')
semctl$GETPID(r2, 0x3, 0x4, &(0x7f0000000240)=""/8)


getsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
kqueue()
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x5, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x8981, 0x0)
openat$tty(0xffffffffffffff9c, &(0x7f0000000040), 0x80, 0x0)
ioctl$TIOCSETVERAUTH(0xffffffffffffffff, 0x8004741c, &(0x7f0000000080)=0x2)
r0 = semget$private(0x0, 0x1, 0x8a)
semctl$SETALL(r0, 0x0, 0x9, &(0x7f0000000680)=[0x9])
semop(r0, &(0x7f0000000140)=[{0x4, 0x200, 0x1000}, {0x4, 0x201, 0x1000}, {0x0, 0x1000}, {0x0, 0x7a5}, {0x3, 0xff72, 0x1000}, {0x1, 0xdb, 0x800}, {0x0, 0x0, 0x800}, {0x3, 0xa, 0x1000}], 0x8)
semctl$IPC_SET(r0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x26, 0x8}, 0xfffffffffffffffd, 0x2})
semctl$GETALL(r0, 0x0, 0x6, &(0x7f00000004c0)=""/195)
r1 = getuid()
seteuid(r1)
openat$vnd(0xffffffffffffff9c, &(0x7f00000001c0), 0x10, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x51fd)
r2 = open(&(0x7f0000000240)='./file0\x00', 0x0, 0x101)
close(r2)
r3 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r3, 0x6, 0x10, &(0x7f0000000000)="00000001", 0x4)
setsockopt(r3, 0x6, 0x10, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
r4 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r2, 0x6, 0xf, &(0x7f0000000180)="00000001", 0xfe2f)
setsockopt(r4, 0x6, 0x10, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
setsockopt(0xffffffffffffffff, 0x10006, 0x10, &(0x7f0000000100)="0100820001", 0x5)
setuid(0xffffffffffffffff)
r5 = syz_open_pts()
setsockopt$sock_timeval(r4, 0xffff, 0x1005, 0x0, 0x0)
ioctl$TIOCSETD(r5, 0x8004741b, &(0x7f00000002c0)=0x8)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000008c0)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmsg(r1, &(0x7f0000000340)={0x0, 0x0, 0x0, 0x0, &(0x7f00000024c0)=""/236, 0xec}, 0x0)
sendmsg(r0, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000140)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
sendmsg$unix(r3, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="28000000ffff000001"], 0x28}, 0x0)
setrlimit(0x8, &(0x7f0000000980))
recvmmsg(r2, &(0x7f0000000000)={&(0x7f0000000000)={0x0, 0x0, &(0x7f0000000000), 0x0, &(0x7f0000000000), 0x63}}, 0x10, 0x0, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, "1a1116f0d0a607000000000000fffffffffff700", 0x9})


setuid(0xffffffffffffffff)
r0 = syz_open_pts()
ioctl$TIOCSPGRP(r0, 0x40047477, 0x0)
setreuid(0xee00, 0x0)
r1 = semget$private(0x0, 0x4000000009, 0x82)
semop(r1, &(0x7f0000000680)=[{0x2, 0x9, 0x1800}], 0x1)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000900), &(0x7f0000000940)=0xc)
semctl$SETALL(r1, 0x0, 0x9, &(0x7f0000000400)=[0x0])
r2 = geteuid()
semop(r1, &(0x7f0000000140)=[{0x4, 0x200}, {0x7}, {0x0, 0x9}, {0x3, 0x4, 0x1800}, {0x0, 0x5e0, 0x1000}, {0x2, 0x0, 0x1000}, {0x1, 0x9c}, {0x4, 0x6, 0x1000}, {0x0, 0x8001, 0x1000}], 0x9)
semop(r1, &(0x7f00000002c0)=[{0x0, 0x3, 0xc00}], 0x1)
r3 = getgid()
semctl$IPC_STAT(r1, 0x0, 0x2, &(0x7f0000000540)=""/163)
semctl$IPC_SET(r1, 0x0, 0x1, 0x0)
semop(r1, 0x0, 0x0)
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f0000000240)={{0x4, r2, 0x0, r2, r3, 0x20}, 0xfffffffffffffff7, 0x8, 0x81})
r4 = semget$private(0x0, 0x2, 0x621)
semop(r4, &(0x7f00000006c0)=[{0x4, 0x3f, 0x1800}, {0x4, 0xff, 0x1000}, {0x3, 0xe75, 0x800}, {0x4, 0x0, 0x400}, {0x3}, {0x1}, {0x0, 0x0, 0x3000}, {0x1, 0x0, 0x1800}], 0x8)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs, 0x1c)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000040)={{0x1, 0xffffffffffffffff, 0x0, 0x0, r3, 0x0, 0xad}, 0x10001, 0x0, 0x9})
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, r3, 0xb2}, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4})
r5 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r5, 0x0, 0x5, &(0x7f0000000000)="5d8ad1ae", 0x12)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000800)={&(0x7f0000000100)=@abs={0x0, 0x0, 0x0}, 0x8, &(0x7f0000000640)=[{0x0}, {0x0}, {0x0}, {0x0}, {&(0x7f0000000340)="9fe41bf9eb48ef101990d2d8a710e6506db2469d252596e982595ff848c71e9fcc5bcd8e52fbe68f7244fc8d172541eae5ce8d32389b5675ce948d9224a3244cfcf50e91c6a57b7c149278158b847311f15c18d8883dee", 0x57}, {&(0x7f00000003c0)="5c14183284c7f8fcec5774c5e5624416e9e392c87f33ee6bd20f68dfd57ee5cf8b8028543440ba4021ae72efb8d10a5e56", 0x31}, {&(0x7f0000000400)="b640302f7b0ecca07282051bce0fcc4e9b85adf6327197e10b531babb91144810fb9728f4338fd892e848acfc31520d7aa721ae597a835f92bd67ebd345acce60a547a0e155a483caed9ce74162b38b12180f427bdd9bc4af6b3e417de51235034ade40be9d89e5d8f0f0a589823af40054e6b28d4927487989c1eac1ec93d6a8b181ca8e1a47c6c019031a7c1f4d024fc453446ba648ee67cf8028838a71e90a6eec8f52aa790e1af25e23702e1e6c91577945916344462f357ceb607b7735fe4a4fee4ed8b17384f59a182c00acb97d18b80b8659d777e2eb6c3279ff612e5cf2e99670822e73db7b46b", 0xeb}, {&(0x7f0000000500)="092475278c9b146ebeead89e090cce6414e5ef8c20cbc925fd738db95d5e3dfbe46f1148cfd9b3e6376bc52cc0fcf9846db22504c4a30e20a9c992d1c2af1dddf3b4cd248fcf6dd91572b419fe7d02068ce9334d71080cba0122702d76", 0x5d}, {0x0}], 0x9, &(0x7f0000000700)=[@cred={0x20}, @cred={0x20}, @rights={0x28, 0xffff, 0x1, [0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff]}, @cred={0x20, 0xffff, 0x0, 0x0, 0x0, r3}, @rights={0x28, 0xffff, 0x1, [0xffffffffffffffff, 0xffffffffffffffff, r5, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff]}, @cred={0x20}], 0xd0, 0x9}, 0x8)
setuid(0x0)
syz_open_pts()


writev(0xffffffffffffff9c, &(0x7f00000004c0)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe2c63a56077123a276d3ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222fb7", 0x42}], 0x1)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='r\x00')
openat$vnd(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)


mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x412dff)
r0 = open(&(0x7f0000000100)='./bus\x00', 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x5ff})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
preadv(r0, &(0x7f00000000c0)=[{0x0}], 0x1, 0x0)


pipe(&(0x7f00000000c0)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
write(r1, &(0x7f00000002c0)="04", 0x1)
write(r0, &(0x7f0000000340), 0xd4e688a67930cd)
write(r1, &(0x7f0000000040), 0xfeea)
r2 = dup2(r0, r1)
write(r2, &(0x7f0000000040)='q', 0x1)
close(r1)
execve(0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x47}, 0x4000000000000004, 0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x0)
openat$vnd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
socket(0x0, 0x0, 0x0)
ioctl$VMM_IOC_READREGS(0xffffffffffffffff, 0xc028756b, 0x0)
ioctl$VMM_IOC_RUN(0xffffffffffffffff, 0xc0205602, 0x0)
mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f0000000040)={0x10, 0x0, [{&(0x7f0000fec000/0x14000)=nil, &(0x7f0000feb000/0x3000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000fee000/0x4000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ff6000/0x3000)=nil}, {&(0x7f0000ff0000/0x4000)=nil, &(0x7f0000fef000/0x3000)=nil}, {&(0x7f0000fec000/0x2000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000d56000/0x4000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000cdc000/0x4000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000feb000/0x1000)=nil, &(0x7f0000ff1000/0x2000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000fef000/0x4000)=nil}, {&(0x7f0000fed000/0x2000)=nil, &(0x7f0000fec000/0x3000)=nil}, {&(0x7f0000ff0000/0x1000)=nil, &(0x7f0000ff1000/0x4000)=nil}, {&(0x7f0000ff4000/0x3000)=nil, &(0x7f0000fef000/0x1000)=nil}, {&(0x7f0000ff6000/0x7000)=nil, &(0x7f0000c00000/0x400000)=nil}, {&(0x7f0000ce2000/0x1000)=nil, &(0x7f0000ded000/0x4000)=nil}, {&(0x7f0000e85000/0x4000)=nil, &(0x7f0000fe0000/0x1000)=nil}, {&(0x7f0000c4d000/0x1000)=nil, &(0x7f0000d14000/0x4000)=nil}], './file0\x00'})
r3 = open(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
ioctl$FIONREAD(r3, 0xc028698d, &(0x7f0000000080))


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000300)={0x2, &(0x7f00000000c0)=[{}, {0x0, 0xd5}]})
open(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
getpid()
socket(0x18, 0x2, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001600)={0x0, 0x0, 0x0, 0x0, &(0x7f0000002c40)=ANY=[@ANYBLOB="10000000ffff000001"], 0x10}, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4e}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x2000, 0x0, 0x37)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
r2 = dup2(r0, r1)
poll(&(0x7f0000000140)=[{r2, 0x245fc6872d8da9f4}, {r1, 0x4}], 0x2, 0x800000)
ioctl$TIOCSETD(r2, 0x8004741b, &(0x7f0000000900)=0x4)
writev(r1, &(0x7f0000000480)=[{&(0x7f0000000000)="e1e664fd79f3a16606548a7a1ab4010c8e3e03", 0x13}], 0x1)


mknod(&(0x7f00000000c0)='./file0\x00', 0x2000, 0x0)
r0 = open(&(0x7f00000002c0)='./file0\x00', 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
setreuid(0xee00, 0x0)
r1 = getuid()
setreuid(0x0, r1)
ioctl$TIOCSFLAGS(r0, 0x8004745c, &(0x7f0000000180))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x15}, {0x4d}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000200)=ANY=[])


getegid()
msgget$private(0x0, 0x0)
msgrcv(0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
msgctl$IPC_SET(0x0, 0x1, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
fcntl$setown(0xffffffffffffffff, 0x6, 0x0)
mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x412dff)
r0 = open(&(0x7f0000001700)='./file0\x00', 0x70e, 0x0)
write(r0, &(0x7f0000000000), 0x7)
clock_settime(0x100000000000000, &(0x7f0000000040))


mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x0)
setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0xee00, r0)
unveil(&(0x7f0000000280)='./file0\x00', &(0x7f0000000080)='x\x00')


writev(0xffffffffffffffff, &(0x7f00000012c0)=[{&(0x7f0000000100)="07bf850fd6d2691cb0cd2fc0a7fd31e85590e334bae49b3b6e3de857c12fd0c5d6b1cc70ec59768b7898e879332a9b9fcea8f793c469abb923da6cfe9b6d0adbeba1fe4a540a5d00f03ec945c47e8ded848f89e6db5fee11c2e3331dd15079f2c82247808aac362671211ed7f17b936892ffe8047d343010e32dbd5f686f5b3221a51d5a81ee6c371bc20cf630194b8ef4a86ba729bd945899a89ebc42552d2d2ab4dffc3b63a0f704f4aa1aee2c54d5b8e3712c3994983dcbce481fe5ef295b115a307c", 0xc4}], 0x1)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f00000001c0))


setrlimit(0x8, &(0x7f0000000040)={0x7, 0x9})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
setrlimit(0x0, &(0x7f0000000980)={0x0, 0x62})
writev(0xffffffffffffffff, &(0x7f0000000800)=[{&(0x7f0000000140)='4', 0x1}], 0x1)
writev(r0, &(0x7f0000000580)=[{&(0x7f0000000080)="6fcba96e64d77dfe77d06091c8341acb34f68c0a", 0x14}], 0x1)
readv(r1, &(0x7f0000000600), 0x10000000000002a5)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
pwritev(r0, &(0x7f0000000840)=[{&(0x7f00000009c0)="88f5051c6d680fcf347e", 0xa}], 0x1, 0x0)
execve(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{}, {}, {0x6, 0x0, 0x0, 0x85}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x0, 0x0)
getgid()
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000200)=[{0x3}, {0x15}, {0x8106}]})
syz_emit_ethernet(0x22, &(0x7f0000000300)=ANY=[])


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000002c0)=@file={0x0, './file1\x00'}, 0xa)
chdir(&(0x7f0000000240)='./file0\x00')
mkdir(&(0x7f00000001c0)='./file1\x00', 0x0)
chmod(&(0x7f00000000c0)='./file1\x00', 0x153)
setreuid(0x0, 0xee01)
rename(&(0x7f0000000040)='./file1\x00', &(0x7f0000000140)='./file0\x00')
msgget(0x1, 0x444)
socket$unix(0x1, 0x5, 0x0)
minherit(&(0x7f0000ffc000/0x1000)=nil, 0xffffffffdf003fff, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000040), 0x0)


r0 = socket(0x11, 0x3, 0x0)
symlink(&(0x7f0000000100)='./file0\x00', &(0x7f0000000140)='./file0\x00')
sendto$unix(r0, &(0x7f0000000400)="b1000504600000000000000007000000331c13fecea10500fef9ed06c72fd3357ae320b37b673039d2d236073705ae04be38164991f7accf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139bb9a70e41f78eb96a05672f4d335d223e7d029d6ba8af630037282102000000720f70c1f5a472c881ea6e69e0bb76d907c400000200361b1257aea8c500002002000000000000aabfba09001d89e001e2ffffffffff7f00ff0000000000000000", 0xb0, 0x400, 0x0, 0x0)
read(0xffffffffffffffff, &(0x7f0000000240)=""/226, 0xe2)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x1, 0x2, 0x0)
r2 = socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0xb, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
getpeername$unix(r1, &(0x7f0000000c40)=@file={0x0, ""/4089}, &(0x7f0000000200)=0xffb)
r3 = socket(0x18, 0x1, 0x0)
dup2(r2, r3)
syz_open_pts()
syz_open_pts()
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f00000000c0)={0x0, 0x1ff}, 0x10)
r4 = socket(0x18, 0x2, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
setsockopt(r4, 0x1000000029, 0x3f, &(0x7f0000000040), 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$TIOCOUTQ(0xffffffffffffffff, 0x40047473, 0x0)
syz_open_pts()
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r5 = openat$wsmouse(0xffffffffffffff9c, 0x0, 0x1, 0x0)
mkdir(&(0x7f00000003c0)='./file1\x00', 0x20)
ioctl$WSMOUSEIO_SETPARAMS(r5, 0x80105727, &(0x7f00000000c0)={&(0x7f0000000000)=[{}], 0x1})
r6 = socket(0x11, 0x3, 0x0)
sendto$unix(r6, &(0x7f0000000000)="b10005016000009f05000000070000007d9113fecea10500fef96ecfc72fd3357a068da3a5673039d2d236acf20b7804be38164991f7cccf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f45335c223e7d026ba8af630037282118000000720fd38bfbb770c1f5a872c881e2772ec5a10400000000000000361b1257aea8c5d0002012fbff0c230000880d6633c556ae9be371a3f8343712051eeab71d89000407000000800420000000", 0xb1, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
ioctl$TIOCCBRK(r0, 0x2000747a)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
getrlimit(0x4, &(0x7f00000002c0))
sysctl$kern(&(0x7f0000000300)={0x1, 0xb}, 0x2, &(0x7f0000000340), 0x0, 0x0, 0x0)
close(r0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r1, 0x80047460, &(0x7f00000000c0)=0x6)
writev(r0, &(0x7f00000004c0)=[{&(0x7f0000000100)="97"}], 0x1)
writev(r0, &(0x7f0000000080)=[{&(0x7f00000009c0)="f941a3733444576b14802158e256a7c16dc37b02eeb94800591b3877b0cde7017caf7d0d3b7541f5d48364442828d19d7685a70ba71fed3158848f9a68bd6f3352d64a21c612e6eaad50cb9e4c8b43773f5f9b43a8aa980dbfd9502b6a34ee4976ad67f2d3d6919c36634a9eed8cbe26d0f87d897cbc091fc32cb21b559dd035fbe6b7765fcef72ca9d31451d6007b61d4e89ec015c7ecf401e9e98cdf9c5c5b1351644720d29c24dd2e9e017f85a12141e44ba2f260339f24381d113c634d9918daec904b75eac711a04c56ee5d4a9149185e2437d8d58e31245fdc52a0f0dfac13288b27ef57616ba55dac691005180d8d67799b5bbee3f7666657b024d2fee10e5be80a28c57f67186765dbe2ea606b620102d062cfee03d1f9410fc4115a1b90c347d103042ea3505f7f900c1ef1be52100394308863e0c555972d3214a0cb62a40b73a050f43ee3bb16c0f3a3ba4853c8bac0678f2477be6abe93e886b17c0538854cd7db840c46c5e1aa86d276ed94148a3553a70a0465a8aba7a9cea676e42c9b8b76e2164ede57d979cc8d20072f410b409ac8363ca7c47c9c884daf9e47f02ffa48d4b8a196ca10432b6a16e55ff8235a3709ae6da6918513832f1b81d6f10d29931a84665eede5643098edd8177e0d201467927b9137aa22441a9bb15e9a290a7989e3121e6daf028920d7833e0d14fb6b504d230e988e6e9fd8b278e4737c7d5641d258a534be01ac889cf64a3766c19f4f3adce393c70fa0aca2d777a519cda3e2e8465eab78249be23596ecab815fb89f1f998c28d84bfa776ecbe80e7cf7a460e147c881a338f5f8cb4ba6d12822b73bb75d6b845f96acfb9cfbebc7fdff17d3a3a499174c153aaaf375f807273f94d8349f44be75ae91874f266ba1500076497b8e69a9d0d47947452b1df0d3ba78a83a9add79bf96e8ffe0f75250081e2685758608461008e0008c0e398b99da93559392f1c235443174e1c34d52ccfaebd34011b7447f12d1a90013fe5f6eca33b2ddb118794282356694d3908edddc1841116590e30eab9ea6ee834f1eb0f0f66d8bcdfcaa4d4b5ee43428e7862de797902d7bc21017130fc01a97c38665ddb0f5650a76b770214f45a176e3da83dbab6660db293a82255a32f6bb359cddf2a231140ca63afd18157b8f48bf78d271b71a0ac5f73992e9501285fc3261aad7b5875748ad2032c70bf3d9daa68fdb50e836a2d0c5d06041810c66fffded9860ce05d6759edb26112695c5833840d92b44c37b84fec34e82cd8345a1366f358088da2940e300d602e81913a7d02963730b6de71d56f43ab33aa34733bf0c1070ad4afd34f0c6d9f98e927d9146bfd770b51761da57d36cbb16a86275d8d78720a1f6d8a5ba63eb29e1771fe53f9aebe5ac4a01bc08f1f20f10566dc4159cce78a44e7db8290c7f96f84d4436747f19f8c4af0e22980ced78b574ca94200be064f146fdd30d47239b432a42f089d1b0f9f7355bc3f85b1ba0ba3c1eb9f4f0fb97433ee2f213d35cc740f5e354555fa6567c86443279553c8739ecfece55d4733ec1043e195d85a731c1028b696fafde001888e0fc7c6c21de50a7ea24110c507ba0221386638de000ee23e4dea416ba3b43b64c34211600c2f45b2bb22fb99f92ca635d08add70e49fa3b4e2dafb266dae06a21f2c28739ccfbb464ba78f94b1aafc3ca52a2b68be6aed79e33fabd0b284451ef964b3ddb14a4820776996dfe6c48eab6a699cd82fe4265cece1628d7fe691c85414e8b37647026a33cd51355638de6e4df36c888db0ef04dbf141ebaf5fd1ad485ff3a146097855b7ec10d5aac4e584100e4cd511fec963818e6ed06cc383158b5188c59f544433d4050f79be3abd4e6743d3bdd51064f10ae47d2cd13d854a373d6217ffa6d2e79337206509dc4075440ddc7a09b6c6e15e65483bb0bceef80002a7599b7f2db9a4ff0d58c8ff57e9357b3ec8e7023f21dcdfe94e7fce201fe3cc0e5b23a33e4de1a7a82085d6c57c3f26f1e2f153d84a4eb2a012b56add52954413fc05e5b7f38818e59891c6238b2cf12f44f44bfd58e0a49534a33515293902302f70cf315d69c21921dda2e1ac78e72724e02a96a063fb673984230c46eb569e84f4f828807043d4ca960d9935d6941258e207e84cd7366388660d075043bd3707bc27e56240dcc258e6840fa4ec54cd933a3f21417a13d987d10c4b03299d4518867c74e0b10f06d0da7c310d6121803b53a6c63287ddb3bdc472dac91ee66304aeea77313254a164a7261560dcd7f56b87848b264eeb38cfe154dd329ec4dcb3f5610370236f235e7ad51ccc28e484d10dce134cc2320a0ce83c451418bb2cf8c48ad42ab12bef92c2b3ac4f3110f1dacf2301638347921d984e4b0893c48aca668023c52fabf9e3fec5bebee87dae9708261e7e8a7316d5aa1a443342e3b33d2a0eba9f9a01799cfea5664d8f71d0403e52fd7f37bb2dccd61907a4fe8a47235425dd51d35f9560563a68dcc1b8c7731498bd0b5b7b6a32689cafb851ff07af189d4e23e466db15336249bc7a6f15e572a9a1d8a1ecad74ed3ba2f91990228edd725f98ab00f3b05c6fa7b56cc665650cbcd961c2239c86c77c44851259d5068266010a0fd90309f6a2e128bc7b7ee0b58def5332844050b488c35db0c0794b64ffda33026fb0d384d6e8fd40eba9eeb2cec494fe823f8011fdea981db1aa14255201f751d1bbc847958abc57fc690219398bdf0f3e58b0d047fde37ca328e181a21aa49ab3acabe9d8c39f16704e84713d61722a77d7baa0edbdcec19fc73a0625efb36d97cbdfd4f20379ae81bc9a4f6920976f835ff96b1eb55a099ddcf3f36c90ef16efebb3a3ab8536dbe07d48772c602c0483724adb338cfe20e5b4dd68dc8c352441040bf88c17dca971440bfb05e63ed889ab7e5a488b82beba9e96b4a3f71b9acb1e8b17ced81bd030c512a97422c394124a87e358a6830bfb4b6a6d253d49a5a6ee228450b21b1934a2b71e7aa2e840636179170df324e5f3832b18aaf0202ff4ed36d4b43dafa28e53a38a96414456ebe791dfdfda128a85f4206b27bf85a4056309fc430b5bc9adfd0dcafb9489c5059f703b226ea9a2baf107ec907abe33b0930fd6e5b8cabb720eb0760cd8698fc3739e00b71b6253e32433f584ad84d14dc6428fbda9e6a34660d5082972b1f56794b41c2a061c34cb8a71251383e1b35f1612ad176df66b0b78ac2704d02436b8fd7401feb4290b56aae3c8aae19fc80e67711089e2756bcf8cccf3774b16b83b26ae264ccf6ac06cbe7e0ab5a5703042269a13c0961af48efaccf9b2233ec6c887f4a42f73d6962754193886c5f613397290b24c25784bd37e50032a3088b51fd956cf3409041a20e3cb546c9e974f1b8894db50ba7d840be905c4ca73921cdd79ca6277bd474fd50d2125ea3efc555aac4401778546d8fffb00ed349981a9308c2a7640d81da5aeb47f63dc059462d81f96231c5b2b2511abb695dbe3ad42740157889a43698b24cd63a0404feac940a70874e9a45c4dfdd1d702ba19ac0710cde8406a55c7984d6a96270a20c483a12fec49a6d66e089ddda3aab0e293100c0ff66a9afada9993fcfa5e31a96ad7e354e75cc58dca9949eb2c113a1d1c079fb9185ece58b405330992e2d33aa8ae741afba029c66dfc7cf70dd73b4d14f3804b81a8d91aafb8d182ee399a913a2ea27c3b9029565fc7136fdb45a8a2da7995844dc43f3a566df0a0d72c9f5f54d9c91bd1e2d700b2855e2cded13a9b7710ea89e2ed66d3793812929db9cbd61e6d2b6891894a939d8804e7a69548adc30e9fd28f9cb80a8132145a58261a8e3f289753108b386be1525865c2ea16c44607d44126942631412ea83cc45195fc03a22faae61bb649f5f7eed85809f194a6c6b0d286d84efc3ed2422e3d0eb24fbda17a1aca3b4bc62f65855b3591bb93f5da23116b1eb840792909a5ba34256f2653b30be6dc1365b65ca8446307269b393e4b8155ae6827e1bdbd8dd0a0cebefe69dde238c608b4fbfa761801bc6585200043282715b645fb3986ee2c216b1d00641992e89906cf85ab217da9e309bec7f31c268e2a544261a671f7387637386ad8e106a4d7b6a4a615eabda45e67b6179ff077421ea241c11f43cc278486aacbc947849da38371d80822ef8c4fdcfa9cd6e5200cb10d1139c4ec2e202d6b4ec10c813094cbb2205664a0746d8256a3435ef1ee2244844c76023613ba2f88be035190792c775ea3c54d07be018ed53818e11bea0d6dc90d99caf5000e3238ede9f162f4e3fe6d85c52edd430b719833f8ee3d94911b03696bce1a04bf01975006cde9b9448769e3659ac4b04b9617c2b19a650a94712f8cf0db2a1bf4b357016479d543f63f42b475df8f84809aca6ac60f37c632a32bc04d49650c4f1bed2a18c1303f71cdfc245e89072a98dd140e2d1c740ffd8393e16919982bdbeb9c7486bb48037343a81edbbb91ae086293434ffa81f96563206ab9e92f7da0778910649baaec276bd5003e3e1651a362d19bae4c04c92d76be232aa98b111916e117194f5320c026175cd84d24b763c8d045b85690cf04c406188e57058790fce1bb8d1c7ad3d0f95546d1d42f04f4e4baffcefddb8366835ac7dbd7dfa567cd54e3954449ad73480156959eb2aba556dffbfc89c3f2819c08fec7d9893579260fd76c80414e1fc976e4bbc433dcfed5c5dd67db1f005d6ab8bb021dd79901d1822b64d1455b165acb1574dfb37215e647fdd8155c5c2c453b8196b80dcc9342da781c3029f1f17e695b35d2949aae0aafd2f44be29b5e3a1e754d583ec15ebe4c3a51d0285aec10f94a4e116e0b32f276c5a2d23cada1eb7b99dc9939625ed72181ad2deccacf6e282c652ff1213a060ca910a7c3d201dda1c049c52c32731e7fd1ffc7eeed62344633ce4c27350422d5b90a3575d14b147889035a446d3d9b013b1ea95d35a6bb78bc2e6914a9d608a2f95b7d83bce2734b1656159056997b9f76c906727926ea0522d00eb76be544c7f1ca7a64566e80693b1b71ccd2d9109591088dba58be43bc5f53784de6b7cfd943266e7e6382a405fcf6e1e7ee0c8783d93f08443b87ac0e8df809cbd917e709ab0c80cb42b8df6854e079dfb1b44ed421ef3b0a305a89daf0a0640b194e2b86c36649d4cb1cf4e7c5294fd753ac355aa6a0de052712c81d740012087a5776810dc4b6eaccdc0b9dea25682d52be89f3eb4f882622ece49fe1696c2dca0d1931e790d4e41f6dfb3e6575da2c304d1730257a50e745affe01f05940efc51f871cacfe73c7ec710615af5d6677f310a0975c645238f924f333543494f85ccfd0ee5135a092b2a8c72622955de6b5215f190784f669bb28c78389546c6743b97b074dc", 0xeff}], 0x1)
ioctl$WSKBDIO_SETBACKLIGHT(0xffffffffffffffff, 0x800c5712, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
sendmmsg(0xffffffffffffffff, &(0x7f00000007c0)={&(0x7f0000000780)={0x0, 0x0, &(0x7f0000000100), 0x0, 0x0}}, 0x10, 0x0)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x3a, &(0x7f0000000400)={@broadcast, @broadcast, [], {@ipv4={0x800, {{0xb, 0x4, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x0, 0x0, @empty, @remote={0xac, 0x14, 0x0}, {[@generic={0x88, 0x2}, @timestamp={0x44, 0x14, 0xb, 0x1, 0x0, [{}, {[], 0x1ff}, {[@loopback]}]}]}}}}}})
open(&(0x7f0000000180)='./file0\x00', 0x70e, 0x0)
r2 = syz_open_pts()
ioctl$TIOCSTAT(r2, 0x20007465, 0x0)
ioctl$TIOCSETD(r2, 0x8004741b, &(0x7f0000000000)=0x7)
socket(0x0, 0x0, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
link(&(0x7f0000000140)='.\x00', 0x0)
r3 = socket(0x18, 0x1, 0x0)
getsockname$inet(r3, &(0x7f00000000c0), &(0x7f0000000600)=0xfffffc6f)


setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETAF(r1, 0x802c7416, &(0x7f00000002c0)={0x978b, 0x0, 0x3, 0x0, "bb08000110f167591050c30abfa522f6919800"})
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)
execve(0x0, 0x0, 0x0)


mkdir(&(0x7f0000000300)='./file0\x00', 0x0)
rename(&(0x7f0000000200)='.\x00', &(0x7f0000000240)='./file0/file0\x00')


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x64}, {0x20}, {0x6}]})
syz_emit_ethernet(0x62, &(0x7f00000006c0)=ANY=[])


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000004c0), 0x10202, 0x0)
writev(r0, &(0x7f0000000240)=[{&(0x7f0000000100)="058c4cc154b5895edf170affb44c37b4e96eb0aa265b33a650172f5b1d2760b1cc8ab19c57387cc77e393974c9e52e4f40f7def3d6a5b18dee9efc7d3d5c7c1cb4c8b4259a21c752094c99e4c4788dec400d2be5113d38b0c266176020113ab90f1e7cf312d450bf0ddb515e6b5278da6da791f6a0eddac871ffc8611d5b03f73e65cefad4259312c4ef3b5c5ab9957ff7daf425c4b50a764b352c491ba8fccc7f68c9f2eb48e41976b073c9248ec6bd13e7a8d063d06f02b42a5d611c8e008dfce53e9a98b2a07ff096fc4736719a167c1e9d95429b6f4e", 0xd8}], 0x1)
sysctl$net_inet_ip(0x0, 0x0, &(0x7f0000000100)="d7a8aac106fa1bee91c724b89283c1477dab85e783af4189a1eaf5f6e8251b1147b330f604ff639b9acd6202c9d8b1aef98ce6eefe", 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000140)=ANY=[@ANYBLOB="00000000000000000000000008060001080006040008ffffffffffff7f00000100000000e3cd60de0066d661a35b000000007fff42f05fee55"])
msgctl$IPC_STAT(0x0, 0x2, &(0x7f0000000000)=""/241)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
sendto$inet(0xffffffffffffffff, &(0x7f00000000c0)="6c25a03ae7b27b4e7fc0924a22334b9b619f09f993c214bf34de94ee6f878793a443c48892901b940ff2189ae976bd635aa66dd55818d1ca20a7f88c2ad799df41ea701f32e36ab928f0ea3b00ddc5613e3590c04b342a5ec356d4f406e612653d7338e1b59ec0f00de4b65b3f18", 0x6e, 0xab7930ffa8ff6f6d, 0x0, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r2, 0x8080691a, &(0x7f0000000100))


r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x33, &(0x7f0000000140)="5ab7776a", 0x4)
shutdown(r0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r1 = socket(0x18, 0x3, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r1, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x18, 0x1, 0x0)
close(r2)
r3 = socket(0x18, 0x3, 0x3a)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r3, &(0x7f0000000100)="00003226a4a9000064e7c803d2a423734333a4dd", 0x14)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000680)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f00000000c0)=[{0x61}, {0x87}, {0x26}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


setrlimit(0x8, &(0x7f0000000040)={0x7, 0x50})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETAW(r1, 0x802c7415, &(0x7f0000000000)={0x29f57365, 0x0, 0x1f, 0xffffffff, "8b644cf1a3f4d3c900000000000000e81f3e6323"})
writev(r0, &(0x7f0000000f40)=[{&(0x7f0000001c00)="b111bec04cae7c7152139c94fc29135885c2b7b1126044c8ec888bb05b00f17dc4a24377c995518a3ead2b2c9078b262945bb9b4554847171f7334a23d1e34d3a2ab8f6f8f6ec6239a564210c690496e1a7c9d8b4b5b52cf10e44b1a9910b266320e7411197c1124d4fac6a4600673ca934eaa4b96dc5f4f1681b2f1b615a30f0979f80f8f9500247a5269642b9019da525b124ec3012cdd35ebb1b58a36bd9942fd9ecf632a7107c7d0a34857fe50e43237f827ee39c903829b68572bb4c373897bbab6be503e86eb3f360d69cbd82f5b99ca60f017506d2ba053ab48c88a94b145399f3b2f1de8ed5d93d8ffc28aa4141c8e99b8f1b0f1963e61a762900a433c6fbb64a350b868d62f3aa8d5efdde5d7051f38ca4c0cb5c3d0da2ceccdc6e57355f42e73744666b8fa01e572800573575d467b5dbe5ca6fc6f7eab1d77ad732fd568e2f8c59c2b1508749a55bf04bdddfd5c2dcb5f5c405c66ad224ca9d6fecc2bf8d7fe1e33ed765b200e1422e4f1599dff9595cfbd55afb3a54aebbe29624cfc769900baf957d3cadfe1be7e605dcd66e7c9b4f7be85d91f20830e296eb31e721e2cbee8d7bd120a20c0e540ef6fdc68f5bd7bd84557774db6730f00b1d786b2491b94332f1a96e2a622ad4a930697eac1d43337214c3973e462595d0b63e05ddec77a72b290093f3b64d2dee99f0a76454375616f3f5e020477c55f798e27a3ce67506563ab1a0dda4c5ae7243b4922e87b4d2bf98826567318a5d79bbc9bd77a2f0e57376bc85226e5e50f97f26e6ad213becc95a282f963e24aa12693e55054f8406228cd40c6768fab639abc9bc5e3d42e811b5ee33930a45444c4b5cf9cbda8db48d1af54f8faaa4c5f025bc084dd0b3742e72075020b7c0f069fa9939d15c82be759fc02dae035c39d21bebd06b1cbe247d119c9076d1c00f35102095dd676377b1a59dc1c2fe6135897882fbcfd6a8811b7e7a25e25b9d197a6217d517a0f398cfc19513ef1177982cb442531fedff8f382469b49d35d3751599c8090fa5169345c9b9fa3d710f373375ebff2aca2c8a750e77cbaf4459a8f782c9da945a96de669360f024a5c761544acc51fcbbda11a68e547826506001d5aaeb603d9a6cc8cb1e4c85d64dce3", 0x32d}], 0x1)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
shmctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0xffffffffffffffff, 0x140}})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x3a)
r2 = dup2(r0, r1)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
r3 = socket(0x18, 0x2, 0x0)
r4 = dup2(r1, r3)
write(r4, &(0x7f0000000140)="0c398c088c93a3ccf8ea23045b766cd41e7991c7fbd4eaa11603876cbaea89c77c07e049fb603ae46d28a7874d5daac09ada48d35448d4abcd8cca749991285c7ade9b964cbbef22a7a5f185a30291308fbe3ba6eb39d2595d7cc05bebfe3be3a6c8ee37087d3bd3544f4d18a3437ea5d98d17e61df56e653e11a875d3d654c1340fc4afacf796d0e091197693e154fcdff4c0958ca215c0e71c0daa1dd071a84ee075a23d083fb92efa15651e955d4b3d3bd736830185328b974f43f553eb18e269386103f0a3fb65f1fae83a343b20f2e6aa4c6be16925f28c57670152e59556845e76ce7fba34e6cc3356b14920b0e6735b72185823a25ec04fe0902602a730ee377947871b749cc08ac498f347ae25b8190ea951a205d267bfa364cc575c1dc55eb08b1758c4e7d5e557a57ae84f8b0fb79b81157f31bb41368508abf76a02bada29c17e952d6efbb1fda650cb19d1eaf3edca69ff972ee63504c725bdd71a5bbffd9b416671dbcfa5572db125939132bb9d98e45cf827da0021e1c424c379259afac6efcd03c54eff682f75a15e24f65e6e9b392c0ceb8a279d3a4d67328fed41c4d1f648651aa4c2443452d2735a33c9d00d23fc1f18c7ba5c66f173c5715687380f43d4ed71542a4e0e7f49b7eec632a00e270e1efed20e6a17d082bbc07a0c00ce376e78f5d9557e20de23727282b89562a418c81a37d4d373f907ddb80193ee013445c30a2b82b2bbac6675a3956b68f65054a3d220327c70ef33eec994c230d9c6f90b8d7bb187eded0dda81fc8382878398d94789e28317ca71607381e7bcc9f305d764762f95b1446ff964e893a4b71bd6af1603320fd9aa65d7535ef37f816e35f78252eb917a33f9db51ac22bad185e27c75633c5f42b778a19b727bb7fed3c8c920ce624d7e8b85be9ec1f9ee439b9a9a8f90c398f957d21c3dc08daa298b5bd4b2dc0fcaa0cc7ef7f0cb932cfda350a5e2daffad436f36793b496bd14e48f7506e66df5e9fe4964c53893da52d7da913fe1ac9fd2563407ec7b375df97a5f7efb01849a14b6bcc62b0800f99a2e3f755940384724f92867252e824f59ea25d46c32f9df369d1454519903717f08667d15a5a6f7706a7c448dfdbf66e58994cba95cc086cb0ac1026d474e02d1243ebeb98e5e3b2d9d282635ee072520242b77ea67adf93cd377b58d3cef40015ec966497b457c0bcb3eb9fe79c62da2bd2907270a0c8ca0321598b906c6c9dd12373085f41f64f5dd29017a1b05caed12a4aca525abae2da2b0603b1530dfdcc7e04840b57546af976f6877878ebbb6dd8c90995418d6ae9c471a30630ad581428228abae8e0d7f05da49852afc82f6e63152b7587322c5f6803c8abf7e704b6aa401e2b6e87c122c3a80f72ed840394fb816f61fe82f872c7c1657525211119c4b1e279d7b684efb39d5c50f144e18fea4912fa5747b8c52205e0a51bb831189bc1760e7d8c03e4dc97b79ba0c8475ac474d92584a97ef7505fb20f117c059667b74a8da3361f3d3367d0a0e175ae6480bbe1c5ed630490fd44f5e51775d5f71a0ad1b67a4e538dd514345966bdf6345ab0a1901a67126c22298f345205582a80766293a21c39b9370f231f529d4663ca2e008310c8e33c6aac12142433e3316903915334ded1ac4c8b79859810d6f0d25568fb3aed05ae686f5b700c1ca2d74388df0dc85167144e9cc501fab02fc64a20a4dca6795b0be938f644756a9ab551e08b8eb1e774e3d7099e3a27aee5d77f7360ec8dbc064ca78146d16bdcc79e2f9511ff24977c5044e3fe2502cf4a9c749864be89a257506eab8e27e31e4285e0902bedfa058a28fb9c412a10ed07790fec30dceedb2be77b29eb40d845f5c503d773f3ee82cee137ce266585f114aa8d566863d645828a0a961851af7a17925cd650e4495fb396166f96dd0a0c14775561ce01536db824d21b2dc4917eae7d9c2b0afbff916dba316b086b2bc15df2763a0b2e9b0fcde5ca5de398ff7faf894fb6c6e667c2a2b5bfce0bf286773625e8e8a90c33c8ac0827a45f48799925c38736ed1d52fba9b99a0857f7d2e6487567b6f87fd69255896dd92c316e978152395280e5d3f5d72e9b01daa6a1233bc4ff1b32e54893c29feadbbaf148247a64db037eb741f8b67c422ffabebd2749a067382b538d8e8041c2e8ea2fd35be473bfff534c9f6192b4f506fe3df0138da69b0b05b3202664f22cc347381115a3b1ba2e179e63affeee8f8a9cd9c5dbd9f14672397176e7f495a39d444b86970ad85c6fd0401a5b34362866e60a96910a02db6ed1a72c0225d69cf715b2963c25af39cb6f4b8d565295bc8ab6ce8cd8d873f175518fa47d88bd19e37a1ae73057c5aac1c8ae65bb4c014d9bfdc50daee43044307bb34a6b539ff9b4b422675c6e5030ba9e245b8655811d5cfdc6066fcd7f7328c607846567cce3293daafc2b11c8ecc9499a9c104c8c9891f97eceb4fa4c813ad690aeb63241daad15fed98555a5c8916e67c31a400e2b646053011e154db944feb9a546a71eec9da006db5ffe8d284646f4a4f5a3cfde87eae4df02212e9463dcf9c5fb6c7cedeb4b74a78ac8de862699b79b940a3cfccbfe6fe7f7ec23251a1ba55b6afca670d65c08b58c7a088658725e08f3383979a2c3471bd1347f70c02e5ae271aba2e1b68eca29d916ea92075ccbacb62b2072dd2226a09db6", 0x784)


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, 0x0)
r0 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r0, 0x0)
r1 = socket(0x11, 0x3, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1002, &(0x7f0000000000), 0x4)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x1f}})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)={0x0, 0x7fffffff})
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000140)={0x0, 0xfffffffffffffffb})
r0 = kqueue()
kevent(r0, &(0x7f00000000c0), 0x7, 0x0, 0x80000001, 0x0)
close(r0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x1d}, {0x34, 0x0, 0x0, 0x800008}, {0xa186}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


sysctl$vm(0x0, 0x0, &(0x7f0000000040)="c06d154be3aee5f8787f8b9cda7554335b763bb5deea5ccecb4d1b57a9f6fa18e47fc7b119db587e58811e666e84a806495b45c36164bd5b135280243ed0a01466056e93082876ba33", 0x0, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ff7000/0x3000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000604000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000287000/0x1000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000691000/0x2000)=nil, &(0x7f0000ff8000/0x4000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000743000/0x13000)=nil}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil}], './file0\x00'})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = socket(0x800000018, 0x1, 0x0)
ioctl$PCIOCGETROM(0xffffffffffffffff, 0xc0107005, &(0x7f0000000080)={{}, 0x0, &(0x7f0000000040)})
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
writev(r0, &(0x7f0000000140)=[{0x0}], 0x1)


open$dir(&(0x7f0000000b80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x200, 0x0)
r0 = open$dir(&(0x7f0000000280)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000300)='./file0\x00', r0, &(0x7f0000000c80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f0000000dc0)='./file0\x00', r0, &(0x7f0000000ec0)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
r1 = openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x8981, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r1, 0x80105728, &(0x7f0000000100)={&(0x7f0000000080)=[{0x1}, {}], 0x2})
symlinkat(&(0x7f00000000c0)='./file0\x00', r0, &(0x7f00000001c0)='./file0\x00')
open$dir(&(0x7f0000000040)='./file1\x00', 0x200, 0x0)
lstat(&(0x7f0000000140)='./file1\x00', &(0x7f0000000200))
mkdirat(r0, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
symlinkat(&(0x7f0000000040)='./file0\x00', r0, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000980)='./file1\x00', &(0x7f0000000100)='./file0\x00')


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)='\t\x00\x00\x00', 0x4)
r1 = dup(r0)
setsockopt(r1, 0x1000000000029, 0xd, &(0x7f0000000000), 0x0)


sysctl$hw(&(0x7f00000002c0)={0x7, 0xf}, 0x2, &(0x7f00000005c0)="f0", &(0x7f00000000c0)=0x1, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
socket$inet(0x2, 0x2, 0x0)
socket(0x1, 0x4, 0xff)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
setrlimit(0x0, 0x0)
syz_open_pts()
open(0x0, 0x0, 0x124)
r0 = socket(0x0, 0x5, 0x7b)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
syz_emit_ethernet(0x138, 0x0)
r1 = msgget$private(0x0, 0x0)
pipe2(0x0, 0x0)
msgsnd(0x0, &(0x7f0000000300)=ANY=[@ANYRES16=r0], 0x1f, 0x0)
msgsnd(r1, &(0x7f0000000240)=ANY=[@ANYRES32], 0x401, 0x0)
msgsnd(r1, 0x0, 0x401, 0x0)
msgrcv(r1, &(0x7f0000000400)={0x0, ""/137}, 0x91, 0x2, 0x0)
msgctl$IPC_RMID(r1, 0x0)
syz_emit_ethernet(0x3e, &(0x7f0000000140)=ANY=[])
pread(0xffffffffffffffff, &(0x7f0000000040), 0x0, 0x100000000)
mkdir(&(0x7f0000000280)='./file0\x00', 0x80)
chroot(&(0x7f0000000340)='./file0\x00')
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r2=>0xffffffffffffffff})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x1, 0x0)
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f00000001c0), &(0x7f0000000080)=0xc)
openat$bpf(0xffffffffffffff9c, 0x0, 0x108, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2977, 0x0)
pipe(0x0)
write(0xffffffffffffffff, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000240)=[{0x5}, {0x7}, {0x6}]})
syz_emit_ethernet(0x76, &(0x7f0000000080)=ANY=[])


open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7949)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
write(r0, &(0x7f0000000340)="6eceffd4360ba29cc622a8f4b71a392535441d7d2bdbbe4c0549cd985796236ab486c44d0d76ae05e1c8b751eabcc82fc9875275ac91142361fbb19a1372da15a7", 0xffffffffffffff2d)
writev(r0, &(0x7f00000002c0)=[{&(0x7f0000000240)="20b4e965ae10884a02c074a7e8d4cd340a9c2afade34b407d7273694f5c1d674c53022572140a6d714", 0x29}, {&(0x7f00000014c0)="20a95ca8769c0a", 0x7}], 0x2)
socket(0x0, 0x0, 0x0)
ioctl$VNDIOCSET(0xffffffffffffffff, 0x41946465, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r1 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x10, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x1)
r2 = socket(0x18, 0x1, 0x0)
setsockopt(r2, 0x1000000029, 0x3e, &(0x7f0000000000)="5ab7776a", 0x4)
r3 = socket$inet6(0x18, 0x3, 0x0)
setitimer(0x2, &(0x7f0000000300)={{}, {0x0, 0x10001}}, 0x0)
getsockopt(r3, 0x29, 0x3e, 0x0, 0x0)
ioctl$FIONBIO(r1, 0x8004667e, &(0x7f0000001180))
mprotect(&(0x7f0000ffb000/0x1000)=nil, 0x1000, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r5, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x4d}, {0x54}, {0x6}]})
syz_emit_ethernet(0x1b, &(0x7f0000000000)=ANY=[])
sysctl$kern(&(0x7f0000000040)={0x1, 0x4d}, 0x2, &(0x7f0000000100), 0x0, 0x0, 0x0)
r6 = socket(0x18, 0x3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r7 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r7, 0xc0106924, &(0x7f00000001c0))
ioctl$FIONREAD(r6, 0xc1206951, &(0x7f0000000100))
ioctl$BIOCSETF(r4, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000140)=[{0x25}, {0x50}, {0x812e}]})
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff}, 0x0, 0x0, 0x4})


mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000080)='./file0/control\x00', 0x0)
mkdir(&(0x7f0000000040)='./file0/control/file1\x00', 0x0)
rename(&(0x7f0000000500)='./file0/control/file1\x00', &(0x7f0000000540)='./file1\x00')
chdir(&(0x7f0000000100)='./file1\x00')
setreuid(0xee00, 0x0)
r0 = getuid()
mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f00000000c0)='./file0\x00', 0x21e)
chdir(&(0x7f0000000140)='./file0\x00')
setreuid(0x0, r0)
unveil(&(0x7f0000000040)='.\x00', &(0x7f0000000080)='c\x00')


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000580)={0x3, &(0x7f0000000540)=[{0x2d}, {0x24}, {0x6}]})
syz_emit_ethernet(0x7e, &(0x7f0000000280)=ANY=[])


faccessat(0xffffffffffffffff, &(0x7f0000000000)='./bus\x00', 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x4001, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
r2 = socket(0x2, 0x1, 0x0)
connect$unix(r2, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r1, 0xffff, 0x1023, &(0x7f0000000080), 0x4)
shutdown(r1, 0x1)
listen(r1, 0x0)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000180)="b1000504600000000000000007000000331c13fecea10500fef9ed061ddd1efb7ae320b37b673039d2d236073705ae04be38164991f7b85143222b297be1aa5b236deb51e2f0ac3ebbc257699a5f139b672f4d335d223e7d029d6ba8af630037282102000000720f70c1f5a472c881ea6e69e0bb76d907a900000200361b1257aea8c5000020020000000000008abfba090008efffffffffff3512b132ae037503682ce371a300803712051eadb71d89e0", 0xb1, 0x0, 0x0, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
socket(0x18, 0x2, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f00000002c0)=""/46, 0x2e}], 0x1)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1800000029"], 0x3e}, 0x0)
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
setsockopt$inet_opts(r0, 0x0, 0x200000000000b, &(0x7f0000000080), 0x0)


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
open(&(0x7f0000000140)='./file0\x00', 0x804, 0x0)
select(0x7, &(0x7f00000002c0)={0xfffffffffffffffc}, 0x0, 0x0, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)


sysctl$kern(&(0x7f0000000080)={0x1, 0x4f}, 0x4000000000000004, 0x0, 0x0, 0x0, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x138, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x4, &(0x7f00000000c0)=[{0x7, 0x8, 0x3, 0x8}, {0x2, 0x1, 0x1f, 0x9}, {0x5, 0x3, 0x8, 0x9}, {0x5, 0x9, 0x20, 0x10001}]})
write(0xffffffffffffffff, 0x0, 0x0)
r1 = accept(0xffffffffffffffff, &(0x7f0000000140)=@in6, &(0x7f0000000180)=0xc)
mmap(&(0x7f0000ffc000/0x4000)=nil, 0x4000, 0x4, 0x1010, r1, 0x9)
r2 = syz_open_pts()
ioctl$TIOCGWINSZ(r2, 0x40087468, &(0x7f0000000a80))
openat$bpf(0xffffffffffffff9c, 0x0, 0x100c0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r3 = syz_open_pts()
ioctl$TIOCSETD(r3, 0x8004741b, &(0x7f0000000000)=0x7)
ioctl$TIOCSETD(r3, 0x8004741b, &(0x7f0000000080))


sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
getpeername(0xffffffffffffffff, 0x0, 0x0)
getppid()
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, &(0x7f00000001c0))
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
close(r0)
r1 = socket(0x18, 0x2, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f0000000240)=""/61, 0x3d}], 0x1)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmsg(r0, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1400000029"], 0x3e}, 0x0)


r0 = kqueue()
ioctl$FIOASYNC(r0, 0x8004667d, &(0x7f00000001c0))


syz_emit_ethernet(0x42, &(0x7f0000000140)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa0800450000340000000000009078ac1400bbac1400aa4e204e20", @ANYRES32=0x41424344, @ANYRES32=0x41424344, @ANYBLOB="8000000090780000050a0000000900000001000094442547f314e2546f476d18dffd68f3280841f329a90f13f0b2aee8ddf34ae117c63fe5c5747ffc39568fdee5558960dfb93cba1292864952e13b6b535e187310a64ccf2593139aa8ffd2a4a3eb4a5d45c2dc107fd113af7a"])
syz_emit_ethernet(0x126f, &(0x7f00000000c0)=ANY=[@ANYBLOB="aaaaaaaaaaaa00000000000086dd609ded1a12390000c4a4e3434e58d025a6a8a81cf312b8befe8000000000000000000000000000aa00030000000000000101000101000401000401000103000000000100010200000000c7ab6f1eba08bf03d1805fce0ef2ab82f4a065245eccda108bec7cb23f632c993265a4cefeb77b1406d562a47d4b0054943553278b519ed107f62b5c352f8e68d83c1fd85b8e1083556d7fa2fc09a3e823fa940de6ef1b18ddb2a2dba0d2d9c1b44b20ed3a932a2c47f4f4d3e34ea1b67a607001a4541a87d5d347b5049b3444dc2b7abe3499079a5701e88493acb2eb1808e8b1f74311083f93341607915aa46325934e81b672d809cb6bc5f3d64480ba4db4432a67c2548e259fe7831f7c6dfe"])
sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f00000001c0)="55f8f5782087a072a82ec35f78d14780f518", 0x12)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc1206949, &(0x7f00000001c0))


socketpair$unix(0x1, 0x0, 0x0, &(0x7f00000001c0))
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x0, 0x0})
open(&(0x7f0000000180)='./file0\x00', 0x80000000000206, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x4, 0x538, 0x0)
chmod(&(0x7f0000000180)='./file0\x00', 0x23f)
setuid(0xee01)
ktrace(&(0x7f0000000040)='./file0\x00', 0x2, 0x0, 0x0)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000180), 0x1, 0x0)
r1 = dup2(r0, r0)
ioctl$WSKBDIO_GETMAP(r1, 0x80047476, &(0x7f0000000100)={0x0, 0x0})


r0 = socket$inet(0x2, 0x2, 0x0)
pipe(&(0x7f00000000c0))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
setsockopt$inet_opts(r0, 0x0, 0x1, &(0x7f0000000240)="ea000001", 0x4)
getsockopt$inet_opts(r0, 0x0, 0x1, 0x0, 0x0)


sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504000004000000000007", 0xd, 0x0, 0x0, 0x0)
r0 = socket(0x11, 0x3, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
sendto$unix(r0, &(0x7f0000000000)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)


r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSTAT(0xffffffffffffffff, 0x20007465, 0x0)
recvmmsg(r0, &(0x7f0000000340)={&(0x7f0000000300)={&(0x7f0000000140)=@in, 0xc, &(0x7f0000000240)=[{&(0x7f0000000180)=""/170, 0xaa}], 0x1, &(0x7f0000000280)=""/119, 0x77}, 0x1}, 0x10, 0x841, 0x0)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f00000003c0), 0x400, 0x0)
r2 = socket(0x0, 0x2, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000140)=[{0x2c}, {0x5}, {0x416}]})
r4 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
r5 = getpgid(0x0)
fcntl$setown(r4, 0x6, r5)
getpgid(0x0)
getsockopt$SO_PEERCRED(r2, 0xffff, 0x1022, &(0x7f0000001b00), 0xc)
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f0000001b40), 0xc)
sendmsg$unix(r0, 0x0, 0xb)
syz_emit_ethernet(0x4e, 0x0)
setsockopt(r0, 0xffff, 0x8, &(0x7f0000000400)="d8b5535e5de8bb88242dbfeeae38bc201973402e6f6c57f762756452ef7d1220e9453469ebd3d182ebcb1168db8954cfcc8616491907b6d30f8b932072b6e1343e4f07af77d78b1a0029f8d3e5f590f4b1c7e5d1d2c3f548", 0x58)
ioctl$VMM_IOC_INFO(r1, 0xc0185603, &(0x7f0000000000)={0x97, 0x0, &(0x7f0000000040)=""/151})
r6 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000800), 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r6, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
syz_emit_ethernet(0x20, &(0x7f0000000480)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaaaaaa88e7"])
ioctl$BIOCPROMISC(r6, 0x20004269)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x84000000000000})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x1, 0x0)
close(r1)
r2 = socket(0x18, 0x2, 0x0)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
connect(r0, &(0x7f0000000040)=@un=@file={0x0, './file0\x00'}, 0xa)
sendmsg$unix(r0, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


syz_emit_ethernet(0x3a, &(0x7f0000000380)={@local, @random="2a152a26f956", [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x0, 0x0, @multicast1, @multicast1, {[@noop, @rr={0x7, 0x3, 0x7a}]}}, @tcp={{0x0, 0x0, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000040)=[{0x5c}, {0x81}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


open(&(0x7f0000000140)='./file0\x00', 0x78e, 0x0)
unlinkat(0xffffffffffffffff, &(0x7f0000000040)='./file0\x00', 0x0)
sysctl$net_inet_tcp(&(0x7f0000000200)={0x4, 0x18}, 0x3, 0x0, 0x0, 0x0, 0x0)
r0 = open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
recvfrom$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x7e, 0x0)
writev(r0, 0x0, 0x0)
write(0xffffffffffffffff, &(0x7f0000000040)="ac", 0x1)
mknodat(0xffffffffffffff9c, &(0x7f00000000c0)='./file0\x00', 0x2000, 0x4401)
fcntl$lock(0xffffffffffffff9c, 0x0, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
syz_emit_ethernet(0x60f, &(0x7f00000004c0)=ANY=[])
socket$inet(0x2, 0x1, 0x0)
r1 = openat$vnd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmat(0x0, &(0x7f0000001000/0x3000)=nil, 0x0)
readv(r1, 0x0, 0x0)
acct(&(0x7f0000000140)='./file0\x00')


sysctl$net_inet_ip(&(0x7f0000000240)={0x4, 0x2, 0x0, 0x5}, 0x4, 0x0, 0x0, 0x0, 0xfffffffffffffdf0)


r0 = socket(0x2, 0x3, 0x2f)
r1 = dup(r0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x2, 0x3, 0x0)
r3 = dup(r1)
dup2(r3, r2)
connect$unix(r2, &(0x7f0000000000), 0x10)
sendto(r1, 0x0, 0x0, 0x0, &(0x7f0000001280)=@in={0x2, 0x0}, 0xc)


openat$bpf(0xffffffffffffff9c, 0x0, 0x462, 0x0)
r0 = socket$inet6(0x1e, 0x0, 0x2)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x8, 0x0)
shutdown(r0, 0x2)
sysctl$kern(&(0x7f0000000040), 0x2, 0x0, 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x8, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r1 = socket(0x18, 0x3, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
getsockname$inet(r1, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x1, 0x1, 0x0)
close(r2)
r3 = socket(0x18, 0x2, 0x0)
setsockopt(r3, 0x1000000000029, 0x0, 0x0, 0x0)
mknodat(0xffffffffffffff9c, 0x0, 0x2000, 0x0)
syz_open_pts()
getuid()
r4 = getuid()
writev(r0, &(0x7f0000000540)=[{&(0x7f0000000140)="07f04111f163833ff790a8a8e2e8560c2a71ebd72b778672b065e531c57bde7ee015219cd39e14ea15220dd600198d0f99860fffb8220b7abb4b081673555f27ea8ebef4fc8eb5077023b664e4919b674399e5d073e25f9edd089db94c75c090efdb4ba80ab4492af0e3b37334926cc46ec07c71fe3d527e1aa306a23f7529c5f6bb5d3f3acc08d7730413c1c55d5db314745c994792a8146b57b20aea48f1930bc742283e38ed551f3898fe27e46b64f11730660c24725e1c6f8093c50352021d26bd69e47cba5c92ee67d2", 0xcc}, {&(0x7f00000002c0)="437651ffc323f9efda259590e069b8c1466178bd53f8406e2b85590c26a3d0fb6b1f91a739e7e6dccccbc9e8c3854ce1dde479c1218c9ec567fdb06c2e23a3052f2ddfce44cff4060c392491c2acc157107d7cca3128e7cdf5c6ad571d9a0895d40b33fdb6f254f5b81c1c09e5de52467ac898724165e8ff617e14f07ef465289b92f4c1ebe68ce39b548b6cc13125d1b3269a6e3c82502f3fa7c780d0605aff94ab90b7b2ad58ac1b39badbcbafd8ad6707a13f14a8983a2797583208a6ffffffffffffff7f16e15c345b34abd939dc36412e1c7463db841023012efe69da16ed2c689b048eeedfae4faf1bded68cbccbdde14edf352f0848ac71ebad24339084cef3785c2bd2", 0x107}, {&(0x7f0000000440)="2b4be870b301ba71483b8f486b35d16f85b90ca104c77ae2101a718a3ea587f4349fd5704f1c834e2173ca3814f823c2cf85124b6d73e4c68102642e064747", 0x3f}, {&(0x7f0000000240)}], 0x4)
r5 = getegid()
chown(&(0x7f0000000080)='./file0\x00', r4, r5)
r6 = msgget$private(0x0, 0x0)
msgsnd(r6, &(0x7f0000001b40)=ANY=[@ANYBLOB="0000000000000000d577a0f1b55d40de92ce05f2148950092f35d5ade543c2e4251bcb32f02a4bff9dd478c1be726a51e302e16c6477cafe3be5feddb3802341be47d5788ea28fe01bcabbc896e693a2dc9c2719a5a7cc02b129a218cce33a7d4f2484a641ed0df6a538e610a3578a7f44126f69a8d99974556a9f33c2689450ecccc386c5b02de7fba562a34e7f102c4f861d62d4dc76ede826d2c00e4ee6d1f68d2af2b9d42a6c0bb375d3b57d9730009e0e9ee912b7196f0022f1c82528e471eea347dd45b0ad7655a5cf3a7fea1b1a0d35b50b490cc27624261977a7b11d9b0a440860644050e8b67c0d4921f2ee950a4bf5507e43d1dcf6ab60d77e4e904664e6d7d93009752264ab69bf744dba4095b9c3d0091e84a8d0497343f033c5ec94bb4017643e3c6c13e01006084beaf2e1a2b3bf"], 0x135, 0x800)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0xca})
syz_open_pts()
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg$unix(r1, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="28000000ffff000001"], 0x28}, 0x0)
recvmmsg(r0, &(0x7f0000000000)={&(0x7f0000000000)={0x0, 0x0, &(0x7f0000000000), 0x0, &(0x7f0000000000), 0x63}}, 0x10, 0x0, 0x0)


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000540), 0x1, 0x0)
pwritev(r0, &(0x7f0000000900)=[{&(0x7f0000000580)="ea", 0x1}, {&(0x7f0000000680)='{', 0x1}], 0x2, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x2}, {0x5, 0x0, 0x0, 0x7f}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x5cda)
r0 = open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
seteuid(0xffffffffffffffff)
chdir(&(0x7f0000000040)='./file0/file0/..\x00')
r1 = geteuid()
setreuid(r1, 0x0)
r2 = geteuid()
r3 = getuid()
setreuid(r3, r2)
setreuid(0xee00, r3)
r4 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x200100000001d, &(0x7f0000000000), 0x4)
r5 = socket$inet(0x2, 0x0, 0x0)
close(0xffffffffffffffff)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, &(0x7f0000000300))
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000340)={0x0, <r6=>0x0}, &(0x7f0000000380)=0xc)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000003c0)={0x0, 0x0, <r7=>0x0}, 0xc)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000400)={&(0x7f0000000000)=@abs={0x0, 0x0, 0x2}, 0x8, &(0x7f0000000180)=[{&(0x7f0000000040)="268a19500222addfdd1965c6e1e677d79e66f38283451cfa0ed102c16ce4f7d3f673d3411137db3f31b073de20bd47e7c8b709d9e8b61b268bb09ce7d8882ea47c660a152e5e194aefc1bafd8f1850a447f47285810a3e79a6ce46100a488a973acc4828c5a732af64dcd5a39a625a2e0fe10f1c0bff3b07aa3b12400fd7be81f3df04fa7945dab15e4d494e71a067b2b5a4fca8f4a7b32fbfd72b67b2a745e6aac6696b8d0fb1a4fa03a1de950a1ab5e603b80691d5675c9bfd1dbec4faa50b66da63292ea7940cd8f541ac1e7b605f214bca6abffa926b3119bdbafe0058c2c8e5a0cbd678", 0xe6}, {&(0x7f00000004c0)="e97d6ebb271004a3ff607a88679674c325347ef87ce0e669d4f3e4379b3c2c4c5befebc28ae5f9255221f06913029a94f499c0683c63d7c204c0181378e71bd94cee34aa013a5676db8d67f3b31591192ef5069008f09029090bc1b540421fb6399d4da97a0ec0ee3e140138ca8e0ea4272ce66b66c1ef40ba6a5f8dbee67e1808242a0ae271a0993cc11bbfbaca77451327c1a6aeedd2c0a66e560de5f74519405b90976e429dccc7101540823271a56f5626ad5279d9b6348dd618428fd2992818c8a53cabb4d2bb907c45796ce5ee92c9889b79164dbb7681f066169e785b55ff0503adf2a7562c2ef7a9274b98944d51aa9fd4856ce4846ee04b0603781c1160ca5129669edf184b7928b362533604b39346dd87c71651282fcf12331f68a8f127f698d85b751217101a70e3057a1bddd2f2deb612f405744f995bfd56e9d9c063e9d079f41b337f9695b7188428db6462b5ce6fddb7ea3b9234c32fadc6a54b6873678ba7e2f763339f154117fde4416c27fa60344a078f1724e5a96b2809ee0dcce23d6056343deea5a9b8f5501ac9910e01b567136d7dd2529bfafb28b8f1477fee95b589ca80560d290c83f5b5273318c613bf03d6dd3f735acd22325f6ce63efdf7c1ce28b90fe056bc35a1df39231030d4e5811be356247729d0c1c33664ebf5a8262eca928cefa21d49b36e960fddc12ee6875a27a83d84d9a9e6dd9bc34a07863a10e02c6288ff36c25048781371960f10654983d988da575d57d8e3489e61926ecace57ba04366ece1d8567b5219ca33e36d93c45b8ae7dbbfbbcc7fc4d533ed75ebf7034492cc62e6fa793be64429242dabbff550f9356986da5491f8ac6d312dd1765c3f9cb38f3d3fa2343e5544df47bd6db9bcedc428e73eccf03f70df485876cf8f92a26803e60c2c9574a30b90064164c51678dc592413e4f749249572c42a1d57186682d13291dbf8250707fbebf958b36974f48c2bd9303d1ae278601fe18d815090268714a5f46d74cffed387c398846cdc7d5d43ec509430581d06d224236a310eeef6fe4e885dd12d8c868cc9d21a072e7e837890efe2e7e1f5ffaad986f672a6ff57e183d034916c4e03d6e9eb744a517d1cfeb68101d501d4ae1ccf5c5c853f4bf46ef20607fc2b4ae4de44bbfbed0a3aec9241c8b6a631444f96b65d0e66d034711084c6767d0d2bf235ccc9fbb3b4ca4e33fd071e4e7cae0725a2535280871e68d9d203990fc128dea64064634d62ceba09bc4221adcbeb0c30792e6f60cb2e2bca950bec2e2ad20e88afcbb9154287d69172025b327c324d534e4ade2087f11ee6da6a1054301260f177e330a34b515f4b8758632e9db1761b623c82b4bd96746a7feff2acc0e5cd1098e30fcfbb26d917b386d13b98a60436cb9272df086bd26ef08571845bbe9e4db9f15893e0be91728d53005cba78d52324cf42ec97e6adeecb14217f491df63d08bd7e2c2f79228de852342470d85af6528ad989b614d72af248b214e2403cbfdaf4bea407cc5810a25844b756adadd1877d8af60eeec6238ba2c692c91facb54920d0d6a46ad2eefa410b16f560dcf04882e28ba710ff42cb8e3e37bf6db45bbdefebe0260cf3d658169d7f18f8058b9bcc04b6a44fb0826037a43b680fce69c44d89ea5896ddd79714d0c1520847ea7fb3004be1a57ed11abdf89f6ba06fe903439bc755f187e94b7c52ccb171404277c422cd56da9e9efdbb96b8737d0933791be97078d67da327701f737c094e43e02875b237bf1ce534490b843728ac55ab80a8ebab618fe643f7cea619de72c86b0109bf16c1e1235e75880764a664ce7be828c7e11412771f083f03f7a93dd7ca9a0e0e42a69dc88245c6f41354502e8ee6e7b6071358c38b86891a31f91250d33535cd830ecaa6a900397233dd3a77a39174a964825767137e8aa888c8ba864c3f9377d60c5c66bf3ee26764f937b6ebbcdd3408c41fa5d3cd53300c5d8a83b81a752b2c1a7be5ec5012b8ba0dd65a4787a90ee190e1f25b26ddd58fb7a684b6d2a45a2ec9a762ae0d81ddfd543e14a47b66c5163fe97bd8390c654d62c6024c65c422e5cecb69ecd47c23e5801790b6db01859c00e45ad11f5952937fad8251e88ca49ea4a112bf13ae4a457a91fe0f994db83a0e508ef79f8b77b6848bfa9079a130ecba486a50644c0eb88acfeabb9ba45510760d687bb1a415c8eac1c70afe9ce65e657e826711a4fff9c4c9d6caca59c9352bbe415f53715faa278b1bb0f1b5f011d97259490d0ae4c8d046cc523bd9167c14714809b96ce3eb18f06f36f68e0c801271227b34edc3c68ef5c333ba6bb2f0f89a34b8f353633fcfff9a31c5469358efff01fe95e24570491d658866be7cf7843b2e4e3117796667df6dc7c28db7fdb7c46d9511b9a6f52c7cefa597a958c4f1a8a1b3a924774eca54769796f70dd60572a4fa0660bbd301ce73e23845ea3fd9a523808a43952beb0ba35cbb91b5d54c934482855ac15261d971cfebd2d53b7c7c38278fe500429d6501a10fe52f6da8ef7b4ce03ee718267d9f3e3c31072274a383d6a3210d7008dd37aeee68fb3faf04fb24027a1792d21e4ae2e46f15bcdc18a602868521093808aa0f307c91884210f29a6ae7b888567d36ac69ed6151a1cfb64117a324c33b98a1cd6beaefe85d47dfbd81b0c19a5fe76c576fbe7f20a299802aaa48e57d0466b06d41b8be698ec11c8a7ff776b79fee7e71297b5da6a1a37a8877a0243e9299e09abe34317bb23ad43e77a34b46a0df72ff3c6bf24a451ed7dc2fca426fafb2b91f491f8f65115867d0960089708681303374caffc1e5bb56725d467d196d85869e57537204bbcf918393330d92f235433b05ca8356b73eee6b606ada78f8f690446435f19ee2df1a35b96dd25480a2097d07c50b5f4714b7a459457c59ee28c9f5026f26c5fdee906852d7069d87a98412b073f50c13f9e61a8d651d87405470236f990dba6deec7c9a0c0caab9b2608434cf8a6afe8d1088215d2ae4d04410da05daada2baa0c101a9d166baf9326543d71c0fb65f5c5c391519789ac5c26e26af4460cd49f2500a1cfaa42aa46eb217ac71aedea27c0207ffbdf919e32abaf7037299d27190afc87936c68f4756efc1c63d4a055fcfa348d9b6b9e64471016698d48ec04bb679a1cc9f380c15572f6638b0c0087ff56115b23f940496020c2f58a0813dfb0e7a9ec5492c6c626c30dfd4cd44b063fda1dc29b0ca96562500d05b8bdb84b1b14d3f015075006f5d89c37fdcd0af3478492c36a20acaca90749906415ab00d1fc1ece1515288e28621af23afc9ef06b116f1aabf7f2f1a93b063fb47649419f587c6b655ec78f60b2145c0634d47a36960657aea1135800acd718287c565f8f541de8b10cfac4baa38f39e154cd5ecf2de2c34b9a86647ccac532a66cf09a6ae0f9d61b793a5bbaa709d6da0a02e8ed45378736f0a37aa2f0ea51f758933ffb1a5a8b57b467e80b7948196d987b4ee6df4c042ab82fa49d273c580753bd0d9ddcb7b64e5cf5fe4bb36786280c699eae4b923465bf70952815d0482c39758f491bd09152aaa0d037ee91fc70d7bec5733b70219c78d15950175dcc217e500d3114088575e6535a44e55f4971ab080d59f2f103ca57770fb9aef7e5477d222c5bbf5528d3e3a1333dd94abe6b63e790cc286e6c14922e8613aef07255acf15abffc95025da99af536fc760bfa47ccf0807dc3dcd63fd7c0760106889207d3c75950dbbfb58105940a1a19eeed23cbad7436f8773e3d56e8ed84988199082abb3d5f96459a52381e1df0ed85a6ab79049450fb773b28f07ab03aca796fd7c460c7b50ed848019c4ea0bb34275a9df87c0103ac706df5f17c290919a5b437b4154b06f9d91a8657b2cae164ae1902b9a2d3516e195dd80952152e1e6bdc34d108c3aefd61eea859b770599097530a139d5f798bdc60e438e38bd75ed9160dfec7c06fc3138e057d56b84c33c190d1c45cf765a1a3f1144aaa6a6b5eec826dbfb364f41fcaf74b28dc72b00272e147f511826d1a8922143d1153f0dec4c68f33a8887614c30edb585549219c3d46a0a33134cdcf201ef71f0d5534023ec9b282e815647de8e42636cda91238f4459cfb1b4bec1435e0622daeab43ba8df48834ad9983051d8c66cb8f4af876c38e37f885cc9c6a323d9d43d1591420a1fbefed085d00cc60d5f2b8512cc486d0be44420b06de1cbd895b699ceb77c36c93a0fd87c02eec5d7d58babc1fb842fafa819673433dca3573a0fad48d90240b0b099d1493cd2779828823c3f92ef4e865ef1dce5dfb26245292230ca85abb87ffe64a1eb7b9f4e390d8dc445cd3e0bc61914ce5971c73edcbbdaa0a7de4a44b155ddf6229af1be000e712965dd1f176e8ebfc6e0f0738757a67d050e253082ebc56d74e3d52fe6d23d2f464ffe5ed4fac7554b6d40897b13bd024b87ca6edcdbba6add4553d534516625163e2b48d73e9c1bfeceb066838305b25f06c9107707177c946caa114e82991955b87e5f215e1dc2900d5f7ff19afbaecdf2e3b6adc708f82b88261aeb7ebd8928addcf102ae9c8e07d8620ed9290adc33e52235d18d8820bab5be29dd23e8eff63b70566a0906f5e61cec8962a9ad441a830a839dc03154cc3d2d9736487bbcf08c57b25caa6840e31759f4462a282f2d3fec3a864c03a4fe5835cd37e25eed0c3b7ec820625f8624b12542a52d99245055d7679a4f425a697fc80e59e64236074ebd282bd4ddef0b2c387c869b80a4927b47c3dcdbbc9f4b01cfc69172dc42f50aa72fa5b38dff426b7b93f6f516cc6804c5ecf035dab3d1526971c25b6b926ed04a0787e9f8ff3a549f6e14469511cbbcf41a10fd1998524d0fac15f836927a8a07f13e8c866994bb3d53a470c56a2e95c66bac8a52574a176eabafde5080035f0ca78b17d13b0b7865191bdbefad5f7ced00de9ed7ca0f5e20409c1b8c76b6c509b27a2b5c3ad478770187e346c3d9aa761835b38d50ce7e4c3d6128156538c90b77bb8140bab19603d1bb101db8d181cf61d11ba939c6b4231f01a655ae42fa8859456a9124556b3901a5cc98f8bcc4b8b4925b71370226a0eb1a7bb944e64bd907174268aa8f9d5c6c6693f5ef7fe150fdd9dc6eaf3947feaf14af1ebde3256b954a3acc99842ab3310bba940d0d7bb560aea4172eebbe0bcacc0482da123543d1b20949a90d421aa84d7e360b394c1a8eb9ddc7ee21d4455e6e23b7bf76a9db0c889fbce07942c09704bc763ba09fbb89dc04f9fb4c6aeb2426e1a00cba2df49a6574df9ec58aa1e9bf6ce19b07cecde8824581af815f4d996a820006ec8bc4c43e7ab9d699c0c4a4c4a2ceec7c7fd580b991a8f1a77f89c68320fd9c7b580a977753751d5d2efe3dd85dd7e2581c80b83ec3796b43d7b0ef4f789a4566ae73d2106daab01129c2fc480b828994652f59e6ce8a4bd9139417258ebc8e332d1a23be99505853eeb00394c8bfd3c8f0cf77c7499634e7bd3493b5e14fe57cd693ada7411d51c6923c45da3dde4cfccf5ff2e24edfcaf2baf7eb146aa8a1498b43d5c30d2a3ce01001b0f86528d32fea9cdd20f564b328d651738e90b43e5af675466396cdd21a5951ccfaeec74a3abd6cb8e7453f08e148095209e1fe6b4548ce603d6a043c66c8fde2193cae08108019e5cf4027b0f02ffb64452aff4f6c52d555d27a44bb0320cd62e00093ccc2e0a5d5c258130b24a86dda9cfa3448778471140c40fb3cade5d32d36", 0x1000}, {&(0x7f0000000140)="3241c4b621caaac034ccdaad1c29ddda4164c30bd010ff85e4a8f0cccb3f26f9c153ae5170e838ba0e32695f", 0x2c}], 0x3, &(0x7f0000002600)=ANY=[@ANYBLOB="1800000000000000ffff000001000000", @ANYRES16=r7, @ANYRES32, @ANYBLOB="2000000000000000ffff000000000300", @ANYRES32, @ANYRES32, @ANYRES32, @ANYBLOB="000000002000000000000000ffff100000000000e844197a80e97c30d9f0e868c89eb4f1eb3c9a59265cd0d68f646c76f56704a4c3dc5e7ab526d17e15e58e739b6a77a560e316b4375858c8e56e4b18c3dfde54ace78147fedede2dbf5aefafd99c06ffff3921eb3f58d8a6ddd45797636753bcc6da9621ce64803f775e5418fab4a6440d20199e21fc2a1287dafbb2ad83e87e43df68dd2d966cb6b1e9b29c6ab4255728babda0fd624f101129617d2eaf622f68875dd93c10e5cebe21f0e40d4cfc9fb4233101717b1f426eea806b992ad89001bc8385b2eb99f65f118aadd9dec8c215703ff23be675f269ba6f29f3dc166c790c7dfd83e3416b29dc1fe4a9ae2e411433e1f88d1255033adfc85a11bca099cd73e10a6ddfd53c40b64df317d01acb8e3996043e2700ff14f955fa3a7bbb77ff4fa836dabcfd7a8c8e4f508661ed22378c5da58acf37288f203a983c6103f6e4c6079165d2293448f01bae4cc9428f4dbfa8c2", @ANYRESOCT, @ANYRES32, @ANYRES32, @ANYBLOB="000000002000000000000000ffff001000000000", @ANYRES32, @ANYRES32, @ANYRES32, @ANYBLOB="000000002000000000000000ffff000000000000", @ANYRES32, @ANYRES32, @ANYRES32, @ANYBLOB="000000002000000000000000ffff000000000000", @ANYRES32, @ANYRES32=r6, @ANYRES32=r7, @ANYBLOB='\x00\x00\x00\x00'], 0xb8}, 0x4)
r8 = getegid()
setsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000140)={0x0, r2, r8}, 0xc)
r9 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r9, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
setsockopt$inet_opts(r5, 0x0, 0x9, &(0x7f0000000640), 0x0)
getsockopt$sock_cred(r4, 0xffff, 0x1022, &(0x7f0000000000), &(0x7f00000000c0)=0xc)
r10 = semget$private(0x0, 0x7, 0x3c0)
semop(r10, &(0x7f0000000100)=[{0x3, 0x2}, {0x1, 0x2ff}, {0x1, 0x8, 0x1000}, {0x3, 0x3ff, 0x1800}, {}, {0x2, 0x1, 0x3000}], 0x6)
semctl$SETALL(r10, 0x0, 0x9, &(0x7f0000000140))


open(0x0, 0x0, 0x0)
poll(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
socket(0x2, 0x2, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
pipe2(&(0x7f00000001c0)={0xffffffffffffffff, <r1=>0xffffffffffffffff}, 0x4)
readv(r1, &(0x7f0000000480)=[{0x0}, {&(0x7f0000000500)=""/202, 0xca}, {&(0x7f0000000680)=""/148, 0x94}, {&(0x7f0000000740)=""/183, 0xb7}], 0x4)
r2 = socket(0x0, 0x2, 0x0)
setsockopt(r2, 0x0, 0x0, 0x0, 0x0)
dup(0xffffffffffffffff)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
open(0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
madvise(&(0x7f0000000000/0x600000)=nil, 0xffffffffffffffff, 0x0)
mlock(&(0x7f0000fff000/0x1000)=nil, 0x1000)
msgget$private(0x0, 0x0)
msgget$private(0x0, 0x0)
msgctl$IPC_RMID(0x0, 0x0)
msgget$private(0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, 0x0)
shmget$private(0x0, 0x3000, 0x0, &(0x7f0000001000/0x3000)=nil)


r0 = socket(0x11, 0x3, 0x0)
shutdown(r0, 0x2)
r1 = dup(r0)
poll(&(0x7f0000000280)=[{r1, 0x4}], 0x1, 0x0)


setrlimit(0x8, &(0x7f0000000100)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f00000000c0)={0x0, 0x0, 0x8a38, 0x0, "07160a009cef01098b748200"})
writev(r0, &(0x7f0000000040)=[{&(0x7f0000000140)="b16c24f4801f41e7de7c79d4e9c2dce27e5b44e2e419ace7bb28300b5f187151501557df62094e6beb40391b25370805e636620e6d994cedf45aedc45a26008b597e715c98d1c41cf19546f21841d1d4cee8472ddf843f01d6fbd3e38a769e6753d182bc0544fe55e135df150ef24e9f3e830e4755f367f532b79697c880f1a5948fac720a8938c262a1f3f1c518b573f4c96727ee3926ca74c8733ce7d83e86206830bf23daabc6f085dbceb229dacb8fef5ea2aacde1d5024356d2acede80adb0dc55d8a61df9f0880ecd98d9f27aa88aec2fbc872d569a0fff1b37668abe37954a5b7718906bd08360ed754313cabc057543f64423df99c40eb15ad8ab2b434af760ca690da5b2d478d31a118c00c3a8746cfea74f73f33b073a50a140012f95e72a740aadd58d591380f80a2df49e8eaf42620916edfab6e8724a4bbd3a89f630b62a7865634090f33b9f07fceb8ac70b63fddc027d42b65ed239f7491b073f32bd26d51213c4350981807b8c295e94ea18a720f24d09bad81968fc86f9c87b01e7c998f40548bc008df0829181d071bfaf6bd65955d3b386e3b0b004a9aba649f19b42c64822671f8befd802f00e63ca3cc1689ec001be47e9f99d639ffe8258fa6ba589daedb8cafa6f728ba326e34a42c63795046db6a567f541fd07b4cf0e1358a5dba6f08963fd7fc487bdd264d206fa92ee4933717d8aac1170ad0c4f240498d4fa489278eeb4496eefecbdd690aacdfb96c4d557739f4a7864b5feac0d1099f855484fca633588977b4540a24f71c30eb2ce676fd73812d29da07a69bc1625a4daafb9d4c3914ab0436de9faf033b84d5f79ea702598c5167e77f24d064365f1ea80551a53ad6e67b56100cb7d60feb1a38dd64735bf731790a12aa402e0494c17a0f10d4c9a7ce98cd56d2e9be8b16e67c34ae7985620509b5719c797793c7828187f2812b867cddd4198302927e9df32d3b7ef95582359be883d269f9a81114dece35fbf98d91e8767783f66ce499224ed06672237727e9ce4ec21aa6aeb59c3cb2e7cf5b1b980993c544b318d06fb1272f377bd227af3bcf9b46560d434a54f5d51912e68ad49ce39ac02295ea166e25a7cc7e6197327ef9d9d8a2c7950dbf5874cd4250c794ce31d40dacbc997b75eff483ed5aaac0345a2ea9b0db69a537a8351d84d4c7b369d49b5ffada26a49747463b8862e69e5db96a8e16bca9cc5f3125e53433faa4117322066b9f4fab575edbb5c44a44ebe78e506e7e5f16bac8720e6e9d83dc9911c2f2fd9e674f9502a1267e98f96d62a1406db9de4b66126c1a8643e13275e2d4c161e153b95454ef56adece0a5cafb0e8d470caed400d0be2f718b16125d3bf730d1d174f36cb835e47a7cb79289550184fd27a1730673da76da906e512ca03f07d569bd1163134bf977eb560a661be3a44d2ae3ccccfcd4334ea02f3ad0a7df3cb6d8ea2323cd365510b997b27f600d9bcbbf4fc85043b41d00337b2458c0edb0670d7dcf2a0f5d0634de23c2a5e765497dc4efe247f636e4f78bc3c556f33c12817bc91f85988acbe04df52f95dfbe3a998e9f44677549216ed527cdf8d59d2896d499c29b6238ac879c1f29db80f0715ee2d8753fd5ffdb5a82e91cd3bc9f3b9874669b9001e7afe80be21eb1057419698ebe00c19d40fe3e73b7aca4729980e01cbc1ad03c0a0ac2889d6d84dcca54e63146891873fcf5a85226b68c46511e99ffe2bec01a099c94e5e70e44d6450adb110078872d3345f54f455e6022225757e6e62d89ecf00e255316d1573556b0a34fe150d9e695d2ebf916dd8743effc2750bd6269c02a0fb148f6b26f6c90620e20d1933438ac058b0cb3254368d6851fc22c3462729284837357f24b418e3b7382b42b84c74b10ed03393f5aae7a2a8e31ddbf52f81e651c735dea7492c3d758d7890c69d98d60e5f3337f0431c258fabb238a5bd69af0edec36bfff77ce7601399b2ed05bbbac7ac9ede7bda9b2c47e0b9f72f1b4c4f45f48dc94dc0816cde44850d041c8aa1ccc6de0a9d11ada0f786368e4a558e4873ac6d59e4b012b030ff6d966e6306e30f0f6bc97129550ec5b52d195356fd2d8ab6c9c6aa273d4a28d185ff879898c170a3169c4a7559838077978500e8ace5ac38d48b2c10263901036324d40f507765206868bb32bf7b792f60836a5c83d42bfcb9fe1d896d13708d625bd3228ef9b9bc85a53ee679d613483143d4b6a1d2681429e3d7a44edd3acc13532a73ce96c15f1c483938b4864a53093183fd0c0c2fc440ea05a3d53c85572fda9bb262c6d064cad2e9254ce79b043fbacd9a02e9e197ca5b3e012cd8e17498474ce0ff39b2369108f7fec2836847e08c63d2e61ef8b9e8b92cf23f330896dede7692899bb7f220d3387181a9849ad68d568cb938b6ac29c75898f55739d18a8d05aee7a525c6193ce73e82ac1d7a8b975c91fddf5cc102097180206afcf33c8106a354a2d5a9589702641af6d16f4b3effa60387423ec4f1ac91b6e02c6c57a39ed4e890ccd7b3aec245a8243adcd5002894a00c9ffef740a687d7fdee8d98020aaa1bde594e6822b282ab46b36ea95e5d73bc4848183d69e293371787335fb9b6b7eaf1275c6a1ff5f9d9c44ba93efbf1f974b0ebf2bc21cb8e93cecb386816cfed4a3acbc132196e44a397b1812d56769e636deb5fdfe1c9a22b7dd9a81d62fe585a5b9aacda2e91bb697ed50447de7e76094760e7a5c5cd10e289bb839aa8d8d883e4ff3c5dde541494d8261662c40e0878db52edd0d82c54bf0736fd2bad1aff62b787e9d41a1a74ce84f2fc0a203a6f4de673f93209345425f2cfa73d789d084cc57bebaf7de41cac685ba6fa5b9c52f2aaa75372965793d0f93b667c4f4b7a57d05e203962135a32be7662faa2092d1d6c3d3a31986ee4f5e913a86343633f87bf0c0bb8686a0b96adb30ba6eb6907c7968513151259ffdcc428496e30e6e6353cfb5ea477ef4c26c78f2eb850a2639d973a0be796301c22dac7aece02fb5260e9d1546b77647afa1cee3bbbd26343b1662785cf4fa2cb68242523ecf07905981d1a61050ec833784eb60aebf219a02ac26fc490a1c2e088a44af86762524d0cca968d2feefe71a72cdcb4b51e95d4e4b3a93016538239412a3f45f10e8670cf59401db0ba0d794c4a0b66b7f9472dd9445f5235122b375da0098b43470139a8f02d14f22a0806e78e4ab023a14b7327457f64a4cc60135fa50f2a8560fe15eeaa9cc836bb17e94d559411e3c2dc04b30e7c77f7920b18a17c8ff0e00040e0c24332467718c6f1911363af4fbfd5610ed4800e1539f88a768390ef9cbd9ebdba9d4fddaa277664e6ae3363785de6fa7d876bc0504109a63c4323e6d257259af46a6eedaaa9ebe8306da7acbef6a7ab5f00d8d89501ff3c78e89a763dc67c7f220ab49fb871d24e122b92de724a64355dd02557daf7a20f5aff7215c4a2aa0491522ed9e4869b9ca4d45d79e4596bd6fde8cd42aefb6d9230626544cb750bd00fb084eb5974a825d0f2bb5c9c679ce9debaa9100f8a5c38e715f228c9a651a17973e12970c6cd94a632b44169c1bd0a7109e7c2dacf4aea809301e5590c79df681681cd32f8d104fb75cb61ee836976f141986da0631fc6f07452bfbf0ec23ecc4ae850920206c99d94689a212a7f9ed7463c645fbb7cece450caa117dcc822268ac02f8bf95694f2c22a8b4b2900816851f0c27401bb576e2204afb2c3d84ecacba7a532739b4c54a2b61e88db8442f731a49076199ee1d154061ae012262f5a6b1c81310f0d95da2be44161a6de3415a72dc9a20271af123a64f11f6920a972493ec9cfba33d8c6da2e3a666706479bdb5e06602492ce777c831b8cefabdcb0df3d28ba136667af2e9e21173ec8cd463746442afc300059f626985d157d2506f92bae2ed7cdc477ad20de2ae3467c63e94881cb43b75638e12b1ba3cc0ec9c5078717a1d930e2176d57c6f3fed16e9311569820b532122f2abbbc6074f438c0416f5927addc6c110beb1ab9062cab731bad2d62bd396479a72fbbe12254189ef45b3e9e57b2647b3f10ee42635fef7795ef64ebec1ca649f1ecbfec394eff3bf52a278d8bfaf8bcf243f8728ec88b4d47439f373d9c3cb8d4a3961ed9bc568629782bb94d0b2ff5350355cac5732503ea6921cb398984197b1b80ff006488d16584d7e11877685d45addd4ef653ae30ee198f1ad950602beab0f0918bf20ab20ac908b04c0cd32c2f293202249b0add89a7d22ab95fef4049a4dbe793bdead7fac6fec60d4a422becd4a8d2c15acb052c40f6a5d0d718c3e9b2e570c4f7e7de82b32d0866e05c2a865b0f651f930cb2924a36031f7b71447cb2233c0fdee11f27fcb01cd8eb0314da8748240d5ed2e369617ee373d6b3820324b4c10aa7961f64451df43041df972de8997dae3cc51276b735f", 0xc59}], 0x1)
r2 = dup2(r1, r0)
ioctl$TIOCSETA(r2, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x1, 0x7fc, "2cf9892af9a590e4cb52e88608007673ca9e5fd7"})
poll(&(0x7f0000000000)=[{r2, 0x40}], 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000240)=[{0x1c}, {0x50}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f00000001c0)=ANY=[])


syz_emit_ethernet(0x4a, &(0x7f0000000000)=ANY=[@ANYBLOB="ffff8b"])
r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x2, 0x2, 0x0)
r4 = socket(0x2, 0x4001, 0x0)
r5 = dup(r4)
r6 = fcntl$dupfd(r5, 0x2, 0xffffffffffffffff)
socket(0x0, 0x0, 0x0)
fcntl$setstatus(r6, 0x4, 0x4)
connect$inet(r3, &(0x7f0000000000), 0x10)


mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0xc0e99db6de761f86, 0x0)
r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x1, 0x0)
r1 = socket(0x18, 0x2, 0x0)
close(r1)
openat$diskmap(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
fcntl$lock(r1, 0x9, &(0x7f00000001c0)={0x0, 0x0, 0x0, 0x2000100000002})
r2 = open(&(0x7f00000001c0)='./file0\x00', 0x0, 0x0)
r3 = dup2(r0, r2)
close(r3)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f00000000c0)=[{0x74}, {0x30}, {0x46}]})
writev(r0, &(0x7f00000002c0)=[{&(0x7f0000000240)="e049e64ada6fa45d6bee0bf84a9e", 0xe}], 0x1)


r0 = socket(0x2, 0x4001, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{0x0, 0x0, 0x0, 0xfffffffe}, {0x9}, {0x41f0}]})
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


r0 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x401, 0x0)
sysctl$hw(&(0x7f0000000040)={0x7, 0x4}, 0x2, &(0x7f0000000100), 0x0, 0x0, 0x0)
getgroups(0x0, 0x0)
socket(0x0, 0x0, 0x0)
getsockname(0xffffffffffffffff, 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001440)={&(0x7f0000000080)=@abs={0x1, 0x0, 0x2}, 0x8, &(0x7f00000002c0)=[{&(0x7f0000000100)="f4", 0x1}, {0x0}, {&(0x7f00000001c0)}, {0x0}], 0x4, &(0x7f00000003c0)=ANY=[@ANYRES32, @ANYBLOB="00000100"], 0x18}, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = kqueue()
kevent(r2, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
setreuid(0xee00, 0x0)
r3 = getuid()
setreuid(0x0, r3)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000500)={0x2, &(0x7f00000000c0)=[{}, {0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x55}, 0x3, &(0x7f0000000200)="58bc5a7f0000000000000084cf8f23dca7a080bb8f00000000000000e74f1dd1ba20b3ffcc35c11fc39a17498311bcf9f34ce55efc6aae818aa9f6e6382c76c7ba51ac6a998cf9860d52111f5d81ef087ffcd82c4c878c5790233ad2174c54cb2612500bf566060916ea8ce2916ee768e635a143b67839dbd0c0f87302ff60121c7c6bb13349a09d77014ade41ef21b1f6673563bbaf74e8c4f207f1a98aae3524c2c831ef18c45f2dae0f7396fd8d8b50b43b38f0e29e7113e47e4251a34854b7457c68087a48e7a3f975dfe7a67fb5a0a018321539a58382d197be5fa64c2065f0f40b3b8d6a779512ac7145", &(0x7f0000000080)=0x33, 0x0, 0xe5f81a4756f9a02)
r4 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r4, 0x80206918, &(0x7f00000001c0))
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000280)=[{}, {0x0, 0x4}, {}]})
ioctl$WSMUXIO_ADD_DEVICE(r0, 0x80085761, &(0x7f0000000040))


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047470, &(0x7f0000000280)=0x5)
syz_emit_ethernet(0x5e, &(0x7f0000000040)={@broadcast, @local, [], {@ipv6={0x86dd, {0x0, 0x6, "cbe4c8", 0x28, 0x0, 0x0, @empty, @mcast1, {[], @tcp={{0x1, 0x3, 0x41424344, 0x41424344, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x0, {[@md5sig={0x13, 0x12, "270689750c172377a96c7793bae952b2"}]}}}}}}}})
readv(r0, &(0x7f0000000200)=[{&(0x7f0000000100)=""/185, 0xb9}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
write(r0, &(0x7f0000000000)='E', 0xfffffc36)


sysctl$kern(&(0x7f0000000040)={0x1, 0x3f}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000040), 0x3, 0x0, 0x0, 0x0, 0xfffffdc4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000080)=[{0x4c}, {0x1d}, {0x8006}]})
syz_emit_ethernet(0x1db, &(0x7f00000007c0)=ANY=[])


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
r1 = dup(r0)
setsockopt(r1, 0x1000000000029, 0xa, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCLOCK(r0, 0x20004276)
seteuid(0xffffffffffffffff)
ioctl$BIOCVERSION(r0, 0x40044271, &(0x7f0000000040))


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x3})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x27}, 0x4000000000000110, &(0x7f0000000000)="71f9942400b5e1a0757cb9af769c7afec37082", &(0x7f0000000100)=0x306, 0x0, 0x2e)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504000004000000000007000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000022acf2047804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0e032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4fcf668246c0900e1937c727a4bdb8d000008e37123fc", 0xad, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100))
mknod(&(0x7f0000000400)='./file0\x00', 0x8000, 0x584a)
ioctl$WSDISPLAYIO_GETSCREEN(0xffffffffffffffff, 0xc0245755, &(0x7f0000000080)={0x0, './file0\x00', './file0\x00'})
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
writev(r0, &(0x7f0000000700)=[{0x0}, {0x0}, {&(0x7f0000000280)="abf0a6d9dd90fae8cd7b97caaa78c53463f557ab6cef44ad1d10f2cf60094b5d60b02340ec1f1a13717c73cfdb61eb2601019504bdd30a027d950c3d3be2f4f72bc5bd3aa0d5b6e37a949d13e96174e83a9f7e8216a0c0ff772315990d397941bd8d7c", 0x63}, {&(0x7f0000000340)="bc2c67c97240afa638e729d5f3e047aa124418a9c0466d9c1e855ae2f45bbddbf75110255343f8d362680e1701ec7cb72fd56529bfc2095cec5e57fb03485e83b87f34a006a12c", 0x47}, {&(0x7f0000000480)="e84add09dde8f30d81632a8f190def48bd5a161a5418c778af0c0dbccccdb85d4981e6bba558e6453569730bc0055c93eee47dc5949fde518b452973", 0x3c}], 0x5)
mkdir(&(0x7f0000000300)='./file1\x00', 0x0)
chroot(&(0x7f0000000240)='./file1\x00')
r1 = semget$private(0x0, 0x2, 0x41)
semop(r1, &(0x7f00000000c0)=[{0x4, 0x3, 0xe5ce97ab354d96be}, {0x0, 0x4}, {0x4, 0x2}], 0x3)
setreuid(0xee00, 0x0)
r2 = getuid()
fchown(0xffffffffffffffff, r2, 0xffffffffffffffff)
r3 = getuid()
setreuid(0xee00, r3)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r4, 0x80104267, &(0x7f0000000000)={0x2, &(0x7f0000000080)=[{0x64}, {0x16}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])
open$dir(&(0x7f0000000000)='./file1\x00', 0x7ffd, 0x0)
truncate(&(0x7f0000000080)='./file1\x00', 0x0)
semop(r1, 0x0, 0x0)
semctl$SETALL(r1, 0x0, 0x9, &(0x7f0000000040))
bind$unix(0xffffffffffffffff, 0x0, 0x0)
syz_open_pts()
syz_open_pts()
syz_open_pts()


shmat(0x0, &(0x7f0000ffc000/0x4000)=nil, 0x0)
shmat(0x0, &(0x7f0000ffd000/0x3000)=nil, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x0, &(0x7f0000000700)})
sysctl$kern(&(0x7f0000000080)={0x1, 0x4f}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)


syz_emit_ethernet(0x4a, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x3, 0x0, 0x28, 0x0, 0x1}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000140)=[{0x81}, {0x44}, {0x12e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


r0 = openat$zero(0xffffffffffffff9c, &(0x7f00000003c0), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
madvise(&(0x7f00000ab000/0x800000)=nil, 0x800000, 0x0)
munmap(&(0x7f0000400000/0xc00000)=nil, 0xc00000)


sysctl$vfs_fuse(&(0x7f0000000000)={0xa, 0xd}, 0x3, 0x0, 0x0, 0x0, 0x0)
r0 = socket$inet(0x2, 0x2, 0x0)
getsockopt(r0, 0x0, 0x18, 0x0, 0x0)
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x10205b1a)
open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)
mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x205b9a)
open(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000280), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
syz_emit_ethernet(0x119, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000180), 0xc)
r1 = socket(0x18, 0x2, 0x0)
close(r1)
socket(0x800000018, 0x3, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
msgctl$IPC_SET(0x0, 0x1, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f0000000240)=@file={0x1, './file0\x00'}, 0xa)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x7c, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
r2 = openat$pf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
poll(&(0x7f00000002c0)=[{r2, 0xac}], 0x1, 0x0)
r3 = getpid()
ktrace(&(0x7f0000001d40)='./file0\x00', 0x0, 0x1720, r3)
clock_getres(0x3, &(0x7f0000000280))
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, &(0x7f0000000380))
r4 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r4, 0x0)
r5 = msgget$private(0x0, 0x0)
msgsnd(r5, &(0x7f0000000040)=ANY=[@ANYRESHEX], 0x0, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000040)='./file0\x00', 0x6000, 0xe02)
mknod(0x0, 0x0, 0xffffffde)
socket$inet(0x2, 0x8000, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
r3 = open(&(0x7f0000000140)='./file0\x00', 0x10000, 0x0)
msgrcv(0x0, &(0x7f0000000500), 0x1008, 0x0, 0x800)
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f0000000000)={<r4=>0x0, <r5=>0x0, <r6=>0x0}, 0xc)
r7 = getpid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000003c0)={{0x6, r5, r6, r5, r6, 0x7, 0xfffc}, 0x2, 0x7ff, r7, r4, 0xff, 0x5e, 0x2, 0xffffffffffffff81})
getgroups(0x1, &(0x7f00000004c0)=[r6])
r8 = getgid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x86, 0x0, r8, 0x0, r6, 0x175, 0xfbfb}, 0x5ddf, 0x5, r7, r4, 0xb8, 0x10000, 0x9, 0x401})
fcntl$lock(r3, 0x8, &(0x7f0000000100)={0x3, 0x1, 0x7fff, 0x800, r7})
clock_getres(0x0, &(0x7f0000000040))
clock_getres(0x2, &(0x7f0000000080))
ioctl$BIOCSETWF(r2, 0x80104277, 0x0)
pwritev(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
shutdown(r0, 0x0)
r9 = socket(0x18, 0x3, 0x0)
setsockopt(r9, 0x1000000029, 0x3c, &(0x7f00000001c0)='\x00\x00\x00\x00', 0x4)
close(r0)
r10 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r10, 0x0, 0x200000000000c, &(0x7f0000000080)="eaef125c00000000", 0x8)
setsockopt$inet_opts(r0, 0x0, 0x9, 0x0, 0x0)
mprotect(&(0x7f0000001000/0x2000)=nil, 0x2000, 0x1)
select(0x40, &(0x7f0000000000)={0x3}, &(0x7f0000001140)={0x0, 0xfffffffffffffffe, 0x0, 0x5}, &(0x7f0000000080)={0x2}, &(0x7f00000000c0))


pipe(0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f00000000c0)={0x0, 0x0, 0x0})


r0 = socket$unix(0x1, 0x2, 0x0)
poll(&(0x7f0000000000)=[{r0, 0x1e0}], 0x1, 0x0)
shutdown(r0, 0x0)


r0 = syz_open_pts()
r1 = open(&(0x7f0000000140)='./file0\x00', 0x78e, 0x0)
r2 = getpid()
ktrace(&(0x7f0000000040)='./file0\x00', 0x0, 0x20, 0x0)
ktrace(&(0x7f0000000280)='./file0\x00', 0x0, 0x928, r2)
utimensat(0xffffffffffffffff, 0x0, &(0x7f0000000100), 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r1, 0x0)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000200)="f6", 0x1}], 0x1)


kevent(0xffffffffffffff9c, &(0x7f0000000000)=[{{}, 0x0, 0x0, 0x0, 0x7fffffff}], 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x42}, 0x6, 0x0, 0x0, 0x0, 0x0)


ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000080)=[{}, {0x100}], 0x2})
r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_GETPARAMS(r0, 0x80105727, &(0x7f00000000c0)={&(0x7f0000000080)})


sysctl$hw(&(0x7f0000001180)={0x7, 0xf}, 0x2, 0x0, 0x0, 0x0, 0xffffffffffffffe7)
r0 = msgget$private(0x0, 0x0)
chdir(&(0x7f0000000240)='./file0\x00')
setreuid(0x0, 0xee01)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r1 = syz_open_pts()
close(r1)
r2 = syz_open_pts()
ioctl$TIOCSETA(r2, 0x802c7414, &(0x7f0000000000)={0xf66c, 0x0, 0x7fffffff, 0x4777c53f, "1c192609307e7be2df67de200000d964612c3300"})
writev(r1, &(0x7f00000000c0)=[{&(0x7f00000009c0)="044a00b3", 0x4}], 0x1)
mkdir(&(0x7f0000000100)='./file1\x00', 0x0)
chflags(&(0x7f0000000040)='./file1\x00', 0x0)
accept$unix(0xffffffffffffff9c, &(0x7f00000002c0)=@file={0x0, ""/503}, &(0x7f00000000c0)=0x1f9)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f0000000080)={&(0x7f0000000040)=[{}, {0x22}], 0x2})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0xffffffff, 0x0, {0x0, 0xfffffffffffffff9}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x18, 0x2, 0x0)
setsockopt(r3, 0x1000000000029, 0xb, 0x0, 0x0)
r4 = socket(0x18, 0x1, 0x0)
dup2(r3, 0xffffffffffffffff)
setsockopt(r4, 0x1000000029, 0xd, &(0x7f0000000000), 0x0)
msgctl$IPC_STAT(r0, 0x2, &(0x7f0000000000))


openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
clock_gettime(0x4, 0xfffffffffffffffe)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)={0x3, 0x7fffffff})
r0 = kqueue()
kevent(r0, &(0x7f00000000c0), 0x30, 0x0, 0x57d, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x4d}, 0x2, 0x0, 0x0, &(0x7f00000007c0), 0x0)
r1 = syz_open_pts()
sendmsg(0xffffffffffffffff, 0x0, 0x0)
dup2(r1, r0)


mmap(&(0x7f0000400000/0xc00000)=nil, 0xc00000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, 0x0)
shutdown(0xffffffffffffffff, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x23, &(0x7f0000000140)=[{}, {0x5}, {0xfffc, 0xfc}]})
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x802, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000340)=[{0x44}, {0x1d}, {0x6, 0x0, 0x0, 0x1000}]})
syz_emit_ethernet(0x3e, &(0x7f0000000040)=ANY=[@ANYBLOB="aaaaaaaaaaaaffffffff"])
socket(0x18, 0x2, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r1 = socket(0x2, 0x1, 0x9)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
r2 = socket(0x2, 0x3, 0x0)
getsockopt(r2, 0x0, 0x66, 0x0, 0x0)
socket(0x6, 0x4000, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x400, 0x0)
syz_emit_ethernet(0x17a, &(0x7f00000001c0)=ANY=[])
r3 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x10215, 0x0)
ioctl$VNDIOCSET(r3, 0x81946467, &(0x7f0000000180)={0x0, 0x0, 0x0})


r0 = kqueue()
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0xfffffffffffffff9, 0x9, 0x8}], 0x0, 0x0, 0x0, 0x0)
kevent(r0, &(0x7f0000000040)=[{{}, 0xfffffffffffffff9, 0x8f}], 0x6, 0x0, 0xbc, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000140)={0x0, 0x0, 0xfffffffe, 0x0, "100000002300000000000000000000000200"})
writev(r1, &(0x7f0000000200)=[{&(0x7f0000000240)="7f", 0x1}], 0x1)
close(r1)
syz_open_pts()
r2 = syz_open_pts()
writev(r2, &(0x7f0000000180)=[{0x0}], 0x1)
syz_open_pts()


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x4, &(0x7f0000000000)=[{0x6, 0x5, 0x3, 0x1}, {0x80, 0x0, 0x1}, {0x2, 0x0, 0x0, 0x148}, {0x0, 0x69, 0x1, 0x400007b9}]})
r0 = open(&(0x7f00000002c0)='.\x00', 0x0, 0x0)
mkdirat(r0, &(0x7f00000003c0)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38/\x00', 0x0)
mkdirat(r0, &(0x7f0000000000)='./file0\x00', 0x0)
mkdirat(r0, &(0x7f0000000440)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//file0\x00', 0x0)
lseek(r0, 0xfffffffffffffe00, 0x3)
r1 = getuid()
r2 = semget$private(0x0, 0x1, 0x300)
semctl$GETZCNT(r2, 0x4, 0x7, &(0x7f00000003c0)=""/96)
r3 = geteuid()
r4 = getgid()
semctl$IPC_SET(r2, 0x0, 0x1, &(0x7f0000000600)={{0xff, r3, 0x0, 0x0, r4, 0xb2}, 0x8, 0x96, 0x5})
semctl$GETVAL(r2, 0x0, 0x5, &(0x7f0000000440)=""/206)
semctl$IPC_SET(r2, 0x0, 0x1, &(0x7f0000000280)={{0x3f, r3, 0x0, r3, r4, 0x0, 0x5}, 0x57e1, 0x9, 0x15})
chown(&(0x7f0000000140)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//file0\x00', r1, r4)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


getgid()
mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x2802)
ktrace(&(0x7f0000000100)='./bus\x00', 0x1, 0x4000010e, 0x0)


getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000000c0)={<r0=>0x0}, &(0x7f0000000100)=0xc)
fcntl$lock(0xffffffffffffffff, 0x7, &(0x7f0000000180)={0x2, 0x1, 0x40, 0x3, r0})
r1 = socket(0x2, 0x4001, 0x0)
r2 = dup(r1)
r3 = fcntl$dupfd(r2, 0x2, 0xffffffffffffffff)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r4 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r4, 0xc0106924, &(0x7f00000001c0))
r5 = kqueue()
kevent(r5, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x0, 0x0)
r6 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r6, 0x802069c5, &(0x7f0000000140))
close(r3)
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r7 = socket(0x2, 0x2, 0x0)
dup2(r2, r3)
setitimer(0x0, &(0x7f0000000200)={{0x0, 0x9}, {0xffffffff}}, 0x0)
getitimer(0x0, 0x0)
setitimer(0x0, 0x0, 0x0)
r8 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r8, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x3e, 0x0)
syz_emit_ethernet(0x138, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000040)="ee08665d19ac14d5e5134876f197a7728420aef6171504b1c3d4b3830c921bf0817a0000040000006a89dbdf", 0x2c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
connect$unix(r7, &(0x7f0000000000), 0x10)


r0 = open$dir(&(0x7f0000000040)='./file0\x00', 0xae828e137847f62, 0x0)
setrlimit(0x1, &(0x7f0000000000)={0xfffffffffffffffd, 0xffffffffffffffff})
ftruncate(r0, 0x40000000007)
truncate(&(0x7f00000000c0)='./file0\x00', 0x5ffffffffd)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x112, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x70e, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1003, &(0x7f0000000000), 0x4)


setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000000)='Z', 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$inet(0x2, 0x1, 0x0)
getsockopt$sock_timeval(r0, 0xffff, 0x1006, 0xffffffffffffffff, &(0x7f0000000000)=0xf)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000100)=[{0x48}, {0x3d}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f0000000000)=ANY=[])


msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x100}})
r0 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1000, &(0x7f0000000000)=0x1, 0x4)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
r1 = socket(0x800000018, 0x1, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0xffffffffffffffff}})
r2 = socket(0x18, 0x2, 0x0)
close(r2)
r3 = socket(0x800000018, 0x1, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x7})
bind$unix(r3, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


r0 = syz_open_pts()
readv(r0, &(0x7f00000012c0)=[{&(0x7f0000001200)=""/1, 0x1}], 0x1)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0xffffff9a, 0x0, "b07b1f660000000000002000"})
syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000040)={0x0, 0x0, 0xfffffffc, 0x0, "0fdbff0100000000000000000000ffbfffff00"})


syz_emit_ethernet(0x2a, &(0x7f00000000c0)=ANY=[@ANYBLOB="000000000000ffffffffffff08004500009078ac1400bbe0000001"])
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
socket(0x18, 0x2, 0x0)
sendmsg$unix(r0, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


r0 = socket(0x18, 0x2, 0x0)
close(r0)
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x10205b1a)
open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)
select(0x40, &(0x7f0000000000), &(0x7f0000000040), 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000340)=[{0x3, 0xfe, 0x0, 0x10000}, {0x81}, {0x6}]})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000400)={0x0, &(0x7f00000003c0)})
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000200)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
write(r2, 0x0, 0x0)
recvmmsg(r3, &(0x7f0000000880)={0x0}, 0x10, 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
kqueue()
shmctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{0x3, 0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, 0x0, 0x0, 0xffffffffffffffff})
kevent(0xffffffffffffffff, 0x0, 0x3, 0x0, 0x7, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
mknodat(0xffffffffffffff9c, &(0x7f0000000480)='./file0\x00', 0x2000, 0x3ffe)
open$dir(&(0x7f0000000a80)='./file0\x00', 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
sysctl$vfs_ffs(&(0x7f00000000c0)={0x4, 0x1, 0x2}, 0x4, 0x0, 0x0, 0x0, 0x0)
mknod$loop(0x0, 0x2000, 0x0)
openat$klog(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0xe8, 0x0)
clock_getres(0xbe44501372635004, 0x0)


r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7949)
writev(r0, &(0x7f00000000c0)=[{&(0x7f0000000080)='#!', 0x2}], 0x1)
write(r0, &(0x7f0000000040)="ba20e80000007c60e1016745b65369db00000000ebbd07a90172c84c838b4278ad535c39413f308cbbaee4ffcb7f31dbd1562ea77b6a0a", 0x37)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000080)=[{0x4c}, {0x1c}, {0x8006}]})
syz_emit_ethernet(0x1db, &(0x7f00000007c0)=ANY=[])


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
writev(r0, &(0x7f0000000b80)=[{0x0}, {&(0x7f00000003c0)}, {&(0x7f0000000c00)="3cac8c4a60cbf30796ccc02c5fb8a4c42bebe1b976774671c31e63cf1e1c485be26a9c1dc54ed0e826d98223f8a73f35e659097592cc60493adee48fa37e530bdfe0dfa7e96c51629799565d50435baf3fc69d7f7a2b816dcd00b5a1781d640762c9ff19846ca67734ef2537c522a53771d1208e4e07785e578af71fc69b3161668dbd3f400a1da35d059f2a377633a6939161992e78fb0756e89a6f6e06f898e9bc33d5660af666fc71b52e75dc71d624e58552fc12c3cdc36617c0a27fd15b44236d58ed165b1dc2914d9a49e60aa8bd1e0d2ed3341d19169099f1f86100b51460d905d9d78f8dec3a6be7d377720d36ed2d38c125db770faf55ed7f442d", 0xff}], 0x3)
execve(0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0xb, 0x4e})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f00000000c0)=0x5)
writev(r0, &(0x7f0000000180)=[{&(0x7f0000000200)="1900c983bc080089a43c5356a1ba699f85af8189f282097564d6085b8d1c5ad4653b7793e17f55bb087b46871c054bc156dec5e8eb8fa578bca8f7deef3089880d6a4c172bde731ecf018aee3bd9fb3df20ef0164ac9411bd43ba598b527b0597b475ae889e2aaeb53", 0x69}], 0x1)


pipe2(&(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff}, 0x0)
dup2(r1, r0)
r2 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r3, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{0x2c}, {0x81}, {0x4000006, 0x0, 0x0, 0x3feffe}]})
r4 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
pwritev(r4, 0x0, 0x0, 0x0)
socket$inet6(0x18, 0x0, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
getegid()
semop(0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
ioctl$WSKBDIO_SETENCODING(r2, 0x80045710, &(0x7f0000000200))


sysctl$kern(&(0x7f0000000000)={0x1, 0x4a}, 0x2, &(0x7f0000000040)="1aec534d", &(0x7f0000000100)=0x4, &(0x7f0000000140)="9ac468a6", 0x4)
socket(0x18, 0x3, 0x0)
r0 = socket(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x80606949, &(0x7f00000001c0))
ioctl$FIONREAD(r0, 0x8218694a, &(0x7f00000001c0))
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x14, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
getpgrp()
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000380)={0x3, &(0x7f0000000140)=[{0xb1}, {}, {0x6}]})
syz_emit_ethernet(0xa2, &(0x7f0000000600)=ANY=[])
openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x8981, 0x0)
r2 = openat$tty(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$TIOCSETVERAUTH(r2, 0x8004741c, &(0x7f0000000080)=0xa)
getgroups(0xffffffffffffff84, 0x0)
r3 = semget$private(0x0, 0x4000000009, 0x82)
getegid()
semop(r3, &(0x7f0000000140)=[{0x4, 0x7f, 0x1000}, {0x3}, {0x4, 0x201, 0x1000}, {0x3, 0x1000, 0x1000}, {0x0, 0x7a5}, {0x3, 0xff72, 0x3800}, {0x1, 0xdb, 0x800}, {0x0, 0x0, 0x800}, {0x3, 0x8000, 0x1000}], 0x9)


r0 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r0, 0x0)
r1 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
close(r1)
accept(r0, 0x0, 0x0)


r0 = open(&(0x7f00000001c0)='./file0\x00', 0x200, 0x0)
mmap(&(0x7f0000ffe000/0x1000)=nil, 0x1000, 0x0, 0x10, r0, 0x0)
msync(&(0x7f0000ffe000/0x1000)=nil, 0x1000, 0x6)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000340)={0x3, &(0x7f0000000080)=[{}, {0x5c}, {0x8106}]})
socketpair$unix(0x1, 0x0, 0x0, 0x0)
bind(0xffffffffffffffff, 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f0000000000)=@file={0xd1653077bafa0115, './file0\x00'}, 0xa)
mkdir(&(0x7f0000000640)='./file0\x00', 0x0)
chmod(&(0x7f00000000c0)='./file0\x00', 0x21e)
chdir(0x0)
symlink(0x0, 0x0)
open(&(0x7f0000000180)='./file0\x00', 0x6d84b028b6b26ff2, 0x0)
r1 = semget$private(0x0, 0x7, 0x3c0)
rename(&(0x7f0000000540)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000080)='./file0\x00')
semctl$GETPID(r1, 0x3, 0x4, &(0x7f0000000680)=""/8)
semop(r1, &(0x7f0000000280)=[{0x1, 0x7, 0x1000}], 0x1)
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f00000001c0)="5b93acdc113e638da9b78eb68cc10c", 0xf)
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x80206979, &(0x7f00000001c0))
semop(r1, &(0x7f00000002c0)=[{0x4, 0x0, 0x1000}, {0x0, 0x420}, {0x1, 0x2}, {0x0, 0x3, 0x800}, {0x2, 0x204}, {0x0, 0x4}, {0x3, 0xfff8}, {0x4}, {0x2, 0x7e7}], 0x9)
socket(0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000002540)={0x0, 0x0, 0x0}, 0x0)
r3 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000140), 0x1, 0x0)
ioctl$WSKBDIO_GETMAP(r3, 0x8010570e, &(0x7f00000001c0)={0x0, 0x0})
semctl$IPC_RMID(r1, 0x0, 0x0)


sysctl$net_inet_tcp(&(0x7f0000000040), 0x4, 0x0, 0x0, 0x0, 0x0)
openat$pf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000080)=[{}, {0x34, 0x0, 0x0, 0x3}, {0x8106}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])
setuid(0x0)
r1 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x20, 0x0, 0x0)
syz_emit_ethernet(0x46, &(0x7f0000000200)=ANY=[@ANYBLOB="7bca7e58f7cd00000000000086dd609f284400102b00"])
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x462, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x35})
syz_extract_tcp_res$synack(&(0x7f0000000040)={0x41424344, <r3=>0x41424344}, 0x1, 0x0)
syz_emit_ethernet(0xbc, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0xae, 0x0, 0x1}, @tcp={{0x2, 0x1, r3, 0x41424344, 0x0, 0x0, 0x5}, {"d1c2f0bfe2d0786ca28e44289f59aba04d62ff16e6bb47f1cd981d0cf5f225560531db5a3a6c3cb3d5ac50e0eec7423f3ef5e3c4a13f81f14f843a32b529e4649b57d581159522ddf03a6cabf358af4e1ae7ab79a9aac6417859ae29d8de08ba3da1e6387381a61f166b78d7ae58ccd15a08555c8e7db3e261cbba4f565ff3567edfcacd1a43"}}}}}})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x2, 0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x37}, 0x4, &(0x7f0000000000)="71f91e3471ac0058bc5a91501d942400b5e1a0757cb9af769c7afec37082", &(0x7f0000000080)=0x56, 0x0, 0x2e)
syz_emit_ethernet(0x344, &(0x7f00000006c0)=ANY=[@ANYBLOB="9b2ba0d57a98aaaaaaaaaaaa88a80c008100040086dd625106480306027fedc9b0879bab0779c90f44bab0a0c3dffe8000000000000000000000000000bb882200000000000004013f0000c20400000001010600000000000007fddc4dd1ad718cc35b9db09b4f2cb22d77d606f29b446451c681cd20efe2e5b9d4ad51c03c33a307da9574f05a33266766a24d88c1ed596c0c2e39724f51c51ee45f977607c55a266e11eee5d3315c0ac4fa7678a77fe9f94f765c17ac248a3a474160d0c095e929c23b0d0e4282c113459f87cdd0f9d699f7325058587f9e8738fbd93047f6fe917fdbe20e4ffe82d0ebd62bd7af21dbd226e311cd535cab60ec7c99ebf24e4ed86398805c597b26c3b7ff5e68b9d796f3d191e418146fc517cdc6088ef4134a9beafa7891ad4e13ef82029ec90779cbcd794c38c0dfa0dbcc0f44ce4b4d6d3e0a185df3899a3de0ccdde73497e0b970c50518ddc142dc00000000000004240000000000000101000001003fc9dfd9425f6a504277156139f74ce95c0ae69cd7137b06c286796dd24b8613bde38c37bf99a6f475cd4c6cd895fd6df5f477b6e727d7c0f320f3a6d16e77b17014479090e7490c1e0cd0ed452090b24218095852dfe728d48e320a4d8c301fb4b6dbf0c2f3b3722b8851920dd13824b307fc0a9422c6ff79038fc893a247f36aa6d771f94811828f41481b0437d5f4c49784b0d5c20588320f7d5613442d59cd96713c2e96f5b77ae582aaf17fb24ef1e008101acfd733bcdd44ac2978297a9a82384ae017b2b5f1df21014b869dca69ddf36363dbd57660cbf579c4db0fc673679a8d92066614f3102b4627a6a4ec01cb71f061ba614f11b4e356ebcc97dac5bdb7d6fce915e7f5cc6d06a09a67aa33c1fe3d0b289dfd000100000000000000002e000761680000000808000000000000c20400000006041e478229b6af4c61183d01740d67bcbc6b3c72d3be2a191efbf3964338ee55010400000000010a00000000000000000000000100010400000000000000000000003c00e020670000004e234e210008907878bea237f1a1302eef3693e0b9be0efd5755acffd7a96c940338ce67a10ef642fdc47f1e79b5f391ec7440c5939067d6e014a5702aee2d9d04a916b1b2955b6891d6164435ccc22f2a233ede9cf4194774a929d20c2ce2f65ec60114c23ffe261363bf901ad3e246860e5dc498bf428245d375bfd6cbb11df35b8bed0f58a2d1757bc23609bcf0083f646e23fe8f778944e87c9dc1cad5f63a9aeebbb5e172a800f9e4daaacb92f7a289bb9ed53e2bc7947732a92b6db276ff023e424093d933f2e0c7eecfaa808f26a377a851b6857d1ef663885b9f80442fce8099c736d3ea0c88982cd5d6eaaeed94"])


r0 = socket$inet(0x2, 0x8003, 0x0)
setsockopt(r0, 0x0, 0x1f, &(0x7f0000000340)="15337ac0", 0x4)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
r1 = socket(0x2, 0x3, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r1, &(0x7f0000000000), 0x10)
write(r1, &(0x7f0000000240)="14bdfa5d1d34e2fecb284a6498307dcda9aec43050036123339a346f737850551408753f95b7688ad4c4e1dd5489e7bafc58d3e5823757ae8b630719ef187ccad995f13dbe19a6dd4e6902bd8297b0799b426aabe9fad9db6996571c6d9f8bb5d542c2148aa42be940970fe88d34d8f99afe7e7820237400000000008000000100"/138, 0xfc7e)


mknod(&(0x7f0000000000)='./file0\x00', 0x6000, 0xe02)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x6000, 0xe02)
ktrace(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0, 0x0)
close(r0)


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x80, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0xffffff1f, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}, 0xf8ffffffffffffff})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x8040691a, &(0x7f00000001c0))
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x0, 0x0})
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[])
sysctl$kern(&(0x7f0000000000)={0x1, 0x30}, 0x2, &(0x7f0000000080), &(0x7f0000000100), &(0x7f0000000300), 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r2, 0xc038694e, &(0x7f00000001c0))
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000140)=[{0x35}, {0x50}, {}]})
syz_emit_ethernet(0x4a, &(0x7f0000000400)=ANY=[])


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x9})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000380)={0x0, 0x0, 0x7f, 0x0, "bddbf448105300"})
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)
writev(r0, &(0x7f00000002c0)=[{&(0x7f0000000100)="b1", 0x1}], 0x1)
readv(r1, &(0x7f0000000140)=[{&(0x7f00000005c0)=""/200, 0xc8}], 0x1)


mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
chroot(&(0x7f0000000100)='./file0/file0\x00')
rename(&(0x7f0000000080)='./file0\x00', &(0x7f00000000c0)='./file0/file0/..\x00')


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x33}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x18, 0x0, 0x37)


mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
kqueue()


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000200)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmsg(0xffffffffffffffff, &(0x7f0000000700)={0x0, 0x0, &(0x7f0000000640)=[{0x0}, {0x0}, {&(0x7f0000000540)=""/239, 0xef}], 0x3, 0x0}, 0x0)
sendmmsg(r0, &(0x7f0000000500)={0x0}, 0x10, 0x0)
recvmsg(r1, &(0x7f0000000680)={0x0, 0x0, &(0x7f00000029c0)=[{&(0x7f0000000000)=""/203, 0xcb}], 0x1, 0x0}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$FIONREAD(0xffffffffffffffff, 0x4004667f, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000180)=[{0xc0}, {0xc0}, {0x810e}]})
syz_emit_ethernet(0x26, &(0x7f00000002c0)=ANY=[])


syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
msync(&(0x7f0000001000/0x4000)=nil, 0x4000, 0x0)
sysctl$kern(&(0x7f0000000300)={0x1, 0x48}, 0x2, 0x0, 0x0, &(0x7f0000001440)='\x00\x00\x00\x00', 0x4)
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000)=@un=@abs={0x0, 0xd}, 0x10)
setsockopt(r0, 0x6, 0x8, &(0x7f0000000100)="77b3d8fa", 0x4)
listen(r0, 0x0)
r1 = socket(0x2, 0x1, 0x0)
connect$unix(r1, &(0x7f0000000000), 0x10)
sendto$inet(r1, &(0x7f0000000100)="18", 0xffffff36, 0x195a05e282d6161, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
accept(r0, &(0x7f0000000040)=@in6, &(0x7f0000000080)=0xc)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000000)=[{}, {0x60}, {0x5ce}]})
syz_emit_ethernet(0x76, &(0x7f0000000140)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000003c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{0x84}, {0x3}, {0x106}]})
syz_emit_ethernet(0x36, &(0x7f0000000240)=ANY=[])


semget(0x3, 0x0, 0x0)
mknod(&(0x7f0000000440)='./bus\x00', 0x2000, 0xd00)
open(&(0x7f0000000040)='./bus\x00', 0x70e, 0x0)


setreuid(0xee00, 0x0)
r0 = open$dir(0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000000c0)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000280)=0xc)
fchown(r0, 0x0, r1)
syz_emit_ethernet(0x5e, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x80, 0x0)
open(&(0x7f0000000100)='./file0\x00', 0x615, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x2, 0xd27d43220c7df9b, 0x0)
getrusage(0xe1d2eaee4b21a314, &(0x7f0000000380))
socket(0x2, 0x8000, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x41000}, {}, {&(0x7f0000ff0000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil, 0xffffffffffffffff}, {&(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000004000/0x2000)=nil}, {&(0x7f0000004000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil, 0x3}, {0x0, 0x0, 0x4}, {0x0, &(0x7f0000fff000/0x1000)=nil, 0x7}, {0x0, &(0x7f0000ffa000/0x4000)=nil, 0x40}, {&(0x7f0000004000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil, 0xfffffffffffffffc}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ff9000/0x6000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffa000/0x1000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000004000/0x1000)=nil}, {0x0, &(0x7f0000ff0000/0x10000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffa000/0x3000)=nil, 0x8}, {&(0x7f0000006000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00', 0xfffffffd})
r2 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r2, 0xc2585601, &(0x7f0000000000)={0x3, 0x0, 0x0, 0x0, 0x0, 0x9})
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000080), 0xc)
r3 = semget$private(0x0, 0x4000000009, 0xa2)
semop(r3, &(0x7f00000000c0)=[{0x1, 0xffff, 0xe5ce97ab354d96be}, {0x4, 0x4, 0x800}, {0x3, 0x0, 0x1000}, {0x2, 0x6}], 0x4)
semop(0x0, &(0x7f0000000340), 0x0)
msgget(0x2, 0x2)
semctl$SETALL(0x0, 0x0, 0x9, &(0x7f0000000100)=[0x0, 0x9, 0x8000, 0x7, 0x1, 0x0, 0x5, 0x401])
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r4 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r4, 0xc0106924, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000100)=[{0x45}, {0x14}, {0x6}]})
syz_emit_ethernet(0xe, &(0x7f00000000c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
sysctl$vfs_ffs(&(0x7f0000000000)={0xa, 0x3, 0x13}, 0x3, 0x0, 0x0, 0x0, 0x0)
open$dir(&(0x7f0000000b80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x200, 0x0)
r1 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000300)='./file0\x00', r1, &(0x7f0000000c80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f0000000dc0)='./file0\x00', r1, &(0x7f0000000ec0)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mkdirat(r1, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
symlinkat(&(0x7f0000000fc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', r1, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000980)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000a80)='./file0\x00')
getpid()
ktrace(0x0, 0x0, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
unlink(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000080)=[{0x30}, {0x5c}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000300)=ANY=[])


sysctl$net_inet6_ip6(&(0x7f0000000180)={0x4, 0x18, 0x29, 0x36}, 0x4, &(0x7f0000000a00)="1091fb7d1209aaa39ef08443", &(0x7f0000000200)=0xc, 0x0, 0x0)
openat$null(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ftruncate(0xffffffffffffffff, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000000c0)=[{0x3d}, {0x44}, {0x8006}]})
socket(0x800000018, 0x1, 0x0)
open(0x0, 0x0, 0x0)
r1 = socket(0x2, 0x4001, 0x0)
r2 = dup(r1)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
listen(0xffffffffffffffff, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x1, &(0x7f0000000040)=[{}]})
write(0xffffffffffffffff, &(0x7f0000000000)="76e5de000001", 0x6)
r3 = fcntl$dupfd(r2, 0x2, 0xffffffffffffffff)
close(r3)
r4 = socket(0x2, 0x2, 0x0)
dup2(r2, r3)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
sysctl$vm_swapencrypt(0x0, 0x0, &(0x7f0000000140)="118bea625d95de8f92c010baed45ec4bf03ace254b57973bb6de7b1c90301e9d3b5e6fb6ffffffffffffffff76c775a2a4e0556565a830032eef776127fd247103c14ab0a1cea9b4593be484f46a02ea73e910d041c5777bd852e57d3248832b91d06fe47d126022a1654859149e9486306d2f11fb1cc826c42f81b0d114f8af4ceb029a5210bb6947464bf678ba1d64a2", 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r5 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r5, 0xc1126939, &(0x7f00000001c0))
setsockopt$inet_opts(r1, 0x0, 0x1, &(0x7f0000000040)="ee08665d19ac14d5e5134876f197a7728420aef6171504b1c3d4b3830c921bf0817a0000040000006a89dbdf", 0x2c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
connect$unix(r4, &(0x7f0000000000), 0x10)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x1, &(0x7f0000000300)=[{}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)="03000000", 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000001c0)={0x3, &(0x7f00000000c0)=[{0x5}, {0x64}, {0x4000006, 0x0, 0x0, 0xfffffffc}]})
writev(r0, &(0x7f0000000240)=[{&(0x7f0000000340)="ebebfd510bbcdda9b489e9775d3e", 0xe}], 0x1)


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r1 = fcntl$dupfd(r0, 0x3, 0xffffffffffffffff)
ioctl$FIONREAD(r1, 0xc0206921, &(0x7f0000000200))
openat$vmm(0xffffffffffffff9c, &(0x7f0000000080), 0x10, 0x0)
sysctl$kern(&(0x7f0000000300)={0x1, 0x36}, 0x2, 0x0, 0x0, &(0x7f0000001440)='\x00\x00', 0x2)
r2 = socket(0x11, 0x3, 0x0)
sendto$unix(r2, &(0x7f0000000140)="b1000501600000000000000007000000330002000000000000f96ecfc72fd3357ae320b37b673039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa5b236de351e2f0ac3ebbc257699a5f139b672f4d335d223e7d026ba8af630037282102000000720fd38bfbb770c1f5a872c881ea6e69e0bb76d907c400000000361b12e19ef6c8cd6d25c95aad79c76619f0ba57aea8c500002002fbff0c2300008abfba0900000008e371a3f8343712051e", 0xb1, 0x0, 0x0, 0x0)
r3 = geteuid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, r3, 0x0, 0x0, 0x0, 0xb2}})
socket(0x0, 0x2, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x3}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0xffffffffffffffff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7, 0x3}, 0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r4 = socket(0x18, 0x1, 0x0)
close(r4)
r5 = socket(0x18, 0x2, 0x0)
setsockopt(r5, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


execve(0x0, &(0x7f00000002c0)=[&(0x7f0000000100)='tap'], 0x0)
r0 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r0, 0x8028698c, &(0x7f0000000100))


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x6})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x33b9)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x0, 0x0)


r0 = kqueue()
r1 = kqueue()
pipe(&(0x7f0000000240)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
dup2(r1, r2)
kevent(r0, &(0x7f0000000000)=[{{r3}, 0xfffffffffffffff7, 0xa5}], 0x9, 0x0, 0x0, 0x0)


syz_emit_ethernet(0x72, &(0x7f0000000100)=ANY=[@ANYBLOB="4544f333d470aaaaaaaaaabb86dd60000000003c2c000000000000000000000000000800000000000000000021"])
faccessat(0xffffffffffffffff, &(0x7f0000000000)='./bus\x00', 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x4001, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
sysctl$net_inet_tcp(&(0x7f0000000080)={0x4, 0x2, 0x6, 0x2}, 0x4, &(0x7f0000000280), 0x0, &(0x7f00000002c0), 0x0)
socket(0x18, 0x3, 0x9ef)
r2 = socket(0x2, 0x1, 0x0)
connect$unix(r2, &(0x7f0000000000), 0x10)
r3 = socket(0x2, 0x4001, 0x0)
r4 = fcntl$dupfd(r3, 0x2, 0xffffffffffffff9c)
setsockopt$sock_int(r4, 0xffff, 0x1023, &(0x7f0000000080), 0x4)
shutdown(r4, 0x1)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
open$dir(&(0x7f0000000a80)='./file0\x00', 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
socket(0x18, 0x3, 0x0)
clock_getres(0xbe44501372635004, 0x0)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
setsockopt(r0, 0x1000000000029, 0xb, 0x0, 0x0)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
setreuid(0xee00, 0x0)
r0 = getuid()
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000340)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000140)=0xc)
chown(&(0x7f0000000200)='./file0\x00', 0x0, r2)
setreuid(0x0, r0)
truncate(&(0x7f00000001c0)='./file0\x00', 0x0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
writev(r0, &(0x7f0000002980)=[{&(0x7f0000000140)="67fbf80100000000000000000000000000e4ffffe14f36814f6c923b296d11a0b21e64", 0x23}, {&(0x7f00000029c0)="240100ffbd285e00fa4d747d55ac3b710e82f18b29b567232e", 0x19}], 0x2)
execve(0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047466, &(0x7f0000000200)=0x5)
poll(&(0x7f0000000040)=[{}, {r0, 0x40}], 0x2, 0x0)
ioctl$TIOCSBRK(r1, 0x2000747b)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f00000006c0)={0x0, 0x0, 0xffffdffc, 0xfffffff7, "ffff0d000300ef01018b00690200000000000400"})
writev(r0, &(0x7f0000000480)=[{&(0x7f0000000440)="ff", 0x1}, {&(0x7f00000009c0)="7208d2879d7ae4e2eb75ba85b9a88add94ebeb1b2608c200150214c90d", 0x1d}], 0x2)
readv(r1, &(0x7f0000000140)=[{&(0x7f0000000000)=""/201, 0xc9}], 0x1)


r0 = syz_open_pts()
ioctl$TIOCCHKVERAUTH(r0, 0x2000741e)
ioctl$TIOCSBRK(r0, 0x2000747b)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x8000, 0xfffffffe, 0x5, 0x0, "a79df021e9db403d3536244351bb500382b4d4ae", 0xffffff41, 0x1})
r1 = syz_open_pts()
ioctl$TIOCSDTR(r1, 0x20007479)
ioctl$TIOCSTAT(r0, 0x20007465, &(0x7f0000000040))
r2 = syz_open_pts()
ioctl$TIOCSETAF(r2, 0x802c7416, &(0x7f0000000080)={0x8, 0x1, 0x2, 0x10000, "efc608bbe0c44c4575dc3cbade7ca79d2f6a0e12", 0x0, 0xffffffff})
ioctl$TIOCGETA(r1, 0x402c7413, &(0x7f00000000c0))
pipe2(&(0x7f0000000100)={<r3=>0xffffffffffffffff, <r4=>0xffffffffffffffff}, 0x4)
ioctl$TIOCMBIS(r3, 0x8004746c, &(0x7f0000000140)=0xa637)
ioctl$TIOCCHKVERAUTH(r1, 0x2000741e)
sendmsg$unix(r3, &(0x7f0000001580)={&(0x7f0000000180)=@file={0x1, './file0\x00'}, 0xa, &(0x7f0000001500)=[{&(0x7f00000001c0)="0e67a71e3fedcd5bdda9c779c4d6c41e339e6e07dca31f76621ec5bc11bbd805c5d3accc686122487a15e996d6ce843e16df91440ebbd1e6dc25fdfa7c358967b3647642ddf332e8cf4a6fa1599bd7cc222fd6706a8c3330d89e0b7ce8e94862c3e80dd3a81832e8bd43fcac9bd45e0f947c8d5be76e9784ae3daa457f0b4edb9444a1fbc5177d0e0fb75a4b24f1fbc35507f3fe66a95b90a1757118e24da53a6e3d6133", 0xa4}, {&(0x7f0000000280)="b8aea73618c098957663982e", 0xc}, {&(0x7f00000002c0)="7e4e9d36de42ab800a4cb0c3d1a35ef10ba877d77c062c67870f3aa13f63de56f0e9c79592aba57d7101815b12112b89c5f7971399e54f670450d75b053f91b447705fad2401ccbb95b6e8a58b2a0cc47c84310f92b4cbea57d179b019145a4101f4c2f6855f317d5b5f8a6dc39e7ebaa234a5f7ea3e525a7a65d2ca320bf7bf1c0272ad3d328c9e732e8c8d078d56d73311882e0ec492ec8abd1af8a877fb0f8fe431bf78a64329142e330f703eb31ab11f9e49c7c751123bacc1cab499ef4cdc2574992a3348130a3fdd3d2d3911ed66cc6842026f5d827e99b9298af8a3f0fb6d5a57c32321", 0xe7}, {&(0x7f00000003c0)="91186ec565371703bc4245080c086b2a43d072ce7e5dd02933cd09ddb6b0ba7e52a3d564c2df2ad00aee3960f67f2ea2b86a19547d1b7c6afa8cb8a8866d0dafedcc8c98ec91c65d0fbbc938eb4f6ed7680c0b09228418c760c8d80eb65b3cc14046886c357fe6bd5f26b5e0e19108db2cc5e24509886c19b39c1da5ac648ec91d5e566faf0ec5b0a0fc2a67a53674d3862dcebd04a0aca5f45fb49af8ed5c217d54c101b12409ada7ad701177e88313f8e98e20d951e374b22480c1bcc3919924c217e764c96b6d8df8383c7d084847cca1174ce2d290143e6406d9822a1700806d961dfa1295563a5d300101cc51211f6e813bf4e3d343f2653d7ea5e7e931fd306c67ecd6d9cab8caf81cbff8b30de36889d8529967f0a2c7be2ef1556a2f1350a41ae7b0468e6c3079a4b214c04ffadfffbdd35a63d80db533b96c455bc2e75966de6bfb2a8b2255d7dc99813063b7e0caf342472267d281d4ac869189dd15c93fe5972f3cc76e96e199a74bd2a05a6fd24453b4ce84f43e686060ecddb89ffd6840371431e3f130a2490c3373c96b5dc135c59ff88d4633a8d0e41738f52f983efa46ca9844b88e440402fd3e347d839353b6f894695acbae3dcd0c9e6bb884139ae555d6148344d84bac14940b493dd7712966be2e6312586ab9d967d2b4903f96078407360c29a25933fc8feacbb3798ddc17140804788fbd9f74faddae26fbd71328f45c72012acf6b30a4042aa5a767777cba0a8a30713c45d327e61d54a73df304b906396a8f10402d022cf9c7ea9467c4d6ba279663c1b8bc549d8c271910aa3927cc1b0f25913ceade15ec715209ce666885e2e579f8c38435c27c26a6302a5a4bdeaa1789e0b4f1bbcdae8898bd43675870947774974962c9244330d495247d84d8732e9f5fe08e8e9522b851e65cb37f2b70a9d828b61ae36095f7f6aec68bfc0749106b931f53efa0013ba1617f5f91f80c919cfa603fbe7e7a05efc9d29db6f38f10ac8fced5e8ca309aca1c22516f8ab0a0e985af3bdeb269a0ad867fef165e2a8e79fda12eacee00834d4436b42afb95c0c39b46901d0c3e8cb42ab1e6c5bbb5758a06a52288f3c63c47d529f79ca680f2c2e692fdc9c8c6418d0c31e2e94702c36dee448d1bf48735a189108418f76a3f43113b582e82998fe4e5a6fd1a11175898658e09dd740c0e630df47e7d1932588eca79261bdb4558d93edfa831214fdb0138f17792192b05fff9c9914aeea669467b351e21ce1d53a3806e89f5c5a00e1c26ac0ab1c40443eda7ef8756928ea6e70ba43b5176ef8896bde2863fa181478672aae77d9b4160ea39f5e8f3ce881dbcf224a931046a41203990bc26008fee2a444532df18ee4c49427da021aa32f8700c7cab8d87c899db0131533560ba53eaf6b9230449102bd57225777c5d92d25f5e15da23dc863f7e940ecff8e289dac5c69985c49a90d2e06b23464f208763b25813438e4177dad72c2b000b1feb593d6ffb270813069eb3b672ef104d595a2e27c7ac60cf84c7cba80e17ba25200d99770eca42f935131dc1fcbb051f8aa71537da89e78c9a08e67635e8daef1a5c27fafa1d2a4681edc050ba99b3bc51c018470c185db06dd243f2fe82988458357a87a8374a1a9508e70a4445441d5c03d0d4e201a73eec1d5398e1165471a2b33824f682513de7429265244b0b2287fa404af7dfaaf9c1e791159341c79de612fe70e4df76df8c03ff63a0e92cba77038674a70f572348c2e16dc0027894d9d157509b0b41b0401a8038b5b07fa509937ca1109d839a4007d99bfe227fc56dfe657eb2047b251728a0fdf3a0c7057426d5250557033ea07f9bb208d93adf3034f3802efb0ebfdc41f6fa7d9a8abcbfd4deedaad9da72b3b32432a6894e3adbd358cf55749a6153d20b025d38124fe5e4a9df072cd78186ea3dcfa7c177ba9415adba5a637caec9e2dd106dd18f5be1dd43baf7c4e6f1870ef9f132a4e1b57fbfaf5dd5270ce5e50f5b5377177a02c49c46b5dfd7bae4aa7aed8e085f565c75f4695edec075b34d4f2b48175e3086c9307db14a115e9695c081710e566c5bfe893231c18af9d5ffc0e15aa7de306d062c8d348f05ad94332f836ded96aeccc99429327e59d45c663669d1f51694073bc1dcfb8cec813139d7d762bff55201ed900626888d38c5fb2b40cf84f1f008e329f08a28e409e566386130b919a057f39e6b1b58e570f18beac2195229846cd7a041702cbc83d659b843274eb3fa4510aacb9810ae22eb9d89254aaa22e6e00c3a326ea9785121a0d16719d2551b9c2aabaa4264cbc7675366556015f6e1ff1e476dc1fee9a4f388a00e081079f07ab41f4d3ee2ffd7ec8f3ac56be143f13a10aee6770936f691acb1b8696a313c9a105d13557f21d0f0f7c73bea4a0d7ee0038b2c43e7c54c0fbb33c66030f24d4be3f12a78ce7557df8356113c0bc112be1b16d03f4a1e3a67a742b3dfdd3f6388a280b3366cd920439c1a3ac7b331b40bd099690b332697c079bacf4be84a8836ba73e5d27dde2a6973cb3dfcadcb17d9fb2ddafd063387faac8c40d4104b8fd71ae199d5699ec396e8659c0219e5d4175a7912122ab008b9b46d58821bcbbe5d3d2ef1dc7b6e6cc3f0d9f0f8d8ce5804d98c4bdb35944963f27625246c2ae853de72b9e472249e684940ce5aba9a5a8fc2ffd1af9a680967e7ef195d3a50d5113312c89bbc0ca881357f9a8ca29b36b04f930df718bc718b9fb46d6cf42f7ecd0e697d3ceba4974964b7b415a27d81227eb93d1a8157a357da3597e3abc1c813f5b14587a6637415f199433432c04d2f2926ab213cb566dfee7d4844e0ec77927eca73a66657041f7603952af758422724e935930d26becbbd8aa94227098d2a0039f747cba9d9e410a502e6a918d0526638242fe4db74c02af53d4b521a2615622e5f9c87ff0886bb8ee7e8b241b89604a81528db1733f6c56cd38999c8b29dac83ac916bfe0c6eef1d3e4e99afd2f91e1a2a7ec9fd9fa69bc83cb0ee2acf4594dfb2d4696d59448f3345a9165d33cc7dcffce2c87b0a04a0ab7188745af14e2d2d1a2a950a5a9452a9086b87bebcadb27482f45740e3013a78a7e93f9de0465b1a2b1da63ba80e14c5fe188fda108a0840d727b43dc6371bcbd1866bbd19abcd28fba2e548bff6be3095add98dc0e75a637244704b57fcb600a153ae233a024e76658d2114a1f519b4e82987d227884064417ddc5de9b0d12e6d005c33f25285373eb5b5de17b692f974f350a6ea91b52c7cdf0d17b89518d70533d8f764b34391b0f3a43cbbf8163b31490d65d8412b326daabbc166b0c96e6dc42715c95b16b8de8102fb5bcf11003486bb4dd38237158fe0b703bf8629be69269822e58c6d04eda85cf3661372d8c4ea7b0503ca736fddb807f16806d0d00756f5a5354dad16a466808c11f36a3dad8a6d49724bc8404045da9dc30e01ab2c2436461cfadca451fe62c404d3da2b717fb798a1bad2a6f660b2ef9e9a8539ea6b43772eeffdc225494b53a51078e9268b20c54ddbab9fd8960aefb0a6e5d78ed0fdaf9ff4f922fe2f5018cc8c7c508c44eee4d48a955b6d7d4a939f41aa8720dd59059f35f1bea02d2273a74e6885440f7dde55710bc252c00c5835f1eb2adc20b519b9e042fbb32342812daa2f5b0b38f325268ddaefb3eda80b1ca9755e7f113684f8570c9fd9d401bfe1ddb35f99641d693dee444c4beba8c1c6195abb435b904878d3bc2e5c5a8991e8cf2b2ba5123f69744cc59234d283d1b39108af241604a11a65f8d20c65b70f772394b7b8ba97ae3b39f6c33f7f7eb383d75f3ec647521fe71ecf75d1ab44e60cb22c40f9c6d309403b1406231afb026a9f9b17db5fa986de3599857a60ce0b332ececbe200c97644abbef9a4eec5565746bbe9719ae612147b09c5c96da065840350ee42168eb95d51697b175570331a0605233acce1cf2b2fa5c17913b8f2a1b307a89fafb86990a875c8e5556ae8abc2193a0cafcd968a239a07643809cc4ff32280d7b6ad76001443b43f246e9a7ee3abd1afba5b2e2775033f7dd4014a01365e5e8707e35d0d38bb4e1db531eb70b30c2060f69810bbc226830200c9bf775912cfae93017ad92d00390d6a72422600a6315e7d09a31cb8dd7586d80e3fcacacc39f9317bdde34698667cc7271ebf4192027cdfcf610952f1d445427bd98395d893c5829526a21e345e5588af036d3571956791e8b995ad3f02ae800e6216dc785f015664ac5051a5773d8151361104fed522d8a6fec4f2c26360257bd749c2836974dfe3585ddcbb490aa30b637386ae7c12795cabb439f6ba79791a7407f53176a2f1658289fed59c222b03578d27ecf114e227e7588d6b9b1231a810f824ac3fc62d751b7235c2739d6f27b97235cbb150d4664c6af93641e4903c3b27fb3438159e9f2fb9bdd071bdc767a18cabbd7f3ce10d8393fef75c7b3f29d839d8395030ddd4ee81c78478430e59ffb16283efef63acbb5a1c29b45c50eba0ed565bb26952a32f31f7a790632fe42ae940284c4b2fb67334efe6713a7e8608fc73a12b6799490d4f4e9f3cc0ed0342f2de501bef55ca0dfa5f4d90b9df1997d3986017a7a7fa5d055b3f73d43252c2f31e8c9c7605f87f124923b1dcf591c95aa6bbb790b986e137bab502e2ded9ffafa9004ab0c7ffca772c528df44e8a17169fc6a742e6829ce6c83f1ad5757c8414a20c0dd64c7743b8238350fcf03737865bf2cff1de596c9217870f89d8870056b40d1ddaac3f89967bfa8ce03ed4acbdc2230dc7df8ec39ed3754d9754c356422c1e6e04f76eca5f5e7e4a8576ba095493545d2ef44a9d2c09c7dcb2e628d49b531245fffe745e111bcee9b04cdba8f3d4e35ba59ddaaccf9dd168d8caeb6a8398270b6cc581cba4353724646579e561479fb0542f8dc3acf03d03276c69f6bb08930122ffa905cf75d1a13d89ad7a9b05adffaff1cfa43afa985bfb2c22409779c9bf95b14b1715e2d1c54ce2711d8cc05885cef2e3dbc6abb0a0780314510aeca83897601b9034298efb445eb75d94873dc6cc45eda2e9ab8ba716a452f84c88342e392b9f184925caee9ae3d792618c020d633bf9c8945e9ac0d24d27483b843115a897dd1d5e557ae73404b0d1c3da1d81fdbe049d6652c40530eba148326b3f3687238a42fd958eefc7b1c8cb4b73a3c160697af7c834faa07588ce48304184684056dba32b97a4d90d5af720f84793d8737419e794d48f6c58d8064dddbe85332f0ce944a606dfb5f815061265b8d03daa0bf43a8975a6f4eccc0605901ec6db9161b221c2a34cb9435044a3cff459c4def6ed2bcc53ee14b096885edc1ff59d635bac2ac164aef4abe7cc0f96f32c331238e17c0fbc7334f4300d5b5db40ca3b5856617cbac1ceb1eff0c10c4ab170fd1e06d6aded4654ee947a0aa3be5a32c1b9752e701363c4487303b2590ad9fdcd53488a47389989e20eca5cbb1ed2978125cbb0b12b81076b6641681eef63cc1ce2e7914d714575dc60e035f7ac324ce49fc897ccab8dfb954bb03b8e7f913821c09c0700b3daf63644436dd6d58817a0dd7ad331b4c85f791acbf54a32311764799c26ebbb2a72eb2955b4ed406646d85b3feb0628e606faa2d85c31000cb4c13becf88181c54770abc6b483f8426d53418d6549907bf2b6ba7d55a98e47cf5d0dcfedf2b8980fea06b25dff7e13a58c35355ff479b3d9e618b3e7c33bf7a9a3a3d087cc892cc87bf975150a8be", 0x1000}, {&(0x7f00000013c0)="930486b146e1d8996e156ea2fc6560d24348120708af435788f6c81958ac390f7be53ce0b075a3d896c23bb0e9e5521deb3c8de299913770a971d29f5a6d348d204c9e87444fe481920a318b0973f76af63781b6c358897acab5216d972fd321eabfae3e660f9bbb7e6b98e7b78af013369e72275560f65da6b350411c284cadbb220a96d52b49473cd697697065e5b506a04191b50c5744b9f5fbd9d438b90e24b720c3369adc3362661e28f288622c895164022794915b4c75b72f4f3652709e00cc1da60b1c29d387b7bce345863fae109f8894a835b439ef069c1d4dbc4cac802976cf638e59978b1e268abaaecddd3aead4d6079577", 0xf8}, {&(0x7f00000014c0)="3ab8f3aaa72482af83a848c59cc5aab70879fba9a4edcd8dfb583bce", 0x1c}], 0x6}, 0x0)
ioctl$TIOCCLRVERAUTH(0xffffffffffffffff, 0x2000741d)
fchflags(0xffffffffffffffff, 0x10001)
ioctl$TIOCGETD(0xffffffffffffffff, 0x4004741a, &(0x7f0000001600))
getpeername$inet6(r3, &(0x7f0000001640), &(0x7f0000001680)=0xc)
ioctl$TIOCGFLAGS(0xffffffffffffffff, 0x4004745d, &(0x7f00000016c0))
ioctl$TIOCSETVERAUTH(r1, 0x8004741c, &(0x7f0000001780)=0x2)
ioctl$TIOCSWINSZ(r2, 0x80087467, &(0x7f00000017c0)={0x9, 0x8000, 0xba, 0x40})
socketpair(0x18, 0x2, 0x1, &(0x7f0000001a40))
r5 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000001a80), 0x800, 0x0)
getsockopt$sock_cred(r3, 0xffff, 0x1022, &(0x7f0000001ac0)={<r6=>0x0}, &(0x7f0000001b00)=0xc)
getsockopt$SO_PEERCRED(r3, 0xffff, 0x1022, &(0x7f0000001b40)={0x0, <r7=>0x0}, 0xc)
sendmsg$unix(r4, &(0x7f0000001d00)={&(0x7f0000001800)=@file={0x0, './file1\x00'}, 0xa, &(0x7f0000001a00)=[{&(0x7f0000001840)="5f055cb142d1535c310f0b0acc0a70605fb0f50f3d5d535eece12beb0e8b3ae2748e922aae9494560e1a3cdc1efe1623b5e660248bf83f61cb8d9d793446b2c3fc2be91d0504076876ac9acb", 0x4c}, {&(0x7f00000018c0)="81080ee93c2f4f2fc17b416695bb84a6757afa0c8a095fa8d4c0658f943753635db97b22a7f8cbe0df86fded4dcd6d26b178dd285fd540c186b647de90be184dd5708d62c6c564861272f54fa13cd212b22a", 0x52}, {&(0x7f0000001940)="4cf87f6cc5e3150bdd1705fe7f4ef4d27abfb77b99ca354ef8468d8fa697d99063dc0191c4f401393b9a0b91976c6a9f6a16871ecdd4e6dae313f6df401e9290f88a536e79f1c976522aa68d717ca87b21e9b7f2a83677f544b64fdf55cfaa986c3ed408", 0x64}, {&(0x7f00000019c0)="717dd93f8effaf4679d98f7f0e7e3ba5e1351651ad37f7196575221359ff2e73e0f866d0f3d86f67676368a3b9", 0x2d}], 0x4, &(0x7f0000001c40)=[@rights={0x20, 0xffff, 0x1, [0xffffffffffffffff, r5, r0, 0xffffffffffffffff]}, @cred={0x20, 0xffff, 0x0, r6, r7, 0xffffffffffffffff}, @cred={0x20}, @cred={0x20}, @cred={0x20}], 0xa0}, 0x0)


mknod(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0xc0206921, &(0x7f00000001c0))
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x80206916, &(0x7f00000001c0))


openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x10205b1a)
open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)
select(0x40, &(0x7f0000000080)={0xffffffffffffffff}, 0x0, 0x0, 0x0)
select(0x40, &(0x7f0000000180)={0xa72}, &(0x7f00000001c0)={0xff, 0x7}, 0x0, 0x0)


mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
recvmmsg(r0, &(0x7f0000000480)={0x0}, 0x10, 0x0, &(0x7f0000000500)={0x200ffffc, 0xa})
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000158000/0x3000)=nil}, {&(0x7f000003d000/0x1000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f00000c3000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000157000/0x1000)=nil}, {0x0, &(0x7f00001eb000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f00000e0000/0x1000)=nil, &(0x7f00000d8000/0x3000)=nil}, {&(0x7f00000ca000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f00000f8000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r1, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0xa})
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)


r0 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(r0, 0x80047476, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x4}})


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000380)="190d", 0x2}], 0x1)
read(r1, &(0x7f0000000480)=""/168, 0xcc)
execve(0x0, 0x0, 0x0)


mknod(&(0x7f00000002c0)='./file0\x00', 0x2000, 0x5200)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
poll(&(0x7f00000000c0)=[{r0, 0x6e}], 0x1, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socket$inet6(0x18, 0x3, 0x0)
getsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, &(0x7f00000001c0))
execve(0x0, 0x0, &(0x7f00000002c0)=[&(0x7f00000001c0)='^\x9b\xb1}\xcb\x00', 0x0])
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x0)
r1 = open(&(0x7f0000000280)='./bus\x00', 0x0, 0x0)
poll(&(0x7f0000000140)=[{r1}], 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
r1 = open$dir(&(0x7f00000003c0)='./file0\x00', 0x400004000011830a, 0x0)
pwritev(r1, &(0x7f0000000340)=[{&(0x7f0000000080)='\x00', 0x8a8615b7}], 0x1, 0x126)
truncate(&(0x7f0000000100)='./file0\x00', 0x3802c)
preadv(r1, &(0x7f0000000000), 0x1000000000000098, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000280)=[{0x1d}, {0x64}, {0x406}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
shutdown(r2, 0x2)


r0 = socket$inet6(0x18, 0x3, 0x0)
getsockopt(r0, 0x29, 0x39, 0x0, 0x0)
r1 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSKBDIO_SETENCODING(r1, 0x80045710, &(0x7f0000000040)=0x300)


getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000001c0), &(0x7f0000000200)=0xfffffffffffffe50)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0206923, &(0x7f00000001c0))
r2 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r3 = fcntl$dupfd(r2, 0x3, 0xffffffffffffffff)
ioctl$FIONREAD(r3, 0x8004745d, &(0x7f0000000200))
ioctl$FIONREAD(r0, 0xc0206923, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x1d}, {}, {0x8106}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])


r0 = openat$vnd(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
r1 = kqueue()
open$dir(&(0x7f00000002c0)='./file0\x00', 0x200, 0x0)
r2 = open$dir(&(0x7f0000000200)='./file0\x00', 0x10149, 0x0)
getdents(r2, 0x0, 0x0)
kevent(r1, &(0x7f0000000200)=[{{r0}, 0xfffffffffffffffc}], 0x8001, &(0x7f00000001c0), 0x400, 0x0)
r3 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000240), 0x1, 0x0)
setreuid(0xee00, 0x0)
r4 = getuid()
setreuid(0xee00, r4)
ioctl$WSKBDIO_SETDEFAULTKEYREPEAT(r3, 0x800c5709, &(0x7f0000000140))
r5 = openat$zero(0xffffffffffffff9c, &(0x7f00000000c0), 0x41, 0x0)
fcntl$lock(r5, 0x9, &(0x7f00000001c0)={0x2, 0x0, 0xfffffffffffffffe, 0x1000100000000})
ioctl$TIOCSETA(r5, 0x802c7414, 0x0)
fchdir(0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r6 = semget(0x1, 0x2, 0x389)
semctl$GETNCNT(0x0, 0x4, 0x3, &(0x7f0000000540)=""/189)
semop(r6, &(0x7f0000000000)=[{0x2, 0xfff, 0x800}, {0x1, 0x4, 0x1000}, {0x2, 0x20, 0x1000}, {0x3, 0x3, 0x800}, {0x1, 0x5}], 0x5)
r7 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r7, 0x801169ac, &(0x7f00000001c0))


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
socket$unix(0x1, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(r0, &(0x7f0000001580)=[{&(0x7f00000000c0)='\x00', 0xfffffeb0}], 0x1)


r0 = syz_open_pts()
close(r0)
setrlimit(0x8, &(0x7f0000000980)={0xb, 0x54})
r1 = syz_open_pts()
close(r1)
syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000080)={0xf66c, 0x0, 0x9, 0x5577c513, "3cee7cae307e08001fb91b000000da64612c3300"})
writev(r0, &(0x7f0000000000)=[{&(0x7f0000000b80)="4b8572730e51a93601084c480dc1199dc57b2495e54e7209c4c7ad688b2768a5c2dc2606cb3396fe19b7684fece0172cf942aa0b7918b45b0efaf120cb28eabf16f7c5000b4159c5d1cc872d79ad1721703966da567664630f2106236f5650fdbfa8246401bb352764be4b6fa3ebc0b99a3665bc25216ba50581e8c9aff5a6691e97bedc672c5e8e3ed4bd372eb4db334603c9fb94a733c8f0455f4285c7b298e66cf9bebb66f447e2fa9afbb8108623ef393b169cbd255c6b3db0b76f90ed460706c5193c7b1f5066d2dbf51d6cd727629cd778450dcb36f693bb26b75e82299e4e39eeac9ae3122c7ddd1adc48621758141b0dca303454edf70ff1e66f574bfa184fe03fd13aadfdb7b196087edddc571ab8a8bf9d9676b2a22ba7e946a26377f29f53d461fbe5238b3ba135febe2821ce168c88fed545c6f82874285b00254d20ec65a168817dcd0157821d9c0c28d4790c62cbf67b6f71982c73fcbc5f943204b649b6313e879d2cd92c788aab06c014a89b3523de83b305e047a0d9ca6acb8bddb5de9aae120000f2eac0b8b83c9502f70f80a627d784037f333ed300c3a993e252ea24c9f5e1d12a5ab0ba3c0346992a80e1cb91283b459e5aeb7d2a03e0a55f27f2b0cacd8c62743f7ca5e9b0541d92a623ff7772df5ec5d228c087209b69c903b0b779defd39352daaffbc17424f5dd6480c80fb74ca117ef2a6870e590350b913d139afbc581ba6e2d87fd7a9b6e8d91b41afa9531e53a297e6474afc5c5e", 0x223}], 0x1)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000132000/0x3000)=nil, &(0x7f00000a0000/0x1000)=nil, 0x80400000}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f000008c000/0x2000)=nil, &(0x7f00001f0000/0x1000)=nil}, {&(0x7f00001f0000/0x1000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000132000/0x4000)=nil, &(0x7f00000b2000/0x1000)=nil}, {&(0x7f00000b2000/0x3000)=nil, &(0x7f0000fff000/0x1000)=nil}, {0x0, &(0x7f000002a000/0x3000)=nil, 0x1}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000086000/0x3000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil}, {&(0x7f0000091000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000141000/0x2000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000132000/0x1000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000008a000/0x1000)=nil}, {0x0, &(0x7f0000134000/0x2000)=nil}], './file0\x00'})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000800), 0x0, 0x0)
syz_extract_tcp_res(&(0x7f0000000200)={0x41424344, <r1=>0x41424344}, 0x6, 0x100)
syz_extract_tcp_res$synack(&(0x7f0000000040)={0x41424344, <r2=>0x41424344}, 0x1, 0x0)
syz_emit_ethernet(0x14b, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x13d, 0x0, 0x1}, @tcp={{0x2, 0x1, r2, 0x41424344, 0x1, 0x0, 0x13, 0x4, 0x2, 0x0, 0x233, {[@generic={0x2, 0xd, "96c729637cae4fa49c1558"}, @sack_perm={0x4, 0x2}, @sack={0x5, 0x1a, [0x4, 0x0, 0x40000001, 0xde5, 0x2, 0xffffffff]}, @timestamp={0x8, 0xa, 0xb018, 0x8}, @generic={0x4, 0x2}]}}, {"d1c2f0bfe2d0786ca28e44289f59aba04d62ff16e6bb47f1cd981d0cf5f225560531db5a3a6c3cb3d5ac50e0eec7423f3ef5e3c4a13f81f14f843a32b529e4649b57d581159522ddf03a6cabf358af4e1ae7ab79a9aac6417859ae29d8de08ba3da1e6387381a61f166b78d7ae58ccd15a08555c8e7db3e261cbba4f565ff3567edfcacd1a43a2f80b44a3727c2f46723f3826d9842357f4d467cb2e24ed586547d107e74cfe46502dde741762fe8ad6742200cf5fd16fcdadae4fd744b730286383e0444647e948151cb63c5c12b79f75a37762e3f013f189799eb699"}}}}}})
syz_extract_tcp_res$synack(&(0x7f0000000000)={0x41424344, <r3=>0x41424344}, 0x1, 0x0)
r4 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000001380), 0x8000, 0x0)
fcntl$setflags(r4, 0x2, 0x1)
syz_emit_ethernet(0x12f6, &(0x7f0000000040)={@broadcast, @local, [], {@ipv6={0x86dd, {0x7, 0x6, "cbe4c8", 0x12c0, 0x1d, 0xff, @mcast2, @mcast1, {[@dstopts={0x8, 0x1, '\x00', [@jumbo={0xc2, 0x4, 0x9}, @pad1]}, @routing={0x29, 0x8, 0x0, 0xff, 0x0, [@empty, @remote={0xfe, 0x80, '\x00', 0x0}, @remote={0xfe, 0x80, '\x00', 0x0}, @mcast2]}, @hopopts={0x61, 0x30, '\x00', [@generic={0x80, 0xb9, "44f94a03e6d05b56744bcc7494d65765677243e390522f36c6cacc615a14090a256af3332438d8c9bb7cc463117d53e055d8e29afd6532b77ca0ee825ca79c29d4f6fc4fdc53b2fbe01214ed2abd027f318c6bac4de360e8e1ba7e6c6f6fa5a8578593a59b3b1293fbca9e68d8a2ca2ca61bae879d04f2131246ab47592cb9f86d0fb14ccccf81a44239a82869c3b2f2184e908da082304e2d027380863a933fb3074b863ebd1ebfe230f779b0690c1592bac268c69d50b4c9"}, @padn={0x1, 0x6, [0x0, 0x0, 0x0, 0x0, 0x0, 0x0]}, @generic={0x1, 0xb5, "f2948f44e98cddc438b2d875924ac0c4e1822c87128c404ca7aff2d8f209b34e461cc21a3186058cc534158ef208df8fd74db74ec6d03d1a41c6e35d4292620a6840df072ea66f26441480e845659eba6fe78373a9d03d145eec08f57056de13c0a96214ba7347561bef6722326e4160f31c10d3320601a44bf2cc17a7b80db5f2fcb72d3a02139ba4d9516ddf86ef7845dc31f3ba02db94aab85147f777ea83c857acf26a810cb747a5a8de295b7a898e69069166"}, @pad1, @padn={0x1, 0x7, [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]}]}, @routing={0x0, 0x12, 0x0, 0x0, 0x0, [@rand_addr="1a47c3d9ecf6d9e681110e71aa428bd4", @mcast2, @ipv4={'\x00', '\xff\xff', @loopback}, @empty, @ipv4={'\x00', '\xff\xff', @local={0xac, 0x14, 0x0}}, @mcast2, @loopback, @ipv4={'\x00', '\xff\xff', @broadcast}, @loopback]}, @hopopts={0x5, 0x3, '\x00', [@padn={0x1, 0x6, [0x0, 0x0, 0x0, 0x0, 0x0, 0x0]}, @jumbo={0xc2, 0x4, 0x7fffffff}, @ra={0x5, 0x2, 0xffff}, @pad1, @enc_lim={0x4, 0x1, 0x9}]}], @tcp={{0x1, 0x3, r2, r3, 0x1, 0x0, 0x6, 0x0, 0x0, 0x0, 0x7, {[@window={0x3, 0x3, 0xa}]}}, {"25519b9bf62d4104ebffa0129a45c74375c7da5af43a77565503e7df9cad892673f22f8a175241ad5a65e438baeef3dd91a797e6abc24ee0f61e74c940daa6cd941c981cc0b3ecf8ce512e2133a242b5c562d672dfcde899c9b0e3351a69b0302dc6dc9b0826850b2a094cbb794ed13e8d0ba7d51e9e895f8a4c58845e9c477ecfd462c2729625e28d28416ef10cbb78d6a2e44eeeccef4c515594890b6aaea10df999d60c23f243737724779122b4601524b5e926e08aba131b09cea33580d1066580da17e9df243ff5384758c44f8237905330412e3b3b35df85acc22ae1d2d71755d8010b289f33a91c65ef3181003767d22a2a10a2e69a75a09f6a76df96f651474886a59973477e2060cff855e15ccdfae50b135843fadfa16c6931d26fb37d3078ea825b97ae5c81dea9e2b3c4ce83482615776df2f9629bbe1a7bb8324f78eff85051389ea3130b006e04d04fdefaa311e3e74b33884f4d4db272f30836b52bb545ee57a1510a6afadd46da758fe3a3561e066ea6b3761963ab57add771a4e2f2de77556d5ec0366942783c401f4590cf4b08182c3455159f52d6c8c5c419f11d36efdded8b209b3104e826eb1e58cf3aeda05fd34921017896c6912abf2218cd89f903968fb383f8c9da00e5ff2b427600856fe5f57bf1b68b5c5143aae714fac59f626346e93a72d15d0c0d98820c886ce1ccd5cc9c08ab22c39e2c70cd52fa2f3a9f776862c2304c72c3297ea89968b4aebea7292655f7dd1d773c30d0b73586d7e049b494ad3dc3db6c14518b8d56b343dae39ff1f4abe6a18adb8f3568b3ee8fc3d319523482cb418141a75c8f1270fabeaf325dfd5eb39934f5a07a969a3e24ec36332961e8927ab668cf110f1ff0bd44aca538ea07a7666d4e68bf6ebba95fb3c90b97aed3529e343f7e088a8eb52c584c8bd28a7743e946d05cb86150823701e67d63774842958b8e289b8cd1ea1f88a79e6f55b59ab51853b1faf3d86173ab8adc96dd7ac768041e3566f8376b12598ee3e738e2941159cfb961eeb50c2568fc0d37e9e3c346d427e68e3603c6b5ecb3b8da7345dc7fff1907325818ac5f253f4cf1139acdd623b45025b779dab9f4b29372306666cc43c98efe82b15194d3fe9c616daebb2d9fafcc8401f964c11316293a417067a5ad442ba7638e61dce30d8cbc57e4dd68a1c243615f93c490765e48baf29ef8aad87793eea516b8096e052e52bdcc57097a91c29b5fa2ad9668e615d596cb1965ea69e6ff89faa24c54f209261693e95a2b3cd2b0e584321651ac2ba756c94e0ad184b76e01dae0edcbfb5f97d3f87b143925cb00ca4438ce6b8935cbb02aba359dc2435351d2bf42c1d9b1096933fc752aa836555111decf1a5f00f6fa88d1754076c21859d6afc17fb84f19517a5bd05179154a3039bd25529d5123d63cb98b0c9941d8ab6df2a4a377d4540b782d026b1d72d76c46b80c326f614e69aa605f00e2d669f34073de508466176afa4067b142f5d1758237c179c97a8e18f80a0d714996e17ec699c625590063ac12cd74b346c63730d0702db1afaa956779a87b95128f965c8fce6408dec00beb3e11bcd456202d5759c577b0972b834a9be9cf45ab617ad1e6798ee01d7bc3125aa686793cf573563d3e7c30f4e4fed2fd357436ba713a64d313f6e96bff5f29210bd04c79e1478171d59e9dfd595cf58792b009da9f619a086925049eb397b342a4719e6dd35373428f03ee66119c10119a6ac49267a411fb71929826f6afca4c2706b4be7e4da60e03070d0b8bd9909564a1a1ad32769bb371bf0cd000c96b19d245193435cda9968c7a4c42e6290aa62e46551c1865afcdba64960f053ec93112657e3649cea15f53cc6d336c9ef9fe0b9a366ba3e38681a89fbd87006372db3fdf3457d8cce4457c857ade3473a98992cc8eba781f50dd2f956dfea0bd30354fcb2fe63746103648c2169b50f171510b54866355a2dea9ee99764df8993106c9897e122f627435a88da40a57bd337aff54cba5e35902b81a2189bdb03be2af66d6367a1cd1ce29648a553225f1fe22cce348df67865d3a7b43a3cb5016294c900d41cc75ff03479fd10c1a734962cda78fdb846d5d4d158ee4f6f78d282ffa6cc5a796434c284311c33ec3cd4c781957f88a6c2d7f2887fcce026da25fd20ba99ec66caefcbbd481dc48419bb0f3264e70075d88879f69d84e54fe4b505d071c59ee8c726a778e9cd4c39706ffc79aa652db414ea2a55020d384bc4dbd1954cf5c134cb6d41d44a7fa3c0faad69f2b664b7976308339d7ea1ffc4e3340ecd68bfdea0092e56609e96204ce4c0a6890954fae06502a87831499477db2bbebb2b8bd967b34ca25166a6762f0dc10923c133ad315f3ae290dfccee6a46e03d000efb29b92dd132a73e6cbd0335218b48b2bfbe9c61178609c8d6d69163e10300fdea039680dbfe023b12cdacf4f9bb2131cd6b8a34747e57dd580ee88dd86a3095421cbd0f8c49b8b91bfd8daf56025646ea38019d1a8203c39fb2e3d22f76e84e9a4726cb4aff1fd2699cc5bca98e664bcb27865ce480524fa867bfcd94ff39797eddedbb0fcc92f6dc6b5669a5c61f771e0ec56318365e82034fbba46d04beea15b115a8ef5b1a8582dde1096dd527df5700a45c251878e04b3ca3dd815f072708080ae44da19c6513761e3783de71a1de11a036542b3206e80710a0d153b7bf61386f8d5f189db5081ccb31bacb9f64cef283a5fbb4cceb628ee62534eecd11b4891abe2d8f4a59276ac1a18178c63cd7d6d13b12df1590953c970f1824d04565be2200d21afa95fa309ba07b0623b6364038f0bec68cebc2879d36880a17b9d9ae8e805bb7d8e0a7a8b46461001a35d20c6ae2afb7cb5ac1b7c8916d80f8b3ba51d9dea9fd185c78f2e542f20193b673283daf212e96d40c9651c72f3e47771fd7fee65d28fa4f607a0ef453c1d9a2772714b39fe11581363be428ec956cdbd18772fa259c777ab5ff7c807bfeaa3e72cc73fdab77dad775b9a816f68e9fb1cbcddb8427d26096a4df566edcb3b3fe278de0936e443f214a635ad33d54503730c6e8d6eddd04ff531177809d4b0e2cdd255d49a7a42a9aed53e1970340189535f3bdf0e7c00f3c8f3379839f379521d94bfc12f1cafdfc58fc5e05a04ee1861b77d00f91837dbbb0e21167b5a13e2540561324b94a5c443a620bc75f2621af8fae038593002d2351e1856e3fabcb5b570b0db962ec8795cf11ff9491611f056f8b2a4c2546e62807d4fcea1cb633a87246b2e154b3c5ef230a56c655f30f8dba19a9199d2359b991a99b4b72507014d2aa0c6354b4f6525e48f7d75e94571bcf2436a10d48aa317ec3eb4a2b42ec5703e3148d8c3960172da9c1ac07543d44759987beecbb4a34743b7641955cda5ae9422ab0047a22090e649ceb5e163d32cc0548f050013b0b8c90ccf0994cdb6e45f629f10d3c6f084f1ec5e4855c3513ddf2de4ca4c239bd78de5d4f7c3b2f7fa5da5fe31960a04a6933010ad2965ead39e43039c49e2011626723d1e411f0bfa7bbbe342ac39a55b2d182f2bb7d50af6dafd3724d46ff5450f5a3c682fe9ae0921353ff3a5feb9fa24806ba5cfccd8fd471c92b48bd45bf0090b3710d679df6dc40c64d1b4ae77b54aee4051efcfba9669457850c5f59b02fbebac1cc79a935ddf30a57d01a1f1c313ed013459a1a49b3512a682b2d95adfb02ad58e778ca39283a16e658c8a37bf9376548db240696a8edb1ce8a9485d90a12ecc3bd9b0ab06cb338a8dd738f46dac5f2a58fecd3fa32d83877e90ec982830d58f0ad27b8a459d0c8d8d17592714770c9b995f628bcf5b8f05f9d84b72507cbaf31e33f8aa7d051e079b47f99af7720f543de0beceb3d716e77c57a075519cf91edce9684862b1a77ae7df3bf7a74bd3a51363459217680829c112fc2fd773a52103dc99a2dd4bae98b2677e1eca8429ca7069b83c0e450044bcf499c7ac32bcb95f1e22e96cbc094bae636a99eab5e9663cfeeeda97ebc4057c098f6986d760699a65d123c0f89c900df589384223b7609f7fe2938e3d1889d67fd4d610db69d1fbf10e57154b11a9d54a2c354bfea974eca068e39c442764c2d4ee0bb40e621720f0edc78ed6bcf16824073b8e350e932b6bd18c4ca05ccd5dc373d20e066017505fff1a6943f4b9d2cdf5117db7ae4a785044387d89081c6218bb7013522baf50c725d3c901a467c88fd9be4ced967a6962073f0416810cd34fea41ddaed728aa0a866d63d583162e1e78305c9a6aafff3fbc9408b740ad7afb90f3c1b41bdd3ae11929f2790719fd87038020c3d1ee76c62ed7820a2f79e4d50256abb058218e2360b29ab44332dbc7f83f5add426ae3c409f688b0c0a594916480c05df307a85b0ae95652cf06b2b6aeea979e078c206f70c7fdbd2fc0657deacf489c5f2090882eecb4c47d0b2fd438cefa90470ea1c7ca0c9e31dec634a9a61d3e5736ba4a657fd5a7a8a9f918704ca455a24fb407efab8331d34f0db65dc00a377ae12b5bc6ff2f6c7d46d9ceffb436e5fc079570f1049b507cea766cab28d5c1a88d3dc205f3d6bb1ff76da8ec4f7a048aa7b96290319061a41d8c1011ed695f7bb9d253190d0d0b38a10fe40c4357ed3dd930277849299ae65c01a71ab6a061312a75827bca02321444cec5d323a46bce50b43d9c6ce985817e00f148f953fddab6f0216f71acdda012cbc0de70f9c9ba0495024cf2148ab09bc0897b3c4adc54fb1f534b0c6ca72f2aa885cf880ccb9402076aeeee21515f7c9019aee5855e3dc00a68ba124d13ac56e128e49bb5537267d08a48c53c31b5083900c89be501b74aa62dc4b137c9a87d8c299e4391d327be72b9394017c16bae2602a7dad27cb50cea1ad8136b7bcd645d023f95022deeda81aa3d598e6c84071c59a2d6c4124ecd03877f4819e76225bfc198e174d36b1c79de2ae88f1be383ba4297f7048967a1c7a94f58c0661e9586b1184c7c9e6d0ee43d25a65aad6705fed257de525d4e5529902792b36d8e9f2fcf9d2c3458107ca3c5c7b4488b3a31a7e6814437f7977ea17c627035ea29e94790ca07454194541f5228ae76c25eade51aab1f4ea8a1e3af9f88b955e90dc6cade02ac99e54604fb5f10df1523e8dda4a416c34ac1e6713ce88418e09b597879171c2e0648302c36d19792955843253ab72b3b4665ab93f5f3ebfb5ff075e7e300f908f6c244212d6b37ba39e78a4e121e8e1e03eec62f67cdc3239669907161dcb092727183422d5a8aa01028ab8ec9daec0ede9e8d0f6a0ad8290e52ea9036f09271d155595d6ecb518ce74bc528596967b520cb092567df5d008f38c4dc9c2b8e3c4da7d81ca9b754d38a94b62b4ce3712383f680986aab3c5412d7f441d4fe878ec34e65e3c61a94c2e32f58050cdbf772eddce64d3ea8b99d6f6783a8da9436fb48c19e50e031aef2d1da08b6fa587d3466c0fa66a8395f35baae636d91f15e020c8c81d10a27e9b2543c460f6ee595a30dca0fbc86762a12122a68b7a278c7ba2f18119aaed9556e9d62195a6ac210702be0ff204ea543446f356a0ee618282504016a419542e5ff850f8c35715f3d43e44bbe63757878a362691232d3e2a69be997f1ce9955bce475f6e6208a0fc136f0b0318eaae86dd8b4bd7e8cb6ae75a26150065e99b3cf155bc45a2490ff8c7772889f008b327d885690c85252f8acf988488a7cdea12075c1fbe7ebdf440660b902b3c33681cac04f57f8132d"}}}}}}})
syz_emit_ethernet(0x65, &(0x7f0000000240)={@empty, @remote, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x2, 0x57, 0x67, 0x3f, 0xff, 0x0, 0x0, @multicast2, @loopback, {[@noop]}}, @tcp={{0x2, 0x0, r1, r2, 0x0, 0x0, 0x6, 0x20, 0x0, 0x0, 0x0, {[@window={0x3, 0x3}]}}, {"8faf4805575c42aa863c11af645ec7b5adbc373d85907784624acaadd00dbb9768a81d5e7e311c"}}}}}})
ioctl$VMM_IOC_RUN(r0, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0})


open(&(0x7f0000000100)='./file0\x00', 0x615, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0x0, 0x0)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x1, 0x8)
fcntl$lock(r0, 0x7, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x1000300010005})


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r1, 0x80047460, &(0x7f00000000c0)=0x6)
writev(r0, &(0x7f0000000280)=[{&(0x7f0000000a00)="918db972f599c02e0565eaed008441dd285e11922f9103f3c18b5e92e496724e488417d1a4aecff3b316656215acb1ba3469e19579f44495b29b07fe40f1d77a39c53e17b28fc542501c9f02c366a9f9679e03513078c8c0bf397f4921a869eb7160b5c6561c003fd67da318f79c2127e7f3c500d169439ae30e39631480864c6bda469ea7e1ecf2e6657adb0036e6931fe3cbc836dcd271081509c32878b2da5d1ab56161436bee33e0cd772d065f1708afa86d57e24a7bea15250c3faefecb4e2b152ba92f6978d8ef7b597faa894d911cb44ae7a71d96593feb079580679d13808303d5049b8b6f11f143f3c81ca0732a03ca4916376e135557348ef5df6c2cba44a39e9d7fe27157ed537227ae5a9590c77f5ac9b9832dd57c60b937113a7ab702d20f45f76460ea7a679b4c54bfa3c005d6965256c37a4583048b5a2aab5d7a8ac18f24c92c93b8a1c764eb4586d562119f8267feddb033f5eb6593166cb966d02946ba52fe745a9eb470cdaa87d7f1629a7df698a12cb59881d8a91e201ad99b44512b810c452fbcb78d3f32f6d76f48a084a44e9941341c6aef84efcfe31104258a6e26073ee8bed10494f667aafaf2505b0722b53583520170a7ae54e0e80e191074d167f17eeba58fd2401a8845bf37d609f74bbcdeea50df8dad70ea9f7108a9611d7eb57b83615b110b4ecd122f41ffa6e0d618e4759cbfb864b3f7d95da051be0458ccb08720cedec863aa80732717ee640ed88052be9a38830269b7cdfea83ba8ebddc1a989dfe1356a7e55d19721cd233aa97687c901746d1ef5c49d028bdea5061311fb81b8312f32e5ed8e52f7432bde05960d96d19241d7148ed50739429604429b21f56fa7713fcbcbf8ffbb49ae1489d2ec834ae31cf30cefc206484ce94cb79117ad2d8a64528afb6f143995c033a84c2efda865b96cbc1587fb2f4ae79eb5e136dfd0997d576ee762349e532ee540be32df7a6e7f67c760c1486c5c46f832d89b499e91ce9648a5e9df83530eb5762be1ff26151eabf5cee46618c2fbddb137baea87c520cd53b568a7e57cd22593bf3facda0eec6868837390846b9413b6e55ba2a21ed06d639f47b4839c39ee6df1bcc7cfcca9178ec0ac1d5780663cfe53d9d2682385141e1d02b4a5c5d2012ac9c83e0a477e49eb0158a79bbc58924c9bb97b911e14e149f88fe719c34cb95c6a458977989e5cec2a902def76269d36f2e980bd7fedd668dc0e2fd1f3c6c3d9befbda2d80e2ebf7cd9d0744b2ae0fff033987d09fa2bfb312c559599f1064913b96a3085735c1cd14bcfe3902c154ec491393e9eeec8fcecdb509632d2797d2abcc9c73e70636bd3e10a9eff051a33fdf73a3ad25f6575829fa3e3f05fd72adca5a74f3bcb2e96fe3ea3a0a045f54e432e26f3f580cf51b3e6e680b675b3d12cda2aa6f769404de58dbf2160b83110e52914340d07696635bd3ce97a620ca9609e7cc4a5173b05571b9572855042a6c59974b990fe7315d4ef882274fcc231be8a4b860169470b48f26ac16c344887cae2a245015954c5b1b42574e7b927077c1377933f6d20bbba799e0a51d1c1969e48b146740fb49dd6051a81b5485fe1d89b083b84082568e35dab66b79dea4848248dabc63eb6040c864bfd468ed578586cc3bfc3dbe978351145138fea623758dbc4ed437891baf5b67b44165e1c7eaf9e0e5252bc5001ea4d5ee4cf9316932f3a13c44e426d101b53ecbf29e05da752c63be86c91803461b30438b2951b504c57887fe570e3ce4def823d0cb3807a013308ad4f9c5c80ba2399db2f305111f48ac7244ecce02ec418d794644f0c4d041310bb1bf383df624a4402add9f52a33252855e18e8bb553e503dab370a7a554e59bd61b8bbdcff41b51144232d7d5bd6d32b7e80e3e8261c370b28e9e8d847bc5a05333d7efed0cfabc7c3e28f4956d364da97036435ab025c1d7dde0c890a26ab5ae010578a09897ea92982918352f65b19a73e55a07491ea807b3d7b096d4dc153223badd7619970ff7b2cfa39f23e025e59111f089012382e1585b7038ebb1634e7729476453f89572b670218bad37a9d6413022ddc2cd4a7e113bc0a282ececebc26d01e9f9fbc837ea1ad04ddafb4335d2888cb150c748ae39c8de3f09a6880df3419dc51a1dd3126921f2451b4a61978c0889496c0ab9dcbd98ad8bdebe5205a4a238b41fdea7c6a97e730a344e4df30a8179067f163e34628504c1dfda646411001579e40795b410a8ceead37bd99166eadd61a6daac078a0603f4bfd8042a21285c240010f4d16abfbf72ad8ff9ad5a9d3e259a39e436ee3ad26523d9fae2c0bb4b9a6655a8572820979e3a172446ac741b4d8020ba5f8f5a6ad6cf6afbb303cae09309a3d0043bfc5f8b798721269b78808f2a4f0be7b0e9d72fb2ab835552b1ddab02af3dd4b319e20e819cf7e74e2bb71d797e8a4abb06620a16b5732dee7699063b6e23f20c0b7418d71098a32a88711e7035f90eb6cf8328baaebb0711cc00c1c295ead8889bf0370ade93db8694fc837b8551f97085a0a1e319acc443ec0a7386caef796fd43bdcb5e282a04811c25407fc8dd1a70715d5c07026aa949ab5eac9834ef0c98dd54119585a59e504ce63696634a277a122d02ddc29192db37b879540b5db47eb27f88f870c42f70157203cd7b5592076fcb385be4b15a0de7ca07fde4c9210d365159a5c3fdc714c60af8f7a205bd7cfd5ec73c5fd3fd26a341f68d1450c82573018340222d3c1324d42568a565e92b970cb4119da54fe8b558d89e6cb4a10b58f3455f055039b961c8dd0c4771bc58bba9479374b08fcb6dc5fb554011273d34b817fc84ff713487dd224d365e7c9bc9258e4ec42bc6df7fe9aa5703dbbde6a5eb718d0944c29125501f555873323f8d4ebf87e1d0b04ddf9408c00f80879a2014de98cfffdf476c9dd30c13900a53086beb9a2de451d59fbbc4fd02477ec8744f0c113a60933115c06b2122178b9a7cceef7a1664d9b72c9d8714c88adc469e64e1a9f73b511b6fcd7924f1d7363e566f6b6e18ca0f52fc566fed4ae5ec7a37130f1c3b1559719e4fbb6be12bf1725a534e00ec050dc96c644a7153e410496baa9684d57542aafcbeaea04e8cf12965beff0382c540c1d564d635b6bc10e422c1e5b3ab724f23ca0ffc76e1da984e31ab30e50d315bed73082e3791baf3c5d19e4ab9d8df77d18045c807fb3907cdeaa1afc7b7b43b203eb8785f4d791d429380bd00602de24ee8728e9b157ee95a58a1152ac35f70df6bd57a1233a3a4d06075688f0656b36bbeb72cf065bb31edbac27f35cbaee649d7cf54b64b3350c29495dcf4255f8dd8e686bf248eedb376fb00faf8c2ac7c533e32eac9ceaba14b9eec7bd9b7cfcd287f6455dd335f923751bd967b763c7912c2a839281c88d47afc22cd93981c4b2c773dd638ca65555ed7941a1287e45e04d04ae8f05aedc3cfc66be9d4a58a555aafa2fbaebc7a5e23766e885916685079637613bafd020ba3a9edb670c8b2365634d932518a49c380b05b1dc965068036edd10de14003e8ce9f8b50f3e2d44521f86bffd03c4e37f02498dba98dd5051b1277d3dc57c35f7acf6de1d2f5f4c85ff463211ec437a5b54e48925aa6b01598a6c010fa4fb689424d9d001a7afc19d2a848e1c284effc5f79a709dc3f95222031b90d6d018df866a6d2be04343ce26e27fa1c8a14c8cf19e723e4a120eb3e0cc290ddc2ff4bd359616d8d033d843da2a45d87423c00eb2f9a5e745da9671cadbd8825655dbaf9b34b2f56657a5683e6af96b44db827dcdce6e8bdfb78e9f1eae83c3ad87f482dcaade4a655721b1673c53b6b0a08e688409db6e6ff387e4182f736b6c43899c1fd87581880946883c046dd9b049134416212155bcf3ad80432aca3c67d3777c3fb94c07759debe771f85a93cee0c32754222ee8b3df8f09eb18643dd53b54d97a39bbb1db11fcf8002dac118226948ecc439cf71649836b59ec4cb99d8dad51bc87734fb3ecdf5d3dfa8a337f2d5e705bbed7e830e4cd5ea8cdad680727d77b5cdfdc461e2bbb766a366f9c108a6085ae207569976b86f5c20269f596a04320a639aa42445ce0239277f502cf340e9a62cfa77975062ad64a9771f70bae6e0d14ba502ed7ab35dd3da65e9788b208fa8b475cb642114609f5bb5034c008008ea7171c3dce25a05c1d871a760c8c632bf28caa7dc6801ef6e54a5af043ab6aa31272c198f9ece06a7c1e74c13ea23cbd012bb1dd38ebc0e7b46688005b78d65af3e85e0a8f3eb86047c6f83db91e28dd59b90aed2ff3d3cc3486a6d9997dcd0013cae0bc230c74e4a4d5482f199cd14700d11231434196f48e478ed7b162574ec96b2f03f3a16ce8ce977f71d23219d56cc2395fd60444e2cc1b1b58478f5beb6a5463d7265e391f7e3f8daa7bcc1b468da66d96eeeb7c0d3791a3ad618cc05832a50e9298e6a81cf518448bd1ea1aae859ab2dffcbf5e39be0e78f4b7baaca2bf3cafa92114d7c7f0cf159e2f4aae2404bf3aede2d0fd57e059472567a1819f64f8634cf995ef6cec655d18e60c85022d1945564fdcd991283694e695f149a8c219558ab19ec3f9112b22df2403aa1d9cb85a0763906ebb464490db271a51d7e1b4111834ee440f42adc1ccdbddf6942952642dc21dddd71edb8a95b5ad91058827f3603441a53b08983d578a27d64109ff2940bfbaf09d142840b462a338e12f76529a3a89c9d308fc113f20d4b67d7feab0dbf7a131b00398d3e74549ae499ea8c9beedb1fbc6db26aeea390aa6b00d894d17b6b5681437d26d52d5c0958580495848a8dbd38c3ad3a325d3f61b9c9bdf9c24dc1c42020931d1e2097f4bd725f8da76bccc1c9c343831f822163b08518724d08dee737085ae372cc5f6c60b03e0f50909ae57678e5ff557bfc8373fcfea61faa8809bb17f565af3c9392d3b4bd76b99a32ff07c091d49542aa48bac686992ca80ec750e8093222e7d8210cec7ece721b2997d9c51a4ec298d2014ed2f3e6a63297af839ba92e281d4ec6c9dbb358032437279eb6e2941972228d9939222a5c9e053389a85538880f2e4caf8b3db88232da0257cab88e98f56af503a0cd1539b860b717e39810c6cb8073faa55cdf5401ab0117976fbc68cf56e2707f29995e9b2b18e304d72004857f60aca7aee4570242b9a1ce97ff176ffa717a656a28a9b8a3fd061c3b9bb64983b44d4f7bad39fc638f510a988a3a4141354a8995f48a08b01aed8a75f8079778df1955cc56e4b3ec70de1b00348a2f8d14d53a17177e43485bb8ef931fd56e4702069d4ce7cfae1509d80c9c3e22cdde3d7a2c60ea758490169be8a8212011ec7574ae90812b3ef68a475dda62141792bb6157e02dada02aff15de5a8da43cb1ecf89d5827b640918e7e49f17bbd89e59fe99b6f09bc00f2d03a221f31fe7987bc19bace7bd5768b44c59c5a822ac84acf267b10de2ebc38c5b7bc14c640099b87741fe2df99889ca0ab42c0b5de84abeab58fcb9ebb75de897204501917c3a9673af2ff5f9ca2b57fc86c88ad98a602e4714b9a43f052b24b8be353a24542a2898372cb94cc5254412d96dd4f8dc494ea8b4cfa896cb30f7f908a97d6fe8fdc26ce351631e366286c889ff5639c9842e3dff2ea9ed150096db35c41d661e738e56cd9cf9ca10b00811e662ac57d15d001ccc3970f359073362a6c2aba5ebac19bb0dab90756414559dade6cc8a441749cfa8c20dd890a252e92a1404c2e", 0x1000}], 0x1)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000380)={0xfffffffc, 0x0, 0xfffffefe, 0x200001ff, "ff00f888494dea16574217c8ff2c0000004000"})
writev(r0, &(0x7f0000000400)=[{&(0x7f00000009c0)='\x00', 0x1}], 0x1)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f00000000c0)="b10005136000009f050000b10010000000000000cea10500fef96ecfc727d3357ae302b37b67ca1f2d61db7f4de57804be38164991f7c8cf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f4d335d223e7db3008b95665bc6fc2102000000720fd38bfbb770c1f5a872c881ea772ec5890405b3b9c2668396f4cd1257aea8c500002002fbfc0c2300008abfba0900000008e37f71a3f8343712051eeab71d89e000040381ecb664000000", 0xb1, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000000)=[{0x87}, {0x5}, {0x6}]})
syz_emit_ethernet(0x1b, &(0x7f0000000000)=ANY=[])


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000))
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000640)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000080)=ANY=[@ANYBLOB="18000000ffff000001"], 0x18}, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000))
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000140)={0x0, &(0x7f0000000080)})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x1ffa, 0x0)
r1 = open(&(0x7f0000000040)='./file0\x00', 0x2, 0x0)
ioctl$FIONREAD(r1, 0x8020697a, &(0x7f0000000180))
r2 = syz_open_pts()
close(r2)
syz_emit_ethernet(0xf9, &(0x7f00000003c0)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaaaabb86dd6000000000c3000000000000000000000000000000000000ff0200000000000000000000000000013c01000000000000000100c2"])
fcntl$lock(0xffffffffffffffff, 0x8, &(0x7f0000000080))
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x2, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000100)={0x9, &(0x7f0000000240)=[{0x1d, 0x4}, {0x1c, 0x0, 0x0, 0xfffffffd}, {0x8126, 0x0, 0x0, 0xfffffffd}, {0x9f1c, 0x5, 0xca, 0xfb3d}, {0x1, 0x60, 0x4, 0x1}, {0x7, 0x7, 0x5, 0x8}, {0x9, 0xca, 0x4, 0x7c5a}, {0x381, 0x8, 0x4, 0x7fffffff}, {0x3, 0x9, 0x7, 0x5}]})
syz_emit_ethernet(0xe, &(0x7f0000000100)=ANY=[])
r4 = socket$inet(0x2, 0x4000, 0x0)
setsockopt(r4, 0x0, 0x7, &(0x7f0000000340)="15337ac0", 0x4)
syz_emit_ethernet(0x2a, &(0x7f0000000480)=ANY=[@ANYBLOB="ff7800edd6e89f4368b5d068502559340956bb85c85e33e991571a4d2eeb98f588fb4a20818a67c355cc8a0cc9fb3b6e9add1a7ebe0c3cb23b7053d9849b3345de71eb9fa64f517833139efc48d022dde659949c0dbc1165ddf93147eaca1bb238430216d3707012d4d699839409fcfa177cbb7060753933d82c35fcac7b409ffc96570de27b1aaf93190bc895a2a224d4f38d9acc344021f14101b0617fc21e21789110fed42bcf7154bef718e0651f62a06fe8c1a2993b27c39d77be6c9abc83c457872f1e147802d98d9884ba3c95c3814f1117d4ebb7119724206775b877d121bda7202555580f9f645ab25c6e6a4ac9274fd96a299b391679b3dc262117eeabe7cb8f6602d60c30cbd2b20137671d7f342b195e2d740ba9d72d0090a38592a7ad0f8847e3ec5322361e31e425d5b7c1b94004d8cc2f02923c780f9646418608ff1999218549cdcc21d5323ccf242643265943fae794ec0bfb"])
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x2, 0x0)
mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x1, 0x0)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r5, 0x80104277, &(0x7f00000000c0)={0x6, &(0x7f0000000340)=[{0x25, 0x0, 0x3}, {}, {}, {}, {0x20}, {0x6}]})
write(r5, &(0x7f0000000200)="d81ad3d20c", 0x5)
chroot(&(0x7f0000000100)='./file0/file0\x00')
r6 = semget$private(0x0, 0x4, 0x1)
semctl$SETVAL(r6, 0x0, 0x8, &(0x7f00000002c0)=0xff)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000180)={<r0=>0xffffffffffffffff})
chown(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, &(0x7f00000001c0))
setreuid(0x0, 0x0)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000001c0)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000000)=0xc)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r1}})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4e}, 0x3, &(0x7f0000000100)="71f95f84cf71b59c7afec37582", &(0x7f0000000080)=0x2, 0x0, 0x37)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000003c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000240)=[{0x4d}, {0x1d}, {0x206}]})
syz_emit_ethernet(0xe, &(0x7f0000000140)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000140)=[{0x74}, {0x1c}, {0x812e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040))
syz_emit_ethernet(0x3e, &(0x7f0000000380)=ANY=[@ANYBLOB="aaaaaaaaaabbaaaaaaaaaabb88a82a0081004f000806000686df060400021f7ea8249a4fbd1e03640000000000004d104b5f4d6b5f2ea32b453c11f5f83c4d3fa01fd9f88aea11ad9180303fa7e62daa030bfab093b4b012219047fe138f1956d61bcb3612d890178b01fd92ef0b5c32a2d52b442bea2c36c3a0711c05f21f41fc318a0bb204ec0c5d75f17a2fdff9"])
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
mknod(&(0x7f0000000500)='./file0\x00', 0x1000, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000200)={0x3, &(0x7f0000000180)=[{0x24}, {0x4}, {0x46}]})
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000080)="35b5c242413c1026089a59583cc3", 0xe}], 0x1)
symlinkat(0x0, 0xffffffffffffff9c, &(0x7f0000000140)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/file0\x00')
r1 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ioctl$FIONREAD(r1, 0x8020699d, &(0x7f00000001c0))
r2 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0))
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(0xffffffffffffffff, 0x80206910, &(0x7f00000001c0))
r3 = dup2(r2, r2)
ioctl$FIONREAD(r3, 0x8020699d, &(0x7f00000001c0))


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETAF(r1, 0x802c7416, &(0x7f0000000000)={0x0, 0xffffff49, 0x7, 0x5bc, "225e00d1554709aa0900fa4ab1896c04aec100"})
writev(r0, &(0x7f00000002c0)=[{&(0x7f00000000c0)="d54f0d6b60d62ed63da253f47665e6cb7c3c5fe2b8157f9f3cb28bcfd1d7312c833573c79f7fc7a95e507f2eff5405ffa6482ad4b2054e22b66b3ec97ee7fb26213efe85d0cbde07c2ca0eebb5a24e5573d77c4cc3d6543c3593cff2ef5666f47d4b2a3f9653598a8c8d813ae7ccb51e9ca7d78a95b4d5d9a203978493d0a10d74be87e2c30c4b67f5437efc033258755fde55f707885cae7a90bf20a58c71bcdffae2472c04e95b5b6ac57a5d9948c05504", 0xb2}], 0x1)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg$unix(r1, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="28000000ffff000001"], 0x28}, 0x0)
recvmsg(r0, &(0x7f0000000180)={0x0, 0x0, &(0x7f0000000640)=[{&(0x7f00000001c0)=""/23, 0x17}], 0x1, 0x0}, 0x42)
recvmmsg(r0, &(0x7f0000000040)={0x0}, 0x10, 0x0, 0x0)
execve(0x0, 0x0, 0x0)


r0 = socket(0x18, 0x3, 0x0)
getsockopt$inet_opts(r0, 0x29, 0x26, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000200)={0x27ffb, 0x0, 0x83, 0x5773c543, "102609307e7be2df67de208c8bda64612c3100"})
writev(r0, &(0x7f0000000180)=[{&(0x7f0000000000)="5b6dda63c7a0e8d05275b7730abc44dc9165014e06811fc2083cfb56b854612e26916e3bdc7509652c8c6f0170ccba4d6c9644b86617832573180cef9f895c7b", 0x40}], 0x1)


r0 = socket$inet(0x2, 0x2, 0x0)
getsockopt(r0, 0x0, 0x24, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000000)=[{0x2}, {0x80}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
sendmmsg(r0, &(0x7f0000000080)={0x0}, 0x6a, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
execve(0x0, 0x0, 0x0)


r0 = socket$unix(0x1, 0x1, 0x0)
r1 = socket(0x2, 0x3, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="0002"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
bind(0xffffffffffffffff, &(0x7f00000000c0), 0x2)
connect$unix(r1, &(0x7f0000000000), 0x10)
ftruncate(0xffffffffffffffff, 0x1000)
sysctl$kern(&(0x7f0000000000)={0x1, 0x21}, 0x2, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x0, 0x0})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x18, 0x2, 0x0)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbdf13b9fd812eaa4e713048e69931929648", 0x14)
write(r1, &(0x7f0000000080)="04bdfa5d1d2873c63e3534825ba166e2fea9aec43050006123339a346f731573d8d508753f95b7688ad48b8cf6bbca325cebc37fc4e1dd543dbe2da6dd", 0xffea)
syz_emit_ethernet(0x40, &(0x7f0000000240)=ANY=[@ANYBLOB="aaaaaaaaaaaaffffffffffff86dd606aa63f000a2b00fe8000000000000000000000000000bb6877ba6ef075da9ec197be1e1741a89233000000000000000170e2e8a4e8407aa70bb6a8876815729a60383e56378ca112b12bd6f965b59612b4948ea53197b0addf818868beed6800def72585d9efa604215d14161f46663a27d744186eccdf80759eed1cac5caba44acb026cc9183dfa81a423689656e27cd7ce6fb35a9eefc56258ad177cee8551f23327d98f4c3b86aa6cdd67c958047fb087cfe0e093bdd57079ef52d910db884dbe4bfec219fc7f4a0691b2c35475d22795dffa295cd2f0d0"])
r3 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000001700), 0x1, 0x0)
ioctl$WSMUXIO_LIST_DEVICES(r3, 0x40047477, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
r4 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r4, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x1}, 0xc)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x34}, 0x4, &(0x7f0000000080), 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
sysctl$net_inet_icmp(&(0x7f0000000040), 0x4, 0x0, 0x0, 0x0, 0x0)


r0 = syz_open_pts()
ioctl$TIOCCONS(r0, 0x80047462, &(0x7f0000000080)=0x7)
mknod(&(0x7f0000000040)='./file0\x00', 0x2000, 0x20)
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
setuid(0xee01)
ioctl$TIOCCONS(r1, 0x80047462, &(0x7f0000000080))


mknod(&(0x7f0000000300)='./file0\x00', 0x2000, 0x6da)
fchownat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
writev(r0, &(0x7f0000000600)=[{0x0}], 0x1)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x0, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
fcntl$lock(r0, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x7f, 0x1000100000005})
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
r1 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r2 = socket(0x18, 0x2, 0x0)
close(r2)
socket(0x800000018, 0x1, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0xffffffffffffffff}, 0x200, 0x6, 0x8})
bind$unix(r1, &(0x7f0000000240)=@file={0x0, './file0\x00'}, 0xa)
writev(0xffffffffffffffff, 0x0, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
getsockname$unix(0xffffffffffffffff, 0x0, 0x0)
setreuid(0xee00, 0x0)
getuid()
setreuid(0xee00, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$TIOCSTAT(r1, 0x20007465, 0x0)
open$dir(0x0, 0x0, 0x100)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x56, 0x0)
sysctl$net_inet_ip(0x0, 0x0, &(0x7f0000000080)="ae215599fed2fce97f573b9c553a0e622d29cd093849cd4fe42e0f5d2d06a4e744f0713d1fcaa1b8274dffd067d413ef9d2224d3fddc171f73a295b6ed18b3d0588be75e78a1d734e15bfe", 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x1, &(0x7f0000000080)=[{0x1ff}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
mkdir(&(0x7f0000000080)='./file0\x00', 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
ftruncate(0xffffffffffffffff, 0x0)


setreuid(0x0, 0xee01)
r0 = shmget$private(0x0, 0x2000, 0x0, &(0x7f0000ffc000/0x2000)=nil)
shmctl$IPC_SET(r0, 0x1, &(0x7f0000000000)={{0x0, 0x0, 0x0, 0x0, 0x140}, 0x0, 0x0, 0x0, 0xffffffffffffffff})
shmctl$IPC_SET(r0, 0x1, &(0x7f0000000180)={{}, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x20})


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x100, r0)
nanosleep(&(0x7f0000000000), &(0x7f0000001180))


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x67, &(0x7f0000000000), 0x0)
symlink(&(0x7f0000000180)='\x00', &(0x7f00000001c0)='./file0\x00')
mprotect(&(0x7f0000ffe000/0x1000)=nil, 0x1000, 0x2)
r1 = semget(0x3, 0x1, 0x4d0)
semctl$GETALL(r1, 0x0, 0x6, &(0x7f0000000080)=""/32)
ktrace(&(0x7f00000032c0)='./file0/file0\x00', 0x0, 0x0, 0x0)
chmod(&(0x7f00000000c0)='./file0\x00', 0x4)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)


open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
r0 = getpid()
ktrace(&(0x7f0000001d40)='./file0\x00', 0x0, 0x1720, r0)
clock_getres(0x4, &(0x7f00000001c0))


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x80286989, &(0x7f00000001c0))


mknod(0x0, 0x0, 0x0)
mlock(&(0x7f0000ffe000/0x1000)=nil, 0xffffffffdf001fff)
r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSKBDIO_SETBELL(r0, 0x80047476, &(0x7f0000000040))
open$dir(0x0, 0x40, 0x0)
sysctl$net_inet_udp(&(0x7f0000000240), 0x4, 0x0, 0x0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCLOCK(r1, 0x20004276)
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
r2 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$TIOCFLUSH(r2, 0x80047476, &(0x7f0000000000))
r3 = openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
socket$unix(0x1, 0x0, 0x0)
ftruncate(r3, 0xd5)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x8}, 0x0, 0x0, 0x4})
r4 = socket$inet(0x2, 0x1, 0x0)
getsockopt(r4, 0x6, 0x4, 0x0, 0x0)
r5 = msgget$private(0x0, 0xfffffffffffffffd)
msgrcv(r5, 0x0, 0x0, 0x2, 0x0)
r6 = socket(0x18, 0x3, 0x0)
msgsnd(r5, &(0x7f0000000040)=ANY=[@ANYBLOB="02"], 0x55, 0x800)
msgrcv(0x0, &(0x7f0000000480)={0x0, ""/237}, 0xf5, 0x0, 0x1800)
setsockopt(r6, 0x1000000029, 0x1a, &(0x7f0000000000)="5ab777a5", 0x4)
msgrcv(0x0, &(0x7f0000000380)={0x0, ""/201}, 0xd1, 0x1, 0x0)
msgsnd(r5, &(0x7f00000000c0)=ANY=[@ANYRES16, @ANYRESHEX, @ANYRES16, @ANYRESHEX, @ANYBLOB], 0x298, 0x0)
openat$null(0xffffffffffffff9c, 0x0, 0x0, 0x0)
msgrcv(r5, &(0x7f00000002c0), 0xa5, 0xfffffffffffffffc, 0x1800)


select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
r0 = socket(0x2, 0x3, 0x0)
setrlimit(0x0, &(0x7f00000000c0)={0x8})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket$inet(0x2, 0x2, 0x0)
getsockopt$sock_int(r1, 0xffff, 0x1001, &(0x7f0000000080), &(0x7f00000000c0)=0x4)
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
getuid()
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000001c0)={0x0, <r2=>0x0, <r3=>0x0}, &(0x7f0000000200)=0xfffffffffffffe50)
getsockopt$SO_PEERCRED(r1, 0xffff, 0x1022, &(0x7f0000000340)={0x0, <r4=>0x0}, 0xc)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, r4, r3}})
r5 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000140), 0x8, 0x0)
fchownat(r5, &(0x7f0000000180)='./file0\x00', r2, r3, 0x0)
r6 = geteuid()
setreuid(r6, 0x0)
ioctl$VT_ACTIVATE(r5, 0x20007605, &(0x7f0000000300)=0x1000)
r7 = getpid()
fcntl$getown(0xffffffffffffffff, 0x5)
r8 = getegid()
r9 = msgget$private(0x0, 0x0)
sysctl$ddb(&(0x7f0000000000)={0x9, 0x5}, 0x2, &(0x7f00000000c0)="c79b9758", &(0x7f0000000080)=0x4, &(0x7f00000001c0)='\x00\x00\x00\x00', 0x4)
msgctl$IPC_SET(r9, 0x1, &(0x7f0000002f80)={{0x0, 0x0, r8}, 0x0, 0xff, r7, 0x0, 0x0, 0x0, 0x2000000100000001})
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, 0x0, 0x0)
msgctl$IPC_SET(0xffffffffffffffff, 0x1, 0x0)
syz_emit_ethernet(0x138, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
write(0xffffffffffffffff, &(0x7f0000000240)="14bdfa5d1d34e2fecb284a6498307dcda9aec43050036123339a346f737850551408753f95b7688ad4c4e1dd5489e7bafc58d3e5823757ae8b630719ef187ccad995f13dbe19a6dd4e6902bd8297b0799b426aabe9fad9db6996571c6d9f8bb5d542c2148aa42be940970fe88d34d8f99afe7e7820237400000000008000000100"/138, 0xfc7e)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x8000000000000001})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x3}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
close(r0)


open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(0xffffffffffffffff, 0x8, &(0x7f0000000000)={0x4, 0x0, 0xfffffffffffffffe, 0x1000300010008, 0xffffffffffffffff})
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000140)={0x0, 0x0, 0xfff, 0x100000002})
sendmmsg(0xffffffffffffffff, &(0x7f0000000000)={0x0, 0x2}, 0x10, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x4, 0x1100, 0xffffffffffffffff)


socket(0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f0000000380)=@file={0x1, './file0\x00'}, 0xa)
syz_emit_ethernet(0x5e, &(0x7f0000000640)=ANY=[@ANYBLOB="ffffffffffffac566789c54108004200005000000000000c90787f000001e000000244340000ffffffff000000000000000000000000000000007f0000010000000000"])
r0 = syz_open_pts()
close(r0)
socket$inet(0x2, 0x0, 0x0)
getsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x3, 0x0, 0x0)
poll(&(0x7f0000000040)=[{r0, 0x2}], 0x1, 0x0)
sysctl$net_inet_divert(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, &(0x7f0000000080), 0x0, 0x0, 0x0)
setrlimit(0x7, &(0x7f0000000280)={0x0, 0x2})
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x9, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
openat$vnd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, 0x0)
openat(0xffffffffffffff9c, 0x0, 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000040), 0x8)
sendmmsg(0xffffffffffffffff, &(0x7f0000000080)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, 0x0, 0x18}}, 0x10, 0x0)
sendmmsg(0xffffffffffffffff, &(0x7f0000000000)={0x0}, 0x10, 0x0)
open(&(0x7f00000001c0)='./file0\x00', 0x2e1, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
shmget(0x0, 0x4000, 0x0, &(0x7f0000ffc000/0x4000)=nil)


open(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
poll(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000400)=[{0x4d}, {0x5}, {0x812e}]})
syz_emit_ethernet(0x36, &(0x7f0000000100)=ANY=[])


r0 = socket(0x0, 0x0, 0x0)
close(r0)
socket(0x6, 0x1, 0x2)
setsockopt(r0, 0x1000000029, 0x32, &(0x7f00000000c0), 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x100000000000000, 0xffffffffffffffff})
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
connect$unix(r0, &(0x7f0000000040)=@file={0x0, './file0\x00'}, 0xa)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x0, "010000000000000000001339e13600005003005b"})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4, 0x0, 0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f0000000000), 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x1e, 0x3, 0x0)
getsockname(r1, 0x0, &(0x7f00000014c0))
r2 = socket(0x2, 0x1, 0x0)
socket(0x2, 0x2, 0x0)
r3 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000480), 0x0, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000040), 0x0)
socket(0x0, 0x0, 0x0)
ioctl$VNDIOCGET(r3, 0x41946472, &(0x7f0000000000)={'./file0\x00'})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
connect$inet(r2, &(0x7f0000000000), 0x10)


select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$unix(0x1, 0x2, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x2, &(0x7f0000000200), &(0x7f0000000000)=0x1)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047466, &(0x7f0000000200)=0x5)
poll(&(0x7f0000000080)=[{r0, 0x80}], 0x1, 0x0)


mmap(&(0x7f0000fff000/0x1000)=nil, 0x1000, 0x1, 0x9011, 0xffffffffffffffff, 0x0)
r0 = socket(0x2, 0x1, 0x0)
shutdown(r0, 0x2)
getsockname$unix(r0, 0x0, &(0x7f00000022c0))
socket$inet(0x2, 0x4000, 0xc1)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000080)="eaef125c00000080", 0x8)
mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file1\x00', 0x2000, 0x2d87)
r2 = open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={<r3=>0xffffffffffffffff, <r4=>0xffffffffffffffff})
sendmsg$unix(r4, &(0x7f0000000400)={0x0, 0x0, &(0x7f0000000080)=[{&(0x7f0000000180)="cf70770c0d6e80f391bb19656265c41dbf978bc8ef8f9c4c61decb06778c275ed5f70fff9371f1e7789cea6dd7768a2bf2e1a3b9964f606ae9f98c61b38d595303b8f29af43b7903151d6d610da3bb97b52d896feb0a9a1e917c89ec20b854157d7a67e8468615947f9903f6affcc36234407d72d527e7514e53d668cd96c5795a50dbf714313fa18f65de35968e6c1744", 0x91}], 0x1}, 0x0)
recvmmsg(r3, &(0x7f0000000000)={0x0}, 0x10, 0x0, 0x0)
poll(&(0x7f00000000c0)=[{r2, 0x6e}], 0x1, 0x0)
close(r2)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
socket(0x18, 0x2, 0x0)
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f0000000300)=""/47, 0x2f}], 0x1)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1400000029"], 0x3e}, 0x0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000002c0), 0x1, 0x0)
writev(r0, &(0x7f00000003c0)=[{&(0x7f0000000140)="cf440b874f6c", 0x6}, {&(0x7f0000000300)="5ce7d83d1a935479e8fe05d4a282cef7178146d527f9ec5b9d46c32d2bdf131e483158d980a25dfcc2a1cfbd5566b2ecd93866af0ea543487e88adf7163394d8dc4f7ab46f92d4de003a3900c84fc62da73914d6e35c7c9b38dd9a87d8b8442ed791328c459bd1949fa3ec6c680c196311cf5c7503df02b85b4148632d", 0x7d}], 0x2)
execve(0x0, 0x0, 0x0)


syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000), 0x10)
r1 = dup(r0)
listen(r1, 0x0)
r2 = socket(0x2, 0x1, 0x0)
connect$unix(r2, &(0x7f0000000000), 0x10)
r3 = dup(r2)
sendto$inet(r3, &(0x7f0000000240)="03", 0x1, 0x1, 0x0, 0x0)


mkdir(&(0x7f0000000180)='./file0\x00', 0x40)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
rename(&(0x7f00000000c0)='./file0/file0/..\x00', &(0x7f0000000200)='./file1\x00')
connect$unix(0xffffffffffffffff, &(0x7f00000001c0)=@abs={0x0, 0x0, 0x2}, 0x8)
sysctl$ddb(&(0x7f0000000000)={0x9, 0x5}, 0x2, &(0x7f00000002c0)="b151efd9ec9b99ce872e665d84241a5d2a4e39ba4a08d1bf87cccd2140583a0309001556c5561af91e1ee1ab99a2a20048472e6ea9041e8d9b0000103b2656be0b83e6bef50a085d22bd29ef0c0cf6a2cb4a0a4101060fc2091b6db2b007f42ac6888d87dbcd66b3604f7ebfcfd1d6cdb18ef112db4e84d61427299453b7842b00c6b5d02eeafced52087993a543d83d2800000000000000000000786175566f830605b2314e9959e1c9e03cafa2c9830196002152912948f7e57a8b53af5aae7a1e7e95c7c63bd3317327069d4a738724a546c3913bddb3627de8c368c628cf63c8a95da60648a8443a2b73950ccbdac6b0a03822112dca055742010f231f", &(0x7f0000000040)=0xff, 0xfffffffffffffffe, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
rename(&(0x7f0000000100)='./file0/file0\x00', &(0x7f0000000240)='./file0/file0/..\x00')
chmod(&(0x7f0000000080)='./file0\x00', 0x100)
r1 = msgget$private(0x0, 0x397)
msgrcv(r1, &(0x7f00000007c0), 0x84, 0x1, 0x1800)
msgrcv(r1, &(0x7f0000000680), 0xd9, 0x3, 0x1000)
mkdir(&(0x7f0000000140)='./file0\x00', 0x21)
setreuid(0xee00, 0x0)
msgctl$IPC_SET(0x0, 0x1, 0x0)
msgrcv(0x0, 0x0, 0x0, 0x2, 0x1000)
unveil(&(0x7f0000000300)='./file0/file0/..\x00', &(0x7f0000000400)='r\x00')
r2 = getuid()
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f00000002c0)={0x0, 0x0, <r3=>0x0}, 0xc)
chown(&(0x7f0000000280)='./file1\x00', r2, r3)
chdir(&(0x7f0000000580)='./file0\x00')
getpeername$unix(r0, &(0x7f0000000d40)=@file={0x0, ""/4099}, &(0x7f0000000540)=0x1005)
msgsnd(r1, &(0x7f0000000d00)=ANY=[@ANYRESHEX], 0x401, 0x0)
getsockopt(0xffffffffffffffff, 0x6, 0x9, 0x0, 0x0)
msgsnd(r1, &(0x7f0000001f40)=ANY=[], 0x401, 0x0)
msgctl$IPC_STAT(0x0, 0x2, &(0x7f00000008c0)=""/208)
write(r0, &(0x7f0000000380)="4bff78f4150fa3c934ee85fe7217dba4a6db9614f70db4a481a20827f2e3ba3c572fced100924a7a686c2da81c0a56547daf5b76310b5fe25ceb8904682c4c65264437bb6ab370fa5318e42636f5dbfd2e13ecdb277aa61710f9f6", 0x5b)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x8000, 0x9)
getpid()
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
fcntl$setstatus(r0, 0x4, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000000)={0x6, 0xb, 0x2}, 0x5, &(0x7f0000000500), 0x0, 0x0, 0x0)
socket$inet(0x2, 0x3, 0x102)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000000c0)=[{0xc0}, {0x15}, {0x16}]})
syz_emit_ethernet(0x6e, &(0x7f00000002c0)=ANY=[])


mkdirat(0xffffffffffffffff, &(0x7f0000000040)='./file0\x00', 0x0)
r0 = syz_open_pts()
fcntl$lock(r0, 0x9, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1000300000000})
flock(r0, 0x1)
flock(r0, 0x3)
fcntl$lock(r0, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000001})


sysctl$kern(&(0x7f0000000000), 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x1a, &(0x7f0000000000)="5ab777a5", 0x4)


syz_emit_ethernet(0x3e, &(0x7f0000000000)={@random="fd9339c0fa4d", @random="5fd01f461c93", [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x30, 0x0, 0xfffe, 0x0, 0x0, 0x0, @multicast1}, @icmp=@redirect={0x5, 0x0, 0x0, @multicast1, {0x5, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, @empty, @local={0xac, 0x14, 0x0}}}}}}})
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x1, &(0x7f0000000080)=[{}]})
openat$null(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
rename(&(0x7f0000000080)='./file0\x00', &(0x7f00000000c0)='./file0\x00')
mkdir(0x0, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x3e, 0x0)
ioctl$BIOCVERSION(0xffffffffffffffff, 0x40044271, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8020699f, &(0x7f0000000100))


sysctl$hw(&(0x7f0000000040)={0x6, 0x12}, 0x2, &(0x7f0000000080)="9a7f1452fe869fac2659b5461edff3c77756ec077602b86e64743d8c0a5c17e6f75e919112", &(0x7f0000000140)=0x25, &(0x7f0000000180), 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000080)=[{0x5}, {0x20}, {0xe}]})
write(r0, &(0x7f00000006c0)="e506000000000000004aaed75a5a", 0xe)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setreuid(0xee00, 0x0)
r0 = geteuid()
setuid(r0)
r1 = getuid()
setreuid(r1, r1)
r2 = semget$private(0x0, 0x2, 0x490)
geteuid()
r3 = getgid()
r4 = getegid()
semctl$IPC_SET(r2, 0x0, 0x1, &(0x7f0000000140)={{0x8000, r1, r3, 0x0, r4, 0x88, 0x8}, 0x8001, 0x1f, 0x3f})
setreuid(0xee00, r1)
setreuid(r0, r1)
r5 = getuid()
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000000)={0x0, <r6=>0x0}, &(0x7f0000000080)=0xc)
r7 = geteuid()
setuid(r7)
semctl$IPC_SET(r2, 0x0, 0x1, &(0x7f00000000c0)={{0x3, r6, r4, r7, r3, 0x12, 0x9}, 0x200, 0x5})
setreuid(0x0, r5)
r8 = socket(0x2, 0x2, 0x0)
r9 = dup(r8)
setsockopt$inet_opts(r9, 0x0, 0x16, &(0x7f0000000040)="fd0cc085", 0x4)


getppid()
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000500)={0x0, 0x0, &(0x7f0000000480)=[{&(0x7f0000000380)='s', 0x1}], 0x100000000000038b}, 0x1)
r0 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmat(r0, &(0x7f0000001000/0x3000)=nil, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000015c0))
madvise(&(0x7f0000001000/0x2000)=nil, 0x2000, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f0000000500)={0x0}, 0x10, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x8040691a, 0x0)


setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r1 = fcntl$dupfd(r0, 0x3, 0xffffffffffffffff)
fcntl$setstatus(r1, 0x4, 0x0)


open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
sysctl$fs(&(0x7f0000000080), 0x2, &(0x7f0000000100)="db4062e8d3bb70dff2e066a2d0db714e4394ad91bb9db7ece95d5d54710acabbf254e0abac31ae06fe909e50bd5392390231352493921a24d843391090c36e4206fdd777d378fe8d0f2b1ae413bc1dd1b870863d1bff0ddbcdd20e51de114b4ac16385f5f2f87f86d5400b6a33c641ba1fda069cf1e9836210cbb7", &(0x7f0000000200)=0x7b, &(0x7f0000000240)="75d7953f75245128038c991de504e51855391173d274de8511f6ea583cc47d74bd0071e816843b1d12191d7830f7f709e81fb02cc70a662a0f810b523da17fd02a86408cc0ac82a8127e96c22911bc9bafd59ef044a7881aebe2fceb19439259235fa906eca55ab8e21f24bc4e8b96f07c1b384257b092bf039af6e8b3663368375164396dd95367fa3273ec52ad25528b50736db32df5234a09fbbf228a1bd96997343b7c8119ab84faacc888f185ceea6ced14c5982c99ac32b106fb214529bb8a9888da38383ec5177e361dcc9e620cca4c695c63dbfe3bf03e28a00c81b55f04ccb0c974afcedd73", 0xea)
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = kqueue()
kevent(r2, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x80146951, &(0x7f00000001c0))
fcntl$lock(r0, 0x8, &(0x7f0000000180)={0x0, 0x0, 0x0, 0x100000401})
socket$inet(0x2, 0x8003, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
mkdir(0x0, 0x0)
chmod(0x0, 0x3a)
chdir(&(0x7f0000000240)='./file0\x00')
mkdir(&(0x7f00000002c0)='./file1\x00', 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000540))
setreuid(0x0, 0xee01)
rename(&(0x7f00000003c0)='./file1\x00', &(0x7f0000000400)='./file0\x00')
semget$private(0x0, 0x4, 0x2)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000002c0)={<r4=>0xffffffffffffffff})
getsockopt$sock_cred(r4, 0xffff, 0x1022, &(0x7f00000000c0)={<r5=>0x0, <r6=>0x0}, &(0x7f0000000040)=0xc)
r7 = msgget$private(0x0, 0x397)
msgrcv(r7, &(0x7f00000007c0), 0x84, 0x1, 0x1800)
msgrcv(r7, 0x0, 0x0, 0x3, 0x1000)
msgsnd(r7, &(0x7f0000000d00)=ANY=[@ANYRESHEX], 0x401, 0x0)
msgctl$IPC_SET(r7, 0x1, &(0x7f0000000340)={{0x80000001, r6, 0x0, r6, 0x0, 0xaf, 0x9}, 0x7ff, 0x0, r5, r5, 0xffffffffffffffff, 0x7, 0x12c, 0x3})


r0 = socket(0x2, 0x4001, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x4, 0x0)
poll(&(0x7f00000000c0)=[{r1, 0x4}], 0x1, 0x0)


mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)={0x3, 0x7fffffff})
r0 = kqueue()
kevent(r0, &(0x7f00000000c0), 0x30, 0x0, 0x57d, 0x0)


r0 = socket(0x18, 0x1, 0x0)
shutdown(r0, 0x1)
ioctl$BIOCSETWF(0xffffffffffffff9c, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x3}, {0x6, 0x0, 0x0, 0xbe}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0xfffffffffffffe59)


syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
syz_extract_tcp_res(&(0x7f0000000040), 0x0, 0x2)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
accept$inet(0xffffffffffffffff, &(0x7f0000001780), &(0x7f00000017c0)=0xc)
r0 = socket(0x2, 0x3, 0x0)
bind(r0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
connect$unix(r0, &(0x7f0000000000), 0x10)
sendto$inet(r0, 0x0, 0x0, 0x0, 0x0, 0x0)


openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = getuid()
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
r1 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
open(&(0x7f0000000140)='./file0\x00', 0xf8e, 0x0)
r2 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r2)
r3 = socket(0x11, 0x3, 0x0)
sendto(r3, 0x0, 0x0, 0x0, &(0x7f0000000040)=@un=@abs={0x0, 0x0, 0x1}, 0x8)
writev(r1, &(0x7f0000000340)=[{&(0x7f0000000000), 0x2cfea}], 0x1000000000000013)
mknod(&(0x7f0000000000)='./bus\x00', 0x3a0914c44f7b202d, 0x0)
r4 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
ioctl$TIOCSETAF(r4, 0x802c7416, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x0, "247497496ed3ffa429fdb9102575e414229eb682"})
execve(0x0, 0x0, 0x0)
chown(0x0, r0, 0xffffffffffffffff)
open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000040)={&(0x7f00000000c0)=[{0x4}, {}], 0x2})


mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
r0 = open(&(0x7f0000000180)='./file0\x00', 0x2, 0x0)
setreuid(0x0, 0xee01)
ioctl$FIONREAD(r0, 0x8020697a, &(0x7f0000000100))


syz_emit_ethernet(0x3e, &(0x7f00000000c0)={@broadcast, @empty, [], {@ipv4={0x800, {{0x7, 0x4, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, @empty, @empty, {[@rr={0x7, 0x3, 0xff}, @rr={0x7, 0x3}]}}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x1, &(0x7f0000000080)=[{0x8a}]})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x200000000000032f, &(0x7f0000000040)=[{}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
mkdir(&(0x7f0000000080)='./file0\x00', 0x0)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
rename(&(0x7f0000000080)='./file0\x00', &(0x7f00000000c0)='./file0\x00')


mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
sysctl$hw(&(0x7f0000000080)={0x6, 0xe}, 0x2, 0x0, 0x0, &(0x7f0000000280), 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x0, 0x3, 0x0)
getsockopt$sock_linger(r1, 0xffff, 0x1021, 0x0, 0x0)
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0206921, &(0x7f0000000000))
r3 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
fcntl$dupfd(r3, 0x3, 0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
execve(0x0, 0x0, 0x0)
r4 = socket$inet(0x2, 0x3, 0x0)
getsockopt$sock_timeval(r4, 0xffff, 0x1004, &(0x7f0000000500), &(0x7f00000004c0)=0xfffffffffffffe84)
r5 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r5, 0x8020690e, &(0x7f00000001c0))
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCPROMISC(0xffffffffffffffff, 0x20004269)
ioctl$PCIOCREAD(0xffffffffffffffff, 0xc00c7007, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000180)=[{}, {0x48}, {0x1d16}]})
mkdir(&(0x7f0000000000)='./file0\x00', 0x0)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000080)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
bind$unix(r0, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
close(r0)
setreuid(0xee00, 0xffffffffffffffff)
r1 = getuid()
chown(&(0x7f00000000c0)='./file0\x00', r1, 0x0)
r2 = getuid()
setreuid(0xee00, r2)
r3 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r3, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000400)=[{0x34, 0x0, 0x0, 0x3fffffff}, {0x50}, {0x6, 0x0, 0x0, 0x23a}]})
write(r0, &(0x7f0000000000)="7696e5f3d1f18c37cea8615ac7cf", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000000)=[{0x3}, {0x60}, {0x5ce}]})
syz_emit_ethernet(0x76, &(0x7f0000000140)=ANY=[])


sysctl$net_inet_carp(&(0x7f0000000000)={0x4, 0x2, 0x6c}, 0x4, 0x0, 0x0, 0x0, 0x68)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
sysctl$kern(&(0x7f0000000000)={0x3}, 0x6, 0x0, 0x0, 0x0, 0xfffffffffffffedf)


mknod(0x0, 0x0, 0x881)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x802, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x54}, {0x48}, {0x6}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x0, 0x0})
write(r0, &(0x7f00000003c0)="985fa7fbdf69aca69c9a97347864", 0xe)


sysctl$net_inet_ip(&(0x7f0000000080)={0x4, 0x2, 0x0, 0x17}, 0x4, 0x0, 0x0, 0x0, 0x0)
r0 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0xffffffffffffffff}})
r1 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x113}})
r2 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x1, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000280)=[{0x50}, {0x80}, {0x9106}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0xca})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000040)={0x7ffffffe, 0x0, 0x7, 0x6b384159, "2f78acf2ee60987b0d026cc4ffffaa175b31cb31"})
writev(r0, &(0x7f0000001580)=[{&(0x7f0000001340)="f2f5060e4a1ab0974870e40af8e001f53e04bf74fed4aee2be0863d275b2e4226489c933194ab7b2a0027b2f6f1b1d9cb787a7933c75e07eed0a09942d0104e4e1c8a9073576a8944f423bcaa96d8169aa92956791fed312477b15c06c89dca7", 0x60}], 0x1)


socketpair$unix(0x1, 0x5, 0x0, 0xfffffffffffffffe)


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
close(0xffffffffffffffff)
close(0xffffffffffffffff)
flock(0xffffffffffffffff, 0x0)
socketpair$unix(0x1, 0x0, 0x0, &(0x7f00000000c0)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
getsockopt$sock_int(r0, 0xffff, 0x100, 0x0, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x1, 0x0, 0x2}, 0x8)
socket(0x2, 0x2, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f0000000100)=@file={0x0, './file2\x00'}, 0xa)
getsockname$unix(0xffffffffffffffff, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
getuid()
setitimer(0x0, &(0x7f0000000000), 0x0)
setitimer(0x0, 0x0, 0x0)
mlock(&(0x7f0000ffb000/0x1000)=nil, 0x1000)
r1 = open$dir(0x0, 0x100, 0x128)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x35}, 0x4, &(0x7f0000000080), 0x0, &(0x7f0000000100), 0x0)
open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000180)='./file1\x00', r1, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x200, 0x0)
setreuid(0xee00, 0x0)
r2 = getuid()
setreuid(0xee00, r2)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x0, 0xffffffffffffffff)
r3 = msgget$private(0x0, 0x0)
msgctl$IPC_STAT(r3, 0x2, 0x0)


r0 = open$dir(&(0x7f0000000040)='.\x00', 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
sysctl$net_inet_ip(0x0, 0x0, &(0x7f0000000100)="d7a8aac106fa1bee91c724b89283c1477dab85e783af4189a1eaf5f6e8251b1147b330f604ff639b9acd6202c9d8b1aef98ce6eefe712df21386a1f60bf4faf9867326180248fad514768c9928b74275ea8724a797051b934fc1a46677c194747c86477c2b49408ac33a50bed4dcd8d719c8e887ac6d1dca49c9ce71f944ba6751c604f18a9ce52aacbefb7d860132e72fc06c9d8f338de4eb9883b149513237c92b275cc73a320f63183363303ff9c417b6ed3f78a83a50368c9b2ce613b854c0e9bbda45c3aac729211c0bc3f3973c541cb95fa6a6696859", 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x80286987, &(0x7f00000001c0))
r2 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x80286989, &(0x7f00000001c0))
socket$unix(0x1, 0x0, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x2, &(0x7f0000000000)=[{0x28}, {0x4000006}]})
write(r3, &(0x7f0000000180)="23009100007adb020317bdda2b7e", 0xe)
sysctl$net_inet_tcp(&(0x7f0000000080)={0x4, 0x2, 0x6, 0x17}, 0x4, &(0x7f00000006c0)="46422995", &(0x7f00000000c0)=0x4, &(0x7f0000000280), 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000380)={<r4=>0xffffffffffffffff})
setsockopt$sock_linger(r4, 0xffff, 0x80, &(0x7f0000000740)={0x1ff}, 0x8)
socket$inet(0x2, 0x0, 0x0)
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000000680)={'tap', 0x0})
ioctl$BIOCSETF(r5, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f00000000c0)=[{0x64}, {0x87}, {0x26}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
sysctl$net_inet_ip(0x0, 0x0, &(0x7f0000000100)="d7a8aac106fa1bee91c724b89283c1477dab85e783af4189a1eaf5f6e8251b1147b330f604ff639b9acd6202c9d8b1aef98ce6eefe712df21386a1f60bf4faf9867326180248fad514768c9928b74275ea8724a797051b934fc1a46677c194747c86477c2b49408ac33a50bed4dcd8d719c8e887ac6d1dca49c9ce71f944ba6751c604f18a9ce52aacbefb7d860132e72fc06c9d8f338de4eb9883b149513237c92b275cc73a320f63183363303ff9c417b6ed3f78a83a50368c9b2ce613b854c0e9bbda45c3aac729211c0bc3f3973c541cb95fa6a6696859", 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r6 = getpid()
ktrace(0x0, 0x5, 0x40000238, r6)
ioctl$FIONREAD(0xffffffffffffffff, 0x80286987, &(0x7f00000001c0))
r7 = socket(0x7b, 0x4, 0x3)
ioctl$FIONREAD(r7, 0x80286989, &(0x7f00000001c0))
symlinkat(&(0x7f00000000c0)='\x00', r0, &(0x7f0000000080)='./file1\x00')
unlink(&(0x7f0000000140)='./file1\x00')


r0 = kqueue()
kevent(r0, &(0x7f00000000c0)=[{{r0}, 0xfffffffffffffff9, 0xcb}, {{r0}, 0xfffffffffffffff9, 0xc5, 0x1}], 0x8be4, 0x0, 0xfffffffb, 0x0)


sysctl$net_inet_ip(&(0x7f0000000040), 0x4, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x2, 0x0)
r1 = dup(r0)
setsockopt$inet_opts(r1, 0x0, 0x16, &(0x7f0000000040)="fd0cc085", 0x4)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0x8020560a, &(0x7f00000002c0)={0x10, 0x0, [{&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000fef000/0x4000)=nil}, {&(0x7f0000165000/0x2000)=nil, &(0x7f00001e6000/0x1000)=nil}, {&(0x7f0000787000/0x4000)=nil, &(0x7f000011c000/0x3000)=nil}, {&(0x7f00005bd000/0x4000)=nil, &(0x7f0000fee000/0x3000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000268000/0x2000)=nil}, {&(0x7f0000328000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000075b000/0x3000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000760000/0x3000)=nil, &(0x7f0000ff2000/0x4000)=nil}, {&(0x7f0000fec000/0x14000)=nil, &(0x7f0000ff9000/0x1000)=nil}, {&(0x7f0000ff9000/0x2000)=nil, &(0x7f0000fef000/0x1000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000729000/0x2000)=nil}, {&(0x7f0000ff5000/0x4000)=nil, &(0x7f0000ff6000/0x1000)=nil}, {&(0x7f0000ff8000/0x2000)=nil, &(0x7f0000fef000/0x3000)=nil}, {&(0x7f0000432000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil}], './file0\x00'})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaaaabb86dd605d34520030000000000000000000000000000000000000000000009f0500040000000000000001010090780000000060397772"])
open$dir(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')


setrlimit(0x8, &(0x7f0000000040)={0x7, 0x200005})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000380)={0xfffff732, 0x0, 0x1, 0xdfdffbc5, "97115f33ba7d00fdff0184000000000000de00"})
writev(r0, &(0x7f0000000e00)=[{&(0x7f0000000000)="8a790538f39456d084543880083267c4d808c19e4e915c29", 0x18}], 0x1)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
r1 = dup(r0)
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
r2 = open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
sysctl$net_inet_divert(&(0x7f0000000100), 0xb, &(0x7f0000000280)="a7c1290f17722447b2c63e743f6b379fa5267a394a5d94db9417b6982f519b111f61ad994119ba843799517c2ddf4c65594fb3b55a5fce717f619f904ce7b41e4296cf777a1db4747703440100000023e48310b779f9619c7642d6d7f500000000000000000000000000000000c37a11ae4dbe56deeb1ccae6d8e73f8976b460abc78bfdf1bf11c3ec2956f559e2ae95b19752a20f358e90edd96264cbc18906750f34e7e595d09e4e313414f688d6388b713904a7996cc92a328db185299eeabc8e35147498451c4a84a9d41bf693affdc27f4569379570f4", &(0x7f0000000180)=0x67, &(0x7f0000000640)="e2714be05c6a432bfcb43ba70e2bb9e6add925cf34d00e465191e199efee4898bfe502dcc0a3e3fd0cc0e7969055dcb470ddd2f263dfb8065cbf63d41b2a29e4f92695a2dae1e619ba2b0ccd1e605cd2827beb6ddaf6b579cccebb6d267a74d6af9f2cddd1eb38180245caf3e0f240c5f1ee52a05a63c446df6149316cc2e17b775698e9114250d85ec893fbd204889e5c3f37ee5894227fa7b36a2803d9c558953caa2452fff1bf82f49299d2fd07d8a464fd351d966782d21806ba5be9dc66d7dd572cdae3822888010771550dd55b3014876e2537e33b838b12b10d843be49e4cfc3b3f04a60088dd3cc3fbdc16864e028753d898f0bc0bd6e20f96274d743755332aebcec91d4f490000000000000000628c7c526f7de4f21b6260bacfe436d6eb63a96ded0b0f29cbc8ea2a7d2760b1fdf551506810d63132c72c14be5ffcc53ca339aea237797e863010f33b057982b6825dbdef1ce4425ae7d1234ad5cb69", 0xee)
open(&(0x7f00000002c0)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
link(0x0, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000000040)=ANY=[@ANYBLOB="aaaaaaaaaaaaffffffffffff86dd600625200000000000000000000000000100ffffac1400d0fe"])
r3 = socket(0x18, 0x1, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000000029, 0x8, &(0x7f0000000100)="54db0b54854d9a37275631fa6e64174e78402377241f3b2ed58c7bda91f1bb6545d47631dff7e76aa265a2f8843b8ce1456e3fb26125a455bacf5bd48c8d7bae6cf710c023b177094b91f32433bbacecd6613f1005d2fb896d2b5266906e9b8c5c1a418c4d72195cfcda996f6f5dce220916634c6dbdefed7290ee704452", 0x7e)
setsockopt(r3, 0x1000000000029, 0xa, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x3e}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)
openat$speaker(0xffffffffffffff9c, 0x0, 0x2, 0x0)
syz_emit_ethernet(0x12, &(0x7f00000002c0)={@local, @local, [{}], {@generic={0x88a8}}})
msgrcv(0x0, 0x0, 0x0, 0x0, 0x0)
r4 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmat(r4, &(0x7f0000001000/0x3000)=nil, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {&(0x7f0000ff9000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffd000/0x1000)=nil, 0x80000001}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f0000ffc000/0x1000)=nil}, {&(0x7f0000003000/0x2000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x2000)=nil}], './file0\x00'})
r5 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r5, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0, 0x1000})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x40b, 0x0)
sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000000)="9b1809ffffffffffffff7f473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6fd74c94d1b44", &(0x7f0000000040)=0x10011, 0x0, 0x0)
utimensat(0xffffffffffffffff, 0x0, 0x0, 0x0)
msgsnd(0x0, 0x0, 0x401, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000440)={0x4, 0x18, 0x6, 0x9}, 0x4, &(0x7f0000000480)="9b0209c3218b07fcfe4189c99e805e6e84d356960798a692992117d6728436ba1bd87f42e3303eac3846528d050712f838130efce33f523ba44765f5f6915b2227390ed95bd9dc6d4dc7f149d4d6d06a3f23616e773302d9cae75e39a5a11e32e0e6ebd635450b2eba540af7f2aa5dbfbdd900a0dad2b74f50acd76b5c567049ef436dbea0d7562f52955af8d4ab84c513252ddd139b5f5cd5c2bd02adc7f1fe850c00000000000000062ab475cca257352828a76e5334be562995e894238b96ca5d4d3e670fa0cc791dfc4415030910fa64eac9b4e8aa9bef19525cb6f7e8570be65bb7ad3fe963cb9a8bd949ee334db1ccf73db06b5947b3e88aa810f8ed7cca10ff0d0000000000001345daa49507756f49775275ca390b94e85d5a95b82000b9429c25483a9275d0da3b561c6adc3c141f26040000006b436218bdbdc9ac0a623855e941dc1872fcb045e0d9df1ecc6357ee21e2b0802cb60edd0300723235f06715e7eecc3e0760c70e1dd7873e27142bbae1a7e44de453a073fe3426f334b80f043ba9136d57c799353d46dd81439b111a511a288bee5dfb2e353e3bb073e3342273216b07e49ca4df0fd2dbe9a8eb377010ee678aad0bd8c7fb7d82693a096344671843a1f2082612b2ff237c6e505ff5f5ba932954d73c630fd2791f833a1da5af0704f687e196f4f7859e071fc98111cc9024f790ce16ceaa427d0104e39789d91000"/528, &(0x7f0000000a40)=0x210, 0x0, 0x0)
poll(&(0x7f00000000c0)=[{r2, 0x6e}], 0x1, 0x0)
getpeername(r2, &(0x7f0000000000)=@in6, &(0x7f0000000040)=0xc)
recvmmsg(r1, 0x0, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000480), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000140)=[{0x44}, {0x74}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000000100)=[{0x3}, {0x3c}, {0x6}]})
write(r0, &(0x7f0000000280)="f659600777eb3e3a6dce3c530404", 0xe)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040))
openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x1, 0x0)
r2 = socket(0x18, 0x1, 0x0)
setsockopt(r2, 0x1000000029, 0x36, &(0x7f0000000040)="03000000", 0x4)
dup2(r2, r1)
ioctl$FIONBIO(r2, 0x8004667e, &(0x7f0000000080))
connect$unix(r1, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000300), 0x0, 0x0)
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000480)={0x2, &(0x7f00000000c0)=[{0x404d, 0x0, 0x9}, {}]})


open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x5, &(0x7f0000000040)=[{0x24, 0x0, 0x4}, {0x4f5, 0x0, 0x1}, {0x416}, {0x0, 0xfe, 0x1f, 0x9}, {0x1, 0xaa}]})
r1 = socket(0x2, 0x1, 0x0)
r2 = dup(r1)
setsockopt$sock_int(r2, 0xffff, 0x1004, &(0x7f0000000180), 0x4)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
syz_open_pts()
syz_open_pts()
socket(0x2, 0x2, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
pipe(&(0x7f00000000c0)={<r3=>0xffffffffffffffff, <r4=>0xffffffffffffffff})
readv(r3, &(0x7f0000000000)=[{&(0x7f0000000380)=""/143, 0x8f}], 0x1)
dup2(r4, r3)
kqueue()
execve(0x0, 0x0, 0x0)
select(0x40, &(0x7f0000000180)={0x0, 0x0, 0x0, 0x0, 0x3f}, &(0x7f00000001c0)={0xff}, 0x0, 0x0)
syz_emit_ethernet(0x138, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r5 = socket(0x2, 0x1, 0x0)
connect$unix(r5, &(0x7f0000000000), 0x10)


socket(0x18, 0x1, 0x0)
ioctl$VNDIOCSET(0xffffffffffffffff, 0x41946465, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, &(0x7f0000000000)="9b1809ffffffffffffff7f473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6fd74c94d1b44", &(0x7f0000000040)=0x3c, 0x0, 0x0)
r0 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$FIONBIO(r0, 0x8004667e, &(0x7f0000001180))
mprotect(&(0x7f0000ffb000/0x1000)=nil, 0x1000, 0x0)
ioctl$WSDISPLAYIO_GBURNER(0xffffffffffffffff, 0x400c5752, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x41, 0x10000})
socketpair$unix(0x1, 0x0, 0x0, &(0x7f0000000080))
openat$zero(0xffffffffffffff9c, 0x0, 0x100, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000001c0)=[{}, {}, {0x6}]})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x8020691f, &(0x7f00000001c0))


sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
r0 = socket(0x18, 0x400000002, 0x0)
r1 = socket(0x18, 0x2, 0x0)
getsockname$inet(r1, &(0x7f0000000080), &(0x7f0000000000)=0xffffffffffffffc6)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = dup2(r1, r0)
sendmsg$unix(r2, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f0000000080)='./file0\x00', 0x1, 0x0)
open(&(0x7f0000000240)='./file0\x00', 0x0, 0x0)
ioctl$WSDISPLAYIO_SETSCREEN(r0, 0x80045756, &(0x7f0000000040))


syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000)=@un=@abs={0x0, 0xd}, 0x10)
listen(r0, 0x0)


r0 = socket(0x2, 0x1, 0x0)
sendmmsg(0xffffffffffffffff, &(0x7f00000007c0)={&(0x7f0000000780)={0x0, 0x0, &(0x7f0000000400)=[{&(0x7f0000000180)="b860fe09625ee6793978a575faa1b6c6c1d6c2eca2950e663d39ab1be31a269a39fd7f97e41e178f37a79f0065733f7e4e4973c1e6b33ac91343ea3b3f8c5c7b93d5c20ab4211791fe30", 0x4a}], 0x1, 0x0}}, 0x10, 0x0)
r1 = socket(0x2, 0x2, 0x0)
lseek(r1, 0x9, 0x3)
ioctl$FIONREAD(r1, 0x80206979, &(0x7f00000001c0))
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000100)=0x200000, 0x4)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1, &(0x7f0000000040)=0x200, 0x4)
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
r2 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
r3 = socket(0x2, 0x1, 0x0)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000000)="b886b4e47f", 0xfffffffffffffee7}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r4 = socket(0x2, 0x1, 0x0)
bind(r4, &(0x7f0000000000), 0x10)
listen(r4, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)
write(r3, &(0x7f0000000080)="04bdfa5d1d2873c63e3534825ba166e2fea9aec43050006123339a346f731573d8d508753f95b7688ad48b8cf6bbca325cebc37fc4e1dd543dbe2da6dd", 0xffea)
ftruncate(r2, 0x0)
dup2(r3, r4)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
connect$unix(r0, &(0x7f0000000000), 0x10)


r0 = socket(0x1, 0x2, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000540)=[{&(0x7f00000001c0)="44697c57153e5a73bc780379382273877174391c65893cb856adca92bc521f", 0x1f}], 0x1)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0xc0286988, &(0x7f00000001c0))
syz_emit_ethernet(0x46, &(0x7f0000000000)=ANY=[@ANYBLOB="ffffffffffffffffffffffff0800490090780000000000007ec88802440c0f00000000000000000000004e224e22"])
syz_emit_ethernet(0x118, &(0x7f0000000580)={@broadcast, @empty, [], {@ipv6={0x86dd, {0x4, 0x6, "d00611", 0xe2, 0xc3, 0x20, @loopback, @remote={0xfe, 0x80, '\x00', 0x0}, {[@fragment={0x89, 0x0, 0x6, 0x1, 0x0, 0x1b, 0x64}], @udp={{0x2, 0x0, 0x8}, {"8582fba88171450db271bab85d468c0aee752cb85656e7a97c8a0f9272c4fb8676eb95a295f2ffb85c09c133f3cb373a0cf80187a5879d66bab9d9b149da62d49f649e1c8f40bb20e8173b6071a216945fb6b11061b44df2600934db14ba4ae1706a8e91d149b25b141fe7d5cb4b96710bf86c465c2153ae205ffbfd2bd131593465a1b45addf76a5a4520fb8ce70efde0edcb1bbbcfdc949c3bcb33ff0fb7005e80cb5f50baae95e41b7c343a0d9dad42bd57920fb3e07bf11372b0cffbb7fa8c0ab7506e6d68b19d398a3798b3851d9821"}}}}}}})
mknod(&(0x7f0000000040)='.\x00', 0x4, 0x8)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r1=>0xffffffffffffffff})
writev(r1, &(0x7f0000000080)=[{&(0x7f0000000380)="e456ab5043b80d3597d07e1152461bb20ca7ffde4f3680e38c0000000000000000eb3c033e61d9d0d2e8612827994d1c8aad9fa35faccf67edf420ae39496b033e1d3054caaf68cc183d249cffad820100491b97b3fdd0048cb1ebbc3c128db181748df932df37cb49996234751b35d7168fc0479866fb44fb1bd9fc94b99eb8fa9c1d14912cfa10f10942ad5118f0016a5cfe725eae73d6e4765b89a62a151520a6c96dca1b3ba7c01ef366418b832a04fac0dea6e4923cc656fb1ee63582583bdd5f4c4863d7cdeb1a3dbd639254e847e500133647a7089bc4e1af017683547950000d3865ee49b1aa50c894e2ad4dbffd818a0a1dc6214e308002386aaa8b0b631e33a18a1872699c90f034aa16", 0xee}, {&(0x7f0000001900)="2a1b111c1376ad5d3c4704f99c34f7d17ad0d25178c43f1a7b88b169a2218171baed0ef03565403f3c4264942ae64fe5578fff1d827183f5ee7bec38281a718869de873422d047bcf26f11a4cbaf48272ff7f035401f9cd5220ce13bf0eee49139b6b1a91fd446a749ca668903e9fb54f5f4df26f8e4c465426bc76c2d3521bd0128667e90dd2a963d379d9d29a427c1932dc85c51783ea75c5cfa65fedbdf6cfe56f85f55af8e369288db20133c0db40908aa215e7a80e97639b24f6bbeddc61d589c5e3cc534990cb08b2da58799a5b6ef9cdf91c4db38e95ab5ad6250834d495c60066e8359ae00577cf7e7a3579898c8634b5dca3faed3e022c8e3a66bd4c6306ebfb539cc5e7d2291dfcf18b28b9a5d9842760df2ca45c223216c866546e0867623502dce5da2c8d50c225f8e4fe6c0aaa23c2fe259a11c125f33eace42993a5e27d4362cd1dcd1da2bc8ae8493cf2f4f6ec26edd0a97cb2bbc46edfa7339eb45e81506055fd7cfed3d2c69e14e0b94b8fb4600ccbe8b5b78163d7044e65fe3e02c8922d2c27a1628a5e17d477401e37869875ca45fa8750f7b9e148cb3db113d158354327e7c53dc6730367edafa389a91a66a3b562f536779eb4d2d069cb069804cf45fd695c67c6b5da055ad4500e4cf09785b053fd743776aa9c6da7a86c18441bceb758606e4624d06af201db04954261deb25c63e7b18f795256840e2e3fbff5a9b443a85ccdf05f5341c563abe679fdf5db8aeaf01c9aa18b215bf0f79ce1a8d9cb211dd291f6668a13e43753f15bd4acaeb7234f5cf1c1368d1fd38d99ba3a68ce1ccffcb863517612acb3f621bbaec5c2f1f1e8a9f7f8665afafe14c62e56fcc19519cc5c8f03ebe74440c3dbdac542080e788378f5eaddb9c3c1a85ed61873f0900efefa2fc8d569b755e00639d0c17c13d664f51bf5206b05289179b39ce1997cfba1adb2ae73cbcaacb467e35202a548a5e8fcd5614c8b790ace1b965ec12842195dc6a62e7a222fb7cd761651059a2425c33aaa07e5e57d5ab7f74ad340e993ddd756c1b916a5a0842e312fd7f6348d1806ce23d2d72ad7616109f04b5537daea15e8e5504492e70eb0442758044117dedd4379de3bc5175f399fa2dd3796a693adda65044be69045bef0a92f5c5850cc78a8c6feab5ea9ba37cad9816f8cb43ee2bdc7273ac019961843665e35460c2efc8ae2da0ec275a39fe1754874bd951b1fd5ab83111ff0d4723c270d73a11db75bd314e55849ffaba2f8dea7ab2c349bd9459efecfdc25ce7bcc11d44e1e126134f238dcacfefd6d486d599cadef492189218ff44e6d5dfa1f7da0a16d8b162fa7660c8255a75a7f0b45c853a800123789bbb373763d34c49a827ba32ab9edf99ac1adba7cd0106dca8608437d2d4b96a021427e8f3603b4e1406d15194b70e4c581481a844456b465867672ffde09caee89c19bc076de510a7b60a3f0c83d1161b49dc820be6dfd96c5036d557dad8fa5832d8f390015259c2a37288d9b842acb1474f171e38f0c5e030c67d6a4c8bf029d8921e0ad39be5f8a2cb843cbf369c09be07227197dbede47d5c839101288fe68fcecda462bd426219a19ef7b240fa89537aa8726a46d00f86153e4f0d8a4cef05942499ef94c7153ad0edd8b56624f73e8cb16d57bdfafa35826067aa25ade0f19a843aeef49b2f38ef41c1f5fafd121db7129e65f495b62c04dc4ad62f2a4d27c3679e869a9f82e4ad60b0a6bb678a5a08fa6812d39feed13609aff93cac8ecf3ca8a732424360073f466c9bf8103b08bbc1662e9845e953e94ed5ebe86371292782fbbd65ef11b1c58d889284883f2b7b3fb1e1749819c6ca0da31cc32d19ae807e307ea50662b63bd161907799370ba4f9b0374b66acd1ce70d781211696b719cdd8ba71277ad3d8ddaf2ac63ccdf7d3670505cc81e9ab85fc571e02eb60674d5c27bbc64cd8e8bfd204d613a57cbac76cb161b43235fb13cf71701ca93467f9caec30d34b2cfe90a733159296137991030e4fda306b91e86804d180a913231bfe241a59575b7e6be743bc0ae89da8a0c72526154fd52e5044c90ccf4bae0f776f43b06401dcdaee74b485e80b9f0b5911bc2326955ab27298db636905251fb4f7e665d53086aa92544d90da62bfddf2c97377211917e7dcd8114a8f8b28cd21bb064d0378e7e12ef365ae9c4b5ee889f0a856330cdfc60d4ac80894a700dbe6b27714b5c0e1c2ee843f4fbba3c7c5c85c25fe80abe30b17bf08336530033920cce1a49886b4c1d8a0c16b383062eecc9b751d00dc6dd33a3f0cad0b62eab694ec230c73b29290628f3b63a2d3017bb12adf33a1a6254438f6a75bb0eba0d5ed9f5f4163068cf89f86584a295e56e5ae49e20b69c3110c2f57259e611e873c512422192275156334b3ed40908a671a468c9600073dd4b802fde96b4bf0776b76452ae369776876cc47f70907599e28b8e9da8a817487f2183e813ed1d711342ff20151eb3bcf2a9f4a4e41876143b1d0224fa460d065090afafe733ebb545a622db76712515107299ece0b48a2a8dfdfbf20fae2baa4ebbe79ca95d8ea72214f287642f5b6f18d26bef083701e0208d54fc54bb4a39118cb9d7e7cfb4972036e708e6841e1b32251835b0144a039bffb87fa79e981da9e10ae8baacfaa598a71c759da0c128e3260c2d190364b8d65f545ce97a58d", 0x782}], 0x2)
openat$pci(0xffffffffffffff9c, &(0x7f0000001740), 0x80, 0x0)
r2 = accept$inet(0xffffffffffffffff, &(0x7f0000001780), &(0x7f00000017c0)=0xc)
r3 = socket$unix(0x1, 0x5, 0x0)
writev(r3, &(0x7f00000018c0)=[{&(0x7f0000001880)="b71ce0c1886ee7500e0b389e98699c", 0xf}], 0x1)
setsockopt$inet_opts(r2, 0x0, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000003c80)="e90ca9cff960b6c077a382ada16c36ae057c1a7c4e2a03bb05a7b2950b1faec59e4a4af20da33f906e0fe16a1c9defee2b1aaf6e028531637726c126544bb8e412c00c258805994ebc1a806c51aaa4618278062fb3cbb160ca75e97bbe80b68435a017a71f31733366d6b10def9fbe65621622484f703e2fa9e2783e22892115d70d555fc84896", 0x87)
r4 = semget(0x2, 0x3, 0x80)
getsockopt$SO_PEERCRED(r1, 0xffff, 0x1022, &(0x7f0000003d40)={0x0, 0x0, <r5=>0x0}, 0xc)
semctl$IPC_SET(r4, 0x0, 0x1, &(0x7f0000003d80)={{0xfff, 0x0, 0x0, 0x0, r5, 0xd, 0x1f}, 0x1, 0x8, 0x3})
writev(0xffffffffffffffff, &(0x7f0000000180)=[{&(0x7f0000000000)="9da8e3e9ed", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
getsockname$inet(r2, &(0x7f00000000c0), &(0x7f0000000100)=0xc)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r6 = socket(0x2, 0x3, 0x0)
r7 = socket$inet(0x2, 0x2, 0x0)
r8 = dup(r7)
dup2(r8, r6)
connect$unix(r6, &(0x7f0000000000), 0x10)
sendmsg$unix(r8, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x0, 0x0, 0x10}, 0x0)


sysctl$kern(&(0x7f0000000000)={0x1, 0x48}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000000), 0x2, 0x0, 0x0, 0xffffffffffffffff, 0x4)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
socket$inet(0x1e, 0x3, 0x0)
select(0x40, &(0x7f0000000000), &(0x7f0000000040)={0x20000007fffffff}, 0x0, 0x0)
ioctl$FIOASYNC(r0, 0x80047466, &(0x7f0000000200)=0x4)
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000000)="b8", 0x1}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
readv(r0, &(0x7f0000000040)=[{0x0}], 0x1)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
write(r0, &(0x7f0000000400)='v', 0x1)


ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000000))
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


syz_emit_ethernet(0x2e, &(0x7f0000000140)={@broadcast, @remote, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x1, 0x0, @remote={0xac, 0x14, 0x0}, @multicast2, {[@lsrr={0x83, 0x3}]}}, @icmp=@generic={0x0, 0x0, 0x0, "e10f46cf"}}}}})


setrlimit(0x8, &(0x7f0000000980)={0xb, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
writev(r0, &(0x7f00000004c0)=[{&(0x7f0000000000)="bf0909b98732e43a60ee63c33dd9cb7de67102649ec14a5cde", 0x19}], 0x1)
r1 = socket(0x18, 0x2, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r1, &(0x7f0000000080), &(0x7f0000000040)=0xc)
syz_emit_ethernet(0x36, &(0x7f0000000400)={@broadcast, @broadcast, [], {@ipv4={0x800, {{0xa, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @empty, @remote={0xac, 0x14, 0x0}, {[@generic={0x88, 0x2}, @timestamp={0x44, 0x10, 0xb, 0x1, 0x0, [{}, {}, {}]}]}}}}}})
r2 = openat$klog(0xffffffffffffff9c, &(0x7f0000000100), 0x40, 0x0)
ioctl$LIOCSFD(r2, 0x80046c7f, &(0x7f0000000140)=r1)
r3 = dup2(r1, 0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r4 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r4, 0x80286987, &(0x7f00000001c0))
connect$unix(0xffffffffffffffff, 0x0, 0x0)
sendmsg$unix(r3, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0xa, r1)


sysctl$ddb(&(0x7f0000000000)={0x9, 0x5}, 0x2, &(0x7f00000000c0)="c79b9758", &(0x7f0000000080)=0x4, &(0x7f00000001c0)='\x00\x00\x00\x00', 0x4)


unveil(&(0x7f0000000040)='./file1\x00', &(0x7f0000000080)='c\x00')
mkdir(&(0x7f0000000340)='./file1\x00', 0x0)
unveil(&(0x7f0000000100)='./file1/file0\x00', &(0x7f0000000140)='c\x00')
open$dir(&(0x7f0000000000)='./file1\x00', 0x0, 0x0)


mknodat(0xffffffffffffff9c, &(0x7f0000000100)='./file0\x00', 0x1000, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
open(&(0x7f0000000100)='./file0\x00', 0x615, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x1d}, {0x24}, {0x286}]})
write(r0, &(0x7f0000000180)="c5449bc1708e16b9805a099e20a0", 0xe)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ftruncate(0xffffffffffffffff, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)
open(0x0, 0x0, 0x0)
mmap(&(0x7f0000ffb000/0x4000)=nil, 0x4000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
setrlimit(0x3, &(0x7f0000000000)={0x7fff, 0x100000})


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x80})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETD(r1, 0x8004741b, &(0x7f0000000140)=0x7)
writev(r0, &(0x7f0000000100)=[{&(0x7f00000009c0)="8a29e29a863bf3d9349ef6e169488cea77bd55a00689bffc55da9f9bbaedadef5fe55c98134b439974b873468fbf58b27013b1d604ed13c664231eb0ccccdfa6570c043272fb296a2f125405088e18b72b437c26461497ad9405c6dcf297a0a9aa4ac9429042f4b24abec18a8b955a5caedbbdfdd3f57a70e8536c04d115f142082772e6512999cf99eabd1b1f84c8fa8cd47811c5dfa4ed9ea3ab92402abc3efb80c49eb7e373d92c76cb22da8cf546a947f112bc5dbeb03c89f72555ebb70034d486149f28b05da48864cbf2f7c5adc8f51e0c7f1de4408786f4159c42ac1411ee68d1eef5e1cc7c54cbb07e30124c0bf2548976b189347ad325cfc2a2494c71737b3163698895fee2ebdc4d85ad544659faafd27174e0c84d1a538c7b2c9df23323815df69f8dac0f0093b80b0bd1283d40848032f592373eb5d268efc5424418b0352a2ef31cb5eb68052ee6faa2a3ec67c55bbc933766e8d057ec92996cf05c877edcdac3fb20b7592c4a77c8df317619d5030352ce21067ddcc7186b01c64bed7cbaa249ad242cc627", 0x18c}], 0x1)


setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000040)={0x0, 0xffffffff, 0x9, 0x203519, "28b7e60ab87aa57800000000d0d2000000001c00"})
rename(0x0, 0x0)
mknod$loop(0x0, 0x0, 0x1)
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000380)="06480eca9d478631b6cbe23e37e6d816b2b597a9980dcc297aeb3399a9b478b32e3d32d69260f557ac39fae10af920906672fdea9d9945ae55ea74887eb4988e1018149d02a0c119de688723d2079cc2b90daa2a836976ccacd2722b36a1ec0ca5d5043f730ae839ff5cf30e25dc0feb876e2579dbfd5b3c68699c5286761d47cf8c2f6332b48e4eea4199d8e14128faaf3019d9258ea8a62c7f8c98975c7870e8416fdd02827dcec2569d61917f3d18f0431e5a1c656da599fa195ed4c13fd8d211a1290e83cb38850688", 0xcb}, {&(0x7f0000002280)="79dcdf7e3555933ff826233e03433c5613a5485e54a4a9cdbd453163180082ccba5e54eddede8a3f3997e3b4f481c91973085ca2353dcaeec6edf7d0a986cc6d7d30fc4d2ddadd701292c3e46377c8e01f25008f666767c5fcaebfec104b13bd73ae038aafb6868635dc3b00ab79c4234379f6f4e2e14868f79d31e85735606218e9329ebbda19b51eca771e0da731c22771e16d7b0d1a20bb2a57f32180b1ebac6c3d695db9", 0xa6}, {&(0x7f0000000240)="9a99c311875acdb2a479c23d591a6201135973d431d30a7c6b1133322d1e227154657476e756444564362367887f0b98a374a86b1c3c39526c63", 0x3a}], 0x3)
writev(r0, &(0x7f0000000000)=[{&(0x7f0000000b80)="4b8572730e51a93601084c480dc1199dc57b2495e54e7209c4c7ad688b2768a5c2dc2606cb3396fe19b7684fece0172cf942aa0b7918b45b0efaf120cb28eabf16f7c5000b4159c5d1cc872d79ad1721703966da567664630f2106236f5650fdbfa8246401bb352764be4b6fa3ebc0b99a3665bc25216ba50581e8c9aff5a6691e97bedc672c5e8e3ed4bd372eb4db334603c9fb94a733c8f0455f4285c7b298e66cf9bebb66f447e2fa9afbb8108623ef393b169cbd255c6b3db0b76f90ed460706c5193c7b1f5066d2dbf51d6cd727629cd778450dcb36f693bb26b75e82299e4e39eeac9ae3122c7ddd1adc48621758141b0dca303454edf70ff1e66f574bfa184fe03fd13aadfdb7b196087edddc571ab8a8bf9d9676b2a22ba7e946a26377f29f53d461fbe5238b3ba135febe2821ce168c88fed545c6f82874285b00254d20ec65a168817dcd0157821d9c0c28d4790c62cbf67b6f71982c73fcbc5f943204b649b6313e879d2cd92c788aab06c014a89b3523de83b305e047a0d9ca6acb8bddb5de9aae120000f2eac0b8b83c9502f70f80a627d784037f333ed300c3a993e252ea24c9f5e1d12a5ab0ba3c0346992a80e1cb91283b459e5aeb7d2a03e0a55f27f2b0cacd8c62743f7ca5e9b0541d92a623ff7772df5ec5d228c087209b69c903b0b779defd39352daaffbc17424f5dd6480c80fb74ca117ef2a6870e590350b913d139afbc581ba6e2d87fd7a9b6e8d91b41afa9531e53a297e6474afc5c5e651eb9696a43eac3a3ec4813", 0x22f}, {&(0x7f0000000600)="6099fbdd9cc44bf7dc52000028adb25e275b8138589de3e05be278b7889f45a4d0b2f5458cfecee79ebe509a8ea6d3", 0x2f}, {&(0x7f0000001280)="730b6c66732ffec6851a540a37647d21f804dfa2bea63ff61b79061ea84bd6a5b9422c77620e4f4892d6c5d3e2f03fa4c68a5bb37b4e0c2877695126c26a04345b5fd3cbaf7e19a47f56418a709ab3bbf8a652f1a2da200d3e550d100e77682ae4e2d15ba0fd8ef6852185678e3ea653e4dacdfac48dea260a53ae97b3912402b45603ffed183829fc0602f7b13acf039dc325829559b82dc75a3bff8edd773a075a5b036d47aa95258e40dc4a30ac578be10495134d62e98c1098ff216aa208b088dceaba4786509931eec12ab01723bfe54b76554bd9cbf76354c5bdbfca6e872f339954fc972f6717fafcfe59a502b08feac1349050b1b7dd558b200c0121eeb4e9cf855469a7d91972e15c1c744f6f3f75c27a3dd194ff5ca8537e8cd34d0b6b79a5b72abf92bf1e31a0548dde68013c6c841213807ea38f10632329210eb4d621650cd7271f1328a9be810848e24c88e9543c6c33937680ff0e0a205909f3827f993efca0381680d7bb624000dd066c36eabb6ebaa010ec079326b18dac2445d7f28c979afa8b8661b628b8282e217fe9698cc4cc5e0ed4547954881a137afdf0d929ec58cb8e797d0dc9cc2f9c18898104c85d5fc6427635f001f8ac8467c12a2e7a", 0x1c5}], 0x3)


syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b0e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000), 0x10)
r1 = dup(r0)
listen(r1, 0x0)
r2 = socket(0x2, 0x4001, 0x0)
connect$unix(r2, &(0x7f0000000000), 0x10)
getpeername(r2, 0x0, &(0x7f0000000100))


r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$PCIOCWRITE(r0, 0xc00c7007, &(0x7f00000001c0)={{0x0, 0x5, 0xfc}, 0x0, 0x0, 0x2})
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
ioctl$FIONREAD(0xffffffffffffffff, 0x8020699b, &(0x7f00000001c0))
read(0xffffffffffffffff, &(0x7f0000000180)=""/198, 0xc6)
setsockopt(0xffffffffffffffff, 0x0, 0x6, &(0x7f0000000040)="46647713d7e556403406bd67f36ea665", 0x10)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
open$dir(&(0x7f0000000b80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x200, 0x0)
r1 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000300)='./file0\x00', r1, &(0x7f0000000c80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f0000000dc0)='./file0\x00', r1, &(0x7f0000000ec0)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mkdirat(r1, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
symlinkat(&(0x7f0000000700)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', r1, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
writev(r0, &(0x7f0000000240)=[{&(0x7f0000000340)='oN', 0x2}], 0x1)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x1, 0x0, 0xff, 0x1}, {0x6, 0x0, 0x0, 0x7fff}]})
sysctl$hw(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f00000000c0)=[{0x80}, {0x24, 0x8}, {0x6, 0x0, 0x0, 0x20}]})
writev(r0, &(0x7f0000000000)=[{&(0x7f0000000240)="1234c147d168098b93029dfee05e", 0xe}], 0x1)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4e}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
openat$null(0xffffffffffffff9c, &(0x7f0000000480), 0x0, 0x0)
symlink(&(0x7f0000000180)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000280)='./file0\x00')
mknod(&(0x7f0000000000)='./file0\x00', 0x1, 0x6381)
open(&(0x7f00000002c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0, 0x180)
link(&(0x7f0000001240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
syz_emit_ethernet(0x46, &(0x7f0000000100)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa86dd60000000060000000b50003e00000700b77391b1000000000000000000000000000000000000000000000000000000002b"])
syz_emit_ethernet(0x4de, &(0x7f0000000000)=ANY=[@ANYBLOB="aaaaaaaaaaaa9cd7361987d486dd60ecea6604a80000fe8000000000000089750e6b000000aaff0200000000000000000000000000010020"])
symlink(&(0x7f00000004c0)='./file0\x00', &(0x7f0000000e40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000600)='./file0\x00', &(0x7f0000000f40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


r0 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f00000007c0)={0x0, 0x3, 0xffffbff6, 0x0, "6106a6bc44862c5008c8b503005a000400008fa8"})
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000240)="76f0b67c483a24febaee4d9c497b7e5f0bf12b7225efb6f6c869e646ecfa588c53283c4dd3ed77706f3868cacea799a3bdfb42db706563dca286f58274eac945d5ffe9054ffd5b7724b408516b9ed309d4751896dd052cc4", 0x58}, {&(0x7f00000002c0)="568446d880d32ef0a4986f171158031372c1c0db83a16c5e4be2133234bf17424dd50774a7f09fe9141026ae3dbd0596a1b641e991aacdb1d8e58984dbdd7c7f50b0c738ab060000000000000000f66d67a0240b68ef993576acc48f0e8ce55b8c7101000000000000000000", 0x6c}, {&(0x7f0000000800)="e163e56d8c18", 0x6}], 0x3)
syz_open_pts()
ioctl$TIOCFLUSH(r0, 0x80047410, &(0x7f0000000380))


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x1000000029, 0x35, &(0x7f0000000040)="03000000", 0x4)
r2 = socket$inet(0x2, 0x8000, 0x2)
setsockopt$sock_int(r2, 0xffff, 0x80, &(0x7f0000000080)=0x400, 0x4)
r3 = dup2(r0, r1)
r4 = accept$inet6(r1, &(0x7f0000000200), &(0x7f00000007c0)=0xc)
setrlimit(0x8, 0x0)
syz_open_pts()
close(0xffffffffffffffff)
syz_open_pts()
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x7ffffffe, 0x0, 0xe3d458f, 0xffffffe8, "1500d67d005b860000e30000008000"})
recvmmsg(r4, &(0x7f0000001a00)={&(0x7f00000019c0)={&(0x7f0000000800)=@in6, 0xc, &(0x7f0000000980)=[{&(0x7f0000000840)=""/49, 0x31}, {&(0x7f0000000880)=""/220, 0xdc}], 0x2, &(0x7f00000009c0)=""/4096, 0x1000}, 0xc000}, 0x10, 0x1, &(0x7f0000001a40)={0x2, 0x3})
r5 = msgget$private(0x0, 0xffffffffffffff41)
msgsnd(r5, &(0x7f00000000c0)=ANY=[@ANYRES8=0x0, @ANYRES32, @ANYRES64=r3, @ANYRES16, @ANYRESHEX], 0x298, 0x800)
msgrcv(r5, &(0x7f00000002c0)={0x0, ""/157}, 0xa5, 0xfffffffffffffffc, 0x1800)


r0 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r0, 0x6, 0x8, 0x0, 0x0)


writev(0xffffffffffffffff, &(0x7f00000000c0)=[{&(0x7f0000000000)="8d6bb85551ec8430", 0x8}], 0x1)
r0 = socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f0000000000))


syz_emit_ethernet(0xf9, &(0x7f0000000000)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaaaabb86dd6000000000c300000000000000000080000000000000ff020000000000000000000000000001"])
mknod(0x0, 0x0, 0x0)
unveil(0x0, 0x0)
socket(0x0, 0x0, 0x0)
syz_emit_ethernet(0x4e, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
truncate(0x0, 0x0)
preadv(0xffffffffffffffff, 0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
syz_emit_ethernet(0x6e, 0x0)
r1 = socket(0x18, 0x1, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f0000000080)={&(0x7f0000000140)={&(0x7f0000000000)=@in6, 0xc, &(0x7f0000000040), 0x0, 0x0}}, 0x10, 0x0, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x6381)
r0 = kqueue()
r1 = openat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x0, 0x0)
kevent(r0, 0x0, 0x0, &(0x7f0000000580), 0x65, 0x0)
kevent(r0, &(0x7f0000000140)=[{{r1}, 0xfffffffffffffffe, 0x9f}], 0xd, 0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000040)={0x7fff, 0x0, 0xa0000401, 0xffdfff8d, "1ba5d82d727c660800"})
writev(r0, &(0x7f00000003c0)=[{&(0x7f00000009c0)="471e49aab0fd752532784bf2515fa242320b4a6e6543ffda060eb842b843d370b936ddaa7f71a0a0c4074da827c862a93983c361dc12dc50305653dd84a6adfc8761f897b60c4dee402807473103485b4475c657ae5428aa89543eec1819c76b9eb1e5c1848e49a2a588ed0f6ac77d2106b8ed9b8e3bf7a033cdd96085e372fde5a0d0e2fa622a7e28febd0934ab925ca1", 0x91}], 0x1)


mkdir(&(0x7f0000000000)='./file2\x00', 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
r3 = socket(0x2, 0x2, 0x0)
r4 = dup(r3)
r5 = fcntl$dupfd(r4, 0x2, 0xffffffffffffffff)
close(r5)
r6 = socket(0x2, 0x2, 0x0)
shutdown(r5, 0x2)
connect$unix(r6, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r5, 0xffff, 0x1023, &(0x7f0000000040), 0x4)
setsockopt$sock_int(r2, 0xffff, 0x1023, &(0x7f0000000040), 0xe0)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047470, &(0x7f0000000140)=0x2)
ioctl$FIOASYNC(r0, 0x80047460, &(0x7f00000000c0)=0x4)
ioctl$FIOASYNC(r1, 0x80047460, &(0x7f0000000180))


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x3})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x27}, 0x4, &(0x7f0000000000)="71f91e3471ac0058bc5a91501d942400b5e1a0757cb9af769c7afec37082", &(0x7f0000000080)=0x306, 0x0, 0x2e)
r0 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1023, &(0x7f0000000040), 0xe0)


syz_emit_ethernet(0x3e, &(0x7f0000000000)={@broadcast, @remote, [], {@ipv6={0x86dd, {0x0, 0x6, "b42f2f", 0x8, 0x0, 0x0, @loopback, @ipv4={'\x00', '\xff\xff', @rand_addr}, {[], @udp={{0x3, 0x1, 0x8}}}}}}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
mkdir(&(0x7f0000000000)='./file0\x00', 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000180)={0x3, &(0x7f0000000000)=[{0x3}, {0x35}, {0xffe}]})
write(r0, &(0x7f0000000200)="d81ad3d20cf7eb4e9be33bbd1a30", 0xe)


clock_getres(0x6, 0x0)


sysctl$hw(0x0, 0x0, &(0x7f00000001c0)="90cb55a661b973835a2b266aeb8d375424f5b0deed9f1055509c0280c3fe63f8b1965025b325ee5c080000000000000098ce461470", 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0206923, &(0x7f00000001c0))
ioctl$FIONREAD(r0, 0x8040691a, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, 0x0)
setreuid(0xee00, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x2801)
r1 = open(&(0x7f0000000280)='./bus\x00', 0x0, 0x0)
close(r1)
getuid()
setreuid(0xee00, 0x0)
ktrace(0x0, 0x0, 0x0, 0x0)
openat$wskbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$WSKBDIO_SETENCODING(0xffffffffffffffff, 0x80045710, 0x0)


mkdir(&(0x7f0000000100)='./file0\x00', 0x0)
r0 = socket(0x2, 0x1, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
open$dir(&(0x7f00000001c0)='./file0\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
recvmsg(r3, &(0x7f0000000340)={0x0, 0x0, 0x0, 0x0, &(0x7f00000024c0)=""/236, 0xec}, 0x0)
chroot(&(0x7f0000000740)='.\x00')
sendmsg(r2, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)


syz_emit_ethernet(0x119, 0x0)
r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000040)={&(0x7f00000000c0)=[{0x101, 0x2000}, {}], 0x2})
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000180)={<r1=>0x0}, 0xc)
r2 = socket(0x18, 0x2, 0x0)
close(r2)
r3 = socket(0x800000018, 0x3, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000000)=0x7, 0x4)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x7fb, 0x0, 0x0, 0x0, 0x0, 0x140, 0x3}, 0x0, 0x20000000002, r1, r1, 0x1000000000000000, 0x4000000000, 0xffffffffffffffff})
bind$unix(r3, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
openat$pf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
poll(&(0x7f00000002c0), 0x0, 0x0)
r4 = getpid()
ktrace(&(0x7f0000001d40)='./file0\x00', 0x0, 0x1720, r4)
clock_getres(0x3, &(0x7f0000000280))
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r5 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x81286947, 0x0)
pipe2(&(0x7f00000001c0)={<r6=>0xffffffffffffffff}, 0x10004)
readv(r6, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r5, 0x0)
r7 = msgget$private(0x0, 0x0)
msgsnd(r7, &(0x7f0000000040)=ANY=[], 0x0, 0x0)


r0 = socket$unix(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x40047309, &(0x7f0000000280))
socket(0x10, 0x5, 0x5)
munmap(&(0x7f00000f2000/0x3000)=nil, 0x3000)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r2 = socket(0x2, 0x1, 0x0)
shutdown(0xffffffffffffffff, 0x1)
r3 = socket(0x11, 0x3, 0x0)
setsockopt(0xffffffffffffffff, 0x11, 0x1, &(0x7f0000000140), 0x0)
r4 = kqueue()
kevent(r4, &(0x7f0000000080)=[{{}, 0xfffffffffffffff9, 0x1b, 0x12}], 0x1, 0x0, 0x0, 0x0)
kevent(r4, &(0x7f0000000040), 0x4, 0x0, 0x20, 0x0)
setsockopt$inet6_MRT6_ADD_MIF(r2, 0x29, 0x66, 0x0, 0x0)
getsockopt$SO_PEERCRED(r3, 0xffff, 0x1022, &(0x7f0000000140), 0xc)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
r5 = socket(0x2, 0x4000, 0x2)
getsockopt(r5, 0x11, 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r6 = socket(0x18, 0x3, 0x0)
r7 = socket(0x18, 0x1, 0x0)
setsockopt(r7, 0x1000000029, 0xc, &(0x7f0000000100), 0x0)
connect$unix(r6, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r6, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
r8 = socket(0x18, 0x2, 0x0)
socket(0x18, 0x2, 0x0)
connect$unix(r8, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x0)
r0 = open$dir(&(0x7f0000000040)='./file1\x00', 0x0, 0x0)
openat(r0, &(0x7f0000000100)='./file0\x00', 0x400, 0x20)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
r1 = socket(0x2, 0x0, 0x4)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
open$dir(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
r2 = kqueue()
kevent(r2, &(0x7f00000000c0), 0x0, 0x0, 0x0, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x80, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000680)={<r3=>0xffffffffffffffff})
sendmmsg(r3, 0x0, 0x0, 0x0)
kevent(r2, &(0x7f0000000100), 0x81, &(0x7f0000000200)=[{{}, 0xfffffffffffffff9, 0x2, 0x0, 0x7, 0xc1c}, {{}, 0x0, 0x0, 0x0, 0x5, 0x5}, {{r2}, 0x0, 0x0, 0x10, 0x0, 0x1}, {{r2}, 0xfffffffffffffff9, 0x6e, 0x1, 0x1, 0x3}, {{r2}, 0xfffffffffffffffe, 0xc4, 0x10, 0x1f}, {{r3}, 0xfffffffffffffff9, 0x3a, 0x20, 0xfeb, 0x1}], 0x8, 0x0)
poll(0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, r2)
r4 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r4, 0x80206979, &(0x7f00000001c0))
fcntl$dupfd(0xffffffffffffffff, 0x0, r4)
connect$unix(r1, &(0x7f0000000100), 0x10)
getitimer(0x6, 0x0)
getsockname$unix(r1, 0x0, 0x0)
bind(0xffffffffffffffff, 0x0, 0x10)
sysctl$net_inet_tcp(&(0x7f00000001c0)={0x4, 0x18, 0x6, 0x9}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, &(0x7f0000000480), 0x0)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x6}, 0x4, 0x0, 0x0, &(0x7f00000004c0), 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000180))
openat$vmm(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)


mkdirat(0xffffffffffffff9c, &(0x7f0000000100)='./file0\x00', 0x0)
mkdirat(0xffffffffffffff9c, &(0x7f0000000000)='./file0/file0\x00', 0x0)
r0 = open$dir(&(0x7f00000001c0)='./file0\x00', 0x0, 0x0)
r1 = open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
mkdirat(r1, &(0x7f0000000180)='./file0/file0\x00', 0x0)
renameat(0xffffffffffffff9c, &(0x7f00000000c0)='./file0/file0\x00', r0, &(0x7f0000000280)='./file0/file0/file0\x00')


ioctl$TIOCSTOP(0xffffffffffffffff, 0x2000746f)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0xc0206921, &(0x7f00000001c0))
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0xc0206923, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$FIOSETOWN(0xffffffffffffffff, 0x8004667c, &(0x7f0000000180)=0x101)
ioctl$FIONBIO(r0, 0x8004667e, &(0x7f0000000100)=0x5)
openat$tty(0xffffffffffffff9c, &(0x7f00000000c0), 0x80, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x6381)
mknod(&(0x7f0000000000)='./bus\x00', 0x2000, 0x6380)
r1 = open(&(0x7f0000000140)='./bus\x00', 0x0, 0x0)
r2 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x4)
dup2(r2, r1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000140)=[{0x84}, {0x2d}, {0x40e}]})
syz_emit_ethernet(0x103e, &(0x7f0000001980)=ANY=[])


open(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
r0 = socket(0x11, 0x3, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
openat$zero(0xffffffffffffff9c, 0x0, 0xe8, 0x0)
ioctl$FIONREAD(r0, 0x8020690e, &(0x7f00000001c0))


r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
socket(0x11, 0x3, 0x0)
r2 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x100, r2)
ioctl$VNDIOCSET(r1, 0xc0384600, &(0x7f0000000600)={&(0x7f0000000500)='./file\x00', 0x276, &(0x7f0000000540)='./file0/file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x81})
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r3 = openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r4 = shmget(0x0, 0x400000, 0x5, &(0x7f0000bfe000/0x400000)=nil)
shmctl$IPC_RMID(r4, 0x0)
r5 = getpid()
ktrace(&(0x7f0000000140)='./file0\x00', 0x0, 0x1424, r5)
fcntl$lock(r3, 0x8, &(0x7f0000000640)={0x3, 0x2, 0x8, 0x401, r5})
ioctl$FIOASYNC(0xffffffffffffffff, 0x8004667d, 0x0)
ioctl$VNDIOCCLR(r0, 0x80384601, &(0x7f0000000340)={0x0, 0x0, 0x0})
readlink(&(0x7f0000000080)='./file0\x00', &(0x7f0000000180)=""/72, 0x48)
getuid()
syz_emit_ethernet(0x2e, &(0x7f00000000c0)=ANY=[@ANYBLOB="aaaaaaaaaaaa002e00000000080046000020000000000001907800000000e0000001440400004e204e2300089078"])


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000000), 0x2cfea}], 0x1000000000000013)
mknod(&(0x7f0000000000)='./bus\x00', 0x3a0914c44f7b202d, 0x0)
r1 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
ioctl$TIOCSETAF(r1, 0x802c7416, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x0, "247497496ed3ffa429fdb9102575e414229eb682"})
execve(0x0, 0x0, 0x0)
sysctl$vm(&(0x7f0000002e40)={0x2, 0x9}, 0x2, 0x0, 0x0, &(0x7f0000002f80)="8162", 0x2)
sysctl$vm(&(0x7f0000000000)={0x2, 0x7}, 0x2, &(0x7f0000000040), 0x0, &(0x7f0000000180)="23e6139a508b7f724d62714ff6fb6c2783cf45eb14c32a85e3d84a7c70b13a2f7bbf5b76f377c6a9bb30d39e0432b05a622e36f345f2ccb09abc5cf10597aff54e33d96a41aaef646b61bde30bb91cee92333c1a7aff29a1de43acd037f9c598f78bf9edb6ecbe580902fb68305a5f187a8cb73656f84d378cd03d954da126c3d3e22e6a1012dc62334979aa0817147ca1aacbe53cd9deaefcf0bf21a3f2cfc746aef3870e02d997be0a8eb4bce82eae87db94541069d320defff192c928b8cb66d437620f293c0814", 0xc9)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x0, 0x0})
socket(0x0, 0x2, 0x0)
open(0x0, 0x0, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r3 = dup(0xffffffffffffffff)
ioctl$BIOCSBLEN(r3, 0xc0044266, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
madvise(&(0x7f0000000000/0x4000)=nil, 0x0, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
utimensat(r3, &(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)={{0x7, 0x36a5}, {0x6, 0x8000000000000000}}, 0x2)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
write(r4, &(0x7f0000000140)="7696e5f7ffff8c37cea8615ac7cf", 0x2c27945c880b947b)
syz_emit_ethernet(0x4f, &(0x7f0000000400)=ANY=[])
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f0000000100)={0x10, 0x0, [{&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000af2000/0xf000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {&(0x7f00008e3000/0x4000)=nil, &(0x7f0000f52000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000826000/0x1000)=nil}, {&(0x7f00005f5000/0x4000)=nil, &(0x7f000093c000/0x2000)=nil}, {&(0x7f0000da9000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000e0a000/0x2000)=nil, &(0x7f0000648000/0x2000)=nil}, {&(0x7f0000b64000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f000062b000/0xf000)=nil, &(0x7f00004df000/0x4000)=nil}, {&(0x7f00004e0000/0x4000)=nil, &(0x7f0000000000/0x1000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000b04000/0x3000)=nil}, {&(0x7f0000ecf000/0x3000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f000064c000/0x2000)=nil, &(0x7f0000c2c000/0x2000)=nil}, {&(0x7f0000c2a000/0x2000)=nil, &(0x7f0000518000/0x3000)=nil}], './file0\x00'})
socket(0x1, 0x2, 0x0)


writev(0xffffffffffffffff, 0x0, 0x0)
msgsnd(0x0, &(0x7f00000001c0)=ANY=[@ANYBLOB="020000000000000059ef0714392d67"], 0xfa, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000001c0)={0x0, 0x0})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
poll(&(0x7f0000000300)=[{r1, 0x40}], 0x1, 0x1000)
dup2(r0, r1)
ioctl$FIONREAD(0xffffffffffffffff, 0x8020699d, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000680)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f00000000c0)=[{}, {0x87}, {0x26}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x32}, 0x2, 0x0, 0x0, &(0x7f0000001440)="cca410df", 0x4)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xffffffffffffffff, 0x0, 0xffffffffffffffff})
sysctl$kern(&(0x7f0000000040), 0x7, 0x0, 0x0, 0x0, 0xfffffe88)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="fe"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0x9, &(0x7f0000000040)="00040080", 0x4)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


r0 = socket(0x18, 0x3, 0x0)
getsockopt(r0, 0x29, 0x2c, 0x0, 0x0)


syz_emit_ethernet(0x23bf, 0x0)
socket$inet(0x2, 0x0, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VMM_IOC_RESETCPU(r0, 0x82405605, &(0x7f0000000280)={0x2, 0x0, {[0x0, 0x0, 0x0, 0x8], [0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x400000000000], [0x0, 0x0, 0x0, 0x0, 0x8000000000000000], [0x0, 0x0, 0xfffffffffffffffe], [{}, {}, {0x0, 0x0, 0xfffffffe}, {}, {}, {0xfffc}]}})


r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000001bc0), 0x0, 0x0)
close(r0)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
r1 = dup(r0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x1009})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
socket(0x1, 0x2, 0x0)
r0 = socket$inet(0x2, 0x2, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x1, &(0x7f0000000100), &(0x7f0000000140)=0x4)
setsockopt$sock_int(r0, 0xffff, 0x1, &(0x7f0000000180), 0x4)
r1 = socket$unix(0x1, 0x1, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x4, 0x0, 0x0)
link(&(0x7f00000002c0)='./file0\x00', 0x0)
recvmmsg(r1, 0x0, 0x0, 0x0, 0x0)
openat(0xffffffffffffff9c, 0x0, 0x0, 0x0)
readlinkat(0xffffffffffffffff, 0x0, 0x0, 0x0)
r2 = semget(0x2, 0x1, 0x0)
semop(r2, &(0x7f0000000940)=[{0x1, 0x27}, {0x3, 0x0, 0x1800}, {0x1, 0x7, 0x800}, {0x4, 0x3ff}, {0x4, 0x818, 0x800}, {0x0, 0x7ff}, {0x1, 0x5, 0x800}, {0x2, 0x6, 0x800}, {0x1, 0x1}], 0x9)
clock_settime(0x2, 0x0)
pipe2(&(0x7f0000000000), 0x8000)
r3 = msgget(0x0, 0x0)
r4 = getuid()
getgroups(0x0, 0x0)
msgctl$IPC_SET(r3, 0x1, &(0x7f0000001040)={{0x2, r4, 0x0, 0xffffffffffffffff, 0x0, 0xa, 0x3}, 0x0, 0x3, 0x0, 0x0, 0x2, 0x0, 0x0, 0x5})


r0 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r0, 0x0, 0x20, &(0x7f0000000100), 0x0)


r0 = syz_open_pts()
poll(&(0x7f0000000000)=[{r0}], 0x1, 0x0)
ioctl$FIOASYNC(r0, 0x8004667d, &(0x7f0000000240)=0x7ff)
syz_open_pts()
syz_open_pts()


open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
r0 = getpid()
ktrace(&(0x7f00000001c0)='./file0\x00', 0x0, 0x40000534, r0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket$inet(0x2, 0x3, 0x0)
recvmmsg(r1, &(0x7f0000000300)={0x0}, 0x10, 0x0, 0x0)


openat$bpf(0xffffffffffffff9c, 0x0, 0x100, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000040), 0x3, &(0x7f0000000080), 0x0, &(0x7f0000000180), 0x0)
setrlimit(0x0, &(0x7f0000000000)={0x8000000000000000, 0xfffffffffffffffc})
kqueue()
getpid()
setreuid(0xee00, 0x0)
socket(0x10, 0x3, 0x0)
setitimer(0x2, &(0x7f00000000c0)={{0x3, 0x80000}, {0xfffffffb, 0x100000001}}, 0x0)
open(&(0x7f0000000200)='./file0\x00', 0x100, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x0, 0x0)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}, 0x0, 0x0, 0x2})
shmctl$IPC_STAT(0x0, 0x2, &(0x7f0000000240)=""/155)
syz_emit_ethernet(0x66, &(0x7f0000000100)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa86dd6000ec0000302c00000000000000000000000000000000000000000000000000001a"])
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sysctl$hw(&(0x7f0000000000)={0x6, 0xf}, 0x2, &(0x7f0000000040)="d2737fc886c1625cab16db1ea60281fd246dc3bab1f7", &(0x7f0000000080)=0x16, 0x0, 0x0)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x1, 0x1, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106978, &(0x7f00000001c0))
close(r1)
socket(0x18, 0x2, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendto$inet(r1, &(0x7f0000000400)="2117cecd05058af5fbce692fb209c0a9047b41d6e3ae771b0ad4031990ec2e2dde0df1fdf6e6a6be5dd94d4f404a8a50ec891bd907fcf8cd4339a97014ee830ec9fb5289f68bd993ae017c359e2f2b656c164c662350cfd3dc778b43352b22c8bc6d9163fa7f245783877b4e079b27ae9b51327132faae536f9006c5d632ae323eb4fc169738c872d524c2cc8451eeef5aca89298580c2e9377d2e967a8e32c5352db2ae293fb6081ab052d1ef19c73c38f4ebdb48d8e2d08e865f9ce0cc5a45beb520e2f24582721811d7c25b3461f53e71f78f0104a532cefe4b2299d4c9196b2cf30629cbfc65a076962ca893ed597e1f55786b272f2d7ec734925f6f7f7c17dea858469f89e90f45ae03aefcd7906d950160f0a2206e16fc0ad156ce8c3bca6f8a55ab64a15cf54e076438f2f28dc428481b57839a42067b04680f4b84734717c23165cb1a5557d6b75fc53c723deddea0e49c8776cbe8dcdfea616e86825bfb31f2b22f368aae1f287d3ddc0aa878bb1a13559b248d12bcce19914ef04299699fee55cb48ca16b7eecc0c4dc9ec7768afb4ce3638266fbad4b8de0d796ca7b0b57ac809608bddc34ddbf2dfd588d3628aa6783c41cbca4e7c9b4a94a67e050010ea1888e3757edb45c7dd184b4aa7c6601fc222f436f9e93a86ccba0b9a8f495840139999fe411afc67ef1bb6734d62a032ba20f695740993d3700849409940728e393b64aa6aa5ebd4caebd7832e3af32b6a9b77f70c4e168d5ac0f0a9f90bbe93dfdb0f017ddc752b08ec6d29f6b8886686e2132917a04fb3bfa11c5820406352788a1b4ec9486508bdf4a3053e02f8195ad4011a8272807ef271e59355bcaca5e9277d7299520c91f322178bfd9cd215a0294b415eb239b96a6b09e8b66ab911f9fb5981675f0b0f641c9fdcccb442a7eb4e998b03c02803ba8f5b93e7c9f1a53fa8cae728ecf072e80973e682f317d9cb97dd3d036907830714a791f665c684269c93c552459c8336724342d0387142e5c6dc530584a01bfa8b4a8affa4ddf7578a95c95abcb5bed8baa966651872dec1d582d17c6fb077f621e0eca00010ca7170281046c7db83ed38448234841cbb661c0cf331ca42cca0253195394e1ce570ed0d9008e31171c2bcb62f1af19abf97840ede00c8fe0f00d205d955e9bfb1328348b4a0adccf847adfa9a7875b8ce79a8b79a16fddbc4773d70bae3e75b3eb8e4bd105f31762e7bca015329561c9d480a95936fa42362607f5de2fa87f27d7a4286418f661771ac5cf9ce11ff861094933e5ffd6bc81b5ae88fe6f38ee5a77305a3f161bb20ed402ccd487288ae8e2db673b2c307d652e16f8bcfe2b4e6c90801228b5c2be7446011bd1f4d10781b204a2aa581215f2ed227b5dcab7026c70e2d90f30af451ac69c478c2f2af58ac2e90b104842f7594cc522750161b933ae722606094c94aa256cbaab34f2aa78907b33bf25fc262261893b64a83446e34444a918bce76921fe4ec70d85c996edf0864230779436add2bcd5646797331ad5931824ff8fd30ee2ab745533bf61c79d12818bcbd34803d0090ed93dbea03f20ade53223f02d1a6b04fc09ef5d612c6da30dbca5e75bed1ef6b73fb5ee7eafc78580b126fe4cf2c4ecda8539b83ee785f8e6c9de1de1ad612c8b5190e7451fe9bb0e207a86373860ffdedcde9eca7407c741f2664e23a125f25c023041e2d98b5ab290d05d098c974f9fa896bb4c987f35342813d96e451b06afa738a0621711779cc91058c30c34b71038190ed171116a8b994b333f70b3cc457608be4549854f878d9f075a25d9e4039a9442df45ed2c45f63ca9c4d51b7fe5da01815afcd269a788e38fc4599985bd68782f58754fb209d970f6f928cab2f77707d3991c66a9d2e7ec42f014297d433bc5feb51f383db02febea974260f0aa3e5534cc18ee9fa395f8499b76e7544132218f8a66a0e16d284ed82ce72cbe1e5faed12bc82b3e8c0e4ad6fe6808da69b8eecf9a7818086360cdb6ef4d0fe54a6fe3d5a3420fba7420d4baed661840d63", 0x5af, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000140)=[{0x14}, {0xc0}, {0x812e}]})
syz_emit_ethernet(0x56, &(0x7f0000000000)=ANY=[])


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000040)={0x0, 0xffffffff, 0x80000001, 0x60451d, "1a0c0100000400000000000000f2d87e3200"})
writev(r0, &(0x7f0000000080)=[{&(0x7f00000000c0)="f2d98d803406fd3f3ae5de618b17e9c1863bd9118a145f9927f34224a70b765f5806ae62f1ceb57a7b93f96e8e8dc14b12f84c4831d1d73185fab7287794eeabb85c67aecbdc7e3b26d4e0960bf6856696a6b425ecd390f200df7bf5c8130233405cd8380398effd73af2948c02fc62f8a9361f8b7e8e0ae77a11789fac5b770be9346f42a68b0c6c8968e1168dacf63730a99da1e9a73951895db801b8504", 0x9f}], 0x1)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f00000001c0)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe1463a52077dc0d00003ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')
execve(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0x0, 0x0, 0xffffffffffffffff}, 0xfeffffffffffffff})
socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = open(0x0, 0x0, 0x0)
r1 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r1, 0x80105728, &(0x7f0000000040)={&(0x7f00000000c0)=[{}, {0x23}], 0x2})
sysctl$hw(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
semget(0x0, 0x0, 0x40)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
fcntl$dupfd(r2, 0x0, r3)
recvmsg(r0, 0x0, 0x0)
sendmmsg(0xffffffffffffffff, &(0x7f0000000080)={0x0}, 0x10, 0x0)
seteuid(0xffffffffffffffff)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
close(0xffffffffffffffff)
socket(0x0, 0x0, 0x0)
readv(0xffffffffffffffff, 0x0, 0x0)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1800000029"], 0x3e}, 0x0)
recvfrom$unix(r2, 0x0, 0x0, 0x0, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
getpeername(0xffffffffffffffff, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r4 = socket(0x2, 0x1, 0x0)
bind(r4, &(0x7f0000000000), 0x10)


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
dup(0xffffffffffffffff)
socket(0x0, 0x0, 0x0)
openat$pf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
getpid()
ktrace(0x0, 0x0, 0x1720, 0x0)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
fcntl$lock(r1, 0x8, &(0x7f0000000200)={0x0, 0x0, 0xfffffffffffffffe, 0x10001fffffffe, 0xffffffffffffffff})
r2 = getuid()
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r3=>0xffffffffffffffff})
getsockopt$sock_cred(r3, 0xffff, 0x1022, &(0x7f0000000580)={0x0, 0x0, <r4=>0x0}, &(0x7f0000000140)=0xc)
chown(&(0x7f0000000200)='./file0\x00', 0x0, r4)
setreuid(0x0, r2)
getsockopt(r0, 0x0, 0x9, 0x0, 0x0)


setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000040)="fd04c084", 0xfffffffffffffdbd)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
clock_settime(0x100000000000000, &(0x7f0000000040))


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
r0 = open$dir(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
preadv(r0, &(0x7f00000004c0)=[{0x0}], 0x1, 0x0)


sysctl$net_inet_udp(&(0x7f0000000000)={0x4, 0x2, 0x11, 0x6}, 0x4, 0x0, 0x0, &(0x7f0000000040), 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x1, &(0x7f0000000040)=[{0x60, 0x0, 0x0, 0xfffffffe}]})


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206916, &(0x7f00000001c0))


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
seteuid(0xffffffffffffffff)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
socket(0x18, 0x2, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f00000000c0)=""/49, 0x31}], 0x1)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1800000029"], 0x3e}, 0x0)
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)


getpid()
pipe(0x0)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0x2e, 0x0, 0x0)
setsockopt(r0, 0x1000000029, 0x2f, &(0x7f0000000000)="eb929648", 0x4)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x181, 0x200}})
socket(0x10, 0x2, 0x8)
socket(0x18, 0x2, 0x0)
socket(0x18, 0x3, 0x0)
r1 = open$dir(&(0x7f0000000280)='./file0\x00', 0x0, 0x2)
fchown(r1, 0x0, 0xffffffffffffffff)
r2 = socket(0x11, 0x3, 0xc1)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000000080)=ANY=[@ANYBLOB="aaaaaaaaaaaa450b08bfa22f0800450000280000000000009078000000007f0000014e224e20", @ANYRES32=0x41424344, @ANYRES32=0x41424344, @ANYBLOB="00000000000000fc"])
ioctl$FIONREAD(0xffffffffffffffff, 0x8080691a, &(0x7f00000001c0))
connect(0xffffffffffffffff, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x3c, &(0x7f0000000000)="030000", 0x3)
close(0xffffffffffffffff)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040))
setitimer(0x0, &(0x7f0000000140)={{0x0, 0x1c0}, {0x9, 0x3}}, &(0x7f0000000200))
sysctl$ddb(&(0x7f0000000040)={0x9, 0x5}, 0x2, &(0x7f0000000080)="6d65f783", &(0x7f0000000180)=0x4, &(0x7f00000001c0), 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000001440)={0xffffffffffffffff, <r3=>0xffffffffffffffff})
r4 = fcntl$getown(r3, 0x3)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x40000000001ff, 0x0, r4})
r5 = socket(0x18, 0x3, 0x0)
connect$unix(r5, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendto$unix(r2, &(0x7f0000000040)="b100050400000400000000000101000000000000cea10500fef96ec0c72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b1257aea8c500002018fbfe0c2300008abfba0900000008e371a3f83437320501eab71d89e0000405f8ffffff13000000", 0xb1, 0x0, 0x0, 0x14)


seteuid(0xffffffffffffffff)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
getpgid(0x0)
getpgid(0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
setreuid(0x0, 0xee01)
shmget(0x1, 0x2000, 0x221, &(0x7f0000ffe000/0x2000)=nil)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000080), 0xc)
semget$private(0x0, 0x0, 0x0)
semop(0x0, &(0x7f00000000c0)=[{0x1, 0xffff, 0xe5ce97ab354d96be}, {0x4, 0x4}, {0x3, 0x0, 0x1000}, {0x2, 0x6}], 0x4)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
setuid(0xee01)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206980, &(0x7f00000001c0))
r1 = getpid()
r2 = msgget$private(0x0, 0x0)
msgctl$IPC_SET(r2, 0x1, &(0x7f0000002f80)={{}, 0x0, 0x0, r1, 0x0, 0x0, 0xa})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000100)=[{0x7c}, {0x40}, {0x16}]})
write(r0, &(0x7f00000001c0)="d9537abde93d050cdd16b13f742a", 0xe)


socket(0x18, 0x1, 0x0)
socket(0x11, 0x3, 0x0)
socket(0x11, 0x3, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0x0, 0x0, 0xffffffffffffffff}, 0xfffffffffffffffc})
socket(0x0, 0x0, 0x0)
r0 = socket(0x18, 0x0, 0x0)
getsockopt(r0, 0x29, 0x31, 0x0, 0x0)
socket(0x2, 0x2, 0x0)
sysctl$net_inet6_icmp6(&(0x7f0000000580)={0x4, 0x18, 0x3a, 0x3}, 0x4, &(0x7f00000005c0)="2195c4ce", &(0x7f0000000600)=0x4, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
socket$inet(0x2, 0x3, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r2, 0x8020699f, &(0x7f0000000100))


setrlimit(0x8, &(0x7f00000000c0)={0x7, 0x51})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
close(r1)
ioctl$FIOASYNC(r0, 0x80047469, 0x0)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000001a00)=0x5)
writev(r0, &(0x7f0000000080)=[{0x0}], 0x1)
writev(r0, &(0x7f0000000240)=[{0x0}], 0x1)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x10000})
r2 = syz_open_pts()
close(r2)
syz_open_pts()
sysctl$net_inet_carp(&(0x7f0000000000)={0x4, 0x2, 0x6c}, 0x4, 0x0, 0x0, 0x0, 0x68)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000000)={0x0, 0x3, 0xfffffc16, 0xfffffffa, "0afff5ff7a095aeba1d76ff218aabc86001800"})


mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0xd02)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0xb2}})
mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
socket(0x11, 0x0, 0x0)
link(0x0, &(0x7f0000001380)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000480)='./file0\x00')
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x0, 0x0)
ioctl$BIOCSRTIMEOUT(r0, 0x8010426d, &(0x7f0000000440)={0xc0000000000000})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
rename(0x0, &(0x7f0000001080)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
syz_emit_ethernet(0x46, &(0x7f0000000080)={@broadcast, @random="ac566789c541", [], {@ipv4={0x800, {{0x9, 0x4, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, @broadcast, @multicast2, {[@timestamp={0x44, 0x10, 0x7, 0x1, 0x0, [{[@rand_addr]}, {}]}]}}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})
r1 = socket(0x0, 0x0, 0x0)
socket(0x0, 0x3, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
preadv(r2, &(0x7f0000000000)=[{&(0x7f0000000c80)=""/4107, 0x1000}, {0x0}], 0x1, 0x0)


open$dir(0x0, 0x300, 0x0)
ktrace(&(0x7f0000000300)='./file0\x00', 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
recvmsg(r1, &(0x7f0000000100)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000180)=""/225, 0x11e}, 0x800)
sendmsg(r0, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)


mknod(&(0x7f0000000300)='./file0\x00', 0x2000, 0x6da)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f0000000640)=[{{r0}, 0x7ffffffffffffff7, 0x1}], 0x6, 0x0, 0x6, 0x0)


r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
mkdir(&(0x7f0000000000)='./file2\x00', 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x2, 0x2, 0x0)
connect$inet(r3, &(0x7f0000000000), 0x10)
r4 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x1023, &(0x7f0000000040), 0x4)
close(r4)


r0 = getppid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r0})
pipe(&(0x7f00000001c0)={<r1=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r1, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r2 = getppid()
socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000015c0)={0xffffffffffffffff, <r3=>0xffffffffffffffff})
fcntl$setown(r3, 0x6, r2)
pipe(&(0x7f00000001c0)={<r4=>0xffffffffffffffff})
fcntl$setown(r4, 0x6, r2)
ioctl$WSKBDIO_GETMAP(r4, 0x80047476, &(0x7f0000000100)={0x0, 0x0})


pipe2(&(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff}, 0x0)
r2 = dup(r0)
write(r1, &(0x7f0000000180)="c3d9b55e98af6de748d2544ff675ee1d4f17caffd0488fb8f152357d636b5badfdba0d80f2b541aa0aeae04c9269dc153a16360ee033c104c1aca88cfb745a282d6f25ec423842d744c3d426cabf7ee12b0600d53d46a60327af167e7bdd596af339f97c9f4840b1aad48f716764e721bcfe659992c7bde8471e582b3c20311f28e029eea114355f37bd23f2d08c9b6ba776ae67bee81f7d5c42b987a8330f8ec9aa34833e492ad772c89defef9aed87e34014b5373c79345170e7a6fd998cb4883f85910e2792b7701a6684853f5d3d10b330bf98d7fcfb89ad0e02e3fbcaaf84e410dd0590e0bbeabb70b904b8f2068f9ad04aacc4bbc321f9ea581ad7372dc7b2efc8961406e1279dcfc11b4ba6fe58d76a2a85af708f6f42b8721a4d534df8d2277198304861464d615eb0b3ae543119edaaf78a591f035bd87faa8d9955f508f1766d46e4657e20de81837595ea84bbb45e857669f2a9639de786be1e9ca0ccef1a33e2231300242965ffc90d04313ec0c1fb54700ca9fd2609766fd8bbf7cbf8b6e84361fcc0413e739d4df4b411cedaa2dab76c6c732325e255d13c077f1fe1b89c1e3632a15bb19cddd29c4b67921fb60961f5b2fd01b740f8aa852c62913c131bc63d71eaa27683ed01752eccbf15240e6153d95abb34481289a2068ab9441f0e6fc958eaa0c1161320d278e182bb035859ca9f36c72680c254969ade8a38f7df01d6dd702d061c9886c6ccfe12dc859e7a35cdfac10819cff9babe300704a607776f8977e606e3782b65d62c1270a3c90e0cd69f29c68ce78647a39b4821fa5a9fa9ab580603d15ff6f9628deda56a0f9650db460176443823d059c439194c0df25eb1c4fdb3945c75db6db36acbbf62c29a146536a28dd05a770bbe3fbeb2763cfe7af68a49b972528413d12ed9d8eaaa4723a969cd3ae7f775222336bb1ddb1c8eb02f4749f0a2d3b3670d7ff51fff42225ee2b8d92d7a373d8f85610ebffe4a12a0878c731fa4e0cc422ac82acfdad8af849043ceb3a31f219d0ef5adb73844c18a967ead05d4adf4497c392002082ded259aa4276a4922af9b221606f94c83303d68d4b6161aafdb7adbf24070345836274d58d304b5243a4f0b84a3eaad3132a5e761458d582c36cb7260c79d7e0373f83786e8eade42dae9bb3cf07633aac9f7920fe2cb45da8cd63e6b93cebf1562caa4425f1ea89624c0147db63c7f1578787815c2928fdf2129302f649ffc7d82cdf47d70cde1b0c2d440dbdc64f0ab24e162c79453407eaea824abe9b53cd05b01d5ce0af4470ca8791cc3a4471fcf0fc64488eb51b07de2faddd8944093440f3813cd2fd0afc06f5333fc992801225622830b1ed9f6873b6ecd452209136f57bc9dae96e98e7d9cc30d227e12123cd56fc5cfb76b0098d3326ce998876ea5b034aebc6102d710b473685df2bc213e608f814c40053ce66e172d42cc0f5a41352d3f1f14afc1a0db3e0b17055c3671ca20cac4dcc1062a52070e20a8b24c000a8d601ca95716fb32c184b780d60c485b5d98f89cfb0ab0bbbc6b763f49cffd4900bfb890a51fdc746b61766372cf95f3d3f8ab5ef7a46e6222d2f10354b6b4e27339802e928b4a9e513035d56c166b07f9b3fa60e8f94687eee6b07ea572fd81c40b29547cd987224af146a64355e67bb308d99f69ea406f3567c12db3dd70aa56c7bbcd247481d7a734f724a232f1f5d336c7618c458b2d23bdffbcfceb9c37bc582598ef336e92f9ad8cf7984612e94d46e768093b12906df1e7fb69bd5a607ed993099f6376bbf769270673a4fd55df7cf7ac03d58a78c2f25e7cf1ff439c42485b79ba3d7976f3783c01cb5a6de1bdb9b23eb88f8de2060636e6e034e5f65b64987880e027c861fcbbd7e1f60d8ba10b0e217e050b44aefba5ba8804fa6df602c063e61eba4cddd271708cccff3ab1d475cfab54fb574f5da1e698ca05bd402ccbaf131bdfbd6ea676dbb086e959c9d47f0e87bec21511b2f8d2546f89643e7f9ce43f2bd32f422bd727b1503cf513d4edf49a56665e61b584156559b8b120f667f748000e0183b31dfdadc856e8226b8a4d5c0396aa08d698962020b4bfe951a694433c085f6dfe9a63aca70f7d9a84ed79d86ee217b7a497423469a114bf1c51dbaf15e38cac31962e1b38cc21a407c4e5b91d467099cffe679ab7b33669adabc75cc345ddacbe8c867e1456661f4d6634704278e744389b46143ab1297f6b4f9ccd352b50f0288549f91c0955bc2a1b047919b45a344a94434686a641395e6c10f88fba7ead0ced62dcc66489ef4342c69fcd8dd27a1f9f81cace022d7ad1e825904b3039626762fd1d0a95268705088cb63e6ee6cb8e4f2827b19076bae67ed62582f1849ac833cedf9ccbe7fd371c98eff0e68f9bb96b20f7af9a3db4cc64921476cad1bfd719f7e4fb4c8ca9cb545f9cb66331d375b772b461abca22a39a1cd9a7a2e8da3dac05ad8c27ae73e4b28f8d8ac4f7461e7d3fd6aa28d488c3d8695260912c08fe4adb981be4551c99bcbac6f08419f36e5f490c8be222e85fd4e85a3af4eda491f4a19a8cad876d300f370de7f1699bab7a88721a4b13bf45e65567ded57295d030348c2624ff7066d359d7e0c69942d824ee06537d882e4f34ba68f0d4abc45b5108e743db85be310b6fe682077c710b89de621f63a6d14abcfd031843804bb6206bdb38b0bfe72c10a1b41d2e363f984d43320300f08b207d886cdd06d0e38765301e343d3281c807fcdb30c7a07f3f82bbd2da0ac1e9bd9a03b6aa3cc4620c29f7edf6ea4b112a9b0fe70fcd1a2e61beb1c1eab98db8747b687a7b74d1d74a5068f89ebb759fa1b221db9cbdb39bd310007437f0662e0fc9f2ba61ba06231d462f90129f3ca876b872bfb9bef2e18d13b03450cc044c849004bbd5f108cd116b0c126374048e73ad30ecf0e5fcc43d2815c14f4b96d813c5527415465f68350e272f8298e697adbebec34af58c162d13659d2e3ae41bc142826ebb6c72cbd8063f26d274218ff335eed8ae606e7bc3c3ebbf9a7a453369f967332c60b43afe9207f2b88683f4387e2d3f7b0087b9e6fc35a68d622f2b37c8ded7e06e1e5fc5e147603c59bc1aa624f7a221383a1b78caacb7c4767690eed9008b95af74ac6ca25e823763f9042c843ad0437cb6e3018ef4c6f024641dfa4f2b5a18483081915fdcbb57114092c00131a7e962405f277378198914755b1d78d7a4cc20587bcea2f09c3f1eee9e4ba7b9e2a1f155c08e3e3dde2a4f54080c09cce98a8a7ecafb84f8ac81dc75d0a1e32cbb1e06c57d8583206dbd2d97a8289086d88ed8bf3a7043d6a1e9fdbe7b8aa353dd380d8d7ee575e5d1585620aa7016111f5576fe8b6108ab808284577dd87c0873f2d560e02a2213ca09f55d8163db8f29cc9c05006f645d776d21e77542a1064e2495fb5fb58604213ecc45c8da8de60c14ed9658e91b895cca8cd296fe90a0be9d79b0f683b3e79addc4870c4f618ce776cdfd966c80b1ef924a34a79c5dbf8293112180354a047ee5dd3543c129875214c4c76d046c6a2c76b00b912e9b0449894e88c9cfd491dfbb479c6010496e0fadba45c7c55791ad56bc963e631953086c6d9f97fe8975caa60107ac394f5e631f655362e9862b34c976617ea41cf1dbb6a4b9e088ac46e3650e95e94c095ea830f0de0fceed7cbe2933cc395a4a6c22964173934a70b70d92502cce447c5eb4973f30abc41405f77194fe9762e3d6cbde47588b9f123dfc4c87d0dc0edd37dd64fba3714c3734763e0e84d12e94c77f0ec96043288426acc303fafb3b94161c9584fd306edcb686b92463f28799513002a104c36c4eb8b797afa894d881fe5c2a0f4489fdc3daba0ffe547a413d393b48e548c05a58404b6ad87d9ea00391ece2484c20123d3dbd0468d26dc2ef6803539b7eae6a3913f78fa5db42590c72e4b7a7ad4daa1635ce397862438507eb8f48e8d5bd91710e5624cd4d851763a5e9b8e0190b3a5d0bac2da0053430731fa2e0d64955f1dd4c1c582e935bced0770923e7264b3f64689df4a5a056eb7eb1470a70500582470706d39e8eeab131ef3943eebd42353a0df72b80ee7775fd5fffa6edffbfe901f32f47c59d0ba02fcc61565c11530f98bebed9c15771bf3a9956e4297929f56ca4f2a4d6b6ac61b56d5658ce03d086fe2610aa827f849e8e714f2a2302e3a653ae0fdcdaced30999b8a6a6002d66cc18cf3b3cef2d8110e1f4f1328aef6fab108de3b06d7fb856d06606d74ee5b825b7d0ad6d514ebf40a752b681dea701a6165f7b894a31acfba8fb7df1e9f468c9f396de84623cdad2faca0f5e679d310092b11293c084b1a511ef625c457f423e4361a1a15875e9e3d7e639fbd9614f563edcf18a63e3c75db7c63366a7434dc25b0ac2cc63bfc2f7d2190058acb0f620d14424e59006b1a0598d5f025038155d14f45ec26addf104053a5ba6e286bbcbab04b3f8332c28c6d4617e65fa4fe9451535bda5a9434127920a83050f3d9900557b23cd6eaba47b1de3c947c3384716712bce25710f10f6ced80397cc614e403e0bb960d650c301fd43098f5acec6f8ab4b1fa3db7131b7e06497eeff8ccc780a141bc20ccb3b5e48be59ecd6fc3ca6df87ccf1343eae4d1e5074cf37910e3d4c6493b1674c895457c4e83a7f0f16de5d9c18a0ec3db8454dd9fe1ef6ad60b782ab2d8d2df6145cd057f51fa3f19bf4da4dc110e73bc6efdf4c3748a506d99b7e8fcb791ef716ed74c4c88148f9738d94fbe15a5cd1a5b6c5bb1acfe555ad87d5539968a7a519cf6ab7d0a705f95a0c559f7d9c47d48bb98be8d648d70ec9876b6a182c0feff555a9eef23cc0eec019d7573253fe675d9ce6764154ae4f40c692318deb390512119e9b2e6a2c5b7cfe68f26fc96ec596222c65ed3a97c8bb8e1e77ff6db35bc042e5071bf1540e97884e36373a4f4ec5c061fde9f68e19b7c8ecdb93e441e612608341baf3ff529b6437c9eedd1a7d8a76f79fa38265fff1a94bd12ca2a7e1a064ba74a942d208180c645c0e1530eceb17c6a6ee0b3c63b56a8c6c79f36fc04651fef47fff4b5c7a7886bde71cbbae07f551c289800f139cab82bdfe2e90a0929655e524852d5d2c916b2bfc1dc8de38bd3f2a46a62949a089ec10842b8c09cc4eb243ac03c44d1fa11db3d8fba48278149a7916384537f9edbe67323e21f9799da8ee451bc71a4c0ce90d0b71a1f9d2cd3be3eacc9d0f45fef5c9e29637c6c515631adde998fc129cd055fef1abfcfce42b9ef3da1a227b4d438cd700d01f65efaf8c673d72ad26cf837d3a6a4aa55fc57d40adfe7710da428d022e6b6778149922df62e346775fcdfda9803c28830da46b0646c9309952f1e05b965d88bef9a859c1e666baad1662d519f79db1b8d86e3cbd0b76a4204956181dbde565f3eee95acf3548d9035b61b5ab105465a07726b695e27f8b18d4848da180f4e7f70c50b4aaaf5f7c4bb97c334faf336c3fedb0e7cab55c173b9b78f5fedc636a51328f822765c5b64027fe2605b07168444e1a27b061a2b12404a24c4b4105f2b9de486b9098ba29e02cd43b7f781a7ae7e858eae036ea22a1b5ca9cb5872a69b7e64691036432c6109dd9f9d6233e67dd7c8bd07de9c23f4583e7ef6abda596c4cb669cfc46f9d3752fd1edc1281fd55cd9f1d886d43f4b3c34913a9ba9495940fa09b46f7d6ded372ab199c0562dd2c414fa1063341033863ef2fe8b95ba413a94ab4099717325ad98", 0x1000)
read(r2, &(0x7f0000001280)=""/4096, 0x1000)


mkdirat(0xffffffffffffff9c, &(0x7f0000000080)='./file1\x00', 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x1, 0x0)
r2 = socket(0x18, 0x1, 0x0)
setsockopt(r2, 0x1000000029, 0x36, &(0x7f0000000040)="03000000", 0x4)
dup2(r2, r1)
ioctl$FIONBIO(r2, 0x8004667e, &(0x7f0000000080))
connect$unix(r1, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg(r1, &(0x7f0000001980)={0x0, 0x0, &(0x7f00000017c0)=[{&(0x7f00000005c0)="57931731cc275c29b1aed3194c6f37430ae48885be99e6b3178c33b1b52f8fa3020763ade3e8010e64c4eb1290ead2acd688118cbcb7a7198705d6301f3cdb2808d786b455db1f997546e8359481b1fe28", 0x51}, {&(0x7f0000000640)="aaff4c51883e004b5f89075a5ddd67f3227908132e2bbca76867b831115dd2fee04f802fa2035c2cdce42602ad61953030e0ebbdf951b204afb415cb2d7571951eeb", 0x42}, {&(0x7f0000000700)="b573975435f384a446acefe3a9c8435fc53be209a95faaa9e582cdd3c8a869899283ef37e7a1f35b03048a939cff0bc18e0e95a0", 0x34}, {&(0x7f0000000740)="9e4673eb165000ef76574090ce780f20f8b3e79fc550b83c59ae6a9ec6fd01a2e59aba4cc2c70ff2a43ae8a76577758607271189d73e487865d275ca686b14c7249ef2619b5f3d2c15c4a57f1c3a996c0883b491a712ac372d1291b0d5f5c7ead631680269803c3482f368433f4fcece46f6d75471dff907485ff9e2387b4176556545f30ed78986606d1978acd39b868a25527876e5cc072759a0554e0386", 0x9f}], 0x4, 0x0}, 0x0)
recvmsg(r0, &(0x7f0000000500)={0x0, 0x0, &(0x7f0000000440)=[{&(0x7f0000000180)=""/97, 0x61}], 0x1, 0x0}, 0x0)
r2 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc028698d, &(0x7f00000001c0))


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f0000000000), 0x1)
socket(0x2, 0x2, 0x0)
socket$inet(0x2, 0x2, 0x0)
r0 = socket$inet(0x2, 0x2, 0x0)
open(&(0x7f0000000180)='./file0\x00', 0x611, 0x0)
r1 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r1, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000401})
r2 = syz_open_pts()
syz_open_pts()
syz_open_pts()
close(r2)
setsockopt$inet_opts(r0, 0x0, 0x0, &(0x7f0000000200)="00aa7fdbc4972736856e40430e3922c6c1fdc0d87669d4fb52807efc84e650a4ee52d36030f1f4e3a430a40257f57bd638e2b0c48adc4d1766179ee03b01e2b3eadf85b8520d0e51724e24decb19647c0071c047d84162b20bc2c0ad94f8c708fcaf2794704479f2de081e4ff382", 0x6e)
pwritev(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f00000005c0)="dc", 0x1}], 0x1, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r3 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r3, 0xc0106924, &(0x7f00000001c0))
r4 = kqueue()
kevent(r4, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r5 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r5, 0xc0206921, &(0x7f00000001c0))
r6 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r6, 0xc0206921, &(0x7f00000001c0))


ktrace(0x0, 0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000002c0)=[{}, {0x2d}, {0x16}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f0000000080)=ANY=[])


r0 = getuid()
setreuid(0x0, r0)
r1 = socket(0x800000018, 0x2, 0x0)
setreuid(0xee00, 0x0)
r2 = socket(0x18, 0x2, 0x0)
close(r2)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
r3 = socket(0x800000018, 0x2, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x104}})
r4 = socket(0x18, 0x1, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r4, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
setsockopt$sock_int(r3, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r3, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r5=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
msgget$private(0x0, 0x0)
getpeername$unix(r5, 0x0, &(0x7f0000000540))
openat$null(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
rename(&(0x7f0000000080)='./file0\x00', &(0x7f00000000c0)='./file0\x00')
mkdir(&(0x7f0000000080)='./file0\x00', 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x3}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)="03000000", 0x4)


getsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{0x7c}, {0x50}, {0x157e}]})
writev(r0, &(0x7f00000002c0)=[{&(0x7f0000000340)="ebebfd510bbcd3a9b489e989c14f", 0xe}], 0x1)


msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x30}, 0x0, 0x0, 0x0, 0x0, 0x8000000000000000})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x1, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = socket(0x800000018, 0x1, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "1a1116f0d0f700"})
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000900), 0x0, 0x0)
close(r0)
getsockname$inet6(r0, 0x0, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140))
socket(0x0, 0x0, 0x0)
dup(0xffffffffffffffff)
setrlimit(0x0, 0x0)
syz_open_pts()
poll(0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
open(0x0, 0x0, 0x0)
ioctl$TIOCSETD(0xffffffffffffffff, 0x8004741b, 0x0)
setrlimit(0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x800000018, 0x2, 0x0)
r2 = socket(0x18, 0x3, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r2, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
semop(0xffffffffffffffff, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
writev(r1, &(0x7f0000001140)=[{&(0x7f0000000140)="88bcbec1d4f5f45ff1b97d9a3842269301a8aa59f0e8a8d35901555d6ed3a413950a1d8c46bac7c10adb871acc7a432be467fc46d4ea1f098b14c76997eca135415e6979f9b415aaa0f1dd5160917b028f32fc3f17b14d432f8869ee0b51d4dbc4d9c7ab75edb1e8d21a03c2f96479ad4a82a1ab6a424389a85ff9ad2f8c87ace187844fab78f56bd41f2da37ab4ab2db2bb534f3c2d0eb4b5248fb543d6d2d9351bdf9db0dc5774dc33ed16a0e438148b9973a7d2883ed7b09b6f2fef1f4264cf0c0978a4acd89a4ba1d784048600f93fd56c47c9363af1254af9078fa955ff1237189606bf2fd8836cef3b9a98208c706156af20bf19e452aa1621a71650fc6633a7ed7cd3621f629a7ed48d1c71b9e4258370c1d7ebf33a7b48c5f77d5b003c692be84498b2a92dc51656916bfed0c9b51de1820eade3d6d3ad0cc80978d7e21646ada91b308570745d4991be774a295475947d414e3833162a9c4594a015f624d8c7a22911a5014dca00f089ae29386fd91e2b2e8fecb5a5311df8e4bcc023e77cca243888673077c0996cfcf82ca67b874e71b067dbfdc544a3025de232632ff3df3a4ff5dae1e9d9082ae4a7618988fa879f58ad58682d61a515b40571f69d3a67fffc0bb7974c09e5809265e1e5d2902632005589db84367d1b2ad161aead9bd00f9a88db7079b7682ac45abfb75a73ff1e1cb26f696b497b43ef0e2670c2538c3caffb476f6b97543fb664958d5ab707d9f39c5c85622518207d965dfc17aff3dc41a6aa6e442810e825c85f1553af68bd2c253c19d38492bc54372c506bb9c24cd080183cb73163b8d65f9d4aba8c6303d522ed45737372e7bc760006e716498971a03ff1b0b163df6b28a2bea07dc8af4afc6aa656aa39d4949d443456fc1fd8f2ef9ac73dc0fe973b10a027202d50b44442147cf7e158850e31398a10f48002875a07ccdb16a5357d5f7165606f0a91889225624ad7e45afebf6c3b50336f7551417f726bf05a098f624ff49848a5a94285b31791fa3972083e466869213c9f286b2aa90927b131c657841d02fdd8fe1d4e3eff002ffb3ffc9e90db96f723dc75908ea35682ea607b0499c0e36925157a87abe2df9b8674821a33a197d35cb3b28ee7fe5de7299f2176d633685f79291732ccf5684cb8b93d25da972ee9b627ed05a8a8090f1e2adde1a88ea71ad98266b4d3c353d8d87a09d2c5d0f2a7093666f48487c348008f59765a258958d7207565dbbb3a75a9e03a6b640be989c26061f42a30bdad3ba4d36567f951377e2e86d6c66e744988071013f2b76ecdd76be4c9b288d9407216fd595b8d00a472c251bf8d1ef7785c39d69355963d271133a22e94722d4bc76e0828f8dc146f5e9e053df725a489e83ec64f853670626ddd31aab52ad82a67356b34e5c2f0b793ec060369f0eeac2a0e14f9bab410e13827f4f83027d80859e0e75e2718d51e977c89cef9bc04fb979f65edfb37fb4a692120311ef8ebc51b19d963ff0632bd065c093c696b34da035370822584cf396e13b2f3a345add0767c13fddc340b2d08d3da5d6e14f285520e3803516be13357897dad243e5ba7188ede9e601f87f981fdd2c27ae7acdc687e26b77272d57d3518c71fd31fe44a5ecea99a81b8bb5147ee869d0efdb44f6a90dc00b6d2b313844eaf9f137d9fd8025f66ad5eac43d2d1ac8ed20e25fb4c282f8cfd5f42a3492ee36291b13ed05a57c7627851f5", 0x4d1}], 0x1)


setrlimit(0x8, &(0x7f0000000980)={0x9, 0x51})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r1, 0x80047460, &(0x7f00000000c0)=0x3)
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)
ioctl$TIOCSETAW(r0, 0x802c7415, &(0x7f0000000180)={0x0, 0x0, 0x524, 0x7d34e0f4, "8159ec285f3a3d0ec7b29a5b69aa64272588542f", 0x3ff, 0xfffffff7})
writev(r0, &(0x7f0000000040)=[{&(0x7f0000000140)='H', 0x1}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000080)=[{0x35}, {0x34, 0x0, 0x0, 0x800}, {0x8186}]})
syz_emit_ethernet(0x10a2, &(0x7f0000000080)=ANY=[])


setrlimit(0x8, &(0x7f0000000980)={0x7, 0xca})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000140)={0x7ffffffd, 0x0, 0x407, 0x6b384155, "2ff2ee6098610d023900"})
writev(r0, &(0x7f0000000280)=[{&(0x7f00000002c0)="c4075c27", 0x4}], 0x1)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
socket$inet(0x2, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f00000002c0)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, @multicast2}, @icmp=@echo}}}})


r0 = getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r0})
setpgid(0x0, 0x0)
setpgid(0x0, r0)
open(&(0x7f0000000180)='./file0\x00', 0x75f493fec6515f78, 0x0)
pipe(&(0x7f00000001c0)={<r1=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r1, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r2 = fcntl$getown(r1, 0x5)
setreuid(0xee00, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0xb32, r2)
setreuid(0x0, 0x0)
ktrace(&(0x7f0000000140)='./file0\x00', 0x4, 0x1808, r2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{0x25}, {0x5}, {0x46}]})
syz_emit_ethernet(0x36, &(0x7f0000000840)=ANY=[])


ktrace(0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$wskbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000380)=[{0x34, 0x0, 0x0, 0x2}, {0xb1, 0x0, 0xfd}, {0x8106, 0x0, 0x5, 0x1}]})
syz_emit_ethernet(0x56, &(0x7f00000003c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r2 = socket$inet(0x2, 0x1, 0x0)
listen(r2, 0x0)
shutdown(r2, 0x1)
select(0x40, &(0x7f00000001c0)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_RESETCPU(r1, 0x82405605, &(0x7f0000000280)={0x3, 0x0, {[0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x100000000000000, 0x2], [], [], [], [{0x0, 0x0, 0x0, 0x7}, {}, {}, {}, {0x0, 0x3}, {}, {0x0, 0x0, 0x100}]}})
flock(r0, 0xa)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x0, 0x0})
r3 = syz_open_pts()
readv(r3, &(0x7f00000012c0)=[{&(0x7f0000001200)=""/1, 0x1}], 0x1)
ioctl$TIOCSETA(r3, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0xffffff9a, 0x0, "b07b1f660000000000002000"})
syz_open_pts()
ioctl$TIOCSETAF(r3, 0x802c7416, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "0fdb000000000000000600000000000000d900"})
r4 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x200000000000a, &(0x7f0000000040)='\x00', 0x1)
setsockopt$inet_opts(r4, 0x0, 0x0, 0x0, 0x0)
pipe(&(0x7f00000000c0))
syz_emit_ethernet(0x3e, &(0x7f0000000100)=ANY=[])


sysctl$net_inet_esp(&(0x7f0000000140)={0x4, 0x22, 0x32, 0x3}, 0x4, &(0x7f00000000c0)="00d5a153fcbb42fc4b67223b8998951ab3b14275d4e6ad8093870566ef975560ce0487b6598e5caef3d4356f70e7a206056d354d9a3d0fe05929ab2c2a202f222317b63e024efaffffffffffffffbe2fe466041419f69ee3b6bb16d91f26559ff54a2cae377653a35b52e2f85d33e009a106adfff5bc74", 0x0, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
sysctl$net_inet_ip(0x0, 0x0, &(0x7f0000000100)="d7a8aac106fa1bee91c724b89283c1477dab85e783af4189a1eaf5f6e8251b1147b330f604ff639b9acd6202c9d8b1aef98ce6eefe", 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
sendto$inet(0xffffffffffffffff, &(0x7f00000000c0)="6c25a03ae7b27b4e7fc0924a22334b9b619f09f993c214bf34de94ee6f878793a443c48892901b940ff2189ae976bd635aa66dd55818d1ca20a7f88c2ad799df41ea701f32e36ab928f0ea3b00ddc5613e3590c04b342a5ec356d4f406e612653d7338e1b59ec0f00de4b65b3f18", 0x6e, 0x0, 0x0, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{}, {0x9}, {0xf7ff}]})
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


syz_emit_ethernet(0x17a, &(0x7f0000000380)=ANY=[@ANYBLOB="f3a2a8908a86aaaaaaaaaabb86dd601ab5b60000000000000000000000000000000000000000ff020000000000000000000000000001001d000000000000040100c204"])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000040)=[{0x1c}, {0x40}, {0x8106}]})
syz_emit_ethernet(0x3e, &(0x7f0000000080)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000280)={0x3, &(0x7f0000000240)=[{0x44}, {0x4d}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000240)=ANY=[])


ioctl$WSMUXIO_LIST_DEVICES(0xffffffffffffffff, 0xc1045763, 0x0)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
r1 = socket(0x1e, 0x3, 0x0)
sendmsg$unix(r1, &(0x7f00000006c0)={0x0, 0x0, 0x0}, 0x0)
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0206923, &(0x7f00000001c0))
socket$inet(0x2, 0x0, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000080)=[{0x14}, {0x5}, {0x8106}]})
syz_emit_ethernet(0x2a, &(0x7f0000000300)=ANY=[])
r4 = socket(0x18, 0x2, 0x0)
r5 = openat$tty(0xffffffffffffff9c, &(0x7f0000000280), 0x80, 0x0)
ioctl$TIOCGETD(r5, 0x4004741a, &(0x7f00000002c0))
r6 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000180), 0x100, 0x0)
fcntl$dupfd(r4, 0xa, r6)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x83fe})
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
setsockopt(r4, 0x1000000029, 0x3e, &(0x7f0000000000)="674cd6e5", 0x4)
chmod(0x0, 0x0)
ioctl$FIONREAD(r0, 0x8040691a, &(0x7f00000001c0))


mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
unveil(&(0x7f0000000300)='./file0/file0/..\x00', &(0x7f0000000400)='r\x00')
chdir(&(0x7f0000000580)='./file0\x00')
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)


preadv(0xffffffffffffffff, &(0x7f0000000080)=[{0x0}, {&(0x7f0000000200)=""/171, 0xab}], 0x2, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
r0 = socket(0x18, 0x2, 0x0)
getsockname$inet(r0, &(0x7f0000000080), &(0x7f0000000040)=0xc)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x3, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r2 = socket(0x18, 0x2, 0x0)
r3 = dup2(r1, r2)
sendmsg$unix(r3, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


syz_emit_ethernet(0x25b, &(0x7f0000000000)={@local, @empty, [], {@ipv6={0x86dd, {0x8, 0x6, "7695e6", 0x225, 0x61, 0x4, @remote={0xfe, 0x80, '\x00', 0x0}, @empty, {[@routing={0x37, 0xa, 0x0, 0x4, 0x0, [@rand_addr="4834da30028505a4317cb38499621529", @mcast1, @remote={0xfe, 0x80, '\x00', 0x0}, @local={0xfe, 0x80, '\x00', 0x0}, @mcast1]}, @fragment={0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x64}, @fragment={0x1d, 0x0, 0x8, 0x0, 0x0, 0x0, 0x64}, @routing={0x0, 0x4, 0x0, 0x2, 0x0, [@rand_addr="9a9a09b35688e0a1b1adfea3c505ddf7", @mcast2]}, @dstopts={0x1d, 0x0, '\x00', [@jumbo={0xc2, 0x4, 0x1ff}]}, @hopopts={0xa3, 0x1e, '\x00', [@generic={0x6, 0x86, "2e8b09ebfc37089f8efd9bcae12bf4f6ae0140709516804fd981b0d0b6aac12776d98228d4b9b82d58aef08fe7ccd08034f512b8ad428e1c00c69615cb6d2edd3ca0b2f62cd917f1e37fb3d1ef63ee4c1a011d91370d5561271921c1219a929fadf7d14e6e63ae7c057f96a76c458e5c374aa1daf1af0d7652231bd0f9f66c803efc7259ca4b"}, @generic={0x5, 0x58, "6d64835b9f370f3e769a437e3947f30c2465b41adb73e40cb2013c18d0d54f53361ac9859129d8c9b3a86f086d214ec4416387d3d7156a2fc265d3dbd7456fb6bef5131440268531a616f94b1c0aa0bc7325e93b66125adf"}, @ra, @pad1, @pad1, @padn={0x1, 0x3, [0x0, 0x0, 0x0]}]}], @udp={{0x1, 0x3, 0x8}, {"3f4557c0f30134edad790575627b78b4ba77be4c38e6b41614d6e3f57de539762e8745bde2c8d0cd049b5bc641e3fd6969056c8525f151a2710a153f7fb18fbc193d3bd007fb4cca7c0b2072bd934b5a26986d9f592fdcb9d833c0e3541e155390e82e569964fd202100936140e9eeb0d188a8a8e0d0a3c758931a4a50"}}}}}}})
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
ioctl$FIOASYNC(r0, 0x8004667d, &(0x7f0000002d00)=0x9)
sysctl$kern(&(0x7f0000000040)={0x1, 0x59}, 0x3, 0x0, 0x0, &(0x7f0000000080)="4f1d4c6344b80ed788b6a4515248df3aa745bb992c574ab4cdf5587145812eab4a988f7fafd7a01d99776d988908cd186b51f34f8c15ffa0c685ad4116c783959eff4278384b4000384dbb1c2aaeff10b4135529a1da6fda67c67469d954be811b25ec5521559154c586eefff122009f659cd3e27e98a3241495005f102d9101d158284c0ee3250aa7c11042330de22a299ab00894fdc9bac6042d", 0xfffffc56)
mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x162226d0)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
fcntl$setown(r0, 0x6, 0x0)
shutdown(r0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
sysctl$net_inet_divert(&(0x7f0000000000)={0x4, 0x2, 0xf0}, 0x4, 0x0, 0x0, 0x0, 0x0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0x9, &(0x7f0000000080)="03000000", 0x4)
r2 = dup(r1)
ioctl$BIOCGETIF(r2, 0x4020426b, &(0x7f00000001c0)={""/16, @ifru_broadaddr=@un=@file={0x0, ""/62}})
setsockopt(r2, 0x1000000029, 0xc, 0x0, 0x0)
sysctl$vm(0x0, 0x0, &(0x7f0000000040)="c06d154be3aee5f8787f8b9cda7554335b763bb5deea5ccecb", 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000180)={0x0, 0x0})
r3 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r3, 0x80085761, &(0x7f00000000c0)={0x3})


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f0000000040)=0xfffffffc)
read(r1, &(0x7f00000000c0)=""/240, 0xf0)
writev(r0, &(0x7f00000003c0)=[{0x0}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCIMMEDIATE(r0, 0x80044270, &(0x7f0000000180)=0x2)
r1 = dup(r0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000), 0x10)
r1 = dup(r0)
listen(r1, 0x0)
r2 = socket(0x2, 0x1, 0x0)
connect$unix(r2, &(0x7f0000000000), 0x10)
getsockopt(r2, 0x6, 0x9, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x3ff})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
sysctl$hw(&(0x7f0000000640)={0x6, 0xd}, 0x2, 0x0, 0x0, 0x0, 0x0)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000000)=0x7)
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)
writev(r0, &(0x7f00000019c0)=[{0x0}, {&(0x7f0000000840)="15814414a550ebfc7bd3886ca2be659c132c02be8ad8e8af6c0620530cb7e41151dc758391dd63cdc1242ef9e3f3c124de04036bf73215198dcdb9ca144d1d23de85c937d77f519dede73efd2767412eeae99c9f0448ff2160309fffe3cd6d3141f2441801afa42d5024b6dd7cdfd3c64d88a72637897458af45b25371b9f2fdfbbbd0e9", 0x84}], 0x2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000280), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f00000000c0)=[{0x20}, {0x5c}, {0x406}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x3d}, {0x1d}, {0x8106}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000480), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000140)=[{0x24}, {0x64}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x80, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x11, r0, 0x0)
ftruncate(r0, 0x8000)
writev(0xffffffffffffffff, &(0x7f00000026c0)=[{&(0x7f0000000400)="640493d78db6a9c1e335bb42b30c7b40a07b3baad98026cb156727aa65cfb18540954a46faf6cd689a437aff3f4961c4e46a834f6785f138abeced17229a790e349e6bd31df47a250b6311c17b41de694d02002d9c138fb5554471ad71a4e3b0c4a0f71fc4b1f3db02e683a852170340fa26d02f5dcb6c3772415d9b0c54258aba6ad66cd42dfd5163936af944020e200f6dad158fa90dfdd051d151c8c8cb6d711f408511a8c922ff7be9bf88fc6a18b3261c65ab46b32f89b7793b789d533f5dabd554659bcbb9e4082598016c9ffd443ad64a6c1384bebc4f0fa12ebee357f81c1bfbb7ff9c0bb5289f98184e590366ece692aac2a0f3fe55ae6072624ff0892d666934e9e7bb159ba7471e9ca862d48aa90c56e33b972e7ab5f15383b1e0bdc135ef14c4b638c9514366af346df10d2d11e3e82c7f98a731867165c536966e32790a098e86bc8c85d1d890537ee1a3b37a907cb151aa5b72801d9b213f04f59acc40bab4f2dfde876c2bc53ed02cd106d289a59310e0297a072b926369982acb409872a3a4325ed56f1d297bc8bbfb8f0a43f793ee9487a4492016350aa61cca26b86045d14a8f08e6f6d3e3be5520397612b66ebdf990efcf9ed9796836fa253dfa0389406ae25edb31abf6797596cf9b4a943972a4a19c43db1926c18bf15fc526127d1b04211fb4f4fe4c34dba511e8801a10008e54d343386c0c096641681899e65d2afea539fec10a2db4f07a06c7745c1005d0c2b1f020bd80e052df5a4969a40602d7b4350068968bae7ed03d05c9f0e7dd8940d1e37cfbf3370f5953261615197d350c60c2e3bdc186eff30d0700e608a4e08b2cac91f42275e3e6378a0747267335e017b5342a1662df7f3144a5c0e08008460631d2fb76c410c11c4dcc7f73fcab23a4794775f4284e02ad1ba71d64db4f1f4ced92b7a389fd596763283771b9faf89865c462f59e57a81cf8c3cbeffb268f00b6589ab79483f517583bc3a949c0df139721b6dcb9635dca559ac670c1b3ac3ffae886d18134df6d3b7078928ad5370c9687de2846d1f89f7455cf1f7bec56f3717cbdcab9a5fbe597f929e432ff093d92cb35d625bc8c5dcdc4df998db4b51f74775e5d6d119c505a2d0f27c9ead9e84af18c5d7e258cb6a4b57d28c5be27c3d72e277ae3a79bec39bdc88df392b2df6afcca55f79efb3fe6d0d8b50d7c8bbbc134450db20f1d5a773ce9cdc3b97b3274cb2e9c85496e9043e1eb83bda1b0960808b7dbf61fa0b420596976194a598a6ce1066867d13ed30035f8ff0ba3dcaa15df0cab8b96807cb82435a42067d4f1257de536842db0d3f7dfda891c146d79b600e6a2f994f2755cb278becfdaaefb2c7b976be36689c7a0feced48a723be73f29851f75e42e9d62c83d6aa220891c5c24634e8c7cc3eab033046727127a802dacbde8cf629c1f57d59ba0690af43ce944607c1fd9df72f74d67e7ddc2efd8dc6c459d0d1fe2ca57d14e20046f139050206dd8d203e0389aef6682cc6b861cc364184ee9708452dcb732992ce6dedbb8d57b5c5689b9836c54cdc91b4766f618d608d4bb380614d8cc2e03b3b3b5897ccb61f9fe2d16e5ced34cee9e856a6c52324c0eef64a4b7f9e8e7ed5a71d7b1fe9f94665ac75da67d114047ff5a1c3d0668d43d78c12565ea154f763418049e8dd3a1929b7fa4877c9e2cd984ab94818219a05b196b643adb3f064dbffd2b22ade017488178c5361a1c93f9c615e0e0cd28f25b7ca582d6942071cb7fae17b52eb41ead6e78914945802c19bac16c76ae14c7ed4be6e42713e8a4bd6220aadf458fa15b40777f94e223c596c7f80bab9584fcf4ff14f138adbbf7b1a7bdd686fa9249fe006aea38651e410fd4b1af0d79d7f1ee0cb2711ca81382f15804771da4a18d5f20e10ff9a7abd6ae8583d94f58769f3401526e517d963800c92485f9c24eac2d914895d4d9b866bbb769d22a00db29ce0b9a7d7112defb15d9776db55edf8fca337b1a496c7710acab8135aee0261a780ef6b39664469e33dab2398639d1becbdc74000b36c2ca5df2c0d3c5d3d3e054a2b8d91bc4656cf09300dd084cb0b625a587fba81cc6c2c3ef6f93342b65bc0e68222de6908492ac431f9f4dc1d3915a2cba79820c8c1f7c6e5c582d953b60a943eef44a6e7b244c808fb292f3944a4b1afbbadb06ed72c1d2cf9a60e02b319af032eddb475ae1947175f437262cefe05a89dc92367c8f8223e3a415b080b2bee22f084d00a289e42f5dcd0c31dc257d6bd09d214fad7aaa03d285a4ca618a5cc2bc0167ce424c40b879bfc294b9f2be0ee1c4669fe57d15c3b8fd626507ebb94d7313eda527d86a2bcaf9234a6eb4fcd2ecd218607961c7816094311a762d783ab7cef7009f103d938a5dee845b827001c87920ea3110b97b40a8525c41a57a03e389d9d864c57e10a849509135cdde81b89da8ee10540b76fe6c303a98bfa68a493ff59104b41c34c62092d3c0cc16d5c5c9abf7d0cc9206605ca6b69511091b512063985b03549573fbe60036cdfb28e77670e99b55a8f8151035ac93ef64b77f36951b0d3a31befef14741f874b313b66908f8da53a8a95255c16019876c85dd6070b2a8470f303b98d3c9ce2d203774794ecd2dbc43a69cd37c21f9c971634ff7b00af46adccaaeb1ca346bbdcad44151e38a94d91339c425554791adf2d3ff197221979625d2993ef7f4af06ec2438ab780ce737ac1bdbd873fa3b5cc0af43097b2be36bb9cbf87d39d3a7d54d5a49b176a3d74d95c06cd9b665248f84c27019f7b62232d9de01396aa0096f36c399b762913e207de7e3d24a2bbb04d879fe29b087ea262e82e4b3ca0fca62f222a592ab6ca1b1609e6a7500b8ed38db0d895c2df29604a64540e796787461ed7d1c5c562662b8f5146839cfbae18a6fb302033ad6558ce8a9d61d5de662b995ecb228535cddd02aa051321dadfd06dcd6409cf98d8a8697c7499f1695f173b427ff5f6cfdd224b66b89682d0e2978710e2bbfe7c9f2793cd2592ec7106c44e46c1d2bfe9d7cb53cac640f92f66506aefcc11c983e6c284a892dfc4b813771087baf9150eeb019ba0877afef77a66ee91b2c85ab1b95cc670ae9e80a4f20b8c8914c655828a68d6e8b509d479b5d04980a5bb17fb9ef17060f802f6e6f57e29d6587d6b8dc3438f592db639f718cc3bdaad6865d8a6aa94c47e1061cb8dfb8d7c54c168a29e8b1a78e1716ce413d429daaf09c924a7cde44eafc58fa5b3a5e3aa387a9465f024f7fe6ed9343d81dee65d106f635bbece1c99d5eb8ca0487c00c2851aaf24b2b6003e7150758f5a50943de2ba7b95710fa05f1c1e305dd7a14dba19feb94c9591d8cf724ef55aca7fb8e054763f7c80027b929666f6864db25a059859ca8831f9b7251e38eda5b00d0fc64a3b3460bd7ad733b9eac508a6a191a6465ca14729214d29cdfef5c6409a3f7e5db2044f836c049f5a14a78bea5c7a55e957a53d8d7d97203de65090319911c1788fc704d9382571d3d1bd2b35927d8d95b3f3b14930350ca34d577ff1d4ab69c7ef9f74f73590b8fd0d3574e7779e7f6564f9245c117c4272054015715a0671bcec7416d95a17da00b50e976168b9de75b673f6998119eb1c3b2bd1eebbf21aabc7e606991dc2e802058344d4854b1fe88688873db69c8ac70a9e4850960390a510231dc7159e3e89be0162258982be870d6135b0870986f66c19cf315552165fdccdd2acdff62cddeba67ca0e9578ab629d895a81f63c2262362a49ef4bd8a25dbf73fd100844496f40753d1496bdae8cf60f23db024ec56dbb594e9047ef5b005f579ff829dc1c3cf6844dd8bdcaf644481d171cec2bd25dce58a23617d5d11d7d44465214accb32a5767548fdfe3a428699ec03d02fbc2ccf1237ba07249af6f37ea83ddd8c7ec77f56ae7025c5662ecee8a8682d61823ec04bfebd6195147b016a28112821ad0f2aa32110dd31b38027f0e7fa042cce3e52ec467aaf95f998db202f819f201ee1322215018824a880755b94a2876e09e4c0cac01005ff8885e5f2f21c28b1aab38c62c33de0268521db2c198d19e7fafe69215465f6421b8503218f394d5a94c8601dd6514ff8a80f442ce07a4de65060229285b873667fa19859753c4b949ada2d3ab20afb732a4d4f0a9e5e13ef5a50c8361a465874e956464e201de1f30fa97398d3636ce88e479428b0bd8521010b92a22b4866c311593c101e3ed6169242c63334c7d6715a6dc50063e1c5658f590d0177464461a2ed8892719a770bcd687c597d51d46b89640b6610bc107a6b6d23e46052680aa18673", 0xc01}], 0x1)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x4)
poll(0x0, 0x0, 0x0)
socket(0x18, 0x3, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000040), &(0x7f0000000100)=0xc)
r2 = socket(0x2, 0x4001, 0x0)
dup(r2)
ktrace(&(0x7f0000000280)='./file0\x00', 0x0, 0x0, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000001080)=[{0xc0}, {}, {0xfffe}]})
syz_emit_ethernet(0xe, &(0x7f0000001100)=ANY=[])
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x6, 0x2, 0x0)
listen(0xffffffffffffffff, 0x0)
getsockopt$SO_PEERCRED(r2, 0xffff, 0x1022, &(0x7f0000000140), 0xc)
sysctl$net_inet_tcp(0x0, 0x0, &(0x7f0000000100), 0x0, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000300)="9b0209c3eb987ab7fe4189c99e805e6e84d356960798a692992117d6728436ba1bd87f42e3303eac3846528d050712f838130efce33f523ba44765f5f6915b0227390ed95bd9dc6d4dc7e149d4d6d06a3f23616e773302d9cae75e39a5a11e32e0e6ebd635450b2eba540af7f2aa5dbfbdd900a0dad2b74f50acd76b5c567049ef436dbea0d7562f52950fa5ef6e84c513252ddd8680a944d5c2bd02adc7f1fe850c00000000000000062ab475cca257352828a76e5334be562995e894238b96ca5d4d3e670feac9b4e8aa9bef19525cb6f7e8570b2a374f1400041ed45bb7ad3fe963cb9a8bd949ee0fc6dbceb7d956015947b3e88aa810f8ed7cca10ff010000000000001345daa49507756f49775275ca390b94e85d5a95b8bdacb9429c25483a9275d0da3b561c6adc3c141f26a88016dd6b436218bdbdc9ac0a623855e941dc1872fcb045e0d9df1ecc6357ee21e2b0802cb60eec6add5e94723235f06715e7eecc3e0760c70e1dd7873e27142bbae1a7e44de453a073fe3426f334b80f043ba9136d57c799353d46dd81439b111a511a288bee5dfb2e353e3bb073e3342273216b07e49ca4df0fd2dbe9a8eb377010ee678aad0bd8e9fb7d82693a096344671843a1f2082612b0ff237c6e505ff5f5ba932954d73c630fdb791f833a1da5af0704f687e196f4f7859e071fc98111cc9024f790ce16ceaa7d0104e39789d9100000010000000000050000000000", &(0x7f00000002c0)=0x210, 0x0, 0x0)


mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0, 0x1)
open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000001})
flock(r0, 0x2)
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r1, 0x8, &(0x7f0000000000)={0x0, 0x0, 0x80000000000000, 0x1000300010008, 0xffffffffffffffff})


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = kqueue()
r2 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
kevent(r1, &(0x7f0000000280)=[{{r0}, 0xfffffffffffffffe, 0x10b}], 0x9, 0x0, 0x0, 0x0)
kevent(r1, 0x0, 0x0, 0x0, 0x7ff, 0x0)
dup2(r2, r1)


open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x8, &(0x7f0000000180)={0x0, 0x0, 0x0, 0x100000401})
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r1, 0x8, &(0x7f0000000000)={0x0, 0x0, 0xfffffffffffffffe, 0x1000300010008, 0xffffffffffffffff})
r2 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r2, 0x8, &(0x7f0000000000)={0x0, 0x0, 0xfffffffffdfffffd, 0x1000300010008})


r0 = socket(0x2, 0x2, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
openat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x10242, 0x0)
r1 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
poll(&(0x7f00000000c0)=[{r1, 0x6e}], 0x1, 0x0)
r2 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
writev(r2, &(0x7f00000000c0)=[{&(0x7f0000000040)='#', 0x1}], 0x1)
poll(&(0x7f0000000300)=[{r0}], 0x1, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x206381)
r0 = open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
fcntl$setstatus(r0, 0x4, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000380)={0x3, &(0x7f0000000200)=[{0x87}, {}, {0x6}]})
syz_emit_ethernet(0xa2, &(0x7f0000000600)=ANY=[])


symlink(&(0x7f0000000900)='.\x00', &(0x7f0000000240)='./file0\x00')
readlink(&(0x7f00000001c0)='./file0\x00', 0x0, 0x2)


mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0xfffe, 0x0)
ioctl$KDSETLED(0xffffffffffffffff, 0x20004b42, &(0x7f0000000080)=0x4)
syz_open_pts()
ioctl$TIOCSETAW(r0, 0x802c7415, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x40000000, "d9c71d75463c8d2213137fd1447a6c893e868ffc"})
syz_open_pts()
r1 = msgget$private(0x0, 0x0)
open(0x0, 0x0, 0x0)
sysctl$hw(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ktrace(&(0x7f0000000040)='./file0\x00', 0x4, 0x6000043e, 0xffffffffffffffff)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x1, 0x10, 0xffffffffffffffff, 0x0)
msgsnd(r1, &(0x7f0000000100)=ANY=[@ANYBLOB], 0x8, 0x0)
r2 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
setrlimit(0x3, &(0x7f00000000c0)={0x100000, 0x100000})
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r3 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r3, 0xc0106924, &(0x7f00000001c0))


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
pwritev(r0, &(0x7f0000000980)=[{&(0x7f0000000440)="1a71730a7031cffa7da50a06a95c8eb3fc91ea35e33b6e78191e6e3b0d09f4d8182297a98bb0430a4379f71fd365706869d1e9d78fdb0eb4a8a9189e2299abc0899ffda4eadd739121c3ca0bb30698e26d78e1003c7cde43708bbf43933530618d0479ffa09854aea38cd421652c14267ff30b572f977b2a5ccdc13bc41ab107004dbd5162db89b96faad87a3cf7d00a01eea96ce088a7bed02fb8b868735fd551e6dba44797bd7c0bb1f59e82d40eb2c53ed9b49bbd97a47b658058", 0xbc}, {&(0x7f00000005c0)="f92a9a3ca895d16d5f505b0ce43e35de96a9890be091a8cb4fac8cf1", 0x1c}, {&(0x7f0000000600)="e415f5e06825fd9eb9f614c144bf306d3dc160", 0x13}, {&(0x7f0000000640)="712bcb12e034433f7b0efa19fa90a8d7c7e4af695134dd5ec2373cbdcc58f9e46cca23984451a2efaa878cd7fc7c6c90faac3f14294cd11fdd49503144fc28f7e0b3e2b28a4fd0415e4190ccd47c8598ab3a56e5b6533c4078e50c18ecdb986e2b6b76b5c2ca8b492dd1551453fdd6a783e81985d392c21b5a1e92fd", 0x7c}, {&(0x7f00000006c0)="3b820c64128e7bae02be625807ba8b0900ca66e9f99458486105f9aeb9b2f3334b001ae8b0de0e0f834ee704f1b9dcd3c3a77518779f21ccd012843aabee04e6b5ad1ba0419f2f4ad8b2ee44de3a245d869dcbc68b07bd24a50f", 0x5a}, {&(0x7f0000000740)="dbf4a12d46433b1a5cce94a85c8edd28bef6e1cffef811204ddc17fdd2b8b207afa1a0f2c5fa42a4d487526683fa79f0c8f92ff1f4522b088ebe78b3cb3b518e4f2af235dc41e45001a6e280ea9659a2e9e17e79d877225330c07bfebd6bc251f2ad846cdeb7fda2f0b30541c9b5c48c2915072ae68a20c23b310ea07017f9f8403452d77f87df9d7d74cf47f26d848eedfb8d5dad041f12735a6e07afae2ae1", 0xa0}, {&(0x7f0000000800)="e3e196b586386aeb35988ecbb719281a263d6815e4518c6564a336f3dfa1fdf83f7c0a9ed21cf3c1d8cdfa5697ac0ab5185e639369e9b6b1de53b369", 0x3c}, {&(0x7f0000000840)="3734a13dff1aa6c05896bb56abd23c4b122c445c999059223d425995edc410d3391e2f45584bf9f685a16ae186a68c3ce734b6f3ae144a32969235206ef289809e34a7a18ef49e70c46bb3d4f4ac324add48879668a2f42f9436a4b8d80f9a510410829c1e7bb41aaf10d75e0d5257644f9ec76bed6fda67897a3f3fefde1b4f0d8db369eaf0b586e81c12a281b8315bd3810b98ae1264357236af077724daad917955b19c00f77e7189af6b31f389e90c19bc2ff031d15ad2927f2f2b50e6e7e0fa28d09d6463154a198f3b86265de26e378f20abded3098ac87fe8c00fb34120fbda20", 0xe4}, {&(0x7f0000000940)="21cdc3a63303c75b2796a47ad2f0542659343abed91243724479e083d51955337500deb0a8c8bc33478bbb1dbac3d2ac68dcb2b4", 0x34}], 0x9, 0x8d84)
mknod(&(0x7f0000000180)='\x00', 0x6000, 0x3)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r1 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000200), 0x10011, 0x0)
ioctl$WSKBDIO_GETKEYREPEAT(r1, 0x400c5708, &(0x7f0000000240))
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
setsockopt$sock_timeval(0xffffffffffffff9c, 0xffff, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
msgget$private(0x0, 0x0)
msgrcv(0x0, 0x0, 0x0, 0x0, 0x1400)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000200)={&(0x7f00000001c0)=[{}, {}], 0x2})
shmget$private(0x0, 0x4000, 0x0, &(0x7f0000ff9000/0x4000)=nil)
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x6384)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x6381)
open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
pipe(0x0)
ioctl$WSDISPLAYIO_LSFONT(0xffffffffffffffff, 0xc058574e, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
getegid()
fchown(0xffffffffffffffff, 0x0, 0x0)
setegid(0x0)
open(&(0x7f0000000140)='./bus\x00', 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
r1 = fcntl$dupfd(r0, 0xa, r0)
r2 = socket$unix(0x1, 0x1, 0x0)
ioctl$FIONREAD(r2, 0x80206979, &(0x7f0000000000))
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
poll(&(0x7f0000000180)=[{r1, 0x40}, {}, {r1, 0x1}], 0x3, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)


sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b10005040000000000000000071000001a5113fecea10500fef96ecfc72fd3357a89583535613ab4cb56355df50b7804be38164991f7c8cf7a4f2b297be1aa5b22abeb51e2f0ac3ebbc2feb3fda1139b672f4d3353eb067e7335a079d7080000000000000000008904000000000022830cf4571bed66f4007fccdcf3e4999d9d20002002c5dbfad800000008e371a3", 0x8f, 0x0, 0x0, 0x0)
r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSKBDIO_GETENCODINGS(r0, 0xc0105715, &(0x7f0000000080))


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
mquery(&(0x7f00003e2000/0x1000)=nil, 0x1000, 0x0, 0x0, 0xffffffffffffffff, 0x0)


mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x4, 0x10, 0xffffffffffffffff, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x1)
mprotect(&(0x7f0000ffb000/0x1000)=nil, 0x1000, 0x0)
ioctl$WSDISPLAYIO_GBURNER(0xffffffffffffffff, 0x400c5752, 0x0)
munmap(&(0x7f0000ffc000/0x1000)=nil, 0x1000)
shutdown(0xffffffffffffffff, 0x1)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000080), 0xc)
socketpair$unix(0x1, 0x4912e92f8141e817, 0x0, &(0x7f0000000080))
openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x100, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000001c0)=[{}, {}, {0x6}]})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x8020691f, &(0x7f00000001c0))


open$dir(&(0x7f0000000b80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x200, 0x0)
r0 = open$dir(&(0x7f0000000280)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000300)='./file0\x00', r0, &(0x7f0000000c80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f0000000dc0)='./file0\x00', r0, &(0x7f0000000ec0)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f00000000c0)='./file0\x00', r0, &(0x7f00000001c0)='./file0\x00')
open$dir(&(0x7f0000000040)='./file1\x00', 0x200, 0x0)
mkdirat(r0, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
symlinkat(&(0x7f0000000040)='./file0\x00', r0, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
open(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
rename(&(0x7f0000000980)='./file1\x00', &(0x7f0000000100)='./file0\x00')


syz_emit_ethernet(0x2e, &(0x7f0000000000)={@local, @local, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x1, 0x0, @remote={0xac, 0x14, 0x0}, @rand_addr, {[@generic={0x1, 0x2}]}}, @icmp=@mask_request}}}})


r0 = socket(0x1e, 0x3, 0x0)
sendmsg$unix(r0, &(0x7f00000008c0)={&(0x7f0000000000)=@abs={0x0, 0x0, 0x1}, 0x8, &(0x7f0000000ac0)=[{0x0}, {0x0}, {0x0}, {0x0}, {0x0}, {0x0}, {0x0}, {0x0}, {0x0}], 0x9, 0x0, 0xd8}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000980)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x1c}, {}, {0x16}]})
write(r0, &(0x7f0000000180)="7f23a3c23cce2575e1dd92c25683", 0xe)


ioctl$WSKBDIO_GETDEFAULTBELL(0xffffffffffffffff, 0x40105706, 0x0)
open$dir(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCLOCK(r0, 0x20004276)
seteuid(0xffffffffffffffff)
writev(0xffffffffffffffff, &(0x7f00000003c0), 0x0)
execve(0x0, 0x0, 0x0)
socket(0x0, 0x3, 0x0)
munmap(&(0x7f0000ffc000/0x2000)=nil, 0x2000)
r1 = socket$inet(0x2, 0x2, 0x0)
getsockopt$sock_int(r1, 0xffff, 0x1021, &(0x7f0000000080), &(0x7f00000000c0)=0x4)
getsockname$unix(0xffffffffffffffff, &(0x7f0000000000)=@abs, &(0x7f0000000340)=0x8)
select(0x40, &(0x7f0000000000), 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
socket(0x0, 0x0, 0x0)
sendto$inet(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCGSTATS(r0, 0x4008426f, &(0x7f0000000880))


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x44002802)
r0 = open(&(0x7f0000000280)='./bus\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000003c0)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
bind(r1, &(0x7f0000000080)=@un=@file={0x41a0805bbded0123, './file0\x00'}, 0xa)
read(0xffffffffffffffff, 0x0, 0xfffffffffffffd7f)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000003c0)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
bind(r2, &(0x7f0000000080)=@un=@file={0x41a0805bbded0123, './file0\x00'}, 0xa)
open(&(0x7f0000000440)='./bus\x00', 0x200, 0x52)
open(&(0x7f0000000580)='./file0\x00', 0x2, 0x107)
readv(r0, &(0x7f00000016c0)=[{&(0x7f0000000100)=""/180, 0xb4}], 0x1)
execve(&(0x7f0000000000)='./bus\x00', &(0x7f00000002c0)=[&(0x7f0000000040), &(0x7f0000000080)='/])\xa9\x00', &(0x7f00000001c0)='%\x00', &(0x7f0000000200)='^', &(0x7f0000000240)='\x00'], &(0x7f0000000400)=[&(0x7f0000000300)='%%].{}#)]#\x00', &(0x7f0000000340)='*\x00', &(0x7f0000000380)='%\x00', &(0x7f00000003c0)='\x00'])


r0 = socket(0x2, 0x1, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
r3 = socket(0x2, 0x4001, 0x0)
r4 = dup(r3)
r5 = fcntl$dupfd(r4, 0x2, 0xffffffffffffffff)
close(r5)
socket(0x1, 0x1, 0x0)
shutdown(r2, 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x802, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000000c0)=[{0x7c}, {0xc}, {0x6, 0x0, 0x0, 0xfffffffe}]})
write(r0, &(0x7f00000003c0)="985fa7fbdf69aca69c9a97347864", 0xe)


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0xfffffffa, 0xffffffbf, "0000c6f26461c094f4ffffffff00"})
readv(r1, &(0x7f0000000280)=[{&(0x7f0000000480)=""/131, 0x83}], 0x1)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000380)={0x0, 0x0, 0x9, 0x0, "5a8a99738a6f98790bc09fa6be1b479ba7c0039e"})
writev(r0, &(0x7f00000001c0)=[{&(0x7f00000002c0)='j', 0x1}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f00000002c0)=[{0x6c}, {0x1}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


open(&(0x7f0000000100)='./file0\x00', 0x70e, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40001928, r0)
ktrace(0x0, 0xa5f3b150e570ff1d, 0x11c, r0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000c40)={0x3, &(0x7f0000000c80)=[{0x7c}, {0x2d}, {0x6, 0x0, 0x0, 0xfffffffd}]})
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000080)="35b5c242413c1026089a59583cc3", 0xe}], 0x1)


r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
r1 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x401, 0x0)
poll(&(0x7f0000000040)=[{0xffffffffffffffff, 0x20}, {r1}], 0x2, 0x0)
ioctl$FIONBIO(r0, 0xc0107008, &(0x7f0000000040))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x1, &(0x7f00000001c0)=[{0xfffc}]})


socketpair(0x1, 0x1, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
write(r0, &(0x7f0000000540)="38c344d08db0e1397e1e89142d973b05d32281bd5fc0241fb7ea5d170607009807c187cebf74ee05cbc21f02ad0f538811ff86fddaf008240000000000000002000000261fcfdd6affc9e2add51ff3806f72ee3227f03b5acae5b56dd0ca261c4e04a084bbf3ed148bc1d3776326dd5ecf57ada312d66ae805d7", 0x7a)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000440)={&(0x7f00000000c0)=@abs={0x0, 0x0, 0x0}, 0x8, &(0x7f0000000140)=[{&(0x7f0000000100)="910268a55dd952c179", 0x9}], 0x1}, 0x0)
recvmmsg(r1, &(0x7f00000003c0)={0x0}, 0x10, 0x802, 0x0)


r0 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r0, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
getsockopt(r0, 0x0, 0x6d, 0x0, 0x0)


r0 = open$dir(&(0x7f00000000c0)='.\x00', 0x0, 0x0)
mkdirat(r0, &(0x7f0000000100)='./file0\x00', 0x0)
mknodat(r0, &(0x7f0000000580)='./file0/file1\x00', 0x6000, 0x0)
mkdirat(0xffffffffffffff9c, &(0x7f00000005c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
rename(&(0x7f00000007c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000400)='./file0\x00')


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x7, 0x0, 0x0, 0x1}, 0xc)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000080)={0x7}, 0xc)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000140)=[{0x2}, {}, {0x6}]})
syz_emit_ethernet(0x127, &(0x7f0000000040)=ANY=[])


setrlimit(0x8, &(0x7f0000000400)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x37c, 0x7f, 0xffffffff, 0x1000009, "00df00003f00000000000000000000006d2b00"})
writev(r0, &(0x7f0000000500)=[{0x0}, {&(0x7f00000009c0)="0a8c03b22d14d53f540a8d8f1045590bc21fbed2165542014afa6a39f722319cd481406df7660c56c056e7f1c61aaa286b2fd5595ad06f3c2c2af2ad07e1579d5ff0e5edff5960b9079e80d6bb9a1b830080a78b4b7a73b9c99c1f01000080000000003e3fa2db6a81c71770abb3ca30bb8e91e502f891b073cace886ff1883458e1b409b12d6ba022c39c8f2065c15c09ddbdffbd1830651d0f2d0f4673647d30", 0xa1}, {&(0x7f0000001700)="274882de9dbfa898728a4c6c8eaeae5dfe8f554f430d38088c37f3677a433dbf13fc099aed8c642c03e5d80552ddfe5835a3cf9bcf66a9720f252aef18f954c6f0372de3d257e0b5c685e81d011c6fe99ca1dc6c9a91195dfee85a45dbf36c643809e2c292a76619d8ddd93c9fba33d333e540c46db39527c25deab308fc36fa10a7ed056def7a219a04ef35c35009db50751c0aaf77bc57481d5c918e1943caabe688e480409e4135e6e757e0590704fcbe1cd7be7ee039d78e2a7c782655c2ec7d1fc898b74ff6bcb2c6b9ada667e79f422bb4dd66f441d235f1a87e9c36b5f0f4463642813cfc779569fb293083f997ffbfeb6de18f91e95f35fb971d9306b04205dcb3720c3a4f1dfd37831987bd909aa261c50de43d08f2f880f9db702b1b10621f5fe061918929e31d73a2522230d55aee33e2fd13099851fe99c288c38cb3cacf0e63d9766baf047c2710543765872fd85c4af5fa5df2b7656202b20ebfd5bc69a2f7b2411387f72f4d47f8b537a0ad9f8f37f36d6ee1f41e8f1b92abb8bf598e038d67a4bf0c2ef43f0bae630ee6e64110fa7e8a662a431a9f25707c4b9ed9227a7e3adc161a34b2d38f633d34e5ddaa161d151f81a3dd4e6336195e28ea843702b02ce71b2f2c896d5d13541c4d362666188d0a91d835c63a5431b36113fbf551fc51467b8ef76d5ce2da7657cb5fc7fd59f1e8af41c6258aba1585f129af32b53c6afe8371938ddd4c2745341ce3279f4f022da011790715401945d6c0ffc070f31c2ab16d7028ed6e637ccec29754b9d61e07e4925be1504f0f6edf1d4f168e2f028bb54093369b16f926a76458e0b068a9d8ea4051367845c17b80e766cd9705e26885a95f45141160b09e1425ff76dbff3f7906ee71738a060cb1403a9b2bf463f65247e646fc8d74c74e875a29f4adff77cae9fb46ee94d29e9b3cc9b899f0af440f4e4744370f0f0d1e270b74b493db38c470600fa63ff49c4717a76f527c36eefd5bdf7d09970a4d4368aff2ea97d8ee4405e33585a35824fb0a53a415e039280e810ef917442f82287e1eab6c0d549963d72085869fad865cdfb0e0089c9b27ce9799a67e92bf12430e006eb19576418daded0bb3320e14c254e57bdeee46bedf66ca27ae7d28b8870275dc266535ef5fa216eec42424537114f8d9d6f6d3959d4d8e8411d449a76d9e09bdf71ec0ebeaea3c2a532e1daa69ac400c52bda3f9f6e877d54f0002511523482cda7b43eb5b7d2a5820843d7bc0003485dfd76d89695c236114c6ac37e10c2e6d7d29076d8fa44680088450017a1956688dce236b26cf66235643cb3726ca1426038feb0d36c6b4a947e91dcee3da90ae6b67d4eebfbca0ae569ef52b3cf5b637a645eaa5cff17a6e989b42c20c9df6b380523c98fb72fa22403407660ae24b639e936aa052529bad1e87c07b2101a09829a6ea6bb3978af315eadde16b398ac6fd1dbc1dcbace5fddd98f0e7fdc845031edd7d9171ba375b69c7872a62f97a4b946cf9d796152d047bdf308acb83f7c6d977abb07d571072d09f9a7c1ed0dcf633c8df83d76472183f275a3ad01cd0bef9611c435d7e781a777b7452c74cd4df5b55ea430a70ef8d166945d91215e3b91ff7a6f558cba617c783010b3e5754ee5bfddf511bc43d74b124358c553122bd9c80b4bdae22dae19702abf765d3fa07d136a60eab7805df6817be4c1f8c98ab2be6f770b6960cc8baa899bbe309da07896aa64ef5ad2d13385caba76c7790e22b0a3c3decb53776fc0d63914a66c6eb6180c90682f6b9e9b713d2a3a2d39be5534ed77aee9997d2bc2d95dfa22c76542b05deaedb14a63133098625f913a8dc43330cb978aa29ef95e7e6344fadbb309af7ccc29754efbdffc1eb8234b59d902cce940858a50f4449ab625908ea2e64d42e100f889ddc96127e25f75bcfb0e493cef0ad1a710af1aafe399d48d18a81546fa3a9f14a8a2b4c868f36a6acc8b3cea213caa9d4979d0a3e22cddb87f1091e55e705976fb96b3cebd7722037312be42f937d9fa9494f48facba22a5eee1adb5d6c9fa7ea4d2e10b4ad14a4a6df4dc474309df6234d55df6b69d46f68b873276fd153eee0ef2c4df8235abb178eb9dff7f410aa190e42dae5948cb39be50d0b3378cce2323640fb4c0eddaba0cf53b984ebefd5e81a0f2c834bf96db7fa9e753e5b0e40a242dfbcdafc78ba33dae1bb00f39d6a7cc2fdcf2935c31aaf4b4f222dd9dbaaf219c18ad7aaf2d146613b82d790c735927730f10628f66580183c24966ee65bf4522ecc0926835ba882570abe99c4a61391f280ef609131e695ad024febbb59006ee78a9be537668ed4a95ed201146428a5f3f2d4b1f12f21f85c1fc77aaadfd6d9137d3bc8ee51d24dcb81ca06655ca7e18a0ad767f643fc2e64f3c3b26be112c18876a2349bbffa1de87bf8a1c91d2004c5aa8407746178863ba2aeb83a0de6b063be25447cea5321d86acd642a1e94f8b6b04f0362b21005eab7be480fd4e88dc0660f71e9bdd559828ec0f026efbd14cd43a64473b1a5a8a18a5f939667dac78327ebcf6a85066325846caf12a54c6bfd885595df82943a644c624ee94b9890fb5a7bd0a23bab9277595f6bc591e26915ceed69f4599731c2bb4bdd12beee7b2e43c4aacaca01666c8afc115d80f2c70f5b61e9c9afd1fdae5ce96c75d94d44c5fb071559a5dac3d8e10e08636683ef03ce70cf35e521be6fa12a94986853e6a4b5de57e5a7cdb2252bb4d0d24fef1b22bfe094d0d87f3721f992d98e02393ef30830cec3c5f3e1c132e471ccdceb036c86b0407d6c4a7c72581ea29213a84b514b3abaad21292c54ddb678610fa484bba2e0f22003dc5d402d51d3fc99d8ff34a288c12499e33bea194a3ce7b81d37d5ba31b29c47acef34dffa5f98103deb2481f0bae91991f26c16bafd8ab9b530a6ee91c03fd33d798a9556bf9ef39479b8f5abb051f7104d195b4073f90259da6ae0ee07833d20b89eaad12b4df8c8236462ddcb149529eaea47a63bb3fad8fea8b18fbd1881c49fdbabe50b5100c3d283ea58daa3fc89b2b8ae5087d7f19b4a13ee31ca3009f029e606bbeab35680447adb7963a07b465d404631f2c92adf83d7abddd5bc66bf09d6bc999b2bc7a21de72ce563ef795ad741df935680a1942bbee368c2ffaa5ba1e3101d9fcbcd4ad38e076ce7a60b40f4db44593306bbb99b3e25fc2ceacf1a864b1c57615838e9b802f66acf43f251a7de0a33b630a47b620a0b0a7e0521c7472fadccb51dfa7aa6ad77efcc719664946b2d81c37db8150296a888651c61a0cc941bcef50a706a18eecc330daa93f416e458fa81de33ec4b2a07f90e6262fcfb05d8a34f47e18f19407a52d7c55997a3465e9af81b0a0c95660ba6507cb93dca754ada3ca38ec25b269381fa421ee4ea24485af8b09e6bc05ad980385d3837eefe1bfd39d26f8197a48fbed305db9c67834571817c96bf961367446dbc38ac08188c2344b0b8a60dc79c56a89fbdcd2c93d2cdf61b1d8fb2794916af13c07608342b4c0830cde55a27c6f9c267d96d3483f21881064ebd4ea2ffd7a1ccc8c9b09606d9f29b59a15e511d7ce2d3b8813fb200ec2ab048540b77e28b3ba7c32a73a170e4c2b96ae26e6b3bdacd44f902887a131f999109fee72d5eb76c39bb13d6ec8acf13d62503674dd0633687468ef4aa4b943004aff525bbcfbf531187f03543362cf61bb63320eeb2c91ea7459de7154f148b08651964d4712cee1e7248cb8340be320958f6301757c5906a0dacaae02f4764f658be694ab754c1cd80976f807b08f8eb451724b60689d22f6e8551493f8ef63b2c49ec789396421126943a125471be7944b924f8f0325903e523974fbfc7d73e89b74ebf56596e2a635da9d779dd1ef7def0129dd124b9ab9d732fb785b223facc18f94959902acb5803533a3edcccd7869337291b62771d13250af6c7f8a31c7adc790a2ff2394993c157fb4b9c17f253653b385d467bb4029a6c5334c765644e95a152d4fdda779f9ae59998b3eb66dcdc8cef99455e777ab0ee1b46bdd5cf90c1428c49fc4e06a2cdd91102acec69ed67f81c259e0346622ecf4077ec5c9b96193d2cf831ce3f6f8dcd95e1053286830cc7dbc33e9d858307b3f904043beb1e5a8cd9a0bce2f10ada41c6af2452d56071ad357ec5fe54c2967cc87afce62cd791422bb014eb342c698a29ed8ed6d8cb468a67ca6a5c9ba8cadb99ac4d8cc986d9202f9f41af1240b098e12afb6b6500e4dde240509c8c0e4e81f132728ebc629f4aec1d0981f1e28b724ab4bf85937c63bd88082c960567c08699abbf5962971ca79e6e891eafca1b3e961a0ba85bc388a31560d791f616bf552ac942b7358106df854f0c59", 0xc2f}], 0x3)
writev(r1, &(0x7f00000012c0)=[{&(0x7f0000000140)="cfbb251e606bea41ad417032985e05b5725bb9a5a4201587136fda2dd727e5f62dde5a3a4482bc0b9d8726d0da46c1d908ab108ea9ec76e02493a12c1b64b1ae00f41186a7b024d2ddf2ae9d3a377c239387d08393adaed08cb6", 0x5a}, {&(0x7f0000002ac0)="60bbad4238f79f3fab424ca4a0c38f34f352c7d5c7b6743ba59aca5b10b7f12be1cfa323ff58d0f57283e760788123b4a989048b3e3733dc8e3463a3713b8e03e9be10b3f7c76b830225cc80a4a30e8bf4756fae56321aa3894ab69fc4e85a1a97cbe34dd09282ac10309c3e29b703b897fcdd82d8fc7688ba2cd139ef3f333ac048fac12ed769c375952c24e6676579a90c4f13d6d4531fac3cc94239d932935ae6f55541b41f24406ca41656dd8e889a023526bff0265e626b535cb4123c4e2bd9e951b2b4d175be8134e3b76491bf204272a534386e4d2ec00bc5b7ecc8375079c2ea5526d6154677d5e2de08d01460cc71b57ac1ab20f6debbb381f3d5952ffa3c413b9c44011fe3eca5714c9e995577c26fa6f4be9cef41e86953f7a67ba4033192ec930ee4a875fd8a2d9e7945f75868255b00c1d5487217f32d2db516fd24a770974859d3e0af7c1368405afacce6876add8c4dda7d84bb1c19850919c6c474260ca663513190f2b732650031fe7abf0498f7fe749be7e9e6ac101382aa72a6a5d13564dcec299fabf7ff328c3d4d7d6bd36dc6249e363c908d6f9b04f61d174a046dd542d71c2ef30a39fbb19573b4f2e16c51520aa99f770b838d7cac545aceed9295c8cacc2be13c08f5ea75691d965e82a6a9cbe553e86d25489b4fc730f2a7712b64df3762913d0afb06179df17b755883b27600d2c8943dd88c3a7e2cdd9fbc6eec90287719b93766304ed49f5d57c3afb3dc4cba148b67797cf390bc442bb29245c2bf1b2f2a2dff528c32ad1e09cdb8a285d491613bdb9f6e567e00184a2ddeb383e6ac4f6f51c13de680b8551e67d41005c645180a9522bab67a29c0617dcbf91dca295be0a8b9fd6c8e9a3bdc81e109ecfbeb026e2391e101a29dbf5d69ec70f783476268cfc5bd0baefee4dc0512f3114fcd10e685021b4a4e0075323ff1c94a6bb7e0339bfa8f7a66cc6d7c1e115f8d8ebbf2db6553927d78c1848463196183a7e8c92e0e3c257889d633cb631b4ff59c051a216f43b532702b4b6ec7451b3ef70a3a50d29ff2a79fdb06c6fb91d8a0a8799b6b6f9d56ed0cf3322f957dc31e1a1729a622c6738e6fa4eccdc51ad158e4852c2bf585910a3726521128386e35103072791d279abe6535f07d9affc005cd85d21bf36450cc4e1d0245e0e2ff195ab6706a0cf0003ac8337adaf54ed5923f9a2e4245e6f03823c1f3f26269f3f3f26cb664a92e773178e9d0b51f1aba3a05337c5387245d009e2187cfeb658a7fe98619a1e769883a6ac7f9c01e3e35e20f7675901ee6c2e2b31f952d35d8f2a38d6236514080ce02d2b8de01801a6e4d0588d0663db5c154ee8cd913e07043ef8045ee57dc97520c3d7c597c82d7b4486c8d94d94191e7971e2ea868304007799447fd1953fb8103afdbffb934ece4527b8797a9ebd69510bee9df749c3e68f5ce9b84d5662032c9a1fed49f81e7886cbe9122ac339f72c7e93e927f628ee59d83c6c13420e0fbfb27ce84d4b8d2035488f99d97c1b87661ef58dd62a9fedef7685ec2dc16f97ceebeca935bc8925900ec234bad42982a7e67a5d33648e1defd0a585365a97535c5d78018b7a2164540ae07f81dde252208eebd15834764dc7a56345da952d9b090aebd2a54888deb5e104bc2f54155c0063a8211269ed2c21b8f5ee6c6515bcc429a093dfd0146deb9e8a56dcc73fb36492c92195ccd793738776168791f3a224fee2a695af5e95d3fdb82b312e9bd98f4aafdd9c268f3cf3790cff6649efe9d9595030aad7b24515746a52e821c6f45cf03240e3eaafd364f095bbb33a47b50fbdc2c66fe86fbcbf7b1c077e929f8e92951697de55ef19623d5ffcb9eab8b268338b8e26a2f5587c031e95917fc9e1c0af59ab18381a39ee73077d6126b26733c4b1ad311fb5ec3496f36b460153df51fd8f3829e877104ca327a6ce688e1f1f928d98bb1731715ca6d74b5279923547399511939c382368449eb3a806ceb299241f0104b56702080154578e3883edf3baf82076aaa002950500ea3a6ffadb1020b3787a7451580b5cee54190883ab55c0674746401b6bea12bad4293f0048efba066f539d1269e0a16fbeb2daf33fd47387688b43d6bf4b4f09d7c3bc07175f954c07f6946c5f4249b7b71f802bca3bdf8019dd6deae065f154a61e151b42b3040866dc7deba7df66f03ea721787e2268e58194b3cd8d9c1f9e965cf3e87b53f466fcaea4b3c9f1853807b05db27e4a206106c2bd7bde96102c3d0f0362b46853a36a12b18c9a0b83b2bf8dac247252c7138fe258c82f66d3446cbc41fff1d6abb165c776d23f6d93053ad368787b6907b1061f86f053ac2fe0ce77d10d8b5d3d52736b6bd89446aa529e636a83b70fe4a13f364d44f0db842cebbdad2e01b41e4ae61ffd309c30666498b9164c9410dca9d90879369602ef8670fc0f82e0deba5e753726e5909234aa1e2086b711d459db6ab35e7d81ebce83c1df31b6c48808f9d52020a72c99e07ca4e0de97e9bca82e2abde799287e966f03b783285cdca5ccac3b9653d94ccb17017a37b5af22832876427b0842849696a39349faaa03ef3078f51c39e4153e1330bb5be69f1103530cc09c5cef0b201111970b0d901a70af9dfa4bca6b34dff016066863936f3005f87f971bdf723d4aa71c8dee65564d66f6e4e2fe83e2a11b097c6a14b651bf1b7e253282e9adf0229f158c1ad0bef485e7a904df7c56cab5724e31b2de2ab6d87abb85a5b7174e27c3c515c1b77bc181d25eec397987deef62ed117c800f434664ce870d7d3f580d330147355c369e6564f049ea833cda2ae8fa9e34ca1a63dbf2117f5a5dd530e85224ff495035e35ae0201a608593401611fa631faa7f8029707fc0333c219acab704dbb9b80a7010989f1f3fa4856cea880c4b3e8e2d43fd12fc46f23dfc079f30407a80956938e27c0354d4f8e3e455497e9679cf2d8b57bbccdbdb75331f15e6fcc26346346d0b59913cfbaf38b2d73091b2c5497f9a8a8d0be52c205c89860e2b11bb16976796d2766b3efb36626bf1d894fc00ce4bcefbbab2608aa37137680d64e568bab8abba22d8fc846ed607e2fcd80a64f11ffb589514e3758c72f7c485a0e62b21de20fb2c481fa14aca0db56fe998247e9f41643b171b904cdc4babb4dd03533bc0b90deba0b66b103492d0ab79b2ae63e79484ebf0ad96b32da892ba082991f77ce7475dea0390f837df5bbca8a64934d722912d651b3c09b02bd3cf2874d3c8ca66496db05c6392963383cd417fca84a4492901d5a532941bede6878f2c0d387bc93439e1e79472a625bfc6f78c54ef44a395da80e6c0b777a6348b356af1c8176087ec63f87555afb3f6b594ac2fee5287b9313a556a3597c69ec3ba1fa1ef3c46c6135fbe78fb739af045d0c0ed99cfede95d7eadb381cd160f3bc34efff00ec4c417e49675c8b6b1f2c3e3f3f66c0db57c468fc7f7a48ff7aeedfa6814e5a0bdf5946f7018558c990e3ce934456b27c6a082481791de85712a334e5efe61e5863647299afe3157d5b815c9935512473ede307e8a546b32c3a85cc65a71a2f9cf4d89cb6d0451789ff6d47cd64448dff7a2cd03a11adf2ffb94618e50221ab6a9718d56dea31af92318f53bb874171f3f34c07b2d9bcbafd944cb02ada658ea094972fc68e21cbef4d884cc594671146ddaa3843fccd56af84aaf0047b2484a24c3b04b067a00dd89a097aaefea71f187e0581fa01a102056b8d26f4cb6900eeb26c860eeead7201fd2d9f2383ce5ec4f330d059dba708ab3eb6ad6662a168c3be14e226791a7d7168495b5826c8b57ba819ff359c984de9daec5273a2853675756a9422ef0ba8bc08961b333d7bf702db9dab08fdca1db9ab42fe80fdbbd020a4d0bb1335df43a8749bf3f5f1d3a30e130e8b7b43e7f78cfe32d0b324e1dbdf151b73cf2f93a7315b080573b4b819e4264526d30f987493d1597ca97f82279cb23eaeca4ebe4ece55b8e09a2deb15c2ae49898f71b7f5694e7e6089ee434c01d1ad586e63dc05e7074be8db1019dfd6ef54a10831c0fc551bed0ae5e40b3585bcbc4b71537f4a4b6b4f355598c897adb5228db77002a2cb148d90c7ea8a4e83af590b48342a053a4240a4239c16ae937fcfc7da372f6b506a761f60f70a8af108914e4aa0050a64a7ae2f73b557eba12166224f32f095e0b91b9f0a75a83ebdf96e59878af7948c553437147187aeb2088910ebc5498711a9443715523140636311999297b504cdbe084e0c5a99b9aeb57bbb974c51b0a49c30cfe2f5f2bfef509258f2d7cf5217b83c710f1ae4bd33a47d17f349779221203baf87c10fc3f93e6c3d2859676104769fedc10032fe91a5d6c027e7371560728a9dcf814b44792721e23973873550ebab1795da12b73ae5d895feb51709406dd3b18ff53fb5d3af8b0b714e484afbc262ba6f2a720ab0b18cf75d1f457e04928334377644332fc58a8f77e91f95d45b684818095b7e41cfb60be405ee289986f36b7e892bb7422aae9656fb031eb9d9b63bb4c70851689c40d54a17f7b48f0f97b3ab9739f937dd251689ef40c92fea33c99db294c1bcc27b695a288cfdff197c28027e7276611f8f97fe98384a843e4968bae4b1f63393346a753aa06042836b6eb1adc25d78c298a234b1cac319edf789f6abaa6d67094fc7f48b24b92d030baf14955159339d38a006fef1349bb73b6fec03b9119f97ea753bf376210c467520eb7cd052a36161eaf5062be089fc657f8fa2245a5887b29c26216a143382bb5e3b77b6f2cc5559a8c4915c496548734666470f24dc19d65f1a0ac2dc1b553f0c3af1510fbcee5f57461b6d14d3bd721e62238c06e2784f1a012fde89e352bbf2365b565d50ee27246fc00bd62fe46ece7b976802a697ccb7c717f85839a6e39b20bffd8e0e25e7b128c962421fde44ed4b742fe7af596add878c920cdebc7afbb42800177016cdc39d852dc64040be9fc5182c05f530e669ce2d0489b5fb5ea95fc56fa3fec5e27e0b7a450507f0b3de240899647fdfe5e7d52546aa7c358d02fe9fea6767d662d651ec1fb10e613b1f219c440362bcad23654f8602dddfef51c21e431c75b0317d0df0f843df1495817a85367e081e1df83647b7d07dbacc4874816214aaeae0a574f57381cc70f4cb782034e9974a6c4cf23c247e69a0f7fa08750b08634957ffb8", 0xe76}], 0x2)
setreuid(0xee00, 0x0)
mknod(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
seteuid(0x0)
writev(r0, &(0x7f0000000800)=[{&(0x7f0000000600)="ec6e6688290eef4d1e3caf403d1c8ec76572ea971ab9100008000000000000e9ca199903fdc9ca6118d232a369e4e3741dc001fe64edfe80fc7c67b715015e97d64167b4cc024469e8ecacfe668e499fbe1a617b4fdd72d4b72f2d2dbe26f7bab1158d052a9d215a57d3f2ba438cfaf0b979ffffff7f97a05b0000000000a41dea0dac1cfc8351b5fc7f6a30b0198d8c3c9b993e5261fd9af52ff55b1467b1a3da339b46dace9eac800d", 0xaa}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f00000000c0)=[{0x4c}, {0x3c}, {0x8006}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f0000000040)={0x10, 0x0, [{&(0x7f0000fec000/0x14000)=nil, &(0x7f0000feb000/0x3000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000fd4000/0x13000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ff6000/0x3000)=nil}, {&(0x7f0000ff0000/0x4000)=nil, &(0x7f0000fef000/0x3000)=nil}, {&(0x7f0000fec000/0x2000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000d56000/0x4000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000cdc000/0x4000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000feb000/0x1000)=nil, &(0x7f0000ff1000/0x2000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000fef000/0x4000)=nil}, {&(0x7f0000fed000/0x2000)=nil, &(0x7f0000d2c000/0x4000)=nil}, {&(0x7f0000ff0000/0x1000)=nil, &(0x7f0000ff1000/0x4000)=nil}, {&(0x7f0000ff4000/0x3000)=nil, &(0x7f0000fef000/0x1000)=nil, 0xfffffffffffffffe}, {&(0x7f0000ff6000/0x7000)=nil, &(0x7f0000c00000/0x400000)=nil}, {&(0x7f0000ce2000/0x1000)=nil, &(0x7f0000cb8000/0x1000)=nil}, {&(0x7f0000e85000/0x4000)=nil, &(0x7f0000fe0000/0x1000)=nil, 0x3ff}, {&(0x7f0000c4d000/0x1000)=nil, &(0x7f0000d14000/0x4000)=nil, 0xfffffffffffffffd}], './file0\x00'})
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f0000000140)={&(0x7f00000000c0)='./file0\x00', 0xcb, 0x0})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000200)=[{0xb1}, {0x3c}, {0x812e}]})
syz_emit_ethernet(0x2a, &(0x7f0000000240)=ANY=[])


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000180)=0xc)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x2, 0x0)
r2 = dup2(r1, r1)
sendmsg$unix(r2, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


mknodat(0xffffffffffffff9c, &(0x7f00000000c0)='./file0\x00', 0x2000, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x4, &(0x7f00000003c0)=[{0x2}, {}, {}, {0x1, 0x2, 0x1, 0x3f8000}]})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000007, 0x0, 0x0, 0x0, 0x0)
r0 = socket$inet(0x2, 0x2, 0x0)
getsockopt(r0, 0x0, 0x9, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
kqueue()
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
fchownat(r1, &(0x7f0000000040)='./file0\x00', 0x0, 0x0, 0x0)
r2 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r2, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
mprotect(&(0x7f00003e0000/0x2000)=nil, 0x2000, 0x0)
r3 = getpid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0xffffffffffffffff}, 0x0, 0x0, 0x0, r3, 0xfffffffffffffffe})
shmat(0x0, &(0x7f0000ff5000/0x4000)=nil, 0x0)
shmctl$IPC_RMID(0x0, 0x0)
r4 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
ioctl$SPKRTUNE(r4, 0x20005302, 0x0)
shmat(0x0, &(0x7f0000ffc000/0x3000)=nil, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r5 = socket(0x1, 0x2, 0x87)
ioctl$FIONREAD(r5, 0xc0106924, &(0x7f00000001c0))
clock_getres(0xbe44501372635004, 0x0)


mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f00000000c0)={&(0x7f0000000000)='./file0\x00', 0x4, 0x0})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
bind$unix(r1, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
bind$unix(r1, &(0x7f0000000200)=@file={0x0, './file0\x00'}, 0xa)


r0 = socket(0x800000018, 0x3, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0xc0}, {0x3d}, {0x16}]})
write(r1, &(0x7f0000000540)="76e5dead6f01f8607d2100000063", 0xe)
setsockopt$sock_int(r0, 0xffff, 0x1000, &(0x7f0000000000)=0x4000007, 0x4)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x120}})
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
syz_emit_ethernet(0x12a, &(0x7f0000000240)=ANY=[@ANYBLOB="b96d9900533a8f943f3614ef86dd6000000000f400008000000000"])
readv(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000002140)=""/4112, 0x1000}, {&(0x7f0000001140)=""/4092, 0x1000}], 0x1000000000000037)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000380)={<r3=>0xffffffffffffffff})
ioctl$FIONREAD(r3, 0x8020690c, &(0x7f00000001c0))
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f00000000c0)=[{0x48}, {0x3c}, {0x8006}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])
connect$unix(r0, &(0x7f0000000100)=@file={0x0, './file0\x00'}, 0xa)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000380)={<r4=>0xffffffffffffffff})
ioctl$FIONREAD(r4, 0x8020690c, &(0x7f00000001c0))
sysctl$kern(&(0x7f0000000000)={0x1, 0x1}, 0x2, 0x0, 0x0, &(0x7f0000000240)="76b0353a558bf248c78c8502fcfdfd08fa1588f2540000000000000008c0ce3671c0907259201eb7cb962ee12d9706a2d4177565da48e3cdade50516597f477c8bea18253c1441678346ddaa98e46b28e2226a296c0fd773959eaad9d65d33cdbf523a06ed457ed3e00f52851f90c14f54ec03a2a5ff8d88b90ab26a8d7dfc18fda08fecf7c006586e74a36a513299a312a5b6a9", 0x94)


mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$TIOCFLUSH(r0, 0x80047476, &(0x7f0000000000))
r1 = openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r1, 0xc2585601, &(0x7f00000004c0)={0x10, 0x0, [{&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff8000/0x4000)=nil, 0x1000}, {&(0x7f0000ff8000/0x4000)=nil, &(0x7f0000ff2000/0x3000)=nil, 0x80000000}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ff2000/0x4000)=nil, 0x3}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000fed000/0x4000)=nil}, {&(0x7f0000fee000/0x2000)=nil, &(0x7f0000ff6000/0x3000)=nil}, {&(0x7f0000fec000/0x3000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ff9000/0x3000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000fee000/0x2000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {&(0x7f0000ff2000/0x4000)=nil, &(0x7f0000ffa000/0x4000)=nil}, {&(0x7f0000ff0000/0x2000)=nil, &(0x7f0000fec000/0x1000)=nil}, {&(0x7f0000ff2000/0x2000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f0000fef000/0x2000)=nil, &(0x7f0000ffc000/0x1000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000fed000/0x1000)=nil}, {&(0x7f0000ff5000/0x2000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ff7000/0x4000)=nil}], './file0\x00'})
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x15c0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000158000/0x3000)=nil}, {&(0x7f000003d000/0x1000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f00000c3000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000157000/0x1000)=nil}, {&(0x7f00002f0000/0x4000)=nil, &(0x7f00001eb000/0x2000)=nil, 0x3}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f00000e0000/0x1000)=nil, &(0x7f00000d8000/0x3000)=nil}, {&(0x7f00000ca000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f00000f8000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
open(0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
r2 = socket$unix(0x1, 0x2, 0x0)
getsockopt$sock_int(r2, 0xffff, 0x2, &(0x7f0000000200), &(0x7f0000000000)=0x1)
syz_emit_ethernet(0x52, &(0x7f0000000080)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaabb86dd60000000001c000080000000000000000000000000000000ff020000000000000000000000000001"])


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000400)={0x3, &(0x7f0000000040)=[{0x15}, {0x4}, {0x8106}]})
syz_emit_ethernet(0x2a, &(0x7f0000000300)=ANY=[])


r0 = socket(0x11, 0x3, 0x0)
kqueue()
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000300)=[{{}, 0xfffffffffffffff9, 0x41}], 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
kevent(0xffffffffffffffff, 0x0, 0xe4a, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={<r2=>0xffffffffffffffff})
kevent(0xffffffffffffffff, &(0x7f0000000140), 0xe4a, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000200)=[{{r2}, 0xfffffffffffffffe, 0x17}], 0x0, 0x0)
r3 = kqueue()
kevent(0xffffffffffffffff, &(0x7f0000000140), 0xe4a, 0x0, 0x0, 0x0)
kevent(r3, 0x0, 0x0, &(0x7f0000000280), 0x9, 0x0)
kqueue()
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000ec0))
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000540)=[{{r1}, 0xfffffffffffffffe, 0x7}], 0x0, 0x0)
r4 = socket(0x11, 0x3, 0x4)
setsockopt(r4, 0x11, 0x4, &(0x7f0000000340)="12000000", 0x4)
sendto$unix(r0, &(0x7f0000000000)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)
r5 = socket$inet(0x2, 0x3, 0x102)
sendmsg(r5, &(0x7f00000007c0)={&(0x7f0000000000)=@un=@file={0x0, './file0\x00'}, 0xa, 0x0, 0x0, &(0x7f00000004c0)=[{0x10}], 0x10}, 0x0)
rename(&(0x7f0000000040)='./file0\x00', &(0x7f0000000080)='./file0/file0\x00')
socket(0x800000018, 0x3, 0x0)
getpid()


r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x1, &(0x7f0000000140)=[{0x40}]})
r1 = socket(0x18, 0x2, 0x0)
close(r1)
r2 = socket(0x800000018, 0x2, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
writev(r1, &(0x7f00000004c0)=[{0x0}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000680)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f00000000c0)=[{0x64}, {0x7}, {0x26}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


shmctl$IPC_SET(0x0, 0x1, 0xfffffffffffffffe)
setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0xee00, r0)
r1 = socket(0x2, 0x2, 0x0)
r2 = dup(r1)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x802069c1, &(0x7f00000001c0))
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000380), 0xc)
semctl$SETALL(0x0, 0x0, 0x9, &(0x7f00000007c0)=[0x8, 0x20, 0x7, 0x0])
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
r4 = open(&(0x7f00000002c0)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSDTR(r4, 0x20007479)
setreuid(0xee00, 0x0)
semop(0x0, &(0x7f0000000180)=[{0x0, 0x43, 0x1800}, {0x4, 0xe6, 0x1800}, {0x0, 0xfd, 0x1000}, {0x1, 0x20}, {0x2, 0x5, 0x1800}, {0x4, 0x9e, 0x1000}, {0x2, 0xfffb, 0x1000}, {0x0, 0x40, 0x1000}, {0x0, 0x6, 0x1000}], 0x9)
semctl$SETALL(0x0, 0x0, 0x9, &(0x7f0000000740)=[0x1000])
r5 = semget(0x1, 0x1, 0x230)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000200)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x182}, 0x6, 0x8000000000000000, 0x2f})
r6 = getuid()
setreuid(0xee00, r6)
semctl$IPC_SET(r5, 0x0, 0x1, &(0x7f0000000280)={{0xffff1c8d, r0, 0x0, r6, 0x0, 0x125, 0x1}, 0x1f, 0xffffffffffff8001, 0x4})
setsockopt$inet_opts(r2, 0x0, 0x14, &(0x7f0000000000)='\x00\x00', 0x2)
setsockopt$inet_opts(r1, 0x0, 0x1, &(0x7f00000001c0)="2aba0f79228522d81505c2abc71dbf569341d25ac6d93d9912f4aa04e960c6de16d2ae23da1e7e82702e9ae3b805f5333e4590e219fd33f2d2444dd95710e219a1f0a812553f18632ffdbe7c313e0040909f82d0cc6b2d510ca58ebada6891cf0b198314378196ca79dd6b0b7e1c9849d9ce03a22e4da51b55ed737e656002ff0bcea5", 0x83)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000180)={0x2, &(0x7f00000000c0)=[{}, {0x5, 0x0, 0x0, 0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x2c}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0xfffffffffffffef1)


mknod(&(0x7f0000000180)='./bus\x00', 0x2000, 0x5700)
open(&(0x7f0000000040)='./bus\x00', 0x0, 0x0)
unlink(&(0x7f0000000080)='./bus\x00')


syz_emit_ethernet(0xae, &(0x7f0000000180)=ANY=[@ANYBLOB="6982ffd40d27aaaaaaaaaabb8863"])


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x70e, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f0000000640)=[{{r0}, 0x7ffffffffffffff7, 0x1}], 0x6, 0x0, 0x6, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000080)=[{0xc0}, {0x40}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000001})
execve(0x0, 0x0, 0x0)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc028698d, &(0x7f0000000080))


r0 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000dc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', r0, &(0x7f0000000ec0)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
r1 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
readlinkat(r1, &(0x7f0000000380)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000840)=""/211, 0xd3)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x4000000000000003}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x100000000000000, 0xffffffffffffffff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x3a)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r1, &(0x7f0000000100)="00003226a4a9000064e7c803d2a423734333a4dd", 0x14)


ioctl$WSKBDIO_SETKEYREPEAT(0xffffffffffffffff, 0x800c5707, 0x0)
mknodat(0xffffffffffffffff, &(0x7f0000000100)='./bus\x00', 0x2110, 0x7fff)
openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x20000, 0x0)
open(&(0x7f0000000280)='./file0\x00', 0x615, 0x0)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0xfffffffa, 0x9, &(0x7f0000000480), 0x0)
dup(0xffffffffffffffff)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
socket(0x1, 0x2, 0x0)
preadv(0xffffffffffffffff, &(0x7f00000012c0)=[{0x0}], 0x1, 0x0)
acct(&(0x7f0000000140)='./file0\x00')
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x4, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, &(0x7f00000004c0))
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, 0x0)
socket(0x0, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
ktrace(0x0, 0x0, 0x0, 0xffffffffffffffff)
r2 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
ioctl$VNDIOCGET(r2, 0xc4104603, &(0x7f0000000000)={'./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0xffffffff})


r0 = open(&(0x7f0000000100)='./file0\x00', 0x205, 0x0)
fcntl$lock(r0, 0x7, &(0x7f0000000040)={0x0, 0x0, 0xfffffffffdfffffc, 0x1100300010008})


msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0xffffffffffffffff, 0xffffffffffffffff}, 0x0, 0x0, 0x0, 0x0, 0x8000000000000000})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x1, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = socket(0x800000018, 0x1, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "1a1116fbd0f700ff000000002000"})
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000240))
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000080))
open$dir(&(0x7f0000000080)='.\x00', 0x0, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r1 = fcntl$dupfd(r0, 0x3, 0xffffffffffffffff)
sysctl$net_inet6_ip6(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)
ioctl$FIONREAD(r1, 0x800c745b, &(0x7f0000000080))
sendto$unix(0xffffffffffffffff, &(0x7f0000000080)="e066fe71dd54c85048a6ae968c22233da611a6ad5fcdcc0da4f05e65380e7c4b38a7e8f79747fbf6778a2124e8310d6299fad15811fa56d3dafd663879a0e3a49d494c166da97165e69ea5b87139f65c8357ce80b37ee49321c89c49c79bd5ccf3a7c6f229d492f017366bd0356fd2c3dc6b27a7419141977b3add295b237297d0d578a7acdbfe2d9509729ff1a8687a2e3a41818466c5802d986dc210fea19a3636fdf6a0a5ff67eb73a775d184bf68c3637ddd3c58cadf78f01593bb86a0ed2afec8da739ed43d541e2a5df12e16d1a71ce14a6169717e65ff1c82db550717668dfe1e356e0797c0d5204613c21b75aad6d61c8d949c85f3fe007a1fc714d30fbe12dbb318c8aed8aa85abafe3242789a90936962bd1e9614df96644808f8db96d8f991d8e23f1866c74760b608fa5803478949940be967f756a296fa1f7be4aa1ebd53cd5977be50376ddde190161a722b2e7ea7f0c1b15b648bfb9634a2bed0424a0e29447e15b227ec9ae2f80fd54", 0x171, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x8040691a, &(0x7f00000001c0))
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000001c0)=[{}, {}, {0x6}]})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r3 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x8020691f, &(0x7f00000001c0))


sendto$unix(0xffffffffffffffff, &(0x7f0000000140)="b1000503000004000000000007000000331c13fecea10500fef96ec0c72fd3357ae30200004e3039d2d236acf20b7804be38164981f70bcf5f882b297be1aa0500000051e2f0ad09000000000000009b672f4d335c223e7d0c032bfa896443a42100000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b1257aea8c500002002fbfe0c2300008abfba0900000008e371a3f834", 0x9d, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80286987, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000140)=[{0x20, 0x1}, {0x3c, 0x0, 0xfc}, {0x6}]})
syz_emit_ethernet(0x127, &(0x7f0000000040)=ANY=[])


kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x2, 0x0)
r0 = socket(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x3, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x1, &(0x7f0000000240)="01000000", 0x4)
socket$inet(0x2, 0x3, 0x0)
ioctl$FIONREAD(r0, 0xc0206923, &(0x7f00000001c0))
ioctl$FIONREAD(r1, 0x8004745d, &(0x7f0000000200))
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x1, &(0x7f00000000c0)=[{}]})
mknod(&(0x7f0000000180)='./file0\x00', 0x6000, 0x0)
lstat(&(0x7f0000000040)='./file0\x00', 0xffffffffffffffff)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
socket(0x18, 0x1, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa", 0xa)
sysctl$net_pipex(&(0x7f0000000000)={0x4, 0x23, 0x1}, 0x3, 0x0, 0x0, 0x0, 0xffffffffffffff17)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000000), 0x6, 0x0, 0x0, 0x0, 0x0)
setpgid(0xffffffffffffffff, 0x0)
setrlimit(0x8, 0x0)
sendto$unix(r0, &(0x7f0000000280), 0x0, 0x0, &(0x7f0000000100)=@abs={0x1, 0x0, 0x1}, 0x8)
r2 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
ioctl$VMM_IOC_INFO(r2, 0xc0185603, &(0x7f0000000000)={0x97, 0x0, &(0x7f0000000180)=""/151})


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$VMM_IOC_RESETCPU(r0, 0x82405605, &(0x7f0000000280)={0x2, 0x0, {[], [0x0, 0x0, 0x8001, 0x337], [], [0x0, 0x0, 0xfffffffffffffffe, 0x0, 0x5], [{}, {}, {}, {}, {}, {}, {}, {0x0, 0x2}]}})


mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x0)
sysctl$net_inet6_icmp6(0x0, 0x0, 0x0, 0x0, &(0x7f0000000140)="80468b309b2548cca0c3bd621508525753789a6678d065d43ee4beba5f1b29d75f17fbc7afd04721d15570cfc48e0c124334ca8f55e8fe16ae3c48f5447f2ffc59e1de35169f015f6c7037faee2301a56aa2741434d2b14fab1e7701f22c3262a9f8e27a8a696caa3b9ab7c06b7d2489b7ce8bf6fd9b847cf1d878486af7992904af965bf98c7545167c41c2041c0942", 0x90)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x8020697a, &(0x7f00000001c0))
kqueue()
sysctl$vm_swapencrypt(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x31}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0xfffffffffffffda3)
setrlimit(0x0, &(0x7f0000000980)={0x0, 0x35})
r1 = socket(0x18, 0x2, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
close(r1)
r2 = socket(0x18, 0x3, 0x0)
setsockopt(r2, 0x1000000029, 0x32, &(0x7f0000000440)="b211d7170d816685c8e360f2fa41c1a0946988b272a746e337b372e93320cff6669cbe7868de45ed3fc33719ca6df71ecec8a900108b2c10a1f8c66653b276e180e9cb9b21f9982230f575295d48889c98000796b2dd921a4975680b37ba955d2c15e6d7c9198ed900ab006ddfb6f869b51a2216114d1ece85f593e74035f5bc054eb1dbddf42a004000000000000000", 0x90)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
writev(0xffffffffffffffff, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_open_pts()
syz_emit_ethernet(0x3e, 0x0)
r3 = socket(0x18, 0x2, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "ce51bf2b1e61cd965d51c9f9c3e137a69f61a565"})
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmsg(r2, &(0x7f0000000340)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000380)=ANY=[], 0x11}, 0x0)
unveil(0x0, 0x0)
open(0x0, 0x0, 0x0)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$inet(0x2, 0x2, 0x0)
close(r0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="9dd6981f1c370d89d86a1420", 0xc)


pledge(0x0, &(0x7f00000000c0)='\x00')
pledge(&(0x7f0000000000)='tty   \x00\x02\x00!\a\x9bp^|#\xcbhl\x97\xa3_\xbc\x04\x9d!\xd9\x9f\x9f\xb4\x96\x13\x12\xe0\r\xe7\xb9E\b\x00\x00\x00B\xaaY\xe1Q<\x19\xc0\xf6Yf\x9au^\xa0\xc9j\xdd-I\x01R\x00w\xf7\x15\x04\xa6\x82aY\x1d\xd7\f>Y\x06\"\xad\xb6\x88_\xeb\at\x91\xd3\xbf\xea\xddt\xe0\bt\x06S,\x1f\x1fj\xa5H\x01nz\x947\xf8Q|o\x80\xdbH\xa7-\xaaw\xcet\x044\xc5\xa9e\xa9\xf6\x1b\x8e\x05\x86\x91IsC\xb9ul\xaeu\xad\x9b\xaf\x04\xc4\x03\"F\x8f\xd5\xe8\r\x8d\xa1\x00\xcc\xd7\xa0\xe1\xeb\xc1>\xbd\t\xc8\x15\v\xb0, \xee\xa4\xa6\xb9a\x01&\xadrj\xd5\xc26p\xa14\xe0\xbf\xa0\x1es\x01=\xdbd\xf0?=<l\x8c\x01\xe3\x05$\x1c\x04B\x00\xa4P\x04\xcf\x87\xaa\x96iP\x14{4\xe6\x87\x9d\x8f\bz9$\x10_\xd8E\x93\x92\xf5\x8au\xab\xf9)\xf5\xa6\xc7\xc8\xed\xb9\x1f:\x03K\xa2\xdbUshx\xbe\\\x19\xdax\xeb_W\xbb\'\x00G\xbb\xfd\xe2\xd58\xf4:)\x10|r\x1e\x06p>\x8afcJ\x8e\xf7\nn\xd4<\x00\xec\xe4^\x00\x00\x00\xca\x90\xfa\x98\xc9gty\xce\xab\xd2\xa1\x85E\xe4\xa9\xd5\xab\x83\xda?w\x83\xbc\xcf\xd20(L&b\xed\x8c\x1d\x1a\x9fd\x99H\x9e\x82\x10\xea\x05\xf8\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\xa6\x8c\x05n\x83\x83\x12+\x16\xc1\x00\x04\x00\x00\x13:o\x0f\x1fB\xa4\xddwB\x92h\xde\xfal3\x88e\x04J\\\x00D\xae`\x8e\xadd\xa8;\xee\xc4K\xe8]\x84\x90\xb8d\xfb\x95\xb3\xe9(x_\x80]\xadW\xd5\xa9\xaa\x03\x9c6\xa9\xc4\x01\x03\xea\xe5\x90\x85\x16\xb0DV\x13\x01\xab\x01\xf0\x8f\x02\xc2\xc89\x19o\xf5zJ\x9b\x03\x1f\xd7\xdbN\\\xc0\xcd?Pg\xd5q\x13\xbd \xfa\xab\xccJK\x11\\\x16~#P.\xc9K\x15r\xab\xda\xe2\xd4\xec8\x8b\xb6e\x96\xe9\xc3\x93\xed\x94.\xc2\xa0\x1fU#\x96\xe6\xb6C\xfa\x03/\x8b\x0e2\xec\x96v\x9b/.\v\x9e\x80\x18s\xae.\xf4\x14KS`\x87\x8b4\t\x00\x87{\xa8@e\xbfe\xeb\xee\xa2\xe72\xb8Q:\x9f\xc2ym\x86\xc4\xcbm\x80%\xfc\x9e\x9f', &(0x7f0000002840)='tty   \x00\x02\x00!\a\x9bp^|#\xcbhl\x97\xa3_\xbc\x04\x9d!\xd9\x9f\x9f\xb4\x96\x13\x12\xe0\r\xe7\xb9E\b\x00\x00\x00l\xaaY\xe1Q<\x19\xc0\xf6Yf\x9au^\xa0\xc9j\xdd-I\x01R\x00w\xf7\x15\x04\xa6\x82aY\x1d\xd7\f>Y\x06\"\xad\xb6\x88_\xeb\at\x91\xd3\xbf\xea\xddt\xe0\bt\x06S,\xdbH\xa7-\xaaw\xcet\x044\xc5\xa9e\xa9\xf6\x1b\x8e\x05\x86\x91IsC\xb9ul\xaeu\x94\x9b\xaf\x04\xc4\x03\"F\x8f\xd5\xe8\r\x8d\xa1\x00\xcc\xd7\xa0\xe1\xeb\xc1>\xbd\t\xc8\x15\v\xb0, \xee\xa4\xa6\xb9a\x01&\xadrj\xd5\xc26p\xa14\xe0\xbf\xa0\x1es\x01=\xdbd\xf0?=<l\x8c\x01\xe3\x05$\x1c\x04B\x00\xa4P\x04\xcf\x87\xaa\x96iP\x14{4\xe6\x87\x9d\x8f\bz9$\x10_\xd8E\x93\x92\xf5\x8au\xab\xf9)\xf5\xa6\xc7\xc8\xed\xb9\x1f:\x03K\xa2\xdbUshx\xbe\\\x19\xdax\xeb_\x10|r\x1e\x06p>\x8afcJ\x8eYEn\xd4<\x00\xec\xe4^\x00\x00\x00\xca\x90\xfa\x98\xc9gty\xce\xab\xd2\xa1\x85E\xe4\xa9\xd5\xab\x83\xda?w\x83\xbc\xcf\xd20(L&b\xed\x8c\x1d\x1a\x9fd\x99H\x9e\x82\x10\xea\x05\xf8\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\xa6\x8c\x05n\x83\x83\x12+\x16\xc1\x00\x04\x00\x00\x13:o\x0f\x1fB\xa4\x00wB\x92h\xde\xfal3\x88e\x04J\\\x00D\xae`\x8e\xadd\xa8;\xee\xc4K\xe8]\x84\x90\xb8d\xfb\x95\xb3\xe9(x_\x80]\xadW\xd5\xa9\xaa\x03\x9c6\xa9\xc4\x01\x03\xea\xe5\x90\x85\x16\xb0DV\x13\x01\xab\x01\xf0\x8f\x02\xc2\xc8\x9b\x03\x1f\xd7\xdbN\\\xc0\xcd?Pg\xd5q\x13\xbd \xfa\xab\xccJK\x11\\\x16~#P.\xc9K\x15r\x04\xd9Z;\xc0\x8dOze\x96\xe9\xc3\x93\xed\x94.\xc2\xa0\x1fU#\x96\xe6\xb6C\xfa\x03/\x8b\x0e2\xec\x96v\x9b/.\v\x9e\x80\x18s\xae.\xf4\x14KS`\x87\x8b4\t\x00\x87{\xa8@e\xbfe\xeb\xee\xa2\xe72\xb8Q:\x9f\xc2b\x897\xbe\r\x04\xdf\xe2\xc0\xf0FV\'m\xcbm\x80%\xfc\x9e\x9f\x87\x80A\xbe\xc2\x00\x00\x00\x00\x00\x006\x96\xbb\x9f\x85\x98\xbb\xbc;\xaa\x97c\xfe\x82jz&t\xa7\xc4\xcd\xb0\b9G\xcag\fY\xe6\r\xcdT\xd3\x1c(\xef\xc0\x038\xbd\xdd\xd9\xc9\x93a]q\xd2\x9b\a\x1e\xf8\xc3\"\xc8:\xb8$\x9f\'P\x17\xfa\xf3Xa\trB-\xf2g\xe6Z\xd5F\xd2\x80\xe0\x99\"\xc12\xe8\b\xc58\x00'/659)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
open(&(0x7f0000000240)='./bus\x00', 0x0, 0x0)
r0 = dup(0xffffffffffffffff)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000080), 0x4)
setsockopt(0xffffffffffffffff, 0x1000000000029, 0x9, &(0x7f0000000240), 0x0)
ftruncate(0xffffffffffffffff, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000000c0)=[{0x3d}, {0x44}, {0x8006}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])
sysctl$net_inet6_ip6(&(0x7f0000000080)={0x4, 0x18, 0x29, 0x35}, 0x4, 0x0, 0x0, 0x0, 0x0)
r2 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0106924, &(0x7f00000001c0))
ioctl$FIONREAD(0xffffffffffffffff, 0xc0406938, &(0x7f00000001c0))
preadv(0xffffffffffffffff, 0x0, 0x0, 0x0)
madvise(&(0x7f00003e1000/0x3000)=nil, 0x3000, 0x0)


r0 = open(0x0, 0x0, 0x0)
mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0, 0x10, r0, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x58}, 0x2, &(0x7f0000000140)="1139a509", &(0x7f0000000180)=0x4, &(0x7f00000001c0), 0x0)
r1 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x80606948, &(0x7f00000001c0))
r2 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000240), 0x0)
openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
sysctl$net_inet6_ip6(&(0x7f0000000000)={0x4, 0x18, 0x29, 0x36}, 0x4, 0x0, 0x0, &(0x7f0000000040)="bcf02f1785a92e9ee0f5bbed4165c6be33", 0x11)
syz_emit_ethernet(0x137, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x129, 0x0, 0x1}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x1, 0x0, 0xe, 0x4, 0x2, 0x0, 0x233, {[@generic={0x2, 0x9, "96c729637cae4f"}, @sack={0x5, 0xe, [0x0, 0x0, 0x0]}, @timestamp={0x8, 0xa, 0xb018, 0x8}, @generic={0x4, 0x2}]}}, {"d1c2f0bfe2d0786ca28e44289f59aba04d62ff16e6bb47f1cd981d0cf5f225560531db5a3a6c3cb3d5ac50e0eec7423f3ef5e3c4a13f81f14f843a32b529e4649b57d581159522ddf03a6cabf358af4e1ae7ab79a9aac6417859ae29d8de08ba3da1e6387381a61f166b78d7ae58ccd15a08555c8e7db3e261cbba4f565ff3567edfcacd1a43a2f80b44a3727c2f46723f3826d9842357f4d467cb2e24ed586547d107e74cfe46502dde741762fe8ad6742200cf5fd16fcdadae4fd744b730286383e0444647e948151cb63c5c12b79f75a37762e3f013f189799eb699"}}}}}})
syz_emit_ethernet(0x6a, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x5c, 0x0, 0x1}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x1, 0x0, 0x12, 0x4, 0x2, 0x0, 0x233, {[@generic={0x0, 0xd, "96c729637cae4fa49c1558"}, @sack_perm={0x4, 0x2}, @sack={0x5, 0x16, [0x0, 0x0, 0x0, 0x0, 0xffffffff]}, @timestamp={0x8, 0xa, 0xb018, 0x8}, @generic={0x4, 0x2}]}}}}}}})


setreuid(0x0, 0xee01)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x8020697a, &(0x7f00000001c0))


mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x2000, 0x2d87)
r0 = kqueue()
r1 = openat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x0, 0x0)
kevent(r0, 0x0, 0x0, &(0x7f0000000580), 0x65, 0x0)
kevent(r0, &(0x7f0000000140)=[{{r1}, 0xfffffffffffffffe, 0x9f}], 0xd, 0x0, 0x0, 0x0)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000100), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105727, &(0x7f0000000200)={&(0x7f0000000240)=[{0x1}, {}], 0x2})


openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000600), 0x1, 0x0)
r0 = socket(0x0, 0x2, 0x0)
close(0xffffffffffffffff)
sysctl$net_inet_ip(&(0x7f0000000080), 0x4, 0x0, 0x0, 0x0, 0x0)
r1 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x88}})
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x840008, 0x4)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f00005bd000/0x3000)=nil}, {&(0x7f0000fff000/0x1000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ff7000/0x3000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000fef000/0x10000)=nil}, {0x0, &(0x7f0000108000/0x1000)=nil}, {0x0, &(0x7f0000560000/0x2000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f00002f6000/0x3000)=nil, &(0x7f0000ff9000/0x6000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ff0000/0x2000)=nil}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0/file0\x00'})
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
sysctl$vm_swapencrypt(&(0x7f0000000040), 0x3, &(0x7f0000000080)="469749", &(0x7f00000000c0)=0x3, &(0x7f0000000100)="c08f92a9acca90f0a7a3fb54e0f6f66db558eec8b09164486369f7b7082d1f718c46166d7b439caa34cf5eb6e8bffd9596b24554c306d231bdc71292211ce36c78792017514604f39fa39d358bb891ac3045334313a3f4a468a6061316220e66ea4790c90f7aea7daa1e5be5090937444b15cd6fad46e47a2223e2bd64a05904c8116f4f995d13989cb96b67288720de52aa8ae8262502f127a5d9", 0x9b)
poll(0xffffffffffffffff, 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000500), 0x1, 0x0)
r3 = open$dir(&(0x7f00000000c0)='.\x00', 0x0, 0x0)
mkdirat(r3, &(0x7f0000000100)='./file0\x00', 0x0)
mknodat(r3, &(0x7f0000000580)='./file0/file1\x00', 0x6000, 0x0)
getpeername$unix(0xffffffffffffffff, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000500)={0x0, 0x0, &(0x7f0000000480)=[{&(0x7f0000000380)='s', 0x1}], 0x100000000000038b}, 0x1)
shmget$private(0x0, 0x4000, 0x1c0, &(0x7f0000001000/0x4000)=nil)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f00000001c0)=[{0x54}, {0x25}, {0x6, 0x0, 0x0, 0xfffffffd}]})
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000080)="35b5c242413c1026089a59583cc3", 0xe}], 0x1)


r0 = syz_open_pts()
openat$zero(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
msgget$private(0x0, 0x1c2)
r1 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
pwritev(0xffffffffffffffff, &(0x7f0000000000)=[{0x0}], 0x1, 0x2fffd)
writev(r1, 0x0, 0x0)
open(0x0, 0x2e1, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000040), 0x4)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000080), 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)
syz_extract_tcp_res(&(0x7f0000000000), 0x0, 0x0)
open(0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
ioctl$TIOCSTOP(0xffffffffffffffff, 0x2000746f)
sendmmsg(0xffffffffffffffff, &(0x7f00000007c0)={&(0x7f0000000780)={0x0, 0x0, &(0x7f0000000200)=[{&(0x7f0000000180)="b860fe09625ee6793978a575faa1b6c6c1d6c2eca2950efd7f97e41e178f37a79f00659c2e89ac56733f7e4e4973c1e600000000000000008c5c7b93d5c20ab4211791fe30", 0x45}], 0x1, 0x0}}, 0x10, 0x0)
r2 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x80206979, &(0x7f00000001c0))
open(0x0, 0x0, 0x4)
writev(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x12, &(0x7f0000000200)=ANY=[@ANYBLOB="abaaaaaaaaaaffffffffdfff8847"])
ioctl$FIOASYNC(r0, 0x80047460, &(0x7f00000000c0))
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000140)={0x5, &(0x7f0000000100)=[{0xcc6}, {}, {0x60}, {0x1f, 0x8, 0x20, 0x3bf}, {0x0, 0x0, 0x40, 0x2}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
ioctl$FIOASYNC(r0, 0x80047460, &(0x7f0000000200))
close(0xffffffffffffffff)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f00000000c0)=[{0x45}, {0x74}, {0x812e}]})
syz_emit_ethernet(0x36, &(0x7f0000000840)=ANY=[])


r0 = socket(0x2, 0x1, 0x0)
r1 = semget$private(0x0, 0x4000000009, 0x82)
semop(r1, &(0x7f0000000300)=[{0x4, 0x3, 0x1800}, {0x3}, {0x4, 0x201, 0x1000}, {0x3, 0x1000, 0x1000}, {0x0, 0x7a5}, {0x3, 0xff72, 0x3800}, {0x4, 0xdb, 0x800}, {0x0, 0x1, 0x800}, {0x3, 0xa, 0x1000}, {0x0, 0x2a22, 0x1000}, {0x3, 0x95ce}, {0x2, 0x100}], 0xc)
semctl$IPC_RMID(r1, 0x0, 0x0)
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x7}, 0x7fffffff, 0x2, 0x10000000009})
semctl$GETALL(r1, 0x0, 0x6, &(0x7f00000002c0)=""/222)
r2 = dup(r0)
listen(r2, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000200)={0xffffffffffffffff, <r3=>0xffffffffffffffff})
r4 = dup(r3)
recvmmsg(r4, &(0x7f0000000440)={&(0x7f00000000c0)={0x0, 0x0, &(0x7f0000000580)=[{0x0}, {0x0}, {&(0x7f0000000240)=""/90, 0x5a}], 0x3, 0x0}}, 0x10, 0x0, 0x0)
dup2(r2, r4)
execve(0x0, 0x0, 0x0)
select(0x40, &(0x7f0000000100)={0xffffffffffffffff}, 0x0, 0x0, 0x0)
select(0x40, &(0x7f0000000000)={0x7fffffffffffffff}, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000980)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x2, &(0x7f0000000000)=[{0x20, 0x0, 0x0, 0x8000}, {0x16}]})
write(r0, &(0x7f0000000180)="7f23a3c23cce2575e1dd92c25683", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000080)=[{0x61}, {0x80, 0xfc, 0x0, 0x5}, {0x6}]})
syz_emit_ethernet(0x5e, &(0x7f0000000040)=ANY=[])


r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r3 = socket(0x2, 0x2, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
connect$unix(r3, &(0x7f0000000000), 0x10)
r4 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x1023, &(0x7f0000000040), 0xe0)
r5 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r5, 0xffff, 0x1023, &(0x7f0000000040), 0x4)
recvmmsg(r5, &(0x7f0000000180)={0x0}, 0x10, 0x0, 0x0)


r0 = open$dir(&(0x7f0000000280)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000300)='./file0\x00', r0, &(0x7f0000000c80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f00000000c0)='./file0\x00', r0, &(0x7f00000001c0)='./file0\x00')
open$dir(&(0x7f0000000700)='./file0\x00', 0x200, 0x0)


r0 = socket(0x18, 0x1, 0x0)
close(r0)
listen(r0, 0x0)


mkdir(&(0x7f0000000300)='./file1\x00', 0x0)
chroot(&(0x7f0000000240)='./file1\x00')
unveil(&(0x7f0000000040)='.\x00', &(0x7f0000000080)='c\x00')
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000040), &(0x7f0000000100)=0xc)
writev(0xffffffffffffffff, &(0x7f00000002c0)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe2c63a56077123a276d3ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
symlink(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000100)='.\x00')
openat$zero(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)


r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
socket(0x1e, 0x3, 0x0)
socket$inet(0x1e, 0x3, 0x0)
dup2(r1, r2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000680)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f00000000c0)=[{0x61}, {0x87}, {0x26}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


open(&(0x7f0000000180)='./file0\x00', 0x75f493fec6515f78, 0x0)
ktrace(&(0x7f0000000140)='./file0\x00', 0x4, 0x1808, 0x0)
writev(0xffffffffffffffff, &(0x7f00000002c0)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe2c63a56077123a276d3ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
mkdir(&(0x7f0000000080)='./file0/file0\x00', 0x0)
rename(&(0x7f0000000080)='./file0\x00', &(0x7f00000000c0)='./file0\x00')


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000080)=[{0x4d}, {0x74}, {0x6}]})
syz_emit_ethernet(0x17a, &(0x7f00000001c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x6d4)
r1 = open(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)
ioctl$FIOASYNC(r1, 0x80047470, &(0x7f00000000c0))
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000280)=[{0x7c}, {0x1}, {0x6}]})
open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r2 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r2, 0x8, 0x0)
r3 = socket(0x800000018, 0x1, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0xffffffffffffffff}})
bind$unix(r3, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
r4 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x1000, &(0x7f0000000000)=0x800009, 0x4)
bind$unix(r4, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
sysctl$net_inet_ip(&(0x7f0000000080)={0x4, 0x2, 0x0, 0x17}, 0x4, 0x0, 0x0, 0x0, 0x0)
r5 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r5, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r5, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


sysctl$net_inet_divert(&(0x7f0000000040)={0x4, 0x2, 0x2}, 0x4, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
sysctl$vm_swapencrypt(&(0x7f0000000040)={0x6, 0xb}, 0x5, 0x0, 0x0, 0x0, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x22, &(0x7f0000000000), 0x0)


kevent(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000015c0))
mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x5200)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$TIOCEXCL(0xffffffffffffffff, 0x2000740d)
r0 = kqueue()
kevent(r0, 0x0, 0x0, 0x0, 0x3f, 0x0)
ioctl$VMM_IOC_RESETCPU(0xffffffffffffffff, 0x82405605, &(0x7f0000000140)={0x0, 0x0, {[], [0x0, 0x0, 0x0, 0x0, 0x0, 0x3], [], [0x0, 0x0, 0x0, 0x0, 0x5, 0x7fffffff]}})
kevent(r0, &(0x7f0000000080), 0x401, 0x0, 0x7fffffff, 0x0)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000280)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000001c0)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000000)=0xc)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r1}})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4e}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080), 0x0, 0x37)


mknod(&(0x7f0000000040)='./file0\x00', 0x2000, 0x3200)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$WSDISPLAYIO_LSFONT(r0, 0xc058574e, &(0x7f0000000340))


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0xfffffffe})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x400000002, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r2 = socket(0x18, 0x1, 0x0)
r3 = dup2(r1, r2)
sendmsg$unix(r3, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


open$dir(&(0x7f0000000240)='./file0\x00', 0x200, 0x0)
r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x1, 0x0)
pwritev(r0, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
r1 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
ftruncate(r1, 0x80002)
pwrite(r0, &(0x7f0000000480)='w', 0xfffffc29, 0x7ffe)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000100), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000580)={&(0x7f0000000000)=[{0x22}, {}], 0x2})


mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
unveil(&(0x7f0000000080)='./file0/file0/../../file1\x00', &(0x7f0000000100)='r\x00')
mknod(&(0x7f00000002c0)='./file0/file1\x00', 0x0, 0x0)


ioctl$VMM_IOC_WRITEREGS(0xffffffffffffffff, 0x8020560a, &(0x7f0000000040)={0x1})
madvise(&(0x7f0000ffd000/0x1000)=nil, 0x1000, 0x0)
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000340), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$VMM_IOC_WRITEREGS(r0, 0xc0205609, &(0x7f0000000040))


connect$unix(0xffffffffffffffff, 0x0, 0x0)
getsockname$inet(0xffffffffffffffff, 0x0, 0x0)
r0 = socket(0x18, 0x2, 0x0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0xa, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
setrlimit(0x0, 0x0)
syz_open_pts()
close(0xffffffffffffffff)
syz_open_pts()
dup2(r1, r0)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f00000000c0)={0x0, 0x1ff}, 0x10)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmsg(r1, &(0x7f0000000ec0)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(r0, &(0x7f0000001580)=[{&(0x7f0000000000)='\x00', 0x1}], 0x1)
select(0x40, &(0x7f0000000100), &(0x7f00000024c0)={0x1ff}, 0x0, 0x0)
readv(r0, &(0x7f0000000740)=[{&(0x7f0000000140)=""/144, 0x90}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000001c0)=[{0x6c}, {0x3}, {0x6}]})
syz_emit_ethernet(0x62, &(0x7f00000000c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000001380)=[{}, {0x24}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000500)={0x3, &(0x7f00000000c0)=[{0x4}, {}, {0x8106}]})
syz_emit_ethernet(0x62, &(0x7f00000008c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{0x15}, {0x3}, {0x8106}]})
syz_emit_ethernet(0x3e, &(0x7f0000000040)=ANY=[])


setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000000)="ebffcbff13", 0x5)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000002a40)={&(0x7f0000000000), 0x10, 0x0}, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x2, 0x0)
connect$unix(r0, &(0x7f0000000000), 0x10)
sendmsg$unix(r0, &(0x7f0000002a40)={0x0, 0x0, 0x0}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000200)=[{0x45}, {0x81}, {0x9756}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0, 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setrlimit(0x3, &(0x7f0000000040))
setrlimit(0x3, &(0x7f00000000c0))


ftruncate(0xffffffffffffffff, 0x0)
setitimer(0x0, &(0x7f0000000040)={{0xffffffff}, {0xffffffff}}, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000080)=[{0x4c}, {0x1d}, {0x8006}]})
syz_emit_ethernet(0x1db, &(0x7f00000007c0)=ANY=[])
r2 = socket(0x1, 0x1, 0x0)
close(r2)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
socket(0x18, 0x1, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


setreuid(0xee00, 0x0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x1604)
open(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)


acct(0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
fchdir(0xffffffffffffffff)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x7}})
r0 = socket(0x18, 0x2, 0x0)
sysctl$vm(&(0x7f0000000200)={0x2, 0x9}, 0x2, 0x0, 0x0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000580)={0x0, 0x0})
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, 0x0)
r2 = socket(0x0, 0x0, 0x0)
setsockopt(r2, 0x29, 0x6c, &(0x7f0000000040), 0x4)
close(r2)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sysctl$vm(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
getsockname$inet(0xffffffffffffffff, 0x0, 0x0)
r3 = socket(0x18, 0x2, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
dup2(r3, r0)


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000080)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
bind$unix(r0, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
setreuid(0x0, 0xee01)
r1 = socket$unix(0x1, 0x1, 0x0)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
dup2(r1, r0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000a, &(0x7f0000000000)="ea00005c00000000", 0x1)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000080)="ea00030000000000", 0x8)
setsockopt$inet_opts(r0, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0x8)


mknodat(0xffffffffffffff9c, &(0x7f0000000280)='./file0\x00', 0x1000, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
openat$diskmap(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
openat$pci(0xffffffffffffff9c, 0x0, 0x0, 0x0)
poll(0x0, 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x4, 0x1000000000054})
r0 = syz_open_pts()
open(&(0x7f0000000000)='./bus/\x00', 0x200, 0x0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r1, 0x80047460, &(0x7f0000000000)=0x6)
setrlimit(0x4, &(0x7f0000000140)={0x2, 0x4})
writev(r0, &(0x7f0000000180)=[{0x0}, {&(0x7f0000000a80)="dac5136729ff29c264006690291b4a87fc2a6d4364edce1cd1720a2fe082492f8b4eb05cc406411072b732020060820bccf45809ca9a9955a43dd6428a1bcc2b97e6969840ce81fd67aef3c1342b63eacdd004205a96ca6aab201e2d59c024ca32c891e579f51637535685d99bdaaed9a0575ab7bdf9cd4a353b67472b8d8f59224cff196be0a7eef4f9d185f5a2d321e3052f91e0f40f832de578c9207ead993163902d01f824420b3600fc08c6fb0cde74fcd4fefacf683832b59c9de7fd3199c4f2ad232c775c5c0d0afd49e869a22a7f6c47f40a51e5d44ecf1146df5208af25547302c24a675a4c070e7194499188895e8a762f468feb223c15e1c42213f463dc5a8edd945dd11cce9eeae536e61ce9133bfee757563e5a0d7662625d5fab90109566af733cad15b87637629b2ea96d6430201aaf83e36d520dca37d6fd32c21e9ed45542d5e65dbd7a6a28051ee7166487444f453ef27523f5eaa737ee5d0777170ffe89ae5d8b4216c40e1d1bc8343832c190561c317e5d820b2445c1b0c03c9d8078fe141d7a4853940f6d9c4af0d2a713c8fa5960c6f65db7462818832b7e728130343ccc946f8b2300ae936cad85af17a192e9259b7a99107ae0f11e587d94a6ea46373810b34d7f1291ad197efb8e66237deb60616739995f6ec6b60b2a34bde7b225fe2c903ea243a638d4fd885ad7d89e3416cdd04f5aaa69", 0x1ff}], 0x2)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
writev(0xffffffffffffff9c, 0x0, 0x0)
mlock(&(0x7f0000ffb000/0x3000)=nil, 0x3000)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, &(0x7f00000001c0))
socket(0x2, 0x3, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000000)={&(0x7f0000000200), 0x1c, 0x0, 0x0, 0x0, 0x0, 0x401}, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x200000000000a, 0x0, 0x0)
sysctl$machdep(&(0x7f0000000080)={0x7, 0xf}, 0x2, 0x0, 0x0, &(0x7f0000001100), 0x4)


close(0xffffffffffffffff)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000040)={0x7fff, 0x0, 0x1, 0x5773c5b9, "5b349b96a0a1000000faffffff000000ff597bd6"})
writev(r0, &(0x7f0000000300)=[{&(0x7f00000019c0)="f9ba003e68abdc8869a8ee40d72fd29bb43cda5969a2dedfc8d945184e3176b55f29e9fc3fc1620383da368d71faf36418863382f8293399b0ce0b621675c4e5320059bbc035fa5aa849fa0ebe7f806fe8f755998682f6e84a153bf85b6be5e2f47c035e9564dd1bd59d8a3d5aeba5963602850c7300bd691b91940a181ac3ea7293b864c6750ac6e7146bb34021fda54dd8926116caf7ef407f48cb59462d705b13c45350a281bfb235984de8477250cf81a7a33927855caeb4fa1e0536dbe6c0dec0b298e924d9c981ad9b9bc30f1f2e6b22943ede616141b79f6356d2913b2f9f8e4fad7a95c231665f418a54817b7fb56909d9b63e9fe3a778f69f6421ac2a1bc5bd31ff6328471b8ddf840cea3357fcf054ae3724baefcbef6bed659a666f3d24efd1c0a6c9c93f5d8814d6a3cd224f2c6f1c1b02220c68f44218833222a22d018df07cf96929f20a65ba83a929d115fd49fd48f38bb9876a5227920ef98291731523b91d351a1c9ce165cf2c40876c5a2254ac8fea506a8b84f67e8d3f86c4349bd6eb86fdd3a09158c9700fd8248e1e4ab97633fcc96e1ee9cc1b5a426c51656dc1a3372bf05f0138ced257c289b70bc6be2fa71dd67da4180be83a69a380a51ff0c49bbcfac80f9cac352eab7a09216eef797c98e869cb02931752e5674f344bdba9c24d5710850f1f0a1d30063a201729c1651c05bf47d5414f85b3de5ca00fd838469634dc5d13a25909b1847b4881529fb589df24422f12c0527c1820e6b79e87e358580097e9d38450d2fb51bc4cace71d28f4390c25314b5c0ffd2b42f8b3ca4dd20957c3d6072d8d5f27bcc226e7ac781050a8730b400ddda3e3d15465f5d9d05c33a8c74281f92dc2355deaddb80199e50f6034ea13db858b6970699ae3b7af12c587f7fd7eeae2a6c6ba472dc40a8536cbde02a8cd8d5541d87d49df7fb3d0db45c47cdc694d8a4239c2eaebf0b88c82412c575ca3b3b44c3f8d16a02b9b4b7cba61bbff04b07e706c288c1820ae2db74e8ed327b66f20a03e336de8f0f94064ac531c0c2491bca0befab14a16d39802cda0dcdf554d7a7844ca8d70b9aa8017529e0d2f1cb4a054358600da365e94f54a2efb634a7e3fca8f452ee06b77787f0b8cc0ddf322e080e83ab5249500e9250ff763edbc65bf807289a169c642a94f8f547b977ab2c7dbc566341caff1693079824d633b29d9b87aed7af4264bd4c02bdd87f8182b41359fd325029d1994c0282314b5a81b609d005a4cbc9e5eca62256ce848c1b6a8a7db95e086b5e6d9bc7bb9c91080b10c85d4c74737a9be73ae29d644bd2c76b62657d6c74627733e8a62b016a36e77460cd4add70da50eeda79ede0dbc2ccff43cb899af6a4cba869ce745e5b27d91f00535a0c36204a6ab0157e0e79c98c648442f5d7d265e23f50ad2ca3ce9287fd329f1236873ee4efe8962ced8abb1ad0f042f4f914ca061c85795f7b71817571d43d4daa6f09ed11b8fbd5acba7987829b9d4b1b31d5ae80f60e8d68f53f4460747d01c8691cd574d4136950783f8d995c5ba93a1ca2a2b5eaf0ed629bde6ff66a53766750c54f5889d0cd796efbc44da5e34c36fcd93dbd4b3e56d0d9ab86aa75955858ac48a8072edc0bf0de739f8ee5beebca6f9a3bb87be9c32921a941dc6a6d21e8e935002b8e3133f90d13d0d10334296ee2ee322cec4569de285cb0a199af8ab3cbd20f8cf71332af3989d9c397c69be8b8f0f3ef3fc07d2c82198b25b5dac22339222fccd4c23de43649c6038b6bf7dce886d89dd77e05a89b42aed0820c2783dfdda2ffe3bce4ea6a536b2c20debdc0e592b7bd040b5b92b7b5f66f94f9145f0bce8ebde82b851f6bbc896c88a6b61f3c69ecc886a1e91818216b81968ec4199a4179a4cbbb304e3b3e5b1e6c64282679d64665a1ae112745dd07351da9047035b75ab43b14d1c06467286549b2b3840ab6be9ebd2cc073ae06dfb0f6aa362a3da440b5ae03fa54b00bc99eb90940baa1fc574a582e524adc94cf97861e590266d3c4d0b171218c90ccd5bf98c0c073a3d85ba33326560a3cbfa16c58b21bc8a1479b8e2f9a2de96fab00c3fb96e1eaed9d7b4b9f89547e09bb3fd393ad6b67a29eed9a11969f01a8ad8415937f38da8e879fbb84906eceec316a8e60c7d07b47746e038074e2417b52be1145ff78abe657118ba61ebe5f2151c7dbf96bbc2eab46719226e1ec376584a53a2b2e840b03d776e87c5c89e03744cb89bfd2a2fc4f76d4acde04a052d1a485ffc48c56a68f8c70da41e86efee0b32b8dad8e9aaf556eb63efbce9b9be260ae077802a2194a4bc3d02d8a805341d9d8fca2975d128df7d8678a92d98aed25997b5e31c5780fdc3536c43b7cef84046c4e1bcac1b9c777713b5db18eca8a6a3e2bf33f4865b51989bfd1aed3cd6b00c330031f282148f330d583f09fb505f10d575fa4e908a1df04e6bc867af784f645866953ef9e238594aa279b8a22f1994a25928f77db01ee575983e4bfb0aaea89ee72c558120f9eb31decc8896bd2cd127dc28", 0x710}], 0x1)


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0xfffff8aa, 0x6c, &(0x7f0000000040), 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
r3 = dup2(r2, r1)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000980)={'tap', 0x0})
ioctl$BIOCSETWF(r4, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x1c}, {0xc}, {0x16}]})
write(r4, &(0x7f0000000180)="7f23a3c23cce2575e1dd92c25683", 0xe)
poll(&(0x7f0000000080)=[{r3, 0xab6cc3d7ffaa0897}], 0x1, 0x0)
poll(&(0x7f00000000c0)=[{r1}, {r3}], 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r5 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r5, 0xc0106924, &(0x7f00000001c0))
kqueue()
kevent(0xffffffffffffffff, 0x0, 0x101, &(0x7f0000000180), 0x6, 0x0)
r6 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r6, 0x802069b2, &(0x7f00000001c0))
mknodat(r3, &(0x7f0000000080)='./file0\x00', 0x4, 0x4)
select(0x40, &(0x7f0000000040)={0xffffffffffffffff, 0x0, 0x3}, 0x0, 0x0, 0x0)
pipe(&(0x7f0000000200)={0xffffffffffffffff, <r7=>0xffffffffffffffff})
fcntl$setown(r7, 0x6, 0xffffffffffffffff)
r8 = socket(0x2, 0x3, 0x0)
getsockopt(r8, 0x0, 0x6b, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
socket(0x18, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000007, 0x0, 0x0, 0x0, 0x3d)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$net_inet6_ip6(&(0x7f0000000040), 0x5, 0x0, 0x0, &(0x7f0000000000), 0x2e)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000280)=[{0x2c}, {0x1c}, {0x40e}]})
syz_emit_ethernet(0x2a, &(0x7f00000001c0)=ANY=[])


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x0)
r0 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
ioctl$TIOCGWINSZ(r0, 0x40087468, &(0x7f00000002c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000980)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x34, 0x0, 0x0, 0x8000}, {0x48}, {0x16}]})
write(r0, &(0x7f0000000180)="7f23a3c23cce2575e1dd92c25683", 0xe)


syz_open_pts()
close(0xffffffffffffffff)
socket$inet(0x2, 0x3, 0x102)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
ioctl$FIONREAD(r0, 0xc0206921, &(0x7f0000000140))


sendmmsg(0xffffffffffffffff, &(0x7f0000000c40)={&(0x7f0000000c00)={&(0x7f00000002c0)=@in={0x2, 0x3}, 0xfffffffffffffc46, 0x0, 0x0, 0x0}}, 0x10, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r0 = syz_open_pts()
close(r0)
pipe(&(0x7f0000000300)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
write(r1, &(0x7f0000000040), 0xfeea)
writev(r0, &(0x7f00000002c0), 0x100000000000026c)


mkdir(&(0x7f0000000040)='./file0\x00', 0x0)
chroot(&(0x7f00000001c0)='./file0/../file0\x00')
openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
open(&(0x7f0000000540)='./file0/file0\x00', 0x0, 0x0)
chroot(&(0x7f0000000100)='./file0\x00')
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000140)=[{0x1c, 0x0, 0x0, 0xfffffffc}, {0x30}, {0x16}]})
write(r0, &(0x7f00000001c0)="d9537abde93d050cdd16b13f742a", 0xe)


kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000300)=[{{}, 0xfffffffffffffff9, 0x41}], 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff})
kevent(0xffffffffffffffff, &(0x7f0000000140)=[{{r0}, 0xfffffffffffffffe, 0x2c5d36d679bbffbf}], 0x0, 0x0, 0x0, 0x0)
r1 = kqueue()
r2 = kqueue()
r3 = dup(r2)
kevent(0xffffffffffffffff, &(0x7f00000003c0)=[{{r3}, 0xffffffffffffffff, 0xc5}], 0x0, 0x0, 0x0, 0x0)
utimensat(0xffffffffffffffff, 0x0, &(0x7f0000000100)={{0x0, 0xfffffffffffffffe}}, 0x0)
kevent(r2, &(0x7f00000000c0), 0x138, 0x0, 0xffffffff, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000180)=[{{r1}, 0xffffffffffffffff, 0xdcd8c4bc089e638d}], 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={<r4=>0xffffffffffffffff})
kevent(r1, &(0x7f0000000140), 0xe4a, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000200)=[{{r4}, 0xfffffffffffffff9, 0x1}], 0x0, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000180)=[{{}, 0xffffffffffffffff, 0x21}], 0x1f, 0x0, 0x0, 0x0)
r5 = kqueue()
dup2(r5, 0xffffffffffffffff)
r6 = socket$inet6(0x18, 0x1, 0x0)
getsockopt(r6, 0x29, 0x40, 0x0, 0x0)
r7 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000000), 0x80, 0x0)
ioctl$BIOCSETWF(r7, 0x80104277, &(0x7f0000000180)={0x3, &(0x7f0000000100)=[{0x0, 0x0, 0x0, 0x7}, {0x0, 0xc2, 0xff, 0x5}, {0x5, 0x2, 0x6, 0x9}]})
getsockopt$SO_PEERCRED(r6, 0xffff, 0x1022, &(0x7f0000000100), 0xc)
getsockopt$SO_PEERCRED(r6, 0xffff, 0x1022, &(0x7f0000000140), 0xc)
getsockopt$SO_PEERCRED(r6, 0xffff, 0x1022, &(0x7f0000000180), 0xc)
geteuid()
r8 = semget$private(0x0, 0x2, 0x7d4)
semop(r8, 0xffffffffffffffff, 0x4)
semctl$SETVAL(r8, 0x2, 0x8, &(0x7f0000000340)=0x3)
semctl$GETVAL(r8, 0x0, 0x5, &(0x7f0000000600)=""/250)
semctl$GETNCNT(r8, 0x3, 0x3, &(0x7f0000000380)=""/64)
getgid()


setrlimit(0x8, &(0x7f0000000980)={0x9})
syz_open_pts()
close(0xffffffffffffffff)
syz_open_pts()
socket(0x0, 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
shmctl$IPC_SET(0x0, 0x1, 0xfffffffffffffffe)
setreuid(0xee00, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x802069c1, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
syz_emit_ethernet(0x126f, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc1206949, &(0x7f0000000100))


sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x2, 0x0, 0x28}, 0x4, 0x0, 0x0, 0x0, 0x0)
r0 = socket(0x2, 0x2, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f0000000180)=[{{r0}, 0xfffffffffffffffe, 0xc9, 0x1, 0x6665}], 0x0, 0x0, 0x0, 0x0)
r2 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
mprotect(&(0x7f0000ffb000/0x4000)=nil, 0x4000, 0x0)
connect$unix(r0, &(0x7f0000000140)=@file={0x1, './file0\x00'}, 0xa)
socket(0x18, 0x2, 0x0)
r3 = openat$vnd(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
r4 = kqueue()
kevent(r4, &(0x7f0000000200)=[{{r3}, 0xfffffffffffffff8}], 0x8001, &(0x7f00000001c0), 0x3f, 0x0)
syz_emit_ethernet(0xe, &(0x7f0000000100)=ANY=[@ANYRES8=r1, @ANYRES64, @ANYRES16, @ANYRES8=r3])
ioctl$PCIOCREAD(0xffffffffffffffff, 0xc0107002, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r5 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r5, 0x801169ac, &(0x7f00000001c0))
setsockopt(r2, 0xfffffffd, 0x3, 0x0, 0xff41)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(&(0x7f0000000080)='./file0\x00', 0x0, 0x0, 0x0)
ktrace(0x0, 0x4, 0x1028, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$WSKBDIO_GETMAP(0xffffffffffffffff, 0x80047476, 0x0)
r6 = socket$inet(0x2, 0x3, 0x0)
setsockopt$sock_int(r6, 0xffff, 0x1004, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000080)=[{0x87}, {0x81}, {0x6}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0xff}})
sysctl$hw(&(0x7f0000000000)={0x4, 0x18}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x1)
sysctl$vfs_nfs(&(0x7f0000000000), 0x7, &(0x7f00000025c0), 0x0, 0x0, 0xffffffffffffff2d)


r0 = socket$inet(0x1e, 0x3, 0x0)
select(0x40, &(0x7f0000000000), &(0x7f0000000040)={0x20000007fffffff}, 0x0, 0x0)
shutdown(r0, 0x2)
select(0x40, &(0x7f0000000180), &(0x7f00000001c0)={0xff}, 0x0, 0x0)


getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000080), 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, 0x0)
mknod(&(0x7f0000000500)='./file0\x00', 0x1000, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ioctl$FIONREAD(r2, 0x80206910, &(0x7f00000001c0))


r0 = socket(0x11, 0x3, 0x0)
setsockopt(r0, 0x11, 0x4, &(0x7f0000000340)="12000000", 0x4)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x6381)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)


mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x2000, 0x2d87)
syz_emit_ethernet(0x1019, 0x0)
r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000080)={0x0})
mknod(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
r1 = syz_open_pts()
close(r1)
syz_open_pts()
getrusage(0x1, &(0x7f0000000380))


open$dir(0x0, 0x0, 0x0)
r0 = openat$pf(0xffffffffffffff9c, &(0x7f0000000000), 0x10, 0x0)
ioctl$WSMOUSEIO_SETMODE(r0, 0x80045726, &(0x7f0000000040)={0x1})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x1ff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x1, 0x5, 0x0)
close(r1)
r2 = socket(0x18, 0x2, 0x0)
setsockopt(r2, 0x1000000000029, 0x9, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000000c0)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000300)=0xc)
setregid(r1, 0xffffffffffffffff)
open(&(0x7f0000000180)='./file0\x00', 0x80000000000206, 0x0)
ktrace(&(0x7f0000001d40)='./file0\x00', 0x0, 0x1720, 0x0)


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
munlock(&(0x7f0000ffd000/0x3000)=nil, 0x3000)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{0x5c}, {0xc}, {0x40e}]})
syz_emit_ethernet(0xe, &(0x7f0000000100)=ANY=[])


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
r0 = kqueue()
r1 = open$dir(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
kevent(r0, &(0x7f00000002c0)=[{{r1}, 0xfffffffffffffffc, 0x63}], 0x1f, 0x0, 0x0, 0x0)


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000140)={0x2, &(0x7f0000000100)=[{0x3d, 0x0, 0xff}, {}]})
ioctl$PCIOCREAD(0xffffffffffffffff, 0xc0107002, 0x0)
sysctl$hw(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
r0 = socket(0x11, 0x3, 0x0)
setsockopt(r0, 0x11, 0x1, 0x0, 0x0)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000500)={0x0, 0x0, &(0x7f00000002c0), 0x1d, 0x0, 0x0, 0x8}, 0x1)
r1 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
r2 = shmat(r1, &(0x7f0000001000/0x3000)=nil, 0x0)
r3 = shmget$private(0x0, 0x4000, 0x0, &(0x7f0000001000/0x4000)=nil)
shmctl$IPC_STAT(r3, 0x2, &(0x7f0000001540)=""/4092)
mknod(&(0x7f0000000300)='./file0\x00', 0x20, 0x0)
ioctl$TIOCOUTQ(0xffffffffffffffff, 0x40047473, &(0x7f0000000340))
setitimer(0x1, 0x0, &(0x7f0000000000))
syz_emit_ethernet(0x17a, &(0x7f0000000240)=ANY=[@ANYBLOB="872ed7c6847bfce51aeb626855850ece00c8eb2a567103bf607264063b57e49a55c36306ba2c5d8028f80f3bc34a0292743b295e", @ANYRESDEC=r2, @ANYRES64=r0])
r4 = socket(0x2, 0x2, 0x0)
socket$inet(0x2, 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f0000000200)=@abs={0x0, 0x0, 0x2}, 0x8)
r5 = socket(0x18, 0x2, 0x0)
setsockopt(r5, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
setsockopt(r5, 0x1000000000029, 0xb, 0x0, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x4, 0x0, 0x0)
syz_emit_ethernet(0x126f, &(0x7f00000000c0)=ANY=[@ANYBLOB="aaaaaaaaaaaa00000000000086dd609ded1a12390000c4a4e3434e58d025a6a8a81cf312b8befe8000000000000000000000000000aa00030000000000000101000101000401000401000103000000000100010200000000c7ab6f1eba08bf03d1805fce0ef2ab82f4a065245eccda108bec7cb23f632c993265a4cefeb77b1406d562a47d4b0054943553278b519ed107f62b5c352f8e68d83c1fd85b8e1083556d7fa2fc09a3e823fa940de6ef1b18ddb2a2dba0d2d9c1b44b20ed3a932a2c47f4f4d3e34ea1b67a607001a4541a87d5d347b5049b3444dc2b7abe3499079a5701e88493acb2eb1808e8b1f74311083f93341607915aa46325934e81b672d809cb6bc5f3d64480ba4db4432a67c2548e259fe7831f7c6dfe"])


mknod(&(0x7f0000000500)='./file0\x00', 0x1000, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
open$dir(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
select(0x40, &(0x7f0000000500)={0x3fc}, 0x0, 0x0, 0x0)
r1 = socket(0x18, 0x3, 0x0)
dup2(r1, r0)


sysctl$vfs_ffs(&(0x7f0000000000)={0x7, 0x4, 0x300}, 0x3, 0x0, 0x0, 0x0, 0x0)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
dup2(r1, r0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000a, &(0x7f0000000000)="ea00005c00000000", 0x1)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f00000003c0)="ea00000100000000", 0x8)


mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x205b9a)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
readv(r0, &(0x7f0000000740)=[{&(0x7f0000000140)=""/144, 0x90}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000040)=[{0x80}, {0x3d}, {0x16}]})
write(r0, &(0x7f0000000540)="76e5dead6f01f8607d2100000063", 0xe)


close(0xffffffffffffffff)
close(0xffffffffffffffff)
flock(0xffffffffffffffff, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000000c0)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
getsockopt$sock_int(r0, 0xffff, 0x100, 0x0, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x1, 0x0, 0x2}, 0x8)
socket(0x2, 0x2, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f0000000040), 0x10)
getsockname$unix(0xffffffffffffffff, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
getuid()
setitimer(0x0, &(0x7f0000000000), 0x0)
setitimer(0x0, 0x0, 0x0)
mlock(&(0x7f0000ffb000/0x1000)=nil, 0x1000)
r1 = open$dir(0x0, 0x100, 0x0)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x35}, 0x4, &(0x7f0000000080), 0x0, &(0x7f0000000100), 0x0)
open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000180)='./file1\x00', r1, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x200, 0x0)
setreuid(0xee00, 0x0)
r2 = getuid()
setreuid(0xee00, r2)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x0, 0xffffffffffffffff)
r3 = msgget$private(0x0, 0x0)
msgctl$IPC_STAT(r3, 0x2, 0x0)
acct(&(0x7f0000000080)='./file0\x00')
r4 = socket(0x11, 0x3, 0x0)
sendto$unix(r4, 0x0, 0x0, 0x0, 0x0, 0x0)
r5 = socket(0x1, 0x1, 0x1)
bind(r5, &(0x7f0000000000), 0x10)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000240)=[{0xb1}, {0x2}, {0x812e}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x2000, 0x2d87)
r0 = open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)={0x3, 0x7fffffff})
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x30, 0x0, 0x57d, 0x0)
close(r0)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "0100012d29fb000700000000098002005e00"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x59}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0x4, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0x63)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x3}, {0x61}, {0x36}]})
write(r0, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xe)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x53})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000080)={0x7ffffffe, 0x0, 0xe3d458f, 0xffffffe8, "1500d67d005b860000e30000008000"})
writev(r0, &(0x7f00000008c0)=[{&(0x7f00000018c0)="bdf83afa87530f0416987cf84f8f0f1c3a4501fc5bf8641b8c10e8575f86dc68d6bea9184e5157d6bda3d51aa9931e826eb413130536533a23f3b4765422e96a36c56c0ec1b65d52c9d24059a25ebe51f722cdb0fbd89106c87c50a74caf860c5de446193f1cd65d7b2b3111158517bfb9e51203b4efce60379fc505e691a2040bef91c58ff48d376af0d488a5e0492dc33df0a6597a2dd85ca396c4cae6db9fdd12bc1428e20e8adb3b2082eea2fb37441739806ee2fde7302c5e0b64c92aca75a7186d7630040ca6ee723360f9454345eba57f581b44316916dfa6ef0fe032da52b60db523aa44ac860cc050547644ffec11291845fad457c4899f015f6b784c878908f6fca14d4a63b7b46374c988e354f69305fdc73a2ae83e221aa5fcae9ee01451e6ac3e09bf22c52d6c93f39869225f7f028b06421570763c9785a61f5e507502300c6340f5200351bdbfa63880c228d11348bb2e306a07e319ab13b8c59ab28f29548492ca3fcc76f5df95f2c8a4703098270f42d36cabc74e318f840d733816de8561548a7da588508b30d9bcf9a7a68c5819c86ff9dd1ba1cb10f641a43bb4429dd798cd1b2e41a708c7bf8a362b46d1419a064a9a2b52009466306d787864fdc8c3f49efbd24cfe2fbca1ead31b6f84e3526bc247476466a72e184c0b4e8360690c288101bab88a1a3b5211a51ee5dafe5a5a64a31837c18f278d10644f896be251cacc29aa36e0bfdea56db220dccd96491c06eb6ef74b61fd1c8b363c9479a4fc6a58af20a14f6dc885134bc005b44b94355f382f13e244d44b836dd37078193c67adc8bc364360f246f744483a8be5345853b3600cc029566331babcaf24224cd2c7ac62577328c74dfdc6970e888e7011a2b3972cfcd1486cb071bdbe82f0fdcde5a887555b6db4fd3920863e4d31bf85473ef3faab39f5679f2807695deaabe39bb053807a5f1d08180e55378cd4a49f151dc27bf12d1525a3d1506a62a79f15317cac40d717542015807c2d54cc29fa946301b8dda134c7907b99ab64111abc5b96d0ec45afd4f2563cb1a8fe8e4169cc18c5859f66ba1865ceba46c8e9883596842607d9bcc66ca54ae4be6c68c982f72b350f000a89544d8620970cd1a2f00a781ecef190a5430730b694b0bed66580375510b02fa0a3d8c95876295f9041bb6cf880685888d3389596ebb672ed932b3668bd96afd83ecd814d3e362d327fbc0b68c3818ab23ab8274dc2adec5d77ba05cf7dfc6fd6652e12177dbac6972f3368e003bff069b18e10f1c04a8832123d5be51eda018c134daf22b74ab171b4a54b90b1b951727529c7fa1ab11819db4da2946c2b8d18e2a3cb9e7f8b10666fdfe294b75a871fddca1401e99272e97282dd44fa71679c61944d965ab2b620b37839ec51440e7af0c1372125037dd98ab638b271b756a5169791f0f445d5270f84fa5a6d8d6725444f90158b8862efd3d0c1d6269b40ed34e41eaee286305c677dc977333fbcac742769f5a47a5e3c653851dd857620a8f14e56b317fdbde658673befe02beb82b248f6af337484b9f4e4d4a3ba108fe69937881e02cd073dbabcd66d487c745446f0ee5d1bd48049396b2a03b3247fa73d70f4bcc767a957b526dba61eebc5f5eab1ef18ccc84ffbf768637cc247933cec1e618169da86f0e0dbf992297fcc48835895e9ae9c7f09c568055850da0fb4a330e6771f3cfeeae088b0fa0894f3db15a83ad9260dfb210922760e9189a2f3d04f87d383d98f3fcf1b09329f672665d5821b8be48b723b68f16c33978b39761919c8a07e0fae61743b09b82cd1d45fbe25edc97dc8ea743d2d47754b9aa28cc9159ffb7833277821507c01ae3ef06102b4604b03aeaf2bf0cb7e8155d473843cefc1145ab6951b98fb083e23354b12fe2e00feb1a53f26b2702cc08f46e504e780033c771dfcba4f780adb7d77d6fb8be31c468b6a978a34e5f1e56d5306c9a2cc118669ec777054b28af9f444c9c2af6d27886c853e0fd7ec7bec564e8b68cdb40a65422b5890b66461e4e41bd0677482b54d37dcc81a1b1643b728d8570b1605a5d420dbcefec5d0d1c9d9da8d496ccb7ea9250c9a76a5e5572df7786b590a28c0b794eca52b55720279ce81f35481e140471d0c0ca27c2b00270da1f439b285a5d2d695fd27e1b3821dece8feafa0e113e352962889ae17d075e4baeab60289c36c548e2f59541fc1fed0d2ba8057de17888dea1d99fafe94777315da51f54f4bbafeb9cf62a32ab7d0c5644f63457310e617d89020d2d0ad7af579db61a9901ff44487cd4fabacca994ef66c295378968fc4da0cd08a104f3177bd640ae0a992feccbbc6ff07fd5d25242aff7af00bc2b601c829dca9", 0x698}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x7}, {0x28}, {0x6}]})
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000400)=[{0x5c}, {0x40}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])
syz_emit_ethernet(0x62, &(0x7f00000006c0)=ANY=[])
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000240)=[{0x61}, {0x54}, {0x46}]})
getpid()
r3 = socket(0x2, 0x2, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r4, 0x80104267, &(0x7f0000000180)={0x2, &(0x7f0000000040)=[{0x28}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])
setsockopt$sock_int(r3, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r5 = open(&(0x7f0000000080)='./file0\x00', 0x1, 0xc8)
ioctl$WSDISPLAYIO_SMODE(r5, 0x8004574c, &(0x7f00000000c0)=0x2)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
syz_extract_tcp_res(&(0x7f00000001c0), 0x3, 0xf5)
connect$unix(r3, &(0x7f0000000000), 0x10)
write(r3, &(0x7f0000000240)="14bdfa5d1d34e2fecb284a6498307dcda9aec43050036123339a346f737850551408753f95b7688ad4c4e1dd5489e7bafc58d3e5823757ae8b630719ef187ccad9", 0x41)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{0x25}, {0x2c}, {0x46}]})
syz_emit_ethernet(0x36, &(0x7f0000000840)=ANY=[])


getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000000)={0x0, <r0=>0x0}, 0xc)
setreuid(0xee00, r0)
getuid()
sysctl$hw(&(0x7f0000000000)={0x6, 0x11}, 0x2, 0x0, 0x0, 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r1 = syz_open_pts()
r2 = syz_open_pts()
writev(r1, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)
ioctl$TIOCSETA(r2, 0x802c7414, &(0x7f00000000c0)={0x0, 0x0, 0x3f, 0xffffffbf, "0000c6186461c0940ad9fffd45ffffffffffffff"})
poll(&(0x7f0000000100)=[{r2, 0x40}], 0x1, 0x0)
shmget$private(0x0, 0x2000, 0x0, &(0x7f0000ffd000/0x2000)=nil)
setgid(0xffffffffffffffff)
setgroups(0x0, 0x0)
setuid(0xee01)
r3 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmctl$IPC_SET(r3, 0x1, &(0x7f0000000140)={{0x0, 0x0, 0x0, 0xffffffffffffffff, 0x140}, 0x100, 0x0, 0x0, 0x0, 0x0, 0x261})
shmctl$IPC_STAT(r3, 0x2, &(0x7f0000002040)=""/4083)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000040)=[{0x87}, {0x3d}, {0x16}]})
write(r0, &(0x7f0000000540)="76e5dead6f01f8607d2100000063", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000080)=[{0x28}, {0x5c}, {0x8106}]})
r1 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r1, 0x80085761, &(0x7f0000000100)={0x2, 0x5})
syz_emit_ethernet(0x138, &(0x7f0000000300)=ANY=[@ANYRES64=r0, @ANYRES64=r0, @ANYBLOB="9e3310953ffe8f519ebdea205dcffbde4432cb6004ea8bd9d70b65ae9ccaed907bdfe9d35c681c9ae2f6302fa85d2b150a2ae907d1da06c166b1cc3e0f281052", @ANYRES64=r0, @ANYRES8])
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000002680), 0x1, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r4=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000bc0)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
sendmmsg(r4, &(0x7f0000000080)={0x0}, 0x10, 0x0)
syz_emit_ethernet(0x0, 0x0)
r5 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x80, 0x0)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f00000002c0)={'tap', 0x0})
syz_emit_ethernet(0x36, &(0x7f0000000000)={@local, @empty, [], {@ipv4={0x800, {{0x8, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @multicast1, {[@rr={0x7, 0xb, 0x7, [@broadcast, @multicast2]}]}}, @udp={{0x1, 0x3, 0x8}}}}}})
syz_emit_ethernet(0x4a, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f0000000040), 0x0)
sysctl$hw(&(0x7f0000000000)={0x2, 0x8}, 0x2, 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x15}, 0x4, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r3, 0x80104277, &(0x7f00000016c0)={0x3, &(0x7f0000001700)=[{0x25}, {}, {0x6, 0x0, 0x0, 0xfffffffe}]})
write(r3, &(0x7f0000002540)="76e5bbda369af8607d2100000063", 0xe)
r6 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r6, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r6, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000180)=[{0x2d}, {0x1d}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
openat$wskbd(0xffffffffffffff9c, 0x0, 0x1, 0x0)


open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x0, 0x0)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000040)="94c79bd261e1e88e83beb11c0a3e154df77b5335bd1667d9fd77c59297b3cad0ade427f63f2912518a179b7c207bc5ba040a20b5c36bfaca54e49900550bad2f165552f266a6b12d4900c56a22e814223e67a3fdf5ae19bcbb5d0a815015db8752d03d1b08f84b4976ec52d4a82598424ed3a6a523a3591db0e862a2f4dd1168cb17845fff1fb5df5535cae3e20e2bdb92138d0c1b0720e1c121ccb763f092cd5dcaa3d901", 0x2cfea}], 0x10000000000001fc)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001a80)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{0x28}, {0x1c}, {0x6}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


socket(0x11, 0x3, 0x0)
write(0xffffffffffffffff, &(0x7f0000000080)="2300efe4855a00beaa9acc7808d0", 0xe)
sysctl$kern(&(0x7f0000000080)={0x1, 0x44}, 0x4000000000000004, 0x0, 0x0, 0x0, 0x0)
r0 = kqueue()
kevent(r0, &(0x7f0000000200)=[{{}, 0xfffffffffffffff9, 0xc7, 0x10, 0x200000000000000}], 0x200020, 0x0, 0x0, 0x0)
openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
bind(0xffffffffffffffff, &(0x7f00000002c0)=@un=@file={0x0, '\x00'}, 0x3)
connect$unix(0xffffffffffffffff, &(0x7f0000000000)=@file={0xd1653077bafa0115, './file0\x00'}, 0xa)
mkdir(&(0x7f0000000640)='./file0\x00', 0x0)
chmod(&(0x7f00000000c0)='./file0\x00', 0x31e)
semop(0x0, &(0x7f0000000080), 0x0)
semctl$GETPID(0x0, 0x3, 0x4, &(0x7f0000000680)=""/8)
semop(0x0, 0x0, 0x0)
semop(0x0, 0x0, 0x0)
socket(0x18, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r1 = openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x8981, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r1, 0x80105727, &(0x7f0000000000)={&(0x7f0000000040)=[{}, {0x5}], 0x2})
setsockopt(0xffffffffffffffff, 0x0, 0xa, &(0x7f0000000c40), 0x0)
fcntl$setstatus(0xffffffffffffffff, 0x4, 0x0)
getsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000000)={0x7, 0x12})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
r2 = getuid()
r3 = semget$private(0x0, 0x1, 0x300)
semctl$GETZCNT(r3, 0x4, 0x7, &(0x7f00000003c0)=""/96)
r4 = geteuid()
r5 = getgid()
semctl$IPC_SET(r3, 0x0, 0x1, &(0x7f0000000600)={{0xff, r4, 0x0, 0x0, r5, 0xb2}, 0x8, 0x96, 0x5})
semctl$GETVAL(r3, 0x0, 0x5, &(0x7f0000000440)=""/206)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r6=>0xffffffffffffffff})
getsockopt$sock_cred(r6, 0xffff, 0x1022, &(0x7f0000000100), &(0x7f0000000140)=0xc)
getsockopt$SO_PEERCRED(r6, 0xffff, 0x1022, &(0x7f0000000080), 0xc)
semctl$IPC_SET(r3, 0x0, 0x1, &(0x7f0000000280)={{0x3f, r4, 0x0, r4, r5, 0x0, 0x5}, 0x57e1, 0x9, 0x15})
getrlimit(0x3, &(0x7f0000000040))
chown(&(0x7f0000000140)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//file0\x00', r2, r5)
setreuid(r2, 0xffffffffffffffff)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000440)={0x20007ff, 0x1, 0xffffbffc, 0x7ff, "01000000080000009bb82f36b921aab39b58505f"})
writev(r0, &(0x7f0000001700)=[{&(0x7f0000000480)="b4bebc969a71689294962668adae5d4aef182d6ebdfb130366922cf92eab319ef4b876ca41a997607c852f53ad5365480a9a698d699080b86dd8e3d9895d59333b414764b8dd9d6331f5d3771c261ea9f51598df5b337da3e27e72abffd4886ad77ba4de6c83e12342d1f2df99ca12e24493259eafae9bfd9a49e2fec4ecaffad5dfceaf65d716a055910b81d2d81bfb53751e06fb04ee59da60dd6e9ce744f68ca6029e98386ac875d515e2f4a2c35e9acfd04c5711ca91a5aebe4b6c0cffad988cc8f5515e807d75b57e40970bc80c4bc176ae756779265b09da59f1dd6a94d49b50a4a7a87558d1856185271b36088a9220093dc38d380ef97f1cec74a87be4db3a124d1df9136ababe7f856e595668ddfaa5996841abe193b5ac9db6b548f03c170dd997e2d60c37e053a33f139855bb14af3a1e52d4ebfb4d8dce5c271febb51ec39f9331749f8d0b2828523db8c31a41818ba540a1cbbdd8989b9e8507c2ca057c9b535ac295be8be39709d20301e303ce073e439a6cba4f5843dbc7e88ef6abf81b436b46f3f4a675c6f9ed21420c9c8ad57740c3f7a604c66d08c613dff9d2bb59fdd70cd5df48c36263cc784b050cc80b0cea9724bd5d8b0052394b1bd63a996e0baffb02a1e6a6525fcce6002a60f7cf9999551c3df399f1875b1b1ad65931aa12bbd6ac5b19fe9e090a19848ed9693546d0d7a55b58b58d8e71fc237389a4c519af98c9c0f022c6e9cc57e627a4d0c4142b7d2037438644bde8ab77c16b0bf18273af9e90ab1616341e58532478208b0df067812dc36d6df0ae9bf38cfc323fe21c1835d597e300533a9a864f3166b779d056bb0d194da4df717433b3fe0a52225a2c98df0c8b6ef1767fb0dbf2f338d437f1258646f9e87420f039c377ae57c055c2b8b98ec9a8c6933eb2cfa0435897c99a9aa1470cbdd09357afac9d1c43424f249c81035efaa8490e7797d6701f8af2aa84f106676d57786457a639896bed8b5d422392e6f5d8cdde2987591cbcb0dca1da9b6cf88896f3f184b0d9fbf569e27c53e02aa394c66629cb80ae6fd100a3c6587f3335faf17e29207f93c7c20fa6ae4642429cab1934749abcabf46c3aefc57bbe63b48060b99da33e386f626ac2eac88d434233dc49b0a1c820eb896638f1f0369c742362f69506c98bf147e616cbc0720b2e01428bfe409a34718b11687d9d5df1ceec8be65ba3c412bf9fc6725072a782c1c989baac8781d1f71ebddc18ac1e4e66e2d6ce71254a44349f1968ec9dc33dfc42d9b138fd125a5a8563f835165cf9a261fd82a8edededf3174493162768fd6e2ca986b11a4f3fcf90e2d05b4dc5d34016bdc38b8f033d1611ea48cb42208f8b6f2f227de1f3fa934c01ab1640da2d65c2bcc05bd5d57f746027f7d095811033f176b735fe213aae73362dda2258a797ab5bd946229d3c076da80c78a6a0439698c66aca2e2c489ed3ada6ca6ca4cd43eee5654f4ad5551aff1c36f1676165b5134d47bac704360808fcbfdf27bc2734ca8ef76487fbf9cafe453de44d0a343b7d2e7b7a24df33c13718bdbc26182799bc733eae72c93ffa8b3ba9313e8e80b7b8b9e2cd824895d7d3cb439388b62ec67fb135316df28cc27a916c7ba95834649a002f22969d6bcf418f80e91a6130abecf074a5c4f945993ca17b2e0aae40f9f69b9809f71f54a56ce89a4e2441b6a24d9d1db965185991f1ea0f683b5a5142328d3d746782f675ea49dc6d52891978008f1f5b4158a25154a1c363d0cea3d52b55fa732b7519d80c29c29271dd8dcd0485cd67e19b3d7ef1c35ac95b25b6a240f56951def90e5c9260539169ac08b0ee112bc17067b6b38c5f0ae9edfe8ac21bbbc48fd7a4f112cadcbe118cd35aee4c063fcb6aa1ff2b71eb7813c0525fbbfb31b8c3e4356acbcba20b9564813f2f2cfc579bfab7a7f6d0dec603ff68b4d3b3f1e8d96b1ebdac347a0024f0a14201187256850bbab8f74196b50b21cbf962a2c961d7fa8dde1628b2835db146cc58c6919535ec228eb2b6585a405b259032ed77efb440f86bd1aaa41f198cfb7c2c85dcf63bcd0adef36bde390df6a6027f2c0749a53a3610774ece03bc8789c0331901ff62beabb6958e52367a308f855c51b1c71c6e9bb327b54dd6dabfca7104d2aefee8611968301ca03fe9fa6f4bb9778a37e7b6206bce61c11ea78f2f66cd5f0380f8541b101f46da2b96b1f93777df108f0cb46afb03b438754ac31b634d7edc17996557195139c2ac54929c064c64043c3deca54f73619ec59a6b67e90a16d477db61213dd873d71bb136a817d8f696c686c842567ba377a932a7ccaba3b9184132aec038bcc86b6b67855557554f5f2c1e8941c2c1f30175ddc74800c3f19a2de8d2f358dd5c6697d067e6814a86420bba151fe3c6ca7415815983be4da62c26617e7ff2f60c54d65da70db334e667a9788462e1b2bfaf72c1c3256c82306139b797c7f88b09bb4aad14bcee5b34482395ff297bf8250f3c50db603a714cc6568b16b335efc9307ce188ffc4679f6bb8f508b5bed419b7ef632bb112985795439d000fb25cb9712a5a01e071985a9d77e77a4b91fb6923487e1fcb713707ff6cd06556bc50a4789b461966f08fa37950430e7e30257afb541e31206a0ad2316b1dd92a244136bc6821c0210a2a007f2655d56f7dcf38c769855e3f5805ea215837ee7ef5e3daae619731328ec75f7ea719d79fd20398867cf83be044a45c8e2a97bf896c34ac6c14352f2703fbf4aa5d121e3dbf237f67fbfc51a615ae46ddde0571bd15b4a5917814e90d57713e8e0591803b2b27710d78c6ffe90ecba73dedb4333d59234874bb938cbc880f4b9239334576de213e8c18fbf3e114b5ecca7e10b88edc3251804f97756c9328e93c7b96848184e094e84a09dd042c494396a78500e6a92ab352c4e60a2e303ea0a13a7ed41187012bbd2db2e4c2148a995900369331e1204e9f9d780da427c3e9cf1bda6c197d719e7b525b118a6bc33ea162b15c77ae4dc6bae54f8e7cd9e1950919213e44f885035464f85026ef6a2e81787a71e58fc4aa645d1b7e95b73816792e0ca2e981aa1b50f824b294800da477170d70f0f00cc645da0e95422ca8a899cc173d0ffdced372077f9d19311ad06c86be335b1532fb9b1932a4697f0b450d64a648c838b92c4ec420e194b1108980", 0x8de}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000180)={0x3, &(0x7f0000000380)=[{}, {0x50}, {0x4000006, 0x0, 0x0, 0x10000}]})
writev(r0, &(0x7f0000000300)=[{&(0x7f0000000080)="a6750e35c39ac622bb5d5334d994", 0xe}], 0x1)


setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)="03000000", 0x4)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000000)="01000000", 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000003c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000001c0)=[{0x24}, {0x20}, {0x6}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "0100012d29fb000700000000098002005e00"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x4f}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0x4, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0x4)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
r1 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSKBDIO_BELL(r1, 0x20005701)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x1, &(0x7f0000000040)=[{}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$SPKRTONE(r0, 0x80085301, &(0x7f0000000080))


setgid(0xffffffffffffffff)
setgroups(0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000080)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
bind$unix(r0, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
setreuid(0x0, 0xee01)
r1 = socket$unix(0x1, 0x1, 0x0)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


sysctl$kern(&(0x7f0000000000)={0xa, 0xd}, 0x7, &(0x7f0000000080), 0x0, 0x0, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
setsockopt$inet_opts(r0, 0x0, 0x200000000000a, 0x0, 0x0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
pwritev(r0, &(0x7f0000000800)=[{&(0x7f00000000c0)='n.\x00', 0x3}], 0x1, 0x0)


setrlimit(0x8, 0x0)
msgctl$IPC_STAT(0x0, 0x2, &(0x7f0000000340)=""/104)
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, 0x0)
r1 = socket(0x2, 0x3, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r1, &(0x7f0000000000), 0x10)
connect$inet(r1, &(0x7f0000000040)={0x2, 0x1}, 0xc)


sysctl$net_inet_etherip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$vm(&(0x7f0000000000)={0x4, 0x2}, 0x2, 0x0, 0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x2, 0x0)
r1 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000600), 0x1, 0x0)
ioctl$WSKBDIO_SETBELL(r1, 0x80105703, &(0x7f0000000640))
ioctl$FIONREAD(r0, 0xc0206981, &(0x7f00000001c0))
r2 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$VMM_IOC_CREATE(r2, 0xc2585601, &(0x7f0000000100)={0x10, 0x5, [{&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ffc000/0x3000)=nil, 0x800}, {&(0x7f0000198000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000433000/0x3000)=nil}, {&(0x7f0000626000/0x2000)=nil, &(0x7f0000686000/0x1000)=nil}, {&(0x7f0000da9000/0x2000)=nil, &(0x7f00000dd000/0x3000)=nil}, {&(0x7f0000e0a000/0x2000)=nil, &(0x7f0000c17000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffe000/0x2000)=nil, 0xefff}, {&(0x7f00000da000/0x400000)=nil, &(0x7f00008bf000/0x1000)=nil}, {&(0x7f00008bf000/0x3000)=nil, &(0x7f0000af4000/0x13000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000601000/0x3000)=nil, &(0x7f0000b08000/0x1000)=nil}, {&(0x7f000064c000/0x2000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {&(0x7f0000633000/0x3000)=nil, &(0x7f0000518000/0x3000)=nil}], './file0\x00', 0xfffffffe})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x0, 0x0})
connect$unix(0xffffffffffffffff, 0x0, 0x0)
openat$null(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
rename(&(0x7f0000000080)='./file0\x00', &(0x7f00000000c0)='./file0\x00')
mkdir(&(0x7f0000000080)='./file0\x00', 0x100)


r0 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r0, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
setsockopt(r0, 0x0, 0x69, 0x0, 0x0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
writev(r0, &(0x7f0000001340)=[{&(0x7f0000000140)="be294b576eea0ab995d4e7e0ceeb3ecdafc4413d1492733049c1e795390f8f4027e2895d13e4d7d899f3d7dd889aef74b56ccee2ea5e47615c510f2f23c2f486c75e3f51580c2f7991b83f99b6be4edfabbabf64f8d8c967e560b7e5e2e5f110f4479d6fda2e3bd8a14407722d2ee0a0ff69daf1f760ebd1b7fa02fe91b46da21aa586f1e475dc4239abcf95b80a8c7780e41bc6505e1f3af24b23526f66156105cc11281073f7df36e33e7795866305983146325a9a5f5cd924a0463e00119d1be97cb9ed0da3c256016b57599c0b4eb986d9b5c94adf1c147b4f7c6eee626af824f812d932e6f7802b0d32e9c528526c6f1daca88e205d5cf8edfb054e95d2ce6717a479c69a8877547cd2620754f64cc2e4290f4b5776195c5cdbe93f55e1ab5b51507905398ec6564899b77e74826a53bc760a3e0193c9acb04b4873a4dc9af19aa85a4b31a624a31cf301c48048b90ed91eb94c952d9f313df7df7d7b63a3dd111c115488ddfd12f0efd67f809b61e196471d8f06dbad317bcc80758f1a56ddb3018d076fa0c69e8dd195d0a94793af5b7f4d6e10", 0x197}], 0x1)
execve(0x0, 0x0, 0x0)


setrlimit(0x3, &(0x7f0000000180)={0xb66c, 0x100000})
setrlimit(0x3, &(0x7f0000000000)={0x1791, 0x100000})
setrlimit(0x3, &(0x7f0000000040)={0x100000, 0x100000})


openat$vmm(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
setrlimit(0x0, &(0x7f0000000000)={0x1, 0x1})
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$WSKBDIO_SETENCODING(0xffffffffffffffff, 0x80045710, &(0x7f00000000c0)=0x2000208)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000240)={0x0, 0x2000000001})
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
r1 = socket$inet(0x2, 0x2, 0x0)
dup2(r0, r1)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000200)="ea00000000000000", 0x8)
socket(0x18, 0x1, 0x0)
open$dir(&(0x7f0000000580)='./file0\x00', 0x40000400001803c1, 0x0)
r2 = open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
poll(&(0x7f00000000c0)=[{r2, 0x6e}], 0x1, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000240)="ea02000000000000", 0x8)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x24, &(0x7f0000000000)="5ab7776a", 0x4)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000140), 0x782, 0x0)
setsockopt$inet6_MRT6_ADD_MFC(0xffffffffffffffff, 0x29, 0x68, &(0x7f00000000c0)={{0x18, 0xffffffffffffffff, 0x0, 0x3}}, 0x3c)
ioctl$SPKRTUNE(r0, 0x20005302, &(0x7f00000000c0)={0x0, 0x8d})


r0 = open(&(0x7f0000001180)='./file0\x00', 0x615, 0x0)
writev(r0, &(0x7f0000001480)=[{&(0x7f0000000100)="cc60d3d79a1a7122a5fb9de9ea6ca0b30fb2942ef7652736f10f86d45ae419b2ecf7af93d33b3de1f2c56c0d93da7484095d0d543baf7f0161a025c9c02a561f9a76d06f1eaec7d8df99d6c28b10fa891e47d6c3bba690a611889032ac7b3581d7c92d1c546e59764f069048316871794f0615dd4d8bb1057a61fb177be649004fb56a7d46c856a20d73f050bf29d58b803a676cc3761e8a47857f51d90a4465f9c605ab2829d78ea2571900", 0xac}, {&(0x7f0000000080)="b389e5ae", 0x4}, {&(0x7f0000000200)="5f6a8de84b4c523a583f91557c748a02cda4cedf13579996073843ec5cbabaadcec85d62a8a897a78307f3d2c30eea6356105ec8aaba86930f1aed0b3d111d", 0x3f}, {&(0x7f0000000240)="2a5f4cd9b73c31d629e8d68e605e5940744ef138960b671d42c56f79fcb70549247e5504e02f85a6099eff9291731e94399a7e966e783d4073ecd5dc8e540f32190bb47050aee3907495ecf7708d1c295a0836f79ba03ea13db12836c2441989726ffbf7fd1da55bfe2caaf081a1ef55599935c0e60cb0866ee48d420b77a6e269bc30b2650349e16792252c6be8bcc6e9ce2b941299ab505e4779fa1960bb7cf924dcbc53c82e76bcd80731a694d12e8a139d8ecef6f5560939054b7842d25cd7396377f39bcfe2a2383feea17b87393cd892b90742631718b1877d8d83d5f66587e3e5b1e129433ead750143a4c51aa46e78e3b1a54a4634eea2846511719b1637b19ea8c96a95332abd69014f53e91a7319a36efb4052387dc6330aa00b5680142650e8dab5eb6b83ff7d0bbf1293338a8d3e8a6dcd7ed4916279eac230dda46e6fcdebe8a4c12d598883d9392da05791e153d905ce1930aebfc5dfc0fc22a88777c9fbc24c0b021189c3503466bf850f59e6649dd0b40d935ba155a9d7e065df6d90a500be9d7e1e77607d495898a8d6c9c48dda88533e75e760dceae91d670f97ebbe68b845c72eb698a9e0389b15cfe768cd4e524dbe939bc2d8363ae3b71a454a0a0378cd1f36565ab9d1b92263688195df65151ee9b8158c7a5280019a38f00ea05142b3cc832ece46e326e36a55d7a30f866ca97da61a3877612f0d9f23c052edf60a430d3a9acbae3d9f14f22f38a1eeac7df37ae17748a960b9e0d265bf6cdec73bd2a7b5f25035d845d936936cbfe6f013f8d7c73eba2bd9876ff6db3224e50e75c051979f4cdc41d28ea54e28f560fb0291cd6b6ba527e0f358ffa46b988f0bdbf801063d2024380071709ac00ed463e08fd1718a857b567d8b3eda143915e943d9530d25ed15743e117be375dc08e241328a53fa05b58c7c72a35d471a72706afce82b6c57eef81444269e06338bfd0af6f6ef6479dcc26aab0b10c7e58572aa507a69831d63c78c947cecda2c57bb8ae6b2ad7862d160b423de941be69928467db10ee4817536196ad0c5cc02a74ba1a1fb467e472f025f200846112b6b3efd298284d8c0cc498fb9203db18e48e34c137d1285120d809a774d56a62b3dbe8f202cb9cf18c33099f5b9651fc7ae41de53842f327fd40bcfaa601a791da1103351a64cc9815ff1f32cde6fbfe4c92f55a9aff41c055d4edce9c656ecd1becb9035bb8bd46cf47bca0dcb1848da94d05d1475c83a48c02f8f808597eaa9e88a4e4b12d0ef95458eeab115cb189fa7e368186bb68610af4651e27feab061c4ada46e8c12d6d33fe32cd40485b02120418a9aaba8f04c17ea1abdcb9e6801f5d8090c0780b3b5ae4382efbb64f62c825527b7e3d60ad9c73ba7f174ea7c7f2d155808052a0ef6ab2af85cf9a758a8c1227c85f2986fc06c5f54807968b18b6b5f9168d0b2de2728689d75f0efaedf79bd8bbbbc1d46b0f6072d46d46687bc92c0b16c4ad36c3fe4c7a2fde0cfec859052dd78d841464a6b4432342ea973bf18f1f5abd7b2fe7962faef39ff38bd88a40dbab0f8c08541e38efe924f9ec1addbd47362e349bfca42fd62cf18fef8db7d3cbf0b1733d37dcdae5b9c738b8426a1cfa205c9671870210508c614f256d199fb822613518b1a6fccfee08c48f0feae1ca4baaf0a02635282d4f630a8df115dc73e72d9f7b8feb4333b2c796f1d3f2cfb398ba1e9c81584185b8b578bac3c64d667da7d91062f0c2ccec0c9d09e0c15c62e7bc509c3204d054c22d4eac685626e48e25cff2fc382279d9cb941c2ca182b1f65b05ff05db880a37b1e7f9b3d8975558858352bbbea9213a885b7d43451230e0624403baa77839baa33ae92de771ca76319c2353e9f98ea8191fbb686aed6d08e87bcc2bb8084ae02fafbac1a0bba93f0f155fa2d7bc21bf77f116429c6a1373c34d080518b73481fcf012c0a9127e8f174695ccd4add75b026bf2935990d5cebc4e74b97ae67a414029252336880232635fce7ed7bf0b069e08e10f7e1cc4d2973dcd2ea0b63f9dc4f4c2db92e03c553afcb1060b12f6b9b4d1d799edceefdfafdae63ad797e400645c149b20f8a10af54db3289441499e122413495c7b32179ab6c274bbdf6dde48ce26f46f07ede9a314c1a73669ee8cb0d854c8a3206dcd4f532d36fa7affca1226962e20ca2c6ca0da1ab0848d23d6f198681911592815c080cead9fe6c81cf0d7ce3578978dbf1dc2f1902e51f740f95b02ebff4cf25ac8d28b8e16998f5e329e9a377a82b5bc227f77c2f1ad505286aac8618799c2363a2d07d229519370be62ef0dde6525df45a7b807759b9ba1c8557bdbecb429432c4e1a84094edda567f1245ba887686342d0a31b7dbe09bd2be75516b255d2bfad9337649e86a29b0a19e16b4059c7c45e9f81db6780af6487a11f9088ea265a99d6e95535e14fe839945f8f7da9bf9142dd12c305bd41bb392cae8eb81b28fda176d4b538f4ddaaed47913cd9149d934ca36879718bbd76a2d7ce11e6294398ea433af6cf53b951974ec96a9527178b6cbad3088a2e2dc75113fa88ede462e68b4d6b63020a45e94fbc6c3e6677d6cffee0e3bf606cd2d4b9fac89f91db8f3a1fb9f506708314249fa5c36912e3cb281acbdec3b080735ae24ebb4bca3c7900c21175435afbe5024a706e90f8ecf257c99cd8b67b5a9c2bdc2bb624201f55882349526f8faf463eecb183635db72a6aef5fa2048d97e6f6c513598f49158050df1efc6b13b8ae396cd6a905c26b94d1d50d361f10c0362a8c206c7dd553dd8b116694aa82ac029c64aa71b8a307793da12f93ce030d3c42443c37b91043687befb7968da97ffe91d45e4fd506ba4d9c5d7fe5ac7433fb6bb3ce471f59ade734d109d2093fa119827b65a360f2128e7e85ab494609b60d6e236ed8a72984f6c75652f5baa07e2e921365af2b819eef58343e65ffb45ba8580d62f5b8a9988f7176c1559f8ede3b1b92e0ff27978fc5225ed1512b605f1fd4fce46e768970b11a7b4802c93eb05a8571887cdc15f69929eadcd1f9d08ed2d6aab2997ffa2102c2d8983a78ad43779d03aa612ecbbdde634b14e980b176f04f99efad82a04001f34d6addb89e0ce629856f5ad401fed1a2c046e1fe18741b24d4253830af94a1defeecdf6f70b430e48d7b2e4ae2fb331322d96e1a361e4dcae1d0865e7ccc4aa58bcbb3ad1ce0b294437887e03088a6bb4c92c3044bb33d2a893975023ad979fb2f84d4842326cf058595398779116245c452e54989df0591238af63c5b187d18457f008f2759ae470282ee4640e92639a46915fb67f22967beb1f46736aa9c90df08f39ee481f6859f9eafdecd473bdc24ef3ad71b4c54dde360f2d550db18af7589c8107f29b0a713b65f039da10c2dc55e408ce75c77aba97c116ab078ed1467464fe4041668228316f0fff7c0e0f1a3cc47aae570182197cc3a030a4af7fe2d401b5a13d59b8fe55d48b0667b782cbf1c2e9e491167d87830bb25008aff93c4459a3ce9fd8655a542c6311d91ec6b6bd7935aba1cd01d10439f5e5a3883566c8538edb97c5d2a7c7533d415973729f52dc03134f3d777b7ad07c0f5b0d985ca48fde6cce9ec99f1223f476dcfbb5ef865a3f54459415b25e2031eeb469c83ac68fd77e59c6b6a4b9543a943c4461e47e94d038c63abf2734a3c0e99b95505e13af6cf7b66840dc60e96fb218436ea00b4a577c2effdba43e6adf97cb47c0ce606e87a7834dec04396c1e4f7df59ae5acedfd1d68c87e405fc5d788884686270cb08f0fb15fe8b11589792f9afc11152cd45f43fac6e758588cfaa88874267c3096bd689108bbb0296f3d182df7d46cf7e6b8bb923ba887443c3d2211785e364c1e55d4e9396d950e50cc11ba9a4da70a64f6acbbcd421183eb2c0521054c4f39650409e21a9d3b781725b0c38abce7b4615fa64a9cbf71a19f7e414279a7494d2e66e4e2b2d5ce7027109cfc763a9dcac37065ae80ec0cf3962deec0f9eba3bd7c514a9854ddec6542cf60a1e69cf5d1a73239633675d4ac1f3b0758e69d1d9fb8659f43f07ef6b0b2a7c9740649198b44f3272a8810d374b00c1d49b7f667ed538d89e91e5734f8d6e270aef0a406fcb4072497dd5f25b49d31cfd64f7af2d5b4df72b74c39a66f442ae61aebe1cdb96b660e3248dad3d05bfce3d8630902a565c3a7636220e0435679ce1c45367570dd08722ddfe7f1bf56c44bcab8ef2d0979eeaa569dade4ec34751833d455b31b55edcb9b64f3045725fcd3a08ce0c20b09a437133df5738092eba91430208814b4135b0a64331aff1847ca60426c91e96a029cff039b14462da6e5f9c545980b3712f7fa5f3958d92278194cf6b37ef76e91103d14db403956a7070d87afa81df227f2189926e1265a2872e9d64c64496083caff36dd3c27e961957acb86f0f9a3cbb5ddbb6bf9c62dc102d70d62eea969b1c2c5f42823f76827e918ffa77cc12ca8d31effd0b55529c496da762b6a95d43360ea4e811979ee316e143733f886a6eca5ac76746d4a302ec57b6b4af57c25631d7773243abd400d15274703154dfde2f1a63e075e4b22ed4516dd1496e3f7848bbf19e3215edda64140649d9b1a06975773d5dd0ca9c4bdfd5eb9fb6164aa659e2a8415098dd05496d0b2a20d966a4c9efefa964e007a3b731d3bad501fd21ca564c6155d893c3075c234af6378a12595d8a88ae0518350b75d57fb91b7610bfc3168f548a9a63432b49a9dbee2ee1a4ddd80255e2c655cc80d59d7e90e21fb090db6d59ef84c0becfda6bd01c5a806ce67bea77fdba62ba40e2114d31e6087ad67b28adc20d7cabe7911aa2db119cf5f43b2011bb92556e8e303a264f813764027fbec36f8248a667c766cfc12c80d96965f222d39b5f58a54b255d3b1eb4530952b6d251ff1f9a2cbc585d539704c8ea6884699ebc95d57cd1daef169da86cc10fe7300352e939c35bbe3104aea1b1c681f3e98be8fad7c91bb56724ffa794ea4ac7c4d51d4aad8e94087b4cdcab897e70558e6648ab42dfadab447735912af011fdbd9a47a4958b953b01d2e274449854cb7d4b44d88fb2db162b8dd664c7c32858c7714c69b838cb30b17e6a42ca760256c4c6da57ad5be955ca8c787262d8bd3f4a5f0170e70f92ee2ec9d227d066e41d0d4b640166b2f6937a66bc84506d102d3edac818b246954ba200a3057820da10b64ff99f016b42d90a29b43290d731ef23a72612d646f92acc05620068fd94edd12902197733cc9dbb55d95930ccc749c4a169b4b7056dba24f767da022eb01243353e1f4d0af2eb32e3feb331283ceab3e0112b37556749a701d11ada5cbe1b4c829fac46e12612679e47d4a066be939b886f0fdc2b4c5b4dd183ca025c5191ac67d7f992643333504da30e8300a0b40152671", 0xf12}], 0x4)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x11, r0, 0x0)
r1 = geteuid()
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040))
fchown(r0, r1, 0x0)
sysctl$net_inet_etherip(&(0x7f0000000000)={0x4, 0x2, 0x61, 0x3}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0x0)
mkdir(0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, 0x0)
r2 = socket$inet(0x2, 0x2, 0x0)
r3 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
dup2(r3, r2)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00004100000000", 0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt$inet_opts(r2, 0x0, 0xd, &(0x7f0000000240)="ea000001000000", 0x7)
r4 = socket(0x18, 0x2, 0x0)
close(r4)
r5 = socket(0x18, 0x2, 0x0)
close(r5)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0x0, 0x0, 0x0, 0x40}], 0x0, 0x0, 0x0, 0x0)
r6 = socket(0x800000018, 0x2, 0x0)
setsockopt$sock_int(r6, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r6, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ff7000/0x3000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil, 0x40}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000604000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f00004f6000/0x3000)=nil, 0x10000}, {&(0x7f0000ff7000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000529000/0x4000)=nil, &(0x7f0000563000/0x3000)=nil}, {&(0x7f0000691000/0x2000)=nil, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil, 0x1000}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil}], './file0\x00'})
connect$unix(r5, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x1, &(0x7f0000000000)=[{0x84}]})


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
bind$unix(r0, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
connect$unix(r0, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
connect$unix(r0, &(0x7f00000000c0)=@file={0x0, './file0\x00'}, 0xa)


r0 = socket(0x18, 0x3, 0x0)
getsockopt$inet_opts(r0, 0x29, 0xe, 0x0, 0x0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
writev(r0, &(0x7f0000000100)=[{&(0x7f0000000240)='O8', 0x2}, {&(0x7f0000000040)="350e", 0x2}], 0x2)


sysctl$hw(&(0x7f0000000000)={0x6, 0x2}, 0x2, &(0x7f0000000040)="293a28f013d6f50cdf71f16d94cf0912b7cd47ba10f79fc38edbff93d64c705006558aaa80cd07d4ba279047c9720831ef59e730ee3d5d59d47213a77b0c47d664e24674524c6e368d7903", &(0x7f00000000c0)=0x4b, &(0x7f0000000100)="5fdf1f2bbf05b850f3fb374253753126c647c279073f0cdf4973a604b55474cc11287d297eb17321db87758655293c54dab8499188139aaa6f574ab1bb170093658003d73511f46d22d019a72ef96ed878591a0dcf728f", 0x57)
msgget$private(0x0, 0x620)
r0 = getuid()
r1 = getegid()
setregid(0x0, r1)
msgget$private(0x0, 0x81)
seteuid(r0)
r2 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000480), 0x40, 0x0)
r3 = accept(r2, &(0x7f00000004c0)=@in6, &(0x7f0000000500)=0xc)
fchownat(r2, &(0x7f0000000540)='./file0/file0\x00', r0, r1, 0x0)
bind(r2, &(0x7f0000000580)=@un=@abs={0x0, 0x0, 0x1}, 0x8)
pipe2(&(0x7f00000005c0)={0xffffffffffffffff, <r4=>0xffffffffffffffff}, 0x4)
sysctl$net_inet_ip(&(0x7f0000000600)={0x4, 0x2, 0x0, 0x23}, 0x4, &(0x7f0000000640)="08cf8930bd163ee3ac1aa462711b108cb02057d60ba963e73ccaeb72180afff6da6c49220f1e3dd14dacef57326f5d71445c89ce125a54420de90ec20db98db2cf422432a210b0e2e802959ce20e23f80a821ab7206dcdf16aa016d3c145d5c585e0c7c26997a9cebb1ffd", &(0x7f00000006c0)=0x6b, &(0x7f0000000700)="66a43b4b18233cf4000dd5c5283b092f7ccd763db957fc53fd943a4526886136d8af9887341c26c03fce628aa9b75880f7efce7b885bf3d4c775c8b18f8a48d27fdcced0fb5a2f86e318dbe64ef8556dc88fdded92cbc1d0f6a566a5e91be66134e0d4921c5ab49d9155bb7034b3be0e3b7dab54279193540f96ca09a787ff65dea96ff7502ee157eb52d1c86dc8cc0e79ad72aaaab7929d52efafea642ac695f4862875116d9850c4022e2dfc66a15c95d3fd06e6e0d79f2e3466cf14", 0xbd)
ioctl$TIOCCDTR(r2, 0x20007478)
getuid()
getppid()
getsockopt$SO_PEERCRED(r3, 0xffff, 0x1022, &(0x7f00000007c0)={<r5=>0x0}, 0xc)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000800)={{0x8, r0}, 0x0, 0x0, 0x0, r5, 0x9, 0xff83, 0x0, 0xbd7})
close(r2)
socket(0x10, 0x2, 0x8)
ioctl$BIOCSDIRFILT(r4, 0x8004427d, &(0x7f0000000880)=0x5)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000008c0)={{0xe3, r0, 0x0, r0, 0x0, 0x190, 0x800}, 0x6, 0xffffffffffffff8b, 0x100000001})


setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0x0, r0)
r1 = socket(0x800000018, 0x2, 0x0)
setreuid(0xee00, 0x0)
r2 = socket(0x18, 0x2, 0x0)
close(r2)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0xfffffffffffffffe}], 0x0, 0x0, 0x0, 0x0)
r3 = socket(0x800000018, 0x2, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x104}})
r4 = socket(0x18, 0x1, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r4, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
setsockopt$sock_int(r3, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r3, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


r0 = socket(0x10, 0x5, 0x0)
r1 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1, &(0x7f0000000040)=0x200, 0x4)
connect$unix(r1, &(0x7f0000000000)=@file={0x0, '\x00'}, 0x3)
getsockopt(r0, 0x29, 0x32, 0x0, 0x0)
r2 = socket$inet6(0x18, 0x2, 0x7)
setsockopt$sock_int(r2, 0xffff, 0x1007, &(0x7f0000000100)=0x2, 0x4)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r3, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000001080)=[{0x281}, {0xc, 0x10}, {0x6, 0x0, 0x0, 0xfffffff8}]})
socket$inet(0x2, 0x5, 0x0)
socketpair$unix(0x1, 0x3, 0x0, &(0x7f00000000c0)={0xffffffffffffffff, <r4=>0xffffffffffffffff})
getsockopt$sock_cred(r4, 0xffff, 0x1022, &(0x7f0000001f80), &(0x7f0000000100)=0xc)
sysctl$net_inet_gre(&(0x7f0000000000)={0x7, 0x4}, 0x4, 0x0, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001880)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000001fc0)="7ba1391c19f08681feda78c83df00c8eb7621977e9e61f6952249ca8364a73442c71d388dbfd11d5f95983a548c5893b5fa7a7c6b099449f0b1c7d94c3be724b7b90ced6d8614e150d07e4d59784b36032eb0e053fa0329e3c8c5ac54fc7645499b4bd9c51efd8ab964c5e50870ea41c680f4ebce0b92426b3ad98b9dc35c922e93fc31181d5700b430bd2453d9e4a9d671141587757ab0fe3c110da3cecdde1987c54a88b06ccc9c7a10a31b1d68ef1e620bc49e124fdeb9f4cc42dc74c99a1e55f7c957e4efd23dcebe9c5f66c3608554bf3ec9711f76c33dad1aebe6252cde23793d3901d51ba7dd7754b5dfbe5d9a110f54c2ecb8693ac2e603f69a177e26dc879d0855d1be985c8d729b07091f56209f5118b825020d3753031a62b5f30d43286405b6e484f9db078a0ef3cc7700b6f5e73ace82ea399505045df06bea049be6d689028b6ff4f950bdede3a2f0027b950febf4d8e9ca38bbed51bffc0c2c00650607d7a658773c64fa85864ed0ac5f51c19e3dfa76d6b26c34360e4ab5be1e297ad3acbe629a0d3c8f3719c7601c56c283d9d3b80dadfcbfcd2b6759da56be8737c6b4e48f7c4ff5394fef445548aeda69035bdfa67fbaad7f1b8dd69ee8debe75048989e1a64e671ba57ab668827b71db165c028d6d641d94c146be89954bc4d50932dec5ce1199bcef1025825c0693096d753162121c7e6869510a4e2aad15eaaf7efaec689e6acc19a48b5c000d6ba93f7fce0607c3b21fbc1cdeb0147e127e5027fc26dca1056c82013a489981fdbc6ce1823a003ddfea9541488720bac0236da9d963b87e7c0b73fa799bfbe18b282e0b628d17d16f560ad0248aba161d669ef46cf8c771c54fbc5278e7824d97e3a469ce3b7ab106e85f3cca91a7c987df717f4b4a0c7efcb0b09ea1f0a0288a847477f6af2451e678bb2e3e7f1919443019fec508de2c3a093576ad5d09179edb21d9dec85841fc5a35b6349df084889f87f0d6891b359fa5f005df9d1fddba7c70a6cbf51c7fc9f4df021cd4fc8eac99f87d6cc6ce1a98716ea5f094fab9514c4a83e3cd01df2f3d8bacfe4f0a21512bc9da31cdec22bf9985c23018b03661a40cef4db4d134d13740d34e99b1f7d6c39e2f41fbd4c66011768f8d6414c3bcdbff6f9ebf5479cbe152b72e086c12bf36be320d2a07879285ca53aee298200f830026130436ae8262958b68a078838e938dffb9fad9a553fa6d13ef8aab4977261eb4067a202a74efa27255862abab19d9a98fec816823b05ec2ba3cb489db0c2ae046984ef11734ab12c78a69c970f1396ffe7eba8751fc45c6e2e30faae293034e2d89f419a198bc93172c96d6e1d96a2d8324604cd3c81d08496e0ed425616cd8277ad4b7769d5b44abb8dab39589e292f0965f2590f011ea662293bcf12866db08b1ab37dd7b3e8c880474371e128013f03601d07186f2cd00236fdd49a54879970a17899a1db175c5128f76eab762d96c0e3f3385086a2073bc11533d2fd1f90bcaf5ff25b2168350912bfd9a8c60ece355cd0ee36aaf178397a1f0f1c2cabefa41f4685effbd6c491c98fae1aaef20b028b92917a9c1710e778add43cbe034c05c1ce9bb510173bd40408cdb7c75e1adad31b259706e0ecbaef0828671e8f1cc2fef5e66cd05724a2d48618b12e6c776812035b1ce7353ab8749827cf2d1ef98cffcd07db1a9480f8d8570804b82491eb900116e9c5ee421905170541c2007103ad070bb59bbeab163eba6521c78618cc841c38382a64563b6bb635cddd061fde2dc7d8d1ca2f4d257b427fff2c7532c96936ed871d2a8625896ed24d1301dff76ba219515e25616df2cb767412555e229bd7184fa1d0e6f96106b1db1c1cf98bed53cd3d3f98cedc385fb1cddb6a8c577ac9f873b9d758c9f3cc0125f349f28b473bf02bb247ffc743ab602ad5f6ddbd9042061f65be06ed41fff152178e3fbfd3b073c8cb6f55ba997074a7cadd5537ea882ebd3b9f94afe8d7b599a736ecca3f5ce706e9be0ee526f1c75f25508c46da76986c2733f6174b0485abc1448f8baec085cdb272addb310816bb4d2cd8f466a510f2383e841ba411ce3e237c2b1c1bca85f69c4833c833bfd892dc5aff392a2f320191c752666edc6b37cfdbef9dbb958f82f956ed0cd7f2b54954ccfe0b76a2d7ad2e284d7e10296ba0241f4dc20b034079404ead5f82e78c78ffeb3425fc28ee9b31d2cc424b45219d31a4cd0b6e1340fdf3ec9c74a4aa5f50044b266f8e4662ce4bd5fae807f762483b8bf5971af8a1ac5c8257a00d75bd3927225d52a84e446f48824a36b51835c4b27f778f3629e3d136c21f3fe4a0ab777fbe5f23b31c110a7ac29b26cfdd5371c76b89f497dcd3502570a8b75fb2807b98756c499b1d83820861f78904261df40b15049b8d50668442fbc5bfa6f91f34adcc470b2e303b11d4d35a26891544c4be89329ac3026a21197402981461d9958c3e570e3731618cd7790322d05c26f711f91dfe3f009c1268c67a36fc879d89a44744019106b276b8341f6194ffb1d2585e59edc87e7df231bf1125c5283e23d4c5faedd311ed16578257a27688394e8960fee13cf7de8a49dcf90afcb066f9234a615127a65b7b625a17f82ada782c662429442767182cfd88fb763a87e68ebd6e455eddf87fbed6d2a7e11eefc2c04b0729b8f4b19fa294a9e04d023b8c581a009203564e7985b22dbb8036968bc784793a4c8770594093399ec376819b2edc43c304ce80409d377e3a9c7360d883c58b00a3859b4945ca08293b347450f3eae8d2a4ed937fdc4249d917bf984b36b2ed8c2abba1f906713a8df396fdbd0fa203b11d12f1bfa5c0ae13eb6fd9fb80cc7908865b1e484b4ae66e2a2497bb5c57ae4fe874c77cc3465eddb53b72235ece23c2e2d226c464e9660f4069bbbafeff2152b092d970a620c5cab5479366519fffe206b85918796e9b4a9b624f2b059988aa19107f097041ac4367d767e826c502e81cf6b72944c24f56ffead013ccf9542f9fe70f0446454b071b9f96381a9e0b3050522e71b00d84323ac89b68b2ab8f3d15e1d34cc17550fc3b8223c8cdfce71c0026a74c6d625ea2503a85e69002aad8b882ea3e95169e21a6cae8d9c6aac1eade0d603cad2f9f2e48122099ffa612dda8f1d9fa81c8143eee536a390363626808ded164b69e5189bdc85b0fcae512013f46ccac63c91c515dc0ea7f747b3c0848f9f651d5166965639df04583f628b2a3a3ee9050bd327f6250328bc6715c39cd48eb5bbfbf1c1e74be5aa6d12b152ee1131d38a938438c8865be70698831bc15b30d0a8a2a235def171128e29ff6fe194819d5eff261ce1af789364d0eb776d919ac816236bbd33fef64e18c6e09148923a93de178e1a0fbefaca26c2b4341e81e54f145f56660dc43ddba0ce088e903724f34d9325536a8c2f1d9f223aa606a1dc06d96ae7e5bf8ebe91cec186e4843b67212aeb78a46cd2aa2b25cb42bff002f9b073c2e02045c3eb1678734f020b8d67d2f037fc7703d37d4f0e4f6dfdbd26a817c8f3bb8514129efc25313f575ce57485726e459e1b054541294342f5e88af901d4fad67efd7ef6c194bb83e40c6d94a8389535105d8c476740b0f06dc383efd246a68e67da3d6b12676af44012760b8c79df99823ce1cf99169bea73fea931c13b9d3c637138612be227d494ecf0772a2cb383e1ecdb90291e56ba88d5937906510d6509be2b2b2e59deb4eaffba0866fc7b114711eb212c3bfb030ebe6aff81e174788321aa79aaba19d7e03d4c19f0b220bc02ba86faa2f5a0cc29fa15c8ac8a3648ce098e7ee07737acdb370d91730af32e1d63350d41fd1fef08b3efaefc6e4fe1e7a319d4e7faba0e3cbe60f23d15c77351da3f266cc0592654072d7483d2c97a20248c8a0979c6423e5bdb5b752e1e037e3d364e2adbf4a30059c6593a5c98586ba1c364ae4253f1ce7e172ee3523ddcf0eaab0b932b41da31c4e3705e7a328719918096e662a2decafce02397eec7e97d4c11e1fb499e9074cdff8d56f55ff8355fc291cb4868bcfd676b73f8fdcd63514080df587396e859248c55957b924ada1bcbe0e96981e1e4c3137c7e1125355b2fc254e7956ea251be8d6fc361ee3df892f6968e3eec4df220ef3e891566ad40097c9280433d34983c6d1cc29255569af42b9989ccf40faebd7bb227abb0532a7e8222e3b062af1a6dd1d5a89776b1611c5a842608deb1389aed838c13fd69f0a69ee4fba9afee2cbda3af079d6c2d8016171bc73ac9e8b68c2c21c117f71ce5ac54aa292cb36c49df38e134df1503c20dfcc71dec61d8273bc1e88426d53cc43e4bef897a8513e2d078c7a1a5335e22b4d5c284067b43e5be2bb5609677a98aed0fd0a436cf9f9cf1a5f7ec8baa4cfd8fea0d072d88f5ec594185ffc43bfd133aa404bb0f8a5ea488616c48f3d44b61d036417414f77af5c6b8348e2ab1a3a8676233219959efa568b2e5c324a08c10999ad5bb518aaeb4c7c919e8a3fb7079da6290ad2a29604b9b52b1792751ca1e796aa875a817d22189b3984976163643768555b7df867ce4413681043510ba1155a9b07bc1654caed57638d224a8bdc34d3d86bf210bec70a29a6f64018c808b9b20489e1480902c79d69461285a6ee80710ba106807f2e2cb55d8abf85fc626732b352160d88fa45671acec280e3367f81a3dc53ddc6a8b17e9bd57d307bde0de1232e94388c1d142c3b5dc6919853961db4283dd2dd04b1233ae872a1197ce177718496b790dfb774c1b260a8f288a34de15e9fbd0894fb3b37ce1971ca69ed79f52470e0159dcbcb744be85d0c5360ddbc96db5ee283fd83617afc0b2ca3428fe4895c37824ec868b49d48a0e1dd9217b961e59e1ff7cb354200f479c30cf3c6c2dd815e627c8b70f4aae478aa30a9f59c31c0b9070f6addf4814dcc0f0510f566ebf39c16b3ff8beb5932a6a6ce9d3a99046ea64b60a3c443a9ac061a150b9e3ccc5ac6ffe0d60e12384cbaecd89082da18bdc4919cc9a969927b67ef56214a099870478b5af5d7e7c845c4b8944a8960ee5840ff3fc752c194362da704fc17c4046a3ef1405799a76d0543df8647fc20ddb9932b57f75f2ca5348969a9b517da37d4cc5e35c7734f4c57f46f64422c2a044fdd7c2ed335980fb3c0e523586fcfc024bd4f7c4109b37a2b7d4e1e4eac628cdcc22e329548359e9f2e4f2790ccf5fcfe8f9d4e76b8d97ad276a3db844f8a27f64621415927e78d57ed70cacc32f83c3a74fce59bd3854e54b45af6b7440273d63738bb02923573d8292eb7340e1cdd813868536afe26d73c57f6858b3427808192866d3f1dd81da33b67a0684a865e1d199187dd4562dde9531db7bb24a90f6ef0dba995f115b4bd595cd46f3b1a249a3ae6aa28032df0f3dedc26be86958780e815df7e6df83b294165cdfee5911d04bd1bec972aefe3dec209dbd8c483c6252905fb79fe8ff775dd4c89384c861215c295e2e560954f2adb77ea2ab0c8d0b843fa7afb150dfec25466c6a6f57e3001d8d7b195fe045a9096f754a50c4c139deb55f0eadcdf30aaa74b5bff61cb06c558ef325ec0a60c203771d54544e533cfdb844e71a1915c1bfbf38542f5d420ef8725e8c61ada58364a762408bd9187e93309e810c391aec02f1e3860ac788363ebc5047676de2dc0d47c9f84f094e83c73cc55d6cc6922e2590b49156fcd73b813e14ec5f3bb10ce8518f9c821ac7bfc3d015ccd2f566757ac50117e7e023", 0x1000}, {&(0x7f0000002fc0)="d672a8aac0a2d5799f6d9fb7cdaed913a51882c947bbcf2e3ed1c25629923979c055b59b72ad1c010030887ea0fc3401dcfb0eac48bf9f8d7157a1590de9d1509ebf98c36cca262a5ed1c126533e6a75f6f9c4ef310b71a31a9242459392833aef042e2ed43b37af8b15007e3d68101189f1457923a7837abe37c7910a6529f2bad9a9239e4747a2d9348204f8499f0b0e6817b75ea9599d136ed1f7cba001e115bc1b0edf9407b5035b16cfa240e5bb6092e5e2a8e192b6dde93c87db63528bf4ae1d44dbd2c0e3d6ce4c3394545821e6a5cbc057d4c100c1d5c8aed9377c9b2330eb0374b9986248f889f97b3c9e9554a66bd81130e4f5fd53cb05dd6e0e9229d20426dab1bb293075580e1d861968c6ff95ffe84334c1ede04e6d8fe1345f4a54fbef3c0c3a3786f2133a5e43baa04db2323775a664970884d9ee6071954d7fb1513b8bddf17a0923a13150fdf68ce9fdd0f30e425ff4705282636ff7ecd517762ca4fe6ff8330e02fc9bbea213e031d5e4b2e06952948e796f124e883acfdafca043b610c820384b7f03f35cf588a95ac1a89bfb1c10365dfce3255473fe3a64726ba90c60d73fbf7b5e0250dfa990c70cfbfb05da741f73b3fad0bfcd61d4bf722b8bb25008012dadfec1ba19b29aa27b104f864776a3cdebfd9fe9e24b46d3b02b825a4cde5515231bebd7f0c0833e4a01c53479d1b77755cc0774aefc22b554105b76d74735882de384719fad13360c1f12dca39eb03a3de0445b436ab02d6d77dcf68afeba3cea9df0571df9bdb61b8d1e629defc8dceeeb75df81cf8dacede4435df7f4338a9ea0ad2442ab1951a6b7b105a2f291f004c4d72d13ccfe91a89095e4bcff6210095011490a92ee9a3f7360ce9d3704d159262df81bd335e670565ffd6b52c417f80f0e838a16cae8a9e803559d3977d9a48dedc4ac9347421d2e72c2257ae2f784502290ca69f7fe54a3771aaf7b6a82040ef1868bceadbff5e13733b4658920f2f063e1d157531a3896d30f2d0f3fc9beb763eaacd38b43c61a57962920aa25d1e3463ff5f1b35e8a0fd4dcf8604d260defbbecb8057c9e4d2a96cde97d2ccd47f70ded300f8e0898fdf1ee2cb43072100947d6fc945b317ae8f1d3c07a6dfc6dd1359c7c2a107beec54c9df64cd383ebc3d46cf3412aa9ba9047b6c4e5e752d56a271475d576f884fe152852f448fe8f7b0fbcb66b7e1e7880696c2ed368eaff214bf195dacc939190d3caa5a9dfb07d993146a954e7e98a7b809a052429170cb869e8986985681de6fcc49473d69e055881a4d009c71b2434c5f4d0a65d180af58ae350969118352b71d2b796cd645bf3470e66e2df23a353126f4dbe7e671ec3b10466bca49171d64a89c742dff83241799db0ac54f35eefa69b2f655bbeccb2145872562d4deb611574a75f7ea709f738b93d2f5626ca341b35b3381fc88510409b9649cd899a482f714109f0dfc818b7db4f04ce003324b042f62ee2dd70d1c360899636d741c96e3849634758fa0dbb18e8c3fec0a67120997c4c62f79fd69ac42d767f75aa7fc4c1887b5d3d1fddded610988bcb09e074ec6f887d76e213ecae69caa18a3d8a5d0d0bde0da6ca437c8e5c46083a0b6d875ec860e6c94d6df14e40660b0277a8dd1d8ace0117028298ebb72615734c6144f4b8c8fd743eb27dc34fe95b6dd3d63968e7619761dde2229eb04e283aa9cb0f2ed119a7d6b46d3d52a1547c1e960321b0a6528fd78d4cbbcdd79ba315e8d1d3b5db8c59d70840c404b37b95fedc614544d5a63e004bba76c1ecba984b7c5e243bef895702f82b870223342eaac9414ecbb11eba24d77696cb6a4308c36ad17be4d7cb29e2d02bf98933a21e07960633dd5235f7a195d3bb703415d9fcf299609759f489183c404cb0099b2288d07b4d18f9ca736fe75bc353caaa15cc9f414dae3eb449a5342cca0ee59fa024c8facea1a19ffa8d7f29eae942c5fb1c732f5e1d8778db7b7700e0f9b96cc1f6ff580b7eab9ce3d18d21dae48f6a0fc693bf5fa2037120d7812a960dc12e1e9a71618a97e901c68df04e6e332ece08d3ee3d43683b504c968228d3b8787de2b9cb7d95b5d8b0c92570e6b3e6a7883e069a169e27d5d0699b8ff73454365d04c1fbe5956729b22a5f3089e5940e7b96b933a15615ea32bf49f5d59dc7577ed3ce76ee31dbd1bceeb3f63f3aede50258d1fedcb19c892f86d8e7887afd880ed57999b55a4326b6c45b244ac8aa3587967cf73da16242adf3c453a92c2ec66162c55e070d07f7d79c931074fa89df5fc1edbcebb101501893f88027f6599c9733af15ceb28eb82e9411bdec081913b49fd348783dc4d0837d6a5e438a747f799d3ce5e268a881ced1d5893218c8bdb72d68681ff187ca0d9382a728e6075a0fdfba465880e71e61ae40b46000a6a64cf9277ae64ef91f6677a9a1ddfdd8fed059465e4b4a4f4749f616d9ffb72ffe80b7ed2752db5e16be7a17926234f34db38bb6ae783428f5d6e86c1d27e3ec7b4bd051233fd94e3026276912ad4c357e69e86a906c093e7782939c2b17734e167fb97c99861c02f47993a3203492db426121eed4208c58ee19061424a35652992b23be4a6c6b36cf808dcc9ce84e7c25ca8672de3d81760981ad3f7ec96a19e85facdf248242fd914fd994bf97771dbe0d0a8b2f0bb762200b3d6a6f17f3609da45a9e8091b38959e211643db7753bbc32bb36d97c5690f9c724123e1ab3be8959768fd6457ac19c0ae70d16d5e32164e040fde3b538eb523d7d7add6b7bb0b16fdc7efb9307be9b6706e36c7e6fe5454671c2224888ef991af4f6d38bc6409df9eccc75bc69d1c722c46e16baf9709cbf77b64632d186faf99007396d46c45e5d791e760d1b379a16ad6a96b435a41a9ae642b3add6c24ff6b317b781e17b03863dd7a8d3d5458fc31816c5ffd0eccbf83884f92f3cf4b3be9e0489d41a39648067bb057347622858b5960b59f88cb09dec1ea3e0d494e8f9e0be56827d5cf7bc84b91434526ca9c9caa3151c91c198bb2d23cd555e14b98002cfd3f9855c2016df0867e0a84091a6e424f3ea147b6f731ef353dad4da3f1e3d35af0661aac353afb2747bdf993ded8c78bc6a487a20ec1fd496e44d7199399ef782115fc28026cdfce994b78804e536fda2d4c41747e51ff24dae22bfed3079c3cf74988299e519ba3a600d58731685533a5dff46b93b36d1aede64eaa099f84da02f82b727c927e0d637ba9b948e7c382f1f75a1d33d17c076f7f53998485662ca965bdbf114c2602801a6f629c6a054f5b559df4b5ccc9b23f2221c8e85daf2167c2ece6d82e65fd7d58d52b32dd53166bec868ecef3716343a9b3d3810c5d3beef4573d780ee105d7d2e04ba0f62f26ba3b7fbc6e02714261e73caee3c65f5ba896ba7415138c6aaea57528d4d23230365d5c7bd4105b329f439965a98ba09c8493daea692316960be11a35acdebda1efd82867549c68eeff5f2e91aeb2d0b42268431dacdcb4357d9e1dfc172cd5d8ff92f1ed08bb1fc08a0f7d7934150a615953461bca2839f8300377ca1ff94b77b45b054b5551cf33691f007209828c36dee1b89a02fca0d1728a001f587a60f238350e79767c70b960e220cd911085aa3aacf2611b0bc13537db590a19f2cc3e0397ca02262d6e4a9b1f13f101ebd73e0bcf5f7d9382942588cc4ea3f53f4f1ac0fecca8ee5392c92a85c884c43350e9eac8226c5650dad244f713554e67b5b87f493600dbdc3a1bd34407efb6e271a734d1ebb8203b7cfe8fb63028e07532bf58a75369f79d632f6e7de0b102b51adf71e9f394825fd0b27715661ef0f2fc662c0d6ed4b93b1d5493552f99d3b8b415d9b5a7a43fa02dac342619bb2e58e4227d3e81cec07f09998b5ed9b5fc342a15615564f34af9419ddb0e1897d776644902a11a4d4da96d77a58da779adf3543bddcf073a76407906f162a2ef4ac10e42eb6683b75bf0461f1659a393b937f28208346d10d6564b0a04d9627f10f0fab2e67c2170c30a20ac1763da3c11a63fc3779bc15863b1c1145b70964559571f7d1e002af32100ad821bd76648337a194202fc71494b6c50f644d44f016c97b642d134d5664dd2684a419880a7eaa4945f2e2d08474cf1eeca3632a69459cc31ccfcc2d6a184f9edac20b18f28868f969a72359e2b986d9ae07833a9239e65cb76bbf878b297f3b3245c2af8f72b4e2edb5a833ad6e3aa30f52783a0d09ff2df7e41496205a6a0f29f9360d50d818db49cb927a296e25ce9b83f0087be883e646072cdd14913a63bd0e16473b2138812e8dcdd8b7360643f6968bfb354485ba53413f6365bc6df2f78561ff451922b7520bb2e7420840035b3ad3455bac08f00f2250a1165cbf626d5097252a6841b5244163c97eba90cf250bf9f2dea355d1de41e7cd716ba22f53a235be29fd7e59dfe6ed69a3defc1d2101c1bf6cec2a47c41870165e7c5bc15b1d87591d021f231f0ffd3a5f0621f17a025aaa2aaaaa6e2a7f6e83f2e74ab4c89d94a33a870210a4d8c4c407a34192f76786f557457c59a67994eee8c8f3b26c57640b86d56ef4fa64ede64df1362c6081b7f80376ee106ae14808416b31dc614393f7367b3119a04403d019231239f7245d389b572b43d0d441c91aa34457c48262fc19a63a30de65a66625398f458a2e6578364a50fee3ee64bb244be8db8d2ce8859971d0c717ef9bbaa65fbf48b63ae7fdb12aa864df25f3cfd44af9d99c11286ea41feeaa472478a0d5c6f0d83f1d3220a3a2ce86464f52079d585067497ee6708cbed8998fba315b75d672339e69cc64b3d60d6287954e28df63e35d0f879bfbfaff6b5267475e4224c3e10c62a9b4ae4b2d11ca5286d115468fa92bb3f03ffd6b440da7a5a33c84092e035bf97fa6f9f9d0f9fae184db73f617ad1ab3b4deea798fe6107ad540a9839e8d0316b99b55215051d2220eb2444a2b17bbd1790ac176aebf33024db2cd7c108a1d7fc56efc3cd23f4de96d726ee868c2edfb033d4fc0035095eaf42d2483a07df35f48bcf435ff03f19b9eec328fa575c18a4cddf4ebeb2d3eb38b2212295eeff72e0666f68e989ec8ab2c85bb15116ee842ec4738d5c905f13072a01d3df919945d8d1aa457280635b173018c310f29aee756656d42db23fd1414270a3ea39c47fdd57a1cb512782cdbcf1e9717e3c96ab90068117dd58e606e3a7d913120663f98e2ccf7a703f07b74b7e8759ee3264e5df9cedf168de2360bb54f4fcfd65fcf37ace21ea1c116ebe88d70aeefac5e56fe2f3dd0f6782ad8e0ceee7f52f335cf1b75744ad7a3d7ab29ebec9e26df60e8219d13b857417470e21f48114b6b1c91bd2b24356b211ce9b371d0a4b4c7c452ba1468a9843fe2e326ad3179112afab95482f995953c5df70e7ee215ec7653ea4ac35443c9a3f3fe5689843a23c6d1d5434145e16bd9fb9820fc93637e5b3a503bc1fd9c72bfb23f0daffc9fdf274b660d9f24e290010cd6c5713bbbc18250de16bf89344b9158e49a58da27c6c155b4dc4cce9cb893d906ec78cf4b55267f2973e65a138d85d9901b7689c5f7d72b7fa5a1fd193c263a6d86620a51dc2bfa0250c151711695ad37a0ec57be3b8fbc656c8f1a7181e51328855ebceda81f3ea94d1e1c6fdc7a5ba6a61ae9e58562dffcc0cb93f0a604dab26e2ff7cde235504456b7706e4a43f63ef2882d106207ebc292d54c5fe6690bc6f7b3358fa1f497cf81fd298f7a79c8c28cf0f6dad3b823", 0x1000}, {&(0x7f0000000300)="0d62797d3ac46802212790be44ae6e326d72257b4dd8cc4e2866b479796aa4e51976931b76160c08cecf653a81a24f4e03bb8f2b0dfee5d2c910740878ba15a9be396fb10d9bad7f1de407a11547694aeee4e6e197f7caf396be5c3f75b026d3b3", 0x61}], 0x3, 0x0, 0x0, 0x400}, 0xc01)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000080)={<r5=>0xffffffffffffffff})
sendmmsg(r5, &(0x7f0000001740)={0x0}, 0xfffffffffffffdf2, 0x0)
r6 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000140), 0x10, 0x0)
ioctl$DIOCMAP(r6, 0xc0106477, &(0x7f00000001c0)={&(0x7f0000000180)='./file0\x00', r6, 0x1})
r7 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000380), 0x0, 0x0)
ioctl$VNDIOCGET(r7, 0xc4104603, &(0x7f0000001a40)={'./file0\x00', 0xfffffbf9, 0x3})
bind$unix(r5, &(0x7f00000002c0)=@abs={0x1, 0x0, 0x1}, 0x8)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000240)={0x0, 0x5})
r8 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r8, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)


mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x5cda)
r0 = open(&(0x7f0000000480)='./file0\x00', 0x1, 0x0)
munmap(&(0x7f0000000000/0x3000)=nil, 0x3000)
write(r0, &(0x7f0000000100)="8a522c6b8a8460561e290ca762e8d6c739d5dd7f0153b7a50498cb60ab818b16929d3bf742c57351df76ca9ec87e92fa9f010342ace3a6ffcf5c4b75c4c160f4acfe629a5717f5f5b7cad5c4e10a76103ea7945a70ea5a8999b18da379b691138c7d8a1529b81a7fb4540022f1324c3dda210f6f132101dfe0acc149685fdaca2fe92b8d4327e9872642c818370d60e800e0f8b2a66ead8ef0ddc9f0258f2275a9a0aefa8edd053e80a46946b0c0df080bb0d9c214c6a2393db966f0c0ace000", 0xc0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
r2 = dup(r1)
recvmmsg(r2, &(0x7f0000000440)={&(0x7f00000000c0)={0x0, 0x0, &(0x7f0000000580)=[{0x0}, {0x0}, {&(0x7f0000000240)=""/90, 0x5a}], 0x3, 0x0}}, 0x10, 0x0, 0x0)
dup2(r0, r1)
rename(&(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
writev(r1, &(0x7f0000000640)=[{&(0x7f0000000140)="90", 0x1}], 0x1)
execve(0x0, 0x0, 0x0)


unveil(&(0x7f0000000040)='.\x00', &(0x7f0000000080)='r\x00')
symlink(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000100)='.\x00')


r0 = socket(0x2, 0x3, 0x2f)
r1 = dup(r0)
setsockopt$inet_opts(r1, 0x0, 0x22, &(0x7f0000000040)="fd0cc085", 0x4)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000080)=[{0x2c}, {0x5c}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000300)=ANY=[])
ftruncate(r1, 0x2a2)
r3 = socket(0x2, 0x3, 0x0)
r4 = dup(r1)
select(0x40, &(0x7f0000000080)={0x9b, 0x81, 0x931c, 0x0, 0x7fffffff, 0x2, 0xa6e0, 0x8001}, &(0x7f00000000c0)={0x1, 0x5, 0x40, 0x66e}, &(0x7f0000000100)={0x6, 0x0, 0xab8f, 0xa4, 0x4, 0x2, 0x2c1, 0x5}, &(0x7f0000000140)={0x100, 0x6})
dup2(r4, r3)
connect$unix(r3, &(0x7f0000000000), 0x10)
sendto$inet(r1, &(0x7f00000001c0)="5e1351d18b9da08c", 0x8, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x61}, {0x1}, {0x6}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


r0 = socket(0x18, 0x1, 0x0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0xb, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
r2 = dup2(r1, r0)
setsockopt(r2, 0x1000000029, 0xd, 0x0, 0x0)


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000600)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
r1 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, r1, 0xffffffffffffffff)
writev(0xffffffffffffffff, &(0x7f0000000ac0)=[{&(0x7f0000000000)="56ce011ab92f8ec534", 0x9}], 0x1)
r2 = socket$unix(0x1, 0x1, 0x0)
r3 = socket$inet(0x2, 0x1, 0x0)
getsockopt$sock_int(r3, 0xffff, 0x1003, &(0x7f0000000000), &(0x7f0000000080)=0xfffffffffffffd22)
ioctl$FIONREAD(r2, 0x80206979, &(0x7f0000000000))
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000380)={<r4=>0xffffffffffffffff, <r5=>0xffffffffffffffff})
sendmsg$unix(r5, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, 0x0, 0x28}, 0x0)
recvmsg(r4, &(0x7f0000000300)={0x0, 0x0, &(0x7f0000000640)=[{&(0x7f00000002c0)=""/23, 0x17}], 0x1, 0x0}, 0x42)
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f0000000140)=[{0x0, 0x40, 0x4, 0x2ae}, {0x0, 0x0, 0x7, 0x200}]})
writev(r0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x50}, {0x48}, {0x6}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
setrlimit(0x0, 0x0)
r0 = socket(0x0, 0x2, 0x0)
close(r0)
socket(0x800000018, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
connect$unix(0xffffffffffffffff, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
recvmsg(0xffffffffffffffff, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
semop(0x0, 0x0, 0x0)
r1 = syz_open_pts()
ioctl$TIOCSETD(r1, 0x8004741b, 0x0)
fsync(0xffffffffffffffff)
pipe2(&(0x7f0000000000), 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001480)={0x0, 0x0, 0x0, 0x0, &(0x7f0000001440)=[@rights={0x10}], 0x10}, 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
sysctl$kern(&(0x7f0000000300)={0x1, 0x48}, 0x2, 0x0, 0x0, &(0x7f0000001440)='\x00\x00\x00\x00', 0x4)


mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x33b9)
r0 = open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f0000000080)={0x0, 0x0, 0x0})


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f00001a9000/0x2000)=nil, &(0x7f00001bf000/0x3000)=nil}, {&(0x7f000018e000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f000078b000/0x3000)=nil, &(0x7f0000093000/0x1000)=nil}, {&(0x7f0000334000/0x1000)=nil, &(0x7f000008a000/0x3000)=nil}, {&(0x7f0000066000/0x1000)=nil, &(0x7f0000133000/0x1000)=nil}, {&(0x7f000008a000/0x4000)=nil, &(0x7f000013e000/0x2000)=nil}, {&(0x7f0000323000/0x4000)=nil, &(0x7f000002a000/0x3000)=nil}, {&(0x7f000008d000/0x4000)=nil, &(0x7f0000089000/0x4000)=nil, 0x4}, {&(0x7f000056d000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil}, {&(0x7f0000765000/0x4000)=nil, &(0x7f0000027000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f00000a7000/0x3000)=nil}, {&(0x7f000071a000/0x11000)=nil, &(0x7f0000ffa000/0x4000)=nil}, {0x0, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000249000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000693000/0x3000)=nil, &(0x7f0000092000/0x3000)=nil}], './file0\x00'})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, &(0x7f00000000c0)=0x2, 0x4)
ktrace(0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_INFO(r0, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})


sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000000c0)=[{0x3d}, {}, {0x8006}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000340), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{0x24}, {0x2}, {0x416}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x138, &(0x7f0000000380)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
accept$inet(0xffffffffffffffff, 0x0, 0x0)
openat$null(0xffffffffffffff9c, &(0x7f0000000440), 0x80, 0x0)
poll(&(0x7f00000004c0)=[{}], 0x1, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000100))
syz_emit_ethernet(0x126, 0x0)
getsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
getsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000400)=[{}, {0x25, 0x0, 0x0, 0x1000000}, {0x812e}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000500)='./file0\x00', 0x1000, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ioctl$FIONREAD(r2, 0x80206910, &(0x7f00000001c0))


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x100000000000000}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x400000002, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r2 = socket(0x18, 0x1, 0x0)
r3 = dup2(r1, r2)
sendmsg$unix(r3, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


r0 = semget$private(0x0, 0x7, 0x3c0)
semop(r0, &(0x7f0000000100)=[{0x3, 0xa, 0x800}, {0x1, 0x2ff}, {0x2, 0x8, 0x1000}, {0x3, 0x3ff, 0x1800}, {0x2}, {0x2, 0x201, 0x3000}], 0x6)
semctl$GETPID(r0, 0x3, 0x4, &(0x7f0000000240)=""/8)
semop(r0, &(0x7f0000000200)=[{0x3, 0x0, 0x800}, {0x1, 0x100, 0x400}], 0x2)
semop(0x0, &(0x7f00000002c0)=[{0x4, 0xffd, 0x1000}, {0x0, 0x7fff}, {0x1, 0x106, 0x1800}, {0x0, 0x3, 0x800}, {0xf94be4091d2c0a4c, 0x81ff, 0x800}, {0x0, 0x4, 0x800}, {0x2, 0xfff8, 0x1000}, {0x2, 0x7}, {0x1, 0x1, 0x1000}, {0x3, 0x7e7, 0x800}], 0xa)
r1 = semget$private(0x0, 0x0, 0x104)
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f00000005c0)={{0x8001, 0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0xffffffffffffffff, 0x11, 0xbff}, 0x2, 0x4, 0xffffffffffffffba})
semop(r0, &(0x7f0000000280)=[{0x4, 0x1}, {0x2, 0x8400, 0x1000}, {0x1, 0x2, 0x400}, {0x3, 0x8, 0x1000}, {0x3, 0x4, 0x800}], 0x5)
semctl$IPC_SET(r0, 0x0, 0x1, &(0x7f0000000140)={{0x1f, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0x10, 0x8}, 0x8, 0x0, 0x5})
r2 = getuid()
seteuid(r2)
semop(r1, &(0x7f00000004c0)=[{0x2, 0x5bef, 0x800}], 0x1)
semop(r1, &(0x7f0000000040)=[{0x2, 0x9, 0x3000}, {0x3, 0x1}, {0x4, 0x70a}], 0x3)
semctl$GETZCNT(0x0, 0x0, 0x7, &(0x7f0000001500)=""/4096)
r3 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
semctl$SETALL(r1, 0x0, 0x9, &(0x7f00000001c0))
semctl$IPC_RMID(r0, 0x0, 0x0)
semget(0x1, 0x3, 0x104)
writev(r3, &(0x7f0000000280)=[{&(0x7f0000000000)='#!', 0x2}], 0x1)
write(0xffffffffffffffff, &(0x7f0000000180)="1e", 0x1)
writev(r3, &(0x7f00000002c0)=[{&(0x7f0000000080)=' ', 0x1}, {&(0x7f00000014c0)="20206000019c0a", 0x7}], 0x2)
semctl$GETALL(0xffffffffffffffff, 0x0, 0x6, &(0x7f0000000500)=""/35)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
semop(0x0, &(0x7f00000001c0)=[{0x4, 0x8, 0x800}, {0x3, 0x0, 0x1000}, {0x2, 0x0, 0x1000}, {0x5, 0x3ff}, {0x2, 0x0, 0x1000}, {0x4, 0x6376, 0x1800}, {0x2, 0x5b5, 0x800}, {0x0, 0xfffe, 0x1800}, {0x2, 0x7fff, 0x1800}, {0x2, 0x4, 0x1000}], 0xa)
setgroups(0x2, &(0x7f0000000440)=[0xffffffffffffffff, 0x0])
getgroups(0x3, &(0x7f0000000300)=[0xffffffffffffffff, 0x0, 0x0])
semctl$IPC_SET(r0, 0x0, 0x1, 0x0)


sysctl$net_inet_carp(&(0x7f0000000000)={0x4, 0x2, 0x6}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$vm(&(0x7f0000000000)={0x4, 0x2}, 0x7, &(0x7f0000000040)="c06d154be3aee5f8787f8b9cda7554335b763bb5deea5ccecb4d1b57a9f6fa18e47fc7b119db587e58811e666e84a806495b45c36164bd5b135280243ed0a01466056e93082876ba33ee8cf2b0b3907f236f38175101000000d7e39544aea098d19ee63d03cbf92380dbe904538135f09e408bbe17a54a364b04ee64b0ad54e6d4e38114ced38c328aff2e224239ba29eb0796e8c3e8344a2cd9e663bb21035ebf391872f3015c164556e4a5b966122c56edd85fc996f12fa1b92e47aa", 0x0, 0x0, 0xfffffffffffffe8f)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
syz_extract_tcp_res$synack(&(0x7f0000000100), 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000100)=[{0x1}, {0x44}, {0x96}]})
syz_emit_ethernet(0x36, &(0x7f00000002c0)=ANY=[@ANYBLOB="aaaaaaaaaaadc5aaaaaa0000000000000000000000eeec211dd1450021b07f5a1933ff00000000000000000000000000aa1a4792b39f252147cae2d26e0da296c9fee0e37314b1130c93562a48e78322e3a9c683d31a4e6bebca7f1128fcc431bd45fb1f2183021ad0eca0ece8f06cb254667a0ec52c4e63deccc8d0428321366b97b6558794d0e0a73ea2ba1e86f8b0b5a5320116b36108da8d509ee2fb0a384a1b11b12f7e70404c54ae549cd813f74835768d5a67435b5bf21efe149c1bddabfe34a50f9b35b2c38ce03853cd4191f9079868740cd527e940c116539c36d6c67d41ceb8f2206943336364f692bb148fb0d07f4283ebe1cc"])
syz_extract_tcp_res$synack(&(0x7f0000000200), 0x1, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x412dff)
r0 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
preadv(r0, &(0x7f0000001440)=[{&(0x7f0000001480)=""/138, 0x8a}, {&(0x7f0000000440)=""/4096, 0x1000}], 0x2, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000280), 0x10000, 0x0)
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000100)={0x1, &(0x7f0000000000)=[{0x1, 0xbd, 0x2, 0x2}]})
fcntl$lock(r1, 0x8, &(0x7f0000000080)={0x3, 0x0, 0x8, 0x100000000000005})
r2 = socket(0x18, 0x2, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
close(r2)
r3 = socket(0x18, 0x1, 0x0)
openat$klog(0xffffffffffffff9c, &(0x7f0000001400), 0x0, 0x0)
shutdown(r3, 0x0)
recvmmsg(r3, &(0x7f0000001380)={0x0}, 0x10, 0x0, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={0x0, 0x4}, 0x10, 0x841, 0x0)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x1006, &(0x7f0000000180)={0x0, 0x3}, 0x10)
sysctl$net_inet_divert(&(0x7f0000000040)={0x4, 0x2, 0x102, 0x3}, 0x4, 0x0, 0x0, 0x0, 0x0)
setitimer(0x0, &(0x7f0000000140)={{0xffffffffffffffff, 0xffffffffffffff7f}, {0x5, 0x5}}, 0x0)
getitimer(0x0, 0x0)
accept$unix(0xffffffffffffffff, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000440)={0x4, 0x18, 0x6, 0x9}, 0x4, &(0x7f0000000740)="9b1809c3218b07fcfe4189c99e805e6e84d356960798a692992117d6728436ba1bd87f42e3303eac3846528d050712f838130efce33f523ba44765f5f6915b2227390ed95bd9dc6d4dc7f149d4d6d06a3f23616e773302d9cae75e39a5a11e32e0e6ebd635450b2eba540af7f2aa5dbfbdd900a0dad2b74f50acd76b5c567049ef436dbea0d7562f52955af8d4ab84c513252ddd139b5f5cd5c2bd02adc7f1fe850c00000000000000062abb9fa45ac78568e1cb54238fbab475cca257352828a76e5334be562995e894238b96ca5d4d3e670fa0cc791dfc4415030910fa64eac9b4e8aa9bef19525cb6f7e8570be65bb7ad3fe963cb9a8bd949ee334db1ccf73db06b5947b3e88aa810f8ed7cca10ff0d0000000000001345daa49507756f49775275ca390b94e85d5a952000b9429c75d0da3b561c6adc3c141f26040000006b436218bdbdc9ac0a623855e941dc1872fcb045e0d9df1ecc6357ee21e2b0802cb60edd0300723221f06715e7eecc3e0760c70e1dd7873e27142bbae1a7e44de453a073fe3426f334b80f043ba9136d57c799353d46dd81439b111a511a288bee5dfb2e353e3bb073e3342273216b07e49ca4df0fd2dbe9a8eb377010ee678aad0bd8c7fb7d82693a096344671843a1f2082612b2ff237c6e505ff5f5ba932954d73c630fd2791f833a1da5af0704f687e196f4f7859e071fc98111cc9024f790ce16ceaa427d0104e39789d9100000", &(0x7f0000000a40)=0x210, 0x0, 0x0)


syz_open_pts()
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x0, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000040)="94c79bd261e1e88e83beb11c0a3e154df77b5335bd1667d9fd77c59297b3cad0ade427f63f2912518a179b7c207bc5ba040a20b5c36bfaca54e49900550bad2f165552f266a6b12d4900c56a22e814223e67a3fdf5ae19bcbb5d0a815015db8752d03d1b08f84b4976ec52d4a82598424ed3a6a523a3591db0e862a2f4dd1168cb17845fff1fb5df5535cae3e20e2bdb92138d0c1b0720e1c121ccb763f092cd5dcaa3d901", 0x2cfea}], 0x10000000000001fc)


mknodat(0xffffffffffffff9c, &(0x7f0000000280)='./file0\x00', 0x1000, 0x0)
unveil(&(0x7f0000000140)='./file0\x00', &(0x7f0000000180)='x\x00')
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f0000000180)=[{0x4c}, {0x16}]})
sysctl$net_inet_carp(&(0x7f0000000480), 0x8, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x1, &(0x7f0000000040)=[{}]})
madvise(&(0x7f0000000000/0x4000)=nil, 0x0, 0x2)
syz_emit_ethernet(0x4f, &(0x7f0000000400)=ANY=[])
semget$private(0x0, 0x6, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={<r1=>0xffffffffffffffff})
syz_extract_tcp_res(0x0, 0x0, 0x0)
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f00000000c0)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000300)=0xc)
setreuid(0xee00, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
setregid(r2, 0x0)
getpid()
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f00000001c0)="24a5b03a7cf812d1", 0x8}], 0x1)
sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x13}, 0x4, 0x0, 0x0, &(0x7f00000001c0)="00020000000a", 0xfe93)
unveil(&(0x7f0000000300)='./file0\x00', &(0x7f00000002c0)='c\x00')
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x7ff, 0x0)
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000140)=[{0x81}, {0xc0}, {0x812e}]})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000340), 0x10, 0x0)
poll(&(0x7f00000016c0)=[{r0, 0x1}], 0x1, 0x1ff)
openat$wskbd(0xffffffffffffff9c, &(0x7f0000001700), 0x0, 0x0)
ioctl$BIOCSRSIG(0xffffffffffffffff, 0x80044272, 0x0)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000140)="03000000", 0x4)
r1 = dup(r0)
setsockopt(r1, 0x1000000000029, 0xb, &(0x7f0000000080), 0x4)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x1000300010008})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
r1 = socket(0x18, 0x1, 0x0)
dup2(r0, r1)
setsockopt(r1, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x1, 0x0)
close(r1)
r2 = socket(0x18, 0x3, 0x3a)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r2, &(0x7f0000000100)="00003226a4a9000064e7c803d2a423734333a4dd", 0x14)


writev(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f00000001c0)="f007426c6a7984d37bf0785ff6c9", 0xe}], 0x1)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f00000001c0))


madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000))
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
sysctl$vm_swapencrypt(&(0x7f0000000000)={0x6, 0xb, 0x1}, 0x3, 0x0, 0x0, 0x0, 0x0)
sysctl$hw(&(0x7f0000000000)={0x4, 0x1}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
sysctl$vm_swapencrypt(&(0x7f0000000000), 0x3, 0x0, 0x0, 0x0, 0x0)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x3}, 0xc)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x34}, 0x4, &(0x7f0000000080), 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x400, 0x0)
socket(0x11, 0x3, 0x0)
r1 = socket(0x1, 0x1, 0xff)
r2 = socket(0x20, 0x8000, 0x0)
dup2(r2, r1)
sysctl$vfs_nfs(&(0x7f0000000040)={0x7, 0x4}, 0x3, 0x0, 0x0, 0x0, 0x0)
connect$unix(r1, &(0x7f0000000100)=@abs={0x0, 0x0, 0x3}, 0x8)
r3 = socket$inet(0x2, 0x2, 0x0)
r4 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
dup2(r4, r3)
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
r5 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSTAT(r5, 0x20007465, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000400)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000300)=[{0x84}, {0x20}, {0x4000006}]})
writev(r0, &(0x7f0000001400)=[{&(0x7f0000000240)="e049c0d37348a45d6bee0bf84a9e", 0xe}], 0x1)


shmctl$IPC_SET(0x0, 0x1, &(0x7f0000000000)={{0x0, 0xffffffffffffffff, 0xffffffffffffffff}, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1})
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x33}, 0x5, 0x0, 0x0, &(0x7f0000000000), 0x2e)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000280)=[{0x2}, {0x3c}, {0x106}]})
socket(0x18, 0x1, 0x0)
r1 = socket(0x2, 0x2, 0x0)
getsockopt$sock_linger(r1, 0xffff, 0x80, &(0x7f0000000000), &(0x7f00000000c0)=0x8)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}, 0xf8ffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000200)={&(0x7f00000001c0)={0x0, 0x0, &(0x7f0000001880), 0x0, 0x0}}, 0x10, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
syz_emit_ethernet(0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x8040691a, &(0x7f00000001c0))
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000000c0)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
ktrace(0x0, 0x5, 0x40001b00, 0x0)
recvfrom$unix(r2, &(0x7f00000000c0), 0x832f1f7d, 0x0, &(0x7f0000000000)=@abs, 0x2000c600)
sendto$unix(r3, 0x0, 0x0, 0x0, 0x0, 0x0)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xfffffffffffffffe, 0x0, 0xffffffffffffffff})
fcntl$setstatus(0xffffffffffffffff, 0x4, 0xc0)
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000000), &(0x7f0000000040)=0xc)
r1 = open(&(0x7f0000000100)='.\x00', 0x0, 0x10)
mkdirat(r1, &(0x7f0000000340)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38/\x00', 0x0)
open(&(0x7f0000000040)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//../file0\x00', 0x0, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket$unix(0x1, 0x2, 0x0)
getsockopt$sock_int(r2, 0xffff, 0x2000, 0x0, &(0x7f0000000040))
getsockopt(r0, 0x29, 0x2c, 0x0, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r3, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f00000001c0)=[{0x48}, {0x5}, {0x16}]})
writev(r3, &(0x7f0000000500)=[{&(0x7f0000000000)="af18a64591749e07ad1273f580a0", 0xe}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{0x3}, {0x14}, {0x6, 0x0, 0x0, 0x4}]})
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000000200)=ANY=[])


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x7}})
r0 = socket(0x18, 0x2, 0x0)
sysctl$vm(&(0x7f0000000200)={0x2, 0x9}, 0x2, &(0x7f0000000380), 0x0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000580)={0x3, &(0x7f0000000080)=[{0x60}, {0x30}, {0x6, 0x0, 0x0, 0x210000}]})
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r2 = socket(0x18, 0x3, 0x0)
setsockopt(r2, 0x29, 0x6c, &(0x7f0000000040), 0x4)
close(r2)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sysctl$vm(&(0x7f0000001340)={0x2, 0x2}, 0x2, &(0x7f00000013c0)="455e0e7fd8042f98a20aadf6b4e0e3883970d6ef930f70e95da2bdf55fd550b63844405ae34ba7a24829aaec432c5388688cde4e733985d2c8b52cba5573cd7eacd9ab0c5fb40003ecbbc9bc8563f4059903478eea4eb52037fdf8ad639b16244d2366b898840a2f8ab673ff77bb7d1be820a246099669b77af0a42d06bc2771cc1b467eac054e1c3d86d266892b58beea97718bb0c287edb299bde3c04069d0eaf56f6746d6b8befb94ea029f8cf3ae4f825208dc35e860b974b2bc2a1251", &(0x7f0000001480)=0xbf, &(0x7f00000014c0)="61cfdfd3b31006714e2320d9ad044d8bda07110b0502283f7094a1411f2fdd928b82fd990b39185679de7c3b49134e7a8e2c9f936b91c60ff6c115e7ab08beb9fbe7c528b054068eb3667dce2e28fb70a960f68c279e563bb1560b3da205c1869bc7ab5ede7b6b34943cc8ccbdf913960f69a1a768311b6aca0807e66bb456c10c0df85c5c798d2fad5a1005ef25147a1e5f7c76dae0c6734f288015dae2c366bacbd3ab403bae8153f3044cd9e5b862f290301d950cbd82b5dde55df13c65f7233a3e38a62d4308c2fe54312c7c318e5606f41a265c60cd99e7d7a516a48d759d29a90ea33bf53084b0253d4a3675d9ab2d8cb8b9b452c4be", 0xf9)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xc)
r3 = socket(0x18, 0x2, 0x0)
fcntl$dupfd(r1, 0xa, r2)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
listen(r0, 0x6)
setsockopt$sock_int(r3, 0xffff, 0x200, &(0x7f0000001380)=0x6, 0x4)
r4 = open(&(0x7f0000001300)='./file0\x00', 0x10, 0x103)
connect$unix(r4, &(0x7f00000012c0)=@abs={0x1, 0x0, 0x1}, 0x8)
r5 = dup2(r3, r0)
write(r5, 0x0, 0x0)
socketpair$unix(0x1, 0x5c7610ef4cb22c27, 0x0, &(0x7f0000000140))
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000080))
syz_emit_ethernet(0x17a, &(0x7f0000000000)=ANY=[@ANYBLOB="f3a2a8908a86aaaaaaaaaaa986dd601ab5b60000000000000000000000000000000000000000ff020000000000000000000000000001001d"])


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140))
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x7c}, {0x60}, {0x812e, 0xfd}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
semget$private(0x0, 0x3, 0x220)
r1 = socket(0x18, 0x3, 0x3a)
setsockopt(r1, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r1, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x3}, 0xc)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt$inet6_MRT6_ADD_MIF(r1, 0x29, 0x66, &(0x7f0000000140), 0xc)


sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000080)='./file0\x00', 0x0, 0x40000630, r0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000000040)=[{}, {}, {}]})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000007, 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x2, 0x0, 0x1a}, 0x4, 0x0, 0x0, 0x0, 0x0)
msgget(0x2, 0x408)
r1 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x20, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r1, 0x80105727, &(0x7f00000000c0)={&(0x7f0000000080)=[{0x8c}], 0x1})
r2 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000280), 0x1, 0x0)
ioctl$WSKBDIO_GETENCODING(r2, 0x4004570f, &(0x7f0000000000))
sysctl$kern(&(0x7f0000000040)={0x1, 0x2f}, 0x2, &(0x7f0000000040), 0x0, 0x0, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
r2 = dup2(r1, r0)
setsockopt(r2, 0x0, 0x20, 0x0, 0x0)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x8981, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105727, &(0x7f0000000100)={&(0x7f0000000000)=[{0x7}, {}], 0x2})


mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$WSMUXIO_LIST_DEVICES(0xffffffffffffffff, 0xc1045763, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
r3 = socket(0x2, 0x2, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)
writev(0xffffffffffffffff, 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
r4 = socket(0x18, 0x2, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x1023, &(0x7f0000000040), 0x4)
select(0x40, &(0x7f0000000000), 0x0, 0x0, 0x0)


r0 = socket(0x18, 0x3, 0x0)
getsockopt(r0, 0x29, 0x32, 0x0, 0x0)
r1 = socket$inet6(0x18, 0x2, 0x7)
setsockopt$sock_int(r1, 0xffff, 0x1007, &(0x7f0000000100)=0x2, 0x4)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f0000000000)={0x15f, &(0x7f0000001080)=[{0x280}, {0xc, 0x10}, {0x6, 0x0, 0x0, 0xfffffff8}]})
socket$inet(0x2, 0x1, 0x0)
socketpair$unix(0x1, 0x3, 0x0, &(0x7f00000000c0)={0xffffffffffffffff, <r3=>0xffffffffffffffff})
getsockopt$sock_cred(r3, 0xffff, 0x1022, &(0x7f0000001f80), &(0x7f0000000100)=0xc)
sysctl$net_inet_gre(&(0x7f0000000000)={0x7, 0x4}, 0x4, 0x0, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001880)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f00000003c0)="5080c5a97558d472b3d20fe4a61339bd547710cb16b1331906dee84e0746ad4a017eeafc6cd84f80da82744d47076311d447c0ad1580769294c53268547ffa2de45c1e30364fef08671030bb9ca9e5f071219824dbbffd53d83e2eded34241119e2dc17a", 0x64}, {0x0}, {&(0x7f0000000300)="7ea3f94ec9aea0cfec8e6958bff13adf333086d3c258d19367300f6a0a5398d749f0c24c3de285a28d9100e4532b0710cbce050e3162b8150acf29179cf07c3286e01de621182f7ed0229c571858cffb0e598a7b21d0621b7b", 0x59}], 0x3, 0x0, 0x0, 0x400}, 0xc01)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000080)={<r4=>0xffffffffffffffff})
sendmmsg(r4, &(0x7f0000001740)={0x0}, 0xfffffffffffffdf2, 0x0)
r5 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000140), 0x10, 0x0)
ioctl$DIOCMAP(r5, 0xc0106477, &(0x7f0000000440)={&(0x7f0000000180)='./file0\x00', r5, 0x1})
r6 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000380), 0x0, 0x0)
ioctl$VNDIOCGET(r6, 0xc4104603, &(0x7f0000001a40)={'./file0\x00', 0xfffffbf9, 0x3})
bind$unix(r4, &(0x7f00000002c0)=@abs={0x1, 0x0, 0x1}, 0x8)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000240)={0x0, 0x5})
r7 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r7, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000006c0), 0x1, 0x0)
writev(r0, &(0x7f0000000200)=[{&(0x7f0000000700)="986718d5a0279aceb86fda64ec0d7e6fea2ed9e879060753c1fda2ea549649364e677dc43367db8a62ae02e606e9ffa4b5c1671f831f7e5b47f95dc960d8632aacc1e5a41fdad49db578c6be991551c854af2b71ad74f732c5e0ec9f2cf2eb2fda78d24528aaab7ac31eb80c9fd6af1b4054a7f596d9da11425976c3a56cd10036a2", 0x82}, {&(0x7f0000000140)="fb21d331ba86fb052e", 0x9}, {&(0x7f00000002c0)='.', 0x1}], 0x3)
writev(r0, &(0x7f0000000400)=[{&(0x7f0000000000)="daf674ad8d4f7caa1b2e65dfbfc13507f699b9a9939557bbf6f71f5b83b03889c629d9687773c058553b80e5e3d1400ba456feff7778c6d082d1daab73ee6c329b0540aa59f1946870cf710fddfa2d1418c4473447365a04aff63a1346abbdd3cff847517d39209bcdfc86cd3dc6de69201bd0c823ec5973a8acd685d3f7c24f2e6ba4c0239aa86e372e", 0x8a}], 0x1)
execve(0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0xca})
open$dir(0x0, 0x200, 0x0)
r0 = openat$pf(0xffffffffffffff9c, &(0x7f0000000000), 0x10, 0x0)
ioctl$WSMOUSEIO_SETMODE(r0, 0x80045726, &(0x7f0000000040)={0x1})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x1ff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x1, 0x5, 0x0)
r2 = openat$tty(0xffffffffffffff9c, 0x0, 0x1, 0x0)
ioctl$TIOCSTOP(r2, 0x2000746f)
close(r1)
r3 = socket(0x18, 0x2, 0x0)
setsockopt(r3, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setreuid(0xee00, 0x0)
getuid()
setreuid(0xee00, 0x0)
setreuid(0xee00, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x2801)
r4 = open(&(0x7f0000000280)='./bus\x00', 0x0, 0x0)
close(r4)
setreuid(0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
setsockopt(r3, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r5 = socket(0x18, 0x2, 0x0)
setsockopt(r5, 0x1000000000029, 0x9, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
setsockopt(r5, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931", 0x11)
ioctl$TIOCSTART(r4, 0x2000746e)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)


mknod(0x0, 0x9000, 0x3200)
r0 = open$dir(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
preadv(r0, &(0x7f0000000000)=[{&(0x7f00000000c0)=""/99, 0x63}], 0x1, 0xffffffffffffffff)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
madvise(&(0x7f000008f000/0x3000)=nil, 0x3000, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {&(0x7f000002f000/0xd000)=nil}, {&(0x7f0000060000/0x2000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000ffb000/0x4000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f000018d000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ioctl$VMM_IOC_RUN(r1, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x9})
r2 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x0, 0x10, r2, 0x0)
faccessat(0xffffffffffffff9c, &(0x7f0000000800)='./file0\x00', 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000200)={0x7, &(0x7f0000000040)=[{}, {0x4}, {0x812e, 0x1}, {}, {0x0, 0x6, 0x85}, {0x9, 0x3f, 0x9, 0x7f}, {0x4, 0x63, 0xff, 0x6}]})
open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
r3 = open(&(0x7f0000000180)='./file0\x00', 0x2, 0x0)
ioctl$FIONREAD(r3, 0x8020697a, &(0x7f0000000100))


r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
r1 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r2 = getpid()
ktrace(&(0x7f0000000080)='./file0\x00', 0x0, 0x20, r2)
ktrace(&(0x7f0000000240)='./file0\x00', 0x0, 0x100, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x1, 0x10, r1, 0x0)
ioctl$WSKBDIO_SETMAP(r0, 0x8010570e, &(0x7f00000000c0)={0x0, 0x0})


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)
r1 = kqueue()
kevent(r1, &(0x7f0000000140)=[{{r0}, 0xfffffffffffffffe, 0x55}], 0xc8b5, 0x0, 0x0, 0x0)


r0 = getppid()
mknod(&(0x7f00000000c0)='./file0\x00', 0x2000, 0x0)
getpgid(r0)
r1 = open(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
ioctl$TIOCGFLAGS(r1, 0x4004745d, &(0x7f00000002c0))
ioctl$BIOCSDLT(0xffffffffffffffff, 0x8004427a, &(0x7f00000001c0))
fcntl$setown(0xffffffffffffffff, 0x6, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
getpid()
r2 = open$dir(&(0x7f0000000140)='./file0\x00', 0x80, 0x6)
ftruncate(r2, 0x1ff)
sysctl$kern(&(0x7f0000000000)={0x1, 0x56}, 0x2, 0x0, 0x0, 0x0, 0x0)
msgget$private(0x0, 0x0)
getgid()
r3 = semget$private(0x0, 0x1, 0x241)
semctl$SETALL(r3, 0x0, 0x9, &(0x7f0000000100)=[0xa5, 0x1])


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ioctl$BIOCGFILDROP(0xffffffffffffffff, 0x40044278, &(0x7f00000000c0))
mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSPGRP(r0, 0x40047477, &(0x7f00000003c0))
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(0x0, 0x5, 0x40000500, 0xffffffffffffffff)
socket$inet6(0x18, 0x1, 0xff)
recvmmsg(r0, &(0x7f0000000400)={&(0x7f0000000200)={0x0, 0x64, &(0x7f00000008c0), 0xa, 0x0}, 0x6}, 0x10, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000280)={<r1=>0xffffffffffffffff})
dup(r1)
sendmmsg(r1, &(0x7f0000000040)={0x0}, 0xffffffffffffff12, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x3, 0x0, "0100012d29fb000700000000098002005a00"})
ktrace(&(0x7f0000000080)='./file0/file0\x00', 0x4, 0x800, 0xffffffffffffffff)
getpgrp()
msgget$private(0x0, 0x421)
r2 = socket(0x11, 0x3, 0x0)
sendto$unix(r2, &(0x7f00000002c0)="b10005010000009f0500070107000000331c13fecea70500fef96ecfc72fd3357ae30200004e30ffd2d236acf20bf404be01000000f7c8cf5f882b297be1aa050400ce94e2f0ad3ebbc257699a1f139b672f335c22db830c032bfa896443c32118210000720fd38bfb0000fd54c125191b1257aea8c500001602fbfe0c2300008abfba0900000808f37193f8343712cc1100b71d0900090105000000000000001300"/177, 0xb1, 0x0, 0x0, 0x0)
r3 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r4 = dup(r3)
pwritev(r4, &(0x7f0000000140)=[{&(0x7f0000000580)="c6302c9c455c7be3d8598d3ac53af8e7574f36a8db981ae2d8854330fd7f9fc4ba71ba88b9ff297ff033cc3a3dd93a7e60391b1e6b1d20ad08c2", 0x3a}], 0x1, 0x400)
writev(r4, &(0x7f0000000540)=[{&(0x7f0000000240)='<', 0x1}, {0x0}], 0x2)
ioctl$BIOCSETF(r4, 0x80104267, 0x0)
execve(0x0, 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0xb3)
msgget$private(0x0, 0x0)
msgrcv(0x0, 0x0, 0x0, 0x3, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x80206999, &(0x7f00000001c0))


mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x10201b1a)
open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)


mkdir(&(0x7f0000000040)='./file0\x00', 0x0)
mkdir(&(0x7f0000000240)='./file0/file1\x00', 0x0)
unveil(&(0x7f0000000180)='./file0/file1\x00', &(0x7f00000001c0)='x\x00')
unveil(&(0x7f0000000080)='./file0\x00', &(0x7f0000000380)='x\x00')
chroot(&(0x7f00000003c0)='./file0\x00')
unveil(&(0x7f0000000280)='.\x00', &(0x7f00000002c0)='r\x00')


syz_emit_ethernet(0x2e, &(0x7f0000000000)=ANY=[@ANYBLOB="000000000000aaaaaaaaaabb810001000806004b08f905040086dbbbba595918e0000002aafffffffffffffe7f02"])
openat$pf(0xffffffffffffff9c, &(0x7f0000000100), 0x8000, 0x0)
sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x25}, 0x4, &(0x7f0000000200), 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
open(0x0, 0x10, 0x0)
utimensat(0xffffffffffffffff, 0x0, 0x0, 0x0)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
getsockopt(r0, 0x0, 0x9, 0x0, 0x0)
r1 = socket(0x11, 0x3, 0x0)
openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
sendto$unix(r1, &(0x7f0000000000)="b10005136000009f05003e0800000000331c13fecea10500fef96ecfc72fd3357a068d02bc31a3a5673039d2d236acf20b7804be38164991f7cccf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f4d335c223e7d026ba8faff0037720fd38bfbb770c1f5a872c881e2772ec5a10400000000000000361b1257aea8c5d0002012000000000000880d6633c556ae9b287948a62310db415f779642cdcd71a3f8343712051e000000000000", 0xb1, 0x0, 0x0, 0x0)
sysctl$net_inet_udp(&(0x7f0000000040)={0x4, 0x2, 0x11, 0x5}, 0x4, &(0x7f0000000140), 0x0, &(0x7f0000000300), 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000080)=[{0x84}, {0x5}, {0x8106}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x8, &(0x7f0000000180)={0x0, 0x0, 0x0, 0x100000401})
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
fcntl$lock(r1, 0x7, &(0x7f0000000040)={0x0, 0x2, 0x0, 0x0, 0xffffffffffffffff})


r0 = open(&(0x7f0000001440)='./file0\x00', 0x615, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r1, 0x9, &(0x7f0000000280)={0x0, 0x0, 0x0, 0x1000301010006})
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x0, 0x10, r0, 0x0)
execve(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{0x50}, {0x60}, {0x836}]})
syz_emit_ethernet(0x36, &(0x7f00000001c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000580)={0x3, &(0x7f0000000540)=[{0x2d}, {0x20}, {0x6}]})
syz_emit_ethernet(0x7e, &(0x7f0000000280)=ANY=[])


sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x1c}, 0x4, &(0x7f0000000040)="e50b796fa52062bced8f646268e24f252922e5207853782e9f0bdbe77c1757b9e3fc0680fa9c9cf08a3c3775850b5905d7d3fae180d335c453e15a0876cc401573704cd525196252ab5cbcadb9", &(0x7f0000000100)=0x4d, &(0x7f0000000140)="63558fdedf3c953f3f83669f08f21e7d02a3", 0x12)
sysctl$net_inet_ip(&(0x7f0000000180)={0x4, 0x2, 0x0, 0x12}, 0x4, &(0x7f00000001c0)="441add139d2879efa7503f87500b9404907c97b0d54fbcab04336299b80dbaff26bf30d4009ffec65c1d8cd28de9c7b04c9694ff3b1efa1dac1b944c674061809efb59edd8d198344e08d68a0a28f01e2798e2330ed3074a81d509b7f79cfd36adada44e4bcd031de401278ed7304775f959b9f6725f477177fb2ed0e940c41db41af800cc5dab4f09dfb885ff7f4fa4f15271b3345e209e639b58e3d8f5d68637eeeadc8a255f28af27e9bfab8abaf2041b28f8ca19261e757e722ef25e5d0295ea21e72b497f34582e5df61405be46bfb48f0593c4f0bad763a1436a65616bc66d3372e98a96dd25e3", &(0x7f00000002c0)=0xea, &(0x7f0000000300)="e656825f035fd089801789e1039faa76c50ae2f4dfe6aa167a862e8b1f26f49077a32f4efc6927c60d0db74ef19ae3a809c0392eb08c12d0952d4dbea41a9e1e6f9daab6ad3577d8c174047c8331572e5a6e975b659f7857bcc40315fbdeb507966382ab63ec6debadbcaf8cec1c700ee64ddc3f61330135d5686b14286252f8531a898bcd3da8d240b694729255a7389b62813400a8a3d2704c409cc26742037eb39cb399429440c0014188d6e887954434b4c4a6af4d1a6a990d09bcbb9fc6843ae8a0d03a02b4484548287a61ee4b9696d981337fb2ae152c9f6f1a0e1f7c9a94781af57aed031c7a16d90192bb67e719", 0xf2)
sysctl$net_inet_ip(&(0x7f0000000400)={0x4, 0x2, 0x0, 0xa}, 0x4, &(0x7f00000012c0)="049515c11e187f4a917998a5e0771a71d15d10dcfe0adf5d1175d8ad537ffadd074b431dda60f6e2d30db629f32b3c72883444bfa214dded718ce5e31883b6dc0f2d85f905d43cc1d1150313d60a3626ae6aaf0d4f67bd1a02c456b8fd0a43bc1c98f7364c8d155d08114b0525db28e0650ce34026405eca143f2e510a9bd9ec0ba2f2db7e5fbf0115e6db", &(0x7f00000004c0)=0x8b, &(0x7f0000002680)="3d27041277c973f03682bde1d99bcdae121242028d0aeb02c3eea5e0700cf8e43db0ef7e1ca62a377ed7bef2e878acfc51990fe386db142e408ecf0cdc101fc588e237cf42978b59e65fb0b638d312d004ddae1ab3cdb2db45ef0b3bfe2885faff37bae2adf17325079985be35f0b93458f21484093df0a26ebda97033ba99f0d54c2ea1a00e1bf8c4a1da9867996084515f9082d5a31792b3d2ae2f677d73f50a7404ad38e3992c8ef0b30a4d03604338413a9dbec71f5ec1cace49178b3c7e99c6138ee7e79be6b2bcf372c4a99957b596e5017752b880e8afd94fc4e7e5807dfd67fd72bdffd5b3746d122563c119220b33e94e76ebb6c99e913157", 0xfd)
sysctl$net_inet_ip(&(0x7f0000000540)={0x4, 0x2, 0x0, 0x19}, 0x4, &(0x7f0000000580)="45203e6ee8e7f915343bc69df01c68d5e82aa8a3841caef6a172142d740e091812", &(0x7f00000005c0)=0x21, &(0x7f0000000600)="6bcd97f7b4825464eb6f17c0b3579cfd31e88dee1c0805d12d4670b6529235c08fef9377a6dffa208d27cd40034ee4994eaf711bc2d799522659ce5e00120a0cd86bc0eab62e3ba598d9e8df55fa6b9bf90c035cd5b7d8c0550760da1c5b1803e11a32d8272a20f723d1f128cf65a946b3c482de0e1c8ceb82228832868df38a7f56a4e281357ca0bb7b24f946748ff1c07208aeaa5bace038ba61e80da151058fae6a1cea8c456d42de0de3667d5d0118416c", 0xb3)
sysctl$net_inet_ip(&(0x7f00000000c0)={0x4, 0x2, 0x0, 0xf}, 0x4, &(0x7f0000001680)="d0749078a859cc3a5935a33af4976bd47628b06086ce6c4fd9f193924359ac6f884298afcd6baf94610a9e63a88a8347087a4fd09d894524ca88db85389473c912bb77f9551a591dbfe1bf82cb2ecd6fcf7f60b2c16fe9b5f57f3a697573212f3927f6aa31fc6e7e2f7d8a83363c0c8e9515050f3a893a69bd25856316707017afedfc3aaea35213b55fde30304588d599e5c143aac3002595b89a6f644fccbdbd9adda685acf5aa0e955f7ba731bf06a951856de1dcbebac45ffc797265a3f7640e73ad2cb5c445cdbd29153b112f95e3f44da95d10776220b97e090bb67e2909b33916332e311b509e1d0b40df5ece0edb65719499b45ba37e93d2781b9b0ddc04f7028213a709d68006d46e15b16582afb30c3923e7f49891011699e4106c0866f4a0f1410ab448020300d7cadc1bd72871339cb73ff6504d1ee6590022cbbc4db16d60cbd68c839c0d5670ba33816193c5d7c610b4adac67351c3e19671481409978012046dc8ff62e5beb49d8ce4aecb78fda6e9ccb64310d11ea3069e5e8ed6433811de2b0f14cbfed4059da495d50aae54aa8e7bffc88ce7e538ddafd2d88a1aa1e58f3bf2cffa4175a6a6e2e0f1574507aa181788f3fe093c40f23545fd5ecaff944f2a7c0d03f98d174b07fbcf3b195ad123ce95edb2223b15be806cf5b7a91e3925ea25e36cb540fabc43dfd13abc7b45c1dc6f76e83b8cb3a49b8a9a9d3c22172f1994466149696a11de4dbb627e573877a1cc1a0265327d8a4250ac6ce0439313839e893ccc3979fc778ac9ba2f9efa699a76317932d5cd8d085ebbe4d7bdfe03790a0cd9ad32a72e1d56667a28950addbe8186a22e31a7be604f6f20b6e30934a0ee34fa129b4a9edde3d32a120476e6f1fcd228971b597b86110e29c84fb8903fdd60295b69c6e77715f38bd01bdc742ac38ccd2f882b323ed04d44aff00a3c5a7a0bb0b99ac20fcaa7d8d3a6219070de83f67691a8a7c99a75605bfa64ce820b1f519c216cfd19db96964e4273933adafcd46345609428c606cb92d5f380025f2493d0c5368393182eb919f2454e3b8f35af8a52fa4dc6882d7dbba3074aa072c5c56e92bea8a41f3092f17b59ee02db6f940df87fc399881f24f63549a37cd48daeab56165576e871958702c15b19358f3669cd77915c9d02be5b1d62721c1ea458122d30cbaa7df615030e114933bdb0e33a012efc67fbeda5e69249df8b6b1691f3e90f9cce068b3a9fe45921887e29fe4663b0ec415f64432d293615123b822d123603c91b390898216383c3a80534bf4e9eeb6bf3a33bf10a61ecd9353c549462343b2b5358581caac100fb451720fd6d849b213357eeb16063c8260e49ddf6ec25463634ae4940e959915e9b484e3032bad4738b686a6ce9865441be49ffc8c3374b0e38ce9b0169e780820bf227a17bb60e043375e0a8c3bbe7d48a3e4f3fe0f009a120b77974c2c34d2f622966b3ceaae3a0edea0c8f6de10f99188ed8639d9b1fbacb85575a4e51166d7212b23fc0d67bd4d5e3de393e953be7453f18fbfbbac833e53c7e4d7ad663245e8b959c939ee0d5673508835125254062d804123ca36b40caa5b750143dcac171577518f7266699df1eb2f82ae3777ca5270756ba7fedbd63dc291e72bc239fbf986d0b5ff7f380d169f4ed7fef51873ca2021e6c814619894a09a619af6cba87b6c306c2a3ebe99b92b778c39dda35ac234c2b1ff8cf3a0f173b08c364eaaf27fb2bf68e077ec1bc45bc73092902218e78b8778b9c71cbeaa15bf64cf562d87c81d6ccf84b628d3d190befa169e1ccec860de86b06781dcedb4ec45ef54c58a30e24c5c189a7c33ba627d57f2781df3a718b02e52b97fd8c74805ac1d1744a7415633bb8fe2f4870c250ea3041e118cca6a692f5076a0eed04acf83b83e367767adea35ee5f89ebc12aa29f0822103971441042f524794e4a7d80a0eab13281bc27c121aac6704c8e9cabd856de147960ef6107f1d7bed7250b439faec4e80a2346d612432114a4a769a743bd53e4fae63f08f2880c3adfec77f07fb81289544fd954c1f8b7dae1566eff048637ef825ae48b6efc230a9e026dd575d2cbf62b3c611828ec0e51099736a5821f989fceaba283e2c91c09a0ab4ededd68cfcba26c338071666f8656f2692665839ce9804c11638f12376c5e59525b6b0b26536d40d736b6d0637bb65ad8cbf28171b4aa2810500eb17bfec7184e7012f10762d2778a1bdbdc9af1355f6e169d12623329463ee2672f40c68071bd3cad1b0c3ed1ae4482249030b9d84ddbd70a413586da5c5bacf935887295635976ced3db1832d0dc80faf0303258ef12735fb1e343bb6f43609ad2a67228a2034190eabcb636a583ec6f6eae251c15089e2cf26d383cfcb30592bfc65f676b8b4055a9f098ccb33f0942e19662ad3075ac03d10c19b7d491fc1ef8adc4843ccb7043e0324f04f9ac74fed566c1fc8a31f084ad4996489bb2cdc027c8e48ecb291dd045589498547b588261012a1f3ffa25dcd3804396c38d194885c8071bf78dcbc15c4e4565ed7d7e8dced0d12689d0df9448af8015a102893643c4046c2a0a6402412c64345ce77930869d97c323df7e03a31320495dff02d4a3f8599c4b1ed2e6f43feafb46b20d671e581397112fb8524c37da07328ccb328c110da68c3920c65f07c0b7bda8b7c494b1bc2cf7e0b06947f1cec04b800bd3b36f08faa0f4bf9177f58b8511a2fef07cc62e7f4eb0a645aefb4880a00eb33ce50f9df566e48c576b29e59fe9e6e8f4f249b220910e2a4977b92a0910c481fe665ae5ad2ab01596b5048ed5de95b2a7e468f95221e7a4c622f5acaff45bb365d5933ee607cdd19f489654b98f72c410e23b6c8cf8736cda2429537ad85d6de18e9ce11797307adeef5cd4926f174f12005fa95e89f69151f84bd19f4a79eb7ab1d86fd3935f45b1603fdabd77ba2b764594cd9ba3cf8d849ae0fa0fd7e0ca424d8f3e431201bce6d26eb68c7cdd7069442a4e4c0672845683ddc0360daa421f9f8ab66ce96c9bc3799fa41adf69439b9607c7677f582ca23714b1e8c80eb769409379d57a68f3a170aac3464a665ce76da5a56869b792d2f4aa1ed2c3f40a2e304247a03c8a5ec151edcdf7c52233436c9fe7ead03eefce8cf10441fb95e01e7d64de157908dcfe248fecfae691be722e99b2d5c09e0fc67af8bffd193f30844e57919c5563788e83d82b5133e0cb2214fbb053efa6fac40c80d2506c940584d741a2d71738c816cabdf506b9e19f4e77f149118c43334beb0814a9236c3648bfc5e4e629fa3972844850cb4bbf77c1e172d5f90583e3f2faf688766f447b523e2a2399c4c0a0d2dc2e794f8a2f632c4478af7e3e37de8f671504791a9526f5324c4546d9d133e0a5c843aeb48b3711f070b0403dc801e473fab5451d68a0865f9a74f272e45a6dcf9b490ecf413f3e07d8569cb4f96b96b590f321454d3bffdfc642f1863c9d8612dea56584d15c288644d958d0f4ddabf82bf4ff849155bf5479457323f1044ed54da9c1e9b35a75cf3a91d6f62a7124f0f34f377bf16471e2379453c97f3087bc057ed0a0172fac4b7cd6df4dfca8268acb59cb60e71db031b1f017387cfd65edf120bb375588f7cd896234e542823fd0f5c706ca3bdf05a95d9f74c2a2dae94f79def23fd5131ab0b91706cecdc15b6730f84427ff244d541f59dcc7d6222b894eb017e934555d8daab61b0c319bc4fc2fa851acf810f2c8258f46aeb816cdec3ba8749169a82755dcaacf3c6b", &(0x7f0000000980)=0xa80, &(0x7f00000009c0)="061f69a8745aacad26f1ea6302541a3b38b38ea1663bab413da3d676a740a1ad4e89a057aec74859b1fc5678ffb9783a39215a67449315e73df418d6680f16026a88bbfd7e1cd6e8b83425e16bc79f0baba817355642c43603429c971b37a5276d77c169b770a127d5acb66cd8ac1ea87298165ecd72a43823f27c0f8e121459e388", 0x82)
r0 = openat$tty(0xffffffffffffff9c, &(0x7f00000006c0), 0x80, 0x0)
ioctl$TIOCSETAW(r0, 0x802c7415, &(0x7f0000000700)={0x1, 0x401, 0xc430, 0x2, "2f9840e74cfedfaaa23087efd7a79d1b9d195752", 0x5, 0x8ce})
sysctl$net_inet_ip(&(0x7f0000000740)={0x4, 0x2, 0x0, 0x27}, 0x4, &(0x7f0000000780)="12e20e5ec2e9239bf63482eff7c590ab2ecaf8e958bcd000977913acabb787bdb6ca97ee48bc669fd9c55d8a2e9841c4ef3c1a794f466029ea348207cd97360249b3b003989a94ae2fb7e596563fc09d116f37d098d5b3a195a47f1c7fa6849adc3d5e89001e097d82c2c867f1aedd624db28bd5404d9693ec00484bff3ebecebafdcb113906015c231beeee740cd8b6d873fe886ab92fb7f8298f5c36ad093fbd992742", 0x0, 0x0, 0x0)
ioctl$TIOCMGET(r0, 0x4004746a, &(0x7f0000000900))
msgget$private(0x0, 0x108)
r1 = semget$private(0x0, 0x6, 0x40)
semctl$SETALL(r1, 0x0, 0x9, &(0x7f0000000b00)=[0x9, 0xbe8, 0x7])
sysctl$net_inet_ip(&(0x7f0000000b40)={0x4, 0x2, 0x0, 0x13}, 0x4, &(0x7f0000000b80)="85fa76c9ca47551930f52c445a24fde8da82489ea8f459f10ca6bd85195d9e12e9af451b2c91b2590fb21a8bc79b429be142ffbf23da6e3b238db049480584db4475f5a7d4a06e45dc21e78e1fc2cd3d3e915f839669468dadf46de1cc56f65f9855f61cc41b5037e49a806d00f80e8e87a0ba8438bcea8907d85f3a0ee2a428bc166aa2a17cca964bf91c511e0cd4177af5b0800dfec0b8", &(0x7f0000000c40)=0x98, &(0x7f0000000c80)="8450f056dfadd67a15af1cb7e1b943979aab28c6a1b9c5b4f575715472df218b8b9c1eafc6d323b7f278df663b5e53a94e3ea7d68b93ea0df4110ce9f794f8519288de3549f2e77780f7ae4b189967d1d4c9b6014847ed0866e04359ec833b865461163b015025fac3e6d47b541aa38755985f8a87d8f682f8dca7a0a3e4228cdf8005d346c516ce831389f959d49e7f5985edaa61a8ef6935b2f7396c07a753a3beadf2cf3dca002eb2de09a071447b7ba0a332532e949acc65e28bca82606f72af4ab237435dd29929c03fb8b0acd74d7b8c0873757b82060a48f4f3ac78f814a5a5cf9f4f", 0xe6)
msgget$private(0x0, 0x201)
r2 = semget$private(0x0, 0x4, 0x20)
semctl$GETVAL(r2, 0x3, 0x5, &(0x7f0000000d80)=""/136)
msgget(0x1, 0x40)
pipe(&(0x7f0000000e40)={<r3=>0xffffffffffffffff, <r4=>0xffffffffffffffff})
sysctl$hw(&(0x7f0000000fc0)={0x6, 0x14}, 0x2, &(0x7f0000001000)="db9c7d752e119d764f82d888308ac4e2de24f20d55a8ed0bfe5a028395949a6c880b8dfcdc8adbfff0ac57187cf71fd65825d6badebe2e59b4ca0f230eac6c", &(0x7f0000001080)=0x3f, &(0x7f00000010c0)="cde57635c535ec8d75b8b991a813b86358a60d373f9356408712", 0x1a)
r5 = openat$pf(0xffffffffffffff9c, &(0x7f0000001100), 0x100, 0x0)
semctl$GETZCNT(0x0, 0x2, 0x7, &(0x7f0000001140)=""/117)
getsockopt(r5, 0x1, 0x400, &(0x7f0000000440)=""/102, &(0x7f0000000500)=0x66)
accept$inet6(r4, &(0x7f00000011c0), &(0x7f0000001200)=0xc)
openat$bpf(0xffffffffffffff9c, &(0x7f0000001240), 0x800, 0x0)
sysctl$net_inet_ip(&(0x7f0000001280)={0x4, 0x2, 0x0, 0x27}, 0x4, &(0x7f00000012c0), &(0x7f00000013c0), 0x0, 0x0)
getsockopt$sock_cred(r3, 0xffff, 0x1022, &(0x7f00000014c0)={0x0, <r6=>0x0}, &(0x7f0000001500)=0xc)
r7 = getuid()
getsockopt$SO_PEERCRED(r4, 0xffff, 0x1022, &(0x7f00000015c0)={0x0, 0x0, <r8=>0x0}, 0xc)
semctl$IPC_SET(r2, 0x0, 0x1, &(0x7f0000001600)={{0xfdf6, r6, 0x0, r7, r8, 0x0, 0x1}, 0x1000, 0xefe, 0x5})


r0 = socket(0x1, 0x1, 0x0)
fcntl$setstatus(r0, 0x4, 0x40)
r1 = getpgid(0x0)
fcntl$setown(r0, 0x6, r1)
shutdown(r0, 0x2)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x1, 0x5, 0x0)
ioctl$FIONREAD(r0, 0x80206913, &(0x7f00000001c0))
kevent(0xffffffffffffffff, &(0x7f0000000040)=[{{}, 0x0, 0x80, 0x0, 0x2}], 0x0, 0x0, 0x0, 0x0)
socket(0x18, 0x1, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}, 0xfffffffffffffe01})
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x8040691a, &(0x7f00000001c0))
sysctl$net_inet_tcp(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)
r2 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r2, 0xc0305602, &(0x7f0000000040)={0x4, 0x0, 0x0, 0x0, 0x0})
open(0x0, 0x70e, 0x0)
getpid()
open$dir(&(0x7f00000003c0)='./file0\x00', 0x400004000011830a, 0x0)
setreuid(0xee00, 0x0)
getuid()
chown(&(0x7f0000000180)='./file0\x00', 0x0, 0xffffffffffffffff)
getuid()
setreuid(0x0, 0x0)
chmod(0x0, 0x0)
ktrace(0x0, 0x0, 0x0, 0x0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "0100012d29fb00"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85baa97981056ef1043f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0x9, &(0x7f0000000340)="0a000000f0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0x4)


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000001440), 0xe8, 0x0)
r1 = fcntl$dupfd(r0, 0x3, 0xffffffffffffffff)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
pread(r1, &(0x7f0000000240)="9e", 0x1, 0x0)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000280)={0x0, 0x0, 0x0, 0x1000301010006})
open(&(0x7f00000000c0)='./file0\x00', 0x20, 0x0)
r1 = open(&(0x7f0000000400)='./file0\x00', 0x0, 0x0)
fcntl$lock(r1, 0x9, &(0x7f0000000140)={0x0, 0x0, 0x4c0, 0x269000000, 0xffffffffffffffff})
r2 = open(&(0x7f0000000bc0)='./file0\x00', 0x0, 0x0)
fcntl$lock(r2, 0x9, &(0x7f0000000080)={0x0, 0x0, 0x100, 0x1000100000000})
r3 = open(&(0x7f0000000bc0)='./file0\x00', 0x0, 0x0)
fcntl$lock(r3, 0x9, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1000100000000})


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x1}, 0xc)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x67, &(0x7f0000000000)={0x20}, 0xc)


setitimer(0x0, &(0x7f00000001c0)={{}, {0x0, 0x10000}}, 0x0)
getitimer(0x0, &(0x7f0000003c40))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x64}, {0x28}, {0x6}]})
syz_emit_ethernet(0x62, &(0x7f00000006c0)=ANY=[])


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={<r0=>0xffffffffffffffff})
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
ioctl$WSDISPLAYIO_GETSCREEN(0xffffffffffffffff, 0xc0245755, &(0x7f0000000080)={0x7fff, './file0\x00', './file0\x00'})
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
writev(r1, &(0x7f0000000700)=[{0x0}, {&(0x7f0000000180)="6f17bb2964703f2297240d688aa83c3beb09b18f297c6f4b042c170b12f3d9ea641fe82924f40571b76a3aa4b13fd677db44fb944e9e0c5326395dd348f8db4e1adee38085112e", 0x47}, {&(0x7f0000000280)="abf0a6d9dd90fae8cd7b97caaa78c53463f557ab6cef44ad1d10f2cf60094b5d60b02340ec1f1a13717c73cfdb61eb2601019504bdd30a027d950c3d3be2f4f72bc5bd3aa0d5b6e37a949d13e96174e83a9f7e8216a0c0ff772315990d397941bd8d7c", 0x63}, {&(0x7f0000000340)="bc2c67c97240afa638e729d5f3e047aa124418a9c0466d9c1e855ae2f45bbddbf75110255343f8d362680e1701ec7cb72fd56529bfc2095cec5e57fb03485e83b87f34a006a12c", 0x47}, {&(0x7f0000000480)="e84add09dde8f30d81632a8f190def48bd5a161a5418c778af0c0dbccccdb85d4981e6bba558e6453569730bc0055c93eee47dc5949fde518b452973", 0x3c}, {&(0x7f0000000500)="ed42532023894fe88cb259164ed2f665bb511d988d84691cbb70c3f3538ba8ab25db3d097da62a77a8705ccbefeeb5e7e789f46847c49eb6805427435246e0721f040ee649f0f370cd388d9bb497c36a0440b1f30c5c04a8d27b7ffefe97080cb4233cecedfb1191487188741ca2", 0x6e}], 0x6)
mkdir(&(0x7f0000000300)='./file1\x00', 0x0)
chroot(&(0x7f0000000240)='./file1\x00')
r2 = semget$private(0x0, 0x2, 0x41)
semop(r2, &(0x7f00000000c0)=[{0x4, 0x3, 0xe5ce97ab354d96be}, {0x0, 0x4}, {0x4, 0x2}], 0x3)
setreuid(0xee00, 0x0)
r3 = open$dir(&(0x7f0000000200)='./file1\x00', 0x40, 0x56)
r4 = getuid()
fchown(r3, r4, 0xffffffffffffffff)
r5 = getuid()
setreuid(0xee00, r5)
r6 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r6, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r6, 0x80104267, &(0x7f0000000000)={0x2, &(0x7f0000000080)=[{0x64}, {0x16}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])
open$dir(&(0x7f0000000000)='./file1\x00', 0x7ffd, 0x0)
truncate(&(0x7f0000000080)='./file1\x00', 0x0)
semop(r2, &(0x7f0000000440)=[{0x2}, {0x0, 0x2a4, 0x800}], 0x2)
semctl$SETALL(r2, 0x0, 0x9, &(0x7f0000000040))
bind$unix(0xffffffffffffffff, &(0x7f0000000040)=@file={0xd19450564dee018c, './file1\x00'}, 0xa)
syz_open_pts()
syz_open_pts()
syz_open_pts()
fcntl$setstatus(r1, 0x4, 0x80)
getpeername(r0, 0x0, &(0x7f0000000140))
shmget$private(0x0, 0x2000, 0x0, &(0x7f0000ffd000/0x2000)=nil)


r0 = syz_open_pts()
writev(r0, &(0x7f00000001c0)=[{&(0x7f0000000580)="7659aeb94832406f050635f0b67c483a24febaee4d9c497b7e5f0bf12b7225efb6f6c869e646ecfa588c53283c4dd3ed77706f3868cacea799a3bdfb42db706563dca286f58274eac945d5ffe9054ffd5b7724b408516b9ed309d4751896dd052cc4977fb3194274891c0663318fc47757be95bdc22a02114abcba148730246ce5aa4f5d217faa6438f9fa2c0e0b7ab697a8d63f824aefa5064bf87f22d6cfd97dca4d46f07c6ad783dcc1a919ba8409ff0f1be654c2b62f0ca1a4087d6d8940691f19a5ba", 0xfffffe5b}], 0x1)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
syz_open_pts()


r0 = socket(0x2, 0x1, 0x0)
r1 = dup(r0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000002c0)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
r3 = dup(r2)
recvmmsg(r3, &(0x7f0000000440)={&(0x7f00000000c0)={0x0, 0x0, &(0x7f0000000580)=[{0x0}, {0x0}, {&(0x7f0000000240)=""/90, 0x5a}], 0x3, 0x0}}, 0x10, 0x0, 0x0)
dup2(r1, r3)
execve(0x0, 0x0, 0x0)
sendto(r0, 0x0, 0x0, 0x0, &(0x7f00000007c0)=@in6={0x18, 0x2}, 0xc)


kqueue()
r0 = socket(0x18, 0x3, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x8000, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000100)={0x0, 0x0})
syz_emit_ethernet(0x126, 0x0)
setegid(0x0)
r2 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
close(r2)
setsockopt(r2, 0x1000000029, 0x0, &(0x7f0000000280), 0x0)
setsockopt$sock_int(r0, 0xffff, 0x800, &(0x7f0000000180), 0x4)
mkdir(&(0x7f0000000100)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
rename(&(0x7f0000000200)='.\x00', &(0x7f0000000240)='./file0/file0\x00')
syz_emit_ethernet(0x4a, &(0x7f0000005c40)={@random="69e1629b6174", @remote, [], {@ipv6={0x86dd, {0x0, 0x6, "6b9efb", 0x14, 0x50, 0x0, @rand_addr="cb69bc83c1677a656ab420666c3e2c6f", @local={0xfe, 0x80, '\x00', 0x0}, {[], @tcp={{0x3, 0x2, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}}})
r3 = open$dir(&(0x7f0000000240)='.\x00', 0x0, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000000)=[{{r3}, 0x0, 0x6f}], 0x7, 0x0, 0x0, 0x0)


r0 = socket$inet(0x2, 0x1, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x1e5f)
r1 = open(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
dup2(r0, r1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000400)=[{0x50}, {0x81}, {0xa7e}]})
write(r0, &(0x7f0000000000)="7696e5f3d1f18c37cea8615ac7cf", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000140)=[{0x74}, {0x44}, {0x812e}]})
syz_emit_ethernet(0x2e, &(0x7f0000000280)=ANY=[])


open(0x0, 0x80000000000206, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
sendto(r1, 0x0, 0x0, 0x0, 0x0, 0x0)
recvmsg(r2, &(0x7f0000002880)={&(0x7f00000014c0)=@in, 0xc, 0x0, 0x0, 0x0}, 0x0)


r0 = open$dir(&(0x7f0000000040)='./file0\x00', 0xae828e137847f62, 0x0)
setrlimit(0x1, &(0x7f0000000000)={0xfffffffffffffffd, 0xffffffffffffffff})
ftruncate(r0, 0x40000000007)
truncate(&(0x7f00000000c0)='./file0\x00', 0x6001000004)


openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000040), &(0x7f0000000100)=0xc)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
symlink(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000100)='.\x00')
unveil(&(0x7f0000000100)='./file0\x00', &(0x7f0000000140)='c\x00')
truncate(&(0x7f0000000100)='./file0\x00', 0x0)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000002a40)={&(0x7f0000000000), 0x10, 0x0}, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r0 = socket(0x2, 0x2, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sendmsg$unix(r0, &(0x7f0000002a40)={0x0, 0xffffffffffffff89, 0x0, 0x6e, 0x0, 0x700000000000000}, 0x0)
sendmsg$unix(r0, &(0x7f0000002a40)={0x0, 0x0, 0x0, 0x40}, 0x0)


open$dir(&(0x7f0000000000)='./file0\x00', 0x200, 0x0)
r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
pwritev(r0, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
r1 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r2 = socket$inet(0x2, 0x3, 0x0)
r3 = open$dir(&(0x7f0000000580)='./file0\x00', 0x40000400001803c1, 0x0)
ftruncate(r3, 0x80002)
recvmsg(r2, &(0x7f0000000500)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000400)=""/220, 0xdc}, 0x0)
readv(r2, &(0x7f0000000d40)=[{&(0x7f0000000180)=""/167, 0xa7}], 0x1)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r1, 0x0)
execve(0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x9, 0x51})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
ioctl$FIOASYNC(r1, 0x80047460, &(0x7f00000000c0)=0x3)
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)


kevent(0xffffffffffffffff, &(0x7f0000000000), 0x0, 0x0, 0x0, 0x0)
r0 = socket(0x11, 0x3, 0x0)
setsockopt(r0, 0x11, 0x2, &(0x7f0000000000), 0x4)
r1 = socket(0x11, 0x3, 0x0)
sendto$unix(r1, &(0x7f0000000140)="b10005016000009f0500070005000000331c13fecea10500fef96ecfc72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd38bfbb770c1f5a872c881ea6e2ec5890400000000000000361b1257aea8c500002002fbfe0c2300008abfba0900000008e371a3f8343712051eeab71d89e0000407000000e011200000", 0xb1, 0x0, 0x0, 0x0)
r2 = socket(0x11, 0x3, 0x0)
sendto$unix(r2, &(0x7f0000000000), 0x0, 0x0, 0x0, 0x0)
read(r0, &(0x7f0000000240)=""/226, 0xe2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000080)=[{0x24}, {0x3}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000300)=ANY=[])


mknod(&(0x7f0000000040)='./file0\x00', 0x2000, 0x2a7e)
ktrace(&(0x7f0000000180)='./file0\x00', 0x0, 0x0, 0x0)


sysctl$kern(&(0x7f0000000040)={0x1, 0x37}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0x2, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = getppid()
fcntl$setown(r0, 0x6, r1)
fcntl$setown(r0, 0x6, r1)


sysctl$net_inet_tcp(&(0x7f0000000040), 0x4, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$vm_swapencrypt(&(0x7f0000000040)={0x6, 0x1b}, 0x3, 0x0, 0x0, 0x0, 0x0)


sysctl$kern(&(0x7f00000000c0)={0x1, 0x47}, 0x9, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000180)=0x66, 0x0, 0x27)


setpgid(0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x300100000})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000002}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
sendmsg$unix(r0, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x2, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504000000000000e30b060000001a5113fecea10500fef96ecfff0f00007a89583535", 0x25, 0x0, 0x0, 0x0)
socket$inet6(0x18, 0x2, 0x0)
r0 = open(&(0x7f0000000200)='./file1\x00', 0x80, 0x2)
ioctl$VMM_IOC_READREGS(r0, 0xc050756a, &(0x7f0000000800))
openat$speaker(0xffffffffffffff9c, &(0x7f0000000080), 0x80, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000500), &(0x7f0000000540)=0xfffffffffffffed5)
r1 = open(&(0x7f0000001180)='./file1\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x0, 0x10, r1, 0x0)
readv(r1, &(0x7f0000000440)=[{&(0x7f0000000280)=""/142, 0x8e}, {&(0x7f0000000340)=""/165, 0xa5}, {&(0x7f0000000400)=""/31, 0x1f}], 0x3)
readv(0xffffffffffffffff, &(0x7f0000000040), 0x0)
setreuid(0xee00, 0x0)
open$dir(0x0, 0x80, 0x30d)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x80, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
clock_gettime(0x0, 0xfffffffffffffffe)
socket$inet(0x2, 0x0, 0x0)
close(0xffffffffffffffff)
bind(0xffffffffffffffff, 0x0, 0x0)
r2 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0106924, &(0x7f00000001c0))
syz_emit_ethernet(0x6e, 0x0)
socket(0x18, 0x3, 0x0)


setitimer(0x0, &(0x7f0000000000)={{}, {0x2}}, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbdf13b9fd812eaa4e713048e69931929648", 0x14)


clock_settime(0x100000000000000, &(0x7f0000000000)={0x8000000000000001})


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff})
setsockopt$sock_int(r0, 0xffff, 0x200, &(0x7f00000000c0), 0x2)


r0 = socket(0x18, 0x1, 0x0)
open$dir(&(0x7f0000000040)='./file0\x00', 0x300, 0x0)
ktrace(&(0x7f0000000300)='./file0\x00', 0x4, 0x530, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
getsockname(r0, 0x0, &(0x7f00000000c0))


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x881)
open$dir(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x801)
open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)


mknod(&(0x7f0000000300)='./file0\x00', 0x2000, 0x6da)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f0000000040))


open(&(0x7f0000000180)='./file0\x00', 0x80000000000206, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000401})
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r1, 0x9, &(0x7f0000000200)={0x0, 0x2, 0x0, 0x1000301010086})
r2 = open(&(0x7f0000000400)='./file0\x00', 0x0, 0x0)
fcntl$lock(r2, 0x9, &(0x7f0000000140)={0x1, 0x0, 0x2, 0x269000000, 0xffffffffffffffff})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000380)=[{0x3d}, {0x20}, {0x406}]})
syz_emit_ethernet(0x138, &(0x7f0000000040)=ANY=[])


socket(0x11, 0x3, 0x0)
socket(0x11, 0x3, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
select(0x40, &(0x7f0000000140), 0x0, &(0x7f0000000200)={0xffffffffffffffcf}, 0x0)


ktrace(&(0x7f0000001d40)='./file0\x00', 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x1, &(0x7f0000000080)=[{0x8a}]})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x2, &(0x7f0000000100)=[{}, {}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
mkdir(&(0x7f0000000080)='./file0\x00', 0x0)
rename(&(0x7f0000000080)='./file0\x00', &(0x7f00000000c0)='./file0\x00')
openat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x0, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VMM_IOC_TERM(r0, 0x80045604, &(0x7f0000000240))


r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$PCIOCWRITE(r0, 0xc0107003, &(0x7f0000000140)={{0x4, 0x2, 0x5}, 0x81, 0x0, 0x2})
r1 = semget$private(0x0, 0x3, 0x6aa)
r2 = getgid()
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000001180)=[{0x7}, {0x7}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f00000000c0)=ANY=[])
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f0000000040)={{0x0, 0x0, r2, 0x0, 0xffffffffffffffff}})
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000080)=[{}, {}, {}], 0x3})
r4 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_GETPARAMS(r4, 0x80105727, &(0x7f00000000c0)={&(0x7f0000000480)=[{}, {0x40}], 0x2})
sendmmsg(0xffffffffffffffff, &(0x7f00000007c0)={&(0x7f0000000780)={0x0, 0x0, &(0x7f0000000440)=[{&(0x7f0000000180)="b860fe09625ee6793978a575faa1b6c6c1d6c2eca2950e663d39ab1be31a269a39fd7f97e41e178f37a79f00659c2ea9ac56733f7e4e4973c1e6b326c91343ea3b3f8c5c7b93d5fe30", 0x49}], 0x1, 0x0}}, 0x10, 0x0)
socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x80206979, &(0x7f0000000240))
openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{}, {}, {0x6, 0x0, 0x0, 0x85}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)
r5 = socket(0x18, 0x3, 0x0)
connect$unix(r5, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000001440))
r6 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r6, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r6, 0x80104277, &(0x7f0000000080)={0x2, &(0x7f0000000700)=[{0x30, 0x0, 0x0, 0xffff}, {0x6, 0x59, 0x40, 0xfffffffe}]})
write(r6, &(0x7f0000000740)="76e5dead6f01f8607d2100000063", 0xe)
getsockname$inet(r5, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
r7 = socket(0x2, 0x4000, 0x1)
connect$unix(r7, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockopt(r7, 0x29, 0x2c, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047470, &(0x7f0000000140)=0x2)
ioctl$FIOASYNC(r0, 0x80047460, &(0x7f00000000c0)=0x4)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "d89d7d000000000020de88d11bd4000900", 0x80000040})


sysctl$kern(&(0x7f0000000080)={0x1, 0x3d}, 0x4000000000000004, 0x0, 0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000040)={0xf66d, 0x0, 0x7fffffff, 0x4777c53f, "1c10260930770300000000000000da64612c2300"})
writev(r0, &(0x7f00000008c0)=[{&(0x7f0000000080)="7ae0445be7e8efef04af3f7ad60d3a98013ce9d94bde9bf8e0cd020deb77e1cfc7e2ea34dbfe4b2a47efd4bc363879d4583d159a507d3134b6634c43f67712aee3fd22aae129c79a1121bf46fcb9c3e44cf50523af75ad15b1fe71ea01395e266dfceecd841f9d25b12034251c03bc60f242c103a900dff29c7d86860795651ccee2a3ab76a0fcb65b596f6af10ceec8f32bb1a73de51df82816eda3dcf0c0dd0684dc61aba4ad29bc9a0000004e09f651c213b8335dadd14cacc0a18f9984e819d1cee13bae0a2b5057deaa8676ced029cdb77d0aad7be4f442afe5b60a89bfcce7aa9815c9a17f1adb04efb34e627d44a31280b09189d381e9701172b4ee171f4f7acd075325f5dbdc824b854f7903d83266edea1fdca53996077ef25c23", 0x11f}], 0x1)


sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b10005", 0x3, 0x0, 0x0, 0x0)
r0 = socket(0x2, 0x2, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x2, 0x2, 0x0)
r4 = socket(0x2, 0x4001, 0x0)
r5 = dup(r4)
r6 = fcntl$dupfd(r5, 0x2, 0xffffffffffffffff)
close(r6)
r7 = socket(0x2, 0x2, 0x0)
connect$unix(r7, &(0x7f0000000000), 0x10)
connect$inet(r3, &(0x7f0000000000), 0x10)


r0 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
mkdirat(r0, &(0x7f0000000040)='./file0\x00', 0x0)
unlinkat(r0, &(0x7f0000000080)='./file0\x00', 0x8)
socket(0x2, 0x2, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
r1 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r1, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000040)=[{0x100, 0x3fffffd}, {}], 0x2})
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r2 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSETD(0xffffffffffffffff, 0x8004741b, 0x0)
ioctl$TIOCCDTR(r2, 0x20007478)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x40}, {0x1d}, {0x8106}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x3}})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7, 0x3}, 0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x0)
sysctl$net_inet6_icmp6(0x0, 0x0, 0x0, 0x0, &(0x7f0000000140)="80468b309b2548cca0c3bd621508525753789a6678d065d43ee4beba5f1b29d75f17fbc7afd04721d15570cfc48e0c124334ca8f55e8fe16ae3c48f5447f2ffc59e1de35169f015f6c7037faee2301a56aa2741434d2b14fab1e7701f22c3262a9f8e27a8a696caa3b9ab7c06b7d2489b7ce8bf6fd9b847cf1d878486af7992904af965bf98c7545167c41c2041c0942", 0x90)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x8020697a, &(0x7f00000001c0))
kqueue()
sysctl$vm_swapencrypt(&(0x7f0000000040)={0x7, 0x2, 0x3}, 0x3, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x31}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0xfffffffffffffda3)
setrlimit(0x0, &(0x7f0000000980)={0x0, 0x35})
r1 = socket(0x18, 0x2, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
close(r1)
r2 = socket(0x18, 0x3, 0x0)
setsockopt(r2, 0x1000000029, 0x32, &(0x7f0000000440)="b211d7170d816685c8e360f2fa41c1a0946988b272a746e337b372e93320cff6669cbe7868de45ed3fc33719ca6df71ecec8a900108b2c10a1f8c66653b276e180e9cb9b21f9982230f575295d48889c98000796b2dd921a4975680b37ba955d2c15e6d7c9198ed900ab006ddfb6f869b51a2216114d1ece85f593e74035f5bc054eb1dbddf42a004000000000000000", 0x90)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
writev(r2, &(0x7f0000000680)=[{&(0x7f0000000000)="2f87bb4098d7de568a6a2453616c321b9657609db9199f45ae67568303000000000000001af7383890", 0x29}, {&(0x7f0000000040)="a6c2f740b256d444e7c4a1cf3e85e989cd7b6de6e007f992fd10d0d1e4190b026d7345ed1542a83278a7ad88c2e4936716a1c9f584b7580b5394d1cedfe065a12c255b8db174397e3c27c523c4fdda9f136777d9a01a5ec173df3c5cd0617444191393", 0x63}, {&(0x7f0000000180)="999a0bdc3e414b91a5b028931d6a721970809e7e46932e5f83d6e1ae971f5f6a39f16780ec2080c21648c5cedd2f0757dc836c6c52a0e26f20fb23dfd317ed739e8c79d11a5ece7fdafb084679f4ae06f28bef576995c0e2f4df9ffc8671bc166b5b85f6c0ade6f95df478a7831d21bf26e2330daad4eca408e39bf2cb41ba4d6c5e567ef5754123d1a7864001946a7e1a2316949601a36d3b4198441767b3ae2dcff405522900e043caec0b2994ca5257891479414094b799efb2567664f4b393937f725cdfa2df512747aa7033bffb238c841a54c1f2b84f9f2ba9322c233efa4794d23429118c33d0ed76b4cca674a799cbad150abe1d", 0xf8}, {&(0x7f0000000280)="4731121e881a0d846f926159fff827e9f50ff9f10a833c33d4dd55db0297f2380247ad2d3eea494b024d8c154ff497da4d8263c1f607f8bd10afb46c7d6b3fd4d5eed763fb7b040bb29bde13e9c269c838f40f58bf35e94a17a0679f3520f573d589c30f7576716d4f", 0x69}, {&(0x7f0000001380)="c7296d3e009ee2ae10dd10d407d10883eda1bd4dbe2d40f37e3a2c3a99bacd7cef9cb9f4d565b7d40faf3a33bc158578993c8ad24b6a7dd93128a1802eadb90b6547165bdb7db8f14b66bd927854d37f09e6cd10fbcbf5c4518836019486ea3168ebb7fd9b7fa5ecaff32b6a5dc8e749c632b29479c507ab1f98dde927e837810cb087d8bbc901a89167ef3c27ac5b23dbefd994e5b766227bb98e5e6c7d5490a7a7caf3d72d1224181b181e5441777a6401669a2ee2243c9a3cfbe3e05d9f396e69ad9301f8cc6586493dde1dd02d6d7af120bd35db33d7fb75441f823373b1471c7ea74caf8ef1c2bceee4470f6b3f872edc7c5cf05b08f15940c68959ebf845e548899040fbdc80f515efb4e37ec4f49e0a1bd51ffe4de7024590c02752cb9a35668c2bed3598cf02a7988c399d3c9deac099c7ec532b739b280b4e1be305539444d14b3f1884ccbd17f8e9c36d9b0045e712e24d3ace5ca7ebb352253bccdcfd5e759419edb5eb34bc44ac69728f394c86aac9dd39f3580e4aaa60d2090a1b6eb8f3950e2f85c543ae7180298ba4bc4d49ccef237dafd5615bf48e51ac3b67a6dce5bd7981b97a04cd089fad110c299659206a3b21c5b8ab9a8a7a33e356cb8c48100b62a11f5f26c11638a25058880e9456c52d1b0b5fcdde101346e2b9a04bde97710181a87f9540f2358df291adbf86c5d95fcd160bcf405e76a8686a38af17d18b56e2658b2e8d15a3de34ed8f371d4bd03d6e39c6c940173d40f8ceb88b78579e38e1f555dfbf55407494cf36d90a3c7a03513013d40d59346a4c87ff06b2f88ed74412605ce640abb5ba192548071a5a0f4f8dfb3d2b66", 0x25c}], 0x5)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000140)=[{0x4c, 0x0, 0x0, 0xffff0001}, {0x0, 0x0, 0x0, 0x10004}, {0x6, 0x0, 0xf5, 0x8000000}]})
syz_open_pts()
syz_emit_ethernet(0x3e, &(0x7f0000000240)=ANY=[])
r4 = socket(0x18, 0x2, 0x0)
close(r4)
r5 = socket(0x800000018, 0x3, 0x0)
setsockopt$sock_int(r5, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "ce51bf2b1e61cd965d51c9f9c3e137a69f61a565"})
bind$unix(r5, &(0x7f00000002c0)=@file={0x0, './file1\x00'}, 0xa)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmsg(r4, &(0x7f0000000280)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000300)=ANY=[@ANYBLOB="11"], 0x11}, 0x0)
unveil(&(0x7f0000000000)='./file0\x00', &(0x7f0000000080)='x\x00')
open(&(0x7f00000001c0)='./file0\x00', 0x0, 0x0)


fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xffffffffffffffff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x1, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0x2a, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r0, 0x0, 0x0)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "0100012d29fb00"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x59}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85baa97981056ef1043f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0x9, &(0x7f0000000340)="0a000000f0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000240)=[{0x15}, {0x1d}, {0x8106}]})
syz_emit_ethernet(0x3e, &(0x7f0000000140)=ANY=[])


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080))
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x1, 0x4)
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x159}})
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = socket(0x800000018, 0x1, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "1a1116f0d0f700"})
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


socket(0x2, 0x2, 0x0)
r0 = socket(0x18, 0x2, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001600)={0x0, 0x0, 0x0, 0x0, &(0x7f0000002c40)=ANY=[@ANYBLOB="10000000ffff000001"], 0x10}, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
openat(0xffffffffffffff9c, &(0x7f0000000140)='./file0\x00', 0x200, 0x0)
r3 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x53e, r3)
r4 = dup2(r2, r0)
recvmsg(r4, &(0x7f0000000280)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000240)=""/11, 0xb}, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
sendmmsg(r1, &(0x7f0000001600)={0x0}, 0x10, 0x0)
select(0x40, &(0x7f0000000000)={0x6, 0x0, 0xfffffffffffffff9, 0x3, 0x0, 0x3, 0x0, 0x401}, 0x0, 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x100, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
r5 = openat$wsdisplay(0xffffffffffffff9c, &(0x7f0000000000), 0x20000, 0x0)
ioctl$WSDISPLAYIO_SMODE(r5, 0x8004574c, &(0x7f0000000040))
ioctl$VT_GETACTIVE(r5, 0x40047607, &(0x7f0000000080))
r6 = openat$wsdisplay(0xffffffffffffff9c, &(0x7f00000000c0), 0x20000, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(r6, 0x80085762, &(0x7f0000000100)={0x3, 0x2})
r7 = accept$inet6(0xffffffffffffff9c, 0x0, &(0x7f0000000140))
accept$inet6(r7, 0x0, &(0x7f0000000180))
preadv(r5, &(0x7f0000000680)=[{&(0x7f00000001c0)=""/112, 0x70}, {&(0x7f0000000240)=""/205, 0xcd}, {&(0x7f0000000340)=""/18, 0x12}, {&(0x7f0000000380)=""/231, 0xe7}, {&(0x7f0000000480)=""/200, 0xc8}, {&(0x7f0000000580)=""/222, 0xde}], 0x6, 0x1000)
ioctl$WSDISPLAYIO_SMODE(r5, 0x8004574c, &(0x7f0000000700)=0x2)
sysctl$hw(&(0x7f0000000740)={0x6, 0x3}, 0x2, &(0x7f0000000780)="e9b407fe1b18eb5af42b5cf0f0734339f6035d5a2eae38307cb705dc8dad8b4644c118631f0baf28ef30db7d5058e8d06046eaca7a34c87d444ed2bbd908dbc6f84533e95a507e1b18631803e948033d35d1c775f3b49895bdf7f657e9f91a4e846b56e364136e087f2c2515c811cd70305a8aa8dce8a4c94d7116c8780246dddeee0693b33ebe", &(0x7f0000000840)=0x87, &(0x7f0000000880), 0x0)
r8 = msgget(0x0, 0x10)
msgctl$IPC_RMID(r8, 0x0)
mmap(&(0x7f0000ffd000/0x2000)=nil, 0x2000, 0x4, 0x10, r7, 0x1)
r9 = semget$private(0x0, 0x4, 0x48)
semctl$GETALL(r9, 0x0, 0x6, &(0x7f0000000940)=""/135)
mknod(&(0x7f0000000a00)='./file0\x00', 0x2, 0x5)


r0 = socket(0x18, 0x3, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x4, &(0x7f0000000000), &(0x7f0000000080)=0x4)


sysctl$kern(&(0x7f00000000c0), 0x2, 0x0, 0x0, 0x0, 0x0)
pipe(&(0x7f0000000080)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$FIOSETOWN(r0, 0x8004667c, &(0x7f00000000c0))


connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendmsg(0xffffffffffffffff, &(0x7f0000000380)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)
r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x40)
writev(r0, &(0x7f0000000100)=[{&(0x7f0000000280)='#!', 0x2}], 0x1)
write(r0, &(0x7f00000006c0)="24a608d334f68b1f26da3fb9a1e5e89f23bf1309400000000000006745b653695b5e8e0010000000000000413fb5df308cefae50ffca562eb77b6a0a", 0x3c)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
socket$unix(0x1, 0x5, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000003c0)={'tap', 0x0})
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x802069db, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, &(0x7f0000000000)="9b1809ffff", 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
socket(0x0, 0x0, 0x0)
r1 = socket(0x2, 0x2, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000340)=[{&(0x7f00000002c0)="b1cdd4f7095175b8411cbe657d59d93930e354e09bc5012b3a4aa2841081626f138cddd0ac1792e4c7cecbcb827f7b20", 0x30}, {&(0x7f0000000300)="58039b918ae5a84e49283c7446882669c4d5fdc1ac2d0627b18bf14c5f2698ad1d54e4e8fa8ea837c0b2f70d88a55201063fbd2f72ad23cd7aea58ef1b33", 0x3e}], 0x10000000000001c0)
ftruncate(0xffffffffffffffff, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x1, &(0x7f0000000080)="0315f1d89ec5a317a9357682", 0xc)
socket(0x18, 0x2, 0x0)
open$dir(0x0, 0x0, 0x40)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
connect$unix(r1, &(0x7f0000000000), 0x10)
write(r1, &(0x7f00000000c0)="6bbc4044635cdfa0130442359ce30f1d6397d3e99e3a21cac54252de3f31068e94599964f0992fc4f57a21f3e43840110c5aedadf534eb754e43cfefbf30d1873b41d1b6db5ac9b567031f5f94e299e42815a09a0b895be4e6fbe32bbcc6eb773fd30096f35767d120948e67b7183f75f955cebe0ab31be9a3471867737ede7592cb85a0a3fa080000009b265adc3f46c7a4790853cbcce224abc7b30926aef1d2c9497b96374901fd3f0fa136327cedf27ab77a7bd690a931e870d6576296ea83f54541af73092ebe7575a3899854202d3ae7ed09d9cb3895d29f8722ad1fc4315f2c7a83cfba586bf6cf2b232222ba0315879fcc0c5c729cbafa39551ad6d7bf1fe58fefee90cd34bebbc4ba6faf759e1647ee8384574e91bb29d971700c1f0f2b3a27263a73328833bd4bc5577fd4521ff3ce1257081533ede709c175acf59272ef759399e20f7f3ebedcdb6485ae8b72228ef2a8172601ce45147783ee8e31631baab0f9836486f8e0acb23c55df91", 0x171)


munmap(&(0x7f00007ff000/0x800000)=nil, 0x800000)
connect$unix(0xffffffffffffff9c, &(0x7f0000000000), 0x1)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
socket(0x0, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket$inet(0x2, 0x3, 0x0)
getsockopt(r0, 0x0, 0x20, 0x0, 0x0)
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
kqueue()
open(&(0x7f0000000180)='./file0\x00', 0x200, 0x0)
kqueue()
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
r2 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x4000073a, r2)
select(0x40, &(0x7f0000000000), &(0x7f0000000040)={0x3f}, 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
r3 = open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
ioctl$TIOCGETA(r3, 0x402c7413, &(0x7f0000000280))
connect$unix(0xffffffffffffffff, &(0x7f0000000000), 0x10)


openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
msgctl$IPC_SET(0x0, 0x1, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x2, &(0x7f0000000040)=[{0x28, 0x0, 0x0, 0x3f}, {0x6}]})
syz_emit_ethernet(0x40, &(0x7f0000000180)=ANY=[])


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
socket(0x18, 0x2, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f0000000080)=""/51, 0x33}], 0x1000000000000036)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1800000029"], 0x3e}, 0x0)
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)


socket(0x0, 0x0, 0x0)
socket(0x2, 0x2, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000003c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000240)=[{0x4d}, {0x1c}, {0x206}]})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r2, 0x81206919, &(0x7f0000000100))
ioctl$BIOCGHDRCMPLT(0xffffffffffffffff, 0x40044274, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
r3 = socket(0x0, 0x1, 0x0)
setsockopt(r3, 0x1000000029, 0xc, &(0x7f0000000000), 0x0)
setsockopt(r3, 0x1000000029, 0x0, &(0x7f0000000040), 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000280)={0x2, &(0x7f0000000000)=[{0x1c, 0x0, 0x1f}, {0x6}]})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
semctl$GETNCNT(0x0, 0x0, 0x3, &(0x7f0000000240)=""/65)
bind(0xffffffffffffffff, &(0x7f0000000240)=@in6={0x18, 0x2}, 0xc)


setrlimit(0x8, &(0x7f0000000040)={0x7, 0x9})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(0xffffffffffffffff, &(0x7f0000000800)=[{&(0x7f0000000140)='4', 0x1}], 0x1)
writev(r0, &(0x7f0000000580)=[{&(0x7f0000000080)="6fcba96e64d77dfe77d06091c8341acb34f68c0a", 0x14}], 0x1)
readv(r1, &(0x7f0000000600), 0x10000000000002a5)


socket(0x2, 0x3, 0x0)
kqueue()
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff})
kevent(0xffffffffffffffff, &(0x7f0000000140)=[{{r0}, 0xfffffffffffffffe, 0x2c5d36d679bbffbf}], 0x0, 0x0, 0x0, 0x0)
kqueue()
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000))
r1 = kqueue()
kevent(r1, &(0x7f0000000140), 0xe4a, 0x0, 0x0, 0x0)
kevent(r1, 0x0, 0x0, &(0x7f0000000280), 0x9, 0x0)
r2 = kqueue()
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x1000, 0x0)
open$dir(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
accept(0xffffffffffffffff, &(0x7f0000000800)=@in6, &(0x7f0000000280)=0xc)
kevent(r2, &(0x7f0000000080), 0xe4a, 0x0, 0xa9fa, 0x0)
kevent(r2, 0x0, 0x0, &(0x7f00000001c0), 0x9, 0x0)


sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f00000001c0)="55f8f5782087a072a82ec35f78d14780f518", 0x12)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc1206949, &(0x7f00000001c0))


open$dir(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000080)='./file0\x00', 0x0, 0x40000530, r0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
sendmmsg(r2, &(0x7f0000000000)={0x0}, 0xfffffe32, 0x0)
recvmsg(r1, &(0x7f0000000100)={0x0, 0x0, &(0x7f00000000c0)=[{&(0x7f0000000280)=""/69, 0x45}], 0x1, 0x0}, 0x0)


mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x205318)
open(&(0x7f00000000c0)='./bus\x00', 0x2, 0x0)
open(&(0x7f0000000300)='./bus\x00', 0x292, 0x0)


kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0xffffffffffffffff}], 0x0, 0x0, 0x0, 0x0)
r0 = socket(0x800000018, 0x1, 0x0)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
getsockname(r0, 0x0, &(0x7f00000016c0))


socket(0x11, 0x3, 0x0)
r0 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = kqueue()
kevent(r2, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
ioctl$FIONREAD(r0, 0xc020691b, &(0x7f0000000200))
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
r3 = getpid()
ktrace(&(0x7f0000001d40)='./file0\x00', 0x0, 0x1720, r3)
clock_getres(0x0, &(0x7f0000000280))
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000240)={{0x8001, 0xffffffffffffffff, 0x0, 0xffffffffffffffff, 0x0, 0x40, 0x2}, 0x0, 0x9})
chown(0x0, 0x0, 0x0)


sysctl$hw(&(0x7f0000000500)={0x6, 0x1c}, 0x2, &(0x7f0000000000)="1c", &(0x7f0000000580)=0x1, 0x0, 0x0)


mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
chroot(&(0x7f0000000100)='./file0/file0\x00')
rename(&(0x7f00000001c0)='./file0/file0/..\x00', &(0x7f0000000280)='./file1\x00')


open(&(0x7f0000000140)='./file0\x00', 0xf8e, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000240)={<r0=>0x0}, 0xc)
ktrace(&(0x7f0000000200)='./file1\x00', 0x0, 0x40000730, 0x0)
setpgid(0x0, r0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000200))
ioctl$TIOCSETD(0xffffffffffffffff, 0x8004741b, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r1 = open$dir(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f00000000c0)={0x0, 0x0, 0xfffffffe, 0x0, "031ffe40630000000000ff00010400"})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
r2 = socket(0x18, 0x3, 0x0)
close(r2)
r3 = socket(0x800000018, 0x2, 0x0)
ioctl$TIOCSETA(0xffffffffffffff9c, 0x802c7414, &(0x7f0000000080)={0x4, 0x0, 0x0, 0x1000, "1a05227955686f43a3207fae5d1404c9a4c0a24f", 0x0, 0xfffffffd})
setsockopt$sock_int(r3, 0xffff, 0x1000, &(0x7f0000000100)=0x7, 0x4)
bind$unix(r3, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r4 = dup2(r2, r1)
sendmsg$unix(r4, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000004c0)=[{0x34, 0x0, 0x0, 0x267}, {0x44, 0x0, 0x0, 0x2}, {0x8306, 0x0, 0x0, 0x2}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000380)=[{0x3d}, {0x24}, {0x406}]})
syz_emit_ethernet(0x138, &(0x7f0000000040)=ANY=[])


sysctl$hw(&(0x7f0000000000)={0x6, 0x11}, 0x2, 0x0, 0x0, &(0x7f0000000240), 0x0)
mprotect(&(0x7f00003fe000/0xc00000)=nil, 0xc00000, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x205b1a)
open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)
r0 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r0, 0x6, 0x2, 0x0, 0x0)
connect(r0, &(0x7f0000000040)=@in={0x2, 0x3}, 0xc)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x1}, {0x87}, {0x6, 0x20, 0x0, 0x8}]})
syz_emit_ethernet(0x26, &(0x7f0000000280)=ANY=[])
shmctl$IPC_SET(0x0, 0x1, 0x0)
socketpair(0x18, 0x0, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ioctl$DIOCMAP(0xffffffffffffffff, 0xc0106477, 0x0)
mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x0)
mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0\x00', &(0x7f0000001380)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000480)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
r2 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0x2, 0x9}, 0x2, 0x0, 0x0, 0xffffffffffffffff, 0x4)
symlinkat(&(0x7f0000000040)='./file0\x00', r2, &(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f0000000000)='./file0\x00', r2, &(0x7f0000000200)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
unlink(&(0x7f0000000700)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


setrlimit(0x8, &(0x7f0000000980)={0x46, 0x56})
r0 = syz_open_pts()
close(r0)
pipe(&(0x7f0000000100)={<r1=>0xffffffffffffffff})
close(r1)
r2 = kqueue()
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f00000006c0)=[{{r0}, 0xfffffffffffffffe, 0x3}], 0x0, 0x0)
kevent(r2, &(0x7f0000000340)=[{{r0}, 0xfffffffffffffffe, 0x1b}], 0x203, 0x0, 0xfffffffd, 0x0)


r0 = open(&(0x7f0000000140)='./file0\x00', 0x78e, 0x0)
getpid()
mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chdir(&(0x7f0000000140)='./file0\x00')
setreuid(0xee00, 0x0)
mkdir(&(0x7f0000000040)='./file0\x00', 0x5c)
chdir(&(0x7f0000000380)='./file0\x00')
r1 = getuid()
mkdir(&(0x7f0000000100)='./file0\x00', 0x0)
setreuid(0xee00, r1)
unveil(&(0x7f0000000280)='./file0\x00', &(0x7f0000000080)='x\x00')
unveil(&(0x7f00000000c0)='./bus\x00', &(0x7f00000001c0)='c\x00')
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000240)={0x0, 0x0, 0x0}, 0x0)


ioctl$TIOCSTSTAMP(0xffffffffffffffff, 0x8008745a, &(0x7f0000000000)={0xffffffff})
r0 = socket(0x11, 0x3, 0x0)
setsockopt(r0, 0x11, 0x3, &(0x7f0000000000), 0x4)


mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x1e5f)
r0 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000002ac0)='./file0\x00', 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f00000001c0)={0x0, 0x0, 0x0})


r0 = openat$klog(0xffffffffffffff9c, &(0x7f0000000000), 0x20, 0x0)
writev(r0, &(0x7f0000000380)=[{0x0}, {&(0x7f0000000180)="4e05e21ba9a8b37d2eadb856314705e3fa2a4e637f03b778305f1d93db8108a69b152867ba61596edeb90ee29a0ec2a170ab7bdc1da1438776304959ccca092a9331aa719680564b37f9ceb4bbfb238a597cc879fe2b0e981b700a412089e231c5e2b0c3e1728e57e0658069cb032f2806f9f74eec1cf47417a377388eff980172c7fb45790b8c5c2a0696885bcae2e82912cab84dec5f7e8e0ab920004362d559a968c36acf63a61313430037e41fb99e9940e0f4851587a5224411b3612e860b83b2d67413798ae2b887fc47ce6556e9a25c2d5ccecd0f", 0xd8}, {&(0x7f0000000280)="bae42d1bb92acff39a56165cb5bf9f2eabe183711712e0203f16af230e11fc977d8295c5e527c89d4fd3365082e3839b5772c5bd37fad0760f009e4128278cb6580981ddb017c3f123f38f9244731d68d0ba93b4", 0x54}], 0x3)
openat$wskbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
r1 = openat$tty(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$TIOCMBIS(0xffffffffffffffff, 0x8004746c, 0x0)
pwritev(r0, &(0x7f00000018c0)=[{&(0x7f00000006c0)}, {&(0x7f00000007c0)="fe03ebbdda29ba8904983ed4f731e51c4d69f57bfa4611f5b53acb10e8e236ba54225162b1480433ce797bea9d8e842d44904c043dc911d125036cfa715f8832dad63a3c719e6a9130b98142b7329b44611cc6caf75b17ff6c2df857aba60f744506eb886bd7082eb37e61d6c64b77ef2c5e80a84c4d8a2e6b7ac1d6a48a0072f1b04027e7fa69f4481e66e90f2499deea0b21e013bfc1a79e5380cc56cfc617db8510d20395c1ad44a8c3b02b48142ee9e252729f14a5ac965950d7e45a14cffc019f0b0d7f5e477e5717d055079b0727f1c8aadf22", 0xd6}, {&(0x7f00000008c0)="e15d98a2de2c2653612a7b677764423cb877dbd3ee7399e3b76a36d2b7ac5872a0b9554cd4508ec8ca84bde9085f67e436f7ba1cfe22e535ccb070393b4dea4fef4861eb3e4f27aed948709d835d4101f6a18b4c79f7dcd06fe8330fca87b646827e0f0f2bfe307be26250c140b09fc2c19010a2aa9d6d721cc68d32bde4905279193b1db585fb2aaeef949870783517e0cac6de01e13d26bc455b5a5173262a9181ae4d580362d441b31735602451fb1dd29c59c0fdd446fb20942536275f2c252a1e2bb0523b0d8f0194c432db07a8caf08f7a1ff631f708c8f3c4f20e0ce6d32eee63ef98eba81103fdaccedd47d61acdf8771f4072253adf097c82b342521a02655bb09407c3285bd7508f96c473b88a37d18e4e24ef05fd0f317d28ff1709f0a207a7855cc4271faae46eeac43ca0d570a3273ca182166419a677dbd60fe8d4d5c7cc9d47e8bee3d59896e14184f6def038e5b5fd233a3b65ba22727b528f6e23b1608ee0c95914cb9b1746059b48ddab0b61399a5c207738a172571a7cc0c47cce7dd358f676b405622aeec9ac9fe30eb617fc97f1dfe9baa58153afef6b021c288f4ae571f535c145f8e0f7546f21ceb28a221433f9441f12a7bfad83d6f40cd9ca5e676577b4a2d6dc69c2a48e42f0e8230c6a3a79bcf9ec70d8ea7beed1db18e5f6fe60aa872aca8a3e85fb1332af96af3c231a138cc5d35059deb9c8ca0e1f5e1aa9666d5946f28ba64c213d2624456e6f56ae627cdca4a75e5cdc4f3e9a09d4240fd233adc0bf5dc53c2d00eb4314a6bc2b085b817081c8c9ff9439a1757bb0a69be9006d7ceafb7e77de37da9d7fa7ee7744a7b624eb0b447622e18f80cf650c095e4eb6a2dd1e64ae33ca6b411225fa7197338fe782476fb8a6559e2a805bef0164e1de614100d93c50747be07af1620824a7e7ee40b0143eb9f400ce4c053eaa703950863d02c254a691f74f95206c1b555928448bcdae2679d27e31fab0bb9df7954a055fc346816e14e797b67738d1832b04e760bb6cbb3bbdc95fa66e1e3618290e556a64a6efca46b4afddf9231cbba505e17c3db069167dc2800899111064cd2bc125f7a255fc8b6423ce1d3361a587017f7c19ead3724c5c51d498a97ce5aff6400e7fae0727ccdfb8baff051b189b2771b3cd69ac105cee4e32ad91643c0c582d3e5f0fa01961321894bb23ccd6c90aeafe9d3ed192e09d354d14aeb29fa07e07b481cfb82ead18600f1d8afb0e5c5de71f061e7bb7246c72e99881be99b6de74566d0cac597bc54151bdfd7218c9fa84d81dd7e925254943ad17384bc6087c808521f1993597e539b4020362e5ac9f0aa9b07d15e415b5a8b0240035746a25c35cd2d34a6e577e8a92334b17bd6eceeb78b7ddc3423290b51489cf2f47383066114e84195a1ecc8077a2050f1601e3b3d6bd14955bcd63dd3f27df9411f0674bda5c3504d9384b750a2aae4509a8ed3d68e5a5262bf1973eee2c8498d8592ad85be6db8f61b43d4574e102e4f6a2a8e2b1e7692af5f9a8f79eb0fe65c69fc6f2fcf15364bf430c85fe6fd0ab77c9d22b7e973dc868e36f5177af658a39300ffc75a5ea600eb804e3a3bd6a5c141b7c22ae13deab076c482235342d5c2fbc1d1d44e5434c7ca3678118a5c38a191a265f3c1f6ca0e6fbf041f2f858e7738646e5805695b521ffc2c9eb9b8f7df37d2d678bc998147bc418b49ec00c61b19b4e7d290e5eb1df4f56c7cdaa9598690451a70bcc8a799f0c81fee68235b0f89ccf0fec51f42e37be130ba77791f4d62f267116268d3d0d5bed1986b64d7649668821b59812bb27521df8fdac4234ed3a35f2188882aed757694525c6c8a6db54ae4d00af66133a13884eb527fd08c4dc418a93c8a1174c2b14e3b393171b0d05f7134757d63470aaa985f1c1ccb90bcb81422fac5b69e281c3141f10803579a38bf72320ec3954cc073d6faa100a113baf8c1660785cac6b0ad97c4d3a500b0b5c8ba25c1b0678e72502223a5045f8572ed0eaae9153a96bf29a2faa0a0096724865be4cbf8601181485fc16c42eb07d704583be282796be340fde994e2e1d7184e2e95b81c7c2942528d228bc1bbe0f836e83478a16d54cc1405f4f692e4e4778a7151778e4f4644ed3bbe3f44d79f320a82cc33b1a538102c023dfc358fd52afab9208bfc2d5f295a11b89183222e97131d233aef6d0dcfbcd1dfde1b79e12fe92c4ecd2f10655e2fc7871dd8614a93f2605de73a846cbc99cd785564540f54353d918e2fc3618ac8b85b9a32e1df1b8cdd05ced3202d487e9add055deaa72165b9e64b134a22df7ce3fce5689dd67e0f4ddc846182bec0bf66af343e8643b140a73f2efd911e9b07fba7f3131f2b4ed0d720b8610ff20dec3b221a016e5be492ac23d135196b6f1f009ff5682c9689ec6fcfc15286a706a8b3462a0fe5ec07ae6ea6d1f37e09ba2d8cd48f562499a9432f5c70789340ab65a5cff85ebd7db2cc854c79406b93dcddae622d9834975a7b5c782b75fdfe5a541cb14ca67d4c0d8a0fec1795c19154aed5cb25db6d52bba3a752b1c3a87eda7336128ebc9ce71679a3f30e48e4627a4c977b2964bbbf0ba095e4f6571fe8754c87ead21d622e4b92b78fa0caa6759d77014697a2c7467665a796656ef5823313241d32fed95a5136e66e31715851fcd8595ef054318df652fe32113888c0b731c94077432dd8cb5e1a343dc812bb33ac01d68fb08c5a5c6a7d3140a3c0525cc6312d29a3f36e9c835654940f7bba8a6cf857fdbace2660078d71da7f5d35acb11018935d0255460c2e6e93669f472aed936446db23a0d4c914762c9cba2ea741e250799016ea525368f10cd7f71590dd895ad457e4206ab1776e51a3e72acd7fd85f02370f591da65018708b977f46aa25790437be444055b5f26e90f1b4e252986aae07a28590da396f7f2dfcfad157a5c1d43a9d851e0eae2c947bada07680319e1e1e4923498cf21d7345ad64d5a0fab72fb9bc9438de5efb4145f2b691afa50d7c1787e2313f96239292be2edc54dbc5a0552d606d7e5a114dae7f181ecea8377a7a35617722a1bb61319de6e08eb8e718d89db1db2bbbf17ec224cf550124673ad3cfe09f89fc0b5114055b1b1521cb501b731eeb69991527c42cb439153a0da5e851ff8c29edd88524922ca280ae05713133805493d8a2c026155006818cd7a2dd1ed4e18bf83373cdab552692f9d57388bb65cb398421521cda04f1dc0fa36c32a3c8b316e548937b1f4639ce1fcdc72edd99357d76217af732ae27f9e04f88fa23b5f2befc97e5dc9aabd26f2727c0d2a15bd8b036a9d8126ea85077279e2091b84051934b176d001f7a8e24e26f2642a5a39e95f51d836143f7b8f262476dacf5ca2e48ba768102d74765676adad8d97a3385e88247f74b0198a212775a824d3c43da1171685a2200f964a649c19c262941120d07a812711a132368699b047b06e95492bb5cbc1537b2465647bc09f22a46463720516a5696487e3f2264ca2965d445d1c7ca867016198c82643a61e77658528a5c0f111de5595e7bc125489f19feee6ed8167ae2e148fc08580c983f377b4f6ecd48e73410082b57c0138966f747f9118e1820ddc75461fa240d5e2a5903d04088cfc7e0a0bbf759e6a32ac97423a553ec19880a4e5d8bcb6e271aac9b088f07252924a00b41fdc4cf90b7e7bd03af31b13381df280f75e9d1fbf614c21301c8f1accb443adcfa5673f496359bb349febe65a92ad08a91ee7b667f1be1461fe43b290782c7c99a0dc218d27b6f0b1dcf47f175e435d2e047e44b951fd25a52883e15e407d28779964457dfe54972ce141a7aedcfd5ffc42e2f9944c11f3fb7b38dfc92aedbc961eb53b3d381e46b75ec5ac2f41885729d4a04d2b9f799d352afe31579059834e824b9dea4a748ed7af445cd30bf04d5d81752e9fde650f52a9a6046d89fa2364a206f92e0581fc7053b6a2e6cec8f2b2d5d23103efc85e2b18226b5ec5d81f0699c07d9e5a029e52dce291de45a1d533c955f57e45e59d8b78e06bc3f9d6a44df1893110439818c94874a98e6d00521e4f79a3329635d784d336303405bd419eb758d3e2e99dd8529e7119517ea8a64ab0a243b2373ced130c010296cdbc90874723df45092d1e3f51c7c2105a23eaa28c12592eb83d737cb44692013e48c965a17e614ed4d6023ed9daf9b15f38250bc6c056a9a8588e808c331addc21c79ee226659d363a8b4d78722a1f0f79e64120ccc62c9d4dc57a43f834420df5a1278504a4871ff64b73f4c4184d4789fefceb21f64604dde86afa72ac683e5ac2384e41a26764f4cfa587e5e71c5c1051f88c91dc79950aae65fe259cd484f324fd6a5fb1fd49a4d0dbb4895cad2602771e82ddc669c15c087c6f89cd3a3bd9a37bcf0dcaa7f70e4d38478f94719f10e6664d37252b404ba4c0eb51d021dcf6e82089a50b13aa10bb4689cb5b93e117b036140f82eb6887adbdc5b2a6d975c8a681ce81bd4f04a79764351cd99833ab2944c3e2a95890fb9b50eb2a35a0d100e42c6ef861dd7a988776797c77faff3be402702c03dc29af6061ecef4a7aef50d07cb72050ab903638d2d6c728dac8bcac598d6d8ce4b927709b21b3ab3191d743804ef2d598a80c58e3399bf9aa3643d8917f695039a6e2409e0c22d9fc451a0178932f89d62b5e40a67f14fd9a28144a86567ddaf7287434875905d289bb37d9b3d3e055bffb7976144258e880fd0a65c2477f227bf4e378237b979ec5b2be376f433cbc7b011a498370b546fde930af8b8321e7c88e47f37", 0xd58}], 0x3, 0x0)
pwrite(0xffffffffffffffff, 0x0, 0x0, 0x0)
r2 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000001a80), 0x0, 0x0)
ioctl$TIOCCDTR(0xffffffffffffffff, 0x20007478)
ioctl$TIOCSETAW(0xffffffffffffffff, 0x802c7415, &(0x7f0000001b00)={0x82, 0xffff2ddd, 0x0, 0x0, "0a6189a51a41d2e1e70260b1230358cfd143af68", 0xfffff346, 0x80000001})
getpeername$inet(r2, &(0x7f0000001b40), &(0x7f0000001b80)=0xc)
ioctl$TIOCCDTR(r1, 0x20007478)
execve(&(0x7f0000001bc0)='./file1\x00', &(0x7f0000001cc0)=[&(0x7f0000001c00)='+$}@\x00', &(0x7f0000001c40)='/dev/wsmouse\x00', &(0x7f0000001c80)=':\x00'], 0x0)
truncate(0x0, 0x0)
ioctl$TIOCCLRVERAUTH(0xffffffffffffffff, 0x2000741d)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x0, 0x0)
r3 = open(0x0, 0x0, 0x0)
fcntl$getown(r2, 0x5)
ioctl$BIOCGRTIMEOUT(r3, 0x4010426e, &(0x7f0000002580))
sysctl$vm(0x0, 0x0, 0x0, 0x0, &(0x7f0000002700)="333c924beebcbcb1fe74f5fa8136afb8b4ba045d187a608b8ae0c60607e9dcc8fa8827a99d27ebf2a0e8d2b46036d535b96974d9240a1515231851733cff8abcac6ce197a60687c896304e2c8c94b8a02a075b9d71463189530445707683aa51a043a6d79e1fcc65de70c80cf86d84616c4ad50a42fcdfd8fe0abe56406926c408c211853a8e70b7ea1a047200fbbf26ff9fdf626a4c32b7556ae81935f01f8874dfc663a4423110f0b82508a9a6e044821fba0a23b8708e7930193457838a9f30b3967975c8d88e7ab5e25695fc248190ad68af7a32997f2d22e169a00f9be26adc925454aba4a0af717580dee70db4587cc11820c60811", 0xf8)
sysctl$net_inet_tcp(&(0x7f0000002800), 0x4, 0x0, 0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
shmget$private(0x0, 0x1000, 0x0, &(0x7f0000fff000/0x1000)=nil)
sysctl$vm_swapencrypt(&(0x7f0000002a40)={0x2, 0x5, 0x1}, 0x3, &(0x7f0000002a80), 0x0, 0x0, 0x0)
socket(0x2, 0x0, 0x4)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ioctl$TIOCSTSTAMP(0xffffffffffffffff, 0x8008745a, &(0x7f0000000000)={0xffffffff})
r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
ioctl$WSKBDIO_SETKEYREPEAT(r0, 0x800c5707, &(0x7f00000000c0))
r1 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r1, 0x8040691a, &(0x7f00000001c0))
openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0x0, 0x0, 0xffffffffffffffff}, 0xffffffffffffffff})
r2 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r2, 0x8040691a, &(0x7f00000001c0))
r3 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40001144, r3)
select(0x2, 0x0, &(0x7f0000000040), &(0x7f0000000080), &(0x7f00000000c0))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x3c, &(0x7f0000000040)="01000000", 0x4)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x1, &(0x7f0000000140)=[{0x40}]})
r1 = socket(0x18, 0x2, 0x0)
close(r1)
r2 = socket(0x800000018, 0x2, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
writev(r1, &(0x7f00000004c0)=[{0x0}], 0x1)


r0 = open(&(0x7f0000000140)='./file0\x00', 0x78e, 0x0)
r1 = getpid()
ktrace(&(0x7f0000001d40)='./file0\x00', 0x0, 0x1720, r1)
fcntl$lock(r0, 0x7, &(0x7f0000000040))


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
setreuid(0xee00, 0x0)
r0 = getuid()
chown(&(0x7f0000000180)='./file0\x00', r0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000200)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000240)=0xc)
setregid(0xffffffffffffffff, r2)
setgroups(0x0, 0x0)
symlink(&(0x7f0000000340)='./file0/file1\x00', &(0x7f0000000380)='./file0/file1\x00')
r3 = getuid()
setreuid(0x0, r3)
chmod(&(0x7f0000000080)='./file0\x00', 0x2ea)
rename(&(0x7f00000003c0)='./file0/file1\x00', &(0x7f0000000400)='./file0\x00')


r0 = getuid()
socketpair(0x18, 0x77f8a78fd4eac7e4, 0x4, &(0x7f0000000040)={<r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f00000000c0), &(0x7f0000000100)=0xc)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0x0, 0x0, r0, 0xffffffffffffffff}, 0xf8ffffffffffffff})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
mknod(&(0x7f0000000000)='./bus\x00', 0x3a0914c44f7b202d, 0x504)
lseek(0xffffffffffffffff, 0x0, 0x0)
r2 = socket(0x1, 0x3, 0x3)
sendto$unix(r2, &(0x7f0000000000)="b1000501600000000000000007000000330002000000000000f96ecfc72fd3357ae320b37b673039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa5b236de351e2f0ac3ebbc257699a5f139b672f4d335d223e7d026ba8af630037282102000000720fd38bfbb770c1f5a872c881ea6e69e0bb76d907c400000000361b1257aea8c500002002fbff0c2300008abfba0900000008e371a3f8343712051eadb71d89e000040781e4b20b0001000020a254a14ce81f0cade4599523db09aef52411cf9886f289e93477356a40880349ff2bc46fa7a9abeecab40b254ccc72c07d97f045e3192f45bbd4279ca9edee5d28", 0xf3, 0x404, 0x0, 0x0)
open(0x0, 0x0, 0x2)
execve(0x0, 0x0, 0x0)
recvmsg(r2, 0x0, 0x1842)
writev(0xffffffffffffffff, 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x40000802)
r3 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSBRK(r3, 0x2000747b)
r4 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r4, 0x8040691a, &(0x7f00000001c0))


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x123}})
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ff7000/0x3000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000604000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f000068f000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000691000/0x2000)=nil, &(0x7f0000ff8000/0x4000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil}], './file0\x00'})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000300)=[{0xb1}, {0x3c}, {0x812e}]})
open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0x0, r0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x8020691f, &(0x7f00000001c0))


sysctl$kern(&(0x7f0000000240)={0x1, 0x16}, 0x2, &(0x7f0000000500), 0x0, &(0x7f0000000640), 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x8020699b, &(0x7f00000001c0))


r0 = kqueue()
kevent(r0, &(0x7f0000000080)=[{{}, 0xfffffffffffffff9, 0x1b}], 0x1, 0x0, 0x0, 0x0)
kevent(r0, &(0x7f0000000280)=[{{}, 0xfffffffffffffff9, 0x9c}], 0x4, 0x0, 0x7fffffff, 0x0)


r0 = open(&(0x7f0000000180)='./file0\x00', 0x70e, 0x0)
writev(r0, &(0x7f0000000240)=[{&(0x7f0000000040)='#', 0x1}], 0x1)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x3, 0x10, r0, 0x0)
r1 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
writev(r1, &(0x7f00000002c0)=[{&(0x7f0000000300)='#', 0x100000}], 0x1)
madvise(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x6)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x15}, {0x7}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000200)=ANY=[])


setuid(0xffffffffffffffff)
r0 = syz_open_pts()
ioctl$TIOCSPGRP(r0, 0x40047477, 0x0)
setreuid(0xee00, 0x0)
r1 = semget$private(0x0, 0x4000000009, 0x82)
semop(r1, &(0x7f0000000680)=[{0x2, 0x9, 0x1800}], 0x1)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000900), &(0x7f0000000940)=0xc)
semctl$SETALL(r1, 0x0, 0x9, &(0x7f0000000400)=[0x7ff, 0xfffd])
r2 = geteuid()
semop(r1, &(0x7f0000000140)=[{0x4, 0x200}, {0x7}, {0x4, 0x9}, {0x3, 0x4, 0x1800}, {0x0, 0x5e0, 0x1000}, {0x2, 0x0, 0x1000}, {0x1, 0x9c, 0x1800}, {0x4, 0x6, 0x1000}, {0x0, 0x8001, 0x1000}], 0x9)
semop(r1, &(0x7f00000002c0)=[{0x0, 0x3, 0xc00}], 0x1)
r3 = getgid()
semctl$IPC_STAT(r1, 0x0, 0x2, &(0x7f0000000540)=""/163)
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f0000000600)={{0x7, 0x0, r3, r2, 0x0, 0xb2, 0x7}, 0x16, 0x400000000000009, 0x1})
semop(r1, &(0x7f00000001c0)=[{0x2, 0x7}, {0x3}, {0x0, 0x801, 0x800}], 0x3)
semop(r1, &(0x7f0000000180)=[{0x1, 0x1, 0x1000}, {0x3, 0x80}, {0x0, 0x4, 0x800}], 0x3)
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f0000000240)={{0x4, r2, 0x0, r2, r3, 0x20, 0x3800}, 0xfffffffffffffff7, 0x8, 0x81})
r4 = socket(0x20, 0x2, 0x0)
r5 = semget$private(0x0, 0x2, 0x621)
semctl$IPC_RMID(r5, 0x0, 0x0)
semop(r5, &(0x7f00000006c0)=[{0x4, 0x3f, 0x1800}, {0x4, 0xff, 0x1000}, {0x3, 0xe75, 0x800}, {0x4, 0xcc7, 0x400}, {0x2, 0x7f, 0x1c00}, {0x3, 0x0, 0x1000}, {0x1, 0x770}, {0x0, 0x23, 0x3000}, {0x1, 0x250, 0x1800}], 0x9)
bind$unix(r4, &(0x7f0000000080)=@abs={0x1f95d27d48731892}, 0x1c)
sendmsg$unix(r4, &(0x7f00000003c0)={&(0x7f0000000040)=@abs={0x1, 0x0, 0x0}, 0x8, &(0x7f0000000100)=[{&(0x7f0000000080)="9e3a0b440b39c6faaefd093d860c56b298d5d949e18293291b4c9887a2607fc093f365c0c59a4e87ed90e32ee5a430394a2558f1f4f94a63f06372ea74c33d06015b0d6cbeaa4be2b208bbf23f2a3ab647b2744fba0bb61c09ea27e01a6e6a4c14370c939f66", 0x66}, {&(0x7f0000000440)="20dc2029560b620988fcd683ba84fe1108a4a6045aba646a34aec5f3276e25d9904af94b4fb2fde80680999a3e3d4d9d553e40e1bdee16830807b6349f7761175b5282706be86af5d70137a913503c85c01986e5d07b7a8c0b5f455e032f2918c60176e6de1abac51a7ccc364a5fd1103fa839aab0d6574f568d9c186ce38f29ddd00022dc540ff0cf59de781c58b33ea6be34ab19e86f6542cb825a30a98a2f1d0e283b10ebd30d747d7658ef1629b9b79ed53e3b7f1883aff1ee06b34fdad06e84b2b8863c541bc1927b3bbcd50c42328d041ff2c7a89fc13570bf813c9887d3921f3ddc0170a7c83a1b6d462085f6f2bb870bd1d2", 0xf6}], 0x2, &(0x7f0000000700)=ANY=[@ANYRES32=r3, @ANYRESDEC=r2, @ANYRES64=r5, @ANYRES32=0xffffffffffffff9c, @ANYBLOB="2548ffe2ffff43163af973fc42f39267633b5783ff76e25cd3eab49b12d42fc045711969f4542b0adc52b291f6fcf6d000"/62], 0x20, 0x8}, 0x406)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000040)={{0x1, 0xffffffffffffffff, 0x0, 0x0, r3, 0x101, 0xad}, 0x10001, 0xfff, 0x9})
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, r3, 0xb2, 0x4}, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4})
r6 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r6, 0x0, 0x5, &(0x7f0000000000)="5d8ad1ae", 0x4)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000800)={&(0x7f0000000100)=@abs={0x0, 0x0, 0x0}, 0x8, &(0x7f0000000640)=[{&(0x7f0000000140)="60c15402f1743e6f110c6ea0ffc66f6950de2f808f608d3ca9deb71c0f69adeef6ecff1a58c248d4447d416ade6e79a58d05c7ca6bfd4bc912943120a218a65aa2273d07e91cde3be2017cb43b35d5a27ca333632eb823d9b83f7497fb53", 0x5e}, {&(0x7f00000001c0)="f20c812b0a4dcb9c4dec7f9bc4c18bae69af8d5217ac4caa60b1d0e8bdab1322f3a99cac6b183588e46fb6f1e7476de5c507108b3b5ecc6b8e73607a7a26db37811945d11bb506f80b699108641b6a15843e60a6fa268d5a68b404c40bfe5a24ebecf03cf737140c48b61d2f9e336aaf4ad4cc1424f2367d9c67f9bec7a77d1be9f066b2af349525918ea8846b299f24ba3df6deb65de5d7693ef517ee3832b1c66e937224e2704b14d55cdd96dc742beb79f2334376c85ca2fe", 0xba}, {&(0x7f0000000280)="59ec7702a09fb2cadb566805d42d72cad494abd12191fd15bea7b5cb0b805c1dbeb2", 0x22}, {&(0x7f00000002c0)="f5249ea56d6a268b67812acec336cdd1a1e1679966ac4498e2c690daf84e3ca4fa3ea96176c2f106f19a4eb7ecce5abd69f0dcdc03b2bdde6b42a569ae1c4c7253d8862118b3ea47c0f703ede7cd51ae07d105224dee", 0x56}, {&(0x7f0000000340)="9fe41bf9eb48ef101990d2d8a710e6506db2469d252596e982595ff848c71e9fcc5bcd8e52fbe68f7244fc8d172541eae5ce8d32389b5675ce948d9224a3244cfcf50e91c6a57b7c149278158b847311f15c18d8883deeef1690d97f16", 0x5d}, {&(0x7f00000003c0)="5c14183284c7f8fcec5774c5e5624416e9e392c87f33ee6bd20f68dfd57ee5cf8b8028543440ba4021ae72efb8d10a5e56f571cf6df78a4b", 0x38}, {&(0x7f0000000400)="b640302f7b0ecca07282051bce0fcc4e9b85adf6327197e10b531babb91144810fb9728f4338fd892e848acfc31520d7aa721ae597a835f92bd67ebd345acce60a547a0e155a483caed9ce74162b38b12180f427bdd9bc4af6b3e417de51235034ade40be9d89e5d8f0f0a589823af40054e6b28d4927487989c1eac1ec93d6a8b181ca8e1a47c6c019031a7c1f4d024fc453446ba648ee67cf8028838a71e90a6eec8f52aa790e1af25e23702e1e6c91577945916344462f357ceb607b7735fe4a4fee4ed8b17384f59a182c00acb97d18b80b8659d777e2eb6c3279ff612e5cf2e99670822e73db7b46b", 0xeb}, {&(0x7f0000000500)="092475278c9b146ebeead89e090cce6414e5ef8c20cbc925fd738db95d5e3dfbe46f1148cfd9b3e6376bc52cc0fcf9846db22504c4a30e20a9c992d1c2af1dddf3b4cd248fcf6dd91572b419fe7d02068ce9334d71080cba0122702d761e6fff35224e", 0x63}, {&(0x7f0000000580)="81df2fdce87ffa60722beae067ec8c7483db986e9a330ada3b7df790ba5b394c8d13a762935de1ac3affbd16ec4ae64def646d6cd6d44118ebc72ab32c7c1f0e42305b693b5b4d9b979ed1d3d7b923a08960ce3c03c86b5660bfc83743913588ed2d9578ae00d3ea09070433b88a10f1f8fb4f3d4e3c47dfd0978a4c06f58a4f51a0d2b55d75f08b05196ac4df99aa2085c16b05d1299c5299e3f3a0fcf570844cd7af1976520a", 0xa7}], 0x9, &(0x7f0000000700)=[@cred={0x20}, @cred={0x20}, @rights={0x30, 0xffff, 0x1, [0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff]}, @cred={0x20, 0xffff, 0x0, 0x0, 0x0, r3}, @rights={0x30, 0xffff, 0x1, [0xffffffffffffffff, 0xffffffffffffffff, r6, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff]}, @cred={0x20}], 0xe0, 0x9}, 0x8)
setuid(0x0)
syz_open_pts()


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff})
setsockopt$sock_int(r0, 0xffff, 0x2000, &(0x7f0000000080)=0x4, 0x4)
writev(r0, &(0x7f0000000100)=[{&(0x7f0000000580)="4534122cb25ac71eee676fa7ef79bfcd8421636cb079da6dffefb384603bdd6bdc6ba6b3916e87bf948e26f6c69b480188166bc6d6de481f66dab68c8548ccea9d0001f20887f575f96ae98678ae2888de940a83231e8d70349e01000000c6403f379a3b071f8c6b6143d2d7592d5faa82d078c66a1f19eaade9dc52ee8450555a9832016a20f25111547ccb78b4d62e75893e54883a1e2c8341281a2ff03bc7edfae48577550a9d3e39ebf25eea03d51d4858372c8c0bf9a064f46102c551c83ede09c06abfd3e017478d3e856b94e7bb6a59aa92d8e7ceb3e24181a5766e3ea1d29ece0ebc56491dd2345fc38355dab6", 0xfffffef9}], 0x1)


setrlimit(0x8, &(0x7f0000000980)={0x9, 0x51})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)
writev(r0, &(0x7f0000000040)=[{&(0x7f0000000240)="00fb", 0x2}], 0x1)
pwritev(0xffffffffffffffff, &(0x7f00000001c0)=[{&(0x7f0000000200)="18d26cb474b5c9d53e0ffdba8c54fecc9031509b1623088cc3e85353a5586603eebda7eccfc5ced62b70a12fbffc2425f3f9e50317605792ea906ef56376aa499b9a909aff511ad2d6", 0x49}], 0x1, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000080)="eaef125c00000000", 0x8)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0xd02)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x100, 0x0, 0x0)
r2 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
openat$pf(0xffffffffffffff9c, &(0x7f00000000c0), 0x80, 0x0)
connect$inet(r2, &(0x7f0000000000)={0x2, 0x0}, 0xc)


getsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
kqueue()
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x5, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x8981, 0x0)
openat$tty(0xffffffffffffff9c, &(0x7f0000000040), 0x80, 0x0)
ioctl$TIOCSETVERAUTH(0xffffffffffffffff, 0x8004741c, &(0x7f0000000080)=0x2)
r0 = semget$private(0x0, 0x1, 0x8a)
semctl$SETALL(r0, 0x0, 0x9, &(0x7f0000000680)=[0x9])
semop(r0, &(0x7f0000000140)=[{0x4, 0x200, 0x1000}, {0x4, 0x201, 0x1000}, {0x3, 0x1000}, {0x0, 0x7a5}, {0x3, 0xff72, 0x1000}, {0x1, 0xdb, 0x800}, {0x0, 0x0, 0x800}, {0x3, 0xa, 0x1000}], 0x8)
semctl$IPC_SET(r0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x26, 0x8}, 0xfffffffffffffffd, 0x2})
semctl$GETALL(r0, 0x0, 0x6, &(0x7f00000004c0)=""/195)
r1 = getuid()
seteuid(r1)
openat$vnd(0xffffffffffffff9c, &(0x7f00000001c0), 0x10, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x51fd)
r2 = open(&(0x7f0000000240)='./file0\x00', 0x0, 0x101)
close(r2)
r3 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r3, 0x6, 0x10, &(0x7f0000000000)="00000001", 0x4)
setsockopt(r3, 0x6, 0x10, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
r4 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r2, 0x6, 0xf, &(0x7f0000000180)="00000001", 0xfe2f)
setsockopt(r4, 0x6, 0x10, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
setsockopt(0xffffffffffffffff, 0x10006, 0x10, &(0x7f0000000100)="0100820001", 0x5)


r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000001700), 0x1, 0x0)
ioctl$WSMUXIO_LIST_DEVICES(r0, 0x40047477, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000240)=[{0x20}, {0x48}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f00000001c0)=ANY=[])


syz_emit_ethernet(0x2a, &(0x7f0000000500)={@local, @remote, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x1c, 0x0, 0x8, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @broadcast}, @udp={{0x1, 0x2, 0x8}}}}}})
syz_emit_ethernet(0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
socket(0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff})
writev(0xffffffffffffffff, 0x0, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
dup2(r1, r0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00004100000000", 0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt$inet_opts(r0, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0x8)


mknod(&(0x7f0000000180)='./file0\x00', 0x1000, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x1, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x2f2, 0x0)
poll(&(0x7f0000000080)=[{r0, 0x7d}], 0x1, 0x0)
select(0x40, &(0x7f0000000000), &(0x7f0000000040)={0x7fffffff}, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
open(&(0x7f00000002c0)='./bus\x00', 0x2, 0x0)
r1 = socket(0x1, 0x1, 0x1)
setsockopt(r1, 0x1000000000029, 0xb, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
r2 = dup2(r1, 0xffffffffffffffff)
setsockopt(r2, 0x2c, 0xc, &(0x7f00000017c0)="4e4bbf5998bd99d606e920ad4a42ab5929b92d9efec19c56915cf97d546a067f3799f2720a37a0c73e2bb97339cc66874a87a16c173a74642696ecac26bedb009401e6ce21e717b07326b8923efb78b401d3133a469e73073fb2ff593736d30e2242895c626dae71bb4758a15180", 0x6e)
select(0x40, &(0x7f0000000040)={0x9, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0xfffffffffffffffe}, 0x0, 0x0, 0x0)
openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
writev(r1, &(0x7f0000000080)=[{&(0x7f0000001880)="974451973f0ca5bb77ac7973ca035917a8df398cb3795b7f8235f7954d73aa8bd3535a86e2db9b2b32a6baa41eae007595554c757403f6a8576ec23b1ae1d9243c167abef82c3021a14290b7081778640dadeb04547743a942ee11cffe5c07", 0x5f}], 0x1)
write(0xffffffffffffffff, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
r3 = socket(0x1, 0x5, 0x0)
msgsnd(0x0, 0x0, 0x401, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
socket(0x2, 0x2, 0x0)
sendmsg(r3, &(0x7f0000001780)={0x0, 0x0, &(0x7f0000000440)=[{&(0x7f0000000340)="fefe92a48f0683ccca47bcc74c09297e578583bc66ced8fb64d925835741137dc724c9d6814630f53092a80d90143ae2ad99302f4ecabee6b36155eafa83b6565f9bcc606505f87703e905578fa0da58f35aa493657f071cbd1f6cd09fbde38ec86234d13a92a27aa1fb5bc3866f93ea5c40d99af86fa4ed63f61850ae221122b51fc332d8d08ca4e98c590bbbc751a81d5d69ef82ed355232b6f6ac9dbefac6a1f32a37867c3637ae06c4d4f3fdd0d31583c8b0ba77cc72fbab147eaed81aca9151e6ddd47eb521bc085b32e225667eaa3c13010f71ad2ecbaba76bb5c5466ea70feb571c3536d3263b8e531bda713e058c7c7bd5f115526623ac76df", 0xfd}], 0x1, &(0x7f0000000480)=ANY=[@ANYBLOB="d800000000000000ffff000000040000359d6a22d080e834a37240dfd900ab9672dc94dd1ed22c2decad01453115f8eecc9e470bbc7b356b0f8a8778a9a924dd882c02ee9baec03b738c0c209b0239b88856a2fb8afaaa2ef6dcbeb3906f8b0201868f396c44b1a7fb8c64364007df5780c230246d7486e4d0472abe8c40d583d585ff104729579d2e05b2cf81d55f7da19160944037e013a29737ec29563aeada81f0a79e0d0ab65f60c9a57fac7d695f393c00a36864618d3d1b4a285ee19ac4da71bf33be56f2175844c36b3f992c81303727665bff7a1010000000000000ffff0000080000006cbe849e4b4d3f0e5b200927327cba3288a5abdf2b201026e617ec1f42700015bc3ff33a87b35bc57bed6db873116f4befc1bacb507d9d3e560276ec30652cd00de2a40ec67c2ba54ca5288cb43ea483b0e829e1a9d82e3fd5aef293bc632d80af3b34f62cd405981c4fd2b6e6cf84f26696b0893e6458aca2ccb9e2057a010d62a0fa898c4fbefd5f8b7dd82c524e0bb00e91f1c76d0eca65609b1a2d62afc2d5adec913d5c6517781fee1ee9e213eac0e1bde15986ebf9c49883e22b4a782447b6f4db044078a790aeef135b927a7a5b499af8b29e1bdf68e5639f194e081d1ccac9069d369c1fdf96ec24baa520336e5c1c7397f1eb86fd32276158eadaa44159dc851e325241b4cc0872d97d257d9d15dbe2073acf2c43ad53bf1edf1a792d4e479f0a62a78c5d1dc6f3e41663fee590547603386ed391eee818ccf1c04865b9520bb12d511cf378bf7f47634752378c8de021c78c9d527a71d4341ff36aca1e8f38cc01f56475a9d42d220f7e08f1ee40c073a7a9f6ae6fb5f6625cafcb537d6f45cddc95d461d62281aa3b176c2f3221e2bd2fc1fedc398b296e9e2ee2e9cee1bd1fb31b101096769308fa00f6cd922922fd4de6ec9022c813fc710f16d85c907e1dcd12f819609abd9ab3a01a20d2b09f09fa1c365b211e7a155d180ab4c88d4ba0ae2a8015a9ed42f69a1038428a3e4fea6e7dc6de6cd7c1a78f2b1f44b6857411c6f79d567e0887dff97b3a398191bd98c0c98a2ddd22425db3fe16243c23e599679b98d2c35ad1297e19577ad1b7ab0098a0c3d6867ca78da8f0d5be184eab691a90b397fc2d82454e21f76fcc1452852256793bdaf830e9fdafb410bc2ad82d60d5e7be5ca2a450ef527c1075febb58dd27db7b62c9179e23253b47e428c874ce6d25e31b272808d2a79e8c0e48c0c26b1aecd6d8c253e6d60c254ed440e75fe8d50da405c640671322dfcb12b08b964ef3f1bf032a32f6357ab031028855f602e5033c62d8afe3806376ac88e6cfe27579b5c5d342a0379bc103bb1a5b3ceec8f77cc1d8fa4acd6468c81845ba54b9af7990e0b0c31aa4a65ce6e52e1c7cab4f85f6e5cc8ac0a4bb79eb010197dffbfdbfbb36da6033d1571ec3f12e5d95fd11685a391cf07ed4d72e5a5fbf35d684b546047e3562731f319b362143d754e19cb87f59c2aa374daddc5f31db8ce69d54a18ee5bf5e866c1ff263514b523384d8630a45434cd1ae0f7a4dc9eb9e3213fd8d1995111cc1836a697fcb5714081dff6984f94155ad2d02210acb9c5b2c00e3a2fe13cc34f41ac81a0d58df1afaee14870d64965809b62e2843b2dbb462aeeb85288815d9fa5f5b7decfd5b4a7d8c8bb2689a93304c42753e6b9e72c3fcfca0f89373f2583b0c924bb7f31bcdb3ab7749db8be854ecdc4e07f135dcfd196cb0c6d4b54d0168e9fc475197fa03da08d5bf8a275644cb14a59d29780f5119c9923c1518aedf8632b3d15147917fb4ad0df5d91bd197fbe772723f95a1cd66901a48c37b579706dbede1e323ed0bd684ae355cae6b77590d306adec06093c1c25f6396eb318452c678cd2015b74f9dad94f1f70ced463e7fe85a2be4e208ebf44d6290e86886a985ac259f89ecd13799af965fddefe2453f9dc5e350820215a1bdc2400a76e9e3551ed7e0231a48c446909639fb414e79423cc089d96d319f1c448ec2e75cc7410766e239ffddb4e2c384d343842bb929e9b2d88d61fc16a25ab3672dcb63abcf7067b08550c73a37cb69c5dbae9a1b600db431d8c63bdc901ec66320b44e3b3bc3e97456c576c45c0242be6bd97b8d697c0cdb126447859928fbc67e8d51893b018e55ce2c0164471bae957978f05dc20796297eda2e60622a26c3bbad5e72ce97a8752d59f1ddbc2e88960a9c76a2646a44b5fa29dd42c585fe3f150d71861b006a16500ddcdc3e114755486276f2280d4063ce22ac974a9a6c5028d16d2018959eab4b59417806fc5da89badd9e75b81b307855fbfc255ece0b3159540630177dbd3e32728d7e4b1593d1c03b5ad3691327d08bbaf01e618e81f7bf85ac8bb99349f11d52ca1b5787f4fd406342e755081b3ac249e0fc7e0509d6855a0ec3d945231a4e5760534a2c338616f2110d8d191727c22abf33a1b6d68d9a8e38f352928c189b7e036caa5a6d4c8b70c58f269ec2c26327ad87347886a4680b275edc5faf8d96daec51124da646112bd9ecbb03ffaf441effd61e81442086bd02c6a55534e1c9aa7e10cd974024fa3014a4e1d9f9aab0a570a4a6cf55d4c579dde8c60b1964df42cb74b9b4588666c523d9ac19d948f5f5ef5a6d04d5d6df742fd24dbdf92ab60a261445890466cf96868078a08dd41ed27a80920442024f344dfc34863972a726a954704213d62810c9a7032e1b99344bae9994315ef294d870774ae5e5292bf0b4cae7b0adf2b693f9948a3f46083f3de179503db10373c8ddeb32276203c99f6d5a97777b07b5737e62cdb56358227e88ba6f2640443d7580466f7a87195976b6f3acbb1a7641bf75cd171eab19bf7e97f520f3369bc257e4e5f584c252c04e65c9bf71acbef723adc5e9f9e885ad583511fc58c0830c4bd8d0e3261c54abb7b27c9cbadf0f1a386313a1e872b1458763800d23d95b69ddf3c0d3791f55f21ceb30c8c2a6037c7e5075b983cc3fa947ac6df4761c415b8f58d3e29166cc090c4a5115566c6d55e540504bb055d6cd9c1048b6a1c4bf3ca6b3700b000363732cae3d791b74ebc9a96a94a07fe5dc007b5301b4543374bd307289adb4832c66f21f9fae1985d52a040af14b5122d753f5655e71bcb32b1998a572ee64f3fbac56ce414f3ac77bd1123e8606729fc7ffc5c4bc28a2b8c45bbbb385d08ae3a5daafecc3dff2f8107f8858e969974b12c4598518822ea2da0bfe3b2f60610fb87c7989ff8d25e086ff053f49fe00bf849ca13ae3dec958320905f7871b1d1426dd1dab7f3e3fded7851d5965ea0a4dee8f6afb64236338798d432bc5a63e010e3f48e41dda7a6054cc2f6d1a6f964b828d9fa41fa94f671e1ea3dd2cd55911531a9598bebbaabc2d7d357c03e7e230aadaf8e258d25976f32a68bbf5b580921f714bbcdde006c6beef515ba549f4aac408e3c154fcdef03a65a79230afb9e4c52edbf00cb61cdaaa39d10a2e9386fd8912565c7ca483e0654959d648bf448bd8d17a09aae7762382c1a0292e237c3902de16d75055913d06b02f0e631c3fe536eea92a350e4c78d0d52552b6b3fc2417e1894970f52ef59cf8ffffa3df5ec0770389246cc93021696df582b55ea6794ef65df2da2d3e29644fccf0616150148913fa0bd25b49c10db58768b53c7e75469555c81a958e740c5d0563c8d07113a755366e982f4de98a38f31042d44147b07cc74e0501110622acb11552af21f91bc0e3696391560e6e31cc69c726bddeceab4fa795177c3dc87946066f29f446ec629d657f03b158812b8d8c5dde2831d7a6d4cbba01b952309cd3223f2e695aacd0f4149a17a2d26cb8b62d4bc46bf99e0ccb39e472d25e363982b4fcb00a42f6956ca761d300f1464a99aa21f9051b4974f1b2c05cac2550297510242e36dfbc3f7c44506bca8d06a01ac3bee3021bf5b231bade9931b1260157af006b37189b19f118f78a8af41f90f3e14af4f226146c78d796198c5b4b021378712a52a21595b49f3204f4aa0a768e52f6e3f118144ed8b62475141e2cc9691d494010244ff68219980d9d9ef394b5fedd502b83e7f0da5ee0c6d217e588641270b3e409c439f6b6cb3af197f537ebfb03635ea685cd0bd7382cf9881764294384d44ae4abdc56cee5c4e643b2e5d2bbf06977d2c6475df198e24c3ad5c45743328bdf3671208af2a624720e1e6ff9fd81d569ebd83c8513cdd98eb0f10085e2f294e5bf0433a589e59f3f0fcb6ba5869ceef0b52def77b589cb4a041bbef68f6fa29b249c9521df92c7236b14b1851a5a28d8fae89ff0d1412f6c04e2be325b6378d7c73ad1a24e60fb73ebfb071b76428768c03ae1667dbd7b7ae04d79774ca08f70db078e7623cf0c3d0f1ceb2b319bfd5355702c7d04e4c341fb5a3984f16f36d93806bd691db460fde4f3422c1fc145643805c93ff31eb7033a97e38459de2c10a2976115371810e83b85eb1b2971272d2300123cd0e4095455e7c2384d5c5387e7ca8fc8ee3281fdf73d9edcee800349818a01a461647448f2a0c8599b9c618d1f280ca5f620d6cbd663d8d4aa2783d39fb3386e9ff3b72a94badf755c9ca3ce85bcbba5e8a523e7ece2bd7a4d19b073a46a53db4a9161dcf779116204b08125dd17bb54f6c94b13cb3fa93b546d87e462cb6150dbd15c1953f7f7d3b438b37375cbdcb49ae8e3f1c8bda8eb8e1fdf6275d3f60b96b14349aa157dbc18265cca5f55a788d840ce7cc13ae7139935a59aca4ff94136707b219d38920b5f5fd2cd0f84fc60cd70bf5058ab74fd33e47142cefa486847a6f62213f64af12c8b086dff4206e2278d99bb22cb8bd4cf4ec042351f1048bb50a47c334d99538c43c3c932c8c4b16ee5d8a36edc76152f315d7b9c269345fd5346a01ac096ac162ea02799780c1b3c7ef2133c9756b726fbc7f57500025b96bcf2fea15ed7eb555e0b8d97d9b9ff29daf55f2fdc96ca78cffb5a4442c892ee159eabff411c00ff2154951f80c112c10f87b58fdd5bdd626e2863fc2475bcfdd91585f99f86fc7de04cbe558356640700435a37b3f1e55589a2af4bb250e072647794f2d9439bee12f59e76a9898ff135e0431515bb0449071701f84edd5d12a38ac298702166834bd0da275f61d8e40d93d6464ebdac557828cda5af85cdb1ececb43316ddc060accc487d909c86d9332ad21d2b11b143a3e3c8a8d0b8749fa2f88a089c32c8754ecfab59c3953417b79da3991e78daff79a729495f35d9a63237d40d98516784560a8582499fa0fa6e413b936cecb66d5b82e82d52b7ff39f3722cab101ba085430c7a9cd6253973a7a53e848c69f16c7c7b3e9dba069ae3332f5b36e204e416dc47d314d41ba6c5700395e98e1dfa91026ae62f1125227735487a564826e779d3eb479bf8da6bddc4a4ebe9c2742113f1b3dc719df1f667be3ae81507294e820948386c07583995964c6477a05380a59e86aa08ca84c4115302d7cc3677cfc4da2cf429a3a3c4266dc755f231bb75d40b30439598b04daa3026f7de3e2261e518ebae99825410b695eea571ebf26bd0401f321c73ac33381c8cc4f79ad739e7907e432e406990c56e1fb9b4efbfdc0e1ae989eb5304cba492e92adc2b19c82ac246a6be35cff34a5582807f8295955bf598d97fcab1e757e0806521de5e094165c9722a3434df8cc3aea4f826e4eaff55954189ad2ed09a1813d87c2deff6353045adf7527b7570cbd69e27acf734156457d409a81a190a0c102e56803a34193129f46e2b3c61a179488511ad0f4dd331c960579e446118d0c3463ab1bdd97f2f8f5ba62b9d2bc15d1d5ac4bbd1a21e7d539c8b249a365f34424ba583b152b20a33a63ac9ed45d3990882b51813ea2dfd3e19289f6091ad3be3b0f5893e295610c985d6fbfcb75dfd9a6eabc02387eb97c83750ea72c6853e2ad18eb577d07ed60e85dba5f3ad79286fa1eab29f10310ea26691fbad8c345030b839e6563327dee510e95d2be8d948792f7999d77f40538fec56340371e03719c5975d430632183e167a1c518b2a82c2ad80339f91bd353e6252e2b8d482755db7313aff5a29bef0ef051ed3000000000000000ffff0000080000007b8afe43689148b9a2ff9da2da95914775b47a38b4336a79fac1000000000000e8000000000000000100000040000000d8490efac66467cd7b818ce0f47d2a4b31a45fa6e1d15bcb6705ef0a8544cd99fe87e5650786096db5fa652da2bd9c38e42551ce052c75ffc647b2c136edaec0f8dbe1934da01f30b4e664227dd8369ba521b19ed3b23c8e2547588e5af65d51ea59133c0243ea924186cd192a281d2462d7f057fe750606a04f07c003be8627263fa5df2cc1a35cfc3e9fbb632f9e56c2a3e58128aa9999ad628f030475dabfbbc983bf2196eaa54ca17cedc9ba199b92346415a5a8a165f89a7b757ba38677d77323b785ca2bc837e42a23f1296e116fd751348e000000e80000000000000001000000ff0300003a1b69307c4dd3076773a491f66cc1e707132f979a4ef80b0f507c06981e94c881d591e438b9bf5a73a03c89e1a8a085cea26213603655d61d02ca67b75c29af84a9ba8657f8122374c358edff1440db55cd63a5a208aafd56bc67130bc040797737f115e8e03c19dddc3a1251bda39e2bf87798c785654241f2998528f41333971aa759356b0e4b3b192e3aa5b47773d22f4c04b58c8ef734caf1d48363324f827b2bbbaa13da64dae090eb543fc4c905128771"], 0x12e8}, 0x2)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000708000/0x3000)=nil, 0x2}, {&(0x7f0000455000/0x3000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f00008a7000/0x4000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil}, {&(0x7f000026a000/0x4000)=nil, &(0x7f0000604000/0x3000)=nil}, {&(0x7f0000a31000/0x3000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f00002dc000/0x4000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f000032e000/0x800000)=nil, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000015000/0x3000)=nil, &(0x7f000015e000/0x2000)=nil}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil}], './file0\x00'})
writev(0xffffffffffffffff, &(0x7f0000000300)=[{&(0x7f0000000140)="f005c71031c1c5f421277b09000000000000007a091a2f47be787538ec7a89ec5ed66daa731ddc384ecc690869a0aa2266affdf772d7a360ee0f15fa664f557bb45071fe9b6d9d28e6e2589000f6a64f370b9e336987d77b38f7aada5309e46a81e0e2efa087aa9f5f89934fdbd2ed96e7234b8972b273e810ca9962a8f461d3a05711a63027321ff62c", 0x8a}], 0x1)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000002c0)={<r4=>0xffffffffffffffff})
ioctl$FIONREAD(r4, 0xc0106924, &(0x7f00000001c0))
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
r5 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r5, 0x8020426c, 0x0)
syz_emit_ethernet(0x3e, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)


shmctl$IPC_SET(0x0, 0x1, 0xfffffffffffffffe)
setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0xee00, r0)
socket(0x0, 0x0, 0x0)
r1 = dup(0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x802069c1, &(0x7f00000001c0))
socket(0x11, 0x3, 0x0)
sysctl$net_inet_carp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x3}, 0x4, 0x0, 0x0, &(0x7f00000010c0)="e1000000", 0x4)
sysctl$net_inet_tcp(&(0x7f0000000040), 0x4, 0x0, 0x0, 0x0, 0x15)
sysctl$vm_swapencrypt(&(0x7f0000000040)={0x6, 0x1b, 0x3}, 0x3, 0x0, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)
ioctl$WSKBDIO_GETDEFAULTBELL(r1, 0x40105706, &(0x7f0000000180))
sysctl$kern(&(0x7f0000000040)={0x1, 0x3f}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0xfffffffffffffda3)
setreuid(r0, r0)
getuid()
r3 = semget$private(0x0, 0x4000000009, 0x82)
semop(r3, &(0x7f0000000340), 0x0)
semop(r3, &(0x7f0000000140), 0x2aaaaaaaaaaaaddb)
mknod(0x0, 0x100, 0x6da)
r4 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000000c0)={<r5=>0xffffffffffffffff, <r6=>0xffffffffffffffff})
r7 = dup2(r6, r5)
shutdown(r7, 0x0)
poll(&(0x7f0000000080)=[{r7, 0xab6cc3d7ffaa0897}], 0x1, 0x0)
poll(&(0x7f0000000000)=[{r5, 0x5}], 0x1, 0x0)
write(r4, 0x0, 0x0)
semctl$SETALL(r3, 0x0, 0x9, &(0x7f0000000040)=[0x7ff, 0x1000])


r0 = socket(0x18, 0x3, 0x0)
getsockopt(r0, 0x29, 0x24, 0x0, 0x0)


sysctl$hw(&(0x7f0000000240)={0x6, 0xa}, 0x2, 0x0, 0x0, 0x0, 0x0)
r0 = socket(0x2, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0), 0x10)
r1 = dup(r0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r2 = shmat(0x0, &(0x7f0000ffa000/0x4000)=nil, 0x3000)
shmdt(r2)
sysctl$net_inet_gre(&(0x7f0000000000)={0x4, 0x2, 0x2f, 0x1}, 0x4, &(0x7f0000000400)="5758680d88960473280278a11f85b581722ae17d3c906b916d485960ee83f2e4134b5e704d06fd63e9d22266ec181596311abb9f47baac5a511975e5c894a33d479bff0b380d43954580bd2f739638406027dc558dc854da58aa2039d2245249e02fcb51b3fed16b1689f99a0de7f1593d56a1ae5c02a0759335e6ad79d5", &(0x7f0000000040)=0x7e, &(0x7f0000000100)="886aef850c86c968be7958fc4b11eec2f10bfed47d31b37ebd6ecbc0706da5d2c56e2e57f6c5045bfe1b8f3b804dfb397c33bd0fc76b67d749da9cb48ca6d0f7507aa46d17d70d98238a5d749c712d6ec44c25e33a2822ade1737e", 0x5b)
pledge(&(0x7f0000000080)='tty V\xef\x86\xce3|#\xcb\x13\x12E\x03hb6\xa3\x1dL\xcc\xf6\xb4M\xb2G\xe0\r\x9c\xe6\x98\x0f\x01\xc2\xe7\xb9E\xc3\x1d\x96\xdbY\x91\x0e\x17\x95  \x01\xa6~\xd0|/?\xc9\xd5k\xbe\xa9kG\x00\x00\x01\x00\x00@\x00\x01\x00\x00\xeb\x91vr)W\x9el\x03', 0x0)
pledge(&(0x7f0000000e00)='tty V\xef\x86\xce3|#\xcb\x13\x12E\x03hb6\xa3\x1dL\xcc\xf6\xb4M\xb2G\xe0\r\x9c\xe6\x98\x0f\x01\xc2\xe7\xb9E\xc3\x1d\x96\xdbY\x91\x0e\x17\x95  \x01\xa6~\xd0|/?\xc9\xd5k\xbe\xa9kG\x00\x00\x01\x00\x00@\x00\x01\x00\x00\xeb\x91vr)W\x9el\x03', &(0x7f0000000e80)='[\x00')
sysctl$net_inet_gre(&(0x7f00000006c0)={0x4, 0x2, 0x2f, 0x2}, 0x4, &(0x7f0000000700)="d3c893211ed5a847c7feb817fb148675062f370202cd4bf66ef319e0f92465c639cd28dfb2bd9f4f3220610b5b07731aaac6e228e6ee273a7fc16f86b3303c0556801a481370a6f0db7f3ccff8af6b81a2488628a04ced25e123b5cd8d7cd68c", &(0x7f0000000780)=0x60, &(0x7f00000007c0)="df3f215a99128bd54f3dc216a74ef7e863d3b362a1270f097ae1e0e53d64125610c575191ade5c4b6468c31c12610b46aff7b10a29d89934ece42792426048d87f94e33965b2dd191cc31d15ad16188490974ce6c53d74e95dc8aae10c43670d72c4cce273911e174f9e8e765b0d1f8f9f6a1095bbb2d4aed53ee094a409ba2cb57e98ad299b192188d7f8ce92e3dc624669a23b4883c9389fb82c3f1ec2b18c7e44eae6d456b2a78af8f8f29b", 0xad)
pledge(&(0x7f0000000180)='/-)..:B}\x00', &(0x7f0000000bc0)='tty V\xef\x86\xce\xbf]\xb9\xe0Cc\x7f+&\x82\x1d5\x18\xcf\x97\x1d7|#\x04\x00\x00\x00\x00\x00\x00\x00\xa3\x1dL\xcc\xf6\xb4M\xb2G\xe0\r\x9c\xe6\x98\x0f\x01\xc2\xe7\xb9E\xc3\x1d\x96\xdb\x01\xa4\x7f\xd0|/?\xc9\xd5k\xbe\xa9kG\x00\xa7\xb2%\x1c\xa9M\xeb\xeb\x00\xeb\x91vr)W\x9el\xd2\x87D\x00\v}.6\x00\x02\'j \xc3\x03-\x17\xb2\xcc\xe0\xae\xa1$\x103}\xd5\x1b\xb0s\f\"\x87M\x11\xad\\\xc0\xc4\x88:\x193\x99\xf6\x04B\x14Ro\\\xda\x84\xf6\x8a\xcd\x13b\x96n\x17NV \xb2\x96\x9f={\a\xe6\x9e\xf8\x86\xe5\x95\xd1U\xaa\x82:\xf4w\x18\"\xffl\xb1\xfcz\xa6P\xef\xb6\xba\xc8\x1f\xd8\xb5\xc6\xec\bi\xd4\xfdl\x80\v\xe9\x10u\x12y\r\x9c+\x18\x124z\xd06\xd1-\xa3]6JW\x023\xe8R\x95R\x9d\x16P\x82\x8c\xf0\xefd\xdexl\x9f\xaf\x8e4\xf4\xb4\xd6T{\x82\v.\x9f\xe4V-')
sysctl$net_inet_gre(&(0x7f0000000300)={0x4, 0x2, 0x2f, 0x3}, 0x4, &(0x7f0000000500)="75d63894217eebda89c65cefbf29e1f0d40dc9e7ef2b32e3fd4063e495ba0349fa095552a5", &(0x7f0000000340)=0x25, &(0x7f00000003c0)="ec9e743635b6e1b16c5e5a28d471a9f784d4b2eb2e76612a0d67", 0x1a)
pledge(&(0x7f0000000200)='tty V\xef\x86\xce3|#\xcb\x13\x12E\x03hb6\xa3\x1dL\xcc\xf6\xb4M\xb2G\xe0\r\x9c\xe6\x98\x0f\x01\xc2\xe7\xb9E\xc3\x1d\x96\xdbY\x91\x0e\x17\x95  \x01\xa6~\xd0|/?\xc9\xd5k\xbe\xa9kG\x00\x00\x01\x00\x00@\x00\x01\x00\x00\xeb\x91vr)W\x9el\x03', &(0x7f0000000280)='tty V\xef\x86\xce3|#\xcb\x13\x12E\x03hb6\xa3\x1dL\xcc\xf6\xb4M\xb2G\xe0\r\x9c\xe6\x98\x0f\x01\xc2\xe7\xb9E\xc3\x1d\x96\xdbY\x91\x0e\x17\x95  \x01\xa6~\xd0|/?\xc9\xd5k\xbe\xa9kG\x00\x00\x01\x00\x00@\x00\x01\x00\x00\xeb\x91vr)W\x9el\x03')
pledge(&(0x7f0000000ac0)='tty V\xef\x86\xce\xbf]\xb9\xe0Cc\x7f+&\x82\x1d5\x18\xcf\x97\x1d7|#\x04\x00\x00\x00\x00\x00\x00\x00\xa3\x1dL\xcc\xf6\xb4M\xb2G\xe0\r\x9c\xe6\x98\x0f\x01\xc2\xe7\xb9E\xc3\x1d\x96\xdb\x01\xa4\x7f\xd0|/?\xc9\xd5k\xbe\xa9kG\x00\xa7\xb2%\x1c\xa9M\xeb\xeb\x00\xeb\x91vr)W\x9el\xd2\x87D\x00\v}.6\x00\x02\'j \xc3\x03-\x17\xb2\xcc\xe0\xae\xa1$\x103}\xd5\x1b\xb0s\f\"\x87M\x11\xad\\\xc0\xc4\x88:\x193\x99\xf6\x04B\x14Ro\\\xda\x84\xf6\x8a\xcd\x13b\x96n\x17NV \xb2\x96\x9f={\a\xe6\x9e\xf8\x86\xe5\x95\xd1U\xaa\x82:\xf4w\x18\"\xffl\xb1\xfcz\xa6P\xef\xb6\xba\xc8\x1f\xd8\xb5\xc6\xec\bi\xd4\xfdl\x80\v\xe9\x10u\x12y\r\x9c+\x18\x124z\xd06\xd1-\xa3]6JW\x023\xe8R\x95R\x9d\x16P\x82\x8c\xf0\xefd\xdexl\x9f\xaf\x8e4\xf4\xb4\xd6T{\x82\v.\x9f\xe4V-', &(0x7f0000000480)='tty V\xef\x86\xce3|#\xcb\x13\x12E\x03hb6\xa3\x1dL\xcc\xf6\xb4M\xb2G\xe0\r\x9c\xe6\x98\x0f\x01\xc2\xe7\xb9E\xc3\x1d\x96\xdbY\x91\x0e\x17\x95  \x01\xa6~\xd0|/?\xc9\xd5k\xbe\xa9kG\x00\x00\x01\x00\x00@\x00\x01\x00\x00\xeb\x91vr)W\x9el\x03')
sysctl$net_inet_gre(&(0x7f00000008c0)={0x4, 0x2, 0x2f, 0x3}, 0x4, &(0x7f0000000900)="e5bd61563c75fe795e2551f62f1ecf96b2132d30c91f3ecdaa2efc67e7c5", &(0x7f0000000940)=0x1e, &(0x7f0000000980)="c498b64be793c0b1b3d3f0e4fe25a497221acb783e210c42555941ec59f24a47bb2d4177b0179428571aba354965e6eeba91feceea80263cb54a6281c9a4dc0a5f8b7433065fd72c4b8246805a4478decfca2a1608dd49180429dfac3fe73ef27761dab2590f8852652c8dc410aab6f089c90ccb84821f2ba8540a294a65306ff18709bdd30933171cda12d5471b5a56f1", 0x91)
connect$unix(r1, &(0x7f0000002580)=@file={0x0, './file0/file0\x00'}, 0x10)


connect$unix(0xffffffffffffffff, 0x0, 0x33)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x3e, &(0x7f0000000240)=ANY=[])
openat$zero(0xffffffffffffff9c, &(0x7f0000000380), 0x0, 0x0)
sysctl$vm(&(0x7f0000000540)={0x2, 0x1}, 0x2, 0x0, 0x0, 0x0, 0x0)


r0 = syz_open_pts()
close(r0)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r1 = syz_open_pts()
close(r1)
syz_open_pts()
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000080)=0x8)
writev(r1, &(0x7f0000000840)=[{&(0x7f00000004c0)="73870ab394d122be3ffe3b0ed86f22154584ce4d17cbd40b37e3370cc5945e80f0a1288b95968a147c72592110249e000c8fbba867f22058c963c2023def7326d6c5d6e3625409f65805bd073d910f7b79fad8cab83b", 0x56}, {&(0x7f0000000600)="75474d8d9e40b29c434e5d2534cf69c96617dbd136789cef48935c9dae4d569f0a7dcdb076285018c74ae7df9d10b79696f04948922979485596e722ee10156278ab8aab1b743eb94ada0533266dd75abf03", 0x52}], 0x2)


r0 = open(&(0x7f0000000200)='./file0\x00', 0x20000, 0x89)
ftruncate(r0, 0x0)
ioctl$WSKBDIO_SETKEYREPEAT(r0, 0x800c5707, 0x0)
mknodat(r0, &(0x7f0000000100)='./file0\x00', 0x2, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
open(&(0x7f0000000280)='./file0\x00', 0x615, 0x0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
r2 = dup(r1)
setsockopt(r2, 0x1000000000029, 0x9, &(0x7f0000000000), 0x0)
socket(0x0, 0x0, 0x0)
socket(0x1, 0x2, 0x0)
preadv(0xffffffffffffffff, &(0x7f00000012c0)=[{0x0}], 0x1, 0x0)
acct(&(0x7f0000000140)='./file0\x00')


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = getuid()
getegid()
setreuid(0x0, r0)
socket(0x800000018, 0x2, 0x0)
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x29, 0xe, &(0x7f0000000000)="02000000", 0x4)
r2 = dup2(r1, 0xffffffffffffffff)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)='\x00', 0x1}], 0x1)
getrlimit(0x5, &(0x7f0000000180))
r3 = socket(0x18, 0x3, 0x3a)
setsockopt(r3, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r3, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x1}, 0x38)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x34}, 0x4, &(0x7f0000000140)="3998a035daa227d1ce40394f044ed95480393e74f486aff61a92312cb952b89c09f24ddb00000000008fb1463d8635bf0f8e2f68a22421d45dcf5b7f5bdf7b47", &(0x7f0000000100)=0x40, 0x0, 0x0)
r4 = socket$inet6(0x18, 0x4000, 0xb7)
dup2(r2, r4)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0xd, 0x0, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
r5 = open(&(0x7f0000000040)='./file0\x00', 0x8000, 0x0)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x3, 0x10, r5, 0x0)
sysctl$ddb(&(0x7f0000000000)={0x9, 0x5}, 0x2, 0x0, 0x0, &(0x7f0000001080), 0x4)
listen(r1, 0x2)
r6 = syz_open_pts()
close(r6)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100))


syz_emit_ethernet(0x61, &(0x7f0000000000)=ANY=[@ANYBLOB="9e262bdbb2d6f4446d29d9f581"])
r0 = socket$unix(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f0000000000))


setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000140)="5ab7776a89fbe691f5dc4ba3b8a64e800b096303c860ecba5540261d1d4f7c51471b4798c620376b14690170dc082195b1c237c4d53699555ab679467a1b20c9", 0x40)
getsockopt(0xffffffffffffffff, 0x0, 0x32, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
syz_emit_ethernet(0x2a, &(0x7f0000000140)=ANY=[@ANYBLOB="00000000000000000000000008060001080006040008ffffffffffff7f00000100000000e3cd60de0066d661a35b000000007fff42f05fee55"])
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x4, 0x1100, 0xffffffffffffffff)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
sysctl$kern(&(0x7f0000000040), 0x2, 0x0, 0x0, &(0x7f0000000340), 0x0)
ktrace(0x0, 0x0, 0x0, 0xffffffffffffffff)
getpgrp()
r0 = openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = dup(r0)
pwritev(r1, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f00000002c0)="24dee952f632c9420a7cd9fca5de24bd829f736b202b", 0x16, 0x0, 0x0, 0x0)
msgrcv(0x0, 0x0, 0x0, 0x3, 0x0)


open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000080)={0x3, 0x0, 0x0, 0x100000409})
open(&(0x7f00000000c0)='./file0\x00', 0x20, 0x0)
r1 = open(&(0x7f0000000400)='./file0\x00', 0x0, 0x0)
fcntl$lock(r1, 0x9, &(0x7f0000000140)={0x0, 0x0, 0x4c0, 0x269000000, 0xffffffffffffffff})


setrlimit(0x8, &(0x7f0000000040)={0x7, 0x50})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETAW(r1, 0x802c7415, &(0x7f0000000000)={0x29f57365, 0x7fff, 0x1f, 0xffffffff, "8b030003000100787d902b56d864d3c3a3f4d3c9"})
writev(r0, &(0x7f0000000f40)=[{&(0x7f00000003c0)="89f77d1e000000001b4068e1642ea58e722c8ab1c50469719aca06110046220f28960d6b4c89d6c1b724", 0x2a}, {&(0x7f0000000740)="b111bec04cae7c7152139c94fc29135885c2b7b1126044c8ec888bb05b00f17dc4a24377c995518a3ead2b2c9078b262945bb9b4554847171f7334a23d1e34d3a2ab8f6f8f6ec6239a564210c690496e1a7c9d8b4b5b52cf10e44b1a9910b266320e7411197c1124d4fac6a4600673ca934eaa4b96dc5f4f1681b2f1b615a30f0979f80f8f9500247a5269642b9019da525b124ec3012cdd35ebb1b58a36bd9942fd9ecf632a7107c7d0a34857fe50e43237f827ee39c903829b68572bb4c373897bbab6be503e86eb3f360d69cbd82f5b99ca60f017506d2ba053ab48c88a94b145399f3b2f1de8ed5d93d8ffc28aa4141c8e99b8f1b0f1963e61a762900a433c6fbb64a350b868d62f3aa8d5efdde5d7051f38ca4c0cb5c3d0da2ceccdc6e57355f42e73744666b8fa01e572800573575d467b5dbe5ca6fc6f7eab1d77ad732fd568e2f8c59c2b1508749a55bf04bdddfd5c2dcb5f5c405c66ad224ca9d6fecc2bf8d7fe1e33ed765b200e1422e4f1599dff9595cfbd55afb3a54aebbe29624cfc769900baf957d3cadfe1be7e605dcd66e7c9b4f7be85d91f20830e296eb31e721e2cbee8d7bd120a20c0e540ef6fdc68f5bd7bd84557774db6730f0000000000000000002f1a96e2a622ad4a930697eac1d43337214c3973e462595d0b63e05ddec77a72b290093f3b64d2dee99f0a76454375616f3f5e020477c55f798e27a3ce67506563ab1a0dda4c5ae7243b4922e87b4d2bf98826567318a5d79bbc9bd77a2f0e57376bc85226e5e50f97f26e6ad213becc95a282f963e24aa12693e55054f8406228cd40c6768fab639abc9bc5e3d42e811b5ee33930a45444c4b5cf9cbda8db48d1af54f8faaa4c5f025bc084dd0b3742e72075020b7c0f069fa9939d15c82be759fc02dae035c39d21bebd06b1cbe247d119c9076d1c00f35102095dd676377b1a59dc1c2fe6135897882fbcfd6a8811b7e7a25e25b9d197a6217d517a0f398cfc19513ef1177982cb442531fedff8f382469b49d35d3751599c8090fa5169345c9b9fa3d710f373375ebff2aca2c8a750e77cbaf4459a8f782c9da945a96de669360f024a5c761544acc51fcbbda11a68e547826506001d5aaeb603d9a6cc8cb1e4c85d64dce37e07f75665386b465fc4630b1bfe6ead70a34837a7090e43dbb4830016d162a5d5453baf74e90ce9f153bf0ca26ed820b6a7d62c572a8725e6eaf28d1ee10593322a9bbaeed488f5e7fe947f2e25e67712447530b5b3517f7ea9a01a77e87efc1479c373da187387878d556c8085fdad7011519326e8aa917e73e6213ea2c3dc04b12fff658aa1d694bc76c0893e7b90e95664b42893fb89bbfe2e42c26d39dbb689ffbf7ce60fdef7e1acccf689ddd6a3e418419bcafe9af14a55117b2b92db97ae26026759ae4828ba35babf26e639612655d0dd1f6b8aa06562f29c7bda8589fe54959366c081b23de084c5765a5d27eccb5e0e3b60f0d135ffc7eda412509424f29878d70dddedd9eb57adbfbe39efe2e855342cb3ddf8efcea24780d14d9710aebe7dea7f70b21b1286048e96c21e636dde7edb3a72529c6ecde7eec8c045f1f1f914d277b21e6f1049013687dd2fefc573351de3e02d53c6e7a6140bf50e05b3df83c8711d15202c997e5a321f23a85f13c8d259d5af55ce1ce2103161472cac1777fa162baddc562051e2f707a0ba80cbbd0e6600f843106fba338bdb934516e99133cb3e70dc74314e3f7c3f7a5f1c9dd54512f737f3e486ac2c4c7bf761a21ef367ac466b0a135d7f952b862c99b884d8de902963829652eaa6393ed1ea5612cd47a77c428707c117554c722cab7ca50fa2a04d7ecc8f1fb45aefdc286c12fc5cee33537218d1499b61dc63aa30a48292c941413988788e2fbdb331714da1db02d6f55a2de06c89978c1b60c5c4ad5704265865d9e92a14d16104ac06ca288caa3c7d55db32e4f132edefe61b", 0x57e}, {&(0x7f0000000100)="06457410db7a86cb445413b034d9d5a4894b645b7fbc38af08458b162f780391906c038879b1b0f7b023ab11c1db8823fc0d76e8da767f2e8dcaa800d2edbdbe9a909ae88adeb2c221020d56baeff5ea6b1a8481a49912a753e83f65f39fb6f6201730471148b236fa1b02be1fb6b72b181b48faffc56883bd55f4a6ad218bb7abad", 0x82}, {&(0x7f00000048c0)="8efe927e139219019b33b40e291a6368427dbff01c7cf9e8ccc4ade5720223e7a6662a0f568427379d9428bc1da8fd20369e0ca8bb91335d364af186d9c5531b9cba018029760cfc5fe5d17bdc790f9925d9cdc96a5caedd8e6eae50d348188460bcc36dd2f6edda2619e63f35a27b1ee4e51f4de695b6a10d863b7bd4e1dbbaa8f26bcde8979f6bba0aa3a8f44ee0fd922a626b5147a7af25e431cf9939d7956aac37ea115181cb846522ada8aa188bec09c17898b1b82042b227be753ff8957a9a29ad685590d48405d84316994db071ed29f21521e5184fcb680dc0db4986739cf9c3c481bb6ea8a7438498d036e6927fdaf18accbf38de8aa188f8ad40261d2a02d88dc9efcab74bd4a77bfbeb013faef596e2895d5583b471e4e4526c5d4e436148a971e5bf1f1c37eb1ae5d542cfb0892b663a208eab4098251262b1f1713a0ae5406d57712c454655a5bcc1bb90e8598723fd410ed54b09212b790b1fb656ae84e53eb922fde9d93c5a3fd97994934f8cb5d7fda2c04b022b668f3aa04850f5a80e68103a8867317c201fa50f0545deb8d8ea0ae16a6884d1060a4e65dfa6fa5f7fffa77593b38e1efd6cac95bf8070243cc1b79e49963de3f2bf4f76768f2d384979d160bf75370f6742feb16efda16e2179310a5b504a2d57c6cd26851677755771a1a250ffd3ae98d60bc18a042d65c74dfb6c1e9f57662faa92126eb67be86773a736b70d176b31f8802de3dcc492727554cd7d7a6cd6b4d1b5daf6291a101b632ef7672a075a244a460b1445647979f1832e72551752eed8048cfafbc9a574613ae6f62efded1ab90fd37d28e6b8506f9f945db79385cee0ad50b922676c193cffdc418a59333b8ee24d9d7547ca00df2786e6aacf4c3e7e267fe0bea3a611dd0e9a36e90720d463af713f54f8b13a42c647847aee0a41743b42c907c5072ee5e769c63ce3614a16a3743eac6f64bb2edc35e44204616616f00d5283ee431a2a9cdeb830d572866dde345c96dd13cd001bdfe6fbf00bf043fda6a3daca8a06c1e4eb15fff83f7b38c35f51e781c8bdff20c78681ce6ce76f6b756dc2ef3fb7481980d1414c001147367f1b302f13992093e9e8decb8daa298efac80c892de7034ad8d355be8270018127c7201c3032007b7dc2cf38c7356dd1b9a80d0828fa345f2bd5b5d9b02324bf970bd5ed5472349a197097b6f69b5adf2dfe7f0074813f3956df325e0f80b9e1edffafb949f677918291b36e3e86a8eb3091febef03ce69f46a31e96e93114c0f62f69ea0ae1326bb9dbcf0e1a82865521ab493a381e91b4f28dcad093c70330cb2a228fe9056ff3bdb4cf5e0edb553559caed3055a37550da1ebd7e5ea13f9085a1a20fa31a17cd5d29ba5c3c01c00e2684513feb7cde3aa3461777112b965202eb8292a27410a34f5499d0ff49ca9da2054b4601c86474b47a15a0ccd994052bf6dee62c006ee762160e253ebf61bdad0e4868788c6b80535e20ee33cfa9dafcf7697aaba6180ea6291e8215493d28063e3f9573a1d3a3cb7d967dd09e402f5bbed673cf76f6a07ecb2d1c085bb6362d4d86be55c7196a52268703e7ee1b87c309c31173ead50cb7d14c0813e03694d71719bfd4ac246ff9ad990d9288ccb40075f57837e1bf15119cba7184c236a0bbf1f90e5e6c1b1862e7d8bd28d3925ad24992028aa8bd2511aa214f9e747453e9ed928fa926054c34470e039a9dbda3d2cf12b83135cafc3785ed09bddcc7bf70444448218028b2044630da30a0b1314d7b7c02792e4226be1e3422b98666d91b0ab08ac0875c7a698c37fb1b15ec3edc4f75af022fa59a58f67e7707e3c9a157aee42201569d4d9f93ec81acac9e951943eb5c3678a84a674e4f2bde76cc4f7dd6c1f4816d8b0423a5225dfe4d0c9d79eebf075372c29a294d4c0365400ab69d1eae152a188f7672c0172d2e509135515e7c9a57755b035230f214ae107c1550cf93f0f97634aee00c8fce7914615d5cf83349f1d528a232c9e56142005a865c0d7e1e736c41ebeac7756b94a981ceac91df4d8192063588f99ecf5883b3c05852490683cae11405440930cf5856615398a6db8620b887dee8b64d894289ee35d18e03f417d4109f551bd73bd29dbeefda2e4f2953ebe18dd3554a5db6f5d2dd97b5b5210be235b388eec8e9bcb631033e999a90307a1a2f39ea46d6714b4509ca7fcb52787f7fb81675dd1846744f42f9be873c1823fa765aef28826dbac4196b83d7d914b24c917fc6605775c8cf3a006864689210da58bd7521a6c8ebafa3c435c1d0b7e776153eed19dcfa4635ac7c05da169900f28c80e556ed8f0d3f449ac6f427c3f6ae61731e25e457eb780cb94a3f971285dad8fe8fa518b73d689b9b8da6ebc578f320c846b6ff8330b54533804e95690cc0b618e47ec64adfaf1b324f34159afc595b0ffd85bd730b76c91b63bdf059d799e5514c1c1006ec2e796c587b88ab90b13577f549d655f689632b49c5e5b42ce6ac5ac6a099727359b0e8e88cbb456b4dc966907e1ef010c81b7099405dde30f4dfd4d88d3d5d109f1f96ce42c0957daf613d3c85e393151d151b82b0001c74b704a62032b9e006e4938742df0864cb2740a6351fc8349f0840966efc051b3b716ac6a17fe6bd4ee4d9eb8a29ebc50d7a6790b891379306c8fe197438f07551406c93b5f4fca59b9de4919e0631b3e6a085780292038b2427822ff7fd6dcf0d5efdb19ffd9bb1a6684fceadcbac2316a880fa5c8ef32554b7565ba3e019ad5fa2406cccacf7093acdd3f348aa6724df7f80ce4513ce5780310d98cda7a9709d4f894d24ab963a895b465d0c5d342507b7a67520c63172634826acb64950b04ec37a1bd8384930db5396e24abc31269f17ae22c55b4a1a401fea8f36691fc27af3476735e901d2b0691a65761c0a3ff23638e805a8e694bf6438c5725463781d5c98188bc5c86c814aefa31f77c8d52d140c207d5c05579ef5bec2d66b33f34658fa95f193d6be077d9ff64b8f07e850eefa598e8a3c9cee522273851a5a66df3cb351d68f0282d90f927ee4c6b070f50a56e170ce3b70f4de97a218da1f54ae5cfb7400000000503e930607d011201b9fddc311f6736380e169b732165ebdfd6f65f61c0356ded5f87c8b1c7398002374e02e85a8a63e3fe74ad9ce5f4467166b00662532a2dc96c4ccd48df46aa01fffc2a873080382b39514919da36fb900e0b6351a387d6edaffe3b453a10fc9a46e8cc1d2d8bc7ae520871730df253ee6552f92a18ba629c95b523ac34b041c1bd60344edf35c0c497a847e236775e1d8d887850415aed2c239d19041fa00f42a52d38e61611bbef6e5763869042bf5bbda6ed3c117ce78b04edea74f92b19e410fbf8b130f83e68623ed3836a96e38dd30c3d2e7cce84d3c0ee9f1b546b0d716417af0d7ba2317a0ee2b152fe5e32527f9b177142aae42558866d982203fea7bee03309469b99ec690d401020dec4d9186657f42f8b3c2475acdf3e01edc6b3765ff1e8754965da7d311f0c30de9ea4090089623824e42dc2378e8dfff132a089be402f828bec70419f3c3d1fac377fe1cb061a60eb9aaea0264c25d4ac7856180da12c30d5dd226315b86956c4e6e6be5db586ecae1f647b914d0c2970305bd672375a66fe2265bd6f41fe16dbba16ba52427f0842de6678fd891db578c7d997e4da74b3588121be9e587da92ab4eb7a46eacc6ab91f6128cc7c0f59b2bcb0d69fc332e0b310e979bde14116e552b92", 0xa76}], 0x4)
writev(r0, &(0x7f0000000640)=[{&(0x7f0000000300)="25a4876bd3bf639aa2d65e277785c3613dee0d773a3d2f8f1b80bddd5988939d00171f1d7d0efa0d81", 0x29}, {&(0x7f0000000440)="50add7375f21355f4f7a8bd47979d416fb01ecc215bd1f249bf75cde348f17640e896b610792189afc772921416837fb0bbfd466891b127354f0fa71093ddf48048e650d598f00cc500c5835d11456110e87070f013499d869a7ee82a95a962da3dbefbf", 0x64}, {&(0x7f0000000540)="12fa59f47bff787eed568b0400fb2d139cb357574ff863577dd8972ae8f2adddede9c30caf45f7727a774ff477bc35034e779bbdc590e91b5097db4b54591a7d1dac815d39530d82dca85bb120fdd6a3e0e6a31a8d6ba91432f81bf578c465c258488beaaf12c5a5c8d890016fb845fc8bb2eb155074", 0x76}, {&(0x7f0000000ec0)="fdda2113cf9349309cde5df66b3c4311b8ad80dee080fe0a2131b4708a266a9273eb4db27177328ab6b5902e62102018802ecd87d30c0eebb87537c479d34c6e6c82368898c55906d5ce87a3742e606a67965b6fb5ad167797", 0x59}, {&(0x7f0000000cc0)="9c1c442c25e6369b003fb1c239767253d5307e7fe1606ced7989f8770162ac99e9e74cb9a8f8164b8d2064e5953a79cfd6e6f9a0b999ca2c1949c230016a7996c66ed4051508783a8b5c2d50bf835dd35ecefa1db43977217dc7296f7db72dcfcd1f8cdb803c7c06d17cda0ab331d4545cc7971db021789dd5af9734a72fae1b61adb5a5a067385344bda1de4fafe23cf1078d01f8b04382b03f94c74ac32f72f73a81cf0c7ad2072552b4c81353d268af179fa17f48bdc427208e6c13de7b7609d24b38d12e65085f1c9bde5022bdd73d60ae869230a09691a36a29bc0b333f687e1dcd02b059cfb8e72f84f693f9", 0xef}, {&(0x7f0000000dc0)="d95307e605302abdcab4969f011459b4889bbc65288ed3b6945d7812ebb2b960998e5c040f4e592806cf48182e78b826dd55b74081a24dc803834b7adc80afe4e9387bbeb635702918c1c3c9ca9033e5706501c12ce2c615c0ec5243d3b192d12ea86c9f238baee04d27c2c9c13c1b625d602a0dc978eeced381a54fcb84e1dba794ea8171", 0x85}], 0x6)


r0 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000100), 0x4)
sendmsg$unix(r0, &(0x7f00000002c0)={&(0x7f0000000040)=@abs={0x0, 0x0, 0x2}, 0x8, 0x0, 0x0, &(0x7f0000000280)=[@rights={0x10}], 0x10}, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x0, 0x0)
pipe(&(0x7f0000000100))
pipe(&(0x7f00000000c0)={<r0=>0xffffffffffffffff})
fcntl$setstatus(r0, 0x4, 0xc0)
r1 = kqueue()
socket$inet(0x2, 0x1, 0x0)
kqueue()
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000080))
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140))
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000080)={<r2=>0xffffffffffffffff})
openat$pf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
openat$pf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000080))
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000080))
r3 = fcntl$dupfd(r2, 0x0, r1)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000240)=[{{r3}, 0xfffffffffffffffa, 0x95}], 0x0, 0x0)
kevent(r1, &(0x7f00000001c0), 0x9, 0x0, 0x9, 0x0)
r4 = getpid()
kevent(r1, 0x0, 0x0, &(0x7f0000000000), 0x2, 0x0)
fcntl$setown(r0, 0x6, r4)
close(r0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000200)="67fbf8010000000000000000000000000019a11e6d4f36814f6c", 0x1a}, {&(0x7f0000000340)="48b88b53c1fb1e4da4c91604527760545a754d4a5433cf6b8a2dc534c09c67316f8c652ff9a8aa28eaa71e351233c7539981fc948be70e1508404f5575458a9f1046322a3a75449a2a8c278ceea820f1ebbfc09bbf57b934f750413d7a45d636278f28b7d848ba163d06243d908373787d30489c6b770ea92e9b506c930c8564940783da71ddb179c8b46a622e00", 0x8e}], 0x2)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
execve(0x0, 0x0, 0x0)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x1000000ff}})
sysctl$hw(&(0x7f0000000000)={0x4, 0x18}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x1)
sysctl$kern(&(0x7f0000000000), 0x6, 0x0, 0x0, 0x0, 0x0)


r0 = syz_open_pts()
r1 = syz_open_pts()
r2 = fcntl$dupfd(r1, 0x0, r1)
syz_open_pts()
syz_open_pts()
fcntl$lock(r0, 0x9, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x1000100000417})
close(r2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000540)={0x3, &(0x7f00000001c0)=[{}, {0x61}, {0x8106}]})
syz_emit_ethernet(0x36, &(0x7f00000001c0)={@local, @local, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @rand_addr}, @tcp={{0x1, 0x2, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, 0x0)
r1 = open(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIOGETOWN(r1, 0x4004667b, &(0x7f0000000140))
mknod(&(0x7f0000000080)='./file0\x00', 0xf6ca5bbea4ea2673, 0x9ab)
open$dir(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r2 = socket(0x2, 0x2, 0x0)
socket$inet(0x2, 0x8000, 0x2)
ioctl$FIONREAD(r2, 0x8040691a, &(0x7f00000001c0))
ioctl$FIONREAD(r0, 0x8020699f, &(0x7f00000001c0))


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000340), 0x0, 0x0)
ioctl$VMM_IOC_WRITEREGS(r0, 0x8020560a, &(0x7f0000000040)={0x1, 0x0, 0x3, {[0x3]}})


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f00000000c0)={0x0, 0x0, 0xfffffffe, 0x0, "031ffe40630000000000ff00010400"})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
close(0xffffffffffffffff)
socket(0x18, 0x3, 0x3a)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x3a)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r1, &(0x7f00000001c0)="00003226a4a9000064e7c803d2a423735d33a4dd72c3b894d1de957eedc56e0380271dc72f5796a20a91046c9782b54e9ebe4819eac1e41bebbc8fc2e5155796116e00a001c0745c0fb366c8c29785b0d6983e036092903b438bee0dd22d219efe232e9cc22761f89554c67e1d9ed3ae72e8352e17bcb4300b3c41577047664b11e0dd9155c39f1ddf1703da62aa7c505bf0229ed8fd3eff829b861046cf6b255de56a04727d21aa78d0fc51b8619d80", 0xb0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000280)=[{0x1d}, {0x74}, {0x406}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f0000000000), 0x1)
socket(0x2, 0x2, 0x0)
r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000a, &(0x7f0000000000)='\x00', 0x1)
pwritev(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f00000005c0)="dc", 0x1}], 0x1, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x5a}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)
dup2(r0, r1)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r2 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0106924, &(0x7f00000001c0))
r3 = kqueue()
kevent(r3, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r4 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r4, 0xc0206921, &(0x7f00000001c0))
r5 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r5, 0xc0206921, &(0x7f00000001c0))


socket(0x18, 0x2, 0x0)
kqueue()
pipe(&(0x7f0000000040)={<r0=>0xffffffffffffffff})
poll(&(0x7f0000000080)=[{}, {r0}], 0x2, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x3e}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000080)={0x27ffb, 0x0, 0x81, 0x5773c545, "944c8f62b57be2df6707049c8bda98612c2100"})
writev(r0, &(0x7f0000000580)=[{&(0x7f0000000140)="080000007ff0e57fb99bf049535c0a0631e3d7860f948f2bcfe59a04cb9f96ab8960e4f272127f555ca8", 0x2a}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{0x4c}, {0x81}, {0x8046}]})
syz_emit_ethernet(0x2a, &(0x7f00000000c0)=ANY=[])


r0 = socket(0x800000018, 0x1, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0xffffffffffffffff}})
r1 = socket(0x18, 0x2, 0x0)
close(r1)
r2 = socket(0x800000018, 0x1, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x7})
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


pipe(&(0x7f0000000040)={<r0=>0xffffffffffffffff})
poll(&(0x7f0000000080)=[{}, {r0}], 0x2, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x3e}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105727, &(0x7f0000000000)={&(0x7f0000000040)=[{0x6}, {}], 0x2})
r1 = socket(0x10, 0x2, 0x1f)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)
munlock(&(0x7f000000f000/0x2000)=nil, 0x2000)
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000140)=[{0x60}, {0x61}, {0x6, 0x0, 0x0, 0x4000003}]})
write(r2, &(0x7f0000000000)="7696e5f3d1f18c37cea8615ac7cf", 0xe)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x2, 0x1, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)
mlockall(0x0)
munlock(&(0x7f000000f000/0x4000)=nil, 0x4000)


r0 = socket(0x2, 0x3, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="0002"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
bind(0xffffffffffffffff, &(0x7f00000000c0), 0x2)
connect$unix(r0, &(0x7f0000000000), 0x10)
ftruncate(0xffffffffffffffff, 0x1000)
sysctl$kern(&(0x7f0000000000)={0x1, 0x21}, 0x2, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x0, 0x0})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbdf13b9fd812eaa4e713048e69931929648", 0x14)
write(r0, &(0x7f0000000080)="04bdfa5d1d2873c63e3534825ba166e2fea9aec43050006123339a346f731573d8d508753f95b7688ad48b8cf6bbca325cebc37fc4e1dd543dbe2da6dd", 0xffea)


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000a, &(0x7f0000000000)="ea00005c00000000", 0x1)
setsockopt$inet_opts(r0, 0x0, 0xb, 0x0, 0x0)


mlock(&(0x7f0000ffe000/0x2000)=nil, 0x2000)
madvise(&(0x7f0000ffd000/0x3000)=nil, 0x3000, 0x5)
munmap(&(0x7f0000ffc000/0x4000)=nil, 0x4000)
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106978, &(0x7f00000001c0))
recvmsg(r0, &(0x7f0000000100)={0x0, 0x0, &(0x7f0000000140)=[{&(0x7f0000000200)=""/4096, 0x1000}, {&(0x7f0000000000)=""/216, 0xd8}, {&(0x7f0000001200)=""/236, 0xec}, {&(0x7f0000001300)=""/4096, 0x1000}, {&(0x7f0000002380)=""/43, 0x2b}], 0x5, &(0x7f0000002300)=""/54, 0x36}, 0x56a)
r1 = socket(0x18, 0x3, 0x0)
getsockopt(r1, 0x29, 0x68, 0x0, 0x0)
listen(r1, 0x5)
r2 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0106924, &(0x7f00000001c0))


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x1000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff9000/0x2000)=nil, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffa000/0x2000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$FIONREAD(r0, 0xc0106978, &(0x7f0000000040))


ioctl$TIOCSETA(0xffffffffffffff9c, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "0100dd2dfa7f0000000400"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x59}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000040), 0x3, 0x0, 0x0, &(0x7f0000000080)="4f1d4c6344b80ed788b6a4515248df3aa745bb992c574ab4cdf5587145812eab4a988f7fafd7a01d99776d988908cd186b51f34f8c15ffa0c685ad4116c783959eff4278384b4000384dbb1c2aaeff10b4135529a1da6fda67c67469d954be811b25ec5521559154c586eefff122009f659cd3e27e98a3241495005f102d9101d158284c0ee3250aa7c11042330de22a299ab00894fdc9bac6042d", 0x4)


syz_emit_ethernet(0x32, &(0x7f0000000080)={@local, @random="b024964c63a4", [], {@ipv4={0x800, {{0x7, 0x4, 0x0, 0x0, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @local={0xac, 0x14, 0x0}, {[@generic={0x7, 0x3, '2'}, @lsrr={0x83, 0x3}]}}, @udp={{0x3, 0x0, 0x8}}}}}})


r0 = syz_open_pts()
fcntl$lock(r0, 0x7, 0xfffffffffffffffe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000300)={0x3, &(0x7f0000000140)=[{0x45}, {0x28}, {0x16}]})
write(r0, &(0x7f00000001c0)="d9537abde93d050cdd16b13f742a", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000580)={0x3, &(0x7f0000000540)=[{0x3}, {0x2c}, {0x6}]})
syz_emit_ethernet(0x7e, &(0x7f0000000040)=ANY=[])


open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7949)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
writev(r0, &(0x7f0000000280)=[{&(0x7f0000000000)='#!', 0x2}], 0x1)
writev(r0, &(0x7f00000002c0)=[{&(0x7f00000001c0)='  \n', 0x3}], 0x1)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


syz_open_pts()
socket(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0xc0206921, &(0x7f00000001c0))
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0xc0206922, &(0x7f00000001c0))


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x5200)
r1 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
kqueue()
ioctl$TIOCSETD(r1, 0x8004741b, &(0x7f0000000040)=0x7)
pread(r0, &(0x7f00000009c0)="fc0a0d89e2d035f365a2d38139bbc66ae03e9cbfa9f70aee", 0x18, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x2, 0x0, 0x4}, {0x48}, {0x16}]})
write(r0, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xfef3)


syz_emit_ethernet(0x49, &(0x7f0000000000)=ANY=[@ANYBLOB="ffffffffffff00000000000008004500003b0000000000f68f7800000000000000004e224e21", @ANYRES32=0x41424344, @ANYRES32=0x41424344, @ANYBLOB="600000009078000004020502d1c2f0bfe2d0786ca28e44289f59ab"])
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
syz_emit_ethernet(0x45, &(0x7f00000000c0)={@empty, @remote, [], {@generic={0x880b, "d7572d148f3eb1a17e7119132bbfe85bf844366b8ca5c727ef924cb14d952438de0eef60eb8ffa3cfdfa771dc6cfab1f57ce61e179f6ad"}}})
r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r0, 0x80085761, &(0x7f00000000c0)={0x3, 0x5})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000400)=[{0x4c}, {0x3}, {0x812e}]})
syz_emit_ethernet(0x66, 0x0)
r1 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000180), 0x1, 0x0)
syz_extract_tcp_res$synack(&(0x7f0000000140), 0x1, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x20)
r2 = socket(0x1, 0x1, 0x0)
fcntl$setstatus(r2, 0x4, 0x40)
socket$inet(0x18, 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(r1, 0x80085762, &(0x7f0000000400)={0x3})


sysctl$hw(&(0x7f0000000100)={0x6, 0x18}, 0x2, 0x0, 0x0, &(0x7f0000000240), 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000240)={0x3, &(0x7f00000000c0)=[{}, {0x1, 0x0, 0x0, 0x2}, {0x6}]})
socket(0x18, 0x0, 0x0)
r0 = socket(0x18, 0x3, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x2a, &(0x7f0000000200)=ANY=[])
getsockopt(r0, 0x29, 0x1b, 0x0, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0xff0a, 0x0, 0x37)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x10000})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000040)={0x3ffffe, 0x0, 0x1b, 0xfff7fffa, "0afff5ff7a095afba1d76ff218aabc86001800"})
writev(r0, &(0x7f0000000840)=[{&(0x7f00000009c0)="1bf882c147063c80d3488dee7e157281374a68073ada17b27df1dfc9c9925c1f027c3b7b1a05319351cdc65fe93981dca9", 0x31}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x84}, {0x80}, {0x812e}]})
syz_emit_ethernet(0x56, &(0x7f0000000340)=ANY=[])


r0 = socket$inet(0x2, 0x2, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
setsockopt$inet_opts(r0, 0x0, 0x1, &(0x7f0000000240)="ea000001", 0x4)
r1 = open(&(0x7f0000000080)='./file0\x00', 0x70e, 0x0)
r2 = socket$inet6(0x18, 0x3, 0x0)
setsockopt$inet6_MRT6_ADD_MIF(r2, 0x3a, 0x66, 0x0, 0x0)
writev(r1, &(0x7f0000000280)=[{&(0x7f00000000c0)}, {&(0x7f0000000180)="6a4f939b9120a9a9809353ee8ab94d9d91982e88125e29ab412d900938c67b9869bc54c26b6074d2a35d9d398f962d89ba53ee17d2e213e3ab6f3979ec0a52db259bf5213f9f085a6ea854d0a9429e9c8ae4502adb1d8605e2001f6891d3e9f68939bddd0f20ca0424c518bf522d50f4df260b3dad2d000ce1940d5d2b0d02d0b498ae6e324cc6fde7a660bf569c4837d7a408a2ce2e3394d529632e37105b9cc83761803108", 0xa6}, {&(0x7f0000001e00)}], 0x3)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
socket(0x0, 0x0, 0x0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
getrusage(0x1, &(0x7f0000000000))
getsockopt$inet_opts(r0, 0x0, 0x1, 0x0, 0x0)
mlock(&(0x7f0000674000/0x1000)=nil, 0x1000)
socketpair(0x18, 0x4, 0x7, &(0x7f00000000c0)={0xffffffffffffffff, <r3=>0xffffffffffffffff})
connect$unix(r3, &(0x7f0000000040)=@abs={0x1, 0x0, 0x2}, 0x8)


socket(0x2, 0x4001, 0x0)
r0 = dup(0xffffffffffffffff)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000000)={0x0, 0x0})
write(r1, &(0x7f00000002c0)="c5449bc1708e16b9805a099e20a0", 0xe)
syz_emit_ethernet(0x66, 0x0)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x2b}, 0x4, 0x0, 0x0, 0x0, 0x0)
socket$inet6(0x1e, 0x3, 0x2)
ioctl$TIOCSTOP(0xffffffffffffffff, 0x2000746f)
socket(0x0, 0x4, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {}]})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000180)={0x4, &(0x7f0000000140)=[{0x561a, 0x1, 0x9, 0x3}, {0xea0}, {0x1, 0x6, 0x1f, 0x5da}, {0x8, 0x4, 0x1f, 0x1e}]})
setreuid(0xee00, 0x0)
getgid()
pipe2(&(0x7f0000002940), 0x0)
getpid()
geteuid()
getgid()
r2 = socket(0x18, 0x3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r3 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r3, 0xc0106924, &(0x7f00000001c0))
ioctl$FIONREAD(r2, 0x8020699d, &(0x7f0000000100))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{0x2}, {0x84}, {0x6}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x26, &(0x7f0000000180), 0x0)


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000100)="058c4cc154b5895edf170affb44c37b4e96eb0aa265b33a650172f5b1d2760b1cc8ab19c57387cc77e393974c9e52e4f40f7def3d6a5b18dee9efc7d3d5c7c1cb4c8b4259a21c752094c99e4c4788dec400d2be5113d", 0x56}], 0x1)
sysctl$net_inet_ip(0x0, 0x0, &(0x7f0000000100)="d7a8aac106fa1bee91c724b89283c1477dab85e783af4189a1eaf5f6e8251b1147b330f604ff639b9acd6202c9d8b1aef98ce6eefe", 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000140)=ANY=[@ANYBLOB="00000000000000000000000008060001080006040008ffffffffffff7f00000100000000"])
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
sendto$inet(0xffffffffffffffff, &(0x7f00000000c0)="6c25a03ae7b27b4e7fc0924a22334b9b619f09f993c214bf34de94ee6f878793a443c48892901b940ff2189ae976bd635aa66dd55818d1ca20a7f88c2ad799df41ea701f32e36ab928f0ea3b00ddc5613e3590c04b342a5ec356d4f406e612653d7338e1b59ec0f00de4b65b3f18", 0x6e, 0xab7930ffa8ff6f6d, 0x0, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))
close(0xffffffffffffffff)
syz_open_pts()
ioctl$FIOASYNC(0xffffffffffffffff, 0x80047466, 0x0)
ioctl$TIOCSBRK(0xffffffffffffffff, 0x2000747b)
poll(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000340)={'tap', 0x0})
dup(r0)
mkdirat(0xffffffffffffffff, &(0x7f0000000040)='./file1\x00', 0x0)
fchownat(0xffffffffffffffff, &(0x7f0000000140)='./file1/file1\x00', 0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000380)={0x0, <r1=>0x0}, &(0x7f00000003c0)=0xc)
r2 = getegid()
fchown(0xffffffffffffffff, r1, r2)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r3 = socket(0x11, 0x3, 0x0)
setsockopt(r3, 0x11, 0x4, &(0x7f0000000000), 0x0)
setsockopt$inet_opts(r3, 0x0, 0x1, &(0x7f0000000200)="f1e4d190c0622e6e44c6f4a60ee2cfec581c44052f117d9d8a703bc599712394ee9e6c7a868ae82a7a023e62eba89b6a4de8bf99c884c3eef4ddb20ce892635713a7037455780acd05bbb5fbf182344ae906448f1263b01defcf6727f98c962c41636d553746025d6ec459f4cd1cc5cadde66e1cae2e74a1b980d2bd57976f70ff2917b98c03d7b09ef1026e", 0x8c)
open(&(0x7f00000002c0)='./file0\x00', 0x0, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x802, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x0, 0x0})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
ioctl$BIOCSETWF(r4, 0x80104277, &(0x7f0000000080)={0x0, 0x0})
write(r4, &(0x7f00000003c0)="985fa7fbdf69aca69c9a97347864", 0xe)
socket$unix(0x1, 0x0, 0x0)
r5 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40003354, r5)
r6 = msgget$private(0x0, 0x120)
msgctl$IPC_SET(r6, 0x1, &(0x7f0000000180)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}})


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
r1 = socket(0x18, 0x2, 0x0)
r2 = socket(0x18, 0x2, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r3 = dup2(r1, r2)
sendmsg(r2, &(0x7f00000002c0)={0x0, 0x0, &(0x7f00000001c0)=[{&(0x7f0000000080)="8a07fc059328491804424a11b2fa028d6cdea11cc55e5eea3e712fd225f505867123b7f479d6809197b7abb245a6a90d101904863d6e9a"}, {&(0x7f0000000180)="02c1e20a2e0ce81d339ed28b04a60d52cda2b3c86ad335e799f27a1597941910"}, {&(0x7f0000001300)="349409068a157a5d1cd1898fdd78cf8ebee5129ab0adf53061d63d4e70ae40ab544d00f5ca6775ae4f9c1076db79108ccedc8e3783e2a86cfc619429c6ab373acab96b35e818ce5154edd20e074dbe033ba9c2af6527497f77063821ec83053996276228d6d5dbc7c13718ca1113bea34ab01fc2932518b5cf93c3a051aade6f26347a74540c310eceaf2304da2d4c37d7b6d0666a67ea50ecf1d2fb7336a52f08695592437406e2ad9d4c9ffbd260dce6a9eff53832111728a7b100fe85beeae0825a2adc97dc1d3eee31d6e482e19f50d8f03b7e92621c09de112e7663521ecb604ad3c5f7902647371e116514953405a10bc3bc5a010d9eacb8f4ede38de585066aaa8ee9dd4886ca2cad43144bd0f3c0809f05382fe0b1b018cd0a1bc3b61c0dadfbc11e7939b47897df90a75084cd4fe203623abc7bd607a2ebc5e8ff0a933cb3498567a9a2941a063d86e263090c95ef9faf103139fa509fd5c76a0652b1e2234816e854812ccac047dad28403551275abee2de74a226ffd6dadbf7b5f550c7f46fab2e11be5af4fc7bbfcbe42885f9d90ebf01523a97dc84416bb4cb755cb7d3268ca6242aa1e0c8bee4bc0efd34a28485acf30427cda6125bd71de4b53a615105e19bab53514e8b1c6f59461cb0c3b4cbb0eb88d3da0534d20a665096e396278f7d4e0789588f420df9b7025f9dec8d2f4deab15687d69a056537b44723c2c12bfc1ed2a57b6b1fa3fff9587e81272484babaf3ca670099edc163a40d67931a457fab205604347d078bc6069602a1ec600475be8d3e0beb8e2528a5bb3d937ff37000c487f7d14f5b8689bc77566719be278e2bf3a293417498c34989d159b7ab42a6d4e0a83df7d4e96f8c537c47cd3f50c19b5576a1830f51b7dd8505607401263dc37e733e5d9e6be4c4a3ce3430228a21ede7d7ad81572f33688fcf39585a9b94169107b8cd092d5bf8861177be35ab14ada48e240f90ff38556173573fe1e3697f27a94a472397b1528fc7269a83576ce8a49f9b4395ba565bb9645818f58ec1d863c61a52d7a6dde3cbf3ea0ccdfe225cd696783685784ca798e4f700c47fbc159b2b41c6573b63061ee61326545d0d815d209b6b07ffde9750a423d4ee028c8ed2ad847ed21bdb58a19c6b4af36b916bbe47272bd33cbdb2bcaaafde3be906ea31ff2f123cc77868ffcbe9cf359390daaf4377101d8454e20cddf100084c0c0688a67d6772c945d27581eb4a1b2e40b1ffe2351ea98114d14d2e4bf3df16e45ce2def4aa9d845a04a27325a697acedfb23e891eabc1e6c8df87f02dc96ad245b3f884b75ff7d6fc421eeb924595daf33bbab051533a9927706a845f92cbae3277a4092a1acc93f7db688de0622c0680b96178015232b5db6a347bb8635b1792b43998c0703519e7ed1a34d66c806e10c70405a6bbe9c62433083d7108974224d0eb76f271b317749ec4b797cadc773d3d3314d9dad7510283080372917e00860d29baba7ca6145fb582468ef85d98b5068d7d25679386c723c47b3fac841731ab44d8935159a4f0d40a937df2c26aa6d6208992487648bcf8cc29d05cb447636561a532b0006ecd363340285cab33fc67d99305b38e66d533a089c20c9c64e96c6246f3c9a6f97bad3ef1abc0854d5619aeeba72cfb62a053245e32916987175e2f527ed6145dad3d46f98b10414c9180dc2c9b01eb2b6e9a58b96547700329febf9a2d9fe9325e5e35e758559ee4648ae2bd392036496b473270cdf3c6083d67ed4752e8107fff174d787ee1067af50f2e12ad33636ca1e3e1b0b98026c1d7214390d53990a84e864b8320cbb9e21d6db32b700265386e8bd338b6b601736ab8d1d8871356ec79fef672aba8074d8acf07def315220bcff5fb03d5e7e57b1ff26732ab9fd571c2876265481f8eaae49b13c840ead6231e7f237a9fc4ed83c3588a3dee05fea7aaaa5aff8e152c8d5c356e1756b2aeeae4d778718f08847421263f2080267144f1eefa5539f8c5b320cddfd4042795822545583bd56951f3f0760b9f0f74a481f29d11c1518bca77320b96a154571c627d7b1d57f910d002b51be7b2a4c7964953c6b80d5b182b7b2227211084c6b036473143f5244ac3e3b392792c661166d694927a8cd948c2a5bb7bf10cf314cfd85f86077b41e9b34c2dee93e671a50a5fafbfcf73f64f5a1afc92d194e310d3b819b90bab16ec7aec59c176dd463c955c14d718b49ae2bc812dcc30d32ab9c83156ae7aafd507bf9901c367c84e292f0af9ea29d2705655f54223f80eee9466faa5cbc4d46ddf62b37acf12063af4024ac1e336bb457b3c2bc0f66c6418c657012bb3aecc900c16b39b86f02894fcc60da0661d0669eda1397aaea4658813ad3868b6693a02be0ff75f64a672255dcc85562fd9d52d97d3f7c911ff9de786bd607abfc6e21d06d22edc93b1c95155c5e998b1bc45b3a544cd698eaeec65322d6b7df4507b19f77d15e8856d15da2abf2be48523eeb5a9971afc617e215861740629b9f0ac1e42d0d904ebcd70e207717c16a57f938b823644cc091a2fe85dd066538318bc2cff34cd4231164ea06300b4d1de763b7eb0fe7c8600a44647e6a760eaf9e91a1482bc3a39c749a426f990db81b5a930d614fbb295d1edda9be352961685b4cd477f3db580f04ee59f27c27f212efb82089f2d71d6951bec7146efa7e392cff3776eb2d10021255a749859a082a265e43eb60896029b6af3ee4e68c02ce2e150045d856fbfca1bb1599169f492722de75dfb81ea0579a9789a1b1a964f534feea3e62d670bd4be55f84a932f644aab077bff3fa9c110224b4e381965f4a9af2e13d7771f5a77498a74deab9de3c759723c6fade4713cc1f857069d889107018d95fde366a43b7b4237e9b903e49b8c21c7ff6aeef833fd79a35c84eb60b3bbbff67ea6243fb214d54de7e276ab39ccb0c5e40489635a44c5aec4978470f068e4c264531b921ed2212f6a06a675da2607968b13984e502068e24427aea33d1647b906124490bd4e9133adb014bfe71a98de1a37566e8c9c65d119131b41980c41be9dfb4149ef4ab6ce2ec81c731466f9ad409f097f7bd0fb6134325b64ea6ab40d6dc001802c6dda494343aae424f1d0e46b582a3a849f8891bb44e4c4a47967db604643cd3c34eff4d646db8dbcb867b4fae8581bb9a14f620efd2fb654733f04420ce010de178c38ef719414990e3742c00fdfd5c3b14c4883d50a0289397fcf08f503134a12ef8f2bfd669a91a5e813535d5d256b1d98490a1795979664dd768de802a0b479b11ee72aee7a0fa021f224ea2418902d2dcccafccafb194ea7db8410e80f8648f96f46df94e5ee12c146366a7dd483caf164ff430a91434b090f07082a3ecee4acea1889f4b7be6cffa58a7f0c4c0af20af88630c9d0ebe64e65204c4da50fef9c19a3f88a57c0480abe449ea08791d5f217b927b13787962234e708e9aea67461d6e2e9db8b3afe6666a33eaedc1c0fc07160705a3098f2394f2220d91b89693eb0533b6512bf27820608d11cd8e928a636e37e296d5cb030d567cce87a411416e7bcae80d21b38b2f50cd80f7b7ad205dba1af9e76f6e91395c830cfaaf0750bddb278687d2f70977b50f3fb7dbdc3ac0aaac14dbae97f49cf40ba6832e4c016e3dd397ce0429ee0ddb637a913c200c7e9384d1f97293db4f86943449b621aa10b7868df92558b8b1788688225d07ea0000cce709ce67ba7be299d0fb950c602da1d0228a61d65130879f6015d3b4787096f04e9a8737d627d4cafbfbe60df40f1dafcdc029d9bab336aaab0a8e9d49e61b127687bbfa40b6e126031be5ab2045c1d5f9d8c5d8f2dae487f5639ce0f57a5fe908d18a282b86c78e8cf6b2bad426d22742f414b30d05386788e65b8ee3b58c36f7cfd1e01e51f02491a0c239ff7d4fefff13dd3565e7075714b634a3c764a1a17126a3ccf451fb60e593be9551b481e4c93c268c6ce7feef26b54497907c721963c0cf6964bf7c194c137b2acb78350854f0a72503444b799d622d3342224e10cefd05381a222e99648882a4f39b65bcc62b8a6618075084819074dae6325e1826a68ccd45b940d8b7bcd38c00ecbfe72690142cf8ffa1b86c37ad7e80f0cf2b39abe0afbdca0f17c97b6d7ec666f335e7ef848946f876870c74fec8dac0beda5f8f5514476304452b936f0e343e440460d578d80eb42d99034b5894b16049f28f1e0d7679f35b672bd241d7bf96f2ef2484b85a12743eb8434da5e35a6c99eeb451b289a96f0a0d41e9d555508de504ec63c4628c02abea2d0ace115b7b1fcaf3679d4f68b45785e1ff2d7ab135834f5a34d69a336e95e64eb754ba9c67cb9787c2cb4a115f09fc70ef5bd87295b0287a8fb33789d53c9de6daa6058e29b017af3acbaa3269c109f131737e91cded362de0a080577affaf912c25a302ada66f94358a1baf648a5d8f20a7d588b159e49ff9ad9634fac8708093990e5cab88d4b2c52818c9fcfb584b9a83bedccec466e94dc5cebd892d89b9059b69ed69ebd52f5a736fd8dd8caac0c296a8e992473cc374d81dd5cff98c7788ab590e450b3b0e2f3d3353e14dfe849847b8b263407c7ce0e45ea70192bb7d0f96ca5846973189abbc9e71f73f2ab4395ba9e2681c67aeee2b6d3ce009b517c0872f3b6b906b9ca86e15196d38aef602a5ee671d511993c940802a4d3c4cf98ee012f5111e9c10e46cf2110afd22ed016238e16e8f1e9bac75c84f59b692e2cc6e4f9e0edca7e85c7fd19989f9de4ea904a572de19af3b8c70319139c0d5c035e54ad3436f6e5cc1bda4e252dbe5335fc1776794926fabbab1e7039e43b112c3b83841fadabda56f531245b1140483fbbe548691b3ddc569fa2b5d156698ca78cdc5d11aef9363fe85eff0dc2292024bba9f055316b1f0b9c08b7729620e4b459d7ceb47ba6de350421dc71698b1494b14bc35be2c21cb125c36230599ba362206d8b9819e8a186d90a218b6195c26ea7e6d215b8c7f210e350396e87e3b9fa302366a91327be7040272d04125355876cecb6d8f6ff13115806cc946f63bfa4ea7675eb11fd027a13fca8375b4682f4b669fb9f7f04320d93e7f665fb3307092e4bc958b4d33604e262f374956f87cc811becd7313c91bbcbefbd4356426d90cca601092a90d16c8dbd8e5e8cfa2d4fdb0a6706682c993336be10378492a9c980a5def332c2a3266f4c3460d9ac4a06eac3addf223454d6896ece7824efadf29f14c8e36b9631891143c952e1f67ca3de76f93ce410d74147eed5af08bb3ce37eebd3cbbb2baf77ad57ffff186f13ee31b263e452c4a6780e677188f872944d2496167ce92eef6f33b16232e6de544c9d0d3a77df877c7ee3c4e2b464fd261c2446bc71d20bbd9947e1de113933efe365bebd8b1de05f0cf11d842c9cd9cbe03dfdd0068ba7e207e48d44e17458ac4420769ca9f3d9cc11bffe6cc16313167b605cee6513989fedd77b076a57a6779cc3cc724b1e2fc219bab630f310e7ec903e74d2a6deeb06179c1d8690ce46a398eeb318d61ac4cd66758f6262235b931c510a5b78f02a3ae00258cebf0ab362c0ec0fbcc6e41b7c6b83f441cfc907d811eae3a39aaaa0b91bd3a3066d1508da3e3df742a97e5e4ff88c2a56655f3efadbf78cab2f32caddf31b9513036e5cf038fbf5641cf1b6e75a961d91e43b299b4e72b6d210902c1a9ca933c282c941b14f336dff31bac5848f12e982b99b7285e128fb000000000000c6159beeddf2165aa1fe5374321ee849bb33733832fb16632ece8fedb7b06d7d2b0159b2c9a85907ca47be9e7c17bacdb2ab0fb592945fa51be18ace572681be61"}], 0x43, 0x0}, 0x0)
connect$unix(r3, &(0x7f0000000040)=@abs={0x1, 0x0, 0x0}, 0x8)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
setuid(0xffffffffffffffff)
r1 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r2 = getuid()
fchown(r1, r2, 0xffffffffffffffff)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000040)=[{0xb1, 0x5}, {0x44}, {0x812e}]})
readv(0xffffffffffffffff, &(0x7f0000000800)=[{&(0x7f0000000500)=""/120, 0x78}], 0x1)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0xff}})
sysctl$hw(&(0x7f0000000000)={0x4, 0x18}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x1)
sysctl$net_inet_ip(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000200)={0x0, 0x0})
msgsnd(0xffffffffffffffff, &(0x7f00000005c0)={0x2, "2f3b5d883810b4ad6915914c9aa27aa3b06463abe071aac2b31590015dbed82ff2f0a12240f7fd961311f2e2c99d7f0ee8f994279eef1e814cbc67cbe2fc0dadce4ab318240f6044c166229646a48623582f52b1aeb01a76b51a8652d90085e2e9a994a461f3de6e5189bfafb295b0249df56b6b22d590932c37c5f8e09b6e66619f577becadc7336c9cad91b4ba1421632ebff60c41a6347b6365347d3bebef5ec44e55c3f8198bd72617475f515ad353a18cc491a212b90d426e4820c9c2499c35b31211c3b9c494c090a34b824bc576bc30133ec15b69c8127252c5996ff1a5f5c83dc114c30593f532dfb3b87f89b43902cdf5ad2555428fa18d1bbaff1fb0f02331e12ddb2ca0cb87528636eaa52d1503209beabd269efc6c8a2926bb74cfb4a5367295222436c1a75ee037dda27e0e716c71ea86def5a7c500196ca2085fd8917263d21db432fcc1d6f4ca5995d99d512ab8d58e66fcc1c8bd3c5f10bfeef78bfe75ccb64a3e74fd374684b8e6fd428d7fb4d42e93eb0cdae09da25283fe0e5011020e57977dbb0fc1916957f37df02679309d6b5b2c06ef9d34b2dfff0c0c1a37ab4316b006fbbb0e8b7613439602483bd0d06f69ff3d8e9bc2e0641b561838b3796bba4adaa0ba29ac1c29223e66a66299e8f7ee8f05e3db7cc111d0af022cb23ff54ae24170a06ae94d5e5ee3e9117069c0724207063eb7d0a1f20b915fd67d6a91cde9031c8557a4aded7e204f6c9811fcc3c680da320104a6fc223d8de29321e2a13b7db743e9df673728499b36f573b99cf57c04c6bc74fbfa51e19f8797d0a09da45b35c877968b9064c075ee338192938ea8f2890f593eaf89d037258a3b6c82f87b8e0d6360b602c02352a36c6f208f6a5fcf765af61fb3abd79e64cd77b16b42a5ddeea47d1db13a7c9236ef01218fa354e487f2bd9e16263d30094a8890e22dc14f9c3542bbd6372e5ebdc9e7c5b9cbcb8c4e940e1158fcec2ba6a92eae3fc0f3beed413172040210c1845a880affe681a0989ac41a838bc296e2920f601b638a3d97979691e374fe6ff939f3e52ac546a6a41ea5d53cbd22323ed568834c49681f4d9e082b7546ac1e23671f7c4adb2c7165a62067f68ab3d4627e5bcbc05887107d7d844f6b72df6ea020547c4b694ef00a09824e59dd1e12d8f80936bf2febafe37975f485ae8be36d7c44f6f6df34fcc3e43295aa4155e3a6cf615cbe345a2f45104544e4dc9ed357c174f89321f4e71936891c2bd275c98915019244c52b072d5692d4c232b9490bd6b8fd9060e96bde08101f2610120e0599c21ed5c2a016bb7bbc1734f0c38f5bc11f17f7deee890dd995527bc42eba5d33969e0ff740c8c49518c7f8563e7aab5a7e5c422bcdce9e8ae484f6021161d38769dfa27ca1916129041c0d007ce80f12307bbb48697adacb4a7690ef8119a6a47c099630c101b52f94b918d3bf6a6d0fa5d7ed4b87f7bb0f7e6d47cb5ee5d19dd3d9c6257be69b11c24a8935f05936fb6653b9505d6aecfa3f95201b750b20e0169e5e8cd9ef5af456e1ac3cc62f8242b97c78c7352966b41a67ff170e6260d80e12e0f9fcb95367912013cb90c17bb8cc25233f0f8c314ab741672269816678a3153411d938d1f99dc144756dacbffccf9d88c1caf1c4a2528c26a3d240e0dc7756a2eb96b2e27494a183e6850141862b55ad7db52a2515ba6ba00427e919962ea10f726dfbed6e8f97139f17d226cd5325096ec6b723bab4cc72d0f4a348220ce99ee808bc721ca795be73954750d4a8f983f76129841fc81b424b31853298a312a87c9806af1d8720adbf4d3fe38e6936d561bd0f96c341edb605fe66149bbee598e00a7438ec82836f578de3405aa8d2c048c61381602b46d64cccd3ec465b82b6448ef402838c220a1f8a6e4413c64164a4337d0d00c9939ecf6f0404ebc505c5e1e783c76fe090adab3531ca805458ed0c6b625f74ce88abc79ff23fd7838d7daa508c0ab59922b4469109a2bbf5ef7f8301e3415348f69e628846a4c9328fcd7370ad6b3996d73bb1863fbd25d36d35d6e75996150a3ee2d9ca2cd0a3e3ea8908adfb3a6b599f483fd87faa8d8fc2c3035a8632768abb698868a0e7285f98eb3476f40eb68f76ff2c19007901209c4a8853e7c4833bcda6d1819be112f37dbb230d1ca54037fc0b06da8d4751af9af19606a6df446f02e5dc79aa72792c792e152a81a5af8b3a43f580aac092f8001065aea9fe1c70788680b8606aa93a4a4f62da273d857c39475234dce51cc217ca20be69c04df91c128c383113c11d5c7126a6e8ada1b9e1665d39dd13aac2b2514cd8a29246dc275b0c9007cf9d591b7e69f2077322bf58bd9c20d6eea62b3cddda153c87494bb93e2951b1e9b859537c58725cd79834f43364920a895d45ab57029cd76286a195ee4914e617cb38b367328f3bc127351d09739a46e49dc807299895de45f2acc0c2b1c03ff74ea3c4d49c3c2b80d038ce30d734279cb7c6e75ab5263a966043b519d16dfadcf157c288e03a365c5924bfb42bd2c3220d67a1fb714e333160acd70133eff32476f3bf0d5f92f3146fdc82a2fdae9f77c69e35e7f4cc4e3c597bfd0a3798c9cccd7c96e9192120c5a6b22feb1bc8093512a2bd42b08b5e4705a0bf8478d86775892f6a9463266e86476da7dc60cc1bbf7cf7f2be2e353cacef8e70e765c34e78d2905b935cc1118e15c94c7ee8f0d06277701a64447d73679f6895a48a6f0d1d4928e1816cce18bf136c56d9c99896c5affabef8b0d67f5ca02bd3c3a36996f64f630b8c3e85644642164f41247bde676c2426bfd394efb090afe0e4a966da1e682a45b279259f94df15610753bb62faec3e2347d6807e7fc8c7d631b81ed8f1cf47935aca6391742c387e67a0102a20b05e8d98703ad04b669707987e58a36606f7f1a9a86c899e8bfff416d9b29981b339b7c367e6c46a9e2a460a0a9d96c8d75e8a6a5ee9da04cbd07b2a233812caed6ac71e3d00e6a4017358016db7a91b29905de150cd309f7e02acc55e0520b8252320019b0905b3f54a5384550a3e95ecf52507e8b0dbeb3729d165670f84e071d2a0c04106bf2eff8e4fcd37495a7a9cc2c07c3f6cbaf9e4d9afe8d9665529df61f3013fd58f65b9307ee211faab57e20c6be49e99832116829230fd807d41b902b45865e018aa2369715cd12c4b7cc188a38fb2da08126fe96d7d0580548049a50820c8b6ade9df99538a5804a41b5440ba7bba325716b3bdfa3bc3c3a736367a9e96f7a2c51715c227c87b8728f65863c6c028abfcf78184a17b33c43d402f0d208a3e87b17b4b4cc1a6d618aae825780d53ff936695a26d5a1d3f323a4e8ebfb83f91987f3b4780ea4c971e150322aff2a758735c3fc9c12884d330dab683ca8cce2f83fe904c5603e0b4522a96ace4317f948f1d748f78ec5032f582053421dd1ad437ec3467353309fd30dc525d07bcbae262cb66e02e796b95407f6d1c5a0470089db4c099a35d28c140dcde594af55628ae5bd6d3600cdeae2dba284fd4ca9a1ada4573b08769f7f44bf94fd114951119776f2e736fe85a4ca28ec2eddbece70c2641a87b058ef7ec139e9ea92a2674efe075c15535721c22efca541513386b523a8ff84286809ea55ab9f6994207dc1b5ce8082e64034c445aee941a7e239954185c8da762694be10ee2a56b75c09ab0de1b9090ac5315613913972648c0e3d37d122e5c799e133b17230995211a83a3220cac73c6e78a5dc13ec562af4862e229bfc3d7d05aa6dc7797e0ae7574353bb8228a90406cdc924ed4ddd063a7986559f9bc9fd583f7edc9bd5a63be8c3b04af3bb804e25f574210fbc9bc2426f9bbc807cdda382fe7223e5ba8fe7a3c543d393d33c24669bc2ee1f901027a4c91602e61512126e462e9edc2a61d75dcb24af5c57d9c81ecd007792c6a2272d4d717d9a56ebcc33c20a4a61c2b85ad572b54c71f25812aee675e413d7eff9d2c66497e462ff2d3188417ce47ac6080f7d704d55ba67ad4b77e1e229b72f84d9a6dbc34060c72a0c0d5788fd6af1cbd0dd5735d2acc7614df6ecc358f2c4a739588505ec7fa29e337ac1a065467d7e1c47a162b94c6eb57b461d6e34d5a8433b71225683a226f9b8f631285b89629286f700edf204147784b8d6b19b8c6eecf00b3bcec336dd652e743f53d37f956ddb7a62cccee9c29faf3c22a28174b191cfe1dd483ea8338ee2ef77557141d79afcc7f6d1808d08f02bc0317fcf5df738a496cd83cc98989c6261e0e5878a5e533fae0207ea3f1c90e7717576cf2f7c8fb90b1e9372a2db3d08bea01e3cb8a71df2cb63ae23f869c362ed160241439858a1e5fc90988b9c9de53afa73a1f96c9f5f45414a555198fffb2c7b1d1f697812a1b12b24a490b2de4ccacca17726d878e5eb3e42b627a7b5afa0d780652c48a09a51afcb405a5d2040ccc816ad3385671e88469c61f1c309b005a9be45a697a104c16b4a523d64d6cf559bc90d9e69c8b0fd36e0e71688672e7d3bd001ad2144cc1c4886b6cc7a4b0c42d9c4ebf233bae69b091d87dc41a2967487c08d45d4216c08a243efa4a15c80d2fda4e31ac6d349fa140e0305e4a20798bb8b41c76cdc112afa82ddbdfa0e9a9997aaedda454e8bf8424fac75acaf6a2b96de23648098dcc60391a3a42c74c0665e014c656b55437946025f02e0f1228cdfafcad88ae97d8e87f41b019becc1d5010bccd12b3c2df5c98063c4bff329b8291a03b22101586548375f6764073619bb47478140c5edd660778c7e58d1ab5d325f68195e05b65758c899a1f3db87b9fb49531d772e235fae11bda86d0c06c6a0dbee9d3d683d73202aff512f0491f1728e291bbea72e850ec104b9eab04ea137c5703d23436f8cc08741be30847485f6394b0369022223422b337e2dc841f90622b7a0997d037ba0f59d3a6a752d5814fd170ac3e0690d6b6b804e5a2ca2ae41227a9b5df2546c50a7a029ff9d9838b11714a459f3c32218ec86f2358ec7714b23275cb73549c7c7158689dacb13998f7a4dc8c26c034f82c28b6643cba0f318df85fdf72b3720b174aa9291d3d099e250f1a27387b16460087113f1b7bd0344d069b409cfd2eb799628fc5112651a9db094621550af6a7d22666c085b78bb807a76b410f9c0fc79e31a57ab61904b6b7f181f3740d129f58cb1037556b8adbc3c8ceb7619042fe036ad4a465246f14a52d55b2c8cad8ecd757c98511a310d1e91e7913e505849a9a351c798277b1b42aefc58a6093eaddf86bef963e0354c165b5583b40363c1ee9285809e7e850a1fb3663d17b7f55a1802f760442a7ac7166a93bebbc8a1d457cd98f51519723e674ec0e4541eff9b4d47be38912e0ad418c2b435f926001bb8cfa9013d31c1a13627256b07add052e55ee1c83c714fab6a1cb021ea3e74b58372673cb2d49e9e97fbe"}, 0xf29, 0x0)
syz_emit_ethernet(0x189, &(0x7f0000001580)={@broadcast, @empty, [], {@ipv6={0x86dd, {0x0, 0x6, "2412c5", 0x153, 0x2e, 0x0, @empty, @remote={0xfe, 0x80, '\x00', 0x0}, {[@dstopts={0x2, 0x0, '\x00', [@padn={0x1, 0x4, [0x0, 0x0, 0x0, 0x0]}]}, @hopopts={0x62, 0x0, '\x00', [@enc_lim={0x4, 0x1, 0x3f}]}, @fragment={0x11, 0x0, 0x1, 0x1, 0x0, 0xe, 0x64}, @fragment={0x67, 0x0, 0x80, 0x0, 0x0, 0x0, 0x67}, @dstopts={0x62, 0xd, '\x00', [@ra={0x5, 0x2, 0x843}, @enc_lim={0x4, 0x1, 0xf9}, @enc_lim={0x4, 0x1, 0x80}, @ra={0x5, 0x2, 0x2}, @generic={0x2, 0x53, "4edaa9fed53b69e4089aa4b08498b370315a2311941b397f1c1ab49388f3713fc487be8c22da11aea3686df0c5c3ac7d87c1268e71234dfb0969ad8c2e6b1bcb8ccdfde05a9392f9e8685b48e5c8c213b2ac72"}, @padn={0x1, 0x4, [0x0, 0x0, 0x0, 0x0]}]}, @dstopts={0x16, 0x0, '\x00', [@jumbo={0xc2, 0x4, 0xfffffff8}]}], @generic="85168e8621b4b0be93f99a52efa2fe24eaeaa9ec77b437d40ad27f57a857f8d857a7a484ec7b0c7650746668837a8112c082c59726b5da1738219277bb63fc605ff5c970ae86d63334cb70234bd9768e84ea8c70812cb78886d7a78df89687c5eff1431ba72cff5e7e01724984f1ee3a8b08ab9d7b9c9b20c3aedaf6b61691327f019f7b75df1b95eb5439667ab120c537985fcd8f0046b67e5619"}}}}})


writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000380)}], 0x1)
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x6d4)
r0 = open(&(0x7f0000000280)='./bus\x00', 0x0, 0x0)
ioctl$FIOASYNC(r0, 0x80047470, &(0x7f00000000c0)=0x5)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
ioctl$FIOASYNC(r0, 0x80047460, &(0x7f00000000c0))
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x0, "0d0e5012c3842ffcc300"})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x7}, {0x7c}, {0x81ae}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


munmap(&(0x7f0000ffa000/0x4000)=nil, 0x4000)
madvise(&(0x7f0000ffc000/0x1000)=nil, 0x1000, 0x0)


semctl$IPC_RMID(0x0, 0x0, 0x0)


open(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
r0 = getpid()
ktrace(&(0x7f00000003c0)='./file0\x00', 0x0, 0x1724, r0)
r1 = socket(0x18, 0x2, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001600)={0x0, 0x0, 0x0, 0x0, &(0x7f0000002c40)=ANY=[@ANYBLOB="10000000ffff000001"], 0x10}, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000080)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
r4 = dup2(r3, r1)
recvmsg(r4, &(0x7f0000000280)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000240)=""/11, 0xb}, 0x0)
sendmmsg(r2, &(0x7f0000001600)={0x0}, 0x10, 0x0)


r0 = socket$inet6(0x18, 0x3, 0x0)
getsockopt(r0, 0x29, 0x69, 0x0, 0x0)


bind$unix(0xffffffffffffffff, &(0x7f0000000040)=@abs={0x0, 0x0, 0x3}, 0x8)
socket$inet(0x2, 0x3, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r1 = open$dir(&(0x7f0000000080)='./file0\x00', 0x402, 0x0)
writev(r1, &(0x7f0000000800)=[{&(0x7f0000000400)='S', 0x1}], 0x1)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, r0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
clock_settime(0x100000000000000, &(0x7f0000000040))


sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0xffffffffffff0000})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x400000002, 0x0)
r1 = socket(0x18, 0x1, 0x0)
r2 = dup2(r0, r1)
sendmsg$unix(r2, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


mknod(&(0x7f0000000180)='./bus\x00', 0x2000, 0xd01)
r0 = open(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)
ioctl$VNDIOCGET(r0, 0x41946472, &(0x7f0000000000)={'./file0\x00'})


r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0x81946467, &(0x7f0000000180)={0x0, 0x0, 0x0})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000080)=[{0x4d, 0x0, 0x0, 0xfffffffd}, {0x74}, {0x6}]})
syz_emit_ethernet(0x17a, &(0x7f00000001c0)=ANY=[@ANYBLOB="f3a2a8908a86aaaaaaaaaabb86dd601ab5b60000100000004e95"])
syz_emit_ethernet(0x126f, &(0x7f00000000c0)=ANY=[@ANYBLOB="aaaaaaaaaaaa00000000000086dd609ded1a12390000c4a4e3434e58d025a6a8a81cf312b8befe8000000000000000000000000000aa00030000000000000101000101000401000401000103000000000100010200000000c7ab6f1eba08bf03d1805fce0ef2ab82f4a065245eccda108bec7cb23f632c993265a4cefeb77b1406d562a47d4b0054943553278b519ed107f62b5c352f8e68d83c1fd85b8e1083556d7fa2fc09a3e823fa940de6ef1b18ddb2a2dba0d2d9c1b44b20ed3a932a2c47f4f4d3e34ea1b67a607001a4541a87d5d347b5049b3444dc2b7abe3499079a5701e88493acb2eb1808e8b1f74311083f93341607915aa46325934e81b672d809cb6bc5f3d64480ba4db4432a67c2548e259fe7831f7c6dfe"])
ioctl$FIONREAD(0xffffffffffffffff, 0x4004667f, &(0x7f0000000340))
sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f00000001c0)="55f8f5782087a072a82ec35f78d14780f518", 0x12)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
preadv(0xffffffffffffffff, 0x0, 0x0, 0x0)
r1 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc1206949, &(0x7f00000001c0))
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000280), 0x10000, 0x0)
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000040)={0x6, &(0x7f00000002c0)=[{0x2, 0x4, 0x3, 0x4}, {0x20, 0x40, 0x1, 0xffffffff}, {0x2, 0x40, 0x1f, 0x6}, {0x34c, 0x0, 0x0, 0xa7e}, {0x0, 0x3f, 0x7, 0x2}, {0x1, 0x9d, 0x7, 0xffff}]})
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f0000000240)={0x1, &(0x7f0000000200)=[{0x6, 0xdd, 0x7, 0x8001}]})
syz_emit_ethernet(0x138, &(0x7f0000000480)=ANY=[@ANYRESDEC])
sysctl$kern(&(0x7f0000000040)={0x1, 0x41}, 0x2, 0x0, &(0x7f00000000c0), 0x0, 0x0)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x7fffffff, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r1 = open(0x0, 0x0, 0x0)
ioctl$TIOCSDTR(r1, 0x20007479)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa", 0xa)
setsockopt(r0, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000380)={0x3, &(0x7f0000000140)=[{0xb1}, {0x4}, {0x6}]})
syz_emit_ethernet(0xa2, &(0x7f0000000600)=ANY=[])


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, 0x0)
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])
r2 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r3 = fcntl$dupfd(r2, 0x0, 0xffffffffffffffff)
ioctl$FIONREAD(r3, 0x800c745b, &(0x7f0000000080))
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000200)=[{0x2}, {}], 0x2})
sysctl$kern(&(0x7f0000000000)={0x1, 0x2f}, 0x2, &(0x7f0000000080)="9336932503a6874c767ba2e4d26007d11eb4bb37ba1123ed85a1215ddb1292419b", &(0x7f0000000100)=0x21, &(0x7f0000000140), 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
socket(0x18, 0x2, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000080))
dup2(0xffffffffffffffff, 0xffffffffffffffff)
accept(0xffffffffffffffff, 0x0, 0x0)
getsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
fcntl$setstatus(r0, 0x4, 0x0)


clock_getres(0x3, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1004, &(0x7f0000001140), 0x4)
socket(0x11, 0x3, 0x0)
select(0x40, &(0x7f0000000100)={0xfffffffffffffffd, 0x9, 0x0, 0x8, 0x0, 0x8000000000000}, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000001a80)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x0, 0x0})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
sysctl$net_inet_gre(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$vm(&(0x7f0000000000)={0x4}, 0x2, 0x0, 0x0, 0x0, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f0000000040)=@abs={0x0, 0x0, 0x3}, 0x8)
pipe(&(0x7f00000001c0)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
openat(0xffffffffffffffff, 0x0, 0x0, 0x0)
poll(&(0x7f0000000040)=[{r2}, {}, {}], 0x3, 0x3ff)
close(r1)
open$dir(0x0, 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000140)=[{0x7}, {0x74}, {0x836}]})
syz_emit_ethernet(0x26, &(0x7f00000001c0)=ANY=[])


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
seteuid(0xffffffffffffffff)
r0 = socket(0x2, 0x2, 0x0)
r1 = dup(r0)
setsockopt$inet_opts(r1, 0x0, 0x16, &(0x7f0000000040)="fd0cc085", 0x4)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
recvmmsg(0xffffffffffffffff, &(0x7f0000000040)={&(0x7f00000000c0)={0x0, 0x0, &(0x7f0000000580)=[{0x0}, {0x0}, {&(0x7f0000000240)=""/76, 0x4c}], 0x3, 0x0}}, 0x10, 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x18, 0x1, 0x0)
close(r3)
r4 = socket(0x18, 0x2, 0x0)
r5 = dup2(r4, r4)
setsockopt(r5, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendmsg$unix(r4, &(0x7f0000000580)={0x0, 0xa, 0x0}, 0x0)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ff3000/0x2000)=nil, 0x41000}, {&(0x7f0000538000/0x2000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f00001f5000/0x4000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ff3000/0xa000)=nil}, {&(0x7f0000ff2000/0x3000)=nil, &(0x7f0000ff9000/0x3000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f0000ffa000/0x4000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f00001f4000/0x2000)=nil}, {&(0x7f0000002000/0x1000)=nil, &(0x7f0000ff9000/0x6000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f000009f000/0x4000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000084000/0x1000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000161000/0x4000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
mknod(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
sysctl$vm(&(0x7f0000000000)={0x6, 0x6}, 0x2, &(0x7f0000000040)="279857da", &(0x7f0000000080)=0x4, 0x0, 0x0)
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000280), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r0, 0xc2585601, &(0x7f0000000000)={0x2, 0x0, 0x0, 0x0, 0x0})


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETAF(r1, 0x802c7416, &(0x7f0000000240)={0x0, 0x0, 0x13, 0x0, "5238f0980ba4b3c8b9129c9e242fd505aac10fe3"})
poll(&(0x7f0000000180)=[{r1, 0x1}], 0x1, 0x0)
writev(r0, &(0x7f00000001c0)=[{&(0x7f0000000080)="536186db8d1f7787522ed0aed7c6889cee96f819992fdb353d1d1a014cfa22cd77ceaebf78091295a09007d59e7953edf8ab77149cb01367db7d4948fdaac3532e78e2032cbd628df8599f808e366013f789d49bb9c2a802994e11523e233bdb399b016ccf7f7638b3af6c623cb247740b0679b7e0123372ac3672cc4b7bd662b154dc32e845ba7aa807b9403a9d4c06d96c52b15dec6dd20a", 0x99}], 0x1)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000140)={0x0, 0x0, 0xfffffffc, 0xb55a, "1a2198b59b58505f40edabfaffffece900"})
writev(r0, &(0x7f0000000900)=[{&(0x7f0000001a80)="415d1d50caf913d67b66975cb99b", 0xe}], 0x1)


sysctl$vfs_nfs(&(0x7f0000000000), 0x3, 0x0, 0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0xfffffffb)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x1, &(0x7f0000000000)=[{0x0, 0x0, 0xc0}]})
mprotect(&(0x7f0000223000/0x3000)=nil, 0x3000, 0x2)
clock_settime(0x100000000000000, &(0x7f0000000000))
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000180)={<r0=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
mprotect(&(0x7f0000c57000/0x1000)=nil, 0x1000, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, 0x0)
syz_emit_ethernet(0x56, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x52, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r1 = msgget$private(0x0, 0x0)
msgrcv(r1, 0x0, 0x0, 0x0, 0x0)
msgrcv(r1, &(0x7f0000000140)={0x0, ""/12}, 0x14, 0x0, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x5200)
ioctl$FIOASYNC(r0, 0x8004667d, &(0x7f0000000300))
open(&(0x7f0000000040)='./file0\x00', 0x2, 0x0)
r2 = open(&(0x7f0000000480)='./file0\x00', 0x80, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
msgsnd(r1, &(0x7f00000000c0)=ANY=[], 0xb9, 0x0)
open(0x0, 0x1, 0x0)
readv(r2, &(0x7f00000003c0)=[{&(0x7f0000002580)=""/4096, 0x1000}], 0x1)
preadv(0xffffffffffffffff, &(0x7f0000001540)=[{&(0x7f00000001c0)=""/204, 0xcc}], 0x1, 0x1000)
msgsnd(r1, &(0x7f00000004c0)=ANY=[@ANYRES32, @ANYRES64=r0], 0x0, 0x800)


r0 = kqueue()
r1 = socket$inet6(0x18, 0x3, 0x0)
kevent(r0, &(0x7f0000000100)=[{{}, 0xfffffffffffffffa, 0x5}], 0x21, &(0x7f0000000180)=[{{r1}, 0xfffffffffffffff8, 0x84f379cb36304153}], 0x967, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000140)=[{0x81}, {0x25}, {0x16}]})
write(r0, &(0x7f00000001c0)="d9537abde93d050cdd16b13f742a", 0xe)


open$dir(0x0, 0x0, 0x0)
symlinkat(0x0, 0xffffffffffffffff, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sysctl$net_inet6_ip6(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000100)=[{0x7}, {0x14}, {0x6}]})
syz_emit_ethernet(0xe, &(0x7f00000000c0)=ANY=[])


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x1, &(0x7f0000000280)=[{}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)


setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0x0, r0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x80286989, &(0x7f00000001c0))


setregid(0xffffffffffffffff, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
mprotect(&(0x7f0000ffb000/0x4000)=nil, 0x4000, 0x1)
mlockall(0x1)
munlock(&(0x7f0000ffb000/0x4000)=nil, 0x4000)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
open(0x0, 0x0, 0x100)
semop(0xffffffffffffffff, &(0x7f00000002c0)=[{0x2}, {0x0, 0x2fe}], 0x2)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4d}, 0x2, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71", &(0x7f0000000400)=0x15, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000080)={0x4, 0x2, 0x0, 0x24}, 0x4, 0x0, 0x0, 0x0, 0x0)
r0 = socket(0x18, 0x4, 0x1)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
socket(0x10, 0x2, 0x41)
ioctl$FIONREAD(r0, 0xc0206925, &(0x7f00000001c0))
sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000000)="9b1809ffffffffffffff7f473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6fd74c94d1b44", &(0x7f0000000040)=0x10011, 0x0, 0x0)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
syz_emit_ethernet(0x23bf, &(0x7f0000000100)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaabb86dd6085ceb2ff61000000000000000000000000000000000000ff"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
recvmsg(r1, &(0x7f0000000100)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)
close(r1)
sendmsg(r0, &(0x7f0000000380)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
r2 = socket$inet(0x2, 0x2, 0x0)
getsockopt$inet_opts(r2, 0x0, 0x23, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x1, &(0x7f0000000140)=[{0x4, 0x0, 0x0, 0xfffffffa}]})
socket(0x0, 0x0, 0x0)
getsockopt(0xffffffffffffffff, 0x29, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000100)=[{0x2}, {0x28}, {0x6}]})
setreuid(0xee00, 0x0)
getuid()
syz_emit_ethernet(0x36, &(0x7f0000000000)=ANY=[@ANYBLOB="ffffffffffffffff"])
r3 = socket(0x18, 0x2, 0x0)
recvmmsg(r3, &(0x7f0000000680)={0x0}, 0x10, 0x0, &(0x7f0000000700)={0x0, 0x5})
poll(&(0x7f0000000480)=[{r3, 0x24}], 0x1, 0x0)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


syz_open_pts()
pipe(&(0x7f0000000840)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
r2 = socket(0x800000018, 0x3, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x4000007, 0x4)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x120}})
bind$unix(r1, &(0x7f0000000180)=@abs={0x1, 0x7, 0x1}, 0x8)
syz_emit_ethernet(0x12a, &(0x7f00000005c0)=ANY=[@ANYRESDEC=r0, @ANYBLOB="4554fff8aa6c925b28d0675dd2ad717f5ec0a97c53068f69259e4d84f1db00bc1165ff577e07ae84c20fafe5cf39e6af7454592549a49772a74e6fb1e14a5c9be1946ecf16b701416c5c2717e4529b7812ceea40c4c4b1e603f32272ba784819b761dd08fd93bc81a02e791894c90234ecb7250e94d5e847b4574d81e1e0bb4b3abe017dad23a7a6cbd6543529fde1d528100310a2ba118d307abadd4e8096257ec7914dcf1b6083a7ef5148ba5c5b4079450bb324e5ce4cedd238ce387c53e5afee"])
readv(0xffffffffffffffff, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000380)={<r3=>0xffffffffffffffff})
ioctl$FIONREAD(r3, 0x8020690c, &(0x7f00000001c0))
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x200, 0x0)
pipe(&(0x7f00000000c0)={<r5=>0xffffffffffffffff})
fcntl$setstatus(r5, 0x4, 0xc0)
r6 = kqueue()
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f00000002c0)=[{{}, 0xfffffffffffffffa, 0x83, 0x0, 0xe7, 0x5d3f}, {}], 0x20, 0x0)
r7 = fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000240)=[{{r7}, 0xfffffffffffffffa, 0x95}], 0x0, 0x0)
kevent(r6, &(0x7f00000001c0), 0x9, 0x0, 0x9, 0x0)
r8 = getpid()
fcntl$setown(r5, 0x6, r8)
close(r5)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xfffffffffffffffe})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0x3d, &(0x7f0000000040)="00fb6c4f", 0x4)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r0, 0x0, 0x0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
r1 = dup(r0)
pwritev(r1, &(0x7f0000000140)=[{&(0x7f0000000980)='o', 0x1}], 0x1, 0x0)
writev(r1, &(0x7f0000000540)=[{&(0x7f0000000240)='<', 0x1}, {0x0}], 0x2)


open(&(0x7f0000000000)='./file0\x00', 0x9cab835cfdc52675, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0xa011, 0xffffffffffffffff, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000538, r0)
r1 = getppid()
ktrace(0x0, 0x5, 0x40000d30, r1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000300), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f00000000c0)=[{0x30}, {0x84}, {0x16}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f0000000080)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000700), 0x0, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x0, 0x0})
ioctl$BIOCGFILDROP(r0, 0x40044278, &(0x7f00000000c0))
r1 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x4, 0x1100, 0xffffffffffffffff)
r2 = socket$inet6(0x18, 0x5, 0xff)
recvmmsg(r2, &(0x7f0000000400)={&(0x7f0000000200)={0x0, 0x0, &(0x7f00000008c0)=[{0x0}, {0x0}, {0x0}, {0x0}, {0x0}, {&(0x7f00000017c0)=""/185, 0xb9}, {&(0x7f0000000440)=""/222, 0xde}, {0x0}, {0x0}, {&(0x7f00000007c0)=""/238, 0xee}], 0xa, 0x0}, 0x6}, 0x10, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000280)={<r3=>0xffffffffffffffff})
dup(r3)
sendmmsg(r3, &(0x7f0000000040)={0x0}, 0xffffffffffffff12, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x3, 0x0, "0100012d29fb000700000000098002005a00"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x45}, 0x3, &(0x7f0000000180)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b10689ca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d12727b1e1d0cc45c7ebd5df53fb588fd0245528fe5700a5868eaf74d373197fb657a56e99cdbddbb382ad676b756d4e8b5a81c9a624348f23ffd260bf5fd344a7a30bcf96e47800acc166910bfc34ce76252dd12fac3b10dd5719aa6e420f60e3d2cbb22f5b3a6f7fa3c909e4823cdc0cdf126bc29456035b9a44ff74d852ba5c", &(0x7f0000000080), &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0xffffff25)
ktrace(&(0x7f0000000080)='./file0/file0\x00', 0x4, 0x800, 0xffffffffffffffff)
getpgrp()
r4 = msgget$private(0x0, 0x421)
r5 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r6 = dup(r5)
pwritev(r6, &(0x7f0000000140)=[{&(0x7f0000000580)="c6302c9c455c7be3d8598d3ac53af8e7574f36a8db981ae2d8854330fd7f9fc4ba71ba88b9ff297ff033cc3a3dd93a7e60391b1e6b1d20ad08c2a031eb04353f", 0x40}], 0x1, 0x400)
writev(r6, &(0x7f0000000540)=[{&(0x7f0000000240)='<', 0x1}, {0x0}], 0x2)
ioctl$BIOCSETF(r6, 0x80104267, &(0x7f0000000680)={0x6, &(0x7f0000000180)=[{0xdd01, 0x0, 0xfe, 0x5}, {0x101, 0x3, 0x1f, 0x62c}, {0xab46, 0x6c, 0x0, 0xfffffffc}, {0x81, 0x20, 0x7f, 0x6}, {0x8000, 0x9, 0xcd, 0x9}, {0x3800, 0x7, 0x5, 0x80000000}]})
execve(0x0, 0x0, 0x0)
sendmmsg(r1, &(0x7f0000000ec0)={&(0x7f0000000e80)={&(0x7f00000006c0)=@in6={0x18, 0x0, 0x800, 0x1}, 0xc, &(0x7f0000000d80)=[{&(0x7f0000000ac0)="ec86094a496e148e614a463322034dfce5d92f57d23fb7754d77b426296c993f5199e8db587df8a2c8ce1e65d3aed9f2a2cd8f7fc6a9829ef0dddd72f0865b02c6310aadcb9f1712f0afa3d4b43b67a97fdd444d540eec8ad398d51c1aedbd66f2309bc771eb3be862015dcea00cd253631dfbf252a1a98ac023275a5f18963f04f8d2c4f25aad364555ca7428337724", 0x90}, {&(0x7f0000000a40)}, {&(0x7f0000000b80)="d11c08f893aff685fb43abcd23d905c78f2e342057", 0x15}, {&(0x7f0000000bc0)="befba56b8b0bdc27cf410174b92f0a1e128e1076dc73bd30c9c8e4d20672ae6af3362653c4b711d8ee26382421b1f44f8d5ed034b454884a83a8157e39202bfa4539197c361bf0a4fa04a808e283ac06abbb5d0d9193e5ea24bbcb4961a384ba21da9649ed471e5de30dd74f273b03f8e36189e36331ff5e8e3545f84b84b089d46cf9c5ca84c490cb782e445d06e5b8f790345c7ec5866b8ba54c53fad7625a1655b30cbb250c00f16512aff4", 0xad}], 0x4, &(0x7f0000001040)=ANY=[@ANYBLOB="5800000000000000010000007f00000089e46fd6d235d5d93863a4fd0668ef9a7cfea583cfbc035d266c3447aebadde27b43803f2d1a405e8ae6c471a9614621f7b078eb03c0119a61663871932c824f87060000000000004000000000000000ffff000005000000608586f108b45bd908ea58ea49de66b48209cd296ca47dbc150da0f6a99868d8d1640a466bc85c0f74a67f5ecae45b75b000000000000000ffff000000020000aee3ac14a7d017c9cbf2d2e2cb7161e652665881159e1adc10b4cb43028151b940548dc0a0c16e35cc189d6622929ead54f0d358d932bf6ab89634614fd52ccb3774a642f7b4c298840f42567981f48ba883316c085a44b987ab12bf5104ea03dbbc570594218f53af58e2164377bab8ede8406fd6a1ec55e3f7b00edc7012866ec113bb21f5a930beb8e2d2545cc25ed1eca533ddc94caabbbf000000000000c800000000000000ffff0000060000006488bc51f5c5cc65b352ad40efdfaebb475e1d001a24a3219885f867b2d377386e6c48e8874fd66667ab5b4e76e53c30075d0cc9f050c6049552541198c96e8ac38507a95f10dff1908799abe6c010f371463149c919e00d0882d4abb60162a6a73edf1ce888b8d7efce21200539ee883c7612183d8422dc00deff715c2fda15b2de66feaf172779aef5b7770c040c9f998fe7a759eeca92b6b0f16ee108445ba25ddad4e9f1b65f5c950e45476e9096e700000000000000500000000000000001000000090000005299391616572d161003e84f977a72df814cc9047562772f66a2d794e60f27d9439c50193fce65d7324d2f7b6098b0dc0b4c3945d84bed6ed7751bbfc70000007800000000000000ffff0000020000006f98feb596508e1df0e3ed2d8e44b255eece00ea05f722866665298c7699314fca6089ff947af4cd5ad19f1578743fd65be26486f5592424afb874e21983dfc13bef4533d10631b092b39c7f8de03424cb29a11088cbf45198340c4cf982869ec980d0d0c4a89f7e"], 0x2d8}, 0x3a}, 0x10, 0x0)
pwritev(r5, &(0x7f00000001c0)=[{&(0x7f00000005c0)="18d26cb474b5c9d53e0ffdba8c54fecc9031509b1623088cc3e85353a5586603eebda7eccfc5ced62c70a12fbffc2425f3f9e50317605792ea906ef56376aa499b9a909aff511ad2d63fc010ee2292f393b11d78e8bc095bbd866e81599df546afa16ce278edae371c4f16d4df85f4ba622daf27aa8a728453bc4e93539080b8d73936bf6499780255943ab4ebd03bdae91f09e60447e17e0e21bf2dbd2c39", 0x9f}], 0x1, 0xb3)
sendto$unix(0xffffffffffffffff, &(0x7f00000002c0)="24dee952f632c9420a7cd9fca5de24bd829f736b202b2d441c77b4f7af183491e9354e6cf57a87b7f80438757d97844b796202813edb49144fe538a092b496ad8ba2ec3e2b614899035deaff09d7140f33ac4ea319626ebe123943c5cfa79a63799b8bd9d159da862bd8770c307f085fe6b5eccbb3b06b06ddc154567641601c414c56f022b77bbce0c1b6b5a420bfb75242d472045e56b3b4e2e299a125a1592295f6815e37401cea0313c779733c190a283312d45ce8290a596bc38a3b050ad1416e60e259b88f3ffcd57f42b7a5ad6ce648e90fa932786fe35c247aa1515b076dfc460dde2f58", 0xe8, 0x404, &(0x7f00000003c0)=@abs={0x1, 0x0, 0x0}, 0x8)
msgget$private(0x0, 0x480)
msgrcv(r4, 0x0, 0x0, 0x3, 0x0)
execve(&(0x7f0000000c80)='./file0\x00', &(0x7f0000000780)=[&(0x7f0000000cc0)='/dev/speaker\x00', &(0x7f0000000d00)='\x10', &(0x7f0000000d40)='%\x92%:{\xbe}&.#,\'\x00', &(0x7f0000000980)='~0[\x1b\by`@\xf0/\x8f\xa2&\xcc\x92', &(0x7f0000000dc0)='\x00\x00\x00\x00', &(0x7f0000000e00)='\x01\x00\x00\x00\x00\x00\x00\x00aker\x00', &(0x7f0000000e40)='/Xev/bp\xdcL'], &(0x7f00000009c0)=[&(0x7f0000000a80)='\xab\xec:\xd2\xdf\x92\xb78%(\n4\xf4O\v|\x00'/30, &(0x7f0000000f00)='*/}\x00', &(0x7f0000000740)='\x18\x15\x0e\nr\x15\x15N\xf3\x97[,B\x93', &(0x7f0000000a00)='\xeb\xec\xbc\xd1\'Phq\xc8\xc8\xa8\xaa\xb7\xf0\xa5\x1d-\xbe\xa4X\xb2\xc3\xc7\xe5\xc9\x1fd7\x1b]n\x91\x9dvtl\xa2\xcd\xed'])
msgsnd(r4, &(0x7f0000001340)=ANY=[@ANYBLOB="0300000000000000b370fb802a993a89140cfbb2a769f96527923c9b5dff2b4f03b94ef09aa699e7a69ed7aa4f73ffcbb7d1e59e3a93ba357fc00b9dc8d264817210a91befe0d63fe4549f77a8be0f23ca6afb74c0d25948a54f5a221da2f60b4bba5672c95125fdda33c2780a7957930660edb6686fb2d929cc202b128081656db0320eca690045b6c51241f9be647697960874a6fb1f718e060081e2ad7407611c1d94b2ffffffffffffff7f0f8c590fe7a0129239ffa3737c792ba98a97e8ae521ace9a9d0dcdce2d13180aea0bb2e533df90f87735af2a09b944fbf6e54cea4410dbe01b9fc087c888f5395418b0308912d849841ea99f523caaeebb4c4efc40a5f9b5c85af84bf2bd55765efa0f7abd5f38e7075a25e8628b7f6a6f5b15c1d2e93d39bf683bf2397704a8cde4d58cf5bfd781c4225b57226686c5816230b422457433e28bc3e69d3b1324f31f6b472987cde8071a8565eb4b727fa4fa0434e2f1641b85992b21fa161d31b561763b9d4075679ad325fc0a6c3159ac448edeb1acd6198a54a5409e84"], 0xed, 0x800)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x206381)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(r0, &(0x7f0000001580)=[{0x0}], 0x1)


sysctl$net_inet6_ip6(&(0x7f0000000000)={0x4, 0x18, 0x29, 0x32}, 0x4, 0x0, 0x0, &(0x7f0000001380), 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000000)=[{0x7}, {0x4d}, {0x6, 0x21}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
msgsnd(0x0, &(0x7f0000000140)=ANY=[@ANYBLOB="0300000000000000a60d524ae979b5a3e111c8cac1b119e4db1e444c9d4eca7af32596137392f4cdc50d82caa6fa7ffd0da455fa2e9f5109d4ccbe9ddd5e3674e689a6714f0ac2ee9e36ae12821cff35f5866888d441f7c29189271982efb7cd9c94766d1c4be0efcbf44d5d0010dc9df78616b167b260dd96322bfbad5f46f92beb4126cf5ffee44ca5b5bdfcf14c9b3003f53d57d96bcceb3c014f4d7b36a32f1fdb2d7783fa77ede48c3db7299ec5e58a1348d1da9304dc8bf8200a241f24ffa673bd7cb93b55b31a3045a1501250df6302a6bbfdcb68febcf98e7aabab17c9e7408bccc3081d1feec21422"], 0x401, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1002}, {0x0, 0x0, 0x9}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000d58000/0x4000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000c00000/0x400000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000f18000/0x3000)=nil, 0x0, 0x40}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000f5c000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil, 0xffffffffffffffff}, {&(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffd000/0x3000)=nil, 0x1}], './file0\x00'})
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r1, 0xc2585601, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, 0x0})
bind$unix(0xffffffffffffffff, 0x0, 0xa)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
connect$inet(0xffffffffffffffff, 0x0, 0x0)
getppid()
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
setreuid(0xee00, 0x0)
r2 = getuid()
chown(0x0, r2, 0x0)
chmod(&(0x7f0000000200)='./file0\x00', 0x1a4)
getuid()
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000240)=[{}, {0x4c}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000240)=ANY=[])
mprotect(&(0x7f0000ffe000/0x1000)=nil, 0x1000, 0x2)
socket(0xc, 0x4000, 0x3)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000180)={0x2, &(0x7f00000000c0)=[{}, {0x5}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x2c}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0xfffffffffffffef1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x2, &(0x7f00000000c0)=[{0x24}, {0x16}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x2a, &(0x7f00000001c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
open$dir(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
renameat(0xffffffffffffff9c, 0x0, 0xffffffffffffffff, &(0x7f0000000100)='./file0\x00')
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000040)=[{0x25}, {0x28}, {0x40e}]})
syz_emit_ethernet(0xe, &(0x7f0000000100)=ANY=[])


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040), 0x0)


r0 = kqueue()
r1 = syz_open_pts()
kevent(r0, &(0x7f0000000640)=[{{r1}, 0xfffffffffffffffe, 0x3f}], 0x8008, 0x0, 0x0, 0x0)
kevent(r0, 0x0, 0x0, &(0x7f0000000280), 0x6c, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000080)=[{0x50}, {0x40}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


r0 = socket(0x2, 0x4001, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
open(&(0x7f0000000000)='./file0\x00', 0x4, 0x0)
shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmctl$IPC_SET(0x0, 0x1, 0x0)
shmctl$IPC_SET(0x0, 0x1, 0x0)
syz_emit_ethernet(0x1b, 0x0)
syz_extract_tcp_res$synack(&(0x7f00000000c0), 0x1, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000100)=[{0x40}, {0x3c, 0x4}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f00000001c0)=ANY=[])
kevent(0xffffffffffffffff, &(0x7f0000000000)=[{{}, 0xfffffffffffffff9, 0x19}], 0x0, 0x0, 0x0, 0x0)
r3 = socket(0x10, 0x4, 0x4)
r4 = kqueue()
kevent(0xffffffffffffffff, &(0x7f0000000180)=[{{}, 0xfffffffffffffff9, 0x5, 0x10}], 0x0, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f00000003c0)=[{{r4}, 0xffffffffffffffff}, {{r3}, 0xfffffffffffffffc, 0x80, 0x4, 0x1, 0xfffffffffffffff7}, {{r2}, 0xfffffffffffffffa, 0x8, 0x80000002, 0x9}, {{r3}, 0xfffffffffffffffa, 0x88, 0x1, 0x8000000000000001, 0x6}, {{r4}, 0xfffffffffffffffa, 0x2, 0x4, 0x7f, 0x20}], 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x6d4)
ktrace(&(0x7f0000000280)='./bus\x00', 0x0, 0x40000200, 0xffffffffffffffff)


r0 = semget$private(0x0, 0x7, 0x3c0)
semop(r0, &(0x7f0000000100)=[{}, {0x3, 0x3ff, 0x1800}, {0x2}, {0x2, 0x201}], 0x4)
semctl$GETPID(r0, 0x3, 0x4, &(0x7f0000000240)=""/8)
semop(r0, &(0x7f0000000200), 0x0)
semget$private(0x0, 0x0, 0x104)
semctl$IPC_SET(r0, 0x0, 0x1, &(0x7f00000005c0)={{0x6a, 0x0, 0xffffffffffffffff, 0x0, 0xffffffffffffffff, 0x40}, 0x0, 0x5, 0xffffffffffffffba})
semop(r0, &(0x7f0000000280)=[{0x4}, {0x2, 0x8400, 0x1000}, {0x1, 0x4, 0x400}, {0x3, 0x8, 0x1000}, {0x3, 0x4, 0x800}], 0x5)
r1 = getuid()
seteuid(0x0)
semctl$IPC_SET(0xffffffffffffffff, 0x0, 0x1, 0x0)
semop(r0, &(0x7f0000000040), 0x0)
semctl$IPC_RMID(r0, 0x0, 0x0)
getgroups(0x3, &(0x7f0000000300)=[0xffffffffffffffff, 0x0, 0x0])
sysctl$net_inet_udp(&(0x7f0000000040)={0x4, 0x12}, 0x4, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$vfs_nfs(&(0x7f0000000040)={0x7}, 0x3, 0x0, 0x0, 0x0, 0xffffffffffffffa0)
semctl$IPC_SET(r0, 0x0, 0x1, &(0x7f00000004c0)={{0x6, r1, 0x0, r1, 0x0, 0x8, 0x1}})
r2 = socket(0x0, 0x0, 0x0)
getsockopt$SO_PEERCRED(r2, 0xffff, 0x1022, &(0x7f0000000180), 0xc)
setsockopt(r2, 0x29, 0xe, &(0x7f0000000000)="02000000", 0x4)
accept(r2, &(0x7f00000000c0)=@in6, &(0x7f00000003c0)=0xc)
semop(r0, &(0x7f0000000080)=[{0x1, 0x100, 0x3800}, {0x0, 0xf001}, {0x1, 0x4}, {0x1, 0x3f, 0x800}], 0x4)
r3 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r3, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
mquery(&(0x7f00003df000/0x3000)=nil, 0x3000, 0x0, 0x0, 0xffffffffffffffff, 0x0)
sysctl$vfs_nfs(&(0x7f0000000440)={0xa, 0x2, 0x1}, 0x3, &(0x7f0000000640)="ca402b634879c5e95a5c03e14b245f27d04cd79b9644b8eabfb113940277d8f88409950fb2f308a538b3a4463e6f87d43b082aa00792c50408c865b5521f3aac3ef0644103c30000ea3b4ed95e36f26b529aa72a03a163170a3005979e9c581d0cf6f171348806c3fdf25025e6dbc266ba832c5a96cde04697e4da054977892e8fd21c03a3874ed1cd6207a2558321dc22887fba389409cfb69d3b98074adfd09ab445211e40ecdef841d047b216e02b7f2be2762ecba2630a99d6f31451ac7c8df8a20018d60e03b988871fef897102220bd91782d0d1f595f136ce07e080686c05aa1d0828f3d85f434d9addc53ed3552213ce32eaba40922a432b5b46055cab8617a3e836cbc716983b835c4183f6e5227db861a9cc3c6c229d", 0x0, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x1e, 0x2, 0x6}, 0x4, &(0x7f0000000300), 0x0, 0x0, 0x0)
r4 = geteuid()
lchown(&(0x7f0000000280)='./file0\x00', r4, 0x0)


openat(0xffffffffffffff9c, &(0x7f00000003c0)='./file0\x00', 0x200, 0x0)
unveil(&(0x7f0000000040)='./file0\x00', &(0x7f00000002c0)='c\x00')
execve(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)


writev(0xffffffffffffffff, 0x0, 0x0)
setrlimit(0x0, 0x0)
syz_open_pts()
shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffb000/0x3000)=nil)
semget$private(0x0, 0x0, 0x0)
semop(0x0, 0x0, 0x0)
semctl$SETALL(0x0, 0x0, 0x9, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
semctl$GETNCNT(0x0, 0x0, 0x3, 0x0)
mprotect(&(0x7f00001bc000/0x1000)=nil, 0x1000, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCVERSION(0xffffffffffffffff, 0x40044271, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000000)=[{0x3}, {0x28}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000180)=ANY=[])


sysctl$net_inet_tcp(&(0x7f0000000080)={0x4, 0x2, 0x6, 0x2}, 0x4, &(0x7f0000000280), 0x0, &(0x7f00000002c0), 0x0)


open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
open$dir(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
unlink(&(0x7f0000000000)='./file0\x00')
openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
r0 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
select(0x40, &(0x7f0000000180)={0x9a}, 0x0, 0x0, 0x0)
listen(r0, 0x0)
r1 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
accept$unix(r0, 0x0, 0x0)


r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7949)
setreuid(0xee00, 0x0)
r1 = getuid()
setreuid(0xee00, r1)
msgrcv(0x0, &(0x7f0000001500), 0x1008, 0x0, 0x1400)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000000)={0x0, 0x0, <r2=>0x0}, 0xc)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x2, 0x0, r2, 0x0, 0x0, 0x156, 0xfbfb}, 0x5de3, 0x5, 0xffffffffffffffff, 0x0, 0xb8, 0x83, 0x3, 0x400})
msgrcv(0x0, &(0x7f0000001200), 0xbc, 0x2, 0x1000)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000001580)={{0x401, r1, r2, r1, 0xffffffffffffffff, 0x8, 0x8}, 0x2, 0x3, 0x2})
r3 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r3)
r4 = semget$private(0x0, 0x4000000009, 0x82)
semop(r4, &(0x7f0000000180)=[{0x2, 0x7}, {0x2, 0x8, 0x800}], 0x2)
semctl$SETALL(r4, 0x0, 0x9, &(0x7f0000000040)=[0x7ff, 0x1000])
r5 = getegid()
r6 = geteuid()
semctl$SETALL(r4, 0x0, 0x9, &(0x7f00000001c0)=[0x7, 0x401, 0x95, 0x1, 0x5])
msgrcv(0x0, &(0x7f0000000440)={0x0, ""/13}, 0x15, 0x2, 0x1800)
semop(r4, &(0x7f00000002c0)=[{0x3, 0xffff, 0x1800}, {0x0, 0x0, 0x1000}], 0x2)
r7 = getegid()
semctl$IPC_SET(r4, 0x0, 0x1, &(0x7f00000000c0)={{0xeaf, 0xffffffffffffffff, r5, r6, r7, 0xb, 0x7}, 0x6, 0x6000000, 0x5})
getgroups(0x8, &(0x7f0000000200)=[0xffffffffffffffff, 0xffffffffffffffff, <r8=>0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff])
r9 = getpid()
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000240)={0x0, 0x0, <r10=>0x0}, 0xc)
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f0000000280)={<r11=>0x0}, 0xc)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000002c0)={<r12=>0x0}, &(0x7f0000000300)=0xc)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000340)={0x0, <r13=>0x0}, &(0x7f0000000380)=0xc)
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f00000003c0)={0x0, 0x0, <r14=>0x0}, 0xc)
sendmsg$unix(r0, &(0x7f0000000400)={&(0x7f0000000000)=@abs={0x0, 0x0, 0x2}, 0x8, &(0x7f0000000180)=[{&(0x7f0000000040)="268a19500222addfdd1965c6e1e677d79e66f38283451cfa0ed102c16ce4f7d3f673d3411137db3f31b073de20bd47e7c8b709d9e8b61b268bb09ce7d8882ea47c660a152e5e194aefc1bafd8f1850a447f47285810a3e79a6ce46100a488a973acc4828c5a732af64dcd5a39a625a2e0fe10f1c0bff3b07aa3b12400fd7be81f3df04fa7945dab15e4d494e71a067b2b5a4fca8f4a7b32fbfd72b67b2a745e6aac6696b8d0fb1a4fa03a1de950a1ab5e603b80691d5675c9bfd1dbec4faa50b66da63292ea7940cd8f541ac1e7b605f214bca6abffa926b3119bdbafe0058c2c8e5a0cbd678", 0xe6}, {&(0x7f00000004c0)="e97d6ebb271004a3ff607a88679674c325347ef87ce0e669d4f3e4379b3c2c4c5befebc28ae5f9255221f06913029a94f499c0683c63d7c204c0181378e71bd94cee34aa013a5676db8d67f3b31591192ef5069008f09029090bc1b540421fb6399d4da97a0ec0ee3e140138ca8e0ea4272ce66b66c1ef40ba6a5f8dbee67e1808242a0ae271a0993cc11bbfbaca77451327c1a6aeedd2c0a66e560de5f74519405b90976e429dccc7101540823271a56f5626ad5279d9b6348dd618428fd2992818c8a53cabb4d2bb907c45796ce5ee92c9889b79164dbb7681f066169e785b55ff0503adf2a7562c2ef7a9274b98944d51aa9fd4856ce4846ee04b0603781c1160ca5129669edf184b7928b362533604b39346dd87c71651282fcf12331f68a8f127f698d85b751217101a70e3057a1bddd2f2deb612f405744f995bfd56e9d9c063e9d079f41b337f9695b7188428db6462b5ce6fddb7ea3b9234c32fadc6a54b6873678ba7e2f763339f154117fde4416c27fa60344a078f1724e5a96b2809ee0dcce23d6056343deea5a9b8f5501ac9910e01b567136d7dd2529bfafb28b8f1477fee95b589ca80560d290c83f5b5273318c613bf03d6dd3f735acd22325f6ce63efdf7c1ce28b90fe056bc35a1df39231030d4e5811be356247729d0c1c33664ebf5a8262eca928cefa21d49b36e960fddc12ee6875a27a83d84d9a9e6dd9bc34a07863a10e02c6288ff36c25048781371960f10654983d988da575d57d8e3489e61926ecace57ba04366ece1d8567b5219ca33e36d93c45b8ae7dbbfbbcc7fc4d533ed75ebf7034492cc62e6fa793be64429242dabbff550f9356986da5491f8ac6d312dd1765c3f9cb38f3d3fa2343e5544df47bd6db9bcedc428e73eccf03f70df485876cf8f92a26803e60c2c9574a30b90064164c51678dc592413e4f749249572c42a1d57186682d13291dbf8250707fbebf958b36974f48c2bd9303d1ae278601fe18d815090268714a5f46d74cffed387c398846cdc7d5d43ec509430581d06d224236a310eeef6fe4e885dd12d8c868cc9d21a072e7e837890efe2e7e1f5ffaad986f672a6ff57e183d034916c4e03d6e9eb744a517d1cfeb68101d501d4ae1ccf5c5c853f4bf46ef20607fc2b4ae4de44bbfbed0a3aec9241c8b6a631444f96b65d0e66d034711084c6767d0d2bf235ccc9fbb3b4ca4e33fd071e4e7cae0725a2535280871e68d9d203990fc128dea64064634d62ceba09bc4221adcbeb0c30792e6f60cb2e2bca950bec2e2ad20e88afcbb9154287d69172025b327c324d534e4ade2087f11ee6da6a1054301260f177e330a34b515f4b8758632e9db1761b623c82b4bd96746a7feff2acc0e5cd1098e30fcfbb26d917b386d13b98a60436cb9272df086bd26ef08571845bbe9e4db9f15893e0be91728d53005cba78d52324cf42ec97e6adeecb14217f491df63d08bd7e2c2f79228de852342470d85af6528ad989b614d72af248b214e2403cbfdaf4bea407cc5810a25844b756adadd1877d8af60eeec6238ba2c692c91facb54920d0d6a46ad2eefa410b16f560dcf04882e28ba710ff42cb8e3e37bf6db45bbdefebe0260cf3d658169d7f18f8058b9bcc04b6a44fb0826037a43b680fce69c44d89ea5896ddd79714d0c1520847ea7fb3004be1a57ed11abdf89f6ba06fe903439bc755f187e94b7c52ccb171404277c422cd56da9e9efdbb96b8737d0933791be97078d67da327701f737c094e43e02875b237bf1ce534490b843728ac55ab80a8ebab618fe643f7cea619de72c86b0109bf16c1e1235e75880764a664ce7be828c7e11412771f083f03f7a93dd7ca9a0e0e42a69dc88245c6f41354502e8ee6e7b6071358c38b86891a31f91250d33535cd830ecaa6a900397233dd3a77a39174a964825767137e8aa888c8ba864c3f9377d60c5c66bf3ee26764f937b6ebbcdd3408c41fa5d3cd53300c5d8a83b81a752b2c1a7be5ec5012b8ba0dd65a4787a90ee190e1f25b26ddd58fb7a684b6d2a45a2ec9a762ae0d81ddfd543e14a47b66c5163fe97bd8390c654d62c6024c65c422e5cecb69ecd47c23e5801790b6db01859c00e45ad11f5952937fad8251e88ca49ea4a112bf13ae4a457a91fe0f994db83a0e508ef79f8b77b6848bfa9079a130ecba486a50644c0eb88acfeabb9ba45510760d687bb1a415c8eac1c70afe9ce65e657e826711a4fff9c4c9d6caca59c9352bbe415f53715faa278b1bb0f1b5f011d97259490d0ae4c8d046cc523bd9167c14714809b96ce3eb18f06f36f68e0c801271227b34edc3c68ef5c333ba6bb2f0f89a34b8f353633fcfff9a31c5469358efff01fe95e24570491d658866be7cf7843b2e4e3117796667df6dc7c28db7fdb7c46d9511b9a6f52c7cefa597a958c4f1a8a1b3a924774eca54769796f70dd60572a4fa0660bbd301ce73e23845ea3fd9a523808a43952beb0ba35cbb91b5d54c934482855ac15261d971cfebd2d53b7c7c38278fe500429d6501a10fe52f6da8ef7b4ce03ee718267d9f3e3c31072274a383d6a3210d7008dd37aeee68fb3faf04fb24027a1792d21e4ae2e46f15bcdc18a602868521093808aa0f307c91884210f29a6ae7b888567d36ac69ed6151a1cfb64117a324c33b98a1cd6beaefe85d47dfbd81b0c19a5fe76c576fbe7f20a299802aaa48e57d0466b06d41b8be698ec11c8a7ff776b79fee7e71297b5da6a1a37a8877a0243e9299e09abe34317bb23ad43e77a34b46a0df72ff3c6bf24a451ed7dc2fca426fafb2b91f491f8f65115867d0960089708681303374caffc1e5bb56725d467d196d85869e57537204bbcf918393330d92f235433b05ca8356b73eee6b606ada78f8f690446435f19ee2df1a35b96dd25480a2097d07c50b5f4714b7a459457c59ee28c9f5026f26c5fdee906852d7069d87a98412b073f50c13f9e61a8d651d87405470236f990dba6deec7c9a0c0caab9b2608434cf8a6afe8d1088215d2ae4d04410da05daada2baa0c101a9d166baf9326543d71c0fb65f5c5c391519789ac5c26e26af4460cd49f2500a1cfaa42aa46eb217ac71aedea27c0207ffbdf919e32abaf7037299d27190afc87936c68f4756efc1c63d4a055fcfa348d9b6b9e64471016698d48ec04bb679a1cc9f380c15572f6638b0c0087ff56115b23f940496020c2f58a0813dfb0e7a9ec5492c6c626c30dfd4cd44b063fda1dc29b0ca96562500d05b8bdb84b1b14d3f015075006f5d89c37fdcd0af3478492c36a20acaca90749906415ab00d1fc1ece1515288e28621af23afc9ef06b116f1aabf7f2f1a93b063fb47649419f587c6b655ec78f60b2145c0634d47a36960657aea1135800acd718287c565f8f541de8b10cfac4baa38f39e154cd5ecf2de2c34b9a86647ccac532a66cf09a6ae0f9d61b793a5bbaa709d6da0a02e8ed45378736f0a37aa2f0ea51f758933ffb1a5a8b57b467e80b7948196d987b4ee6df4c042ab82fa49d273c580753bd0d9ddcb7b64e5cf5fe4bb36786280c699eae4b923465bf70952815d0482c39758f491bd09152aaa0d037ee91fc70d7bec5733b70219c78d15950175dcc217e500d3114088575e6535a44e55f4971ab080d59f2f103ca57770fb9aef7e5477d222c5bbf5528d3e3a1333dd94abe6b63e790cc286e6c14922e8613aef07255acf15abffc95025da99af536fc760bfa47ccf0807dc3dcd63fd7c0760106889207d3c75950dbbfb58105940a1a19eeed23cbad7436f8773e3d56e8ed84988199082abb3d5f96459a52381e1df0ed85a6ab79049450fb773b28f07ab03aca796fd7c460c7b50ed848019c4ea0bb34275a9df87c0103ac706df5f17c290919a5b437b4154b06f9d91a8657b2cae164ae1902b9a2d3516e195dd80952152e1e6bdc34d108c3aefd61eea859b770599097530a139d5f798bdc60e438e38bd75ed9160dfec7c06fc3138e057d56b84c33c190d1c45cf765a1a3f1144aaa6a6b5eec826dbfb364f41fcaf74b28dc72b00272e147f511826d1a8922143d1153f0dec4c68f33a8887614c30edb585549219c3d46a0a33134cdcf201ef71f0d5534023ec9b282e815647de8e42636cda91238f4459cfb1b4bec1435e0622daeab43ba8df48834ad9983051d8c66cb8f4af876c38e37f885cc9c6a323d9d43d1591420a1fbefed085d00cc60d5f2b8512cc486d0be44420b06de1cbd895b699ceb77c36c93a0fd87c02eec5d7d58babc1fb842fafa819673433dca3573a0fad48d90240b0b099d1493cd2779828823c3f92ef4e865ef1dce5dfb26245292230ca85abb87ffe64a1eb7b9f4e390d8dc445cd3e0bc61914ce5971c73edcbbdaa0a7de4a44b155ddf6229af1be000e712965dd1f176e8ebfc6e0f0738757a67d050e253082ebc56d74e3d52fe6d23d2f464ffe5ed4fac7554b6d40897b13bd024b87ca6edcdbba6add4553d534516625163e2b48d73e9c1bfeceb066838305b25f06c9107707177c946caa114e82991955b87e5f215e1dc2900d5f7ff19afbaecdf2e3b6adc708f82b88261aeb7ebd8928addcf102ae9c8e07d8620ed9290adc33e52235d18d8820bab5be29dd23e8eff63b70566a0906f5e61cec8962a9ad441a830a839dc03154cc3d2d9736487bbcf08c57b25caa6840e31759f4462a282f2d3fec3a864c03a4fe5835cd37e25eed0c3b7ec820625f8624b12542a52d99245055d7679a4f425a697fc80e59e64236074ebd282bd4ddef0b2c387c869b80a4927b47c3dcdbbc9f4b01cfc69172dc42f50aa72fa5b38dff426b7b93f6f516cc6804c5ecf035dab3d1526971c25b6b926ed04a0787e9f8ff3a549f6e14469511cbbcf41a10fd1998524d0fac15f836927a8a07f13e8c866994bb3d53a470c56a2e95c66bac8a52574a176eabafde5080035f0ca78b17d13b0b7865191bdbefad5f7ced00de9ed7ca0f5e20409c1b8c76b6c509b27a2b5c3ad478770187e346c3d9aa761835b38d50ce7e4c3d6128156538c90b77bb8140bab19603d1bb101db8d181cf61d11ba939c6b4231f01a655ae42fa8859456a9124556b3901a5cc98f8bcc4b8b4925b71370226a0eb1a7bb944e64bd907174268aa8f9d5c6c6693f5ef7fe150fdd9dc6eaf3947feaf14af1ebde3256b954a3acc99842ab3310bba940d0d7bb560aea4172eebbe0bcacc0482da123543d1b20949a90d421aa84d7e360b394c1a8eb9ddc7ee21d4455e6e23b7bf76a9db0c889fbce07942c09704bc763ba09fbb89dc04f9fb4c6aeb2426e1a00cba2df49a6574df9ec58aa1e9bf6ce19b07cecde8824581af815f4d996a820006ec8bc4c43e7ab9d699c0c4a4c4a2ceec7c7fd580b991a8f1a77f89c68320fd9c7b580a977753751d5d2efe3dd85dd7e2581c80b83ec3796b43d7b0ef4f789a4566ae73d2106daab01129c2fc480b828994652f59e6ce8a4bd9139417258ebc8e332d1a23be99505853eeb00394c8bfd3c8f0cf77c7499634e7bd3493b5e14fe57cd693ada7411d51c6923c45da3dde4cfccf5ff2e24edfcaf2baf7eb146aa8a1498b43d5c30d2a3ce01001b0f86528d32fea9cdd20f564b328d651738e90b43e5af675466396cdd21a5951ccfaeec74a3abd6cb8e7453f08e148095209e1fe6b4548ce603d6a043c66c8fde2193cae08108019e5cf4027b0f02ffb64452aff4f6c52d555d27a44bb0320cd62e00093ccc2e0a5d5c258130b24a86dda9cfa3448778471140c40fb3cade5d32d36", 0x1000}, {&(0x7f0000000140)="3241c4b621caaac034ccdaad1c29ddda4164c30bd010ff85e4a8f0cccb3f26f9c153ae5170e838ba0e32695f", 0x2c}], 0x3, &(0x7f0000002600)=ANY=[@ANYBLOB="1800000000000000ffff000001000000", @ANYRES16=r14, @ANYRES32=r0, @ANYBLOB="2000000000000000ffff000000000300", @ANYRES32=r3, @ANYRES32=r1, @ANYRES32=r5, @ANYBLOB="000000002000000000000000ffff100000000000e844197a80e97c30d9f0e868c89eb4f1eb3c9a59265cd0d68f646c76f56704a4c3dc5e7ab526d17e15e58e739b6a77a560e316b4375858c8e56e4b18c3dfde54ace78147fedede2dbf5aefafd99c06ffff3921eb3f58d8a6ddd45797636753bcc6da9621ce64803f775e5418fab4a6440d20199e21fc2a1287dafbb2ad83e87e43df68dd2d966cb6b1e9b29c6ab4255728babda0fd624f101129617d2eaf622f68875dd93c10e5cebe21f0e40d4cfc9fb4233101717b1f426eea806b992ad89001bc8385b2eb99f65f118aadd9dec8c215703ff23be675f269ba6f29f3dc166c790c7dfd83e3416b29dc1fe4a9ae2e411433e1f88d1255033adfc85a11bca099cd73e10a6ddfd53c40b64df317d01acb8e3996043e2700ff14f955fa3a7bbb77ff4fa836dabcfd7a8c8e4f508661ed22378c5da58acf37288f203a983c6103f6e4c6079165d2293448f01bae4cc9428f4dbfa8c2", @ANYRESOCT, @ANYRES32=r1, @ANYRES32=r8, @ANYBLOB="000000002000000000000000ffff001000000000", @ANYRES32=r9, @ANYRES32=r1, @ANYRES32=r10, @ANYBLOB="000000002000000000000000ffff000000000000", @ANYRES32=r11, @ANYRES32=r1, @ANYRES32, @ANYBLOB="000000002000000000000000ffff000000000000", @ANYRES32=r12, @ANYRES32=r13, @ANYRES32=r14, @ANYBLOB='\x00\x00\x00\x00'], 0xb8}, 0x4)
faccessat(0xffffffffffffff9c, &(0x7f00000001c0)='./file0\x00', 0x1, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x1, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x1, 0x0)
sysctl$kern(&(0x7f00000001c0)={0x1, 0x1b}, 0x2, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
getsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
socketpair(0x0, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x7e, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504600000000000000007000000331c13fecea10500fef9ed06c72fd3357ae320b37b673039d2d236073705ae04be38164991f7accf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f13", 0x4f, 0x0, 0x0, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000300), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$BIOCGDLTLIST(r2, 0xc010427b, &(0x7f0000000040)={0x0, 0x0})
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000100)={0x3})
ioctl$BIOCSETWF(r1, 0x80104277, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000240)={0x0, &(0x7f0000000100)})
setsockopt$inet_opts(r0, 0x0, 0xd, &(0x7f0000000240), 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000100)=[{0x48}, {0x1}, {0x6}]})
syz_emit_ethernet(0xe, &(0x7f00000000c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x1, &(0x7f0000000280)=[{0x34, 0x0, 0x0, 0x701196bc}]})
open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
r1 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x144, r1)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r2 = open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
sysctl$net_inet_carp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x12}, 0x4, 0x0, 0x0, &(0x7f00000010c0)="00040000", 0x4)
open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
getpid()
utimensat(0xffffffffffffffff, 0x0, &(0x7f0000000100)={{}, {0x3}}, 0x0)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x3, 0x10, r2, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f0000000540)={0x0}, 0x10, 0x801, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x14}, 0x4, 0x0, 0x0, &(0x7f00000010c0), 0x4)


open(&(0x7f0000000180)='./file0\x00', 0x200, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r0)
pledge(0x0, &(0x7f0000000380)='tty ( #\x1f)\x10\x1d\b\xef$|#\xcbh|\x97\xa3_\xbc\x04\x9d!\xd9\x9f\x9f\xb4\x96\x13\x12\xe0\r\xe7\xb9E\xdf\xae\x96\x01\x00\x91\x0e\x17\x95 \x00Mj\x84+\xf0B\xaaY\xe1Q<\x19\x9f\xf6Yf\x9au^\xa0\xc9j\xdd-I\x01R\x00wY\x1d\xd7\f>Y\x06\"\xad\xb6\x88_\xeb\at\x91\xd3\xbf\xea\xdd\xb9\xf7@mJ\x0f\x90\xb34\xc5\xa9e\xa9\xf6\x1b\x8e\x05\x86\x91I\x8fC}~K\xd97\xc8\xb9ul\xaeu\xad\x9b\xaf\x04\xc4\x03\"F\x8f\xd5\xde\r\x8d\xa1\x00\xcc\xd7\xb6\xe1\xeb\xc1>\xb9\x9eQg\xc00]\xe3\xcd\x95\x86\f\x1f\xbd\t\xc8 \v\xb0, \xee\xa4\xa6\xb9a4\xe0\xbf\xa0\x1es\x01\xd1\xd8\xd5\xb8=\x1f\xaf}\xe4\x90\xde\xa5\xa5\xa3\xa1j?\xb0\xdbd\xf0?=<l\x8c\x01\xe3\x05$\x1c\x04B\xa2\xa4P\x04\xcf\x87\xaa\x96i4\x14{/\xe6\x87\xdd\x8f\bz9$\x10_\xd8h\x93\x8f\xf5\x8au\xab\xf9)\xf5\xa6\xc7\xc8\xed\xb9\x1f:\x03K\xa2q\xe1\xd5\xdbUshx\xbe\\\x19\xda\xf8\xeb_W\xbb7\x00G\xbb\x1f\xe3\xd58\xf4:)\x10|r\x1e\x06p>\x8af\nn\xd4<\x00\xec\xe4^\x00\x00\x00\xca\x90L\x98\xc9gty\xce\xab\xd2\xa1\x85E\x00\x00\xd5\xab\x83\xda?w\x83\xbc\xcf\xd20(L&b\xed\x8c\x1d\x1a\x9fd\x99H\x9e\x82\x10\xea\x05\xe8A\xe3{\x8dE\x97\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-#\x92\xc0\x8a}W~\xd3\xa7?%\x9a\x1a\xdaC?\xc4#\xaa\x80)44\xb7,>\xd2l\xaaTU\xe2\xf9\"?\xf3\xb1\xee;\x04\xa7hN\r\xe4J\x02}kF\xaf\xf4\xbc\x98kD\xd4\xbdQ7O\xc6\x16#\xd5~j\x1f\xce\x11\x85}\xaa\n#\xad%I\xe1I\xa7\xade$\xbd?\x84\xd1\x8f\xea\xac\x1c\xac\xe8\xbe\xa9+\xed\x97\x16#\xd5}EJ\xb6B\x82~.\x92\xe4l\x02o{3Oag\xc2\xd0\x85\x80E\xc2\x8bB\xe3\x8c\x8d\xdea\x1f\xff\x83Y\xb3m\x03Y\x93\xf63\xb25\x8fF%\a\xcd\xc0\xacF\xfd>\xa2\x97\x1e\x85v@k\"\xc3\x02\xd1\x92\xe8\xf9\xef\r\x99\xba\xe2\xcb\xbfX\xe6\xbb\xd7\x1fiC\x1e\x89ZK\xe9X\x82\xa5gou\x04\x18\x02\x84\xd7\xf7\x01\xdc\xc4\xac\x8a\xeb`\x1d\x18Y$1\xbc\x05S\xc1\x94\x121\xd8;\xb7\x12\xa0\x1a\x8c\xe9\xa5U\xa5\xfc}[1\x12\xb6\x02\xb9\xe2h/Hj\x15u-\xd4\x927|\x05\x91\xfcr4(~\x97*rj\f\xbc\xaf\xb1\xc6\xc0\t\x8e\x1f,\xbd\xe6\xc4\x8b\xa2_8\xd4G)\xa2\xac\x0f\xc6\xfc\xc99\xaa\xa0?\x12\'z\x93\xb8\xda}\xc8\x17\xd8\xaaS\x02\x7fh\r\'\xd6-t\xc8\x10\x01\x00\x00\x00\x00\x00\x00\x00U\xf7t\xa6\"l\xffz\x8a\rm\xd7Vq\x806\n\xff\xe2\x06R\xf4\x9d\xeas\xd0vS\xb8]\b\xe7\xc3Fc>ZM\xa2\xc02Y*\xdd\x95r\xe5\xc2n\x00?\x00\xa9\f]\xe4\xc5\x0e\x81\x15YO.y\xdb\xe89\xf6\xe5\xe9^\xf6\xa2\xb3(\'_\xae\x12\x14\xb4\xf8R\xcc\xea:\xd4g\x95\x19\xb7{#\x04\xba\xdf\x1f\xaeW\xba\xecyec\x8b\xb5;&\xbc\x8e\xc3G:\xa4\x05U\xdd9\xaf\xad\xf69\xfa\xd2\xe4V\xa9\x03\x13*\xc8\xf7\x99\xa6}%br\x1e\xa7>I%>\xdc\x91\x1d\x1d\n\x1cgT\x01\xc4b#P\xd4\x91\xad\x1by\xde\x1bh\x90\xf7K\xf9\x12\xbb\xc5\x04\x03\xaf\xa0\x87b\xd7\xaf\xfc\xce\xb6\xe5V\x92\xdfG\xc4&\x11\xe2\xber\xb5c\xd9F\x9bU(\xc9l\xb8v\xbd]\xf1 H\x16\xf8\xa4\xce.\xa4\xd70^\xb0\xab\x1b\x9dj\xd5\xb6\x00\xf4\xb1\xbd\xc8\x8e\xa9\xcb\xaa`\xaex\x16\xea\xaf')


socketpair$unix(0x1, 0x2, 0x0, 0x0)
r0 = openat$null(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000100)={0x0, 0x0, 0x0, 0x100000000})
r1 = openat$null(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
fcntl$lock(r1, 0x9, &(0x7f0000000100)={0x0, 0x2, 0x6, 0x2fffffffe})
r2 = openat$null(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
fcntl$lock(r2, 0x0, &(0x7f0000000100)={0x0, 0x0, 0x7, 0x2fffffffe})
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r3=>0xffffffffffffffff})
sysctl$vm_swapencrypt(&(0x7f0000000040), 0x3, 0x0, 0x0, 0x0, 0xfffffffffffffd5d)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r4 = socket(0x18, 0x1, 0x0)
msgget(0x3, 0x60)
setsockopt(r4, 0x1000000029, 0x37, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
connect$unix(r3, &(0x7f0000000000)=@file={0xd1653077bafa0115, './file0\x00'}, 0xa)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000380)=[{0x20}, {0x14}, {0x9006}]})
syz_emit_ethernet(0x56, &(0x7f00000000c0)=ANY=[])


msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x30}, 0x0, 0x0, 0x0, 0x0, 0x8000000000000000})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
close(r1)
r2 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x1, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x401})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000040)={0x0, 0x5, 0xfffffffe, 0xd2d, "8717f9050700000000000090d692480d51aa8000"})
writev(r0, &(0x7f00000000c0)=[{&(0x7f0000000340)="3cf025a599de06000628d2d7454edb084f2ea69b25f5d706322c39b18c491074742eff07739836f673dfb698b83f1cfd63f946734180980807707ce3ccd982420f41e7fae79915df4f5d98b681b71bebde8bd2500d", 0x55}], 0x1)


r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000c80), 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x80, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x1, 0x5, 0x0)
syz_emit_ethernet(0x17a, &(0x7f00000001c0)=ANY=[])
r3 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chdir(&(0x7f0000000140)='./file0\x00')
setreuid(0xee00, 0x0)
r4 = getuid()
setreuid(0xee00, r4)
unveil(&(0x7f0000000280)='./file0\x00', &(0x7f0000000080)='x\x00')
r5 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r5, 0x0, 0x200000000000c, &(0x7f0000000080)="eaef125c000000", 0x7)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
ioctl$PCIOCREAD(0xffffffffffffff9c, 0xc0107002, &(0x7f0000000040))
sysctl$net_inet6_ip6(0x0, 0x0, &(0x7f0000000240)="0700006a7a00000086", 0x0, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000400)={0x4, 0x2, 0x2, 0x6}, 0x4, 0x0, 0x0, &(0x7f00000000c0)="34237eb2ccaf47234a83e7ee9ee897be39536e4c3fd58ae20f1ed1ff964f", 0x1e)
setsockopt$inet_opts(r2, 0x0, 0xd, &(0x7f0000000500)="000001000000000051fd819a9e98846382cfd655c334d31e38db0f905cd7c8dcb23b7dbb0c55fc48ec77eff427e014ba2ec747ebbd9014d440ec551bc9c9a274f91d20f6bfcc1fea1b1957a3b670da5f6ac2593194", 0x55)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x100, 0x0)
r6 = shmget$private(0x0, 0x1000, 0x400, &(0x7f0000fff000/0x1000)=nil)
socket$inet(0x2, 0x0, 0x0)
ioctl$VNDIOCGET(r3, 0xc4104603, &(0x7f0000000800)={'./file0\x00', 0x8, 0x7fff, 0x5})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
semctl$GETVAL(r6, 0x1, 0x5, &(0x7f00000002c0)=""/229)
ioctl$PCIOCGETROM(r0, 0xc0107005, &(0x7f0000000d00)={{}, 0x0, 0x0})


msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x100}})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x1, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000132000/0x3000)=nil, &(0x7f00000a0000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f000008c000/0x2000)=nil, &(0x7f00001f0000/0x1000)=nil}, {&(0x7f00001f0000/0x1000)=nil, &(0x7f0000001000/0x1000)=nil}, {&(0x7f0000132000/0x4000)=nil, &(0x7f00000b2000/0x1000)=nil}, {&(0x7f000008a000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {0x0, &(0x7f000002a000/0x3000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000e58000/0x4000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil}, {&(0x7f0000091000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000001000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000132000/0x1000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000008a000/0x1000)=nil}, {0x0, &(0x7f0000092000/0x3000)=nil}], './file0\x00'})
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x2, 0x1, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r2, 0xffff, 0x1023, &(0x7f0000000080), 0x4)
shutdown(r2, 0x1)
close(r2)


link(0x0, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f00000001c0)=[{}, {}, {0x840}]})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x8020699d, &(0x7f00000001c0))


syz_emit_ethernet(0xc1, &(0x7f00000000c0)=ANY=[@ANYBLOB="ffffffffffffffffffffffff86dd602eba78008b3a007558bec263551eeec9bce87b891a61b1fe80"])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f00000004c0)=[{0x2}, {0x40, 0x0, 0x0, 0x7}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000200)=ANY=[])


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
r1 = socket$inet(0x2, 0x2, 0x0)
close(r1)
r2 = socket$inet(0x2, 0x2, 0x0)
dup2(r0, r2)
setsockopt$inet_opts(r1, 0x0, 0xa, &(0x7f0000000240), 0x0)


r0 = open(&(0x7f0000000240)='./file0\x00', 0x200, 0x0)
lseek(r0, 0x7ffffffffffffffd, 0x0)
readv(r0, &(0x7f00000024c0)=[{&(0x7f0000000000)=""/212, 0xd4}], 0x1)


sysctl$vm_swapencrypt(&(0x7f0000000000)={0x2, 0x5, 0x2}, 0x3, &(0x7f0000000380)="f9332a8065153d62eee22f72a6e579c872efe2bf2ff1efedb88ac4d8312a86340df6b706a5cc9746cdea8e010da87e2cc0f66c07a6456619cd4286b0271ab4de1a7a06a00794c4fde755cc14306bfd61ec5d22aa143e0485c04f946f3a0573862fc050662f8e9aa342fd58d99de6c2d999046e13aaac016e72fc0e48777dbbe3985f05b24df7a09f3fe35ab6634a14f810cae4bb08885c7e80b5432e6647892cb7aa5c76cab8c6836d437515b8d78348cefedbd070d531a95e8687f00e3a9645a8a920189f4f116827c3eff83d8d8243256eb631838f93acb83f5c16574981479229e1882ce95f013f11b8ad489c4ded377d72e8442bc58ae3055d4865c4214897ade41c606cd74526c67dbbb4b2acf37b369cf27a72da422ab28e6bf84a30bacdc79fccc900372cfc6cf4719c8fb5fe2771a7e798a3d47fa51be4f814612a09036799cc8180348a339a57afc6f8b99a046cd4de20bd1a9a410f2b89c81d7dad2855908b3cf6a5f1c348011ce7e846c9a6043b2fc36eaa8568517eef4afcf3c9e2b9c25b25791bd2c298275c95e9b780bb3febf11fb66b6443ff47fb0879748c0e1d8a256865e19863c9191655bae481d96fce4815933ff9b03309896495d4dd62a8d6c97267a9db48e4bdc810e4d588a85620e1ce02c783219e9ed804f4cadebb37a921fb668afa4f1af31943a52ebd1abef496f23232f4423ed6e670295b9abad96fa1b1f05ca76bed339e16f676d232ce64be74a7068d81dd12c85a2972dc5e5f0ff28c355f60ef0f17bb23f06e72a31774eeaee68f346ab5c548b8cf47c5ebfa9e4f87bd8ced1fd1e4911263d6675e1d0cd2d71d32d293c2930f101c72b2cd2eec39f35e1f097d7181d26e42e5f09d0b14c07c2ce35d7c872033466e1d53bf5d0be0fb5ab4776ff6528b97c928b3bf4ec068a08b92e91448494f7749c8d2fbc1e0f386e3b352ba1014776705da60e930c89e636ceaa2e8f839541bc941134229d6fdd6af3681f7080ca770266e6ee1d1bb807673d51cd8562d3546ccc86ee8ad096ed86ea207677c54022218ecdaa8a0f2b2a957e50aaf92485960cdd1e5687634bf4fb8b69f37b8538ebdf372299895a9df76e29abb2ef2de42d8ac3c1f7b52e7040d860f2e5170d65056dd6d974a149193811fe217a04b266f04a538009c859fa0d80ee7cf4622630ee506bc7e425de3e27b4d4770f37d1a4a5634ab6d14433a6d3eae625898107e48c2bd10eee8692167abcea04abb0bdc7a1d9ffcb2b73cd7dec0b458e0ca71f8bdc3fc6c44c56744a384d0da599354ef67edc2d22c1b591a42e9d516c6846bf8104830e4cc3ecf9f00b0a07ef561e699dd95e4b303b57abb0595085eadeaea15213d6292e7187e59996b80359ed376f857a464ef5027a32ce0f9924698b400b2c21efe4d83aed49e282544d2e606ae785c7c96a5fbf832c55b188bf048d4c9a99e14444faa5536bf4a528eb266d24141b72491d1d5d16e5f1c4720bee29febbbef27ad35e4769c33b506d50931ccef48da4420bb29cff4358cf90c19313193656a14326252bf911b91d30a032a0d1d08d33740a07757b1fe94d2d7f5b25d271b3041cd06de3c7901af14443ce336aad9d972349a6e4df85cad9c0a2e905ad3c6006a8b11a0ca2b2b86c450e8c3968fbab18c0ac1583f64b7cc6010bdfa2b78e602cbc329304a272bf15f1ba8a988177b092cbae2b1fa2b09935fd0a9fb66e3b8081f7ad5500eca3a38317966db350b1d5c8f5ab65245235f55f41ff8a49526029021cc18af9ee80ccd6b8c7c5be0fe502a0ce7d048458ec7240cd8968cf61b26df6257f78f2bc0d129c7032dd9410d1ec468555792d42b3496fa8910a96fdfe9b2de92ffb2a68deed5901c3c9639cc2001bbef1c1d927f0b0c24a9dc71ae21f26bf331fa64c9c2a6dfe4de16c9c47aecc537e618cbc9f4506b4a8aaa3be261abc6c7a969380c019175766d9223a53b69f3dc7dec8230237d0e3524728d530cfb2fb6dfcce483de8bdecc7e22cfdb8042caa5a28cad2569cc0394ac202fe6f99e9fb7498804b622463219a880b17745c23c3677313e7484956a9fc27441ba07603dc73ca8cb1b1b92b562ff1b6507435dd5a71c2d8c8de6a8faec8a5a304c2ec8e058fc9f7cb98ac6e325cf798bf9858eef52f3f93309b92bf5a3825200c6d90e985af0b40e18e58f78c58bcef8728ff8bbc4155aac09e7c6663226b118c3562f5b26fa3d6f102ec59f162f27e31f67378d16cee32756d26de868d6b4f197ec8f3fff0872caf231a73050f78fe21f267e6e01982cf3978e1dbf6ad527ea936e19010987916e01883ea3f9fcf17d7c2418cf57987e3ba66b1dd8953450320e602a90a11162631e64d984e43f563f7d9ce73f5071089bd8b86b85eae6b0536240ea57fd08f54b3e41fba00e97d62d4ceecdd5df58c0e0b5b4b619090f5bded89376030a3d556db77534aaaedca5abec93e0d27261abf6c377c92fc0918f7639ce44c861b8bcf7b8b86c6c4bd54ef0c006df55eb1a54dee0705627f3e3c9a404df8759b37c24445b34ab8a114b2bdb1742e33a523da2ae3a2278ee496f8735dc2b971735996569774420f8e09801e623e1b2bfb5dd4c83937083babf0fd4bd0a21f8585a2e7e821062a0d975e43195f0e7169b27cf51b858b956b409e78485fd4605e0c5f92758b468b8e5c297ae69f8b23281576119659a351e392c0aa6605c65d6f762574b25c89541aef4d2cb89fe2f61e680bd2ff4e22970fd2dc0b004606f07da714ad5d25e7f984f6400b075ce4f06223d16d3be408fac462ab8d3b88ef8b5957f4990cde1472a2d869c32001a42865281f7bf8691358469ce2169f9b7e7c296b23e452ed54f5695ade2606bf67b98e96bed66e16184bc01186b0434ea5ea6979f741e0a0026a270cf749541eac61bbed1e4ba98c9f09e4b4c868ce5e27880aa77fb09becaccd7dbed64d58e793a003e346325f24f1f3f0c823ac84d15ecc20bbb5459060d5953a98a399bcd4398114b4c5461873c3b58435bc7e5f86ffe7f718bdbde699de7321b3fd7e0f715f602caf520a631407acfea0b74b071bf280d597c95d12a9460d5356854eec6c894f2edc5467fa1f8367eaa84a9c462758d6f61eef38821258a5ac1f5bda3cf2adede09739e3e6c617b3f02248ceb44e3e75010a9ce84d5467f32a6431c354fdda7c80c2dfd853739ff1fbf61d6ce416145d22864e35adeeb6ab968a82460e6959f261208bada1ee740d4407c5e36c2ace1d396f26039a5235d25ca99ef995123b73386ef5f54d4bfb73fac7f2b536dd460ca26fb2752720dfd9a4d27f2317879c24af20b23f2cd3694fb976c7dda0e5cbd0261f7f05adeabbc8c8ae1d12a8954f541ad26103339776481478d54de9fadcbf1c4c77198bcbce7c56a8f87a3fd3b5239d2af2e8a188c16d57b8bc60dbc22ac0e38635b8a1d756072af820c5bd35372e7c336c818649a181a95453d11f8e8c0ec4d1b43c98f049810f38fb63fb44a8b2996303fabe0db7b3e63a87943a11630bea4029bf6f2d51961029ad3f5e4f61669a871c3341e0b65b85eb0ea7c92b5b39e2a6479234ecd7bad14922d60cd71c32b53e694d83c085b68e7295828c0569d79985dde8c389e7f9039412dd40412b20310acc61e7935cfa350836ca82849d84cb3cf802d361be9e4c649b22c6daf5bb34c1dbbade3a79267696f90ece95f3c59fc315151c71c8c2aa979cce8d18af5a76d4f5ed2bb6367bda5f5e60515e7fa8ce022451b346019d551bc2295c866c889c3a9820a61ad5b3312f11b6d8575bbfdb0ceb8ec54e463f1c3e0605486f622eb429b894ed93cb46cf5ea4b5a70c0157ea21890cf26beeec1a4cee00a5590f90b39a17dca05ca5cdc6cbb74afaeb3cafdb5710ea948c80e977d3b8870589718fab4c4a8cc376ca5036c764a45b50c0370e53d43edc87ee09a20b29eb04526a8a16371e31a1b854c2532be568fd55be0241a466eb5fdc7621c5da5cc28539f34a6ec369b4aedb4de82b5c52c71b7ec62c2addf309b65f86775e76cb8bb85cf11e57ab155b866363ba9469d18f38db28283182f7799984e61fa0f8dcf778288864f61b70b703908f1cca608b08f94b35d8b9ace8804f518883156948f3728cc1b807c40771adbeca0c6557c0f906a2930ef85eafcf4185f48a85a052294e648bfae08d4c08522e8e0fb5e40bb6fb144f984e333f567f995c93f4ec615d4ae6501c2a5b34bca468a3f354ff9ac80b72082bed3aa393a86ed90c76bf45e72ea01ec9cace3fb27355e9d8a224348449305a5505e104ec54297de548679d11e9827f3c7a7ae55a787e09975df5dc497990613f5bda73a731fb3953fb5e9fd0bda6184775559f14e917905c5c5d7e86e3e845ed8a8882d8e200715e01d88ba1167ce550b3470134fa6cab0c626d1e94b71396e3c4af3d4a385e2e44f3b73fde66451ded569ac08b4a1f4b6482367b690cd1f021ead3f44440fb8992a0dd3dcb5a147b76e3860ed0239c5bcd8b4c23cb7810119ce50fd6ead36c5d0661007a87c3fc5dc7c0c4098e09baac6b117ebf10cf423a1bcdf5a2587a2ae128a742a288df9a6eb67d34105b1ca61536e3535cc2abba9f2e2e4ebce7f2a606091f1718e75e680a9456855b49be8e120a2b88761e4e7a6fe9d6a64d0500c9950606b8398cf3bb6f0e8ece75f2802f604d43fd2d342deada696df377d7b6575a23e44c068192793124c963a71403d7b9002fb2a99acbea45e3ae864033a169f1183014d484005577f139d515464fac50a815667ce6f1d6b3e3b48775ddcce8765d179c5822e7119dad2ad2d0eef29d208170d9203d2424476f81cd762067b041114edf0900a2f02c5ef54498a31f9ed3b4eef3a4594a1040a644d69fc52fba13aa4456d7ec28692e6937fa6b5d5e4716e170328fb362fc249f4ac83d9312efca4d63fe76273957a720373ebcb5e90937bb99325babd40563285355c45fbca5393a902c46df4f7d72a6f235b05a96bca27b50e0002f99e17702f306449ccfb308a7ba8db1b482ca75507712beaf239ed94aea126f24a14343ad41be14f58becb35529a54a682a7e0704c4a2b01c306a5abf237f041203aaa51e5f7d075f82dcd42fbf65a9c84aeab400b1de48b3998b42933c74a92db46aba7dd23eb1796fbd91a91fb288666971132e5e99e1fe5bd67fd452f3e5c1b34850f9779e8a12ea3be12bd000b9ddd34c6bccb520d26f37f81cad6ebd65ece8e8eda6e7782d7aa380ecd58d7a94cac62f70f3ed560b8a21dab6761762eb8f0fbf5ce3087534a3bb7c8c0aa8a000f5f880d98b2a1b4387b26e545c83ef677309397991f43b730da1729bd898d70da5c05f7c46ae6225e7ec0872b476c3f7beef610a57b6c91093b6e3c3037bdb67c42be7b937c6fc845e577c1e1a2669ae7106bce63356197b38ca14c7709d9cab4ebf0ff9b0e15209319ba113a6a88667f622c9ac3553718ab2c2367379c64c66627a1e4f0ba3bac6c5dda4e70fb82573e832aac48ab70ed3597d2e91594b75f19cd91379393c582131a8dffad5963ce6a65143ea8121d6619855b60a54106975884ae47d2a6d2eb28dea933c00de799b85c829301a42f56483c939104cb24331663250da178c0cce6d170439024c0a5196a17a13258b6323d872a837de126f85d2a09d5c77c5e9643730dbfdfce3d8ed351a4fe05b48a03bbb47f37fa33b8ce00a7335886ee68cde929c85277adc4d2047c600f5c12d3e2755920fb2c71b5eb020280dca424212266edac", &(0x7f0000000040)=0x1000, &(0x7f0000000080)="b8edac04076f400049fa74e21b972189c90d7c8bddd1d7212cf543201d060b2e9387f5422385d06a5b1c5e6d4dbb3c2ff55b763a5609e7b13cc217f64a1c459d66bf043f1113201f8479678e64c918d69ea06a2b80b3b9d65be06f846797b6bb", 0x60)
r0 = socket(0x11, 0x3, 0x0)
bind$unix(r0, &(0x7f0000001380)=@file={0x0, './file0\x00'}, 0xa)
mknodat(0xffffffffffffff9c, &(0x7f00000000c0)='./file0\x00', 0x2000, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x4, &(0x7f00000003c0)=[{0x2}, {}, {}, {0x1, 0x2, 0x1, 0x3f8000}]})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000007, 0x0, 0x0, 0x0, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
getsockopt(r1, 0x0, 0x9, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
r2 = openat$zero(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
fchownat(r2, &(0x7f0000000040)='./file0\x00', 0x0, 0x0, 0x6)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
r3 = socket(0x2, 0x1, 0x0)
execve(0x0, 0x0, 0x0)
setsockopt$sock_int(r3, 0xffff, 0x8, &(0x7f0000000200)=0x6, 0x4)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r4, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000100)=[{0x45}, {0x5}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000240)=ANY=[])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b88eb4e47f", 0x5}], 0x1)
sysctl$vm_swapencrypt(&(0x7f0000000000)={0x6, 0xb, 0x2}, 0x5, &(0x7f0000000500), 0x0, 0x0, 0x0)
r5 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r5, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
mprotect(&(0x7f00003e0000/0x2000)=nil, 0x2000, 0x0)
sendto$unix(r0, &(0x7f00000002c0)="b10005010000009f05000701070000000000000000000500fef96ecfc72fd3357ae30200004e30ffd2d236acf20bf404be01000000f7c8cf5f882b297be1aa050400ce94e2f0ad3ebbc257699a1f139b672f335c22db830c032bfa896443c32118210000720fd38bfb0000fd54c125191b1257aea8c500001602fbfe0c2300000100be0900000808e37193f8343712cc11fffffffffffffcff000000000000000000007f62b60beab90000000000000000", 0xb1, 0x0, 0x0, 0x0)
fchmod(r0, 0x80)


pipe(&(0x7f00000000c0)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
write(r0, &(0x7f00000002c0)="04", 0x1)
write(r0, &(0x7f00000003c0)="ff8433db1072c05460110d5f792332a405e44cb145c4aca54362b610d51e8968a319d946298839879193b7898e40707e9c53a82d03644126df9e0f6c3b5feda2d8c8aef2653e668611c4574b493c322abb3a1608dc37239ae46fc500693f489fe95a92ad8f06452f5ae6f79729d78d20edb40d18dbaae9d006b3a8fdb2a707ce1a183a70169780873992ef748da658bfda724af7c2cfa988658d2ff3c95f3b", 0xfffffd3e)
write(r0, &(0x7f0000000040), 0xfeea)


open(&(0x7f0000000040)='./file0\x00', 0xfffe, 0x51)
setreuid(0xee00, 0x0)
r0 = getuid()
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff})
setgroups(0x40000000000000d9, &(0x7f0000000040)=[0x0])
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000580)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000140)=0xc)
getsockopt$sock_linger(r1, 0xffff, 0x80, &(0x7f00000000c0), &(0x7f0000000100)=0x8)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{}, {0x1d}, {0x8106}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])
r4 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x0, 0x0)
ioctl$VT_GETACTIVE(r4, 0xc1045763, &(0x7f0000000100))
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x25}, {0x28}, {0x4000006, 0x0, 0x0, 0x8001}]})
close(0xffffffffffffffff)
r5 = socket(0x11, 0x3, 0x0)
sendto$unix(r5, &(0x7f0000000000)="b1000502000000000000000007000000330086000000000000f96ec4db745b76edcca1b37b673039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa5b236de351e2f0ac3ebbc257699a5f139b672f4d335d223e7d026ba8af630037382102000000720fd38bfbb770c1f5a8727781ea2e69e0bb76d907c400000000361b1257aea8c500002002fbff0c230000aabfba0900000008e371a304353712051eadb71d89e0ff0f0000e4b2ffff800000", 0xb1, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000001400)=[{&(0x7f0000000240)="e049c0d37348a45d6bee0bf84a9e", 0xe}], 0x1)
sysctl$net_inet_icmp(&(0x7f0000000200)={0x4, 0x12}, 0x4, &(0x7f0000000340), 0x0, 0x0, 0x0)
chown(&(0x7f0000000200)='./file0\x00', 0x0, r2)
setreuid(0x0, r0)
getegid()
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x287e)
r6 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r6, 0x0, 0x200000000000c, &(0x7f0000000080)="eaef125c00000000", 0x8)
setsockopt$inet_opts(r6, 0x0, 0x200000000000c, &(0x7f00000001c0)="ea00000100000000", 0x8)
setsockopt$inet_opts(r6, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0xc)
mkdirat(0xffffffffffffffff, &(0x7f0000000040)='./file0\x00', 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f00000000c0)="b211d7170d816684c8", 0x9)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendmsg$unix(r0, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


sysctl$machdep(&(0x7f0000000040)={0x7, 0xa}, 0x2, 0x0, 0x0, &(0x7f0000000340), 0x0)
r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000140), 0x1, 0x0)
dup2(r0, r0)
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0xc0185603, &(0x7f0000000000)={0x9f, 0x0, &(0x7f0000000080)=""/159})
r2 = syz_open_pts()
readv(r1, 0x0, 0x0)
setsockopt$sock_linger(0xffffffffffffffff, 0xffff, 0x80, &(0x7f0000000080)={0x2e49}, 0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
mkdir(&(0x7f0000000080)='./file0/file0\x00', 0x32)
openat$null(0xffffffffffffff9c, &(0x7f0000000080), 0x810a, 0x0)
rmdir(&(0x7f0000000080)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38/\x00')
pipe(&(0x7f0000000180)={0xffffffffffffffff, <r3=>0xffffffffffffffff})
r4 = socket$unix(0x1, 0x5, 0x0)
r5 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x1928, r5)
r6 = getuid()
sendmsg$unix(r4, &(0x7f0000000600)={&(0x7f0000000200)=@abs={0x1, 0x0, 0x3}, 0x8, &(0x7f00000005c0)=[{&(0x7f0000001640)="b46280f9ec989ef04430977966fcc9ac592a36bde047f36ea4ac83487ad64a84c334550ece2c45fe1496f665436fefd71635456d60922d6e23e44e7dea098b81089a57ac798e6cdecc6e161a6e0104322903205c083f2d09571985ff87bb8634ab3a004b630b20e48a0e05e180c2bb01b7a0e6eecd74a0e9633188e01a4e26b6ca65a507bced38051c4ae21767b1015fb7c67513d369464b09c0cac7ed17f41f79c44f3488b5cbeed12b07ddfcaf26b1adf5bd960f39d133b5bb65fa3391468622c0b433447c2c442ef96b96bf90dcdd32e92429f18c3fd884b4465c8700f8fe42f428466951299899d96a757562b32d0c", 0xf1}, {&(0x7f0000001740)="9bbe3ccf016abcbd735a41ee168824df24c18e1f3be88b98950b63ca08c097e2f2465b0cf64f11c8f680952cdc604767d0ebae90d6df266ff714c29b2db88f0984ad7844aa8dc4bff2767407a24d88ba89c228a24a3fbbf2bdcc887221f31b40541185733441b76bc93afaedcef917037467a1d063a77cf50a66be66f2e1345e4ac607f2a0232b7c28c3bc44223843e77761430049ba5aa172c6e60d4883fb960200d93cd3fc591ef7b9cf2d56d932cf1acae40bd894c3d53b09643da2dfa434d4b67ffd6a9558d12d0e0af8086838599d967f8260b1ac2b1ab2e0c0ea073b959431f489f78076ffbb4939b0e977", 0xee}, {&(0x7f0000000240)}, {&(0x7f0000001840)="cb0b0c28de90774e19ee92e1fc8dbdf58a0664db756c8a1fa5d5284c2c7b4b94c7955acdd162126487ee3238181b5e62b049996711702abe6edbbc4df0bc7c93708849a05f83478ec39652f7c57c0275361c73fb301cda7a6063d2202080b6d2947170c70795c20a068dcedc2dc78147a44ca6bd3cd5a2ec08d9f301caa4cbba1d6893e6541805b6f74b67d6457de7eff6cb54eb819a47ef038a90c51b8896896fec179bd27968a5a379a4d066e4973844aafe48eea89f3074246edfa5abea17c720fcecf93177363a0e48d43b245e934a91c23e0f78a32b073ff49a0a0b6f76d993e80fc199ee5705cd3d80e3b3e991c7794068ab268f0ff882cd3711d3da98deb0bda8f1775e8bb7a0492b7adc48ce03e2002ca1a3e0acd7cfba81b327959af13a2c15886b2a202edea65c01e7e045c859dbe0f0911746a9041a76661287f4214026779afa9454affa1a95d2a502d81a708147e253ab8df714bfeb909fe777eb98d0a007b5bdc8161e9fa1228a3d7446efb25fdd90baa12ec71cee1816531adcb0b070c5fd6c84df4f3400f819b594b19efebfc2b4606c86e3f9f7ac24a357e60b8ef0183a2a5174b003d470a84c557be5601e3d1f01222f65a2461aa6a089f510337169e2c3e08586aae113e76356e0011be9baf2487aaaa2af1838e2a1539eb14f2831f0ad0175ce46e73b2e37ec9f9c4f2c32f9dcd5ce67113dc99d0e8a048e5f4eb12f212512f95b090b0e2df98f987febfecbaa2da5818554040fa01e0a0d473ecf804814808d4eb7eb488066c70044251ef1a383bec55e29bdb3940c607b399ccbf8cdacdbdbf8a36ee78986b06a7ad66011dfcc588f6c3712d8bccde4269860d85aa2c57b8af6bb784d94727e4f73460d91d4629d3e6bcc1c6e1f0409a1bc84c2f0f5428f60ff350a767803647617c1e1f0bbda609c9c25bd74ac251cfb3e5d420a432302d9dabf74af99d9735906be0cf3b48ab446d12355267be1c7ecad68b4ff2a07b0fe42d00e9ced44d69ccd70460bcfccb979887486dfa280be73e86f01bfa840c51178f59520d2971ff39dd0c379e0b08c0593626fd2b7a6d8b63722a69b9f7f4f7337782261d6523502d64ef6515f954a81d901b5f525f5198b84791c7501e53ced56c17962a3ebafcc4c57b672ab5053752858c35bbf5afab01006bf0c48a951fb4541dda6445b86a0e4e5c25a08c62ea8120977487f67366d136c4ebf9c966ca1bae7145ba7c0b0e4533a03b8067994350baae30de786acab65fcb138b20241449b6db4fdb4e75de582ad16d9369e46a9d76647916a9a448aeeb1bc75456bd57a316ecabf4dc7969d4320b1ee973a38c1c46b5e5b26847143fa0d74cabbcaa953e7f4ae929ac2d1794b8af96ea159cfccec5ae661b7caf5860d936db290ae1bed79808e3b73531ebd33ab24622b2f24bf09251a3977b9a3ade3b60aedca546190da030abc27328c39d47542a7bdcfe5f1ba521ec2eacc6269734031ba31e51bf563ede9184c06f735753e6b64f0ab87eb068ea31ab6419dfef47d476374211e9a5c6386fa475ef649dd43009be2171062390fdfeb3149eae5ef9514e3801ac08ab11d17a5410effb6591237f8ed4218f1f5bef6b479b1cdf72222bb4ccc8706e3edf7f26373af86f1d183ed55bb70c8a06d58204809146397824da5e485117a3e4d454dd0171b05bf614ec39b419dfa41b14447878d31ee2efd1b7b53b313c52f7d3cb8f3cda5d4e589089f482d5909141f0462cd97a4638dfd0d7beeb130bacf02f6d15f641b410d48ee84298df04bb81337f53b618f4e5d1a75b567862e09ff7f7ed4b412ea13a96cf0a9bf787e9a32b42f29869eef1f39a289756caf6dcd28c1c8ef0c07c16830d9ba4c0086eb5ea36ae9cc8b980b7adfa477fe14a5b6bdffe19cae76b2d5343aceb7f627140127b1fccc353ea120152e6c83dea01b328a48da5c70b63d664cc034e5e67479cb9b998c66133d9a5b9a832f758838dd292f6eb26f21999f287d194ed895669c20fd2f3bb053b2bd6d5f97f7909035fe0d6c0de14afe65a48fb5477c45a8adaab4b98c48c58ecd384e89182baf0e6032ae3fb528c59fee473e15416901d481cd4749d0d9604aa0797a5139e23b40524b6e9da482d30216b5f58ae53a13e7b18cf7da91364a883cfaa9a52fbe0564c995626b7d26ddf74202f72c917dcc634ca2bfefcd6aded9fb39842e0db7e0ba658921d1822762c2c4486f686bc49bf816c57f3aba83a829a6d7fd4775c4476dddafa2d9d824f8243fdeb7c8ad8ac9d92a44c976c625fbd5252f558318f1d9a5c07c759101b407885d702d5ae9a4ae2a9b6f0124459af91e5b82a0d0bf01659f185995c0ff86757e5f4491900fc29bda78e4651536fd5689d8db3c267297963c0988baba5992c2ab9a11b4b73cdaf72b724d0f6fa61dc1352fae8e75a4dc902929c86b3e6baa606acfdc3704e22a63a8fba34aa035741e7a19a015363863244da009d32b36c8ccc4bd50ff6b22bccf90fcc3130f0bfda31c0b2b188d0d32e0f76dc3073628d7831aa057ff68077e82a0a66790a31cc16e658473f0262aadf91f166067ee6c0923d1a7a10d6ab7165729e8be9336f187892f5a68abfc66783f89a9477f4f3db154088ec1180a90644870facdfa5aec0f193385cf2d14e32340305f584dc9f544f9afe71042fff0099a981d3e16a84630de8d264d9067fc731a1bda093d29e60d8a05261cead1a97a4e652603b8392ae85300176abe713586c0af7f2fa164f6d2abcd3cae0f77f5298dbe500aaf6cb625c8004cbb26e323bfb99747a5d8584a028d777396fa4faa89c305a2f46405cbd2be9d052b76bb3457b39b8624d3b953a496b81a411e2f8511f98beac0060267e61b7f822baf9763b24d058f092f21f055fc08c19be05f0952db8ea2227d937fed655052eee01794b78ce3d255a645cce2615dacc389328f2b817aed5ea938c8cd53c44a22f2464cf256a975565b38b9c589a0e54ff291377960f116a1221185873a9002376747c995c912065d397780ca065b367cfcbf92af868cd31e481a33d41ef5e86c3e50b6d0c400223f1099cfa8f3a2d695b5fb2b986b31e15944f8ac8e3630dc23646095f0e72b15c8dc915d230c93dfcf336cfcfe60eaf449a5688af1a7d1fd91322868cfcf4e3bc69cb021bdae26717a150f88d2ea540748c91df34321e9f91366ba511029db5f38b5638b40511ee197bb867dd0322b80eb3a09b6aa2d6e93576890c61c4d0213a57b60952991b69036e3ec715adebf529f79d63eb28b2bb74f11843c9a7b04560d60e93edf58352c8af3c342f75f87861df5dbbaeb5d7afdc1f9c296b3792284c08adf00959111144a8d14031c83526d886566355ce295cbfddcffc41871cdb51dd84ae908a1dae801a06fc64b356f7a96015639ef2f8bcf27a2276d8bcf9ded3a0db52457a5c696f5d6f6660efaacbeb676022059d84d0a81921b746a21157861a881a90197c5f1f42df4c5de61e1f90f22c8a0765792630ce4168f3c2fbf4341139bac84a18fe13f9122320367ec8d516fe2e1ff4bd57301e11283a2edc55e4572af2a7d494705e4e410349f764fde1771df4bdf416989a009f10d3d80b25b215031db62776a1da3ce5dba54da9e0dc31131865e2ade71b61a06ac2af225652bf7c3d8cc2afec2b29fbb0eff9f1ef8bb122cbbfd7c5e61a345281bf593e6ac59d7487f50a477bc1cf07ed38f3f63e28ac3f1c61c14133dc4e1f0c65021125b9daa56bc3165a331ab5de6529fa614f032b157384f59f4c8c8193526522f08c420dccd389b4cdc4e59593252ee06bcfc9672d682781befe8893c23e9bcb86f031aee30c8a9f9be9dfd13ca95d45c38b69b722e08e39199fd593cf6898ef1683f3287a392a7d28d0f5fcc77c616c902de8b5c476fcb7989fb209047f3f6038a2c9eea3f8bd4a2216b29fd0daaeed3ce1ea23d1e3e61ad256b694579011cca8b18baa8ce0358722038bc0d05ef6d2874fc0189da23833374fb4fcc372c89a21565a97433ef34859c5887c6a3d9967ffa6e2e48ea07f9b52411296df0cc38daff57ad1e9e6c0d1b5ef51d29c2f84d2113d2e7628ef3adbf38ce24adb79a219253085eea591a58d2a44a20b0534ba51074b1d473e809475d1cf3422f9981cea3fd22501cf0369184867fbb8c5c2c86dab526bafc96b896164a9d471befe6cc108b7d8676736b14893039769d403f6c0f25f86981248caa3ec4bb79fdd7e207a211568ee55c37aabd799a9dc80242bffe6bfe4088c092c232a1b4b286390395b4b63ceb40809e1591107ed216f756eda2c240a3a00a986322ada3fd457177cc034c30c723e71fd5269f1a985e0b5863fdc39a3a8349455aebd52d1dd39d421f2c6bb60f9c365ec41215b48c71fe3b94763067d48c56323a09f89e3a994945c75bde3fe0dd73675041bb09f639a18f4288b816c88d6a7ead76a4ffff0e360078007c3422183ef06a17dcdb9d81670b75c09f161a8f71b84536445a65275c7e3ecb759fa9984bb5334620cf92fe3e9821ed9cb8347dd8edb3efe529c4e4a752c06c870ffe037ce65d0dd2668ec6ef7e252ff31541773c8f8027c7f41a666491617f6ac2a2c03e56f24d6f6f19605077891b924408e61eab909f8642b4d3ee5571c8c38cda0dc15cdf9e81fa0de4d9280a52b14cafc1c3f9ba047a99bbf6ffb40e5da6dd2fd368b49121bfabb6c8da45d404bae7a3f62ccbb16e23f8568fe89a49cb3cf522de16f017e7fa35f99499b40b210af612560c01d84d0e3545d465f53f1fa3ce5213172ad55b74229b47433819967a807dff1cd41476ac244f703abd5acda073bf9791c3f0ceaf610c04fea328edfc7dbefd3bc124df132ca8d4aef1ae8b26498b4d7fa53de28fcb200800f2fe3839a4e893a0456a5757493c83ca767320444ad7d3e9e50911e5025387dcf573d33e6f718cf62aa695dcf61345611110783852009a9294622572e7a46eb20aa2d5313f358bc985b30e40b29fb2e11e1b863ee360f81caf2f171e42cf1000753027ef7d8871c65772293cc916fdcaa53995cf38c2222dd782eb3ef037fb356bc333550f5e536012f255dd39a88eabe2e8e55b49cdff2dd6892b09c1c159d1a799b4ca7d7de371d823b99cacbb33982e69c25ef53693f52193e9cce14b3c2a53980160466e5dac7b4d82fe72670cbf0f3b66c642a4641ff1fbb49045835ac89ebb1d68dbf609dcebaec6fbcc34aa471dd093a30c1af45c00d33a93a09ea7104367def3fad5e180b9af3680c9656a4ec74edc781a825cfbf18625614e83dd130cfe2b370dd84151975bad10e411898755f6f0086187b07d6042827179787b51d7d1b08f53e17153d8cba77fd80e00ecf0d51775dad88041fdccd4ddd3b0de4b020bb83f736038e6cf9e1540e3267662c0e1b736ed81055823644490ca8f057bf0d52cab11b0ffb2adff4adf59579c8c96ea2ef5f8cf9ca9526062c5f699f80534fe7b29632febaabd760f6dbd94b0ae43705c41a58b3e3f5076a4b3aa91955ba2811a0f0eb7fa8caf260d8387d74bf038b03ede8f1ad7113d9c0c2db53b42529314f64e6938d12fd15f1fade7d46bf51169f8138ab90cfaf3d3a8fbf461cd5e533fda8ab66227f5354de26fd975039c4f630aad450eed0c561523581c11a9a2685dc95cf51a9e311067324ab0bebd9b6ed99f9ff7a4690442650a0f1de90f2db042f26ec65fc371a24056ae194e276cff62f7f91aa1611790ba5b73a0e10ff3ea290fbc5e6d79c5ab55241d19577b", 0x1000}], 0x4, &(0x7f0000002840)=ANY=[@ANYBLOB="2800000000000000ffff000001000000", @ANYRES32=r3, @ANYRES32, @ANYRES32=r3, @ANYRES32, @ANYBLOB='\x00\x00\x00\x00 \x00'/20, @ANYRES32=r5, @ANYRES32=r6, @ANYRES32=0x0, @ANYBLOB='\x00\x00\x00\x00'], 0x48, 0x4}, 0x0)
sysctl$kern(&(0x7f0000000240)={0x1, 0x1b}, 0x2, &(0x7f00000004c0), 0x0, &(0x7f0000000640)="3150007f6e4dc124e8a96b2fab2ee0f7a8d7e36e83ec6ce486510188f18ea38465009eaaf5353ab638ece50b27b606fcf77082aa2e061077918929e6a07806145376fce5d64d774d144a4c927481ce3aa541f8ebbe5fc63373beec49114dacd4efdd84aac4d6684744fa65174bb97648dfa8527dbbc8dffb45c6172ad92585d692266b4ec87ff49e6505adfbd62ee35160cfbe870ab76cfb2dad307007b93a3923a64b47189b80b19bbbfe3a3a97b5871b31a72566af05e00352f001e4114a320a16fe3f7d029e8aa058a82538f92bfe6335965151", 0xd5)
getpgid(0xffffffffffffffff)
ioctl$TIOCSETA(r2, 0x802c7414, &(0x7f00000001c0)={0x4, 0x7, 0x4, 0x100, "71d7515ba785d1c18841c127a508ce690574f19a", 0x7, 0x8})
r7 = semget$private(0x0, 0x1, 0x0)
semop(r7, &(0x7f00000028c0)=[{0x4, 0xd9, 0x1800}, {0x0, 0x0, 0x1000}, {0x4, 0x6, 0x1000}], 0x3)


setrlimit(0x8, &(0x7f00000000c0)={0x8})
setreuid(0xee00, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
writev(r0, &(0x7f0000000300)=[{&(0x7f0000000140)="f005c71031c1c5f421277b090000", 0xe}], 0x1)
r1 = getuid()
setreuid(0xee00, r1)
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000040)="03", 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x18, 0x2, 0x0)
setsockopt(r2, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
r3 = dup(r2)
setsockopt(r3, 0x1000000000029, 0xd, 0x0, 0x0)
getpeername(0xffffffffffffffff, 0x0, 0x0)
r4 = socket(0x2, 0x0, 0x0)
setsockopt(0xffffffffffffff9c, 0x2a, 0x2e9, &(0x7f0000000040)="5ab7736a", 0x4)
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r5 = socket$inet(0x2, 0x2, 0x0)
getsockopt$sock_int(r5, 0xffff, 0x800, &(0x7f0000000080), &(0x7f00000000c0)=0x4)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x800, &(0x7f0000000000)=0x6, 0x4)
getpgrp()
syz_emit_ethernet(0x52, &(0x7f0000000340)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaabb86dd60000000001c000080000000000000000000000000000000ff02000000000000000000000000000100000000", @ANYRES32=0x41424344, @ANYRES32=0x41424344, @ANYRESHEX=r4])
r6 = semget$private(0x0, 0x4, 0x108)
semctl$GETALL(r6, 0x0, 0x6, &(0x7f00000000c0)=""/158)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000003680)=ANY=[@ANYBLOB="aaaaaaaabb08004500002800681b0000009078ac1400aaac14002a0d000400"/41])
semctl$SETVAL(r6, 0x9960523362a3d0b9, 0x8, &(0x7f0000000200)=0xffffffff)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)


r0 = syz_open_pts()
kevent(0xffffffffffffffff, &(0x7f0000000640)=[{{r0}, 0x7ffffffffffffff7, 0x1}], 0x0, 0x0, 0x0, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f0000000140), 0xe4a, 0x0, 0xa9fa, 0x0)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x8000000000000001})
semctl$SETALL(0x0, 0x0, 0x9, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xb, &(0x7f0000000000), 0x0)


r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
acct(&(0x7f0000000140)='./file0\x00')
pwritev(r0, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{0x80}, {0x5}, {0x6}]})
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[])


openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r0 = openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000240)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000280)=0xc)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f00000002c0)={0x0, 0x0, <r2=>0x0}, 0xc)
setregid(r1, r2)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
msgsnd(0x0, &(0x7f0000001180)=ANY=[@ANYRES32], 0x0, 0x0)
msgget$private(0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r3 = syz_open_pts()
close(r3)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
kqueue()
open$dir(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSWINSZ(r3, 0x80087467, &(0x7f0000000200)={0x0, 0x0, 0x0, 0x9})
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
acct(0x0)
shmget$private(0x0, 0xc00000, 0x0, &(0x7f0000400000/0xc00000)=nil)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000132000/0x3000)=nil, &(0x7f00000a0000/0x1000)=nil, 0x80400000}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f000008c000/0x2000)=nil, &(0x7f00001f0000/0x1000)=nil}, {&(0x7f00001f0000/0x1000)=nil, &(0x7f0000001000/0x1000)=nil}, {&(0x7f0000132000/0x4000)=nil, &(0x7f00000b2000/0x1000)=nil}, {&(0x7f000008a000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {0x0, &(0x7f000002a000/0x3000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000086000/0x3000)=nil, 0xfffffffffffffffc}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil}, {&(0x7f0000091000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000001000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f000076a000/0x1000)=nil, &(0x7f0000132000/0x1000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000008a000/0x1000)=nil}, {0x0, &(0x7f0000092000/0x3000)=nil}], './file0\x00', 0x10000})
mprotect(&(0x7f0000145000/0x3000)=nil, 0x3000, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r4 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000800), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r4, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0})
msync(&(0x7f00000da000/0x3000)=nil, 0x3000, 0x2)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)


ioctl$TIOCCONS(0xffffffffffffffff, 0x80047462, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000000640)=ANY=[@ANYBLOB="c19648fbbc4c261c7d7c88d008004a1000280000000000009078000000000000000d0144100903000000007f00000100000000000000"])
open(&(0x7f0000000300)='.\x00', 0x0, 0x0)
pipe2(0x0, 0x4)
r0 = open$dir(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
mkdirat(r0, &(0x7f0000000340)='./file0\x00', 0x1a)
r1 = open(&(0x7f0000000040)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//../file0\x00', 0x0, 0x0)
r2 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, 0x0)
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])
r4 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r5 = fcntl$dupfd(r4, 0x0, 0xffffffffffffffff)
ioctl$FIONREAD(r5, 0x800c745b, &(0x7f0000000080))
ioctl$WSMOUSEIO_SETPARAMS(r2, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000200)})
sysctl$kern(&(0x7f0000000000)={0x1, 0x16}, 0x2, &(0x7f00000002c0)="9336932503a6874c767ba2e4d26007d11eb4bb37ba116711048fa5be4d5a5b638336d87023ed85a1215ddb1292519b", &(0x7f0000000100)=0x2f, &(0x7f0000000380)="f1a38a5ee848d8d67fc1e5febd4292d62fd2841dd14722239e5093859645116ade6ab14e3eca8da8317344905104dd36809862f5a1c0824f7fa0a07f554779a7f16ea59824df97b26e7891fccc2b", 0xfffffffffffffc91)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
socket(0x6, 0x2, 0x6)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000080))
dup2(0xffffffffffffffff, 0xffffffffffffffff)
accept(0xffffffffffffffff, 0x0, 0x0)
getsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1001, 0x0, 0x0)
fcntl$setstatus(r2, 0x4, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x10000, [{&(0x7f0000400000/0xc00000)=nil, &(0x7f0000c32000/0x4000)=nil, 0x3}, {&(0x7f0000412000/0x2000)=nil, &(0x7f00007e1000/0x3000)=nil, 0x642d045d}, {&(0x7f00006d3000/0x3000)=nil, &(0x7f000091c000/0x2000)=nil, 0x7}, {&(0x7f0000ff4000/0x9000)=nil, &(0x7f000090c000/0x4000)=nil, 0x5}, {&(0x7f0000ae2000/0x2000)=nil, &(0x7f000032f000/0x4000)=nil, 0xe635}, {&(0x7f0000e0e000/0x3000)=nil, &(0x7f0000a80000/0x3000)=nil, 0x18}, {&(0x7f0000635000/0x1000)=nil, &(0x7f0000308000/0x3000)=nil}, {&(0x7f000086f000/0x2000)=nil, &(0x7f000028d000/0x1000)=nil}, {&(0x7f0000ded000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000970000/0x4000)=nil}, {&(0x7f0000809000/0x1000)=nil, &(0x7f0000204000/0x2000)=nil, 0x2}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000596000/0x4000)=nil}, {&(0x7f0000fd3000/0x1000)=nil, &(0x7f0000ad3000/0x2000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f00001e7000/0x2000)=nil}, {&(0x7f0000b23000/0x1000)=nil, &(0x7f0000785000/0x2000)=nil}, {&(0x7f0000752000/0x1000)=nil, &(0x7f0000107000/0x1000)=nil}], './file0\x00', 0xd8a})
mmap(&(0x7f000070e000/0x2000)=nil, 0x2000, 0x0, 0x2010, r1, 0x0)
madvise(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x6)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x8060693c, 0x0)


pipe2(0x0, 0x0)
r0 = socket(0x18, 0x2, 0x0)
setgid(0xffffffffffffffff)
socketpair$unix(0x1, 0x1, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
preadv(0xffffffffffffffff, &(0x7f0000000440)=[{0x0}, {&(0x7f0000000340)=""/164, 0xa4}], 0x2, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x1b}, 0x4, 0x0, 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0))
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4e}, 0x2, &(0x7f00000004c0), 0x0, 0x0, 0x0)
close(r0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0xb0}})
r1 = socket(0x18, 0x1, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r1, &(0x7f00000000c0), &(0x7f0000000200)=0xc)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f00000001c0)={0x0, 0x401}, 0x10)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000480)={0x3, &(0x7f0000000240)=[{0x54}, {0x20}, {0x6}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000180)=[{0x60, 0x8}, {0x1c}, {0x206}]})
write(r0, &(0x7f0000000000)="7696e5f3d1f18c37cea8615ac7cf", 0xe)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r0, 0x8210560b, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0})


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
kqueue()
mknod(&(0x7f0000000300)='./file0\x00', 0x2000, 0x6da)
r1 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$FIOASYNC(r1, 0x80047466, &(0x7f0000000100)=0x5)
ioctl$FIOASYNC(r0, 0x80047470, &(0x7f0000000280)=0x5)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{}, {0x3d}, {0x16}]})
write(r0, &(0x7f0000000540)="76e5dead6f01f8607d2100000063", 0xe)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
bind$unix(r1, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={<r2=>0xffffffffffffffff})
dup2(r2, r0)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000640)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000080)=ANY=[@ANYBLOB="18000000ffff000001"], 0x18}, 0x0)
recvmsg(0xffffffffffffffff, &(0x7f0000000100)={0x0, 0x0, &(0x7f0000000640)=[{&(0x7f00000006c0)=""/86, 0x56}], 0x1, 0x0}, 0x0)
sendmmsg(r0, &(0x7f0000000480)={0x0}, 0x10, 0x0)


r0 = socket(0x2, 0x1, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
socket(0x11, 0x3, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
recvmsg(r3, &(0x7f0000000340)={0x0, 0x0, 0x0, 0x0, &(0x7f00000024c0)=""/236, 0xec}, 0x0)
sendmsg(r2, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
setsockopt$sock_int(r0, 0xffff, 0x2000, &(0x7f0000000080)=0x4, 0x4)
writev(r0, &(0x7f0000000640)=[{&(0x7f0000000140)="4534122cb25ac71eee67fea7ef79bfcd8421636cb079da6dffefb384603bdd6bdc6ba6b3916e87bf948e26f6c69b480188166bc6d6de481f66dab68c8548ccea9d0001f20887f575f96ae98678ae2888de940a83231e8d70349ef32df073c6403f37ab3b071f8c6b6143d2d7592d5faa82d078c66a1f19eaade9dc52ee8450555a9832016a20f25111317ccb78b4d62ef5", 0x91}], 0x1)
writev(r0, &(0x7f0000002cc0)=[{&(0x7f0000000440)="e2e41f7e9877650af85764", 0xb}, {&(0x7f0000000480)="e0961267527edfec3cd84bfdbf5a8f0de6a7dbaf6e31f0434d679d0f7d9f4668039209d744fc15753f3eda3b9291a3c1f2c247be62c0e3b00728cd6c34aa09f786d4d37a769b9f5f4eb1ac484a319acfd81da82a6d45acd7a270961970fef5cd35f715cfd2331f0b30a4e1fbf6c8a7e82abf9d2565e11de1fc66f5c95a8931ef04771354103dd288030564b7576ebb549ac7057b1fa9464eda41fde389a328566098e9dbfceec1102442dcee05a7fa1f20c4f373a7b8dccd65", 0xb9}, {&(0x7f0000000540)="7a8d4c47680e2d3e197359a72af0f843728001f1c33e8d0c4c36fdb4", 0x1c}], 0x3)
shutdown(r1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000300)=[{0x74}, {0x3}, {0x812e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0xc0}, {0x60}, {0x16}]})
write(r0, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xe)


sysctl$net_inet6_icmp6(&(0x7f0000000000)={0x4, 0x18, 0x3a, 0x1}, 0x4, 0x0, 0x0, 0x0, 0x0)


r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(r0, &(0x7f0000000400)=[{&(0x7f0000000180)="9c0b291fec6a5560c6011c38", 0xc}], 0x1)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000980)={'tap', 0x0})
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
sysctl$ddb(&(0x7f0000000000)={0x9, 0x5}, 0x2, 0x0, 0x0, 0xfffffffffffffffe, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000ffc000/0x4000)=nil, 0x4000, 0x0)
sysctl$hw(&(0x7f0000000040), 0x40000371, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x0, 0x0})
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0xffffd)
open(0x0, 0x0, 0x0)
getuid()
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
mlock(&(0x7f0000007000/0xc000)=nil, 0xc000)
getpid()
setuid(0xffffffffffffffff)
setrlimit(0x0, &(0x7f0000001480)={0x0, 0xfffffffffffffffb})
fcntl$setown(0xffffffffffffffff, 0x6, 0x0)
msgctl$IPC_SET(0x0, 0x1, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000280)={0xffffffffffffffff, <r3=>0xffffffffffffffff})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt$sock_timeval(r3, 0xffff, 0x1005, &(0x7f0000000000), 0x10)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
r4 = semget$private(0x0, 0x4, 0x100)
semctl$IPC_STAT(r4, 0x0, 0x2, 0x0)
semctl$SETALL(r4, 0x0, 0x9, &(0x7f0000000180)=[0x401])
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000240)=[{0x40}, {0x44}, {0x6}]})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000680)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f00000000c0)=[{0x64}, {0x84}, {0x26}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x16, 0x0, 0x0)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000600), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000680)={&(0x7f0000000640)=[{0x7}, {0x88}], 0x2})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{0xc0}, {0x84}, {0x4000006}]})
write(r0, &(0x7f0000000180)="23009100007adb020317bdda2b7e", 0xe)


socket(0x11, 0x3, 0x0)
symlinkat(0x0, 0xffffffffffffffff, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000140)="b10005016000009f0500070005000000331c13fecea10500fef96ecfc72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd38bfbb770c1f5a872c881", 0x72, 0x0, 0x0, 0x0)
socket(0x11, 0x0, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
mkdir(0x0, 0x0)
sysctl$vm(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ff7000/0x3000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000604000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000691000/0x2000)=nil, &(0x7f0000ff8000/0x4000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil}], './file0\x00'})
bind$unix(0xffffffffffffffff, 0x0, 0x0)
semctl$GETALL(0x0, 0x0, 0x6, 0x0)
sysctl$hw(&(0x7f0000000200)={0x6, 0x18}, 0x2, 0x0, 0x0, 0x0, 0x0)
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))


open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
r0 = getpid()
ktrace(&(0x7f0000001d40)='./file0\x00', 0x0, 0x1720, r0)
stat(&(0x7f00000001c0)='./file0\x00', &(0x7f0000000200))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000400)=[{0x4d}, {0x3}, {0x812e}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


mkdir(&(0x7f0000000040)='./file0\x00', 0x0)
unveil(&(0x7f0000000280)='.\x00', &(0x7f00000002c0)='c\x00')
unveil(&(0x7f00000001c0)='./file0/file0\x00', &(0x7f0000000080)='r\x00')
execve(&(0x7f00000002c0)='./file0\x00', 0x0, 0x0)


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000100))
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x17}, 0x4, &(0x7f0000000180)="bb713058073a48a41f4e0c8854efbdf4c849e12ca0179d48757e7304a9160073f610dd7404000000000000007e6fe7bafde5758cc530e208942fb171b67be174816488078ce5afbb5484546d7a1e3919ec3c27e49c30df6001fc2c530c83937f463161cf575946b242ac97a258989929e36dcefc152bfe953cddb80b21ccde27", &(0x7f0000000040)=0x80, 0x0, 0x0)
sysctl$kern(&(0x7f0000000200)={0x0}, 0x2, 0x0, 0x0, 0x0, 0x0)
r0 = socket$inet(0x18, 0x0, 0x102)
r1 = dup(r0)
connect$unix(r1, &(0x7f0000000000)=@abs={0x0, 0x0, 0x0}, 0x8)
ioctl$WSKBDIO_SETBELL(r1, 0x80105703, &(0x7f0000000240)={0x100, 0x80000001, 0x4003, 0x1000006})
ioctl$WSKBDIO_GETDEFAULTKEYREPEAT(0xffffffffffffffff, 0x400c570a, &(0x7f0000000440))
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x287e)
close(0xffffffffffffffff)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd01)
r2 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
utimensat(0xffffffffffffffff, 0x0, &(0x7f0000000140)={{0xfffffffffffffff7, 0xffffffff}, {0x0, 0x2}}, 0x0)
fchmodat(r2, &(0x7f0000000d00)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x297856873e19a725, 0x2)
readv(r2, &(0x7f0000000040)=[{&(0x7f0000002140)=""/4112, 0x1000}, {&(0x7f0000001140)=""/4092, 0x1000}], 0x1000000000000037)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000580), 0x8000, 0x0)
setreuid(0x0, 0xee01)
socket(0x18, 0x1, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000040)=[{}, {}, {0x3, 0x0, 0x0, 0x2}]})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000007, 0x0, 0x0, 0x0, 0x0)
r3 = socket$inet(0x2, 0x2, 0x0)
r4 = socket$inet(0x2, 0x2, 0x0)
dup2(r4, r3)
setsockopt$inet_opts(r4, 0x0, 0x200000000000a, &(0x7f0000000000)="ea00005c00000000", 0x1)
setsockopt$inet_opts(r3, 0x0, 0x200000000000c, &(0x7f00000003c0)="ea00000100000000", 0x8)
setsockopt$inet_opts(r3, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0x8)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sysctl$vm(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, 0x0)
socket(0x18, 0x2, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000280)={0x3, &(0x7f0000000380)=[{0x1c}, {0x80}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = openat$zero(0xffffffffffffff9c, &(0x7f00000003c0), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
mquery(&(0x7f0000ffc000/0x2000)=nil, 0x2000, 0x0, 0x0, 0xffffffffffffffff, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
setrlimit(0x0, &(0x7f0000000040)={0x0, 0x8})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$FIONBIO(r1, 0x8004667e, &(0x7f00000004c0)=0x8001)
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f00000000c0)=0x5)
readv(r1, &(0x7f0000000000)=[{&(0x7f00000009c0)=""/4096}], 0x3e)


r0 = socket$inet(0x2, 0x1, 0x0)
getsockopt$sock_timeval(r0, 0xffff, 0x1006, 0xffffffffffffffff, &(0x7f0000000000)=0xf)


socketpair$unix(0x1, 0x0, 0x0, 0x0)
syz_open_pts()
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000240)=[{0x24}, {0x2d, 0x0, 0x0, 0xfffffffe}, {0x6, 0x0, 0x6}]})
syz_emit_ethernet(0x1019, &(0x7f0000000400)=ANY=[])
ioctl$TIOCOUTQ(0xffffffffffffffff, 0x40047473, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000240)=[{0x84, 0x0, 0x1, 0x3}, {0x1c}, {0x3786}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])


ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f0000000080)={&(0x7f0000000300)=[{}, {}, {}], 0x3})
sysctl$vm(&(0x7f0000000080)={0xa}, 0x3, 0x0, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
syz_open_pts()
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
mkdir(0x0, 0x0)
unveil(0x0, 0x0)
unveil(&(0x7f00000001c0)='./file0/file0\x00', &(0x7f0000000080)='r\x00')
execve(&(0x7f00000002c0)='./file0\x00', 0x0, 0x0)
r1 = open(0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc018696c, 0x0)
sysctl$vm(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socket(0x2, 0x7, 0x8)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mkdirat(0xffffffffffffff9c, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
mkdirat(0xffffffffffffff9c, &(0x7f00000005c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
connect$unix(0xffffffffffffffff, &(0x7f0000000000)=@abs={0x682eb13985c518e6, 0x7}, 0x8)
openat(0xffffffffffffffff, 0x0, 0x2, 0x123)
r2 = socket(0x800000018, 0x0, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}, 0x0, 0x8000000000000000})
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
r3 = semget$private(0x0, 0x2, 0x86)
semctl$GETALL(r3, 0x0, 0x6, &(0x7f0000001240)=""/4096)
socket(0x20, 0x0, 0xdd)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$FIOASYNC(r1, 0x8004667d, &(0x7f0000000000)=0x3)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
chdir(0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000240)={0x5, &(0x7f0000000280)=[{0x35, 0x0, 0x2, 0x283d000}, {}, {}, {0x80}, {0xfffe}]})
writev(r0, &(0x7f0000000500)=[{&(0x7f0000000000)="af18a64591749e07ad1273f580a0", 0xe}], 0x1)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x0, 0x0})
write(0xffffffffffffffff, 0x0, 0x0)
fcntl$getown(0xffffffffffffffff, 0x3)
openat$vnd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$VNDIOCCLR(0xffffffffffffffff, 0x80384601, 0x0)
r0 = socket(0x0, 0x0, 0x0)
pipe2(0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{0x2c}, {0x84}, {0x4000006, 0x2, 0x0, 0x3feffe}]})
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSETAW(r2, 0x802c7415, &(0x7f0000000040)={0x0, 0x0, 0xfffffffe, 0x0, "254dfc210b4aa916fbd5f000"})


ioctl$BIOCSETWF(0xffffffffffffff9c, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x3, 0x0, 0x0, 0xfffffffe}, {0x6, 0x0, 0x0, 0xbe}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0xfffffffffffffe59)
munmap(&(0x7f0000e34000/0x1000)=nil, 0xffffffffdf1cbfff)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f0000000500)={&(0x7f0000000480)='./file0\x00', 0x56, 0x0, 0x3e})
fchmod(0xffffffffffffffff, 0x2)
r1 = syz_open_pts()
ioctl$FIOASYNC(r1, 0x80047460, &(0x7f00000000c0))
ioctl$FIONREAD(r1, 0x4004667f, &(0x7f0000000280))
socketpair$unix(0x1, 0x1, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r2 = socket$unix(0x1, 0x5, 0x0)
listen(r2, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
syz_open_pts()
syz_open_pts()
syz_open_pts()
socket(0x2, 0x0, 0x0)
acct(&(0x7f0000000040)='./file0\x00')


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
r1 = socket(0x18, 0x2, 0x0)
r2 = open$dir(&(0x7f0000000000)='./file0\x00', 0x200, 0x0)
r3 = open$dir(&(0x7f0000000680)='./file0\x00', 0x0, 0x0)
select(0x40, &(0x7f0000000500)={0x3fc}, 0x0, 0x0, 0x0)
r4 = openat$diskmap(0xffffffffffffff9c, &(0x7f00000000c0), 0x20, 0x0)
ioctl$DIOCMAP(r4, 0xc0106477, 0x0)
dup2(r3, r2)
r5 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
close(r5)
setsockopt(r1, 0x1000000029, 0x37, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
syz_extract_tcp_res(0x0, 0x81, 0xe53)
syz_extract_tcp_res$synack(&(0x7f0000000040)={0x41424344, <r6=>0x41424344}, 0x1, 0x0)
syz_emit_ethernet(0xf8, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0xea, 0x0, 0x1}, @tcp={{0x2, 0x1, r6, 0x41424344, 0x1, 0x0, 0x10, 0x4, 0x2, 0x0, 0x233, {[@generic={0x0, 0x5, "96c729"}, @sack_perm={0x4, 0x2}, @sack={0x5, 0x16, [0x4, 0x0, 0x40000001, 0xde5, 0x2]}, @timestamp={0x8, 0xa}, @generic={0x4, 0x2}]}}, {"d1c2f0bfe2d0786ca28e44289f59aba04d62ff16e6bb47f1cd981d0cf5f225560531db5a3a6c3cb3d5ac50e0eec7423f3ef5e3c4a13f81f14f843a32b529e4649b57d581159522ddf03a6cabf358af4e1ae7ab79a9aac6417859ae29d8de08ba3da1e6387381a61f166b78d7ae58ccd15a08555c8e7db3e261cbba4f565ff3567edfcacd1a43a2f80b44a3727c2f46723f3826d98423"}}}}}})
syz_emit_ethernet(0xb4, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
syz_emit_ethernet(0x6e, &(0x7f00000002c0)=ANY=[])
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x1, &(0x7f0000000000)=[{0x401, 0x4, 0xad, 0x6}]})
syz_emit_ethernet(0x36, &(0x7f00000001c0)=ANY=[])
flock(r0, 0x0)


r0 = socket(0x2, 0x3, 0x0)
setreuid(0xee00, 0x0)
r1 = getuid()
setreuid(0xee00, r1)
r2 = dup(r0)
setsockopt$inet_opts(r2, 0x0, 0x15, &(0x7f0000000080)='\x00\x00\x00\x00', 0x4)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x4, 0x0, 0x0)
socket(0x1, 0x0, 0x0)
mknod(&(0x7f0000000100)='./file0\x00', 0x2000, 0x6000)
r1 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$FIOSETOWN(r1, 0x8004667c, &(0x7f00000000c0)=0x1)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0286988, &(0x7f00000001c0))
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x20000, 0x0)
ioctl$BIOCFLUSH(r2, 0x20004268)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x0, 0x0})
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000800)="9b0209c3eb987ab7fe4189c99e805e6e84d356960798a692992117d672a736ba1bd857feb09901fe0dcee53766797f42e3303eac3846528d050712f838130efce33f523ba44765f5f6915b0227390ed95bd9dc6d4dc7e149d4d6d06a3f23616e773302d9cae75e39a5a11e32e0e6ebd635450b2eba540af7f2aa5dbfbdd900a00800000050acd76b5c567049ef436dbea0d7562f52950fa5ef6e84c513252ddd8680a944d5c2bd021cc793994922dfc10000000000062ab475cca257352828a76e5314be5629235c0febeff57cab95e894238b96ca5d4d3e670fea610c00009bef19525cb6f7e8570b2a374f1400041ed45bb7ad3fe963cb9a8bd949ee0fc6dbceb7d956015947b3e88aa810f8ed7cca10ff010000000000001345daa49507756faf775275ca390b94e85d5a95b8bdacb9429c25483a9275d0da3b561c6adc3ca67845c3386ce33141141f26a88016dd6b436218bdbdc9ac0a623855e941dc1872fcb045e0d9df1ecc6357ee21e2b0802cb60eec6add5e94723235f06715e7eecc3e0760c70e1dd7873e27142bbae1a7e44de453a073fe3426f334b80f043ba9136d57c799353d46dd81439b111a511a288bee5dfb2e353e3bb073e3342273216b07e49ca4df0fd2dbe9a8eb377010ee678a0900d8c7fb7d82693a096344671843a1f2082612b0ff237c6e505ff5f5ba932954d73c630fdb791f833a1da5af0704f687e196f4f7859e071ec98111cc9024f790ce16ceaa7d0104e39789d91000009a5bec77c992c792eb013621a86709cf57acd9981f947115f608227da8c54d8aa668931edd0b599b3d8cf5a8438ae08c1f70483223c3ba38088fb2e65a51edfed44c55a4d734bb553d642ca2bcdd1a08378317dc8f787469c3b3c14e4b1b46c2c8b03b99", &(0x7f00000002c0)=0x285, 0x0, 0x0)


sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504000000000000e30b060000001a", 0x11, 0x0, 0x0, 0x0)
socket$inet6(0x18, 0x2, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
fcntl$lock(r0, 0xf, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000001c0)={0x4, &(0x7f0000000200)=[{0x3ff, 0x8, 0x5, 0x3}, {0x9, 0x4, 0x0, 0x46c7}, {0x200, 0xdb, 0x8, 0x1}, {0x6, 0x6, 0x40, 0x7}]})
openat$vmm(0xffffffffffffff9c, &(0x7f00000000c0), 0x200, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x70e, 0x54)
open(&(0x7f0000000080)='./file0\x00', 0x70e, 0x0)
open(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000300)={0x0, 0x0})
setreuid(0xee00, 0x0)
r1 = getuid()
socket$inet(0x2, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x2, &(0x7f0000000100), 0x0, 0x0, 0x0)
setreuid(0x0, r1)
r2 = semget$private(0x0, 0x2, 0x490)
r3 = getgid()
r4 = getegid()
semctl$IPC_SET(r2, 0x0, 0x1, &(0x7f0000000140)={{0x8000, r1, r3, 0x0, r4, 0x88, 0x8}, 0x8001, 0x1f, 0x3f})
setreuid(0xee00, r1)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x50}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x10, 0x0, 0x37)
r5 = msgget$private(0x0, 0xfffffffffffffffd)
msgsnd(r5, &(0x7f0000000040)=ANY=[@ANYRESHEX, @ANYRESDEC], 0x0, 0x0)


r0 = socket(0x2, 0x2, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f0000000180)=[{{r0}, 0xfffffffffffffffe, 0xc9, 0x1, 0x6665}], 0x8491, 0x0, 0x0, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r0, &(0x7f0000000000), 0x10)


syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000), 0x10)
r1 = dup(r0)
listen(r1, 0x0)
r2 = socket(0x2, 0x1, 0x0)
connect$unix(r2, &(0x7f0000000000), 0x10)
r3 = dup2(r2, r2)
shutdown(r3, 0x1)
dup2(r0, r2)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000200), 0x1, 0x0)
ioctl$SPKRTONE(r0, 0x80085301, &(0x7f0000000000)={0x0, 0xffffffff})


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r1 = socket$unix(0x1, 0x5, 0x0)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
semop(0x0, &(0x7f00000000c0)=[{}], 0x1)
semop(0x0, 0x0, 0x0)
getegid()
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
setreuid(0x0, 0x0)
getuid()
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
r2 = getuid()
r3 = semget$private(0x0, 0x0, 0x0)
semctl$SETALL(0x0, 0x0, 0x9, 0x0)
r4 = getegid()
semop(r3, &(0x7f0000000140)=[{0x4, 0x200, 0x1000}, {0x3, 0x6, 0x1800}, {0x4, 0x201, 0x1000}, {0x3, 0x1000}, {0x0, 0x7a5}, {0x3, 0xff72}, {0x1, 0xdb, 0x800}, {0x0, 0xa}], 0x8)
semctl$IPC_SET(r3, 0x0, 0x1, &(0x7f00000000c0)={{0x9, 0xffffffffffffffff, r4, 0x0, r4, 0xa, 0x7}, 0x2, 0x2, 0x10000000009})
r5 = getuid()
setreuid(0x0, r5)
getgid()
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000000)={{0x186, r2, 0x0, 0x0, 0x0, 0x51, 0x5}, 0x2, 0x100000001, 0x1})
setsockopt$sock_cred(r1, 0xffff, 0x1022, 0x0, 0x0)
munlock(&(0x7f0000ffa000/0x1000)=nil, 0x800000000000)
socket(0x18, 0x2, 0x0)
socket(0x0, 0x2, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
sendmsg(0xffffffffffffffff, 0x0, 0x0)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$unix(0x1, 0x5, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x1000, 0x0, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x27, &(0x7f0000000040)="5ab7736a", 0x4)
syz_emit_ethernet(0x12a, &(0x7f0000000240)=ANY=[@ANYBLOB="b96d9900533a8f943f3614ef86dd6000000000f4000080000000000000000000000000000000ff020000000000000000000000000001001b0000000000000023d63955dd91e3781ca5c89f22e94aea9836f38b3b4ce8dba8b2ce03014d1c98dbfeebb60401000502000004010003a734b2bf062e1864097b38c4ae703b19b8b0e64ab7e6ea2ff1cf9faa5f2b79ce61dae2d4eef74c30ed247fd5d7b2da2519057bc5de49b07b1192291f3bd629357be75e023661c8ff1703ba1306f3a1ce5d89e2a7afff3e8db264174e4dc47bced7b8cef69c861e9f5c707e9cf8f4a9fbdbeaedddd497c6fe2a67172b9eeff53cfa531cfbda6ed848279db84aedaee08e393a46fde303a5845199cb4ccbc142f3ce4e204e2000000000000000", @ANYRES32=0x41424344, @ANYRES32=0x41424344, @ANYBLOB="5000000090780000"])
open$dir(&(0x7f0000000b80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x200, 0x0)
r1 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
r2 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000300)='./file0\x00', r2, &(0x7f0000000c80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mkdirat(r2, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
symlinkat(&(0x7f0000000700)='./file0\x00', r2, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f0000000dc0)='./file0\x00', r1, &(0x7f0000000ec0)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mkdir(&(0x7f0000000000)='./file0\x00', 0x0)


r0 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1001, 0x0, 0x0)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000000)="b886b4e47f", 0xfffffffffffffee7}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r1 = socket(0x2, 0x1, 0x0)
bind(r1, &(0x7f0000000000), 0x10)
listen(r1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1002, &(0x7f00000000c0), 0x4)
connect$unix(r0, &(0x7f0000000000), 0x10)
write(r0, &(0x7f0000000080)="04bdfa5d1d2873c63e3534825ba166e2fea9aec43050006123339a346f731573d8d508753f95b7688ad48b8cf6bbca325cebc37fc4e1dd543dbe2da6dd", 0xffea)


socket(0x0, 0x2, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1023, 0x0, 0x0)
connect$inet(0xffffffffffffffff, 0x0, 0x0)
r0 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000680), 0x0, 0x0)
close(r0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r1 = syz_open_pts()
close(r1)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
setreuid(0x0, 0xee01)
open$dir(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$TIOCCONS(r1, 0x80047462, &(0x7f0000000100)=0x8)


sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x19}, 0x4, &(0x7f0000000040)="bb703057", &(0x7f0000000080)=0x4, 0x0, 0x0)


sendmsg(0xffffffffffffffff, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x0, 0x0, 0x280}, 0x0)
open(0x0, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r0, 0x80085761, &(0x7f00000000c0)={0x3})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000400)=[{0x4c}, {0x3}, {0x812e}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])
r2 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000180), 0x1, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(r2, 0x80085762, &(0x7f0000000400)={0x3})


r0 = socket$inet6(0x18, 0x3, 0x0)
getsockopt(r0, 0x29, 0x1a, 0x0, 0x0)
openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000100), 0x7fd121c96b60a609, 0x0)
open(0x0, 0x0, 0x0)
r1 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r1)
setgroups(0x0, 0x0)
ktrace(&(0x7f0000000180)='./file0\x00', 0x4, 0x1024, r1)
socket(0x11, 0x3, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x11a}})
r2 = socket(0x18, 0x1, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
setrlimit(0x3, &(0x7f0000000000)={0x7fff, 0x100000})
sysctl$hw(&(0x7f0000000440)={0x6, 0x19}, 0x2, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000280), 0x1, 0x0)
ioctl$BIOCSETWF(r3, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000700)=[{0xc}, {0x24}, {0x6}]})
write(r3, &(0x7f0000000740)="76e5dead6f01f8607d2100000063", 0xe)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7}})
getsockname$inet(r2, &(0x7f00000000c0), &(0x7f0000000140)=0xc)
r4 = socket(0x18, 0x1, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


r0 = socket(0x11, 0x3, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{}, 0xffffffffffffffff})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000140)={0x3, &(0x7f0000000100)=[{0x64}, {0xc}, {0x6, 0x0, 0x0, 0xfffffffe}]})
writev(r1, &(0x7f0000000080)=[{&(0x7f00000000c0)="d3d9bc6f7a689f455f7bc4e71ba7", 0xe}], 0x1)
setsockopt$sock_int(r0, 0xffff, 0x1002, &(0x7f0000000080), 0x4)
r2 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x28}, 0x2, 0x0, &(0x7f0000000080), 0x0, 0x0)
mknod(&(0x7f0000000300)='./file0\x00', 0x2000, 0x6da)
r3 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
sendmsg$unix(r3, 0x0, 0x0)
openat(0xffffffffffffff9c, 0x0, 0x0, 0x0)
setreuid(0xee00, 0x0)
openat(0xffffffffffffffff, 0x0, 0x0, 0x0)
r4 = getuid()
ioctl$KDSETLED(0xffffffffffffffff, 0x20004b42, &(0x7f0000000140)=0x7)
setreuid(0xee00, r4)
r5 = socket(0x2, 0x2, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
getsockname$inet(0xffffffffffffffff, 0x0, &(0x7f0000000000))
syz_emit_ethernet(0x36, &(0x7f0000000000)=ANY=[@ANYBLOB="ffffffffffffffff"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
bind(r5, &(0x7f0000000000), 0x10)
ioctl$FIONREAD(r2, 0x8040691a, &(0x7f00000001c0))


recvmsg(0xffffffffffffffff, &(0x7f0000000240)={0x0, 0x0, &(0x7f0000000140)=[{&(0x7f00000000c0)=""/91, 0x5b}], 0x1, 0x0}, 0x0)
r0 = openat$pci(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$PCIOCGETROM(r0, 0xc0107004, &(0x7f0000000140)={{}, 0x0, 0x0})


select(0x40, &(0x7f0000000040)={0xffffffffffffffff}, 0x0, 0x0, 0x0)
r0 = socket(0x2, 0x1, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000180)={<r2=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
dup2(r0, r1)
sendmsg(r2, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000001c0)=[{0x6c}, {0x48}, {0x6}]})
syz_emit_ethernet(0x62, &(0x7f00000006c0)=ANY=[])


open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$WSMOUSEIO_GETPARAMS(r0, 0x80105727, &(0x7f00000000c0)={0x0})


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x1, 0x0, 0x100000000000000, 0xffffffffffffffff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x2, 0x0, 0x1b}, 0x4, 0x0, 0x0, &(0x7f0000000200), 0x0)
open(&(0x7f0000000180)='./file0\x00', 0x75f493fec6515f78, 0x0)
getppid()
setreuid(0xee00, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x20000, 0x0)
r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r0, 0x80085761, &(0x7f00000000c0)={0x3})
openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)


r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x80, 0x90)
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, 0x0}}, 0x10, 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
poll(&(0x7f0000000140)=[{0xffffffffffffffff, 0x4}], 0x1, 0x0)
recvfrom$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
symlinkat(&(0x7f0000000000)='./file0\x00', r0, &(0x7f00000000c0)='./file0\x00')
sysctl$net_inet6_ip6(&(0x7f0000001f40), 0x4, 0x0, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sysctl$net_inet6_ip6(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socket$unix(0x1, 0x0, 0x0)
semget(0x0, 0x0, 0x0)
getuid()
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000280), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000140)=[{0x54}, {0x54, 0x0, 0x0, 0x2}, {0x812e}]})
syz_emit_ethernet(0x17a, &(0x7f0000000500)=ANY=[])


semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f0000000a80), 0x10)
sysctl$hw(&(0x7f0000001240)={0x6, 0x12}, 0x2, &(0x7f0000000140)="ecca4536ef224438a550b9abad6250e65b220ad2095b97edf56befb8a1b1dbe552b3b35ecd", &(0x7f0000001140)=0x25, 0x0, 0x0)
r0 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r1 = getuid()
fchown(r0, r1, 0xffffffffffffffff)
r2 = getuid()
setreuid(0xee00, r2)
mkdirat(0xffffffffffffff9c, &(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x180)
renameat(0xffffffffffffff9c, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0xffffffffffffff9c, &(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
faccessat(r0, &(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x6, 0x0)
getsockname$unix(0xffffffffffffffff, &(0x7f0000000000)=@abs, &(0x7f0000001200)=0x8)
r3 = socket(0x2, 0x1, 0x0)
bind(r3, &(0x7f0000000000), 0x10)
r4 = dup(r3)
listen(r4, 0x0)
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
syz_open_pts()
syz_open_pts()
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
connect$unix(0xffffffffffffffff, &(0x7f0000000000), 0x10)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b1000504600000000000000007000000331c13fecea10500fef9ed06c72fd3357ae320b37b673039d2d236073705ae04be38164991f7accf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139b672f4d335d223e7d029d6ba8af630037282102000000720f70c1f5a472c881ea6e69e0bb76d907c400000200361b1257aea8c5000020020000000000008abfba09001d89e001e2ffffffffff7f00ff00"/177, 0xb1, 0x0, 0x0, 0x0)
open$dir(&(0x7f00000000c0)='./file0\x00', 0x1, 0x0)
r1 = openat$pci(0xffffffffffffff9c, &(0x7f00000001c0), 0x6, 0x0)
preadv(r1, &(0x7f0000002400)=[{&(0x7f0000000200)=""/139, 0x8b}, {&(0x7f00000002c0)=""/30, 0x1e}, {&(0x7f0000000300)=""/247, 0xf7}, {&(0x7f0000000400)=""/4096, 0x1000}, {&(0x7f0000001400)=""/4096, 0x1000}], 0x5, 0x1f)
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x10205b1a)
r2 = open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)
r3 = socket(0x18, 0x1, 0x0)
listen(r3, 0x0)
accept$unix(r3, 0x0, 0x0)
openat$klog(0xffffffffffffff9c, &(0x7f0000001400), 0x0, 0x0)
shutdown(r3, 0x0)
recvmmsg(r3, &(0x7f0000001380)={0x0}, 0x10, 0x0, 0x0)
shutdown(r3, 0x2)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x205b9a)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
readv(r2, &(0x7f0000000380)=[{&(0x7f0000000200)=""/87, 0x57}], 0x1)
setuid(0xffffffffffffffff)
socketpair(0x1e, 0x3, 0x0, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
pipe(&(0x7f00000001c0)={<r5=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r5, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)='\x00', 0x1}], 0x1)
socket$inet(0x2, 0x2, 0x0)
r6 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r6, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
setsockopt$inet_opts(r6, 0x0, 0xd, &(0x7f0000000240)="ea08000000000000", 0x8)


r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0x2e, 0x0, 0x0)
getsockopt(r0, 0x29, 0x2e, 0x0, 0x0)


setrlimit(0x0, 0x0)
syz_open_pts()
open(0x0, 0xa02, 0xc)
r0 = socket(0x0, 0x4, 0xc7)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r1 = msgget$private(0x0, 0x2e)
pipe2(0x0, 0x0)
setreuid(0xee00, 0x0)
r2 = getuid()
setreuid(0x0, r2)
r3 = socket(0x800000018, 0x2, 0x0)
r4 = socket(0x18, 0x1, 0x0)
setsockopt(r4, 0x29, 0xe, &(0x7f0000000000)="02000000", 0x4)
dup2(r4, r3)
listen(r3, 0x0)
msgsnd(0x0, &(0x7f0000000040)=ANY=[@ANYRES64=r1, @ANYRESOCT, @ANYRES8=r0], 0x1f, 0x0)
msgctl$IPC_RMID(r1, 0x0)


r0 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
ioctl$FIONREAD(r0, 0x4004667f, &(0x7f0000000000))


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
sysctl$kern(&(0x7f0000000300)={0x1, 0x48}, 0x2, 0x0, 0x0, &(0x7f0000001440)='\x00\x00\x00\x00', 0x4)


r0 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0206923, &(0x7f00000001c0))
ioctl$FIONREAD(r0, 0xc0206922, &(0x7f00000001c0))


madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x0)
socketpair$unix(0x1, 0x5, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000001180), &(0x7f0000000040)=0xc)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000015c0))
mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x5200)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
kqueue()
setrlimit(0x0, 0x0)
r0 = semget$private(0x0, 0x4, 0x5c0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000300)={0x2, &(0x7f00000000c0)=[{}, {0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x33}, 0x2, 0x0, &(0x7f0000000080), 0x0, 0x0)
syz_emit_ethernet(0x46, &(0x7f0000000140)=ANY=[@ANYBLOB="aaaaaaaaaaaa000000001c0086dd00000000000000020000000000bbfe800000000000000000000189a95ace1efac6e9052475ca0400000000aa0000"])
semctl$SETALL(r0, 0x0, 0x9, &(0x7f0000000000)=[0x1, 0x4, 0x6529])
close(0xffffffffffffffff)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000a, &(0x7f0000000040)='\x00', 0x1)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x9, &(0x7f0000000240), 0x0)
r2 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
getppid()
r3 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f000000e000/0x2000)=nil, 0x2000, 0x0, 0x10, r3, 0x0)
munmap(&(0x7f000000e000/0x3000)=nil, 0x3000)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x0, 0x10, r2, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x1ffa, 0x0)
symlink(&(0x7f0000000780)='./file0\x00', &(0x7f0000000740)='./bus\x00')
open(&(0x7f0000000000)='./bus/\x00', 0x200, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0x0, 0xffffffbf, "0000c6f26461c094f4ffffffff00"})
readv(r1, &(0x7f0000000280)=[{&(0x7f0000000600)=""/131, 0x83}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000001340)={0x3, &(0x7f00000003c0)=[{0x84}, {0x60}, {0xe}]})
write(r0, &(0x7f00000006c0)="e506000000000000004aaed75a5a", 0xe)


open(&(0x7f0000000040)='./file0\x00', 0xf8e, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r0)
r1 = kqueue()
readv(r1, &(0x7f0000000180)=[{0x0}], 0x1)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000180)=0xc)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
r1 = socket(0x18, 0x3, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x18, 0x2, 0x0)
r3 = dup2(r1, r2)
sendmsg$unix(r3, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000000c0)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000300)=0xc)
r2 = socket(0x11, 0x3, 0x0)
sendto$unix(r2, &(0x7f0000000000)="b1000503000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)
r3 = socket$unix(0x1, 0x2, 0x0)
getsockopt$sock_int(r3, 0xffff, 0x200, &(0x7f0000000040), &(0x7f0000000000)=0x4)
mknodat(0xffffffffffffff9c, &(0x7f0000000400)='./file0\x00', 0x2000, 0x0)
r4 = open(&(0x7f0000000180)='./file0\x00', 0x10, 0x12)
fcntl$setstatus(r4, 0x4, 0x4)
mknod(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
ioctl$TIOCSETA(0xffffffffffffff9c, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "0100dd2dfa7f0000000400"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x4f}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000040), 0x3, 0x0, 0x0, &(0x7f0000000080)="4f1d4c6344b80ed788b6a4515248df3aa745bb992c574ab4cdf5587145812eab4a988f7fafd7a01d99776d988908cd186b51f34f8c15ffa0c685ad4116c783959eff4278384b4000384dbb1c2aaeff10b4135529a1da6fda67c67469d954be811b25ec5521559154c586eefff122009f659cd3e27e98a3241495005f102d9101d158284c0ee3250aa7c11042330de22a299ab00894fdc9bac6042d", 0x4)
pipe(&(0x7f0000000100)={<r5=>0xffffffffffffffff})
fcntl$setstatus(r5, 0x4, 0xc0)
r6 = getppid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r1, 0x0, 0x0, 0x64}, 0x0, 0x0, r6})
pipe(&(0x7f00000001c0)={<r7=>0xffffffffffffffff})
setreuid(0xee00, 0x0)
r8 = getuid()
setreuid(0x0, r8)
ioctl$WSKBDIO_GETMAP(r7, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x8000000000000000, 0x8000000000000001})
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000003c0)={<r9=>0x0}, &(0x7f0000000400)=0xc)
r10 = semget$private(0x0, 0x7, 0x3c0)
semop(r10, &(0x7f0000000700)=[{0x3, 0x4}, {0x2, 0x2ff}, {0x3, 0x8, 0x800}, {0x3, 0x3ff, 0x1800}, {0x0, 0x0, 0x1800}, {0x2, 0x6ff, 0x1400}, {0x1, 0x7ff, 0x1800}], 0x7)
ktrace(&(0x7f0000000340)='./file0\x00', 0x4, 0x0, r9)
semop(0x0, &(0x7f0000000280)=[{0x3, 0x1f}, {0x4, 0x3f}, {0x0, 0x2, 0x800}], 0x3)
semctl$SETALL(r10, 0x0, 0x9, &(0x7f00000002c0)=[0x87fc, 0x9b7])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{0x21, 0x0, 0x0, 0x8001}, {0x1, 0x0, 0x0, 0x3}, {0x216, 0x0, 0x0, 0xfffffffe}]})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100))
ioctl$BIOCSETWF(0xffffffffffffff9c, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x2}, {0x9, 0x0, 0x0, 0xffffffff}]})
setreuid(0x0, 0xee01)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
r1 = socket$inet(0x2, 0x2, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
dup(0xffffffffffffffff)
openat$pf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
ktrace(0x0, 0x0, 0x1720, 0x0)
openat$vmm(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
getuid()
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000580), &(0x7f0000000140)=0xc)
getsockopt(r1, 0x0, 0x9, 0x0, 0x0)


socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000015c0)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000000), &(0x7f0000000040)=0xc)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbdf13b9fd812eaa4e713048e69931929648", 0x14)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x5900)
r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
kevent(0xffffffffffffffff, &(0x7f00000000c0)=[{{r0}, 0xffffffffffffffff, 0xb7c61f5c345976d}], 0x0, 0x0, 0x0, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x7, 0x0, 0x0, 0x0)
close(r0)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
r0 = socket(0x2, 0x1, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000040), 0x3, &(0x7f0000000080), 0x0, &(0x7f0000000180), 0x0)
setrlimit(0x0, &(0x7f0000000000)={0x8000000000000000, 0xfffffffffffffffc})
kqueue()
getpid()
setreuid(0xee00, 0x0)
socket(0x10, 0x3, 0x0)
setitimer(0x2, &(0x7f00000000c0)={{0x3, 0x80000}, {0xfffffffb}}, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x0, 0x0)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
shutdown(0xffffffffffffffff, 0x0)
semctl$IPC_SET(0xffffffffffffffff, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x21d}, 0xfffffffffffffffc})
r1 = socket(0x18, 0x3, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sysctl$hw(&(0x7f0000000000)={0x6, 0xf}, 0x2, &(0x7f0000000040)="d2737fc886c1625cab16db1ea60281fd246dc3bab1f7", &(0x7f0000000080)=0x16, &(0x7f0000000140), 0x0)
getsockname$inet(r1, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$inet(r0, &(0x7f0000000000), 0x10)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
munmap(&(0x7f0000f0a000/0x2000)=nil, 0x2000)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105727, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
open$dir(0x0, 0x2, 0x0)
sysctl$machdep(&(0x7f0000000000)={0x7, 0x1}, 0x2, 0x0, &(0x7f0000000140), &(0x7f0000000180), 0x0)
mmap(&(0x7f0000557000/0x2000)=nil, 0x2000, 0x0, 0x2dbe387c4417487e, 0xffffffffffffffff, 0x22f2f052)
mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0, 0x1012, 0xffffffffffffffff, 0x0)
syz_open_pts()
setrlimit(0x6, &(0x7f00000000c0))
mprotect(&(0x7f0000ffb000/0x4000)=nil, 0x4000, 0x1)
mlockall(0x1)
munlock(&(0x7f0000ffb000/0x4000)=nil, 0x4000)
mlock(&(0x7f0000ffb000/0x3000)=nil, 0x3000)


r0 = semget$private(0x0, 0x2, 0x621)
semctl$IPC_RMID(r0, 0x0, 0x0)
semop(r0, &(0x7f00000006c0)=[{0x4, 0x3f, 0x1800}, {0x4, 0xff, 0x1000}, {0x3, 0xe75, 0x800}, {0x4, 0xcc7, 0x400}, {0x2, 0x7f, 0x1c00}, {0x3, 0x0, 0x1000}, {0x1, 0x770}, {0x0, 0x23, 0x3000}, {0x1, 0x250, 0x1800}], 0x9)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892}, 0x1c)
sendmsg$unix(0xffffffffffffffff, &(0x7f00000003c0)={&(0x7f0000000040)=@abs={0x1, 0x0, 0x0}, 0x8, &(0x7f0000000100)=[{&(0x7f0000000080)="9e3a0b440b39c6faaefd093d860c56b298d5d949e18293291b4c9887a2607fc093f365c0c59a4e87ed90e32ee5a430394a2558f1f4f94a63f06372ea74c33d06015b0d6cbeaa4be2b208bbf23f2a3ab647b2744fba0bb61c09ea27e01a6e6a4c14370c939f66", 0x66}, {&(0x7f0000000440)="20dc2029560b620988fcd683ba84fe1108a4a6045aba646a34aec5f3276e25d9904af94b4fb2fde80680999a3e3d4d9d553e40e1bdee16830807b6349f7761175b5282706be86af5d70137a913503c85c01986e5d07b7a8c0b5f455e032f2918c60176e6de1abac51a7ccc364a5fd1103fa839aab0d6574f568d9c186ce38f29ddd00022dc540ff0cf59de781c58b33ea6be34ab19e86f6542cb825a30a98a2f1d0e283b10ebd30d747d7658ef1629b9b79ed53e3b7f1883aff1ee06b34fdad06e84b2b8863c541bc1927b3bbcd50c42328d041ff2c7a89fc13570bf813c9887d3921f3ddc0170a7c83a1b6d462085f6f2bb870bd1d2", 0xf6}], 0x2, &(0x7f0000000700)=ANY=[@ANYRES32, @ANYRESDEC, @ANYRES64=r0, @ANYRES32=0xffffffffffffff9c, @ANYBLOB="2548ffe2ffff43163af973fc42f39267633b5783ff76e25cd3eab49b12d42fc045711969f4542b0adc52b291f6fcf6d000"/62], 0x20, 0x8}, 0x406)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000040)={{0x1, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x101, 0xad}, 0x10001, 0xfff, 0x9})
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0xb2, 0x4}, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4})
r1 = socket$inet(0x2, 0x5, 0x2)
setsockopt(r1, 0x0, 0x5, &(0x7f0000000000)="5d8ad1ae", 0x4)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000800)={&(0x7f0000000100)=@abs={0x0, 0x0, 0x1}, 0x8, &(0x7f0000000640)=[{&(0x7f0000000140)="60c15402f1743e6f110c6ea0ffc66f6950de2f808f608d3ca9deb71c0f69adeef6ecff1a58c248d4447d416ade6e79a58d05c7ca6bfd4bc912943120a218a65aa2273d07e91cde3be2017cb43b35d5a27ca333632eb823d9b83f7497fb53", 0x5e}, {&(0x7f0000000840)="f20c812b0a4dcb9c4dec7f9bc4c18bae69af8d5217ac4caa60b1d0e8bdab1322f3a99cac6b183588e46fb6f1e7476de5c507108b3b5ecc6b8e73607a7a26db37811945d11bb506f80b699108641b6a15843e60a6fa268d5a68b404c40bfe5a24ebecf03cf737140c48b61d2f9e336aaf4ad4cc1424f2367d9c67f9ca2ebec7a77d1be9f066b2af349525918ea8846b299f24ba3df6deb65de5d7693ef517ee3832b1c66e937224e2704b14d55cdd96dc742beb79f2334376c85ca2fe", 0xbc}, {&(0x7f0000000280)="59ec7702a09fb2cadb566805d42d72cad494abd12191fd15bea7b5cb0b805c1dbeb2", 0x22}, {&(0x7f00000002c0)="f5249ea56d6a268b67812acec336cdd1a1e1679966ac4498e2c690daf84e3ca4fa3ea96176c2f106f19a4eb7ecce5abd69f0dcdc03b2bdde6b42a569ae1c4c7253d8862118b3ea47c0f703ede7cd51ae07d105224dee", 0x56}, {&(0x7f0000000340)="9fe41bf9eb48ef101990d2d8a710e6506db2469d252596e982595ff848c71e9fcc5bcd8e52fbe68f7244fc8d172541eae5ce8d32389b5675ce948d9224a3244cfcf50e91c6a57b7c149278158b847311f15c18d8883deeef1690d97f16", 0x5d}, {&(0x7f00000003c0)="5c14183284c7f8fcec5774c5e5624416e9e392c87f33ee6bd20f68dfd57ee5cf8b8028543440ba4021ae72efb8d10a5e56f571cf6df78a4b", 0x38}, {&(0x7f0000000900)="b640302f7b0ecca07282051bce0fcc4e9b85adf6327197e10b531babb91144810fb9728f4338fd892e848acfc31520d7aa721ae597a835f92bd67ebd345acce60a547a0e155a483caed9ce74162b38b12180f427bdd9bc4af6b3e417de51235034ade40be9d89e5d8f0f0a589823af40054e6b28d4927487989c1eac1ec93d6a8b181ca8e1a47c6c019031a7c1f4d024fc453446ba648ee67cf8028838a71e90a6eec8f52aa790e1af25e23702e1e6c91577945916344462f357ceb607b7735fe4a4fee4ed8b17384f59a182c00acb97d18b80b8659d777e2eb6c3279ff612e5cf2e99670822e73db7b46b", 0xeb}, {&(0x7f0000000500)="092475278c9b146ebeead89e090cce6414e5ef8c20cbc925fd738db95d5e3dfbe46f1148cfd9b3e6376bc52cc0fcf9846db22504c4a30e20a9c992d1c2af1dddf3b4cd248fcf6dd91572b419fe7d02068ce9334d71080cba0122702d761e6fff35224e", 0x63}, {&(0x7f0000000580)="81df2fdce87ffa60722beae067ec8c7483db986e9a330ada3b7df790ba5b394c8d13a762935de1ac3affbd16ec4ae64def646d6cd6d44118ebc72ab32c7c1f6f6c4edba6242a0e42305b693b5b4d9b979ed1d3d7b923a08960ce3c03c86b5660bfc83743913588ed2d9578ae00d3ea09070433b88a10f1f8fb4f3d4e3c47dfd0978a4c06f58a4f51a0d2b55d75f08b05196ac4df99aa2085c16b05d1299c5299e3f3a0fcf57084", 0xa7}], 0x9, &(0x7f0000000700)=ANY=[@ANYBLOB="2000000000000000ffff000000000000", @ANYRES32=0x0, @ANYRES32=0x0, @ANYRES32=0x0, @ANYBLOB="000000002000000000000000ffff000000000000", @ANYRES32=0x0, @ANYRES32=0x0, @ANYRES32=0x0, @ANYBLOB="00000000302da65901000000ffff0000011d0000", @ANYRES32, @ANYRES32, @ANYRES32, @ANYRES32, @ANYRES32, @ANYRES32, @ANYRES32, @ANYBLOB="000000002000000000000000ffff000000000000", @ANYRES32=0x0, @ANYRES32=0x0, @ANYRES32=0x0, @ANYBLOB="000000003000000000000000ffff000001000000", @ANYRES32, @ANYRES32=r1, @ANYRES32=r1, @ANYRES32, @ANYRES32, @ANYRES32, @ANYRES32, @ANYBLOB="000000002000000000000000ffff000000000000", @ANYRES32=0x0, @ANYRES32=0x0, @ANYRES32=0x0, @ANYBLOB='\x00\x00\x00\x00'], 0xe0}, 0x8)
r2 = geteuid()
r3 = semget$private(0x0, 0x4000000009, 0x82)
semop(r3, &(0x7f0000000340)=[{0x2, 0x8}], 0x1)
semop(r3, &(0x7f0000000140), 0x2aaaaaaaaaaaaddb)
semctl$SETALL(r3, 0x0, 0x9, &(0x7f0000000040)=[0x7ff, 0x1000])
semctl$SETALL(r3, 0x0, 0x9, &(0x7f00000001c0)=[0x7, 0x401, 0x95, 0x1, 0x5])
semop(r3, &(0x7f0000000080), 0x0)
r4 = getuid()
semctl$IPC_SET(r3, 0x0, 0x1, &(0x7f0000000240)={{0x21d, r2, 0x0, r4, 0x0, 0x188, 0x7e00}, 0x5, 0x8000000000000001, 0x10000000005})
r5 = getegid()
r6 = getpid()
r7 = open(&(0x7f0000000200)='./file0\x00', 0x102, 0x0)
r8 = getpid()
fcntl$setown(r7, 0x6, r8)
fcntl$setown(r7, 0x6, r8)
shmctl$IPC_SET(0x0, 0x1, &(0x7f0000000040)={{0x9, 0x0, 0x0, r4, r5, 0x42, 0xfff}, 0xc01, 0x79, r6, r8, 0xfff, 0x4, 0x8000000000000001})
r9 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r9, 0x0, 0x64, &(0x7f0000000000)="0100009bb7916646eb8cac75f639f9b1a4", 0x11)
r10 = socket$inet(0x2, 0x8000, 0xf8)
dup2(r10, r9)


r0 = socket(0x18, 0x1, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff}})
setsockopt$sock_int(r0, 0xffff, 0x1, &(0x7f0000002700)=0xffffffff, 0x4)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


r0 = socket(0x18, 0x1, 0x0)
shutdown(r0, 0x1)
shutdown(r0, 0x2)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0xca})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000040)={0x7ffffffe, 0x0, 0x7, 0x6b38415a, "2f78acf2ee60987b0d026cc4ffffaa175b31cb31"})
writev(r0, &(0x7f0000001580)=[{&(0x7f0000001340)="f2f5060e4a1ab0974870e40af8e001f53e04bf74fed4aee2be0863d275b2e4226489c933194ab7b2a0027b2f6f1b1d9cb787a7933c75e07eed0a09942d0104e4e1c8a9073576a8944f423bcaa96d8169aa92956791fed312477b15c06c89dca7", 0x60}], 0x1)


r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0xae828e137847f62, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
r1 = socket(0x18, 0x2, 0x0)
close(r1)
r2 = socket(0x18, 0x3, 0x0)
setsockopt(r2, 0x1000000029, 0x31, &(0x7f00000000c0)="b211d7170d816685c8e360f2fa41c1a0946988b272d2dd3dc90142a84231a746e337b372e93320cff6669cbe7868de45ed3fc33719ca6df71ecec8a918458b2c10a1f8c66653b276e180e9cb9b21f9982230f575295d48889c9a920796b2dd92fc8575680b37ba955d2c15e6d7c9198ed900ab006ddfb67869b51a2216114d1ece85f593e74035f5bc054eb1dbddf42a", 0x90)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x100000000000000, 0xffffffffffffffff})
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
writev(r2, &(0x7f0000001680)=[{&(0x7f0000000240)="ee61908275d599aea7a8e85c5b115df6304eaaca93cc7a7b505a93c15f76a526e66cf9baffd687bb", 0x28}, {&(0x7f00000002c0)="2aad6e921e4e810ec905857c284904078536dfca12b1e4e9621b7768012d27e33e5b6fdc89f96021efd76118f912b8ae373026ce7f9caaea7e0eaa0186cb9fb8996fc2efc47fb39c0caf57f346c0b6f77cb77d5b49e1d2ff060730e4af18fd20de92f2ead5138bbef498bae74cf1dd675c94a5ab67cb78c8915424f36622b7b2d88e41e9a9023eba8d10c6d8188d4f31535b5e8fdc7849609bc2c4d65eabc968fda90fb9df6c51b3d2b6d720a950be8dad814bc2caca3ca420c6f496141380094466fefed76eac8c9d194c217c8912f03e18abe31452048702efee7e96a9318546e79d8d19e6874a05ce00b3a3c6f98403f4", 0xf2}, {&(0x7f0000001700)="5c669053bc415ed0712e72e34b3499eefd6f7a3839ed20d54f0efd2ddea8a4aba09f94816987ac6807af98895716bf7e339a4fac086c8bedb1b6056ee2aef505b3ca86fe58678c82083a5180708a9d3e53e539ed5dd7", 0x56}, {&(0x7f0000000480)="1e226e9f857bfbb543b630b09d09214468401a21e5fbe9c33132f860089d", 0x1e}, {&(0x7f00000004c0)="e9862d50cda1ad305321428d2c6ca9e1af202279139624dbe3961effe54a37ea5c864d2636c2d564c7601d7104578d25cc4020b73b2bbee0bb26d83a3ea41b62d1a08685a4bfb55fa55da76ce0a6dc52", 0x50}, {&(0x7f0000000680)}], 0x6)
setrlimit(0x1, &(0x7f0000000000)={0xfffffffffffffffd, 0xffffffffffffffff})
ftruncate(r0, 0x20008002)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
r3 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r3)
r4 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x1, 0x0)
pwritev(r4, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)


r0 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x0, 0x0)
ioctl$WSMOUSEIO_SRES(r0, 0x80045721, &(0x7f0000000cc0)=0x3f)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000700)=[{0x48}, {0x2d}, {0x6, 0x0, 0x0, 0xfffffffe}]})
write(r0, &(0x7f0000000540)="76e5dead6f01f8607d2100000063", 0xe)


mknod(&(0x7f0000000500)='./file0\x00', 0x1000, 0x0)
symlinkat(0x0, 0xffffffffffffff9c, &(0x7f0000000140)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/file0\x00')
r0 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
r1 = open$dir(&(0x7f0000000040)='./file0\x00', 0x80, 0x149)
renameat(r1, &(0x7f00000000c0)='./file0/file0\x00', r0, &(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/file0\x00')
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
syz_emit_ethernet(0x46, &(0x7f00000002c0)=ANY=[@ANYBLOB="7bca7e58f7cd00000000000086dd609f284400102b0000000000000000000022642046cd40441d00fffffffffffffe800000000000000000ff00000000bb2b"])


mknod(&(0x7f0000000040)='./file0\x00', 0x2000, 0xe02)
open(&(0x7f0000000200)='./file0\x00', 0x0, 0x82)
openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x2, 0x0)


writev(0xffffffffffffff9c, &(0x7f0000000440)=[{&(0x7f00000001c0)="a0dd3dad6ba1364904b8095e4870a1448d", 0x11}], 0x1)
mknod(&(0x7f0000000500)='./file0\x00', 0x1000, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
socket(0x6, 0x3, 0x7)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000300), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, 0x0)
dup2(r0, r0)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000480), 0x1, 0x0)
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f00000004c0), 0xc)
geteuid()
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
write(r2, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xfef3)
r3 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x9, 0x0, 0x0)
getsockopt(r3, 0x0, 0xa, 0x0, 0x0)
accept(r0, 0x0, &(0x7f0000001580))
mknodat(0xffffffffffffff9c, 0x0, 0x0, 0x2d87)
open$dir(&(0x7f0000000580)='./file0\x00', 0x40000400001803c1, 0x0)
r4 = open(&(0x7f0000000080)='./file0\x00', 0x80, 0xe2)
mmap(&(0x7f0000011000/0x2000)=nil, 0x2000, 0x0, 0x10, r4, 0x0)
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r5, 0x80104267, &(0x7f0000000200)={0x2, &(0x7f0000000040)=[{0x28, 0x0, 0x0, 0x3f}, {0x6}]})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x8020699d, &(0x7f00000001c0))


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0xc0206921, &(0x7f00000001c0))
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x80206913, &(0x7f00000001c0))


sysctl$kern(0x0, 0x0, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cdde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f", 0x0, 0x0, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000001})
flock(r0, 0x2)
r1 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
flock(r1, 0x2)
r2 = open(&(0x7f0000000040)='./file0\x00', 0x205, 0x0)
fcntl$lock(r2, 0x8, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x1000300010008, 0xffffffffffffffff})
r3 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r3, 0x9, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x100000002})


mkdir(&(0x7f0000000040)='./file0\x00', 0x0)
mkdir(&(0x7f0000000100)='./file0/file1\x00', 0x0)
unveil(&(0x7f0000000180)='./file0/file1\x00', &(0x7f00000001c0)='x\x00')
unveil(&(0x7f0000000140)='.\x00', &(0x7f00000002c0)='r\x00')
chroot(&(0x7f0000000200)='./file0/file1\x00')
unveil(&(0x7f0000000300)='./file0\x00', &(0x7f0000000380)='x\x00')


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000240)=[{0x8}, {0x40}, {0x8006}]})
setrlimit(0x8, 0x0)
r1 = syz_open_pts()
close(r1)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
open(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000100)=[{0x54}, {0x80}, {0x6}]})
open(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206910, &(0x7f00000001c0))
syz_emit_ethernet(0x60f, &(0x7f00000004c0)=ANY=[@ANYBLOB="aaaaaaaaaaaaf8de7d15ee9c86dd60516d1405d90000fe80000000000000070000000000ffbbff0200000000000000000000000000012c1081"])


pipe(&(0x7f0000001440))
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
sysctl$kern(&(0x7f0000000040)={0x1, 0x32}, 0x2, 0x0, 0x0, &(0x7f0000001440)="cca410df", 0x4)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)='\t\x00\x00\x00', 0x4)
r1 = dup(r0)
setsockopt(r1, 0x1000000000029, 0xc, &(0x7f0000000000)="ffdaff10aac6a28ac93e2eddc45c8454e486f64c", 0x14)


setitimer(0x0, &(0x7f0000000100)={{0xffffffff, 0x2}}, 0x0)


r0 = kqueue()
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
kevent(0xffffffffffffffff, &(0x7f0000000140)=[{{r2}, 0xffffffffffffffff, 0x882919ab1cb74ec9, 0x91}], 0x0, 0x0, 0x0, 0x0)
kevent(r0, &(0x7f0000000100), 0x7a, 0x0, 0xffffffff, 0x0)
select(0x40, &(0x7f0000000080)={0xffffffffffffffff}, 0x0, 0x0, 0x0)
r3 = open(&(0x7f0000000300)='.\x00', 0x0, 0x0)
kevent(0xffffffffffffff9c, &(0x7f0000000440)=[{{r0}, 0xfffffffffffffffa, 0x0, 0x20, 0x0, 0x7}, {{r1}, 0x8000000000000006, 0x16, 0x8, 0x80000001, 0x20}, {{}, 0xffffffffffffffff, 0xa0, 0x1, 0x100, 0x9}, {{}, 0xfffffffffffffffb, 0x10, 0x20000000, 0x7fffffffffffffff, 0x6}, {{r0}, 0xfffffffffffffff9, 0x40, 0x20000004, 0xf602, 0x1}], 0x9, &(0x7f0000000540)=[{{}, 0x4, 0x20, 0x1, 0x401, 0x5}, {{}, 0xfffffffffffffffc, 0x8c, 0x1, 0x5, 0x1000}, {{}, 0xfffffffffffffff8, 0x20, 0x40, 0x1, 0x9fa}, {{}, 0xfffffffffffffffd, 0x24, 0x8, 0x7, 0x4}, {{}, 0xfffffffffffffffd, 0x12, 0xfffff, 0x8, 0x5}], 0x1, &(0x7f0000000600)={0x80000000, 0x3})
poll(&(0x7f0000000000)=[{r3, 0x4}], 0x1, 0x0)
poll(&(0x7f0000000200)=[{}, {r3, 0x15}, {r3, 0x1}], 0x3, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r4, 0x80104277, &(0x7f0000000140)={0x3, &(0x7f0000000100)=[{0x35}, {0x4}, {0x6, 0x0, 0x0, 0xfffffffe}]})
writev(r4, &(0x7f0000000080)=[{&(0x7f00000000c0)="d3d9bc6f7a689f455f7bc4e71ba7", 0xe}], 0x1)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000000), 0x10, 0x0)
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r5, 0x80104277, &(0x7f0000000140)={0x3, &(0x7f0000000100)=[{0x35}, {0x4}, {0x6, 0x0, 0x0, 0xfffffffe}]})
writev(r5, &(0x7f0000000080)=[{&(0x7f00000000c0)="d3d9bc6f7a689f455f7bc4e71ba7", 0xe}], 0x1)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000180), 0x800, 0x0)
r6 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r6, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r6, 0x80104277, &(0x7f0000000140)={0x3, &(0x7f0000000100)=[{0x35}, {0x4}, {0x6, 0x0, 0x0, 0xfffffffe}]})
writev(r6, &(0x7f0000000080)=[{&(0x7f00000000c0)="d3d9bc6f7a689f455f7bc4e71ba7", 0xe}], 0x1)
r7 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r7, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r7, 0x80104277, &(0x7f0000000140)={0x3, &(0x7f0000000100)=[{0x35}, {0xc}, {0x6, 0x0, 0x0, 0xfffffffe}]})
writev(r7, &(0x7f0000000080)=[{&(0x7f00000000c0)="d3d9bc6f7a689f455f7bc4e71ba7", 0xe}], 0x1)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b100050460000000c2190000000007000000331c13fecea10500fef9ed06c72fd3357ae320b37b673039d2d236073705ae04be38164991f7accf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139b672f4d335d223e7d029d6ba8af630037282102000000720f70c1f5a472c881ea6e69e0bb76d907c400000200361b1257aea8c5000020020000000000008abfba00007f3200"/177, 0xb1, 0x0, 0x0, 0x0)


ioctl$SPKRTONE(0xffffffffffffffff, 0x80085301, &(0x7f0000000040)={0x9})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
sysctl$kern(&(0x7f0000000040), 0x3, 0x0, 0x0, &(0x7f0000000080)="4f1d4c6344b80ed788b6a4515248df3aa745bb992c574ab4cdf5587145812eab4a988f7fafd7a01d99776d988908cd186b51f34f8c15ffa0c685ad4116c783959eff4278384b4000384dbb1c2aaeff10b4135529a1da6fda67c67469d954be811b25ec5521559154c586eefff122009f659cd3e27e98a3241495005f102d9101d158284c0ee3250aa7c11042330de22a299ab00894fdc9bac6042d", 0x4)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
socket(0x18, 0x2, 0x0)
sysctl$kern(0x0, 0x0, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436", 0x0, 0x0, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f00000002c0)=""/49, 0x31}], 0x1)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1800000029"], 0x3e}, 0x0)
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)


sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504600000000000000007000000331c13fecea10500fef9ed06c72fd3357ae320b37b673039d2d236073705ae04be38164991f7accf5f882b297be1aad2236deb51e2f0ac3ebbc257699a5f139b672f4d335d223e7d029d6ba8af630037282102000000720f70c1f5a472c881ea6e69e0bb76d907c400000200361b1257aea8c5000020020000000000008a", 0x8e, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x84000000000000})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendmsg$unix(r0, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff})
recvmmsg(r0, &(0x7f0000000480)={0x0}, 0x10, 0x0, &(0x7f0000000500)={0x2007fffc, 0xa})
munmap(&(0x7f000000e000/0x400000)=nil, 0x400000)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
fcntl$getown(r0, 0x5)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{0x44}, {0x81}, {0x8006}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x36}, 0x4, &(0x7f0000000080)="ab157888df3ccd154815a7bde7b1e1b4", &(0x7f0000000140)=0x10, 0x0, 0x0)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd02)
open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0x20006473, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000200)=[{0x7}, {0x80}, {0x812e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])


sysctl$kern(&(0x7f0000000080)={0x1, 0x55}, 0x4000000000000004, 0x0, 0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000100)={0x800b2a8, 0x0, 0x9, 0xffffffe1, "9f07957d0f7e32089069ee68d6a78615b7118c00"})
writev(r0, &(0x7f00000006c0)=[{&(0x7f00000005c0)="12e87772468cca40c2b5eb54b5672e3003b0bdd7b434cd0f14fc5be5c6f9b8674ad293218bd9cbcdb68c5be7154d00ffd8a92f183ce845f55dbcca388f9cadad7ab6e0ae48fe266b56beaa29b13e9db77b5c72f3f81da7f983069f454ccfc19ce1498ac1c8cd2965e210c10aea21d558875c29", 0x73}], 0x1)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x11, r0, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
getpid()
ioctl$FIOASYNC(0xffffffffffffffff, 0x8004667d, 0x0)
ftruncate(r0, 0x8531)
setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
mlockall(0x1)


r0 = open(&(0x7f0000002600)='./file0\x00', 0x78e, 0x0)
r1 = getpid()
ktrace(&(0x7f00000001c0)='./file0\x00', 0x0, 0x124, r1)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000180))


pipe2(&(0x7f0000000040), 0x0)
socket(0x18, 0x2, 0x0)
setgid(0xffffffffffffffff)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
pipe(&(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
open(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
ktrace(0x0, 0x1, 0x400, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
ioctl$FIONREAD(r1, 0x4004667f, &(0x7f0000001100))
fsync(r1)
setreuid(0x0, 0x0)
r2 = getuid()
setreuid(0xee00, r2)
semget$private(0x0, 0x4, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x0, 0x3011, r0, 0x4)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r3, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000400)=[{0x4d, 0xfc}, {0x0, 0x0, 0x0, 0xffffffff}, {0x16}]})
setitimer(0x0, &(0x7f0000000000)={{0x8000000000000000}}, 0x0)
shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffc000/0x3000)=nil)
r4 = socket(0x18, 0x3, 0x0)
r5 = socket(0x18, 0x2, 0x2)
r6 = dup2(r4, r5)
getsockopt(r6, 0x29, 0x400, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
socket(0x1, 0x2, 0x0)
shmdt(0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000340), 0x0, 0x0)


r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x39, &(0x7f0000000100), 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000080)=[{0x24}, {0x44, 0x7f, 0xc0}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000300)=ANY=[])


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$inet6(0x18, 0x3, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x1021, &(0x7f0000001ac0), &(0x7f0000001b00)=0xffffffffffffff10)


syz_emit_ethernet(0x36, &(0x7f0000000200)={@local, @broadcast, [], {@ipv6={0x86dd, {0x0, 0x6, "062500", 0x0, 0x2b, 0x0, @rand_addr="fe350e28ef0900c08cfe24be00", @loopback={0xfeffffff00000000}}}}})


r0 = socket(0x2, 0x1, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
mkdir(&(0x7f0000000000)='./file2\x00', 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x2, 0x4001, 0x0)
r3 = dup(r2)
r4 = fcntl$dupfd(r3, 0x2, 0xffffffffffffffff)
close(r4)
r5 = socket(0x2, 0x2, 0x0)
connect$unix(r5, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r4, 0xffff, 0x1023, &(0x7f0000000040), 0xe0)
close(r1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x4c}, {0x30}, {0x6}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


r0 = kqueue()
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
kevent(r0, 0x0, 0x0, 0x0, 0x7ff, 0x0)
dup2(r1, r0)


mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x2801)
r0 = socket(0x2, 0x4001, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(0xffffffffffffffff)
socket(0x18, 0x3, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r2=>0xffffffffffffffff})
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000040), &(0x7f0000000100)=0xc)
r3 = socket(0x6, 0x5, 0x4)
dup(r3)
ktrace(&(0x7f0000000280)='./file0\x00', 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
r4 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r4, 0x80206916, &(0x7f00000001c0))
r5 = socket(0x2, 0x1, 0x0)
listen(r5, 0x0)
close(r3)
getsockopt$SO_PEERCRED(r3, 0xffff, 0x1022, &(0x7f0000000140), 0xc)
sysctl$net_inet_tcp(0x0, 0x0, &(0x7f0000000100), 0x0, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000300)="9b0209c3eb987ab7fe4189c99e805e6e84d356960798a692992117d6728436ba1bd87f42e3303eac3846528d050712f838130efce33f523ba44765f5f6915b0227390ed95bd9dc6d4dc7e149d4d6d06a3f23616e773302d9cae75e39a5a11e32e0e6ebd635450b2eba540af7f2aa5dbfbdd900a0dad2b74f50acd76b5c567049ef436dbea0d7562f52950fa5ef6e84c513252ddd8680a944d5c2bd02adc7f1fe850c00000000000000062ab475cca257352828a76e5334be562995e894238b96ca5d4d3e670feac9b4e8aa9bef19525cb6f7e8570b2a374f1400041ed45bb7ad3fe963cb9a8bd949ee0fc6dbceb7d956015947b3e88aa810f8ed7cca10ff010000000000001345daa49507756f49775275ca390b94e85d5a95b8bdacb9429c25483a9275d0da3b561c6adc3c141f26a88016dd6b436218bdbdc9ac0a623855e941dc1872fcb045e0d9df1ecc6357ee21e2b0802cb60eec6add5e94723235f06715e7eecc3e0760c70e1dd7873e27142bbae1a7e44de453a073fe3426f334b80f043ba9136d57c799353d46dd81439b111a511a288bee5dfb2e353e3bb073e3342273216b07e49ca4df0fd2dbe9a8eb377010ee678aad0bd8e9fb7d82693a096344671843a1f2082612b0ff237c6e505ff5f5ba932954d73c630fdb791f833a1da5af0704f687e196f4f7859e071fc98111cc9024f790ce16ceaa7d0104e39789d9100000010000000000050000000000", &(0x7f00000002c0)=0x210, 0x0, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1023, &(0x7f0000000080), 0x4)
shutdown(r1, 0x1)
listen(r1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r1, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000000)=[{0x1bed436cf54a9f1c, 0x7}, {0x100, 0x4cacf823}, {0x44, 0x9}, {0x88, 0x7f}, {0x1, 0x5}, {0x88, 0x2}], 0x6})
r6 = open(&(0x7f0000000180)='./bus\x00', 0x0, 0x0)
recvfrom(r1, &(0x7f0000000100)=""/22, 0x16, 0x800, &(0x7f0000000140)=@un=@file={0x0, './bus\x00'}, 0x8)
ioctl$FIONREAD(r6, 0x4004667f, &(0x7f0000000080))


mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
sysctl$net_inet_divert(&(0x7f0000000100), 0xb, &(0x7f0000000280)="a7c1290f17722447b2c63e743f6b379fa5267a394a5d94db9417b6982f519b111f61ad994119ba843799517c2ddf4c65594fb3b55a5fce717f619f904ce7b41e4296cf777a1db4747703440100000023e48310b779f9619c7642d6d7f500000000000000000000000000000000c37a11ae4dbe56deeb1ccae6d8e73f8976b460abc78bfdf1bf11c3ec2956f559e2ae95b19752a20f358e90edd96264cbc18906750f34e7e595d09e4e313414f688d6388b713904a7996cc92a328db185299eeabc8e35147498451c4a84a9d41bf693affdc27f4569379570f4", &(0x7f0000000180)=0x67, &(0x7f0000000640)="e2714be05c6a432bfcb43ba70e2bb9e6add925cf34d00e465191e199efee4898bfe502dcc0a3e3fd0cc0e7969055dcb470ddd2f263dfb8065cbf63d41b2a29e4f92695a2dae1e619ba2b0ccd1e605cd2827beb6ddaf6b579cccebb6d267a74d6af9f2cddd1eb38180245caf3e0f240c5f1ee52a05a63c446df6149316cc2e17b775698e9114250d85ec893fbd204889e5c3f37ee5894227fa7b36a2803d9c558953caa2452fff1bf82f49299d2fd07d8a464fd351d966782d21806ba5be9dc66d7dd572cdae3822888010771550dd55b3014876e2537e33b838b12b10d843be49e4cfc3b3f04a60088dd3cc3fbdc16864e028753d898f0bc0bd6e20f96274d743755332aebcec91d4f490000000000000000628c7c526f7de4f21b6260bacfe436d6eb63a96ded0b0f29cbc8ea2a7d2760b1fdf551506810d63132c72c14be5ffcc53ca339aea237797e863010f33b057982b6825dbdef1ce4425ae7d1234ad5cb69", 0xee)
open(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
link(0x0, 0x0)
syz_emit_ethernet(0x36, 0x0)
r0 = socket(0x18, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000000029, 0x8, &(0x7f0000000100)="54db0b54854d9a37275631fa6e64174e78402377241f3b2ed58c7bda91f1bb6545d47631dff7e76aa265a2f8843b8ce1456e3fb26125a455bacf5bd48c8d7bae6cf710c023b177094b91f32433bbacecd6613f1005d2fb896d2b5266906e9b8c5c1a418c4d72195cfcda996f6f5dce220916634c6dbdefed7290ee704452", 0x7e)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000080)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
sendto$unix(r2, 0x0, 0x0, 0x8, 0x0, 0xfffffffffffffd4e)
sendto$unix(r2, 0x0, 0x0, 0x0, 0x0, 0x0)
sendto(r2, 0x0, 0x0, 0x0, 0x0, 0x0)
recvfrom$unix(r1, &(0x7f0000000100)=""/55, 0x37, 0x0, 0x0, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x0, 0x0})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x3e}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)
openat$speaker(0xffffffffffffff9c, 0x0, 0x2, 0x0)
syz_emit_ethernet(0x1c7, &(0x7f0000000a80)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa8100000086dd67518aec018d3204ff010000000000000000000000000001fe8000000000000000000000000000bb67140003000000008730d9c21e763952528cfae9719c796afe8000000000000000000000000000bb0000000000000000000000000000000100000000000000000000000000000000ff020000000000000000000000000001ff020000000000000000000000000001ff010000000000000000000000000001ff02000000000000000000000000000135d9872d62202de705029e045ac34d54ff02000000000000000000000000000104000000000000004e214e2100089078802c0788e97cac35298ae5a599324acc1098e1b9c87fcd96d1901a9b7e56d554f54d1c9618f96a153e3ae94457dcbfeae1bc6dd6d0ea7e1a890991093b4212b2b198b2b6cb1157e93a570bb4433790d419d143f6e5ef7ea3b8afa8c62a31d002c2f8a5503855d26f39a572ddc0f49ef4cc1b69d1f74a665bb2ef8178a2bf4c653bc005cecbe0ee7afb11218af570fc96b272b4e3441e1c32a53efb919f"])
msgrcv(0x0, 0x0, 0x0, 0x0, 0x0)
shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000000)="9b1809ffffffffffffff7f473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6fd74c94d1b44", &(0x7f0000000040)=0x10011, 0x0, 0x0)


r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
r1 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x401, 0x0)
poll(&(0x7f0000000040)=[{}, {r1}], 0x2, 0x0)
ioctl$FIONBIO(r0, 0xc0107008, &(0x7f0000000040))
sysctl$kern(&(0x7f00000008c0)={0x1, 0x48}, 0x2, &(0x7f0000000900), 0x0, 0x0, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x462, 0x0)
pwritev(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f00000000c0)="bd", 0x1}], 0x1, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x2c}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)
r0 = semget$private(0x0, 0x1, 0x300)
semctl$GETZCNT(r0, 0x4, 0x7, &(0x7f00000003c0)=""/96)


sysctl$kern(&(0x7f0000000000)={0x1, 0x45}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000000), 0x6, 0x0, 0x0, 0x0, 0x0)


open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
flock(r0, 0x2)
r1 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
close(0xffffffffffffffff)
fcntl$lock(r1, 0x9, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x100000002})


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r2, 0x80206919, &(0x7f00000001c0))


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x1000000000000})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


setitimer(0x0, &(0x7f0000000100)={{}, {0x0, 0xced3}}, 0x0)
setitimer(0x0, &(0x7f0000000080)={{}, {0x0, 0x8001}}, 0x0)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
open(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000100)=[{0x54}, {0x80}, {0x6}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000580)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000140)=0xc)
setreuid(0xee00, 0x0)
r2 = getuid()
r3 = open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
r4 = getuid()
fchown(r3, r4, 0xffffffffffffffff)
fchdir(r3)
setreuid(0xee00, r2)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r1}})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4e}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000180)=0x66, 0x0, 0x27)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
socket(0x18, 0x2, 0x0)
sysctl$kern(0x0, 0x0, &(0x7f0000000100)="71f91e3471ac00cb5c656358bc5a91501d94", 0x0, 0x0, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f0000000080)=""/51, 0x33}], 0x1000000000000036)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1800000029"], 0x3e}, 0x0)
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)


mknod(&(0x7f0000000500)='./file0\x00', 0x1000, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x80206910, &(0x7f00000001c0))
r2 = dup2(r0, r0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f00000001c0)="55f8f5782087a072a82ec35f78d14780f5", 0x11)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r2, 0x8020699d, &(0x7f00000001c0))


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000140)="b100050160000000ff01000007000000330002000000000000f96ecfc72fd3357ae320b37b673039d2d236acf20b7804be0600aa5b236de351e2f0139b672f4d335d223e7d026ba8af636aa9003728210200001b720fd38bfbb770c1f5a872c881eaee69e0bb76d907c400000000361b12e19ef6c8cd6d25c95aad79c76619f0ba57aea8c500002002fbff0c2300008abfba0900000008e371a3f8343794ab1e00"/177, 0xb1, 0x0, 0x0, 0x0)


r0 = socket$inet6(0x18, 0x2, 0x0)
ioctl$VMM_IOC_READREGS(r0, 0xc028756b, &(0x7f0000000000))


sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f0000000180)="fc", 0x1}], 0x1)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x84000000000000})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendmsg$unix(r0, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
getgroups(0x2, &(0x7f0000000180)=[0x0, 0x0])
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000280)={{0x3, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfff7}, 0x7, 0x6, 0x3})
sysctl$net_inet_tcp(0x0, 0x0, &(0x7f00000000c0)="d43243b79298270335c65ce195", 0x0, 0x0, 0x0)
r1 = kqueue()
ioctl$FIONBIO(r1, 0x8004667e, &(0x7f0000000000))
r2 = dup2(r0, r0)
socket(0x1, 0x5, 0x5)
r3 = socket(0x2, 0x1, 0x0)
setsockopt(r3, 0x6, 0x8, &(0x7f0000000140), 0x0)
ioctl$BIOCVERSION(0xffffffffffffffff, 0x40044271, 0x0)
setitimer(0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000300)="800f000000000000000000000024a8a4f4a4905fa2b0c36bc75c31ffa6f3d946bc4a42fd9917413164e9c129e0c6b0d923fe1764e82ed0404960d4260ffd05e4c54f52a1cbdae4f9b1b874875eee3f557feab57e188937bc22e1eb80bed6c05069bffd6179f2750e486b8f014cf47fd0023d2d19ed3231b382b8f07cd7df988abbdc4f13fb808ccb11fbfc1a9b522d46005d8f06b6b4187e2c72d17a5eaf359e9022dfb5676f50506eb5f51e0b44be12b75cdbe6e523362e740e1af9e846e8d74eede322ecbba599b11f545e3ac7b4a91ca17fc74719a72ce748d47cb96dffd16df7b4fa250fcc9fff00be69cdc2e3229f1e987ca23a0ea7707637c6f78f5871e7c1214f04693409d14700ad4826c1771041475840f408cd7933c2f4ba7a87f766337e31d82b9e754f818237a22b", 0x12e}], 0x1)
r4 = socket$inet(0x2, 0x2, 0x0)
r5 = socket$inet(0x2, 0x2, 0x0)
mknod(&(0x7f0000000540)='./file0\x00', 0x2000, 0x177d)
open$dir(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
setsockopt$inet_opts(r5, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
dup2(r5, r4)
setsockopt$inet_opts(r4, 0x0, 0x200000000000c, 0x0, 0x0)
ioctl$WSKBDIO_GETMAP(r2, 0x80047476, &(0x7f0000000100)={0x0, 0x0})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
getitimer(0x0, 0xfffffffffffffffe)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000440)={0x3, &(0x7f00000004c0)=[{0x14}, {0x2}, {0x6}]})
syz_emit_ethernet(0x126f, &(0x7f00000000c0)=ANY=[])


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000080)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendto$unix(r1, &(0x7f0000000300)="dda652a9dbede9bb1fe672e501afb8ea5aaace657657dbb8a5693b1bcef5985f1fe199002afea2da2b076467d543360e3b5355ead7240487c080b98b85428334deb2dae4974b032b225f5b93a5746c804918852b08d6803543f2dcecee0c657dd70b6e3dd66285149be2459167f3d507b965a9b588f20e151831e1237324cb4580264c90ffeb120711a1d13c80aab5734dbb3d9880b7cd254930f5e2458e4d2a942d0112cbb17de297be10c04549a81766f59c70ed9b6d04", 0xb8, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
recvfrom$unix(r0, &(0x7f0000000180)=""/183, 0xb7, 0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
r2 = semget$private(0x0, 0x3, 0x3c0)
semop(r2, &(0x7f00000003c0)=[{0x4, 0x3, 0x1000}, {0x0, 0xfff9, 0x1000}, {0x1, 0x102, 0x1800}, {0x1, 0x3, 0x800}, {0x0, 0x200, 0x1000}, {0x0, 0x8}, {0x2, 0xfff8}, {0x2, 0x7}, {0x4, 0x1, 0x1000}, {0x3, 0x7e7, 0x800}, {0x7, 0x81, 0x1000}], 0xb)


mknod(&(0x7f0000000000)='./bus\x00', 0x2000, 0x0)
r0 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000180)={0x0, 0x0, 0xe150, 0x0, "32cd8b6abdc8a5508471050000000010000407ff"})


recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f0000000100)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x4, 0x0, 0x0)
setreuid(0x0, 0xee01)
r0 = fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000080)="eaef125c00000000", 0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt$inet_opts(r1, 0x0, 0x9, &(0x7f0000000240)="ea000001", 0x4)
recvmsg(r0, &(0x7f0000000540)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x3)
r2 = semget$private(0x0, 0x2, 0x110)
openat$tty(0xffffffffffffff9c, &(0x7f00000000c0), 0x200, 0x0)
write(r0, &(0x7f0000001740)="6bcfa4b9881483a90b39b3d69b291d52febf872310aaa4a2e578b500e36c06a801b9a1b1b0b3f59f4d5c5ac74912174aba1cf8e255ba77ab172e180d8bb1244819f4cbd4b890f9f315b41d033489ac5c4ed4615f3ec975c8fc24c1bc448c343e1c19739fa2c68cbc0e21f289ffda3f998a9abacc2c720876300a6ecbceb1c58d8c7e7c5eb2ecc8721dc51f6cedaeeacce5b5ed4c899d1c7cfbafd9c4a60f9d5895f761f7b8b324b3da1c55fa5af4310804297391416570e18b94a3847d35995834ee06640fd366081b288c7516fe585f21d763a8775c3d50c4f9263d0eeb9ff64f99cdca2aa53b7f7e93fc53967a95ce6eb378bbe9626e39af4ef39aacf80f1401259138e04360ea5509d8927f26a95b449009ed1aa610a7e179a2f335bf32a97c742c32f4fd73d5258aa2d133eb3d16e72b7b610d3944f8f56de83615c34a486679dd0d57beb341f6aafd300c1b1d758f1137a0d309b0d3dd4b8bfbc16c7cab9826d4c1ee46845c44d8995b2ac3c83dd18172d29a39ebecfe3fe41c4a75d614b87f54d4cdf9cb23974af98c91a20cbc76c4805b59139819e2dc728571d19812e1594babf4bfe8a5029188eff1b8382c9ea0aeb6d76830ecdc19ce585905b63f45e8c90b510393279580a3c23287b3927e2384f7ff6d40b38ae2ce662f404556d71097c56ede95cbe17e6495749ccb2d15095d67f5c7f7aa3049b1948f60c00d8c82e3d688374e65f214c4320fae37fc3ce4f8c9197e1c0ffe13cb366a41dab2037bd9ffe88b6b6d97dbab48bb5c043199b918f67e3dffe6aadb890a8b7444398f9d3e0ae27c7f70d343dd465c505b464813b339cba541257dee3c6c572685894534cabfb457b2bc0c90222625dfbe7a6a204ae56c92e869d4fad87dc7316bc9f67333228690d8384859072d2e61bf9031b161a98e45a5e351b058853eb5eb25b0419939ec5307aeceffe0a60f1e2ee7e642b889746987e4cac34ecd7b25f754451140517d64253e0dcea3cd32989f41daffb5f67d5979c332044b7174f7144011fa8137e3c7df5d79aa4ebc141a0c2a0bc55c21638a5b917bba420aa411f461257601161a1a7ad1c785440c88c069c4360014253bf919daf995984167a9066ceb4248089d808637378a88e234c2a1fb896624515c25db2f67be18ba345a5353cb6784429bb9bd7e79a72f1f852143b2ec0858276d51b52ebfc7dd893e6b655d6bda4b937c2c8f962f5680bc920082ca194e22e465c4fe9435af8457e558893bee96523ee2df670df477cb0c68054853f572d4405ccb89cda6318f1cf078aa250a0ebfb96842869c8d4fe064a05c2b7b36e7e16d439c27e4f959fba2138bc9c60dbb04a7d0f9c5ccbc641f79904362c9d5b7e4db8a6850247ef1eaee4209ad58c02ed482f0497d110d2b90dc1481b38a059256db4a7ce1c23aeb2fbf8ead2ced84567050e04b305d2203aa33c3dd3e9302d32dd87f4b0756eb95dd9d123f00afad000b6628ce20ae5a9c58cbc81b3c8590703a4775dd33111a06f1b8227918790c212b9330f2f0bcaecc538d56ff88685d29ce79099364edc82b3bbf80452ed035d0dee05fbbb7a74383f9ec377668a14163a46412983b8ea9fb8cebfe6cb38545f34e0a6fd1329670e1f73fb4ea8922f4078dd07ce1c612e97d825780ad3fd7f0337db7bcdc3c5c108477eb6d4cbef239bd478a5ea968048acabb378b26e570af01a795c5f55834741b802081d20534e757a0713ab8629ac795e1e7aafc0d593c08d96b6b62a1997d851f1850029ade0922d863c8952dcfc265b1ce92ffa664cb9fcb422f522aafc11a923eddbc9412303de0e5ba682ffa2071d12559ba3183a54224aa3da58915248f631036b180dbae63f689c0a29152b2a60ecdc2dd5c4d8012a71d0f553bacbb68c206d22fa3243e68428f1d8b846c77f1d7f89f4b61addf5e40e99484652b730d37c47fe90a65d04af519d97896b03ddcc561963ee353e48a6b41e499d0721832ddc0ad9f683dec6a45ab2f4b019a54889b2c99073e558a784a28893a603fb9189c0778c35f2cdf495bea08720bfb23ed0db657d2a92acd8551c3b7ee40985a0a874d380df0ffbfd1e50c5ac38a8de3f87366780b0df3ca39968251a1c6571192a14aecf34f02cc11483636f43047cb0da21091fa28a4edc8db40a54e31ba1ea3ca512abd7add4bac0c0edf57362309bcbda5c9a783a2cd35e4b0de7f35ec5f40ea6269bc83063b891dae128dc907070f7da619e309410983e6e7d23db49f7e4383224e766761dfd6eef29af1177598ea2851b3fe1d287bafb923da4ee8a77022249ad5ddde63810c37bf349bda50c150aa4a038099b866dbb01ee8fa26f04d95a78e7dd2c373c31ed1e01f18aaea790aea003ac618745f18fd759d2008af66a816f22c21709b7f58f253bcee27286bf4d71d4da79395fcbe29baa6bf194e7f1cda452cbf74ea8d71ea635cf37cea93e7f585baec9336f30ddc55de8c5afa6fdb372750012d01fb580a136417b4afd493e921f82cca403649c80512725140cb43f90f5d50ed626134533aea0e53bb85dadb5577102e29def342d204378baa3f89dc3e78cedb6afa6ea71e69411afc814027955e7616c00f14f48911b427478c2627cda8b3c21363e1e6ae7cff0d76052f121522f5da3300ab191d44c4a0d9902a29060d48114e655b94748c0949081841477e55076084a5a5b77465bdb1ffe02461e1fb845b471b5d6570c17a4dd9975c626a6bd91f44856a3ce1355ac565533b10bd2fdeeb57dda1a71b00228c80a03da1b53d8dcf4ffabf4186d821199a35a3b95707570d63dff1d803333c70572a457e71840f125874f9b2cffc2c66951d71a8a325232a80a038b90ba1df27ae830a07d12f8f57b87a4581944dc4576ec8719b62e55758aa899234d1771d6e742ed9f950e2067abae7b2f80a292aa7aec60c2813636810eefbc4009c958fc56ea3b3f0554a85c2a6a391f0f8c02f982b8e228b1488ad79e2d1584b2b7e41fcf2552f37b9c8d157afdb3f228cfcaeba2c19d0813cd39cd226e00db9f8747ae8aa954dd0f2ad90ebdf84490c72f4c1f5a84902a3b03bd80d9c0dc354c9022fc5b80e5dca7bc505c565ca014437ae751acc1c1a7eb1e0d33aff1a745cd6d24dd05d507b8dc4bb4d06660697c58169e8c9fca2c5d877921cf0505b317f7522b272daebe0edbcd7a00f733f8f10c0fe592dbdecd2d3fb434883d57646dad2e7a717dfa00872e26a3d9789989dae562caa8e8e5799fc33f3a02ad6106c993d8275edc2639f8ee80979ec5468b34cda90916bee91091f260f56f1082bd11655fea6143a95bb92e200f79e03fbd71ade29ef8a3449dadb41567887befeaea4541074df6cbf7844834052eeaf2c995d5d9dcf81c8354e3e9409b533b9e42f7a0c9a506a3f06f426f94d02c6b01922dfbe3000252834728c49c188fbe64d2b6875b30ebd77e87097012652991cb0024c657e297751de362b732e87182847b1afc137bbec1ffc2e2fa0a6ba063baa3491a19a7326608879819a0dcc9b6bc19a0b518bb2f1e13eea442d7ef3a096f612a6e433d3b252ff4dc1e84033e82ad0a400d13a4b33c41a4f3c3ed5638c0840b228102cac0c6a1bb1c5a2c05594752b40b8ae79b92b2ecbf94f3ac0c2ef249552f3715e9c1023651cf7964016dccb4641b77f1701e89633107aa43521ae6602dea11282643b32ac3d5fb7052a773f3cb5e3bcbd509e0d3f51ab0ad0ae3001037f43f21968e2a7de5ada2adb98fd7741606ad57b0c44b0a12e9e209b846f1b6cdc3aa43741fe304c2e0889615df0c17519bf754ef66fc8db24c7d6ce842e9f773d2428a54b394c9a74841faf9f346a74fc2ecaa67a1bcc8116eff4448636f468693dac70f1e806f07d6b033d78e0e648642c061b831ebbae586c2e2bf9ab1fb5cd0dff12815a3ae4e19a7f068c8fae594adca813f88bc0afcac886ee0698b32b14dcae47551850df99001d110f62a77c9d89fa5dfc0a5ce6a87581efc7bb9b0cf0c2229742b5cdf4a470e157b1134b5614c81523d077fb0352d8ce364f891c5b5601b5d945bfd568060bbeecb8f724addcb088ba9943dc3a1e1fc9f59db410dcea0c0f664bdff6a73b849fabfa84406e9cbcc567062b46476c43e4a3c8ed662a8e3afb66e6fad5bac154ae778c8d9bed8232384a4c7c93ecdf1109800061ec988ff7e965d82ab9a2b6651e4e56422d4d1c92349d85b8f9c4dff8c5729d4f6103d259cc992842501bbfabf9a978401b23e376d8fcda31eefb1676b9050329fa0928225c0740ab522e3aa22eb726dff94b1d43c00dd0f843ab7be3c1d19fa840b1a5b05ad18a4a6af6db3ef70e072fdf64dbd5136a3475147f0e3aa6d7184b0cdb0e3e246e835d92d66743834d8a327d3517424ed48923f4b738d1efd4f7470a5efcf9fbe9d6227649c53b19021e7a5ac15b273c010d0ad925a545e02179c137d7d5ecdc35c6045e8dffc1e01f8912df51959985c8917aabeff67645629a1f1a93610d1b61772a90623e0283fa809433a7e10e52fc4f7d2de634658acf25f28f798e95b49c867e29d04c961634f83f9da17b4cb53a04e6690a4ec135cc7e5846ac900eac9d802d96549f09d35e701491c16da7d4d8ddd9e47fb9e0467d1993acf85d87ad1afa0b7d1d049fd816f5c49f13c99e705276088776f61170b2e6c657366f45e90c471d93b8309b926106091d3cdf6f56d5ed56cb81e6cf837d45fb9748a1874504523a6591eb12771fb8ff947007155aa78c3f0beb42966f7df9aae84b431755d02fc407d552b7d87b64a6a0543aa40cf37596d241114c291f9ad2a66e9d0a6e91195de97226c256f083203ed460d04ad93f23ea070380b0a7db251ed013b831c77e5f6e4f60d8cdf675e5762f5b7631ebd8732de33a0d39d3849cef89a997e897bb25e634f1f35143c64a9f6c2a164f4de062b848f0168bb4e8091c87ad8bb20119fa8ea58fed6c3051bfc6e2695675b3c8c674039783ac9c4bd63f20fc690ebbd3b393a5d46857d30bb4802e2a96d1f9968df85c2e0d20d877e15d2e0bb203497d2fab3edb1560c7f5131373c9a4e26ec540e272b0f50e2fb1670df096ab097f173d718b2cdf79fbbe601f7abe7a83203541367b08a4177a49b208bc93641c9a53de6e468d714e965cf2f5058f032525c9727083b813897824a45845059576963ee08dae7f085a314e79368144b074a2062dddf7accd9a6f3c90fb4d13843ecd36d2f9524a86ce3bda595a3612628dbaeb7216a62150adc53d7f4372285760070e4fbcf21f540f584dde5d4bb1e698f5a1944a8b79d214ca04fe217559064c16523fefb809d03515c6c75ab2203253447bc4ea841bd44f07506c5327f084b7eddd5928b3061a7e2d307e7e212e4e655e390199c80a5f377cc59a2e0fc4de335777c05e44f3454219181582d97ac0ec082fe739fa0011e2df203bc0a4827641639b5b94817b84537e4442287b986b84e758fbbd2b6b735d928f6a587d016c947d2bb35e3b1be1bb0d3fe8c6d25b04b792a3da556458fe23345cb429654b78106c435c2aa01e4b758f8142e137b55b6b63ed0961737e02869f2ce6c2d8088ab5c7dd6cbfc80923ec526ed00103636d2ccb0c42bd3ce8b904c8e6c2a59d4e6732bc7ff348695ef9cb116bddd47e17354ad59ee191ce3f4973aa2af34dfa552077b2538a07704ed0c397eb43d28245a3e08c393c46f239ba78113ae5986e6a52fad2a3ea134b5de8cac5edc69bae9e217090600b3d63c13fee02c92008", 0x1000)
semctl$GETPID(r2, 0x3, 0x4, &(0x7f0000000040)=""/40)
semctl$GETALL(r2, 0x0, 0x6, &(0x7f0000003780)=""/4116)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
setuid(0xee01)
ioctl$WSDISPLAYIO_USEFONT(r0, 0x80585750, 0xffffffffffffffff)
recvfrom$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
minherit(&(0x7f0000ffc000/0x4000)=nil, 0x4000, 0x3)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}})
r3 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r3, 0xffff, 0x1000, &(0x7f0000000000)=0x1, 0x4)
bind$unix(r3, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x30}})
r4 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x1000, &(0x7f0000000000)=0x1, 0x4)
bind$unix(r4, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b10005040000000000000000071000001a5113fecea10500fef96ecfc72fd3357a89583535613ab4cb56355df50b7804be38164991f7c8cf7a4f2b297be1aa5b22abeb51e2f0ac3ebbc2feb3fda1139b672f4d3353eb067e7335a079d7080000000000000000008904000000000022830cf4571bed66f4007fccdcf3e4999d9d20002002c5dbfad800000008e371a3", 0x8f, 0x0, 0x0, 0x0)


shmat(0x0, &(0x7f0000ffc000/0x4000)=nil, 0x0)
mlock(&(0x7f0000ffd000/0x1000)=nil, 0x1000)
r0 = shmget$private(0x0, 0x1000, 0x0, &(0x7f0000ffd000/0x1000)=nil)
munmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000)
shmctl$IPC_RMID(r0, 0x0)
munlock(&(0x7f0000ffb000/0x4000)=nil, 0x4000)
shmat(r0, &(0x7f0000ffd000/0x3000)=nil, 0x0)
shmget$private(0x0, 0x4000, 0x0, &(0x7f0000ffa000/0x4000)=nil)
madvise(&(0x7f0000ff8000/0x2000)=nil, 0x2000, 0x1)
shmget$private(0x0, 0x4000, 0x0, &(0x7f0000ffc000/0x4000)=nil)
shmctl$SHM_LOCK(0x0, 0x3)
munmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000)
shmctl$IPC_RMID(0x0, 0x0)
mlock(&(0x7f0000ffc000/0x3000)=nil, 0x3000)
shmctl$IPC_STAT(0x0, 0x2, 0x0)
madvise(&(0x7f0000ff9000/0x4000)=nil, 0x4000, 0x0)
shmat(0x0, &(0x7f0000ffc000/0x4000)=nil, 0x0)
r1 = socket(0x11, 0x3, 0x0)
sendto$unix(r1, &(0x7f00000000c0)="b1000501600000903f00000009000000331c1306cfa10500fef96ecfc73fd3357ae36caa0416fa4f376b36acf00b7804be381e4991f7c8cf5f882b297be1aa5323edeb51e2f0ca3ebbc257699a1f133ea7acb5d602000d7d026ba8af6300372a2102000000720fd38bfbb770c1f5a8aec881ea772ec5890400000000000000361b1257aea8c500002012000000042000000000000000000000000000002000"/177, 0xb1, 0x0, 0x0, 0x0)
mmap(&(0x7f0000ffa000/0x2000)=nil, 0x2000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
shmctl$IPC_STAT(0x0, 0x2, 0x0)
msync(&(0x7f0000ffd000/0x1000)=nil, 0x1000, 0x1)
minherit(&(0x7f0000ff8000/0x4000)=nil, 0x4000, 0x0)
socket$inet6(0x18, 0x0, 0x14)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000001080), 0xc)


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
fsync(0xffffffffffffffff)
open(0x0, 0x75f493fec6515f78, 0x1a0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x8981, 0x0)
getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000440)={0x4, 0x18, 0x6, 0x9}, 0x4, &(0x7f0000000480)="9b0209c3218b07fcfe4189c99e805e6e84d356960798a692992117d6728436ba1bd87f42e3303eac3846528d050712f838130efce33f523ba44765f5f6915b2227390ed95bd9dc6d4dc7f149d4d6d06a3f23616e773302d9cae75e39a5a11e32e0e6ebd635450b2eba540af7f2aa5dbfbdd900a0dad2b74f50acd76b5c567049ef436dbea0d7562f52955af8d4ab84c513252ddd139b5f5cd5c2bd02adc7f1fe850c00000000000000062ab475cca257352828a76e5334be562995e894238b96ca5d4d3e670fa0cc791dfc4415030910fa64eac9b4e8aa9bef19525cb6f7e8570be65bb7ad3fe963cb9a8bd949ee334db1ccf73db06b5947b3e88aa810f8ed7cca10ff0d0000000000001345daa49507756f49775275ca390b94e85d5a95b82000b9429c25483a9275d0da3b561c6adc3c141f26040000006b436218bdbdc9ac0a623855e941dc1872fcb045e0d9df1ecc6357ee21e2b0802cb60edd0300723235f06715e7eecc3e0760c70e1dd7873e27142bbae1a7e44de453a073fe3426f334b80f043ba9136d57c799353d46dd81439b111a511a288bee5dfb2e353e3bb073e3342273216b07e49ca4df0fd2dbe9a8eb377010ee678aad0bd8c7fb7d82693a096344671843a1f2082612b2ff237c6e505ff5f5ba932954d73c630fd2791f833a1da5af0704f687e196f4f7859e071fc98111cc9024f790ce16ceaa427d0104e39789d91000"/528, &(0x7f0000000a40)=0x210, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000001080)=[{0xc0}, {0x50}, {0xfffe}]})
syz_emit_ethernet(0xe, &(0x7f0000001100)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000000)=[{0x40}, {0x28}, {0x6, 0x0, 0x0, 0xfffffffd}]})
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000080)="35b5c242413c1026089a59583cc3", 0xe}], 0x1)


setrlimit(0x8, &(0x7f0000000980)={0xb, 0x54})
r0 = syz_open_pts()
close(r0)
sysctl$hw(&(0x7f00000000c0)={0x7, 0xf}, 0x2, 0x0, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_WRITEREGS(0xffffffffffffffff, 0x8020560a, &(0x7f0000000040)={0x1, 0x0, 0x3, {[0x3], [], [], [0xfffffffffffffffc]}})
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x37a, 0xff, 0xffffffff, 0x9, "6c2b90f62f6e624e000000240000002000"})
sysctl$vm(&(0x7f0000000000)={0x2, 0x7}, 0x2, &(0x7f0000000040), 0x0, &(0x7f0000000180)="23e6139a508b7f724d62714ff6fb6c2783cf45eb14c32a85e3d84a7c70b13a2f7bbf5b76f377c6a9bb30d39e0432b05a622e36f345f2ccb09abc5cf10597aff54e33d96a41aaef646b61bde30bb91cee92333c1a7aff29a1de43acd037f9c598f78bf9edb6ecbe580902fb68305a5f187a8cb73656f84d378cd03d954da126c3d3e22e6a1012dc62334979aa0817147ca1aacbe53cd9deaefcf0bf21a3f2cfc746aef3870e02d997be0a8eb4bce82eae87db94541069d320defff192c928", 0xbe)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x0, 0x0})
socket(0x0, 0x2, 0x0)
nanosleep(&(0x7f0000000480)={0x13}, &(0x7f00000009c0))
open(0x0, 0x103, 0xa9)
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r2 = dup(0xffffffffffffffff)
ioctl$BIOCSBLEN(r2, 0xc0044266, 0x0)
r3 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$WSMOUSEIO_GTYPE(r3, 0x40045720, &(0x7f0000000080))
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
madvise(&(0x7f0000000000/0x4000)=nil, 0x0, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
write(r4, &(0x7f0000000a40)="7696e5f7ff008c0400df4ae7d9ca4a00a9cbcfa76e0d8a231e949999941e6173fc4c46b925143ea620003052a27ef49baa1e908432d1b357a276673c378e1145", 0x40)
syz_emit_ethernet(0x4f, &(0x7f0000000400)=ANY=[])
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f0000000100)={0x10, 0x0, [{&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000af2000/0xf000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {&(0x7f00008e3000/0x4000)=nil, &(0x7f0000f52000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000826000/0x1000)=nil}, {&(0x7f00005f5000/0x4000)=nil, &(0x7f000093c000/0x2000)=nil}, {&(0x7f0000da9000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000e0a000/0x2000)=nil, &(0x7f0000648000/0x2000)=nil}, {&(0x7f0000b64000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f000062b000/0xf000)=nil, &(0x7f00004df000/0x4000)=nil}, {&(0x7f00004e0000/0x4000)=nil, &(0x7f0000000000/0x1000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000b04000/0x3000)=nil}, {&(0x7f0000ecf000/0x3000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f000064c000/0x2000)=nil, &(0x7f0000c2c000/0x2000)=nil}, {&(0x7f0000c2a000/0x2000)=nil, &(0x7f0000518000/0x3000)=nil}], './file0\x00'})
r5 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r5, 0xc028698d, &(0x7f00000001c0))


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x6381)
r0 = open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
ioctl$FIONREAD(r0, 0x4004667f, &(0x7f0000000040))


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000080)={0x27ffb, 0x0, 0x81, 0x5773c545, "944c8f62b57be2df6707049c8bda98612c2100"})
writev(r0, &(0x7f0000000580)=[{&(0x7f0000000140)="b868b4e47ff0e57fb99bf049535c0a063153f6e2e3d7860f948f2bcfe59a04cb9f96ab8960e4f272127f555ca8", 0x2d}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
r1 = dup(r0)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000040)=[{0x7c}, {0x4}, {0x16}]})
syz_emit_ethernet(0x6e, &(0x7f00000001c0)=ANY=[])


r0 = socket(0x11, 0x3, 0x0)
r1 = socket(0x11, 0x3, 0x0)
setsockopt(r1, 0x11, 0x3, &(0x7f0000000000)="03000000", 0x4)
setsockopt(r1, 0x11, 0x1, &(0x7f0000000200)="12000001", 0x4)
sendto$unix(r0, &(0x7f0000000280)="b100050400000400000000000101000000000000cea10500fef96ec0c72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b1257aea8c500002002fbfe0c2300008abfba0900000008e371a3f8343732051eeab71d89e0000405f8ffffff13000000", 0xb1, 0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x9})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000880)={0x0, 0x10001, 0x1ff, 0xd2c, "8717f905070000b29b5c0300c9abbc0d51aa8000"})
writev(r0, &(0x7f0000000240)=[{&(0x7f0000000080)='\r', 0x1}], 0x1)


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
setuid(0xffffffffffffffff)
r0 = geteuid()
chown(&(0x7f0000000340)='./file0\x00', r0, 0xffffffffffffffff)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
setsockopt$sock_timeval(r0, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x100008}, 0x10)


readv(0xffffffffffffff9c, &(0x7f0000001280)=[{0x0}, {0x0}], 0x2)
r0 = open$dir(&(0x7f0000001340)='./file0\x00', 0x8, 0x137)
renameat(0xffffffffffffffff, &(0x7f0000001300)='./file0\x00', r0, &(0x7f0000001380)='./file0\x00')
r1 = openat$tty(0xffffffffffffff9c, &(0x7f00000013c0), 0x80, 0x0)
ioctl$TIOCSWINSZ(r1, 0x80087467, &(0x7f0000001400)={0x80, 0xa98e, 0x4})
ioctl$FIONBIO(r0, 0x8004667e, &(0x7f0000001440)=0x1)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000001480)={<r2=>0x0}, &(0x7f00000014c0)=0xc)
getpgid(r2)
getuid()
openat$bpf(0xffffffffffffff9c, &(0x7f0000001500), 0x80, 0x0)
ioctl$TIOCOUTQ(r1, 0x40047473, &(0x7f0000001540)=0x4)
r3 = accept$inet(0xffffffffffffff9c, &(0x7f0000001580), 0x0)
fcntl$getflags(0xffffffffffffffff, 0x1)
r4 = semget(0x2, 0x4, 0x200)
semctl$GETVAL(r4, 0x3, 0x5, &(0x7f0000001600)=""/109)
connect$inet(r3, &(0x7f0000001680)={0x2, 0x0}, 0xc)
recvfrom(r3, &(0x7f00000016c0)=""/171, 0xab, 0x1843, &(0x7f0000001780)=@in={0x2, 0x0}, 0xc)
getegid()
mprotect(&(0x7f0000ffc000/0x1000)=nil, 0x1000, 0x1)
pipe2(&(0x7f00000017c0)={<r5=>0xffffffffffffffff, <r6=>0xffffffffffffffff}, 0x10000)
ioctl$WSKBDIO_GETDEFAULTBELL(r5, 0x40105706, &(0x7f0000001800))
ioctl$VMM_IOC_RESETCPU(r6, 0x82405605, &(0x7f0000001840)={0x0, 0x100, {[0x2, 0x401, 0x3, 0xa9, 0xffffffffffffff6d, 0x1, 0x9, 0x7, 0x1, 0x3ff, 0x7, 0x4, 0x80000000000000, 0x9, 0x0, 0x0, 0x3, 0x7ff], [0x7, 0x2, 0x9, 0x4, 0x1, 0x9, 0x7fffffff, 0x1000, 0x5, 0x4], [0x9, 0x6147, 0x8, 0xffffffffffffffff, 0x8, 0x8, 0x9], [0x5, 0x8, 0x4, 0x9, 0x7, 0x10000], [{0x8, 0x9, 0x401, 0x2}, {0x80, 0xec11, 0x7ff, 0x1f}, {0x6, 0x1, 0xe950, 0x7}, {0x77, 0x6, 0x4, 0x7fffffff}, {0x1, 0x4, 0x401, 0x7ff}, {0x9, 0x7, 0x6, 0x80000000}, {0x5b, 0x3f12, 0xe14, 0x9}, {0x7, 0x52, 0x6, 0xc}], {0x800, 0x7f, 0x5, 0x3}, {0x401, 0x0, 0x1, 0x101}}})
openat$vnd(0xffffffffffffff9c, &(0x7f00000044c0), 0x2, 0x0)
semctl$GETALL(r4, 0x0, 0x6, &(0x7f0000004500)=""/143)


r0 = syz_open_pts()
syz_open_pts()
syz_open_pts()
fcntl$getown(r0, 0x5)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x1, &(0x7f0000000000)=[{}]})
ioctl$VMM_IOC_INFO(r1, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r0, 0xc2485607, &(0x7f0000000300)={0x2, 0x0, 0xd0, 0x0, 0x0})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x1c}, {0x34, 0x0, 0x0, 0x800008}, {0xa186, 0x0, 0x83, 0x2}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = socket(0x18, 0x1, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000140)=[{0x4, 0x3}, {0x5c}, {0x81ae, 0x0, 0x0, 0x80000000}]})
syz_emit_ethernet(0x2e, &(0x7f0000000340)=ANY=[@ANYRESDEC])
listen(r0, 0x0)
accept$unix(r0, 0x0, 0x0)
shutdown(r0, 0x2)
setrlimit(0x8, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd02)
r2 = open(&(0x7f0000000240)='./bus\x00', 0x0, 0x0)
pread(r2, &(0x7f0000000040)="3cd15db7c30016", 0x50cc00, 0x0)
madvise(&(0x7f000023d000/0x3000)=nil, 0x3000, 0x0)
sysctl$hw(&(0x7f0000000000)={0x6, 0xb}, 0x2, &(0x7f0000000140), 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000000), 0x0, 0x0, 0x0, 0x0)
r3 = socket(0x0, 0x0, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
sysctl$hw(0x0, 0x0, 0x0, &(0x7f0000000700), &(0x7f0000000740)="d1f839ac5cf19fd04dba6c0dbf68ca1fdf288b359001bb5dbb35a6c00bb1eb0c894854fdfb43fceb8a956ece264f96", 0x2f)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
setsockopt$inet6_MRT6_ADD_MFC(0xffffffffffffffff, 0x29, 0x68, &(0x7f0000000080)={{0x18, 0x1, 0x8, 0x7fffffff}, {0x18, 0x2, 0x6, 0x200}, 0x8, [0x8, 0x80, 0x0, 0x4, 0x60, 0x10000, 0xffff7cc0, 0x5]}, 0x3c)
writev(r3, &(0x7f0000000200)=[{0x0}], 0x1)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000780)={0x1, 0x9}, 0x2, &(0x7f00000007c0)="22c4d67167902fb46fcbb7c2aa129cc43f1bdb46166de147841b5ba81acac4bb59a7199b47d6de0e9317a83156f27193ece874749f58d8dff0d8f29c94eef52a1b275b088e84ba5b1816036f88fac0dc6489e2459ffec710a84a534eeafa7a426b430a337355e5e05d59aed39da5b8012ae07b196ed7", &(0x7f0000000840)=0x76, &(0x7f0000000880)="c409e8d66e1427ea932c3e1b0b5d197634a0ca118e56e1", 0x17)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
r4 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
getsockopt(r4, 0x0, 0x9, 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x50}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)


mknod(&(0x7f0000000000)='./file0\x00', 0x6000, 0xe02)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
setreuid(0xee00, 0x0)
r1 = getuid()
setreuid(0x0, r1)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x0, 0x10, r0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x10, &(0x7f0000000300), &(0x7f0000000100)=0x4)
setsockopt$sock_int(r1, 0xffff, 0x1, &(0x7f0000000180), 0x4)
sendto$unix(0xffffffffffffffff, &(0x7f00000010c0)="3568ad18e51361c69a4281aba9910005c2dc27832e30bb72d2d5ee107b209cec51de9f1cb5c7afff91d1030a6a5d44ab6a0862776fded5b81a70e927af39b288355d5fa2e4a8e4aaed6e6da614c45ac7cca88d10a567dac9a6d58fc5145a25da4ca4743d00403ddf9ff1eb5d8d070000005bee7620e9726953e4208477f5571712b5e198334294fb9a816ea1873d6f4e", 0x90, 0x4, 0x0, 0x0)
fcntl$setstatus(r1, 0x4, 0x80)
link(&(0x7f00000002c0)='./file0\x00', 0x0)
r2 = openat(0xffffffffffffff9c, &(0x7f0000000780)='./file0\x00', 0x1, 0x6)
readlinkat(r2, &(0x7f00000007c0)='./file0\x00', &(0x7f0000000800)=""/219, 0xdb)
r3 = semget(0x2, 0x1, 0x240)
semop(r3, &(0x7f0000000940)=[{0x1, 0x24}, {0x3, 0x0, 0x1800}, {0x3, 0x7, 0x800}, {0x4, 0x3ff}, {0x0, 0x818, 0x800}, {0x0, 0x7ff}, {0x1, 0x7, 0x800}, {0x2, 0x6, 0x800}, {0x1, 0x1}], 0x9)


r0 = socket(0x2, 0x4001, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000100)={0x1, &(0x7f00000001c0)=[{0x80}]})
r2 = dup(r0)
r3 = fcntl$dupfd(r2, 0x2, 0xffffffffffffffff)
close(r3)
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000100)={0x2, &(0x7f0000000080)=[{}, {0x5}]})
sysctl$kern(&(0x7f0000000080)={0x1, 0x31}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)
r4 = socket(0x2, 0x2, 0x0)
dup2(r2, r3)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
connect$unix(r4, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r3, 0xffff, 0x1023, 0x0, 0x0)
recvfrom$unix(r3, 0x0, 0x0, 0x0, 0x0, 0x0)


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000040)=[{{}, 0x0, 0x1}], 0x0, 0x0, 0x0, 0x0)
ioctl$FIONREAD(r0, 0xc0106978, &(0x7f0000000040))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000080)=[{}, {0xc0}, {0x8006}]})
rename(0x0, 0x0)
rename(0x0, 0x0)
rename(0x0, 0x0)
syz_emit_ethernet(0x1db, &(0x7f0000000180)=ANY=[])


syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000), 0x10)
r1 = dup(r0)
listen(r1, 0x0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
r3 = socket(0x2, 0x1, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)
r4 = dup(r3)
sendto$inet(r4, &(0x7f0000000240)="03c0", 0x2, 0x0, 0x0, 0x0)
write(r3, &(0x7f0000000040)="04", 0xff9a)
setsockopt$sock_int(r2, 0xffff, 0x1023, &(0x7f0000000080), 0x4)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
writev(r0, &(0x7f00000002c0)=[{&(0x7f00000004c0)='L', 0x1}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x87}, {0x84}, {0x106}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg$unix(r1, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="28000000ffff000001"], 0x28}, 0x0)
recvmsg(r0, &(0x7f0000000780)={0x0, 0x0, &(0x7f0000000340)=[{&(0x7f0000000300)=""/8, 0x8}], 0x1, 0x0}, 0x42)
recvmsg(r0, &(0x7f0000000740)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x18c2)


mknod(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$unix(0x1, 0x2, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x20, &(0x7f0000000200), &(0x7f0000000000)=0x4)


kevent(0xffffffffffffffff, &(0x7f0000000000)=[{{}, 0xfffffffffffffff9, 0x19}], 0x0, 0x0, 0x0, 0x0)
r0 = kqueue()
kevent(0xffffffffffffffff, &(0x7f0000000180)=[{{}, 0xfffffffffffffff9, 0x5, 0x10}], 0x0, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f00000000c0)=[{{r0}, 0xffffffffffffffff, 0xc1}], 0x0, 0x0)
kevent(r0, &(0x7f0000000000), 0x3ff, 0x0, 0x8000800, 0x0)


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x4, 0x1100, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r0, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f0000000140), 0xe4a, 0x0, 0xa9fa, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
seteuid(0xffffffffffffffff)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
socket(0x18, 0x2, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f00000002c0)=""/50, 0x32}], 0x1)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1800000029"], 0x3e}, 0x0)
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f000050c000/0x2000)=nil}, {0x0, &(0x7f0000ffb000/0x3000)=nil, 0x1000000}, {0x0, &(0x7f0000158000/0x3000)=nil}, {&(0x7f000003d000/0x1000)=nil, &(0x7f000064e000/0x4000)=nil}, {&(0x7f00007eb000/0x3000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000157000/0x1000)=nil}, {0x0, &(0x7f00001eb000/0x2000)=nil}, {0x0, &(0x7f0000770000/0x1000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f00000e0000/0x1000)=nil, &(0x7f000026f000/0x3000)=nil}, {&(0x7f000050a000/0x3000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f00000f8000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffe000/0x2000)=nil}], './file0\x00'})
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r0 = socket(0x2, 0x4001, 0x0)
dup(r0)
sysctl$kern(&(0x7f0000000240)={0x1, 0x32}, 0x2, &(0x7f0000000280)="1a44c592", &(0x7f0000000380)=0x4, &(0x7f00000003c0)="27cb6cbf", 0x4)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x41, 0x0)
r1 = syz_open_pts()
syz_open_pts()
syz_emit_ethernet(0x3e, &(0x7f0000000000)=ANY=[@ANYBLOB="aaaaaaaaaabb00000000000086dd"])
ioctl$TIOCNXCL(r1, 0x2000740e)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x2, 0x2, 0x0)
connect$unix(r2, &(0x7f0000000000), 0x10)
sendto$inet(r2, 0x0, 0x0, 0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r0, &(0x7f0000000080)=[{&(0x7f00000005c0)="fb", 0x1}], 0x1)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000400)={0x0, 0x0, 0x0, 0x0, "29ae7c918d93aad129db69f2fbe9adcf0071cbfe"})
readv(r1, &(0x7f0000000a80)=[{&(0x7f0000000440)=""/86, 0xffbf}], 0x1)


open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000401})
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r1, 0x9, &(0x7f0000000280)={0x0, 0x0, 0x0, 0x1000301010006})


sendmsg$unix(0xffffffffffffffff, &(0x7f00000008c0)={0x0, 0x0, &(0x7f0000000540)=[{&(0x7f0000000040)="d7f7130955acdf6b18020261d7143e4a4b91765a8788cbbfdb2fd3cf01ea5b294c064c4a3ae46170779cae043eeed8505a67ebe4318cbfe5063eb77542639ee469677b035f6e514eb6b954bef74fc7f2", 0x50}], 0x1, 0x0, 0xd0}, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x44}, 0x4000000000000004, 0x0, 0x0, 0x0, 0x0)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$inet(0x2, 0x8003, 0x0)
setsockopt(r0, 0x0, 0x7, &(0x7f0000000340)="15337ac0", 0x4)


open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
flock(r0, 0x1)
r1 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
fcntl$lock(r1, 0x7, &(0x7f0000000100)={0x0, 0x0, 0x420a72db})


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x33}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x10, 0x0, 0x37)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x0, 0xff6cae7, 0x1, 0xfffffffc, "1a118c37510a9c4fa879000000fffffffffff700"})
writev(r0, &(0x7f00000003c0)=[{&(0x7f0000000380)="d62a752c883a0802006203000000000000002e0917da3c", 0x17}, {&(0x7f0000000740)="473f6f7a0054aa8ee4b485989b32a6de716e45a78e61606d7819ff90688ad6344eff00bf60f2fe4ec925668c1e16bda2826891a37efcdbe745c8822604060520009a76d50efc1e9148bc6e14c066650e6d32665120c6a8ed89e6261fa7e1990448fc4eec134e5d8c652a2282c72eb295fba8256976b949ce2242ec94165178d333e858f466e0edf8a9843900ecb40279aa8b567a377e75bea514b8", 0xfde4}], 0x2)
writev(r0, &(0x7f0000000800)=[{&(0x7f0000000040)="abe164e934a68e6d1510e7fa389869fb162b157d865ec39cc3733506517595f954083bab10f912ce8df4bb32e95b218bcc678c570cd2d4230e643de6aa40bae4ff9c48f78479f294916e81a25b302a81df4dd06d00a07c7a0a", 0x59}], 0x1)


ioctl$FIOASYNC(0xffffffffffffffff, 0x80047466, 0x0)
ioctl$TIOCSBRK(0xffffffffffffffff, 0x2000747b)
poll(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000132000/0x3000)=nil, &(0x7f00000a0000/0x1000)=nil, 0xc0400000}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f0000065000/0x2000)=nil, &(0x7f0000093000/0x1000)=nil}, {&(0x7f00001f0000/0x1000)=nil, &(0x7f000008a000/0x3000)=nil, 0x4}, {&(0x7f000008f000/0x3000)=nil, &(0x7f000002c000/0x3000)=nil}, {&(0x7f000008a000/0x4000)=nil, &(0x7f000002d000/0x2000)=nil}, {&(0x7f0000087000/0x4000)=nil, &(0x7f000002a000/0x3000)=nil}, {&(0x7f000008d000/0x4000)=nil, &(0x7f0000132000/0x3000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000001000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000132000/0x1000)=nil}, {&(0x7f000002e000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000087000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f000008a000/0x2000)=nil, &(0x7f0000092000/0x3000)=nil}], './file0\x00'})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000800), 0x0, 0x0)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r1 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmat(r1, &(0x7f0000001000/0x3000)=nil, 0x0)
ioctl$VMM_IOC_RUN(r0, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0})


open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
r0 = socket(0x18, 0x1, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
open$dir(&(0x7f0000001700)='./file0\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
recvmsg(r3, &(0x7f0000000340)={0x0, 0x0, 0x0, 0x0, &(0x7f00000024c0)=""/236, 0xec}, 0x0)
chroot(&(0x7f0000000740)='.\x00')
sendmsg(r2, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000001c0)=[{0x6c}, {0x4c}, {0x810e}]})
r1 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSDISPLAYIO_USEFONT(r1, 0x80585750, &(0x7f0000000340)={'./file0\x00', 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x5ddad896, 0x1ff})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x2, &(0x7f0000000000)=[{0x6c}, {0x16}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f0000000080)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000300)={0x3, &(0x7f0000000080)=[{0x14}, {0x87}, {0x6}]})
syz_emit_ethernet(0x26, &(0x7f0000000280)=ANY=[])


ioctl$TIOCSTSTAMP(0xffffffffffffff9c, 0x8008745a, &(0x7f0000000140)={0xfffffff9, 0x2})
kqueue()
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x0)
open(0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x7, 0x0, 0xffffffffffffffff})
socket$unix(0x1, 0x5, 0x0)
getsockopt(0xffffffffffffffff, 0x11, 0x2, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0x2, 0x7}, 0x2, 0x0, 0x0, 0xffffffffffffffff, 0x4)
r1 = socket(0x18, 0x0, 0x0)
ioctl$FIOASYNC(r1, 0x8004667d, &(0x7f0000000000)=0x8)
connect$unix(r1, 0x0, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, 0x0)
getpid()
fcntl$getown(0xffffffffffffffff, 0x5)
setpgid(0x0, 0x0)
getegid()
r3 = msgget$private(0x0, 0x0)
socket(0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
setreuid(0xee00, 0x0)
r4 = getuid()
setreuid(0xee00, r4)
msgctl$IPC_SET(r3, 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000380)=[{0x3d}, {0x28}, {0x406}]})
syz_emit_ethernet(0x138, &(0x7f0000000500)=ANY=[])


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xffffffffffffffff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x1, &(0x7f0000000300)=[{}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x1, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0x2a, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f00000002c0)=[{0xb1}, {0x40}, {0x812e}]})
syz_emit_ethernet(0x3e, &(0x7f0000000080)=ANY=[])


writev(0xffffffffffffffff, &(0x7f0000000180)=[{&(0x7f0000000000)="9da8e3e9ed", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x2, 0x0)
bind(r0, &(0x7f0000000000), 0x10)
connect$unix(r0, &(0x7f0000000000), 0x10)
writev(r0, &(0x7f00000003c0)=[{0x0}], 0x1)


chdir(0x0)
mknod(0x0, 0x1ffa, 0x0)
r0 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000240)='./file0\x00', 0x0, 0x0)
setreuid(0x0, 0xee01)
poll(&(0x7f00000002c0)=[{}, {}], 0x2, 0x7fff)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x10, r0, 0x0)
execve(0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, &(0x7f0000000100)="82f91e3471ac0058bc5a91501d400000005f84cf6fd2dc448a", &(0x7f0000000000)=0x19, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = getuid()
setreuid(0x0, r1)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9}, 0x0, 0x5})
setreuid(0x0, 0x0)
socket(0x0, 0x0, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
shmctl$IPC_SET(0x0, 0x1, &(0x7f0000000000)={{0xffffffff, 0x0, 0x0, 0xffffffffffffffff}, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0xfffffffffffffffe})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
setsockopt$inet6_MRT6_ADD_MFC(0xffffffffffffffff, 0x29, 0x25, 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
r0 = msgget$private(0x0, 0x0)
msgsnd(r0, &(0x7f00000000c0)=ANY=[@ANYRES32], 0x1f, 0x800)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
setsockopt$inet6_MRT6_DEL_MFC(0xffffffffffffffff, 0x29, 0x69, &(0x7f0000000240)={{0x18, 0x1, 0x6, 0x2}, {0x18, 0x1, 0x4, 0x7ff}, 0x3f, [0x0, 0x0, 0x0, 0x0, 0x823, 0x0, 0x1, 0x7fff]}, 0x3c)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x55421451)
open(0x0, 0x0, 0x0)
getpgrp()
fcntl$setown(0xffffffffffffffff, 0x6, 0x0)
sysctl$kern(&(0x7f0000001200)={0x1, 0x9}, 0x2, &(0x7f0000000440)="06a3f7b9", &(0x7f00000001c0)=0x4, &(0x7f0000001340)="fa6b2e39", 0x4)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000158000/0x3000)=nil}, {&(0x7f000003d000/0x1000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f00000c3000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000157000/0x1000)=nil}, {0x0, &(0x7f00001eb000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f00000e0000/0x1000)=nil, &(0x7f00000d8000/0x3000)=nil}, {&(0x7f00000ca000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f00000f8000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r0, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0xa})
minherit(&(0x7f0000149000/0x4000)=nil, 0x4000, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000080)=[{0x5}, {0x20}, {0xe}]})
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0x9, &(0x7f0000000140)="03000000", 0x4)
r2 = dup(r1)
setsockopt(r2, 0x1000000000029, 0xb, &(0x7f0000000280), 0x0)
pipe(&(0x7f00000001c0)={<r3=>0xffffffffffffffff})
close(0xffffffffffffffff)
recvmsg(r3, &(0x7f0000000600)={0x0, 0x0, &(0x7f0000000540)=[{&(0x7f0000000280)=""/50, 0x32}, {&(0x7f00000002c0)=""/49, 0x31}, {&(0x7f0000000300)=""/224, 0xe0}, {&(0x7f0000000400)=""/127, 0x7f}, {&(0x7f0000000480)=""/135, 0x87}], 0x5, &(0x7f00000005c0)=""/30, 0x1e}, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCLOCK(0xffffffffffffffff, 0x20004276)
r4 = msgget$private(0x0, 0x0)
pipe2(&(0x7f0000000000)={<r5=>0xffffffffffffffff}, 0x0)
msgsnd(r4, &(0x7f0000000240)=ANY=[@ANYRES32=r5, @ANYRES8], 0x401, 0x0)
msgsnd(r4, 0x0, 0x401, 0x0)
msgrcv(r4, &(0x7f0000000400)={0x0, ""/137}, 0xaf, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETAW(r1, 0x802c7415, &(0x7f0000000000)={0x29f57365, 0x0, 0x1f, 0xffffffff, "8b030003000100787d902b56d864d3c3a3f4d3c9"})
writev(r0, &(0x7f0000000500)=[{&(0x7f00000048c0)="8efe927e139219019b33b40e291a6368427dbff01c7cf9e8ccc4ade5720223e7a6662a0f568427379d9428bc1da8fd20369e0ca8bb91335d364af186d9c5531b9cba018029760cfc5fe5d17bdc790f9925d9cdc96a5caedd8e6eae50d348188460bcc36dd2f6edda2619e63f35a27b1ee4e51f4de695b6a10d863b7bd4e1dbbaa8f26bcde8979f6bba0aa3a8f44ee0fd922a626b5147a7af25e431cf9939d7956aac37ea115181cb846522ada8aa188bec09c17898b1b82042b227be753ff8957a9a29ad685590d48405d84316994db071ed29f21521e5184fcb680dc0db4986739cf9c3c481bb6ea8a7438498d036e6927fdaf18accbf38de8aa188f8ad40261d2a02d88dc9efcab74bd4a77bfbeb013faef596e2895d5583b471e4e4526c5d4e436148a971e5bf1f1c37eb1ae5d542cfb0892b663a208eab4098251262b1f1713a0ae5406d57712c454655a5bcc1bb90e8598723fd410ed54b09212b790b1fb656ae84e53eb922fde9d93c5a3fd97994934f8cb5d7fda2c04b022b668f3aa04850f5a80e68103a8867317c201fa50f0545deb8d8ea0ae16a6884d1060a4e65dfa6fa5f7fffa77593b38e1efd6cac95bf8070243cc1b79e49963de3f2bf4f76768f2d384979d160bf75370f6742feb16efda16e2179310a5b504a2d57c6cd26851677755771a1a250ffd3ae98d60bc18a042d65c74dfb6c1e9f57662faa92126eb67be86773a736b70d176b31f8802de3dcc492727554cd7d7a6cd6b4d1b5daf6291a101b632ef7672a075a244a460b1445647979f1832e72551752eed8048cfafbc9a574613ae6f62efded1ab90fd37d28e6b8506f9f945db79385cee0ad50b922676c193cffdc418a59333b8ee24d9d7547ca00df2786e6aacf4c3e7e267fe0bea3a611dd0e9a36e90720d463af713f54f8b13a42c647847aee0a41743b42c907c5072ee5e769c63ce3614a16a3743eac6f64bb2edc35e44204616616f00d5283ee431a2a9cdeb830d572866dde345c96dd13cd001bdfe6fbf00bf043fda6a3daca8a06c1e4eb15fff83f7b38c35f51e781c8bdff20c78681ce6ce76f6b756dc2ef3fb7481980d1414c001147367f1b302f13992093e9e8decb8daa298efac80c892de7034ad8d355be8270018127c7201c3032007b7dc2cf38c7356dd1b9a80d0828fa345f2bd5b5d9b02324bf970bd5ed5472349a197097b6f69b5adf2dfe7f0074813f3956df325e0f80b9e1edffafb949f677918291b36e3e86a8eb3091febef03ce69f46a31e96e93114c0f62f69ea0ae1326bb9dbcf0e1a82865521ab493a381e91b4f28dcad093c70330cb2a228fe9056ff3bdb4cf5e0edb553559caed3055a37550da1ebd7e5ea13f9085a1a20fa31a17cd5d29ba5c3c01c00e2684513feb7cde3aa3461777112b965202eb8292a27410a34f5499d0ff49ca9da2054b4601c86474b47a15a0ccd994052bf6dee62c006ee762160e253ebf61bdad0e4868788c6b80535e20ee33cfa9dafcf7697aaba6180ea6291e8215493d28063e3f9573a1d3a3cb7d967dd09e402f5bbed673cf76f6a07ecb2d1c085bb6362d4d86be55c7196a52268703e7ee1b87c309c31173ead50cb7d14c0813e03694d71719bfd4ac246ff9ad990d9288ccb40075f57837e1bf15119cba7184c236a0bbf1f90e5e6c1b1862e7d8bd28d3925ad24992028aa8bd2511aa214f9e747453e9ed928fa926054c34470e039a9dbda3d2cf12b83135cafc3785ed09bddcc7bf70444448218028b2044630da30a0b1314d7b7c02792e4226be1e3422b98666d91b0ab08ac0875c7a698c37fb1b15ec3edc4f75af022fa59a58f67e7707e3c9a157aee42201569d4d9f93ec81acac9e951943eb5c3678a84a674e4f2bde76cc4f7dd6c1f4816d8b0423a5225dfe4d0c9d79eebf075372c29a294d4c0365400ab69d1eae152a188f7672c0172d2e509135515e7c9a57755b035230f214ae107c1550cf93f0f97634aee00c8fce7914615d5cf83349f1d528a232c9e56142005a865c0d7e1e736c41ebeac7756b94a981ceac91df4d8192063588f99ecf5883b3c05852490683cae11405440930cf5856615398a6db8620b887dee8b64d894289ee35d18e03f417d4109f551bd73bd29dbeefda2e4f2953ebe18dd3554a5db6f5d2dd97b5b5210be235b388eec8e9bcb631033e999a90307a1a2f39ea46d6714b4509ca7fcb52787f7fb81675dd1846744f42f9be873c1823fa765aef28826dbac4196b83d7d914b24c917fc6605775c8cf3a006864689210da58bd7521a6c8ebafa3c435c1d0b7e776153eed19dcfa4635ac7c05da169900f28c80e556ed8f0d3f449ac6f427c3f6ae61731e25e457eb780cb94a3f971285dad8fe8fa518b73d689b9b8da6ebc578f320c846b6ff8330b54533804e95690cc0b618e47ec64adfaf1b324f34159afc595b0ffd85bd730b76c91b63bdf059d799e5514c1c1006ec2e796c587b88ab90b13577f549d655f689632b49c5e5b42ce6ac5ac6a099727359b0e8e88cbb456b4dc966907e1ef010c81b7099405dde30f4dfd4d88d3d5d109f1f96ce42c0957daf613d3c85e393151d151b82b0001c74b704a62032b9e006e4938742df0864cb2740a6351fc8349f0840966efc051b3b716ac6a17fe6bd4ee4d9eb8a29ebc50d7a6790b891379306c8fe197438f07551406c93b5f4fca59b9de4919e0631b3e6a085780292038b2427822ff7fd6dcf0d5efdb19ffd9bb1a6684fceadcbac2316a880fa5c8ef32554b7565ba3e019ad5fa2406cccacf7093acdd3f348aa6724df7f80ce4513ce5780310d98cda7a9709d4f894d24ab963a895b465d0c5d342507b7a67520c63172634826acb64950b04ec37a1bd8384930db5396e24abc31269f17ae22c55b4a1a401fea8f36691fc27af3476735e901d2b0691a65761c0a3ff23638e805a8e694bf6438c5725463781d5c98188bc5c86c814aefa31f77c8d52d140c207d5c05579ef5bec2d66b33f34658fa95f193d6be077d9ff64b8f07e850eefa598e8a3c9cee522273851a5a66df3cb351d68f0282d90f927ee4c6b070f50a56e170ce3b70f4de97a218da1f54ae5cfb7400000000503e930607d011201b9fddc311f6736380e169b732165ebdfd6f65f61c0356ded5f87c8b1c7398002374e02e85a8a63e3fe74ad9ce5f4467166b00662532a2dc96c4ccd48df46aa01fffc2a873080382b39514919da36fb900e0b6351a387d6edaffe3b453a10fc9a46e8cc1d2d8bc7ae520871730df253ee6552f92a18ba629c95b523ac34b041c1bd60344edf35c0c497a847e236775e1d8d887850415aed2c239d19041fa00f42a52d38e61611bbef6e5763869042bf5bbda6ed3c117ce78b04edea74f92b19e410fbf8b130f83e68623ed3836a96e38dd30c3d2e7cce84d3c0ee9f1b546b0d716417af0d7ba2317a0ee2b152fe5e32527f9b177142aae42558866d982203fea7bee03309469b99ec690d401020dec4d9186657f42f8b3c2475acdf3e01edc6b3765ff1e8754965da7d311f0c30de9ea4090089623824e42dc2378e8dfff132a089be402f828bec70419f3c3d1fac377fe1cb061a60eb9aaea0264c25d4ac7856180da12c30d5dd226315b86956c4e6e6be5db586ecae1f647b914d0c2970305bd672375a66fe2265bd6f41fe16dbba16ba52427f0842de6678fd891db578c7d997e4da74b3588121be9e587da92ab4eb7a46eacc6ab91f6128cc7c0f59b2bcb0d69fc332e0b310e979bde14116e552b928976f47415e23450a089635541e9606e1518c87acd60a8b174d35b4619becd33ae5905b69f27a5628f914a8df7ba1039331a2ed319814c37144a3d45b51486437684f4c46a27c01c658720910af53d3b8be0f3097f95a2156acd530e3b84bca7eab6d6ad8ad66f6c3952f5b6747ddef4977279655ff3432173c691c3fe54c18703108586f8e70e05971ffb93e31adf16dcdfc25819713a8c54b996d9bb07c4f5c677f7151aec32caa2bd78fa2d6d72e34c136000140821dd9192e22f06ff1a70bdcd48a7484c79ea27ab81134b0ddaa12e4e9730f406e07b7c2075354a108d5d4fb467dfc9a46211fe9d3829e95b4fbc436641848325771699a4f89f1bd912203cfc9dbfd535fb6aead5a15f158a710296ce64e7d1212baed41eaccbca23c238f69b1dde29a023e182051455460de920073cbb66d15e1d8bd8c8fb4fb9ed75eaa807db46a192329b16bb99cff6545695020298044751aee4099ebecaff43d26dff5ec7c0f2ccd1b0fe5c83", 0xbe1}], 0x1)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "1a0001ad00"})
ioctl$FIONBIO(r0, 0x8004667e, &(0x7f0000000000)=0x100)
writev(r0, &(0x7f00000008c0)=[{&(0x7f00000009c0)="6600fd5c61fd0441066c539ed7e416ce4aa1ec3ae1a80f68826971499047e00604ca74fde3802fcca726c6f41301a29d71034b62233e9c0c4d185fcca49b9bc811c6af87beb7885e5c2640f32516838ce615b33da525dc7b593531c08f2c65cf522c5f167644eb4ccabdd99bbe26a4d4a7005e060000173fff3c95581d09ec2a97824002e0332ce777eab6816177ec7ecbdbbb282351d664261791757338c392bfaf365971139cf40ff609e84a93799b3db231bde2ae5d6189bc57b593a4aa702e86fd8bf9b0d76c55ed0f1a4172db6f7731f0234532635f5a6170739a98552a4cb823a737880da41466fac4b1f0eb9d11c57bd8c4808fe67dd23b869403d1a87d3986e64d514ad76226aa29aa0bee239a9e66ff53b9456534bf", 0x11a}], 0x1)
writev(r0, &(0x7f0000000300)=[{&(0x7f00000020c0)="283c22ed5062ec38a5a31b126833436aea0503eba16c99aa01892652a82693c7a0e1061b41c27b1351ebfb695e43954a7f046c855ced4c667f6be22635dd449e2d9cf56e974ce7bdf751ad2ad1c2fbe07ad0403b1cc256617dcc68e2f61e6b58274b42ca9c774e091db99902cca3d11fbf4b84cfd34b665931d329c3d13d79799cd9b38509e8c6ac932cacbd4f1b79353753e7221033498b900b8c6f5bf816b5a51aa326c47e6ce17ffd94a5e54f8a7f0fa8339bf3c37b30e869bee1d86615c9fb9a3619e07c08c8c225a10dc1ebf937e40009d0b9b86114c6662cf13c495a5be5dc3b91a1408f7ca5a703c95be548f9499da51b81cea094067cc7830f2099e6ab6fdeb8765ad1191e543eba5b5741e56771a0c67f9ce67d66da02a77b9941fe7830008c1afc61baaf1c2c0137174b1dfb45ffdd24694393c056c2f73a59e005", 0x140}], 0x1)
writev(r0, &(0x7f0000000080)=[{&(0x7f0000000180)="a4d1def6a09663e3088418dc50bb23fe818a60107465f8e9e15bc1419eeec039785002dffed6a8fdff74a20cff73d24ec0141cd009ddcab13270c0e254c7c433f392db83f49bb5dd6a865d8e42a5ebe8ea0ae0059e89992a3c954d39b199a088b0555e39ee71b85b16a4afec6fb773314e84777024f41cce52f23e327b1621d4304b4997698b5c10ab129bc463ffe608b85f231a17365f7cb7d86712955a923da57fc6b3939bb2afcdd8b07d95002c84e67a00", 0xb3}, {&(0x7f0000001ac0)="309a1a55d84a881503c2863151df4e94423d99f81a584548ae93a7e0b34680ee03827e67ff193b6b52298bc8039dd9ba9d8ad449adaa09c1896eda6bf13b66ecac3bde0bad256abd27bbc5a4db53fae15f1216ac5c11c49988d966d263aa168c2923e163be64712e88922a8360ba0fcc14bb3a33078d94b27763528334fdff46aae7e609aff568f2b18e9503fe0be1f7abf73754f3af91c0dd2adb6a0a4e9516716c8766b4cfefd87bf81f9408cb38740168d917e2dfbac08ab6b136aa804feaa4c535212db4c0e58249026ff3d140a69a42d076d60c934585f6ededa1e3831bc789c113335527abcd1990bf69e0d005099149d84c329c299ec7d222591e1ee4387479a060457b23646681d75243a8783b93386272", 0x115}, {&(0x7f0000002200)="0120d5d1a2a5648433df7b4f4c01abc24a11dbafdcc09ddc9dee9841674769b2894f2496446d35fa662c1d2256392786f4d5e14e14154cd52a774d2b56cd38d12b64fe1e457e81e7b25ed9c49781ddb7a56c6856afbb2ae7502bc3b279a626b873b2b67e86e1a6f1974f7fe5d330f1eec9f419b6c0e3d2bb236a945d3862df214adb7d1c721d3ec82f8aa076f31124f83b41a6f640e94761c6575e69f3595526871bde40e70292c4b526d93eba60cf51b84a9d579cfd226e4bb97d03d2775b959bb17ae3f1ba23176fb84efcbbe90120af5e9b23cde83a54b839fdf8921c31ad47005c3d9c4c5205dc155a273b4885712648ab6da879220f8f94f91d0e1e3894c8952de49f7f2b2ba8ab8f54a6250a9939a363ed49bc1ead2bf19c47990be00741efe2baa67d5700bfa673b01db8038db10ad984a7d5d22de34888de63f427e7bf6c26e32d12ecf4d229ecef3755400b20eb791aef4f5b4b98e4cf9aa6ec48a2eb99fe43daa357e0c5bbb22040bc4c11a15dbd9684246b401cd4e5cc1f85ca91777a4a77ef793ee95fd2570414ab932da5c14ba2108fec91bb6ebc1b8c15e6cd80f571411195c191e9dc5a20f024ab35751b5e1bdae01deb0afdd46ce59a1316d2a74e20d603fd3ca9b60ca78e9a7bf96f554f04b73a67cd213041bdd626da3d869b0bd601d9955fbf7560b9bd36f885a829606e5448a963ca759d338e0eac3087b271cf4e0b388780be1d8b48917ff2a394aae91ed386b9bf5b23f3a62a590799804e4ad3536c14151da22bdd9d09ece8389bd9f1fb70069280849d8c88c25223c77b460c0d6da21dbcc380fef8fdf320336e8ebc44f4cbae93b3a2c7cbd6412c9b52ae93b3c749db047780f5cf5dfc1968aa6fd660c5f40203b91ed26d39f63b06460bbe6758c85e8d3c4e6960acfeadd14d7dbf92a4e0912092769ef09432549d69cd8c39e84c20fd3b7d12bdac8ed4c716dd1ee82b9ae5fc80d2b53a89e2a89cd789dd0beb5d0f03a8bf20a73e13440a6dbcc5d4ed71c122f5029657c1a635cefb1e157e2d914bbf493b5bb61ddf5413135d7fa186694871e70d5e89a3b458935e60647b240a0dcc71798340fec1ef03a3271ba41e779ba441ebf6710e57dedca84b096634a41c330ea8244d131535480f4b51ec4576372643014c1beda8bfe612f9e89bcf3424c02e1dfc3716d9d29f368dc5884e180e0ee86f9d773ee75ac8d16510e590e206d8df01ff80c85ace267c59f0839581f0585c78409b420d1ad16c3720e03a4a9bbbd6e7021af5185a302e2ecb2b8e3cf571793020924c9c350311599daa0cbecfe17cde0e83bf2ed940e50cb825382c27c4551c42cd70cdce9114287f7ba5c11e0967c1ee891f55022d6669005755634d8842911ef3fe4227f09e9b6186208f82510e87bd0514dd334ab5c89e0bf06fa3e181db2437113ecf78be49d29b00a143288fd2175b5e0f9af2a774320bca45e011c9ad23394da6508a7e9c9770f3232fd50b0f0c27b3cb2e04b6e5d1a5710aa6f5c86d679aaecdd36b4095f37a4db4cb80cfa7cbc2b92137ce9242819b0c9e8330f9b59eba54a222641f293159333836e195a22ef89a318e8522d9fe9034dbb65a44f3171d23f3386b306842281e6f73ebc9620bc01fe099a294bf5be85c8156a9287904bfde7616522d214fff9a1cf83a6645dfb446ef6301d953859268277f24b60b0922b8dbca2bee79bf7f6f14319e454aeb9fc989367900ea89456fa7c5d7283a2e28805b5b493925d05920b3f189d7abf2cbf1ac13756d5d2d0666b2b014c7ad775237687a9d1841028757116cde5e9499d1c5e606e656dc31fd35e59ec4fa440ca13e06ac727c847f1e69da4889d0ea54624d91b0be46447084e2b54525d8a267cecee89a2a23cb64ff37bdcaef302424857902e0e7c9c0367ae39525b28e2d316f7711b5952ef7bea6a51a6bf5a97cf69d7c44a5c58b3acd4fd1cedc78cd8b133d50780d36d02b3f3234500ec40269412a33583c47b78255879f5695b7ed167ef869dfc7ac9c7c5a2a1d804185c725b01a99b0154ddff3a99d17a82be1aa03bd1e9ba1b73567ea3915746f005e26b68bd27c86024685dffc55015f6c8d1785e52dace35ba3b120cbc38f0b629bbf2b542340da8c897704515e9516256abaf73e3f6726af25ce0a0839c436932cf2d631378110a860a9d0663bb47ed5c1fba162099f94771b0ed558d7bf53ef0685e8ce2cf7403313db7cdcd482b6638a1befdd53a575814f59a8ca9114640653ac96a77bab01334ff2c2d7546fda9e4ccb555b36c4497b9f319b5b371c27bdb584a6898f7f12045c09610389eb862c35a2cdb64343cccf246123aac07200a4e788dab3c6087e7dc41ba2d0b03ddb45d6326a03f0f807c47cdcabfca23b6ad6645eb8d8373a3b66e005bdbb143476104cdcd54e8ac083d8fb574f2a27da0e657a6df02bc945523dd3afc6b5f232aec7071bc4744a36f02245040e4686f0620c092745e6b58b15c3ea3299572dbaaac604eb7b8d508bb099ac852ecb288978549d7161435a4a37fcf8e9124b3c97da6850d64fe61d1a0ce6402c93d60e7706971ac77e842b1740b3104e8853896d39abd5fd8873403a360dbacf00b9eaefad86ae3143c479ce0023e8dee3269e4b90f44a2e65dbb9fde16427211cca2fd17b6299901cbbebb7f99147c8952c8480e1897f6c63330ffd1ff72f03d4f48b1668d2a88c76b7257c8aefa881afa2a8a0907fa2086d08ca76fa56ef7df3d9ee8d3c1325e037611d649290285048cf35db51adc3bd8134955ab731035c496280a06f44601dabb1c6574c97164bd05d60f7054d98afbdfeefcbae9468060802fca9b5034ea771592b384c6e1aaee4d5f3226dbc3726a8876c7cb0c6de83e3afa50dad54641b93a66ffa8f6db74826e6008f73b16912e061a28000c3ce75701492c176d6bd5135bc7334a0f114ed10ef79bf98d15baad3e120ea4295d7512915dd01728a0a6b13addefa32754c21f6b0deb9f9b5bf7368d7f16ca4325a6aef8b86471bf730fead3b9db49e436ec6b694e53ea7d43959e40bc1709fc7be3e08c93f5ffdbe5d0123c6be2aecfd4bd4785644e4be3363bdf17c0bd113316a5482e2f29b6367d411e20c5596cb568db3c76e781f29974a4208f416a20b1c1fa7624d2b3f3c5537af43ae6938276e7447291987e2c31a05d21d4f994e32ff5e1eca4e227c9ad6fed68a03d52135b284610dcc7ed955b1a68a1248be89f125a5344f912fe240852300c658c2a7e290cb9b3ef7e41c1ef93139691d66f2d38ac507724dc00ff5ee1e5a3daaa6f5bed372942a624740897ef282c580f26356e5f6223496dfdccca1f9a090886d35ae2cc870a957cf88c8767685f864398e93defa7aed1e39560d962621b7c32128689d1b6db52c2260af6ccd7fe4cb56a99ade6f019dc40becd5c19bb8de10230224b01647919237790bd3bbe5746401f437a6cc4b8e6345f16a6d64a7816a4b0cf4fb104d7b202e8290ad9539ed9b0937faf378aa7ef640f482c32867fdf3ab103452e4b5d3e6cd0dc8bcc19ae252ab89305771493cb42fefb46ca67b8a42cc233eda800dc173efb2fc3dde6bdf5579d0782530773afc5abbec7a92ddec2fad511a1975ee03856d81900442a5355cb379d8e6ed15febe9853607e17dceb3075b389ead69565d345c65d8d9edc592c75558927da7a96270cfc44d82563dbf0b83ed17194daf827b94c9803c7a227fd041dfb8cafab204e647ddc2c91092c685fc8fc4b262161eeaead0877a807825a4421ec37128b8148ee99376dbd033b5800f69bafcc7ff01783a4be306c6e9afefb6697fb013f5cf7ffffff163ecf93525e336984c8c2fc6c1c3fa62ae1cd7e73d6ef3e4f6600d902684a79c0ab43748b4fa77a69b92e3e6435e8c8bc1c0c73be644bd8f290ed7f1346cacb26bde561a17d98867b2ceaa08098ee22182998f89614df54a82f03f0b30f5219d04ec17835eb452605d9f7e6b21c845237bc9ad103d1b86d3ac0d73b2fc4a9d6c7b386539f95dae84d2e162e85a05c6d6551352b847fa7b2e708a1e3874fe09c5b6429df2f4eab080e88e847150061aeea6237ac9a7aa96377a6e36b2809f9d1bc048efbe9a4e7aec727eda3046a83770e66fb27935a3353c252986f21fda39c27d2e5b1294f02f55fcc3ceec98877172aef83832dbb57db91d10016cff35045b7d0fdf70734a992606cab972cf65d20799c3734cce1f21164ffb5e136c32ad6cd4b99909f9c3f8d5abc1b2cfc6218b64740900eca35ea86ea6a57f24a500aaa6475fa1d97c188fcee39227fb78c519e870b32496296b43f53c7ba4ee572035b87bfab0243a309db64f6ab241e359fffaf0a3b5c816ce6399eaf57ee27a79e477b9fb98e7d14060a52ef94be083d8d66986296d9fe28c63259966bcb5d7555c814e0dc78f8a7bd8233f5c915d3394c1d7bc7437e59ffc6d13886c2e4a2d0eddc40c84f6759ec95c3d865a968d8aa99fe13613aebae637cce9cdc25ac3b58ca018eea512b9c46e41d2957b86cb5e75a313a032b12277ed82acfda6263fbc5cd4f3c8dcb743c6c8dc8706bca27d01c8c540d59f8fafc242f35420b8cf9fba9d38ab283c89f9494de3d388560a48fe3cba27ed4cef3d4c188769fe63e631b959a85734a7be80ec1d099526a5b6e76ee0e3a16d30ff918fd5983fe2e969114619067dc569f85a89600390716c4276b25182e3d543d1ed933e2584165cfad8c68af60abf27fc7ac29e74ff2cdeebb230f6f5b63881378f2c9ecf89b3f6fa704d308b3237ec4375697af425e4436ec644b986df2acd8738cd7fc65b236e57d2425521d6c3d3f786a9f26ccaa306c750026232499db9a53391159cf84b0a0d92d828161b19ab4d981894bc9fdb20bab4d97c52f53c416d6aa43f8cb26cb3b3fbb9584b69563e35b60d386e7b2b72178645c74b8b2743a66eee6cf046e54d7f231caed48589c54e29ee4d3f65c30af90647f21e1f0adaa5bfac8e8a090d0f481a13380f3746485f742d6b6e742dcd407ec92acc475f6cda9a4659d626b53812b61c734c50b13ca162dc190b9efa9c5c28871810a04138b6b679aa76438bdf8faea95fbe67ad6e5ddba19c03c155d91cb10a41ff7a03b014afc97b0d1ba4abf380b2ebad3d05ea5aa3a7ac5da32bebf2634567190bf56c827ce0bd6020919921c5e67a71f2d9daf1c1695b2615c5d5a04b3c3240127a89ac0e551d8c47c011e941c9f6d9ec4526917673f1cabbe186ea916bae81ac34873b30147bba560687e6820a260da10303c0e7d67c62bc1f0e00e7908b3007dd9e23c5a27a4be6d759cc4495139b58102dc935284a9a86918bcb09dcbc801a9928703451ab26fd382ddebe92e81afcc42d847a1dee611f8493ca969fc64baf6a077ad761b0186c1a540cfcdbae2e952416a0a15312e0dce367b5147ed1b421f040dc63b5cf6d2c57ba3c16c5cfb338dccb31f0045d8e0ea986187deb6387aba49c9b99e43905f2253c1ac61ab2a92411b24100bcc31023c15b836271968d0a7df57bda793fdc409c94fd387c4bd4ee75edc70bdce44de18ce40fd417796e5746bbb894ff8eef3c62b0ae76d6324d0f4a76f47eacca1cb916abc42a48cfad126d7cb5ce15338b7eb2ec0737c1f6e0c98877fc94ab0891a", 0xfb0}, {&(0x7f0000000100)="91e4b022de2e2a83af5ed474e218838b9aaa0cdd3489f83fedb3f91edafbd780fc02b33ee31ea42c4173945e8ca759f0e5359d61a529ac1b343573de74e6acaa0e535303740c07408d3dece03827ade7e8e569b0de1a03bb5ea9acdf40400c90552ad33cf65bad3f0e6f9f890fc5c876a82e9c55bd401ad2", 0x78}, {&(0x7f0000005ac0)="b3b34a5cd83eef3705ba5e97db29d5bdab21c859ce4dc8d77d379fb5456f500e6e073c570b3a25fa33bd55c1581246c8b209a51b38efc20e116d4f47374418a0474fcde3896f04b0f196eb51c66bfdbd420201f3ee30d2011656ff24bb6f29daa767f565f6f5973a20f9dd998e9fb61e55c677e436df0665772cc75d7e26d6e05ff535c23d092eb97fc98bcdfaddb2ed8883001f19a04c56eeb62891dcec787cc6286821f8c2e0f419dafaa4b5fdd3d10f8707199dff78f23830e0750a12691091f834403c5c8e1592ca88e3451d15fe98a7e1cbb6185a8513e7ba33705757110558c6b61f9bdf3106fc380f9dda71ce88cae1d92f07a986892998d46b3834c67eddb9873c978c3fd16c1c18ffcb61737bf42ae1414da9abc155b34c8ba255e0a41884ec29c2f5381e67034180d7da0d50129336293112f05614118d784340073b2f291327d07742d75c1dd86221db6e83fc08de361158a878d610b9c928126bc277cf27132bed244ff3d6f273aa49147792d36b388710ed50c5a530c7e8a8a80888e4a45ed23d726e03beab0da105040be2a49496b1ec473c0a6335dad7113ce6c871b318377a482e6eb32b441ad09720f36adcb6564f884e09c02f4217a2fc7d2abc3d8d7c735f9ee33f34c80e877517d286722d1d94b6c279b26e4df6fc2f0153068b7896599b92a33de406ac4eb2bf44673655a9aaa5f97ca567acf397b2e88626c14e13799f0a0761e5c1d807c09ec3e688499e095682dcd14f949bdc2a9e0e3188f2fda7f2226465e74fdbfa4cfb2fa5deb136b8e6a4fd02a19d96297dd5c171f30058fd94f62cbb40f8efed96fc051ed9418a312690ac7dd16c959e8e21cd59e11c26485d62d66eece29fe5bd8c8bd09d74db036a5beea81c62c3b8b71bb3eadea65d8143aaa686fd430db05bb2ada31d9420e04fdfbe4bf5f026424c54d8c62e039b62dddd285b29a1d795543ee7bb5fe4eb39919e2d926f9a6ef577fe165860d14e916f822ca24fcef835f8c2f50ef31d93e2eb8c6541be5a9feee66b4d94c47c5bd6147f4d47ac4b00e484b302731f2bc5ec4752ba3419d17f2814da28665ff8369dc47ff3215b6480c4a639f0a0c4c0c705b1d0eb7d6cf82be999b9d20423e4d7b39b210bc0166caa9975d180dae8a04c83bbd9dc98d63fa6edffa5c2e5c4799167bee3dc0d9f7b0e64b148b79aa0faaadf86bd8f0126782cb56c73b58c5b70cec90292acc47c9dcd0919824bae9b2fc5d20ab31522fa8e387f8ad61078fa606a1321d25f2f28f33dd009caaeea1310b84ed757bb33ff418315ec8bdbc1cbee0b63b8acfd96ad17cb94c5485cb6fc3f5c44dab4eee12552b44258cb0e0fcf8bd110888475200619e4826d0ad28190e8e13be235275d6a3777a13e81a7996dc55b0650ee4a114f5f5fa4fac910e22a7668a2131fe38322845d3cca4d25b68c57a60d1ab505e67934a116490745051db648bfeccd40236372077c41d1f62d2d403426a4950f1f467b7fa0006b40443240798e7615d3790d0d68d99bc9d70b527ef9e7165e17c19e828d59ad430cf83b6d2436613a8844ba9212c04d386e78e8b37349ea8e1f75c3ff80ed53305a3ed6fa7a244cde64fc591879f7a828b3d3a198d6b8f46e18fd72d688847bba7cee29301850b71fd400cdbf1cbba5ca3ba2eb6b0e4c440413fc2cee2f1911f1a9b503551f32f36429ce0343b659b693a13dd32288b9a7b123dac4c43871cee49cab84ab8e3c6c762d9182c9d29b9d21f4b127ee6925e588bb25a077e8d353ec24c42e8da6abe50e3a400175a1acf8d2903fe6c6d846803c7a0c25f91ab27bb209859a779037ac48487480e72919155f60a6d66b48b84118708ff25ca8003e37e0e94bc1221fb20ad6cd7ae56a660c4eff04c08d178d0dc35d80c50ef1ed8d9e3cf736186a4139d09230931eaba133d5aa6bf1720be8b6545ce3a93a56b9fa3dd83238afb92519d50b8c6deee819a626357d22adae1545579f7b6803b2efc928039c74ed1c9192d106ef3d19c3872a3da04068bb97d733942c737bdb24ce035c64db9c954a940ad405397459a39b8dc77e0525d11f22c4a029a66bd04dd0db02423d6c99f5926dbdd41d69fc44c248df5c960ceebeb00ecba65685bf9adb664c0b07c2e03c417ca1bcba66248dd45e2faeefb239f15e57e3a5e857cc0a67f455898d7e420ab3fa6e1da05ed93c727e89c1d8116b8718bc21684e8e65699723e8e1f18eb8a62bed6975dac66afde781e6d14daea6c7720efd1b252dd989642f1d302a7b29302bacf0477f05224bbc3ab354c94edd2585f63fb70c643435f5a978dac7213932f8b6f678bf55b1b6988bf16a06726dd65dba29f55107ec8fe984e66b67be9c3b242b19d0ad88d1dd4eb9a134551a6ed532f0a992a572ca7270cb3635dbae8df1f812bcd9e6068e9c710771d54d8f10df34232949c838f546f7cbe70554ffa0f66b00299c83bfe5c8f5f98fd6e3d54351e90186bb46f3f180bf7cc4ce86c6243e76d0e3cb7315a17a40a6a1eef773d02c80458f9de8a9963e9ec608e4b145d26ce4c380b2a82b0d25c1fa96925db007fcb1641d49e164974b0b561a354583a0a8f48fe9b2eb18610007b9179909dff7dd8cb3a88f1652ae3e50d3a5aaffdb5551ac81493d1d9bcf868237c05c17f05370b06727fd6c791fd5c66e4438ee40df14d1ce3fb337f48e4e4a54091eb1326af2731026866b1bfeb1f5cf6bdab5c7948c896791f76f3771529b3783eb2bf4d62949e7889a95bb7abe6becf6986b6d85af0f0383da26c31d6ca64676a2274eba76a74d6e9f82205c4897aee0a30efd4836f80a2eb6b6b7210fed1d00652802adb63cc3a0a4058671d5911efc2b4ad0f2d5e3bb0875f860b679aafd1c0536415dfc720bfc57474f39707e9d0a7c8b8cbd6536554ac912414d31cb65450d0a8264f43185ed271e7979de01c33cd3fff6a59a696e383bb2dda95993eab3b041334251b6bf353f37abb33c6753c51f5ce91b385a2e7063f63adf839c7f82955d39ccb3a890263194e9a6367bd7c14dda59fb076a1f85c75c45b6915350301c4a5ac8f8d1f3378d429c5d26723335faad69d995dfdc86014dd519e532dba0b8895c8e079b8683b72449c1d582b868ae67552501d63a2f089fb80636f91e41bfe748930aa64eba8f3f5af912151f203dc46080b22c9ec52ef533d6f4d38819e6167bd3a6f122ff80bda2460a93d3886823c43ed1e155934d2dd664bf8f33525246b8a624c68c4eade7c2d32745e133f8b4c433560e2ee4e25dd5ecaa77ef72580b9c6bf288609e1302088844fdb36b9a0caa79d0f55a2270e603416ed791991fa943488f9cef297f2ea45e69d558b83a766672b9219a8ba954d926f3e30842bc922c159c7eeacc590d8c787d4aa56433db2fa5b1772942cf5da20f6730116a1efee255ac6b8868662cf390c1e86d8576a0ea03bc87baa522a6a39d64df89cd3edaa4476549886b9c53fc1369b9d886a093dead3b89e4c3a052f3cf430c42147f9ebbc5d669fe389b81be8dcda53d573000c65d65d9e502f283cda944671f3ed26f2e53f4c352243149f3e4ccc43e63cfadab085d0e82196fb72ef5e24217bfb45cf9ee88b96aef2908a794cfac85cbbdbfcb68b52849677471052f7a6dbb835a476f3adaa37dcd6703ba1e83585793815554d264fdb71654ca23177561fe19939cba60b59395fe27f657d9d38dd3bde3f09c192b4aa46522e0e41e0966f25eef7cd462e4c41df1d2f88e49a491ee85cd4850924cf1c8b4df9a5abe44e38fb36eb63f24d63764506048d680112a6de56915a37dbf1ba3c31b43d64d24ac9b1ec6a9e33bba7cbdfaddcd59e005b8a4a92928f5dda293b9eb61d7327fb0e93b6ee4d9609256cbb015588af82a4a1ace90efd999c230f5eec694e1374fe11dd55aa18ac8be2e581073448fe1f41b779c1aeb3b49c332d04953710663d817a764f7ec2b3bb3a3e391", 0xb08}, {&(0x7f00000004c0)="64686e39700c056b9552e340725d1df77dbb1af2997a53bf4d2294b1860f8b4ac196675565328890b4fdf39a50a1af245ec0a53d6a0c4ea0671d0ccd94b97e268ca45e11583dd4777ccc3ff8be61269cdab201d48208f52652187b253ca94a92dba1f823948d5a80746f55b8f073b90b0daeb6e969", 0x75}], 0x6)
writev(r0, &(0x7f0000001280)=[{&(0x7f0000000ec0)="5d20d61924495f5749f5c45c7fabe8f26c5b2ed784a905ccd97d15b819b4718dd9f11a09665336fbc15b8637b612f017a63db97121eabe00", 0x38}], 0x1)


sysctl$net_inet_ipip(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000000), 0x6, 0x0, 0x0, 0x0, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0xfffffffffffffffe}], 0x0, 0x0, 0x0, 0x0)
r0 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
getsockname(r0, 0x0, &(0x7f00000016c0))
r1 = syz_open_pts()
ioctl$TIOCSCTTY(r1, 0x20007461)
select(0x40, &(0x7f0000000000)={0x7ff, 0x1, 0x9, 0x6, 0x101, 0x9, 0x1, 0x7}, &(0x7f0000000600)={0x4, 0x9, 0x7, 0xfff, 0x2, 0x4, 0x100, 0x81}, &(0x7f0000000080)={0x4001, 0xe08a, 0xffffffffffff0000, 0x8, 0x1f48, 0x5, 0x6, 0xcff9}, &(0x7f00000000c0)={0x80, 0x4})
ioctl$TIOCCBRK(r1, 0x2000747a)
ioctl$TIOCSFLAGS(r1, 0x8004745c, 0x0)
ioctl$TIOCSTOP(0xffffffffffffffff, 0x2000746f)
r2 = openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCLOCK(0xffffffffffffffff, 0x20004276)
r3 = getuid()
r4 = getegid()
fchownat(r2, &(0x7f0000000180)='./file0\x00', r3, r4, 0x2)
ioctl$TIOCNOTTY(r1, 0x20007471)
ioctl$TIOCSETD(r1, 0x8004741b, &(0x7f00000001c0)=0x400)
connect$inet6(r2, &(0x7f0000000200)={0x18, 0x1, 0x3ff, 0x4}, 0xc)
close(r2)
openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000240), 0x80, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0x8020699f, &(0x7f00000001c0))


syz_emit_ethernet(0x36, &(0x7f00000000c0)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaaaaaa86dd61f481a600000040fe8000a5f97806e84e2811f218dcf080000000000000000000000000bb"])


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000080)={0x0, 0x7, 0x4007, 0x200099, "d88c28fa8797f9bdca0988d15554000900"})
writev(r0, &(0x7f0000000000)=[{&(0x7f0000000380)="7e746376ecb3f4b7c3b9648dde9d8c13de18b9e215c4a9cac7034ab89ebf86868d83590bbbc0d90ba99e59ac2ac3a2812db4a42c910ec132c100ff7f737c911d105ade6f74489113b68abf53fec3be6aeb96d1dd0b41272e9a67087a7fbcf181a77e72520b7622324acd62aee319cf3e29c7534ed4beb03e67ea8902030d8222e539564932f2040000000000003e8baddb5ec102383f95df148f2944152806cfcb731235c9b66b30ab00daec0ec87a189a8d240141070000008de968692f4a942984cd03000000000000000b17e13cd9b51d09", 0xd3}], 0x1)


sysctl$kern(&(0x7f0000002940)={0x1, 0x20}, 0x2, &(0x7f0000002980), 0x0, &(0x7f0000002a00), 0x0)


r0 = socket(0x18, 0x1, 0x0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0xa, &(0x7f0000000040)='\t\x00\x00\x00', 0x4)
r2 = dup(r1)
dup2(r2, r0)
setsockopt(r0, 0x1000000029, 0xb, &(0x7f0000000000), 0x0)


mknod(&(0x7f0000000040)='./bus\x00', 0x0, 0x412dff)
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, &(0x7f0000000440)={&(0x7f0000000280)='./bus\x00', 0x1000, &(0x7f00000002c0)='./bus\x00', 0x6})
r0 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
recvmsg(0xffffffffffffffff, &(0x7f00000025c0)={0x0, 0x0, &(0x7f0000002540)=[{&(0x7f0000000600)=""/4094, 0xffe}], 0x1, 0x0}, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
kqueue()
kqueue()
socket(0x0, 0x1, 0x0)
sysctl$net_inet_udp(&(0x7f0000000040)={0x4, 0x2, 0x11, 0x5}, 0x4, 0x0, 0x0, 0x0, 0x0)
sendmsg(0xffffffffffffffff, &(0x7f0000000800)={&(0x7f0000000040)=@in6={0x18, 0x1, 0x0, 0x4}, 0xc, 0x0, 0x0, 0x0, 0x3d0}, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140))
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB], 0x9}, 0x0)
sendmsg(0xffffffffffffffff, 0x0, 0x0)
shmget$private(0x0, 0x1000, 0x0, &(0x7f0000ffd000/0x1000)=nil)
shmget$private(0x0, 0x1000, 0x0, &(0x7f0000ff8000/0x1000)=nil)
shmctl$IPC_RMID(0x0, 0x0)
r1 = kqueue()
fcntl$setstatus(r1, 0x4, 0x0)
shmget$private(0x0, 0x4000, 0x0, &(0x7f0000ffa000/0x4000)=nil)
preadv(r0, &(0x7f0000000300), 0x0, 0x0)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
sendmsg(0xffffffffffffffff, 0x0, 0x0)
close(0xffffffffffffffff)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
sendmsg(0xffffffffffffffff, 0x0, 0x0)
bind$unix(r0, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
shutdown(r0, 0x0)
r1 = socket$unix(0x1, 0x2, 0x0)
sendmsg$unix(r1, &(0x7f0000000080)={&(0x7f0000000040)=@file={0x170, './file0\x00'}, 0xa, 0x0}, 0x0)


setrlimit(0x8, 0x0)
syz_open_pts()
mlockall(0x0)
r0 = socket(0x18, 0x0, 0x0)
setsockopt(r0, 0x1000000000029, 0x0, &(0x7f0000000040), 0x0)
r1 = socket(0x1, 0x1, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
setsockopt(r1, 0x1000000000029, 0x9, &(0x7f0000000040), 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x0, 0x0})
mlock(&(0x7f0000ffe000/0x1000)=nil, 0x1000)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f0000000180))
kqueue()
kevent(0xffffffffffffffff, &(0x7f00000000c0), 0x101, &(0x7f0000000100)=[{{}, 0xfffffffffffffff9, 0x0, 0x4}], 0x0, 0x0)
r3 = socket(0x0, 0x2, 0x0)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x8)
r4 = socket(0x0, 0x3, 0x0)
ioctl$FIONREAD(r4, 0xc0206921, &(0x7f00000001c0))
r5 = socket(0x2, 0x0, 0x0)
sysctl$vfs_nfs(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r6 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSKBDIO_SETENCODING(r6, 0x80045710, &(0x7f0000000040)=0x200)
syz_open_pts()
msgget$private(0x0, 0x0)
ioctl$FIONREAD(r5, 0x80206919, &(0x7f00000001c0))


r0 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000100)=0x200000, 0x4)
setsockopt$sock_int(r0, 0xffff, 0x1, &(0x7f0000000040)=0x200, 0x4)
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000000)="b886b4e47f", 0xfffffffffffffee7}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
connect$unix(r0, &(0x7f0000000000), 0x10)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000000)='Z', 0x1)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000008c0)={<r0=>0xffffffffffffffff})
sendmsg(r0, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000))
ioctl$WSDISPLAYIO_GMODE(0xffffffffffffff9c, 0x4004574b, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000180)=[{0xc0}, {0x1}, {0x810e}]})
syz_emit_ethernet(0x26, &(0x7f00000002c0)=ANY=[])
execve(0x0, 0x0, 0x0)
r1 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1, &(0x7f0000000240)=0x5, 0x4)
getsockopt$SO_PEERCRED(r1, 0xffff, 0x1022, &(0x7f00000000c0)={0x0, <r2=>0x0}, 0xc)
setreuid(0xffffffffffffffff, r2)
mknod(&(0x7f0000000040)='./file0\x00', 0x6000, 0xe02)
chroot(&(0x7f0000000180)='./file1\x00')
mknod(&(0x7f0000000000)='./bus\x00', 0x3a0914c44f7b202d, 0x504)
open(&(0x7f0000000040)='./bus\x00', 0x10005, 0x0)
ioctl$TIOCSETD(0xffffffffffffffff, 0x8004741b, &(0x7f0000000080)=0x7)
open(&(0x7f0000000040)='./bus\x00', 0x10005, 0x0)
r3 = open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
r4 = socket(0x11, 0x3, 0x0)
r5 = dup2(r4, r4)
sendto$unix(r5, &(0x7f0000000000)="b1000504000004000000000001410000331c13fecea10500fef96ec0c72fd3357ae30200004e300300000000f20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc256699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec589041f000000008000361b4cc702fac50000ecd1fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)
readv(r3, &(0x7f00000001c0)=[{&(0x7f0000000140)=""/5, 0x5}], 0x1)


r0 = socket(0x2, 0x3, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
connect$unix(r0, &(0x7f0000000000), 0x10)
getpeername$unix(r0, 0x0, &(0x7f0000000040))


r0 = socket$inet(0x2, 0x8003, 0x0)
setsockopt(r0, 0x0, 0x1e, &(0x7f0000000080), 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
getpid()
fcntl$getown(0xffffffffffffffff, 0x5)
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(r1, 0x80104267, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{0x81}, {0x50}, {0x6}]})
socket(0x0, 0x0, 0x0)
syz_extract_tcp_res(0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
syz_emit_ethernet(0x138, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
r3 = socket(0x18, 0x0, 0x0)
setsockopt(r3, 0x0, 0xc, &(0x7f0000000000), 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
sysctl$hw(&(0x7f0000000200), 0x2, 0x0, 0x0, &(0x7f0000000140), 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x1, &(0x7f0000000000)=[{0x0, 0xff, 0xfd}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
clock_settime(0x100000000000000, &(0x7f0000000000))


sysctl$net_inet_tcp(0x0, 0x0, &(0x7f0000000000)="9b1809ffffffffffffff7f473f11e1a4e5f2f9f220ef7f0abdbc34fe4202", &(0x7f0000000040)=0x1e, 0x0, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x3d}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)
r0 = syz_open_pts()
openat$speaker(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000100)={0x9, 0x0, 0xc0b6, 0x6, "3cbd74892345d5dcac43d4e364da4602497d1a50"})
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
setreuid(0xee00, 0x0)
openat$pf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
select(0x40, &(0x7f0000000c00)={0x7fff, 0x0, 0x6, 0x0, 0x7fffffffffffffff}, &(0x7f00000001c0)={0x1, 0x0, 0x0, 0x0, 0xffffffffffff5fe1}, 0x0, 0x0)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
setrlimit(0x0, &(0x7f0000000000)={0x1, 0x1})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$VMM_IOC_RUN(r1, 0x8020560a, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, 0x0})
socketpair$unix(0x1, 0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
getuid()
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, 0x0)
socket(0x0, 0x0, 0x0)
msgget(0x3, 0x0)
sysctl$net_inet_udp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
msgsnd(0x0, &(0x7f00000002c0)=ANY=[@ANYBLOB="010000000000000010ee20dcedb37a57f7fd03dc4d7f8da54329a1d0aad976c8d29de7ace0fb86e24bead91f650bcae0e939f439df94a10ff08a4e15fd3ea168627e1b4aea403d35107c3e32631cc7e89ed0e766d31701f79c0f0dc416f21eb14ed4f1d0a0105c52e2e7d9cb4f5d82bc83b882667f218e23c46809f223a0ce416d2f24d79a01d5fff008abb98cfa911f0022ecc43c7f1f339a9780ad0ee5dd9ed963a2dd70d7bd2ac057ec"], 0xe4, 0x0)


mknod(&(0x7f0000000300)='./file0\x00', 0x2000, 0x6da)
r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
writev(r0, &(0x7f0000000100)=[{0x0}], 0x1)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000500)="94010502000000000000002797888fd1f838a311000000000000b13886ca3849451ae3c3051020741038f5538551f30ce390500e08fecea11ea8fef96e4fc748e93f0b780486aebdbe781e4d8f5eef9187a869a4d3a4cbba982fd825582fe223ed00f4c8b2ca3ebbc259699a1f132e27acb5d62934e4fd89070000000000000070c1f5a872c88dff7cc53c894303b2a0a85ff3faa800000000009ec7ab3a34c29000000000000000000000000000002d7e4a5d76cc3f9cff2ed2243e56fa277603c5cc1e047326bcf6b67b75d00bf6ee330b6a80874b70559d9975ebd13da2447a78aa4b00cd0ba1870215607bb912e3d7325183ce69456b4b6ca927871c81672a54ec695c5bdeb842836656f917945cc076f87dc714dfe0aa2947252df350707b22884a7730cb6dba8742110fbe9ec7481885274387e0b1dbe5695122604819b0b2294b7b20726a5d4fcb44f62d00fabb2f247a166d8d79d05b8cc370f5c11db58aedca632a83acd58ff0ea0a3dca58ccb03cce466cda735017196ff346c32717397d6ec6952ec90de81ed297b2509e130f0000", 0x194, 0x0, 0x0, 0x0)


fcntl$lock(0xffffffffffffffff, 0x8, &(0x7f0000000280)={0x3, 0x0, 0x100000000, 0xd660000000000000})
getgroups(0x9a, 0xfffffffffffffffe)
ioctl$VNDIOCSET(0xffffffffffffff9c, 0xc0384600, &(0x7f00000000c0)={&(0x7f0000000000)='./file0\x00', 0x4, 0x0})
r0 = socket(0x1e, 0x3, 0x0)
connect$inet(r0, &(0x7f00000000c0)={0x2, 0x0}, 0xc)
setsockopt$sock_int(r0, 0xffff, 0x1002, &(0x7f0000000000)=0xfffffffd, 0x4)
socket(0x2, 0x7, 0x49)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
dup2(r1, 0xffffffffffffffff)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
setpgid(0x0, 0x0)
msgsnd(0x0, 0x0, 0x0, 0x0)
sysctl$hw(&(0x7f0000000040)={0x6, 0x2}, 0x2, 0x0, &(0x7f0000001080), 0x0, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r3 = socket(0x20, 0x2, 0x0)
ioctl$FIONREAD(r3, 0xc0106924, &(0x7f00000001c0))
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
r4 = kqueue()
openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000180), 0x8, 0x0)
kevent(r4, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r5 = socket(0x1, 0x2, 0x2)
sysctl$net_inet_etherip(&(0x7f0000000240)={0x4, 0x2, 0xf0}, 0x4, 0x0, 0x0, 0x0, 0xffffffffffffff12)
syz_emit_ethernet(0x4e, 0x0)
socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r5, 0x0, 0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
open(&(0x7f0000000100)='./file0\x00', 0x8000, 0x0)
open(0x0, 0x205, 0x0)
ioctl$FIONREAD(r5, 0x80206910, &(0x7f00000001c0))


socketpair$unix(0x1, 0x0, 0x0, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000380)=""/116, 0x74}}, 0xfffffffffffffd67, 0x0, 0x0)
syz_emit_ethernet(0x17a, &(0x7f00000001c0)=ANY=[@ANYBLOB="f3a2a8908a86aaaaaaaaaabb86dd601ab5b60000100000004e95"])
syz_emit_ethernet(0x126f, &(0x7f00000000c0)=ANY=[@ANYBLOB="aaaaaaaaaaaa00000000000086dd609ded1a12390000c4a4e3434e58d025a6a8a81cf312b8befe8000000000000000000000000000aa00030000000000000101000101000401000401000103000000000100010200000000c7ab6f1eba08bf03d1805fce0ef2ab82f4a065245eccda108bec7cb23f632c993265a4cefeb77b1406d562a47d4b0054943553278b519ed107f62b5c352f8e68d83c1fd85b8e1083556d7fa2fc09a3e823fa940de6ef1b18ddb2a2dba0d2d9c1b44b20ed3a932a2c47f4f4d3e34ea1b67a607001a4541a87d5d347b5049b3444dc2b7abe3499079a5701e88493acb2eb1808e8b1f74311083f93341607915aa46325934e81b672d809cb6bc5f3d64480ba4db4432a67c2548e259fe7831f7c6dfe"])
sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f00000001c0)="55f8f5782087a072a82ec35f78d14780f518", 0x12)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc1206949, &(0x7f00000001c0))


setreuid(0xee00, 0x0)
r0 = getuid()
r1 = getuid()
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x10, 0x0)
r2 = openat$tty(0xffffffffffffff9c, &(0x7f0000000040), 0x80, 0x0)
ioctl$TIOCSETVERAUTH(r2, 0x8004741c, 0x0)
getgroups(0xffffffffffffff84, 0x0)
r3 = semget$private(0x0, 0x4000000009, 0x82)
semctl$SETALL(r3, 0x0, 0x9, &(0x7f0000000680)=[0x9, 0x6])
getegid()
nanosleep(&(0x7f0000000180)={0x0, 0x2fea7dce}, 0x0)
execve(0x0, 0x0, 0x0)
semop(r3, &(0x7f0000000140)=[{0x4, 0x200, 0x1000}, {0x3, 0x6, 0x1800}, {0x4, 0x201, 0x1000}, {0x3, 0x1000}, {}, {0x3, 0xff72}, {0x1, 0xdb, 0x800}, {0x0, 0x0, 0x800}, {0x3, 0xa, 0x1000}], 0x9)
sendmmsg(0xffffffffffffffff, &(0x7f0000000380)={&(0x7f0000000340)={&(0x7f0000000240)=@un=@abs={0x1, 0x0, 0x1}, 0x8, &(0x7f0000000300)=[{&(0x7f0000000280)="8bbe837bf99b5b8dd9fe51fa744d49734967bc2c4a577f5bc033429a1cec8a0a9510e3e3510ddd4b15926d3257f270545388dbb9b5fa5ab75124f76ef8c0e88c4d9e0016980f68cc13324d", 0x4b}], 0x1, &(0x7f00000012c0)=[{0x28, 0x1, 0xff, "e8ba4131160eafdfb96fb8732d8c44fe47a5"}, {0x48, 0xffff, 0x7, "f9e8e83c94efa734248b16b639e0d7f13abfedc508f37e6f17098ac11c99e186568ef99ab283ff9a9394ac6d0fb7e4ed452797ab94"}, {0xd8, 0xffff, 0x3, "1535649750284260b0018eebf9c3241678e3831933ccd492d16b65c440ad62ce5cc1461652154047913d6c71ce5632af54f3aa632525a85376bdbd6b2e6ff446b050b709a2770b9726c2b37fa4a6f4094e81b3e3bf25c0702d95c3b2dbac21702a78f44f8137b13d4fe2b458043acb5feb7f5437018a12391a7c9e8c45aec731ab567707ef113af65240adae2a1aacbb67910802db2ad62fe8c8480ba40816374650d982cd0799b5f05a0d41978496c549a093ca2212e46806962632c3fd3c122f"}, {0x78, 0x1, 0x6da026a3, "ba18e7e709da2710d7beff9aed1accc9b86e825b3cefb6a0a331b95cd53b9802380813bf12c99ec28f55e57d29fdc8e05ce83340d81371e0d6708ac8f8a932a2963cc2aed36702697bbe78b6c0237b7327825a45e2f952af95d958ae85201e6242e1a646"}, {0x50, 0x1, 0x40, "08fc6421679c03525ea32d67bed7ef960743fdccfe9c2fed4db819774fa394d62b073859f65d5163eda502f6fc9ebd0ca0a7962691fbd4b3840f"}, {0x1000, 0xffff, 0x3, "1d565891502cfdf54f0408d72abc69daf2008a6cc7d05091a82277632004ce4e354d33aa32ef1b0be227909221cd5733bdd3dae5e5cb82c840998af5ea19d27b4c7f1d6c9bb92b8d952b84e6c960cd9fe5df0877db1a1722af2789b3c21c189d032cf967278ce9d1f577537bd4e306b76da7eb58ef78e4619a9ce828064af0cd0044e0ad716e0f54359c2a55255b2fd83e71ade14a9d6472e9c11676d79024aaea6756aa9da04a8f6cf90353656242480aeaecd11face2e370a2b9ffe9986f9fe0b5392b9f0cfa3f84aa2b19284e24fbccfbd97283d30bbb93e077b0ac3da8951d26df909e4f47047013c8aa4e0e8a528cc232e335590ac637aa008c6962eeac78a73b1b45c27c441319191bb71bf5deab43feac070eea6924bff84f887b74737c6a0c22938984d0354e1781b2a2b8b20e5b0da4d7c7b3cee68f4901bd99c1a6b5f4851834c780dacc7a65e9e0696d097dd79257861858b8d343f2b5911fd7d58ef619ffc91bc8c54cc9d4441b53251b782e03284ff0d4f476fd8e8bc224bd89857440a148498525f91e32ae72a6debaf0122848b40795421833d83d84c42a76d14d80b4c61e003b95bf26d08ebf772e8511782d689d3a38a938c3bbc1e8be7f38c18a8f03d809b71e08a4f208fc5782697f77c8808489243c4d8a88025b8efd0e3edcb0e30d9b0365c5830eec6eec7cfc208f5a4f16050727ec87f02da9546d4bdf71c7bc8d078fe7550c426d0fa8f162a3acb482d8d916b8485422171b3d5d7baf965c4f3475a941135600928547720fac5759daac01d374ca244288eafbae105fbefb49d9beaf6ca39ceaa853c053a289a80a28070c42c138de8d355cf08b60d569e384840ea7bddc1b1d71fafac9d51962e1cf1aad70e8c42df448e9a25a68acd835186bfbb71c0690af5819587a5d6059256cca11c5be83141dc745222b3a0e7ec402e0952a6d9c19a29d52631056d9c45bcedd41b0621e73e9eda65c7b5a7f79a0ba526f30affdb4979ec89f2b2624197907e73aa3530631aa3df8ca57c6492ce83790d9bec167a2afe43234cd6ebc1f274d478085c57b3c5a9e1119d6e452ca2dfa99a572012b3fec5370f25f5737b090749e707732a155f5daddaf89a69cce4bc17d175dc0e4617c703c160a5955211a305bf0088ab9c3023e3b1b6598ef3cf6a822b172e73d757351133d88704243f354539ff5596c2f054c97ff38fbdda5edcca44c1f5cdb5395a92a3a9bce5f8270f16eed3267b52ba398e66d7634e23cf56b53eae3bfff45df97009cb0b57550affdcb3ae14766084d491abf0d6fe2788dececa5de3f236df587354e9f02cc6505dd5a98696e6052aac17427f20670d98e7797a28d7936638e3d12c2d5a95da7c9908f46e52e3e8876bc5b51259f66c561c38d0c33c286b4a4511bb3bb6aef92e0f0ccd2f2f19aa427730ea8051aef71e5454e831645ec4cca1a163f9fe85d8033cb35d14fabc5e600d411ef2a20e2c7b4697d568e80d6935df2315f19081d654fd04aa154aa4b6d64d7fe39254935050428cc5e55ce0dc7b0702ab71785284a8b0dae2ad95e6e2da31ca5808867e20a00805be3874b65ae9d15f58862dca79228c5a5bb0468b0fd6bb1e687b64a65bcd2a566172f45bdb6be29e0587d228c3c17a26c275faee441ceca93afac1074709989bb7ba685e350b1a0096e619718eca095f92f67161db0a25177c1af756bafe989eb025545897dc3a5bb3efd0c6952a9a925078b52a62bac78df6d2a828293c0358b4663ecbeeee18f14d6ae85f98c322bd552cab7d6a37ce97346edc9e9b494c086f73f8e0b3c4279d71fffdfdf4a3fc387fee534b8d5397177919a1e61fd3a853b66814c5f5d84c9743c154e395ccf9ba321a995b181d056bc89256335069ddfaa0962bb4cfa51960bcca8e2695c524ca85224d10a6866c18a009b6a4f564424b2202b049d5b81140e05d8c018737e9ef1d31528a15b897ac57f2effabf353a5dd027ce9ca2c6da8c8f1e00b6c7fed2d966fa1e809c0f4f94445f16c5f82e43953de0e9c245793e1071b1fef5367c4ed29b1d412b5e89d48a042693f3c05b845e1188b426ab359cc8b128f0ff8dca057771d690b712d16a9133273e0485fbdfc9408c78a9786c2ad148f239fd232908c6f6d8ec9f40c37fc4f224591fd86791ed0b392ee24cc2ab2381349b92eee91ef59ef65a0e0b5fdb6a1c92670b96ec2d66614771b9847124c334c3bf8c62a8dc9cc2094bfd4d619e01b99dc7c149b1f5ca7d7e3304a56d2eb0a77f414f515f76ab19cfbfc60736e603f11e697534fa2a0cfbe97101dd5827c0129e9f8ea82217af602cbf1ea9e3092043925bb88ccdcfcf57f54ecbbff4dbbd9de884c64fac39e4731adc8562e046ce2ed3a161071a7b98cec3daeafb9311fb15cca19b6ea8f93632c3c7dc9c7743961908302f953e820d0b0fc3ac152fe93d0031e10d264cb5e01e6813b3fd6644054425df5cbca82066ea66227c22f57f7029055ff1c5f022924f3b6abcc6550565cc19f97106cbb4b0715f3711aa5ac416ab1b95d7d9e1c724e37cab09ec61da273e788b56917787cf1af35ef1da45bb9f59fd68fc26217e7def1671e4644bff1ba5ecebd8b865f19102f0c52adb6662eb6ca1fd60946c7f4ae728ebad3c63f4632f740ddc98ad67d61f12b0639a2ed457f3ff1c6e29312299eb5f34fe65747f90d9b484af525085ce1774f2b4e6f67a5cf19885f175768801d9f14066e8b550945ff41bd5301da6ea8aaedfac3a8c410398ad0a37263be500cb0bd4816167bbb204cc71a6ffb0f42b38f31dad84bdc833e3a509c7577f2d9f4e6d89e964bccc312ff02c904260aa9617ecf4b68ad7e2d31354dca74b8f71876108f6ce7b7299c3df3fdb48101995608338fda03604757727cb0f3ffd559e4fddc28a85ab8ee4d83d3f1f66335e4fd8bd97a3563f893a9b503f68092096ef09a5bbba61c344e6eec687f1eef7f5fabf0a67cfea409f2d481ddfea1ef1b13ce879ef9015fe5b2b651fc5b1d5c826597a84161b286fe7977597bb16ecc5a792f6dc7910cbc37598e0fa5afaa34a569783e16d18c97f8a37b4649940f7583eed47d75372302684f833fac969cfa37b3105701cf5e5c40775f81391437d24a6b8c0aa3a74e6d31080421202223f315038e0fa3c1db1e99927de50945b29d917606457f801b7809dee0bc63f5d8685274e75849d2949de306a5a19b4b67c4c7c451db0e4626796c1a601b6c4b5d3b1c728404b3bf3f2618d6daf9080db49e1194fd8245b159a27799a8e7f57ea946e7f62a95fa16eafa594bbe51a2e4c35a2f94e6e30c15ba0bc839e7eb12f8c24b1410dd97fd827dd6742c51ff41679b7ef2a9839ea7524964f45f4e9521750e0daa671ae47a1014a70b271c670a5ad8bb79f5b3cf73f10079a3a0ec5fe2311b8545d76adea3b6afb017f04e2de635720c4b8c486aa53518d156ea5dd915061f95d49dff048ac8e5da6896064d5e82a0e2c12c6282e6bba2259b87a957c116ddc1a9c8cd7e36aae0f05b77874313e605b6053fa24303f3a7326592a0192d543bd7a5ee577e94aacf8ae0aeadfa44c30d30d0d291866d4f4020f2ed4ca5e3589f699f366dfcc90809ce3e7c53ebeb0fbec0fa6c7e34c1fcd555a2d3f627c0227cafae53488db31f89a47efbd7e33891f42138c0eb106e98ad35c71c5ebd536ce8e964d9f564b3577d6889f66a1d38dd6d7b432c86ee26696a34ff106944fcf5e99c1848b2b72d8155a9ab4cd1cb451475e4678f64f60c226bcc9559abf05900be0ea076808d4aa855f80c4c55ef5662c325f43571c5994ad3e4ff85ddb7ad0425f16bf77defe6a4da21c32b6c3bd7b6f53ba8a3249dfd8b27cb8c1fe802a97bdf224859d5a3e39941a19e13e025092fe3373ad936940f4267174ae9872cf2bd1baa207e7db9148f8aa0d5e0d9e9ad3cc9bfc6796bcdb5b8ad37da63ed5a90e1be45e3e12a9355ccab8197526e85b91a2bead52b4010a317763bd6429e730e0e03d4c4887b22f69d1a6fe71fb9ff6d72bf0e26b498c70ecf9793825eb73bd811fa47951f1934e20235903c6dbef909bb31b0aeb6b404abdad1ea82ea11d668951989edc7303aad658f820ada097152b094fb3115cbf7688724cd425433c749ef5a5cda91245e0df71dc41853aa4ed41d5beda387598ca304b31d31f43768e819aed735d2cc6e481720471050841e1f4883179bef9524412f08ce8112c08db1e5c4a0a2c3889ead113233f3a887f25d82375817fb294894e412e5418b72c35624b5280fa5b8d94bbff37e0899176d6264ca673769e823ee2c60e18b33b9eef0cdd29e5cc57df5969b9215cee0b04bdd31c380714663114ef8f1470941a9309c96dbd4b2a2a976bb8408d1b25e86b25a13c5081366cb7f159dcf7f018738e653a84a64fc7e332d72dd5a77413058fcfee641cb1927a686832322287e8812a152a924d0e61bb37e0cb4a80f67d6d5fce6275613f56cfcf23683ba31560101ca93cf60434f79a27f16f22ba3c81a376c593e10931dc5a192f7ba2ce4e07711febabd07c0c798eb0de4216c3d149c1170455594f103bcc0f2d8b24b20587995811409e59b5f4ea7c3a596d8b41b52dd06a226ca2b3007ba94c118dec78d9e98e0f31b90d8cf988974f1e9dc1f31967ac9251949aa5d806b52241ea3f204e550c5728756355eb458cfc7c84e230cf76f91a4e6087b4280637b81be671e35b6e359c7bc530bda47e947aa9099905ae966b3607fce16ade937b9b9229b53bb3a8b796f75bde6879020e00ea03ea560da71e6231d6710dd674be9e51f1434da2e8ae9ddbd2b25ac44bafb532ea5ba7aec0ecbbc7d93f9fc272c569683f07f52054ae30be9fb1b9b718ef28f50f2a1510f016f3c52dd86f8e841b04eae85ae018055107d5485a6b337f984952c4b69519e711bb9ec6eb5777b9c97e7b50bef2725737a065ede82b834f76e58683556fa62eae731a90417b02a450f4aca631b094f1a27f5fd83a4bd5566c78bdfddf71b38ec6dfd4f08335f29242c78a5070e1369ff63e2d4f17f7d2aefb3694466b4438904700df59ef225f4d899fed097cf35cd8520776986ab3eca1f108db4f15ac6bca840dbfe156b07038f7d2bbc75da1bcdadbdd716a7ddbb65c28279aca1a4ecd3a8edde39ddf44f6fb40e0d6f81c9d81ac861b4f6bbc4d65b5de1847735e3158b7a671aa13d9c6b105509f34476aefb241caa629751469ca69ee8da9e55a3ddd8b8a5f7d0f20e8167f0a4905fd0f3298af6551786b7d9042b15b38ea825c7de5a7d54f6be209fcd59bd7da7b755c9f16440c3c4debd54d12afaa94c8fc472c6fd2159a15c71d4eeb4272ef1129a8b58fc2c7eb692ec539053a95c02766d2c3541bb73650690a06a5ee85d82b8c4bd6e2d36a72b040fd0cc4a36084de5e21bab25da45b877c5f53c3e1cc766b565bf2dd90a1979f391fe41ccb87e30d784b22213d427474194b7b3f95ee1296c7c7ff95f9c9c5c6cd6e4049177816708dba7719697d2d720c0055e27b7e6a11c9fa58a3d981a75356f3ba9a73e7bd75b928ec148ab6d47bd71fd4539d7dfa0ec956a99f9e541246ead17e4545800998cd5d09862d77c2931aeff2fd460570a76f110dd6951271bb4b6799fa147ff44ce0430ce9a7119727f9795415014fad3a3dd00f569445a1121e4cde4885511ac4c71d0b60030fc4058d7b97cfe80902c3c0f177810e12d439d770d467da7b77fe3b4eb9b5a6b69d194"}, {0x28, 0x1, 0x0, "5cdf48f09399ba864b69e21dbe59d40a401ea0e0a397"}, {0x10, 0x1, 0x2}, {0x38, 0xffff, 0x8001, "c1fa7934cb080c2fd15e0ee8b2f789da631ce60dde1449fd4e02e28bc4c8de99872059fe"}], 0x1280}}, 0x10, 0x1)
semctl$GETALL(r3, 0x0, 0x6, &(0x7f00000004c0)=""/195)
r4 = getuid()
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={<r5=>0xffffffffffffffff})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000080)=[{0x0, 0x0, 0x1f}, {}, {0x0, 0x10, 0x0, 0xd9}]})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000640)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000080)=ANY=[@ANYBLOB="18000000ffff000001"], 0x18}, 0x0)
setsockopt(r5, 0x4, 0x0, 0x0, 0x0)
sendmmsg(r5, &(0x7f0000000480)={0x0}, 0x10, 0x0)
seteuid(r4)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000000c0)={<r6=>0xffffffffffffffff})
sendmsg$unix(r6, &(0x7f0000001280)={0x0, 0x0, &(0x7f0000001200)=[{&(0x7f0000000100)="de7a022065cd6a454bb319cb2527f3c54b315461030856506f307270f54c5e1d1c681387532d3fdeaa94427c2a6825e7f887a52561d4ec1241f216afdf205490", 0x40}, {&(0x7f0000000180)="bf3b684c5ae963b4567084e096cf973983b85e5df63e013eaa9405095e88157332b4f68e78e0793d3e30417acbf4419893cfd424b75262dc5ade2ab6278ab86672f9ed186987b8c19d9295a17b", 0x4d}], 0x2, &(0x7f0000001240)=ANY=[], 0x18}, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000080)={{0x8, r4, 0xffffffffffffffff, 0x0, 0x0, 0x3, 0x20}, 0x3f, 0x100, 0x400})
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffff9c, 0x80105727, &(0x7f0000000000)={&(0x7f0000000100)=[{0x4}, {}], 0x2})
chown(&(0x7f0000000040)='./file0\x00', r1, 0xffffffffffffffff)
setreuid(0xee00, r0)
unveil(&(0x7f00000000c0)='./file0/file0\x00', &(0x7f0000000080)='r\x00')


socket$inet(0x2, 0x5, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
mprotect(&(0x7f0000fff000/0x1000)=nil, 0x1000, 0xb14766e595c6303e)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
seteuid(0xffffffffffffffff)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x28, 0x0, 0x0)
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x8040691a, &(0x7f00000001c0))
ioctl$FIONREAD(0xffffffffffffffff, 0xc0286988, &(0x7f00000001c0))
renameat(0xffffffffffffffff, &(0x7f0000000080)='./file0/file0\x00', 0xffffffffffffffff, &(0x7f00000000c0)='./file0\x00')
socketpair$unix(0x1, 0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000440), &(0x7f0000000380)=0xc)
r2 = semget$private(0x0, 0x7, 0x3c0)
openat$wsdisplay(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
semctl$SETALL(r2, 0x0, 0x9, &(0x7f0000000340))
semop(r2, &(0x7f0000000180)=[{0x1, 0x5}, {0x3, 0x3, 0x1000}, {0x2, 0x7, 0x1000}, {0x2, 0x6, 0x1000}, {0x4}, {0x4, 0x2, 0x1800}, {0x3, 0x9, 0x1000}, {0x1, 0x9d5b, 0x1000}, {0x1, 0x8}], 0x9)
semctl$SETALL(r2, 0x0, 0x9, &(0x7f0000000480)=[0x0])
socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000b, 0x0, 0x0)
semctl$GETALL(r2, 0x0, 0x6, &(0x7f0000001200)=""/40)
semop(r2, &(0x7f0000000100)=[{0x0, 0x4, 0x1000}], 0x1)
semop(r2, &(0x7f0000000000), 0x0)
semop(r2, &(0x7f0000000040)=[{0x0, 0x3, 0x400}, {0x1, 0x0, 0x1800}, {0x2, 0x4000, 0x1000}, {0x0, 0x3ff, 0x1800}, {0x4, 0x14, 0x1800}, {0x1, 0x100, 0x1000}, {0x1, 0x1, 0x1800}, {0x3, 0x7fff, 0x1800}, {0x0, 0x7}], 0x9)
semctl$GETVAL(r2, 0x2, 0x5, &(0x7f0000000140)=""/14)
pwritev(r1, &(0x7f00000003c0)=[{&(0x7f00000004c0)="353774137ccaeda0ef46364ba4a09d1558773c22ca940435548dedcd7fd362138dce0c7fee832f407559eee914bf726755178affc9e20fb41698f1575a26ff779de06a263edc0183c8c4d0f03750c6a011126def3d7f3eb9f671aabab11a87007e30d5e44bad7d9893231e18c8f6d4e14dcc34fc2f2bc12f2ad5476e254e006ea6e37a4b25679fd587cc523d4af2d54d6ae3c5e5450099802d66c5f5d607e9a86b8421f14e967bdb72ec00e0313adcdb0a79ca18f9f18773f417bf43e4a972699d3e7f49e52ba2376fbab255f767076a95b43d73e618054d85963ed7b35ca137d4514b7295cebba97730c7728b4a108a1fb16b29cf5080aff72dded179cd", 0xfe}, {&(0x7f0000000200)="f38fedfa74bedd26", 0x8}, {&(0x7f00000002c0)="ac0b21e41f7cdc1f84db18ed0af077a76d1211c54186dfec806800aff1f7a7712762737145f0cc59c0058946f57497487d944a92f6ddc2a63ccfc4f532c3a09757bbad419e6480671ef9281f20ee8711abadeaa86e78451fb1aab0872846a9dde47c5478aabf130431e08bc4fa3c0d7cb53ee059", 0x74}, {&(0x7f00000005c0)="7ee4a5e84646b3dca7bb800db13e64c17f84cad051b4159bacb3287780948978ddffc57a97131118a2c92a6043aed234268ded66d655e55db889b736e685f057d4d2ca0ae42edbc74ab0ddadfcc54d42b93aef3aec390ddaeb45e840c1b79f8cf2ed07b69992c7a6b545a0eb1fdbe0d9a6153b915192493dc949213c625763a3a76035df8becf89506a900cc43d199fe7cdc18ecb9435ef62febcb7a1cf6445017d44bfa2a23638c5dc7c93bca52f8ae632e07561d2c9bd51883b54dba708fdf44056641353fb7f7c4cab1c8a332fc5403e657106e600296d0ca", 0xda}, {&(0x7f00000006c0)="781278fc310c9a176556392bb149c34320ab9b10b3b6df0515151328b1478fe146b63f02876121001de825223c27a636711289a361f35afedf380a37cdbbf7aa92a88b005b864d98158505d3fc7ac989930278b65c3d7f7008bdccc9bd502bde7384b77fd40b85fafa74fd26af5d9983b2baed860094fa35b97549ed98b14c53e03f996720dac4c2b98b4a25de1b35aaa47d85d2f38688e40057bd7cbd2f4856a4fdd1283d9017033d92296e0426fc47db227b9d99e7a8d4a3ab3c7aaf1b696a8250e2e4a87e4f5c74f5b4ee97f23510d133b73630d9997fc0623b40b96900101b9d", 0xe2}], 0x5, 0x2)
semctl$SETVAL(r2, 0x4, 0x8, &(0x7f0000000240)=0x7ff)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000180), 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)


setrlimit(0x8, &(0x7f0000000600)={0xa, 0xc0})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000080)={0x7ffffffb, 0x0, 0x80000005, 0xfffffff8, "0100000063026d00000100000000000000777d00"})
writev(r0, &(0x7f0000000180)=[{&(0x7f0000000100)='\\)', 0x2}], 0x1)


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x601, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0xb2}})
socket(0x11, 0x3, 0x0)
open(&(0x7f0000000100)='./file0\x00', 0x615, 0x0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x1604)
open(&(0x7f0000000040)='./bus\x00', 0x0, 0x0)
r1 = socket(0x18, 0x1, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r1, &(0x7f00000000c0), 0x0)
r2 = socket(0x0, 0x2, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
write(r2, 0x0, 0x0)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000580)={0x0, 0x0, <r3=>0x0}, &(0x7f0000000140)=0xc)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r3}})
sysctl$kern(0x0, 0x0, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000180)=0x1c, 0x0, 0x0)


r0 = socket(0x2, 0x1, 0x0)
r1 = dup(r0)
listen(r1, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000200)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
r3 = dup(r2)
recvmmsg(r3, &(0x7f0000000440)={&(0x7f00000000c0)={0x0, 0x0, &(0x7f0000000580)=[{0x0}, {0x0}, {&(0x7f0000000240)=""/90, 0x5a}], 0x3, 0x0}}, 0x10, 0x0, 0x0)
dup2(r1, r3)
execve(0x0, 0x0, 0x0)
r4 = socket(0x2, 0x1, 0x0)
r5 = socket$inet(0x2, 0x1, 0x0)
getsockopt$sock_int(r5, 0xffff, 0x10, &(0x7f0000000000), &(0x7f0000000080)=0xca555f06cd31e785)
r6 = fcntl$dupfd(r4, 0x0, r5)
close(r6)
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r7 = socket(0x2, 0x1, 0x0)
connect$unix(r7, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r6, 0xffff, 0x1023, &(0x7f0000000080), 0x4)
select(0x40, &(0x7f0000000000), 0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f0000000040)=0xfffffbfc)
pipe(&(0x7f0000000000)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
open(&(0x7f0000000200)='./file1\x00', 0x8000, 0x0)
setuid(0xee01)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x8020699b, &(0x7f00000001c0))
r3 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r3)
recvmmsg(0xffffffffffffffff, &(0x7f0000000080)={&(0x7f0000000240)={&(0x7f0000000780)=@un=@file={0x0, ""/525}, 0x21b, 0x0, 0x0, 0x0, 0xbb9c2d4915ca7f35}, 0x10001}, 0x10, 0x807, 0x0)
socketpair$unix(0x1, 0x1, 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
fcntl$setown(r1, 0x6, 0x0)
write(r1, &(0x7f00000002c0)="7c84cf179279b50eda5dd1951a661d2e3a20851082c188f8b3d8a063d2025ff0d27a44bc29bdcac27fcb7aaa95cb2007be22c5553cd2f66a1f419a83d4275218a89d7a7803f069d851ff628dd309c40f6e3c932af00cb6219ae6e21d2c28d492cd5404b16dfa627d93b1e8ad2ea49d2344c1a3b234bd6f1c70fd4252844a6e6ab7b8997bc55fa22ce951ee038d289078b95510b0f2473ce1348434f0ec4a885ee84fd08fc50f08ca7991af3f8c322b496466f804c4b700cc9391855bd0ee339196de2b5ec2d8425c711d3f9e051eb055d45c693d7549712f5284a9fbca7d15c5bf1a9c8e3b3c1a43983056782e046c29e3d57082f7743b8bf6d994cd3c26c85609eaa11e6f7bc4", 0xfffffdaf)
syz_emit_ethernet(0xff, &(0x7f0000000400)=ANY=[@ANYBLOB="ffffffffffff0000000000000800471200f10068fffbc08990787f000001ac1400aa010105cc971a00004050cca730ad1e6745146e13df2c1a53289babdada005923ca93f659a5f366ec5b151e1cae6ef3a23e21a7d7cc9f6fdcff53dcd7593d7d52d07099427f705c90d147217c1f8857586421408a66048cc88ca41574530df55c00b8910a56f7c838556fc19ce0c3aed174195abf554c50952b3c31a9ccbc6871c871254ba5e0e047775ddce8cdc209ca9fc9c960f77ecfa8b32090ce91260b5b318f1bf00437a02b3b844d243e92c6af9d4306f60dabbb208884a5167b611b96be9941e4604b40599a64e7ab0cea437f00000000000000e47f8b64747d"])
execve(0x0, 0x0, 0x0)
fcntl$setown(r1, 0x6, 0x0)
r4 = semget$private(0x0, 0x2, 0x68)
semctl$SETALL(r4, 0x0, 0x9, &(0x7f00000000c0)=[0x100, 0x8, 0x57])


unlink(&(0x7f0000000000)='./file0\x00')
r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b10005016000009f05000700200000000000000000970500fef96ecfc72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf5f882b29e7fb32619a5f927e7be1aa050000ffffffffffffffff57699a1f139b672f4d335c223e7d0c032bfa896443a40602000000720fd38bfbb770aff5a872c881ea6e2ec5892000000000000000361b1257aea8c5000020027bfe031000008abfba0900000008e371a3f8343712051eeab71d89e0000407", 0xb1, 0x0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{0x44}, {0x80, 0x8}, {0x8006, 0x0, 0x8}]})
r3 = openat$wsdisplay(0xffffffffffffff9c, &(0x7f0000000100), 0x80, 0x0)
ioctl$WSDISPLAYIO_LSFONT(r3, 0xc058574e, &(0x7f0000000180))
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r4 = socket(0x11, 0x3, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x3, 0x0, 0x0)
ioctl$TIOCNXCL(0xffffffffffffffff, 0x2000740e)
syz_extract_tcp_res(&(0x7f0000000140), 0x8001, 0x1f)
r5 = dup(0xffffffffffffffff)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$WSDISPLAYIO_GVIDEO(r5, 0x40045744, 0x0)
sendto$unix(r4, &(0x7f0000000000)="b1000501600000000000000007000000331c13fecea10500fef96ecfc72fd3357ae320b37b673039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139b672f4d335d223e7d026ba8af630037282102000000720fd38bfbb770c1f5a872c881ea6e69e0bb76d907c400000200361b1257aea8c500002002fb00000000008abfba09000000ec29dff8f8343712051eadb71d89e08a32010de4b2fff040ff00", 0xb1, 0x0, 0x0, 0x12)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
pwritev(0xffffffffffffffff, &(0x7f00000004c0)=[{&(0x7f0000000200)="18d26cb474b5c9d53e0ffdba8c54fecc9031509b1623088cc3e85353a5586603eebda7eccfc5ced62b70a12fbffc2425f3f9e50317605792ea906ef56376aa499b9a909aff511ad2d6", 0x49}], 0x0, 0x2)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000100)="9908dd7b78511b17eb73f4343de5d29636fe33fc3cfc0375a0975adedac3db44030c596df980828cd11dea293d0ddbbf76c891791cc801e3684c619ca455779f9f80b26706c6f5ba485b75527a9bfe6f0382f643306ffc0100"/105, 0x69)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000540)={0x3, &(0x7f00000001c0)=[{0x30}, {0x61}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{0x15, 0xfe, 0x0, 0x7fff}, {0x3}, {0x8106}]})
syz_emit_ethernet(0x3e, &(0x7f0000000040)=ANY=[])
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
r4 = open$dir(&(0x7f0000000100)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000140)='./file1\x00', r4, &(0x7f0000000d80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
open$dir(&(0x7f0000000b80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x200, 0x0)
symlinkat(&(0x7f0000000480)='./file0\x00', r4, &(0x7f0000000180)='./file1\x00')
r5 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
mkdirat(r5, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
symlinkat(&(0x7f0000000040)='./file0\x00', r5, &(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f0000000000)='./file0\x00', r5, &(0x7f0000000200)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x0)
shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmat(0x0, &(0x7f0000001000/0x3000)=nil, 0x0)
unlink(&(0x7f0000000800)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
unlink(&(0x7f0000000700)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000e80)='./file1\x00', &(0x7f0000000f80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000300)=[{0x83}, {0x0, 0x0, 0x0, 0xfffffffd}, {0x3, 0x0, 0x0, 0x3feffe}]})
write(r0, &(0x7f0000000180)="23009100007adb020317bdda2b7e", 0xe)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
chdir(&(0x7f0000000240)='./file0\x00')
mkdir(&(0x7f00000001c0)='./file1\x00', 0x0)
setreuid(0x0, 0xee01)
mkdir(&(0x7f0000000100)='./file0\x00', 0x184)
rename(&(0x7f0000000340)='./file0\x00', &(0x7f0000000380)='./file1\x00')
rename(&(0x7f0000000080)='./file1\x00', &(0x7f0000000540)='./file0\x00')
r0 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmat(r0, &(0x7f0000001000/0x3000)=nil, 0x0)
r1 = semget$private(0x0, 0x1, 0x300)
semctl$GETZCNT(r1, 0x4, 0x7, &(0x7f00000003c0)=""/96)
r2 = geteuid()
r3 = getgid()
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f0000000600)={{0xff, r2, 0x0, 0x0, r3, 0xb2}, 0x8, 0x96, 0x5})
shmget$private(0x0, 0x1000, 0x464, &(0x7f0000002000/0x1000)=nil)
r4 = socket(0x2, 0x5, 0x0)
semctl$GETVAL(r1, 0x0, 0x5, &(0x7f0000000440)=""/206)
bind(0xffffffffffffffff, &(0x7f0000000000), 0x10)
r5 = dup(r4)
accept$inet(r5, 0x0, 0x0)
connect$unix(r4, &(0x7f00000005c0), 0xa)
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f0000000280)={{0x9, r2, r3, r2, r3, 0x0, 0x5}, 0x57e1, 0x9, 0x15})
chdir(&(0x7f0000000040)='./file1\x00')
chdir(&(0x7f0000000180)='./file1\x00')
getsockopt$SO_PEERCRED(r4, 0xffff, 0x1022, &(0x7f0000000300), 0xc)
open$dir(&(0x7f0000000580)='./file0\x00', 0x40, 0x12)
getppid()
semctl$SETVAL(r1, 0x1, 0x8, &(0x7f0000000140)=0x2)


sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
dup(0xffffffffffffffff)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x40}, {0x6, 0x0, 0x0, 0x85}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0xfffffffffffffe53)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f00000001c0), 0x0)


link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000001})
open(0x0, 0x0, 0x0)
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r1, 0x8, &(0x7f0000000000)={0x0, 0x0, 0x80000000000000, 0x1000300010008, 0xffffffffffffffff})
r2 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
fcntl$lock(r2, 0x8, &(0x7f0000000180)={0x0, 0x0, 0x0, 0x100000401})


mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
r0 = fcntl$dupfd(0xffffffffffffff9c, 0xa, 0xffffffffffffffff)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000400), &(0x7f0000000440)=0xc)
r1 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmctl$IPC_STAT(r1, 0x2, 0xfffffffffffffffe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000680)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f00000000c0)=[{0x81}, {}, {0x26}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


utimensat(0xffffffffffffffff, 0x0, 0x0, 0x1)


syz_emit_ethernet(0x36, &(0x7f0000000100)=ANY=[@ANYBLOB="aaaaaaaaaa2aaaaaaa86dd6089328b00000000fc7be31dda4e647e1cfaceb91fcfb1660000000000000000000000000000000100000075233ee47094329304d31d0ed7c2f140f9104c62d13a4e92a8efc205a33cee5aa817aa087d1fa5863446f8aa179eb8faad0aa0848faf722312319e918e2fbf7edd199964a0f94ebfbeceb6e4acd7a8bf5d0a8c6fb11ee1e1c935917deb8df8eb264a90089fd1478fbddc4689a435930c5b7d6785f1859453e8649a36e86c127f45e4847cc5"])
socket$inet(0x2, 0x3, 0x0)
socket(0x11, 0x3, 0x0)
syz_emit_ethernet(0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff})
socket(0x18, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x80606942, &(0x7f00000001c0))
socket$inet(0x2, 0x3, 0x5)
socket$inet(0x2, 0x3, 0x2)
r1 = fcntl$dupfd(0xffffffffffffffff, 0x3, 0xffffffffffffffff)
setreuid(0xee00, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x4a, &(0x7f0000000200)=ANY=[])
sysctl$ddb(&(0x7f0000000040)={0x9, 0x8}, 0x2, 0x0, 0x0, 0x0, 0x0)
ktrace(&(0x7f0000000180)='./file0\x00', 0x0, 0x0, 0x0)
fchmod(r1, 0x20)
r2 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x10215, 0x0)
ioctl$VNDIOCSET(r2, 0x81946467, &(0x7f0000000180)={0x0, 0x0, 0x0})


madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000))
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x3}, 0xc)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x34}, 0x4, &(0x7f0000000080), 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x400, 0x0)
socket(0x11, 0x3, 0x0)
r1 = socket(0x1, 0x1, 0xff)
r2 = socket(0x20, 0x8000, 0x0)
dup2(r2, r1)
sysctl$vfs_nfs(&(0x7f0000000040)={0x7, 0x4}, 0x3, 0x0, 0x0, 0x0, 0x0)
connect$unix(r1, &(0x7f0000000100)=@abs={0x0, 0x0, 0x3}, 0x8)
r3 = socket$inet(0x2, 0x2, 0x0)
r4 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
dup2(r4, r3)
setsockopt$inet_opts(r3, 0x0, 0x200000000000b, &(0x7f0000000200), 0x0)
socket(0x11, 0x1, 0x21)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x2, 0x0, 0x0, 0x0, 0x0, 0x2}, 0x20d)
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
r5 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSTAT(r5, 0x20007465, 0x0)


r0 = socket(0x18, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1, &(0x7f0000002700)=0xffffffff, 0x4)
recvmmsg(r0, &(0x7f0000000540)={0x0}, 0x10, 0x801, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0x3006ff, 0x1, 0x9, 0xd, "feb9fa588f00"})
writev(r0, &(0x7f0000000040)=[{&(0x7f0000000180)="8a9ce4036307187ac8b8804f20f81b83c8ba79d72cbd641e690ca7f75c9e2ad2a284af6a5bf164e818358fefe887e8f8e172d17799657f41aec12efc5febc0ff437185b8532117c1000000002d21797f5acfba4e465810d918cb3e1cf8f06937c71e0b39f64012ce974526e31d1937376a87872c0b286508f6d774d8f5100b51a3275ddb218a808a", 0x88}], 0x1)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
socket(0x18, 0x2, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f00000002c0)=""/49, 0x31}], 0x1)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1800000029"], 0x3e}, 0x0)
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)
getsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000080), &(0x7f0000000100)=0x10)


writev(0xffffffffffffffff, &(0x7f00000001c0)=[{0x0}, {&(0x7f0000000040)}], 0x2)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r0, 0xc020691b, &(0x7f00000001c0))


shmget$private(0x0, 0x2000, 0x0, &(0x7f0000ffc000/0x2000)=nil)


msgget$private(0x0, 0x0)
msgrcv(0x0, 0x0, 0x0, 0x0, 0x0)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
setreuid(0x0, 0xee01)
r0 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmctl$IPC_SET(r0, 0x1, &(0x7f0000000000)={{0x0, 0x0, 0x0, 0x0, 0x140}, 0x0, 0x0, 0x0, 0xffffffffffffffff})
shmat(r0, &(0x7f0000001000/0x3000)=nil, 0x1000)


setrlimit(0x8, &(0x7f0000000980)={0x52, 0x62})
r0 = syz_open_pts()
close(r0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
bind$unix(r1, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
connect$unix(r2, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
close(r0)


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(0xffffffffffffffff, 0x29, 0x66, 0x0, 0x0)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x67, &(0x7f0000000000)={0x2}, 0xc)
sysctl$kern(&(0x7f0000000000)={0x1, 0x47}, 0x3, &(0x7f00000000c0)="3be91ab1ded9ab1f79d4e06e235fa47dc44ed1a04e24f926e97cec247521215f39a634cd83019a560c1183dec3be8e7234b80c3740811cc8661e5a338031708d", &(0x7f0000000080)=0x40, &(0x7f0000000180)="5935bd8e76660d907c045aa6a852a6085f1b0528f526434c7f46bad55fed13c8bca5b717b826048d2269af85d528bb5086c9a14a4c9dcd1cc539c3066ff73adb7e19d50d69a6fb5522ee8a427bbad734d4bb13cd0ee6a7081a76ad71ac7e32ef3ecf252edb184e27fdc4153045be1ccf841ff2e51189508ef04851921d163b97d2a646", 0x83)


r0 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x80, &(0x7f0000000100), 0x4)


sysctl$kern(&(0x7f0000000100), 0x2, &(0x7f0000000040), 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000001c0)={0x3, &(0x7f0000000040)=[{0x5c, 0x0, 0x0, 0x2}, {0x2d}, {0x4000006}]})
writev(r0, &(0x7f0000000240)=[{&(0x7f0000000340)="ebebfd510bbcdda9b489e9775d3e", 0xe}], 0x1)


pipe(&(0x7f0000000040))
kqueue()
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
pwritev(0xffffffffffffffff, &(0x7f0000000340)=[{&(0x7f0000000080)}], 0x1, 0x126)
truncate(&(0x7f0000000100)='./file0\x00', 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000240)={0x0, 0x2000000001})
socket$inet(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x0, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
syz_emit_ethernet(0x36, &(0x7f0000000080)={@local, @random="450b08bfa22f", [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @empty, @loopback}, @tcp={{0x2, 0x0, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})
ioctl$FIONREAD(0xffffffffffffffff, 0x8080691a, &(0x7f00000001c0))
r1 = socket(0x18, 0x2, 0x0)
connect(r0, &(0x7f0000000200)=@in6={0x18, 0x2, 0x5, 0x3}, 0xc)
setsockopt(r1, 0x1000000029, 0x3c, &(0x7f0000000000), 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000240)={0x3, &(0x7f00000000c0)=[{}, {0x1, 0x0, 0x0, 0x2}, {0x6, 0x0, 0x0, 0x8002}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0xff0a, 0x0, 0x37)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f0000000100)={0x10, 0x0, [{&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000b20000/0x1000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {&(0x7f00008e3000/0x4000)=nil, &(0x7f0000725000/0x4000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000400000/0xc00000)=nil}, {&(0x7f0000c34000/0x4000)=nil, &(0x7f000093c000/0x2000)=nil}, {&(0x7f0000da9000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000e0a000/0x2000)=nil, &(0x7f0000648000/0x2000)=nil}, {&(0x7f0000b64000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f000062b000/0xf000)=nil, &(0x7f00004df000/0x4000)=nil}, {&(0x7f00008bf000/0x3000)=nil, &(0x7f0000af4000/0x13000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000ecf000/0x3000)=nil, &(0x7f0000b08000/0x1000)=nil}, {&(0x7f000064c000/0x2000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {&(0x7f0000c2a000/0x2000)=nil, &(0x7f0000518000/0x3000)=nil}], './file0\x00'})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc028698d, &(0x7f00000001c0))
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r1, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
munmap(&(0x7f0000800000/0x800000)=nil, 0x800000)


r0 = socket(0x18, 0x3, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x2, 0x0, 0x0)


r0 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1000, &(0x7f00000000c0), 0x1)
recvmmsg(0xffffffffffffffff, &(0x7f0000000040)={&(0x7f0000000000)={0x0, 0x0, &(0x7f0000000100)=[{&(0x7f0000000240)=""/61, 0x3d}], 0x1, 0x0}}, 0x10, 0x0, 0x0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt$inet6_MRT6_ADD_MIF(r1, 0x29, 0x32, 0x0, 0x0)
socket(0x18, 0x2, 0x0)
socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x0, 0x0)
socket$unix(0x1, 0x0, 0x0)
open(0x0, 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
getpid()
msgsnd(0x0, &(0x7f0000000140)=ANY=[], 0x401, 0x0)
msgget(0x1, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
sysctl$kern(&(0x7f0000000200)={0x1, 0x16}, 0x2, &(0x7f0000000280)="d2a4629fc3395824c3a6abdd47f46546f69cc6e639e3d9a57d4128e369e2a1adea72966b04d93220fd53c6a03539263ddd16b7ef9361d4f95416cf2f6753546a3ec1c85912182e26bc6fd7da32709b62ab10563dbc2c95973738453937ab0b25a707e2e34d09898ac2b42f882f9b6489e71a05f7af1e04ecd3413e1f4c15b192741942fbeb59b27229e76d5cde8ebe4b804ab243884ec79687a1d1603095c3be4c6d4e1d738da1e89662aadf78c9e16781f88083a35e2e4a3150e51a462e175f935429e9d6f1b670f274e061b861b66557563bda038e88ac142d20e7c523df0d36c26bea26cc139b2347f38957a20641229247", &(0x7f0000000380)=0xf3, 0x0, 0x0)
msgget$private(0x0, 0x0)


ioctl$FIOASYNC(0xffffffffffffffff, 0x80047460, &(0x7f00000000c0)=0x406)
recvmmsg(0xffffffffffffffff, &(0x7f0000000c80)={&(0x7f0000000c40)={0x0, 0x0, &(0x7f0000000bc0)=[{&(0x7f00000000c0)=""/67, 0x43}], 0x1, 0x0}}, 0x10, 0x0, 0x0)
r0 = socket$inet(0x2, 0x3, 0x102)
sendmmsg(r0, &(0x7f0000000c40)={&(0x7f0000000c00)={&(0x7f00000002c0)=@in={0x2, 0x3}, 0xfffffffffffffc46, 0x0, 0x0, 0x0}, 0x10}, 0x10, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000480), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x2c}, {0x25}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000d40)={@local, @random="94ea09066dbd", [], {@ipv6={0x86dd, {0x0, 0x6, "db8344", 0x8, 0x0, 0x0, @rand_addr="135e80f1d38ddba80b9e61dd0c575a88", @local={0xfe, 0x80, '\x00', 0x0}, {[], @udp={{0x0, 0x2, 0x8}}}}}}})


mknod(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
ioctl$FIOASYNC(0xffffffffffffffff, 0x80047470, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x1, &(0x7f0000000200)=[{0x420, 0x0, 0x0, 0xfffffffc}]})


openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000080), 0x20, 0x0)
ioctl$VMM_IOC_RUN(r0, 0xc0205602, &(0x7f0000000140)={0xb6e, 0x5, 0x5e, 0x6, &(0x7f0000000300)={{0xfb, 0x7f, 0x2, 0x93, 0x4, 0x3, 0x2}, {[0x80, 0xe93c, 0x100000000, 0x101, 0x4, 0x7, 0x1f, 0x1, 0x5, 0x5, 0x80, 0x7f, 0x2, 0x1, 0xfffffffffffffb7b, 0x0, 0x4, 0x2000000003], [0x8000, 0x7fff, 0x6, 0x6, 0x8, 0x3360, 0x0, 0x5, 0x0, 0x400], [0x3, 0x7, 0x3, 0x9bc, 0xd72c, 0x10, 0x8], [0x80000000, 0x2f9, 0x7, 0x0, 0x0, 0x2], [{0x4, 0x77000, 0x2, 0x7}, {0x6, 0x3, 0x5, 0x6}, {0x16, 0x20, 0x10001}, {0x8, 0x7d, 0x7, 0x9}, {0x1f, 0x8, 0xe76, 0x8}, {0x0, 0x8, 0x289a, 0x4}, {0x20, 0x277a, 0x7, 0x15ea5bf3}, {0x9, 0x22, 0x6}], {0x800, 0x4, 0xfffffeff, 0x3}, {0x4, 0x7f}}}, 0x0, 0x2d})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
mkdir(0x0, 0x0)
unveil(0x0, 0x0)
r2 = openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCGDLTLIST(0xffffffffffffffff, 0xc010427b, &(0x7f0000000300)={0x6, &(0x7f00000002c0)=[0x404, 0x81, 0x64fc5fc7, 0x10f, 0x6, 0xef88]})
accept$inet(0xffffffffffffffff, &(0x7f0000000180), &(0x7f00000001c0)=0xc)
getsockname(r2, &(0x7f0000000200)=@in, &(0x7f0000000240)=0xc)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r3 = socket(0x18, 0x3, 0x41)
ioctl$FIONREAD(r3, 0xc018696c, &(0x7f00000001c0))
readv(r1, &(0x7f0000000ac0)=[{0x0}, {&(0x7f0000000080)=""/31, 0x1f}], 0x2)


r0 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r0, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
setsockopt(r0, 0x0, 0x68, 0x0, 0x0)


sysctl$net_inet_ah(&(0x7f0000000000)={0x4, 0x2, 0x33, 0x2}, 0x4, 0x0, 0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
sysctl$net_inet_ah(&(0x7f0000000240)={0x4, 0x2, 0x33, 0x1}, 0x4, &(0x7f0000000280)="75d916cf2a8090d0d290072b7767c8f7a230b04db693f2dc797b88aba8226f70943858b294786fb13c44dd389971784f6521d74eba620ed9a86f6b2763c00197499d1769407522ff1e3beaff5d826f2d87cd4e9ce982495639", 0x0, 0x0, 0x0)
syz_emit_ethernet(0x3e, &(0x7f0000002fc0)={@broadcast, @random="d28be5230b24", [], {@ipv4={0x800, {{0x7, 0x4, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @remote={0xac, 0x14, 0x0}, {[@ra={0x94, 0x6}, @generic={0x7, 0x2}]}}, @icmp=@timestamp}}}})
mknodat(0xffffffffffffff9c, 0x0, 0x2000, 0x200)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
chmod(&(0x7f0000000040)='./file0\x00', 0x1)
ioctl$BIOCSETIF(r0, 0x8020426c, 0x0)
sysctl$net_inet_ah(&(0x7f0000000180)={0x4, 0x2, 0x33, 0x6}, 0x4, &(0x7f0000000300)="9b9934b28609edbeed6e3c047668202b15ee610a671e29906d9b2f31feccd5ce0017e2445cdf2f6b4de5c622453f7a55b2772f75", &(0x7f0000000340)=0x34, 0x0, 0x0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r1, 0x80047460, &(0x7f00000000c0))
dup(r1)
ioctl$BIOCGRTIMEOUT(0xffffffffffffffff, 0x4010426e, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, 0x0)
syz_emit_ethernet(0x62, &(0x7f0000000140)=ANY=[@ANYRESDEC, @ANYRESHEX=0x0, @ANYRES8=r0, @ANYRES8, @ANYRES64=r0, @ANYRES8=r0])
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x8040691a, &(0x7f00000001c0))


r0 = socket(0x11, 0x3, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xffffffffffffffff})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x1, 0x0)
close(r1)
r2 = socket(0x18, 0x3, 0x3a)
r3 = dup2(r2, r2)
setsockopt(r3, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r2, &(0x7f00000001c0)="00003226a4a9000064e7c803d2a423735d33a4dd72c3b894d1de957eedc56e0380271dc72f5796a20a91046c9782b54e9ebe4819eac1e41bebbc8fc2e5155796116e00a001c0745c0fb366c8c29785b0d6983e036092903b438bee0dd22d219efe232e9cc22761f89554c67e1d9ed3ae72e8352e17bcb4300b3c41577047664b11e0dd9155c39f1ddf1703da62aa7c505bf0229ed8fd3eff829b861046cf6b255de56a04727d21aa78d0fc51b8619d80", 0xb0)
sendto$unix(r0, &(0x7f00000000c0)="b10005136000009f050000b10010000000000000cea10500fef96ecfc727d3357ae302b37b67ca1f2d61db7f4de57804be38164991f7c8cf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f4d335d223e7db3008b95665bc6fc2102000000720fd38bfbb770c1f5a872c881ea772ec5890405b3b9c2668396f4cd1257aea8c500002002fbfc0c2300008abfba0900000008e37f71a3f8343712051eeab71d89e000040381ecb664000000", 0xb1, 0x0, 0x0, 0x0)


syz_open_pts()
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000140)={0x480, 0xfffffffffffffffd})
kqueue()
kevent(0xffffffffffffffff, 0x0, 0x7, 0x0, 0x80000001, 0x0)
socket(0x18, 0x3, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0xffffffffffff0000})
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000280)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
sendmsg$unix(r0, &(0x7f0000000ac0)={0x0, 0x0, 0x0}, 0x8)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000080)=[{0x15}, {0xe, 0x0, 0x1}, {0x8106}]})
unlink(&(0x7f0000000000)='./file0\x00')
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
connect$unix(r3, &(0x7f0000000080)=@file={0x0, './file0\x00'}, 0xa)
getsockname$unix(r3, &(0x7f00000000c0)=@file={0x0, ""/34}, &(0x7f0000000100)=0x24)
bind$unix(0xffffffffffffffff, &(0x7f0000000180)=@file={0x0, './file0\x00'}, 0xa)
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f00000001c0), &(0x7f0000000200)=0xc)
stat(&(0x7f0000000240)='./file0\x00', &(0x7f0000000280))
r4 = semget(0x0, 0x1, 0x0)
semctl$GETNCNT(r4, 0x2, 0x3, &(0x7f0000000300)=""/113)
r5 = dup2(0xffffffffffffffff, 0xffffffffffffffff)
semctl$IPC_STAT(r4, 0x0, 0x2, &(0x7f0000000380)=""/205)
sendto$unix(r2, &(0x7f0000000480)="7d1184", 0x3, 0x2, &(0x7f00000004c0)=@file={0x1, './file0\x00'}, 0xa)
renameat(r5, &(0x7f0000000500)='./file0/file0\x00', r5, &(0x7f0000000540)='./file0\x00')
semop(r4, &(0x7f0000000580)=[{0x4, 0x2, 0x1800}, {0x2, 0x5, 0x1800}, {0x1, 0xb2e5, 0x1000}, {0x0, 0x5, 0x800}, {0x2, 0x7, 0x800}, {0x1, 0x8, 0x1000}], 0x6)
sysctl$net_inet_ipip(0x0, 0x0, 0x0, 0x0, &(0x7f0000001440)="1c31", 0x2)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
sysctl$kern(&(0x7f0000000300)={0x2, 0x7}, 0x2, 0x0, 0x0, &(0x7f0000001440)='\x00\x00\x00\x00', 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000240)=[{0x15}, {0x5}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])


openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
syz_open_pts()
syz_open_pts()
syz_open_pts()
socket(0x2, 0x1, 0x0)
socket(0x2, 0x3, 0x0)
select(0x40, &(0x7f0000000440)={0xffffffffffffffff}, 0x0, 0x0, 0x0)
select(0x7, &(0x7f00000002c0)={0xfffffffffffffffc}, 0x0, 0x0, 0x0)


open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
ftruncate(0xffffffffffffffff, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
unlink(&(0x7f0000000000)='./file0\x00')
r0 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r0, 0x0)
r1 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
accept$unix(r0, &(0x7f0000000480)=@file={0x0, ""/244}, &(0x7f00000000c0)=0xfffffffffffffe7c)


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000002c0)={0x1, &(0x7f0000000080)=[{}]})
syz_emit_ethernet(0x138, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSTAT(r0, 0x20007465, 0x0)


ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105727, &(0x7f0000000000)={&(0x7f0000000440)=[{}, {}, {}, {}], 0x4})
sysctl$kern(&(0x7f0000000000)={0x1, 0x45}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
sysctl$vm_swapencrypt(&(0x7f0000000000), 0x3, 0x0, 0x0, 0x0, 0x0)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt(r0, 0x29, 0xa, &(0x7f0000000000)="ebffcbff2bb9fd812eaa4e710100000000000000", 0x4)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x1, 0x1, 0x0, 0x100000000000000, 0xffffffffffffffff})
r0 = socket(0x18, 0x2, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
close(r0)
shutdown(0xffffffffffffffff, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x36}, 0x2, &(0x7f0000000240)="1b7f5833214ddc84446578229cd25bbb310acb4dc3008398d31bdca4a16d93662d0014840c7df8cf665f7649d91d299214f586f78f587f96c5af4e6106efa45147aafb54bd4c436b832913e6b8d31d7fffffff3148c900000000", 0x0, 0x0, 0xfffffffffffffdcd)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
socket$inet(0x2, 0x2, 0x0)
close(0xffffffffffffffff)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x4, &(0x7f0000000000)="5ab777a5", 0x4)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r2 = syz_open_pts()
ioctl$FIOSETOWN(r2, 0x80047476, &(0x7f0000000500)=0xffffe001)


syz_emit_ethernet(0x36, &(0x7f0000000100)=ANY=[@ANYBLOB="aaaaaaaaaa2aaaaaaa86dd6089328b00000000fc7be31dda4e647e1cfaceb91fcfb1660000000000000000000000000000000100000075233ee47094329304d31d0ed7c2f140f9104c62d13a4e92a8efc205a33cee5aa817aa087d1fa5863446f8aa179eb8faad0aa0848faf722312319e918e2fbf7edd199964a0f94ebfbeceb6e4acd7a8bf5d0a8c6fb11ee1e1c935917deb8df8eb264a90089fd1478fbddc4689a435930c5b7d6785f1859453e8649a36e86c127f45e4847cc50ad2c18703bb3db4f96f7d1e13e339cde568b5794f3f7c0e9e3349afe370e5bc2dfec98a4589fc7b89b851a34e7dbf28371f60cefafa312b2b04f18ca91d"])
r0 = socket$inet(0x2, 0x3, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x24, 0x0, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x70e, 0x0)
socket(0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, 0x0)
syz_emit_ethernet(0x4a, 0x0)
r2 = socket(0x2, 0x1, 0x0)
r3 = socket(0x2, 0x2, 0x0)
connect$unix(r3, &(0x7f0000000a80), 0x10)
getsockname$unix(r3, &(0x7f0000000000)=@abs, &(0x7f0000001200)=0x8)
r4 = socket(0x2, 0x1, 0x0)
bind(r4, &(0x7f0000000000), 0x10)
listen(r4, 0x0)
fcntl$setstatus(r2, 0x4, 0x40)
fcntl$setown(0xffffffffffffffff, 0x6, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$inet(r2, &(0x7f0000000000), 0x10)
shutdown(r2, 0x2)


sysctl$net_inet_ip(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sysctl$hw(&(0x7f00000002c0)={0x7, 0xf}, 0x2, &(0x7f00000005c0)="f0", &(0x7f00000000c0)=0x1, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
socket$inet(0x2, 0x2, 0x0)
socket(0x1, 0x4, 0xff)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
setrlimit(0x0, 0x0)
syz_open_pts()
open(0x0, 0x0, 0x124)
r0 = socket(0x0, 0x5, 0x7b)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
syz_emit_ethernet(0x138, 0x0)
r1 = msgget$private(0x0, 0x0)
pipe2(0x0, 0x0)
msgsnd(r1, &(0x7f0000000300)=ANY=[@ANYRES16=r0], 0x1f, 0x0)
msgsnd(r1, &(0x7f0000000240)=ANY=[@ANYRES32], 0x401, 0x0)
msgsnd(r1, 0x0, 0x401, 0x0)
msgrcv(r1, &(0x7f0000000400)={0x0, ""/137}, 0x91, 0x2, 0x0)
msgctl$IPC_RMID(r1, 0x0)
syz_emit_ethernet(0x3e, &(0x7f0000000140)=ANY=[])
pread(0xffffffffffffffff, &(0x7f0000000040), 0x0, 0x100000000)
mkdir(&(0x7f0000000080)='./file1\x00', 0x106)
chroot(&(0x7f0000000340)='./file0\x00')
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040))
openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x1, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000001c0), &(0x7f0000000180)=0xfffffffffffffe58)
mknod(&(0x7f0000000000)='./file0\x00', 0x2977, 0x0)
pipe(0x0)


syz_emit_ethernet(0x36, &(0x7f0000000080)={@local, @local, [], {@ipv6={0x86dd, {0x0, 0x6, '6/_', 0x0, 0x0, 0x0, @remote={0xfe, 0x80, '\x00', 0x0}, @rand_addr="607ba243b1f577704405a50200"}}}})
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "ff000000ff597bd600"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000040), 0x3, 0x0, 0x0, &(0x7f0000000080)="4f1d4c6344b80ed788b6a4515248df3aa745bb992c574ab4cdf5587145812eab4a988f7fafd7a01d99776d988908cd186b51f34f8c15ffa0c685ad4116c783959eff4278384b4000384dbb1c2aaeff10b4135529a1da6fda67c67469d954be811b25ec5521559154c586eefff122009f659cd3e27e98a3241495005f102d9101d158284c0ee3250aa7c11042330de22a299ab00894fdc9bac6042d", 0x4)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
setreuid(0xee00, 0x0)
r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
r1 = getuid()
setreuid(0x0, r1)
fchdir(r0)


mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x2802)
ktrace(&(0x7f0000000100)='./bus\x00', 0x1, 0x4000010e, 0x0)


mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x4, 0x10, 0xffffffffffffffff, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x1)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
socket(0x1, 0x0, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000040)=[{{}, 0x0, 0x0, 0x0, 0x6}], 0x0, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x881)
r0 = open$dir(&(0x7f0000000100)='./bus\x00', 0x0, 0x0)
fcntl$getown(r0, 0x5)
r1 = socket(0x18, 0x2, 0x0)
close(r1)
r2 = socket(0x18, 0x2, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x100000000000000, 0xffffffffffffffff})
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x6d4)
r1 = open(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)
ioctl$FIOASYNC(r1, 0x80047470, &(0x7f00000000c0)=0x400)
r2 = fcntl$dupfd(r1, 0x0, r0)
poll(&(0x7f00000001c0)=[{r2, 0x2}], 0x1, 0x0)
fcntl$getown(r1, 0x5)
select(0x40, &(0x7f00000000c0), 0x0, &(0x7f0000000200)={0x3ff}, 0x0)


sysctl$kern(&(0x7f0000000000)={0x1, 0x49}, 0x6, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$net_inet6_ip6(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000040)="00000200", 0x4)


pipe2(&(0x7f0000000080)={<r0=>0xffffffffffffffff}, 0x0)
ioctl$DIOCMAP(r0, 0x40047309, &(0x7f00000000c0)={0x0})
ioctl$BIOCSETWF(r0, 0x80104277, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
syz_emit_ethernet(0x3e, &(0x7f00000004c0)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa86dd60362f5f00082b00fe8000000000000000000000000000bb60"])


kqueue()
sysctl$ddb(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
open$dir(&(0x7f00000002c0)='./file0\x00', 0x200, 0x0)
accept(0xffffffffffffffff, &(0x7f0000000040)=@un=@abs, 0xfffffffffffffffe)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
socket$unix(0x1, 0x2, 0x0)
sendto$unix(r0, 0x0, 0x0, 0x40a, &(0x7f0000000080)=@abs={0x1, 0x0, 0x1}, 0x8)
socket$inet(0x2, 0x0, 0x0)
r1 = socket$inet6(0x18, 0x2, 0x0)
ioctl$VMM_IOC_READREGS(r1, 0xc050756a, &(0x7f0000000000))


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000040)={0x0, 0x3, 0x7, 0x200499, "d88c28fa8797f9bdca0988d15554000900"})
writev(r0, &(0x7f0000000000)=[{&(0x7f0000000380)="7e746376ecb3f4b7c3b9648dde9d8c13de18b9e215c4a9cac7034ab89ebf86868d83590bbbc0d90ba99e59ac2ac3a2812db4a42c910ec132c100ff7f737c911d105ade6f74489113b68abf53fec3be6aeb96d1dd0b41272e9a67087a7fbcf181a77e72520b7622324acd62aee319cf3e29c7534ed4beb03e67ea8902030d8222e539564932f2040000000000003e8baddb5ec102383f95df148f2944152806cfcb731235c9b66b30ab00daec0ec87a189a8d240141070000008de968692f4a942984cd03000000000000000b17e13cd9b51d0900000000000000005dee44094817f0371f5dbed0a1360ec95a7ca9c35fc7a4b4053392eb7600f107f3c4337737a7040ea2322bb3d97fb26b218f86637f46c1f649194828bf85b1b5b3504eb7595c53cace06191b6ef66778617ea9c2500ac0fb51a8acd0a28900775565e90a8948d4e135bfa9443ec80e200809736e36f1d2e6fa70a18a645e191e81307c4247050fa07b160471f7d67efa0573046f92e7fe688a048af645668782b094e610876461dc7435dfb23e4275fabb9d24e24ce323f21527f027c6e818c045ea2a9586fd7105e89570d8c33a8455b1d62781d6563c7a2ad57df0f649ce8bc440e8c26693b45319867472884620e65344b01d2eb8eee502324af03719f08a077ee9d57ceae9510c0158899b4d44322006e94fbc6319aa9ed42caf4a1ead787952832b97057a4611a83d721cc389a134bacfc1253f157052ae6b56dfe53c018d74b21085537a7c00d29411a83460a50b4cd94d26542a626f87eceac528b523c3cf047b70b6699c456b9a4d90a2f3b0968809", 0x24e}], 0x1)


sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x8000, 0x2)
open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x400, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000240)={<r1=>0x0}, 0xc)
getpgid(r1)
socket$inet(0x2, 0x2, 0x0)
ioctl$BIOCSHDRCMPLT(0xffffffffffffffff, 0x80044275, &(0x7f0000000180)=0x1)
sysctl$vm_swapencrypt(&(0x7f0000000000), 0x3, 0x0, 0x0, &(0x7f00000012c0), 0x0)
semget(0x1, 0x2, 0x144)
mkdirat(0xffffffffffffffff, &(0x7f0000000040)='./file0\x00', 0x0)
unlinkat(0xffffffffffffffff, &(0x7f0000000080)='./file0\x00', 0x0)
socket(0x0, 0x1, 0x0)
mknod(&(0x7f0000001040)='./file0\x00', 0x2000, 0x3fd)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0xffffff9a, 0x400, "b07f008e00000000000004000000000000004000", 0x0, 0x3f})
syz_open_pts()
r2 = semget$private(0x0, 0x2, 0x0)
semctl$GETPID(r2, 0x2, 0x4, &(0x7f0000000000)=""/4096)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x102}})
sysctl$hw(&(0x7f0000000000)={0x4, 0x18}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x1)
sysctl$kern(&(0x7f0000000000), 0x6, 0x0, 0x0, 0x0, 0x0)


sysctl$vfs_ffs(&(0x7f0000000000)={0x4, 0x1, 0x5}, 0x4, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x1)
sysctl$vfs_nfs(&(0x7f0000000000), 0x7, &(0x7f00000025c0), 0x0, 0x0, 0xffffffffffffff2d)


mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x9}, 0x2, 0x0, 0x0, &(0x7f0000001440)="cca410df", 0x4)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x2, &(0x7f0000000080)=[{}, {0x2, 0x0, 0x0, 0x81}]})
sysctl$kern(&(0x7f0000000080)={0x1, 0x31}, 0x4000000000000004, 0x0, 0x0, 0x0, 0x0)


r0 = socket(0x18, 0x1, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
setsockopt(r0, 0x1000000029, 0x36, &(0x7f0000000040)="03f31241", 0x4)


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
setreuid(0x0, 0xee01)
truncate(&(0x7f0000000140)='./file0\x00', 0x0)


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r1 = fcntl$dupfd(r0, 0x3, 0xffffffffffffffff)
ioctl$WSKBDIO_GETMAP(r1, 0x40047477, &(0x7f0000000180)={0x0, 0x0})


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x11, r0, 0x0)
ftruncate(r0, 0x7)
clock_getres(0x0, &(0x7f0000000040))
msync(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x2)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000000)={0x0, 0x5c66d352a8f45687, 0x7fffffffffffffff, 0x1000200000000})


r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x1b, &(0x7f0000000000)="5ab7776a", 0x4)


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
dup2(r1, r0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000240)="ea", 0x1)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt$inet_opts(r0, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0x8)


setrlimit(0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f00000012c0)=[{&(0x7f0000000000)="c2514bbf316e7fabc6fd17a135260f61611b8b0d214881", 0x17}], 0x1)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
getsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
socket(0x18, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x81206919, 0x0)
openat$diskmap(0xffffffffffffff9c, 0x0, 0x2, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{0x34, 0x0, 0x0, 0xf7d9}, {0x2d}, {0x46}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
open(0x0, 0x40, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x10, 0xffffffffffffffff, 0x0)
ftruncate(0xffffffffffffffff, 0x0)
msgsnd(0x0, &(0x7f0000000d00)=ANY=[@ANYRESHEX], 0x401, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r2 = socket(0x18, 0x2, 0x0)
sendmsg(r2, &(0x7f0000000840)={&(0x7f0000000380)=@in={0x2, 0x2}, 0xc, 0x0, 0x0, &(0x7f00000000c0)=ANY=[], 0x2d8}, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x2, &(0x7f0000000000)=[{}, {0x6}]})
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = dup(r0)
setsockopt(r1, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff2bb9fd812eaa4e713048e69931929648", 0x14)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f00000001c0)=[{0x44}, {0x54}, {0xfe}]})
syz_emit_ethernet(0x36, &(0x7f0000000400)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000000)=[{0x81}, {0x60}, {0x5ce}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


r0 = socket(0x18, 0x2, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r1 = socket(0x18, 0x3, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r1, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff}})
socket(0x0, 0x3, 0x7)
mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x205b9a)
r2 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
writev(r2, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
getsockname$inet(0xffffffffffffffff, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)


open(0x0, 0x0, 0x0)
r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
listen(0xffffffffffffffff, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x3, &(0x7f0000000040)=[{0xc0}, {0x5c}, {0x6, 0x0, 0x0, 0x6df1}]})
write(0xffffffffffffffff, &(0x7f0000000000)="76e5de000001", 0x6)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
r3 = socket(0x2, 0x2, 0x0)
r4 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000140), 0x782, 0x0)
setsockopt$inet6_MRT6_ADD_MFC(0xffffffffffffffff, 0x29, 0x68, &(0x7f00000000c0), 0x5c)
ioctl$SPKRTUNE(r4, 0x20005302, &(0x7f00000000c0)={0x0, 0x5358})
execve(0x0, 0x0, 0x0)
dup2(r1, r2)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
setsockopt$inet_opts(r0, 0x0, 0x1, &(0x7f0000000040)="ee08665d19ac14d5e5134876f197a7728420aef6171504b1c3d4b3830c921bf0817a0000040000006a89dbdf", 0x2c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
sysctl$net_mpls(&(0x7f0000000000)={0x6, 0xb, 0xfffffffe}, 0x3, 0x0, 0x0, 0x0, 0xfffffffffffffe64)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
pipe(0x0)
syz_emit_ethernet(0x36, &(0x7f00000001c0)=ANY=[@ANYBLOB="ffffffffffffffff96a06e4b4c5dffffffff0800490000280000000000009078ac1400bbe000000101440cb4f0000000000000000000"])
poll(0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000340)={0x3, &(0x7f0000000180)=[{0x44}, {0x5}, {0xe6}]})
syz_emit_ethernet(0x4e, &(0x7f0000000140)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{0x45}, {0x4c}, {0x8006}]})
syz_emit_ethernet(0x26, &(0x7f0000000440)={@broadcast, @broadcast, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, @multicast1, @multicast1}, @icmp}}}})


sysctl$kern(&(0x7f00000000c0)={0x1, 0x59}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x1, &(0x7f00000000c0)=[{0x0, 0x0, 0x4, 0xfffffffd}]})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x80, 0x200}, 0x0, 0x7f})
getpid()
pipe(0x0)
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, 0x0, 0x0)
r2 = openat$vmm(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$VMM_IOC_RESETCPU(r2, 0x82405605, &(0x7f0000000480)={0x2, 0x1})
setsockopt(r1, 0x1000000029, 0x2f, &(0x7f0000000000)="0f0f0000", 0x4)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x181, 0x200}})
socket(0x6, 0x2, 0x8)
socket(0x6, 0x5, 0x0)
socket(0x18, 0x0, 0x0)
r3 = open$dir(&(0x7f0000000200)='./file0\x00', 0x80, 0x108)
fchown(r3, 0x0, 0xffffffffffffffff)
r4 = socket(0x11, 0x3, 0xc1)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
sendto$unix(r4, &(0x7f0000000040)="b100050400000400000000000101000000000000cea10500fef96ec0c72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b1257aea8c500002018fbfe0c2300008abfba0900000008e371a3f83437320501eab71d89e0000405f8ffffff13000000", 0xb1, 0x0, 0x0, 0x14)


socket(0x18, 0x3, 0x3a)
syz_emit_ethernet(0x4e, &(0x7f0000000140)=ANY=[@ANYBLOB="aaaaaaaaaaaa7fd67572210786dd6007558300183701fe8000000000000000000000000000aaff020000000000000000000000000001"])


open$dir(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r0, 0xc0206983, &(0x7f00000001c0))


sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
r0 = socket(0x18, 0x3, 0x0)
close(r0)
r1 = socket(0x800000018, 0x2, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x8}})
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x18, 0x2, 0x0)
r3 = dup2(r0, r2)
sendmsg$unix(r3, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x1000000ff}})
sysctl$hw(&(0x7f0000000000)={0x4, 0x18}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x1)
sysctl$net_inet_ip(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg$unix(r1, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="28000000ffff000001"], 0x28}, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
recvmmsg(r0, &(0x7f0000000000)={&(0x7f0000000000)={0x0, 0x0, &(0x7f0000000000), 0x0, &(0x7f0000000000), 0x63}}, 0x10, 0x0, 0x0)


ftruncate(0xffffffffffffffff, 0x0)
open(0x0, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
dup(0xffffffffffffffff)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000680)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x138, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSKBDIO_SETMODE(r0, 0x80045713, &(0x7f0000000200))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000140)=[{0x5}, {0x5}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000240)=ANY=[])


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
ioctl$SPKRTUNE(r0, 0x20005302, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000140)=[{0x3}, {0xc0}, {0x812e}]})
syz_emit_ethernet(0x56, &(0x7f0000000000)=ANY=[])


mkdir(&(0x7f0000000040)='./file0\x00', 0x0)
mkdir(&(0x7f0000000240)='./file0/file1\x00', 0x0)
unveil(&(0x7f0000000180)='./file0/file1\x00', &(0x7f00000001c0)='x\x00')
symlink(&(0x7f0000000340)='./file0/file1\x00', &(0x7f0000000380)='./file0/file1\x00')


sysctl$vm_swapencrypt(&(0x7f0000000000)={0x7}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x1)
sysctl$net_inet_ip(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000140)=[{0x2d}, {0x50}, {0x6}]})
write(r0, &(0x7f0000000000)="7696e5f3d1f18c37cea8615ac7cf", 0xe)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f0000000040)=0x1)
ioctl$TIOCSETAW(0xffffffffffffffff, 0x802c7415, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f0000000080)=[{{r0}, 0xfffffffffffffffe, 0x41}], 0x8000, 0x0, 0x0, 0x0)


r0 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r0, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
r1 = socket$inet(0x2, 0x3, 0x0)
dup2(r1, r0)


socket(0x0, 0x0, 0x0)
ioctl$VNDIOCSET(0xffffffffffffffff, 0x41946465, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x10, 0x0)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
writev(r0, &(0x7f0000000e40)=[{&(0x7f0000000c40)="cc60d3d79a1a7122a5fb9de9ea6ca0b30fb2942ef7652736f10f86d45ae419b2ecf7af93d33b3de1f2c56c0d93da7484095d0d543baf7f0161a025c9c02a561f9a76d06f1eaec7d8df99d6c28b10fa891e47d6c3bba690a611889032ac7b3581d7c92d1c546e59764f061048316871794f0615dd4d8bb1057a61fb177be649004fb56a7d46c856a20d73f050bf29d58b803a676cc3761e8a47857f51d90a4465f9c605ab2829", 0xa6}, {&(0x7f0000000d00)="5ff08de84b4c423a583f91557c748a02cda4cedf13579996073843ec5cbabaadcec85d62a9a497a78307fad2c30eea6356105ec899ba86930f1aed0b3d1156be8cc8f31c165f4886791456171d407c98b070f563309d05582420b8d67dd4935c912b5e3efd816aaa98e9d527ddcf0b5dca1657040731ee29f29b9cd2a71e683a5f", 0x81}, {&(0x7f00000019c0)="2a5f4cd9b73c31d629e8d68e605e5940744ef138960b671d42c56f79fcb70549247e5504e02f85a6099eff9291731e94399a7e966e783d4073ecd5dc8e540f32190bb47050aee3907495ecf7708d1c295a0836f79ba03ea13db12836c2441989726ffbf7fd1da55bfe2caaf081a1ef55599935c0e60cb0866ee48d420b77a6e269bc30b2650349e16792252c6be8bcc6e9ce2b941299ab505e4779fa1960bb7cf924dcbc53c82e76bcd80731a694d12e8a139d8ecef6f5560939054b7842d25cd7396377f39bcfe2a2383feea17b87393cd892b90742631718b1877d8d83d5f66587e3e5b1e129433ead750143a4c51aa46e78e3b1a54a4634eea2846511719b1637b19ea8c96a95332abd69014f53e91a7319a36efb4052387dc6330aa00b5680142650e8dab5eb6b83ff7d0bbf1293338a8d3e8a6dcd7ed4916279eac230dda46e6fcdebe8a4c12d598883d9392da05791e153d905ce1930aebfc5dfc0fc22a88777c9fbc24c0b021189c3503466bf850f59e6649dd0b40d935ba155a9d7e065df6d90a500be9d7e1e77607d495898a8d6c9c48dda88533e75e760dceae91d670f97ebbe68b845c72eb698a9e0389b15cfe768cd4e524dbe939bc2d8363ae3b71a454a0a0378cd1f36565ab9d1b92263688195df65151ee9b8158c7a5280019a38f00ea05142b3cc832ece46e326e36a55d7a30f866ca97da61a3877612f0d9f23c052edf60a430d3a9acbae3d9f14f22f38a1eeac7df37ae17748a960b9e0d265bf6cdec73bd2a7b5f25035d845d936936cbfe6f013f8d7c73eba2bd9876ff6db3224e50e75c051979f4cdc41d28ea54e28f560fb0291cd6b6ba527e0f358ffa46b988f0bdbf801063d2024380071709ac00ed463e08fd1718a857b567d8b3eda143915e943d9530d25ed15743e117be375dc08e241328a53fa05b58c7c72a35d471a72706afce82b6c57eef81444269e06338bfd0af6f6ef6479dcc26aab0b10c7e58572aa507a69831d63c78c947cecda2c57bb8ae6b2ad7862d160b423de941be69928467db10ee4817536196ad0c5cc02a74ba1a1fb467e472f025f200846112b6b3efd298284d8c0cc498fb9203db18e48e34c137d1285120d809a774d56a62b3dbe8f203cb9cf18c33099f5b9651fc7ae41de53842f327fd40bcfaa601a791da1103351a64cc9815ff1f32cde6fbfe4c92f55a9aff41c055d4edce9c656ecd1becb9035bb8bd46cf47bca0dcb1848da94d05d1475c83a48c02f8f808597eaa9e88a4e4b12d0ef95458eeab115cb189fa7e368186bb68610af4651e27feab061c4ada46e8c12d6d33fe32cd40485b02120418a9aaba8f04c17ea1abdcb9e6801f5d8090c0780b3b5ae4382efbb64f62c825527b7e3d60ad9c73ba7f174ea7c7f2d155808052a0ef6ab2af85cf9a758a8c1227c85f2986fc06c5f54807968b18b6b5f9168d0b2de2728689d75f0efaedf79bd8bbbbc1d46b0f6072d46d46687bc92c0b16c4ad36c3fe4c7a2fd030000009052dd78d841464a6b4432342ea973bf18f1f5abd7b2fe7962faef39ff38bd88a40dbab0f8c08541e38efe924f9ec1addbd47362e349bfca42fd62cf18fef8db7d3cbf0b1733d37dcdae5b9c738b8426a1cfa205c9671870210508c614f256d199fb822613518b1a6fccfee08c48f0feae1ca4baaf0a02635282d4f630a8df115dc73e72d9f7b8feb4333b2c796f1d3f2cfb398ba1e9c81584185b8b578bac3c64d667da7d91062f0c2ccec0c9d09e0c15c62e7bc509c3204d054c22d4eac685626e48e25cff2fc382279d9cb941c2ca182b1f65b05ff05db880a37b1e7f9b3d8975558858352bbbea9213a885b7d43451230e0624403baa77839baa33ae92de771ca76319c2353e9f98ea8191fbb686aed6d08e87bcc2bb8084ae02fafbac1a0bba93f0f155fa2d7bc21bf77f116429c6a1373c34d0ff518b73481fcf012c0a9127e8f174695ccd4add75b026bf2935990d5cebc4e74b97ae67a414029252336880232635fce7ed7bf0b069e08e10f7e1cc4d2973dcd2ea0b63f9dc4f4c2db92e03c553afcb1060b12f6b9b4d1d799edceefdfafdae63ad797e400645c149b20f8a10af54db3289441499e122413495c7b32179ab6c274bbdf6dde48ce26f46f07ede9a314c1a73669ee8cb0d854c8a3206dcd4f532d36fa7affca1226962e20ca2c6ca0da1ab0848d23d6f198681911592815c080cead9fe6c81cf0d7ce3578978dbf1dc2f1902e51f740f95b02ebff4cf25ac8d28b8e16998f5e329e9a377a82b5bc227f77c2f1ad505286aac8618799c2363a2d07d229519370be62ef0dde6525df45a7b807759b9ba1c8557bdbecb429432c4e1a84094edda567f1245ba887686342d0a31b7dbe09bd2be75516b255d2bfad9337649e86a29b0a19e16b4059c7c45e9f81db6780af6487a11f9088ea265a99d6e95535e14fe839945f8f7da9bf9142dd12c305bd41bb392cae8eb81b28fda176d4b538f4ddaaed47913cd9149d934ca36879718bbd76a2d7ce11e6294398ea433af6cf53b951974ec96a9527178b6cbad3088a2e2dc75113fa88ede462e68b4d6b63020a45e94fbc6c3e6677d6cffee0e3bf606cd2d4b9fac89f91db8f3a1fb9f506708314249fa5c36912e3cb281acbdec3b080735ae24ebb4bca3c7900c21175435afbe5024a706e90f8ecf257c99cd8b67b5a9c2bdc2bb624201f55882349526f8faf463eecb183635db72a6aef5fa2048d97e6f6c513598f49158050df1efc6b13b8ae396cd6a905c26b94d1d50d361f10c0362a8c246c7dd553dd8b116694aa82ac029c64aa71b8a307793da12f93ce030d3c42443c37b91043687befb7968da97ffe91d45e4fd506ba4d9c5d7fe5ac7433fb6bb3ce471f59ade734d109d2093fa119827b65a360f2128e7e85ab494609b60d6e236ed8a72984f6c75652f5baa07e2e921365af2b819eef58343e65ffb45ba8580d62f5b8a9988f7176c1559f8ede3b1b92e0ff27978fc5225ed1512b605f1fd4fce46e768970b11a7b4802c93eb05a8571887cdc15f69929eadcd1f9d08ed2d6aab2997ffa2102c2d8983a78ad40500d03aa612ecbbdde634b14e980b176f04f99efad82a04001f34d6addb89e0ce629856f5ad401fed1a2c046e1fe18741b24d4253830af94a1defeecdf6f70b430e48d7b2e4ae2fb331322d96e1a361e4dcae1d0865e7ccc4aa58bcbb3ad1ce0b294437887e03088a6bb4c92c3044bb33d2a893975023ad979fb2f84d4842326cf058595398779116245c452e54989df0591238af63c5b187d18457f008f2759ae470282ee1640e92639a46915fb67f22967beb1f46736aa9c90df08f39ee481f6859f9eafdecd473bdc24ef3ad71b4c54dde360f2d550db18af7589c8107f29b0a713b65f039da10c2dc55e408ce0000000000000000078ed1467464fe4041668228316f0fff7c0e0f1a3cc47aae570182197cc3a030a4af7fe2d401b5a13d59b8fe55d48b0667b782cbf1c2e9e491167d87830bb25008aff93c4459a3ce9fd8655a542c6311d91ec6b6bd7935aba1cd01d10439f5e5a3883566c8538edb97c5d2a7c7533d415973729f52dc03134f3d777b7ad07c0f5b0d985ca48fde6cce9ec99f1223f476dcfbb5ef865a3f54459415b25e2031eeb469c83ac68fd77e59c6b6a4b9543a943c4461e47e94d038c63abf2734a3c0e99b95505e13af6cf7b66840dc60e96fb218226ea00b4a577c2effdba43e6adf97cb47c0ce606e87a7834dec04396c1e4f7df59ae5acedfd1d68c87e405fc5d788884686270cb08f0fb15fe8b11589792f9afc11152cd45f43fac6e758588cfaa88874267c3096bd689108bbb0296f3d182df7d46cf7e6b8bb923ba887443c3d2211785e364c1e55d4e9396d950e50cc11ba9a4da70a64f6acbbcd421183eb2c0521054c4f39650409e21a9d3b781725b0c38abce7b4615fa64a9cbf71a19f7e414279a7494d2e66e4e2b2d5ce7027109cfc763a9dcac37065ae80ec0cf3962deec0f9eba3bd7c514a9854ddec6542cf60a1e69cf5d1a73239633675d4ac1f3b0758e69d1d9fb8659f43f07ef6b0b2a7c9740649198b44f3272a8810d374b00c1d49b7f667ed538d89e91e5734f8d6e270aef0a406fcb4072497dd5f25b49d31cfd64f7af2d5b4df72b74c39a66f442ae61aebe1cdb96b660e3248dad3d05bfce3d8630902a565c3a7636220e0435679ce1c45367570dd08722ddfe7f1bf56c44bcab8ef2d0979eeaa569dade4ec34751833d455b31b55edcb9b64f3045725fcd3a08ce0c20b09a437133df5738092eba91430208814b4135b0a64331aff1847ca60426c91e96a029cff039b14462da6e5f9c545980b3712f7fa5f3958d92278194cf6b37ef76e91103d14db403956a7070d87afa81df227f2189926e1265a2872e9d64c64496083caff36dd3c27e961957acb86f0f9a3cbb5ddbb6bf9c62dc102d70d62eea969b1c2c5f42823f76827e918ffa77cc12ca8d31effd0b55529c496da762b6a95d43360ea4e811979ee316e143733f886a6eca5ac76746d4a302ec57b6b4af57c25631d7773243abd400d15274703154dfde2f1a63e075e4b22ed4516dd1496e3f7848bbf19e3215edda64140649d9b1a06975773d5dd0ca9c4bdfd5eb9fb6164aa659e2a8415098dd05496d0b2a20d966a4c9efefa964e007a3b731d3bad501fd21ca564c6155d893c3075c234af6378a12595d8a88ae0518350b75d57fb91b7610bfc3168f548a9a63432b49a9dbee2ee1a4ddd80255e2c655cc80d59d7e90e21fb090db6d59ef84c0becfda6bd01c5a806ce67bea77fdba62ba40e2114d31e6087ad67b28adc20d7cabe7911aa2db119cf5f43b2011bb92556e8e303a264f813764027fbec36f8248a667c766cfc12c80d96965f222d39b5f58a54b255d3b1eb4530952b6d251ff1f9a2cbc585d539704c8ea6884699ebc95d57cd1daef169da86cc10fe7300352e939c35bbe3104aea1b1c681f3e98be8fad7c91bb56724ffa794ea4ac7c4d51d4aad8e94087b4cdcab897e70558e6648ab42dfadab447735912af011fdbd9a47a4958b953b01d2e274449854cb7d4b44d88fb2db162b8dd664c7c32858c7714c69b838cb30b17e6a42ca760256c4c6da57ad5be955ca8c787262d8bd3f4a5f0170e70f92ee2ec9d227d066e41d0d4b640166b2f6937a66bc84506d102d3edac818b246954ba200a3057820da10b64ff99f016b42d90a29b43290d731ef23a72612d646f92acc05620068fd94edd12902197733cc9dbb55d95930ccc749c4a169b4b7056dba24f767da022eb01243353e1f4d0af2eb32e3feb331283ceab3e0112b37556749a701d11ad", 0xedb}], 0x3)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x11, r0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000280)=[{&(0x7f0000001300)="8b", 0x1}], 0x1)
munmap(&(0x7f0000000000/0x3000)=nil, 0x3000)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f00000000c0)=[{0x4d}, {0x61}, {0x6, 0x0, 0x0, 0xfffffffe}]})
write(r0, &(0x7f0000000540)="76e5dead6f01f8607d2100000063", 0x17)


r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x35, &(0x7f0000000000)="5ab7776a", 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x64}, {0x7c}, {0x812e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x8000000000000001})
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


r0 = socket$inet(0x2, 0x3, 0x0)
socket(0x2, 0x3, 0x0)
shutdown(r0, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000000480)={@local, @local, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @broadcast, @broadcast}, @tcp={{0x0, 0x3, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})


open(0x0, 0x205, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r0)
r1 = socket(0x11, 0x3, 0x0)
sendto$unix(r1, &(0x7f00000000c0)="b10005166000009f050000002009000000000000cea10500fef96ecfc727d3357ae302b37b67ca1f2d61db7f4de57804be38164991f7c8cf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f4d335d223e7db3008b95665bc6fc2118000000720fd38bfbb770c1f5a872c881ea772ec5890405b3b9c2668396f4cd1257aea8c500002002fbfc0c2300008abfba0900000008e37f71a3f8343712051eeab71d89e000040381ecb664000000", 0xb1, 0x0, 0x0, 0x0)
getpeername(0xffffffffffffff9c, 0x0, &(0x7f0000000040))
semget(0x0, 0x1, 0x620)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
r1 = dup(r0)
sysctl$kern(&(0x7f0000000000)={0x1, 0xa}, 0x2, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x0, 0x0})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt(r1, 0x1000000000029, 0xd, &(0x7f0000000000)="ffdaf64c000000004f0527000000055e473e0000", 0x14)


r0 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r0, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
r1 = socket(0x18, 0x3, 0x0)
r2 = socket(0x2, 0x3, 0x0)
r3 = dup(r2)
setsockopt$inet_opts(r3, 0x0, 0x15, &(0x7f0000000080)="00000003", 0x4)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r1, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
sysctl$vfs_ffs(&(0x7f00000000c0)={0x3}, 0x3, 0x0, 0x0, 0x0, 0x0)
r4 = socket(0x18, 0x2, 0x0)
r5 = socket(0x18, 0x2, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
kevent(0xffffffffffffff9c, &(0x7f0000000000)=[{{0xffffffffffffff9c}, 0x0, 0x0, 0x0, 0x7}], 0x0, 0x0, 0x0, 0x0)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000000)={0x0, 0x80000000002}, 0x10)
sysctl$kern(&(0x7f0000000000)={0x1, 0x42}, 0x6, 0x0, 0x0, 0x0, 0x0)
r6 = dup2(r4, r5)
setsockopt(r6, 0x1000000029, 0x23, &(0x7f00000000c0)="b211d7170d816684c8e360f2fa41c1a0946988b272d2dd3dc90142a84231a746e337b372e93320cff6669cbe7868de45ed3fc33719ca6df71ecec8a918458b2c10a1f8c66653b276e7aae9cb9b21f9982230f575295d48889c9a920796b2dd92fc8575680b37ba955d2c15e6d7c9198ed900ab006ddfb67869b51a2216114d1ece85f593e74035f5bc054eb1dbddf42a", 0x90)
write(r6, 0x0, 0x0)
r7 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r7, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0x8)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{}, {0x6c}, {0x4000006, 0x0, 0x0, 0x5d8}]})
socket(0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
write(r0, &(0x7f00000002c0)="c5449bc1708e16b9805a099e20a0", 0xe)


mkdir(&(0x7f0000000100)='./file0\x00', 0x49)
setreuid(0xee00, 0x0)
r0 = getuid()
r1 = getuid()
chown(&(0x7f0000000040)='./file0\x00', r1, 0xffffffffffffffff)
setreuid(0xee00, r0)
unveil(&(0x7f0000000140)='./file0\x00', &(0x7f0000000180)='W\x00')


openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r0 = socket$unix(0x1, 0x1, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f0000000000))


r0 = socket(0x18, 0x2, 0x0)
close(r0)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0xfffffffffffffffe}], 0x0, 0x0, 0x0, 0x0)
r1 = socket(0x800000018, 0x2, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x100000000000000, 0xffffffffffffffff})
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
writev(r0, &(0x7f0000000440)=[{0x0}], 0x1)


syz_emit_ethernet(0x2e, &(0x7f0000000000)={@local, @local, [], {@ipv4={0x800, {{0x8, 0x4, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, @multicast1, @empty, {[@timestamp={0x44, 0xc, 0x6, 0x0, 0x0, [{}, {}]}]}}}}}})


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f00000000c0)="b10005010000009f0500070107000000331c13fecea70500fef96ecfc72fd3357ae30200004e30ffd2d236acf20bf404be01000000f7c8cf5f882b297be1aa050400ce94e2f0ad3ebbc257699a1f139b672f335c22db830c032bfa896443c32118210000720fd38bfb0000fd54c125191b1257aea8c500001602fbfe0c2300008abfba0900007db10808f37193f8343712cc1100b71dc000090105000000000000001300"/177, 0xb1, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000000)=[{0x40}, {0x60}, {0x5ce}]})
setrlimit(0x0, 0x0)
ioctl$WSDISPLAYIO_GETSCREENTYPE(0xffffffffffffffff, 0xc028575d, 0x0)
open(0x0, 0x0, 0x0)
syz_emit_ethernet(0x76, &(0x7f0000000140)=ANY=[])
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={0x0, 0x3f8d}, 0x10, 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{0x7}, {0x60}, {0xcc6}]})
syz_emit_ethernet(0x138, &(0x7f0000000180)=ANY=[])
setreuid(0xee00, 0x0)
r2 = getuid()
open$dir(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
r3 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r3)
getrusage(0x1, &(0x7f0000000000))
setreuid(0xee00, r2)
r4 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffb000/0x3000)=nil)
r5 = semget$private(0x0, 0x4, 0x70)
semop(r5, &(0x7f0000000000)=[{0x1, 0x5, 0x800}], 0x1)
shmctl$IPC_RMID(r4, 0x0)
sysctl$hw(&(0x7f0000000040)={0x6, 0x18}, 0x2, &(0x7f0000000080)="c7cc1468", &(0x7f00000000c0)=0x4, &(0x7f0000000340), 0x1)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={<r6=>0xffffffffffffffff, <r7=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000640)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000080)=ANY=[@ANYBLOB="18280000fff2000001"], 0x18}, 0x0)
recvfrom$unix(r7, &(0x7f0000000140)=""/245, 0xf5, 0x41, &(0x7f00000000c0)=@file={0x1, './file0\x00'}, 0xa)
sendmmsg(r6, &(0x7f0000000480)={0x0}, 0x10, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000002c0)=[{0x1}, {0x4}, {0x16}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x4e, &(0x7f00000005c0)=ANY=[])


mmap(&(0x7f0000000000/0xfbe000)=nil, 0xfbe000, 0x100000b, 0x10, 0xffffffffffffffff, 0x0)
setgroups(0x1, &(0x7f0000000080)=[0x0])
getgroups(0x27, &(0x7f0000002540))


setrlimit(0x0, &(0x7f0000000980)={0x1000000101, 0x51})
pipe(&(0x7f0000000340)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
ioctl$BIOCIMMEDIATE(r0, 0x80044270, &(0x7f0000000380)=0xb2d)
r1 = syz_open_pts()
close(r1)
setrlimit(0x0, 0x0)
r2 = syz_open_pts()
bind(0xffffffffffffff9c, 0x0, 0x0)
close(r2)
msync(&(0x7f0000952000/0x2000)=nil, 0x87abbe8d1cc6ad9, 0x4)
getpgid(0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
syz_open_pts()
getsockname$inet(0xffffffffffffffff, 0x0, &(0x7f0000000180))
setegid(0xffffffffffffffff)
r3 = msgget$private(0x0, 0x0)
setuid(0xffffffffffffffff)
socket$inet(0x2, 0x8000, 0x0)
connect$inet(0xffffffffffffffff, 0x0, 0x0)
openat(0xffffffffffffffff, 0x0, 0x20, 0x8e)
sendmsg$unix(r0, &(0x7f0000000280)={0x0, 0x0, 0x0}, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x4a, 0x0)
setgid(0x0)
msgrcv(r3, 0x0, 0x0, 0x0, 0x0)
r4 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x0, 0x0)
ftruncate(0xffffffffffffffff, 0x0)
ioctl$WSMUXIO_INJECTEVENT(r4, 0x80047476, &(0x7f0000000000)={0x5, 0x1})


r0 = socket$inet(0x2, 0x3, 0x0)
r1 = socket$inet(0x2, 0x1, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000080)="eaef125c00000000", 0x8)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000000)="ea00000100000000", 0x8)
dup2(r0, r1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f00000000c0)=[{0x1d}, {0x28}, {0x6}]})
syz_emit_ethernet(0x10a2, &(0x7f0000000540)=ANY=[])


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x8981, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f00000002c0)={&(0x7f0000000240)=[{}, {0x101}], 0x2})


r0 = getuid()
setreuid(0x0, r0)
r1 = semget$private(0x0, 0x2, 0x490)
r2 = getgid()
r3 = getegid()
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f0000000140)={{0x8000, r0, r2, 0x0, r3, 0x88, 0x8}, 0x8001, 0x1f, 0x3f})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
setitimer(0x0, &(0x7f0000000200)={{}, {0x0, 0x7}}, 0x0)
getitimer(0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0xb})
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x4)
shmget(0x3, 0x1000, 0x8, &(0x7f0000084000/0x1000)=nil)
mlockall(0x1)
munlock(&(0x7f0000ffb000/0x4000)=nil, 0x4000)
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, 0x0)
socket(0x6, 0x0, 0x0)
r4 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r4, 0xc0384600, &(0x7f00000000c0)={&(0x7f0000000000)='./file0\x00', 0x3, 0x0})
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
socket(0x18, 0x8000, 0xfe)
semctl$GETVAL(r1, 0x4, 0x5, &(0x7f0000000000)=""/7)


r0 = socket(0x18, 0x2, 0x0)
r1 = socket(0x18, 0x2, 0x0)
r2 = dup2(r0, r1)
setsockopt(r2, 0x1000000029, 0x23, &(0x7f00000000c0)="b211d7170d816684c8e360f2fa41c1a0946988b272d2dd3dc90142a84231a746e337b372e93320cff6669cbe7868de45ed3fc33719ca6df71ecec8a918458b2c10a1f8c66653b276e7aae9cb9b21f9982230f575295d48889c9a920796b2dd92fc8575680b37ba955d2c15e6d7c9198ed900ab006ddfb67869b51a2216114d1ece85f593e74035f5bc054eb1dbddf42a", 0x90)
sendmsg$unix(r1, &(0x7f0000000780)={&(0x7f00000001c0)=@abs={0x0, 0x0, 0x0}, 0x8, 0x0, 0x0, &(0x7f0000000600)=[@cred={0x20, 0xffff, 0x0, 0x0, 0x0, 0xffffffffffffffff}], 0x20}, 0x0)


setgid(0xffffffffffffffff)
sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x13}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000040)={0x6, 0x1b, 0x2}, 0x3, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x3f}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0xfffffffffffffda3)
setgroups(0x0, 0x0)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
socketpair(0x1, 0x2, 0x0, &(0x7f0000001640)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
recvmmsg(r0, &(0x7f0000001dc0)={0x0}, 0x10, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000040), 0x0)
r1 = syz_open_pts()
ioctl$TIOCSETAF(r1, 0x802c7416, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x0, "226fcf009fe10000000080000000000000010010"})
read(r1, &(0x7f0000000100)=""/140, 0x8c)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
bind(r2, &(0x7f00000002c0), 0xa)
connect$unix(r2, &(0x7f0000000000)=@file={0xd1653077bafa0115, './file0\x00'}, 0xa)
mkdir(&(0x7f0000000640)='./file0\x00', 0x0)
chdir(&(0x7f0000000140)='./file0\x00')
symlink(&(0x7f0000000200)='./file2\x00', &(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
open(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
r3 = semget$private(0x0, 0x3, 0x3c0)
semop(r3, &(0x7f0000000080), 0x0)
rename(0x0, 0x0)
semctl$GETPID(r3, 0x3, 0x4, &(0x7f0000000680)=""/8)
semop(r3, &(0x7f0000000280)=[{0x1, 0x7, 0x1000}], 0x1)
semop(r3, &(0x7f00000002c0)=[{0x4, 0x0, 0x1000}, {0x0, 0x420}, {0x1, 0x2}, {0x0, 0x3, 0x800}, {0x2, 0x204}, {0x3, 0xfff8}, {0x2, 0x9}, {0x4, 0x1, 0x1000}, {0x2, 0x7e7}], 0x9)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000002540)={0x0, 0x0, &(0x7f00000001c0)=[{&(0x7f00000000c0)}], 0x1}, 0x0)
ioctl$WSKBDIO_GETMAP(0xffffffffffffffff, 0x8010570e, &(0x7f00000001c0)={0x0, 0x0})
r4 = socket(0x11, 0x3, 0x0)
sendto$unix(r4, &(0x7f0000000500)="94010504000000000000002797888fd1f838a311000000000000b13886ca3849451ae3c3051020741038f5538551f30ce390500e08fecea11ea8fef96e4fc748e93f0b780486aebdbe781e4d8f5eef9187a869a4d3a4cbba982fd825582fe223ed00f4c8b2ca3ebbc259699a1f132e27acb5d62934e4fd89070000000000000070c1f5a872c88dff7cc53c894303b2a0a85ff3faa800000000009ec7ab3a34c29000000000000000000000000000002d7e4a5d76cc3f9cff2ed2243e56fa277603c5cc1e047326bcf6b67b75d00bf6ee330b6a80874b70559d9975ebd13da2447a78aa4b00cd0ba1870215607bb912e3d7325183ce69456b4b6ca927871c81672a54ec695c5bdeb842836656f917945cc076f87dc714dfe0aa2947252df350707b22884a7730cb6dba8742110fbe9ec7481885274387e0b1dbe5695122604819b0b2294b7b20726a5d4fcb44f62d00fabb2f247a166d8d79d05b8cc370f5c11db58aedca632a83acd58ff0ea0a3dca58ccb03cce466cda735017196ff346c32717397d6ec6952ec90de81ed297b2509e130f0000", 0x194, 0x0, 0x0, 0x0)


sysctl$kern(&(0x7f00000002c0)={0x3, 0x1}, 0x2, 0x0, 0x0, 0x0, 0x0)


r0 = syz_open_pts()
r1 = syz_open_pts()
r2 = syz_open_pts()
syz_open_pts()
r3 = syz_open_pts()
poll(&(0x7f0000000040)=[{r0, 0x84}, {r1}, {r2, 0xe65dc00084cf4bdf}, {r1}, {r2}, {r3}], 0x6, 0x235)


r0 = openat(0xffffffffffffff9c, &(0x7f0000000040)='.\x00', 0x0, 0x0)
lseek(r0, 0xffffffffffffffff, 0x1)


r0 = open(&(0x7f0000000200)='./file0\x00', 0x200, 0x0)
fcntl$lock(r0, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000001})
open(&(0x7f0000000200)='./file0\x00', 0x210, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
close(r0)


getdents(0xffffffffffffffff, 0x0, 0xfffffffffffffd8d)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r1, 0x8020690e, &(0x7f0000000100))


sysctl$kern(0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r0 = socket(0x2, 0x3, 0x0)
r1 = socket(0x2, 0x2, 0x0)
r2 = dup(r1)
setsockopt$inet_opts(r2, 0x0, 0x22, &(0x7f0000000040)="fd0cc085", 0x4)
dup2(r2, r0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r0, &(0x7f0000000000), 0x10)
write(r1, &(0x7f0000000080)="77122f1bcfab543f", 0x8)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x1, 0x0)
pwrite(r0, &(0x7f0000000000)="a6158034f9edea5f0aae33255c7b33ef2c2f2df81183ccf446c169dcd3aafe08fef589560c4ac9dacd44ac0ee6cc1479a6c5153fed0395949524842e4f6e99633f1210276d950a9d2b814b96f6f36c39", 0x50, 0x0)
execve(0x0, 0x0, 0x0)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x7})
syz_emit_ethernet(0x1b, &(0x7f0000000000)=ANY=[@ANYBLOB="fffd640000000000000000000a"])
sysctl$kern(&(0x7f0000000000)={0x6, 0xb}, 0x5, 0x0, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f00000001c0)=[{0x80}, {0x24}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0xffffffffffffffff}})
r0 = geteuid()
chown(&(0x7f0000000340)='./file0\x00', r0, 0xffffffffffffffff)
r1 = getegid()
r2 = socket$inet(0x2, 0x3, 0xff)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000540), 0x8000, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r4, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000100)=[{0x5c}, {0x25, 0x0, 0x0, 0x4}, {0x6, 0x0, 0x0, 0xfffffffd}]})
writev(r4, &(0x7f0000000140)=[{&(0x7f0000000080)="35b5c242413c1026089a59583cc3", 0xe}], 0x1)
r5 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000580), 0x800, 0x0)
r6 = accept$inet6(0xffffffffffffffff, &(0x7f00000005c0), &(0x7f0000000600)=0xc)
r7 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40001928, r7)
ktrace(0x0, 0xa5f3b150e570ff1d, 0x11c, r7)
r8 = getuid()
setreuid(0x0, r8)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000640), 0xc)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000740)={&(0x7f0000000140)=@file={0x0, './file0\x00'}, 0xa, &(0x7f0000000180)=[{&(0x7f0000000200)="eca04f101fd653ea6f747a43aec52b65a0652855d76a63e56344cb27503e6c69ac1b52ede09e649d9f7f045b39e284c2c0818b100ed8581e5b9b0795e416e627028d30ce39c876401c5a9651f42fcc593bda3d0eb278aadef1f6fe4221a84a2fad46f32b83e74f36a5fdefd9d3f0b59417098a111b2cd585c4dd29f0489d9cf98b3d7a338660a1dbd0c4ca8bf063c0f34c2b9479351707499ff2f052378f76ccead97742507a37289bfa", 0xaa}, {&(0x7f0000000300)="43d171e50d052ee0a33f7087e5e978e226b2b048140e75ea36a8c122307a8c00c51fdb42066eac844d4cadb7e4b8654ee86a418d980b5cfbd12ec8c1805f99f9711247bd674c575f6a1e036986f3c932a76dcadebe21c44fe0a986d2add1b70e27100933f9c708e209a554b73fdd2aea84cf391eb7e4c501cd6d1fe1c837421266048106b068159671a333443040205061df0085a24a5c59086a4b45069ca7112f1af3f246a7dfa56f", 0xa9}, {&(0x7f00000003c0)="c1ca9bd2119232edc6b75110a82dfc01b3f9e809700398177b1c365d18ee362db7b2a0520175a9d5009e076773ec856a37e69700f0307e520b96c7b70e6415b8a6b419c3a85ed5ef7cb7d07493e8adf55e4bd8", 0x53}, {&(0x7f0000000440)="13936c9ee7e0c239289315ec0c256f611df5a08c2ca1de75fefb2309c751007c1d15371b46b50f1fec8083414485e8bb3200719ab0ff7d3515a20053fad35d1c308304e8e8588feb7cc5c3236156c5cf60e70e6a8b575f4d28c4e12c3be782cc60b6b1fca074f198bef49dacc680bfc01f5a8309e2e88a68aa4640a395cf876f6c96a28463e955b6cd28781a779e1584a578bbba498305fe883b100f61c4eb785b0e7950a4c08d3d6a8ef5b8fa61ebda06944257c6b6f9590096ce047961fd773397151b8ebc738d9140ccda4a2676d9b0b36a68fcd5", 0xd6}], 0x4, &(0x7f0000000680)=[@cred={0x20}, @cred={0x20, 0xffff, 0x0, 0x0, r0, r1}, @rights={0x28, 0xffff, 0x1, [r2, r3, r4, r5, r6, 0xffffffffffffff9c]}, @cred={0x20, 0xffff, 0x0, r7, r8}], 0x88, 0x6}, 0x6)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r9 = socket(0x18, 0x3, 0x0)
connect$unix(r9, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r9, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
r10 = socket(0x18, 0x2, 0x0)
r11 = socket(0x18, 0x2, 0x0)
connect$unix(r10, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
dup2(r10, r11)
sendmsg(r11, &(0x7f00000002c0)={0x0, 0x0, &(0x7f0000000880)=[{&(0x7f0000000080)="8a07fc059328491804424a11b2fa028d6cdea11cc55e5eea3e712fd225f505867123b7f479d6809197b7abb245a6a90d101904863d6e9a", 0x37}, {&(0x7f0000000180)}, {&(0x7f0000001300)="349409068a157a5d1cd1898fdd78cf8ebee5129ab0adf53061d63d4e70ae40ab544d00f5ca6775ae4f9c1076db79108ccedc8e3783e2a86cfc619429c6ab373acab96b35e818ce5154edd20e074dbe033ba9c2af6527497f77063821ec83053996276228d6d5dbc7c13718ca1113bea34ab01fc2932518b5cf93c3a051aade6f26347a74540c310eceaf2304da2d4c37d7b6d0666a67ea50ecf1d2fb7336a52f08695592437406e2ad9d4c9ffbd260dce6a9eff53832111728a7b100fe85beeae0825a2adc97dc1d3eee31d6e482e19f50d8f03b7e92621c09de112e7663521ecb604ad3c5f7902647371e116514953405a10bc3bc5a010d9eacb8f4ede38de585066aaa8ee9dd4886ca2cad43144bd0f3c0809f05382fe0b1b018cd0a1bc3b61c0dadfbc11e7939b47897df90a75084cd4fe203623abc7bd607a2ebc5e8ff0a933cb3498567a9a2941a063d86e263090c95ef9faf103139fa509fd5c76a0652b1e2234816e854812ccac047dad28403551275abee2de74a226ffd6dadbf7b5f550c7f46fab2e11be5af4fc7bbfcbe42885f9d90ebf01523a97dc84416bb4cb755cb7d3268ca6242aa1e0c8bee4bc0efd34a28485acf30427cda6125bd71de4b53a615105e19bab53514e8b1c6f59461cb0c3b4cbb0eb88d3da0534d20a665096e396278f7d4e0789588f420df9b7025f9dec8d2f4deab15687d69a056537b44723c2c12bfc1ed2a57b6b1fa3fff9587e81272484babaf3ca670099edc163a40d67931a457fab205604347d078bc6069602a1ec600475be8d3e0beb8e2528a5bb3d937ff37000c487f7d14f5b8689bc77566719be278e2bf3a293417498c34989d159b7ab42a6d4e0a83df7d4e96f8c537c47cd3f50c19b5576a1830f51b7dd8505607401263dc37e733e5d9e6be4c4a3ce3430228a21ede7d7ad81572f33688fcf39585a9b94169107b8cd092d5bf8861177be35ab14ada48e240f90ff38556173573fe1e3697f27a94a472397b1528fc7269a83576ce8a49f9b4395ba565bb9645818f58ec1d863c61a52d7a6dde3cbf3ea0ccdfe225cd696783685784ca798e4f700c47fbc159b2b41c6573b63061ee61326545d0d815d209b6b07ffde9750a423d4ee028c8ed2ad847ed21bdb58a19c6b4af36b916bbe47272bd33cbdb2bcaaafde3be906ea31ff2f123cc77868ffcbe9cf359390daaf4377101d8454e20cddf100084c0c0688a67d6772c945d27581eb4a1b2e40b1ffe2351ea98114d14d2e4bf3df16e45ce2def4aa9d845a04a27325a697acedfb23e891eabc1e6c8df87f02dc96ad245b3f884b75ff7d6fc421eeb924595daf33bbab051533a9927706a845f92cbae3277a4092a1acc93f7db688de0622c0680b96178015232b5db6a347bb8635b1792b43998c0703519e7ed1a34d66c806e10c70405a6bbe9c62433083d7108974224d0eb76f271b317749ec4b797cadc773d3d3314d9dad7510283080372917e00860d29baba7ca6145fb582468ef85d98b5068d7d25679386c723c47b3fac841731ab44d8935159a4f0d40a937df2c26aa6d6208992487648bcf8cc29d05cb447636561a532b0006ecd363340285cab33fc67d99305b38e66d533a089c20c9c64e96c6246f3c9a6f97bad3ef1abc0854d5619aeeba72cfb62a053245e32916987175e2f527ed6145dad3d46f98b10414c9180dc2c9b01eb2b6e9a58b96547700329febf9a2d9fe9325e5e35e758559ee4648ae2bd392036496b473270cdf3c6083d67ed4752e8107fff174d787ee1067af50f2e12ad33636ca1e3e1b0b98026c1d7214390d53990a84e864b8320cbb9e21d6db32b700265386e8bd338b6b601736ab8d1d8871356ec79fef672aba8074d8acf07def315220bcff5fb03d5e7e57b1ff26732ab9fd571c2876265481f8eaae49b13c840ead6231e7f237a9fc4ed83c3588a3dee05fea7aaaa5aff8e152c8d5c356e1756b2aeeae4d778718f08847421263f2080267144f1eefa5539f8c5b320cddfd4042795822545583bd56951f3f0760b9f0f74a481f29d11c1518bca77320b96a154571c627d7b1d57f910d002b51be7b2a4c7964953c6b80d5b182b7b2227211084c6b036473143f5244ac3e3b392792c661166d694927a8cd948c2a5bb7bf10cf314cfd85f86077b41e9b34c2dee93e671a50a5fafbfcf73f64f5a1afc92d194e310d3b819b90bab16ec7aec59c176dd463c955c14d718b49ae2bc812dcc30d32ab9c83156ae7aafd507bf9901c367c84e292f0af9ea29d2705655f54223f80eee9466faa5cbc4d46ddf62b37acf12063af4024ac1e336bb457b3c2bc0f66c6418c657012bb3aecc900c16b39b86f02894fcc60da0661d0669eda1397aaea4658813ad3868b6693a02be0ff75f64a672255dcc85562fd9d52d97d3f7c911ff9de786bd607abfc6e21d06d22edc93b1c95155c5e998b1bc45b3a544cd698eaeec65322d6b7df4507b19f77d15e8856d15da2abf2be48523eeb5a9971afc617e215861740629b9f0ac1e42d0d904ebcd70e207717c16a57f938b823644cc091a2fe85dd066538318bc2cff34cd4231164ea06300b4d1de763b7eb0fe7c8600a44647e6a760eaf9e91a1482bc3a39c749a426f990db81b5a930d614fbb295d1edda9be352961685b4cd477f3db580f04ee59f27c27f212efb82089f2d71d6951bec7146efa7e392cff3776eb2d10021255a749859a082a265e43eb60896029b6af3ee4e68c02ce2e150045d856fbfca1bb1599169f492722de75dfb81ea0579a9789a1b1a964f534feea3e62d670bd4be55f84a932f644aab077bff3fa9c110224b4e381965f4", 0x7df}, {&(0x7f0000000780)="c9250a7d11855283c1b5678c6a3cc3c40b687ebebc25f46967c2ca8d725186f3eaba335c1402708d96f9864a6c093bc51e90148981c424572318b634e66e32aa725fc072810bc6d9195c58b2b0cbcf7014ba72f227cbf02998a874c5d05fcc80193edbed2af76fc9134a977e7f94d6f626791e0993073fb081af124836d45b4c7bfce1f591bde76031f7210ce47c56f6436b0810b234a4e478ed5898afb2df4f00ead8b254c97b4ffe239a9a023a7e8a96ee453ab17e472fdf83392da7d9cad730690610ee0655626f9aaf30a8f5cba4d198aa33809d2958016ca22d41028075d7866fad73a26971d6b141d537b76a5286f340a21416431dc8", 0xf9}], 0x4, 0x0}, 0x8)


close(0xffffffffffffffff)
socket(0x0, 0x0, 0x0)
listen(0xffffffffffffffff, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x0, 0x0, 0x0)
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000080)=[{0x4}, {0x3d}, {0x6}]})
syz_emit_ethernet(0x1db, &(0x7f0000000100)=ANY=[])


r0 = socket$inet(0x2, 0x3, 0x2)
r1 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r1, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
setsockopt$inet_opts(r0, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)


sysctl$vm_swapencrypt(&(0x7f0000000000)={0x2, 0x5, 0x2}, 0x3, 0x0, 0x0, &(0x7f0000000080)="b8edac04076f400049fa74e21b972189c90d7c8bddd1d7212cf543201d060b2e9387f5422385d06a5b1c5e6d4dbb3c2ff55b763a5609e7b13cc217f64a1c459d66bf043f1113201f8479678e64", 0x4d)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r0 = fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
recvmsg(0xffffffffffffffff, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(r0, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
recvmmsg(0xffffffffffffffff, &(0x7f0000000040)={&(0x7f00000000c0)={0x0, 0x0, &(0x7f0000000580)=[{0x0}, {0x0}, {&(0x7f0000000240)=""/90, 0x5a}], 0x3, 0x0}}, 0x10, 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x1, 0x0)
close(r1)
r2 = socket(0x18, 0x3, 0x0)
r3 = dup2(r2, r2)
setsockopt(r3, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


getsockname$inet(0xffffffffffffffff, &(0x7f0000000180), 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x400000051})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000080)={0x20, 0x7fed, 0x5, 0x1603519, "1a0001ad090201070000200007791dcebf00"})
writev(r0, &(0x7f0000000000)=[{&(0x7f0000000ac0)="a2de4b8e565f2bb52773d5616cabb69cc1a7a14051d04a27b5cb057d5ec186c897764a6fafeca04412715ba10e7ca93a9707b7cbd754867d0e0c8b7d17024a0065d70589e2daf7b535b109449a2bc51dc2889b09657923e30afb1295c5da1adf4193324f9129900fdd105dfdb1b164c6d77275ccdb3ad35ea196c329b7d6fda0dff1cdfabc9911929ed856c5cf1af29612ac0e5d565e6c5b3a679f459013a54eb9c6883ae71e629b9dee9bf29955832d2dd6eadb9043b7967d9fc8426daa8a4f5563e0362a1bf39ccc41dbb3904202c1e6011925e7a12194ccd6a093a7bdfcd611372cdac340948a8df5060ba7b1e8bd16a5bfd317976e4729855241e2c0123f641c2daf5939a4f1667a91590eac28f3929181", 0x113}], 0x1)
rmdir(0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0x0, r2)
syz_open_pts()
openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f00000000c0), 0x80, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x10a, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0xfc, 0x3, 0x1, 0x0, 0x2e, 0x0, @rand_addr=0x1}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x1, 0x0, 0xa, 0x40, 0x2, 0x0, 0x233, {[@generic={0x2, 0xd, "96c729637cae4fa49c1558"}, @sack_perm={0x4, 0x2}, @generic={0x0, 0x2}]}}, {"d1c2f0bfe2d0786ca28e44289f59aba04d62ff16e6bb47f1cd981d0cf5f225560531db5a3a6c3cb3d5ac50e0eec7423f3ef5e3c4a13f81f14f843a32b529e4649b57d581159522ddf03a6cabf358af4e1ae7ab79a9aac6417859ae29d8de08ba3da1e6387381a61f166b78d7ae58ccd15a08555c8e7db3e261cbba4f565ff3567edfcacd1a43a2f80b44a3727c2f46723f3826d9842357f4d467cb2e24ed586547d107e74cfe46502dde741762fe8ad6742200cf5fd16fcdadae4fd744b73028"}}}}}})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f00000001c0)=[{0x14}, {}, {0x8106}]})
syz_emit_ethernet(0x62, &(0x7f0000000140)=ANY=[])
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
socket(0x0, 0x0, 0x0)
syz_emit_ethernet(0xba, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
close(0xffffffffffffffff)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000700)=[{0x48}, {0x2c}, {0x6, 0x0, 0x0, 0xfffffffe}]})
write(r0, &(0x7f0000000540)="76e5dead6f01f8607d2100000063", 0xe)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)="000001ad", 0x4)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
r2 = dup2(r0, r1)
ioctl$TIOCSETD(r2, 0x8004741b, &(0x7f00000004c0)=0x2)
readv(r1, &(0x7f0000000000)=[{&(0x7f00000000c0)=""/199, 0xc7}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000100)=[{0x44}, {0x28}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])


open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000001})
flock(r0, 0x1)
r1 = open(&(0x7f0000000400)='./file0\x00', 0x0, 0x0)
fcntl$lock(r1, 0x9, &(0x7f0000000140)={0x1, 0x0, 0x0, 0x269000000, 0xffffffffffffffff})


setuid(0xee01)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
ioctl$FIOASYNC(r0, 0x8004667d, &(0x7f0000002d00)=0x9)
r1 = getpid()
fcntl$setown(r0, 0x6, r1)
shutdown(r0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x25}, {0x81}, {0x16}]})
write(r0, &(0x7f00000001c0)="d9537abde93d050cdd16b13f742a", 0xe)
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, 0x0)
syz_emit_ethernet(0x138, 0x0)
socket$unix(0x1, 0x0, 0x0)
read(0xffffffffffffffff, 0x0, 0x0)


open$dir(&(0x7f0000001640)='./file0\x00', 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x14}, 0x4, 0x0, 0x0, &(0x7f00000010c0), 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000680)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000300)=[{0x87}, {0x2}, {0x26}]})
syz_emit_ethernet(0x3e, &(0x7f0000000240)=ANY=[])


open(0x0, 0x615, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
unlink(&(0x7f0000000000)='./file0\x00')
r0 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r0, 0x0)
r1 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
accept$unix(r0, &(0x7f0000000480)=@file={0x0, ""/244}, &(0x7f00000000c0)=0xfffffffffffffe7c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000080)=[{0x34, 0x0, 0x0, 0x7f}, {0x2}, {0x40e}]})
syz_emit_ethernet(0xe, &(0x7f0000000100)=ANY=[])


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x4, 0x1100, 0xffffffffffffffff)
ktrace(&(0x7f0000000040)='./file0\x00', 0x4, 0x112, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
close(r0)
r1 = socket(0x18, 0x2, 0x0)
close(r1)
r2 = socket(0x18, 0x3, 0x0)
setsockopt(r2, 0x1000000029, 0x31, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmsg(r0, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1400000029"], 0x3e}, 0x0)


setrlimit(0x8, &(0x7f0000000100)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
select(0x40, &(0x7f0000000280)={0x10374}, 0x0, 0x0, 0x0)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, "ffff09009cef01098b748200"})
r2 = dup2(r1, r0)
ioctl$TIOCSETA(r2, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x7ff, "2cf9892af9a590e4cb52e88608007673ca9e5fd7"})


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r1 = syz_open_pts()
getrlimit(0x7, &(0x7f0000000040))
close(r1)
r2 = syz_open_pts()
ioctl$TIOCSETAW(r1, 0x802c7415, &(0x7f0000000000)={0x0, 0x0, 0x9, 0x6bf, "28113bb1e6648a1a267bc03b7a447ab255dcd9f0"})
readv(r2, &(0x7f0000000140)=[{&(0x7f00000000c0)=""/121, 0xb3}], 0x1000000000000203)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r3 = socket(0x18, 0x1, 0x0)
r4 = socket(0x18, 0x1, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x1, &(0x7f0000001240)=0x6, 0x4)
r5 = socket(0x18, 0x3, 0x0)
ioctl$FIONBIO(r4, 0x8004667e, &(0x7f0000000080)=0x1)
connect$unix(r5, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r5, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
dup2(r4, r3)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
mknod(0x0, 0x0, 0x0)
open$dir(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x3, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000003380)={@broadcast, @random="ecd5f06a9aa8", [], {@ipv4={0x800, {{0x8, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @multicast1, @remote={0xac, 0x14, 0x0}, {[@ra={0x94, 0x6}, @rr={0x7, 0x3}]}}, @udp={{0x3, 0x2, 0x8}}}}}})
close(r1)
r2 = socket(0x18, 0x2, 0x0)
r3 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x1e, &(0x7f0000000240), 0x4)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r4 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r4, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
sysctl$net_inet_ip(&(0x7f0000000180)={0x4, 0x2, 0x0, 0x13}, 0x4, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
mknod$loop(&(0x7f0000000140)='./file0\x00', 0x0, 0x1)
sendmsg$unix(r0, &(0x7f0000001700)={0x0, 0xfffffffffffffe0b, 0x0}, 0x0)


r0 = socket(0x18, 0x2, 0x0)
close(r0)
socket(0x800000018, 0x1, 0x0)
mkdir(&(0x7f0000001140)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0xc5)
unlink(&(0x7f00000001c0)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//file0\x00')
chmod(&(0x7f00000000c0)='./file0\x00', 0x21e)
mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000001380)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000480)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f00000006c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000580)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mknod$loop(&(0x7f0000001040)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/file0\x00', 0x0, 0x1)
chdir(&(0x7f0000000a80)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38/\x00')
rename(&(0x7f00000007c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000a40)='./file0\x00')
open(&(0x7f0000000140)='./bus\x00', 0x0, 0x0)
semop(0xffffffffffffffff, 0x0, 0x0)
mknodat(0xffffffffffffffff, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000002180)={0x1, 0xa}, 0x2, &(0x7f0000002400), 0x0, 0x0, 0x0)
sysctl$net_inet6_ip6(&(0x7f0000000b40)={0x4, 0x18, 0x29, 0x2}, 0x4, 0x0, 0x0, &(0x7f0000001480), 0x0)
sysctl$net_inet_tcp(0x0, 0x0, 0x0, &(0x7f0000000040), 0x0, 0x0)
chdir(&(0x7f0000000080)='./file0\x00')
r1 = open(0x0, 0x0, 0x21c)
close(0xffffffffffffffff)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r2 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000480), 0x0, 0x0)
ioctl$VNDIOCGET(r2, 0x41946472, &(0x7f0000000700)={'./file0\x00', 0xbad4})
linkat(0xffffffffffffffff, 0x0, r1, &(0x7f0000000f40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x1, 0x0)
writev(r0, &(0x7f0000000080)=[{&(0x7f0000000440)="f4224d76d1203d7b5bdd30df670715d7761f779255a953ce0b82d560ddb6258959ddbc6ffc8c6c0ca1b7e505e8746afc2e7c88719770085b4385cf20238415f39fc96f8f37804fb78787967723b00c5828ae", 0x52}], 0x1)
pwrite(r0, &(0x7f0000000000)="a6158034f9edea5f0aae33255c7b33ef2c2f2df81183ccf446c169dcd3aafe08fef589560c4ac9dacd44ac0ee6cc1479a6c5153fed0395949524842e4f6e99633f1210276d950a9d2b814b96f6f36c3938", 0x51, 0x0)
execve(0x0, 0x0, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
socket(0x1, 0x2, 0x0)
r0 = socket(0x2, 0x3, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
r2 = socket(0x18, 0x1, 0x0)
r3 = dup2(r1, r2)
msgsnd(0x0, &(0x7f00000000c0)=ANY=[@ANYRES8=0x0, @ANYRES32, @ANYRES64=r3], 0x298, 0x0)
ioctl$FIOASYNC(0xffffffffffffffff, 0x80047460, &(0x7f00000000c0)=0x406)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r0, &(0x7f0000000000), 0x10)
setsockopt$inet_opts(r0, 0x0, 0x1, &(0x7f00000000c0)="9876d692a3ef9c7ab923a2f0", 0xc)
write(r0, &(0x7f0000000240)="14bdfa5d1d34e2fecb284a6498307dcda9aec43050036123339a346f737850551408753f95b7688ad4c4e1dd5489e7bafc58d3e5823757ae8b630719ef187ccad995f13dbe19a6dd4e6902bd8297b0799b426aabe9fad9db6996571c6d9f8bb5d542c2148aa42be940970fe88d34d8f99afe7e7820237400000000008000000100"/138, 0xfc7e)


setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
sysctl$hw(&(0x7f0000000000)={0x6, 0x1}, 0x2, &(0x7f0000000040), 0x0, &(0x7f00000000c0), 0x0)
setreuid(0xffffffffffffffff, 0x0)
socket$inet(0x2, 0x8000, 0x5)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x80, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSRTIMEOUT(0xffffffffffffffff, 0x8010426d, 0x0)
r1 = socket(0x0, 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
symlink(0x0, 0x0)
sendto$unix(r1, 0x0, 0x8da991d8902dac1d, 0x7, 0x0, 0xd)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
getpeername$unix(0xffffffffffffffff, 0x0, 0x0)
r2 = socket(0x10, 0x5, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
setsockopt(r2, 0x4029, 0x3f, &(0x7f0000000100)='\x00\x00\x00\x00\x00\x00', 0x6)
writev(r2, &(0x7f0000000080), 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0xfffffffffffffffe, 0x0)
syz_open_pts()
socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r3 = socket(0x11, 0x3, 0x0)
sendto$unix(r3, &(0x7f0000000000)="b10005016000009f05000000070000007d9113fecea10500fef96ecfc72fd3357a068da3a5673039d2d236acf20b7804be38164991f7cccf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f45335c223e7d026ba8af630037282118000000720fd38bfbb770c1f5a872c881e2772ec5a10400000000000000361b1257aea8c5d0002012fbff0c230000880d6633c556ae9be371a3f8343712051eeab71d89000407000000800420000000", 0xb1, 0x0, 0x0, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, 0x0)
r0 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r0, 0xc018696c, &(0x7f00000001c0))
r1 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8020699f, &(0x7f00000001c0))
syz_emit_ethernet(0x126f, &(0x7f00000000c0)=ANY=[@ANYBLOB="aaaaaaaaaaaa00000000000086dd609ded1a12390000c4a4e3434e58d025a6a8a81cf312b8befe8000000000000000000000000000aa00030000000000000101000101000401000401000103000000000100010200000000c7ab6f1eba08bf03d1805fce0ef2ab82f4a065245eccda108bec7cb23f632c993265a4cefeb77b1406d562a47d4b0054943553278b519ed107f62b5c352f8e68d83c1fd85b8e1083556d7fa2fc09a3e823fa940de6ef1b18ddb2a2dba0d2d93ef6a9582ae42f5a2c47f4f4d3e34ea1b67a607001a4541a87d5d347b504ca3444dc2b7abe3499079a5701e88493acb2eb1808e8b1f74311083f93341607915aa46325934e81b672d809cb6bc5f3d64480ba4db4432a67c2548e259fe7831f7c6dfe"])
sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f00000001c0)="55f8f5782087a072a82ec35f78d14780f518", 0x12)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc1206949, &(0x7f00000001c0))


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r0 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmat(r0, &(0x7f0000001000/0x3000)=nil, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000040)=[{0x0}], 0x1)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x10, 0xffffffffffffffff, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x4)


mkdir(&(0x7f0000000100)='./file0\x00', 0x0)
setreuid(0xee00, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000015c0)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000000)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000040)=0xc)
setegid(r1)
setgroups(0x0, 0x0)
r2 = getuid()
setreuid(0xee00, r2)
rmdir(&(0x7f0000000080)='./file0\x00')


shmat(0x0, &(0x7f0000ffc000/0x4000)=nil, 0x0)
mlock(&(0x7f0000ffd000/0x1000)=nil, 0x1000)
r0 = shmget$private(0x0, 0x1000, 0x0, &(0x7f0000ffd000/0x1000)=nil)
munmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000040)={0x0, &(0x7f0000000200)})
syz_emit_ethernet(0x4a, &(0x7f0000000440)=ANY=[])
shmctl$IPC_RMID(r0, 0x0)
munlock(&(0x7f0000ffb000/0x4000)=nil, 0x4000)
shmat(r0, &(0x7f0000ffd000/0x3000)=nil, 0x0)
shmget$private(0x0, 0x4000, 0x0, &(0x7f0000ffa000/0x4000)=nil)
madvise(&(0x7f0000ff8000/0x2000)=nil, 0x2000, 0x1)
shmget$private(0x0, 0x4000, 0x0, &(0x7f0000ffc000/0x4000)=nil)
shmctl$SHM_LOCK(0x0, 0x3)
munmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000)
shmctl$IPC_RMID(0x0, 0x0)
mlock(&(0x7f0000ffc000/0x3000)=nil, 0x3000)
shmctl$IPC_STAT(0x0, 0x2, 0x0)
madvise(&(0x7f0000ff9000/0x4000)=nil, 0x4000, 0x0)
shmat(0x0, &(0x7f0000ffc000/0x4000)=nil, 0x0)
socket(0x11, 0x3, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
mmap(&(0x7f0000ffa000/0x2000)=nil, 0x2000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
shmctl$IPC_STAT(0x0, 0x2, 0x0)
msync(&(0x7f0000ffd000/0x1000)=nil, 0x1000, 0x0)
minherit(&(0x7f0000ff8000/0x4000)=nil, 0x4000, 0x0)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)="000001ad", 0x4)


openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x87}, {0x3}, {0x6}]})
syz_emit_ethernet(0x1b, &(0x7f0000000000)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSDIRFILT(r1, 0x8004427d, &(0x7f0000000a00)=0xd57)
syz_emit_ethernet(0x26, &(0x7f00000001c0)=ANY=[])


openat$bpf(0xffffffffffffff9c, &(0x7f0000000340), 0x322, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
r2 = dup(r1)
r3 = open$dir(&(0x7f0000000200)='.\x00', 0x0, 0x0)
mknodat(r3, &(0x7f0000000100)='./file0\x00', 0x0, 0x0)
syz_emit_ethernet(0x66, &(0x7f0000000100)={@local, @local, [], {@ipv6={0x86dd, {0x0, 0x6, "36ea07", 0x30, 0x0, 0x0, @empty, @local={0xfe, 0x80, '\x00', 0x0}, {[], @icmpv6=@dest_unreach={0x1, 0x0, 0x0, 0x0, '\x00', {0x0, 0x6, "5adf00", 0x0, 0x0, 0x0, @ipv4={'\x00', '\xff\xff', @rand_addr}, @mcast1}}}}}}})
openat(r3, &(0x7f0000000000)='./file0\x00', 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
semget(0x0, 0x0, 0x12)
semctl$SETALL(0x0, 0x0, 0x9, &(0x7f0000000400)=[0x0, 0x0, 0x401, 0xfffe, 0x0])
ioctl$WSKBDIO_GETMAP(0xffffffffffffffff, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
r4 = dup2(r0, r1)
writev(r1, &(0x7f0000000080)=[{&(0x7f00000003c0)="ae", 0x1}], 0x1)
shutdown(r2, 0x0)
dup2(r4, r2)
execve(0x0, 0x0, 0x0)


mknod(0x0, 0x0, 0x0)
unveil(0x0, 0x0)
socket(0x0, 0x0, 0x0)
syz_emit_ethernet(0x4e, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
syz_open_pts()
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{}, {}, {0x7, 0x0, 0x0, 0x7fffffff}]})
r0 = socket$unix(0x1, 0x0, 0x0)
semget$private(0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r1 = msgget$private(0x0, 0x0)
msgrcv(r1, &(0x7f0000000b40), 0xa6, 0x0, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x6000, 0x5200)
fcntl$dupfd(0xffffffffffffffff, 0x0, r0)
msgsnd(r1, &(0x7f0000000340)=ANY=[@ANYBLOB="02"], 0xe1, 0x0)
ioctl$FIOASYNC(0xffffffffffffffff, 0x8004667d, &(0x7f0000000180)=0x2a)
open(&(0x7f00000001c0)='./file1\x00', 0x2, 0x20)
open(0x0, 0x80, 0x40)
writev(0xffffffffffffffff, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
socket(0x2, 0x1, 0x0)
open(&(0x7f0000000140)='./file0\x00', 0x1ffff, 0x1a8)


openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
sysctl$vm(&(0x7f0000000000)={0x6, 0xe}, 0x2, &(0x7f0000000040), 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
ioctl$WSDISPLAYIO_SVIDEO(0xffffffffffffffff, 0x80045745, 0x0)
mknod(0x0, 0x0, 0x5c4a)
ioctl$WSDISPLAYIO_LDFONT(0xffffffffffffffff, 0x8058574d, 0x0)
open(0x0, 0x14800, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$VNDIOCSET(0xffffffffffffffff, 0x81946467, 0x0)
ktrace(0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ioctl$WSKBDIO_SETMODE(0xffffffffffffffff, 0x80045713, 0x0)
r0 = socket$inet(0x2, 0x0, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x64, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
socket(0x2, 0x2, 0x0)
r1 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0206923, &(0x7f00000001c0))
ioctl$FIONREAD(r1, 0x8040691a, &(0x7f00000001c0))


mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
r0 = open(0x0, 0x20000, 0xf2)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
setrlimit(0x8, &(0x7f0000000180)={0x3d, 0xff})
ioctl$WSMUXIO_REMOVE_DEVICE(r0, 0x80085762, &(0x7f0000000040)={0x2})
r1 = socket(0x18, 0x3, 0x3a)
setsockopt(r1, 0x29, 0x6c, &(0x7f0000000040), 0x4)
socket(0x2, 0x2, 0x0)
setsockopt(0xffffffffffffffff, 0x11, 0x3, &(0x7f0000000340)="02", 0x1)
ioctl$BIOCSETIF(r0, 0x8020426c, 0x0)
mlockall(0x0)
munlock(&(0x7f000000f000/0x2000)=nil, 0x2000)
mlockall(0x0)
munlock(&(0x7f000000f000/0x4000)=nil, 0x4000)
openat(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r2 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
open(0x0, 0x10080, 0x1d0)
socket(0x0, 0x0, 0x0)
r3 = getpid()
ktrace(0x0, 0x4, 0x0, r3)
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, 0x0)
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$VNDIOCCLR(r2, 0x80106468, &(0x7f0000000b80)={0x0, 0xfffffffffffffffd, 0x0})
open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x59}, 0x6, 0x0, 0x0, 0x0, 0x0)
socket(0x18, 0x4, 0x0)
sysctl$vm(&(0x7f0000000140), 0x2, 0x0, 0x0, 0x0, 0x0)
setrlimit(0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x7}, {0x1}, {0x8186}]})
syz_emit_ethernet(0x4e, &(0x7f00000005c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000140)=[{0x1c}, {0x74}, {0x812e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000200)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
close(r0)
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)
mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x412dff)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x1e56)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x35}, 0x4, 0x0, 0x0, &(0x7f0000000180), 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{0xffff, 0x0, 0xfe}, {0x0, 0x0, 0x0, 0x2}]})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f00000000c0), &(0x7f0000000240)=0x5d)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x37}, 0x4, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x4d, 0x0, 0x2e)
acct(&(0x7f0000001240)='./file0\x00')
socket$inet(0x1e, 0x1, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x32e6)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f00000001c0)=[{0x5}, {}, {0x6}]})
syz_emit_ethernet(0x6e, &(0x7f0000000000)=ANY=[])
ioctl$TIOCSETAF(0xffffffffffffffff, 0x802c7416, &(0x7f0000000000)={0x0, 0x0, 0x3, 0xfffffffc, "fc686b340da1e4795af94547bd1305d65c21963c"})
poll(0x0, 0x0, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000240)=[{0x44}, {0x7}, {0x6}]})
syz_emit_ethernet(0x2a, &(0x7f00000000c0)=ANY=[])
r4 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0xc, &(0x7f0000000240)="ea00000100000000", 0xc)


nanosleep(&(0x7f0000000100), &(0x7f0000001740))


sysctl$kern(&(0x7f0000000000)={0x1, 0x47}, 0x3, &(0x7f0000000080)="b9d55a65edf95074454cbeef747750212b261340975c61c98fc44606f6c84c8106c596189f2824da6ce26ef22601faa932f8506c338734f736b71fe63c3db1e9d4ed2ce08ee7f16195ac49fb6ee8486b47aae9157492458d108d0fcface1392fdf88be327280a9ccb04d81e8c6efb7ee", &(0x7f0000000100)=0x70, 0x0, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "0100dd2d018000000000005e00"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x3d}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000040), 0x3, 0x0, 0x0, &(0x7f0000000080)="4f1d4c6344b80ed788b6a4515248df3aa745bb992c574ab4cdf5587145812eab4a988f7fafd7a01d99776d988908cd186b51f34f8c15ffa0c685ad4116c783959eff4278384b4000384dbb1c2aaeff10b4135529a1da6fda67c67469d954be811b25ec5521559154c586eefff122009f659cd3e27e98a3241495005f102d9101d158284c0ee3250aa7c11042330de22a299ab00894fdc9bac6042d", 0x4)
sysctl$kern(&(0x7f0000000040), 0x3, 0x0, 0x0, &(0x7f0000000080)="4f1d4c6344b80ed788b6a4515248df3aa745bb992c574ab4cdf5587145812eab4a988f7fafd7a01d99776d988908cd186b51f34f8c15ffa0c685ad4116c783959eff4278384b4000384dbb1c2aaeff10b4135529a1da6fda67c67469d954be811b25ec5521559154c586eefff122009f659cd3e27e98a3241495005f102d9101d158284c0ee3250aa7c11042330de22a299ab00894fdc9bac6042d", 0x4)


open(&(0x7f0000000480)='./file0\x00', 0x200, 0x0)
writev(0xffffffffffffffff, &(0x7f00000001c0)=[{&(0x7f0000000100)="ed89f1a5f0365946b16f", 0xa}], 0x1)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000340)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)


mkdir(&(0x7f0000000040)='./file0\x00', 0x0)
setuid(0xffffffffffffffff)
unveil(&(0x7f0000000200)='./file0/file1\x00', &(0x7f0000000280)='x\x00')


syz_emit_ethernet(0xe, &(0x7f0000000640)={@broadcast, @random="3193563ef365", [], {@generic={0x8864}}})


r0 = socket(0x18, 0x2, 0x0)
r1 = socket(0x18, 0x3, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
sendmsg$unix(r2, &(0x7f0000000a80)={&(0x7f0000000200)=@abs={0x0, 0x0, 0x0}, 0x8, 0x0, 0x0, &(0x7f0000000a40)=[@cred={0x20}, @cred={0x14}], 0x40}, 0x0)


r0 = syz_open_pts()
syz_open_pts()
poll(&(0x7f00000000c0)=[{r0}, {r0}], 0x2, 0x0)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000000)=0x9)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0xffffffffffffffff}})
r0 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
r1 = socket(0x800000018, 0x1, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x4, &(0x7f0000000040)=0x80000000, 0x4)
ioctl$PCIOCGETROM(0xffffffffffffffff, 0xc0107005, &(0x7f0000000080)={{}, 0x0, 0x0})
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x2}, {0x20}, {0x4000006, 0x0, 0x0, 0x8001}]})
writev(r0, &(0x7f0000001400)=[{&(0x7f0000000240)="e049c0d37348a45d6bee0bf84a9e", 0xe}], 0x1)


sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x13}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(&(0x7f00000001c0)={0x6, 0x1b, 0x2}, 0x400000000000000d, 0x0, 0x0, 0x0, 0x5a)
sysctl$kern(&(0x7f0000000040)={0x1, 0x3f}, 0x2, 0x0, 0x0, 0x0, 0x0)
socket(0x18, 0x1, 0x0)
shutdown(0xffffffffffffffff, 0x1)
shutdown(0xffffffffffffffff, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
mknod(0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$TIOCSTOP(0xffffffffffffffff, 0x2000746f)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000080), 0xc)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000300)="9b0209c3eb987ab7fe4189c99e805e6e84d356960798a692992117d6728436ba1bd87f42e3303eac3846528d050712f838130efce33f523ba44765f5f6915b0227390ed95bd9dc6d4dc7e149d4d6d06a3f23616e773302d9cae75e39a5a11e32e0e6ebd635450b2eba540af7f2aa5dbfbdd900a0dad2b74f50acd76b5c567049ef436dbea0d7562f52950fa5ef6e84c513252ddd8680a944d5c2bd02adc7f1fe850c00000000000000062ab475cca257352828a76e5334be562995e894238b96ca5d4d3e670feac9b4e8aa9bef19525cb6f7e8570b2a374f1400041ed45bb7ad3fe963cb9a8bd949ee0fc6dbceb7d956015947b3e88aa810f8ed7cca10ff010000000000001345daa49507756f49775275ca390b94e85d5a95b8bdacb9429c25483a9275d0da3b561c6adc3c141f26a88016dd6b436218bdbdc9ac0a623855e941dc1872fcb045e0d9df1ecc6357ee21e2b0802cb60eec6add5e94723235f06715e7eecc3e0760c70e1dd7873e27142bbae1a7e44de453a073fe3426f334b80f043ba9136d57c799353d46dd81439b111a511a288bee5dfb2e353e3bb073e3342273216b07e49ca4df0fd2dbe9a8eb377010ee678aad0bd8e9fb7d82693a096344671843a1f2082612b0ff237c6e505ff5f5ba932954d73c630fdb791f833a1da5af0704f687e196f4f7859e071fc98111cc9024f790ce16ceaa7d0104e39789d9100000010000000000050000000000", &(0x7f00000002c0)=0x210, 0x0, 0x0)


ktrace(0x0, 0x0, 0x0, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x3, 0x10, r0, 0x0)
clock_gettime(0x0, &(0x7f0000000140))


sysctl$net_inet_carp(&(0x7f00000000c0)={0x4, 0x2, 0x70, 0x1}, 0x4, &(0x7f00000001c0)="6cf11dd2", &(0x7f0000000340)=0x4, &(0x7f0000000780), 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000005c0)=[{0x25}, {0x2}, {0x8016}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f00000001c0)=ANY=[])


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, 0x0)
socket$inet(0x2, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
r0 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1, &(0x7f0000000100)=0x60000, 0x4)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r1 = socket(0x2, 0x1, 0x0)
bind(r1, &(0x7f0000000000), 0x10)
listen(r1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1002, &(0x7f00000000c0), 0x4)
connect$unix(r0, &(0x7f0000000000), 0x10)
write(r0, &(0x7f0000000080)="04bdfa5d1d2873c63e3534825ba166e2fea9aec43050006123339a346f731573d8d508753f95b7688ad48b8cf6bbca325cebc37fc4e1dd543dbe2da6dd", 0xffea)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x3}})
sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x1e}, 0x5, 0x0, 0x0, 0x0, 0x45)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000000c0)=[{0x7}, {0x44}, {0x8006}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = socket$inet(0x2, 0x1, 0x0)
listen(r0, 0x85)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)={0x3, 0x7fffffff})
syz_emit_ethernet(0x2e, &(0x7f0000000080)={@local, @broadcast, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x1, 0x0, @remote={0xac, 0x14, 0x0}, @multicast2, {[@lsrr={0x83, 0x3}]}}, @icmp=@generic={0x9, 0x0, 0x0, "e10f46cf"}}}}})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r2 = socket(0x11, 0x3, 0x0)
sendto$unix(r2, &(0x7f0000000140)="b1000502000000000000000001010000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc256699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)
shutdown(r2, 0x2)
ioctl$BIOCIMMEDIATE(r1, 0x80044270, &(0x7f0000000180)=0x2)
r3 = dup(r1)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
syz_emit_ethernet(0xe, &(0x7f0000000200)=ANY=[])
select(0x40, &(0x7f0000000380)={0x3f}, 0x0, 0x0, 0x0)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)
r4 = syz_open_pts()
ioctl$TIOCMBIC(r4, 0x8004746b, &(0x7f0000000080)=0x7ff)
r5 = socket(0x18, 0x1, 0x0)
read(r5, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x48}, 0x2, &(0x7f00000000c0)="53da903e", &(0x7f0000000040)=0x4, &(0x7f0000000180), 0x0)
r6 = kqueue()
kevent(r6, &(0x7f0000000080), 0x7ff, 0x0, 0xc0000000, 0x0)
kevent(r6, &(0x7f00000000c0), 0x30, 0x0, 0x57d, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
syz_extract_tcp_res$synack(&(0x7f0000000000), 0x1, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x8, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000002c0)={0x3, &(0x7f0000000700)=[{0x0, 0x0, 0x3f, 0x1}, {0x96b2, 0x3}, {0x6}]})
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000100), 0x1, 0x0)
semop(0xffffffffffffffff, &(0x7f00000002c0)=[{0x0, 0x8001, 0x800}, {0x3}, {0x4, 0x8, 0x800}, {0x4, 0xfff, 0x800}, {0x4, 0x4}, {0x2, 0x1000, 0x1800}, {0x0, 0x8000, 0x800}, {0x2, 0x8, 0x800}, {0x4, 0x1162, 0x400}], 0x9)
sysctl$vfs_ffs(&(0x7f0000000000)={0xa, 0x1, 0x10}, 0x3, &(0x7f0000000080)="d3f3351a05", &(0x7f0000000140)=0x5, &(0x7f0000000180)="21ab58aa1bfdca668af6b1f30cca5274ecb7375c064bc152f50867d33581c087b3fcecc8502601bfea75539052ae34eab61285a81b5bd726e3b11466d1d58af39f8c0797fda1135421ae9c8662ece405fd13fc809e3ce5580ade826c7faeee91c7ec5e9f9a8e89d63382ba66b2997773b9d30ced07136574a9ccf9429a887322411be15bf2dd60dc5031974356e40b4627881faeb7f3b1d9eb6dbeb26ae8ede6bbcc8de933183c1e148a38f8391bf03963883c50c129bd34a1ffc5ee39015e38735b525b6b3822090edc1b", 0xcb)
socket(0x18, 0x1, 0x0)
r1 = socket(0x800000018, 0x1, 0x0)
getsockopt$sock_int(r1, 0xffff, 0x20, &(0x7f0000000200), &(0x7f0000000240)=0x4)
r2 = open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
r3 = open$dir(&(0x7f0000001640)='./file0\x00', 0x2, 0x0)
writev(r3, &(0x7f0000000440)=[{&(0x7f0000000300)='k', 0x1}, {&(0x7f0000000340)="12800300c4121c2c3ac1dda5b0861b963639a261b3f1e80fd619d132f4a9565c978bf9731473fedc3683319e202aaf05b65e74b6792d8db52aee64d4ebb615f816de534920213d54f9c74c5916a880f842b3a124d40c1c6474846322063925a30f44e12e7548d71509662c5319692f35f4660ee91446c2cfeb589b67d34e260a43cc5f4a536825e0945d6b57956e90cf950b1a38c5d19686c0092c5d41337e9715515888abedc75b5373ae81acee3c1b6f6a71ae13060f8ec074449737", 0xbd}], 0x2)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x3, 0x10, r2, 0x0)
r4 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x0, 0x0)
ioctl$VT_GETACTIVE(r4, 0xc1045763, &(0x7f0000000100))
sysctl$net_inet_tcp(&(0x7f0000000140)={0x4, 0x1e, 0x2, 0x1}, 0x4, &(0x7f0000000300), 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{0x2f, 0xfe, 0x3, 0xfffff000}, {0x7c}, {0x15, 0x1, 0x6}]})
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r5, 0x80104267, &(0x7f0000000980)={0x0, 0x0})
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
getgroups(0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
setsockopt$inet6_MRT6_ADD_MIF(0xffffffffffffffff, 0x29, 0x66, 0x0, 0x0)
readv(0xffffffffffffffff, 0x0, 0x0)
open(&(0x7f0000000280)='./file0\x00', 0x0, 0x50)


open(&(0x7f0000000480)='./file0\x00', 0x200, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r0)
recvmmsg(0xffffffffffffffff, &(0x7f0000000080)={&(0x7f0000000100)={&(0x7f00000006c0), 0x213, 0x0, 0x0, 0x0}}, 0x10, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000340)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)


syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x3, 0x2f)
connect$unix(r0, &(0x7f0000000000), 0x10)
connect$unix(r0, &(0x7f0000001180)=@file={0x0, './file0\x00'}, 0xa)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x889, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000040)={&(0x7f0000000000)=[{}, {0x2}], 0x2})


kevent(0xffffffffffffffff, &(0x7f00000000c0)=[{{}, 0xfffffffffffffff9, 0x1}], 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x5, 0x0)
r1 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000140), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r1, 0x80085761, &(0x7f00000000c0)={0x0, 0xfffffffc})
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r2 = kqueue()
kevent(r2, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000001c0)={<r3=>0xffffffffffffffff, <r4=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000600)={0x0, 0x0, 0x0, 0x0, &(0x7f00000005c0)=ANY=[@ANYBLOB="10000000ffff000001"], 0x10}, 0x0)
sendmmsg(r3, &(0x7f0000000600)={0x0}, 0x10, 0x0)
dup2(r4, r3)
shutdown(r3, 0x0)
r5 = socket(0x10, 0x4000, 0x0)
ioctl$FIONREAD(r5, 0x80206932, &(0x7f00000001c0))


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0x94739c02}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
mknod(&(0x7f0000000040)='./file0\x00', 0x2000, 0x3200)
r1 = open$dir(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
preadv(r1, &(0x7f00000004c0)=[{&(0x7f00000000c0)=""/99, 0xfffffd23}], 0x1, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x10000})
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)='\x00', 0x1}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
r1 = socket$inet(0x2, 0x2, 0x0)
dup2(r0, r1)
setsockopt$inet_opts(r1, 0x0, 0xa, &(0x7f0000000240), 0x0)
syz_open_pts()
socket$unix(0x1, 0x2, 0x0)
shutdown(0xffffffffffffffff, 0x0)
mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(0x0, 0x0)
unlink(0x0)
rename(&(0x7f00000007c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000a40)='./file0\x00')
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0\x00', &(0x7f0000000e40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000600)='./file0\x00', &(0x7f0000000f40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000001040)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000001140)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000080)={0x0, 0xe5, 0x9fd, 0x88c, "43b2b0bf3e79036980220d348bba04ff4e629aa0"})
writev(r0, &(0x7f0000000740)=[{&(0x7f0000000200)="71994c1de376a629d07b09610817554b444e03bbccd179a857389f23c8a50b91a62a5453774c410d0d", 0x29}], 0x1)


mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
syz_emit_ethernet(0x56, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
syz_open_pts()
ioctl$TIOCCONS(r0, 0x80047462, &(0x7f0000000340)=0x8)
syz_open_pts()
ioctl$WSDISPLAYIO_GETEMULTYPE(r0, 0xc014575e, &(0x7f0000000040)={0x0, './file0\x00'})


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x4, 0x0, 0x0, 0xfffffffc}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x27}, 0x4, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x50, 0x0, 0x2e)
syz_emit_ethernet(0x17a, &(0x7f00000001c0)=ANY=[@ANYBLOB])
r0 = open(&(0x7f0000000480)='./file0\x00', 0x200, 0x4ebfac6bbaf796d)
r1 = kqueue()
open$dir(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
r2 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000100), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r2, 0x80105727, &(0x7f00000001c0)={&(0x7f0000000040)=[{}, {0x4}], 0x2})
kevent(r1, &(0x7f0000000000)=[{{r0}, 0xffffffffffffffff, 0xa1}], 0x8c0, 0x0, 0x0, 0x0)
r3 = open(&(0x7f0000000080)='./file0\x00', 0x70e, 0x0)
writev(r3, &(0x7f0000001580)=[{&(0x7f0000000280)="98", 0x1}], 0x1)
ftruncate(r3, 0x0)
kevent(r1, 0x0, 0x0, 0x0, 0x653, &(0x7f0000001840))
r4 = open(0x0, 0x0, 0x8)
kqueue()
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r5, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{0x45}, {0x40}, {0x8006}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])
writev(r4, 0x0, 0x0)
ioctl$BIOCGDIRFILT(r4, 0x4004427c, &(0x7f0000000180))
openat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r6 = shmget$private(0x0, 0x1000, 0x0, &(0x7f0000ffc000/0x1000)=nil)
munmap(&(0x7f0000ffb000/0x4000)=nil, 0x4000)
shmat(r6, &(0x7f0000ffd000/0x1000)=nil, 0x0)
shmat(r6, &(0x7f0000ffa000/0x4000)=nil, 0x0)
mkdirat(0xffffffffffffff9c, &(0x7f0000000080)='./file1\x00', 0x0)
unveil(&(0x7f0000000000)='./file1/file0\x00', &(0x7f00000001c0)='x\x00')
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {}, {0x6, 0x0, 0x0, 0x85}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


socket(0x0, 0x0, 0x0)
r0 = dup(0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0206921, &(0x7f00000001c0))
openat$zero(0xffffffffffffff9c, 0x0, 0xe8, 0x0)
r2 = socket(0x18, 0x3, 0x0)
setsockopt(r2, 0x1000000029, 0x24, &(0x7f0000000040)="e81e1a97f45a60ef4b4e150cd4", 0xd)
r3 = syz_open_pts()
close(r3)
msgget$private(0x0, 0x342)
dup(0xffffffffffffffff)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
socket(0x2, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
semctl$SETALL(0x0, 0x0, 0x9, 0x0)
ioctl$VMM_IOC_CREATE(r0, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000ffd000/0x1000)=nil, &(0x7f00006e1000/0x3000)=nil}, {&(0x7f0000a29000/0xc000)=nil, &(0x7f000041b000/0x4000)=nil}, {&(0x7f0000acf000/0x11000)=nil, &(0x7f00007a5000/0x3000)=nil, 0x20000000000000}, {&(0x7f0000554000/0x4000)=nil, &(0x7f000042d000/0x4000)=nil, 0x9}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil, 0x20}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000a64000/0x1000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil}, {&(0x7f0000bb2000/0x4000)=nil, &(0x7f0000312000/0x3000)=nil}, {&(0x7f0000a31000/0x3000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f00002dc000/0x4000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f000032e000/0x800000)=nil, &(0x7f0000ffe000/0x1000)=nil, 0x8004}, {&(0x7f0000015000/0x3000)=nil, &(0x7f000015e000/0x2000)=nil}, {&(0x7f0000893000/0x1000)=nil, &(0x7f0000487000/0x2000)=nil, 0x400000000000000}, {&(0x7f000052f000/0x2000)=nil, &(0x7f0000ff3000/0x2000)=nil}], './file0\x00'})
socket$inet(0x2, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x2, &(0x7f0000000080), 0x0)
mprotect(&(0x7f0000ff3000/0x2000)=nil, 0x2000, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000300)=[{&(0x7f0000000140)="f005c71031c1c5f421277b09000000000000007a091a2f47be787538ec7a89ec5ed66daa731ddc384ecc690869a0aa2266affdf772d7a360ee0f15fa664f557bb45071fe9b6d9d28e6e2589000f6a64f370b9e336987d77b38f7aada5309e46a81e0e2efa087aa9f5f89934fdbd2ed96e7234b8972b273e810ca9962a8f461d3a05711a63027321ff62c", 0x8a}], 0x1)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000002c0)={<r4=>0xffffffffffffffff})
ioctl$FIONREAD(r4, 0xc0106924, &(0x7f00000001c0))
getuid()
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x25}, 0x4, 0x0, 0x0, 0x0, 0x0)
utimensat(0xffffffffffffffff, 0x0, 0x0, 0x2)
pipe2(0x0, 0x0)
socket$inet(0x2, 0x0, 0xee)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
sysctl$hw(&(0x7f0000001180)={0x7}, 0x2, 0x0, 0x0, 0x0, 0x0)
msgget$private(0x0, 0x0)
r1 = openat$null(0xffffffffffffff9c, 0x0, 0x1, 0x0)
openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x20000, 0x0)
mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
chdir(&(0x7f0000000240)='./file0\x00')
setreuid(0x0, 0xee01)
mkdir(&(0x7f0000000100)='./file1\x00', 0x0)
chflags(&(0x7f0000000040)='./file1\x00', 0x10000)
accept$unix(0xffffffffffffff9c, &(0x7f00000011c0)=@file={0x0, ""/528}, &(0x7f0000000300)=0x212)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
ioctl$WSMOUSEIO_GETPARAMS(0xffffffffffffffff, 0x80105727, &(0x7f0000000080)={0x0})
ioctl$WSKBDIO_GETMAP(r1, 0xc010570d, &(0x7f00000003c0)={0x0, 0x0})
r2 = semget$private(0x0, 0x2, 0x0)
semctl$GETPID(r2, 0x2, 0x4, &(0x7f0000000000)=""/4096)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000100)=[{0x4}, {0x4c}, {0x8016}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x138, &(0x7f00000009c0)=ANY=[])
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{0x6, 0x20, 0x1, 0x16}, {0x1f, 0x3f, 0x9, 0xfffffffc}, {0x9, 0x20, 0x1a, 0x9}]})


mkdir(&(0x7f0000000040)='./file0\x00', 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
ioctl$WSDISPLAYIO_GMODE(0xffffffffffffff9c, 0x4004574b, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x284, 0x100})
syz_open_pts()
close(0xffffffffffffffff)
syz_open_pts()
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
execve(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x6000, 0x80000001)
ioctl$WSDISPLAYIO_SVIDEO(0xffffffffffffffff, 0x80045745, &(0x7f0000000300)=0x1)
mknod(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)
open(0x0, 0x0, 0x0)
ioctl$TIOCSETD(0xffffffffffffffff, 0x8004741b, 0x0)
open(0x0, 0x10005, 0x0)
r1 = open(&(0x7f0000000200)='./bus\x00', 0x0, 0x0)
readv(r1, &(0x7f00000001c0)=[{&(0x7f0000000140)=""/5, 0x5}], 0x1)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000180)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
r3 = fcntl$getown(r2, 0x3)
setpgid(0x0, r3)
r4 = socket(0x18, 0x3, 0x0)
setsockopt(r4, 0x1000000029, 0x2a, 0x0, 0x7)
fcntl$setstatus(0xffffffffffffffff, 0x4, 0x0)
r5 = msgget$private(0x0, 0x0)
msgctl$IPC_SET(r5, 0x1, &(0x7f00000001c0)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}, 0x400002, 0x4, r3, 0x0, 0x5e, 0x100000001, 0x8001, 0x9})
getsockopt$sock_linger(r0, 0xffff, 0x80, &(0x7f0000000100), &(0x7f0000000280)=0x8)
getpeername(0xffffffffffffffff, &(0x7f00000002c0)=@un=@file={0x0, ""/40}, &(0x7f0000003880)=0xffffff56)


syz_emit_ethernet(0x11f, &(0x7f0000000280)=ANY=[@ANYBLOB="ffffffffffff00000000000086dd605af6a400000000e1403605dd3b845a85a7a49610787775ff0200000000000000000000000000010000c204"])


socketpair$unix(0x1, 0x0, 0x0, 0x0)
socket$unix(0x1, 0x0, 0x0)
syz_emit_ethernet(0x2b, &(0x7f0000000500)={@local, @remote, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x1d, 0x0, 0x8, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @broadcast}, @udp={{0x1, 0x2, 0x8}, {"a9"}}}}}})
syz_emit_ethernet(0x65, &(0x7f0000000000)={@random="39d0fb9200", @broadcast, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x57, 0x0, 0x1, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @broadcast}, @generic="a3c169503e7136d4892052a64f57bed416a8c17605e60e679657e8df51542edfdc83b519d35b90d8174072d1a5f781251833a3e6f23da062e4a6d02991cd1aa7f3f20c"}}}})


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x0, 0xff6cae7, 0x1, 0xfffffffa, "1a118c37510a9c4fa879000b00ffef76ee3bf700"})
writev(r0, &(0x7f00000003c0)=[{&(0x7f0000000380)="d62a752c883a0802006203000000000000002e0917da3c", 0x17}, {&(0x7f0000000740)="473f6f7a0054aa8ee4b485989b32a6de716e45a78e61606d7819ff90688ad6344eff00bf60f2fe4ec925668c1e16bda2826891a37efcdbe745c8822604060520009a76d50efc1e9148bc6e14c066650e6d32665120c6a8ed89e6261fa7e1990448fc4eec134e5d8c652a2282c72eb295fba8256976b949ce2242ec94165178d333e858f466e0edf8a9843900ecb40279aa8b567a377e75bea514b8", 0xfde4}], 0x2)
writev(r0, &(0x7f0000000800)=[{&(0x7f0000000040)="abe164e934a68e6d1510e7fa389869fb162b157d865ec39cc3733506517595f954083bab10f912ce8df4bb32e95b218bcc678c570cd2d4230e643de6aa40bae4ff9c48f78479f294916e81a25b302a81df4dd06d00a07c7a0a", 0x59}], 0x1)


r0 = socket(0x2, 0x3, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
connect$unix(r0, &(0x7f0000000000), 0x10)
write(r0, &(0x7f0000000080), 0x20000)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000240)=[{0x2}, {0x1d}, {0x6}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x6000, 0xe02)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$VNDIOCGET(r0, 0xc4104603, &(0x7f00000002c0)={'./file0/file0\x00', 0x3f, 0xead7, 0x3})
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, &(0x7f00000001c0))
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x3, 0x10, r0, 0x8000000000000000)
pipe(&(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000000)=[{0x80}, {0x5c}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000240)=ANY=[])


poll(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f00000000c0)=[{0x60}, {0x84}, {0x6, 0x0, 0x0, 0xfffffffc}]})
writev(r0, &(0x7f0000000640)=[{&(0x7f0000000100)="6f86efc09802952688084127b3e0", 0xe}], 0x1)


r0 = open$dir(&(0x7f0000000040)='./file0\x00', 0xae828e137847f62, 0x0)
setrlimit(0x1, &(0x7f0000000000)={0xfffffffffffffffd, 0xffffffffffffffff})
ftruncate(r0, 0x20008002)
r1 = open$dir(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
preadv(r1, &(0x7f00000004c0)=[{&(0x7f00000000c0)=""/99, 0xfffffd23}], 0x1, 0x0)


mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x1, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000040)="03000000", 0x4)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)


r0 = semget$private(0x0, 0x7, 0x3c0)
semop(r0, &(0x7f0000000100)=[{0x3, 0xa, 0x800}, {0x1, 0x2ff}, {0x2, 0x8}, {0x3, 0x3ff, 0x1800}, {0x2}], 0x5)
semctl$GETPID(r0, 0x3, 0x4, &(0x7f0000000240)=""/8)
semop(r0, &(0x7f0000000200), 0x0)
semop(0x0, &(0x7f00000002c0)=[{}, {}, {0x2, 0xfff8}, {0x1, 0x1, 0x1000}, {0x3, 0x7e7, 0x800}], 0x5)
r1 = semget$private(0x0, 0x0, 0x104)
semctl$IPC_SET(r1, 0x0, 0x1, 0x0)
semop(0x0, &(0x7f0000000280)=[{}], 0x1)
semctl$IPC_SET(r0, 0x0, 0x1, 0x0)
r2 = getuid()
seteuid(0x0)
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f0000000340)={{0xfffffffc, 0x0, 0xffffffffffffffff, r2}, 0x5, 0x9})
semop(0x0, &(0x7f0000000040), 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7949)
semop(r1, &(0x7f00000004c0)=[{0x2, 0x5bef, 0x800}], 0x1)
open(0x0, 0x0, 0x0)
semctl$SETALL(0x0, 0x0, 0x9, &(0x7f00000001c0))
semctl$IPC_RMID(0x0, 0x0, 0x0)
semget(0x1, 0x3, 0x104)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000001c0)={0x3, &(0x7f0000000040)=[{0x60}, {0x28}, {0x4000006}]})
writev(r0, &(0x7f0000000240)=[{&(0x7f0000000340)="ebebfd510bbcdda9b489e9775d3e", 0xe}], 0x1)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x400, 0x0)
syz_open_pts()
r0 = socket(0x18, 0x1, 0x0)
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f00000001c0), 0xffffffffffffff84)
ioctl$TIOCSETAW(0xffffffffffffffff, 0x802c7415, 0x0)
msgctl$IPC_SET(0x0, 0x1, 0x0)
sysctl$hw(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
syz_open_pts()
close(0xffffffffffffffff)
setrlimit(0xa, &(0x7f0000000980)={0x9, 0x5})
r1 = syz_open_pts()
close(r1)
syz_open_pts()
ioctl$FIOASYNC(r1, 0x80047469, &(0x7f0000000040)=0xfffffffc)
writev(r1, 0x0, 0x0)
msgctl$IPC_SET(0x0, 0x1, 0x0)
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x1, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
unveil(0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x0, 0x0})
syz_emit_ethernet(0x42, 0x0)
sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000000)="9b1809ffffffffffffff7f473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6fd74c94d1b44", &(0x7f0000000040)=0x10011, 0x0, 0x0)
getegid()


truncate(&(0x7f0000000000)='./file0\x00', 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)
poll(&(0x7f0000000380)=[{}], 0x1, 0xffff)
r0 = socket(0x1, 0x1, 0x0)
r1 = dup2(r0, r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
socket(0x2, 0x2, 0x0)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x60}, {0x3}, {0x6}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x40000802)
r1 = open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSFLAGS(r1, 0x8004745c, &(0x7f0000000080))
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0)=@file={0x0, '\x00'}, 0x3, 0x0}, 0x0)
r2 = socket$inet(0x18, 0x3, 0x102)
r3 = dup(r2)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sendmsg$unix(r3, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


syz_emit_ethernet(0x4e, &(0x7f0000000140)={@local, @local, [], {@ipv6={0x86dd, {0x0, 0x6, "bd23ca", 0x18, 0x1, 0x0, @remote={0xfe, 0x80, '\x00', 0x0}, @local={0xfe, 0x80, '\x00', 0x0}, {[], @tcp={{0x3, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, {[@mss={0x2, 0x4}]}}}}}}}})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000200)={0x3, &(0x7f0000000100)=[{0x34, 0x0, 0x0, 0x3}, {0x1d}, {0x6, 0x0, 0x0, 0x101}]})
write(r0, &(0x7f0000000080)="2300110000fa4000805a099e20a0", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000280)=[{0xc}, {0x20}, {0x40e}]})
syz_emit_ethernet(0x2a, &(0x7f00000001c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
unveil(&(0x7f0000000080)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38/\x00', &(0x7f00000001c0)='W\x00')
r1 = socket(0x11, 0x3, 0x0)
sendto$unix(r1, &(0x7f00000000c0)="b10005136000009f050000002010000000000000cea10500fef96ecfc727d3357ae302b37b67ca1f2d61db7f4de57804be38164991f7c8cf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f4d335d223e7db3008b95665bc6fc2118000000720fd38bfbb770c1f5a872c881ea772ec5890405b3b9c2668396f4cd1257aea8c500002002fbfc0c2300008abfba0900000008e37f71a3f8343712051eeab71d89e000040381ecb664000000", 0xb1, 0x0, 0x0, 0x0)


socket$unix(0x1, 0x0, 0x0)
open(0x0, 0x70e, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
sysctl$net_inet_ip(&(0x7f00000000c0)={0x4, 0x1e, 0x2, 0x2}, 0x4, 0x0, 0x0, 0x0, 0x0)
socket(0x18, 0x1, 0x0)
shutdown(0xffffffffffffffff, 0x1)
close(0xffffffffffffffff)
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
socket(0x2, 0x2, 0x0)
socket$inet(0x2, 0x3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, &(0x7f00000001c0))
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
syz_open_pts()
ioctl$TIOCSETAW(0xffffffffffffffff, 0x802c7415, 0x0)
readv(0xffffffffffffffff, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r1 = socket(0x18, 0x1, 0x0)
r2 = socket(0x18, 0x1, 0x0)
r3 = socket(0x18, 0x3, 0x0)
ioctl$FIONBIO(r2, 0x8004667e, &(0x7f0000000080)=0x1)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r4 = semget$private(0x0, 0x0, 0x204)
semop(r4, &(0x7f0000000040)=[{0x2, 0x3, 0x1400}, {0x4}, {0x1, 0x2, 0x1000}, {}, {0x4, 0x8, 0x1800}, {0x1, 0x0, 0x1800}], 0x6)
getsockname$inet(r3, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
dup2(r2, r1)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x206381)
r0 = socket(0x11, 0x3, 0x0)
open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1002, &(0x7f00000000c0)=0x80, 0x4)
sendto$unix(r0, &(0x7f0000000000)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)
recvmmsg(r0, &(0x7f0000000280)={0x0}, 0x10, 0x0, 0x0)


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ioctl$FIOASYNC(r0, 0x8004667d, &(0x7f0000000000))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x2, &(0x7f0000000000)=[{0x28, 0x0, 0x0, 0x80}, {0x4000006}]})
write(r0, &(0x7f0000000180)="23009100007adb020317bdda2b7e", 0xe)


r0 = socket(0x18, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x8040691a, &(0x7f00000001c0))


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000640)={0x0, 0x0, 0x0, 0x0, &(0x7f00000000c0)=ANY=[@ANYBLOB="18000000ffff000001"], 0x18}, 0x0)
shutdown(r1, 0x0)
sendmmsg(r0, &(0x7f0000000480)={0x0}, 0x10, 0x0)
syz_emit_ethernet(0x3e, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x11}, 0x4, 0x0, 0x0, &(0x7f00000001c0)="7094148ef48fbeae04f372c775f74b253e2c17f3757f8d192b98e200ab33813bf24438598f9c4b524349b5945f9f1e7a6d35ee91cecf40447da8b3d5e7c0219afef82007cad6a5f7b448c382f438de1feada69fc4977f11ce553bd81967e9d1ff15cb03607bcf5a9be944a6249a3c1bcd043c7f1fca338a0daf3e988569108dc7061db3c33c56ee91fab7d4963d74dfefa44a51b8b9ff785e100"/167, 0xa7)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000000)={0x0, 0x453, 0x0, 0x0, "c07b1f46000000efff0020fbff00"})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)='\t\x00\x00\x00', 0x4)
r1 = dup(r0)
setsockopt(r1, 0x1000000000029, 0xc, &(0x7f0000000000)="ffdaff10aac6a28ac93e2eddc45c8454e486f64c", 0x14)


socketpair(0x1, 0x1, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
write(r0, &(0x7f0000000340)="38c344d08db0e1391e89142d173b05d32264bd5fd9f127", 0x17)
r2 = fcntl$dupfd(r1, 0x0, r0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000440)={&(0x7f0000000400)=@file={0x0, './file0\x00'}, 0xa, 0x0}, 0x0)
writev(r0, &(0x7f00000004c0)=[{&(0x7f0000000180)="18345e5fb8de11ff09622c03d2efee7358836aaeaa580fbed001637148d70ecb143e41c66b43c5c6113b3446679834f4a37b4dc718a61fe3920f135d6f7900cf9393b1ad44a2a3e673ad9ed27e5898ab850da0f0", 0x54}, {&(0x7f0000000280)="41951012587bbe9a05fd7ff77c33d41fd29e6b3c4652c1c1a73768371e78175ec3767bdd91e3", 0x26}], 0x2)
recvmmsg(r2, &(0x7f00000003c0)={0x0}, 0x10, 0x2, 0x0)


r0 = socket(0x2, 0x2, 0x0)
sendmsg$unix(r0, &(0x7f0000001a00)={&(0x7f0000000080)=@file={0x0, '\x00'}, 0x3, 0x0, 0x0, &(0x7f0000000040)=ANY=[@ANYBLOB="14"], 0x18}, 0x0)


r0 = socket(0x2, 0x1, 0x0)
setsockopt(r0, 0x6, 0x4, &(0x7f0000000140)="aef43c05", 0x4)
open(&(0x7f0000000080)='./bus\x00', 0x200, 0x0)
mkdir(&(0x7f0000000100)='./file0\x00', 0x0)
setreuid(0xee00, 0x0)
chown(&(0x7f0000000040)='./file0\x00', 0x0, 0xffffffffffffffff)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000180)={<r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000340)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000380)=0xc)
setregid(0x0, r2)
setreuid(0xee00, 0x0)
socket(0x2, 0x2, 0x0)
r3 = semget$private(0x0, 0x7, 0x3c0)
semop(r3, &(0x7f0000000180)=[{0x3, 0x43, 0x1800}, {0x1, 0xfffe, 0x1800}, {0x0, 0xfd, 0x1000}, {0x1, 0x20, 0x1800}, {0x2, 0x5, 0x1800}, {0x4, 0x9e, 0x1800}, {0x2, 0xfffb, 0x1000}, {0x0, 0x40, 0x3800}, {0x3, 0x8}], 0x9)
semctl$SETALL(r3, 0x0, 0x9, &(0x7f00000004c0)=[0x9, 0x1001])


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffff9c, 0x80185760, &(0x7f0000000000)={0xa, 0x0, {0x400000002}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$net_inet_carp(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)


r0 = open$dir(&(0x7f0000000040)='./file0\x00', 0xae828e137847f62, 0x0)
pwrite(r0, &(0x7f00000002c0)="191e80bd23b48941029ba5926a4e54c802732497a372ad32a140e2cfab9b27f6735c0706d5f4de14763ffed9de4895d5bc65ffa082a7ff4d12460a8abb048fb3ccbcd19b68705ba50563a35d5b221e8302ae0125773e4e26e94099d4d0fd68c6d24b9e5309c6a6c0943997a84e90b06908f77d154c89d990def5821d2dd65edd0f3acdea08243991eaa35e79ef4feae797524e59b174231f0d6106075da312aea2ffdf1f180ecf00a6d000a8eadb0000014da00c95f9d216d409973462856a9dc9bac948c69063e840d714313e0082a0019c3f4426c4b95c7d6ebe369c0651087019a3364ffbd2585bb194b2d17a094e5cb9043a9748", 0xfffffffd, 0x0)
setrlimit(0x1, &(0x7f0000000000))
ftruncate(r0, 0x8000)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmsg(r0, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000440)=[{0x10}], 0x10}, 0x0)


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setuid(0xee01)
stat(&(0x7f0000000040)='./file0\x00', 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETAF(r1, 0x802c7416, &(0x7f0000000100)={0x978b, 0x0, 0xfffffffa, 0x80a19f, "bb080000009a019fbcc2583e2f00"})
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)
writev(r0, &(0x7f0000001480)=[{&(0x7f00000011c0)="cc60d3d79a1a7122a5fb9de9ea6ca0b30fb2942ef7652736f10f86d45ae419b27043a7ae54fddafef2c56c0d93da7484095d0d543baf7f0161a025c9c02a561f9a76d06f1eaec7d8df99d6c2", 0x4c}], 0x1)


syz_open_pts()
r0 = socket$inet(0x1e, 0x3, 0x0)
setrlimit(0x0, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x3, 0x0, "1c10260974612c330000fcff00"})
getpeername(r0, 0x0, &(0x7f0000000040))
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000340), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$VMM_IOC_WRITEREGS(r1, 0xc0205609, &(0x7f0000000040))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000240)=[{0x60}, {0x20}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000140)=ANY=[])


r0 = getgid()
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000040)={{0x7f, 0x0, r0, 0x0, 0x0, 0x0, 0x200}})
sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x26}, 0x4, &(0x7f0000000080), 0x0, 0x0, 0x0)
r1 = socket(0x18, 0x3, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r1, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000002}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x18, 0x400000002, 0x0)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r3 = socket(0x18, 0x1, 0x0)
recvfrom(r2, &(0x7f0000000100)=""/94, 0x5e, 0x43, &(0x7f0000000180)=@in={0x2, 0x3}, 0xc)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000016c0)={0x3, &(0x7f0000001700)=[{0x25}, {0x40}, {0x6, 0x0, 0x0, 0xfffffffe}]})
write(0xffffffffffffffff, &(0x7f0000002540)="76e5bbda369af8607d2100000063", 0xe)
r4 = dup2(r2, r3)
accept(r4, &(0x7f00000001c0)=@in, &(0x7f0000000200)=0xc)
sendmsg$unix(r4, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


setitimer(0x0, &(0x7f0000001600)={{}, {0x1}}, 0x0)
getitimer(0x0, &(0x7f0000000000))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setitimer(0x0, &(0x7f0000000000), &(0x7f0000000040))


r0 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r0, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
r1 = socket(0x2, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCLOCK(0xffffffffffffffff, 0x20004276)
seteuid(0xffffffffffffffff)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
listen(r1, 0x401)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b10005016000009f0500060003000000331c13fecea10500fef96ecfc72fd3357af302b37b673039d2d236acf20b7804be382249d1f7c8cf5f88882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f4d335c223e7d026ba8af6300372821", 0x62, 0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504000004000000000007", 0xd, 0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000001})
r2 = socket(0x11, 0x3, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
sendto$unix(r2, &(0x7f0000000000)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)
ioctl$FIONREAD(r0, 0xc0207534, &(0x7f0000000440))


r0 = open$dir(&(0x7f0000000040)='./file0\x00', 0xae828e137847f62, 0x0)
setrlimit(0x1, &(0x7f0000000000)={0xfffffffffffffffd, 0xffffffffffffffff})
ftruncate(r0, 0x20008002)
preadv(r0, &(0x7f00000000c0)=[{&(0x7f0000000080)=""/61, 0x3d}], 0x1, 0x3800000)


setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
r1 = open(&(0x7f0000000140)='./file0\x00', 0x78e, 0x0)
r2 = getpid()
ktrace(&(0x7f0000000040)='./file0\x00', 0x0, 0x20, 0x0)
ktrace(&(0x7f0000000280)='./file0\x00', 0x0, 0x928, r2)
utimensat(0xffffffffffffffff, 0x0, &(0x7f0000000100), 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r1, 0x0)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000200)="f6", 0x1}], 0x1)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
bind$unix(r0, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000040)={0x0, 0x0, <r3=>0x0}, &(0x7f0000000080)=0xc)
chown(&(0x7f0000000280)='./file0\x00', 0x0, r3)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
setreuid(0x0, 0xee01)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


r0 = syz_open_pts()
ioctl$TIOCSTAT(r0, 0x20007465, 0x0)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000180)=0x7)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000040)=0x7)
execve(0x0, 0x0, 0x0)


clock_getres(0x0, &(0x7f0000000000))
setreuid(0xee00, 0x0)
sysctl$net_inet_carp(&(0x7f0000000380)={0x4, 0x2, 0x70, 0x4}, 0x4, 0x0, 0x0, 0x0, 0x0)
getuid()
socket(0x2, 0x1, 0x0)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x0, 0x10, r0, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
chdir(&(0x7f0000000140)='./file0\x00')
symlink(&(0x7f0000000200)='./file2\x00', &(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
open(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
r1 = semget$private(0x0, 0x7, 0x3c0)
semop(r1, &(0x7f0000000080), 0x0)
rename(&(0x7f0000000540)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000080)='./file0\x00')
semctl$GETPID(r1, 0x3, 0x4, &(0x7f0000000240)=""/8)
semop(r1, &(0x7f0000000280)=[{0x1, 0x7, 0x1000}], 0x1)
semop(r1, &(0x7f0000000280)=[{0x4, 0x94}, {0x0, 0x8400, 0x1000}, {0x1, 0x2, 0x400}, {0x3, 0x8, 0x800}, {0x0, 0x4, 0x1800}], 0x5)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, 0x0, 0x1}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {0x0, &(0x7f0000ffc000/0x2000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffc000/0x1000)=nil}], './file0\x00'})
getpgid(0xffffffffffffffff)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
writev(r0, &(0x7f0000000680)=[{&(0x7f0000000080)="2a97990f7cbe82ab29502e", 0xb}], 0x1)
execve(0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000040)={0x0, 0x1, 0x80000001, 0x60451d, "1a0c0109020400"})
writev(r0, &(0x7f0000000080)=[{&(0x7f00000000c0)="f2d98d803406fd3f3ae5de618b17e9c1863bd9118a145f9927f34224a70b765f5806ae62f1ceb57a7b93f96e8e8dc14b12f84c4831d1d73185fab7287794eeabb85c67aecbdc7e3b26d4e0960bf6856696a6b425ecd390f200df7bf5c8130233405cd8380398effd73af2948c02fc62f8a9361f8b7e8e0ae77a11789fac5b770be9346f42a68b0c6c8968e1168dacf63730a99da1e9a73951895db801b8504", 0x9f}], 0x1)


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000a, &(0x7f0000000040)='\x00', 0x1)
setsockopt$inet_opts(r0, 0x0, 0x200000000000a, &(0x7f0000000380), 0x0)


syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000), 0x10)
r1 = dup(r0)
listen(r1, 0x0)
r2 = socket(0x2, 0x1, 0x0)
connect$unix(r2, &(0x7f0000000000), 0x10)
r3 = dup2(r2, r2)
shutdown(r3, 0x1)
accept$unix(r1, &(0x7f0000000140)=@abs, &(0x7f0000000180)=0x8)
r4 = socket(0x18, 0x2, 0x0)
dup2(r4, r3)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000480), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000140)=[{0x25}, {0x74}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])


setreuid(0xee00, 0x0)
r0 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r1 = getuid()
fchown(r0, r1, 0x0)
r2 = getuid()
setreuid(0xee00, r2)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r3=>0xffffffffffffffff})
bind$unix(r3, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
lstat(&(0x7f0000000040)='./file0\x00', 0xffffffffffffffff)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {0x0, &(0x7f0000363000/0x2000)=nil, 0x2000000000}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000191000/0x1000)=nil}, {&(0x7f000003d000/0x1000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f00000c3000/0x4000)=nil, &(0x7f0000ffa000/0x4000)=nil}, {&(0x7f0000157000/0x1000)=nil}, {0x0, &(0x7f00001eb000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f00000e0000/0x1000)=nil, &(0x7f00000d8000/0x3000)=nil}, {&(0x7f00000ca000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f00000f8000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x2, 0x0, 0x0, 0xffffffffffffffff})
ioctl$VMM_IOC_RUN(r0, 0xc2585601, &(0x7f0000000000)={0x7, 0x0, 0x0, 0x0, 0x0})


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r0 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
geteuid()
getegid()
socket(0x0, 0x0, 0x0)
shmat(r0, &(0x7f0000001000/0x3000)=nil, 0x0)
shmctl$IPC_RMID(r0, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x2, 0x2, 0x0)
bind(r1, &(0x7f0000000000), 0x10)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000240)=[{0x3d}, {0x5c}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f00000001c0)=ANY=[])


mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
ioctl$SPKRTUNE(0xffffffffffffffff, 0x20005302, &(0x7f0000000080))
madvise(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x6)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = kqueue()
kevent(r0, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000400))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000140)=[{0x14}, {0x2c}, {0x16}]})
write(r0, &(0x7f00000001c0)="d9537abde93d050cdd16b13f742a", 0xe)


mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2010, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f00000019c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000480)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f00000007c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000a40)='./file0\x00')


r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x3e, &(0x7f0000000000)="5ab7776a", 0x4)
r1 = socket$inet6(0x18, 0x3, 0x0)
dup2(r0, r1)
getsockopt(r1, 0x29, 0x33, 0x0, 0x0)


writev(0xffffffffffffffff, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000000)=[{0x87}, {0x45}, {0x6}]})
syz_emit_ethernet(0x1b, &(0x7f0000000000)=ANY=[])


r0 = syz_open_pts()
ioctl$TIOCSETAW(r0, 0x802c7415, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, "ab7f93b5e88ee3bc955efc092e8d349bba354316", 0xfffffffa})
syz_open_pts()
socket(0x2, 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000005c0), 0x10)
r1 = socket(0x2, 0x1, 0x0)
r2 = dup(r0)
listen(r2, 0x0)
r3 = socket(0x1, 0x5, 0x0)
r4 = accept$inet(r1, 0x0, 0x0)
dup2(r4, r3)
write(0xffffffffffffffff, &(0x7f00000001c0), 0x0)
recvmmsg(r4, 0x0, 0x0, 0x42, 0x0)
ioctl$TIOCSETA(r2, 0x802c7414, &(0x7f0000000180)={0x0, 0x8, 0xd, 0x0, "1a91a80201d03f84e33ee7790000000500"})


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000001140), 0x0, 0x0)
r1 = openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
chdir(0x0)
r2 = open(0x0, 0x0, 0x0)
mkdirat(0xffffffffffffffff, 0x0, 0x0)
syz_open_pts()
close(0xffffffffffffffff)
syz_open_pts()
ioctl$TIOCSETD(0xffffffffffffffff, 0x8004741b, 0x0)
renameat(0xffffffffffffffff, 0x0, r2, &(0x7f0000000340)='./file1\x00')
ioctl$WSMOUSEIO_GETPARAMS(r1, 0x80105727, 0x0)
ioctl$VMM_IOC_CREATE(r0, 0xc0285602, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffa000/0x2000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffa000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff9000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000ff9000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff8000/0x4000)=nil, &(0x7f0000ff8000/0x3000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}], '.\x00'})


sysctl$kern(0x0, 0x0, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afe", 0x0, 0x0, 0x0)
semop(0x0, &(0x7f0000000100)=[{}, {0x0, 0x2ff}], 0x2)
sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000000)="9b1809ffffffffffffff7f473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6fd74c94d1b44", &(0x7f0000000040)=0x10011, 0x0, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x6000, 0xe02)
open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x6000, 0xe02)
r0 = socket$unix(0x1, 0x5, 0x0)
ioctl$FIONBIO(r0, 0x8004667e, &(0x7f0000001400)=0x1)
connect$unix(r0, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
ktrace(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0, 0x0)


r0 = geteuid()
r1 = semget$private(0x0, 0x4000000009, 0x82)
semop(r1, &(0x7f0000000180)=[{0x2, 0x7}, {0x2, 0x8, 0x800}], 0x2)
semop(r1, &(0x7f0000000140)=[{0x3, 0x4}, {0x4, 0x7f7e, 0x800}, {0x0, 0x1a, 0x1000}, {0x4, 0x3, 0x1400}, {0x0, 0xe0b, 0xc00}, {0x1, 0x3, 0x800}, {0x3, 0x800, 0x1000}, {0x4, 0x7ff, 0xc00}, {0x0, 0x33, 0x1800}], 0x9)
semctl$SETALL(r1, 0x0, 0x9, &(0x7f0000000040)=[0x7ff, 0x1000])
r2 = getegid()
r3 = geteuid()
semctl$SETALL(r1, 0x0, 0x9, &(0x7f00000001c0)=[0x7, 0x401, 0x95, 0x1, 0x5])
semop(r1, &(0x7f00000002c0)=[{0x3, 0xffff, 0x1800}, {0x0, 0x0, 0x1000}], 0x2)
r4 = getegid()
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f00000000c0)={{0xeaf, 0xffffffffffffffff, r2, r3, r4, 0xb, 0x7}, 0x6, 0x6000000, 0x5})
setreuid(r0, r3)
r5 = getuid()
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f0000000240)={{0x21d, r0, 0x0, r5, 0xffffffffffffffff, 0x1, 0xfe00}, 0xdce, 0x32f9, 0x3})
r6 = getuid()
r7 = semget$private(0x0, 0x4000000009, 0x82)
semctl$SETALL(r7, 0x0, 0x9, &(0x7f0000000680)=[0x9, 0x6])
r8 = getegid()
semop(r7, &(0x7f0000000140)=[{0x4, 0x200, 0x1000}, {0x3, 0x6, 0x1800}, {0x4, 0x201, 0x1000}, {0x3, 0x1000}, {0x0, 0x7a5}, {0x3, 0xff72}, {0x1, 0xdb, 0x800}, {0x3, 0x0, 0x800}, {0x3, 0xa, 0x1000}], 0x9)
semctl$IPC_SET(r7, 0x0, 0x1, &(0x7f00000000c0)={{0x9, 0xffffffffffffffff, r8, 0x0, r8, 0xa, 0x7}, 0x2, 0x2, 0x10000000009})
r9 = getuid()
setreuid(0x0, r9)
r10 = getgid()
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f0000000000)={{0x186, r6, r8, r9, r10, 0x51, 0x5}, 0x2, 0x100000001, 0x1})
madvise(&(0x7f0000000000/0x4000)=nil, 0x0, 0x18)


r0 = kqueue()
r1 = open$dir(&(0x7f00000000c0)='.\x00', 0x0, 0x0)
kevent(r0, &(0x7f0000000040)=[{{r1}, 0xfffffffffffffffc, 0x7}], 0x7fffffff, 0x0, 0x0, 0x0)
close(r1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000340)=[{0x4}, {0x35}, {0x9106}]})
syz_emit_ethernet(0x4e, &(0x7f0000000100)=ANY=[])


mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
sysctl$kern(&(0x7f0000000040)={0x1, 0xa}, 0x2, 0x0, 0x0, &(0x7f0000001440)="cc", 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000000c0)=[{0x3d}, {0x45}, {0x8006}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "1a0001ad09fb000700000000098000"})
writev(r0, &(0x7f0000000080)=[{&(0x7f00000005c0)="fb051aea3f669986f7bd29eed47902538960e80cfdcc03e596bf70240e08a7c28327a48426cfc9523c60b4b3be6da4309ba34030436c6f8c33e9140d56b3", 0x3e}], 0x1)
sysctl$vfs_nfs(&(0x7f0000000000)={0xa, 0x5}, 0x3, &(0x7f0000000180), 0x0, 0x0, 0x0)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000140)={0xf34, 0x0, 0x7, 0x479b, "bb5d8846eb3c87f896bf01c2b1be4c895091a896"})
writev(r0, &(0x7f0000000700)=[{&(0x7f00000000c0)="9af2baecbeb339e70dbe111c5720cbf1776dae432811135fb69471cf8ef7cc99c39917e8174bb309b0e7df00135f437c0923e7d9f3de99e1c5a059ce635df6f1e2e32e1fc6a5c3dfc7a24484c8bc2845af40f6f61279dc0330bcbdd5a880", 0x5e}, {&(0x7f0000000180)="9edb3bd3e1cc5cb43ea52cf2bce66a455cd7598db84351826b290ed541eff508dc0ea345de5f8a1efde549705b7c9d633c54ccd5672c5c6dd65d50b64bc1fa6e676f71c965e70d", 0x47}, {&(0x7f0000000200)="2434bca619b2110bd4b4bd079be055bac9b684ad36cd12dcd39eadba9168c325d9b61d60e4ea7ebb1f7e774dd9607018e408cfbe8bbec0a101caaa87922d49efa40a766c8f0fe8b2a6222fc2e6599c9c7a8560d8b75aec8884bea3c0e8929f9815f4dc2504ec119fbcde38f09304d51745647b374ff19af1b83fe666a0e70116e5ff30ffc172fb1ceac26df12344eac5e7a8c3976466f4d0456bb02426fc77fcffcd722c5128506f1b8e3165bb025247e557fba606e6e9aee0a360f98b5d89e400d78abf950793dc023bfe0fb43feca9700ad23e56561070218e62fd56acab2df837ec7e17", 0xe5}, {&(0x7f00000004c0)="b17df885f3ce9a8407e96723fd4015cf5f72ec9a74f6ba67224b41ab5b7ca5c5a62576b840a52e0d3dcc2872d7fe75b78a9ae575f078c2e56ff5cba251824a1a55ca3a745bd2eb66323e683efcdd89989dd186ec456505c4d397d1023566630dd3e7355efcf69756732486696cdc378ae64938a55999fcda43662c79161f3bacd2c525d06fd7face8be583850fa0e69aab73f4ebe88543dda701a754d16671fdffbb95a41fbbd3cfe470dab25f92a5e86ec9d8bae476a4f4299bd3497adab03c5016c5f477fac76d6662d4d0c644e33c2ecfc8197379136f9e0522ed1d73942cd7f1b6bfb0", 0xe5}, {&(0x7f0000000300)="73f8a324832e1e7bf34eee08bf9c1fedbdcf4d4f48793eea63002744c3f6057991552edd61fb96d8ab5640d84c96131f4dc412add23e360ce1d94fefca31b39010a38ab9f2f957e09887f2d36d7e4b5b00f9b392b733d5cf45", 0x59}, {&(0x7f0000000ac0)="f85ca1d0bab1e4c1ab2e90ed60342ac59359b735d68dbb06a23831556e05fee25a1cc3557b1f59cb719cd5d4d738ce430efedbbc8b2fca9f1b7de80b3fa350d385ae54c590c714624628fb0e4a7f80b63832fcd484a945686f8d5b051822c1ce4b599e27e577c03312920872c8aa4227d169ab77da5add6ac147444c0b9d8bbe1381131f7a8a748ba3676335faf4d7ad861693dc614387d8bdd8e39f1b66c05b1d499159d41a3d71deb8654d6cbd5757a6b135b559a4f765967e4b083e613f124caa6106958066b2b63c4a835514244e413bf3054603818006b16bb266ddbcfbda9eddf876496a1993bced16af42d2da4d5415b4679a631fc186d65a1c9796a6135a28bb65d33809e9c8a3f75da84134e2a3899908a72ffc296413416b58b91e942edebf1f3eb1b846b80890c85b9f72d81484e5a1bccab44816617cfa4ef10ee93d0b1889b3a2a29d913572a62418414b4793c3bb5c6a65e4914350d984f4db8924992e13ede84246f826f9d69f0f0733511e71bfb779f59975a0db59fe083e1d69bf1f9b60c44a46f9d22b964343e4580f5b5685a6038aaadf1335fa20c4468581e41ec1e5c89779a4728f130f51a8e16027395b7c6e0ed850b66408026277137a811a26345656f73c67b9d1161b2388f09e8ba269c9e18d67789b9a1b089c4908a859681ad448c4e9ee99812ff63075ed0e7cfd9936878d28e9c407660183f91cae89ac0bbfe64edf01c9a80a9f56423247e58bb323808327b207f785ed052be81c1bef368590f8c03cbf98ac3005b4a74d2b8331eb83f77cc4ea69174a6aa38ca594882c76bdaea0f7fa04ec215e8d34980c123c4659d573607bb6845b119ded184e74a01d1593757ea484034a8735415970bccef38a7a774e94fed4816923f6a699911982eb926f4a77142841163cf9254b4e66ffdfc82e0511cee617c892acd5ec1d99084ab3a5ee5db57bd7fd79815569c7074e3824d5a98bb2d4de9d017f880db01baf81a0e0c27e0e4a2a34e0bef25b75039e189e3c8972575dd52ea49b0f191517f46d49f19c738f72c88fb2dce50a9deff39220a8890900418b13790646e2963b0b1540f27556825fbda8352fd2082da470566499e8402ae71deb00a439dd65f266d9bdcdab081c1cd42e401fed621e70b68b416473a39c54a70aa4929fc474ee4b7f40e493742c3cf298beb9400c2fec4c374484fa13919b9335b8b5f0fedf4b462f21796bbe23f8b93eb4278620f5a39c477aa7b7eafc3e21deb6130078ae6d873a43830817f09e475a7ea7dc47565cceca01f4eb45c505372b534812aefef0089d71fda1ac36e7276310266f904988ffeddbf7f6c7e2aa56602112b06956af4a94314bce802ac1db11ee20f148c42a1149f740bc1c7c1689479da0dd8ebb394de51271671fb69a412d3e00f295bf19a19e4d5c27979454b84d1197faa7f065876d3692379c1852ea6c74a03fa25e0549e366f6567d58e5d7d122b649f83c83fb6892cc53ba57450ba6dc9f2fdc472fd4f4413668462325b91d37e979557df2b97b752ffef4d292841df8b20f9d5dab76d8a729a99bda2dc0ecb56d42ed18eed29a17464ea31e31f1d667009b7cb202cbc957d481634310fde527d04276577b349508b66650962d44d686033f84a99af17eb7076d722f3b08ebe6233c6574cc1a7c6bf9eef032e764c460ec5425eb444ade11d279583092f8c4502975e330679d93635a9b7acb2d328ca17a836c374a3ac50c80e0cd55ab2aff0895b982614615a3b841b8d044be2dc641c3eb2cf4bb19151317833606ce63d4d913ed102ec86455443bbadc126b5132cf6701c2af3e9eab42df1de971f6efecebfdaef0bd0d86eac4287464c78219b8901511bffbdb9c9aa51c3fab172c74b041ecb845f33b9d1de5dda9f8b8ecb56cf91cf316457184d923fe38fe365ea6fe243f94a5d869c1b6ca1d7f2cfb98d6f51b8775709188443734ff86788a3b1df27aa0de006e18dc889703dc9e80173f3d05153360e70e0675f97c5a02a43e38e86825c7b372f41a32624a7c99af21d3c6a426306b51c0045e01650c808bc51c1c7a51ea347031746c587d909c50ead0acecd74a6b87cdae173a1a4497b9ec0ce8a0a2f331dabe857d481497d06b9c06a9a7e5dd0fde2f111797a4877dd57be9800e5472ea1dfd588a13b5c3b91e2e3174fb49a436982eb63f4c3a029d8669cb73457fd05871f9d2cff6116048aa4c08dd0cdc46721bce577e2b8045f17a51cab7586da3cdf849c0ae0b0d3cf5465959b3b03482785f95daea790c753d4c713ac603f4c4e37cccdeba6c5a9a515021ca1b9f63e1f3ab224d27ac209ad811d26af9ab657fb2f48df1d70387b9ddbe96e1f992aa7d2530420c1dbf0049ffc3393476267e6ab053a0897ca5f8712d95295b309a77c3255fe8cdc25b0ce657c76f0d8933e713485a245b1ba44f082bb17d9b831c15cd9d373cfbcb40dae0d3ad4dd0f77d2e4da1e6bb62b7cea06adbc5fdc392ebdf279ccccc3d3c85b587c60b7387eccce34b51dcf8ac7c108594b9643a404a6d63795e2e68db6a5c8c0df44c17f3829e702dd49d35c1199ae7b5cdcab9f56deec8ec07a2abbede4fd6deb5f3d54c1172c65fa8b9307210c0e3518aafa7170b7a449a9788125fd4c68e4342c4aa2e33c79d44b041c3ea1e2534e987a99ea4092d04b673221a78209a8a440b483f0db6184d549f01320d12502184625a2a8afa0ebd247b8d902796f44233d109334623e64bf07060cd5ff1fb68f802eb78a52e931a94b021d87aad7adef6a78b3b277f702f1d9c8f209f97dfdb38e1f09d642810a957a5d19e5c8f1b2ac89367cf701624fb163cb513c592ce1c7860ebed8bd50cb08f34afec315c3328a20f19fde52cb8b3929a91e6fea087014e36e7df3a2c13fc4e9c11e157aee21d06207e8056bb9b5898e98fa2d434e7ed295edf1cc4df59e8dbb4a14c4dfb34df7f6ebad7a19510e1fac6c6282806f3e7a74a52fa7ff3f74fd63ed7cb4809b54760260599282660ed2eb894e09d728a89486270f61f297c6bd3dcdef703365828d170f07411e989fd5c276df4ea6f31fbd2ef58511d1a935fbf6f6e58b038929512ffb324e2e368b18a1dc44e3f33a33038792b63e6f65868c44f053bb7d9fe70a64474263ea92257fe107dff93e707153046c95656c7e35122c9bfdc474bb779b34ab35a96108d905b4c32c2766017d507872948c802c1a120467ec2318492181c3b9a2063b1537761e3d53969d754a4553839752e80a47cd9f2835ea85aac6d5815a5f4686e132745a8c16cfdfbfeeb48b89d1a0473d168f5cf268b6e140ec7c0d7abaf14410da789c17004031c9c9fba446c7e698c74377ec6930365adbb7aadb2bedae64bd642a1b2378448588f4a00c56046e3968ad94b5d20704afaff987e94796378bd99a93f7112a0119d1d0ef69c29e6e200b27505ffd32bd3394610b1c6c5a56390e0f30779a0e068711ce31fc1a7cb305d270248122f242205c2e772fd235997ad949c190512ef59dd0ee7f750e318306caed8cb202bf6202e714c217986d70c6f1438f123fcccee976d3bdc0e753e54a4cdb20be8dd5a586aa34aa611ba706caf4eb1128114deb42ded8b1b07b43f4ef7cce82882bb4fe6e4b64b4ce17461f59eb0c218681222f68836e54e48b20a1d78186bcc16471dfc1825c67eaf870e31296ee7a4abe3eb1d3d308628abc4378521f29ddc39aea26137453fafd44152aa224007d210ad91a4ecaf0ab09491f906f94825dfb3948e322a75956a7f46b7017eee22c3dbfff4a431e729f65eb13d43d2a5745ee1bd609b467d9c7cb173ca7cf3e1ac3ccb28fc32c620ed5b03c044985ae0b631df44e8e91db87c0a255ad0f1904a56bbddf3cc97ad8f0a49e3f3428213186879f8fd1526b205df57e8c4f401b9690b00381515665129443b7acba4f1a0ced3a75f7cad04812d7f3b8f335722bc5558cfd0361c8dfc9adcc4d275a167c518120018bccbb8b29d94d08f2ef2e9714fcaf9a6824f36eef9e6921637cb28d8f0d28bd744596ead01ea2f02a2481aab0873b7ffd8be7d13ed2d4ea8f85010f2cb8e2e236d156fb0564cc2c2cc28e9d8995380b1731779b6dc9a77e8496fd24e9e19f9556f56eb505a071f5689fa681a208dcea02091893115bd4e089a4a2bd2e6e4f2e9666e08b3f9a701a20dc67e517a2f36cfe6c17d37e538e1e82fdd57f12b5f73d0cf8daaee41cea01adea78f6f9d816968638c407967b9416b6c3d667c6a96b3db4e3ec697450d9fc3476c001cbd58d98c980fb343c0fc7c81cfa7f4b32f6f0bd464e84eac62db0b001f2e34d293d54d473fe51e20654c41e25b64b44abf9e6afff459214fe30dd9e72b0c4ffb613118130815a9c69a95e4b3a75e5e974a1aea249da27da83a1b6018ed433a3c10e1f687a433f1dbe9def8a441f7ede85d145c94593128215d943f081865ff5fa4dd10420222425d3b715476021b1fb5c1c2d53c0059fb3001297beb493e0e8310b7810c7765de2136a94fd260a7728085eda416be1ca9aff7946dd516cc7499ba8a8fd5d584ab39392253c6d992e871ee5669e47147f8c276940c223adaff97f9fd702161737a59f8f2633113e4a1d8957c34fdf696b7b60fd23988236dbc559e2d71b3d0f370adc03b6b51008a3ea5911c3a96ed345531e03cadf04b4b9ad6606c3b33d097af6f99bedfcc44b8891589c4b491302902d69d70729cb34cf5ffa07a7c5ecb8b06b05a2df0cc2aae1f6863db2a16292ec8afa6f27ea9a8a918c8a24b53ff3903f4a7ed76952bbddee40910b8407234a9b51e5b246e2bfc63b342412de493b1e62ec3fd2166b4aa802a1772a5f6cc0ebad4e0f10b008268eb8c6f7fba68588c3748f516933fb3b67217fe569c8ec666e612e00b65acf21b7b537bf33dec7cd43c2f97dd453d652527bf3f28e9adfdea45340186fbe420eec26b81c46f07dcfbebfed55dee7d56920d289eb1f352df774dc4d4601848ec2b7bffc166631d558f80c7cc745ddad3d24e40a2399017d822d9a66955c1de79187fdbb8d5c7eb20576a6c3b69c125ddcda33dc536d43c0ac07a85f13d39d8bd73d4282697f22d181d70a26a90dfdcdeda19c85f955456ca9c92224cbefaf037392bcaddc13d68c226dc7288ab23734e509d5d4737ad1fb8e888af5783f876b559f2b177df5dff805752c91a6b9c07c990b0ad72e1ac2cd9ecd23512d0d60992c0f97b8c498bb8fee2b8816f75d5bea8e1c783d78969de06fa09df821076ac2cf6f1ae28df4c2333fa57c1fcbe040aede90864b0904fd245aefc5d8d2c1c4e56ca2586631d382caf1f2da26f73da72e73b0e782c439aac0735f71bfffed9d9c694a091395533ffca45566ffa7eb0eba8949efc85af0a79dc71382fbf61e132f0a047e8fb2dc966ec5ccd13e08ba987b80c00f0ca0e3eac5d68502de3d076e460b7cd3a36c2a6f59e7e3ad47de3a06beca214adbda2ccf024afd427b23dc967ff4c966e678d060726be0c40e387294bf1c177d05cfafbd356f77b0e52c55913be99ea73beb472e0ef4f98f7491562c5bb6ee2073a3b94ef2fa95a29678bdd38ba1585b04eed5d0af865f382903fc1a33440e062df6773a1e12caa672761f47e6751f9902622dd691709efb1ccf9a6a1690bdbfabfe01fbf58dcaf761d212c3006509d4ba5de74e2832cdcc05baf93d0f8d6f43df90913053b6af40d937a735ddad3c77df7e6acf2383e7eec32933e8c9038ac9fe7d5e4fa65b158377b602aa30624e71aef", 0x1000}, {&(0x7f0000000640)="4d18a1d00d059e4658185f8610e5dbc6503190cf99db70c9767a7881b439161ba84966268ad14dcc776ee06bec2915866deb430f35962b8d9768a1d61321c0217fa477a19b0f179d3a4d8d38a8f8a4df2900647596a566a363719d30a624e61b2bc063b77714eb37e161d7b0a992f07da16ad4893583ed20398f96099e2c69ad0ca04cc5b947", 0x86}], 0x7)
readv(r1, &(0x7f0000000a80)=[{&(0x7f0000000440)=""/86, 0xffbf}], 0x1)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, &(0x7f00000000c0)=0x2, 0x4)
ioctl$VMM_IOC_INFO(r0, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})


ioctl$TIOCSETAF(0xffffffffffffffff, 0x802c7416, &(0x7f0000000000)={0x9, 0x0, 0x80000000, 0xfffffffe, "cb00a6c8d30000000062ecff6a2129fe8d008500"})
write(0xffffffffffffffff, &(0x7f0000000200)="11d5fe656a", 0x5)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)
mprotect(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000001})
flock(r0, 0x2)
open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x82d)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f00000000c0)={0x0, 0x0})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x1, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r2, 0xc0286988, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000440)={0x3, &(0x7f0000000100)=[{0x4}, {0x6c}, {0x8016}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x4e, &(0x7f0000000300)=ANY=[])


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0xb, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
dup2(r1, r0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
select(0x0, 0x0, 0x0, &(0x7f0000000100)={0x3, 0xfffffffffffffffe}, 0x0)
r0 = kqueue()
kevent(r0, &(0x7f00000000c0), 0x7, 0x0, 0x80000001, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f0000000000), 0x723, 0x0, 0xd1c, 0x0)
close(r0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000140)=[{0x7}, {0x2}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000240)=ANY=[])


syz_emit_ethernet(0x36, &(0x7f0000000040)={@local, @broadcast, [], {@ipv6={0x86dd, {0x0, 0x6, "6aa63f", 0x0, 0x2b, 0x0, @remote={0xfe, 0x80, '\x00', 0x0}, @loopback={0x4}}}}})


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
setreuid(0xee00, 0x0)
r0 = getuid()
chown(&(0x7f0000000180)='./file0\x00', r0, 0x0)
r1 = getuid()
seteuid(r1)
r2 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r3 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r3, 0xc0106924, &(0x7f00000001c0))
ioctl$FIONREAD(r2, 0x80206910, &(0x7f0000000100))


seteuid(0xffffffffffffffff)
r0 = syz_open_pts()
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000200)=0x7)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000004c0), 0x2, 0x0)
writev(r0, &(0x7f0000000040)=[{&(0x7f0000000080)="cc031bd37bb57acfdbeb740e38b4ea2891bd92622b", 0x15}], 0x1)
execve(0x0, 0x0, 0x0)


r0 = open(&(0x7f0000000080)='./file1\x00', 0x200, 0x0)
mmap(&(0x7f0000012000/0x3000)=nil, 0x3000, 0x4, 0x10, r0, 0x0)
mlock(&(0x7f000000f000/0x4000)=nil, 0x4000)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x5}, {0x2c}, {0x83c6}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f00000001c0)=ANY=[])


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = semget$private(0x0, 0x2, 0x82)
semop(r0, &(0x7f00000000c0)=[{0x4, 0x3, 0xe5ce97ab354d96be}, {0x0, 0x4}, {0x4, 0x2}], 0x3)
semop(r0, &(0x7f0000000440)=[{0x3}, {0x2, 0x94}, {0x0, 0x2a4, 0x800}], 0x3)
semctl$SETALL(r0, 0x0, 0x9, &(0x7f0000000040))
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
r1 = getpgid(0xffffffffffffffff)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000005c0)={{0x9c2, 0x0, 0x0, 0x0, 0x0, 0x1, 0x8000}, 0x3ff, 0x5, 0x0, r1, 0x0, 0x0, 0x0, 0x7f})
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
r2 = geteuid()
semop(r0, 0x0, 0x0)
r3 = getegid()
semctl$IPC_SET(r0, 0x0, 0x1, &(0x7f00000000c0)={{0x7, 0x0, 0x0, r2, r3, 0x88, 0x7}, 0x7, 0x6000000, 0x5})
socket$inet6(0x18, 0x3, 0x0)
getsockopt(0xffffffffffffff9c, 0x2, 0x7, 0x0, 0x0)
r4 = socket$inet6(0x18, 0x3, 0x0)
getsockopt(r4, 0x29, 0x0, 0x0, 0x0)
getsockopt(r4, 0x2c, 0x51, 0x0, 0x0)
getsockopt(0xffffffffffffffff, 0x29, 0x25, 0x0, 0x0)
r5 = socket$inet6(0x18, 0x3, 0x0)
getsockopt(r5, 0x29, 0x25, 0x0, 0x0)
openat$diskmap(0xffffffffffffff9c, &(0x7f0000000440), 0x10, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000580)={&(0x7f0000000340)=@file={0x0, '\x00'}, 0x3, 0x0}, 0x0)
unveil(&(0x7f0000000000)='./file0\x00', &(0x7f0000000040)='r\x00')
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0xfffffff7, 0xffffffffffffffff, 0x0, 0x0, r3}, 0x3, 0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x2000000000000000, 0x0, 0x5})
connect$unix(0xffffffffffffffff, &(0x7f0000000280), 0x10)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000240)='c\x00')
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
writev(0xffffffffffffffff, &(0x7f0000000180)=[{&(0x7f00000003c0)="4844db2f8e905208d0ce7e0203", 0xd}], 0x1)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000000)=0x8)
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
kqueue()
r1 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r1, 0xc0206921, &(0x7f00000001c0))
sysctl$net_inet_udp(&(0x7f0000000000)={0x2, 0x4}, 0x2, 0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r2=>0xffffffffffffffff})
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f00000001c0), &(0x7f0000000200)=0xfffffffffffffe50)
socket(0x0, 0x0, 0x0)
r3 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000d40), 0x1, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x1, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r4, 0x80104277, &(0x7f0000000080)={0x0, 0x0})
write(0xffffffffffffffff, 0x0, 0x0)
close(r3)
sysctl$kern(&(0x7f00000000c0), 0x2, &(0x7f0000000100)="71f91e3471ac00", &(0x7f0000000180)=0x7, 0x0, 0x0)
socket(0x18, 0x1, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000200), 0xc)
mmap(&(0x7f0000ffa000/0x4000)=nil, 0x4000, 0x2, 0x6012, r3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffff9c, 0x80104277, 0x0)
sysctl$kern(0x0, 0x0, &(0x7f0000000100)="71f91e3471ac00", &(0x7f0000000080)=0x7, 0x0, 0x0)
munmap(&(0x7f0000e34000/0x1000)=nil, 0xffffffffdf1cbfff)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
openat$vnd(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0xfffffffffffffffe})
mprotect(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x1)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x6)
utimensat(0xffffffffffffffff, 0x0, &(0x7f0000000040), 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x4}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x2c}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0xfffffffffffffef1)


setrlimit(0x8, &(0x7f0000000980)={0x9, 0x51})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
select(0x45, &(0x7f0000000000), &(0x7f0000000040)={0x7fffffff}, 0x0, 0x0)


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
ioctl$FIOASYNC(r0, 0x8004667d, &(0x7f0000002d00)=0x9)
shutdown(r0, 0x1)


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x17}, 0x4, &(0x7f0000000080)="775ea3a7", &(0x7f00000000c0)=0x4, &(0x7f0000000100)="c80250c7", 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x7}, 0xc)


mknod(&(0x7f0000000080)='./bus\x00', 0x6000, 0x20e02)
open(&(0x7f00000002c0)='./bus\x00', 0x0, 0x0)


r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x40047307, &(0x7f00000001c0))


mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x5593)
open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000180)={0x3, &(0x7f0000000080)=[{0x87}, {0x40}, {0x6, 0x0, 0x0, 0x1000}]})
write(r0, &(0x7f0000000040)="7f00"/14, 0xe)


r0 = syz_open_pts()
r1 = getpgrp()
fcntl$lock(r0, 0x8, &(0x7f00000000c0)={0x2, 0x1, 0xfffffffffffffffe, 0x10000000f2, r1})
r2 = socket$inet(0x2, 0x1, 0x0)
setsockopt$sock_timeval(r2, 0xffff, 0x1006, 0x0, 0x0)
getsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000000), &(0x7f0000000040)=0x10)
sysctl$vm(&(0x7f0000000000)={0x4, 0x2}, 0x7, &(0x7f0000000040)="c06d154be3aee5f8787f8b9cda7554335b763bb5deea5ccecb4d1b57a9f6fa18e47fc7b119db587e58811e666e84a806495b45c36164bd5b135280243ed0a01466056e93082876ba33ee8cf2b0b3907f236f38175101000000d7e39544aea098d19ee63d03cbf92380dbe904538135f09e408bbe17a54a364b04ee64b0ad54e6d4e38114ced38c328aff2e224239ba29eb0796e8c3e8344a2cd9e663bb21035ebf391872f3015c164556e4a5b966122c56edd85fc996f12fa1b92e47aa", 0x0, 0x0, 0xfffffffffffffe8f)
flock(r0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
close(0xffffffffffffffff)
syz_open_pts()
socketpair$unix(0x1, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
openat$pci(0xffffffffffffff9c, &(0x7f0000001740), 0x0, 0x0)
accept$inet(0xffffffffffffffff, &(0x7f0000001780), &(0x7f00000017c0)=0xc)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001840)={&(0x7f0000001140)=@file={0x1, './file0\x00'}, 0xa, 0x0}, 0x0)
r3 = socket(0x0, 0x0, 0x0)
bind(0xffffffffffffffff, &(0x7f0000000000), 0x10)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f0000000000), 0x10)
sendto$inet(r3, 0x0, 0x0, 0x0, 0x0, 0x0)
socket(0x18, 0x0, 0x0)
sysctl$hw(&(0x7f0000000140)={0x6, 0x9}, 0x2, 0x0, 0x0, 0x0, 0x0)


sysctl$kern(&(0x7f0000000000)={0x1, 0x27}, 0x6, 0x0, 0x0, 0x0, 0x0)


symlink(&(0x7f0000001340)='./file0\x00', &(0x7f0000001440)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
rename(&(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000f40)='./file0\x00')
rename(&(0x7f0000001140)='./file0\x00', &(0x7f0000000240)='./file2\x00')


openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000200)={0x0, &(0x7f00000001c0)})
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000), 0x10)
r1 = dup(r0)
listen(r1, 0x0)
r2 = accept$inet(r0, 0x0, 0x0)
r3 = socket(0x2, 0x1, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)
r4 = dup(r2)
sendto$inet(r4, &(0x7f0000000100)="03c019b7e2399b388d3cc45f01364c934feea3d4c1fbf21dc5dab6090e154d84d22c5ff1da069dd0d4af159f8000000000000000c892a0", 0xff4c, 0x401, 0x0, 0x0)


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
sendmsg$unix(r0, &(0x7f0000001540)={0x0, 0x0, &(0x7f00000014c0)=[{&(0x7f0000000140)="1487a91f73502e1469656667cd491f0aac1d76a3951ac5e4315eaf4e992f77b624d21ec5aaf2fb791bc8cfecc0bc7292f0b622145ff1a2ccaeb213c06874dc03053260855a2c81c6a34e69bd2622427b9bed9eacd0ad416a0f35dea7036de0e481a931734287c4fba2e512ca962d40811ecbf0bbe8c417a52420e505ca6cf8d93d76dc6b1ba61df3cf54d1db2a7f5a039587dff5b8ebf3d5856ae63f5ccc4934424eaa656de44969d5941cb03e6f12f36da0ef4679fd3fbe49b1048c2656a3f01734b53f1f7465c13eb59c23ca7a55d5d657454c9f9737541176eeb5a68302f886c3bf9383eb73b41b786bca11776638a8d6323a5a5cd3439ed680c0ddc5c459f92590a88e4bbd42648521054c070bf1afda91343d3f3b158ee6b81d5128fc916fcbc7950a48c3e1a48b3f562984409e01564e00c5d1ade231866635ded88ab398f19bc35972e1bda100b51bc4a0b4647169d8e894e60bcdbebf8d520831174a8a2026696dc8d680fd70a4637625662c0f", 0x171}], 0x1}, 0x0)


r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
r3 = socket(0x18, 0x2, 0x0)
r4 = socket(0x2, 0x2, 0x0)
r5 = socket(0x2, 0x4001, 0x0)
r6 = dup(r5)
r7 = fcntl$dupfd(r6, 0x2, 0xffffffffffffffff)
close(r7)
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r8 = socket(0x2, 0x2, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
connect$unix(r8, &(0x7f0000000000), 0x10)
r9 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r9, 0xffff, 0x1023, &(0x7f0000000040), 0xe0)
r10 = dup2(r3, r4)
connect$inet(r3, &(0x7f0000000080)={0x2, 0x3}, 0xc)
setsockopt$sock_int(r10, 0xffff, 0x1023, 0x0, 0x0)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1000300000001, 0xffffffffffffffff})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x1ff})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000002a80)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x1000000000000000, 0x2}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbdf13b9fd812eaa4e713048e69931929648", 0x14)


open(&(0x7f0000000480)='./file0\x00', 0x200, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
recvmsg(r1, &(0x7f0000002880)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
bind$unix(r0, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000040)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000080)=0xc)
chown(&(0x7f0000000280)='./file0\x00', 0x0, r2)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
setreuid(0x0, 0xee01)
connect$unix(r0, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


open(&(0x7f00000000c0)='./file0\x00', 0x200, 0x40)
mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x0)
sysctl$net_inet6_icmp6(0x0, 0x0, 0x0, 0x0, &(0x7f0000000140)="80468b309b2548cca0c3bd621508525753789a6678d065d43ee4beba5f1b29d75f17fbc7afd04721d15570cfc48e0c124334ca8f55e8fe16ae3c48f5447f2ffc59e1de35169f015f", 0x48)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x8020697a, &(0x7f00000001c0))
kqueue()
sysctl$vm_swapencrypt(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x31}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0xfffffffffffffda3)
setrlimit(0x0, &(0x7f0000000980)={0x0, 0x35})
r1 = socket(0x18, 0x2, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
close(r1)
r2 = socket(0x18, 0x3, 0x0)
setsockopt(r2, 0x1000000029, 0x32, &(0x7f0000000440)="b211d7170d816685c8e360f2fa41c1a0946988b272a746e337b372e93320cff6669cbe7868de45ed3fc33719ca6df71ecec8a900108b2c10a1f8c66653b276e180e9cb9b21f9982230f575295d48889c98000796b2dd921a4975680b37ba955d2c15e6d7c9198ed900ab006ddfb6f869b51a2216114d1ece85f593e74035f5bc054eb1dbddf42a004000000000000000", 0x90)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
writev(0xffffffffffffffff, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_open_pts()
sendmsg(r2, &(0x7f0000000340)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000380)=ANY=[], 0x11}, 0x0)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x28, &(0x7f0000000000)="5ab7776a", 0x4)


r0 = getuid()
r1 = semget$private(0x0, 0x7, 0x3c0)
semctl$SETALL(r1, 0x0, 0x9, &(0x7f0000000380)=[0x400, 0x1, 0x8, 0x6, 0xc65])
semop(r1, &(0x7f0000000100)=[{0x3, 0xe, 0x1000}, {0x4, 0x303}, {0x3, 0x7f, 0x1800}, {0x2, 0x1, 0x800}, {0x2, 0x202, 0x3000}], 0x5)
semctl$IPC_RMID(r1, 0x0, 0x0)
r2 = msgget$private(0x0, 0x597)
msgrcv(r2, &(0x7f0000000500), 0x8, 0x1, 0x800)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000000)={<r3=>0x0, <r4=>0x0, <r5=>0x0}, 0xc)
r6 = getpid()
fcntl$setown(0xffffffffffffffff, 0x6, r6)
msgctl$IPC_SET(r2, 0x1, &(0x7f00000003c0)={{0x6, r4, r5, r4, r5, 0x7, 0xfffc}, 0x2, 0x7ff, r6, r3, 0xff, 0x5e, 0x2, 0xffffffffffffff81})
getgid()
msgctl$IPC_SET(r2, 0x1, 0x0)
msgrcv(0xffffffffffffffff, &(0x7f0000000440)={0x0, ""/16}, 0x18, 0x2, 0x800)
getgroups(0x4, &(0x7f00000002c0)=[0x0, <r7=>0x0, 0x0, 0xffffffffffffffff])
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f0000000300)={{0x1, r0, r5, r0, r7, 0xb9, 0x3}, 0xfffffffffffffffb, 0x3ff, 0x6})
r8 = getegid()
chown(&(0x7f00000001c0)='./file0\x00', r0, r8)
mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x4003487)
r9 = open$dir(&(0x7f0000000240)='./file0\x00', 0x0, 0x0)
renameat(r9, &(0x7f0000000200)='./file1\x00', r9, &(0x7f0000000280)='./file0\x00')
r10 = accept$inet(0xffffffffffffffff, &(0x7f0000000000), &(0x7f0000000040)=0xc)
symlink(&(0x7f0000000080)='./file0\x00', &(0x7f00000000c0)='./file0\x00')
sendto$inet(r10, &(0x7f0000000100)="ee598539830f398c120aaa3886579eea1b584580c33c758bdd0f4ff15f7c55a3f9d4360548a798a52648b63d4a43e6", 0x2f, 0x0, &(0x7f0000000180)={0x2, 0x2}, 0xc)
sendto(r10, &(0x7f0000000080), 0x0, 0x8, 0x0, 0x0)
setreuid(0xee00, 0x0)
getuid()
setreuid(r4, r0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x7fffffff, 0x0, {0x0, 0x1}})


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x4000000000000002}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x100000000000000, 0xffffffffffffffff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
socket$inet(0x2, 0x2, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
sysctl$net_inet6_ip6(&(0x7f00000000c0)={0x4, 0x18, 0x29, 0x36}, 0x4, &(0x7f00000002c0)="9d88982b397f8d60586be19f4c136163", &(0x7f0000000000)=0x10, &(0x7f00000010c0), 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000280)={0x3, &(0x7f0000000240)=[{0x2d}, {0x61}, {0x6}]})
syz_emit_ethernet(0x1019, &(0x7f0000000400)=ANY=[])


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100))
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f00000000c0)=[{0x3d}, {0x30, 0xfe}, {0x40e}]})
syz_emit_ethernet(0x66, &(0x7f0000000100)=ANY=[@ANYRES64=0x0, @ANYRES8=0x0])


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r0, 0xc2485607, &(0x7f0000000040)={0x2, 0x0, 0x5c, 0x0, 0x0})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000040)=[{0x34, 0x0, 0x0, 0x10000}, {0x28}, {0x40e}]})
syz_emit_ethernet(0xe, &(0x7f0000000100)=ANY=[])


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
execve(0x0, 0x0, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x200, 0x0)
r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
pwritev(r0, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
r1 = open$dir(&(0x7f00000002c0)='./file0\x00', 0x2, 0x0)
ftruncate(r1, 0x0)


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000980), 0xe8, 0x0)
r1 = fcntl$dupfd(r0, 0x3, 0xffffffffffffff9c)
poll(&(0x7f0000000080)=[{r1, 0x51}], 0x1, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
poll(&(0x7f0000000380)=[{}], 0x1, 0x0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x0, 0x0)
writev(r0, &(0x7f0000000040), 0x0)
open(0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000))
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000029, 0x0, &(0x7f0000000040), 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000640)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000240)=ANY=[@ANYRESHEX], 0x18}, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {}, {0x6, 0x0, 0x0, 0x85}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0xfffffffffffffe53)


r0 = syz_open_pts()
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000001a00)=0x5)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{}, {0x54}, {0x6}]})
syz_emit_ethernet(0x1b, &(0x7f0000000000)=ANY=[])


getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000001c0)={0x0, <r0=>0x0, <r1=>0x0}, &(0x7f0000000200)=0xfffffffffffffe50)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r1}})
r2 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000140), 0x8, 0x0)
fchownat(r2, &(0x7f0000000180)='./file0\x00', r0, r1, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
socket$inet6(0x18, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
socket(0x11, 0x3, 0x0)
r3 = socket(0x11, 0x3, 0x0)
ioctl$VT_GETACTIVE(0xffffffffffffff9c, 0x40047607, &(0x7f0000000000))
dup2(0xffffffffffffff9c, 0xffffffffffffffff)
poll(0x0, 0x0, 0x3)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x4})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000006, 0x0, 0x0, 0x0, 0x0)
r4 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000080), 0x202, 0x0)
r5 = getppid()
fcntl$setown(r4, 0x6, r5)
close(r4)
sendto$unix(r3, &(0x7f0000000000)="b10005016000009f05000000070000007d9113fecea10500fef96ecfc72fd3357a068da3a5673039d2d236acf20b7804be38164991f7cccf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f45335c223e7d026ba8af630037282112000000720fd38bfbb770c1f5a872c881e2772ec5a10400000000000000361b1257aea8c5d0002012fbff0c230000880d6633c556ae9be371a3f8343712051eeab71d89000407000000800420000000", 0xb1, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x2, 0x0, 0x1b}, 0x4, 0x0, 0x0, 0x0, 0x0)


r0 = shmget(0x0, 0x2000, 0x300, &(0x7f0000ff8000/0x2000)=nil)
shmctl$IPC_RMID(r0, 0x0)
shmat(r0, &(0x7f0000ff5000/0x3000)=nil, 0x0)
getgroups(0x0, 0x0)
getppid()
getppid()
shmctl$IPC_SET(0x0, 0x1, 0x0)
r1 = getegid()
chown(0x0, 0x0, r1)
r2 = msgget(0x1, 0xbbba82ad40073d53)
msgsnd(r2, &(0x7f0000000400)={0x3}, 0x8, 0x0)
msgget(0x0, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
shmget(0x3, 0x2000, 0x2, &(0x7f0000fee000/0x2000)=nil)


r0 = getuid()
setreuid(0x0, r0)
r1 = socket(0x800000018, 0x2, 0x0)
r2 = socket(0x18, 0x2, 0x0)
close(r2)
r3 = socket(0x800000018, 0x2, 0x0)
bind$unix(r3, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x50}, {0x30}, {0x6}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x0, 0x0})
write(r0, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xe)


sysctl$kern(&(0x7f0000001680)={0x1, 0xa}, 0x2, 0x0, 0x0, &(0x7f0000001800)="0c2fa4104b6d7ea6f45936680015b295e404f997312c1e7b36b8c754554383a176005c23005531f61ff6da5822313d04a7a8879e3830ee335f7ce67ce00a8290bee6aaa27a9a0848f824aa628937512eeaa3be2cf4e080019e5d0f410297433a09a01591308b296d84012e60f55d750c54d68a8066fd324843d4dd064414437a01f616f0b908d82ac2a46e0042d2fbbc8df4146624d90b5a36f7dc45da720d895660d8da21717d22d11e5c03d6373dfd6a93cbdbaa2bb04286231e97f65c313b865ceb318a570a242fd76c9a5e20fbed3d8601e0df4a28b5c969a358428d2e96cdec62b8da89472d90ab03ae83c5de4ae50b977fdb7344c999d28dca30d50f1f", 0x100)


r0 = getpid()
getgroups(0x0, 0x0)
r1 = getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r1})
pipe(&(0x7f00000001c0)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
fcntl$setown(r2, 0x6, r1)
ioctl$WSKBDIO_GETMAP(r2, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
socket$inet(0x2, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
socket$inet(0x18, 0x3, 0x102)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
poll(&(0x7f0000000000), 0x0, 0x0)
recvmsg(0xffffffffffffffff, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
setreuid(0xee00, 0x0)
r5 = getuid()
sysctl$vm(&(0x7f0000000000)={0x2, 0x8}, 0x2, &(0x7f0000000040)="1b729cf5", &(0x7f0000000100)=0x4, &(0x7f0000000140), 0x4)
setreuid(0xee00, r5)
unveil(0x0, &(0x7f0000000140)='r\x00')
sendto$unix(r3, &(0x7f0000000080)="5bd772933e598e8d2ecaeeda3027efec040f00fe0ea32f98b57ff642989baa8ab2462c98f94fa145cab4ba3bda338cd37f", 0x31, 0xc, &(0x7f0000000180)=@abs={0x0, 0x0, 0x3}, 0x8)
fchflags(r4, 0x0)
ktrace(0x0, 0x5, 0x1b0b, r0)
shmget(0x3, 0x2000, 0x40, &(0x7f0000ffe000/0x2000)=nil)


r0 = socket$unix(0x1, 0x2, 0x0)
poll(&(0x7f0000000000)=[{r0, 0x4}], 0x1, 0x0)
shutdown(r0, 0x2)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000180)={&(0x7f0000000040)=[{0x21}, {}], 0x2})


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x3}, 0xc)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x34}, 0x4, 0x0, 0x0, 0x0, 0x0)


mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x205318)
ioctl$BIOCGETIF(0xffffffffffffff9c, 0x4020426b, &(0x7f0000000440))
r0 = getpgid(0xffffffffffffffff)
ktrace(&(0x7f0000000140)='./bus\x00', 0x41ecf3848c59a689, 0x4000000c, r0)
semctl$IPC_SET(0xffffffffffffffff, 0x0, 0x1, &(0x7f00000007c0)={{0x9, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff}, 0x0, 0x40, 0x7})
r1 = semget$private(0x0, 0x7, 0x3c0)
semop(r1, &(0x7f0000000100)=[{0x3, 0x2, 0x800}, {0x1, 0x2ff}, {0x0, 0x3ff}, {}, {}], 0x5)
semctl$GETPID(r1, 0x3, 0x4, &(0x7f0000000240)=""/8)
semop(r1, &(0x7f0000000280)=[{0x1, 0x1, 0x1000}], 0x1)
semop(r1, &(0x7f00000003c0)=[{0x4, 0x3, 0x1000}, {0x0, 0xfff9, 0x1000}, {0x1, 0x102, 0x1800}, {0x1, 0x3, 0x800}, {0x0, 0x200, 0x1000}, {0x0, 0x8}, {0x2, 0xfff8}, {0x2, 0x7}, {0x4, 0x1, 0x1000}, {0x3, 0x7e7, 0x800}, {0x7, 0x81, 0x1000}], 0xb)
semop(r1, &(0x7f0000000380)=[{0x2, 0x1, 0x1000}, {0x4, 0x8, 0x3000}, {0x0, 0x2, 0x1000}, {0x0, 0x8000, 0x1800}], 0x4)
semop(r1, &(0x7f0000000280)=[{0x4, 0x1}, {0x2, 0x1, 0x1000}, {0x4, 0x8}, {0x4, 0x4, 0x800}], 0x4)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000340)={<r2=>0xffffffffffffffff})
getsockopt$sock_cred(r2, 0xffff, 0x1022, 0x0, &(0x7f0000000180))
chown(0x0, 0x0, 0x0)
fchown(r2, 0x0, 0x0)
getuid()
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f00000001c0)={{0x8000, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0x0, 0x1000}, 0x6, 0xffffffffffffffff, 0x2})
semctl$SETALL(r1, 0x0, 0x9, &(0x7f0000000000)=[0x0, 0x2249, 0x6, 0x2, 0x1, 0x6, 0x6, 0x7])
sysctl$vm(&(0x7f00000001c0)={0x2, 0xa}, 0x2, 0x0, 0x0, 0x0, 0x0)
geteuid()
getgroups(0x8, &(0x7f0000000100)=[0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff, 0xffffffffffffffff])
r3 = getgid()
getpid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000200)={{0x4, 0xffffffffffffffff, 0x0, 0x0, r3, 0x100, 0x5}})
r4 = open(&(0x7f0000000100)='./bus\x00', 0x8000, 0x100)
utimensat(r4, &(0x7f0000000180)='./bus/file0\x00', &(0x7f00000001c0)={{0x4, 0x1}, {0xec, 0x3}}, 0x0)
open(&(0x7f00000000c0)='./bus\x00', 0x2, 0x0)
open(&(0x7f0000000000)='./bus\x00', 0x20, 0x60)
madvise(&(0x7f0000268000/0x4000)=nil, 0x4000, 0x7)


socket(0x0, 0x0, 0x0)
getsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
socket$inet6(0x18, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000001080)=[{0x2}, {0xc}, {0x6, 0x0, 0x0, 0xfffffff8}]})
socket$inet(0x2, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
sysctl$net_inet_gre(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
write(r0, &(0x7f0000000200)="b1c05b5fb165120a4224a763037a", 0xe)
sysctl$vm(&(0x7f0000000000)={0x2, 0x6}, 0x2, 0x0, 0x0, &(0x7f0000002280), 0x0)
syz_emit_ethernet(0x62, &(0x7f00000004c0)=ANY=[@ANYBLOB="aaaaaaaaaaaaffffffffffff86dd6008000000000000008000000000000000002300000000aaff020000000000000000000000000001"])
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000))
getsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)


r0 = socket(0x2, 0x4001, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x1004, &(0x7f00000003c0), &(0x7f00000000c0)=0x4)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
writev(r0, &(0x7f0000000100)=[{&(0x7f0000000000)="f4b533c408ae65ec81e9d08a3ea2700301aa3c44c4df00afd5175b923df6254400bc51f3624b209049130de2509cafc1dcbe6411378fdcc47f393c25447a04f4b34f227292ab1f5a79074b9a792940d1e2a5c8b368a5b1f9349cf0bb242266c43d692753401e78596f21d3305837fc72ff0c2fcec8f40c220d87484d85e65e1eff380165254de2208baae9f45fd4a49f4e787bad18f1902728146986a16900b5ca2e6355390e18412e", 0xa9}], 0x1)
execve(0x0, 0x0, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
r2 = fcntl$dupfd(r0, 0x0, r1)
ioctl$VNDIOCSET(r2, 0xc0387200, &(0x7f0000000380)={0x0, 0x0, 0x0})


sysctl$hw(&(0x7f0000000000)={0x6, 0xb}, 0x2, &(0x7f0000000140)="d5bd0d1d2d9ffee9de25ae000299278f439e7ba85cfc68", &(0x7f0000000040)=0x17, 0x0, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000000), 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x3, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
sysctl$hw(&(0x7f0000000340)={0x6, 0x5}, 0x2, &(0x7f0000000380), 0x0, &(0x7f0000000740)="d1f839ac5cf19fd04dba6c0dbf68ca1fdf288b359001bb5dbb", 0x19)
sysctl$hw(&(0x7f00000000c0)={0x6, 0x13}, 0x2, &(0x7f0000000600)="d41019f09593ab60d3e06c72b73f22f39b5ad12bd48f326b7f0e1aabfa9e3c4292bdae5e697b8fcaa4a4bbf823f7d6b604a234feada380812336b407f50a0d7a4ac2f2c2d7cb451d0ed0a6c13a9c14c53aa1a559664159cde3267cfda30825579f91ecf4a9f31c5248915759d54514b8a020b7bd372957c00803244cb3a18099a81987577b69e3cac54a76ad76b9017853d68dee8b9d2fe2bf41032b21297b0d69e220c109b799f3b2f18fb6ddfb489e3462b42d114c3a1cc6cece40390a899222dcee4e4b3b529c89e0bef4b3e8891bd9a6ed", &(0x7f0000000100)=0xd3, &(0x7f00000008c0), 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
setsockopt$inet6_MRT6_ADD_MFC(0xffffffffffffffff, 0x29, 0x68, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
shmget(0x1, 0x3000, 0x0, &(0x7f0000ffb000/0x3000)=nil)
shmat(0x0, &(0x7f0000ffb000/0x2000)=nil, 0x3000)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000780)={0x1, 0x9}, 0x2, 0x0, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
getsockopt(r0, 0x0, 0x9, 0x0, 0x0)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "0100012d29fb00"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85baa97981056ef1043f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0xd, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0x2)


msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000000)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}, 0x0, 0x0, 0xffffffffffffffff})
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
sysctl$kern(&(0x7f0000001200), 0x2, &(0x7f0000000440), 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000380)=[{0xb1}, {0x50}, {0x8006}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])


r0 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = kqueue()
kevent(r2, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x5, 0x0)
socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206919, 0x0)
ioctl$FIONREAD(r0, 0x8040691a, &(0x7f00000001c0))


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x8450c)
r0 = open(&(0x7f0000000240)='./bus\x00', 0x80, 0x104)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$WSDISPLAYIO_GBURNER(r0, 0x400c5752, &(0x7f0000000280))
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000340)=[{0x5, 0x81}, {0x35}, {0x9106, 0x0, 0x9}]})
syz_emit_ethernet(0x4e, &(0x7f0000000100)=ANY=[])


syz_open_pts()
r0 = socket(0x18, 0x0, 0x0)
syz_emit_ethernet(0x4a, &(0x7f0000000480)={@random="69e1629b6174", @remote, [], {@ipv6={0x86dd, {0x0, 0x6, "6b9efb", 0x14, 0x50, 0x0, @rand_addr="cb69bc83c1677a656ab420666c3e2c6f", @local={0xfe, 0x80, '\x00', 0x0}, {[], @tcp={{0x3, 0x2, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}}})
recvmmsg(r0, &(0x7f0000000640)={0x0}, 0x10, 0x2, 0x0)


open$dir(&(0x7f0000000000)='./file0\x00', 0x200, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
connect$unix(0xffffffffffffffff, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000040)=0x3, 0x4)
getpgrp()
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000080)=[{0x87}, {0x3c}, {0x6}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])


getsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2b, &(0x7f0000000500)={@local, @remote, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x1d, 0x0, 0x8, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @broadcast}, @udp={{0x1, 0x2, 0x8}, {"a9"}}}}}})
syz_emit_ethernet(0x5b, &(0x7f0000000480)={@random="b9053107df7d", @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x4d, 0x0, 0x1, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @broadcast}, @icmp=@echo={0x8, 0x0, 0x0, 0x0, 0x0, "96b68bf1bd837cf3a3603aaa24521b32a8c2e383cf1565a1233e4057777c54782e464ca1c16d521ee78dd0d62f00724c1d"}}}}})


open(&(0x7f0000000200)='./file0\x00', 0x80000000000206, 0x0)
socket$inet(0x2, 0x8003, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r0)
writev(0xffffffffffffffff, &(0x7f00000000c0)=[{&(0x7f0000000180)="a91d572018dfc112b211c9b7f9dbdc4e9c7752845816984bb622d74a83050000000fd383c857ce942c438f2ea02b33f59d83749b711951efa88a2a6dcd049f666033a9f518c180b3eefaedee0d0f34a08b", 0x51}], 0x1)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
mmap(&(0x7f0000ffc000/0x2000)=nil, 0x2000, 0x0, 0x10, r1, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000040)={@broadcast, @broadcast, [], {@arp={0x8035, @ether_ipv4={0x1, 0x800, 0x6, 0x4, 0x0, @empty, @empty, @broadcast, @remote={0xac, 0x14, 0x0}}}}})


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000180)={&(0x7f0000000040)=[{0x26}, {}], 0x2})


mkdir(&(0x7f0000000300)='./file1\x00', 0x0)
chroot(&(0x7f0000000240)='./file1\x00')
unveil(&(0x7f0000000040)='.\x00', &(0x7f0000000080)='c\x00')
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000040), &(0x7f0000000100)=0xc)
unveil(&(0x7f0000000280)='./file1\x00', &(0x7f00000002c0)='c\x00')
writev(0xffffffffffffffff, &(0x7f00000002c0)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe2c63a56077123a276d3ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
symlink(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000100)='.\x00')
openat$zero(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = dup(r0)
ioctl$BIOCSRTIMEOUT(r0, 0x8010426d, &(0x7f0000000000)={0x0, 0x7})
ioctl$BIOCSBLEN(r1, 0xc0044266, &(0x7f0000000100))
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
syz_extract_tcp_res(0x0, 0x0, 0x0)
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
readv(r1, &(0x7f0000000080)=[{&(0x7f0000000180)=""/15, 0xf}, {&(0x7f0000000040)=""/17, 0x11}], 0x2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f00000001c0)=[{}, {0x4}, {0x6}]})
syz_emit_ethernet(0x1046, &(0x7f0000000040)=ANY=[])


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x80206931, &(0x7f00000001c0))


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r0 = syz_open_pts()
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)


open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
r0 = open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
r1 = getpid()
ktrace(&(0x7f0000000280)='./file0\x00', 0x0, 0x928, r1)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r0, 0x0)
r2 = open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x3, 0x10, r2, 0x0)
clock_gettime(0x0, &(0x7f0000000140))


r0 = open(&(0x7f0000000000)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`\x00', 0x200, 0x44)
r1 = openat$diskmap(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$DIOCMAP(r1, 0xc0106477, &(0x7f0000000240)={&(0x7f00000001c0)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`\x00', r0, 0x3})
socket(0x11, 0x0, 0x0)
r2 = socket(0x0, 0x0, 0x0)
shutdown(r2, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x53})
r3 = syz_open_pts()
close(0xffffffffffffffff)
r4 = syz_open_pts()
ioctl$TIOCSETA(r4, 0x802c7414, &(0x7f0000000080)={0x7ffffffe, 0x0, 0xe3d458f, 0xffffffe8, "1500d67d005b860000e30000008000"})
writev(r3, &(0x7f00000008c0)=[{&(0x7f00000018c0)="bdf83afa87530f0416987cf84f8f0f1c3a4501fc5bf8641b8c10e8575f86dc68d6bea9184e5157d6bda3d51aa9931e826eb413130536533a23f3b4765422e96a36c56c0ec1b65d52c9d24059a25ebe51f722cdb0fbd89106c87c50a74caf860c5de446193f1cd65d7b2b3111158517bfb9e51203b4efce60379fc505e691a2040bef91c58ff48d376af0d488a5e0492dc33df0a6597a2dd85ca396c4cae6db9fdd12bc1428e20e8adb3b2082eea2fb37441739806ee2fde7302c5e0b64c92aca75a7186d7630040ca6ee723360f9454345eba57f581b44316916dfa6ef0fe032da52b60db523aa44ac860cc050547644ffec11291845fad457c4899f015f6b784c878908f6fca14d4a63b7b46374c988e354f69305fdc73a2ae83e221aa5fcae9ee01451e6ac3e09bf22c52d6c93f39869225f7f028b06421570763c9785a61f5e507502300c6340f5200351bdbfa63880c228d11348bb2e306a07e319ab13b8c59ab28f29548492ca3fcc76f5df95f2c8a4703098270f42d36cabc74e318f840d733816de8561548a7da588508b30d9bcf9a7a68c5819c86ff9dd1ba1cb10f641a43bb4429dd798cd1b2e41a708c7bf8a362b46d1419a064a9a2b52009466306d787864fdc8c3f49efbd24cfe2fbca1ead31b6f84e3526bc247476466a72e184c0b4e8360690c288101bab88a1a3b5211a51ee5dafe5a5a64a31837c18f278d10644f896be251cacc29aa36e0bfdea56db220dccd96491c06eb6ef74b61fd1c8b363c9479a4fc6a58af20a14f6dc885134bc005b44b94355f382f13e244d44b836dd37078193c67adc8bc364360f246f744483a8be5345853b3600cc029566331babcaf24224cd2c7ac62577328c74dfdc6970e888e7011a2b3972cfcd1486cb071bdbe82f0fdcde5a887555b6db4fd3920863e4d31bf85473ef3faab39f5679f2807695deaabe39bb053807a5f1d08180e55378cd4a49f151dc27bf12d1525a3d1506a62a79f15317cac40d717542015807c2d54cc29fa946301b8dda134c7907b99ab64111abc5b96d0ec45afd4f2563cb1a8fe8e4169cc18c5859f66ba1865ceba46c8e9883596842607d9bcc66ca54ae4be6c68c982f72b350f000a89544d8620970cd1a2f00a781ecef190a5430730b694b0bed66580375510b02fa0a3d8c95876295f9041bb6cf880685888d3389596ebb672ed932b3668bd96afd83ecd814d3e362d327fbc0b68c3818ab23ab8274dc2adec5d77ba05cf7dfc6fd6652e12177dbac6972f3368e003bff069b18e10f1c04a8832123d5be51eda018c134daf22b74ab171b4a54b90b1b951727529c7fa1ab11819db4da2946c2b8d18e2a3cb9e7f8b10666fdfe294b75a871fddca1401e99272e97282dd44fa71679c61944d965ab2b620b37839ec51440e7af0c1372125037dd98ab638b271b756a5169791f0f445d5270f84fa5a6d8d6725444f90158b8862efd3d0c1d6269b40ed34e41eaee286305c677dc977333fbcac742769f5a47a5e3c653851dd857620a8f14e56b317fdbde658673befe02beb82b248f6af337484b9f4e4d4a3ba108fe69937881e02cd073dbabcd66d487c745446f0ee5d1bd48049396b2a03b3247fa73d70f4bcc767a957b526dba61eebc5f5eab1ef18ccc84ffbf768637cc247933cec1e618169da86f0e0dbf992297fcc48835895e9ae9c7f09c568055850da0fb4a330e6771f3cfeeae088b0fa0894f3db15a83ad9260dfb210922760e9189a2f3d04f87d383d98f3fcf1b09329f672665d5821b8be48b723b68f16c33978b39761919c8a07e0fae61743b09b82cd1d45fbe25edc97dc8ea743d2d47754b9aa28cc9159ffb7833277821507c01ae3ef06102b4604b03aeaf2bf0cb7e8155d473843cefc1145ab6951b98fb083e23354b12fe2e00feb1a53f26b2702cc08f46e504e780033c771dfcba4f780adb7d77d6fb8be31c468b6a978a34e5f1e56d5306c9a2cc118669ec777054b28af9f444c9c2af6d27886c853e0fd7ec7bec564e8b68cdb40a65422b5890b66461e4e41bd0677482b54d37dcc81a1b1643b728d8570b1605a5d420dbcefec5d0d1c9d9da8d496ccb7ea9250c9a76a5e5572df7786b590a28c0b794eca52b55720279ce81f35481e140471d0c0ca27c2b00270da1f439b285a5d2d695fd27e1b3821dece8feafa0e113e352962889ae17d075e4baeab60289c36c548e2f59541fc1fed0d2ba8057de17888dea1d99fafe94777315da51f54f4bbafeb9cf62a32ab7d0c5644f63457310e617d89020d2d0ad7af579db61a9901ff44487cd4fabacca994ef66c295378968fc4da0cd08a104f3177bd640ae0a992feccbbc6ff07fd5d25242aff7af00bc2b601c829dca9", 0x698}], 0x1)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1001, 0x0, 0x0)
r5 = msgget$private(0x0, 0x0)
pipe2(&(0x7f0000000000)={<r6=>0xffffffffffffffff}, 0x0)
msgsnd(r5, &(0x7f00000000c0)=ANY=[@ANYRES32], 0x1f, 0x0)
select(0x0, 0x0, 0x0, 0x0, 0x0)
msgsnd(0x0, 0x0, 0x401, 0x0)
msgsnd(r5, &(0x7f0000000540)=ANY=[@ANYRES16], 0x401, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80606941, &(0x7f00000001c0))
openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
msgrcv(r5, &(0x7f00000002c0)={0x0, ""/206}, 0xd6, 0x3, 0x1000)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x10, 0xffffffffffffffff, 0x0)
ftruncate(0xffffffffffffffff, 0x25b3)
execve(0x0, 0x0, 0x0)
syz_emit_ethernet(0x109, &(0x7f0000000580)=ANY=[@ANYBLOB="ffffffffffff00000000000081004d0002003de54961e1326bff1435a47db71c45ceb46641be6f4f950350f890c3a26f4ba3da7a7147ada92d1155734cb9afddb81083726b1dd6394728f4956df98f88e89a013c9f3d9f01d27703788bcb61fbb830133ccca6360206ba0cb9087a4215d2f21c8ce28b456c20b7738e0de198ac5c2fe6aa3268a7d42a412a3732632df979340898c0ea5334ff6e83191e366f49f8c60980b0afed92002dae8626fa08727a661bb0f024b406f3a8356c0e880051a5095cfd77de91862c44f1ea9f6f958eb05e212279777c9603bcfe13af8c71b3967b417811f556732bb28e6e512e8a862727e69e56b9f4c2ae32580fa87361446b53325c1e47e20000"])
msgsnd(r5, &(0x7f0000000100)={0x3, "1b18f212a6f34c1c20e11229827b6640450885396ec261592b6554b6ba051ba9a5d7895c5ac9ce1cb6e84191b2726cfac510481b18d7dd4559ab66ce8b9bd317a26a842169d4586d5410da25787eceec027704581e81ae84"}, 0x60, 0x800)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
recvfrom(r6, &(0x7f00000003c0)=""/222, 0xde, 0x0, &(0x7f0000000080)=@in6={0x18, 0x0, 0x0, 0x6}, 0xc)


setrlimit(0x1, 0x0)
writev(0xffffffffffffffff, &(0x7f0000001100)=[{0x0}], 0x1)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSFILDROP(r0, 0x80044279, &(0x7f0000000000)=0x2)
sendto(0xffffffffffffffff, &(0x7f0000000180)="23698d1b6bfed491b12ecde0825273b43642cb2f3b0f99df8707b7d05050012d806ac9587201ab7717487e76b31e34d0225fea2ea6bd8692c3ba5d8570fe4c1b4fe4c4a193a7ffa6dda5ae1534", 0x4d, 0x0, 0x0, 0x0)
r1 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x80206979, &(0x7f00000001c0))
sysctl$net_inet_etherip(&(0x7f0000000000)={0x4, 0x2, 0x6c, 0x2}, 0x4, 0x0, 0x0, 0x0, 0x0)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
socket(0x11, 0x3, 0x0)
r2 = socket(0x11, 0x3, 0x0)
sendto$unix(r2, &(0x7f0000000000)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x2, &(0x7f0000000080)=[{0x16}, {0x8106}]})
syz_emit_ethernet(0x2a, &(0x7f0000000180)=ANY=[])
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
sysctl$vfs_nfs(&(0x7f0000000000)={0xa, 0xe}, 0x3, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000000)={0x0, 0x0})
syz_emit_ethernet(0x2a, 0x0)
kqueue()
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000001c0))
socket$unix(0x1, 0x1, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x10000, 0x68)
sysctl$kern(&(0x7f0000000080)={0x1, 0x37}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x10000, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x3e, 0x0)
setuid(0x0)
rmdir(&(0x7f0000000000)='./file0\x00')
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r3 = socket(0x18, 0x2, 0x0)
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f0000000200)={0x6, &(0x7f0000000100)=[{0x7ff, 0x3, 0x0, 0x7}, {0x6, 0x8, 0x5, 0x2}, {0x0, 0xea, 0x1f, 0x4bff}, {0x0, 0x2, 0x4, 0x4}, {0x3, 0x0, 0x7, 0x1b5}, {0x1, 0xb9, 0x0, 0x8}]})
ioctl$FIONREAD(r3, 0x802069a1, &(0x7f00000001c0))
r4 = socket(0x18, 0x2, 0x0)
setsockopt(r4, 0x1000000029, 0x41, &(0x7f0000000040)="71040071", 0x4)
r5 = semget$private(0x0, 0x3, 0xb7)
semctl$GETNCNT(r5, 0x3, 0x3, &(0x7f0000000240)=""/49)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
socket(0x0, 0x0, 0x0)
getsockname$inet(0xffffffffffffffff, 0x0, 0x0)
r0 = socket(0x18, 0x2, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockopt(r0, 0x29, 0x2c, 0x0, 0x0)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
socket(0x18, 0x3, 0x0)
r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000100)="b10005010000009f0500070007000000331c13fecea10500fef96ecfc72fd3357ae30200004e3039d2d236acf20bf404be01000000f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f335c22db830c032bfa896443c32118210000720fd38bfb0000fd54c125191b1257aea8c500002002fbfe0c2300008abfba0900000008e37193f8343712051eeab71dc000266c05080000fca65361ba84913f0100"/177, 0xb1, 0x0, 0x0, 0x0)
openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$PCIOCREAD(0xffffffffffffffff, 0xc0107002, 0x0)
socket(0x0, 0x0, 0x0)
syz_open_pts()
ioctl$TIOCSETAF(0xffffffffffffffff, 0x802c7416, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, "2cf748460adb56e8dd42caee5275882ceece40cf"})
syz_open_pts()
ioctl$TIOCSTART(0xffffffffffffffff, 0x2000746e)
socket$inet(0x2, 0x0, 0x0)
bind(0xffffffffffffffff, &(0x7f00000004c0)=@in={0x2, 0x2}, 0xc)
msgget$private(0x0, 0x460)
sysctl$vm(&(0x7f0000000000)={0x2, 0x8}, 0x2, &(0x7f0000000040), 0x0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCIMMEDIATE(r1, 0x80044270, &(0x7f0000000180)=0x2)
r2 = dup(r1)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
syz_emit_ethernet(0xe, &(0x7f0000000100)={@local, @remote})
r3 = socket$inet(0x2, 0x3, 0x3d)
setsockopt$inet_opts(r3, 0x0, 0x1, &(0x7f00000000c0)="89144c0129ea94f77ea66ed006e3bc58e261c99a", 0x14)
sysctl$net_inet6_ip6(&(0x7f0000000000)={0x4, 0x18, 0x29, 0x34}, 0x4, &(0x7f0000000140), 0x0, &(0x7f0000000180), 0x0)
r4 = msgget$private(0x0, 0x0)
msgrcv(r4, 0x0, 0x1008, 0x0, 0x0)
msgctl$IPC_RMID(r4, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x8, 0x40)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000700), 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r0 = syz_open_pts()
close(r0)
pipe(&(0x7f0000000300)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
write(r2, &(0x7f0000000040), 0xfeea)
readv(r1, &(0x7f0000000540)=[{&(0x7f0000000340)=""/177, 0xb1}, {&(0x7f00000001c0)=""/188, 0xbc}], 0x2)
writev(r0, &(0x7f00000002c0), 0x100000000000026c)


socketpair$unix(0x1, 0x0, 0x0, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
preadv(0xffffffffffffffff, 0x0, 0x0, 0x0)
madvise(&(0x7f00003e0000/0x3000)=nil, 0x3000, 0x0)
recvmsg(0xffffffffffffffff, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x2a, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000040), 0x3, &(0x7f0000000080)="397c9aca", &(0x7f0000000780)=0x4, 0x0, 0x0)
ioctl$VMM_IOC_RESETCPU(0xffffffffffffffff, 0x82405605, 0x0)


sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x13}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(&(0x7f00000001c0)={0x6, 0x1b, 0x2}, 0x400000000000000d, 0x0, 0x0, 0x0, 0x5a)
sysctl$kern(&(0x7f0000000040)={0x1, 0x3f}, 0x2, 0x0, 0x0, 0x0, 0x0)
socket(0x18, 0x1, 0x0)
shutdown(0xffffffffffffffff, 0x1)
shutdown(0xffffffffffffffff, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, 0x0)
socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x6c, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
mknod(0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
bind$unix(r0, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
getsockname$unix(r0, 0x0, &(0x7f00000000c0))
r1 = open(0x0, 0x81, 0x80)
mknod(0x0, 0x2000, 0x0)
ioctl$TIOCSTOP(0xffffffffffffffff, 0x2000746f)
getsockopt$SO_PEERCRED(r1, 0xffff, 0x1022, &(0x7f0000000080), 0xc)
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f00000000c0), &(0x7f0000000100)=0xc)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000300)="9b0209c3eb987ab7fe4189c99e805e6e84d356960798a692992117d6728436ba1bd87f42e3303eac3846528d050712f838130efce33f523ba44765f5f6915b0227390ed95bd9dc6d4dc7e149d4d6d06a3f23616e773302d9cae75e39a5a11e32e0e6ebd635450b2eba540af7f2aa5dbfbdd900a0dad2b74f50acd76b5c567049ef436dbea0d7562f52950fa5ef6e84c513252ddd8680a944d5c2bd02adc7f1fe850c00000000000000062ab475cca257352828a76e5334be562995e894238b96ca5d4d3e670feac9b4e8aa9bef19525cb6f7e8570b2a374f1400041ed45bb7ad3fe963cb9a8bd949ee0fc6dbceb7d956015947b3e88aa810f8ed7cca10ff010000000000001345daa49507756f49775275ca390b94e85d5a95b8bdacb9429c25483a9275d0da3b561c6adc3c141f26a88016dd6b436218bdbdc9ac0a623855e941dc1872fcb045e0d9df1ecc6357ee21e2b0802cb60eec6add5e94723235f06715e7eecc3e0760c70e1dd7873e27142bbae1a7e44de453a073fe3426f334b80f043ba9136d57c799353d46dd81439b111a511a288bee5dfb2e353e3bb073e3342273216b07e49ca4df0fd2dbe9a8eb377010ee678aad0bd8e9fb7d82693a096344671843a1f2082612b0ff237c6e505ff5f5ba932954d73c630fdb791f833a1da5af0704f687e196f4f7859e071fc98111cc9024f790ce16ceaa7d0104e39789d9100000010000000000050000000000", &(0x7f00000002c0)=0x210, 0x0, 0x0)


syz_emit_ethernet(0x3a, &(0x7f0000000440)=ANY=[@ANYBLOB, @ANYRESOCT=0x0, @ANYBLOB="5000000090780000"])
writev(0xffffffffffffffff, &(0x7f0000000080)=[{0x0}], 0x1)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
ktrace(0x0, 0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
listen(0xffffffffffffffff, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
getsockname$unix(0xffffffffffffffff, 0x0, 0x0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
close(0xffffffffffffffff)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x4}, {0x3c, 0x8, 0x1}, {0x83c6}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f00000001c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, 0x0)
sysctl$hw(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f00000002c0)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, @multicast2}, @icmp=@echo}}}})


socketpair$unix(0x1, 0x0, 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x2}, {0x5}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
sysctl$net_pipex(&(0x7f0000000000)={0x4, 0x22, 0x1}, 0x3, 0x0, 0x0, &(0x7f00000000c0), 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f00000001c0)=[{0x1}, {0x1d}, {0x8106}]})
syz_emit_ethernet(0x26, &(0x7f0000000280)=ANY=[])


syz_emit_ethernet(0x68, &(0x7f0000000280)=ANY=[@ANYBLOB="836ce898e0fcffffffffffff86dd60ab046500328900fe8000000000000000000000000000aa6ddd6d79cbe7cfff3aa873063828d9dc11000000000000004e224e2100089078c7754b603b"])
sysctl$hw(0x0, 0x0, 0x0, 0x0, &(0x7f0000000200)="1db8708db61b5d13aa269568235de39cff7594923114acaf9ed6549cbffa06e71fa3295a8e7e96fde0a5f5227d4508fbb7af5cd43e1c86cecdebbf0d4a741e115cd4087f0760741c91378a35ef10e607edf27bec182fa15f3d0707557ddbc9336ea9d017a39d3ad62af3ccb59f83717775b06778a6effa172530362347336a8f34577be260f6a3023e0143659de755c3d10f2931c65d5cc39bee155e7fcc83147aea32ba00554ac21bc9b502", 0xac)
ioctl$VMM_IOC_WRITEREGS(0xffffffffffffff9c, 0x82485608, &(0x7f0000000440)={0x0, 0x0, 0x0, {[], [], [], [], [], {0x0, 0x0, 0x0, 0x3}}})
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETD(r1, 0x8004741b, &(0x7f0000000080)=0x8)
writev(r0, &(0x7f00000001c0)=[{&(0x7f0000000100)="791c965780508f54dbcb129a9b6934991cba070d2e0c2f19ce57fdf185dff047b76f5bce561cfa080860c2905c9d57ef9df88eecb44cc27bf73a964b794a1daba7ac8742bea32f4d23e71ae0658372c558d41ee20902ae", 0xff81}], 0x1)


mknodat(0xffffffffffffff9c, &(0x7f00000000c0)='./file0\x00', 0x2000, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000000040)=[{}, {}, {0x2}]})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000007, 0x0, 0x0, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
kqueue()
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
close(r0)
fchownat(r0, &(0x7f0000000040)='./file0\x00', 0x0, 0x0, 0x0)
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r1, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
mprotect(&(0x7f00003e0000/0x2000)=nil, 0x2000, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0xffffffffffffffff}, 0x0, 0x0, 0x0, 0x0, 0xfffffffffffffffe})
clock_getres(0xbe44501372635004, 0x0)
sysctl$net_inet_ip(&(0x7f00000003c0)={0x4, 0x2, 0x0, 0x19}, 0x4, &(0x7f0000000400)="1fec388eb9049602b151b0060854aa4dafba21a23fe09f97a3e8add277517eea8539bf8660ba93eeacf61217429bc2454995412a2b1dd9c408b98aa28b5885f9dc195209615a4b6d11c912043a5ea598fa66c44cb59602b042155fecccfbf4c8592b51a962834aeb33a53b9e04bcec01ff3b803391921741aa732179d01dead22c38751d6ad5bac18905d9194bfa48f1670dfe4fafbe583d15b671ed1c50da4d3d9f", &(0x7f00000004c0)=0xa2, &(0x7f0000000500)="7c2d52a29b65be8c5f5e9c487ed76e13462e106861ca2fa573ae63fc120677831efbb23cfde0da97e50ece267417570ccd4d375156f9d6e4c75be4125a5c5a6b9901e63c0930364f3abaf41f0dd59ceff3e3eb7d163db7b342cba7c485fb5bb8efa5e99633ad37f852de83d5", 0x6c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000140)=[{0xc}, {0x25}, {0x6}]})
syz_emit_ethernet(0x7e, &(0x7f0000000400)=ANY=[])


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x20, 0x0)
flock(r0, 0x15)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000c40)={0x3, &(0x7f00000001c0)=[{0x7c}, {0x24}, {0x6, 0x0, 0x0, 0xfffffffd}]})
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000080)="35b5c242413c1026089a59583cc3", 0xe}], 0x1)


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000000)=' :', 0x2}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x881)
r0 = open$dir(&(0x7f0000000240)='./bus\x00', 0x0, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x801)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r1 = syz_open_pts()
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
dup2(r1, r0)


sysctl$kern(0x0, 0x0, &(0x7f0000002380)="d7", 0x0, 0x0, 0x0)
sendsyslog(0x0, 0x0, 0x0)
r0 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f00000007c0)={0x0, 0x3, 0xffffbff6, 0x0, "6106a6bc44862c5008c8b503005a000400008fa8"})
writev(r0, &(0x7f00000001c0)=[{&(0x7f00000003c0)="7659aeb94832406f050635f0b67c483a24febaee4d9c497b7e5f0bf12b7225efb6f6c869e646ecfa588c53283c4dd3ed77706f3868cacea799a3bdfb42db706563dca286f58274eac945d5ffe9054ffd5b7724b408516b9ed309d4751896dd052cc4977fb319", 0x66}], 0x1)
syz_open_pts()
ioctl$TIOCFLUSH(r0, 0x80047410, &(0x7f0000000380))


open(&(0x7f0000000100)='./file0\x00', 0x80, 0x185)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x0, &(0x7f0000000080)})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000300)={0x3, &(0x7f0000000380)=[{0x34, 0x0, 0x0, 0x3b}, {0x7c}, {0x6, 0x0, 0x0, 0xffffffff}]})
ioctl$BIOCGHDRCMPLT(0xffffffffffffffff, 0x40044274, 0x0)
syz_emit_ethernet(0xe, &(0x7f0000000100)=ANY=[])
r1 = getuid()
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000000)={<r2=>0x0, <r3=>0x0, <r4=>0x0}, 0xc)
setreuid(r1, r3)
r5 = semget$private(0x0, 0x4, 0x42)
chown(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
semget$private(0x0, 0x3, 0x1c6)
semget(0x3, 0x4, 0x3bd)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000140), &(0x7f0000000180)=0xc)
r6 = semget(0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000540)={0x0, <r7=>0x0}, &(0x7f0000000040)=0xc)
msgsnd(0x0, &(0x7f0000000580)=ANY=[], 0x401, 0x0)
setreuid(0x0, 0x0)
r8 = fcntl$getown(0xffffffffffffff9c, 0x5)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000480)={{0x7ff, 0x0, r4, r7, r4, 0x5, 0xab8a}, 0x5e6, 0x4, r2, r8, 0x0, 0x200, 0x3, 0x9})
semctl$SETALL(r6, 0x0, 0x9, &(0x7f0000000200)=[0x4009])
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x584a)
open(&(0x7f0000000500)='./file0\x00', 0x0, 0x0)
semop(0x0, &(0x7f00000002c0)=[{0x2, 0x9ddb}, {0x1, 0x3, 0x1000}], 0x2)
semctl$IPC_RMID(0x0, 0x0, 0x0)
semop(r6, 0x0, 0x0)
semop(0x0, &(0x7f0000000340)=[{0x3, 0x100, 0x1800}, {0x0, 0x8}, {0x0, 0x87, 0x1800}, {0x2, 0x0, 0x800}, {0x0, 0x3, 0x1000}, {0x0, 0x3f, 0x1800}, {0x1, 0x0, 0x400}, {0x2, 0x2a}], 0x8)
semop(0x0, &(0x7f00000001c0)=[{0x2, 0x8, 0x1800}, {0x4, 0x3, 0x1000}], 0x2)
semctl$GETPID(r5, 0x1, 0x4, &(0x7f0000000240)=""/84)


nanosleep(&(0x7f0000000080)={0x0, 0x40000000000000}, 0xfffffffffffffffe)
r0 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1000, 0x0, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000540)={<r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, 0x0, &(0x7f0000000180))
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
clock_gettime(0x4, &(0x7f00000001c0))
r2 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r2, 0x9, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000001})
flock(r2, 0x1)
r3 = open(&(0x7f0000000400)='./file0\x00', 0x0, 0x0)
fcntl$lock(r3, 0x9, &(0x7f0000000140)={0x1, 0x0, 0x0, 0x269000000, 0xffffffffffffffff})
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
mknod(&(0x7f00000000c0)='./file0\x00', 0x6000, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$PCIOCGETROM(0xffffffffffffffff, 0xc0107005, &(0x7f0000000080)={{}, 0x0, &(0x7f0000000040)})
r4 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r4, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000040)=[{0x7}, {0x3d}, {0x16}]})
write(r0, &(0x7f0000000540)="76e5dead6f01f8607d2100000063", 0xe)


syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
socket(0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000), 0x10)
r1 = dup(r0)
listen(r1, 0x0)
r2 = socket(0x2, 0x4001, 0x0)
connect$unix(r2, &(0x7f0000000000), 0x10)
write(r2, &(0x7f0000000080)="04bdfa5d1d2873c63e3534825ba166e2fea9aec43050006123339a346f731573d8d508753f95b7688ad48b8cf6bbca325cebc37fc4e1dd543dbe2da6dd", 0xffea)


r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r3 = socket(0x2, 0x2, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
connect$unix(r3, &(0x7f0000000000), 0x10)
r4 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x1023, &(0x7f0000000040), 0xe0)
setsockopt$sock_int(r4, 0xffff, 0x1023, &(0x7f0000000040), 0x4)


r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
syz_open_pts()
syz_open_pts()
r2 = kqueue()
kevent(r2, &(0x7f0000000180)=[{{r0}, 0xfffffffffffffffe, 0x1}], 0x8, 0x0, 0x0, 0x0)
dup2(r2, r1)


mknod(&(0x7f0000000300)='./file0\x00', 0x2000, 0x6da)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
poll(&(0x7f0000000080)=[{r0}], 0x1, 0x0)
fcntl$setown(r0, 0x6, 0x0)


ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, 0x0)
syz_extract_tcp_res(&(0x7f0000000140), 0x63, 0x5)
socket$inet6(0x1e, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x46, 0x56})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047460, &(0x7f00000000c0)=0x9)
ioctl$TIOCSTOP(r1, 0x2000746f)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000180)={0x0, 0x0, 0x8001f7e, 0x808, "e7303483ef00000000000000000000000000ff00"})
writev(r0, &(0x7f0000000080)=[{&(0x7f0000000100)='>', 0x1}], 0x1)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])
syz_emit_ethernet(0x36, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x3, 0x0, 0x28, 0x0, 0x1}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x6381)
r0 = openat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
poll(&(0x7f00000000c0)=[{r0, 0x45}], 0x1, 0x0)
poll(&(0x7f0000000040)=[{r1}], 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000280)=[{0x87}, {0x20}, {0x96}]})
syz_emit_ethernet(0x3e, &(0x7f0000000000)=ANY=[])


sysctl$vm(&(0x7f0000000000)={0x2, 0xc}, 0x2, 0x0, 0x0, 0x0, 0x0)


r0 = socket$inet(0x2, 0x3, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x1024, &(0x7f0000000080), &(0x7f00000000c0)=0xfffffff5)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206982, &(0x7f00000001c0))
socket(0x2, 0x2, 0x0)
socket(0x2, 0x0, 0x0)
socketpair(0x18, 0x3, 0xfa, &(0x7f00000004c0))
open(0x0, 0x0, 0x0)
getpid()
socket(0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
syz_open_pts()
r1 = socket(0x18, 0x3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r2 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0106924, &(0x7f00000001c0))
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000140)="67b5b992045c1a7733de71184dc12714990881d0d282bbbb82f88aee3375246d60d056448a", 0x25}], 0x1)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, 0x0)
socket$inet(0x2, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
openat$null(0xffffffffffffff9c, &(0x7f0000000480), 0x200, 0x0)
r3 = fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
syz_open_pts()
syz_open_pts()
fcntl$lock(0xffffffffffffffff, 0x9, &(0x7f0000000080))
close(r3)
openat$vnd(0xffffffffffffff9c, 0x0, 0x0, 0x0)


r0 = socket(0x18, 0x3, 0x0)
close(r0)
r1 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
setsockopt$sock_int(r1, 0xffff, 0x1, &(0x7f0000000040)=0x8, 0x4)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0xfffffffffffffffe}], 0x0, 0x0, 0x0, 0x0)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
getsockname$unix(r0, 0x0, &(0x7f0000000200))


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x80206919, &(0x7f00000001c0))


pipe(&(0x7f00000004c0)={<r0=>0xffffffffffffffff})
ioctl$TIOCSPGRP(r0, 0x40047477, &(0x7f0000000680))


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000200)={<r0=>0xffffffffffffffff})
write(r0, &(0x7f0000000040)="ed", 0x1)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
chdir(&(0x7f0000000240)='./file0\x00')
mkdir(&(0x7f00000001c0)='./file1\x00', 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000540)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000140)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000080)=0xc)
chown(&(0x7f0000000040)='./file1\x00', 0x0, r1)
chmod(&(0x7f00000018c0)='./file1\x00', 0xb7)
setreuid(0x0, 0xee01)
mkdir(&(0x7f0000000100)='./file0\x00', 0x184)
rename(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000400)='./file1\x00')


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000040)=[{0x1c}, {0x1c}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000934, 0x0)
open(0x0, 0x0, 0x0)
r0 = socket(0x18, 0x3, 0x0)
r1 = socket(0x18, 0x2, 0x0)
r2 = dup2(r0, r1)
getsockopt(r2, 0x29, 0x66, 0x0, 0x0)
r3 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, r3, 0x0)
select(0x0, 0x0, 0x0, 0x0, &(0x7f00000000c0))
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000740)={<r4=>0xffffffffffffffff, <r5=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000380)=""/93, 0x5d}, 0x3f8d}, 0x10, 0x0, 0x0)
sendmmsg(r5, &(0x7f0000000080)={0x0}, 0x10, 0x0)
close(r5)
socket$inet6(0x1e, 0x3, 0x0)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
pwritev(0xffffffffffffffff, &(0x7f0000000540)=[{&(0x7f0000000580)='F', 0x1}, {&(0x7f0000000180)='O3', 0x2}], 0x2, 0x0)
recvfrom$unix(r4, 0x0, 0xfcff, 0x0, 0x0, 0x0)
r6 = semget(0x2, 0x4, 0x300)
semop(r6, &(0x7f0000000140)=[{0x3, 0x0, 0x1000}, {0x3, 0x0, 0x1000}, {0x2, 0x81, 0x1000}, {0x0, 0x5, 0x1000}], 0x4)


writev(0xffffffffffffffff, &(0x7f0000000180)=[{&(0x7f0000000000)="9da8e3e9ed", 0x5}], 0x1)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000000), 0x4)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x2, 0x0)
bind(r0, &(0x7f0000000000), 0x10)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{0x15}, {0x3d}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000200)=ANY=[])


r0 = syz_open_pts()
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f00000006c0)=0x9)
r1 = syz_open_pts()
ioctl$TIOCSETD(r1, 0x8004741b, &(0x7f0000000100)=0x9)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000440)=0x8)


writev(0xffffffffffffffff, &(0x7f00000000c0)=[{&(0x7f0000000180)="a91d572018dfc112b211c9b7f9dbdc4e9c7752845816984bb622d74a83050000000fd383c857ce942c438f2ea02b33f59d83749b711951efa88a2a6dcd049f666033a9f518c180b3eefaedee0d0f34a08b", 0x51}], 0x1)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
mmap(&(0x7f0000ffc000/0x2000)=nil, 0x2000, 0x0, 0x10, r0, 0x0)
ioctl$FIONREAD(r0, 0x80206910, &(0x7f00000001c0))


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000080)="eaef125c00000000", 0x8)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100070000", 0x8)


pipe(&(0x7f0000000280)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
r2 = open(&(0x7f0000000200)='./file1\x00', 0x8000, 0x0)
setuid(0xee01)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x8020699b, &(0x7f00000001c0))
r4 = getpid()
recvmmsg(0xffffffffffffffff, &(0x7f0000000080)={&(0x7f0000000240)={&(0x7f0000000780)=@un=@file={0x0, ""/525}, 0x21b, 0x0, 0x0, 0x0, 0xbb9c2d4915ca7f35}, 0x10001}, 0x10, 0x807, 0x0)
socketpair$unix(0x1, 0x5, 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
fcntl$setstatus(r0, 0x4, 0xc0)
socket(0x11, 0x3, 0x0)
r5 = getppid()
fcntl$setown(r1, 0x6, r5)
write(r1, 0x0, 0x0)
syz_emit_ethernet(0xff, 0x0)
fcntl$setown(r1, 0x6, r5)
r6 = semget$private(0x0, 0x2, 0x68)
semctl$SETALL(r6, 0x0, 0x9, &(0x7f00000000c0)=[0x100, 0x8, 0x57])
r7 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r7, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000140)=[{0x5c}, {0x28}, {0xc3e}]})
r8 = syz_open_pts()
close(r8)
sysctl$vfs_ffs(0x0, 0x0, &(0x7f00000009c0)="78a99892df2111d2ef2765cf3d1bd7acdcfe05638871a2a31b73c01b1435739dc76afde9dd4d2b3dbfbbcfa9bf286a44e4ce631e84d9e7d212affcd5a655aabcc5785b2e14607b542f8f05b6962b1de96264f78af2c4097640e23da075bd3703e8ebbb2cddd02e2dc401c8c1521d78601a1f3411becfd486629bd499ddddfe757db4b6168180543618b9117b2c43e9121073aa0dc4c3311213ba39bd7497e3d2f10ca2e4e3b45188955de15ab1711a62da48f8380ab14603715fd4759272a0d4c8408cca1af031bfe4c55e803460de75c9aab350b45646f2dbdd4b8e262cfaf1ec7c3d1a898863d6fed5335b2a9c952bc9fc25e8c64ebc099bcb04307fdd60c6fae715569956d12548dea55521092a8a944cfe458156e6b493011b2da28f9df8aa9a138d7bfda65a988e950ec9840ae6603430afa2ea624f2b83916734c5682a809c2c06e0379acc1c050516411533eb059248cf3109332b1b3c1fe0f7e35b08c1bae10e2dc9870749c4f2f08ad3e7074813e96c2951843e2ae5d91e7d2187015cb0c7d35c5da1f5c36ba105574b6203a321c2fdce5a51e8ed2ffec8130eb83a28e3628ae6c29369dee50189d9375c9fe8a4f2afa802023a7d51a22691d7739b2078a6fc7244dac2c6b73919fe5753b8a60a32fde94d19b5f404764e822e4ebcc9d77df5d5081a0fc5f9a2c584a231d57ac0e618c029e535931504f176a4e9c48489cc265953eae670f52f5724e173cc4a41ea3d9158442fdfe4a949bdee8ea2ae76276217b83daff1d1d0343631265675727620892c341233602e739ef109b2f7d73052bee31a8e9ba44ff9789adfb53c2e789bc5ece3020e1a516eacf19dab959e2428f043db2352800c5dfcce8f3807c71e6a7fcf6ca27b09df0626fd70af7245fcc7b9548e43faf98f9846e8666bcfc0ce4cad4430b3a4bf40475b0108287cff50d75e4aae8078f2e695f331f71b9e206e554ef038d44b1b857647103a458ba4d1d07fd72fc73b4512f4440a378dba558a65cc46cb3d5e9b5017f7fccdd06c5d20b47d3e84316e0580a2916b415f3073e541b9061b2dc9feb7165d677523e21ca4cacd11b17b93746fb5629007c30c7cc2d7d7a0575c46446bc2c9c5b63b0cd60c052ec21729f53e64dda99c64584c62c6dcb95eab188d3c5ff761302213d2b28dffa8ed0333e866bb580f341cd3ae1cbff7a17aedb6599fd4ced6d960d99c528412f297122be1b36f7277d67b32f793e4a67ed7f86e256eaeafec99c73ad21a559967262a05311118a98b30e4d1e3a2f59eb21ca4b9c68b60c45eaf12e607fcc6af8347104db9aad6825c8eed0ebac5cf81e09175c9bd98d3dd784f39b9d5802e9b1ed5f882983d0c10492e1883587510fb2103165aad14649016cc0b943e8228e6c36d3b8ea800a0a762590071f22e5aef0ece2771616dcd93b14aa6694392fdcc044c70f912ca88904eb9075ec7d5cc4dcdd04c2ecd359b018dd62c273cb379351bb2621d13805e691a1c7d5d453fd3f55248780b2d6b8ce60cf8592d2fca579be5d36d70122f02e39a92069cd3b9cb4e288e239648ec5731fdf9f8a15c7b43194a8c615dac88f6f9b049a5aa1b8790166b37c6f1108afc2d6106792aa81ff6fc5fbc87e93ff5a3e4e013f03cad483bdec69c385d655f84b69a95e3dba814f5b382ccaa3f5e1685d95e3d644f1580988c9c674a1e670a198373f93a82acdfeec0c5bbb5c84ac9f5cfac08874180f4eaad6a8b78738c7844330ebadd8ac9543dc950af4710533dadab787c37db540ccfd62af420e04ee947fba96a827d714206b839bd4fa0644702c1c5a9654589b1e84cbc3c21bb159841cfa089fe920299a54b24fd978774e029df0bc564e77dc619457be7f0c1b864975566e7edeaba66f35134d779e611ae0e1e524d5789a1150b10a20000376fc9465f4b0fb5e8b977839960da0ab60ab7a2bac205bd051e1f521bb9a1e8a8a2174ac0be6785b281278cbed98360bc2f7468a6c9c55ec58c6ffcb05a0ad414269fed04150226c3ef3b48e3ccc9cf20c320b894ebb76992f8680b962e6f8303de33e45cb2bf1700a199938a23ae932bd2d67c9159ee2b321691866d97be2ada37f879e26974435a5bd58d51d49491a985a421d064f28bc12dbef3efe6f4690e9cb4010c5a8a633fd81bbc531d3a41da8b246ba48a96783c4240c4e64aaf870c3837257a11fe633ac5b74c0622b4bfbaf921a88afeb90c56071294c74e3a57449cd9703fab1759a26aa5acddb3b77599c1590cf9af6659df19155502205b48db53df42c068f8b69a1c9fe10f5d12fa1301f8599419526e7dbd85c55069ac09d7eca5b82f91ef2df9b898546ece1cbffc28018165dd3cc5caf1551ddf06518f8e27bc5b749e23f38e90e40be183c77be743288387961b9ff97dbb897172ef5f180d1b52b68de358c50d3b82562390cc2f8cd52d95a6586a328731b0fec2ea9fa3b6cf03de97d318d4520d8de6291ea769d0dadc59f559b0f0a296b454ee0cf2f7090a5bbc6647ce34d5227275bb9033c824218e604abed978c070a758ba6759a8e4a4a7df9ec419251b300089a2ff77d1d62e07d1839840e32faf65b7929a284b323e55b645db43d5ab44dce477964aab824984e8bce3f3aeaf397bd7d2d498c3820954b56431e4ca211fcd8ec06ffbad2256a0076acd3d404b04eb9d4c7fce0fab43c7fa1d18e5701663d1e94d00337db71585c3f5f5d6aabfd2ddd056bede7860bf57e74ccb267f31e5a651b68037a03c36daaec1f6ac94a39bf5ade284feebb08a88ce974c0459710054e94b7ca669d0b0d615bb4ae877e560573bf70b386f47d796ebfd2b0aec5913ef898123a6cf181e75cda3f699a5434fbde7f1fe33cd09bddef15c1c1ca02ceb7a801dbe2db518c29f4673cfd9c69ce1b9a0e43f9412fc097d402061be7b1254fbca064e932b7f613601cdcaf72fb6a29d9847ccd9afca4f117046c6f39bb9bd01394c2444aef0540fb9a8d09d70949e33c3d8e1a4e7608356de731f23cbc96b8d991213ae24e8eeaddf4cdd6e260be505173d477c34e547d1b106cd0802f7980b0d520c39c83153cec5b42a6eed83ab2b2023a545d056275530db4e98404f6cb09088cb57a0d16db9064ea6aa3f9586e7c7adff5b8b7f7ff742a67890c83385ab53c0dc9700e30a1fa22105c9c2de3651bd965453920f88e06704e844a10f39cf2558b7086071c93c7327c2f6fb4177f3f6da10b2ce8c749314f0968529894e3041af6ce577f68c44750dfb16995bb65cec707cd63ad16b782d2acc95e7021f37dd31b16f20e7299e23998a9346acc253bdb4a6f149fa823fcdd4e69e493d4388c6b7ef36a989a6a907c9f6b796326d11ef463e1b4eb84b107600760573930613ef530caac808eee3a09c4d97e43b70c448016bbc92c98fcd4ba3650389570b6fa717b5195363ec19544a46b037b25d4f9ea87a576c07860a13a1f7001932608fa2b66e50c71adb101214cefc477acb438265208fdaa926221d383371cc5e6215a736a9ad7de22086610fe4b8dccc1e22f7d28eec4344ab053cba0776e026af209fbecad20ba8944cd55cdb920374ed0925e4362f691fc8b1893e4e4227e1e8c8a97612b1ee046622550a9c2b29c47efc13c6ae5895017f5bdcc11254889aafa0a76917e5a6eba780337713437a48595a2ee96920b6f87d159c4ea377ed5a9c4cd5e15a760a686f4fe3c46e8be298fa2b79c4eabd3f6668980523e696e481acee2ead73f4341057928445da3da1544da7f72fe71ea6d1862f03015bc9aa38363bca9694963cf3ff919b159b95b92cf4a4b774f064e3a3745d5f1a3de16af4b3969bc2ec2848c1163fb2e43f6894b8662368845a55b04b70b984313899c6b307655596134577c956056efba6597cb2647a53efb3dd92c5b3d28c2e18e7b074d82c75030c571d961271b96729f4f98b51d04444039a2932fec52723f41be26f247e91f13cd601d6d9cf002fe98dd7aec8af76a9d29e316dfca9c9cd9b655eae70d1bcef5daf3ba020227de18bd533bfec6d36fcbca9f42fcb0e841cbcb453b3187fb3e6f1c9917f34f13d5f449fb9644d9227e69329027efc84407a4a971430c93cdae6aa61b4ccabdda6013a80f29add995faa84aec59f8984bc50dac23fc18b2ad8a89e0805cf70a9c88e95a1766c8cf4f07187de91be32cc6681b4e4d2fdb4bb5ba6aa9aee8a4c7b2756d2d313d705a3dcdade3be193d18c4029e9b2fc9bcb5577752e235e9e2e1056d2c91dd437774f66c052a50e0797a2a9d4fe30b088210c91090906417fdf081cd2df4f990dc476d4ef5b785ea3a12513b16743265a1bf486b395cbb4044310d9f5203c96aeb3a6e3b280177f27f8f60733a1b5ec3ac46fe61f564f8151f45db8ae8677327dd168a44adba1f3e7a55ddc84576bfbe3df8c2b00cfc851897ca06b5faebf2840bd3d64e9155ae95a31be2f8ba16c80a12df6093a97812d68a1518edca5735c932cdd02883e3f623427879fb856c21ba13b850276902b996c1fbdfccf94550b991cba1341c9550183e50cf86b0582fc12b961d54be79247010e1591d40c967dcd292d804563e9015623529f0eedb655c0c6335050ce124b392656d21b668b074a42c2855f93d5f4e4ce3211b29b73560b7242e5fb578e990d9832b84469b85ca52cd880826eeda9b5dd3f235ab449434da45f38c118a33974e353095219fcfb8c7d8379e109451625bec841128fe7f09d13083cf6f7f8e0d62d67f2ae8c1d6750b5175f99fde8153523808cd19537ec0aa9466cb0a1f93805585fc4057951f64db323d02e9bf8fa504ea4c4607b912f4dbe4e2fa0c01631c22931ee1919781a4851a39fdbd9c8ef29126b1f29420322cc65e9cc60377ae08356a4692a8e8a81070e7182bf1f855a647ba4d9b884e8092319cfa0050b5bd53675226c3d0bbee749a5e0476874e91043854e8fdb6b21c7470903132aa617b5ac33c954d98fdf50335925ded5fe93b1d4bee3a7addea54c92741b6b236799a5658e96c1a65411e0e20063b36ddae84dcbdafeb36c293bb51161887f2a1c5c77f6300495f52ec72149f0813916fdfa370b01247cf2051697c6e2f4f8a80467e44535149a0b2f641e68ed7ac88f9c05ff7779d63bf0de3da6895d472168a03e68f43d40526c202f45b0807e36c729009dd92a6b102c48a0ab11423ad666f950fc3e60289ae59d113fe2f3a101afb7403e2ab931648fce05b3deb838c2f62b5a1ae387cb19a5a17581f3340934a8012a6186e03229c095896e60943a725187710ed704e7048878ad28c6617db9b660f5b506f4a4ad0daa8b601440ae1adeeaa252b194142b354fc7b4f4240b8c526a094bdd34d282ab9baa818cb85b9b6e009700d192bab23c02e93f684d885d3479681d8a718702c72950249943d5ae9aff21ea5ce16bd2c003a708de3ee2cde2141eb29a48cf1283ac8387e77d40d1082948335e62d340e37d0c60d98968548c7df84cb27847c6367f856f91aad376201e351297a9321ba4a83be3d362ddc98f5549f34533609b06b6647ce910b9404e6b6375802c34be2a28432d2995bb1bdfac1075ba06a23a29cc8daf53ea3098f8a797176b91abdff1ad365668f618d1c0de408f3d64139cafdd8d7f2a3aa0bad6a13930bae5a538a2128bd6218465680e4982c15c7bc9477f19a7fae714901d79cc91b8de37e2bdc686c4d4b2b7e08af3a7dacb641cb33e6e39719319ddf16cc4cc4a8ca2819dfc10351cb290fd3b1abbf35bfb7c756b7336240b0d", &(0x7f0000000440)=0x1000, &(0x7f00000005c0)="688f4e9e92acdec50d861099ca7a8a3d228410656fab71473de1caef11e2520d74fac9cae6649da8a162fdb7e10d5b16cf9bda1df14109811e89c99fd5f5f48cbb25225dda4939ee1b485f6770f45d4150096c00ed955d9f45e05e4c455be108e6eccd3f2449c956c9ced7", 0x6b)
lseek(r8, 0x0, 0x0)
syz_emit_ethernet(0x4e, &(0x7f0000000500)=ANY=[@ANYRES8=r0, @ANYRES16=r5, @ANYRES16=r2, @ANYRES16=r1, @ANYRES8=r4, @ANYRES16=r6])
getppid()


mknodat(0xffffffffffffff9c, &(0x7f0000000280)='./file0\x00', 0x1000, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r1 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
pwritev(0xffffffffffffffff, &(0x7f0000000200), 0x0, 0x0)
sysctl$hw(&(0x7f0000000000)={0x9, 0x6}, 0x2, 0x0, 0x0, &(0x7f00000010c0), 0x4)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000000c0)={<r2=>0x0, <r3=>0x0}, &(0x7f0000000040)=0xc)
r4 = msgget$private(0x0, 0x397)
msgrcv(r4, &(0x7f00000007c0), 0x8, 0x1, 0x1800)
msgrcv(r4, 0x0, 0x0, 0x3, 0x0)
msgsnd(r4, &(0x7f0000000d00)=ANY=[@ANYRESHEX], 0x401, 0x0)
msgctl$IPC_SET(r4, 0x1, &(0x7f0000000340)={{0x80000001, r3, 0x0, r3, 0x0, 0x2, 0x9}, 0x7ff, 0xffffffff00000000, r2, r2, 0xffffffffffffffff, 0x7, 0x12c, 0x3})
syz_emit_ethernet(0x4e, &(0x7f0000000100)=ANY=[])
ioctl$DIOCMAP(r1, 0xc0106477, &(0x7f0000000080)={&(0x7f00000002c0)='./file0\x00', r0})
close(r1)


setitimer(0x0, &(0x7f0000001600)={{}, {0x1}}, 0x0)
getitimer(0x0, &(0x7f0000000000))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setitimer(0x0, &(0x7f0000000000), 0x0)


r0 = socket$inet(0x2, 0x8003, 0x0)
setsockopt(r0, 0x0, 0x7, &(0x7f0000000340)="15337ac0", 0x4)
syz_emit_ethernet(0x2a, &(0x7f00000002c0)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, @multicast2}, @icmp=@echo}}}})
syz_emit_ethernet(0x7e, &(0x7f00000002c0)=ANY=[])
recvmmsg(r0, &(0x7f0000000040)={0x0}, 0x10, 0x0, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x1, 0x1, 0x0, 0x100000000000000, 0xffffffffffffffff})
r0 = socket(0x18, 0x2, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
close(r0)
r1 = socket(0x18, 0x1, 0x0)
openat$klog(0xffffffffffffff9c, &(0x7f0000001400), 0x0, 0x0)
shutdown(r1, 0x0)
recvmmsg(r1, &(0x7f0000001380)={0x0}, 0x10, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x1}, 0x2, &(0x7f0000000040)="1b7f", 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
socket$inet(0x2, 0x2, 0x0)
close(0xffffffffffffffff)
r2 = socket(0x18, 0x2, 0x0)
setsockopt(r2, 0x1000000029, 0x4, &(0x7f0000000000)="5ab777a5", 0x4)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
r3 = syz_open_pts()
ioctl$FIOSETOWN(r3, 0x80047476, &(0x7f0000000500)=0xffffe001)
recvmmsg(r1, &(0x7f0000000700)={0x0}, 0x10, 0x841, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
r4 = socket(0x18, 0x1, 0x0)
setsockopt$sock_timeval(r4, 0xffff, 0x1006, &(0x7f0000000100)={0x0, 0xffffffffffffffff}, 0x10)
sysctl$net_inet_divert(&(0x7f0000000040)={0x4, 0x2, 0x102, 0x3}, 0x4, 0x0, 0x0, 0x0, 0x0)
setitimer(0x0, &(0x7f0000000140)={{0x0, 0xffffffffffffff7f}, {0x0, 0x5}}, 0x0)
socket(0x18, 0x1, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000440)={0x4, 0x18, 0x6, 0x9}, 0x4, &(0x7f0000000480)="9b1809c3218b07fcfe4189c99e805e6e84d356960798a692992117d6728436ba1bd87f42e3303eac3846528d050712f838130efce33f523ba44765f5f6915b2227390ed95bd9dc6d4dc7f149d4d6d06a3f23616e773302d9cae75e39a5a11e32e0e6ebd635450b2eba540af7f2aa5dbfbdd900a0dad2b74f50acd76b5c567049ef436dbea0d7562f52955af8d4ab84c513252ddd139b5f5cd5c2bd02adc7f1fe850c00000000000000062abb9fa45ac78568e1cb54238fbab475cca257352828a76e5334be562995e894238b96ca5d4d3e670fa0cc791dfc4415030910fa64eac9b4e8aa9bef19525cb6f7e8570be65bb7ad3fe963cb9a8bd949ee334db1ccf73db06b5947b3e88aa810f8ed7cca10ff0d0000000000001345daa49507756f49775275ca390b94e85d5a952000b9429c75d0da3b561c6adc3c141f26040000006b436218bdbdc9ac0a623855e941dc1872fcb045e0d9df1ecc6357ee21e2b0802cb60edd0300723221f06715e7eecc3e0760c70e1dd7873e27142bbae1a7e44de453a073fe3426f334b80f043ba9136d57c799353d46dd81439b111a511a288bee5dfb2e353e3bb073e3342273216b07e49ca4df0fd2dbe9a8eb377010ee678aad0bd8c7fb7d82693a096344671843a1f2082612b2ff237c6e505ff5f5ba932954d73c630fd2791f833a1da5af0704f687e196f4f7859e071fc98111cc9024f790ce16ceaa427d0104e39789d9100000", &(0x7f0000000a40)=0x210, 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x3}]})
sysctl$kern(&(0x7f00000000c0), 0x2, &(0x7f0000000100), &(0x7f0000000080), 0x0, 0x0)
openat$pci(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$PCIOCREAD(0xffffffffffffffff, 0xc0187009, 0x0)
ioctl$PCIOCREAD(0xffffffffffffffff, 0xc0187009, &(0x7f00000000c0))
write(0xffffffffffffffff, &(0x7f00000005c0)="89", 0x1)
socket(0x2, 0x2, 0x0)
dup(0xffffffffffffffff)
ioctl$PCIOCREAD(0xffffffffffffffff, 0xc0107002, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000400), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
madvise(&(0x7f00000ab000/0x800000)=nil, 0x800000, 0x6)
getuid()
sysctl$kern(0x0, 0x0, &(0x7f0000001900), &(0x7f0000001840), 0x0, 0x0)
semctl$SETALL(0x0, 0x0, 0x9, 0x0)


mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x33b9)
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
sysctl$net_inet_divert(0x0, 0x13, 0x0, 0x0, 0x0, 0xfffffffffffffcd1)
sysctl$net_inet_tcp(0x0, 0x0, &(0x7f00000001c0)="19a28b60fdd1084c94bcde6c14c97c9e3de38a95dd", 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001280)={0x0, 0x0, &(0x7f0000001200)=[{&(0x7f0000000180)="bf3b684c5ae963b4567084e096cf973983b85e5df63e013eaa9405095e88157332b4f68e78e0793d3e30417acbf4419893cfd424b75262dc5ade2ab6278ab86672f9ed186987b8c19d9295a17b98020f6002", 0x52}], 0x1}, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000100)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000240)={0x0, 0x0, <r2=>0x0}, &(0x7f00000001c0)=0xc)
r3 = semget$private(0x0, 0x4000000009, 0x82)
r4 = semget$private(0x0, 0x1, 0x400)
semop(r4, &(0x7f00000000c0)=[{0x1, 0x2}], 0x1)
semctl$SETALL(0x0, 0x0, 0x9, &(0x7f0000000200))
semctl$IPC_RMID(r3, 0x0, 0x0)
semctl$IPC_SET(r3, 0x0, 0x1, 0x0)
setregid(0x0, r2)
setregid(r2, 0xffffffffffffffff)
r5 = kqueue()
ftruncate(r5, 0x80000000)
kqueue()
bind(r1, &(0x7f0000000080)=@un=@file={0x0, './file0\x00'}, 0xa)
ioctl$BIOCSDLT(0xffffffffffffffff, 0x8004427a, &(0x7f0000000040)=0x8)
openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
pipe(0x0)
fcntl$setstatus(0xffffffffffffffff, 0x4, 0x0)
getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, 0x0)
pipe(0x0)
setreuid(0xee00, 0x0)
getuid()
setreuid(0x0, 0x0)
ioctl$WSKBDIO_GETMAP(0xffffffffffffffff, 0x80047476, 0x0)


semop(0x0, &(0x7f00000000c0), 0x0)
open(0x0, 0x0, 0x0)
sysctl$net_inet6_ip6(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x137, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x129, 0x0, 0x1}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0xe, 0x0, 0x2, 0x0, 0x233, {[@generic={0x2, 0x9, "96c729637cae4f"}, @sack={0x5, 0xe, [0x0, 0x0, 0x0]}, @timestamp={0x8, 0xa, 0xb018, 0x8}, @generic={0x4, 0x2}]}}, {"d1c2f0bfe2d0786ca28e44289f59aba04d62ff16e6bb47f1cd981d0cf5f225560531db5a3a6c3cb3d5ac50e0eec7423f3ef5e3c4a13f81f14f843a32b529e4649b57d581159522ddf03a6cabf358af4e1ae7ab79a9aac6417859ae29d8de08ba3da1e6387381a61f166b78d7ae58ccd15a08555c8e7db3e261cbba4f565ff3567edfcacd1a43a2f80b44a3727c2f46723f3826d9842357f4d467cb2e24ed586547d107e74cfe46502dde741762fe8ad6742200cf5fd16fcdadae4fd744b730286383e0444647e948151cb63c5c12b79f75a37762e3f013f189799eb699"}}}}}})


socket$inet(0x2, 0x8003, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
chdir(&(0x7f0000000240)='./file0\x00')
mkdir(&(0x7f00000002c0)='./file1\x00', 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000540)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000140)={0x0, <r1=>0x0, <r2=>0x0}, &(0x7f0000000080)=0xc)
chown(&(0x7f0000000040)='./file1\x00', 0x0, r2)
setreuid(0x0, 0xee01)
rename(&(0x7f00000003c0)='./file1\x00', &(0x7f0000000400)='./file0\x00')
r3 = semget$private(0x0, 0x4, 0x2)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000002c0)={<r4=>0xffffffffffffffff})
getsockopt$sock_cred(r4, 0xffff, 0x1022, &(0x7f00000000c0)={<r5=>0x0, <r6=>0x0}, &(0x7f0000000040)=0xc)
r7 = msgget$private(0x0, 0x397)
msgrcv(r7, &(0x7f00000007c0), 0x84, 0x1, 0x1800)
msgrcv(r7, 0x0, 0x0, 0x3, 0x1000)
msgsnd(r7, &(0x7f0000000d00)=ANY=[@ANYRESHEX], 0x401, 0x0)
msgctl$IPC_SET(r7, 0x1, &(0x7f0000000340)={{0x80000001, r6, 0x0, r6, 0x0, 0x2, 0x9}, 0x7ff, 0x0, r5, r5, 0xffffffffffffffff, 0x7, 0x12c, 0x3})
semctl$IPC_SET(r3, 0x0, 0x1, &(0x7f0000000300)={{0x0, r6, r2, r1, r2, 0x56, 0x3ff}, 0xb0, 0x3, 0xb245})
pipe(&(0x7f00000001c0)={<r8=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r8, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
write(0xffffffffffffffff, &(0x7f0000000240)="14bdfa5d1d34e2fecb284a6498307dcda9aec43050036123339a346f737850551408753f95b7688ad4c4e1dd5489e7bafc58d3e5823757ae8b630719ef187ccad995f13dbe19a6dd4e6902bd8297b0799b426aabe9fad9db6996571c6d9f8bb5d542c2148aa42be940970fe88d34d8f99afe7e7820237400000000008000000100"/138, 0xfc7e)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000001440))
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VNDIOCCLR(r1, 0x80384601, &(0x7f0000000100)={0x0, 0x6, &(0x7f0000000200)='./file0\x00', 0x8})
mprotect(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x4)
socket(0x18, 0x3, 0x0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
r2 = open(&(0x7f0000000080)='./bus\x00', 0x8000, 0x5)
r3 = getpid()
fcntl$setown(r2, 0x6, r3)
close(r2)
pipe2(0x0, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r4, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{0x2c}, {0x84}, {0x4000006, 0x2, 0x0, 0x3feffe}]})
r5 = socket(0x18, 0x3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r6 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r6, 0xc0106924, &(0x7f00000001c0))
writev(0xffffffffffffffff, &(0x7f0000000040), 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$FIONREAD(r5, 0x8080691a, &(0x7f0000000100))
pipe(&(0x7f0000000140))


r0 = open$dir(&(0x7f0000000580)='./file0\x00', 0x40000400001803c1, 0x0)
r1 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
poll(&(0x7f0000000180)=[{r1, 0x4}], 0x1, 0x0)
r2 = open(&(0x7f0000000080)='./file1\x00', 0x200, 0x0)
mmap(&(0x7f0000011000/0x2000)=nil, 0x2000, 0x0, 0x10, r2, 0x0)
pwritev(r0, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0x8020560a, &(0x7f00000002c0)={0x10, 0x0, [{&(0x7f0000ff3000/0x4000)=nil, &(0x7f0000fef000/0x4000)=nil}, {&(0x7f0000165000/0x2000)=nil, &(0x7f00001e6000/0x1000)=nil}, {&(0x7f0000787000/0x4000)=nil, &(0x7f000011c000/0x3000)=nil}, {&(0x7f00005bd000/0x4000)=nil, &(0x7f0000fee000/0x3000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000268000/0x2000)=nil}, {&(0x7f0000328000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000075b000/0x3000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000760000/0x3000)=nil, &(0x7f0000ff2000/0x4000)=nil}, {&(0x7f0000fec000/0x14000)=nil, &(0x7f0000ff9000/0x1000)=nil}, {&(0x7f0000ff9000/0x2000)=nil, &(0x7f0000fef000/0x1000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000729000/0x2000)=nil}, {&(0x7f0000ff5000/0x4000)=nil, &(0x7f0000ff6000/0x1000)=nil}, {&(0x7f0000ff8000/0x2000)=nil, &(0x7f000075c000/0x3000)=nil}, {&(0x7f0000432000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil}], './file0\x00'})
mknodat(0xffffffffffffff9c, &(0x7f0000000280)='./file0\x00', 0x1000, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r1 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
ioctl$DIOCMAP(r1, 0xc0106477, &(0x7f0000000080)={&(0x7f00000002c0)='./file0\x00', r0})
close(r0)
execve(0x0, 0x0, 0x0)
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaaaabb86dd605d34520030000000000000000000000000000000000000000000009f05000400000000000000010100"])
r2 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r2, 0x0, 0x0)
sysctl$vfs_nfs(&(0x7f0000000280)={0x7}, 0x5, 0x0, 0x0, 0x0, 0x0)
r3 = semget$private(0x0, 0x1, 0x0)
semctl$SETALL(r3, 0x0, 0x9, &(0x7f0000000040)=[0x0, 0x8001, 0x0])
r4 = socket(0x18, 0x2, 0x0)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f00000000c0)={0x0, 0x1ff}, 0x10)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0xfffffffffffffffe, 0x0, 0x0, 0x6ee}], 0x0, 0x0, 0x0, 0x0)
r5 = socket(0x18, 0x2, 0x0)
r6 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x0, 0x10, r6, 0x0)
setgroups(0x1, &(0x7f0000000080)=[0x0])
setsockopt$sock_int(r5, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r5, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
close(r4)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0x0, 0x0, 0x0, 0x40}], 0x0, 0x0, 0x0, 0x0)
r7 = socket(0x18, 0x2, 0x0)
setsockopt$sock_int(r7, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
close(r4)


sysctl$kern(0x0, 0x0, &(0x7f0000000180)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b10689ca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d12727b1e1d0cc45c7ebd5df53fb588fd0245528fe5700a5868eaf74d373197fb657a56e99cdbddbb382ad676b756d4e", 0x0, 0x0, 0x0)
r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
r1 = dup(r0)
writev(r1, &(0x7f0000000540)=[{&(0x7f0000000240)='<', 0x32}, {0x0}], 0x2)
execve(0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)


r0 = open$dir(&(0x7f0000000040)='./file0\x00', 0xa00, 0x0)
mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x0, 0x810, r0, 0x0)
r1 = open$dir(&(0x7f0000000380)='./file0\x00', 0x1, 0x0)
ftruncate(r1, 0x91a1)


socket(0x1e, 0x3, 0x0)
socket(0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
ioctl$TIOCSTSTAMP(0xffffffffffffffff, 0x8008745a, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
openat$vnd(0xffffffffffffff9c, &(0x7f0000000200), 0x4a0, 0x0)
open(&(0x7f0000000180)='./file0\x00', 0x75f493fec6515f78, 0x0)
r0 = getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r0, 0x0, 0x3, 0x2, 0x100000000})
r1 = fcntl$getown(0xffffffffffffffff, 0x5)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0xb32, r1)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
pipe(&(0x7f0000000000))
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040))
select(0x40, &(0x7f0000000040), 0x0, &(0x7f00000000c0), &(0x7f0000000100))
munmap(&(0x7f000000f000/0x7000)=nil, 0x7000)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000500)={0x0, 0x0, &(0x7f0000000480)=[{0x0}], 0x1}, 0x1)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000180)=[{{}, 0xfffffffffffffff9, 0x9, 0x0, 0x0, 0x2}, {{}, 0x0, 0x8, 0x0, 0x0, 0x10}], 0x0, 0x0)
r2 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x10215, 0x0)
ioctl$VNDIOCSET(r2, 0x81946467, &(0x7f0000000180)={0x0, 0xffffffffffffffff, 0x0})


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff}})
socket(0x0, 0x0, 0x0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000380), 0x0, 0x0)
socket(0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
getpgid(0x0)
fcntl$setown(0xffffffffffffffff, 0x6, 0x0)
getpgid(0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x4e, 0x0)
ioctl$VMM_IOC_INFO(r0, 0xc0185603, &(0x7f0000000000)={0x97, 0x0, &(0x7f0000000040)=""/151})


mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
mkdir(&(0x7f0000000000)='./file1\x00', 0x0)
rename(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000480)='./file0\x00')
rename(&(0x7f0000000a40)='./file0\x00', &(0x7f00000007c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


semctl$IPC_SET(0xffffffffffffffff, 0x0, 0x1, &(0x7f0000000000)={{0x1fe}, 0x0, 0x0, 0x1})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x1ff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x20, 0x0, 0x0, 0x1603519, "1a0001ad090201070000200007791dcebf00"})
writev(0xffffffffffffffff, &(0x7f0000000000)=[{&(0x7f0000000ac0)="a2de4b8e565f2bb52773d5616cabb69cc1a7a14051d04a27b5cb057d5ec186c897764a6fafeca04412715ba10e7ca93a9707b7cbd754867d0e0c8b7d17024a0065d70589e2daf7b535b109449a2bc51dc2889b09657923e30afb1295c5da1adf4193324f9129", 0x66}], 0x1)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
msync(&(0x7f0000ffc000/0x2000)=nil, 0x2000, 0x3)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000100)='./file0\x00', 0x2000, 0x0)
link(&(0x7f0000000340)='./bus\x00', &(0x7f0000000400)='./file0\x00')
ktrace(&(0x7f0000000180)='./file0\x00', 0x0, 0x0, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f0000000080)={&(0x7f0000000040)=[{0x24}, {}], 0x2})
r0 = socket(0x18, 0x3, 0x0)
setsockopt$sock_timeval(r0, 0xffff, 0x1021, 0x0, 0x0)
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x287e)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
close(0xffffffffffffffff)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0x9, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000480)={0x3, &(0x7f0000000200)=[{0xc}, {0x48}, {0x6}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x11, r1, 0x0)
ftruncate(r1, 0x8531)
writev(0xffffffffffffffff, &(0x7f00000026c0)=[{&(0x7f0000000400)="640493d78db6a9c1e335bb42b30c7b40a07b3baad98026cb156727aa65cfb18540954a46faf6cd689a437aff3f4961c4e46a834f6785f138abeced17229a790e349e6bd31df47a250b6311c17b41de694d02002d9c138fb5554471ad71a4e3b0c4a0f71fc4b1f3db02e683a852170340fa26d02f5dcb6c3772415d9b0c54258aba6ad66cd42dfd5163936af944020e200f6dad158fa90dfdd051d151c8c8cb6d711f408511a8c922ff7be9bf88fc6a18b3261c65ab46b32f89b7793b789d533f5dabd554659bcbb9e4082598016c9ffd443ad64a6c1384bebc4f0fa12ebee357f81c1bfbb7ff9c0bb5289f98184e590366ece692aac2a0f3fe55ae6072624ff0892d666934e9e7bb159ba7471e9ca862d48aa90c56e33b972e7ab5f15383b1e0bdc135ef14c4b638c9514366af346df10d2d11e3e82c7f98a731867165c536966e32790a098e86bc8c85d1d890537ee1a3b37a907cb151aa5b72801d9b213f04f59acc40bab4f2dfde876c2bc53ed02cd106d289a59310e0297a072b926369982acb409872a3a4325ed56f1d297bc8bbfb8f0a43f793ee9487a4492016350aa61cca26b86045d14a8f08e6f6d3e3be5520397612b66ebdf990efcf9ed9796836fa253dfa0389406ae25edb31abf6797596cf9b4a943972a4a19c43db1926c18bf15fc526127d1b04211fb4f4fe4c34dba511e8801a10008e54d343386c0c096641681899e65d2afea539fec10a2db4f07a06c7745c1005d0c2b1f020bd80e052df5a4969a40602d7b4350068968bae7ed03d05c9f0e7dd8940d1e37cfbf3370f5953261615197d350c60c2e3bdc186eff30d0700e608a4e08b2cac91f42275e3e6378a0747267335e017b5342a1662df7f3144a5c0e08008460631d2fb76c410c11c4dcc7f73fcab23a4794775f4284e02ad1ba71d64db4f1f4ced92b7a389fd596763283771b9faf89865c462f59e57a81cf8c3cbeffb268f00b6589ab79483f517583bc3a949c0df139721b6dcb9635dca559ac670c1b3ac3ffae886d18134df6d3b7078928ad5370c9687de2846d1f89f7455cf1f7bec56f3717cbdcab9a5fbe597f929e432ff093d92cb35d625bc8c5dcdc4df998db4b51f74775e5d6d119c505a2d0f27c9ead9e84af18c5d7e258cb6a4b57d28c5be27c3d72e277ae3a79bec39bdc88df392b2df6afcca55f79efb3fe6d0d8b50d7c8bbbc134450db20f1d5a773ce9cdc3b97b3274cb2e9c85496e9043e1eb83bda1b0960808b7dbf61fa0b420596976194a598a6ce1066867d13ed30035f8ff0ba3dcaa15df0cab8b96807cb82435a42067d4f1257de536842db0d3f7dfda891c146d79b600e6a2f994f2755cb278becfdaaefb2c7b976be36689c7a0feced48a723be73f29851f75e42e9d62c83d6aa220891c5c24634e8c7cc3eab033046727127a802dacbde8cf629c1f57d59ba0690af43ce944607c1fd9df72f74d67e7ddc2efd8dc6c459d0d1fe2ca57d14e20046f139050206dd8d203e0389aef6682cc6b861cc364184ee9708452dcb732992ce6dedbb8d57b5c5689b9836c54cdc91b4766f618d608d4bb380614d8cc2e03b3b3b5897ccb61f9fe2d16e5ced34cee9e856a6c52324c0eef64a4b7f9e8e7ed5a71d7b1fe9f94665ac75da67d114047ff5a1c3d0668d43d78c12565ea154f763418049e8dd3a1929b7fa4877c9e2cd984ab94818219a05b196b643adb3f064dbffd2b22ade017488178c5361a1c93f9c615e0e0cd28f25b7ca582d6942071cb7fae17b52eb41ead6e78914945802c19bac16c76ae14c7ed4be6e42713e8a4bd6220aadf458fa15b40777f94e223c596c7f80bab9584fcf4ff14f138adbbf7b1a7bdd686fa9249fe006aea38651e410fd4b1af0d79d7f1ee0cb2711ca81382f15804771da4a18d5f20e10ff9a7abd6ae8583d94f58769f3401526e517d963800c92485f9c24eac2d914895d4d9b866bbb769d22a00db29ce0b9a7d7112defb15d9776db55edf8fca337b1a496c7710acab8135aee0261a780ef6b39664469e33dab2398639d1becbdc74000b36c2ca5df2c0d3c5d3d3e054a2b8d91bc4656cf09300dd084cb0b625a587fba81cc6c2c3ef6f93342b65bc0e68222de6908492ac431f9f4dc1d3915a2cba79820c8c1f7c6e5c582d953b60a943eef44a6e7b244c808fb292f3944a4b1afbbadb06ed72c1d2cf9a60e02b319af032eddb475ae1947175f437262cefe05a89dc92367c8f8223e3a415b080b2bee22f084d00a289e42f5dcd0c31dc257d6bd09d214fad7aaa03d285a4ca618a5cc2bc0167ce424c40b879bfc294b9f2be0ee1c4669fe57d15c3b8fd626507ebb94d7313eda527d86a2bcaf9234a6eb4fcd2ecd218607961c7816094311a762d783ab7cef7009f103d938a5dee845b827001c87920ea3110b97b40a8525c41a57a03e389d9d864c57e10a849509135cdde81b89da8ee10540b76fe6c303a98bfa68a493ff59104b41c34c62092d3c0cc16d5c5c9abf7d0cc9206605ca6b69511091b512063985b03549573fbe60036cdfb28e77670e99b55a8f8151035ac93ef64b77f36951b0d3a31befef14741f874b313b66908f8da53a8a95255c16019876c85dd6070b2a8470f303b98d3c9ce2d203774794ecd2dbc43a69cd37c21f9c971634ff7b00af46adccaaeb1ca346bbdcad44151e38a94d91339c425554791adf2d3ff197221979625d2993ef7f4af06ec2438ab780ce737ac1bdbd873fa3b5cc0af43097b2be36bb9cbf87d39d3a7d54d5a49b176a3d74d95c06cd9b665248f84c27019f7b62232d9de01396aa0096f36c399b762913e207de7e3d24a2bbb04d879fe29b087ea262e82e4b3ca0fca62f222a592ab6ca1b1609e6a7500b8ed38db0d895c2df29604a64540e796787461ed7d1c5c562662b8f5146839cfbae18a6fb302033ad6558ce8a9d61d5de662b995ecb228535cddd02aa051321dadfd06dcd6409cf98d8a8697c7499f1695f173b427ff5f6cfdd224b66b89682d0e2978710e2bbfe7c9f2793cd2592ec7106c44e46c1d2bfe9d7cb53cac640f92f66506aefcc11c983e6c284a892dfc4b813771087baf9150eeb019ba0877afef77a66ee91b2c85ab1b95cc670ae9e80a4f20b8c8914c655828a68d6e8b509d479b5d04980a5bb17fb9ef17060f802f6e6f57e29d6587d6b8dc3438f592db639f718cc3bdaad6865d8a6aa94c47e1061cb8dfb8d7c54c168a29e8b1a78e1716ce413d429daaf09c924a7cde44eafc58fa5b3a5e3aa387a9465f024f7fe6ed9343d81dee65d106f635bbece1c99d5eb8ca0487c00c2851aaf24b2b6003e7150758f5a50943de2ba7b95710fa05f1c1e305dd7a14dba19feb94c9591d8cf724ef55aca7fb8e054763f7c80027b929666f6864db25a059859ca8831f9b7251e38eda5b00d0fc64a3b3460bd7ad733b9eac508a6a191a6465ca14729214d29cdfef5c6409a3f7e5db2044f836c049f5a14a78bea5c7a55e957a53d8d7d97203de65090319911c1788fc704d9382571d3d1bd2b35927d8d95b3f3b14930350ca34d577ff1d4ab69c7ef9f74f73590b8fd0d3574e7779e7f6564f9245c117c4272054015715a0671bcec7416d95a17da00b50e976168b9de75b673f6998119eb1c3b2bd1eebbf21aabc7e606991dc2e802058344d4854b1fe88688873db69c8ac70a9e4850960390a510231dc7159e3e89be0162258982be870d6135b0870986f66c19cf315552165fdccdd2acdff62cddeba67ca0e9578ab629d895a81f63c2262362a49ef4bd8a25dbf73fd100844496f40753d1496bdae8cf60f23db024ec56dbb594e9047ef5b005f579ff829dc1c3cf6844dd8bdcaf644481d171cec2bd25dce58a23617d5d11d7d44465214accb32a5767548fdfe3a428699ec03d02fbc2ccf1237ba07249af6f37ea83ddd8c7ec77f56ae7025c5662ecee8a8682d61823ec04bfebd6195147b016a28112821ad0f2aa32110dd31b38027f0e7fa042cce3e52ec467aaf95f998db202f819f201ee1322215018824a880755b94a2876e09e4c0cac01005ff8885e5f2f21c28b1aab38c62c33de0268521db2c198d19e7fafe69215465f6421b8503218f394d5a94c8601dd6514ff8a80f442ce07a4de65060229285b873667fa19859753c4b949ada2d3ab20afb732a4d4f0a9e5e13ef5a50c8361a465874e956464e201de1f30fa97398d3636ce88e479428b0bd8521010b92a22b4866c311593c101e3ed6169242c63334c7d6715a6dc50063e1c5658f590d0177464461a2ed8892719a770bcd687c597d51d46b89640b6610bc107a6b6d23e46052680aa18673", 0xc01}], 0x1)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x4)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
munmap(&(0x7f0000000000/0x3000)=nil, 0x3000)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x2, 0x1, 0x0)
setsockopt(r1, 0x6, 0x4, &(0x7f0000000000)="695cdd27", 0x4)
writev(r0, &(0x7f0000001480)=[{&(0x7f0000000100)="cc60d3d79a1a7122a5fb9de9ea6ca0b30fb2942ef7652736f10f86d45ae419b2ecf7af93d33b3de1f2c56c0d93da7484095d0d543baf7f0161a025c9c02a561f9a76d06f1eaec7d8df99d6c28b10fa891e47d6c3bba690a611889032ac7b3581d7c92d1c546e59764f069048316871794f0615dd4d8bb1057a61fb177be649004fb56a7d46c856a20d73f050bf29d58b803a676cc3761e8a47857f51d90a4465f9c605ab2829d78ea2571900", 0xac}, {&(0x7f0000001600)="b389e5ae8315694e73e14c29fdf9969f7fb32e47f8e5db595cfbb65daa477753f54afde1f80e268ce7b3d5ea6550ead1af49266905da721f77750e150fc7c9e77c824dc8bd7732a84a774fe0edce2662a2fa", 0x52}, {&(0x7f0000000240)="2a5f4cd9b73c31d629e8d68e605e5940744ef138960b671d42c56f79fcb70549247e5504e02f85a6099eff9291731e94399a7e966e783d4073ecd5dc8e540f32190bb47050aee3907495ecf7708d1c295a0836f79ba03ea13db12836c2441989726ffbf7fd1da55bfe2caaf081a1ef55", 0x70}], 0x3)
pipe2(&(0x7f0000000080), 0x0)
recvfrom$unix(0xffffffffffffffff, &(0x7f0000000400)=""/157, 0xad, 0x1800, 0x0, 0xfffffffffffffe7b)
sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000000)="9b1809ffffffffffffff7f473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6fd74c94d1b44", &(0x7f0000000040)=0x10011, 0x0, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x0, 0x10, r0, 0x0)
r2 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r3 = fcntl$dupfd(r2, 0x3, 0xffffffffffffffff)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x47}, 0x2, &(0x7f00000000c0)="3be91ab1ded9ab1f79d4e06e235fa47dc44ed1a04e24f926e97cec247521215f39a634cd83019a560c1183dec3be8e7234b80c3740811cc8661e5a33803170", &(0x7f0000000080)=0x3f, &(0x7f0000000180)="5935bd8e76660d907c045aa6a852a6085f1b0528f526434c7f46bad55fed13c8bca5b717b826048d2269af85d528bb5086c9a14a4c9dcd1cc539c3066ff73adb7e19d50d69a6fb5522ee8a427bbad734d4bb13cd0ee6a7081a76ad71ac7e32ef3ecf252edb184e27fdc4153045be1ccf841ff2e51189508ef04851921d163b97d2a646", 0x83)
ioctl$FIONREAD(r3, 0x8004745d, &(0x7f0000000200))
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x0, 0x0})
pipe(0x0)
r4 = socket(0x18, 0x2, 0x0)
setsockopt(r4, 0x1000000000029, 0xb, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
setsockopt(r4, 0x1000000029, 0xd, &(0x7f0000000080), 0x0)
r5 = kqueue()
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000340)=[{{}, 0xffffffffffffffff, 0x15}], 0x0, 0x0)
kevent(r5, &(0x7f0000000000), 0x4c, 0x0, 0x300, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r6=>0xffffffffffffffff})
dup2(r6, 0xffffffffffffffff)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
setuid(0xffffffffffffffff)
mkdir(0x0, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
recvmsg(0xffffffffffffffff, 0x0, 0x0)
sendmsg(0xffffffffffffffff, 0x0, 0x0)
recvfrom(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
unveil(&(0x7f0000000000)='./file0\x00', &(0x7f00000001c0)='r\x00')
unveil(&(0x7f0000000080)='./file0/file1\x00', 0x0)
unveil(&(0x7f0000000200)='./file0/file1\x00', 0x0)
ioctl$BIOCLOCK(r0, 0x20004276)
seteuid(0x0)
ioctl$BIOCGDLTLIST(r0, 0xc010427b, &(0x7f0000000180)={0x0, &(0x7f0000000140)})
r1 = socket(0x800000018, 0x0, 0x7)
r2 = getgid()
getsockopt$SO_PEERCRED(r1, 0xffff, 0x1022, &(0x7f0000000040), 0x16)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0xffffffffffffffff, 0x0, r2}})
socket(0x0, 0x0, 0x0)
close(0xffffffffffffffff)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, 0x0)
munmap(&(0x7f0000ffa000/0x3000)=nil, 0x3000)
syz_emit_ethernet(0x52, &(0x7f0000000380)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa86dd60362f5f001c2b00fe800000000000000000000000000004000004"])


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x100, r0)
r1 = open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r1, 0x0)
recvmmsg(0xffffffffffffffff, 0x0, 0x2, 0x0, &(0x7f0000000100))


open(&(0x7f0000000000)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`\x00', 0x200, 0x0)
openat$diskmap(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
socket(0x0, 0x0, 0x0)
mmap(&(0x7f0000400000/0xc00000)=nil, 0xc00000, 0x2, 0x10, 0xffffffffffffffff, 0x1000000)
mprotect(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
ioctl$FIOASYNC(0xffffffffffffffff, 0x8004667d, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1001, 0x0, 0x0)
r0 = msgget$private(0x0, 0x8)
pipe2(&(0x7f0000000000), 0x0)
setrlimit(0x8, &(0x7f0000000040)={0x7, 0x50})
r1 = syz_open_pts()
close(r1)
syz_open_pts()
ioctl$TIOCSETAW(0xffffffffffffffff, 0x802c7415, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000380)=[{0xb1, 0x0, 0xfd}, {0x34, 0x0, 0x0, 0x2}, {0x8006}]})
syz_emit_ethernet(0x56, &(0x7f00000003c0)=ANY=[])
writev(r1, &(0x7f0000000640), 0x0)
select(0x40, &(0x7f0000000040)={0x10374, 0x6a, 0x2, 0x0, 0x0, 0x0, 0x0, 0xff}, 0x0, 0x0, 0x0)
msgsnd(r0, &(0x7f0000000200)=ANY=[@ANYBLOB, @ANYRESOCT], 0x401, 0x800)
msgsnd(r0, 0x0, 0x401, 0x0)
msgrcv(r0, &(0x7f0000000400)={0x0, ""/137}, 0xaf, 0x0, 0x0)


select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x2, 0x0)
r1 = dup(r0)
setsockopt$inet_opts(r1, 0x0, 0x14, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000000)=[{0x4c}, {0x24}, {0x812e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])


sysctl$hw(&(0x7f0000000040)={0x6, 0x9}, 0x2, 0x0, 0x0, 0x0, 0x0)
socket(0x1, 0x2, 0x0)
clock_getres(0x5, 0x0)
kqueue()
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, &(0x7f00000001c0))
r0 = open(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
ioctl$FIONBIO(r0, 0x8004667e, &(0x7f0000000200)=0x80000000)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
openat$wskbd(0xffffffffffffff9c, &(0x7f0000000140), 0x1, 0x0)
r1 = socket(0x1, 0x0, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f0000000080)={0x2, &(0x7f0000000400)=[{0x35}, {0x6, 0x0, 0x0, 0xe00000}]})
write(r2, &(0x7f0000000000)="7696e5f3d1f18c37cea8615ac7cf", 0xe)
msgctl$IPC_SET(0x0, 0x1, 0x0)
lseek(r1, 0x0, 0x2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x1}, {0x50}, {0x16}]})
write(r0, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xfef3)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000200)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmsg(0xffffffffffffffff, &(0x7f0000000700)={0x0, 0x0, &(0x7f0000000640)=[{0x0}, {0x0}, {&(0x7f0000000540)=""/239, 0xef}], 0x3, 0x0}, 0x0)
setreuid(0xee00, 0x0)
r2 = getuid()
setreuid(0x0, r2)
r3 = socket(0x2, 0x1, 0x0)
fchmod(0xffffffffffffffff, 0x3218b84e33509d91)
ioctl$FIONREAD(r3, 0x80206979, &(0x7f0000000000))
setsockopt$sock_int(r1, 0xffff, 0x1004, &(0x7f00000000c0)=0x8000, 0x4)
sendto(r0, &(0x7f0000000440)="df", 0xa, 0x0, 0x0, 0x0)
sendmmsg(r0, &(0x7f0000000500)={0x0}, 0x10, 0x0)
recvmsg(r1, &(0x7f0000000380)={0x0, 0x0, &(0x7f0000000040)=[{&(0x7f0000000100)=""/218, 0x11d}], 0x1, 0x0}, 0x0)
sendto(r0, &(0x7f0000000280)="e61d6921d404904850d48de053d6d14ee63d8e254c600111c457a9af65b83aeb21", 0x21, 0x0, 0x0, 0x0)


r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r3 = socket(0x2, 0x1, 0x0)
r4 = dup(r3)
r5 = fcntl$dupfd(r4, 0x2, 0xffffffffffffffff)
close(r5)
r6 = socket(0x2, 0x1, 0x0)
connect$unix(r6, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r5, 0xffff, 0x1023, &(0x7f0000000080), 0x4)
setsockopt$sock_int(r2, 0xffff, 0x1023, 0x0, 0x0)


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x2, &(0x7f0000000200)=[{0x74}, {0x6}]})
setrlimit(0x5, &(0x7f0000000980))
r0 = syz_open_pts()
socket$inet6(0x18, 0x2, 0x0)
ioctl$VMM_IOC_READREGS(r0, 0xc028756b, &(0x7f0000000400))
socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x66, &(0x7f0000000100)=ANY=[@ANYBLOB="aaaaaaaaaaaaffffffffffff86dd60aa862000302c0000000000070000000000000000000500000000000000"])
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x2b}, 0x4, &(0x7f0000000380)="3998a035", &(0x7f0000000080)=0x4, 0x0, 0x0)
ioctl$TIOCSTOP(0xffffffffffffffff, 0x2000746f)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x6, &(0x7f0000000000)=[{0x7, 0x0, 0x0, 0x81}, {}, {0x4000006, 0x0, 0x0, 0x3fefff}, {0x3, 0x6, 0x7, 0x3ff}, {0x7, 0x40, 0x3, 0x2}, {0xd5c, 0x0, 0x1, 0x2c61}]})
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
r2 = open(&(0x7f00000002c0)='./bus\x00', 0x2, 0x0)
poll(&(0x7f0000000040)=[{r2, 0x40}], 0x1, 0x0)
ioctl$WSMUXIO_INJECTEVENT(r2, 0x80185760, &(0x7f0000000140))
r3 = openat(0xffffffffffffff9c, &(0x7f00000003c0)='./file0\x00', 0x200, 0x2)
syz_emit_ethernet(0x3e, &(0x7f00000009c0)=ANY=[@ANYBLOB="aaaaaaaaaaaaccaaaaaaaaaa86dd60cb706500083b0035b282d55c8bf287fa1f01eb6b0de395ff02000000000000000000d958de4ab500000000014e214e"])
poll(&(0x7f00000000c0)=[{r3, 0x4}], 0x1, 0x0)
write(r1, &(0x7f0000000180), 0x0)
fcntl$setflags(r1, 0x2, 0x1)
open$dir(&(0x7f00000000c0)='.\x00', 0x0, 0x0)
kqueue()
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r4 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r4, 0xc0106924, &(0x7f00000001c0))
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000100), 0x8, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)


r0 = socket(0x11, 0x3, 0x0)
r1 = msgget$private(0x0, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x0, 0x0)
openat(0xffffffffffffff9c, 0x0, 0x0, 0x0)
msgrcv(r1, &(0x7f0000001500)={0x0, ""/4096}, 0x1008, 0x0, 0x1400)
msgsnd(r1, &(0x7f0000000500)=ANY=[@ANYBLOB="000000000012000042fee188"], 0x11, 0x0)
msgsnd(0x0, 0x0, 0x0, 0x0)
msgsnd(r1, &(0x7f00000006c0)=ANY=[@ANYBLOB="0300000000000000ffffffffffff10fd226fe763c17d3a2c97f93d274962bca36246e07d5514744c52fd78f2d0a5dc1bc819c7c2d589f27295c96ca8a194794cefc1fc5993108c52e9c994b3b33779def1bbffdc7a368dd99f2107c345001fa4c0fe80f176dd198361a14c2eeca785c42609a1abdc1677910a5aef891496a8ca501975bdffcbe9b636e55618fdb7cff43c80595ee173a889b13cedea322a68ebaadbd0d0857a22ddc8df0084c097c74e2c4b17027b930d64efd9547f58f81dcdfce7d8970cb58857df4053e0226dfc2d65cf02e404ed3b5dabd3c5f31aeef615280d8dd4d9d5a71328a5fece40dcc3f592193cf9fa9de2db394a37d2101a92143611ef510e"], 0xed, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x0, 0x0)
msgctl$IPC_SET(r1, 0x1, &(0x7f0000000140)={{0xc4b, 0x0, 0x0, 0x0, 0x0, 0x4, 0x8}, 0x1ff, 0x20, 0x0, 0x0, 0xc5b, 0xffffffffffffffff, 0x6, 0x6})
msgctl$IPC_STAT(r1, 0x2, &(0x7f00000003c0)=""/153)
r2 = syz_open_pts()
fcntl$lock(r2, 0x7, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETWF(r3, 0x80104277, 0x0)
msgsnd(r1, &(0x7f0000000080)={0x1, "7cbe308e552465be350e44b638fb671bbe4485f364a9408fa4b68cf1d3093adffe61fc15c6b0ee032cf54a13"}, 0x34, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
msgrcv(0x0, 0x0, 0x90, 0x0, 0x0)
msgrcv(0x0, 0x0, 0xe8, 0x0, 0x0)
msgsnd(0x0, 0x0, 0x0, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
getgid()
getuid()
getgid()
sendto$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x14}, 0x4, 0x0, 0x0, 0xfffffffffffffffe, 0x4)
syz_emit_ethernet(0x3e, &(0x7f0000000000)={@local, @local, [], {@ipv6={0x86dd, {0x0, 0x6, "9ac9d0", 0x8, 0x0, 0x0, @rand_addr="03498c7d3c88732762c5bbfb418dbe5c", @rand_addr="b82957248c3701367c9909fa96bf7cb7", {[@fragment]}}}}})


syz_emit_ethernet(0x1b, &(0x7f0000000000)=ANY=[@ANYBLOB="fffd640000000000000000000a"])
sysctl$hw(&(0x7f0000000000)={0x6, 0xb}, 0x5, &(0x7f0000000040), 0x0, 0x0, 0x0)


sendmsg$unix(0xffffffffffffffff, &(0x7f00000018c0)={0x0, 0x0, &(0x7f00000003c0)=[{0x0}], 0x1, 0x0, 0x10}, 0x40a)
sendmsg$unix(0xffffffffffffffff, 0xfffffffffffffffe, 0x0)
mknod(0x0, 0x0, 0x0)
sysctl$net_inet6_icmp6(0x0, 0x0, 0x0, 0x0, &(0x7f0000000140)="80468b309b2548cca0c3bd621508525753789a6678d065d43ee4beba5f1b29d75f17fbc7afd04721d15570cfc48e0c124334ca8f55e8fe16ae3c48f5447f2ffc59e1de35169f015f6c7037faee2301a56aa2741434d2b14fab1e7701f22c3262a9f8e27a8a696caa3b9ab7c06b7d2489b7ce8bf6fd9b847cf1d878486af7992904af965bf98c7545167c41c2041c0942", 0x90)
r0 = socket(0x2, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x8020697a, 0x0)
kqueue()
sysctl$vm_swapencrypt(&(0x7f0000000040)={0x7, 0x2, 0x3}, 0x3, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x31}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0xfffffffffffffda3)
setrlimit(0x0, &(0x7f0000000980)={0x0, 0x35})
r1 = socket(0x18, 0x2, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
close(r1)
r2 = socket(0x18, 0x3, 0x0)
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f0000000100), 0xc)
setsockopt(r2, 0x1000000029, 0x0, 0x0, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
writev(r2, &(0x7f0000000680)=[{&(0x7f0000000000)="2f87bb4098d7de568a6a2453616c321b9657609db9199f45ae67568303000000000000001af7383890", 0x29}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000240)=[{0x6c}, {0x64}, {0x6}]})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000))
r1 = socket(0x18, 0x2, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r2 = socket(0x18, 0x3, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r2, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f00000000c0), 0x10)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sysctl$kern(&(0x7f0000000040)={0x1, 0x59}, 0x2, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85baa97981056ef1043f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0xa1, &(0x7f0000000340)='\n\x00', 0x2)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
syz_emit_ethernet(0x138, &(0x7f00000002c0)=ANY=[])
sendmsg(r1, &(0x7f0000000ec0)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
r4 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000158000/0x3000)=nil}, {&(0x7f000003d000/0x1000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f00000c3000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000157000/0x1000)=nil}, {0x0, &(0x7f00001eb000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f00000e0000/0x1000)=nil, &(0x7f00000d8000/0x3000)=nil}, {&(0x7f00000ca000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f00000f8000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
ioctl$TIOCSTAT(r4, 0x20007465, &(0x7f0000000200))
ioctl$WSDISPLAYIO_WSMOUSED(r4, 0x80185758, &(0x7f0000000280)={0x8, 0x10001, {0x4, 0x9}})
syz_emit_ethernet(0x1019, &(0x7f0000000400)=ANY=[])


mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f00000000c0)={&(0x7f0000000000)='./file0\x00', 0x4, 0x0})
r1 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r1, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r1, 0x0)


r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x400000002, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r2 = socket(0x18, 0x1, 0x0)
r3 = dup2(r1, r2)
sendmsg$unix(r3, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


nanosleep(&(0x7f0000000340)={0x4}, 0xfffffffffffffffe)
execve(0x0, 0x0, 0x0)


r0 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000680)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000300)=[{0x87}, {0x2}, {0x26}]})
r2 = getpid()
r3 = msgget$private(0x0, 0x0)
msgctl$IPC_SET(r3, 0x1, &(0x7f0000002f80)={{}, 0x0, 0xff, r2, 0x0, 0x7fffffff})
syz_emit_ethernet(0x3e, &(0x7f0000000340)=ANY=[@ANYRES64=r0, @ANYRESOCT=r1, @ANYRESDEC=r2, @ANYRES64, @ANYRES32=0x0, @ANYRESOCT=r0, @ANYRESDEC=r0, @ANYRESDEC=r0, @ANYRES32, @ANYRESOCT=r2, @ANYRESDEC=r3, @ANYRES32=r0])
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000280), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r4, 0x80104267, &(0x7f0000000440)={0x0, 0x0})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000000), 0x4)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0xc, &(0x7f00000000c0)="eaff125c0000e909", 0x8)


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
r2 = socket$inet(0x2, 0x2, 0x0)
close(r2)
r3 = socket$inet(0x2, 0x3, 0x0)
dup2(r1, r3)
setsockopt$inet_opts(r2, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0x8)


mquery(&(0x7f0000ff4000/0x1000)=nil, 0x7ed841f1e000, 0x0, 0x0, 0xffffffffffffffff, 0x0)
socket$inet(0x2, 0x0, 0x0)
r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000540), 0x1, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x1, &(0x7f0000000180)=[{0x6c}]})
ioctl$WSKBDIO_GETMAP(r0, 0xc010570d, &(0x7f0000000180)={0x0, 0x0})


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
writev(r0, &(0x7f0000000280)=[{&(0x7f0000000000)='T5', 0x2}], 0x1)


getuid()
setreuid(0x0, 0x0)
r0 = socket(0x800000018, 0x2, 0x0)
setreuid(0xee00, 0x0)
r1 = socket(0x18, 0x2, 0x0)
close(r1)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
r2 = socket(0x800000018, 0x2, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0))
socket(0x0, 0x0, 0x0)
getsockname$inet(0xffffffffffffffff, 0x0, &(0x7f0000000000))
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000), 0x4)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
setsockopt$sock_int(r0, 0xffff, 0x1000, &(0x7f0000000140)=0x3, 0x4)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000180))
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
openat$null(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
rename(&(0x7f0000000080)='./file0\x00', &(0x7f00000000c0)='./file0\x00')
mkdir(&(0x7f0000000080)='./file0\x00', 0x0)


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000280)="58c2d25c8e502a2995880810b3f160e2c254952259b75eca23bc92", 0x2}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
getsockopt(r0, 0x0, 0x9, 0x0, 0x0)


sysctl$vm(&(0x7f0000000000)={0x4, 0x12}, 0x7, &(0x7f0000000040)="c06d154be3aee5f8787f8b9cda7554335b763bb5deea5ccecb4d1b57a9f6fa18e47fc7b119db587e58811e666e84a806495b45c36164bd5b135280243ed0a01466056e93082876ba33ee8cf2b0b3907f236f38175101000000d7e39544aea098d19ee63d03cbf92380dbe904538135f09e408bbe17a54a364b04ee64b0ad54e6d4e38114ced38c328aff2e224239ba29eb0796e8c3e8344a2cd9e663bb21035ebf391872f3015c164556e4a5b966122c56edd85fc996f12fa1b92e47aa", 0x0, 0x0, 0xfffffffffffffe8f)


sysctl$machdep(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
msync(&(0x7f0000001000/0x4000)=nil, 0x4000, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000)=@un=@abs={0x0, 0xd}, 0x10)
setsockopt(r0, 0x6, 0x8, &(0x7f0000000100)="77b3d8fa", 0x4)
listen(r0, 0x0)
r1 = socket(0x2, 0x1, 0x0)
connect$unix(r1, &(0x7f0000000000), 0x10)
sendto$inet(r1, &(0x7f0000000100)="18", 0xffffff36, 0x195a05e282d6161, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
dup(0xffffffffffffffff)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x0, 0x0})
syz_emit_ethernet(0x36, 0x0)


r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
mkdir(&(0x7f0000000000)='./file2\x00', 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x2, 0x2, 0x0)
fcntl$setstatus(r3, 0x4, 0x40)
connect$inet(r3, &(0x7f0000000000), 0x10)
r4 = getpid()
fcntl$setown(r3, 0x6, r4)
setsockopt$sock_int(r2, 0xffff, 0x1023, &(0x7f0000000040), 0x4)
shutdown(r3, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000280)=[{0x2c}, {0x64}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f00000002c0)=ANY=[])


setreuid(0xee00, 0x0)
r0 = getuid()
setuid(r0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x80206916, &(0x7f00000001c0))


mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
poll(&(0x7f0000000ac0)=[{0xffffffffffffff9c}], 0x20000000000000cd, 0xffffffff)
execve(0x0, 0x0, 0x0)


socket(0x2, 0x2, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000000c0))
sysctl$net_inet6_icmp6(0x0, 0x0, &(0x7f0000000080)="65feaba9a71942a5", &(0x7f0000000100)=0x8, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000200)={0x4, 0x2, 0x6, 0x19}, 0x4, 0x0, 0x0, &(0x7f00000002c0)="e2420dc5", 0x4)
socket$inet(0x2, 0x3, 0x0)
setreuid(0xee00, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x0, 0x0})
syz_emit_ethernet(0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
socket(0x2, 0x2, 0x0)
sysctl$kern(&(0x7f0000000040), 0x1, 0x0, 0x0, 0x0, 0x0)
socket(0x18, 0x3, 0x3a)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{0x0, 0x0, 0x0, 0x402}, {0x2}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x33}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)


openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
select(0x40, &(0x7f00000000c0), 0x0, 0x0, 0x0)
ioctl$SPKRTONE(0xffffffffffffffff, 0x80085301, &(0x7f0000001540))
ioctl$VNDIOCGET(0xffffffffffffffff, 0xc4104603, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r0, 0xc0206922, &(0x7f00000001c0))


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000180)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
connect$unix(r0, &(0x7f0000000040)=@file={0x0, './file0\x00'}, 0xa)
clock_getres(0x0, &(0x7f0000000000))
setreuid(0xee00, 0x0)
sysctl$net_inet_carp(&(0x7f0000000380)={0x4, 0x2, 0x70, 0x4}, 0x4, 0x0, 0x0, 0x0, 0x0)
getuid()
socket(0x2, 0x1, 0x0)
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x0, 0x10, r1, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x12, r1, 0x0)
mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f00000000c0)='./file0\x00', 0x21e)
chdir(&(0x7f0000000140)='./file0\x00')
symlink(&(0x7f0000000200)='./file2\x00', &(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
open(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
r2 = semget$private(0x0, 0x7, 0x3c0)
semop(r2, &(0x7f0000000080), 0x0)
rename(&(0x7f0000000540)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000080)='./file0\x00')
semctl$GETPID(r2, 0x8cf42d929c474033, 0x4, &(0x7f0000000240))


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)='\x00', 0x1}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
setsockopt$inet_opts(r0, 0x0, 0xa, &(0x7f0000000080)="02", 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x3d}, {0x1d}, {0x8106}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0x8020560a, &(0x7f00000002c0)={0x10, 0x0, [{&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000fef000/0x4000)=nil}, {&(0x7f0000165000/0x2000)=nil, &(0x7f0000ff6000/0x4000)=nil}, {&(0x7f0000772000/0x4000)=nil, &(0x7f000011c000/0x3000)=nil}, {&(0x7f00005bd000/0x4000)=nil, &(0x7f0000fee000/0x3000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000ff4000/0x4000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000760000/0x3000)=nil, &(0x7f0000ff2000/0x4000)=nil}, {&(0x7f0000fec000/0x14000)=nil, &(0x7f0000ff9000/0x1000)=nil}, {&(0x7f0000ff9000/0x2000)=nil, &(0x7f0000fef000/0x1000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000ff0000/0x1000)=nil}, {&(0x7f0000ff5000/0x4000)=nil, &(0x7f0000ff6000/0x1000)=nil}, {&(0x7f0000ff8000/0x2000)=nil, &(0x7f0000fef000/0x3000)=nil}, {&(0x7f00005db000/0x3000)=nil, &(0x7f0000ffa000/0x4000)=nil}], './file0\x00'})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaaaabb86dd605d34520030000000000000000000000000000000000000000000009f0500040000000000000001010090780000000060397772"])
open$dir(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000000c0)=[{0x3d}, {0x4}, {0x8006, 0x0, 0x0, 0x400000}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])


setitimer(0x0, &(0x7f0000000040)={{}, {0x0, 0x8000}}, 0x0)
setitimer(0x0, &(0x7f0000001000)={{}, {0x400}}, 0x0)


open$dir(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
ktrace(&(0x7f0000000440)='./file0\x00', 0x4, 0xf06, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000000c0)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvfrom$unix(r0, &(0x7f00000000c0), 0x832f1f7d, 0x0, &(0x7f0000000000)=@abs, 0x2000c600)
sendto$unix(r1, 0x0, 0x0, 0x0, 0x0, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x4, 0x0, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x0, &(0x7f0000000000)="60e115575bd5f63b0dd7a4e26c43a4c0a6a27fb4c1e48d497ad7e8f101ac60dbf73a5fe7ba0c37253b86d68ba32a39c3067bf8ebbc375ff2dcd0c4c45dfba79d2f13a6836160f4d60b2b3369c7492ca8bf397e8f6586f430d1b3ba1dbcc5332beb5561be8087a1f9e8e7f80e208250903e98cab7c111fe5a62420a4c621fa643d3488593d65ea3dc7a811fa328f4fe838573f9b45406112398ffd5b0dd49cd490c3fada3737ddeb852d637368f43336239aba77f2e2bf5f23a0733a6152ef8fdf831751b7cf74dc014", 0xc9)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240), 0x0)
r2 = socket$inet(0x2, 0x2, 0x0)
dup2(r0, r2)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000240)="ea1ffe548af97817", 0x8)
rename(0x0, &(0x7f0000000200)='./file1\x00')
r3 = socket(0x18, 0x3, 0x0)
setsockopt(r3, 0x1000000029, 0x28, &(0x7f0000000000)="5ab7776a", 0x4)
syz_emit_ethernet(0xba, &(0x7f0000000180)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaabb86dd600000000084000080000000000000000000000000000000ff020000000000000000000000000001"])
sysctl$hw(&(0x7f00000001c0)={0x6, 0x18}, 0x2, &(0x7f00000000c0), 0x0, &(0x7f0000000140), 0x0)
r4 = socket$inet(0x2, 0x2, 0x0)
r5 = fcntl$dupfd(r4, 0x0, r4)
sendmsg$unix(r5, &(0x7f0000000a80)={&(0x7f0000000200)=@abs={0x0, 0x0, 0x0}, 0x8, 0x0, 0x0, &(0x7f0000000a40)=[@cred={0x20}, @cred={0x14}], 0x40}, 0x0)
r6 = syz_open_pts()
fcntl$lock(r6, 0x9, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1000300000000})
flock(r6, 0x1)
flock(r6, 0x3)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000100)=[{0x15}, {0xc0}, {0x6, 0x0, 0x0, 0x88f0}]})
write(0xffffffffffffffff, &(0x7f0000000280)="ce4aa4a25043cb02aadf8701f131", 0xe)
r7 = semget$private(0x0, 0x7, 0x3c0)
semop(r7, &(0x7f0000000100)=[{0x3, 0xa, 0x800}, {0x1, 0x2ff}, {0x1, 0x8, 0x1000}, {0x3, 0x3ff, 0x1800}, {0x2}, {0x2, 0x201, 0x3000}], 0x6)
semctl$GETPID(r7, 0x3, 0x4, &(0x7f0000000240)=""/8)
semop(r7, &(0x7f0000000200)=[{0x3, 0x0, 0x800}, {0x1, 0x100, 0x800}, {0x0, 0x1}, {0x4, 0x49, 0x400}, {0x0, 0x8, 0x1800}], 0x2aaaaaaaaaaaab5f)
semop(r7, &(0x7f00000002c0)=[{0x4, 0xfff, 0x1000}, {0x0, 0x420, 0x1000}, {0x1, 0x106, 0x1800}, {0x0, 0x3, 0x800}, {0x0, 0x200}, {0x0, 0x4, 0x800}, {0x2, 0xfff8}, {0x2, 0x7}, {0x4, 0x1, 0x1000}, {0x3, 0x7e7, 0x800}], 0xa)
semop(r7, &(0x7f0000000280)=[{0x4, 0x1}, {0x2, 0x8400, 0x1000}, {0x1, 0x2, 0x400}, {0x3, 0x8, 0x1000}, {0x3, 0x4, 0x800}], 0x5)
semctl$IPC_SET(r7, 0x0, 0x1, &(0x7f0000000140)={{0x1f, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0x10, 0x8}, 0x8, 0x0, 0x5})
getuid()


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)={0x3, 0x7fffffff})
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x30, 0x0, 0x57d, 0x0)
dup2(r1, r0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x3, 0x0)
seteuid(0xffffffffffffffff)
ioctl$FIONREAD(r2, 0xc0206937, &(0x7f00000001c0))


mknod(&(0x7f0000000040)='./file0\x00', 0x6000, 0xe02)
sysctl$kern(&(0x7f0000000040)={0x1, 0x48}, 0x2, &(0x7f0000000080), &(0x7f00000000c0), 0x0, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(0xffffffffffffffff, &(0x7f0000001100)=[{0x0}], 0x1)
socket$inet6(0x18, 0x0, 0x0)
pwritev(r0, &(0x7f0000000000)=[{&(0x7f00000000c0)='\b', 0x1}], 0x1, 0x0)


r0 = socket$unix(0x1, 0x2, 0x0)
sendmmsg(r0, &(0x7f0000001900)={&(0x7f00000018c0)={&(0x7f0000000140)=@in={0x2, 0x2}, 0xc, 0x0, 0x0, 0x0}, 0xc8}, 0x10, 0x0)


setrlimit(0x8, &(0x7f0000000100)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f00000000c0)={0x0, 0x0, 0x8a38, 0x0, "07160a009cef01098b748200"})
writev(r0, &(0x7f0000000040)=[{&(0x7f0000000180)="9532e1276d71a275de262aed", 0xc}], 0x1)
r2 = dup2(r1, r0)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000080)={0x7fffffff, 0x0, 0x1, 0x7ff, "892af9a5b145aa9606a6d700"})
poll(&(0x7f0000000000)=[{r2, 0x40}], 0x1, 0x0)


ktrace(&(0x7f0000000100)='./file1\x00', 0x0, 0x0, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x0, 0x0)
symlink(&(0x7f0000000100)='./bus/\x00', &(0x7f0000000140)='./bus\x00')
open$dir(&(0x7f00000001c0)='./bus/\x00', 0x0, 0x0)


close(0xffffffffffffffff)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
getsockname$inet(0xffffffffffffffff, 0x0, 0x0)
semop(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
syz_extract_tcp_res(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{0x4c}, {0x54}, {0x8126}]})
syz_emit_ethernet(0x2e, &(0x7f0000000140)=ANY=[])


open(&(0x7f0000000140)='./file0\x00', 0xf8e, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000240)={<r0=>0x0}, 0xc)
ktrace(&(0x7f0000000200)='./file1\x00', 0x0, 0x40000730, r0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000200))
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x40000802)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$vfs_nfs(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
socket(0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
sysctl$vfs_nfs(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$fs(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
msgctl$IPC_SET(0x0, 0x1, 0x0)
sendsyslog(0x0, 0xfffffffffffffc59, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r1 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSKBDIO_SETENCODING(r1, 0x80045710, &(0x7f00000000c0)=0x100)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, "090e4d000000000000000000000000000900", 0x1})
setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000100)={0x978b, 0x80000001, 0x3, 0x80a19f, "bb08000100f1675910508b00"})
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, 0x0)
syz_emit_ethernet(0x17a, &(0x7f00000001c0)=ANY=[@ANYBLOB="f3a2a8908a86aaaaaaaaaabb86dd601ab5b60000100000004e95"])
syz_emit_ethernet(0x126f, &(0x7f00000000c0)=ANY=[@ANYBLOB="aaaaaaaaaaaa00000000000086dd609ded1a12390000c4a4e3434e58d025a6a8a81cf312b8befe8000000000000000000000000000aa00030000000000000101000101000401000401000103000000000100010200000000c7ab6f1eba08bf03d1805fce0ef2ab82f4a065245eccda108bec7cb23f632c993265a4cefeb77b1406d562a47d4b0054943553278b519ed107f62b5c352f8e68d83c1fd85b8e1083556d7fa2fc09a3e823fa940de6ef1b18ddb2a2dba0d2d9c1b44b20ed3a932a2c47f4f4d3e34ea1b67a607001a4541a87d5d347b5049b3444dc2b7abe3499079a5701e88493acb2eb1808e8b1f74311083f93341607915aa46325934e81b672d809cb6bc5f3d64480ba4db4432a67c2548e259fe7831f7c6dfe"])
fcntl$setstatus(r0, 0x4, 0x80)
ioctl$FIONREAD(0xffffffffffffffff, 0x4004667f, &(0x7f0000000340))
sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f00000001c0)="55f8f5782087a072a82ec35f78d14780f518", 0x1a)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
preadv(0xffffffffffffffff, 0x0, 0x0, 0x0)
r1 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc1206949, &(0x7f00000001c0))


open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x8, &(0x7f0000000180)={0x0, 0x0, 0x0, 0x100000401})
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r1, 0x8, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x1000300010008, 0xffffffffffffffff})
setrlimit(0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000))
r2 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r2, 0x8, &(0x7f0000000000)={0x0, 0x0, 0xfffffffffdfffffd, 0x1000300010008})


sysctl$kern(&(0x7f0000000040)={0x1, 0x4d}, 0x2, &(0x7f0000000100)="bc66da1c", &(0x7f0000001100)=0x4, &(0x7f0000001140), 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f00000002c0)=[{0xb1}, {0x5}, {0x812e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])


kqueue()
r0 = socket(0x2, 0x4001, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x4, 0x0)
poll(&(0x7f0000000ac0)=[{0xffffffffffffff9c}], 0x20000000000000d7, 0x0)
ktrace(&(0x7f0000000100)='./file0\x00', 0x0, 0x0, 0x0)


mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x0)
r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
ioctl$FIONREAD(r0, 0x4004667f, &(0x7f0000000040))


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x2, 0x0)
setrlimit(0x8, &(0x7f0000000980))
dup(r0)


sysctl$hw(0x0, 0x0, &(0x7f00000004c0)="001f03989dd49060e8", 0x0, 0x0, 0x0)
r0 = socket(0x11, 0x3, 0x0)
recvmmsg(r0, &(0x7f0000000280)={0x0}, 0x10, 0x0, 0x0)
select(0x40, &(0x7f0000000040), &(0x7f0000000080)={0xff}, 0x0, 0x0)


munmap(&(0x7f0000ffb000/0x3000)=nil, 0xffffffffffffffff)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
ioctl$FIONREAD(r0, 0x80206916, &(0x7f00000001c0))


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r1, 0xc0384600, &(0x7f00000000c0)={&(0x7f0000000000)='./file0\x00', 0x4, 0x0})
socket(0x0, 0x0, 0x0)
sendto(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000000), 0x2cfea}], 0x1000000000000013)
mknod(0x0, 0x0, 0x0)
r2 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
ioctl$TIOCSETAF(r2, 0x802c7416, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x0, "247497496ed3ffa429fdb9102575e414229eb682"})
execve(0x0, 0x0, 0x0)
chown(0x0, 0x0, 0xffffffffffffffff)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x100000001})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x7fffffff, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xd, &(0x7f00000000c0)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


connect$unix(0xffffffffffffffff, 0x0, 0x0)
setitimer(0x0, &(0x7f0000000000)={{}, {0xffffffff}}, 0x0)
mknod(0x0, 0x100000000205f, 0x0)
syz_emit_ethernet(0x22, &(0x7f0000000080)={@local, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x1, 0x0, @remote={0xac, 0x14, 0x0}, @remote={0xac, 0x14, 0x0}}}}}})
dup2(0xffffffffffffffff, 0xffffffffffffffff)
utimensat(0xffffffffffffffff, 0x0, 0xfffffffffffffffe, 0x0)
mquery(&(0x7f0000ffb000/0x2000)=nil, 0x2000, 0x46eb37715ae71901, 0x0, 0xffffffffffffffff, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{}, 0x54, 0x0, 0x0, 0x0, 0x0, 0x1f})
accept$inet(0xffffffffffffff9c, &(0x7f0000000000), &(0x7f0000000040)=0xc)
getuid()
r0 = msgget$private(0x0, 0x0)
msgsnd(r0, &(0x7f0000000500)=ANY=[@ANYBLOB="000000000012000042fee18850"], 0x11, 0x800)
msgsnd(r0, &(0x7f00000006c0)=ANY=[@ANYBLOB="0300000000000000bc597b8a7110cfcfb630f8fce91c8815cdb3170494422f94d3ca7b7e6e85277277ed8b80324a3721ef9788207334532be3f0940418dfc357ad34a8ff249bd5640720a0ef96857717d47c739a7105b1f5e3f02c84cacb4f83921ee9801773dfb84f3afbcfacf7b467bf6b551d8e905c883ef3bb3011e829e5ddce4e243de033ed1ad495516771cab6167098bc69fe5984b6280e3fc97b2d624151901511c550e6d5d4ec5f930c0dcec4366ceb87"], 0xa9, 0x0)
msgrcv(r0, &(0x7f00000007c0), 0x90, 0x3, 0x0)


writev(0xffffffffffffffff, &(0x7f0000000440)=[{&(0x7f0000000180)="4dfb6b79951845e2cd9668618b36d93df01b8b7d45d0bc640ada53de1096c280bc3fe8a11c5aeea07cc0aca57612f97d4b101b5199f73cd5a5bb955d8f2ab8d018223f7b466cfec2b1a9fb56b65db7afa8570d748d", 0x55}], 0x1)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206916, &(0x7f00000001c0))


setrlimit(0x8, &(0x7f0000000980)={0x9, 0x100000001})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000040)={0x0, 0xffd, 0xfffffffe, 0xd2d, "8717f9050700000000000090d692480d51aa8000"})
writev(r0, &(0x7f0000000280)=[{&(0x7f0000000000)="f90b94074f9cfa606f36130794f73c16284d0d", 0x13}], 0x1)


semop(0x0, 0x0, 0x0)
r0 = open(0x0, 0x0, 0x0)
mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0, 0x10, r0, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x58}, 0x2, &(0x7f0000000140)="1139a509", 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80606948, 0x0)
socket$inet(0x2, 0x0, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x28, 0x0, 0x1}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})


r0 = socket(0x11, 0x3, 0x0)
connect$inet(r0, &(0x7f0000000040)={0x2, 0x3}, 0xc)
socket(0x2, 0x1, 0x0)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000001140), 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r1, 0xc2585601, &(0x7f0000001180)={0xdead4110, 0x0, [{&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffa000/0x2000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffa000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff9000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000ff9000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}], '.\x00'})
socket(0x18, 0x3, 0x0)
socket(0x1, 0x1, 0x0)
socket(0x2, 0x3, 0x0)
pipe(&(0x7f00000000c0)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(0xffffffffffffffff, 0xc010570d, &(0x7f0000000080)={0xa, &(0x7f0000000180)=[{0x7, 0x101, 0xf800, 0x8, 0x3}, {0xfff7, 0x3, 0xfff8, 0x2b6, 0x5}, {0x9, 0x101, 0xe904, 0x800, 0x800}, {0xd90, 0xff, 0xfff, 0x7fff, 0x2}, {0xfffa, 0x3ff, 0x9, 0x8, 0x8000}, {0x81, 0x2, 0x400, 0x7, 0xa6}, {0x8, 0x5, 0xfff9, 0x0, 0xfff}, {0x80, 0x4, 0xff00, 0x3f, 0x9}, {0xffff, 0x9, 0x8a97, 0x3f, 0x8001}, {0x44a0, 0xfff, 0x0, 0xb5af, 0x2}]})
poll(&(0x7f0000000000)=[{r2}], 0x1, 0x0)
dup2(r2, r3)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)='\x00', 0x1}], 0x1)
r4 = socket$inet(0x2, 0x2, 0x0)
socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0x8)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000100)=[{0x4}, {0x45}, {0x6}]})
syz_emit_ethernet(0x2a, &(0x7f00000001c0)=ANY=[])


r0 = semget$private(0x0, 0x1, 0x6c0)
semop(r0, &(0x7f0000000040)=[{0x0, 0x6, 0x1800}, {0x6, 0xc2}], 0x2)
semctl$SETALL(r0, 0x0, 0x9, &(0x7f0000000000)=[0x3ea9, 0x80, 0x7f, 0x400])
sysctl$kern(&(0x7f0000000180)={0x1, 0x9}, 0x2, 0x0, 0x0, &(0x7f0000000040), 0xc40)
r1 = socket(0x11, 0x3, 0x0)
sendto$unix(r1, &(0x7f0000000500)="94010503000000000000002797888fd1f838a311000000000000b13886ca3849451ae3c3051020741038f5538551f30ce390500e08fecea11ea8fef96e4fc748e93f0b780486aebdbe781e4d8f5eef9187a869a4d3a4cbba982fd825582fe223ed00f4c8b2ca3ebbc259699a1f132e27acb5d62934e4fd89070000000000000070c1f5a872c88dff7cc53c894303b2a0a85ff3faa800000000009ec7ab3a34c29000000000000000000000000000002d7e4a5d76cc3f9cff2ed2243e56fa277603c5cc1e047326bcf6b67b75d00bf6ee330b6a80874b70559d9975ebd13da2447a78aa4b00cd0ba1870215607bb912e3d7325183ce69456b4b6ca927871c81672a54ec695c5bdeb842836656f917945cc076f87dc714dfe0aa2947252df350707b22884a7730cb6dba8742110fbe9ec7481885274387e0b1dbe5695122604819b0b2294b7b20726a5d4fcb44f62d00fabb2f247a166d8d79d05b8cc370f5c11db58aedca632a83acd58ff0ea0a3dca58ccb03cce466cda735017196ff346c32717397d6ec6952ec90de81ed297b2509e130f0000", 0x194, 0x0, 0x0, 0x0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, &(0x7f0000000100)={0x0, 0x301d0bcd})


mknodat(0xffffffffffffff9c, &(0x7f0000000100)='./file0\x00', 0x1000, 0x0)
open$dir(&(0x7f0000000240)='./file0\x00', 0x0, 0x0)
unveil(0x0, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x1, 0x0)
ioctl$FIONREAD(r0, 0x8020697a, &(0x7f0000000100))


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000280)="b1000501600000000000000007000000331c13fecea10500fef96ecfc72fd3357ae320b37b673039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa5b236deb51e2f0ac3ebbc2576b9a5f139b672f4d335d223e7d026ba8af630037002102000000720fd38bfbb770c1f5a872c881ea6e69e0bb76d907c400000200361b1257aea8c500002002fb00000000008ad20300000000ec1d89e000040781e4b2fff040ff00"/177, 0xb1, 0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x4e, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x8000, 0x0)


r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
munmap(&(0x7f0000000000/0x3000)=nil, 0x3000)
ftruncate(r0, 0x101)
pwrite(r0, &(0x7f0000000140)='w', 0x1, 0x0)


bind(0xffffffffffffffff, 0x0, 0x0)
r0 = socket$inet(0x2, 0x3, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000000480)={@local, @local, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @broadcast, @broadcast}, @tcp={{0x0, 0x3, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})
shutdown(r0, 0x2)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
acct(0x0)
r1 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
ioctl$LIOCSFD(r1, 0x80046c7f, &(0x7f0000000140)=r0)
socket$unix(0x1, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
sysctl$vm(&(0x7f0000002e40)={0x2, 0xc}, 0x2, &(0x7f0000000000)="8d", 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000100)=[{0xc0}, {0x14}, {0x6, 0x0, 0x0, 0x88f0}]})
write(r2, &(0x7f0000000280)="ce4aa4a25043cb02aadf8701f131", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{0x50}, {0x60}, {0x836}]})
mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r1, 0xc0384600, &(0x7f00000000c0)={&(0x7f0000000000)='./file0\x00', 0x4, 0x0})


setrlimit(0x8, &(0x7f0000000100)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f00000000c0)={0x0, 0x0, 0x8a38, 0x0, "07160a009cef01098b748200"})
writev(r0, &(0x7f0000001540)=[{&(0x7f0000000240)="97571630bec18b555416f129d7b608c43a06c4ef2229c498832bbced5eb4fb063ad3a77d56d2ee9e137a2d561dc9c72a70ff3497d9f72e141130440033a8f69290257be1b61fed44ae3ed36dabe44b79b4a088b2db0ca7bb797c1ef0005c1f47c6fbf0a35e15e2909c59fd3f4d9db07bb4b7cbc7179bf40bc28ec0a8de4baf8b15cfed157b5480b77a25e6118492e6408b10da9c61076bfe3ff306821bf3d152d0669f1f9624f9b0a03ded49485042c70ba3d96788e1033aff23f1ce657f89fda0da2a4b9ac9352a684d88eefb50ec7221e14afee19f1895a44ece44bf12ca747ca7c7eef28727b22545ae31ceeccaedf37db14edb2043e084e8ef72c147ecb4781935aca2d7feb54a2f7804df2368c74aaea4727dc90b0ba03556726a06faae593316b15b8b9c32dd3e7931aa32a7711af8391998ea496d751f1546596d89e887040f3eaff7c57f274be559d5e2ea1107f61307cbad7868ab1a433d0917c341c4bf0dba800601a118d9566fac9ee2ead44b0f2644b6e1d145978b51b8480aa755864f7ca40ff7585c9519be7d3a8d644e731c3e706ff7d9f6fc0c32be260867a364008581bf86903823b27cb509288b39ef9286309c889c6e712792d47cf747315183b85c0ed0fbd2111c2622ffeced6f2321dd63fe25ee9051a6c23a7f682573669cd56024eeb14b0ec868646c944144a40ac8411148f232d63ba1e6e2f647d6033ef191672e125eaffac6fdc5dafc973861c2021225f175b7a2e05daa66f1f6134cc14051336145410ef641e903a3cfe1804b42b6f2a852235aa825bafcd8b914e6c4300efb5fd8baad2cc500d7ea481baf1e75567cf678f6d0687f546481681d27d1c85602cc7f9c431bf412dcfe4888ae30e4459e84ccd4c7b423a8a41dbd7bc965f93255f44b73eda91a80727aa68a1e2873d3240989a1954d6674cd1e89ca55d25d5db3a618c96ab7160a9fbc072b16dc91287bff0d5613b3d9d551ee862992f19b122c24f56cb1742f84f7acfffc189a545119928992bafb72d28b02bd5c399d32e3b69f1377622b5420bff3354e02fedccc222da55291e35c36bf65a8e4c3a0ec3ac2e92f1f1f83f228aa01eaaf6ac6d294a22e364f7e604686c27bd7c283fc8b373d8e3ffda59d30491c88d340122e6158e7d8af1486cd080c5e7f4a96cf73d2696918ee00552994efa7ef556b63c2e573ef8047c82c6e73b1b450037ec852f6730cc725f1fbaf8be81baf300d8fa49bd362a301d50fae22eec036325f3a0abb80777cc2450572e7cb1abf15f795624f43a0cb1361b94716a469fa7eb5c9cd2038534b546efb6b2f5085d4159dd1217fd5c65fc05c0774cfd94c647c15e697e293ca93d963c5c051bbc0253a954fd7a87ce372bc81bd69bd3a2b4d334e78bdaa4ba97627a35037350036da76d99aaa0c29bdac9c1fa921515c88635735d484bd625d5a5057ce46ed84c1f8543a6af33d74d7305b56b2f400ea70db536e68c7d5a28f743f5376a0603374329ff9a0e6fab026cddfe5bfe01d996f90ee6f1672524f0933e7787cea3a9d4ea323555e11851b5b9bef29a23b0c8b367ef2945cf52914864d30418f29334eae4c886540ca641b65817ec7d15859f2da11c37dcecff5ce34a8e50fcb509725918f17b2aa7cc0ae29caa01dee2a2ce4a3d3d3fcbbc5714ba27885c08e7e47ee8eb1162ed33e249c2fcc4124d77abf94d2eef23c6e997782a245fb0477fb86acd794ed2a45cbdc81189668a117e968f6d87da004fb480afd702fe5a92bd8e930b4d2d75177ec91ce553318bdf0b7ac031ebfa4ccabf808bfcfd57606d7bf2bf1198f8e6e1266ac39626ab0640ba81c3e734822e72c06066a99cc9c0ccbe279f79770d86b08bc18ee351907f94ee873", 0x53d}], 0x1)
r2 = dup2(r1, r0)
ioctl$TIOCSETA(r2, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x1, 0x7fc, "2cf9892af9a590e4cb52e88608007673ca9e5fd7"})
poll(&(0x7f0000000000)=[{r2, 0x40}], 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000980)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x2, &(0x7f0000000000)=[{0x20}, {0x16}]})
write(r0, &(0x7f0000000180)="7f23a3c23cce2575e1dd92c25683", 0xe)


r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000100), 0x1, 0x0)
ioctl$TIOCSPGRP(r0, 0x40047477, 0x0)


sysctl$net_inet_carp(&(0x7f0000000280)={0x4, 0x2, 0x6, 0x17}, 0x4, 0x0, 0x0, &(0x7f00000010c0), 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
socket(0x18, 0x2, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f00000000c0)=""/62, 0x3e}], 0x1)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1800000029"], 0x3e}, 0x0)
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)


sysctl$vfs_nfs(&(0x7f0000000000)={0xa, 0x2, 0x1}, 0x3, 0x0, 0x0, 0x0, 0x0)
sysctl$hw(&(0x7f0000000000)={0x4, 0x1f}, 0x3, 0x0, 0x0, 0x0, 0x2)
mprotect(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x1)
sysctl$vfs_nfs(&(0x7f0000000000), 0x3, &(0x7f00000025c0), 0x0, 0x0, 0x0)


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000540)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xf}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
msync(&(0x7f0000ffa000/0x4000)=nil, 0x4000, 0x6)


sysctl$net_inet_carp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
pipe(&(0x7f0000000140)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
poll(&(0x7f0000000040)=[{r2, 0x1a4}], 0x1, 0x0)
fcntl$setstatus(r1, 0x4, 0x0)
write(0xffffffffffffffff, &(0x7f00000002c0)="7c84cf179279b50eda5dd1951a661d2e3a20851082c188f8b3d8a063d2025ff0d27a44bc29bdcac27fcb7aaa95cb2007be22c5553cd2f66a1f419a83d4275218a89d7a7803f069d851ff628dd309c40f6e3c932af00cb6219ae6e21d2c28d492cd5404b16dfa627d93b1e8ad2ea49d2344c1a3b234bd6f1c70fd4252844a6e6ab7b8997bc55fa22ce951ee038d289078b95510b0f2473ce1348434f0ec4a885ee84fd08fc50f08ca7991af3f8c322b496466f804c4b700cc9391855bd0ee339196de2b5ec2d8425c711d3f9e051eb055d45c693d7549712f5284a9fbca7d15c5bf1a9c8e3b3c1a43983056782e046c29e3d57082f7743b8bf6d994cd3c26c85609eaa11e6f7bc4", 0xfffffdaf)
execve(0x0, 0x0, 0x0)
sysctl$hw(&(0x7f0000000bc0)={0x6, 0x6}, 0x2, &(0x7f0000000c00)="ce55e9e3", &(0x7f0000000cc0)=0x4, &(0x7f0000000d00), 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f00000000c0)=[{0x54}, {0x1}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])
r3 = socket(0x11, 0x3, 0x0)
setsockopt(r3, 0x11, 0x3, &(0x7f0000000340)="02000000", 0x4)
r4 = socket(0x11, 0x3, 0x0)
sendto$unix(r4, &(0x7f0000000000)="b10005016000009f05000000070000007d9113fecea10500fef96ecfc72fd3357a068da3a5673039d2d236acf20b7804be38164991f7cccf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f45335c223e7d026ba8af630037282118000000720fd38bfbb770c1f5a872c881e2772ec5a10400000000000000361b1257aea8c5d0002012fbff0c230000880d6633c556ae9be371a3f8343712051eeab71d89000407000000800420000000", 0xb1, 0x0, 0x0, 0x0)


mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x412dff)
mknod(&(0x7f0000000300)='./file0\x00', 0x0, 0x6da)
r0 = kqueue()
kevent(r0, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r1, 0x80206982, &(0x7f00000001c0))
socket(0x0, 0x2, 0x0)
socket(0x2, 0x0, 0x0)
r2 = open(&(0x7f0000000080)='./file0\x00', 0x70e, 0x0)
mmap(&(0x7f000000f000/0x2000)=nil, 0x2000, 0x0, 0x10, r2, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
r3 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
writev(r3, &(0x7f0000000080)=[{&(0x7f0000002540)="19af1c0c1e5eb664227eebc46add329414c4d8e18e2b0884bed6b78e0b1ef6c5df9323bc41e735352e310cada713bb31d5975394e7e1d5eae70b6d1e71ef0748fd597d6a55491b43fd42", 0x4a}], 0x1)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80606941, &(0x7f00000001c0))


sysctl$net_inet_carp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x1}, 0x4, 0x0, 0x0, &(0x7f0000000000)="00028300", 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000000c0)=[{0x3d}, {0x3}, {0x8006}]})
syz_emit_ethernet(0x138, &(0x7f00000002c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x24}, {0x6c}, {0x6}]})
syz_emit_ethernet(0x6e, &(0x7f0000000000)=ANY=[])


setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0xee00, r0)
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x1000000029, 0x36, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)


mknod(&(0x7f0000000040)='./bus\x00', 0x6000, 0x2802)
r0 = socket(0x11, 0x3, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000080), 0x0)
setsockopt$inet_opts(r1, 0x0, 0xd, &(0x7f0000000240), 0x0)
recvmmsg(r1, 0x0, 0x0, 0x1, &(0x7f0000000380)={0x9})
ktrace(&(0x7f0000000100)='./bus\x00', 0x1, 0x4000010e, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000080), 0x0)
r2 = socket$inet6(0x18, 0x2, 0x0)
recvmmsg(r2, &(0x7f00000002c0)={0x0, 0xfffffffe}, 0x10, 0x0, 0x0)
recvmmsg(r2, &(0x7f0000000300)={0x0}, 0x10, 0x2, 0x0)
r3 = dup2(r0, r2)
r4 = socket(0x11, 0x3, 0x0)
setsockopt(r3, 0x10, 0x39, 0x0, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x0, &(0x7f0000000140)="c2969223a7fa593766989f2f1cc188b254b3efea7f38ed59d3aed2eb973f2604496d55", 0x23)
stat(&(0x7f0000000080)='./bus\x00', &(0x7f0000000280))
r5 = socket$inet(0x2, 0x0, 0x0)
setsockopt$inet_opts(r5, 0x0, 0x200000000000a, &(0x7f0000000040)='\x00', 0x1)
setsockopt$inet_opts(r5, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00100001000000", 0x8)
connect$unix(r0, &(0x7f00000000c0)=@file={0x1, './file0\x00'}, 0xa)
recvmmsg(r4, &(0x7f00000001c0)={&(0x7f0000000200)={&(0x7f0000000180)=@in, 0xc, &(0x7f0000000340)=[{&(0x7f00000003c0)=""/74, 0x4a}, {&(0x7f0000000440)=""/203, 0xcb}, {&(0x7f0000000540)=""/208, 0xd0}], 0x3, &(0x7f0000000780)=""/193, 0xc1}, 0x401}, 0x10, 0x1002, &(0x7f0000000880)={0x80000000, 0x8})
r6 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x1, 0x10, r6, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
socket(0x0, 0x0, 0x0)
r1 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000180), 0x1, 0x0)
r2 = dup2(r1, r1)
ioctl$WSKBDIO_GETMAP(r2, 0x40047477, 0x0)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{}, {0x7}, {0xffff, 0xfd}]})
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000513fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38", 0x23, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r3 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r3, 0x8080691a, &(0x7f0000000100))
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r4, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x80}, {0x50}, {0x6, 0x5}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
mprotect(&(0x7f0000000000/0x1000)=nil, 0x1000, 0x4)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
select(0x0, 0x0, 0x0, 0x0, &(0x7f0000000280))


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x3}})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$VMM_IOC_INFO(r0, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})


sysctl$kern(&(0x7f0000000000)={0x1, 0x55}, 0x3, 0x0, 0x0, &(0x7f0000001300), 0x0)
r0 = getpid()
ioctl$WSDISPLAYIO_GETEMULTYPE(0xffffffffffffff9c, 0xc014575e, &(0x7f0000000040)={0x5, './file0\x00'})
fcntl$setown(0xffffffffffffffff, 0x6, r0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
r1 = getpid()
setpgid(0x0, 0x0)
pipe(0x0)
fcntl$setown(0xffffffffffffffff, 0x6, r1)
r2 = semget$private(0x0, 0x4000000009, 0x82)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000400)={0x2, &(0x7f0000000080)=[{0xed1, 0x41, 0x6, 0x80}, {0x3}]})
r3 = openat$zero(0xffffffffffffff9c, &(0x7f0000000180), 0x800, 0x0)
close(r3)
flock(r3, 0x0)
semop(r2, &(0x7f0000000300)=[{0x0, 0x6, 0x800}, {0x4, 0x22}, {0x1, 0x0, 0x800}, {0x2, 0x1}, {0x2, 0x0, 0x1000}, {0x4, 0xfc0a}, {0x3}, {0x3, 0x5}, {0x4, 0xfff7, 0x800}, {0x3, 0x46a, 0x1800}, {0x2, 0x1}], 0xb)
semctl$SETALL(r2, 0x0, 0x9, &(0x7f00000001c0)=[0x0])
getegid()
madvise(&(0x7f0000000000/0x4000)=nil, 0x100000000000000, 0x0)
semctl$SETALL(0x0, 0x0, 0x9, &(0x7f0000000200)=[0x1, 0x4, 0x2])
semctl$IPC_RMID(r2, 0x0, 0x0)
kqueue()
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000000)={0x0, 0x4, 0xffffff9a, 0x0, "c07b00"})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)


pipe(&(0x7f0000000040)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
r1 = fcntl$dupfd(r0, 0x3, 0xffffffffffffffff)
write(r1, &(0x7f0000000080), 0x39)


open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
open(0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
semget(0x0, 0x0, 0x0)


r0 = socket(0x1e, 0x3, 0x0)
write(r0, &(0x7f0000000300)="e4810f8cd9dc5fdf21a9ebd49db0eef161e6e74a860fc6adb0015e68089047cee54f05322c35a5d2c7a5a19be3eceac6c443b0605cb9e0f4225065abaed302138a6375d5a0272ba6731329c9e0f02a615d91dd492fbfb97c2ea73a7538c82a94e51c371c37f2def9f87e93962597a22f2728344297d3fac981ca5993dcd0b39fd9e0cff3b9b20f8c1d2b94728f29ada308", 0x91)


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r1 = fcntl$dupfd(r0, 0x3, 0xffffffffffffffff)
ioctl$FIONREAD(r1, 0x400c745c, &(0x7f0000000080))


r0 = socket(0x1e, 0x3, 0x0)
write(r0, 0x0, 0x9000)


sysctl$net_inet_carp(&(0x7f0000000100)={0x4, 0x3}, 0x4, &(0x7f0000000140), 0x0, 0x0, 0x0)


r0 = openat$pf(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
close(r0)
recvmmsg(r0, &(0x7f0000000ac0)={0x0}, 0x10, 0x0, 0x0)


open(&(0x7f0000000200)='./file0\x00', 0x200, 0x0)
r0 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x8, &(0x7f0000000140)={0x0, 0x2, 0xffffffffffffffff, 0x2000269000001})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000280)=[{0x3}, {0x5}, {0x3efe}]})
syz_emit_ethernet(0x36, &(0x7f0000000000)=ANY=[])


mknod(&(0x7f0000000500)='./file0\x00', 0x1000, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000001c0)=[{}, {}, {0x6}]})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x2, 0x0)
r1 = dup2(r0, r0)
ioctl$FIONREAD(r1, 0x8020699d, &(0x7f00000001c0))


syz_emit_ethernet(0x3e, &(0x7f0000002fc0)={@broadcast, @random="d28be5230b24", [], {@ipv4={0x800, {{0x7, 0x4, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @remote={0xac, 0x14, 0x0}, {[@ra={0x94, 0x6}, @generic={0x7, 0x2}]}}, @icmp=@timestamp}}}})


shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)


r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r1 = getpid()
ktrace(&(0x7f00000002c0)='./file0\x00', 0x0, 0x40001220, r1)
ftruncate(r0, 0x5)
clock_gettime(0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000004c0)=[{0x2c}, {0x3d}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


r0 = socket$inet(0x2, 0x3, 0x0)
close(0xffffffffffffffff)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000300)={0x3, &(0x7f0000000100)=[{0x25}, {}, {0x106}]})
syz_emit_ethernet(0x3e, 0x0)
ioctl$BIOCVERSION(0xffffffffffffffff, 0x40044271, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x42}, 0x6, 0x0, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
shmctl$IPC_SET(0x0, 0x1, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r2, 0x8020699f, &(0x7f0000000100))
sysctl$kern(&(0x7f0000000040)={0x1, 0x4e}, 0x3, 0x0, 0x0, &(0x7f0000000180)="76b0353a558bf248c78c8502fcf9fd08fa1588f254df98bdc2703864ecc0ce3671c0907259201eb7cb962ee12d9706a2d4177565da48e3cdade50516597f477ca5ea18253c1441678346ddaa98e46b28e2226a296c0fd773959eaad9d65d33cdbf523a06ed457ed3e00f52851f90c14f54ec03a2a5ff8d88b9", 0x79)
getsockopt$inet_opts(r0, 0x0, 0xc, 0x0, 0x0)
openat$wsdisplay(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
openat$wsdisplay(0xffffffffffffff9c, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x3, 0x0, 0x28, 0x0, 0x1}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
writev(r0, &(0x7f0000000140)=[{&(0x7f0000003380)="c0d6", 0x2}, {&(0x7f00000001c0)='4', 0x1}, {&(0x7f0000002280)="d93e4f5489f0f797174e7441646f7a28c6a59939bfafa1ce93defc3efeb099e8e1fe0fa3cab7a175cbaf99528be73bc24807f33bfd4b8007742888944b9fad8b5c7e86eaa1f84104772cff8ab994880e09e0cb6ec829760ed795a61ea33c65dc9d870b82a9c762f99e43a107e62daed6473fd6eb4e2730524faf4482f00b418e710bd4f540e7602c9291c914495ffda2284da440e0a375fcaeca4cfc4c5e34b97056aaf96d72d6856f4115614b10c149d1d853674582e24aaa8a41780c09ec1a40b76d15663a5a7aa2d6b5bccd", 0xcd}], 0x3)
r1 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r1, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)


symlink(&(0x7f0000000900)='.\x00', &(0x7f0000000240)='./file0\x00')
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
mkdir(&(0x7f0000000000)='./file0\x00', 0x180)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
chdir(&(0x7f0000000240)='./file0\x00')
setreuid(0x0, 0xee01)
mkdir(&(0x7f0000000100)='./file0\x00', 0x184)
rename(&(0x7f0000000340)='./file0\x00', &(0x7f0000000380)='./file1\x00')
rename(&(0x7f0000000080)='./file1\x00', &(0x7f0000000540)='./file0\x00')
r0 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmat(r0, &(0x7f0000002000/0x4000)=nil, 0x1000)
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x200, 0x0)
ioctl$WSDISPLAYIO_ADDSCREEN(r1, 0x80245753, &(0x7f00000000c0)={0x0, './file0\x00', './file0\x00'})
r2 = semget$private(0x0, 0x1, 0x300)
semctl$GETZCNT(r2, 0x4, 0x7, &(0x7f00000003c0)=""/69)
getgid()
semctl$IPC_SET(r2, 0x0, 0x1, &(0x7f0000000600)={{0xff}, 0x40000000000008, 0x96, 0x3})
shmget$private(0x0, 0x1000, 0x464, &(0x7f0000002000/0x1000)=nil)
ioctl$FIONREAD(r1, 0x4004667f, &(0x7f0000000140))
socket(0x2, 0x5, 0x0)
semctl$GETVAL(r2, 0x0, 0x5, &(0x7f0000000440)=""/206)


setreuid(0x0, 0xee01)
socket(0x18, 0x1, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000040)=[{}, {}, {0x3, 0x0, 0x0, 0x2}]})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000007, 0x0, 0x0, 0x0, 0x0)
r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
dup2(r1, r0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000a, &(0x7f0000000000)="ea00005c00000000", 0x1)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f00000003c0)="ea00000100000000", 0x8)
setsockopt$inet_opts(r0, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0x8)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000006c0), 0x1, 0x0)
writev(r0, &(0x7f0000000400)=[{&(0x7f0000000000)="daf674ad8d4f7caa1b2e65dfbfc13507f699b9a9939557bbf6f71f5b83b03889c629d9687773c058553b80e5e3d1400ba456feff7778c6d082d1daab73ee6c329b0540aa59f1946870cf710fddfa2d1418c4473447365a04aff63a1346abbdd3cff847517d39209bcdfc86cd3dc6de69201bd0c823ec5973a8acd685d3f7c24f2e6ba4c0239aa86e372e", 0x8a}], 0x1)
execve(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000001380)=[{0x40}, {0x24}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])


r0 = socket(0x18, 0x3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
ioctl$FIONREAD(r0, 0xc02069a0, &(0x7f0000000100))


socket(0x11, 0x3, 0x0)
r0 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = kqueue()
kevent(r2, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
ioctl$FIONREAD(r0, 0xc020691b, &(0x7f0000000200))


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f00000000c0)='./file0\x00', 0x21e)
chdir(&(0x7f0000000140)='./file0\x00')
mkdir(&(0x7f0000000280)='./file1\x00', 0x0)
setreuid(0x0, 0xee01)
unveil(&(0x7f0000000080)='./file1\x00', &(0x7f00000001c0)='x\x00')
rmdir(&(0x7f0000000040)='./file1\x00')


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000100)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000140)=0xc)
setregid(0x0, r1)
setegid(0x0)


sysctl$kern(&(0x7f00000000c0)={0x1, 0x33}, 0x4, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x1, &(0x7f0000000000)=[{0x0, 0x1, 0x6, 0x7ff}]})
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x100, 0x0)
ioctl$BIOCGSTATS(r0, 0x4008426f, &(0x7f00000000c0))
r1 = openat$wsdisplay(0xffffffffffffff9c, &(0x7f0000000100), 0x8820, 0x0)
ioctl$WSKBDIO_SETMAP(r1, 0x8010570e, &(0x7f00000001c0)={0x9, &(0x7f0000000140)=[{0xc, 0x8, 0xffff, 0x3, 0x2}, {0x2, 0x9, 0x3, 0xf87, 0x9}, {0x0, 0x8001, 0x8, 0xbc, 0x1}, {0x6, 0x0, 0x1, 0x1, 0x80}, {0xa49e, 0x4, 0x0, 0x7e5e}, {0x8, 0xfffb, 0xffff, 0xe5b, 0x1}, {0x8, 0x4d, 0xfff9, 0x3, 0x9}, {0x9, 0x6c7, 0x1, 0x5, 0x2}, {0x6, 0x4}]})
open$dir(&(0x7f0000000200)='./file0\x00', 0x800, 0x31)
r2 = openat$pf(0xffffffffffffff9c, &(0x7f0000000240), 0x40, 0x0)
mquery(&(0x7f0000ffe000/0x1000)=nil, 0x1000, 0x2, 0x10, r2, 0x0)
ioctl$WSDISPLAYIO_SMODE(r2, 0x8004574c, 0x0)
r3 = socket(0x2, 0x1, 0xb8)
mkdir(&(0x7f00000002c0)='./file0\x00', 0x190)
sysctl$hw(&(0x7f0000000300)={0x6, 0xa}, 0x2, &(0x7f0000000340)="f6f514eaed6a9007beddc07905152a383e69ab9a1eebb26e5fbcfa840d886ae615cd9b8f22927606505eb3b06e25", &(0x7f0000000380)=0x2e, &(0x7f00000003c0)="c5e85c1b37dde77be105ba92ebc317fcc5df4be3c444cfbd565ea0f23c4f9780f2adecee2e08b5db2f07eaf6ebbcc3707524f9077a8f1da4194db7a51d40df01b0f18672d07ae6dec8758936e087fca66cd98599b0cb43e1c09037774b08568ee9a54f8b8ea5ad56bb9de9f45865168cb9a7cb3c97a94317ceb8ea8928971595c584b671a963b06e7f6fb0", 0x8b)
r4 = openat$zero(0xffffffffffffff9c, &(0x7f0000000480), 0x18200, 0x0)
ioctl$WSKBDIO_GETMAP(r4, 0xc010570d, &(0x7f0000000500)={0x3, &(0x7f00000004c0)=[{0x1b0, 0xfff7, 0x0, 0x8000, 0x7fff}, {0x3f, 0x8, 0x2, 0x920d}, {0x101, 0x6, 0x5, 0x2, 0x4}]})
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000540))
r5 = semget$private(0x0, 0x2, 0x532)
getsockopt$sock_cred(r3, 0xffff, 0x1022, &(0x7f0000000580)={0x0, <r6=>0x0}, &(0x7f00000005c0)=0xc)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000600)={0x0, <r7=>0x0}, &(0x7f0000000640)=0xc)
getsockopt$SO_PEERCRED(r4, 0xffff, 0x1022, &(0x7f0000000680)={0x0, 0x0, <r8=>0x0}, 0xc)
semctl$IPC_SET(r5, 0x0, 0x1, &(0x7f00000006c0)={{0x5, r6, 0xffffffffffffffff, r7, r8, 0x120, 0x81}, 0x7fffffffffffffff, 0x3})
semctl$GETPID(r5, 0x4, 0x4, &(0x7f0000000740)=""/4096)
r9 = socket$inet6(0x18, 0x3, 0x7)
setsockopt$sock_int(r9, 0xffff, 0x100, &(0x7f0000001740)=0x8, 0x4)
ioctl$WSDISPLAYIO_SMODE(r1, 0x8004574c, &(0x7f0000001780)=0x2)
setsockopt$sock_linger(r2, 0xffff, 0x80, &(0x7f00000017c0)={0x40, 0x101}, 0x8)
r10 = openat$bpf(0xffffffffffffff9c, &(0x7f0000001800), 0x0, 0x0)
ioctl$BIOCGDIRFILT(r10, 0x4004427c, &(0x7f0000001840))
r11 = socket(0x2, 0x5, 0x40)
listen(r11, 0x100)
setsockopt(r11, 0x4, 0x2, &(0x7f0000001880)="df961fa2e429d423c87755f5e86dbd67b2d51bfd8b9ca5f780bfe260791ae91a99df29c0f329b7ffca12fee541c47c210c9f7ad6e2a553d387fc8b117c62", 0x3e)


sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0xffffffffffffffff}})
r0 = geteuid()
chown(&(0x7f0000000340)='./file0\x00', r0, 0xffffffffffffffff)
r1 = getegid()
r2 = socket$inet(0x2, 0x3, 0xff)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000540), 0x8000, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r4, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000100)=[{0x5c}, {0x25, 0x0, 0x0, 0x4}, {0x6, 0x0, 0x0, 0xfffffffd}]})
writev(r4, &(0x7f0000000140)=[{&(0x7f0000000080)="35b5c242413c1026089a59583cc3", 0xe}], 0x1)
r5 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000580), 0x800, 0x0)
r6 = accept$inet6(0xffffffffffffffff, &(0x7f00000005c0), &(0x7f0000000600)=0xc)
r7 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40001928, r7)
ktrace(0x0, 0xa5f3b150e570ff1d, 0x11c, r7)
r8 = getuid()
setreuid(0x0, r8)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000640), 0xc)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000740)={&(0x7f0000000140)=@file={0x0, './file0\x00'}, 0xa, &(0x7f0000000180)=[{&(0x7f0000000200)="eca04f101fd653ea6f747a43aec52b65a0652855d76a63e56344cb27503e6c69ac1b52ede09e649d9f7f045b39e284c2c0818b100ed8581e5b9b0795e416e627028d30ce39c876401c5a9651f42fcc593bda3d0eb278aadef1f6fe4221a84a2fad46f32b83e74f36a5fdefd9d3f0b59417098a111b2cd585c4dd29f0489d9cf98b3d7a338660a1dbd0c4ca8bf063c0f34c2b9479351707499ff2f052378f76ccead97742507a37289bfa", 0xaa}, {&(0x7f0000000300)="43d171e50d052ee0a33f7087e5e978e226b2b048140e75ea36a8c122307a8c00c51fdb42066eac844d4cadb7e4b8654ee86a418d980b5cfbd12ec8c1805f99f9711247bd674c575f6a1e036986f3c932a76dcadebe21c44fe0a986d2add1b70e27100933f9c708e209a554b73fdd2aea84cf391eb7e4c501cd6d1fe1c837421266048106b068159671a333443040205061df0085a24a5c59086a4b45069ca7112f1af3f246a7dfa56f", 0xa9}, {&(0x7f00000003c0)="c1ca9bd2119232edc6b75110a82dfc01b3f9e809700398177b1c365d18ee362db7b2a0520175a9d5009e076773ec856a37e69700f0307e520b96c7b70e6415b8a6b419c3a85ed5ef7cb7d07493e8adf55e4bd8", 0x53}, {&(0x7f0000000440)="13936c9ee7e0c239289315ec0c256f611df5a08c2ca1de75fefb2309c751007c1d15371b46b50f1fec8083414485e8bb3200719ab0ff7d3515a20053fad35d1c308304e8e8588feb7cc5c3236156c5cf60e70e6a8b575f4d28c4e12c3be782cc60b6b1fca074f198bef49dacc680bfc01f5a8309e2e88a68aa4640a395cf876f6c96a28463e955b6cd28781a779e1584a578bbba498305fe883b100f61c4eb785b0e7950a4c08d3d6a8ef5b8fa61ebda06944257c6b6f9590096ce047961fd773397151b8ebc738d9140ccda4a2676d9b0b36a68fcd5", 0xd6}], 0x4, &(0x7f0000000680)=[@cred={0x20}, @cred={0x20, 0xffff, 0x0, 0x0, r0, r1}, @rights={0x28, 0xffff, 0x1, [r2, r3, r4, r5, r6, 0xffffffffffffff9c]}, @cred={0x20, 0xffff, 0x0, r7, r8}], 0x88, 0x6}, 0x6)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r9 = socket(0x18, 0x3, 0x0)
connect$unix(r9, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r9, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
r10 = socket(0x18, 0x2, 0x0)
r11 = socket(0x18, 0x2, 0x0)
connect$unix(r10, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
dup2(r10, r11)
sendmsg(r11, &(0x7f00000002c0)={0x0, 0x0, &(0x7f00000001c0)=[{&(0x7f0000000080)="8a07fc059328491804424a11b2fa028d6cdea11cc55e5eea3e712fd225f505867123b7f479d6809197b7abb245a6a90d101904863d6e9a", 0x37}, {&(0x7f0000000180)}, {&(0x7f0000001300)="349409068a157a5d1cd1898fdd78cf8ebee5129ab0adf53061d63d4e70ae40ab544d00f5ca6775ae4f9c1076db79108ccedc8e3783e2a86cfc619429c6ab373acab96b35e818ce5154edd20e074dbe033ba9c2af6527497f77063821ec83053996276228d6d5dbc7c13718ca1113bea34ab01fc2932518b5cf93c3a051aade6f26347a74540c310eceaf2304da2d4c37d7b6d0666a67ea50ecf1d2fb7336a52f08695592437406e2ad9d4c9ffbd260dce6a9eff53832111728a7b100fe85beeae0825a2adc97dc1d3eee31d6e482e19f50d8f03b7e92621c09de112e7663521ecb604ad3c5f7902647371e116514953405a10bc3bc5a010d9eacb8f4ede38de585066aaa8ee9dd4886ca2cad43144bd0f3c0809f05382fe0b1b018cd0a1bc3b61c0dadfbc11e7939b47897df90a75084cd4fe203623abc7bd607a2ebc5e8ff0a933cb3498567a9a2941a063d86e263090c95ef9faf103139fa509fd5c76a0652b1e2234816e854812ccac047dad28403551275abee2de74a226ffd6dadbf7b5f550c7f46fab2e11be5af4fc7bbfcbe42885f9d90ebf01523a97dc84416bb4cb755cb7d3268ca6242aa1e0c8bee4bc0efd34a28485acf30427cda6125bd71de4b53a615105e19bab53514e8b1c6f59461cb0c3b4cbb0eb88d3da0534d20a665096e396278f7d4e0789588f420df9b7025f9dec8d2f4deab15687d69a056537b44723c2c12bfc1ed2a57b6b1fa3fff9587e81272484babaf3ca670099edc163a40d67931a457fab205604347d078bc6069602a1ec600475be8d3e0beb8e2528a5bb3d937ff37000c487f7d14f5b8689bc77566719be278e2bf3a293417498c34989d159b7ab42a6d4e0a83df7d4e96f8c537c47cd3f50c19b5576a1830f51b7dd8505607401263dc37e733e5d9e6be4c4a3ce3430228a21ede7d7ad81572f33688fcf39585a9b94169107b8cd092d5bf8861177be35ab14ada48e240f90ff38556173573fe1e3697f27a94a472397b1528fc7269a83576ce8a49f9b4395ba565bb9645818f58ec1d863c61a52d7a6dde3cbf3ea0ccdfe225cd696783685784ca798e4f700c47fbc159b2b41c6573b63061ee61326545d0d815d209b6b07ffde9750a423d4ee028c8ed2ad847ed21bdb58a19c6b4af36b916bbe47272bd33cbdb2bcaaafde3be906ea31ff2f123cc77868ffcbe9cf359390daaf4377101d8454e20cddf100084c0c0688a67d6772c945d27581eb4a1b2e40b1ffe2351ea98114d14d2e4bf3df16e45ce2def4aa9d845a04a27325a697acedfb23e891eabc1e6c8df87f02dc96ad245b3f884b75ff7d6fc421eeb924595daf33bbab051533a9927706a845f92cbae3277a4092a1acc93f7db688de0622c0680b96178015232b5db6a347bb8635b1792b43998c0703519e7ed1a34d66c806e10c70405a6bbe9c62433083d7108974224d0eb76f271b317749ec4b797cadc773d3d3314d9dad7510283080372917e00860d29baba7ca6145fb582468ef85d98b5068d7d25679386c723c47b3fac841731ab44d8935159a4f0d40a937df2c26aa6d6208992487648bcf8cc29d05cb447636561a532b0006ecd363340285cab33fc67d99305b38e66d533a089c20c9c64e96c6246f3c9a6f97bad3ef1abc0854d5619aeeba72cfb62a053245e32916987175e2f527ed6145dad3d46f98b10414c9180dc2c9b01eb2b6e9a58b96547700329febf9a2d9fe9325e5e35e758559ee4648ae2bd392036496b473270cdf3c6083d67ed4752e8107fff174d787ee1067af50f2e12ad33636ca1e3e1b0b98026c1d7214390d53990a84e864b8320cbb9e21d6db32b700265386e8bd338b6b601736ab8d1d8871356ec79fef672aba8074d8acf07def315220bcff5fb03d5e7e57b1ff26732ab9fd571c2876265481f8eaae49b13c840ead6231e7f237a9fc4ed83c3588a3dee05fea7aaaa5aff8e152c8d5c356e1756b2aeeae4d778718f08847421263f2080267144f1eefa5539f8c5b320cddfd4042795822545583bd56951f3f0760b9f0f74a481f29d11c1518bca77320b96a154571c627d7b1d57f910d002b51be7b2a4c7964953c6b80d5b182b7b2227211084c6b036473143f5244ac3e3b392792c661166d694927a8cd948c2a5bb7bf10cf314cfd85f86077b41e9b34c2dee93e671a50a5fafbfcf73f64f5a1afc92d194e310d3b819b90bab16ec7aec59c176dd463c955c14d718b49ae2bc812dcc30d32ab9c83156ae7aafd507bf9901c367c84e292f0af9ea29d2705655f54223f80eee9466faa5cbc4d46ddf62b37acf12063af4024ac1e336bb457b3c2bc0f66c6418c657012bb3aecc900c16b39b86f02894fcc60da0661d0669eda1397aaea4658813ad3868b6693a02be0ff75f64a672255dcc85562fd9d52d97d3f7c911ff9de786bd607abfc6e21d06d22edc93b1c95155c5e998b1bc45b3a544cd698eaeec65322d6b7df4507b19f77d15e8856d15da2abf2be48523eeb5a9971afc617e215861740629b9f0ac1e42d0d904ebcd70e207717c16a57f938b823644cc091a2fe85dd066538318bc2cff34cd4231164ea06300b4d1de763b7eb0fe7c8600a44647e6a760eaf9e91a1482bc3a39c749a426f990db81b5a930d614fbb295d1edda9be352961685b4cd477f3db580f04ee59f27c27f212efb82089f2d71d6951bec7146efa7e392cff3776eb2d10021255a749859a082a265e43eb60896029b6af3ee4e68c02ce2e150045d856fbfca1bb1599169f492722de75dfb81ea0579a9789a1b1a964f534feea3e62d670bd4be55f84a932f644aab077bff3fa9c110224b4e381965f4", 0x7df}], 0x3, 0x0}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000100)=[{0x48}, {0x3}, {0x6, 0x0, 0x0, 0x5}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x2, &(0x7f0000000040)=[{}, {0x1}]})
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0x2, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0x4)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd02)
r0 = open(&(0x7f0000000240)='./bus\x00', 0x0, 0x0)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x80, 0x0)
ioctl$VMM_IOC_RUN(r1, 0xc2485607, &(0x7f0000000300)={0x2, 0x0, 0x0, 0x0, 0x0})
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r2=>0xffffffffffffffff})
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000280), &(0x7f0000000340)=0xc)
open$dir(0x0, 0x0, 0x0)
socket(0x2, 0x1, 0x81)
setreuid(0xee00, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x50}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x10, 0x0, 0x37)
r3 = msgget$private(0x0, 0xfffffffffffffffd)
msgsnd(r3, 0x0, 0x0, 0x0)
msgrcv(r3, &(0x7f0000000140)={0x0, ""/204}, 0xd4, 0x0, 0x0)
syz_emit_ethernet(0x1b, &(0x7f0000000000)=ANY=[@ANYBLOB="fffd640000000000000000000a"])
pread(r0, &(0x7f0000000040)="3cd15db7c30016", 0x50cc00, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x2, &(0x7f0000000080)=[{0x145, 0x0, 0x8}, {}]})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{}, {0x84}, {0x6}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
r1 = socket(0x2, 0x2, 0x0)
socket$inet(0x2, 0x0, 0x0)
ioctl$FIOASYNC(r0, 0x8004667d, &(0x7f0000000000)=0x7)
dup2(r1, r0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000180)={0x3, &(0x7f0000000000)=[{0x4d}, {0x48}, {0x6, 0x0, 0x0, 0x480000}]})
write(r0, &(0x7f0000000400)="76e5dead6f01f8407d2100000063", 0xe)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080)=@file={0x0, '\x00'}, 0x3, 0x0}, 0x0)
r0 = socket(0x18, 0x2, 0x0)
getsockname$inet(r0, &(0x7f0000000080), &(0x7f0000000000)=0xfffffffffffffe22)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x3, 0x0)
sendmsg$unix(r1, &(0x7f0000001700)={0x0, 0x0, 0x0, 0x0, 0x0, 0xfffffffffffffe4c}, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg$unix(r1, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="28000000ffff000001"], 0x28}, 0x0)
setrlimit(0x8, &(0x7f0000000980))
recvmmsg(r0, &(0x7f0000000000)={&(0x7f0000000000)={0x0, 0x0, &(0x7f0000000000), 0x0, &(0x7f0000000000), 0x63}}, 0x10, 0x0, 0x0)


syz_open_pts()
poll(&(0x7f0000000200)=[{}], 0x1, 0x87e)
r0 = open(&(0x7f0000001440)='./file0\x00', 0x615, 0x0)
poll(&(0x7f0000000000)=[{}], 0x1, 0x8001)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x10, r0, 0x0)
ftruncate(r0, 0x25b3)
execve(0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
write(0xffffffffffffffff, &(0x7f0000000100), 0x0)
ioctl$TIOCSETD(0xffffffffffffffff, 0x8004741b, 0x0)
close(0xffffffffffffffff)
open(0x0, 0x0, 0x0)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2006, 0x4f4b)
r0 = open$dir(&(0x7f0000000200)='./bus\x00', 0x0, 0x0)
ioctl$FIOASYNC(r0, 0x8004667d, &(0x7f0000000280))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000180)={0x3, &(0x7f0000000000)=[{0x4d}, {0x44}, {0x6, 0x0, 0x0, 0x480000}]})
write(r0, &(0x7f0000000400)="76e5dead6f01f8407d2100000063", 0xe)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000000100)={&(0x7f0000000080)=@file={0x0, './file1\x00'}, 0xa, 0x0}, 0x0)
r0 = open(&(0x7f0000000200)='./file0\x00', 0x200, 0x0)
fcntl$lock(r0, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000001})
r1 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
fcntl$lock(r1, 0x9, &(0x7f0000000000)={0x0, 0x0, 0x20000, 0x269000000})


mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
recvmmsg(r0, &(0x7f0000000480)={0x0}, 0x10, 0x0, &(0x7f0000000500)={0x200ffffc, 0xa})
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)


open$dir(&(0x7f0000000780)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x200, 0x2)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000100)={<r0=>0xffffffffffffffff})
sendmmsg(r0, &(0x7f0000001600)={&(0x7f0000001280)={0x0, 0x0, &(0x7f0000001580)=[{&(0x7f0000001700)="15ceb8b240cdf5f667", 0x9}], 0x1, 0x0}, 0x8}, 0x10, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0xc0e99db6de761f86, 0x0)
open$dir(&(0x7f00000011c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x200, 0x0)
r1 = open$dir(&(0x7f0000000880)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0, 0x10)
symlinkat(&(0x7f0000000300)='./file0\x00', r1, &(0x7f0000000c80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
r2 = socket(0x2, 0x2, 0x0)
connect$unix(r2, &(0x7f0000000140), 0x10)
getsockname$unix(r2, &(0x7f0000000000)=@abs, &(0x7f0000001200)=0x8)
r3 = socket(0x2, 0x1, 0x0)
bind(r3, &(0x7f0000000000), 0x10)
dup(r3)
connect$unix(0xffffffffffffffff, &(0x7f0000000000), 0x10)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1, &(0x7f0000000040)=0x7ff, 0x4)
r4 = socket(0x18, 0x1, 0x0)
dup2(r4, 0xffffffffffffffff)
symlinkat(&(0x7f0000000dc0)='./file0\x00', 0xffffffffffffffff, &(0x7f0000000ec0)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
socket(0x11, 0x3, 0x0)
r5 = msgget$private(0x0, 0x51c)
msgctl$IPC_SET(r5, 0x1, 0x0)


mkdirat(0xffffffffffffff9c, &(0x7f00000005c0)='./file0\x00', 0x0)
open$dir(0x0, 0x0, 0x0)
symlinkat(0x0, 0xffffffffffffffff, &(0x7f0000000bc0)='./file0\x00')
open(0x0, 0x0, 0x0)
mkdirat(0xffffffffffffffff, &(0x7f0000000340)='./file1\x00', 0x0)
syz_open_pts()
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
ftruncate(r0, 0x0)
r1 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x8000, 0x0)
ioctl$WSDISPLAYIO_GETSCREENTYPE(r1, 0xc028575d, &(0x7f0000000440)={0x0, 0xfffffff9, './file0\x00', 0x1000, 0x3})
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0x801169ab, &(0x7f00000001c0))
mquery(&(0x7f0000ffa000/0x3000)=nil, 0x3000, 0x2, 0x0, r0, 0x7f)
ioctl$WSDISPLAYIO_LSFONT(r1, 0xc058574e, &(0x7f0000000500))
getpid()
r3 = socket(0x18, 0x1, 0x0)
setsockopt(r3, 0x1000000000029, 0xb, &(0x7f0000000080), 0x0)
ioctl$WSMOUSEIO_SRES(r1, 0x80045721, &(0x7f0000000cc0)=0x3f)


open(&(0x7f0000000180)='./file0\x00', 0x80000000000206, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r0)
socketpair(0x1, 0x1, 0x0, &(0x7f0000000140)={<r1=>0xffffffffffffffff})
writev(r1, &(0x7f00000026c0)=[{&(0x7f0000000080)="95cf1644576ddfc27eedb614b8fe62e8508e59eebe46ede3df912faac6e89cb50cde487ffadbb8bd7d8bb98142084d8dfbba80b8fa035944ecc8d16fee63e3629624f81ade647f935f7c2159c700cf89a8850b", 0x53}, {&(0x7f0000000100)="0226039ef800000000000000000000000068", 0x12}, {&(0x7f0000002240)="dec91f1ffcacf3289a009059c3ad53ec0e9db3f29aa80c3d1fcd4f2a7b726b9a389c5596908615c4bf634a7d4cb1bd6fc2ac9f39a6e1050394c87409c95f620cbcde42d7a6f7dc8ccfb125a4787e5684ed6c977f3510d0a4657d20b9b46aeb3611fd3bdc3e04ce9d3f88ed7c9924ffa9e9c3a23189ca3e9643f66685ec34a94d0e86b92601ca54dae5eb7830e368947edc24a8935d3035661d07daa5fe258c4dca3f8c18df50293227ba17cd2b482142329185cf5fed4e7821a8ea115295e9d01ac74246d8c627622dbf8d6e739571d4a06c8bbfc19636410d1adcb035f3ca41787bfa167e05adcaf6ed8c2f726eb1cc30e55c50e9c921bbfa3fa24f76491b57a05203661e2ab7f29c549a168eacc757180389716927dd9962db1ef9721830ba5a2218ebcf779175f21b9f53cbac6cc1e4a00bb3385a215ac92b8426e9a95a3065c8f3f14d5666", 0x147}, {&(0x7f0000000340)="b90a4bb6283d91389424811bf589b3c857d1305c152f6eef53b51af06bcce17116de9edefab7b2d524b86f7ddc215671f07540d4d7d9e8b73bb5802555ecf41a8b4fc8110880626365e55c1d75f84d18cb651f5800f1481e1b99d3f3bb0c3d012cb253b3685db13aa813aaba51a0897c990ef2db1be8069c5479766243aa7d86bebf97af1e9b1c0685b2a5382acdf080449401d219d308079238954403a26846f804313151b674b9915c4b5cc0b95d9fd587dbfe1559cfa027bf", 0xba}, {&(0x7f0000000400)="640493d78db6a9c1e335bb42b30c7b40a07b3baad98026cb156727aa65cfb18540954a46faf6cd689a437aff3f4961c4e46a834f6785f138abeced17229a790e349e6bd31df47a250b6311c17b41de694d02002d9c138fb5554471ad71a4e3b0c4a0f71fc4b1f3db02e683a852170340fa26d02f5dcb6c3772415d9b0c54258aba6ad66cd42dfd5163936af944020e200f6dad158fa90dfdd051d151c8c8cb6d711f408511a8c922ff7be9bf88fc6a18b3261c65ab46b32f89b7793b789d533f5dabd554659bcbb9e4082598016c9ffd443ad64a6c1384bebc4f0fa12ebee357f81c1bfbb7ff9c0bb5289f98184e590366ece692aac2a0f3fe55ae6072624ff0892d666934e9e7bb159ba7471e9ca862d48aa90c56e33b972e7ab5f15383b1e0bdc135ef14c4b638c9514366af346df10d2d11e3e82c7f98a731867165c536966e32790a098e86bc8c85d1d890537ee1a3b37a907cb151aa5b72801d9b213f04f59acc40bab4f2dfde876c2bc53ed02cd106d289a59310e0297a072b926369982acb409872a3a4325ed56f1d297bc8bbfb8f0a43f793ee9487a4492016350aa61cca26b86045d14a8f08e6f6d3e3be5520397612b66ebdf990efcf9ed9796836fa253dfa0389406ae25edb31abf6797596cf9b4a943972a4a19c43db1926c18bf15fc526127d1b04211fb4f4fe4c34dba511e8801a10008e54d343386c0c096641681899e65d2afea539fec10a2db4f07a06c7745c1005d0c2b1f020bd80e052df5a4969a40602d7b4350068968bae7ed03d05c9f0e7dd8940d1e37cfbf3370f5953261615197d350c60c2e3bdc186eff30d0700e608a4e08b2cac91f42275e3e6378a0747267335e017b5342a1662df7f3144a5c0e08008460631d2fb76c410c11c4dcc7f73fcab23a4794775f4284e02ad1ba71d64db4f1f4ced92b7a389fd596763283771b9faf89865c462f59e57a81cf8c3cbeffb268f00b6589ab79483f517583bc3a949c0df139721b6dcb9635dca559ac670c1b3ac3ffae886d18134df6d3b7078928ad5370c9687de2846d1f89f7455cf1f7bec56f3717cbdcab9a5fbe597f929e432ff093d92cb35d625bc8c5dcdc4df998db4b51f74775e5d6d119c505a2d0f27c9ead9e84af18c5d7e258cb6a4b57d28c5be27c3d72e277ae3a79bec39bdc88df392b2df6afcca55f79efb3fe6d0d8b50d7c8bbbc134450db20f1d5a773ce9cdc3b97b3274cb2e9c85496e9043e1eb83bda1b0960808b7dbf61fa0b420596976194a598a6ce1066867d13ed30035f8ff0ba3dcaa15df0cab8b96807cb82435a42067d4f1257de536842db0d3f7dfda891c146d79b600e6a2f994f2755cb278becfdaaefb2c7b976be36689c7a0feced48a723be73f29851f75e42e9d62c83d6aa220891c5c24634e8c7cc3eab033046727127a802dacbde8cf629c1f57d59ba0690af43ce944607c1fd9df72f74d67e7ddc2efd8dc6c459d0d1fe2ca57d14e20046f139050206dd8d203e0389aef6682cc6b861cc364184ee9708452dcb732992ce6dedbb8d57b5c5689b9836c54cdc91b4766f618d608d4bb380614d8cc2e03b3b3b5897ccb61f9fe2d16e5ced34cee9e856a6c52324c0eef64a4b7f9e8e7ed5a71d7b1fe9f94665ac75da67d114047ff5a1c3d0668d43d78c12565ea154f763418049e8dd3a1929b7fa4877c9e2cd984ab94818219a05b196b643adb3f064dbffd2b22ade017488178c5361a1c93f9c615e0e0cd28f25b7ca582d6942071cb7fae17b52eb41ead6e78914945802c19bac16c76ae14c7ed4be6e42713e8a4bd6220aadf458fa15b40777f94e223c596c7f80bab9584fcf4ff14f138adbbf7b1a7bdd686fa9249fe006aea38651e410fd4b1af0d79d7f1ee0cb2711ca81382f15804771da4a18d5f20e10ff9a7abd6ae8583d94f58769f3401526e517d963800c92485f9c24eac2d914895d4d9b866bbb769d22a00db29ce0b9a7d7112defb15d9776db55edf8fca337b1a496c7710acab8135aee0261a780ef6b39664469e33dab2398639d1becbdc74000b36c2ca5df2c0d3c5d3d3e054a2b8d91bc4656cf09300dd084cb0b625a587fba81cc6c2c3ef6f93342b65bc0e68222de6908492ac431f9f4dc1d3915a2cba79820c8c1f7c6e5c582d953b60a943eef44a6e7b244c808fb292f3944a4b1afbbadb06ed72c1d2cf9a60e02b319af032eddb475ae1947175f437262cefe05a89dc92367c8f8223e3a415b080b2bee22f084d00a289e42f5dcd0c31dc257d6bd09d214fad7aaa03d285a4ca618a5cc2bc0167ce424c40b879bfc294b9f2be0ee1c4669fe57d15c3b8fd626507ebb94d7313eda527d86a2bcaf9234a6eb4fcd2ecd218607961c7816094311a762d783ab7cef7009f103d938a5dee845b827001c87920ea3110b97b40a8525c41a57a03e389d9d864c57e10a849509135cdde81b89da8ee10540b76fe6c303a98bfa68a493ff59104b41c34c62092d3c0cc16d5c5c9abf7d0cc9206605ca6b69511091b512063985b03549573fbe60036cdfb28e77670e99b55a8f8151035ac93ef64b77f36951b0d3a31befef14741f874b313b66908f8da53a8a95255c16019876c85dd6070b2a8470f303b98d3c9ce2d203774794ecd2dbc43a69cd37c21f9c971634ff7b00af46adccaaeb1ca346bbdcad44151e38a94d91339c425554791adf2d3ff197221979625d2993ef7f4af06ec2438ab780ce737ac1bdbd873fa3b5cc0af43097b2be36bb9cbf87d39d3a7d54d5a49b176a3d74d95c06cd9b665248f84c27019f7b62232d9de01396aa0096f36c399b762913e207de7e3d24a2bbb04d879fe29b087ea262e82e4b3ca0fca62f222a592ab6ca1b1609e6a7500b8ed38db0d895c2df29604a64540e796787461ed7d1c5c562662b8f5146839cfbae18a6fb302033ad6558ce8a9d61d5de662b995ecb228535cddd02aa051321dadfd06dcd6409cf98d8a8697c7499f1695f173b427ff5f6cfdd224b66b89682d0e2978710e2bbfe7c9f2793cd2592ec7106c44e46c1d2bfe9d7cb53cac640f92f66506aefcc11c983e6c284a892dfc4b813771087baf9150eeb019ba0877afef77a66ee91b2c85ab1b95cc670ae9e80a4f20b8c8914c655828a68d6e8b509d479b5d04980a5bb17fb9ef17060f802f6e6f57e29d6587d6b8dc3438f592db639f718cc3bdaad6865d8a6aa94c47e1061cb8dfb8d7c54c168a29e8b1a78e1716ce413d429daaf09c924a7cde44eafc58fa5b3a5e3aa387a9465f024f7fe6ed9343d81dee65d106f635bbece1c99d5eb8ca0487c00c2851aaf24b2b6003e7150758f5a50943de2ba7b95710fa05f1c1e305dd7a14dba19feb94c9591d8cf724ef55aca7fb8e054763f7c80027b929666f6864db25a059859ca8831f9b7251e38eda5b00d0fc64a3b3460bd7ad733b9eac508a6a191a6465ca14729214d29cdfef5c6409a3f7e5db2044f836c049f5a14a78bea5c7a55e957a53d8d7d97203de65090319911c1788fc704d9382571d3d1bd2b35927d8d95b3f3b14930350ca34d577ff1d4ab69c7ef9f74f73590b8fd0d3574e7779e7f6564f9245c117c4272054015715a0671bcec7416d95a17da00b50e976168b9de75b673f6998119eb1c3b2bd1eebbf21aabc7e606991dc2e802058344d4854b1fe88688873db69c8ac70a9e4850960390a510231dc7159e3e89be0162258982be870d6135b0870986f66c19cf315552165fdccdd2acdff62cddeba67ca0e9578ab629d895a81f63c2262362a49ef4bd8a25dbf73fd100844496f40753d1496bdae8cf60f23db024ec56dbb594e9047ef5b005f579ff829dc1c3cf6844dd8bdcaf644481d171cec2bd25dce58a23617d5d11d7d44465214accb32a5767548fdfe3a428699ec03d02fbc2ccf1237ba07249af6f37ea83ddd8c7ec77f56ae7025c5662ecee8a8682d61823ec04bfebd6195147b016a28112821ad0f2aa32110dd31b38027f0e7fa042cce3e52ec467aaf95f998db202f819f201ee1322215018824a880755b94a2876e09e4c0cac01005ff8885e5f2f21c28b1aab38c62c33de0268521db2c198d19e7fafe69215465f6421b8503218f394d5a94c8601dd6514ff8a80f442ce07a4de65060229285b873667fa19859753c4b949ada2d3ab20afb732a4d4f0a9e5e13ef5a50c8361a465874e956464e201de1f30fa97398d3636ce88e479428b0bd8521010b92a22b4866c311593c101e3ed6169242c63334c7d6715a6dc50063e1c5658f590d0177464461a2ed8892719a770bcd687c597d51d46b89640b6610bc107a6b6d23e46052680aa18673c61e68b22202cdb77ef1c562bf2a8ecfda4202832cff13192dbcb22df5bab0f174836a522169e91006456e5288f039d3efb332d26954f458323f5fb725a3a277c4ceeead163fdd3c0e423af8fb55d7182bb409e14fd2feb5e47764a5fbf44d6248c1bb0ab9f34be7df38df03dd9d83c56dbaa1d8fe1e47867e089672f9b52770aebdbca8ce07a89470dada6a71eee8290b35df04f70444beb343124306c42d7e2b7bf841fc8a3a67ea8fb27141e5c069a15691b65159d14566ae2985d1e65b25bff6b0205200bc735cb0c0c11226afe39792147af879c86c10227fa079ce1ae1c3116c260ed5cfcf4b160d04f2ee98fdac6e73e93c7888c2cbeac4402f6ce9bbab5f3a982cb761f271bc1d1c5e4fe9a48ae30b948480d12559b4089b33dca7d3152d56ae4e5ea5898f75bab167374149dd7753990e4d39fc48c04c92ed7ee4b77b2c91be5030d44b07a264251d53728a202dfb503054ff283acba3cf0c775742413cdc2b8f5ffca2d6f55595597c1c3d4a43c5e7d9f746372e59e774fc7579a3f4ee59c1f7e051699b8090ba1a7a2a820550452ab2b2c7725580e0d9f2f7d4db1c275d91afab90a682f12439c927a05998b994e03cfaf35bbb5085f58dc7e9e1f9dba4eb4b19baee1cb7fd222ee02b87053a449771b3234ef914242740b4be0859d3dda815d3a7031f1a1df3cbc71d248022245b805e9d06e9926e81ed4935e71dc94f66f8e5eb21962e56adcf7700126c68e45c9a3849041eba23e12eb88cfac2c8ba2226c746045a218b79f5a1a2a837f7f3bc3da86ca600d5ba1c5354c0d3bb78ee5e6777ca927a9994b81c51894ac8383c0c2abe54b9ab590b6fc7a4c639a988df1e53fd0b7d19002e62fa9b47328443bf082aa2782a5f89224b50096d90c0b595e751c3084c7c9cac6f653649685726c1c316eb3983a9fb37b55ebdf1ef51f3fe5b698fefd6b58f79dc2fca0fff8f2508ac63ae60751ee6961f2e1689e91a53c44ed487e2d3949a536293108c569b9bb3a30a929f39f6b229f7d75551d945c1e3129f1a479329d37f951528ddca3d38d8d5ac59925a47315d23b8f84549a0786421e6bbc588959c03b067adb3d63eae80a0c0ca2a52cfbfb328942b9cc0081d89375c56aba5b5df7b3608dd9b238cd743b39bef345627dac20547108366b9a31d02910d77b7bc0ddaac0beb526c412f612bd7f039967c3edac424050d34aa03d169c38cb0c575c9766abeb048511db51c649e24236532229b623ea26e5d60daf10e67cf2b07a01a3a8a8291534b08144fa4348bbf500cc92f99ee49eec595e9e511f4ea3641260e215509d048121d4c432eb069b829a2585f8554860c503b6c50970c5f50376a747cef9c4a53d42ce03b9d461abe102d7b0e50d70cb48045f45caa835bfc3bb9876c447102d8562a8aec95c5668d9d140aad718dea04", 0x1000}, {&(0x7f0000001400)="ca87803dff144c6b6b264a5851de033559a01bda1781d91a919177508facb2e29acbba7bb84709cde1e209bfb2a1fa4db4faea7fa5a4bad906bceac6e6f4f66980588643f2537045cd8ecc65340388deff9e602f1461492b8fc7f540d36f3690965910c311d0c4d3eca93b25177a9d8e5f6ba10d90ce7f99aba4224aab0b19d7d7432be4297d87bd9c9104e14aa65453962fb7d3762cdd5a368d", 0x9a}, {&(0x7f00000014c0)="0ec3f773b61cff1d39eaa0814beb7894b6fdd2f60fd048a3e29b317de8f9d00af19afd6b962cbce6d22ad1ba59209bb89093fb757b3a848ab0c08dbfccf909db1489c2c78d604e663badd9eb748620750ca606b77396bddea537f13dcb0163f2294928e65625b43d422d8de7dc3c9ce9931ffa472d35e1b31efbe38b993dd4416c32c7842d27fdadab1b2d7c24a203a62b486585a55d5ab4aff932c4b9385a99f863dd5f54153213ce78396f1be5c890242dcf3e2db2199e3985ce68858612aed57cedffe55926b7a9fd4ddbf675a817111eb63156243b15e19078fb80d5d7e5209727c6bbc14cb345adfbcfb382be6e37e35d8a73325f3b51574ac3e3a18747044a7255283c2e8a333ab806427931afa53e24224ba756959a78c465a551f9ac3ebacf3bb99b800e19ab119b3b99422127a6b76109bb4f2219f5c633f8fc8ff9196b8509dc4b668c2acbfa17415d4c55e328d967fc18209f7204dd73d9be75e60af58c18ac5dccfe05b35846479b497510768d5697bfdededf9a8c123b6348ed25ff7092538d86181d9278d327e390a96e4c6d65ca47e60eda262a7d54305684ec1fa51009005a966e37667636bc10b0c383507325baa2d027d926abfc06e9c282bff756bf6bb22eeaa5f0f5b3ded8f0b10bd58d1bc070a790c38fde52470455c9f3b981ecd1dc821fae715b04408779e06d4c22b13b66f16d1eb4b8ba7a69b365a164b511b625b2ab9625d88f49d68ad0e34910b6575090d45eca80fc824ca1e636d47e330eb8265a6e656ea0ca69734acd193adcc72c4f8eb356b6be86444d3bfe7efa8deee5cda9d7915738d947354d6c02b4c1b0c1926a840187f684c15b18db9b8f83fb365a891386295e51532ce3dcec9be8f401ae993631403f17a53b100de1238253a5b008b054e633d61cd9812174ecccd81737d9ab5144cc31bea4323114fbc619ae22bcb4129e0474a5632bf2d718a6c6dfffcd5f74317799ae39f9ec6aa698d9f7e4fdb4c003e899ef7de27d06258ca11ed029cd30893288204523798f02b5196d1bc3bd40b38156ed2f9e2f795edf46868c7c51732b935eda80dcbdcda037e34e356aa78dcf9e820b8de034e091682b545f387afeab5ea1f7ac06bde32f6add0ffa8d213ac0f5a59a5dbf9d672aa26f249ab6d369e64378b0890a7193d5fb297a71fd8a830a387cf57c319889f12ded293625f39a75f9bf214b7fc0c22af1f03bf5cd228b4300283467993cfde637d991d1d34d792b7a58fe92e6b218a53769021b5aabd16cd98239cce2c76feadfd276bfa6cee44de2c2d03544062a513733654102d3c292a21986a2cd0c981014e7b820279927eb5c7a5bb059b70b847673c4e4b325a5bbccc10fbeb08643016577b8d77e89c6fb663086157c53105ab213ba3c62a1a0576dc3318f9291de594a9b284842ed3b94e4d7dada4f433f825f39dcf5c3e2c8a9e7a30e9d032c30f25bd9b3760e90538ad687448e4dd88ba0fd1a593e04286fb2893792a9b7dc4bffefda85a0be1dff8d07fafb6351791f53fc7ff14348282e6d26cbf190f757934411621be890b1423d84a2305a1d954e9ba752a0d5cc4acc29bed04af12fc9d1788242800f5397a287c64dc91b9d6ebb31f5efffec3f38bc19f6e3cb485f00edf46d63b890cfb16190f31ecf75cb60c2fdd8c59f209637261c2629f81ea247bbec02f9c5cfc5045bb91764749e7d689b1b0c4a414134adc2863dafa63e8d4553f37877225e1be466e5d372fc1fcc91aac6550a28c088d370fad2830a0836f13fdd32c94a93e7b3e66d892b6764c0a68ca572f8bde4fc548c40098a3b05cd275be5483e39a9543813404396dd078a6dd3c9cc53beb02acf943c23c504260b54fd18411bea820c34b2a23aaa7cb52246df00185cf6485dfed080e3f5299992cad7fe9a830b6d95bc54c2cc014bce4dc4f8ca28609786901e81e0bf8f30118efe27b6c6fcb1d84fcbf62acbb67c51af13f83b55913c0e308d58982d60ab89b804985da01a8ab6c0a81eff92a66dd6baf3d5e91ee7d5b51a52bb9a0ce89a010d5551efea02fcc41430ad20dc487578de6471acdc3eee92f250485ce24ccb0edb7b4fd2f59e1b148fadd93dde3b418cf1a5eb8a5c7b937c09ed5140670d3fdee73b7c8a98cbcace8f6d2053bda2b84f0f61437610980b4d67aa4688860fce347058b6a08c2a19e57e2440e8ba643a94bcd8abd1590d23eccffaf4e00153548d8ecd6e3840842b3d3af1cafb6daadb81791baeb02bfc574d23ac8c1f656c390e4701a0299c40a539369993b558bed079ddd24d36387678cf505e653b65da9e4ffb7eb753a4dcd6a617e4a85768041e7de91a9e24d01f3bb600be7e7f625e5f342dfa12e815da31fa2b301a609229c4fc02d75895dc925ed2dfef1645ca8436642d4d38e74b39d065675d8f403c3c43b8965cf1f9418bd7c80fe0596bf02739a542afdcf3ee5c4d412a94d80ea9ab67687c96ac45c2f48b5b4d4bc7cf20aa84a18cdf9958ee150b622e6a7d455e37830b3ea938554f38eb6005b58a477cb6c05a96ca4d4670d567d051c2645eecfaae4b9d0c74c3ebcd6c4d9240aa7e9860a3c7d910cc24497b6b3fd035dfc853fe72211f3893c4436845b310abeb9d7e77b21273b9f9e17a768f3f010a19164bccd0f9b4d3a612225a24a18ec2da9c3f94c39da138b795757120cd07639ea9d143e229bcce4884a6628d0075ab20cb1d6d2b29d1e732e03fbba247eab361b92ade14827a0cfb2a450c238ff9fcb1fe56bcc256c7dad6f219e800f48e33b1e2461652842926186147e3bf6083e83e4fd06c4dd1b6bd12b7f5f3632694050b25216d78e9b83aea32852b6a7ecf822d056f5535206d15f44d5f4dab4b036b4a59768e803e9462c8b740c3ca26b4ea048a2df9389161909823574bfdff90b3d5668ff22e9fbf087729845e685921991f46abb7098ac6eddf696107e2fbfb6b7e89bad9ed956dc59b289fdcf7742c227647d592dc5a5c9bc32b8f0d37d42130fea84037c7c273b730097985c4f6e94792a026190141526b74333d3b3fa3c5cfaa94007a2880754d0a10a3995eefc7fc44a0fc26d071f62b068908d19fc8f140a68d75f8eea4457f975edc9709c6f477d2c62563ed5b831b36976aea4559298cb10abc26359f2814100e6991b75052f46e17bde5654e03e179bc3d1d8ad6442b40a653eee937ec54e1e3d730a964e512856d8381a1a6e4ca23000db72696afeae3bf2f335138f8c5abd1dfbe1f8a3b1ab115deadf3ae8ccd4914f110293284442a41c670b1cfed5289d9ae2e140cdfea1ec68ec898714e9bfc6686d1a093eef9a8c9f2131f85217332a25eec622f46c23b9f333f7b7a74061d893eab3e26dfaa67d47f599e1b0395f012647a6d3d8aab777b5e01915d8dc1fda0dfe15615b94da67e9ad5649f4dc72e5f01aa89d1e4704d43f5a44202914171538c0ed82f25a7c4979e6f47f0aa89f04af24d85b073dcde2405280b625e3e6111d56bd60ad00e8e1d93f65da22e2a2e58f28f8cd41b0328f19e80c3d7d8e0aa8680895fbfb4f19e405aa00e221d4b65201fcb1eff8165f75d137e18bb1e1f34219f7978941746cbaf4c97031cb3dff5680d30461f9260e8397bf1891812ceb7c4b9dfb2aebdecfcf82c31311cd4a42e91f8b070ad1ac293fbae1442678c000a7ecc1255a911ea0f403306b250ac39ce8191f05070161cff171e27338c9b15c092ef0a38659b911cb22db47e10dc3dbe5d4d09d2f310e43495ceb7eaffab9cb8485e617afdf05f12066d8da0506504eb81ff483b77afd9945135a45f2b8d2d309066e3a5843d62fa071ce239afc72c6a1130838305519bef9a2a7bcaa48b6db57f572922a6e071851e5bcceb7e198e47da979962bf5162aeb4369437af0ea35d6c94313252a3c697296cc7013924e2f14d1fdf7926bbf8919b672b11044e24d56df2be93104028f26d5602235d3ab67e10b8a83f6c0bea0df11339f28738ea776052538a70ab436ba45fb191b22d23dd2156713004a32c03badd917f35fe4e616caf8287b5d85a68e7ea984b2fbc6ee4e2af76763bbb975893c2d5ad961bcf3adb39b786ff5af9db2e4a6f602b5246e7a0500f9473804da7fa5f20620add2651af6d773b56373b25fb057f87d75135766777736d59e70f25a0cf05feefec616a7153a0db2a7158a286645529819fbfcf8f7dc813ec4779012d47985caeb6e5b6a8bc6eaa62afb9706ef3c897cd3a7c8019fac466ac5258ece31fed297840172e27bcedaf1c0df8e149899b3485773d035e161d0316c2f0098dceaeca927b95367d5cf80e9ece808f300aaf1bbb8e3e6ec7bb786e06ed1e4cf7966165819c9cc8537c8eb2107b9a07a0e770dc21b1664269f0de27a573d4350a2523886a93d7a95eaab531e4f6426c5d5aecb49d81636e8037cd81091bd0b87c6502536a4ef08f835b270a8e818746a42ac5f260761137470c7fd7196043325720d48873fa0a0aa08003be52607c45d32b913d37af0cb84960de245518cb37d30f48e714d75cb34279cc1c7f44f74f59a78256aa28bae3fc62a410f146716fc1ae98e2c4976052be99b62eae7e632b2ee1c5a839eb754303b18e62ba47e44e3e26ddc74369f3c4df7a74c1560c645f5a71c03e8f7d2b992e6ff7655ff5a14916ede9c7c1b2a7cd6942bca24079bdf8266f075e92be", 0xd01}], 0x7)
close(r1)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
execve(0x0, 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x1, &(0x7f0000000000)=[{0x0, 0x0, 0xc0}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
clock_settime(0x100000000000000, &(0x7f0000000000))


socketpair$unix(0x1, 0x0, 0x0, 0x0)
sysctl$net_inet6_icmp6(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = kqueue()
kqueue()
openat$pci(0xffffffffffffff9c, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
accept$unix(0xffffffffffffff9c, &(0x7f0000000180)=@file={0x0, ""/260}, &(0x7f0000000300)=0x106)
kqueue()
r1 = openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
kqueue()
kevent(0xffffffffffffffff, &(0x7f0000000040)=[{{}, 0x0, 0x11, 0x4, 0x0, 0x10000}, {{r0}, 0x0, 0x0, 0x10, 0x400000000000000, 0x81}, {{r1}, 0xfffffffffffffffc, 0x8}], 0x9, 0x0, 0xe9ea, &(0x7f00000002c0)={0x4, 0x3})
r2 = kqueue()
r3 = openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
kevent(r2, &(0x7f0000000040)=[{{}, 0xfffffffffffffffd}, {{}, 0xfffffffffffffffe}, {{0xffffffffffffff9c}, 0x0, 0x0, 0x0, 0x0, 0x4}, {{0xffffffffffffff9c}, 0xfffffffffffffffb, 0x11}, {{}, 0xfffffffffffffffb}, {{0xffffffffffffff9c}, 0xfffffffffffffffa, 0xd5, 0x10}, {{r3}, 0xfffffffffffffffe, 0x83}], 0x9, 0x0, 0x0, &(0x7f00000002c0))
r4 = msgget$private(0x0, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x6000, 0x101)
open(&(0x7f0000000180)='./file0\x00', 0x200, 0x0)
syz_emit_ethernet(0x36, 0x0)
setuid(0xee01)
stat(0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
msgrcv(r4, &(0x7f0000001540), 0x1008, 0x2, 0x800)


open(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = msgget$private(0x0, 0x0)
pipe2(0x0, 0x0)
msgsnd(0x0, 0x0, 0x1f, 0x0)
msgsnd(r0, &(0x7f0000000240)=ANY=[@ANYRES32], 0x401, 0x0)
msgsnd(r0, 0x0, 0x401, 0x0)
msgrcv(r0, &(0x7f0000000400)={0x0, ""/137}, 0x91, 0x2, 0x0)
msgctl$IPC_RMID(r0, 0x0)
syz_emit_ethernet(0x3e, 0x0)
pread(0xffffffffffffffff, &(0x7f0000000040), 0x0, 0x0)
mkdir(0x0, 0x80)
chroot(&(0x7f0000000340)='./file0\x00')
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040))
openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x1, 0x0)


ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, 0x0)
socket$inet(0x1e, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r1 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
mmap(&(0x7f0000ffb000/0x4000)=nil, 0x4000, 0x2, 0x2010, r0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000140)="67b5b992045c1a7733de71184dc12714990881d0d282bbbb82f88aee3375246d60d056448aeda248819c876f2c6e59c445667afca993a0516665954db86908d70836eed6da0b08d886dfd3ab4c442de33c74d0ff7946a83c180aed511af0d3eff58a00acff7ecc72afce9830fbd4edc05a5b077b39f6b4b7e961ce3c370f2f88a7bfe9e2762ddb30c131b1d20aa39f57ee", 0x91}], 0x1)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = dup2(r1, r1)
ioctl$FIONREAD(r2, 0x8020699d, &(0x7f00000001c0))
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0))
r3 = socket(0x18, 0x1, 0x0)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
setrlimit(0x3, &(0x7f0000000000)={0x7fff, 0x100000})
sysctl$hw(&(0x7f0000000440)={0x6, 0x19}, 0x2, 0x0, 0x0, &(0x7f0000000500), 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0xab62, 0x0, 0x0, 0x0, 0x0, 0x18a, 0x7}, 0x0, 0x0, 0x4})
getsockname$inet(r3, &(0x7f00000000c0), &(0x7f0000000140)=0xc)
r4 = socket(0x18, 0x1, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(0xffffffffffffffff, &(0x7f00000000c0), &(0x7f0000000600)=0xfffffffffffffdc1)
shmat(0x0, &(0x7f0000001000/0x3000)=nil, 0x0)
execve(&(0x7f0000000380)='./file0\x00', 0x0, 0x0)
syz_emit_ethernet(0x12, &(0x7f0000000200)=ANY=[@ANYBLOB="aaaaaaaaaaaaffff0500ffff8847"])
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})


mkdir(&(0x7f0000000000)='./file2\x00', 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
r0 = socket(0x2, 0x2, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x2, 0x2, 0x0)
connect$inet(r3, &(0x7f0000000000), 0x10)
r4 = socket(0x2, 0x2, 0x0)
r5 = dup(r4)
r6 = fcntl$dupfd(r5, 0x2, 0xffffffffffffffff)
socket(0x0, 0x0, 0x0)
shutdown(r6, 0x2)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1023, &(0x7f0000000080), 0x4)


r0 = semget$private(0x0, 0x7, 0x3c0)
semop(r0, &(0x7f0000000100)=[{0x3, 0xa, 0x800}, {0x1, 0x2ff}, {0x2, 0x8, 0x1000}, {0x3, 0x3ff, 0x1800}, {0x2}, {0x2, 0x201, 0x3000}], 0x6)
semctl$GETPID(r0, 0x3, 0x4, &(0x7f0000000240)=""/8)
semop(r0, &(0x7f0000000200)=[{0x3, 0x0, 0x800}, {0x1, 0x100, 0x400}, {0x2, 0x1, 0x1800}, {0x4, 0x49, 0x400}, {0x0, 0x8, 0x1800}], 0x5)
semop(0x0, &(0x7f00000002c0)=[{0x4, 0xffd, 0x1000}, {0x0, 0x7fff}, {0x1, 0x106, 0x1800}, {0x0, 0x3, 0x800}, {0xf94be4091d2c0a4c, 0x81ff, 0x800}, {0x0, 0x4, 0x800}, {0x2, 0xfff8, 0x1000}, {0x2, 0x7}, {0x1, 0x1, 0x1000}, {0x3, 0x7e7, 0x800}], 0xa)
r1 = semget$private(0x0, 0x0, 0x104)
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f00000005c0)={{0x8001, 0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0xffffffffffffffff, 0x11, 0xbff}, 0x2, 0x4, 0xffffffffffffffba})
semop(r0, &(0x7f0000000280)=[{0x4, 0x1}, {0x2, 0x8400, 0x1000}, {0x1, 0x2, 0x400}, {0x3, 0x8, 0x1000}, {0x3, 0x4, 0x800}], 0x5)
semctl$IPC_SET(r0, 0x0, 0x1, &(0x7f0000000140)={{0x1f, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0x10, 0x8}, 0x8, 0x0, 0x5})
r2 = getuid()
seteuid(r2)
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f0000000340)={{0xfffffffc, 0x0, 0xffffffffffffffff, r2}, 0x5, 0x9, 0xffe})
semop(r0, &(0x7f0000000040), 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7949)
semop(r1, &(0x7f00000004c0)=[{0x2, 0x5bef, 0x800}], 0x1)
semop(r1, &(0x7f0000000040)=[{0x2, 0x9, 0x3000}, {0x3, 0x1}, {0x4, 0x70a}], 0x3)
semctl$GETZCNT(0x0, 0x0, 0x7, &(0x7f0000001500)=""/4096)
r3 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
semctl$SETALL(r1, 0x0, 0x9, &(0x7f00000001c0))
semctl$IPC_RMID(r0, 0x0, 0x0)
semget(0x1, 0x3, 0x104)
writev(r3, &(0x7f0000000280)=[{&(0x7f0000000000)='#!', 0x2}], 0x1)
write(r3, &(0x7f0000000180)="1e", 0x1)
writev(r3, &(0x7f00000002c0)=[{&(0x7f0000000080)=' ', 0x1}, {&(0x7f00000014c0)="20206000019c0a", 0x7}], 0x2)
semctl$GETALL(0xffffffffffffffff, 0x0, 0x6, &(0x7f0000000500)=""/35)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
semop(0x0, &(0x7f00000001c0)=[{0x4, 0x8, 0x800}, {0x3, 0x0, 0x1000}, {0x2, 0x0, 0x1000}, {0x5, 0x3ff}, {0x2, 0x0, 0x1000}, {0x4, 0x6376, 0x1800}, {0x2, 0x5b5}, {0x0, 0xfffe, 0x1800}, {0x2, 0x7fff, 0x1800}, {0x2, 0x4, 0x1000}], 0xa)
setgroups(0x2, &(0x7f0000000440)=[0xffffffffffffffff, 0x0])
getgroups(0x3, &(0x7f0000000300)=[<r4=>0xffffffffffffffff, 0x0, 0x0])
semctl$IPC_SET(r0, 0x0, 0x1, &(0x7f0000000540)={{0x6, r2, 0x0, r2, r4, 0x8, 0x52}, 0x9, 0x265, 0x72e})


mknod(&(0x7f0000000400)='./file0\x00', 0x0, 0x0)
getrusage(0x0, &(0x7f0000000300))


r0 = socket(0x18, 0x3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
ioctl$FIONREAD(r0, 0x802069a8, &(0x7f0000000100))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000200)=[{0x61}, {}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f00000001c0)=ANY=[])


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/97, 0x61}, 0x3f8d}, 0x10, 0x0, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
poll(&(0x7f0000000140)=[{r1, 0x4}], 0x1, 0x0)
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)


setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000000)=0x7, 0x4)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$net_inet_carp(&(0x7f0000000000)={0x4, 0x2, 0x6}, 0x4, 0x0, 0x0, 0x0, 0x0)


r0 = open$dir(&(0x7f0000000040)='./file0\x00', 0xae828e137847f62, 0x0)
setrlimit(0x1, &(0x7f0000000000)={0xfffffffffffffffd, 0xffffffffffffffff})
ftruncate(r0, 0x40000000007)
truncate(&(0x7f00000000c0)='./file0\x00', 0x6000000000)


open$dir(&(0x7f0000000580)='./file0\x00', 0x40000400001803c1, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x80, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
open(&(0x7f0000000000)='./bus/\x00', 0x200, 0x0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r1, 0x80047460, &(0x7f0000000000)=0x6)
setrlimit(0x4, &(0x7f0000000140)={0x2, 0x4})
writev(r0, &(0x7f0000000180)=[{&(0x7f00000000c0)}, {&(0x7f0000000100)="28478b9e621f", 0x6}, {&(0x7f0000000a80)="dac5136729ff29c264006690291b4a87fc2a6d4364edce1cd1720a2fe082492f8b4eb05cc406411072b732020060820bccf45809ca9a9955a43dd6428a1bcc2b97e6969840ce81fd67aef3c1342b63eacdd004205a96ca6aab201e2d59c024ca32c891e579f51637535685d99bdaaed9a0575ab7bdf9cd4a353b67472b8d8f59224cff196be0a7eef4f9d185f5a2d321e3052f91e0f40f832de578c9207ead993163902d01f824420b3600fc08c6fb0cde74fcd4fefacf683832b59c9de7fd3199c4f2ad232c775c5c0d0afd49e869a22a7f6c47f40a51e5d44ecf1146df5208af25547302c24a675a4c070e7194499188895e8a762f468feb223c15e1c42213f463dc5a8edd945dd11cce9eeae536e61ce9133bfee757563e5a0d7662625d5fab90109566af733cad15b87637629b2ea96d6430201aaf83e36d520dca37d6fd32c21e9ed45542d5e65dbd7a6a28051ee7166487444f453ef27523f5eaa737ee5d0777170ffe89ae5d8b4216c40e1d1bc8343832c190561c317e5d820b2445c1b0c03c9d8078fe141d7a4853940f6d9c4af0d2a713c8fa5960c6f65db7462818832b7e728130343ccc946f8b2300ae936cad85af17a192e9259b7a99107ae0f11e587d94a6ea46373810b34d7f1291ad197efb8e66237deb60616739995f6ec6b60b2a34bde7b225fe2c903ea243a638d4fd885ad7d89e3416cdd04f5aaa69342f7f5278b8087de9b3bc9988336c18f655c07b48a3cdfac1bc39d9a960526c1f593efdde03fc41f5263e876bf499b9627d6083e2bfe1708d1a9486189e1c70b296be58175384d6557e7e7612abfcce6c7b66cfda76da7e8a6084bfdcc2fcc6e0e3fa7d8e876e11a93e58064d10342e3418cb4adb05de1a5a2167ba23980d3da9697991fd3803a1c9d463815ee38d2f11b608c9063719cda251f4bcd26f603a0583e189127695c6620853882a881a31f6e9884cd9084c9adf5cebc2c84b48cbe15cfd92fea52ed9e53fab751673be53814979103b8e73347c72a057deda0e6cb4fa1997676e0e1271e531e65cdc6d8051cce59d0a28cc6adf0a76f5b0bc50dcd89c642a8953fc1aa96b16c9d81555b747a82b5450738770b61c68593770309db2ba486e9f751a2956cfc6372292c9f5969ec686f1e954e11644f54fce4b46a16887d1d385a50948cada21a2f7ace7adf93cf449cf469914c177ba9358d6ce0fc3d058c05db70b3850a72f22a9c2f8e3e3caf6367c75dfc450044ccf69af6d93d9c42861b08a791ac870dadef185343ce616cea9b118e786853626714c96ba8a62d4d4a79d5c7aefb3000f6f26fb747f211be769cd62bbd3b8d72b4972d1c0088ffd609f5cd891fbf86b9f0187d7686394159430548ffc4a0b649d2d803ab9800341851790b38d8752f6bbf4ebed48abb7a4ccc1ab2f69677238db8e9ea20586047d4b581e3b5d0837747a0119b16be349852214422be6e64045e6b0d952f547d6a025c0fa3bbabea9c6cfb6d94901deb730b6d6d4c2f2058ab73600d1820090aba1c9fa43d89c79e042d434f111f27f7666102cab5e433e5f97aa70fca2161cdd798e6d01d7c483c77e1143c7c4efc465844ba0632ab1ccf48a80d983fc2e183d21c7d53a78b6d4eb8e8bb8c30268d0103a470b2091fb07355cf6f27c0ef6e7d3a56fe6fc36ee3d0403ad381d48642606c8a3ae1e78db055038c0ec3223c155621c9975f13c74651210de795aa700f4205a473ba43af3ec1d5f25c29a951512cd0da692685831c51e6fe5fb110e6acb360c0a8c4faa8130d946b28d634c284d2f982edf3740f5cb70c6c00617b8d4fb6f8cc925606bd53d652237434d617d4c3f461821b97005cc25ebbafc2398a677904fb0614f6e6f3631491dae91e8b6b5d8d1c71d45e2d464eabb9e92dc3f02525d903ed3230f437b84573885f141eeca1cdb909a80a778eda97661838552595dc409cedfe088477a9f30d848b4f862a27faef2ea167e54089bbbc1a36b4cf1c4b703a7b9bf8e5acd18e1de59040aa4d157e20dcdb029dac5e156feee9f64bcf023c7ef3e2d964aafb4bf97050fec5827f65e89016529b02bac7f5a69ae2b06a41f595315ebd001c46a5fe04728c83adab949bcf8c61e54bb5df73e1748cfd1fc299bb658aa50deb6fc45e03191cb99cc9f0bb4a7e8c9993530e8b5d988d8cb4a691702fc41f314aea39c0f33d8d8c163f9cf2b25fdf266cda80423be1bb6c51162d4776cb1b6bb1030c3193a36dd18a9b815674114dcf5c22cec3d089bda936d5aa592734cae4a479dc64a3c35e1c506cfa8e85d0e80187af0ff5951365c2537503fefd3c6668db8328f263bd67b9930feeacac91a9a47f1406fe6b192b5d71ad23584c6ad0983dec0d2bc93256cdd9c6680feeb915b083a0fed15d06bf6891a37680eb92bf4683a5d8cc7fb91b5809969b234f016f119112ec6035fcaffb0bdac42feed2c17f6a5b52c58de65dd4343c6e62e8e8da1a5ec53f617a44991984b140055dc8ac125891753eabb253eb6a4a29882b38e988de3baa97dfe7af6f29f9543b9d220c4cee96df0d4e8fd4a2d2d67038df338b65926bf82156adad8cce2be410bd05ff0df842dcec7bd5330c8921e0966dfc4e27bd97f16be2a49a1a84eb6c2a2b6eb960ccf08df79a155c328c3068884cab34279ba0e5ecc62f509dd349399ce49c9e4bd7e9d2742a6b3b4a9647e6860a943cb32b3a4ed8c4ad37cf32980ae4b19378ad0783a5e1d7899486bb0eb9a52c9a9826d6e9a5e6499d228bf3a2da55421fbd5d78c914872071259c1a6f5c8028e60a4e211b0bf0f4d4dea1345a2379215795e6bb941060fb7582da1306b9e2d156b801f926177cfc42b57a2fa476e9fed1ce76fbdcd314f1baeee62f02e22ce0606648706e01642891fe12eda6c91d7af49d84842a352af8dead21ee9fd1e441ffcd0ef7b68c85a821304ef4c87bb1978c3397ac3869fc93d3215b3852c7a39d1eeb4ac3c7b6be5108c252df12ed5611030a399781f604850f6e26d48596a6a8a8084cb3cb7beb80179200e91da0884c5bdc7f01d561e91a43ab76dd703bfbfcb3c2fb26583c0e65d5c78c50b38f5d51160fedc6376bd28c228ec25ab3fe7f060f52d4cfd647867b9522db6c6557d0d9f77f3ca0a34e59b9a7b972f8fe3160363a21350c78cea9aa964379111e5e59bc8f5ee5d15a1d7fae5c9e71b112f6c00adafc04fac2928b8a16d2f477366f065db1eee5fdf641d0bf53108f3097a4659314925227eaae301bb1238089a583ddbf9fb6e9ee493a711d33fa07a988da181eda063ea7608a6b17a8c9b8fca2cfc0b7036f376a4a7c1a6c0605647b633b549a7196825cdb99d4313ceca61c8868157c393133dc49065270b4f43cacf89b088efa9be8754219c5fc346e981028c133d8a4e4f6e392d8ba6b64ca74e759567fbbd7b16eeb09f6b886b7d07992c180e8f1fbc1cb3df334a7e398e250be4149fd599f4dbd85b7a35e87164d13bdc6ee19ddbf601fc55dcdd1abc7d7af0bc4fd948c1e2f1aed868014791a358ccc228b160cc476092edefce914d5d0d9b107a458edf9428a201032d21ce62bc119bc07b8538378038890a46a051ead9df330eb9b90e5d8b5dfa3ec8b6de1df04220aecf68540620b2b4c71deb1315d3defe625bcc3c9ede804fa3a3f55fbe52e51dd01fb6fa4b0b1d2b7d175e09a72dccfb68591176f15685d71c7785d21702508f24d2a3658e8826f3fe09b9f20131bb8fea54885d281a1a1edad3ef46ec7e1e3660605fd2c8f1002aa6d029499565d27e21d033395b3ecad701870eb9ba3bf4d530aedfbff6f6da744f69a9bb81308cc5a751e07ed368592f4b195a0b5fbb1639b976af063d8e53f8bcc386de53d1199446d86c1d60c23eb31395df94dc8b0ccbc4d39f0588d30e04f6faa58248112fcf81e87d9dfcfac515aed62ceec62219d4054f57eede708c19be2bf049ba88675082b0db7b65837d9c0271fff27fa09f34b11c583101279692dfd96232754c7f2637b2320a6856e83e9f61c64f4aa6e4c3e3fe24c12bfbf321269e89be47d964158ad1cc66bb9ab7465435b9cb39efa132ebcd342f655135e9f4276cb6da0b0bcbd57e03ec8bb107d1d700c4cb2a0acb14ccc64e83ccc7feaec5eca72ee76716abd8e24eff36b26809d1584ab6e5252ffe7a2c416a2dd1e37198a8486e1002f1278b7955f9281cc39312937c7885e2f81347fe157392112cea957324a94e298ba0ea426559c4c4e275941b86ccc7d4d4a5a88363bb6ccffb6b3fb94b2b3b2b00a132c0901a1c7783ae707e662289e23d48de110839b9b0daf95f2c0fbb13d1072e73dbe94ccab7cc064ea69c541af564d632208cd27c61d85a7a1c2d7c6c705cee0ef9dd3a22af00ff93276b068a420fa8d7977e796afa44d70d30ae235de6b75f0971deb8e9cdfcf64e486ceb7a58752490100904e7f324c28df487a3a41822b0eba5db92bbc34b73b2ab0589a71d2cba9a3dd20a0c3d65cfeec214da9e08082e6f9803ec614c16a251bb4c6581cd85e6cb8fdd990b53dee5212f61f2e3b12097588ca332c0b2a8ffe91e7a5f71619116f92fdfe4824e0fc29dcb857ea94171e367d05c3e8dad3007bd84ba11276c60eb0149152d4ac5ee8946be651b319a53f676dbbdbff937a6fdf34e7305672f00304f127f8711f7ebd3171939e75315a8e59abe90dca113df2613ba376f772a0ac1a422e126da1eaf89cad485f026348aaaaf9f3eed95bb15ecef5ab10a07793b21c2adfe660e31b4f6f939a9b318ba12919154347a74300ff2ad3a1e754676babdae6160bc2975e6bb223e922773e2a9f8d56b8b6e88659026338ce70644444dd3cc43d6ddba52552a4d15dd7bd62643636ccc483b61f47b0430b5115f8083cceb2d94592ee8556d3d40da79933fe5e20fb797f69833c39a321adafb9ae184e30c658dbb0983f69c9d2755d5556b7c2c6794fd1b6a958a20e7c36196af8975553eaab65329058c5bf6f365b3a1783e1838cd4f494ce0b2cebfe191744b416198ce23b745ea91dca93fa63bbd830859568caaa40ba7a3d48bfd669491bfc94c28efe3af3223eecefd75993764869802caf5030a7ca6ebbd9344a451a14cc5fada332e125aabbd912754a63b86ec36081a6ee153c81bdd91e024755f5b32955602f0a2998eee2b4e2a6f1ebdf532464da52d9898ad2b74f57c3561bf93ad1dd7b8db18623e08d060bf0a4361095477a1325bccaa7ef98dba52e952b81c68bde5cf1bfaeb46b236a5cc8934dfd86e4538e2d65d0b4c43fce54cbc86adc5f4ebb40a721fc09bdd8b57852727a17ea0b30334ceb2411f77ccce694f492cdf7c729737c7a5670728a8fb590fa9d73c34b891a4c5d6ada3b5751b2eadb140ca346efe25e3c8abe855a0be97efef438358fc61f9f15ac6e9069d39dc925d219b2ee49a6f50bb89898df6b39728c8ec133b013b2f90bf40edbfd01ed5bbf953498cf3f9eecc3e1937c66bd946da030a6cd3e718f1500eecd254e2648e1ba31941ed1c3739698061dad912c864f73eaf47af483d3b9daf33752f010b743d2a562c6c5c510e49507abf8849237e4609e7afb9e2a782677b5650d3c4e64daf65f46c11cdb3c3f508cb108d2b42b14c22fb6c3523cf7760702f66bbe346987ac353541ee500f59137bec876b9e3a06ffb19d538d794addfdeab2f23431b7eb9b40ea8c3e400d60112891fdaca22f9b76527a8b6a2b6faa394eda2691d23ff89c4ba36bcb8847dd15930dc", 0xff2}], 0x3)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000240)={0x0, 0x0, 0xfffffffa, 0x0, "863bb0c205ff4b54a9c3e665cb5c31c265ed2e1c", 0x2})
writev(0xffffffffffffff9c, &(0x7f0000000400)=[{&(0x7f0000000040)="e2", 0x1}], 0x1)
mlock(&(0x7f0000ffb000/0x3000)=nil, 0x3000)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x0, 0x3, 0x0)
ioctl$FIONREAD(r2, 0xc0206921, &(0x7f0000000280))
socket(0x2, 0x3, 0x0)
r3 = socket$inet(0x2, 0x2, 0x0)
r4 = socket(0x18, 0x2, 0x0)
sendmsg$unix(r4, &(0x7f0000000000)={&(0x7f0000000200), 0x1c, 0x0, 0x0, 0x0, 0x0, 0x401}, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
connect$inet(0xffffffffffffffff, &(0x7f0000000200)={0x2, 0x2}, 0xc)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xfffffffffffffffe, 0x0, 0xffffffffffffffff})
socket(0x18, 0x0, 0x5)
socket(0x0, 0x2, 0x0)
syz_emit_ethernet(0x36, &(0x7f00000000c0)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x1, 0x0, @empty, @rand_addr=0xffffff}, @tcp={{0x0, 0x3, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})
setsockopt$inet_opts(r3, 0x0, 0x200000000000a, &(0x7f0000000340)="00f4dffe77e0c1e790280e45ea74ccaeae001d2eefb20985caa97fe210b0f5cafa1a92ed355e345cd2b9c661eb7ec9fc36c2f116681b8d1edf47b124efbc7684f4c66bc17ff9cd772649df8cdb943ee791792e21ddcfb2aee91c6dd31253dfe277c2", 0x62)
setsockopt$inet_opts(r3, 0x0, 0x200000000000a, 0x0, 0x0)
munlock(&(0x7f0000ffc000/0x1000)=nil, 0x1000)


sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x4, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x4d, 0x0, 0x2e)


setreuid(0xee00, 0x0)
r0 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r1 = getuid()
fchown(r0, r1, 0xffffffffffffffff)
r2 = getuid()
setreuid(0xee00, r2)
rename(&(0x7f00000003c0)='.\x00', &(0x7f0000000400)='.\x00')


write(0xffffffffffffffff, &(0x7f0000000000)="7696e5f3d1f18c37cea8615ac7cf", 0xe)
r0 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$WSMUXIO_INJECTEVENT(r0, 0x80047476, &(0x7f0000000000))


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff})
getpeername$unix(r0, 0x0, 0xffffffffffffffff)


getrusage(0xffffffffffffffff, 0xfffffffffffffffe)


syz_emit_ethernet(0x66, &(0x7f0000000000)={@broadcast, @remote, [], {@ipv6={0x86dd, {0x0, 0x6, '\x00o3', 0x30, 0x0, 0x0, @rand_addr="8a211dd1450021b07f5a1957de7400", @local={0xfe, 0x80, '\x00', 0x0}, {[], @icmpv6=@pkt_toobig={0x2, 0x0, 0x0, 0x0, {0x0, 0x6, '\x00', 0x0, 0x3a, 0x0, @local={0xfe, 0x80, '\x00', 0x0}, @ipv4}}}}}}})


setgid(0xffffffffffffffff)
setgroups(0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000080)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
bind$unix(r0, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
setreuid(0x0, 0xee01)
r1 = socket$unix(0x1, 0x1, 0x0)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


syz_open_pts()
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
mkdirat(0xffffffffffffff9c, &(0x7f00000005c0)='./file0\x00', 0x0)
r0 = open(&(0x7f0000000300)='.\x00', 0x0, 0x0)
mkdirat(r0, &(0x7f0000000340)='./file1\x00', 0x0)
rename(&(0x7f0000000380)='./file1\x00', &(0x7f00000003c0)='./file0\x00')


r0 = open$dir(&(0x7f0000000200)='.\x00', 0x0, 0x0)
mknodat(r0, &(0x7f0000000100)='./file0\x00', 0x1000, 0x0)
syz_emit_ethernet(0x66, &(0x7f0000000100)={@local, @local, [], {@ipv6={0x86dd, {0x0, 0x6, "36ea07", 0x30, 0x0, 0x0, @empty, @local={0xfe, 0x80, '\x00', 0x0}, {[], @icmpv6=@dest_unreach={0x1, 0x0, 0x0, 0x0, '\x00', {0x0, 0x6, "5adf00", 0x0, 0x0, 0x0, @ipv4={'\x00', '\xff\xff', @rand_addr}, @mcast1}}}}}}})
openat(r0, &(0x7f0000000000)='./file0\x00', 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSKBDIO_GETMAP(r1, 0x80047476, &(0x7f0000000100)={0x0, 0x0})


setrlimit(0x8, &(0x7f0000000980)={0xb, 0x4e})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f00000000c0)=0x5)
writev(r0, &(0x7f0000000080)=[{&(0x7f0000000180)="fcffc883bc080089", 0x8}], 0x1)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbdf13b9fd812eaa4e713048e69931929648", 0x14)


sysctl$kern(&(0x7f0000000040), 0x2, 0x0, 0x0, 0x0, 0x0)
r0 = socket(0x2, 0x2, 0x0)
connect$unix(r0, &(0x7f0000000a80), 0x10)
r1 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x9, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000000)=[{{r1}, 0x0, 0x0, 0x0, 0x3, 0x100000000000000}], 0x0, 0x0, 0x0, 0x0)
r2 = socket(0x11, 0x3, 0x0)
setsockopt(r2, 0x11, 0x2, &(0x7f0000000000), 0x4)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x3, 0x0, "0100012d29fb000700000000098002005e00"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0x4, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0xfffffffffffffe37)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r3 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7949)
writev(r3, &(0x7f00000000c0)=[{&(0x7f0000000080)='#!', 0x2}], 0x1)
write(r3, &(0x7f0000000040)="0920e80000007c60e1016745b65369db00000000ebbd07a90172c84c838b4278ad535c39413f308cbbaee4ffcb7f31dbd1562eb77b6a0a", 0x37)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
r4 = socket(0x2, 0x1, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$inet(r4, &(0x7f0000000000), 0x10)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x5900)
r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
kevent(0xffffffffffffffff, &(0x7f00000000c0)=[{{r0}, 0xffffffffffffffff, 0xb7c61f5c345976d}], 0x0, 0x0, 0x0, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x7, 0x0, 0x0, 0x0)
r2 = shmget$private(0x0, 0x1000, 0x0, &(0x7f0000003000/0x1000)=nil)
r3 = shmat(r2, &(0x7f0000002000/0x2000)=nil, 0x0)
shmctl$IPC_RMID(r2, 0x0)
symlink(&(0x7f00000002c0)='./file0/file0aaaaaaaaaaaaaaaaaaa/file0\x00', &(0x7f0000001280)='./file0\x00')
syz_emit_ethernet(0x66, &(0x7f0000000280)=ANY=[@ANYRESHEX=r3])
r4 = socket(0x1, 0x5, 0x3f)
seteuid(0xffffffffffffffff)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
setreuid(0x0, 0xee01)
shmget(0x1, 0x2000, 0x221, &(0x7f0000ffe000/0x2000)=nil)
semget$private(0x0, 0x0, 0x0)
semop(0x0, &(0x7f00000000c0)=[{0x1, 0xffff, 0xe5ce97ab354d96be}, {}, {0x3, 0x0, 0x1000}, {0x2, 0x6}], 0x4)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
setuid(0xee01)
socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206980, &(0x7f00000001c0))
msgsnd(0x0, &(0x7f0000000140)=ANY=[@ANYBLOB="0300000000000000a60d524ae979b5a3e111c8cac1b119e4db1e444c9d4eca7af32596137392f4cdc50d82caa6fa7ffd0da455fa2e9f5109d4ccbe9ddd5e3674e689a6714f0ac2ee9e36ae12821cff35f5866888d441f7c29189271982efb7cd9c94766d1c4be0efcbf44d5d0010dc9df78616b167b260dd96322bfbad5f46f92beb4126cf5ffee44ca5b5bdfcf14c9b3003f53d57d96bcceb3c014f4d7b36a32f1fdb2d7783fa77ede48c3db7299ec5e58a1348d1da9304dc8bf8200a241f24ffa673bd7cb93b55b31a3045a1501250df6302a6bbfdcb68febcf98e7aabab17c9e7408bccc3081d1feec2142247dcd0e3ab8a8ab390b2a70909b2f114aa2b6ff737"], 0x401, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x1000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffa000/0x2000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, 0x0, 0xfffffffffffffffc}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_RUN(0xffffffffffffffff, 0xc2585601, 0x0)
r5 = getpid()
r6 = msgget$private(0x0, 0x0)
msgctl$IPC_SET(r6, 0x1, &(0x7f0000002f80)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3}, 0x0, 0x0, r5, 0x0, 0x2000000000, 0xa})
bind$unix(r4, &(0x7f0000000080)=@abs={0x1}, 0x8)
open$dir(&(0x7f0000000380)='./file0/file0aaaaaaaaaaaaaaaaaaa/file0\x00', 0x200, 0x40)


ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, &(0x7f00000001c0))
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000080)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
bind$unix(r1, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
setuid(0xffffffffffffffff)
getpeername(r0, 0x0, &(0x7f00000019c0))


setrlimit(0x8, &(0x7f0000000600)={0xa, 0xc0})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r1, &(0x7f0000002040)=[{&(0x7f0000000280)="00000053f6953b578a5e78ba726a44164282fbdce59879e20721c0b25930ac15cad92b17987d6c70b9047f2d23cdb8b6d76cdb4acd0f01d102ca1b9624dcb92a3496a85cd3e9356c954d9ad25d87bbbfee51603c6f705bcd4ebc04feceea4a01bb7075d879a19cf6c8ca7a76f1a3377ba643b0b06bef67d736f39ab2dfaa21a7c9f74a537a67ea748b925d5c0db14f19b8643bb65a04e2a641830b2ef9ab4087e50c63959920d13ff13464ce1c18b643a71260860e0483ab217250cdcb121305c5c1b22a236c83d7b8d20dfc08bebe5664e1ea1eb7bb0814dd", 0xd9}, {&(0x7f0000001d00)="6156b89a6c15794f5426cf6a9a99b45b13564d6568f0610200e27d20182a400c7a9a8f0bf304294555b6b6cd19d32607b3754f4a88c97fe52899b92de96dbe32036c902694cbd8aaeda1b13395179e9aa22d5bb4ed975d8a585625759478115f4c4ea9fbe58382e00bad0ecc43529514d50fd81869975cce62c2e1a2520b63fd16166f35d4894abbed34c52f3e7e55be11106341ebcf1c65", 0x98}, {&(0x7f0000000900)="d09f6591cbc30693afd0b88a5a095acbc2a56dfe7b00631bbf4fdf76ffff000000000000057fa75fcb6b520094262d6b81f8fb491e0d5f97f7e6e6fa34e3a87f4928bdcaba0d83c8a2f903007224ea89dd9aec6f5b8a9b09b2593bf5a6bf21f0983e", 0x62}, {&(0x7f00000009c0)="e0707225df5da0a3cde8f30024830d8e0a6a680844e59fcfa5dde0a596d8cb2901b8b60f269bdffed86a45026e99759cd124180e6c72cdd068718d18c40fc74364f4efef980c177c9d13853ee6bd3efb6bdd04795f2e00eef893ba9db6c641724b4320eb59db72e821e00eacae80ac14ec93e79465b5dfe980b08c3e219e10a322fc6a99d984aa3a17ac3eb99a7d90cd400081b6b1e9c2e49f51572f7f000000000000002cf371ea6bd4c4ec685cb5f1e1944576a86ba1fb802e8228e5f58b56265448b08e1f2d780a33751c191bc1a169ff48b7256c2993e0bc717933110bd6383d6022fb98dde74b5ab0ecd85d1c8019b3b8c07c14da5e8c27dea1464f6fc6dfbdd6c0f4b271cd8e8de9884f86ed79b994b9ed88cf29836e05544d9b93bb7fc1e2c2c2fddcddc82f884d45aeb0ce7407d2577be2fe2f8098613ab2ad60b5032a13dd9d63a2407efe3fadd1846988c3a299fddc1186d14064c4aeeee77394eb10e65516559f522378718fd87e5514c8fe55366b2154c898a888dcbbde73ca9e0126d6ee8c27af7b9eda998ffa359f377ea61147a6c3197247f363596ad3d3d0d9282758b09339d02616828993b0855085ed4748e48c50f7dab9668a7dca419149596579bb01408b8f2afa2b4bada88efbc57b7a096065fe6cb148eaed8f3becd5c7287c19d8b8d9341c416f2716c7a6ebaff889cf1ce69c7f4bf117fe4aefad2a50526a28df87ac628879076fe3b857ea830f45cb702afb7c25a06abe4d2a754d0fb77ff30877884fda5755e1c1c02700bade0be10b3c75c0166e477992584dbe308f2136ef82f72391136424d14b3fe1c4ff4cf8ee3d4a30577aa377438a795ce1efe0fef1f6436644224f92b45b87ec346a63a4600abb2bbc572ea82333f56d942d0294230c7ea8cf24bcbab7de10a06fbf4b8a5e4bc88a0b4d676062a62d5042b5d88b0ab80962dfff7ad508e6580ec0e565541c713e4a854483788c4440ed3cb388bb2fcf71e33495d9729eaa4f3df7d9118ea8942720f5dfda14cc5e35cd1c648b1e295dd0984536f225043b7aa56f45b94959d83990e6050353c7681fd596fae2ad6b43b26aac3e6302691eb49a92ac075b0973cc230bf41a02ef123a80cf799a9cf2c472ab0b45cde3c980a092662b79a78e428b56b878c2c9d7d2f667205d07c040744781e9c27e32a133cbe9e219489d97bcae4b2ec4ec0839978daba24fa23bb89fa6edc2b1f929e127136e13d7ab140a240aec7006d0740d15ce77b028746549bb91bde24e341d6aaef7684082283943780105de76983bc8c5101001c3a3a5dfe282d11d70ba08237d0c23eecbdc4a0738dcd1d0e92649c64d1fc75f5d4b1ccd10cee6ed69f4f63f63d63b04a73fe9b0d95ec3d98d55429524a7d5dc83c878f9bff0744c3c3dac7513e665383d243302b985da0fb404dddbde640a4f389fa4c3fb9ea1c5f9d515a2ccc8f64c832aff4f136f99b4d917ed0c1cdede6ffe621e6cd136bc2d43fb680dff0c68099c9503f61d3640c8ab7e0e00fc4a83fb01f03024f4f5325c1fb55568bae34451d9363cdc81e46e97b1686ae29abc9b06c8b5c7e989d3ad961e7216588c01b58b29fb05c432a615d17a09e3adf06cdfdf3dd2283aaa8fc9399b7b1d83c595c27f27b0c43fa110727fa37634d748bad8737cf7e94fb2c07b9737c4576b58e746ff84bbc736f246a7a368af9bcc22ca05122b160c0382db54145a62832ab52e1db855a1b160ef5f619b49f1e02baac67b9b0e626ba6070806e70c82c2d7c3273cf8e90270481e7baa2b2b4dde1b355f71c38405ae3f4f20e53db5e1542091b7f01507410184c37574a9ac52e3d588311c12bec275849496e726f8190529c0a49a0e3e6f455202aaa85bd892385fe7109b119dc4b5f9d6f74b0d27e04b2b648769af58d288765be71b37989a5ac5ae732d9e2a12c722e285383500d13e00dc7d6a064a7b207427edd517b5d30ca905935dbffff61e10b84ca904e4b58ab3278b09d1a3af7e337f777393b93c0e84ae3eb61f87e8f1388622fa35fdd51868a3329cf2c05fcba3c7cbf6afe20466583fbb1a8fa5fefdef3f8340feeff8048a96a2bf7466dce009599d9290c3e091ddddbe3f2031ac6e4c5ae5cf7099f92dde452dbaea6df2ad42b0cf665b8e221206fec348a6e3a70de77d7f474b88e8d328009c8ee253caef981ae633705c28594d3da0ce0de71b21f1cf64ffa8a23f58164d60240e1252aa62de9da39247acc335c352a8724ee35770747b3baf2ad195811dd7b768054277f7e59984084c464d49d936d1c66f7eb006001104bb29906ed7a14ffd968315fcad150cae3d278da5c0b1c82a62da917c39114deddd5bdfbaec686968e8f1aae41a18121de00cb66e9cf95403ec3c47f9155482f2b586fdaa860ac2d3d47329b1d493480fa5c968f3908f56c3c4731df5baab9d67b7b2253e3965a783031979ab940db29a998af0ad8fb492a883a60df2b28462813f8030bf701ab0e779cbc175a7e8d60352352ebbad06f6f1fa8b7d642ce526043ea448fb8583f5ad9759a422a41e41d7b3a36f2fd3acbb63c4d59a719300c9820093262d6b7953ac6f90c270364c31e7295ed15d106cee1285fe71b446abcf7dcf3c0e275e4426bd4e7a57e93e7cf73e1372510d8e6a2048ff8780eda3223277a03eacb710cddfe510169064edbce166244de18084dfe2508159f889a55a67f083c558a9b77f733daff67179a2322b53179e0079c92bd7aebaea9c5340f3ab4b7cc81d51803abd09fcc33392063c34ce1e1a0e675adfdd4a492f5a45e96d2da3d4533c9591bba11ee5a7f8552bba7cdc68932f8f4583e0c8f72b064fc249e1be449f1d4e6c8faa0010000000000000ed34660c399113ca2e1af84335086124e5880174e4db34d7e82a81ad779a2abb3f6de2d6e5ed9e08855396579362285f40c6aba7fac5766b30caa1b5a3ca31935a45e124040a29b974de1cff0eca1b1ba280228bafa33d26d87f77abb36415122a0cf24e1525228ccca1f6873e67bec443c6fc46790d2af8029bc97719078956a3d3c897faf5b19beccc2b37813351bb8a0964a5f8cde403f162d4035b6743fdf93830888e6d0927e68c924de1ee1e6eda7de8348196a0e240b4fd629338d977b497c315662ab60b84797b733a931741f0f7ae88e608a9dc73ce5f2b075af61b6acb61f8fd475ae504f97723326778a75a37474e1cf7aeebc8baa20f2168d566c1cbfa0eba48c19297ed0036090a7989ef743211924453e79ea244aa18c85170c9aef0f4047332f8b35b47776723379273f292200f4a95c5a19ecd42eba114c3f8cab75937ae571eefd7d79368272db2d2db75a1951fba103340a092a7f7a11e6ed7aede39b6992f2163fddcd8998b1a51ce55edd4991bcf242545192c5da99577e6362b1a26c98ebdd7353b0a1ad10b5736faf60273485d0b7d8f9c6dce6538e5e8dac1b564bcf788efd488490736c1cc354758e6d394c77561e47c8c5de55c824dcef6c2ebb6e9e2c734ea05b56b5017f2447a2634099c1b9b09e061f6747e663dd92e0dc5eafa5eccc7e8d161c1e79f30230bb07dba9894fa6af1c66592cbbff937c01747ce5ca6b356f54f141420e38ae84b8ef505cb8e5a20933c463f48a70983996b72219e31cefc8a9485f6f5451deb8686bf1551de5b549da221a014fa06222265932a5dbdcca51d053482d30798e805c6c65808d72cca8d8aff611be639e7af32a8e9e92b2b83d59a081b86a7704b92ba6ea48259a31175760354ca8733a53ada1537a123ba7dd87b55bce95c238e30f19092f9585e8dd9053bad2c51385afe012c2dbd3c277c9e6689e907b907748964f38b9576ff9b88ec5f1961cdbe845c7e096061686ce822e34a2228227e934803ede4b984ac3e4ef28f0c0e24e0893e70d7d0f668c7d38a14b3b2ff87cae2d1fcf1c8db5c32d02250145fbb20cfb8b279baa4a12526484bdfe4d36d49a82db857b82a0e11a315ea2e298bc8b8a69f4f7545008a440ace5b2654872f3f569269a1144e946c90f904e48ba061c1a615e8cde0a4194a567e86041ac9fa4b42553e19147ef3185fdbc685da9b439f02a6a34d8858eff5d762d4970488508f194b7af38590888c70d69b9eec79e53497645006ec6658dda11a7898ae96c8bc1a54b48470dbd840f0fc68799019b5b4137dc5de49af82d12ff2f50033ee8007c7d9ef1ebb3d60fddcb9239508a858df67e6ad3ffe23acf973db7421777a6a2f23ac58f599d88487ad8515808de09a0f59aaad6ecd7ba190bae74968c49b63451fd68cb2b835db73f7e341587aec98e7618b9836b8e851cb31ba1a2a86d52cf167279f850d811a0209a3d4a9c54055ba189eefa40ea10cd6458e1ba09979a3bafd21c5837fe11c264dea2f529ad2ed6d19849f2e8c0fad613478cb66a6724091e4b2c56588793813b44745eb97e688f382026c85e87124a66f542bdb99fb7fcd874d34985353e74a166a9f1ad64c305912b2b6ec1423c15788fa6b2194e2be021f1deb0f1b3d44b3313fbc9a38c290cede3cba47afcd98a4e50d019dfb64214d9c18448c375186ae9cbc7df4614ed4b9ef760c9808a5698c81b1542bb08e4fc82bfaa01be44d5cda756d4111192661807d4f0ae852777642019dd45d876e2c3bfc3f0486016b3d763cbd9d899b3e00c7d3001e94ed8515f0ec9b9f1ed7b8df767103ef964acb4281a59f5cebf08cc14e5f5166b9a77a43e8a3ea75c3a6a8e56eea86eb2c861fcbee63d44e60a2dc88c726b8149380aaaca89e83433c919c53754a64f9d8fee3049a5ab750eb8191f7676cdf3257c9e0c661921049962b800a299e5f5c002629bf053030203b5925b0f782c8bc5982546761b4256dd7c37a99de97f1187190f3a1068c86eb7c54cb3ba99052518ddff6c2f5a3601808ebccb435889a32b844d663330dd2231d55cec6a2e6f880ac93dc383f0323f33f66cce427475e117054827db2ddee05696992299131d9621d5041a596c3e72d7b018c813c5e1f698381000d3efe1cf189e2f749047bed3c6cff9184f22b4f3b6368e4ed839802f31394207395f8b3758f3c93f640734ebd122b52739a610d85092beeb06e47d32ddbdb1ff4ae18c696cdb93f8169f5980b01ac14ff66fdbc7efccf6f572a58e1a05efb444510edbd59cfef4ad12fe842483a3178cf9c81bb43e9213a7a49339d9a4d8150b5f253f938e91b3801252ca80230a9eb6a15c048cf10e068c6bccdc756d7fa1cce0b1cb147325b435cb504e5db48c32bc68f74a60b8baae0dae80bc4cb1cf4856802868817de6e7345ed493ce177a3dbbdec2690d590a23e3feb49554dac882dd8b70d8b7128d7ba1fcb715dc8b18a2bcfae0bf0a0bb557eb6eae8bad4ce3ee4246398e304188b1dcac6ef8f5e251db9c29e0ddd58abd191c5e2a961fa3e09fbf5a540c7687fefa036743134bf7008f66f484fe72a812844385fccf500123ddce1c3628c0826250f6e2dbe51bb7f525261f64bed241d3ce57b7da9f91e0d6cea8b3b249b461a3bd0372b2a76758de3113532ab8ddb3188cec04333d8d8930673fa753cdda63376e388d99a995642c7c43859ddc8bdde9101a7ebab17d4894f75dacde90fa971ed682fec74e25bd782a6c56d8e5fedd9ceafb8a71afdbeda2bc8c52047c4918c1ca24846c83e1b94fcbae7fb12d01f425e799de44da53c08a063e1ed1c47cc2fb55235c1b305afd000ef8f8cdd7a6234a37198b7bd8acf59a52c325b34f76cf5879128463d3948b4c401d9c8c8b1ebefe4405252612148a2fc80edd07131faae7998ab5e42519b9d536e4a", 0x1020}, {&(0x7f0000000000)="f286a84d365450931351d56a392f125053e372a5", 0x14}, {&(0x7f0000001b80)="09b3a74bcc4c28d5", 0x8}, {&(0x7f0000003f80)="9160123d76061585eaf66ae5661e9ef1dcb68a5ffeafff2953cf2e1d8a09ae56a62de6211d18c47e0f3491f0ea03e6790e5c82c2e7d1212652cfacc7743261bc7250207396761e126a9d84b718819d4edbd78a680b79e1459388cd1540571bc7b6b22be82fdc23a0dea1e96238ef53fb6547dc8aaeb3c796eb7be3628b9ce4b2ad3af54bb93a7b609ec98c4fd6e6f40b78a136ec58ac977c0f03880adda9eccffaab3d25acbd77ff269c9d99d292846bbca602408217d66179330b08563d3a2d036050e08f5a632a2d9b8f4399eb7eba6d146046c29decb9837d0127d596bbf3fa47843a5cdf896c9f39db9bf43040c135b43dd710a612c93cbd250efd513478460b88afa894267d6d3b5caa4df2f742ff9f3e6be94897da6794576524701994971c7ef2dfed4f359e8504ee8e93001e9ff61410a2465cfddedb29910228dfc73c71e88be80ce1905310216847c784c3b3be3d4491d25c99901497a2c4856b2989ff73d183474a1870befe42a2236851fa6240071ab8abe4e31179c2f53e634e70a12583be24974f6f85153aa453611c0c8a03b2294a3b234c4ae161d9265cced961b0df5d4515c76984e5e4e15f50b23d890b2bfe7b6c30a6409a5b74fe5a4a8c036b93cd9fb91ea84271269c52f8222916306f23edd3000f7b41cc4b3a4e5fa88a5c2d7678f0227a3782b1f8d6864b7fd8c2e76eff5021235dc3aaf4995d721d6aabaacc97373a107af76ec2c2520e400fbc749f8dd479d0cf5da54c4a73e41270d0391963e0cb8542be65f43fb2538d605085c22bc116b371c9aa02811aa86bd54a65a4b6983168180a3be1560b526de700f1949bb32d5d9f38f6a5c6281624c6fcb44aa657468ffafafdc0637748df145f718082709de89edc894c517a0f7ee0835e1fde37ba18740263c5dbb872aaf3640c55df4ae91f1c4d8a6d060fd46d2cfe9928475da6c0d001f9e2777437a663cabc593f8aa84f3799263cfc27076568723a08221b4bd190a3d24bc7f9bf91698e19479435a59a8ca4fdc38005a55d1e61eaaa9e4d71c99bca17b34045c700de76b4d90df4ff250341605ae4a680f6bdfe6ea5e6ff77bec1f6963c790519181faa2ec1a2f9b16d1b824dabfcef556e91ef4bce02b702146012f691ca05e0f873b793d6051c6448876a93fcaf32ad9b129aad644b9761508e0cbdda42424f5ca9ac5a0cb67fd5ef8d26078c16cf525df596a885bb192168ba4a86e99c0827b56331e6fce281bfdbe7601e6dd9f80e645d073e5fcfb80f23ed8d6a1c4c6f1a0593f126a47bdc15964106058ba5a3f5e3937e4d1936709df941849452f2c9c392aa70906c85e0edba5772c67f4ea0fe3719344d03a358fb664d793c4aa54e216aa56f8cf2b407ff5d4a529911af166a61b7ed4c3ddee3a52bb0c74950249d112f60d18b35e6c199bbaafda43d0f0e1e29b0bed4faeed45e840be722bfab97e30a01e8fdea1117a6b8581d6a9497c3921d84b377cd7bc1a1f3df421fa0a31f196c9f011339a202c77d552d5e30df29ad6a54a02d0bc728969bcb38626a82fab1855df909acb56dbbbe1338015737b460b9085379f144f08f4fe6fbe9c9df241061196a35365a34eaf0c65f97d15c811b98869c4a49ddae0601994d545d202d856fb5e3c96921e56b80ec978feb36f5daef50f995dc3cad442da07de75b97f810dce38413e8cc64ce3d32372a5b7b08ee898f5fbb37c4cb70e8b555322af7968013968ab4d07441409a43d6c68dc5b5cc02ed048e6a296f1f735fae1874c921c15dc6c4422c87c803c1783b344f60f90a3d2efafad2938d8269bda4df1bb247b482f36c1713859723951d31241fe7b3fc4b7c3bf11f055de8365b2b69328e5755fbab9dfb0b03205b2e98dc059fa5487c37ce89acb18613cc62486ce09e75a72a8be009793b00c74e9adc2b93471102f16e83cc9ef0ac2c2b7cb5aa757a5d51cd7f6336151beaf55eabd134a6e6b93593a151653837ed5d494a03bcf061d63d7a8e501973506642f68d6b2d490490cdc9980a624714008335f98caa71d22e8651849caa054b5c119dd154a80afd2ae95506728c0acf02eecd8887b821c764a2be51ba755b9db883a75748d3c20c2205fbdd1ad4ea848883642e27adf313fddfba60f314a80a463f056179643abd18bf0454dc13dd799d25c244460d8d2619238bb5aebe667fb38048d9dc84242dbcb17ecdb64170bb6b80fd710f597cc96d081da2ba082ea62605bb3388f43d1849f8b80ce8f8dadaefa84b0cf5e12c2a3db678dc0859bf927320cf765fedaaefad94d0da4ab50368105e4b5981feeb3edef40cf25780b6b00752e4839a1f3e0c3def6e5233db0490dc8ce93dedf0d44a05d2a132a3649eda3ab5da9e7762edd08b83a8cf2e7d253a78fdddc2c6ce97cbff41532692140ffd82bb4249328d01a9878e3f59d7159c493bec6184cd3d71e9213b4b6f70a7c26404ecde93e81e897e497f3b44ee04bf394cbe8540a49d31e33aa875b0c0e43e0c6af30350c5b7992a08d8cf0b5a88f0e5b88b6da6de61c0d1b6289be8d9effcaadd6b62f47b7169092f07ac1b1469f52b4b2369fd2e0fae1bc43cc415586b11e4fcac1b4148d5e7417e3a0a0ba64973581546781ae2a069073a0a557ed02b2462a2f26ac44729308c2347f4a7d7032b521ff58a8d1b3f095c376216c44762c889ff33f4688ba61dd2f1da40892e49a0bc0ef08940af0352cd6393eb1aef2fe707b138ba8119f3907993810a70bc4f1625ee0618230b58016277b50f89d8a7b92601c697b9ee5915a8cdf0b0d6f23005bc29ad38f7f3a7085efa550ea390ec31873f999733b874242b1eb5dc9dd5a8deb0c14d37e250d98060bbc30e8b5e6155267b424cf16deea1c1b003407f1308f93e8fa0ed90fb3789c7b05a5c6cb65fd34df7555dc14ee95eebbb0b2f0d75e3bffe98aaf4eaad9d39ceabed5967907007aeaff27bb2d0f11cd021bf1adfea43f09a6860db43ee3be9e520399bfe1f4e53b9981ba8f27f1c5e81c63f5e3292ada5c1876436b1d2d5504ab0affda2663d82dfd368cf67113f6dc50db630cd05b71d340afda503c2076f8bdb0f7dfb915defc7c1c9231234ec1b9bc51c9fd412ca09d7b0fd44af63461ece300c5e13c97be28a46be7d7811b648aef748905a3edc10c9854c2019b8da98f39ddae20857a9e10c0e0d31d21732b4464e69a7427f947d0d1428d785238cbe29febfe78002738319659cecaf443da90ce463923c09849bcd23590513bf05b9a0030329d29422057bfad1e9201efde01056efb4338152a90f3958d92affc0d28026067b9fb53847c3eb773edc09361b824de631476c50a9536d3432204f02d55679966fdac3284f5a8e6bb1a0fa8765f1bdf044f58610340b4405c1865340ee14aa612738218e58822cea59b2233bde7f515dca110b5b69cd023c65fe76c05b3101d2cb8839179c19e1253eedd8aa49eec5e61a234404b5050d3ae406b39ef356a61b9b70ff362dacc91ac18bd993d3411624b33516f5ce027fd14b98b71a127f100d0cd7bc06650ffd79b5acbfd6ac8acedd641151f765effd984de0d56aff18d939839671669b2f46ceaaf178b40652aa0830a4d01899721f7ec0f80745a021c2f3ec6ae4c2aa9c94bb13f46cd5ae8790b3da1c0399de2f2832c9ddc7265cdb6564934420b3dae8a9d18b929f23ebf03603a3504894e9091122598eb58a97d6455c7290a8c1762596b926a00ef0c38559b91682e3bc67defa7bfbadd8", 0xa6a}], 0x7)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000080)={0x7ffffffb, 0xffffffff, 0x80000005, 0xfffffffa, "0100000048026d00000100000000000000737d00"})
writev(r0, &(0x7f0000002f40)=[{&(0x7f0000000640)="8e78dbebae5d90546f15d52a70c0d6c01f58a61f32323c0794131b931fec61639d2f39a6047225d023e386c4556448c215cf2412d15d80dbf9f84b8741dd0b85594b84517605a7a7397ed4fb170e22d274b430934323f2f4fb5606ef5596615f1483c475b95ef23aea27e3b7a7c35f66ed518b4f97d9fa5945621a1173a9e1e34a3761486699739b5dd0f87a0d15ddb90c5f0b6935666ed373a8123f5a6167a180b5021fd0acff9d9731a5bd60e3ec94e2b7771d82937d6c7ff1b9422fdfbfa590964ca5b01b1ec5b60ef0bdd0be043b45cf8d18a5e672cff3c0aad2f41623f7ba3ba28c9b2419a3492b027f5169f1c7a49d496800dc3655536d25fd59b9cc0aa0d3bf78ad55f60a9ed41e1bb19b1c13d2d39a03a32123e8c58bbbd8603eaf87c9feff40795f8ef85e2c71683f9b14eefdc5e149b900000000000058d83b20ec6e38ea7ffa40bfb8663e568765f8dd8d20143f82711d82d74b2d81b884ef21822818bd82a0920bb8c5b6e58e7aa743bc6b19d3b903b3060c45f45802625565acd852f29eb1842818fca07662cb2d4d73565b41a0f5063b7194e477ce1132b8be22af9b9b7cb4006a3c800a640b194a2f78149ab96862f708c438bed872da989432c3532e81", 0x1c5}], 0x1)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
recvmsg(r1, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=""/236, 0xec}, 0x0)
sendmsg(r0, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)
r2 = socket(0x2, 0x1, 0x0)
r3 = fcntl$dupfd(r2, 0x2, 0xffffffffffffffff)
close(r3)
open(0x0, 0x0, 0x0)


r0 = socket$inet(0x2, 0x3, 0x0)
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000003c0)={{0x7f, 0x0, 0x0, 0xffffffffffffffff}})
recvmmsg(r0, &(0x7f00000002c0)={0x0}, 0x10, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
sendmmsg(r0, &(0x7f0000000cc0)={0x0}, 0x10, 0x0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
write(r0, &(0x7f0000000080)='T', 0x1)


sysctl$net_inet_etherip(&(0x7f0000000000)={0x4, 0x2, 0x61, 0x2}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0x0)
mkdir(0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, 0x0)
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
close(r1)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0x0, 0xd, 0x40, 0x40}], 0x0, 0x0, 0x0, 0x0)
r2 = socket(0x800000018, 0x2, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000180)={<r3=>0xffffffffffffffff})
open(&(0x7f0000000200)='./file0\x00', 0x200, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
r4 = socket$unix(0x1, 0x2, 0x0)
r5 = socket$inet(0x2, 0x3, 0x102)
sendmmsg(r5, &(0x7f0000000c40)={&(0x7f0000000c00)={&(0x7f00000002c0)=@in={0x2, 0x0}, 0xc, 0x0, 0x0, 0x0}, 0xff}, 0x10, 0x0)
sendmsg(r4, &(0x7f0000000880)={&(0x7f0000000000)=@in6={0x18, 0x2}, 0xc, &(0x7f0000000500)=[{&(0x7f0000000300)="04ee1220a39d7e607c22524941bc1e655012816e01b31c94e0b973973eb7ab413e7efab02b7eb3ead79ddf455daf6423befdf55551a58322ffca19a5fcc6687a3d47168886092104c0c1dfc0", 0x4c}, {&(0x7f00000000c0)="e5bbc8e6ea26c4a2c2339abbcadd2848ad683bce7b6a651528cf23a18e1d17c0b79fcc0ba4c21c4529b6effa638c926f12409dc212af3fd9f9a2b79288b50f01cec927dbb52d2da427d7ec08fb7b93ba2db6deda06d03a41d3258c901e8c9bc59aa88c1e383d2ebecc07eda7e754c3bd06b3335c0ca323229ef090e28a241fcc4dccbb751b292f5ab5334580da2e161590cb3c1b92d70a45e3a2fbbae0732287983bb6bc8df2a77417a3c3558d5b7c632f0cd37382229275b640fb8c1702beb96458b4182752adbab4b4263676845b2a6d845e2e36fba221e31ff02afbbefddc698be60bf84f76d0a62c5a1dc785d092b0591ef9e31d6b9a21", 0xf9}, {0x0}], 0x3, &(0x7f0000000980)=ANY=[@ANYBLOB="200000000000000001000000000000000fe24e05dccc752cc800000000000000c800000000000000ffff000000000000f351fe518620ba1ec0933d07222a353fef6b8b48192f3dc3f5f488ca5ef329494d2ca6d80435bb3cc514ba85bf8bb07d53686a3a0dca59360180ca5c46ef40e1209d41eca72a4884a515185357b5fa41edf1154b5c5fca8a2d128b72b9680511ca1fc5888f75c46264a3096b8f2867b82001f46ebd030a4520dde29069f1602e17002884bdd53df524e5e34c1da1b44b601e2837821e248d556ff925ae0e9f958f37e86d8980a0f2aa4abb28323a3d697a00000000000000900000000000000000000000000000000f5db35e05f2b6ffd6cba5d84bbe6636fb2c302eaf57b8c87dff269d4b23ebc6a547dd45088f943a4484fe1cbcedb2829d048b5317f13995df9dd9a71cec09a3b3de7e860986cb83feaa4d5cb01f1f5b8c3b777944183f6f2cee2c59838f0394a9495c7dd3e667f871163ef9490d2b95ac80cd91142e2a709c86627fa8e5547f0e00000000000000"], 0x178}, 0x0)
ioctl$FIONBIO(r4, 0x8004667e, &(0x7f00000008c0)=0xb24)
execve(0x0, 0x0, 0x0)
getsockopt$sock_cred(r3, 0xffff, 0x1022, &(0x7f0000000100)={<r6=>0x0}, &(0x7f0000000040)=0x2)
ktrace(&(0x7f00000000c0)='./file0\x00', 0x4, 0x0, r6)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ff7000/0x3000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000604000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ff7000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000691000/0x2000)=nil, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil}], './file0\x00'})
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


mknod(&(0x7f0000000000)='./bus\x00', 0x3a0914c44f7b202d, 0x504)
r0 = open(&(0x7f0000000040)='./bus\x00', 0x10005, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
seteuid(0xffffffffffffffff)
ioctl$TIOCEXCL(r0, 0x2000740d)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {}, {0x8, 0x0, 0x0, 0xffffffff}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b10005016000009f0500060003000000331c13fecea10500fef96ecfc72fd3357af302b37b673039d2d236acf20b7804be382249d1f7c8cf5f88882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f4d335c223e7d026ba8af630037282102000000720fd38bfbb770c1f572ca81ea77b3c5890400000000000000361b1257aea8c500002002fbffec2200008abfba090000001d89e40004070000008004200000000000001400000000000000", 0xb1, 0x0, 0x0, 0x0)
recvmsg(0xffffffffffffffff, &(0x7f00000002c0)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000100)=[{0x84}, {0x48}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


sysctl$vfs_ffs(&(0x7f0000000000)={0x4, 0x1, 0x7}, 0x3, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x1)
sysctl$vfs_nfs(&(0x7f0000000000), 0x7, &(0x7f00000025c0), 0x0, 0x0, 0xffffffffffffff2d)


read(0xffffffffffffffff, &(0x7f0000000100)=""/140, 0x8c)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000480))
syz_emit_ethernet(0x4e, &(0x7f0000000400)=ANY=[@ANYBLOB="3bb8723504f0aaaaaaaaaabb86dd60b234f900180000000000000000000000ff020000000000000000000000000001"])
socket$inet(0x2, 0x1, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{0x0}], 0x1, 0x0)
close(0xffffffffffffffff)
mknod(&(0x7f0000000300)='./file0\x00', 0x2000, 0x6da)
r1 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r2 = kqueue()
kevent(r2, &(0x7f0000000640)=[{{r1}, 0x7ffffffffffffff7, 0x1}], 0x6, 0x0, 0x6, 0x0)
r3 = socket(0x11, 0x3, 0x0)
sendto$unix(r3, &(0x7f0000000140)="b10005010000009f0500000007010000331c13fece910b00fef96ecfc72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf5f882b2b7be1aa0500000051e2f0ad3ebbc257699a1f139b672f335c223e7d0c032bfa896443a42118210000720fd38bfb0000fd54c125191b1257aea8c500002002fbfe0c230000", 0x80, 0x0, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000540)="9b0209c3eb987ab7fe4189c99e805e6e84d356960798a692992117d6728436ba1bd87f42e3303eac3846520d050712f838130efce33f524b3fa75085f35dfa4dc7e149d4d6d06a3f23616e774c02f1a07bee7385e6664282cb6988f8d9cae75e39a5a11e32e0e6ebd635450b2eba540af7f2aa5dbfbdd900a0da9e274f50acd76b5c567049ef436dbea0d7562f52950fa5ef6ec2bd02adc7f1fe850c081d95dcf4f06a852ab475cca257352828a76e5334be562995e894238b96ca5d4d3f670feac9b4e8aa9bef19525cb6f7e8570b2a374f1408341ed45bb7ad3fb975ffc080e963cb9a8bd949ee0fc6dbceb7d956e658a5673cc947b3e88aa810f8ed7cca10ff010000000000001345daa49507756f49775275ca390b94e85d5a95b8bdacb9429c25483a9275d0da3b561c6adc3c141f26a88016dd6b436218bdbdc9ac0a623855e941dc1872fcb045e0d9df1ecc6357ee21e2b0802cb60eec6a34396ce1e34e8a0bdd5e94723235f0675fad5315e7eecc3e11347f40e67a8c0ae4428f0760c70e1dd7873e27142bbae1a7e44de453a073c799353d46dd81439b115afb2e353e3bb073e3342773216b07e49ca4df0fd2dbe9a8eb3770ea880f76e6f4588ffb7d82693a096344671843a1f2082612b09a507c6e505ff594828b388f9ed85f1602a20561aed73c87e196f4f7859e071fc98111cc9024f790ce68e3f54baaee16ceaa7d01620500"/528, &(0x7f00000002c0)=0x210, 0x0, 0x0)


r0 = syz_open_pts()
syz_open_pts()
syz_open_pts()
mquery(&(0x7f000008e000/0x3000)=nil, 0x3000, 0x0, 0x0, r0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f00000003c0)=[{0x7}, {0x1c}, {0x6}]})
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000080)="35b5c242413c1026089a59583cc3", 0xe}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000240)=[{0x6c}, {0x64}, {0x6}]})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x4000000000000003}})
r1 = socket(0x18, 0x2, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r2 = socket(0x18, 0x3, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r2, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f00000000c0)={0x0, 0x1ff}, 0x10)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sysctl$kern(&(0x7f0000000040)={0x1, 0x59}, 0x2, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85baa97981056ef1043f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0xa1, &(0x7f0000000340)='\n\x00', 0x2)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
syz_emit_ethernet(0x138, &(0x7f00000002c0)=ANY=[])
sendmsg(r1, &(0x7f0000000ec0)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
r4 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000158000/0x3000)=nil}, {&(0x7f000003d000/0x1000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f00000c3000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000157000/0x1000)=nil}, {0x0, &(0x7f00001eb000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f00000e0000/0x1000)=nil, &(0x7f00000d8000/0x3000)=nil}, {&(0x7f00000ca000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f00000f8000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
ioctl$TIOCSTAT(r4, 0x20007465, &(0x7f0000000200))
syz_emit_ethernet(0x1019, &(0x7f0000000400)=ANY=[])


ftruncate(0xffffffffffffffff, 0x0)
sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x26}, 0x4, 0x0, 0x0, &(0x7f0000000080), 0x0)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
openat$wskbd(0xffffffffffffff9c, 0x0, 0x1, 0x0)
r0 = openat$null(0xffffffffffffff9c, &(0x7f0000000080), 0x20, 0x0)
r1 = socket(0x2, 0x1, 0x0)
semop(0x0, &(0x7f0000000300)=[{0x4, 0x3, 0x1800}, {0x3}, {0x3}, {0x0, 0x7a5}, {0x3, 0xff72, 0x3800}, {0x0, 0x1, 0x800}, {0x3, 0xa, 0x1000}, {0x0, 0x2a22, 0x1000}, {0x3, 0x95ce}, {0x2, 0x100}], 0xa)
semctl$IPC_RMID(0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x7}, 0x7fffffff, 0x0, 0x10000000009})
semctl$GETALL(0x0, 0x0, 0x6, 0x0)
r2 = dup(r1)
listen(r2, 0x0)
socketpair$unix(0x1, 0x0, 0x0, &(0x7f0000000200))
r3 = dup(0xffffffffffffffff)
recvmmsg(0xffffffffffffffff, &(0x7f0000000440)={0x0}, 0x10, 0x0, 0x0)
dup2(r2, r3)
execve(0x0, 0x0, 0x0)
select(0x40, &(0x7f0000000100)={0xffffffffffffffff}, 0x0, 0x0, 0x0)
select(0x40, &(0x7f0000000000)={0x7fffffffffffffff}, 0x0, 0x0, 0x0)
fcntl$getown(r0, 0x5)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x200, 0x0)
r4 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
pwritev(r4, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
r5 = open$dir(&(0x7f00000002c0)='./file0\x00', 0x2, 0x0)
ftruncate(r5, 0x80002)
r6 = open$dir(&(0x7f0000000180)='./file0\x00', 0x2, 0x0)
pwrite(r6, &(0x7f0000000300)='_', 0x1, 0x8001)
preadv(r6, &(0x7f00000012c0)=[{&(0x7f00000001c0)=""/224, 0xfffffdd5}], 0x1, 0x0)


openat$vmm(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
mknod(&(0x7f00000001c0)='./file0\x00', 0x2000, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
kqueue()
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSTOP(r1, 0x2000746f)
ioctl$FIOASYNC(r0, 0x80047470, &(0x7f0000000280)=0x1000005)
socket$inet(0x2, 0x3, 0x0)
select(0x40, &(0x7f0000000000)={0x3ff}, 0x0, 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0xc0206921, &(0x7f00000001c0))
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x8040691a, &(0x7f00000001c0))


socket(0x1, 0x0, 0x1)


r0 = kqueue()
r1 = syz_open_pts()
kevent(r0, &(0x7f0000000640)=[{{r1}, 0xffffffffffffffff, 0x3f}], 0x8008, 0x0, 0x0, 0x0)
syz_open_pts()
r2 = syz_open_pts()
ioctl$TIOCSETAW(r2, 0x802c7415, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x0, "ae2f00000000000000000000000011000200"})
syz_open_pts()


r0 = socket(0x18, 0x3, 0x0)
getsockopt(r0, 0x29, 0x41, 0x0, 0x0)


ioctl$WSMUXIO_LIST_DEVICES(0xffffffffffffffff, 0xc1045763, &(0x7f0000000040)={0x0, [{}, {}, {}, {}, {}, {}, {}, {0x0, 0xc8}, {0x3}, {}, {}, {0x0, 0xfffffffe}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {0x2}, {}, {}, {0x0, 0x651d}, {}, {0x0, 0x7}]})
poll(&(0x7f0000000000), 0x0, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = dup2(0xffffffffffffffff, 0xffffffffffffffff)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
dup(0xffffffffffffffff)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000132000/0x3000)=nil, &(0x7f0000ff9000/0x4000)=nil, 0xc0400000}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f0000065000/0x2000)=nil, &(0x7f0000093000/0x1000)=nil}, {&(0x7f00001f0000/0x1000)=nil, &(0x7f000008a000/0x3000)=nil}, {&(0x7f000008f000/0x3000)=nil, &(0x7f00000b2000/0x1000)=nil}, {&(0x7f00001dc000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000087000/0x4000)=nil, &(0x7f000002a000/0x3000)=nil}, {&(0x7f00005a8000/0x4000)=nil, &(0x7f0000145000/0x2000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil, 0xfffffffffffffffc}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f000011a000/0x2000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000466000/0x3000)=nil, 0xfffffffffffffffc}, {&(0x7f00000b1000/0x1000)=nil, &(0x7f0000145000/0x4000)=nil}, {0x0, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000087000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ff0000/0x10000)=nil}, {&(0x7f000008a000/0x2000)=nil, &(0x7f00002d7000/0x3000)=nil}], './file0\x00'})
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000800), 0x0, 0x0)
ioctl$BIOCGBLEN(r0, 0x40044266, &(0x7f0000000580))
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "1a1116f0d0f700"})
r2 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f00000005c0)=0x800007, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
ioctl$VMM_IOC_RUN(0xffffffffffffffff, 0xc0205602, 0x0)
r3 = socket(0x0, 0x1, 0x0)
bind$unix(r3, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
ioctl$VMM_IOC_RUN(r1, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0})
poll(0x0, 0x0, 0x0)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000380)=[{&(0x7f00000004c0)="e237724f0b69bc613bf424bab1160abccd8ab2832e4e2e57ba57b61c6e50bedaf4eb71c27ca2845128c0fabf2a9e12a8b26a24ffd2e355ca55c7be6546d1e920a07a4d88a9c3f30302d54ff3fcbb4bb74e2c2d9abec47035e611acbd85a7f64f35051016a90f9103ec7a66ab23d2b7b6cfcb49d6bc5aa40da7678ddf5460111d4b218e9fd6c4f7a6a4664b59fe85702eda", 0x91}], 0x1)
execve(0x0, 0x0, 0x0)
r4 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VMM_IOC_RESETCPU(r4, 0x82405605, &(0x7f0000000280)={0x3, 0x0, {[], [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x171], [], [], [], {0x0, 0x0, 0x1}}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r5 = socket$inet(0x2, 0x1, 0x0)
getsockopt$sock_int(r5, 0xffff, 0x40, &(0x7f0000000000), &(0x7f0000000040)=0x4)
r6 = msgget$private(0x0, 0x0)
setreuid(0x0, 0xee01)
msgctl$IPC_STAT(r6, 0x2, &(0x7f00000003c0)=""/153)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000200)=[{0x48}, {0x60}, {0x9756}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x0, 0x0})
write(r0, &(0x7f0000000180)="23009100007adb020317bdda2b7e", 0xe)


r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7949)
writev(r0, &(0x7f00000003c0)=[{&(0x7f0000000380)='#!', 0x2}], 0x1)
writev(r0, &(0x7f0000000100)=[{&(0x7f00000004c0)="407fb506fae6e1dec095983d06062ba449e33c9d068c415d513fc5af94da5b5062728d50e619fcf232780fb06b89234a8d2d104ac8be64b194806d43d0113e933db09cac75fefdba347c022783b3131ee835daee550378e4191b1e6926f46680b3ce713b148a0546bb942f3c1f1a0394dd0a", 0x72}], 0x1)
unveil(&(0x7f00000001c0)='./file0\x00', &(0x7f0000000200)='x\x00')
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$diskmap(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
ioctl$DIOCMAP(0xffffffffffffffff, 0xc0106477, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, 0x0)
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
mmap(&(0x7f0000000000/0x4000)=nil, 0x4000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
clock_settime(0xffffffffffffffff, &(0x7f0000000140)={0x0, 0x1})
socket(0x0, 0x1, 0x0)
r0 = dup(0xffffffffffffffff)
listen(r0, 0x0)
socket(0x0, 0x1, 0x0)
r1 = socket$inet(0x2, 0x1, 0x0)
getsockopt$sock_int(r1, 0xffff, 0x1004, 0x0, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
close(0xffffffffffffffff)
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
syz_emit_ethernet(0x138, 0x0)
mprotect(&(0x7f0000761000/0x2000)=nil, 0x2000, 0x1)
r2 = msgget$private(0x0, 0x0)
msgrcv(r2, 0x0, 0x0, 0x2, 0x1000)
msgctl$IPC_STAT(r2, 0x2, &(0x7f0000000240)=""/56)


fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x100000000000000}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x2000, 0x2d87)
r0 = open$dir(&(0x7f0000000580)='./file0\x00', 0x40000400001803c1, 0x0)
r1 = open(&(0x7f0000000080)='./file1\x00', 0x200, 0x0)
mmap(&(0x7f0000011000/0x2000)=nil, 0x2000, 0x0, 0x10, r1, 0x0)
pwritev(r0, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1023, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0206923, &(0x7f00000001c0))
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x8040691a, &(0x7f00000001c0))


listen(0xffffffffffffffff, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000000029, 0x0, &(0x7f0000000040)="0d2a2ce8", 0x4)
r0 = socket$inet(0x2, 0x8003, 0x0)
r1 = socket(0x18, 0x1, 0x0)
getsockopt(r1, 0x6, 0x0, 0x0, 0x0)
setsockopt(r0, 0x0, 0x7, &(0x7f0000000340), 0x0)
sysctl$hw(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f00000001c0)={0x0, 0x0, <r3=>0x0}, &(0x7f0000000280)=0xc)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r3}})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4e}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94100e4ac63c90dddc11f11cad5cc4", &(0x7f0000000080)=0x2, 0x0, 0x37)


mkdir(&(0x7f0000000040)='./file0\x00', 0x0)
unveil(&(0x7f0000000280)='.\x00', &(0x7f00000002c0)='c\x00')
unveil(&(0x7f00000001c0)='./file0/file0\x00', &(0x7f0000000080)='r\x00')
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f00000000c0)=[{0x60}, {0x84}, {0x6, 0x0, 0x0, 0xfffffffc}]})
writev(r0, &(0x7f0000000640)=[{&(0x7f0000000100)="6f86efc09802952688084127b3e0", 0xe}], 0x1)
open$dir(&(0x7f0000000140)='./file0\x00', 0x1, 0x0)
open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
sysctl$ddb(&(0x7f0000000040), 0x3, &(0x7f0000000100)="fe709e34ecfa8f5dd9ececdba98faff9343b1582de05ca53826962831cd302f3a87460ccb6d4d6d14b88dfff5e0000ef1664c916f09ab41a685b2612c4570735cded9e5372df5c62ae77a339060d16057d53bff6b12c816b8049c8f2ee36a46fb4cf7c82ad8bc910e8b0c6f589b2", 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000000)=[{}], 0x0, 0x0, 0x0, 0x0)
r1 = socket(0x11, 0x3, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000300)=[{0x2}, {0x7}, {0x6, 0x0, 0x0, 0x400}]})
write(r2, &(0x7f0000000240)="32848000"/14, 0xe)
setsockopt(r1, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
geteuid()
socketpair$unix(0x1, 0x0, 0x0, &(0x7f0000000040))
r3 = msgget$private(0x0, 0x0)
msgsnd(r3, &(0x7f0000000d00)=ANY=[@ANYRESHEX], 0x401, 0x0)


mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x0)
r0 = open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
fcntl$setown(r0, 0x6, 0x0)


close(0xffffffffffffffff)
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
r0 = open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
poll(&(0x7f00000000c0)=[{r0, 0x6e}], 0x1, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000080), 0x10, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
close(r0)


utimes(0x0, &(0x7f0000000040)={{0x100000000, 0x4000000000000004}})
r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$PCIOCREAD(r0, 0xc0107002, &(0x7f0000000040))


setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
socket$inet6(0x18, 0x0, 0x0)
stat(0x0, &(0x7f0000000280))
socket$inet(0x2, 0x2, 0x0)
setrlimit(0x0, &(0x7f0000000180)={0x8001})
socket(0x18, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000029, 0x0, 0x0, 0x0)
sendmsg(0xffffffffffffffff, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x40001ff})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
open(0x0, 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
setsockopt(r0, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
r0 = open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000001700)='./file0\x00', 0x0, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
close(r0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000006c0), 0x1, 0x0)
writev(r0, &(0x7f0000000380)=[{0x0}], 0x1)
execve(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffff9c, 0x80104277, 0x0)
socket$unix(0x1, 0x0, 0x0)
msync(&(0x7f0000952000/0x2000)=nil, 0x87abbe8d1cc6ad9, 0x0)
getpgid(0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x4)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="aaa4aaaaaaaa00000000001c0000000000009078ac1400bb"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
sysctl$kern(&(0x7f0000002240)={0x1, 0x3a}, 0x2, 0x0, 0x0, 0x0, 0x0)
setitimer(0x0, &(0x7f0000000000), 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
munmap(&(0x7f0000000000/0x1000)=nil, 0x7f7fffffc000)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r1 = socket(0x2, 0x1, 0x0)
shutdown(r1, 0x1)
recvmmsg(r1, &(0x7f0000000240)={0x0}, 0x10, 0x1, 0x0)
pipe(&(0x7f0000000040))
syz_open_pts()
syz_open_pts()
getsockname$inet(0xffffffffffffffff, &(0x7f0000000140), &(0x7f0000000180)=0xc)
setegid(0xffffffffffffffff)
r2 = msgget$private(0x0, 0xb)
setuid(0xffffffffffffffff)
setgid(0x0)
msgrcv(r2, 0x0, 0x0, 0x0, 0x0)


getpeername(0xffffffffffffffff, &(0x7f0000000040)=@in, &(0x7f0000000080)=0xc)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001280)={0x0, 0x0, &(0x7f0000001200)=[{&(0x7f0000000180)="bf3b684c5ae963b4567084e096cf973983b85e5df63e013eaa9405095e88157332b4f68e78e0793d3e30417acbf4419893cfd424b75262dc5ade2ab6278ab86672f9ed186987b8c19d9295a17b98020f6002", 0x52}], 0x1}, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0206925, &(0x7f00000001c0))
r2 = socket(0x18, 0x2, 0x0)
shmctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4}})
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f00000000c0)={0x0, 0x1ff}, 0x10)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sysctl$ddb(&(0x7f0000000840), 0x2, 0x0, 0xffffffffffffffff, 0x0, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r4 = dup(r3)
ioctl$BIOCSBLEN(r4, 0xc0044266, &(0x7f0000000100))
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCIMMEDIATE(r3, 0x80044270, &(0x7f00000000c0)=0x4)
syz_extract_tcp_res(0x0, 0x0, 0x0)
readv(r4, &(0x7f0000000080)=[{&(0x7f0000000180)=""/15, 0xf}, {&(0x7f0000000040)=""/17, 0x11}], 0x2)
r5 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x1, &(0x7f0000000000)=[{}]})
listen(0xffffffffffffffff, 0x0)
r6 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r6, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r6, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f00000001c0)=[{0x1d}, {0x7}, {0x8106}]})
syz_emit_ethernet(0x3e, &(0x7f0000000380)=ANY=[])
ioctl$VMM_IOC_INFO(r5, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f0000000240)={&(0x7f0000000140)='./file0\x00', 0x0, &(0x7f0000000200)='./file0\x00', 0x8})


r0 = socket(0x11, 0x3, 0x0)
getsockopt(r0, 0x11, 0x1, 0x0, 0x0)


mprotect(&(0x7f0000ffd000/0x1000)=nil, 0xe3487e4f6fb, 0x0)


setrlimit(0x8, &(0x7f0000000400)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETD(r1, 0x8004741b, &(0x7f0000000500)=0x7)
writev(r0, &(0x7f0000002000)=[{&(0x7f0000001000)="25b9f743860de9d44b2a8439abc5fd75e4cf5dbaf93de57eda4d30b27a8b1aedae3011249e63783b5ac5011269f8d31b936babe2f97e53fdc9c00769c4f347c8f38eef80a1a9ccaa38919a7625dcb895c82e3f7ede17c19b2f1d9212fb1cd95bd0dc9a38895ab7b839f3ccc4a3cca460dca95aacefed8dd6d6f3915c9b0cb0666a45a790a9b67d241956c876373a730dbf278e8f77734a79567bdae6360b7809af172ae0c4291ec06597eed83661bd0baa19b163eecdde88aaed78514d8fcf64d7b419140fb8941122167f799845245bce12f6642b6e5d513302b9804a86f8dddb2728a000c7c38795068da777edc5c3b71e704238e76a0d1155c7c02345d1588eb6d630ac84bc7e3653ffba7148bef98da5225a5c3764d0ab8a99c250405bd254f312ff1c56961a8016dee14a748ae9377796bc7b06db0d91e55d35d903b5dc2fc8a497b2afa23d4722ddea9088cf78c63885262f5132c535df0cff69b45399061e08c47a8c263298cd60ccdd03c542a32d5e8305879d7840b0711b4aec649b0d1327bc55f8e438d86b39d6801eea3e468b2e8c81d0870cebec4649373630aa79418b424308edb2c6be2e0b84a7a10499ecf933be6e3275a2b8d6671fdc6ced549dd47857dabd8b044d4f00011681de9a2df7f184834bab060af9449d94f6048fdd79113789b68a730e8ab3d790d3e55102f20a6755cdddf8c07afe18af717c103d5655da77d8510cb248f3e58330aa6c0efb9e48f1e2488cbfd32c7dd84e1afd462e063ec4529791297e85ad5df8712223a99ea241da037dad58f2e6a68081cb9849a8c998a6749c803ddc88c10230308902dcca22e05d428663ab947722f531be7b0b3318257eefb918b7c46729376863d902025f0b007fc980da57f8f07372b551fde77dc2f83d42c3db131d08f807b9f5203ba9f5adf9e0d4fdcac7e7ddcd360bcf364d7ac09d85636b26efcbf9d8b8bf6a5a04a31ccf59d029275e0371e13325828d75266b696e7d7a33c33d4896af49c365e5b0937f95aaea0db27deb2341bea1a801a76501ce80307e10a1b62c1e6df08481020c054df5c0be4f9983fc7ce2b63485153375e699b05fd6bb1b96c2a14523b800833f85049583b5e8075e85220b56dc02055f0b386c71a2341c2cf3aa5a749c15869a4aa9c80ca53ad3994ac3a96565c9700a0a55cfe0ab6a389f3bda818f34a6b7c963406021591a90e706baaf6186a116b14241d5f45371af9b5418d84298e9d108897c68f820397e2b7b63f558997a8b165eaaca4fe2e128eb0871cc03c28b54dd9a779cdec9fa38c1ab50a8cfdee63dcfd6ca65869a40ad16525c3a206912b09fa984cd207988d218e17d3af680363cea3025ae2ceda0a69e40b72a0a2bed671cdb8ac867985f4a5bbd6c9fbb491d88ffb86c2a08f7f1c37651ce3f71300d92524818b866afbb1af7b861b0f87233c9cb335879685f54326ff6afa12467fbb8ec4b4db88dccc40fb96a3bf81fe04404d18e8505ac049382355677a78ea288080f5850d50068a6c4faa505e1e32a26899524fe8059df8b8cd58b552afe3343c13085086e7f51287b75f691b5f96886b36a125725e35104869fe3a403a043cf2dd6856ebead426d6ef5c95a579c952f7bfa870e29c6f0915ca1d4190537339cf7396e509070cf63acc035b13b65a93627d41a77005ee0f92ac1c3881bcbb03c29c333825fdda88f726b925e905346e70269b861493449b0f135f1e37f990281b6056a0a7da61d60125cf03d9ea8cd232baadfb69de67090660451dea748b1f71669d4b536f2efd4bef98220048cecf1ab18b5b33ea732a994d2b722bcb59c8f03239c5d80d86cd1356695793c174bd2652769c6817bca145bbf032ea0ddcf74c3997b7892b829f0b7c4f3f720a835078ad79089cee6a11ed2e267968a63e6372cd68ae5bcd0f2628708b8418ab01467b8a8ca3668443a6dbe3e163bb46efaecc5386ea7dadacb59620cc1eefbdfa2492e380ef1e061e15f9a62a024cff3b21bc9c5a4501ace00c42ba6647e7f6b00a3a7018e3e303cda0703e89bb7406f0c60008b147b98597871e1317b72e9a16cc6ed6b050977b24e572ac7846aa1283d17f08be62159696ec7dc6d98e73c18138d9814af34595f88454c1bcdbd4060332100c6227c9466e0a8511254faae862feec7ec33393bd1329cea1156bc416d9f9c90549d82d4b73004c17550f1193cecd87933484b8a6d781370761dc0836705b3ef40b1312d19da156f192ba2e9eafa58737c05a68189a9ec670892326951b6c859d2ef48ef7ea1bc168b44188efc96b003602f044d1c2425d27eb75a66f1accc5304f582c334094a2629790e5a94b2febd53be7454df6e4e8eb984697d9d68ab598688e4f14807a65a40688207f91a3bb1edc325a9f9598c9ab6fb8f7cb3aec1d32c0a", 0x6ba}], 0x1)


r0 = syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x0, "cb00a6c8d300000062ecff6a210dfe8d008500"})
read(r0, &(0x7f0000000100)=""/140, 0x8c)
syz_open_pts()


mprotect(&(0x7f0000ffe000/0x1000)=nil, 0x1000, 0x0)
syz_emit_ethernet(0x4a, &(0x7f0000000340)={@local, @local, [], {@ipv6={0x86dd, {0x0, 0x6, '\x00', 0x14, 0x0, 0x0, @ipv4={'\x00', '\xff\xff', @multicast1}, @rand_addr="b82957248c3701367c9909fa96bf7cb7", {[], @tcp={{0x3, 0x2, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}}})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x7fffffff, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x0)
r2 = dup2(r1, r1)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


mknod(&(0x7f0000000040)='./file0\x00', 0x2000, 0x3200)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x106)
close(r0)
kqueue()
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
mknodat(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
pipe2(&(0x7f0000000000), 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
socket(0x1, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, 0x0)
dup(0xffffffffffffffff)
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000040)={0x0, 0x0})
syz_emit_ethernet(0x26, 0x0)
setitimer(0x0, 0x0, 0x0)
r2 = kqueue()
kevent(r2, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x80206916, &(0x7f00000001c0))
open$dir(0x0, 0x0, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
kevent(0xffffffffffffff9c, &(0x7f0000000000)=[{{0xffffffffffffff9c}, 0x0, 0x0, 0x0, 0x2}], 0x0, 0x0, 0x0, 0x0)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000000)={0x0, 0x3}, 0x10)
sysctl$kern(&(0x7f0000000000)={0x1, 0x42}, 0x6, 0x0, 0x0, 0x0, 0x0)


setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000000)={0x0, 0x8}, 0x10)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
r1 = dup(r0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
sysctl$kern(&(0x7f0000000300)={0x1, 0x9}, 0x2, 0x0, 0x0, &(0x7f0000001440)="00000100", 0x4)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000000040)=[{}, {}, {0x7, 0x0, 0x0, 0x4}]})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000007, 0x0, 0x0, 0x0, 0x0)


mkdir(&(0x7f0000000100)='./file0\x00', 0x49)
setreuid(0xee00, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000015c0)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, 0x0, 0x0)
setitimer(0x0, &(0x7f0000000000)={{0x7, 0x1}, {0x8, 0x200}}, &(0x7f0000000040))
sysctl$net_inet_gre(&(0x7f0000000000)={0x4, 0x2, 0x2f, 0x1}, 0x4, 0x0, 0x0, 0x0, 0x0)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r1, 0xc2585601, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000440)={0x6, 0x18}, 0x4, &(0x7f0000000480), 0x0, 0x0, 0x0)
socket$inet(0x2, 0x2, 0x0)
mknod(0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
sysctl$net_inet_gre(&(0x7f00000000c0)={0x4, 0x2, 0x2f, 0x3}, 0x4, &(0x7f0000000100)="80815d97e5e9ec42557fbfa1b208d658d9983f117a859fd619a67026beff80585ebedf283df04854cf98e456c11215a266b3c48e70351ef02e", 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000002a40)={&(0x7f0000000000), 0x10, 0x0}, 0x0)
chmod(&(0x7f0000000300)='./file0\x00', 0xd0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000695000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f00005fd000/0x1000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ff7000/0x3000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000545000/0x1000)=nil}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000069d000/0x4000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ff8000/0x4000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f00002f6000/0x3000)=nil, &(0x7f0000ff3000/0x2000)=nil, 0x3}], './file0\x00'})
r2 = socket(0x2, 0x2, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000180)=[{&(0x7f0000000000)="9da8e3e9ed", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$VMM_IOC_INTR(r1, 0x800c5606, 0x0)
r3 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
dup2(r3, r2)
sendmsg$unix(r2, &(0x7f0000002a40)={0x0, 0xffffffffffffff89, 0x0, 0x6e, 0x0, 0x700000000000000}, 0x0)
sendmsg$unix(r2, &(0x7f0000002a40)={0x0, 0x0, 0x0, 0x40}, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{0x80}, {0x74}, {0x8006}]})
syz_emit_ethernet(0x138, &(0x7f0000000080)=ANY=[])


open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
chdir(&(0x7f0000000040)='./file0/file0\x00')
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x1, &(0x7f0000000080)=[{0x1ff}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
mkdir(&(0x7f0000000080)='./file0\x00', 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)


r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x40)
writev(r0, &(0x7f0000000100)=[{&(0x7f0000000280)='#!', 0x2}], 0x1)
write(r0, &(0x7f0000000000)="24a608d334f68b1f26da3fb9a1e5e89f23bf136473c01cf9efec93275e090909400000000000006745b653695b5e8e0010000000000000413fb5df308cefae50ffca562eb77b6a0a", 0x48)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
open$dir(&(0x7f0000000300)='.\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
r1 = kqueue()
poll(&(0x7f0000000000)=[{}, {r0}, {r1}], 0x3, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x42}, 0x6, 0x0, 0x0, 0x0, 0x0)


sysctl$kern(0x0, 0x0, &(0x7f0000000080)="71f91e3471ac0058bc5a91501d94a34b8e5f84cc42c3fbe6edf28f03055a7b8379c80000ff7f000000000000000000", &(0x7f0000000040)=0x2f, 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')
fchdir(0xffffffffffffffff)
openat$vnd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000006c0), 0x1, 0x0)
writev(r0, &(0x7f00000001c0)=[{&(0x7f0000000200)="ed89f1a5f8365946b16f", 0xa}, {&(0x7f0000000000)='9', 0x1}], 0x2)


r0 = socket$inet(0x18, 0x3, 0x102)
shutdown(r0, 0x2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000000c0)=[{0xc}, {0x61}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000000c0)=[{0xc}, {0x7}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


syz_emit_ethernet(0x3e, &(0x7f0000000180)={@broadcast, @local, [], {@ipv6={0x86dd, {0x0, 0x6, "481e0c", 0x8, 0x0, 0x0, @empty, @ipv4={'\x00', '\xff\xff', @loopback}, {[], @icmpv6=@echo_reply}}}}})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCLOCK(r0, 0x20004276)
seteuid(0xffffffffffffffff)
ioctl$BIOCGHDRCMPLT(r0, 0x40044274, &(0x7f0000000180))


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
socket(0x1, 0x0, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000040)=[{{}, 0x0, 0x0, 0x0, 0x6}], 0x0, 0x0, 0x0, 0x0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x881)
r0 = open$dir(&(0x7f0000000100)='./bus\x00', 0x0, 0x0)
fcntl$getown(r0, 0x5)
r1 = socket(0x18, 0x2, 0x0)
close(r1)
r2 = socket(0x18, 0x2, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x100000000000000, 0xffffffffffffffff})
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f00000001c0)=[{0x54}, {0x84}, {0x8106}]})
syz_emit_ethernet(0x62, &(0x7f0000000140)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000140)={0x3, &(0x7f0000000100)=[{0x35}, {0x2}, {0x6, 0x0, 0x0, 0xfffffffe}]})
writev(r0, &(0x7f0000000080)=[{&(0x7f00000000c0)="d3d9bc6f7a689f455f7bc4e71ba7", 0xe}], 0x1)


r0 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r1, &(0x7f0000000000), 0xa)
listen(r0, 0x0)


r0 = open$dir(&(0x7f0000000100)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000480)='./file0\x00', r0, &(0x7f0000000180)='./file1\x00')
select(0x40, &(0x7f0000000100), &(0x7f00000024c0)={0x1ff}, 0x0, 0x0)
rename(&(0x7f0000000e80)='./file1\x00', &(0x7f0000000f80)='./file0\x00')


r0 = getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r0})
open(&(0x7f0000000180)='./file0\x00', 0x75f493fec6515f78, 0x0)
pipe(&(0x7f00000001c0)={<r1=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r1, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r2 = fcntl$getown(r1, 0x5)
setreuid(0xee00, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0xb32, r2)
setreuid(0x0, 0x0)
ktrace(&(0x7f0000000140)='./file0\x00', 0x4, 0x1808, r2)


sysctl$net_inet_etherip(&(0x7f0000000000)={0x4, 0x2, 0x61, 0x1}, 0x4, &(0x7f0000000380)="e92ba77a99ae6b545e74f9bf49b3bf3431f029d7d7ddc5e76a06766120b3e33b13bb1587fecb75a201b21fccf28b8613bb49cd68d87411b1cc96f137d092c89a51780dd9dc4641e9dfe4c1df53187df77deac8f3d9e877571f3cd826319de2892cedd9e229132f89eb0428497883bbde132aa235e0e8255c9dc94276279c1658557877b81cc83f2508a41adf7f31c7b74141ca7539127643db6d080100"/172, 0x0, 0x0, 0x0)
mkdir(0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
pipe(&(0x7f00000001c0)={<r0=>0xffffffffffffffff})
fcntl$setown(r0, 0x6, 0x0)
ioctl$WSKBDIO_GETMAP(r0, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
ioctl$BIOCFLUSH(r0, 0x20004268)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, 0x0)
r1 = socket(0x18, 0x2, 0x0)
close(r1)
socket$inet(0x2, 0x3, 0x102)


r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r0, 0x80085761, &(0x7f00000000c0)={0x3})
ioctl$WSKBDIO_GETDEFAULTKEYREPEAT(r0, 0x400c570a, &(0x7f0000000000))
open(&(0x7f0000000180)='./file0\x00', 0x200, 0x0)
r1 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x53e, r1)
select(0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)={0x0, 0x100000001})
r2 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000180), 0x1, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(r2, 0x80085762, &(0x7f0000000400)={0x3})


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000280)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000340)=0xc)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r1}})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4e}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000180)=0x66, 0x0, 0x27)


mknod(&(0x7f0000000000)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f0000000180)='./file0\x00', 0x2, 0x0)
ioctl$TIOCFLUSH(r0, 0x80047476, &(0x7f0000000000)=0xffffffff)


msgget(0x3, 0x2a1)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "28b77c09b87aa57800080017d0d2000010001c00"})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x800000018, 0x3, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x18, 0x1, 0x0)
close(r2)
r3 = socket(0x18, 0x3, 0x0)
dup2(r0, r3)
setsockopt(r2, 0x1000000029, 0x2e, 0x0, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


syz_emit_ethernet(0x5e, &(0x7f0000000080)={@broadcast, @local, [], {@ipv6={0x86dd, {0x0, 0x6, '\x00\t\x00', 0x28, 0x0, 0x0, @rand_addr="6e1aa4058b74adad9a4e721f5b293380", @mcast2, {[@hopopts={0x0, 0x1, '\x00', [@pad1, @pad1, @ra]}], @icmpv6=@ndisc_ra}}}}})
openat$speaker(0xffffffffffffff9c, &(0x7f00000000c0), 0x8000, 0x0)
open(&(0x7f0000000180)='./file0\x00', 0x80000000000206, 0x0)
socket$inet(0x2, 0x8003, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd, 0x0, 0x4}, 0x0, 0x0, 0x0)
mkdir(0x0, 0x0)
setreuid(0x0, 0xee01)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000002c0)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000000c0)={<r1=>0x0, <r2=>0x0}, &(0x7f0000000040)=0xc)
r3 = msgget$private(0x0, 0x397)
msgrcv(r3, 0x0, 0x0, 0x0, 0x0)
msgctl$IPC_SET(r3, 0x1, &(0x7f0000000340)={{0x80000001, r2, 0x0, r2, 0x0, 0x2, 0x9}, 0x7ff, 0x0, r1, r1, 0xffffffffffffffff, 0x7})


r0 = syz_open_pts()
r1 = syz_open_pts()
r2 = kqueue()
socketpair(0x0, 0x8000, 0x0, &(0x7f00000002c0))
openat$bpf(0xffffffffffffff9c, &(0x7f00000004c0), 0x500, 0x0)
kevent(r2, &(0x7f0000000140)=[{{r0}, 0xfffffffffffffff8, 0x81, 0x4, 0x93, 0x81}, {{}, 0x0, 0x0, 0x8, 0x0, 0x7}, {{r0}, 0xffffffffffffffff, 0x0, 0x40000000, 0x6}, {{r0}, 0x0, 0x0, 0x80, 0x0, 0xffffffffffff8000}, {{}, 0x7, 0x4, 0x0, 0x0, 0x1}, {{r0}, 0xfffffffffffffffe, 0x0, 0x0, 0x400, 0x3}, {{}, 0xffffffffffffffff, 0x0, 0x0, 0x8}], 0x200, &(0x7f0000000340)=[{{r1}, 0xfffffffffffffff9, 0x2, 0x1}, {{}, 0x0, 0x0, 0x40000000, 0x200, 0x9}, {{}, 0x6, 0xc0, 0x200ffffe, 0xfffffffffffffffc, 0x1000}, {{}, 0xfffffffffffffff9, 0x0, 0x5d19e6c3bb03b694}, {{}, 0xfffffffffffffffb}], 0x1, 0x0)
sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x20}, 0x4, &(0x7f0000000100), &(0x7f0000000040), &(0x7f0000000080), 0x0)


r0 = socket(0x11, 0x3, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x40, 0x0, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
dup2(r1, r0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, 0x0, 0x0)


sysctl$net_inet_carp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x4}, 0x4, 0x0, 0x0, &(0x7f0000000040)="e1000000", 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
syz_open_pts()
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000440)={0x2, &(0x7f00000000c0)=[{}, {}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4f}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8efdb4cf71c37082", &(0x7f0000000000)=0x2, 0x0, 0x37)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000100)=[{0x4d}, {0x14}, {0x6}]})
syz_emit_ethernet(0xe, &(0x7f00000000c0)=ANY=[])
setsockopt$sock_linger(0xffffffffffffffff, 0xffff, 0x80, &(0x7f0000000100)={0xff}, 0x8)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000080))
close(0xffffffffffffffff)
r2 = socket(0x800000018, 0x0, 0x0)
mknod(&(0x7f0000000040)='./file0\x00', 0x6000, 0xe02)
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000340)={0x0, 0x0, <r3=>0x0}, &(0x7f0000000300)=0xffffff44)
chown(&(0x7f0000000180)='./file0\x00', 0xffffffffffffffff, r3)
r4 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
pwritev(r4, &(0x7f0000000080)=[{&(0x7f00000003c0)="1f1d137fe265ecaee9385ff30becc172866b897ccbe0660621320a667005c376e0efc8744ca0d354f242b2d95da2f2523bfd671284a1ceabe322f148b0e098e9291cb0c301e358ea2d5e97ed4c78d22eb927464aef04e0204bcddb448baa36184cdafe0a38c7ac7400ee1b4c9626", 0x6e}], 0x1, 0x3)
syz_emit_ethernet(0x3e, &(0x7f0000000240)=ANY=[])
sysctl$kern(&(0x7f00000000c0)={0x1, 0x59}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1, 0x0, 0x37)
getrusage(0x0, &(0x7f0000000200))
sysctl$net_inet6_ip6(&(0x7f0000000040), 0x4, 0x0, 0x0, 0x0, 0x0)
preadv(0xffffffffffffffff, &(0x7f0000000000), 0x1000000000000098, 0x0)
execve(0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000000)={<r5=>0x0}, 0xc)
fcntl$setown(r0, 0x6, r5)


shmget$private(0x0, 0x3000, 0x0, &(0x7f0000fef000/0x3000)=nil)
shmat(0x0, &(0x7f0000001000/0x3000)=nil, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, 0x0)
getgroups(0x9a, 0xfffffffffffffffe)
unlinkat(0xffffffffffffffff, 0x0, 0x0)
sysctl$hw(&(0x7f0000000040)={0x6, 0x2}, 0x2, &(0x7f0000000080)="3b727a099addf9401e2f3166cdd29a3b66d196e1091d338a73239ce1d763b8", &(0x7f0000001080)=0x1f, 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000300)={0x20000316, &(0x7f00000000c0)=[{}, {0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x3e}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1, 0x0, 0x37)
r0 = semget$private(0x0, 0x1, 0x100)
semctl$SETALL(r0, 0x0, 0x9, &(0x7f0000000000)=[0x1, 0x4, 0x6529])
pwritev(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f00000005c0)="dc", 0x1}], 0x1, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r1 = open(0x0, 0x0, 0x0)
pread(0xffffffffffffffff, &(0x7f0000000040)="3cd15db7c30016", 0x50cc00, 0x0)
ioctl$WSDISPLAYIO_LSFONT(r1, 0xc058574e, &(0x7f0000000100))
sysctl$net_inet_udp(&(0x7f0000000000)={0x2, 0x4}, 0x2, 0x0, 0x0, 0x0, 0x0)
r2 = socket(0x18, 0x2, 0x0)
msgctl$IPC_STAT(0x0, 0x2, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x83fe})
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
setsockopt(r2, 0x1000000029, 0x3e, &(0x7f0000000000)="674cd6e5", 0x4)
writev(r2, &(0x7f0000000080)=[{0x0}], 0x1)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000002c0)={<r0=>0xffffffffffffffff})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x2, {0x2}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
sendmmsg(r0, &(0x7f0000000000)={0x0}, 0x10, 0x0)


r0 = socket$unix(0x1, 0x2, 0x0)
sendmsg(r0, &(0x7f0000000880)={&(0x7f0000000000)=@un=@abs={0x0, 0x0, 0x1}, 0x8, 0x0, 0x0, &(0x7f0000000980)=[{0x58, 0x1, 0x0, "17efd51edc01752cc8513840bb5c9fdb805e424664529c1738c3febfaca398b81ec7981eca22ff23f200a745f31d55b967300e5d20243d91af888d9b4872c18bf4"}, {0x198, 0x0, 0x0, "f351fe518620ba1ec0933d07222a353fef6b8b48192f3dc3f5f488ca5ef329494d2ca6d80435bb3cc514ba85bf8bb07d53686a3a0dca59360180ca5c46ef40e1209d41eca72a4884a515185357b5fa41edf1154b5c5fca8a2d128b72b9680511ca1fc5888f75c46264a3096b8f2867b82001f46ebd030a4520dde29069f1602e17002884bdd53df524e5e34c1da1b44b601e2837821e248d556ff925ae0e9f958f37e86d8980a0f2aa4abb28323a3d697ab28c576a42f9810494244ddce9ff9cd424c86301b18a0276e078d170f58d2dd606f0b487e39ca943ee8382bca235c0c704f5524858cdebf7231b3c5f43ad31d279334c078b4fbffec71047e60d5b1c7cf6062acd6e3232a8babaa98aba58a4ba4cb48fe17a4c7ef823d25913f7e515e0ef466a091d9958e9f35359c53f8251c29c319350eca54a232ff9ac6ee0c63daf199871e40032c135fc80ca734fa21effdc0e0e2aa5688dae6cbc1eb60ccde07b4033b1ef06ab9d2293824cc9d3064492406962db52d7a55395b7dd47457e0d1f"}, {0x20, 0x0, 0x0, "0f5db35e05f26636fb"}], 0x210}, 0x0)
ioctl$FIONBIO(r0, 0x8004667e, &(0x7f00000008c0)=0xb24)
execve(0x0, 0x0, 0x0)


sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b100050460000000000000000010000000000000cea10500fef900000000d3357ae320b37b673039d2d236073705ae04be38164991f7c8cf5f882b297be1aa5b236deb51e2f0ac7ebbc257699a5f139b672f4d335d223e7d026ba8af630037282102", 0x62, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x0, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b100050400000400000000000700", 0xe, 0x0, 0x0, 0x0)
r0 = socket(0x11, 0x3, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
sendto$unix(r0, &(0x7f0000000000)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000380)=[{0x3}, {0x81}, {0x8006}]})
syz_emit_ethernet(0x56, &(0x7f00000003c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000380), 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = dup(r0)
ioctl$BIOCSBLEN(r1, 0xc0044266, &(0x7f0000000100))
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
syz_emit_ethernet(0x2e, &(0x7f0000000200)=ANY=[])
kqueue()
syz_emit_ethernet(0x4e, &(0x7f0000000080)=ANY=[])
select(0x7, &(0x7f00000002c0)={0xfffffffffffffffc}, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000000)=[{0x1d}, {0x40}, {0x406}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x10, r0, 0x0)
ftruncate(r0, 0x8531)
r1 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r1, 0x0)
setrlimit(0x0, &(0x7f0000000980))


r0 = socket$unix(0x1, 0x2, 0x0)
close(r0)
socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x3c, &(0x7f0000000100)="03001a00", 0x4)


ioctl$WSMUXIO_LIST_DEVICES(0xffffffffffffffff, 0xc1045763, &(0x7f00000000c0)={0x0, [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {0x3, 0x4}, {0x1, 0x6}, {0x2, 0x7f}, {0x3, 0x6}, {0x0, 0x2}, {}, {}, {}, {}, {}, {0x0, 0xbf}]})
r0 = socket(0x18, 0x3, 0x0)
sendmmsg(0xffffffffffffff9c, &(0x7f0000000180)={&(0x7f0000000140)={&(0x7f0000000000)=@un=@file={0x0, './file0\x00'}, 0xa, &(0x7f00000000c0), 0x0, 0x0}}, 0x10, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x8080691a, 0x0)
munmap(&(0x7f0000384000/0x3000)=nil, 0x3000)
ioctl$FIONREAD(r0, 0x8080691a, &(0x7f0000000100))
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
truncate(0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
preadv(0xffffffffffffffff, 0x0, 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x5a}, 0x6, 0x0, 0x0, 0x0, 0x0)


mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x412dff)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
writev(r0, &(0x7f0000000080)=[{&(0x7f0000002540)="19", 0x1}], 0x1)


mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x32e6)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
select(0x40, &(0x7f0000000000), &(0x7f0000000040)={0xfffffffffffffffe}, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000380)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}], 0x1, 0x0}, 0x0)
close(r1)
syz_open_pts()


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r0, 0xc0206921, &(0x7f00000001c0))
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0206925, &(0x7f00000001c0))


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
bind$unix(r0, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sendmsg$unix(r0, &(0x7f0000000080)={0x0, 0x0, 0x0}, 0x0)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000080))
setitimer(0x0, &(0x7f0000001280)={{}, {0xfff}}, 0x0)
getitimer(0x0, &(0x7f0000000000))
geteuid()
getgroups(0x1, &(0x7f0000000140)=[0xffffffffffffffff])
r0 = geteuid()
r1 = semget$private(0x0, 0x4000000009, 0x82)
semop(r1, &(0x7f0000000340)=[{0x2, 0x8}], 0x1)
semop(r1, &(0x7f0000000140), 0x2aaaaaaaaaaaaddb)
semctl$SETALL(r1, 0x0, 0x9, &(0x7f0000000040)=[0x7ff, 0x1000])
semctl$SETALL(r1, 0x0, 0x9, &(0x7f00000001c0)=[0x7, 0x401, 0x95, 0x1, 0x5])
semop(r1, &(0x7f0000000080), 0x0)
r2 = getuid()
accept$unix(0xffffffffffffff9c, 0x0, 0x0)
mknod(&(0x7f0000000040)='./file0\x00', 0x6000, 0xe02)
open(0x0, 0x0, 0x0)
readv(0xffffffffffffffff, 0x0, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
r3 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(r3, &(0x7f0000000140)=[{0x0}], 0x1)
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f0000000240)={{0x21d, r0, 0x0, r2, 0x0, 0x188, 0x7e00}, 0x5, 0x8000000000000001, 0x10000000005})
getuid()
r4 = geteuid()
setreuid(0x0, r4)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000040), 0x0)
r5 = socket(0x0, 0x1, 0x0)
setsockopt(r5, 0x1000000029, 0x2f, 0x0, 0x0)
mmap(&(0x7f0000000000/0x4000)=nil, 0x4000, 0x1, 0x9412, 0xffffffffffffffff, 0x0)
semctl$IPC_STAT(r1, 0x0, 0x2, &(0x7f00000002c0)=""/116)
select(0x40, &(0x7f0000000040), &(0x7f0000000080), 0x0, &(0x7f0000000100))


r0 = open(&(0x7f0000001700)='./file0\x00', 0x70e, 0x0)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000200), 0x8000, 0x0)
ioctl$VMM_IOC_TERM(r1, 0x80045604, &(0x7f0000000240)={0x1})
mmap(&(0x7f0000ffc000/0x1000)=nil, 0x1000, 0x0, 0x10, r0, 0x1)
mprotect(&(0x7f0000001000/0x3000)=nil, 0x3000, 0x0)
socket(0x18, 0x3, 0x6)
madvise(&(0x7f00003e0000/0x1000)=nil, 0x1000, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
socketpair$unix(0x1, 0x2, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETF(r2, 0x80104267, 0x0)
socket$inet(0x2, 0x2, 0x0)
mlockall(0x0)
r3 = semget$private(0x0, 0x3, 0x2)
r4 = geteuid()
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000000)={0x0, 0x0, <r5=>0x0}, 0xc)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000040)={<r6=>0x0, <r7=>0x0}, 0xc)
semctl$IPC_SET(r3, 0x0, 0x1, &(0x7f0000000080)={{0x1, r4, r5, r7, 0xffffffffffffffff, 0x10, 0x3}, 0x101, 0x8, 0x4})
r8 = getuid()
r9 = msgget$private(0x0, 0x200)
msgctl$IPC_SET(r9, 0x1, &(0x7f0000001840)={{0x4, r7, r5, 0x0, r5, 0x22, 0x7ffc}, 0x200000006, 0x4, 0x0, r6, 0x6, 0x8, 0x7fffffff, 0x9ed8})
mmap(&(0x7f00007c7000/0x2000)=nil, 0x2000, 0x3, 0x5012, 0xffffffffffffffff, 0x2)
preadv(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
madvise(&(0x7f00000ab000/0x800000)=nil, 0x800000, 0x6)
fchown(0xffffffffffffffff, r8, r5)
kqueue()


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket(0x2, 0x3, 0x0)
r2 = dup2(r1, r0)
open(&(0x7f0000000080)='./file0\x00', 0x100, 0x80)
r3 = dup(0xffffffffffffffff)
setsockopt$inet_opts(r3, 0x0, 0x13, &(0x7f0000000040), 0x0)
ktrace(0x0, 0x4, 0x0, 0x0)
syz_open_pts()
writev(0xffffffffffffffff, 0x0, 0x0)
mkdir(0x0, 0x0)
socket$inet6(0x18, 0x3, 0x0)
setsockopt$inet6_MRT6_ADD_MIF(r3, 0x3a, 0x66, 0x0, 0x25)
mkdir(0x0, 0x0)
unveil(0x0, 0x0)
r4 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x880, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(0xffffffffffffffff, 0x80085761, &(0x7f0000000180)={0x1, 0x8})
fcntl$setown(r4, 0x6, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x1, &(0x7f0000000600)="ee08665d19ac14d5e5134876f197a7728420aef6171504b1", 0x18)
socket(0x6, 0x8000, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)


open(&(0x7f0000000280)='./file0\x00', 0x615, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000), 0x10)
r1 = dup(r0)
listen(r1, 0x0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
accept$inet(r0, 0x0, 0x0)
r3 = socket(0x2, 0x1, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)
r4 = dup(r3)
sendto$inet(r4, &(0x7f0000000240)="03c019b7e2399b388d3cc45f01364c934fe5a3d4c1fbf21dc5dab6090e154d84", 0x20, 0x0, 0x0, 0x0)
getsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
write(r3, &(0x7f0000000040)="04", 0xff9a)
syz_emit_ethernet(0x12a, &(0x7f0000000240)=ANY=[])
symlinkat(0x0, 0xffffffffffffffff, 0x0)
symlinkat(&(0x7f0000000dc0)='./file0\x00', 0xffffffffffffffff, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1023, &(0x7f0000000080), 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000340)={0x3, &(0x7f0000000180)=[{0x44}, {0x4}, {0xe6}]})
syz_emit_ethernet(0x4e, &(0x7f0000000140)=ANY=[])


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x100000000000000, 0xffffffffffffffff})
r0 = socket(0x18, 0x2, 0x7)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000004c0)=[{0x30}, {0x44, 0x0, 0x0, 0x2}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])
sendmsg(r0, 0x0, 0x4)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
socket$inet(0x2, 0x2, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000380), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
lseek(r2, 0x0, 0x2)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, 0x0)
openat$vnd(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r3=>0xffffffffffffffff})
r4 = socket(0x2, 0x3, 0x0)
dup2(r3, r4)
setsockopt$sock_int(r4, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
write(r4, &(0x7f0000001680)="04bdfa5d1d2873c63e3534825ba166e2fea9aec43050006123339a346f731573d8d508753f95b7688ad48b8cf6bbca325cebc37fc4e1dd543dbe2da6dd", 0x1001c)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000600), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000680)={&(0x7f0000000640)=[{}, {0x100}], 0x2})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000600)={0x3, &(0x7f0000000140)=[{0x6c}, {0x60}, {0x812e}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000700)=[{0x2}, {0x30}, {0x6, 0x0, 0x0, 0xfffffffc}]})
write(r0, &(0x7f0000000740)="76e5dead6f01f8607d2100000063", 0xe)


socket(0x2, 0x1, 0x0)
r0 = socket$inet(0x2, 0x2, 0x0)
getsockopt$inet_opts(r0, 0x0, 0x1d, 0x0, 0x0)
msgget(0x3, 0x30)
truncate(&(0x7f00000001c0)='./file2\x00', 0x7fffffffffffffff)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0xd, &(0x7f0000000000)="ea0000ee7f000801", 0x8)


getgid()
mknod(&(0x7f00000000c0)='./file0\x00', 0x2000, 0x40000802)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000540)=0x8)
getsockname(r0, &(0x7f0000000240)=@un=@file={0x0, ""/238}, &(0x7f0000000200)=0xf0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x16, &(0x7f0000000000), 0x0)
open$dir(0x0, 0x40000400001803c1, 0x0)
r2 = getuid()
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f000002f000/0xd000)=nil}, {&(0x7f0000060000/0x2000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000ffb000/0x4000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil, 0xffffffffffffffff}, {}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {0x0, 0x0, 0x7fffffffffffffff}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000053000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil, 0xfffffffffffffffd}], './file1\x00'})
mknod(0x0, 0x0, 0x0)
r3 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r3, 0xc0384600, &(0x7f00000000c0)={&(0x7f0000000000)='./file0\x00', 0x4, 0x0})
getgroups(0x9, &(0x7f00000001c0)=[0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff, <r4=>0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff])
chown(&(0x7f0000000140)='./file1\x00', r2, r4)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105727, &(0x7f0000000000)={&(0x7f0000000340)=[{}, {}, {}, {0x0, 0xfffffffc}], 0x4})
syz_emit_ethernet(0x42, &(0x7f0000000140)=ANY=[])
syz_emit_ethernet(0x126f, &(0x7f00000000c0)=ANY=[@ANYBLOB="aaaaaaaaaaaa00000000000086dd609ded1a12390000c4a4e3434e58d025a6a8a81cf312b8befe8000000000000000000000000000aa00030000000000000101000101000401000401000103000000000100010200000000c7ab6f1eba08bf03d1805fce0ef2ab82f4a065245eccda108bec7cb23f632c993265a4cefeb77b1406d562a47d4b0054943553278b519ed107f62b5c352f8e68d83c1fd85b8e1083556d7fa2fc09a3e823fa940de6ef1b18ddb2a2dba0d2d9c1b44b20ed3a932a2c47f4f4d3e34ea1b67a607001a4541a87d5d347b5049b3444dc2b7abe3499079a5701e88493acb2eb1808e8b1f74311083f93341607915aa46325934e81b672d809cb6bc5f3d64480ba4db4432a67c2548e259fe7831f7c6dfe"])
sysctl$kern(&(0x7f0000000000)={0x1, 0x45}, 0x3, 0x0, 0x0, &(0x7f0000000040)="3944eb3f115f79037148fa0ddc3adf427d080000006ceb99ea265a4a19b2e72fd9cbb4db32e128db447c5e01000080d5fa1d9213ebefff7ad23b886bf325280bc040eac897a0d4168da6b6b75d146499e1ee9ddeb2d68e8d011a", 0x5a)


sysctl$kern(&(0x7f0000000180)={0x1, 0x58}, 0x2, &(0x7f0000000140), 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000400)=[{0x50}, {0x3}, {0x812e}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


sysctl$vm(&(0x7f0000000200)={0x2, 0x9}, 0x2, &(0x7f0000000480)="71a09787", &(0x7f0000000340)=0x4, 0x0, 0x0)


sysctl$hw(&(0x7f0000000040)={0x6, 0x18}, 0x2, &(0x7f0000000080)="c7cc1468", &(0x7f00000000c0)=0x4, &(0x7f0000000340), 0x1)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000004c0), 0x10202, 0x0)
writev(r0, &(0x7f0000000240)=[{&(0x7f0000000100)="058c4cc154b5895edf170affb44c37b4e96eb0aa265b33a650172f5b1d2760b1cc8ab19c57387cc77e393974", 0x2c}], 0x1)


shmget$private(0x0, 0x2000, 0x0, &(0x7f0000ffb000/0x2000)=nil)
r0 = shmget$private(0x0, 0xc00000, 0x0, &(0x7f0000400000/0xc00000)=nil)
shmctl$IPC_STAT(0x0, 0x2, 0x0)
openat(0xffffffffffffffff, 0x0, 0x0, 0x0)
fcntl$setstatus(0xffffffffffffffff, 0x4, 0x0)
r1 = openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mquery(&(0x7f000094b000/0x4000)=nil, 0x4000, 0x2, 0x10, r1, 0x380000)
ioctl$BIOCGRTIMEOUT(0xffffffffffffffff, 0x4010426e, 0x0)
shmctl$IPC_RMID(r0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f00000000c0)=[{0x1d}, {0x3}, {0x6}]})
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


open(&(0x7f0000000200)='./file0\x00', 0x80000000000206, 0x0)
r0 = socket$inet(0x2, 0x8003, 0x0)
r1 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r1)
setsockopt(r0, 0x0, 0x7, &(0x7f0000000340)="15337ac0", 0x4)
syz_emit_ethernet(0x2a, &(0x7f0000000040)={@broadcast, @broadcast, [], {@arp={0x8035, @ether_ipv4={0x1, 0x800, 0x6, 0x4, 0x0, @empty, @empty, @broadcast, @remote={0xac, 0x14, 0x0}}}}})
syz_emit_ethernet(0x2a, &(0x7f00000002c0)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, @multicast2}, @icmp=@echo}}}})
recvmmsg(r0, &(0x7f0000000040)={0x0}, 0x10, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000280)=[{0x25}, {0x54}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000300)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{}, {0x3c}, {0x6}]})
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[])


r0 = openat$pf(0xffffffffffffff9c, &(0x7f0000001440), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
fcntl$lock(r0, 0x7, &(0x7f0000002640))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x7c}, {0x5c}, {0x812e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


sysctl$vm(&(0x7f0000000000)={0x6, 0x5}, 0x2, &(0x7f0000000040)="279857da", &(0x7f0000000080)=0x4, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setrlimit(0x2, &(0x7f0000000080)={0x60000000, 0x60000000})
clock_settime(0x100000000000000, &(0x7f0000000040))


r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0x33, &(0x7f0000000000)="ebffcbff", 0x4)


r0 = socket(0x2, 0x1, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
getsockopt$sock_cred(r1, 0xffff, 0x1022, 0x0, 0x0)


connect$unix(0xffffffffffffffff, &(0x7f0000000000), 0x1)
r0 = socket(0x2, 0x3, 0x0)
connect$unix(r0, &(0x7f0000000280)=@abs={0x1, 0x0, 0x3}, 0x8)
bind(r0, &(0x7f0000000000), 0x10)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000080)={0x0, <r1=>0x0, <r2=>0x0}, 0xc)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{0x30}, {0x7c}, {0x16}]})
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f0000000080)=ANY=[])
r4 = semget$private(0x0, 0x4000000009, 0x82)
semop(r4, &(0x7f00000000c0)=[{0x1, 0xffff, 0xe5ce97ab354d96be}, {0x4, 0x4, 0x1800}, {0x3, 0x0, 0x1000}, {0x2, 0x6}], 0x4)
open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETF(r5, 0x80104267, &(0x7f0000000140)={0x2, &(0x7f0000000100)=[{0x3d, 0x0, 0xff}, {}]})
r6 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r6)
connect$unix(r0, &(0x7f00000001c0)=@abs={0x0, 0x0, 0x2}, 0x8)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000380)={0x0, 0x0, &(0x7f0000000840)=[{0x0}, {0x0}], 0x2, 0x0, 0x0, 0x400}, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000200)={0xffffffffffffffff, <r7=>0xffffffffffffffff})
sendmmsg(r7, &(0x7f0000000240)={0x0}, 0x10, 0x0)
semctl$SETALL(r4, 0x0, 0x9, &(0x7f0000000040)=[0x0, 0x1000])
semop(r4, &(0x7f0000000180)=[{0x1, 0x1, 0x1000}, {0x2, 0x4, 0x1000}], 0x2)
r8 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r8, 0x80105728, &(0x7f0000000100)={&(0x7f00000000c0)=[{0x24, 0x7ff}], 0x1})
semctl$SETALL(r4, 0x0, 0x9, &(0x7f0000000240)=[0x7, 0x4, 0x7])
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000380)={{0x9, r1, r2, r1, r2, 0x100, 0x5}, 0x2f8, 0xffffffffffffffff, 0x7})
connect$unix(r0, &(0x7f0000000100), 0x10)
sendto$inet(r0, 0x0, 0x0, 0x0, 0x0, 0x0)


r0 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
syz_emit_ethernet(0x3a, &(0x7f0000000000)=ANY=[@ANYBLOB="ffffffffffffffff"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r0, &(0x7f0000000000), 0x10)
setsockopt$inet_opts(r0, 0x0, 0x1, &(0x7f0000000440)="9876d692a3ef9c7ab923a2f0", 0xc)
write(r0, &(0x7f0000000240)="14bdfa5d1d34e2fecb284a6498307dcda9aec43050036123339a346f737850551408753f95b7688ad4c4e1dd5489e7bafc58d3e5823757ae8b630719ef187ccad995f13dbe19a6dd4e6902bd8297b0799b426aabe9fad9db6996571c6d9f8bb5d542c2148aa42be940970fe88d34d8f99afe7e7820237400000000008000000100"/138, 0xfc7e)


socket$inet(0x2, 0x0, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VMM_IOC_RESETCPU(r0, 0x82405605, &(0x7f0000000280)={0x2, 0x0, {[0x0, 0x0, 0x0, 0x858a], [0x2, 0x0, 0xb, 0x334], [0xffffffffffffffff], [0x0, 0x0, 0xfffffffffffffffe]}})
socket(0x0, 0x0, 0x0)
r1 = dup(0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x20, 0x3, 0x3)
ioctl$FIONREAD(r2, 0xc0206921, &(0x7f00000001c0))
openat$zero(0xffffffffffffff9c, 0x0, 0xe8, 0x0)
r3 = socket(0x18, 0x3, 0x0)
setsockopt(r3, 0x1000000029, 0x24, &(0x7f0000000040)="e81e1a97f45a60ef4b4e150cd4", 0xd)
r4 = syz_open_pts()
close(r4)
msgget$private(0x0, 0x342)
dup(0xffffffffffffffff)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
socket(0x2, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
semctl$SETALL(0x0, 0x0, 0x9, 0x0)
ioctl$VMM_IOC_CREATE(r1, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000ffd000/0x1000)=nil, &(0x7f00006e1000/0x3000)=nil}, {&(0x7f0000a29000/0xc000)=nil, &(0x7f000041b000/0x4000)=nil}, {&(0x7f0000acf000/0x11000)=nil, &(0x7f00007a5000/0x3000)=nil, 0x20000000000000}, {&(0x7f0000554000/0x4000)=nil, &(0x7f000042d000/0x4000)=nil, 0x9}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil, 0x20}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000a64000/0x1000)=nil, 0xfffffffffffffffe}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil}, {&(0x7f0000bb2000/0x4000)=nil, &(0x7f0000312000/0x3000)=nil}, {&(0x7f0000a31000/0x3000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000628000/0x2000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f000032e000/0x800000)=nil, &(0x7f0000ffe000/0x1000)=nil, 0x8004}, {&(0x7f0000015000/0x3000)=nil, &(0x7f000015e000/0x2000)=nil}, {&(0x7f0000893000/0x1000)=nil, &(0x7f0000487000/0x2000)=nil, 0x400000000000000}, {&(0x7f000052f000/0x2000)=nil, &(0x7f0000ff3000/0x2000)=nil}], './file0\x00'})
socket$inet(0x2, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000300)=[{&(0x7f0000000140)="f005c71031c1c5f421277b09000000000000007a091a2f47be787538ec7a89ec5ed66daa731ddc384ecc690869a0aa2266affdf772d7a360ee0f15fa664f557bb45071fe9b6d9d28e6e2589000f6a64f370b9e336987d77b38f7aada5309e46a81e0e2efa087aa9f5f89934fdbd2ed96e7234b8972b273e810ca9962a8f461d3a05711a63027321ff62c", 0x8a}], 0x1)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000002c0)={<r5=>0xffffffffffffffff})
ioctl$FIONREAD(r5, 0xc0106924, &(0x7f00000001c0))


msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x8}})
r0 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
sendmsg(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, 0x0, 0x10}, 0x0)
r1 = socket(0x800000018, 0x1, 0x0)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0x9, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
dup(0xffffffffffffffff)
ioctl$BIOCIMMEDIATE(r0, 0x80044270, &(0x7f00000000c0)=0x4)
select(0x40, &(0x7f00000001c0)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
select(0x40, &(0x7f0000000000)={0xa0cb}, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000000)=[{0x14}, {0x3c}, {0x6}]})
syz_emit_ethernet(0x1019, &(0x7f00000000c0)=ANY=[])


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
r1 = socket(0x1, 0x1, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x1928, 0x0)
r2 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r2, 0x0)
dup2(r0, r1)
setsockopt(r1, 0x1000000000029, 0x9, &(0x7f0000000040)="ca5e1885", 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000400), 0x0, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000500)={0x2, &(0x7f00000004c0)=[{}, {0xc894}]})


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffc000/0x3000)=nil, 0x1000}, {&(0x7f0000ff9000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffc000/0x1000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f0000ffc000/0x1000)=nil}, {&(0x7f0000003000/0x2000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x2000)=nil}], './file0\x00'})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r0, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0, 0x1000})
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x0, 0x1010, 0xffffffffffffffff, 0x0)


sysctl$kern(&(0x7f0000000080)={0x1, 0x3e}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)


setreuid(0x0, 0xee01)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000380)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000280)={<r1=>0x0}, &(0x7f0000000340)=0xc)
setpgid(r1, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000040)={0x7fff, 0x0, 0x80000401, 0xffdfff8c, "1b91a5d81c727c6600"})
writev(r0, &(0x7f00000003c0)=[{&(0x7f00000009c0)="471e49aab0fd752532784bf2515fa242320b4a6e6543ffda060eb842b843d370b936ddaa7f71a0a0c4074da827c862a93983c361dc12dc50305653dd84a6adfc8761f897b60c4dee402807473103485b4475c657ae5428aa89543eec1819c76b9eb1e5c1848e49a2a588ed0f6ac77d2106b8ed9b8e3bf7a033cdd96085e372fde5a0d0e2fa622a7e28febd0934ab925ca1", 0x91}], 0x1)


r0 = socket(0x18, 0x3, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000029, 0x27, &(0x7f0000000040)="5ab7736a", 0x4)
r1 = socket(0x18, 0x1, 0x0)
shutdown(r1, 0x2)
select(0x40, &(0x7f0000000180), &(0x7f00000001c0)={0xff}, 0x0, 0x0)
read(r0, &(0x7f00000000c0)=""/194, 0xc2)
setsockopt$sock_int(r0, 0xffff, 0x1003, &(0x7f00000001c0)=0x8, 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
open(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x2}, {0x3d}, {0x16}]})
write(r0, &(0x7f0000000540)="76e5dead6f01f8607d2100000063", 0xe)


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000001c0)={0x2, &(0x7f0000000000)=[{}, {0x84}]})
r0 = socket(0x18, 0x2, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)='\t\x00\x00\x00', 0x4)
r1 = dup(r0)
setsockopt(r1, 0x1000000000029, 0xd, &(0x7f0000000000)="ffdaff10aac6a28ac93e2eddc45c8454e486f64c", 0x14)


r0 = socket(0x11, 0x3, 0x0)
connect$inet(r0, &(0x7f0000000040)={0x2, 0x3}, 0xc)
socket(0x2, 0x1, 0x0)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000001140), 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r1, 0xc2585601, &(0x7f0000001180)={0xdead4110, 0x0, [{&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffa000/0x2000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffa000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff9000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000ff9000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}], '.\x00'})
socket(0x18, 0x3, 0x0)
socket(0x1, 0x1, 0x0)
socket(0x2, 0x3, 0x0)
pipe(&(0x7f00000000c0)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(0xffffffffffffffff, 0xc010570d, &(0x7f0000000080)={0xa, &(0x7f0000000180)=[{0x7, 0x101, 0xf800, 0x8, 0x3}, {0xfff7, 0x3, 0xfff8, 0x2b6, 0x5}, {0x9, 0x101, 0xe904, 0x800, 0x800}, {0xd90, 0xff, 0xfff, 0x7fff, 0x2}, {0xfffa, 0x3ff, 0x9, 0x8, 0x8000}, {0x81, 0x2, 0x400, 0x7, 0xa6}, {0x8, 0x5, 0xfff9, 0x0, 0xfff}, {0x80, 0x4, 0xff00, 0x3f, 0x9}, {0xffff, 0x9, 0x8a97, 0x3f, 0x8001}, {0x44a0, 0xfff, 0x0, 0xb5af, 0x2}]})
poll(&(0x7f0000000000)=[{r2}], 0x1, 0x0)
dup2(r2, r3)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)='\x00', 0x1}], 0x1)
r4 = socket$inet(0x2, 0x2, 0x0)
r5 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r5, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
dup2(r5, r4)
setsockopt$inet_opts(r5, 0x0, 0xd, &(0x7f0000000240)="ea08000000000000", 0x8)


r0 = socket(0x11, 0x3, 0x0)
setsockopt(r0, 0x11, 0x2, &(0x7f0000000340), 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x205b9a)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$FIONREAD(r0, 0x4004667f, &(0x7f0000000200))


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x0, "010000000000000000001339e13600005003005b"})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11, 0x0, 0x5}, 0x6, &(0x7f0000000080), 0x0, 0x0, 0x42)


setrlimit(0x8, &(0x7f0000000980)={0x46, 0x56})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047460, &(0x7f00000000c0)=0x9)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000180)={0x0, 0x0, 0x8001f7e, 0x808, "e7303483ef00000000000000000000000000ff00"})
writev(r0, &(0x7f0000000080)=[{&(0x7f0000000100)='>', 0x1}], 0x1)


kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f00000001c0)={0xc8, 0xffffffffffffffff})
r0 = kqueue()
kevent(r0, &(0x7f0000000000), 0x1ff, 0x0, 0x89c, 0x0)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x80206979, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000003c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000240)=[{0x4d}, {0x1c}, {0x206}]})
syz_emit_ethernet(0xe, &(0x7f0000000140)=ANY=[])


r0 = open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
r1 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
writev(r1, &(0x7f0000000340)=[{&(0x7f0000000000), 0x2cfea}], 0x1000000000000013)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x3, 0x10, r0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x41000}, {}, {0x0, &(0x7f0000002000/0x2000)=nil}, {}, {&(0x7f0000134000/0x4000)=nil, &(0x7f00001fb000/0x3000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {0x0, &(0x7f0000086000/0x3000)=nil}, {0x0, &(0x7f00001f0000/0x4000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f00001d5000/0x2000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {0x0, &(0x7f0000092000/0x3000)=nil}], './file0\x00'})
r2 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r2, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0})
sysctl$kern(&(0x7f00000000c0), 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0xff0a, 0x0, 0x37)


syz_open_pts()
poll(0x0, 0x0, 0x0)
syz_open_pts()
mknod(&(0x7f0000000000)='./file0\x00', 0x6000, 0xe02)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x0, 0x11, r0, 0x0)


semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x101}})
r0 = socket(0x1, 0x1, 0x0)
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x1000000029, 0x37, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
dup2(r1, r0)
ioctl$FIONBIO(r1, 0x8004667e, &(0x7f0000000080))
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


write(0xffffffffffffffff, 0x0, 0x0)
r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
acct(&(0x7f0000000140)='./file0\x00')
pwritev(r0, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg$unix(r1, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="28000000ffff000001"], 0x28}, 0x0)
recvmmsg(r0, &(0x7f0000000040)={0x0}, 0x10, 0x0, 0x0)
recvmsg(r0, &(0x7f0000000580)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000001940)=""/137, 0x89}], 0x1, 0x0}, 0x40)


setrlimit(0x8, &(0x7f0000000980)={0x7})
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sysctl$net_inet_esp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
setrlimit(0x3, &(0x7f00000001c0)={0x3, 0x1})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000180)={0x3, &(0x7f0000000700)=[{0x1c}, {0x81}, {0x6}]})
write(r1, &(0x7f00000002c0)="0000003171f6b2b6a767df38ab0cb405a59e41f361b1dc624a493871dbc9ec07257497", 0x23)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r2 = socket(0x18, 0x3, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r2, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
sendmsg$unix(r2, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x9}})
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206923, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
syz_emit_ethernet(0x26, &(0x7f00000001c0)=ANY=[])


r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
getpid()
ktrace(&(0x7f00000002c0)='./file0\x00', 0x0, 0x40001220, 0x0)
ftruncate(r0, 0x8)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f0000000300)={0x10, 0xffff, [{&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffc000/0x1000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil, 0x5}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil, 0x7ff}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff7000/0x9000)=nil, &(0x7f0000ffc000/0x4000)=nil, 0x80000001}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000ffc000/0x1000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ff6000/0x3000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffa000/0x1000)=nil}, {&(0x7f0000ff8000/0x1000)=nil, &(0x7f0000ff5000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000fff000/0x1000)=nil, 0x3}, {&(0x7f0000ff4000/0x3000)=nil, &(0x7f0000ff9000/0x1000)=nil, 0xc00000000}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ffb000/0x1000)=nil, 0x9}, {&(0x7f0000ff3000/0x4000)=nil, &(0x7f0000ff3000/0x4000)=nil}, {&(0x7f0000ff4000/0x1000)=nil, &(0x7f0000ff6000/0x2000)=nil}], './file0\x00'})
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000000)={0x2, &(0x7f0000000040)=[{}, {0x8106}]})
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
open(0x0, 0x615, 0x0)
ktrace(0x0, 0x0, 0xd27d43220c7df9b, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
r2 = kqueue()
kevent(r2, 0x0, 0x0, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x2, 0x0)
syz_emit_ethernet(0x32, &(0x7f0000000200)=ANY=[])
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f00000000c0)={0x6, &(0x7f0000000080)=[{0x34, 0x0, 0x0, 0x7}, {0x5}, {0x8706}, {0x0, 0x7, 0x0, 0x8}, {0x5, 0x81, 0x5, 0x8}, {0x1f, 0x0, 0xff, 0x5}]})
r4 = socket$inet(0x2, 0x1, 0x0)
setsockopt$sock_timeval(r4, 0xffff, 0x1006, &(0x7f0000000080)={0x0, 0x4}, 0x10)
getsockopt$sock_timeval(r4, 0xffff, 0x1006, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000300)=ANY=[])
clock_gettime(0x0, 0x0)
madvise(&(0x7f0000ffc000/0x4000)=nil, 0x4000, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000040)={0x7, 0x2, 0x1}, 0x3, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x31}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0xfffffffffffffda3)


mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x5d4a)
r0 = open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
r1 = getpid()
fcntl$setown(r0, 0x6, r1)
fcntl$setown(r0, 0x6, 0x0)


poll(0x0, 0x0, 0x87e)
open(0x0, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
execve(0x0, 0x0, 0x0)


sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f00000001c0)="55f8f5782087a072a82ec35f78d14780f518", 0x12)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x8080691a, &(0x7f00000001c0))


r0 = open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
sendmsg(0xffffffffffffffff, 0x0, 0x0)
r1 = syz_open_pts()
syz_open_pts()
ftruncate(r1, 0xfffffffffffffff8)
accept(0xffffffffffffffff, 0x0, 0x0)
mmap(&(0x7f0000116000/0x4000)=nil, 0x4000, 0x1, 0x1012, r0, 0x40000)
r2 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
ftruncate(r2, 0x8531)
ioctl$BIOCPROMISC(r2, 0x20004269)
setrlimit(0x6, &(0x7f00000000c0))
open(0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000132000/0x3000)=nil, &(0x7f00000a0000/0x1000)=nil, 0x80400000}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f0000ff3000/0xa000)=nil, &(0x7f00001f0000/0x1000)=nil}, {&(0x7f00001f0000/0x1000)=nil, &(0x7f000007c000/0x2000)=nil}, {&(0x7f0000132000/0x4000)=nil, &(0x7f00000b2000/0x1000)=nil}, {&(0x7f000008a000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {0x0, &(0x7f000002a000/0x3000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000e58000/0x4000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil}, {&(0x7f0000091000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000001000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000132000/0x1000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000008a000/0x1000)=nil}, {0x0, &(0x7f0000092000/0x3000)=nil}], './file0\x00'})
r3 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000800), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r3, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0})


open$dir(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r0)
socketpair(0x1, 0x1, 0x0, &(0x7f0000000140))
pipe(&(0x7f00000001c0))
writev(0xffffffffffffffff, &(0x7f00000002c0)=[{0x0}], 0x1)
r1 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r1, 0x0)
r2 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r2, 0x8020697a, &(0x7f0000000100))


syz_extract_tcp_res$synack(0x0, 0x1, 0x0)
syz_emit_ethernet(0x12e, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x120}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x0, {[@generic={0x0, 0xd, "96c729637cae4fa49c1558"}, @sack_perm={0x4, 0x2}, @sack={0x5, 0xa, [0x0, 0x0]}]}}, {"d1c2f0bfe2d0786ca28e44289f59aba04d62ff16e6bb47f1cd981d0cf5f225560531db5a3a6c3cb3d5ac50e0eec7423f3ef5e3c4a13f81f14f843a32b529e4649b57d581159522ddf03a6cabf358af4e1ae7ab79a9aac6417859ae29d8de08ba3da1e6387381a61f166b78d7ae58ccd15a08555c8e7db3e261cbba4f565ff3567edfcacd1a43a2f80b44a3727c2f46723f3826d9842357f4d467cb2e24ed586547d107e74cfe46502dde741762fe8ad6742200cf5fd16fcdadae4fd744b730286383e0444647e948151cb63c5c12b79f75a37762e3f013f189799eb6"}}}}}})
symlinkat(0x0, 0xffffffffffffff9c, &(0x7f0000000140)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/file0\x00')
open(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
r1 = socket(0x18, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


open(0x0, 0x0, 0x0)
r0 = dup(0xffffffffffffffff)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000040), 0x0)
ktrace(0x0, 0x0, 0x0, 0x0)
syz_open_pts()
writev(0xffffffffffffffff, 0x0, 0x0)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x3a, 0x66, 0x0, 0x25)
mkdir(0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
syz_emit_ethernet(0x56, &(0x7f0000000340)=ANY=[])
unveil(0x0, 0x0)
r2 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x880, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x10, 0x0)
r3 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000140), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r3, 0x80085761, &(0x7f0000000180)={0x1, 0x8})
fcntl$setown(r2, 0x6, 0x0)


mprotect(&(0x7f0000ffc000/0x2000)=nil, 0x2000, 0x1)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f0000000100)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x4, 0x0, 0x0)
setreuid(0x0, 0xee01)
r2 = fcntl$dupfd(r0, 0x0, r1)
r3 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x200000000000c, &(0x7f0000000080)="eaef125c00000000", 0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt$inet_opts(r3, 0x0, 0x9, &(0x7f0000000240)="ea000001", 0x4)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x3)
r4 = semget$private(0x0, 0x2, 0x110)
openat$tty(0xffffffffffffff9c, &(0x7f00000000c0), 0x200, 0x0)
write(r2, &(0x7f0000001740)="6bcfa4b9881483a90b39b3d69b291d52febf872310aaa4a2e578b500e36c06a801b9a1b1b0b3f59f4d5c5ac74912174aba1cf8e255ba77ab172e180d8bb1244819f4cbd4b890f9f315b41d033489ac5c4ed4615f3ec975c8fc24c1bc448c343e1c19739fa2c68cbc0e21f289ffda3f998a9abacc2c720876300a6ecbceb1c58d8c7e7c5eb2ecc8721dc51f6cedaeeacce5b5ed4c899d1c7cfbafd9c4a60f9d5895f761f7b8b324b3da1c55fa5af4310804297391416570e18b94a3847d35995834ee06640fd366081b288c7516fe585f21d763a8775c3d50c4f9263d0eeb9ff64f99cdca2aa53b7f7e93fc53967a95ce6eb378bbe9626e39af4ef39aacf80f1401259138e04360ea5509d8927f26a95b449009ed1aa610a7e179a2f335bf32a97c742c32f4fd73d5258aa2d133eb3d16e72b7b610d3944f8f56de83615c34a486679dd0d57beb341f6aafd300c1b1d758f1137a0d309b0d3dd4b8bfbc16c7cab9826d4c1ee46845c44d8995b2ac3c83dd18172d29a39ebecfe3fe41c4a75d614b87f54d4cdf9cb23974af98c91a20cbc76c4805b59139819e2dc728571d19812e1594babf4bfe8a5029188eff1b8382c9ea0aeb6d76830ecdc19ce585905b63f45e8c90b510393279580a3c23287b3927e2384f7ff6d40b38ae2ce662f404556d71097c56ede95cbe17e6495749ccb2d15095d67f5c7f7aa3049b1948f60c00d8c82e3d688374e65f214c4320fae37fc3ce4f8c9197e1c0ffe13cb366a41dab2037bd9ffe88b6b6d97dbab48bb5c043199b918f67e3dffe6aadb890a8b7444398f9d3e0ae27c7f70d343dd465c505b464813b339cba541257dee3c6c572685894534cabfb457b2bc0c90222625dfbe7a6a204ae56c92e869d4fad87dc7316bc9f67333228690d8384859072d2e61bf9031b161a98e45a5e351b058853eb5eb25b0419939ec5307aeceffe0a60f1e2ee7e642b889746987e4cac34ecd7b25f754451140517d64253e0dcea3cd32989f41daffb5f67d5979c332044b7174f7144011fa8137e3c7df5d79aa4ebc141a0c2a0bc55c21638a5b917bba420aa411f461257601161a1a7ad1c785440c88c069c4360014253bf919daf995984167a9066ceb4248089d808637378a88e234c2a1fb896624515c25db2f67be18ba345a5353cb6784429bb9bd7e79a72f1f852143b2ec0858276d51b52ebfc7dd893e6b655d6bda4b937c2c8f962f5680bc920082ca194e22e465c4fe9435af8457e558893bee96523ee2df670df477cb0c68054853f572d4405ccb89cda6318f1cf078aa250a0ebfb96842869c8d4fe064a05c2b7b36e7e16d439c27e4f959fba2138bc9c60dbb04a7d0f9c5ccbc641f79904362c9d5b7e4db8a6850247ef1eaee4209ad58c02ed482f0497d110d2b90dc1481b38a059256db4a7ce1c23aeb2fbf8ead2ced84567050e04b305d2203aa33c3dd3e9302d32dd87f4b0756eb95dd9d123f00afad000b6628ce20ae5a9c58cbc81b3c8590703a4775dd33111a06f1b8227918790c212b9330f2f0bcaecc538d56ff88685d29ce79099364edc82b3bbf80452ed035d0dee05fbbb7a74383f9ec377668a14163a46412983b8ea9fb8cebfe6cb38545f34e0a6fd1329670e1f73fb4ea8922f4078dd07ce1c612e97d825780ad3fd7f0337db7bcdc3c5c108477eb6d4cbef239bd478a5ea968048acabb378b26e570af01a795c5f55834741b802081d20534e757a0713ab8629ac795e1e7aafc0d593c08d96b6b62a1997d851f1850029ade0922d863c8952dcfc265b1ce92ffa664cb9fcb422f522aafc11a923eddbc9412303de0e5ba682ffa2071d12559ba3183a54224aa3da58915248f631036b180dbae63f689c0a29152b2a60ecdc2dd5c4d8012a71d0f553bacbb68c206d22fa3243e68428f1d8b846c77f1d7f89f4b61addf5e40e99484652b730d37c47fe90a65d04af519d97896b03ddcc561963ee353e48a6b41e499d0721832ddc0ad9f683dec6a45ab2f4b019a54889b2c99073e558a784a28893a603fb9189c0778c35f2cdf495bea08720bfb23ed0db657d2a92acd8551c3b7ee40985a0a874d380df0ffbfd1e50c5ac38a8de3f87366780b0df3ca39968251a1c6571192a14aecf34f02cc11483636f43047cb0da21091fa28a4edc8db40a54e31ba1ea3ca512abd7add4bac0c0edf57362309bcbda5c9a783a2cd35e4b0de7f35ec5f40ea6269bc83063b891dae128dc907070f7da619e309410983e6e7d23db49f7e4383224e766761dfd6eef29af1177598ea2851b3fe1d287bafb923da4ee8a77022249ad5ddde63810c37bf349bda50c150aa4a038099b866dbb01ee8fa26f04d95a78e7dd2c373c31ed1e01f18aaea790aea003ac618745f18fd759d2008af66a816f22c21709b7f58f253bcee27286bf4d71d4da79395fcbe29baa6bf194e7f1cda452cbf74ea8d71ea635cf37cea93e7f585baec9336f30ddc55de8c5afa6fdb372750012d01fb580a136417b4afd493e921f82cca403649c80512725140cb43f90f5d50ed626134533aea0e53bb85dadb5577102e29def342d204378baa3f89dc3e78cedb6afa6ea71e69411afc814027955e7616c00f14f48911b427478c2627cda8b3c21363e1e6ae7cff0d76052f121522f5da3300ab191d44c4a0d9902a29060d48114e655b94748c0949081841477e55076084a5a5b77465bdb1ffe02461e1fb845b471b5d6570c17a4dd9975c626a6bd91f44856a3ce1355ac565533b10bd2fdeeb57dda1a71b00228c80a03da1b53d8dcf4ffabf4186d821199a35a3b95707570d63dff1d803333c70572a457e71840f125874f9b2cffc2c66951d71a8a325232a80a038b90ba1df27ae830a07d12f8f57b87a4581944dc4576ec8719b62e55758aa899234d1771d6e742ed9f950e2067abae7b2f80a292aa7aec60c2813636810eefbc4009c958fc56ea3b3f0554a85c2a6a391f0f8c02f982b8e228b1488ad79e2d1584b2b7e41fcf2552f37b9c8d157afdb3f228cfcaeba2c19d0813cd39cd226e00db9f8747ae8aa954dd0f2ad90ebdf84490c72f4c1f5a84902a3b03bd80d9c0dc354c9022fc5b80e5dca7bc505c565ca014437ae751acc1c1a7eb1e0d33aff1a745cd6d24dd05d507b8dc4bb4d06660697c58169e8c9fca2c5d877921cf0505b317f7522b272daebe0edbcd7a00f733f8f10c0fe592dbdecd2d3fb434883d57646dad2e7a717dfa00872e26a3d9789989dae562caa8e8e5799fc33f3a02ad6106c993d8275edc2639f8ee80979ec5468b34cda90916bee91091f260f56f1082bd11655fea6143a95bb92e200f79e03fbd71ade29ef8a3449dadb41567887befeaea4541074df6cbf7844834052eeaf2c995d5d9dcf81c8354e3e9409b533b9e42f7a0c9a506a3f06f426f94d02c6b01922dfbe3000252834728c49c188fbe64d2b6875b30ebd77e87097012652991cb0024c657e297751de362b732e87182847b1afc137bbec1ffc2e2fa0a6ba063baa3491a19a7326608879819a0dcc9b6bc19a0b518bb2f1e13eea442d7ef3a096f612a6e433d3b252ff4dc1e84033e82ad0a400d13a4b33c41a4f3c3ed5638c0840b228102cac0c6a1bb1c5a2c05594752b40b8ae79b92b2ecbf94f3ac0c2ef249552f3715e9c1023651cf7964016dccb4641b77f1701e89633107aa43521ae6602dea11282643b32ac3d5fb7052a773f3cb5e3bcbd509e0d3f51ab0ad0ae3001037f43f21968e2a7de5ada2adb98fd7741606ad57b0c44b0a12e9e209b846f1b6cdc3aa43741fe304c2e0889615df0c17519bf754ef66fc8db24c7d6ce842e9f773d2428a54b394c9a74841faf9f346a74fc2ecaa67a1bcc8116eff4448636f468693dac70f1e806f07d6b033d78e0e648642c061b831ebbae586c2e2bf9ab1fb5cd0dff12815a3ae4e19a7f068c8fae594adca813f88bc0afcac886ee0698b32b14dcae47551850df99001d110f62a77c9d89fa5dfc0a5ce6a87581efc7bb9b0cf0c2229742b5cdf4a470e157b1134b5614c81523d077fb0352d8ce364f891c5b5601b5d945bfd568060bbeecb8f724addcb088ba9943dc3a1e1fc9f59db410dcea0c0f664bdff6a73b849fabfa84406e9cbcc567062b46476c43e4a3c8ed662a8e3afb66e6fad5bac154ae778c8d9bed8232384a4c7c93ecdf1109800061ec988ff7e965d82ab9a2b6651e4e56422d4d1c92349d85b8f9c4dff8c5729d4f6103d259cc992842501bbfabf9a978401b23e376d8fcda31eefb1676b9050329fa0928225c0740ab522e3aa22eb726dff94b1d43c00dd0f843ab7be3c1d19fa840b1a5b05ad18a4a6af6db3ef70e072fdf64dbd5136a3475147f0e3aa6d7184b0cdb0e3e246e835d92d66743834d8a327d3517424ed48923f4b738d1efd4f7470a5efcf9fbe9d6227649c53b19021e7a5ac15b273c010d0ad925a545e02179c137d7d5ecdc35c6045e8dffc1e01f8912df51959985c8917aabeff67645629a1f1a93610d1b61772a90623e0283fa809433a7e10e52fc4f7d2de634658acf25f28f798e95b49c867e29d04c961634f83f9da17b4cb53a04e6690a4ec135cc7e5846ac900eac9d802d96549f09d35e701491c16da7d4d8ddd9e47fb9e0467d1993acf85d87ad1afa0b7d1d049fd816f5c49f13c99e705276088776f61170b2e6c657366f45e90c471d93b8309b926106091d3cdf6f56d5ed56cb81e6cf837d45fb9748a1874504523a6591eb12771fb8ff947007155aa78c3f0beb42966f7df9aae84b431755d02fc407d552b7d87b64a6a0543aa40cf37596d241114c291f9ad2a66e9d0a6e91195de97226c256f083203ed460d04ad93f23ea070380b0a7db251ed013b831c77e5f6e4f60d8cdf675e5762f5b7631ebd8732de33a0d39d3849cef89a997e897bb25e634f1f35143c64a9f6c2a164f4de062b848f0168bb4e8091c87ad8bb20119fa8ea58fed6c3051bfc6e2695675b3c8c674039783ac9c4bd63f20fc690ebbd3b393a5d46857d30bb4802e2a96d1f9968df85c2e0d20d877e15d2e0bb203497d2fab3edb1560c7f5131373c9a4e26ec540e272b0f50e2fb1670df096ab097f173d718b2cdf79fbbe601f7abe7a83203541367b08a4177a49b208bc93641c9a53de6e468d714e965cf2f5058f032525c9727083b813897824a45845059576963ee08dae7f085a314e79368144b074a2062dddf7accd9a6f3c90fb4d13843ecd36d2f9524a86ce3bda595a3612628dbaeb7216a62150adc53d7f4372285760070e4fbcf21f540f584dde5d4bb1e698f5a1944a8b79d214ca04fe217559064c16523fefb809d03515c6c75ab2203253447bc4ea841bd44f07506c5327f084b7eddd5928b3061a7e2d307e7e212e4e655e390199c80a5f377cc59a2e0fc4de335777c05e44f3454219181582d97ac0ec082fe739fa0011e2df203bc0a4827641639b5b94817b84537e4442287b986b84e758fbbd2b6b735d928f6a587d016c947d2bb35e3b1be1bb0d3fe8c6d25b04b792a3da556458fe23345cb429654b78106c435c2aa01e4b758f8142e137b55b6b63ed0961737e02869f2ce6c2d8088ab5c7dd6cbfc80923ec526ed00103636d2ccb0c42bd3ce8b904c8e6c2a59d4e6732bc7ff348695ef9cb116bddd47e17354ad59ee191ce3f4973aa2af34dfa552077b2538a07704ed0c397eb43d28245a3e08c393c46f239ba78113ae5986e6a52fad2a3ea134b5de8cac5edc69bae9e217090600b3d63c13fee02c92008", 0x1000)
semctl$GETPID(r4, 0x3, 0x4, &(0x7f0000000040)=""/40)
semctl$GETALL(r4, 0x0, 0x6, &(0x7f0000003780)=""/4116)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
setuid(0xee01)
ioctl$WSDISPLAYIO_USEFONT(r2, 0x80585750, 0xffffffffffffffff)
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)
minherit(&(0x7f0000ffc000/0x4000)=nil, 0x4000, 0x3)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b10005040000000000000000071000001a5113fecea10500fef96ecfc72fd3357a89583535613ab4cb56355df50b7804be38164991f7c8cf7a4f2b297be1aa5b22abeb51e2f0ac3ebbc2feb3fda1139b672f4d3353eb067e7335a079d7080000000000000000008904000000000022830cf4571bed66f4007fccdcf3e4999d9d20002002c5dbfad800000008e371a3", 0x8f, 0x0, 0x0, 0x0)
r5 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSKBDIO_GETENCODINGS(r5, 0xc0105715, &(0x7f0000000080))
r6 = syz_open_pts()
close(r1)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
close(0xffffffffffffffff)
syz_open_pts()
ioctl$TIOCSETD(r6, 0x8004741b, &(0x7f0000000080)=0x8)


utimensat(0xffffffffffffffff, 0x0, &(0x7f0000000140)={{}, {0x0, 0x8000000000000000}}, 0x0)


syz_emit_ethernet(0x3a, &(0x7f00000004c0)=ANY=[@ANYBLOB, @ANYRES32=0x41424344, @ANYBLOB="5000000090780000"])
setreuid(0xee00, 0x0)
setgroups(0x0, 0x0)
getuid()
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000200)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000280)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000340)=0xc)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r1}})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4e}, 0x2, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f", &(0x7f0000000180)=0x12, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
r2 = open$dir(&(0x7f0000000040)='.\x00', 0x10, 0x21)
writev(r2, &(0x7f0000000080)=[{&(0x7f00000002c0)="aba7013a5e4fc9172f7a2048e6716c97aa063a8bd6a1cfd23e67d2509003bc743988aa82ccf23646149a26cc104d9895cc95ec4ea6b966e5911077e27dad241f37f781859c5d1a22c68cbcd29f7ed7cc4bda0875db8b9ea7fc2b360598772f96b605", 0x62}, {&(0x7f0000000380)="4491cfa1683cfea8972ead6da7e251fc1c8ca16d273088974d2e44fa1db8838fe775c71beb20cec7eb7202097b5bfff63c58dfa541d785178efd133b0315680a7306aeacaa8d0f1015fa71ea8a770c79d26ca6207aa9d4bd4c48c08a3afadfbcfc63a87616ca6605411e65d63a6257dbc358d4cea70166caf321bfe0fe78dd5c30288c81464012be", 0x88}], 0x2)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x0, 0x0})
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000934, 0x0)
open(0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000740)={<r3=>0xffffffffffffffff, <r4=>0xffffffffffffffff})
r5 = socket(0x18, 0x4001, 0x0)
listen(r5, 0x0)
setsockopt(r5, 0x1000000000029, 0x1b, &(0x7f0000000040)="0d2a2ce8", 0x4)
getsockname$unix(r3, &(0x7f0000000180)=@abs, &(0x7f0000000200)=0x8)
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000380)=""/93, 0x5d}, 0x3f8d}, 0x10, 0x0, 0x0)
sendmmsg(r0, &(0x7f0000000080)={0x0, 0xd6}, 0x4, 0x402)
close(r4)
clock_getres(0x4, &(0x7f0000000140))
setsockopt(0xffffffffffffffff, 0x8, 0x1, &(0x7f00000000c0)="f6c0cca6", 0x4)
r6 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$VNDIOCSET(r6, 0x20006473, 0x0)


mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, 0x0)
socket(0x80000002b, 0x8000, 0x0)
sysctl$ddb(&(0x7f0000000000), 0x2, 0x0, 0x0, 0xfffffffffffffffe, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
sysctl$ddb(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000280)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
getsockopt$sock_int(r1, 0xffff, 0x1002, 0x0, 0x0)
r3 = socket$inet(0x2, 0x1, 0x0)
setsockopt$sock_int(r3, 0xffff, 0x1021, &(0x7f0000000000)=0x5, 0x4)
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r4 = open(0x0, 0x0, 0x0)
readv(0xffffffffffffffff, 0x0, 0x0)
readv(r4, 0x0, 0x0)
r5 = openat$vnd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$VNDIOCGET(r5, 0xc4104603, &(0x7f0000000540)={'./file0\x00'})
mprotect(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x1)
sysctl$vfs_nfs(&(0x7f0000000000), 0x3, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x4, 0x42)
open$dir(0x0, 0xa00, 0xc1)
open$dir(&(0x7f0000000140)='./file0\x00', 0x1, 0x0)
socket$unix(0x1, 0x5, 0x0)
sysctl$vm(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
dup2(r2, r4)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x0, 0x0})
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
clock_settime(0xffffffffffffffff, 0xffffffffffffffff)


r0 = syz_open_pts()
ioctl$TIOCCONS(r0, 0x80047462, &(0x7f0000000000)=0x7)
openat$zero(0xffffffffffffff9c, &(0x7f0000001500), 0x0, 0x0)
msgget$private(0x0, 0x0)
pipe2(0x0, 0x0)
r1 = syz_open_pts()
ioctl$TIOCCONS(r1, 0x80047462, &(0x7f0000000240)=0x2)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000001c0))
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000080))
open$dir(&(0x7f0000000080)='.\x00', 0x0, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r1 = fcntl$dupfd(r0, 0x3, 0xffffffffffffffff)
ioctl$FIONREAD(r1, 0x800c745b, &(0x7f0000000080))
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000001c0)=[{}, {}, {0x6}]})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x8020691f, &(0x7f00000001c0))


poll(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f0000000100)={0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{}, {0x3c}, {0x6}]})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x7fffffff, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000480)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


r0 = socket(0x800000018, 0x3, 0x0)
shutdown(r0, 0x0)
socket(0x18, 0x3, 0x0)
syz_emit_ethernet(0x4a, &(0x7f0000000440)=ANY=[@ANYBLOB="69e1629b6174aaaaaaaaaabb86dd606b9efb00145000cb69bc83c1677a656ab420666c3e2c6fff020000000000000000000000000001"])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
socket(0x0, 0x0, 0x0)
socket$unix(0x1, 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000080)=[{0x84}, {0x34, 0x0, 0x0, 0x3}, {0x8106}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


sysctl$net_inet6_ip6(&(0x7f0000000200)={0x4, 0x18, 0x29, 0x36}, 0x4, &(0x7f0000000240)="0257e7a815d755f91bb2c052b2ec2684", &(0x7f0000000340)=0x10, &(0x7f0000000380)="ade7d510f0a69db3ec740ac4dd098b53d8", 0x11)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000140)=[{0x64}, {0x64}, {0x812e}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000340)="48b88b53c1fb1e4da4c91604527760545a754d4a5433cf6b8a2dc534c09c67316f8c652ff9a8aa28eaa71e351233c7539981fc948be70e1508404f5575458a9f1046322a3a7544", 0x47}], 0x1)
execve(0x0, 0x0, 0x0)


r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_LIST_DEVICES(r0, 0xc1045763, &(0x7f0000000580)={0x40, [{}, {}, {}, {}, {}, {}, {0x3, 0x401}, {0x1, 0x1}, {0x1, 0x4}, {0x0, 0x404}, {0x2, 0x204}, {0x2, 0x6d}, {0x3, 0x400000}, {0x2, 0x5}, {0x2, 0x1}, {0x2, 0x7ff}, {0x2, 0xf7}, {0x2, 0x2}, {0x3, 0xff}, {0x2, 0x8}, {0x2}, {0x3, 0x699d}, {0x2, 0x5}, {0x1, 0xffff960d}, {0x1, 0x401}, {0x3, 0x8}, {0x1, 0x800009}, {0x0, 0x1}, {0x3, 0x8}, {0x0, 0x5f}, {}, {0x1, 0x7}]})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{}, {0x80}, {0x16}]})
r1 = socket(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
socket(0x0, 0x0, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x30}, 0x0, 0x0, 0x0, 0x0, 0x8000000000000000})
setsockopt$inet6_MRT6_ADD_MIF(r1, 0x29, 0x66, &(0x7f0000000100)={0x9, 0x0, 0x59}, 0xc)
r2 = socket(0x18, 0x2, 0x0)
close(r2)
r3 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r3, 0xffff, 0x1000, &(0x7f0000000000)=0x1, 0x4)
bind$unix(r3, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r4 = socket(0x18, 0x2, 0x0)
close(r4)
r5 = socket(0x800000018, 0x1, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x1, "1a1116f0d0f700"})
setsockopt$sock_int(r5, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r5, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
write(r0, &(0x7f00000001c0)="d9537abde93d050cdd16b13f742a", 0xe)


mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000001700)='./file0\x00', 0x0, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
getsockopt$inet_opts(r0, 0x0, 0x6, 0x0, 0x0)


sysctl$net_inet_tcp(&(0x7f0000000100)={0x4, 0x2, 0x6, 0x13}, 0x4, &(0x7f0000000180), 0x0, 0x0, 0x0)


syz_emit_ethernet(0x2a, &(0x7f00000002c0)={@local, @remote, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x1c, 0x0, 0x36ea, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @broadcast}, @udp={{0x1, 0x1, 0x8}}}}}})
syz_emit_ethernet(0x22, &(0x7f0000000080)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x14, 0x0, 0x1, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @broadcast}}}}})


mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
r0 = open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
sysctl$net_inet_divert(&(0x7f0000000100), 0xb, &(0x7f0000000280)="a7c1290f17722447b2c63e743f6b379fa5267a394a5d94db9417b6982f519b111f61ad994119ba843799517c2ddf4c65594fb3b55a5fce717f619f904ce7b41e4296cf777a1db4747703440100000023e48310b779f9619c7642d6d7f500000000000000000000000000000000c37a11ae4dbe56deeb1ccae6d8e73f8976b460abc78bfdf1bf11c3ec2956f559e2ae95b19752a20f358e90edd96264cbc18906750f34e7e595d09e4e313414f688d6388b713904a7996cc92a328db185299eeabc8e35147498451c4a84a9d41bf693affdc27f4569379570f4", &(0x7f0000000180)=0x67, &(0x7f0000000640)="e2714be05c6a432bfcb43ba70e2bb9e6add925cf34d00e465191e199efee4898bfe502dcc0a3e3fd0cc0e7969055dcb470ddd2f263dfb8065cbf63d41b2a29e4f92695a2dae1e619ba2b0ccd1e605cd2827beb6ddaf6b579cccebb6d267a74d6af9f2cddd1eb38180245caf3e0f240c5f1ee52a05a63c446df6149316cc2e17b775698e9114250d85ec893fbd204889e5c3f37ee5894227fa7b36a2803d9c558953caa2452fff1bf82f49299d2fd07d8a464fd351d966782d21806ba5be9dc66d7dd572cdae3822888010771550dd55b3014876e2537e33b838b12b10d843be49e4cfc3b3f04a60088dd3cc3fbdc16864e028753d898f0bc0bd6e20f96274d743755332aebcec91d4f490000000000000000628c7c526f7de4f21b6260bacfe436d6eb63a96ded0b0f29cbc8ea2a7d2760b1fdf551506810d63132c72c14be5ffcc53ca339aea237797e863010f33b057982b6825dbdef1ce4425ae7d1234ad5cb69", 0xee)
open(&(0x7f00000002c0)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
link(0x0, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000000040)=ANY=[@ANYBLOB="aaaaaaaaaaaaffffffffffff86dd600625200000000000000000000000000100ffffac1400d0fe"])
r1 = socket(0x18, 0x1, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000000029, 0x8, &(0x7f0000000100)="54db0b54854d9a37275631fa6e64174e78402377241f3b2ed58c7bda91f1bb6545d47631dff7e76aa265a2f8843b8ce1456e3fb26125a455bacf5bd48c8d7bae6cf710c023b177094b91f32433bbacecd6613f1005d2fb896d2b5266906e9b8c5c1a418c4d72195cfcda996f6f5dce220916634c6dbdefed7290ee704452", 0x7e)
setsockopt(r1, 0x1000000000029, 0xa, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x3e}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)
openat$speaker(0xffffffffffffff9c, 0x0, 0x2, 0x0)
syz_emit_ethernet(0x12, &(0x7f00000002c0)={@local, @local, [{}], {@generic={0x88a8}}})
msgrcv(0x0, 0x0, 0x0, 0x0, 0x0)
r2 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmat(r2, &(0x7f0000001000/0x3000)=nil, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {&(0x7f0000ff9000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffd000/0x1000)=nil, 0x80000001}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f0000ffc000/0x1000)=nil}, {&(0x7f0000003000/0x2000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x2000)=nil}], './file0\x00'})
r3 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r3, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0, 0x1000})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x40b, 0x0)
sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000000)="9b1809ffffffffffffff7f473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6fd74c94d1b44", &(0x7f0000000040)=0x10011, 0x0, 0x0)
utimensat(0xffffffffffffffff, 0x0, 0x0, 0x0)
msgsnd(0x0, 0x0, 0x401, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000440)={0x4, 0x18, 0x6, 0x9}, 0x4, &(0x7f0000000480)="9b0209c3218b07fcfe4189c99e805e6e84d356960798a692992117d6728436ba1bd87f42e3303eac3846528d050712f838130efce33f523ba44765f5f6915b2227390ed95bd9dc6d4dc7f149d4d6d06a3f23616e773302d9cae75e39a5a11e32e0e6ebd635450b2eba540af7f2aa5dbfbdd900a0dad2b74f50acd76b5c567049ef436dbea0d7562f52955af8d4ab84c513252ddd139b5f5cd5c2bd02adc7f1fe850c00000000000000062ab475cca257352828a76e5334be562995e894238b96ca5d4d3e670fa0cc791dfc4415030910fa64eac9b4e8aa9bef19525cb6f7e8570be65bb7ad3fe963cb9a8bd949ee334db1ccf73db06b5947b3e88aa810f8ed7cca10ff0d0000000000001345daa49507756f49775275ca390b94e85d5a95b82000b9429c25483a9275d0da3b561c6adc3c141f26040000006b436218bdbdc9ac0a623855e941dc1872fcb045e0d9df1ecc6357ee21e2b0802cb60edd0300723235f06715e7eecc3e0760c70e1dd7873e27142bbae1a7e44de453a073fe3426f334b80f043ba9136d57c799353d46dd81439b111a511a288bee5dfb2e353e3bb073e3342273216b07e49ca4df0fd2dbe9a8eb377010ee678aad0bd8c7fb7d82693a096344671843a1f2082612b2ff237c6e505ff5f5ba932954d73c630fd2791f833a1da5af0704f687e196f4f7859e071fc98111cc9024f790ce16ceaa427d0104e39789d91000"/528, &(0x7f0000000a40)=0x210, 0x0, 0x0)
poll(&(0x7f00000000c0)=[{r0, 0x6e}], 0x1, 0x0)
getpeername(r0, &(0x7f0000000000)=@in6, &(0x7f0000000040)=0xc)


setreuid(0xee00, 0x0)
r0 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r1 = getuid()
fchown(r0, r1, 0xffffffffffffffff)
r2 = getuid()
setreuid(0xee00, r2)
open(&(0x7f00000003c0)='./file0\x00', 0x200, 0x40)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


pipe(&(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
write(r1, &(0x7f0000000080)="c7", 0x1)
write(r0, &(0x7f0000000340), 0xd4e688a67930cd)
close(r0)
write(r1, &(0x7f0000000040), 0xfeea)
close(r1)
execve(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000340)={0x3, &(0x7f0000000080)=[{0x7}, {0x5c}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f00000002c0)=ANY=[])


writev(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe2c63a56077123a276d3ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000280)='./file0\x00', 0x0, 0x938, r0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')


setrlimit(0x0, &(0x7f00000003c0)={0x200004, 0x5})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x80, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000001500), 0x0, 0x0)
fcntl$lock(r0, 0x7, &(0x7f0000000140)={0x0, 0x0, 0x0, 0xfffffffffffd, 0xffffffffffffffff})
ioctl$WSDISPLAYIO_SMODE(0xffffffffffffffff, 0x8004574c, &(0x7f0000000040)=0x2)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000080)={0xfffff001, 0x2, 0x7ff, 0x8000000, "f7ad08f40f3d0a808d0e158966ecad62696b42ed", 0x6, 0x4c3})
open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
socket(0x10, 0x2, 0x80)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f0000001440)=[{0x64}, {0x16}]})
mprotect(&(0x7f0000ffc000/0x2000)=nil, 0x2000, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x58}, 0x2, 0x0, 0x0, &(0x7f0000000180), 0x0)
r1 = semget$private(0x0, 0x7, 0x3c0)
semop(0x0, &(0x7f0000000000)=[{0x0, 0x4}, {0x2, 0x2ff}, {}, {0x1, 0xfffd, 0x1800}, {0x0, 0x7ff, 0x2000}, {0x2, 0x804, 0x800}], 0x6)
semctl$SETALL(r1, 0x0, 0x9, &(0x7f00000002c0)=[0x87fc, 0x9b7])
semctl$GETALL(r1, 0x0, 0x6, &(0x7f0000000180)=""/250)
munmap(&(0x7f0000ffa000/0x3000)=nil, 0x3000)
mprotect(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x1)
ioctl$WSMUXIO_LIST_DEVICES(0xffffffffffffffff, 0xc1045763, &(0x7f0000000040)={0x0, [{}, {}, {}, {}, {}, {}, {}, {0x0, 0xc8}, {0x2}, {}, {}, {0x3}, {}, {}, {}, {0x0, 0x9}, {}, {}, {}, {0x1}, {}, {0x0, 0x1000000}, {}, {}, {}, {}, {}, {0x1}, {}, {0x1, 0x5}]})
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
unveil(0x0, 0x0)
mkdir(0x0, 0x0)
poll(0x0, 0x0, 0x0)
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x205b1a)
r2 = open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)
fcntl$setstatus(r2, 0x4, 0x0)
ioctl$WSDISPLAYIO_DELFONT(0xffffffffffffff9c, 0x8058574f, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
dup(0xffffffffffffffff)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x0, 0x10, r0, 0x0)
setgroups(0x1, &(0x7f0000000080)=[0x0])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000300), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f00000000c0)=[{0x5}, {0x84}, {0x16}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f0000000080)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000400)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000380)=[{}, {0x7}, {0x8006}]})
syz_emit_ethernet(0x56, &(0x7f00000003c0)=ANY=[])


r0 = socket(0x2, 0x2, 0x0)
getsockopt(r0, 0x0, 0x1f, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
socket(0x18, 0x1, 0x0)
r1 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0xc0206923, &(0x7f00000001c0))
ioctl$PCIOCREAD(0xffffffffffffffff, 0xc0107002, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$FIONREAD(r1, 0x8040691a, &(0x7f00000001c0))


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x4, 0x1100, 0xffffffffffffffff)
ktrace(&(0x7f0000000000)='./file0\x00', 0x4, 0x1100, 0xffffffffffffffff)


sysctl$net_pipex(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = open(&(0x7f0000000280)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000028000/0x4000)=nil, 0x4000, 0x0, 0x10, r0, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
r1 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
pwritev(r1, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
r2 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
ftruncate(r2, 0x80002)
r3 = open$dir(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
preadv(0xffffffffffffff9c, 0x0, 0xfffffffffffffe16, 0x0)
preadv(r3, &(0x7f00000012c0)=[{&(0x7f00000001c0)=""/224, 0xfffffdd5}], 0x1, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x0, 0x0)
ftruncate(0xffffffffffffffff, 0x0)
syz_emit_ethernet(0x138, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000002a40)={0x0, 0xffffffffffffff89, 0x0, 0x6e}, 0x0)


sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, &(0x7f0000000440)="e96ae754362f1de1c98139baf73a0000e2351874baee4d277ef5b45c01924fdbd568451b9599313a8f45b61028d2d6d3aeebfe6497377234f0bea8c658f8afdaa7eed96e5326012ce7f69a8a1b35465cb16738d167412e1a1539db4db674b7914418adac94c1854abcf92685e4fc6cb45b6769f965fbf664d911bf0415f43c6ef32aef9acdc8df6dbde08f3f6a4e7e7e3855db5de20f263fc8a0fcc6219d3a92dd19cc2f4348f14d51103c094605b524fd4eab446b135158a4f64f5b0a0480bcbfc2ff3f6e663010603713e21878", 0xce)
sysctl$hw(&(0x7f0000000040), 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
pwritev(r0, &(0x7f0000000500)=[{0x0}], 0x1, 0x0)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
shmctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0xffffffffffffffff, 0x140}})
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)='\t\x00\x00\x00', 0x4)
r1 = dup(r0)
setsockopt(r1, 0x1000000000029, 0xd, &(0x7f0000000000), 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x18, 0x1, 0x0)
close(r2)
r3 = socket(0x18, 0x3, 0x3a)
r4 = dup2(r2, r3)
setsockopt(r4, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendmsg$unix(r4, &(0x7f0000000bc0)={0x0, 0x0, 0x0}, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000040)={0x0, 0x80000001, 0x3, 0x80a19f, "081f000000f1675910508b00e0ffffff00"})
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
socket(0x18, 0x2, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f00000002c0)=""/47, 0x2f}], 0x1)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1800000029"], 0x3e}, 0x0)
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)


r0 = open(&(0x7f0000000300)='.\x00', 0x0, 0x0)
mkdirat(r0, &(0x7f0000000000)='./file0\x00', 0x0)
mknod(&(0x7f0000000600)='./file0/file0\x00', 0x0, 0x0)


sysctl$net_inet_udp(&(0x7f0000000000)={0x4, 0x2, 0x11, 0x6}, 0x4, 0x0, 0x0, 0x0, 0xfffffffffffffe5a)
sysctl$vm_swapencrypt(&(0x7f0000000000)={0x2, 0x5, 0x2}, 0x3, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0xa}, 0x3, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000000), 0x6, 0x0, 0x0, 0x0, 0x0)


r0 = syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, "ad95be4b065c389983d554ecc416cf34eb18fa8e"})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
mknod(0x0, 0x2000, 0x40000802)
open(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$VNDIOCSET(r1, 0xc0384600, &(0x7f0000000000)={&(0x7f00000000c0)='./file0\x00', 0xc9, 0x0})
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x802069af, &(0x7f00000001c0))
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0xd02)
shmat(0x0, &(0x7f0000001000/0x3000)=nil, 0x0)
r2 = socket(0x18, 0x2, 0x0)
setsockopt(r2, 0x1000000029, 0x32, &(0x7f0000000000)="eb", 0x1)
r3 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r3, 0xffff, 0x1021, &(0x7f0000000000)=0x5, 0x4)
readv(r0, &(0x7f0000000180)=[{&(0x7f0000000100)=""/25, 0x19}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ktrace(0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000140)=[{0x2}, {0x35}, {0x6}]})
syz_emit_ethernet(0x127, &(0x7f0000000040)=ANY=[])


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x881)
open(&(0x7f0000000100)='./bus\x00', 0x0, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x801)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
openat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x0, 0x0)
execve(0x0, 0x0, 0x0)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x3f, 0x0, 0x0)
syz_emit_ethernet(0x3e, &(0x7f0000000100)=ANY=[])
socket(0x0, 0x0, 0x0)
r1 = msgget$private(0x0, 0x5bd)
msgsnd(r1, &(0x7f0000000d00)=ANY=[@ANYRESHEX=r1], 0x401, 0x0)
msgsnd(r1, &(0x7f0000000000)=ANY=[], 0x401, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000200)={0x4, 0x2, 0x6, 0x19}, 0x1, &(0x7f0000000380)="1a093598fc41000080ebffffff42319256cc222efa6839f9921b9868836b0539488056cef91ad449c4ea014cfc838731ea44ea713c508c7e6856662932f5edb5eb7bfbda93c203f44f6271a95258e7472b80f384e84673a61129cb607fcc201c1f000038c5ce79a316ef880c337108553b4f910581efbd7cc19250c3abe08b8eadca57b714cdd00d08cb6c3db3e8c1d40006fd61bf0b8162c4d06fbf377229976b0a6700000000000000020002000000000000000000bbc7dcdc107f9b7ace93", &(0x7f0000000340)=0x4b, 0x0, 0x0)
openat$vnd(0xffffffffffffff9c, &(0x7f0000000040), 0x400, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
open$dir(0x0, 0x0, 0x0)
pwrite(0xffffffffffffffff, 0x0, 0x0, 0x0)
msgrcv(r1, &(0x7f00000002c0), 0xaf, 0x0, 0x1800)
readlink(0x0, 0x0, 0x0)
r2 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r2, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r2, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@file={0x0, './file0\x00'}, 0xa)
msgsnd(0x0, &(0x7f00000006c0)=ANY=[@ANYBLOB], 0xe1, 0x0)
sysctl$hw(&(0x7f00000002c0)={0x6, 0xe}, 0x2, &(0x7f0000000000)="00000000000000a9ad0898d06119f0e45ae44d8a8f18560b2edcb0392c4a", &(0x7f0000000040)=0xfeb5, 0x0, 0x0)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "0100dd2d018000000000005e00"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x3d}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000040), 0x3, 0x0, 0x0, &(0x7f0000000080)="4f1d4c6344b80ed788b6a4515248df3aa745bb992c574ab4cdf5587145812eab4a988f7fafd7a01d99776d988908cd186b51f34f8c15ffa0c685ad4116c783959eff4278384b4000384dbb1c2aaeff10b4135529a1da6fda67c67469d954be811b25ec5521559154c586eefff122009f659cd3e27e98a3241495005f102d9101d158284c0ee3250aa7c11042330de22a299ab00894fdc9bac6042d", 0x4)


socketpair$unix(0x1, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000700)=[{0x64}, {0x30}, {0x6, 0x0, 0x0, 0xfffffffe}]})
write(r0, &(0x7f0000000740)="76e5dead6f01f8607d2100000063", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000280)={0x3, &(0x7f0000000240)=[{0x5c}, {0x45}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000140)=ANY=[])


sysctl$vm(&(0x7f0000002880)={0x2, 0xc}, 0x2, &(0x7f00000028c0)="ba", &(0x7f0000002940)=0x1, &(0x7f0000002980)="9f1e4c69fed207f28f4af9d4f513fa0d8938798898a47cc48513e95503a1a0822b204189b8dede3496ad72f6170a0f601a52", 0x32)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x11, r0, 0x0)
ftruncate(r0, 0x8531)
writev(0xffffffffffffffff, &(0x7f00000026c0)=[{&(0x7f0000000400)="640493d78db6a9c1e335bb42b30c7b40a07b3baad98026cb156727aa65cfb18540954a46faf6cd689a437aff3f4961c4e46a834f6785f138abeced17229a790e349e6bd31df47a250b6311c17b41de694d02002d9c138fb5554471ad71a4e3b0c4a0f71fc4b1f3db02e683a852170340fa26d02f5dcb6c3772415d9b0c54258aba6ad66cd42dfd5163936af944020e200f6dad158fa90dfdd051d151c8c8cb6d711f408511a8c922ff7be9bf88fc6a18b3261c65ab46b32f89b7793b789d533f5dabd554659bcbb9e4082598016c9ffd443ad64a6c1384bebc4f0fa12ebee357f81c1bfbb7ff9c0bb5289f98184e590366ece692aac2a0f3fe55ae6072624ff0892d666934e9e7bb159ba7471e9ca862d48aa90c56e33b972e7ab5f15383b1e0bdc135ef14c4b638c9514366af346df10d2d11e3e82c7f98a731867165c536966e32790a098e86bc8c85d1d890537ee1a3b37a907cb151aa5b72801d9b213f04f59acc40bab4f2dfde876c2bc53ed02cd106d289a59310e0297a072b926369982acb409872a3a4325ed56f1d297bc8bbfb8f0a43f793ee9487a4492016350aa61cca26b86045d14a8f08e6f6d3e3be5520397612b66ebdf990efcf9ed9796836fa253dfa0389406ae25edb31abf6797596cf9b4a943972a4a19c43db1926c18bf15fc526127d1b04211fb4f4fe4c34dba511e8801a10008e54d343386c0c096641681899e65d2afea539fec10a2db4f07a06c7745c1005d0c2b1f020bd80e052df5a4969a40602d7b4350068968bae7ed03d05c9f0e7dd8940d1e37cfbf3370f5953261615197d350c60c2e3bdc186eff30d0700e608a4e08b2cac91f42275e3e6378a0747267335e017b5342a1662df7f3144a5c0e08008460631d2fb76c410c11c4dcc7f73fcab23a4794775f4284e02ad1ba71d64db4f1f4ced92b7a389fd596763283771b9faf89865c462f59e57a81cf8c3cbeffb268f00b6589ab79483f517583bc3a949c0df139721b6dcb9635dca559ac670c1b3ac3ffae886d18134df6d3b7078928ad5370c9687de2846d1f89f7455cf1f7bec56f3717cbdcab9a5fbe597f929e432ff093d92cb35d625bc8c5dcdc4df998db4b51f74775e5d6d119c505a2d0f27c9ead9e84af18c5d7e258cb6a4b57d28c5be27c3d72e277ae3a79bec39bdc88df392b2df6afcca55f79efb3fe6d0d8b50d7c8bbbc134450db20f1d5a773ce9cdc3b97b3274cb2e9c85496e9043e1eb83bda1b0960808b7dbf61fa0b420596976194a598a6ce1066867d13ed30035f8ff0ba3dcaa15df0cab8b96807cb82435a42067d4f1257de536842db0d3f7dfda891c146d79b600e6a2f994f2755cb278becfdaaefb2c7b976be36689c7a0feced48a723be73f29851f75e42e9d62c83d6aa220891c5c24634e8c7cc3eab033046727127a802dacbde8cf629c1f57d59ba0690af43ce944607c1fd9df72f74d67e7ddc2efd8dc6c459d0d1fe2ca57d14e20046f139050206dd8d203e0389aef6682cc6b861cc364184ee9708452dcb732992ce6dedbb8d57b5c5689b9836c54cdc91b4766f618d608d4bb380614d8cc2e03b3b3b5897ccb61f9fe2d16e5ced34cee9e856a6c52324c0eef64a4b7f9e8e7ed5a71d7b1fe9f94665ac75da67d114047ff5a1c3d0668d43d78c12565ea154f763418049e8dd3a1929b7fa4877c9e2cd984ab94818219a05b196b643adb3f064dbffd2b22ade017488178c5361a1c93f9c615e0e0cd28f25b7ca582d6942071cb7fae17b52eb41ead6e78914945802c19bac16c76ae14c7ed4be6e42713e8a4bd6220aadf458fa15b40777f94e223c596c7f80bab9584fcf4ff14f138adbbf7b1a7bdd686fa9249fe006aea38651e410fd4b1af0d79d7f1ee0cb2711ca81382f15804771da4a18d5f20e10ff9a7abd6ae8583d94f58769f3401526e517d963800c92485f9c24eac2d914895d4d9b866bbb769d22a00db29ce0b9a7d7112defb15d9776db55edf8fca337b1a496c7710acab8135aee0261a780ef6b39664469e33dab2398639d1becbdc74000b36c2ca5df2c0d3c5d3d3e054a2b8d91bc4656cf09300dd084cb0b625a587fba81cc6c2c3ef6f93342b65bc0e68222de6908492ac431f9f4dc1d3915a2cba79820c8c1f7c6e5c582d953b60a943eef44a6e7b244c808fb292f3944a4b1afbbadb06ed72c1d2cf9a60e02b319af032eddb475ae1947175f437262cefe05a89dc92367c8f8223e3a415b080b2bee22f084d00a289e42f5dcd0c31dc257d6bd09d214fad7aaa03d285a4ca618a5cc2bc0167ce424c40b879bfc294b9f2be0ee1c4669fe57d15c3b8fd626507ebb94d7313eda527d86a2bcaf9234a6eb4fcd2ecd218607961c7816094311a762d783ab7cef7009f103d938a5dee845b827001c87920ea3110b97b40a8525c41a57a03e389d9d864c57e10a849509135cdde81b89da8ee10540b76fe6c303a98bfa68a493ff59104b41c34c62092d3c0cc16d5c5c9abf7d0cc9206605ca6b69511091b512063985b03549573fbe60036cdfb28e77670e99b55a8f8151035ac93ef64b77f36951b0d3a31befef14741f874b313b66908f8da53a8a95255c16019876c85dd6070b2a8470f303b98d3c9ce2d203774794ecd2dbc43a69cd37c21f9c971634ff7b00af46adccaaeb1ca346bbdcad44151e38a94d91339c425554791adf2d3ff197221979625d2993ef7f4af06ec2438ab780ce737ac1bdbd873fa3b5cc0af43097b2be36bb9cbf87d39d3a7d54d5a49b176a3d74d95c06cd9b665248f84c27019f7b62232d9de01396aa0096f36c399b762913e207de7e3d24a2bbb04d879fe29b087ea262e82e4b3ca0fca62f222a592ab6ca1b1609e6a7500b8ed38db0d895c2df29604a64540e796787461ed7d1c5c562662b8f5146839cfbae18a6fb302033ad6558ce8a9d61d5de662b995ecb228535cddd02aa051321dadfd06dcd6409cf98d8a8697c7499f1695f173b427ff5f6cfdd224b66b89682d0e2978710e2bbfe7c9f2793cd2592ec7106c44e46c1d2bfe9d7cb53cac640f92f66506aefcc11c983e6c284a892dfc4b813771087baf9150eeb019ba0877afef77a66ee91b2c85ab1b95cc670ae9e80a4f20b8c8914c655828a68d6e8b509d479b5d04980a5bb17fb9ef17060f802f6e6f57e29d6587d6b8dc3438f592db639f718cc3bdaad6865d8a6aa94c47e1061cb8dfb8d7c54c168a29e8b1a78e1716ce413d429daaf09c924a7cde44eafc58fa5b3a5e3aa387a9465f024f7fe6ed9343d81dee65d106f635bbece1c99d5eb8ca0487c00c2851aaf24b2b6003e7150758f5a50943de2ba7b95710fa05f1c1e305dd7a14dba19feb94c9591d8cf724ef55aca7fb8e054763f7c80027b929666f6864db25a059859ca8831f9b7251e38eda5b00d0fc64a3b3460bd7ad733b9eac508a6a191a6465ca14729214d29cdfef5c6409a3f7e5db2044f836c049f5a14a78bea5c7a55e957a53d8d7d97203de65090319911c1788fc704d9382571d3d1bd2b35927d8d95b3f3b14930350ca34d577ff1d4ab69c7ef9f74f73590b8fd0d3574e7779e7f6564f9245c117c4272054015715a0671bcec7416d95a17da00b50e976168b9de75b673f6998119eb1c3b2bd1eebbf21aabc7e606991dc2e802058344d4854b1fe88688873db69c8ac70a9e4850960390a510231dc7159e3e89be0162258982be870d6135b0870986f66c19cf315552165fdccdd2acdff62cddeba67ca0e9578ab629d895a81f63c2262362a49ef4bd8a25dbf73fd100844496f40753d1496bdae8cf60f23db024ec56dbb594e9047ef5b005f579ff829dc1c3cf6844dd8bdcaf644481d171cec2bd25dce58a23617d5d11d7d44465214accb32a5767548fdfe3a428699ec03d02fbc2ccf1237ba07249af6f37ea83ddd8c7ec77f56ae7025c5662ecee8a8682d61823ec04bfebd6195147b016a28112821ad0f2aa32110dd31b38027f0e7fa042cce3e52ec467aaf95f998db202f819f201ee1322215018824a880755b94a2876e09e4c0cac01005ff8885e5f2f21c28b1aab38c62c33de0268521db2c198d19e7fafe69215465f6421b8503218f394d5a94c8601dd6514ff8a80f442ce07a4de65060229285b873667fa19859753c4b949ada2d3ab20afb732a4d4f0a9e5e13ef5a50c8361a465874e956464e201de1f30fa97398d3636ce88e479428b0bd8521010b92a22b4866c311593c101e3ed6169242c63334c7d6715a6dc50063e1c5658f590d0177464461a2ed8892719a770bcd687c597d51d46b89640b6610bc107a6b6d23e46052680aa18673", 0xc01}], 0x1)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x4)
kqueue()
dup(0xffffffffffffffff)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000680)={0x0, 0x0, 0x0, 0x0, "2c63ad7996f1e758e5fd06a7cd67261a796926ba"})
msync(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000700)={0x3, &(0x7f00000006c0)=[{0x20}, {0x40}, {0x8106}, {}, {}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000001180)="06006f293599", 0x6, 0x408, 0x0, 0x0)
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x10000, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f00000000c0)={0x1, &(0x7f0000000140)=[{0x7fff, 0x7e, 0x0, 0x5}]})
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
mknod(&(0x7f0000000080)='./file0\x00', 0x1000, 0x104)
mmap(&(0x7f0000fff000/0x1000)=nil, 0x1000, 0x8, 0x10, 0xffffffffffffffff, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000180)={0x0, 0x1, 0x8000000000000000, 0x8000000000000001})
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, &(0x7f0000000400))
r3 = semget$private(0x0, 0x7, 0x0)
setreuid(0xee00, 0x0)
getpgid(0x0)
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000001c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x2}, 0xffffffffffffff27, 0x3ff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbdc0})
semctl$GETALL(r3, 0x0, 0x6, &(0x7f0000000440)=""/248)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x1, &(0x7f0000000000)=[{0xc0}]})
r4 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
writev(r4, &(0x7f0000001440), 0x0)
execve(0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r5 = socket(0x2, 0x2, 0x0)
dup(r5)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000001c0)={<r6=>0x0, 0x0, <r7=>0x0}, 0xc)
r8 = getuid()
setreuid(0xee00, r8)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000200)={{0x0, r8, 0xffffffffffffffff, r8, r7, 0x2, 0xfffc}, 0x1007f, 0x0, 0x3})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
semctl$GETALL(r3, 0x0, 0x6, &(0x7f0000000540)=""/240)
preadv(r1, &(0x7f0000000080)=[{0x0}], 0x1, 0x100000000)
syz_emit_ethernet(0x4e, &(0x7f0000000080)=ANY=[@ANYRESOCT=r6, @ANYRES8=r1])


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
dup2(r1, r0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000a, &(0x7f0000000000)="ea00005c00000000", 0x1)
setsockopt$inet_opts(r0, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0x8)


chdir(0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])
r1 = socket(0x18, 0x0, 0x0)
close(r0)
r2 = socket(0x18, 0x3, 0x0)
setsockopt(r2, 0x0, 0x31, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0xffffffffffffffff}})
connect$unix(r1, 0x0, 0x0)
writev(r1, &(0x7f00000012c0)=[{0x0}, {&(0x7f0000000180)="430306cdd77ed0ac61aa1f1f178c6c0713bc9cfa7239e77a9e6600ca5e9d629af6f184918750c99e7bd6f34ca8dd1f617265e1f412fedeb6bb6194b7d1852add2a41fa896e741873aeba30762434c1a6323389ff33671f1a2c1cc2e614760b1f6d01dc4622dd11a02d46d919ce75847818817e263b2e4435b9fb0afd2a47857ddae65394ac61d4ba0ba20f678abd863fb05290657bf6354b735114153b4525f1707b0648a795a0d60759ffd754a5a43857426bada52c4cfc99e9509dad9b6342bffaf158f7448384260087bf626a649412588ef780385c8922d82e216cf6395758a00bb7a6f2ad000dbe9984355439c38f2679ce87a8ec319b2d211117eff838b904796f43105a1d78272579fd0c8f27b5ab46c4018e9901a97bd8f8ffffffcf2bd006db0a16198db749074e5417b7f5e2256e3189d8fa356b8711007447abae29de0cfdaabc5ae8e92e4a663d8780556de5b2b6701ccd1540a7b920686e84aad89a12eacb14380d7158af71d7dd440ee0320d1b99b2a8bb3b41f1837d0291fe1eaa5a651b6adf995dc7de12525e327db1164c3ecd9e276b335a3c1df9c7f6c27d9dd5517cef01a2f0e30b36801286d4fe632dea933a5476b86c71ffcdc8ab9b3b24d74d29b8088288083a84cde46d89e25d53197fa86dcf07500c7e88c103db15d38d12a581a8fa11f68ab81f8ea8803b05c7906654a51314796e9ea65fe1e24e9ab25f10b4e69156856a568a71743f2c8014293455eee063ca7be42105e595d9d5dd476ce56b46ffa5f8e142bf48f0b315d0672949a6c47d6e86850cfed924286598bfe2ad07f3008cd0bf928f8437f70d6e4eafa9877082a627e651903dc45874b2893441c92fbf60c7d0acd476976774948523b38ed67372230d0f39773bff65c3946c625124912e8d9a609d640364009f6c63fa219afbf17faf987d3c5cbfaba0bab2e611d62664d06051bb6d29f5079c08b89b0a2dbeb2c920ad8b31f4d6dba94fc8a5da82bc928640755240c31db94b137c6deec27d930664cc5361486f35f2ff7a5362787116b8973b0e01b32ea5390808dbcc1c4c260bc6fe457f19fb414d6f26072aac6c1351c2434b983925ba47588b5db0807aa72217f2eeb3343a1dd90c6db8d915e1ea8ade4e8599", 0x32f}], 0x2)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000280)={&(0x7f00000001c0), 0xa, &(0x7f0000000140), 0x0, &(0x7f00000005c0)=ANY=[@ANYBLOB="2000000000000000ffff000000000000", @ANYRES32=0x0, @ANYRES16, @ANYRES32, @ANYBLOB="000000002800000000000000ffff000001000000", @ANYRES32, @ANYRES32=0xffffffffffffff9c, @ANYRES32, @ANYRES32, @ANYRES32, @ANYBLOB="007bacb039000000000000009ce4344b3a826d1affff00000010a18bafe2d0577329417e938dbd6d835d3d0aac", @ANYRES32, @ANYRES32, @ANYRES32, @ANYBLOB="ff000001000000", @ANYRES32, @ANYRES32, @ANYRES32, @ANYBLOB="000000002000000000000000ffff000000000000", @ANYRES32, @ANYRES32=0x0, @ANYRES32, @ANYBLOB="000000002000000000000000ffff000000000000", @ANYRES32=0x0, @ANYRES32=0x0, @ANYRES32=0x0, @ANYBLOB='\x00\x00\x00\x00'], 0xc8, 0x400}, 0x1)
getsockopt$SO_PEERCRED(r1, 0xffff, 0x1022, &(0x7f0000000740), 0xc)
r3 = getgid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000000)={{0x8, 0x0, 0x0, 0xffffffffffffffff, r3}, 0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x2})
r4 = open(&(0x7f00000002c0)='./bus\x00', 0x2, 0x0)
read(r4, &(0x7f0000000300)=""/4072, 0xfe8)
readv(r4, &(0x7f0000001cc0)=[{&(0x7f0000001ac0)=""/195, 0xc3}], 0x1)
ioctl$WSMUXIO_INJECTEVENT(r4, 0x80185760, &(0x7f0000000140))
ioctl$WSMUXIO_INJECTEVENT(r4, 0x80185760, &(0x7f0000000000))
r5 = socket(0x18, 0x1, 0x0)
setsockopt(r5, 0x1000000000029, 0xb, &(0x7f0000000080)='\x00\x00\x00\x00', 0x4)
setsockopt(r5, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
open$dir(0x0, 0x10000, 0x105)
ioctl$FIONREAD(r5, 0x80206979, &(0x7f0000001340))
r6 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r6, 0x80085761, &(0x7f0000000000)={0x3})
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x35}, 0x4, &(0x7f0000000080)="ab", &(0x7f0000000000)=0xfd8c, 0x0, 0x0)
chroot(&(0x7f0000000300)='./file0/file0\x00')


mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
unveil(&(0x7f0000000380)='./file0\x00', &(0x7f00000003c0)='x\x00')
execve(&(0x7f0000000500)='./file0\x00', 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r1 = dup(r0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000140)=[{0xb1}, {0x81}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


nanosleep(0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
setitimer(0x0, &(0x7f0000000100), 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r0, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
ioctl$FIONREAD(r0, 0xc0287533, &(0x7f0000000440))


socketpair$unix(0x1, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
execve(&(0x7f0000000040)='./file0\x00', &(0x7f0000000300)=[&(0x7f0000000140)='/dev/bpf\x00'], &(0x7f0000000440)=[0x0])
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x4, &(0x7f0000000100)=[{0x25}, {0x3}, {0x1, 0x0, 0x0, 0x3}, {0x6}]})
syz_emit_ethernet(0x127, &(0x7f0000000040)=ANY=[])


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b1000513000000000000000004000000000013fecea10500fe3c9df96ecf2ac72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf7f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f335c7d0c032bfa896443a42118000000720fd38bfbb770c1f5a872c88106002ec5890400000000000000361b1257aea8c500002002fbfe0c2300008abfba0900000008e371a3f8343712051eeab7196fcbd80407000000c011200000", 0xb1, 0x0, 0x0, 0x0)


r0 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffb000/0x3000)=nil)
shmat(r0, &(0x7f0000ffb000/0x1000)=nil, 0x3000)


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
fcntl$dupfd(r0, 0x3, 0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
syz_emit_ethernet(0x52, &(0x7f0000000080)={@local, @local, [], {@ipv6={0x86dd, {0x0, 0x6, '\x00', 0x1c, 0x0, 0x0, @rand_addr="fe350e28ef0900c08cfe24be00", @remote={0xfe, 0x80, '\x00', 0x0}, {[@dstopts], @tcp={{0x0, 0x0, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}}})
sysctl$net_inet_ip(&(0x7f0000000040), 0x4, 0x0, 0x0, &(0x7f0000000180)="53f26aef7623ba3c93334d8028df9ef5ea234abf5ea8361356fc962ad17ade4d7dc249ea77aae57a39db576b16027c1a64a5beaba2001c5b2d7b453de5f7424c4c62d4a67fb459311f1e9c4e6571f58fcddf60ce42fc125005877a91ba6ce4f1d95e5c1f9a862ade829bcac5d45bbf9fd8747282663997f4a2e5848cd9449e9f1eb2", 0x82)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x1, 0x0)
close(r1)
r2 = socket(0x18, 0x2, 0x0)
setsockopt(r2, 0x1000000000029, 0x3f, &(0x7f0000000040)="00fb6c4f", 0x4)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendto(r2, &(0x7f0000000200)="0e330b4bede90af3", 0x8, 0x0, 0x0, 0x0)


ioctl$TIOCSDTR(0xffffffffffffffff, 0x20007479)
minherit(&(0x7f0000ffc000/0x1000)=nil, 0x1000, 0x0)
munmap(&(0x7f0000fff000/0x1000)=nil, 0x1000)
munmap(&(0x7f0000ffc000/0x4000)=nil, 0x4000)
mlock(&(0x7f0000ffd000/0x1000)=nil, 0x1000)
munmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000)
shmctl$IPC_RMID(0x0, 0x0)
shmget$private(0x0, 0x4000, 0x0, &(0x7f0000ffa000/0x4000)=nil)
madvise(&(0x7f0000ff8000/0x2000)=nil, 0x2000, 0x0)
mlock(&(0x7f0000ffc000/0x3000)=nil, 0x3000)
shmctl$IPC_STAT(0x0, 0x2, 0x0)
madvise(&(0x7f0000ff9000/0x4000)=nil, 0x4000, 0x0)
shmat(0x0, &(0x7f0000ffc000/0x4000)=nil, 0x0)
socket(0x11, 0x3, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r0 = fcntl$dupfd(0xffffffffffffffff, 0xa, 0xffffffffffffffff)
ioctl$KDMKTONE(r0, 0x20004b08, &(0x7f0000000040)=0x6)
getrusage(0x0, 0x0)
ioctl$WSDISPLAYIO_DELSCREEN(r0, 0x80085754, &(0x7f0000000080)={0x6})
ioctl$BIOCSFILDROP(r0, 0x80044279, &(0x7f0000000000)=0x7)
r1 = socket(0x11, 0x3, 0x0)
sendto$unix(r1, &(0x7f0000000500)="9401050138a85a80b1b0782797888fd1f838a311000000000000b13886ca3849451ae3c3051020741038f5538551f30ce390500e08fecea11ea8fef96e4fc748e93f0b780486aebdbe781e4d8f5eef9187a869a4d3a4cbba982fd825582fe2aa7923ed00f4c8b2ca3ebbc259699a1f132e27acb5d62934e4fd89070000000000000070c1f5a872c88dff7cc53c894303b2a0a85ff3faa800000000009ec7ab3a34c29000000000000000000000000000002d7e4a5d76cc3f9cff2ed2243e56fa277603c5cc1e047326bcf6b67b75d00bf6ee330b6a80874b70559d9975ebd13da2447a78aa4b00cd0ba1870215607bb912e3d7325183ce69456b4b6ca927871c81672a54ec695c5bdeb842836656f917945cc076f87dc714dfe0aa2947252df350707b22884a7730cb6dba8742110fbe9ec7481885274387e0b1dbe5695122604819b0b2294b7b20726a5d4fcb44f62d00fabb2f247a166d8d79d05b8cc370f5c11db58aedca632a83acd58ff0ea0a3dca58ccb03cce466cda735017196ff346c32717397d6ec6952ec90de81ed297b2319e130f", 0x194, 0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r2 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
semget$private(0x0, 0x0, 0x0)
semctl$GETZCNT(r2, 0x0, 0xf, 0x0)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x1e, 0x3, 0x0)
getgroups(0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f00000000c0)="964b2e8c33c6b9184c54128f975fecf28b35a6b4fe6c2c7decb370e1ded56c32941e0b88ddd1b408c2570ee069d4b5d9fe2d8c0e0e6fcae82f887c519aef0e4f551a8da94ec5e94e8cc86014dcae87ce36ccfa7db954ba0ac2262672aa4264b2ec6ad65c12edb84ce1def64f79b40d76e2c7318805285dcb26b2adfb8bdfa599fa5d155b68e34a92a4e96829325b7b8acd8cb6c66aa407b4ff97282541ca92edef6fc0382c47bd1c63e463375341590f6a327092643b98a174e443c056da46158047e0b068975ba714199a52b4034fa4364e7304b31dd9dcaced366eb800389ecb0e1c41c6058bb7fa03702e8a03363bc593818269f64a0be94d29087369babc60ce10bc4c561f687122c1b20dd9f10518", 0x111)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x801169ac, &(0x7f00000001c0))
r1 = socket(0x18, 0x3, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x9, &(0x7f0000000240)="9dd6981f1c370d89d86a1420", 0xc)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r1, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
r2 = socket(0x18, 0x2, 0x0)
close(r2)
getsockname$inet(0xffffffffffffffff, &(0x7f0000000140), &(0x7f0000000180)=0xc)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0xfffffffffffffffe}], 0x0, 0x0, 0x0, 0x0)
r3 = socket(0x800000018, 0x2, 0x0)
setsockopt$sock_int(r3, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
pipe(0x0)
poll(0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
munlockall()
bind$unix(r3, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, &(0x7f00000000c0)=0x5, 0x4)
r0 = socket(0x2, 0x2, 0x0)
getsockname$unix(r0, &(0x7f0000000000)=@abs, &(0x7f0000001200)=0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x2, 0x3, 0x0)
connect$unix(r1, &(0x7f0000000000), 0x10)
setsockopt(r1, 0x0, 0x2, &(0x7f00000000c0)="63e1303d", 0x4)
writev(r1, &(0x7f0000000980)=[{0x0}], 0x1)


sysctl$kern(&(0x7f00000000c0)={0x1, 0xb}, 0x2, &(0x7f0000000100)="71f91e34", &(0x7f0000000040)=0x4, 0x0, 0x0)


open(&(0x7f0000000280)='./file0\x00', 0x615, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
ftruncate(r0, 0x0)


r0 = msgget$private(0x0, 0x0)
msgctl$IPC_STAT(r0, 0x2, 0x0)
msgsnd(r0, 0xfffffffffffffffe, 0x0, 0x800)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{0x30, 0x0, 0x1f, 0x5}, {0x7, 0x0, 0x0, 0x80000000}, {0x16, 0x0, 0x0, 0x6d72}]})
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f0000000080)=ANY=[])


sysctl$net_inet_etherip(&(0x7f0000000000)={0x4, 0x2, 0x61, 0x2}, 0x4, &(0x7f0000000040)="af784282e2082d78b01a1cf5c749cdc76146badcd5854fcbaabafcdec656fff0b1e173417c495865a90264bb1b3f998e0f404a949f4ef0a6f4c230f9a08d9c0946d2e30ee3469731", &(0x7f0000000140)=0x48, 0x0, 0x0)
mkdir(&(0x7f0000000000)='./file2\x00', 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
r3 = socket(0x2, 0x2, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r2, 0xffff, 0x1023, &(0x7f0000000040), 0xe0)
ioctl$TIOCSTSTAMP(0xffffffffffffffff, 0x8008745a, &(0x7f0000000080)={0x7f})
r4 = socket(0x18, 0x2, 0x0)
setsockopt(r4, 0x1000000000029, 0x9, &(0x7f0000000140), 0x0)
dup(0xffffffffffffffff)
kqueue()
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x0, 0x0})
r5 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r5, 0xc028698a, &(0x7f00000001c0))


r0 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1, &(0x7f0000000240)=0x5, 0x4)
r1 = socket(0x11, 0x3, 0x0)
dup2(r1, r0)


mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x8)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f0000000100)={&(0x7f00000001c0)='./file0\x00', 0x4, 0x0})
rename(&(0x7f0000000080)='./file0\x00', &(0x7f00000000c0)='./file0\x00')
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000a, &(0x7f0000000040)='\x00', 0x1)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000440), 0x0)
writev(0xffffffffffffffff, &(0x7f00000000c0)=[{&(0x7f0000000180)="a91d572018dfc112b211c9b7f9dbdc4e9c7752845816984bb622d74a83050000000fd383c857ce942c438f2ea02b33f59d83749b711951efa88a2a6dcd049f666033a9f518c180b3eefaedee0d0f34a08b", 0x51}], 0x1)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x2, 0x0)
r3 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r4 = fcntl$dupfd(r3, 0x3, 0xffffffffffffffff)
ioctl$FIONREAD(r4, 0x8004745d, &(0x7f0000000200))
ioctl$FIONREAD(r2, 0x80206910, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000000040)=[{0x3}, {0x3d}, {0x6}]})
write(r0, &(0x7f0000000280)="f659600777eb3e3a6dce3c530404", 0xe)


open(&(0x7f0000001700)='./file0\x00', 0x70e, 0x0)
sysctl$machdep(&(0x7f0000000080)={0x7, 0xf}, 0x2, 0x0, 0x0, &(0x7f0000001100), 0x4)


socket(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
syz_emit_ethernet(0x138, 0x0)
r0 = msgget$private(0x0, 0x0)
msgsnd(r0, &(0x7f00000005c0)=ANY=[@ANYBLOB="0100000000000000bcff98a66a978da027ee68af00d1ed8f0f2b77e5ae7529b162945aaeba93ab1e0a8cefa732522d95550700000010c638dddce23c10ed7a5f245f42212612be75f87e545d03990554eb20558e0648dce5fc980663c99a08ef466c008f1c560b69f47f0c4582164954b7a099f6b0aafe43e1c76cc297349f151bb74e67e0591109b060702ee5b49d098e4bcfe6a5938dddb6b40715ea48817d5b8d8795c0fd67554723f6b51f7abed257871b35afdf329dded2b4374086e2b362f7"], 0x19, 0x0)
msgsnd(r0, &(0x7f0000000240)=ANY=[@ANYRES32], 0x401, 0x0)
msgctl$IPC_RMID(r0, 0x0)


socket(0x18, 0x2, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0xc0e99db6de761f86, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {}, {0x2, 0x0, 0x0, 0x40804}]})
ioctl$DIOCMAP(0xffffffffffffffff, 0xc0106477, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


mknod(&(0x7f00000000c0)='./bus\x00', 0x6000, 0x5)
open(&(0x7f0000000040)='./bus\x00', 0x10005, 0x0)
open(&(0x7f0000000200)='./file0\x00', 0x0, 0x15)
readv(0xffffffffffffffff, &(0x7f00000001c0)=[{&(0x7f0000000140)=""/5, 0x5}], 0x1)
r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
writev(r0, &(0x7f0000000000)=[{&(0x7f00000002c0)='Oo', 0x2}], 0x1)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000001440)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
fcntl$getown(r1, 0x3)
r2 = socket(0x11, 0x3, 0x0)
sendto$unix(r2, &(0x7f0000000000)="b1000504b10004000000000003000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac5000010000000000000008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)
r3 = socket(0x1, 0x2, 0x0)
ioctl$VMM_IOC_RESETCPU(0xffffffffffffffff, 0x82405605, &(0x7f0000000080)={0x4, 0xec9, {[0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfffffffffffffffe, 0x4000000000000], [], [], [], [{}, {}, {0x0, 0x0, 0x0, 0x3}, {}, {0x0, 0x0, 0x7f}, {0xfffe}, {0x0, 0x0, 0x1, 0xf85}]}})
ioctl$FIONREAD(r3, 0xc0106924, &(0x7f00000001c0))


semop(0xffffffffffffffff, &(0x7f00000002c0)=[{0x0, 0x8001, 0x800}, {0x3, 0x27b3}, {0x4, 0x8, 0x800}, {0x4, 0xfff, 0x800}, {0x1, 0x4}, {0x4, 0x1000, 0x1800}, {0x0, 0x8000, 0x800}, {0x2, 0x8, 0x800}, {0x4, 0x1162, 0x400}], 0x9)
sysctl$vfs_ffs(&(0x7f0000000000)={0xa, 0x1, 0x10}, 0x3, &(0x7f0000000080)="d3f3351a05", &(0x7f0000000140)=0x5, &(0x7f0000000180)="21ab58aa1bfdca668af6b1f30cca5274ecb7375c064bc152f50867d33581c087b3fcecc8502601bfea75539052ae34eab61285a81b5bd726e3b11466d1d58af39f8c0797fda1135421ae9c8662ece405fd13fc809e3ce5580ade826c7faeee91c7ec5e9f9a8e89d63382ba66b2997773b9d30ced07136574a9ccf9429a887322411be15bf2dd60dc5031974356e40b4627881faeb7f3b1d9eb6dbeb26ae8ede6bbcc8de933183c1e148a38f8391bf03963883c50c129bd34a1ffc5ee39015e38735b525b6b3822090edc1b", 0xcb)
r0 = socket(0x18, 0x1, 0x0)
shutdown(r0, 0x2)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, 0x0, 0x0)
readv(r0, &(0x7f0000002d40)=[{&(0x7f0000001800)=""/198, 0xc6}, {&(0x7f0000001900)=""/130, 0x82}, {&(0x7f00000019c0)=""/68, 0x44}, {&(0x7f0000001a40)=""/44, 0x2c}, {&(0x7f0000001a80)=""/235, 0xeb}, {&(0x7f0000001b80)=""/76, 0x4c}, {&(0x7f0000001c00)=""/144, 0x90}, {&(0x7f0000001cc0)=""/4096, 0x1000}, {&(0x7f0000002cc0)=""/85, 0x55}], 0x9)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x10000520)
open(&(0x7f0000000100)='./bus\x00', 0x0, 0x50)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
syz_open_pts()
r1 = socket$inet(0x2, 0x3, 0x0)
getsockopt$sock_cred(r1, 0xffff, 0x1024, 0x0, 0x0)
ioctl$VMM_IOC_RESETCPU(r0, 0x82405605, &(0x7f0000000780)={0x1, 0x0, {[], [0x1, 0x0, 0x0, 0xffffffffffffffff]}})
ioctl$VT_OPENQRY(0xffffffffffffffff, 0x40047601, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r2, 0x0, 0x1f, &(0x7f00000000c0)="0000ad14", 0x4)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
bind(0xffffffffffffffff, &(0x7f0000000440), 0xa)
r3 = socket$unix(0x1, 0x2, 0x0)
recvmmsg(r3, &(0x7f00000002c0)={&(0x7f0000000280)={&(0x7f0000000080)=@in6, 0xc, &(0x7f0000000200)=[{&(0x7f0000000140)=""/184, 0xb8}], 0x1, &(0x7f0000000240)=""/33, 0x21}, 0x8}, 0x10, 0x3, &(0x7f0000000300)={0x9, 0x400})
r4 = dup2(r3, 0xffffffffffffffff)
connect$unix(r4, &(0x7f0000000000)=@file={0xd1653077bafa0115, './file0\x00'}, 0xa)
ioctl$WSDISPLAYIO_LSFONT(r4, 0xc058574e, 0x0)
syz_emit_ethernet(0x0, 0x0)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x11, r0, 0x0)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r1 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000001000/0x3000)=nil)
shmat(r1, &(0x7f0000001000/0x2000)=nil, 0x0)
writev(0xffffffffffffffff, &(0x7f00000026c0)=[{&(0x7f0000000400)}], 0x1)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x4)


r0 = open(&(0x7f0000000280)='./file0\x00', 0x615, 0x0)
write(0xffffffffffffffff, &(0x7f0000000000)="4d8e262725f33aba16ead05738eca9d24a93e2ca8990899ccd64ed88e35538f448f34a9100b9821b8f3035d378ea4e1e2b6a04e13bfc1ae2182cf63afae0a77fa92038dc2d460685ab44d89d220be8e7971c3d010064686df5a0aff84c2ea6f0b0a4509d9867b7bd1848ec6bd21740daba313980966bc7e69c43fdda87a8588524fa61dae3bc90363a0ed744d6e56e8d8db71f536592d5cceb022ad4d8b32a3b6ff652bf9d1b6d2fd0b649caa8af", 0xae)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x50}, 0x4000000000000004, 0x0, 0x0, 0x0, 0xfe7d)
r1 = syz_open_pts()
fcntl$lock(r1, 0x7, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x10004fffffffc})
mkdir(0x0, 0x0)
open(0x0, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x3, [{&(0x7f00004f7000/0x2000)=nil, &(0x7f0000604000/0x2000)=nil}, {&(0x7f00004f8000/0x1000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f000069c000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f00004f3000/0xa000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f0000690000/0x4000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000ff2000/0xb000)=nil, &(0x7f0000ff2000/0x2000)=nil}, {&(0x7f000069c000/0x3000)=nil, &(0x7f0000ff2000/0x4000)=nil}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000604000/0x3000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ff6000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff6000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f00004f6000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil}, {&(0x7f0000ff9000/0x2000)=nil, &(0x7f0000ff7000/0x2000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000605000/0x2000)=nil}], './file0\x00'})
open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
r2 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
flock(r2, 0x1)
r3 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
fcntl$lock(r3, 0x7, &(0x7f0000000100))
close(0xffffffffffffffff)
syz_open_pts()
syz_emit_ethernet(0xe, &(0x7f00000002c0)=ANY=[@ANYRESOCT=r0])
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r4=>0xffffffffffffffff})
socket$unix(0x1, 0x0, 0x0)
ioctl$FIONREAD(r4, 0xc0106924, &(0x7f00000001c0))


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000300)={0x2, &(0x7f00000000c0)=[{}, {0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x3d}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1, 0x0, 0x37)


mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSPGRP(r0, 0x40047477, &(0x7f00000003c0))


r0 = socket(0x18, 0x3, 0x3a)
getsockopt(r0, 0x29, 0x1a, 0x0, 0x0)


syz_emit_ethernet(0x36, &(0x7f0000000300)=ANY=[@ANYBLOB="ffffffffffffffffffffffff867e392ea078bb25724fdd6060626000000000fe8000080000052f5dac0000000000bbfe8000400000000000000000000000aab2f8b7d29beee6658e437483226b3e4de9c8b844dc5651c977a22774ebe8a4989446635360daf0f1ca08d580fa41107c99bd47c00b8ca8867bc1e13c109968f2dd9fd10985403437dcfd472454a968b621be8684ead1611e51dcb5b2c4f34cae57408358e2b624c29d3c371714d323a5993c55212b0d9df20a06898ad87659c4c69dfd3c443ea56656b13ac7283f80efa27fad9af1c685509a51cf956186796da0e8d77fdfda199d83a52b4ebd3744840b13a3958dc26546666390fd08b5a966fb08"])
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0))
r0 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000140), 0x8, 0x0)
fchownat(r0, &(0x7f00000002c0)='./file0\x00', 0x0, 0x0, 0x6)
writev(0xffffffffffffffff, 0x0, 0x0)
socket$inet6(0x18, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
socket(0x11, 0x3, 0x0)
socket(0x11, 0x3, 0x0)
ioctl$VT_GETACTIVE(0xffffffffffffff9c, 0x40047607, 0x0)
r1 = dup2(0xffffffffffffff9c, 0xffffffffffffffff)
poll(0x0, 0x0, 0x3)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x4})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000006, 0x0, 0x0, 0x0, 0x0)
r2 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000080), 0x202, 0x0)
r3 = getppid()
fcntl$setown(r2, 0x6, r3)
fcntl$setstatus(r1, 0x4, 0x80)
close(r2)


open(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x2, 0x0, 0x0, 0x1}, {0x86}]})
write(0xffffffffffffffff, 0x0, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f0000000180)='./file0\x00', 0x23f)
chdir(&(0x7f00000001c0)='./file0\x00')
setuid(0xee01)
open$dir(&(0x7f0000000080)='./file0\x00', 0x400000002c2, 0x0)
symlink(&(0x7f00000004c0)='./file0\x00', &(0x7f0000000e40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000200)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


syz_emit_ethernet(0x36, &(0x7f0000000140)={@local, @empty, [], {@ipv4={0x800, {{0x8, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @local={0xac, 0x14, 0x0}, @local={0xac, 0x14, 0x0}, {[@timestamp={0x44, 0xc, 0x80, 0x0, 0xf, [{[@broadcast]}]}]}}, @udp={{0x2, 0x0, 0x8}}}}}})


r0 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r0, 0x0, 0x64, &(0x7f0000000240), 0x0)
r1 = socket(0x0, 0x3, 0x0)
sendto$unix(r1, &(0x7f0000000180), 0x0, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x2e, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
recvmsg(r3, &(0x7f0000000340)={0x0, 0x0, 0x0, 0xfffffffffffffc56, &(0x7f00000024c0)=""/236, 0xec}, 0x840)
accept$inet6(0xffffffffffffff9c, &(0x7f0000000000), &(0x7f0000000040)=0xc)
socket(0x10, 0x4000, 0x2)
shutdown(r2, 0x2)
r4 = syz_open_pts()
ioctl$TIOCSETD(r4, 0x8004741b, &(0x7f00000002c0)=0x8)
syz_open_pts()
syz_open_pts()
getsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)


sysctl$kern(&(0x7f0000000240)={0x1, 0x32}, 0x2, &(0x7f0000000280)="1a44c592", &(0x7f0000000380)=0x4, &(0x7f00000003c0)="01000000", 0x4)


mknodat(0xffffffffffffff9c, &(0x7f0000000100)='./file0\x00', 0x0, 0x0)
r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$PCIOCREAD(r0, 0xc00c7007, &(0x7f0000000100))


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x9f9d})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0x4, &(0x7f0000000040)="00fb6c2e", 0x4)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
r1 = dup(r0)
ioctl$BIOCSBLEN(r1, 0xc0044266, &(0x7f0000000100))
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
syz_emit_ethernet(0x4f, &(0x7f0000000400)=ANY=[])
syz_extract_tcp_res(0x0, 0x0, 0x0)
ioctl$FIONREAD(r0, 0x4004667f, &(0x7f00000001c0))


socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000001c0))
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000080))
open$dir(0x0, 0x0, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r1 = fcntl$dupfd(r0, 0x3, 0xffffffffffffffff)
ioctl$FIONREAD(r1, 0x800c745b, &(0x7f0000000080))
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x80206913, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000080)=[{0x2c}, {0x34, 0x0, 0x0, 0xffffffff}, {0x8106}]})
syz_emit_ethernet(0x3e, &(0x7f0000000040)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000002c0)=[{0x4}, {0x2d}, {0x16}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f0000000080)=ANY=[])


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
sysctl$net_inet_carp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x17}, 0x4, 0x0, 0x0, &(0x7f00000010c0)="00040000", 0x4)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg$unix(r1, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="28000000ffff000001"], 0x28}, 0x0)
recvmmsg(r0, &(0x7f0000000000)={&(0x7f0000000000)={0x0, 0x0, &(0x7f0000000000), 0x0, &(0x7f0000000000), 0x63}}, 0x10, 0x0, 0x0)


sysctl$vfs_nfs(&(0x7f00000000c0)={0xa, 0x2, 0x2}, 0x3, &(0x7f00000001c0), 0x0, &(0x7f0000001900), 0x0)
r0 = fcntl$dupfd(0xffffffffffffff9c, 0x0, 0xffffffffffffffff)
ioctl$DIOCMAP(r0, 0xc0106477, &(0x7f0000000000)={&(0x7f0000000100)='./file0\x00'})
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
semget(0x3, 0x0, 0x0)
setreuid(0xee00, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, &(0x7f00000001c0))
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000140))
setregid(0x0, 0x0)
ioctl$LIOCSFD(r0, 0x80046c7f, &(0x7f0000000040)=r0)
mknod(&(0x7f0000000000)='./bus\x00', 0x2000, 0x2e00)
r2 = open(&(0x7f0000000200)='./bus\x00', 0x0, 0x0)
close(r2)
setregid(0x0, 0xffffffffffffffff)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x18, 0x2, 0x0)
setsockopt(r3, 0x1000000000029, 0xb, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
r4 = dup(r3)
setsockopt(r4, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
ioctl$BIOCSDIRFILT(r1, 0x8004427d, &(0x7f0000000080)=0x6)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000280)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x81}})
shmget$private(0x0, 0xc00000, 0x0, &(0x7f0000400000/0xc00000)=nil)


socket(0x0, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$FIOSETOWN(0xffffffffffffffff, 0x8004667c, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x80}, {0x2}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f00000000c0)=[{0x1}, {0x84, 0x0, 0x0, 0x8001}, {0x406}]})
syz_emit_ethernet(0x36, &(0x7f0000000400)=ANY=[])
minherit(&(0x7f0000ffc000/0x4000)=nil, 0x4000, 0x0)
r1 = socket(0x18, 0x2, 0x0)
msgctl$IPC_STAT(0x0, 0x2, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x83fe})
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000440), 0x1, 0x0)
fcntl$setstatus(r2, 0x4, 0x0)
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f0000000380)={0x2, &(0x7f0000000340)=[{0x0, 0x3, 0xe6, 0x9}, {0x5, 0x20, 0x4, 0x1}]})
r3 = socket(0x11, 0x3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x3}]})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000180), &(0x7f0000000280)=0xc)
r4 = socket(0x2, 0x4001, 0x0)
r5 = socket(0x18, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r5, 0xc020691b, &(0x7f00000001c0))
r6 = fcntl$dupfd(r4, 0x2, 0xffffffffffffff9c)
close(r6)
mquery(&(0x7f00004ef000/0x2000)=nil, 0x2000, 0x0, 0x0, r6, 0x0)
connect$unix(r3, &(0x7f0000000300)=@abs={0x0, 0x0, 0x1}, 0x8)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, &(0x7f0000000000))
select(0x40, &(0x7f0000000140)={0x10000}, 0x0, &(0x7f0000000200)={0xffffffffffffffcf}, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000240)={0xc8, 0xfffffffe})
kqueue()
setsockopt(r1, 0x1000000029, 0x3e, &(0x7f0000000000)="674cd6e5", 0x4)
writev(r1, &(0x7f0000000080)=[{0x0}], 0x1)


syz_emit_ethernet(0x46, &(0x7f0000000200)=ANY=[@ANYBLOB])
clock_gettime(0x0, 0x0)
setrlimit(0x8, &(0x7f0000000100)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000040)={0x0, 0xcf, 0xd, 0x203519, "1bb7e60ab87aa57800000000d0d200000000fd00"})
writev(r1, &(0x7f0000000000)=[{&(0x7f0000000980)="9b9431a5d715597f32c28150472c5c4a26761d657e140316ea35d282feeeaf745cf3e4bf90e1903276332cfaaa820fef61ff3e48cec7057ad907ac1df25524bd150d15c304380f7ae3170b2fcd5a74731b6cbd17fb8136e5287cb39417d25bd833815ebef001deb672d80fa0f8bc68f7187cd337803948baa7e34f56701b2180ddedf8852feae4274e0629", 0x8b}, {&(0x7f00000014c0)="874efc64a16404b3dc9c5bce1a5ecabc9ad87a2c628890d6c0144206d4f104d9344df375dfd3bb105ae821f98218363f92fa5e9c05234d33d0a8d963888d8822f30019a93c93d85f62e363a3eee977e582890dacc2371a48a4431bd985409647e571a93d2a66e5b7f67ff0c6fa6dd62af727a8200ecc56044fc7d427e40ae2086abd08e51d7b88e9dd4f2f9b44b3e969212e9d954795f6c302de6406b45beeb8f5a34ad8acf5ae86909381263bdee8839a61832d6b11df3dcebcbfd8f73f3da2e026766309eec290c2427714cfa2f92495293de2c336949475c17a49469a7b6d7d237ddfb60b74ef5f99682e18887d3bc75cfce8150b94974af2204d42c994b8910d5fd06b7bd9ab57e26310ac63c59cda6de93302b7e1812811086a2ee2ee23e61b77a6d519b43ddfe016f394ae0a2751d8b420fce01e9dda4c2a43b5318afb3b6b9e9f99d71684bfaf02ed0327a58d5049b8b62e28239022820778336a5ddba0c4c7960d4998b7e8c10e5bc641ee6fe80d267590de91d2b6b50e879119ca15c7f70420506fe54a6c5537a486e83ebbcb7e95af437eefbf299a6c2c9fb95b9983374fe6a743c52828761bfba9f79f6850214ce56ddd9a859bea12b3e8bc2e30aff6aba9a488775d52d1d2a90ec9c23c908f9bd356eead53715274ee47fc9ca4a7a5189fe1027e625b7a3b5350f2b76ec2a1e192eccbce78286f134c4523b74a953bd01754d2238f1880d748c9f55eab8aede59252ca39caad3598d6e9bc03bd59426501afd5ee61ba70ccb04e7e385f3e089c5493ce9ee428c30865f9bec095fbbc30cf50d52e5b2ee7139a6b4c99b82c5a07cb4411f2a0d19174c70e508c2cdb4cad591a33db002d7d5121d6fd26f8b31af12a1e9d2058cb2bc8e34ccb1b23bddb8306484cefecbbd8ae919fc8595c0f25940a449ea2b6f345b8bf320e0a31bbe427d2431bdd52a28d3e5b15169fde2390e3121dc18b6a6c4450a03c3f3f84d9fa5f774c529591058bb00d21bfe726575817b975fb8dc62427f9b7b4f0d22cfa9975b84eded78aa3a0edb9a13165bed3443b5f35d8c68041c081f0af3eabac120d7a8e879b525f0ca9954f2a2ea752ab18683c283410f14bd859ce8806983fd20050ef80155afb0c254a6878e3e099e796242938446a642234ba124bcaecb683bbe7526007befe7d90f120ed76f987f2f8a445dae46c794d4e345564ff042bc68c2b72461ebd498235a1212bd3ed669ac480b011fbb4041136e88003c5210d142ac0c643d3db0039e21e5d9157f26cfc71fb7fe767e9c938e51b64c22ac394c8aec52ee25a226265f632bce7d79c5b7b749b56fa67ac00d5aa0571c573f23fa3ea26f15cb679742c7b9f17e22aae2892006fef55dd244c4613134227ebd4af1e5c7867295b45f91b5bcc7fa0f3ac9daa8f49b9363e9e01250fcc8d72fdcae8f6222ae3a2fb01eef75cbb2ae84ea7fcce5ef3e86c2221ed491f5d7e0b595f574857c20cc49f9162c31e8267984a4328ce6dd4a6de2e68cb4e811391651588873eff36062bb6a7c5df5e870a050338af57644ed41e2e80e66d91dd3744a5c18ec2c30ff917fd7485f92597fe4bc3ab8e18ac1f7d3c80e86a7f1b0b8bdd2f9146a900c63085ff5c6e74dee637fe3c255f16b07f5395e2b803c44147171b52ecee292c414c5415c317b14b8086b15ce3efefcf790a3fd4faf3f3dabe410c730477a829ceb589d567d97e26ccdc6fec6ca5599414458f7c0f459ff45eece2fe4d6b031507b83c44cadf24f5a4b30a8048e4d5b267bc06cc12393fd31bfe8eab256881d2618dd41491418e636be2a412dbed78da3448a52e666d3348fdf76928d380f62dd63f3a01b32679f92d7e3df380b6af601037085266b68abcd636586a763dc244252385b5b80b6c3c3ab5c3cad35bcc7a5f6bdef137e886604f3649b1af4abcd2f3d56f708e8d9003e00866ecf76da72bff382d28efc05d53f31f05e3027d8f699c9f93967bf590c984836ebec878ddcd29fe74f0647fa32ef13201ebf2a81bfd02df5b53e13594b662358e14d9dfe6cd721b31c18e1165e6a1e586b688a97b1a41c028fc1e7d2895fbe915fada9f3c28d9dfb13eda790f67a6d0a190fa80d01a5b58196a7d4827be51f043d56a49ddff95ee20260e02c53f5967ddce1510939ae04916282e782f728f02d62a06a0dc1d285cf4811566eb93d5305696517fd89fcb90fe1ea392e9d35fe02218506581661d2b1d5f4df93a8c3b556912a29e1328c739934d4c8112563c7629040721cd0bfd5c6123b7de1b39c9adb28eb3c97df75d0266dfe02f45428a3785f0ad7ea9b0ba5ff7915ed7aded81ec61c54340c46938c4d7bf8bb2dfe0ba8b69480cd1ea64107acefb62ca76a35be999f646077813d455b51bb643de2a39f7353a9a4a0d69d2200edc3a4fc671eda7db4fa39ca2f6c68a19a5468836fde4eda83145a0569a987e4011679d993420d918a640839f02595fdf0eac4e57f69fa50cc6f01030506df03ad16d418a6fd66c4230c494761e4be904e33dbf4e46c60ac4c0bd04df0da41f1d111c2252edb39c76dba2aec9abd2b2325b5b948db76f451dc23bab13ede45a0d0d63428748bf42de7084547b881f5a70e73e72efdf4046d6b1f677507ae5ce05a5878b542e55ca224e6c89f32e98d270f3644541861b6dbf8e7c2ca3b23f0230cc4d13774339f45f5871a4ac7ff0f460abb7d7d0da6bbedfe27cf2a0d4a140163d76156fb51612f5df85ce150f8795308707ce06b1581fb46d511281d77eb346ec043ca42d6182a8e484571c003f42909c69ca52a77a", 0x7cb}], 0x2)
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000200)="485a3b45042938c62a10619bfa9635e568d85dffffff7f00000000d4536889e89908892b8316047e6dfbb6e1e162571c015e99b581b8e909103942ee8a921cb8d85504b7a940cc09869c3a9f585eb1ad792b59457b2cdcf5ffd25c3d1d9b0be56236bc1f4faa891191b0a962a8989455c84c44199bf73d1b62b88b18c9bed8fcef9da0409c146a0d616fbd50b2bec0f256fd9e21b3fc41849e8967f2beb0a5501e0acdb299f8e242983156a46b53cf77274c1f056d97f0cbc62b7b3625e1e68ccc6687102a38000c9a6cec5590e3", 0xce}, {&(0x7f0000002000)="a0095ba17dd0d086b3b2119ce6a7c6b1e6838280c81119f1665a8453bc1df36edbe9413ed9e9e18a679b6ccd7c1a2e0b63d1de4e941a4efd063dcb3146c575b9700f10316bae4d76cb9ab951cbe141cb7ca93718969e928d443c8a86f7ad244eacec73482dd6dfdd90dd7664fa214398b8b13457d398ce7d953f86304b841c796ec7d6a1afb4a1692f0830caf997b9017541d479b6beb4f57cdc09fdfaa6e560f53348a733a5cba87f54d82fa39b42f30d3976075fadd6ce4c0575c2451e1f2e53c921d7247a9f3ecbf44bdab7ca2f52e490c1b6d87b9f892b359e1a8dac7b4af8715e991ed256d756409730bb65185b8d321e86ff47a96a153b4a1a43540578e0b2bf61935a476864793803b5583328ebd1d5c45077d0ae7bc20ff4c95dcc06bb255720aa614176a9d9554daba519b8f4ecec5e88c7502a5f3bc25ca17d82badf6d682b648398009c9224bec46a02a7454997ea90de2277b55a190e52bcbcfa793d11bd5485831b37f9cb817f5c900ec34b932f076f9000f07e11053f5e9e851448ba62f877da4e89d05c2ac925a89c95769e6b4b6806aef4528b158cfa3bd4cd888f6c75a2a07f2d26b5ffea5334732f5630aa34cedc7550c5add0486735da9dd3ce36201e26248683c1d8ac2bdbd1e4ed25fe4beae9c06ac107d813ed2db7de0dafa0e9df17310ebe807c2ca76e3ad48468bdcb0021ea27c6f648a41fe9073d16fe5d9313dfaf3072a59019bfd9fd675f4cd27bd2483f77b95d0efba1949404db031e1f8cbcd5d8b3893a042b78c69cf00abff8088ef2144a24349a367a6c217ed5856611f3d44064ba2f58585f641c368969f1be0c84d322541d7f1bf3ae403904f2d9bbc4e0daa2b1a1eb14bb6064d629c7f7ffb5186ea27dfbbedace6d76e975bc4d879f72ca6cf8058a6c18e8faf89c5c4c8d206d690256f2974e7d4675e08c5401a3ef3fdf19aca6a70a1a99ded148aea456f6cec5b87e05a1260b0830e4bbb8adacac0fa2e05fa39f5e8113ab6c53c629a7f28cffed8bd22aa2ceee9cbb630cb40d5cc8a44a98ba8ed5b3ed5319c99a8b0070cdefa3f9b386665e9dd5930e18bb7a231108646d1d2c9c6297a8a03f00f69ae3e713f740b41d5e0a6ae22bb5a634ebaf38ee2dc78836714c1b111334c39415d82bf47924c591db9abf16e70a76cd16e780757137fa8928924fe0e433ac7ae099b391079e3f04d4cd107b080f8a7ffd845dd13f17db971cc4392670fe0b250975b209c57387663b8c8c0fe09839bbc05c821e29c7d41b683b10e420c3cb0af82db92abf58e4631233691259345fb9ed0ba227486fbe1efbd215471172b013c60df1e72562439038e83c10942c61bcf613b2c83ef58fc2f5ab8e2368de87392c093d1d652cf3d2a6cd12149ceb64cb6806901114364635221aa83d258bc0367e3305653ac03726d93db99b486b55af18faaca1bd2c8920fc09ff1d03b9c317a6ce578437ba9ec7606a3f0df965edd03f0119c1b1ca0fea3d7d318e68af767ee0168a0ad21aec87825b36dc7bd43b9ca70306e3d387d4667abbb1f024a58bf2fabe56ba49f6a0b75529b33a07ab29f41f0083bbcf1d9d9d98e7acbfac7ab51a98bd5d5b389f64ad13ef0c789e295b1921ab0a470da077a685c84861e8942273c0ebd548ba19d1941471ca03f96be800a52ea7254c3d2d69ca24273d53beee8e11456a07437ff9280fb9de9a1a34c7cd92a7e89498c64e584c994d13395c2460720f81554639b36a9163227898252b0fd99ed3a9156ab65feb8fc70ab1f837f2ecd66f936706cd95b2698f89c9798d6426bd121e11e0674140721c8be3f610aba6e7bf641fc2cdb02b0439e4d8bb6670c4b57038e4db59fc497416ac60bf8f95c3cb01074d83f4b2b92c19ecf2746484dba8bbd4a38da8c23b6faf4fa516603b0c75f2aadc860d3ac5189045fe3d6106160bc6ba2866223c1aecd1547a07a2c3d806137afc843bfca802cad87552afa0c9d1ac8b22c1d6d5fa2f001fad62bd71f24c9f846bd332524044de306c5e62385b40604680b4a2fa276451af36a6e6c89959c0afc48c420237da9f2f4cdd3dec126f16aa1e1f1715ec49e04f98265ad14344b0ad08202c8ae4d8a92dab7317e5bdf42daa1c1b551ca6a147433c632f233d92c99202facec89354a2213e10b125fd", 0x606}], 0x2)


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r0 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
r1 = shmat(r0, &(0x7f0000001000/0x3000)=nil, 0x0)
shmctl$IPC_RMID(r0, 0x0)
madvise(&(0x7f0000000000/0x4000)=nil, 0x4000, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000017c0))
shmdt(r1)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000100), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105727, &(0x7f0000000040)={&(0x7f0000000000)=[{0x20}, {0x3}, {}], 0x3})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
socket(0x11, 0x3, 0x0)
socket(0x11, 0x0, 0x0)
setreuid(0xee00, 0x0)
r1 = getuid()
setreuid(0x0, r1)
r2 = socket(0x800000018, 0x2, 0x0)
r3 = shmget$private(0x0, 0x4000, 0xef, &(0x7f0000ffc000/0x4000)=nil)
setgid(0xffffffffffffffff)
setgroups(0x0, 0x0)
setuid(0xee01)
shmctl$IPC_STAT(r3, 0x2, &(0x7f00000001c0)=""/4050)
socket(0x18, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, r2)
listen(0xffffffffffffffff, 0x0)
read(0xffffffffffffffff, &(0x7f0000000240)=""/218, 0xda)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0xfffffffffffffffe)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x2, &(0x7f00000001c0)=[{0x6c}, {}]})
syz_emit_ethernet(0x62, &(0x7f00000006c0)=ANY=[])
r4 = msgget$private(0x0, 0x0)
msgctl$IPC_STAT(r4, 0x2, &(0x7f0000000340)=""/235)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x6, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0206923, &(0x7f00000001c0))
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x8020697f, &(0x7f00000001c0))
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000001c0)=[{}, {}, {}]})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x8020691f, &(0x7f00000001c0))
semget$private(0x0, 0x6, 0x240)
r3 = getuid()
setreuid(0xee00, r3)
getgid()
geteuid()
r4 = socket(0x18, 0x3, 0x0)
connect$unix(r4, 0x0, 0x0)
getsockname$inet(r4, 0x0, &(0x7f0000000000))
getpgrp()
getsockname$unix(r1, &(0x7f0000000100)=@file={0x0, ""/72}, &(0x7f0000000280)=0x4a)
geteuid()
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000080), 0xc)
r5 = semget$private(0x0, 0x4000000009, 0x82)
semop(r5, &(0x7f00000000c0)=[{0x1, 0xffff, 0xe5ce97ab354d96be}, {0x4, 0x4, 0x1800}, {0x3, 0x0, 0x1000}, {0x2, 0x6}], 0x4)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
r6 = socket(0x800000018, 0x1, 0x0)
bind$unix(r6, &(0x7f0000000080)=@abs={0x1f95d27d48731892}, 0x1c)
setsockopt$sock_int(r6, 0xffff, 0x1021, &(0x7f00000000c0)=0x5, 0x4)


r0 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x1, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f0000000080))


semop(0xffffffffffffffff, &(0x7f0000000100)=[{0x2}, {0x0, 0x2fe}], 0x2)
semctl$IPC_RMID(0xffffffffffffffff, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000340)={{0x80, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0x40}})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001280)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000180)="bf3b684c5ae963b4567084e096cf973983b85e5df63e013eaa9405095e88157332b4f68e78e0793d3e30417acbf4419893cfd424b75262dc5ade2ab6278ab86672f9ed186987b8c19d9295a17b98020f6002", 0x52}, {&(0x7f0000000200)="2011002fa640468441d5a9bdc238b47a75b6f0b4a547b23d038ec16a0ebe9a819eb353a9e6b9dd1a501cf4e590cb7779f2ae2efc81ca5051b5d2609b1889beb7aa22285e0f0bfe009a53d6", 0x4b}], 0x2}, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000002c0)={0x1ffffffffffffcb4, &(0x7f0000000300)=[{0x2, 0x7, 0x7, 0x9}]})
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b1000513000000000000000004000000000013fecea10500fe3c9df96ecf2ac72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf7f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f335c223e7d0c032bfa896443a42118000000720fd38bfbb770c1f5a872c88106002ec5890400000000000000361b1257aea8c500002002fbfe0c2300008abfba0900000008e371a3f8343712051eeab7196fcbd80407000000c01120", 0xb1, 0x0, 0x0, 0x0)
semget(0x1, 0x0, 0x84)
munmap(&(0x7f0000ffb000/0x4000)=nil, 0x4000)
r1 = shmget$private(0x0, 0x1000, 0x0, &(0x7f0000ffc000/0x1000)=nil)
shmat(r1, &(0x7f0000ffc000/0x4000)=nil, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
shmdt(0x0)
sysctl$kern(&(0x7f00000000c0), 0x2, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71", &(0x7f0000000080)=0x15, 0x0, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socket(0x18, 0x4, 0x1)
mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
r2 = open(&(0x7f00000000c0)='./file0\x00', 0x182, 0x8a)
open(&(0x7f0000000000)='./file0\x00', 0x22, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r3 = socket(0x10, 0x2, 0x41)
ioctl$FIONREAD(r3, 0x80146951, &(0x7f00000001c0))
r4 = semget$private(0x0, 0x4, 0x42)
semctl$SETVAL(r4, 0x4, 0x8, &(0x7f0000000140)=0x2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x10000, 0x0)
r1 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
write(r1, &(0x7f0000000000)="5429102bb15d3d2145", 0x9)
writev(r1, &(0x7f00000004c0)=[{&(0x7f0000000140)='a', 0x1}], 0x1)
execve(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000001c0)=[{0x87}, {0x7c}, {0x6, 0x0, 0x0, 0x4ff1}]})
writev(r0, &(0x7f00000003c0), 0x0)
sysctl$vfs_ffs(&(0x7f0000000040)={0x4, 0x1, 0x6}, 0xb, 0x0, 0x0, 0x0, 0x0)


fcntl$setown(0xffffffffffffffff, 0x6, 0x0)
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$VMM_IOC_WRITEREGS(r0, 0x82485608, &(0x7f0000000180)={0x2})


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000700)=[{0x44}, {0x2c}, {0x6, 0x0, 0x0, 0xfffffffe}]})
write(r0, &(0x7f0000000540)="76e5dead6f01f8607d2100000063", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000380)=[{0xb1, 0x0, 0xfd}, {0x35}, {0x8006}]})
syz_emit_ethernet(0x56, &(0x7f00000003c0)=ANY=[])


r0 = syz_open_pts()
syz_open_pts()
syz_open_pts()
r1 = kqueue()
kevent(r1, &(0x7f0000000180)=[{{r0}, 0xfffffffffffffff8, 0x3f}], 0x8, 0x0, 0xfffffff7, 0x0)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
chmod(&(0x7f0000000080)='./file0\x00', 0x40)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000380)='#!', 0x2}], 0x1)
writev(r0, &(0x7f0000000100)=[{&(0x7f00000003c0)="a15c404ed886480e8222626905a0817a780703d687474a40c79015bd411c6ef41570fc4c33bbcc41e7a094712aeb4fbdb8c8bb9ac4c3f23ba5eec8ddc6581096dd41f87f7f2aef8997092b42d394de4af8070a", 0x53}], 0x1)
open(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f0000000080)={0x10, 0x0, [{&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffb000/0x5000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000800000/0x800000)=nil, &(0x7f0000d91000/0x4000)=nil}, {&(0x7f0000f56000/0x1000)=nil, &(0x7f00008fb000/0x2000)=nil}, {&(0x7f0000e4c000/0x4000)=nil, &(0x7f0000efd000/0x1000)=nil}, {&(0x7f0000cd3000/0x1000)=nil, &(0x7f0000862000/0x2000)=nil}, {&(0x7f0000d3d000/0x4000)=nil, &(0x7f0000aff000/0x1000)=nil}, {&(0x7f0000f6a000/0x2000)=nil, &(0x7f0000887000/0x4000)=nil}, {&(0x7f0000da1000/0x4000)=nil, &(0x7f0000b4b000/0x3000)=nil}, {&(0x7f0000e0f000/0x2000)=nil, &(0x7f0000e03000/0x3000)=nil}, {&(0x7f0000c64000/0x14000)=nil, &(0x7f0000d93000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000bd7000/0x4000)=nil}, {&(0x7f0000913000/0x2000)=nil, &(0x7f0000c5e000/0x4000)=nil}], './file0\x00'})
r2 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0106978, &(0x7f00000001c0))
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
execve(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, 0x0)
syz_emit_ethernet(0x138, 0x0)
ioctl$BIOCSBLEN(r0, 0xc0044266, &(0x7f00000000c0)=0x10001)
clock_settime(0xffffffffffffffff, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x2, &(0x7f0000000280)=[{}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f00000002c0)=ANY=[@ANYRES8, @ANYRES32=r1, @ANYRES8])
msgsnd(0x0, &(0x7f0000000040)=ANY=[@ANYBLOB="02000000000000001df33699fb723383"], 0x55, 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
sysctl$vm_swapencrypt(0x0, 0x0, &(0x7f0000000140)="118bea625d95de8f92c010baed45ec4bf03ace254b57973bb6de7b1c90301e9d3b5e6fb6ffffffffffffffff76c775a2a4e0556565a830032eef776127fd247103c14ab0a1cea9b4593be484f46a02ea73e910d041c5777bd852e57d3248832b91d06fe47d126022a1654859149e9486306d2f11fb1cc826c42f81b0d114f8af4ceb029a5210bb6947464bf678ba1d64a2013131fedfe60443aa13e015b28a16ea924bf89ad45c006213a6d0e194b9abcb3ddfab0c69b8c280bfc9c11f26026f6231b5e72592", 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x0, &(0x7f00000000c0)})
sysctl$kern(&(0x7f0000000040)={0x1, 0x47}, 0x2, &(0x7f0000000100), 0x0, 0x0, 0x0)
ioctl$WSMOUSEIO_GETPARAMS(0xffffffffffffffff, 0x80105727, &(0x7f0000000080)={0x0})
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{}, 0x8001})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x3, 0x0)
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0x8040691a, &(0x7f00000001c0))


r0 = socket$unix(0x1, 0x2, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000100)="03001a00", 0x4)


r0 = kqueue()
kevent(r0, 0x0, 0x0, 0x0, 0x2000000, &(0x7f0000000100)={0x0, 0x7fffffff})
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000140)={0x0, 0xfffffffffffffffb})
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x7, 0x0, 0x80000001, 0x0)
socketpair(0x1, 0x1, 0x0, &(0x7f0000000140)={<r2=>0xffffffffffffffff})
r3 = open(&(0x7f0000000000)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`\x00', 0x200, 0x44)
r4 = openat$diskmap(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$DIOCMAP(r4, 0xc0106477, &(0x7f0000000240)={0x0, r3, 0x3})
socket(0x11, 0x0, 0x0)
r5 = socket(0x0, 0x0, 0x0)
shutdown(r5, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1001, 0x0, 0x0)
r6 = msgget$private(0x0, 0x0)
pipe2(&(0x7f0000000000)={<r7=>0xffffffffffffffff}, 0x0)
msgsnd(r6, &(0x7f00000000c0)=ANY=[@ANYRES32=<r8=>0xffffffffffffffff], 0x1f, 0x0)
select(0x40, &(0x7f0000000280)={0x0, 0x6a, 0x0, 0x7fffffffffffffff, 0x7}, 0x0, 0x0, 0x0)
msgsnd(0x0, &(0x7f0000000240)=ANY=[@ANYRES32=r7, @ANYRES8], 0x401, 0x0)
msgsnd(r6, &(0x7f0000000440)=ANY=[@ANYRES8, @ANYRESDEC=r2, @ANYRESOCT, @ANYRES32=r7, @ANYRESDEC=r5, @ANYRES8=r6, @ANYRES8=r8, @ANYBLOB="6baa1408cbb97663c64f36a5c00a10c192f8cff1b5b3e3d3b77558906a6cd7f1a411e383ed116770bbf8b8f0efcc8ff79c16dfcdb2d7f28960ad0a7ecb0a42ee87dae8eac3ffc629728a20cc7c04294fab866a8b76dbd5ba13a492eb6cf02ff9735e17333636d82c1c976d502c8e871022b544f80747e99de0d7200c6d333b28089837d323fe105d63d7c1924fc4b3d918e15ed8bcbdbe36c26baecc9fa66f3df0b214a90ab50e785210a8d4ddb6244a3b21e887c31b942e0eaa27b7507c7d1c389791651d51e59ee0024dc0938bae9c2c6f5f92b3c5abc14c868f872b6da6f5a8b209d336f70bc352dda12faeda9e105826198942842053d06210c70bd664510b14aa3d87c0baa6b7095bdbb518dd0342acead49b212ddfc4f2b16c4389ce2d46947337746ec353d261390f5fb09f792be5cc89150a9ab1c7b9afd7c35f29d4d172f08f4be8f68db49597cef0588c761afa8dc97c18198efe13c0949ca17a3f81f05406e9ad5ebb5332e71409efc9225ea54d92771c6f0c1e4be3e66e150abae2fb358e67afef85ee94d0e4beb3f7cad0efa43973e07d385383c29d0f990bc74eacc5ecb79feddb458a007f14766a8c9c8f84ac377c5f90df0773213be1b459d0d81143758e925c8d32ad5ec8994e4729172dae36f0517110d8d0ba5a68e0da44306861b49795734518f4b5a6b952e76e0554276e8f898bbbdad8fdd4f8f8bba6f5ba04235a5145687c0ce2067fcfbc6317287fa9617886e31d0bbc4b7b0e797c99753fff01fc47d163ac1ec5e1c22283f715c4af455fe711cea6d943e2ef3a883e4dd8fc298f4f5366930331f4fca9adadc3f517bebe8cb63dfa48a78b57f7202e035882f37cdfdd34b8819eac620c3850e109bacc801530abc35180e1e16d3441283aa4de8c2b04d63cd3b2fe0da7d1c1c8e76559395032f9129cef01a27ea4b9d967383a0af0c3734f3ea238e8b64eb9373bc88d5a0180d8766c70436fdeeab3c3bae20fa97c284d58a0b0c2f1d70e15d1198a5f2b7333ae3e1a9203c157df61ea50ac464db448d26a207f0d41f8bca309251e73ce58def3e5945b15f7429a82af5fdd7c07db9b63aeb5b4f84234dd8f7c7e20b78860f090335d5e839b0854f47c45d08fff598931dd9f47fa183ae8dc2b2804abc348cd61ead88c6bd66ad58cca4cbcba08b2c5b2fe55b3e1f34860a2c88f5d1c7c5fb1632e9eda964607bd57eb4ab6d26476951219b061858f99a30b029e79b0d240d18fa1fc0b6cd9a9a1ab8756777d1f527769bb22021f5a0d5200ca3e453e8f53e4b3ad0032dcd3de19c15014d05be6ede5cac802f47b77bc793282567f51c908038407ecdf1c7769a7a2bf20e92648ad3367ec7f5c3966cd8337463ad7521bc7c80b33c7b5ba7dd3d244a338c87ae51a070492fdcd89ce9246839a5e312a7fa0380a7079b98ad58fa5818fc0c40c4f13e3de73fa0ac6a193d21e2ee6dc3c0de7e30f85ea966852130deed2f20cb21316929deefbf7adcac51f81a3b236220010315aec380828d55c6b503ee0bf991e0861c1169092de53447029b438db4546c48c9db0d24dab9d993d1ba6ebe9ae62e5dbbe45341daa52aa1ee5d795ac2e584893a1ce652b6ffe0c33184a02a076f7a4a37dae66ddcd8e5da0b770369cd76531211e43fe05f15ae24b9fd9c668d48de3ba78b7dff42f85808cddb768d28ee89d2be0136f8e4c7298eb7d8b0449fb30a73dbc05a5984229afba89ab79ec693c7859f6b96c603da69b0fac72ea19647d209d04dee6c6c2624f959b2c099101ca17131aa081ff6f08724b20ead3983b1a4214884913b1a2412348dcbd574d1e0dcfeb594be33d79a48c4795d910f686b836343caf35ad883f6128de075c52382547c5d1b881ffb804a9270ad250f983d748e39b7a6b46492191ff74755d538ef2fdfc465572a58921edc6208991b5e321e2283b5364cb90e07a28ba9ac7a3720e52750f1ba4b8b9b2a69f9b2ba824ac87e2797140166044a9e6e85e414ead63bfc4058d563ad2b43763ea6a032df1a5892ae41f73f6e0f83aba84142e36e3e4343f47e91692753b3743d877286e3a36047daf459174f41ee615a3ed1c05b41b3c0237deb9101172ebca5b41df23f70cbcb4e21519bb8cbb4af89bd9eab729a9b762d44b0411c299a17c11e5b0fc6578efb0e2db1d95fc762c82a5cd776a2461441ec71b742930290be9c608fca67e95cc4136d8d8a71ca44728c38ed0b063124e8042680365f02b5c11a5cc17d0d637522d4c57cf850acd4b4b2dc168037a78240f53541534f61cd9c6138f343a69a2a2d5dc6f405f38471df30cf50766cdc3cb05f1ad26eacc1da3ed69fbada77ab689a1f0640a1251837fd228424d61ca24bcb83c65a9483e35a01537273f01e8cc6c20851b1de81925f8a88d9ea3df72386a16c895f2c1a27d9277d52bff18e545ca10fe8d1d343cc8e55529af0dd49c937f981f7eaabde3f32a192eedf0bd7babbfdf80e54597dea0d08c82cb787cfa5d3eddd325141eade69e969775a0528cb68c72da8c2af94148192d59c94e828a4d151a90f54bace26f0e170030d2c066550982dbccc00d6b59d8c6727182e910bb0e2638ef4539e5c34057d43678e915e132ec85214ec928537af1add1d6a9d2a14f6548ecd9cef51340966c1794003f95bb38979d67c7d6373f22a2d0e7825876728d2e27527ed9ddd36589e506fdec86f90042a1e3d3720c7fcccc7057ffdfa0fe4e73a8e50acb562da6dcfa9247e5a26da054b7d1f0925fc79f89ac84938fdaca6867db8ec3723a12bfc8162f58c2941a92521bf9bd5182f8bb3270f3a38af4973f1f1a31d5eeef6f84f1545731802475f8095f940a018dd91378703c9e213a70c56dd620174b1503baf685f86a22848723fd461cf417e7a122abc6ac8337c0f6d35bf11ea034788bf1a5813788b98fcbc55f22693fcac885b2051c3687dca257406194ddd2805724340852957af5cc6ff13c51abd2f430bbdb31bfeda192cc44073789321063cacf8cd75dcd3b21c15131416582d6452296e664e382b96284b382540bc697f0e220062b9e77661825b8a86607cf6f23210597f35996690f3a073b684507d4ffcf1e2498e3412e3631cd4aa6432ef0d816a15a6844fe0dc00ab1c1f46aebc70c6c25da2fbee7ed3631b0a6d8a83bc70a8f2d1fb4cf7cfd1c8e9a0b407806c6dbf46f61b6df176d5a149687a42a2d82586dc298c73eb622563dddb25eb3a8d340a1a2113ab871256a8d5bf5e18bbf393c44be91589a646ba28c9b4fb8f007be72a95f774eabde91c902d0f46078255b691aceb4a1b256d41c3927ea440adf4d32f4e2b49ff5d9b1329c81d826a62bbb7250e4a70080ce8fd734aa4317507059b992c75351d1117a581e3f1f93628373587df8295525e0588937dbe2268c1164455439961637a3e80e6b078e4f151932f1c9a89377ad878721264cf098ab40b4326378dacd6c42ab4a42268c5cb60f30277ac0cbf66e8d13d0869715378011230318ad0e72fd453ea27b43495e5c31c1ff4c8fc7ab16414064a8bfdece2b2714a5def5b605bacd6984158edcad234c79d25ac03bd10edef60d5862092f8934f8d986139e935a869cc4c3dd32692fa33b3207412cbebe4b00ff34f6c3d06f4e31744f0387a788f32700bc1eed6bb1ae58406a6491e7414e69856041f00f924e134bd99ebf09f8e4d7f89131304ad814e0db0c085b24dc93faeca361eeae46be77d1760ada2cf9ebf1145e57a889334588405ab57219fd55493a4ff29a10b203b7ece46f9dab8cae9ae755fd3a0490ccdc2dcb063eb34dbe808a66ac68232de7998a16fdb0e50d277d5491188842447d35e4ee3fa999bb0ed5788e495e168fc773faf6069728c4aaaed421b7d87bb956574599fe12f1f4b6a8c256fe975525f321a32052bb66227c59651c5125e59d9a4b36aa75e8109b24dda38b51f622b5f74b48f07f591f123c1527dba2084c5d790c0f7be07be3916746a67684d29c54f6afa858e271eaa5ac8131afdbce6c0c3659c1a26eb85624850fb59bc85e6571778a4db0cb1a71feaea87d1be8e61a3c15a7810d7166febf1a3a14d6438fe4f3ab55827d1e42139501fe88489842796d80fbbb9007637591658d7dafae0f9991f1b731a0d2041df88e1f4b0b445213360e6dd2ba9810500161cad30f404144e4ddffd00f7fa6348cfef11c0c3ed20f4fe95ae96ebdfd31b49cffb1ffd42fd9b29d36c8ab41907bab3566f4b8adddc19a0320f0f2205cbd091c34e6af03de658d1d9cab7f30154995ddc514c9e54dad6e58e5ea4bb3ca68eeaa9e80b20de9d12651cdafaf85435453476e20ca18adad32e51ec508bb75c8ac260c9cbef1d9885e817c25bd89527828cf0ac1e9bfe32ecd15f6fb37208d872ce5102af08ea9f99321db37b6597373248d092444777682b2ea4ae50dec9d284ff5bc00df25186f4f35ee2d94ac04c0845bdefdf208adbe872ede5cc4aadc015e9501337e0b69b2c89ef44abf17afeb68b965499b9c19c147ea32229632b9456b61147f8dfc53e5624a59467179a10834d8595c04408a1959c4b80bd96ba382c887eb947dfbed18cdc6bad0f349eaf61ca5b15d09a85e621e3bde917e1e5b8dd1f470b6e653be8fc451ef055f90cbe86ca3048ae3ea086e31694a67b1bee3620716672bc032087b9407e2fbe7fc99d7906cff2f983a4f2d4e5c36bbee591efe6228c0fd6a282f3d75a5df15cca0e43a735bfa2e53976c93dfb5c71624cf7b462fd09261c081140922eeb9164ef386b004854b2d7b16744793df5786ad9e690f97013195753a992b7afd323a64670bb065651c97a3e87276e85c44690e108f9628ca025482c4a501b537d7363e359581ade0c7b10e4c7876e8216096b9786ed370776e0012fa028a39d237e3eeb1a3b8f414df306873168ffa0acb67b7d77761236fec30a094247ec5ae4736291b7e3884c60f332dc0745a99c9814bd757be7b5ba922600c1941ef54d66c7e63823b541cf0407cfa3966f59d3124a99d6fe1cc49367613ca242fec4c313a5ae758f27061f832746a92425864eff151b9e52d4d74901eff03c71302cb8525e2fd7fd5c933c91c78ab47e9c9409696d235285eed56a741aa3232fcf9b07c6046473a181123f4e45c460e2e836107d905ca185b755ba205fd3a64e79b98618e060cf0f3bc570621fbae23e8cc1099c33bf6da2fb8d67201db897d71d1f8658201f26089b865328cec1466f27217ab330f56ccbcc167be0ab83fb8450b97c45916f02ceb92617a9cb278887db47583b745cf8cdaf3aeb114be5681e366c4e8386013bc98fcbd016ddf394d52acaca30b0be0061cddce85f98d3f97723df98d13416286422734c1f3befc25db89d987f803b01dc8a7b53170ce784e1ec940f77795233f7815a5a3927b53553e89b1053c13c68adbbaf84c8db06f57ab101e1fbfe59ba3db4af325ed27a7622a323da917a300590da6bea48003cb6ad7ae1b309bf5620111ca905a3125943aa02e62fbe412052b9c20278b20a58e4f89c38b4403c10263efece15ad29e388a9236f7cf1d7d602aee56e518038b24dd615d71f0ae90dbda14a213d1a15572f5105086bf7ca6d16ea7b889f8944c6d296f1461d1c28102dd7dc146b2ec85ceb4ffd9ebee4b06b5593c8394921012ed12b4f7b2a7be1cacdb3c4059ca49b8a7c8f7cbc209514671a252c0c6bf56efa3de4e08e384da4a407688cabd963608dab70d5b5f5924ccb9d05ab39ea3c206b9ffb0145b116ae7b453d6"], 0x401, 0x800)
msgrcv(r6, &(0x7f00000002c0)={0x0, ""/206}, 0xd6, 0x3, 0x1000)
execve(0x0, 0x0, 0x0)
syz_emit_ethernet(0x49, &(0x7f0000000040)=ANY=[@ANYRES64=r0, @ANYRES32=0x41424344, @ANYRESDEC=r7, @ANYBLOB="e290786ca28e44a89f59ab1c5721d4ee7fc74d7efe71227498f27f60d01f76a3548deb5d303c50dcacdd547c23afcf3879d584e5b05700000000000022000000000000000000"])
msgsnd(r6, &(0x7f0000000100)={0x3, "1b18f212a6f34c1c20e11229827b6640450885396ec261592b6554b6ba051ba9a5d7895c5ac9ce1cb6e84191b2726cfac510481b18d7dd4559ab66ce8b9bd317a26a842169d4586d5410da25787eceec027704581e81ae84"}, 0x60, 0x800)


r0 = socket(0x2, 0x2, 0x0)
r1 = getpid()
sendmsg$unix(r0, &(0x7f0000000440)={&(0x7f0000000000)=@abs={0x0, 0x0, 0x0}, 0x8, 0x0, 0x0, &(0x7f00000003c0)=ANY=[@ANYBLOB="1400000000000000070000000000", @ANYRES32=r1], 0x30}, 0x0)


open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
syz_emit_ethernet(0x2e, &(0x7f0000001280)=ANY=[@ANYBLOB="b1d3bd0a0c02ffffffffffff08004a"])
socket(0x18, 0x1, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
setrlimit(0x8, &(0x7f0000000400)={0x7, 0x54})
r1 = syz_open_pts()
close(r1)
r2 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0x37c, 0x7f, 0xffffffff, 0x1000009, "00df00003f00000000000000000000006d2b00"})
writev(r1, &(0x7f0000000500)=[{0x0}, {&(0x7f00000009c0)="0a8c03b22d14d53f540a8d8f1045590bc21fbed2165542014afa6a39f722319cd481406df7660c56c056e7f1c61aaa286b2fd5595ad06f3c2c2af2ad07e1579d5ff0e5edff5960b9079e80d6bb9a1b830080a78b4b7a73b9c99c1f01000080000000003e3fa2db6a81c71770abb3ca30bb8e91e502f891b073cace886ff1883458e1b409b12d6ba022c39c8f2065c15c09ddbdffbd1830651d0f2d0f4673647d30", 0xa1}, {&(0x7f0000001700)="274882de9dbfa898728a4c6c8eaeae5dfe8f554f430d38088c37f3677a433dbf13fc099aed8c642c03e5d80552ddfe5835a3cf9bcf66a9720f252aef18f954c6f0372de3d257e0b5c685e81d011c6fe99ca1dc6c9a91195dfee85a45dbf36c643809e2c292a76619d8ddd93c9fba33d333e540c46db39527c25deab308fc36fa10a7ed056def7a219a04ef35c35009db50751c0aaf77bc57481d5c918e1943caabe688e480409e4135e6e757e0590704fcbe1cd7be7ee039d78e2a7c782655c2ec7d1fc898b74ff6bcb2c6b9ada667e79f422bb4dd66f441d235f1a87e9c36b5f0f4463642813cfc779569fb293083f997ffbfeb6de18f91e95f35fb971d9306b04205dcb3720c3a4f1dfd37831987bd909aa261c50de43d08f2f880f9db702b1b10621f5fe061918929e31d73a2522230d55aee33e2fd13099851fe99c288c38cb3cacf0e63d9766baf047c2710543765872fd85c4af5fa5df2b7656202b20ebfd5bc69a2f7b2411387f72f4d47f8b537a0ad9f8f37f36d6ee1f41e8f1b92abb8bf598e038d67a4bf0c2ef43f0bae630ee6e64110fa7e8a662a431a9f25707c4b9ed9227a7e3adc161a34b2d38f633d34e5ddaa161d151f81a3dd4e6336195e28ea843702b02ce71b2f2c896d5d13541c4d362666188d0a91d835c63a5431b36113fbf551fc51467b8ef76d5ce2da7657cb5fc7fd59f1e8af41c6258aba1585f129af32b53c6afe8371938ddd4c2745341ce3279f4f022da011790715401945d6c0ffc070f31c2ab16d7028ed6e637ccec29754b9d61e07e4925be1504f0f6edf1d4f168e2f028bb54093369b16f926a76458e0b068a9d8ea4051367845c17b80e766cd9705e26885a95f45141160b09e1425ff76dbff3f7906ee71738a060cb1403a9b2bf463f65247e646fc8d74c74e875a29f4adff77cae9fb46ee94d29e9b3cc9b899f0af440f4e4744370f0f0d1e270b74b493db38c470600fa63ff49c4717a76f527c36eefd5bdf7d09970a4d4368aff2ea97d8ee4405e33585a35824fb0a53a415e039280e810ef917442f82287e1eab6c0d549963d72085869fad865cdfb0e0089c9b27ce9799a67e92bf12430e006eb19576418daded0bb3320e14c254e57bdeee46bedf66ca27ae7d28b8870275dc266535ef5fa216eec42424537114f8d9d6f6d3959d4d8e8411d449a76d9e09bdf71ec0ebeaea3c2a532e1daa69ac400c52bda3f9f6e877d54f0002511523482cda7b43eb5b7d2a5820843d7bc0003485dfd76d89695c236114c6ac37e10c2e6d7d29076d8fa44680088450017a1956688dce236b26cf66235643cb3726ca1426038feb0d36c6b4a947e91dcee3da90ae6b67d4eebfbca0ae569ef52b3cf5b637a645eaa5cff17a6e989b42c20c9df6b380523c98fb72fa22403407660ae24b639e936aa052529bad1e87c07b2101a09829a6ea6bb3978af315eadde16b398ac6fd1dbc1dcbace5fddd98f0e7fdc845031edd7d9171ba375b69c7872a62f97a4b946cf9d796152d047bdf308acb83f7c6d977abb07d571072d09f9a7c1ed0dcf633c8df83d76472183f275a3ad01cd0bef9611c435d7e781a777b7452c74cd4df5b55ea430a70ef8d166945d91215e3b91ff7a6f558cba617c783010b3e5754ee5bfddf511bc43d74b124358c553122bd9c80b4bdae22dae19702abf765d3fa07d136a60eab7805df6817be4c1f8c98ab2be6f770b6960cc8baa899bbe309da07896aa64ef5ad2d13385caba76c7790e22b0a3c3decb53776fc0d63914a66c6eb6180c90682f6b9e9b713d2a3a2d39be5534ed77aee9997d2bc2d95dfa22c76542b05deaedb14a63133098625f913a8dc43330cb978aa29ef95e7e6344fadbb309af7ccc29754efbdffc1eb8234b59d902cce940858a50f4449ab625908ea2e64d42e100f889ddc96127e25f75bcfb0e493cef0ad1a710af1aafe399d48d18a81546fa3a9f14a8a2b4c868f36a6acc8b3cea213caa9d4979d0a3e22cddb87f1091e55e705976fb96b3cebd7722037312be42f937d9fa9494f48facba22a5eee1adb5d6c9fa7ea4d2e10b4ad14a4a6df4dc474309df6234d55df6b69d46f68b873276fd153eee0ef2c4df8235abb178eb9dff7f410aa190e42dae5948cb39be50d0b3378cce2323640fb4c0eddaba0cf53b984ebefd5e81a0f2c834bf96db7fa9e753e5b0e40a242dfbcdafc78ba33dae1bb00f39d6a7cc2fdcf2935c31aaf4b4f222dd9dbaaf219c18ad7aaf2d146613b82d790c735927730f10628f66580183c24966ee65bf4522ecc0926835ba882570abe99c4a61391f280ef609131e695ad024febbb59006ee78a9be537668ed4a95ed201146428a5f3f2d4b1f12f21f85c1fc77aaadfd6d9137d3bc8ee51d24dcb81ca06655ca7e18a0ad767f643fc2e64f3c3b26be112c18876a2349bbffa1de87bf8a1c91d2004c5aa8407746178863ba2aeb83a0de6b063be25447cea5321d86acd642a1e94f8b6b04f0362b21005eab7be480fd4e88dc0660f71e9bdd559828ec0f026efbd14cd43a64473b1a5a8a18a5f939667dac78327ebcf6a85066325846caf12a54c6bfd885595df82943a644c624ee94b9890fb5a7bd0a23bab9277595f6bc591e26915ceed69f4599731c2bb4bdd12beee7b2e43c4aacaca01666c8afc115d80f2c70f5b61e9c9afd1fdae5ce96c75d94d44c5fb071559a5dac3d8e10e08636683ef03ce70cf35e521be6fa12a94986853e6a4b5de57e5a7cdb2252bb4d0d24fef1b22bfe094d0d87f3721f992d98e02393ef30830cec3c5f3e1c132e471ccdceb036c86b0407d6c4a7c72581ea29213a84b514b3abaad21292c54ddb678610fa484bba2e0f22003dc5d402d51d3fc99d8ff34a288c12499e33bea194a3ce7b81d37d5ba31b29c47acef34dffa5f98103deb2481f0bae91991f26c16bafd8ab9b530a6ee91c03fd33d798a9556bf9ef39479b8f5abb051f7104d195b4073f90259da6ae0ee07833d20b89eaad12b4df8c8236462ddcb149529eaea47a63bb3fad8fea8b18fbd1881c49fdbabe50b5100c3d283ea58daa3fc89b2b8ae5087d7f19b4a13ee31ca3009f029e606bbeab35680447adb7963a07b465d404631f2c92adf83d7abddd5bc66bf09d6bc999b2bc7a21de72ce563ef795ad741df935680a1942bbee368c2ffaa5ba1e3101d9fcbcd4ad38e076ce7a60b40f4db44593306bbb99b3e25fc2ceacf1a864b1c57615838e9b802f66acf43f251a7de0a33b630a47b620a0b0a7e0521c7472fadccb51dfa7aa6ad77efcc719664946b2d81c37db8150296a888651c61a0cc941bcef50a706a18eecc330daa93f416e458fa81de33ec4b2a07f90e6262fcfb05d8a34f47e18f19407a52d7c55997a3465e9af81b0a0c95660ba6507cb93dca754ada3ca38ec25b269381fa421ee4ea24485af8b09e6bc05ad980385d3837eefe1bfd39d26f8197a48fbed305db9c67834571817c96bf961367446dbc38ac08188c2344b0b8a60dc79c56a89fbdcd2c93d2cdf61b1d8fb2794916af13c07608342b4c0830cde55a27c6f9c267d96d3483f21881064ebd4ea2ffd7a1ccc8c9b09606d9f29b59a15e511d7ce2d3b8813fb200ec2ab048540b77e28b3ba7c32a73a170e4c2b96ae26e6b3bdacd44f902887a131f999109fee72d5eb76c39bb13d6ec8acf13d62503674dd0633687468ef4aa4b943004aff525bbcfbf531187f03543362cf61bb63320eeb2c91ea7459de7154f148b08651964d4712cee1e7248cb8340be320958f6301757c5906a0dacaae02f4764f658be694ab754c1cd80976f807b08f8eb451724b60689d22f6e8551493f8ef63b2c49ec789396421126943a125471be7944b924f8f0325903e523974fbfc7d73e89b74ebf56596e2a635da9d779dd1ef7def0129dd124b9ab9d732fb785b223facc18f94959902acb5803533a3edcccd7869337291b62771d13250af6c7f8a31c7adc790a2ff2394993c157fb4b9c17f253653b385d467bb4029a6c5334c765644e95a152d4fdda779f9ae59998b3eb66dcdc8cef99455e777ab0ee1b46bdd5cf90c1428c49fc4e06a2cdd91102acec69ed67f81c259e0346622ecf4077ec5c9b96193d2cf831ce3f6f8dcd95e1053286830cc7dbc33e9d858307b3f904043beb1e5a8cd9a0bce2f10ada41c6af2452d56071ad357ec5fe54c2967cc87afce62cd791422bb014eb342c698a29ed8ed6d8cb468a67ca6a5c9ba8cadb99ac4d8cc986d9202f9f41af1240b098e12afb6b6500e4dde240509c8c0e4e81f132728ebc629f4aec1d0981f1e28b724ab4bf85937c63bd88082c960567c08699abbf5962971ca79e6e891eafca1b3e961a0ba85bc388a31560d791f616bf552ac942b7358106df854f0c59", 0xc2f}], 0x3)
listen(r0, 0x7)
writev(r2, &(0x7f00000012c0)=[{&(0x7f0000000140)="cfbb251e606bea41ad417032985e05b5725bb9a5a4201587136fda2dd727e5f62dde5a3a4482bc0b9d8726d0da46c1d908ab108ea9ec76e02493a12c1b64b1ae00f41186a7b024d2ddf2ae9d3a377c239387d08393adaed08cb6", 0x5a}, {&(0x7f0000002ac0)="60bbad4238f79f3fab424ca4a0c38f34f352c7d5c7b6743ba59aca5b10b7f12be1cfa323ff58d0f57283e760788123b4a989048b3e3733dc8e3463a3713b8e03e9be10b3f7c76b830225cc80a4a30e8bf4756fae56321aa3894ab69fc4e85a1a97cbe34dd09282ac10309c3e29b703b897fcdd82d8fc7688ba2cd139ef3f333ac048fac12ed769c375952c24e6676579a90c4f13d6d4531fac3cc94239d932935ae6f55541b41f24406ca41656dd8e889a023526bff0265e626b535cb4123c4e2bd9e951b2b4d175be8134e3b76491bf204272a534386e4d2ec00bc5b7ecc8375079c2ea5526d6154677d5e2de08d01460cc71b57ac1ab20f6debbb381f3d5952ffa3c413b9c44011fe3eca5714c9e995577c26fa6f4be9cef41e86953f7a67ba4033192ec930ee4a875fd8a2d9e7945f75868255b00c1d5487217f32d2db516fd24a770974859d3e0af7c1368405afacce6876add8c4dda7d84bb1c19850919c6c474260ca663513190f2b732650031fe7abf0498f7fe749be7e9e6ac101382aa72a6a5d13564dcec299fabf7ff328c3d4d7d6bd36dc6249e363c908d6f9b04f61d174a046dd542d71c2ef30a39fbb19573b4f2e16c51520aa99f770b838d7cac545aceed9295c8cacc2be13c08f5ea75691d965e82a6a9cbe553e86d25489b4fc730f2a7712b64df3762913d0afb06179df17b755883b27600d2c8943dd88c3a7e2cdd9fbc6eec90287719b93766304ed49f5d57c3afb3dc4cba148b67797cf390bc442bb29245c2bf1b2f2a2dff528c32ad1e09cdb8a285d491613bdb9f6e567e00184a2ddeb383e6ac4f6f51c13de680b8551e67d41005c645180a9522bab67a29c0617dcbf91dca295be0a8b9fd6c8e9a3bdc81e109ecfbeb026e2391e101a29dbf5d69ec70f783476268cfc5bd0baefee4dc0512f3114fcd10e685021b4a4e0075323ff1c94a6bb7e0339bfa8f7a66cc6d7c1e115f8d8ebbf2db6553927d78c1848463196183a7e8c92e0e3c257889d633cb631b4ff59c051a216f43b532702b4b6ec7451b3ef70a3a50d29ff2a79fdb06c6fb91d8a0a8799b6b6f9d56ed0cf3322f957dc31e1a1729a622c6738e6fa4eccdc51ad158e4852c2bf585910a3726521128386e35103072791d279abe6535f07d9affc005cd85d21bf36450cc4e1d0245e0e2ff195ab6706a0cf0003ac8337adaf54ed5923f9a2e4245e6f03823c1f3f26269f3f3f26cb664a92e773178e9d0b51f1aba3a05337c5387245d009e2187cfeb658a7fe98619a1e769883a6ac7f9c01e3e35e20f7675901ee6c2e2b31f952d35d8f2a38d6236514080ce02d2b8de01801a6e4d0588d0663db5c154ee8cd913e07043ef8045ee57dc97520c3d7c597c82d7b4486c8d94d94191e7971e2ea868304007799447fd1953fb8103afdbffb934ece4527b8797a9ebd69510bee9df749c3e68f5ce9b84d5662032c9a1fed49f81e7886cbe9122ac339f72c7e93e927f628ee59d83c6c13420e0fbfb27ce84d4b8d2035488f99d97c1b87661ef58dd62a9fedef7685ec2dc16f97ceebeca935bc8925900ec234bad42982a7e67a5d33648e1defd0a585365a97535c5d78018b7a2164540ae07f81dde252208eebd15834764dc7a56345da952d9b090aebd2a54888deb5e104bc2f54155c0063a8211269ed2c21b8f5ee6c6515bcc429a093dfd0146deb9e8a56dcc73fb36492c92195ccd793738776168791f3a224fee2a695af5e95d3fdb82b312e9bd98f4aafdd9c268f3cf3790cff6649efe9d9595030aad7b24515746a52e821c6f45cf03240e3eaafd364f095bbb33a47b50fbdc2c66fe86fbcbf7b1c077e929f8e92951697de55ef19623d5ffcb9eab8b268338b8e26a2f5587c031e95917fc9e1c0af59ab18381a39ee73077d6126b26733c4b1ad311fb5ec3496f36b460153df51fd8f3829e877104ca327a6ce688e1f1f928d98bb1731715ca6d74b5279923547399511939c382368449eb3a806ceb299241f0104b56702080154578e3883edf3baf82076aaa002950500ea3a6ffadb1020b3787a7451580b5cee54190883ab55c0674746401b6bea12bad4293f0048efba066f539d1269e0a16fbeb2daf33fd47387688b43d6bf4b4f09d7c3bc07175f954c07f6946c5f4249b7b71f802bca3bdf8019dd6deae065f154a61e151b42b3040866dc7deba7df66f03ea721787e2268e58194b3cd8d9c1f9e965cf3e87b53f466fcaea4b3c9f1853807b05db27e4a206106c2bd7bde96102c3d0f0362b46853a36a12b18c9a0b83b2bf8dac247252c7138fe258c82f66d3446cbc41fff1d6abb165c776d23f6d93053ad368787b6907b1061f86f053ac2fe0ce77d10d8b5d3d52736b6bd89446aa529e636a83b70fe4a13f364d44f0db842cebbdad2e01b41e4ae61ffd309c30666498b9164c9410dca9d90879369602ef8670fc0f82e0deba5e753726e5909234aa1e2086b711d459db6ab35e7d81ebce83c1df31b6c48808f9d52020a72c99e07ca4e0de97e9bca82e2abde799287e966f03b783285cdca5ccac3b9653d94ccb17017a37b5af22832876427b0842849696a39349faaa03ef3078f51c39e4153e1330bb5be69f1103530cc09c5cef0b201111970b0d901a70af9dfa4bca6b34dff016066863936f3005f87f971bdf723d4aa71c8dee65564d66f6e4e2fe83e2a11b097c6a14b651bf1b7e253282e9adf0229f158c1ad0bef485e7a904df7c56cab5724e31b2de2ab6d87abb85a5b7174e27c3c515c1b77bc181d25eec397987deef62ed117c800f434664ce870d7d3f580d330147355c369e6564f049ea833cda2ae8fa9e34ca1a63dbf2117f5a5dd530e85224ff495035e35ae0201a608593401611fa631faa7f8029707fc0333c219acab704dbb9b80a7010989f1f3fa4856cea880c4b3e8e2d43fd12fc46f23dfc079f30407a80956938e27c0354d4f8e3e455497e9679cf2d8b57bbccdbdb75331f15e6fcc26346346d0b59913cfbaf38b2d73091b2c5497f9a8a8d0be52c205c89860e2b11bb16976796d2766b3efb36626bf1d894fc00ce4bcefbbab2608aa37137680d64e568bab8abba22d8fc846ed607e2fcd80a64f11ffb589514e3758c72f7c485a0e62b21de20fb2c481fa14aca0db56fe998247e9f41643b171b904cdc4babb4dd03533bc0b90deba0b66b103492d0ab79b2ae63e79484ebf0ad96b32da892ba082991f77ce7475dea0390f837df5bbca8a64934d722912d651b3c09b02bd3cf2874d3c8ca66496db05c6392963383cd417fca84a4492901d5a532941bede6878f2c0d387bc93439e1e79472a625bfc6f78c54ef44a395da80e6c0b777a6348b356af1c8176087ec63f87555afb3f6b594ac2fee5287b9313a556a3597c69ec3ba1fa1ef3c46c6135fbe78fb739af045d0c0ed99cfede95d7eadb381cd160f3bc34efff00ec4c417e49675c8b6b1f2c3e3f3f66c0db57c468fc7f7a48ff7aeedfa6814e5a0bdf5946f7018558c990e3ce934456b27c6a082481791de85712a334e5efe61e5863647299afe3157d5b815c9935512473ede307e8a546b32c3a85cc65a71a2f9cf4d89cb6d0451789ff6d47cd64448dff7a2cd03a11adf2ffb94618e50221ab6a9718d56dea31af92318f53bb874171f3f34c07b2d9bcbafd944cb02ada658ea094972fc68e21cbef4d884cc594671146ddaa3843fccd56af84aaf0047b2484a24c3b04b067a00dd89a097aaefea71f187e0581fa01a102056b8d26f4cb6900eeb26c860eeead7201fd2d9f2383ce5ec4f330d059dba708ab3eb6ad6662a168c3be14e226791a7d7168495b5826c8b57ba819ff359c984de9daec5273a2853675756a9422ef0ba8bc08961b333d7bf702db9dab08fdca1db9ab42fe80fdbbd020a4d0bb1335df43a8749bf3f5f1d3a30e130e8b7b43e7f78cfe32d0b324e1dbdf151b73cf2f93a7315b080573b4b819e4264526d30f987493d1597ca97f82279cb23eaeca4ebe4ece55b8e09a2deb15c2ae49898f71b7f5694e7e6089ee434c01d1ad586e63dc05e7074be8db1019dfd6ef54a10831c0fc551bed0ae5e40b3585bcbc4b71537f4a4b6b4f355598c897adb5228db77002a2cb148d90c7ea8a4e83af590b48342a053a4240a4239c16ae937fcfc7da372f6b506a761f60f70a8af108914e4aa0050a64a7ae2f73b557eba12166224f32f095e0b91b9f0a75a83ebdf96e59878af7948c553437147187aeb2088910ebc5498711a9443715523140636311999297b504cdbe084e0c5a99b9aeb57bbb974c51b0a49c30cfe2f5f2bfef509258f2d7cf5217b83c710f1ae4bd33a47d17f349779221203baf87c10fc3f93e6c3d2859676104769fedc10032fe91a5d6c027e7371560728a9dcf814b44792721e23973873550ebab1795da12b73ae5d895feb51709406dd3b18ff53fb5d3af8b0b714e484afbc262ba6f2a720ab0b18cf75d1f457e04928334377644332fc58a8f77e91f95d45b684818095b7e41cfb60be405ee289986f36b7e892bb7422aae9656fb031eb9d9b63bb4c70851689c40d54a17f7b48f0f97b3ab9739f937dd251689ef40c92fea33c99db294c1bcc27b695a288cfdff197c28027e7276611f8f97fe98384a843e4968bae4b1f63393346a753aa06042836b6eb1adc25d78c298a234b1cac319edf789f6abaa6d67094fc7f48b24b92d030baf14955159339d38a006fef1349bb73b6fec03b9119f97ea753bf376210c467520eb7cd052a36161eaf5062be089fc657f8fa2245a5887b29c26216a143382bb5e3b77b6f2cc5559a8c4915c496548734666470f24dc19d65f1a0ac2dc1b553f0c3af1510fbcee5f57461b6d14d3bd721e62238c06e2784f1a012fde89e352bbf2365b565d50ee27246fc00bd62fe46ece7b976802a697ccb7c717f85839a6e39b20bffd8e0e25e7b128c962421fde44ed4b742fe7af596add878c920cdebc7afbb42800177016cdc39d852dc64040be9fc5182c05f530e669ce2d0489b5fb5ea95fc56fa3fec5e27e0b7a450507f0b3de240899647fdfe5e7d52546aa7c358d02fe9fea6767d662d651ec1fb10e613b1f219c440362bcad23654f8602dddfef51c21e431c75b0317d0df0f843df1495817a85367e081e1df83647b7d07dbacc4874816214aaeae0a574f57381cc70f4cb782034e9974a6c4cf23c247e69a0f7fa", 0xe6d}], 0x2)
setreuid(0xee00, 0x0)
mknod(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
seteuid(0x0)
writev(r1, &(0x7f0000000800)=[{0x0}], 0x1)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000700)=[{0x44}, {0x2d}, {0x6, 0x0, 0x0, 0xfffffffe}]})
write(r0, &(0x7f0000000540)="76e5dead6f01f8607d2100000063", 0xe)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETAW(r1, 0x802c7415, &(0x7f0000000000)={0xffffffff, 0x7f73, 0x7ffffffe, 0xffff4b1b, "0de9f3fb7f5b9804dc1b48696d6e9fc6c9f4d3c9"})
writev(r0, &(0x7f0000000700)=[{&(0x7f0000001b40)="dd5f1642b89adfcc1a32f7e23c2a98690d12d10bb5bdc1404b07ff30aef193ec6b27b992ca6b11ac17f6afb46459b834b7b42b43ba12046b7b3475efe1bd9b26a030e2a795c6e3fb322c496e236a26755355dbb684b66a5ff972f2e4ace8ffcf78acaec151fb7c72b092574258da71eaf70c2178f36c81d1947ab964a7cf2bc41a1adeea8dc240ce496d742912e21466b3e3f9ff188eb01b5ed3c70a7beb987eea496426ad61d0075d448c8eef0533b257d7902e55ed659a09c5c3a8458788a2fca05117d427c51ea4036788eafddd35b0249f80bb374b4ee8558cc14705493940ede4ed83297c546309cdcce7684746ebb63d92c110c11ff015982a09694a252e17775c21c4765e37eccdd055ac4882ffcab35c9c63e3952861b843683d97a8cc494bc3ef7c015b7642c13d6293375ad13a33b524128f60dd1e0a5c9d41d1905ef9392715d4391fd135670251c5aecb1a9043411e98418f1e7a867ce3cee99813de64913a5fbb9a295939a5c1b46fe3fe93919852b17ef2ac032c397d8e5996648ea32c6244b9e1333f24ffe17a6e386877fe31526e9342d2e6641ff731e416d9399ad940106f5d767993f363701adfbc9691187ec28c3f4f3c9a015dd6707d6435d8d49564d7cd5dc402a251f7316910fd659c5b5e5deb44502179815b48bb5a9e1d6b2fb7f1ed2515bbb068b2fce364aede000e62029441e5ad82897269da667539276756ed8143a5aa782861955faaae00bd1c424a869361d85056226da576b52af3ad45385aa4dafec08d99bf2d8fc18821773c6941507a868b6782b6ce28e598d4cc0036c9b6369afa42b84e370e9b9f5e9f7d85d59a0fa0aa42d5718b2a30d2fcdcfd655bc2155dc3a67b37f6abe5ea194efba006a1298ae79655a1db0bb7265b04645d96e95bb7909336c3114a8fd15d3f66b03516a82e05bc7ca00f694a1f93f7366ac66e1c5587891da7376bb5f01e90aa7069d0685d3fdc623f928b6b58e213fb343cd1a67ef3dbcfc1688a85adcb4017356c471628aa717cbb4b84efe8f35f9c2ca758b879345c95c1fb9f549e36fae0d24fc1ec1f369b0031e72cc9d48c62df6a5fd9cd739d88bc24c0b2f7a48e15cdf1f647074df000b0049100fcc5d4e4e260ee8afae9c34d33581dc91535e52af89421b0319b45c5d7d2ff1a73af0c4bf490cd4a1d466df3aec9a18465775ae48e2026df4f61a4638cde7c4f86f8c02316dcbdc267e0f6568b587056de8d6f5fc0938ebd7a59c5013d230440f6a8da95505617496366ed7acdaf72153e6d4b6d93c43bb5f3b855d264c6210b83b6e7327986816a7eab80cb6a48bb9fad8c3d2b39c58841f598385673b6bb16d0472a7e4b4599c2090e1ef44c463d261d03ab9392ede03ffee0fc82356525f62db20f10faf869ac6c150a24e0b424c382213a61f2deff8ebdd8706540ab9a34392dde47693d49c954e082a7b5e0ed7ebee1524eee1fba9b73cfd074f83a89f68acb39f3ed9a4ebb4aa99ee7311a148f6699213242cda53eab746a1e95efb2bce781649d1ce6b9366be103f8c2bb37adf874be6e4d89d2b2f7a0cfe05d882f17be8cdfb0d10f64cb89c88906f8ec892b504315026e9d6f1e9ab73618c430ce2580d23ab5981a3768bb3be75ec06ab2c6c8182016ff91a692cfeecd70309cd757ae123a4ba35d7b714fedfa0e209cd5bdaae25664b74e20900a28ed563cf673ec72a9683b9194889e9eb83eb38d6a62a001e996251e52e7c24df1a473952751f54c78080ff128d63cf68f74324547afb4c88af276c02f0f11db72d286c5ef1e6fe2161871ccb94d1be345628e0d7817502558be89b7d20eb12694bce5e6486c58d6a1f54e822af0601a67ab9f3560c40fa3560c502959e264e4f41b1ba37d9f047759f8be5fea265db8dfd000df918f075a1d7b446f6ca7a656a27d0429aae7008184d69dd9ac62a02594288c041e3a27bb4ca2aca1c8566b1979c93a0a89ec85f02428f7625d276a075d056a71e1f9e45b", 0x592}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000280)=[{0xc}, {0x1}, {0x40e, 0x0, 0x0, 0x10000}]})
syz_emit_ethernet(0x2a, &(0x7f00000001c0)=ANY=[])


sysctl$vfs_nfs(&(0x7f0000000040)={0xa, 0x2, 0x1}, 0x3, &(0x7f0000000440)="ffcb278c38112c96c26690d200c98e9e4f8856d8141a96fbe9c2450a5eff43fa08ea231caaae14f0a047dab20cb1ee27b12544cd9a3fd4f5b8a706fc32dbbf9584f97c021fa8957d5c8b280f675b98dc833d5494f2a0e7ce573e4cad06ec84d890725c517de8138b09c916204edc2f53a88c9f5ae0942c220da63195d954ce8853bf6927e00c8a0bb8f1fbbd309cca4f6cca1df718191e0a814159ea6e13325df46164c3cdcb17cee5a6ec476411b5d3340e3d89aa788ee410307a5a08f30c23a6132c3a433cc19a86941e55f005a3d7aa1c6677059f2cbf0c6d3a011d660b92a01158e87508f4bb67c34aae4784c62e398893b1214b40d3fb48da798eee714d41a8e77e68bd93acaec217faf0c9333e0f3985abc945adf2cd2a6b0113059fdb035ef43b1f65b844ed913c5de6963e292af6a58d0cd607b204e975221cb093b38fdf1dd046c6f897fdf229fa616415a848f793381d95d1c093362753abeb874f813be838de4dc14943e00bf8c4fe19706b5eb1add0ef731ea76c30d0db8301e383c6f5eceb51d209a4836d8c8d2c3dd0480d8117227425d14eddd31bb34f1f36502a7a64cede38d907ff270e2e0f0beeb65815eb6542dea33b133c536555dac6a9c615fd12b270166be357f4b0e16eb76e9c42d5782f06c7b5fd3a451b7349b4ed530fb7235f15870cef23a1d3f0afc16b14d251e8cc4c25c2c8bcc75c8868ab9be5d4a2f44163bcbc11e7bba3b2f85f9f5c9fe7b1398946fbb8d5ead11d0201c2dbe115291e93c634f74dd5e5d14ec98f3ee0befae3433291f616ea353c96f4344e61d45766ee55f4f4f2f0194d5cdfddb4d132fc54f644de1e1c8b846ccb14736f84cb4a4a2c93272308281c3a89d6", &(0x7f0000001040)=0x270, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000340)={{0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2}, 0xd7e, 0x4, 0x3c72e0df})
r0 = socket(0x2, 0x4000, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sysctl$vfs_nfs(&(0x7f0000000180)={0xa, 0x2, 0x3}, 0x3, &(0x7f00000006c0)="835257c3099d427d6bc420e4d47dfa3e78a660c7fb92c6eff25cae4483b13feb1e4b6ffb94df4bb6e0a4db4c6dd5628c171e34a605ae2b70303f52981126992d269b65110d4d90fa20aceae90e3070f16ace2bb9ce2e90c9fa52065f21aa0fa7e8960e102fec3f47457d7254b21274ed25578bf4749b55516662584bb789b26d5481174e3e7e602d5177f2d068021902ba4ea3cf72e876d9be6b4fdd50858fa0070bc4e263ace2a4a8e61bbebb", &(0x7f0000000000)=0xad, &(0x7f0000000780)="4ee5b3628da7e0aabd4d5f716456f25b2ae86838306eebd360258b5c907b3ca147a8d8d494d15db55a28cf3093d9f84e53661ac6cb8c097e", 0x38)
sysctl$fs(&(0x7f0000000040)={0x3, 0x1}, 0x2, &(0x7f0000000080), 0x0, 0x0, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0xb2, 0x3}, 0x6, 0x2, 0x0, 0x0, 0x4, 0xfffe})
sendsyslog(0x0, 0xfffffffffffffc59, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
open(0x0, 0x0, 0x0)
openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
r1 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSKBDIO_SETENCODING(r1, 0x80045710, &(0x7f00000000c0)=0x100)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0, 0x1)
sysctl$net_inet6_icmp6(&(0x7f0000000000)={0x4, 0x18, 0x3a, 0x3}, 0x4, 0x0, 0x0, 0x0, 0x0)
lstat(0x0, 0x0)
rename(&(0x7f0000000140)='./file2\x00', &(0x7f00000001c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
socket(0x18, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
unveil(0x0, &(0x7f0000000100)='W\x00')
poll(0x0, 0x0, 0x5)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x103e, &(0x7f0000001980)=ANY=[])
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
unveil(&(0x7f0000000040)='.\x00', 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0xfffffffffffffdc6, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
sendmsg(0xffffffffffffffff, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)
sendmmsg(r0, &(0x7f00000001c0)={0x0}, 0x10, 0x0)


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
dup(0xffffffffffffffff)
ioctl$BIOCSBLEN(0xffffffffffffffff, 0xc0044266, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
sysctl$vfs_fuse(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
pledge(0x0, &(0x7f0000002840)='tty   \x00\x02\x00!\a\x9bp^|#\xcbhl\x97\xa3_\xbc\x04\x9d!\xd9\x9f\x9f\xb4\x96\x13\x12\xe0\r\xe7\xb9E\b\x00\x00\x00l\xaaY\xe1Q<\x19\xc0\xf6Yf\x9au^\xa0\xc9j\xdd-I\x01R\x00w\xf7\x15\x04\xa6\x82aY\x1d\xd7\f>Y\x06\"\xad\xb6\x88_\xeb\at\x91\xd3\xbf\xea\xddt\xe0\bt\x06S,\xdbH\xa7-\xaaw\xcet\x044\xc5\xa9e\xa9\xf6\x1b\x8e\x05\x86\x91IsC\xb9ul\xaeu\x94\x9b\xaf\x04\xc4\x03\"F\x8f\xd5\xe8\r\x8d\xa1\x00\xcc\xd7\xa0\xe1\xeb\xc1>\xbd\t\xc8\x15\v\xb0, \xee\xa4\xa6\xb9a\x01&\xadrj\xd5\xc26p\xa14\xe0\xbf\xa0\x1es\x01=\xdbd\xf0?=<l\x8c\x01\xe3\x05$\x1c\x04B\x00\xa4P\x04\xcf\x87\xaa\x96iP\x14{4\xe6\x87\x9d\x8f\bz9$\x10_\xd8E\x93\x92\xf5\x8au\xab\xf9)\xf5\xa6\xc7\xc8\xed\xb9\x1f:\x03K\xa2\xdbUshx\xbe\\\x19\xdax\xeb_\x10|r\x1e\x06p>\x8afcJ\x8eYEn\xd4<\x00\xec\xe4^\x00\x00\x00\xca\x90\xfa\x98\xc9gty\xce\xab\xd2\xa1\x85E\xe4\xa9\xd5\xab\x83\xda?w\x83\xbc\xcf\xd20(L&b\xed\x8c\x1d\x1a\x9fd\x99H\x9e\x82\x10\xea\x05\xf8\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\xa6\x8c\x05n\x83\x83\x12+\x16\xc1\x00\x04\x00\x00\x13:o\x0f\x1fB\xa4\x00wB\x92h\xde\xfal3\x88e\x04J\\\x00D\xae`\x8e\xadd\xa8;\xee\xc4K\xe8]\x84\x90\xb8d\xfb\x95\xb3\xe9(x_\x80]\xadW\xd5\xa9\xaa\x03\x9c6\xa9\xc4\x01\x03\xea\xe5\x90\x85\x16\xb0DV\x13\x01\xab\x01\xf0\x8f\x02\xc2\xc8\x9b\x03\x1f\xd7\xdbN\\\xc0\xcd?Pg\xd5q\x13\xbd \xfa\xab\xccJK\x11\\\x16~#P.\xc9K\x15r\x04\xd9Z;\xc0\x8dOze\x96\xe9\xc3\x93\xed\x94.\xc2\xa0\x1fU#\x96\xe6\xb6C\xfa\x03/\x8b\x0e2\xec\x96v\x9b/.\v\x9e\x80\x18s\xae.\xf4\x14KS`\x87\x8b4\t\x00\x87{\xa8@e\xbfe\xeb\xee\xa2\xe72\xb8Q:\x9f\xc2b\x897\xbe\r\x04\xdf\xe2\xc0\xf0FV\'m\xcbm\x80%\xfc\x9e\x9f\x87\x80A\xbe\xc2\x00\x00\x00\x00\x00\x006\x96\xbb\x9f\x85\x98\xbb\xbc;\xaa\x97c\xfe\x82jz&t\xa7\xc4\xcd\xb0\b9G\xcag\fY\xe6\r\xcdT\xd3\x1c(\xef\xc0\x038\xbd\xdd\xd9\xc9\x93a]q\xd2\x9b\a\x1e\xf8\xc3\"\xc8:\xb8$\x9f\'P\x17\xfa\xf3Xa\trB-\xf2g\xe6Z\xd5F\xd2\x80\xe0\x99\"\xc12\xe8\b\xc58\x00'/659)


r0 = syz_open_pts()
ioctl$FIOASYNC(r0, 0x8004667d, &(0x7f0000000240)=0x7ff)
syz_open_pts()
syz_open_pts()


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
r0 = open(&(0x7f0000000400)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x269000000, 0xffffffffffffffff})


syz_emit_ethernet(0x42, &(0x7f0000000500)={@broadcast, @broadcast, [], {@ipv4={0x800, {{0x8, 0x4, 0x0, 0x0, 0x34, 0x0, 0x0, 0x0, 0x0, 0x0, @broadcast, @multicast2, {[@timestamp={0x44, 0xc, 0x9, 0x2, 0x0, [{}, {}]}]}}, @tcp={{0x3, 0x0, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000280), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f00000001c0)=[{0x1d}, {0x7}, {0x8106}]})
syz_emit_ethernet(0x3e, &(0x7f0000000380)=ANY=[])


r0 = syz_open_pts()
ioctl$TIOCSTOP(r0, 0x2000746f)
writev(r0, &(0x7f0000000280)=[{&(0x7f00000012c0)="de", 0x1}], 0x1)
close(r0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0xbe68df9a610de7e1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000280)={0x3, &(0x7f00000001c0)=[{0x50}, {0x25}, {0x16}]})
write(r0, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xe)


pipe(&(0x7f0000000100)={<r0=>0xffffffffffffffff})
fcntl$setstatus(r0, 0x4, 0xc0)
r1 = getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r1})
pipe(&(0x7f00000001c0)={<r2=>0xffffffffffffffff})
setreuid(0xee00, 0x0)
r3 = getuid()
setreuid(0xee00, r3)
ioctl$WSKBDIO_GETMAP(r2, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r4 = fcntl$getown(r2, 0x5)
fcntl$setown(r0, 0x6, r4)
setpgid(0x0, 0x0)
setpgid(0x0, r1)
close(r0)


syz_emit_ethernet(0x42, &(0x7f0000000100)=ANY=[@ANYBLOB="ffffffffffffffffffffffff08"])
syz_emit_ethernet(0xe, &(0x7f0000000100)=ANY=[])


r0 = socket(0x18, 0x3, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1002, &(0x7f0000000180), 0x4)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
semctl$GETNCNT(0xffffffffffffffff, 0x3, 0x3, &(0x7f0000000000)=""/4096)
r1 = semget$private(0x0, 0x2, 0x9)
semctl$GETVAL(r1, 0x4, 0x5, &(0x7f0000001000)=""/253)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x30}})
r2 = socket(0x800000018, 0x1, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f0000000440)={&(0x7f00000000c0)={0x0, 0x0, &(0x7f0000000580), 0x0, 0x0}}, 0x10, 0x0, 0x0)
shutdown(r2, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
r3 = socket(0x18, 0x1, 0x0)
dup2(r2, r3)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
getgid()
semctl$GETZCNT(r1, 0x3, 0x7, &(0x7f0000001100))
semctl$IPC_STAT(r1, 0x0, 0x2, &(0x7f00000012c0)=""/74)
semop(0x0, &(0x7f0000001400)=[{0x1, 0x335c, 0x1800}, {0x6, 0x4, 0x3000}, {0x4, 0x5, 0x800}, {0x2, 0x43b9, 0x800}], 0x4)
r4 = openat$pf(0xffffffffffffff9c, &(0x7f0000001440), 0x800, 0x0)
ioctl$BIOCSETF(r4, 0x80104267, &(0x7f00000014c0)={0x1, &(0x7f0000001480)=[{0x100, 0x1, 0x9, 0x400}]})
shmget(0x2, 0x3000, 0x21, &(0x7f0000ffd000/0x3000)=nil)
getuid()
getuid()
fcntl$getown(0xffffffffffffff9c, 0x5)
getpgid(0xffffffffffffffff)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {0x0, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f00003c5000/0x1000)=nil}, {&(0x7f0000ffc000/0x2000)=nil}, {0x0, &(0x7f0000208000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000577000/0x4000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffa000/0x2000)=nil}, {&(0x7f00002bf000/0x2000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000ffd000/0x1000)=nil}], './file0\x00'})
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
ioctl$BIOCGDLTLIST(r0, 0xc010427b, &(0x7f0000000040)={0x0, 0x0})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000480), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x6c}, {0x25}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000d40)={@local, @random="94ea09066dbd", [], {@ipv6={0x86dd, {0x0, 0x6, "db8344", 0x8, 0x0, 0x0, @rand_addr="135e80f1d38ddba80b9e61dd0c575a88", @local={0xfe, 0x80, '\x00', 0x0}, {[], @udp={{0x0, 0x2, 0x8}}}}}}})


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000424, r0)
syz_open_pts()


open$dir(&(0x7f0000000040)='./file0\x00', 0x1, 0x20)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000280), 0x10, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
writev(0xffffffffffffffff, 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x80000000})
r1 = syz_open_pts()
close(r1)
syz_open_pts()
r2 = open(&(0x7f00000000c0)='./bus\x00', 0x615, 0x10)
ftruncate(r2, 0x9)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x10, r2, 0x0)
ioctl$FIOASYNC(r1, 0x80047469, &(0x7f0000000040)=0xfffffffc)
write(r1, &(0x7f0000000380)="feaefb66d909ec4d0da82748ae558f245ae995f911f70b39a831eeedd542a30b7694924a16e8f2ce1d9139db272e810b8f995f554138f306b1fd4e8434ef6e1147a90209341f2f75777933d6736442abbcef8a037d285e3ba4be08806490e84b1e80d6067243dcae3471ef2cfe3db56b62125caab7e4f018cfaa9a82bea85d6180b05ed81f5d1ed9b1c0cfaf8853e69a519f1fbc9cbb12edb464f64a72e88182b24b3dc1c184fa5ef023000f541b075f1c4c91", 0xb3)
syz_open_pts()
mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x2802)
openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r2, 0xc0384600, &(0x7f0000000240)={&(0x7f00000001c0)='./file0\x00', 0xb, 0x0, 0xfffffe12})
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x84}, {0x50}, {0x6}]})
syz_emit_ethernet(0x1b, &(0x7f0000000000)=ANY=[])
pipe(&(0x7f0000000080)={<r3=>0xffffffffffffffff})
r4 = open(&(0x7f0000000340)='./file0\x00', 0x0, 0x0)
readv(r3, &(0x7f00000000c0)=[{&(0x7f0000000140)=""/118, 0x76}], 0x1000000000000212)
dup2(r4, r3)
ktrace(&(0x7f0000000100)='./bus\x00', 0x1, 0x40000808, 0x0)
execve(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x28}, {0x5}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])


mknod(&(0x7f0000000080)='./file0\x00', 0x6000, 0xe02)
recvmmsg(0xffffffffffffff9c, &(0x7f0000003cc0)={&(0x7f00000009c0)={&(0x7f00000001c0)=@in, 0xc, &(0x7f0000003c40)=[{&(0x7f0000000240)=""/3, 0x3}, {&(0x7f0000000580)=""/129, 0x81}, {&(0x7f0000000b40)=""/4096, 0x1000}, {&(0x7f0000001b40)=""/4096, 0x1000}, {&(0x7f0000002b40)=""/4096, 0x1000}, {&(0x7f0000000940)=""/122, 0x7a}, {&(0x7f0000003b40)=""/200, 0xc8}], 0x7, &(0x7f0000000280)=""/64, 0x40}, 0xbf6f}, 0x10, 0x821, &(0x7f0000003d00)={0x600000000000, 0x5})
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000a00), 0x0, 0x0)
readv(r0, &(0x7f0000000800)=[{&(0x7f0000000500)=""/120, 0x68}, {&(0x7f00000002c0)=""/122, 0x7a}, {&(0x7f0000000340)=""/228, 0xe4}, {&(0x7f0000000440)=""/102, 0x74}, {&(0x7f00000004c0)=""/62, 0x3e}, {&(0x7f0000000a40)=""/225, 0xec}, {&(0x7f0000000640)=""/242, 0xf2}, {&(0x7f0000000740)=""/142, 0x8e}], 0x8)
r1 = socket$inet(0x2, 0x4003, 0x0)
r2 = syz_open_pts()
close(r2)
ioctl$TIOCSETD(r2, 0x8004741b, &(0x7f00000000c0)=0x9)
r3 = openat(0xffffffffffffff9c, &(0x7f0000000180)='./file0\x00', 0x7fd600faffc9bf32, 0x0)
getsockname(r3, &(0x7f0000003d80)=@in, &(0x7f0000003e00)=0xc)
poll(&(0x7f0000000040)=[{}, {r3, 0x1}], 0x2, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x0, &(0x7f0000003d40)="06d8d1b81f3a6632510d154a7788e22c4fbc5227deb161aa30e68e070dce9ee3852d5c1a466c8b4492756c792fa7fe3532befd969cae2283e7", 0x39)
writev(r2, &(0x7f00000005c0)=[{&(0x7f0000000740)="725c8409679f313f04e4b9d42c3c87840bce82cdd178d6ed6a60862c0ec6c2efa1fffa6bc8e424931e23a9f3edb23850f45d360bd5ea818b41738cb92aadcee4d8b3400a1063dd91e935979dec31aaccb2cb5899ad1281ca57ce5eed2e6196c591f280f290f40361623853a6555485007cd1d82417488523ab00e83703eeaa96594999f5045941a0b7a270405e11557ddb9502b9a513bf0da7c552814269d3edbf5a65a973b9a2e71e3d1478a032f7422f8a0d1ff92589429f95ae780075f65ed3d4d7fc564ac6eb890cea7c046de94e9ef5297a1a6190831076bd70b9640c7b894baf78df076e3232d8159045b9f987d6a8d9353ac5c2257ffdcea15ac32c8696111eadacaa5960f704f8bd481a807777724cc4d646d0ec68d1228734d300e74105c9fbf82add6c8da38517c0f0f15d20dc228a2b9c3616731027b99b0a2e74cde07afb29fdb47013353c3fd88935aa944641eeac605d6dd23a8dd9e565c3187a86be9a4aef895e9d8e6d2fdc644a858a5d8907f60fd9db761281b977f3058f3e33e2f65b13ba640f536fd39dba38c0187e0e2a1716ab480fecb11d4f46f56cbabf76506774f4332d60afbffdc9244a7b3ee7ccd1fe86191ed4f74a4620116539957a785975621bac2cba5200c375c1cd1784cf23bbb56681b037e7c4d921dbb037ce546c561c3bb5eb0ca0d6a620ae87e5f66bb9f33cd79cd20e49ffe81695189d65b7c77d253b45917a0c4761a8c822401aeefe6dd13c9ee120b2d14b5a9a0db341407350933c1efb9f5c61dd7f91ace54e78b746b196d37ddb4742f25efa660be97cb2581311a94ecccd2da878a1d052e9e19a5b3cb854cd0a697b600e417817131266834ec8ce59669c9fa755641874f2877e6f82a88246815ae114b53fe2c0685ef2789b1b4f02cbac6645d7de427f3ef35938a4a499a7f05b054886ea8c7117bb3c99e003176ed9df7fe50b875e3ab206456bd5566c8007051482c9a01b5363fe1557213119070bfa39f1b71ffbf531fa0d929da5698c2c9286e9b5ce0b660d8829645c6c08f2f095f91a57fc70b3f173682b64c400086c4f0aaa94df08ed8f69245bdb5a15b14baf7bf72b451f25bc5fdd51c0c5d0f40a7a813dc07c9dfa3c7039c4585b49885d2420bb9af88f362e5ca203d3a3b2dc6b58c06d5908dd5b5d2e802578e46ee80e21003c7935a340412442747d920f78ef27905a2f0fb2efff968cf4bb33bd4d8a5384fcd886b4c4dbea593770b799f1e09b6fa08f966ae16feab25cdb104b075d424bd371d51b054b94fb288e0e2b76bc67b695baa5bebc7a68f00ea8b8d9d6e6c9e53af21a30cd5fc31c9a07b33da448bf4543fe850e1dd5fdf5cfca72e5dab0e36a5e0854fea45a590eef3297449bc082ee3e80f552ddec8c0dc7f7adf9d960c94cbfa9ce4d1990249fd4ad6c59b91040dbef8611bce60459e85c5f9125b0c769192ef40f1eefba6067aa75fa2e0cfc92cf8d5c65db999e16d43f6d6cf28a460b3ef7ff8d9421c9602cee2bda0b817021fe41964b305e8b9ab2be3e898fbf7c42ffe01ce1edd3c71622bcfd15b67d320e0917d191d209f709a268b0c324898437883922514fcddefd035d315a14de005c9ede97e539f5054f3aec738fb2394d4178ef323c7cb85a273064f3af8d274ea034a9cdd8e10582fdec0e3a385df843ea102f368bf8a89e15c42cc7fd85e33f6229f47c6b3143e0c6476a62d50ca341e7679aa816f901a5546c78774cb9663591f71f9eea1467034dd1a90a829a104727c8c61dc27491d146c4b26b9054ea346512d2aa363f64d5cdbe80d8c4db33998f25e777e44c6eec49c4bdb3cc122cb5dbece3cf106381eecfb789dc8f013a07358386ac575a0c94aba872e5d6f91e1dcdf4f3c60af3a1aaf2c4895b33ccfc176a3c553e07fe21d2f3c617833f92fc0e86ec93c024ce7c3deb72fd1712c7022dad05345cf0b78f69d55a622d81b72e03067449b5c04b8c3d17c25bb97ae27203201739d6271b6752a7520e90266b1d920eaed1f70f97d9e7da4da94862989b494fdcadde71182329c47269a149b14d1fd4443f3ee97bf73e2a097f60854b0f36c35f017a30300d2d39fdb822fcc7ec3fb188f73112f869ec57b04888c35417a8806569f5b9f060fbfe7560b735f85677febc836cdc7feefac1546d6a45673bb31aa004edda049f28f167c533156823f2ded3236c8502216ce2188e3099a6c20f1f3af437ceb5bedbfcbeea20212ac2bdf574037cff354799a1739f1fdeaf59e8698d9dc1132484c64ac771f6b4eddc3cf359c267fbed037bba5025a9a9ef596628b5e1a3de1489dda596e7f8461fc394fc3a6199378a55a53d14c7cf1f0bfe3a41fe73d749e215ec6a06ee36c5fb53930162ae840685a7020566919720e5e86091eecbb2e4e35ef009974abfffdfcaa95266ad3fb17a102ccb2c222cc5d23684a70e67918eb659f541883ad975634b6bd5a1f6e7b426355c68267147d435152db7a0ba33adca52901cbca3f716eba2b7dc2a3341d7be725ee70caf99142d3c40872ef30e64841d03beee1c6bef29a69ddd0e1c701e1ee4656f5cca9a40b9aa0b5a797b3a6587a775d85a8fdbe9ffdb54073ed8df4c35b80bada6c86cba3172e985bc91c6f090068d5d53df3073c8e4bffa3c37d40077f95184ca9f35d1e7866c62dad0a7b36ada4c3f7704f2bbd5a435520b84f106600358952e7377fa8027f81783e7b8f4441e014db0f99ec83e29cc2e34c47ecbeb8c08b1f4622102c213bdd056a1b58328579bc81cead0291cf46e4c24aeef8161204a6307ae5d86010c77ae87c39ef640e3e5872e59a4e4f4d53df9f1c327dd1bf471b89d42b5bce7666c830e781d031b78dcaf76b697b3f2c823dc8997caca87b12cddc604058fb134f2948a09a45afae836d051aef84b624c1184c76ddd895cc2480d3d4fa1b6ff606afddf894da02c4c1e62277ec6612cf85b9451aa8d33ce73ff2620e3532f00a85cb9713492d0ac31b6800d5efe6511a971a608286e45df8ac8e2cbbe2498ae7cff5fff2912d9a09febb949feb59ef5da653f864656a9d5d6bc65cea79d987ee5c370474252a6c43b00177f4f94a1bc3e1c6d1affe6ed3cddc074edcfd84e22269359ccf5d8a24fb1d6cf22ea160edfff061792bd9ca386a311ebeec593c083821c242ec78d040a3fc5e14bfff47c499509b20f21fb294ce521fa4ffd79afe32e163b6dc80d09f2085f78a6d407b1107b68ce31927ea3aa1e7d43400ed67c9b525912a73c7cad2977bbc4288503e5595b865842caba1f6a27b463f37d74ca81e6f420eb59fc94e35204d04817c405016b350cf3c63d73d588b444d46f52fc775ab0fb4f855757855f90bbca18f93ed2b88587ecb20b50420b18c32fa7732ca25231a09a178cf263e349b7ff36ae4e3f4c590e7c704830bd050f4783e43e6e480135debac1acdd504baf17f5aa919d74d2ed0248278f885fd0e9a6e0ec0ac614a5c3d9fee0f077f4ca3b14541e43a032e121cf91a0f6509ca135a16f58bcfe954b62e0e73a71067dd3e389f0e0806864b9d427a820ceee0763d4f455c2fa75a442ad8c9ac8163f484d32d1f3edc6b7d9af5d4b00eb93f896fbb953dac8d6cac4ce4bbe70e716a6fa45e79a2d1137f271099f7ec197bedece74dac272850c04f2d10a0e1ce1c1fa034fafe2bd976269a0bfdfe6e313361789550aa213fed4ac6c6def448411ca59ecb2382bfa6b2245c49a373a931950de09b23d56bfd0a7ab72c44d0f90910d063979dc6a7228f2d578b4d6f80d77a0e9b4abf18606a1ecadaea9493897c910757ddb6837c54a466b67a495868947f47b504f71d0fa48d99245d18c5e37dbf73cb91650f704de521b6f864ccc016d26d002bcad06d278b6f21c324121f9a37997f0875b7fa024f7b2d9fb8ae8263de347dd3939b2308d79ff4e28291c6afbc7932a077a5443ea64b6b3c1afc78c80b6531d08c220a1cb3be9de6c092941d98ee3aa6dcadc3ef1d6b5c9cae5de7c0c8a9d4a0c31d65fc0d1bb758d2ecd464e9bc81d945625c26702569afc841a2f170a0de02549fedf36474597b6fb4caef11d291fe8ceb1761ab0e428d43c20d703b474786af57839d1e8bd971dacde760fc77956c57665dcc2b50106f91d90da4bb0772eeddccfe7e6f374bb6dd4c2510a", 0xb8e}], 0x1)
dup(r2)
setsockopt$inet_opts(r1, 0x0, 0x6, &(0x7f0000000180)="99c300016bae3b53fb0b7051", 0x4)
writev(r1, &(0x7f0000000200)=[{&(0x7f0000000000)="741693220c5b6189a4e45ee498d2756dfb0e9e4986cb196a5323d8fd9fef2d03f8cb57a8a7b5a547375fb4b308e849187741595c11dd5f59c4a08adc72848e6956056f6790e1379c3f394f86bb1712aea6a6a68310a12908b17379c5278fe07a075021a4b548f4ff84f4e4b37be1b610d5dc71795730b619d2f7f2826e624bee7bfc2ef6f6d18922022fc1188ea02b6820654804d25d2bf689a5d43a22f7f4f35278248e972b7795285746", 0xab}, {&(0x7f00000000c0)="4118a3d9e102ac9cb0e0b038d3f743512c5c8b30112c99a8eae151b0d2b264d282f6b7085f4a99bf135100fccfdb6088c45e22a47891a845644b5426e792e7c072bd6fde9a7898a0123317837d38fe463c52e145be75a0d358d3f3c632e8a1d8fff333456f7c1165306141cc6f2002bee67105f0daaadf979c2b3f9789c5cd8877ee0e7e1426fdc43f8f5d91068d7a2a277733f96cfeef1cb698057c2d2ff951e5921d65852a8c2ee61f93f1893d0bca5467d0dbd89c00851d5a309eabcc9ac7c47d30bb279745ca18778c103fc22e8dc218a2f12e290332ce31835b6563c7fd6bcf8b1b697f6a297c636baca143815d0f5a9f21e1d08044", 0xf8}], 0x2)
r4 = socket(0x6, 0x4000, 0x1f)
mquery(&(0x7f0000ffd000/0x3000)=nil, 0x3000, 0x4, 0x10, r4, 0x4)


mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x2802)
r0 = socket(0x11, 0x3, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000080), 0x0)
setsockopt$inet_opts(r1, 0x0, 0xd, &(0x7f0000000240), 0x0)
recvmmsg(r1, 0x0, 0x0, 0x1, &(0x7f0000000380)={0x9})
ktrace(&(0x7f0000000100)='./bus\x00', 0x1, 0x4000010e, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000080), 0x0)
r2 = socket$inet6(0x18, 0x2, 0x0)
recvmmsg(r2, &(0x7f00000002c0)={0x0}, 0x10, 0x0, 0x0)
recvmmsg(r2, &(0x7f0000000300)={0x0}, 0x10, 0x2, 0x0)
r3 = dup2(r0, r2)
r4 = socket(0x11, 0x3, 0x0)
setsockopt(r3, 0x10, 0x39, 0x0, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x0, &(0x7f0000000140)="c2969223a7fa593766989f2f1cc188b254b3efea7f38ed59d3aed2eb973f2604496d55", 0x23)
stat(&(0x7f0000000080)='./bus\x00', &(0x7f0000000280))
r5 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r5, 0x0, 0x200000000000a, &(0x7f0000000040)='\x00', 0x1)
setsockopt$inet_opts(r5, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00100001000000", 0x8)
connect$unix(r0, &(0x7f0000000000)=@abs={0x0, 0x0, 0x0}, 0x8)
recvmmsg(r4, &(0x7f0000000340)={&(0x7f0000000200)={&(0x7f0000000180)=@in, 0xc, &(0x7f0000000700), 0x0, &(0x7f0000000780)=""/193, 0xc1}, 0x401}, 0x10, 0x1002, &(0x7f0000000880)={0x80000000, 0x8})
r6 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x1, 0x10, r6, 0x0)
shutdown(r6, 0x0)
r7 = accept(r4, &(0x7f0000000940)=@un=@abs, &(0x7f0000000980)=0x8)
recvfrom$inet(r7, &(0x7f00000009c0)=""/57, 0x39, 0x2, &(0x7f0000000a00)={0x2, 0x2}, 0xc)
r8 = socket(0x11, 0x3, 0x0)
setsockopt(r8, 0x11, 0x2, 0x0, 0x0)
setsockopt$inet_opts(r8, 0x0, 0x1, &(0x7f00000008c0)="9fa684a3f1835c36c1fd0e65d446a7f2d601a6f6f66ce4e19247169d2a304546672b4a8de74defa315bc5dbb5309148ca79bab7b72138b21cd84d70fbeca7fe2839786e434d8cc25d161eb5ac73983c5d0dc0b1ea0b2e54c46ceb7ebcb62fd97e8c9b1700bab9fcd0ac15bc4fbc601b41bc49f", 0x73)
connect$unix(r6, &(0x7f0000000a80), 0x8)


mkdir(&(0x7f0000000040)='./file0\x00', 0x0)
unveil(&(0x7f0000000280)='.\x00', &(0x7f00000002c0)='r\x00')
chdir(&(0x7f0000000140)='./file0\x00')
unveil(&(0x7f0000000000)='./file0\x00', &(0x7f0000000080)='x\x00')
open(&(0x7f0000000100)='.\x00', 0x200, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
chroot(&(0x7f0000000100)='./file0\x00')


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000240)=[{0x35}, {0x5c}, {0x6, 0xfe}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x1}, {0x7}, {0x16}]})
write(r0, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xfef3)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{0x28}, {0x30}, {0x6, 0x0, 0x0, 0xfffffffa}]})
write(r0, &(0x7f0000000740)="76e5dead6f01f8607d2100000063", 0xe)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x4000000000000003}})
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$TIOCFLUSH(r0, 0x80047476, &(0x7f0000000000))
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r1, 0xc2585601, &(0x7f00000004c0)={0x10, 0x0, [{&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff8000/0x4000)=nil, 0x1000}, {&(0x7f0000ff8000/0x4000)=nil, &(0x7f0000ff2000/0x3000)=nil, 0x80000000}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ff2000/0x4000)=nil, 0x3}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000fed000/0x4000)=nil}, {&(0x7f0000fee000/0x2000)=nil, &(0x7f0000ff6000/0x3000)=nil}, {&(0x7f0000fec000/0x3000)=nil, &(0x7f000047f000/0x2000)=nil}, {&(0x7f0000ff9000/0x3000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000fee000/0x2000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {&(0x7f0000ff2000/0x4000)=nil, &(0x7f0000ffa000/0x4000)=nil}, {&(0x7f0000ff0000/0x2000)=nil, &(0x7f0000fec000/0x1000)=nil}, {&(0x7f0000ff2000/0x2000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f0000fef000/0x2000)=nil, &(0x7f0000ffc000/0x1000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000fed000/0x1000)=nil}, {&(0x7f0000ff5000/0x2000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ff7000/0x4000)=nil}], './file0\x00'})
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000158000/0x3000)=nil}, {&(0x7f000003d000/0x1000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f00000c3000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000157000/0x1000)=nil}, {0x0, &(0x7f00001eb000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f00000e0000/0x1000)=nil, &(0x7f00000d8000/0x3000)=nil}, {&(0x7f00000ca000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f00000f8000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
ioctl$TIOCSTAT(r0, 0x20007465, &(0x7f0000000200))


madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff})
getsockname$unix(r0, &(0x7f0000000280), &(0x7f0000000040)=0x205)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x61}, {0x7}, {0x6}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
getsockopt(r2, 0x6, 0x9, &(0x7f0000000500)=""/243, &(0x7f0000000600)=0xf3)
r4 = openat$wsdisplay(0xffffffffffffff9c, 0x0, 0x10, 0x0)
ioctl$WSDISPLAYIO_GETSCREENTYPE(r4, 0xc028575d, &(0x7f00000004c0)={0x5, 0x100000, './file0\x00', 0xe4e0, 0x0, 0x9, 0x401})
sendmmsg(r3, &(0x7f0000000000)={0x0}, 0xfffffe32, 0x0)
recvmsg(r2, &(0x7f0000000100)={0x0, 0x0, &(0x7f0000000080)=[{&(0x7f0000000180)=""/236}], 0x100000000000039d, 0x0, 0x28}, 0x0)


r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
setuid(0xee01)
ioctl$FIONREAD(r1, 0x8020699d, &(0x7f00000001c0))


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047466, &(0x7f0000000200)=0x5)
ioctl$TIOCSBRK(r1, 0x2000747b)
poll(&(0x7f0000000080)=[{r0, 0x80}], 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000000c0)=[{0x54}, {0x64}, {0x6, 0x0, 0x0, 0xfffffffe}]})
write(r0, &(0x7f0000000540)="76e5dead6f01f8607d2100000063", 0x17)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
pipe(&(0x7f0000000040))
open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
r1 = getpid()
ktrace(&(0x7f0000001d40)='./file0\x00', 0x0, 0x1720, r1)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, &(0x7f0000000380))
r2 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, &(0x7f00000009c0))
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r2, 0x0)
writev(r0, &(0x7f0000000140)=[{0x0}], 0x1)


close(0xffffffffffffffff)
r0 = open(&(0x7f0000000200)='./file0\x00', 0x200, 0x0)
preadv(r0, &(0x7f0000000000)=[{&(0x7f0000000240)=""/139, 0x8b}], 0x1, 0x7fffffffffffffff)
close(0xffffffffffffffff)
flock(0xffffffffffffffff, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000000c0)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
getsockopt$sock_int(r1, 0xffff, 0x1001, 0x0, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x1, 0x0, 0x2}, 0x8)
socket(0x2, 0x2, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f0000000040), 0x10)
getsockname$unix(0xffffffffffffffff, 0x0, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETWF(r3, 0x80104277, &(0x7f0000000140)={0x2, &(0x7f0000000040)=[{}, {0x6}]})
writev(0xffffffffffffffff, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
getuid()
setitimer(0x0, 0x0, 0x0)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x35}, 0x4, &(0x7f0000000080), 0x0, 0x0, 0x0)
setreuid(0xee00, 0x0)
r4 = getuid()
setreuid(0xee00, r4)
r5 = msgget$private(0x0, 0x0)
msgctl$IPC_STAT(r5, 0x2, 0x0)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x2})
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


ioctl$BIOCFLUSH(0xffffffffffffffff, 0x20004268)
r0 = kqueue()
kevent(r0, &(0x7f0000000040), 0x20b89, 0x0, 0xffff3955, 0x0)
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000000280), 0x0, 0x0)
mmap(&(0x7f0000003000/0xc00000)=nil, 0xc00000, 0x0, 0x10, r1, 0x0)


open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
select(0x40, &(0x7f0000000080)={0x825d}, 0x0, 0x0, 0x0)
r0 = socket(0x2, 0x3, 0x0)
r1 = socket(0x2, 0x2, 0x0)
r2 = dup(r1)
setsockopt$inet_opts(r2, 0x0, 0x22, &(0x7f0000000040)="fd0cc085", 0x4)
dup2(r2, r0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r0, &(0x7f0000000000), 0x10)
write(r1, &(0x7f0000000080)="77122f1bcfab543f", 0x8)


r0 = socket(0x2, 0x2, 0x0)
fcntl$setown(r0, 0x6, 0x0)
connect$unix(r0, &(0x7f00000000c0), 0x10)
socket(0x20, 0x5, 0x81)
connect$unix(r0, &(0x7f0000000180)=@abs={0x0, 0x0, 0x0}, 0x8)
r1 = socket(0x18, 0x3, 0x8)
setsockopt(r1, 0x3a, 0x12, 0x0, 0x0)
connect$unix(r1, &(0x7f00000007c0), 0xa)
r2 = socket(0x2, 0x2, 0x0)
setreuid(0xee00, 0x0)
r3 = fcntl$dupfd(r0, 0x0, r0)
getsockname$unix(r3, &(0x7f0000000380), &(0x7f0000000140)=0x51)
r4 = getuid()
setreuid(0xee00, r4)
setsockopt$sock_int(r2, 0xffff, 0x1023, &(0x7f0000000040)=0x40000001, 0x4)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x2, 0x0, 0xba}, {0x6, 0x0, 0x0, 0x8002}]})
bind(r0, &(0x7f0000000280)=@in6={0x18, 0x1, 0x21, 0x4}, 0xc)
r5 = accept(r3, &(0x7f0000000340)=@in6, &(0x7f00000003c0)=0xe)
bind(r5, &(0x7f0000000400)=@in6={0x18, 0x0, 0x0, 0xffffffff}, 0xc)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)
setreuid(0xee00, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000004c0)={{0x7781, 0x0, 0x0, 0x0, 0x0, 0x350, 0x3}, 0x2, 0x1, 0x4a})
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000002c0)={{0x7e13, 0x0, 0x0, r4, 0x0, 0x10e, 0x9}, 0x7, 0x3, 0x9})
connect$unix(0xffffffffffffffff, &(0x7f0000000240)=@abs={0x1, 0x0, 0x2}, 0x8)
semget(0x3, 0x0, 0x80)
getuid()
dup2(0xffffffffffffffff, r1)
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f00000001c0), &(0x7f0000000200)=0xc)
r6 = msgget$private(0x0, 0x201)
msgctl$IPC_RMID(r6, 0x0)


open$dir(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
r0 = getpid()
ktrace(&(0x7f0000001d40)='./file0\x00', 0x0, 0x1720, r0)
utimensat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', &(0x7f0000000080)={{0x0, 0xfffffffffffffffe}}, 0x0)


setrlimit(0x6, &(0x7f00000000c0))
open(&(0x7f0000000100)='./file0\x00', 0x70e, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x520, r0)
r1 = socket(0x800000018, 0x1, 0x0)
r2 = socket(0x800000018, 0x1, 0x0)
bind$unix(r2, &(0x7f0000000080)=@abs={0x0, 0x7}, 0x1c)
bind$unix(r1, &(0x7f0000000080)=@abs={0x0, 0x7}, 0x8)
r3 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r3, 0x0)
setrlimit(0x3, &(0x7f0000000140))
mlockall(0x1)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f0000000040)=0x1)
writev(r0, &(0x7f00000003c0)=[{0x0}], 0x1)
r1 = kqueue()
kevent(r1, &(0x7f0000000080)=[{{r0}, 0xfffffffffffffffe, 0x41}], 0x8000, 0x0, 0x0, 0x0)


sysctl$kern(&(0x7f0000000040)={0x1, 0x55}, 0x3, 0x0, 0x0, 0x0, 0xfffffdc4)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000))
open(0x0, 0x0, 0x0)
syz_open_pts()
sysctl$hw(&(0x7f0000000040)={0x6, 0x5}, 0x2, &(0x7f0000000080), 0x0, 0x0, 0x0)
semget(0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
setpgid(0xffffffffffffffff, 0x0)


openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x1, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0xc}, 0x2, 0x0, 0x0, 0x0, 0x0)
r0 = socket(0x11, 0x3, 0x0)
getsockopt(r0, 0x11, 0x3, 0x0, 0x0)
socketpair(0x0, 0x0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000280)=[{0x1}, {}, {0x6}]})
syz_emit_ethernet(0x7e, &(0x7f0000000400)=ANY=[])
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140))
semctl$SETVAL(0x0, 0x0, 0x8, 0x0)
semctl$SETVAL(0x0, 0x0, 0x8, 0x0)
r2 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x1, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETF(r3, 0x80104267, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504600000000000000007000000331c13fecea10500fef9ed06c72fd3357ae320b37b673039d2d236073705ae04be38164991f7accf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f13", 0x4f, 0x0, 0x0, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$BIOCGDLTLIST(r4, 0xc010427b, &(0x7f0000000040)={0x0, 0x0})
ioctl$WSMUXIO_REMOVE_DEVICE(r2, 0x80085762, &(0x7f0000000100)={0x3})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000400)=[{0x34, 0x0, 0x0, 0x3fffffff}, {0x3d}, {0x6, 0x0, 0x0, 0x23a}]})
write(r0, &(0x7f0000000000)="7696e5f3d1f18c37cea8615ac7cf", 0xe)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)


sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x17}, 0x4, 0x0, 0x0, &(0x7f0000000240)="f438cf3f", 0x4)


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x1}, 0x38)
r1 = socket$inet6(0x18, 0x2, 0x0)
ioctl$VMM_IOC_READREGS(r1, 0xc028756b, &(0x7f0000000000))


kqueue()
syz_emit_ethernet(0x3e, &(0x7f0000000040)=ANY=[@ANYBLOB="aaaaaaaaaaaa00000000000086dd60004b0000082b00fe8000000000000000000000000000aafe"])


madvise(&(0x7f000008f000/0x3000)=nil, 0x3000, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {&(0x7f000002f000/0xd000)=nil}, {&(0x7f0000060000/0x2000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000ffb000/0x4000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000053000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ioctl$VMM_IOC_RUN(r0, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x9})
r1 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x0, 0x10, r1, 0x0)


setreuid(0xee00, 0x0)
r0 = getuid()
r1 = geteuid()
setreuid(r0, r1)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000040)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000140)=0xc)
r3 = socket$inet(0x2, 0x3, 0x0)
getsockopt$inet_opts(r3, 0x0, 0x65, 0x0, 0x0)
getsockopt$sock_cred(r3, 0xffff, 0x1022, &(0x7f0000000180), &(0x7f0000000200)=0xc)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x1}, {0x6, 0x0, 0x0, 0x8002}]})
r4 = socket(0x18, 0x1, 0x0)
r5 = socket$inet(0x2, 0x8000, 0x16)
getsockopt$SO_PEERCRED(r5, 0xffff, 0x1022, &(0x7f0000000300), 0xc)
setsockopt(r4, 0x1000000029, 0x2f, 0x0, 0x0)
fchown(r4, r0, r2)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


r0 = socket$inet(0x2, 0x2, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r1 = socket(0x18, 0x3, 0x3a)
setsockopt(r1, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r1, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x3}, 0xc)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt$inet6_MRT6_ADD_MIF(r1, 0x29, 0x66, &(0x7f0000000140), 0xc)
r2 = socket(0x18, 0x1, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1, &(0x7f0000002700)=0xffffffff, 0x4)
r3 = socket(0x18, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
recvfrom$inet6(r1, &(0x7f00000002c0)=""/4096, 0x1000, 0x1, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{}, 0xffffffffffffffff})
setsockopt$sock_int(r3, 0xffff, 0x1002, &(0x7f0000000080), 0x4)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(0xffffffffffffffff, 0x8040691a, &(0x7f00000001c0))
bind(0xffffffffffffffff, &(0x7f0000000000), 0x10)
r4 = dup(0xffffffffffffffff)
listen(r4, 0x0)
ioctl$WSDISPLAYIO_LSFONT(r4, 0xc058574e, &(0x7f00000012c0))
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x1, 0x7}, 0x8)
r5 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r5, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000000), &(0x7f0000000280)=0xc)
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
r6 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r6, 0x80206979, &(0x7f00000001c0))
dup2(r5, r0)
setsockopt$inet_opts(r0, 0x0, 0xd, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
setrlimit(0x0, &(0x7f0000000040)={0x0, 0x50})
ioctl$FIOASYNC(r0, 0x80047466, &(0x7f0000000200)=0x5)
ioctl$TIOCSBRK(r1, 0x2000747b)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
readv(r0, &(0x7f0000000040)=[{0x0}], 0x1)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x300100000})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000002}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendmsg$unix(r0, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000040)=[{0x4d}, {0x40}, {0x86}]})
syz_emit_ethernet(0x2e, &(0x7f0000000200)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000280), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x84}, {0x54}, {0x6}]})
syz_emit_ethernet(0x1b, &(0x7f0000000000)=ANY=[])


r0 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1000, &(0x7f00000000c0), 0x1)
recvmmsg(0xffffffffffffffff, &(0x7f0000000040)={&(0x7f0000000000)={0x0, 0x0, &(0x7f0000000100)=[{&(0x7f0000000240)=""/61, 0x3d}], 0x1, 0x0}}, 0x10, 0x0, 0x0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt$inet6_MRT6_ADD_MIF(r1, 0x29, 0x32, 0x0, 0x0)
r2 = socket(0x18, 0x2, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000140), &(0x7f0000000180)=0xc)
socket$inet(0x2, 0x2, 0x0)
setreuid(0xffffffffffffffff, 0xee00)
r3 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r3, 0xffff, 0x1000, 0x0, 0x0)
syz_emit_ethernet(0x5e, &(0x7f0000000080)={@broadcast, @random="be2c6050b8fb", [], {@ipv6={0x86dd, {0x0, 0x6, "fecf0c", 0x28, 0x0, 0x0, @ipv4={'\x00', '\xff\xff', @multicast1}, @rand_addr="ff94d99b4500", {[], @icmpv6=@ndisc_redir={0x89, 0x0, 0x0, '\x00', @loopback, @ipv4={'\x00', '\xff\xff', @local={0xac, 0x14, 0x0}}}}}}}})
socket$unix(0x1, 0x2, 0x0)
open(&(0x7f0000000180)='./file0\x00', 0x200, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
getpid()
msgsnd(0x0, &(0x7f0000000140)=ANY=[], 0x401, 0x0)
msgget(0x1, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
sysctl$kern(&(0x7f0000000200)={0x1, 0x16}, 0x2, &(0x7f0000000280)="d2a4629fc3395824c3a6abdd47f46546f69cc6e639e3d9a57d4128e369e2a1adea72966b04d93220fd53c6a03539263ddd16b7ef9361d4f95416cf2f6753546a3ec1c85912182e26bc6fd7da32709b62ab10563dbc2c95973738453937ab0b25a707e2e34d09898ac2b42f882f9b6489e71a05f7af1e04ecd3413e1f4c15b192741942fbeb59b27229e76d5cde8ebe4b804ab243884ec79687a1d1603095c3be4c6d4e1d738da1e89662aadf78c9e16781f88083a35e2e4a3150e51a462e175f935429e9d6f1b670f274e061b861b66557563bda038e88ac142d20e7c523df0d36c26bea26cc139b2347f38957a20641229247", &(0x7f0000000380)=0xf3, &(0x7f00000003c0)="ccce78f37b1cb121ed0382df6d01c1bf274d04f381015a8cfe8e35970d1164bf697af43f4ff439044c30b2f0e30adf0fee87917ea4bfb889872f068cfc881796d26b0f2eb283778cec23b3a41e3ea66e08330e36d57de7c3f9333c16", 0x5c)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000900), 0x0)
r4 = msgget$private(0x0, 0x0)
mprotect(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x2)
minherit(&(0x7f0000ffd000/0x2000)=nil, 0x2000, 0x3)
msgctl$IPC_RMID(r4, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000280)=[{0x5c}, {0x50}, {0x6}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[])


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0xffffffffffffffff}})
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = socket(0x800000018, 0x1, 0x0)
ioctl$PCIOCGETROM(0xffffffffffffffff, 0xc0107005, &(0x7f0000000080)={{}, 0x0, &(0x7f0000000040)})
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x800008, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0206923, &(0x7f00000001c0))
ioctl$FIONREAD(r0, 0xc0206923, &(0x7f00000001c0))


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
socket$inet(0x2, 0x3, 0x2)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
open$dir(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
ktrace(&(0x7f0000000440)='./file0\x00', 0x4, 0xf06, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000000c0)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
recvfrom$unix(r2, &(0x7f00000000c0), 0x832f1f7d, 0x0, &(0x7f0000000000)=@abs, 0x2000c600)
sendto$unix(r3, 0x0, 0x0, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
semctl$SETALL(0x0, 0x0, 0x9, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0x4, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0xfffffffffffffe37)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r4 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7949)
writev(r4, &(0x7f00000000c0)=[{&(0x7f0000000080)='#!', 0x2}], 0x1)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x800, 0x0)
kevent(r4, &(0x7f0000000200)=[{{}, 0xfffffffffffffffc, 0x18, 0xf0000000, 0x7fb, 0x4}, {{r1}, 0xfffffffffffffffa, 0x4, 0x1, 0xffffffffffffffff}, {{r4}, 0xfffffffffffffffd, 0x40, 0xf0000000, 0x3, 0x5000000000}, {{}, 0xfffffffffffffffe, 0x0, 0xfffff, 0x403, 0x99c4}], 0x4, &(0x7f0000000280)=[{{}, 0x0, 0x0, 0x2, 0x8, 0x2d5375e0}, {{}, 0x0, 0x41, 0x0, 0xfffffffffffffc01, 0x19}, {{}, 0xffffffffffffffff, 0x0, 0x40000000, 0x10000000000006, 0x80000001}, {{}, 0xffffffffffffffff, 0x12, 0xfffff, 0x1, 0x80}], 0x80000000, &(0x7f0000000440)={0x0, 0x8})
syz_emit_ethernet(0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
r5 = socket(0x2, 0x1, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$inet(r5, &(0x7f0000000000), 0x10)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000180)={0x3, &(0x7f0000000080)=[{0x87}, {0x44}, {0x6, 0x0, 0x0, 0x1000}]})
write(r0, &(0x7f0000000040)="7f00"/14, 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000280), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000040)=[{0x3}, {0x4}, {0x8106}]})
syz_emit_ethernet(0x32, &(0x7f0000000200)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
r2 = dup2(r0, r1)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000001c0)=[{0x81}, {0x2}, {0x8106}]})
syz_emit_ethernet(0x4a, &(0x7f0000000200)=ANY=[])
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
writev(0xffffffffffffffff, &(0x7f0000000180)=[{&(0x7f0000000000)="9da8e3e9ed", 0x5}], 0x1)
r3 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000080), 0x8, 0x0)
ioctl$WSMOUSEIO_GETPARAMS(r3, 0x80105727, &(0x7f0000000100)={&(0x7f00000000c0)=[{0x23, 0x2}, {0x8b, 0x80000000}, {0x45, 0xef07}, {0x101, 0x3f}, {0x45, 0x7}, {0x23}], 0x6})
r4 = socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(r4, 0x80206979, &(0x7f0000000000))
r5 = syz_open_pts()
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r6 = syz_open_pts()
close(r6)
syz_open_pts()
ioctl$FIOASYNC(r6, 0x80047469, &(0x7f00000000c0)=0x5)
writev(r6, &(0x7f0000000380)=[{&(0x7f0000000080)="e0", 0x1}, {&(0x7f0000000100)="6fa533b2eda506b781f8dbc069461641c8da6d2785be257e9335395711a3c7bb0641c680be122bb694db035c7ff596ddc06acd1ed5f884d1d7820bd4eb283ccca63a80435b8b57253e7fd0cb02d9ea1683186f1afd3976fcfcd3", 0x5a}, {&(0x7f0000000180)="c88483de365a5309893d38c4b4701e88a5f1d3a8e59c1f6f3790ceef13c83d3f54530552ecaeb64b69ed438e15ba62710e5e3231d50932b6d50934c3201e78970ac1b0a85527e0e1006b0cda673f8dd39b57b7643d24f61afa7cfc8683b59b741bac0d39438fe9727a8827bcb524eca9c32ec59f515d4ab671a0d3f2ca43e65ed3f69a860f304ef2f526391bd840ddc36e729d29c205f7bf7b1ae0abf525faa46cbc5ebb8599795cd4d742e70c750e4ce6d249c47e8e6a82cf9a7688df513b3f344c9bcf45e89f5ee16b01e6d8647c4129ee89d8ca4db3fe8e0abb687fb64d8140c71a1f36eb04", 0xe7}, {&(0x7f0000000280)="978f1d00f7e35bd3fd0202fdf9c0d9ccba091c2409a7f79b9e4abe9d5cf493163cb730aa61c9548a0f8519c778af0c2fc42937fbe082ac5f003b74c11c33b7cd46ccdc7fdf3649388e5865ae19b2f68dd87babc9995e727666def7155f4d7b37e145996a42cf89df895a60", 0x6b}, {&(0x7f0000000000)="b06bd2f306128f5c98b4f9af9495df0317cd4a579946d6d9b7e2d2fec6fe448e57aa46e17a268288e2d98e498e07c4ab931e43178557a5bcf7d2ac5f55577fe4943bb58cd47e701385", 0x49}], 0x5)
close(r5)
syz_open_pts()
getuid()
r7 = semget$private(0x0, 0x7, 0x3c0)
semctl$SETALL(r7, 0x0, 0x9, &(0x7f0000000380)=[0x400, 0x1, 0x8, 0x6, 0xc65])
semop(r7, &(0x7f0000000100)=[{0x3, 0xe, 0x1000}, {0x4, 0x303}, {0x1, 0x8, 0x1000}, {0x3, 0x7f, 0x1800}, {0x2, 0x1, 0x800}, {0x2, 0x202, 0x3000}], 0x6)
semctl$IPC_RMID(r7, 0x0, 0x0)
r8 = msgget$private(0x0, 0x597)
msgrcv(r8, &(0x7f0000000500), 0x1008, 0x0, 0x800)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000000), 0xc)
getpid()


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
recvmmsg(0xffffffffffffffff, &(0x7f0000000040)={&(0x7f00000000c0)={0x0, 0x0, &(0x7f0000000580)=[{0x0}, {0x0}, {&(0x7f0000000240)=""/90, 0x5a}], 0x3, 0x0}}, 0x10, 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x18, 0x1, 0x0)
close(r3)
r4 = socket(0x18, 0x3, 0x0)
r5 = dup2(r4, r4)
setsockopt(r5, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendmsg$unix(r4, &(0x7f0000000580)={0x0, 0xa, 0x0}, 0x0)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xffffffffffffffff, 0x0, 0xffffffffffffffff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x3}, 0xc)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x34}, 0x4, &(0x7f0000000080), 0x0, 0x0, 0x0)


msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000040)={{}, 0x0, 0x0, 0x0, 0x0, 0x400000000004})
sysctl$kern(&(0x7f0000000080)={0x1, 0x27}, 0x4000000000000004, 0x0, 0x0, 0x0, 0x0)


r0 = syz_open_pts()
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
flock(0xffffffffffffffff, 0x0)
flock(r0, 0x0)
syz_open_pts()
socket(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
msgctl$IPC_SET(0x0, 0x1, 0x0)
r1 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
pwritev(r1, &(0x7f0000000380)=[{&(0x7f0000000440)="e9", 0x1}], 0x1, 0x3fffd)
r2 = open$dir(&(0x7f00000003c0)='./file0\x00', 0x20, 0x0)
preadv(r2, &(0x7f00000004c0)=[{&(0x7f00000000c0)=""/99, 0xfffffd23}], 0x1, 0x0)
truncate(&(0x7f0000000140)='./file0\x00', 0x30001)
recvmsg(0xffffffffffffffff, 0x0, 0x0)
sendmsg(0xffffffffffffffff, 0x0, 0x0)
r3 = open(&(0x7f0000000080)='./file1\x00', 0x200, 0x0)
mmap(&(0x7f0000011000/0x2000)=nil, 0x2000, 0x0, 0x10, r3, 0x0)
mprotect(&(0x7f000000e000/0x4000)=nil, 0x4000, 0x3)
mlock(&(0x7f000000f000/0x4000)=nil, 0x4000)
dup(0xffffffffffffffff)
close(0xffffffffffffffff)


r0 = socket(0x2, 0x3, 0x2f)
r1 = dup(r0)
setsockopt$inet_opts(r1, 0x0, 0x22, &(0x7f0000000040)="fd0cc085", 0x4)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000002a40)={&(0x7f0000000000), 0x10, 0x0}, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
sendmsg$unix(r0, &(0x7f0000002a40)={0x0, 0x0, 0x0, 0x34}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000340)=[{0x1}, {0x15}, {0x46}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
r2 = dup(r1)
recvmmsg(r2, &(0x7f0000000440)={&(0x7f00000000c0)={0x0, 0x0, &(0x7f0000000580)=[{0x0}, {0x0}, {&(0x7f0000000240)=""/90, 0x5a}], 0x3, 0x0}}, 0x10, 0x0, 0x0)
close(r2)
dup2(r0, r1)
openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
writev(r1, &(0x7f0000000640)=[{&(0x7f0000000140)="90", 0x1}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{0x64}, {0x2c}, {0x46}]})
syz_emit_ethernet(0xba, &(0x7f0000000080)=ANY=[@ANYRES32])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000100)=[{0x2}, {0x28}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000000)=ANY=[])


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
r2 = dup2(r0, r1)
ioctl$TIOCSETD(r2, 0x8004741b, &(0x7f0000000900)=0x4)
kqueue()
ioctl$FIOASYNC(r0, 0x80047470, &(0x7f0000000280)=0x1)
select(0x40, &(0x7f00000002c0)={0x7fffffffffffffff}, 0x0, 0x0, 0x0)


sysctl$net_inet_icmp(&(0x7f00000005c0)={0x4, 0x2, 0x1, 0x5}, 0x4, &(0x7f0000000600), 0x0, &(0x7f0000000680), 0x0)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x881)
r0 = open$dir(&(0x7f0000000240)='./bus\x00', 0x0, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x801)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r1 = syz_open_pts()
dup2(r1, r0)
r2 = open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSETD(r2, 0x8004741b, &(0x7f0000000080)=0x9)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000040)=[{0x1c}, {0x61}, {0x8106, 0x0, 0x0, 0x3}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
open(&(0x7f0000000280)='./file0\x00', 0x0, 0x0)
ktrace(0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000240)={0x3, &(0x7f0000000400)=[{0x7}, {0x50}, {0x6, 0x0, 0x0, 0x239}]})
write(r0, &(0x7f0000000000)="7696e5f3d1f18c37cea8615ac7cf", 0xe)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x25}, 0x4, &(0x7f0000000200), 0x0, 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r1, 0x80206932, &(0x7f0000000100))


mknod(&(0x7f0000000000)='./bus\x00', 0x2000, 0x6380)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x6381)
open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000280)='./bus\x00', 0x0, 0x0)
open(&(0x7f0000000bc0)='./file0\x00', 0x0, 0x0)


faccessat(0xffffffffffffffff, &(0x7f0000000000)='./bus\x00', 0x0, 0x0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd02)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0x81946467, &(0x7f0000000180)={0x0, 0x0, 0x0})


r0 = socket(0x1, 0x1, 0x0)
fcntl$setstatus(r0, 0x4, 0x40)
shutdown(r0, 0x2)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000140)="b1000503000004000000000007000000331c13fecea10500fef96ec0c72fd3bc7ae30200004e3039d2d236acf20b7804be38164991f7c8ad5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b1257aea8c500002002fbfe0c2300008abfba090000000835713f00219b8db5ccd2feae000000000000b71d89e0000407", 0xb1, 0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x401})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000040)={0x0, 0x6d5, 0xfffffffe, 0xd2d, "8717f9050700000000000090d6b2480d51aa8000"})
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000480)='\r', 0x1}], 0x1)


r0 = kqueue()
kevent(0xffffffffffffffff, &(0x7f0000000200)=[{{}, 0xfffffffffffffff9, 0xd, 0x10}], 0x0, 0x0, 0x0, 0x0)
kevent(r0, 0x0, 0x0, &(0x7f0000000000)=[{{r0}, 0xffffffffffffffff, 0xc1}], 0xff, 0x0)
kevent(r0, &(0x7f0000000000), 0x3ff, 0x0, 0x8000800, 0x0)


pipe2(&(0x7f0000000040), 0x0)
r0 = socket(0x18, 0x2, 0x0)
setgid(0xffffffffffffffff)
close(r0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
r1 = socket(0x0, 0x0, 0x0)
msgctl$IPC_SET(0x0, 0x1, 0x0)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000), 0x4)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000440)={0x3, &(0x7f0000000240)=[{0x3}, {0x20}, {0x6}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


r0 = geteuid()
r1 = semget$private(0x0, 0x4, 0x3c8)
semop(r1, &(0x7f0000001480)=[{0x3, 0x6}, {0x1, 0x8}, {0x3, 0x1, 0xfb0bf9bc52962a4e}, {0x0, 0xfffd, 0x1000}, {0x1, 0x1, 0x3400}, {0x0, 0x9}, {0x3, 0x800, 0x1000}], 0x7)
semctl$SETALL(r1, 0x0, 0x9, &(0x7f00000002c0)=[0x3, 0xfff])
semctl$SETALL(r1, 0x0, 0x9, &(0x7f0000000140)=[0x6, 0x2080])
r2 = getegid()
r3 = getegid()
getgroups(0x6, &(0x7f00000003c0)=[0x0, 0x0, r2, r3, 0x0, 0x0])
r4 = getuid()
setreuid(0xee00, r4)
r5 = getpid()
getpgid(r5)
shmctl$IPC_SET(0x0, 0x1, &(0x7f00000014c0)={{0x9faa, r4, r2, r4, 0x0, 0x100, 0x101}, 0xfffffffc, 0x8f, 0x0, r5, 0x6, 0x0, 0xb1})
chown(&(0x7f0000000140)='./file0\x00', r0, r2)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000240)={0x3, &(0x7f00000000c0)=[{}, {0x1, 0x0, 0x0, 0x2}, {0x6}]})
socket(0x18, 0x0, 0x0)
socket(0x18, 0x3, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
syz_emit_ethernet(0x2a, 0x0)
getsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1c, 0x0, 0x0)


r0 = socket(0x18, 0x1, 0x0)
getsockopt(r0, 0x6, 0x8, 0x0, 0x0)
r1 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
semctl$GETZCNT(r1, 0x0, 0xf, 0x0)


r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x6, 0x4, &(0x7f0000000000), 0x0)


r0 = socket(0x18, 0x3, 0x0)
getsockopt$inet_opts(r0, 0x29, 0x33, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
accept$inet6(0xffffffffffffff9c, &(0x7f0000000100), &(0x7f0000000140)=0xc)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = socket(0x18, 0x2, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1023, &(0x7f0000000040)=0x3, 0x4)
getpgrp()
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000080)=[{0x1, 0x5, 0x0, 0xfffffffd}, {0x3c, 0x2}, {0x6}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f00000004c0)="ea9ffa45", 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000480), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000040)=[{0x30}, {0x35}, {0x46}]})
syz_emit_ethernet(0x3e, &(0x7f0000000d40)={@local, @random="94ea09066dbd", [], {@ipv6={0x86dd, {0x0, 0x6, "db8344", 0x8, 0x0, 0x0, @rand_addr="135e80f1d38ddba80b9e61dd0c575a88", @local={0xfe, 0x80, '\x00', 0x0}, {[], @udp={{0x0, 0x2, 0x8}}}}}}})


setrlimit(0x8, &(0x7f0000000980)={0x8, 0x2000000100059})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
readv(r0, &(0x7f00000003c0)=[{&(0x7f0000000040)=""/59, 0x3b}], 0x1)
select(0x40, &(0x7f0000000000), &(0x7f0000000040)={0xfffffffffffffffe}, 0x0, 0x0)
writev(r0, &(0x7f0000000080)=[{&(0x7f0000000100)="c9", 0x1}], 0x1)


msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{}, 0x0, 0x0, 0x0, 0x0, 0x8000000000000000})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x800000018, 0x1, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x0, &(0x7f0000000040)})
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x30}})
r2 = socket(0x18, 0x1, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000000)=[{0x5}, {0x60}, {0x5ce}]})
syz_emit_ethernet(0x76, &(0x7f0000000140)=ANY=[])
open(0x0, 0x0, 0x0)
semop(0x0, 0x0, 0x0)
shmctl$IPC_RMID(0x0, 0x0)


setrlimit(0x8, &(0x7f0000000100)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000040)={0x0, 0xcf, 0xd, 0x203519, "1bb7e60ab87aa57800000000d0d200000000fd00"})
writev(r1, &(0x7f0000000000)=[{&(0x7f0000000980)="9b9431a5d715597f32c28150472c5c4a26761d657e140316ea35d282feeeaf745cf3e4bf90e1903276332cfaaa820fef61ff3e48cec7057ad907ac1df25524bd150d15c304380f7ae3170b2fcd5a74731b6cbd17fb8136e5287cb39417d25bd833815ebef001deb672d80fa0f8bc68f7187cd337803948baa7e34f56701b2180ddedf8852feae4274e0629", 0x8b}, {&(0x7f00000014c0)="874efc64a16404b3dc9c5bce1a5ecabc9ad87a2c628890d6c0144206d4f104d9344df375dfd3bb105ae821f98218363f92fa5e9c05234d33d0a8d963888d8822f30019a93c93d85f62e363a3eee977e582890dacc2371a48a4431bd985409647e571a93d2a66e5b7f67ff0c6fa6dd62af727a8200ecc56044fc7d427e40ae2086abd08e51d7b88e9dd4f2f9b44b3e969212e9d954795f6c302de6406b45beeb8f5a34ad8acf5ae86909381263bdee8839a61832d6b11df3dcebcbfd8f73f3da2e026766309eec290c2427714cfa2f92495293de2c336949475c17a49469a7b6d7d237ddfb60b74ef5f99682e18887d3bc75cfce8150b94974af2204d42c994b8910d5fd06b7bd9ab57e26310ac63c59cda6de93302b7e1812811086a2ee2ee23e61b77a6d519b43ddfe016f394ae0a2751d8b420fce01e9dda4c2a43b5318afb3b6b9e9f99d71684bfaf02ed0327a58d5049b8b62e28239022820778336a5ddba0c4c7960d4998b7e8c10e5bc641ee6fe80d267590de91d2b6b50e879119ca15c7f70420506fe54a6c5537a486e83ebbcb7e95af437eefbf299a6c2c9fb95b9983374fe6a743c52828761bfba9f79f6850214ce56ddd9a859bea12b3e8bc2e30aff6aba9a488775d52d1d2a90ec9c23c908f9bd356eead53715274ee47fc9ca4a7a5189fe1027e625b7a3b5350f2b76ec2a1e192eccbce78286f134c4523b74a953bd01754d2238f1880d748c9f55eab8aede59252ca39caad3598d6e9bc03bd59426501afd5ee61ba70ccb04e7e385f3e089c5493ce9ee428c30865f9bec095fbbc30cf50d52e5b2ee7139a6b4c99b82c5a07cb4411f2a0d19174c70e508c2cdb4cad591a33db002d7d5121d6fd26f8b31af12a1e9d2058cb2bc8e34ccb1b23bddb8306484cefecbbd8ae919fc8595c0f25940a449ea2b6f345b8bf320e0a31bbe427d2431bdd52a28d3e5b15169fde2390e3121dc18b6a6c4450a03c3f3f84d9fa5f774c529591058bb00d21bfe726575817b975fb8dc62427f9b7b4f0d22cfa9975b84eded78aa3a0edb9a13165bed3443b5f35d8c68041c081f0af3eabac120d7a8e879b525f0ca9954f2a2ea752ab18683c283410f14bd859ce8806983fd20050ef80155afb0c254a6878e3e099e796242938446a642234ba124bcaecb683bbe7526007befe7d90f120ed76f987f2f8a445dae46c794d4e345564ff042bc68c2b72461ebd498235a1212bd3ed669ac480b011fbb4041136e88003c5210d142ac0c643d3db0039e21e5d9157f26cfc71fb7fe767e9c938e51b64c22ac394c8aec52ee25a226265f632bce7d79c5b7b749b56fa67ac00d5aa0571c573f23fa3ea26f15cb679742c7b9f17e22aae2892006fef55dd244c4613134227ebd4af1e5c7867295b45f91b5bcc7fa0f3ac9daa8f49b9363e9e01250fcc8d72fdcae8f6222ae3a2fb01eef75cbb2ae84ea7fcce5ef3e86c2221ed491f5d7e0b595f574857c20cc49f9162c31e8267984a4328ce6dd4a6de2e68cb4e811391651588873eff36062bb6a7c5df5e870a050338af57644ed41e2e80e66d91dd3744a5c18ec2c30ff917fd7485f92597fe4bc3ab8e18ac1f7d3c80e86a7f1b0b8bdd2f9146a900c63085ff5c6e74dee637fe3c255f16b07f5395e2b803c44147171b52ecee292c414c5415c317b14b8086b15ce3efefcf790a3fd4faf3f3dabe410c730477a829ceb589d567d97e26ccdc6fec6ca5599414458f7c0f459ff45eece2fe4d6b031507b83c44cadf24f5a4b30a8048e4d5b267bc06cc12393fd31bfe8eab256881d2618dd41491418e636be2a412dbed78da3448a52e666d3348fdf76928d380f62dd63f3a01b32679f92d7e3df380b6af601037085266b68abcd636586a763dc244252385b5b80b6c3c3ab5c3cad35bcc7a5f6bdef137e886604f3649b1af4abcd2f3d56f708e8d9003e00866ecf76da72bff382d28efc05d53f31f05e3027d8f699c9f93967bf590c984836ebec878ddcd29fe74f0647fa32ef13201ebf2a81bfd02df5b53e13594b662358e14d9dfe6cd721b31c18e1165e6a1e586b688a97b1a41c028fc1e7d2895fbe915fada9f3c28d9dfb13eda790f67a6d0a190fa80d01a5b58196a7d4827be51f043d56a49ddff95ee20260e02c53f5967ddce1510939ae04916282e782f728f02d62a06a0dc1d285cf4811566eb93d5305696517fd89fcb90fe1ea392e9d35fe02218506581661d2b1d5f4df93a8c3b556912a29e1328c739934d4c8112563c7629040721cd0bfd5c6123b7de1b39c9adb28eb3c97df75d0266dfe02f45428a3785f0ad7ea9b0ba5ff7915ed7aded81ec61c54340c46938c4d7bf8bb2dfe0ba8b69480cd1ea64107acefb62ca76a35be999f646077813d455b51bb643de2a39f7353a9a4a0d69d2200edc3a4fc671eda7db4fa39ca2f6c68a19a5468836fde4eda83145a0569a987e4011679d993420d918a640839f02595fdf0eac4e57f69fa50cc6f01030506df03ad16d418a6fd66c4230c494761e4be904e33dbf4e46c60ac4c0bd04df0da41f1d111c2252edb39c76dba2aec9abd2b2325b5b948db76f451dc23bab13ede45a0d0d63428748bf42de7084547b881f5a70e73e72efdf4046d6b1f677507ae5ce05a5878b542e55ca224e6c89f32e98d270f3644541861b6dbf8e7c2ca3b23f0230cc4d13774339f45f5871a4ac7ff0f460abb7d7d0da6bbedfe27cf2a0d4a140163d76156fb51612f5df85ce150f8795308707ce06b1581fb46d511281d77eb346ec043ca42d6182a8e484571c003f42909c69ca52a77a", 0x7cb}], 0x2)
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000200)="485a3b45042938c62a10619bfa9635e568d85dffffff7f00000000d4536889e89908892b8316047e6dfbb6e1e162571c015e99b581b8e909103942ee8a921cb8d85504b7a940cc09869c3a9f585eb1ad792b59457b2cdcf5ffd25c3d1d9b0be56236bc1f4faa891191b0a962a8989455c84c44199bf73d1b62b88b18c9bed8fcef9da0409c146a0d616fbd50b2bec0f256fd9e21b3fc41849e8967f2beb0a5501e0acdb299f8e242983156a46b53cf77274c1f056d97f0cbc62b7b3625e1e68ccc6687102a38000c9a6cec5590e3", 0xce}, {&(0x7f0000002000)="a0095ba17dd0d086b3b2119ce6a7c6b1e6838280c81119f1665a8453bc1df36edbe9413ed9e9e18a679b6ccd7c1a2e0b63d1de4e941a4efd063dcb3146c575b9700f10316bae4d76cb9ab951cbe141cb7ca93718969e928d443c8a86f7ad244eacec73482dd6dfdd90dd7664fa214398b8b13457d398ce7d953f86304b841c796ec7d6a1afb4a1692f0830caf997b9017541d479b6beb4f57cdc09fdfaa6e560f53348a733a5cba87f54d82fa39b42f30d3976075fadd6ce4c0575c2451e1f2e53c921d7247a9f3ecbf44bdab7ca2f52e490c1b6d87b9f892b359e1a8dac7b4af8715e991ed256d756409730bb65185b8d321e86ff47a96a153b4a1a43540578e0b2bf61935a476864793803b5583328ebd1d5c45077d0ae7bc20ff4c95dcc06bb255720aa614176a9d9554daba519b8f4ecec5e88c7502a5f3bc25ca17d82badf6d682b648398009c9224bec46a02a7454997ea90de2277b55a190e52bcbcfa793d11bd5485831b37f9cb817f5c900ec34b932f076f9000f07e11053f5e9e851448ba62f877da4e89d05c2ac925a89c95769e6b4b6806aef4528b158cfa3bd4cd888f6c75a2a07f2d26b5ffea5334732f5630aa34cedc7550c5add0486735da9dd3ce36201e26248683c1d8ac2bdbd1e4ed25fe4beae9c06ac107d813ed2db7de0dafa0e9df17310ebe807c2ca76e3ad48468bdcb0021ea27c6f648a41fe9073d16fe5d9313dfaf3072a59019bfd9fd675f4cd27bd2483f77b95d0efba1949404db031e1f8cbcd5d8b3893a042b78c69cf00abff8088ef2144a24349a367a6c217ed5856611f3d44064ba2f58585f641c368969f1be0c84d322541d7f1bf3ae403904f2d9bbc4e0daa2b1a1eb14bb6064d629c7f7ffb5186ea27dfbbedace6d76e975bc4d879f72ca6cf8058a6c18e8faf89c5c4c8d206d690256f2974e7d4675e08c5401a3ef3fdf19aca6a70a1a99ded148aea456f6cec5b87e05a1260b0830e4bbb8adacac0fa2e05fa39f5e8113ab6c53c629a7f28cffed8bd22aa2ceee9cbb630cb40d5cc8a44a98ba8ed5b3ed5319c99a8b0070cdefa3f9b386665e9dd5930e18bb7a231108646d1d2c9c6297a8a03f00f69ae3e713f740b41d5e0a6ae22bb5a634ebaf38ee2dc78836714c1b111334c39415d82bf47924c591db9abf16e70a76cd16e780757137fa8928924fe0e433ac7ae099b391079e3f04d4cd107b080f8a7ffd845dd13f17db971cc4392670fe0b250975b209c57387663b8c8c0fe09839bbc05c821e29c7d41b683b10e420c3cb0af82db92abf58e4631233691259345fb9ed0ba227486fbe1efbd215471172b013c60df1e72562439038e83c10942c61bcf613b2c83ef58fc2f5ab8e2368de87392c093d1d652cf3d2a6cd12149ceb64cb6806901114364635221aa83d258bc0367e3305653ac03726d93db99b486b55af18faaca1bd2c8920fc09ff1d03b9c317a6ce578437ba9ec7606a3f0df965edd03f0119c1b1ca0fea3d7d318e68af767ee0168a0ad21aec87825b36dc7bd43b9ca70306e3d387d4667abbb1f024a58bf2fabe56ba49f6a0b75529b33a07ab29f41f0083bbcf1d9d9d98e7acbfac7ab51a98bd5d5b389f64ad13ef0c789e295b1921ab0a470da077a685c84861e8942273c0ebd548ba19d1941471ca03f96be800a52ea7254c3d2d69ca24273d53beee8e11456a07437ff9280fb9de9a1a34c7cd92a7e89498c64e584c994d13395c2460720f81554639b36a9163227898252b0fd99ed3a9156ab65feb8fc70ab1f837f2ecd66f936706cd95b2698f89c9798d6426bd121e11e0674140721c8be3f610aba6e7bf641fc2cdb02b0439e4d8bb6670c4b57038e4db59fc497416ac60bf8f95c3cb01074d83f4b2b92c19ecf2746484dba8bbd4a38da8c23b6faf4fa516603b0c75f2aadc860d3ac5189045fe3d6106160bc6ba2866223c1aecd1547a07a2c3d806137afc843bfca802cad87552afa0c9d1ac8b22c1d6d5fa2f001fad62bd71f24c9f846bd332524044de306c5e62385b40604680b4a2fa276451af36a6e6c89959c0afc48c420237da9f2f4cdd3dec126f16aa1e1f1715ec49e04f98265ad14344b0ad08202c8ae4d8a92dab7317e5bdf42daa1c1b551ca6a147433c632f233d92c99202facec89354a2213e10b125fd", 0x606}], 0x2)


syz_emit_ethernet(0x32, &(0x7f0000000640)={@broadcast, @random="261c7d7c88d0", [], {@ipv4={0x800, {{0x9, 0x4, 0x0, 0x0, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, @rand_addr, @rand_addr, {[@noop, @timestamp={0x44, 0xc, 0x9, 0x3, 0x0, [{}, {}]}]}}}}}})


faccessat(0xffffffffffffffff, &(0x7f0000000000)='./bus\x00', 0x0, 0x0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x80000001)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000000c0)=[{0x3d}, {0x5}, {0x8006}]})
syz_emit_ethernet(0x138, &(0x7f0000000080)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000380)=[{0x3}, {0x34, 0x0, 0x0, 0x2}, {0x8006}]})
syz_emit_ethernet(0x56, &(0x7f00000003c0)=ANY=[])


r0 = socket(0x2, 0x2, 0x0)
sendmmsg(0xffffffffffffffff, &(0x7f0000000000)={&(0x7f0000000f80)={0x0, 0x0, 0x0, 0x0, 0x0}}, 0x1, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x2, 0x2, 0x0)
bind(r1, &(0x7f0000000000), 0x10)
connect$unix(r1, &(0x7f0000000000), 0x10)
bind(r0, &(0x7f0000000000), 0x10)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000700), 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ioctl$BIOCGFILDROP(r0, 0x40044278, &(0x7f00000000c0))
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(0x0, 0x0, 0x1100, 0xffffffffffffffff)
r1 = socket$inet6(0x18, 0x5, 0xff)
recvmmsg(r1, &(0x7f0000000400)={&(0x7f0000000200)={0x0, 0x0, &(0x7f00000008c0)=[{0x0}, {0x0}, {0x0}, {0x0}, {0x0}, {&(0x7f00000017c0)=""/185, 0xb9}, {&(0x7f0000000440)=""/222, 0xde}, {0x0}, {0x0}, {&(0x7f00000007c0)=""/238, 0xee}], 0xa, 0x0}, 0x6}, 0x10, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000280)={<r2=>0xffffffffffffffff})
dup(r2)
sendmmsg(r2, &(0x7f0000000040)={0x0}, 0xffffffffffffff12, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x3, 0x0, "0100012d29fb000700000000098002005a00"})
ktrace(&(0x7f0000000080)='./file0/file0\x00', 0x4, 0x800, 0xffffffffffffffff)
getpgrp()
r3 = msgget$private(0x0, 0x421)
r4 = socket(0x11, 0x3, 0x0)
sendto$unix(r4, &(0x7f00000002c0)="b10005010000009f0500070107000000331c13fecea70500fef96ecfc72fd3357ae30200004e30ffd2d236acf20bf404be01000000f7c8cf5f882b297be1aa050400ce94e2f0ad3ebbc257699a1f139b672f335c22db830c032bfa896443c32118210000720fd38bfb0000fd54c125191b1257aea8c500001602fbfe0c2300008abfba0900000808f37193f8343712cc1100b71d0900090105000000000000001300"/177, 0xb1, 0x0, 0x0, 0x0)
r5 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r6 = dup(r5)
pwritev(r6, &(0x7f0000000140)=[{&(0x7f0000000580)="c6302c9c455c7be3d8598d3ac53af8e7574f36a8db981ae2d8854330fd7f9fc4ba71ba88b9ff297ff033cc3a3dd93a7e60391b1e6b1d20ad08c2a031eb04353f", 0x40}], 0x1, 0x400)
writev(r6, &(0x7f0000000540)=[{&(0x7f0000000240)='<', 0x1}, {0x0}], 0x2)
ioctl$BIOCSETF(r6, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000180)=[{}, {0x8000, 0x9, 0xcd, 0x9}, {0x3800, 0x7, 0x5, 0x80000000}]})
execve(0x0, 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
pwritev(0xffffffffffffffff, &(0x7f00000001c0)=[{&(0x7f00000005c0)="18d26cb474b5c9d53e0ffdba8c54fecc9031509b1623088cc3e85353a5586603eebda7eccfc5ced62c70a12fbffc2425f3f9e50317605792ea906ef56376aa499b9a909aff511ad2d63fc010ee2292f393b11d78e8bc095bbd866e81599df546afa16ce278edae371c4f16d4df85f4ba622daf27aa8a728453bc4e93539080b8d73936bf6499780255943ab4ebd03bdae91f09e60447e17e0e21bf2dbd2c39", 0x9f}], 0x1, 0xb3)
msgget$private(0x0, 0x480)
msgrcv(r3, 0x0, 0x0, 0x3, 0x0)
execve(0x0, 0x0, &(0x7f00000009c0)=[&(0x7f0000000a80)='\xab\xec:\xd2\xdf\x92\xb78%(\n4\xf4O\v|\x00'/30, &(0x7f0000000f00)='*/}\x00', &(0x7f0000000740)='\x18\x15\x0e\nr\x15\x15N\xf3\x97[,B\x93'])


r0 = socket(0x2, 0x2, 0x0)
connect$unix(r0, &(0x7f0000000a80), 0x10)
r1 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x9, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000000)=[{{r1}, 0x0, 0x0, 0x0, 0x3, 0x100000000000000}], 0x0, 0x0, 0x0, 0x0)
r2 = socket(0x11, 0x3, 0x0)
setsockopt(r2, 0x11, 0x2, &(0x7f0000000000), 0x4)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x3, 0x0, "0100012d29fb000700000000098002005e00"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0x4, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0xfffffffffffffe37)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f00000000c0)=[{&(0x7f0000000080)='#!', 0x2}], 0x1)
write(0xffffffffffffffff, &(0x7f0000000040)="0920e80000007c60e1016745b65369db00000000ebbd07a90172c84c838b4278ad535c39413f308cbbaee4ffcb7f31dbd1562eb77b6a0a", 0x37)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
r3 = socket(0x2, 0x1, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$inet(r3, &(0x7f0000000000), 0x10)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000240)=[{0x84, 0x3f, 0x1}, {0x20}, {0x3786, 0x1}]})
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[])


r0 = socket(0x18, 0x2, 0x0)
close(r0)
socket(0x800000018, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmsg(r0, &(0x7f0000000280)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000300)=ANY=[@ANYBLOB="10"], 0x10}, 0x0)


open(&(0x7f0000000100)='./file0\x00', 0x70e, 0x0)
r0 = socket(0x2, 0x4001, 0x0)
r1 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r1)
r2 = dup(r0)
recvmsg(r2, &(0x7f00000002c0)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)


pipe2(&(0x7f0000000040)={0xffffffffffffffff, <r0=>0xffffffffffffffff}, 0x0)
r1 = socket(0x18, 0x2, 0x0)
setgid(0xffffffffffffffff)
socketpair$unix(0x1, 0x6, 0x0, &(0x7f0000000140)={<r2=>0xffffffffffffffff})
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000280)={0x0, 0x0, <r3=>0x0}, &(0x7f0000000340)=0xc)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r3, 0x0, 0x0, 0x20, 0x7fff}, 0x0, 0x9})
sysctl$kern(&(0x7f00000000c0)={0x1, 0xc}, 0x2, &(0x7f00000004c0)="71f91e3471ac0058bc6e91501d0200000000000000b59c7afec370825c8bace20edd09039c646ac19bb2f12974d31c5bd43529be92425c1affc2121e5b", &(0x7f0000000180)=0x3d, 0x0, 0x0)
close(r1)
kevent(r0, &(0x7f0000000080)=[{{}, 0xfffffffffffffffe, 0xa, 0x20, 0x0, 0x4}], 0x0, 0x0, 0x1, 0x0)
r4 = socket(0x6, 0x2, 0x4)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0xb0}, 0x5})
r5 = socket(0x18, 0x1, 0x0)
connect$unix(r5, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r5, &(0x7f00000000c0), &(0x7f00000001c0)=0xc)
socket$inet(0x1e, 0x3, 0x0)
select(0x40, &(0x7f0000000000), &(0x7f0000000040)={0x20000007fffffff}, 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x2)
select(0x40, &(0x7f0000000180), &(0x7f00000001c0)={0xff}, 0x0, 0x0)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x1006, &(0x7f00000000c0), 0x10)
setsockopt$sock_int(r4, 0xffff, 0x0, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r4, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
mprotect(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x2)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000480)={0x0, &(0x7f0000000240)})
socket$inet6(0x18, 0x0, 0x0)
getsockopt(0xffffffffffffffff, 0x0, 0x12, 0x0, 0x0)
r6 = socket(0x11, 0x3, 0x0)
sendto$unix(r6, &(0x7f0000000000)="b10005016000009f0500000007000000331c13fecea10500fef96ecfc72fd3357a068da3a5673039d2d236acf20b7804be38164991f7cccf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f4d335c223e7d026ba8af63003728211e000000720fd38bfbb770c1f5a872c881e2772ec5a10400000000000000361b1257aea8c5d0002012020000000000880d6633c556ae9be371a3f8343712051eeab71d89000407000000800420000000", 0xb1, 0x0, 0x0, 0x0)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000080)={&(0x7f0000000040)=[{}, {0x24}], 0x2})


open(&(0x7f0000000180)='./bus\x00', 0x0, 0x0)
open(0x0, 0x0, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x20530c)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
writev(r0, &(0x7f0000000280)=[{&(0x7f00000001c0)='ol', 0x2}], 0x1)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
ktrace(&(0x7f0000000040)='./file0\x00', 0x4, 0x6000043e, 0xffffffffffffffff)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001600)={0x0, 0x0, 0x0, 0x0, &(0x7f0000002c40)=ANY=[], 0x10}, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff})
sendmmsg(r1, &(0x7f0000001440)={0x0}, 0x10, 0x0)


r0 = syz_open_pts()
ioctl$TIOCCONS(r0, 0x80047462, &(0x7f0000000000)=0x7)
r1 = syz_open_pts()
ioctl$TIOCCONS(r1, 0x80047462, &(0x7f0000000240)=0x2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000140)=[{0x7}, {0x24}, {0x6}]})
syz_emit_ethernet(0x127, &(0x7f0000000040)=ANY=[])


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x5900)
r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
kevent(0xffffffffffffffff, &(0x7f00000000c0)=[{{r0}, 0xffffffffffffffff, 0xb7c61f5c345976d}], 0x0, 0x0, 0x0, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x7, 0x0, 0x0, 0x0)
close(r1)


r0 = socket(0x2, 0x1, 0x0)
setsockopt(r0, 0x6, 0x4, &(0x7f0000000140)="aef43c05", 0x4)
connect$unix(0xffffffffffffffff, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
connect$unix(r0, &(0x7f0000000000), 0x10)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
sendmmsg(r0, &(0x7f0000000080)={0x0}, 0x10, 0x0)
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x10, r1, 0x0)
ftruncate(r1, 0x25b3)
execve(0x0, 0x0, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b10005040000000000000000071000001a5113fecea10500fef96ecfc72fd3357a89583535673039d2d236ace20b7804be38164991f7c8cf894f2b297be1aa5b22abeb51e2f0ac3ebbc2feb3fda1139b672f4d3353eb067e7335a069d7080000000000000000008904000000000022830cf41bed66f40066ccdcf3e4999d9d20002002c5dbfad800000008e371a3f8340012051e0000000000000200"/177, 0xb1, 0x0, 0x0, 0x0)
r1 = openat$pf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
unlinkat(r1, &(0x7f0000000180)='./file0\x00', 0x8)
nanosleep(&(0x7f0000000000), 0x0)
clock_settime(0x100000000000000, &(0x7f0000000040))
socket(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206923, 0x0)
kqueue()
r2 = kqueue()
kevent(r2, &(0x7f0000000040)=[{}, {{0xffffffffffffff9c}, 0xfffffffffffffff9, 0xd5, 0x10}, {{}, 0xfffffffffffffffe}], 0x9, 0x0, 0xe9ea, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000100)=[{0x3d}, {0x6c}, {0x8016}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x4e, &(0x7f0000000100)=ANY=[])


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{}, {0x3, 0x0, 0x0, 0x49}, {0x81, 0x0, 0x0, 0x2}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1934, 0x0, 0x94e88e483d20a485)
open(0x0, 0x0, 0x0)
setrlimit(0x0, 0x0)
close(0xffffffffffffffff)


socket(0x11, 0x3, 0x0)
socket(0x2, 0x1, 0x0)
socket(0x18, 0x3, 0x0)
socket(0x1, 0x1, 0x0)
socket(0x2, 0x3, 0x0)
pipe(&(0x7f00000000c0)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
poll(&(0x7f0000000000)=[{r0}], 0x1, 0x0)
dup2(r0, r1)
select(0x40, &(0x7f00000000c0), 0x0, &(0x7f0000000240)={0x3ff}, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
ioctl$FIONREAD(r0, 0x8080691a, &(0x7f0000000100))


sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
openat$tty(0xffffffffffffff9c, &(0x7f0000000040), 0x80, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x3ff, 0x22e, 0x0, 0x0)
getsockopt(r0, 0x29, 0x23, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
syz_emit_ethernet(0xe26, &(0x7f0000000100)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaa"])
r1 = kqueue()
kevent(r1, &(0x7f0000000080), 0x101, &(0x7f0000000140), 0xffff, 0x0)
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0x80206979, &(0x7f00000001c0))
socket(0x2, 0x0, 0x0)
r3 = socket(0x2, 0x3, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)
sendto$inet(r3, &(0x7f0000000680)="cbc7fe96b6eb2bba76d2b9449899032f66add755a3d40ffe5ef0ec3fdaf327d90b1acccf8e98a3b17ae78fa871945803d25ac0e8aa28ba36e5c0fa29dfa01dcba45aef9981d87a708124cc90aff908b3b82a5c30e4eb828fcd1873d8a18ed6dddf67bd182b445bfab4e8aa3d199c8ad5f40d356f2157cd6dcdbb402e12d5dc72c06e301deddade58d790447f11f742d6dd363ef3c817d8764529d912a63922211422423137ada36b0160541117788dfbfc8c010916851918e47edecc3872869580f200b54703831613b92d0bcb62de48b5452a9bbb38a543c220b5893a24b8257cfb1df405a7d4e5af8c137b6be0cd16465676cbea5306eccd64089185178fe1a4b85e290cf38fbd18e6feb1c2e8fe835b272ed7d51a2a0b869f4477768a472c7d1500d287ce447b6c3a42b2bc48d9a0d99b642c13588291db22223e03c4e3b83723f98ad576113f00000000000000cc2e0c2d358502eaf53840782b331c91795ab90596dd5bf52301bfe0a5ff6eba19d0806ae31235db3338f7a7eb24b8fdd87e50e6c46e1f17d882f7eb62dfd1be51f933122dda5607645cbbd7d5c98facfcde1ac920b5bd21f29b7dc73a516b4e06479a8db06b59c33adaecd04dc38be752f4ed90761f3e3b241beb9fb2f7aab924dc03ef0892ef62e86c8d50ab60d88f2096a76c7524efe2df0021d16cc5849103433d4fbe53574ab97cc21ea5cba077f5bc683ed1f6dfd101a8f53ab8abed8a9c492cbf4e1e06e872e6c96abb9325f7237af4584098b7b89e94362877be33e7d90e848cae3d99eff9e7859e2268c5b8cda5a6269d16f98799f91e1afe1e480681583f4d55ecf7fe571d9c09eb83942da3e421b0bc60c7f18510c5374bf727310ea86bec5a5313eee5d961e2f2dc9b37b3a1ce7fe4b3de3794964c55dc50aba6ad1948d20f67b8e68cbe71dc1c9d8e02c75c2e81d4dddfa4657988b4af9744265199a8a48169963b12f2fa24e426024ac9969e1e348fd57a8adc277127e9fac5e640960991e9a6e0e1097f96979c711f2580c94140431d952b72cfd2f773deab68ec07bb56464aaa7e6bbeb325575f92ef8a05ee247e2273b6e31904f1b9f440db0d65ea198d7418859d9e0130e99eed40e34db0d661d834f43e48a8b271d94f92dfb3999b03b86d41d9b8ef4df3ba51dcdfb559725ecaad6b64c853b569be3c83b7f9ac136b7a02181e10aefca3d6a72f8d4ccf0a6dd3f5b01a059b8d47aac30478fe4cbb42000c69fb9b0c63c80d27049677af67c68e56a1a1223a82cc780063c6fa5010bfd60075975b300d1374a431828f5921e5e64f1da40f28a94baabc374c5e19770c1d58cf9895192e0a504abd2ef59ec7830e95a9cd0ccba54f0a1580a4c9d715dc7afa3287b5a5c20dad69e5fe1818007d4c85b19f5a78caaaca4c762ce426fc1818e724d76eaeecc194936889dfa2391d809c16cd72054eb208cbebb3c4e0daf4cbe6fe9e350df18130137e163280d5b83f6bc33fc27b041ff130dda3ccb93d260d380d845fde501fe6fd3f74beb3ba6c6f7ef1d200002c9cb10da82699311b9003954de25984bbf43bb51c54b8a1a24d24e02e94b97a5ae92e73f05c4c9aee115645dc7a84c12fb23ece3df8d13fe473fa9fa09f2312ca97b0e735882325ed01b5873d274044a2478445a609ed98670a476ffa94b2594f561af5fd70cfe44618e33d6cb9aefbac3d784da059fd1b7a3ffea36894d0e011563c5ff3291b4ff2da71f36f0bafffa74086bdb64f24ad8af4130f907fdc92f66db45a822dd02880b863d844227c761658ac91a9a5aeb803dcbc7e60ad8c1e4531e7e52d112d600bd059938f10f1572c50fdd1618ad1f96fb06f56c3260f5df6ec461653141fc36a7c98207443d55917763e17b1a7e40dfd5bbb39aadd5656522eca4fea463014f90517eeeaaf8602538b2fa197ad15bdaf3e04ba7967e64b3eb03416c3813fd22e1666a97dcd95e963f8d66e563e0d22fcc6464b84242237320802f0adf0926d439de03c78598e710684e88cc7eae195cb1feab26c2dd588ae618408fd9fb60003e20c608e0a42aefd26fd4a3c9058367029fd2f372c", 0x5c9, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000140)=[{0x74}, {0x84}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000100)=ANY=[])


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
mmap(&(0x7f0000003000/0x4000)=nil, 0xfffff000, 0x0, 0x1011, 0xffffffffffffffff, 0x0)
openat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x0, 0x0)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f0000000100)={0x10, 0x0, [{&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {&(0x7f0000d2f000/0x4000)=nil, &(0x7f000082c000/0x3000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000400000/0xc00000)=nil}, {&(0x7f0000626000/0x2000)=nil, &(0x7f000093c000/0x2000)=nil}, {&(0x7f0000da9000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000e0a000/0x2000)=nil, &(0x7f0000c17000/0x3000)=nil}, {&(0x7f0000b64000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f000062b000/0xf000)=nil, &(0x7f00004df000/0x4000)=nil}, {&(0x7f00008bf000/0x3000)=nil, &(0x7f0000af4000/0x13000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffb000/0x4000)=nil, 0x4}, {&(0x7f0000601000/0x3000)=nil, &(0x7f0000dba000/0x4000)=nil}, {&(0x7f000064c000/0x2000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {&(0x7f0000c2a000/0x2000)=nil, &(0x7f0000518000/0x3000)=nil}], './file0\x00'})
r0 = socket(0x1, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x0)
r1 = open(&(0x7f00000001c0)='./file0\x00', 0x0, 0x0)
mknod(&(0x7f0000000140)='./file0\x00', 0x8, 0x33da)
ktrace(&(0x7f0000000000)='./bus\x00', 0x1, 0x200, 0xffffffffffffffff)
r2 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000480), 0x8000, 0x0)
bind(r2, &(0x7f00000004c0)=@in={0x2, 0x2}, 0xc)
msgget$private(0x0, 0x460)
sysctl$vm(&(0x7f0000000000)={0x2, 0x8}, 0x2, &(0x7f0000000040)="1b729cf5", &(0x7f0000000100)=0x4, &(0x7f0000000140), 0x4)
r3 = socket$inet(0x2, 0x3, 0x3d)
setsockopt$inet_opts(r3, 0x0, 0x1, &(0x7f00000000c0)="89144c0129ea94f77ea66ed006e3bc58e261c99a", 0x14)
sysctl$net_inet6_ip6(&(0x7f0000000000)={0x4, 0x18, 0x29, 0x34}, 0x4, &(0x7f0000000140), 0x0, &(0x7f0000000180), 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
setitimer(0x0, &(0x7f0000000400), 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
open(0x0, 0x0, 0x2)
setsockopt$inet_opts(r3, 0x0, 0x1, 0x0, 0x0)
r4 = msgget$private(0x0, 0x0)
msgrcv(r4, 0x0, 0x1008, 0x0, 0x0)
msgctl$IPC_RMID(r4, 0x0)
fcntl$getown(r1, 0x5)
mmap(&(0x7f0000ec7000/0x1000)=nil, 0x1000, 0x0, 0x11, r0, 0xa9d)
open(&(0x7f0000000000)='./file0\x00', 0x8, 0x40)


getuid()
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x5200)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSETD(0xffffffffffffffff, 0x8004741b, 0x0)
pread(r0, &(0x7f00000009c0)="fc0a0d89e2d035f365a2d38139bbc66ae03e9cbfa9f70aee", 0x18, 0x0)
sysctl$hw(&(0x7f0000000500)={0x6, 0x1c}, 0x2, 0x0, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000580), 0x0)


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r0 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmat(r0, &(0x7f0000001000/0x3000)=nil, 0x0)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000000)={0x1})
r1 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000140), 0x1, 0x0)
r2 = dup2(r1, r1)
ioctl$WSKBDIO_GETMAP(r2, 0xc0105715, &(0x7f0000000000)={0x0, &(0x7f0000002780)})


setrlimit(0x8, &(0x7f00000003c0)={0x7, 0x9})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f00000000c0)={0x0, 0x1, 0x1, 0x820351a, "090e4de6d30aa692318c7e0002f9ffffff00"})
writev(r0, &(0x7f0000000100)=[{&(0x7f0000001340)="accd938ff3f8c1cb68a96ce24fa3215ae3f23f6ec074a99c3067fcae9884d924a039e67683007555d75474dc27b205b892df904dfcbdb8a85e40c0c760eecaf17dcdbcb6bfc9be16d49836aa3c8decfa226ceb49187a08a5fa5cb4b4f5aa097dfb66297a40fb214d6ecaf6e75e566cf32def06eeb9a5769734cc32cb87eb6c9a20075e63632be5cf312d1b489bd181198bba3e89ab290861e75b8f29d91a9a260fd315ed5ccf4b8c528e18044f50f23621ad6a438262684f2ea7df09eaf3d9efc1e0f93eaa878ddf8f8fbc72556b0ed74138815ec05db3431d0b6b969bf397135b0191dfcbddd954a220638f53e8700fb4be45eed98b313d27c147d41413bdc26b34f7ea207197d96aff5dba1b4667d734fbcb2c42ed7e2dff6bf921b7d9f81523a7a79971232735f27a35ff4a0be33259fa4c5745d7154a30450ef70223b8170a", 0x141}], 0x1)


sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
setsockopt$inet6_MRT6_ADD_MIF(0xffffffffffffffff, 0x29, 0x67, 0x0, 0x0)
r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000180), 0x1, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(r0, 0x80085762, &(0x7f0000000080)={0x1})
bind$unix(0xffffffffffffffff, &(0x7f0000000100)=@file={0x0, './bus\x00'}, 0x8)
msgctl$IPC_SET(0x0, 0x1, 0x0)
seteuid(0x0)
setsockopt(0xffffffffffffffff, 0x1000000000029, 0x26, &(0x7f0000000180), 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x31}, 0x4000000000000004, 0x0, 0x0, 0x0, 0x0)
sysctl$hw(&(0x7f0000000480)={0x6, 0x1b}, 0x2, &(0x7f00000004c0), 0x0, 0x0, 0x0)
sysctl$hw(&(0x7f0000000000)={0x6, 0x15}, 0x2, &(0x7f0000000200)="b1319386b7539d2263000e8c061dd6879145d16a92fc41d3269976816db0ce7d02a414da28b4e6d34c7cbd1b90ef96bfcdaad43b8a2ca966b6596dfc3fd25239b10d04a1553024565f984d9ce16cb0a1faad5de8cd2c049fac2d3aebd8bfcc00ce75142c15ed7176a3ce4e0c556cf542a075e88df0036425917032e9b2c803bfa9a51c52ea71337aa4b18254d6ccc83209b78e35ad612c9d3ae1262985eaa24e9d4909dc2e582cc1e248dd2a6ce285fd4440229489d66f6cac757d5a75f09e7b953e76ee18c058", &(0x7f00000001c0)=0xc7, &(0x7f0000000300), 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
socket(0x0, 0x0, 0x0)


open(&(0x7f0000000380)='./file0\x00', 0x80000000000206, 0x0)
setreuid(0xee00, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000000c0)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000000)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000080)=0xc)
chown(&(0x7f0000000100)='./file0\x00', 0x0, r1)
r2 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r3 = dup(r2)
faccessat(r3, &(0x7f0000000040)='./file0\x00', 0x2, 0x0)


getgroups(0x3, &(0x7f0000000080)=[0x0, 0x0, 0xffffffffffffffff])
r0 = socket(0x800000018, 0x3, 0x0)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
getsockname(r0, 0x0, &(0x7f0000000140))


ioctl$BIOCSETWF(0xffffffffffffff9c, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x0, 0x3}]})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0x0, 0x0, 0x0, 0x40}], 0x0, 0x0, 0x0, 0x0)
r1 = socket(0x800000018, 0x2, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmsg(r0, &(0x7f0000000280)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000300)=[{0x10}], 0x10}, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f0000000040)=0xfffffbfc)
writev(r0, &(0x7f0000000000)=[{0x0}], 0x1)
writev(r0, &(0x7f0000000280)=[{0x0}], 0x1)
close(r1)


r0 = socket(0x2, 0x2, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000180)=[{{r0}, 0xfffffffffffffffe, 0xc9, 0x1}], 0x0, 0x0, 0x0, 0x0)
select(0x0, 0x0, 0x0, &(0x7f0000000100)={0x3, 0xfffffffffffffffe}, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x7, 0x0, 0x80000001, 0x0)


r0 = socket(0x18, 0x3, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
r2 = socket(0x2, 0x3, 0x0)
getsockopt(r2, 0x0, 0x16, 0x0, 0x0)
recvmmsg(r2, &(0x7f00000001c0)={&(0x7f0000000180)={0x0, 0x0, &(0x7f00000000c0)=[{&(0x7f0000000240)=""/222, 0xde}], 0x1, &(0x7f0000000100)=""/64, 0x40}}, 0x10, 0x1801, &(0x7f0000000340)={0x2, 0x200})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140))
r3 = semget$private(0x0, 0x7, 0x3c0)
semop(r3, &(0x7f0000000200)=[{}, {0x1, 0x4, 0x1800}, {0x2, 0x8, 0x800}, {0x0, 0x1, 0x1000}, {0x0, 0x3}], 0x5)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x1}, {0x1c}, {0x8906}]})
socketpair$unix(0x1, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
setsockopt(r0, 0x1000000029, 0x27, 0x0, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x800, &(0x7f0000000000)=0x6, 0x4)
syz_emit_ethernet(0x4e, &(0x7f0000000140)=ANY=[@ANYBLOB="aaaaaaaaaaaa7fd67572210786dd6007558300183701fe8000000000000000000000000000aaff020000000000000000000000000001"])
sysctl$net_inet_ipip(&(0x7f0000000000)={0x4, 0x2, 0x4, 0x1}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000040)={0x6, 0xb}, 0x5, 0x0, 0x0, 0x0, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffc}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r4 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x1, &(0x7f0000000040), 0x4)
connect$unix(r4, &(0x7f0000000000), 0x10)
syz_emit_ethernet(0xba, &(0x7f0000000080)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaabb86dd600000000084000180000000000000000000000000000000ff0200"/51])
recvmsg(r0, &(0x7f0000000580)={0x0, 0x0, 0x0, 0x0, &(0x7f00000004c0)=""/159, 0x9f}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000140)=[{0x14}, {0x30}, {0x16}]})
write(r0, &(0x7f00000001c0)="d9537abde93d050cdd16b13f742a", 0xe)


syz_emit_ethernet(0x3e, &(0x7f00000001c0)={@broadcast, @broadcast, [], {@ipv6={0x86dd, {0x0, 0x6, "062500", 0x8, 0x0, 0x0, @ipv4={'\x00', '\xff\xff', @broadcast}, @loopback={0xfeffffff00000000}, {[], @udp={{0x3, 0x3, 0x8}}}}}}})


syz_emit_ethernet(0x46, &(0x7f0000000200)={@random="7bca7e58f7cd", @empty, [], {@ipv6={0x86dd, {0x0, 0x6, "9f2844", 0x10, 0x2b, 0x0, @remote={0xfe, 0x80, '\x00', 0x0}, @remote={0xfe, 0x80, '\x00', 0x0}, {[@fragment={0x2b, 0x0, 0x20}], @udp={{0x1, 0x3, 0x8}}}}}}})
clock_gettime(0x67f3248105b4e004, 0x0)
r0 = syz_open_pts()
r1 = msgget$private(0x0, 0x0)
msgsnd(0x0, 0x0, 0x401, 0x0)
msgsnd(0x0, 0x0, 0x14, 0x0)
socket$inet(0x2, 0x0, 0x0)
r2 = msgget$private(0x0, 0xfffffffffffffffd)
msgrcv(0x0, 0x0, 0x0, 0x0, 0x0)
msgsnd(r2, &(0x7f0000000040)={0x2}, 0x8, 0x0)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
mquery(&(0x7f0000ffd000/0x1000)=nil, 0xfbd510af000, 0x0, 0x0, 0xffffffffffffffff, 0x0)
setreuid(0x0, 0xee01)
r3 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmctl$IPC_SET(r3, 0x1, &(0x7f0000000000)={{0x0, 0x0, 0x0, 0x0, 0x140}, 0x0, 0x0, 0x0, 0xffffffffffffffff})
shmat(r3, &(0x7f0000001000/0x3000)=nil, 0x3000)
msgrcv(r1, &(0x7f0000000380)={0x0, ""/201}, 0xd1, 0x1, 0x2000)
msgsnd(r2, &(0x7f00000000c0)=ANY=[@ANYRES16, @ANYRES32, @ANYRES64=r1, @ANYRESHEX, @ANYRESDEC, @ANYRES16, @ANYRESHEX, @ANYRESHEX, @ANYRESOCT, @ANYRESHEX=r2], 0x298, 0x800)
msgrcv(r2, &(0x7f00000002c0), 0xa5, 0xfffffffffffffffc, 0x1800)
close(r0)
close(r0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000000), 0xc)
fcntl$lock(r0, 0x9, 0x0)
r4 = open(0x0, 0x0, 0x0)
getpid()
ktrace(0x0, 0x0, 0x0, 0x0)
utimensat(0xffffffffffffffff, 0x0, 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r4, 0x0)
utimensat(0xffffffffffffffff, 0x0, &(0x7f0000000100), 0x0)


r0 = socket(0x18, 0x2, 0x0)
close(r0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
getsockopt(r0, 0x29, 0x2e, 0x0, 0x0)


socket(0x0, 0x0, 0x0)
getsockname$inet(0xffffffffffffffff, 0x0, 0x0)
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x3a)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r1, &(0x7f0000000100)="00003226a4a9000064e7c803d2a423734333a4dd", 0x14)


openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_GETPARAMS(0xffffffffffffffff, 0x80105727, 0x0)
socket(0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
open$dir(&(0x7f0000000300)='.\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
r1 = kqueue()
poll(&(0x7f0000000000)=[{}, {r0}, {r1}], 0x3, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x42}, 0x6, 0x0, 0x0, 0x0, 0x0)


open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7949)
setreuid(0xee00, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000015c0)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000000)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000140)=0xc)
setegid(r1)
setgroups(0x0, 0x0)
r2 = getuid()
setreuid(0xee00, r2)
unveil(&(0x7f00000001c0)='./file0\x00', &(0x7f0000000200)='x\x00')


ktrace(0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
r2 = dup(r1)
recvmmsg(r2, &(0x7f0000000440)={&(0x7f00000000c0)={0x0, 0x0, &(0x7f0000000580)=[{0x0}, {0x0}, {&(0x7f0000000240)=""/90, 0x5a}], 0x3, 0x0}}, 0x10, 0x0, 0x0)
close(r2)
dup2(r0, r1)
writev(r1, &(0x7f0000000640)=[{&(0x7f0000000140)="90", 0x1}], 0x1)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{}, {0x3, 0x0, 0x0, 0x49}, {0x81, 0x0, 0x0, 0x2}]})
getdents(0xffffffffffffffff, 0x0, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1934, 0x0, 0x94e88e483d20a485)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x8020691f, 0x0)


getgroups(0x0, 0x0)
fcntl$setown(0xffffffffffffffff, 0x6, 0x0)
socket$inet(0x2, 0x0, 0x0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x1800, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
poll(&(0x7f0000000000), 0x0, 0x0)
recvmsg(0xffffffffffffffff, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
setreuid(0xee00, 0x0)
r0 = getuid()
sysctl$vm(&(0x7f0000000000)={0x2, 0x8}, 0x2, &(0x7f0000000040)="1b72", &(0x7f0000000100)=0x2, 0x0, 0x0)
setreuid(0xee00, r0)
shmget(0x3, 0x2000, 0x40, &(0x7f0000ffe000/0x2000)=nil)


ktrace(0x0, 0x0, 0x0, 0xffffffffffffffff)
socket(0x0, 0x0, 0x0)
getsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
ioctl$VNDIOCGET(r0, 0xc4104603, &(0x7f0000000000)={'./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0xffffffff})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000240)=[{0x5}, {0x40}, {0x8006}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])


r0 = getppid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0xffffffffffffffff}, 0x0, 0x0, r0})
pipe(&(0x7f0000000200)={<r1=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r1, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
fcntl$setown(r1, 0x6, 0x0)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000007000/0x3000)=nil, 0x3000, 0x0, 0x11, r0, 0x3)
ftruncate(r0, 0x8531)
writev(0xffffffffffffffff, &(0x7f00000026c0)=[{&(0x7f0000000400)="640493d78db6a9c1e335bb42b30c7b40a07b3baad98026cb156727aa65cfb18540954a46faf6cd689a437aff3f4961c4e46a834f6785f138abeced17229a790e349e6bd31df47a250b6311c17b41de694d02002d9c138fb5554471ad71a4e3b0c4a0f71fc4b1f3db02e683a852170340fa26d02f5dcb6c3772415d9b0c54258aba6ad66cd42dfd5163936af944020e200f6dad158fa90dfdd051d151c8c8cb6d711f408511a8c922ff7be9bf88fc6a18b3261c65ab46b32f89b7793b789d533f5dabd554659bcbb9e4082598016c9ffd443ad64a6c1384bebc4f0fa12ebee357f81c1bfbb7ff9c0bb5289f98184e590366ece692aac2a0f3fe55ae6072624ff0892d666934e9e7bb159ba7471e9ca862d48aa90c56e33b972e7ab5f15383b1e0bdc135ef14c4b638c9514366af346df10d2d11e3e82c7f98a731867165c536966e32790a098e86bc8c85d1d890537ee1a3b37a907cb151aa5b72801d9b213f04f59acc40bab4f2dfde876c2bc53ed02cd106d289a59310e0297a072b926369982acb409872a3a4325ed56f1d297bc8bbfb8f0a43f793ee9487a4492016350aa61cca26b86045d14a8f08e6f6d3e3be5520397612b66ebdf990efcf9ed9796836fa253dfa0389406ae25edb31abf6797596cf9b4a943972a4a19c43db1926c18bf15fc526127d1b04211fb4f4fe4c34dba511e8801a10008e54d343386c0c096641681899e65d2afea539fec10a2db4f07a06c7745c1005d0c2b1f020bd80e052df5a4969a40602d7b4350068968bae7ed03d05c9f0e7dd8940d1e37cfbf3370f5953261615197d350c60c2e3bdc186eff30d0700e608a4e08b2cac91f42275e3e6378a0747267335e017b5342a1662df7f3144a5c0e08008460631d2fb76c410c11c4dcc7f73fcab23a4794775f4284e02ad1ba71d64db4f1f4ced92b7a389fd596763283771b9faf89865c462f59e57a81cf8c3cbeffb268f00b6589ab79483f517583bc3a949c0df139721b6dcb9635dca559ac670c1b3ac3ffae886d18134df6d3b7078928ad5370c9687de2846d1f89f7455cf1f7bec56f3717cbdcab9a5fbe597f929e432ff093d92cb35d625bc8c5dcdc4df998db4b51f74775e5d6d119c505a2d0f27c9ead9e84af18c5d7e258cb6a4b57d28c5be27c3d72e277ae3a79bec39bdc88df392b2df6afcca55f79efb3fe6d0d8b50d7c8bbbc134450db20f1d5a773ce9cdc3b97b3274cb2e9c85496e9043e1eb83bda1b0960808b7dbf61fa0b420596976194a598a6ce1066867d13ed30035f8ff0ba3dcaa15df0cab8b96807cb82435a42067d4f1257de536842db0d3f7dfda891c146d79b600e6a2f994f2755cb278becfdaaefb2c7b976be36689c7a0feced48a723be73f29851f75e42e9d62c83d6aa220891c5c24634e8c7cc3eab033046727127a802dacbde8cf629c1f57d59ba0690af43ce944607c1fd9df72f74d67e7ddc2efd8dc6c459d0d1fe2ca57d14e20046f139050206dd8d203e0389aef6682cc6b861cc364184ee9708452dcb732992ce6dedbb8d57b5c5689b9836c54cdc91b4766f618d608d4bb380614d8cc2e03b3b3b5897ccb61f9fe2d16e5ced34cee9e856a6c52324c0eef64a4b7f9e8e7ed5a71d7b1fe9f94665ac75da67d114047ff5a1c3d0668d43d78c12565ea154f763418049e8dd3a1929b7fa4877c9e2cd984ab94818219a05b196b643adb3f064dbffd2b22ade017488178c5361a1c93f9c615e0e0cd28f25b7ca582d6942071cb7fae17b52eb41ead6e78914945802c19bac16c76ae14c7ed4be6e42713e8a4bd6220aadf458fa15b40777f94e223c596c7f80bab9584fcf4ff14f138adbbf7b1a7bdd686fa9249fe006aea38651e410fd4b1af0d79d7f1ee0cb2711ca81382f15804771da4a18d5f20e10ff9a7abd6ae8583d94f58769f3401526e517d963800c92485f9c24eac2d914895d4d9b866bbb769d22a00db29ce0b9a7d7112defb15d9776db55edf8fca337b1a496c7710acab8135aee0261a780ef6b39664469e33dab2398639d1becbdc74000b36c2ca5df2c0d3c5d3d3e054a2b8d91bc4656cf09300dd084cb0b625a587fba81cc6c2c3ef6f93342b65bc0e68222de6908492ac431f9f4dc1d3915a2cba79820c8c1f7c6e5c582d953b60a943eef44a6e7b244c808fb292f3944a4b1afbbadb06ed72c1d2cf9a60e02b319af032eddb475ae1947175f437262cefe05a89dc92367c8f8223e3a415b080b2bee22f084d00a289e42f5dcd0c31dc257d6bd09d214fad7aaa03d285a4ca618a5cc2bc0167ce424c40b879bfc294b9f2be0ee1c4669fe57d15c3b8fd626507ebb94d7313eda527d86a2bcaf9234a6eb4fcd2ecd218607961c7816094311a762d783ab7cef7009f103d938a5dee845b827001c87920ea3110b97b40a8525c41a57a03e389d9d864c57e10a849509135cdde81b89da8ee10540b76fe6c303a98bfa68a493ff59104b41c34c62092d3c0cc16d5c5c9abf7d0cc9206605ca6b69511091b512063985b03549573fbe60036cdfb28e77670e99b55a8f8151035ac93ef64b77f36951b0d3a31befef14741f874b313b66908f8da53a8a95255c16019876c85dd6070b2a8470f303b98d3c9ce2d203774794ecd2dbc43a69cd37c21f9c971634ff7b00af46adccaaeb1ca346bbdcad44151e38a94d91339c425554791adf2d3ff197221979625d2993ef7f4af06ec2438ab780ce737ac1bdbd873fa3b5cc0af43097b2be36bb9cbf87d39d3a7d54d5a49b176a3d74d95c06cd9b665248f84c27019f7b62232d9de01396aa0096f36c399b762913e207de7e3d24a2bbb04d879fe29b087ea262e82e4b3ca0fca62f222a592ab6ca1b1609e6a7500b8ed38db0d895c2df29604a64540e796787461ed7d1c5c562662b8f5146839cfbae18a6fb302033ad6558ce8a9d61d5de662b995ecb228535cddd02aa051321dadfd06dcd6409cf98d8a8697c7499f1695f173b427ff5f6cfdd224b66b89682d0e2978710e2bbfe7c9f2793cd2592ec7106c44e46c1d2bfe9d7cb53cac640f92f66506aefcc11c983e6c284a892dfc4b813771087baf9150eeb019ba0877afef77a66ee91b2c85ab1b95cc670ae9e80a4f20b8c8914c655828a68d6e8b509d479b5d04980a5bb17fb9ef17060f802f6e6f57e29d6587d6b8dc3438f592db639f718cc3bdaad6865d8a6aa94c47e1061cb8dfb8d7c54c168a29e8b1a78e1716ce413d429daaf09c924a7cde44eafc58fa5b3a5e3aa387a9465f024f7fe6ed9343d81dee65d106f635bbece1c99d5eb8ca0487c00c2851aaf24b2b6003e7150758f5a50943de2ba7b95710fa05f1c1e305dd7a14dba19feb94c9591d8cf724ef55aca7fb8e054763f7c80027b929666f6864db25a059859ca8831f9b7251e38eda5b00d0fc64a3b3460bd7ad733b9eac508a6a191a6465ca14729214d29cdfef5c6409a3f7e5db2044f836c049f5a14a78bea5c7a55e957a53d8d7d97203de65090319911c1788fc704d9382571d3d1bd2b35927d8d95b3f3b14930350ca34d577ff1d4ab69c7ef9f74f73590b8fd0d3574e7779e7f6564f9245c117c4272054015715a0671bcec7416d95a17da00b50e976168b9de75b673f6998119eb1c3b2bd1eebbf21aabc7e606991dc2e802058344d4854b1fe88688873db69c8ac70a9e4850960390a510231dc7159e3e89be0162258982be870d6135b0870986f66c19cf315552165fdccdd2acdff62cddeba67ca0e9578ab629d895a81f63c2262362a49ef4bd8a25dbf73fd100844496f40753d1496bdae8cf60f23db024ec56dbb594e9047ef5b005f579ff829dc1c3cf6844dd8bdcaf644481d171cec2bd25dce58a23617d5d11d7d44465214accb32a5767548fdfe3a428699ec03d02fbc2ccf1237ba07249af6f37ea83ddd8c7ec77f56ae7025c5662ecee8a8682d61823ec04bfebd6195147b016a28112821ad0f2aa32110dd31b38027f0e7fa042cce3e52ec467aaf95f998db202f819f201ee1322215018824a880755b94a2876e09e4c0cac01005ff8885e5f2f21c28b1aab38c62c33de0268521db2c198d19e7fafe69215465f6421b8503218f394d5a94c8601dd6514ff8a80f442ce07a4de65060229285b873667fa19859753c4b949ada2d3ab20afb732a4d4f0a9e5e13ef5a50c8361a465874e956464e201de1f30fa97398d3636ce88e479428b0bd8521010b92a22b4866c311593c101e3ed6169242c63334c7d6715a6dc50063e1c5658f590d0177464461a2ed8892719a770bcd687c597d51d46b89640b6610bc107a6b6d23e46052680aa18673", 0xc01}], 0x1)
syz_emit_ethernet(0x56, &(0x7f00000000c0)=ANY=[@ANYBLOB="89ffa23f3c252adb0070162e86dd6009000000200600030000000000000037f87c"])
socket(0x2, 0x2, 0x0)
r1 = socket(0x2, 0x400000000002, 0x0)
setsockopt(r1, 0x0, 0x21, &(0x7f0000000180), 0x0)
r2 = dup2(0xffffffffffffffff, 0xffffffffffffffff)
setsockopt$sock_int(r2, 0xffff, 0x800, &(0x7f0000000040)=0x20, 0x4)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x2, 0x2, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
r1 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
getdents(r1, 0x0, 0xfe9f)
socket$inet6(0x18, 0x4, 0x90)
openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000140), 0x20000, 0x0)
fcntl$getown(r1, 0x5)
geteuid()
setitimer(0x0, &(0x7f0000000000)={{0xffffffff}}, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
sysctl$kern(0x0, 0x0, 0x0, &(0x7f0000000080), 0x0, 0x0)
ioctl$WSDISPLAYIO_SBURNER(0xffffffffffffffff, 0x800c5751, 0x0)
r2 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
ioctl$VNDIOCGET(r2, 0xc4104603, &(0x7f0000000000)={'./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0, 0x0, 0xfffffffffffffffd})


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000100)=[{0x3d}, {0x1}, {0x8016}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x4e, &(0x7f0000000100)=ANY=[])


r0 = socket(0x18, 0x2, 0x0)
socket(0x6, 0x5, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
bind$unix(r0, 0x0, 0x4b)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendmsg(0xffffffffffffffff, 0x0, 0x40d)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x53e, 0x0)
sysctl$net_inet_ip(0xfffffffffffffffe, 0x5, 0x0, 0x0, 0x0, 0xfffffffffffffea8)
r1 = socket(0x20, 0x2, 0x0)
sysctl$hw(&(0x7f0000000040)={0x6, 0xe}, 0x2, &(0x7f0000000080)="7178e230c23632c7fe2cbf2b1b8dedccdf0e474f72234651102310ebc843ed5297eee515382b5b5f59926c877b10fc287077a26ff9531d13afa0fdc8497b70a9ad8acc84b50e6db7a1a222d79c89274b3837a417c34a0bc3becebc1eed5b641407d4b746e7de21c19957d366b3fb32159eec63848ed1af589555df0d4ca15db2e73d48ed4a3961939c44819e01caa94d5eb11a90f7189c3dcb45e280865a160198312e3652c705eca9ab00e98bd175c7", 0x0, 0x0, 0x0)
r2 = kqueue()
kevent(r2, &(0x7f0000000440)=[{{}, 0xfffffffffffffffa, 0x38, 0x2, 0x2000000000004, 0x4000800}, {{r0}, 0xfffffffffffffffc, 0x0, 0x8, 0xfffffffffffffffa, 0xb}, {{r1}, 0xfffffffffffffffd, 0x0, 0x2, 0x7fff, 0x1f}, {{r2}, 0xfffffffffffffffe, 0x8, 0x1, 0x3, 0x7}, {{r2}, 0xffffffffffffffff, 0x2, 0x1, 0x6, 0x784}, {{r1}, 0x0, 0x8, 0x20, 0x22f, 0x6}, {{r2}, 0xfffffffffffffffd, 0x12, 0x40000000, 0x0, 0x1}], 0x1000, &(0x7f0000000380), 0x4000006, 0x0)


r0 = socket(0x18, 0x2, 0x0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1023, &(0x7f0000000000)=0x3, 0x4)
munmap(&(0x7f0000002000/0x1000)=nil, 0x1000)
recvmmsg(r0, &(0x7f0000000640)={0x0}, 0xfffffffffffffe51, 0x0, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)


r0 = socket(0x11, 0x3, 0x0)
getsockname$inet(r0, 0x0, &(0x7f0000000040))


mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x287e)
open$dir(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
select(0x40, &(0x7f0000000000), &(0x7f0000000040)={0x7fffffff}, 0x0, 0x0)
select(0x40, &(0x7f0000000180), &(0x7f00000001c0)={0xff}, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000040)=[{0x20}, {0x81}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(&(0x7f00000002c0)='./file0\x00', 0x0, 0x40001220, 0x0)
ftruncate(r0, 0x8)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
sendmmsg(r0, &(0x7f0000000000)={0x0}, 0xfffffe32, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000001c0)=[{}, {}, {0x6}]})
r0 = socket$inet6(0x18, 0x3, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1021, &(0x7f0000001040), 0x4)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0286988, &(0x7f00000001c0))
r2 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000040), 0x8000, 0x0)
fcntl$lock(r2, 0x8, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
recvmsg(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r3 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r3, 0xc0106924, &(0x7f00000001c0))


open(&(0x7f0000000140)='./file0\x00', 0xf8e, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000240)={<r0=>0x0}, 0xc)
ktrace(&(0x7f0000000200)='./file1\x00', 0x0, 0x40000730, r0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
readv(0xffffffffffffffff, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, 0x0)
mknod(0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000002c0), 0xc)
r1 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(r1, 0x80085762, &(0x7f0000000400))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f00000001c0)=[{0x48}, {0x45}, {0x16}]})
writev(r0, &(0x7f0000000500)=[{&(0x7f0000000000)="af18a64591749e07ad1273f580a0", 0xe}], 0x1)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000440)={0x4, &(0x7f0000000400)=[{0x3ff, 0x1f, 0x0, 0x1}, {0x0, 0x7f, 0x4, 0x9af}, {0x5, 0x1, 0x20, 0x200}, {0x7, 0xf0, 0x20, 0x1}]})
msgsnd(0x0, &(0x7f0000000200)=ANY=[@ANYRES64=0x0, @ANYBLOB="a4621e3a2938aef62ea5dc78742e30da7eb765fa8b3740af25be9ada56369a5c30908bfbec9aac8a5bdd9a566fc512550bcfdafc57082aee8f49685ddf852e39e99379d860"], 0x401, 0x0)
write(0xffffffffffffffff, &(0x7f0000000080)="2300efe4855a00beaa9acc7808d0", 0xe)
r1 = socket(0x11, 0x3, 0x0)
sendto$unix(r1, &(0x7f00000000c0)="b10005010000009f0500070107000000331c13fecea70500fef96ecfc72fd3357ae30200004e3039d2d236acf20bf404be01000000f7c8cf5f882b297be1aa0504000051e2f0ad3ebbc257699a1f139b672f335c22db830c032bfa896443c32118210000720fd38bfb0000fd54c125191b1257aea8c500001602fbfe0c2300008abfba0900000008e37193f8343712050500b71dc000090005080000fca65361ba84913f0100"/177, 0xb1, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x1000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffc000/0x1000)=nil}], './file0\x00'})
r2 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r2, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0})
mmap(&(0x7f0000ffd000/0x2000)=nil, 0x2000, 0x4, 0x4010, r2, 0x1)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x462, 0x0)
writev(r3, &(0x7f0000000000), 0x0)
r4 = msgget$private(0x0, 0x208)
ioctl$VMM_IOC_INFO(r2, 0xc0185603, &(0x7f0000000300)={0x7b, 0x0, &(0x7f0000000280)=""/123})
ioctl$VMM_IOC_RUN(r2, 0xc0205602, &(0x7f0000000480)={0x1, 0x1, 0x81, 0x2, &(0x7f00000016c0)={{0x40, 0x40, 0x2, 0x7, 0x3f, 0x1ff, 0x800}, {[0x1, 0xff, 0xffffffffffff8000, 0xe000000000, 0x2, 0x9, 0x3, 0x1f4, 0x1, 0x6cf0, 0xe7, 0x800, 0xfffffffffffffffc, 0x0, 0x7f, 0x7ff, 0x2ac, 0x1000], [0xae, 0xfdfc, 0x35bf, 0x800, 0x3ff, 0x81, 0x3, 0x6, 0x623000000000000, 0x6], [0x7fffffffffffffff, 0x2, 0xfffffffffffffff8, 0x6, 0x10000, 0x1, 0x52c], [0x3, 0x0, 0xb20, 0x6, 0x2, 0x429b], [{0x2, 0x1, 0x1, 0x5}, {0x400, 0x4, 0x3ff, 0x7}, {0x200, 0x5, 0x9}, {0x8, 0x6, 0x1000, 0x6e}, {0x5, 0x4e9280ea, 0x6, 0x9}, {0x1, 0x0, 0x2, 0x6}, {0xfffa, 0x9d7, 0x2, 0x8000000000000000}, {0x9, 0x10001, 0x5b, 0x1}], {0x2, 0x70, 0x6ba, 0x100}, {0x2, 0x3, 0x2, 0x3}}}, 0x388, 0x81})
msgrcv(r4, 0x0, 0x0, 0x0, 0x0)
msgsnd(r4, &(0x7f0000000680)={0x3, "f7a8619f869a25f34420e4a75c92fd8ec1bae4c13e77be23fdf4b604bdd2438f1e889be0cbaef22d628beff1c7ffb6b1b0fecab04618b2ab5f5412ac6220b41dd5f473c9e933d7be137297790205d1db5b8ce197543d024540244b162eb840d98f05cdb607f30eba59aeba32817b9c48cbf7a281eaa52e5dc39d0f1dc41b08982da065351c8a3c281ba6de6f305d3c51122f4dff5a81712f8ccc488982caa94173dd7a145459592b4330eb19f38e4f3e5596619697ffa5cf2339585978460fef093658503c92e0b7484fb1b7011eade73834a999764e15a34aef86fe6f2b811a6e7424ad95e3ae176bf4039f98b5b832c22e8118358bf102148a842568be8c591a483e1d8c85be0eb1f0482569ea44688f105a2c01e96d95344dd87cda1aa1ab7f4dbf58f8ccac0c9086890b4d1be30ee5be863b11e970822b8327acfc60cdb00e6a428cb187b1d88233a6e7597fcf587e368a11ba01c44aedd6a4848ff7e7db7061cf8673f09645a4f5d0a1bfffdb0a1b7e9be95c962ca72eb66319a4ae3a623852d540ee0db54dfaa439f269d10122e8cd03b46f509816cbb580f8fa228f9b18e3a35728a1d25b8adb04d6cb72f9fc1b156433008b471871c9f90d66d736277a1471841e73b5b6c97449d0d0d6981da8af6f56640412ee800a475bda7c1c1ae779091a4ad81024d4b7fa354daa1ef2746fa158cae5af7be2c90f7da21d2388e7e81be076e4fc6a67c757b6539e5609369855c637e8f47d7d0172fb57b0bc4e8fec89e9d5ab4eb01890225d207ee93e3486338eced5fe22e1f8c2e2ce0047e7f2aa74d95b0789b35cdcceafb277e9e3332466582d970d0279e58de51e13dcc601e0d611ace0f4086ad17d01178d86a89554220efe321394395bfa8e74028ef992b75e67984ec38f321da82a195a60eb6103021b58a1b914a10d509c131defd6175c96ede8470fab89632e83fecbfeeb28fa7af7952be6137fd6f1328e0c4b8902e8cc6c270f45a0c62bfc7b890220011f1d955c294dd17953d9910debd96ec5bd0ee48ce1a12c2d955e7977b816ce2e493478649cbc079cf11c407dfff7eb92cfee83f6b22410f3accde3030cf15b781e487fb2df1cb31fa3bf20cffc628e603f8ee89159179f3ccd2fb9741a0497f48238860037ea4e999f9e8e9189a19857b35934c9717cec6a16e5975a9887320a1673c2a9654c099d3ee002366e3fd1042b7141f2ddeba5bff3c20af6d0637c6cd65b0cd7fb1a752856434e571cb83806f655ad1bdaaa3ea31bc26747aa571174b819f26f5008d1ee125acaa48be70b6e56a38fb4a2097a3b4847f5aa1ce2766d0da16d51eeac92fc812de7bd7be5a66f4cf780eee72c708a095078b0326a1767079ed2280254b774572945a029c3655953f45d8469de9acc1d8dcbfadeedfc5792c1c254dd79b8f8e31657739a48b2e712ec8ca0056e179177f5f30ceff9f407a834228481f93c81bca6db49da4219d68d90cd9e2695d27d94ed90f1a6947f370fafe54d956c061f47158a93f1361e7e6d8c53d1d8470f235099d4db3ba7940cc754b2feae21f8ce3425623977bb0f19f33153398d61b67165959755d4c448089c813778dbd26923c065be62a78db10c596045e18349ca8eb878a16ed505f66c8d2ae37bf0d9cc1f9bdda53547f13f031f2cf34d77dabc2ecbe0097d1c74ca3e92bcfcbd4bb00cf321d52d13bef8a8784de3b31a32e2b5fdceff2ffe4a028e3cc36f057e20fbc0aae603deecb3c164a91e66056a77c5e3ea92ff545efa89afc65d560fb62523f33bda6e29de18cec413b329afaa9bec24415b1199553f9833dae18ce421cbec819768692782193b82f6f074a04a94c79a03acb821644cfb4438f322ecf7ebf80f265625fa7cca145a3d45f33bc6efc2999b7ec18d43aabf6568b3e5f1ef8ddfe3003f9116d4d3273964fb4a4a6423be14a49c17296e2bd3342e6272e4335641815a31866594b7632588968512918f7a0f375279d9d9663e813444df607ccbd2e26a2d47092a106e5da9c6c1f355f8dc43e20433373dbd7afc5577e2d658998078fa0ecd1777bcee79f6afd4aedaa8f16fffb62cccfd773b657fd459bbae34a80b0b401c574bb683098491708ae0285e9edb6d4d4b8844c4351cc310d5567348b4f6445ca4df4506f8056aec0bb2c09f5f3b82cf1846c18f3bd1b5217b9d572ee9a66e43ce153be6087fd2627bcb4d3c778be7e0195aec30a28a95c29da29f4b3cf12df2584a28b154972c51a656d685c42db42220d969c76becff0748183fa7ba7cb1d534278b5ca777553f86f75da5715bf5339e06cdc72ee2981ecfcc5d5f3fd04a776004b144a9c1be30110bc929be1647c2770b29379a34377cd3a8fd959a564cdd0dca0f85bdeec097b039c4daf53304022345d2a57a24fd78c0a176f0ab7808666daef9cd94ef87ca1b64ba50f2dd90a622eb3c04f61678e74c8aac12152f65758e738a2847bedf193b3ef8ff37c484e28b2d51adef97af75ec7bb9f57d3ab81283937a84c85449b65e4d302f767fd64dd9c05410448ac166aa5762cc938011afe3d63e690789b5683bad800d2bb7a59e411918c922cbeed8e09bc70ee65d8ec6cdcd1b50dac1f09b2d14688335cef0815053d3d777b1ee3c08cc79cac19f9bde0038a72edb1e16aeb2e30564e8158e4b2b74c0be378803396051e3df3cd9c41db5b7414fbe1e5639696393f763ec896cdbadfff57c9de4ab28fc03d950143b423e421f8374df287342c26a97311918d921b78a74ee71d4b1873e19a7db35c41bd6f66c0c09766f47dde3608b95478f31d598822dfbf7626bfe72a53cab2463f53bda4f618d8d9b8a78dc05bc4967a93e4ef5b20c5c8c9d40950711da69650b8e0c9c9bae56b659a3cae457fdd7826ef050400d76d93f361f0ff8cda82a854cedc595afcd07f35f70405248d2cc4aaddead5a12a4e8dbe370176f568b196cd4fde9f89c214eb43c79b809f966ea53aad94e1191516d9dd2c6f1a05d1c79792b95619559cbdce29ef9efc86cd806446eb324c1c7e3009040914c0a11ee0a57585d60665ac83e09ea7e05ae8d5a6b24bade77a1e8e4d953e0f3dc08aecfe990dee1b6045e538da9ef8b01fe82c70604365b1ba8098b7074e7708c826a2514e2ee4d01ac1431ec43b05ba8e5e38a03d0686221a3bd9aeea2953e143b43a05be0bef03686dc2cefba277376c89b6452f2e6db006511e995c5096e3376729f139645b7095e7b70fb1d244e795ae2060e6e672ed3df4116d3542f194540d50376e0e9db9e490ea266600a5283c948c086ba2c6fd9019aa5e37fdaabfaed655d0231bf3b5138835962c8f41eaf0f6e8d4f9d4e602a3aa58cb8fd2929f472ff77a0a2652e6dc9955aa6b654301322d0d39c4fc70456b5a59e569e4848515295005917f4528a632bcf6cb5f97b3ecc173da6b0f59a76782f7c942de1cb1accbc74b7f9ea87ab92f2c2a5caee0e08448be49eda122f3589dbd6057be6f7577bc84367a1e23794c3d7e4aa8622995492e6523aa22e1ac1c26b4bb9ef7c11ac8bc52064c7ed1d1a63f37bb944dbfea2a732a68ce54c9a9d357c59cad365507079a1eb788e35251d20e986c8be394c319e0ea3b82b6f666e93d369e1d0ceab8c9202bd3bd3893d2440eb4a8c429c0cfda5cc6a4a0512be7321760a99c8cc09c42806f3e4e9b06749286228337f095387ffa9aec5ab700e310445e0e500088a26c0ead8f25a2b5bfcc5e9fc4211a0f30e4c70d6f90f92b56f7a3f6f99ddd56328e1cbfb59e93d8c9a0583ac91b50e899b9a24624a06f5a1ad9d0714aa502510eb945830a97baddf93139a7d30d1a69ad51432a6c762d339993de45f607790e0af6561045ec96f73c48f55b8b8a375d5bfc453cf87d55506f95ca6d775ea186ea46680f0aa93ff8e801b8ba955a46e81c03ae630451fa564bf0247cdcf9938b80751771c376bc7029efb890903b95e664ef241a7f0afe951cd27ac59fab02ec5ce9bc32286a778711382c4bfac912b77906f1d058da436abe1e1dadaed2181b0474145284b09f54845504e65c4c13b43d1608c58e6cac5b0cd5b12f8ed3ced3dcaf99fbc440b62796cac7440fd094e82e408c7f8465a89ff3a3ddcbc50712be534e34fe6b7e2ea31ff7d1da5d0a32f582d70a151b58558178d35aa662b6c61097600f826930a4147da30f669dc9f6ed5205a22a7cef7dbd81a39a0527b5afb9b0dd48bd3492d9141022f978a15b4a8a4027f39fd5425cec5296a2dac5701ebc62755c4ace67b28e069252b138c6e66573bbca327a1a02e7607af981fd63670894e7dae9e2a2fa751f7b2c4ed97bea840fc933516f6499afc8c7ad28e85e9b0b6e11735a948d2e77e14a40b56e01d4a8357b4eefec5b4c139337fce7eaf28a3d703559082cc7ac2500ed45d931fc92024587ae8d20d97a3937dc1aa18392911abbd734c05e71befe2d1b6e2dbb626891edbd89d58e7b472d10d3f155510cbb4db15e7c503ccd097ad3f268868ffec7e298b004e9aecc9a15e537587b66e9cacf4813464853b66eda240f05ddee635c0e80920afbdd20418734b1f10dc6ae52a94960a321402f953d79e0335e2641b4d09e87dab85e2dce300bc429f3167eb18d085ce7a92e692b269cbac17bf61668a87604bb70eb3dc1dd57d7139d663b27f51eb93ec4da24f80c18aa12dc9f17dd1469d80247601fe69418edb112565289e57a65d9893df66bc5f8ce2338a32fabe6f7a35e6bd7e9ed9e1daba7b8141f88beee9d8a59992c4424255be2923231daa6412e986d5a172df815356a12c2d57812775cf961f3ed49a428f07caadd19790609eff1a3cb5d16cbd097d0fdc8be5ec57ba9ffb23ff60258554d1fec2e73b43454b33ec52a7027c798f1a01768a819cc56ad02899a3e211e6afa1db4b78aae07e550e8c4b4f0016bafd52e94b1ad3738be2a8dcf4c9357d841fc0600ee6b9680f9d5e03796e8cf98e157abf8654900182ed38646268cd0ee27dd9e86fd597444641261f30173ea9409f7513432cc36f018858724b18f524f80673db1675d2889fab0e3bbb457e279afa2af4a823ec19de1a29546ea3923f6c70256627d90dcca1d6df5bedb9ad2ce5caba8e8a8b1ec1e5c53ee2cd39a77e430606ce08f0a74fc7aa8c004639c03b4af2edde005a93a7f8e1c187b00548c3d633184439ead5987dbbabe58d68d8d026bc61964f96814d7277d4a8630f9d4f816115d4f0f9d568440ba89ec0d7c19959052250adeb8b13469bdbb5b9cd6a528a4dedae203faaa5f53f53a2353147758fa75ab9147589569df1a11374673ee3e870e02da072a3f24f637f01c4a83b078ac4341670da9a947df66261cf4a063938b49ee3be72d2b98c823bd2502c0a2c6258058f560c828cc57aa6ac5a9605e1ea30fc54f978edab79213716454f31687018175045fb9f671eaade233eb49856c69d300d58c471f5015cc6af374a8692fbae1057ce12f2de526f5171417f6b17f792e179f0f016a522317c4d95aa577cfbb440dc31ba6ff93b5a97d9a395ba82c5eb1fb6cf7d2bd94479053789ae6e8951b2453daa61892c3edb533ec5f325385d08f0ecc84a55f1c7a85d912701e97e2a3cdd9716e985c4521cb04130851a03ee172e4673cb95ef263021b1562baceba6e1ef19dc78c0d21bc4d672e009cb89049772078aac06e9f49c0cdec945d4fced6580bcb9865efbadee5ea20124cec15b5cc3f7feac1de0e0b0e2b509d1c680c952b5146d3f0f98245dabd576323df0db0333510800ec"}, 0x1008, 0x800)
msgsnd(r4, &(0x7f0000000600)=ANY=[@ANYBLOB="020000000000c5c4cf3025e712843cfa4f43e74d304c2900c08f512848d8054aa694967d5cf132d9f4d1e74319a40fbf4177a874f43f82c5ad62e09a6810cc174aba44"], 0xb9, 0x0)
msgrcv(0x0, 0x0, 0x0, 0x2, 0x0)


pipe2(&(0x7f0000000380)={<r0=>0xffffffffffffffff}, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "0100012d29fb00"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x54}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0x2, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0x4)
sysctl$kern(&(0x7f0000000480)={0x1, 0x32}, 0x2, &(0x7f0000004e80)="e7a060d0", &(0x7f0000004f00)=0x4, &(0x7f0000004f40), 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, 0x0)
r1 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
writev(r1, &(0x7f0000000000)=[{&(0x7f00000005c0)="f4b533c408ae65ec81e1d08a3ea2700301aa3c44c4dffa2eb5be5bb2dd33000000000000afd5175b9213452ab5d84f6c9d0ce61d3b194791bfc27428a088311d09ec78df0fe8364e1e362a61e1b8b3fc61e568aa7c9df08f53ac77bb4312e6f79ee96148d019ee9bd31859a11c664b3e17c1898b694b1438417a4cdc427ccd5d6d17cf2b3a6de21a17fa545663239350d32db03bd4a409f4ad4355a7a068281b48a8c59e7f832d2d269edb94fd62cefff05d09137bc87c57a8e388b6966408a5c5abd1faaf18d58b729f15ad96d112f93c258f57dd2de572449cab12a1323d71a56bedbe1739c8d85bf38afb8aaa27c0c4d39eb8", 0xf4}, {&(0x7f0000000700)="a753506bdfab65e4da7a397b16da08a9beeeaa476a3171269b965fd027d2f46c0842aa1060348c554aa17c9be75639de34bf0676052f8093cd1bbd55d980cca2213b2a40b678d187adf77764e5e8390cdfc06165ad543c7299f4d2403527d5c0691dafbd74ebb6dd14bed9a9d2be0564228a9bf09c80ad96e13d90190566ba8f78cef018f217642b354743fe6da381c8ed01550f57f4c39471f63d3fee7873677285859561f596a1692ef9d30e7d3527f3cde60959ce39737072b77fca62db5f5d341e0496cd475e885950eb0f43b8fc112c2cc0d25f7d", 0xd7}], 0x2)
execve(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc1206949, &(0x7f0000000100))
r2 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(0xffffffffffffffff, 0x8020699f, &(0x7f00000001c0))
ioctl$FIONREAD(r2, 0x8040691a, &(0x7f00000001c0))


symlink(&(0x7f0000000280)='./file0/file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000001280)='./file0\x00')
open$dir(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)


mlock(&(0x7f000000f000/0x4000)=nil, 0x4000)


kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0xffffffffffffffff}], 0x0, 0x0, 0x0, 0x0)
socket(0x18, 0x2, 0x0)
syz_open_pts()
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
dup(r1)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
ioctl$VNDIOCGET(0xffffffffffffffff, 0xc4104603, 0x0)
dup(r0)
socket(0x18, 0x1, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x5cda)
r2 = open(&(0x7f0000000480)='./file0\x00', 0x1, 0x0)
r3 = getuid()
setreuid(0xee00, r3)
setreuid(0x0, r3)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
write(r2, &(0x7f0000000100)="8a522c6b8a8460561e290ca762e8d6c739d5dd7f0153b7a50498cb60ab818b16929d3bf742c57351df76ca9ec87e92fa9f010342ace3a6ffcf5c4b75c4c160f4acfe629a5717f5f5b7cad5c4e10a76103ea7945a70ea5a8999b18da379b691138c7d8a1529b81a7fb4540022f1324c3dda210f6f132101dfe0acc149685fdaca2fe92b8d4327e9872642c818370d60e800e0f8b2a66ead8ef0ddc9f0258f2275a9a0aefa8edd053e80a46946b0c0df080bb0d9c214c6a2393db966f0c0ace000", 0xc0)
sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000000)="9b1809ffffffffffffff7f473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6fd74c94d1b44", &(0x7f0000000040)=0x10011, 0x0, 0x0)


sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x2, 0x0, 0x1a}, 0x4, 0x0, 0x0, 0x0, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105727, &(0x7f0000000040)={&(0x7f0000000180)=[{}, {}, {}, {}], 0x4})
sysctl$kern(&(0x7f0000000040)={0x1, 0x31}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0xfffffffffffffda3)


mknod(&(0x7f00000002c0)='./file0\x00', 0x2000, 0x5200)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
poll(&(0x7f00000000c0)=[{r0, 0x6e}, {r0, 0x40}], 0x2, 0x0)
r1 = syz_open_pts()
ioctl$TIOCSETD(r1, 0x8004741b, &(0x7f00000006c0)=0x9)


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
setsockopt$inet_opts(r1, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
r2 = dup2(r1, r0)
r3 = socket(0x2, 0x1, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000180)=[{&(0x7f0000000000)="9da8e3e9ed", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
dup2(r2, r3)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$inet(r3, &(0x7f0000000000), 0x10)


r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$PCIOCREAD(r0, 0xc00c7007, &(0x7f0000000140))


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x35})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r1, &(0x7f0000002040)=[{&(0x7f0000000700)="6c0135", 0x3}, {&(0x7f0000001d00)="6156b89a6c15794f5426cf6a9a99b45b13564d6568f0610200e27d20182a400c7a9a8f0bf304294555b6b6cd19d32607b3754f4a88c97fe52899b92de96dbe32036c902694cbd8aaeda1b13395179e9aa22d5bb4ed975d8a585625759478115f4c4ea9fbe58382e00bad0ecc43529514d50fd81869975cce62c2e1a2520b63fd16166f35d4894abbed34c52f3e7e55be11106341ebcf1c65", 0x98}, {&(0x7f0000000900)="d09f6591cbc30693afd0b88a5a095acbc2a56dfe7b00631bbf4fdf760bdb5ce6c02523c5057fa75fcb6b520094262d6b81f8fb491e0d5f97f7e6e6fa34e3a87f4928bdcaba0d83c8a2f9b2297224ea89dd9aec6f5b8a9b09b2593bf5a6bf21f0983e", 0x62}, {&(0x7f0000002f80)="e0707225df5da0a3cde8f30024830d8e0a6a680844e59fcfa5dde0a596d8cb2901b8b60f269bdffed86a45026e99759cd124180e6c72cdd068718d18c40fc74364f4efef980c177c9d13853ee6bd3efb6bdd04795f2e00eef893ba9db6c641724b4320eb59db72e821e00eacae80ac14ec93e79465b5dfe980b08c3e219e10a322fc6a99d984aa3a17ac3eb99a7d90cd400081b6b1e9c2e49f51572faa4aea239b26ccce2cf371ea6bd4c4ec685cb5f1e1944576a86ba1fb802e8228e5f58b56265448b08e1f2d780a33751c191bc1a169ff48b7256c2993e0bc717933110bd6383d6022fb98dde74b5ab0ecd85d1c8019b3b8c07c14da5e8c27dea1464f6fc6dfbdd6c0f4b271cd8e8de994b9ed88cf29836e05544d9b93bb7fc1e2c2c2fddcddc82f884d45aeb0ce7407d2577be2fe2f8098613ab2ad60b5032a13dd9d63a2407efe3fadd1846988c3a299fddc1186d14064c4aeeee77394eb10e65516559f522378718fd87e5514c8fe55366b2154c898a888dcbbde73ca9e0126d6ee8c27af7b9eda998ffa359f377ea61147a6c3197247f363596ad3d3d0d9282758b09339d02616828993b0855085ed4748e48c50f7dab9668a7dca419149596579bb01408b8f2afa2b4bada88efbc57b7a096065fe6cb148eaed8f3becd5c7287c19d8b8d9341c416f2716c7a6ebaff889cf1ce69c7f4bf117fe4aefad2a50526a28df87ac628879076fe3b857ea830f45cb702afb7c25a06abe4d2a754d0fb77ff30877884fda5755e1c1c02700bade0be10b3c75c0166e477992584dbe308f2136ef82f72391136424d14b3fe1c4ff4cf8ee3d4a30577aa377438a795ce1efe0fef1f6436644224f92b45b87ec346a63a4600abb2bbc572ea82333f56d942d0294230c7ea8cf24bcbab7de10a06fbf4b8a5e4bc88a0b4d676062a62d5042b5d88b0ab80962dfff7ad508e6580ec0e565541c713e4a854483788c4440ed3cb388bb2fcf71e33495d9729eaa4f3df7d9118ea8942720f5dfda14cc5e35cd1c648b1e2c5dd0984536f225043b7aa56f45b94959d83990e6050353c7681fd596fae2ad6b43b26aac3e6302691eb49a92ac075b0973cc230bf41a02ef123a80cf799a9cf2c472ab0b45cde3c980a092662b79205d07c040744781e9c27e32a133cbe9e219489d97bcae4b2ec4ec0839978daba24fa23bb89fa6edc2b1f929e127136e13d7ab140a240aec7006d0740d15ce77b028746549bb91bde24e341d6aaef7684082283943780105de76983bc8c5101001c3a3a5dfe282d11d70ba08237d0c23eecbdc4a0738dcd1d0e92649c64d1fc75f5d4b1ccd10cee6ed69f4f63f63d63b04a73fe9b0d95ec3d98d55429524a7d5dc83c878f9bff0744c3c3dac7513e665383d243302b985da0fb404dddbde640a4f389fa4c3fb9ea1c5f9d515a2ccc8f64c832aff4f136f99b4d917ed0c1cdede6ffe621e6cd136bc2d43fb680dff0c68099c9503f61d3640c8ab7e0e00fc4a83fb01f03024f4f5325c1fb55568bae34451d9363cdc81e46e97b1686ae29abc9b06c8b5c7e989d3ad961e7216588c01b58b29fb05c432a615d17a09e3adf06cdfdf3dd2283aaa8fc9399b7b1d83c595c27f27b0c43fa110727fa37634d748bad8737cf7e94fb2c07b9737c4576b58e746ff84bbc736f246a7a368af9bcc22ca05122b160ca182db54145a62832ab52e1db855a1b160ef5f619b49f1e02baac67b9b0e626ba6070806e70c82c2d7c3273cf8e90270481e7baa2b2b4dde1b355f71c38405ae3f4f20e53db5e1542091b7f01507410184c37574a9ac52e3d588311c12bec275849496e726f8190529c0a49a0e3e6f455202aaa85bd892385fe7109b119dc4b5f9d6f74b0d27e04b2b648769af58d288765be71b37989a5ac5ae732d9e2a12c722e285383500d13e00dc7d6a064a7b207427edd517b5d30ca905935dbffff61e10b84ca904e4b58ab3278b09d1a3af7e337f777393b93c0e84ae3eb61f87e8f1388622fa35fdd51868a3329cf2bb1a8fa5fefdef3f8340feeff8048a96a2bf7466dce009599d9290c3e091ddddbe3f2031ac6e4c5ae5cf7099f92dde452dbaea6df2ad42b0cf665b8e221206fec348a6e3a70de77d7f474b88e8d328009c8ee253caef981ae633705c28594d3da0ce0de71b21f1cf64ffa8a23f58164d60240e1252aa62de9da39247acc335c352a8724ee35770747b3baf2ad195811dd7b768054277f7e59984084c464d49d936d1c66f7eb006001104bb29906ed7a14ffd968315fcad150cae3d278da5c0b1c82a62da917c39114deddd5bdfbaec686968e8f1aae41a18121de00cb66e9cf95403ec3c47f9155482f2b586fdaa860ac2d3d47329b1d493480fa5c968f3908f56c3c4731df5baab9d67b7b2253e3965a783031979ab940db29a998af0ad8fb492a883a60df2b28462813f8030bf701ab0e779cbc175a7e8d60352352ebbad06f6f1fa8b7d642ce526043ea448fb8583f5ad9759a422a41e41d7b3a36f2fd3acbb63c4d59a719300c9820093262d6b7953ac6f90c270364c31e7295ed15d106cee1285fe71b446abcf7dcf3c0e275e4426bd4e7a57e93e7cf73e1372510d8e6a2048ff8780eda3223277a03eacb710cddfe510169064edbce166244de18084dfe2508159f889a55a67f083c558a9b77f733daff67179a2322b53179e0079c92bd7aebaea9c5340f3ab4b7cc81d51803abd09fcc33392063c34ce1e1a0e675adfdd4a492f5a45e96d2da3d4533c9591bba11ee5a7f8552bba7cdc68932f8f4583e0c8f72b064fc249e1be449f1d4e6c8faab0b83cf3b6f79639ed34660c399113ca2e1af84335086124e5880174e4db34eee82a81ad779a2abb3f6de2d6e5ed419d855396579362285f40c6aba7fac5766b30caa1b5a3ca31935a45e124040a29b974de1cff0eca1b1ba280228bafa33d26d87f77abb36415122a0cf24e1525228ccca1f6873e67bec443c6fc46790d2af8029bc97719078956a3d3c897faf5b19beccc2b37813351bb8a0964a5f8cde403f162d4035b6743fdf93830888e6d0927e68c924de1ee1e6eda7de8348196a0e240b4fd629338d977b497c315662ab60b84797b733a931741f0f7ae88e608a9dc73ce5f2b075af61b6acb61f8fd475ae504f97723326778a75a37474e1cf7aeebc8baa20f2168d566c1cbfa0eba48c19297ed0036090a7989ef743211924453e79ea244aa18c85170c9aef0f4047332f8b35b47776723379273f292200f4a95c5a19ecd42eba114c3f8cab75937ae571eefd7d79368272db2d2db75a1951fba103340a092a7f7a11e6ed7aede39b6992f2163fddcd8998b1a51ce55edd4991bcf242545192c5da99577e6362b1a26c98ebdd7353b0a1ad10b5736faf60273485d0b7d8f9c6dce6538e5e8dac1b564bcf788efd488490736c1cc354758e6d394c77561e47c8c5de55c824dcef6c2ebb6e9e2c734ea05b56b5017f2447a2634099c1b9b09e061f6747e663dd92e0dc5eafa5eccc7e8d161c1e79f30230bb07dba9894fa6af1c66592cbbff937c01747ce5ca6b356f54f141420e38ae84b8ef505cb8e5a20933c463f48a70983996b72219e31cefc8a9485f6f5451deb8686bf1551de5b549da221a014fa06222265932a5dbdcca51d053482d30798e805c6c65808d72cca8d8aff611be639e7af32a8e9e92b2b83d59a081b86a7704b92ba6ea48259a31175760354ca8733a53ada1537a123ba7dd87b55bce95c238e30f19092f9585e8dd9053bad2c51385afe012c2dbd3c277c9e6689e907b907748964f38b9576ff9b88ec5f1961cdbe845c7e096061686ce822e34a2228227e934803ede4b984ac3e4ef28f0c0e24e0893e70d7d0f66847d38a14b3b2ff87cae2d1fcf1c8db5c32d02250145fbb20cfb8b279baa4a12526484bdfe4d36d49a82db857b82a0e11a315ea2e298bc8b8a69f4f7545008a440ace5b2654872f3f569269a1144e946c90f904e48ba061c1a615e8cde0a4194a567e86041ac9fa4b42553e19147ef3185fdbc685da9b439f02a6a34d8858eff5d762d4970488508f194b7af38590888c70d69b9eec79e53497645006ec6658dda11a7898ae96c8bc1a54b48470dbd840f0fc68799019b5b4137dc5de49af82d12ff2f50033ee8007c7d9ef1ebb3d60fddcb9239508a858df67e6ad3ffe23acf973db7421777a6a2f23ac58f599d88487ad8515808de09a0f59aaad6ecd7ba190bae74968c49b63451fd68cb2b835db73f7e341587aec98e7618b9836b8e851cb31ba1a2a86d52cf167279f850d811a0209a3d4a9c54055ba189eefa40ea10cd6458e1ba09979a3bafd21c5837fe11c264dea2f529ad2ed6d19849f2e8c0fad613478cb66a6724091e4b2c56588793813b44745eb97e688f382026c85e87124a66f542bdb99fb7fcd874d34985353e74a166a9f1ad64c305912b2b6ec1423c15788fa6b2194e2be021f1deb0f1b3d44b3313fbc9a38c290cede3cba47afcd98a4e50d019dfb64214d9c18448c375186ae9cbc7df4614ed4b9ef760c9808a5698c81b1542bb08e4fc82bfaa01be4807d4f0ae852777642019dd45d876e2c3bfc3f0486016b3d763cbd9d899b3e00c7d3001e94ed8515f0ec9b9f1ed7b8df767103ef964acb4281a59f5cebf08cc14e5f5166b9a77a43e8a3ea75c3a6a8e56eea86eb2c861fcbee63d44e60a2dc88c726b8149380aaaca89e83433c919c53754a64f9d8fee3049a5ab750eb8191f7676cdf3257c9e0c661921049962b800a299e5f5c002629bf053030203b5925b0f782c8bc5982546761b4256dd7c37a99de97f1187190f3a1068c86eb7c54cb3ba99052518ddff6c2f5a3651808ebccb435889a32b844d663330dd2231d55cec6a2e6f880ac93dc383f0323f33f66cce427475e117054827db2ddee05696992299131d9621d5041a596c3e72d7b018c813c5e1f698381000d3efe1cf189e2f749047bed3c6cff9184f22b4f3b6368e4ed839802f31394207395f8b3758f3c93f640734ebd122b52739a610d85092beeb06e47d32ddbdb1ff4ae18c696cdb93f8169f5980b01ac14ff66fdbc7efccf6f572a58e1a05efb444510edbd59cfef4ad12fe842483a3178cf9c81bb43e9213a7a49339d9a4d8150b5f253f938e91b3801252ca80230a9eb6a15c048cf10e068c6bccdc756d7fa1cce0b1cb147325b435cb504e5db48c32bc68f74a60b8baae0dae80bc4cb1cf4856802868817de6e7345ed493ce177a3dbbdec2690d590a23e3feb49554dac882dd8b70d8b7128d7ba1fcb715dc8b18a2bcfae0bf0a0bb557eb6eae8bad4ce3ee4246398e304188b1dcac6ef8f5e251db9c29e0ddd58abd191c5e2a961fa3e09fbf5a540c7687fefa036743134bf7008f66f484fe72a812844385fccf500123ddce1c3628c0826250f6e2dbe51bb7f525261f64bed241d3ce57b7da9f91e0d6cea8b3b249b461a3bd0372b2a76758de3113532ab8ddb3188cec04333d8d8930673fa753cdda63376e388d99a995642c7c43859ddc8bdde9101a7ebab17d4894f75dacde90fa971ed682fec74e25bd782a6c56d8e5fedd9ceafb8a71afdbeda2bc8c52047c4918c1ca24846c83e1b94fcbae7fb12d01f425e799de44da53c08a063e1ed1c47cc2fb55235c1b305afd000ef8f8cdd7a6234a37198b7bd8acf59a52c325b34f76cf5879128463d3948b4c401d9c8c8b1ebefe4405252612148a2fc80edd07131faae799833abda290e8e1b423af9c93307cf4cd3c77dd2", 0x1000}, {&(0x7f0000000000)="f286a84d365450931351d56a392f125053e372a5", 0x14}, {&(0x7f0000001b80)="09b3a74bcc4c28d5", 0x8}, {&(0x7f0000003f80)="9160123d76061585eaf66ae5661e9ef1dcb68a5ffeafff2953cf2e1d8a09ae56a62de6211d18c47e0f3491f0ea03e6790e5c82c2e7d1212652cfacc7743261bc7250207396761e126a9d84b718819d4edbd78a680b79e1459388cd1540571bc7b6b22be82fdc23a0dea1e96238ef53fb6547dc8aaeb3c796eb7be3628b9ce4b2ad3af54bb93a7b609ec98c4fd6e6f40b78a136ec58ac977c0f03880adda9eccffaab3d25acbd77ff269c9d99d292846bbca602408217d66179330b08563d3a2d036050e08f5a632a2d9b8f4399eb7eba6d146046c29decb9837d0127d596bbf3fa47843a5cdf896c9f39db9bf43040c135b43dd710a612c93cbd250efd513478460b88afa894267d6d3b5caa4df2f742ff9f3e6be94897da6794576524701994971c7ef2dfed4f359e8504ee8e93001e9ff61410a2465cfddedb29910228dfc73c71e88be80ce1905310216847c784c3b3be3d4491d25c99901497a2c4856b2989ff73d183474a1870befe42a2236851fa6240071ab8abe4e31179c2f53e634e70a12583be24974f6f85153aa453611c0c8a03b2294a3b234c4ae161d9265cced961b0df5d4515c76984e5e4e15f50b23d890b2bfe7b6c30a6409a5b74fe5a4a8c036b93cd9fb91ea84271269c52f8222916306f23edd3000f7b41cc4b3a4e5fa88a5c2d7678f0227a3782b1f8d6864b7fd8c2e76eff5021235dc3aaf4995d721d6aabaacc97373a107af76ec2c2520e400fbc749f8dd479d0cf5da54c4a73e41270d0391963e0cb8542be65f43fb2538d605085c22bc116b371c9aa02811aa86bd54a65a4b6983168180a3be1560b526de700f1949bb32d5d9f38f6a5c6281624c6fcb44aa657468ffafafdc0637748df145f718082709de89edc894c517a0f7ee0835e1fde37ba18740263c5dbb872aaf3640c55df4ae91f1c4d8a6d060fd46d2cfe9928475da6c0d001f9e2777437a663cabc593f8aa84f3799263cfc27076568723a08221b4bd190a3d24bc7f9bf91698e19479435a59a8ca4fdc38005a55d1e61eaaa9e4d71c99bca17b34045c700de76b4d90df4ff250341605ae4a680f6bdfe6ea5e6ff77bec1f6963c790519181faa2ec1a2f9b16d1b824dabfcef556e91ef4bce02b702146012f691ca05e0f873b793d6051c6448876a93fcaf32ad9b129aad644b9761508e0cbdda42424f5ca9ac5a0cb67fd5ef8d26078c16cf525df596a885bb192168ba4a86e99c0827b56331e6fce281bfdbe7601e6dd9f80e645d073e5fcfb80f23ed8d6a1c4c6f1a0593f126a47bdc15964106058ba5a3f5e3937e4d1936709df941849452f2c9c392aa70906c85e0edba5772c67f4ea0fe3719344d03a358fb664d793c4aa54e216aa56f8cf2b407ff5d4a529911af166a61b7ed4c3ddee3a52bb0c74950249d112f60d18b35e6c199bbaafda43d0f0e1e29b0bed4faeed45e840be722bfab97e30a01e8fdea1117a6b8581d6a9497c3921d84b377cd7bc1a1f3df421fa0a31f196c9f011339a202c77d552d5e30df29ad6a54a02d0bc728969bcb38626a82fab1855df909acb56dbbbe1338015737b460b9085379f144f08f4fe6fbe9c9df241061196a35365a34eaf0c65f97d15c811b98869c4a49ddae0601994d545d202d856fb5e3c96921e56b80ec978feb36f5daef50f995dc3cad442da07de75b97f810dce38413e8cc64ce3d32372a5b7b08ee898f5fbb37c4cb70e8b555322af7968013968ab4d07441409a43d6c68dc5b5cc02ed048e6a296f1f735fae1874c921c15dc6c4422c87c803c1783b344f60f90a3d2efafad2938d8269bda4df1bb247b482f36c1713859723951d31241fe7b3fc4b7c3bf11f055de8365b2b69328e5755fbab9dfb0b03205b2e98dc059fa5487c37ce89acb18613cc62486ce09e75a72a8be009793b00c74e9adc2b93471102f16e83cc9ef0ac2c2b7cb5aa757a5d51cd7f6336151beaf55eabd134a6e6b93593a151653837ed5d494a03bcf061d63d7a8e501973506642f68d6b2d490490cdc9980a624714008335f98caa71d22e8651849caa054b5c119dd154a80afd2ae95506728c0acf02eecd8887b821c764a2be51ba755b9db883a75748d3c20c2205fbdd1ad4ea848883642e27adf313fddfba60f314a80a463f056179643abd18bf0454dc13dd799d25c244460d8d2619238bb5aebe667fb38048d9dc84242dbcb17ecdb64170bb6b80fd710f597cc96d081da2ba082ea62605bb3388f43d1849f8b80ce8f8dadaefa84b0cf5e12c2a3db678dc0859bf927320cf765fedaaefad94d0da4ab50368105e4b5981feeb3edef40cf25780b6b00752e4839a1f3e0c3def6e5233db0490dc8ce93dedf0d44a05d2a132a3649eda3ab5da9e7762edd08b83a8cf2e7d253a78fdddc2c6ce97cbff41532692140ffd82bb4249328d01a9878e3f59d7159c493bec6184cd3d71e9213b4b6f70a7c26404ecde93e81e897e497f3b44ee04bf394cbe8540a49d31e33aa875b0c0e43e0c6af30350c5b7992a08d8cf0b5a88f0e5b88b6da6de61c0d1b6289be8d9effcaadd6b62f47b7169092f07ac1b1469f52b4b2369fd2e0fae1bc43cc415586b11e4fcac1b4148d5e7417e3a0a0ba64973581546781ae2a069073a0a557ed02b2462a2f26ac44729308c2347f4a7d7032b521ff58a8d1b3f095c376216c44762c889ff33f4688ba61dd2f1da40892e49a0bc0ef08940af0352cd6393eb1aef2fe707b138ba8119f3907993810a70bc4f1625ee0618230b58016277b50f89d8a7b92601c697b9ee5915a8cdf0b0d6f23005bc29ad38f7f3a7085efa550ea390ec31873f999733b874242b1eb5dc9dd5a8deb0c14d37e250d98060bbc30e8b5e6155267b424cf16deea1c1b003407f1308f93e8fa0ed90fb3789c7b05a5c6cb65fd34df7555dc14ee95eebbb0b2f0d75e3bffe98aaf4eaad9d39ceabed5967907007aeaff27bb2d0f11cd021bf1adfea43f09a6860db43ee3be9e520399bfe1f4e53b9981ba8f27f1c5e81c63f5e3292ada5c1876436b1d2d5504ab0affda2663d82dfd368cf67113f6dc50db630cd05b71d340afda503c2076f8bdb0f7dfb915defc7c1c9231234ec1b9bc51c9fd412ca09d7b0fd44af63461ece300c5e13c97be28a46be7d7811b648aef748905a3edc10c9854c2019b8da98f39ddae20857a9e10c0e0d31d21732b4464e69a7427f947d0d1428d785238cbe29febfe78002738319659cecaf443da90ce463923c09849bcd23590513bf05b9a0030329d29422057bfad1e9201efde01056efb4338152a90f3958d92affc0d28026067b9fb53847c3eb773edc09361b824de631476c50a9536d3432204f02d55679966fdac3284f5a8e6bb1a0fa8765f1bdf044f58610340b4405c1865340ee14aa612738218e58822cea59b2233bde7f515dca110b5b69cd023c65fe76c05b3101d2cb8839179c19e1253eedd8aa49eec5e61a234404b5050d3ae406b39ef356a61b9b70ff362dacc91ac18bd993d3411624b33516f5ce027fd14b98b71a127f100d0cd7bc06650ffd79b5acbfd6ac8acedd641151f765effd984de0d56aff18d939839671669b2f46ceaaf178b40652aa0830a4d01899721f7ec0f80745a021c2f3ec6ae4c2aa9c94bb13f46cd5ae8790b3da1c0399de2f2832c9ddc7265cdb6564934420b3dae8a9d18b929f23ebf03603a3504894e9091122598eb58a97d6455c7290a8c1762596b926a00ef0c38559b91682e3bc67defa7bfbadd8834f154c195cfa545a5d2b61a1c70f70b22ba920d96e9d1be18cf02d20d506505c098a6cabc45b81120a18bf7dee36f092917cf01bb1b5cc29b1047abc682d28c28f692860e4397298be4d20b52c63221220b995054d2d1ea4f8b51000cc93612add83f113c6197398d4a16a4f385dd825df203540da118fda3b6f0ca27c77b32f6288994bd8f56e41be27b820aa82ccf105c535790d95617a3d4c2c8a7e0d379682375e081bf920b2a2df309cf6d1ae50f39769534d2a47f48b30e9b4d5cbce04c84b6173bc31c6e4a5ed3d5905e0107c6daa440ca612d99ec1ee118156af1f5e4de9b01d83a5c4ccad4fa6fdd29dcb5f967b3ad7987b14448f9a7e9bcde6a5c791c789838caaa5e93761b0e49c1aaab894a505004dde4dfd6a97833accc7d0423352b09c7923d563a47767", 0xb96}], 0x7)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000080)={0x7ffffffb, 0x0, 0x80000005, 0xffffffff, "0100000063026d00000100000000000000777d00"})
writev(r0, &(0x7f0000002f40)=[{&(0x7f0000001e40)="8e78dbebae5d90546f15d52a70c0d6c01f58a61f32323c0794131b931fec61639d2f39a6047225d023e386c4556448c215cf2412d15d80dbf9f84b8741dd0b85594b84517605a7a7397ed4fb170e22d274b430934323f2f4fb5606ef5596615f1483c475b95ef23aea27e3b7a7c35f66ed518b4f97d9fa5945621a1173a9e1e34a3761486699739b5dd0f87a0d15ddb90c5f0b6935666ed373a8123f5a6167a180b5021fd0acff9d9731a5bd60e3ec94e2b7771d82937d6c7ff1b9422fdfbfa590964ca5b01b1ec5b60ef0bdd0be043b45cf8d18a5e672cff3c0aad2f41623f7ba3ba28c9b2419a3492b027f5169f1c7a49d496800dc3655536d25fd59b9cc0aa0d3bf78ad55f60a9ed41e1bb19b1c13d2d39a03a32123e8c58bbbd8603eaf87c9feff40795f8ef85e2c71683f9b14eefdc5e1d5c634c796cb911a58d83b20ec6e38ea7ffa40bfb8663e568765f8dd8d20143f82711d82d74b2d81b884ef21822818bd82a0920bb8c5b6e58e7aa743bc6b19728a785d2dd1b13ed5f5d3b903b3060c45f45802ae7c7b17cf2caa35d71ea86eda33fcff40bc22d55c804b946da28430427592d4178dd1694408c5d354f5ee480efdbcde222289063511a0f8dc2d674686be160347b81545049e76c44bd2df568eb1a2ca777e0c7df50943", 0x1dd}], 0x1)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd02)
open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
ioctl$VNDIOCSET(r0, 0x81946466, &(0x7f0000000040)={0x0, 0x0, 0x0})


mknod(&(0x7f0000000500)='./file0\x00', 0x1000, 0x0)
symlinkat(0x0, 0xffffffffffffff9c, &(0x7f0000000140)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/file0\x00')
open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = dup2(0xffffffffffffffff, r0)
ioctl$FIONREAD(r1, 0x8020699d, &(0x7f00000001c0))
syz_emit_ethernet(0x3e, &(0x7f0000000040)=ANY=[@ANYBLOB="aaaaaaaaaaaaffffffffffff86dd606aa63f00082b00000000000000000000bb0000000000000004"])


sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000007, 0x0, 0x0, 0x0, 0x3d)
socket$unix(0x1, 0x5, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x2, 0x0, 0x20}, 0x4, &(0x7f0000000140), &(0x7f00000006c0), 0x0, 0x0)
socket(0x18, 0x1, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000100)=ANY=[])
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000001540), &(0x7f0000001580)=0xc)
sendto$unix(0xffffffffffffffff, &(0x7f0000001640)="669ea98b245474aa4f5c8bde02accb608e07842cc4a15b8c8bebeb7f9abff3086921dec8ca022285c2a02513072f747613bf5d8c093ffa13deca94d605b0c043ac00b5e9bff371416134c94d750197f4f312983ec094285e57a0e734f13ceeb0e9cb9325834400f14f5b962ca601f312726d25e4afdc6cae9c6ce14b64b472a0e22b5a850870e31b68dfeada0e2af920f13afa68aea84b85b742bb6fe7e86df10ed8bb00af06ffafb821f539ddfb9d145be06b9e0b170ceadc89fcc2771b06590c8b4ead93c2f8ca6ab0c196cb9ad346f019276cfa2468e8277ddd5faaa29c5b3946132626e3285996501103fc842d3885b121eb8b1dc47aaf59f93b8b92ce2ec03b2f711f41f726cd7eb15750c0a1780fbc04b9922f997a4ecca29416fcb6c90a446c6e12f35abd790c5cbf04ad3a6bdd2443e20176490fda861739a33712b6f6151e880fb12db94fea7b458553ae5641355fdc24d7a40a0c5b8c8edfbeb6b6354bb98553767b2e3108adb7982edda9534823c38f2fad6224b6392ac9d731b560c8356a791ca35dd1ebf85aadb24bee0779da34a157a2f08e9367bb90ceb8cfc86fbc9a475aaff5145a2a8ff51fb588214ca19fcdeec8197d334addd4dbbec4bb0a17913b13243b4a11ad20b2630f4f7ab79d5599318f2862521d0bb9303d86de60660dfadc291ab5966b35818769717d1dfc7ad582b989ff34c9d09b7b160ee8c81ff503ddac27221c000d9c96b9e953e2718240010b9fb2523adf4694eeea47a778f2c190142b5fa0229eaf12a774e51bf7007dd0859af1200bdff2d9099351a91c5bbe37d94bd096470650a1efbfd17f71308c5b57e856188486280f0215f4eac084309881f36697398f3baa1e44beb9787d27ae0206191c8847768b3647ca3110eec5b1b46f0349ca40593d4e4574bd553fa97430822866c1fe0a6df5f7eebc639a271299032557e1ddbc27c3abe160ad7d2f6fb90696fc8f1ccbe4cf9f53b57225e4cddf18751360f1dec7ed3032e0efc66ea7c1c1a72c5d12d52504f17ad53da6c57c4cf7084c2d2b35b2512ec0d8c914b64562e05c7006531dee79784a391dac81d43172aaf56da7cb389072ef53672a0c0fc788b01fde7728a2f0c675a28f054539cc754f73e805791adbdf036f1372162a793ba93c00cc404b6ee0bbf8421de3a5291beb0323086320118f447394a87982b288a5cad1d2991ecfaffb00f0917183812566086fd546ca8811d1f9a452b3c912d0c0082c508bf17329892a288a71826c7c1276db8cf5b0f6136b0e1411650fc08ef51a836d786cf3445a924664f1d72d806ca3ac4752b9c4372d4e998771cc1ca55fb2e6c09c73def8f79be501f3aa9dea0f43b3274aa88d22e777790254913004ceae3d29c8107d4df9684b69e3110493aca0860ac520130b6b5509defe686cda8b7008befaee81199e7d73106f653b763b8600fb72d3769bc4ecd9eb9b4aeeaea6f5d242828afd4c7c06e5a23d314b119a5d3f91db37f26a7d13f72836d4622ec86d7ea136b6a0ba3f6a7d0d4e3f442fd215718154a9bcecfdb773189f9d2f284fb4d4be837a2efa576368988525a9d5a5a6d76e69520723916c8231927d223377a1e7b66a35b4d0b849eb65e3c7f57171e2a7db6332655845802aa55bf71c5e9c1e55cd66ff4348bd886ad3493e5b91253d21d30e672bc5c4ccc2d2c048c08498f029d55654ceb921edd2c920f3c0833d9941216abab89db26f180cb0f6b1b706978b29b281f05854f8653eb40800334e98ef97671755f10b4ea7f5dd14932dfa6e9e9178bb1802c7cfef31f1976b92326c4ec5e6be99637a4bfba280286cd172caa3cbdf4172ca503711beb87b6263c207e6b10970ba302d6ccd5349fff2f23df77014b7df296c40bbb9bda583cc6a7bf699b45488e56193097f3352b020a0a0d8688f70cd2106261b64f5edd110d91ebd5ca0f714ec1d4ebe8e75a84cae5af4841d001159187dc52172c86b5ef372a75fa661d04614b83fcbbb01905d039fae71afe727d1122151879d0e4b84130761c027b9ed788e88bb5230e355fbc7015bf610baf2dd1627c5b45d3456426e278c08c6709fde669fb2c640859333c3818c69e9cc13dde441c8dafa8a8e1c72c42de22481daa9955b66680acb4e7597f64ed10667035b5bb08452b398cc0b94ffd0a6b6f14a3cf24551605660fd0e3dcb44192cea38c5b790fe5f4dee4c1e137c1525f2ee746c645a41c939664fe87f31120030afc187beb39878d6b0654e939f92c3023535caea94c14999b825125e58db83b593a2d6a283df0619ee998d275b27a0d3db62e768e6f20006003fdb80b7cff1ffde2af56069233360cca6f35e49b83415f93703c49690bd4aa89ccd8cbcdf2601dc1871005423bcd90a41d48cd5b420f20491e3be10d8c59f3dac7aad63bc367fab331b72e6eb23eab509ffd06ca73365790cfa00a89348e6efb17875e5c874bf30a654af1ee99d2b234d89a5356433454dff793629c1f3805581ab7b0fe282af8a801ef153e4d13c5309aa06bc336fa514ce2f20207c472573e18d8f2df0fa7c0c4519f51433232a7754be917a64853a97a5f06269ff176cfde4fdd51a13a14fa56f64c4b853a708ee6f501ccec9019897c61778ca023f6db4c5f87b8d0e31557af04ecdb263b07b8b5091a491c529499b523c391ccfdaa89a17055f9926cb6bb21dd5b1b91e04bebf7ba13f42beb6a2094ee4258dd6f187aacc99e59b412849ccd860700451497aef2c693808b378db5665fdd3935da2f02cbb62752cad1daf62d2b3eae42b3dba8d0ebd54cb2018d676bf1f39c0a57a999202b75ac5f0c53376d22577c6c90510514da5eb1d456ed59076ba0deeeaa59fbc80502953a6131b6c1e119a87b05f01ccd994b3ddcf0a3b9d020fa6ada514b4924fd1ab62b3442a97f2e456e5d5d97c7bb54fb41c36b66b1bebabb9a7da73a9beaa183f1ee44e524e7589312a44f9a1fb1957c102fc3722294e05c02b215d72576307466ba0cf699bf222c8fd1cb6d83abf59f84c34c4229fb7e2931e13ba1178998d5ce8aaf213826009cc387c1cc8f4b82a8174bf19b9e01f8130f382586a0ea8fbd25243ee6664900d98bd06aca2ecf85f39785f435d7e97c3f5314deb01a0018bc1138b680c7d2c0781b299779189bae2be9ccc81f9124a3b9adce5323df9688e7424bc20f7006c20895df306463f86600112f906be6b7a96bb078314aead1fda61cb43474bee01770f30abc4afe0900d26dd739818ad50dd22734c509cae4786f76f134fb56fb974f592d190cabd91203e539518bd3692f38dea2dbbc82ef42b357c90f5e7116f9acaa2440697f7484f4da3522a9b51c7abb2f31dc54f22a79566a485acc2a2484058a4fc5db07c0169c37ada45e437cb124344454229b9c74e86e847b0d168b9acf7c6423d3166372b08c16de489b972c373cc4fe919adf18d4495160fbe2944e439849a8b46da5ec4c99c53db862d7b09d79afd736067e574ed48aab5be4ecc657659e2c9765131a51c873dd5045eba6623518c4111a88f197ce468383316e8fbf4b8e1a3f1b89aa8d132da5e2946e491ad5f4e7ab012d96cfc423a42d397ccea9b0d51fe03db1757e214441e9eb0ecd40a6cd29cf06b430639d3fb22fbea603ac24eb106ddaa6b9c511888e9c6758ef2359a0c6a23cd75ece52e18c98f905c09ba57f03e0d16d3df497beb66855ecc7c89b548e4c2184871a2f3b76d96ba63613363521f9128b75a7236aec14ac5b1eeedfeb9b1ef004eadcc77bf04ddd71c22f8181ec1bddf097b6abc9fb2cbbd137254d13aecfcdb7e7649ec0fbf33fe42a4eeb8c6f1e53304b39041cd38380d2e050f5ae10de2a9e1a530696cbd7779504407f450d5ae1fc0ddc0210ccc54753160848913f44210df8e8dc67951576468869ea06d5535c9d2118e3bfd2118539719ee77104cb199b46dfa142140c3ba537c4fb30bf067a97213e45c8698c16b5bc11ce9f9529e0466d86b6e7d509ccab76d87a3e46325aa4d01a20655f4354525fb17a780ee004639e0c00e387fe93295185028a053aaa92d76fedf35d7340a2717103d6b9eeb2cf034aa8cc3375487d5dbad3579f8c553256e4e168ccf1ae79785d580b4efced8afafca85856430033aa781bf8e846e81208c0061907c3b6fcaa90c26d4e7efb20b3ef8fbb186c33b58de1599d7d1e3442bcb1a9c16ab11faaaf4980c7d15148cc86b5715ed8fdb804d86aa0cb8928ae412a5200aaf50f4438b93894c367a8f756e47c608d2de350e222827c7c7455a793be74ffbab020ac928db53ee898702275717a6a44abc4a5d37d19d89025726105e7d094ef0a86d3fc32a174d276c574c1d5f5b8f1144e78ed1d11bfeb270a4d0aa8260a94381af5630dbbe13e5f50cb5c3c9e50b3e880a1d411ab3f84b72a79aee0a139b6d62c5cec343779ea35165831529b93921096f00f4c225613c6e7a0284d249eeab61e8405cdf477fd1696308595f424a3988ba7b215ad3868792993a7401c7526f4bdabff66f418e29b151e36d05bb182b1f0c97788401fc64e1fdc39254bae46137e58fb8e1935d7d99e92bb5cebed109ad65745cde58ea2c0f3ecbe73aa206d738558d6f3b8563bda792d891df1cdf0f8d28106584aba70ef45a98f1d90366ba9e9b488176f961b3c321d8f085d45fbbde014c6e169319df6eba07dbe75874dd83c97962472c7f96e50007b58ee7750b6821bd83ca1f6723d58c182ade81685b66ba18ee555b2ff3f480845e3849d9fa9ae517ddcf7b2c681bbfdec65205e32c57dca2373091c444fc0b5b07e81f35db301c194a13f7828f0afad797fa863fd2e375cac211ab1fb4db73e0dbef40c63f482ba0aee3832be3f714b109fc65973e6ecddf763901537587d8d21a350f00d2587d6fd74697e2e1d35b7f5a6be4f0ef5f2a33af89c26c9b500eeef83ce17d1bb6beba6a65170d5542ec0e9a04e44ba12494fdf9325e0cd9fae8ed7ab1c0276b073b8f34f0fa13e82c28b2649140ac5b4bfcf3ba71aa808ffea765d7e9d5b5ed7ddaf327960fd13396084da40a21eb0bccd9ac410622112ff3fa827332fd4604b80417000c54e41120c913add59996c6ffabad510c1755e2b24bfa5ff1e654479074dc41161c22744d6dbc6bae34f4dc04640ef330bd05b36b4216f66df74f9f77b51374d4b9941b6b0c6ad910360fdd496fdf4362611eefe7571837f3899784b971469cdd0f5d8f59ab1e633b998447ef9f5c7b6df66821efacd87aef07a420498c0ff92a314cc51c22c7dd2dd07c62982641b34ee53b34465770a913a506fa5e601ef6d5ebffdb155292c0412b8dde03f71a9ab2e5e877b94a456ddc4f1dd35ba0b658ccb8e69f73345dee42042f7345c732fe767e24c5390f95b81fa96ccc68e37578bc6e0e618cc139ba91cd36edd20d92d5bbf48c6a1cc2be1b63dc2b987141368a9af14e206dbee2bd1539d47e594673528570128ba4f95af2c9b5a923ee101031fcb3254a3c4b3cd46357a1f2e2d9f5533a78d0e696265d42400eefd3dd51d324864a9c736d721dfe4ee1d4d369f0175ba05350791b72c2f9c1864277fe07f2aa63c984f47bff81f7b95be5fd3ed1609cf70c035210dd0a56ac15931e2d067c2bf79a5f84e0ce732a80d333fbfcecc33f8bee7649d17829b0fc62acad7eb17155aad174452f1eee6b2f5277e96f29222fa1f49fda4ef62e8201086bd509a3a6fe1ddec9", 0xfe0, 0xc, 0x0, 0x0)
r0 = socket(0x2, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x0, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x8020697f, &(0x7f00000001c0))
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, 0x0)
ioctl$FIONREAD(r0, 0x8020699f, 0x0)
getsockopt$sock_cred(0xffffffffffffff9c, 0xffff, 0x1022, 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r2 = socket(0x18, 0x3, 0x3a)
setsockopt(r2, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r2, 0x29, 0x65, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, &(0x7f0000000140), 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000240)={0x4, 0x2, 0x0, 0x15}, 0x4, 0x0, 0x0, 0x0, 0x0)
symlink(&(0x7f0000000ac0)='./file0\x00', &(0x7f0000000e40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(0x0, &(0x7f0000000800)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/file0\x00')
r3 = socket(0x2, 0x2, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x1, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
setreuid(0xee00, 0x0)
r0 = getuid()
chown(&(0x7f0000000180)='./file0\x00', r0, 0x0)
r1 = getuid()
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000200)={0x0, 0x0, <r3=>0x0}, &(0x7f0000000240)=0xc)
setregid(0xffffffffffffffff, r3)
setreuid(0x0, r1)
chmod(&(0x7f0000000080)='./file0\x00', 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000c40)={0x3, &(0x7f00000001c0)=[{0x5c}, {0x24}, {0x6, 0x0, 0x0, 0xfffffffd}]})
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000080)="35b5c242413c1026089a59583cc3", 0xe}], 0x1)


pwritev(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f0000000040)='+KV', 0x3}], 0x1, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r0)
r1 = socket(0x11, 0x3, 0x0)
getpeername$unix(r1, 0x0, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x2c}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x9})
r2 = syz_open_pts()
close(r2)
syz_open_pts()
shmat(0x0, &(0x7f0000ffc000/0x4000)=nil, 0x0)
mlock(&(0x7f0000ffd000/0x1000)=nil, 0x1000)
shmget$private(0x0, 0x1000, 0x0, &(0x7f0000ffd000/0x1000)=nil)
munmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
munlock(&(0x7f0000ffb000/0x4000)=nil, 0x4000)


r0 = socket(0x18, 0x1, 0x0)
sendto$unix(r0, &(0x7f0000000180)="6dbab6e3cab8cb09975e59dd175bbe56fb6a39a00e245b8a0a456236824307f878812b70a0f227adecdece44ac238e9030d056dac5f908e3c65a8fd48a998c8a4efa8c89e48e2c68ecfad086aed14af1641bc1724d7236f1210e9865c168d91fde0f7e0d4fa80fdefbd870bade81", 0x6e, 0x400, &(0x7f0000000000)=@abs={0x1, 0x0, 0x2}, 0x8)
listen(r0, 0x0)
accept$unix(r0, 0x0, 0x0)
shutdown(r0, 0x2)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd02)
open(0x0, 0x0, 0x0)
pread(0xffffffffffffffff, 0x0, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffff9c, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0x8)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
r2 = socket$inet(0x2, 0x2, 0x0)
close(r2)
r3 = socket$inet(0x2, 0x3, 0x0)
dup2(r1, r3)
ftruncate(0xffffffffffffffff, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r4 = socket(0x18, 0x3, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r4, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r5 = socket(0x1, 0x1, 0x0)
close(r5)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r6 = socket(0x18, 0x1, 0x0)
connect$unix(r5, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
shutdown(r6, 0x1)


semctl$IPC_SET(0xffffffffffffffff, 0x0, 0x1, &(0x7f0000000000)={{0x1fe}, 0x0, 0x0, 0x1})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x1ff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x1603519, "1a0001ad090201070000200007791dcebf00"})
writev(0xffffffffffffffff, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, &(0x7f0000000040))
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
msync(&(0x7f0000ffc000/0x2000)=nil, 0x2000, 0x3)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000100)='./file0\x00', 0x2000, 0x0)
ktrace(&(0x7f0000000180)='./file0\x00', 0x0, 0x0, 0x0)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xffffffffffffffff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x1, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
sendmmsg(r1, &(0x7f0000003cc0)={0x0}, 0x10, 0x0)


open(0x0, 0x0, 0x0)
getpid()
ktrace(0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x6e, &(0x7f0000000080)=ANY=[@ANYBLOB="ffffffff070000003817463486dd6000010000383a00fe8000000000000000000000000000bbff02000000000000000000000000000101009078000000006000000000002c00fe8000000000000000000000000000aa"])
r0 = socket(0x1, 0x5, 0x0)
close(r0)
socket(0x800000018, 0x2, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETAW(r1, 0x802c7415, &(0x7f0000000000)={0x29f57365, 0x0, 0x1f, 0xffffffff, "8b0300aa010000787d902b56d864d3c3a3f4d3c9", 0x0, 0x8})
writev(r0, &(0x7f0000000500)=[{&(0x7f00000048c0)="8efe927e139219019b33b40e291a6368427dbff01c7cf9e8ccc4ade5720223e7a6662a0f568427379d9428bc1da8fd20369e0ca8bb91335d364af186d9c5531b9cba018029760cfc5fe5d17bdc790f9925d9cdc96a5caedd8e6eae50d348188460bcc36dd2f6edda2619e63f35a27b1ee4e51f4de695b6a10d863b7bd4e1dbbaa8f26bcde8979f6bba0aa3a8f44ee0fd922a626b5147a7af25e431cf9939d7956aac37ea115181cb846522ada8aa188bec09c17898b1b82042b227be753ff8957a9a29ad685590d48405d84316994db071ed29f21521e5184fcb680dc0db4986739cf9c3c481bb6ea8a7438498d036e6927fdaf18accbf38de8aa188f8ad40261d2a02d88dc9efcab74bd4a77bfbeb013faef596e2895d5583b471e4e4526c5d4e436148a971e5bf1f1c37eb1ae5d542cfb0892b663a208eab4098251262b1f1713a0ae5406d57712c454655a5bcc1bb90e8598723fd410ed54b09212b790b1fb656ae84e53eb922fde9d93c5a3fd97994934f8cb5d7fda2c04b022b668f3aa04850f5a80e68103a8867317c201fa50f0545deb8d8ea0ae16a6884d1060a4e65dfa6fa5f7fffa77593b38e1efd6cac95bf8070243cc1b79e49963de3f2bf4f76768f2d384979d160bf75370f6742feb16efda16e2179310a5b504a2d57c6cd26851677755771a1a250ffd3ae98d60bc18a042d65c74dfb6c1e9f57662faa92126eb67be86773a736b70d176b31f8802de3dcc492727554cd7d7a6cd6b4d1b5daf6291a101b632ef7672a075a244a460b1445647979f1832e72551752eed8048cfafbc9a574613ae6f62efded1ab90fd37d28e6b8506f9f945db79385cee0ad50b922676c193cffdc418a59333b8ee24d9d7547ca00df2786e6aacf4c3e7e267fe0bea3a611dd0e9a36e90720d463af713f54f8b13a42c647847aee0a41743b42c907c5072ee5e769c63ce3614a16a3743eac6f64bb2edc35e44204616616f00d5283ee431a2a9cdeb830d572866dde345c96dd13cd001bdfe6fbf00bf043fda6a3daca8a06c1e4eb15fff83f7b38c35f51e781c8bdff20c78681ce6ce76f6b756dc2ef3fb7481980d1414c001147367f1b302f13992093e9e8decb8daa298efac80c892de7034ad8d355be8270018127c7201c3032007b7dc2cf38c7356dd1b9a80d0828fa345f2bd5b5d9b02324bf970bd5ed5472349a197097b6f69b5adf2dfe7f007481", 0x365}], 0x1)


sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x1}, 0x4, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f00000001c0)=[{}, {0x1c}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
shmctl$IPC_SET(0x0, 0x1, &(0x7f0000000000)={{0x0, 0xffffffffffffffff, 0xffffffffffffffff}})
r1 = open$dir(&(0x7f0000000100)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000140)='./file1\x00', r1, &(0x7f0000000d80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
r2 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
mkdirat(r2, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
symlinkat(&(0x7f0000000040)='./file0\x00', r2, &(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
open(&(0x7f0000000480)='./file0\x00', 0x200, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r3 = socket(0x1, 0x2, 0x0)
ioctl$KDGETLED(0xffffffffffffffff, 0x40044b41, 0x0)
ioctl$FIONREAD(r3, 0xc0106924, &(0x7f00000001c0))
r4 = kqueue()
kevent(r4, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r5 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r5, 0xc0206921, &(0x7f00000001c0))
socket(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
fcntl$dupfd(0xffffffffffffffff, 0x3, 0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
r6 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r6, 0x8020690e, &(0x7f00000001c0))


mkdirat(0xffffffffffffffff, 0x0, 0x0)
r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000280)="b1000501600000000000000007000000331c13fecea10500fef96ecfc72fd3357ae320b37b673039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa5b236deb51e2f0ac3ebbc2576b9a5f139b672f4d335d223e7d026ba8af630037002102000000720fd38bfbb770c1f5a872c881ea6e69e0bb76d907c400000200361b1257aea8c500002002fb00000000008ad20300000000ec1d89e000040781e4b2fff040ff00"/177, 0xb1, 0x0, 0x0, 0x0)


mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x2000, 0x2d87)
r0 = open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
poll(&(0x7f00000000c0)=[{r0, 0x6e}], 0x1, 0x0)
r1 = kqueue()
kevent(r1, 0x0, 0x0, 0x0, 0xffff, 0x0)
close(r0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000080)=[{0x1}, {0x54, 0x0, 0x3}, {0x40e}]})
syz_emit_ethernet(0x138, &(0x7f0000000400)=ANY=[])


setitimer(0x1, &(0x7f0000000280)={{0x2, 0x4}, {0x20, 0x9}}, &(0x7f00000002c0))
r0 = getuid()
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000140)={{0x1, r0, 0xffffffffffffffff, 0x0, 0xffffffffffffffff, 0x7, 0x3ff}, 0x0, 0x6, 0x100000001})
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x101}})
r1 = socket(0x1, 0x1, 0x0)
r2 = socket(0x18, 0x1, 0x0)
setsockopt(r2, 0x1000000029, 0x37, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
r3 = msgget$private(0x0, 0x100)
msgrcv(r3, 0x0, 0x0, 0x0, 0x1400)
msgsnd(r3, &(0x7f0000001540)=ANY=[@ANYBLOB="02000000000040006d1d5fcb28d9fc2efd0008000000000000b8f707aff57432a505995139959fe8249fcfeb969ee0027faa"], 0x32, 0x0)
msgrcv(r3, &(0x7f00000001c0)={0x0, ""/14}, 0x16, 0x3, 0x800)
r4 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
dup2(r4, r1)
r5 = getuid()
fchown(r4, r5, 0xffffffffffffffff)
r6 = getuid()
getgroups(0x7, &(0x7f0000000080)=[0xffffffffffffffff, 0x0, 0xffffffffffffffff, <r7=>0x0, 0x0, 0xffffffffffffffff, 0x0])
getegid()
fchown(r1, r5, r7)
r8 = getgid()
r9 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r10 = getuid()
fchown(r9, r10, 0xffffffffffffffff)
seteuid(r10)
r11 = getgid()
semctl$IPC_SET(0xffffffffffffffff, 0x0, 0x1, &(0x7f0000000200)={{0x0, r6, r8, r10, r11, 0x30, 0x3}, 0x2, 0x441f, 0x10000})
dup2(r2, r1)
connect$unix(r1, &(0x7f0000000000)=@abs={0x1, 0x0, 0x3}, 0x8)
ioctl$FIONBIO(r2, 0x8004667e, &(0x7f0000000080)=0x8001)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000240)=[{0x20}, {0x25}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000040)=ANY=[])


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
r2 = dup2(r0, r1)
readv(r2, &(0x7f0000000080)=[{&(0x7f00000001c0)=""/199, 0xc7}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
r1 = openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, &(0x7f0000000480)="9b0209c3218b07fcfe4189c99e805e6e84d356960798a692992117d6728436ba1bd87f42e3303eac3846528d050712f838130efce33f523ba44765f5f6915b2227390ed95bd9dc6d4dc7f149d4d6d06a3f23616e773302d9cae75e39a5a11e32e0e6ebd635450b2eba540af7f2aa5dbfbdd900a0dad2b74f50acd76b5c567049ef436dbea0d7562f52955af8d4ab84c513252ddd139b5f5cd5c2bd02adc7f1fe850c00000000000000062ab475cca257352828a76e5334be562995e894238b96ca5d4d3e670fa0cc791dfc4415030910fa64eac9b4e8aa9bef19525cb6f7e8570be65bb7ad3fe963cb9a8bd949ee334db1ccf73db06b5947b3e88aa810f8ed7cca10ff0d0000000000001345daa49507756f49775275ca390b94e85d5a95b82000b9429c25483a9275d0da3b561c6adc3c141f26040000006b436218bdbdc9ac0a623855e941dc1872fcb045e0d9df1ecc6357ee21e2b0802cb60edd0300723235f06715e7eecc3e0760c70e1dd7873e27142bbae1a7e44de453a073fe3426f334b80f043ba9136d57c799353d46dd81439b111a511a288bee5dfb2e353e3bb073e3342273216b07e49ca4df0fd2dbe9a8eb377010ee678aad0bd8c7fb7d82693a096344671843a1f2082612b2ff237c6e505ff5f5ba932954d73c630fd2791f833a1da5af0704f687e196f4f7859e071fc98111cc9024f790ce16ceaa427d0104e39789d91000"/528, &(0x7f0000000a40)=0x210, 0x0, 0x0)
close(0xffffffffffffffff)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)
ioctl$WSMUXIO_ADD_DEVICE(r1, 0x80085761, &(0x7f0000000100))
sysctl$kern(&(0x7f0000000000)={0x1, 0x2a}, 0x2, 0x0, 0x0, &(0x7f0000000200), 0x0)
r2 = socket$inet(0x2, 0x3, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x200100000001d, &(0x7f0000000000), 0x4)
syz_emit_ethernet(0x62, &(0x7f00000007c0)=ANY=[@ANYBLOB="ffffffffffff00000000000086dd600abad7002c0000000000000000638000000000000000000000000000000000d57aa79c6b632500fe010000000000030000000093b0c83e5be3e6bf6a3584876740e1994e841dd217d6e6e370f4780800000085da6022f18a0aa86331bc467f0be1fe2c790d3fca0615dab7fe8d0e2e65c1c4ffd06c764ead89a2afedf1515bd0fc20454a128c32efed5a8501bbbb42fd5f15fd7796632e7610d911a7b97f339e58accd2069ee3f35ef9e72e8de86f5ef2cdecd03075b629eb192f83177fed2d345b82b18027e918d0c819a3b01", @ANYRES32=0x41424344, @ANYRES32=0x41424344, @ANYBLOB="d4bc4bac90000000000000000020"])
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000280)={<r3=>0x0}, &(0x7f0000000440)=0xffffffffffffff1d)
r4 = semget$private(0x0, 0x7, 0x3c0)
r5 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r5, 0x0, 0x21, &(0x7f0000000000), 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000240)={<r6=>0x0, <r7=>0x0, <r8=>0x0}, &(0x7f0000000580)=0xc)
semctl$SETALL(r4, 0x0, 0x9, &(0x7f00000002c0)=[0x3, 0xfff])
r9 = getuid()
setreuid(0xee00, r9)
getpgid(r3)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000001c0)={{0x5, 0x0, 0x0, r9, 0x0, 0x30, 0x6d}, 0x0, 0x0, 0x0, 0x0, 0x1ffe00000000, 0xb, 0x6, 0x5})
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000080), 0x0)
getuid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000740)={{0x1, 0x0, r8, r7, r8, 0x2, 0x40}, 0x762, 0x7, r6, r6, 0x5, 0x3, 0x1f15, 0x3})
setreuid(0xee00, r7)
semctl$GETALL(r4, 0x0, 0x6, &(0x7f0000000040)=""/1)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x2, &(0x7f0000000180)=[{0x401, 0x81, 0x8, 0x1f}, {0x9, 0x8, 0x9, 0x9}]})
syz_emit_ethernet(0xe, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x5900)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000400)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000540)={0x37c, 0x7f, 0x3ff, 0x1000009, "00df00003f00000000000000080000006d2b00"})
writev(r0, &(0x7f0000000100)=[{&(0x7f0000000800)="590e495b1ad2a14423c0fe6a9ba42f89606f8f5773e9ed4805627b1953e8526d359eb2d55c75c5eecce22f844fad5fcbda0e438594cd635b99159ba469291f4a807055e8cb61b875b2ff967153d9e416a79321aa4587cc1a8d8a520b57552c61a43a412d7a084aa4d72d74db60e90ff741c303bf276a00cb7754", 0x7a}, {&(0x7f00000009c0)="00681c735ebcdf1ddeb0dbde935a3cf2bafc27af3e17379e0c6f59175bbdf7db589843ec39f45c9e97fcc284b3e7f351b6095346d655708a92e51d9899c26bf2e2e9e2f53ed7c2110923ce8d6a14c8d7d3a5365a48a6d32aedba526af9decda1f4334ada2453510c65da4b3d74237650f09229a75edf77cc02b39529f32b0e968ed8c4bfc420bda1d74821ccaf18e9108568f3dbf6dd9b16cfa1828461d3d94b9d357cc6a2d548278c0ae8c2b3be444fca9e989e4ce02e161f43d4f87e09222ca614698db720e3b463d4de47f303d024413eb4b81b41036b2c596227426b434e9f31154e31b73317439b8d9240244835cc2721abe86ab0e0dd3d4c73d4c00cf68c9afc905765609fc35a380a6e9d8e4d10e4d12376994955304127d26ba79d36138474a1cc28e071c6735125c516d169017f5f3cee60f73c2d019a830b16260fcf8073dc905fcb352a92d336b71bf1a0c8d406b10a9f48ff7d061eb1ec56eb5344706936529522159916a6c934b263bccfa618797586b077bfe5e0154be5b0decca6053828b9d8c9aaece80cecd1a9693a05709047b1c547f01a5facd7ca9218b0a6f5d93b059642249ad1795e38413ac6bcf56d7596b59e61f2cb6268122b2fa16b5cd3aea17c3f511846bb9d64961224762f5d56dca3e3d78ec8810f756a809f9a4dfe133513a5b04f196192de1072d700a0a5a6a5a1205f48fe09ac940c9aa301c6d38145df76cea91f7bf7246d6bc167a93f15eb33c3fb5d6fd3afd8c6ae979055260c42fa01cae241be43be81814dba18954c12b0ac8c54fea3311d6bfecba5baa16a686842e1042e0f5e6c0035071043769cb7c9cc00a2e783fc1fb9f208e448656eeabc27af59e5b20b2948a5506b20a74e89342f85f32e01862b8ebb551293526ed2254773816a93fd3f3766e820ecdc8e98436baec88481cf58c48c521cfaaf6709c3cf6abfa7cac19fa165bee6013d800e3084fc7704ca582bd9356d11961ac1c6a31a79ac2f3f86df631bc1ca12bab2256d7ef3e64239e6acfb25ebe836f47e137d7a2bf85a7799f985f0e9937543dbaf4be34632d37b346b29ada854c6437aeecc2d2a480bb2c7f1e3d7393b9f12b4b05cfeb9a2a29e85195014802bf56160f89f9697d9a463d77ffc07ed4b4870670fad275b2c098329870d20b26209494d8029f34819e63ec879533726ed50a30b1a48457f2d7703cf6b628cd004a19adcfc578c2638ac55208a6cc9d6d908beffb83fec68d72b505aa85f5c2ac40decd02ffbfaa2d618f31758948f3bb44f81b2660e53480e0576a9234f06e65bfc7d3b5acd6efe81ff3c9dc1f88c6059ce054eb00940d689709420acf3e6d5271d53d3a223c99aa240387dbbe8a8dc868b0ca1713e620059c27b2536bd30c2c7023b738aef186bdbf32e0b9015352a5c797da6445b6e948aa531412b123596de6cb14971f2707d17ac32b376a5f06a9dc13cd92f8d2d1ff6aa74c4f3208442950e4eb330efad17ff5e40031c2c748ab0884b3d04dc7724605ab3d842009ca23a495ca67bb45d77748e9b623afae4205307afeeeea0893c462392d3d414f638ecc1d2e9eb9017ef9fa86f283dd724f47a44b6850fbf52e9960c5c2ee63804592b001500faba09cea9956f0fdb29ac17425a59ff80db874ea07a4a1183566034f656b9e91aa8f057771d64e2aa59561729d199340526ce11e505fb5b56b30071a8bf3cef0bd7b899bb3b7cbe69524452f5cf6bdc07d2a8bcc8a4c6630b773dbb70d8f9dec6b8b2e46becbfba5c9ca550afa391d3b7f69de0f05dc387cf1c6852250be0876913c52e3c5466d1e391d01c981cedbf79f5eee881e2045e8cac130101b782037c4a07da4e353153270fe24e5550c07321aee2945a3945ecfe41185dc1a4065fbb7e076f7fd7f4ac5d32e930177d250cf25efa8f4bf0c2078be8a338e796829eba1bcbd147f8ea84b6ac4e31d8fe758245ea49ba923e2e897851584fe9dba4af25a6572c8ef9e4db2aee254fa29c6724ae211536d82dbff61cfcdc0f208ca7d9287424a135df42c464ba7d4d859a62d43260271dcf7bedd04437295ab8c3ae958c914c07bd3b2686c7", 0x5ce}], 0x2)
writev(r1, &(0x7f00000012c0)=[{&(0x7f0000000140)="cfbb251e606bea41ad417032985e05b5725bb9a5a4201587136fda2dd727e5f62dde5a3a4482bc0b9d8726d0da46c1d908ab108ea9ec76e02493a12c1b64b1ae00f41186a7b024d2ddf2ae9d3a377c239387", 0x52}, {&(0x7f0000001700)="60bbad4238f79f3fab424ca4a0c38f34f352c7d5c7b6743ba59aca5b10b7f12be1cfa323ff58d0f57283e760788123b4a989048b3e3733dc8e3463a3713b8e03e9be10b3f7c76b830225cc80a4a30e8bf4756fae56321aa3894ab69fc4e85a1a97cbe34dd09282ac10309c3e29b703b897fcdd82d8fc7688ba2cd139ef3f333ac048fac12ed769c375952c24e6676579a90c4f13d6d4531fac3cc94239d932935ae6f55541b41f24406ca41656dd8e889a023526bff0265e626b535cb4123c4e2bd9e951b2b4d175be8134e3b76491bf204272a534386e4d2ec00bc5b7ecc8375079c2ea5526d6154677d5e2de08d01460cc71b57ac1ab20f6debbb381f3d5952ffa3c413b9c44011fe3eca5714c9e995577c26fa6f4be9cef41e86953f7a67ba4033192ec930ee4a875fd8a2d9e7945f75868255b00c1d5487217f32d2db516fd24a770974859d3e0af7c1368405afacce6876add8c4dda7d84bb1c19850919c6c474260ca663513190f2b732650031fe7abf0498f7fe749be7e9e6ac101382aa72a6a5d13564dcec299fabf7ff328c3d4d7d6bd36dc6249e363c908d6f9b04f61d174a046dd542d71c2ef30a39fbb19573b4f2e16c51520aa99f770b838d7cac545aceed9295c8cacc2be13c08f5ea75691d965e82a6a9cbe553e86d25489b4fc730f2a7712b64df3762913d0afb06179df17b755883b27600d2c8943dd88c3a7e2cdd9fbc6eec90287719b93766304ed49f5d57c3afb3dc4cba148b67797cf390bc442bb29245c2bf1b2f2a2dff528c32ad1e09cdb8a285d491613bdb9f6e567e00184a2ddeb383e6ac4f6f51c13de680b8551e67d41005c645180a9522bab67a29c0617dcbf91dca295be0a8b9fd6c8e9a3bdc81e109ecfbeb026e2391e101a29dbf5d69ec70f783476268cfc5bd0baefee4dc0512f3114fcd10e685021b4a4e0075323ff1c94a6bb7e0339bfa8f7a66cc6d7c1e115f8d8ebbf2db6553927d78c1848463196183a7e8c92e0e3c257889d633cb631b4ff59c051a216f43b532702b4b6ec7451b3ef70a3a50d29ff2a79fdb06c6fb91d8a0a8799b6b6f9d56ed0cf3322f957dc31e1a1729a622c6738e6fa4eccdc51ad158e4852c2bf585910a3726521128386e35103072791d279abe6535f07d9affc005cd85d21bf36450cc4e1d0245e0e2ff195ab6706a0cf0003ac8337adaf54ed5923f9a2e4245e6f03823c1f3f26269f3f3f26cb664a92e773178e9d0b51f1aba3a05337c5387245d009e2187cfeb658a7fe98619a1e769883a6ac7f9c01e3e35e20f7675901ee6c2e2b31f952d35d8f2a38d6236514080ce02d2b8de01801a6e4d0588d0663db5c154ee8cd913e07043ef8045ee57dc97520c3d7c597c82d7b4486c8d94d94191e7971e2ea868304007799447fd1953fb8103afdbffb934ece4527b8797a9ebd69510bee9df749c3e68f5ce9b84d5662032c9a1fed49f81e7886cbe9122ac339f72c7e93e927f628ee59d83c6c13420e0fbfb27ce84d4b8d2035488f99d97c1b87661ef58dd62a9fedef7685ec2dc16f97ceebeca935bc8925900ec234bad42982a7e67a5d33648e1defd0a585365a97535c5d78018b7a2164540ae07f81dde252208eebd15834764dc7a56345da952d9b090aebd2a54888deb5e104bc2f54155c0063a8211269ed2c21b8f5ee6c6515bcc429a093dfd0146deb9e8a56dcc73fb36492c92195ccd793738776168791f3a224fee2a695af5e95d3fdb82b312e9bd98f4aafdd9c268f3cf3790cff6649efe9d9595030aad7b24515746a52e821c6f45cf03240e3eaafd364f095bbb33a47b50fbdc2c66fe86fbcbf7b1c077e929f8e92951697de55ef19623d5ffcb9eab8b268338b8e26a2f5587c031e95917fc9e1c0af59ab18381a39ee73077d6126b26733c4b1ad311fb5ec3496f36b460153df51fd8f3829e877104ca327a6ce688e1f1f928d98bb1731715ca6d74b5279923547399511939c382368449eb3a806ceb299241f0104b56702080154578e3883edf3baf82076aaa002950500ea3a6ffadb1020b3787a7451580b5cee54190883ab55c0674746401b6bea12bad4293f0048efba066f539d1269e0a16fbeb2daf33fd47387688b43d6bf4b4f09d7c3bc07175f954c07f6946c5f4249b7b71f802bca3bdf8019dd6deae065f154a61e151b42b3040866dc7deba7df66f03ea721787e2268e58194b3cd8d9c1f9e965cf3e87b53f466fcaea4b3c9f1853807b05db27e4a206106c2bd7bde96102c3d0f0362b46853a36a12b18c9a0b83b2bf8dac247252c7138fe258c82f66d3446cbc41fff1d6abb165c776d23f6d93053ad368787b6907b1061f86f053ac2fe0ce77d10d8b5d3d52736b6bd89446aa529e636a83b70fe4a13f364d44f0db842cebbdad2e01b41e4ae61ffd309c30666498b9164c9410dca9d90879369602ef8670fc0f82e0deba5e753726e5909234aa1e2086b711d459db6ab35e7d81ebce83c1df31b6c48808f9d52020a72c99e07ca4e0de97e9bca82e2abde799287e966f03b783285cdca5ccac3b9653d94ccb17017a37b5af22832876427b0842849696a39349faaa03ef3078f51c39e4153e1330bb5be69f1103530cc09c5cef0b201111970b0d901a70af9dfa4bca6b34dff016066863936f3005f87f971bdf723d4aa71c8dee65564d66f6e4e2fe83e2a11b097c6a14b651bf1b7e253282e9adf0229f158c1ad0bef485e7a904df7c56cab5724e31b2de2ab6d87abb85a5b7174e27c3c515c1b77bc181d25eec397987deef62ed117c800f434664ce870d7d3f580d330147355c369e6564f049ea833cda2ae8fa9e34ca1a63dbf2117f5a5dd530e85224ff495035e35ae0201a608593401611fa631faa7f8029707fc0333c219acab704dbb9b80a7010989f1f3fa4856cea880c4b3e8e2d43fd12fc46f23dfc079f30407a80956938e27c0354d4f8e3e455497e9679cf2d8b57bbccdbdb75331f15e6fcc26346346d0b59913cfbaf38b2d73091b2c5497f9a8a8d0be52c205c89860e2b11bb16976796d2766b3efb36626bf1d894fc00ce4bcefbbab2608aa37137680d64e568bab8abba22d8fc846ed607e2fcd80a64f11ffb589514e3758c72f7c485a0e62b21de20fb2c481fa14aca0db56fe998247e9f41643b171b904cdc4babb4dd03533bc0b90deba0b66b103492d0ab79b2ae63e79484ebf0ad96b32da892ba082991f77ce7475dea0390f837df5bbca8a64934d722912d651b3c09b02bd3cf2874d3c8ca66496db05c6392963383cd417fca84a4492901d5a532941bede6878f2c0d387bc93439e1e79472a625bfc6f78c54ef44a395da80e6c0b777a6348b356af1c8176087ec63f87555afb3f6b594ac2fee5287b9313a556a3597c69ec3ba1fa1ef3c46c6135fbe78fb739af045d0c0ed99cfede95d7eadb381cd160f3bc34efff00ec4c417e49675c8b6b1f2c3e3f3f66c0db57c468fc7f7a48ff7aeedfa6814e5a0bdf5946f7018558c990e3ce934456b27c6a082481791de85712a334e5efe61e5863647299afe3157d5b815c9935512473ede307e8a546b32c3a85cc65a71a2f9cf4d89cb6d0451789ff6d47cd64448dff7a2cd03a11adf2ffb94618e50221ab6a9718d56dea31af92318f53bb874171f3f34c07b2d9bcbafd944cb02ada658ea094972fc68e21cbef4d884cc594671146ddaa3843fccd56af84aaf0047b2484a24c3b04b067a00dd89a097aaefea71f187e0581fa01a102056b8d26f4cb6900eeb26c860eeead7201fd2d9f2383ce5ec4f330d059dba708ab3eb6ad6662a168c3be14e226791a7d7168495b5826c8b57ba819ff359c984de9daec5273a2853675756a9422ef0ba8bc08961b333d7bf702db9dab08fdca1db9ab42fe80fdbbd020a4d0bb1335df43a8749bf3f5f1d3a30e130e8b7b43e7f78cfe32d0b324e1dbdf151b73cf2f93a7315b080573b4b819e4264526d30f987493d1597ca97f82279cb23eaeca4ebe4ece55b8e09a2deb15c2ae49898f71b7f5694e7e6089ee434c01d1ad586e63dc05e7074be8db1019dfd6ef54a10831c0fc551bed0ae5e40b3585bcbc4b71537f4a4b6b4f355598c897adb5228db77002a2cb148d90c7ea8a4e83af590b48342a053a4240a4239c16ae937fcfc7da372f6b506a761f60f70a8af108914e4aa0050a64a7ae2f73b557eba12166224f32f095e0b91b9f0a75a83ebdf96e59878af7948c553437147187aeb2088910ebc5498711a9443715523140636311999297b504cdbe084e0c5a99b9aeb57bbb974c51b0a49c30cfe2f5f2bfef509258f2d7cf5217b83c710f1ae4bd33a47d17f349779221203baf87c10fc3f93e6c3d2859676104769fedc10032fe91a5d6c027e7371560728a9dcf814b44792721e23973873550ebab1795da12b73ae5d895feb51709406dd3b18ff53fb5d3af8b0b714e484afbc262ba6f2a720ab0b18cf75d1f457e04928334377644332fc58a8f77e91f95d45b684818095b7e41cfb60be405ee289986f36b7e892bb7422aae9656fb031eb9d9b63bb4c70851689c40d54a17f7b48f0f97b3ab9739f937dd251689ef40c92fea33c99db294c1bcc27b695a288cfdff197c28027e7276611f8f97fe98384a843e4968bae4b1f63393346a753aa06042836b6eb1adc25d78c298a234b1cac319edf789f6abaa6d67094fc7f48b24b92d030baf14955159339d38a006fef1349bb73b6fec03b9119f97ea753bf376210c467520eb7cd052a36161eaf5062be089fc657f8fa2245a5887b29c26216a143382bb5e3b77b6f2cc5559a8c4915c496548734666470f24dc19d65f1a0ac2dc1b553f0c3af1510fbcee5f57461b6d14d3bd721e62238c06e2784f1a012fde89e352bbf2365b565d50ee27246fc00bd62fe46ece7b976802a697ccb7c717f85839a6e39b20bffd8e0e25e7b128c962421fde44ed4b742fe7af596add878c920cdebc7afbb42800177016cdc39d852dc64040be9fc5182c05f530e669ce2d0489b5fb5ea95fc56fa3fec5e27e0b7a450507f0b3de240899647fdfe5e7d52546aa7c358d02fe9fea6767d662d651ec1fb10e613b1f219c440362bcad23654f8602dddfef51c21e431c75b0317d0df0f843df1495817a85367e081e1df83647b7d07dbacc4874816214aaeae0a574f57381cc70f4cb782034e9974a6c4cf23c247e69a0f7fa08750b08634957ffb8826bc753bb42000c6df0e2b493ae873f7d30ce865d5a419fae68052d035a898d89642f748e6a50cc49129042298325da86c94b430396fec4bb4d3cb232a23e051061f31b9c6152c692caad3f9a1c44d06e4766d4a3137c638fa75eac3ae9e1c6a6226667470592040fa642e72722b1c98badc64d33ab3d28f1cf6f30a4c63d65d14bbd626c3612716817d83f3f9a2d96022fd5159fa45e765d02d141a4f66ed715ef7695b0ff2bb59360a729e23fbdffdee91fcb8b8a3d9e9312a522f153acbc9e9a0b412747a936731577b0a91aa6b8ae503bc74a83462f3ce2ae41a1c152a9000ad0bd7443c2f41fefc91efab2d43099aea185d7200861c97a6787cfea734be370bf36a510e4fdc186aa9f4dbe92f32fa3770dc8db2d7cdcbf9344157da48d6a5ebacbebddeae4c408c08de0a081aaf79d98b230eda6c8823cdfe59bd148b736d02f94b64afc46d3df29558891bc48c8ec7d485aa99c4417a1879c9ff1625f3e821b2347c176a0ef958ad7fc54eb10a53005b922393cee5a6cf7300f4c9171d462ddabbc0227d491f37606fc5c8e545d2a85634608", 0x100c}, {&(0x7f00000001c0)="25fd26f0c2f6f8454eb4598cefd3a544b22bac827dfb6921cd320fabb353b6abd1bdf7a6dd432ca5295f892a5056cb9908d6095b22d9c02cf7a1653f1749274f069fd0a76fa516008092282620fdb3582c7b29a74fc9a0628e26889677f0ab87054b774261de8656a080d103c0504abd02c0f742a4a5cddc2434f350c2d1e641ddfb5bd0cacc83eb73828ca34a56b3b35bc8b2610eb4eb453adb749734526c46d9b2ab6d8614761d796909a6fc66c7d08cb1527152db4272ad88493fb38f40398b5ab50934fa551a4b2630e0900d08787e89612408f5c38d3185e17475d4a49400"/240, 0xf0}, {&(0x7f00000002c0)="e041bac6e222cda5a8a83a629eb6514522c599cee99c1c36bf1a6bc1303e5e1af2c7d6ef7e7a04f1ec148d49241dd0881538a2afc2faf893f9dfa86f68f0f3f25c0bc65341263ac9ac9d46c0f4257d89bc3db24110867d5653d7bfbe294fd3c8f7d004762cd5c286b039df3ed0e2aa6f15488dfe95d5b74aefce77e0afee5ddd2876e6cf2d05000000000000007ad4273acd0f", 0x93}, {&(0x7f0000000600)="6973b3b7b5f516f850b75a28715b10f7ad5d42b6ad24befe41ebdfe071af14f8fc7b9031407b78e22b9d0814b9d792c9c83e5098efb4993f4ad8f4562dc983a42eb32fd9120e86d581ca3b88d1e1d14bf2fced5de86ab55c2a3e0199c24c232e3965832a8b339aa00261dde68a23b8d6b17ccb20b3598262b33d77dfb2f699e8003ba5e6852657ebe417b248026d5e296738d18e4508f37274f008a4fdfa9b8c2a1838de9e17b63c47d9fa63336e630736d37c3d7c65312e131b82ef9cc1b0bced06209a65ff61b2a8b14004fe487ef66b23acee047b049423f836ab87a7345585cbf92f2a4ac7e1cfe61fc4349db1e33c2da8f35920c7c73d54042f6daeca3eaf67967c50e6da9709ba6f60f11ba40091ddf33ab51f0af7d079126cc2a31c2ed60bd75314d3d4b3fb68441788ef99c0c89a954a03a54780d6b185ede26f65208dcce5c269e7cd1e035d18d1a6ab12971530f9560be23b0f79e88eaa7e2000792a8097b4ddd49daab1ef9fc945a49add61f933b61998cf8127db66386e739bf2b1f12674a63fd4c33bd7160fd5b2776725e2553e40f4d7f8bd00b660a77af3d19d56b494232e2d8003139151a8bffb808519313f751d17b8dddb913a8ff30fa7f017d701ed9dd8d01988d59945d5", 0x1ce}], 0x5)
writev(r0, &(0x7f0000001180)=[{&(0x7f0000001200)="ec6e6688290eef4d1e3caf403d1c8ec765728f141ab9100008000000000000e9ca199903fdc9ca6118d232a369ababce52c001fe64edfe80fc7c67b715015e97d64167b4cc024469e8ccacfe668e499fbe1a61794fdd72d4b72f2d2dbe26f7bab1158d052a9d215a57d3f2ba438cfaf0b979ffffff7f97a05b0000000000a41dea0dac1cfc8351b5fc", 0x89}, {&(0x7f0000000580)="6e0e59233e96f72fbe9d7537c357c1e762ffdd2941d1480727fd7e2179ded76e26da7e0a87570dceb33df4e272cf9d641dc9cacb280d539069084c386a14de14b8d6ed2b78bbb26aba3379894e573bfe95dbf8df93438d0c534134a7898dc14ca5cca20aaf4bb1443b740645be2adaf635694e4e6ad1120301", 0x79}, {&(0x7f0000000440)="06f2d803612e7c3baa2d418f22715baaa6d45f8a50f1cffc08bc399d774601dfc4f36e37320c27dd6c0f91d2a7ba63361022803132f486a8e3d4a6448eab74f80505e0f87950b4c9fa81dc2544e390117246d5a994c5781aa279fe298273fea66e7ce2b926f5acd0d1dd0b375905f26a8935eda41833b3891f1f56c1e95bed206462a8c1248fff9f06d41336ef4a", 0x8e}, {&(0x7f00000008c0)="12b1c68e4e76099b4c66a551dc6f52feeb34be35ff519fdffcc2381874f4e22146234bd7fdd653264ede74f85478f382a524978e17e1668fc8c3c27e57219888594710cb91a83fe52cb4b0a622e2c27fda34f75bc07eb331bf06e05a60b012427f8766f9a8d41134b1e4fb77f608bb25b5cf2b44ede1681033c314a01ea45a28bcd2512788ad3e876415d6b570827847e07bd29a49742f68e434af36448131c789d3e209a0a4fa3d3082d27dac39999e72a0603dc4e2dae3768ac549136b868fb642d55f", 0xc4}, {&(0x7f0000000500)="ffffdf57000000000080602c6a9b9722af847f", 0x13}, {&(0x7f0000001040)="be5f9af4744d7a7f3899a46aa1321d50719f12a311557cfa9b7d48a9359787d62f40a1c43a2e6ed68c0da7e54f0365b0054449b78550a77c6f26411f5d73f1280667f6959e0c1d3dc6187bb36431a3e2ce66eb78cff2e41cded868fe25e92711df1c4289759dc4b49d573a32da0ed8ab79c5976cc7a57d4c6db9780d5e84e90a24bdc5a0145c0f03f1800746a476ab5c153ee93eb47b12b71e22dd4890d3d330614fd54ea776df09008df6bc0ccc4fcb4a", 0xb1}], 0x6)


syz_emit_ethernet(0x2e, &(0x7f0000000200)={@broadcast, @remote, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x1, 0x0, @remote={0xac, 0x14, 0x0}, @multicast2, {[@timestamp={0x44, 0x4}]}}, @icmp=@generic={0xa, 0x0, 0x0, "e10f7965"}}}}})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f00000001c0)=[{0x6c}, {0x54}, {0x810e}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


setrlimit(0x8, &(0x7f0000000980)={0x6, 0x51})
r0 = syz_open_pts()
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r1 = dup2(r0, r0)
close(r1)
r2 = syz_open_pts()
ioctl$TIOCSETA(r2, 0x802c7414, &(0x7f0000000880)={0x0, 0x10000043, 0x5, 0xa7bb, "d8f1f9bdca0d8300"})
writev(r0, &(0x7f00000003c0)=[{&(0x7f0000000280)="4de815b9331dd829184f10a369913c70535806d594c4f33ae8e4ddd667ca763214729273fd80ba3283e73e27e19fc56b88a42573598164c93c757aabda6f7f9bab8439c34c18d7525c9892388b6ca7d49bb34b885632ca81ca077c729b17fa42ff51bbdfed16e2586cc3899b38608ca5878515e5e43f2a6212ef99b4458dbd491e2e09e67e49040b4f872475ece74e473c66b2afd8da8ab503ebb7f71fc3002ed4c39d285cc143454016929c9ce705f41c19da51ebdecf56eedbd954d82a037bdb0d0d", 0xc3}], 0x1)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x1, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x0)
setsockopt(r1, 0x1000000029, 0x35, &(0x7f0000000000)="5ab7776a", 0x4)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r0, 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x27}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


kqueue()
socket(0x0, 0x0, 0x0)
symlink(0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x138, 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
sysctl$kern(&(0x7f0000000300)={0x2, 0x8}, 0x2, 0x0, 0x0, &(0x7f0000001440)="00000100", 0x4)
getsockopt(0xffffffffffffffff, 0x29, 0x33, 0x0, 0x0)
syz_emit_ethernet(0x3e, &(0x7f00000001c0)=ANY=[@ANYBLOB])
r0 = socket$inet(0x2, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1021, &(0x7f0000000000)=0x5, 0x4)
shmget(0x1, 0x4000, 0x0, &(0x7f0000ffb000/0x4000)=nil)
shmat(0x0, &(0x7f0000ffd000/0x1000)=nil, 0x0)
getsockopt(0xffffffffffffffff, 0x29, 0x4, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f00000001c0)={0x4, 0x2, 0x0, 0x1b}, 0x4, &(0x7f00000014c0)="70c34227", &(0x7f0000000400)=0x4, &(0x7f00000004c0), 0x0)
setrlimit(0x0, &(0x7f0000000040)={0x3, 0x1})


openat$wsdisplay(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
socket(0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x0, 0x3}]})
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000002c0)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000000c0), &(0x7f0000000100)=0xc)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x37}, 0x4, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x10, 0x0, 0x2e)


sendmmsg(0xffffffffffffffff, &(0x7f00000007c0)={&(0x7f0000000780)={0x0, 0x0, &(0x7f0000000400)=[{&(0x7f0000000180)="b860fe09625ea575faa1b6c6c1d6c2eca2950e663d39ab1be31a269a39fd7f97e41e178f37a79f0065733f7e4e4973c1e6b33ac91343ea3b3f8c5c7b93d5c20ab4211791fe30", 0x46}], 0x1, 0x0}}, 0x10, 0x0)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f00000001c0))


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x881)
r0 = open$dir(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x801)
setreuid(0xee00, 0x0)
r1 = getuid()
fchown(0xffffffffffffffff, r1, 0x0)
r2 = getuid()
setreuid(0xee00, r2)
mkdirat(0xffffffffffffff9c, &(0x7f0000000340)='./file0\x00', 0x0)
renameat(0xffffffffffffff9c, 0x0, 0xffffffffffffff9c, 0x0)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000140)='r\x00')
open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r3 = syz_open_pts()
dup2(r3, r0)
syz_emit_ethernet(0x2e, &(0x7f0000000040)={@local, @remote, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, @rand_addr=0x10000000, @empty, {[@rr={0x7, 0x3}]}}, @udp={{0x1, 0x3, 0x8}}}}}})


getppid()
r0 = getuid()
setreuid(0xee00, r0)
semget(0x1, 0x1, 0x230)
r1 = getuid()
setreuid(0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000280)={{0xffff1c8d, r0, 0x0, r1, 0x0, 0x125, 0x1}, 0x1f, 0xffffffffffff8001, 0x1})
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
msgctl$IPC_SET(0xffffffffffffffff, 0x1, 0x0)
open(0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x62, 0x0)
ioctl$WSKBDIO_GETMAP(0xffffffffffffffff, 0x80047476, 0x0)
r2 = fcntl$getown(0xffffffffffffffff, 0x5)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ktrace(0x0, 0x0, 0x0, r2)
setreuid(0x0, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{0x1d}, {0xc}, {0x6, 0x0, 0x0, 0x7}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = socket(0x2, 0x1, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000180)=[{&(0x7f0000000000)="9da8e3e9ed", 0x5}], 0x1)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt$sock_int(r0, 0xffff, 0x1, &(0x7f0000000200), 0x4)
connect$unix(r0, &(0x7f0000000000), 0x10)


open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000401})
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r1, 0x9, &(0x7f0000000280)={0x2, 0x0, 0x1, 0x1000301010006})
r2 = open(&(0x7f0000000400)='./file0\x00', 0x0, 0x0)
fcntl$lock(r2, 0x9, &(0x7f0000000140)={0x2, 0x0, 0x2, 0x269000000})


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000280)="b1", 0x1, 0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
getsockname(0xffffffffffffffff, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000340), 0x0)
getpeername(r0, &(0x7f0000000200)=@in6, 0x0)
r1 = socket$unix(0x1, 0x1, 0x0)
getsockopt$sock_timeval(r1, 0xffff, 0x0, &(0x7f0000000000), &(0x7f0000000040)=0x10)
r2 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSDIRFILT(r2, 0x8004427d, 0x0)
ioctl$VMM_IOC_TERM(r2, 0x80045604, &(0x7f0000000240)={0x1})
rmdir(&(0x7f00000012c0)='./file0\x00')
r3 = semget$private(0x0, 0x0, 0x60)
semop(0x0, 0x0, 0x0)
recvfrom$unix(0xffffffffffffffff, &(0x7f00000014c0)=""/88, 0x58, 0x41, &(0x7f0000001540)=@file={0x0, './file1\x00'}, 0xa)
semop(r3, &(0x7f0000001580), 0x0)
sysctl$kern(0x0, 0x0, &(0x7f0000000180)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b10689ca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d12727b1e1d0cc45c7ebd5df53fb588fd0245528fe5700a5868eaf74d373197fb657a56e99cdbddbb382ad676b756d", 0x0, 0x0, 0x0)
r4 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
r5 = dup(r4)
writev(r5, &(0x7f0000000540)=[{&(0x7f0000000240)='<', 0x32}, {0x0}], 0x2)
execve(0x0, 0x0, 0x0)
execve(0x0, &(0x7f0000001640), &(0x7f0000001880)=[0x0, &(0x7f00000017c0)='\x00', 0x0, &(0x7f0000001840)='\x00'])


r0 = socket$inet(0x2, 0x1, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x40, &(0x7f0000000000), &(0x7f0000000040)=0x4)


sysctl$vm_swapencrypt(&(0x7f0000000040), 0x3, &(0x7f0000000080), 0x0, &(0x7f0000000180), 0x0)
setrlimit(0x0, &(0x7f0000000000)={0x8000000000000000, 0xfffffffffffffffc})
r0 = kqueue()
getpid()
setreuid(0xee00, 0x0)
r1 = socket(0x11, 0x3, 0x0)
sendto$unix(r1, &(0x7f00000000c0)="b10005026000009f0000000000070000001c130500000000fef96ecfc72fd3357ae380b37b673039d2d236acf60b7804be78164991f7c8cf5f882b297be1aa5b23edeb51e2f0ac3ebbc215000000eeffffff028ea8af630037282102000000720fd38bfbb770c1f572c881ea772ec592040000000000ff0c2300008abfba0900000008e371a3f8343712051eeab71d89e0442c5e52000080042000"/177, 0xb1, 0x0, 0x0, 0x0)
socket$inet(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0x80206931, &(0x7f00000001c0))
writev(r0, &(0x7f0000000080)=[{&(0x7f0000000140)='\b', 0x1}], 0x1)
setsockopt$inet_opts(r2, 0x0, 0x9, &(0x7f0000000240)="093f49cb", 0x4)


sysctl$net_inet_divert(&(0x7f0000000040)={0x4, 0x2, 0xf0}, 0x4, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000007, 0x0, 0x0, 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
kqueue()
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000000)="5ab7776a", 0x4)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
clock_settime(0x100000000000000, &(0x7f0000000000))
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, &(0x7f00000001c0))
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x8020690e, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000180)={0x3, &(0x7f0000000380)=[{0x4c}, {0x50}, {0x4000006, 0x0, 0x0, 0x10000}]})
writev(r0, &(0x7f0000000300)=[{&(0x7f0000000080)="a6750e35c39ac622bb5d5334d994", 0xe}], 0x1)


socket$unix(0x1, 0x2, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
syz_open_pts()
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x5900)
r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
select(0x7, &(0x7f00000002c0)={0xfffffffffffffffc}, 0x0, 0x0, 0x0)
close(r0)


ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000080)=[{}], 0x1})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b10005160000000000000000070000001a5113fecea10500fef96ecfc72fd3357a89583535673039d2d236acf20b7804be38164991f7c8cf5f882b2900e1aa5b23edebc8ef99a8ad491726fa8251e2f0ac3ebbc2feb3fda1139b672f4d3353eb06acdb35a069d7080000000000000000008904000000000022830cf41bed66f4f365ccdcf3e4999d9d20002002", 0x8d, 0x0, 0x0, 0x0)
sendmsg(0xffffffffffffffff, &(0x7f0000000240)={&(0x7f0000000080)=@in={0x2, 0x1}, 0xc, 0x0, 0x0, 0x0}, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendmsg$unix(r0, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x40000802)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000140)=0x7e10a2f)


r0 = socket$inet(0x2, 0x1, 0x0)
getsockopt$inet_opts(r0, 0x6, 0x1, 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
execve(0x0, &(0x7f00000002c0)=[&(0x7f0000000100)='tap'], 0x0)
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0xc028698a, &(0x7f0000000100))


ioctl$VNDIOCGET(0xffffffffffffffff, 0xc4104603, &(0x7f0000000000)={'./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00'})
sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x1e, 0x2}, 0x6, &(0x7f00000003c0)="808f643b27da5db78de07d2b0ffbc05bc906aa654bb4ae3384fe6f5b54eb996eacaf981c99c213e2bba73f4133a5d70d759d3c86801b4d07a6a9b001c0b4297151cc28e2dbd90de9418cee114caf8de15b81540bec2bacf4b8991b2fa225e6c000000000", 0x0, 0x0, 0x0)


socketpair$unix(0x1, 0x0, 0x0, 0x0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
recvmsg(0xffffffffffffffff, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x10000000000, 0x0, 0xffffffffffffffff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


setreuid(0xee00, 0x0)
r0 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r1 = getuid()
fchown(r0, r1, 0xffffffffffffffff)
r2 = getuid()
setreuid(0xee00, r2)
fchdir(r0)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000002}})
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x1}, 0x38)
socket$inet6(0x18, 0x2, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
ioctl$VMM_IOC_READREGS(0xffffffffffffffff, 0xc028756b, &(0x7f0000000000))
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x5ff, 0x0, 0xffffffffffffffff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x3, 0x0)
close(r1)
r2 = socket(0x18, 0x2, 0x0)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


sysctl$hw(&(0x7f0000000000)={0x4, 0x1f}, 0x3, 0x0, 0x0, 0x0, 0x2)
mprotect(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x1)
sysctl$net_inet_tcp(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x1}], 0x1)
setsockopt$inet_opts(r1, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
r2 = dup2(r1, r0)
r3 = socket(0x2, 0x1, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000180)=[{&(0x7f0000000000)="9da8e3e9ed", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
dup2(r2, r3)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$inet(r3, &(0x7f0000000000), 0x10)


open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x144, r0)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r1 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
sysctl$net_inet_carp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
getpid()
utimensat(0xffffffffffffffff, 0x0, 0x0, 0x0)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x3, 0x10, r1, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
getitimer(0x0, &(0x7f00000001c0))
openat$diskmap(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socket(0x0, 0x8000, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x14}, 0x4, 0x0, 0x0, &(0x7f00000010c0), 0x4)


sysctl$vm(&(0x7f0000000000)={0x2, 0x9}, 0x2, &(0x7f0000000040)="c4fef8fe2a72cca3eb0584963497b0cfb055c06ce437c73c00579c2e47631ed3d8c59a9b893ae34549ea813e9b4d4a6dff894490b145227fb9c86455d8bdfa28b68cf91acfe68257dee42818ae5ae5fada6bda685a2bd3394ab499ee664b0fb93f888183fcd0b5fc0db2e2a495d4704f7da5e6d46bce316ef593e79e08f7ac8ad1a31ced366255da268f68e868589e4495ee3a91c465cf7530abb6647b449a7833b8e66e5579052112ecbf8ee1d6211a2aeee2102c8521", &(0x7f0000000100)=0xb7, &(0x7f0000000140)="7933c25246dec538d492dbd7d74e0567e52e230d91ce797833d666da21ebe6873a77a3af0862291e", 0x28)
sysctl$vm(&(0x7f0000000180)={0x2, 0xc}, 0x2, &(0x7f00000001c0)="2313025893751ce60c08bb74b7db5efc61b787c726ff8396a4cb3dcf48c00d4ae68d5b968090954015e071cd0c364b4e7cb777a576798ae85f316cfa322fa9c265ac1c39b480e6dde114578aadb4f38ce48a4f39adf4d680a6d658dd1e894f3c494fb67b7a994110bb20047d019a3c3a82add58e2e89313c65834a40fdc64141cdfc3efd96818858152ce4e81ab3f283befc74", &(0x7f0000000280)=0x93, &(0x7f00000002c0), 0x0)
sysctl$vm(&(0x7f00000003c0)={0x2, 0x6}, 0x2, &(0x7f0000000400)="60dccb08df84478002c6f4637652e7a3f78335041ff37918474173cdcc35269a77dbf17e4b19e26f982bbe8f3aa2d8276ba4767c3a4479b8ba8c5e9208655da84bdbd20a6307d16d4b0f850995569d191fa8b4f5497f3ee7d47ee5e50a4b3e7ac4153037480cde5e8e087a526fdc4abf20551277db6341fc95aa92fb8575c55c9d4aa37261fdc83e948653929839cccea4dd37f89eb598ce1cca4ce46a4579e9be59bb3275480c94872c4d89ed89b68e289baa3f0685fa93e51343395e1b24e532af", &(0x7f0000000500)=0xc2, &(0x7f0000000540)="b6cb656e9bcb715644da6e0174c22bc07cbf8cc168b285996b0894b60840b7fd228aeb6bc3f6af16d5af6768dbc2529ceafcc033b8b61fdd0a79a5d861965feb8b196e8690f0c3d34cc284c688e84194042d5ee3db4ced2307db30dc0d843dcce75099ed17ccaaeabf75d6c12aa8fac5b22480534bc30c3b3d1562ed524b0a68cdaaf5200fa8d3052b9fe919d81108fa885ac6613b6af1af0a8f9cdda528b598622a82e54ff25418c9ff9c5ddef2", 0xae)
r0 = syz_open_pts()
pwrite(r0, &(0x7f0000000600)="71bc1da6de84def4dca33e19a53f1d32d7f9ad371c66332fcaab5ab10d71a116cbf44841f2a278ac0b280d5141eda1e3944cede9446e2ba681fde43ebe6e7bdb39a7984f576440a99dff41cb02d200332b0b216e0283ae3c21e5ba6e521811e5e17ebf307fbf0fdc16b685b13b95727de8651878baa877002653e4c70e1b63c8d8f5e88a0f1b231e0eab4da18d6d0ab5fa5ff006472f982e0e3b437cc1ae29234498b5efe43bba8d55f4bddb98bc5b2be9cce4a74321ae4752cde5e14c0741c23e7d46026145d0fcc5a51c963a9199bf81a7c65d99eef30a79e9b0", 0xdb, 0x5)
sysctl$vm(&(0x7f0000000700)={0x2, 0xc}, 0x2, &(0x7f0000000740)="b2bcd9530213d1e1c41c2eb0aa6cf6b31b277ab341da8ddc2a0b1f42141c2e5196c52a53d72b51edf7611f963f6b526faba3774d8bf904e25cb4098ab242b5d440b14f269049cbc03dc87fda77f691f1335890bcb2b714cc94fac7a3fd3321d46dc0887e8ed1eeb082fb9053faeb3b9884b6915e704ad69e6c1e3741173590b37ef33a20bcef1cd91c74c84edbda28fb20ca2a2554cb391adb60844e2fa34eaf416d7e9d44ff7217fc6d84a2013762470969c5729fb9fab20f9ebc129406cadaac99c19c", &(0x7f0000000840)=0xc4, &(0x7f0000000880)="c3766ca3c77c", 0x6)
r1 = semget(0x3, 0x0, 0x201)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, &(0x7f0000000980))
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f00000009c0)={{0x9, 0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff, 0x0, 0x8000}, 0x5, 0xfffffffffffffc3a, 0x7cb4fff})
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000a40)={<r2=>0xffffffffffffffff})
getsockopt$SO_PEERCRED(r2, 0xffff, 0x1022, &(0x7f0000000a80)={<r3=>0x0, <r4=>0x0, <r5=>0x0}, 0xc)
socketpair(0x6, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000b00)={<r6=>0xffffffffffffffff})
listen(r6, 0xff)
recvfrom$inet(0xffffffffffffffff, &(0x7f0000000b40)=""/103, 0x67, 0x2, &(0x7f0000000bc0)={0x2, 0x0}, 0xc)
chown(&(0x7f0000000c00)='./file0\x00', r4, r5)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000c40)={{0xda2, 0x0, 0x0, 0x0, 0x0, 0x5, 0x7}, 0x545c, 0x5, r3, 0x0, 0x4, 0x3, 0x0, 0xa12})
getsockname$unix(r2, &(0x7f0000000cc0)=@file={0x0, ""/259}, &(0x7f0000000e00)=0x105)
open$dir(&(0x7f0000000e40)='./file0\x00', 0x80, 0x20)
syz_open_pts()
getuid()
openat$klog(0xffffffffffffff9c, &(0x7f0000000f00), 0x8000, 0x0)
mlock(&(0x7f0000ffb000/0x4000)=nil, 0x4000)
open$dir(&(0x7f0000000f40)='./file0\x00', 0x100, 0x4)
r7 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000f80), 0x8000, 0x0)
ioctl$VT_ACTIVATE(r7, 0x20007605, &(0x7f0000000fc0))
readlinkat(r7, &(0x7f0000001000)='./file0\x00', &(0x7f0000001040)=""/171, 0xab)
shmctl$IPC_STAT(0x0, 0x2, &(0x7f0000001100)=""/28)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f00000000c0)=[{0x4c}, {0x5c}, {0x406}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


sysctl$hw(&(0x7f0000000100)={0x6, 0x8}, 0x2, &(0x7f0000000180)="113da6b7196ce340f98efe56ceed6f0c1cb790d557", &(0x7f0000000200)=0x15, &(0x7f0000000240), 0x0)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(0xffffffffffffffff, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000401})
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r1, 0x8, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x1000300010008, 0xffffffffffffffff})
r2 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
faccessat(0xffffffffffffffff, &(0x7f0000000000)='./bus\x00', 0x0, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
fcntl$lock(r2, 0x8, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff})
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f00000001c0), 0xc)
mknod(&(0x7f0000000180)='./file0\x00', 0x1000, 0x0)
r3 = open(&(0x7f0000000440)='./bus/file0\x00', 0x8000, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x2f2, 0x0)
poll(&(0x7f0000000080)=[{r3, 0x7d}], 0x1, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x2e92994837ed377e, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x45d48)
ioctl$FIONREAD(r1, 0x4004667f, &(0x7f0000000140))
open(&(0x7f0000000200)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r4 = socket$inet(0x2, 0x4000, 0x0)
mknod(&(0x7f0000000340)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x1, 0x637e)
r5 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$FIONREAD(r5, 0x4004667f, &(0x7f0000000080))
setsockopt$inet_opts(r4, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
setsockopt$inet_opts(r4, 0x0, 0x9, &(0x7f0000000240)="ea000001", 0x4)
ioctl$TIOCSBRK(0xffffffffffffffff, 0x2000747b)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
r1 = dup(r0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


socket$inet(0x2, 0x8000, 0xc2)
r0 = socket$inet(0x2, 0x5, 0x0)
syz_emit_ethernet(0x108e, &(0x7f0000000100)=ANY=[@ANYBLOB])
recvfrom$inet(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
recvmsg(r2, &(0x7f0000000280)={&(0x7f0000000180)=@un=@file={0x0, ""/81}, 0x53, 0x0, 0x0, &(0x7f00000005c0)=""/214, 0xd6}, 0x0)
setrlimit(0x0, 0x0)
r3 = syz_open_pts()
close(r3)
writev(r3, &(0x7f0000000440)=[{0x0}], 0x1)
getrusage(0x1, 0xfffffffffffffffe)
sendmsg(r1, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)
open(&(0x7f0000000180)='./file0\x00', 0x80000000000206, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, 0x0)
r4 = openat$speaker(0xffffffffffffff9c, 0x0, 0x782, 0x0)
r5 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r5, 0x0)
r6 = dup(r4)
sysctl$kern(&(0x7f00000000c0), 0x2, 0x0, 0x0, 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r7 = syz_open_pts()
close(r7)
r8 = syz_open_pts()
close(r8)
ioctl$TIOCSTAT(r7, 0x20007465, 0x0)
ioctl$SPKRTUNE(r6, 0x20005302, &(0x7f0000000040))
sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x2, 0x1}, 0x4, 0x0, 0x0, &(0x7f0000000080), 0x0)
setsockopt$inet_opts(r0, 0x0, 0x1, &(0x7f0000000000)="6228951c7f85b0b56aab81b6e533fbeeb0254b38b4984076233bc43918963438e600"/44, 0x2c)


r0 = syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, "ad95be4b065c389983d554ecc416cf34eb18fa8e"})
readv(r0, &(0x7f0000000180)=[{&(0x7f0000000100)=""/25, 0x19}], 0x1)
syz_open_pts()


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
r1 = getpgid(0x0)
r2 = socket$inet(0x2, 0x2, 0x0)
r3 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
mkdirat(r3, &(0x7f0000000040)='./file0\x00', 0x0)
unlinkat(r3, &(0x7f0000000080)='./file0\x00', 0x0)
socket(0x0, 0x2, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
r4 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
r5 = syz_open_pts()
readv(r5, &(0x7f00000012c0)=[{&(0x7f0000001200)=""/1, 0x1}], 0x1)
ioctl$TIOCSETA(r5, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0xffffff9a, 0x0, "b07b1f660000000000002000"})
syz_open_pts()
ioctl$TIOCSETAF(r5, 0x802c7416, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "0fdb00000000000000060004000000000800"})
ioctl$WSMOUSEIO_SETPARAMS(r4, 0x80105728, 0x0)
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
rename(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000100)='./file0\x00')
r6 = open(0x0, 0x0, 0x0)
ioctl$TIOCSETD(0xffffffffffffffff, 0x8004741b, 0x0)
ioctl$TIOCCDTR(r6, 0x20007478)
getsockopt(r2, 0x0, 0x7, 0x0, 0x0)
fcntl$setown(r0, 0x6, r1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000000)=[{0xc}, {0x20}, {0x4000006, 0x0, 0x0, 0x80000005}]})
write(r0, &(0x7f0000000140)="0000000000009cb8e7b6242a091f", 0xe)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
sysctl$kern(0x0, 0x0, 0x0, &(0x7f0000000080), 0x0, 0x0)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000000)=0x9)
writev(r0, &(0x7f0000000280)=[{&(0x7f0000000cc0)="e5f61f916b00531fff97848481d264a674c52536b37da446ef4b0eca834f8b775f988d267fce9294aa5396a754606a113915f5f7bafe1836fafcce70b287b062cb3617f641089c5218cb14c76785977784e9be500f1b66a5dd1d12eb59b929549182f5aa248a24e6ba6b1c61d39d13cc297cf6a450f7042613cf03bfa5a69e75b572047c20e60e9b478e960f178b2c62a600cb6ac7118f76244431a0cd030f41eb987c7710b7aa2555621dcf165a05ffdcf597f0295af80151bc18779ab4d8e7a887b9eb74212e9cf5645199e93324a749d0af77ca57a052c36f000c755be247d20c6a8649c9ba98bd0748f390fc3d8cba7a179e3435dd1b645e8c1e1bc134f4d76befbedceb47635e554ede99fd97da28267409cfce1c209da5177e2ef8f2300088471c531c90ffc28ec42612c21db79511e90ed9018998b277accfcc04e1413b101a99a977a1a3b1b2d87942bf276a3792802c0832a5f24c565f6d77b630028944c3d9100391feef9b0c51319161042c77392809eb43dd8391ac93df96439862b95861607f569f404f673dce157581e6ff475304e2ea84bbb2be87d9025b2192694281de498dfecd3e83021a261d751dd0b0844e6c573167ff7ad60fac64563b6c835b737706b5ee055d6acbca30b74cd98884519da7cd529a964862bfc5a31d08fda2d2d7c9aa0b4cb4f040b2860ff1402735cc89816d1d76b8cecae9c8ad4d201f41ab9ff6681205a4f2ee7e2a9bf95e4aee3088e0917b3eb62b715be8130b84a93e3db8d794668a39570691f0be7d5abdf980557c72fca24867f8cb56169ad1786d5a3ef44cc5c10eff506c3b7c1f80bf6e976ef57bc4ff4b6ef826e20c605624eb2c5c51a48ad0dbe140dc5da4c7ae7b7656b549804afd6590a1bc09c19dba9db8f69b7fee311a3901f44aa87dad57b1136078b6509c0ebf1ac57f7840b7fef5885ca0350350cf79250d717adf0b51ba529c45ee6a1bdf2addbc437aaef7137bd50f7253119d84614d7423788dd33111d352779d1a85f1c503116940e62a5155a96b5f38ee5be8aaadd48e216ca3e973c4b3614dedee3dec82f450f371a76eb837ed77aed6cf3a46ce29cfe9a5a2e411489ba3a047242a7c3ea7c665d322b34abe105f24d6f5ccd7a05e960331e4bbfc7395dd0a9b036796afb2e9d8c3cae7e006c33bee39794596d96435581190b26faca2385959ab51df29c1846113e80f3e9b5aded254d012dde56c90010b33d460f3b9497cef4aa14f0ada320d5d2c0fcbcf93e7b50b0f0e247852be749ed387c877ba7f333266dee90505d58ce38dc8f15b8a011b6703748802d9ece9afd2372afeba0193825ab03df1db3d730324ce2aca552d43de0528315b6e1d48a726303c84c05350d6a24a1741e4b8bbdb472c937153a817dd69ed2f941886ea26e571a4598b55e4f4a0197083b02fb0b3d5e66a510e40601b2c723f06a811c5114258f306a444a916d64a11557a8e262412263f84bfa2598e4d82954709d87eb2acaa379b5bb72d77708b153a5f2439213ae15dce4a5f8716e7b857d76139f8ca04f11dad9044a80cb0311460c22de3a532aff31b4b98a06b5e4f44cda8eb205b7133fe6f243a6f4d92873e4f4054a40c8fdc129dab91dde27983f8569bcaf08ab7ea094c250f59b1ae57761c44a9d40f704bf423b5aeccf9f474de39724152ab634c3688ca807ce0674ee38028bcf84905f622575a0ca51d5236917dcd39e13ab29f4580809fae8edc6bb8d21877dfe562c3e83320404182f0db4b0b8b8c356933f83ff3e90a", 0x4f6}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x2, &(0x7f0000000040)=[{0x49}, {0x812e}]})


open(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000140)=[{0x1}, {0x61}, {0x6, 0x0, 0x0, 0x4000003}]})
write(r0, &(0x7f0000000000)="7696e5f3d1f18c37cea8615ac7cf", 0xe)
r1 = socket(0x1e, 0x3, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
sendmsg$unix(r1, &(0x7f0000000080)={0x0, 0x0, &(0x7f0000000000), 0x1d}, 0x0)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x4, 0x0, "0100012d29fb000700000000098002005a00"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x45}, 0x3, &(0x7f0000000180)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b10689ca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d12727b1e1d0cc45c7ebd5df53fb588fd0245528fe5700a5868eaf74d373197fb657a56e99cdbddbb382ad676b756d4e8b5a81c9a624348f23ffd260bf5fd344a7a30bcf96e47800acc166910bfc34ce76252dd12fac3b10dd5719aa6e420f60e3d2cbb22f5b3a6f7fa3c909e4823cdc0cdf126bc29456035b9a44ff74d852ba5c", &(0x7f0000000080)=0xaa, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0xffffff25)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
syz_emit_ethernet(0x36, &(0x7f00000001c0)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa86dd6089328b00000000fc7be31dda4e647e1cfaceb91fcfb1660000000000000c7eeeaa000080000000000002018605a27b90231011da9d86a6e5"])
openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
msync(&(0x7f0000ffb000/0x1000)=nil, 0xffffffffdf004fff, 0x2)
mkdirat(0xffffffffffffff9c, &(0x7f0000000100)='./file0\x00', 0x0)
r0 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
r1 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000140), 0x782, 0x0)
r2 = open(&(0x7f0000001700)='./file0\x00', 0x70e, 0x0)
writev(r2, &(0x7f0000001580)=[{&(0x7f0000000280)="986dd270be6ac02e9e752104269eb5a5fbdb6d78b13e6b317db4c3c91d806d3117b454794642d9a136fdc6a93a92885b7b7d701c39eb43a2eba3fda5909633c7059ede1e2bb43c8a06121030bcf5b4fc73aef1830a8a44c36c4f60140f5554a0bf950cf6aa08a476b2b1e26894ca05431d770df0d7cf77928f6a", 0x7a}, {&(0x7f00000000c0)}, {&(0x7f00000004c0)="f713c4d5f33865c032e189907f732703f921f230c367713c9621d826a435c8a5a6b73c5e38fa6dfa1881b4c54c0fc8171a857a0f4c94ecd5be8ae63e33ecaa5f5ca33d62261c71e4a1500d6e0997d735817ed2ce00fdae0760868412852794ff57ced4e699a3e4df1d9ab3e0b03845f549d6c287cb0b4fe826261feb0bf0bf0997d07c068f9fa807e88467f85a543c458ddc1d578603f40078f2702898ff2cc93c0346049fe10e7c8e06981c8dbd8f5375d71a32e76ee5f79144ac3995bfbf7df2dd74912b45de529f7c0c0a95a2b25dc0dcd02db702caf8eaf14efcd34109d7cdcd191eb7dd383e1e34ae4ad2099265a80e1ab16aaff43ed5bec42b949fe273312c7aaed09daaf9bc4806fce6ea07691d610959168394cd250787937be3b9d9eb4fe5ac4c81154584d7554ada652943", 0x130}], 0x3)
r3 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
ioctl$SPKRTUNE(r1, 0x20005302, &(0x7f0000000280)={0x0, 0x8bd9})
r4 = openat$wsdisplay(0xffffffffffffff9c, &(0x7f00000000c0), 0x400, 0x0)
fchdir(r4)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r3, 0x0)
r5 = socket(0x11, 0x3, 0x0)
listen(r5, 0x20)
syz_extract_tcp_res$synack(&(0x7f0000000240), 0x1, 0x0)
sendto$unix(r5, &(0x7f00000023c0)="b1000501600000000000000007000000331c13fecea10500fefd6ecfc72fd3357ae320b37b673039d2d236acf20b7804be64174991f7c8cf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139b672f4d335d323e7d026ba8af63003728211e0000d4500fd38bfbbf70c1f5a872c881ea6e69e0bb76d907c400000200361b1257aea8c500002002fb001ff1edc7ea24551761d12767e371a3f83437120557adb71d89e000040781e4b2fff840ff00", 0xb1, 0x0, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
preadv(r0, &(0x7f0000000180)=[{0x0}], 0x1, 0x0)
recvmmsg(0xffffffffffffffff, 0xfffffffffffffffe, 0x50, 0x0, 0x0)
r6 = openat$vmm(0xffffffffffffff9c, &(0x7f0000001140), 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r6, 0xc2585601, &(0x7f0000001180)={0xdead4110, 0x0, [{&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffa000/0x2000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffa000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff9000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000ff9000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}], '.\x00'})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000000)=[{0x20}, {0x24}, {0x4e}]})
mkdir(0x0, 0x0)
setreuid(0xee00, 0x0)
unveil(0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f00000000c0)=ANY=[])


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x80146952, &(0x7f00000001c0))


mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x6d4)
r0 = open(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)
select(0x40, &(0x7f00000000c0), 0x0, &(0x7f0000000240)={0x3ff}, 0x0)
select(0x40, &(0x7f0000000440)={0x1ff}, 0x0, 0x0, 0x0)
ioctl$TIOCGTSTAMP(r0, 0x4010745b, &(0x7f00000028c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x64}, {0x2}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f00000002c0)=ANY=[])


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
seteuid(0xffffffffffffffff)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)='\t\x00\x00\x00', 0x4)
r1 = dup(r0)
setsockopt(r1, 0x1000000000029, 0xc, &(0x7f0000000000)="ffdaff10aac6a28ac93e2eddc45c8454e486f64c", 0x14)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x822, {0x10000, 0xfffffffffffffffe}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x31680000, 0xffffffffffffffff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x1, 0x0)
sync()
getrusage(0x0, 0xfffffffffffffffe)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000001440)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
r4 = fcntl$getown(r3, 0x3)
setpgid(0x0, r4)
r5 = msgget$private(0x0, 0x20)
msgsnd(r5, &(0x7f00000004c0)={0x1, "9cfa0b55f5dfa44c224947f72892822564bea470b0d6ea9e67c08138a1eb15201308f3e430d738c5a02a5de8f9dc6d40f1213013e231c81de361eb80db5ee892e3a36abfc776db9f004060969f4f106d7be733572523f619c7bfb7dae3e7337c6223f07794950f4314d2b7dd818ddad7d892c893cfa9e7d5ceeb015bc9537f85ac9ca0ad0c07993ac97b4fc2dc14dd0cc0269d49e7e8aa8018487013b98b27bb381fd75b15169274846a16bd9aeea1dc82aa260ee8644083ae5d"}, 0xc2, 0x800)
r6 = geteuid()
getgroups(0x7, &(0x7f0000000100)=[0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, <r7=>0x0, 0x0, 0x0, 0xffffffffffffffff])
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000140)={<r8=>0x0}, &(0x7f0000000180)=0xc)
msgctl$IPC_SET(r5, 0x1, &(0x7f00000001c0)={{0x1ff, r6, r7, 0x0, 0xffffffffffffffff, 0x100, 0x2}, 0x2, 0x684, r4, r8, 0x5e, 0x100000001, 0x8001, 0x9})
wait4(r4, &(0x7f0000000000), 0xa, &(0x7f0000000040))
setsockopt$sock_int(r0, 0xffff, 0x10, &(0x7f0000000040)=0x3, 0x4)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
socket(0x10, 0x4, 0xff)


open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
r0 = socket(0x10, 0x2, 0x80)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000001440)=[{0x64}, {0x2c}, {0x16}]})
mprotect(&(0x7f0000ffc000/0x2000)=nil, 0x2000, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x58}, 0x2, 0x0, 0x0, &(0x7f0000000180), 0x0)
r2 = semget$private(0x0, 0x7, 0x3c0)
semop(0x0, &(0x7f0000000000)=[{0x0, 0x4}, {0x2, 0x2ff}, {0x3, 0x8, 0x800}, {0x0, 0x0, 0x1800}, {0x0, 0xfffd, 0x1800}, {0x0, 0x7ff}, {0x2, 0x804, 0x800}], 0x7)
semctl$SETALL(r2, 0x0, 0x9, &(0x7f00000002c0)=[0x87fc, 0x9b7])
semctl$GETALL(r2, 0x0, 0x6, &(0x7f0000000180)=""/250)
munmap(&(0x7f0000ffa000/0x3000)=nil, 0x3000)
mprotect(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x1)
ioctl$WSMUXIO_LIST_DEVICES(0xffffffffffffffff, 0xc1045763, &(0x7f0000000040)={0x0, [{}, {}, {}, {}, {}, {}, {}, {0x0, 0xc8}, {0x3}, {}, {}, {}, {}, {}, {}, {0x0, 0x9}, {}, {}, {}, {}, {}, {0x0, 0x1000000}, {}, {}, {}, {}, {}, {0x1}]})
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
unveil(0x0, 0x0)
mkdir(0x0, 0x0)
poll(0x0, 0x0, 0x0)
ioctl$WSDISPLAYIO_DELFONT(0xffffffffffffff9c, 0x8058574f, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
dup(0xffffffffffffffff)
ioctl$FIOASYNC(r3, 0x8004667d, &(0x7f0000000000))
ioctl$BIOCSBLEN(0xffffffffffffffff, 0xc0044266, &(0x7f0000000280))
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000040)='\x00', 0x1)
setsockopt$inet_opts(r0, 0x0, 0x0, 0x0, 0x10)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x0, &(0x7f0000000040)})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x4010000000000000})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


sysctl$net_inet_tcp(0x0, 0x0, &(0x7f0000000100)="de58b3499f15b9604ce11084d8e230b5fe3d87c894d4c4ef1dc57832caec4e7e5978709f9130384a71dd83459408ff7281dd41a08fe769fa6aa63bcef41a07fad86c79728319dbf4a2ef66b0ef844f542fe82c5a0631e5bc3a5d56d5bf571d3f3138d2f1059167db657b747b5687450b3f780ae2f274b746cc87afb29f3b1102d2b733df43f7ce759f53b536bd39d30bf455f16e02d999c7aef3861dfb3c34ade7689863f19d727187fbc1680bc2c1a74862c0c467e8d4c1156379e446260c981e6d7eb8ffcc8d622112b82b4a38", 0x0, 0x0, 0x0)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f00000001c0))


openat$speaker(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$WSMUXIO_LIST_DEVICES(0xffffffffffffffff, 0xc1045763, &(0x7f0000000040)={0x0, [{}, {}, {0x0, 0x100}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
r3 = socket(0x2, 0x2, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r2, 0xffff, 0x1023, &(0x7f0000000040), 0xe0)
ioctl$FIOGETOWN(0xffffffffffffffff, 0x4004667b, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
r4 = socket(0x18, 0x2, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x1023, &(0x7f0000000040), 0x4)


mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mknod(&(0x7f00000000c0)='./bus\x00', 0x2006, 0x0)
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000480)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f00000006c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000580)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
unlink(&(0x7f0000000a80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f00000007c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000a40)='./file0\x00')
mknod$loop(&(0x7f0000001040)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0, 0x1)


r0 = socket(0x18, 0x2, 0x0)
sysctl$vm(&(0x7f0000000080)={0x2, 0xc}, 0x2, 0x0, 0x0, &(0x7f0000000000)="7f94d7b3557cdd6c36b3003f00", 0xfffffc7e)
close(r0)
r1 = openat$speaker(0xffffffffffffff9c, 0x0, 0x1, 0x0)
munmap(&(0x7f0000ffa000/0x4000)=nil, 0x4000)
madvise(&(0x7f0000ffd000/0x3000)=nil, 0x3000, 0x0)
pwritev(r1, 0x0, 0x0, 0x0)
mmap(&(0x7f0000ffd000/0x3000)=nil, 0x3000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000000)=[{0x7}, {0x4d}, {0x6}]})
r3 = openat$tty(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$TIOCSETA(r3, 0x802c7414, &(0x7f0000000080)={0x1ff, 0x800004, 0xfffffffe, 0x0, "1a05227955686f43a3207fae210b8591073300"})
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r4=>0xffffffffffffffff})
getsockopt$sock_cred(r4, 0xffff, 0x1022, &(0x7f00000001c0)={0x0, 0x0, <r5=>0x0}, &(0x7f0000000200)=0xfffffffffffffe50)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r5}})
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r5, 0x0, r5, 0x8, 0x7fff}, 0x0, 0xfffffffffffffff9, 0xfffffffffffffffb})
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
r6 = socket(0x800000018, 0x1, 0x0)
ioctl$PCIOCGETROM(0xffffffffffffffff, 0xc0107005, &(0x7f0000000080)={{}, 0x0, 0x0})
sendto(r6, &(0x7f0000000140)="71953c47b56f4020b189f00567cfece29ff68c35c21d9ce30dc8b9f618e14be0781a436e872660826202f648a4af608847038630f661c7ed995f8ff84a19f9ebaf73deea1cf352ab0a23b8be0a99b562142af89a06a4160f42af19be57c2e647486a7e3c14167997467ff1978bc27385765b5c4db8d57428a8909f2ae5718117a998258f32a6f18a42fcc827d874f216d74c0e4695a91dd28be0a45c388c1b65515f72964e204e164eaa1cb91917e34444eeed3b68eb14cd", 0xb8, 0xa, 0x0, 0x0)
setsockopt$sock_int(r6, 0xffff, 0x1000, &(0x7f0000000000)=0x800009, 0x4)
bind$unix(r6, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


open$dir(&(0x7f0000000000)='./file0\x00', 0xf02, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, 0x0)
r0 = open(&(0x7f0000000040)='./file0/file0\x00', 0x800, 0x13)
mmap(&(0x7f000000b000/0x1000)=nil, 0x1000, 0x5, 0x10, r0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000480)=ANY=[@ANYRES64=r0])
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x2, 0x0)
mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
write(0xffffffffffffffff, &(0x7f0000000200), 0x0)
chroot(&(0x7f0000000100)='./file0/file0\x00')
r1 = semget$private(0x0, 0x4, 0x1)
semctl$SETVAL(r1, 0x0, 0x8, &(0x7f00000002c0)=0xff)
rename(&(0x7f00000001c0)='./file0/file0/..\x00', &(0x7f0000000280)='./file0\x00')
connect$unix(0xffffffffffffffff, &(0x7f0000000140)=@file={0x0, './file0/file0\x00'}, 0x10)
openat$bpf(0xffffffffffffff9c, 0x0, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000180)="b1000501600000000000000007000000331c13fecea10500fef96ecfc72fd3357ae320b37b673039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139b672f4d335d223e7d026ba8af630037282102000000720fd38bfbb770c1f5a872c881ea6e69e0bb76d907c400000200361b1257aea8c500002002fb00000000008abfba09000000ec29dff8f8353712051eadb71d89e000040781e4b2ffe040ff0008254842899ff2ef932e811f29902bd41c00", 0xb1, 0x406, 0x0, 0x3c)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000300), 0x10, 0x0)
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f00000000c0)=[{0x5}, {0x84}, {0x16}]})


munmap(&(0x7f0000001000/0x2000)=nil, 0x2000)
msync(&(0x7f0000002000/0x4000)=nil, 0x4000, 0x1)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
writev(r0, &(0x7f0000000040)=[{&(0x7f00000000c0)="000076e27510c96b2a311ffdc2bcd4e4d2509b4b509d580bf1dc3e8adf057469fcc034c39d55ea56399ba343104869a9d0be351abd330a6f3aab4056b799c635e712225300536b29a100e504e4fc0cf7362e07418a8c8d302fb3ff6049f9dc1d09a00864445838889d1c87a332462e2e", 0x70}, {&(0x7f0000000140)="d6", 0x1}], 0x2)
execve(0x0, 0x0, 0x0)


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000080)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendto$unix(r1, 0x0, 0x0, 0x8, 0x0, 0xfffffffffffffd4e)
sendto$unix(r1, 0x0, 0x0, 0x0, 0x0, 0x0)
recvfrom$unix(r0, &(0x7f0000000100)=""/55, 0x37, 0x0, 0x0, 0x0)


open$dir(&(0x7f0000000000)='./file0\x00', 0x200, 0x0)
r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
pwritev(r0, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
r1 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r2 = socket$inet(0x2, 0x3, 0x0)
r3 = open$dir(&(0x7f0000000580)='./file0\x00', 0x40000400001803c1, 0x0)
ftruncate(r3, 0x80002)
recvmsg(r2, &(0x7f0000000500)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000400)=""/220, 0xdc}, 0x0)
readv(r2, &(0x7f0000000d40)=[{&(0x7f0000000180)=""/167, 0xa7}], 0x1)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r1, 0x0)
execve(0x0, 0x0, 0x0)
semctl$SETALL(0x0, 0x0, 0x9, 0x0)
getegid()


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x100000000000000}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000080)='\x00\x00\x00\x00', 0x4)
r1 = socket(0x2, 0x3, 0x0)
dup2(r0, r1)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000400)=[{0x5c}, {0x3d}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])


setitimer(0x0, &(0x7f0000000000)={{0x7}, {0xb}}, 0x0)
sysctl$net_inet_gre(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r0, 0xc2585601, &(0x7f0000000040)={0x10, 0x0, [{&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ff7000/0x9000)=nil}, {&(0x7f0000ff8000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000ff7000/0x4000)=nil, &(0x7f0000ff7000/0x2000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ff8000/0x2000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff8000/0x4000)=nil, &(0x7f0000c00000/0x400000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000c74000/0x4000)=nil}, {&(0x7f0000ee7000/0x4000)=nil, &(0x7f0000eda000/0x2000)=nil}, {&(0x7f0000f0a000/0x2000)=nil, &(0x7f0000d2d000/0x3000)=nil}, {&(0x7f0000d50000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000d82000/0x2000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000dbe000/0x2000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000e40000/0x1000)=nil}, {&(0x7f0000dbd000/0x4000)=nil, &(0x7f0000c2e000/0x3000)=nil}, {&(0x7f0000ff5000/0x8000)=nil, &(0x7f0000dae000/0x4000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000c19000/0x3000)=nil}], './file0\x00'})
sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
sysctl$net_inet_gre(0x0, 0x0, 0x0, &(0x7f0000000140), &(0x7f00000002c0)="3d5c4fb3856c4746eb2eb0", 0xb)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000002a40)={&(0x7f0000000000), 0x10, 0x0}, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x7, [{&(0x7f0000edc000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil, 0x8}, {&(0x7f00005fd000/0x1000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ff7000/0x3000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil, 0x1}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000545000/0x1000)=nil}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000069d000/0x4000)=nil, 0x2}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ff8000/0x4000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil, 0xe5}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f00002f6000/0x3000)=nil, &(0x7f0000ff3000/0x2000)=nil, 0x3}], './file0\x00'})
r1 = socket(0x2, 0x2, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000180)=[{&(0x7f0000000000)="9da8e3e9ed", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
r3 = dup2(r2, r1)
sendmsg$unix(r3, &(0x7f0000002a40)={0x0, 0xffffffffffffff89, 0x0, 0xaf, 0x0, 0x700000000000000}, 0x0)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, &(0x7f00000016c0))


syz_open_pts()
r0 = open(&(0x7f0000000200)='.\x00', 0x0, 0x2)
r1 = getpid()
ktrace(&(0x7f0000000040)='./file0\x00', 0x0, 0x106, 0x0)
ktrace(&(0x7f0000000280)='./file0\x00', 0x4, 0x928, r1)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r0, 0x0)
r2 = openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$PCIOCWRITE(r2, 0xc0107003, 0x0)
semop(0x0, &(0x7f0000000100), 0x0)
semctl$GETALL(0x0, 0x0, 0x6, &(0x7f0000000140)=""/169)
socket(0x0, 0x0, 0x0)
rmdir(0x0)
sysctl$vm(&(0x7f0000000140)={0x2, 0x9}, 0x2, 0x0, &(0x7f0000000100), 0x0, 0x0)
getpgrp()
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x1e56)
acct(&(0x7f0000001240)='./file0\x00')
openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x10, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f00000002c0), 0x1, 0x0)
openat$tty(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$TIOCSETVERAUTH(0xffffffffffffffff, 0x8004741c, &(0x7f0000000080)=0x2)
getgroups(0x85ed0e3098300e08, 0x0)
r3 = semget$private(0x0, 0x4000000009, 0x82)
semop(r3, &(0x7f0000000240)=[{0x3, 0x100, 0x1000}, {0x3, 0x4, 0x1800}, {0x3, 0xfff9}], 0x3)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')
open(&(0x7f0000000000)='./file0\x00', 0x2f2, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f00000000c0)=[{0x74}, {0x2d}, {0x46}]})
writev(r0, &(0x7f00000002c0)=[{&(0x7f0000000240)="e049e64ada6fa45d6bee0bf84a9e", 0xe}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000c40)={0x3, &(0x7f0000000c80)=[{0x80}, {0x2d}, {0x6, 0x0, 0x0, 0xfffffffd}]})
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000080)="35b5c242413c1026089a59583cc3", 0xe}], 0x1)


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
fcntl$lock(r0, 0x7, &(0x7f0000000580)={0x0, 0x0, 0x0, 0x8000000000000001})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
sysctl$kern(&(0x7f0000000040), 0x1, 0x0, 0x0, 0x0, 0x0)
r3 = socket(0x18, 0x3, 0x3a)
setsockopt(r3, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MFC(r3, 0x29, 0x69, &(0x7f00000000c0)={{}, {}, 0x0, [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1600]}, 0x5c)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r4 = getppid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0xffffffffffffffff}, 0x0, 0x0, r4})
pipe(0x0)
setpgid(0x0, 0x0)
setpgid(0x0, r4)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000140)={0x0, 0x0, <r5=>0x0}, &(0x7f0000000080)=0xc)
ftruncate(r1, 0xffffffffffffffff)
setregid(0x0, r5)
r6 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000424, r6)
sendmmsg(r2, &(0x7f0000000000)={&(0x7f0000000f80)={0x0, 0x0, 0x0, 0x0, 0x0}, 0xb5}, 0x1, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000001c0)=[{0x6c}, {0x45}, {0x6}]})
syz_emit_ethernet(0x62, &(0x7f00000006c0)=ANY=[])
getitimer(0x2, &(0x7f0000000040))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
mknod(0x0, 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000001c0)=[{0x60}, {0x7}, {0x106}]})
syz_emit_ethernet(0x36, &(0x7f0000000200)=ANY=[])


syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x4001, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
socket(0x2, 0x1, 0x0)
shutdown(r1, 0x0)
select(0x40, &(0x7f0000000000), 0x0, 0x0, 0x0)
select(0x40, &(0x7f0000000000), 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
setreuid(0xee00, 0x0)
r1 = getuid()
setreuid(0xee00, r1)
ioctl$BIOCLOCK(r0, 0x20004276)
ioctl$BIOCGRTIMEOUT(r0, 0x4010426e, &(0x7f0000000140))


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f00000000c0)='./file0\x00', 0x63)
setreuid(0xee00, 0x0)
r0 = getuid()
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000580)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000140)=0xc)
chown(&(0x7f0000000200)='./file0\x00', 0x0, r2)
setreuid(0x0, r0)
chdir(&(0x7f0000000100)='./file0\x00')
rename(&(0x7f00000003c0)='.\x00', &(0x7f0000000400)='.\x00')


r0 = socket(0x11, 0x3, 0x0)
r1 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
writev(r1, &(0x7f0000000580)=[{&(0x7f00000001c0)='N', 0x1}], 0x1)
r2 = socket(0x0, 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
r3 = openat$vnd(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$VNDIOCSET(r3, 0xc0384600, &(0x7f0000000500)={&(0x7f0000000480)='./file0\x00', 0x56, 0x0, 0x3e})
r4 = socket$unix(0x1, 0x5, 0x0)
unveil(&(0x7f0000000040)='./file0\x00', &(0x7f0000000080)='x\x00')
bind$unix(r4, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
execve(0x0, 0x0, 0x0)
setsockopt(r2, 0x1000000029, 0x35, &(0x7f0000000040)="03000000", 0x4)
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r5, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000040)=[{0x84}, {0x64}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
chmod(&(0x7f0000000240)='./file0\x00', 0x8)
getpeername(r2, &(0x7f0000000000)=@in, &(0x7f0000000040)=0xc)
sendto$unix(r0, &(0x7f0000000140)="b1000504000004000000000007000000331c13fecea10500fef96ec0c72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a421020000ed710fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b1257aea8c500002002fbfe0c2300008abfba0900000008e371a3f8343732051ed6b71d89e0000405f8fffffe13000000", 0xb1, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000080)=[{0x3}, {0x74, 0x0, 0x0, 0x2000}, {0x6}]})
ktrace(0x0, 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000480)=ANY=[])


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f0000000100)={0x10, 0x0, [{&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000433000/0x3000)=nil}, {&(0x7f0000626000/0x2000)=nil, &(0x7f000093c000/0x2000)=nil}, {&(0x7f0000da9000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000e0a000/0x2000)=nil, &(0x7f0000c17000/0x3000)=nil}, {&(0x7f0000b64000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f000062b000/0xf000)=nil, &(0x7f00008bf000/0x1000)=nil}, {&(0x7f00008bf000/0x3000)=nil, &(0x7f0000af4000/0x13000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000601000/0x3000)=nil, &(0x7f0000b08000/0x1000)=nil}, {&(0x7f000064c000/0x2000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {&(0x7f0000633000/0x3000)=nil, &(0x7f0000518000/0x3000)=nil}], './file0\x00'})
r0 = socket(0x1, 0x2, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x8, &(0x7f0000000140), 0x7f, 0x0)
r2 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r2, 0xc028698d, &(0x7f00000001c0))
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0xc0286988, &(0x7f00000001c0))


msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0xb2}})
mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
r0 = socket(0x11, 0x0, 0x0)
sendto$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)
link(0x0, &(0x7f0000001380)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000480)='./file0\x00')
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x0, 0x0)
ioctl$BIOCSRTIMEOUT(r1, 0x8010426d, &(0x7f0000000440)={0xc0000000000000})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
rename(0x0, &(0x7f0000001080)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
syz_emit_ethernet(0x46, &(0x7f0000000080)={@broadcast, @random="ac566789c541", [], {@ipv4={0x800, {{0x9, 0x4, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, @broadcast, @multicast2, {[@timestamp={0x44, 0x10, 0x7, 0x1, 0x0, [{[@rand_addr]}, {}]}]}}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})
r2 = socket(0x18, 0x1, 0x0)
r3 = socket(0x18, 0x3, 0x0)
setsockopt(r3, 0x29, 0x6c, &(0x7f0000000640), 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


mknod(&(0x7f0000000000)='./file0\x00', 0x1ffa, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x1, 0x0)
r0 = open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
flock(r0, 0x2)
close(r0)


syz_emit_ethernet(0x3a, &(0x7f00000001c0)={@local, @local, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x0, 0x0, @local={0xac, 0x14, 0x0}, @remote={0xac, 0x14, 0x0}, {[@generic={0x7, 0x2}]}}, @tcp={{0x0, 0x3, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})


mknod(&(0x7f00000000c0)='./file0\x00', 0x2000, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
ioctl$TIOCGETD(r0, 0x4004741a, &(0x7f00000003c0))


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r0, 0x80606954, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = dup(r0)
ioctl$BIOCSRTIMEOUT(r0, 0x8010426d, &(0x7f0000000000)={0x0, 0x7})
ioctl$BIOCSBLEN(r1, 0xc0044266, &(0x7f0000000100))
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCIMMEDIATE(r0, 0x80044270, &(0x7f0000000200)=0x10001)
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])
readv(r1, &(0x7f0000000080)=[{&(0x7f0000000180)=""/15, 0xf}, {&(0x7f0000000040)=""/17, 0x11}], 0x2)


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
r1 = socket(0x11, 0x3, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000100)=[{0x7c}, {0x7, 0xff}, {0x6, 0x0, 0x0, 0x400}]})
r3 = socket(0x2, 0x4, 0x6)
write(r3, &(0x7f00000000c0)="1fe3", 0x2)
write(r2, &(0x7f0000000240)="32848000"/14, 0xe)
r4 = socket$unix(0x1, 0x2, 0x0)
connect$unix(r4, &(0x7f0000000000)=@file={0xd1653077bafa0115, '\x00'}, 0x2)
writev(r4, &(0x7f00000002c0)=[{&(0x7f0000000140)="6b78fb3e55824866e782e223033000a458c230ab0bc7103f6e1e2f17d98b8a29207f4fcfc9881752ff5259fd5b6f6230c5d858df3bd12b4bc767097d415a522de709ee71ee8c12af84920fb0baae11744eacb4bd3734bd1ccfedecf4772383f7aafd6dfcb62825d599a4637c39513172f42597510feb8a0b98c247513a079d0772a54e79d66cdd573af53f41a2771859a128c9cbed5c6aade8a4f1d7495e790cc7cdc56feff0cc44b27ec1119beb6e555ceed305fb4a84dd868c445e7b62946b410fec5ba311c2602d5c554626f369397b8956cf40c37768", 0xd8}, {&(0x7f0000000280)="ae91a638a9", 0x5}], 0x2)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x2, 0x0)
setsockopt(r1, 0x11, 0x3, &(0x7f0000000340)="02", 0x1)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
socket(0x2, 0x2, 0x0)
sysctl$vm(&(0x7f0000000140), 0x2, 0x0, 0x0, 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980))
setsockopt$inet6_MRT6_DEL_MFC(r0, 0x29, 0x69, &(0x7f0000000200)={{0x18, 0x1}, {0x18, 0x1}}, 0x5c)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
r5 = socket(0x18, 0x3, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x2, 0x0, 0x0, 0x3, 0xffffffffffffffff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
sysctl$hw(&(0x7f0000000000)={0x9, 0x6}, 0x2, 0x0, 0x0, &(0x7f00000010c0), 0x4)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r6 = socket(0x18, 0x2, 0x0)
dup2(r5, r6)


sysctl$kern(&(0x7f0000000140)={0x1, 0x16}, 0x2, &(0x7f0000000080), 0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
r0 = msgget$private(0x0, 0x13a)
msgsnd(r0, 0xffffffffffffffff, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000300), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f00000000c0)=[{0x4, 0x0, 0x20, 0xfffffffe}, {0x87}, {0x16, 0x80, 0xfe, 0xfffffffd}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x6e, &(0x7f0000000000)=ANY=[])


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
setsockopt(r0, 0x1000000000029, 0x9, 0x0, 0x0)


setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000040)="fd0cc085", 0x4)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
clock_settime(0x100000000000000, &(0x7f0000000040))


r0 = socket(0x18, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x802069a6, &(0x7f00000001c0))


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbdf13b9fd812eaa4e713048e69931929648", 0x14)


fsync(0xffffffffffffffff)
mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x5d4a)
r0 = kqueue()
r1 = openat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x0, 0x0)
kevent(r0, 0x0, 0x0, &(0x7f0000000580), 0x65, 0x0)
kevent(r0, &(0x7f0000000140)=[{{r1}, 0xfffffffffffffffe, 0x9f}], 0xd, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000002000/0x1000)=nil, 0x1000, 0x0)
r2 = accept$inet(0xffffffffffffffff, 0x0, 0x0)
sendto$inet(0xffffffffffffffff, 0x0, 0x0, 0x1, 0x0, 0x0)
fcntl$setflags(0xffffffffffffffff, 0x2, 0x0)
ioctl$VT_OPENQRY(0xffffffffffffffff, 0x40047601, 0x0)
poll(&(0x7f0000000000)=[{0xffffffffffffffff, 0x1}, {0xffffffffffffffff, 0x80}, {r2, 0x1}, {0xffffffffffffffff, 0x10}, {r2, 0x1}, {0xffffffffffffffff, 0x20}, {r2, 0x40}, {r2, 0x4}, {r2, 0x80}], 0x9, 0xf6d)
r3 = socket(0x2, 0x2, 0x0)
setsockopt(r3, 0x0, 0x15, 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(r1, 0x80085762, &(0x7f0000000c00)={0x3, 0xffffffff})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
setitimer(0x1, &(0x7f0000000280)={{}, {0xfffffffffffffff9}}, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r4 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000a00), 0x0, 0x0)
readv(r4, &(0x7f0000000800)=[{&(0x7f0000000500)=""/120, 0x68}, {&(0x7f00000002c0)=""/122, 0x7a}, {&(0x7f0000000340)=""/228, 0xe4}, {&(0x7f0000000440)=""/102, 0x74}, {&(0x7f00000004c0)=""/62, 0x3e}, {&(0x7f0000000a40)=""/225, 0xec}, {&(0x7f0000000640)=""/242, 0xf2}, {&(0x7f0000000740)=""/142, 0x8e}], 0x8)


setreuid(0xee00, 0x0)
mprotect(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0)
minherit(&(0x7f0000ffd000/0x2000)=nil, 0x2000, 0x3)
getuid()
mknod(&(0x7f0000000000)='./file0\x00', 0x6000, 0xe02)
r0 = open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
readv(r0, &(0x7f00000001c0)=[{&(0x7f0000000140)=""/18, 0x12}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x61}, {0x5}, {0xe}]})
write(r0, &(0x7f00000006c0)="e506000000000000004aaed75a5a", 0xe)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$inet(0x2, 0x1, 0x0)
recvmsg(0xffffffffffffffff, &(0x7f0000000d80)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000d40)=""/16, 0x10}, 0x0)
setrlimit(0x0, &(0x7f0000000980)={0x42, 0x62})
r1 = syz_open_pts()
syz_open_pts()
writev(r1, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000280)=[{&(0x7f0000000480)=""/131, 0x83}], 0x1)
setsockopt(r0, 0x6, 0x1, &(0x7f0000000040)="60ba1d1e", 0x4)
r2 = socket(0x18, 0x2, 0x0)
write(r1, &(0x7f0000000140)="9cdd730159712a008572b0338d227bef10f05b6095a1fa6e7f376dae690555215825460169418ac014269c206c45882b480879d8b850b094abf41acd507a9c1c8da1cb714c6265b80b042c563cef35ce223780ca228517652cdca4a293fb366d56a652", 0x63)
r3 = socket(0x18, 0x2, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
dup2(r2, r3)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
pipe(&(0x7f0000000100)={<r4=>0xffffffffffffffff})
fcntl$setstatus(r4, 0x4, 0xc0)
setreuid(0xee00, 0x0)
r5 = getuid()
setreuid(0xee00, r5)
getpid()
geteuid()
r6 = semget$private(0x0, 0x3, 0x83)
semop(r6, &(0x7f0000000340)=[{0x0, 0x7}, {0x2, 0x8, 0x800}], 0x2)
r7 = socket(0x800000018, 0x3, 0x0)
shutdown(r7, 0x0)
socket(0x18, 0x3, 0x0)
syz_emit_ethernet(0x4a, &(0x7f0000000440)=ANY=[@ANYBLOB="69e1629b6174aaaaaaaaaabb86dd606b9efb00145000cb69bc83c1677a656ab420666c3e2c6fff020000000000000000000000000001"])


open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
r0 = getpid()
ktrace(&(0x7f0000001d40)='./file0\x00', 0x0, 0x1720, r0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, &(0x7f0000000380)={0x0, 0xffffffffffffffff})


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
sendmmsg(0xffffffffffffffff, &(0x7f00000007c0)={&(0x7f0000000780)={0x0, 0x0, &(0x7f0000000140)=[{&(0x7f0000000180)="b860fe09625ee6793978a575faa1b6c6c1d6c2eca2950e663d39ab1be31a269a39fd7f97e41e178f37a79f00659c2ea9ac56733f7e4e4973c1e6b33ac91343ea3b3f8c5c7b93d5c20ab4211791fe", 0x4e}, {0x0}], 0x2, 0x0}}, 0x10, 0x0)
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f00000002c0)=[{0x80}, {0x6c, 0x6}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f00000002c0), 0x1, 0x0)
fcntl$lock(r0, 0x8, &(0x7f0000000200)={0x0, 0x0, 0xfffffffffffffffe, 0x10001fffffffe, 0xffffffffffffffff})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{0x45}, {0x3d}, {0x8006}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
sysctl$kern(&(0x7f0000000280)={0x1, 0x44}, 0x3, &(0x7f00000003c0)="8b5ea54a413c745995d4a95b979bb64d0541e6a50849f2861cc5f3e014d9ea6bba61da747d3cd9a068b38d0bb67a985e46184f42a6c16a68078392dee63af6e601c0865da92ccdbbf8b85cb74d593a4d771ba5adb1403ae15565ef56d99f35fcc544e7a02a6c038ad8350c06a67bb9150e72e4f7e3084bf8a8cd1f65c4f707722236a4bc53e00f6e41aaea38a0c4e09508e1e439d617879713ed556c9f38b1213fe3ebb3d05a1fb9af890b38975b0a67fee19a5840f6e655d79e6d8596f328b0a7315e826f5b2d2ef536e5c9fa3e6af4a8c312e71e7da86dd5ea55f5a6a153b43941fab0217cbe2a5fbfc598f2f1bdd630558d225116d927d6d4c600418246ac0b6dde68455e73bcbe8a3d", &(0x7f00000002c0)=0x12, &(0x7f0000000300)="6675ce01f40d6aca4f5b680c7e17a4db799bb2480f1b4e922dd582704df696f66891b95981f7d920436699f59f5bcdb142bd08777d3dfee17dabe90c8f0d3defb72a65e0583485bfd0ab622d2267677a928d2d3d84731c57b234e88df06caf4fee4aa32022541c8c057f1c601f54d25fec982caee472cbce44bb86c6d5b25c6ba673915108c6f254cc12f9287a60000fbbf686386e3e", 0x96)
sysctl$kern(&(0x7f0000000240)={0x1, 0x16}, 0x2, &(0x7f0000000500)="acfe4c9d75fdd76eee340fe756a818fc6c6ed00f871fd56979f9de44204a56e7aeff1c6c9ebf1fb01125ec6885af5380d351ccb69968989e66e6635d10451aba8718a607ad90a6299ac184c999222686f94b44a69d0ba257b33fdae408d5d7c54754448247423e004b75c64ebe23277f8ce4a553a803b840bdaf06020698720e2bf3d32a655fcb1da1519cd3da075a07cdda3f86534b3159ec53927184996fece2fd11ed612488494ad1daef0dae61c1eb800356436fc44c47bbf6aaa87e0b781814e54db54bc0576aad1886a78e3251e132e5", &(0x7f0000000600)=0xd3, &(0x7f0000000640)="36c7c1ac79c6da92bcd40e9c8711742ac79f16ebcadeb984515155f56cda4d96f66b86c126128d037b62148fe2049b4a0023c5625deade2f36167a902ad76300256d28bbe1536b04ce87d66d41278745064ee98fc6a068938487bfe4528cf64c5b0d4913d257e3a8be43e476548b977540d9b5a2fe6a359822adf1140c59a9380b1ceb1bb539bac8c5c2a69d8812019661019b60468cd8eb5590880a52ecfd95dd3586bd29c6c62facb5cdec2468effc1973c533abadf898e5990127d69340a4270b2ea518059a8e21", 0xc9)
r1 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0206923, &(0x7f00000001c0))
ioctl$FIONREAD(r1, 0xc0206922, &(0x7f00000001c0))
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106978, 0x0)
open$dir(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
syz_emit_ethernet(0xe, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x2, 0x2, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x1, &(0x7f0000000080)="0315f1d89ec5a317a9357682", 0xc)
connect$unix(r3, &(0x7f0000000000), 0x10)
write(r3, &(0x7f00000000c0)="6bbc4044635cdfa0130442359ce30f1d6397d3e99e3a21cac54252de3f31068e94599964f0992fc4f57a21f3e43840110c5aedadf134eb754e43cfefbf30d1873b41d1b6db5ac9b567031f5f94e299e42815a09a0b895b7d71fbe32bbcc6eb773fd30096f35767d120948e67b7183f75f955cebe0ab31be9a3471867737ede7592cb85a0a3fa080000009b265a129a79ed9980eaaacbcce224abc7b30926aef1d2c9497b96374901fd3f0fa136327cedf27ab77a7bd690a931e870d6576296ea83f54541af73092ebe7575a3899854202d3ae7ed09d9cb3895d29f8722ad1fc4315f2c7a83cfba586bf6cf2b232222ba0315879fcc0c5c729cbafa39551ad6d7bf1fe58fefee90cd34bebbc4ba6faf759e1647ee8384574e91bb29d971700c1f0f2b2c27263a73328833bd4bc5577fd4521ff3ce1257081533ede709c175acf59272ef759399e20f7f3ebedcdb6485ae8b72228ef2a8172601ce45147783ee8e3186f8e0acb23c55df91e99a", 0x16c)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x2}, {0x14}, {0x6}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000340)={0xffffffffffffff09, 0xfffffffffffffffe})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x2, &(0x7f0000000100)=[{0x4d}, {0x14}]})
syz_emit_ethernet(0xe, &(0x7f00000000c0)=ANY=[])
openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2060, 0xcd5331e3)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x200000000000b, &(0x7f0000000240)="8fce3f1335c37b8980230497252b014e9c3df5c9c8a376e1174c022936fa9b22e2017c951fa0840b757af27dafc1a19734d1675d53fa8893a3c3c56c642aa38d96aa9b5d6d2ad565e73efd4859a3d57f23f87d0018e74d9a8a317c6a416598362454ea80d177d038176b7651630f25e065714f00d00ce2a7a66a45f0acec50e7fce45cfef32f47becdb62e0c43ba2e21074db568b0dcffc5f11ebf00da616cea31dd2edfa5fe692dd16574722890206d06d3e23f3c567d70199530f08cdc77f959e3fe3301ee00f9529c3aabfb71fad90ea2a6bb92c54ea7961df3428824644b51a79a93b725508cd9052b8b2c1ffecb9b1c643f991a00000000", 0xfa)
r1 = socket(0x18, 0x1, 0x0)
listen(r1, 0x0)
r2 = openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$PCIOCWRITE(r2, 0xc00c7007, &(0x7f00000005c0)={{}, 0x2})
accept$unix(r1, 0x0, 0x0)
r3 = openat$pci(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$PCIOCWRITE(r3, 0xc00c7007, &(0x7f00000005c0))
ioctl$TIOCSETAW(0xffffffffffffffff, 0x802c7415, 0x0)
open(&(0x7f0000000180)='./file0\x00', 0x200, 0x0)
r4 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x53e, r4)
setuid(0xee01)
stat(0x0, &(0x7f0000000080))
socket(0x11, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f00000000c0)=[{0x15}, {0x5c}, {0x406}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
getgid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0xb2}})
r0 = socket(0x18, 0x1, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
r1 = socket(0x18, 0x2, 0x0)
r2 = socket(0x18, 0x2, 0x3)
setsockopt(r2, 0x1000000000029, 0xa, &(0x7f0000000040)="03e81875", 0x4)
dup2(r2, r1)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f00000000c0)={0x9, 0x1ff}, 0x10)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmsg(r1, &(0x7f0000000ec0)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000))
socket$inet(0x2, 0x3, 0x0)
r0 = socket(0x2, 0x2, 0x0)
select(0x40, &(0x7f0000000140), 0x0, &(0x7f0000000200)={0xffffffffffffffcf}, 0x0)
poll(&(0x7f00000000c0)=[{r0}], 0x1, 0x0)


open(0x0, 0x0, 0x0)
syz_open_pts()
dup(0xffffffffffffffff)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
sendmsg(0xffffffffffffff9c, &(0x7f0000000380)={0x0, 0x0, &(0x7f0000000500)=[{0x0}, {&(0x7f0000000280)="2dbadba001e777029cffa4c50e097be8c63ff9b5dcb94d86ef34528218c83a7225dfc1678301f8daf2edf069ca146ff6c62a635cb68b1741a2f161e220ac3d3c38931de41a015a26028553d4f059ad322d4da1ef5fdadfffacc200c0c980e30f61c975b7a51c43c96dfb489548ecb860284c2b4f38218b1edf181500c2d93075a875", 0x82}], 0x2, 0x0, 0x120}, 0x0)
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000280), 0x0, 0x0)
ioctl$VMM_IOC_INFO(r0, 0xc0185603, &(0x7f0000000300)={0x0, 0x0, &(0x7f00000002c0)})


sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0xd}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000000)={0x2, 0x5, 0x2}, 0x3, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0xa}, 0x3, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000000), 0x6, 0x0, 0x0, 0x0, 0x0)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x1ff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mkdir(&(0x7f0000000000)='./file0\x00', 0x4)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000029, 0x2e, 0x0, 0x0)
setsockopt(r1, 0x1000000000029, 0xa, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x1}})
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
r0 = socket(0x11, 0x3, 0x0)
r1 = dup2(r0, r0)
sendto$unix(r1, &(0x7f0000000340)="b1000504000004000000000001410000331c13fecea10500fef96ec0c72fd3357ae30200004e300300000000f20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc256699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x412, 0x0, 0x0)
open(0x0, 0x70e, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x1, 0x0)
ftruncate(0xffffffffffffffff, 0x0)
r2 = socket(0x2, 0x3, 0x2)
sendto$unix(r2, &(0x7f0000000000)="b1000504600000000000000007000000331c13fecea10500fef9ed06c72fd3357ae320b37b673039d2d236073705ae04be38164991f7accf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139b672f4d33", 0x54, 0x0, 0x0, 0x0)
read(0xffffffffffffffff, &(0x7f0000000240)=""/226, 0xe2)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
syz_emit_ethernet(0x36, &(0x7f0000000000)=ANY=[@ANYBLOB="aaaaaaaaaaaa0000000000000800480000280000000000009078ac1400bbe0000001078749fd5a6d6207ffffffffe000020000000000"])
syz_emit_ethernet(0x4a, 0x0)
sysctl$kern(&(0x7f0000000000), 0x2, 0x0, 0x0, 0x0, 0x0)
sysctl$hw(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSFILDROP(0xffffffffffffffff, 0x80044279, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
socket(0x2, 0x2, 0x0)
sysctl$machdep(&(0x7f0000000080)={0x7, 0xf}, 0x2, 0x0, 0x0, 0x0, 0x0)


r0 = socket$unix(0x1, 0x1, 0x0)
socket(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
r1 = getpid()
ktrace(0x0, 0x1, 0x20, r1)
poll(&(0x7f0000004d40)=[{r0, 0x4}, {}], 0x2, 0x0)


pledge(0x0, &(0x7f00000000c0)='\x00')
openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
connect$inet(0xffffffffffffffff, 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000000)={0xffffffffffffffff})
r0 = syz_open_pts()
close(r0)
r1 = accept$unix(0xffffffffffffff9c, &(0x7f0000000180)=@abs, &(0x7f00000001c0)=0x8)
getpeername(r1, 0x0, &(0x7f0000000240))
sysctl$kern(&(0x7f0000000300)={0x1, 0x16}, 0x2, &(0x7f0000000340)="0e", &(0x7f0000000400)=0x1, &(0x7f0000000800), 0x0)
syz_emit_ethernet(0x126f, &(0x7f00000000c0)=ANY=[@ANYBLOB="aaaaaaaaaaaa00000000000086dd609ded1a12390000c4a4e3434e58d025a6a8a81cf312b8befe8000000000000000000000000000aa00030000000000000101000101000401000401000103000000000100010200000000c7ab6f1eba08bf03d1805fce0ef2ab82f4a065245eccda108bec7cb23f632c993265a4cefeb77b1406d562a47d4b0054943553278b519ed107f62b5c351a8e68d83c1fd85b8e1083556d7fa2fc09a3e823fa940de6eff9ffffffa2dba0d2d9c1b44b47000000"])
sysctl$net_inet_ip(&(0x7f00000000c0)={0x4, 0x2, 0x0, 0x1b}, 0x4, &(0x7f0000000100)="3d7a1499", &(0x7f0000000140)=0x4, &(0x7f0000000180), 0x4)
r2 = openat$bpf(0xffffffffffffff9c, 0x0, 0x1, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
setrlimit(0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, 0x0, 0x462, 0x0)
writev(r3, 0x0, 0x0)
munmap(&(0x7f0000ffb000/0x2000)=nil, 0x2000)
mlock(&(0x7f0000ffd000/0x2000)=nil, 0x2000)
ioctl$BIOCGDIRFILT(0xffffffffffffffff, 0x4004427c, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
r4 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
getsockopt(r4, 0x0, 0x9, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000280)=[{0x81}, {0x35}, {0x812e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])


r0 = socket$unix(0x1, 0x2, 0x0)
r1 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(r1, &(0x7f00000001c0)=[{&(0x7f0000000180)="b1", 0x1}], 0x1)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x1, 0x10, r1, 0x0)
unveil(0x0, &(0x7f00000002c0)='c\x00')
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
sysctl$kern(&(0x7f0000002240), 0x2, 0x0, 0x0, 0x0, 0x0)
ioctl$FIOSETOWN(r0, 0x8004667c, &(0x7f00000000c0))


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
mmap(&(0x7f0000ffb000/0x4000)=nil, 0x4000, 0x6, 0x10, 0xffffffffffffffff, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000140)="67b5b992045c1a7733de71184dc12714990881d0d282bbbb82f88aee3375246d60d056448aeda248819c876f2c6e59c445667afca993a0516665954db86908d70836eed6da0b08d886dfd3ab4c442de33c74d0ff7946a83c180aed511af0d3eff58a00acff7ecc72afce9830fbd4edc05a5b077b39f6b4b7e961ce3c370f2f88a7bfe9e2762ddb30c131b1d20aa39f57ee", 0x91}], 0x1)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = dup2(r0, r0)
ioctl$FIONREAD(r1, 0x8020699d, &(0x7f00000001c0))
writev(0xffffffffffffffff, &(0x7f0000000440)=[{&(0x7f0000000180)="4dfb6b79951845e2cd9668618b36d93df01b8b7d45d0bc640ada53de1096c280bc3fe8a11c5aeea07cc0aca57612f97d4b101b5199f73cd5a5bb955d8f2ab8d018223f7b466cfec2b1a9fb56b65db7afa8570d748d5d8c08785882a940bd45d0984200a1bcd0fac462e146746296242e7342abce5beee86b92b0be65d3aef495a0ec7e2df79837fde3b44ac1773ffd11cf25", 0x92}], 0x1)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x11a}})
r2 = socket(0x18, 0x1, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
setrlimit(0x3, &(0x7f0000000000)={0x7fff, 0x100000})
sysctl$hw(&(0x7f0000000440)={0x6, 0x19}, 0x2, 0x0, 0x0, &(0x7f0000000500), 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x1, &(0x7f00000000c0)=[{0x0, 0x0, 0x0, 0x7fff}]})
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000280), &(0x7f0000000200)=0xc)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0xab42, 0x0, 0x0, 0x0, 0x0, 0x89, 0x7}, 0x0, 0x0, 0x4})
getsockname$inet(r2, &(0x7f00000000c0), &(0x7f0000000140)=0xc)
r3 = socket(0x18, 0x1, 0x0)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r3, &(0x7f00000000c0), &(0x7f0000000600)=0xfffffffffffffdc1)
r4 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmat(r4, &(0x7f0000001000/0x3000)=nil, 0x0)
execve(&(0x7f0000000380)='./file0\x00', 0x0, 0x0)
syz_emit_ethernet(0x12, &(0x7f0000000200)=ANY=[@ANYBLOB="aaaaaaaaaaaaffff0500ffff8847"])


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = getppid()
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000100)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000140)=0xc)
setregid(0x0, r2)
r3 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000424, r3)
setregid(0x0, 0x0)
ktrace(&(0x7f0000000180)='./file0\x00', 0x4, 0x330, r0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0xc0206921, &(0x7f00000001c0))
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x80206919, &(0x7f00000001c0))
ioctl$VT_GETMODE(0xffffffffffffffff, 0x40087603, 0x0)
r4 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r4, 0x8020690c, &(0x7f00000001c0))


r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f00000000c0)=[{{r0}, 0xfffffffffffffffa, 0xb7c61f5c34597ef}], 0x8, 0x0, 0x0, 0x0)
r2 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
dup2(r2, r1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x64}, {0x24}, {0x6}]})
syz_emit_ethernet(0x62, &(0x7f0000001a00)=ANY=[])


mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
setreuid(0xee00, 0x0)
r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000015c0)={<r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000140)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000040)=0xc)
setegid(r2)
setgroups(0x0, 0x0)
r3 = getuid()
setreuid(0xee00, r3)
fchdir(r0)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
open$dir(&(0x7f0000000300)='.\x00', 0x0, 0x0)
open$dir(&(0x7f00000002c0)='.\x00', 0x0, 0x0)
socket(0x11, 0x3, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
r1 = kqueue()
poll(&(0x7f0000000000)=[{}, {r0}, {r1}], 0x3, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x42}, 0x6, 0x0, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000340)={'tap', 0x0})
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000280)=[{0x74}, {0x1d}, {0x6}]})
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[])


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000100), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105727, &(0x7f0000000200)={&(0x7f0000000040)=[{0x26}, {}], 0x2})


r0 = kqueue()
r1 = open$dir(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
kevent(r0, &(0x7f0000000000)=[{{r1}, 0xffffffffffffffff, 0xa1, 0x2}], 0x8c0, 0x0, 0x0, 0x0)
ftruncate(0xffffffffffffffff, 0x0)
kevent(r0, 0x0, 0x0, 0x0, 0x653, 0x0)


syz_emit_ethernet(0x4e, &(0x7f0000000400)={@broadcast, @remote, [], {@ipv6={0x86dd, {0x0, 0x6, "b42f2f", 0x18, 0x0, 0x0, @rand_addr="064e3f71ffb1d85274c02ccb77965ece", @local={0xfe, 0x80, '\x00', 0x0}, {[@hopopts={0x0, 0x1, '\x00', [@generic={0x5, 0x6, "e666bc87a572"}]}], @udp={{0x3, 0x1, 0x8}}}}}}})


mknod(&(0x7f0000000080)='./file0\x00', 0x6000, 0x202)
open(&(0x7f0000000bc0)='./file0\x00', 0x0, 0x0)
mknod(&(0x7f0000000200)='./bus\x00', 0x2000, 0x202)
unlink(&(0x7f0000000080)='./bus\x00')


r0 = socket(0x18, 0x3, 0x0)
getsockopt(r0, 0x29, 0x6c, 0x0, 0x0)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff}, 0xe0ffffffffffffff})
r0 = socket(0x2, 0x2, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001280)={0x0, 0x0, &(0x7f0000001200)=[{&(0x7f0000000180)="bf3b684c5ae963b4567084e096cf973983b85e5df63e013eaa9405095e88157332b4f68e78e0793d3e30417acbf4419893cfd424b75262dc5ade2ab6278ab86672f9ed186987b8c19d9295a17b98020f6002", 0x52}], 0x1}, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(r1, 0xc0206921, &(0x7f00000001c0))
ioctl$FIONREAD(r0, 0x8040691a, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000100)=[{0x5c}, {0xc0}, {0x2006}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


open(&(0x7f0000000080)='./bus\x00', 0x200, 0x0)
mkdir(&(0x7f0000000100)='./file0\x00', 0x0)
setreuid(0xee00, 0x0)
r0 = getuid()
r1 = getuid()
chown(&(0x7f0000000040)='./file0\x00', r1, 0xffffffffffffffff)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000180)={<r2=>0xffffffffffffffff})
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000340)={0x0, <r3=>0x0, <r4=>0x0}, &(0x7f0000000380)=0xc)
setregid(0x0, r4)
setreuid(0xee00, r0)
r5 = socket(0x2, 0x2, 0x0)
r6 = semget$private(0x0, 0x7, 0x3c0)
semop(r6, &(0x7f0000000180)=[{0x3, 0x43, 0x1800}, {0x1, 0xfffe, 0x1800}, {0x0, 0xfd, 0x1000}, {0x1, 0x20, 0x1800}, {0x2, 0x5, 0x1800}, {0x4, 0x9e, 0x1800}, {0x2, 0xfffb, 0x1000}, {0x0, 0x40, 0x3800}, {0x3, 0x8}], 0x9)
semctl$SETALL(r6, 0x0, 0x9, &(0x7f00000004c0)=[0x9, 0x1001])
getsockopt$SO_PEERCRED(r5, 0xffff, 0x1022, &(0x7f0000000200)={0x0, <r7=>0x0, <r8=>0x0}, 0xc)
setreuid(r7, r1)
semctl$IPC_SET(r6, 0x0, 0x1, &(0x7f0000000240)={{0x0, 0xffffffffffffffff, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x2}, 0x0, 0x2000000009, 0xe7})
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000080)={{0x1f, r1, r4, r3, r4, 0x17, 0x100}, 0x3, 0x6137, 0x1})
getsockopt$sock_cred(r5, 0xffff, 0x1022, &(0x7f0000000000), &(0x7f00000001c0)=0xc)
chown(&(0x7f0000000140)='./file0\x00', r0, r4)
chown(&(0x7f00000002c0)='./file0\x00', r7, r8)
recvmsg(0xffffffffffffffff, &(0x7f00000025c0)={0x0, 0x0, &(0x7f0000002540)=[{0x0}], 0x1, 0x0}, 0x0)
open(0x0, 0x0, 0x0)
getpid()
ktrace(0x0, 0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r9 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000934, r9)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f00000001c0)=[{0x15}, {0x84}, {0x8106}]})
syz_emit_ethernet(0x62, &(0x7f0000000140)=ANY=[])


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
open(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$SPKRTUNE(r0, 0x20005302, &(0x7f0000000000))


mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
poll(&(0x7f0000000080)=[{r0}], 0x1, 0x0)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)


setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1003, &(0x7f0000000080)=0x100, 0x4)
writev(0xffffffffffffffff, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000001c0)=[{0x7}, {0x30}, {0xe}]})
open$dir(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
setuid(0xee01)
shmget$private(0x0, 0x4000, 0x0, &(0x7f000055b000/0x4000)=nil)
shmctl$IPC_RMID(0x0, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
truncate(0x0, 0x0)
ktrace(0x0, 0x0, 0x2a12, 0x0)
ioctl$BIOCSETWF(0xffffffffffffff9c, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x0, 0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x37}, 0x4, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x19a, 0x0, 0x2e)
r1 = msgget$private(0x0, 0x0)
msgrcv(r1, 0x0, 0x0, 0x2, 0x1000)


open(&(0x7f0000002600)='./file0\x00', 0x78e, 0x0)
r0 = open$dir(&(0x7f0000000040)='./file0\x00', 0x2, 0x0)
madvise(&(0x7f0000000000/0xc00000)=nil, 0xc00000, 0x2)
pwritev(r0, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)


faccessat(0xffffffffffffffff, &(0x7f0000000000)='./bus\x00', 0x0, 0x0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd02)
close(0xffffffffffffffff)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x2, 0x0)
ioctl$VNDIOCSET(r0, 0x81946467, &(0x7f0000000180)={0x0, 0x0, 0x0})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f00000000c0)=[{0x1}, {0x80}, {0x406}]})
syz_emit_ethernet(0x36, &(0x7f0000000400)=ANY=[])


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$VMM_IOC_WRITEREGS(r0, 0x82485608, &(0x7f0000000040)={0x2, 0x9, 0x80000001, {[0x1752316f, 0x81, 0x5, 0x8, 0x6, 0xfffffffffffffff7, 0x8, 0x2, 0x1f, 0x4, 0x9, 0xfffffffffffffffb, 0x0, 0x9, 0x2, 0x8, 0x10001, 0x8000000000000000], [0xa4, 0xfff, 0x5, 0x800, 0x1f, 0x2, 0x6, 0x6, 0xcb31, 0x7b], [0x5, 0x8, 0x3, 0x3ff, 0x6, 0x0, 0x8001], [0x80000000000000, 0x5927, 0x2, 0x0, 0x3, 0x7ff], [{0x7, 0x3f, 0x8000, 0x1ff}, {0x81, 0x3f, 0x400, 0xf00}, {0xb80, 0x4, 0x20, 0x100000001}, {0x9, 0x10001, 0xffffffc0, 0x9}, {0x1, 0x800, 0xf0, 0x6576}, {0x2, 0xfffffff9, 0x6, 0x401}, {0x3, 0x8001, 0x1, 0x1}, {0x1, 0x7fff, 0x6}], {0x101, 0x100, 0x9, 0x2}, {0xb1ec, 0xcd, 0xb9e, 0x20}}})
syz_emit_ethernet(0x3a, &(0x7f00000004c0)={@broadcast, @random="6c8d0a936b3a", [], {@ipv4={0x800, {{0x9, 0x4, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x0, 0x0, @empty, @broadcast, {[@noop, @timestamp={0x44, 0xc, 0x8, 0x39a3e35ce35b3d5d, 0x0, [{}, {}]}]}}, @udp={{0x0, 0x3, 0x8}}}}}})


kevent(0xffffffffffffffff, 0x0, 0x400, 0x0, 0x4, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
r1 = socket(0x2, 0x4000, 0x0)
r2 = socket$inet(0x2, 0x3, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x1, &(0x7f0000000240)="01000000", 0x4)
socket$inet(0x2, 0x3, 0x0)
ioctl$FIONREAD(r1, 0xc0206923, &(0x7f00000001c0))
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{}, {}, {0x0, 0x0, 0x0, 0xffff8000}]})
r3 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r3, 0xffff, 0x1023, &(0x7f0000000040), 0x190)
openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0)=@file={0x0, '\x00'}, 0x3, 0x0}, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setrlimit(0x0, &(0x7f0000000980)={0x0, 0xfffc})
r4 = syz_open_pts()
close(0xffffffffffffffff)
ioctl$TIOCSETA(r4, 0x802c7414, 0x0)
ioctl$FIONREAD(r0, 0x8020690e, &(0x7f00000001c0))


ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, 0x0)
socket$inet(0x1e, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r1 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
mmap(&(0x7f0000ffb000/0x4000)=nil, 0x4000, 0x2, 0x2010, r0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000140)="67b5b992045c1a7733de71184dc12714990881d0d282bbbb82f88aee3375246d60d056448aeda248819c876f2c6e59c445667afca993a0516665954db86908d70836eed6da0b08d886dfd3ab4c442de33c74d0ff7946a83c180aed511af0d3eff58a00acff7ecc72afce9830fbd4edc05a5b077b39f6b4b7e961ce3c370f2f88a7bfe9e2762ddb30c131b1d20aa39f57ee", 0x91}], 0x1)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = dup2(r1, r1)
ioctl$FIONREAD(r2, 0x8020699d, &(0x7f00000001c0))
writev(0xffffffffffffffff, &(0x7f0000000240), 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x11a}})
r3 = socket(0x18, 0x1, 0x0)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
setrlimit(0x3, &(0x7f0000000000)={0x7fff, 0x100000})
sysctl$hw(&(0x7f0000000440)={0x6, 0x19}, 0x2, 0x0, 0x0, &(0x7f0000000500), 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x1, &(0x7f00000000c0)=[{}]})
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0xab42, 0x0, 0x0, 0x0, 0x0, 0x89, 0x7}, 0x0, 0x0, 0x4})
getsockname$inet(r3, &(0x7f00000000c0), &(0x7f0000000140)=0xc)
r4 = socket(0x18, 0x1, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(0xffffffffffffffff, &(0x7f00000000c0), &(0x7f0000000600)=0xfffffffffffffdc1)
r5 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmat(r5, &(0x7f0000001000/0x3000)=nil, 0x0)
execve(&(0x7f0000000380)='./file0\x00', 0x0, 0x0)
syz_emit_ethernet(0x12, &(0x7f0000000200)=ANY=[@ANYBLOB="aaaaaaaaaaaaffff0500ffff8847"])
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f00000000c0)=[{0x50}, {0x35}, {0x46}]})
writev(r0, &(0x7f00000002c0)=[{&(0x7f0000000240)="e049e64ada6fa45d6bee0bf84a9e", 0xe}], 0x1)


utimes(0x0, 0xffffffffffffffff)
r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000140)="b10005010000009f0500000006010000331c13fece910b00fef96ecfc72fd1357ae3020000693039d2d236acf20beffb54cc164991f7c8cf5f882b2b7be1aab0d44e73fc521fdf953bc3d7b5631405e2f0ad3ebbc257699a1f139b672f335c223e7d0c032bfa896443a42118210000720fd38bfb0000fd54c125191b1257aea8c500002002fbfe0c2300008abfbb0902000000e371a3f8343712051eeab70800000000001000"/177, 0xb1, 0x0, 0x0, 0x0)


kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000240)={0x0, 0x5})
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f00000000c0)='./file0\x00', 0x21e)
chdir(&(0x7f0000000140)='./file0\x00')
mkdir(&(0x7f0000000280)='./file1\x00', 0x0)
r0 = open(&(0x7f0000000040)='./file1\x00', 0x0, 0x0)
mkdirat(r0, &(0x7f00000001c0)='./file1\x00', 0x0)
renameat(r0, &(0x7f0000000140)='./file1\x00', 0xffffffffffffff9c, &(0x7f0000000340)='./file1\x00')


r0 = socket(0x2, 0x1, 0x0)
setsockopt(r0, 0x6, 0x4, &(0x7f0000000140)="aef43c05", 0x4)
setsockopt$sock_int(r0, 0xffff, 0x1, &(0x7f0000000040)=0x200, 0x4)
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
connect$unix(r0, &(0x7f0000000000), 0x10)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
sendmmsg(r0, &(0x7f0000000080)={0x0}, 0x10, 0x0)
socketpair(0x1, 0x0, 0x7, 0x0)
socket(0x0, 0x0, 0x0)
close(0xffffffffffffffff)
r1 = socket(0x18, 0x0, 0x0)
dup2(0xffffffffffffffff, r1)
setsockopt(0xffffffffffffffff, 0x0, 0x2e, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
pipe(&(0x7f0000000000)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
poll(&(0x7f0000000040)=[{r1, 0x1a4}], 0x1, 0x0)
fcntl$setstatus(r1, 0x4, 0x80)
write(0xffffffffffffffff, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
sysctl$hw(&(0x7f0000000bc0)={0x6, 0x6}, 0x2, 0x0, 0x0, &(0x7f0000000d00), 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000000), &(0x7f0000000040)=0xc)
mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x0, 0x810, 0xffffffffffffffff, 0x0)
unlink(&(0x7f0000000000)='./file0\x00')
socket(0x2, 0x3, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd, 0x10000, 0x0, 0x0, 0x4}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x3a, &(0x7f0000000240)=ANY=[@ANYBLOB="ffffffffffff00000000000008004500002c000000000000907800000000ffffffff4e204e20", @ANYRES32=0x41424344, @ANYRES32=0x0, @ANYBLOB="50800000d07800003f000000"])
syz_emit_ethernet(0x0, 0x0)
semop(0x0, 0x0, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x5901)
select(0x40, &(0x7f0000000440)={0xff, 0x8}, 0x0, 0x0, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000100)=[{0x2, 0x7}, {0x3}, {}], 0x3})
symlink(&(0x7f0000000ac0)='./file0\x00', &(0x7f0000000e40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000f40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x4a, 0x0)
socket(0x11, 0x3, 0x0)


sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000540)="9b0709c3eb987ab7fe4189c99e805e6e84d356960798a692992117d6728436ba1bd87f42e3303eac3846520d050712f838130efce33f524b3fa75085f35dfa4dc7e149d4d6d06a3f23616e774c02f1a07bee7385e6664282cb6988f8d9cae75e39a5a11e32e0e6ebd635450b2eba540af7f2aa5dbfbdd900a0da9e274f50acd76b5c567049ef436dbea0d7562f52950fa5ef6ec2bd02adc7f1fe850c081d95dcf4f06a852ab475cca257352828a76e5334be562995e894238b96ca5d4d3f670feac9b4e8aa9bef19525cb6f7e8570b2a374f1408341ed45bb7ad3fb975ffc080e963cb9a8bd949ee0fc6dbceb7d956e658a5673cc947b3e88aa810f8ed7cca10ff010000000000001345daa49507756f49775275ca390b94e85d5a95b8bdacb9429c25483a9275d0da3b561c6adc3c141f26a88016dd6b436218bdbdc9ac0a623855e941dc1872fcb045e0d9df1ecc6357ee21e2b0802cb60eec6a34396ce1e34e8a0bdd5e94723235f0675fad5315e7eecc3e11347f40e67a8c0ae4428f0760c70e1dd7873e27142bbae1a7e44de453a073c799353d46dd81439b115afb2e353e3bb073e3342773216b07e49ca4df0fd2dbe9a8eb3770ea880f76e6f4588ffb7d82693a096344671843a1f2082612b09a507c6e505ff594828b388f9ed85f1602a20561aed73c87e196f4f7859e071fc98111cc9024f790ce68e3f54baaee16ceaa7d01620500"/528, &(0x7f00000002c0)=0x210, 0x0, 0x0)


pipe(&(0x7f0000000140))
open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f0000000440)={&(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, 0x0}}, 0x10, 0x0, 0x0)
select(0x40, &(0x7f0000000040)={0xfd}, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
select(0x2, 0x0, &(0x7f0000000040), &(0x7f0000000080), &(0x7f00000000c0))


r0 = syz_open_pts()
close(r0)
setrlimit(0x8, &(0x7f0000000980)={0xb, 0x54})
r1 = syz_open_pts()
close(r1)
syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000080)={0xf66c, 0x0, 0x9, 0x5577c533, "3c107dae307e08002b4600000000da64612c3300"})
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)


r0 = socket$inet6(0x18, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x8, &(0x7f0000000100), 0x3)


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x3f}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x2000, 0x0, 0x2a)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000180)=[{0xc0}, {0x2}, {0x810e}]})
syz_emit_ethernet(0x26, &(0x7f00000002c0)=ANY=[])


open(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
r0 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = getpid()
ktrace(&(0x7f0000001d40)='./file0\x00', 0x0, 0x1720, r1)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, &(0x7f0000000380))
r2 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, &(0x7f00000009c0))
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r2, 0x0)
ioctl$DIOCMAP(r0, 0xc0106477, &(0x7f0000000140)={0x0})


mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x1012, 0xffffffffffffffff, 0x0)
r0 = syz_open_pts()
fcntl$lock(r0, 0x8, &(0x7f0000000040))


sendmsg$unix(0xffffffffffffffff, &(0x7f0000000640)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000080)=ANY=[@ANYBLOB="18000000ffff000001"], 0x18}, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x33}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
socket(0x18, 0x2, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000100)=[{}, {}, {0x6}]})
readv(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f00000002c0)=""/42, 0x2a}], 0x1)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1400000029"], 0x3e}, 0x0)
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000200)=[{0x7}, {0x3}, {0x8106}]})
syz_emit_ethernet(0x3e, &(0x7f0000000280)=ANY=[])


getrusage(0x0, 0xfffffffffffffffe)


mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x2000, 0x2d87)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
writev(r0, 0x0, 0x0)
writev(r0, &(0x7f00000002c0)=[{&(0x7f0000000080)}, {&(0x7f00000014c0)="20206000019c0a", 0x7}], 0x2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000580)={0x3, &(0x7f0000000040)=[{0x25}, {0x34, 0x0, 0x0, 0xffffffff}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000180)=[{0x0}], 0x1)
fcntl$setstatus(0xffffffffffffffff, 0x4, 0xc0)
open(&(0x7f0000000180)='.\x00', 0x8, 0x10)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r0 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000001000/0x3000)=nil)
shmat(r0, &(0x7f0000001000/0x3000)=nil, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x6)


r0 = kqueue()
kevent(r0, &(0x7f0000000400)=[{{}, 0xfffffffffffffff9, 0x11, 0x4}], 0x8c0, 0x0, 0xfffffffe, 0x0)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000008c0)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmsg(r1, &(0x7f0000000340)={0x0, 0x0, 0x0, 0x0, &(0x7f00000024c0)=""/236, 0xec}, 0x0)
sendmsg(r0, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000200)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000008c0)={<r4=>0xffffffffffffffff, <r5=>0xffffffffffffffff})
recvmsg(r5, &(0x7f0000000340)={0x0, 0x0, 0x0, 0x0, &(0x7f00000024c0)=""/236, 0xec}, 0x0)
sendmsg(r4, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)
close(r3)
fcntl$dupfd(r2, 0x0, r5)


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x1c}, 0x4, 0x0, 0x0, &(0x7f0000001100), 0x4)


syz_emit_ethernet(0x76, &(0x7f0000000040)=ANY=[@ANYBLOB="7fe55d082259aaaaaaaaaaaa86dd60000900004000006e1aa4058b74adad9a4e721f5b293380ff02000000000000000000000000000100010000000000000012000502008d01"])


sysctl$net_inet_esp(&(0x7f0000000040)={0x4, 0x22, 0x2}, 0x4000000000000006, 0x0, 0x0, 0x0, 0x0)


mknod(&(0x7f0000000200)='./file0\x00', 0x2000, 0x1002)
open(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)


r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000002640), 0x1, 0x0)
ioctl$WSKBDIO_COMPLEXBELL(r0, 0x80105702, &(0x7f0000002680))


socket$inet(0x2, 0x0, 0x0)
dup(0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(r0, 0xc0206921, &(0x7f00000001c0))
openat$zero(0xffffffffffffff9c, 0x0, 0x80, 0x0)
socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
syz_open_pts()
close(0xffffffffffffffff)
msgget$private(0x0, 0x0)
dup(0xffffffffffffffff)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
semctl$SETALL(0x0, 0x0, 0x9, 0x0)
open(0x0, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000ffd000/0x1000)=nil, &(0x7f00006e1000/0x3000)=nil}, {&(0x7f0000a29000/0xc000)=nil, &(0x7f000041b000/0x4000)=nil}, {&(0x7f0000acf000/0x11000)=nil, &(0x7f00007a5000/0x3000)=nil}, {&(0x7f0000554000/0x4000)=nil, &(0x7f000042d000/0x4000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000a64000/0x1000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil}, {&(0x7f0000bb2000/0x4000)=nil, &(0x7f0000312000/0x3000)=nil}, {&(0x7f0000a31000/0x3000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000628000/0x2000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f000032e000/0x800000)=nil, &(0x7f0000ffe000/0x1000)=nil, 0x8004}, {&(0x7f0000015000/0x3000)=nil, &(0x7f000015e000/0x2000)=nil}, {&(0x7f0000893000/0x1000)=nil, &(0x7f0000487000/0x2000)=nil, 0x400000000000000}, {&(0x7f000052f000/0x2000)=nil, &(0x7f0000ff3000/0x2000)=nil}], './file0\x00'})
socket$inet(0x2, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000300)=[{&(0x7f0000000140)="f005c71031c1c5f421277b09000000000000007a091a2f47be787538ec7a89ec5ed66daa731ddc384ecc690869a0aa2266affdf772d7a360ee0f15fa664f557bb45071fe9b6d9d28e6e2589000f6a64f370b9e336987d77b38f7aada5309e46a81e0e2efa087aa9f5f89934fdbd2ed96e7234b8972b273e810ca9962a8f461d3a05711a63027321ff62c", 0x8a}], 0x1)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000002c0)={<r1=>0xffffffffffffffff})
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))


mlock(&(0x7f0000ffd000/0x2000)=nil, 0x2000)
sysctl$vm(&(0x7f0000000000)={0x2, 0x8}, 0x2, &(0x7f0000000080)="3cb774c225c9af053b85c3bffcd6228e8686a84423fb039f92a931280d9153c6a9f64122383ae7315eea104f81", &(0x7f0000000140)=0x2d, &(0x7f0000000280), 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x2, &(0x7f00000000c0)=[{0x7}, {}]})
syz_emit_ethernet(0x119, 0x0)
sysctl$hw(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
setgid(0xffffffffffffffff)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
mlock(&(0x7f0000ffb000/0x3000)=nil, 0x3000)


r0 = socket(0x18, 0x3, 0x0)
setreuid(0xee00, 0x0)
r1 = getuid()
seteuid(r1)
setsockopt(r0, 0x1000000029, 0x3c, &(0x7f00000001c0)='\x00\x00\x00\x00', 0x4)


connect$unix(0xffffffffffffffff, &(0x7f0000000040)=@abs={0x1, 0x0, 0x1}, 0x8)
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x3}, 0xc)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000140)={0x1, &(0x7f00000004c0)=[{}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x67, &(0x7f0000000140), 0xc)


mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
unveil(&(0x7f0000000080)='./file0/file0/..\x00', &(0x7f0000000100)='r\x00')
unveil(&(0x7f0000000040)='./file1\x00', &(0x7f00000000c0)='c\x00')
openat(0xffffffffffffff9c, &(0x7f0000000240)='./file0/file0/../../file1\x00', 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x1, &(0x7f00000000c0)=[{}]})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r1, 0x80206932, &(0x7f00000001c0))
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000000c0), &(0x7f0000000240)=0xc)
unlink(&(0x7f0000000000)='./file0\x00')
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000180)={0x2, &(0x7f0000000200)=[{}, {}]})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCIMMEDIATE(0xffffffffffffffff, 0x80044270, 0x0)
open(0x0, 0x0, 0x0)
kqueue()
dup2(0xffffffffffffffff, 0xffffffffffffffff)
syz_emit_ethernet(0x32, 0x0)
setrlimit(0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r2 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
write(r2, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x2, &(0x7f00000001c0)=[{}, {0x6, 0x0, 0x0, 0x4ff1}]})
writev(0xffffffffffffffff, 0x0, 0x0)
sysctl$vfs_ffs(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
close(0xffffffffffffffff)
syz_emit_ethernet(0x36, &(0x7f00000000c0)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @empty, @rand_addr=0xac14ffff}, @tcp={{0x0, 0x3, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})
utimes(0x0, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f00000001c0)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x1, 0x0)
ioctl$VNDIOCSET(r0, 0xc0387200, &(0x7f0000000340)={0x0, 0x0, 0x0})


kevent(0xffffffffffffffff, &(0x7f0000000040)=[{{}, 0x0, 0x0, 0x0, 0x2}], 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x2, 0x0, 0x1e}, 0x5, &(0x7f0000000080)="e33745e84d5ebfb9cc2f7fa3a7f7891721720e69dac610a4fb5eaf3e3c6e1d648a8ca6ebc70f949c442aee9dc79e2cd74f4e1092a2aeba2fbbe28c42903bbf6c161c6f382caf01ada3bc4efb0f6bc50690e5d879fac2492f4a0491b1ea3359aa5c5164ad97ac7c3aaddd498c0f962f5167b69cfdc8287fc34b8138340e60c404a855a58ea5fca343265bc1ed6bd51cd0eef26db847abb2e7b21442c0", &(0x7f0000000000)=0x2, 0x0, 0xfffffdfd)


mlockall(0x1)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
socket(0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
getuid()
getgid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, 0x0, 0x9}, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{}, 0xffffffffffffffff})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000001c0), &(0x7f0000000200)=0xfffffffffffffe50)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0206923, &(0x7f00000001c0))
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r2 = fcntl$dupfd(r1, 0x3, 0xffffffffffffffff)
ioctl$FIONREAD(r2, 0x8004745d, &(0x7f0000000200))
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x8040691a, &(0x7f00000001c0))


r0 = openat(0xffffffffffffffff, &(0x7f0000000100)='./file0\x00', 0x800, 0x0)
close(r0)
mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x0, 0x0)
open$dir(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000400)={<r1=>0xffffffffffffffff})
r2 = dup2(0xffffffffffffffff, r0)
connect$unix(0xffffffffffffff9c, &(0x7f00000000c0)=@file={0x0, './file0\x00'}, 0xa)
r3 = getuid()
seteuid(r3)
r4 = getpid()
ktrace(0x0, 0x1, 0x40000930, r4)
shutdown(r1, 0x1)
poll(&(0x7f0000000080)=[{r2, 0xab6cc3d7ffaa0897}], 0x1, 0x0)
socket$inet(0x2, 0x4000, 0x0)
kqueue()
openat$vnd(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
r5 = openat(0xffffffffffffff9c, &(0x7f0000000040)='.\x00', 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000615000/0x2000)=nil, 0x8}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil, 0x1}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000697000/0x3000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ff7000/0x3000)=nil, 0x4}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f000061a000/0x3000)=nil, 0x100000001}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f000068e000/0x12000)=nil, 0xfffffffffffffffe}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil, 0x5}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000604000/0x3000)=nil}, {&(0x7f000069a000/0x3000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f000034d000/0x2000)=nil, &(0x7f0000693000/0x4000)=nil}, {&(0x7f0000691000/0x2000)=nil, &(0x7f0000ff8000/0x4000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil, 0x1}, {&(0x7f0000ff5000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000614000/0x14000)=nil}], './file0\x00'})
connect$unix(r5, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000380)=[{&(0x7f00000002c0)="dc5e04fb39e84ed2a76610ff3f3a49f99a56534b99b7b9c9e0ddb47c296c7fa35db07e2c4d09c7d6e7df6ce5625bc182b958c173a8500721a103e630e28d930dae15a5301b0d0b107380d3a4e515b4bc9032de245b7bbc8d0caa174202d10bac75bf48c8ca9b2b42fa8203c9aac5116f57c4cc44a40d9ce267ec98b046450528c41d8078ef4243acb4c95eb455c9aa67b70730356f60307f38795020fd4ac3f62c2dfe16df1016d3a3c616bbb8933c7a0ce2a0", 0xb3}], 0x1)
r6 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x10000, 0x0)
ioctl$FIOASYNC(r6, 0x8004667d, &(0x7f0000000040))
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r7=>0xffffffffffffffff})
ioctl$FIONREAD(r7, 0xc0106924, &(0x7f00000001c0))
syz_open_pts()
r8 = kqueue()
close(r8)
kevent(r8, 0x0, 0x6, 0x0, 0xff, 0x0)
syz_open_pts()


r0 = open(&(0x7f0000001700)='./file0\x00', 0x70e, 0x0)
mmap(&(0x7f000000e000/0x2000)=nil, 0x2000, 0x1, 0x10, r0, 0x0)
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x11, r1, 0x0)
ftruncate(r1, 0x8531)
setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)
ioctl$BIOCGFILDROP(0xffffffffffffffff, 0x40044278, &(0x7f00000000c0))
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)


r0 = syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x0, "1d9c1b538cb9a6c0259d4c012252ffd7f564187e", 0xfffffbff})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000280)=[{0x1}, {}, {0x6}]})
syz_emit_ethernet(0x7e, &(0x7f0000000400)=ANY=[])


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r0, 0xc038694e, &(0x7f00000001c0))


socket$inet(0x2, 0x3, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
syz_open_pts()
r0 = socket(0x18, 0x3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
writev(0xffffffffffffffff, &(0x7f0000000740)=[{0x0}, {&(0x7f0000000380)}, {0x0}, {&(0x7f0000000700)="a0c8b1040e0748ad6cffdedb8674a80a3bbf907a36b7fa91693a6cbbc9b3630f", 0x20}], 0x4)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x8080691a, &(0x7f0000000100))


r0 = syz_open_pts()
write(r0, &(0x7f0000000100)='@', 0x1)
ioctl$TIOCSETAW(r0, 0x802c7415, &(0x7f0000000480)={0x0, 0x0, 0x0, 0x0, "e90bc613db3473d5180201a03b13887b043580a5"})
execve(0x0, 0x0, 0x0)


mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2010, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f00000019c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000480)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f00000006c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000580)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
unlink(&(0x7f0000000a80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f00000007c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000a40)='./file0\x00')
mknod$loop(0x0, 0x2000, 0x1)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$WSMUXIO_LIST_DEVICES(0xffffffffffffffff, 0xc1045763, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
sysctl$vm(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
recvmsg(r0, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
execve(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000b80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000f80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mkdirat(0xffffffffffffff9c, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "01000000d000"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x54}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000040), 0x3, 0x0, 0x0, &(0x7f0000000180)="76b0353a558bf248c78c8502fcf9fd08fa1588f254df98bdc2703864ecc0ce3671c0907259201eb7cb962ee12d9706a2d4177565da48e3cdade50516597f477ca5ea18253c1441678346ddaa98e46b28e2226a296c0fd773959eaad9d65d33cdbf523a06ed457ed3e00f52851f90c14f54ec03a2a5ff8d88b9", 0x79)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f0000000040)=0xfffffffc)
writev(r0, &(0x7f0000000580)=[{&(0x7f0000000440)="38a218fa614f35646b977002109b49a8389eeb5f5921d33b331e4bf8f32c4bdb9c41098f792ee307796473049e8e8b264e0a", 0x32}, {&(0x7f00000005c0)="9410b9d9331202fe5fd80cc06d851e11f225cb4f0000", 0x16}], 0x2)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
r1 = socket(0x18, 0x2, 0x0)
r2 = socket(0x18, 0x2, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
syz_extract_tcp_res(&(0x7f0000000040), 0xfffffff7, 0x1)
dup2(r1, r2)
writev(r2, &(0x7f0000000080)=[{&(0x7f0000000240)="d9c50597b3312f266a0c995fa69dd09f963ec82628f58f2f5a5f063154395deeb26b4dcdfe30f8b08bb59ed6ddbf3d3dc834044b668d99bcc98a6f158c2b653784d1a021f89906ccec86d142c590085b294b22638b9b209380097bf2c46b88edef53f18e6b9913672cf95d3bcd5bc16b35612eb80d60c38317331556e8388f8aead3c1b95ec3ce0f5e73b3bdd6c4f117ec", 0x91}], 0x1)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{0x0, 0x0, 0x0, 0x8000000}, {0x7}, {0xffff, 0xc1}]})
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


openat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x10242, 0x0)
pipe(&(0x7f0000000100)={<r0=>0xffffffffffffffff})
close(r0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
select(0x40, &(0x7f0000000000)={0xffffffffffffffff}, 0x0, 0x0, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffff9}, 0x0, 0x0, 0x0)


sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x2}, 0x4, &(0x7f0000000080)="909105d1", &(0x7f0000000140)=0x4, &(0x7f0000000180), 0x0)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
setreuid(0xee00, 0x0)
r0 = getuid()
chown(&(0x7f0000000180)='./file0\x00', r0, 0xffffffffffffffff)
symlink(&(0x7f0000000340)='./file0/file1\x00', &(0x7f0000000380)='./file0/file1\x00')
r1 = getuid()
setreuid(0x0, r1)
chmod(&(0x7f0000000080)='./file0\x00', 0x2ea)
rename(&(0x7f00000003c0)='./file0/file1\x00', &(0x7f0000000400)='./file0\x00')


openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
fchmodat(0xffffffffffffffff, 0x0, 0x9f, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(0xffffffffffffffff, 0x80085761, 0x0)
open$dir(0x0, 0x0, 0x0)
mknod(0x0, 0x100000000205f, 0x2802)
socket(0x11, 0x0, 0x0)
ktrace(0x0, 0x0, 0x0, 0xffffffffffffffff)
r0 = socket(0x18, 0x3, 0x3a)
openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x100, 0x0)
ioctl$FIOSETOWN(r0, 0x8004667c, &(0x7f0000000240)=0x8001)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x0, 0x0})
write(r0, &(0x7f0000000000)="7696e5f3d1f18c37cea8615ac7cf", 0xe)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000240)={0x3, &(0x7f00000000c0)=[{}, {0x1, 0x0, 0x0, 0x2}, {0x6}]})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
openat(0xffffffffffffffff, &(0x7f0000000180)='./file0\x00', 0x800, 0x1a0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000100)=[{0x5c, 0xf9}, {0x1, 0x0, 0x0, 0x6}, {0x16}]})
write(r1, &(0x7f00000001c0)="d9537abde93d050cdd16b13f742a", 0xe)
r2 = socket(0x2, 0x4001, 0x0)
r3 = fcntl$dupfd(r2, 0x2, 0xffffffffffffffff)
close(r3)
socket$unix(0x1, 0x1, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0xff0a, 0x0, 0x37)


symlink(0x0, &(0x7f0000001440)='./file0\x00')
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
sysctl$kern(&(0x7f0000000300)={0x2, 0x9}, 0x2, 0x0, 0x0, &(0x7f0000001440)="00000100", 0x4)


r0 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1, 0x0, 0x0)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
getpeername(r0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r1 = socket(0x2, 0x1, 0x0)
bind(r1, &(0x7f0000000000), 0x10)
r2 = dup(r1)
listen(r2, 0x0)
connect$unix(r0, &(0x7f0000000000), 0x10)
sendmsg$unix(r0, &(0x7f0000000480)={0x0, 0x0, 0x0}, 0x1)


r0 = socket(0x18, 0x2, 0x0)
r1 = dup(r0)
setsockopt(r1, 0x1000000000029, 0xb, &(0x7f0000000080), 0x4)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000240), 0x0)


ioctl$FIONREAD(0xffffffffffffffff, 0xc0106978, 0x0)
open$dir(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
syz_emit_ethernet(0xe, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x1, &(0x7f0000000080)="0315f1d89ec5a317a9357682", 0xc)
connect$unix(r0, &(0x7f0000000000), 0x10)
write(r0, &(0x7f00000000c0)="6bbc4044635cdfa0130442359ce30f1d6397d3e99e3a21cac54252de3f31068e94599964f0992fc4f57a21f3e43840110c5aedadf134eb754e43cfefbf30d1873b41d1b6db5ac9b567031f5f94e299e42815a09a0b895b7d71fbe32bbcc6eb773fd30096f35767d120948e67b7183f75f955cebe0ab31be9a3471867737ede7592cb85a0a3fa080000009b265a129a79ed9980eaaacbcce224abc7b30926aef1d2c9497b96374901fd3f0fa136327cedf27ab77a7bd690a931e870d6576296ea83f54541af73092ebe7575a3899854202d3ae7ed09d9cb3895d29f8722ad1fc4315f2c7a83cfba586bf6cf2b232222ba0315879fcc0c5c729cbafa39551ad6d7bf1fe58fefee90cd34bebbc4ba6faf759e1647ee8384574e91bb29d971700c1f0f2b2c27263a73328833bd4bc5577fd4521ff3ce1257081533ede709c175acf59272ef759399e20f7f3ebedcdb6485ae8b72228ef2a8172601ce45147783ee8e3186f8e0acb23c55df91e99a27c8bc1358", 0x171)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x40}, {0x6, 0x0, 0x0, 0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0xfffffffffffffe53)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000540)={0x3, &(0x7f00000001c0)=[{0x3d}, {0x61}, {0x8106}]})
syz_emit_ethernet(0x3e, &(0x7f0000000240)=ANY=[])


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f0000000080)={&(0x7f0000000040)=[{0x8}, {0x24}, {0x24}], 0x3})
ioctl$WSMOUSEIO_GETPARAMS(r0, 0x80105727, &(0x7f0000000080)={&(0x7f0000000040)})


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000440)={0x2, &(0x7f00000000c0)=[{}, {0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x3e}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8efdb4cf71c37082", &(0x7f0000000000)=0x2, 0x0, 0x37)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000080)={0x0, 0x0, 0x4})
sysctl$kern(&(0x7f0000000080)={0x1, 0x31}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)


mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x2802)
ktrace(&(0x7f0000000100)='./bus\x00', 0x0, 0x0, 0xffffffffffffffff)
chmod(0x0, 0x3a)
chown(&(0x7f0000000040)='./file1\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
bind$unix(r0, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
bind$unix(r0, &(0x7f0000000080)=@abs={0x0, 0x0, 0x0}, 0x8)
mknod(&(0x7f0000000100)='./file0\x00', 0x1ffa, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x0, 0xffffffffffffffff)
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x10201b1a)
open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x1, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
kqueue()
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, &(0x7f00000001c0))
r2 = socket(0x2, 0x2, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x74}, {0x2c}, {0x16}]})
ioctl$FIONREAD(r2, 0x80206919, &(0x7f00000001c0))
r4 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r4, 0x8020690c, &(0x7f00000001c0))
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000140)=[{0x3}, {0xc0}, {0x812b}]})
syz_emit_ethernet(0x56, &(0x7f0000000000)=ANY=[])
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)


mknod(&(0x7f0000000180)='./bus\x00', 0x2000, 0x450c)
r0 = open(&(0x7f00000002c0)='./bus\x00', 0x2, 0x0)
ioctl$WSMUXIO_INJECTEVENT(r0, 0x80185760, &(0x7f0000000140))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
pread(r0, &(0x7f0000000400)="d0b88f95ca7c031a2a49b63b047ef0a885a6df0980527e78", 0x18, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000001c0)=[{0x61}, {0x4c}, {0x6}]})
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[])


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
dup(r0)
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
sysctl$net_inet_divert(&(0x7f0000000100), 0xb, &(0x7f0000000280)="a7c1290f17722447b2c63e743f6b379fa5267a394a5d94db9417b6982f519b111f61ad994119ba843799517c2ddf4c65594fb3b55a5fce717f619f904ce7b41e4296cf777a1db4747703440100000023e48310b779f9619c7642d6d7f500000000000000000000000000000000c37a11ae4dbe56deeb1ccae6d8e73f8976b460abc78bfdf1bf11c3ec2956f559e2ae95b19752a20f358e90edd96264cbc18906750f34e7e595d09e4e313414f688d6388b713904a7996cc92a328db185299eeabc8e35147498451c4a84a9d41bf693affdc27f4569379570f4", &(0x7f0000000180)=0x67, &(0x7f0000000640)="e2714be05c6a432bfcb43ba70e2bb9e6add925cf34d00e465191e199efee4898bfe502dcc0a3e3fd0cc0e7969055dcb470ddd2f263dfb8065cbf63d41b2a29e4f92695a2dae1e619ba2b0ccd1e605cd2827beb6ddaf6b579cccebb6d267a74d6af9f2cddd1eb38180245caf3e0f240c5f1ee52a05a63c446df6149316cc2e17b775698e9114250d85ec893fbd204889e5c3f37ee5894227fa7b36a2803d9c558953caa2452fff1bf82f49299d2fd07d8a464fd351d966782d21806ba5be9dc66d7dd572cdae3822888010771550dd55b3014876e2537e33b838b12b10d843be49e4cfc3b3f04a60088dd3cc3fbdc16864e028753d898f0bc0bd6e20f96274d743755332aebcec91d4f490000000000000000628c7c526f7de4f21b6260bacfe436d6eb63a96ded0b0f29cbc8ea2a7d2760b1fdf551506810d63132c72c14be5ffcc53ca339aea237797e863010f33b057982b6825dbdef1ce4425ae7d1234ad5cb69", 0xee)
syz_emit_ethernet(0x12, &(0x7f00000002c0)={@local, @local, [{}], {@generic={0x88a8}}})
msgrcv(0x0, 0x0, 0x0, 0x0, 0x0)
r1 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmat(r1, &(0x7f0000001000/0x3000)=nil, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {&(0x7f0000ff9000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffd000/0x1000)=nil, 0x80000001}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f0000ffc000/0x1000)=nil}, {&(0x7f0000003000/0x2000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x2000)=nil}], './file0\x00'})
sysctl$net_inet_tcp(0x0, 0x0, &(0x7f0000000000)="9b1809ffffffffffffff7f473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6fd74c94d1b44", &(0x7f0000000040)=0x3c, 0x0, 0x0)


r0 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
sysctl$vfs_nfs(&(0x7f0000000280)={0x7, 0x2, 0x2}, 0x5, 0x0, 0x0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
r2 = socket$inet(0x2, 0x0, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
setsockopt$inet_opts(r2, 0x0, 0xd, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
r3 = semget$private(0x0, 0x1, 0x54)
semctl$SETALL(r3, 0x0, 0x9, &(0x7f0000000000)=[0x8001, 0x5, 0x94, 0x8001])
getuid()
getgroups(0x6, &(0x7f0000000240)=[0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff])
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
setsockopt$sock_timeval(r0, 0xffff, 0x1005, &(0x7f0000000180)={0x0, 0x4}, 0x10)
syz_emit_ethernet(0x36, &(0x7f00000000c0)=ANY=[@ANYBLOB="ffffff88a7c84301000000bddf9ee23bf80035000000000000000000000034c3043d21d1c3fb", @ANYRES32=0x41424344])
semop(0x0, &(0x7f0000000100)=[{0x0, 0x28}, {0x3, 0xffff}], 0x2)
sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000000)="9b1809ffffffffffffff7f473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6fd74c94d1b44", &(0x7f0000000040)=0x10011, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
syz_open_pts()
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x3e, 0x0)
ioctl$BIOCVERSION(0xffffffffffffffff, 0x40044271, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8020699f, &(0x7f0000000100))


setrlimit(0x8, &(0x7f0000000980)={0xb, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0xf66f, 0x0, 0x9, 0x5577c530, "3c007dae307e08002b4600005900da64612c3300"})
writev(r0, &(0x7f00000004c0)=[{&(0x7f00000000c0)="bf0909b98732e43ae0ee63c33dd9cb7de67102649ec14a5cde", 0x19}], 0x1)


sysctl$hw(&(0x7f0000000080)={0x6, 0x2}, 0x2, &(0x7f0000000180), 0x0, 0x0, 0x0)


r0 = socket(0x2, 0x2, 0x0)
connect$unix(r0, &(0x7f0000000340), 0x10)
r1 = syz_open_pts()
close(r1)
r2 = socket$inet(0x2, 0x3, 0x0)
getsockopt$inet_opts(r2, 0x0, 0x3, 0x0, 0x0)
poll(&(0x7f0000000040)=[{r1, 0x2}], 0x1, 0x0)
openat$wsdisplay(0xffffffffffffff9c, &(0x7f0000000200), 0x20, 0x0)
writev(r0, &(0x7f0000000300)=[{&(0x7f0000000400)="f30e8141c25525564416c01d2df74948348070af23598f62127838152a643c1a9a3c4cdd10ea9aed465b3ca33d1e6d7b9e4cf0509254f831be564bd0fdae3444e3ba3ab1795570405d4161072f1663191eb3bab90d3f1194f4a575cdf6bac25eaa621438860b406c1e55287ef2b11cc8370c561a05ea4a206a1e007c11766204ebcfcd72d38d0800000000000000705dc9a187b7753d2429e4b7f1c9d9cd95751b530308da05f8d5bbcaf3d27dceb454d3443f1e4ad23a89228f13633d5a8fbed24c7faa0ff6ec4f43889c6d6131800b8fcdd2c19b4b0a7959787c583abcf86615d4af20ae8272581bb0bf696b658abe02cb8ecd8b4f743e0da2e853404554fe13f0129df8d4641adc216a02bff87d2389ad299c46c4c605e8a4c4bfdcede6f9d61d6cb268fbf91052ded32653d09a746ca8aa38e06eda0000000000", 0x13c}], 0x1)
r3 = socket$inet(0x2, 0x2, 0x0)
sysctl$net_inet_divert(&(0x7f0000000000)={0x4, 0x11, 0x2}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0xa}, 0x3, &(0x7f0000000080), 0x0, 0x0, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
mknod(&(0x7f0000000040)='./file0\x00', 0x2950, 0x13d4)
r4 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$VNDIOCSET(r4, 0xc0384600, &(0x7f0000000140)={&(0x7f00000000c0)='./file0\x00', 0xcb, 0x0})
openat(0xffffffffffffff9c, 0x0, 0x0, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x200000000000c, &(0x7f0000000040), 0x8)
sendmmsg(0xffffffffffffffff, &(0x7f0000000080)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f00000002c0)=ANY=[@ANYBLOB="14"], 0x18}}, 0x10, 0x0)
sendmmsg(r0, &(0x7f0000000000)={0x0}, 0x10, 0x0)
r5 = open(&(0x7f00000001c0)='./file0\x00', 0x2e1, 0x0)
r6 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
pwritev(r6, &(0x7f0000000600)=[{&(0x7f00000000c0)="95", 0x1}], 0x1, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x1, 0x10, r6, 0x0)
openat(0xffffffffffffffff, &(0x7f0000000100)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0, 0x2015, r5, 0x0)
msync(&(0x7f0000ffa000/0x4000)=nil, 0x4000, 0x6)
shmget(0x0, 0x4000, 0x0, &(0x7f0000ffc000/0x4000)=nil)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
r1 = fcntl$getown(r0, 0x3)
setpgid(r1, 0x0)
sendmsg$unix(0xffffffffffffff9c, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000380)=[{0x1d}, {0x1}, {0x406}]})
syz_emit_ethernet(0x4e, &(0x7f0000000140)=ANY=[])


mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0xc0e99db6de761f86, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
r0 = open$dir(&(0x7f00000001c0)='./file0\x00', 0x1, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000e00)=[{&(0x7f0000000080)="c3778fe486fa8f9f05ce4bfcaad7868e4bd7872ff0597773fa1e061cebd702547202798b96c0a24deae72d0db883bac94c4761e84558e6ca6270794d9b5eb06bb75ce478a7f5a6d622", 0x49}], 0x1)
ioctl$FIONREAD(r0, 0xc0106978, &(0x7f00000000c0))


getgroups(0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
setegid(0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff})
getgroups(0x0, 0x0)
semget$private(0x0, 0x0, 0x20)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd, 0xfffffffffffffffd}, 0x0, 0x0, 0x0)
fchflags(r0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x2, 0x3, 0x0)
connect$unix(r1, &(0x7f0000000000), 0x10)
sendmsg(r1, &(0x7f0000001ec0)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000000)=[{0x84}, {0x14}, {0x8106}]})
syz_emit_ethernet(0x62, &(0x7f0000000140)=ANY=[])


openat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x10242, 0x0)
rename(&(0x7f0000000280)='./file0\x00', &(0x7f00000002c0)='./file1\x00')
mknod(&(0x7f0000000280)='./file1\x00', 0x0, 0x0)
r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0xd6)
writev(r0, &(0x7f00000000c0)=[{&(0x7f0000000280)='#!', 0x10}, {&(0x7f0000000000)="8d6bb85551ec8430877ae32fe9bbe42cc8f2147a3eba8e1969f0435119cf4c071c8aee7ef2921be5d7d4796c5566c95989acb3d185587234186e96b8fde9ffac51de05a87b8b893e2abd154dd886eafbe03881d25b7b13b4c32227fc9e5a86a06f59f701322b3a109a13436e486b0a", 0x6f}], 0x2)
execve(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x8})
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000380)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
sendmsg$unix(r0, &(0x7f00000018c0)={0x0, 0x0, &(0x7f00000003c0)=[{&(0x7f0000000500)="a9a8a9595e236830adcecc2832a2dae3682dc973f131335fc3580cecc90d0a098b1538fb7417e137c89fa8f19a2ba68fac1cf2494c8ed88e91af80cb3820101f5411255b4ed57b3429f1ec3346c2452de0dc241ae19e3cf35fc70d4a4f484855683c7e38cb1822c5aaba19227f79e6d7cf48e813329fd1a52fcfc6b48aeaf523f3ecfe0889d0fb10", 0x88}, {&(0x7f0000000200)="2f17d594d3ed826047", 0x9}], 0x2, &(0x7f0000000000)=ANY=[@ANYBLOB="10000000ffff000001"], 0x10}, 0x40a)


ioctl$FIONREAD(0xffffffffffffffff, 0x80206913, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000080)=[{0x25}, {0x44}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000300)=ANY=[])
sendmsg$unix(0xffffffffffffffff, &(0x7f0000002a40)={&(0x7f0000000000), 0x10, 0x0}, 0x0)
r1 = socket(0x2, 0x2, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000695000/0x3000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f00005fd000/0x1000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f00006a7000/0x1000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f0000218000/0x4000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f00002e5000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000376000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000041d000/0x1000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ff8000/0x4000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil, 0x3}], './file0\x00'})
writev(0xffffffffffffffff, &(0x7f0000000180)=[{&(0x7f0000000000)="9da8e3e9ed", 0x5}], 0x1)
bind(0xffffffffffffffff, &(0x7f0000000080)=@in6={0x18, 0x2}, 0xc)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
open$dir(&(0x7f0000000040)='./file0\x00', 0x8, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = syz_open_pts()
poll(&(0x7f0000000000)=[{r2}], 0x1, 0x0)
syz_open_pts()
syz_open_pts()
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)
r3 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
dup2(r3, r1)
sendmsg$unix(r1, &(0x7f0000002a40)={0x0, 0xffffffffffffff89, 0x0, 0x6e, 0x0, 0x700000000000000}, 0x0)


sysctl$net_inet_divert(&(0x7f0000000040)={0x4, 0x2, 0x102, 0x3}, 0x4, 0x0, 0x0, 0x0, 0x0)
setitimer(0x0, &(0x7f0000000140)={{0x0, 0xffffffffffffff7f}, {0x0, 0x5}}, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
readv(r0, &(0x7f0000000300)=[{&(0x7f00000000c0)=""/169, 0xa9}], 0x1)
getitimer(0x0, 0x0)
accept$unix(0xffffffffffffffff, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x18, 0x3, 0x0)
setsockopt(r1, 0x1000000029, 0x3c, 0x0, 0x0)
socket(0x18, 0x1, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, 0x0, 0x9}, 0x0)
socket(0x2, 0x2, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000440)={0x4, 0x18, 0x6, 0x9}, 0x4, &(0x7f0000000480)="9b1809c3218b07fcfe4189c99e805e6e84d356960798a692992117d6728436ba1bd87f42e3303eac3846528d050712f838130efce33f523ba44765f5f6915b2227390ed95bd9dc6d4dc7f149d4d6d06a3f23616e773302d9cae75e39a5a11e32e0e6ebd635450b2eba540af7f2aa5dbfbdd900a0dad2b74f50acd76b5c567049ef436dbea0d7562f52955af8d4ab84c513252ddd139b5f5cd5c2bd02adc7f1fe850c00000000000000062abb9fa45ac78568e1cb54238fbab475cca257352828a76e5334be562995e894238b96ca5d4d3e670fa0cc791dfc4415030910fa64eac9b4e8aa9bef19525cb6f7e8570be65bb7ad3fe963cb9a8bd949ee334db1ccf73db06b5947b3e88aa810f8ed7cca10ff0d0000000000001345daa49507756f49775275ca390b94e85d5a952000b9429c75d0da3b561c6adc3c141f26040000006b436218bdbdc9ac0a623855e941dc1872fcb045e0d9df1ecc6357ee21e2b0802cb60edd0300723221f06715e7eecc3e0760c70e1dd7873e27142bbae1a7e44de453a073fe3426f334b80f043ba9136d57c799353d46dd81439b111a511a288bee5dfb2e353e3bb073e3342273216b07e49ca4df0fd2dbe9a8eb377010ee678aad0bd8c7fb7d82693a096344671843a1f2082612b2ff237c6e505ff5f5ba932954d73c630fd2791f833a1da5af0704f687e196f4f7859e071fc98111cc9024f790ce16ceaa427d0104e39789d9100000", &(0x7f0000000a40)=0x210, 0x0, 0x0)


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000000)=[{0x20}, {0x80}, {0x8106}]})
syz_emit_ethernet(0x36, &(0x7f0000000240)=ANY=[])


sendmsg$unix(0xffffffffffffffff, &(0x7f0000002a40)={&(0x7f0000000000), 0x10, 0x0}, 0x0)
r0 = socket(0x2, 0x2, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sendmsg$unix(r0, &(0x7f0000002a40)={0x0, 0xffffffffffffff89, 0x0, 0x6e, 0x0, 0x700000000000000}, 0x0)


symlink(0x0, &(0x7f0000001440)='./file0\x00')
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
sysctl$kern(&(0x7f0000000300)={0x2, 0x8}, 0x2, 0x0, 0x0, &(0x7f0000001440)="00000100", 0x4)


seteuid(0xffffffffffffffff)
setuid(0x0)


madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
socketpair(0x1, 0x2, 0x0, &(0x7f0000001640)={<r0=>0xffffffffffffffff})
recvmmsg(r0, &(0x7f0000001dc0)={0x0}, 0xb, 0x0, 0x0)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff, 0x192}, 0xe0ffffffffffffff})
socket(0x2, 0x2, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001280)={0x0, 0x0, &(0x7f0000001200)=[{&(0x7f0000000180)="bf3b684c5ae963b4567084e096cf973983b85e5df63e013eaa9405095e88157332b4f68e78e0793d3e30417acbf4419893cfd424b75262dc5ade2ab6278ab86672f9ed186987b8c19d9295a17b98020f6002", 0x52}], 0x1}, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
setrlimit(0x8, &(0x7f0000000980)={0x7})
r0 = open(0x0, 0x611, 0x0)
openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r0, 0xc2585601, &(0x7f0000000040)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000ff6000/0x9000)=nil, &(0x7f0000ffc000/0x1000)=nil}, {&(0x7f0000ff8000/0x2000)=nil, &(0x7f0000fef000/0x11000)=nil}, {&(0x7f0000ff4000/0x1000)=nil, &(0x7f0000ffb000/0x3000)=nil, 0x4}, {&(0x7f0000fec000/0x4000)=nil, &(0x7f0000feb000/0x9000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ff2000/0x3000)=nil}, {&(0x7f0000feb000/0x4000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {&(0x7f0000ff9000/0x1000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {&(0x7f0000ff0000/0x1000)=nil, &(0x7f0000fec000/0x1000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ff4000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000f8c000/0x3000)=nil}, {&(0x7f0000fe9000/0xf000)=nil, &(0x7f0000fee000/0x12000)=nil}, {&(0x7f0000fea000/0x4000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000fee000/0x10000)=nil, &(0x7f0000c2b000/0x3000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000e35000/0x2000)=nil}], './file0\x00'})
ioctl$PCIOCREAD(r0, 0xc0187009, &(0x7f00000002c0))
r1 = syz_open_pts()
close(r1)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
open(0x0, 0x80, 0x0)
r2 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000480), 0x1, 0x0)
r3 = dup(r2)
ioctl$WSKBDIO_SETMODE(r3, 0x80045713, &(0x7f0000000400)=0x1)
chdir(0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000080), 0xc)
r4 = semget$private(0x0, 0x4000000009, 0x51f)
semop(r4, &(0x7f0000000440)=[{0x3, 0x7}, {0x1, 0x3, 0x1800}, {0x2, 0x8, 0x1000}, {0x4, 0x9, 0x1000}, {0x0, 0x7, 0x800}, {0x3, 0x3f}], 0x6)
ioctl$BIOCSETWF(r3, 0x80104277, &(0x7f0000000340)={0x1, &(0x7f0000000300)=[{0xf8, 0xfd}]})
sysctl$kern(0x0, 0x0, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1c, 0x0, 0x0)
semop(r4, &(0x7f0000000180)=[{0x1, 0x1, 0x1000}, {0x2, 0x4, 0x1000}], 0x2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000080)=[{}, {0x5c}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000300)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000400)=[{0x50}, {0x4}, {0x812e}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x11a}})
syz_emit_ethernet(0x3e, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000000)={0x6, 0xb, 0x2}, 0x5, &(0x7f0000000500), 0x0, 0x0, 0x0)
r0 = socket(0x18, 0x1, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000))
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
fcntl$lock(r1, 0x9, &(0x7f0000000000)={0x0, 0x0, 0xeffffffffffffffb, 0x10002ffffffff, 0xffffffffffffffff})
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
setrlimit(0x3, 0x0)
sysctl$hw(&(0x7f0000000440), 0x2, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000280), &(0x7f0000000200)=0xc)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0xab42, 0x0, 0x0, 0x0, 0x0, 0x89, 0x7}, 0x0, 0x0, 0x4})
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000140)=0xc)
socket$inet(0x2, 0x4, 0x5)
socket(0x18, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f0000000340), 0x0)
openat$wsdisplay(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$WSDISPLAYIO_GETEMULTYPE(0xffffffffffffffff, 0xc014575e, 0x0)
shmat(0x0, &(0x7f0000003000/0x2000)=nil, 0x0)
execve(0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x9, 0x51})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r1, 0x80047460, &(0x7f00000000c0)=0x3)
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)
writev(r0, &(0x7f0000000040)=[{&(0x7f0000000140)='H', 0x1}], 0x1)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000180))
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSETD(r1, 0x8004741b, &(0x7f0000000140)=0x7e10a2f)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, 0x0)
socket$inet6(0x18, 0x5, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x20530c)
open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
r2 = socket(0x2, 0x1, 0x0)
r3 = dup(r2)
shutdown(r2, 0x1)
ioctl$TIOCSTSTAMP(r3, 0xc0207534, &(0x7f00000001c0))
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
chmod(&(0x7f0000000300)='./file0\x00', 0x80)
open(&(0x7f0000000140)='./file0\x00', 0x10000, 0x10b)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
recvfrom$unix(r2, &(0x7f0000000200)=""/240, 0xf0, 0x1001, &(0x7f0000000040)=@abs={0x0, 0x0, 0x2}, 0x8)
r4 = socket(0x18, 0x2, 0x0)
close(r4)
socket(0x6, 0x2, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r5 = socket(0x18, 0x3, 0x0)
connect$unix(r5, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


socket$unix(0x1, 0x1, 0x0)
sendto(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x2000, 0x0)
unveil(0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7", 0xe}], 0x1)
openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
r0 = socket(0x18, 0x3, 0x0)
getsockname$inet(r0, &(0x7f0000000080), &(0x7f0000000000)=0xc)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000080)=[{0x48, 0x0, 0x0, 0x20}, {0x48, 0x0, 0xff}, {0xe6, 0x0, 0x0, 0xfffffffe}]})
syz_emit_ethernet(0x126, &(0x7f0000000140)=ANY=[])
r1 = socket(0x800000018, 0x2, 0x0)
bind$unix(r1, &(0x7f0000000080)=@abs={0x0, 0x7}, 0x1c)


open$dir(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0xb, &(0x7f0000000080)='\x00\x00\x00\x00', 0x4)
setreuid(0xee00, 0x0)
r2 = getuid()
setreuid(0xee00, r2)
setsockopt(r0, 0x1000000029, 0xd, &(0x7f0000000040)="ebffcb92964800"/20, 0x14)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000140)=[{0x64}, {0x60}, {0x812e}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f00000000c0)="b211d7170d816685c8e360f2fa41c1a0946988b272d2dd3dc90142a84231a746e337b372e93320cff6669cbe7868de45ed3fc33719ca6df71ecec8a918458b2c10a1f8c6", 0x44)
r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000180), 0x1, 0x0)
r1 = dup2(r0, r0)
ioctl$WSKBDIO_GETMAP(r1, 0x80047476, &(0x7f0000000100)={0x0, 0x0})


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}], 0x1, 0x0}, 0x2)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)


setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931", 0x11)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f0000000040)={&(0x7f0000000000)=[{}, {}], 0x2})
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
r1 = dup(r0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0xc0}, {0x61}, {0x16}]})
write(r0, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xe)
open(0x0, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
syz_extract_tcp_res(0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)


kqueue()
r0 = kqueue()
r1 = openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
kevent(r0, &(0x7f0000000040)=[{{}, 0xfffffffffffffffd}, {{}, 0xfffffffffffffffe}, {{0xffffffffffffff9c}, 0xfffffffffffffffa}, {{0xffffffffffffff9c}, 0xfffffffffffffffb, 0x11}, {{}, 0xfffffffffffffffb}, {{0xffffffffffffff9c}, 0xfffffffffffffff9, 0xd5, 0x10}, {{r1}, 0xfffffffffffffffe}], 0x9, 0x0, 0xe9ea, &(0x7f00000002c0))
accept$unix(0xffffffffffffff9c, &(0x7f0000000180)=@file={0x0, ""/260}, &(0x7f0000000300)=0x106)
r2 = kqueue()
r3 = openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
kqueue()
kevent(r2, &(0x7f0000000040)=[{{}, 0xfffffffffffffffd}, {{}, 0xfffffffffffffffd}, {{0xffffffffffffff9c}, 0xfffffffffffffffa}, {{0xffffffffffffff9c}, 0xfffffffffffffffb, 0x40}, {{}, 0xfffffffffffffffb}, {{0xffffffffffffff9c}, 0xfffffffffffffff9, 0xd5, 0x10}, {{r3}, 0xfffffffffffffffe}], 0x9, 0x0, 0xe9ea, &(0x7f00000002c0)={0x0, 0x3})
r4 = kqueue()
r5 = openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
kevent(r4, &(0x7f0000000040)=[{{}, 0xfffffffffffffffd}, {{}, 0xfffffffffffffffe, 0x0, 0x0, 0x1}, {{0xffffffffffffff9c}, 0xfffffffffffffff8}, {{0xffffffffffffff9c}, 0xfffffffffffffffb, 0x11}, {{}, 0xfffffffffffffffb}, {{0xffffffffffffff9c}, 0xfffffffffffffffa, 0xd5, 0x10}, {{r5}, 0xfffffffffffffffe, 0x82}], 0x9, 0x0, 0xe9ea, &(0x7f00000002c0))
r6 = msgget$private(0x0, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x6000, 0x100)
execve(&(0x7f0000000000)='./file0\x00', &(0x7f0000000280)=[&(0x7f0000000040)='-,^[/..[:\x00', &(0x7f0000000100)='-^!/[(-[\x00', &(0x7f0000000140)='://.]))&{(\x00', &(0x7f0000000180)='(#\x00', &(0x7f00000001c0)='\x00', &(0x7f0000000200)=':$-\xb7\x00', &(0x7f0000000240)='-k%-.\xae]$\x00'], &(0x7f00000003c0)=[&(0x7f00000002c0)='#{@@\x00', &(0x7f0000000300)='\\(\\-+\x00', &(0x7f0000000340)='!-)*\x00', &(0x7f0000000380)=')\x00'])
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x5}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r7 = socket(0x18, 0x2, 0x0)
setsockopt(r7, 0x1000000000029, 0xb, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
r8 = socket(0x18, 0x1, 0x0)
dup2(r7, r8)
setsockopt(r8, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
msgrcv(r6, &(0x7f0000001540), 0x1008, 0x2, 0x800)
msgsnd(r6, &(0x7f0000001480)=ANY=[@ANYBLOB="0100000000000000d6bf9b46140ec404b2f6c443fa7edc74654cbe4025f66c59ac4ae332be1cebc3416ea053a90b3f467e4730bbeb1b63c15016e4d313925221f680d037d7ebb4e5b2e9bcd739085f3d0ca3d485b2f9c1a3ec26d333b39fba09bad33ffefea801a7e801e8843c97fb161c0de812dc4c88b9a7c1497433b6cbf96f09002b3895c979baa01963882b4ab1420176ce07b5c0476d48f1354f5eb0c81c42661fc55200"], 0xa7, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000001140)=[{0x81}, {0x3c}, {0x6}]})
syz_emit_ethernet(0x5e, &(0x7f0000000040)=ANY=[])


r0 = open(&(0x7f0000000300)='.\x00', 0x0, 0x0)
mkdirat(r0, &(0x7f0000000340)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38/\x00', 0x0)
mkdirat(r0, &(0x7f0000000000)='./file0\x00', 0x0)
mkdirat(r0, &(0x7f0000000440)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//file0\x00', 0x0)
r1 = open(&(0x7f0000000040)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//../file0\x00', 0x0, 0x0)
r2 = fcntl$dupfd(r1, 0x0, r0)
renameat(r2, &(0x7f00000004c0)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//file0\x00', 0xffffffffffffffff, 0x0)
rename(&(0x7f0000000540)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//../file0\x00', &(0x7f00000005c0)='./file0/file0\x00')
rename(&(0x7f0000000100)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//file0\x00', &(0x7f0000000180)='./file0\x00')
recvmsg(r1, &(0x7f0000000a00)={&(0x7f0000000b40), 0xff, &(0x7f0000000940)=[{&(0x7f00000001c0)=""/114, 0x72}, {&(0x7f0000000640)=""/202, 0xca}, {&(0x7f00000003c0)=""/76, 0x4c}, {&(0x7f0000000740)=""/88, 0x58}, {&(0x7f00000000c0)=""/20, 0x14}, {&(0x7f00000002c0)=""/48, 0x30}, {&(0x7f00000007c0)=""/145, 0x91}, {&(0x7f0000000880)=""/181, 0xb5}], 0x8, &(0x7f00000009c0)=""/8, 0x8}, 0x40)
openat(r1, &(0x7f0000000240)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38/\x00', 0x200, 0x0)


writev(0xffffffffffffffff, &(0x7f0000000740)=[{&(0x7f0000000040)="dd", 0x1}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0x37, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)


open(&(0x7f0000000480)='./file0\x00', 0x200, 0x4ebfac6bbaf796d)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000200)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000240)=0xc)
setregid(0xffffffffffffffff, r1)
setgroups(0x0, 0x0)
setreuid(0xee00, 0x0)
r2 = getuid()
setreuid(0x0, r2)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x33}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x24, 0x0, 0x37)


setitimer(0x0, &(0x7f00000000c0)={{0x100000000}, {0xffffffff}}, 0x0)


pipe2(&(0x7f0000000380), 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "0100012d29fb00"})
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, &(0x7f0000004e80), 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc1206949, 0x0)
r0 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x0, 0x0, 0x0)
r1 = syz_open_pts()
close(0xffffffffffffffff)
syz_open_pts()
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
readv(0xffffffffffffffff, 0x0, 0x0)
setrlimit(0x0, &(0x7f00000000c0)={0xffffffff00000003, 0x8000})
sysctl$vfs_nfs(&(0x7f0000000000)={0xa, 0x2, 0x2}, 0x3, &(0x7f00000000c0), 0x0, 0x0, 0x0)
writev(r1, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(0xffffffffffffffff, 0x8020699f, 0x0)
ioctl$FIONREAD(r0, 0x8040691a, &(0x7f00000001c0))
symlink(&(0x7f0000000900)='.\x00', &(0x7f0000000240)='./file0\x00')
readlink(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
sysctl$net_inet_ah(&(0x7f0000000000)={0x4, 0x1e, 0x2}, 0x4, 0x0, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000300)={0x2, &(0x7f00000000c0)=[{}, {0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4f}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000000)=0x4, 0x0, 0x37)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047466, &(0x7f0000000200)=0x5)
ioctl$TIOCSBRK(r1, 0x2000747b)
readv(r0, &(0x7f0000000040)=[{&(0x7f0000000100)=""/207, 0xcf}], 0x1)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
link(0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000100)={0x4, 0x2, 0x0, 0x21}, 0x4, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x2, 0x7)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r1 = syz_open_pts()
close(r1)
r2 = syz_open_pts()
writev(r1, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)
ioctl$TIOCSETA(r2, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0x0, 0xffffffbf, "0000c6f26461c094f4ffffffff00"})
readv(r2, &(0x7f0000000280)=[{&(0x7f0000000600)=""/131, 0x83}], 0x1)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f00000001c0)=[{}, {}, {0x8001, 0x0, 0x4}]})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001780)={0x0, 0x0, &(0x7f0000001500)=[{&(0x7f00000001c0)="cac73ce119f42809f7c30824a593555ffe", 0x11}], 0x1, 0x0, 0xc8}, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r3 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
read(r3, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r4 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r4, 0xc038694e, &(0x7f00000001c0))
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000140)={0x0, 0x8001, 0x7fff, 0x40049c, "d88c07ea0000f9bdca0988d1155c000900", 0xffffffff})
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000001c0)={{0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x18f}, 0x8000000042})
socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
setrlimit(0x6, &(0x7f00000000c0))
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000000)={{0x0, 0x0, 0x0, 0xffffffffffffffff}, 0x0, 0x0, 0xffffffffffffffff, 0x0, 0x4, 0x0, 0x0, 0x7})
socket(0x2, 0x2, 0x0)


openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)
poll(&(0x7f0000000380)=[{}], 0x1, 0xffff)
r0 = socket(0x1, 0x1, 0x0)
r1 = dup2(r0, r0)
mknod(&(0x7f0000000000)='./file0\x00', 0x1ffa, 0x0)
r2 = open(&(0x7f00000001c0)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x1, 0x0)
ioctl$VNDIOCSET(r2, 0xc0387200, &(0x7f0000000340)={0x0, 0x0, 0x0})
r3 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r3)
r4 = msgget$private(0x0, 0x0)
pipe2(&(0x7f0000000000), 0x0)
msgsnd(r4, &(0x7f00000000c0)=ANY=[@ANYRES32], 0x1f, 0x800)
msgctl$IPC_RMID(r4, 0x8000000)


open$dir(&(0x7f0000001240)='.\x00', 0xee29e94d96024fa4, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000680)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f00000000c0)=[{0x80}, {0x87}, {0x26}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
r0 = open(&(0x7f00000002c0)='./bus\x00', 0x2, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)={0x3, 0x7fffffff})
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x30, 0x0, 0x57d, 0x0)
kevent(r1, 0x0, 0x0, &(0x7f0000000600), 0x2, 0x0)
ioctl$WSMUXIO_INJECTEVENT(r0, 0x80185760, &(0x7f0000000140))


r0 = socket$inet(0x2, 0x0, 0x0)
setsockopt(r0, 0x0, 0x1f, 0x0, 0x0)
ioctl$VMM_IOC_RUN(0xffffffffffffffff, 0xc2485607, 0x0)
socket(0x18, 0x2, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
mprotect(&(0x7f00004d2000/0x1000)=nil, 0x1000, 0x4)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0xffcc)
msgctl$IPC_SET(0x0, 0x1, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x3, 0x0, "01000000d000"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000040), 0x3, 0x0, 0x0, &(0x7f0000000080)="4f1d4c6344b80ed788b6a4515248df3aa745bb992c574ab4cdf5587145812eab4a988f7fafd7a01d99776d988908cd186b51f34f8c15ffa0c685ad4116c783959eff4278384b4000384dbb1c2aaeff10b4135529a1da6fda67c67469d954be811b25ec5521559154c586eefff122009f659cd3e27e98a3241495005f102d9101d158284c0ee3250aa7c11042330de22a299ab00894fdc9bac6042d", 0x4)


mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0xd02)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r0 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
preadv(r0, &(0x7f0000000000)=[{&(0x7f0000000c80)=""/4107, 0x100b}], 0x1, 0x0)


open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r0, 0xffff, 0x1, &(0x7f0000000040), 0x4)
r1 = dup(r0)
listen(r1, 0x0)


sysctl$vm(0x0, 0x0, &(0x7f0000000040)="c06d154be3aee5f8787f8b9cda7554335b763bb5deea5ccecb4d1b57a9f6fa18e47fc7b119db587e58811e666e84a806495b45c36164bd5b135280243ed0a01466056e93082876ba33ee8cf2b0b3907f236f38175101000000d7e39544aea098d19ee63d03cbf92380dbe9045381", 0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b100050460000000000000000010000000000000cea10500fef900000000d3357ae320b37b673039d2d236073705ae04be38164991f7c8cf5f882b297be1aa5b236deb51e2f0ac7ebbc257699a5f139b672f4d335d223e7d026ba8af630037282102000000720fd38bfbb770c1f5a872c881ea6e69e0bb7600000000000200361b1257aea8c5000020020000000000008abfba0900000008e371a3f8343712051eadb71d89e000040781e4b2c0", 0xad, 0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b100050400000400000000000700", 0xe, 0x0, 0x0, 0x0)
r0 = socket(0x11, 0x3, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
sendto$unix(r0, &(0x7f0000000000)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)


nanosleep(&(0x7f0000000080)={0x0, 0x40000000000000}, 0xfffffffffffffffe)
r0 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1000, 0x0, 0x0)
syz_emit_ethernet(0x2e, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}, 0xe0efffffffffffff, 0x2000000000})
r1 = socket(0x2, 0x2, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r2, 0xc018696c, &(0x7f00000001c0))
ioctl$FIONREAD(r1, 0x8040691a, &(0x7f00000001c0))


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x27ff1, 0x0, 0x1, 0x5773c548, "10327e7be2df67de208c8bdaa22c31e1ff00"})
writev(r0, &(0x7f00000000c0)=[{&(0x7f00000009c0)="1913371a7464fd4f5a420c4fcecaf125779f43cb3f5bb4f0a59f3947abd5b4375a1b4778a2948a3e0e7aeb5a1750e9f58481cf1391b1088d3d404d9531144aa223745ae5f0c3d3f8f36d3d433fb342b0b14b8c6b28a6c4c187e58592c9b7ccedf9fac1b8290a6ac81df213bb92983b4d1716c45a8b1efdb117230033c3554d9a56e54274d728d99e1c9163c1111619dd7f72a3a7a3ad3cadbc82f1f604dee919b666d329ade6df06c9558bb560f39095d0bd9d4f8ab1805eaa706ac6f601c79942e6912e2578132f7bb6f17f0ee74202aeab12e3e0986ac686e20baf89e031f6f071a5211e528707302b2b983c9166efecd45c47ff61bbaee124096491c37ea14b692a0ef6b6513dcea55fdc958c54aee1b672c4bec4181a2c5a06474423b39b3d41fcd4a0b3b3c796b9ca7d5a0556c44f7eead5e50b66d7be30a66b2118f9b61165842a52cb8fd0a9f3c791934436fcb4e08f63f45e6fe0ef03a4f97844b9f10112bbd3e0edb6ca7a5e98ddcbe1e01419729b385276b7826522000ef9a9c8bd82702504595bec73e20e72201abeae542e87f02edbb5106d1449d9397bff06324a4fa9e5d7dd37fad5b050d8c53a08604353c23c4b4ea2d1b4d552511e29782e7791c893343f7a354a04dd3b5446f431ad7279dc28", 0x1d5}], 0x1)


r0 = syz_open_pts()
fcntl$lock(r0, 0x9, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1000300000000})
flock(r0, 0x3)
flock(r0, 0x1)
syz_open_pts()
syz_open_pts()


munmap(&(0x7f0000400000/0xc00000)=nil, 0xc00000)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x200, 0x0)
mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0, 0x10, r0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0x0, 0x7fffffff, 0xfffffffe, 0xfffffff8, "0900f4ad2ae298560000000000fffffffffff700"})
writev(r0, &(0x7f0000000500)=[{&(0x7f0000000e40)="cdb2ad61ad64f8cbd40672bca315e26911f5b4f347b8c792cbfdb4ef908b282b1ed47b7a5ca377cab5b3f8d8b8bbd5cb4877551bc2dc495e4939811216917a5a81aaacec7eba7d9bf6abb8f5cbf0119776986e3bd86301cf8043cae8b951c9249b702b41829c770fd7fc0d7ee34460d81fc75ec29a6dbdeb769a51f1df011e7bd192cb13e39597007789629dd923aa4ff1640b0a7030e67e804f49f656c1f4dd7dfd1fd46bea2e5049eff79936dee78ff55c9986233db6e20ec6295cc24cc54a673a57cf9691b910cce90dd0f573afa6dbfd886db6d8f4a56c11c0ae5af4855d478414039bb8dcb7d86cf9537f8abcdb0fd7e0abb38ec0556e495ea1667b6cd3353411fcf950bbbe9cb7f2fbeb34329c81357b6cdfa3788a6696845a0db16bdb406d4f090e671ef11b8890345ba2e7a094912be55f1f6f669a2cc489f9264c789e56dcaf7073659dcfabd5489feec768ac66484afd2e1b74eefbab6d1ecaa5c76e648461a3a5f5b0b1f8a0fe42e34e2516dae628457a2ed5b4b87c237d4ac63851379058dec7371dc6f51bb6bbe84e335d4509f242871066ef4b7d5cb5a93ad5acf8a118d6702db6f75cf49c232eb20eada800a4283fdebe0c2b5d721ddd9c93192cfa9b777e6eac6b08aac493d93813c17ab67cfb1d0207247feb37ecc3c2d57acba029ec1acd73895bc529a341657d7eca7c91b0cbd439c35b50047b95c7e5f67000286ca9d885e08a93d4c8fe7b6ae210675ad323c5e847d7ff5021fd0a75b75b648e3a3c99560698c93b9cba0a7727458539dd79ba5769ab18859adf9cebdfd680b857645b607bde6f5a414aca2e732baabecca7d4034544253d57ff6e951a59c8f5aff6faef7b60b74f830033b7bc2258cc196b37c0ae65e8318a6b0e6dfa925542ccbc45e488ad9135df52150fafa752523427268156470831473542cfdd0a3287acbf230611a741484dc741b06e1a337a7bd7408db8ab94adeded534e023b4835af38c28533e6b5d9027ed8ea8241a04eb5bb1aaa41b67eb5bbe447bcf989c6b1540aa68c8e9912931d7990861cc55a9612b33985d6115ad2984ec3d3511bea981fe37b9d9ee77cde1b1d28baf486e36224bc4290f62465228be64b09", 0x320}], 0x1)
writev(r0, &(0x7f00000003c0), 0x1d)


socket$inet(0x2, 0x2, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {}, {0x2, 0x0, 0x0, 0x40804}]})
ioctl$DIOCMAP(0xffffffffffffffff, 0xc0106477, &(0x7f00000000c0)={0x0, r0})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
r1 = socket(0x18, 0x2, 0x0)
close(r1)
kevent(0xffffffffffffffff, &(0x7f00000000c0)=[{{}, 0x0, 0x61}], 0x4, 0x0, 0x2, 0x0)
r2 = socket(0x800000018, 0x3, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r1, &(0x7f0000000180)=@abs={0x0, 0x0, 0x2}, 0x8)
r3 = open$dir(&(0x7f0000000080)='.\x00', 0x0, 0x0)
r4 = dup(r3)
mknodat(r4, &(0x7f0000000240)='./file0\x00', 0x2000, 0x204)
r5 = open$dir(&(0x7f0000000080)='.\x00', 0x0, 0x0)
open$dir(&(0x7f0000001180)='./file0\x00', 0x0, 0xa2)
openat(r5, &(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r6 = socket$unix(0x1, 0x5, 0x0)
open$dir(&(0x7f0000000100)='./file0\x00', 0x40, 0x40)
r7 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f00000003c0), 0x0, 0x0)
dup2(r6, r7)
mmap(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x0, 0x10, 0xffffffffffffffff, 0xfffffffffffff000)
open(&(0x7f00000001c0)='./file0\x00', 0x80, 0x86)
ioctl$WSDISPLAYIO_DELFONT(0xffffffffffffffff, 0x8058574f, &(0x7f0000000140)={'./file0\x00', 0x40, 0x10001, 0x6de, 0x1, 0xffff0ea9, 0x6, 0x3f, 0x2, 0x1, 0x1, 0x6})
write(r0, &(0x7f0000000080), 0x0)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000080)='\x00\x00\x00\x00', 0x4)
r1 = socket(0x2, 0x3, 0x0)
dup2(r0, r1)
setsockopt(r1, 0x1000000029, 0xc, 0x0, 0x0)


sysctl$kern(&(0x7f0000000240)={0x1, 0x4d}, 0x2, 0x0, 0x0, 0x0, 0x0)
r0 = socket$inet(0x2, 0x2, 0x0)
getsockopt$inet_opts(r0, 0x0, 0x1d, 0x0, 0x0)
msgget(0x3, 0x30)
truncate(&(0x7f00000001c0)='./file0\x00', 0x7fffffffffffffff)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f00000001c0)=[{0x14}, {0x6c}, {0x106}]})
syz_emit_ethernet(0x1046, &(0x7f0000001e80)=ANY=[])


openat$vmm(0xffffffffffffff9c, &(0x7f0000000800), 0x0, 0x0)
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)
ioctl$VMM_IOC_READREGS(0xffffffffffffffff, 0xc028756b, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
socket(0x1, 0x2, 0x0)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040), 0x0)
setsockopt(0xffffffffffffffff, 0x1000000029, 0xc, &(0x7f0000000080), 0x0)
mknod(&(0x7f0000000000)='./bus\x00', 0x3a0914c44f7b202d, 0x504)
open(&(0x7f0000000040)='./bus\x00', 0x10005, 0x0)
ktrace(&(0x7f00000010c0)='./bus\x00', 0x0, 0x0, 0x0)


socket$inet6(0x18, 0x3, 0x0)
socket(0x18, 0x3, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
getsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206982, &(0x7f00000001c0))
socket(0x2, 0x2, 0x0)
socket(0x2, 0x0, 0x0)
socketpair(0x18, 0x3, 0xfa, &(0x7f00000004c0))
open(0x0, 0x0, 0x0)
getpid()
socket(0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
syz_open_pts()
r0 = socket(0x18, 0x3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000140)="67b5b992045c1a7733de71184dc12714990881d0d282bbbb82f88aee3375246d60d056448a", 0x25}], 0x1)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x8080691a, &(0x7f0000000100))


sysctl$net_inet6_ip6(&(0x7f0000000000)={0x4, 0x18, 0x29, 0x36}, 0x4, 0x0, 0x0, &(0x7f0000000040)="bcf02f1785a92e9ee0f5bbed4165c6be33", 0x11)
syz_emit_ethernet(0x2e, &(0x7f00000000c0)={@local, @random="f644322eee7f", [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x1, 0x0, @broadcast, @remote={0xac, 0x14, 0x0}, {[@lsrr={0x83, 0x3}]}}, @icmp=@mask_reply}}}})
msgget$private(0x0, 0x425)
syz_extract_tcp_res$synack(&(0x7f0000000040)={0x41424344, <r0=>0x41424344}, 0x1, 0x0)
syz_emit_ethernet(0x14b, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x13d, 0x0, 0x1}, @tcp={{0x2, 0x1, r0, 0x41424344, 0x1, 0x0, 0x13, 0x4, 0x2, 0x0, 0x233, {[@generic={0x2, 0xd, "96c729637cae4fa49c1558"}, @sack_perm={0x4, 0x2}, @sack={0x5, 0x1a, [0x4, 0x0, 0x40000001, 0xde5, 0x2, 0xffffffff]}, @timestamp={0x8, 0xa, 0xb018, 0x8}, @generic={0x4, 0x2}]}}, {"d1c2f0bfe2d0786ca28e44289f59aba04d62ff16e6bb47f1cd981d0cf5f225560531db5a3a6c3cb3d5ac50e0eec7423f3ef5e3c4a13f81f14f843a32b529e4649b57d581159522ddf03a6cabf358af4e1ae7ab79a9aac6417859ae29d8de08ba3da1e6387381a61f166b78d7ae58ccd15a08555c8e7db3e261cbba4f565ff3567edfcacd1a43a2f80b44a3727c2f46723f3826d9842357f4d467cb2e24ed586547d107e74cfe46502dde741762fe8ad6742200cf5fd16fcdadae4fd744b730286383e0444647e948151cb63c5c12b79f75a37762e3f013f189799eb699"}}}}}})
syz_emit_ethernet(0x9e, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x90, 0x0, 0x1}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x1, 0x0, 0x12, 0x4, 0x2, 0x0, 0x233, {[@generic={0x0, 0xd, "96c729637cae4fa49c1558"}, @sack_perm={0x4, 0x2}, @sack={0x5, 0x16, [0x0, 0x0, 0x0, 0x0, 0xffffffff]}, @timestamp={0x8, 0xa, 0xb018, 0x8}, @generic={0x4, 0x2}]}}, {"d1c2f0bfe2d0786ca28e44289f59aba04d62ff16e6bb47f1cd981d0cf5f225560531db5a3a6c3cb3d5ac50e0eec7423f3ef5e3c4"}}}}}})


openat$bpf(0xffffffffffffff9c, &(0x7f0000000700), 0x0, 0x0)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x70e, 0x0)
mmap(&(0x7f000000f000/0x2000)=nil, 0x2000, 0x0, 0x8010, r0, 0x0)
getsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
kqueue()
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x5, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x8981, 0x0)
openat$tty(0xffffffffffffff9c, &(0x7f0000000040), 0x80, 0x0)
ioctl$TIOCSETVERAUTH(0xffffffffffffffff, 0x8004741c, &(0x7f0000000080)=0x2)
r1 = semget$private(0x0, 0x1, 0x8a)
semctl$SETALL(r1, 0x0, 0x9, &(0x7f0000000680)=[0x9])
semop(r1, &(0x7f0000000140)=[{0x4, 0x200, 0x1000}, {0x4, 0x201, 0x1000}, {0x0, 0x1000}, {0x0, 0x7a5}, {0x3, 0xff72, 0x1000}, {0x1, 0xdb, 0x800}, {0x0, 0x0, 0x800}, {0x3, 0xa, 0x1000}], 0x8)
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x26, 0x8}, 0xfffffffffffffffd, 0x2})
semctl$GETALL(r1, 0x0, 0x6, &(0x7f00000004c0)=""/195)
r2 = getuid()
seteuid(r2)
openat$vnd(0xffffffffffffff9c, &(0x7f00000001c0), 0x10, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x51fd)
r3 = open(&(0x7f0000000240)='./file0\x00', 0x0, 0x101)
close(r3)
r4 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r4, 0x6, 0x10, &(0x7f0000000000)="00000001", 0x4)
setsockopt(r4, 0x6, 0x10, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
setsockopt(0xffffffffffffffff, 0x10006, 0x0, 0x0, 0x0)
setuid(0xffffffffffffffff)
syz_open_pts()


r0 = socket(0x2, 0x3, 0x2f)
r1 = dup(r0)
setsockopt$inet_opts(r1, 0x0, 0x22, &(0x7f0000000040)="fd0cc085", 0x4)
sendto$unix(r0, 0x0, 0x0, 0x0, &(0x7f00000001c0)=@abs={0x0, 0x0, 0x2}, 0x8)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x0, 0x0})
r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
setsockopt$inet_opts(r1, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
dup2(r1, r0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00004100000000", 0x8)


open(&(0x7f0000000140)='./file0\x00', 0x78e, 0x0)
r0 = getpid()
ktrace(&(0x7f0000001d40)='./file0\x00', 0x0, 0x1720, r0)
pledge(&(0x7f0000000000)='(*--+^-:\'+{-\x00', 0x0)


fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
getpid()
sendmsg(0xffffffffffffffff, 0x0, 0x0)
open(0x0, 0x0, 0x0)
r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r0, 0x80085761, &(0x7f00000000c0)={0x3})
ioctl$WSMUXIO_INJECTEVENT(r0, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x100000000000000, 0x10000000000001}})


mknod(&(0x7f0000000500)='./file0\x00', 0x1000, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
open$dir(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000001c0)={0x0, 0x0})
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1002, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x8040691a, &(0x7f00000001c0))
sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f00000001c0)="55f8f5782087a072a82ec35f78d14780f518", 0x12)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc1206949, &(0x7f00000001c0))


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000002c0), 0x1, 0x0)
r1 = socket(0x2, 0x4001, 0x0)
r2 = dup(r1)
r3 = fcntl$dupfd(r2, 0x2, r0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r4, 0x80104267, &(0x7f0000000000)={0x2, &(0x7f0000000100)=[{}, {0x96, 0x4}]})
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x36, 0x0)
close(0xffffffffffffffff)
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r5 = socket(0x2, 0x1, 0x0)
connect$unix(r5, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r3, 0xffff, 0x1023, &(0x7f0000000080), 0x4)
shutdown(r3, 0x1)
close(r3)
r6 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000040), 0x100, 0x0)
ioctl$WSKBDIO_SETDEFAULTBELL(r6, 0x80105705, &(0x7f0000000080)={0xd0, 0x0, 0x6, 0x10000})
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff}, 0xe0ffffffffffffff})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r7 = socket(0x2, 0x2, 0x0)
r8 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r9 = fcntl$dupfd(r8, 0x3, 0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$FIONREAD(r9, 0x8004745d, &(0x7f0000000200))
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r7, 0x8040691a, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000080)=[{0x30}, {0x24}, {0x8106}]})
syz_emit_ethernet(0x2e, &(0x7f0000000280)=ANY=[])


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(r0, 0xc0206921, &(0x7f00000001c0))
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0206923, &(0x7f00000001c0))


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x100000000000000, 0xffffffffffffffff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
r0 = socket(0x18, 0x1, 0x0)
r1 = socket(0x800000018, 0x1, 0x0)
r2 = socket(0x18, 0x2, 0x0)
close(r2)
r3 = socket(0x18, 0x3, 0x0)
setsockopt(r3, 0x1000000029, 0x31, &(0x7f00000000c0)="b211d7170d816685c8e360f2fa41c1a0946988b272d2dd3dc90142a84231a746e337b372e93320cff6669cbe7868de45ed3fc33719ca6df71ecec8a918458b2c10a1f8c66653b276e180e9cb9b21f9982230f575295d48889c9a920796b2dd92fc8575680b37ba955d2c15e6d7c9198ed900ab006ddfb67869b51a2216114d1ece85f593e74035f5bc054eb1dbddf42a", 0x90)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0))
connect$unix(0xffffffffffffffff, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892}, 0x1c)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1021, &(0x7f00000000c0)=0x5, 0x4)
close(r0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r4, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000000280)=[{0x80}, {0x1}, {0x6, 0x0, 0x0, 0xfffffff8}]})
write(r4, &(0x7f0000000200)="b1c05b5fb165120a4224a763037a", 0xe)
r5 = socket(0x18, 0x3, 0x0)
setsockopt(r5, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000380)=[{0x30}, {0x2d}, {0x8506}]})
syz_emit_ethernet(0x2e, &(0x7f0000000280)=ANY=[])


open(0x0, 0x0, 0x0)
syz_emit_ethernet(0x0, 0x0)
munmap(&(0x7f0000400000/0xc00000)=nil, 0xc00000)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
socket$inet(0x2, 0x0, 0x0)
poll(&(0x7f0000000000), 0x0, 0x0)
setitimer(0x0, 0x0, 0x0)
socket(0x18, 0x0, 0x0)
openat$speaker(0xffffffffffffff9c, 0x0, 0x1, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, &(0x7f00000001c0))
openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
msgctl$IPC_RMID(0x0, 0x8000000)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x1010, 0xffffffffffffffff, 0x0)
sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x20}, 0x4, 0x0, 0x0, &(0x7f0000001140), 0x4)
ioctl$VNDIOCGET(0xffffffffffffffff, 0xc4104603, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)


sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000400)}, {&(0x7f0000000600)="72b78a2309d21d724fccb5cf0f80d5716e62dbce3a6f4992d47084ddc570943c5e3549de177d455df13f5c9e662da36a", 0x30}], 0x2)
writev(r0, &(0x7f0000000280)=[{&(0x7f0000000100)="96e9cf1c159fc25ac05e6f4c", 0xc}], 0x1)
execve(0x0, 0x0, 0x0)


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = getppid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0xffffffffffffffff}, 0x0, 0x0, r0})
pipe(&(0x7f0000000000)={<r1=>0xffffffffffffffff})
setpgid(0x0, r0)
ioctl$WSKBDIO_GETMAP(r1, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r2 = fcntl$getown(r1, 0x5)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
setreuid(0x0, 0xee01)
ktrace(&(0x7f0000000180)='./file0\x00', 0x4, 0x40000d30, r2)


dup2(0xffffffffffffffff, 0xffffffffffffffff)
getsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000080)="e066fe71dd54c85048a6ae968c22233da611a6ad5fcdcc0da4f05e65380e7c4b38a7e8f79747fbf6778a2124e8310d6299fad15811fa56d3dafd663879a0e3a49d494c166da97165e69ea5b87139f65c8357ce80b37ee49321c89c49c79bd5ccf3a7c6f229d492f017366bd0356fd2c3dc6b27a7419141977b3add295b237297d0d578a7acdbfe2d9509729ff1a8687a2e3a41818466c5802d986dc210fea19a3636fdf6a0a5ff67eb73a775d184bf68c3637ddd3c58cadf78f01593bb86a0ed2afec8da739ed43d541e2a5df12e16d1a71ce14a6169717e65ff1c82db550717668dfe1e356e0797c0d5204613c21b75aad6d61c8d949c85f3fe007a1fc714d30fbe12dbb318c8aed8aa85abafe3242789a90936962bd1", 0x117, 0x4, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000140)=ANY=[@ANYBLOB="00000000000000000000000008060001080006040008ffffffffffff7f00000100000000e3cd"])
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
sendto$inet(0xffffffffffffffff, &(0x7f00000000c0)="6c25a03ae7b27b4e7fc0924a22334b9b619f09f993c214bf34de94ee6f878793a443c48892901b940ff2189ae976bd635aa66dd55818d1ca20a7f88c2ad799df41ea701f32e36ab928f0ea3b00ddc5613e3590c04b342a5ec356d4f406e612653d7338e1b59ec0f00de4b65b3f18", 0x6e, 0x0, 0x0, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


setrlimit(0x0, &(0x7f0000000040)={0x7})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
setrlimit(0x2, &(0x7f0000000080)={0x60000000, 0x60000000})
mmap(&(0x7f00006f6000/0x3000)=nil, 0x3000, 0x0, 0x10, r0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)


mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
recvmmsg(r0, &(0x7f0000000480)={0x0}, 0x10, 0x0, &(0x7f0000000500)={0x200ffffc, 0xa})
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000158000/0x3000)=nil}, {&(0x7f000003d000/0x1000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f00000c3000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000157000/0x1000)=nil}, {0x0, &(0x7f00001eb000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f00000e0000/0x1000)=nil, &(0x7f00000d8000/0x3000)=nil}, {&(0x7f00000ca000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f00000f8000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r1, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0xa})
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x802, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x80}, {0x2c}, {0x6, 0x0, 0x0, 0xfffffffe}]})
write(r0, &(0x7f0000000500)="762bdead0f01f864cb36347f538fa163df", 0x11)


mknod(&(0x7f00000002c0)='./file0\x00', 0x2000, 0x5200)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
chflagsat(0xffffffffffffffff, &(0x7f0000000000)='./file0\x00', 0x0, 0x0)
socket(0x18, 0x0, 0x0)
fchmod(0xffffffffffffffff, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x119, 0x0)
mknod(0x0, 0x0, 0x0)
r0 = kqueue()
kevent(r0, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000680)={0x0, 0x0, &(0x7f00000001c0)=[{0x0}, {0x0}, {&(0x7f00000002c0)}], 0x3}, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8040691a, &(0x7f00000001c0))


r0 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r0, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1021, &(0x7f0000000000), 0x4)
setsockopt$inet_opts(r1, 0x0, 0xc, &(0x7f00000000c0)="eaff125c0000e909", 0x8)
ioctl$BIOCSDIRFILT(0xffffffffffffffff, 0x8004427d, 0x0)
syz_emit_ethernet(0x3e, 0x0)
ioctl$BIOCGSTATS(0xffffffffffffffff, 0x4008426f, &(0x7f00000002c0))


r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x0, &(0x7f00000002c0)})
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000380)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg$unix(r1, &(0x7f00000018c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="10000000ffff000001"], 0x10}, 0x40a)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x2c}, 0x4, &(0x7f0000000000)="71f91e3471ac0058bc5a91501d942400b5e1a0757cb9af769c7afec37082", &(0x7f0000000080)=0x56, 0x0, 0x2e)


r0 = socket$unix(0x1, 0x1, 0x0)
getsockopt$sock_timeval(r0, 0xffff, 0x1005, &(0x7f0000000000), &(0x7f0000000040)=0x10)
r1 = open(&(0x7f0000000080)='./file0\x00', 0x20, 0x110)
ioctl$BIOCSDIRFILT(r1, 0x8004427d, &(0x7f00000000c0)=0x2)
recvfrom$inet(r1, &(0x7f0000000100)=""/102, 0x66, 0x1002, &(0x7f0000000180)={0x2, 0x3}, 0xc)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000001c0)={<r2=>0xffffffffffffffff})
write(0xffffffffffffffff, 0x0, 0x0)
ioctl$VMM_IOC_TERM(r1, 0x80045604, &(0x7f0000000240)={0x1})
flock(r0, 0x0)
socketpair(0x18, 0x8000, 0x81, &(0x7f0000000280)={<r3=>0xffffffffffffffff, <r4=>0xffffffffffffffff})
setsockopt(r4, 0xa0, 0x0, 0x0, 0x0)
rmdir(&(0x7f00000012c0)='./file0\x00')
r5 = semget$private(0x0, 0x3, 0x60)
semop(r5, &(0x7f0000001300)=[{0x0, 0x100, 0x1000}, {0x0, 0x1000, 0x800}], 0x2)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000001380)={<r6=>0x0, <r7=>0x0, <r8=>0x0}, &(0x7f00000013c0)=0xc)
ktrace(&(0x7f0000001340)='./file0\x00', 0x0, 0x0, r6)
stat(&(0x7f0000001400)='./file0\x00', &(0x7f0000001440))
recvfrom$unix(r2, &(0x7f00000014c0)=""/88, 0x58, 0x41, &(0x7f0000001540)=@file={0x0, './file1\x00'}, 0xa)
semop(r5, &(0x7f0000001580)=[{0x1, 0x9ffc}], 0x1)
execve(&(0x7f00000015c0)='./file1\x00', &(0x7f0000001640)=[&(0x7f0000001600)='\x00'], &(0x7f0000001880)=[&(0x7f0000001680)='\x00', &(0x7f00000016c0)='*\x00', &(0x7f0000001700)='$%\x00', &(0x7f0000001740)='#\':\x00', &(0x7f0000001780)='\x00', &(0x7f00000017c0)='\x00', &(0x7f0000001800)='/@\x00', &(0x7f0000001840)='\x00'])
sysctl$hw(&(0x7f00000018c0)={0x6, 0xf}, 0x2, &(0x7f0000001900)="b0d51478cc3af47f4226663abfc9a9ef59acdb818b94e082445336e6760289119491043c489d612784897842884f364e325ddd528a66a6a3cb8448d79fd94adad95ccdb1d277ff4ad4e9d922e8d129246b180ed3ea655c0eae47f56459d1b41c78200ff30816481c7682d6577be366b0058a900b685bb7c39cace8d877a61efb560b10e5c1c1ebe36004038131d87ec0535828394bdbd49a189fe9cc5f58420c7fbc36dcd858fd627366461ec2803abd40df47749831b146b3540001c3c3bada7c64210f0076f421eb786d2f451fa9659c53576db9cd6a23c0145d05a1b6900ce20222b9440753e00a60c5bac23aadcf11c6e9045eefef897b", &(0x7f0000001a00)=0xf9, &(0x7f0000001a40)="3f3fa688fa9f957fee031a0071836391d02a00284c63886d5455a27559d60c3a477b808c3bfffbbce34bcaa5b48b13e4f5babd61a3bfe5c7cfdaef27f7e535b145bdd1e4ccaf99419e5ba5b65bbe27b2f653f378d2bd95a339c0acc5", 0x5c)
sysctl$hw(&(0x7f0000001ac0)={0x6, 0x19}, 0x2, &(0x7f0000001b00)="fb3f42150a38d1bca171521358fae7efb6fe25d4b8b2ce80100acb3bc85d365ac94f517c62e3d4294678a8d77d53822680bb4a679808b5f830fcd7142adc33fb6636bb5d76617243ba44e70842ff026ba7", &(0x7f0000001b80)=0x51, &(0x7f0000001bc0)="9d1e947b6eea115b", 0x8)
r9 = dup2(r0, r3)
ioctl$BIOCGDIRFILT(r9, 0x4004427c, &(0x7f0000001c40))
getsockopt$sock_timeval(r3, 0xffff, 0x1005, &(0x7f0000001c80), &(0x7f0000001cc0)=0x10)
ioctl$WSDISPLAYIO_GETEMULTYPE(r4, 0xc014575e, &(0x7f0000001d00)={0x9, './file0\x00'})
link(&(0x7f0000001d40)='./file0\x00', &(0x7f0000001d80)='./file1\x00')
semop(r5, &(0x7f0000001dc0)=[{0x5, 0x3ff, 0x1800}, {0x3, 0x3, 0x1000}], 0x2)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000001e00)={{0x8, r7, r8, r7, r8, 0x20, 0xfffc}, 0x761c, 0x80000001, r6, r6, 0x8, 0x80000001, 0x6, 0x100000000})


kqueue()
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x800, 0x0)
r1 = dup(r0)
ioctl$BIOCSBLEN(r1, 0xc0044266, &(0x7f0000000100))
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSHDRCMPLT(r1, 0x80044275, &(0x7f0000000340)=0x8000)
r2 = kqueue()
kevent(r2, &(0x7f0000000040)=[{{0xffffffffffffff9c}, 0xfffffffffffffff9, 0xd5, 0x10, 0x5}], 0x9, 0x0, 0xe9ea, 0x0)


r0 = socket$unix(0x1, 0x1, 0x0)
getsockopt$sock_timeval(r0, 0xffff, 0x1005, &(0x7f0000000000), &(0x7f0000000040)=0x10)
r1 = open(&(0x7f0000000080)='./file0\x00', 0x800, 0x110)
ioctl$BIOCSDIRFILT(r1, 0x8004427d, &(0x7f00000000c0)=0x2)
recvfrom$inet(r1, &(0x7f0000000100)=""/102, 0x35, 0x1, &(0x7f0000000180)={0x2, 0x3}, 0xc)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000001c0)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
write(r3, 0x0, 0xffffffffffffff05)
ioctl$VMM_IOC_TERM(r1, 0x80045604, &(0x7f0000000240)={0x9})
flock(r0, 0x0)
socketpair(0x18, 0x3, 0x81, &(0x7f0000000280)={<r4=>0xffffffffffffffff, <r5=>0xffffffffffffffff})
setsockopt(r5, 0xa0, 0x0, 0x0, 0x0)
r6 = semget$private(0x0, 0x3, 0x160)
semop(r6, &(0x7f0000001300)=[{0x0, 0x1ff, 0x800}, {0x0, 0x3000, 0x800}], 0x0)
ktrace(&(0x7f0000001340)='./file0\x00', 0x0, 0x0, 0x0)
stat(&(0x7f0000001400)='./file0\x00', &(0x7f0000001440))
recvfrom$unix(r2, &(0x7f00000014c0)=""/88, 0x58, 0x41, &(0x7f0000001540)=@file={0x0, './file1\x00'}, 0xa)
semop(r6, &(0x7f0000001580)=[{0x1, 0x9ffc}], 0x1)
execve(&(0x7f00000002c0)='./file1\x00', &(0x7f0000001640)=[&(0x7f0000001600)='\x00'], &(0x7f0000000200)=[&(0x7f0000001680)='\x00', &(0x7f00000016c0)='*\x00', &(0x7f0000001700)='$%\x00', &(0x7f0000001740)='#\':\x00', &(0x7f0000001780)='\x00', &(0x7f0000000300)='\x00\x05o=\x8c\x01\xf5*\x18\"\xf0\x99\xd7\xb3;\t?&4\xffO\xf3L\xc0\xa5', &(0x7f0000001800)='d\xf2l', &(0x7f0000001840)='\x00'])
sysctl$hw(&(0x7f00000018c0)={0x6, 0xf}, 0x2, &(0x7f0000001900)="b0d51478cc3af47f4226663abfc9a9ef59acdb818b94e082445336e6760289119491043c489d612784897842884f364e325ddd528a66a6a3cb8448d79fd94adad95ccdb1d277ff4ad4e9d922e8d129246b180ed3ea655c0eae47f56459d1b41c78200ff30816481c7682d6577be366b0058a900b685bb7c39cace8d877a61efb560b10e5c1c1ebe36004038131d87ec0535828394bdbd49a189fe9cc5f58420c7fbc36dcd858fd627366461ec2803abd40df47749831b146b3540001c3c3bada7c64210f0076f421eb786d2f451fa9659c53576db9cd6a23c0145d05a1b6900ce20222b9440753e00a60c5bac23aadcf11c6e9045eefef897b", &(0x7f0000001a00)=0xf9, &(0x7f0000001a40)="3f3fa688fa9f957fee031a0071836391d02a00284c63886d5455a27559d60c3a477b808c3bfffbbce34bcaa5b48b13e4f5babd61a3bfe5c7cfdaef27f7e535b145bdd1e4ccaf99419e5ba5b65bbe27b2f653f378d2bd95a339c0acc5", 0x5c)
sysctl$hw(&(0x7f0000001ac0)={0x6, 0x3}, 0x2, &(0x7f0000001b00)="fb3f42150a38d1bca171521358fae7efb6fe25d4b8b2ce80100acb3bc85d365ac94f517c62e3d4294678a8d77d53822680bb4a679808b5f830fcd7142adc33fb6636bb5d76617243ba44e70842ff026ba7", &(0x7f00000003c0)=0x51, &(0x7f0000001bc0)="9d1e947b6eea115b", 0x8)
r7 = dup2(r0, r4)
ioctl$BIOCGDIRFILT(r7, 0x4004427c, &(0x7f0000001c40))
getsockopt$sock_timeval(r4, 0xffff, 0x1005, &(0x7f0000001c80), &(0x7f0000001cc0)=0x10)
ioctl$WSDISPLAYIO_GETEMULTYPE(r5, 0xc014575e, &(0x7f0000000340)={0x9, './file0\x00'})
link(&(0x7f0000001d40)='./file0\x00', &(0x7f0000001d80)='./file1\x00')
getsockopt$SO_PEERCRED(r2, 0xffff, 0x1022, &(0x7f0000000380), 0xc)
semop(r6, &(0x7f0000001dc0)=[{0x5, 0x3ff, 0x1000}, {0x0, 0x3, 0x1000}], 0x2)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000001e00)={{0x8, 0x0, 0x0, 0x0, 0x0, 0x20, 0xfffc}, 0x761c, 0x80000001, 0x0, 0x0, 0x8, 0x80000001, 0x6, 0x100000000})
msgget$private(0x0, 0x24)


socketpair$unix(0x1, 0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
mknodat(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, &(0x7f0000000340)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000000c0), &(0x7f0000000240)=0x5d)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x37}, 0x2, 0x0, 0x0, 0x0, 0x0)
listen(0xffffffffffffffff, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f00000001c0)=[{0x5}, {0x3}, {0x6}]})
syz_emit_ethernet(0x6e, &(0x7f0000000000)=ANY=[])


setrlimit(0x0, &(0x7f0000000980)={0x0, 0x54})
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x412dff)
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, &(0x7f0000000440)={0x0, 0x1000, 0x0})
openat(0xffffffffffffff9c, &(0x7f0000000200)='./bus\x00', 0x1, 0x162)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000180)={<r0=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
mprotect(&(0x7f0000c57000/0x1000)=nil, 0x1000, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, 0x0)
r1 = msgget$private(0x0, 0x23a)
msgrcv(r1, 0x0, 0x0, 0x0, 0x0)
msgrcv(r1, &(0x7f0000000b40), 0xa6, 0x0, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x5200)
ioctl$FIOASYNC(r0, 0x8004667d, &(0x7f0000000300))
msgsnd(r1, &(0x7f00000000c0)=ANY=[@ANYRES32=r0], 0xb9, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1004, &(0x7f00000002c0), 0x1)


mknod(&(0x7f0000000080)='./file0\x00', 0x6000, 0x202)
mknod(&(0x7f0000000200)='./bus\x00', 0x2000, 0x202)
link(&(0x7f00000000c0)='./bus\x00', &(0x7f0000000100)='./file0\x00')
unlink(&(0x7f0000000080)='./bus\x00')


sysctl$net_inet_esp(&(0x7f0000000000)={0x4, 0x2, 0x2, 0x2}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0xa, 0x56}, 0x1, &(0x7f0000000380)="7120609015a562165e0cd91e0dbd643f7b071354a8d65f1741035aa57f42b1e4499dfa083a14081304c5a7e2cb250ccb2cfa49b065698db4b8f3146e6f1c4e540683f8a34b710000f3d927fb5b0540bc947562521013c60528c7a591e986654e0ce14a1aa7eaecdc84d463783920657e239a483e64bf36ad0cceaae122a5e6d5552aa207518100"/147, 0x0, 0x0, 0xfffffffffffffe23)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
ioctl$TIOCCONS(r0, 0x80047462, &(0x7f0000000080))
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r1 = socket(0x18, 0x3, 0x3a)
setsockopt(r1, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r1, 0x29, 0x66, &(0x7f0000000100)={0x0, 0x0, 0x0, 0x1}, 0xc)
sysctl$net_inet_gre(&(0x7f0000000000)={0x4, 0x2, 0x2f, 0x1}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000440)={0x6, 0x18}, 0x4, &(0x7f0000000480), 0x0, 0x0, 0x0)
socket$inet(0x2, 0x2, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r2 = socket$inet(0x2, 0x2, 0x0)
r3 = kqueue()
r4 = dup2(r2, r3)
sysctl$net_inet_gre(&(0x7f0000000240)={0x4, 0x2, 0x2f, 0x1}, 0x4, &(0x7f0000000200)="80815d97e5e9ec42557fbfa1b208d658d9983f117a859fd619a67026beff80585ebedf283df04854cf98e456c11215a266b3c48e70351ef02e", &(0x7f0000000140)=0x39, &(0x7f00000002c0)="3dfa4fb3856c4746eb2eb03594054ba42844c05dead99310706c5380ab882add6f79368371958ce85cbed5c98127e26c20bc4220457829ff5f35b5b2bd0401add90419a4b7bc32df22afe1de3f826109e8ca97080d38acf67d1026fd2cfce5c0cd0f94a8b0eccf9d1541bb2d7d5d32f9a5986f36c532686d60", 0x79)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
pwritev(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f00000005c0)="dc", 0x1}], 0x1, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x4f}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
syz_emit_ethernet(0xba, &(0x7f0000000080)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaabb86dd600000000084000080000000000000000000000000000000ff020000000000000000000000000001"])
socket$inet(0x2, 0x4002, 0x0)
socket$inet(0x2, 0x2, 0x0)
socket(0x0, 0x0, 0x0)
mkdir(0x0, 0x0)
setreuid(0x0, 0xee01)
semctl$GETALL(0x0, 0x0, 0x6, 0x0)


kqueue()
kqueue()
r0 = socket(0x2, 0x1, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
sendmsg(0xffffffffffffffff, &(0x7f0000000800)={&(0x7f0000000040)=@in6={0x18, 0x1, 0x0, 0x4}, 0xc, 0x0, 0x0, 0x0, 0x3d0}, 0x0)
close(r1)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140)={<r2=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
sendmsg(r2, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)


mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x287e)
r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
writev(r0, &(0x7f00000000c0)=[{&(0x7f0000000280)='#!', 0x2}, {&(0x7f0000000000)="8d6b", 0x2}], 0x2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000080)=[{0x5}, {0x3c}, {0x6}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000440)={0x3, &(0x7f0000000100)=[{0x40}, {0x2d}, {0x8016}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x4e, &(0x7f0000000100)=ANY=[])


socketpair(0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000240)=[{0x2}, {0x25}, {0x6}]})
syz_emit_ethernet(0x1019, &(0x7f0000000400)=ANY=[])


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f00000000c0)="b1000501600000903f0000000700000000000000cfa10500fef96ecfc73fd3357ae36caa0416fa4f376b36acf00b7804be381e4991f7c8cf5f882b297be1aa5323edeb51e2f0ca3ebbc257699a1f133ea7acb5d602000d7d026ba8af6300372a2102000000720fd38bfbb770c1f5a8aec881ea772ec5890400000000000000361b1257aea8c500002012000000042000000000000000000000000000002000"/177, 0xb1, 0x0, 0x0, 0x0)


r0 = socket(0x2, 0x1, 0x0)
r1 = dup(r0)
listen(r1, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
r3 = dup(r2)
recvmmsg(r3, &(0x7f0000000440)={&(0x7f00000000c0)={0x0, 0x0, &(0x7f0000000580)=[{0x0}, {0x0}, {&(0x7f0000000240)=""/90, 0x5a}], 0x3, 0x0}}, 0x10, 0x0, 0x0)
dup2(r1, r3)
execve(0x0, 0x0, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, &(0x7f0000000100)="e4", 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
select(0x40, &(0x7f0000000100), 0x0, 0x0, 0x0)
select(0x40, &(0x7f0000000100), 0x0, 0x0, 0x0)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000001440)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000700)=[{0x5}, {0x30}, {0x6, 0x0, 0x0, 0xfffffffe}]})
write(r1, &(0x7f0000000740)="76e5dead6f01f8607d2100000063", 0xe)
r2 = fcntl$getown(r0, 0x3)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, r2})
openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VNDIOCCLR(0xffffffffffffffff, 0x80384601, &(0x7f0000000100)={0x0, 0x1, &(0x7f0000000080)='./file0\x00', 0x8})
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
r3 = socket(0x18, 0x3, 0x0)
pipe2(0x0, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r4, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{0x2c}, {0x84}, {0x4000006, 0x2, 0x0, 0x3feffe}]})
write(r4, &(0x7f0000000180)="23009100007adb020317bdda2b7e", 0xe)
ioctl$BIOCFLUSH(r1, 0x20004268)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


ioctl$WSDISPLAYIO_DELFONT(0xffffffffffffffff, 0x8058574f, &(0x7f0000001940)={'./file0\x00', 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4})
setrlimit(0x8, &(0x7f0000000980)={0xb, 0x200400000000062})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)
readv(r1, &(0x7f0000000100), 0x4c)
sysctl$vm(&(0x7f0000000000)={0x6, 0x6}, 0x2, 0x0, 0x0, 0x0, 0xffffffffffffffda)
setreuid(0xee00, 0x0)
open$dir(0x0, 0x0, 0x0)
fchown(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
mkdirat(0xffffffffffffff9c, 0x0, 0x0)
renameat(0xffffffffffffff9c, &(0x7f00000004c0)='./file0\x00', 0xffffffffffffff9c, &(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
socketpair$unix(0x1, 0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
chmod(0x0, 0x40)
writev(0xffffffffffffffff, 0x0, 0x0)
execve(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$BIOCGDLTLIST(0xffffffffffffffff, 0xc010427b, 0x0)


r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
mkdir(&(0x7f0000000000)='./file2\x00', 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x2, 0x2, 0x0)
fcntl$setstatus(r3, 0x4, 0x40)
connect$inet(r3, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r2, 0xffff, 0x1023, &(0x7f0000000040), 0x4)
shutdown(r3, 0x0)


syz_emit_ethernet(0x3e, &(0x7f0000000140)=ANY=[@ANYBLOB="ffffffffffffffffffffffff86dd6060626000082c00fe830e00000000000000000000bbfe8000000000000000000000aa"])
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x1, &(0x7f0000000000)=[{0x0, 0x6, 0xc0}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
clock_settime(0x100000000000000, &(0x7f0000000000))
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
socket(0x18, 0x1, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)
syz_emit_ethernet(0xe, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
madvise(&(0x7f00007de000/0x3000)=nil, 0x3000, 0x0)
openat$pf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
select(0x0, 0x0, &(0x7f0000000c40)={0x1}, 0x0, 0x0)
syz_emit_ethernet(0x32, &(0x7f0000000040)=ANY=[@ANYBLOB="ffffffffffff00100000000088a8300081041b00e2769fe4fd060aa80006000000000000e000000100988dfcfdc8e12eb300970fee653b7e5cb6521d1fbad834"])


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r0 = syz_open_pts()
sysctl$vm_swapencrypt(&(0x7f0000000000), 0x3, 0x0, 0x0, 0x0, 0x0)
close(r0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f0000000040)=0xfffffffc)
writev(r0, &(0x7f00000003c0)=[{&(0x7f00000001c0)="c8a9d805a8e7b15f1b9bb59d56c762c3229af9eef397ca51e4024b18ae7e9e3d51caf669312175eb550bc83df0b948034c29521b1b6ea36a2321e7d00fc3ac653a7722df8e4686a7e646a4929580e40184c1d8dc82304fee6b282e83ff9ccf870c4f009160d0f2815545d7f1b025bf494e4d0fdf94d16e5754620edd", 0x7c}, {0x0}, {0x0}], 0x3)
readv(r1, &(0x7f0000000000)=[{0x0}, {&(0x7f0000004740)=""/4092, 0xffc}], 0x2)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000080))


open(&(0x7f0000000280)='./file0\x00', 0x615, 0x0)
ktrace(&(0x7f0000000080)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
r0 = syz_open_pts()
writev(r0, &(0x7f0000000300)=[{&(0x7f0000000180)="98d926cc1c68bcafda73d24239c0ec64cb0f13f5df63fa33a13c37427233489492cb7aa9893eb485b2422794d5a835bd5ea43cc591eb21d9b52584162d5ecc8d9a3929ba91e5c40163dd1a3434dc9493de1a2a19b30280aa5868ca588773d1db052b7de16a22183e334af913fb8e87001ee8db03e1912fa380c9984c71c001bd449627f1be8f9ec9c7dc834e1194702c233664175a4d2a21d590fb3e0a2b6efba8afb59425ed19e7c6dde07f70f4a025a96645b9d7a3b9a395db39e70880f7bfb44ab4cbfe2880e593cf583cbee4ba33763347c7771ebe84f76cc72fcbc289da7881da17d6ed21bacf0dfecee5d8ed3a", 0xf0}, {&(0x7f0000000840)="c18d9e0ed9d500492e86bfa0c687ae90529a3065aa96d61d055eecefb3a069e5f21570eb75cdfc934972b07e23129331726780398ca9cabe8ec75df8cac5947810e4a42da307cad91082621d59802df13e3e6c8bd3de4d69279f674bdeb50c7ed969d2b3ac003b39df7e6f420460f62830824b3663fcc140ef60c7bf485ae2ed3601c41f3b72373a72d30bb2a11cbbecfb317ec60529f682adfc44eb1e67e47f0f67d302fb4ffc5c34cdf812fb55453afed7629d6ff817bf8978e60dfb83eef7fb1d36818e2b3581a691a23dc2bc494f5e916479bb9d795a68acc019a89f186c7a62d7a425190a4d9bf192c39b564907e8ad08c388e749a650099467e3c31938287d1226acf87f473e2c7113c360d7930693951192a941aeb30f0546a1bb4ebb5d9a5f13345e08beafe7c4e18368ef1e9a2f664fd1e85823e30fcf4935677d2022e42ac131ca346feedb2979288992240038f9b171bd3ec2dbeb3b34a4b63a976e8d47646699454059f31857e4b8dcd99b4225828d20d37e73a06bd30d1474ec07947c7fd79f3304b222a85c5213d58c7675b54ad17d9acb101b09c8104558817de653587c2bad0daf0cc8d28657909f11f52cd465d86a309011628bf015805fed00580df6d8c27046fc49c1132701cf611e3674b4d924487c3418a35caa974c31efc108f98536c5cc28ae7d5e3fc7092a0a01a16c029c595e3062bfe7d1ba616136d8299819e288b07b7890109379ad5d1596faec8ad9ffb732cc96bc29a5916ba94c39a76ee328b73407c5faeb701ab9851a44a704b6447d93a2f757b6b0b795b9edea463eaf88eea599aac1b74195f71005e5913ec90254c7c964aa63c254b29f46d28771066c499b8c02bb53468d319ff2f2fb3cb64a9f46e2cbf74d9eceee0b2d9b4f89b31cf0231e8ee6a146e75488cd0929a15dc1cb0f1b7221e68be6711aa259529c56aa4d733862493e3697bfea722636ca94d5ac1758a78892d66a08e4a8d9d5a11249ae005367ebe63db1e13836bb09b818b2d10ebc911cf51437d1253d71e7eb14961c87e7babf1796937eafb6c732ef07e4c11113cce542bed771fe0dfcf1685ed12656425d142d0cb938c3d34721b0d96c0097897314fe8a74ca94962525220b7f9059708e5305780323cf2207d720c84bd5774eaf641357eb7c912a405eb251523610573e4da0bd98649d7c76d290e40091830d7d6ddbef69120936b2dd1185082ec6da8cc482f7c9e747b1d97cc920ba7c4ee12dbe0a0ea32791b2275003fb653263276534e76b39fd545bfe83a8ad962bc06d54f564c268cb7e49fed35d114c9df58944fcb40a8c1e6acc1316905f329689a7dc1983d5a524074fd8c07c0beec8c46e3c60646c71ac2e6636f9a81f86ea19d4607b5fd345455eb70e5a3cbccad57a6a0ea5f1828aac86700fef82b724b12650f7001898147ad20732f2dffdb7f08ae3992475e2cfcc9ed373d55b99efe289e13373948cf9ba90d1c91fe3201f6949599c9a15ceeb9300084bff496b87b3a9fdcc39ea52aaf2e4d81c8d0de6947383f4acee2b1d82f67e339743fa0baf8298cf3f0f08011ece3dc71590b518957c09131d11e7884d7ea903233cb6103d3bfb5c97b669136273348158475ff2d7ee8313db192e24c82942d6592b064879f9d45a7f1ce49e01f3eb3fa23d33309b3bc56a2f0b37f9ba79d163db3d9d5f6613665934a7bf09bd2b653c53851cfda8cd228b63305f11064417f94b1577c6aa34ab90668afe335b7cd9c9b5c0acc410aa08a8bb02c14627cd1267e1b0b8fe88daf0ec8cf430d7f3a44fe0c2ab452d0498e988993537af58ffecf93efd87b5a9ce49326b2cfae0eab37577a814e8a548f035f1cd1ab0456e31f04cdb823896f12e25db7592ae4d9f11d072f03713e0880f9a63bde4d07ed159a9ab0a0b95f2a8a68750d9efad028f80037b2400a1cb3205c5f6e46d1cc23ae2a285e8c66921182c057d281c9b5b52e115cf29464736a097ab89b09d2e6c3632963c58780fabc74e3d3278ef7119a15a5482340b7c597e895112a820d97c039f706212322134c11e4842d80afba00cc3b08441ecc3a58e2ceef31eb69e88f104dc3eb91da5d679f6af504a6d3e033897f73e494e11ddf90d5c11c44ef53830b0d8d84d5e6d42f0d0175d9e1fc42a12a517113b3ec1049b7d6334e940ffbdf65d7062f6520a78c38d3fc6a11d0adcd45f4fc5b9ba08757e6e3d8592cf986b8d181aac7151346e8f62c4966c2cedf68bcce9ffa7173e026b6b983380671439fa2681e06172ee3891ae5f9264d67ce5f8a361db9eea084ce2338921754fd17ccf2d5477507f9991aebbe6f96979f9157ccbb46ca5cbe6888a6286a1173dea87ef53ea60ce73b2cfea4a9477c39af0d85f1b0bb2c9665fa41f4a42e920a30cf3101f8debc52f172bdc17589122b121f84b416685f2c74bb7b0cb326653bf92481fb5c7d3c0f8fc00e0898985a987ca01fb25863485190f7cc5fc0a8b697892072d7a6d506950968ad7cd67db2da8edf72b1cef7a15808e087eb53b4669d5197ea3e409f24fd99e271802d797dca849bce85b9ac4e8134fb346e619a3f6012e1121eb589adb3181b2aa29fea30f9102f4e867e2cf6c1d154418970a80982e7314c39e34cbaf5f16c6dc5c582528b13f08dd4906438ca79ff2d07b37f8c89b85d5e4e59d9fd925a0b21b2c65f54d6f2fbb3045a5fc8b3824e182e3adb3131abf67476d178feedd61d8b6b03efc34c68a8a99c0c5da98e2533ade85ae515b9318c13209c715be5e58074ba69b1cd8cda69b74139ab2eb67fb4931a10d3cfe3e745cdaeec74e4b5be864e4b5485a82ef1be5293585f11a082e9d978c133922d8f401339261dead95c4d6cb022e827adb92336281fda25ce6a9141328e010fc0625f1979b7e01ad37b45027c6f813516476254253684bde127e2d5306f6f54e7b303ac1c59a54e18deac9aaf5366310350567a8182aa2e8ec0e7abf063ac3f105c933a4c13f2f2ed96006152ff5a9a05d5886badaaf70097064b24340914265286f35654eacfd96971f62801042d915d2775a3434ab5659e19a1e2058b1f8c4e6dbbdd44bf1164dbfa7b343477919e001104a34306cbea72de0cd444fe4bf6348ff84b01ba0274c861ae4e83d171228d878116593e46500c7ab3b3ad4c7106baa4a76c9c88aeb3184f9a905189b77b5f753f0278f5b6c1a32e473c66a5760976d770a3913965464ccd718e72c03d7d413b1541c3f442b450c3ae3210eec4f2687cea253ef6cc3d17412862c6cb902c21eff7132fe2170c8f8ee641c592d4cd2e4ad95db0a272943da125fb7dd8b9f7c187c2c6047fa206df00aafc5b480a0dca23d33e2166994f27f76e54827e2676bdffdf450933c55afbde2debc50765e7eb9dbfc6bc4ccfe49a8977cb41bd86deaafe5579100129410e64a66489ab339db44e499468ccf8688da9344471ffbc189c7dac424b61b5d336304bf4b4ec712485415d3e868fb1b1ebdf3bc299d740c70a351ddcdb75e2cceeb78ea602036dfadaead5df60233bd8aa079c667a0c915809b667bbb6ec5162456667b8db2ccae91745f9a5e3f1e494a7c0b9a2405668b2722f710cafeee2e36b707b69d957e5f6aedd4e35de354028a9d148589bd2ac51ccd2243b6eda1582accbd432839a8b740367ada5ff94d6dcbb15cd21a64b3b03bedc9d6cb60fb42327178aaebca16ae787119b0bec226a8b631c7d5b2f437fa7b6fd69fb4dfb8c67a9c94890e2838de6e91d09490ce95e98c640d09a5b463c8c3f5de1e50d40fab10c8d5eb82aa1026e81beaa61d2c54f422faaff45b7ffec46ee0ab8db1702eb8729655534b81e2edc753fb7e8563e64937936a19ef41f7676fa1dbd0ae97d8058c826f37fdbadfda35dfd8b62b79b4f5c3ee4ef9fba2f94cb22508e292a1598c9f24be9a1e19988efb5b583ac6ac8413d5cb0aaac207ccadafa1bf93cbcbfec5762a4a50ea08c4cad427a6a82b6b263ab4519cf0f4b4a8a638e3fe3a77424855c935d84f5a51cd966f6743ec0c41d9d3dc2475c35cc3b05eaf9426a269bb6667a0af25233d71c54b1db3f702ea61b4600e0a8a60d6efa2eac129c535ef03ed6bb5f014e8e39e445e814912298f21a38a3a8d22c0f5c72afafc6d020292b13f5ee27bc92963d20135ac708bba2977fe538623278cc80e4a8d3e65474bee174cc2e52caa75a9db1fda66ac148ea31a042137e87c9d7b2de94dccc4484b12c1b896061a722669669f76204b9d46957a9621ad23fe2452d528c98a1a376ab73e0ec4db0e549793aedbd49096be4e6e6127e167336905b91ada2156d61f7cf1e10ab876da8b56f889191401c575a7fcc7e61c826ae774ed5f15356d250474608a97f5262d3cfc102a945554e641f43caa00d3f543fb3fef23664e31d5e2ff5ad157fd2a439f0375287142d30f2f85e28704b1e4ab4a4929a4fcec6d15c4c201d88feb1715c027f6544f0cd8960d221944057709c9769ea60e64602ba48dc8173179ce56f7d14afa9e7f6b30774762fcdf1f0a0f3f4de38e17823c227647561a25ba30c5fece1357dfbdc2fe5816060d15bf03f3ac025c6ae1d69a4a3d4cc86e5ce07fbdcc728ac5b30c57df9c59d81aa7aa45fa142417dbcc2f626bff69ed1aa426a7e9830f81cf63fc11e574c055960c3330bf8b02b01691724ab53c246fbe9d199a78bd86b4879b07a2745155a5e0d72b424ce0f37b97f0f188b5dd96233fd5cd729ef2a2e42fcd394a1546dc30ee14805be37526379e0976477a5cc8d39696379ff8b4dd1a5987b262aa8a10a9abdfe42dc934ed620a41d521e392a3fa50e04c7bdc2ffb3552ed6ed11314beef2d2713433cb305b4dc9efa88f0d6d085656299cfade118d0ef73a4d3c86f91990af00556f2ccba2d0eabfd2fff571ab01d6347bfba35638b555363a0f01a7831b7cf85c83a4f5ea402f9ca7eecc48e0509fa8174f30895e6fbae3f58e45c66dbea11e71a0de08c6852f0ae09c4e19feb8a59068dc0c43e87e9dc02dbd3f7b9936518f8accb110fd88f19f03b762dbfaf6ce3ce185d6901ac8c366cd9f6c9cac88ac3be5183f55a02e270e9d466bc9d6766996d315cbe075ce2376711d452232b9ed5f67b969d16f4ba5797c3654cb1936ffcd95b69380cbae57add07de38ab3735be789fd261ba963433a80839c907018bb6985b07558ae5ec2356d7e759399fc236fdcfe6c3a3e9946723dcf618891e7ac51c397178b016df71f34f6f31cb0d2f65358f12a92107f456c2d5a9ab6eec6a61ed2f9992cf30557fedd03e2fdcfc3722152c6b057e8c2f523fd0b6b4dc7a0a47ba9cdefb7755f95206a215f9e7a74a0f728a3e6aa63bf45f0f6bfd71257d0d64df3d12de2b8707d25bde800c449ccba96416cc0ea7cc9f6c1925511a4dd3b81f49bdaa992466b74cdcef938d33ccc42ce6c1c55fc56b8d62d0b716429239246b437c1df58020b6eec8c870c095b70f11df684680d5e329119ad2113e403ed0c47de0fea61ee658b6687c3826a1489fa22d98e76ce8234c58c4934402a869d44f58f15c591541323cd61d5a8e6fe7d9b6f8e43cfbd121d6ddac0bb47d7d797490a99cc288a8d2b6ceb23823d3487732fa2000ae97af4e1f55b86eab370561a467042d43efc37a8ea6b86c60b9541acb4f8fb76386f4d9722ba1d162e1292cdd849ef15b663ad07a9e2353e574a40aa21e8bf750e4af54f3f4daf679e57e4c09e4de206c563a95af9832d7db8e0a2f6e12bbd10acd0b393204015b359abc6100", 0x1000}, {&(0x7f0000000000)="4b2f99fc20020c0a3fca4c05a33de8830c093d276081cbc8b321923dc746a1", 0xfea4}, {&(0x7f0000001940)="46c01acdbbb5137d1e7c4a0c86505daa5ed31064f78caa10ab2010169e9f2c8408bec02ced6dc9cad1a657c87048f20d7eaeff48f1dfa9f8d50e2b6dba8a02e818745ab931bb5c0fca332d92a0dbe6b75bf7b21c103ddaf7f6d5815564dafd61b91fd4408a1297f484153ed406cabcc94f60d3c2be1c45564c5ed9c77f845e37796624e0c29ac9dd4c3ad0df4470973b1f2939b92639fa2be1294a992f883166a56b", 0xa2}, {&(0x7f0000000280)="a24358b3583def805ed8a91c4e6b0b4039d87d63294d921784d566b7740c568a39bb5295c9fd5d96a7566f3a1f1c07d78efe86f8ae37aff13667bbe0d063aa970ced6ce1fdc802882a9c81ec63da5484b5fe50cf", 0x54}], 0x5)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
execve(0x0, 0x0, 0x0)


open(&(0x7f0000000040)='./file0\x00', 0xf8e, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, 0x0)
writev(0xffffffffffffffff, &(0x7f00000001c0)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe1463a52077dc0d00003ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x0, "80347e7bc3cd7eb6040000000000000800007000"})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000007, 0x0, 0x0, 0x0, 0x0)
r0 = syz_open_pts()
syz_open_pts()
r1 = openat$diskmap(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x1)
ioctl$TIOCSTSTAMP(0xffffffffffffffff, 0xc0207534, &(0x7f00000001c0))
syz_open_pts()
ioctl$DIOCMAP(r1, 0xc0106477, &(0x7f0000001400)={&(0x7f00000013c0)='./file0\x00', r0})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')
r2 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000240), 0x1, 0x0)
setreuid(0xee00, 0x0)
r3 = getuid()
setreuid(0xee00, r3)
ioctl$WSKBDIO_SETDEFAULTKEYREPEAT(r2, 0x800c5709, &(0x7f0000000140))
socketpair$unix(0x1, 0x1f2756e19e0c57dd, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r4=>0xffffffffffffffff})
recvfrom$unix(r4, &(0x7f0000000240)=""/152, 0x98, 0x0, &(0x7f0000000200)=@file={0x1, './file1\x00'}, 0xa)


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r1 = fcntl$dupfd(r0, 0x3, 0xffffffffffffffff)
ioctl$WSKBDIO_GETMAP(r1, 0x80047476, &(0x7f0000000180)={0x0, 0x0})
socket(0x11, 0x3, 0x0)
sysctl$vfs_ffs(&(0x7f0000000100)={0x4, 0x1, 0x6}, 0x3, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
r2 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
r3 = getpid()
clock_getres(0x2, 0x0)
fcntl$setown(r2, 0x6, r3)
fcntl$setown(r2, 0x6, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlink(&(0x7f0000000180)='./file0\x00', &(0x7f0000000280)='./file0\x00')
link(&(0x7f0000001240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlink(&(0x7f00000004c0)='./file0\x00', &(0x7f0000000e40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000600)='./file0\x00', &(0x7f0000000f40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


r0 = socket$inet(0x2, 0x1, 0x0)
setreuid(0xee00, 0x0)
r1 = getuid()
setreuid(0x0, r1)
getsockopt(r0, 0x6, 0x9, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x42})
syz_open_pts()
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f00000000c0)={0x0, 0x0, 0x8a38})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000100)=[{0x3d}, {0x4d}, {0x6}]})
write(r1, &(0x7f0000000000)="7696e5f3d1f18c37cea8615ac7", 0xd)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000001280)={0x0, 0x0, &(0x7f0000001200)=[{&(0x7f0000000180)="bf3b684c5ae963b4567084e096cf973983b85e5df63e013eaa9405095e88157332b4f68e78e0793d3e30417acbf4419893cfd424b75262dc5ade2ab6278ab86672f9ed186987b8c19d9295a17b98020f6002", 0x52}], 0x1}, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(r0, 0x80206916, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000140)=[{0xc0}, {0x35}, {0x6}]})
syz_emit_ethernet(0x127, &(0x7f0000000040)=ANY=[])


r0 = socket(0x800000018, 0x3, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1000, &(0x7f0000000000)=0x4000007, 0x4)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000012c0)={<r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000540)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000580)=0xc)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, r2}})
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
syz_emit_ethernet(0x12a, &(0x7f0000000240)=ANY=[@ANYBLOB="b96d9900533a8f943f3614ef86dd6000000000f4000080000000000000000000000000000000ff020000000000000000000000000001"])


sysctl$net_inet6_ip6(&(0x7f0000000040), 0x5, 0x0, 0x0, &(0x7f0000000000), 0x4)


sysctl$kern(&(0x7f0000000040)={0x1, 0x55}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0x4, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x2}, {0x87}, {0x6}]})
syz_emit_ethernet(0x26, &(0x7f0000000280)=ANY=[])


sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x1b}, 0x4, 0x0, 0x0, &(0x7f0000001100), 0x4)


sysctl$net_inet_carp(&(0x7f0000000140)={0x4, 0x2, 0x70, 0x1}, 0x4, &(0x7f0000000180), 0x0, 0x0, 0x0)


ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000080)=[{}, {0x1}], 0x2})
r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_GETPARAMS(r0, 0x80105727, &(0x7f00000000c0)={&(0x7f0000000080)})


sysctl$net_inet6_ip6(&(0x7f0000000000)={0x4, 0x18, 0x29, 0x36}, 0x4, 0x0, 0x0, &(0x7f0000000040)="bcf02f1785a92e9ee0f5bbed4165c6be33", 0x11)
syz_emit_ethernet(0x2e, &(0x7f00000000c0)={@local, @random="f644322eee7f", [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x1, 0x0, @broadcast, @remote={0xac, 0x14, 0x0}, {[@lsrr={0x83, 0x3}]}}, @icmp=@mask_reply}}}})


r0 = socket(0x2, 0x2, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
openat$tty(0xffffffffffffff9c, &(0x7f0000000000), 0x10, 0x0)
pipe(&(0x7f00000000c0)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
fcntl$dupfd(r2, 0x3, 0xffffffffffffffff)
open(&(0x7f0000000080)='./file1\x00', 0x200, 0x0)
write(r1, &(0x7f0000000100)="63fe0000003cacbbe9b6c0106db2ce63f500040000ea724847f1bbfc583ecdc469c02328ef940200005bd4621381dcb294589502200000002c00000093a1b4406ba21caa7b88f15d52d70017d8ff86e5564b9cd772a2fb8c16498fb1bbc1943f78ae8bae338eed3c6bc1141fe6ebb3b5bc20c85b99dc3556ffe06b9ae74dc3da79f0f646d40000000000000000000000000041d34b27", 0x96)
sysctl$net_inet_udp(&(0x7f0000000000)={0x2, 0x4}, 0x2, 0x0, 0x0, 0x0, 0x0)
openat$wskbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
minherit(&(0x7f0000ffc000/0x4000)=nil, 0x4000, 0x0)
r3 = socket(0x18, 0x2, 0x0)
msgctl$IPC_STAT(0x0, 0x2, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x2, 0x83fe, 0x10000})
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
seteuid(0xffffffffffffffff)
r4 = socket(0x2, 0x2, 0x0)
r5 = dup(r4)
setsockopt$inet_opts(r5, 0x0, 0x14, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffff9c)
close(0xffffffffffffffff)
setsockopt(r3, 0x1000000029, 0x3e, &(0x7f0000000000)="674cd6e5", 0x4)
writev(r3, &(0x7f0000000080)=[{0x0}], 0x1)
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000100)=0x7fffffff, 0x29)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
open(0x0, 0x0, 0x0)
select(0x40, &(0x7f0000000180), &(0x7f00000001c0), 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000380)={0x2, &(0x7f0000000140)=[{0xb1}, {0x6}]})
syz_emit_ethernet(0xa2, &(0x7f0000000600)=ANY=[])


openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000100)='./file0\x00', 0x1, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f0000000040))


setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)
socket(0x18, 0x2, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x9, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
getsockname$inet(0xffffffffffffffff, 0x0, &(0x7f0000000000))
openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x1, &(0x7f00000000c0)=[{}]})
r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$PCIOCREAD(r0, 0xc0187009, &(0x7f00000000c0))


mknodat(0xffffffffffffff9c, &(0x7f00000000c0)='./file0\x00', 0x2000, 0x48b4)
r0 = open(&(0x7f0000000200)='./file0\x00', 0x8, 0x0)
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
socket(0x1, 0x4000, 0xdc)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
openat$vnd(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x8020697a, &(0x7f00000001c0))
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f0000000040)=[{0x7, 0x7, 0x9, 0x8}, {0x422, 0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x27}, 0x2, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afe", &(0x7f0000000080)=0x19, 0x0, 0x0)
open$dir(&(0x7f0000000000)='./file0\x00', 0x40, 0x14c)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
r3 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
r4 = getpgid(0x0)
fcntl$setown(r3, 0x6, r4)
msgctl$IPC_SET(0x0, 0x1, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r5 = msgget$private(0x0, 0x0)
msgsnd(0x0, &(0x7f00000000c0)=ANY=[@ANYRES32], 0x1f, 0x800)
pipe(&(0x7f00000000c0))
execve(0x0, 0x0, 0x0)
msgsnd(r5, 0x0, 0xffffffffffffff6d, 0x0)
msgsnd(0x0, 0x0, 0x401, 0x0)
open$dir(&(0x7f0000000440)='./file1\x00', 0x0, 0x0)
open(&(0x7f00000003c0)='./bus\x00', 0x0, 0x0)
shmget$private(0x0, 0x2000, 0x0, &(0x7f0000ffc000/0x2000)=nil)
setuid(0xee01)
msgctl$IPC_RMID(r5, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{0x64}, {0x3}, {0x46}]})
syz_emit_ethernet(0xba, &(0x7f0000000080)=ANY=[])


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x0, "0100012d29fb000700000000098002005e00"})
sysctl$net_inet_esp(&(0x7f0000000040)={0x4, 0x1e, 0x2}, 0x4000000000000006, 0x0, 0x0, 0x0, 0x0)


sysctl$vfs_nfs(&(0x7f0000000000), 0x3, 0x0, 0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0xfffffffb)
r0 = dup2(0xffffffffffffffff, 0xffffffffffffff9c)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x1, &(0x7f00000002c0)=[{0x0, 0x0, 0xc0, 0x4}]})
mprotect(&(0x7f0000223000/0x3000)=nil, 0x3000, 0x2)
clock_settime(0x100000000000000, &(0x7f0000000000))
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000180)={<r1=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
mprotect(&(0x7f0000c57000/0x1000)=nil, 0x1000, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, 0x0)
syz_emit_ethernet(0x56, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x52, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r2 = msgget$private(0x0, 0x0)
msgrcv(r2, 0x0, 0x0, 0x0, 0x0)
msgrcv(r2, &(0x7f0000000140)={0x0, ""/12}, 0x14, 0x0, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x5200)
ioctl$FIOASYNC(r1, 0x8004667d, 0x0)
open(0x0, 0x0, 0x0)
r3 = open(&(0x7f0000000480)='./file0\x00', 0x80, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
msgsnd(r2, &(0x7f00000000c0)=ANY=[], 0xb9, 0x0)
open(0x0, 0x1, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSDLT(r4, 0x8004427a, &(0x7f0000000000)=0x1)
readv(r3, &(0x7f00000003c0)=[{&(0x7f0000002580)=""/4096, 0x1000}], 0x1)


open(&(0x7f0000002600)='./file0\x00', 0x78e, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000))
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
sysctl$vm_swapencrypt(&(0x7f0000000000)={0x6, 0xb, 0x1}, 0x3, 0x0, 0x0, 0x0, 0x0)
sysctl$hw(&(0x7f0000000000)={0x4, 0x1}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
sysctl$vm_swapencrypt(&(0x7f0000000000), 0x3, 0x0, 0x0, 0x0, 0x0)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x3}, 0xc)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x34}, 0x4, &(0x7f0000000080), 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x400, 0x0)
socket(0x11, 0x3, 0x0)
r1 = socket(0x18, 0x4000, 0xff)
r2 = socket(0x20, 0x8000, 0x0)
dup2(r2, r1)
sysctl$vfs_nfs(&(0x7f0000000040)={0x7, 0x4, 0x2}, 0x3, 0x0, 0x0, 0x0, 0x0)
connect$unix(r1, &(0x7f0000000100)=@abs={0x0, 0x0, 0x3}, 0x8)
socket$inet(0x2, 0x2, 0x0)
socket$inet(0x2, 0x2, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
r3 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSTAT(r3, 0x20007465, 0x0)


pwrite(0xffffffffffffffff, &(0x7f00000010c0)="92e71a54b328bc568d067f9bf4a2ed3bfcf65602d0d14e5c75f01e49bcb509cfb9de95577291580d4c3f10e99062bb5fc6f2dbc78a827b28c0b193e81365d141fb78e901490077a38bb0157f6cdde67519140d386017fefbd63631d14f78e8c6c7a3c51b5985eb03b3b7734ed7d0214e599598c4e128533fd5cd490b57e3fe7aff0d035b5afe5d6e37ebaaa94534b57b62080ad6fe00a8a6113914f583f6117593f0b59b675676e5edbfcec08fbff8b91d978355ea35f55284eeb00afdabf8204f694cef41d672a32ed05a753649d2612849bb5adae07897510243406eb86d4342bc18a7e8a5e13f4f2e19a222b01cd14fb3df28e4f66df92b777ee6ec50348c892cf74fb094371dbf3a4cbba2ff9c8dc9692bcb34d023bfc270d6cf02b5b26b46cbe03351e086bd484dcab353c707183dbf7269d1e26aecd4f1ca8316829543bdad6e171f2a65efa944243a50da0fad9823ee2ded4dc59835bdd283423bf9513b796bf330c837742431b36953c5a00b156a37936fe8d53e7c00ce637a05741fc4e26160992ace7b9ca6b4a036e496ba311570fe34078184e9ab9b8a4069a281cfa1b8d38eb4eefe509d03ce774c6d34604cf589d9bfe42e04231dfd21a019a75ac2ea8c73cd82dccd9e97c168187becddcd3c93a572e621a0a393264ca7cc7324f5fbb625834f9ea3d1258f9d614d64a3286f1cb9f0ada5586d0b17e8f731845e46ad0f2fa0a869d169491fab6076ff1a77ff51d8ceb1c32f8a581ced072075fd91116fac0dd0a12bc5c11074f7edf3d6f5c495105d3db62339103417a801dec7c4770de71dcac74d4c802bb4028e469b9b61e9caf7a194b277a256aaa3529fb458c7253077f648917b9ce41c73e0920f328520fdff8116097ca445c16011df1bfffb994fceaec719438a50dfa3c626b2adf5c632da2547649defb417da6f47d0b1824de5a9219692220bb2893c3fd9b3a1f131bc547c91c46cf688ba7b0024a8ae23c5ab271979c7c90546506076e6f16519ce8aeecd8fdf28f9961fd74f67978613704921d4ef2c76a294cff3b906871979f2c89a1740533f387b05834f0c3363b72f14720e4429ad58400d3b7c2034684458074fef11b5c1aa1f924f8e465b90ad492439f7fb7e8a643995845822b83effc9ddf0508cb9d2ae67f1b3461b0d791775b1e1adf0954c1e06a111d3795caeb0c74173a6f6bf9dfc1563d2c1c993563d618558c10bc07eac727a6a66c375835a7cd79cbdc128c5cc7c6adabc2e5cc3854c28153d4188734e87afae3503a99f157d2e938c5c353062b5b6ce4c0a4aedfecfd5df734835928b3d7ab00f2c1953f4bd4637e59a62a4f0221e2b2d28a21e9521f9f3c9a0c377d5494d5a87158fdf4293ad8065957a952c7f4bc57f3bc952c6b2f859696a3693c92f7ab691817d07854778cba6be9bc700e2fd717489a840ed07a6b79968dd560eb0c872b8af5829ed91eff8a1136846aa79e126e2d7e21ff5b7268a2bbdaf4d8213370e3c6c13952452bb0b5b979f12b0b1e061f77c18b4f4244d2c8ef35ddf614cc83e18ea447d95d1655f87055ea16407fed39532bf09bde067e9dc786008bda875d9d1db4093a8152f371bf196189a997a9bdf645487f3078aa73ee887ead5407457ce9323215895aa65cb617b99a8652fb18cfcc821acfd9bf95adaa8b65c17b74515e7a5acd6c8c7777426c0d8e836e0cc4fc385e17825343c7f7715ff880d96febd3c5a273f92217b09d31d68bc96a95f39a2158a7991625c477fd904e60b2311eb32e8be18f98d1ea0ce072548e109eafd6233ff556af1996138e1a77a891e3d4b272a9971a95b23495dd4d3dfc82cc897605d7cee98b9087269dc6d8dfbda570dd33cfbee80a6f41a0be6a9e4a2ea8775d3f327066e748ffa870d42a67fa49a677e9692a7bdbf656ce133965b67cf154b4b4efcaca94474a3b0b3b6e271427bf3ca9b0362c52f57fa92390b284ff8031f2a6ceedccc4f27339a7bfb52301dd2be98a25451d0f7da34f8bb3551c7f4bb73dc0c3b960977585561ad9a9f4a76032ae9aa79e8ee7041f01978a5cbbfe9780fa93ee30e5c20888334a46c4b63a14790c547e05e50c1f2fea73ce27cf3e7522d19ffdf7467a75ebd92466bef6c45de62e3422b08a824efb87daf3bba9cda701c361fe68eeed90167d6609362c292181717b527bd9ba1d634c3ddd2c998b44c65ed46bfba6a9c25c30cd5a91c2c23b3de263f9f0f9c181f9decfe09edd9c05992d62503aee6d90f5e509fb0d85f587c08f3db786e7f391a4e964e0d24a4f119230fbe83994d7458ce4a38414723d987c7a3743b8e9ba1e6870cf75d2fc3972452d5e990bb894f5b15aadfbc1e605d346f33c0904197d8aabed2ac2cac3291154fd64d97799efd85ce92d71c821a060ca5b859a10dfc69ff5db30211a19e1d0c36eaf3685950d74db95122354d4099ba54503ce6f93d933c79194d3f06c5fe80abe54c3ae7e9f8ffdb85911223f04bb6e5513a57751ecc73c0382befd11f1ed1db2a04ef28a3a17fc960340c5371e2f057c2e2f6af56664d2728ae49ca438fe2dc9cf82e4cf2d8214d4ac366df60977188bf158652dce6a6f8e1759240c68c5c56f3b0b93172f9609e76f1e51410ebac8c7b953efc3c0579dd6676e892e14955de3cf330e360199a522f3dc89743e23d414da9302cf570bdb6a21d170a74ec71e8252063d447a4144f637985580a1ba4f88fd1d710617d6a67fc53c35e08e8d307625bc6ffb527d331cb1453ab51cdf994e568f45538046a670229328451325158f3b5064b52700cb0106ae483e41911d6d1ee562e89a7d2e0f35c4b844644b8e5c03e18b24865c6d6f5149f6f2498bc194e399d0bdfc32cf796bbe3da17abbf92f18dd161ec7622d46ed2ca39482248bb86a3eddd99e49298420500cc3de9f19995a5f052cfdfea82cc95f9ac6b8b20a7237c577f0ee507b38a2c3f59c7b2c48b889f89edfa3ba3383f4c64ff85a5ee40991eb8615561b2de4eb2ab82ef8007e2ac62232dd53d6c503ef9d9aa24fa606d9463b0cc85374d5e300207614b8f482a870d649ac91a34ca8c4c3a442d27ca9728c52f00ec6641004e6c675e1964ad7b1d927fbeea71dbba06ac2c23b785f1c6e2dbc945f00952680242c991d2b4a0437056a775a51f9f0cd9dee3ca5ed9faf5cd2f43a2ec38f719a76e9aa81b096be6c062aadf7de4bd7dc0af7aace17ab4eca5517faf8af223998221c1d20139e79366e6b23c086592becfb33dfee0245177ec939acdcaecd4d6d780746956545933aeeefd3eb5e69ee3bb77534165f73d41d67b9f2ee60c5903cf0b9bbeaaec3705f45e6440770dc05c5a9d4f30a47d9815c6e014a8ba6dfbdb632e1e971d5780194588475c03d42b13135a061c64e0d8cac4a2117993236494fe87c31c3a06d6fd65c2b0a3a4a684972296e167f8bd1808400d5f40816f13163f1e8d00d18a7ebe48e1f6a2fa4d05b8f233817849c5f029105c8fbbc4644f4230ee3e0e6c0c632db913be2a5ed221a5a649707ddadaac3eb38395f8b3874775d2b84ee442cfc21f1531038b4601885b932dc7a4c3bf01fbb898720c5ce84bb9d1840e8394b58217476c5034d65d24eeadd6cd129ffbcdcdfb5b3beb4173cc94e701378f31317c442df3deec3dd79ce541bc035882672b2a22051c86e588c7913f06fb99851edcfe80ee2ee793ade24e186f7abf566705853e92694304a30556173e7766db64108aa29741011edd4269ae2e6766a6661306bd3266e040966d6d1913274306557a6e70b5f5e1597da53129f7332fa85aaefa7abc41be887b6f0fc461f0a91abc49a0a7c9fb5a7c24a85262a31d13a5bfca17dd01434c03ac2c536b9eb671f951a89c8b338965f931b48d3b0a996308cd7af7906adf4361ac3152a7aeaabc0d2205344b171e5e13e851d4c10cfd7b0c0c66eae44531f0f28802d7c8fa8be008713a1f8e37575d7e38a25265fea7c508857c65f211b288034cc7a4c8e7ce6a7d90042035e9b1000000000000585795692b2649747195cb2535f04453db641e61ee4eeb8ccce49a6ba3068741bab2dd143a0a814fff9eb9dab6466570d9427cf93efa6c6cf1cf72a99662d409553c578b2ddcfc1d3d640cedf3b419e92297bebaff99c2f5ba701cc7df7929e46c548c3a439750ea0fe3dcedb281753cc5b6de1bdf5fa358dffdb8cc48d7c9ac13919527b2d20f80bb72b6c777ff0c8181273a6a26d90f9f245d47212fbf3fae71bb1a51d21b6c3f9cad1d895dc6b215ff27d46adfcbdfba410e84eae64353e88915a27a252a4541ab589fce26fe91f24f0cce058acaafccdae72c3df741f40b4a73d5a6f89a4b7b1ef31bc1cd7ad341a40c13d26cb23678b13b115b25f26eee3864a8452aceb7a3cbf6518cc488f925263d9a642b4a3c7b77fddcccad9184711a7f27de63e90684ffd84082b65cd80b4f3d4793965152ee9f347517fea5f43b3dece277c70bf6c7a7dc10e5752b49d641e56e89077209effc2aa2e489d8f5d6ed7b1925e62abbc7114156a48e71b930e006daab1741173f19f67789d00099e5b7850c4620659e36c223015cd19fef08247a6df9383c75a7c2bc909309e1ae3ae8e7cda07e2c974206059edd8f9cd852d5b5c170cb418b22357e069b2e8fefaa492fcf2f18d9459cfcff960059f507b5d8332f5fc3c6d10f3d05d4c3777961351062b28ed0a1a7b00f27ebd86a4bad93c1bb6c264e95257f0583ec4c765bb6ddda0815e14c6443a058f49cbd8d77991c98f572ca4a5e1acfc12a0939de984a0522a249a6cb162f81ac67ef65cf85597efcfb87981983773edb5c56782509c2d6b21545cc0ffb4364a02838c2dea36ddc09a86a727be740f465ac58240de204a22ed64e99af51e67a85c74fd8d5cd2bd03a0bdd0874d2b788abacacf9ab15b273e3be1a14b6999117ddd3d12ed035707327337e4a408dd18f0534cc98bea6a945457b059ad5345ab30ccfa9844823cad0d1a6a2cd3a402151b322cc7d57b88145a762f004071c2b9b05116bb81ca4cbb560274aae8fbc32259ab5ccdfd722a21b466e5ae232d3468c81f3cd4bc383fae25c4acdd868e041cc0d56481a98a9f91f4edb0d3f42bbd5c22c230d4a122970b604af72f4ac2c1e84aedcde8201e06023323b6f97f5909fc62760f92f386f8a9a12f0a8d3717be20a68d9a5e7a7c390a3f2d2a2803364ff9532f71e24f3f84a66e2c5e8b17e4573f59fb1845eb44d91a641b2ed9441338b0cebb6391dad07082adfc83b79e4ebcc5e786294fd69593f464f62e940f17b56b661ec2f6356832102b02a51b0660887314c53eacfd3c571ae5f0aaa45553755786c161942c3087cea2ab3040d0cde2456ddaeb3335c3d429b4f3cc7795b86d8f296cffaf9cc88f7f60733930ac75bee10e8614c810d07461f5b45927d9b3bb9b689823a6d6e6b132df2f4489b119d7ec72bc695b467921ea87a09491287d72d71bde2c929eb4b05ff2347d1ab34d7b771fcced40f4bd980cedd0a4033be3cd902d3b9e5d3de8acef1c91b8445dc387809963956629a335ec69fddccfc2470a999a49bfcc57f7875192bf23154b20f325457515f5ef8f01558e304191f43947fa9d6256ef7a63415c2e5cbe93c6e11d54e69299bb37d38f25b034d36f4f017b5f80d2acd296e0790146d79c567c76382c2d83c41d7fb03c369ba3213b865546c1859d317f6f660abaa6c27598415c97341a17b56c97d262d962cba25c43a2724c8aaaac0784cb45f0000000000000000000051d6699d288b9038b7a330c41453f5ab69e31cacecdbe0a5b734e12f826d47011763d05024b45b1a24dda7b144cd06a45321d19948e7f3a37c01e6ca9ee759b6e53849796e4ab92c73a52d6c9d3baceb1b1028266a56bdef5fdbd4e1ec5261344794a8c8bf6ff235729b650b4b72c892212bad2f24288740921f1b75fde082721e2d445ebe5ab8a317715ee2e72e2cf38a73fcf231a02b51d10cb329f0e140cd5e97ad6ae5bcb164e09e0fa25af592a335f67117fdcc2909838c02337e32e2d888bc60fe0ee64d5e2a0e4257f7d8c011372347a95c1becd039358b26f20df4b08d7b56f4ee1c935ae4e030f9179b799a03253ecc5b7250f0fc61b8e7a6926a27f2a24f9a969a39f55ffee2eea37c86e1ba910e44627681ae9d3458707558b186462ad116a3e67cfdb6e47d5125bcb5fa48", 0xffffffffffffff1c, 0x5)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000140)=[{0x20}, {0x74}, {0x812e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = socket(0x1e, 0x3, 0x0)
poll(0x0, 0x0, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
setpgid(0x0, 0x0)
getgroups(0x1, &(0x7f0000000700)=[0x0])
sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f00000000c0)="964b2e8c33c6b9184c54128f975fecf28b35a6b4fe6c2c7decb370e1ded56c32941e0b88ddd1b408c2570ee069d4b5d9fe2d8c0e0e6fcae82f887c519aef0e4f551a8da94ec5e94e8cc86014dcae87ce36ccfa7db954ba0ac2262672aa4264b2ec6ad65c12edb84ce1def64f79b40d76e2c7318805285dcb26b2adfb8bdfa599fa5d155b68e34a92a4e96829325b7b8acd8cb6c66aa407b4ff97282541ca92edef6fc0382c47bd1c63e463375341590f6a327092643b98a174e443c056da46158047e0b068975ba714199a52b4034fa4364e7304b31dd9dcaced366eb800389ecb0e1c41c6058bb7fa03702e8a03363bc593818269f64a0be94d29087369babc60ce10bc4c561f687122c1b20dd9f10518", 0x111)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x801169ac, &(0x7f00000001c0))


r0 = socket(0x2, 0x3, 0x0)
r1 = dup2(r0, r0)
setsockopt$inet_opts(r1, 0x0, 0x1, &(0x7f0000000600)="ee08665d19ac14d5e5134876f197a7728420aef6171504b1c3d4b3830c921bf0817a0000040000006a89dbdf", 0x2c)
setsockopt$inet_opts(r1, 0x0, 0x1, &(0x7f0000000440)="1f", 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000100)=[{0x1}, {0x44}, {0x96}]})
syz_emit_ethernet(0x36, &(0x7f0000000200)={@local, @local, [], {@ipv6={0x86dd, {0x0, 0x6, "5f6ad9", 0x0, 0x0, 0x0, @rand_addr="8a211dd1450021b07f5a1957de7400", @local={0xfe, 0x80, '\x00', 0x0}}}}})


syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, &(0x7f00000000c0)=0xfffe, 0x4)
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000), 0x10)
r1 = dup(r0)
listen(r1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1002, &(0x7f00000000c0), 0x4)
r2 = socket(0x2, 0x1, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x1, &(0x7f0000001340)="0315f1d89ec5a317a9357682", 0xc)
connect$unix(r2, &(0x7f0000000000), 0x10)
write(r2, &(0x7f0000000080)="04bdfa5d1d2873c63e3534825ba166e2fea9aec43050006123339a346f731573d8d508753f95b7688ad48b8cf6bbca325cebc37fc4e1dd543dbe2da6dd", 0xffea)


open$dir(&(0x7f00000003c0)='./file0\x00', 0x400004000011830a, 0x0)
setuid(0xee01)
shmget$private(0x0, 0x4000, 0x0, &(0x7f000055b000/0x4000)=nil)
shmctl$IPC_RMID(0x0, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
truncate(0x0, 0x0)
ktrace(0x0, 0x0, 0x2a12, 0x0)
ioctl$BIOCSETWF(0xffffffffffffff9c, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x0, 0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x37}, 0x4, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x19a, 0x0, 0x2e)
r0 = msgget$private(0x0, 0x0)
msgrcv(r0, 0x0, 0x0, 0x2, 0x1000)
r1 = syz_open_pts()
ioctl$TIOCCONS(r1, 0x80047462, &(0x7f0000000000)=0x7)
ioctl$TIOCCONS(0xffffffffffffffff, 0x80047462, 0x0)
pipe2(&(0x7f0000000340)={<r2=>0xffffffffffffffff}, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f00000000c0)={0x7, &(0x7f00000001c0)=[{0x0, 0x0, 0x0, 0x1}, {0x4, 0x2, 0x7, 0x1}, {0x101, 0x7, 0x80, 0xbb4}, {0x7, 0x1, 0xf1, 0x401}, {0xbf, 0x7, 0x2, 0x7}, {0x81, 0x7f, 0x1, 0x7}, {0x8, 0x20, 0x14}]})
r3 = open(0x0, 0x0, 0x0)
writev(r3, 0x0, 0x0)
madvise(&(0x7f000055d000/0x1000)=nil, 0x1000, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000140)=[{0x0}, {0x0}], 0x2)
msgrcv(0x0, 0x0, 0x0, 0x0, 0x0)
msgsnd(r0, &(0x7f0000000400)={0x1, "94a54dc1256789520e2f43efda42aa69e26fdb885603cf5eb870d7726ebf93dcb89ad9300017c4d186c40457720226912126edee94530eb87b7b9996348c396a0e494060528589c1c1643d28f1b0dc0638c9e8c79068e27ef2e90bb3ba2fd5426ef8416c1d3515f3d1a1166ddd3bc35a0fded467451b0a7b74ac0f1ff276ebd0d5b3604f4ecbb91502e381f3146b978acb4f76e58da9a097859fd966182b8192c2631c01a27bb86bc3e8c7977bf030fa861343bb09e7c6ebc7ae1e3039bc86b78b70d2af6b1d64c745e1ff9436ceb3ea14643502737a710bf48ff8a1cfca01662fc95bd4130e3b98b498c3769e95a95c155ccf9038269639809e1dbd095fd276e463768ac17fd9f4a7c3ea6232aecbfad992f7633e7bdf21d6016880c24a226b9b9df6712a87a1492404029a379a0f2e06aac6c032dbf89cb92aa413595d56615efc07db6298ff5843140f68502796c4fa8aa49249e0689b97f36448bcd136ba78b490ca9450c673ed3756adf44ec2f694623856de7dabbe43c1d0b043d1cc5a6c71f5491f6f64053df08158c19bbb209b0045b34f2e74460a767d33580cd2b10e86bb2f4dae6243c8d7bca09548394e4d8bf754fd77b19f906a92f992449dc272fda50570515cbe495e7bc68e76a072cf0dc6a868444b966acb96122c3fab2e8206768781b433e25061348dcc01aae491649fe70e27b043258bc322a0f81bfe90e9847746025fb684654c34f54c8d31cd22520633b0aed1d4902c6a5bc5a44fcf68c2b30d61f09d720551a5bc6e4858d0612703539a6e90e443e43f1a90a80de20a68fc25a3ac3c75d628cb08ae2282f9e6488bdd24bd949ebd7588552ec62a69484cc9f9d23377cbdae33f8a663b182a543ce6cd64ae7fe4c5a9c56d872b7b906d93386da24f3283471842b26a62ed8059608a9d2d27df81d686b5e5fb05c969dc609839d8f036ab479e6ee334120b7af74e4b98302d542dd48b76cf6a8aa8478ff8158a136a8240a6d77034559eaca04664ea217bccd16a597e6e3d7a4675252f5d157322594d79ebbeaa7ec4c9767ef9eb0331214cb8822ac84db94e946c48ae654263c692732ced223e12d1f3a211d3a48d5e0ced2764a39585f17c0418a1a0d1be239877f3b2d32462390eb0b9b4056b352d7e6de52d6aa6216fbed577222b353a118e322329a8b982d5c4edbe69b29aa023bcdd2cda9394322adb2507e66f71090bb7196557891fa83620299fbd60ab8a45d9f30a78335aa68aacd1d6b520c5666e6eadd284e660e15f7cb53226572dc513653f095c275b72a008cbc1ea8735c2239c866af3913fd7dc7bbfff540e6faa78a1748829108f5b4019ef8bbf0ac1e39b5fa31a8b84827fc592611e0b7fe5d69236d1ad4411561a4100af0a1d96908459858009c1ebb14009f89ae2756be3ac43e86864c4f61e17b65176d7fd392938b2936514903ecb5d95f39de1f73f0363b9156623debfe7b483af93659fb7d815debbcb3786e06924fb91eed32667483a026f2ee1be49e651a1e43d32bf2a8cedea6161bd4661f8732219a366dcc2134361c1d258aeecca5a7bf1c27da8ed29e1a28373619127c78a7eb70cf2293975a5b9b989edf584f37a6ddb70f9087f14b8ec3577650fcad91714d205a237dd231900ddff921668267a72078a983c8e545369bfa2b5df84f26321c38bc4a7321313e7e1312528691a9405a2a52847a1d8697dac1940620d4f1ac17b3219dffcf18f4749de88df3549f006f10ef28b9eb75279e26854f55d540985a4ee30647e212db1816402e047a1963b0fc204bed6031c84341e14ab6265024bc95cf0cf4c85c168dfe793e91bb49ac81f9ce470f0548e762497a7c9b52f1b0a225b34ac04a1f990aa8c3691054fa69e42071403837cbb5c5cbda7cd7df364156b5bbb2caa2dbe0e3619e3e80eafb1c2b685eb154204770af435fe46d02bdd2b6e93d4514d7a88ed90aad80427adb90782d0ae92fbf7993d31ad3cc11ae72c891e9524fe73b54137591aa4d0b6ec49d6ea4a27ce6c1735a83300293ad0ebfc3e5fc6f34ad62f770f46ec7c4874b71d3e46ca7134193c1fca014689ae471151b42f426289f32b1d4270b79174bdb3d9c69351e83aa56260fef41c636e4017a96cbc233449b964cab8b9ebc47c51cff4125065d9b8994144ca37ec57941f1e7d11fb0e16122e807bbef8bc48253bbda51c3b551cfb902f21210cfa73176b9a7a2d293ea76355c7e7c448d2dcb820d0701cba2d79cb3d88fb7f11b44e224245589f38247c7fe62fc0a4c5c0819eec94aab68b4358f455e3e051744ba922b36c44a55f987d2b19a5bd8c701714bd2d85ae8dbfd4338b2a625843b9c831b96e4ca84bf556f616db35fa086c136c85a76b8811c650544e8b609fa398176106c82a0e62795126e9e1b079f67a8caf16052a66ed00dd6ee174b7d2fa82a77da410fe36d44b39f4aaaabef6d953ef3c0da2c27f2c24294ae29dab1852bad6c75c4dd5c8accc3589c55ebf623dfd8732cb94ba8ab1f7545fc39e0ccd8a5b6fca496fb4f1b79d150d0bcbac2825fc5c14c1aeb32420b72356b7ea97fd28d7391f5574557f204f553518ed1f766bff94daa9615ba06b3c1bc9451aa840c92c9cc8390c2a55150bea91f8ed6a3a7de3149595c3d88168613de3528303b3f5c2d96ce404efe074137c12a47a174cbf390834c5d64e34644143096d80a71ce22318e1c9ec498fd0e8f481382d24f303d0ef59360815eaeb520a597993979157c514e0e9780c81f46c827dff7c496fd5bc7cff6fb67aedc5e8656669ee58ba6e2c79d27f42e256d581d42fbb5bfca562a55baca551ca05b9a4faccefa243fc27868fb056f4ce4b9dc14828bd97dfe2716d5fa77e4896abb3f6f404f6dd9367963e27c202b790f9ea77ea9f36f2161c1376d7b73f008cf337810f492748ea772a6c850b5cd2ff6854621aad49e307da6edf69addd094e1c1372378fdb7a4d1d6b8762031ac10ac85c8f706582a9e561fab4f1191909013ca67be4a22a39313571693ba8b4b441ea7c76774f11d3ffc1acb10bfea7a1aa0c1bc92f77a2d39b3859b9ad1fa05f517b5da2e8a75f35686b64b400d0029a5d6549fd62bfbfc028a304b81e119b7b61b42310ce8a40a8543b571847b3cd7e23c20d37c577d2e25c9be420669eb2dbfa1f4c5e66907f0eabe42b8640370004f16f16aab560591eb4405e2ad6141af1fa15fb0f9b10a7259d4c693af31457c17de012ee1697b31e37827b88ce666fa957f924041ddee5a6568ae122ed3dc72d1e7ef9c7e5cc13eec5119fbbf47cc83d36613f7175b9f4e63ec3ca19a893ad1f522c8c7dadfc4af5fb5a9445a6c5fbb2d2fbe849fbfded9add8b1bf3ba2e97d44bbbc0b1ee34038f7770bc697f3a88cefab8d9bc88f06ed7615731ce7efc5768d962a1a0cd2f3aa9d12799e6d16173fd21cb5b70ff4865c24a0638ed935781fc00bdb7786c2ec107763198017c39dd2cf07370348f5aac29fba587194db4d574fdc91660f3210d435c49fe30852bb8bc5e98d5894969f1ea2f1cd4ec552b75000f5f609067d411272b8d0843670a234994c2580a2bed8d7e11b8104e830d1c30dce567066914a43eb7f4127d1bdc8d6342724c946b1613fd8d0c3ff8883e1cea961de28a6b86cc3e61c5b75bf56c80a984f300cef7a128109327b6fa689acd9243f006393d655c37e2664a5ac9fe887c6bf0edd5a56a942ad86dc7f4ec250d915e85f2dd4df1da810173c943b5bce628cd3533ab50252719ab8ae69421be3a15c1323ae806b038584e8bc4b7dadbcf56d02dc4bb4d1612428340070393ae6bc219343e9300dac3b2e0b58e9bf1ad188bc55d4c28ddeed7a76970e6891a9542de6897ee55d6ba93de5f6d0fc3c20169165f79408eb005f50c0509fb092f2dcd62c87a610501ec3d8c2288d5820cf58ac77c6d014837c70979928f4208146aa581afdec0bac9eaaeb62216702f5f1f887de4fff53591a9bcf87a0e0d5930e85bb1254fa9110b3ef97098712da5973a1a1709e27b481aeb9578228c4bf792f57171199a9eb52f51bfdc50f2528d0e838cc7a73effa14ae58af9844ba13d6f20bf065d7dde046d5989cbac53f6955a5cce648b828a0fbb3298310be396b6807cea04a6c7fd19776413ec2a4a46db10e9fc717700a3b0a2fa96771c19a56c4a88fa21825dab72b8980c0e9c1885aec88e613dbd027d3990ed74a03dfca848ca88826347850e3b5de17e4f1725da66c3a3633d97425377454491f536903b8ebf196a427800190dbdebafc6349fefcc6ba32aee2d24eb614d66af87935b7669d98df28b8434e56e77f9cf7faa2b90be42f29695f420124f157614a95ba92fbde435938647fa60e9579eec1942783e9284e9a5ba49fbd9f37bfd29288c6d5e82d10c3b2a766a72e31d2b12c1052bd0b302b63f063371a4caa2bccfd1946140d69a2ab368ac0f4568b5ee2341ee96c9bd1afd840278aa124a1a815616d8eb4c7ed4764664816d0cf5968770f9f6c23e8b2300266ef7a696f4ba9f74a713e144ae75de7c3f617d3ae115ff3178de67736e6bd3046612703350dc4dc3e47b630c71d3d620bfc3afdfca2b6b6f7514073f5e04b0b150997a305f6084fb29dafebafb25feb8256fd12a59277d9de081fa47166a8f6f3b703dbc6724d02d32063ca2827bd66544236bb8eb3b1019903d21f66717f119b7e8d15cc35c4fa038f091b4ab5485d1fe2ce375e909a95474166b6cf1be4d4bf2ff878810ef4cabf1223e826ebf514b6e34ab00dae0b9894cb062ef6a785cd4b79778b3aaaa26a5a5504834e41da737efe4f32c6eb55172f1e70590a0f523a89768a244d61172e79d4ffbeffaa675aeaa5122bb1e8913f1ef880591e3b9ee8d5046fdb627e02cff938642bad08195723f08965bc5467a7cc499666f533102a5247e611f84c69ff9b6c47fa4e38f2ada62e3f075a1aa65196f3871f966cda13bab414dbf9afdc49c7b59aabdc0daeeb457189693a8c37470267420d9cae5217030261381cd53bdf5baf92667929e64b1f2991baf750030dec94b8cea6b11dc132246a0a549d9b0b1578ce669c0f09a55603df70dbaa5db9eb85ecaf7774eb7c26840805abb2d9b9f8a0452f92c0b298fc4f3199446fb9e13e090110bed11ea4079931f0c4d4190401ca727ccc8f76ae758ec7de62aa379a64fd0e10676d7b33d2c10f74242e5c9face9b17c274d589a9ef92c88c9c74fe8b2a168e8e74e34b2ff8a52a16371bb23c7e5ce68862f0f41804bab9e0d353f3ed05bf56f5bd86c19ba5b1ad60fe82154b1025da3c0a7de46a5233c3cad473e9e1e74c8e3cbfe0132d520cf63b8f22007cf15b84f0cedd1406bd194e4356226dbd933d9736e0c1005dacfeae8b4e47371b8408b9cf4fa96261d2ad60f496cc8536d3216d95d266a3cac363cc6c8cc2c3145a2d57febe42319bd7d2256bd1b44825c65ecc446e71a1eaeeda6e566e3ea00578b618c61d7607dd32396bd98239cb7c21854c6963bb7b640002b081b81629d1191c339486c3762e63e54b0b485e5a207e3e9e8ee3b91022d02a4840437943b297e1848c5afba8b26a0f86e04ceb393e113a070981c2217ca9761ad87be820f0ae6899fc4dc52eba64a4a505f6f0a5feece04b5100bfc4acaf7c6e648bfaf8983e4df33a1365beb18098dd1c1550f4073315b67a312d257cd2f57899dc475b8730e33c88e3348fbd7e75c814c5a314ef05f7ed67a9bc6b644dbad0762482210144d6f868b776334065425a74d1c8c3"}, 0x1008, 0x0)
truncate(&(0x7f0000000000)='./file0\x00', 0x5)


openat(0xffffffffffffff9c, &(0x7f0000000440)='./file0\x00', 0x103a42, 0x0)
acct(&(0x7f00000001c0)='./file0\x00')
acct(0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r1, 0x80047460, &(0x7f00000000c0)=0x6)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f00000001c0)={0xfffffffa, 0x0, 0xfffffff4, 0x0, "474fa4d9159e7fffffffffffffffff00000500"})
writev(r0, &(0x7f0000000300)=[{&(0x7f0000000680)="dd722286aaa50f2a1300184ab8d130077c906ce85cb422a4f2c62cbd29c72c46661b4cad2da173d40b5106dd414d1529058ea57c0b83a2b5cd54ee9cd215eb90eea8e58e81e972fc5235d1cf8d6a5c2243d2bbede201ec8e6828a616309345bbac0658713001c94c8313f478fcbe0f92027aefbb1856574e8f2ed7addb58f9d79ece0c9f5d948a1c5f0e5299550d2a052c4cf3b5c367dad1cdb6830a652b7314a08179a1eb7fa04f32aabdaa403b19758aa4965d925f79692a36c3c5db606fabc956ec9138fc4ece16cdcc4f3a70ff31ceb008a2b93478c5a11b8d18574a3c007bba7764560b38077129cbce81f8ac611fbe3531e715f59336f0", 0xfa}, {&(0x7f00000029c0)="471e49aab0fd752532784bf2515fa242320b4a6e6543ffda060eb842b843d370b936ddaa7f71a0a0c4074da827c862a93983c361dc12dc50305653dd84a6adfc8761f897b60c4dee402807473103485b4475c657ae5428aa89543eec1819c76b9eb1e5c1848e49a2a588ed0f6ac77d2106b8ed9b8e3bf7a033cdd96085e372fde5a0d0e2fa622a7e28febd0934ab925ca1366c58af7e3a8eb8ff419a564f33a00db68da6ec62572fd800b44ddb72a27d384d7c0f59283172e5cffa871fbf54d432e04803f306b4bdd17a8ae02f5634de7f261bf856f7b29c4a8c1f03004f7c52f2f9e6db563bdacf11a4312b36e471badb5937dffaad3492204b136b6c7af7e032a3ca5851a267482edd7e7d92ccb87a8b65d5673815b76e9c1698ae7b1f4b5f9abdf83dd28f7ec1cfb85b91f142276afac2efbe6ca1204a2ea66c34768fde97b6e3ec499757af16215bc8f51325d653dabd4ebd4845684b1610443d845a10cbd974b2019ab2aaa364b771cdc3278d4439b96185ed0c3859ea5a4baaa391506d5bbdceb7f20da251814d96c79c641c12dee3c6c3008dea5b63a8d17dd8d567ae2ef71e10eec7343ade58044f19d750017b393a9747caa8e97186fd10cecb761f0f78928e19f8ffb6b5dfb954d1d90140f6b15bad46f9b7aaaae4fbe2f6dadf2ac7fa305306410a426f3da1198dc24f11845142715e81157342de40463eaeb5787d1f552f98f7bc8ec1477f11332e37e3705530ef8c541edf935da193d01448768fbaafb47d5eb3f82bf3ed063b7827445eab5a8fcd7d99d53b0dde5df24f8b5786d8351244164630515bc0fed985baf297cf2da41ac75f2ba68e432552f11b1d722468ffbbbe6a9ac46102969d269c43d624e218459a8db1b21cfa29109698467a1764e1f68dacfd6038037273063b89f01f1eaac9cf5dd2a8d42b1b6e4a60a373d77a7cd04d7b2b836af003812130ab23f44fcc641672be8e1c451c69e042efb361fbbf25916d4e725e9567d74ced7dd8fc1421c9119932838f3f3f3744d6e7e1c79455107178e0a968ee2f8e893781613452e0d241d0c342b0d8f869c0625dc711f82fd4b6b1ed73f62b1cb9e12bedc5fa2eaf58c969a25dbbce9fd087036ac4b95924f64111ef591d3dd0e905f3c89cabb205ab30fbfe844af7ed55b8cb1a3d4486b0cba74dab7a6c381441630966b0bdb830bf78a9677c64c62c79d165ec9562277f4782108d08240bd5f20a6ba683478ba115732d06b05c0f7eb5e8853600ce62b5a8c45b5d690dadec6b380193096ad5d18217d8dba3cd6c7902519df26cdc69b60278e57e2e70ca3e40459e3b61c295c3c23899923cc8a8745e91ec0a20d6f6e97f0fbad67600e90844f6257ca914e6e8cb5dea58a8be0939f827b9493aa6b3072e6c631a801957dca35357b4caa78b94e3faccdb887ae5c705f53765787f4440a7077baf1c4700f1d0b9c2de9602a940fa7ca022737006fae730003b66588848a757801f811710a078d2c7f91b1f66a01dadebbcd4540034aac930bac2cdffb947b6726a3b266484b0a5c94f6b80b6e432e01b8f89bab377c3f7dc878605ed50277c066aaefc75fa5bb1b4d642c651b4d46561a4eaa9b7dcea3b81fb6133fb0900c86b58f99d634bf7dd2ce3e25a5e3033419a976a476ba03bf690876b3e7c19e8c847293663cc45febc4335c19a81837e61a38b0d71951c305b63105fc9c150822cd35df33f5e459bfbd4c22f03ee3c830cc06cf37029fa9edd3da0930df6dd76775a4b91ac307c4034b1a96859507dd68b3e0befab34c62704f7cb8c44245be25f265046787e67e835a05b5ac84ca95719c50acb616369d213a8753f91c1cfd168cb128109d8de46d5add8377a795259418a03afc15647e54fb9a9c0b0757611968e9424c2848ebde24a91ef14aed1fa1879b51b131fcd441302916164af8b9ae3ce8e86b5d66d58efe5a181b4b4451a911f64267c9b46815e1b79909bea47f5e555bac2287aa1e2de031da61439a739fbc6efa2f08bb804c2f76a28680b29d881ec1404a25cad03445d4045236e3b919130c38efd90451764a9d897e91ac9058feeacb0194788279c02e757eb6ad6c3af3283ba03bd142d2032d59191b89601df69297aa05c95339f70460a68df78f44e52fe19fd2633cddd261e86d11052f6bb0a6c7cb9e9750bc540588d2108e6937bf16218efeddcf9d540c13150b1cbb911f03c0ab569a760f88f518a26798c2dbcc074d18a43d106001ee87eeb81a8bebd5c0a1c069efa9a3c0384514b455871de72160f0a898983f547c211345555d976c795fc1b05ef8706f199930ba4aa083a0642ff8dafbe9d582a4bfa09fd5c9d9ab0a17b361d141849583798f73b08f5e1a2290ec35d256a1399c5eba5cd805dac65021606753c5dcd1262eadf4d3d0af31075cfb71a1fa4dfcce346327495b898fcdebf04f7ecf7cb3aeb9fe99dee2e6734d95667f532c3a997641a53f56a9f2e082c211d4fb5f15a04142fefc1ecd89b77d371e541988cc326dc848681c8413c778962e54324ef1113e7b908558eb49a4617de12d619d16ed5a0224f728a1367d9e5a1773488d7ce986fc4208c35d8797ee3ad33b007849d98225f8003f0048707512002078305b8aa8642cf695833fdc84bb551ccc5ff920790c976a727b7972fb88f8e7272bf2450a18a5eddac6f9e8093f75f85d702307b302a54da7612d34d874bd86cf6934a3162c6745c579d279d5f62d27d0263d2f319e70d6e4d9f8376c7eb93511b07b4a588da9977c899d761811535d4b94f605e74c79a6ae820d882972ba524720e8a814d98fb778e26d7fc235b5b4a794b1244ca878a3193d48321f601d009d810c6c63e7853fa2e66661eaa1dadd55378e8c42d7d3b18996dc4af7b76cd9344dde9046b00f2c2135a71000587f22b5a8999eaabd1d3d15b1ea247f630259afeb5d3552d8b8d25353a45ea93e85f8b62a909a329007cb78d1441a3f88409c9e4a7f5e3a38b3ff8f83e5786214f4635d5602cd6305853225b133e6a44059fc6d88a3fea95b2d15d3ba3a9fa47a77d6a6b48ffe582f23c2997be60db8b496007e6cf91820657a4e10732d3471f128ea972f6b233b04d481c1a14fa32ba6601cc183f675644652d66df2b119a85d1751cd5104f77b7bc30ef503e606c5e9d1b255cc040f9f27f6b447223271a8124da64c1cb39d57c5796571529d7787859787063c3a44addc1c392267477ad30ba5ff674eca98cb2e445d458dacc6835b192e933218b4baf0ccb78228c7e3a7e3290ed3824a9cd4a9e74887bac564fc0097edf2226c38489946ec2ffc2527c9d5e26575da74d376f8080f8c56442720cb038157cbcae1ed319c2688f298b1515dec5a155a7ced1682a0c083934b6e0e806936b25e674148f39ade1d6fa5a554856dcb9984660df0de4245b70a27c8e9cbedc06423ae06ea9a27f7102113c4388befa688c8468b4e2865a94e58f3a2568211911af2aa038767fb7a05018dc45e70c33c6cbab47f81fba0c551d775ac92a1343e8dcfa61f102159adc5eefbff463be23f2278c3c7123465ae1574671ae665a91d1f80cfd9b9cf0b3edf53cc637db4ad77bd436b6bd32ea2f1032aaea3e99c30b7afe299232664b5c0d6d2f3c4d7e6a854c38937fff124977b399fb0e1566245703fbc2a6f666451602af52a979ab1b54f82b346b8e0b13c5019783e4497e6e68ff68236e8bafc37baf5e2b83ec8fb9868b8d6481db9b0e315bd554d8078be2710a7e3fab3ad15aec2062aa34bc67da31edf4bed01fe5630a0800794150856ef0db6f6b9b8e6b9a0a5a96b68d0f77fc4a3eb04cdd0a6f26590d8643b535c89288de0f81670b3f227e53d33c155b74af56ef72db01d191c9a216b48e82214b87d30b510b95dcaaf01748f8c772a271a77eaf30dbe0e3e33e3f319bbfcb4a3dc4c609c2b90f42c8c82861142a8d90c0f40304c7aa40ade9e50cce01ef6f819edd17f0ba3c8cfa225f500f3c4344700f0ee0e18b4da149ee963aac4cce9c9bea9990e20c798d717f7e8eead7c015903a408919cf3498224efc9d2b2c87cb21d3248cb8bbcf7f484fcea6ec760e301403dd65ddeb12b02070f597d48a2a93b89e21a3baac18af30e8678754e8548e573a1ccfaa2f280cf6d845e368cdb9faf5c6e6ba5414b8425ab454260acb52f5dfafacc64e83bda30b0eeb92d0bed8289ac0af11c6fb5e6bb123318fe8361159ca138e34dd85de53d0354c2ab887891dfd62081a7bd5e7ef910a3eab78110ee3cb7828416b51b2eaa3c1ce4c87ea75550e614dadc1ea104a55662c8cfa8a8562b04142d8025309372c528d2a6df1c8235d0df14e4ff5b2da06b22e68e3b62da0855ce7de35578dd1a4e39b0134acb52fb46e86960c6e8453f6bcdced3ea35e8973999c0bc300590d8bb76e48ebb1b8d960e530496f7ceacb128126ccd0341202e99368f2bea76caa9f60ee728cb1337fdfd896604cc9d80e5863067d44176ccc030503c7771123246edb4e2c18c27a601b204ff769f47b9120cb6cd61e723bee4892bb7632a5101adee58880464e6d7a56bd8eaf9b744e18ab2f72f14853ce8a9bf0fb41c5b853473a9f2b7c3a06c0558c653c0f19e5ad8598b21c3118242a226c8d63bc4584d8b1f60f3aa607d4f41547abf2535f693a6903b0d7ed40553dcb28e23d7885cc0aab8b5d0ec81bb9b1de6f3685f70dcbe591163cd4f535ac144776304a06a9c4a508c9798d3039747fd0b739eb6a0081de61ddf5ee31dede9dcc77ad35f9397e1503032697bdd022e29dba0f58675600c420174e707e8bb379e03b7410bdda2f71eecfd92c667ab9191fd1eb82d7745c84849b5a9c7a6daf10838e1b1bdbd05cd8b8f0e4b0a8c732aea7794fd3a06262abb3067a55db9e9740084af2e16587a33504abef0004f86d6fd9197419869806c99dd29ab408c8961d1467cccbbec49f51b3f597412212b849665e251b8ff963daf701e7b7dbad236e47a975b9cb6653017c2fc8db2927f06a0e8a39465db10b6b92e80ac87c00bc291b2013fee8320e1601b7866d7bf94f41cf9be7bb6612457c1c7187bc79793eea40c7a648dec22159196f9b1b27c56af83efffeb967030cccbf849f617dc143b32a49c847cf3579a91fcc2ea8d8d49fadea5462228b079acbc3c4ed37e147568492defde75bbb5f38f172a578de7053d7d7ee2cc25fb38c0a77a0fe41101da85a9f7cb8cab82e012e2867365cd02622dec5f215b2284955afcf74ccd1ef4b25bb2141155b97a0bc7037", 0xe9e}], 0x2)
writev(r0, &(0x7f0000000000)=[{&(0x7f0000000440)="4b9af7fcfcd118266599d337f3ab2855c2484c2badc135683fabf4e02113e2651449f7c04cee40ab794bd047d3a99b65d75b1ecad12e9710e9a4a16efaff6a2405e1e1cde5f1756553dab144cdda592a8ed55973e9f03e9b6fb5dc975212971aaca3fac3e25b7e5ae4", 0x69}], 0x1)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x5a}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)
r2 = semget$private(0x0, 0x4, 0x0)
semop(r2, &(0x7f00000000c0)=[{0x0, 0x94, 0x800}, {0x0, 0x7fff, 0x800}, {0x1, 0x9}, {0x3, 0x5, 0x800}], 0x4)
dup2(r1, r0)
recvmmsg(0xffffffffffffffff, &(0x7f0000000200)={&(0x7f00000001c0)={0x0, 0x0, &(0x7f0000001880), 0x0, 0x0}}, 0x10, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x802069b5, &(0x7f00000001c0))
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r4 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r5 = fcntl$dupfd(r4, 0x3, 0xffffffffffffffff)
fcntl$getown(r5, 0x5)
socket(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
r6 = openat$wsmouse(0xffffffffffffff9c, &(0x7f00000002c0), 0x200, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
r7 = getpid()
ktrace(&(0x7f0000001d40)='./file0\x00', 0x0, 0x1720, r7)
clock_getres(0x0, &(0x7f0000000280))
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, &(0x7f0000000380))
r8 = open(&(0x7f0000000240)='./file1\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r8, 0x0)
ioctl$WSMOUSEIO_GETPARAMS(r6, 0x80105727, &(0x7f0000000140)={0x0})
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1001, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000132000/0x3000)=nil, &(0x7f00007f7000/0x2000)=nil, 0xfffffffffffffffc}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f000008c000/0x2000)=nil, &(0x7f00001f0000/0x1000)=nil}, {&(0x7f00001f0000/0x1000)=nil, &(0x7f000036e000/0x2000)=nil, 0x4000080000000}, {&(0x7f0000132000/0x4000)=nil, &(0x7f00000b2000/0x1000)=nil}, {&(0x7f000008a000/0x4000)=nil, &(0x7f0000091000/0x2000)=nil}, {0x0, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000376000/0x2000)=nil, 0xffffffffffffffff}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil}, {&(0x7f0000090000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000001000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000132000/0x1000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000376000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000008a000/0x1000)=nil}, {0x0, &(0x7f0000092000/0x3000)=nil}], './file0\x00'})


ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000080)=[{}, {}, {}], 0x3})
r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_GETPARAMS(r0, 0x80105727, &(0x7f00000000c0)={&(0x7f0000000200)=[{}, {0x21}], 0x2})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f00000000c0)=[{0x20}, {0x3}, {0x6}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f0000000100)={&(0x7f00000002c0)=[{0x2, 0x20007ff}, {0x3}], 0x2})
r0 = semget$private(0x0, 0x0, 0x621)
semctl$IPC_RMID(r0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000200)={0x0, 0x0})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x100000001})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x7fffffff, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000480)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r1, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "ff000000ff597bd600"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000040), 0x3, 0x0, 0x0, &(0x7f0000000080)="4f1d4c6344b80ed788b6a4515248df3aa745bb992c574ab4cdf5587145812eab4a988f7fafd7a01d99776d988908cd186b51f34f8c15ffa0c685ad4116c783959eff4278384b4000384dbb1c2aaeff10b4135529a1da6fda67c67469d954be811b25ec5521559154c586eefff122009f659cd3e27e98a3241495005f102d9101d158284c0ee3250aa7c11042330de22a299ab00894fdc9bac6042d", 0x4)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b1000502000000000000000001010000331c13fecea10500fef96ec0c72fd3355ae30200004e3003000000acf20b7804bec256699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5aa0400000000008700361b4cc702fac500002021fbfa0c0f00008abf3a2271a3f834371205d3660400"/177, 0xb1, 0x0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x10462, 0x0)
syz_emit_ethernet(0x1c, &(0x7f00000005c0)=ANY=[@ANYBLOB="aaaaaaaaaaaaffffffff00000806000108000604"])
ioctl$BIOCSETIF(r1, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000200)=[{0x48}, {0x3, 0x4}, {0x6, 0x0, 0x0, 0xf83}]})
write(r1, &(0x7f00000002c0)="766dc698d1465d780e0a617cc7cf", 0xe)
open(&(0x7f0000000180)='./file0\x00', 0x80000000000206, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x54}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, 0x0)
r2 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r3 = socket(0x18, 0x1, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000140)={0x4, 0x2, 0x6, 0x3}, 0x4, &(0x7f0000000180), 0x0, &(0x7f0000000380), 0x0)
semget$private(0x0, 0x1, 0x448)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
connect$unix(r3, &(0x7f0000000240), 0xa)
ioctl$FIONBIO(r2, 0x8004667e, &(0x7f00000001c0))
shmget(0x1, 0x2002, 0x0, &(0x7f0000000000/0x2000)=nil)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
sysctl$kern(0x0, 0x0, 0x0, &(0x7f0000000080), 0x0, 0x0)
write(r2, &(0x7f0000000000)='$', 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x200, 0x0)
ioctl$BIOCGETIF(r0, 0x4020426b, &(0x7f0000000040)={""/16, @ifru_media})
pipe(&(0x7f0000000100))
getuid()
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {0x0, &(0x7f0000363000/0x2000)=nil, 0x2000000000}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000191000/0x1000)=nil}, {&(0x7f000003d000/0x1000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f00000c3000/0x4000)=nil, &(0x7f0000ffa000/0x4000)=nil}, {&(0x7f0000157000/0x1000)=nil}, {0x0, &(0x7f00001eb000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f00000e0000/0x1000)=nil, &(0x7f00000d8000/0x3000)=nil}, {&(0x7f00000ca000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f00000f8000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0x40, 0x0, 0x0)
r2 = socket(0x2, 0x2, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
r3 = socket$inet(0x2, 0x3, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r4 = dup2(r3, r2)
connect$unix(r2, &(0x7f0000000000), 0x10)
writev(r4, &(0x7f0000002400)=[{0x0}], 0x1)


openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000180)={0x0, 0x0, 0x7, 0x100000002})
r1 = open(&(0x7f0000000040)='./file0\x00', 0x205, 0x0)
fcntl$lock(r1, 0x8, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x1000300010008, 0xffffffffffffffff})


mkdir(&(0x7f0000000a40)='./file0\x00', 0x0)
r0 = socket(0x18, 0x1, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
open$dir(&(0x7f0000001700)='./file0\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
rmdir(&(0x7f00000000c0)='./file0\x00')
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
recvmsg(r3, &(0x7f0000000340)={0x0, 0x0, 0x0, 0x0, &(0x7f00000024c0)=""/236, 0xec}, 0x0)
chroot(&(0x7f0000000740)='.\x00')
sendmsg(r2, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000100)=[{0x4c}, {0x28}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])


mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x5d4a)
open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)


writev(0xffffffffffffffff, &(0x7f0000000500)=[{&(0x7f00000000c0)="acabcf121c66403989618f102986590fda96cd6ce3e6319bfbfa5f4e11792ff556376e0a66db2064e7fdd436d5e11d47b40f598865ae30e4577e64f3cea3db7406d3f30fcf81af59f08cd850e080468c406a2576d93a6e610ace0fe401b3af94886a9209a9552e5231c14d5842ce811ae17ac41ca78ffb36e5d9a788ac68443f49b920121df80a106ac6859fedff6187d880e9a8849805a46b28e6ef435d45e7e0343d939f21ef05ff3e31f9b2777b169b10c28b07dc4845ed10f14a549e3c0228e974f48b", 0xc5}], 0x1)
kevent(0xffffffffffffffff, &(0x7f00000001c0)=[{{}, 0xfffffffffffffff9, 0xc7}], 0x0, 0x0, 0x0, 0x0)
r0 = kqueue()
openat$wskbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000180)=[{{}, 0xfffffffffffffff9, 0x81}], 0x0, 0x0)
kevent(r0, &(0x7f0000000140)=[{{}, 0xfffffffffffffff9, 0x2c5d36d679bbffbf}], 0xe4a, 0x0, 0xa9fa, 0x0)
kevent(r0, 0x0, 0x0, &(0x7f00000001c0), 0x9, 0x0)


setreuid(0xee00, 0x0)
r0 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r1 = getuid()
fchown(r0, r1, 0xffffffffffffffff)
r2 = getuid()
setreuid(0xee00, r2)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r3=>0xffffffffffffffff})
bind$unix(r3, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
connect$unix(r3, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


setrlimit(0x0, &(0x7f0000000000)={0xffffffffffffff9c})
r0 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x4, &(0x7f0000000140)=0x20000, 0x4)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r0, &(0x7f0000000000), 0x10)


setitimer(0x1, &(0x7f0000000000)={{}, {0x7c}}, 0x0)
sendmsg(0xffffffffffffffff, &(0x7f0000000400)={0x0, 0x0, 0x0, 0x0, &(0x7f00000009c0)=[{0x18, 0x0, 0x3ff, "0f"}], 0x18}, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000240)={0x3, &(0x7f0000000140)=[{0x6c}, {0x28}, {0x86, 0x0, 0x0, 0x7d}]})
write(r0, &(0x7f00000002c0)="c5449bc1708e16b9805a099e20a0", 0xe)


mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
recvmmsg(r0, &(0x7f0000000480)={0x0}, 0x10, 0x0, &(0x7f0000000500)={0x200ffffc, 0xa})
mknod(&(0x7f0000000040)='./file0\x00', 0x6000, 0x0)
mknod(&(0x7f0000000000)='./bus\x00', 0x3a0914c44f7b202d, 0x504)
r1 = open(&(0x7f0000000040)='./bus\x00', 0x10005, 0x0)
ioctl$TIOCSETD(r1, 0x8004741b, &(0x7f0000000080)=0x7)
open(&(0x7f0000000040)='./bus\x00', 0x10005, 0x0)
r2 = open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
readv(r2, &(0x7f00000001c0)=[{&(0x7f0000000140)=""/5, 0x5}], 0x1)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000001440)={0xffffffffffffffff, <r3=>0xffffffffffffffff})
r4 = fcntl$getown(r3, 0x3)
setpgid(0x0, r4)
r5 = openat$wskbd(0xffffffffffffff9c, &(0x7f00000001c0), 0x1, 0x0)
r6 = socket(0x18, 0x3, 0x0)
setsockopt(r6, 0x1000000029, 0x2a, 0x0, 0x7)
fcntl$setstatus(r5, 0x4, 0x0)
r7 = msgget$private(0x0, 0x0)
msgctl$IPC_SET(r7, 0x1, &(0x7f00000001c0)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}, 0x2, 0x0, r4, 0x0, 0x5e, 0x100000001, 0x8001, 0x9})


r0 = syz_open_pts()
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
flock(0xffffffffffffffff, 0x0)
flock(r0, 0x0)
syz_open_pts()
mknod(&(0x7f0000000180)='./file0\x00', 0x2000, 0x202)
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
writev(r1, &(0x7f0000001480)=[{&(0x7f0000000100)}], 0x1)
msgctl$IPC_SET(0x0, 0x1, 0x0)
r2 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
pwritev(r2, &(0x7f0000000380)=[{&(0x7f0000000440)="e9", 0x1}], 0x1, 0x3fffd)
open$dir(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
preadv(0xffffffffffffffff, &(0x7f00000004c0)=[{0x0}], 0x1, 0x0)
truncate(0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
r3 = open(&(0x7f0000000080)='./file1\x00', 0x200, 0x0)
mmap(&(0x7f0000011000/0x2000)=nil, 0x2000, 0x0, 0x10, r3, 0x0)
mprotect(&(0x7f000000e000/0x4000)=nil, 0x4000, 0x3)
mlock(&(0x7f000000f000/0x4000)=nil, 0x4000)
msgget(0x1, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, &(0x7f00000001c0))
r4 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r4, 0x8080691a, 0x0)
mkdir(&(0x7f0000000100)='./file0\x00', 0x49)
r5 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
readv(r5, &(0x7f0000000ac0)=[{0x0}, {&(0x7f0000000080)=""/31, 0x1f}], 0x2)


r0 = socket(0x11, 0x3, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
mprotect(&(0x7f00003e0000/0x2000)=nil, 0x2000, 0x0)
sendto$unix(r0, &(0x7f00000002c0)="b10005010000009f05000701070000000000000000000500fef96ecfc72fd3357ae30200004e30ffd2d236acf20bf404be01000000f7c8cf5f882b297be1aa050400ce94e2f0ad3ebbc257699a1f139b672f335c22db830c032bfa896443c32118210000720fd38bfb0000fd54c125191b1257aea8c500001602fbfe0c2300000100be0900000808e37193f8343712cc11fffffffffffffcff000000000000000000007f62b60beab90000000000000000", 0xb1, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x6000, 0xe02)
r1 = open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
readv(r1, &(0x7f00000001c0)=[{&(0x7f0000000140)=""/18, 0x12}], 0x1)
preadv(r1, &(0x7f0000001540)=[{&(0x7f0000000080)=""/189, 0xbd}], 0x1, 0x1000)


r0 = kqueue()
r1 = open$dir(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
kevent(r0, &(0x7f0000000000)=[{{r1}, 0xffffffffffffffff, 0xa1, 0x2}], 0x8c0, 0x0, 0x0, 0x0)
open(&(0x7f0000001440)='./file0\x00', 0x615, 0x0)


syz_emit_ethernet(0x36, &(0x7f0000000000)=ANY=[@ANYBLOB="aaaa0800480000280000ff"])
sysctl$hw(&(0x7f0000000000)={0x6, 0xb}, 0x3, &(0x7f0000000140)="d5bd0d1d2d9ffee9de25ae000299278f439e7ba85cfc6828fac6bd2c4db863", &(0x7f0000000040)=0x74, 0x0, 0x0)


r0 = syz_open_pts()
poll(&(0x7f0000000000)=[{r0, 0x4}], 0x1, 0x0)
syz_open_pts()
syz_open_pts()
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)


unveil(&(0x7f00000000c0)='.\x00', &(0x7f0000000180)='c\x00')
mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
open(&(0x7f00000002c0)='./file0\x00', 0x1, 0x0)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f000002f000/0xd000)=nil}, {&(0x7f0000508000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000328000/0x1000)=nil}, {&(0x7f0000000000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ad4000/0x2000)=nil}, {&(0x7f000081b000/0xf000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000156000/0x1000)=nil, 0x39}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f00004c1000/0x2000)=nil}, {&(0x7f0000148000/0x1000)=nil}, {&(0x7f00001d2000/0x4000)=nil, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
execve(0x0, &(0x7f00000002c0)=[&(0x7f0000000100)='tap'], 0x0)
r0 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r0, 0xc028698a, &(0x7f0000000100))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000180)=[{0x2d}, {}, {0x8206}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x28}, {0x81}, {0x16}]})
write(r0, &(0x7f00000001c0)="d9537abde93d050cdd16b13f742a", 0xe)


mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0xc0e99db6de761f86, 0x0)
socket$inet6(0x18, 0x0, 0x0)
mkdir(&(0x7f00000001c0)='./file1\x00', 0x0)
rename(&(0x7f00000003c0)='./file0\x00', &(0x7f0000000380)='./file1/file0\x00')
open$dir(&(0x7f0000000040)='./file1/file0\x00', 0x8b1b15ec90417e16, 0x0)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chdir(&(0x7f0000000140)='./file0\x00')
setreuid(0xee00, 0x0)
mkdir(&(0x7f0000000040)='./file0\x00', 0x5c)
chdir(&(0x7f0000000380)='./file0\x00')
r0 = getuid()
mkdir(&(0x7f0000000100)='./file0\x00', 0x0)
setreuid(0xee00, r0)
unveil(&(0x7f0000000280)='./file0\x00', &(0x7f0000000080)='x\x00')
unveil(&(0x7f00000000c0)='./bus\x00', &(0x7f00000001c0)='c\x00')


sysctl$net_inet_carp(&(0x7f0000000380), 0x4, 0x0, 0x0, 0x0, 0x0)


syz_emit_ethernet(0x4a, &(0x7f00000015c0)={@broadcast, @random="50d5d449ecf3", [], {@ipv6={0x86dd, {0x0, 0x6, "8474f3", 0x14, 0x0, 0x0, @ipv4={'\x00', '\xff\xff', @remote={0xac, 0x14, 0x0}}, @remote={0xfe, 0x80, '\x00', 0x0}, {[], @tcp={{0x0, 0x0, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}}})


r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x3b, &(0x7f0000000000)="5ab7776a", 0x4)
syz_emit_ethernet(0x4e, &(0x7f0000000140)=ANY=[@ANYBLOB="aaaaaaaaaaaa7fd67572210786dd6007558300183701fe8000000000000000000000000000aaff020000000000000000000000000001"])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000700)=[{0x5c}, {}, {0x6, 0x0, 0x0, 0xfffffffe}]})
write(r0, &(0x7f0000000740)="76e5dead6f01f8607d2100000063", 0xe)


kevent(0xffffffffffffffff, &(0x7f0000000040)=[{}, {}, {{0xffffffffffffff9c}}, {{0xffffffffffffff9c}}, {}], 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd01)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0x80106468, &(0x7f0000000380)={0x0, 0x0, 0x0})


mknod(&(0x7f00000002c0)='./file0\x00', 0x2000, 0x5200)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
poll(&(0x7f0000000000)=[{r0, 0x6e}], 0x1, 0x0)
select(0x40, &(0x7f00000001c0)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)


msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000000)={{0x0, 0x0, 0x0, 0xffffffffffffffff, 0xffffffffffffffff}, 0x0, 0x0, 0xffffffffffffffff})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
sysctl$kern(&(0x7f0000002240), 0x2, 0x0, 0x0, 0x0, 0x0)
setitimer(0x0, &(0x7f0000000000), 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSRTIMEOUT(r0, 0x8010426d, &(0x7f0000000080)={0xffffffffffffffff})
setsockopt(0xffffffffffffffff, 0x25, 0x6c, &(0x7f0000000300)="594db3e5dac05c530a3ded94d2eb158922dd3a6e39935b60d1b46ee4e6f1b925ffc3fced0daa12036b2143fe192170d0a07fbb945b426701b3ce21bbe6d45037bd0d692c0449f9a4c05c8a0e3aeec50bdec5fa409dd6a296f2062d4b3986117e37ba6df9e383c41e5f89a9c8e4e9bffeaff86c7bd707bd598eec59e8e473241abcf29bdd77905028e88d1e4af53b80a6a06bb28655fe9180c209ff1b07c336e13242cff6a2a279187e583448792714d9", 0xb0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
r1 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
poll(&(0x7f0000000180)=[{r1, 0x4}], 0x1, 0x0)
r2 = open(&(0x7f0000001180)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSTART(r2, 0x2000746e)
sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x17}, 0x4, &(0x7f0000000080), &(0x7f00000000c0), &(0x7f0000000100)="c80250c7", 0x4)
setsockopt$inet6_MRT6_ADD_MIF(0xffffffffffffffff, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x7}, 0xc)
syz_emit_ethernet(0x6e, &(0x7f00000003c0)={@empty, @random="e8850d8b98bd", [{[{0x88a8, 0x0, 0x1, 0x3}], {0x8100, 0x0, 0x1, 0x4}}], {@ipv4={0x800, {{0xc, 0x4, 0x0, 0x0, 0x58, 0x0, 0xf96, 0x8, 0x33, 0x0, @local={0xac, 0x14, 0x0}, @remote={0xac, 0x14, 0x0}, {[@lsrr={0x83, 0xf, 0xda, [@rand_addr=0x80, @local={0xac, 0x14, 0x0}, @multicast2]}, @ra={0x94, 0x6, 0x1}, @ra={0x94, 0x6, 0x88d}]}}, @icmp=@parameter_prob={0xc, 0x0, 0x0, 0x0, 0x8, 0x0, {0x8, 0x4, 0x0, 0x35, 0x0, 0x64, 0xfffd, 0x3, 0x8, 0x0, @local={0xac, 0x14, 0x0}, @multicast1, {[@noop, @ssrr={0x89, 0xb, 0x1a, [@local={0xac, 0x14, 0x0}, @broadcast]}]}}}}}}})
r3 = socket(0x0, 0x3, 0x0)
setsockopt(r3, 0x1000000029, 0x24, &(0x7f0000000000)="5ab7776a", 0x4)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
sendto$unix(0xffffffffffffffff, &(0x7f0000000000), 0x0, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000001340)=[{0x0}], 0x1)
nanosleep(&(0x7f0000000000), &(0x7f0000001180))
r4 = socket(0x2, 0x2, 0x0)
r5 = socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(r5, 0xc0206923, &(0x7f00000001c0))
ioctl$FIONREAD(r4, 0x8040691a, &(0x7f00000001c0))
socket(0x2, 0x2, 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
sysctl$kern(&(0x7f0000000040), 0x2, 0x0, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000400)=[{0x4d}, {0x4}, {0x812e}]})
syz_emit_ethernet(0x3e, &(0x7f0000000040)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
ioctl$BIOCGDLTLIST(r0, 0xc010427b, &(0x7f0000000040)={0x0, 0x0})


socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000000c0)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvfrom$unix(r0, &(0x7f00000000c0), 0x832f1f7d, 0x0, &(0x7f0000000000)=@abs, 0x2000c600)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
close(r0)
close(r1)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xffffffffffffffff})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x3a)
r2 = dup2(r1, r1)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r1, &(0x7f0000000300)="00003226a4a9000064e7c803d2a423735d33a4dd72c3b894d1de957eedc56e0380271dc72f5796a20a91046c9782b54e9ebe4819eac1e41bebbc8fc2e5155796116e00a001c0745c0fb366c8c29785b0d6983e036092c219a09099d8903b438bee0dd22d219efe232e9cc22761f89554c67e1d9ed3ae72e8352e17bcb4300b3c41577047664b11e0dd9155c39f1ddf1703da62aa7c505bf0229ed8", 0x9b)


r0 = socket$inet6(0x18, 0x3, 0x0)
getsockopt(r0, 0x29, 0x3b, 0x0, 0x0)


syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x1025, 0x0, 0x0)
ioctl$PCIOCREAD(0xffffffffffffffff, 0xc0107002, 0x0)
ioctl$TIOCCONS(0xffffffffffffffff, 0x80047462, &(0x7f0000000000))
socket(0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r1 = socket(0x2, 0x1, 0x0)
bind(r1, &(0x7f0000000000)=@un=@abs={0x0, 0xd}, 0x10)


r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0x81946466, &(0x7f0000000040)={0x0, 0x0, 0x0})


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000080)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
bind$unix(r0, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
setreuid(0xee00, 0xffffffffffffffff)
r1 = getuid()
chown(&(0x7f00000000c0)='./file0\x00', r1, 0x0)
r2 = getuid()
setreuid(0xee00, r2)
r3 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r3, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


sysctl$net_inet_ip(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = open$dir(&(0x7f00000003c0)='./file0\x00', 0x400004000011830a, 0x0)
pwritev(r0, &(0x7f0000000340)=[{&(0x7f0000000080)='\x00', 0x8a8615b7}], 0x1, 0x126)
truncate(&(0x7f0000000100)='./file0\x00', 0x3802c)
preadv(r0, &(0x7f0000000000), 0x1000000000000098, 0x0)


r0 = getpgid(0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, r0})
r1 = open$dir(&(0x7f0000000000)='./file0\x00', 0x400004000011830a, 0x0)
pwritev(r1, &(0x7f0000000340)=[{&(0x7f0000000080)='\x00', 0x8a8615b7}], 0x1, 0x126)
truncate(&(0x7f0000000100)='./file0\x00', 0x3802c)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
preadv(r1, &(0x7f0000000000), 0x1000000000000098, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r1, 0xc02069b6, &(0x7f0000000100))


openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x20200, 0x0)
setsockopt(0xffffffffffffffff, 0x25, 0x6c, &(0x7f0000000300), 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
getpid()
sendmsg(0xffffffffffffffff, 0x0, 0x0)
open(0x0, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r0, 0x80085761, &(0x7f00000000c0)={0x3})


syz_open_pts()
mknod(&(0x7f00000000c0)='./file0\x00', 0x2000, 0x40000802)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000080)=0x9)
close(r0)


sysctl$net_inet_esp(&(0x7f0000000000)={0x4, 0x2, 0x32, 0x1}, 0x4, &(0x7f0000000040)="82338798", &(0x7f0000000100)=0x4, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000000029, 0xe, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
listen(r0, 0x0)


mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0xc0e99db6de761f86, 0x0)
r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x1, 0x0)
r1 = open(&(0x7f00000001c0)='./file0\x00', 0x0, 0x0)
r2 = dup2(r0, r1)
ioctl$FIONREAD(r2, 0x8020697f, &(0x7f00000001c0))


setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000))
socket(0x18, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, 0x0)
r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r0, 0x80085761, &(0x7f0000000000)={0x3})


rmdir(&(0x7f00000000c0)='.\x00')
ioctl$VNDIOCCLR(0xffffffffffffffff, 0x80384601, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
rmdir(&(0x7f0000000000)='./file0\x00')
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, 0x0)
r0 = socket(0x0, 0x0, 0x0)
socket$unix(0x1, 0x0, 0x0)
listen(0xffffffffffffffff, 0x3)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
socket$inet6(0x1e, 0x0, 0x0)
chmod(0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
setrlimit(0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r1 = socket(0x18, 0x3, 0x7)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r1, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
r2 = socket(0x18, 0x1, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x6d4)
r0 = open(&(0x7f0000000280)='./bus\x00', 0x0, 0x0)
ioctl$FIOASYNC(r0, 0x80047470, &(0x7f00000000c0)=0x5)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
select(0x40, &(0x7f0000000000), 0x0, &(0x7f0000000080), 0x0)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x0, "0d0e5012c3842ffcc300"})


r0 = socket$inet(0x2, 0x3, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x6a, 0x0, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x5200)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
open$dir(&(0x7f00000002c0)='./file0\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040))
r1 = syz_open_pts()
ioctl$TIOCMBIS(r1, 0x8004746c, &(0x7f0000000000)=0x187)
r2 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x10, 0x0)
ioctl$BIOCGBLEN(r2, 0x40044266, 0x0)
pipe2(0x0, 0x10000)
ioctl$TIOCSTOP(0xffffffffffffffff, 0x2000746f)
ioctl$TIOCGETD(r1, 0x4004741a, &(0x7f0000000180))
faccessat(0xffffffffffffffff, &(0x7f00000001c0)='./file0\x00', 0x80, 0x2)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000001400)={0x0, <r3=>0x0}, 0xc)
r4 = getegid()
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001480)={&(0x7f0000000200)=@abs={0x0, 0x0, 0x0}, 0x8, &(0x7f00000013c0)=[{&(0x7f0000000240)="c970d86ee917ae98c433c0c4f3c0ddfceae3b0abc8bc37b80b78b0d7666b43a9a64a6ebc10a534f4618d7b6cfced10197c89297da63ae19af3eb2e21d464e609d27a0d9d02752f5cc5fa66cfd952dfb2bee732cac4a8162e32e909359faceb16e90827f22c1734d02367ecd87cf552ffa6cde3266821b799270a919449f907b43bec1af1c88651a8965431189fa6", 0x8e}, {&(0x7f0000000300)="4742b261f15e771468bd4cde6458a2e7c543c3869a8cafa46d371397e445cf90f77cc174d7c45b429926afaade810c56cfbceb4ad9a683d4f576628f53a29521f52368b289b4891b1797c02c8fc3a82fdf9c56372a84bedd625b93694755d28bd35a", 0x62}, {&(0x7f0000000380)="ccf79a75fb275a80747e1f0682aa8393e8377ebae46f7fa5fdb8c37e8c37a1ab80fe49757327a584b1cbe1e15ee341346008bc40414868642a3ea1d82c5382d040c0f7980e04e1cd5654b6a13be01fc507779c6cb37a0f8a9c6f70d982558d2478b669fb36328d4c6b192d5a51a5d0e88187a71ed31996b8436de6650911331aab1cb50a406825622b0be76a39b61885f12409b7641d6495e8eed4579431d1e33aa2a00c3d7f8530e0d9c1f6c3302508461c3fa4975c98e8284dffeccfd775f6e44701317b357682dd370c67e963d726c4639fccf071c49d3bd32e0022d8efbc7e9edab02299f25b55762b38f4d0f3f9428a9e5320db34b3613b9cf142e12ec7a067afdecb963f1dcdb278d6bfffb3ab2ceb920be828becf28fcb2afb23bbec1b4e370b834b82f6982f194cc84777530671af2bb78ff4c1853e221507a5f7dac83264ba7ef9fc15b9a8119778cf9cabd2bcf219bc459ada5c16e26252a700630148740799f5c541e1866df49486b6c3cbd3ce92abf29f36a4956fcdd06196208a08cff57f53a85da62e9b7542219b7670e0caa30773c56357ca89410e8e0f0fa20e41038d839824a9fba68e1f597a60040009d07dc17d264e29ec0f3c087d83c37790649d9370984fe115527dffbefaac707aeee09f82bc8818304ef8e51858fc0ec6d3160396bcb5176c049f2eb5f416414f20bc9c13f3e5cb8bd6deb55c2527156f25b9fff3f8c554901e0b5c87cbb7645d5e6f1637a85ec5ea9f59834d777076f85b8bb920740db7fcc6f9bfd15644489d8e61ac40cd2ffa4e6b73536002aba82328a7ca48e10c082c2bda6b289026b6188a73a58e6172d2555736eafbb96b5c5451dc31eda2123e074a8d0ae04ee68934224e81e0251d6dce46b81e917ec3a06b25d5164ada4362a385bc0474dc2105dcc409f5e9fb01803c2e4a8a4eaf72705a5b935580aac8a3249cff107a5f872bd50c3b3e8c31eba0f94eb3783bb1eb6aafbd33a69643e7d0ff91199916f59c4de97da6270f04cf1e4775f3912159ac67c11ee562f5a56d368ee3ea6a7d776b4c9a4d24ec5cf54ba26ce557ac3cf99e30521308a4ef21f171dae809e105d096eb0fb8ab837e768da5536d0b82bbf60027876501c68e558bdf9c592586f5a9cdaa73b752a7f2f42140a7fee488bb993031e3afb7f0d2061492bdcda88293042b558d55365b158f04c5c74049fd5792a691b3f543e7a76b4c9a6fc1473225be78248d02e4681ed021dd69027e48e6fb8d2d84b77dd188884436ba869e2f71a7e072dc12a5c9e7d0187577bb3bb3ef4d1e95c04bbe061b93931317a4edd736215c649a16912e2fdcb1ab0587340f738ba80b236f0200707dc849959dc57a3bf795ba0d4bbfd2dd3ad957aedff2afb9910e6c3358d15e84a5236a9399979f07a24a770ad892bac65d7fe6879d61e97a1f85ac4027c0cd1106e0e2308c4ed20c40f99810cfd475db2d5bed8116f08774d948275fad4c2c2bce67a2f7c15cba7d58668b0668048473166dbc1e953e4deff1a8948d99caf964b81b9d55371daa7cc1ea8f62a03bdbf4b7d190699c82f4a7ba199a8b47452a43eae3a4d3d2acd1b90f0703f0231b8b8ff6312739b94494b99635708008bc04ec2c982e9462b25f9f3b441abbf663be9eb88292922de9fe321d40039b73ecfebaf3d834914226545405f3271033f14c678e65f86a5e9fe980a18db0c676487ec0421ac8f59292145e6a04dc2d71f0f2259deb86905dac56e90fa7f0dfd2620abd20ad8cdd5ae4778bea96eb204d5ebb4986355f88de23e64e7a12a4c29e3e13559ef0948386adec48f13b5ab88b565cfefca7ea20e3f47a93e7bba94554767ac9b2fe4b8eaab0078d1117219505c45b20eadcbf18fb527e1429b037a9ebdb0a39e05cfca008ffbbc54b3e42d1b28617eea05a8882bce35a940b023c926b552afdf629bc78737d88c53ea5294326dac390d1803701ef5558c7c9368e68f1e999e11bc5cd706f404a3e7740a927d2b0bf091d7d402d88eb6de8df6d27ba63e735c4a34b30503aa07d026d62cd68c1cef27dbfb9af84db4f7de6faa7a71c641b98a7a428c5b9b180b59808d60ab3aade675ef22f83cb63db891fdb9799939b53798a79c4961d2e8d1dfed9727413759c59dac5a61548090ec3b49a705726ee436a4edc994d0466b55a17aaeebcbb53cc6de0174a062bb7962167e0fc6eb9ba8bd6cab7464d77e66e30622991b8e5052753b5a30aad2b814a79988b8d5a8a665458f044457048b08a5a106e90cb103c96a157a9d6d48a01f269cb4af77e7aa27f972ecf928b04c18eef9b9d93130c66e1205859d3bac368faf2621d5604c69f52f692087487f85ea9d2a13e443cf67d866cb05ec7e462bebd203be70bce32f2dc156724aac2874b23583fc35ecfc7f64fdbed9643b4ccd33f58272bf7ee14bdfc12dd51549d8221bcf88cfdfe97ca37ffab9ed8cb628f0e463a5bcd7956137fbfba83f720c3e68dc37ab453f6438ff759e2220d0c56b3f72cbf3b4eed1de7f074574db30a37676e5d62d9b7b1909b182aaaf8b4d503aba440360ba55ba52303d29caffad03f98cddbe49b7cbd29d0aabcb164a64de6ab144d47300a2a718b470fe474532fd7f80ff8d6542f66bd97e911addf35a3ce5e7ca6c8d4330353694e4ffc30484e5a6b37ee3b6af695aff9c0ff6e93c6b9b37f093c12d74736e86772d1aae35695625583708813794efb0a9afa73e16eb78d735adcbdfc6165fe28d177c05d0d4b67fd626a726b6a39ed80b90acab5c1ad3d7f6a95c753320fe13b1d214dc21742cc284a6c0496cc554b14ef719ce45d98668cd77a74c1b38c6799b3c1d0b764a64bd1cf4884b19c76a138c42ec8c7f1374e4cc1fbac5a218bb0b7673d1e957d3d6c9164643f1cae0c45efa6f2f20707529f12a6ec445d716ede04b6b0d25f218a8eb52c69e84ed1a00f5ff16b318ecf7eaba37446fbc0230640b52424373b394c5b1528324c20b28e3df72790eaba1a6877e106d3bd60c4869d9beb53607a7882b83503d6ce63b2ffceb735bc30037a4e7a020169562c67654f6a85a7ca25da1421a9dd39ae3c78f01bfd9ec6874dedf3c0e3affd091390c3c9616ee3fac826ef004dfdb4fd1c8d2c862acf72cf6a23e1d579efdc35bd52e8a48ff040298a485cb1fefe4a2154f6450c581c4d7997a5c21635233cde11fcc11bea67e6039558d580b526ba1bb305f082e52020822f8f5908fa8eef747bcd6aa99404e995ed72c3be89701a2b7fb8f153b6f7432ab4e921fa4fc0bc9b6b148c2103dbc9c0536ba4e4b0cfaf79325c193905f4624fab1a84099d0b66b5b5b837b38f0fbbff28af83553966ff0b5fc67686481f165634379ff04241d77d8b0dc0663e6b7eeeadb451cfd63e69ad65126521b5c6964c155f7c2e6c8549d263bf6812c289c25c2ae3b9d737edf604d2e98135fa17471c7063c0bf45f72479b856ea7b630d734ada7dc5fbd0dc7641388a4e6bb2730cc3207bf53d7cf4c689302fe095d47abbb317b87e4d1d682b373c4302d2757f6ed3f0340bdbbb3b1121788beebc7f29c720c03d182799a5bb504750e7dbb6d4ebc7724ce658eb91d4a67d28f429546ce07d8f7af7467b64f15aeea5aaeb62aecfaf679aa033192f477d5d7f9a2c70d8351531f7a55a44bbc55367b05fa1107568ae2debc221bc3b44612cceb3a2fcd7c529a4415655c8d58028522c696087adc883e06ffdd0272513492cdb772dfd752dbbc361a43164b670f41b9753b01d215d85e600536466c272c72ed3e069d86698e57d9fde315ac66d88b403ceb8142dcb512ba98f5d5b7ed9b627e93a466a1e4e7245bcbed5d77843552c3694d1a303e83d6542e5a6f2a499d715bf17ea5705d3873ba3342a4153b33a4c3fee97cb80aabf3d5622805e76ce579e91926d681d4984be1465b5a8f4e95d9a6897ec4b45b1150eb3fdfbc786aecee11b2a494aaacfb3fe614d3446909ef133a9af2ee8c72c5aa161407136479aaebdc75a2adbb2c859f7b44caf3163409c73a28bf248be41cccb041dda8d7189e74038dc4a18f688fe07036c87487656f7672d41a8d31d59f4b8fd5a50e4b85a0bf5bcd5fd756143b606b42e7750415092f22e3f2e1540afd294f56be3f22141ec0897b8578bd6f1a0e18ae50434063bb513380cf65e4ab633f001997b3cb18c2340ebc74dc7d01ce3f0af0eb8c44a8a297c9e6f7255806482b9e5bd0127bee5ce52fc9cc34d11e285e1b702cbe56c51fef97ae0dda0fd51f8d6a7c190bf8b2616f9a442b1218ddcd592e73d6a7e447b91312fc78c84af29b9f88ec3abbcdd6e91a484e40ae9ce809b92d4afced83dd7e7493f86dccc576de02fe39eca291d29df21244f7399a47a44132fbe5dd9618ec6f1b0a9cfaa4a96c89df38ff7ea4284c918625f0b1c1fef11f9d32ba78038d1d1482804831f04be0b4afd5c58292d1cd4206b469605b39ad96fa043c5b5d61338a190a8489c3510ab40a6f7379697cebe029c5aa0065a65d1da3a4fa09fc774b99c6848d8dcf4751f9cb3ac914f88776873d6eb09ce23645a8556676240cce9de5fba4c5efb90640d53ee8f35edd793b704f3cc6cf7833c27f45e1711c7a8a30165b6aca9f4aa97d886352b798e682370d2d9e4b94449d2cf88b4d91c672d13ea2ab86c66deecdf088f224488e9580aa37a6b66319ac3217f66b754ab23f0228ac84966970ed1fbe5de888ba2736214ed966119edd2afde9993641dd01dec47660f1fcc0af43463b7aa45b01cd497b92d58842e01dce3cf44dd03b938ecc3902f21b04e9a40dd24fdd5f7def33e3ef7b2fc72715f2deeb8ac6c8821a2e8b82e508dcf9a2f5d321e4c4ab0117a0d5084c0fffbcb83fb649f086f8d5628aae73432509e8e936e482720e5e814dd2219beb4e268a251cf65f28c13093af507968fee85b57fbe2718181d57dfa74c2a9ac8df9b25b7c1c04f566ac17265ef774e6a95d53421e1bd9765d11d504219331984bb992e0e3870e65b89636b495f8fba1d46b8efc03303fa7dd2c1222015dde34064c5f2063446fbd0dfb78deb08d363818741e9ddcbc1ff55db5513b88c6a19ce8587651ca3a8e167edace144611ec5610e68773ecadb2498b54154f4cd6b4403311a51c0fd98d10a069ed7a02e515038ea4d2010a2a1069dc7c3a0af66165b5544a415bb2868d168c7c285b6a731161630f2734f4da69bdee8900b425ab002874f84cd3323c3d776217c091dfadb9c27868199cb75ce823d3cfbff85307b3fa04ca4bf99aab34d6a1104119fa505f3faf6ecf6ebc1568d613d797f516412246aa049cc4b8561c1f187cd9b956d223dd37a70336e53f6d0ea9711b8ba0c7735fc7d222fe4283c1379301b6d00e1d0a7c31113e1f6eb2cf605e84d000c98e7f712812d93e99e5668550339388470e2b7c1901f124101d4ab0934ce36c3d8e0671a867b0e56d54efe274a396c2570251d1b243c240f015e40c9fe22c85ad2c9424633e84d307304bdf4217a2a615bfa7f2e2df986c8afea77d98928e36089866bf3b345b361ab75d276047f284bd35638d62d9e1aacc9fa54c737404e283a094603ac921c6121fd7535624cbdeb6036f778966f40d82768278f10672c15e29284b9801aafab98599dd70a30b52871f41b6ed20ce359da77e83b3018d314ddd3fdb6e7796e4619b01f39ddc59b123a1c3084f86fd3fba8b7800e3c37ef05a2cdb70ed3763bb769b895d94a2467d154e3ab785d0bb0c3527053445f28303a330b9f5ca579b63", 0x1000}, {&(0x7f0000001380)}], 0x4, &(0x7f0000001440)=[@cred={0x20, 0xffff, 0x0, 0x0, r3, r4}], 0x20, 0x402}, 0x5)
fcntl$getflags(0xffffffffffffffff, 0x1)
openat(0xffffffffffffffff, &(0x7f00000014c0)='./file0\x00', 0x2, 0x8)
openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000003000), 0x80, 0x0)


r0 = socket(0x2, 0x1, 0x0)
r1 = dup(r0)
listen(r1, 0x0)
connect$unix(r1, &(0x7f0000000180)=@file={0x0, './file0\x00'}, 0xa)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000340)=[{}, {0x15}, {0x46}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


mkdirat(0xffffffffffffffff, &(0x7f0000000040)='./file1\x00', 0x0)
fchownat(0xffffffffffffffff, &(0x7f0000000140)='./file1/file1\x00', 0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000380)={0x0, <r0=>0x0}, &(0x7f00000003c0)=0xc)
r1 = getegid()
fchown(0xffffffffffffffff, r0, r1)
r2 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r3 = socket(0x11, 0x3, 0x0)
setsockopt(r3, 0x11, 0x4, &(0x7f0000000000), 0x0)
setsockopt$inet_opts(r3, 0x0, 0x1, &(0x7f0000000200)="f1e4d190c0622e6e44c6f4a60ee2cfec581c44052f117d9d8a703bc599712394ee9e6c7a868ae82a7a023e62eba89b6a4de8bf99c884c3eef4ddb20ce892635713a7037455780acd05bbb5fbf182344ae906448f1263b01defcf6727f98c962c41636d553746025d6ec459f4cd1cc5cadde66e1cae2e74a1b980d2bd57976f70ff2917b98c03d7b09ef1026e", 0x8c)
open(&(0x7f00000002c0)='./file0\x00', 0x0, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x802, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x0, 0x0})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
ioctl$BIOCSETWF(r4, 0x80104277, &(0x7f0000000080)={0x0, 0x0})
write(r4, &(0x7f00000003c0)="985fa7fbdf69aca69c9a97347864", 0xe)
socket$unix(0x1, 0x0, 0x0)
r5 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40003354, r5)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r2, 0x0)
select(0x0, 0x0, 0x0, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x7}, &(0x7f00000000c0))
r6 = msgget$private(0x0, 0x120)
msgctl$IPC_SET(r6, 0x1, &(0x7f0000000180)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}})


socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
setrlimit(0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000240), 0x0)
syz_open_pts()
socket$unix(0x1, 0x2, 0x0)
shutdown(0xffffffffffffffff, 0x0)
mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(0x0, 0x0)
unlink(0x0)
rename(&(0x7f00000007c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000a40)='./file0\x00')
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0\x00', &(0x7f0000000e40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000600)='./file0\x00', &(0x7f0000000f40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000001040)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000001140)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0xfffffffc, 0x0, "2bbf09a76e9bd301d6291ab88842329097184589"})
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)
r1 = kqueue()
kevent(r1, &(0x7f0000000000)=[{{r0}, 0xfffffffffffffffe, 0x11}], 0x6, 0x0, 0xfffffff9, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000240)=[{0x20}, {0x4}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f00000001c0)=ANY=[])


openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000bc0)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r2, 0x80105727, &(0x7f0000000200)={&(0x7f0000000100)=[{}, {0x25}], 0x2})
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
syz_emit_ethernet(0x46, &(0x7f0000000000)={@broadcast, @broadcast, [], {@ipv4={0x800, {{0x9, 0x4, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, @broadcast, @multicast2, {[@generic={0x88, 0x2}, @timestamp={0x44, 0xc, 0xf, 0x0, 0x0, [{}, {}]}]}}, @tcp={{0x2, 0x2, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})
r3 = kqueue()
mknodat(0xffffffffffffff9c, 0x0, 0x0, 0x0)
accept$unix(r0, &(0x7f0000000300)=@file={0x0, ""/504}, &(0x7f0000000240)=0x1fa)
r4 = openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
dup2(r4, r3)
r5 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$DIOCMAP(r5, 0xc0106477, &(0x7f0000000200)={&(0x7f00000002c0)='./file0\x00', r4})
close(r4)
syz_emit_ethernet(0x36, &(0x7f0000000000)={@local, @empty, [], {@ipv4={0x800, {{0x8, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @multicast1, {[@rr={0x7, 0xb, 0x7, [@broadcast, @multicast2]}]}}, @udp={{0x1, 0x3, 0x8}}}}}})


sysctl$kern(0x0, 0x0, &(0x7f0000000140)='6', 0x0, 0x0, 0x0)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x2b}, 0x4, 0x0, 0x0, &(0x7f0000000140), 0x4)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1, &(0x7f0000000000)=0x787, 0x4)
mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
unveil(&(0x7f0000000080)='./file0/file0/..\x00', &(0x7f0000000100)='r\x00')
openat(0xffffffffffffff9c, &(0x7f0000000240)='./file0/file0/../../file1\x00', 0x0, 0x0)
mknod(&(0x7f00000000c0)='./file0\x00', 0x2000, 0x40000802)
open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
mknod(&(0x7f0000000040)='./file0\x00', 0x2000, 0x6da)
r0 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
r1 = socket(0x2, 0x4001, 0x0)
dup(r1)
r2 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, 0x0)
r3 = fcntl$dupfd(r0, 0x0, r2)
close(r3)
fchdir(r3)
munmap(&(0x7f000000e000/0x400000)=nil, 0x400000)
mmap(&(0x7f000002a000/0x1000)=nil, 0x1000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)


semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
open(0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x58}, 0x2, &(0x7f0000000140)="1139a509", &(0x7f0000000180)=0x4, &(0x7f00000001c0), 0x0)
r0 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r0, 0x80606948, &(0x7f00000001c0))
syz_emit_ethernet(0x6a, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x5c, 0x0, 0x1}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x1, 0x0, 0x12, 0x4, 0x2, 0x0, 0x233, {[@generic={0x0, 0xd, "96c729637cae4fa49c1558"}, @sack_perm={0x4, 0x2}, @sack={0x5, 0x16, [0x0, 0x0, 0x0, 0x0, 0xffffffff]}, @timestamp={0x8, 0xa, 0xb018, 0x8}, @generic={0x4, 0x2}]}}}}}}})


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f00000003c0)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x134, 0x0)
madvise(&(0x7f00003e1000/0x1000)=nil, 0x1000, 0x0)


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000080)="eaef125c00000000", 0x8)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000100)="ea00000100000000", 0x8)


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
fchflags(0xffffffffffffffff, 0x0)
r0 = semget(0x3, 0x1, 0x80)
sysctl$net_inet_ip(&(0x7f0000003a40)={0x4, 0x2, 0x0, 0x14}, 0x4, 0x0, 0x0, &(0x7f0000003b00)="2018b958", 0x4)
semop(r0, &(0x7f00000001c0)=[{0x0, 0x259, 0x1800}, {0x1, 0x9, 0x1800}, {0x3, 0x7ff, 0x800}], 0x3)
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0xd02)
open(&(0x7f00000000c0)='./bus\x00', 0x10, 0x0)
syz_open_pts()
open(&(0x7f0000000040)='./bus\x00', 0x70e, 0x0)
r1 = getpid()
open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
semctl$GETNCNT(r0, 0x6, 0x3, &(0x7f00000002c0)=""/204)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x37}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)
r2 = socket(0x11, 0x3, 0x0)
r3 = syz_open_pts()
ioctl$TIOCSTSTAMP(r3, 0x8008745a, &(0x7f0000000000)={0x3f, 0xd65a})
sendto$unix(r2, &(0x7f0000000100)="b10005010000009f0500070007000000331c13fecea10500fef96ecfc72fd3357ae30200004e3039d2d236acf20bf404be01000000f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f335c22db830c032bfa896443c32118210000720fd38bfb0000fd54c125191b1257aea8c500002002fbfe0c2300008abfba0900000008e37193f8343712051eeab71dc000266c05080000fca65361ba84913f0100"/177, 0xb1, 0x0, 0x0, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x2, 0x40000934, r1)
madvise(&(0x7f0000000000/0x1000)=nil, 0x1000, 0x4)
clock_gettime(0x2, &(0x7f0000000280))
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
sysctl$kern(&(0x7f0000000200)={0x1, 0x1d}, 0x2, &(0x7f00000003c0)="440a9430092fdb5e0956c8699bb0b24a90537c27caac9fc2b1f476662b621a9fcf0b2f9a0968b5f1dc0f7b54d2dd7a872403d2262a797c258290f08c72703559fdb605401d70bbcbf1fbff9bfd9f4904ae25c55a3e6b38fc4022e698796f5b6cd89bf4f01c4bd35892a14d4c214c6116f398cef418b20204f7211271d035853ff03e7a3d3cf63af46b7ae59aa26e2cd5e0e804b03d5917817a7bbb410695f15f562265d2f3216670028893ccaff3bcd11ec1849c481eada73ebd11c86597deec26fb4751f081d30e9b24765dea3f95b8d21d0247", &(0x7f0000000240)=0xd4, &(0x7f00000004c0)="c028b693acc49bbfb7151e0a227a570989ae0fcd5f85451d06e039d102a57780d7751487d4d78efbe7f04a7c6dd74d402966a888b6021f3937d4f3a7f7c2f757cf8115cb921ae8c544236d980c891c8cdf874b8cb2c28fed3819af40cbd40a084300180a245c1004fa8007256b7d58f8d5b6b6003b93deb31dbdc220b0d8ef974f34c3759e4f224e5feb0e1d84e5cf68406351a04a46fcffd09f303d12805723393c84f69db5a0b64abffe3a1616dc04516e72b40b9318a7f99952e3ee32c49fa2494372eea4044a2d6485f8556c1a04557157540364f34e7e48fa509ee6ebf0684052cbb470e0b7f02db8def884730fa8b53e809507b64ca0", 0xf9)
r4 = socket(0x2, 0x2, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r5 = socket(0x2, 0x2, 0x0)
bind(r5, &(0x7f0000000000), 0x10)
connect$unix(r5, &(0x7f0000000000), 0x10)
bind(r4, &(0x7f0000000000), 0x10)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
fchown(r0, 0xffffffffffffffff, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000140)={0x3, &(0x7f0000000000)=[{0x87}, {0x2c}, {0x4000006, 0x0, 0x0, 0x3feffe}]})
write(r0, &(0x7f0000000180)="23009100007adb020317bdda2b7e", 0xe)


shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmctl$IPC_SET(0x0, 0x1, 0x0)
shmctl$IPC_SET(0x0, 0x1, 0x0)
syz_emit_ethernet(0x1b, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000c40)={0x3, &(0x7f00000001c0)=[{0x7c}, {0x25}, {0x6, 0x0, 0x0, 0xfffffffd}]})
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000080)="35b5c242413c1026089a59583cc3", 0xe}], 0x1)


sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000540)="9b1809c3eb987ab7feb13ec99e805e6e84d3569607987c0d00000001000036ba1bd87f42e3003eac3846520d050712f838130efce149d4d6d06a3f23616e778c826e0c1f59734a32e0ccebd635450b2eba540af7f290e42d34d900a0dad2b74f50acd76b5c567049ef436dbea0d7612752950fa5ef6eff03000000000000a944d5c2bdbff4f06a852ab475cca25735282896ca5d4d3e670feac9b4e8aa9bef193b90163de8570b2a374f1408341ed45bb703eb63cb9a8bd949ee8fc6dbceb7ed7cca108d739a38d726341f1345daa49507756f49775275ca390bb9400000003a9275d0da3b56186adc3c141f939800000000000018bdbdc9ac0a623855e941dc1872fcb045e0d9df1ecc6357ee21e2b8802cb60eec6add5e94723235f06715e7eeccad2dc1a0d0f5509f3e0760c70e1dd7873e27142bbae1a7e44de453a073fe3426f334b80f043ba9136d57c799343d46dd81439b111a511a288beeddfb2e353e3bb073e3342773216b07e49ca4df0fd2dbe9a8eb3770ea880f76e6f4588ffb7d826a208788b33aa87b4a81082612630fdb791f833a1da5af886129cc7b7907f374fcece1799fd99d7a2441da17670852140704f687e196f4f7859e071fc98111cc9024f790ce16ceaa7dd8c52efd580400cd0c3a99f23c7ef760b4f4a063b9efe74db5b55700000000d4253d65b083e40b9baa468a7dd0a36c384200000000000000000000000888549ced16184347", &(0x7f0000000000)=0x210, 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x35})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
socket(0x1, 0x0, 0x0)
mknod(&(0x7f0000000100)='./file0\x00', 0x10, 0x6000)
r1 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$FIOSETOWN(r1, 0x8004667c, &(0x7f00000000c0)=0x1)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000800)="9b0209c3eb987ab7fe4189c99e805e6e84d356960798a692992117d672a736ba1bd857feb09901fe0dcee53766797f42e3303eac3846528d050712f838130efce33f523ba44765f5f6915b0227390ed95bd9dc6d4dc7e149d4d6d06a3f23616e773302d9cae75e39a5a11e32e0e6ebd635450b2eba540af7f2aa5dbfbdd900a00800000050acd76b5c567049ef436dbea0d7562f52950fa5ef6e84c513252ddd8680a944d5c2bd021cc793994922dfc10000000000062ab475cca257352828a76e5314be5629235c0febeff57cab95e894238b96ca5d4d3e670fea610c00009bef19525cb6f7e8570b2a374f1400041ed45bb7ad3fe963cb9a8bd949ee0fc6dbceb7d956015947b3e88aa810f8ed7cca10ff010000000000001345daa49507756faf775275ca390b94e85d5a95b8bdacb9429c25483a9275d0da3b561c6adc3ca67845c3386ce33141141f26a88016dd6b436218bdbdc9ac0a623855e941dc1872fcb045e0d9df1ecc6357ee21e2b0802cb60eec6add5e94723235f06715e7eecc3e0760c70e1dd7873e27142bbae1a7e44de453a073fe3426f334b80f043ba9136d57c799353d46dd81439b111a511a288bee5dfb2e353e3bb073e3342273216b07e49ca4df0fd2dbe9a8eb377010ee678a0900d8c7fb7d82693a096344671843a1f2082612b0ff237c6e505ff5f5ba932954d73c630fdb791f833a1da5af0704f687e196f4f7859e071ec98111cc9024f790ce16ceaa7d0104e39789d91000009a5bec77c992c792eb013621a86709cf57acd9981f947115f608227da8c54d8aa668931edd0b599b3d8cf5a8438ae08c1f70483223c3ba38088fb2e65a51edfed44c55a4d734bb553d642ca2bcdd1a08378317dc8f787469c3b3c14e4b1b46c2c8b03b99", &(0x7f00000002c0)=0x285, 0x0, 0x0)


poll(&(0x7f0000000000), 0x0, 0x0)
socket(0x2, 0x1, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000340)=[{0x3d}, {}, {0x8006}]})
r1 = socket$inet(0x2, 0x2, 0x0)
dup2(0xffffffffffffffff, r1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt$inet_opts(r1, 0x0, 0xd, 0x0, 0x0)
syz_emit_ethernet(0x119, 0x0)
syz_emit_ethernet(0x2a, 0x0)
getrusage(0x1, &(0x7f0000000000))


r0 = socket(0x18, 0x3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
ioctl$FIONREAD(r0, 0x8060694a, &(0x7f0000000100))


sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
sendto$unix(0xffffffffffffff9c, 0x0, 0x0, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000401})
open(&(0x7f0000000100)='./file0\x00', 0x615, 0x0)
sendmsg(0xffffffffffffffff, &(0x7f0000000240)={&(0x7f0000000080)=@in={0x2, 0x1}, 0xc, 0x0, 0x0, 0x0}, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x2000000000, 0xffffffffffffffff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x1, 0x0)
close(r1)
socket(0x18, 0x2, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendmsg$unix(r1, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


r0 = socket(0x2, 0x1, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
recvmsg(r3, &(0x7f0000000340)={0x0, 0x0, 0x0, 0x0, &(0x7f00000024c0)=""/236, 0xec}, 0x0)
sendmsg(r2, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)


sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x3}, 0x4, &(0x7f0000000040)="e184767f", &(0x7f0000000140)=0x4, &(0x7f0000000180), 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{0x87}, {0x24}, {0x4000006, 0x0, 0x0, 0x3feffe}]})
write(r0, &(0x7f0000000180)="23009100007adb020317bdda2b7e", 0xe)


socketpair$unix(0x1, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
syz_emit_ethernet(0x3e, &(0x7f00000001c0)=ANY=[])
r0 = socket(0x800000018, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
chown(&(0x7f0000000380)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/file0\x00', 0x0, 0x0)
syz_emit_ethernet(0x7e, &(0x7f00000011c0)=ANY=[])
bind$unix(r0, &(0x7f0000000000)=@abs={0x1f95d27d48731892}, 0x8)
setsockopt$sock_int(r0, 0xffff, 0x1021, &(0x7f00000000c0)=0x5, 0x4)


pipe(&(0x7f0000000080)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$FIONBIO(r0, 0x8004667e, &(0x7f0000000000))


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
socket(0x11, 0x3, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000080)={0x0, 0x0})
socket(0x0, 0x0, 0x0)
write(0xffffffffffffffff, &(0x7f0000000380), 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
r2 = socket$unix(0x1, 0x2, 0x0)
connect$unix(r2, &(0x7f0000000000)=@file={0xd1653077bafa0115, '\x00'}, 0x2)
writev(r2, &(0x7f00000002c0)=[{0x0}], 0x1)
socket(0x0, 0x0, 0x0)
sysctl$vm(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
setrlimit(0x0, 0x0)
setsockopt$inet6_MRT6_DEL_MFC(r0, 0x29, 0x69, &(0x7f0000000200)={{0x18, 0x1}, {0x18, 0x1}}, 0x5c)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
r3 = socket(0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x2, 0x0, 0x0, 0x3, 0xffffffffffffffff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r4 = socket(0x18, 0x2, 0x0)
dup2(r3, r4)


semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
r1 = socket(0x2, 0x3, 0x0)
flock(0xffffffffffffffff, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
ktrace(0x0, 0x0, 0x0, 0x0)
r2 = openat$null(0xffffffffffffff9c, &(0x7f0000002f40), 0x0, 0x0)
readv(r2, &(0x7f00000002c0)=[{0x0}], 0x1)
openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
r3 = socket(0x18, 0x2, 0x0)
unveil(0x0, 0x0)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r4 = dup2(r3, r1)
setsockopt$sock_int(r4, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
write(r1, &(0x7f0000001680)="04bdfa5d1d2873c63e3534825ba166e2fea9aec43050006123339a346f731573d8d508753f95b7688ad48b8cf6bbca325cebc37fc4e1dd543dbe2da6dd", 0x1001c)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x0, 0x11, r0, 0x0)
mmap(&(0x7f0000000000/0x4000)=nil, 0x4000, 0x0, 0x11, r0, 0x0)


getuid()
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000280), 0x0, 0x0)
ioctl$VMM_IOC_INFO(r0, 0xc0185603, &(0x7f0000000300)={0x0, 0x0, 0x0})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000280), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{0x87}, {0x50}, {0x6}]})
syz_emit_ethernet(0x1b, &(0x7f0000000000)=ANY=[])


socket$inet(0x2, 0x8003, 0x0)
r0 = socket$inet(0x2, 0x8003, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x800, &(0x7f0000000000)=0x10000, 0x4)
syz_emit_ethernet(0x2a, &(0x7f00000002c0)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, @multicast2}, @icmp=@echo}}}})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000980)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f0000000000)=[{0x44}, {0x16}]})
write(r0, &(0x7f0000000180)="7f23a3c23cce2575e1dd92c25683", 0xe)


open(&(0x7f0000000480)='./file0\x00', 0x200, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r0)
r1 = getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r1})
pipe(&(0x7f00000001c0)={<r2=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r2, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r3 = fcntl$getown(r2, 0x5)
setreuid(0xee00, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0xb32, r3)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r0, 0xc2585601, &(0x7f0000000040)={0x10, 0x0, [{&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil, 0x100000000}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ff7000/0x4000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ff2000/0xe000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ff9000/0x3000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ff1000/0x2000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff4000/0x1000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000ffc000/0x1000)=nil}, {&(0x7f0000ff7000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000001000/0x2000)=nil, &(0x7f0000ff2000/0x4000)=nil}], './file0\x00'})


sysctl$kern(&(0x7f0000000000), 0x2, &(0x7f0000000080)="71f91e3471ac0058bc5a91501d94a34b8e5f84cc42c3fbe6edf28f03055a7b8379c80000ff7f000000000000000000", &(0x7f0000000040)=0x2f, 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000240)="ea", 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = open$dir(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')
unveil(&(0x7f0000000240)='.\x00', &(0x7f00000002c0)='c\x00')
chflagsat(r0, &(0x7f0000000000)='./file0\x00', 0x0, 0x0)


sysctl$kern(0x0, 0x0, &(0x7f0000000100)='q', &(0x7f0000000080)=0x1, 0x0, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x2, 0x0, "01000000d000"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000040), 0x3, 0x0, 0x0, &(0x7f0000000080)="4f1d4c6344b80ed788b6a4515248df3aa745bb992c574ab4cdf5587145812eab4a988f7fafd7a01d99776d988908cd186b51f34f8c15ffa0c685ad4116c783959eff4278384b4000384dbb1c2aaeff10b4135529a1da6fda67c67469d954be811b25ec5521559154c586eefff122009f659cd3e27e98a3241495005f102d9101d158284c0ee3250aa7c11042330de22a299ab00894fdc9bac6042d", 0x4)


mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000001380)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000340)='./file0\x00', 0x0)
rename(0x0, &(0x7f0000000580)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000f80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000001080)='./file0\x00')
chroot(0x0)
msgget(0x3, 0xc0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x2, 0x0, 0x0, 0x1}, {0x86}]})
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000240)=[{0x40}, {0x54}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f00000001c0)=ANY=[])
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x3, 0x0)
setsockopt(r1, 0x1000000029, 0x2b, &(0x7f0000000000)="8c740b72", 0x4)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCLOCK(r2, 0x20004276)
seteuid(0xffffffffffffffff)
r3 = semget$private(0x0, 0x2, 0x80)
semctl$IPC_RMID(r3, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x2c8})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000140)={0x7fffffff, 0x0, 0x7, 0x0, "2fecacf2ee60987a0d0239060000aa175b31cb31"})
writev(r0, &(0x7f0000000200)=[{&(0x7f0000000440)="b8f980f85c259576fe50f665028b465eb82f1c79fe905245dfdfd22072971f805f78c84deb9ccdc2998500e7d7986ef9b8a986265e3160e19c180f1268133068b9a6652a45e2c011178d119b52e1813d197406de1f68cb00649378904fdf4f56776e9eab2169d5749eeb8c84736525e8ed8441536b73e524a7563235068a8e102686eeb2ee590000", 0x88}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f00000002c0), 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000280)={0x3, &(0x7f0000000140)=[{0x64}, {0x5c}, {0x812e}]})
socket(0x0, 0x0, 0x0)
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)


r0 = syz_open_pts()
unveil(&(0x7f0000000280)='.\x00', &(0x7f00000002c0)='c\x00')
ioctl$TIOCCONS(r0, 0x80047462, &(0x7f00000001c0)=0x3)


fchdir(0xffffffffffffffff)
syz_open_pts()
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
socket(0x20, 0x0, 0x2)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, &(0x7f00000001c0))
socketpair$unix(0x1, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1, &(0x7f0000000240)=0x5, 0x4)
mknod(&(0x7f0000000040)='./file0\x00', 0x6000, 0xe02)
mknod(&(0x7f0000000000)='./bus\x00', 0x3a0914c44f7b202d, 0x504)
open(&(0x7f0000000040)='./bus\x00', 0x10, 0x96)


r0 = socket(0x18, 0x2, 0x0)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x3b, 0x0, 0x0)


openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f00000000c0)=[{0x1d}, {0x3}, {0x6}]})
syz_emit_ethernet(0x10a2, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x2}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x200, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x8040691a, 0x0)
ioctl$BIOCVERSION(0xffffffffffffffff, 0x40044271, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
mprotect(&(0x7f000051d000/0x3000)=nil, 0x3000, 0x0)
clock_settime(0x3, &(0x7f0000000000)={0x0, 0x401})
connect$unix(0xffffffffffffffff, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
sync()


r0 = socket$inet(0x2, 0x8002, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
dup2(r1, r0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000a, &(0x7f0000000000)="01", 0x1)


r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r3 = socket(0x2, 0x2, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r3, &(0x7f0000000000), 0x10)
r4 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x1023, &(0x7f0000000040), 0x4)
recvmmsg(r4, &(0x7f0000000180)={0x0}, 0x10, 0x0, 0x0)


ioctl$WSDISPLAYIO_GVIDEO(0xffffffffffffffff, 0x40045744, 0x0)
semget$private(0x0, 0x1, 0x0)


r0 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
unveil(&(0x7f0000000040)='./file1\x00', &(0x7f00000000c0)='c\x00')
mknodat(r0, &(0x7f0000000500)='./file0\x00', 0x0, 0x0)


r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
setsockopt$inet_opts(r0, 0x0, 0x200000000000b, &(0x7f0000000340)="b7", 0x1)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
syz_open_pts()
syz_emit_ethernet(0x119, 0x0)
r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x2, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000040)={&(0x7f00000000c0)})
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000180)={<r1=>0x0}, 0xc)
r2 = socket(0x18, 0x2, 0x0)
close(r2)
r3 = socket(0x0, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x7fb, 0x0, 0x0, 0x0, 0x0, 0x140, 0x3}, 0x0, 0x20000000002, r1, r1, 0x1000000000000000, 0x4000000000, 0xffffffffffffffff})
bind$unix(r3, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
openat$pf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
poll(&(0x7f00000002c0), 0x0, 0x0)
r4 = getpid()
ktrace(&(0x7f0000001d40)='./file0\x00', 0x0, 0x1720, r4)
clock_getres(0x3, &(0x7f0000000280))
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r5 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x81286947, 0x0)
pipe2(&(0x7f00000001c0)={<r6=>0xffffffffffffffff}, 0x10004)
readv(r6, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r5, 0x0)
r7 = msgget$private(0x0, 0x230)
msgsnd(r7, &(0x7f0000000040)=ANY=[], 0x0, 0x0)


setreuid(0xee00, 0x0)
setreuid(0x0, 0xffffffffffffffff)


open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
chmod(&(0x7f0000000080)='./file0\x00', 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
open(0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{0x45}, {0x2}, {0x8006}]})
syz_emit_ethernet(0x119, &(0x7f0000000c80)=ANY=[])
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f0000000080)={0x10, 0x0, [{&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffb000/0x5000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000800000/0x800000)=nil, &(0x7f0000d91000/0x4000)=nil}, {&(0x7f0000f56000/0x1000)=nil, &(0x7f00008fb000/0x2000)=nil}, {&(0x7f0000e4c000/0x4000)=nil, &(0x7f0000efd000/0x1000)=nil}, {&(0x7f0000cd3000/0x1000)=nil, &(0x7f0000862000/0x2000)=nil}, {&(0x7f0000d3d000/0x4000)=nil, &(0x7f0000aff000/0x1000)=nil}, {&(0x7f0000f6a000/0x2000)=nil, &(0x7f0000887000/0x4000)=nil}, {&(0x7f0000da1000/0x4000)=nil, &(0x7f0000b4b000/0x3000)=nil}, {&(0x7f0000e0f000/0x2000)=nil, &(0x7f0000e03000/0x3000)=nil}, {&(0x7f0000c64000/0x14000)=nil, &(0x7f0000d93000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000bd7000/0x4000)=nil}, {&(0x7f0000913000/0x2000)=nil, &(0x7f0000c5e000/0x4000)=nil}], './file0\x00'})
r2 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0106978, &(0x7f00000001c0))
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x2, 0x0, 0x0, 0x3}, {0x1f}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
write(r0, &(0x7f0000000500)="5429102bb15d3d2145f713a5bb02fc8801121b8d2117cbc1f045d9385a2ad3a7b5c5a3e1fef0e412d92882d53acc5fa16cacabb889054ef0155fdd5b9f583ce3d6d3a62ebab52329fc904ba46a45626f53c72ac1a4a94b1c13edc18d71acc6aae76f77cd134d981340b488138e38a031323e3758e12321705826acc2c7889d7c44d98630db3843bc3d9cdc525d6da59e109c19b3050da712c1c43449b3b47a73ecaa31908d5e826810b8d1d94d76ef28b930e5b8b2bc691ed3ba07028c4385eb21b83164fd23bec76433eb3276fe6467077c4bd55c814d", 0xd7)
execve(0x0, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000400)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f00000000c0)={0x0, 0x1ff, 0x7, 0x820351a, "00000000000400000000000000000900"})
writev(r0, &(0x7f0000000040)=[{&(0x7f0000000000)="c0a93fab87272b3e50476effff2f28ee52b607bcdceac0d123208a3e3a1b02c6cdbc87580400", 0x26}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x81}, {0x4d}, {0x16}]})
write(r0, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xfef3)


socketpair$unix(0x1, 0x2, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000080))
open$dir(&(0x7f0000000080)='.\x00', 0x0, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r1 = fcntl$dupfd(r0, 0x3, 0xffffffffffffffff)
open(&(0x7f0000000000)='./file0\x00', 0x9cab835cfdc52675, 0x0)
r2 = getppid()
ktrace(0x0, 0x5, 0x40000d30, r2)
ioctl$FIONREAD(r1, 0x800c745b, &(0x7f0000000080))
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000001c0)=[{}, {}, {0x6}]})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r3 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x8020691f, &(0x7f00000001c0))


r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
socket(0x2, 0x2, 0x0)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)
poll(0x0, 0x0, 0xffff)
r3 = socket(0x1, 0x1, 0x0)
r4 = dup2(r3, r3)
r5 = fcntl$dupfd(r4, 0x2, 0xffffffffffffffff)
close(r5)


syz_emit_ethernet(0x2d, &(0x7f0000000000)={@local, @local, [], {@ipv6}})
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
r1 = getpgid(0x0)
setpgid(0x0, 0x0)
setpgid(0x0, r1)
setpgid(0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000140)=[{0x80}, {0x40}, {0x12e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x2, 0x1, 0x0)
connect$inet(r2, &(0x7f0000000000), 0x10)


r0 = socket$inet(0x2, 0x4000, 0x0)
setsockopt(r0, 0x0, 0x7, &(0x7f0000000340)="15337ac0", 0x4)
syz_emit_ethernet(0x2a, &(0x7f0000000480)=ANY=[@ANYBLOB="ff7800edd6e89f4368b5d068502559340956bb85c85e33e991571a4d2eeb98f588fb4a20818a67c355cc8a0cc9fb3b6e9add1a7ebe0c3cb23b7053d9849b3345de71eb9fa64f517833139efc48d022dde659949c0dbc1165ddf93147eaca1bb238430216d3707012d4d699839409fcfa177cbb7060753933d82c35fcac7b409ffc96570de27b1aaf93190bc895a2a224d4f38d9acc344021f14101b0617fc21e21789110fed42bcf7154bef718e0651f62a06fe8c1a2993b27c39d77be6c9abc83c457872f1e147802d98d9884ba3c95c3814f1117d4ebb7119724206775b877d121bda7202555580f9f645ab25c6e6a4ac9274fd96a299b391679b3dc262117eeabe7cb8f6602d60c30cbd2b20137671d7f342b195e2d740ba9d72d0090a38592a7ad0f8847e3ec5322361e31e425d5b7c1b94004d8cc2f02923c780f9646418608ff1999218549cdcc21d5323ccf242643265943fa"])
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x2, 0x0)
mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
r2 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f00000000c0)={0x5, &(0x7f0000000340)=[{0x25, 0x0, 0x3}, {}, {}, {0x8}, {0x6}]})
write(0xffffffffffffffff, &(0x7f0000000200), 0x0)
chroot(&(0x7f0000000100)='./file0/file0\x00')
r3 = semget$private(0x0, 0x4, 0x1)
semctl$SETVAL(r3, 0x0, 0x8, &(0x7f00000002c0)=0xff)
rename(&(0x7f00000001c0)='./file0/file0/..\x00', &(0x7f0000000280)='./file0\x00')
connect$unix(0xffffffffffffffff, &(0x7f0000000140)=@file={0x0, './file0/file0\x00'}, 0x10)
openat$bpf(0xffffffffffffff9c, 0x0, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000180)="b1000501600000000000000007000000331c13fecea10500fef96ecfc72fd3357ae320b37b673039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139b672f4d335d223e7d026ba8af630037282102000000720fd38bfbb770c1f5a872c881ea6e69e0bb76d907c400000200361b1257aea8c500002002fb00000000008abfba09000000ec29dff8f8353712051eadb71d89e000040781e4b2ffe040ff0008254842899ff2ef932e811f29902bd41c00", 0xb1, 0x406, 0x0, 0x3c)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000300), 0x10, 0x0)
ioctl$BIOCSETF(r4, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f00000000c0)=[{0x5}, {0x84}, {0x16}]})
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f0000000080)=ANY=[])
r5 = socket$inet(0x2, 0x3, 0x7)
fchmod(r1, 0x14d)
setrlimit(0x2, &(0x7f0000000000)={0x60000000, 0xffffffffffff4e6e})
setsockopt$inet_opts(r5, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)


syz_emit_ethernet(0x4a, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x0, 0x1}]})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
clock_gettime(0x2, 0x0)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000000c0), &(0x7f0000000240)=0x5d)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x37}, 0x4, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x4d, 0x0, 0x2e)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
socket(0x18, 0x2, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f00000002c0)=""/42, 0x2a}], 0x1)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1400000029"], 0x3e}, 0x0)
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)


mkdir(&(0x7f0000000040)='./file0\x00', 0x0)
mkdir(&(0x7f0000000140)='./file1\x00', 0x0)
mkdir(&(0x7f0000000240)='./file0/file1\x00', 0x0)
unveil(&(0x7f0000000000)='./file0\x00', &(0x7f00000001c0)='x\x00')
chroot(&(0x7f0000000100)='./file0/file1\x00')
unveil(&(0x7f0000000340)='./file1\x00', &(0x7f0000000380)='r\x00')
unveil(&(0x7f0000000080)='./file0/file1\x00', &(0x7f00000000c0)='r\x00')


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
dup2(r1, r0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00004100000000", 0x8)
setsockopt$inet_opts(r0, 0x0, 0xd, &(0x7f00000000c0)="ea001d0100004865f88ac400", 0xc)


nanosleep(&(0x7f0000000040)={0x7}, &(0x7f00000000c0))
execve(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x5}, {0x1}, {0x6}]})
syz_emit_ethernet(0x1b, &(0x7f0000000000)=ANY=[])


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
semop(0x0, 0x0, 0x0)
shmctl$IPC_STAT(0x0, 0x2, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r0 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000002000/0x3000)=nil)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
shmctl$IPC_RMID(r0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x28}, {}, {0x6}]})
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
recvmmsg(r1, &(0x7f0000000480)={0x0}, 0x10, 0x0, &(0x7f0000000500)={0x2007fffc})
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, &(0x7f00000001c0))
kqueue()
socket$inet(0x2, 0x1, 0x0)
setsockopt(r2, 0x0, 0x6, &(0x7f0000000200)="0090a98fef487a94abb8e62683bc5b0f022047724590a8b0f3dc48986ff939b050456410459628aeba07be25f7549acb560e84a7496a7c1f0a695b87ba56086d8743e962c09ad5f334aedc3e65cffaca7f000000000500000000000000", 0x5d)
mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x40005d4a)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x3, 0x0, 0x0, 0x0, 0x0, 0x60, 0x1}})
r3 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000180), 0x100, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$VMM_IOC_INFO(r3, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})


r0 = syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x7fffffff, "2cf748460adb56e8dd42caee5275882ceece40cf"})
syz_open_pts()
ioctl$TIOCSTART(r0, 0x2000746e)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000140)=[{0x84}, {0x81}, {0x810e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


socket(0x11, 0x3, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000340)={'tap', 0x0})
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
fcntl$dupfd(r1, 0x3, 0xffffffffffffffff)
syz_emit_ethernet(0x76, &(0x7f0000000080)=ANY=[])
r2 = socket(0x2, 0x2, 0x0)
open$dir(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
r3 = socket(0x18, 0x1, 0x0)
close(r3)
r4 = socket(0x18, 0x2, 0x0)
setsockopt(r4, 0x1000000000029, 0xb, &(0x7f0000000080)='\x00\x00\x00\x00', 0x4)
setreuid(0xee00, 0x0)
r5 = getuid()
setreuid(0xee00, r5)
setsockopt(r3, 0x1000000029, 0xd, &(0x7f0000000040)="ebffcb9296", 0x5)
r6 = dup(r2)
setsockopt$inet_opts(r6, 0x0, 0x13, 0x0, 0x0)
r7 = semget$private(0x0, 0x1, 0x498)
kevent(0xffffffffffffff9c, &(0x7f0000000000)=[{{r0}, 0x0, 0x0, 0x0, 0x2}], 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f00000010c0)={0x1, 0x30}, 0x2, &(0x7f0000001100)="2134517fca6ea5beab9bf93a7b188b0284728e1fa334091e153c00155b6c6fd6b4263fc53d7d7ecda89fdf5ba5006d03c1a3a485ddb79b17d5ae844fa8b54b9e4988f8c5c2726e7ffc2b52ba5d3228a9571bf5d30c6c7d47399313a8271143fa805a5ef16b619b9fd09e259941e1e0d5b6e6a8c21a04c1a2dffe1af25bebdadcca0967ef96af6822486f04d9b21b5228943e58e66f55a677a1bc26a18fb2fdfb15feeeb0afcd81ad65e1fe3264dab61bcbb440", &(0x7f00000011c0)=0xb3, &(0x7f0000001200), 0x0)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000000)={0x0, 0x3}, 0x10)
sysctl$kern(&(0x7f0000000000)={0x1, 0x42}, 0x6, 0x0, 0x0, 0x0, 0x0)
semctl$GETNCNT(r7, 0x2, 0x3, &(0x7f00000000c0)=""/4096)


kevent(0xffffffffffffff9c, &(0x7f0000000040)=[{{}, 0x0, 0x0, 0x0, 0x5}], 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x6, &(0x7f0000000080), 0x0, 0x0, 0x0)


semop(0x0, &(0x7f0000000100)=[{}, {0x0, 0x2ff}], 0x2)
sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000000)="9b1809ffffffffffffff7f473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6fd74c94d1b44", &(0x7f0000000040)=0x10011, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
poll(&(0x7f0000000300)=[{r1, 0x40}], 0x1, 0x1000)
dup2(r0, r1)


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
setreuid(0x0, 0xee01)
r0 = shmget$private(0x0, 0x2000, 0x0, &(0x7f0000ffc000/0x2000)=nil)
shmctl$IPC_SET(r0, 0x1, &(0x7f0000000000)={{0x0, 0x0, 0x0, 0x0, 0x140}, 0x0, 0x0, 0x0, 0xffffffffffffffff})
shmat(r0, &(0x7f0000001000/0x3000)=nil, 0x3000)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
shmctl$IPC_RMID(r0, 0x0)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x2, 0x0)
r1 = dup(r0)
setsockopt$inet_opts(r1, 0x0, 0x13, &(0x7f0000000040)="fd0cc085", 0x4)


r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x0)
setsockopt(r1, 0x1000000029, 0x31, &(0x7f00000000c0)="b211d7170d816685c8e360f2fa41c1a0946988b272d2dd3dc90142a84231a746e337b372e93320cff6669cbe7868de45ed3fc33719ca6df71ecec8a918458b2c10a1f8c66653b276e180e9cb9b21f9982230f575295d48889c9a920796b2dd92fc8575680b37ba955d2c15e6d7c9198ed900ab006ddfb67869b51a2216114d1ece85f593e74035f5bc054eb1dbddf42a", 0x90)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff})
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
writev(r1, &(0x7f0000000000)=[{0x0}], 0x1)


syz_emit_ethernet(0x36, &(0x7f0000000000)={@local, @empty, [], {@ipv4={0x800, {{0x8, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @rand_addr, {[@rr={0x7, 0xb, 0x7, [@broadcast, @loopback]}]}}, @udp={{0x1, 0x3, 0x8}}}}}})


syz_emit_ethernet(0x1a, &(0x7f0000000040)={@broadcast, @broadcast, [], {@arp={0x8035, @ether_ipv4={0x1, 0x800, 0x6, 0x4, 0x0, @empty, @empty, @broadcast, @loopback}}}})
sysctl$hw(&(0x7f0000000000)={0x6, 0x1}, 0x2, 0x0, 0x0, &(0x7f0000000280), 0x0)
r0 = socket$inet(0x2, 0x8003, 0x0)
setsockopt(r0, 0x0, 0x7, &(0x7f0000000340)="15337ac0", 0x4)
syz_extract_tcp_res(&(0x7f0000000000), 0x9, 0x347)
syz_emit_ethernet(0xbc, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0xae, 0x0, 0x1}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}, {"d1c2f0bfe2d0786ca28e44289f59aba04d62ff16e6bb47f1cd981d0cf5f225560531db5a3a6c3cb3d5ac50e0eec7423f3ef5e3c4a13f81f14f843a32b529e4649b57d581159522ddf03a6cabf358af4e1ae7ab79a9aac6417859ae29d8de08ba3da1e6387381a61f166b78d7ae58ccd15a08555c8e7db3e261cbba4f565ff3567edfcacd1a43"}}}}}})


write(0xffffffffffffffff, &(0x7f0000000740)="76e5dead6f01f8607d2100000063", 0xe)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000040)="94c79bd261e1e88e83beb11c0a3e154df77b5335bd1667d9fd77c59297b3cad0ade427f63f2912518a179b7c207bc5ba040a20b5c36bfaca54e49900550bad2f165552f266a6b12d4900c56a22e814223e67a3fdf5ae19bcbb5d0a815015db8752d03d1b08f84b4976ec52d4a82598424ed3a6a523a3591db0e862a2f4dd1168cb17845fff1fb5df5535cae3e20e2bdb92138d0c1b0720e1c121ccb763f092cd5dcaa3d901", 0x2cfea}], 0x10000000000001fc)


ioctl$BIOCSETWF(0xffffffffffffff9c, 0x80104277, &(0x7f0000000000)={0x1, &(0x7f00000000c0)=[{}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)='\t\x00\x00\x00', 0x4)
r1 = dup(r0)
setsockopt(r1, 0x1000000000029, 0xc, &(0x7f0000000000)="ffdaff10aac6a28ac93e2eddc45c8454e486f64c", 0x14)


mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x2801)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f0000000140)={&(0x7f00000000c0)='./bus\x00', 0x497, 0x0})


pipe2(&(0x7f0000000780)={<r0=>0xffffffffffffffff}, 0x0)
close(r0)
getdents(r0, 0x0, 0x0)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xffffffffffffffff})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x0)
r2 = dup2(r0, r1)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
r3 = socket(0x18, 0x2, 0x0)
r4 = dup2(r1, r3)
write(r4, &(0x7f0000000140)="0c398c088c93a3ccf8ea23045b766cd41e7991c7fbd4eaa11603876cbaea89c77c07e049fb603ae46d28a7874d5daac09ada48d35448d4abcd8cca749991285c7ade9b964cbbef22a7a5f185a30291308fbe3ba6eb39d2595d7cc05bebfe3be3a6c8ee37087d3bd3544f4d18a3437ea5d98d17e61df56e653e11a875d3d654c1340fc4afacf796d0e091197693e154fcdff4c0958ca215c0e71c0daa1dd071a84ee075a23d083fb92efa15651e955d4b3d3bd736830185328b974f43f553eb18e269386103f0a3fb65f1fae83a343b20f2e6aa4c6be16925f28c57670152e59556845e76ce7fba34e6cc3356b14920b0e6735b72185823a25ec04fe0902602a730ee377947871b749cc08ac498f347ae25b8190ea951a205d267bfa364cc575c1dc55eb08b1758c4e7d5e557a57ae84f8b0fb79b81157f31bb41368508abf76a02bada29c17e952d6efbb1fda650cb19d1eaf3edca69ff972ee63504c725bdd71a5bbffd9b416671dbcfa5572db125939132bb9d98e45cf827da0021e1c424c379259afac6efcd03c54eff682f75a15e24f65e6e9b392c0ceb8a279d3a4d67328fed41c4d1f648651aa4c2443452d2735a33c9d00d23fc1f18c7ba5c66f173c5715687380f43d4ed71542a4e0e7f49b7eec632a00e270e1efed20e6a17d082bbc07a0c00ce376e78f5d9557e20de23727282b89562a418c81a37d4d373f907ddb80193ee013445c30a2b82b2bbac6675a3956b68f65054a3d220327c70ef33eec994c230d9c6f90b8d7bb187eded0dda81fc8382878398d94789e28317ca71607381e7bcc9f305d764762f95b1446ff964e893a4b71bd6af1603320fd9aa65d7535ef37f816e35f78252eb917a33f9db51ac22bad185e27c75633c5f42b778a19b727bb7fed3c8c920ce624d7e8b85be9ec1f9ee439b9a9a8f90c398f957d21c3dc08daa298b5bd4b2dc0fcaa0cc7ef7f0cb932cfda350a5e2daffad436f36793b496bd14e48f7506e66df5e9fe4964c53893da52d7da913fe1ac9fd2563407ec7b375df97a5f7efb01849a14b6bcc62b0800f99a2e3f755940384724f92867252e824f59ea25d46c32f9df369d1454519903717f08667d15a5a6f7706a7c448dfdbf66e58994cba95cc086cb0ac1026d474e02d1243ebeb98e5e3b2d9d282635ee072520242b77ea67adf93cd377b58d3cef40015ec966497b457c0bcb3eb9fe79c62da2bd2907270a0c8ca0321598b906c6c9dd12373085f41f64f5dd29017a1b05caed12a4aca525abae2da2b0603b1530dfdcc7e04840b57546af976f6877878ebbb6dd8c90995418d6ae9c471a30630ad581428228abae8e0d7f05da49852afc82f6e63152b7587322c5f6803c8abf7e704b6aa401e2b6e87c122c3a80f72ed840394fb816f61fe82f872c7c1657525211119c4b1e279d7b684efb39d5c50f144e18fea4912fa5747b8c52205e0a51bb831189bc1760e7d8c03e4dc97b79ba0c8475ac474d92584a97ef7505fb20f117c059667b74a8da3361f3d3367d0a0e175ae6480bbe1c5ed630490fd44f5e51775d5f71a0ad1b67a4e538dd514345966bdf6345ab0a1901a67126c22298f345205582a80766293a21c39b9370f231f529d4663ca2e008310c8e33c6aac12142433e3316903915334ded1ac4c8b79859810d6f0d25568fb3aed05ae686f5b700c1ca2d74388df0dc85167144e9cc501fab02fc64a20a4dca6795b0be938f644756a9ab551e08b8e", 0x4d9)


socket(0x11, 0x3, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x100, 0x80)
sysctl$machdep(&(0x7f0000000080)={0x7, 0x10}, 0x2, 0x0, 0x0, &(0x7f0000000200), 0x0)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
r1 = socket(0x2, 0x1, 0x0)
r2 = dup2(r1, r1)
shutdown(r2, 0x1)
sendto(r1, 0x0, 0x0, 0x404, 0x0, 0x0)
writev(r0, &(0x7f0000001480)=[{&(0x7f0000000100)="cc60d3d79a1a7122a5fb9de9ea6ca0b30fb2942ef7652736f10f86d45ae419b2ecf7af93d33b3de1f2c56c0d93da7484095d0d543baf7f0161a025c9c02a561f9a76d06f1eaec7d8df99d6c28b10fa891e47d6c3bba690a611889032ac7b3581d7c92d1c546e59764f069048316871794f0615dd4d8bb1057a61fb177be649004fb56a7d46c856a20d73f050bf29d58b803a676cc3761e8a47857f51d90a4465f9c605ab2829d78ea2571900", 0xac}, {&(0x7f0000000080)="b389e5ae", 0x4}, {&(0x7f0000000200)}, {&(0x7f0000000240)="2a5f4cd9b73c31d629e8d68e605e5940744ef138960b671d42c56f79fcb70549247e5504e02f85a6099eff9291731e94399a7e966e783d4073ecd5dc8e540f32190bb47050aee3907495ecf7708d1c295a0836f79ba03ea13db12836c2441989726ffbf7fd1da55bfe2caaf081a1ef55599935c0e60cb0866ee48d420b77a6e269bc30b2650349e16792252c6be8bcc6e9ce2b941299ab505e4779fa1960bb7cf924dcbc53c82e76bcd80731a694d12e8a139d8ecef6f5560939054b7842d25cd7396377f39bcfe2a2383feea17b87393cd892b90742631718b1877d8d83d5f66587e3e5b1e129433ead750143a4c51aa46e78e3b1a54a4634eea2846511719b1637b19ea8c96a95332abd69014f53e91a7319a36efb4052387dc6330aa00b5680142650e8dab5eb6b83ff7d0bbf1293338a8d3e8a6dcd7ed4916279eac230dda46e6fcdebe8a4c12d598883d9392da05791e153d905ce1930aebfc5dfc0fc22a88777c9fbc24c0b021189c3503466bf850f59e6649dd0b40d935ba155a9d7e065df6d90a500be9d7e1e77607d495898a8d6c9c48dda88533e75e760dceae91d670f97ebbe68b845c72eb698a9e0389b15cfe768cd4e524dbe939bc2d8363ae3b71a454a0a0378cd1f36565ab9d1b92263688195df65151ee9b8158c7a5280019a38f00ea05142b3cc832ece46e326e36a55d7a30f866ca97da61a3877612f0d9f23c052edf60a430d3a9acbae3d9f14f22f38a1eeac7df37ae17748a960b9e0d265bf6cdec73bd2a7b5f25035d845d936936cbfe6f013f8d7c73eba2bd9876ff6db3224e50e75c051979f4cdc41d28ea54e28f560fb0291cd6b6ba527e0f358ffa46b988f0bdbf801063d2024380071709ac00ed463e08fd1718a857b567d8b3eda143915e943d9530d25ed15743e117be375dc08e241328a53fa05b58c7c72a35d471a72706afce82b6c57eef81444269e06338bfd0af6f6ef6479dcc26aab0b10c7e58572aa507a69831d63c78c947cecda2c57bb8ae6b2ad7862d160b423de941be69928467db10ee4817536196ad0c5cc02a74ba1a1fb467e472f025f200846112b6b3efd298284d8c0cc498fb9203db18e48e34c137d1285120d809a774d56a62b3dbe8f202cb9cf18c33099f5b9651fc7ae41de53842f327fd40bcfaa601a791da1103351a64cc9815ff1f32cde6fbfe4c92f55a9aff41c055d4edce9c656ecd1becb9035bb8bd46cf47bca0dcb1848da94d05d1475c83a48c02f8f808597eaa9e88a4e4b12d0ef95458eeab115cb189fa7e368186bb68610af4651e27feab061c4ada46e8c12d6d33fe32cd40485b02120418a9aaba8f04c17ea1abdcb9e6801f5d8090c0780b3b5ae4382efbb64f62c825527b7e3d60ad9c73ba7f174ea7c7f2d155808052a0ef6ab2af85cf9a758a8c1227c85f2986fc06c5f54807968b18b6b5f9168d0b2de2728689d75f0efaedf79bd8bbbbc1d46b0f6072d46d46687bc92c0b16c4ad36c3fe4c7a2fde0cfec859052dd78d841464a6b4432342ea973bf18f1f5abd7b2fe7962faef39ff38bd88a40dbab0f8c08541e38efe924f9ec1addbd47362e349bfca42fd62cf18fef8db7d3cbf0b1733d37dcdae5b9c738b8426a1cfa205c9671870210508c614f256d199fb822613518b1a6fccfee08c48f0feae1ca4baaf0a02635282d4f630a8df115dc73e72d9f7b8feb4333b2c796f1d3f2cfb398ba1e9c81584185b8b578bac3c64d667da7d91062f0c2ccec0c9d09e0c15c62e7bc509c3204d054c22d4eac685626e48e25cff2fc382279d9cb941c2ca182b1f65b05ff05db880a37b1e7f9b3d8975558858352bbbea9213a885b7d43451230e0624403baa77839baa33ae92de771ca76319c2353e9f98ea8191fbb686aed6d08e87bcc2bb8084ae02fafbac1a0bba93f0f155fa2d7bc21bf77f116429c6a1373c34d080518b73481fcf012c0a9127e8f174695ccd4add75b026bf2935990d5cebc4e74b97ae67a414029252336880232635fce7ed7bf0b069e08e10f7e1cc4d2973dcd2ea0b63f9dc4f4c2db92e03c553afcb1060b12f6b9b4d1d799edceefdfafdae63ad797e400645c149b20f8a10af54db3289441499e122413495c7b32179ab6c274bbdf6dde48ce26f46f07ede9a314c1a73669ee8cb0d854c8a3206dcd4f532d36fa7affca1226962e20ca2c6ca0da1ab0848d23d6f198681911592815c080cead9fe6c81cf0d7ce3578978dbf1dc2f1902e51f740f95b02ebff4cf25ac8d28b8e16998f5e329e9a377a82b5bc227f77c2f1ad505286aac8618799c2363a2d07d229519370be62ef0dde6525df45a7b807759b9ba1c8557bdbecb429432c4e1a84094edda567f1245ba887686342d0a31b7dbe09bd2be75516b255d2bfad9337649e86a29b0a19e16b4059c7c45e9f81db6780af6487a11f9088ea265a99d6e95535e14fe839945f8f7da9bf9142dd12c305bd41bb392cae8eb81b28fda176d4b538f4ddaaed47913cd9149d934ca36879718bbd76a2d7ce11e6294398ea433af6cf53b951974ec96a9527178b6cbad3088a2e2dc75113fa88ede462e68b4d6b63020a45e94fbc6c3e6677d6cffee0e3bf606cd2d4b9fac89f91db8f3a1fb9f506708314249fa5c36912e3cb281acbdec3b080735ae24ebb4bca3c7900c21175435afbe5024a706e90f8ecf257c99cd8b67b5a9c2bdc2bb624201f55882349526f8faf463eecb183635db72a6aef5fa2048d97e6f6c513598f49158050df1efc6b13b8ae396cd6a905c26b94d1d50d361f10c0362a8c206c7dd553dd8b116694aa82ac029c64aa71b8a307793da12f93ce030d3c42443c37b91043687befb7968da97ffe91d45e4fd506ba4d9c5d7fe5ac7433fb6bb3ce471f59ade734d109d2093fa119827b65a360f2128e7e85ab494609b60d6e236ed8a72984f6c75652f5baa07e2e921365af2b819eef58343e65ffb45ba8580d62f5b8a9988f7176c1559f8ede3b1b92e0ff27978fc5225ed1512b605f1fd4fce46e768970b11a7b4802c93eb05a8571887cdc15f69929eadcd1f9d08ed2d6aab2997ffa2102c2d8983a78ad43779d03aa612ecbbdde634b14e980b176f04f99efad82a04001f34d6addb89e0ce629856f5ad401fed1a2c046e1fe18741b24d4253830af94a1defeecdf6f70b430e48d7b2e4ae2fb331322d96e1a361e4dcae1d0865e7ccc4aa58bcbb3ad1ce0b294437887e03088a6bb4c92c3044bb33d2a893975023ad979fb2f84d4842326cf058595398779116245c452e54989df0591238af63c5b187d18457f008f2759ae470282ee4640e92639a46915fb67f22967beb1f46736aa9c90df08f39ee481f6859f9eafdecd473bdc24ef3ad71b4c54dde360f2d550db18af7589c8107f29b0a713b65f039da10c2dc55e408ce75c77aba97c116ab078ed1467464fe4041668228316f0fff7c0e0f1a3cc47aae570182197cc3a030a4af7fe2d401b5a13d59b8fe55d48b0667b782cbf1c2e9e491167d87830bb25008aff93c4459a3ce9fd8655a542c6311d91ec6b6bd7935aba1cd01d10439f5e5a3883566c8538edb97c5d2a7c7533d415973729f52dc03134f3d777b7ad07c0f5b0d985ca48fde6cce9ec99f1223f476dcfbb5ef865a3f54459415b25e2031eeb469c83ac68fd77e59c6b6a4b9543a943c4461e47e94d038c63abf2734a3c0e99b95505e13af6cf7b66840dc60e96fb218436ea00b4a577c2effdba43e6adf97cb47c0ce606e87a7834dec04396c1e4f7df59ae5acedfd1d68c87e405fc5d788884686270cb08f0fb15fe8b11589792f9afc11152cd45f43fac6e758588cfaa88874267c3096bd689108bbb0296f3d182df7d46cf7e6b8bb923ba887443c3d2211785e364c1e55d4e9396d950e50cc11ba9a4da70a64f6acbbcd421183eb2c0521054c4f39650409e21a9d3b781725b0c38abce7b4615fa64a9cbf71a19f7e414279a7494d2e66e4e2b2d5ce7027109cfc763a9dcac37065ae80ec0cf3962deec0f9eba3bd7c514a9854ddec6542cf60a1e69cf5d1a73239633675d4ac1f3b0758e69d1d9fb8659f43f07ef6b0b2a7c9740649198b44f3272a8810d374b00c1d49b7f667ed538d89e91e5734f8d6e270aef0a406fcb4072497dd5f25b49d31cfd64f7af2d5b4df72b74c39a66f442ae61aebe1cdb96b660e3248dad3d05bfce3d8630902a565c3a7636220e0435679ce1c45367570dd08722ddfe7f1bf56c44bcab8ef2d0979eeaa569dade4ec34751833d455b31b55edcb9b64f3045725fcd3a08ce0c20b09a437133df5738092eba91430208814b4135b0a64331aff1847ca60426c91e96a029cff039b14462da6e5f9c545980b3712f7fa5f3958d92278194cf6b37ef76e91103d14db403956a7070d87afa81df227f2189926e1265a2872e9d64c64496083caff36dd3c27e961957acb86f0f9a3cbb5ddbb6bf9c62dc102d70d62eea969b1c2c5f42823f76827e918ffa77cc12ca8d31effd0b55529c496da762b6a95d43360ea4e811979ee316e143733f886a6eca5ac76746d4a302ec57b6b4af57c25631d7773243abd400d15274703154dfde2f1a63e075e4b22ed4516dd1496e3f7848bbf19e3215edda64140649d9b1a06975773d5dd0ca9c4bdfd5eb9fb6164aa659e2a8415098dd05496d0b2a20d966a4c9efefa964e007a3b731d3bad501fd21ca564c6155d893c3075c234af6378a12595d8a88ae0518350b75d57fb91b7610bfc3168f548a9a63432b49a9dbee2ee1a4ddd80255e2c655cc80d59d7e90e21fb090db6d59ef84c0becfda6bd01c5a806ce67bea77fdba62ba40e2114d31e6087ad67b28adc20d7cabe7911aa2db119cf5f43b2011bb92556e8e303a264f813764027fbec36f8248a667c766cfc12c80d96965f222d39b5f58a54b255d3b1eb4530952b6d251ff1f9a2cbc585d539704c8ea6884699ebc95d57cd1daef169da86cc10fe7300352e939c35bbe3104aea1b1c681f3e98be8fad7c91bb56724ffa794ea4ac7c4d51d4aad8e94087b4cdcab897e70558e6648ab42dfadab447735912af011fdbd9a47a4958b953b01d2e274449854cb7d4b44d88fb2db162b8dd664c7c32858c7714c69b838cb30b17e6a42ca760256c4c6da57ad5be955ca8c787262d8bd3f4a5f0170e70f92ee2ec9d227d066e41d0d4b640166b2f6937a66bc84506d102d3edac818b246954ba200a3057820da10b64ff99f016b42d90a29b43290d731ef23a72612d646f92acc05620068fd94edd12902197733cc9dbb55d95930ccc749c4a169b4b7056dba24f767da022eb01243353e1f4d0af2eb32e3feb331283ceab3e0112b37556749a701d11ada5cbe1b4c829fac46e12612679e47d4a066be939b886f0fdc2b4c5b4dd183ca025c5191ac67d7f992643333504da30e8300a0b40152671", 0xf12}], 0x4)
r3 = openat$bpf(0xffffffffffffff9c, 0x0, 0x2, 0x0)
ioctl$BIOCSETWF(r3, 0x80104277, &(0x7f0000000580)={0x0, 0x0})
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, 0x0)
r4 = socket(0x18, 0x3, 0x0)
setsockopt(r4, 0x4, 0x0, &(0x7f0000000040), 0x0)
close(r4)
getsockname$inet(0xffffffffffffffff, &(0x7f00000000c0), &(0x7f0000000000)=0xc)
r5 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$VNDIOCCLR(r5, 0x80384601, &(0x7f0000000040)={&(0x7f0000000180)='./file0\x00', 0x4, &(0x7f00000001c0)='./file0\x00', 0x8})
r6 = dup(0xffffffffffffffff)
setsockopt$inet_opts(r6, 0x0, 0x13, &(0x7f0000000040), 0x0)
ktrace(0x0, 0x4, 0x0, 0x0)
r7 = open$dir(0x0, 0xa00, 0x0)
mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x0, 0x810, r7, 0x0)
r8 = open$dir(&(0x7f0000000380)='./file0\x00', 0x0, 0x0)
ftruncate(r8, 0x91a1)
syz_open_pts()
writev(0xffffffffffffffff, 0x0, 0x0)
mkdir(0x0, 0x0)
socket$inet6(0x18, 0x3, 0x0)
setsockopt$inet6_MRT6_ADD_MIF(r6, 0x3a, 0x66, 0x0, 0x25)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f00000001c0)=[{0x81}, {0x1c}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000180), 0x1, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(r0, 0x80085762, &(0x7f0000000400)={0x3})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000000)=[{0x15, 0x0, 0x0, 0x4000}, {0x14}, {0x40e}]})
syz_emit_ethernet(0xe, &(0x7f0000000100)=ANY=[])


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
dup(r0)
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
sysctl$net_inet_divert(&(0x7f0000000100), 0xb, &(0x7f0000000280)="a7c1290f17722447b2c63e743f6b379fa5267a394a5d94db9417b6982f519b111f61ad994119ba843799517c2ddf4c65594fb3b55a5fce717f619f904ce7b41e4296cf777a1db4747703440100000023e48310b779f9619c7642d6d7f500000000000000000000000000000000c37a11ae4dbe56deeb1ccae6d8e73f8976b460abc78bfdf1bf11c3ec2956f559e2ae95b19752a20f358e90edd96264cbc18906750f34e7e595d09e4e313414f688d6388b713904a7996cc92a328db185299eeabc8e35147498451c4a84a9d41bf693affdc27f4569379570f4", &(0x7f0000000180)=0x67, &(0x7f0000000640)="e2714be05c6a432bfcb43ba70e2bb9e6add925cf34d00e465191e199efee4898bfe502dcc0a3e3fd0cc0e7969055dcb470ddd2f263dfb8065cbf63d41b2a29e4f92695a2dae1e619ba2b0ccd1e605cd2827beb6ddaf6b579cccebb6d267a74d6af9f2cddd1eb38180245caf3e0f240c5f1ee52a05a63c446df6149316cc2e17b775698e9114250d85ec893fbd204889e5c3f37ee5894227fa7b36a2803d9c558953caa2452fff1bf82f49299d2fd07d8a464fd351d966782d21806ba5be9dc66d7dd572cdae3822888010771550dd55b3014876e2537e33b838b12b10d843be49e4cfc3b3f04a60088dd3cc3fbdc16864e028753d898f0bc0bd6e20f96274d743755332aebcec91d4f490000000000000000628c7c526f7de4f21b6260bacfe436d6eb63a96ded0b0f29cbc8ea2a7d2760b1fdf551506810d63132c72c14be5ffcc53ca339aea237797e863010f33b057982b6825dbdef1ce4425ae7d1234ad5cb69", 0xee)
open(&(0x7f00000002c0)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
link(0x0, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000000040)=ANY=[@ANYBLOB="aaaaaaaaaaaaffffffffffff86dd600625200000000000000000000000000100ffffac1400d0fe"])
r1 = socket(0x18, 0x1, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000000029, 0x8, &(0x7f0000000100)="54db0b54854d9a37275631fa6e64174e78402377241f3b2ed58c7bda91f1bb6545d47631dff7e76aa265a2f8843b8ce1456e3fb26125a455bacf5bd48c8d7bae6cf710c023b177094b91f32433bbacecd6613f1005d2fb896d2b5266906e9b8c5c1a418c4d72195cfcda996f6f5dce220916634c6dbdefed7290ee704452", 0x7e)
setsockopt(r1, 0x1000000000029, 0xa, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x3e}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)
openat$speaker(0xffffffffffffff9c, 0x0, 0x2, 0x0)
syz_emit_ethernet(0x12, &(0x7f00000002c0)={@local, @local, [{}], {@generic={0x88a8}}})
msgrcv(0x0, 0x0, 0x0, 0x0, 0x0)
r2 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmat(r2, &(0x7f0000001000/0x3000)=nil, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {&(0x7f0000ff9000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffd000/0x1000)=nil, 0x80000001}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f0000ffc000/0x1000)=nil}, {&(0x7f0000003000/0x2000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x2000)=nil}], './file0\x00'})
sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000000)="9b1809ffffffffffffff7f473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6fd74c94d1b44", &(0x7f0000000040)=0x10011, 0x0, 0x0)


r0 = syz_open_pts()
syz_open_pts()
syz_open_pts()
ftruncate(r0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x802, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x80}, {0x30}, {0x6, 0x0, 0x0, 0xfffffffe}]})
write(r0, &(0x7f0000000500)="762bdead0f01f864cb36347f538f", 0xe)


openat$speaker(0xffffffffffffff9c, 0x0, 0x2, 0x0)
r0 = socket(0x2, 0x0, 0x9)
r1 = socket(0x18, 0x1, 0x0)
getsockname(r0, &(0x7f0000000240)=@un=@file={0x0, ""/4090}, &(0x7f00000000c0)=0xffc)
sysctl$kern(&(0x7f0000004e40)={0x1, 0x32}, 0x2, 0x0, &(0x7f0000004f00), &(0x7f0000004f40), 0x0)
setreuid(0xee00, 0x0)
chmod(0x0, 0x33)
r2 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r3 = dup(r2)
faccessat(r3, &(0x7f0000000040)='./file0\x00', 0x2, 0x0)
dup2(r1, r0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
sysctl$hw(&(0x7f0000000000)={0x6, 0xb}, 0x2, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
getppid()
getuid()
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000025c0), 0x0)
openat$speaker(0xffffffffffffff9c, &(0x7f0000002640), 0x40, 0x0)
getpid()
setreuid(0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x2, 0x0, 0x20}, 0x4, 0x0, 0x0, &(0x7f0000000100), 0x4)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000100)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmsg(r0, &(0x7f0000000300)={0x0, 0x0, &(0x7f0000000000)=[{&(0x7f0000000180)=""/106, 0x6a}], 0x1, 0x0}, 0x842)
sendmsg$unix(r1, &(0x7f0000000680)={0x0, 0x0, &(0x7f0000000140)=[{&(0x7f0000000480)="caaa3bb9d7758cdaa226a1fa90bbb8629a3e50e780cd61024b2f2071abf1489df55657049c708de674027c7648d91845892437ff4ee83accb49fe9301ef25695a46a138c094b8de1353f", 0x4a}, {&(0x7f0000000040)="a0f6415cde912ca699ece0c7dcc3f37938614a253f1e270e0eb70e0ae62382", 0x1f}, {&(0x7f0000000340)="95", 0x1}], 0x3}, 0x0)
socket(0x0, 0x0, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0xee00, r0)
r1 = socket(0x1, 0x1, 0x0)
ioctl$FIONREAD(r1, 0x8020697f, &(0x7f00000001c0))


fchdir(0xffffffffffffffff)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
r0 = socket(0x11, 0x3, 0x0)
listen(0xffffffffffffffff, 0x0)
sendto$unix(r0, &(0x7f00000023c0)="b1000501600000000000000007000000331c13fecea10500fefd6ecfc72fd3357ae320b37b673039d2d236acf20b7804be64174991f7c8cf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139b672f4d335d323e7d026ba8af63003728211e0000d4500fd38bfbbf70c1f5a872c881ea6e69e0bb76d907c400000200361b1257aea8c500002002fb001ff1edc7ea24551761d12767e371a3f83437120557adb71d89e000040781e4b2fff840ff00", 0xb1, 0x0, 0x0, 0x0)


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(0x0, 0x0)
setreuid(0xee00, 0x0)
sysctl$net_inet_ip(&(0x7f00000000c0)={0x4, 0x2, 0x0, 0x18}, 0x4, 0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000000)={0x1, &(0x7f0000000080)=[{0x15, 0x0, 0x0, 0x4}]})
write(r1, &(0x7f0000000180)="c5449bc1708e16b9805a099e20a0", 0xe)
sysctl$net_inet_ip(&(0x7f00000002c0)={0x4, 0x2, 0x0, 0x6}, 0x4, &(0x7f0000000340)="64b905872de171cc8d6e5bb97c4c6002d9c40850e971cc18953cdf", &(0x7f0000000380)=0x1b, &(0x7f00000003c0)="388a5b2f91996c80f6e9124cf39c6efd2f7facfa72aaa6d7eaea2bf900b7cdac8f3b5f22c7cfdd949b71a97ef07408ee9f6d90e91f929af3a122980ab09a2e6d21834b5b2dfee7454eac9c326ec5a312e1c4ff457eb57eef8598882ac62e9ecd84674ee5d984eeffddfaae9d01309b4fc53f47aa0bb5ed1ff29faa191cdbc24a0213640e194dc02f53d46be8677e0813c8053b03d43e657d713a755e2dd4c616f825bb3095f02bffac08fd52d43cb2d6190d95173cd66fb02f5dcefb73191dc0beccd1638214ec47f4d3eff66efcf76fe60d", 0xd2)
mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x1e5f)
r2 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
ioctl$VNDIOCSET(r2, 0xc0384600, &(0x7f00000001c0)={0x0, 0x0, 0x0})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000580), &(0x7f0000000140)=0xc)
mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0xc0e99db6de761f86, 0x0)
rename(&(0x7f00000007c0)='./file0\x00', &(0x7f0000001040)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
accept$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ff7000/0x3000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000604000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000691000/0x2000)=nil, &(0x7f0000ff8000/0x4000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil}], './file0\x00'})
sysctl$net_inet_tcp(&(0x7f0000000180)={0x4, 0x11, 0x4}, 0x3, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000ff3000/0x2000)=nil, 0x2000, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
r3 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
setsockopt$inet_opts(r3, 0x0, 0x9, &(0x7f0000000080), 0x0)
writev(0xffffffffffffffff, &(0x7f0000000000)=[{&(0x7f00000017c0)}], 0x1)
writev(0xffffffffffffffff, &(0x7f0000000300)=[{&(0x7f0000000140)="f005c71031c1c5f421277b09000000000000007a091a2f47be787538ec7a89ec5ed66daa731ddc384ecc690869a0aa2266affdf772d7a360ee0f15fa664f557bb45071fe9b6d9d28e6e2589000f6a64f370b9e336987d77b38f7aada5309e46a81e0e2efa087aa9f5f89934fdbd2ed96e7234b8972b273e810ca9962a8f461d3a05711a63027321ff62c", 0x8a}], 0x1)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r4=>0xffffffffffffffff})
ioctl$FIONREAD(r4, 0xc0106924, &(0x7f00000001c0))


openat$zero(0xffffffffffffff9c, &(0x7f0000000980), 0xe8, 0x0)
ioctl$KDSETLED(0xffffffffffffffff, 0x20004b42, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x1ff, 0x0, {0x0, 0x1}})
ioctl$FIONREAD(0xffffffffffffffff, 0x802069c7, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
r0 = socket(0x18, 0x4002, 0x0)
r1 = dup(r0)
setsockopt(r1, 0x1000000000029, 0xc, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x0, 0x0})
socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, &(0x7f00000001c0))
ioctl$FIONREAD(0xffffffffffffffff, 0xc1206951, &(0x7f0000000100))
ktrace(&(0x7f0000000100)='./file1\x00', 0x1, 0x104, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x0)
open(0x0, 0x0, 0x0)
poll(0x0, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
mknod(0x0, 0x0, 0x0)
r2 = socket(0x18, 0x1, 0x0)
setsockopt(r2, 0x1000000029, 0xc, &(0x7f0000002a80)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r2, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000480), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000140)=[{0x44}, {}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])


r0 = socket(0x18, 0x2, 0x0)
getsockopt(r0, 0x29, 0xc, 0x0, 0x0)


r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r0, 0x80085761, &(0x7f00000000c0)={0x3})
ioctl$WSMUXIO_LIST_DEVICES(r0, 0xc1045763, &(0x7f0000000440)={0x0, [{0x1, 0x1f}, {0x1, 0x4}, {0x2, 0x1000}, {0x1, 0x3}, {0x1, 0x210001}, {0x1, 0x6f}, {0x3, 0x401}, {0x1, 0x1}, {0x1, 0x4}, {0x1, 0x400}, {0x2, 0x200}, {0x2, 0x6d}, {0x3, 0x400000}, {0x2, 0x2}, {0x2, 0x1}, {0x2, 0x7ff}, {0x2, 0xf7}, {0x2, 0x2}, {0x2, 0xff}, {0x3, 0x8}, {0x2, 0x81}, {0x3, 0x699d}, {0x2, 0x5}, {0x1, 0xffff960d}, {0x1, 0x401}, {0x3, 0x5}, {0x1, 0x800009}, {0x0, 0x1}, {0x3, 0x8}, {0x0, 0x5f}, {}, {0x1, 0x7}]})
r1 = syz_open_pts()
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001280)={0x0, 0x0, 0x0}, 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
sysctl$kern(&(0x7f0000000040)={0x1, 0x32}, 0x2, 0x0, 0x0, &(0x7f0000001440)="cca410df", 0x4)
writev(r1, &(0x7f0000001c00)=[{0x0}, {&(0x7f0000000180)}, {0x0}, {&(0x7f0000001880)="a1180719c77651b431827ef2e2a33c8ccec2618f56654cb97bec8f1dc9980f66c7424f4890a37eb9afba1cc163f990ecd783625d6a7d30eec7995ba3749e70bc20ba9cfcd43e24c6ba12fce0378554fbbc80c585035c7ba69d03e2de510cb4fa84c59c8513609802ac395cd286344f5ce66eeab2a8c3d0bf610d990ee6760019b832f4f7bf5ba8214ff020bd25da40dbf04ab1b03753de6beff6e8ab80c2eecad508bee4ce0e0432e26a1dd9d5bd5a38aa82c27acdbcea48393635", 0xbb}, {&(0x7f0000001cc0)="93d92f66aeff6385debdef67fe6422704d2115e7c53ffe58afc6b99ed2d42e7e6f52c03606ca6308af3c4fbc8c8d9898ff7f4e9bd3a5a0e1a20ec3b3242cd22f0437e05d5b66bb86f5c54deff6975cc9e54e6cfd5ef09fa5c1a5f2fc6b96740ec92de045fd924ea8f481e8dfc115f4f3897d2f7114cdf127a5cea920ecba98bbe7d10ec2478a92306efa8f830c135bb1ef1dff3858faca6980dc78f626a336420542deb69eb10507391a9cc213a63fe00727fbba2ab43a3fbccb41705bd9f66a5c7bd025b71f6318b330ccc138b6134418bcfdd218b3eb13933a0521713ef8bf8291f808070fdf676a9e0708134d2527c4d6d93e23cfc735ad6e2137c4c63a83ccecba61f833", 0x106}, {&(0x7f0000001a40)}, {&(0x7f0000001b00)="071ed203bbc0624c2f0896555ffca9e7c265203a8126367c626c9135065120711b1db15ff6e9084672cfd4053f46f41752c1b5062be0dc3e4f47ce694b02bb58b9f96c865d31bfd3865734fe3382229d93067bc92865ac558401387699ceed4398cf142b4d7ff2cbd39438d567313c1d82538d9eb34249e6177552b807af33a676d041e5ae0ed5d57d632ab3d79e22f96cd0ed78a79ce12df1acd2c3f545414765e1b313b0f5cba87d065bfb7f375919c110086ec0b578c4eb63cff94d3a44c21522d1d40fb9050b7c1baf3a92d12cb5e981", 0xd2}], 0x7)
syz_open_pts()
syz_open_pts()
fchown(0xffffffffffffffff, 0x0, 0x0)
open(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])


close(0xffffffffffffffff)
r0 = syz_open_pts()
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)


syz_emit_ethernet(0xe, &(0x7f00000006c0)={@local, @random="632ce495778b", [], {@generic={0x8864}}})


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
dup(r0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
mknod(0x0, 0x0, 0x6381)
openat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x8, 0x4)
r1 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f00000000c0), 0x40, 0x0)
close(r1)


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ioctl$FIOSETOWN(r0, 0x8004667c, &(0x7f0000000100))


r0 = socket(0x18, 0x2, 0x0)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x33, 0x0, 0x0)


open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
r0 = getpid()
ktrace(&(0x7f00000001c0)='./file0\x00', 0x0, 0x40000534, r0)
sysctl$net_inet_tcp(0x0, 0x0, &(0x7f00000000c0)="9b1809c3dd7d3f", 0x0, 0x0, 0x0)
r1 = socket(0x2, 0x2, 0x0)
r2 = socket(0x2, 0x400000000002, 0x0)
r3 = dup2(r2, r1)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r4 = socket(0x2, 0x2, 0x0)
connect$unix(r4, &(0x7f0000000000), 0x10)
bind(r1, &(0x7f0000000000), 0x10)
write(r4, 0x0, 0x0)
recvmmsg(r3, &(0x7f00000000c0)={0x0}, 0xfffffdfb, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000080)=[{0x4d}, {0x84}, {0x8106}]})
syz_emit_ethernet(0x3e, &(0x7f0000000000)=ANY=[])


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r1=>0xffffffffffffffff})
recvmmsg(r1, &(0x7f0000000480)={0x0}, 0x10, 0x0, &(0x7f0000000500)={0x2007fffc, 0xa})
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x0, 0x10, r0, 0x0)
msync(&(0x7f000000b000/0x1000)=nil, 0x1000, 0x4)


syz_open_pts()
pipe(&(0x7f0000000840)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
r2 = socket(0x800000018, 0x3, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r3, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0xc0}, {0x3d}, {0x16}]})
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x4000007, 0x4)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x120}})
bind$unix(r1, &(0x7f0000000180)=@abs={0x1, 0x7, 0x1}, 0x8)
syz_emit_ethernet(0x12a, &(0x7f00000005c0)=ANY=[@ANYRESDEC=r0, @ANYBLOB="4554fff8aa6c925b28d0675dd2ad717f5ec0a97c53068f69259e4d84f1db00bc1165ff577e07ae84c20fafe5cf39e6af7454592549a49772a74e6fb1e14a5c9be1946ecf16b701416c5c2717e4529b7812ceea40c4c4b1e603f32272ba784819b761dd08fd93bc81a02e791894c90234ecb7250e94d5e847b4574d81e1e0bb4b3abe017dad23a7a6cbd6543529fde1d528100310a2ba118d307abadd4e8096257ec7914dcf1b6083a7ef5148ba5c5b4079450bb324e5ce4cedd238ce387c53e5afee"])
readv(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000002140)=""/4112, 0x1000}, {&(0x7f0000001140)=""/4092, 0x1000}], 0x1000000000000037)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000380)={<r4=>0xffffffffffffffff})
ioctl$FIONREAD(r4, 0x8020690c, &(0x7f00000001c0))


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x1, &(0x7f0000000080)=[{0x8a}]})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x1, &(0x7f0000000100)=[{}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
mkdir(&(0x7f0000000080)='./file0\x00', 0xaf)
r0 = open(&(0x7f0000000180)='./file0\x00', 0x200, 0x0)
getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000424, 0x0)
getpid()
r1 = socket(0x11, 0x3, 0x0)
sendto$unix(r1, &(0x7f0000000100)="b10005016000009f0000000000070000001c130500000000fef96ecfc72fd3357ae380b37b673039d2d236acf60b7804be78164991f7c8e750882b297be1aa5b23edeb51e2f0ac3ebbc215000000eeffffff028ea8af630037", 0x59, 0x0, 0x0, 0x0)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000000c0), &(0x7f00000001c0)=0xc)
mknod(&(0x7f0000000000)='./bus\x00', 0x2000, 0x2cff)
open(&(0x7f0000000340)='./bus\x00', 0x20000, 0x60)
mprotect(&(0x7f0000521000/0x1000)=nil, 0x1000, 0x2)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
socket(0x18, 0x3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000200)={0x0, &(0x7f0000000040)})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11, 0x0, 0x57}, 0x4, 0x0, 0x0, 0x0, 0xfffffffffffffe64)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r2 = msgget$private(0x0, 0x74d)
msgrcv(r2, 0x0, 0x1008, 0x0, 0x0)
msgctl$IPC_RMID(r2, 0x0)


sysctl$net_inet_icmp(&(0x7f0000000200)={0x4, 0x12}, 0x3, &(0x7f0000000280)="32d55286f3dccac0ce7240cd7d1b97d95c8f29197646f5caa2bc630100000093f57e8ffd9e57bb", 0x0, 0x0, 0x0)


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
sysctl$net_inet_carp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x3}, 0x4, 0x0, 0x0, &(0x7f00000010c0)="00040000", 0x4)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000132000/0x3000)=nil, &(0x7f00000a0000/0x1000)=nil, 0x80400000}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f000008c000/0x2000)=nil, &(0x7f00001f0000/0x1000)=nil}, {&(0x7f00001f0000/0x1000)=nil, &(0x7f0000001000/0x1000)=nil}, {&(0x7f0000132000/0x4000)=nil, &(0x7f00000b2000/0x1000)=nil}, {&(0x7f000008a000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {0x0, &(0x7f000002a000/0x3000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000086000/0x3000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil}, {&(0x7f0000091000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000001000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000132000/0x1000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000008a000/0x1000)=nil}, {0x0, &(0x7f0000092000/0x3000)=nil}], './file0\x00'})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000040)="fd", 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$VMM_IOC_RUN(r0, 0xc2585601, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, 0x0})


semget(0x2, 0x0, 0x0)
open$dir(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105727, &(0x7f0000000000)={&(0x7f00000003c0)=[{}, {}, {}], 0x3})
sysctl$kern(&(0x7f0000000000)={0x1, 0x45}, 0x3, 0x0, 0x0, &(0x7f0000000040)="3944eb3f115f79037148fa0ddc3adf427d080000006ceb99ea265a4a19b2e72fd9cbb4db32e128db447c5e01000080d5fa1d9213ebefff7ad23b886bf325280bc040eac897a0d4168da6b6b75d146499e1ee9ddeb2d68e8d011a", 0x5a)
open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x7, 0x0, 0x0, &(0x7f0000000100)={0x6, 0x7fffffff})
r0 = kqueue()
kevent(r0, &(0x7f00000000c0), 0x30, 0x0, 0x457d, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
utimes(&(0x7f0000000080)='./file0\x00', &(0x7f0000000100))
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x1, &(0x7f00000001c0)=[{0x48}]})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
semget(0x2, 0x0, 0x200)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r2 = socket(0x18, 0x3, 0x3a)
setsockopt(r2, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r2, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x1}, 0xc)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x34}, 0x4, &(0x7f0000000080), 0x0, 0x0, 0x0)
setrlimit(0x0, &(0x7f00000000c0)={0x3f, 0x5})
socket$inet(0x2, 0x3, 0x0)
r3 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x200000000000c, &(0x7f0000000480)="eaef125c00000000", 0x8)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
sysctl$net_pipex(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
symlinkat(0x0, 0xffffffffffffffff, &(0x7f0000001940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x0, 0x9, &(0x7f0000000040)="03000000", 0x4)
setsockopt(r1, 0x1000000000029, 0xa, &(0x7f0000001980), 0x4)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
mkdir(&(0x7f0000000000)='./file0\x00', 0x100)


open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r0)
setgroups(0x0, 0x0)
ktrace(&(0x7f0000000180)='./file0\x00', 0x4, 0x1024, r0)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f00000000c0)="b1000502000000000000000007000000330002000000000000f96ecfc72fd3357ae320b37b673039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa5b236de351e2f0ac3ebbc257699a5f139b672f4d335d223e7d026ba8af630037382102000000720fd38bfbb770c1f5a8727781ea2e69e0bb76d907c400000000361b1257aea8c500002002fbff0c230000aabfba09000007000000a304353712051eadb71d89e000040781e4b2ffff130000", 0xb1, 0x0, 0x0, 0x0)
recvmmsg(r0, &(0x7f0000000500)={0x0}, 0x10, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000200)=[{0x0}], 0x1)
sysctl$vm(&(0x7f0000000200)={0x4, 0x1}, 0x3, &(0x7f0000000240), 0x0, 0x0, 0x32)
r2 = socket(0x11, 0x3, 0x0)
sendto$unix(r2, &(0x7f00000001c0)="b1000504", 0x4, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000340)={0x3, &(0x7f0000000080)=[{0x64}, {0x4}, {0x6, 0x0, 0x0, 0xfffffc00}]})
writev(r1, &(0x7f0000000980)=[{&(0x7f0000000380)="80ecd993af8e500876c3890067a5", 0xe}], 0x1)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000180)=[{0x28}, {0xc}, {0x6, 0x0, 0x0, 0x1000}]})
pwrite(r0, &(0x7f0000000140)="a1a5537ea29fb8c6386c0d25c172", 0xe, 0x0)
semctl$SETALL(0x0, 0x0, 0x9, 0x0)
semop(0x0, 0x0, 0x0)
semctl$GETALL(0x0, 0x0, 0x6, 0x0)
semop(0x0, 0x0, 0x0)
semget(0x0, 0x2, 0x624)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000001180)={0x3, &(0x7f0000000040)=[{0x5c}, {0x48}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f0000000040)=0xfffffbfc)
writev(r0, &(0x7f0000001b00)=[{0x0}], 0x1)
writev(r0, &(0x7f0000000280)=[{0x0}], 0x1)
write(r0, 0x0, 0x0)
readv(r1, &(0x7f0000000640)=[{&(0x7f0000000600)=""/9, 0x9}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
fchflags(r0, 0x0)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x102}})
sysctl$hw(&(0x7f0000000000)={0x4, 0x18}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x1)
sysctl$vfs_nfs(&(0x7f0000000000), 0x7, &(0x7f00000025c0), 0x0, 0x0, 0xffffffffffffff2d)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd01)
open(&(0x7f0000000040)='./bus\x00', 0xcd0, 0x0)
getsockname$inet(0xffffffffffffffff, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
getuid()
r0 = geteuid()
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x41, 0x0)
r1 = getpgid(0x0)
pipe2(&(0x7f0000000080)={<r2=>0xffffffffffffffff}, 0x4)
r3 = semget$private(0x0, 0x4000000009, 0x82)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000380)={{0x7fffffff, r0, 0x0, 0x0, 0x0, 0x44, 0x7fc}, 0x80000000, 0x3, r1, r1, 0x7, 0x26c3, 0x1009, 0x2})
semop(r3, &(0x7f00000002c0)=[{0x3, 0xbf4e, 0x1800}, {0x2, 0x1f}, {0x1, 0x4, 0x1800}, {0x4, 0xe5f1}, {0x0, 0xffd, 0x1000}, {0x4, 0x53, 0x1000}, {0x2, 0x2, 0x1000}, {0x2, 0x0, 0x800}, {0x2, 0xfffd}, {0x0, 0x9, 0x1800}], 0xa)
semop(r3, &(0x7f0000000440)=[{0x3, 0x0, 0x1c00}, {0x2, 0x95}, {0x0, 0x3ff, 0x400}, {0x0, 0xb10, 0x1800}], 0x4)
semctl$SETALL(r3, 0x0, 0x9, &(0x7f0000000040))
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000280)={<r4=>0x0, <r5=>0x0}, 0xc)
getpgid(0xffffffffffffffff)
r6 = getgid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000140)={{0x4, r5, 0x0, 0x0, r6, 0x1, 0x8000}, 0x3fd, 0x2, r4, r1, 0x744, 0x3, 0xa, 0x2})
semctl$IPC_SET(r3, 0x0, 0x1, &(0x7f00000001c0)={{0x39c5, 0x0, 0x0, 0x0, r6, 0x5c, 0x101}, 0x40, 0x800, 0xff})
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000580)={0x0, 0x0, <r7=>0x0}, &(0x7f0000000240)=0xc)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f00000004c0)={<r8=>0x0}, 0xc)
shmctl$IPC_SET(0x0, 0x1, &(0x7f0000000500)={{0x1e, 0x0, r6, 0x0, r7, 0x0, 0x1}, 0x8, 0x4003, r8, 0x0, 0xfffffffffffffffc, 0x3, 0x81})
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000080)={<r9=>0x0}, &(0x7f0000000300)=0xc)
r10 = semget$private(0x0, 0x4000000009, 0x82)
semop(r10, &(0x7f00000000c0)=[{0x3, 0x837, 0xe5ce97ab354d96be}, {0x2, 0x3, 0x1800}, {0x0, 0x1, 0x1000}, {0x4, 0x2, 0xc00}], 0x4)
semop(r10, &(0x7f0000000440)=[{0x3}, {0x2, 0x94}, {0x0, 0x3ff, 0x400}, {0x0, 0x2a4, 0x800}], 0x4)
semctl$SETALL(r10, 0x0, 0x9, &(0x7f0000000040))
fcntl$setown(r2, 0x6, 0x0)
open$dir(&(0x7f0000000100)='./bus\x00', 0x0, 0x0)
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000005c0)={{0xe6, r0, 0x0, 0x0, r6, 0x1, 0x7ff}, 0x9, 0x8, 0x0, r9, 0x3f4, 0x3, 0x7, 0x9})


mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x40)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0xffffffff})
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
r0 = socket(0x0, 0x0, 0x0)
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, &(0x7f00000000c0)={&(0x7f0000000000)='./file0\x00', 0x0, 0x0})
ioctl$TIOCSETAF(0xffffffffffffffff, 0x802c7416, &(0x7f0000000200)={0x20, 0x8d96, 0x2, 0xe1b9, "3f7affef952ef7729bf744680b7b2c8eb81112c6", 0x9, 0x6})
getsockname$inet(r0, &(0x7f0000000080), &(0x7f0000000040)=0xc)
mquery(&(0x7f000059a000/0x3000)=nil, 0x3000, 0x1, 0x0, r0, 0x6)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = openat$klog(0xffffffffffffff9c, &(0x7f0000000100), 0x80, 0x0)
ioctl$LIOCSFD(r1, 0x80046c7f, &(0x7f0000000140)=r0)
r2 = socket(0x18, 0x3, 0x0)
r3 = socket(0x0, 0x2, 0x0)
r4 = dup2(r2, r3)
socketpair$unix(0x1, 0x5, 0x0, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f00000001c0)=@abs={0x1, 0x0, 0x1}, 0x8)
sendmsg$unix(r4, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)
getsockopt$sock_cred(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000500), &(0x7f0000000040)=0xc)
r5 = socket(0x2, 0x3, 0x0)
r6 = dup(r5)
getsockname(r6, 0x0, 0xffffffffffffffff)
accept$inet6(0xffffffffffffffff, &(0x7f0000000380), &(0x7f00000003c0)=0xc)
getsockopt(0xffffffffffffffff, 0x0, 0x16, 0x0, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f00000001c0)={&(0x7f0000000180)={0x0, 0x0, &(0x7f00000000c0)=[{&(0x7f0000000240)=""/222, 0xde}], 0x1, &(0x7f0000000100)=""/64, 0x40}}, 0x10, 0x1801, &(0x7f0000000340)={0x0, 0x200})


r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000440), 0x1, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
bind(r1, &(0x7f00000002c0), 0xa)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0115, './file0\x00'}, 0xa)
mkdir(&(0x7f0000000640)='./file0\x00', 0x0)
chmod(&(0x7f00000000c0)='./file0\x00', 0x21e)
chdir(&(0x7f0000000140)='./file0\x00')
symlink(&(0x7f0000000200)='./file2\x00', &(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
open(&(0x7f0000000180)='./file0\x00', 0x6d84b028b6b26ff2, 0x0)
r2 = semget$private(0x0, 0x7, 0x3c0)
semop(r2, &(0x7f0000000080), 0x0)
rename(&(0x7f0000000540)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000080)='./file0\x00')
semctl$GETPID(r2, 0x3, 0x4, &(0x7f0000000680)=""/8)
semop(r2, &(0x7f0000000280)=[{0x1, 0x7, 0x1000}], 0x1)
semop(r2, &(0x7f00000002c0)=[{0x4, 0x0, 0x1000}, {0x0, 0x420}, {0x1, 0x2}, {0x0, 0x3, 0x800}, {0x2, 0x204}, {0x0, 0x4}, {0x3, 0xfff8}, {0x2, 0x9}, {0x4, 0x1, 0x1000}, {0x2, 0x7e7}], 0xa)
r3 = socket(0x18, 0x2, 0x0)
setsockopt(r3, 0x1000000000029, 0xa, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
setsockopt(r3, 0x1000000000029, 0xa, &(0x7f0000000c40), 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000002540)={0x0, 0x0, 0x0}, 0x0)
r4 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000140), 0x1, 0x0)
ioctl$WSKBDIO_GETMAP(r4, 0x8010570e, &(0x7f00000001c0)={0x0, 0x0})
semop(r2, &(0x7f0000000100)=[{0x3, 0x801}, {0x2, 0x8}, {0x4, 0x1, 0x1800}, {0x3, 0x101}, {0x2, 0x3fd, 0x1800}, {0x0, 0xecb}], 0x6)
semctl$IPC_RMID(r2, 0x0, 0x0)
chmod(&(0x7f0000000440)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2)
getuid()
getpeername(r1, 0x0, &(0x7f0000000300))
fcntl$setstatus(r0, 0x4, 0x0)
clock_getres(0x7, 0x0)


syz_open_pts()
r0 = open(&(0x7f0000000280)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000028000/0x4000)=nil, 0x4000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
setsockopt$sock_linger(r0, 0xffff, 0x80, &(0x7f0000000080)={0x6, 0xafc0}, 0x8)
writev(0xffffffffffffffff, &(0x7f00000001c0)=[{&(0x7f00000003c0)}], 0x1)
open(0x0, 0x0, 0x0)
kqueue()
open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
lchown(&(0x7f0000000280)='./file0\x00', 0x0, 0x0)
acct(&(0x7f0000000180)='./file0\x00')


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r0, 0xc0205602, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x0, 0x0})


r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000100)=[{0xc0}, {0x74}, {0x86}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, 0x0)
r1 = socket$inet6(0x18, 0x3, 0x0)
getsockopt$sock_int(r1, 0xffff, 0x1008, 0x0, 0x0)
socket(0x2, 0x2, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x2, 0x0, &(0x7f0000000080), &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458b", 0x69)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x1}, {0x4c}, {0x16}]})
write(r2, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xfef3)
r3 = syz_open_pts()
ioctl$TIOCGFLAGS(r3, 0x4004745d, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
syz_emit_ethernet(0x4a, 0x0)
socket(0x0, 0x3, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x5cda)
ioctl$BIOCGBLEN(r2, 0x40044266, &(0x7f0000000200))
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r5 = socket(0x11, 0x3, 0x0)
sendto$unix(r5, &(0x7f00000000c0)="b1000504600000000000000007000000331c13fecea10500fef96ecfc72fd3357ae320b37b673039d2d236073705ae04be38164991f7c8cf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139b672f", 0x52, 0x2, 0x0, 0x0)
sysctl$hw(0x0, 0x0, &(0x7f0000000080)="1d6306b4eefe033a28a8c4804f12fd", 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f0000000000)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe2c63a56077123a276d3ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0xffffffffffffff7b}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
mkdirat(0xffffffffffffffff, &(0x7f0000000040)='./file0\x00', 0x0)


r0 = kqueue()
r1 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x200, 0x0)
kevent(r0, &(0x7f0000000040)=[{{r1}, 0xffffffffffffffff, 0xa1}], 0x8c4, 0x0, 0x0, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
kevent(r0, 0x0, 0x0, 0x0, 0x653, 0x0)


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
fcntl$getown(r0, 0x5)


kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x6, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206923, &(0x7f00000001c0))
getgid()
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{}, 0xffffffffffffffff})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(0xffffffffffffffff, 0x8040691a, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000001c0), &(0x7f0000000200)=0xfffffffffffffe50)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0206923, &(0x7f00000001c0))
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r2 = fcntl$dupfd(r1, 0x3, 0xffffffffffffffff)
ioctl$FIONREAD(r2, 0x8004745d, &(0x7f0000000200))
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206922, &(0x7f00000001c0))
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x8040691a, &(0x7f00000001c0))


mknod(&(0x7f0000000500)='./file0\x00', 0x1000, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000001c0)=[{}, {}, {0x6}]})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x80206910, &(0x7f00000001c0))
r2 = dup2(r0, r0)
ioctl$FIONREAD(r2, 0x8020699d, &(0x7f00000001c0))


setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f00000000c0)=[{0x81}, {0x81}, {0x812e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


open(&(0x7f0000000180)='./file0\x00', 0x80000000000206, 0x0)
r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000140), 0x782, 0x0)
r1 = getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r1})
pipe(&(0x7f00000001c0)={<r2=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r2, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r3 = fcntl$getown(r2, 0x5)
ktrace(&(0x7f0000000180)='./file0\x00', 0x0, 0xd30, 0x0)
ktrace(&(0x7f0000000680)='./file0\x00', 0x0, 0x28, r3)
r4 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r4, 0x0)
r5 = dup(r0)
ioctl$SPKRTUNE(r5, 0x20005302, &(0x7f0000000100))


setreuid(0x0, 0xee01)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000240)={0x3, &(0x7f00000000c0)=[{}, {0x1, 0x0, 0x0, 0x2}, {0x6, 0x0, 0x0, 0x8002}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0xff0a, 0x0, 0x37)


mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x200)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)


sysctl$net_inet_ip(&(0x7f0000000100), 0x4, 0x0, 0x0, 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0x0, 0xffffffbf, "a309000064070094f6ffff9e0000000000000020"})
readv(r1, &(0x7f0000000280)=[{&(0x7f0000000600)=""/131, 0x83}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000240)=[{0x4}, {0x25}, {0x6}]})
syz_emit_ethernet(0x1019, &(0x7f0000000400)=ANY=[])


madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
sendmmsg(r0, &(0x7f0000000000)={&(0x7f0000000f80)={0x0, 0x0, 0x0, 0x0, 0x0}, 0xb5}, 0x1, 0x0)


mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x205b9a)
r0 = getpgid(0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x0, r0})
r1 = open$dir(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
preadv(r1, &(0x7f0000000000), 0x1000000000000098, 0x0)
execve(0x0, 0x0, 0x0)


syz_emit_ethernet(0x3e, &(0x7f0000000040)=ANY=[@ANYBLOB="aaaaaaaaaaaaffffffffffff86dd606aa63f00082b00000000000000000000bb0000000000000004"])
socket(0x18, 0x2, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
socket(0x18, 0x3, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0x0, 0x0, 0x0, 0x40}], 0x0, 0x0, 0x0, 0x0)
r0 = socket(0x800000018, 0x2, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0xfffffffffffffffe, 0x0, 0x0, 0x0, 0xff}], 0x0, 0x0, 0x0, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{}], 0xfffffffe, 0x0, 0x0, 0x0)
r1 = socket(0x18, 0x2, 0x0)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
socket(0x6, 0x4000, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x400, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
syz_emit_ethernet(0x17a, &(0x7f00000001c0)=ANY=[@ANYBLOB="00000000000000051ab5b60000100000004e95003f9a00000000"])
r3 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x100, 0x0)
r5 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x10215, 0x0)
ioctl$VNDIOCSET(r5, 0x81946467, &(0x7f0000000180)={0x0, 0x0, 0x0})
ioctl$VNDIOCGET(r5, 0xc4104603, &(0x7f00000002c0)={'./file0\x00', 0x5, 0x80, 0x7fff})
ioctl$BIOCSETWF(r4, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x85, 0x4, 0x20, 0x5}, {0x8, 0xf, 0x1b, 0x5}, {0x40, 0x2, 0x1, 0xaa}]})
readv(r3, &(0x7f0000000280)=[{&(0x7f0000000140)=""/156, 0xfffffdf1}], 0x1)


r0 = syz_open_pts()
kevent(0xffffffffffffffff, &(0x7f0000000640)=[{{r0}, 0xfffffffffffffffe, 0x3f}], 0x0, 0x0, 0x0, 0x0)
syz_open_pts()
r1 = syz_open_pts()
r2 = kqueue()
kevent(r2, &(0x7f0000000000), 0x723, 0x0, 0xd1c, 0x0)
dup2(r1, r2)


setrlimit(0x0, 0x0)
syz_open_pts()
close(0xffffffffffffffff)
msgctl$IPC_SET(0x0, 0x1, 0x0)
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f0000000080), &(0x7f0000000000)=0xfffffffffffffe22)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x800000018, 0x2, 0x0)
bind$unix(r1, &(0x7f0000000080)=@abs={0x0, 0x7}, 0x1c)
r2 = open$dir(&(0x7f0000000000)='./file0\x00', 0x8028ca56d081abe6, 0x0)
mprotect(&(0x7f0000359000/0x1000)=nil, 0x1000, 0x1)
r3 = socket(0x2, 0x3, 0x0)
r4 = dup(r2)
r5 = dup2(r4, r3)
write(r5, &(0x7f0000000180)="7f", 0x1)
pwritev(r2, &(0x7f0000000900)=[{&(0x7f0000000440)="d5", 0x1}], 0x1, 0x80000)
ioctl$WSDISPLAYIO_GBURNER(0xffffffffffffffff, 0x400c5752, &(0x7f0000000040))


r0 = socket(0x11, 0x3, 0x0)
connect$inet(r0, &(0x7f0000000040)={0x2, 0x3}, 0xc)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000001140), 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r1, 0xc2585601, &(0x7f0000001180)={0xdead4110, 0x0, [{&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffa000/0x2000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffa000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff9000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000ff9000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}], '.\x00'})


mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x6384)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x6381)
r0 = open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000140)='./bus\x00', 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r0, 0xc2585601, &(0x7f0000000240)={0x10, 0x0, [{&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffa000/0x4000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000fa6000/0x4000)=nil}, {&(0x7f000088c000/0x3000)=nil, &(0x7f0000ff9000/0x2000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ffc000/0x1000)=nil}, {&(0x7f0000ff9000/0x2000)=nil, &(0x7f0000c23000/0x3000)=nil}, {&(0x7f0000400000/0xc00000)=nil, &(0x7f0000677000/0x2000)=nil}, {&(0x7f0000881000/0x2000)=nil, &(0x7f0000b7d000/0x3000)=nil}, {&(0x7f00007e1000/0x3000)=nil, &(0x7f0000ff9000/0x4000)=nil}], './file0\x00'})


socket$inet(0x2, 0x1, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
socket(0x11, 0x3, 0x0)
r0 = socket(0x11, 0x3, 0x0)
r1 = socket(0x11, 0x3, 0x0)
dup2(r1, r0)
sysctl$vfs_nfs(&(0x7f0000000040)={0x7, 0x4}, 0x3, 0x0, 0x0, 0x0, 0x0)
connect$unix(r0, &(0x7f0000000000)=@file={0x0, '\x00'}, 0x3)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)


syz_emit_ethernet(0x416, &(0x7f0000000300)={@random="c7e052ea36fb", @broadcast, [], {@ipv6={0x86dd, {0x0, 0x6, "826e03", 0x3e0, 0x0, 0x0, @rand_addr="00000000000000000e14fc11cd3f6420", @mcast2, {[], @icmpv6=@ndisc_redir={0x89, 0x0, 0x0, '\x00', @mcast1, @ipv4={'\x00', '\xff\xff', @multicast1}, [{0x18, 0x6, "15bd7b6947fadae9d755ecfe59049c5e0e7cde530fd1de6b16d39a4266c7bc6116d31145454f733e8e0f085dbb0e0b6b5d967b"}, {0x0, 0x11, "df1df3ba48b6a1dfc04f9d6e87f8a4d6fe57aadd7e60336f89dc8dda530ad8c39b7cb4f935b737a2e4536f55d42043399dcad4f52b7a5d7ffc5a13bb8cd94c23c17b8945251b67dac433546f1b2dd30ea4abad00dabb53a52d7d7d4e945d51feca0cd9ed0fb0b83ea3bbe277da0c5ea9f3d14ad104a88fe58e84138c9768dd21f7a6787b3b65"}, {0x0, 0x17, "6c1a28322ee05dc0c88ab62b7d8a447daa952346bd53dba216271ce987fa745c8c14460acf70d21b8eeb733e8269778ea0968755bf2e154f4d44216055aa8f8532f878deadecd4b01d5ce8bb1fb3c781f60cb6aae91358398ad4285ece760cb736f2fa62e06f01ba17a5ac9dd54879bbf4b0587d2c546035b89f44119b51f1d6c5557e4300a69d60d5df61bdfcd5710d1606ea019d2ef7691ba3b00ab210c690ec3beac234d9ddca4f4c9ccea4b1db71c8423c5655e7531742f7c8"}, {0x2, 0x7, "c4adba067fc9f91b1998b9986fb1126182c5d663528aae6141af2b4ebeb8df28ea25f4e4b418c71752dc6909c1ba3c19533c5e304fcc83f8bce2"}, {0x5, 0x12, "c677aa917835bbb4fd125af9515834707e380e60cb0ec35a8bcb291cdbdc16a04aa5e0d6c0a009998b840edcd826f690d44f507909bdcb8ae73c6e45da12998de14d3911c8c78b6eb385d002c580793b4d94775190692eae4cbf5da2ec45775e58d2365fd083078977e438f62a05aba8d22a8b367413100d653d6cb88cf4b6258055f06a8e6bfbdc084d767bba8c09e8"}, {0x19, 0x13, "64668ebd5db97a4c56bca32c1fbdf39d165a97f7936de001b05fa9ad26b0cab0344365ce1e1918d0e131d0f4fe788916afb32acf3946c167dbac4baf0fb33710989840b56f4386724e08c48af7604619a79c1701c329542b34e8e5992689a8efa458364e5a7adcbbf712ece8eae8374fe2af72512aec60e7cdc57824ca7ee0789f122b75e032c0f1cc6736532ecab63bb9a1a0e0153677a701"}, {0x1f, 0x1a, "7a16c472659a88ddf0325f160281cc619001094aeb22de1fe5457bc44e346d488f91ab70f64f5db8f3c809293334ab695083053adcb8c6f7fe8ea3f2827e38948bd1be59d3e9a1d6df37b9802720b56f5b05beb041dae556fdddec142ce65e4a88895af77765ee958e29bdf8eabd7ac561d2e3b78d15cefb408ec62193948fedab10efd0441ffd55347c308514b873726707f9688140ef48f7b902f766f1f88b9985cb11892f4350434d55721f8e34ffa1ac0248d287437f4b7d5af5d418e8e737ff363cb40c38660d576b27d659c2c0e01e83"}]}}}}}})


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{}, {}, {0x5, 0x0, 0x0, 0x80000000}]})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x6, &(0x7f0000000080)="ae215599fed2fce97f573b9c553a0e622d29cd093849cd4fe42e0f5d2d06a4e744f0713d1fcaa1b8274dffd067d413ef9d2224d3fddc171f73a295b6ed18b3d0588be75e78a1d734e15bfe", 0x0, 0x0, 0xfffffffffffffd37)


r0 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1, &(0x7f0000000200)=0x8, 0x4)
getsockname(r0, &(0x7f0000000000)=@in, &(0x7f0000000080)=0xc)
connect$unix(0xffffffffffffffff, &(0x7f0000000000), 0x10)
connect$unix(0xffffffffffffff9c, &(0x7f0000000000), 0x1)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
socket(0x0, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket$inet(0x2, 0x3, 0x0)
getsockopt(r1, 0x0, 0x20, 0x0, 0x0)
r2 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0106924, &(0x7f00000001c0))


madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000080)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000001180)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000040)=0xc)
r2 = semget$private(0x0, 0x4, 0x5c0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000300)={0x2, &(0x7f00000000c0)=[{}, {0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x33}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x18, 0x0, 0x37)
syz_emit_ethernet(0x46, &(0x7f0000000140)=ANY=[@ANYBLOB="aaaaaaaaaaaa000000001c0086dd00000000000000020000000000bbfe800000000000000000000189a95ace1efac6e9052475ca0400000000aa0000"])
semctl$SETALL(r2, 0x0, 0x9, &(0x7f0000000000)=[0x1, 0x4, 0x6529])
r3 = socket$inet(0x2, 0x2, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000200)="b1000503000004000000000007000000331c13fecea10500fef96ec0c72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa05000000512f4d335c22", 0x49, 0x0, 0x0, 0x0)
close(r3)
r4 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x200000000000a, &(0x7f0000000040)='\x00', 0x1)
setsockopt$inet_opts(r3, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
r5 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
getppid()
r6 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f000000e000/0x2000)=nil, 0x2000, 0x0, 0x10, r6, 0x0)
munmap(&(0x7f000000e000/0x3000)=nil, 0x3000)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x0, 0x10, r5, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
writev(0xffffffffffffffff, &(0x7f00000001c0)=[{0x0}, {&(0x7f0000000040)}], 0x2)
r7 = socket(0x18, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r7, 0x80206982, &(0x7f00000001c0))
semop(r2, &(0x7f00000001c0)=[{0x0, 0x5}, {0x0, 0x7}, {0x3, 0x6, 0x800}, {0x2, 0x24f6, 0x800}, {0x2, 0x0, 0x1000}, {0x3, 0x9, 0x1000}, {0x0, 0x9d57}, {0x1, 0x8, 0xc00}], 0x8)
setregid(r1, r1)
sysctl$vm(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x8060693c, &(0x7f00000001c0))


syz_emit_ethernet(0x66, &(0x7f0000000000)={@broadcast, @remote, [], {@ipv6={0x86dd, {0x0, 0x6, '\x00o3', 0x30, 0x3a, 0x0, @rand_addr="8a211dd1450021b07f5a1957de7400", @local={0xfe, 0x80, '\x00', 0x0}, {[], @icmpv6=@pkt_toobig={0x2, 0x0, 0x0, 0x0, {0x0, 0x6, '\x00', 0x0, 0x0, 0x0, @local={0xfe, 0x80, '\x00', 0x0}, @ipv4}}}}}}})


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r1, 0xc1206925, &(0x7f0000000100))
mknod(&(0x7f0000000000)='./bus\x00', 0x2000, 0x6380)
r2 = msgget$private(0x0, 0x0)
msgsnd(r2, &(0x7f0000000440)=ANY=[@ANYBLOB="000000000012000042fee188507af9149e61f61f53aaf3757ccb78896d3c837f925dc9db9108ae5e024eab385884d1d263bf23f6b047f237b3044cae340a3113198d0989c5bd76407c38f806e8f98e4e785567c23e5d0560e086fa607be55619c73ae912ec6b79ace314ffb9ff1be677be050beecd6bfe2e5449aee9b4e74dd9fd5a9fe72c37d7cebd8f0e4d766264d3c71de6d9c2d09ed3d2192220aca447f80c0a4df648ccc961660c9a475d12361a624646494b44f0dba28594a94b73fb8b7eb30574e0a9856ad8709d3459ec012de499f444d85c0a87f4bc140812221d78096d7d642600f9def393dcf631a1d4ecd9"], 0x11, 0x800)
msgsnd(r2, &(0x7f00000006c0)=ANY=[@ANYBLOB="03"], 0xa9, 0x0)
msgrcv(r2, &(0x7f00000007c0), 0x90, 0x3, 0x0)


setreuid(0x0, 0xee01)
r0 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmctl$IPC_SET(r0, 0x1, &(0x7f0000000140)={{0x0, 0x0, 0x0, 0x0, 0x140}, 0x0, 0x0, 0xffffffffffffffff})
shmctl$IPC_STAT(r0, 0x2, 0xfffffffffffffffe)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0x3006ff, 0x264b, 0x9, 0xd, "fabafa588fc0001000000010000000001000"})
writev(r0, &(0x7f0000000040)=[{&(0x7f0000000180)="8a9ce4036307187ac8b8804f20f81b83c8ba79d72cbd641e690ca7f75c9e2ad2a284af6a5bf164e818358fefe887e8f8e172d17799657f41aec12efc5febc0ff437185b8532117c1000000002d21797f5acfba4e465810d918cb3e1cf8f06937c71e0b39f64012ce974526e31d1937376a87872c0b286508f6d774d8f5100b51a3275ddb218a808a", 0x88}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{0x5c}, {0x54}, {0x8126}]})
syz_emit_ethernet(0x2e, &(0x7f0000000140)=ANY=[])


open(0x0, 0x75f493fec6515f78, 0x0)
r0 = getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r0})
r1 = fcntl$getown(0xffffffffffffffff, 0x5)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0xb32, r1)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
pipe(&(0x7f0000000000))
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040))
select(0x40, &(0x7f0000000040), 0x0, &(0x7f00000000c0), &(0x7f0000000100))
munmap(&(0x7f000000f000/0x7000)=nil, 0x7000)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000500)={0x0, 0x0, &(0x7f0000000480)=[{0x0}], 0x1}, 0x1)
r2 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
r3 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000100), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r3, 0x80105728, &(0x7f0000000040)={&(0x7f00000000c0)=[{0x6}, {0x7}], 0x2})
sysctl$kern(&(0x7f0000000040)={0x1, 0x3f}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0xfffffffffffffda3)
sendto$unix(0xffffffffffffffff, &(0x7f00000000c0), 0x0, 0x0, 0x0, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r4, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000100)=[{0x14}, {0x25}, {0x16}]})
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f00000001c0)=ANY=[])
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000180)=[{}, {{}, 0x7, 0x0, 0x0, 0x0, 0x10}], 0x0, 0x0)
r5 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x10215, 0x0)
ioctl$VNDIOCSET(r5, 0x81946467, &(0x7f0000000180)={0x0, 0xffffffffffffffff, 0x0})


r0 = syz_open_pts()
syz_open_pts()
ioctl$TIOCSTSTAMP(r0, 0x8008745a, &(0x7f0000000080)={0x0, 0x20})


r0 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1, 0x0, 0x0)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
getpeername(r0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
mlock(&(0x7f0000ffa000/0x4000)=nil, 0x4000)
r1 = socket(0x2, 0x1, 0x0)
bind(r1, &(0x7f0000000000), 0x10)
connect$unix(r0, &(0x7f0000000000), 0x10)


r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
fchdir(r2)


semctl$SETALL(0x0, 0x0, 0x9, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
sysctl$net_inet_icmp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ktrace(0x0, 0xe53a055dd4cd665d, 0xa24, 0x0)


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(r0, &(0x7f0000001580)=[{&(0x7f00000000c0)='\x00', 0xfffffeb0}], 0x1)
open(&(0x7f0000000200)='./file0\x00', 0x2, 0x0)
select(0x40, &(0x7f0000000100), &(0x7f00000024c0)={0x1ff}, 0x0, 0x0)
readv(r0, &(0x7f0000000740)=[{&(0x7f0000000140)=""/144, 0x90}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000440)=[{0x1}, {0x3d}, {0x6}]})
syz_emit_ethernet(0x52, &(0x7f0000000300)=ANY=[])


ioctl$FIOASYNC(0xffffffffffffffff, 0x80047460, &(0x7f00000000c0)=0x406)
syz_emit_ethernet(0x36, &(0x7f0000000440)=ANY=[@ANYRES64])
recvmmsg(0xffffffffffffffff, &(0x7f0000000c80)={&(0x7f0000000c40)={0x0, 0x0, &(0x7f0000000bc0)=[{&(0x7f00000000c0)=""/67, 0x43}], 0x1, 0x0}, 0x4}, 0x10, 0x0, 0x0)
socket(0x2, 0x5, 0x0)
syz_emit_ethernet(0x138, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{0x2000}, {0x3}, {0x6, 0x7, 0xfc, 0xbe}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0xfffffffffffffe59)
sendmmsg(0xffffffffffffffff, &(0x7f00000007c0)={&(0x7f0000000780)={0x0, 0x0, &(0x7f0000000140)=[{&(0x7f0000000180)="b860fe09625ee6793978a575faa1b6c6c1d6c2eca2950e663d39ab1be31a269a39fd7f97e41e178f37a79f00659c2ea9ac56733f7e4e4973c1e6b33ac91343ea3b3f8c5c7b93d5c20ab4211791fe30", 0x4f}, {&(0x7f00000002c0)="0c7e3528e8738137eec5df95e45c178ca5e230d41d12099347e8f5f6c7defb54810b04d83c455860d69355b50c4a9ad5f6f56885af5e18a14b667b3421913ce61b086394557c0bf88e9f4947bd", 0x4d}], 0x2, 0x0, 0x5d}}, 0x10, 0x1)
r1 = socket(0x18, 0x3, 0x3)
mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x202)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
mknod(&(0x7f0000000200)='./bus\x00', 0x6000, 0x202)
link(&(0x7f00000000c0)='./bus\x00', 0x0)
ktrace(&(0x7f0000000180)='./file0\x00', 0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, &(0x7f0000000200))
close(0xffffffffffffffff)
r2 = socket(0x0, 0x0, 0x0)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x8}, 0x4, 0x0, 0x0, &(0x7f0000000200), 0x0)
connect$unix(r2, &(0x7f0000000280)=@abs={0x0, 0x0, 0x3}, 0x8)
mmap(&(0x7f0000ffb000/0x1000)=nil, 0x1000, 0x0, 0x813, r1, 0x2)
msync(&(0x7f0000ffa000/0x4000)=nil, 0x4000, 0x0)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x3a, &(0x7f0000000340)=ANY=[@ANYBLOB="ffffffffffffffffffffffff08004600002c000000000000907800000000e00000014404204e2041fe8ef27d8e", @ANYRES32=0x41424344, @ANYRES32=0x41424344, @ANYBLOB="501b88db784f003e060b06fc5e44ce2b6531304fc59e3030"])
syz_emit_ethernet(0x0, 0x0)
semop(0x0, &(0x7f0000000580)=[{0x4, 0x8, 0x800}, {0x4, 0x0, 0x800}, {0x1, 0x3f}, {0x1, 0x4}, {0x4, 0x1000, 0x1800}, {0x0, 0x8ef, 0x1000}, {0x2, 0x8, 0x2000}, {0x2, 0x1162, 0x400}, {0x0, 0x755, 0x1800}, {0x2, 0x0, 0x800}], 0xa)
r3 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r3, 0xc0106924, &(0x7f00000001c0))


kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000140)={0x0, 0xfffffffffffffffb})
r0 = kqueue()
kevent(r0, &(0x7f00000000c0), 0x7, 0x0, 0x80000001, 0x0)
r1 = kqueue()
r2 = kqueue()
kevent(r1, &(0x7f0000000080), 0x9, 0x0, 0xfffffff7, 0x0)
kevent(r2, &(0x7f00000000c0), 0x7, 0x0, 0x80000001, 0x0)
r3 = kqueue()
kevent(r3, &(0x7f0000000000), 0x81, 0x0, 0x1c6c, 0x0)
close(r0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r1, 0xc1206925, &(0x7f0000000100))


recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0xffffffffffffff40, 0x0)
close(0xffffffffffffffff)
recvfrom$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
getgid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0xb2}})
r0 = socket(0x18, 0x1, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
r1 = socket(0x18, 0x2, 0x0)
r2 = socket(0x18, 0x2, 0x0)
setsockopt(r2, 0x1000000000029, 0xa, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
dup2(r2, r1)
r3 = syz_open_pts()
syz_open_pts()
syz_open_pts()
flock(r3, 0x1)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f00000000c0)={0x0, 0x1ff}, 0x10)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


preadv(0xffffffffffffffff, &(0x7f0000000440)=[{0x0}, {0x0}, {0x0}, {0x0}, {0x0}, {&(0x7f0000000300)=""/41, 0x29}, {&(0x7f0000000340)=""/164, 0xa4}], 0x7, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff})
writev(0xffffffffffffffff, &(0x7f0000000140)=[{&(0x7f0000000500)="7182052190a8db37c2", 0x9}], 0x1)
sendmmsg(r0, &(0x7f0000000480)={0x0}, 0x10, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000280)=[{0x35}, {0x24}, {0x6}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
syz_emit_ethernet(0x36, &(0x7f0000000100)=ANY=[])


connect$unix(0xffffffffffffffff, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
r1 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
fcntl$getown(r1, 0x5)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x9}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206923, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r2 = socket(0x18, 0x400000002, 0x0)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r3 = socket(0x18, 0x1, 0x0)
r4 = dup2(r2, r3)
sendmsg$unix(r4, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


pipe(&(0x7f0000000100)={<r0=>0xffffffffffffffff})
r1 = getpid()
setpgid(0x0, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r1})
pipe(&(0x7f00000001c0)={<r2=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r2, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r3 = fcntl$getown(r2, 0x5)
fcntl$setown(r0, 0x6, r3)
fcntl$setown(r0, 0x6, r1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000180)=[{0x60}, {0x24}, {0x206}]})
write(r0, &(0x7f0000000000)="7696e5f3d1f18c37cea8615ac7cf", 0xe)


semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
sysctl$vm(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x10, 0x0)
socket(0x18, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
munmap(&(0x7f0000ff7000/0x3000)=nil, 0x3000)
setreuid(0xee00, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000500)={0x0, 0x0})
syz_emit_ethernet(0x7e, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
getsockname$inet(0xffffffffffffffff, 0x0, 0x0)
r1 = socket(0x18, 0x2, 0x0)
fcntl$dupfd(r0, 0xa, 0xffffffffffffffff)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x200, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)


mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x5d4a)
r0 = open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
r1 = getpid()
fcntl$setown(r0, 0x6, r1)
fcntl$setown(r0, 0x6, r1)


r0 = socket(0x2, 0x4001, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x1, 0x1, 0x0)
close(r2)
r3 = socket(0x18, 0x3, 0x0)
setsockopt(r3, 0x1000000029, 0x1a, &(0x7f0000000000)="5ab777", 0x3)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(0xffffffffffffffff, 0x0, 0x0)
open(0x0, 0x4, 0x0)
poll(&(0x7f0000000ac0)=[{0xffffffffffffff9c}], 0x20000000000000d7, 0x0)
r4 = socket(0x2, 0x4001, 0x0)
r5 = dup(r4)
r6 = fcntl$dupfd(r5, 0x2, 0xffffffffffffffff)
close(r6)


faccessat(0xffffffffffffffff, &(0x7f0000000000)='./bus\x00', 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x8000, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x0, 0x0})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x3}, {0x4c}, {0x16}]})
write(r1, &(0x7f00000003c0)="7f23a3c23cce2575e1dd92c25678", 0xe)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
r1 = open$dir(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x0, 0x810, r1, 0x0)
unlink(&(0x7f0000000000)='./file0\x00')
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000140)=ANY=[@ANYBLOB])
msgctl$IPC_STAT(0x0, 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r2 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0106924, &(0x7f00000001c0))
r3 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r3, 0x8020699d, &(0x7f0000000100))
openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000040)={0x0, <r4=>0x0}, &(0x7f0000000100)=0xc)
seteuid(r4)
r5 = semget$private(0x0, 0x1, 0x10)
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
r6 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r6, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r6, 0x0)
r7 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r7, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
connect$unix(r0, &(0x7f0000000180)=@file={0x1, './file0\x00'}, 0xa)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
accept$unix(r6, &(0x7f0000000480)=@file={0x0, ""/244}, &(0x7f00000000c0)=0xfffffffffffffe7c)
semop(r5, &(0x7f0000000140)=[{0x0, 0x7, 0x800}], 0x1)
sysctl$vm_swapencrypt(&(0x7f0000000000)={0x7, 0x2, 0x1}, 0x3, &(0x7f0000000040)="74e09c14a2a2d52256b0b9da0c1c53ee70c810c95a5c3b16a7883638ed40bd316ec407f0d78f8ebab9a9", 0x0, 0x0, 0x0)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000000400)={0x0, 0x0, &(0x7f0000000080)=[{&(0x7f0000000180)="cf70770c0d6e80f391bb19656265c41dbf978bc8ef8f9c4c61decb06778c275ed5f70fff9371f1e7789cea6dd7768a2bf2e1a3b9964f606ae9f98c61b38d595303b8f29af43b7903151d6d610da3bb97b52d896feb0a9a1e917c89ec20b854157d7a67e8468615947f9903f6affcc36234407d72d527e7514e53d668cd96c5795a50dbf714313fa18f65de35968e6c1744ebc1a81ee87beb77bef9e84b047377255e3f21a21862b5acf40b49dbbd24ea82380a299266d9", 0xb7}], 0x1}, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000132000/0x3000)=nil, &(0x7f00000a0000/0x1000)=nil, 0x80400000}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f0000ff3000/0xa000)=nil, &(0x7f00001f0000/0x1000)=nil}, {&(0x7f00001f0000/0x1000)=nil, &(0x7f0000001000/0x1000)=nil}, {&(0x7f0000132000/0x4000)=nil, &(0x7f00000b2000/0x1000)=nil}, {&(0x7f0000083000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {0x0, &(0x7f000002a000/0x3000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000e58000/0x4000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil}, {&(0x7f0000091000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000001000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000132000/0x1000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000008a000/0x1000)=nil}, {0x0, &(0x7f0000092000/0x3000)=nil}], './file0\x00'})
openat$vmm(0xffffffffffffff9c, &(0x7f0000000800), 0x0, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
r1 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x401, 0x0)
open(&(0x7f0000000100)='./file0\x00', 0x615, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
r2 = socket(0x18, 0x3, 0x0)
setsockopt(r2, 0x1000000029, 0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0xffff)
r3 = kqueue()
kevent(r3, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000080)={0x0, 0x80000002})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x1, &(0x7f00000000c0)=[{}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$WSMUXIO_ADD_DEVICE(r1, 0x80085761, &(0x7f0000000040))
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000040)="94c79bd261e1e88e83beb11c0a3e154df77b5335bd1667d9fd77c59297b3cad0ade427f63f2912518a179b7c207bc5ba040a20b5c36bfaca54e49900550bad2f165552f266a6b12d4900c56a22e814223e67a3fdf5ae19bcbb5d0a815015db8752d03d1b08f84b4976ec52d4a82598424ed3a6a523a3591db0e862a2f4dd1168cb17845fff1fb5df5535cae3e20e2bdb92138d0c1b0720e1c121ccb763f092cd5dcaa3d901", 0x2cfea}], 0x10000000000001fc)
munmap(&(0x7f000006f000/0x1000)=nil, 0x1000)
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f00000001c0), &(0x7f0000000240)=0xc)
r4 = open$dir(&(0x7f0000000340)='./file0\x00', 0x0, 0x0)
openat(r4, &(0x7f00000002c0)='./file0\x00', 0x100, 0xb1)
r5 = open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
mkdirat(r5, &(0x7f0000000180)='./file0/file0\x00', 0x0)
renameat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', r4, &(0x7f0000000280)='./file0/file0/file0\x00')
openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f00000003c0), 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300))
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}}, 0x10, 0x0, 0x0)


socket(0x0, 0x0, 0x0)
ioctl$VNDIOCSET(0xffffffffffffffff, 0x41946465, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x10, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x9, 0x54})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x0)
setsockopt(r1, 0x0, 0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x100000000000000, 0xffffffffffffffff})
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
writev(r1, &(0x7f0000000180)=[{&(0x7f0000000200)}, {&(0x7f0000000100)="56ab93703ee39124a918356389fff97c954f6c051bfc4d4300d470410f5d3b5b8242c298708b", 0x26}], 0x2)


open(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
r3 = socket(0x2, 0x1, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r2, 0xffff, 0x1023, &(0x7f0000000080), 0x4)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)='\x00', 0x1}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000000)="a23bc03626603cf6e9040000", 0xc)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000000)="b8", 0x1}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
readv(r0, &(0x7f0000000040)=[{0x0}], 0x1)
dup2(r0, r1)


r0 = socket(0x18, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x821869de, &(0x7f00000001c0))


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0x8020560a, &(0x7f00000002c0)={0x10, 0x0, [{&(0x7f0000ff3000/0x4000)=nil, &(0x7f0000fef000/0x4000)=nil}, {&(0x7f0000165000/0x2000)=nil, &(0x7f00001e6000/0x1000)=nil}, {&(0x7f0000787000/0x4000)=nil, &(0x7f000011c000/0x3000)=nil}, {&(0x7f00005bd000/0x4000)=nil, &(0x7f0000fee000/0x3000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000268000/0x2000)=nil}, {&(0x7f0000328000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000075b000/0x3000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000760000/0x3000)=nil, &(0x7f0000ff2000/0x4000)=nil}, {&(0x7f0000fec000/0x14000)=nil, &(0x7f0000ff9000/0x1000)=nil}, {&(0x7f0000ff9000/0x2000)=nil, &(0x7f0000fef000/0x1000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000729000/0x2000)=nil}, {&(0x7f0000ff5000/0x4000)=nil, &(0x7f0000ff6000/0x1000)=nil}, {&(0x7f0000ff8000/0x2000)=nil, &(0x7f000075c000/0x3000)=nil}, {&(0x7f0000432000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil}], './file0\x00'})
mknodat(0xffffffffffffff9c, &(0x7f0000000280)='./file0\x00', 0x1000, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r1 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
ioctl$DIOCMAP(r1, 0xc0106477, &(0x7f0000000080)={&(0x7f00000002c0)='./file0\x00', r0})
close(r0)
execve(0x0, 0x0, 0x0)
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaaaabb86dd605d34520030000000000000000000000000000000000000000000009f05000400000000000000010100"])
r2 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r2, 0x0, 0x0)
sysctl$vfs_nfs(&(0x7f0000000280)={0x7}, 0x5, 0x0, 0x0, 0x0, 0x0)
r3 = semget$private(0x0, 0x1, 0x0)
semctl$SETALL(r3, 0x0, 0x9, &(0x7f0000000040)=[0x0, 0x8001, 0x0])
r4 = socket(0x18, 0x2, 0x0)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f00000000c0)={0x0, 0x1ff}, 0x10)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0xfffffffffffffffe, 0x0, 0x0, 0x6ee}], 0x0, 0x0, 0x0, 0x0)
r5 = socket(0x18, 0x2, 0x0)
r6 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x0, 0x10, r6, 0x0)
setgroups(0x0, 0x0)
setsockopt$sock_int(r5, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r5, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
close(r4)
kevent(0xffffffffffffffff, &(0x7f0000000080)=[{{}, 0x0, 0x0, 0x0, 0x40}], 0x0, 0x0, 0x0, 0x0)
r7 = socket(0x18, 0x2, 0x0)
setsockopt$sock_int(r7, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r7, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
close(r4)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000100), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105727, &(0x7f00000001c0)={&(0x7f0000000200)=[{0x25}, {}], 0x2})


socketpair(0x1, 0x5, 0x0, &(0x7f0000000380)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000000)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000080)=0xc)
setregid(0x0, r1)
openat(0xffffffffffffff9c, &(0x7f0000001500)='./file0\x00', 0x222, 0xb3d2b0b5428267ec)
openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r2 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r2, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r2, 0x0)
r3 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r3, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
r4 = kqueue()
kevent(r4, &(0x7f00000000c0), 0x30, 0x0, 0x57d, 0x0)
accept(r2, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETF(r5, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000080)=[{0x3d}, {0x7}, {0x8186}]})
setrlimit(0x8, &(0x7f0000000040)={0x7, 0x50})
r6 = syz_open_pts()
close(r6)
r7 = syz_open_pts()
ioctl$TIOCSETAW(r7, 0x802c7415, &(0x7f0000000000)={0x29f57365, 0x0, 0x1f, 0xffffffff, "8b644cf1a3f4d3c900000000000000e81f3e6323"})
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000340))


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r1, 0xc0206917, &(0x7f0000000100))


mkdir(&(0x7f0000000040)='./file0\x00', 0x0)
unveil(&(0x7f0000000280)='.\x00', &(0x7f00000002c0)='c\x00')
unveil(&(0x7f00000001c0)='./file0/file0\x00', &(0x7f0000000080)='r\x00')
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)


sysctl$net_pipex(&(0x7f0000000000)={0x4, 0x23, 0x1}, 0xb, &(0x7f00000001c0)="cd3ddb7672b09e0ca6c2e69c9c6e2f1830e04251a9bca8f2c458d0dfa75e536a5ff4c1fe4cfd2af5fbec9360699c963fb7e9c4a640e5c09fb261d4b5577589bb886e172b97ba8b0d37475a00082542967b500116042821b8c3bde0d2fd8863c80739510849a4c61a74a3c447448f6fd64ab1dd18a8b709fed6a3c96afe923414f0e791e4b3393f5765a4020801d34eac2c807cfb75c76f728167644b5c5121d07cb9cb01444f67ecf6e552e38dba15254642d791c33e0a4e39f3b33aefbd0c28510ed628cb1719768d44746586dd8584a100fdf1cd74936ac7ba3609a0314a419268dec3710f795bdd512f956d6e98e8cb8dc75613e5d75155a8e6e49dac6094c0eaf0e5198df968fd4dc6c9d0aa99ae3fbc1507000000aa", &(0x7f0000000140)=0x11d, &(0x7f0000001580)="2fc989f86d85ebf448c52757a9ea9b79aa86356e6d6c917d12cd2ee38a34a3cb0a7cd0cf6105d00db8f1356c2f466a51531ec76b8acb3448ab810aad2f24d2fc6f29e5b4b63626fb57dd211f7c5a72b9259ffe258a4e7e718e8619bca396b4c885833b2794124cb291f8334bdc3babf42314172d75b9f124acb4b861b709f96954170bda83e6ca5a022a6b4dc8e46b866368c151d3ca1cbd55f592d665efa6282449e33c353662369772dec63927b9923311af1dd261fb27794bce584e87c4aeb09f9b4777a08ee29af3ce70f3aa51a8e8ce57d59fde41cad1d03b872c8a44d34bf25c679276fa1af314bd9b68ea03570cc84d272feeb97ddb172ee1725c56c4146893f54294aa120bb5f3de373216645db8c01c1c995aae6fdf6ef11399c2510bec9df11b3047ce239b7348ddae869790fff592bae9a3510abdc878976d34fc45fb8a1a05f4f8ac41a1c62f7269154812d658e68ec4bf333cd16a5815d5b5bad11560de19db25a42b89efec1abd8a4744a2ec340c8fb44d9a1621d56135c3bbdfdc04bdabe26646643d8656cdb3e239bdae079112d15c4668f66707ccf32935c48dba4fe3ba8898135fa7643d17668c0046b2beda469afa20b88b6c6406659508a6c14e297923e1c416bafd717e6807ff5a5b443a3cf95ec2425121db529e12761aa850ca9acad42a3a6dd1c7e47308798bd81c0644d7cecf0d5f3789044279e0c751bc3f58867409e94f763be4927b06aaf5e4f75899d233c478b1be09309ec725c0f96d25e3ff748a5412b65bdd51c1e2374fcf33d9ffd82171171248ac19cba5efdd249e9cdc9162226c7b9f6f074af2280a970069bf1bb423af2115b045119ccec66c79b808f963281343b14e60400783cd4aaa593872596c7920bd8895c415714d3add9c6c3ecf82501bcc8617d9a6478f88e02a12c76febb57b9faf5262a363bec739cdb3248a16e3623fad4fd5c3b3459d622b161e2d1b4bfbf1e0ec103b6e46d026f92bf3540368a810fb88aa20d437081a9dcf967c7872076be8bd1e0a34df2a0596fb892e901a0646d8027b376b7c1be75720cabd10d2c16d0d97525dc80d52697b6e41add4995e4396758a90e4241d3a80ffbfd7429dfdff93431ba2f26c84853b34c602356b5b10b2186d1efb5fd8aeefb4cfaf11819cfa2f29441d49c9c5c94ecd1395bcd90115a0b9e218cd1eccdd1c78f3bf4395c8d264836fdee86a9f411375750f935be238790dfed1b8eb60c72828e767553cad0502594ddef99ffd91787dd3e6a24928a6551994b9a82b37dd2ea72a06481abe4fc8cc1363c14c83808d6cb48e9e5e1f91e7c228bb89f182876c09858ee32bb817fa7f6436a1cd20c30656a00e1935088539248efc707bd5847493421529659d6ccbda64aedd7f1a6e60020d1cd24525e9a4a66b269b47b0864bfef1f0365c0e307c9d8f35874f36a37f6b7f72224ee927fa0dde041ca354ec639c27cc1a399fc4d89e1c4cdf0e9d411c441579d5b41c6607929d77e62ca87ee4fd76182410befa222832156fc5faa2831aee3c81d9651003a8b51c394f0d9c971ddb73cc46dd438f818133d40c775252256243367e795b4e6a2e64c3dfc33813463aedc0516512d64032becb261143c69cb23c7a0b988b57c33b842dc8d3d790509e44fdb492d5c020be8396cccad4babf094d72c4ba2d5613be3b6e584ded40a920d83dc073cfd7f95ff781f66b3b8f656daea226dd07783b86e803ec777afb79b00c873af3911afd3a004aaa5871f1b263c56644312484a581ac3e656044802871f8d24ee5d53c0649cee463807d3a6f8907d4989cbb7f5261437a25b161ba9e999bbd1d40ca130a494d4aecc94d1857f02a34c34a9b4c82bef084e7293b11b3c18decdc1f0423259cd25611313e796d2c06322a5796fc9e609e918aac52c34dd8ff0f424672a856067e2a8cb8890bd9cbaf0c2b8a74b919126657f247f75112fca4e0337e0c9e690d20d14864fe6cd9496f591c62172a445f2e1ea3d401f7954cc4bd1706c7b59ce0844df39121a4a4e55b1efec9338ea2388ca262aae64dae7f4ce23b961eb0c6f2a7a60d996063b5b8b4331ff8ecdcd5cb18e3e1bd936377cdc2eb502ce060c5197f88017ef0f8cf5f5256b0e148aaafb7e22c818887191bb9abdf2493faf1980842f8c2e6edb035b61056f2dfcd9865c1d3c067eaed87c0fe6c338db0963ae38802109be8b8b85aacb3d1c5a37aeea206b9c820713de15b6c198fd2301675b1319c709e568a3d1fcf94d311c5c4ab8f4b381907977d3d6b5e6263415ad3348cd3e8eec82e2cbe43bffb4df96a407f875a22217f791c2532a5e5e8acef6313d566f174f433643c678cd259fc9a859f3be1f34c7ac648fce3f26e80171685405d5acff31846571ce6d2cd9d222709706bb81ad45b8f293f7f18b2a2fc4259b40fd60d9819b5fc0caff1b5cb5c96e488df2bb5866945ada79ea379059931cf2d0f94963ef425832f16b348ce83dc83a39c4947485cd80e4196135c06e985a16969324eaff655424722682c709951ea0db0d4769b46af2796d10df3d0cac1b6c6f75c43ca2ba37952f56ea092109428d1c1cc8bef8816e432686734edc556be7729a25064209262f04421d25ec0f6b5bbf75d7001d0e2d7b2ae18a2e2b8e602cbf55e309b9985d2edc67232fafffcd92695cf4e0da02ae8cb57df7c198ec37e4bc9d4a50eebcc9274155cdaa932473ce6d2c5ead89e2f4517fdf578ae7801beab3c0d37057eb93fb628e92499d7ae1323a1fcec59a06b0aa5f4e5e110e395d05f76e9e3a78de49a020a2f25dd2c70fb73c6752dffe011eb68b287f10efc9668b15c138d3db23a12f61c197cda705fd44b911f8420973ad97e7db327f2325bd01c1444a1f5d5b159dda3f0c76e4b6706b802b000577a8335a713dc4f854013c8b79e8c910f402587be07f020b859f1bef0f5edeb40558d6d790eb391bbbde4ce0e016d2f0bced2eca7ab7eaaf001f7f1bae74dc3395632e8be930c68be6e94c2857e678dc81e9886870d92eb33a6bfab9636bdae98e0eaf558e243770ab042bc08b22052829cc58028aeeee12fecacd948bded186e36882f286c64e791c989743cad4ef774273e9dfbf6ab148b4d65f3abe39ff789eab488cd294d64ef33db7a241557ba990a6220a90acda8f017d1cd8f83d1d9b7ea2233454d6e9adbadce84d008702f894c77c4346495795f8e13acedf2b96d5c31cb816a1203ec49779387debbfdd89ff5f2ca03bdfdcbd9942e9e29d1231aae8eee6656e952e17c3aa7feea40e1dbb5dde4c9e24eb17fc88bda4597e4ae20284e344a0bee1da46886ddcd429491363388b1657cbaa5c7eec2a66970776aa07dbbc5282fefcde7d6609b48dcc898223ad59ce10f5465195c8f3956784c76c4d0924a3bffd902018cc5b654d368f78a3a876901da8a4baaabf876997b80dbc3a2e6bc57e319f30fb48dada38e04b44b886f076b06da1b7c8a7481707607a2ac2710c1c36fe8bd1d46854d62cdd1786e45968ade7098812de109c29ef970de2b5fa7f52fb21e1f2982994a1909765597c4908852785c4b64138926d0427b447e668eca3004ea8d7f9ef966c2bf1093b659b5d2368b0f06e8ce595b29573e32e6bc4682d76505c82cf0b7c19f9a9c979948ae6e006d65f3a7b36685103339d6e1d8b3c84c7c6940bf7c5ef38ba1ab71ecd262612b66246af714c85b295f6219b2ce6e622fe32fe197f94a92c37db4195f752e14a2cb20b63c323e67534b8dc8ef9cbe0a44f5eca4ea5a6f58f0f505dd8604f51a0842f0fabb5b7d84a749c05438dfc7f4e20f8d1c076890c6859ae9afe79175d3640261c3e310ab7f688bdcc7eea1ba58c5ff1343daf1c40631e3998b80114f308ce3c1b40f8cde24c5ca501ac260c724281edda0ff4f152f7393d7f78ec4cd4dc0b0bfdc44dd2d9cfd627d9073b9a6a52bc627affe18cd04ed11a55f071da00e3e9f60d974f61ca9d47f3eaef8cbf11e662ce132adb844c28451236b764f846ae1b34edcffce5481ea5519a468602e4f77fdb012e3a04d900be17d5b18cd1e9de4cb3d6a11b46ea84f39e55c3bb8a7c03965ede0fbbb2c28e8bc94a1cec8ee64956a8c1e013376d93c51942c697ecc8188ec92a66c6d7634b4f0d4a42505d4393f25f75f946342394ac73cdaf787c1902d709cb5540ac90ff936fc058a2da2569d0254cf489a44acf35b3023fe02c33e9c681a642c9f692475ae5365a165fd15fa9522d30360b67a5a044c9015ba99b831666e0d5fbb8454bd414b2cdd6547847c0b38d0b0b3dcc3d301978c421633d5b8c78bda59ce51ae0d746a1f3d9ac967699bafe5cd459d1a66bae31dce4db42becae37e10656ffdf47ceef1cd95873e64e194a015c30528edc8dc778023ae00dbc5a10994013587a512dd15d23ceeff9807be73d918199b452cbf111117283f0d470db4452df0dc9d1a6771742f7ff29989e6bb50cec72edc782592b3b17765c6402cf7fc5b599fcea708b6b0e423195cd0456d365e8cc6ac0569b4690f8683564a64a6257a92b9d62a929558cc6f624c011a07e4d4e555bd277eb1665ff5cb6f968220a0c7bd8abff3fe8f9129bc0cd829154be4f870fc1156bb330eca65b171e3d861c8f5fdd3b22a3c5a0c9f5828d9a41f48a14c74b4bd9582afb136eda1ae97e6cfcb4c15e5b2b5fdd5f7be4d08c9ab7daceb444ee87b6fc51ff8a085a5faf399d83d6914ccffeff46632f1d7d400eae63476de57ac5a998e8b27ca17c9b052cba49507260c522b485553cd087a0bd7b3755766daf55ddcfbe4416c9741bbfa72ae6555e8586c6f72af92eb280c1903449503b6f88e2490f5470e33316665679d0196e51aef63eeaeecf7bbf815810b2decf4d193784510315f3cb3c91a8927e163973b378d74b3db1b313af964d01a1105b16c6517ad74705640e33862f8aadf19b3979763d186619bade5364f1218586243d835415fd936b5177df1c48ba1537c02cc5bbc3b2e90fd936c0df9a3d159d1a7fd19827025f7dbd288b85b0fe37f64895ddd64582d65eb428b5c5771d3d4eb596f96d52b75c82db613e226df4b51c076e1e6963360962f365871e55f5d10da1e38d0ca6d34a905c1ec8d6afa77dbbc203f2393806f5c4c517c426f9a73dfd6afd2c3533c7b940c76c70a5406749569023c71cbdca48eefbdfe031ddb76e8cf72cf379ec41a915f846e3dd6d70c71650a63a4ed0b0392c2ec8561a647fa07b2c4ac0e08b840563f10a5ccc3eb3214c1fe2a59389b2236139c2bb3512247abca8bb0c67caa33d4fc22697a06abddce5633b248f23204e5f485c0e5d1fcdf562fe87ac673dc0719254d155b0c9f4f1054bdad77f3f8688fe7a93a974e94d11e89da9f8307b1a4d30a0d19ff543418877f4c3ab6ffad12cb50a831eaf45c19fb54396ea39a8bd6decc3b4856cbee040485a306fa46c919f559576220ca4fe48746b8e7de07ecfea3a4f99c09f3c927bee9c00c0c92e4a98eb5a51a05671f09b07cf894e3d139131f0d733f1df0f77133ab12b5b886092a418bbab3cfd40f842180bd5114fd3ba1b477804393fe01754f1638878c377ec870c4416c424eb1bd30f84362100f86998eba9cf44f21f903ae9cb9eaa86023f095ba0c191fc8abaea76c38d92fb71587167770336d6f4b94f60110741932ec1ce367e74a659309f072c21d3c406d93375bf427c7274b3989e0fd05036a2a528af410d1352000000000000000000000000000000f8d3de4dbc80d0c71167d264d4107a9a8baa50c5b9466c465834148d6346468d05812ed4d7d6c77c615214c9f7b558d3", 0x1022)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b1000504600000000000000007000000331c13fecea10500fef96ecfc72fd3357ae320b37b673039d2d236073705ae04be38164991f7c8cf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139b672f4d335d223e7d026ba8af630037282102000000720fd38bfbb770c1f5a872c8f1c86e69e0bb76d907c400000200361b1257aea8c5000020020000000000008abfba0900000008e371a3f8343712051eadb71d89e0000407ae9a3fe03d757ce7", 0xb1, 0x0, 0x0, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000080), 0x0)
socket$inet(0x2, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
msgget(0x1, 0x0)
msgctl$IPC_RMID(0x0, 0x0)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x1b}, 0x4, 0x0, 0x0, &(0x7f0000001100), 0x4)


openat$bpf(0xffffffffffffff9c, 0x0, 0x462, 0x0)
write(0xffffffffffffffff, &(0x7f00000006c0)="e506000000000000004aaed75a5a", 0xe)
mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x412dff)
r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x402, 0x0)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000000), 0x2cfea}], 0x1000000000000013)


setsockopt(0xffffffffffffffff, 0x0, 0x4, 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000000)="60e115575bd5f63b0dd7a4e26c43a4c0a6a27fb4c1e48d497ad7e8f101ac60dbf73a5fe7ba0c37253b86d68ba32a39c3067bf8", 0x33)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x200000000000c, &(0x7f0000000240), 0x0)
socket$inet(0x2, 0x2, 0x0)
syz_open_pts()
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000100)=[{0x15}, {0xc0}, {0x6, 0x0, 0x0, 0x88f0}]})
write(0xffffffffffffffff, &(0x7f0000000280)="ce4aa4a25043cb02aadf8701f131", 0xe)
r0 = semget$private(0x0, 0x7, 0x3c0)
semop(r0, &(0x7f0000000100)=[{0x3, 0xa, 0x800}, {0x1, 0x2ff}, {0x1, 0x8, 0x1000}, {0x3, 0x3ff, 0x1800}, {0x2}, {0x2, 0x201, 0x3000}], 0x6)
semctl$GETPID(r0, 0x0, 0x4, 0x0)
semop(0x0, 0x0, 0x0)
semop(0x0, 0x0, 0x0)
semop(0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
getuid()


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xffffffffffffffff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0x3f, &(0x7f0000000040)="00fb6c4f", 0x4)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r0, 0x0, 0x0)


sysctl$kern(&(0x7f0000000000)={0x1, 0x40}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$net_inet_tcp(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000000)={0x0, 0x453, 0x0, 0x0, "c07b1f46000000efff0020fbff00"})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbdf13b9fd812eaa4e713048e69931929648", 0x14)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f0000000080)={&(0x7f0000000000)=[{}, {}], 0x2})
ioctl$WSMOUSEIO_GETPARAMS(r0, 0x80105727, &(0x7f0000000080)={&(0x7f00000000c0)=[{0x23}, {0x6}], 0x2})


r0 = socket$inet(0x2, 0x3, 0x0)
r1 = socket$inet6(0x18, 0x3, 0x0)
getsockopt(r1, 0x29, 0x3c, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000546000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ff7000/0x3000)=nil, 0x7}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil, 0x4}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil, 0x1}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000604000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000691000/0x2000)=nil, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil, 0xfffffffffffffffe}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil}], './file0\x00'})
r2 = socket$inet(0x2, 0x3, 0x0)
setsockopt(r2, 0x0, 0x2, &(0x7f0000000080), 0x0)
mprotect(&(0x7f0000ff3000/0x2000)=nil, 0x2000, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, &(0x7f0000000040)={<r3=>0xffffffffffffffff})
ioctl$FIONREAD(r3, 0xc0106924, &(0x7f00000001c0))
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r4=>0xffffffffffffffff})
setsockopt$sock_int(r4, 0xffff, 0x2000, &(0x7f0000000080)=0x4, 0x4)
fcntl$setstatus(r4, 0x4, 0x4)
writev(r4, &(0x7f0000002cc0)=[{0x0}], 0x1)
r5 = dup2(0xffffffffffffffff, 0xffffffffffffffff)
recvmmsg(r4, 0x0, 0x0, 0x0, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
ioctl$KDSETMODE(r5, 0x20004b0a, &(0x7f00000002c0))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt(0xffffffffffffffff, 0x1000000029, 0xc, &(0x7f00000000c0)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(0xffffffffffffffff, 0x25, 0xd, &(0x7f0000000380)="ebff000000c100000000004e71cb48eacf1ce369bdc82dfb69e6a1519da2560f42563b20743c521d00920907ad7c37206755346a5f9d01d7f9fd8778375606ccb551ac1b83153557b5487a57237d0e2f9b7af964411e25dfd85fbca13123e48d00c558051cf24910729a90f44c67cd5e29e467e631807728b71598c04623406dc7fb4916a0aef692dd9de32e6348b93abeb0564770b50bad7790ab71a47877fb425e6f425e4995b0f09b3072ffb27ce126b9385a433768129bb2507d7878dd8ef9c7daab02ae4f1d4574621d18559a02a2abaa8054f1e4606b08b63118c4b6f4ed6158", 0xe3)
setitimer(0x2, &(0x7f0000000280)={{0x2, 0x4}, {0x20, 0x9}}, &(0x7f0000000040))
getuid()
r6 = semget$private(0x0, 0x4, 0x1e)
semctl$GETALL(r6, 0x0, 0x6, &(0x7f0000001000)=""/229)
setsockopt(r0, 0x0, 0x23, &(0x7f0000000040)="3342b19c", 0x4)
syz_emit_ethernet(0x36, &(0x7f00000005c0)=ANY=[@ANYBLOB="b2ea61583222854eeaaaaaaaaaaaaaaaaaa57f2403399369aaaaaaaa08004500009078fffbffa8e94cae3f56a4b13aeec8a01b27024249c921ce967b03a31dd6636e0b1491cb021f292fac66662512d40fe52d476caa8de7321c2f16d7072ae764d62e21f6143f158f6e7e2a67bc8046ac55e60f8206a28f", @ANYBLOB="7a8ac6374001ab1c", @ANYRES32=0x41424344, @ANYBLOB="000000caa32ef69dc11a4c8b1cc1080000000000dac69b61bf"])
r7 = openat$wsdisplay(0xffffffffffffff9c, &(0x7f00000001c0), 0x10, 0x0)
ioctl$VT_GETMODE(r7, 0x40087603, &(0x7f0000000200))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000180)=[{0x20}, {0x4c}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x4001, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
r2 = socket(0x2, 0x1, 0x0)
connect$unix(r2, &(0x7f0000000000), 0x10)
shutdown(r1, 0x0)
r3 = socket(0x2, 0x4001, 0x0)
r4 = dup(r3)
r5 = fcntl$dupfd(r4, 0x2, 0xffffffffffffffff)
setsockopt$sock_int(r5, 0xffff, 0x1023, &(0x7f0000000040), 0x4)


socket(0x11, 0x3, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f00000000c0)='./file0\x00', 0x2000, 0x0)
socket$inet(0x2, 0x1, 0x0)
kqueue()
openat$zero(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
kqueue()
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
select(0x40, &(0x7f0000000540), 0x0, &(0x7f0000000140)={0xab6}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f00000001c0)=[{0x6c}, {0x40}, {0x106}]})
syz_emit_ethernet(0x62, &(0x7f00000000c0)=ANY=[])


r0 = semget$private(0x0, 0x7, 0x3c0)
semop(r0, &(0x7f0000000100)=[{0x3, 0xa, 0x800}, {0x1, 0x2ff}, {0x1, 0x8, 0x1000}, {0x3, 0x3ff, 0x1800}, {0x2}, {0x2, 0x201, 0x3000}], 0x6)
semctl$GETPID(r0, 0x3, 0x4, &(0x7f0000000240)=""/8)
semop(r0, &(0x7f0000000200)=[{0x3, 0x0, 0x800}, {0x1, 0x100, 0x800}, {0x0, 0x1}, {0x4, 0x49, 0x400}, {0x0, 0x8, 0x1800}], 0x2aaaaaaaaaaaab5f)
semop(r0, &(0x7f00000002c0)=[{0x4, 0xfff, 0x1000}, {0x0, 0x420, 0x1000}, {0x1, 0x106, 0x1800}, {0x0, 0x3, 0x800}, {0x0, 0x200, 0x800}, {0x0, 0x4, 0x800}, {0x2, 0xfff8}, {0x1, 0x7, 0x1800}, {0x4, 0x1, 0x1000}, {0x3, 0x7e7, 0x800}], 0xa)
semop(r0, &(0x7f0000000280)=[{0x4, 0x1}, {0x2, 0x8400, 0x1000}, {0x1, 0x2, 0x400}, {0x3, 0x8, 0x1000}, {0x3, 0x4, 0x800}], 0x5)
r1 = getuid()
semop(r0, &(0x7f0000000700)=[{0x4, 0xfff7, 0x1000}, {0x1, 0x200, 0x1000}, {0x1, 0xd22, 0x1800}, {0x2, 0x1, 0x1000}, {0x4, 0x8, 0x800}, {0x7, 0x2, 0x1800}], 0x6)
getsockopt$sock_cred(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f00000003c0)={<r2=>0x0, <r3=>0x0, <r4=>0x0}, &(0x7f0000000400)=0xc)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000015c0)={<r5=>0xffffffffffffffff, <r6=>0xffffffffffffffff})
getsockopt$sock_cred(r5, 0xffff, 0x1022, &(0x7f0000000000)={<r7=>0x0, 0x0, <r8=>0x0}, &(0x7f0000000040)=0xc)
setegid(r8)
semctl$IPC_SET(r0, 0x0, 0x1, &(0x7f0000000440)={{0x100, r1, r4, r1, r8, 0x40, 0x1000}, 0x1, 0x4, 0x1000})
seteuid(r1)
r9 = msgget$private(0x0, 0x102)
getsockopt$SO_PEERCRED(r6, 0xffff, 0x1022, &(0x7f0000000740)={<r10=>0x0, <r11=>0x0, <r12=>0x0}, 0xc)
getgroups(0x1, &(0x7f0000000780)=[<r13=>r8])
msgctl$IPC_SET(r9, 0x1, &(0x7f00000007c0)={{0x0, r11, r13, r1, r8, 0x4, 0x1dd}, 0x4, 0x6, r2, r7, 0x1, 0xfffffffffffffffe, 0x6, 0x9})
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r14=>0xffffffffffffffff})
getsockopt$sock_cred(r14, 0xffff, 0x1022, &(0x7f0000000200)={<r15=>0x0, <r16=>0x0, <r17=>0x0}, &(0x7f0000000240)=0xc)
setregid(r17, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, r3, r12, 0x0, r17, 0x101, 0x2}, 0x0, 0x68, 0x0, r10})
r18 = socket(0x18, 0x1, 0x0)
r19 = socket(0x18, 0x1, 0x0)
shmctl$IPC_SET(0x0, 0x1, &(0x7f0000000140)={{0x8, 0xffffffffffffffff, r13, r16, r12, 0x2b, 0x8}, 0x7f, 0x7f, r15, r7, 0x6, 0x5, 0x7})
setsockopt(r19, 0x1000000029, 0x36, &(0x7f0000000040)="03000000", 0x4)
dup2(r19, r18)
setsockopt$sock_int(r18, 0xffff, 0x1, &(0x7f0000002700)=0xffffffff, 0x4)
ioctl$FIONBIO(r19, 0x8004667e, &(0x7f0000000080)=0x8001)
connect$unix(r18, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x1e56)
r0 = open$dir(&(0x7f00000003c0)='./file0\x00', 0x0, 0x0)
preadv(r0, &(0x7f0000000000)=[{&(0x7f00000000c0)=""/99, 0x63}], 0x1, 0x0)
close(r0)
execve(0x0, 0x0, 0x0)


syz_emit_ethernet(0x2a, &(0x7f0000000040)=ANY=[@ANYBLOB="ffffffffffffffffffffffff8035"])
syz_emit_ethernet(0xe, &(0x7f0000000040)=ANY=[])


madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
recvmmsg(r0, &(0x7f0000000480)={0x0}, 0xffffffffffffff42, 0x0, &(0x7f0000000500))


bind(0xffffffffffffffff, 0x0, 0x0)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000140)={0x0, &(0x7f0000000080)})
syz_emit_ethernet(0x17a, &(0x7f00000000c0)=ANY=[@ANYBLOB="f3a2a8908a86aaaaaaaaaabb86dd601ab5b60000000000000000000000000000000000000000ff020000000000000000000000000001001d"])


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000440)={<r0=>0xffffffffffffffff})
getsockopt$sock_int(r0, 0xffff, 0x1000, &(0x7f0000000000), &(0x7f0000000040)=0x4)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)


r0 = syz_open_pts()
syz_open_pts()
syz_open_pts()
fcntl$setstatus(r0, 0x4, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0xfffffffc, 0x0, "2bbf09a76e9bd301d6291ab88842329097184589"})
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)
kqueue()
select(0x40, &(0x7f0000000000), &(0x7f0000000400)={0x7fffffff}, 0x0, 0x0)


syz_emit_ethernet(0x52, &(0x7f0000000380)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa86dd60362f5f001c2b00fe800000000000000000000000000004000004"])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x35})
r2 = syz_open_pts()
close(r2)
r3 = syz_open_pts()
writev(r3, &(0x7f0000002040)=[{&(0x7f0000000280)="00000053f6953b578a5e78ba726a44164282fbdce59879e20721c0b25930ac15cad92b17987d6c70b9047f2d23cdb8b6d76cdb4acd0f01d102ca1b9624dcb92a3496a85cd3e9356c954d9ad25d87bbbfee51603c6f705bcd4ebc04feceea4a01bb7075d879a19cf6c8ca7a76f1a3377ba643b0b06bef67d736f39ab2dfaa21a7c9f74a537a67ea748b925d5c0db14f19b8643bb65a04e2a641830b2ef9ab4087e50c63959920d13ff13464ce1c18b643a71260860e0483ab217250cdcb121305c5c1b22a236c83d7b8d20dfc08bebe5664e1ea1eb7bb0814dd", 0xd9}, {&(0x7f0000001d00)="6156b89a6c15794f5426cf6a9a99b45b13564d6568f0610200e27d20182a400c7a9a8f0bf304294555b6b6cd19d32607b3754f4a88c97fe52899b92de96dbe32036c902694cbd8aaeda1b13395179e9aa22d5bb4ed975d8a585625759478115f4c4ea9fbe58382e00bad0ecc43529514d50fd81869975cce62c2e1a2520b63fd16166f35d4894abbed34c52f3e7e55be11106341ebcf1c65", 0x98}, {&(0x7f0000000900)="d09f6591cbc30693afd0b88a5a095acbc2a56dfe7b00631bbf4fdf76ffff000000000000057fa75fcb6b520094262d6b81f8fb491e0d5f97f7e6e6fa34e3a87f4928bdcaba0d83c8a2f903007224ea89dd9aec6f5b8a9b09b2593bf5a6bf21f0983e", 0x62}, {&(0x7f00000009c0)="e0707225df5da0a3cde8f30024830d8e0a6a680844e59fcfa5dde0a596d8cb2901b8b60f269bdffed86a45026e99759cd124180e6c72cdd068718d18c40fc74364f4efef980c177c9d13853ee6bd3efb6bdd04795f2e00eef893ba9db6c641724b4320eb59db72e821e00eacae80ac14ec93e79465b5dfe980b08c3e219e10a322fc6a99d984aa3a17ac3eb99a7d90cd400081b6b1e9c2e49f51572f7f000000000000002cf371ea6bd4c4ec685cb5f1e1944576a86ba1fb802e8228e5f58b56265448b08e1f2d780a33751c191bc1a169ff48b7256c2993e0bc717933110bd6383d6022fb98dde74b5ab0ecd85d1c8019b3b8c07c14da5e8c27dea1464f6fc6dfbdd6c0f4b271cd8e8de9884f86ed79b994b9ed88cf29836e05544d9b93bb7fc1e2c2c2fddcddc82f884d45aeb0ce7407d2577be2fe2f8098613ab2ad60b5032a13dd9d63a2407efe3fadd1846988c3a299fddc1186d14064c4aeeee77394eb10e65516559f522378718fd87e5514c8fe55366b2154c898a888dcbbde73ca9e0126d6ee8c27af7b9eda998ffa359f377ea61147a6c3197247f363596ad3d3d0d9282758b09339d02616828993b0855085ed4748e48c50f7dab9668a7dca419149596579bb01408b8f2afa2b4bada88efbc57b7a096065fe6cb148eaed8f3becd5c7287c19d8b8d9341c416f2716c7a6ebaff889cf1ce69c7f4bf117fe4aefad2a50526a28df87ac628879076fe3b857ea830f45cb702afb7c25a06abe4d2a754d0fb77ff30877884fda5755e1c1c02700bade0be10b3c75c0166e477992584dbe308f2136ef82f72391136424d14b3fe1c4ff4cf8ee3d4a30577aa377438a795ce1efe0fef1f6436644224f92b45b87ec346a63a4600abb2bbc572ea82333f56d942d0294230c7ea8cf24bcbab7de10a06fbf4b8a5e4bc88a0b4d676062a62d5042b5d88b0ab80962dfff7ad508e6580ec0e565541c713e4a854483788c4440ed3cb388bb2fcf71e33495d9729eaa4f3df7d9118ea8942720f5dfda14cc5e35cd1c648b1e295dd0984536f225043b7aa56f45b94959d83990e6050353c7681fd596fae2ad6b43b26aac3e6302691eb49a92ac075b0973cc230bf41a02ef123a80cf799a9cf2c472ab0b45cde3c980a092662b79a78e428b56b878c2c9d7d2f667205d07c040744781e9c27e32a133cbe9e219489d97bcae4b2ec4ec0839978daba24fa23bb89fa6edc2b1f929e127136e13d7ab140a240aec7006d0740d15ce77b028746549bb91bde24e341d6aaef7684082283943780105de76983bc8c5101001c3a3a5dfe282d11d70ba08237d0c23eecbdc4a0738dcd1d0e92649c64d1fc75f5d4b1ccd10cee6ed69f4f63f63d63b04a73fe9b0d95ec3d98d55429524a7d5dc83c878f9bff0744c3c3dac7513e665383d243302b985da0fb404dddbde640a4f389fa4c3fb9ea1c5f9d515a2ccc8f64c832aff4f136f99b4d917ed0c1cdede6ffe621e6cd136bc2d43fb680dff0c68099c9503f61d3640c8ab7e0e00fc4a83fb01f03024f4f5325c1fb55568bae34451d9363cdc81e46e97b1686ae29abc9b06c8b5c7e989d3ad961e7216588c01b58b29fb05c432a615d17a09e3adf06cdfdf3dd2283aaa8fc9399b7b1d83c595c27f27b0c43fa110727fa37634d748bad8737cf7e94fb2c07b9737c4576b58e746ff84bbc736f246a7a368af9bcc22ca05122b160c0382db54145a62832ab52e1db855a1b160ef5f619b49f1e02baac67b9b0e626ba6070806e70c82c2d7c3273cf8e90270481e7baa2b2b4dde1b355f71c38405ae3f4f20e53db5e1542091b7f01507410184c37574a9ac52e3d588311c12bec275849496e726f8190529c0a49a0e3e6f455202aaa85bd892385fe7109b119dc4b5f9d6f74b0d27e04b2b648769af58d288765be71b37989a5ac5ae732d9e2a12c722e285383500d13e00dc7d6a064a7b207427edd517b5d30ca905935dbffff61e10b84ca904e4b58ab3278b09d1a3af7e337f777393b93c0e84ae3eb61f87e8f1388622fa35fdd51868a3329cf2c05fcba3c7cbf6afe20466583fbb1a8fa5fefdef3f8340feeff8048a96a2bf7466dce009599d9290c3e091ddddbe3f2031ac6e4c5ae5cf7099f92dde452dbaea6df2ad42b0cf665b8e221206fec348a6e3a70de77d7f474b88e8d328009c8ee253caef981ae633705c28594d3da0ce0de71b21f1cf64ffa8a23f58164d60240e1252aa62de9da39247acc335c352a8724ee35770747b3baf2ad195811dd7b768054277f7e59984084c464d49d936d1c66f7eb006001104bb29906ed7a14ffd968315fcad150cae3d278da5c0b1c82a62da917c39114deddd5bdfbaec686968e8f1aae41a18121de00cb66e9cf95403ec3c47f9155482f2b586fdaa860ac2d3d47329b1d493480fa5c968f3908f56c3c4731df5baab9d67b7b2253e3965a783031979ab940db29a998af0ad8fb492a883a60df2b28462813f8030bf701ab0e779cbc175a7e8d60352352ebbad06f6f1fa8b7d642ce526043ea448fb8583f5ad9759a422a41e41d7b3a36f2fd3acbb63c4d59a719300c9820093262d6b7953ac6f90c270364c31e7295ed15d106cee1285fe71b446abcf7dcf3c0e275e4426bd4e7a57e93e7cf73e1372510d8e6a2048ff8780eda3223277a03eacb710cddfe510169064edbce166244de18084dfe2508159f889a55a67f083c558a9b77f733daff67179a2322b53179e0079c92bd7aebaea9c5340f3ab4b7cc81d51803abd09fcc33392063c34ce1e1a0e675adfdd4a492f5a45e96d2da3d4533c9591bba11ee5a7f8552bba7cdc68932f8f4583e0c8f72b064fc249e1be449f1d4e6c8faa0010000000000000ed34660c399113ca2e1af84335086124e5880174e4db34d7e82a81ad779a2abb3f6de2d6e5ed9e08855396579362285f40c6aba7fac5766b30caa1b5a3ca31935a45e124040a29b974de1cff0eca1b1ba280228bafa33d26d87f77abb36415122a0cf24e1525228ccca1f6873e67bec443c6fc46790d2af8029bc97719078956a3d3c897faf5b19beccc2b37813351bb8a0964a5f8cde403f162d4035b6743fdf93830888e6d0927e68c924de1ee1e6eda7de8348196a0e240b4fd629338d977b497c315662ab60b84797b733a931741f0f7ae88e608a9dc73ce5f2b075af61b6acb61f8fd475ae504f97723326778a75a37474e1cf7aeebc8baa20f2168d566c1cbfa0eba48c19297ed0036090a7989ef743211924453e79ea244aa18c85170c9aef0f4047332f8b35b47776723379273f292200f4a95c5a19ecd42eba114c3f8cab75937ae571eefd7d79368272db2d2db75a1951fba103340a092a7f7a11e6ed7aede39b6992f2163fddcd8998b1a51ce55edd4991bcf242545192c5da99577e6362b1a26c98ebdd7353b0a1ad10b5736faf60273485d0b7d8f9c6dce6538e5e8dac1b564bcf788efd488490736c1cc354758e6d394c77561e47c8c5de55c824dcef6c2ebb6e9e2c734ea05b56b5017f2447a2634099c1b9b09e061f6747e663dd92e0dc5eafa5eccc7e8d161c1e79f30230bb07dba9894fa6af1c66592cbbff937c01747ce5ca6b356f54f141420e38ae84b8ef505cb8e5a20933c463f48a70983996b72219e31cefc8a9485f6f5451deb8686bf1551de5b549da221a014fa06222265932a5dbdcca51d053482d30798e805c6c65808d72cca8d8aff611be639e7af32a8e9e92b2b83d59a081b86a7704b92ba6ea48259a31175760354ca8733a53ada1537a123ba7dd87b55bce95c238e30f19092f9585e8dd9053bad2c51385afe012c2dbd3c277c9e6689e907b907748964f38b9576ff9b88ec5f1961cdbe845c7e096061686ce822e34a2228227e934803ede4b984ac3e4ef28f0c0e24e0893e70d7d0f668c7d38a14b3b2ff87cae2d1fcf1c8db5c32d02250145fbb20cfb8b279baa4a12526484bdfe4d36d49a82db857b82a0e11a315ea2e298bc8b8a69f4f7545008a440ace5b2654872f3f569269a1144e946c90f904e48ba061c1a615e8cde0a4194a567e86041ac9fa4b42553e19147ef3185fdbc685da9b439f02a6a34d8858eff5d762d4970488508f194b7af38590888c70d69b9eec79e53497645006ec6658dda11a7898ae96c8bc1a54b48470dbd840f0fc68799019b5b4137dc5de49af82d12ff2f50033ee8007c7d9ef1ebb3d60fddcb9239508a858df67e6ad3ffe23acf973db7421777a6a2f23ac58f599d88487ad8515808de09a0f59aaad6ecd7ba190bae74968c49b63451fd68cb2b835db73f7e341587aec98e7618b9836b8e851cb31ba1a2a86d52cf167279f850d811a0209a3d4a9c54055ba189eefa40ea10cd6458e1ba09979a3bafd21c5837fe11c264dea2f529ad2ed6d19849f2e8c0fad613478cb66a6724091e4b2c56588793813b44745eb97e688f382026c85e87124a66f542bdb99fb7fcd874d34985353e74a166a9f1ad64c305912b2b6ec1423c15788fa6b2194e2be021f1deb0f1b3d44b3313fbc9a38c290cede3cba47afcd98a4e50d019dfb64214d9c18448c375186ae9cbc7df4614ed4b9ef760c9808a5698c81b1542bb08e4fc82bfaa01be44d5cda756d4111192661807d4f0ae852777642019dd45d876e2c3bfc3f0486016b3d763cbd9d899b3e00c7d3001e94ed8515f0ec9b9f1ed7b8df767103ef964acb4281a59f5cebf08cc14e5f5166b9a77a43e8a3ea75c3a6a8e56eea86eb2c861fcbee63d44e60a2dc88c726b8149380aaaca89e83433c919c53754a64f9d8fee3049a5ab750eb8191f7676cdf3257c9e0c661921049962b800a299e5f5c002629bf053030203b5925b0f782c8bc5982546761b4256dd7c37a99de97f1187190f3a1068c86eb7c54cb3ba99052518ddff6c2f5a3601808ebccb435889a32b844d663330dd2231d55cec6a2e6f880ac93dc383f0323f33f66cce427475e117054827db2ddee05696992299131d9621d5041a596c3e72d7b018c813c5e1f698381000d3efe1cf189e2f749047bed3c6cff9184f22b4f3b6368e4ed839802f31394207395f8b3758f3c93f640734ebd122b52739a610d85092beeb06e47d32ddbdb1ff4ae18c696cdb93f8169f5980b01ac14ff66fdbc7efccf6f572a58e1a05efb444510edbd59cfef4ad12fe842483a3178cf9c81bb43e9213a7a49339d9a4d8150b5f253f938e91b3801252ca80230a9eb6a15c048cf10e068c6bccdc756d7fa1cce0b1cb147325b435cb504e5db48c32bc68f74a60b8baae0dae80bc4cb1cf4856802868817de6e7345ed493ce177a3dbbdec2690d590a23e3feb49554dac882dd8b70d8b7128d7ba1fcb715dc8b18a2bcfae0bf0a0bb557eb6eae8bad4ce3ee4246398e304188b1dcac6ef8f5e251db9c29e0ddd58abd191c5e2a961fa3e09fbf5a540c7687fefa036743134bf7008f66f484fe72a812844385fccf500123ddce1c3628c0826250f6e2dbe51bb7f525261f64bed241d3ce57b7da9f91e0d6cea8b3b249b461a3bd0372b2a76758de3113532ab8ddb3188cec04333d8d8930673fa753cdda63376e388d99a995642c7c43859ddc8bdde9101a7ebab17d4894f75dacde90fa971ed682fec74e25bd782a6c56d8e5fedd9ceafb8a71afdbeda2bc8c52047c4918c1ca24846c83e1b94fcbae7fb12d01f425e799de44da53c08a063e1ed1c47cc2fb55235c1b305afd000ef8f8cdd7a6234a37198b7bd8acf59a52c325b34f76cf5879128463d3948b4c401d9c8c8b1ebefe4405252612148a2fc80edd07131faae7998ab5e42519b9d536e4a", 0x1020}, {&(0x7f0000000000)="f286a84d365450931351d56a392f125053e372a5", 0x14}, {&(0x7f0000001b80)="09b3a74bcc4c28d5", 0x8}, {&(0x7f0000003f80)="9160123d76061585eaf66ae5661e9ef1dcb68a5ffeafff2953cf2e1d8a09ae56a62de6211d18c47e0f3491f0ea03e6790e5c82c2e7d1212652cfacc7743261bc7250207396761e126a9d84b718819d4edbd78a680b79e1459388cd1540571bc7b6b22be82fdc23a0dea1e96238ef53fb6547dc8aaeb3c796eb7be3628b9ce4b2ad3af54bb93a7b609ec98c4fd6e6f40b78a136ec58ac977c0f03880adda9eccffaab3d25acbd77ff269c9d99d292846bbca602408217d66179330b08563d3a2d036050e08f5a632a2d9b8f4399eb7eba6d146046c29decb9837d0127d596bbf3fa47843a5cdf896c9f39db9bf43040c135b43dd710a612c93cbd250efd513478460b88afa894267d6d3b5caa4df2f742ff9f3e6be94897da6794576524701994971c7ef2dfed4f359e8504ee8e93001e9ff61410a2465cfddedb29910228dfc73c71e88be80ce1905310216847c784c3b3be3d4491d25c99901497a2c4856b2989ff73d183474a1870befe42a2236851fa6240071ab8abe4e31179c2f53e634e70a12583be24974f6f85153aa453611c0c8a03b2294a3b234c4ae161d9265cced961b0df5d4515c76984e5e4e15f50b23d890b2bfe7b6c30a6409a5b74fe5a4a8c036b93cd9fb91ea84271269c52f8222916306f23edd3000f7b41cc4b3a4e5fa88a5c2d7678f0227a3782b1f8d6864b7fd8c2e76eff5021235dc3aaf4995d721d6aabaacc97373a107af76ec2c2520e400fbc749f8dd479d0cf5da54c4a73e41270d0391963e0cb8542be65f43fb2538d605085c22bc116b371c9aa02811aa86bd54a65a4b6983168180a3be1560b526de700f1949bb32d5d9f38f6a5c6281624c6fcb44aa657468ffafafdc0637748df145f718082709de89edc894c517a0f7ee0835e1fde37ba18740263c5dbb872aaf3640c55df4ae91f1c4d8a6d060fd46d2cfe9928475da6c0d001f9e2777437a663cabc593f8aa84f3799263cfc27076568723a08221b4bd190a3d24bc7f9bf91698e19479435a59a8ca4fdc38005a55d1e61eaaa9e4d71c99bca17b34045c700de76b4d90df4ff250341605ae4a680f6bdfe6ea5e6ff77bec1f6963c790519181faa2ec1a2f9b16d1b824dabfcef556e91ef4bce02b702146012f691ca05e0f873b793d6051c6448876a93fcaf32ad9b129aad644b9761508e0cbdda42424f5ca9ac5a0cb67fd5ef8d26078c16cf525df596a885bb192168ba4a86e99c0827b56331e6fce281bfdbe7601e6dd9f80e645d073e5fcfb80f23ed8d6a1c4c6f1a0593f126a47bdc15964106058ba5a3f5e3937e4d1936709df941849452f2c9c392aa70906c85e0edba5772c67f4ea0fe3719344d03a358fb664d793c4aa54e216aa56f8cf2b407ff5d4a529911af166a61b7ed4c3ddee3a52bb0c74950249d112f60d18b35e6c199bbaafda43d0f0e1e29b0bed4faeed45e840be722bfab97e30a01e8fdea1117a6b8581d6a9497c3921d84b377cd7bc1a1f3df421fa0a31f196c9f011339a202c77d552d5e30df29ad6a54a02d0bc728969bcb38626a82fab1855df909acb56dbbbe1338015737b460b9085379f144f08f4fe6fbe9c9df241061196a35365a34eaf0c65f97d15c811b98869c4a49ddae0601994d545d202d856fb5e3c96921e56b80ec978feb36f5daef50f995dc3cad442da07de75b97f810dce38413e8cc64ce3d32372a5b7b08ee898f5fbb37c4cb70e8b555322af7968013968ab4d07441409a43d6c68dc5b5cc02ed048e6a296f1f735fae1874c921c15dc6c4422c87c803c1783b344f60f90a3d2efafad2938d8269bda4df1bb247b482f36c1713859723951d31241fe7b3fc4b7c3bf11f055de8365b2b69328e5755fbab9dfb0b03205b2e98dc059fa5487c37ce89acb18613cc62486ce09e75a72a8be009793b00c74e9adc2b93471102f16e83cc9ef0ac2c2b7cb5aa757a5d51cd7f6336151beaf55eabd134a6e6b93593a151653837ed5d494a03bcf061d63d7a8e501973506642f68d6b2d490490cdc9980a624714008335f98caa71d22e8651849caa054b5c119dd154a80afd2ae95506728c0acf02eecd8887b821c764a2be51ba755b9db883a75748d3c20c2205fbdd1ad4ea848883642e27adf313fddfba60f314a80a463f056179643abd18bf0454dc13dd799d25c244460d8d2619238bb5aebe667fb38048d9dc84242dbcb17ecdb64170bb6b80fd710f597cc96d081da2ba082ea62605bb3388f43d1849f8b80ce8f8dadaefa84b0cf5e12c2a3db678dc0859bf927320cf765fedaaefad94d0da4ab50368105e4b5981feeb3edef40cf25780b6b00752e4839a1f3e0c3def6e5233db0490dc8ce93dedf0d44a05d2a132a3649eda3ab5da9e7762edd08b83a8cf2e7d253a78fdddc2c6ce97cbff41532692140ffd82bb4249328d01a9878e3f59d7159c493bec6184cd3d71e9213b4b6f70a7c26404ecde93e81e897e497f3b44ee04bf394cbe8540a49d31e33aa875b0c0e43e0c6af30350c5b7992a08d8cf0b5a88f0e5b88b6da6de61c0d1b6289be8d9effcaadd6b62f47b7169092f07ac1b1469f52b4b2369fd2e0fae1bc43cc415586b11e4fcac1b4148d5e7417e3a0a0ba64973581546781ae2a069073a0a557ed02b2462a2f26ac44729308c2347f4a7d7032b521ff58a8d1b3f095c376216c44762c889ff33f4688ba61dd2f1da40892e49a0bc0ef08940af0352cd6393eb1aef2fe707b138ba8119f3907993810a70bc4f1625ee0618230b58016277b50f89d8a7b92601c697b9ee5915a8cdf0b0d6f23005bc29ad38f7f3a7085efa550ea390ec31873f999733b874242b1eb5dc9dd5a8deb0c14d37e250d98060bbc30e8b5e6155267b424cf16deea1c1b003407f1308f93e8fa0ed90fb3789c7b05a5c6cb65fd34df7555dc14ee95eebbb0b2f0d75e3bffe98aaf4eaad9d39ceabed5967907007aeaff27bb2d0f11cd021bf1adfea43f09a6860db43ee3be9e520399bfe1f4e53b9981ba8f27f1c5e81c63f5e3292ada5c1876436b1d2d5504ab0affda2663d82dfd368cf67113f6dc50db630cd05b71d340afda503c2076f8bdb0f7dfb915defc7c1c9231234ec1b9bc51c9fd412ca09d7b0fd44af63461ece300c5e13c97be28a46be7d7811b648aef748905a3edc10c9854c2019b8da98f39ddae20857a9e10c0e0d31d21732b4464e69a7427f947d0d1428d785238cbe29febfe78002738319659cecaf443da90ce463923c09849bcd23590513bf05b9a0030329d29422057bfad1e9201efde01056efb4338152a90f3958d92affc0d28026067b9fb53847c3eb773edc09361b824de631476c50a9536d3432204f02d55679966fdac3284f5a8e6bb1a0fa8765f1bdf044f58610340b4405c1865340ee14aa612738218e58822cea59b2233bde7f515dca110b5b69cd023c65fe76c05b3101d2cb8839179c19e1253eedd8aa49eec5e61a234404b5050d3ae406b39ef356a61b9b70ff362dacc91ac18bd993d3411624b33516f5ce027fd14b98b71a127f100d0cd7bc06650ffd79b5acbfd6ac8acedd641151f765effd984de0d56aff18d939839671669b2f46ceaaf178b40652aa0830a4d01899721f7ec0f80745a021c2f3ec6ae4c2aa9c94bb13f46cd5ae8790b3da1c0399de2f2832c9ddc7265cdb6564934420b3dae8a9d18b929f23ebf03603a3504894e9091122598eb58a97d6455c7290a8c1762596b926a00ef0c38559b91682e3bc67defa7bfbadd8834f154c195cfa545a5d2b61a1c70f70b22ba920d96e9d1be18cf02d20d506505c098a6cabc45b81120a18bf7dee36f092917cf01bb1b5cc29b1047abc682d28c28f692860e4397298be4d20b52c63221220b995054d2d1ea4f8b51000cc93612add83f113c6197398d4a16a4f385dd825df203540da118fda3b6f0ca27c77b32f6288994bd8f56e41be27b820aa82ccf105c535790d95617a3d4c2c8a7e0d379682375e081bf920b2a2df309cf6d1ae50f39769534d2a47f48b30e9b4d5cbce04c84b6173bc31c6e4a5ed3d5905e0107c6daa440ca612d99ec1ee118156af", 0xb49}], 0x7)
ioctl$TIOCSETA(r3, 0x802c7414, &(0x7f0000000080)={0x7ffffffb, 0x0, 0x80000005, 0xfffffff8, "0100000063026d00000100000000000000777d00"})
syz_extract_tcp_res$synack(&(0x7f0000000040)={0x41424344, <r4=>0x41424344}, 0x1, 0x0)
syz_emit_ethernet(0xd7, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0xc9, 0x0, 0x1}, @tcp={{0x2, 0x1, r4, 0x41424344, 0x1, 0x0, 0x7, 0x4, 0x0, 0x0, 0x0, {[@generic={0x2, 0x6, "96c72963"}, @sack_perm={0x4, 0x2}]}}, {"d1c2f0bfe2d0786ca28e44289f59aba04d62ff16e6bb47f1cd981d0cf5f225560531db5a3a6c3cb3d5ac50e0eec7423f3ef5e3c4a13f81f14f843a32b529e4649b57d581159522ddf03a6cabf358af4e1ae7ab79a9aac6417859ae29d8de08ba3da1e6387381a61f166b78d7ae58ccd15a08555c8e7db3e261cbba4f565ff3567edfcacd1a43a2f80b44a3727c2f46723f3826d9842357f4d4"}}}}}})
syz_emit_ethernet(0x12d, &(0x7f0000000380)={@remote, @remote, [{[], {0x8100, 0x0, 0x1, 0x2}}], {@ipv4={0x800, {{0xe, 0x4, 0x3, 0x4, 0x11b, 0x67, 0x40, 0x3f, 0x37, 0x0, @empty, @broadcast, {[@lsrr={0x83, 0xb, 0x2, [@rand_addr=0x7, @remote={0xac, 0x14, 0x0}]}, @rr={0x7, 0x3, 0xff}, @end, @timestamp={0x44, 0xc, 0x1, 0x2, 0x6, [{[@multicast2], 0x81}]}, @ra={0x94, 0x6, 0x80}]}}, @tcp={{0x2, 0x0, r4, 0x41424344, 0x0, 0x0, 0xa, 0x0, 0xffff, 0x0, 0x2800, {[@sack_perm={0x4, 0x2}, @sack={0x5, 0xe, [0x6, 0x3a247c0d, 0x3]}, @nop]}}, {"21136a477363509097fb04ceffd044c01eddd2734ed26571bcd41a45a275231c72125ddbe1a7beb968f64795a28c6b847a72ed19ed8eddb6141ed2bf813ea1ebb0423bb6e3133028a74aa45cb44772f989f9415001981b177c8191ada46110c4e5157ba136355999c9eda0e8fb43d6cab036303ab15109fe011b052dab6b02abb4e8984b515fe117de91915593ee42174bbb207f95e27709e6638f466d5c12d2c4b736c4dae7b4efb700a8074af0a882d5b93be797f324073d9889"}}}}}})
writev(r2, &(0x7f0000002f40)=[{&(0x7f0000001e40)="8e78dbebae5d90546f15d52a70c0d6c01f58a61f32323c0794131b931fec61639d2f39a6047225d023e386c4556448c215cf2412d15d80dbf9f84b8741dd0b85594b84517605a7a7397ed4fb170e22d274b430934323f2f4fb5606ef5596615f1483c475b95ef23aea27e3b7a7c35f66ed518b4f97d9fa5945621a1173a9e1e34a3761486699739b5dd0f87a0d15ddb90c5f0b6935666ed373a8123f5a6167a180b5021fd0acff9d9731a5bd60e3ec94e2b7771d82937d6c7ff1b9422fdfbfa590964ca5b01b1ec5b60ef0bdd0be043b45cf8d18a5e672cff3c0aad2f41623f7ba3ba28c9b2419a3492b027f5169f1c7a49d496800dc3655536d25fd59b9cc0aa0d3bf78ad55f60a9ed41e1bb19b1c13d2d39a03a32123e8c58bbbd8603eaf87c9feff40795f8ef85e2c71683f9b14eefdc5e1d5c634c796cb911a58d83b20ec6e38ea7ffa40bfb8663e568765f8dd8d20143f82711d82d74b2d81b884ef21822818bd82a0920bb8c5b6e58e7aa743bc6b19728a785d2dd1b13ed5f5d3b903b3060c45f45802", 0x186}], 0x1)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000080)=[{0x5}, {0x87}, {0x40e}]})
syz_emit_ethernet(0x6e, &(0x7f0000000000)=ANY=[])
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000001c0)={0x3, &(0x7f00000000c0)=[{0x54}, {0x61}, {0x4000006, 0x0, 0x0, 0xfffffffd}]})
ioctl$TIOCGETA(r3, 0x402c7413, &(0x7f0000000140))
writev(r0, &(0x7f0000002500)=[{&(0x7f0000000080)="ebebfd510bbcd3a9b489e989c13e", 0xe}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000300), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f00000003c0)=[{0x2d}, {0x15}, {0x8106}]})
syz_emit_ethernet(0x3e, &(0x7f00000002c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x2, &(0x7f00000000c0)=[{0xc0, 0x5}, {0x16}]})
syz_emit_ethernet(0x6e, &(0x7f00000002c0)=ANY=[])


mknod(&(0x7f0000000000)='./file0\x00', 0x6000, 0xe02)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
writev(0xffffffffffffff9c, &(0x7f0000000040)=[{&(0x7f00000001c0)="f007426c6a7984d37bf078", 0xb}], 0x1)
r1 = socket(0x1, 0x5, 0x0)
ioctl$VNDIOCGET(r0, 0xc4104603, &(0x7f00000002c0)={'./file0/file0\x00', 0x3f, 0xead7, 0x7f})
ioctl$FIONREAD(r1, 0x80206979, &(0x7f00000001c0))
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x3, 0x10, r0, 0x8000000000000000)
pipe(&(0x7f00000001c0)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
getppid()
mkdir(&(0x7f0000000100)='./file0\x00', 0x0)
mknod(0x0, 0x0, 0x0)
setreuid(0xee00, 0x0)
getuid()
getuid()
chown(0x0, 0x0, 0xffffffffffffffff)
setreuid(0xee00, 0x0)
unveil(&(0x7f00000000c0)='./file0/file0\x00', &(0x7f0000000080)='r\x00')
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
geteuid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, 0x0)
pread(0xffffffffffffffff, 0x0, 0x0, 0x0)
ioctl$WSKBDIO_GETMAP(0xffffffffffffffff, 0x80047476, 0x0)
fcntl$getown(0xffffffffffffffff, 0x5)
syz_open_pts()
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$DIOCMAP(r2, 0xc0106477, &(0x7f0000000280)={0x0})
ktrace(0x0, 0x1, 0x0, 0x0)
poll(0x0, 0x0, 0x0)
syz_emit_ethernet(0x3e, &(0x7f0000000040)=ANY=[@ANYBLOB="aaaaaaaaaaaa00000000000086dd60004b0000082b00fe8000000000000000000000000000aafe80000000000a"])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f00000001c0)=[{}, {0x40}, {0x106}]})
syz_emit_ethernet(0x62, &(0x7f00000000c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000240)=[{0x60}, {0x54}, {0x46}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])


socket(0x0, 0x0, 0x0)
r0 = socket$unix(0x1, 0x1, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
setrlimit(0x8, &(0x7f00000002c0)={0x42})
syz_open_pts()
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000695000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f00005fd000/0x1000)=nil, &(0x7f00006ce000/0x3000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ff7000/0x3000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f0000473000/0x1000)=nil, &(0x7f000068e000/0x12000)=nil, 0x4000000000}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000545000/0x1000)=nil}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000069d000/0x4000)=nil, 0x8000000000000}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ff8000/0x4000)=nil}, {&(0x7f0000ff6000/0x7000)=nil, &(0x7f000015a000/0x1000)=nil}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f00002f6000/0x3000)=nil, &(0x7f0000ff3000/0x2000)=nil, 0x3}], './file0\x00'})
socket(0x2, 0x2, 0x0)
r1 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000180), 0x80, 0x0)
r2 = getpid()
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000300), 0x800, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000140)=[{0x1, 0x0, 0x0, 0x9}, {0x7c}, {0x416}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r1, 0x80105728, &(0x7f0000000240)={&(0x7f00000001c0)=[{0x3, 0x2}, {}, {0x26, 0x800}, {}, {0x45, 0x9}], 0x5})
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
ktrace(&(0x7f0000000040)='./file0\x00', 0x2, 0x40000214, r2)
open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
semctl$GETPID(0x0, 0x0, 0x4, 0x0)
socket(0x0, 0x0, 0x0)
mknodat(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)


mknodat(0xffffffffffffff9c, &(0x7f0000000400)='./file0\x00', 0x2000, 0x0)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x11, r0, 0x0)
ftruncate(r0, 0x8531)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0xffffffffffffffff, 0xffffffffffffffff}, 0x0, 0x0, 0x0, 0x0, 0x8000000000000000})
r1 = socket(0x18, 0x2, 0x0)
close(r1)
r2 = semget$private(0x0, 0x1, 0x300)
semctl$GETZCNT(r2, 0x2, 0x7, 0x0)
geteuid()
mkdir(0x0, 0x0)
chdir(0x0)
mkdir(0x0, 0x0)
chdir(&(0x7f0000000380)='./file0\x00')
r3 = open(&(0x7f00000002c0)='.\x00', 0x0, 0x0)
mkdirat(r3, &(0x7f0000000440)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//file0\x00', 0x0)
unveil(&(0x7f00000004c0)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//file0\x00', &(0x7f00000000c0)='c\x00')
unveil(&(0x7f00000003c0)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38/\x00', &(0x7f0000000200)='x\x00')
setreuid(0xee00, 0x0)
r4 = getuid()
setreuid(0x0, r4)
unveil(&(0x7f0000000300)='./file1\x00', &(0x7f0000000340)='x\x00')
semctl$GETVAL(r2, 0x0, 0x5, &(0x7f0000000440)=""/206)
r5 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r5, 0xffff, 0x1000, &(0x7f0000000000)=0x1, 0x4)
bind$unix(r5, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r6 = socket(0x800000018, 0x1, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "1a1116fbd0f700ff000000002000"})
setsockopt$sock_int(r6, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)


syz_emit_ethernet(0x4e, &(0x7f0000000400)=ANY=[@ANYBLOB="aaaaaaaaaaaa7fd67572210786dd6007558300183701fe8000000000000000000000000000aaff02f0"])


setrlimit(0x8, &(0x7f0000000980)={0xb, 0x4e})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f00000000c0)=0x5)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
select(0x6c, &(0x7f0000000000), &(0x7f0000000040)={0xfffffffffffffffe}, 0x0, 0x0)
writev(r0, &(0x7f0000000080)=[{0x0}], 0x1)
poll(&(0x7f0000000140)=[{r0, 0x4}], 0x1, 0x0)


bind$unix(0xffffffffffffffff, &(0x7f0000000040)=@file={0x0, './file0\x00'}, 0xa)
sysctl$kern(&(0x7f0000000040)={0x1, 0x4e}, 0x3, 0x0, 0x0, &(0x7f0000000180)="76b0353a558bf248c78c8502fcf9fd08fa1588f254df98bdc2703864ecc0ce3671c0907259201eb7cb962ee12d9706a2d4177565da48e3cdade50516597f477ca5ea18253c1441678346ddaa98e46b28e2226a296c0fd773959eaad9d65d33cdbf523a06ed457ed3e00f52851f90c14f54ec03a2a5ff8d88b9", 0x79)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000040)=[{0x44}, {0x61}, {0x406}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


lseek(0xffffffffffffffff, 0x2, 0x0)
setsockopt$inet_opts(0xffffffffffffff9c, 0x0, 0x0, 0x0, 0x0)
socketpair(0x0, 0x5, 0x0, &(0x7f0000000380)={<r0=>0xffffffffffffffff})
syz_emit_ethernet(0x2a, &(0x7f0000000b00)={@local, @remote, [], {@ipv4={0x800, {{0x7, 0x4, 0x0, 0x0, 0x1c, 0x0, 0x7, 0x0, 0x0, 0x0, @broadcast, @local={0xac, 0x14, 0x0}, {[@generic={0x7, 0x6, "11ab22ca"}]}}}}}})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x80, 0x0)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000140)={0x1, &(0x7f0000000040)=[{0x61}]})
fsync(r0)
open(&(0x7f0000000180)='./file0\x00', 0x75f493fec6515f78, 0x0)
r2 = openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x8981, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r2, 0x80105727, &(0x7f0000000080)={&(0x7f0000000100)=[{0x21}], 0x1})
r3 = getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r3})
pipe(&(0x7f0000000100))
setreuid(0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x2, 0x0, 0x20}, 0x4, 0x0, 0x0, &(0x7f0000000100), 0x4)
pipe(0x0)
ioctl$WSKBDIO_GETMAP(0xffffffffffffffff, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
fcntl$getown(0xffffffffffffffff, 0x5)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r4, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000240)=[{0x7}, {0x50}, {0x6}]})
syz_emit_ethernet(0x66, &(0x7f0000000100)=ANY=[])
ktrace(&(0x7f0000000140)='./file0\x00', 0x4, 0x0, 0x0)
semop(0xffffffffffffffff, 0x0, 0x0)
semctl$IPC_RMID(0xffffffffffffffff, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000440)={0x4, 0x18, 0x6, 0x9}, 0x4, &(0x7f0000000480)="9b0209c3218b07fcfe4189c99e805e6e84d356960798a692992117d6728436ba1bd87f42e3303eac3846528d050712f838130efce33f523ba44765f5f6915b2227390ed95bd9dc6d4dc7f149d4d6d06a3f23616e773302d9cae75e39a5a11e32e0e6ebd635450b2eba540af7f2aa5dbfbdd900a0dad2b74f50acd76b5c567049ef436dbea0d7562f52955af8d4ab84c513252ddd139b5f5cd5c2bd02adc7f1fe850c00000000000000062ab475cca257352828a76e5334be562995e894238b96ca5d4d3e670fa0cc791dfc4415030910fa64eac9b4e8aa9bef19525cb6f7e8570be65bb7ad3fe963cb9a8bd949ee334db1ccf73db06b5947b3e88aa810f8ed7cca10ff0d0000000000001345daa49507756f49775275ca390b94e85d5a95b82000b9429c25483a9275d0da3b561c6adc3c141f26040000006b436218bdbdc9ac0a623855e941dc1872fcb045e0d9df1ecc6357ee21e2b0802cb60edd0300723235f06715e7eecc3e0760c70e1dd7873e27142bbae1a7e44de453a073fe3426f334b80f043ba9136d57c799353d46dd81439b111a511a288bee5dfb2e353e3bb073e3342273216b07e49ca4df0fd2dbe9a8eb377010ee678aad0bd8c7fb7d82693a096344671843a1f2082612b2ff237c6e505ff5f5ba932954d73c630fd2791f833a1da5af0704f687e196f4f7859e071fc98111cc9024f790ce16ceaa427d0104e39789d91000"/528, &(0x7f0000000a40)=0x210, 0x0, 0x0)


sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x29}, 0x4, 0x0, 0x0, 0x0, 0x0)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
msgget(0x3, 0x640)
pipe(&(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
write(r1, &(0x7f0000000080)="c7", 0x1)
write(r0, &(0x7f0000000200)="8a06a6efc0a912cc7debe87fd48abc37b3e8171e1ecb39804f13519b1892004f03189f184d7413d29d3d50bef1888136e2a64fe08b9eafef88ed36519f0fd218438a05642c964591548735ad50e2f426dd5b46a40485f8df92de77b6de8c107ebaa0414993da5671304f7b4400a6757eb6b09bdd98ca607b86655667447779e9e89bccccf815c229", 0x88)
openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
close(r0)
r2 = open$dir(&(0x7f0000000100)='./file0\x00', 0x10, 0x0)
write(r2, &(0x7f0000000000)="424b60e63cd1a69ff72b2921f047bcb9400a4a413422c8ace7f58065c06161cae932e6a275299c35ce9bc0fc", 0x2c)
r3 = socket$inet(0x2, 0x1, 0xfe)
write(r3, &(0x7f00000002c0), 0x0)
poll(0x0, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
r4 = semget$private(0x0, 0x2, 0x81)
semop(r4, &(0x7f0000000180)=[{0x0, 0x3c, 0x1000}], 0x1)


open$dir(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
sendto(r1, 0x0, 0x0, 0x0, 0x0, 0x0)
recvmsg(r2, &(0x7f0000002880)={&(0x7f00000014c0)=@in, 0xc, 0x0, 0x0, 0x0}, 0x0)


mlock(&(0x7f0000ffa000/0x4000)=nil, 0x4000)
writev(0xffffffffffffffff, &(0x7f0000000080)=[{0x0}, {0x0}], 0x2)
sendto(0xffffffffffffffff, 0x0, 0xfffffffffffffce0, 0x0, &(0x7f0000000080)=@in6={0x18, 0x3, 0x0, 0x1ff}, 0xc)
socket(0x800000018, 0x1, 0x0)
r0 = semget$private(0x0, 0x7, 0x3c0)
semctl$GETPID(r0, 0x3, 0x4, &(0x7f0000000680)=""/8)
semop(r0, &(0x7f0000000280)=[{0x1, 0x7, 0x1000}], 0x1)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x1, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000040)=[{0x1}, {0x25}, {0x16}]})
write(r1, &(0x7f0000000540)="76e5dead6f01f8607d2100000063", 0xe)
semop(r0, &(0x7f00000002c0)=[{}, {0x2, 0x7e7}], 0x2)
semctl$IPC_RMID(0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x1, 0x200}})
r2 = socket(0x18, 0x3, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r2, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
r3 = socket(0x2, 0x3, 0x0)
r4 = socket(0x18, 0x2, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r5, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x28}, {0x5}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])
dup2(r4, r3)
setsockopt$sock_int(r3, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
write(r3, &(0x7f0000001680)="04bdfa5d1d2873c63e3534825ba166e2fea9aec43050006123339a346f731573d8d508753f95b7688ad48b8cf6bbca325cebc37fc4e1dd543dbe2da6dd", 0x1001c)


mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140))
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)


pipe(&(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
write(r1, &(0x7f0000000000)="af", 0x1)
r2 = getpid()
fcntl$setown(r0, 0x6, r2)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
write(r0, &(0x7f0000000340), 0xd4e688a67930cd)
close(r0)
write(r1, &(0x7f0000000040), 0xfeea)
execve(0x0, 0x0, 0x0)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xfffffffffffffffe, 0x0, 0xffffffffffffffff})
fcntl$setstatus(0xffffffffffffffff, 0x4, 0xc0)
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000000), &(0x7f0000000040)=0xc)
r1 = open(&(0x7f0000000100)='.\x00', 0x0, 0x10)
mkdirat(r1, &(0x7f0000000340)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38/\x00', 0x0)
open(&(0x7f0000000040)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//../file0\x00', 0x0, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket$unix(0x1, 0x2, 0x0)
getsockopt$sock_int(r2, 0xffff, 0x2000, 0x0, &(0x7f0000000040))
getsockopt(r0, 0x29, 0x2c, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f00000000c0)=[{0x4}, {0x84}, {0x406}]})
syz_emit_ethernet(0x36, &(0x7f0000000400)=ANY=[])


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_DEL_MFC(r0, 0x29, 0x69, &(0x7f0000000200)={{0x18, 0x1}, {0x18, 0x1}}, 0x3c)


r0 = socket(0x11, 0x3, 0x0)
setsockopt(r0, 0x11, 0x3, &(0x7f0000000000)="03000000", 0x4)
setsockopt(r0, 0x11, 0x1, &(0x7f0000000200)="12000001", 0x4)
ioctl$TIOCFLUSH(0xffffffffffffffff, 0x80047410, 0x0)
syz_emit_ethernet(0x3e, &(0x7f0000000040)=ANY=[@ANYBLOB="aaaaaaaaaaaaffffffffffff86dd606aa63f00082b00fe8000000000000000000000000000bb00000000000000ec"])


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
bind$unix(r0, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
close(r0)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
setreuid(0x0, 0xee01)
r1 = socket$unix(0x1, 0x1, 0x0)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
r1 = socket$inet(0x2, 0x2, 0x0)
close(r1)
r2 = socket$inet(0x2, 0x3, 0x0)
dup2(r0, r2)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000200)="ea00000000000000", 0x8)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, 0x0, 0x0)
setsockopt$inet_opts(r1, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0x8)


mknod(0x0, 0x0, 0x0)
close(0xffffffffffffffff)
socket(0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
setrlimit(0x8, &(0x7f0000000980)={0x9, 0x54})
r0 = socket(0x18, 0x2, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
connect$unix(r0, &(0x7f0000000140)=@file={0x0, './file0\x00'}, 0xa)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0xc0}, {0x74}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000001c0)=[{0x6c}, {0x7}, {0x6}]})
syz_emit_ethernet(0x66, &(0x7f00000004c0)=ANY=[])


writev(0xffffffffffffffff, &(0x7f00000002c0)=[{&(0x7f0000000080)}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
select(0x7, &(0x7f00000002c0), 0x0, 0x0, 0x0)
execve(0x0, 0x0, 0x0)


getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000001c0), &(0x7f0000000200)=0xfffffffffffffe50)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0206923, &(0x7f00000001c0))
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r2 = fcntl$dupfd(r1, 0x3, 0xffffffffffffffff)
ioctl$FIONREAD(r2, 0x8004745d, &(0x7f0000000200))
r3 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r3, 0xc0206922, &(0x7f00000001c0))


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x1, &(0x7f0000000140)=[{}]})
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)="000001ad", 0x4)


setsockopt$inet_opts(0xffffffffffffff9c, 0x0, 0x0, &(0x7f0000000000)="01", 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
r2 = dup2(r1, r0)
setsockopt$inet_opts(r2, 0x0, 0x200000000000a, &(0x7f0000000000)='\x00', 0x1)


r0 = socket$inet(0x2, 0x3, 0x0)
getsockopt$sock_cred(r0, 0xffff, 0x1023, 0x0, 0x0)


mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x0)
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, 0x0)
r0 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
select(0x0, 0xfffffffffffffffe, 0x0, 0x0, 0x0)
getsockname$inet(0xffffffffffffffff, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
r2 = open(&(0x7f00000003c0)='./bus\x00', 0x10, 0x0)
pread(r2, &(0x7f0000000000)="2beba8c5bfaaff44b437dfbb000000", 0xf, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000200)=[{{}, 0x0, 0x0, 0x1}, {}], 0x0, &(0x7f0000000300), 0x0, 0x0)
socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x101, &(0x7f0000000480)=[{{r0}, 0xfffffffffffffffb, 0x43, 0x4, 0x10001}, {{}, 0xfffffffffffffff8, 0x69, 0xf0000000, 0x0, 0x2}, {{}, 0xfffffffffffffffb, 0x7b, 0x0, 0x7f}, {{}, 0xffffffffffffffff, 0x40, 0x2, 0x1}], 0x6, 0x0)
openat$wskbd(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSKBDIO_COMPLEXBELL(0xffffffffffffffff, 0x4004570c, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, 0x0)
kqueue()
setsockopt(0xffffffffffffffff, 0x11, 0x1, &(0x7f0000000200)="22a807a2", 0x4)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x8040691a, &(0x7f00000001c0))
socket(0x18, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000029, 0x26, 0x0, 0x0)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
ioctl$VMM_IOC_INFO(r0, 0xc0185603, &(0x7f0000000000)={0x97, 0x0, &(0x7f0000000180)=""/151})
sysctl$net_inet6_icmp6(&(0x7f0000000100), 0x5, 0x0, 0x0, 0x0, 0x0)
sysctl$net_pipex(&(0x7f0000000180)={0x6, 0x1b, 0x2}, 0x3, &(0x7f0000000080), 0x0, 0x0, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000002c0)={<r1=>0x0, <r2=>0x0, <r3=>0x0}, 0xc)
ktrace(&(0x7f00000001c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x4, 0x40000200, r1)
r4 = syz_open_pts()
r5 = socket(0x11, 0x3, 0x0)
sendto$unix(r5, &(0x7f0000000000)="b1000504000004000000400001000000331c13fecea10500fef96ec0c72fd3357ae30200004e301ac20008acf20b6604be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abeba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)
getsockopt$sock_cred(r5, 0xffff, 0x1022, &(0x7f0000000100)={<r6=>0x0, <r7=>0x0}, &(0x7f0000000140)=0xc)
fcntl$lock(r4, 0x8, &(0x7f00000000c0)={0x0, 0x0, 0x5, 0x801000100000008, r6})
r8 = getgid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f0000000300)={{0x7f, r2, r3, r7, r8, 0x2, 0x43}, 0x4, 0x9, r6, r1, 0x4, 0x3f, 0xcf, 0x9})


pipe(&(0x7f0000000300))
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
r2 = socket$inet6(0x18, 0x3, 0x0)
getsockopt(r2, 0x29, 0x2b, 0x0, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
ioctl$BIOCPROMISC(r0, 0x20004269)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
setitimer(0x0, &(0x7f0000000000)={{0x0, 0x8000000000000000}}, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = dup(r0)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7949)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
writev(r0, &(0x7f0000000280)=[{&(0x7f0000000000)='#!', 0x2}], 0x1)
writev(r0, &(0x7f00000002c0)=[{&(0x7f0000000080)="dccd5872e57ab75ac39f155c97fc8c20200a", 0x12}], 0x100000000000030a)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


mknod(&(0x7f0000000500)='./file0\x00', 0x1000, 0x0)
symlinkat(0x0, 0xffffffffffffff9c, &(0x7f0000000140)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/file0\x00')
r0 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x8020699d, &(0x7f00000001c0))
r1 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r2 = dup2(r1, r1)
syz_emit_ethernet(0x126f, &(0x7f00000000c0)=ANY=[@ANYBLOB="aaaaaaaaaaaa00000000000086dd609ded1a12390000c4a4e3434e58d025a6a8a81cf312b8befe8000000000000000000000000000aa00030000000000000101000101000401000401000103000000000100010200000000c7ab6f1eba08bf03d1805fce0ef2ab82f4a065245eccda108bec7cb23f632c993265a4cefeb77b1406d562a47d4b0054943553278b519ed107f62b5c352f8e68d83c1fd85b8e1083556d7fa2fc09a3e823fa940de6ef1b18ddb2a2dba0d2d9c1b44b20ed3a932a2c47f4f4d3e34ea1b67a607001a4541a87d5d347b5049b3444dc2b7abe3499079a5701e88493acb2eb1808e8b1f74311083f93341607915aa46325934e81b672d809cb6bc5f3d64480ba4db4432a67c2548e"])
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r2, 0x8020699d, &(0x7f00000001c0))


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x4, 0x0, "0100012d29fb000700000000098002005a00"})
r0 = socket(0x18, 0x2, 0x0)
accept$inet(r0, &(0x7f0000000000), &(0x7f00000000c0)=0xc)
close(r0)
dup2(r0, 0xffffffffffffffff)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r1 = syz_open_pts()
close(r1)
r2 = syz_open_pts()
ioctl$TIOCSETA(r2, 0x802c7414, &(0x7f0000000040)={0x7fff, 0x0, 0x1, 0x5773c5b9, "5b349b96a0a1000000faffffff000000ff597bd6"})
writev(r1, &(0x7f0000000000)=[{&(0x7f0000000580)="014acc63235d305ac1b376c7c19b51e46eb6626c5ff5ba4b4c76811c1f68612cb2fb24b2a9ae4c00574c75b56fdf69e4b95f490d13ae5b4a", 0x38}], 0x1)
close(r1)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r1, 0x8004667d, &(0x7f0000000000)=0x43e10e0f)
ioctl$TIOCSETAF(r1, 0x802c7416, &(0x7f00000006c0)={0x0, 0x0, 0x13, 0x0, "5238f0980ba4b32494000000002fd505aac10fe3"})
writev(r0, &(0x7f0000000800)=[{&(0x7f0000000280)="be", 0x1}], 0x1)
poll(&(0x7f0000000140)=[{r1, 0x86ef6a69ee17bf91}], 0x1, 0x0)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0xfffffffc, 0x7ff, "1a0e0ad5e4a52a829bb82f36b921aab39b58505f"})


semctl$GETNCNT(0xffffffffffffffff, 0x3, 0x3, &(0x7f0000000000)=""/4096)
r0 = semget$private(0x0, 0x2, 0x9)
semctl$GETVAL(r0, 0x4, 0x5, &(0x7f0000001000)=""/253)
r1 = getgid()
semctl$GETZCNT(r0, 0x3, 0x7, &(0x7f0000001100))
sysctl$kern(&(0x7f0000001140)={0x1, 0x3a}, 0x2, &(0x7f0000001180)="1ba048e65ca1eb17d10b3c1d4474941094b1bf33ad02f1ecffa9abafce038fd84791cad218c6d1d8a6d57bd51d3c0aaaba2a60e2846dc53a8bac127ff88a877e152ff7a362d90aa635a1bd02bf8b0739e4049e7bc4629be50c303d4d2c538223a8f977672f10a97920a2cce5db8adda66d3230d485dda4ae5b8253d92cc4b94b37863a13e635848f4031e759eb52d21f79cbd06281898b497a43e5c2bff34cbecba7c303d541eeb2e5416f501b1dacf6a6f1", &(0x7f0000001240)=0xb2, &(0x7f0000001280), 0x0)
semctl$IPC_STAT(r0, 0x0, 0x2, &(0x7f00000012c0)=""/74)
r2 = semget$private(0x0, 0x3, 0x0)
semop(r2, &(0x7f0000001400)=[{0x1, 0x335c, 0x1800}, {0x6, 0x4, 0x3000}, {0x4, 0x5, 0x800}, {0x2, 0x43b9, 0x800}], 0x4)
r3 = openat$pf(0xffffffffffffff9c, &(0x7f0000001440), 0x800, 0x0)
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f00000014c0)={0x1, &(0x7f0000001480)=[{0x100, 0x1, 0x9, 0x400}]})
r4 = shmget(0x2, 0x3000, 0x21, &(0x7f0000ffd000/0x3000)=nil)
r5 = getuid()
r6 = getuid()
r7 = fcntl$getown(0xffffffffffffff9c, 0x5)
r8 = getpgid(0xffffffffffffffff)
shmctl$IPC_SET(r4, 0x1, &(0x7f0000001500)={{0x7, r5, r1, r6, r1, 0x1, 0x800}, 0x10000, 0x33, r7, r8, 0x6, 0x7, 0x8001})
sysctl$net_pipex(&(0x7f0000001580)={0x4, 0x23, 0x2}, 0x3, &(0x7f00000015c0)="2e946f5e06b465610938e0741f7d4a9ad0c42ff894fb677ed63c84dd407c151eddfab29501c7d48e0e8f6ce33bdbdb98f7104debb11b6c9d490e880e85a3aebcf98cc6c388c1127e980f604bd20f3efab55e79dc75db7d5b7fe95867a535511db972b6ec35d2ccb1248eb4afbb88380d9c6e7a9028d8ab65373ac21b0fa322ee53070ae3309f21556a6c46bfa86d0cd7ddded7c03a4a845d4c10406820867e383ce3c7e2b528e5d1739ac32a91264efc0dbc076624ebdafa68d06a5a4a39215799df6c1cc684a94f3c50409777f747a8f7bf8010c6f5ae7df0c5b332d432580c0f37be7dd94ef7c1362db89d834191417d672c10c66b3af0e3710b4f70466fed8afeacad908f845481de51184d3f8b53b6745c505843ee6ba86010bec207b03845d19edb0c359d8d544aca79d992169dc10a08fe2c2091c7e9b94fbb189c080636c6e3b5d3a55eddb8684590b103962136e4a279ad4406017f3bd8f27aae76eea593deff34c994227fab7598b3d5bea3bd24d1e3dedc87f3fd2532dc8cc0680b87d03f9e47689ffb22886ac8935503e94a69d35f32616a7d9a15f56fa00038537faf1795f920355d2103f5420c3b4e05f07f6deae063be9b3e918c784bd9f1e4d0c86909f44c186a025a802bf9cac6eed5d0fd8b4591679781cb010a4275ca7f4a153cc8d5993a85d95447bfedaad356c7c1af9a36573f6edb684776bc70a5d52841be321035f764ec0b8a6febea3ba0fe2471562b1a12895d921b3479bfb1bb949554f813836294a50f64e095458b9e7c7fc62a12d91f0b7a4a090835da21cae49061231efe580d2c483a411a05041dae067d956746dc170dc14720b6d0e7c4b5a542a82d12a610395faff86fc54947b2d48c72fa9c486b5e0388b515c8f49b9d6fb9d3aab26b968369096db76859601bd5bbf1b9b306e90aab97f06b4112fc75102d5b2145df028cfb60c87fdffbeeb1f98c8c70767bb5467a6a9b775d590878a66ba3bdac15e32af240470083e78e534b5892e1a0b250a4c5768fcf1cb819f5dfb42e2b66e6d204c78aa9784e4ca75e21d676135af6879519bd68456ce210398fa464c31b28b3099f93d99d0b6db2922fa7e21dea2f60355766d4a90c41d57f6b4138dbd46a4fd99e2a922cc067a87a15a61aeec100525959423812ed519bd63bfd9f780a9b553832e78c49c71c9f3110a1278f58ef3c7e3798ab8789f38e1b5ab40d25eb9a5df55ed9946042249d3911f69bec1b7d4e70491e72ff20fd8f1951af98a797299cb5297d62472b66b5a6a66ee5f33c7a544fd2252109bf6e9026ff8a8f961891bf52503b49f4016348e0188ada9f27465f3e65eddb76f6cda0818ff8c0560598fa60bb121e713501172c498a4a7f44a012085ccfcd07698f6e5e92e99ffa819bd4d80f8d09e4d2050383c93fe68f95e381e7f9372baab0a2cc5675b7cf9748b7188b8b5cc9a49471d390a77984c882b766449517deb38eef3d7afc399b2f365432bab5825f9f6ffa17a67df786c9426ceb1bdaa86c08f63fb1beb7dd7cb42947daa7a01830e2e644195d85d633f7b77877be80a9a4fcee9d45e0f042b15c87bddc4809a78495c32af2b38db1df283775f8f01093525411feb8338d0a0a1f4eaf235ed529b4b78bbf7a0edf7cc272c7a3a4e6bf31b23c69f64b4607c98de44c49a69d8a143f270ddd1c96a495f1d5732f9e809970f219dbc618ee23c1b7ed45387fbfed5d5da1bf3d7f740e02f35c9f71f7fee87128e665d19f86e61c35fdebdb247c12ca873660caab431a83a253016ba67f7000f94bf6ce7b14b125602c6f98707c48c2b70ba59f53c5e202284613fdfd92f527d327fd9dea7afb4a3731de65e15985dc18629a1c4288d38e1b3be186f9f73145517c5889f0f75aab22ecb01471b3a68321bb549e9ed3952ef1d6aab1dcf364095e9cc5f67ea801ea994f206a8116515946af69a12f7588d3609b8ce7f233aede5090d799aa5df4c58cb493864e961aa3bf13bbba79cdd9a8f8cb20a1087da10d3ba2092795b50c7ff4cc0d1cdbd7ce4c7b795908285be72f59e5d488c8de36369cc91b9cf9774ab1badd70d125fd5a2ed0353d79ff2ae5bfaed36b94a9c9dd605d7e9f4f57d123a7aa8b863b27217b4bb9544d1b7745f5cc107177402af7a133d347a4f0f0aaceaa1abbe5c0bdf6bbb9f4faae3faf939e8bc58872ced6d56a2338aed84621e3bea3592ddf0d5db9a51399092914c9340445ca7bd2f06e3e2952e382f1097bd57273899dd7b65f09853a2924815b0dba37413bb7d031fc6aebd12dd25d20f5138a64c5398dc33c67502eadf30e9886252286b21b0786af172e300cd59fa71c2cae240296f0bea2a7b60e7ec08bee3f27557b8fce217fa1293f86abb5526d7930ab565c2212fa48a995d1f022e623841a8b4076ac4485da5c80724869179ee8189d998ce0a2b0d1d285bacb5ff30d4f862829daf25368c13590ad82e233f6ac8d34efdffc838ef37ef29117e93d195d364de519712e2a21e6532e88224a98617f0f82b15dbb1eddb40be15be124c1869440c07f8deb83415767aed3d0c1c62ed35456790ac1f18dc332c8c5f8eb58ba2fe6b1fff89fd70c462acefaffdbc89baf513942b556f66c8008b088444c9d4c955914c68b087e36cf0a7e8520f3fc6fbedf976daa4f40ae442da3ddd371b1e6d816b2abd8378b56328f2456aa90f812827059b89081e9e034f34792a7f1e130efbbca5fe41ceab6d3ed088ad6497ce699d377683fe3923247ad60410053f1410e5e9c2c07d3efeeadb2f46eb51864cc850425909617c69b2cb5c722b20b461371ebfe3518c895e380b0d64aa3f99e6b444bb4dd6d79a1ffdbd94fc13d9dacc486362dbbff9e8c0b958b2e332110d3cf6ab542b2278e0a01f033cea8e12a73f448ae686885e583fc13eaa7ab767d1d38d046fb9ef05e10809c8537e31149c0f113930229e49f6aba6b23904664474229ded7903d8533c6f88792e322481a520e917c61aabaf581ed0eb4dcf72d343d471b4074d0ac4cc674f289fe793460a2900d4aa420df79251518686651b5199295a47b6fe08ae69544fb45282d80bf5a2d16c83bd58a81f0280987d7c984b06cb7a2624467379a7bf43b0e162c0c3157361ddb0e2f3871dffd1e19da329f204904cb7324d6b9cb0f573edc60e87c4e9f8aee0cb741971dc7ddc95cc29cc15a2773c295ee9425d76a3d998e2f96d69238c5c0c0db83feec1acb3e62840414ab16dd6fdc924fcefae636a1677b501a4494ed5aaa2beff6ac686682627c38bf7f138b91e23a490b35b75582ceb6079f84cda461fa21edf1582045114a071a1707f54d260372ffac7293e8adfc3b79847ea57977c4f1026bb055ad4bb51a056de07bd11d132dbe65d8d336f8f00fbe1cefbbd288dbbf02bb2f8e1ddba05dcf3afb8f76e563c3afe1d106e948e12d5e3d0ed4c27b557b677f61f2dc6ec9402709485a0a7e500bf02c80ee7030b9101b1621fd0210b729d070b6d14bfeba94371f09a11515b548b97f791f232ac1f6aea45007211b7e1efc0d442141e662330b78756022fa48c448c280fefcd010ee698ea28b172e8cf5d2b0108d3e2aa11905e05278d29937281a66901f62789ea3845805ec253c0b099a23bde894e896d531697e101af27f3ac207bd48951c49842e430593847790175211a019370658185a003def12f015d88f669357fb1e600b45b7c4cb7c8453bf729d397e2974dc305d89574d0f2eb976189076b245e1195dfc30e0d4c480867cb2a4e9d5e7219f9b863c3a288c198379af60cbb02ba213846e18fbeca309e88da74f4b8c710dd82792a68037b2990c92019a465a7a6e52ec88415b56eb86e0fac5e6ad6dfd250db13e4f546918428487d51c362ac3d4fd33c898c299ae5fbad52832a48f388c9012acc837e6ab9c8a5ea9e3a2891d870e90b3cad2a277eb351e4ec9b2a80784a8da7319fb5a2d7a73f42c6d2b04c84c41ce2537378895ada767618c468d3d7c53d143a5a209b89960e2c26533152770497e527f0908ff27aac1d1e0ce9a11f1dee645896a79551a65243d2a7bddb3c535eeefec3803b0d3cb99d67c815e965da3651ff0cea13b5916a38d6c846f1f90ef2d4aa11e45a7ba5aa86dc5f9dd34a85d511c7c446c66a6bad087e85b3e57b5d7a63a0a09de89863b706b088011c275aa2d9b760e4912a67ce73a1ae2343a6e4952ac104cf9af778a0efeb1f0f4a53089585969bd2d74ffb39f609ebae366ed34cbce2d0b27f1f402864205aa53066432cc6dc327387e122369b7fa388ed819b9ef4fba9cfa610118f1de0bd57ff7e7c83599fb25dc21c7f6264acfb723d9c194c3f19517fd6ae5a34364e23f760383e078ed2fd84c9e4af660e6dbab6ab8fe73017694acc32536b75def078675fb89a354f6c8e02c0348ebf28352deca6b22e04874e81482a7e10f38d44db7ba0755df3bce41640a9ce8fbe600679be4d6340127be25ddf3de4762b1c74b551958b6662197c8b2393827f41daf2b0e8ef97e2c8c95220fc9e4f7bd0de128019345afce31a778fa1ccf9f5ecad7fe607c2f2281efe45f418bcd6665ef8573990ba8169ea6db045d5c2768eea39f756336d5bf8e86883a3e81adfb7c65444973a1040688bb0708569741756eb2e70db6d5f619e9a0e568afca42669fcbb80386aa9cb1414b96cff24f936d94198c256550ed4ad35077f552106201c2bc0df83db448e673d31346fe3040ef6c795f9b0d034b00b6a811afc987ac58201e938b6ae4f6481120c9ad7a5860af9561409290a4fd091a561ec96b581739663abb36fbe64f14fd53616f4242fc1ad63ca5005280064923057206cafab8434f5d7246f5d9602a0644cd602f958c3f292416fa607c89a134b9a0a1d1b160e2e8c5fd7ec61f80d8657215009c64e3491bfa375d06b5587b9dbd1ddf7baaef9a383547585df6dad388a1e0b2017de4e309f35b0ae2b89c9844e948fa49041682115c69985298de3311ab02cda6a52868cb044da088cb56dcadc3c511e7df1d7ce5d9bb681e784ba0468416f3b2c171bf4edae59b37c018e503ee5ce3c8a1c61e7c93ca7d1a0b8077a22dba3422c61016a0235ac7dba3a27db141011e6df0244376af7f0aee13677dcc246b38e84799cfc2d818cb1a43feb03760da66a7db5978a1736c1611888bc53fb35243a68c200d60b109735ad4a7e4d7eee8796dad28a05d3b1fe4775503e6c211344b536945aea435381eb1add8d42b7cd97a2454cc449c182c9d6f5b052df52b8181cdd5fa4bd46c18dc4931426020d95a2a824346f282f048ee170e0a38b66cff82ea1792eb80399ce33c342bdbfb46c6bea6dfc44694d13eb0233b6e03b9dbb2fa33822c0b9fc18777274c160bbfa6ce12968a9ce675ac2c4f33cd7a250e543cc02db67f7c47bdd81ce54e9bcd902be4587e7f27d6aed44d7ea7e0d7b78cdff2b93ff00ab5c21b082eb3f0ca0efd2b67f8b6d0c28c7ce46dce68e0a92b38b94a57b6ae6593f55ebd36e0e52d501eb28d1b032bae399b7adb9f76b6f440fccd30cdb53b49ed912e99d167ffd25e15b6a8a554098ee2ca6da94628a3bb1ab7eb35e7a9ae9c951abdd62ce7c356b98fd3c1fdd200c266cd37c0a302a7f5e9f4f52a53d2840361a5ddabbd416c651f8414f4edd9e50f608590a313c298463fb482499d6d7e5d1d2e28f09a6f1e572e3d2973ca7ca25be248f28092bc9c5e3220c8a7f554331eed6babcb9e2daddca3bd5a7c83ab936414d19c3f4d97a7247b7dd5a66a777ad4", &(0x7f00000025c0)=0x1000, &(0x7f0000002600)="33048b4918e22c33b76a", 0xa)
fcntl$lock(r3, 0x8, &(0x7f0000002640)={0x1, 0x1, 0xffffffffffffffff, 0xffff, r8})
openat$bpf(0xffffffffffffff9c, &(0x7f0000002680), 0x8000, 0x0)
semop(r2, &(0x7f00000026c0)=[{0x0, 0x1}], 0x1)
r9 = getuid()
r10 = getpgrp()
r11 = getpgrp()
shmctl$IPC_SET(r4, 0x1, &(0x7f0000002700)={{0x4, r6, r1, r9, r1, 0x8, 0x6}, 0x53b, 0x186, r10, r11, 0x2, 0x7e80, 0x180})
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000002780)={'tap', 0x0})
r12 = semget$private(0x0, 0x1, 0x40)
semctl$IPC_SET(r12, 0x0, 0x1, &(0x7f00000027c0)={{0x3, r9, r1, r9, r1, 0x46, 0x2}, 0x0, 0x8000000000000001, 0x9})
sysctl$net_inet_udp(&(0x7f0000002840)={0x4, 0x2, 0x11, 0x6}, 0x4, &(0x7f0000002880)="e4cbab2bbef8e9b650720845cdac2b4af917a0b98d", &(0x7f00000028c0)=0x15, &(0x7f0000002900)="99d161ffbdf3374628d62011f0e978311de1898a5ea4a7f674a0f3c8a09b2df29b1373f49d6693f55926a70fc0513d61e77102d0a9aa6da05fd46b160fd5f4a56aff1a857991da4154fa7a", 0x4b)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x1, &(0x7f00000002c0)=[{0x6, 0x0, 0x0, 0x7ff}]})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000340)={'tap', 0x0})
syz_emit_ethernet(0x36, &(0x7f00000003c0)=ANY=[])


r0 = shmget$private(0x0, 0x1000, 0x0, &(0x7f0000003000/0x1000)=nil)
shmat(r0, &(0x7f0000002000/0x2000)=nil, 0x0)
shmctl$IPC_RMID(r0, 0x0)
symlink(&(0x7f00000002c0)='./file0/file0aaaaaaaaaaaaaaaaaaa/file0\x00', &(0x7f0000001280)='./file0\x00')
syz_emit_ethernet(0x66, &(0x7f0000000080)=ANY=[@ANYBLOB="ffffffffffff000000000000000000000000ffff"])
r1 = socket(0x800000018, 0x1, 0x0)
seteuid(0xffffffffffffffff)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
setreuid(0x0, 0xee01)
shmget(0x1, 0x2000, 0x221, &(0x7f0000ffe000/0x2000)=nil)
semget$private(0x0, 0x0, 0x0)
semop(0x0, &(0x7f00000000c0)=[{0x1, 0xffff, 0xe5ce97ab354d96be}, {}, {0x3, 0x0, 0x1000}, {0x2, 0x6}], 0x4)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
setuid(0xee01)
socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206980, &(0x7f00000001c0))
r2 = getpid()
r3 = msgget$private(0x0, 0x0)
msgctl$IPC_SET(r3, 0x1, &(0x7f0000002f80)={{}, 0x0, 0x0, r2, 0x0, 0x0, 0xa})
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892}, 0x1c)
open$dir(&(0x7f0000000380)='./file0/file0aaaaaaaaaaaaaaaaaaa/file0\x00', 0x0, 0x0)


r0 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
mkdir(&(0x7f0000000500)='./file0\x00', 0x0)
mkdirat(0xffffffffffffff9c, &(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
renameat(0xffffffffffffff9c, &(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', r0, &(0x7f0000000240)='./file0\x00')
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000300)={<r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f00000001c0)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000000)=0xc)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r2}})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4e}, 0x3, &(0x7f0000000100)="71f95f84cf71b59c7afec37582", &(0x7f0000000080)=0x2, 0x0, 0x37)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = socket(0x18, 0x3, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0xb, 0x4e})
r1 = syz_open_pts()
close(r1)
syz_open_pts()
ioctl$FIOASYNC(r1, 0x80047469, &(0x7f00000000c0)=0x5)
writev(r1, &(0x7f0000000180)=[{&(0x7f0000000200)="1900c983bc080089a43c5356a1ba699f85af8189f282097564d6085b8d1c5ad4653b7793e17f55bb087b46871c054bc156dec5e8eb8fa578bca8f7deef3089880d6a4c172bde731ecf018aee3bd9fb3df20ef0164ac9411bd43ba598", 0x5c}], 0x1)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r2 = syz_open_pts()
open$dir(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
symlinkat(0x0, 0xffffffffffffffff, &(0x7f0000000080)='./file0\x00')
fcntl$lock(r2, 0x8, &(0x7f0000000040)={0x2, 0x0, 0xfffffffffffffffc, 0x1000300000000})
fcntl$lock(r2, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000003})
r3 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r3, 0xc0106924, &(0x7f00000001c0))
ioctl$FIONREAD(r0, 0xc1206951, &(0x7f0000000100))


open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x144, r0)
seteuid(0xffffffffffffffff)
lstat(&(0x7f0000000380)='./file0\x00', &(0x7f0000000280))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x24}, {0x1}, {0x8106}]})
syz_emit_ethernet(0x36, &(0x7f0000000240)=ANY=[])


mkdir(&(0x7f0000000040)='./file0\x00', 0x0)
writev(0xffffffffffffffff, &(0x7f00000002c0)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe2c63a56077123a276d3ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
unveil(&(0x7f0000000080)='./file0/file0/../../file1\x00', &(0x7f0000000100)='r\x00')
unveil(&(0x7f0000000280)='./file0/file0\x00', &(0x7f00000001c0)='r\x00')
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
openat$null(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x80206913, &(0x7f00000001c0))


r0 = kqueue()
r1 = open$dir(&(0x7f0000000240)='.\x00', 0x0, 0x0)
kevent(r0, &(0x7f0000000000)=[{{r1}, 0xffffffffffffffff, 0x6f}], 0x7, 0x0, 0x0, 0x0)
mknodat(r1, &(0x7f0000000040)='./file0\x00', 0x6000, 0x0)
unlinkat(r1, &(0x7f0000000080)='./file0\x00', 0x0)


shmctl$IPC_SET(0x0, 0x1, &(0x7f0000000000)={{0x0, 0xffffffffffffffff, 0xffffffffffffffff}})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x2, 0x0)
bind(r0, &(0x7f0000000000), 0x10)


mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
pread(r0, &(0x7f0000000000)="b5", 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000280)=[{0x60}, {0x15}, {0x812e}]})
syz_emit_ethernet(0x56, &(0x7f0000000000)=ANY=[])


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f000002f000/0xd000)=nil}, {&(0x7f0000060000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000000000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ad4000/0x2000)=nil}, {&(0x7f000081b000/0xf000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000156000/0x1000)=nil, 0xffffffffffffffff}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f00004c1000/0x2000)=nil}, {&(0x7f0000148000/0x1000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
execve(0x0, &(0x7f00000002c0)=[&(0x7f0000000100)='tap'], 0x0)
r0 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r0, 0xc028698a, &(0x7f0000000100))


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000004c0), 0x2, 0x0)
writev(r0, &(0x7f0000000380)=[{&(0x7f0000000180)="e741a883cc60157a810468823ac987a7254eba680c54664b8a3b537273fff1c3d4ae6950f3d030e3dc1c729ce1bb4d0e7dec57876947d3d26f8d356150f6b052bd44cc7280c8724198c173f70a712dceccc05077889f297affadcde5f1ad9e2d5363aa93bb37c6c73e0f4f8ad07537aaf9bcf3cfd30353113487589d60233184c0fd43e9f38537079fa1f0d832f277395d0802b941d2040dc8b180d9fbdc6e39334ccf08067c7cdaec5fe52f5a1c9f211fa896ff7dac6b76218c8fa7f1536311341abb6206ffda9672f479bedcb7c67ecde88e3728cb5761b35435", 0xdb}], 0x1)
execve(0x0, 0x0, 0x0)


connect$unix(0xffffffffffffffff, &(0x7f0000000040)=@abs={0x1, 0x0, 0x1}, 0x8)
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x3}, 0xc)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x67, &(0x7f0000000140), 0xc)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000200)=[{0x40}, {0xc}, {0x406}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


r0 = socket(0x18, 0x3, 0x0)
getsockopt(r0, 0x29, 0xd, 0x0, 0x0)


r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x800000018, 0x1, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
sysctl$vfs_ffs(&(0x7f00000000c0)={0x6, 0xb, 0x81000000}, 0x5, 0x0, 0x0, 0x0, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x1, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = socket(0x800000018, 0x1, 0x0)
ioctl$PCIOCGETROM(0xffffffffffffffff, 0xc0107005, &(0x7f0000000080)={{}, 0x0, &(0x7f0000000040)})
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{0x2}, {0xc0}, {0x2006}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


ioctl$PCIOCWRITE(0xffffffffffffff9c, 0xc0107003, &(0x7f0000000580)={{0x0, 0xf9, 0x4}, 0xc11, 0x80, 0x5})
r0 = socket(0x18, 0x2, 0x0)
r1 = socket(0x18, 0x3, 0x0)
r2 = socket(0x800000018, 0x0, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000040)=0x7, 0x4)
r3 = openat$zero(0xffffffffffffff9c, &(0x7f00000005c0), 0x80, 0x0)
shutdown(r3, 0x1)
write(r2, &(0x7f0000000500)="16a9717e51ce65966e15cb088f303c11e1fe579f37dd5cc232645d3723299d9a3c4413ccafb398c05676a02c7de9a13276412f5e12ad2d89c2ac1e906847418993e7c9fb7fd236aaa0f3bf35699f0bfa1adcb4fd1b8547a8015b2c6dd43b146d450efb6d3a5adfc4895cf3666d", 0x6d)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
write(r2, &(0x7f0000000300)="8cf2403336335b48ff86cf1ef8d639b65c302eac1f72a4c6f55da01c64f861f62f1a66a1573c6f5ee702ada92298e7363bd99b3be08e3246afc508e52c6f444fa8c2b61d3e3a437f0e4a8bda5eb3518b6f03eb161132798a174faed4a50a70d946a6f4100d1ac93cf9558e62ad8d248d756bb27005d478ba0e93a7eca4b092774e6a925debcb81bf2eb3e06275b40f5f95a00e984617caba6a35cefc9e989dfb50056e0754e9c4e2cac100a44df9a8653257817c0ee26481f326839e74f71d06c57c6e803f8965ae97d67f179b149ca05865f49b753cabe97359051b81c82f0128f025955145bf6e8d130e4d0ada6f27", 0xf0)
setsockopt(r1, 0x3, 0x40, &(0x7f0000000200)="0f3f4c6d7d8a6b613f6caf56388bc010d48d5a98305cf9ce49d712d33ed9621e72bd234ab31cf06d14953bb6d4a1de9524f3b217f56fa044e30e18b3120033d5c9196f6d42c8291e4d3f7540970f9d3dac5f5e90b062118345427ee738c9da6389957b39474fdbd7970047a3661b6bec1b8718df4cfc72d06afbfc95f7165461add645ffdc5f39ed12e674ab667a97cedb1290a2f3b56ab1126c5e5c38e0e8d1a23c94ddb1914d42978e200b0ebbd3d75583604021e021e68691d23985a2c68bf8c80f823197fb82c159ec6b", 0xcc)
setsockopt(r1, 0x1000000029, 0x40, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
setsockopt$inet_opts(r1, 0x0, 0x1, &(0x7f0000000400)="b9416348eb829fd182c71bd2327a3212ae5089e5be4e3dcd34f3461e5e26c7e1a8e6cf75467e1ec846baa1aaea679a0448b0dd0188224455676abd614445f71b33c404ed7fe09d88ea4f27e8a2cbdc559ca3f64522e89e52f98f4699c9fd477508352443af6e8e02195c945738b5bb8e7df68efc7ba9b6eeefac3b83436fb50605b2ed59e367727f164cfeabb1d22ca4ebe99e306837ba4aa4ef9c06687710d19e4dfdc133a1fcaa56fc8ebc6a120f578eb79059a7d71690155af4993c2ac69b15a54663d8fc60ff2c3e9f9d9b3f454e13fd2ffc7c55ea237b0c21b582e4235f91fabfec19fc3ac0e690fe3d09d885d518850473cb68b2a32309b9948a6975", 0xff)
r4 = openat$null(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
fcntl$lock(r4, 0x9, &(0x7f0000000100)={0x0, 0x0, 0x80000000, 0x100000000})
setsockopt$sock_int(r4, 0xffff, 0x1008, &(0x7f0000000000)=0x8, 0x4)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
accept$unix(r4, &(0x7f0000000140)=@abs, &(0x7f0000000180)=0x8)
msgsnd(0x0, &(0x7f0000000100)={0x2}, 0x8, 0x0)
r5 = openat$null(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
fcntl$lock(r5, 0x9, &(0x7f0000000100)={0x0, 0x0, 0x3, 0x300000000})


setsockopt(0xffffffffffffffff, 0x1000000000029, 0xb, 0x0, 0x0)
syz_emit_ethernet(0x2d, &(0x7f00000002c0)=ANY=[])
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x1, &(0x7f0000000140)=[{0xfff8}]})


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000002c0), 0x1, 0x0)
ioctl$SPKRTUNE(r0, 0x20005302, &(0x7f0000000000)={0x0, 0x80000002})


mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x0)
r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b10005016000009f0000000000070000001c130500000000fef96ecfc72fd3357ae380b37b673039d2d236acf60b7804be78164991f7c8cf5f882b297be1aa5b23edeb51e2f0ac3ebbc215000000eeffffff028ea8af630037282102000000720fd38bfbb770c1f572c881ea772ec5920400000000000000361b12578ea8c500002002fbff0c2300008abfba0900000008e371a3f8343712051eeab71d89e0442c5e520000800420000000000000000000", 0xb1, 0x0, 0x0, 0x0)
open(&(0x7f0000000140)='./file0\x00', 0x400, 0xc)
open(&(0x7f0000000100)='./file0\x00', 0x615, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
getrusage(0x0, &(0x7f0000000300))
setreuid(0xee00, 0x0)
r1 = getuid()
setuid(r1)
r2 = socket(0x18, 0x1, 0x0)
setsockopt(r2, 0x1000000029, 0x27, 0x0, 0x0)
syz_emit_ethernet(0x3e, &(0x7f00000000c0)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x30, 0x0, 0x1}, @tcp={{0x2, 0x0, 0x41424344, 0x41424344, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0, {[@sack_perm={0x4, 0x2}, @window={0x3, 0x3, 0x5}]}}}}}}})
r3 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
writev(r3, &(0x7f00000000c0)=[{&(0x7f0000000040)='#', 0x1}], 0x1)


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1003, 0x0, 0x0)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1000300000001, 0xffffffffffffffff})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x40001ff, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r1, 0x1000000029, 0xc, 0x0, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


socket(0x0, 0x0, 0x0)
msgsnd(0x0, &(0x7f0000000140)=ANY=[@ANYBLOB="0300000000000000a60d524ae979b5a3e111c8cac1b119e4db1e444c9d4eca7af32596137392f4cdc50d82caa6fa7ffd0da455fa2e9f5109d4ccbe9ddd5e3674e689a6714f0ac2ee9e36ae12821cff35f5866888d441f7c29189271982efb7cd9c94766d1c4be0efcbf44d5d0010dc9df78616b167b260dd96322bfbad5f46f92beb4126cf5ffee44ca5b5bdfcf14c9b3003f53d57d96bcceb3c014f4d7b36a32f1fdb2d7783fa77ede48c3db7299ec5e58a1348d1f8200a241f24ffa673bd7cb93b55b31a3045a1501250df6302a6bbfdcb68febcf98e7aabab17c9e7683a114b35681c98d31a241159997fa2408bccc3081d1feec2142247dcd0e3ab8a8ab390b2a70909b2f114070000000000"], 0x401, 0x0)
msgget(0x1, 0x0)
sysctl$vfs_nfs(&(0x7f0000000180)={0xa, 0x2, 0x2}, 0x3, 0x0, &(0x7f0000000240), &(0x7f0000000600), 0x0)
r0 = socket(0x18, 0x0, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x3}, 0xc)
ioctl$VMM_IOC_READREGS(0xffffffffffffffff, 0xc028756b, &(0x7f0000001000))
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {0x0, 0x0, 0xffffffffffffffff}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ioctl$VMM_IOC_RUN(r1, 0xc2585601, &(0x7f0000000000)={0x1, 0x0, 0x1, 0x0, 0x0})


mknod(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)
ioctl$TIOCSTOP(r1, 0x2000746f)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0x1cc45f45, 0xffffffc3, "070000010000fbff00e6ff20a1ec7500"})
poll(&(0x7f0000000040)=[{r1, 0x1}], 0x1, 0x0)


mknodat(0xffffffffffffff9c, &(0x7f0000000280)='./file0\x00', 0x1000, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
readv(r0, &(0x7f0000000740)=[{&(0x7f0000000140)=""/144, 0x90}], 0x1)


open(&(0x7f0000000100)='./file0\x00', 0x78e, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x1928, r0)
pledge(0x0, &(0x7f00000000c0)='\x00')
pledge(0x0, &(0x7f00000003c0)='tty   \x00\x02\x00!\a\x9bp^|#\xcbhl\x97\xa3_\xbc\x04\x9d!\xd9\x9f\x9f\xb4\x96\x13\x12\xe0\r\xe7\xb9E\b\x00\x00\x00l\xaaY\xe1Q<\x19\xc0\xf6Yf\x9au^\xa0\xc9j\xdd-I\x01R\x00w\xf7\x15\x04\xa6\x82aY\x1d\xd7\f>Y\x06\"\xad\xb6\x88_\xeb\at\x91\xd3\xbf\xea\xddt\xe0\bt\x06S,\xdbH\xa7-\xaaw\xcet\x044\xc5\xa9e\xa9\xf6\x1b\x8e\x05\x86\x91IsC\xb9ul\xaeu\x94\x9b\xaf\x04\xc4\x03\"F\x8f\xd5\xe8\r\x8d\xa1\x00\xcc\xd7\xa0\xe1\xeb\xc1>\xbd\t\xc8\x15\v\xb0, \xee\xa4\xa6\xb9a\x01&\xadrj\xd5\xc26p\xa14\xe0\xbf\xa0\x1es\x01=\xdbd\xf0?=<l\x8c\x01\xe3\x05$\x1c\x04B\x00\xa4P\x04\xcf\x87\xaa\x96iP\x14{4\xe6\x87\x9d\x8f\bz9$\x10_\xd8E\x93\x92\xf5\x8au\xab\xf9)\xf5\xa6\xc7\xc8\xed\xb9\x1f:\x03K\xa2\xdbUshx\xbe\\\x19\xdax\xeb_\x10|r\x1e\x06p>\x8afcJ\x8eYEn\xd4<\x00\xec\xe4^\x00\x00\x00\xca\x90\xfa\x98\xc9gty\xce\xab\xd2\xa1\x85E\xe4\xa9\xd5\xab\x83\xda?w\x83\xbc\xcf\xd20(L&b\xed\x8c\x1d\x1a\x9fd\x99H\x9e\x82\x10\xea\x05\xf8\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\xa6\x8c\x05n\x83\x83\x12+\x16\xc1\x00\x04\x00\x00\x13:o\x0f\x1fB\xa4\x00wB\x92h\xde\xfal3\x88e\x04J\\\x00D\xae`\x8e\xadd\xa8;\xee\xc4K\xe8]\x84\x90\xb8d\xfb\x95\xb3\xe9(x_\x80]\xadW\xd5\xa9\xaa\x03\x9c6\xa9\xc4\x01\x03\xea\xe5\x90\x85\x16\xb0DV\x13\x01\xab\x01\xf0\x8f\x02\xc2\xc8\x9b\x03\x1f\xd7\xdbN\\\xc0\xcd?Pg\xd5q\x13\xbd \xfa\xab\xccJK\x11\\\x16~#P.\xc9K\x15r\x04\xd9Z;\xc0\x8dOze\x96\xe9\xc3\x93\xed\x94.\xc2\xa0\x1fU#\x96\xe6\xb6C\xfa\x03/\x8b\x0e2\xec\x96v\x9b/.\v\x9e\x80\x18s\xae.\xf4\x14KS`\x87\x8b4\t\x00\x87{\xa8@e\xbfe\xeb\xee\xa2\xe72\xb8Q:\x9f\xc2b\x897\xbe\r\x04\xdf\xe2\xc0\xf0FV\'m\xcbm\x80%\xfc\x9e\x9f\x87\x80A\xbe\xc2\x00\x00\x00\x00\x00\x006\x96\xbb\x9f\x85\x98\xbb\xbc;\xaa\x97c\xfe\x82jz&t\xa7\xc4\xcd\xb0\b9G\xcag\fY\xe6\r\xcdT\xd3\x1c(\xef\xc0\x038\xbd\xdd\xd9\xc9\x93a]q\xd2\x9b\a\x1e\xf8\xc3\"\xc8:\xb8$\x9f\'P\x17\xfa\xf3Xa\trB-\xf2g\xe6Z\xd5F\xd2\x80\xe0\x99\"\xc12\xe8\b\xc58\x00')


mknod(&(0x7f0000000200)='./bus\x00', 0x2000, 0x202)
link(&(0x7f00000000c0)='./bus\x00', &(0x7f0000000100)='./file0\x00')
unlink(&(0x7f0000000080)='./bus\x00')
mknod(&(0x7f0000000200)='./bus\x00', 0x2000, 0x202)
link(&(0x7f00000000c0)='./bus\x00', &(0x7f0000000100)='./file0\x00')
r0 = open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
close(r0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f00000002c0)=[{0x64}, {0x80}, {0x8306}]})
syz_emit_ethernet(0x416, &(0x7f0000000740)=ANY=[])


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0x0, r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0xb, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
r2 = dup(r1)
setsockopt(r2, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


setrlimit(0x8, &(0x7f0000000980)={0xb, 0x54})
mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x0)
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
r2 = dup2(r0, r1)
ioctl$TIOCCONS(r2, 0x80047462, &(0x7f0000000100)=0x207)
r3 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(r3, &(0x7f0000000000)=[{0x0}], 0x1)


r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0x2b, &(0x7f0000000000)="8c740b72", 0x4)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x7fffffff, 0x0, "fcdc81d0ee4a1466fcd1ce667f3e3fb6c4547a05"})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x100000000000000, 0x10000000000001}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
sendmsg$unix(r0, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000140)=[{0x5c}, {0x60}, {0x40e}]})
syz_emit_ethernet(0x2a, &(0x7f0000000200)=ANY=[])


sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e", 0x57, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x29}, 0x5, 0x0, 0x0, 0x0, 0x45)
shmctl$IPC_SET(0x0, 0x1, &(0x7f0000000000)={{0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x3f}})
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x2, 0x0)
bind(r0, &(0x7f0000000000), 0x10)
syz_open_pts()
syz_open_pts()
socket(0x1, 0x4, 0x0)
select(0x0, 0x0, 0x0, 0x0, 0x0)
select(0x7, &(0x7f00000002c0)={0xfffffffffffffffc}, 0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f000038b000/0x3000)=nil, 0x3000, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
socket$inet(0x2, 0x2, 0x0)
recvmsg(0xffffffffffffffff, 0x0, 0x0)
getuid()
setreuid(0x0, 0x0)
socket(0x0, 0x0, 0x0)
fchmod(0xffffffffffffffff, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, 0x0)


setrlimit(0x8, &(0x7f0000000040)={0x7, 0x9})
r0 = syz_open_pts()
close(r0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x2, 0x0)
mprotect(&(0x7f0000ff9000/0x4000)=nil, 0x4000, 0x2)
clock_getres(0x4, &(0x7f0000000000))
getsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0))
sysctl$kern(&(0x7f00000000c0)={0x1, 0x50}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0xfe10, 0x0, 0x37)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSRSIG(r1, 0x80044272, &(0x7f0000000280)=0x7fffffff)
r2 = socket(0x2, 0x1, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
dup(r2)
getppid()
getgid()
r3 = msgget$private(0x0, 0x0)
msgsnd(r3, &(0x7f0000000280)=ANY=[@ANYRESDEC, @ANYRES64], 0x0, 0x0)


r0 = socket(0x11, 0x3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f0000000000)=[{}, {0x0, 0x0, 0x0, 0xffffffff}]})
recvmmsg(r0, &(0x7f0000000440)={&(0x7f00000000c0)={0x0, 0x0, &(0x7f0000000580)=[{0x0}, {0x0}, {&(0x7f0000000000)=""/96, 0x53}], 0x3, 0x0}}, 0xb, 0x0, 0x0)


sysctl$kern(&(0x7f00000000c0), 0x2, 0x0, &(0x7f0000000080), 0x0, 0x0)
r0 = socket$inet(0x18, 0x3, 0x102)
r1 = dup(r0)
connect$unix(r1, &(0x7f0000000000)=@abs={0x0, 0x0, 0x0}, 0x8)
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x287e)
close(0xffffffffffffffff)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
dup(r2)
mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000001380)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x205310)
r3 = open(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)
rename(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000480)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
ioctl$TIOCEXCL(r3, 0x2000740d)
rename(&(0x7f00000006c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000580)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mknod$loop(&(0x7f0000000a80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0, 0x1)
rename(&(0x7f00000007c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000a40)='./file0\x00')


kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
r1 = socket(0x2, 0x2, 0x0)
r2 = socket$inet(0x2, 0x3, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x1, &(0x7f0000000240)="01000000", 0x4)
r3 = socket$inet(0x2, 0x3, 0x0)
dup2(r3, r2)
ioctl$FIONREAD(r1, 0xc0206923, &(0x7f00000001c0))
r4 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r5 = fcntl$dupfd(r4, 0x3, 0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$FIONREAD(r5, 0x8004745d, &(0x7f0000000200))
ioctl$FIONREAD(r0, 0x8020690e, &(0x7f00000001c0))


socket(0x0, 0x0, 0x0)
r0 = getuid()
setreuid(0x0, r0)
r1 = socket(0x800000018, 0x2, 0x0)
setreuid(0xee00, 0x0)
r2 = socket(0x18, 0x2, 0x0)
close(r2)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
r3 = socket(0x800000018, 0x2, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x104}})
r4 = socket(0x18, 0x1, 0x43)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r4, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
setsockopt$sock_int(r3, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r3, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, 0x0, 0x0)
open(0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
msgget$private(0x0, 0x0)
getpeername$unix(0xffffffffffffffff, 0x0, 0x0)
openat$null(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
rename(&(0x7f0000000080)='./file0\x00', &(0x7f00000000c0)='./file0\x00')
mkdir(&(0x7f0000000080)='./file0\x00', 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000380)=[{0x5}, {0x4}, {0x8106}]})
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x20, &(0x7f0000000480)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000240)=[{0x81}, {0x87}, {0x6}]})
syz_emit_ethernet(0x2a, &(0x7f00000000c0)=ANY=[])


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x9})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000880)={0x0, 0x800000cd, 0x1ff, 0xd2c, "8717f905070000b29b5c0300c9abbc0d51aa8000"})
writev(r0, &(0x7f0000000240)=[{&(0x7f0000000080)='\r', 0x1}], 0x1)


r0 = kqueue()
kevent(r0, &(0x7f00000000c0)=[{{}, 0xfffffffffffffff9, 0x1, 0x0, 0x7}], 0x1, &(0x7f0000000100), 0x7ff, &(0x7f0000000240)={0x0, 0x4})


mknodat(0xffffffffffffff9c, &(0x7f0000000100)='./file0\x00', 0x1000, 0x0)
open$dir(&(0x7f0000000240)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = open(&(0x7f0000000040)='./file0\x00', 0x1, 0x0)
ioctl$FIONREAD(r1, 0x8020697a, &(0x7f0000000100))


r0 = socket$inet6(0x18, 0x1, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x1008, &(0x7f00000000c0), &(0x7f0000000040)=0xffffffe2)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000002c0)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
sendmmsg(r0, &(0x7f0000000080)={0x0}, 0x10, 0x0)


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000240)="ea00000100000000", 0xc)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
r1 = socket$inet(0x2, 0x2, 0x0)
close(r1)
r2 = socket$inet(0x2, 0x2, 0x0)
dup2(r0, r2)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000240)="ea02000000000000", 0x8)
setsockopt$inet_opts(r1, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0x8)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000))
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000001180)={'tap', 0x0})
ioctl$BIOCSETWF(r3, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{}, {0x48, 0x0, 0x0, 0x4}, {0x6}]})
write(r3, &(0x7f0000000180)="23009100007adb020317bdda2b7e", 0xe)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r4 = socket(0x2, 0x8000, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r5 = open$dir(&(0x7f00000003c0)='./file0\x00', 0x400004000011830a, 0x0)
lseek(r5, 0x0, 0x0)
setsockopt(r4, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f00000006c0)={0x0, 0x0, 0xffffdffc, 0xfffffff7, "ffff0d000300ef01018b00690200000000000400"})
writev(r0, &(0x7f0000000480)=[{0x0}, {&(0x7f0000000200)="9d7a04000000000000008add940000003d467bc98f361d4af4a3a2d2958607d89cda38d915b3fb2b343b27bbe92a5dc192eb52b6acaafa25f4a382633b92b618b774b01f591633adc173d07873bff7eca22442d07d819ce4351ef6aa31272804ec1b01a7216e9ce96eb15a3d6d804ff8cd8015f5be3a4cee2ad900d428cfbd5344162bff5fe5716388130a", 0x8b}], 0x2)
readv(r1, &(0x7f0000000140)=[{&(0x7f0000000000)=""/201, 0xc9}], 0x1)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0xffffffffffffffff}})
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x0, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setrlimit(0x2, &(0x7f0000000080)={0x60000000, 0x60000000})
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x10, r0, 0x0)


syz_extract_tcp_res$synack(&(0x7f0000000100), 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000100)=[{0x1}, {0x44}, {0x96}]})
syz_emit_ethernet(0x36, &(0x7f00000002c0)=ANY=[@ANYBLOB="aaaaaaaaaaadc5aaaaaa0000000000000000000000eeec211dd1450021b07f5a1933ff00000000000000000000000000aa1a4792b39f252147cae2d26e0da296c9fee0e37314b1130c93562a48e78322e3a9c683d31a4e6bebca7f1128fcc431bd45fb1f2183021ad0eca0ece8f06cb254667a0ec52c4e63deccc8d0428321366b97b6558794d0e0a73ea2ba1e86f8b0b5a5320116b36108da8d509ee2fb0a384a1b11b12f7e70404c54ae549cd813f74835768d5a67435b5bf21efe149c1bddabfe34a50f9b35b2c38ce03853cd4191f9079868740cd527e940c116539c36d6c67d41ceb8f2206943336364f692bb148fb0d07f4283ebe1cc"])
syz_extract_tcp_res$synack(&(0x7f0000000200), 0x1, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x412dff)
r0 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
preadv(r0, &(0x7f0000001440)=[{&(0x7f0000001480)=""/138, 0x8a}, {&(0x7f0000000440)=""/4096, 0x1000}], 0x2, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000280), 0x10000, 0x0)
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000100)={0x1, &(0x7f0000000000)=[{0x1, 0xbd, 0x2, 0x2}]})
fcntl$lock(r1, 0x8, &(0x7f0000000080)={0x3, 0x0, 0x8, 0x100000000000005})
r2 = socket(0x18, 0x2, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
close(r2)
r3 = socket(0x18, 0x1, 0x0)
openat$klog(0xffffffffffffff9c, &(0x7f0000001400), 0x0, 0x0)
shutdown(r3, 0x0)
recvmmsg(r3, &(0x7f0000001380)={0x0}, 0x10, 0x0, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={0x0, 0x4}, 0x10, 0x841, 0x0)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x1006, &(0x7f0000000180)={0x0, 0x3}, 0x10)
sysctl$net_inet_divert(&(0x7f0000000040)={0x4, 0x2, 0x102, 0x3}, 0x4, 0x0, 0x0, 0x0, 0x0)
setitimer(0x0, &(0x7f0000000140)={{0xffffffffffffffff, 0xffffffffffffff7f}, {0x5, 0x5}}, 0x0)
getitimer(0x0, 0x0)
accept$unix(0xffffffffffffffff, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r4 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r4, 0xc020697e, &(0x7f00000001c0))
sysctl$net_inet_tcp(&(0x7f0000000440)={0x4, 0x18, 0x6, 0x9}, 0x4, &(0x7f0000000740)="9b1809c3218b07fcfe4189c99e805e6e84d356960798a692992117d6728436ba1bd87f42e3303eac3846528d050712f838130efce33f523ba44765f5f6915b2227390ed95bd9dc6d4dc7f149d4d6d06a3f23616e773302d9cae75e39a5a11e32e0e6ebd635450b2eba540af7f2aa5dbfbdd900a0dad2b74f50acd76b5c567049ef436dbea0d7562f52955af8d4ab84c513252ddd139b5f5cd5c2bd02adc7f1fe850c00000000000000062abb9fa45ac78568e1cb54238fbab475cca257352828a76e5334be562995e894238b96ca5d4d3e670fa0cc791dfc4415030910fa64eac9b4e8aa9bef19525cb6f7e8570be65bb7ad3fe963cb9a8bd949ee334db1ccf73db06b5947b3e88aa810f8ed7cca10ff0d0000000000001345daa49507756f49775275ca390b94e85d5a952000b9429c75d0da3b561c6adc3c141f26040000006b436218bdbdc9ac0a623855e941dc1872fcb045e0d9df1ecc6357ee21e2b0802cb60edd0300723221f06715e7eecc3e0760c70e1dd7873e27142bbae1a7e44de453a073fe3426f334b80f043ba9136d57c799353d46dd81439b111a511a288bee5dfb2e353e3bb073e3342273216b07e49ca4df0fd2dbe9a8eb377010ee678aad0bd8c7fb7d82693a096344671843a1f2082612b2ff237c6e505ff5f5ba932954d73c630fd2791f833a1da5af0704f687e196f4f7859e071fc98111cc9024f790ce16ceaa427d0104e39789d9100000", &(0x7f0000000a40)=0x210, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000140)=[{0x84}, {0x2c}, {0x40e}]})
syz_emit_ethernet(0x103e, &(0x7f0000001980)=ANY=[])


open(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x1}, {0x2}, {0x6}]})
syz_emit_ethernet(0x26, &(0x7f0000000280)=ANY=[])


ktrace(0x0, 0xe53a055dd4cd665d, 0xa24, 0x0)


r0 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r0, 0x0)
r1 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
r2 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r2, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)={0x3, 0x7fffffff})
r3 = kqueue()
kevent(r3, &(0x7f00000000c0), 0x30, 0x0, 0x57d, 0x0)
accept(r0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x50}, 0x2, &(0x7f00000000c0)="8d39613b3472c82ca3ef2b0bf64c89d7c732f3f37c1a1b59e928134daa29a71c173af5f18211afe3311e522eddeef12ea0ac2874e371eec0dab339c28577fa4ed060f52b276d4e5d5bcdd5aaf6ac5b19f4f3cf7b7b62788a30d197903be160e165c7160dd834b945e99fe5f95e8af5e785dbc96d1a5a722a39639aeb45", &(0x7f0000000440)=0x7d, &(0x7f0000000080)="bdd8a95987ec64b6fe82f1386e2b7a5c79163d99ae26dbb5f29e838a0558c27cea7e0d3281951279ba11e2c727", 0x2d)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {}, {0x2}]})
ioctl$DIOCMAP(0xffffffffffffffff, 0xc0106477, &(0x7f00000000c0)={0x0, r0})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


r0 = socket$unix(0x1, 0x2, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x2000, &(0x7f0000000200), &(0x7f0000000000)=0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000000)=[{0x7}, {0x40}, {0x6}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {0x0, &(0x7f0000ffc000/0x2000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {}, {0x0, &(0x7f0000ffe000/0x2000)=nil}, {}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {0x0, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffc000/0x1000)=nil}], './file0\x00'})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x6, 0x0, 0xffffffffffffffff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendmsg$unix(r0, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
socket$inet(0x2, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
r1 = dup(0xffffffffffffffff)
setsockopt(r1, 0x6, 0x8, &(0x7f0000000380), 0x0)
getsockopt$inet_opts(r0, 0x0, 0xd, 0x0, 0x0)
syz_emit_ethernet(0x9c, &(0x7f0000000100)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa86dd604292c800660000fe0aad1f4900000000000000000000aaff0200000000000000000000000000012902000000000000bc"])
syz_emit_ethernet(0x2a, &(0x7f0000000080)={@local, @local, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x1, 0x0, @local={0xac, 0x14, 0x0}, @multicast1}, @icmp=@mask_request}}}})


r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x200, 0x0)
r1 = open$dir(&(0x7f0000000680)='./file0\x00', 0x0, 0x0)
select(0x40, &(0x7f0000000500)={0x3fc}, 0x0, 0x0, 0x0)
r2 = kqueue()
kevent(r2, &(0x7f0000000000), 0x400, 0x0, 0xdb74, 0x0)
r3 = openat$diskmap(0xffffffffffffff9c, &(0x7f00000000c0), 0x20, 0x0)
ioctl$DIOCMAP(r3, 0xc0106477, &(0x7f0000000140)={&(0x7f0000000100)='./file0\x00', r0})
dup2(r1, r0)
r4 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
close(r4)


writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="0002"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
fcntl$setstatus(r0, 0x4, 0x40)
r1 = getpgid(0x0)
fcntl$setown(r0, 0x6, r1)
connect$inet(r0, &(0x7f0000000000), 0x10)
shutdown(r0, 0x2)


r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
r1 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x401, 0x0)
poll(&(0x7f0000000040)=[{}, {r1}], 0x2, 0x0)
openat$vnd(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
open(&(0x7f0000000200)='./file0\x00', 0x80000000000206, 0x0)
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, 0x0)
readv(0xffffffffffffffff, 0x0, 0x0)
ioctl$WSMOUSEIO_GETPARAMS(0xffffffffffffffff, 0x80105727, &(0x7f0000000100)={&(0x7f0000000080)=[{0x26, 0x5}, {0x84, 0x1d}, {0x20}], 0x3})
readv(0xffffffffffffffff, 0x0, 0x0)
getrusage(0x5f8a20f5b4f2087b, 0x0)
sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000000)="9b1809ffffffffffffff7f473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6fd74c94d1b44", &(0x7f0000000040)=0x10011, 0x0, 0x0)
ioctl$FIONBIO(r0, 0xc0107008, &(0x7f0000000040))
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
r2 = syz_open_pts()
write(r2, &(0x7f0000000100)='@', 0x1)
ioctl$TIOCSETD(r2, 0x8004741b, &(0x7f00000006c0)=0x9)
ioctl$TIOCSETD(r2, 0x8004741b, &(0x7f0000000040)=0x9)
close(0xffffffffffffffff)
syz_open_pts()
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r3 = syz_open_pts()
close(r3)
syz_open_pts()
writev(r3, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(&(0x7f0000000040)='./file0\x00', 0x1, 0x6000043e, 0xffffffffffffffff)
open(&(0x7f0000000100)='./file0\x00', 0x70e, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x100, r0)
socket(0x800000018, 0x1, 0xfc)
r1 = socket$inet(0x2, 0x2, 0x0)
munmap(&(0x7f0000000000/0xf000)=nil, 0xf000)
mmap(&(0x7f0000001000/0x2000)=nil, 0x2000, 0x0, 0x9810, 0xffffffffffffffff, 0x0)
minherit(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x3)
getsockopt$inet_opts(r1, 0x0, 0x5, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
mprotect(&(0x7f0000fff000/0x1000)=nil, 0x1000, 0xb14766e595c6303e)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x0, 0x2, 0x0)
setsockopt(r2, 0x1000000000029, 0x28, 0x0, 0x0)
r3 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x8040691a, &(0x7f00000001c0))
ioctl$FIONREAD(r1, 0xc0286988, 0x0)
renameat(0xffffffffffffffff, &(0x7f0000000080)='./file0/file0\x00', 0xffffffffffffffff, &(0x7f00000000c0)='./file0/file0\x00')
socketpair$unix(0x1, 0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000440), &(0x7f0000000380)=0xc)
semget$private(0x0, 0x7, 0x3c0)
r4 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x22, 0x0, 0x0)
r5 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r5, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)


minherit(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f00000001c0)=[{0x44}, {0xc}, {0x8126}]})
clock_gettime(0x2, 0xfffffffffffffffe)
r1 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r2 = getuid()
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ff7000/0x3000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000604000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000691000/0x2000)=nil, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil}], './file0\x00'})
r3 = socket$inet(0x2, 0x3, 0x0)
setsockopt(r3, 0x0, 0x2, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x50}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r4 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r4, 0x80206918, &(0x7f00000001c0))
ioctl$FIONREAD(r4, 0x4004667f, &(0x7f00000002c0))
mprotect(&(0x7f0000ff3000/0x2000)=nil, 0x2000, 0x4)
writev(0xffffffffffffffff, &(0x7f0000000300)=[{&(0x7f0000000140)="f005c71031c1c5f421277b09000000000000007a091a2f47be787538ec7a89ec5ed66daa731ddc384ecc690869a0aa2266affdf772d7a360ee0f15fa664f557bb45071fe9b6d9d28e6e2589000f6a64f370b9e336987d77b38f7aada5309e46a81e0e2efa087aa9f5f89934fdbd2ed96e7234b8972b273e810ca9962a8f461d3a05711a63027321ff62c", 0x8a}], 0x1)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r5=>0xffffffffffffffff})
ioctl$FIONREAD(r5, 0xc0106924, &(0x7f00000001c0))
fchown(r1, r2, 0xffffffffffffffff)
syz_emit_ethernet(0x4a, &(0x7f00000001c0)=ANY=[])


syz_emit_ethernet(0x36, &(0x7f0000000200)={@local, @local, [], {@ipv6={0x86dd, {0x0, 0x6, "5f6ad9", 0x0, 0x0, 0x0, @rand_addr="8a211dd1450021b07f5a1957de7400", @local={0xfe, 0x80, '\x00', 0x0}}}}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
openat$pf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x46, &(0x7f0000000200)=ANY=[])


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x4000000000000003}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x100000000000000, 0xffffffffffffffff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
close(0xffffffffffffffff)
socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000029, 0x2e, &(0x7f0000000380), 0x0)
ioctl$TIOCGETD(0xffffffffffffffff, 0x4004741a, 0x0)
openat$wsdisplay(0xffffffffffffff9c, 0x0, 0x20040, 0x0)
openat$wsdisplay(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
r0 = openat$wskbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, r0)
ioctl$WSKBDIO_GETMAP(0xffffffffffffffff, 0xc0105715, &(0x7f0000000000)={0x0, &(0x7f0000001f40)})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
r1 = socket(0x1, 0x1, 0x0)
syz_open_pts()
close(r1)
r2 = socket(0x18, 0x1, 0x0)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000480))
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
mmap(&(0x7f0000ffd000/0x2000)=nil, 0x2000, 0x0, 0x2010, r0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
socket(0x18, 0x2, 0x0)
r1 = open$dir(&(0x7f0000000000)='./file0\x00', 0x200, 0x0)
r2 = open$dir(&(0x7f0000000680)='./file0\x00', 0x0, 0x68)
select(0x40, &(0x7f0000000500)={0x3fc}, 0x0, 0x0, 0x0)
r3 = openat$diskmap(0xffffffffffffff9c, &(0x7f00000000c0), 0x20, 0x0)
ioctl$DIOCMAP(r3, 0xc0106477, 0x0)
dup2(r2, r1)
r4 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
close(r4)
syz_emit_ethernet(0xc1, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0xb3, 0x0, 0x1}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x1, 0x0, 0x10, 0x4, 0x2, 0x0, 0x233, {[@generic={0x0, 0x5, "96c729"}, @sack_perm={0x4, 0x2}, @sack={0x5, 0x16, [0x4, 0x0, 0x40000001, 0xde5, 0x2]}, @timestamp={0x8, 0xa}, @generic={0x4, 0x2}]}}, {"d1c2f0bfe2d0786ca28e44289f59aba04d62ff16e6bb47f1cd981d0cf5f225560531db5a3a6c3cb3d5ac50e0eec7423f3ef5e3c4a13f81f14f843a32b529e4649b57d581159522ddf03a6cabf358af4e1ae7ab79a9aac6417859ae29d8de08"}}}}}})


setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000040)={0x0, 0xffffffff, 0x9, 0x203519, "28b7e60ab87aa57800000000d0d2000000001c00"})
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000380)="06480eca9d478631b6cbe23e37e6d816b2b597a9980dcc297aeb3399a9b478b32e3d32d69260f557ac39fae10af920906672fdea9d9945ae55ea74887eb4988e1018149d02a0c119de688723d2079cc2b90daa2a836976ccacd2722b36a1ec0ca5d5043f730ae839ff5cf30e25dc0feb876e2579dbfd5b3c68699c5286761d47cf8c2f6332b48e4eea4199d8e14128faaf3019d9258ea8a62c7f8c98975c7870e8416fdd02827dcec2569d61917f3d18f0431e5a1c656da599fa195ed4c13fd8d211a1290e83cb38850688", 0xcb}, {&(0x7f0000002280)="79dcdf7e3555933ff826233e03433c5613a5485e54a4a9cdbd453163180082ccba5e54eddede8a3f3997e3b4f481c91973085ca2353dcaeec6edf7d0a986cc6d7d30fc4d2ddadd701292c3e46377c8e01f25008f666767c5fcaebfec104b13bd73ae038aafb6868635dc3b00ab79c4234379f6f4e2e14868f79d31e85735606218e9329ebbda19b51eca771e0da731c22771e16d7b0d1a20bb2a57f32180b1ebac6c3d695db9", 0xa6}, {&(0x7f0000000240)="9a99c311875acdb2a479c23d591a6201135973d431d30a7c6b1133322d1e227154657476e756444564362367887f0b98a374a86b1c3c39526c63", 0x3a}], 0x3)
writev(r0, &(0x7f0000000000)=[{&(0x7f0000000b80)="4b8572730e51a93601084c480dc1199dc57b2495e54e7209c4c7ad688b2768a5c2dc2606cb3396fe19b7684fece0172cf942aa0b7918b45b0efaf120cb28eabf16f7c5000b4159c5d1cc872d79ad1721703966da567664630f2106236f5650fdbfa8246401bb352764be4b6fa3ebc0b99a3665bc25216ba50581e8c9aff5a6691e97bedc672c5e8e3ed4bd372eb4db334603c9fb94a733c8f0455f4285c7b298e66cf9bebb66f447e2fa9afbb8108623ef393b169cbd255c6b3db0b76f90ed460706c5193c7b1f5066d2dbf51d6cd727629cd778450dcb36f693bb26b75e82299e4e39eeac9ae3122c7ddd1adc48621758141b0dca303454edf70ff1e66f574bfa184fe03fd13aadfdb7b196087edddc571ab8a8bf9d9676b2a22ba7e946a26377f29f53d461fbe5238b3ba135febe2821ce168c88fed545c6f82874285b00254d20ec65a168817dcd0157821d9c0c28d4790c62cbf67b6f71982c73fcbc5f943204b649b6313e879d2cd92c788aab06c014a89b3523de83b305e047a0d9ca6acb8bddb5de9aae120000f2eac0b8b83c9502f70f80a627d784037f333ed300c3a993e252ea24c9f5e1d12a5ab0ba3c0346992a80e1cb91283b459e5aeb7d2a03e0a55f27f2b0cacd8c62743f7ca5e9b0541d92a623ff7772df5ec5d228c087209b69c903b0b779defd39352daaffbc17424f5dd6480c80fb74ca117ef2a6870e590350b913d139afbc581ba6e2d87fd7a9b6e8d91b41afa9531e53a297e6474afc5c5e651eb9696a43eac3a3ec4813", 0x22f}, {&(0x7f0000000600)="6099fbdd9cc44bf7dc52000028adb25e275b8138589de3e05be278b7889f45a4d0b2f5458cfecee79ebe509a8ea6d3", 0x2f}, {&(0x7f0000001280)="730b6c66732ffec6851a540a37647d21f804dfa2bea63ff61b79061ea84bd6a5b9422c77620e4f4892d6c5d3e2f03fa4c68a5bb37b4e0c2877695126c26a04345b5fd3cbaf7e19a47f56418a709ab3bbf8a652f1a2da200d3e550d100e77682ae4e2d15ba0fd8ef6852185678e3ea653e4dacdfac48dea260a53ae97b3912402b45603ffed183829fc0602f7b13acf039dc325829559b82dc75a3bff8edd773a075a5b036d47aa95258e40dc4a30ac578be10495134d62e98c1098ff216aa208b088dceaba4786509931eec12ab01723bfe54b76554bd9cbf76354c5bdbfca6e872f339954fc972f6717fafcfe59a502b08feac1349050b1b7dd558b200c0121eeb4e9cf855469a7d91972e15c1c744f6f3f75c27a3dd194ff5ca8537e8cd34d0b6b79a5b72abf92bf1e31a0548dde68013c6c841213807ea38f10632329210eb4d621650cd7271f1328a9be810848e24c88e9543c6c33937680ff0e0a205909f3827f993efca0381680d7bb624000dd066c36eabb6ebaa010ec079326b18dac2445d7f28c979afa8b8661b628b8282e217fe9698cc4cc5e0ed4547954881a137afdf0d929ec58cb8e797d0dc9cc2f9c18898104c85d5fc6427635f001f8ac8467c12a2e7a", 0x1c5}], 0x3)


sysctl$net_inet_ip(&(0x7f00000002c0)={0x4, 0x2, 0x0, 0x20}, 0x4, &(0x7f0000000340)="64b90587", &(0x7f0000000380)=0x4, &(0x7f00000003c0), 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x80206997, &(0x7f00000001c0))


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
ftruncate(r0, 0x8531)
r1 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r1, 0x0)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
select(0x40, &(0x7f0000000280), &(0x7f00000024c0), 0x0, 0x0)


mknod(&(0x7f0000000000)='./bus\x00', 0x2000, 0x6380)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x6381)
open(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
select(0x40, &(0x7f0000000080)={0xffffffffffffffff}, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x54}, {0x4c}, {0x6}]})
syz_emit_ethernet(0x17a, &(0x7f0000000000)=ANY=[])


munmap(&(0x7f0000001000/0x2000)=nil, 0x2000)
r0 = shmget$private(0x0, 0x1000, 0x0, &(0x7f0000003000/0x1000)=nil)
shmat(r0, &(0x7f0000002000/0x1000)=nil, 0x0)
munmap(&(0x7f0000002000/0x1000)=nil, 0x1000)
r1 = shmget$private(0x0, 0x1000, 0x0, &(0x7f0000003000/0x1000)=nil)
shmat(r1, &(0x7f0000002000/0x1000)=nil, 0x0)
shmdt(0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
r1 = socket$inet(0x2, 0x2, 0x0)
close(r1)
r2 = socket$inet(0x2, 0x2, 0x0)
dup2(r0, r2)
close(0xffffffffffffffff)
socket(0x0, 0x0, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
r3 = socket(0x2, 0x2, 0x0)
connect$unix(r3, &(0x7f0000000040), 0x10)
getsockname$unix(r3, &(0x7f0000000000)=@abs, &(0x7f0000001200)=0x8)
r4 = socket(0x2, 0x1, 0x0)
bind(r4, &(0x7f0000000000), 0x10)
r5 = dup(r4)
listen(r5, 0x0)
r6 = socket(0x2, 0x1, 0x0)
connect$unix(r6, &(0x7f0000000000), 0x10)
r7 = dup2(r6, r6)
setsockopt(r7, 0x6, 0x2, &(0x7f0000000200)='c\x00\x00\x00', 0x4)
setsockopt$inet_opts(r7, 0x0, 0x1, &(0x7f0000000600)="ee08665d19ac14d5e5134876f197a7728420aef6171504b1c3d4b3830c921bf0817a0000040000006a89dbdf", 0x2c)
sendto$inet(r7, &(0x7f00000000c0)="da5ca0e90660987bb7e641f8d95f7c601120bd155931e4788b7c1995b3f51444ba93c7974cd8bd02e27ede376f4291ebcd6bb68b3e81bf8bf8834b833717bd7151224a49d05deba92c028554fc0909202850432aaf5a1676bad07c9cefba2405908475943a5fc734709f932f6289e467f3504f9e716ce458f3d8132001fbb572711e70699a03", 0x86, 0x0, 0x0, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000200)="ea00000000000000", 0x8)
setsockopt$inet_opts(r2, 0x0, 0x200000000000c, &(0x7f0000000240)="ea02000000000000", 0x8)
setsockopt$inet_opts(r1, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0x8)


r0 = open(&(0x7f0000000300)='./file0\x00', 0x8, 0x8)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000380)={0x0, &(0x7f0000000340)})
socket(0x0, 0x0, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(&(0x7f00000003c0)={0x6, 0x1b}, 0x3, 0x0, 0x0, 0x0, 0x0)
r2 = socket(0x2, 0x1, 0x0)
fcntl$setstatus(r2, 0x4, 0x40)
r3 = getpgid(0x0)
fcntl$setown(r2, 0x6, r3)
listen(r2, 0x0)
shutdown(r2, 0x2)
sysctl$kern(&(0x7f0000000040)={0x1, 0x3f}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0xfffffffffffffda3)
r4 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r5 = dup2(r4, r1)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r6 = getpid()
r7 = fcntl$getown(0xffffffffffffffff, 0x5)
setpgid(0x0, 0x0)
r8 = getegid()
r9 = msgget$private(0x0, 0x0)
msgctl$IPC_SET(r9, 0x1, &(0x7f0000002f80)={{0x0, 0x0, r8}, 0x0, 0xff, r6, r7, 0x7fffffff, 0xa, 0x2000000100000001, 0x7})
msgrcv(r9, &(0x7f00000000c0)={0x0, ""/113}, 0x79, 0x0, 0x1000)
symlink(&(0x7f0000002340)='\x00', &(0x7f0000002380)='./file0\x00')
open(&(0x7f00000001c0)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETF(r5, 0x80104267, &(0x7f0000000140)={0x0, 0x0})


mkdirat(0xffffffffffffffff, &(0x7f0000000040)='./file1\x00', 0x0)
fchownat(0xffffffffffffffff, &(0x7f0000000140)='./file1/file1\x00', 0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000380)={0x0, <r0=>0x0}, &(0x7f00000003c0)=0xc)
r1 = getegid()
fchown(0xffffffffffffffff, r0, r1)
r2 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
open(&(0x7f00000002c0)='./file0\x00', 0x0, 0x0)
socket$unix(0x1, 0x0, 0x0)
r3 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40003354, r3)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r2, 0x0)
select(0x0, 0x0, 0x0, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x7}, &(0x7f00000000c0))
r4 = msgget$private(0x0, 0x120)
msgctl$IPC_SET(r4, 0x1, &(0x7f0000000180)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}})


sendmmsg(0xffffffffffffffff, &(0x7f00000007c0)={&(0x7f0000000780)={0x0, 0x0, &(0x7f0000000540)=[{&(0x7f0000000180)="b860fe09625ee6793978a575fa00000000d6c2eca2950e663d39ab1be31a269a39fd7f97e41e178f37a79f00659c2eb33ac91343ea3b3f8c5c7b93d5c20ab4201791fe30", 0x44}], 0x1, 0x0}}, 0x10, 0x0)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f00000001c0))


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000280)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000340)=0xc)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r1}})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x50}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0xfe10, 0x0, 0x37)


writev(0xffffffffffffffff, &(0x7f00000000c0)=[{&(0x7f0000000180)="9cf72464b4fabdda7378197c2eeaf7b9513c4168902e6689dd6c90f04881c6e925fc78d07173e47feaafcda76a7fa95a589939bea0bd7c6f1abf94daf42fc685edaafe4e7bf54e3d4156e7750b88", 0x4e}], 0x1)
r0 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r0, 0xc0106978, &(0x7f00000001c0))


setitimer(0x2, &(0x7f0000000100)={{}, {0x0, 0xffff}}, &(0x7f00000001c0))


r0 = kqueue()
r1 = open$dir(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
kevent(r0, &(0x7f0000000000)=[{{r1}, 0xffffffffffffffff, 0xa1, 0x2, 0x0, 0x1}], 0x8c0, 0x0, 0x0, 0x0)
ftruncate(0xffffffffffffffff, 0x0)
kevent(r0, 0x0, 0x0, 0x0, 0x653, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
r4 = fcntl$dupfd(r2, 0x0, r3)
recvmsg(r4, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r3, 0x0, 0x0, 0x7)
setsockopt$sock_timeval(r3, 0xffff, 0x1005, &(0x7f0000000000), 0x10)
seteuid(0xffffffffffffffff)
socket(0x0, 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x0)
shmctl$IPC_SET(0x0, 0x1, &(0x7f0000000000)={{0xffffffff, 0x0, 0x0, 0xffffffffffffffff}, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0xfffffffffffffffe})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
r5 = msgget$private(0x0, 0x0)
msgsnd(r5, &(0x7f00000000c0)=ANY=[@ANYRES32], 0x1f, 0x800)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
sysctl$hw(&(0x7f0000000040)={0x6, 0x9}, 0x2, 0x0, 0x0, 0x0, 0x0)
socket(0x1, 0x2, 0x0)
clock_getres(0x5, 0x0)
kqueue()
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, &(0x7f00000001c0))
r6 = open(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
ioctl$FIONBIO(r6, 0x8004667e, &(0x7f0000000200)=0x80000000)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})


setitimer(0x0, &(0x7f00000001c0)={{}, {0x0, 0x4}}, 0x0)
setitimer(0x0, 0x0, 0xffffffffffffffff)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r1 = getppid()
fcntl$setown(r0, 0x6, r1)
fcntl$setown(r0, 0x6, 0x0)


r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x200, 0x0)
truncate(&(0x7f0000000000)='./file0\x00', 0x30001)
close(r0)
truncate(&(0x7f0000000040)='./file0\x00', 0x30000)
unlink(&(0x7f0000000280)='./file0\x00')


setuid(0xffffffffffffffff)
sysctl$kern(&(0x7f0000000040)={0x1, 0x53}, 0x2, &(0x7f0000000100), 0x0, 0x0, 0x0)


munmap(&(0x7f0000ff4000/0x1000)=nil, 0x1000)
mquery(&(0x7f0000ff4000/0x1000)=nil, 0x7f7fffffc000, 0x0, 0x0, 0xffffffffffffffff, 0x0)


poll(0x0, 0x0, 0x0)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0x41946465, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80146959, &(0x7f00000001c0))
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000bc0)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x3f8d}, 0x10, 0x0, 0x0)
r3 = openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r3, 0x80105727, &(0x7f0000000200)={&(0x7f0000000100)=[{}, {0x25}], 0x2})
sendmmsg(r2, &(0x7f0000000080)={0x0}, 0x10, 0x0)
syz_emit_ethernet(0x46, &(0x7f0000000500)={@broadcast, @broadcast, [], {@ipv4={0x800, {{0x9, 0x4, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, @broadcast, @multicast2, {[@generic={0x88, 0x2}, @timestamp={0x44, 0xc, 0x1, 0x0, 0x0, [{}, {}]}]}}, @tcp={{0x2, 0x2, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})
r4 = kqueue()
mknodat(0xffffffffffffff9c, 0x0, 0x0, 0x0)
accept$unix(r1, &(0x7f0000000300)=@file={0x0, ""/504}, &(0x7f0000000240)=0x1fa)
r5 = openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
dup2(r5, r4)
r6 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$DIOCMAP(r6, 0xc0106477, &(0x7f0000000200)={&(0x7f00000002c0)='./file0\x00', r5})
open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r7 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r7, 0x9, &(0x7f0000000300)={0x0, 0x0, 0x0, 0x100000001})
open(&(0x7f0000000040)='./file0\x00', 0x205, 0x0)
syz_extract_tcp_res$synack(&(0x7f0000000280), 0x1, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000000000)={@local, @empty, [], {@ipv4={0x800, {{0x8, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @multicast1, {[@rr={0x7, 0xb, 0x7, [@broadcast, @multicast2]}]}}, @icmp=@info_request}}}})


r0 = syz_open_pts()
flock(r0, 0x1)
syz_open_pts()
syz_open_pts()
close(r0)


r0 = syz_open_pts()
close(0xffffffffffffffff)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x45}, 0x4, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
bind$unix(0xffffffffffffffff, &(0x7f0000000040)=@file={0x0, './file0\x00'}, 0xa)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
connect$unix(r2, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
connect$unix(r1, &(0x7f00000000c0)=@file={0x0, './file0\x00'}, 0xa)
msgget$private(0x0, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000140)=[{0x4c}, {0x5}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000240)=ANY=[])
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$VT_GETACTIVE(0xffffffffffffffff, 0x40047607, &(0x7f0000000380))
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000040)=0xffff)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
shmat(0x0, &(0x7f00004b1000/0x3000)=nil, 0x3000)
socket(0x0, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x2000000000, [{&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000321000/0x1000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000021000/0x1000)=nil}, {&(0x7f000096f000/0x1000)=nil, &(0x7f0000ffb000/0x4000)=nil, 0x7fffffffffffffff}, {&(0x7f0000a68000/0x2000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00007c1000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000000000/0xc00000)=nil}, {&(0x7f0000a31000/0x3000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f00002ec000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f00002f9000/0x1000)=nil, &(0x7f00006a5000/0x4000)=nil}, {&(0x7f000032e000/0x800000)=nil, &(0x7f0000ffe000/0x1000)=nil, 0x200}, {&(0x7f0000015000/0x3000)=nil, &(0x7f000015e000/0x2000)=nil}, {&(0x7f0000893000/0x1000)=nil, &(0x7f0000487000/0x2000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ff9000/0x4000)=nil}], './file0\x00'})
mprotect(&(0x7f0000ff3000/0x2000)=nil, 0x2000, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000300)=[{&(0x7f0000000140)="f005c71031c1c5f421277b09000000000000007a091a2f47be787538ec7a89ec5ed66daa731ddc384ecc690869a0aa2266affdf772d7a360ee0f15fa664f557bb45071fe9b6d9d28e6e2589000f6a64f370b9e336987d77b38f7aada5309e46a81e0e2efa087aa9f5f89934fdbd2ed96e7234b8972b273e810ca9962a8f461d3a05711a63027321ff62c", 0x8a}], 0x1)
ioctl$BIOCGBLEN(r3, 0x40044266, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000002c0))
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f0000000340))
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r4, 0x80104267, &(0x7f0000000280)={0x3, &(0x7f0000000200)=[{0x45}, {0x1c}, {0x8006}]})
syz_emit_ethernet(0x1db, &(0x7f00000007c0)=ANY=[])


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x3c}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
r1 = dup(r0)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


syz_emit_ethernet(0x36, &(0x7f0000000440)={@random="db04b06577ac", @broadcast, [], {@ipv4={0x800, {{0x8, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @empty, @multicast2, {[@timestamp={0x44, 0xc, 0x0, 0x0, 0x0, [{[@multicast2]}]}]}}, @udp={{0x3, 0x2, 0x8}}}}}})


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f0000000180)='./file0\x00', 0x23f)
chdir(&(0x7f00000001c0)='./file0\x00')
setuid(0xee01)
r0 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
mkdirat(0xffffffffffffff9c, &(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x18c)
faccessat(r0, &(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x4, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000004c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000280)=[{0x48}, {0x35}, {0x9106}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


mlock(&(0x7f0000ffb000/0x3000)=nil, 0x3000)
munmap(&(0x7f0000fff000/0x1000)=nil, 0x1000)
mlock(&(0x7f0000ffc000/0x3000)=nil, 0x3000)
shmget(0x2, 0x3000, 0x410, &(0x7f0000ffb000/0x3000)=nil)


setuid(0xee01)
r0 = syz_open_pts()
syz_open_pts()
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000001a00)=0x5)


getgroups(0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
setegid(0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001a80)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x2, &(0x7f0000000340)=[{0x2c}, {0x6}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])
getgroups(0x6, &(0x7f00000001c0)=[0x0, 0x0, 0x0, 0x0, 0x0, 0x0])
semget$private(0x0, 0x0, 0x20)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
fchflags(0xffffffffffffffff, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x2, 0x3, 0x0)
connect$unix(r1, &(0x7f0000000000), 0x10)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000380)=[{0x5}, {0x4}, {0x8106}]})
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
sendmsg(r1, &(0x7f0000001ec0)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)


munmap(&(0x7f0000400000/0xc00000)=nil, 0xc00000)
mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, 0x0)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc028698d, &(0x7f0000000080))


socket(0x1, 0x3, 0xee)
ioctl$SPKRTONE(0xffffffffffffffff, 0x80085301, &(0x7f0000000040)={0x9})
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000340)={0xffffffffffffff09, 0xfffffffffffffffe})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x4, &(0x7f00000001c0)=[{}, {0x14, 0x0, 0x0, 0x8000}, {0xfff7, 0x4b, 0x3f, 0xde12}, {0x7a, 0x7, 0x3, 0x7fffffff}]})
syz_emit_ethernet(0xe, &(0x7f00000000c0)=ANY=[])
openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x3022, 0xcd5331e3)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x200000000000b, &(0x7f0000000240)="8fce3f1335c37b8980230497252b014e9c3df5c9c8a376e1174c022936fa9b22e2017c951fa0840b757af27dafc1a19734d1675d53fa8893a3c3c56c642aa38d96aa9b5d6d2ad565e73efd4859a3d57f23f87d0018e74d9a8a317c6a416598362454ea80d177d038176b7651630f25e065714f00d00ce2a7a66a45f0acec50e7fce45cfef32f47becdb62e0c43ba2e21074db568b0dcffc5f11ebf00da616cea31dd2edfa5fe692dd16574722890206d06d3e23f3c567d70199530f08cdc77f959e3fe3301ee00f9529c3aabfb71fad90ea2a6bb92c54ea7961df3428824644b51a79a93b725508cd9052b8b2c1ffecb9b1c643f991a00000000", 0xfa)
r1 = socket(0x18, 0x1, 0x0)
listen(r1, 0x0)
r2 = openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r3 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r4 = fcntl$dupfd(r3, 0x3, 0xffffffffffffffff)
fcntl$setstatus(r4, 0x4, 0x0)
ioctl$PCIOCWRITE(r2, 0xc00c7007, &(0x7f00000005c0)={{}, 0x2})
accept$unix(r1, 0x0, 0x0)
r5 = openat$pci(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
ioctl$PCIOCWRITE(r5, 0xc00c7007, &(0x7f00000005c0))
ioctl$TIOCSETAW(0xffffffffffffffff, 0x802c7415, 0x0)
open(&(0x7f0000000180)='./file0\x00', 0x200, 0x221)
getpid()
setuid(0xee01)
stat(0x0, &(0x7f0000000380))


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000004c0), 0x10202, 0x0)
writev(r0, &(0x7f0000000240)=[{&(0x7f0000000280)="058c4cc154b5895edf170affb44c37b4e96eb0aa265b33a650172f5b1d2760b1cc8ab19c571f000000393974c9e52ef95df7def3d6a5b18dee9efc7d3d5c7c1cb4c8b4259a21c752094c99e4c4788dec400d2be5113d38b0c266176020113ab90f1e7cf312d450bf0ddb515e6b5278da6da791f6a0eddaca71ffc8611d5b03f73e65cefad4259312c4ef3b5c5ab9957ff7daf425c4b50a764b352c491ba8fccc7f68c9f2eb48e4192b5d4e7af882f87f13e7a8d063d06f02b42a5d611c8e008dfce53e9a98b2a07ff096fc4736719a167c1e9d95429b6f4e6b", 0xd9}], 0x1)
execve(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{0x20}, {0x5}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x400000002, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r2 = socket(0x18, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r3 = dup2(r1, r2)
sendmsg$unix(r3, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


writev(0xffffffffffffffff, &(0x7f0000000500)=[{&(0x7f00000000c0)="acabcf121c66403989618f102986590fda96cd6ce3e6319bfbfa5f4e11792ff556376e0a66db2064e7fdd436d5e11d47b40f598865ae30e4577e64f3cea3db7406d3f30fcf81af59f08cd850e080468c406a2576d93a6e610ace0fe401b3af94886a9209a9552e5231c14d5842ce811ae17ac41ca78ffb36e5d9a788ac68443f49b920121df80a106ac6859fedff6187d880e9a8849805a46b28e6ef435d45e7e0343d939f21ef05ff3e31f9b2777b169b10c28b07dc4845ed10f14a549e3c0228e974f48b0b191f74acbb8c4b6b3514b384444d10c203a141c90bf928db0bb64a58fcea41c91073336fe5a3a5a0f82f3f7136ff66292f4641b1a94bae4de83f3c5966f9489587e2c92d75edf7b94832", 0x110}], 0x1)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f00000001c0))


openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$unix(0x1, 0x2, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x4, &(0x7f0000000200), &(0x7f0000000000)=0x4)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
close(r1)
ioctl$TIOCSTAT(r0, 0x20007465, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000140)=[{0x4c}, {0x74}, {0x812e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000000)=0x7, 0x4)
mprotect(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x1)
sysctl$vfs_nfs(&(0x7f0000000000), 0x7, &(0x7f00000025c0), 0x0, 0x0, 0xffffffffffffff2d)


r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))


msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x1, 0x4)
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x159}})
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = socket(0x800000018, 0x1, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "1a1116f0d0f700"})
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


setrlimit(0x8, &(0x7f0000000980)={0x8, 0x51})
r0 = syz_open_pts()
close(r0)
pipe(&(0x7f0000000100)={<r1=>0xffffffffffffffff})
close(r1)
r2 = kqueue()
kevent(r2, &(0x7f0000000040)=[{{r0}, 0xfffffffffffffffc, 0x1}], 0x3, 0x0, 0x8, 0x0)


mknod(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
r0 = socket(0x18, 0x3, 0x0)
getsockname$inet(r0, 0x0, &(0x7f0000000000))
r1 = dup(0xffffffffffffffff)
fcntl$dupfd(0xffffffffffffffff, 0x0, r1)
ioctl$DIOCMAP(0xffffffffffffffff, 0xc0106477, 0x0)
r2 = fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
socket(0x0, 0x0, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1023, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000500)={0x3, &(0x7f00000000c0)=[{}, {0x1, 0x0, 0x0, 0x2}, {0x6, 0x0, 0x0, 0xff}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0xff0a, 0x0, 0x37)


mknod(&(0x7f0000000000)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f0000000080)='./file0\x00', 0x1, 0x0)
open(&(0x7f00000001c0)='./file0\x00', 0x0, 0x0)
ioctl$FIONREAD(r0, 0xc02069b6, &(0x7f00000004c0))


sysctl$net_inet6_ip6(0x0, 0x0, 0x0, 0x0, &(0x7f0000000140)="65b81128cf2800a9d110afd727da9ca726026a8707116412d170b645891d8133f142954cd9c2dbb6ef2a046cd4d57ee3a4c5acb36fb4f67d0995f5ff32e63450634b0ad3", 0x44)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r1 = fcntl$dupfd(r0, 0x3, 0xffffffffffffffff)
ioctl$WSKBDIO_GETMAP(r1, 0x80047476, &(0x7f0000000180)={0x0, 0x0})


mknod(&(0x7f00000000c0)='./file0\x00', 0x2000, 0x4302)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0xb}, 0xc)
getsockopt$sock_timeval(r0, 0xffff, 0x1006, &(0x7f0000000000), &(0x7f00000000c0)=0x10)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x34}, 0x4, &(0x7f0000000080), 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x10000, 0x0)
r1 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x0, 0x0)
ioctl$VT_GETACTIVE(r1, 0xc1045763, &(0x7f0000000100))
mknod(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
r2 = open(&(0x7f0000000040)='./file0\x00', 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x138, 0x0)
ioctl$TIOCFLUSH(r2, 0x80047476, 0x0)
r3 = open$dir(0x0, 0x10, 0x2)
chflagsat(r3, &(0x7f0000000100)='./file0\x00', 0x0, 0x0)
r4 = socket(0x18, 0x3, 0x0)
setsockopt(r4, 0x1000000029, 0x40, &(0x7f00000006c0), 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x1, &(0x7f0000002700)=0xffffffff, 0x4)
ioctl$TIOCFLUSH(0xffffffffffffffff, 0x80047410, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
open$dir(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)


mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0xa60f2c93)
open$dir(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
mknod(&(0x7f0000000080)='./bus\x00', 0x6000, 0x20e02)
r0 = msgget$private(0x0, 0x0)
msgctl$IPC_STAT(r0, 0x2, &(0x7f00000001c0)=""/143)
open(0x0, 0x0, 0x0)
r1 = socket(0x11, 0x3, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000140)=[{0x28}, {0x2}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
sendto$unix(r1, &(0x7f0000000500)="94010513000000000000002797888fd1f838a311000000000000b13886ca3849451ae3c3051020741038f5538551f30ce390500e08fecea11ea8fef96e4fc748e93f0b780486aebdbe781e4d8f5eef9187a869a4d3a4cbba982fd825582fe223ed00f4c8b2ca3ebbc259699a1f132e27acb5d62934e4fd89070000000000000070c1f5a872c88dff7cc53c894303b2a0a85ff3faa800000000009ec7ab3a34c29000000000000000000000000000002d7e4a5d76cc3f9cff2ed2243e56fa277603c5cc1e047326bcf6b67b75d00bf6ee330b6a80874b70559d9975ebd13da2447a78aa4b00cd0ba1870215607bb912e3d7325183ce69456b4b6ca927871c81672a54ec695c5bdeb842836656f917945cc076f87dc714dfe0aa2947252df350707b22884a7730cb6dba8742110fbe9ec7481885274387e0b1dbe5695122604819b0b2294b7b20726a5d4fcb44f62d00fabb2f247a166d8d79d05b8cc370f5c11db58aedca632a83acd58ff0ea0a3dca58ccb03cce466cda735017196ff346c32717397d6ec6952ec90de81ed297b2509e130f0000", 0x194, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000040)=ANY=[])


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$SPKRTONE(r0, 0x80085301, &(0x7f0000000040))


setrlimit(0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000700)=[{0x40}, {0x30}, {0x6}]})
write(r0, &(0x7f0000000740)="76e5dead6f01f8607d2100000063", 0xe)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
r2 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
writev(r2, &(0x7f0000000280)=[{&(0x7f00000001c0)}], 0x1)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
ktrace(&(0x7f0000000040)='./file0\x00', 0x0, 0x6000043e, 0xffffffffffffffff)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001600)={0x0, 0x0, 0x0, 0x0, &(0x7f0000002c40)=ANY=[], 0x10}, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
fcntl$dupfd(r0, 0x0, 0xffffffffffffffff)
recvmsg(0xffffffffffffffff, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x0, &(0x7f0000000000), 0x10)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, &(0x7f0000000200))
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x0, 0x2, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206923, 0x0)
r3 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
fcntl$dupfd(r3, 0x3, 0xffffffffffffffff)
r4 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r4, 0xc0206922, &(0x7f00000001c0))


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r0)
r1 = socket(0x11, 0x3, 0x0)
getpeername$unix(r1, 0x0, &(0x7f0000001140))


r0 = socket(0x18, 0x2, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1006, &(0x7f0000000040), 0x4)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000700)=[{0x3d}, {0x40}, {0x1006}]})
write(r0, &(0x7f0000000740)="76e5dead6f01f8607d2100000063", 0xe)


r0 = socket$inet(0x2, 0x1, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x1e5f)
r1 = open(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
dup2(r0, r1)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000007000/0x3000)=nil, 0x3000, 0x0, 0x11, r0, 0x3)
ftruncate(r0, 0x8531)
writev(0xffffffffffffffff, &(0x7f00000026c0)=[{&(0x7f0000000400)="640493d78db6a9c1e335bb42b30c7b40a07b3baad98026cb156727aa65cfb18540954a46faf6cd689a437aff3f4961c4e46a834f6785f138abeced17229a790e349e6bd31df47a250b6311c17b41de694d02002d9c138fb5554471ad71a4e3b0c4a0f71fc4b1f3db02e683a852170340fa26d02f5dcb6c3772415d9b0c54258aba6ad66cd42dfd5163936af944020e200f6dad158fa90dfdd051d151c8c8cb6d711f408511a8c922ff7be9bf88fc6a18b3261c65ab46b32f89b7793b789d533f5dabd554659bcbb9e4082598016c9ffd443ad64a6c1384bebc4f0fa12ebee357f81c1bfbb7ff9c0bb5289f98184e590366ece692aac2a0f3fe55ae6072624ff0892d666934e9e7bb159ba7471e9ca862d48aa90c56e33b972e7ab5f15383b1e0bdc135ef14c4b638c9514366af346df10d2d11e3e82c7f98a731867165c536966e32790a098e86bc8c85d1d890537ee1a3b37a907cb151aa5b72801d9b213f04f59acc40bab4f2dfde876c2bc53ed02cd106d289a59310e0297a072b926369982acb409872a3a4325ed56f1d297bc8bbfb8f0a43f793ee9487a4492016350aa61cca26b86045d14a8f08e6f6d3e3be5520397612b66ebdf990efcf9ed9796836fa253dfa0389406ae25edb31abf6797596cf9b4a943972a4a19c43db1926c18bf15fc526127d1b04211fb4f4fe4c34dba511e8801a10008e54d343386c0c096641681899e65d2afea539fec10a2db4f07a06c7745c1005d0c2b1f020bd80e052df5a4969a40602d7b4350068968bae7ed03d05c9f0e7dd8940d1e37cfbf3370f5953261615197d350c60c2e3bdc186eff30d0700e608a4e08b2cac91f42275e3e6378a0747267335e017b5342a1662df7f3144a5c0e08008460631d2fb76c410c11c4dcc7f73fcab23a4794775f4284e02ad1ba71d64db4f1f4ced92b7a389fd596763283771b9faf89865c462f59e57a81cf8c3cbeffb268f00b6589ab79483f517583bc3a949c0df139721b6dcb9635dca559ac670c1b3ac3ffae886d18134df6d3b7078928ad5370c9687de2846d1f89f7455cf1f7bec56f3717cbdcab9a5fbe597f929e432ff093d92cb35d625bc8c5dcdc4df998db4b51f74775e5d6d119c505a2d0f27c9ead9e84af18c5d7e258cb6a4b57d28c5be27c3d72e277ae3a79bec39bdc88df392b2df6afcca55f79efb3fe6d0d8b50d7c8bbbc134450db20f1d5a773ce9cdc3b97b3274cb2e9c85496e9043e1eb83bda1b0960808b7dbf61fa0b420596976194a598a6ce1066867d13ed30035f8ff0ba3dcaa15df0cab8b96807cb82435a42067d4f1257de536842db0d3f7dfda891c146d79b600e6a2f994f2755cb278becfdaaefb2c7b976be36689c7a0feced48a723be73f29851f75e42e9d62c83d6aa220891c5c24634e8c7cc3eab033046727127a802dacbde8cf629c1f57d59ba0690af43ce944607c1fd9df72f74d67e7ddc2efd8dc6c459d0d1fe2ca57d14e20046f139050206dd8d203e0389aef6682cc6b861cc364184ee9708452dcb732992ce6dedbb8d57b5c5689b9836c54cdc91b4766f618d608d4bb380614d8cc2e03b3b3b5897ccb61f9fe2d16e5ced34cee9e856a6c52324c0eef64a4b7f9e8e7ed5a71d7b1fe9f94665ac75da67d114047ff5a1c3d0668d43d78c12565ea154f763418049e8dd3a1929b7fa4877c9e2cd984ab94818219a05b196b643adb3f064dbffd2b22ade017488178c5361a1c93f9c615e0e0cd28f25b7ca582d6942071cb7fae17b52eb41ead6e78914945802c19bac16c76ae14c7ed4be6e42713e8a4bd6220aadf458fa15b40777f94e223c596c7f80bab9584fcf4ff14f138adbbf7b1a7bdd686fa9249fe006aea38651e410fd4b1af0d79d7f1ee0cb2711ca81382f15804771da4a18d5f20e10ff9a7abd6ae8583d94f58769f3401526e517d963800c92485f9c24eac2d914895d4d9b866bbb769d22a00db29ce0b9a7d7112defb15d9776db55edf8fca337b1a496c7710acab8135aee0261a780ef6b39664469e33dab2398639d1becbdc74000b36c2ca5df2c0d3c5d3d3e054a2b8d91bc4656cf09300dd084cb0b625a587fba81cc6c2c3ef6f93342b65bc0e68222de6908492ac431f9f4dc1d3915a2cba79820c8c1f7c6e5c582d953b60a943eef44a6e7b244c808fb292f3944a4b1afbbadb06ed72c1d2cf9a60e02b319af032eddb475ae1947175f437262cefe05a89dc92367c8f8223e3a415b080b2bee22f084d00a289e42f5dcd0c31dc257d6bd09d214fad7aaa03d285a4ca618a5cc2bc0167ce424c40b879bfc294b9f2be0ee1c4669fe57d15c3b8fd626507ebb94d7313eda527d86a2bcaf9234a6eb4fcd2ecd218607961c7816094311a762d783ab7cef7009f103d938a5dee845b827001c87920ea3110b97b40a8525c41a57a03e389d9d864c57e10a849509135cdde81b89da8ee10540b76fe6c303a98bfa68a493ff59104b41c34c62092d3c0cc16d5c5c9abf7d0cc9206605ca6b69511091b512063985b03549573fbe60036cdfb28e77670e99b55a8f8151035ac93ef64b77f36951b0d3a31befef14741f874b313b66908f8da53a8a95255c16019876c85dd6070b2a8470f303b98d3c9ce2d203774794ecd2dbc43a69cd37c21f9c971634ff7b00af46adccaaeb1ca346bbdcad44151e38a94d91339c425554791adf2d3ff197221979625d2993ef7f4af06ec2438ab780ce737ac1bdbd873fa3b5cc0af43097b2be36bb9cbf87d39d3a7d54d5a49b176a3d74d95c06cd9b665248f84c27019f7b62232d9de01396aa0096f36c399b762913e207de7e3d24a2bbb04d879fe29b087ea262e82e4b3ca0fca62f222a592ab6ca1b1609e6a7500b8ed38db0d895c2df29604a64540e796787461ed7d1c5c562662b8f5146839cfbae18a6fb302033ad6558ce8a9d61d5de662b995ecb228535cddd02aa051321dadfd06dcd6409cf98d8a8697c7499f1695f173b427ff5f6cfdd224b66b89682d0e2978710e2bbfe7c9f2793cd2592ec7106c44e46c1d2bfe9d7cb53cac640f92f66506aefcc11c983e6c284a892dfc4b813771087baf9150eeb019ba0877afef77a66ee91b2c85ab1b95cc670ae9e80a4f20b8c8914c655828a68d6e8b509d479b5d04980a5bb17fb9ef17060f802f6e6f57e29d6587d6b8dc3438f592db639f718cc3bdaad6865d8a6aa94c47e1061cb8dfb8d7c54c168a29e8b1a78e1716ce413d429daaf09c924a7cde44eafc58fa5b3a5e3aa387a9465f024f7fe6ed9343d81dee65d106f635bbece1c99d5eb8ca0487c00c2851aaf24b2b6003e7150758f5a50943de2ba7b95710fa05f1c1e305dd7a14dba19feb94c9591d8cf724ef55aca7fb8e054763f7c80027b929666f6864db25a059859ca8831f9b7251e38eda5b00d0fc64a3b3460bd7ad733b9eac508a6a191a6465ca14729214d29cdfef5c6409a3f7e5db2044f836c049f5a14a78bea5c7a55e957a53d8d7d97203de65090319911c1788fc704d9382571d3d1bd2b35927d8d95b3f3b14930350ca34d577ff1d4ab69c7ef9f74f73590b8fd0d3574e7779e7f6564f9245c117c4272054015715a0671bcec7416d95a17da00b50e976168b9de75b673f6998119eb1c3b2bd1eebbf21aabc7e606991dc2e802058344d4854b1fe88688873db69c8ac70a9e4850960390a510231dc7159e3e89be0162258982be870d6135b0870986f66c19cf315552165fdccdd2acdff62cddeba67ca0e9578ab629d895a81f63c2262362a49ef4bd8a25dbf", 0xa81}], 0x1)
syz_emit_ethernet(0x56, 0x0)
socket(0x2, 0x2, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000ec0)={0x0, &(0x7f0000000f00)})
open(0x0, 0x0, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
sendmsg(0xffffffffffffff9c, &(0x7f0000000380)={0x0, 0x0, &(0x7f0000000500)=[{&(0x7f0000000080)="c9777d04151cf5379168d599", 0xc}, {0x0}, {&(0x7f0000000180)="599829a7e35d50feebbd50a6b82aa98f31cbc19c715c9339fb9a5b63fea0c99517c6a8c415e2f8da5d3f97ed11f14062c14364652590d25a93081fd3fb075fc246d0aa9393f4b3a767caf14487e228f5e056e1d6b50934d3c35a6cb25039bd47fa3706c98407c2bca885e626142b9d2332459031de", 0x75}, {&(0x7f0000000280)="2dbadba001e777029cffa4c50e097be8c63ff9b5dcb94d86ef34528218c83a7225dfc1678301f8daf2edf069ca146ff6c62a635cb68b1741a2f161e220ac3d3c38931de41a015a26028553d4f059ad322d4da1ef5fdadfffacc200c0c980e30f61c975b7a51c43c96dfb489548ecb860284c2b4f38218b1edf181500c2d93075a87548bc84fa29009387b29c1eb0813b98759b7b7e44", 0x96}], 0x4, &(0x7f0000000580)=ANY=[@ANYBLOB="580000000000000001000000000800007dce30a9170466abc814fda9b4e8873a7803e99f6ef631cc8d9475f682c99b14cdd078d175e1cb47ddbe6f7bec06b2ccbc557b2c856325b1075c60a8fd398258df000000000000003000000000000000ffff00000000000033c5997ad07408a573e94b893bfbc21e0ec8b72d2f1d63e71e825629340000001000000000000000ffff000003000000780000000000000001000000256a00004009ee5664120eede8c953b5114a0607549b98199556f324adc53f01cdc480dd929a6379c29c525797e9c33241db684b9486900cfe8e200242a086761bdac195a63c3f3b3e17e9e3658f3f4e928d4ba444f4fee9b95c8edd490f7a28c8252b17620000000000000010000000e946e1d322e5a224126abfd2"], 0x120}, 0x0)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000280), 0x8, 0x0)
ioctl$VMM_IOC_INFO(r1, 0xc0185603, &(0x7f0000000300)={0x0, 0x0, &(0x7f00000002c0)})


setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048", 0xe)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f0000000000))


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x1, 0x0)
ioctl$SPKRTUNE(r0, 0x20005302, &(0x7f0000000040))
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r1 = getpid()
r2 = getpgid(r1)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x8000004000000001, r2})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x18, 0x1, 0x0)
r4 = socket$inet(0x2, 0x1, 0x0)
r5 = dup(r4)
setsockopt(r5, 0x0, 0x24, &(0x7f00000000c0)='\x00\x00\x00\x00', 0x4)
mknod(&(0x7f0000000000)='./file0\x00', 0x6000, 0xe02)
r6 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0xe0)
mmap(&(0x7f0000fff000/0x1000)=nil, 0x1000, 0x0, 0x10, r6, 0x8000000000000000)
socket(0x6, 0x0, 0x0)
getgid()
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r7 = socket(0x18, 0x1, 0x0)
r8 = dup2(r7, 0xffffffffffffffff)
setsockopt(r8, 0x0, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x2, 0x0)
setsockopt(r3, 0x27, 0xc, &(0x7f0000000140)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r9 = socket$inet(0x2, 0x1, 0x0)
dup2(r9, r3)
r10 = semget(0x2, 0x4, 0x300)
semctl$GETVAL(r10, 0x1, 0x5, &(0x7f0000000180)=""/147)


syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x1, 0x0)
r1 = socket$inet(0x2, 0x3, 0x102)
dup2(r1, r0)
bind(r0, &(0x7f0000000000)=@un=@abs={0x0, 0xd}, 0x10)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000006c0), 0x1, 0x0)
writev(r0, &(0x7f0000000380)=[{0x0}], 0x1)
execve(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffff9c, 0x80104277, 0x0)
socket$unix(0x1, 0x0, 0x0)
msync(&(0x7f0000952000/0x2000)=nil, 0x87abbe8d1cc6ad9, 0x0)
getpgid(0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0xfffffffffffffe8b)
socket$inet(0x2, 0x0, 0x0)
syz_emit_ethernet(0x2a, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
sysctl$kern(&(0x7f0000002240)={0x1, 0x3a}, 0x2, 0x0, 0x0, 0x0, 0x0)
setitimer(0x0, &(0x7f0000000000)={{0x4, 0x1003}, {0x0, 0x80000000000002}}, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
munmap(&(0x7f0000000000/0x1000)=nil, 0x7f7fffffc000)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r1 = socket(0x2, 0x1, 0x0)
shutdown(r1, 0x1)
recvmmsg(r1, &(0x7f0000000240)={0x0}, 0x10, 0x1, 0x0)
syz_open_pts()
syz_open_pts()
getsockname$inet(0xffffffffffffffff, &(0x7f0000000140), &(0x7f0000000180)=0xc)
setegid(0xffffffffffffffff)
r2 = msgget$private(0x0, 0xb)
chmod(&(0x7f0000000080)='./file0\x00', 0x1a4)
setuid(0xffffffffffffffff)
setgid(0x0)
msgrcv(r2, 0x0, 0x0, 0x0, 0x0)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000080)="b10005010000009f0500070007010000331c13fecea10500fef96ecfc72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f335c223e7d0c032bfa896443a42118210000720fd38bfb0000fd54c125191b1257aea8c500002002fbfe0c2300008abfba0902000000e371a3f8343712051eeab70800000000000000ffffffff00"/177, 0xb1, 0x0, 0x0, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
recvfrom$unix(r0, 0x0, 0x3a, 0x0, 0x0, 0x0)


open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
r0 = getpid()
ktrace(&(0x7f0000001d40)='./file0\x00', 0x0, 0x1720, r0)
r1 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000000)='Z', 0x1)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, &(0x7f0000000300))
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r1, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f0000000300)={0x0}, 0x10, 0x0, 0x0)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
r1 = socket(0x18, 0x3, 0x0)
close(r1)
r2 = socket(0x800000018, 0x2, 0x0)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x18, 0x2, 0x0)
r4 = dup2(r1, r3)
sendmsg$unix(r4, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f00000001c0)=[{}, {0x81}, {0x6}]})
syz_emit_ethernet(0x1046, &(0x7f0000000040)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f00000000c0)=[{0xc0}, {0x25}, {0x6}]})
syz_emit_ethernet(0x127, &(0x7f0000000040)=ANY=[])


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, 0x0)
socket(0x0, 0x1, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc018696c, 0x0)
r0 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r0, 0x8020699f, &(0x7f00000001c0))


socket(0x18, 0x3, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000200)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
close(r0)
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)
mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x412dff)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x1e56)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x35}, 0x4, 0x0, 0x0, &(0x7f0000000180), 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000000c0), &(0x7f0000000240)=0x5d)
syz_emit_ethernet(0x3e, &(0x7f0000000140)=ANY=[@ANYBLOB="ffffe5ffffff00000000000086dd6073d477e407000000000000000000006b00000001ac2c0000000000000000000000000080"])
openat(0xffffffffffffff9c, &(0x7f00000001c0)='./file0\x00', 0x0, 0x0)
open(0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x9, 0x0)
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x2, 0x0)
ioctl$VNDIOCSET(r1, 0x81946467, &(0x7f0000000180)={0x0, 0x0, 0x0})


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
ftruncate(r0, 0x8531)
r1 = socket(0x11, 0x3, 0x0)
sendto$unix(r1, &(0x7f00000000c0)="b10005236000009f050000002010000000000000cea10500fef96ecfc727d3357ae302b37b67ca1f2d61db7f4de57804be38164991f7c8cf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f4d335d223e7db3008b95665bc6fc2118000000720fd38bfbb770c1f5a872c881ea772ec5890405b3b9c2668396f4cd1257aea8c500002002fbfc0c2300008abfba0900000008e37f71a3f8343712051eeab71d89e000040381ecb664000000", 0xb1, 0x0, 0x0, 0x0)
setrlimit(0x6, &(0x7f00000000c0)={0x6})
writev(r0, &(0x7f0000000800)=[{&(0x7f00000001c0)="7fd0465fe1a1e3d1f958e0e0f9606dbfb8e31b42b753bdf405b0b2f2bfa8fd556978b0a48081089466e1d9d53dcedb58930f6c099512794b886ff08b4f8c565151db", 0x42}], 0x1)
r2 = socket(0x18, 0x2, 0x0)
close(r2)
socket(0x800000018, 0x0, 0x0)
r3 = socket(0x10, 0x1, 0x1)
getsockname$inet(r3, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
semop(0xffffffffffffffff, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
writev(0xffffffffffffffff, &(0x7f00000000c0)=[{&(0x7f0000000180)="a91d572018dfc112b211c9b7f9dbdc4e", 0x10}], 0x1)
openat$null(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
rename(&(0x7f0000000080)='./file0\x00', &(0x7f00000000c0)='./file0\x00')
sysctl$net_inet_ip(&(0x7f0000000000)={0x4, 0x2, 0x0, 0x1c}, 0x4, 0x0, 0x0, 0x0, 0x0)
socket(0x18, 0x0, 0x0)


r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
r2 = syz_open_pts()
fcntl$lock(r2, 0x8, &(0x7f0000000080))
r3 = kqueue()
kevent(r3, &(0x7f0000000180)=[{{r0}, 0xfffffffffffffffe, 0x1}], 0x8, 0x0, 0x0, 0x0)
dup2(r3, r1)


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000440)={0x1, &(0x7f0000000100)=[{0x15}]})
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r1, &(0x7f0000000040)=[{&(0x7f0000000380)="079facfaaed69aea4dc561c3b736feac0a2a76087be8b904ddc6f90b66e0f69b6dfba683b348224cf0ccc2a39b0f79389a2bd9b211424a22ca014b9231e253e257706c75b3f320166475c72455021edf575fab8b5d65b8d261c87c3ccc4e784ea7462f3723edabb8e26d27acb1797e2ef4db27270a", 0xffffff01}], 0x1)
pwrite(0xffffffffffffffff, &(0x7f0000000480)="103924d891c20d1c", 0x8, 0x0)
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000140)=[{0x74}, {0x60}, {0x812e}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
fcntl$dupfd(r0, 0x0, r0)
select(0x40, &(0x7f00000000c0)={0x33b0}, 0x0, 0x0, 0x0)


sysctl$kern(&(0x7f0000000000)={0x1, 0x45}, 0x2, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x2, &(0x7f0000000040)=[{0x81}, {0x6c}]})
syz_emit_ethernet(0x52, &(0x7f00000003c0)=ANY=[])
mprotect(&(0x7f000011e000/0xa000)=nil, 0xa000, 0x5)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040))
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x80, 0x0)
semget$private(0x0, 0x7, 0x3c0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x802, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x0, &(0x7f0000000080)='\x00', 0x1)
sysctl$kern(&(0x7f0000000000)={0x1, 0x16}, 0x2, 0x0, 0x0, &(0x7f0000001440), 0x0)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$VMM_IOC_WRITEREGS(r0, 0x82485608, &(0x7f0000000180)={0x2})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000180)={0x3, &(0x7f0000000000)=[{0x4d}, {0x45}, {0x6, 0x0, 0x0, 0x480000}]})
write(r0, &(0x7f0000000400)="76e5dead6f01f8407d2100000063", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f00000001c0)=[{0x20}, {0x7}, {0x46}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


mprotect(&(0x7f00002f2000/0x4000)=nil, 0x4000, 0x0)
minherit(&(0x7f000006e000/0x2000)=nil, 0x2000, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil, 0x1000}, {}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f00003f7000/0x2000)=nil, &(0x7f0000158000/0x3000)=nil}, {&(0x7f000003d000/0x1000)=nil, &(0x7f0000166000/0x4000)=nil}, {&(0x7f00000c3000/0x4000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f000008c000/0x3000)=nil}, {&(0x7f00006c4000/0x4000)=nil, &(0x7f00001c5000/0x13000)=nil}, {0x0, &(0x7f00002d9000/0x3000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f00000e0000/0x1000)=nil, &(0x7f00000d8000/0x3000)=nil}, {&(0x7f00000ca000/0x2000)=nil, &(0x7f0000171000/0x1000)=nil}, {&(0x7f00000f8000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {}, {&(0x7f0000ffd000/0x3000)=nil}, {0x0, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
socket(0x6, 0x0, 0xe)
r1 = socket$inet6(0x18, 0x3, 0x0)
getsockopt(r1, 0x80000025, 0x401, 0x0, 0x0)
dup2(r1, 0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0206921, &(0x7f0000000080))
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x8040691a, &(0x7f00000001c0))
r4 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
fcntl$dupfd(r4, 0x0, 0xffffffffffffffff)
setitimer(0x0, &(0x7f0000001600)={{}, {0x1}}, 0x0)
setitimer(0x0, 0x0, &(0x7f0000000140))
ioctl$FIONREAD(0xffffffffffffffff, 0x8004745d, 0x0)
r5 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r5, 0x8020690e, &(0x7f00000001c0))
ioctl$WSKBDIO_SETENCODING(r0, 0x80045710, &(0x7f00000000c0)=0x5)


setrlimit(0x0, &(0x7f0000000980))
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
setrlimit(0x0, &(0x7f0000000980))
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
open(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000001c0)=[{0x50}, {0x7}, {0x40e}]})
syz_emit_ethernet(0xe, &(0x7f0000000100)=ANY=[])


ktrace(0x0, 0x0, 0x0, 0x0)
sysctl$vm(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x1}, {0x6, 0x0, 0x0, 0x5}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f0000000040)=0xfffffbfc)
writev(r0, &(0x7f0000001b00)=[{0x0}], 0x1)
ioctl$FIONBIO(r0, 0x8004667e, &(0x7f0000000000)=0xe0000000)
write(r0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000008c0)={0x3, &(0x7f00000004c0)=[{0x3}, {0x4d}, {0x8306}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000180)={<r0=>0xffffffffffffffff})
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
r1 = open(&(0x7f0000000180)='./file0\x00', 0x0, 0x101)
ioctl$TIOCMGET(r1, 0x4004746a, &(0x7f00000001c0))
sendto$unix(r0, &(0x7f00000003c0)="53866f0e029a45b469efb220f11011fc73a6b12bf1fb5bf33562618d13786aa5198a8504f3713289cdd0a0cd8049a6c0fd7f56a04d41ab1997a7f1108813892c5654a92579d9bf8414b1f208f67ad182d4d75ba0", 0x54, 0xa, &(0x7f0000000000)=@abs={0x0, 0x0, 0x2}, 0x8)
open(&(0x7f0000000200)='./file0\x00', 0x20000, 0x106)
syz_emit_ethernet(0x2a, &(0x7f0000000100)=ANY=[@ANYBLOB="ff019aff"])
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000100), &(0x7f0000000040)=0x2)
socket$inet(0x2, 0x8000, 0xbe)
setsockopt$inet_opts(r1, 0x6, 0x0, 0x0, 0x0)
pledge(0x0, 0x0)
listen(0xffffffffffffffff, 0x0)
ioctl$WSKBDIO_GETMAP(0xffffffffffffffff, 0x80047476, 0x0)
ioctl$TIOCSTOP(0xffffffffffffffff, 0x2000746f)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r2 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r2, 0xc0106924, &(0x7f00000001c0))
r3 = kqueue()
kevent(r3, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r4 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r4, 0xc0206921, &(0x7f00000001c0))
r5 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r5, 0xc0206923, &(0x7f00000001c0))


openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
sysctl$net_inet_udp(&(0x7f0000000240)={0x4, 0x2, 0x11, 0x2}, 0x4, 0x0, 0x0, &(0x7f00000002c0)="2f616e1218c42968445e60284ecba63997ef7833b8f195d4261289f70cb8ca3a859b7b92f5712b31d72adf89be9b6b43880d8685af500ab2002859cc10757886b03763e86da19f8d7bd05ac93d8142bbea932da4d3e9d625d545773376aeaa7e0aedd87f510fc5a9bcd03246b8f307a5c46f784c186544cccc7dabaf06a311ebee6d4cfc2b5630295d922e1ed7812b3becaee22d7afd6daf091bb78f8d15d370c30bb23584bc59a2", 0xfd5d)
r2 = getppid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0xffffffffffffffff}, 0x0, 0x0, r2})
pipe(&(0x7f0000000000)={<r3=>0xffffffffffffffff})
setreuid(0xee00, 0x0)
r4 = getuid()
setreuid(0xee00, r4)
ioctl$WSKBDIO_GETMAP(r3, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r5 = fcntl$getown(r3, 0x5)
ktrace(0x0, 0x1, 0xf32, r5)
dup2(r1, 0xffffffffffffffff)
poll(0x0, 0x0, 0x0)
poll(&(0x7f00000000c0)=[{}], 0x1, 0x0)
select(0x40, &(0x7f0000000040)={0xffffffffffffffff, 0x0, 0x3, 0x0, 0x1c}, 0x0, 0x0, 0x0)
getsockopt(r0, 0x0, 0x6b, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r6 = socket(0x18, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
setsockopt(r6, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


socket$inet(0x2, 0x3, 0x0)
select(0x40, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4000000000}, &(0x7f0000000040)={0x3f}, 0x0, 0x0)
r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f00000002c0), 0x0, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x40)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000300)={0x1, &(0x7f00000000c0)=[{0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x33}, 0x2, &(0x7f0000000100), &(0x7f0000000080), 0x0, 0x0)
r1 = semget$private(0x0, 0x2, 0x0)
semop(r1, &(0x7f00000001c0)=[{0x1, 0x13, 0x1800}, {0x0, 0x3, 0x1000}, {0x1, 0x20, 0x800}, {0x0, 0x9dc8, 0x1000}, {0x3, 0x0, 0x800}, {0x0, 0x0, 0x1800}, {0x4, 0x1, 0x800}, {}, {0x0, 0x2000, 0x800}], 0x9)
bind$unix(0xffffffffffffffff, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
seteuid(0xffffffffffffffff)
socket$unix(0x1, 0x5, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
mknod(0x0, 0x2000, 0x0)
r2 = socket$inet(0x2, 0x0, 0x0)
semctl$SETVAL(r1, 0x3, 0x8, &(0x7f0000000180)=0x5)
setsockopt$inet_opts(r2, 0x0, 0x0, &(0x7f0000000240), 0x0)
socketpair(0x2, 0x1, 0x0, &(0x7f0000000000))
socket$inet(0x2, 0x0, 0x0)
dup2(r0, 0xffffffffffffffff)
ioctl$TIOCCDTR(0xffffffffffffffff, 0x20007478)
syz_emit_ethernet(0x3f, &(0x7f00000005c0)=ANY=[@ANYRESOCT=r0, @ANYBLOB="700002007dd1a800020000000000000000ada26a792ad6f9d3c2fa6f179f00d91d01aa2c22df3e81eff1fe388af5f800"/60, @ANYRES32=0x41424344, @ANYBLOB="ffffffffffff000000000000080045000031000000010000907800000000000000004e22"])
r3 = open(0x0, 0x0, 0x0)
r4 = syz_open_pts()
ioctl$TIOCSETAF(r4, 0x802c7416, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x7fffffff, "2cf748460adb56e8dd42caee5275882ceece40cf"})
writev(r3, &(0x7f0000001740)=[{&(0x7f00000004c0)="e894fa42536fd08ef59d6601411f1d2a07ba8da13fdc6deb33b10b7d51d2ea9065a2cdea987277dc5b64ccc69e495be72c200000000000000084f47c73b091ed96d22c04bc7dc993c69e0bf20f91364150ff0a679eb2903d2d2f3d1f5d2d7bb4a89634b02915e291cedca7417be388cb0e9e35f070127ee695d4312c9f8c380d69924ec4c82192ba17829bacd3b138ad10e120fd6e914e5696d08b620b1c81f2529d5432c0d8f4c8e691ae76263cfc112f11515b6506a3d67b89fd02f649dee4899a47f6501882", 0xc7}, {&(0x7f0000000240)="b090f865593f3183", 0x8}, {&(0x7f00000006c0)="8153c2f4df6834286f9fc77492a2ca3ce0fe2b42d45725afedaf3c01ee9b71d34034b24f95efd0663f1006ebb3e8255805be820c2e3e5559ba9e1dbe490e9fa7feeaf941e483f0822cb218e8818e3e5804dd4f4c0b5e875093da125ae2a9dc61166e9207734a8b12c9f1841c3cfc49ce8bb1eceb3814d0ca7c6511e0a26774f7a0ff3e9fdcf82c48f9b1ddd9f77b212aa007418e915f04382c8a7ec39771bc65e66853ff97cbdc9a70e871de10e92da79e70f7d6a6164ee26375cfd35871db3d39ecc1a7fa4c532222055432c8f628ab1dbe9e2d42f0c8180ffc9b0207afec7cbf2de4b8c6bf1b8793eeb085af5d2420809ddc3049487ba1b1dc8f5ed445617e4dc872beb51f332ba5390b77de93a13479f0e5104a7638bf8b7abc4967e5401f6ea0d6200bbbe8d42614ec38131dadc22ea53b56261179ce693659e5d03c826c4e56d6052807c946489344779015820d1c8d6e43f779157761d79ab24d34545462f36f6d02a87a8ef95333fcbd38dec10968e38b488c7ccaed070202c76a2b0e7dd6e4ba29f2ce96ca3804895e6a26dd019f5666abfb3191abf035338d5ab2434095cc01c1106e5ff4eec92ec732c03998345a7cfbe4cc0972fac549005f49b6713a8c7d11673d4a0caf1ef3f4e0414c873b62b8922427daf7416f2e13162944b9f94481e0a831c23030c62226fa1e77735af9e8f618d41ccc37b52e34028a5e8fd14e770b7a1902dab309fc7d94b6ba7856b8cc02450bf72ed8f89a01d72022a577f5b67c350980b3f64ebb0ccdc2dc344abf5537940d5ba123f83abdfeaeda8ce107eefc9696b6d18ffd35b3ffc682bd7a50deb5b8002fa087c4c837a4920461df824dab2ca28517294c2d55187035528e3644c52757673d355521982e0c1ef6bcb8797a19f2bbdaf4f3b5eaedc331ccffe212f87e4c8834e7f64e98fe1124c7fbe03bea9b7d5d43c3d9b6c2cbb3b72090e2d75f486101390748acd8a393d6a72a3bcdc787f795fbf7170246492dd5675e25c591e231b9b01e90c15a68d7e24cc6db3eb1bf6c208cd41a67a93541c94cfa88d6e0e4e05d4daff45d93e35f05dfc75a90b4d2b244053d15c51862a929ce86a7f58e5a5d7c78aa86626e59d1efa639feb21855672efc820ac0902a823de044a437a7444d197d4ef9556bf849820a18028615531ba04952a8a798e11e2f77691150367738489360edd17b157d144b303905fee9e3a668abffa35cd9d90bf546efcdc3e3eb2dffd372b3129637dfd529ae41ffaefc7d7c296d693f45f03bc43112de8af4e75cf234d9c3f26c591287a3040a1ac2c5951c795e87631a0c2eb2353ed8b40012df35de7627ea161f16aa90fde480d9d65a556d0306e5b6659d3f8bb583594352e59dfdf9df6d7258aaab4c194eb86078fcf2b5a7ee2b8145d881a32c863ae2501811c107a7c25c78815f19fb49e74f43d54c16debb90541df8393a43557580db243fcb87152461181b635b03b95ccca4692c969d7a42afa6592b08f291d640305f6f6cb11ed7b96f3b3725c585e0d8077e4943711f4f896fbddd0301f99ee96fe7d8ff81dcaa223fad00c6e01dcb4f7a12fb9d5d6b6531cff66a03fc3b4b0ae0127e6045017a7dfb7f83eafd6c03cd649f244d8e7f80d5736c29957fe6d50c099ea174642b67ed1f7c1ccc200f7521abb8ebf0698dc3b9ef178cd882bac31bf1651de142962cf51f6d0d3582ea0456852908810bcc3f5b4c72a4e0d4c30cd841148faa8f9b34f1d55b59f704309c4cff2cd991b3e3cc30a325aa8e5f12cd05e9ade3e8033fed3da60cd461de1622b74094dcea78ca727513991241f15b9248507ddc95c3b65f232ac42274070add6c16d61b56cdcd5f5237807a8820959c8e855588bc57f8e31991f21f0647a4504360bc3389d35a531883bc36c0fca669c036542d3ea00403af8f4f843894b5cc512e7425edc5993f534c0e34a8bc6f7729ccf2bc82ffcbc43721753069b61590b338dc958821d52cfdbadcc42822a4b050e6e1ed1da3f977ca587e852c1c9439f1ad53f0491bfc0c861c97e52e1d5687ad6a3e19d9c1e5a341cd3b47c6dd80a4a6c15a101d849f6f050114b4fd0346cdf08485fd7b351d62773a229c5222d4710856bd3efd13cee0252d998d6cd68f2584a8f160b354a55025422ac8af9979d4929a05274270675af96b5942123a921635977573531162e1928bbd290f25723569a3a5eadf9ba86dc4c06a50d8f8614e2f51b4d415353a3fb8fde3cc93d7d8f5158a770a2fab827929f213954b8d8187a15c717e3b3095b6cb9ae2d63209e3f5ac96836b0bfa305920a7c989c78d0936a8756e40ac03eafb576faf693762183b1c93f8885afd417a6a904c7e23fa8c55c112a74946a7f98e9b39f2018aad027db7ce30245f3df383e78735818626bb7ea9d885527226c61f4c341d5ec64be9a601c065db764427177237383e4301298a84b840ba551ffe1c6b8584ffb1690613328fa8d28cfab6f3d6e363b71b39f7e07aa6f732a2287bbc00a14a66ad7c4bb0d03d94e2ca41185e403ccf024a6a5c94c5f7b8e66ad99c5d7a66798ec5fc3fe99c5f9ff77e1f50bd2d052f9efdd3314a777e3350797acf9942201a62550995ad4d5c2b4587f8026be2dda7712ba5a4dddfc26e600d6f98c02035c7747362af39c735385cf605a30bca64ac23c78d9c2c462a72182ec1595484e5ca3d91d26b754c7f91c40d7a633c32d8e9388accffa7c1721bb5df52e05b0c5cb053c6c74ad0b67e46301ca0fa1112586fb2fe3016c3b40cfc6ec56440a313360b6d163cf20cad1efe73170b65196b5b68c61a36c31272f47ce8db41085f38e868a1f45992dcc3614dc8dc2b4bfbd74749ad21561a56fa137dc6768571804b546890d4b072e88ece97414d9f3501d9988778830403f81b0e566da3b0e4592c7b8495e0cb0e03561f08d66a0948a15e8e1a77910bca2f6d215c1a2c9c82c8f74fa182c1d1443aa034bc3064485bf4c7dcae8738e42e19563fbcde9a2d4927ad0da5570ba5793678e4eab1d074ca922c7978d9af0679e5d13da88b6e58e63696888dbc4939c206d0ec1451b3d62f1e15ee35a236f2209ac70053a6fa48b91b3915a47d0f62c21432397c4b6062cc094e1ff2fbe0484feb2c27fc8161b257c5acf42ea1bce126c35937770768f5bd604adcc0d3fb20729a821b5eab770207bd891bc49f293372e0a66b7dd7e51dbc73f085668b9b81ae53ef6aaa946fd5bae734ca49d35a23d3d1252a38dc036909580881d5efb68f2e1bc11420096713be8135f7f74ec46caa05b881eacdb1cbc7569164bac796095692bb96da5ef56926b427e38dcce0971ffdbf15f4e814e28f58ab5b07bdbbb9b2bfe098675f59df055c9611425b038395ff57eb218720b28c89647c10f0c168393f2e31cb548a6cd144f9a5083dd6eeef1544703527abbf16133cc6278b8f7b843984033c8ecc8370713f2f508aaccba06ef7f246db9ffcb39cf8e187d022b340a1d7a09a8abbf923ed3f1594655e908217216484f28705bd212a5918f62f590e6dedcb4fa5c9c2494145141a52a66796be1a14e06c25da3e3a9573534f6c28db3352c1215d2ac679c8d0a0d82d53e55265d1359bc6346ae7cc3fa47d470470e788dd2199fd40440c1c8f14efec2ba99bdb3ac0883815cd2d2adc9dbe1285877e1dfa3569c60eba2b003ef905af2128e619f4095fb7894065fefb7090af22faee19113ddb6a6e8663dbac14ebdb6d2ea2418d77d9b5fe8ee0dff51e8ac55f077bb00eae58c537050cb905e811f1bbcf6b905f3707365ed30e30d3131c9948a11e5d36a18a62c42d870e63de49e85dd4b5246e4134a0d72878374eedb7896fdae5f7adb3d1e009e82460aa9e3893759ceab886c1516afe858c4f66b7ef436cd7755354caf0f24b6d3c54a9b816612ff25fde59021d037bf8e05e307bb75045c7025dbf6dbadab4dff5784f3af063b12f3c0d6dce0d81c0f7cfc8e8c29cb975a2d17f8ccdb6fd788c3093c06e4639292b3340bf542901f2fea457f950e7eb0c9d441ef7986bff3a1c8ab745a13de746f7682588770c4fe3ca2e1c86a585a131d07bd5839e9dcf8c43279ac94544ebd3f6cc1344491adfd478df6b5c8203a26b9c4a6455ad8140c9bd0f16d6ec6d4e320a0d3431f87b0a91ff5c9d1dbfb0a8fb116227263995fc9f8587361461e0fd31689ede732a899f45548532696a9b05a1109395bdd5a08d80dd850e499148ba0c05da3ce3cf3bf193967289ddbb8efafbafdc19e95215dcd7d0ca85f56ff4c6325cecbac38af19bb16281781ad043a6dcb32be4e19691ea86eb6a1f8e8006631ce535f94f06495ad7677cee5ad70a1317f2d113ad0759c87be3e40fdd7c28fa49f8b9f2e311c03e0236ae5aedd86475923798210c0ffaf2c33c3fea6c13a38e52a25c5e32d70490da7956202a99f0aa0f212bbae6aad437155c93febd5ed3d88683354d0a1f65d239740f673e468c485bba7faa35dd465a23e1956f7f4c6e2e4b07788424dee6960ef6e8ecb394fff2d6b12707699bbe89c5bcff9b97236fd2d0e12b563186f01e3c058383a6a51003f82082af1b4e94f825a82f3246554609334351200d968a9f1b61bc7a2dd357a8c188b6e8eb3b9473f7a04f7771efac4ac9673f3b50f08874afe6019d9912083d6850b9225b4eecb6c83870e55664b9a17a91d89a2515366912fe23b90d450a753e01dde3ad21e75343fcc8268c936a7fb001aa58d5ff72574e07334bc7cdc095d2bf4b0ebdd4030cac3e8a5712033a9367f215f123291276eba49b6f662364e85554ff1cccedb2b96fcff2a65a1bfca2d94c2e9889f42b942ee5247cc15918487b5802c21bc11cde5e6907d0d5857fb5738ffa3fff5edf3959c8388ec067377bcc8f256f1c8fdd20b398ae2e8ef17b45e93fd6b07e76eaa254f3d885401cc4a0a24cb6aff5ce557d62649f4cc8ea90e3fac434c6f9352e687004148cb449f7b1a57da7a7ce8ed7535d2b7793679a2289b2cebde8e066462672533d6d372298a85c2c8f6675e6ed28f9371d15fe79103aa5072e2c4ce5ed320a4e6bd94ff1695ab10d279570c5a3b746970d6c4a5500167b183ec0b3e8137ae9b585a6e21a8d662f8c1b94aaeadc4a28188c29babc94f2f1be790f99ae6fb56f2eb7a52856a9164793d6f787b414996155c42af06c8780ce8b4e4f2215478921ebbe4c7e652e1394ab60dc9fe2bda77812f402f9e9546140354ae6d3dcff1e150cc4f5a939fb12ec0bb0074ef950a27698b3a5a163f68a1d28ed57462120b79a0ab9d8c77f9b8b6614f9bd5a53adfffee7f295e413f54b23d79ac1ce5ba18ff171ccde935433ec9e796e69a44090514a067494d8237843b81d01cc85b425e54a45182b27668cf93adad626839fef0be272eed490a6f469898783c0ec6605292e7dbac3ba0f7d085b28b74a7be1dd13db3981b22f96fb9c9e022e342cfb65be1802123a3fa1fec29f310029fc485b0a1a392df7968f6557ce6ec86c85335f8c3129b6253cc3f9fc43aae1d45d866538eedf130d09e1f724a8202efb0cbe1d2697840ed170fae1c682ab6ffb7009698a85e9124ae0e9e5", 0xf80}, {&(0x7f0000000280)="8a559d6d4243ffbbf7", 0x9}], 0x4)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
recvfrom(0xffffffffffffffff, &(0x7f0000000340)=""/198, 0xc6, 0x0, 0x0, 0x0)
sysctl$vm(&(0x7f0000000000)={0x6, 0x19}, 0x2, &(0x7f0000000040), 0x0, 0x0, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setreuid(0x0, 0xee01)
chflags(&(0x7f0000000040)='./file1\x00', 0x0)


r0 = open(&(0x7f0000001700)='./file0\x00', 0x70e, 0x0)
mmap(&(0x7f000000e000/0x2000)=nil, 0x2000, 0x0, 0x10, r0, 0x0)
open(&(0x7f0000000140)='./file0\x00', 0x200, 0x0)
pwritev(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
mmap(&(0x7f0000ffc000/0x4000)=nil, 0x4000, 0x4, 0x6810, 0xffffffffffffffff, 0x80402)
open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
munmap(&(0x7f0000ff7000/0x3000)=nil, 0x3000)
setreuid(0xee00, 0x0)
syz_open_pts()
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000200)={0x3, &(0x7f00000000c0)=[{}, {0x3}, {0x6, 0x0, 0x0, 0x47}]})
sysctl$vfs_nfs(&(0x7f0000000000)={0xa, 0x2, 0x1}, 0x3, &(0x7f0000000080)="14bf485ca4aac46f10a190408a48d5927b9f914ef183c51c0619cd8cbbfb82e45af7868d94cacbcecb", &(0x7f00000000c0)=0x29, &(0x7f0000001200)="bbf9952ef3ee395df77af11e2154f9fd04b9ec01cd326699b45f8041fe85a59481cbbcd57bc0d1fc3bc629bd3e96141a1602f281fe84d8c71b5d6b008679dd3db39659f7706071000455f60d3e8999adf9612492a63e882a6d99d57c82c6bacdddf9cf7480588548f324abd69447558db91c41f54851a106b65c8da28c3b1b63339483d7b3fa0cbf5ff06fcdf039959461ffb34e63f4995fbc03e9417a7b40a51586682e712053bfb1f77aca1f69c98a5a924914f53d1a8b01c4872385cd1325de5c7414f684ffe2d3181ad299431ff71414eba6ff23e85ec8025d31cda5f76a92f40156e7fa53302bedaf37ef8dadd09a42b5b4bf59e5f03bc9f86c101075b7393af6717316ddcabf6716adfc4a3e73d7dfb24e95e6a78e4afec5a849e1725fc1cbe26e93a5e747aab1c9e4edad7eec930d97e2dc7ac5886a795974d148eccfa666b7184514217014159d30404bb0ca8dac5e1c43f62a892592d7844b383a3195b700c2a1f78bc32336fa031358f1d76bb121530cd31f1c87c3bf9e5b73b34270e546b0ac9b890da7e73680fe18ba4fbc51ff4d3b3f28db60cd911aa1659ff3666f166e3f73d2b00b5f4f55f271416f89728db09ba78b0a896730bf0e143a11bcc5bcc024caa62f9526655f14ab3db31dedcd7ce29a4b30a00402c79885b784e60ee6b158d6282a19e9bbdf496b3d836656e57a6726d9ebe2878df11c627ce09e0f979caaf423be33931b2cd224d57b9fba94a643897e879f6ffc85378a9b65a95473f4056b37cdd4d65deb0f2c480612eadfa2b6f049920c1ac16a752d37c7c1258836732b6c494d878073425e04e8528bc1af9ed2a9eb3be2e0b86cf6f36cc323da510a7d54220416b0f8d944363feb81b9cdf508904022a377f989b8ec72a227869d13ddd05be3b180fd34708dca45626645358563a56b13e7bdf9dc566ee6164870adad402c3057dbd0a43b1398548b02bdacc89d3f4ae0dbd11cad3e1f6859e70d0921f07f2e343dc40764a2f42efdba0411c6d05c8b23c9f29a300e7147a0c58177ef5aab200fd2f2012e1a1983995c49a5f235e42e032b365a8a115209cf85579bbae58be35d51ad5ae5edd673e7238cd9c57f2583bab7a0f9e54ab3d713ce8b2b436c519fba4196c95682af7994fa7217eeca00cf32082b910696dafb1441c69d0a207480bb52b0f823fed20977da4890591ba81245f39183b8153d2348fc34c57c9d68535290dd02ab6aca4b75716f37b20b9f20cabffad94ba4f70bcdf04d73dd4f3af1eb8864a708a480803a096318d9653bd53c265246213f3430fc7bac5956f577bb09432808aaa6e41a44328c67d73765be08db2608df6ca84f544da4b4388bc17645e4ee290d84a9d18aacf3e1283d7842eed39938baa612d975ae67a09bd37843c2a4c80a547fcbc247ee00c19fcabb78b2297458a02181899a079cbc78a241447d591da79cf99ac5968021ff27c46ff2131c60c195f7a99c2fa747567ff4154ce91acb4c369967a1a58fb12677730c56a181da1c80da68bd5f4653493f18e4e98b115296ce89fd31e18ea8ed76f603fc0ead6e1374039ce1a013843cb4184e3b2e71c5b55933b4f7b8ef40bd44033dd74fd8c7689e10131fbf6977db6f7fe0767eb5cf262252b7e2eb70a73dbc705c55b356fd92dfcf66a609717d8e8522b2c255b068b04a0992c0f1ab197e0242315a9cc1b01ffb166a07f4963c0abbf93b7c6f00b56b3f1e582a092243ac4578ae64ee3e6ea7168027d15727c0d0b1842129c3ec070ac684eb7540bae4ec03413f8b2b7f9da461c365e10bb89bad01cbfa125483ceaf6b38750c8c57b3655ab8ed211f4f75cae5bc62f4aca38942efa6f3a330d824c4638925a65634b90d26db7f3915dbb4fb5ba8e008662607a08022941c29938209369a5d011aa9ec457f2446e815c16cdca72192ccb7382a63d302da604ebc0854004b7783042ded49bbd99c09f2cf6babff0d0ac7c6431b842a96a2f719e6a11dea4d89a81a318165a66f4f127ea947d5bcfd4ecb23b10db25e31f018a7644f2191b1d8de805101d7aa2d35f8b5e63420c5882cdabd2571951c6b9583ea79c45b89c662df781a053c69d9010f362a261a569521fc806a9aed53e6764c970062dabb409936ec595e4f1532294afbb5e8f0ec133ae27bfd48cf5387474b45ddaa14971f73e4678903ee7a8bad1c1387ca5a300cebf01b2e32060e78834f8f8deca0a084b28067e9e176ca11de6b76629a55bed455e19f1f42dddee6097b266a28f666e7a66b3b9a47469deb222ab723f709b76664e8c068c341326909d642e6294cd838512842f5ed7daf7e9d4ca9e7a62b4c846c3ed1258523be1ba24466aeaf57786a92f836ed4478f40221f8530be9ef6d7bc07e8a59da24d140155fba2e3059cc9f84a9612dffc51577c3242d9279f1058db5eff969636a7a9b8d547980e4cafde3b6985942e55bb1e1626b9de52149f0403d6ef6d199bb0b8ffc53c6191596c293529158d51df1ebe6c545b33d09d3584ac5bbe9aeae0eb8c57d32dcbba6940a6b167c13d5990a7f72835eb54cd24050a1da6c1fe3f803a3e6cbcc743d90ed9ddc52649f801d7174b58f037761e51460703637a191accd7ed4d76357eca35539aad897212a4ac17a8347cce10875e09214e871664eefca144d565aa0c3af4fbc1cc01dd5e28812b7fd4ec6393693ccd61b27f71be526c6a174e12671503eda5aab48bd0a3b61d8b9764a256f15d65e19eab48c5216d7fbfd38bb55552692dbb2fbe5c4726e9c91aee836f186e568842f728683c27cbbce6a770f9bb196a6df4f498e8c025c32d6269a9a5e414728e5820d4c3b515ccbfccfccb0f5450053ca56e6adbd09504303e14cf9a2913dc6a474f18382707c81400c77761d91be5ad42ff4f3f1e1639542d88b065fb678cc06a087811197c012cfdbfc4ac095c5360e3fb73587252062dda4f501f69b58e783bfd9d2ce3a6e7057ea012704d93ba155faa7229000e1c200a71ed2183fdd8f68748c6d946af99e49c2ce8daa8b1c0dff05f84ffb693c6956c1696ae26b1ddf5ca80ddc4c07e8968b3a4d035426d73351889b8fe0fd5cf0d780df58890ca6fcaf3b3b4a6800e71948e1359cb54e667cbd0484264fd498b4c31d27efdf4d5eddf8409abc4d88b4a1059b842b1c1bd3bea1d558b47c70402b396bb621f642dde22a4b8d1ab412261a4d786a01490e98bf92787a44397fc950cd1ec720bcdf346dce8bd47106982e218418400627d2eb0966281d53b1813692f90431a4099682c3e88a1fed5c544cde30d02c0486448176afbc38e0c4f6f272f432479930e1dfb6774cadae0620e12cf1d9f8bc1b0b311a7ad55031a7eb2b5a561c2fb4640eac94eb1ab690d03f0e99887ed9fa8ebfd4e7fa7ff0a0292e747911cd2084d97ccc6dafda721833f36ce050218edea77358bbbcae0cac5d69785c4c1b3ec43f393a38a388bf3d218dcadac4afe337452c62e0a788d35d74b3c1629c8fae16a52b2ef890a676ea753e9ead011a78c8b38f9d1afab95d6f9ed59b6b9f5462be62afe8a9d9c9cc739aa237e2a01b922872351dc33cd6944b25ef73fed4c4c390705fe5f7d97d2d06964f57c54d05da1d75e272101fca7099e37534c0d06c4e328d0d3b6f39d8afa0152d3d04fc7013cd56a03d62133219abf0b8872204cb6b8b46cd6c67f8bd09743220c1ef41c1e23ddf3035aa0c5df96ab75764e50d3ed29b4e58d2d68f6b58d3a2246d6b66cd934d46226980c3e00ea77234d45172138439b1078bda8782010237ea4044540d17e1199fb3dbac6710f93e53554a854623847aff5adb7a9581dae7cbd9d0474e42439d7bdb90324baa503d0250cb81e382fc7722bccb5434db68c76d510b246b1c58a2c1382efd89f67153b2a8f56e6b845a33d16efac20796aa77876c27a6ec33b6e439e23a327558ad70f6920e6280731c351832cdfe7820fd4b0c08bbe0096178ded6dba2fc5da47cdb2f031ae275f5b96ad3c06b51b986be2198163a5b55986b4e60ccdcebd0b4b1668937f645918d2c1156597670b3920a10338268ada04ccdbd16d3d59b6fccb49adf8dffdf720142f3fb718f0e08e19f1c149d0335e0ce0002e578e8fd4e45fa6d3a6138feacbf0955d9b6666f98729ce4c8e6510ae2ce6bfcbf1205219f180b7d327d3b97c062c5f92a5c35769ca748c2f8552a275a15161a208047237e023e8fac1ad5b0cbc728c6122530ec7703a751490fc6aae8db7b904c9cd8495bde10bb4b09b64a45d405963ce763d845eff6d56e2fe80970a22965c092f817fc4a2cce8b8c2ba9cfb4f413f0e4b843e5b073f01e7186c2f2b27a3b3bd157be46b7b94997f8d955d2d694b00d6fa54b8e2006a30dcf6c49724819ba7adc05355a3da94808eeba24af292493bd04b68ebd13fa1a360aa5a5120527ce4838f99103db043f2ef6bf3e42ec72bc3115a7995eff3d1480d6667d0c7998924ac1be95e82656828e25bccda679b27537a549554b81d308a9aa9b11ae4dd53792deb3d78266c83d222af983248dbe2483e117d18c2b5ed9ea9975f8a03495e6bb1a9df659d98678f7a2618720c4cd6d7e058e86f61950966282a940089f6a4c337e8cfe80c449cabacad2a7b98f4eaf659d0eecce958f18462591384b470cefd7803c71f02609968849db50196ae07dbb0a183e3a81c42c286707c12aa99bc0edc02b0785284eeecbaea3d26c43f07c8b07533a40422edb05624c0e313a9d020219941168e7c2c8dc3ccdf63fe4", 0xd37)
kqueue()
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000340)={{0x3, 0x0, 0x0, 0xffffffffffffffff, 0x0, 0x40, 0x8001}, 0x0, 0x0, 0x0, 0x0, 0x67, 0x7, 0x3f, 0x6})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f00000001c0)=[{0x81}, {0x20}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
r2 = socket$inet(0x2, 0x1, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x200000000000b, &(0x7f00000000c0), 0x0)
pipe(&(0x7f0000000140)={<r3=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r3, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r4 = socket(0x11, 0x3, 0x0)
sendto$unix(r4, &(0x7f0000000000)="b10005136000009f05003e0800000000331c13fecea10500fef96ecfc72fd3357a068d02bc31a3a5673039d2d236acf20b7804be38164991f7cccf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f4d335c223e7d026ba8faff0037720fd38bfbb770c1f5a872c881e2772ec5a10400000000000000361b1257aea8c5d0002012000000000000880d6633c556ae9b287948a62310db415f779642cdcd71a3f8343712051e000000000000", 0xb1, 0x0, 0x0, 0x0)
truncate(&(0x7f00000000c0)='./file0\x00', 0xff48)
open$dir(&(0x7f0000000040)='./file0\x00', 0x2, 0x0)


open(&(0x7f0000000180)='./file0\x00', 0x200, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x53e, r0)
setrlimit(0x0, &(0x7f0000000980))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000240)=[{0x6c}, {0x14}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


r0 = shmget$private(0x0, 0x1000, 0x0, &(0x7f0000003000/0x1000)=nil)
munmap(&(0x7f0000002000/0x1000)=nil, 0x1000)
r1 = shmat(r0, &(0x7f0000002000/0x1000)=nil, 0x0)
open(0x0, 0x0, 0x0)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
shmdt(r1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{0x87}, {0x28}, {0x4000006, 0x0, 0x0, 0x3feffe}]})
write(r0, &(0x7f0000000180)="23009100007adb020317bdda2b7e", 0xe)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x0, 0x1}]})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000000c0), &(0x7f0000000240)=0xc)
setuid(0xffffffffffffffff)
utimes(&(0x7f0000000000)='.\x00', 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x37}, 0x4, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3, 0x0, 0x2e)


r0 = syz_open_pts()
poll(&(0x7f0000000000)=[{r0}], 0x1, 0x0)
syz_open_pts()
syz_open_pts()
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)


setrlimit(0x0, 0x0)
openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
ktrace(&(0x7f00000032c0)='./file0/file0\x00', 0x0, 0x0, 0x0)
r0 = socket$inet(0x2, 0x2, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f00000002c0)='./file0/file0/..\x00', 0x100, 0x6)
r1 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
setitimer(0x0, 0x0, 0xffffffffffffffff)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000040)=[{0x0, 0x81}, {}], 0x2})
sysctl$vm_swapencrypt(&(0x7f0000000040)={0x7, 0x2}, 0x3, &(0x7f0000000140), 0x0, 0x0, 0x0)
ioctl$WSMOUSEIO_GETPARAMS(r1, 0x80105727, &(0x7f0000000080)={0x0})
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r2 = socket(0x18, 0x2, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r3 = kqueue()
mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
rename(&(0x7f00000000c0)='./file0/file0/..\x00', &(0x7f0000000040)='./file0/file0/..\x00')
kevent(r3, &(0x7f0000000000)=[{{}, 0xfffffffffffffff9, 0x41, 0x1, 0xfffffffffffffffc}], 0x802, 0x0, 0x0, 0x0)
sendmsg(r2, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000340)=ANY=[@ANYBLOB="8500000000000000000000a14bf6a61733e5962b94ee71010000000000a46d8d12db6edfbe0b83da64a6824b01be262e604a8f4c5721e6490dd2d23817111a19eb77d03ef43e3561fc9081a0da13ad5d8b99e464b83282e8b98a9b55fef3ca377e377d6fef9bef3ea00cfd3a184339d3f2e85fd0e9c073eade30f5f1b211c3f4472641b22115794b8af9f4ec85b1740fa47c9c575ec5393cead0318f0615a28fdbc759b4f4300c8324306f78897f9e3b3e105cab5226105208d5cd0607cfe0546f35a16ce138b233ffe728994156ee9803f13822622a1f0f429b296deabbd7f8188ed3901c7ff0d46c1556da779c68fa69341dbc1ba18cacb52b71698e37eb1db064c4bbebf04b3de553c8f863df6025f5486c9c6f08883de1ab2de7090942377c3845c3510ba9fb962c97645aeba8e74f35c71d4b5c9709036d798600fbdcf87613c2d614c02c22cee1215162a6ed3cad3bb02243fa6c7b9baf0524b9cf223cd16f96259116961db851dafeaf89f4258c13ccad28c8710adbf97533"], 0x90}, 0x0)
r4 = msgget$private(0x0, 0x0)
msgsnd(r4, &(0x7f0000000100)=ANY=[@ANYRES64=r0], 0x107, 0x0)
msgrcv(r4, &(0x7f0000003c00), 0x1013, 0x3, 0x0)
open$dir(&(0x7f0000000b80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x200, 0x0)
r5 = open$dir(&(0x7f0000000280)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000300)='./file0\x00', r5, &(0x7f0000000c80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f0000000dc0)='./file0\x00', r5, &(0x7f0000000ec0)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
open$dir(&(0x7f0000000040)='./file1\x00', 0x200, 0x0)
mkdirat(r5, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
symlinkat(&(0x7f0000000040)='./file0\x00', r5, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r0})
pipe(&(0x7f00000001c0)={<r1=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r1, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r2 = fcntl$getown(r1, 0x5)
ktrace(&(0x7f0000000180)='./file0\x00', 0x0, 0xd30, r2)
ktrace(&(0x7f0000000680)='./file0\x00', 0x0, 0x28, r2)


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = socket$inet(0x2, 0x4002, 0x0)
dup2(r1, r0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000a, &(0x7f0000000000)="ea00005c00000000", 0x1)
setsockopt$inet_opts(r0, 0x0, 0xd, &(0x7f0000000240), 0x0)


lseek(0xffffffffffffffff, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000400)=""/92, 0x5c}, 0x7}, 0x10, 0x1001, 0x0)
sendmmsg(r0, &(0x7f0000000080)={0x0}, 0x10, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x81}, {0x50}, {0x16}]})
write(r0, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xfef3)


setrlimit(0x6, &(0x7f00000000c0))
open(&(0x7f0000000100)='./file0\x00', 0x70e, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x100, r0)
r1 = socket(0x800000018, 0x1, 0x0)
r2 = socket(0x18, 0x2, 0x0)
r3 = socket(0x800000018, 0x1, 0x0)
bind$unix(r3, &(0x7f0000000080)=@abs={0x0, 0x7}, 0x1c)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
bind$unix(r1, &(0x7f0000000180)=@abs={0x0, 0x0, 0x3}, 0x8)
r4 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r4, 0x0)
setrlimit(0x3, &(0x7f0000000140))
mlockall(0x1)


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
r1 = dup(r0)
lseek(r1, 0xfffffffffffffa3d, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000300), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{0x4d}, {}, {0x206}]})
syz_emit_ethernet(0xe, &(0x7f0000000380)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x802, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f00000001c0)=[{0x45}, {0x30}, {0x6, 0x0, 0x0, 0x7fff}]})
write(r0, &(0x7f0000000000)="76a5dead0f01f8607d2100000063", 0xe)


mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
open(&(0x7f0000000600)='./file0\x00', 0x70e, 0x0)
socket(0x1, 0x3, 0x0)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x4e, 0x0)
mknod(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
r2 = socket(0x0, 0x0, 0x0)
select(0x0, 0x0, &(0x7f0000000080)={0xce9, 0x0, 0x9, 0x0, 0x400000}, 0x0, 0x0)
r3 = open(&(0x7f0000000080)='./file0\x00', 0x70e, 0x0)
mmap(&(0x7f000000f000/0x2000)=nil, 0x2000, 0x0, 0x10, r3, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
recvfrom$unix(r3, &(0x7f0000000640)=""/222, 0xde, 0xd789624329d9a426, &(0x7f0000000200)=@file={0x0, './file1\x00'}, 0xa)
pwrite(r3, &(0x7f0000001500)="18", 0x1, 0xffff)
connect$unix(r2, &(0x7f0000000340)=@abs={0x0, 0x0, 0x1}, 0x8)
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000480)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
r0 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000180), 0x3a8, 0x0)
fcntl$lock(r0, 0x7, &(0x7f00000001c0))


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x100000000000000}})
socket(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x400000002, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r2 = socket(0x18, 0x1, 0x0)
r3 = dup2(r1, r2)
sendmsg$unix(r3, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


sysctl$kern(&(0x7f00000000c0)={0x1, 0x50}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x4, 0x1100, 0xffffffffffffffff)
setuid(0xffffffffffffffff)
ktrace(0x0, 0x5, 0x40000d30, 0x0)


r0 = kqueue()
ioctl$FIOASYNC(r0, 0x8004667d, &(0x7f0000000280)=0x6)


sysctl$net_inet_tcp(&(0x7f0000000400)={0x4, 0x2, 0x6, 0x12}, 0x4, 0x0, 0x0, &(0x7f0000000140)="53183374", 0x4)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000600), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f0000000680)={&(0x7f0000000640)=[{}, {0x100, 0x80}], 0x2})


r0 = socket(0x18, 0x2, 0x0)
r1 = dup(r0)
setsockopt(r1, 0x1000000000029, 0xb, &(0x7f0000000080), 0x4)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000000), 0x0)


pipe(&(0x7f0000000100)={<r0=>0xffffffffffffffff})
fcntl$setstatus(r0, 0x4, 0xc0)
select(0x40, &(0x7f0000000100), &(0x7f00000024c0)={0x1ff}, 0x0, 0x0)
close(r0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000d80)={0x3, &(0x7f0000000040)=[{0x40}, {0x61}, {0x406}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
preadv(r0, &(0x7f0000000280)=[{&(0x7f0000000440)=""/248, 0xf8}], 0x1, 0x0)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000012c0)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000540)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000580)=0xc)
setregid(0x0, r1)
mkdirat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x0)
faccessat(0xffffffffffffff9c, &(0x7f0000000140)='./file0\x00', 0x0, 0x0)


r0 = syz_open_pts()
syz_open_pts()
syz_open_pts()
fchflags(r0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSRSIG(r0, 0x80044272, &(0x7f0000000100))


r0 = syz_open_pts()
fcntl$lock(r0, 0x7, &(0x7f0000000040)={0x0, 0x0, 0xffffffff7bffffff, 0x1000300000000})


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x1, &(0x7f0000000240)="6a07199177a34457", 0x8)


sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000001c0)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
r1 = fcntl$getown(r0, 0x3)
ktrace(0x0, 0x5, 0x40003504, r1)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
shutdown(0xffffffffffffffff, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000080), 0x20, 0x0)
ioctl$VMM_IOC_RUN(r1, 0xc0205602, &(0x7f0000000140)={0xb6e, 0x5, 0x5e, 0x6, &(0x7f0000000300)={{0xfb, 0x7f, 0x2, 0x93, 0x4, 0x3, 0x2}, {[0x80, 0xe93c, 0x100000000, 0x101, 0x4, 0x9, 0x20, 0x1, 0x5, 0x5, 0x80, 0x7f, 0x2, 0x1, 0xfffffffffffffb7b, 0x0, 0xa9, 0x2000000003], [0x8000, 0x7fff, 0x6, 0x6, 0x8, 0x3360, 0x0, 0x5, 0x0, 0x400], [0x3, 0x7, 0x3, 0x9bc, 0xd72c, 0x10, 0x8], [0x80000000, 0x2f9, 0x7, 0x0, 0x0, 0x2], [{0x4, 0x77000, 0x2, 0x7}, {0x6, 0x3, 0x5, 0x6}, {0x16, 0x20, 0x10001, 0x5}, {0x8, 0x80, 0x7, 0x9}, {0x1f, 0x8, 0xe76, 0x8}, {0x0, 0x8, 0x289a, 0x4}, {0x20, 0x277a, 0x7, 0x15ea5bf3}, {0x9, 0x22, 0x6}], {0x800, 0x4, 0xfffffeff, 0x3}, {0x4, 0x7f, 0x6, 0x7}}}, 0x5, 0x2d})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
r2 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
mkdir(&(0x7f0000000040)='./file0\x00', 0x0)
unveil(&(0x7f0000000000)='./file0/file1\x00', &(0x7f0000000100)='x\x00')
r3 = openat$zero(0xffffffffffffff9c, &(0x7f0000000280), 0x80, 0x0)
ioctl$BIOCGDLTLIST(r3, 0xc010427b, &(0x7f0000000300)={0x6, &(0x7f00000002c0)=[0x404, 0x81, 0x64fc5fc7, 0x10f, 0x6, 0xef88]})
accept$inet(0xffffffffffffffff, &(0x7f0000000180), &(0x7f00000001c0)=0xc)
getsockname(r3, &(0x7f0000000200)=@in, &(0x7f0000000240)=0xc)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r4 = socket(0x18, 0x3, 0x41)
ioctl$FIONREAD(r4, 0xc018696c, &(0x7f00000001c0))
r5 = open(&(0x7f0000000940)='./file0/../file0\x00', 0x0, 0x0)
getsockopt$sock_cred(r4, 0xffff, 0x1022, &(0x7f0000000340), &(0x7f00000003c0)=0xc)
readv(r2, &(0x7f0000000ac0)=[{0x0}, {&(0x7f0000000080)=""/31, 0x1f}], 0x2)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x2, &(0x7f0000000000)=[{0x45, 0x0, 0xff}, {0x906}]})
syz_extract_tcp_res(0x0, 0xfffffffe, 0x0)
r6 = socket(0x11, 0x3, 0x0)
setsockopt(r6, 0x11, 0x1, &(0x7f0000000140), 0x0)
kqueue()
kevent(0xffffffffffffffff, &(0x7f0000000040), 0x0, 0x0, 0x20, 0x0)
setsockopt$inet6_MRT6_ADD_MIF(r6, 0x29, 0x66, 0x0, 0x0)
socket(0x11, 0x3, 0x0)
ioctl$FIOASYNC(0xffffffffffffffff, 0x80047460, &(0x7f00000000c0)=0x406)
recvmmsg(r5, &(0x7f0000000c80)={&(0x7f0000000c40)={0x0, 0x0, &(0x7f0000000bc0)=[{&(0x7f0000000580)=""/69, 0x45}], 0x1, 0x0}, 0x3ffffff}, 0x10, 0x278e8d1fa6cbbecd, 0x0)


mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x205310)
open(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)={0x3, 0x7fffffff})
r0 = kqueue()
kevent(r0, &(0x7f00000000c0), 0x30, 0x0, 0x57d, 0x0)
kevent(r0, 0x0, 0x0, &(0x7f0000000600), 0x2, 0x0)


socket(0x11, 0x3, 0x0)
socket(0x11, 0x3, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}], 0x1, 0x0}, 0x0)
sendmmsg(r2, &(0x7f0000000080)={0x0, 0xa}, 0x10, 0x400)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
close(r1)
readv(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f0000000080)=""/51, 0x33}], 0x1000000000000036)


setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0x0, r0)
r1 = socket(0x11, 0x3, 0x0)
sendto$unix(r1, &(0x7f0000000100)="b10005016000009f0500000007000000001813fecea10500fef96ecfc72fd3357ae302b37b673039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f4d335c223e7d026ba8af630037282102000000720fd38bfbb770c116a972c881ea772ec5890400000000ff0000361b1257aea8c500002002fbff0c2300008a09000000000008e37195f8343712051eeab71d89e00004070000008004200000", 0xb1, 0x0, 0x0, 0x0)


open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000502000000000000000020010000331c13fecea10500fef96ec0c72fd3355ae30200004e3003000000acf20b7804bec256699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5aa0400020000008700361b4cc702fac500002021fbfa0c0f00008abf3a2271a3f834371205d366", 0x85, 0x0, 0x0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000001})
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
open(&(0x7f00000001c0)='./file0\x00', 0x2e1, 0x0)
flock(r0, 0x2)
r1 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
flock(r1, 0x2)
r2 = open(&(0x7f0000000040)='./file0\x00', 0x205, 0x0)
fcntl$lock(r2, 0x8, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x1000300010008, 0xffffffffffffffff})


sysctl$hw(&(0x7f0000000040)={0x6, 0x13}, 0x2, &(0x7f0000000080), 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080)=@file={0x0, '\x00'}, 0x3, 0x0}, 0x0)
r0 = socket(0x2, 0x2, 0x1)
getsockname$inet(r0, &(0x7f0000000080), &(0x7f00000000c0)=0xc)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x3, 0x0)
r2 = socket(0x18, 0x2, 0x0)
r3 = dup2(r1, r2)
setrlimit(0x8, &(0x7f0000000100)={0x7, 0x54})
r4 = syz_open_pts()
close(r4)
syz_open_pts()
r5 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
writev(r5, &(0x7f0000000100)=[{&(0x7f0000000040)="556f2ea0088416ca8fb2517aa7f23c2530c94c53f2fffa551007ee363de7ad76266cd92dbe6ffba5f3822fcce7f3176153d3777e51f79f72ab303d59f10b", 0x3e}], 0x1)
writev(r2, &(0x7f00000001c0)=[{&(0x7f0000000500)="96e9cf1c0f9fc25ac05e6f4c", 0xc}, {&(0x7f0000000180)="24c90001e896b6bd2deeb05cfa5ca5eac66aea4d22daa4a447a511a582bfc9f6c5af", 0x22}], 0x2)
writev(r5, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0xcf, 0xd, 0x0, "28b7e60ab87aa57800000000d0d2000000001c00"})
writev(0xffffffffffffffff, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000b40)=[{&(0x7f00000014c0)="874efc64a16404b3dc9c5bce1a5ecabc9ad87a2c628890d6c0144206d4f104d9344df375dfd3bb105ae821f98218363f92fa5e9c05234d33d0a8d963888d8822f30019a93c93d85f62e363a3eee977e582890dacc2371a48a4431bd985409647e571a93d2a66e5b7f67ff0c6fa6dd62af727a8200ecc56044fc7d427e40ae2086abd08e51d7b88e9dd4f2f9b44b3e969212e9d954795f6c302de6406b45beeb8f5a34ad8acf5ae86909381263bdee8839a61832d6b11df3dcebcbfd8f73f3da2e026766309eec290c2427714cfa2f92495293de2c336949475c17a49469a7b6d7d237ddfb60b74ef5f99682e18887d3bc75cfce8150b94974af2204d42c994b8910d5fd06b7bd9ab57e26310ac63c59cda6de93302b7e1812811086a2ee2ee23e61b77a6d519b43ddfe016f394ae0a2751d8b420fce01e9dda4c2a43b5318afb3b6b9e9f99d71684bfaf02ed0327a58d5049b8b62e28239022820778336a5ddba0c4c7960d4998b7e8c10e5bc641ee6fe80d267590de91d2b6b50e879119ca15c7f70420506fe54a6c5537a486e83ebbcb7e95af437eefbf299a6c2c9fb95b9983374fe6a743c52828761bfba9f79f6850214ce56ddd9a859bea12b3e8bc2e30aff6aba9a488775d52d1d2a90ec9c23c908f9bd356eead53715274ee47fc9ca4a7a5189fe1027e625b7a3b5350f2b76ec2a1e192eccbce78286f134c4523b74a953bd01754d2238f1880d748c9f55eab8aede59252ca39caad3598d6e9bc03bd59426501afd5ee61ba70ccb04e7e385f3e089c5493ce9ee428c30865f9bec095fbbc30cf50d52e5b2ee7139a6b4c99b82c5a07cb4411f2a0d19174c70e508c2cdb4cad591a33db002d7d5121d6fd26f8b31af12a1e9d2058cb2bc8e34ccb1b23bddb8306484cefecbbd8ae919fc8595c0f25940a449ea2b6f345b8bf320e0a31bbe427d2431bdd52a28d3e5b15169fde2390e3121dc18b6a6c4450a03c3f3f84d9fa5f774c529591058bb00d21bfe726575817b975fb8dc62427f9b7b4f0d22cfa9975b84eded78aa3a0edb9a13165bed3443b5f35d8c68041c081f0af3eabac120d7a8e879b525f0ca9954f2a2ea752ab18683c283410f14bd859ce8806983fd20050ef80155afb0c254a6878e3e099e796242938446a642234ba124bcaecb683bbe7526007befe7d90f120ed76f987f2f8a445dae46c794d4e345564ff042bc68c2b72461ebd498235a1212bd3ed669ac480b011fbb4041136e88003c5210d142ac0c643d3db0039e21e5d9157f26cfc71fb7fe767e9c938e51b64c22ac394c8aec52ee25a226265f632bce7d79c5b7b749b56fa67ac00d5aa0571c573f23fa3ea26f15cb679742c7b9f17e22aae2892006fef55dd244c4613134227ebd4af1e5c7867295b45f91b5bcc7fa0f3ac9daa8f49b9363e9e01250fcc8d72fdcae8f6222ae3a2fb01eef75cbb2ae84ea7fcce5ef3e86c2221ed491f5d7e0b595f574857c20cc49f9162c31e8267984a4328ce6dd4a6de2e68cb4e811391651588873eff36062bb6a7c5df5e870a050338af57644ed41e2e80e66d91dd3744a5c18ec2c30ff917fd7485f92597fe4bc3ab8e18ac1f7d3c80e86a7f1b0b8bdd2f9146a900c63085ff5c6e74dee637fe3c255f16b07f5395e2b803c44147171b52ecee292c414c5415c317b14b8086b15ce3efefcf790a3fd4faf3f3dabe410c730477a829ceb589d567d97e26ccdc6fec6ca5599414458f7c0f459ff45eece2fe4d6b031507b83c44cadf24f5a4b30a8048e4d5b267bc06cc12393fd31bfe8eab256881d2618dd41491418e636be2a412dbed78da3448a52e666d3348fdf76928d380f62dd63f3a01b32679f92d7e3df380b6af601037085266b68abcd636586a763dc244252385b5b80b6c3c3ab5c3cad35bcc7a5f6bdef137e886604f3649b1af4abcd2f3d56f708e8d9003e00866ecf76da72bff382d28efc05d53f31f05e3027d8f699c9f93967bf590c984836ebec878ddcd29fe74f0647fa32ef13201ebf2a81bfd02df5b53e13594b662358e14d9dfe6cd721b31c18e1165e6a1e586b688a97b1a41c028fc1e7d2895fbe915fada9f3c28d9dfb13eda790f67a6d0a190fa80d01a5b58196a7d4827be51f043d56a49ddff95ee20260e02c53f5967ddce1510939ae04916282e782f728f02d62a06a0dc1d285cf4811566eb93d5305696517fd89fcb90fe1ea392e9d35fe02218506581661d2b1d5f4df93a8c3b556912a29e1328c739934d4c8112563c7629040721cd0bfd5c6123b7de1b39c9adb28eb3c97df75d0266dfe02f45428a3785f0ad7ea9b0ba5ff7915ed7aded81ec61c54340c46938c4d7bf8bb2dfe0ba8b69480cd1ea64107acefb62ca76a35be999f646077813d455b51bb643de2a39f7353a9a4a0d69d2200edc3a4fc671eda7db4fa39ca2f6c68a19a5468836fde4eda83145a0569a987e4011679d993420d918a640839f02595fdf0eac4e57f69fa50cc6f01030506df03ad16d418a6fd66c4230c494761e4be904e33dbf4e46c60ac4c0bd04df0da41f1d111c2252edb39c76dba2aec9abd2b2325b5b948db76f451dc23bab13ede45a0d0d63428748bf42de7084547b881f5a70e73e72efdf4046d6b1f677507ae5ce05a5878b542e55ca224e6c89f32e98d270f3644541861b6dbf8e7c2ca3b23f0230cc4d13774339f45f5871a4ac7ff0f460abb7d7d0da6bbedfe27cf2a0d4a140163d76156fb51612f5df85ce150f8795308707ce06b1581fb46d511281d77eb346ec043ca42d6182a8e484571c003f42909c69ca52a77a5493d3bc4ac7a12ef4b20966a4db291cead1abaed40af33a2b15bc06f7671eb88e97e11f1d51c901ce4f448d4f7d4828a190fe6f0b0e3330c9441b0602f7eda564811b0fab62e83a7cab92f4a3a6f02b4dc14c6a391f21cdcc1c3c8f45b74dd7c896507aded7a38b84f00cd56afb338711d617420cc56e45fec58a568a01d938031749b9625310773f807eea04b248461d14ebc2891131c4fcf6341db6fee4312bf428ef49a61c8b8c53865950d917b77203110d54cb6f433e20d45e36e6d6235c0db0bef30acaab0d53aea5f1640c2fd5d182808f1b680e348e63bf886cab2c3f17fd0053da136be9b9e7652207d05e0bad6736cf0aded9e493271b4a7e2f64e77355632e07d75f37d3ef7317b8d393dc19d61481b4006505b33dbb458496b48533de7c99391a6d092777867c9bc3085185dde89731261eb6ea05876c7ab7405ddb2a487c74e0533ea57e6bcd74e59480b424b8b1a129725422f11b2aa08aded47e06edc1d4b7a00edd83da2979d827f06fd7d41ae131036a929d5b2c619bd993d8c627735c335f80cf33cbe0fad7467b33dcde30809ffa7b22be3e394a79530bded2f0a296b650e20d13566fa4b181a70696d7b9f479cebde8af1ae708495dd4343fbc2142b0ca514b8416e67ea61902cc9204397c2a241bf5922094d0a4530587c7f9d10a003714da15ef14b7c1754e8e8386f48272e6dcdc1e2da7a9233d1e992994da824ae10ab1e03b938db824c43fe5f90fadf7ccbfe28ac644f2239273be96c9b55655417c4329532afb9aa9aa65b9ad92a8c0af9e902e458d2df4e2bcbed6f06a6fafd965a3ee422c99dc39e8426081647cb322e4db0f49bd74ee392854716f7f52cf1d245d8896f753bd75b0802ddbf7b40fe3b5cae47b41473166bed18ff525e3e2ff52ae20edd8758a3c699247d235a68dfca39cd635c3ce9f3cc79642874018bb1ca50e1662e42976c61457480c0fc464826d1e9d580ebd7c7a17f88175af5c80febfc9be1a161a8f5a33ec774c829087af8fdca10e18bfb7a9314c86f45849f369a49ae097d3dc17c267f149510b02cefc2d48f7ccedf8e8ed6a777dcd2d100dff3a63366f06be6095412fa67e604ac68802de10172269b1143175fed804d95905206e877c2b5122f863f53f26e41e648acfdf03b2bfd627dac0a7660c87a614a96986f5514d5d8cff8f24f5a6fa4948946c8cbf38c05bfec4ad3da68e893cdbeaf5d34f26019108ca53fe69f22480b8d5d06118cd1a8d0842a88efdc6141121180b2c516016044f82eb9cba26264b0199e958368c688fb5e81794dac44716facba22107a3a9a86220f0ec4ef428698a0f3e972941036f084b441a4509e1c7647260f0f8c7d1e6e46ceaefcd9b56e060ea915c24ea7bb1f42333fa14eaa9b5ef087ec2a88209ef0532dc0d2ab675f7446e8b63d819e24c3022a03ae1ebe8c153b00a419f67719f7990f3014e37c2a6dfcae8e97d1d774f1b35ca81ecc8c0111418d386f5f696c883b3e1c47937542efe74fbb38f1b4dd0a4287f2bef1030e5557964e5ce1769804b7669442d5a8ef98df18588b39cfa709baa98b9b8d029452a53454cc752c6787fc3049237b63c80089bcd809a941924247c88eac81e4879c13419fab443c8b536b3a8613b906ed4c1c0a93972de8e0ae60c41c28d2495d525663cd89a622645c99e2b77163f40fa38dea7b16ac51898e28a74625cce47f886af6cc62d2094c0e4b8cb72f53cbdf0ab193d446c3a0e024da33e79e4f37e39e0b399b14afd6006ed5eb57acc499036b293a454f86b50a82bcdc91f956ace3013e97ca2c5bd435812457ae946f1b04d44c1cfa899ad25ee1a91897576fe9442a49e93a603943706aa4f2141cd6e5848c0a4f475950db64d72b40067b8d1814797a30edb4a62f864930c19c97dfa13ffe283c25cb2bc0f526db6eee7115a6b9bf8c754bbf7ba5b5b06dcda3f37181af0cd2c325564eabc778db138026b3c8f9586290a54fcc6e53b1d8772c710ad3cad0491131cad7419f090f65a0e6dc336837d2b469e8bbf3c1a0a76303769886dde6a91f2fb115bbe240977dbd106a07b1ce52eb2f6d86b5621623589de54804fffcd5710859448ae9d028d46c8380a4edf09b6458ea5823e5e853940f8a00a3f80d2ca0bd03eb28d16ee05f28f3e13", 0xdcf}], 0x1)
writev(r4, &(0x7f0000000000)=[{&(0x7f0000000b80)="b8dc7ad66d6d45a4c1f168647c2ce4e83f2eb13e4980057b4fee8ed93efef125ef3d6f4ece8c5de164086a4d86da79b1614138b36c5aec12d75a8e4dbdcbfeeabae21a3758613214bdbec5a3c9c45e5696a373965c936aac1f9c966cd787168ba0a9db085be31f9881be6667228783638366d46d81d55dc0a755bbaf07ceea03c566595430a112105e30e329dbdd32c1d81a49355a4bfafe38c81be6dd52f4b28c7c99926e0b1e193b227489d98ef36cb6b7e4c3cfd7695f6b2fae0d84413d1ab504685b4ca0bc2e98f2d723ce0b20b5ae8c205858e7b83829bf53566bdf0f0aa340d9722b536dd1b88f3d4e6bf118b113f544529c280757b7f1a32fe3e77244c7accb62d98fa748a8ad43fcf3c85f41d52d8fd5af548700edd86036b883b760ab8c4a6b5561368b35efe214dd83bc09aaf318e237fe1b92d11f2d9b1c090bbaae05d34a662223d26e79fde0d9252a44871bdf0eb77828f8e9af02fa8eb53361f5f8f371b59c5296449720b6a2819fcb5c6db614ec3fcddd9733f58f674e29bd9b79f00abe85e23b252cf5489ff75600e1fa5a34dd64062af8a005a049b7b3f5c482e76b482ba164b7c59aef3e229474d38582bafe1f26bf416dc334fda652790e6176ddc9225e49ff5c98710bfd1dacede297d6d179a2e593977e191451d674c708d75efe4879219dcd2ed1cf6a222541e79da23046db1aa845ff5bbe9bd9dc41bfef9bf20c2aa25398c252a54b8dcc9078b3212c8c8706016d98a9a71bddcb688c14e6fef3c62212303b64b399030434b2a1068a1fd57554b3ab684cf1f06f7ca52d3664a90a359eb47b8e11446a95d1bcffb4fa7125e68130bcb4cb68e7e32102f24c7bfc1deaea52147f26729e728fa6373cf2ba17a185d2715fb494a78e09cbbc85a14a2132e601817b6ae0008bfed42c5c64aa98ba96b37ab2139ee210e3fc32b2951078c4e8bd44ce65a80e4999371944feb3d8c0004d31717655ae351eae8ede9e1eb7a87ea7d4e5bc810ad6dfe2cef8b326e2069ebb0ca03ff501e3124637c777e48a001676c159f64713ae8e113d32a9f946b2eab9b40b24c31cafa2da790cad4e60163d1dcfd9e9b10890932582bf735c6c96d202a64794e36542d0f8d3ffc2e9bb1ff8d89166b4c7d08c5789e46cceb62bf0e16587a743c2a3a7440e25cd59f8f08e049202175965a20464c1f7c95e6b01c12641e35e75848832429c1ed844a1bace93c42daf7d2aaabc10b0d7a1a103fd0ac24b88cd03ddd34afeda118d9e28454d9067e74ee3709e518121adf383bcdcf351139d9d84759aae90d21e927f887d0633939453d83ee3692cc30ae92bbd086274ebb8d284980903418ca8cee0514a1c582103d4f315210aa3d5c37a1e6cfb4edc73373c34e53ea64fcfed8c7e956207329403ac9896f6e2dd6d7a152b7e0e82a01b170b11aa3cd731767c865e4b5dfd7784a8f32eb938f0342495782bd40ea1830052cd803c2b16f10a034ce1d1a56cf26b73b144b28f522567cea57965ce4eb777f1a6b88a3b97942fe7e3b447d8c9bd0f37561166e8e48ee2b05514341299d404edc0b23342e3c3545dead6890e545ae99489a9035018abf5be4b65cca8bb3c2b6ed4ca5bf513492497d69467250f3bfeaf3b6606e207fda0e09cad749e9a003cd0333fd4e01af6af58119d8df17ba7cca2aee2ef0b6b6a8f861904a46eff37f0485fbcbf21056b1e1086e649a7f3b4896ade45230a99a979c99b88f7f2cfefc9", 0x4da}], 0x1)
sendmsg$unix(r3, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)
socketpair(0x20, 0x4, 0x106, &(0x7f0000000040))
utimes(0x0, &(0x7f0000000040)={{0x40000000000000, 0x4000002000000004}})
openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r6 = semget$private(0x0, 0x2, 0x388)
semop(r6, &(0x7f0000001480)=[{0x3, 0x6}, {0x1, 0x2ff}, {0x1, 0x8, 0x1000}, {0x3, 0x1, 0xfb0bf9bc52962a4e}, {0x0, 0xfff5, 0x1000}, {0x1, 0x1, 0x3400}, {0x3, 0x800}], 0x7)


r0 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r0, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
getsockopt(r0, 0x0, 0x6a, 0x0, 0x0)


r0 = getpid()
setpgid(0x0, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r0})
pipe(&(0x7f00000001c0)={<r1=>0xffffffffffffffff})
ioctl$WSKBDIO_GETMAP(r1, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
r2 = fcntl$getown(r1, 0x5)
fcntl$setown(r1, 0x6, r2)


r0 = socket(0x18, 0x1, 0x0)
sendmsg(r0, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0xdf}, 0x0)


r0 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0xffffff9a, 0x0, "b07b1f660000000000002000"})
syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000040)={0x0, 0x0, 0xfffffffc, 0x0, "0fdbff0100000000000000000000ffbfffff00", 0x0, 0x96d})


open(0x0, 0x0, 0x0)
chmod(0x0, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x0, 0x205310)
open(0x0, 0x10, 0x0)
ioctl$TIOCSFLAGS(0xffffffffffffffff, 0x8004745c, 0x0)
getegid()
minherit(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x1be76362, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
clock_gettime(0x0, 0xfffffffffffffffe)
getuid()
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ff7000/0x3000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000604000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000691000/0x2000)=nil, &(0x7f0000ffe000/0x1000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil}], './file0\x00'})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))


mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f00000000c0)={&(0x7f0000000000)='./file0\x00', 0x4, 0x0})
open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
open$dir(&(0x7f00000000c0)='.\x00', 0x0, 0x0)
execve(0x0, 0x0, 0x0)


ktrace(0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000000)=[{0x44}, {0x87}, {0xe6}]})
syz_emit_ethernet(0x126, &(0x7f0000000280)=ANY=[@ANYRES8])


sysctl$ddb(0x0, 0x0, 0x0, &(0x7f0000000080), &(0x7f00000001c0)='\x00\x00\x00\x00', 0x4)
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(0xffffffffffffffff, &(0x7f00000008c0)=[{&(0x7f00000009c0)="ec6af1225e5efb35bcc371fe5f2279ab7b237c8eb065eb3826fc2caca9965debba4bf1c787b41174632621a3d074f851818d888349ee3331561ed0349e22278576ba84838a22aad6adbd0c9cc80e9c7f148f56b9c0da9e722f5b94c7c39ef3c59039c87e7af3d1cda857ad8f371786d4032f4b573ed230210e1c2bc5059a5a4aec9b55317fb73be306a80b34872436118bea62cf17086c45c815d63217a22198060a20496f2ece", 0xa7}, {0x0}], 0x2)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000000)=0x9)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x0, "51fa6278e9e960b4dd89080863ab366d112be29e"})
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0xff99}], 0x1)


socket$inet(0x2, 0x2, 0x0)
r0 = open(&(0x7f0000000140)='./file0\x00', 0x1878e, 0x122)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x4011, r0, 0xaef1)
utimensat(0xffffffffffffffff, 0x0, &(0x7f0000000100), 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
connect$unix(0xffffffffffffffff, &(0x7f0000000000), 0x1)
r1 = socket(0x2, 0x3, 0x0)
connect$unix(r1, &(0x7f0000000280)=@abs={0x1, 0x0, 0x3}, 0x8)
bind(r1, &(0x7f0000000000), 0x10)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{0x20, 0x7f, 0x3}, {0x0, 0x0, 0x0, 0x1fff}, {0x16, 0x1, 0x4, 0x800000}]})
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f0000000080)=ANY=[])
r3 = semget$private(0x0, 0x4000000009, 0x28c)
semop(r3, &(0x7f00000000c0)=[{0x1, 0xffff, 0xe5ce97ab354d96be}, {0x4, 0x4, 0x1800}, {0x3, 0x0, 0x1000}, {0x2, 0x6}], 0x4)
open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETF(r4, 0x80104267, &(0x7f0000000140)={0x2, &(0x7f0000000100)=[{0x3d, 0x0, 0xff}, {}]})
r5 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r5)
connect$unix(r1, &(0x7f0000000400)=@file={0x1, './file0\x00'}, 0xa)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, &(0x7f00000002c0)=[{&(0x7f00000004c0)="9f6c34a0a04ef7251acd483d4214119b1dfe8db5c8d6e3d9d7307e9bc69095055e85b8788b845c06701810fa0bed9dc8829352e8fbea763a0b3f0f96f5d03fecb8d6ff35ac527184c184412f372dc19c646dca044d85f159c13eed832a0c4b41e82d366232a494d04c47045c228fba8589926b2440472b00d951d501f76e61e6120c43fc971c8acffd4491108ac8c0c9076abe4fc1ea7f6bbf81d7b3242a033deea5a4e54017d85311d40b81cee5a45b776e49479302c9901e85d22784bba860ec4349661b779c09f0d101be3a1a10b0cec7e4fb0f36b1ab506fa8347ad7d927a2d8f6f354d31db44b1d863ead34d1b4113269119c4c58f8ab7d73149eb98c4673c9dd4f4c434ed3e8760332fd6dbca57af1c6129e17a885baaf672ff798b8b763a8ba254980bd23d6161f8cff4b5291200f3464f9d50d9c8451c044796f352d7f7b85f296ac1b260019", 0x14a}], 0x1, 0x0, 0x0, 0x400}, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000200)={0xffffffffffffffff, <r6=>0xffffffffffffffff})
sendmmsg(r6, &(0x7f0000000240)={0x0}, 0x10, 0x0)
semctl$SETALL(r3, 0x0, 0x9, &(0x7f0000000340)=[0x400, 0x1000, 0x3f, 0x1ff])
semop(r3, &(0x7f0000000180)=[{0x1, 0x1, 0x1800}, {0x2, 0x4, 0x1000}], 0x2)
r7 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r7, 0x80105728, &(0x7f0000000100)={&(0x7f00000000c0)=[{0x24, 0x7ff}], 0x1})
semctl$SETALL(r3, 0x0, 0x9, &(0x7f0000000240)=[0x7, 0x4, 0x7])
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000380)={{0x9, 0x0, 0x0, 0x0, 0x0, 0x100, 0x5}, 0x2f8, 0xffffffffffffffff, 0x7})


mknod(&(0x7f0000000080)='./file0\x00', 0x6000, 0x202)
mknod(&(0x7f0000000200)='./bus\x00', 0x6000, 0x202)
link(&(0x7f00000000c0)='./bus\x00', &(0x7f0000000100)='./file0\x00')
unlink(&(0x7f0000000080)='./bus\x00')


mknod(0x0, 0x0, 0x5c4a)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x4}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x3e}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)
sysctl$net_inet_tcp(&(0x7f00000000c0)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000000)="9b1809ffffffffffffff7f473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6fd74c94d1b44", &(0x7f0000000040)=0x10011, 0x0, 0x0)


socket(0x2, 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
socket(0x0, 0x2, 0x0)
kqueue()
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000040)=0xc)
semop(0x0, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000400)={0x4, 0x2, 0x6, 0x12}, 0x4, 0x0, 0x0, &(0x7f0000000140)="53183374", 0x4)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x37}, 0x4, &(0x7f0000000000)="71f91e3471ac0058bc5a91501d942400b5e1a0757cb9af769c7afec37082", &(0x7f0000000080)=0x56, 0x0, 0x2e)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000000c0), 0xc)
sysctl$hw(&(0x7f0000000000)={0x6, 0x12}, 0x2, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x0, 0x0})
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
r1 = msgget$private(0x0, 0x0)
msgrcv(0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$FIOASYNC(0xffffffffffffffff, 0x8004667d, 0x0)
r2 = open(0x0, 0x70e, 0x0)
writev(r2, &(0x7f0000001580), 0x0)
dup2(r2, 0xffffffffffffffff)
read(0xffffffffffffffff, 0x0, 0x0)
msgsnd(r1, &(0x7f0000001540)=ANY=[], 0x32, 0x0)
r3 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r3, 0xc0106924, &(0x7f00000001c0))


mkdir(&(0x7f0000000500)='./file0\x00', 0x0)
chmod(&(0x7f0000000180)='./file0\x00', 0x23f)
chdir(&(0x7f00000001c0)='./file0\x00')
r0 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
mkdir(&(0x7f0000000500)='./file0\x00', 0x0)
chmod(&(0x7f0000000180)='./file0\x00', 0x23f)
chdir(&(0x7f00000001c0)='./file0\x00')
setuid(0xee01)
mkdirat(0xffffffffffffff9c, &(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x180)
renameat(0xffffffffffffff9c, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', r0, &(0x7f0000000240)='./file0\x00')


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000000)=[{0x7}, {}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x12}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000000)={0x2, 0x5, 0x2}, 0x3, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0xa}, 0x3, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000000), 0x6, 0x0, 0x0, 0x0, 0x0)


r0 = socket(0x2, 0x1, 0x0)
r1 = dup(r0)
setsockopt(r0, 0x6, 0x4, &(0x7f0000000240)="5194eb5d", 0x4)
setsockopt(r1, 0x6, 0x8, &(0x7f0000000080)="1385d4d8", 0x4)


r0 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r0, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
setsockopt(r0, 0x0, 0x6e, 0x0, 0x0)


mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x205b1a)
open(&(0x7f0000000040)='./bus\x00', 0x0, 0x0)
select(0x40, &(0x7f0000000000), &(0x7f0000000040)={0x7fffffff}, 0x0, 0x0)
select(0x40, &(0x7f0000000180), &(0x7f00000001c0)={0xff}, 0x0, 0x0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
pwritev(r0, &(0x7f00000012c0)=[{&(0x7f0000000000)='~', 0x1}], 0x1, 0x0)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
syz_extract_tcp_res$synack(&(0x7f0000000000), 0x1, 0x0)
select(0x40, &(0x7f0000000040)={0x0, 0x400, 0x7, 0x0, 0x8, 0x1f, 0x6, 0x8}, &(0x7f0000000080)={0x7, 0x1000, 0xfc3b, 0x4, 0x4, 0x0, 0x6, 0x10001}, &(0x7f00000000c0)={0x4, 0x0, 0x3, 0xfffffffffffffffc, 0x80000001, 0x8000000000000000, 0x3, 0x4}, &(0x7f0000000100)={0x790, 0xfff})
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x8, 0x0)
r1 = kqueue()
kevent(r1, 0xffffffffffffffff, 0x3998, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000002c0)={0x5, &(0x7f00000007c0)=[{0x0, 0x0, 0x0, 0x6}, {0x28}, {0x6, 0x0, 0x7, 0x3}, {0x8, 0x9, 0x1, 0x1f}, {0x0, 0x20, 0x6}]})
write(r0, &(0x7f0000000540)="76e5dead6f01f8607d2100000063", 0xe)
setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000003c0)={{}, 0x0, 0x0, 0x0, 0x0, 0xff})
r2 = syz_open_pts()
close(r2)
syz_open_pts()
writev(r2, &(0x7f0000000700)=[{&(0x7f0000000800)="34eb4cd59e8456ebc0881681cb934394c5951c1d96fd943a004bc5968c001000000000a3b800", 0xff99}], 0x100000000000025d)
accept$unix(0xffffffffffffff9c, &(0x7f0000000440)=@file={0x0, ""/34}, &(0x7f0000000680)=0x24)
r3 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
writev(r3, &(0x7f0000000580)=[{&(0x7f00000001c0)='N3-', 0x3}], 0x1)
openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$WSKBDIO_GETMAP(0xffffffffffffffff, 0x80047476, &(0x7f0000000200)={0x0, 0x0})
execve(0x0, 0x0, 0x0)
mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000a40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000001380)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000480)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
setreuid(0xee00, 0x0)
r2 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r3 = getuid()
fchown(r2, r3, 0x0)
r4 = getuid()
setreuid(0xee00, r4)
bind$unix(r0, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x200, 0x0)
getgroups(0x7, &(0x7f0000000040)=[<r1=>0xffffffffffffffff, 0x0, <r2=>0x0, <r3=>0x0, 0x0, <r4=>0x0, <r5=>0x0])
setregid(r4, r2)
setgroups(0x0, 0x0)
socketpair(0x1e, 0x3, 0x0, 0x0)
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f0000000380)={0x0, <r6=>0x0, <r7=>0x0}, 0xc)
setreuid(0xee00, 0x0)
semop(0x0, &(0x7f0000000080)=[{0x3, 0x2, 0x800}, {0x1, 0x2ff}, {0x3, 0x8, 0x1000}, {0x2, 0x3ff, 0x1800}, {0x0, 0x0, 0x1000}, {0x2, 0x6ff, 0x1400}, {0x0, 0x7ff, 0x800}], 0x7)
fchown(0xffffffffffffffff, r6, r1)
semctl$SETALL(0x0, 0x0, 0x9, &(0x7f00000002c0)=[0x3, 0xfff])
semctl$GETALL(0x0, 0x0, 0x6, &(0x7f0000000440)=""/248)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000001c0), 0xc)
r8 = getuid()
setreuid(0xee00, r8)
setreuid(r8, r6)
r9 = semget(0x1, 0x1, 0x230)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000200)={{0x0, 0x0, 0x0, r8, r3, 0x182}, 0x6, 0x8000000000000000, 0x2f})
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x10200, 0x0, 0xffffffffffffffff, 0x0, r7, 0x44, 0xeb}, 0x2, 0xd47, 0x7})
semctl$GETALL(0x0, 0x0, 0x6, &(0x7f0000000540)=""/240)
semctl$SETALL(0x0, 0x0, 0x9, &(0x7f0000000140))
semctl$IPC_SET(r9, 0x0, 0x1, &(0x7f0000000100)={{0x6, r6, r5, r6, r1, 0x20, 0x9}, 0xe41, 0x800, 0x1f})
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f0000000000), 0xc)
setegid(r3)
getuid()
semctl$GETZCNT(r9, 0x1, 0x7, &(0x7f0000000640)=""/199)
execve(&(0x7f0000000580)='./file0\x00', 0x0, 0x0)
setegid(r7)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "0100012d29fb000700000000098002005e00"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x54}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0x4, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0xffffffffffffffe8)


r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x24, &(0x7f0000000000)="5ab7776a", 0x4)
syz_emit_ethernet(0x4a, &(0x7f0000005c40)={@random="69e1629b6174", @remote, [], {@ipv6={0x86dd, {0x0, 0x6, "6b9efb", 0x14, 0x50, 0x0, @rand_addr="cb69bc83c1677a656ab420666c3e2c6f", @mcast2, {[], @tcp={{0x3, 0x2, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}}})


mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
open(0x0, 0x0, 0x0)
ioctl$TIOCFLUSH(0xffffffffffffffff, 0x80047476, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
r0 = socket$unix(0x1, 0x2, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x2, &(0x7f0000000200), &(0x7f0000000000)=0x1)
syz_emit_ethernet(0x52, &(0x7f0000000080)=ANY=[@ANYBLOB])
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x0, 0x1f}]})
r1 = openat$pci(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$PCIOCREAD(r1, 0xc0187009, &(0x7f00000000c0))
chroot(&(0x7f0000000240)='./file0\x00')


openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r0 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000440)={0x20007db, 0x0, 0x0, 0x0, "090000006f000021000000450000000000000100"})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r0, &(0x7f0000000000), 0x10)
setsockopt$inet_opts(r0, 0x0, 0x1, &(0x7f0000000440)="9876d692a3ef9c7ab923a2f0", 0xc)
write(r0, &(0x7f0000000240)="14bdfa5d1d34e2fecb284a6498307dcda9aec43050036123339a346f737850551408753f95b7688ad4c4e1dd5489e7bafc58d3e5823757ae8b630719ef187ccad995f13dbe19a6dd4e6902bd8297b0799b426aabe9fad9db6996571c6d9f8bb5d542c2148aa42be940970fe88d34d8f99afe7e7820237400000000008000000100"/138, 0xfc7e)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000029, 0x3b, &(0x7f0000000100), 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{0x81}, {0x14}, {0x6, 0x0, 0xfc, 0x4}]})
syz_emit_ethernet(0x36, &(0x7f0000000200)=ANY=[])


r0 = accept$unix(0xffffffffffffff9c, &(0x7f0000000080), &(0x7f0000000180)=0x28)
r1 = getpgid(0x0)
fcntl$lock(r0, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0xffffffffffff0000, r1})
r2 = socket(0x18, 0x1, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000200)={{0x3, 0x0, 0x0, 0x0, 0x0, 0xa, 0x8}, 0x1, 0x1, 0x5})
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000380)={{0x8000, 0x0, 0x0, 0xffffffffffffffff, 0x0, 0x100, 0x8}, 0x6, 0xffff, r1, r1, 0x4, 0x3ff, 0x8000000000000001, 0x1ff})
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x2, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r4, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x20}, {0x20, 0x0, 0x81}, {0x4000006, 0x0, 0x0, 0x8001}]})
writev(r4, &(0x7f0000001400)=[{&(0x7f0000000240)="e049c0d37348a45d6bee0bf84a9e", 0xe}], 0x1)
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000040)=[{0x1c}, {0x20}, {0x906}]})
r5 = openat$null(0xffffffffffffff9c, &(0x7f0000000280), 0x1, 0x0)
close(r5)
r6 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={<r7=>0xffffffffffffffff, <r8=>0xffffffffffffffff})
recvmmsg(r7, &(0x7f0000000580)={0x0}, 0x10, 0x0, 0x0)
dup2(r6, r7)
r9 = socket$inet6(0x18, 0x2, 0x0)
getsockopt(r9, 0x29, 0x9, 0x0, 0x0)
write(r8, 0x0, 0x0)
getsockopt$sock_cred(r8, 0xffff, 0x1022, &(0x7f00000000c0)={0x0, <r10=>0x0}, &(0x7f0000000100)=0xc)
setsockopt$sock_cred(r6, 0xffff, 0x1022, &(0x7f0000000140)={0x0, r10, 0xffffffffffffffff}, 0xc)
ioctl$BIOCSETWF(r6, 0x80104277, &(0x7f00000002c0)={0x0, &(0x7f0000000280)})
r11 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r11, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x33}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047470, &(0x7f0000000280)=0x5)
readv(0xffffffffffffffff, &(0x7f0000000200)=[{&(0x7f0000000100)=""/173, 0xad}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = syz_open_pts()
close(r1)
fcntl$dupfd(r0, 0x0, r0)
ioctl$FIOASYNC(r1, 0x80047466, &(0x7f0000000200))


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0))
connect$unix(0xffffffffffffffff, &(0x7f0000000280)=@file={0x0, './file0\x00'}, 0xa)
r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
r1 = dup(r0)
writev(0xffffffffffffffff, 0x0, 0x0)
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000140), 0x0)
mprotect(&(0x7f000063d000/0x3000)=nil, 0x3000, 0x0)
socket(0x0, 0x0, 0x0)
getsockopt(0xffffffffffffffff, 0x29, 0xfff, 0x0, 0x0)
r2 = socket(0x18, 0x2, 0x0)
setsockopt(r2, 0x1000000029, 0x3e, 0x0, 0x0)
r3 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000180), 0x1, 0x0)
r4 = dup2(r3, r3)
ioctl$WSKBDIO_GETMAP(r4, 0x80047476, &(0x7f0000000100)={0x0, 0x0})


setrlimit(0x8, &(0x7f0000000400)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x37c, 0x7f, 0xffffffff, 0x1000009, "00df00003f00000000000000000000006d2b00"})
writev(r0, &(0x7f0000000500)=[{&(0x7f0000000080)="590e495b1ad2a14423c0fe6a9ba42f89606f8f5773e9ed4805627b1953e8526d359eb2d55c75c5eecce22f844fad5fcbda0e438594cd635b99159ba469291f4a807055e8cb61b875b2ff967153d9e416a79321aa4587cc1a8d8a520b57552c61a43a412d7a084aa4d72d74db60e90ff741c303bf276a00cb7754b0", 0x7b}, {&(0x7f00000009c0)="00681c735ebcdf1ddeb0dbde935a3cf2bafc27af3e17379e0c6f59175bbdf7db589843ec39f45c9e97fcc284b3e7f351b6095346d655708a92e51d9899c26bf2e2e9e2f53ed7c2110923ce8d6a14c8d7d3a5365a48a6d32aedba526af9decda1f4334ada2453510c65da4b3d74237650f09229a75edf77cc02b39529f32b0e968ed8c4bfc420bda1d74821ccaf18e9108568f3dbf6dd9b16cfa1828461d3d94b9d357cc6a2d548278c0ae8c2b3be444fca9e989e4ce02e161f43d4f87e09222ca614698db720e3b463d4de47f303d024413eb4b81b41036b2c596227426b434e9f31154e31b73317439b8d9240244835cc2721abe86ab0e0dd3d4c73d4c00cf68c9afc905765609fc35a380a6e9d8e4d10e4d12376994955304127d26ba79d36138474a1cc28e071c6735125c516d169017f5f3cee60f73c2d019a830b16260fcf8073dc905fcb352a92d336b71bf1a0c8d406b10a9f48ff7d061eb1ec56eb5344706936529522159916a6c934b263bccfa618797586b077bfe5e0154be5b0decca6053828b9d8c9aaece80cecd1a9693a05709047b1c547f01a5facd7ca9218b0a6f5d93b059642249ad1795e38413ac6bcf56d7596b59e61f2cb6268122b2fa16b5cd3aea17c3f511846bb9d64961224762f5d56dca3e3d78ec8810f756a809f9a4dfe133513a5b04f196192de1072d700a0a5a6a5a1205f48fe09ac94fe9aa301c6d38145df76cea91f7bf7246d6bc167a93f15eb33c3fb5d6fd3afd8c6ae979055260c42fa01cae241be43be81814dba18954c12b0ac8c54fea3311d6bfecba5baa16a686842e1042e0f5e6c0035071043769cb7c9cc00a2e783fc1fb9f208e448656eeabc27af59e5b20b2948a5506b20a74e89342f85f32e01862b8ebb551293526ed2254773816a93fd3f3766e820ecdc8e98436baec88481cf58c48c521cfaaf6709c3cf6abfa7cac19fa165bee6013d800e3084fc7704ca582bd9356d11961ac1c6a31a79ac2f3f86df631bc1ca12bab2256d7ef3e64239e6acfb25ebe836f47e137d7a2bf85a7799f985f0e9937543dbaf4be34632d37b346b29ada854c6437aeecc2d2a480bb2c7f1e3d7393b9f12b4b05cfeb9a2a29e85195014802bf56160f89f9697d9a463d77ffc07ed4b4870670fad275b2c098329870d20b26209494d8029f34819e63ec879533726ed50a30b1a48457f2d7703cf6b628cd004a19adcfc578c2638ac55208a6cc9d6d908beffb83fec68d72b505aa85f5c2ac40decd02ffbfaa2d618f31758948f3bb44f81b2660e53480e0576a9234f06e65bfc7d3b5acd6efe81ff3c9dc1f88c6059ce054eb00940d689709420acf3e6d5271d53d3a223c99aa240387dbbe8a8dc868b0ca1713e620059c27b2536bd30c2c7023b738aef186bdbf32e0b9015352a5c797da6445b6e948aa531412b123596de6cb14971f2707d17ac32b376a5f06a9dc13cd92f8d2d1ff6aa74c4f3208442950e4eb330efad17ff5e40031c2c748ab0884b3d04dc7724605ab3d842009ca23a495ca67bb45d77748e9b623afae4205307afeeeea0893c462392d3d414f638ecc1d2e9eb9017ef9fa86f283dd724f47a44b6850fbf52e9960c5c2ee63804592b001500faba09cea9956f0fdb29ac17425a59ff80db874ea07a4a1183566034f656b9e91aa8f057771d4be2aa59561729d199340526ce11a505fb5b56b30071a8bf3cef0bd7b899bb3b7cbe69524452f5cf6bdc07d2a8bcc8a4c6630b773dbb70d8f9dec6b8b2e46becbfba5c9ca550afa391d3b7f69de0f05dc387cf1c6852250be0876913c52e3c5466d1e391d01c981cedbf79f5eee881e2045e8cac130101b782037c4a07da4e353153270fe24e5550c07321aee2945a3945ecfe41185dc1a4065fbb7e076f7fd7f4ac5d32e930177d250cf25efa8f4bf0c2078be8a338e796829eba1bcbd147f8ea84b6ac4e31d8fe758245ea49ba923e2e897851584fe9dba4af25a6572c8ef9e4db2aee254fa29c6724ae211536d82dbff61cfcdc0f208ca7d9287424a135df42c464ba7d4d859a62d43260271dcf7bedd04437295ab8c3ae958c914c07bd3b2686c7208ada7a67bff42ef73f90c50b96241dc57c095fe29f9ad801747fd5a52c5dbb35090dfaf28a5fed1901c0eae196e3096383014d2cdfeba126f41fe02cfa847f5c7cc2202a5a9190aae94f9fd17513c5ca67f839ebef8fe343909129ba5fbf4635899a8c0e58f441df4b609c7f", 0x63b}], 0x2)
writev(r1, &(0x7f00000012c0)=[{&(0x7f0000000140)="cfbb251e606bea41ad417032985e05b5725bb9a5a4201587136fda2dd727e5f62dde5a3a4482bc0b9d8726d0da46c1d908ab108ea9ec76e02493a12c1b64b1ae00f41186a7b024d2ddf2ae9d3a377c239387d08393adaed08cb632e695", 0x5d}, {&(0x7f0000002ac0)="60bbad4238f79f3fab424ca4a0c38f34f352c7d5c7b6743ba59aca5b10b7f12be1cfa323ff58d0f57283e760788123b4a989048b3e3733dc8e3463a3713b8e03e9be10b3f7c76b830225cc80a4a30e8bf4756fae56321aa3894ab69fc4e85a1a97cbe34dd09282ac10309c3e29b703b897fcdd82d8fc7688ba2cd139ef3f333ac048fac12ed769c375952c24e6676579a90c4f13d6d4531fac3cc94239d932935ae6f55541b41f24406ca41656dd8e889a023526bff0265e626b535cb4123c4e2bd9e951b2b4d175be8134e3b76491bf204272a534386e4d2ec00bc5b7ecc8375079c2ea5526d6154677d5e2de08d01460cc71b57ac1ab20f6debbb381f3d5952ffa3c413b9c44011fe3eca5714c9e995577c26fa6f4be9cef41e86953f7a67ba4033192ec930ee4a875fd8a2d9e7945f75868255b00c1d5487217f32d2db516fd24a770974859d3e0af7c1368405afacce6876add8c4dda7d84bb1c19850919c6c474260ca663513190f2b732650031fe7abf0498f7fe749be7e9e6ac101382aa72a6a5d13564dcec299fabf7ff328c3d4d7d6bd36dc6249e363c908d6f9b04f61d174a046dd542d71c2ef30a39fbb19573b4f2e16c51520aa99f770b838d7cac545aceed9295c8cacc2be13c08f5ea75691d965e82a6a9cbe553e86d25489b4fc730f2a7712b64df3762913d0afb06179df17b755883b27600d2c8943dd88c3a7e2cdd9fbc6eec90287719b93766304ed49f5d57c3afb3dc4cba148b67797cf390bc442bb29245c2bf1b2f2a2dff528c32ad1e09cdb8a285d491613bdb9f6e567e00184a2ddeb383e6ac4f6f51c13de680b8551e67d41005c645180a9522bab67a29c0617dcbf91dca295be0a8b9fd6c8e9a3bdc81e109ecfbeb026e2391e101a29dbf5d69ec70f783476268cfc5bd0baefee4dc0512f3114fcd10e685021b4a4e0075323ff1c94a6bb7e0339bfa8f7a66cc6d7c1e115f8d8ebbf2db6553927d78c1848463196183a7e8c92e0e3c257889d633cb631b4ff59c051a216f43b532702b4b6ec7451b3ef70a3a50d29ff2a79fdb06c6fb91d8a0a8799b6b6f9d56ed0cf3322f957dc31e1a1729a622c6738e6fa4eccdc51ad158e4852c2bf585910a3726521128386e35103072791d279abe6535f07d9affc005cd85d21bf36450cc4e1d0245e0e2ff195ab6706a0cf0003ac8337adaf54ed5923f9a2e4245e6f03823c1f3f26269f3f3f26cb664a92e773178e9d0b51f1aba3a05337c5387245d009e2187cfeb658a7fe98619a1e769883a6ac7f9c01e3e35e20f7675901ee6c2e2b31f952d35d8f2a38d6236514080ce02d2b8de01801a6e4d0588d0663db5c154ee8cd913e07043ef8045ee57dc97520c3d7c597c82d7b4486c8d94d94191e7971e2ea868304007799447fd1953fb8103afdbffb934ece4527b8797a9ebd69510bee9df749c3e68f5ce9b84d5662032c9a1fed49f81e7886cbe9122ac339f72c7e93e927f628ee59d83c6c13420e0fbfb27ce84d4b8d2035488f99d97c1b87661ef58dd62a9fedef7685ec2dc16f97ceebeca935bc8925900ec234bad42982a7e67a5d33648e1defd0a585365a97535c5d78018b7a2164540ae07f81dde252208eebd15834764dc7a56345da952d9b090aebd2a54888deb5e104bc2f54155c0063a8211269ed2c21b8f5ee6c6515bcc429a093dfd0146deb9e8a56dcc73fb36492c92195ccd793738776168791f3a224fee2a695af5e95d3fdb82b312e9bd98f4aafdd9c268f3cf3790cff6649efe9d9595030aad7b24515746a52e821c6f45cf03240e3eaafd364f095bbb33a47b50fbdc2c66fe86fbcbf7b1c077e929f8e92951697de55ef19623d5ffcb9eab8b268338b8e26a2f5587c031e95917fc9e1c0af59ab18381a39ee73077d6126b26733c4b1ad311fb5ec3496f36b460153df51fd8f3829e877104ca327a6ce688e1f1f928d98bb1731715ca6d74b5279923547399511939c382368449eb3a806ceb299241f0104b56702080154578e3883edf3baf82076aaa002950500ea3a6ffadb1020b3787a7451580b5cee54190883ab55c0674746401b6bea12bad4293f0048efba066f539d1269e0a16fbeb2daf33fd47387688b43d6bf4b4f09d7c3bc07175f954c07f6946c5f4249b7b71f802bca3bdf8019dd6deae065f154a61e151b42b3040866dc7deba7df66f03ea721787e2268e58194b3cd8d9c1f9e965cf3e87b53f466fcaea4b3c9f1853807b05db27e4a206106c2bd7bde96102c3d0f0362b46853a36a12b18c9a0b83b2bf8dac247252c7138fe258c82f66d3446cbc41fff1d6abb165c776d23f6d93053ad368787b6907b1061f86f053ac2fe0ce77d10d8b5d3d52736b6bd89446aa529e636a83b70fe4a13f364d44f0db842cebbdad2e01b41e4ae61ffd309c30666498b9164c9410dca9d90879369602ef8670fc0f82e0deba5e753726e5909234aa1e2086b711d459db6ab35e7d81ebce83c1df31b6c48808f9d52020a72c99e07ca4e0de97e9bca82e2abde799287e966f03b783285cdca5ccac3b9653d94ccb17017a37b5af22832876427b0842849696a39349faaa03ef3078f51c39e4153e1330bb5be69f1103530cc09c5cef0b201111970b0d901a70af9dfa4bca6b34dff016066863936f3005f87f971bdf723d4aa71c8dee65564d66f6e4e2fe83e2a11b097c6a14b651bf1b7e253282e9adf0229f158c1ad0bef485e7a904df7c56cab5724e31b2de2ab6d87abb85a5b7174e27c3c515c1b77bc181d25eec397987deef62ed117c800f434664ce870d7d3f580d330147355c369e6564f049ea833cda2ae8fa9e34ca1a63dbf2117f5a5dd530e85224ff495035e35ae0201a608593401611fa631faa7f8029707fc0333c219acab704dbb9b80a7010989f1f3fa4856cea880c4b3e8e2d43fd12fc46f23dfc079f30407a80956938e27c0354d4f8e3e455497e9679cf2d8b57bbccdbdb75331f15e6fcc26346346d0b59913cfbaf38b2d73091b2c5497f9a8a8d0be52c205c89860e2b11bb16976796d2766b3efb36626bf1d894fc00ce4bcefbbab2608aa37137680d64e568bab8abba22d8fc846ed607e2fcd80a64f11ffb589514e3758c72f7c485a0e62b21de20fb2c481fa14aca0db56fe998247e9f41643b171b904cdc4babb4dd03533bc0b90deba0b66b103492d0ab79b2ae63e79484ebf0ad96b32da892ba082991f77ce7475dea0390f837df5bbca8a64934d722912d651b3c09b02bd3cf2874d3c8ca66496db05c6392963383cd417fca84a4492901d5a532941bede6878f2c0d387bc93439e1e79472a625bfc6f78c54ef44a395da80e6c0b777a6348b356af1c8176087ec63f87555afb3f6b594ac2fee5287b9313a556a3597c69ec3ba1fa1ef3c46c6135fbe78fb739af045d0c0ed99cfede95d7eadb381cd160f3bc34efff00ec4c417e49675c8b6b1f2c3e3f3f66c0db57c468fc7f7a48ff7aeedfa6814e5a0bdf5946f7018558c990e3ce934456b27c6a082481791de85712a334e5efe61e5863647299afe3157d5b815c9935512473ede307e8a546b32c3a85cc65a71a2f9cf4d89cb6d0451789ff6d47cd64448dff7a2cd03a11adf2ffb94618e50221ab6a9718d56dea31af92318f53bb874171f3f34c07b2d9bcbafd944cb02ada658ea094972fc68e21cbef4d884cc594671146ddaa3843fccd56af84aaf0047b2484a24c3b04b067a00dd89a097aaefea71f187e0581fa01a102056b8d26f4cb6900eeb26c860eeead7201fd2d9f2383ce5ec4f330d059dba708ab3eb6ad6662a168c3be14e226791a7d7168495b5826c8b57ba819ff359c984de9daec5273a2853675756a9422ef0ba8bc08961b333d7bf702db9dab08fdca1db9ab42fe80fdbbd020a4d0bb1335df43a8749bf3f5f1d3a30e130e8b7b43e7f78cfe32d0b324e1dbdf151b73cf2f93a7315b080573b4b819e4264526d30f987493d1597ca97f82279cb23eaeca4ebe4ece55b8e09a2deb15c2ae49898f71b7f5694e7e6089ee434c01d1ad586e63dc05e7074be8db1019dfd6ef54a10831c0fc551bed0ae5e40b3585bcbc4b71537f4a4b6b4f355598c897adb5228db77002a2cb148d90c7ea8a4e83af590b48342a053a4240a4239c16ae937fcfc7da372f6b506a761f60f70a8af108914e4aa0050a64a7ae2f73b557eba12166224f32f095e0b91b9f0a75a83ebdf96e59878af7948c553437147187aeb2088910ebc5498711a9443715523140636311999297b504cdbe084e0c5a99b9aeb57bbb974c51b0a49c30cfe2f5f2bfef509258f2d7cf5217b83c710f1ae4bd33a47d17f349779221203baf87c10fc3f93e6c3d2859676104769fedc10032fe91a5d6c027e7371560728a9dcf814b44792721e23973873550ebab1795da12b73ae5d895feb51709406dd3b18ff53fb5d3af8b0b714e484afbc262ba6f2a720ab0b18cf75d1f457e04928334377644332fc58a8f77e91f95d45b684818095b7e41cfb60be405ee289986f36b7e892bb7422aae9656fb031eb9d9b63bb4c70851689c40d54a17f7b48f0f97b3ab9739f937dd251689ef40c92fea33c99db294c1bcc27b695a288cfdff197c28027e7276611f8f97fe98384a843e4968bae4b1f63393346a753aa06042836b6eb1adc25d78c298a234b1cac319edf789f6abaa6d67094fc7f48b24b92d030baf14955159339d38a006fef1349bb73b6fec03b9119f97ea753bf376210c467520eb7cd052a36161eaf5062be089fc657f8fa2245a5887b29c26216a143382bb5e3b77b6f2cc5559a8c4915c496548734666470f24dc19d65f1a0ac2dc1b553f0c3af1510fbcee5f57461b6d14d3bd721e62238c06e2784f1a012fde89e352bbf2365b565d50ee27246fc00bd62fe46ece7b976802a697ccb7c717f85839a6e39b20bffd8e0e25e7b128c962421fde44ed4b742fe7af596add878c920cdebc7afbb42800177016cdc39d852dc64040be9fc5182c05f530e669ce2d0489b5fb5ea95fc56fa3fec5e27e0b7a450507f0b3de240899647fdfe5e7d52546aa7c358d02fe9fea6767d662d651ec1fb10e613b1f219c440362bcad23654f8602dddfef51c21e431c75b0317d0df0f843df1495817a85367e081e1df83647b7d07dbacc4874816214aaeae0a574f57381cc70f4cb782034e9974a6c4cf23c247e69a0f7fa08750b08634957ffb8826bc753bb42000c6df0e2b493ae873f7d30ce865d5a419fae68052d035a898d89642f748e6a50cc49129042298325da86c94b430396fec4bb4d3cb232a23e051061f31b9c6152c692caad3f9a1c44d06e4766d4a3137c638fa75eac3ae9e1c6a6226667470592040fa642e72722b1c98badc64d33ab3d28f1cf6f30a4c63d65d14bbd626c3612716817d83f3f9a2d96022fd5159fa45e765d02d141a4f66ed715ef7695b0ff2bb59360a729e23fbdffdee91fcb8b8a3d9e9312a522f153acbc9e9a0b412747a936731577b0a91aa6b8ae503bc74a83462f3ce2ae41a1c152a9000ad0bd7443c2f41fefc91efab2d43099aea185d7200861c97a6787cfea734be370bf36a510e4fdc186aa9f4dbe92f32fa3770dc8db2d7cdcbf9344157da48d6a5ebacbebddeae4c408c08de0a081aaf79d98b230eda6c8823cdfe59bd148b736d02f94b64afc46d3df29558891bc48c8ec7d485aa99c4417a1879c9ff1625f3e821b2347c176a0ef958ad7fc54eb10a53005b922393cee5a6cf7300f4c9171d462ddabbc0227d491f37606fc5c8e545d2a85634608", 0x100c}, {&(0x7f00000001c0)="25fd26f0c2f6f8454eb4598cefd3a544b22bac827dfb6921cd320fabb353b6abd1bdf7a6dd432ca5295f892a5056cb9908d6095b22d9c0274f069fd0a76fa516008092282620fdb3582c7b29a74fc9a0628e26889677f0ab87054b774261de8656a080d103c0504abd02c0f742a4a5cddc2434f350c2d1e641ddfb5bd0cacc83eb73828ca34a56b3b35bc8b2610eb4eb453adb749734526c46d9b2ab6d8614761d796909a6fc66c7d08cb1527152db4272ad88493fb38f40398b5ab50934fa551a4b2630e0900d08787e89612408f5c38d3185e17475d4a4942473058501ebaf20b435261800"/240, 0xf0}, {&(0x7f00000002c0)="e041bac6e222cda5a8a83a629eb6514522c599cee99c1c36bf1a6bc1303e5e1af2c7d6ef7e7a04f1ec148d49241dd0881538a2afc2faf893f9dfa86f68f0f3f25c0bc65341263ac9ac9d46c0f4257d89bc3db24110867d5653d7bfbe294fd3c8f7d0da9f05529ae206849560ac6666403704762cd5c286b039df3ed0e2aa6f15488dfe95d5b74aefce77e0afee5ddd2876e6cf2d4619b88ea57677837ad4273acd0f", 0xa2}, {&(0x7f00000015c0)="6973b3b7b5f516f850b75a28715b10f7ad5d42b6ad24befe41ebdfe071af14f8fc7b9031407b78e22b9d0814b9d792c9c83e6b98efb4993f4ad8f4562dc983a42eb32fd9120e86d581ca3b880600d14bf2fced5de86ab55c2a3e0199c24c232e3965832a8b339aa00261dde68a2350cd0cdccb20b3598262b33d77dfb2f699e8003ba5e6852657ebe417b248026d5e8fbf77988e4508f37274f008a4fdfa9b8c2a1838de9e17b63c47d9fa63336e630736d37c3d7c65312e131b4004fe487ef66b23acee047b049423f836ab87a7345585cbf92f2a4ac7e1cfe61fc4349db1e33c2da8f35920c7c73d54042f6daeca3eaf67967c50e6da9709ba6f60f11ba40091ddf33ab51f0af7d079126cc2a31c2ed60bd75314d3d4b3fb6844", 0x11b}], 0x5)
writev(r0, &(0x7f0000000800)=[{&(0x7f0000000600)="ec6e6688290eef4d1e3caf403d1c8ec76572ea971ab9100008000000000000e9ca199903fdc9ca6118d232a369e4e3741dc001fe64edfe80fc7c67b715015e97d64167b4cc024469e8ecacfe668e499fbe1a617b4fdd72d4b72f2d2dbe26f7bab1158d052a9d215a57d3f2ba438cfaf0b979ffffff7f97a05b0000000000a41dea0dac1cfc8351b5fc7f6a30b0198d8c3c9b993e5261fd9af52ff55b1467b1a3da339b46dace9eac800dfc30d91c20cc93982a3c1df9a4f4ce9830303df8e752879e4ec3b7216edd72fd", 0xca}, {&(0x7f0000000380)="6e0e59233e96f72fbe9d7537c357c1e762ffdd2941d1480727fd7e2179cf9d641dc9cacb280d539069084c386a14de14b8d6ed2b78bbb26aba3379894e573bfe95dbf8df93438d0c534134a7898dc14ca5cca20aaf4bb1443b740645be2adaf635694e4e6ad1", 0x66}, {&(0x7f0000000440)="06f2d803612e7c3baa2d418f22715baaa6d45f8a50f1cffc08bc399d774601dfc4f36e37320c27dd6c0f91d2a7ba63361022803132f486a8e3d4a6448eab74f80505e0f87950b4c9fa81dc2544e390117246d5a994c5781aa279fe298273fea66e7ce2b926f5acd0d1dd0b375905f26a8935eda41833b3891f1f56c1e95bed206462a8c1248fff9f06d41336ef4a", 0x8e}, {&(0x7f00000008c0)="12b1c68e4e76099b4c66a551dc6f52feeb34be35ff519fdffcc2381874f4e22146234bd7fdd653264ede74f85478f382a524978e17e1668fc8c3c27e57219888594710cb91a83fe52cb4b0a622e2c27fda34f75bc07eb331bf06e05a60b012427f8766f9a8d41134b1e4fb77f608bb25b5cf2b44ede1681033c314a01ea45a28bcd2512788ad3e876415d6b570827847e07bd29a49742f68e434af36448131c789d3e209a0a4fa3d3082d27dac39999e72a0603dc4e2dae3768ac549136b868fb642d55f", 0xc4}, {&(0x7f0000000040)="d1", 0x1}, {&(0x7f0000000700)="52aeab1ce5077eb22066fb42b5d697c647555d642778f7638d2296872a486ab134d67cc8576900ae534b4e7fc38d1bc0581d9b961989b51dfd016f484c95d1bd10f0ad5419b0650da9f35861a26ebd9522a2c3232722bfd6f5036847aa5974fb538abeaace326a55f53179042ffd16fde2ccd5", 0x73}, {&(0x7f0000000780)="42e54155126a70a32d59019723c9b40e7959efc2e9fb1dc97efc5a70a08048", 0x1f}], 0x7)


r0 = open(&(0x7f0000000000)='./file0\x00', 0x9cab835cfdc52675, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x2, 0x4001, 0x0)
r2 = dup(r1)
r3 = fcntl$dupfd(r2, 0x2, 0xffffffffffffffff)
r4 = socket(0x2, 0x4001, 0x0)
r5 = dup(r4)
r6 = fcntl$dupfd(r5, 0x2, 0xffffffffffffffff)
close(r6)
r7 = socket(0x2, 0x2, 0x0)
connect$inet(r7, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r6, 0xffff, 0x1023, &(0x7f0000000040), 0x4)
shutdown(r7, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0xa011, r0, 0x0)
poll(&(0x7f0000000040)=[{r3, 0x1}], 0x1, 0x0)


syz_open_pts()
dup2(0xffffffffffffffff, 0xffffffffffffffff)
sendto$unix(0xffffffffffffffff, &(0x7f0000000080)="e066fe71dd54c85048a6ae968c22233da611a6ad5fcdcc0da4f05e65380e7c4b38a7e8f79747fbf6778a2124e8310d6299fad15811fa56d3dafd663879a0e3a49d494c166da97165e69ea5b87139f65c8357ce80b37ee49321c89c49c79bd5ccf3a7c6f229d492f017366bd0356fd2c3dc6b27a7419141977b3add295b237297d0d578a7acdbfe2d9509729ff1a8687a2e3a41818466c5802d986dc210fea19a3636fdf6a0a5ff67eb73a775d184bf68c3637ddd3c58cadf78f01593bb86a0ed2afec8da739ed43d541e2a5df12e16d1a71ce14a6169717e65ff1c82db550717668dfe1e356e0797c0d5204613c21b75aad6d61c8d949c85f3fe007a1fc714d30fbe12dbb318c8aed8aa85abafe3242789a90936962bd1", 0x117, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "0100012d29fb00"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x54}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85baa97981056ef1043f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0x9, &(0x7f0000000340)="0a000000f0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0x4)


kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x4, 0x0)
kqueue()
r0 = dup(0xffffffffffffffff)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
pwrite(0xffffffffffffffff, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(0x0, 0x0, &(0x7f0000000100)="d7a8aac106fa1bee91c724b89283c1477dab85e783af4189a1eaf5f6e8251b1147b330f604ff639b9acd6202c9d8b1aef98ce6eefe", 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
sendto$inet(0xffffffffffffffff, &(0x7f00000000c0)="6c25a03ae7b27b4e7fc0924a22334b9b619f09f993c214bf34de94ee6f878793a443c48892901b940ff2189ae976bd635aa66dd55818d1ca20a7f88c2ad799df41ea701f32e36ab928f0ea3b00ddc5613e3590c04b342a5ec356d4f406e612653d7338e1b59ec0f00de4b65b3f18", 0x6e, 0x0, 0x0, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r2, 0x8080691a, &(0x7f0000000100))


clock_settime(0x100000000000000, &(0x7f0000000000)={0x8000000000000001, 0xdc9})
mknod(&(0x7f00000000c0)='./file0\x00', 0x2000, 0x4302)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0xb}, 0xc)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x34}, 0x4, &(0x7f0000000080), 0x0, 0x0, 0x0)


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r0 = shmat(0x0, &(0x7f0000002000/0x2000)=nil, 0x0)
shmdt(r0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$diskmap(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$DIOCMAP(0xffffffffffffffff, 0xc0106477, 0x0)
close(0xffffffffffffffff)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
socket(0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
r1 = socket(0x0, 0x0, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r1, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
r2 = socket(0x18, 0x2, 0x0)
r3 = socket(0x18, 0x2, 0x0)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r4 = dup2(r2, r3)
setsockopt(r4, 0x1000000029, 0x23, &(0x7f00000000c0)="b211d7170d816684c8e360f2fa41c1a0946988b272d2dd3dc90142a84231a746e337b372e93320cff6669cbe7868de45ed3fc33719ca6df71ecec8a918458b2c10a1f8c66653b276e7aae9cb9b21f9982230f575295d48889c9a920796b2dd92fc8575680b37ba955d2c15e6d7c9198ed900ab006ddfb67869b51a2216114d1ece85f593e74035f5bc054eb1dbddf42a", 0x90)
sendmsg(r3, &(0x7f00000002c0)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)


r0 = socket(0x6, 0x4, 0x1)
setsockopt(r0, 0x1000000029, 0x2e, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r1 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
flock(r1, 0x1)
fcntl$lock(r1, 0x7, &(0x7f0000000280)={0x2, 0x0, 0x0, 0x1000301010006})
open$dir(&(0x7f0000000580)='./file0\x00', 0x40000400001803c1, 0x0)
open(0xfffffffffffffffe, 0x400, 0xe)
syz_open_pts()
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x30, 0x0, 0x1}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x1, 0x0, 0x7, 0x4, 0x0, 0x0, 0x0, {[@generic={0x2, 0x6, "96c72963"}, @sack_perm={0x4, 0x2}]}}}}}}})


openat$pf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
select(0x40, &(0x7f0000000c00)={0x9}, &(0x7f0000000c40)={0x1}, 0x0, 0x0)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x40, 0x0)
ioctl$VMM_IOC_CREATE(r0, 0xc2585601, &(0x7f0000000040)={0x10, 0x357, [{&(0x7f0000ff9000/0x7000)=nil, &(0x7f0000ff9000/0x1000)=nil, 0x30f8}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffa000/0x3000)=nil, 0xfffffffffffffffe}, {&(0x7f0000ff5000/0xb000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000ffc000/0x3000)=nil, 0x4269}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ffb000/0x3000)=nil, 0xfff}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff8000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ff8000/0x1000)=nil}, {&(0x7f0000ff8000/0x3000)=nil, &(0x7f0000ffc000/0x3000)=nil, 0x2}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000ffc000/0x3000)=nil, 0xbc7}, {&(0x7f0000ff8000/0x3000)=nil, &(0x7f0000ffa000/0x4000)=nil, 0x2}, {&(0x7f0000ff9000/0x2000)=nil, &(0x7f0000ffb000/0x2000)=nil, 0x1}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ff7000/0x1000)=nil, 0x7}, {&(0x7f0000ff5000/0x2000)=nil, &(0x7f0000ffa000/0x1000)=nil, 0x8000000000000001}, {&(0x7f0000ff8000/0x1000)=nil, &(0x7f0000ffb000/0x4000)=nil, 0x3ff}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil, 0x3}, {&(0x7f0000ff5000/0x4000)=nil, &(0x7f0000c00000/0x400000)=nil, 0x9}], './file0\x00', 0x1})
r1 = openat$null(0xffffffffffffff9c, &(0x7f0000000240), 0x100, 0x0)
connect$unix(r1, &(0x7f0000000280)=@file={0x0, './file0\x00'}, 0xa)
connect$unix(r1, &(0x7f00000002c0)=@abs={0x1, 0x0, 0x1}, 0x8)
ioctl$TIOCSETAF(r1, 0x802c7416, &(0x7f0000000300)={0x2, 0x2, 0x3, 0x6, "7691069c00e510f74a62aa40d25b0be91444b567", 0x7, 0x4})
r2 = socket$inet(0x2, 0x2, 0x1f)
setsockopt$inet_opts(r2, 0x0, 0x0, &(0x7f0000000340)="9d443513bc8fb7bc8dafb5f4c00b1c7bce596d3e89bf4a1032464200274aaee541f3d9ee20d09bc7aadbfd7abbeeff418bb0c65303f4b62f1dfc33eebac3b37bbd79062d75539fa245e5ed4c85e94e5eef3ed56f393947109a8459f6903d130da79e879675a0afa283a99f5ccd2cf222544eb7818914085fd94d42bfb601053af7658f552e3d112023152f655a36e41588519a8329ee9d7d2a3361e086cb5e0fb5cebf0fe32cd8dccdb02f5f32fecd7b2757dc75295d819bece48c5d0f7a208d1a7e6c2f5b1ea394353674f43a010cdbdc7d0796622827444dcf42cca315fd0e7da066153734053787f9f195c34133ca8e", 0xf1)
connect$inet(r1, &(0x7f0000000440)={0x2, 0x1}, 0xc)
ioctl$VMM_IOC_RUN(r0, 0xc0205602, &(0x7f0000000700)={0x4, 0x2, 0x92, 0x3, &(0x7f0000000480)={{0x1, 0x5, 0x7, 0x3f, 0xef, 0x8, 0x3f}, {[0x0, 0x4, 0x3, 0x3, 0x8df, 0x535, 0x8, 0xffffffff, 0x9, 0x2, 0x0, 0x7, 0xffffffffad8d0227, 0x2, 0x7, 0x5, 0x81, 0x2], [0x9, 0x35cd7ac8, 0x8, 0x8000000000000001, 0x2f78, 0x8, 0x7, 0x0, 0x4, 0x7fffffff], [0x5, 0x6, 0x0, 0x8, 0xee0, 0xc69, 0x773], [0x8, 0x8000000000000000, 0x100000000, 0x0, 0x1], [{0x200, 0x3, 0x8, 0x6}, {0x80, 0x7ff, 0x8, 0x8}, {0x5, 0x5b0b, 0x60000000, 0x7063}, {0x0, 0x0, 0x3f, 0x6}, {0x120, 0x0, 0x10001, 0x7}, {0x81, 0x1, 0x1f, 0xfff}, {0x7, 0xffffffff, 0x7}, {0x1, 0x270, 0xffffffff, 0x7ff}], {0x200, 0x2, 0xfff, 0x1c00}, {0x28, 0xb120a20, 0x207275fd, 0xff}}}, 0x6, 0x5})
fcntl$getflags(r2, 0x3)
syz_extract_tcp_res(&(0x7f0000000740), 0x4, 0x8001)
r3 = socket$inet6(0x18, 0x4000, 0xfc)
getsockopt$sock_linger(r3, 0xffff, 0x80, &(0x7f0000000780), &(0x7f00000007c0)=0x8)
sysctl$hw(&(0x7f0000000800)={0x6, 0x4}, 0x2, &(0x7f0000000840)="2d4f7195186940eddfed52ed4e175c770f47e17d89c96025620259b34051326f3233c74aa6a32bbf8fd889c2c8efa93ef8399a10cb5a013df935162023695ec5259aeb6b8123c9165c64d67b654d4e5a7402dcebf28f2c18bedd0200f5019848c6d99205433fbd4b87ca8ccc1674d43d56e01858da71cc3447d326f56c3fa8a14560647f5932d3e3f5d607794f354bd30e703fa66ce1ce12cecf1ed94613eeff1820af359d95812671c55169af6f2a9a29175c6709d9dd7b088b6b48c4ff937a0e87b819608b8fedd71ed8141881ee01cbc67f4bb147367a738b7f5bdf526cab2bcb64eeb5fcba61997382d91e4ba8fcd9c264698ea71d57dff7d1a70537", &(0x7f0000000940)=0xfe, &(0x7f0000000980)="60fe1c1727174f6df844be190cdf92fe0ad2003e29d71bc659ff829953176d33a47c43493477af5ec25c55b659bd392a356f1b5bbb72d0871a2a7761565ac41b5cd4c04e77e293b5066216208ad15a3eabbe4845dc721b7a", 0x58)
r4 = dup2(r2, r0)
read(r0, &(0x7f0000000a00)=""/190, 0xbe)
semget(0x1, 0x1, 0x112)
sendto$inet(r1, 0x0, 0x0, 0x400, &(0x7f0000000b80)={0x2, 0x2}, 0xc)
accept(r4, &(0x7f0000000bc0)=@in, &(0x7f0000000c00)=0xc)
getpeername(r2, &(0x7f0000000c40)=@in, &(0x7f0000000c80)=0xc)
socket$inet(0x2, 0x4, 0x20)
sysctl$hw(&(0x7f0000000cc0)={0x6, 0x19}, 0x2, &(0x7f0000000d00)="3a903e6ecd9fceae59730a4ffa442c6c0fa0923235497da136aeee28384d05eb58ca734f4d885ace9616f578d04d6512d5d481c1d34d03a90c792fdbfebac6462ede855226221e0f410626b02571a54089534b736c20b586da5ad7608f68d9bcbbf17ef6564fac82a63411db4b8446778c8339d6cff6ef395fb2e2ade1d9a8a2a8f0c7477d7b2488f3b98b409e9045835843342d80f81d371a4814ed3e0b33fb20e4f8fdf8a3fb055342d18db17fcd6803a55eafd1d938ef9d41b4b4161c35", &(0x7f0000000dc0)=0xbf, &(0x7f0000000e00)="ee8423f8d2a7ec0ec6136ad0bf79f94adcb84708d9bde050d0ebece028fd672504f2289307bbaa6d4e4c26746920cb121235fa64d90465e43ea54f646665af26b1b62b9ed403505f4e82b86deb598da8aca1711b12f88eebb9adbda18122695dcc5d6bb899fdf121beaf52787d4caf24376aa95d1b1c0ef8882ed7af7b3360a6dcff7f0b4befe8eb4a566fdcfa0d8d6544a34cb231f32efd1129513013648954cda668b338b573b99ba3b2d1faf112056c40598bc03a25ce48203af0bc3328bb9b6ef8de9f51dd4cc6f8c2ba39ce85140d7a9a2efe97e501fae5ea19008704d7c1ddc293ba", 0xe5)
execve(&(0x7f0000000f00)='./file0\x00', &(0x7f0000001100)=[&(0x7f0000000f40)='\\\x00', &(0x7f0000000f80)='[+\x15\x00', &(0x7f0000000fc0)='/dev/vmm\x00', &(0x7f0000001000)='/dev/vmm\x00', &(0x7f0000001040)='\xd9\\**\x80\x00', &(0x7f0000001080)=':\x00', &(0x7f00000010c0)='\x00'], &(0x7f0000001240)=[&(0x7f0000001140)='/dev/null\x00', &(0x7f0000001180)='/dev/vmm\x00', &(0x7f00000011c0)='[/(\x00', &(0x7f0000001200)='-\x00'])
execve(&(0x7f0000001280)='./file0\x00', &(0x7f0000001300)=[&(0x7f00000012c0)='/dev/null\x00'], &(0x7f0000001440)=[&(0x7f0000001340)='\\\x00', &(0x7f0000001380)='*\x00', &(0x7f00000013c0)='-^-@)\x00', &(0x7f0000001400)='[+\x15\x00'])
connect$unix(r1, &(0x7f0000001480)=@abs={0x0, 0x0, 0x2}, 0x8)
getsockopt$SO_PEERCRED(r4, 0xffff, 0x1022, &(0x7f00000014c0)={<r5=>0x0, <r6=>0x0}, 0xc)
rename(&(0x7f0000001500)='./file0\x00', &(0x7f0000001540)='./file0\x00')
r7 = getgid()
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001980)={&(0x7f0000001580)=@abs={0x0, 0x0, 0x3}, 0x8, &(0x7f00000018c0)=[{&(0x7f00000015c0)="5655bd40b3f7bc8a16240aeae7a49bf1e8a89d2ac4646153f59b2822d72f9e9f96864dc691b4ea8ee871a2ea1880b94a81be08e81853d83b3098a96f04be95276c8a2aa353d27743e293496d149b549d58d3a20e43b9b6af7efe227e98f3c204b324335a2b3a6ae5e50feb65cad0032e5f8c0b36ca04afdd9c9028289ed7595a1179d4076929bbd88ce28be717db269916ce33bc7e7ed0401093f4f53a2fcf8102a0582d2caa71e70c69b4aa5854967343941d2a1a3076f0ed57ab3242771decb6942359f3d5e633d3cea0ef2251fff341a1df6cc8d1538c4b89de3bef1dba929c007c5b6dccd3c1b801009a00cc4aeb9e0c3e8901e904ce", 0xf8}, {&(0x7f00000016c0)="47833471270326aa87a434f79ea3ff85f39b90b82cb5f8d7e0a911c319f5cebd07db08634a446026e9d9e99cccfd52b74430cfb8cc76460281263791ea0df3bd91d203cb0fb95eb916757d987b87e3ca9c9e02cfbe789c9d8e2ca8a01eac96cbffe0ce36f74f29ce93204926f70909bf5da4673be23fa3e16683e7d5d9ddc3ae3c431697fcf01ac6d9bcde122977ca8ec00d9fd13e442a795b0b40eb999b1f9d4fdb24cb207e69", 0xa7}, {&(0x7f0000001780)="d8ac22e0e8f7d6dcf45eae3ecf4959c1429a91991281a200a4db79dcd26e5a927a51e390213cf74bfef8503d65b918e74c69ab87a09d67297d5c9a2bdd3b653f0f3eeb7bed823c7cbf9f8d82c687c91d82ff0486c517a07b5ef4a9c09ad589116eb363a67e9d109e5c80358ae32034901fbfbd64d6418622a3e578e424", 0x7d}, {&(0x7f0000001800)="4333b9f075146d74217eee5e7f02e0aa65a739f293ed9f51761e60a49998c4d43eff39bd512692b4774e84cee775", 0x2e}, {&(0x7f0000001840)="af7bee82ef6f9a1dfa261436dc5185e933b642b680b3a37bbf1ea0ec5392f8829c1b92312b968d4206d2688c69721b6d75bd4a7faec7bdfc6018baf902de2d941a42c2203a937ea3c73ec86fcdcd2e8384cd2ce58db1ea30c223f42178632933882a2102668fc99ef911d2712a74942b277f", 0x72}], 0x5, &(0x7f0000001940)=[@cred={0x20, 0xffff, 0x0, r5, r6, r7}], 0x20, 0x402}, 0x7)


sysctl$kern(&(0x7f0000000240)={0x1, 0x48}, 0x2, &(0x7f0000000100)="71f91e34", &(0x7f0000000200)=0x4, 0x0, 0x0)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x100000000000000}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x1, 0x0)
dup2(r0, r1)
setsockopt(r1, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


open(&(0x7f0000000180)='./file0\x00', 0x80000000000206, 0x0)
socket(0x11, 0x3, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{}, 0xffffffffffffffff})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
setreuid(0xee00, 0x0)
r0 = getuid()
ioctl$KDSETLED(0xffffffffffffffff, 0x20004b42, &(0x7f0000000140)=0x7)
setreuid(0xee00, r0)
r1 = socket(0x2, 0x2, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000000000)=ANY=[@ANYBLOB="ffffffffffffffff"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
bind(r1, &(0x7f0000000000), 0x10)


r0 = socket(0x2, 0x1, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
recvmsg(r3, &(0x7f0000000100)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000180)=""/225, 0x11e}, 0x800)
sendmsg(r2, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x44002802)
open(&(0x7f00000001c0)='./bus\x00', 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
r0 = socket(0x18, 0x2, 0x0)
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, &(0x7f00000000c0)={&(0x7f0000000000)='./file0\x00', 0x0, 0x0})
getsockname$inet(r0, &(0x7f0000000080), &(0x7f0000000040)=0xc)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x3, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r2 = socket(0x18, 0x2, 0x0)
r3 = dup2(r1, r2)
sendmsg$unix(r3, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


open$dir(0x0, 0x0, 0x0)
syz_emit_ethernet(0x66, &(0x7f0000000100)={@local, @local, [], {@ipv6={0x86dd, {0x0, 0x6, "36ea07", 0x30, 0x0, 0x0, @empty, @local={0xfe, 0x80, '\x00', 0x0}, {[], @icmpv6=@dest_unreach={0x1, 0x0, 0x0, 0x0, '\x00', {0x0, 0x6, "5adf00", 0x0, 0x0, 0x0, @ipv4={'\x00', '\xff\xff', @rand_addr}, @mcast1}}}}}}})


setreuid(0xee00, 0x0)
r0 = getuid()
seteuid(r0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200100000001d, &(0x7f0000000000), 0x4)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$wskbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$WSKBDIO_SETENCODING(0xffffffffffffffff, 0x80045710, &(0x7f0000000080))
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(r0, &(0x7f0000001580)=[{&(0x7f00000000c0)='\x00', 0xfffffeb0}], 0x1)
socket(0x0, 0x3, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$TIOCFLUSH(r0, 0x80047410, &(0x7f0000000100)=0x2)


r0 = socket$inet(0x2, 0x2, 0x0)
close(r0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000a, &(0x7f0000000040)='\x00', 0x1)
setsockopt$inet_opts(r0, 0x0, 0x9, 0x0, 0x0)


sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
symlink(0x0, &(0x7f0000000200)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/file0\x00')
close(0xffffffffffffffff)
sysctl$net_inet6_ip6(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, 0x0)
r1 = msgget(0x3, 0x0)
msgsnd(0x0, 0x0, 0xf0, 0x800)
msgrcv(r1, &(0x7f00000006c0)={0x0, ""/182}, 0xbe, 0x0, 0x1000)
syz_emit_ethernet(0x22, &(0x7f00000000c0)={@local, @broadcast, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, @local={0xac, 0x14, 0x0}, @remote={0xac, 0x14, 0x0}}}}}})
r2 = socket$inet(0x2, 0x3, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x1, 0x0, 0x21)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x8020699d, &(0x7f00000001c0))
connect$unix(0xffffffffffffff9c, &(0x7f0000000000), 0x1)
mprotect(&(0x7f0000001000/0x2000)=nil, 0x2000, 0x0)
sysctl$kern(&(0x7f0000000300)={0x1, 0x1d}, 0x2, 0x0, 0x0, &(0x7f0000001440)='\x00\x00\x00\x00', 0x4)
r4 = socket(0x2, 0x1, 0x0)
dup2(r2, r2)
setsockopt$sock_int(r4, 0xffff, 0x4, &(0x7f0000000040)=0x3ff, 0x4)
bind(r4, &(0x7f0000000000), 0x10)


openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r0 = socket(0x2, 0x4001, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r3 = socket(0x2, 0x1, 0x0)
r4 = dup(r3)
r5 = fcntl$dupfd(r4, 0x2, 0xffffffffffffffff)
close(r5)
r6 = socket(0x2, 0x1, 0x0)
connect$unix(r6, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r5, 0xffff, 0x1023, &(0x7f0000000080), 0x4)
setsockopt$sock_int(r2, 0xffff, 0x1023, 0x0, 0x0)


open(&(0x7f0000000000)='./file0\x00', 0x200, 0x0)
writev(0xffffffffffffffff, &(0x7f00000001c0)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe1463a52077dc0d00003ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')
execve(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)


r0 = open(&(0x7f0000000080)='./file1\x00', 0x200, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
truncate(&(0x7f0000000140)='./file1\x00', 0x20)
mmap(&(0x7f000000f000/0x1000)=nil, 0x1000, 0x0, 0x10, r0, 0x0)
socket(0x0, 0x0, 0x0)
syz_open_pts()
ioctl$TIOCSETD(0xffffffffffffffff, 0x8004741b, 0x0)
execve(0x0, 0x0, 0x0)
ioctl$TIOCSETD(0xffffffffffffffff, 0x8004741b, 0x0)
execve(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
getsockname$inet(0xffffffffffffffff, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x0, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000), 0x0)
socket(0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
mlock(&(0x7f000000f000/0x4000)=nil, 0x4000)


openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
faccessat(0xffffffffffffffff, &(0x7f0000000040)='./file0\x00', 0x2, 0x0)


r0 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r0, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
getsockopt(r0, 0x0, 0x6e, 0x0, 0x0)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b10005036000009f0500060007000000331c13fecea10500fef96ecfc72fd3357af302b37b673039d2d236acf20b7804be38224991f7c8cf5f88882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f4d335c223e7d026ba8af630037282102000000720fd38bfbb770c1f572ca81ea77b3c5890400000000000000361b1257aea8c500002002fbffec2200008abfba090000001d89e400040700000080042000"/177, 0xb1, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000280), 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000040), 0x3, &(0x7f0000000080)="397c9aca", &(0x7f0000000780)=0x4, 0x0, 0x0)
ioctl$VMM_IOC_RESETCPU(0xffffffffffffffff, 0x82405605, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000400), 0x0, 0x0)
ioctl$BIOCSETWF(r1, 0x80104277, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x3}, {0x50}, {0x6}]})
r2 = semget$private(0x0, 0x3, 0xb7)
semctl$GETNCNT(r2, 0x0, 0x3, &(0x7f0000000240)=""/65)
semctl$SETVAL(r2, 0x0, 0x8, &(0x7f00000000c0)=0x1)
syz_emit_ethernet(0x1b, &(0x7f0000000000)=ANY=[])


sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x13}, 0x4, 0x0, 0x0, &(0x7f00000010c0), 0x210)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
r1 = dup(r0)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{0x24}, {0x2c}, {0x46}]})
syz_emit_ethernet(0x36, &(0x7f0000000840)=ANY=[])


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
r0 = open(&(0x7f0000000240)='./bus\x00', 0x0, 0x0)
pread(r0, &(0x7f0000001400)="ce", 0x1, 0x0)


r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x27, &(0x7f0000000000)="5ab7776a", 0x4)
syz_emit_ethernet(0x4a, &(0x7f0000005c40)={@random="69e1629b6174", @remote, [], {@ipv6={0x86dd, {0x0, 0x6, "6b9efb", 0x14, 0x50, 0x0, @rand_addr="cb69bc83c1677a656ab420666c3e2c6f", @local={0xfe, 0x80, '\x00', 0x0}, {[], @tcp={{0x3, 0x2, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}}})


openat$pf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
select(0x40, &(0x7f0000000180), &(0x7f00000001c0)={0xff}, 0x0, 0x0)


mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
sysctl$net_inet_tcp(&(0x7f00000000c0), 0x4, &(0x7f0000000000)="9b1809ffffffffffffff7f473f11e1a4e5f2f9f220ef7f0abdbc34fe42021588dc8ff44f4b76c76d41859d85ea800dabe467badf35b6fd74c94d1b44", &(0x7f0000000040)=0x10011, 0x0, 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
madvise(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x6)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000004c0), 0x10202, 0x0)
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000180)="011e827a778862e2b998aa4236bead34250f5ed427746adfcbb98ec9bec660a702e3b77736e61114cc076fdd5070310ff2b0a3ccdc49a25287bb2a5068746e7a4a36d4d51143333a662b0000000000714e7413bc701491516cd066b8f272584a9c8110ac2394dd196b251993b65a6ebd4baef3c1197134f4eae6affaf8ecce6f2a4dae8906ef59b00f90c04544112123267489f79465eafe77ec36f2cf096a6617df8b2ff9f6f6156d5dcd47a013e8412f776af40e45207662977f788b1feb5c8d1dcbd92d88b3e36cb29e1359d86358d1d9faf35d10a07783de25d146ae468e92459159d599b9c1b167299dc2578b431a4a4aeffee76c6e32", 0xf9}], 0x1)
execve(0x0, 0x0, 0x0)


r0 = open(&(0x7f0000002600)='./file0\x00', 0x78e, 0x0)
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r2=>0xffffffffffffffff})
recvmmsg(r2, &(0x7f0000000480)={0x0}, 0x10, 0x0, &(0x7f0000000500)={0x2007fffc, 0xa})
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x0, 0x10, r1, 0x0)
recvfrom$unix(0xffffffffffffffff, &(0x7f00000000c0), 0x832f1f7d, 0x0, &(0x7f0000000000)=@abs, 0x2000c600)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, r0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x2c8})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x4}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x45}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000140)={0x7fffffff, 0x0, 0x7, 0xfffffff7, "2fecacf2ee60987a0d0239060000aa175b31cb31"})
writev(r0, &(0x7f0000000180)=[{&(0x7f0000000080)="b8f980f85c27", 0x6}], 0x1)
unlinkat(0xffffffffffffff9c, 0x0, 0x4633c1de46705d12)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x0, 0x0})
mknodat(0xffffffffffffff9c, &(0x7f0000000400)='./file0\x00', 0x2000, 0x0)
r1 = open(&(0x7f0000000380)='./file0\x00', 0x0, 0x0)
r2 = getuid()
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
dup(0xffffffffffffffff)
socket(0x1, 0x5, 0xff)
setreuid(0x0, r2)
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f00000000c0), &(0x7f0000000100)=0xc)
ioctl$WSDISPLAYIO_GETSCREENTYPE(r1, 0xc028575d, &(0x7f0000000180)={0x85, 0x239, './file0\x00', 0x6, 0x4e, 0x80, 0x101})
mknod(&(0x7f0000000280)='./file0\x00', 0x2000, 0x5d4a)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)


mmap(&(0x7f0000400000/0xc00000)=nil, 0xc00000, 0x0, 0x1011, 0xffffffffffffffff, 0x0)
r0 = msgget$private(0x0, 0x282)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000100)={0x3b, 0x0})
munmap(&(0x7f0000ffa000/0x4000)=nil, 0x4000)
open(&(0x7f0000000200)='./file0\x00', 0x230, 0x0)
sysctl$machdep(&(0x7f0000000000)={0x7, 0x1}, 0x2, &(0x7f0000000040)="60ec01e9ccc902469b4c43c3de981de8937a043cd2933c5f5e97c1fc6a271b4377016ef7dd4cf9324639bb89d081f3d781", &(0x7f0000000140)=0x31, &(0x7f0000000180)="2786ab31a5e4563b8c9e304ef9a23ecb", 0x10)
open(&(0x7f00000002c0)='./file0\x00', 0x8, 0x8e)
mmap(&(0x7f0000557000/0x2000)=nil, 0x2000, 0x4, 0x2dbe387c4417487e, r1, 0x22f2f052)
mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0, 0x1012, 0xffffffffffffffff, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0xb2}})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r2 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r2, 0x0, 0x0)
listen(0xffffffffffffffff, 0x0)
socket$unix(0x1, 0x5, 0x0)
getpeername(0xffffffffffffffff, 0x0, 0x0)
r3 = socket(0x0, 0x0, 0x0)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r3, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
sysctl$kern(&(0x7f0000000200)={0x1, 0x57}, 0x2, &(0x7f0000000240), 0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
setreuid(0xee00, 0x0)
r4 = getuid()
seteuid(r4)
msgsnd(r0, 0x0, 0x1f, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x6, &(0x7f0000000340)=[{0x2d, 0x0, 0x3}, {}, {}, {}, {0x2}, {0x6}]})
write(r0, &(0x7f0000000200)="d81ad3d20cf7eb4e9be33bbd1a30", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000140)=[{0x60}, {0x60}, {0x6, 0x0, 0x0, 0x4000003}]})
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
r1 = socket(0x11, 0x3, 0x0)
sendto$unix(r1, &(0x7f0000000300), 0x0, 0x0, 0x0, 0x0)
msgsnd(0x0, &(0x7f0000000400)=ANY=[@ANYRES16=r1, @ANYBLOB="04ae167205efd3ec3fcd17d294be075746ce926375d6792fb213038424d77d24cfd1c8c1997c662af4ff06c40544fb80864901ee5c9b8c639ee3c4aaaf2cdb72f1f770662262cc5ff07062bcfb87e5db30812b7d2f1a08734f5e44a9c03b3eebba0d7064fbfe620d9cf9f8400a37990bfebb09f7e937394e4713b7da17981620139363367b1155"], 0x55, 0x0)
r2 = socket$inet(0x2, 0x2, 0x0)
mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
ioctl$WSMOUSEIO_GETPARAMS(0xffffffffffffffff, 0x80105727, &(0x7f0000000080)={0x0})
r3 = msgget$private(0x0, 0x0)
socket$inet(0x2, 0x1, 0x0)
getsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
msgsnd(r3, &(0x7f0000000100)=ANY=[@ANYRES64=r2], 0x107, 0x0)
msgrcv(r3, 0x0, 0x0, 0x3, 0x0)
setrlimit(0x8, &(0x7f0000000000)={0x0, 0x200})
msgctl$IPC_RMID(r3, 0x0)
r4 = socket(0x18, 0x2, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r4, &(0x7f0000000080), &(0x7f0000000000)=0xffffffffffffffc6)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
socket(0x18, 0x1, 0x0)
openat$null(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0x40000802)
write(r0, &(0x7f0000000000)="7696e5f3d1f18c37cea8615ac7cf", 0xe)


msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfffffffffffffffe})
r0 = socket(0x18, 0x2, 0x0)
close(r0)
r1 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x40, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = socket(0x800000018, 0x1, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "1a1116f0d0f700"})
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


r0 = kqueue()
open$dir(&(0x7f0000000240)='./file1\x00', 0x0, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x6000, 0x400)
open$dir(&(0x7f0000000700)='./file0\x00', 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x24db362bdfdca8ce, 0x0)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x0)
sysctl$net_inet6_ip6(&(0x7f00000000c0)={0x4, 0x18, 0x29, 0x36}, 0x4, &(0x7f0000000080)="20b7c64185914d070000007d", &(0x7f0000000000)=0xc, &(0x7f00000010c0), 0x0)
syz_open_pts()
kevent(r0, 0x0, 0x0, 0x0, 0x0, 0x0)
syz_open_pts()
sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
socket(0x2, 0x3, 0x0)
getsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r1 = openat$tty(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$TIOCSDTR(r1, 0x20007479)
mkdir(&(0x7f0000000100)='./file0\x00', 0x0)
setreuid(0xee00, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000000), &(0x7f0000000040)=0xc)
setegid(0x0)
setgroups(0x0, 0x0)
r2 = getuid()
setreuid(0xee00, r2)
r3 = msgget$private(0x0, 0x0)
msgsnd(r3, &(0x7f00000001c0)=ANY=[@ANYRES32], 0x401, 0x0)
msgsnd(r3, 0x0, 0x401, 0x800)
sysctl$kern(&(0x7f0000000080)={0x1, 0x2c}, 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0206923, &(0x7f00000001c0))
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x8040691a, &(0x7f00000001c0))


open$dir(&(0x7f0000000000)='./file0\x00', 0xf02, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, 0x0)
r0 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r0, 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
msgget$private(0x0, 0x0)
open(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x2})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x27}, 0x4, &(0x7f0000000000)="71f91e3471ac0058bc5a91501d942400b5e1a0757cb9af769c7afec37082", &(0x7f0000000080)=0x306, 0x0, 0x2e)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000000)=ANY=[@ANYBLOB="89000000ffff000001"], 0x9}, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
sendmsg(r0, &(0x7f0000000380)={0x0, 0x32c, 0x0, 0x0, &(0x7f0000000000), 0x90}, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
recvmsg(0xffffffffffffffff, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
close(r1)
openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x80, 0x0)
r2 = semget$private(0x0, 0x7, 0x3c0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x802, 0x0)
r4 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
setsockopt$inet_opts(r4, 0x0, 0x9, &(0x7f0000000240)="ea000001", 0x4)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r3, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000040)=[{0x80}, {0x2c}, {0x6, 0x0, 0x0, 0xfffffffe}]})
sysctl$kern(&(0x7f0000000000)={0x1, 0x16}, 0x2, 0x0, 0x0, &(0x7f0000001440), 0x0)
write(r3, &(0x7f0000000000)="76a5dead0f01f8", 0x7)
semop(r2, &(0x7f0000000200)=[{0x3, 0xa, 0x800}, {0x0, 0x4, 0x800}, {0x1, 0x4, 0x1800}, {0x2, 0x8}, {0x0, 0x1, 0x1000}, {0x0, 0x3}], 0x2aaaaaaaaaaaac5c)
sysctl$net_inet_tcp(&(0x7f00000002c0)={0x4, 0x2, 0x6, 0x14}, 0x4, 0x0, 0x0, &(0x7f00000003c0), 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000080)={0xffffffffffffffff, <r5=>0xffffffffffffffff})
openat$pf(0xffffffffffffff9c, &(0x7f0000000100), 0x8000, 0x0)
sysctl$net_inet_ip(&(0x7f0000000180)={0x4, 0x2, 0x0, 0xd}, 0x4, &(0x7f0000000480)="fd769dc3a7bcfbff0700000000000000000000005684894a6a38a5bd99dca821bd532d54080400000000000049990298d0746c1333cc17595957b40e9f03791c5ac212f867e041a876b3664d05b37f02419a00"/105, 0x0, 0x0, 0x0)
getsockopt$sock_int(r5, 0xffff, 0x0, &(0x7f0000000280), &(0x7f0000000300)=0x4)


syz_emit_ethernet(0x46, &(0x7f00000000c0)={@broadcast, @broadcast, [], {@ipv4={0x800, {{0x9, 0x4, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, @local={0xac, 0x14, 0x0}, @local={0xac, 0x14, 0x0}, {[@noop, @rr={0x7, 0xf, 0x9, [@broadcast, @loopback, @multicast1]}]}}, @icmp=@timestamp_reply}}}})


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f00000000c0)="b1000502000000000000000007000000330002000000000000f96ecfc72fd3357ae320b37b673039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa5b236de351e2f0ac3ebbc257699a5f139b672f4d335d223e7d026ba8af630037382102000000720fd38bfbb770c1f5a8727781ea2e69e0bb76d907c400000000361b1257aea8c500002002fbff0c230000aabfba0900000008e371a304353712051eadb71d89e000040781e4b2ffffc00000", 0xb1, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000240)={0x3, &(0x7f0000000000)=[{0x25}, {0x87}, {0x4000006, 0x0, 0x0, 0x3feffe}]})
write(r0, &(0x7f0000000180)="23009100007adb020317bdda2b7e", 0xe)


open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x0, 0x10, r0, 0x0)
r1 = kqueue()
kevent(r1, 0x0, 0x0, 0x0, 0x0, &(0x7f00000002c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x1, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
dup2(r1, r0)


mkdir(&(0x7f0000000440)='./file0/file0/../../file0\x00', 0x190)
rename(&(0x7f0000000100)='./file0/file0\x00', 0x0)
openat$wskbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
fchownat(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
socket$inet6(0x18, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
socket(0x11, 0x3, 0x0)
ioctl$VT_GETACTIVE(0xffffffffffffff9c, 0x40047607, &(0x7f0000000000))
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x2, 0x0, 0x1b}, 0x4, 0x0, 0x0, 0x0, 0x0)


r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x0, r0)
close(r2)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
setreuid(0xee00, 0x0)
r4 = getuid()
setreuid(0xee00, r4)
ioctl$BIOCLOCK(r3, 0x20004276)
fcntl$setown(r2, 0x6, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f00000002c0)=[{0x6c}, {0x80}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000640)=ANY=[])


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
writev(r0, &(0x7f0000000580)=[{&(0x7f00000001c0)='N', 0x1}], 0x1)


r0 = syz_open_pts()
ioctl$TIOCCONS(r0, 0x80047462, &(0x7f0000000000)=0x7)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
r1 = open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
ioctl$TIOCCONS(r1, 0x80047462, &(0x7f0000000180)=0x9)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0xc0206911, &(0x7f00000001c0))


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000b, &(0x7f0000000080)='\x00', 0x1)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000180), 0x0)


sysctl$vm_swapencrypt(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x2, 0x3, 0x3)
bind(r1, &(0x7f0000000000), 0x10)
connect$unix(r1, &(0x7f0000000000), 0x10)
sendto$inet(r1, 0x0, 0x0, 0x0, 0x0, 0x0)
r2 = socket(0x18, 0x1, 0x0)
setsockopt(r2, 0x1000000029, 0x2f, &(0x7f0000000040), 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
r3 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000600), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r3, 0x80105728, &(0x7f0000000680)={&(0x7f0000000640)=[{0xd0, 0x40000006}, {0x47, 0x80}], 0x2})
r4 = syz_open_pts()
fcntl$lock(r4, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000001})
r5 = syz_open_pts()
r6 = socket$inet(0x2, 0x2, 0x0)
socket$inet(0x2, 0x0, 0x0)
dup2(r6, r5)
close(r5)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000140)=[{0x2d}, {0x3}, {0x812e}]})
open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)


ktrace(&(0x7f0000000100)='./file1\x00', 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000200)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
openat$pf(0xffffffffffffff9c, &(0x7f0000000080), 0x10000, 0x0)
open(0x0, 0x0, 0x0)
getpid()
open(0x0, 0x0, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000000)=[{0x1}, {0x45}, {0x16}]})
write(r2, &(0x7f0000000180)="7f23a3c23cce2575e1dd92c25683", 0xe)
recvmsg(0xffffffffffffffff, &(0x7f0000000700)={0x0, 0x0, &(0x7f0000000640)=[{0x0}, {0x0}, {&(0x7f0000000540)=""/239, 0xef}], 0x3, 0x0}, 0x0)
sendmmsg(r0, &(0x7f0000000500)={0x0}, 0x10, 0x0)
recvmsg(r1, &(0x7f0000000680)={0x0, 0x0, &(0x7f00000029c0), 0x1, 0x0, 0x3}, 0x0)
ktrace(0x0, 0x0, 0x0, 0x0)
symlink(0x0, 0x0)
open$dir(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = dup(r0)
ioctl$BIOCSBLEN(r1, 0xc0044266, &(0x7f0000000100))
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
syz_emit_ethernet(0x2a, &(0x7f0000000400)=ANY=[])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000200)={0x0, 0x0})


setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000000)="ebffff132f", 0x5)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x3, 0x0)
connect$unix(r0, &(0x7f0000000000), 0x10)
r1 = dup(r0)
setsockopt$inet_opts(r1, 0x0, 0x15, &(0x7f0000000080)='\x00\x00\x00\x00', 0x4)
write(r0, 0x0, 0x0)


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
mprotect(&(0x7f00003e0000/0x3000)=nil, 0x3000, 0x0)
munmap(&(0x7f00003e2000/0x3000)=nil, 0x3000)


r0 = socket(0x11, 0x4003, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b1000504600000000000000007000000331c13fecea10500fef9ed06c72fd3357ae320b37b673039d2d236073705ae04be38164991f7accf5f882b297be1aad2236deb51e2f0ac3ebbc257699a5f139b672f4d335d223e7d029d6ba8af630037282102000000720f70c1f5a472c881ea6e69e0bb76d907c400000200361b1257aea8c5000020020000000000008abfba09001d89e0000000000000008000ff00000000090000000000000000000000f600", 0xb1, 0x0, 0x0, 0x0)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$VMM_IOC_RESETCPU(r0, 0x82405605, &(0x7f0000000480)={0x2, 0x1})


socket(0x11, 0x3, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x0, &(0x7f0000000140)})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
syz_emit_ethernet(0x3e, 0x0)
ioctl$PCIOCREAD(0xffffffffffffffff, 0xc0107002, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$VNDIOCSET(r1, 0xc0384600, &(0x7f0000000500)={&(0x7f0000000480)='./file0\x00', 0x56, 0x0, 0x3e})
ioctl$VNDIOCSET(r1, 0xc0384600, &(0x7f0000000300)={&(0x7f0000000280)='./file0\x00', 0x7, 0x0})
execve(0x0, 0x0, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000))
syz_open_pts()
sysctl$kern(0x0, 0x0, 0x0, 0x0, &(0x7f0000000180), 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x3, 0x0)
r1 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r1, 0x80085761, &(0x7f0000000080)={0x2, 0x1})
ioctl$FIONREAD(r0, 0xc0206921, &(0x7f00000001c0))
socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x8040691a, &(0x7f00000001c0))
r2 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(0xffffffffffffffff, 0x80206982, 0x0)
r3 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r3, 0xc018696c, &(0x7f00000001c0))
r4 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r4, 0x8020699f, &(0x7f00000001c0))
writev(r2, &(0x7f0000000040)=[{&(0x7f0000000140)="cc60d3d79a1a7122a5fb9de9ea6ca0b30fb2942ef7652736f10f86d45ae419b2ecf7af93d33b3de1f2c56c0d93da7484095d0d543baf7f0161a025c9c02a561f9a76d06f1eaec7d8df99d6c28b10fa891e47d6c3bba690a611889032ac7b3581d7c92d1c546e59764f069048316871794f0615dd4d8bb1057a61fb177be649004fb56a7d46c856a20d73f050bf29d58b803a676cc3761e8a47857f51d90a4465f9c6", 0xa2}, {&(0x7f0000000080)="b30000659336dee4f0a3c1e1e4c3364ba1a4a09fa27a970fe766", 0x1a}, {&(0x7f0000000200)="5ff08de84b4c523a583f9155df135799960704000000babaadcec85d62a9a897a78307f3d2c30eea6356105ec8aaba86930f1aed0b0000000000", 0x3a}, {&(0x7f0000000240)="2a5f4cd9b73c31d629e8d68e605e5940744ef138960b671d42c56f79fcb70549247e5504e02f85a6099eff9291731e94399a7e966e783d4073ecd5dc8e540f32190bb47050aee3907495ecf7708d1c295a0836f79ba03ea13db12836c2441989726ffbf7fd1da55bfe2caaf081a1ef55599935c0e60cb0866ee48d420b77a6e269bc30b2650349e16792252c6be8bcc6e9ce2b941299ab505e4779fa1960bb7cf924dcbc53c82e76bcd80731a694d12e8a139d8ecef6f5560939054b7842d25cd7396377f39bcfe2a2383feea17b87393cd892b90742631718b1877d8d83d5f66587e3e5b1e129433ead750143a4c51aa46e78e3b1a54a4634eea2846511719b1637b19ea8c96a95332abd69014f53e91a7319a36efb4052387dc6330aa00b5680142650e8dab5eb6b83ff7d0bbf1293338a8d3e8a6dcd7ed4916279eac230dda46e6fcdebe8a4c12d598883d9392da05791e153d905ce1930aebfc5dfc0fc22a88777c9fbc24c0b021189c3503466bf850f59e6649dd0b40d935ba155a9d7e065df6d90a500be9d7e1e77607d495898a8d6c9c48dda88533e75e760dceae91d670f97ebbe68b845c72eb698a9e0389b15cfe768cd4e524dbe939bc2d8363ae3b71a454a0a0378cd1f36565ab9d1b92263688195df65151ee9b8158c7a5280019a38f00ea05142b3cc832ece46e326e36a55d7a30f866ca97da61a3877612f0d9f23c052edf60a430d3a9acbae3d9f14f22f38a1eeac7df37ae17748a960b9e0d265bf6cdec73bd2a7b5f25035d845d936936cbfe6f013f8d7c73eba2bd9876ff6db3224e50e75c051979f4cdc41d28ea54e28f560fb0291cd6b6ba527e0f358ffa46b988f0bdbf801063d2024380071709ac00ed463e08fd1718a857b567d8b3eda143915e943d9530d25ed15743e117be375dc08e241328a53fa05b58c7c72a35d471a72706afce82b6c57eef81444269e06338bfd0af6f6ef6479dcc26aab0b10c7e58572aa507a69831d63c78c947cecda2c57bb8ae6b2ad7862d160b423de941be69928467db10ee4817536196ad0c5cc02a74ba1a1fb467e472f025f200846112b6b3efd298284d8c0cc498fb9203db18e48e34c137d1285120d809a774d56a62b3dbe8f202cb9cf18c33099f5b9651fc7ae41de53842f327fd40bcfaa601a791da1103351a64cc9815ff1f32cde6fbfe4c92f55a9aff41c055d4edce9c656ecd1becb9035bb8bd46cf47bca0dcb1848da94d05d1475c83a48c02f8f808597eaa9e88a4e4b12d0ef95458eeab115cb189fa7e368186bb68610af4651e27feab061c4ada46e8c12d6d33fe32cd40485b02120418a9aaba8f04c17ea1abdcb9e6801f5d8090c0780b3b5ae4382efbb64f62c825527b7e3d60ad9c73ba7f174ea7c7f2d155808052a0ef6ab2af85cf9a758a8c1227c85f2986fc06c5f54807968b18b6b5f9168d0b2de2728689d75f0efaedf79bd8bbbbc1d46b0f6072d46d46687bc92c0b16c4ad36c3fe4c7a2fde0cfec859052dd78d841464a6b4432342ea973bf18f1f5abd7b2fe7962faef39ff38bd88a40dbab0f8c08541e38efe924f9ec1addbd47362e349bfca42fd62cf18fef8db7d3cbf0b1733d37dcdae5b9c738b8426a1cfa205c9671870210508c614f256d199fb822613518b1a6fccfee08c48f0feae1ca4baaf0a02635282d4f630a8df115dc73e72d9f7b8feb4333b2c796f1d3f2cfb398ba1e9c81584185b8b578bac3c64d667da7d91062f0c2ccec0c9d09e0c15c62e7bc509c3204d054c22d4eac685626e48e25cff2fc382279d9cb941c2ca182b1f65b05ff05db880a37b1e7f9b3d8975558858352bbbea9213a885b7d43451230e0624403baa77839baa33ae92de771ca76319c2353e9f98ea8191fbb686aed6d08e87bcc2bb8084ae02fafbac1a0bba93f0f155fa2d7bc21bf77f116429c6a1373c34d080518b73481fcf012c0a9127e8f174695ccd4add75b026bf2935990d5cebc4e74b97ae67a414029252336880232635fce7ed7bf0b069e08e10f7e1cc4d2973dcd2ea0b63f9dc4f4c2db92e03c553afcb1060b12f6b9b4d1d799edceefdfafdae63ad797e400645c149b20f8a10af54db3289441499e122413495c7b32179ab6c274bbdf6dde48ce26f46f07ede9a314c1a73669ee8cb0d854c8a3206dcd4f532d36fa7affca1226962e20ca2c6ca0da1ab0848d23d6f198681911592815c080cead9fe6c81cf0d7ce3578978dbf1dc2f1902e51f740f95b02ebff4cf25ac8d28b8e16998f5e329e9a377a82b5bc227f77c2f1ad505286aac8618799c2363a2d07d229519370be62ef0dde6525df45a7b807759b9ba1c8557bdbecb429432c4e1a84094edda567f1245ba887686342d0a31b7dbe09bd2be75516b255d2bfad9337649e86a29b0a19e16b4059c7c45e9f81db6780af6487a11f9088ea265a99d6e95535e14fe839945f8f7da9bf9142dd12c305bd41bb392cae8eb81b28fda176d4b538f4ddaaed47913cd9149d934ca36879718bbd76a2d7ce11e6294398ea433af6cf53b951974ec96a9527178b6cbad3088a2e2dc75113fa88ede462e68b4d6b63020a45e94fbc6c3e6677d6cffee0e3bf606cd2d4b9fac89f91db8f3a1fb9f506708314249fa5c36912e3cb281acbdec3b080735ae24ebb4bca3c7900c21175435afbe5024a706e90f8ecf257c99cd8b67b5a9c2bdc2bb624201f55882349526f8faf463eecb183635db72a6aef5fa2048d97e6f6c513598f49158050df1efc6b13b8ae396cd6a905c26b94d1d50d361f10c0362a8c206c7dd553dd8b116694aa82ac029c64aa71b8a307793da12f93ce030d3c42443c37b91043687befb7968da97ffe91d45e4fd506ba4d9c5d7fe5ac7433fb6bb3ce471f59ade734d109d2093fa119827b65a360f2128e7e85ab494609b60d6e236ed8a72984f6c75652f5baa07e2e921365af2b819eef58343e65ffb45ba8580d62f5b8a9988f7176c1559f8ede3b1b92e0ff27978fc5225ed1512b605f1fd4fce46e768970b11a7b4802c93eb05a8571887cdc15f69929eadcd1f9d08ed2d6aab2997ffa2102c2d8983a78ad43779d03aa612ecbbdde634b14e980b176f04f99efad82a04001f34d6addb89e0ce629856f5ad401fed1a2c046e1fe18741b24d4253830af94a1defeecdf6f70b430e48d7b2e4ae2fb331322d96e1a361e4dcae1d0865e7ccc4aa58bcbb3ad1ce0b294437887e03088a6bb4c92c3044bb33d2a893975023ad979fb2f84d4842326cf058595398779116245c452e54989df0591238af63c5b187d18457f008f2759ae470282ee4640e92639a46915fb67f22967beb1f46736aa9c90df08f39ee481f6859f9eafdecd473bdc24ef3ad71b4c54dde360f2d550db18af7589c8107f29b0a713b65f039da10c2dc55e408ce75c77aba97c116ab078ed1467464fe4041668228316f0fff7c0e0f1a3cc47aae570182197cc3a030a4af7fe2d401b5a13d59b8fe55d48b0667b782cbf1c2e9e491167d87830bb25008aff93c4459a3ce9fd8655a542c6311d91ec6b6bd7935aba1cd01d10439f5e5a3883566c8538edb97c5d2a7c7533d415973729f52dc03134f3d777b7ad07c0f5b0d985ca48fde6cce9ec99f1223f476dcfbb5ef865a3f54459415b25e2031eeb469c83ac68fd77e59c6b6a4b9543a943c4461e47e94d038c63abf2734a3c0e99b95505e13af6cf7b66840dc60e96fb218436ea00b4a577c2effdba43e6adf97cb47c0ce606e87a7834dec04396c1e4f7df59ae5acedfd1d68c87e405fc5d788884686270cb08f0fb15fe8b11589792f9afc11152cd45f43fac6e758588cfaa88874267c3096bd689108bbb0296f3d182df7d46cf7e6b8bb923ba887443c3d2211785e364c1e55d4e9396d950e50cc11ba9a4da70a64f6acbbcd421183eb2c0521054c4f39650409e21a9d3b781725b0c38abce7b4615fa64a9cbf71a19f7e414279a7494d2e66e4e2b2d5ce7027109cfc763a9dcac37065ae80ec0cf3962deec0f9eba3bd7c514a9854ddec6542cf60a1e69cf5d1a73239633675d4ac1f3b0758e69d1d9fb8659f43f07ef6b0b2a7c9740649198b44f3272a8810d374b00c1d49b7f667ed538d89e91e5734f8d6e270aef0a406fcb4072497dd5f25b49d31cfd64f7af2d5b4df72b74c39a66f442ae61aebe1cdb96b660e3248dad3d05bfce3d8630902a565c3a7636220e0435679ce1c45367570dd08722ddfe7f1bf56c44bcab8ef2d0979eeaa569dade4ec34751833d455b31b55edcb9b64f3045725fcd3a08ce0c20b09a437133df5738092eba91430208814b4135b0a64331aff1847ca60426c91e96a029cff039b14462da6e5f9c545980b3712f7fa5f3958d92278194cf6b37ef76e91103d14db403956a7070d87afa81df227f2189926e1265a2872e9d64c64496083caff36dd3c27e961957acb86f0f9a3cbb5ddbb6bf9c62dc102d70d62eea969b1c2c5f42823f76827e918ffa77cc12ca8d31effd0b55529c496da762b6a95d43360ea4e811979ee316e143733f886a6eca5ac76746d4a302ec57b6b4af57c25631d7773243abd400d15274703154dfde2f1a63e075e4b22ed4516dd1496e3f7848bbf19e3215edda64140649d9b1a06975773d5dd0ca9c4bdfd5eb9fb6164aa659e2a8415098dd05496d0b2a20d966a4c9efefa964e007a3b731d3bad501fd21ca564c6155d893c3075c234af6378a12595d8a88ae0518350b75d57fb91b7610bfc3168f548a9a63432b49a9dbee2ee1a4ddd80255e2c655cc80d59d7e90e21fb090db6d59ef84c0becfda6bd01c5a806ce67bea77fdba62ba40e2114d31e6087ad67b28adc20d7cabe7911aa2db119cf5f43b2011bb92556e8e303a264f813764027fbec36f8248a667c766cfc12c80d96965f222d39b5f58a54b255d3b1eb4530952b6d251ff1f9a2cbc585d539704c8ea6884699ebc95d57cd1daef169da86cc10fe7300352e939c35bbe3104aea1b1c681f3e98be8fad7c91bb56724ffa794ea4ac7c4d51d4aad8e94087b4cdcab897e70558e6648ab42dfadab447735912af011fdbd9a47a4958b953b01d2e274449854cb7d4b44d88fb2db162b8dd664c7c32858c7714c69b838cb30b17e6a42ca760256c4c6da57ad5be955ca8c787262d8bd3f4a5f0170e70f92ee2ec9d227d066e41d0d4b640166b2f6937a66bc84506d102d3edac818b246954ba200a3057820da10b64ff99f016b42d90a29b43290d731ef23a72612d646f92acc05620068fd94edd12902197733cc9dbb55d95930ccc749c4a169b4b7056dba24f767da022eb01243353e1f4d0af2eb32e3feb331283ceab3e0112b37556749a701d11ada5cbe1b4c829fac46e12612679e47d4a066be939b886f0fdc2b4c5b4dd183ca025c5191ac67d", 0xf01}], 0x4)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x0, 0x11, r2, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000000)=[{&(0x7f0000001300)}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
socket(0x0, 0x1, 0x0)
socket$inet(0x2, 0x3, 0x2)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VMM_IOC_WRITEREGS(r0, 0x82485608, &(0x7f0000000280)={0x1, 0x0, 0x5, {[], [], [0x3], [0x0, 0x0, 0x0, 0x0, 0x5, 0xf4bfc88], [], {}, {0x0, 0x0, 0x0, 0x9}}})


sendmsg$unix(0xffffffffffffffff, &(0x7f0000001600)={0x0, 0x0, 0x0, 0x0, &(0x7f0000002c40)=ANY=[@ANYBLOB="10"], 0x10}, 0x0)
r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
mkdir(&(0x7f0000000000)='./file2\x00', 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x2, 0x4001, 0x0)
r4 = dup(r3)
r5 = fcntl$dupfd(r4, 0x2, 0xffffffffffffffff)
close(r5)
r6 = socket(0x2, 0x2, 0x0)
connect$unix(r6, &(0x7f0000000000), 0x10)
sendmmsg(r2, &(0x7f0000001600)={0x0}, 0x10, 0x0)


mknod(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000700)=[{0x0, 0x0, 0x0, 0x400}, {0x2c}, {0x6, 0x0, 0x0, 0x100000}]})
write(r0, &(0x7f0000000740)="76e5dead6f01f8607d2100000063", 0xe)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "0100dd2d018000000000005e00"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x3d}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000040), 0x3, 0x0, 0x0, &(0x7f0000000180)="76b0353a558bf248c78c8502fcf9fd08fa1588f254df98bdc2703864ecc0ce3671c0907259201eb7cb962ee12d9706a2d4177565da48e3cdade50516597f477ca5ea18253c1441678346ddaa98e46b28e2226a296c0fd773959eaad9d65d33cdbf523a06ed457ed3e00f52851f90c14f54ec03a2a5ff8d88b9", 0x79)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
writev(r0, &(0x7f0000000080)=[{&(0x7f00000009c0)="cf63fccf005a9d45f0faeb23d96a696f7f77b151fedf96d63ec5e7849472043594136a3c55b6e45944ff6352b1ae2458fd167d6b88735e2026b14a996199855664308a3381a03ae6b87504842cc8b97f7c5478fbadda28cb7d5853e85d0572db4742fc6a38be642f2efd295033b0ca09a5d66ff9400ec29d8b8b62dc1d103c1ab61a18c34afa29011665318709e8160a29bd293b9e9efadef1a44e7a103293bff34d22d491e1b86fe3121401e4e224568214658676e4b8fe6660792497fd669c4c9068e34d5d4fe090ddee32bd9798a5f6b3cac4a9875e80fecdefc78e3d28b1b918da35f29b7f8b8c7b05712212ed0253e877a287de9bd0515d6086324550abb36a4696e175a2cfbec1be567f48a50ce561b4122cff8acce1b20259509a594515", 0x121}], 0x1)


r0 = socket(0x800000018, 0x3, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000000), 0x4)
sendmsg$unix(r0, &(0x7f0000000440)={&(0x7f0000000080)=@file={0x0, './file0/file0\x00'}, 0x10, 0x0, 0x0, &(0x7f0000000400)=[@cred={0x20}], 0x20}, 0x0)


r0 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000140)={0x0, 0x0, 0xfffffffe, 0x0, "100000002300000000000000000000000200"})
writev(r0, &(0x7f0000000180)=[{&(0x7f0000000240)='\b', 0x1}], 0x1)
close(r0)
syz_open_pts()
r1 = syz_open_pts()
readv(r1, &(0x7f0000000600)=[{&(0x7f0000000380)=""/250, 0xfa}], 0x1)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x100000001})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xd, &(0x7f0000000000), 0x0)


r0 = open$dir(&(0x7f00000000c0)='.\x00', 0x0, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f0000000140)=[{{r0}, 0xfffffffffffffffc, 0x21}], 0x9, 0x0, 0x0, 0x0)
setsockopt$sock_linger(0xffffffffffffffff, 0xffff, 0x80, &(0x7f0000000080)={0x2e49}, 0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
mkdir(&(0x7f0000000080)='./file0/file0\x00', 0x0)
rmdir(&(0x7f0000000080)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38/\x00')


sendmsg(0xffffffffffffffff, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x0, 0x0, 0x280}, 0x0)
open(0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, &(0x7f0000000140), 0x0, 0x0, 0x0)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x2b}, 0x4, 0x0, 0x0, &(0x7f0000000140), 0x4)
mknod(&(0x7f00000000c0)='./file0\x00', 0x2000, 0x40000802)
open(&(0x7f0000000100)='./file0\x00', 0x8401, 0x0)
mknod(&(0x7f0000000040)='./file0\x00', 0x2000, 0x6da)
open(0x0, 0x0, 0x0)
munmap(&(0x7f000000e000/0x400000)=nil, 0x400000)
mmap(&(0x7f000002a000/0x1000)=nil, 0x1000, 0x3, 0x10, 0xffffffffffffffff, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000400)={0x0, 0x0, &(0x7f0000000080)=[{&(0x7f0000000180)="cf70770c0d6e80f391bb19656265c41dbf978bc8ef8f9c4c61decb06778c275ed5f70fff9371f1e7789cea6dd7768a2bf2e1a3b9964f606ae9f98c61b38d595303b8f29af43b7903151d6d610da3bb97b52d896feb0a9a1e917c89ec20b854157d7a67e8468615947f9903f6affcc36234407d72d527e7514e53d668cd96c5795a50dbf714313fa18f65de35968e6c1744ebc1a81ee87beb77bef9e84b047377255e3f21a21862b5acf40b49dbbd24ea82380a299266d9f5204d7c3f03c3ff802ae9a2c9f12137d5dff9b82c618267", 0xcf}], 0x1}, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000132000/0x3000)=nil, &(0x7f00000a0000/0x1000)=nil, 0x80400000}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f0000ff3000/0xa000)=nil, &(0x7f00001f0000/0x1000)=nil}, {&(0x7f00001f0000/0x1000)=nil, &(0x7f0000001000/0x1000)=nil}, {&(0x7f0000132000/0x4000)=nil, &(0x7f00000b2000/0x1000)=nil}, {&(0x7f0000083000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {0x0, &(0x7f000002a000/0x3000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000e58000/0x4000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil}, {&(0x7f0000091000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000001000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000132000/0x1000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000008a000/0x1000)=nil}, {0x0, &(0x7f0000092000/0x3000)=nil}], './file0\x00'})
openat$vmm(0xffffffffffffff9c, &(0x7f0000000800), 0x0, 0x0)
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000280), 0x8, 0x0)
mkdirat(0xffffffffffffff9c, &(0x7f0000000100)='./file0\x00', 0x0)
mkdirat(0xffffffffffffff9c, &(0x7f0000000000)='./file0/file0\x00', 0x0)
r1 = open$dir(&(0x7f0000000340)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
renameat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', r1, &(0x7f0000000280)='./file0/file0/file0\x00')
ioctl$VMM_IOC_INFO(r0, 0xc0185603, &(0x7f0000000300)={0x17, 0x0, &(0x7f0000000380)=""/23})
r2 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r2, 0x80085761, &(0x7f00000000c0)={0x3})


writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
kevent(0xffffffffffffffff, &(0x7f0000000040)=[{{}, 0x0, 0x0, 0x0, 0x3}], 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11, 0x0, 0x2}, 0x4000000000000006, 0x0, 0x0, 0x0, 0x0)


syz_emit_ethernet(0x3e, &(0x7f00000000c0)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, @rand_addr, @multicast1}, @icmp=@parameter_prob={0xc, 0x0, 0x0, 0x0, 0x0, 0x0, {0x5, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, @multicast1, @multicast1}}}}}})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f00000001c0)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe1463a52077dc0d00003ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)


open(&(0x7f0000000080)='./file1\x00', 0x80, 0x4)
r0 = socket$unix(0x1, 0x5, 0x0)
r1 = getppid()
fcntl$setown(r0, 0x6, r1)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ktrace(0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
socket(0x2, 0x0, 0x63)
bind$unix(0xffffffffffffffff, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, &(0x7f00000001c0))
kqueue()
kevent(0xffffffffffffffff, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0xc0206921, &(0x7f00000001c0))
r3 = socket(0x20, 0x4000, 0x0)
ioctl$FIONREAD(r3, 0x80206919, &(0x7f00000001c0))
clock_settime(0x100000000000000, &(0x7f0000000000))


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
close(r0)
mmap(&(0x7f0000001000/0x2000)=nil, 0x2000, 0x0, 0x10, r0, 0x0)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000001600)={0x0, 0x0, 0x0, 0x0, &(0x7f0000002c40)=ANY=[@ANYBLOB="10"], 0x10}, 0x0)
r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000000)={0x27ff5, 0x0, 0x0, 0x0, "102609307e7be2df67de208c8bda612c3100"})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x2, 0x4001, 0x0)
r4 = dup(r3)
r5 = fcntl$dupfd(r4, 0x2, 0xffffffffffffffff)
close(r5)
r6 = socket(0x2, 0x2, 0x0)
connect$unix(r6, &(0x7f0000000000), 0x10)
sendmmsg(r2, &(0x7f0000001600)={0x0}, 0x4, 0x0)


r0 = kqueue()
select(0x40, &(0x7f00000002c0)={0x7fffffffffffffff}, 0x0, 0x0, 0x0)
r1 = socket$inet(0x2, 0x3, 0x0)
kevent(r0, &(0x7f0000000080)=[{{r1}, 0xffffffffffffffff, 0x5}, {{r1}, 0xffffffffffffffff, 0x4d, 0x1}], 0x200, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000140)=[{0x80}, {0x25}, {0x496}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x138, &(0x7f00000001c0)=ANY=[])


mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x11bc62ce)
open(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f00000001c0)=[{0x0}], 0x1)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x18, 0x0, 0x0)
mlock(&(0x7f0000ffe000/0x1000)=nil, 0x1000)
getpid()
msgsnd(0x0, 0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
recvmsg(0xffffffffffffffff, 0x0, 0x0)
sendmsg(0xffffffffffffffff, 0x0, 0x0)
r0 = open(&(0x7f0000000080)='./file1\x00', 0x200, 0x20)
mmap(&(0x7f0000011000/0x2000)=nil, 0x2000, 0x0, 0x10, r0, 0x0)
mprotect(&(0x7f000000e000/0x4000)=nil, 0x4000, 0x3)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000100)=[{0x3}, {0x3}, {0x8106}]})
syz_emit_ethernet(0x36, &(0x7f0000000000)={@local, @empty, [], {@ipv4={0x800, {{0x8, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @multicast1, {[@rr={0x7, 0xb, 0x7, [@broadcast, @multicast2]}]}}, @udp={{0x1, 0x3, 0x8}}}}}})
sendmmsg(0xffffffffffffffff, &(0x7f00000007c0)={&(0x7f0000000440)={0x0, 0x0, &(0x7f0000000400)=[{&(0x7f0000000180)="b860fe09625ee6793978a575faa1b6c6c1d6c2eca2950e663d39ab1be31a269a39fd2ad2a38f5803b46d2c516e85da9f00659c2ea9ac56733f7e", 0x3a}], 0x1, 0x0}}, 0x10, 0x0)
socket(0x2, 0x2, 0x0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
writev(r0, &(0x7f0000000240)=[{&(0x7f0000000180)="50a11938744cf948efad1132514e5cefe216eb2e1661d7543de76e0e6b3a53f9e54112dd8949a835ec14ceb13fd89c73faaee614335ccd76c8ba4cb360f4d3aa217facf1610be34bd2e6b4dc231f1862cadac26b44a1992251727d2734a95414b222792d617fd124b89877af70aa82679b2bfbd82d10f2c4ff60d86c", 0x7c}], 0x1)
execve(0x0, 0x0, 0x0)


sysctl$net_inet_tcp(&(0x7f0000000200)={0x4, 0x2, 0x6, 0x19}, 0x4, 0x0, 0x0, &(0x7f00000002c0)="25010000", 0x4)


sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x3}, 0x4, &(0x7f00000002c0)="9be7fdff", &(0x7f0000000300)=0x4, 0x0, 0x0)


pipe2(&(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff}, 0x0)
readv(r1, &(0x7f0000000280)=[{&(0x7f0000000040)=""/124, 0xfd00}], 0x10000000000001bc)
pipe2(&(0x7f0000000200)={<r2=>0xffffffffffffffff}, 0x0)
dup2(r2, r0)


syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
bind(r0, &(0x7f0000000000)=@un=@file={0x0, '\x00'}, 0x3)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
r3 = socket(0x2, 0x1, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)
r4 = dup(r3)
sysctl$net_inet_etherip(&(0x7f0000000140), 0x7, 0x0, &(0x7f0000000240), 0x0, 0x28)
sendto$inet(r4, &(0x7f0000000240)="03c0", 0x2, 0x0, 0x0, 0x0)
write(r3, &(0x7f0000000040)="04", 0xff9a)
setsockopt$sock_int(r2, 0xffff, 0x1023, &(0x7f0000000080), 0x4)


setrlimit(0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
r0 = syz_open_pts()
close(0xffffffffffffffff)
syz_open_pts()
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
write(r0, &(0x7f0000000480)='\b', 0x1)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
sendmsg(0xffffffffffffffff, 0x0, 0x0)
open(0x0, 0x0, 0x0)
r1 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r1, 0x80085761, &(0x7f00000000c0)={0x3})


r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000240), 0x1, 0x0)
ioctl$WSKBDIO_SETDEFAULTBELL(r0, 0x80105705, &(0x7f0000000340))


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r1, 0x802069dc, &(0x7f0000000100))


open(0x0, 0x0, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)
madvise(&(0x7f000061a000/0x1000)=nil, 0x1000, 0x6)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xfffffffffffffffe, 0x0, 0xffffffffffffffff})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockopt(r0, 0x29, 0x2c, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000200)={0x3, &(0x7f0000000100)=[{0x35}, {0x15}, {0x6, 0x0, 0x0, 0x101}]})
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x0, 0x10, r1, 0xfffffffffffff000)
open(&(0x7f00000001c0)='./file0\x00', 0x80, 0x86)
write(r0, &(0x7f0000000080)="2300110000fa4000805a099e20a0", 0xe)


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000280), 0x0, 0x0)
ioctl$VMM_IOC_INFO(r0, 0xc0185603, &(0x7f0000000300)={0x0, 0x0, &(0x7f00000002c0)})
ftruncate(r0, 0x9)
pipe(&(0x7f00000000c0)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
write(r2, &(0x7f00000002c0)="04", 0x1)
write(r1, &(0x7f0000000340), 0xd4e688a67930cd)
write(r2, &(0x7f0000000040), 0xfeea)
r3 = dup2(r1, r2)
write(r3, &(0x7f0000000040)='q', 0x1)
close(r2)
execve(0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000080)={0x1, 0x47}, 0x4000000000000004, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x48}, 0x2, &(0x7f0000000300)="0a36559a4871d5d46cf2e3131df2f3ffc55e9e9ef8905be04b4caf8cffc238a8531f787ddc7ced15ad8d843fac1d9e56bfb23dc53a09bd88a4efeb935e1bccb15f5d8929e0c8a428f393db80a7414f236c19fff68ca09f620b28df7263a43510f7d224ee9b5573b400abd325df01d455f9f33224625cffb1071eb3a8bf01190eb5d11c6727bfb2686af81570fbf6e3c2eed3d76dc8c0181a2bfd1d9ba45410d86a227fb0f84f697178d2bac50f9a52a4e36f3271c95242638713a9179884018eaef1aaadac8e65f158f2a66c295ac74ef3e07fef6893445836920f46e8bf2bfa97a562bb4dc9c49b0045021853a173122bdeee75", &(0x7f0000000240)=0xf4, &(0x7f0000000280)="279dc7211c4dc40fef2c215bf8dd5d507cedb9ec5986", 0x16)
r4 = socket(0x11, 0x3, 0x0)
sendto$unix(r4, &(0x7f0000000000)="b10005010000009f0500070107000000331c13fecea70500fef96ecfc72fd3357ae30200004e30ffd2d236acf20bf404be01000000f7c8cf5f882b290008aa050400ce94e2f0ad3ebec257699a1f139b672f335c22db830c032bfa896443c32118210000720fd38bfb0000fd54c125191b1257aea8c500001602fbfe0c2300008abfd9adf071da68f24a83ba0900000808f37193f8343712cc1100b71dc000090105000000000000001300000000000000", 0xb1, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x0)
openat$vnd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
socket(0x0, 0x0, 0x0)
ioctl$VMM_IOC_READREGS(0xffffffffffffffff, 0xc028756b, 0x0)
mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f0000000040)={0x10, 0x0, [{&(0x7f0000fec000/0x14000)=nil, &(0x7f0000feb000/0x3000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000fee000/0x4000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ff6000/0x3000)=nil}, {&(0x7f0000ff0000/0x4000)=nil, &(0x7f0000fef000/0x3000)=nil}, {&(0x7f0000fec000/0x2000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000d56000/0x4000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000cdc000/0x4000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000feb000/0x1000)=nil, &(0x7f0000ff1000/0x2000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000fef000/0x4000)=nil}, {&(0x7f0000fed000/0x2000)=nil, &(0x7f0000fec000/0x3000)=nil}, {&(0x7f0000ff0000/0x1000)=nil, &(0x7f0000ff1000/0x4000)=nil}, {&(0x7f0000ff4000/0x3000)=nil, &(0x7f0000fef000/0x1000)=nil}, {&(0x7f0000ff6000/0x7000)=nil, &(0x7f0000c00000/0x400000)=nil}, {&(0x7f0000ce2000/0x1000)=nil, &(0x7f0000ded000/0x4000)=nil}, {&(0x7f0000e85000/0x4000)=nil, &(0x7f0000fe0000/0x1000)=nil}, {&(0x7f0000c4d000/0x1000)=nil, &(0x7f0000d14000/0x4000)=nil}], './file0\x00'})
r5 = open(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
ioctl$FIONREAD(r5, 0xc028698d, &(0x7f0000000080))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000240)={0x5, &(0x7f0000000280)=[{0x35, 0x0, 0x2, 0x283d000}, {}, {0x0, 0x2}, {0x7c, 0x0, 0x0, 0x6}, {0xfffe, 0x0, 0x6}]})
writev(r0, &(0x7f0000000500)=[{&(0x7f0000000000)="af18a64591749e07ad1273f580a0", 0xe}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x200, 0x4ebfac6bbaf796d)
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000300)={0x2, &(0x7f00000000c0)=[{0x721}, {0x1}]})
setreuid(0xee00, 0x0)
r2 = getuid()
setreuid(r2, r2)
r3 = semget$private(0x0, 0x2, 0x490)
r4 = getgid()
r5 = getegid()
semctl$IPC_SET(r3, 0x0, 0x1, &(0x7f0000000140)={{0x8000, r2, r4, 0x0, r5, 0x88, 0x8}, 0x8001, 0x1f, 0x3f})
setreuid(0xee00, r2)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x50}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x10, 0x0, 0x37)
r6 = msgget$private(0x0, 0xfffffffffffffffd)
msgsnd(r6, &(0x7f0000000040)=ANY=[@ANYRESHEX, @ANYRESDEC], 0x0, 0x0)
msgrcv(r6, &(0x7f0000000340)={0x0, ""/204}, 0xd4, 0x0, 0x1000)
writev(r1, &(0x7f0000000080)=[{&(0x7f0000000000)='#!', 0x2}, {&(0x7f0000000040)="18", 0x1}], 0x2)
writev(r1, &(0x7f00000002c0)=[{&(0x7f00000014c0)=' ', 0x1}], 0x1)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000140)=[{0x1c, 0xd1}, {0x5c}, {0x40e}]})
syz_emit_ethernet(0x2a, &(0x7f0000000200)=ANY=[])
openat$diskmap(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x881)
r0 = open$dir(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x801)
open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
r1 = syz_open_pts()
dup2(r1, r0)
execve(0x0, 0x0, 0x0)


fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x100000000000000, 0x10000000000001}})
mknod(&(0x7f0000000040)='./file0\x00', 0x2000, 0x3200)
open(0x0, 0x0, 0x0)
close(0xffffffffffffffff)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
r2 = fcntl$getown(r1, 0x3)
setpgid(r2, 0x0)
r3 = socket(0x18, 0x3, 0x3a)
r4 = dup2(r3, r3)
setsockopt(r4, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f00000002c0)=[{0xb1}, {0x60}, {0x812e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1021, 0x0, 0x0)


r0 = socket(0x0, 0x0, 0x0)
getsockopt(r0, 0x0, 0x0, 0x0, 0x0)
r1 = openat$tty(0xffffffffffffff9c, &(0x7f0000000140), 0x20000, 0x0)
ioctl$TIOCSDTR(r1, 0x20007479)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x81}, {0x1}, {0x16}]})
write(r2, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xfef3)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)
r1 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8080691a, &(0x7f0000000100))


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000002c0)={0x3, &(0x7f0000001080)=[{0x30}, {0x1}, {0x6, 0x0, 0x0, 0x2001}]})
write(r0, &(0x7f0000000200)="b1c05b5fb165120a4224a763037a", 0xe)


getpid()
pipe(0x0)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0x2e, 0x0, 0x0)
setsockopt(r0, 0x1000000029, 0x2f, &(0x7f0000000000)="eb929648", 0x4)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x181, 0x200}})
socket(0x10, 0x2, 0x8)
socket(0x18, 0x2, 0x0)
socket(0x18, 0x0, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x0, "12211b6dae6ea993f1bd205a65f45ed76d57b310"})
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x1, &(0x7f0000000040)=[{}]})
madvise(&(0x7f0000000000/0x4000)=nil, 0x0, 0x2)
syz_emit_ethernet(0x4f, &(0x7f0000000400)=ANY=[])
semget$private(0x0, 0x6, 0xacf8a22a973f3654)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000000), 0xc)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={<r1=>0xffffffffffffffff})
syz_extract_tcp_res(0x0, 0x0, 0x0)
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f00000000c0)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000300)=0xc)
setregid(r2, 0x0)
setregid(r2, 0xffffffffffffffff)
r3 = openat$vmm(0xffffffffffffff9c, &(0x7f0000001140), 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r3, 0xc2585601, &(0x7f0000001180)={0xdead4110, 0x0, [{&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffa000/0x2000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffa000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffb000/0x4000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff9000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ff9000/0x4000)=nil}, {&(0x7f0000ff9000/0x1000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffa000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}], '.\x00'})
mmap(&(0x7f0000ffd000/0x1000)=nil, 0xfffffffffffffffc, 0x0, 0x10, 0xffffffffffffffff, 0x3)
socket$inet(0x2, 0x1, 0x0)
setrlimit(0x3, &(0x7f0000000980)={0x8001, 0x200})
ioctl$TIOCSETAF(0xffffffffffffffff, 0x802c7416, &(0x7f0000000000)={0x0, 0x0, 0x0, 0xffffffe1, "23d90e327fc61be44abe7a1c8113e6586d396565"})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x3414, 0x0, 0x37)
read(0xffffffffffffffff, &(0x7f0000000140)=""/223, 0xdf)
mknod(&(0x7f0000000280)='./file0\x00', 0x10, 0x1e5f)


r0 = open$dir(&(0x7f0000000100)='.\x00', 0x0, 0x0)
mknodat(r0, &(0x7f0000000080)='./file0\x00', 0x2000, 0x4000)
open(&(0x7f0000000500)='./file0\x00', 0x0, 0x0)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0xffffffffffffffff}, 0xf0ffffffffffffff})
r0 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x8040691a, &(0x7f00000001c0))


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
syz_emit_ethernet(0x2e, &(0x7f0000000080)=ANY=[@ANYBLOB="d18bbf20950faaaaaaaaaabb8100260008060001080006040000aaaaaaaaaaaa00000000aa500cd578aae0007eed"])
mknod(&(0x7f0000000040)='./file0\x00', 0x2000, 0xe02)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
socket(0x18, 0x2, 0x0)
sysctl$kern(0x0, 0x0, &(0x7f0000000100)="71f91e3471ac00cb5c656358bc5a91501d94", 0x0, 0x0, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f0000000080)=""/51, 0x33}], 0x1000000000000036)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1800000029"], 0x3e}, 0x0)
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)
r3 = socket(0x800000018, 0x3, 0x0)
getsockopt$SO_PEERCRED(r3, 0xffff, 0x1022, &(0x7f0000000140), 0xc)
bind$unix(r3, &(0x7f0000000080)=@abs={0x1f95d27d48731891, 0x7}, 0x8)
r4 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$VNDIOCCLR(r4, 0x80384601, &(0x7f00000000c0)={&(0x7f0000000000)='./file0\x00', 0x3, &(0x7f0000000040)='./file0\x00', 0x8})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x200}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x27}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)
open(&(0x7f0000000200)='./file0\x00', 0x0, 0x82)


open(&(0x7f00000000c0)='./file0\x00', 0x200, 0x0)
r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
pwritev(r0, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
r1 = open$dir(&(0x7f00000002c0)='./file0\x00', 0x2, 0x0)
ftruncate(r1, 0x80002)
r2 = open$dir(&(0x7f0000000180)='./file0\x00', 0x2, 0x0)
pwrite(r2, &(0x7f0000000300)='_', 0x1, 0x8001)
preadv(r2, &(0x7f00000012c0)=[{&(0x7f00000001c0)=""/224, 0xfffffdd5}], 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000240)=[{0x4}, {0x50}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000140)=ANY=[])


r0 = socket(0x2, 0x1, 0x0)
r1 = socket(0x2, 0x2, 0x0)
close(r0)
getsockname$unix(r1, &(0x7f0000000000)=@abs, &(0x7f0000001200)=0x8)
r2 = socket(0x2, 0x3, 0x0)
fcntl$setstatus(r2, 0x4, 0x4c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$inet(r0, &(0x7f0000000000), 0x10)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000080)=[{0x48}, {0x48}, {0xe6}]})
syz_emit_ethernet(0x126, &(0x7f0000000140)=ANY=[])


r0 = kqueue()
kevent(r0, &(0x7f0000000400)=[{{}, 0xfffffffffffffff9, 0x41, 0x3, 0xfffffffffdfffffc}], 0x802, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000580)={0x3, &(0x7f0000000040)=[{0x34, 0x0, 0x0, 0x2}, {0x25}, {0x6}]})
syz_emit_ethernet(0xe, &(0x7f0000000100)=ANY=[])


syz_emit_ethernet(0x3a, &(0x7f0000000140)={@broadcast, @local, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x1, 0x0, @rand_addr, @multicast1, {[@lsrr={0x83, 0x3}]}}, @icmp=@timestamp_reply}}}})


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x1, &(0x7f0000000040)=[{0x0, 0x1}]})
r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$PCIOCREAD(r0, 0xc0107002, &(0x7f0000000040))


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f0000000040)=0xfffffffc)
writev(r0, &(0x7f0000000580)=[{&(0x7f0000000440)="38a218fa614f35646b977002109b49a8389eeb5f5921d33b331e4bf8f32c4bdb9c41098f792ee307796473049e8e8b264e0a", 0x32}, {&(0x7f0000000480)="7d1df3d32c5e32f2621dccb3f04ad746405eff3514a22ad416f895bce1a409d9b4f8b396b013e6eb5310056fdba31058dc666a1191e8ca97fd052d786640a3498d499eeb70330608c15f0f90cee372845d0e6ef2f2bbbb13030cd7", 0x5b}, {&(0x7f00000005c0)="9410b9d9331202fe5fd80cc06d851e11f225cb4f51912cb63edad2", 0x1b}], 0x3)
readv(r1, &(0x7f00000002c0)=[{&(0x7f0000000300)=""/167, 0xa7}], 0x1)


open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x144, r0)
r1 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r1, 0x0)
utimes(0x0, &(0x7f0000000040))


syz_emit_ethernet(0x9c, &(0x7f0000000100)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa86dd604292c800660000fe0aad1f4900000000000000000000aaff0200000000000000000000000000012902000000000000bc"])
syz_emit_ethernet(0x66, &(0x7f0000000100)=ANY=[])
syz_extract_tcp_res$synack(&(0x7f0000000100), 0x1, 0x0)
syz_extract_tcp_res$synack(&(0x7f0000000200), 0x1, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x1, &(0x7f0000000000)=[{0x1, 0xbd, 0x2, 0x2}]})
sysctl$vm_swapencrypt(&(0x7f0000000040)={0x6, 0x1b, 0x1}, 0x3, &(0x7f0000000040), 0x0, 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
getppid()
pipe(&(0x7f0000000000))
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x287e)
open(&(0x7f0000000080)='./file0\x00', 0xed3, 0x0)
rename(&(0x7f0000000140)='./file0\x00', &(0x7f0000000000)='./file1/file0\x00')
open(&(0x7f0000000080)='./file0\x00', 0x8203, 0x0)
syz_open_pts()
syz_open_pts()
r1 = socket(0x18, 0x3, 0x0)
setsockopt(r1, 0x1000000029, 0x0, 0x0, 0x0)
ioctl$WSDISPLAYIO_ADDSCREEN(0xffffffffffffffff, 0x80245753, &(0x7f0000000240)={0x4, './file1\x00', './file1/file0\x00'})
getsockopt(r1, 0x29, 0x2e, 0x0, 0x0)
socket$inet(0x2, 0x2, 0x0)
select(0x40, &(0x7f0000000440)={0xffffffffffffffff, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x8}, 0x0, 0x0, 0x0)
r2 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x2, 0x0)
writev(r2, &(0x7f0000000200)=[{&(0x7f00000000c0)="9385c627db7ab718657a54f5563f3f428e628d6941fe0a43907b7c0f0dddf61e4bae2535ee7d412464fb35d253983decf64ba48e9ef4cace8d7b049a85936214695ebe694b23c244349818f3acd2a7", 0x4f}, {&(0x7f0000000140)="a1182787549b50171e4c6489a005778eeade0770f28ea06d6c386203c6a50a073475e5eb52aa98f40cd92271801445e75b39a8461f96e4674bf1111a310b621f02289d1d64f0139fb3785cf31249f5ba48d84fad0b26394984a7a5146ff1a9712d9355530a1c66178a38cbb0fccf4b923a1332522242331e8604299b2e0478667ecd5a06bc4e6362364d1d85618012e95508b16535169f3e6bddc039f9", 0x9d}, {}], 0x3)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000240)={0x5, &(0x7f0000000280)=[{0x35, 0x0, 0x2, 0x283d000}, {}, {}, {0x1}, {0xfffe}]})
writev(r0, &(0x7f0000000500)=[{&(0x7f0000000000)="af18a64591749e07ad1273f580a0", 0xe}], 0x1)


setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000000)=0x7, 0x4)
mprotect(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x1)
r0 = syz_open_pts()
write(r0, &(0x7f0000000100)='@', 0x1)
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000000))
execve(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000001080)=[{0x80}, {0x7}, {0x6, 0x0, 0x0, 0xfffffff7}]})
write(r0, &(0x7f0000000200)="b1c05b5fb165120a4224a763037a", 0xe)


mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000400), 0x0, 0x0)
preadv(r0, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
munmap(&(0x7f00003a1000/0x1000)=nil, 0x1000)


r0 = syz_open_pts()
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f00000006c0)=0x9)
r1 = syz_open_pts()
ioctl$TIOCSETD(r1, 0x8004741b, &(0x7f0000000100)=0x9)
syz_open_pts()
sysctl$vm_swapencrypt(&(0x7f0000000000)={0x6, 0xb, 0x2}, 0x3, 0x0, 0x0, 0x0, 0x0)


mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x2000, 0x3d1e)
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)


r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0x24, 0x0, 0x0)


setreuid(0x0, 0xee01)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x8080691a, &(0x7f00000001c0))


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd02)
r0 = open(&(0x7f0000000240)='./bus\x00', 0x0, 0x0)
pread(r0, &(0x7f0000000040)="3cd15db7c30016", 0x50cc00, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)


syz_emit_ethernet(0x46, &(0x7f0000000d80)=ANY=[@ANYBLOB="7bca7e58f7cd00000000000086dd609ffffffeae3300fe8000000000000000000000000000bbfe"])


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047466, &(0x7f0000000200)=0x5)
ioctl$TIOCCBRK(r1, 0x2000747a)


syz_emit_ethernet(0xf9, &(0x7f00000003c0)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaaaabb86dd6000000000c3000000000000000000000000000000000000ff0200000000000000000000000000013c01000000000000000100c2"])


r0 = kqueue()
mknodat(0xffffffffffffff9c, &(0x7f0000000100)='./file0\x00', 0x1000, 0x0)
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
dup2(r1, r0)
r2 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
ioctl$DIOCMAP(r2, 0xc0106477, &(0x7f0000000200)={&(0x7f00000002c0)='./file0\x00', r1})
close(r1)
acct(&(0x7f0000000140)='./file0\x00')


syz_emit_ethernet(0x2d, &(0x7f0000000000)={@local, @local, [], {@ipv6}})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x1, 0x0)
connect$inet(r0, &(0x7f0000000000), 0x10)
recvfrom$inet(r0, &(0x7f0000000080)=""/146, 0x92, 0x0, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f0000000040)={0x0, <r1=>0x0}, 0xc)
bind(r0, &(0x7f00000001c0)=@in6={0x18, 0x2, 0x5, 0x4}, 0xc)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000140)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000180)=0xc)
fchown(r0, r1, r2)
shutdown(r0, 0x0)


open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000401})
r1 = open(&(0x7f0000000bc0)='./file0\x00', 0x0, 0x0)
fcntl$lock(r1, 0x9, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x1000100000000})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000140)={0x3, &(0x7f0000000700)=[{0x1c}, {0x48}, {0x6}]})
write(r0, &(0x7f00000002c0)="0000003171f6b2b6a767df38ab0c", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{0x34, 0x0, 0x0, 0xf7d9}, {0x2d}, {0x46}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = socket(0x2, 0x2, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f00000001c0)=[{0x6c}, {}, {0x6, 0x0, 0x0, 0x2}]})
syz_emit_ethernet(0x62, &(0x7f00000000c0)=ANY=[])
open(&(0x7f0000000100)='./file0\x00', 0x615, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, &(0x7f00000000c0)="d43243b79298270335c65ce195cd2511baa9", 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r2=>0xffffffffffffffff})
sendmmsg(r2, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000100), 0x4)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x2e, 0x0)
clock_getres(0x0, 0x0)
open$dir(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000280)={{0xfffffffe, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}, 0x1})
r3 = socket(0x18, 0x3, 0x0)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r3, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
acct(0x0)
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
socket(0x2, 0x3, 0x0)
r4 = socket(0x18, 0x2, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


setreuid(0xee00, 0x0)
r0 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r1 = getuid()
fchown(r0, r1, 0xffffffffffffffff)
r2 = getuid()
setreuid(0xee00, r2)
mkdirat(0xffffffffffffff9c, &(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x180)
renameat(0xffffffffffffff9c, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0xffffffffffffff9c, &(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
faccessat(r0, &(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x6, 0x0)


r0 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
shutdown(r0, 0x0)
listen(r0, 0x0)
r1 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


r0 = socket(0x18, 0x3, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x800, &(0x7f0000000000), 0x3)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd02)
open(&(0x7f0000000240)='./bus\x00', 0x10000, 0x15e)
openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, &(0x7f0000000380), 0x10, 0x0)
ioctl$VMM_IOC_RUN(0xffffffffffffffff, 0xc2485607, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
socket(0x0, 0x1, 0x81)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0xc0206921, &(0x7f00000001c0))
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x80206913, &(0x7f00000001c0))


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)="03000000", 0x4)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000000)="01000000", 0x4)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f0000000080), &(0x7f0000000000)=0xc)
r1 = socket(0x800000018, 0x1, 0x0)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


r0 = socket$inet(0x2, 0x2, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
mknod(&(0x7f0000000040)='./file0\x00', 0x6000, 0xe02)
mknod(0x0, 0x0, 0xffffffde)
socket$inet(0x2, 0x8000, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
r3 = open(&(0x7f0000000140)='./file0\x00', 0x10000, 0x0)
msgrcv(0x0, &(0x7f0000000500), 0x1008, 0x0, 0x800)
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f0000000000)={<r4=>0x0, <r5=>0x0, <r6=>0x0}, 0xc)
r7 = getpid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000003c0)={{0x6, r5, r6, r5, r6, 0x7, 0xfffc}, 0x2, 0x7ff, r7, r4, 0xff, 0x5e, 0x2, 0xffffffffffffff81})
getgroups(0x1, &(0x7f00000004c0)=[r6])
r8 = getgid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x86, 0x0, r8, 0x0, r6}, 0x0, 0x0, r7, 0x0, 0x0, 0x10000, 0x9, 0x401})
fcntl$lock(r3, 0x8, &(0x7f0000000100)={0x3, 0x1, 0x7fff, 0x800, r7})
clock_getres(0x0, &(0x7f0000000040))
clock_getres(0x2, &(0x7f0000000080))
ioctl$BIOCSETWF(r2, 0x80104277, 0x0)
pwritev(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
shutdown(r0, 0x0)
r9 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r9, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r9, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000100)=[{0x44}, {0x20}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])
r10 = socket(0x18, 0x3, 0x0)
setsockopt(r10, 0x1000000029, 0x3c, &(0x7f00000001c0)='\x00\x00\x00\x00', 0x4)
r11 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r11, 0x0, 0x200000000000c, &(0x7f0000000080)="eaef125c00000000", 0x8)


socket(0x2, 0x0, 0x0)
syz_emit_ethernet(0x138, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
close(0xffffffffffffffff)
socket(0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r0 = open(&(0x7f0000000240)='./file0\x00', 0x200, 0xe)
mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0, 0x2015, r0, 0x0)
msync(&(0x7f0000ffa000/0x4000)=nil, 0x4000, 0x6)
bind$unix(0xffffffffffffffff, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
connect$unix(0xffffffffffffffff, &(0x7f0000000000)=@file={0x0, './file0\x00'}, 0xa)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x3a, &(0x7f0000000280)=ANY=[@ANYBLOB="ffffffffffffffffffffffff08004600002c000000000000907800000000e00000014404204e2041fe8ef27d8e", @ANYRES32=0x41424344, @ANYRES32=0x41424344, @ANYBLOB="5000000090780000"])
syz_emit_ethernet(0x0, 0x0)
semop(0x0, &(0x7f0000000580)=[{0x4, 0x8, 0x800}, {0x4, 0x0, 0x800}, {0x1, 0x3f}, {0x1, 0x4}, {0x4, 0x1000, 0x1800}, {0x0, 0x8ef, 0x1000}, {0x2, 0x8, 0x800}, {0x2, 0x1162, 0x400}, {0x0, 0x755, 0x1800}, {0x2, 0x0, 0x800}], 0xa)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlink(&(0x7f0000000ac0)='./file0\x00', &(0x7f0000000e40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000f40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000300)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000200)='./file0\x00')
rename(&(0x7f0000000740)='./file0\x00', &(0x7f0000000780)='./file1\x00')


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x4, &(0x7f0000000340)=[{0x2, 0x0, 0xff, 0x8}, {0x0, 0x0, 0xfc, 0x1}, {0x4, 0x0, 0x0, 0x1000}, {0xffff, 0x0, 0x3, 0x40}]})
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x3, 0x0)
r1 = syz_open_pts()
fcntl$lock(r1, 0x8, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1000300800000})
flock(r1, 0x3)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, 0x0)
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000300)=[{0x3}, {0x4c}, {0x6}]})
openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x5200)
r3 = open(0x0, 0x40, 0x0)
ioctl$WSMUXIO_INJECTEVENT(r3, 0x80185760, &(0x7f0000000140))
ioctl$WSMOUSEIO_SCALIBCOORDS(0xffffffffffffffff, 0x81205724, 0x0)
r4 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
close(r4)
open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
chmod(&(0x7f0000000080)='./file0\x00', 0x40)
fchflags(r4, 0x10000)
writev(r4, 0x0, 0x0)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
r5 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r5, 0x6, 0x10, &(0x7f0000000000)='\x00\x00', 0x2)
setsockopt(0xffffffffffffffff, 0x6, 0x10, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
socket$inet(0x2, 0x1, 0x0)
socket$inet(0x2, 0x3, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x64, 0x0, 0x0)


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000200)={0x0, 0x0, 0x0, 0x3}, 0xc)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x34}, 0x4, &(0x7f0000000140)="3998a035daa227d1ce40394f044ed95480393e74f486aff61a92312cb952b89c09f24ddb00000000008fb1463d8635bf0f8e2f68a22421d45dcf5b7f5bdf7b47", &(0x7f0000000100)=0x40, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000380)=[{0xb1, 0x0, 0xfd}, {0x34, 0x0, 0x0, 0x2}, {0x8006}]})
syz_emit_ethernet(0x56, &(0x7f00000003c0)=ANY=[])


socket$inet(0x2, 0x3, 0x2)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
semctl$SETALL(0x0, 0x0, 0x9, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0x4, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0xfffffffffffffe37)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7949)
writev(r0, &(0x7f00000000c0)=[{&(0x7f0000000080)='#!', 0x2}], 0x1)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x800, 0x0)
kevent(r0, &(0x7f0000000200)=[{{}, 0xfffffffffffffffc, 0x1a, 0xf0000000, 0x7fb, 0x4}, {{r0}, 0xfffffffffffffffa, 0x4, 0x1, 0xffffffffffffffff}, {{r0}, 0xfffffffffffffffd, 0x40, 0xf0000000, 0x3, 0x5000000000}, {{}, 0xfffffffffffffffe, 0x0, 0xfffff, 0x3ff, 0x99c0}], 0x0, &(0x7f0000000280)=[{{}, 0x0, 0x0, 0x2, 0x8, 0x2d5375e0}, {{}, 0x0, 0x41, 0xfffff, 0xfffffffffffffc01, 0x19}, {{}, 0xffffffffffffffff, 0x5a, 0x4, 0x10000000000006, 0x80000001}, {{}, 0xffffffffffffffff, 0x12, 0xfffff, 0x1, 0x80}], 0x80000000, &(0x7f0000000440)={0x0, 0x8})
syz_emit_ethernet(0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
shmctl$SHM_LOCK(0x0, 0x3)
setrlimit(0x0, 0x0)
syz_open_pts()
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ktrace(0x0, 0x0, 0x40000500, 0xffffffffffffffff)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
msgget$private(0x0, 0x20)
openat(0xffffffffffffff9c, &(0x7f0000000440)='./file0\x00', 0x103a42, 0x0)
acct(&(0x7f00000001c0)='./file0\x00')
r1 = socket(0x2, 0x1, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$inet(r1, &(0x7f0000000000), 0x10)
openat$wskbd(0xffffffffffffff9c, &(0x7f0000000180), 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000180)={0x1, &(0x7f00000001c0)=[{0x3c}]})


mknod(&(0x7f0000000180)='./file0\x00', 0x2000, 0x202)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
writev(r0, &(0x7f0000001280)=[{0x0}, {&(0x7f00000001c0)="c5", 0x1}], 0x2)


mkdir(&(0x7f0000000300)='./file1\x00', 0x0)
chroot(&(0x7f0000000240)='./file1\x00')
unveil(&(0x7f0000000040)='.\x00', &(0x7f0000000080)='c\x00')
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000040), &(0x7f0000000100)=0xc)
symlink(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000100)='.\x00')
openat$zero(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x29}, 0x2, &(0x7f0000000340)="bee4a8d74a3529db0bab3cdc6475ce574976a262da130862829d4d395c16c1163c83a31ec0f597f30bc5d9fe5a7f4b62b65d5e0b3004633d7579f8489d9b4379fd2f3097458f0ed09cc633f17dd2318ed9a3a7ecd3f705a500d65525b1d6fcf735177baf6d46ebbe488f2cb2dc1f130594a638076784a32d3e45be46bc45cb8fbac9a5da388bc6caa3b875e12ae94805f0a66b2e630c2b78892a9c3ab149810284d15f5f6eb0673bb8030f8da35d3e025ffee619e8ce9a01a821ff9d05dd6d394dafcc3890e03e9f9ac1d3b467f678940e45468591d0e6144b34e17cbbab7fd3845af5f1519260a529ea84a44d724949cb0621bb9bdfb271123862081887ed0306e51032eb9e186a76c1be920caf17b5e77c023cbc79e39a06eb53f65cd346d985459f68ade88ad9b363cc5daecfc04b3385b32e4d78749480109aa0123a123bddc842a188c734267dc9b76f1adfcf1da926d953c62089f44e4930b931550558377bfc5007f8e467b77bdc4f2b14292daa982b1a303e8bc8704f2f852e194dc60b14a11df16389cec1ce36325b958431eec6d35e4ba1aa4e1ff42ff092c22547644cb6431a8ed91c45ebe0c6f3c3394754965305bbe4f3ed6b8dd08b9d287ec79eca4e1397a2e08d44e46036cd4eac794f73100271e2e6ffa6c62fcefe4b54bd365bd7f06fd3b57ea946259005b6481b9b88c1f27c82d193e2767db83d85c0aa723fc03909aecc6bb2384a19e442c8331c609dd5d15b8450ec3816ba34e68521726183925bba2b9095cf0bce71872302d432208b5e81ae88c514e2cda794940f89791fcb652e0b74bd80d359445bb77303afe46a38ed678b5bdcaddbeaeeb48d0252fe2388effb959f8a26942f00ad4fced9ddd7640f5a660504b43965ed2a66b14db7ec0fc831968e494d89057a7b0424691fd12154a1ff47ba16d4cd9e0f81611e5e19ed5972471453e6acc3c450ffea0c38893a1f33d9f29b10919cf0bb6e5ecf45c14ba6a23b7c9840acabb12e126dd7d2b6973ad01fd2032b1d7c98dd6643f44e488e38ad8ab81ca85ab746504564a28a3bfd9a4b3fa84681d7da87b9cdecfae730a3e4bd8997f20421157c8720a95858a808a4b0758db1d64ff6517c16e2e8992eb60ffb1e12bfec7eb1ac7b9466b8e6156341cf76c5774cc77af15ba75cca24711ebe26d8734ab8303ff0de5f15aa34baab18a01dac1f89ece0315ebd5914e1d0095057de4c196fb98b01a49c09048ebb9d6c8a0280f280836875d932946e428abfeee90ecad162630826385dec657c0464845cb2a728ea5fc318b659cc660ba799567b1ec8fe2931b39dbcb8a73a72243a774dc090440c1702c91d877ae75c3f811f87ea54cfea3ca5c61e65068ae975ffd66f138bac1e6ec6f8783a260ff4c419200991ee093586b300cacc2d175299ea3986cc7ee70d3a1cdd8db5911ae5a4c9d6b6912b880c749b13ce0e633fffa21596d12917677ea249944425ebf76bef4be831f55aeee8a49da2cbcb8af3eb0a109c0ea2e5418eebc90569b1ef3ea956e819c079bdea08517dc30cf62f1ebda0f4ef52094ff002f6b5009b509fd6e43e6978845356f6396d2ea9657a1ef6eab22b8da1441663d4a3a0102316fe8d97e975c8fc20d18cc1f20a8b77ae65b4f9a10c6e77af22ad9f09f79c35c1d60b30e13370f819327b822ebb7b8bba08b1d1449500e2d6fb75da131f682abe0aa55efa14350cec4bb7d93b17af19eb6158bfc04fdc858cef09085029d02ccfb3be76f93d316dfd5cd93523e942fc9ca446e11618bb20514b05dd0325c2822bea8b3040f25c809a1f6493d0fe6ddc78c1c9a41fc4fcb0a92c3c1aa96456812ddda8014b49b7d24ec25714295377a6b2fcbeae032a1b0704f9850b653d7b090ebfd83b7942bd26c6be8e9b45311a4ace537a79a7f0345969bf3ec2e2d83790f8f1174f6085b279eafb531118733d2144a8f87fece31aee11052d4630bfaabf4763b725a0c226acb40302e185501ba489cfe5a3fa2b443fc1971e533ce36633d4788925175f3346eaf9dbdddffad6fc4b6c0bc5dcfad48ea539bc6762601a38e4ceea81db95eddf2ef06a2f6515c40434c39960fb669e388ddfcb3a41b1f0e2ad5aa4e27eaf39ea505e516c1076612d183530c2db7d9ae314264739f93b9f9cc903b0ee7a6d94d9e850743691a0e17b29665cb06ab7401d11df2c7c969a1cf5575f1e09253e4ce705781678c07082bc88b7c71e0021b8ca5dfae0c6db21cbb2cdc1f182c82333adf50d2f0cbf6508473626127126b3c98aa5adcbc8b823bed0dce8391e427ea7c584f2cbb35df5a745f338f1ba64f756db915179f55bacb7630c3c14e7cbd5151048ffeed1e4d28a754a3b4ec2363cd0c892f591edab8abacd94c8793b8b13ebbdfcac9f70d1fff05d62f3352a1907b23c95dbfbd193df95269b22504a2e557e28e59b7329950cc59557dbb89dad683731f591c40ed07538da02c25a83d6c463bf0a19a1bd45cd299e48625345efec27e80dfdfd5a64adac2304246612f64b76b3168fa875f474c759a57ad4f4837b4f6ad45e2a8856f9cba085cfc457c4a0c32c68c8b9679345b30757af1edf5902c4d9d60e8166a2909c5270462dc15c318eb627372f04af1d1e685614a2089b834384f8fbeb323181e73332c2565364823364a909419cc725003792a68c59e33f2e50f2c00d7518b477d4239c3a3c031cc9a49ee866a349d3536960cbeb1712e7dd1909ce0b530f5fdc99352277c804f46397872091d71fc5d588210e41202bc06d557c3b6e8148088fe94e7a4295afcb819c38e8ed1445d101dacf93a13d2d4943902d12e2a3e940cb0df80e01585fd315eb34f872495fec1ac2aae76555ae1a032556286cdda1ab00fd16d1886ba5223311e2e8dadc553aa9f88f0fe9420ccbda1bedd2f70bd60fadac278ffcaf8a705b7e5b3f8d8f9d1afd00631f30c0be63d8510c3302fa1884286162fb929d8e92ed1537277b91dd03beb588a009093ff615a3dc6e70293f4eb9e76b06021d752f5c2cd46d317cd313fc119a8f72c10aa4a04543d585d737e31b5796b0afb2972f2634c90939cde59b70008cebbb3a5ebce7279e7faf41c41585212b524db33b4594d32738dacab917a712bf48939d7bcd7e084553e949fade96b2715a2d849fd286f14748eecc77f04e83214034a78c05a712eeb2de49c0fc340d16e37b6c1242598b8f1be4c77574b6164847d13795309ca8e0c6e61dd419b9af8b2322f1699ad800d1f5983edd920862f04cfca173585fc8eddeba6ebcea60451ae05918988bf3c0b760fc8d179ba40487e02ca918c1a1500f1f4d5d04d6f5ffc2bea206842122e26aaef147c7412270c3b541828ab57afa123582df3f8926c2d9eeb30054b5aa2b3385e4659d07a75e613ffa8599c59a318afef587759eb382e15ee63662ced1080efd3d191debeb7207b59009b45c08fc424a70db5e82eee046b9ac186ced720f5fce835e5ee27ddb35ce5ae9377fca8dce136a0c4ca14bd9d4169bf720af31281287efb16ffb152858feb311c4ce2378b155bd0680efc572205b7d37c356aa46fa5456281c146695d902fb8d53f05b62599a6ef426520dec38c00fd52bf9c823c9719d05e3aaa2dbbecd444eb1d6f0553b4077e1476c7b57dd33e1ac6df4f598b1dbf2ff3fbdc530d9bb1d8761db1b20d39903e5cde3a99c1388398c7d2eacd6488269ad4a1f999fe7281350218746780bd78b93f3c73f39424b21e7a4bdc75ce3ed12d719e881b6d2c331bfcb2fd198fd2a90bb744bb3cfee5eef84f6f443f570188d93a1739f17a1121ea4993a1fdd3b10f7569d454c4d6e9a531e9ba1714024bddc4dde1c37768150c2eb0e82914e7ecff7c2ac18cae8e137ecd01894ab9ffbff8f3e1f49b2e56846d7a69cc0f575fe975f27958a53acd908b04b40ea02ec82ea22a3a1f0ef515edb96dbf4ab7e48c5a9961b3da13591e726b536d3e7c3839b3465270bcd64cd34cc5d8ba3a9010d77b2bb98e4795c1436eb51e42137c7379d290cefd195f09d9811da6eb21506e34b8f24b3fc74cbdc14552830c9ba66aa3cb760795984f9f1e4e4c0cebc1ad68d9c2fa03ec703ce24c30a197debfa88186ea3156925fc2a30863eed94400486b53a9e5bcfc27a2e9c962cdbc94bbeef88f9fab7a756184f3baf1b07084698455315be769269967361d54319a3c6bc1d8a8c2d58bf97c0b51003b01cddd4169c8476a69c1bd705df1164345017a1b9adc4d4623495ca54772c28dcbd8595b3c5369df18605ddd3cb94434e7d39746dc803733bb17c1280fd5a61691165a849e74437f2c681258fd1360b0af303c966badd164808f5fdba7d6a60420fedb69d7591960640b2c856a739e4cfc37d3ad5d2139566632a94f9a2b512eafc15b244b0798c5b308cde960810f915499ec55c5b0038a2b740c76309a4de0fe27b20251dc045abab87cb677031b2f3baebc7843d9fff3a3483e969df8cf10858ca53db4fc358e6845cd5a154086368ea5b88359d37902d9e9b8d87ab0857b4b33da466dfc222fce0858affb562c4e8a78436f36e8ed57f6bc0b202365a89e9943b2b0c35286118c14c87d7faf75c2598c19b9c738072897db60459bbb1d495f41b477251abef641da9e07d24668a1861b47ad8a9364e2b8428787ceb6da762f31774944b04146a914ec25fce6bf5b488ac071a890b021340a49d5d065386cef602855ab538ad0e0bb50dc8a35fa24c122882623c7091264460fb7b3c0f80bc75603e304bd0abf48ef8b5e7a57bbdc3353d00b4313264afffd17dcde766eb8ff13d4944a420aacebdf5e2fcf5f1cb9446b663e4a8b8f4abd3b7553035a4fd0f7f5d95c992b452bbd318fd467d1578", &(0x7f0000000140)=0xd80, &(0x7f0000001340)="b8d474a1bebf361a6611da01748db4651cc50b76fc934af118efaa0a11c630e4ebac87f770da02640888a716b18c984e4be543dfe26f886667b90cf45ebdcc65065783b6fa2e4eb40b016d0f0345610cab4373adc4d5ff907be0e577e80ae8fd9ef03db554c7b9ac6f1b3a484eca3ed49810a49aab7c7a4bf1d22a61a7009d4b34e3d8b26d4a7257771dfb6b73ede04bf86bab1f9024ca2028ca6ae7ccd5efd21d3d43e48d4a294e90bfff867b1339414d590924816d51bd85c8d2a15aae442b035956ede40324370c483ea558124a38618a8cf66035eb5eddf1927341c6926d25a3adb6217f1d96e8aab7fbb48ef6226c10bb81d41495c0f3fe8b37855bb8e36178d89f8c6455933d6d6bd8c9f3b0fcda0f9b9bad0161b0cf0a9fdb71f37791129c0bfd70a330edff31f26778cc22b55a6837d9cbc7629e1f7371c8bcf499fca72ec10149c73665a1b4c09de26263855f259f09e391a2c64888be96265be11c5aad81d33335c6f4d6e38a2b7319d0f0b81fe0316e06c8c11c3b13ee1b7bc475f9aa9ad4f1dfeee07a34d2a754d50baa2943d1923ef19da043f601987fc06d65cadf71916035c2ea54e0adbbfb375408de6567e08fc14a716cc77b6c01ab0d493449d66ef450efb8600f893a8373c49e68d323cb55b68776f616ea84a95c71db8268ef8f8bb94d366ac7c77c950cb012a5adc05765bdced6b1a0fdedad0ee2e6076661047043966a21b5c57fd8ac3c56d09b9921136308489e064480cf28defbca9b1234790e7439ce82bdac3b763cf32313d8230867914ba5858de19ee8a29228be4b988191e42928f31c3087d2c5c049c8c57d59c20762013a82adabc8701c5ad4c65dc819ab09d722893224dbc0fde265247e677d27dfe381ee9cf1a3fdbb9d4017510b706bd04ac451c47ab3ca0f5b3d897c437946559986293164213a1201adfacbc08ca6a9a2b00605dee1cc19a93d8d36675fc53eca3a5795c6e334f3f91c1abca7486db98ca610c9364080a55ad9e482eb6e9ce08b8a71313b20bef98140859015c80efe94f1815d718aa869462d8880b356d97600d4ae945185dfce50e8924da18f0b5e95b1277901e64f3040108be271c1011b32f4571f2e1dd73fb027897e25389b1591ddac9d9219613f855791726a656c512a61f6ff72cee36297d0c9faa326fe79f55d814270940b0ea3e43f20ac1651d727b32aa18c3fb62639226752e2ae5644d06c134ba05bc54b2bf56f745e2aca7b1377fefa269c6cd39aed629421986a2710d5e9676814595824d51ae3186e0f8a43bb8c0db913b0723e1d3ed3447adee80959230b93c8a79a37a0b6dd5d6352ee3260472c60bffd27c62b10c06c2d539b225566caaf97d4ed13da4d89c2700a8af59f952b45fab6794ff5add561d94f16155e32c50646cae83d53d2c382b36851f4958a011edeef7249b7bfe8b576402d56ad90aacba68ebe34b7c9210eec007826111d28240e308379177e7f33617a622abc2fda92f2bb3f13d3f3de35acae912c7b6155fa04f4e3a875e61d2bb89bd619f2de8b0b23e0891057282fb772fcaf1af34a2e50527b127504e8b0644280738dec33024ec89687c2d2447bb6eaf7f44a15ece2747e568fe63e2ae982d26398fdd1233971638f90e672116bfcb3e310ad9eb788500aa68117706d9b74fd97377e5fec14e07fd4fa3a049b97954bdcdf228c07cfd404e4016efefd7ef7096c2a11bb936c0720bde08ceaa9783d940d371c10f1586eac53722e2b2b59fa2e40544e46640fde100a12b6d971f14ea72ee89d3f8f96e74059cb95371e9350285c0b02fa9b69e3eaf898afd6ee26487bb40a68ae43578e009a87da4e7371697ba58d1f36db5469a5b48a5c5d9969eecf4205ec9bed6afa51ec3d80986408a743aa4383aed9d2dfa36d3b1130f69a73052f9babc8872f11ebf23071a2a4cabec3d19160426c4c15a082bc2200e65a71665eb367e40c6120250846ae4b5169b3510089d1f6b27ffbd6bddbe678b1954eee248efaf4d0960755c52660b06db591fa2dd86e2ee0271d5b19496556911ab1c5d5bfeba901785497a50d1da2567d46ec8fad4c35d7a72a994f10f7de725ca9c18480a20fb6b90874f457cdef7fcb10a8bb1e0d0678596cc8057748480e44c70ab98310db541e238f82492ff5acb66b2c903842c14b225f8edb906c4b147cf6a2178e6b4a27fb29e111bfc4c0975a549b16d660cf79f2ee63edae6128d836e173069b2db461204f1f1e047f0a32fa423de558631e61f4b1c5392990535ce6bb0f959fd90eb0f7b1cf15b7f3d119ac10b43285483c7252d69faa26e83ac3b3b6bf3bf7a37e6b915a4523fcd3a17f19bcebc8886f97be9f54db651b1aa22a861662e32c04334cad83f0ba6650cd95dd4de9c53d81d880dcbae8ded67e88e025278da947ccb95d317a986d8e4d4e07f55d323963ac1eac4f41ea1e68df611d0c683ee1dac238184c258029364e21c7f42f0c5a8251c549281d9804dacadf5a7b7ef3b869bcc48ec86413491ce8b5e382425f4137e3fdef359df789bc4dca8c4201480cb2c449901f274390498f6aca0b8562cd284affb62e1ce6c19ea96d39d4ee61d333e65127e79f41d61cd98d81d26421c854e192c340305a31d5ddf1fb80a271268297f3b548350a91ce60afe6ac0f181b989a747793e2a968c58ee1f86127c4be9b348b930152712685755cab2d2f5c4d5b2e7ed2d4360ed080596c0a6de9fff1b5245d01b9f04018e5b47eabd1cac1a566dadd052c50f12bcb96476709e27d847105080891c8ac18507822529fe8f81f0a89380573d1fd54908f34a9785cbbe5a147b87fcc754a31cdb331cbd15d68c7b3d075b81423e35c10ae00b615e3539a5476225c517de3be648b3794ec76abcc27989decab247e5daf7379d09548171e2de0e47643cc4304a65fa347d22e91f558e89cf1bab97654872802c673cd09e36f3801b9bfa3103d8f8e2938497daa7fe0395fab94afa4b91e65e8d149dc1da5d82f36b0e6cfb3a361ca8aa767ad32a96843e21615d7109bfd1a752bdc4f26a687e2c16fa174f4682c86253b4cfd3d9b1f6aad7e8165401f88ad4d928ca035f77a0f909f22f45512508a8c674dabce5755d48651b27f296aa939116567e160607e758ad4b6fb66a81e9db0f378bd1503cdad785ade3072d2018a3cd6095f24f0c388f4ca5fb9f5f928310e4e6564244455380657d4a7db664b6fddb8e1334194cbe61d223b04dd49acdd43dd04ffa9911b2cf6ff16395cb93ced6b5cbc7a1ff398e0f6ce6644920dabfe7a6f2dc7827acb4b8c34b72eebabe4087cb0af10106bb89000e9163ae3aca3a8eff7f57f278c34358229d657a7eb076ee9a5b73d35143ca5c8270fa7f9c1a1d4496b13a91e5588d61f6c4dde5970f02c56cca8b0b9e56eb2d3023d5867592a67e580b03f1d4ff18698f08b8735921299bffa2aaed071827092951dc33b5df9152f1ff7ae6989d90cd3d0d07c262af042860c0abfd151ef4889ce86bc10f8ca581fbd747ffcf8fbf3ed1eb660642c370095121a3d7cb03759417aad5057f8475d36690565ac7f1f415bc9006e8a7552943c7c386555d969b239c04815c0c01bc91aaf83a2d9a86fa9ec49732d30a9e0f3454dc081831a96233488c7c352ac315f400b45b49a2a7dd1e5699f6398229ce0a7f3cbe9ac23c283cb58a9025fb85e15d44e0d18d8c33c2d49140cfa96f35ba35f05da491a7c025791d3a7b9150c763f03d51b62095dacd991734b8d05a9341ba4deb32bc84b356d4c633990e200cf947329fb3aa611ce0aa38ebcb4adee812d2e584eb9228c88f23f57939cc4c4203cd20977d52db1abe11b2645c27c59c2e1e778fc155342b90fbcbaa0842087f47ae9eeba3d683a95d25e9ea596580d133f83fb0d9b2683dabd638e92abc990b35c3ce21058d89b1be5d7c3dfee6fdfa595f0c30a3a5c268fafe17dbd5580da00defc8a2706bcabadef04ec3f727f69f92c2f8191e303581dfa7ea345d9d64f4691e7bd0ad58451c80f7e13b83a9653376d36496a6aa55db2719b4522945cc154ab2f0d57f02e015bc9dba0008569ab283cceb6824fada3a9594f8419e94343d19f81630583da36a8f957a70d037252fae29cbf503b56a23da3a7f8b7dd9bb0a7af8ad2a536a69397c2a10491243cc7094c44233a0ba55ea2cff3bac99f615097712424d8764557c10a1b16af3b87cc3309e18a46adea695673082bce3f841e2d0b4cfa221b6adc18d97c0a98f9f410b34b47929e7323d7ec69d59cf70df08375f8c0333b2aeb170a73aeee15c83ddc2a72576790e0ca5a0bad7af5861a4b69f5d4b5e77273c43533627fb2fae380701d87eb0649f858acf337be8aa94f6a49c219eaa4018ddcff4b0a183503a9060d50dba301fa8686bbaa0a892b640f32deb06dd73bae16eac49f0e3b9cb3ac0aaf5590286772adc997b4958924b5c145847543ec51585bf71d4d95a3c2b24a92243716ec41e4889e7159dd811f6b5fafa4b23aeee274ea65d373230c475b500037904fa256bc52596817631b4b07f1dd9bdcdd9a523c12cfe18bebe400b55f93bcf3f677fe6df3f248af52ddc2d0c547fe0b36dffcec500a9742e8e754b9d3e8b839d2ea0025ea67a04a643cb59b7afac3a4277442cc4585f1e190f79150a4fc72b0a4510fed5db7730949cb428bda8d5e18fd7cce3cbd92753b27d4c0b703740e4adc4db1fdc6b57e45f01c20361a6b75eb0675a543b233ee7f52d66321015d7e894515f83f2711b7bcae98aae0cd39b96a8cbeb359d322a1a081cd681ad3efd873a131e2750b3d7a73808cf8f234870b8e521b4f6e2f587786b881c896342b3fb1a4c57d355cb41417cb38e89c889ad9b51ed4f71669d96780d8f13a5901b3e712e883584c194718440e682fdcb81154e2bf5cfa46ea54b531f3031cd0709c06d7ab931da1e9b6793bdb70fee9f8a3645b745a7c8247299b4206faebc6421741e1a7f52f3743f2473aeae09e3254849068c4a49036cb7dff63ec68ced9d7420310e94baf4e72a328c0d54bc030b1f494e4d4c82a8533b5787d25607a7d12a6c068f987c37b2727e9e94452a3ff3b22a21a97d76fcd67a2ce57c1fbb51a2a2b1fc03299141966891f5754eece711184d3764a7850222b3f1b2a6a9dae731ea9642cc1f34e94232d2e4f1b775483653ce5ad2888a3553a4171dcf33286dc72a5a49279586448c6dc4caf44432b18017eed599c48c60b115b001f2f003c92a295eab5581fcf7e9c2584710904554a8cdf6454e924326f37dee72680ab1bdce66867e50b26cfa71081084aba17b8dd16f51249c4fcec789806030edf9e22487c1cda7a48b63e0521b88379c425654b76e7ca7ccf8969199c16656a47323cef328c15df0b1a60e2903495627e386fbfb7721ee0ab3b87c11d532f14a4d50020c36de88a5bd3351d777b64cb5be7303fc511b2f648f5741386be6ad1d0980b77e8f45b750497fd5a3408ed329377963014eed046357566599f586bb04fe53e736d833577c85966aed99e4865f6ad2988007cc161a88f300c2699695524db2e58f87487c2fbda85690bb88762f91469a148e790ab081f9c167bb45b9e86a8642c767f07326e9488ee1cc817aeb8dae009cc5c0076730c79a2a03ec6063f721e293965520585cb9a3eadb15268b2799d4f64f2f6b9005a94ffff8708c1cc83aeec0956a7b60e4131482dad1ece47c73babe356d2f94f3fcca7df89385b6afe7f66fe5df9b30027d68361b45b74", 0xff8)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000340), 0x2, 0x0)
lseek(0xffffffffffffffff, 0x0, 0x0)
writev(r0, &(0x7f00000001c0)=[{&(0x7f0000000080)="18305d6865", 0x5}], 0x1)
write(r0, &(0x7f0000000400)="370baaddbc8de3e745", 0x9)
execve(0x0, 0x0, 0x0)


r0 = socket(0x2, 0x3, 0x0)
setsockopt(r0, 0xffff72c9, 0x0, 0x0, 0x0)


shmget$private(0x0, 0x4000, 0x0, &(0x7f0000003000/0x4000)=nil)
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x1000, &(0x7f0000000500)={0x100000001})
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000040), 0x100, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x2, &(0x7f0000000180)="71f91e3471ac0058bc5a91501d94a34b8e5f", 0x0, 0x0, 0x0)
ioctl$VMM_IOC_INFO(r0, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})


sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x6}, 0x4, &(0x7f00000006c0), 0x0, 0x0, 0x0)
r0 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r0, 0x0, 0x20, &(0x7f0000000140)="caddf7f2", 0x4)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f00000006c0)={0x0, &(0x7f0000000640)})
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000500)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000300)={0x2, &(0x7f00000002c0)=[{0x0, 0x4, 0x41, 0x3ff}, {0x3366, 0x0, 0x85, 0xa}]})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000700)=[{0x4, 0x0, 0x20, 0x57cb}, {0x30}, {0x6, 0x40, 0x2, 0xfffffffe}]})
write(0xffffffffffffffff, 0x0, 0x0)
r2 = fcntl$dupfd(r1, 0xa, 0xffffffffffffffff)
r3 = socket$unix(0x1, 0x1, 0x0)
ioctl$FIONREAD(r3, 0x80206979, &(0x7f0000000000))
ioctl$BIOCGDIRFILT(r1, 0x4004427c, &(0x7f00000001c0))
r4 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000040), 0x80, 0x0)
r5 = openat$null(0xffffffffffffff9c, &(0x7f0000000140), 0x8000, 0x0)
poll(&(0x7f0000000180)=[{r2, 0x40}, {r4, 0x1}, {r2, 0x1}, {}], 0x4, 0x86)
write(r3, &(0x7f00000003c0)="3077e6edbf450f7eabd90769d9940e199feaa2cef90946b88f3abbdc7f5ab082ffb65659bded969dbb809d082be965c9ade7b37f80034ce92c0606f55bccfe53d46b7146ab112ee62a55a6617368ded70cc2e781eb61653f6c30f170551c3c46d2edf2d207f41b777a71e88cbdea70cda96d58b25b5f7cf6945bb4f7df6b6ea8493db2c5ffb09d883e5d797e5c004783726b0d4a9ea37241c51304ff804551859fcd4b3499fbba", 0xa7)
dup2(r3, r1)
r6 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r6, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000100)={0x0, &(0x7f0000000280)})
writev(0xffffffffffffffff, &(0x7f0000000280), 0x0)
kevent(0xffffffffffffffff, &(0x7f0000001300)=[{{r0}, 0xfffffffffffffff8, 0x80, 0x2, 0x8001, 0xff}, {{}, 0xfffffffffffffff8, 0x14, 0xf0000000, 0x5, 0x36c}, {{r5}, 0xfffffffffffffffb, 0x7, 0x40000000, 0x2, 0x1000}], 0x2, &(0x7f0000001380)=[{{}, 0xfffffffffffffffc, 0x8, 0x40000000, 0x7, 0x2}, {{}, 0xfffffffffffffffa, 0x31, 0x0, 0x10000, 0xfffffffffffffffe}, {{}, 0xfffffffffffffff8, 0x20, 0x8, 0x8, 0x6}, {{}, 0xfffffffffffffffd, 0x0, 0x2, 0x1, 0x584}, {{}, 0x0, 0x3, 0x4deacc94c1d1a19b, 0x7, 0x6}, {{}, 0xfffffffffffffffb, 0x30, 0x20, 0x4, 0x400000000}, {{r2}, 0xfffffffffffffff9, 0x42, 0x0, 0x4, 0x8}], 0x6, &(0x7f0000000100)={0x68, 0x4})
fcntl$dupfd(r6, 0x0, 0xffffffffffffffff)
r7 = syz_open_pts()
close(r7)
msgget$private(0x0, 0x342)


open$dir(&(0x7f0000000000)='./file0\x00', 0x200, 0x0)
r0 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
pwritev(r0, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
r1 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r2 = socket$inet(0x2, 0x3, 0x0)
r3 = open$dir(&(0x7f0000000580)='./file0\x00', 0x40000400001803c1, 0x0)
ftruncate(r3, 0x80002)
recvmsg(r2, &(0x7f0000000500)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000400)=""/220, 0xdc}, 0x0)
readv(r2, &(0x7f0000000d40)=[{&(0x7f0000000180)=""/167, 0xa7}], 0x1)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x5, 0x10, r1, 0x0)
execve(0x0, 0x0, 0x0)
getuid()
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x10, 0x0)
r4 = openat$tty(0xffffffffffffff9c, &(0x7f0000000040), 0x80, 0x0)
ioctl$TIOCSETVERAUTH(r4, 0x8004741c, 0x0)
getgroups(0xffffffffffffff84, 0x0)
r5 = semget$private(0x0, 0x4000000009, 0x82)
semctl$SETALL(r5, 0x0, 0x9, &(0x7f0000000680)=[0x9, 0x6])
getegid()
nanosleep(&(0x7f0000000100)={0x80000000000000df, 0x7}, 0x0)
execve(0x0, 0x0, 0x0)
semop(r5, &(0x7f0000000140)=[{0x4, 0x200, 0x1000}, {0x3, 0x6, 0x1800}, {0x4, 0x201, 0x1000}, {0x3, 0x1000}, {}, {0x3, 0xff72}, {0x1, 0xdb, 0x800}, {0x0, 0x0, 0x800}, {0x3, 0xa, 0x1000}], 0x9)
sendmmsg(0xffffffffffffffff, &(0x7f0000000380)={&(0x7f0000000340)={&(0x7f0000000240)=@un=@abs={0x1, 0x0, 0x1}, 0x8, &(0x7f0000000300)=[{&(0x7f0000000280)="8bbe837bf99b5b8dd9fe51fa744d49734967bc2c4a577f5bc033429a1cec8a0a9510e3e3510ddd4b15926d3257f270545388dbb9b5fa5ab75124f76ef8c0e88c4d9e0016980f68cc13324d", 0x4b}], 0x1, &(0x7f00000012c0)=[{0x28, 0x1, 0xff, "e8ba4131160eafdfb96fb8732d8c44fe47a5"}, {0x40, 0xffff, 0x7, "f9e8e83c94efa734248b16b639e0d7f13abfedc508f37e6f17098ac11c99e186568ef99ab283ff9a9394ac6d0fb7e4"}, {0xd8, 0xffff, 0x3, "1535649750284260b0018eebf9c3241678e3831933ccd492d16b65c440ad62ce5cc1461652154047913d6c71ce5632af54f3aa632525a85376bdbd6b2e6ff446b050b709a2770b9726c2b37fa4a6f4094e81b3e3bf25c0702d95c3b2dbac21702a78f44f8137b13d4fe2b458043acb5feb7f5437018a12391a7c9e8c45aec731ab567707ef113af65240adae2a1aacbb67910802db2ad62fe8c8480ba40816374650d982cd0799b5f05a0d41978496c549a093ca2212e46806962632c3fd3c122f"}, {0x78, 0x1, 0x6da026a3, "ba18e7e709da2710d7beff9aed1accc9b86e825b3cefb6a0a331b95cd53b9802380813bf12c99ec28f55e57d29fdc8e05ce83340d81371e0d6708ac8f8a932a2963cc2aed36702697bbe78b6c0237b7327825a45e2f952af95d958ae85201e6242e1a646"}, {0x50, 0x1, 0x40, "08fc6421679c03525ea32d67bed7ef960743fdccfe9c2fed4db819774fa394d62b073859f65d5163eda502f6fc9ebd0ca0a7962691fbd4b3840f"}, {0x1000, 0xffff, 0x3, "1d565891502cfdf54f0408d72abc69daf2008a6cc7d05091a82277632004ce4e354d33aa32ef1b0be227909221cd5733bdd3dae5e5cb82c840998af5ea19d27b4c7f1d6c9bb92b8d952b84e6c960cd9fe5df0877db1a1722af2789b3c21c189d032cf967278ce9d1f577537bd4e306b76da7eb58ef78e4619a9ce828064af0cd0044e0ad716e0f54359c2a55255b2fd83e71ade14a9d6472e9c11676d79024aaea6756aa9da04a8f6cf90353656242480aeaecd11face2e370a2b9ffe9986f9fe0b5392b9f0cfa3f84aa2b19284e24fbccfbd97283d30bbb93e077b0ac3da8951d26df909e4f47047013c8aa4e0e8a528cc232e335590ac637aa008c6962eeac78a73b1b45c27c441319191bb71bf5deab43feac070eea6924bff84f887b74737c6a0c22938984d0354e1781b2a2b8b20e5b0da4d7c7b3cee68f4901bd99c1a6b5f4851834c780dacc7a65e9e0696d097dd79257861858b8d343f2b5911fd7d58ef619ffc91bc8c54cc9d4441b53251b782e03284ff0d4f476fd8e8bc224bd89857440a148498525f91e32ae72a6debaf0122848b40795421833d83d84c42a76d14d80b4c61e003b95bf26d08ebf772e8511782d689d3a38a938c3bbc1e8be7f38c18a8f03d809b71e08a4f208fc5782697f77c8808489243c4d8a88025b8efd0e3edcb0e30d9b0365c5830eec6eec7cfc208f5a4f16050727ec87f02da9546d4bdf71c7bc8d078fe7550c426d0fa8f162a3acb482d8d916b8485422171b3d5d7baf965c4f3475a941135600928547720fac5759daac01d374ca244288eafbae105fbefb49d9beaf6ca39ceaa853c053a289a80a28070c42c138de8d355cf08b60d569e384840ea7bddc1b1d71fafac9d51962e1cf1aad70e8c42df448e9a25a68acd835186bfbb71c0690af5819587a5d6059256cca11c5be83141dc745222b3a0e7ec402e0952a6d9c19a29d52631056d9c45bcedd41b0621e73e9eda65c7b5a7f79a0ba526f30affdb4979ec89f2b2624197907e73aa3530631aa3df8ca57c6492ce83790d9bec167a2afe43234cd6ebc1f274d478085c57b3c5a9e1119d6e452ca2dfa99a572012b3fec5370f25f5737b090749e707732a155f5daddaf89a69cce4bc17d175dc0e4617c703c160a5955211a305bf0088ab9c3023e3b1b6598ef3cf6a822b172e73d757351133d88704243f354539ff5596c2f054c97ff38fbdda5edcca44c1f5cdb5395a92a3a9bce5f8270f16eed3267b52ba398e66d7634e23cf56b53eae3bfff45df97009cb0b57550affdcb3ae14766084d491abf0d6fe2788dececa5de3f236df587354e9f02cc6505dd5a98696e6052aac17427f20670d98e7797a28d7936638e3d12c2d5a95da7c9908f46e52e3e8876bc5b51259f66c561c38d0c33c286b4a4511bb3bb6aef92e0f0ccd2f2f19aa427730ea8051aef71e5454e831645ec4cca1a163f9fe85d8033cb35d14fabc5e600d411ef2a20e2c7b4697d568e80d6935df2315f19081d654fd04aa154aa4b6d64d7fe39254935050428cc5e55ce0dc7b0702ab71785284a8b0dae2ad95e6e2da31ca5808867e20a00805be3874b65ae9d15f58862dca79228c5a5bb0468b0fd6bb1e687b64a65bcd2a566172f45bdb6be29e0587d228c3c17a26c275faee441ceca93afac1074709989bb7ba685e350b1a0096e619718eca095f92f67161db0a25177c1af756bafe989eb025545897dc3a5bb3efd0c6952a9a925078b52a62bac78df6d2a828293c0358b4663ecbeeee18f14d6ae85f98c322bd552cab7d6a37ce97346edc9e9b494c086f73f8e0b3c4279d71fffdfdf4a3fc387fee534b8d5397177919a1e61fd3a853b66814c5f5d84c9743c154e395ccf9ba321a995b181d056bc89256335069ddfaa0962bb4cfa51960bcca8e2695c524ca85224d10a6866c18a009b6a4f564424b2202b049d5b81140e05d8c018737e9ef1d31528a15b897ac57f2effabf353a5dd027ce9ca2c6da8c8f1e00b6c7fed2d966fa1e809c0f4f94445f16c5f82e43953de0e9c245793e1071b1fef5367c4ed29b1d412b5e89d48a042693f3c05b845e1188b426ab359cc8b128f0ff8dca057771d690b712d16a9133273e0485fbdfc9408c78a9786c2ad148f239fd232908c6f6d8ec9f40c37fc4f224591fd86791ed0b392ee24cc2ab2381349b92eee91ef59ef65a0e0b5fdb6a1c92670b96ec2d66614771b9847124c334c3bf8c62a8dc9cc2094bfd4d619e01b99dc7c149b1f5ca7d7e3304a56d2eb0a77f414f515f76ab19cfbfc60736e603f11e697534fa2a0cfbe97101dd5827c0129e9f8ea82217af602cbf1ea9e3092043925bb88ccdcfcf57f54ecbbff4dbbd9de884c64fac39e4731adc8562e046ce2ed3a161071a7b98cec3daeafb9311fb15cca19b6ea8f93632c3c7dc9c7743961908302f953e820d0b0fc3ac152fe93d0031e10d264cb5e01e6813b3fd6644054425df5cbca82066ea66227c22f57f7029055ff1c5f022924f3b6abcc6550565cc19f97106cbb4b0715f3711aa5ac416ab1b95d7d9e1c724e37cab09ec61da273e788b56917787cf1af35ef1da45bb9f59fd68fc26217e7def1671e4644bff1ba5ecebd8b865f19102f0c52adb6662eb6ca1fd60946c7f4ae728ebad3c63f4632f740ddc98ad67d61f12b0639a2ed457f3ff1c6e29312299eb5f34fe65747f90d9b484af525085ce1774f2b4e6f67a5cf19885f175768801d9f14066e8b550945ff41bd5301da6ea8aaedfac3a8c410398ad0a37263be500cb0bd4816167bbb204cc71a6ffb0f42b38f31dad84bdc833e3a509c7577f2d9f4e6d89e964bccc312ff02c904260aa9617ecf4b68ad7e2d31354dca74b8f71876108f6ce7b7299c3df3fdb48101995608338fda03604757727cb0f3ffd559e4fddc28a85ab8ee4d83d3f1f66335e4fd8bd97a3563f893a9b503f68092096ef09a5bbba61c344e6eec687f1eef7f5fabf0a67cfea409f2d481ddfea1ef1b13ce879ef9015fe5b2b651fc5b1d5c826597a84161b286fe7977597bb16ecc5a792f6dc7910cbc37598e0fa5afaa34a569783e16d18c97f8a37b4649940f7583eed47d75372302684f833fac969cfa37b3105701cf5e5c40775f81391437d24a6b8c0aa3a74e6d31080421202223f315038e0fa3c1db1e99927de50945b29d917606457f801b7809dee0bc63f5d8685274e75849d2949de306a5a19b4b67c4c7c451db0e4626796c1a601b6c4b5d3b1c728404b3bf3f2618d6daf9080db49e1194fd8245b159a27799a8e7f57ea946e7f62a95fa16eafa594bbe51a2e4c35a2f94e6e30c15ba0bc839e7eb12f8c24b1410dd97fd827dd6742c51ff41679b7ef2a9839ea7524964f45f4e9521750e0daa671ae47a1014a70b271c670a5ad8bb79f5b3cf73f10079a3a0ec5fe2311b8545d76adea3b6afb017f04e2de635720c4b8c486aa53518d156ea5dd915061f95d49dff048ac8e5da6896064d5e82a0e2c12c6282e6bba2259b87a957c116ddc1a9c8cd7e36aae0f05b77874313e605b6053fa24303f3a7326592a0192d543bd7a5ee577e94aacf8ae0aeadfa44c30d30d0d291866d4f4020f2ed4ca5e3589f699f366dfcc90809ce3e7c53ebeb0fbec0fa6c7e34c1fcd555a2d3f627c0227cafae53488db31f89a47efbd7e33891f42138c0eb106e98ad35c71c5ebd536ce8e964d9f564b3577d6889f66a1d38dd6d7b432c86ee26696a34ff106944fcf5e99c1848b2b72d8155a9ab4cd1cb451475e4678f64f60c226bcc9559abf05900be0ea076808d4aa855f80c4c55ef5662c325f43571c5994ad3e4ff85ddb7ad0425f16bf77defe6a4da21c32b6c3bd7b6f53ba8a3249dfd8b27cb8c1fe802a97bdf224859d5a3e39941a19e13e025092fe3373ad936940f4267174ae9872cf2bd1baa207e7db9148f8aa0d5e0d9e9ad3cc9bfc6796bcdb5b8ad37da63ed5a90e1be45e3e12a9355ccab8197526e85b91a2bead52b4010a317763bd6429e730e0e03d4c4887b22f69d1a6fe71fb9ff6d72bf0e26b498c70ecf9793825eb73bd811fa47951f1934e20235903c6dbef909bb31b0aeb6b404abdad1ea82ea11d668951989edc7303aad658f820ada097152b094fb3115cbf7688724cd425433c749ef5a5cda91245e0df71dc41853aa4ed41d5beda387598ca304b31d31f43768e819aed735d2cc6e481720471050841e1f4883179bef9524412f08ce8112c08db1e5c4a0a2c3889ead113233f3a887f25d82375817fb294894e412e5418b72c35624b5280fa5b8d94bbff37e0899176d6264ca673769e823ee2c60e18b33b9eef0cdd29e5cc57df5969b9215cee0b04bdd31c380714663114ef8f1470941a9309c96dbd4b2a2a976bb8408d1b25e86b25a13c5081366cb7f159dcf7f018738e653a84a64fc7e332d72dd5a77413058fcfee641cb1927a686832322287e8812a152a924d0e61bb37e0cb4a80f67d6d5fce6275613f56cfcf23683ba31560101ca93cf60434f79a27f16f22ba3c81a376c593e10931dc5a192f7ba2ce4e07711febabd07c0c798eb0de4216c3d149c1170455594f103bcc0f2d8b24b20587995811409e59b5f4ea7c3a596d8b41b52dd06a226ca2b3007ba94c118dec78d9e98e0f31b90d8cf988974f1e9dc1f31967ac9251949aa5d806b52241ea3f204e550c5728756355eb458cfc7c84e230cf76f91a4e6087b4280637b81be671e35b6e359c7bc530bda47e947aa9099905ae966b3607fce16ade937b9b9229b53bb3a8b796f75bde6879020e00ea03ea560da71e6231d6710dd674be9e51f1434da2e8ae9ddbd2b25ac44bafb532ea5ba7aec0ecbbc7d93f9fc272c569683f07f52054ae30be9fb1b9b718ef28f50f2a1510f016f3c52dd86f8e841b04eae85ae018055107d5485a6b337f984952c4b69519e711bb9ec6eb5777b9c97e7b50bef2725737a065ede82b834f76e58683556fa62eae731a90417b02a450f4aca631b094f1a27f5fd83a4bd5566c78bdfddf71b38ec6dfd4f08335f29242c78a5070e1369ff63e2d4f17f7d2aefb3694466b4438904700df59ef225f4d899fed097cf35cd8520776986ab3eca1f108db4f15ac6bca840dbfe156b07038f7d2bbc75da1bcdadbdd716a7ddbb65c28279aca1a4ecd3a8edde39ddf44f6fb40e0d6f81c9d81ac861b4f6bbc4d65b5de1847735e3158b7a671aa13d9c6b105509f34476aefb241caa629751469ca69ee8da9e55a3ddd8b8a5f7d0f20e8167f0a4905fd0f3298af6551786b7d9042b15b38ea825c7de5a7d54f6be209fcd59bd7da7b755c9f16440c3c4debd54d12afaa94c8fc472c6fd2159a15c71d4eeb4272ef1129a8b58fc2c7eb692ec539053a95c02766d2c3541bb73650690a06a5ee85d82b8c4bd6e2d36a72b040fd0cc4a36084de5e21bab25da45b877c5f53c3e1cc766b565bf2dd90a1979f391fe41ccb87e30d784b22213d427474194b7b3f95ee1296c7c7ff95f9c9c5c6cd6e4049177816708dba7719697d2d720c0055e27b7e6a11c9fa58a3d981a75356f3ba9a73e7bd75b928ec148ab6d47bd71fd4539d7dfa0ec956a99f9e541246ead17e4545800998cd5d09862d77c2931aeff2fd460570a76f110dd6951271bb4b6799fa147ff44ce0430ce9a7119727f9795415014fad3a3dd00f569445a1121e4cde4885511ac4c71d0b60030fc4058d7b97cfe80902c3c0f177810e12d439d770d467da7b77fe3b4eb9b5a6b69d194"}, {0x28, 0x1, 0x0, "5cdf48f09399ba864b69e21dbe59d40a401ea0e0a397"}, {0x10, 0x1, 0x2}, {0x30, 0xffff, 0x8001, "c1fa7934cb080c2fd15e0ee8b2f789da631ce60dde1449fd4e02e28bc4c8de99"}], 0x1270}}, 0x10, 0x1)
semctl$GETALL(r5, 0x0, 0x6, &(0x7f00000004c0)=""/195)
getuid()
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000080)=[{0x0, 0x0, 0x1f}, {}, {0x0, 0x10, 0x0, 0xd9}]})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000640)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000080)=ANY=[@ANYBLOB="18000000ffff000001"], 0x18}, 0x0)


sysctl$kern(&(0x7f0000000080)={0x1, 0x37}, 0x4000000000000004, 0x0, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000500)={0x3, &(0x7f00000000c0)=[{0x1}, {0x74}, {0x8106}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


clock_getres(0xbe44501372635004, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000080)=[{0x28}, {0x7}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])


sendmmsg(0xffffffffffffffff, &(0x7f00000007c0)={&(0x7f0000000780)={0x0, 0x0, &(0x7f0000000400)=[{&(0x7f0000000180)="b860fe09625ee6793978a575faa1b6c6c1d6c2eca2950e663d39ab1be31a269a39fd7f97e41e178f37a79f00659c2ea9ac56733f7e4e4973c1e6b33ac91343ea3b3f8c5c7b93d5c20ab4211791fe30", 0x4f}], 0x1, 0x0}}, 0x10, 0x0)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f00000001c0))


poll(0x0, 0x0, 0x0)
close(0xffffffffffffffff)
r0 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSKBDIO_SETENCODING(r0, 0x80045710, &(0x7f00000000c0)=0x1300)
openat$speaker(0xffffffffffffff9c, 0x0, 0x2, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f00000005c0)="b107ea397682e68ba592222e26eb0e783affaa", 0x13, 0xa, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000), 0x2, &(0x7f0000000080)="71f91e3471ac0058bc5a91501d94a34b8e5f84cc42c3fbe6edf28f03055a7b8379c80000ff7f000000000000000000", &(0x7f0000000040)=0x2f, 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
r1 = open$dir(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')
fchdir(r1)
mkdir(&(0x7f0000000080)='./file0/file0\x00', 0x0)


syz_emit_ethernet(0x6a, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
mprotect(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0)
munmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000)
mknod(&(0x7f0000000080)='./file0\x00', 0x2000, 0x82d)
open$dir(&(0x7f0000000040)='./file0\x00', 0x0, 0x10a)
syz_emit_ethernet(0xc2, &(0x7f00000000c0)={@broadcast, @remote, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0xb4, 0x0, 0x0, 0x0, 0x0, 0x0, @empty, @rand_addr=0x3fffffff}, @tcp={{0x0, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}, {"bc5e706206cde009380c483dc9d39e4bef640dd24222973086fe9b1bd2bb2c8f92fc1b6a84a7f53423a4ec5a407da178a25fae17b99a6fbc69f17de1ba245f6cc5891ea6f128a3b8d42a2daa7dd5f443dbaa9fec88bde68f0ad97b4e739c0b7b3c7be4dbd6930a0e80061fdd9ab8d507506d095e5dc3576d8df265523694e2e4b29e3f5fef24475bb9b0c0f5"}}}}}})


socketpair(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
write(r0, &(0x7f0000000140)='W', 0x1)
fcntl$setstatus(r1, 0x4, 0x44)
recvmsg(r1, &(0x7f0000000f40)={0x0, 0x0, &(0x7f0000000e80)=[{&(0x7f0000003780)=""/4121, 0x1019}], 0x1, 0x0}, 0x1042)
close(r0)


r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x28, &(0x7f0000000000)="5ab7", 0x2)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{}, {}, {}, {}, {0x0, 0x0, 0x8}]})
r1 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r2 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
socket(0x11, 0x3, 0x0)
getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x100, 0x0)
ioctl$VNDIOCSET(r2, 0xc0384600, &(0x7f0000000600)={&(0x7f0000000500)='./file\x00', 0x276, &(0x7f0000000540)='./file0/file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x81})
ioctl$VNDIOCSET(0xffffffffffffffff, 0xc0384600, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r4 = openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r5 = getpid()
ktrace(&(0x7f0000000140)='./file0\x00', 0x4, 0x1424, r5)
fcntl$lock(r4, 0x8, &(0x7f0000000640)={0x3, 0x2, 0x8, 0x401, r5})
ioctl$FIOASYNC(0xffffffffffffffff, 0x8004667d, 0x0)
ioctl$VNDIOCCLR(r1, 0x80384601, &(0x7f0000000b80)={0x0, 0x0, 0x0})


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000200)="67fbf8010000000000000000000000000019a11e6d4f36814f6c", 0x1a}, {&(0x7f0000000340)="48b88b53c1fb1e4da4c91604527760545a754d4a5433cf6b8a2dc534c09c67316f8c652ff9a8aa28eaa71e351233c7539981fc948be70e1508404f55bf81ccd275458a9f104690c134322a3a75449a2a8c278ceea820f1ebbfc09bbf57b934f750413d7a45d636278f28b7d848ba163d06243d908373787d30489c6b770ea92e9b506c930c8564940783da71ddb179c8b46a622e", 0x94}], 0x2)
execve(0x0, 0x0, 0x0)


open(&(0x7f0000000280)='./file0\x00', 0x615, 0x0)
r0 = open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000001})
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
fcntl$lock(r1, 0x7, &(0x7f0000000300)={0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff})


fchownat(0xffffffffffffffff, &(0x7f00000001c0)='./file0/file0\x00', 0xffffffffffffffff, 0x0, 0x0)
sendmmsg(0xffffffffffffffff, &(0x7f00000007c0)={&(0x7f0000000780)={0x0, 0x0, &(0x7f0000000540)=[{&(0x7f0000000180)="b860fe09625ee6793978a575fa00000000d6c2eca2950e663d39ab1be31a269a39fd7f97e41e178f37a79f00659c2eb33ac91343ea3b3f8c5c7b93d5c20ab4201791fe30", 0x44}], 0x1, 0x0}}, 0x10, 0x0)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f00000001c0))


sysctl$net_inet_carp(&(0x7f0000000000)={0x4, 0x2, 0x70, 0x3}, 0x4, 0x0, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000580)=[{&(0x7f0000000000)="b886b4e47f", 0x5}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x1, 0x0)
dup(r0)
close(0xffffffffffffffff)
r1 = socket(0x2, 0x1, 0x0)
r2 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
fcntl$dupfd(r2, 0x3, 0xffffffffffffffff)
ioctl$WSKBDIO_GETMAP(0xffffffffffffffff, 0x80047476, 0x0)
socket(0x11, 0x3, 0x0)
sysctl$vfs_ffs(&(0x7f0000000100)={0x4}, 0x3, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
mknod(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
getpid()
clock_getres(0x0, 0x0)
link(0x0, &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlink(&(0x7f0000000180)='./file0\x00', &(0x7f0000000280)='./file0\x00')
connect$unix(r1, &(0x7f0000000000), 0x10)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000140)=[{0x8, 0xa}, {}], 0x2})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000100)=[{0x48}, {0x80}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
socket$inet(0x2, 0x0, 0x0)
r1 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
socket(0x2, 0x3, 0x0)
r2 = socket(0x2, 0x3, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x0, &(0x7f0000000100)=0x20000, 0x4)
r3 = socket$inet(0x2, 0x8003, 0x0)
setsockopt(r3, 0x0, 0x1e, &(0x7f0000000080)="4d082af4", 0x4)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r2, 0x0, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
ioctl$VMM_IOC_RUN(r1, 0x8210560b, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, 0x0})


openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x9, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000001})
flock(r0, 0x2)
r1 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
flock(r1, 0x2)
r2 = open(&(0x7f0000000040)='./file0\x00', 0x205, 0x0)
fcntl$lock(r2, 0x8, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x1000300010008, 0xffffffffffffffff})
r3 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r3, 0x9, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x100000002})


close(0xffffffffffffffff)
r0 = syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x0, "5238f0980ba4b3c8b9129c9e242fd505aac10fe3"})
poll(&(0x7f0000000180)=[{r0, 0x1}], 0x1, 0x0)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000140)={0x0, 0x0, 0x0, 0xb55a, "1a2198b59b58505f40edabfaffffece900"})


r0 = socket(0x1, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0xc020699c, &(0x7f00000001c0))


pipe(&(0x7f0000000100)={<r0=>0xffffffffffffffff})
fcntl$setstatus(r0, 0x4, 0xc0)
getppid()
r1 = open$dir(&(0x7f0000000100)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000140)='./file1\x00', r1, &(0x7f0000000d80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
open$dir(&(0x7f0000000b80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x200, 0x112)
r2 = open$dir(&(0x7f0000000000)='.\x00', 0x0, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x1, 0x0)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r4=>0xffffffffffffffff})
getsockname$unix(r4, &(0x7f0000000280), &(0x7f0000000040)=0x205)
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r5, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x61}, {0x7}, {0x6}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r6=>0xffffffffffffffff})
getsockopt(r6, 0x6, 0x9, &(0x7f0000000500)=""/243, &(0x7f0000000600)=0xf3)
r7 = openat$wsdisplay(0xffffffffffffff9c, 0x0, 0x10, 0x0)
ioctl$WSDISPLAYIO_GETSCREENTYPE(r7, 0xc028575d, &(0x7f00000004c0)={0x5, 0x100000, './file0\x00', 0xe4e0, 0x0, 0x9, 0x401})
recvmsg(r6, &(0x7f0000000100)={0x0, 0x0, &(0x7f0000000080)=[{&(0x7f0000000180)=""/236}], 0x100000000000039d, 0x0, 0x28}, 0x0)
ioctl$BIOCSETWF(r3, 0x80104277, &(0x7f0000000180)={0x4, &(0x7f0000000000)=[{0x1}, {0x35}, {0x7, 0x0, 0x0, 0x104}, {0xffe, 0x7b, 0x2d, 0x95}]})
write(r3, &(0x7f0000000200)="d81ad3d20cf7eb4e9be33bbd1a30", 0xe)
mkdirat(r2, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
rename(&(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000f40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000001140)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000001540)='./file0\x00')
socket$inet(0x2, 0x1, 0x2c)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
syz_open_pts()


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = dup(r0)
ioctl$BIOCSRTIMEOUT(r0, 0x8010426d, &(0x7f0000000000)={0x0, 0x7})
ioctl$BIOCSBLEN(r1, 0xc0044266, &(0x7f0000000100))
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$FIONBIO(r0, 0x8004667e, &(0x7f0000000340)=0x200)
readv(r1, &(0x7f0000000080)=[{&(0x7f0000000180)=""/15, 0xf}, {&(0x7f0000000040)=""/17, 0x11}], 0x2)


fcntl$setstatus(0xffffffffffffffff, 0x4, 0x0)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r0 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000001000/0x3000)=nil)
shmat(r0, &(0x7f0000001000/0x3000)=nil, 0x0)
setrlimit(0x0, 0x0)
socket$inet(0x2, 0x8002, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
dup2(r1, 0xffffffffffffffff)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
mlockall(0x0)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x0)
setsockopt$inet6_MRT6_ADD_MIF(0xffffffffffffffff, 0x29, 0x66, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x138, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$BIOCSETWF(0xffffffffffffff9c, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x2}, {0x9}]})
setreuid(0xee00, 0x0)
getuid()
setreuid(0xee00, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0xff0a, 0x0, 0x37)
socket(0x2, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)


socket(0x2, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206916, &(0x7f00000001c0))
open(0x0, 0x78e, 0x0)
getpid()
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
syz_open_pts()
sendmsg(0xffffffffffffffff, &(0x7f0000000400)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000300)={0x2, &(0x7f00000000c0)=[{}, {0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x50}, 0x3, &(0x7f0000000100)="00e0ae5b7e0d0000bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x50, 0x0, 0x37)
socket(0x2, 0x0, 0x0)
socketpair(0x0, 0x0, 0x0, &(0x7f0000000000))
sysctl$net_inet_udp(&(0x7f0000000240), 0x4, 0x0, 0x0, 0x0, 0x0)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
r0 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
r1 = getpid()
fcntl$setown(r0, 0x6, r1)
r2 = getppid()
fcntl$setown(r0, 0x6, r2)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000140), 0x2, 0x0)
ioctl$SPKRTONE(r0, 0x80085301, &(0x7f0000000ec0)={0x80000000})


sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b10005016000009f0500060003000000331c13fecea10500fef96ecfc72fd3357af302b37b673039d2d236acf20b7804be382249d1f7c8cf5f88882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f4d335c223e7d026ba8af6300372821", 0x62, 0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504", 0x4, 0x0, 0x0, 0x0)
r0 = socket(0x11, 0x3, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
sendto$unix(r0, &(0x7f0000000000)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)


sysctl$ddb(&(0x7f0000000000)={0x9, 0x5}, 0x2, &(0x7f00000000c0), &(0x7f0000000080), &(0x7f00000001c0)='\x00\x00\x00\x00', 0x4)
r0 = socket$inet(0x2, 0x2, 0x0)
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
sysctl$ddb(&(0x7f00000003c0)={0x9, 0x3}, 0x2, &(0x7f0000000480)="1ea51b87e76b9636e491f5f12897b73e9222e0415631f096b4a0d78a3aacf2b0ffdecc7e82cf59645a272f2facf37cd659144af92ad061ba361db44c116d63cf10e560b2b3447c444695f81b9d64e918c52a599506c1edc033f9d38d899ab685db8cbd231a3943535df7b92aa690480c6f6ab0168a0feff032cf271fda651e1516f7fcfc8a1df29a2a9a89532e3302d8de3ba4de18e08573479da87e4334c672b8f73ed243f072f908f5c8c673baf200102747524f51f4d8b431c2333c5546e7337583f011ec7d3c986c79ca3216feaa92e0b25076110ed05d27c8a3b8e864f23f36e08f099d3844e6226a5f1fee99bbb33e34fb69b5", &(0x7f0000000400)=0xf6, &(0x7f0000000580)="47f77056fd38f0fbf51e22d64c9aa6f71bed7d42e06804a2e1760f8d8f61c30b851ca7dfe3dfdadc450703465e6523da59ed606a4ee26dbdf4019d24e259a0e1134d4e28593d7e601662517a630ba4b2fce41080fa50437ce1028c96e653f676516b4324559cdc021fdf5dfe6ea979f0f0e28fc34048fb815f035be9332a97036a1d3ad6177ca43af783ebb354e85da511fda2605cb5da75ee94b8b1c26a8025bc628ae03ec53bafa4ff54d75346795370accfae9cdab6e98e03596436ffda7a68462f2ba4c6bdccf4de1898fd4fadd52ce344ee6cd28030465811b11b514e8f33df6526eacb626cd9fcaadc0c7e10f84b83bfdd5cd8dfcc134ac3cb0c8829b47bfef7d59cdba1e6b74bb14650de99e5322ed3d95e5193686328eec6c62bfeb0a1e843307709ea840d924cafa8bdf47651a2ac9e67abd6ee1668d3a9fdeb1a4914c73315060d17c94ebc8c5391e5bcd9c2d46c7b675e0b36de2c2227b2bb5e8c1b4f11437718f65f03c96e22cccae5eb687902fb62e7bfbd4475104e94224a517b2b8f82743f27c7ffe1d2b44e8d52c7321710b7ad7190ee3322544d6e8a0512f2226b06306c9b3a28a2d834f508ff78405ac773f904ef9544abc0419786404ce0f94686337767730ca93c9cb794f793a40fd7773714316de37eee0889301ed4f50749630483c97d2dd175034c45ecd7e2611368ffc806074bf2dc304f531cb9768fb7855015d01d9f563a36c5157ef27befb9e9d5ad02e938079ca61e05105c196f8419c191c6165975156c025f98777ad4ff41db0aea9cd584a45b7f05e5bc19098b1190a6e1b67e20060beee30d85a933b5ccd1b94b4cc4b772881d1e4404d1322a69b35859015500036fc259b27a799991f2ac7bbbd8d61256fd848fd56a080f59e5da3cc305c448bc6eb3b8fca33fdb95dd64e1fd1cc99d05b50eee6f6514813f69f42cd1a751859db759123c02f602a2655674e87c3db438be88ec7f51e3847e1c10d6070e74a2a92eeb1177312f70bd87cf2ff8c676679370c74f9761b0dfe5eff4dc4e28f1cf3242f0e7d62fd19767a519def9b711e582386ecc6ba83a6d42512d3a77ab069fca2f77c9a78c65463d536006fe5e21f8ba71369f8fe638aa1a5daf9279f6c851a099f5ccdb3c405e5df1eb42c20c6f6a2731bd51eecb57e0fae90d3e76c4988060b1d990fd3140d9e6e7e96f73f40142eb129417988883a00951a8739f039776fec367b7047633a40c88ba46c0bd2a44c7c99bc1095462bdca09fc9600c96a22c1ffbb7906270db5aec091b02bd96e98f2b95ace02116a72f19ceb7caa4bd955f0969acbc8313980fda7c70063b0d373ad5072b79f585107461a7e4dd3ec45abd704896ed8e8cae67fe103d0934c8484f03e503562f25cbef231c6f6f6f8a7491ce1fd1916ca78c196936085ca824b451ca0ccf6f9c8523d9e9812b4192159e91a78416e45ab0302e03b561dd0bc57c7e161b6b7168786abcc71cbc77a0b075e9472052d3333f510225271e0005d75b65929c913a0d0438ac26274b5bfefdde46e7377aa29d12d6a48fab21345c1b674b1b005f54974c0f85f36fcb98d124b3b79b127120a13783c89dffeaa5dd80a331c1dc977131ee5b8bece1a815d193240b0ca293339832961ffa513e632d54d0e7d4105a0361f3098c73f677267a9f974a3e09d6753ab45203fc25536c86f034cde0db5decf9a6464eab1ff2101b8b1d6e270a9253119f1e3faf2953a25aafe9ca95c935fd9e0f823cb5a1dc6d5589440f3a4f74dd9a1cef29c5712c412bf95adfe2ad06c7f2b4cb82b8bbf322c1c07e8fd75b309f8efcbf5a2f40cfa3156d592a8a364c0bf2830811ef0115d2c445f01f5cc722ee845f843329ca0c38df1739bce5bc29c8fe313dbff162ec009f22ca7f94a109f437268ab30db406d6dd1d4601ddc40e252643e6fbc763529bf4b6180a42879ac82aebafe4cbf3dfb18af0a05acaf51b7f943be929a397278a12529aacd11e9a4b4547c43a9aa10dc8dcc845a716e1c18fe9163244b0ce48aabcb55aebf57d103d277f91780b0afda6768ece58738f836f0d74c4e72e736f53a60e6020f45c4b955033f71eda4f7bfde2cfd78a07d31b27a94d6bbedf689950390ccc09c64d69986e696a6e45d0a49a044f086fa4d73f95e4414bf8e88d3bd10ec15854499f5989eb9ac495ff38b22e3008fb539702d52614af7120f2142e0e67602ad9631113ca98a0eaf6222c1a5a9b0c94f404602d5204504ea75f99297bb353a907ccb75d96708a5a96f609bf94255384948c540096895af0643428f5a8ec6baefd85e4a858e55661fab129305e6161242e25ae08f34085a87701787b707200d9f78b1dd84ebef53e0e50c1a72d617dc83d497258a75f8de3fa51d60cfcb6bb1f2cde81845e92cfbac1efd20294c613f075fc44d1b77926f594e7c6a3decb2a46596af4b024a6814d62e719293cd4494031fd8bdd8d83bbbfd3f072655d9116cad43cab16b35a3f6d56101ddbc6b519f4a01a1050cb9b67f5de64bd072f39ab8936798b5c7a5a4645382e3bf9c2d1338f493f978c533031d96fa5e148ddb94d67225e2955f6c532ef104a55b678ae513ab092990ea1da1aeda0980e997fd3ef1bdf43794db77ef37a14187bea55751e339ba4d38f405b3c0d0352e93c8154a3e35befccf39f9338a52fb503dc0b0645863923d1e0aadbed78510bd6fbf494518080f5588c9d52c4c8d2311da15a97abbdbfb3b4e6c68feca53f713cc246502bfd5cde53769fddda40e1ae68bcda0a0cbcecf0ecb6ba9289cb8225327df75aee2e430d971cfc93291bb188b7882ecf7b85014e766444508fbaf0fa0ea33b8f6ef6115097d722c547f64a84fe4b3225d6bde1b5fe2affc99c741e1458b8887c1ff5fa1d3a4d784b3cdff0e952637dadf7f3fcc5fcea59ef1f2d73ab8d8f9fd1415473958b3cdc872740b3bf21ef3b9d80d77f0579410f3420f1be88e3b5ef857a5af10dfc316d1b448923714ca89dbedc5ec0b6731f3208baec5291545ce916dd727d3b0e6d7adb1fc20c3c05176c8a5ff77a6eb4f3184f0469a733d302437b311ef94a379c794bc6d3aa7d16319701395584f112aa90eda16c187b6a8964ae30a37a77015b5740da83ab4930d0e799d4b079b0eef9ffeade4e751aa401a945b8fa42c1a9359c1104747cab5580df688f0c53e1068a5d824ba01d2a0437fa2fa963102f16b513399e9e0bb2a13c04b947ac4f93a94f26a0b942482081fb01fd45039c733a5ccdcf845e63e016ed8eac7c85f23efee1b6af30c1c7b78d213ea7e4516ee1761180db3c72148cd4ba53e91173520f7318b098470b4136148f80426865041a2c2cab3ea18701cc54aa6af97a1a75015ec7dcd50112ede0786bd2394812c84c02ed69784de30a9e9b173e1c9616a214b7619dacb48f77fd84e2d0a9f1824593b4bbb84b2e24a3fcea5bb094a5f1b19258e9769429777bb9068605762d08a90e3eca198457c5749455b00e72e1dc585e0651a6935dedd68475b2259b7d30a036a48e8d389ffe0388e6bf17fecbe22e14b244117989558053a75a2530e90ff1ac7d93ed124b2de13adb5ecfa5dd6916d515ed34ffeece0f3874e78c30a6a47a930a391d00e1aae0b0dd5c051eba21f48929e4ff478b0683965e1e486cdabf83895beb84efbaf25a7f4fbbf0ba3cf59fd555ba7210862d7c13201049c2ef32c3e9d695de088e81904f7156a567004a1b02351be647b2bfab6a84dd168aff6437bf5ed70309b4f20c3053f619da3d34e8c5366cdc88a5b19e882e2af87f7109bc3d5193f8b4fd784ea9ecb08061816087bee4c3efd94cecad97a2c9d12affa6ffadc3c5f4bb1d5ce8c851a434e1c4fdcf1c1d60c2d470ba66c8f14ed6dbe56f0766bb713cc6555a19ebabd24c7582f79f6529cccd91923731e69b2a2a590dc53c55b13b8fe85d33c296854e6b6e867e0114571e819e7e63994bc4300d005957d028206d3e1f838a1740096c8160e11065698cfa23eb5f66b584c27691ce08fcf39dbeb605f3cbf7b1d9273d86c7792ea09a13a97dc08fd82c5eb739eb9a1d5d24b69a68e400ae91d01d4f24c9916f2ec67d28fd36974ad6b2123a8343ea6aacbd555f02eb6aa616afc25803799300e1a33691157643cb7cb9896182adfe2b9c265ed6c74818faba4e6342820409e2c3192f46122c3fc03eae53296d02e8c6857ab3db900291604eb902321dc34b4564b85e6590aaf5cdfb3d612423ed7d049d49c20986e910c77b58f1e02f6b6ce29773ced8491de155dd57aece8c8c3df7c88b5410e217fbc646341c424bbed04acf57954f27dfb95fc8ecd92c9ac498672f7c3fee7092e953f2f7ff0bc2b2eeecb1a5e679d6f09bfd5a1e8cf23ef80ea1915719e80a32c3e952ef9c33ea756db02711b5e1d03f8f495c4b69335c6e6fd77adb1e2df0bbb8ee6102f7ad76efc8f334223aa3df68c2debdca5504db556035e9b1c0b645fe28323b878f7e4f920e1c6f25d74a5e5a667129bd0dd090704442946aff1215f5313625fbf945523cdaf3cb718c0958d7ce3676cd6e738c44f33cb6bcefc5241abac1507e2fa9dec40332e197bfcfc1d7b5510ba94ddf5898b2af8d14072578aa5ff7ca3b91673e0e1ab1ed52703ee60f8ed25603771cd89edc769ec4d562c10e1b599477345f4eee0d9e8f77702800bb54e873dde6e61376be774a6d1b5b43d2ed0648813e7d617c9986364b99a0a1450393bacbe93dd2aea84df4286157a69d55f61735ba6f4eb48af630f680d6b5abc4fb1b398ac66e337322ec8cd2f171b88cb31be2d0a7aebaf4edd88f323cbf9f3a1c87bcd737ba873910d36c42a7e1feec4ce5fdd3c1963c46809b434ecada314d8ee7c04a06100dab0b100ce49d4042166e22f2e44b5757e972e32e7e988fe685096274a32320ec5a2818721bf4fd59765016941c934d1db411f323e5dd0bbb65817362b8a2fdb93ebfe046f6b2bb2c7ddbf0cdf15158eba99452b3b51cabbc65dca153ad14053c29b6e83c393776ff0a3910c945f920e281af8fce1ae78f00ce49f7e7a0916237b493193353002a922b93a1761ff4a96ecc233fa8d2bc0649a0e843a9b5625aee8126d008551089c20c8eecacbc18994f913fc1b2f0aa7597e3334db60446eb7cbc4381951762eeb1621b3f278bd6853e8e328a81dbfac12b0855aff51f6b6c3722146a186db2cf98e32d1486c8a9fa9963eac6b9d629a87dec465b72f012c994ddd7d7a53b58fd9e1aa07e8404247b7dbdd21cd5eeb4ccdf9b62a98c3630a9c73f545e015c7f4448d4e61c6a222a12e9df9e5a4325fb6dc038342a7ba8e7e8ad53add3c3ea2bdb23fda10902e10834fbd5add5c791450d119d97990eae91c19d3e3e0f41d5db11dcf29bc89aa8ff50e03fe5286445820f353571068f4cd24e142f485c6f833f0249c21ec827917f65656a963ad90314d7efe3274cef45689d6c1e594746ce5b5666317b23d500f36075906e8940373b2018a4629263c994a775c620049715c1b880f187ba72054324f91b4bcaf1bd182e3399d5e9161d9f5d33b5c8af95ed1fddbe3140e6de7270e7f5cd586ff3c91ef7d33cadf90dc4ab4892e7581338118cc6fe63f38c15d23ec7449b1ede688be0f4c29935e9f94a6267fea0aa6effc7506d5992b7558a23e4fb9ea507d3803e0c0e7e656ca2f3a1dcb14c0aa2faacfb07ea5a1d1e220e4d3f243f2deef1128ec45d18a2e5615308f105eff6f5aaba54d197237fc09a7d4a05f9ab10216c7dda65b196e66", 0x1000)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000240)=[{0x60, 0x0, 0x4}, {0x50}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000140)=ANY=[])
preadv(r1, &(0x7f0000000080)=[{&(0x7f0000000100)=""/254, 0xfffffc47}, {&(0x7f0000000200)=""/171, 0xab}, {&(0x7f00000002c0)=""/243, 0xe2}], 0x50, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
r3 = socket(0x18, 0x2, 0x0)
getsockname$inet(r3, &(0x7f0000000080), &(0x7f0000000040)=0xc)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r4 = socket(0x18, 0x3, 0x0)
setsockopt(r4, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
r5 = socket(0x18, 0x2, 0x0)
r6 = dup2(r4, r5)
sendmsg$unix(r6, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)
mquery(&(0x7f00003df000/0x3000)=nil, 0x3000, 0x0, 0x0, r0, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x1e, 0x0, 0x0)
sysctl$hw(&(0x7f00000000c0)={0x6, 0x1c}, 0x2, &(0x7f0000000240)="c5", &(0x7f0000000280)=0x1, &(0x7f00000002c0), 0x0)
r7 = socket$inet6(0x18, 0x2, 0x0)
ioctl$VMM_IOC_READREGS(r7, 0xc050756a, &(0x7f0000000000))


open(&(0x7f0000000040)='./file0\x00', 0xfffe, 0x0)
setreuid(0xee00, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f00000000c0)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000000)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000080)=0xc)
chown(&(0x7f0000000200)='./file0\x00', 0x0, r1)
chmod(&(0x7f00000000c0)='./file0\x00', 0x21e)
r2 = getuid()
setreuid(0xee00, r2)
unveil(&(0x7f00000001c0)='./file0\x00', &(0x7f0000000200)='x\x00')


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x3, &(0x7f0000000340)=[{0x7}, {0x35}, {0x9106}]})
syz_emit_ethernet(0x4e, &(0x7f0000000100)=ANY=[])


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {}, {0x0, 0x0, 0x0, 0x7fff}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setitimer(0x0, &(0x7f00000000c0), 0x0)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
lseek(r0, 0x8000000000000001, 0x2)


mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x205b1a)
r0 = open(&(0x7f0000000080)='./bus\x00', 0x2, 0x0)
pwritev(r0, &(0x7f0000001840)=[{0x0, 0x5b}, {0x0}, {0x0}, {0x0}, {0x0}, {0x0}, {0x0}, {0x0}, {0x0}], 0x9, 0x0)
sysctl$kern(&(0x7f0000000300)={0x1, 0x16}, 0x2, &(0x7f0000000340)="0e", &(0x7f0000000400)=0x1, &(0x7f0000000800)="d862b587c93d3b1171a1aab1523ba0b5301631bf86b46055af1b8dda71562f1f5be7cf27961abd489a218879145d86b43beced79cbe41a743953a3f2d9ae09862f0bbd77ad13b0f5e7823a30d479cded3305078d3a7bf5951a0d1e895f049fb4e1d98884895e255f39d84e52348a39052b6a802ae7d06648ccec42bcd32af277442864fcf3074576ee4d89ad4b9d0537427878e0c36d454478d072ea3f1fa5d37b9cfc73c6ea12d5861f6ab0c98277229337e2d938205cd0594f2de000c182f8849cf2f771ed4c2def168a8551aae080e5404bce4ac810da609eedd8a0deb10d0fefb67af3d2259cd87481275c9d11f2d7f104f41774bcf4bdfef3e35e8a6488", 0x100)
poll(0x0, 0x0, 0x0)
setitimer(0x2, &(0x7f0000000000)={{}, {0xffffffff}}, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x100000000205f, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x0, 0x0)
seteuid(0x0)
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r2 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r2, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x4, 0x100000001})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000140)={0x6, &(0x7f0000000040)=[{0x4, 0x81, 0x9, 0x1ff}, {0x20, 0x6, 0x2, 0x401}, {0x0, 0x1, 0x40, 0x5}, {0x0, 0x9, 0x1, 0xfffffffe}, {0x9, 0x8, 0x40, 0xfffffffb}, {0x101}]})
r3 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
fcntl$lock(r3, 0x8, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x1000300010008})
open(0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$wskbd(0xffffffffffffff9c, &(0x7f0000000180), 0x80, 0x0)
r4 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
setsockopt$inet_opts(r4, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0x8)


r0 = socket(0x18, 0x1, 0x0)
openat$klog(0xffffffffffffff9c, &(0x7f0000001400), 0x0, 0x0)
shutdown(r0, 0x0)
recvmmsg(r0, &(0x7f0000001380)={0x0}, 0x10, 0x0, 0x0)
recvmmsg(r0, &(0x7f0000000700)={0x0}, 0x10, 0x0, 0x0)


sysctl$net_inet_carp(&(0x7f0000000000), 0x4, &(0x7f0000000080), 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
r1 = socket(0x18, 0x2, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmsg(r1, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000440)=[{0x10}], 0x10}, 0x0)


ioctl$TIOCSETA(0xffffffffffffff9c, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x3, 0x0, "01000000d000"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x2, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$kern(&(0x7f0000000040), 0x3, 0x0, 0x0, &(0x7f0000000080)="4f1d4c6344b80ed788b6a4515248df3aa745bb992c574ab4cdf5587145812eab4a988f7fafd7a01d99776d988908cd186b51f34f8c15ffa0c685ad4116c783959eff4278384b4000384dbb1c2aaeff10b4135529a1da6fda67c67469d954be811b25ec5521559154c586eefff122009f659cd3e27e98a3241495005f102d9101d158284c0ee3250aa7c11042330de22a299ab00894fdc9bac6042d", 0x4)


r0 = socket(0x11, 0x3, 0x0)
setsockopt(r0, 0x11, 0x3, &(0x7f0000000340)="02000000", 0x4)
setsockopt(r0, 0x11, 0x0, &(0x7f0000000200)="12000001", 0x4)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(r1, 0xc0206921, &(0x7f00000001c0))
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x2, 0x0)
r2 = socket(0x2, 0x2, 0x0)
r3 = socket$inet(0x2, 0x3, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x1, &(0x7f0000000240), 0x0)
r4 = socket$inet(0x2, 0x3, 0x0)
dup2(r4, r3)
ioctl$FIONREAD(r2, 0xc0206923, &(0x7f00000001c0))
r5 = fcntl$dupfd(0xffffffffffffffff, 0x3, 0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$FIONREAD(r5, 0x8004745d, &(0x7f0000000200))
r6 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r6, 0x8020690c, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x800, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000240)=[{0x14}, {0x1c}, {0x6}]})
syz_emit_ethernet(0x103e, &(0x7f0000001980)=ANY=[])


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x80, 0x0)
ioctl$VMM_IOC_RUN(r0, 0xc2485607, &(0x7f0000000300)={0x2, 0x0, 0x2, 0x0, 0x0})


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
pwritev(r0, &(0x7f0000000a00)=[{&(0x7f0000000340)="5e230486512e875ecc26bf64fbe1e392a29b06ac33a57d0e8f08cc2bd645c45360091188f05eb1e723487d6623", 0x2d}], 0x1, 0x0)
fcntl$dupfd(0xffffffffffffffff, 0x0, 0xffffffffffffffff)
execve(0x0, 0x0, 0x0)


ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ff3000/0x2000)=nil}, {&(0x7f0000538000/0x2000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f00001f5000/0x4000)=nil, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ff3000/0xa000)=nil}, {&(0x7f0000ff2000/0x3000)=nil, &(0x7f0000ff9000/0x3000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f0000ffa000/0x4000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f00001f4000/0x2000)=nil}, {&(0x7f0000002000/0x1000)=nil, &(0x7f0000ff9000/0x6000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f000009f000/0x4000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000084000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f000061a000/0x3000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
mknod(&(0x7f0000000000)='./bus\x00', 0x3a0914c44f7b202d, 0x0)
r0 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x0, "247497496ed3ffa429fdb9102575e414229eb682"})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r1 = socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = kqueue()
kevent(r2, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r3 = socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0xa, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
setsockopt(r3, 0x1000000000029, 0xa, &(0x7f0000000040)="000001ad", 0x4)
r4 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r4, 0x8020697f, &(0x7f00000001c0))
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000240))
mknod(&(0x7f0000000180)='./file0\x00', 0x1000, 0x0)
r5 = open(&(0x7f0000000040)='./file0\x00', 0x1, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x2f2, 0x0)
poll(&(0x7f0000000080)=[{r5, 0x7d}], 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{0x7}, {0xc0}, {0x2006}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x1, &(0x7f00000000c0)=[{}]})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x80, 0x200}, 0x0, 0x7f})
r1 = socket(0x18, 0x3, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000540)={<r2=>0xffffffffffffffff})
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000100)={0x0, 0x0, <r3=>0x0}, &(0x7f0000000180)=0xc)
chown(&(0x7f0000000080)='./file0\x00', 0x0, r3)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r4=>0xffffffffffffffff, <r5=>0xffffffffffffffff})
r6 = getpgrp()
fcntl$setown(r5, 0x6, r6)
getsockopt$sock_cred(r5, 0xffff, 0x1022, &(0x7f0000000200), &(0x7f0000000240)=0xc)
dup2(r4, r5)
setreuid(0x0, 0x0)
chdir(&(0x7f0000000100)='./file0\x00')
unveil(&(0x7f0000000140)='./file0\x00', &(0x7f00000001c0)='c\x00')
getsockname$inet(r1, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
r7 = socket(0x18, 0x2, 0x0)
r8 = socket(0x18, 0x2, 0x0)
connect$unix(r7, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
dup2(r7, r8)
sendmsg(r8, &(0x7f0000000e00)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
mmap(&(0x7f0000ff8000/0x6000)=nil, 0x6000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
open$dir(&(0x7f0000000b80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x200, 0x0)
r0 = open$dir(&(0x7f0000000280)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000300)='./file0\x00', r0, &(0x7f0000000c80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f0000000dc0)='./file0\x00', r0, &(0x7f0000000ec0)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f00000000c0)='./file0\x00', r0, &(0x7f00000001c0)='./file0\x00')
open$dir(&(0x7f0000000040)='./file1\x00', 0x200, 0x0)
lstat(&(0x7f0000000140)='./file1\x00', &(0x7f0000000200))
mkdirat(r0, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
symlinkat(&(0x7f0000000040)='./file0\x00', r0, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000980)='./file1\x00', &(0x7f0000000100)='./file0\x00')


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047469, &(0x7f0000000040)=0xfffffbfc)
open(&(0x7f0000000200)='./file1\x00', 0x8000, 0x0)
setuid(0xee01)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x8020699b, &(0x7f00000001c0))
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000100)={0xee, 0x8001, 0x6, 0xffff, "7901cc1f0c8ab9bd89cc7184e54c5ec88b836daa", 0x2, 0x20})
r2 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r2)
recvmmsg(0xffffffffffffffff, &(0x7f0000000080)={&(0x7f0000000240)={&(0x7f0000000780)=@un=@file={0x0, ""/525}, 0x21b, 0x0, 0x0, 0x0, 0xbb9c2d4915ca7f35}, 0x10001}, 0x10, 0x807, 0x0)
socketpair$unix(0x1, 0x1, 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
fcntl$setown(0xffffffffffffffff, 0x6, 0x0)
write(0xffffffffffffffff, &(0x7f00000002c0)="7c84cf179279b50eda5dd1951a661d2e3a20851082c188f8b3d8a063d2025ff0d27a44bc29bdcac27fcb7aaa95cb2007be22c5553cd2f66a1f419a83d4275218a89d7a7803f069d851ff628dd309c40f6e3c932af00cb6219ae6e21d2c28d492cd5404b16dfa627d93b1e8ad2ea49d2344c1a3b234bd6f1c70fd4252844a6e6ab7b8997bc55fa22ce951ee038d289078b95510b0f2473ce1348434f0ec4a885ee84fd08fc50f08ca7991af3f8c322b496466f804c4b700cc9391855bd0ee339196de2b5ec2d8425c711d3f9e051eb055d45c693d7549712f5284a9fbca7d15c5bf1a9c8e3b3c1a43983056782e046c29e3d57082f7743b8bf6d994cd3c26c85609eaa11e6f7bc4", 0xfffffdaf)
syz_emit_ethernet(0xff, &(0x7f0000000400)=ANY=[@ANYBLOB="ffffffffffff0000000000000800471200f10068fffbc08990787f000001ac1400aa010105cc971a00004050cca730ad1e6745146e13df2c1a53289babdada005923ca93f659a5f366ec5b151e1cae6ef3a23e21a7d7cc9f6fdcff53dcd7593d7d52d07099427f705c90d147217c1f8857586421408a66048cc88ca41574530df55c00b8910a56f7c838556fc19ce0c3aed174195abf554c50952b3c31a9ccbc6871c871254ba5e0e047775ddce8cdc209ca9fc9c960f77ecfa8b32090ce91260b5b318f1bf00437a02b3b844d243e92c6af9d4306f60dabbb208884a5167b611b96be9941e4604b40599a64e7ab0cea437f00000000000000e47f8b64747d"])
execve(0x0, 0x0, 0x0)
fcntl$setown(0xffffffffffffffff, 0x6, 0x0)
r3 = semget$private(0x0, 0x2, 0x68)
semctl$SETALL(r3, 0x0, 0x9, &(0x7f00000000c0)=[0x100, 0x8, 0x57])


setuid(0xffffffffffffffff)
r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
r1 = dup(r0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


setrlimit(0x8, &(0x7f0000000480)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETAF(r1, 0x802c7416, &(0x7f00000000c0)={0x0, 0x0, 0x10001, 0x0, "ad95be4b065c389983d554ecc416cf34eb18fa8e"})
readv(r1, &(0x7f0000000180)=[{&(0x7f0000000100)=""/25, 0x19}], 0x1)
writev(r0, &(0x7f0000000000)=[{&(0x7f0000000080)="45db9950f4b16ed62dbd450000", 0xd}], 0x1)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000040)={0x7ff, 0x0, 0xfffffff8, 0x101, "1abd1c37bb18fbffffdeffffff00000000e9ff00"})


r0 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r0, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
setsockopt(r0, 0x0, 0x66, 0x0, 0x0)


open$dir(&(0x7f00000000c0)='./file0\x00', 0x200, 0x0)
truncate(&(0x7f0000000000)='./file0\x00', 0x30001)
truncate(&(0x7f0000000040)='./file0\x00', 0x30004)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000040)=[{0x28}, {0x28}, {0x6, 0x0, 0x2}]})
syz_emit_ethernet(0x138, &(0x7f0000000300)=ANY=[@ANYRESOCT])


sysctl$kern(&(0x7f0000004e40)={0x1, 0x2}, 0x2, 0x0, 0x0, &(0x7f0000001280), 0x0)


r0 = kqueue()
r1 = open$dir(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
r2 = open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
kevent(r0, &(0x7f00000002c0)=[{{r1}, 0xfffffffffffffffc, 0x63}, {{r2}, 0xfffffffffffffffc, 0x85}], 0x1f, 0x0, 0x7, 0x0)
chmod(&(0x7f0000000180)='./file0\x00', 0x0)


r0 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f00000007c0)={0x0, 0x3, 0xffffbff6, 0x0, "6106a6bc44862c5008c8b503005a000400008fa8"})
writev(r0, &(0x7f0000000080)=[{&(0x7f00000003c0)="76f0b67c483a24febaee4d9c497b7e5f0bf12b7225efb6f6c869e646ecfa588c53283c4dd3ed77706f3868cacea799a3bdfb42db706563dca286f58274eac945d5ffe9054ffd5b7724b408516b9ed309d4751896dd052cc4", 0x58}, {&(0x7f0000000480)="568446d880d32ef0a4986f1711580313c8a39613e9e532e4f672c1c0db83a16c5e4be2133234bf17424dd50774a7f09fe9141026ae3d9d0596a191aacdb1d8e58984dbdd7c7f50b0c738ab46d9469e43a0b4f9a1f66d8160621e5c0f8e480fd767a0240b68ef993576acc48f0e8ce55b8c7101", 0x73}], 0x2)
syz_open_pts()
ioctl$TIOCFLUSH(r0, 0x80047410, &(0x7f0000000380))


mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x64d1)
open(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
shmctl$IPC_SET(0x0, 0x1, &(0x7f0000000000)={{0x0, 0xffffffffffffffff, 0xffffffffffffffff}})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f00000000c0)=[{0x14}, {0x5c}, {0x406}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
mknod(0x0, 0x0, 0x412dff)
open$dir(&(0x7f0000000080)='./file0\x00', 0x402, 0x0)
syz_emit_ethernet(0x4e, &(0x7f0000000100)={@local, @local, [], {@ipv6={0x86dd, {0x0, 0x6, '\x00K\x00', 0x18, 0x2b, 0x0, @remote={0xfe, 0x80, '\x00', 0x0}, @rand_addr="607ba243b19d8e9ea241f577704405b6", {[@dstopts={0x3a, 0x1, '\x00', [@generic={0x0, 0x6, "f9972bfa0eeb"}]}, @routing={0x88}]}}}}})
r0 = socket(0x18, 0x2, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000040)='\t\x00\x00\x00', 0x4)
r1 = dup(r0)
setsockopt(r1, 0x1000000000029, 0xc, &(0x7f0000000000)="ffdaff10aac6a28ac93e2eddc45c8454e486f64c", 0x14)


r0 = syz_open_pts()
readv(r0, &(0x7f00000012c0)=[{&(0x7f0000001200)=""/1, 0x1}], 0x1)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0xffffff9a, 0x0, "b07b1f660000000000002000"})
syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000100)={0x0, 0x0, 0x0, 0x0, "0fdb000000000000040600000000000000d900"})


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x20101, 0x3, "cfe4ef0d51a8f12514cfc9f3cb5e53f617f969ef"})
sysctl$kern(&(0x7f0000000080)={0x1, 0x37}, 0x4000000000000004, 0x0, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, 0x0)
syz_emit_ethernet(0x119, 0x0)
setreuid(0xee00, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
getdents(0xffffffffffffffff, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x8020691f, 0x0)
openat$vmm(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$VMM_IOC_INFO(0xffffffffffffffff, 0xc0185603, 0x0)
lchown(0x0, 0x0, 0x0)
getuid()
socket$inet(0x2, 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x2, 0x4001, 0x0)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
r2 = socket(0x2, 0x1, 0x0)
connect$unix(r2, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r1, 0xffff, 0x1023, &(0x7f0000000080), 0x4)
recvmsg(r1, &(0x7f00000007c0)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)


ioctl$BIOCSETWF(0xffffffffffffff9c, 0x80104277, &(0x7f0000000000)={0x1, &(0x7f00000000c0)=[{0x3, 0x0, 0x0, 0xfffffffe}]})
r0 = socket$inet(0x1e, 0x3, 0x0)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)
connect$inet(r0, &(0x7f0000000040)={0x2, 0x2}, 0xc)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000340), 0x0, 0x0)
ioctl$BIOCSBLEN(r0, 0xc0044266, &(0x7f0000000000)=0x80000000)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000080)=[{}, {}], 0x2})
r1 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_GETPARAMS(r1, 0x80105727, &(0x7f00000000c0)={&(0x7f0000000200)=[{}, {0x22}], 0x2})
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000400)={0x3, &(0x7f0000000040)=[{0x15}, {0x1}, {0x8106}]})
syz_emit_ethernet(0x2a, &(0x7f0000000300)=ANY=[])
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f0000000080), 0x1c, 0x0}, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b10005160000000000000000070000001a5113fecea10500fef96ecfc72fd3357a89583535673039d2d236acf20b7804be38164991f7c8cf5f882b2900e1aa5b23edebc8ef99a8ad491726fa8251e2f0ac3ebbc2feb3fda1139b672f4d3353eb06acdb35a069d7080000000000000000008904000000000022830cf41bed66f4f365ccdcf3e4999d9d20002002", 0x8d, 0x0, 0x0, 0x0)
sendmsg(0xffffffffffffffff, &(0x7f0000000240)={&(0x7f0000000080)=@in={0x2, 0x1}, 0xc, 0x0, 0x0, 0x0}, 0x0)
bind$unix(0xffffffffffffffff, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x100000040000000, 0xffffffffffffffff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
socket(0x18, 0x2, 0x0)
writev(r2, &(0x7f00000002c0), 0x0)
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x80206979, &(0x7f00000001c0))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r4 = socket(0x18, 0x1, 0x0)
close(r4)
r5 = socket(0x18, 0x2, 0x0)
setsockopt(r5, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
sendmsg$unix(r4, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)
fcntl$lock(0xffffffffffffff9c, 0x7, &(0x7f0000000280)={0x2, 0x1, 0xffffffffffffffff, 0x3, 0xffffffffffffffff})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f00000003c0)=[{0x4}, {0x4}, {}]})


socket(0x18, 0x1, 0x0)
mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000ffb000/0x1000)=nil, 0x1000, 0x0)
ioctl$WSDISPLAYIO_GBURNER(0xffffffffffffffff, 0x400c5752, 0x0)
munmap(&(0x7f0000ffc000/0x1000)=nil, 0x1000)
shutdown(0xffffffffffffffff, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
socketpair$unix(0x1, 0x4912e92f8141e817, 0x0, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000001c0)=[{}, {}, {0x6}]})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x8020691f, &(0x7f00000001c0))


sysctl$hw(&(0x7f00000000c0)={0x7, 0xf}, 0x2, &(0x7f0000000040), 0x0, 0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000100), 0x4, 0x0, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x462, 0x0)
writev(r0, &(0x7f0000002500)=[{0x0}], 0x1)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}, 0xfffffffffffffffe, 0x0, 0x0, 0x0, 0x6})
r2 = socket(0x18, 0x2, 0x0)
sysctl$hw(&(0x7f00000001c0)={0x6, 0x16}, 0x2, &(0x7f00000002c0)="4ed8ff25df559131656510c2f2533801f982102dc99b8ad9bd578a409668b98ffc254ec7f69a44c8bdaab654f80095b4b9cfecea13647e0007b9fb3f44350a83d8e11bdb0686bbc151bbe8045ee559249d226cea69478ec190d369e4e2b2865ea039f6e0df56a73687132ec93be8d0b65d4195100d664d40762955583fdd1c76831809ae23f1fd931eaa9b039c6817f34848cb63b8cc842f0b37b59111231b6be092bd12243f41d67ad34d994ce72855e130691bb646c42135c83dcb699221550744e5b4f82e67c4886a791c5ed8992cbc2892f4a480632de2a8ef", &(0x7f0000000200)=0xdb, &(0x7f00000009c0)="d11b3008a232ea370183c28fb7116802cc5424969635a8aa7d138d3015bc22ebc8ee0727aa9a9a3a84d61c583553c20d52670b702e576e355b8a19d72ca47dbb097bfa53443cb8b1cd9d1c2fad0deecad37c6de4b0e27fff6a5810ee3981608a682bea0f1683539f642a767ed03044d183fb80e953298760edb0680e093860300ae6913e77173b9b1ff087eddd373815193385f00a722f4aff4f3c15c0442d7d8bf62643920af1c62379342de3929d1f72c544462746926feff901193cb2f9298595a9c5eb65278b56db2e44877b58e5604d06c7814edf5b5574df8d634f03588baef8badbd6e19a145e869f952f281ca43533f32ebe0de29fa3b3aacd5412fe9b066ec8be32632daed9288f3667b5707ba67b7a9f38ebee316d04709dc8560ad5ed6926e399d1a5cd9105d82086711e3d2937282e17d721f22829aba44a2d6df69153c4019ccb71b06caec91c4cc39493e2d5a4fee8f6812df3773e7b49a8d71e7e3e34d00500d2e923f6cf241191cb14f0ab99443fc9995ab48a8e9205621f205cfaa5c9a8bbb9c552c02a015c71622a8df7bf0713a11558777bc88345f1c7113e824de6a4b6f808aa05910ec0dae1375be21057f688f1cddc757471189d20f854e01f4dae0154c1aae10678210c1ec6a802942f33f4e81b294513273902b6869a43e6a7d7f515e269a2a9c84b20bab6cd4309c8412422113eb3dfde734b9e9fbc3ee21720bca0014a3eb646366c0646e4d2d2808bb69239e68ebaa15a8321500e638e9ede7ac26804ba9dbc84f1aceb065685dc2a5ef3da95ced041b2a8c625820fec205d7f9caa5ca146097de35a2a1e23476882fff953585c7adf4e0195afc4eb77d6e91ff705ef832e50e34b752b4315d56a79b07ee577540c8b47fc59b91c175534df7a4d70770dc0e15512b4872bcd28fc38dd1643df2aedce7e187add24e13bfbc0c56fb274a628d6720fc4447e23323066a3205018993f126f4a430d226af994ab96ec1c445b46a5b5ea211c783e3449d40eee0429b8eb3ed851160458e67aab6bce13d8a317224a5f4f1bea0b8a4d59d622f5651f7f62eef5c9abb0dc11d513b908489b456b97717c92be63e4036628aa90ab9903647a69405ff19bf0a9bd37a7170d6e672a1635f93fe46f56d5e5dc7e39d03748911dedc0dd7d5ae4c0315cbec57251613463ff69cf4dfc59753dab2d401f3f5d076f9a1b7b7f6198e7e179ccafaed27be792e295bf7d3b2b3e8ab0c2d75164095f20f7a6ee21629569f96f3b1e7d0feb4f7492fc653a83f044466d0c006c759a22b10a0fc30945daf0cfc5c8a98e83f2a947399213ac5cb3c8e023f142f36229b321717e492e4383b3f43830398d4447e7bd50a43a5e33b8bbaf395d44f0a0a6d2ed4b07d50a7e161d07dd048ed441c553b947af3b7ca4fc17ee8e4d80268b536b9a673b27615a6c5971f10fce2aa06ab08d22c8d7000692ed68cc9babd62411badcaf0e9d8b124404501429fe51567b09dc9c755e269a9e84d9f12c8f3237b37b525038b0c67eb23d7cbcd2941b39daf15a690d7a934a9ded887380e1d6b0054013d74b076f0a3b3b8d5e67cd42697e144da50622c263336b686d305fe894613689ec65b7108b9fb9dd682b853f561fa71ca5e953d927b91a4623cd2ef913ddbc90273bc38bbc92dd64a4eca8aac917e02c2fee6aed2868215851c5c2fce6df6c89963b27c370482a9fc943e947e3e6580305bdf3757158581d6de9af1f04995373054dfef37b4b0ef08eb3abb568ae66b4435dbb5c364b3f1a3fbb1bd1b36bb222385f2a18a0853713ae53bc329b317c410d77006be07e9f89d895301f4339a9c3fc6d0be422718c82136288c71b80575f919a30b90350794d252318037a0f6648b5ee8c637f80183044bf4068d64ed6c6b1a0539ad209009752dfc7f93ab83ce04f32b92a705b7301427bc97d1c1c9cb28f69096b530da16337ee136745cef97e8e05f8beb30df1a210843dcd50bf786b822c4a26676184965ca1fbbc88e83d94dc8266adbee7eb7604e93f7f5a4741bbfaf688bfe432d08891e40be808d0867b47ab6dcb860f4a9b2400749578ce724e1e55b863eeafd2db61a0944e51420650aaf3de560adb51c7598c66be0a530de5706b8781e4bf927bfd8e1f214f8b6071c406660036261b05e3e8499ec45cb3ecb44c0c87cb69655b05f1471f5c4e52eec057a643ee9472d7ba112275662bf7fa6737cc3f9dde20c5e05852296dee6da26666a4aed021575652b4f75ac8cec9aef7f06a305f966ea67dc4e6cbbc41e93d02d801ae072b7bf1a7210a6764ea455fa92633bfbd5dc43f9ced52ee8ed6f84bc12cf41caf575eb58d353f69e34eaa95f4ec2b935c38e6e2cfa0b77481cb12c8a332f3c8d8a5dd4168f0bd34967a42a7a25716b14bab705ef7e6bff0859b5b1807026592fb1fc02ef05f2675661c1e2c826a6ed1fef177b7cc84e908f6ae575fb4d6654402a88c3b06e7e0ea6ef95fab39fdcd060f2421759487857a9cc7e4342033f64413c1233667a639e9382fb78f602ef38e69587f6ccaa5e5307d30e64928dc0f7ccff6092e9eee382a05b55258abb4cc189b47b2dfc06931260eb99efc47652a478babcfaf788b0dbbd7d4a2b0ff21c3dbf9103b96126d85abc67bf1010e22090bb596aa1dfa3af781fc3983f6b50244e22ca6b45387d7404da00eae42cdb50b553149dfd8a125b46d6ee5368ae6f1e5f86c29a584d8a638ba794a975f83804faa1375682ba20f088dc35792c369f7cdc5d2d93c302130eaf7ecd35a91d95b81860dbeacb2dac063dc0c214eea82116db9a09c83f81c03c66c435f9bac317a2821def094883c0a513ac86f1ada8cfefccca5873fe8dc01a368d3ab8d3c2ea0aa8ceefb9a265ed407e0c1dd83de2ba9f3da77e349b51b738e41babfabff3acdf97a9eb3f4a46d3e3a5dfff07f049ee140fe2ca2d26bcf333d8a6d0c05fc4c8a0bd7f3ed0e0b6b27283c7a1c9f0e67cfe60f061d27cc3e98ad5d47374667b76622f90115151f7f5c0b49087968a54e1aa9d5741bf1af0e415954d04f27444e5b4533769e7e6f65a94da6799709157999f4a834520ebf30f44e225bdc879cf18a9fb619c47ff738d000018942f88f50eeb1ae41821be6ef88dac5cfac95949c6aa6d5f14dcae3522b974ee2323303b80d1b3fe4d2fd49a02caef2b3056d0f17772d1d11fe52102d5c6daabbedf48f995d0d8559c5d26328f37fd306da37be0d7fc7d57183c8a8d99a353ae2155230934451f6385f59920c1ec58c7b1df58ae1913ceefa3711391542e8f45ed8eb2d69a89ff86c166bc1285647310c574f33da042542a7b8ddd952af1eab83ccb83ef919911bfb1463a393f1a1c4035f50c0425e14f9d02a548f727781e58cfec7a695abf58b528181dfc4648c897aeec290825d9778cc7d49909e476b5f0922a8d3f91b74e07a287e3fd897d05b5f1794507aa4e080540301874b3eaf26f7fe8c87beb46699c6545b9265bd7bc67c7a4307b159f96744eba01621e709d7fe52a34b96e14dd27ba6a152bb9279385d907500b8c3634c88c3aa9e6f559a1dd7e9905301fd6f9946b7822bb66616e6f4524d7810e80821fac2f074733080422b989ea1b5da4599aeaeb4e9d8c392220d3da72c8b15ca5fb4e411335370fad2adca07779b4e4adc8b7d2f2e3ddbae2b54f9851da892ca7ee9009ea7cb7a9110a02631db32d7d0cbcae6a1badaf518f1561109e6dea4a57f16963bc1779bd163a1863d7c6935398bdd1ae06f0200b93ba538fe01748f25933f4626ee1dffc28c79f9f36071c25cc31a9ee819c3dbd1d86b0e1ff45e04f267ce8934e96700d34b77fe25fc2061b4e79d7cd0401ff89bf65e3d6544eee1ae67aedb74daee7007833fe41f91215a2e6e82369baf577b3bda272697f1a7db14c471fa1507fb0839f2d066a6ef9aad6c979e9783db93be78f6f95f8681dea1b3885dc6afbafbb768a028ede19d66c19649a415a9e0fd4ef64fefc02c3b0c5baf37e7799106157012745441416039a655ae31b22eb2600162aed71bda1feec96b5cdadd8e5d8aab86691948891e7bb5172343bc64c69a4b4d97ebd8e43e5af9ad424f938e7a54102ffb06a9419d2a309addde6f2948e03c274d8096111e0da52433c3ef54f5b1eaf51714906567aa138891aaaa074e456530cee4c92dce649705037cf8773ac8e18755a5234c180eef1fee7c312cc7db09c4d7aac8bf675a345b8412f20b42b7a1de28f525e4fbefe36d00e930bb383f7bfa82720275a2efb9d3faebccc639f6c2da44fdcffa900d1bbc8fedef3aee9ecc64990965b721937b2dc19ba01ecf1943e46ff486e74536443b79ddb9581478777de51a6cf492f66028db35452bcac70625f5a2920bc21c592e2bdd88cb4c998ea96f05ca41fa239cf2dd72dc519e07fa1f3a97686edb1c5e62b2135d0844c4a1917abc66c1990783d711e63430d7f71b8e792f89799a19a0935bf0047d673de6333d39aed6cdb3f5904fc2f0a37cb8db0ed517880ead6d5781afb1f31d92d1601549119aae0dfa749171924852d3c9d675d1f515a45fa53563cfe91db25230e1d2de67ae092bbdb46e3585b8f3a462ac6c665de845289d93c0389ff2610d4370dd8360f327588b1477ac470f1ed9370207747c6563e6644b7dee99d4e58a15c89b45521cc35894ff838a1821d9a1ee7117dc982f61d7824862cb3d6be03ec7b43a43ad5acad526e5ace9555193468580fbbdc93afe15ec25ceab12d1f4834603e14d1b3984b29d311d9f25f38fc754d38079d5acb9dca890349175f6b7e45c7ff0189a1eea4c7dcfe6c078c21804fb2c41ba679d04285a9ecd7c278f142e25ed6b7d395bc585f6c9d77ad5820b92d74f5b887e7a0e107308a4c101f1a3037e1b89e6f0f1a8fd76d9b35c8d3f51a83d57c92f929ab829c31198d52df60fed1e176d60a9da54ff595378b2627898076360dcd987a94c345c58924da5ae00d3e18af9edfd6e0752cec2c78428f4e713f73888f114c55bd26b14a622574e5e643e68d1eb3da933c87d6a4ff9e6110fae6b9c1d41699f35d247b3eeffbb45e9b4aab348c1a45797bb0cdecc75bd48ad97dfa6dd2f699156b9b993e5951a118ad3c17f026dc03fdceecfc020ba77d90bea462047de1c15ca91ce5ac00b8f5fe12e94b86c8ade8ccd4d57d651cf3193c5d02741efe59f81632090b849c479d0d6907b79125c275c2ffb88837903c1525adc344be30d10451de1df25f4b502a1cea42180bf6152c07532ac66e6179e5290aafd9d56214e5fccc45bd88bc7ba9584154aced285965333c0ad9b227f095ecd0608ac909cea23756e9fecaf69b7dfdfd5ee979d15885d76ff2aeca7553e482ab8afef6010760b1b74aa507178784586b9730d82998bc2d25547fd85386aaa22273ab339c601e109d9fee13a39179963408f3e7a85ef73cbf286b6e973b7afea4c60171aa6a9ea80344fcd176c671f55f108bc293d2290e9e2ce31402ca538eac2d5c9f47ed2232541394caeb98e5d6320b2e1669afae06d5e9151e4d92d6901d09fab9404ba3f644f95baa18e3a11d28d8561849c40695789063ca29f160d175b107637db9625711c20572e8cd4b5d6a0e01698ff4794f8bb13fdc51aa992692377a2fa940d0b9c1dc2e1f85b0d5536ec2aeeb6f03f39ab499442990489d29980428c893a239a7c8e5e7a17490f1e8cf3f4742ac9f8afa86c37776684ebc272b7254a1f1b90966dea07ceaea947e14ba8d439d651011e08914d5eacff", 0x1000)
close(r2)
r3 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r3, 0xffff, 0x1000, &(0x7f0000000000)=0x1, 0x4)
bind$unix(r3, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r4 = socket(0x800000018, 0x1, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "1a1116f0d0f700"})
setsockopt$sock_int(r4, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r4, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000004c0)=[{0x2d}, {0x44}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000200)=ANY=[])
r5 = syz_open_pts()
close(r5)
r6 = syz_open_pts()
writev(r5, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)
r7 = getpgid(0xffffffffffffffff)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000500)={{0x3f, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0x19, 0x8}, 0x4, 0x101, r7, 0x0, 0x9df, 0x7f0, 0x3, 0x10001})
ioctl$TIOCSETA(r6, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0x0, 0xffffffbf, "f4f1c6f26461c094f4ffffffff00000000000002"})
readv(r6, &(0x7f0000000280)=[{&(0x7f0000000600)=""/131, 0x83}], 0x1)


mknod(&(0x7f0000000540)='./file0\x00', 0x2000, 0x5e4b)
open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)


r0 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r0, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
getsockopt(r0, 0x0, 0x69, 0x0, 0x0)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xffffffffffffffff, 0x0, 0xffffffffffffffff})
sysctl$kern(&(0x7f0000000040), 0x7, 0x0, 0x0, 0x0, 0xfffffe88)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0x9, &(0x7f0000000040)="00040080", 0x4)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
r0 = open(&(0x7f00000002c0)='./bus\x00', 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(r0, 0x80185760, &(0x7f0000000140))


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x3}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x100000000})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7, 0x3}, 0x8)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
write(r1, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000380)=[{0x1d}, {0xc0}, {0x406}]})
syz_emit_ethernet(0x138, &(0x7f0000000040)=ANY=[])


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931", 0x11)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f0000000040)={&(0x7f0000000000)=[{}, {}], 0x2})
r3 = socket(0x18, 0x2, 0x0)
setsockopt(r3, 0x1000000000029, 0xb, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
r4 = dup(r3)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt(r4, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
syz_extract_tcp_res$synack(&(0x7f0000000000), 0x1, 0x0)
select(0x40, &(0x7f0000000040)={0x0, 0x0, 0x7, 0x0, 0x8, 0x1f, 0x6, 0x8}, &(0x7f0000000080)={0x7, 0x1000, 0xfc3b, 0x4, 0x4, 0x0, 0x6, 0x10001}, &(0x7f00000000c0)={0x4, 0x0, 0x3, 0xfffffffffffffffc, 0x80000001, 0x8000000000000000, 0x3, 0x4}, &(0x7f0000000100)={0x790, 0xfff})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x8, 0x0)
r5 = kqueue()
kevent(r5, 0xffffffffffffffff, 0x3998, 0x0, 0x0, 0x0)
close(0xffffffffffffffff)
mknod(&(0x7f0000000000)='./file0\x00', 0x6000, 0xe02)
open(0x0, 0x0, 0x0)
r6 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
r7 = socket(0x11, 0x3, 0x0)
sendto$unix(r7, &(0x7f0000000100)="b1000504000004020000000001400000331c13fecea10500fef96ec72fd3357ae30200004e3003000004be38166a91f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d1b5c223e7d0c032bfa8970c1f505002021fbfa0c0f00008abfa1221554f4e0f668246c0900000008e371a3f8343712051eea040000000000de653a1163386e7ef42eb062dc165c8ac01c367ab984af52ec07e748d7ed4c61313835c63f11553b26c58e5c086ba952dd9850a5d17bac31917b481064294eef1caaf6f3ec6f4c7fe252464996961b9a5235a0de3164dcf8b7848e06413a8857e22422905e38112ac8e0d80144f1305e5597d2863af7e44c4fe3d66de1b19b5809a4641ffa14d52f4ed1b65e000049d73bcb496c416c51a6abcd97aac8c601d973470359a118d6865bf147233514ab846168af80b2fcab8e48bf0e53afac7641fd0261d7c16aa67d4b4de3440500548c4bcb5f830dd6b5fd2325243f7f4bac915250adcc508d59580bb7c97bb953ccf446c248c60d468880861706c7bda320cc1969032d00b30000000000000000", 0xb1, 0x6, 0x0, 0xff7c)
r8 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r6, 0x8020426c, 0x0)
ioctl$BIOCSETF(r8, 0x80104267, 0x0)


open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
syz_emit_ethernet(0x0, 0x0)
openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = socket(0x18, 0x2, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
fcntl$setstatus(r0, 0x4, 0x40)
shutdown(r0, 0x1)
r1 = socket(0x18, 0x2, 0x0)
close(r1)
r2 = socket(0x18, 0x3, 0x0)
setsockopt(r2, 0x1000000029, 0x31, &(0x7f00000000c0)="b211d7170d816685c8e360f2fa41c1a0946988b272d2dd3dc90142a84231a746e337b372e93320cff6669cbe7868de45ed3fc33719ca6df71ecec8a918458b2c10a1f8c66653b276e180e9cb9b21f9982230f575295d48889c9a920796b2dd92fc8575680b37ba955d2c15e6d7c9198ed900ab006ddfb67869b51a2216114d1ece85f593e74035f5bc054eb1dbddf42a", 0x90)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x100000000000000, 0xffffffffffffffff})
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
writev(r2, &(0x7f0000001240)=[{&(0x7f0000000240)="f0a8468fa819ad5e71a8be585f2ae642a8278564317b78a3b743b3a68a64daa9a6f3c6f09bb877ebb5e695854113c37dae52b9a28acdc6c3de65edf75d107620028e9e3222034bfc22f12273ade2fea06ba00180b581b22d4bbf9030e7a702419e4555ba924b69970c80e8cad1ec74bdf0e4d012c4ddb0faac2fab4d1beadbc73d8e33c6f1b1730bcf1f6d37953b01037c6dbe2a0cfddb69afdee5092b3b460918d483aff973cc6c5aae0db223a8a79191dd28cbd40085800d363de83d507bbee66900f19f6ff46e3ff6fc16ff3e5e88368ffb2decd3077b6fd06468d1137c1df3c1c86939a408a7378a362ae3b2c2cecdad6d8dc50c6130a6b1e38d6abde93d47d04880143f8afec24b852554da94f94652c2a4b9c089b939ddf179a96a28243025d8c8eb5e626ae398b3b7c29c9ef49cf4907b99d23b214eaf9ee3f625ef247f205070b13b332f52ba64172fffbbd8fc6d12632798c98a3aea02126a56de88e199ffe4ff47556475341c04e34587ec6ddcc16420b6cfb04cc92fc491c1c46ba92d0e4e045389c3effc8cc6709e7658557ab28e21c315cb46edca8c092279500d61386ca707986ba2bf03a8e80b0029fbe1ab6f5a77233342f2d1f5b31e5f1768b0419ede2ab832f1d4ed64329fc3fb7dfa1edaace42f8479834a4d9dbae61b3c5be768ffd3f9035216dc6e684fad65d86a75e7912e8e18ea317c505380d9c954c31e5c05ee5ab8bec432a9f69bbd9c2d3ba50a08ec3d9d22b97bc1099c2b9cc27e3e0d72c74757225b898a985fd01f05179e2f31de5ab58368212288dd39050623ecf9e8808a69424c32c08f0200c7eebd8b76abd152164df103129d5291ac8043fcba7dd5f63a33f943623c509887af66fd315f77ea0da829daa768beef2edf33cd5c1c98a18496e24e71d8553e72bd63cf981bcb166828dcf4ead7e7be78e7f4acd4916cbf37bd6860776e07c2e4f00ee2edee5a35e32b33f0ea4fea4d9e6f519c3ebac30e2fb32abca3e128dc4ffb38c2067b8f2564629c21094f0e660189b1c1108c20f0ffa4e6bae0889ebd6389fa86f465db3da9e2371f07a9af58c53a5b196f5a5e9be9c7f8e3a0f9fb126ba77d8ef25c8a6e67eefcad70fa715aa4052d2c457afd5a7d941ecf7aff6824612bbdab2be07a43b72787c35a9e157dc4e0cd81d7d33985923fb99304d54bac07b374b1b2054a", 0x356}], 0x1)


r0 = socket(0x11, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f00000003c0)={0x2, &(0x7f0000000140)=[{}, {0x40e}]})
syz_emit_ethernet(0x6e, &(0x7f0000000140)=ANY=[])
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000140)={0x0, 0x0})
syz_emit_ethernet(0xe, &(0x7f0000000480)=ANY=[])
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x8, &(0x7f0000000b00), 0x4)
ioctl$BIOCPROMISC(r1, 0x20004269)
close(0xffffffffffffffff)
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
r3 = open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
poll(&(0x7f0000000240)=[{r1, 0x10}, {r0, 0x2}, {0xffffffffffffffff, 0x4}], 0x3, 0x9)
open(&(0x7f0000000100)='./file0\x00', 0x0, 0x60)
r4 = socket$inet(0x2, 0x3, 0x0)
getsockopt$sock_int(r4, 0xffff, 0x1008, &(0x7f0000000080), &(0x7f0000000100)=0x4)
close(r3)
sendmsg$unix(0xffffffffffffffff, &(0x7f00000006c0)={0x0, 0x0, &(0x7f0000000000)=[{&(0x7f0000000040)}], 0x1}, 0x0)
r5 = openat$pci(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
symlink(0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000001c0)=[{}, {}, {0x6}]})
socket(0x20, 0x8000, 0x80)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r6 = socket(0x1, 0x4, 0x2)
ioctl$FIONREAD(r6, 0x8020691f, &(0x7f00000001c0))
ioctl$PCIOCWRITE(r5, 0xc00c7007, &(0x7f00000001c0)={{}, 0x3})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)


syz_emit_ethernet(0x2e, &(0x7f0000001280)=ANY=[@ANYBLOB="b1d3bd0a0c02ffffffffffff08004a"])


sysctl$net_inet_ipip(&(0x7f0000000000), 0x4, 0x0, 0x0, 0x0, 0x0)
setreuid(0x0, 0x0)
r0 = socket(0x800000018, 0x2, 0x0)
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0xf694, 0x7fff, &(0x7f00000001c0)="0242007ea950e47b118b7636520000f1ff", 0xfffffe18)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000380), 0x20520, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000100)=[{0x20}, {0x7}, {0x6}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)
r3 = dup2(r1, r0)
ioctl$KDGETLED(r3, 0x40044b41, &(0x7f0000000080)=0x1)
chown(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
r4 = socket(0x2, 0x2, 0x0)
r5 = semget$private(0x0, 0x7, 0x3c0)
semop(r5, &(0x7f0000000180)=[{0x0, 0x43, 0x1800}, {0x4, 0xe6, 0x1800}, {0x0, 0xfd, 0x1000}, {0x1, 0x0, 0x1800}, {0x2, 0x5, 0x1800}, {0x4, 0x9e, 0x1000}, {0x2, 0xfffb, 0x1000}, {0x4, 0x40}, {0x3, 0x8, 0x1000}], 0x9)
semctl$SETALL(r5, 0x0, 0x9, &(0x7f00000004c0)=[0x9, 0x1001])
getsockopt$SO_PEERCRED(r4, 0xffff, 0x1022, &(0x7f0000000340)={0x0, <r6=>0x0, <r7=>0x0}, 0xc)
semctl$IPC_SET(r5, 0x0, 0x1, &(0x7f0000000240)={{0x8001, 0xffffffffffffffff, r7, 0xffffffffffffffff, 0x0, 0x40, 0x2}, 0x0, 0x9, 0xe7})
r8 = socket(0x11, 0x3, 0x0)
sendto$unix(r8, &(0x7f00000000c0)="b10005166000009f0000000000070000001c130500000000fef96ecfc72fd3357ae380b37b673039d2d236acf60b7804be78164991f7c8cf5f882b297be1aa5b23edeb51e2f0ac3ebbc215000000eeffffff028ea8af630037282102000000720fd38bfbb770c1f572c881ea772ec592040000000000ff0c2300008abfba0900000008e371a3f8343712051eeab71d89e0442c5e52000080042000"/177, 0xb1, 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000200)={{0x3, 0x0, 0x0, r6, r7, 0xa, 0x8}, 0x1, 0x1, 0x5})
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000000c0), &(0x7f0000000040)=0xc)
semget(0x0, 0x0, 0x470)
getuid()
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r9 = socket(0x18, 0x3, 0x3a)
setsockopt(r9, 0x2, 0x6c, &(0x7f00000002c0)="183011443d397e653a8a9dbe85bf49717a8de80b3720072c8e55e1b11eb6d7a06b0ef2f35e5bc724f17296a63ac5c48baa47df31ddebdaceb720bfaddfc2c364b972ced928321dcc23a532f5a3f87486e5853ec5930d0e979103b4ea078086876aae8301f14e5be93972755b3e357a", 0x6f)
setsockopt$inet6_MRT6_ADD_MIF(r9, 0x29, 0x68, 0x0, 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0x80606948, &(0x7f00000001c0))


setrlimit(0x8, &(0x7f0000000200)={0x9, 0xc0})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r1, &(0x7f0000001480)=[{&(0x7f0000000280)="00000053f6953b578a5e78ba726a44164282fbdce59879e20721c0b25930ac15cad92b17987d6c70b9047f2d23cdb8b6d76cdb4acd0f01d102ca1b9624dcb92a3496a85cd3e9356c954d9ad25d87bbbfee51603c6f705bcd4ebc04feceea4a01bb7075d879a19cf6c8ca7a76f1a3377ba643b0b06bef67d736f39ab2dfaa21a7c9f74a537a67ea748b925d5c0db14f19b8643bb65a04e2a641830b2ef9ab4087e50c63959920d13ff13464ce1c18b643a71260860e0483ab217250cdcb121305c5c1b22a236c83d7b8d20dfc08bebe5664e1ea1eb7bb0814dd", 0xd9}, {&(0x7f0000001d00)="6156b89a6c15794f5426cf6a9a99b45b13564d6568f0610200e27d20182a400c7a9a8f0bf304294555b6b6cd19d32607b3754f4a88c97fe52899b92de96dbe32036c902694cbd0aaeda1b13395179e9aa22d5bb4ed975d8a585625759478115f4c4ea9fbe58382e00bad0ecc43529514d50fd81869975cce62c2e1a2520b63fd16166f35d4894abbed34c52f3e7e55be11106341ebcf1c65", 0x98}, {&(0x7f00000000c0)="4266852a5bd711d4aa1bcdb84c1683023895f3c09dd09f6591cbc32693afd0b88a5a095acbc2a56dfe7b00631bbf4f1e0d5f97f7e6e6fa34e3a87f4928bdcaba0d83c8a2eb4036e617f903007224ea89dd9aec6f5b8a9b09b2593bf5a6bf21f0983e00000000000000000000000000000000ed7535a47ce1bd9d6e044370222d71e81d8cb355ec6f3d3dbe487352f0886fcd2a5a6470960cd614ac3aec14578c684d6e20dd82f1bd5fd29c321865cf155d4fb1667f1300000000eeb5681a51d1910abaaeea3cb6aa6f6b8075ac11889a339f163d310000000000", 0xda}, {&(0x7f0000004a80)="e0707225df5da0a3cde8f30024830d8e0a6a680844e59fcfa5dde0a596d8cb2901b8b60f269bdffed86a45026e99759cd124180e6c72cdd068718d18c40fc74364f4efef980c177c9d13853ee6bd3efb6bdd04795f2e00eef893ba9db6c641724b4320eb59db72e821e00eacae80ac14ec93e79465b5dfe980b08c3e219e10a322fc6a99d984aa3a17ac3eb99a7d90cd400081b6b1e9c2e49f51572f7f000000000000002cf371ea6bd4c4ec685cb5f1e1944576a86ba1fb802e8228e5f58b56265448b08e1f2d780a33751c191bc1a169ff48b7256c2993e0bc717933110bd6383d6022fb98dde74b5ab0ecd85d1c8019b3b8c07c14da5e8c27dea1464f6fc6dfbdd6c0f4b271cd8e8de9884f86ed79b994b9ed88cf29836e05544d9b93bb7fc1e2c2c2fddcddc82f884d45aeb0ce7407d2577be2fe2f8098613ab2ad60b5032a13dd9d63a2407efe3fadd1846988c3a299fddc1186d14064c4aeeee77394eb10e65516559f522378718fd87e5514c8fe55366b2154c898a888dcbbde73ca9e0126d6ee8c27af7b9eda998ffa359f377ea61147a6c3197247f363596ad3d3d0d9282758b09339d02616828993b0855085ed4748e48c50f7dab9668a7dca419149596579bb01408b8f2afa2b4bada88efbc57b7a096065fe6cb148eaed8f3becd5c7287c19d8b8d9341c416f2716c7a6ebaff889cf1ce69c7f4bf117fe4aefad2a50526a28df87ac628879076fe3b857ea830f45cb702afb7c25a06abe4d2a754d0fb77ff30877884fda5755e1c1c02700bade0be10b3c75c0166e477992584dbe309f2136ef82f72391136424d14b3fe1c4ff4cf8ee3d4a30577aa377438a795ce1efe0fef1f6436644224f92b45b87ec346a63a4600abb2bbc572ea82333f56d942d0294230c7ea8cf24bcbab7de10a06fbf4b8a5e4bc88a0b4d676062a62d5042b5d88b0ab80962dfff7ad508e6580ec0e565541c713e4a854483788c4440ed3cb388bb2fcf71e33495d9729eaa4f3df7d9118ea8942720f5dfda14cc5e35cd1c648b1e295dd0984536f225043b7aa56f45b94959d83990e6050353c7681fd596fae2ad6b43b26aac3e6302691eb49a92ac075b0973cc230bf41a02ef123a80cf799a9cf2c472ab0b45cde3c980a092662b79a78e428b56b878c2c9d7d2f667205d07c040744781e9c27e32a133cbe9e219489d97bcae4b2ec4ec0839978daba24fa23bb89fa6edc2b1f929e127136e13d7ab140a240aec7006d0740d15ce77b028746549bb91bde24e341d6aaef7684082283943780105de76983bc8c5101001c3a3a5dfe282d11d70ba08237d0c23eecbdc4a0738dcd1d0e92649c64d1fc75f5d4b1ccd10cee6ed69f4f63f63d63b04a73fe9b0d95ec3d98d55429524a7d5dc83c878f9bff0744c3c3dac7513e665383d243302b985da0fb404dddbde640a4f389fa4c3fb9ea1c5f9d515a2ccc8f64c832aff4f136f99b4d917ed0c1cdede6ffe621e6cd136bc2d43fb680dff0c68099c9503f61d3640c8ab7e0e00fc4a83fb01f03024f4f5325c1fb55568bae34451d9363cdc81e46e97b1686ae29abc9b06c8b5c7e989d3ad961e7216588c01b58b29fb05c432a615d17a09e3adf06cdfdf3dd2283aaa8fc9399b7b1d83c595c27f27b0c43fa110727fa37634d748bad8737cf7e94fb2c07b9737c4576b58e746ff84bbc736f246a7a368af9bcc22ca05122b160c0382db54145a62832ab52e1db855a1b160ef5f619b49f1e02baac67b9b0e626ba6070806e70c82c2d7c3273cf8e90270481e7baa2b2b4dde1b355f71c38405ae3f4f20e53db5e1542091b7f01507410184c37574a9ac52e3d588311c12bec275849496e726f8190529c0a49a0e3e6f455202aaa85bd892385fe7109b119dc4b5f9d6f74b0d27e04b2b648769af58d288765be71b37989a5ac5ae732d9e2a12c722e285383500d13e00dc7d6a064a7b207427edd517b5d30ca905935dbffff61e10b84ca904e4b58ab3278b09d1a3af7e337f777393b93c0e84ae3eb61f87e8f1388622fa35fdd51868a3329cf2c05fcba3c7cbf6afe20466583fbb1a8fa5fefdef3f8340feeff8048a96a2bf7466dce009599d9290c3e091ddddbe3f2031ac6e4c5ae5cf7099f92dde452dbaea6df2ad42b0cf665b8e221206fec348a6e3a70de77d7f474b88e8d328009c8ee253caef981ae633705c28594d3da0ce0de71b21f1cf64ffa8a23f58164d60240e1252aa62de9da39247acc335c352a8724ee35770747b3baf2ad195811dd7b768054277f7e59984084c464d49d936d1c66f7eb006001104bb29906ed7a14ffd968315fcad150cae3d278da5c0b1c82a62da917c39114deddd5bdfbaec686968e8f1aae41a18121de00cb66e9cf95403ec3c47f9155482f2b586fdaa860ac2d3d47329b1d493480fa5c968f3908f56c3c4731df5baab9d67b7b2253e3965a783031979ab940db29a998af0ad8fb492a883a60df2b28462813f8030bf701ab0e779cbc175a7e8d60352352ebbad06f6f1fa8b7d642ce526043ea448fb8583f5ad9759a422a41e41d7b3a36f2fd3acbbf4ad53f4babb0028820093262d6b7953ac6f90c270364c31e7295ed15d106cee1285fe71b446abcf7dcf3c0e275e4426bd4e7a57e93e7cf73e1372510d8e6a2048ff8780eda3223277a03eacb710cddfe510169064edbce166244de18084dfe2508159f889a55a67f083c558a9b77f733daff67179a2322b53179e0079c92bd7aebaea9c5340f3ab4b7cc81d51803abd09fcc33392063c34ce1e1a0e675adfdd4a492f5a45e96d2da3d4533c9591bba11ee5a7f8552bba7cdc68932f8f4583e0c8f72b064fc249e1be449f1d4e6c8faa0010000000000000ed34660c399113ca2e1af84335086124e5880174e4db34d7e82a81ad779a2abb3f6de2d6e5ed9e08855396579362285f40c6aba7fac5766b30caa1b5a3ca31935a45e124040a29b974de1cff0eca1b1ba280228bafa33d26d87f77abb36415122a0cf24e1525228ccca1f6873e67bec443c6fc46790d2af8029bc97719078956a3d3c897faf5b19beccc2b37813351bb8a0964a5f8cde403f162d4035b6743fdf93830888e6d0927e68c924de1ee1e6eda7de8348196a0e240b4fd629338d977b497c315662ab60b84797b733a931741f0f7ae88e608a9dc73ce5f2b075af61b6acb61f8fd475ae504f97723326778a75a37474e1cf72de50206a2b6fe5bd566c1cbfa0eba48c19297ed0036090a7989ef743211924453e79ea244aa18c85170c9aef0f4047332f8b35b47776723379273f292200f4a95c5a19ecd42eba114c3f8cab75937ae571eefd7d79368272db2d2db75a1951fba103340a092a7f7a11e6ed7aede39b6992f2163fddcd8998b1a51ce55edd4991bcf242545192c5da99577e6362b1a26c98ebdd7353b0a1ad10b5736faf60273485d0b7d8f9c6dce6538e5e8dac1b564bcf788efd488490736c1cc354758e6d394c77561e47c8c5de55c824dcef6c2ebb6e9e2c734ea05b56b5017f2447a2634099c1b9b09e061f6747e663dd92e0dc5eafa5eccc7e8d161c1e79f30230bb07dba9894fa6af1c66592cbbff937c01747ce5ca6b356f54f141420e38ae84b8ef505cb8e5a20933c463f48a70983996b72219e31cefc8a9485f6f5451deb8686bf1551de5b549da221a014fa06222265932a5dbdcca51d053482d30798e805c6c65808d72cca8d8aff611be639e7af32a8e9e92b2b83d59a081b86a7704b92ba6ea48259a31175760354ca8733a53ada1537a123ba7dd87b55bce95c238e30f19092f9585e8dd9053bad2c51385afe012c2dbd3c277c9e6689e907b907748964f38b9576ff9b88ec5f1961cdbe845c7e096061686ce822e34a2228227e934803ede4b984ac3e4ef28f0c0e24e0893e70d7d0f668c7d38a14b3b2ff87cae2d1fcf1c8db5c32d02250145fbb20cfb8b279baa4a12526484bdfe4d36d49a82db857b82a0e11a315ea2e298bc8b8a69f4f7545008a440ace5b2654872f3f569269a1144e946c90f904e48ba061c1a615e8cde0a4194a567e86041ac9fa4b42553e19147ef3185fdbc685da9b439f02a6a34d8858eff5d762d4970488508f194b7af38590888c70d69b9eec79e53497645006ec6658dda11a7898ae96c8bc1a54b48470dbd840f0fc68799019b5b4137dc5de49af82d12ff2f50033ee8007c7d9ef1ebb3d60fddcb9239508a858df67e6ad3ffe23acf973db7421777a6a2f23ac58f599d88487ad8515808de09a0f59aaad6ecd7ba190bae74968c49b63451fd68cb2b835db73f7e341587aec98e7618b9836b8e851cb31ba1a2a86d52cf167279f850d811a0209a3d4a9c54055ba189eefa40ea10cd6458e1ba09979a3bafd21c5837fe11c264dea2f529ad2ed6d19849f2e8c0fad613478cb66a6724091e4b2c56588793813b44745eb97e688f382026c85e87124a66f542bdb99fb7fcd874d34985353e74a166a9f1ad64c305912b2b6ec1423c15788fa6b2194e2be021f1deb0f1b3d44b3313fbc9a38c290cede3cba47afcd98a4e50d019dfb64214d9c18448c375186ae9cbc7df4614ed4b9ef760c9808a5698c81b1542bb08e4fc82bfaa01be44d5cda756d4111192661807d4f0ae852777642019dd45d876e2c3bfc3f0486016b3d763cbd9d899b3e00c7d3001e94ed8515f0ec9b9f1ed7b8df767103ef964acb4281a59f5cebf08cc14e5f5166b9a77a43e8a3ea75c3a6a8e56eea86eb2c861fcbee63d44e60a2dc88c726b8149380aaaca89e83433c919c53754a64f9d8fee3049a5ab750eb8191f7676cdf3257c9e0c661921049962b800a299e5f5c002629bf053030203b5925b0f782c8bc5982546761b4256dd7c37a99de97f1187190f3a1068c86eb7c54cb3ba99052518ddff6c2f5a3601808ebccb435889a32b844d663330dd2231d55cec6a2e6f880ac93dc383f0323f33f66cce427475e117054827db2ddee05696992299131d9621d5041a596c3e72d7b018c813c5e1f698381000d3efe1cf189e2f749047bed3c6cff9184f22b4f3b6368e4ed839802f31394207395f8b3758f3c93f640734ebd122b52739a610d85092beeb06e47d32ddbdb1ff4ae18c696cdb93f8169f5980b01ac14ff66fdbc7efccf6f572a58e1a05efb444510edbd59cfef4ad12fe842483a3178cf9c81bb43e9213a7a49339d9a4d8150b5f253f938e91b3801252ca80230a9eb6a15c048cf10e068c6bccdc756d7fa1cce0b1cb147325b435cb504e5db48c32bc68f74a60b8baae0dae80bc4cb1cf4856802868817de6e7345ed493ce177a3dbbdec2690d590a23e3feb49554dac882dd8b70d8b7128d7ba1fcb715dc8b18a2bcfae0bf0a0bb557eb6eae8bad4ce3ee4246398e304188b1dcac6ef8f5e251db9c29e0ddd58abd191c5e2a961fa3e09fbf5a540c7687fefa036743134bf7008f66f484fe72a812844385fccf500123ddce1c3628c0826250f6e2dbe51bb7f525261f64bed241d3ce57b7da9f91e0d6cea8b3b249b461a3bd0372b2a76758de3113532ab8ddb3188cec04333d8d8930673fa753cdda63376e388d99a995642c7c43859ddc8bdde9101a7ebab17d4894f75dacde90fa971ed682fec74e25bd782a6c56d8e5fedd9ceafb8a71afdbeda2bc8c52047c4918c1ca24846c83e1b94fcbae7fb12d01f425e799de44da53c08a063e1ed1c47cc2fb55235c1b305afd000ef8f8cdd7a6234a37198b7bd8acf59a52c325b34f76cf5879128463d3948b4c401d9c8c8b1ebefe4405252612148a2fc80edd07131faae7998ab5e42519b9d536e4a", 0x1020}, {&(0x7f0000001540)="f286a84d365450931351d56a392f125053e372a5d738c37505db0309af2da86a2fb994a60b88c2d1b12db552a6c56314abef9b6b532015b4391f6421738d526a3c4905254667ff45ff720515bbb9e9803abae3f6c56a2119054f120fc0254eac0791fea04fc293d35a97e02dfc2b60dc5eb83364686fb7960fc4fc3dfa1dcb0bc1dd509003092b466336283c87db76ca57cc7b0ec75d90e34d356d6696aa10951cdbb4d415589474d7a00326ea53830bf3ba7fe924eb4f146802e79e7177e20f998dd2f99a7614716dfd2ddbee5cc8c83c422d2c3edc86555bfe1a04325009426b745134a4fa7ab813986a9eabe105a05374", 0xf2}, {&(0x7f0000000000)="fcc08cbdb3c54d40fc4c28d500eab996a057e82ea0f2018b538efafb69d3d143ab519ce9b7ffda20bcf2e3a8c037b71be2ddae827928d412c1c9a85def5ba42b7577146b901a", 0x46}, {&(0x7f0000000980)="9160123d76061585eaf66ae5661e9ef1dcb68a5ffeafff2953cf2e1d8a09ae56a62de6211d18c47e0f3491f0ea03e6790e5c82c2e7d1212652cfacc7743261bc7250207396761e126a9d84b718819d4edbd78a680b79e1459388cd1540571bc7b6b22be82fdc23a0dea1e96238ef53fb6547dc8aaeb3c796eb7be3628b9ce4b2ad3af54bb93a7b609ec98c4fd6e6f40b78a136ec58ac977c0f03880adda9eccffaab3d25acbd77ff269c9d99d2e3e1c9391c7ba8b006b705cab5266892846bbca602408217d66179330b08563d3a2d036050e08f5a632a2d9b8f4399eb7eba6d146046c29decb9837d0127d596bbf3fa47843a5cdf896c9f39db9bf43040c135b43dd710a612c93cbd250efd513478460b88afa894267d6d3b5caa4df2f742ff9f3e6be94897da6794576524701994971c7ef2dfed4f359e8504ee8e93001e9ff61410a2465cfddedb29910228dfc73c71e88be80ce1905310216847c784c3b3be3d4491d25c99901497a2c4856b2989ff73d183474a1870befe42a2236851fa6240071ab8abe4e31179c2f53e634e70a12583be24974f6f85153aa453611c0c8a03b2294a3b234c4ae161d9265cced961b0df5d4515c76984e5e4e15f50b23d890b2bfe7b6c30a6409a5b74fe5a4a8c036b93cd9fb91ea84271269c52f8222916306f23edd3000f7b41cc4b3a4e5fa88a5c2d7678f0227a3782b1f8d6864b7fd8c2e76eff5021235dc3aaf4995d721d6aabaacc97373a107af76ec2c2520e400fbc749f8dd479d0cf5da54c4a73e41270d0391963e0cb8542be65f43fb2538d605085c22bc116b371c9aa02811aa86bd54a65a4b6983168180a3be1560b526de700f1949bb32d5d9f38f6a5c6281624c6fcb44aa657468ffafafdc0637748df145f718082709de89edc894c517a0f7ee0835e1fde37ba18740263c5dbb872aaf3640c55df4ae91f1c4d8a6d060fd46d2cfe9928475da6c0d001f9e2777437a663cabc593f8aa84f3799263cfc27076568723a08221b4bd190a3d24bc7f9bf91698e19479435a59a8ca4fdc38005865d1e61eaaa9e4d71c99bca17b34045c700de76b4d90df4ff250341605ae4a680f6bdfe6ea5e6ff77bec1f6963c790519181faa2ec1a2f9b16d1b824dabfcef556e91ef4bce02b702146012f691ca05e0f873b793d6051c6448876a93fcaf32ad9b129aad644b9761508e0cbdda42424f5ca9ac5a0cb67fd5ef8d26078c16cf525df596a885bb192168ba4a86e99c0827b56331e6fce281bfdbe7601e6dd9f80e645d073e5fcfb80f23ed8d6a1c4c6f1a0593f126a47bdc15964106058ba5a3f5e3937e4d1936709df941849452f2c9c392aa70906c85e0edba5772c67f4ea0fe3719344d03a358fb664d793c4aa54e216aa56f8cf2b407ff5d4a529911af166a61b7ed4c3ddee3a52bb0c74950249d112f60d18b35e6c199bbaafda43d0f0e1e29b0bed4faeed45e840be722bfab97e30a01e8fdea1117a6b8581d6a9497c3921d84b377cd7bc1a1f3df421fa0a31f196c9f011339a202c77d552d5e30df29ad6a5463ed0bc728969bcb38626a82fab1855df909acb56dbbbe1338015737b460b9085379f144f08f4fe6fbe9c9df241061196a35365a34eaf0c65f97d15c811b98869c4a49ddae0601994d545d202d856fb5e3c96921e56b80ec978feb36f5daef50f995dc3cad442da07de75b97f810dce38413e8cc64ce3d32372a5b7b08ee898f5fbb37c4cb70e8b555322af7968013968ab4d07441409a43d6c68dc5b5cc02ed048e6a296f1f735fae1874c921c15dc6c4422c87c803c1783b344f60f90a3d2efafad2938d8269bda4df1bb247b482f36c1713859723951d31241fe7b3fc4b7c3bf11f055de8365b2b69328e5755fbab9dfb0b03205b72c16558ca2e98dc059fa5487c37ce89acb18613cc62486ce09e75a72a8be009793b00c74e9adc2b93471102f16e83cc9ef0ac2c2b7cb5aa757a5d51cd7f6336151beaf55eabd134a6e6b93593a151653837ed5d494a03bcf061d63d7a8e501973506642f68d6b2d490490cdc9980a624714008335f98caa71d22e8651849caa054b5c119dd154a80afd2ae95506728c0acf02eecd8887b821c764a2be51ba755b9db883a75748d3c20c2205fbdd1ad4ea848883642e27adf313fddfba60f314a80a463f056179643abd18bf0454dc13dd799d25c244460d8d2619238bb5aebe667fb38048d9dc84242dbcb17ecdb64170bb6b80fd710f597cc96d081da2ba082ea62605bb3388f43d1849f8b80ce8f8dadaefa84b0cf5e12c2a3db678dc0859bf927320cf765fedaaefad94d0da4ab50368105e4b5981feeb3edef40cf25780b6b00752e4839a1f3e0c3def6e5233db0490dc8ce93dedf0d44a05d2a132a3649eda3ab5da9e7762edd08b83a8cf2e7d253a78fdddc2c6ce97cbff41532692140ffd82bb4249328d01a9878e3f59d7159c493bec6184cd3d71e9213b4b6f70a7c26404ecde93e81e897e497f3b44ee04bf394cbe8540a49d31e33aa875b0c0e43e0c6af3035bc5b7992a08d8cf0b5a88f0e5b88b6da6de61c0d1b6289be8d9effcaadd6b62f47b7169092f07ac1b1469f52b4b2369fd2e0fae1bc43cc415586b11e4fcac1b4148d5e7417e3a0a0ba64973581546781ae2a069073a0a557ed02b2462a2f26ac44729308c2347f4a7d7032b521ff58a8d1b3f095c376216c44762c889ff33f4688ba61dd2f1da40892e49a0bc0ef08940af0352cd6393eb1aef2fe707b138ba8119f3907993810a70bc4f1625ee0618230b58016277b50f89d8a7b92601c697b9ee5915a8cdf0b0d6f23005bc29ad38f7f3a7085efa550ea390ec31873f999733b874242b1eb5dc9dd5a8deb0c14d37e250d98060bbc30e8b5e6155267b424cf16deea1c1b003407f1308f93e8fa0ed90fb3789c7b05a5c6cb65fd34df7555dc14ee95eebbb0b2f0d75e3bffe98aaf4eaad9d39ceabed5967907007aeaff27bb2d0f11cd021bf1adfea43f09a6860db43ee3be9e520399bfe1f4e53b9981ba8f27f1c5e81c63f5e3292ada5c1876436b1d2d5504ab0affda2663d82dfd368cf67113f6dc50db632cd05b71d340afda503c2076f8bdb0f7dfb915defc7c1c9231234ec1b9bc51c9fd412ca09d7b0fd44af63461ece300c5e13c97be28a46be7d7811b648aef748905a3edc10c9854c2019b8da98f39ddae20857a9e10c0e0d31d21732b4464e69a7427f947d0d1428d785238cbe29febfe78002738319659cecaf443da90ce463923c09849bcd23590513bf05b9a0030329d29422057bfad1e9201efde01056efb4338152a90f3958d92affc0d28026067b9fb53847c3eb773edc09361b824de631476c50a9536d3432204f02d55679966fdac3284f5a8e6bb1a0fa8765f1bdf044f58610340b4405c1865340ee14aa612738218e58822cea59b2233bde7f515dca110b5b69cd023c65fe76c05b3101d2cb8839179c19e1253eedd8aa49eec5e61a234404b5050d3ae406b39ef356a61b9b70ff362dacc91ac18bd993d3411624b33516f5ce027fd14b98b71a127f100d0cd7bc06650ffd79b5ac", 0x9ed}], 0x7)
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000080)={0x7ffffffb, 0x0, 0x80000005, 0xfffffff8, "0100000063026d00000100000000000000777d00"})
writev(r0, &(0x7f0000002f40)=[{&(0x7f0000000640)="8e78dbebae5d90546f15d52a70c0d6c01f58a61f32323c0794131b931fec61639d2f39a6047225d023e386c4556448c215cf2412d15d80dbf9f84b8741dd0b85594b84517605a7a7397ed4fb170e22d274b430934323f2f4fb5606ef5596615f1483c475b95ef23aea27e3b7a7c35f66ed518b4f97d9fa5945621a1173a9e1e34a3761486699739b5dd0f87a0d15ddb90c5f0b6935666ed373a8123f5a6167a180b5021fd0acff9d9731a5bd60e3ec94e2b7771d82937d6c7ff1b9422fdfbfa590964ca5b01b1ec5b60ef0bdd0be043b45cf8d18a5e672cff3c0aad2f41623f7ba3ba28c9b2419a3492b027f5169f1c7a49d496800dc3655536d25fd59b9cc0aa0d3bf78ad55f60a9ed41e1bb19b1c13d2d39a03a32123e8c58bbbd8603eaf87c9feff40795f8ef85e2c71683f9b14eefdc5e149b900000000000058d83b20ec6e38ea7ffa40bfb8663e568765f8dd8d20143f82711d82d74b2d81", 0x15b}], 0x1)


chmod(0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000140)=[{0x80}, {0x44, 0x0, 0x6}, {0x12e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x3e, 0x0)
write(0xffffffffffffffff, &(0x7f0000000180)="23009100007adb020317bdda2b7e", 0xe)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x6}, {0x2, 0x0, 0x0, 0x40804}]})
ioctl$DIOCMAP(0xffffffffffffffff, 0xc0106477, &(0x7f00000000c0)={0x0, r0})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


r0 = kqueue()
kevent(0xffffffffffffffff, &(0x7f0000000140)=[{{r0}, 0xffffffffffffffff, 0x4b}], 0x0, 0x0, 0x0, 0x0)
r1 = kqueue()
kevent(r1, &(0x7f0000000140), 0x8f, 0x0, 0x0, 0x0)
r2 = kqueue()
kevent(r2, &(0x7f0000000140), 0x8f, 0x0, 0x0, 0x0)
r3 = kqueue()
kevent(r3, &(0x7f0000000140), 0x8f, 0x0, 0x0, 0x0)
r4 = kqueue()
kevent(r4, &(0x7f0000000140), 0x8f, 0x0, 0x0, 0x0)
kevent(r1, &(0x7f0000000340)=[{{r0}, 0xffffffffffffffff, 0x2}], 0x8, 0x0, 0x9, 0x0)


faccessat(0xffffffffffffffff, &(0x7f0000000000)='./bus\x00', 0x0, 0x0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd02)
syz_emit_ethernet(0x23bf, &(0x7f0000000100)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaabb86dd6085ceb2ff61000000000000000000000000000000000000ff020000000000000000000000000001001d000000000000010300000001e31dd3d88e1f8a59f12d913d98105d13d89788b69a72e34bcc921389d20a071b3f7a6b75bc7aa609b48143d932edbf6f0e881f67cd0d55956c7f26ac75f6a2a89056748b9249d0d36f8d3f0b931021c871c35786c46ababc7b51a4996ff063e6259fa3dac1259cec17067b4dda84e1dfd38e49f53f576fb7e1c6704bce1bf58f0938a19d9532"])
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x2, 0x0)
ioctl$VNDIOCSET(r0, 0x81946467, &(0x7f0000000180)={0x0, 0x0, 0x0})
clock_gettime(0x3, &(0x7f0000000040))


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000440)={0x2, &(0x7f00000000c0)=[{}, {0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4f}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8efdb4cf71c37082", &(0x7f0000000000)=0x2, 0x0, 0x37)


sendto$unix(0xffffffffffffffff, &(0x7f00000003c0)="b1000504", 0x4, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x17a, &(0x7f0000000380)=ANY=[@ANYBLOB="f3a2a8908a86aaaaaaaaaabb86dd601ab5b60000000000000000000000000000000000000000ff020000000000000000000000000001001d000000000000040100c204"])


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}, 0xf8ffffffffffffff})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x8040691a, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000001600)={0x3, &(0x7f0000000100)=[{0x54}, {0x15}, {0x6}]})
syz_emit_ethernet(0xe, &(0x7f00000000c0)=ANY=[])


msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}})
r0 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1000, &(0x7f0000000000)=0x1, 0x4)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x30}})
r1 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x1, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r0 = open(&(0x7f0000000200)='./file0\x00', 0x20000, 0x89)
ftruncate(r0, 0x0)
openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
dup(0xffffffffffffffff)
mkdirat(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSBLEN(0xffffffffffffffff, 0xc0044266, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSFILDROP(r1, 0x80044279, &(0x7f0000000840)=0xff)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
ioctl$WSKBDIO_SETKEYREPEAT(r0, 0x800c5707, 0x0)
clock_getres(0x4, 0xfffffffffffffffe)
r2 = openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x8981, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r2, 0x80105727, &(0x7f0000000000)={&(0x7f0000000100)=[{0x4}, {}], 0x2})
r3 = semget(0x0, 0x6, 0x3d4)
semop(r3, &(0x7f00000001c0)=[{0x1, 0x4, 0x1800}, {0x1, 0x3}, {0x4, 0x6838, 0x800}, {0x1, 0xfff6}, {0x2, 0xf26c}], 0x5)
r4 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmat(r4, &(0x7f0000001000/0x3000)=nil, 0x0)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x6)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000080)='./file0\x00', 0x1, 0x0)


r0 = socket(0x18, 0x2, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000000), 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000700)=[{0x61}, {0x20}, {0x6, 0x0, 0x0, 0xfffffffe}]})
write(r0, &(0x7f0000000740)="76e5dead6f01f8607d2100000063", 0xe)


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
setreuid(0x0, 0xee01)
r0 = open(&(0x7f0000000280)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000028000/0x4000)=nil, 0x4000, 0x0, 0x10, r0, 0x0)
r1 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
pwritev(r1, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{0x7c}, {0x30, 0xfe}, {0x16}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f0000000080)=ANY=[])


mknod(&(0x7f0000000000)='./file0\x00', 0x6000, 0xe02)
open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
mknod(&(0x7f0000000040)='./bus\x00', 0x6000, 0xe02)
ktrace(&(0x7f00000000c0)='./bus\x00', 0x0, 0x0, 0x0)
close(r0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
utimensat(0xffffffffffffff9c, &(0x7f0000000100)='./file0\x00', &(0x7f0000000140)={{0x20, 0x1}, {0x7fff, 0x3}}, 0x0)
r1 = socket(0x0, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0x3f, 0x0, 0x0)
syz_emit_ethernet(0x3e, &(0x7f0000000100)=ANY=[])
socket(0x0, 0x0, 0x0)
r2 = msgget$private(0x0, 0x5bd)
msgsnd(r2, &(0x7f0000000d00)=ANY=[@ANYRESHEX=r2], 0x401, 0x0)
msgsnd(r2, &(0x7f0000000000)=ANY=[], 0x401, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000200)={0x4, 0x2, 0x6, 0x19}, 0x4, &(0x7f0000000380), &(0x7f0000000340), 0x0, 0x0)
openat$vnd(0xffffffffffffff9c, &(0x7f0000000040), 0x400, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
open$dir(0x0, 0x0, 0x0)
pwrite(0xffffffffffffffff, 0x0, 0x0, 0x0)
msgrcv(r2, &(0x7f00000002c0), 0xaf, 0x0, 0x1800)
readlink(0x0, 0x0, 0x0)
r3 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r3, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r3, 0x0)
connect$unix(r3, &(0x7f00000000c0)=@file={0x0, './file0\x00'}, 0xa)
msgsnd(0x0, &(0x7f00000006c0)=ANY=[@ANYBLOB], 0xe1, 0x0)
sysctl$hw(&(0x7f00000002c0)={0x6, 0xe}, 0x2, &(0x7f0000000000)="00000000000000a9ad0898d06119f0e45ae44d8a8f18560b2edcb0392c4a", &(0x7f0000000040)=0xfeb5, 0x0, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000000)={0x1, &(0x7f0000000080)=[{0x2, 0x80, 0x2, 0x8}]})
write(r0, &(0x7f0000000180)="23009100007adb020317bdda2b7e", 0xe)


r0 = kqueue()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x11a}})
r1 = socket(0x18, 0x1, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
setrlimit(0x0, &(0x7f0000000180)={0x10000007fff, 0x100000})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x1, &(0x7f00000000c0)=[{}]})
socketpair$unix(0x1, 0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000000c0), &(0x7f0000000240)=0x5d)
r2 = getgid()
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000380), &(0x7f00000003c0)=0xffffffffffffffa5)
getgroups(0x7, &(0x7f0000000000)=[0x0, 0xffffffffffffffff, 0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0x0, <r3=>0x0])
setregid(r3, 0x0)
setregid(0xffffffffffffffff, r3)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0xab42, 0x0, 0x0, 0x0, r2, 0x89, 0x7}})
sysctl$vm_swapencrypt(&(0x7f0000000040)={0x6, 0x1b}, 0x3, &(0x7f0000000280), 0x0, 0x0, 0x0)
getsockname$inet(r1, &(0x7f00000000c0), &(0x7f0000000140)=0xc)
r4 = socket(0x18, 0x1, 0x0)
r5 = socket(0x18, 0x1, 0x0)
connect$unix(r5, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r5, &(0x7f00000000c0), &(0x7f0000000600)=0x5e)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sysctl$net_inet_icmp(&(0x7f0000000000)={0x4, 0x12, 0x1, 0x7}, 0x1, &(0x7f0000000040), 0x0, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000080)={0x4, 0x2, 0x6, 0x12}, 0x4, &(0x7f00000000c0)="eca2c906", &(0x7f0000000140)=0x4, &(0x7f0000000180), 0x0)
r6 = open$dir(&(0x7f0000000240)='.\x00', 0x400, 0x0)
kevent(r0, &(0x7f0000000000)=[{{r6}, 0xffffffffffffffff, 0x6f}], 0x7, 0x0, 0x0, 0x0)
mknodat(r6, &(0x7f0000000040)='./file0\x00', 0x6000, 0x0)
r7 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r7, 0x0, 0x200000000000c, &(0x7f0000000080)="eaef125c00000000", 0x8)
setsockopt$inet_opts(r7, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
setsockopt$inet_opts(r7, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0xc)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000080)=[{0x20}, {0x35}, {0x8186}]})
syz_emit_ethernet(0xe, &(0x7f00000000c0)={@broadcast, @remote})


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
socket(0x18, 0x2, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f0000000380)=""/61, 0x3d}], 0x1)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1800000029"], 0x3e}, 0x0)
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000006c0), 0x1, 0x0)
writev(r0, &(0x7f0000000080)=[{&(0x7f00000001c0)='M', 0x1}, {&(0x7f0000001600)='L', 0x1}], 0xf)


sendto$unix(0xffffffffffffffff, &(0x7f0000000180)="8f0ec34b5999bd6ae65ccd6a4f94b931c46db1676f9d80cc731fc642bbe214939d6417615c308ae214031c74bf3642d76aae725700064dc822d011867ed9b089133e89f9200abee655f4018c59f57bd497223c181fb38e5ba5a6492d538ce6c9e15ae47f7b2585f631774eb70a2bdac1ba257a70ac8bb6616d8caf6e69f7eea7d1e2de33d3a18119089347b286beb4a47925543d7a882be99b7e577095d8a04af02bb955f5ddcafafac51808671d5c877bf03c0ee5ec", 0xb6, 0x0, 0x0, 0x0)
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$VMM_IOC_WRITEREGS(r0, 0x82485608, &(0x7f0000000180)={0x6, 0x0, 0xb, {[], [], [], [], [{}, {0x0, 0x0, 0x0, 0x1}], {}, {0x0, 0xffffff01}}})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x28}, {}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])


socket$inet6(0x18, 0x1, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000))
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000000)=0x7, 0x4)
mprotect(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x1)
sysctl$vfs_nfs(&(0x7f0000000000), 0x7, &(0x7f00000025c0), 0x0, 0x0, 0xffffffffffffff2d)


r0 = socket(0x2, 0x2, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r1 = socket(0x18, 0x3, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
setsockopt(r1, 0x1000000029, 0x1b, &(0x7f0000000000)="5ab7776a", 0x4)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r0, &(0x7f0000000000), 0x10)
write(r0, 0x0, 0x0)


openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000080), 0x40, 0x0)
mknod(&(0x7f0000000200)='./file0\x00', 0xc000, 0x412dff)
pwrite(0xffffffffffffffff, &(0x7f00000003c0)="062e8f5ea745a61429", 0x9, 0x0)
r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x402, 0x0)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000000), 0x2cfea}], 0x1000000000000013)
open(&(0x7f0000000140)='./file0\x00', 0x78e, 0x0)
r1 = getpid()
ktrace(&(0x7f0000000040)='./file0\x00', 0x0, 0x20, 0x0)
ktrace(&(0x7f0000000280)='./file0\x00', 0x0, 0x928, r1)
pipe(&(0x7f0000000000)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r4 = getpid()
mknod(&(0x7f0000000180)='./file0\x00', 0x8000, 0x4e6)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r4)
recvmmsg(0xffffffffffffffff, &(0x7f0000000080)={&(0x7f0000000100)={&(0x7f0000000480)=@un=@file={0x0, ""/537}, 0x21b, 0x0, 0x0, 0x0, 0xffffffffffffff3f}}, 0x10, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
fcntl$setstatus(r2, 0x4, 0xc0)
r5 = getppid()
fcntl$setown(r3, 0x6, 0x0)
write(r3, &(0x7f00000006c0)="7c84cf179279b50eda5dd1951a661d2e3a20851082c188f8b3d8a063d2025ff0d27a44bc29bdcac27fcb7aaa95cb2007be22c5553cd2f66a1f419883d4275218a89d7a7803f069d851ff628dd309c40f6e3c932af00cb6219ae6e21d2c28d492cd5404b16dfa627d93b1e8ad2ea49d2344c1a3b234bd6f1c70fd4252844a6e6ab7b8997bc55fa22ce951ee038d289078b95510b0f2473ce1348434f0ec4a08ca7991af3f8c322b496466f804c4b700cc9391855bd0ee339196de2b5ec2d8425c711d3f9e051eb055d45c693d7549712f5284a9fbca7d15c5bf1a9c8e3b3c1a43983056782e046c29e3d57082f7743b8bf6d994cd3c26", 0xf6)
syz_emit_ethernet(0xff, 0x0)
execve(0x0, 0x0, 0x0)
fcntl$setown(r3, 0x6, r5)
semget$private(0x0, 0x2, 0x68)
semctl$SETALL(0x0, 0x0, 0x9, 0x0)
r6 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
setuid(0xffffffffffffffff)
ioctl$BIOCLOCK(r6, 0x20004276)
ioctl$FIONREAD(r6, 0x4004667f, &(0x7f0000000000))


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(&(0x7f0000000080)='./file0\x00', 0x0, 0x40000800, 0x0)
setreuid(0xee00, 0x0)
r0 = getuid()
chown(&(0x7f0000000180)='./file0\x00', r0, 0x0)
chmod(&(0x7f0000000200)='./file0\x00', 0xa5)
r1 = getuid()
seteuid(r1)
truncate(&(0x7f0000000000)='./file0\x00', 0x1000)


ioctl$FIONREAD(0xffffffffffffffff, 0x80206913, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000002c0)={0x2, &(0x7f0000000080)=[{0x44}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000300)=ANY=[])
sendmsg$unix(0xffffffffffffffff, &(0x7f0000002a40)={&(0x7f0000000000), 0x10, 0x0}, 0x0)
r1 = socket(0x2, 0x2, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000695000/0x3000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f00005fd000/0x1000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f00006a7000/0x1000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f0000218000/0x4000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f00002e5000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000376000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000041d000/0x1000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000ff8000/0x4000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil, 0x3}], './file0\x00'})
writev(0xffffffffffffffff, &(0x7f0000000180)=[{&(0x7f0000000000)="9da8e3e9ed", 0x5}], 0x1)
bind(0xffffffffffffffff, &(0x7f0000000080)=@in6={0x18, 0x2}, 0xc)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
open$dir(&(0x7f0000000040)='./file0\x00', 0x8, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
syz_open_pts()
poll(&(0x7f0000000000), 0x0, 0x0)
syz_open_pts()
syz_open_pts()
poll(0x0, 0x0, 0x0)
r2 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
dup2(r2, r1)
sendmsg$unix(r1, &(0x7f0000002a40)={0x0, 0xffffffffffffff89, 0x0, 0x6e, 0x0, 0x700000000000000}, 0x0)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x3})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x27}, 0x4, &(0x7f0000000000)="71f91e3471ac0058bc5a91501d942400b5e1a0757cb9af769c7afec37082", &(0x7f0000000080)=0x306, 0x0, 0x2e)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504000004000000000007000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000022acf2047804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0e032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4fcf668246c0900e1937c727a4bdb8d000008e37123fc", 0xad, 0x0, 0x0, 0x0)
r0 = socket(0x11, 0x3, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sendto$unix(r0, &(0x7f0000000000)="b1000504000004000000000001000000331c13fecea10500fef96ec0c72fd3357ae30200004e3003000000acf20b7804be38164991f7c8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a42102000000720fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b4cc702fac500002021fbfa0c0f00008abfba221554f4e0f668246c0900000008e371a3f8343712051eea040000000000", 0xb1, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000080)=[{0x50}, {0x30}, {0x6}]})
syz_emit_ethernet(0x62, &(0x7f00000000c0)=ANY=[])


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {}, {0x0, 0x0, 0x8}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


r0 = socket(0x2, 0x1, 0x0)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB="0000000000000001"])
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000000)="b886b4e47f", 0xfffffffffffffee7}], 0x1)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
r1 = socket(0x2, 0x1, 0x0)
bind(r1, &(0x7f0000000000), 0x10)
listen(r1, 0x0)
syz_emit_ethernet(0x3e, &(0x7f0000000180)={@broadcast, @local, [], {@ipv6={0x86dd, {0x0, 0x6, "1d9755", 0x8, 0x0, 0x0, @rand_addr="085adba551584819b50651f24e969773", @loopback, {[], @udp={{0x3, 0x3, 0x8}}}}}}})
write(0xffffffffffffffff, 0x0, 0x0)
r2 = socket(0x2, 0x1, 0x0)
connect$unix(r2, &(0x7f0000000000), 0x10)
socket(0x0, 0x0, 0x0)
dup(0xffffffffffffffff)
r3 = socket(0x2, 0x1, 0x0)
connect$unix(r3, &(0x7f0000000000), 0x10)
dup2(r0, r1)


ioctl$BIOCSETWF(0xffffffffffffff9c, 0x80104277, &(0x7f0000000000)={0x1, &(0x7f00000000c0)=[{0x3, 0x0, 0x0, 0xfffffffe}]})
socket$inet(0x1e, 0x3, 0x0)
poll(&(0x7f0000000000)=[{}], 0x20000000000000fe, 0x0)
socket(0x1e, 0x3, 0x0)
socket(0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
ioctl$TIOCSTSTAMP(0xffffffffffffffff, 0x8008745a, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
openat$vnd(0xffffffffffffff9c, &(0x7f0000000200), 0x4a0, 0x0)
open(&(0x7f0000000180)='./file0\x00', 0x75f493fec6515f78, 0x0)
r0 = getppid()
msgctl$IPC_SET(0xffffffffffffffff, 0x1, &(0x7f00000000c0)={{}, 0x0, 0x0, r0, 0x0, 0x3, 0x2, 0x100000000})
r1 = fcntl$getown(0xffffffffffffffff, 0x5)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0xb32, r1)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
pipe(0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000180)=[{{}, 0xfffffffffffffff9, 0x9, 0x0, 0x0, 0x2}, {{}, 0x0, 0x8, 0x0, 0x0, 0x10}], 0x0, 0x0)
r2 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000000), 0x10215, 0x0)
ioctl$VNDIOCSET(r2, 0x81946467, &(0x7f0000000180)={0x0, 0xffffffffffffffff, 0x0})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f00000000c0)=[{0x1c}, {0x3d}, {0x16}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f0000000080)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
r1 = socket(0x18, 0x2, 0x0)
dup2(r1, r0)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x9f9d})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x1000000000029, 0x4, &(0x7f0000000040)="00fb6c2e", 0x4)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
r1 = socket(0x18, 0x2, 0x0)
r2 = socket$inet(0x18, 0x3, 0x102)
r3 = dup2(r2, r1)
sendmsg$unix(r3, &(0x7f0000000840)={&(0x7f0000000000)=@file={0x0, './file0\x00'}, 0x9, 0x0, 0x0, &(0x7f0000000a80)=ANY=[], 0x118}, 0x0)


open(0x0, 0x0, 0x0)
chmod(0x0, 0x0)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd02)
r0 = open(&(0x7f0000000240)='./bus\x00', 0x0, 0x0)
preadv(r0, &(0x7f00000001c0)=[{&(0x7f0000000400)=""/4096, 0x1000}], 0x1, 0x20000000000)
mknod(&(0x7f0000000040)='./bus\x00', 0x0, 0x205310)
open(0x0, 0x10, 0x0)
ioctl$TIOCSFLAGS(0xffffffffffffffff, 0x8004745c, 0x0)
getegid()
clock_gettime(0x0, 0xfffffffffffffffe)


kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f00000001c0)={0xc8, 0xffffffffffffffff})
r0 = kqueue()
kevent(r0, &(0x7f0000000000), 0x1ff, 0x0, 0x89c, 0x0)
kevent(r0, 0x0, 0x0, &(0x7f0000000040), 0x200, 0x0)


pipe(&(0x7f0000000140)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
write(r0, &(0x7f00000002c0)="7c84cf179279b50eda5dd1951a661d2e3a20851082c188f8b3d8a063d2025ff0d27a44bc29bdcac27fcb7aaa95cb2007be22c5553cd2f66a1f419a83d4275218a89d7a7803f069d851ff628dd309c40f6e3c932af00cb6219ae6e21d2c28d492cd5404b16dfa627d93b1e8ad2ea49d2344c1a3b234bd6f1c70fd4252844a6e6ab7b8997bc55fa22ce951ee038d289078b95510b0f2473ce1348434f0ec4a885ee84fd08fc50f08ca7991af3f8c322b496466f804c4b700cc9391855bd0ee339196de2b5ec2d8425c711d3f9e051eb055d45c693d7549712f5284a9fbca7d15c5bf1a9c8e3b3c1a43983056782e046c29e3d57082f7743b8bf6d994cd3c26c85609eaa11e6f7bc4", 0xfffffdaf)
open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r1 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x100, r1)
nanosleep(&(0x7f0000000000), &(0x7f0000001180))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{0x87}, {0x25}, {0x4000006, 0x0, 0x0, 0x3feffe}]})
write(r0, &(0x7f0000000180)="23009100007adb020317bdda2b7e", 0xe)


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x27}, 0x2, &(0x7f0000000100), 0x0, 0x0, 0x0)
socket$inet6(0x18, 0x0, 0x0)
shmctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4}})
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x1, &(0x7f0000000000)=[{}]})
ioctl$VMM_IOC_INFO(r0, 0x8020560b, &(0x7f00000000c0)={0x0, 0x0, 0x0})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{0x20}, {0xc}, {0x6, 0x0, 0x0, 0x7}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000380)=[{0x3}, {0x25}, {0x8006}]})
syz_emit_ethernet(0x56, &(0x7f00000003c0)=ANY=[])


socketpair$unix(0x1, 0x0, 0x0, &(0x7f00000000c0))
sysctl$net_inet6_icmp6(0x0, 0x0, &(0x7f0000000080)="65feaba9a71942a5", &(0x7f0000000100)=0x8, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000200)={0x4, 0x2, 0x6, 0x19}, 0x4, 0x0, 0x0, &(0x7f00000002c0)="e2420dc5", 0x4)
socket$inet(0x2, 0x3, 0x0)
mkdir(&(0x7f0000000240)='./file0\x00', 0x108)
r0 = getuid()
seteuid(r0)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000180)=[{}, {}, {{}, 0x0, 0x0, 0x0, 0x20000000210}], 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x2, 0x0)
sysctl$kern(&(0x7f0000000040), 0x1, 0x0, 0x0, 0x0, 0x0)
r1 = socket(0x18, 0x3, 0x3a)
setsockopt(r1, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MFC(r1, 0x29, 0x68, &(0x7f00000000c0), 0x5c)


socket(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r0, 0xc018696c, &(0x7f00000001c0))
r1 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r1, 0x8020699f, &(0x7f00000001c0))
getdents(0xffffffffffffffff, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)


r0 = socket(0x18, 0x1, 0x0)
listen(r0, 0x0)
accept$unix(r0, 0x0, 0x0)
shutdown(r0, 0x2)
setrlimit(0x8, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = open(&(0x7f0000000200)='./file0\x00', 0x20000, 0x89)
ftruncate(r1, 0x0)
openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
dup(0xffffffffffffffff)
openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x8981, 0x0)
r2 = semget(0x0, 0x6, 0x3d4)
syz_emit_ethernet(0xde, &(0x7f0000000240)={@random="10fa6100a181", @random="faedbb64e256", [], {@ipv6={0x86dd, {0xb, 0x6, "8bc31c", 0xa8, 0x47, 0x5, @loopback, @remote={0xfe, 0x80, '\x00', 0x0}, {[@routing={0x4, 0xc, 0x0, 0x5, 0x0, [@rand_addr="81c93b5a739df63aefd3ff954f984958", @local={0xfe, 0x80, '\x00', 0x0}, @local={0xfe, 0x80, '\x00', 0x0}, @remote={0xfe, 0x80, '\x00', 0x0}, @remote={0xfe, 0x80, '\x00', 0x0}, @loopback]}, @dstopts={0x3a, 0x1, '\x00', [@enc_lim={0x4, 0x1, 0x6}, @jumbo={0xc2, 0x4, 0x2}]}], @tcp={{0x1, 0x0, 0x41424344, 0x41424344, 0x0, 0x0, 0xa, 0x40, 0x40, 0x0, 0x2, {[@eol, @md5sig={0x13, 0x12, "57712f065118837da260d5578790c467"}]}}}}}}}})
semop(r2, &(0x7f00000001c0)=[{0x1, 0x4, 0x1800}, {0x4, 0x3}, {0x4, 0x7, 0x800}, {0x1, 0xfff6}, {0x2, 0xf26c}], 0x5)
shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)


mkdir(&(0x7f0000000180)='./file0\x00', 0x0)
mkdir(&(0x7f0000000000)='./file0/file0\x00', 0x0)
chroot(&(0x7f0000000100)='./file0/file0\x00')
rename(&(0x7f00000000c0)='./file0/file0/..\x00', &(0x7f0000000040)='./file0/file0/..\x00')


sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x13}, 0x4, 0x0, 0x0, &(0x7f0000000140)="53183374", 0xffffffba)
r0 = openat$pf(0xffffffffffffff9c, &(0x7f0000000080), 0x40, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x37}, 0x2, 0x0, 0x0, 0x0, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
sysctl$hw(0x0, 0x0, &(0x7f0000000040), 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
sysctl$net_inet_ip(&(0x7f0000000300)={0x4, 0x2, 0x0, 0x25}, 0x4, &(0x7f00000013c0), 0x0, &(0x7f0000001480), 0x0)
setitimer(0x1, &(0x7f0000000280)={{0x2, 0x4}, {0x0, 0x9}}, &(0x7f00000002c0))
r1 = getuid()
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000140)={{0x0, r1, 0xffffffffffffffff, 0x0, 0xffffffffffffffff, 0x7, 0x3ff}})
r2 = msgget$private(0x0, 0x0)
msgrcv(0x0, 0x0, 0x0, 0x0, 0x0)
fsync(r0)
pipe(0x0)
ioctl$FIOASYNC(0xffffffffffffffff, 0x8004667d, 0x0)
r3 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(r3, &(0x7f0000001580)=[{0x0}], 0x1)
r4 = dup(r3)
r5 = dup2(r3, r4)
sysctl$net_inet_tcp(&(0x7f0000000100)={0x4, 0x2, 0x6, 0x12}, 0x4, &(0x7f0000000200)="2daeddd3ede9d7aadb3706aae5a410a836af01263fa075d7865d0fec53512ffd74e0b824da9ac3c89baef6c6b43da1bf126a190443766ab70aeccb2ec5c6fe3c9a96e67924087392569678b2c0301336ed240b0b", &(0x7f0000000340)=0x54, &(0x7f0000000380)="6405978227d578ae9a406d57ce8dfdb4d19da87ae6b860f9bbcdfa3f455bfdc1f3881e272185f9e5b28c6fae8b82784ccc012515b244ef78d9ed05fbe5611a85b347165cf8d13cf16e7898b7a49ac041bb3e869503b3d4a865712eca63eaddd7d262b461855e19c1cce73bc62097b6eb9c07d7a3e8", 0x75)
read(0xffffffffffffffff, 0x0, 0x0)
msgsnd(0x0, &(0x7f0000001540)=ANY=[@ANYRESHEX=r5], 0x32, 0x0)
msgrcv(r2, &(0x7f00000001c0)={0x0, ""/14}, 0x16, 0x0, 0x800)
r6 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r6, 0xc0106924, &(0x7f00000001c0))
ioctl$FIONREAD(r6, 0x4004667f, &(0x7f00000000c0))
r7 = kqueue()
kevent(r7, &(0x7f0000000000)=[{{r7}, 0xfffffffffffffff8, 0x8, 0x4, 0x3, 0x3}], 0x101, &(0x7f0000000040)=[{{}, 0xffffffffffffffff, 0x2d, 0x20}, {{r6}, 0xfffffffffffffff8, 0xa0, 0x0, 0x0, 0xdd3}], 0x0, 0x0)
setsockopt$sock_int(r6, 0xffff, 0x10, 0x0, 0x0)


fcntl$setflags(0xffffffffffffffff, 0x2, 0x0)
kqueue()
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
fcntl$setown(r1, 0x6, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffe000/0x2000)=nil, 0x1000}, {0x0, 0x0, 0x3f}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffb000/0x3000)=nil, 0x1}, {&(0x7f0000fff000/0x1000)=nil, &(0x7f0000002000/0x3000)=nil}, {0x0, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffd000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, 0x0, 0x4}, {&(0x7f0000002000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {0x0, 0x0, 0x4000002002}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil, 0x8001}, {0x0, &(0x7f0000ffb000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f0000ffa000/0x2000)=nil, 0x1}, {0x0, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, 0x0, 0x2}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000ffd000/0x1000)=nil}], './file0\x00'})
openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
r2 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000340), 0x20, 0x0)
ioctl$VMM_IOC_RUN(r2, 0x8210560b, &(0x7f0000000000)={0x200001, 0x577, 0x1, 0x1ff, 0x0, 0xff, 0x4})
r3 = openat(0xffffffffffffffff, &(0x7f0000000100)='./file0\x00', 0x10000, 0x250)
close(r3)
mknodat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', 0x2000, 0x1192)
open$dir(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000240)={<r4=>0xffffffffffffffff, <r5=>0xffffffffffffffff})
dup2(r5, r4)
connect$unix(0xffffffffffffff9c, &(0x7f00000000c0)=@file={0x0, './file0\x00'}, 0xa)
seteuid(0x0)
r6 = getpid()
ktrace(0x0, 0x1, 0x40000930, r6)
open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
r7 = socket$inet(0x2, 0x3, 0x0)
sendmmsg(r7, &(0x7f0000000c40)={&(0x7f0000000c00)={&(0x7f00000002c0)=@in={0x2, 0x0}, 0xc, 0x0, 0x0, 0x0}, 0x10}, 0x10, 0x0)


kevent(0xffffffffffffff9c, &(0x7f0000000000)=[{{0xffffffffffffff9c}, 0x0, 0x0, 0x0, 0x9}], 0x0, 0x0, 0x0, 0x0)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000000)={0x0, 0x80000000004}, 0x10)
sysctl$kern(&(0x7f0000000000)={0x1, 0x42}, 0x6, 0x0, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000480), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x6c}, {0x4}, {0x6, 0x0, 0x4}]})
syz_emit_ethernet(0x3e, &(0x7f0000000d40)={@local, @random="94ea09066dbd", [], {@ipv6={0x86dd, {0x0, 0x6, "db8344", 0x8, 0x0, 0x0, @rand_addr="135e80f1d38ddba80b9e61dd0c575a88", @local={0xfe, 0x80, '\x00', 0x0}, {[], @udp={{0x0, 0x2, 0x8}}}}}}})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000001200)=[{0x40, 0x0, 0x0, 0x1}, {0x1c}, {0x6, 0x0, 0x4}]})
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000080)="35b5c242413c1026089a59583cc3", 0xe}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000480), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000140)=[{0x25}, {0x61}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f00000001c0)=[{0x5}, {0x24, 0x0, 0x2}, {0x6}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


syz_emit_ethernet(0x5e, &(0x7f0000000100)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaaaaaa86dd60000900002800006e1aa4058b74adad9a4e721f5b293380ff02000000000000000000000000000100010000000000000001000600000002"])


syz_emit_ethernet(0x3e, &(0x7f0000000000)=ANY=[@ANYBLOB="ffffffffffffaaaaaaaaaabb86dd60b42f2f0008000000000000000000000000000000000001000000000000b7"])


sysctl$hw(&(0x7f0000000000)={0x4}, 0x3, 0x0, 0x0, 0x0, 0x2)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r0, 0x0, 0x4, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0206923, &(0x7f00000001c0))
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x8020697f, &(0x7f00000001c0))
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f00000001c0)=[{}, {}, {}]})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x8020691f, &(0x7f00000001c0))
semget$private(0x0, 0x6, 0x240)
r3 = getuid()
setreuid(0xee00, r3)
getgid()
geteuid()
r4 = socket(0x18, 0x3, 0x0)
connect$unix(r4, 0x0, 0x0)
getsockname$inet(r4, 0x0, &(0x7f0000000000))
getpgrp()
getsockname$unix(r1, &(0x7f0000000100)=@file={0x0, ""/72}, &(0x7f0000000200)=0x4a)
geteuid()
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000080), 0xc)
r5 = semget$private(0x0, 0x4000000009, 0x82)
semop(r5, &(0x7f00000000c0)=[{0x1, 0xffff, 0xe5ce97ab354d96be}, {0x4, 0x4, 0x1800}, {0x3, 0x0, 0x1000}, {0x2, 0x6}], 0x4)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
r6 = socket(0x800000018, 0x1, 0x0)
bind$unix(r6, &(0x7f0000000080)=@abs={0x1f95d27d48731892}, 0x1c)
setsockopt$sock_int(r6, 0xffff, 0x1021, &(0x7f00000000c0)=0x5, 0x4)
semctl$SETALL(r5, 0x0, 0x9, &(0x7f0000000040)=[0x7ff, 0x1000])
semop(r5, &(0x7f0000000180)=[{0x1, 0x1, 0x1000}, {0x2, 0x4, 0x1000}, {0x4, 0x3, 0x1000}], 0x3)
semctl$SETALL(r5, 0x0, 0x9, &(0x7f0000000240)=[0x7, 0x4, 0x7])


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x802069af, &(0x7f00000001c0))
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0xd02)
shmat(0x0, &(0x7f0000001000/0x3000)=nil, 0x0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x32, &(0x7f0000000000)="eb", 0x1)
r2 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1021, &(0x7f0000000000)=0x5, 0x4)


mknod(&(0x7f0000000080)='./file0\x00', 0x6000, 0x202)
mknod(&(0x7f0000000200)='./bus\x00', 0x6000, 0x202)
link(&(0x7f00000000c0)='./bus\x00', &(0x7f0000000100)='./file0\x00')
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)


r0 = openat$vnd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
r1 = dup2(r0, r0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x2, 0x0, 0x20}, 0x4, 0x0, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
socket(0x18, 0x3, 0x3a)
ioctl$LIOCSFD(r1, 0x80046c7f, &(0x7f0000000180)=r1)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000140), 0x782, 0x0)
sysctl$net_inet_ip(&(0x7f00000001c0)={0x4, 0x2, 0x0, 0x1b}, 0x4, &(0x7f00000014c0)="70c34227", &(0x7f0000000400)=0x4, &(0x7f00000004c0), 0x0)


r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x31, &(0x7f00000000c0)="b2", 0x1)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x9})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000880)={0xaabc, 0x800000cd, 0x1ff, 0xd2c, "8717f9050700000000000090d692480d51018000"})
writev(r0, &(0x7f0000000240)=[{&(0x7f0000000000)="355a43f0271d379747000d", 0xb}], 0x1)


r0 = socket(0x800000018, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892}, 0x1c)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg(0xffffffffffffffff, 0x0, 0x0)
close(0xffffffffffffffff)
mmap(&(0x7f0000000000/0x4000)=nil, 0x4000, 0x1, 0x9412, 0xffffffffffffffff, 0x0)
clock_settime(0xffffffffffffffff, &(0x7f0000000140))
socket(0x2, 0x1, 0x0)
dup(0xffffffffffffffff)
listen(0xffffffffffffffff, 0x0)
r2 = socket(0x0, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
getsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x10, &(0x7f0000000000), &(0x7f0000000080)=0xca555f06cd31e785)
r3 = msgget$private(0x0, 0x2)
msgrcv(r3, 0x0, 0x0, 0x0, 0x1000)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000000)={<r4=>0x0}, &(0x7f0000000040)=0xc)
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETWF(r5, 0x80104277, &(0x7f0000000180)={0x3, &(0x7f0000000080)=[{0x87}, {0x44}, {0x6, 0x0, 0x0, 0x1000}]})
write(r2, &(0x7f0000000040)="7f00"/14, 0xe)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, &(0x7f00000000c0))
r6 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x1c00, 0x0)
msgctl$IPC_SET(r3, 0x1, &(0x7f0000000180)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0xfffc}, 0x0, 0x3, r4, r6, 0x4, 0xfc9, 0x9, 0x3fe})
msgctl$IPC_STAT(r3, 0x2, &(0x7f0000000240)=""/56)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
sendmsg(0xffffffffffffffff, 0x0, 0x0)
nanosleep(0xffffffffffffffff, 0x0)
bind$unix(r1, 0x0, 0x0)


r0 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
r1 = socket$inet6(0x18, 0x8000, 0x0)
ioctl$DIOCMAP(r0, 0xc0106477, 0x0)
writev(r0, &(0x7f0000000380)=[{&(0x7f00000000c0)="13", 0x1}, {&(0x7f00000001c0)="40b2d27b8e7d6f7374f6b3a7b96e8abb87d6691c4fc8e1112f1b706249904dfad0f4b69ccab38f3a8624e3ca69e7693bb53722d19d2e4759ce7dc909c7e038acd57433cb2b401e9f5db856b820b88b3e06c9967fbbb1e5ff87be2e687654a69dce4dd1e837a49ab2dce9e6b7541d06ebb67a0dd1d26c4804385580604b7d10ef31", 0x81}, {&(0x7f0000000280)="92dea91ba578227d1cc991dca9c5ecb248ec58212fd15dc25f1bc67d4af58ffee28d5d1f265091b513056b2e64d4475fda1ec76e9e5df8e3388d9679a8cc6c5a7d8660ec7711f242bed4c0d0400028f96604a521beff24bd4bff62557e9d65d12b9be9bf01d2eaa6201b0d24c7699afc63ae1dacd21f0e2cd74cb8b59a9ce3042e54702db056c3886052b1b6a10d8a8718f7ed071f68fde6ea98f040cf88c02cbf3c1fbc5414982b5dfa8c2db74af1931ac0c7b134cdb9e56b9a2f8dd2560b7fd5c0d0cba1329a01f3e6b64f6f5f7c645371", 0xd2}], 0x3)
fchmod(r1, 0x0)
socket$inet(0x2, 0x2, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x4004667f, 0x0)
fcntl$setown(0xffffffffffffffff, 0x6, 0x0)
openat$null(0xffffffffffffff9c, &(0x7f0000000400), 0x0, 0x0)
rename(0x0, 0x0)
openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
getuid()
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x7b042a68de3fe18b, 0x0)
geteuid()
setuid(0x0)
writev(0xffffffffffffffff, &(0x7f00000010c0), 0x0)


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)="10", 0x3}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
openat$pf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
getpid()
ktrace(0x0, 0x0, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
getsockopt(r0, 0x0, 0x9, 0x0, 0x0)


writev(0xffffffffffffff9c, &(0x7f0000000440)=[{&(0x7f00000001c0)="a0dd3dad6ba1364904b8095e4870a1448d", 0x11}], 0x1)
mknod(&(0x7f0000000500)='./file0\x00', 0x1000, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x8020699d, &(0x7f00000001c0))
r1 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0))
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x80206910, &(0x7f00000001c0))
r3 = dup2(r1, r1)
ioctl$FIONREAD(r3, 0x8020699d, &(0x7f00000001c0))


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0xffffffff})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r0, 0x0, 0x4, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc020699e, &(0x7f00000001c0))


openat$bpf(0xffffffffffffff9c, &(0x7f0000000400), 0x0, 0x0)
socket(0x11, 0x3, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
open(0x0, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, 0x0)
sysctl$vm(0x0, 0x0, 0x0, &(0x7f0000000340), 0x0, 0x0)
ioctl$TIOCSTSTAMP(0xffffffffffffffff, 0x8008745a, &(0x7f0000000000)={0xffffffff})
ioctl$WSKBDIO_SETKEYREPEAT(0xffffffffffffffff, 0x800c5707, &(0x7f00000000c0))
ioctl$FIONREAD(0xffffffffffffffff, 0x8040691a, &(0x7f00000001c0))
openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x400, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{0x0, 0x0, 0x0, 0xffffffffffffffff}, 0xffffffffffffffff})
r0 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x8040691a, &(0x7f00000001c0))


sendmsg$unix(0xffffffffffffffff, &(0x7f0000000400)={0x0, 0x0, &(0x7f0000000080)=[{&(0x7f0000000180)="cf70770c0d6e80f391bb19656265c41dbf978bc8ef8f9c4c61decb06778c275ed5f70fff9371f1e7789cea6dd7768a2bf2e1a3b9964f606ae9f98c61b38d595303b8f29af43b7903151d6d610da3bb97b52d896feb0a9a1e917c89ec20b854157d7a67e8468615947f9903f6affcc36234407d72d527e7514e53d668cd96c5795a50dbf714313fa18f65de35968e6c1744ebc1a81ee87beb77bef9e84b047377255e3f21a21862b5acf40b49dbbd24ea82380a299266d9", 0xb7}], 0x1}, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000132000/0x3000)=nil, &(0x7f00000a0000/0x1000)=nil, 0x80400000}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000063000/0x4000)=nil}, {&(0x7f0000ff3000/0xa000)=nil, &(0x7f00001f0000/0x1000)=nil}, {&(0x7f00001f0000/0x1000)=nil, &(0x7f0000001000/0x1000)=nil}, {&(0x7f0000132000/0x4000)=nil, &(0x7f00000b2000/0x1000)=nil}, {&(0x7f0000083000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {0x0, &(0x7f000002a000/0x3000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000e58000/0x4000)=nil}, {&(0x7f00001f2000/0x2000)=nil, &(0x7f0000000000/0x3000)=nil}, {&(0x7f0000091000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000001000/0x3000)=nil}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {0x0, &(0x7f0000132000/0x1000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f000008a000/0x1000)=nil}, {0x0, &(0x7f0000092000/0x3000)=nil}], './file0\x00'})
openat$vmm(0xffffffffffffff9c, &(0x7f0000000800), 0x0, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x611, 0x0)
r0 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
r1 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x401, 0x0)
open(&(0x7f0000000100)='./file0\x00', 0x615, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
r2 = socket(0x18, 0x3, 0x0)
setsockopt(r2, 0x1000000029, 0x26, 0x0, 0x0)
mknod(&(0x7f0000000180)='./file0\x00', 0x8, 0xffff)
r3 = kqueue()
kevent(r3, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000080)={0x0, 0x80000002})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x1, &(0x7f00000000c0)=[{}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$WSMUXIO_ADD_DEVICE(r1, 0x80085761, &(0x7f0000000040))
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000040)="94c79bd261e1e88e83beb11c0a3e154df77b5335bd1667d9fd77c59297b3cad0ade427f63f2912518a179b7c207bc5ba040a20b5c36bfaca54e49900550bad2f165552f266a6b12d4900c56a22e814223e67a3fdf5ae19bcbb5d0a815015db8752d03d1b08f84b4976ec52d4a82598424ed3a6a523a3591db0e862a2f4dd1168cb17845fff1fb5df5535cae3e20e2bdb92138d0c1b0720e1c121ccb763f092cd5dcaa3d901", 0x2cfea}], 0x10000000000001fc)
munmap(&(0x7f000006f000/0x1000)=nil, 0x1000)
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f00000001c0), &(0x7f0000000240)=0xc)
r4 = open$dir(&(0x7f0000000340)='./file0\x00', 0x0, 0x0)
r5 = open(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
mkdirat(r5, &(0x7f0000000180)='./file0/file0\x00', 0x0)
renameat(0xffffffffffffff9c, &(0x7f0000000040)='./file0\x00', r4, &(0x7f0000000280)='./file0/file0/file0\x00')
r6 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f00000003c0), 0x0, 0x0)
ioctl$FIONBIO(r6, 0x8004667e, &(0x7f0000000400)=0x7f)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f00000001c0)=[{0x45}, {0x1}, {0x406}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


mknodat(0xffffffffffffff9c, &(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$wsmuxkbd(0xffffffffffffff9c, 0x0, 0x1, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x8, 0x0)
poll(&(0x7f0000000180)=[{}], 0x1, 0x0)
poll(0x0, 0x0, 0x0)
openat$speaker(0xffffffffffffff9c, 0x0, 0x100, 0x0)
openat$speaker(0xffffffffffffff9c, &(0x7f0000000180), 0x8, 0x0)
socket$inet(0x2, 0x3, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000006c0), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x2, &(0x7f00000004c0)=[{0x3}, {0x7c}]})


r0 = socket$inet(0x2, 0x3, 0x2)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
semctl$SETALL(0x0, 0x0, 0x9, 0x0)
sysctl$kern(&(0x7f0000000040)={0x1, 0x3e}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0x4, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0xfffffffffffffe37)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, 0x0)
sysctl$net_inet_ip(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r1 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7949)
writev(r1, &(0x7f00000000c0)=[{&(0x7f0000000080)='#!', 0x2}], 0x1)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)
sendmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, 0x0, 0x800, 0x0)
kevent(r1, &(0x7f0000000200)=[{{}, 0xfffffffffffffffc, 0x1a, 0xf0000000, 0x7fb, 0x4}, {{r1}, 0xfffffffffffffffa, 0x4, 0x1, 0xffffffffffffffff}, {{r1}, 0xfffffffffffffffd, 0x40, 0xf0000000, 0x3, 0x5000000000}, {{}, 0xfffffffffffffffe, 0x0, 0xfffff, 0x3ff, 0x99c0}], 0x0, &(0x7f0000000280)=[{{}, 0x0, 0x0, 0x2, 0x8, 0x2d5375e0}, {{}, 0x0, 0x41, 0xfffff, 0xfffffffffffffc01, 0x19}, {{}, 0xffffffffffffffff, 0x5a, 0x4, 0x10000000000006, 0x80000001}, {{}, 0xffffffffffffffff, 0x12, 0xfffff, 0x1, 0x80}], 0x80000000, &(0x7f0000000440)={0x0, 0x8})
syz_emit_ethernet(0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
r2 = socket(0x2, 0x1, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$inet(r2, &(0x7f0000000000), 0x10)
r3 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000180), 0x1, 0x0)
ioctl$WSKBDIO_GETMAP(r3, 0xc010570d, &(0x7f00000001c0)={0x1, &(0x7f0000000240)=[{}]})
openat$speaker(0xffffffffffffff9c, &(0x7f00000006c0), 0x1, 0x0)
msgget$private(0x0, 0x4)
r4 = accept$inet(r0, &(0x7f0000000000), &(0x7f0000000040)=0xc)
writev(r4, &(0x7f00000001c0)=[{&(0x7f0000000080)="01"}], 0x1)
setsockopt$inet_opts(r0, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
ioctl$FIONREAD(r0, 0xc0287533, &(0x7f0000000440))


kevent(0xffffffffffffffff, &(0x7f0000000180)=[{{}, 0xffffffffffffffff, 0x21}], 0x1f, 0x0, 0x0, 0x0)
r0 = kqueue()
dup2(r0, 0xffffffffffffffff)
r1 = socket$inet6(0x18, 0x1, 0x0)
getsockopt(r1, 0x29, 0x40, 0x0, 0x0)
r2 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000000), 0x80, 0x0)
ioctl$BIOCSETWF(r2, 0x80104277, &(0x7f0000000180)={0x3, &(0x7f0000000100)=[{0x8, 0x1, 0x0, 0x7}, {0x0, 0xc2, 0xff, 0x5}, {0x5, 0x2, 0x6, 0x9}]})
getsockopt$SO_PEERCRED(r1, 0xffff, 0x1022, &(0x7f0000000100)={<r3=>0x0}, 0xc)
getsockopt$SO_PEERCRED(r1, 0xffff, 0x1022, &(0x7f0000000140)={0x0, <r4=>0x0}, 0xc)
getsockopt$SO_PEERCRED(r1, 0xffff, 0x1022, &(0x7f0000000180)={0x0, 0x0, <r5=>0x0}, 0xc)
r6 = geteuid()
r7 = semget$private(0x0, 0x2, 0x7d4)
semop(r7, 0xffffffffffffffff, 0x4)
semctl$SETVAL(r7, 0x2, 0x8, &(0x7f0000000340)=0x3)
semctl$GETVAL(r7, 0x0, 0x5, &(0x7f0000000600)=""/250)
semctl$GETNCNT(r7, 0x3, 0x3, &(0x7f0000000380)=""/64)
r8 = getgid()
semctl$IPC_SET(r7, 0x0, 0x1, &(0x7f0000000180)={{0x0, 0x0, r8, 0x0, 0x0, 0x0, 0xd}, 0x5, 0x442, 0x7fffffffffffffff})
getsockopt$sock_cred(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000480)={0x0, <r9=>0x0, <r10=>0x0}, &(0x7f00000004c0)=0xc)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000580)={{0x3ff, 0x0, r8, r9, r10, 0xb9, 0x6}, 0x5, 0x2, 0x6})
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000740)={0x0, 0x0, <r11=>0x0}, &(0x7f0000000700)=0x4e)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f00000000c0)={0x0, <r12=>0x0}, &(0x7f00000003c0)=0x20)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000500)={{0x5, r9, 0x0, r12, r11, 0x8, 0x1f}, 0x7a, 0x0, 0x9})
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000400)={{0x8001, r12, 0xffffffffffffffff, 0x0, r11, 0x10, 0x208}, 0x0, 0x9bf1})
sendmsg$unix(r2, &(0x7f0000000200)={&(0x7f0000000000)=@abs={0x1, 0x0, 0x0}, 0x8, &(0x7f00000000c0)=[{&(0x7f0000000040)="ca8e", 0x2}, {&(0x7f0000000080)="260886782710e6b0ac5e27227045cce293943120718047657e78b0ebc915f0576b7cae1f49ae4be4dc", 0x29}], 0x2, &(0x7f00000001c0)=[@cred={0x20, 0xffff, 0x0, r3, r4, r5}, @cred={0x20, 0xffff, 0x0, 0xffffffffffffffff, r6, r11}], 0x40, 0x4}, 0x404)
r13 = openat$pci(0xffffffffffffff9c, &(0x7f00000019c0), 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001b00)={&(0x7f00000000c0)=@file={0x0, './file0\x00'}, 0xa, &(0x7f0000001700)=[{&(0x7f0000000100)="819bc059cc3914db837395d623050faba1f9d60fd119de4043c25a7c08d173f0392c4b72f474a446cf4e8af04b4cada62b34d73ceadf2fd24faebd559449ee255d44f1a2af96c7aacbc53b05900a5a427bb2fb02d3193dd3cc01103796b71ccf22a6b961e9606290c8077b2d22fdeaeccd39aea82192829aeaba306a701ca2b9683831742da62ac68f194d27611dd27991edcb", 0x93}, {&(0x7f00000001c0)="fe4a1325058c5f706bf44cdaa1bec3fa8a6f9513f426608e308fb02cff1a69d46c8d1caadd6d7f62978f022a52684b6d6d2572e2f3661fb67c82964079cbf7231f665642f3198c138e04447b86e688257dbf50ed5eeee36bad381224fc555d01b2c780fc27d2e08769e99d126d53adcaca2c0aa6bab23e61296be8d92931f7bed2c2dedbcf144510e3c76f1bfe13974c5659967dc83a6078003128d8e9f529a759770f3174419cf96facf47d8e6dfe3517ea861a0a0c14203659fc2a292b33339485977a978ae7d063fc218554e054155b76f949aa0738d165080498eed3eab805", 0xe1}, {&(0x7f00000002c0)="3f4bbe458843c7c863b8faecadd8bde2ea3d3ce3805f5e72acbbafcfe852088037a0b24c2702f10777909170fbb3c03a7126366e5765645d9471e16aa2e196cf2b4c6c61bb13b49e43f4e0ff3fd790ffc6014a9cab96445aca3be267124e9cd210867fd4835fd899be47843637d757815f832036c367c1093a82e365f058", 0x7e}, {&(0x7f0000000340)="fb4e2003baa87a64bbb824ead773abc14e06719b6cc67930e8179f59d2ba6dddcd046add897c81269fe671095fcaac26705bcddb4988925fa550848c3dabf54d927a2f68b1a9c9cd2fa1b31256009320183b8d30e7476803a9c565d3210deeb97f205cb4b7f4bd83f565470e18f82d50bb8ff77b04f6f89426fa33559f3854c5b3d8acc29e344f0be3478fffd51cff6f8b986cecb4789f044d9829bffd877a387e872b09dea34f155c51777ab4184385c8ab0d8fa2b4ec094baacf43c8b5d07208dd533d7a0c1dbf7dd243fb6be812fd4d49564e884d6247648662992992c069361eed5614cf75cff7e20d2ea168eaf972a4514e154da469222983814bfd", 0xfe}, {&(0x7f0000000440)="f48c2a0f4263c8fe7d6ed4866b9eb15f897fb0b4e7a895ce9025b20781511940b19d009e9718e17c5685c5cbb5add4fd8380ed73caf64c1ec306d75fa1bec6b383e9d21fc50f79e8cace44dc2a0ae331fd28677ad6a51e2b31537a93522865009fa576cdf9b5bbb1749091dec7c8a1f7e049c79c901eee7bb43709edf4c84195cc72beeb20f50b2c72518ceb1d018e262cd9deea761e45348aa1070e0790400c850819e131060c0383af14451791864d9fbd840608cd7b488fe6fc112eb0cd", 0xbf}, {&(0x7f0000000500)="0ab02808cd5e6006453d1160d7ab", 0xe}, {&(0x7f0000000540)="4213faf0aa36d7116fea285ebc93d29a1551b01a4151343b560c7cfea61a9e4cb4867b307ec6ca5f36229f8bacbfcb533f1cc435fb92253741866f84442e4cf28f6dd6d5aa69204f6a5697ea1dc1459264522a9c75cdcffd420647", 0x5b}, {&(0x7f00000005c0)="5d3345f96154c4e468d3619ec63453d207e0c50c893ed154fade2fe00141e7ea4650932900925c4ebb26ed672805315101e310f53b60d7501c2bee3f13766c723b113c472a9dd351cd634c4ca595a562bdd3431eb7bdd4ecbd96d49a1b389d63a7bc467e809a5bb0fe8e38e06a930955948b87b3444ee6e89df708a227a97c99b6f0604935b0d26956d02134d011a7a9537478c38cc3e08f9dfff53e7e6c5d65141300a8bc2ec791b5a57e91d713b0579be290921ede383935ad2e6f5ab4f728808612b556fdb36b1031c2d145fb85d2237df0039cd782f6417f7779a86736ba4e6e072c2610dfcbd6edec12f87762986cc7feac2d54a7ee648b387d53e534740fcedfc69a8f23d866f88f03707d7151337102bac85936d1120a3b4c9738d8a5201c2d6a76ab6855d645db8defc13673145693f6f2fe0fca2241928c19878fb001b5cab88b09f0fc0223ac405954280a72daa95528a6f358169918fa20a219264f319d3a6ad580dbc41d389360cebc8635c78156f7696529f5dbb842c39b9032bd0f622dd26f803a62314a30082848211083e91505e72462fb3598e9d5c8f1f171f00497b1077717998bf3be801438cf230033f5b3e8a1181ea0c27f20fd3f8a368658aed85269d94144b4bfaf6639004161b819c25981627f56495457929a42562a86bd7fe46769f352ad274716ff45c5ff9610f98570e51013ff4ceaa351a5f3aedaf99dd78b7f00d47661db0f78060f251f90e1dbe05813bd050c0117980f9de8f87eeb46200130482ddad744f7a3f85f39f29f723e8d8c18cb4a1133ef8365a4c369cc9c672f1a8d9729763749d4436608f55501d7bff9452af393bd31853eb7d30aa9ed8a5c2c7837de2e74742007153e26783c2a7ab9f4fe39d447b903d7c8f081e854b72050e343e147f5ec9115cd049d8daabf9c6551705da7749a84334dca13b3d838f2c647813d7f7b2aafc5b50ebb5486f435ae6e250ff71d77e08c6a7eb4900f99a0a656802c122953d415be3a9dfdbe3b06d149e7dc682bffeff0a2abedca94c3d733a18a1a65fe3ceeb6cfed12815f740568e9902c93a47b1458c5a8533fc017258b8ea4d6609afbed878341f8d7d611c02c2e43d015d238f98d22da768e9446f18ad68e4a0787e9bc8d8eec94566e3d6180a8c2d5420dfe4611008b60027f3d147b792ac3c173cc5c4a6450f0bd738acbbb530aea0eaaac58a2232ca28578d93eb888489b71040e64f740729b64e0be9d6768c4cf170619943d347fb4d2e19100c09481edfa0bbbcd596abfe280f81fd961e26f5c69d6a5ee47e0858fa77ea6c2c01291c9b2cf7f0d5fdca2f3baa7314f8bde41a2e098a17ae162ef7990d561b852e60185ddb3a4aca70dc0751df5398e7b5f9844c8a25c10e377eb0c0d7df99e381b79ef05b14d1073d9b8b0d4eef7be0dcb8b60e257f0addebb669f1af9770e905ca71140cc749e148cbb5c3be0d935c64d0dc5d4a0243173e032194b41af5205e1eef2364fd3795b463b9cd00ff6c648d32ae6dda2c940e6134b6b79bed730b32ed00aeb4152c345a81184e673644e287bc514671318bf0b245deec848f38b9f32b4e6fa87b1bb7dc2b30e7e66d1edfcbd954ab20914ac4cf0bf5ee284e2efe694439b140eaa12f477271f27106e1e198bde9221ea8e21721dd48c7fe7283a67f90ce593b2aae95450d5da907f3ea007eb052586e355bdc532e74ce045045ec7c3bd6f1655b9a88f1f8968b5bb501aac501fd6cd96b77c75978fa9cad4168a71be40e039b43471dde81579b7cd195eefa8792064a036805d3eed6c890de0bd058f090adb0d06b562ed77bb250e2e257db56b9f2fb7ac010992404c6cd480808c477a1fef28743aefad7d2fd78648819becbe571e363fc31c0634053193e72a68d2ee90e519908010d326cdcaedc34019445a64af6655ab89eefb5045fd99f0dccd5226af6200a0434c1d35c4d90920b9e302c9b932803edd583841a2c5575bc38b089cd29cc5a13a388416cc1fe56397a96985a91355bb1280d82a9e6425ea97434fa005ed46d885c20e920009b3e48d71e31b903f0a4d0c81f35a536abdf7295086772995474cfe38ce4b2c9fe26bc68c92d4762fe9f7dd0fd45c4947bb10af2e3e1ae2896410e7357a0fa2e9ae786ce11ba9b6dea37c516378bdf75e8fda7081722bf0e3ae955dff32a813bb5c6c9c4731eaa37d87e8185166089086c7810b7f3b4952d464530eca085d42a563fcdf258b43c24b3858b2dbba8aadd124809c14dcc3086b46b39dd5b708f42951f4f6f333d1e7d5c66f3c767240c641fc539dc1569a3124056a37454a37311f335f3eea9226c6d494738176656876732b0f02a8d539198cacdb8518f50951998b9f2fee71e53f9cddacb586a4fed4a350999168b355c6fcd69a642405be9d03b34d665d58b6b31eac51fde3b0d6dbf39453164157dea241fb880fbf8f71c02457b9b4be9b39813e41943cbd96b0d00f8ec8ff0a28a6e22041de6f052ffb6db865d49c8ec05f0471aad62dbcc1f9f7ca23157179c6ae5b61c7f8cd273e093c36fe97c576a6f90e45a073c8454b12ed181a242f59b7473f5c261707a2ba1cc3e1a174d22a5608e00950d9eb9e74d232582fd5bb1f05c4f8f7bc1640c7547157c7301428153540643feba3f18b414116d5e75783fffe0edfee8a285db332984ff467790808608552dd250efc7791b60cb29fc0a6b90a814e3b0e8420fea63defbff4c7fbc0fff46f584fc8e2b91e269c38c3f4721d7f56ffd01ced7fdb536eec97e469deeccd63bb1ca760885f744abc37f3901bb8830819b3bff09d1a1974afe5134e36190b10102380d8e148013237187f1b44bd5b6dd546e07bcdc1d462d0b6722671698fd1b938dc545e4730ce6092a3fd18eb2ec64c4b4a30993b4ec102aaafb087549457ee66aed479c0829173f92d28e74beed08e56929eab969078b2d083e1b1c22d2d7629540427dbfe03647ef150a210453892451a380f65ad16bce0d09cb6d6c8bba39b740e79b9854ccfe7a1a1959b40252312d449a3233355fc7341839fb4eaa18c67d6a37ac4bbc31e177572f84352b359b63134d905d4d45c6fae7ee531fccdcd8793c15fdb89530e143f91dcd884085fb60bec9d99c2124fee2db9e7a5ef672cc53f5964f21c19b0e8eb812a3486fe87c186dea6d397a569ef96327aadde49dcae274067038390e8dbf415f70c52249dbcfe05f1d65252ccc3b8af09b6a39a09b2f2950172c0a806204f048e25be56cd90d240786305ced113e0095a71a2e2e5f99d47134a1129b597fec5f2df333698eaeebe93093243b6cbb3e1e782846f0ed0ebcf5c41476187409883ebd969104db808c30956d66bbcca538ede636f49a93c1c48f4d15ea5e1e0f641167d85241d6a934135b7c2c182cd7e67173c944e6bc4859d8eee36206d169771dd56fc29feb27ede4534e17ea4c08c489d4e4c33bdaa901cd24dd8072c8c456a9eeaf6f4c5899dd489b44ce11a3e2968a61118e8474b5afd77dfdad8e73646b0b9e5b4ce55b7ee9d0c968a6c0d1862f38a8abad9dbacd083563889a35808b03deb852f2d85eb32483f0d41724fdda2f0d6f600c27dec85e1be0ffcef8b90b72bcc890ca26a26a0727054e0ac40ea8a2ef05c887a7374f15ba0edaec205c5a3fbc1de79bc96a5e93b622cbfc10ec8e635dffdf0435a18c2cf07953c695b36e6f89f42f05ab5ee4cb89030a41717fa670aed7aaa23482a0c660b3a2437fe5fc86c7a0d2abb95f36db6834292615090917d96aad4748acc3f0d02b74935bbaff665b2060c23a5fe6331331f67e8f1f1f748330a84735352b6a5b9443845fd96112f58e287df79d7e39f82806394e7fd29fb4067a6998f3997178d0e001bc8bcdfbf03e7373cfb1c94fd21ab34d74b29bae565a48740352c5a6861c75aa983838a5a37dd3d138f0de0a9882b0ce6120787956fe752fcb518ac9223c8614f878e6e7ec85afe607989d9227a80224cdeb84a9ed0bcf03967aa7f04658d6e91952b6cb462775a0f3bf953982f379318b29cf71ea9a028566abee5503ee5bda79c02dede4231228d00581eb4a659e8082c14e5f0ae42dcfa0da8844e2a51d8aa3867fef630abd077b41b6a85ca1008f64adf6823dd1cf010b4323b8100956c47f94e56835cc9e16c5e798ad31734faff006e91dde837751bf490cdbf737b80ef298975e3229d1bd22b5b16c0fc90b0f4105125f093c72c301c951fd770e0254575de3f3f79c58bc304237bcdcf4fcf82e94623f7fb9835a30081b923ec57cca1eee39a973c62cd85f2b30aa09d4246ff690fcb27a98410fbbe1f2ab3f6613238725771258065db178652ec35466fa97b8eb0f61590e04345abd386510155590a8324690384848a45f056478c9beff97baaf71ef63f1d5036bc0b7da9d0b8daeb2162d9e3a3d9cead429c06245e7f580c853ff3b5d442f4a07a8539dcc4a3487399e43fb279bbe44720ad1bf5a30bfd1895c295ef52b82543eca6770b7278d30dbceedb2a0157d886b59e6d9daebf577b10e08435814c0d3b8521499268539e5636e766301fd9922b0a40495eef179297e99094625dccc163fc38c221fa20c7ae53d8bd9ffebd83c124894ba31a034275d6065bd5e94d39168f43307d8518848a31dfacd6fd08bbdba163b2ed425440bd93e62ccea1c0d521d8a859c4e4d58843967b3e240a306389d2a1beac335af61a369b53b18d26fe6b511e6a7943468b72386e6ff9fcc81d3e6140d1a8fc362ca4333d0acfa70bc5bf724bbea854f5997cff345256d37d30e0439db506d4dc9eedf2a8f748caf5d683c6ee2e29edbfcfdf9af4bebb0fd3a26d2953a8b45de6ef262be382106e69f44cf1a0b28082119d92440176f867acc8613d3f3ea642059085a9b40c84ca2aad43449befac836b67f37eefbec667a4da0d94a4d5efec515ccb6a1bd71473fcd39fd48e8e74afc8c2cbffe886c40d2e44757f66be8c320216128dbcfb9bbbeece38f45f0a4c38864b3bc42c8ab89fcaba978f1a1648b27f1885f9c2bd950d7324af6b6e232568c2436a4708c94e6cbd92017cee69555495c99895bb6bd1ec3661801ff1792f8d59a06bf875dacc7718ea028ecceb39c913c874b85b666b91326b1dbf1b63bdffc9d81a88cdd446317591b7737ceb5ceb9bf5038ccb5cfbdbe478efff6d50ab670615114563ce77ada50d5cd6b2247499973b5d90910a4e9b53194e40b0a5aa09b6f1724b95e70794f9afe4a2392d4d707b8d478963f8b615b7e2846cbae90e5f1df1b1e78397b05e98d7efe04bc04d2cdb77ed3371a592085b455492ce81999235c4f5afaace51d05744f44def833280ace1578d94d7d87d3372301cf77230050510d30168e6fdf2947584d661fdb80c8f025c1b48620c05ad0640b9d8ad7e9b50d64e6c5ff3dc6ea09e2ef0b4cc133dfb5a2cfadb6a261a2d218e393e0f63761c431c70525a698f6ff885096b959332cfce7671534bc31ab02f7a45bf4970514e9dfa54653164734d0d0c817208a51240866b00b49c760606966960cd40d03173df8b7ecaef672c3f6e4a90be1a84065d204bac98145b9eac115e7b402c68bb240973ccff8a0616b8917a8e1258a2e0365b24b055648f1359b8212f61e281430af88c7cdcb9cb334698252221c0bdeafe0ae35adecc61a6341c9ede0e75ad0dfbbb12e2f22cb466abc86ea73b82de80825bf0d932ba3cbac4a43695007006431e3f2558048d3e844694af705a9db536958aba870eedb127a0d7ba1fc60e80", 0x1000}, {&(0x7f00000015c0)="804bda0ec9b0dfba9ae48ec899cff81c406a447466d9413f72bd7e297bdbffc6591581a078555fa3a0f5f7ca42658d2fd1d96ced15575da7ece513b8cd1a7d0b93a2fc0cea8ed448be945b07fcf06ad397bd11fa3fd797fc797ba497706855aacd74ca03083499071358c9229565fa0b7446ea9cdb9d8ebf8d3c09eea8dda6c818c086", 0x83}, {&(0x7f0000001680)="88ae9f2a6779f57c8499c2ce326a1c3982d65196f1d0586bb850e3f2859c9505a5112c9e1bbdcd1c380d8458d9d795b0ac35989372cd28c4ff0f4f4728567a07b391f25003830e4548594ba3ec40c8087ffa091f4de58c9572f4a785c0394f356aa8476fc24de081d165c88851baa2f666cb016a", 0x74}], 0xa, &(0x7f0000001a00)=[@rights={0x28, 0xffff, 0x1, [0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffff9c, 0xffffffffffffffff]}, @rights={0x28, 0xffff, 0x1, [0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff]}, @rights={0x38, 0xffff, 0x1, [0xffffffffffffff9c, 0xffffffffffffffff, 0xffffffffffffff9c, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff]}, @rights={0x28, 0xffff, 0x1, [0xffffffffffffff9c, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff]}, @rights={0x28, 0xffff, 0x1, [0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, r2, r13]}], 0xd8, 0x405}, 0x4)
syz_emit_ethernet(0x36, &(0x7f0000000000)={@remote, @remote, [{}], {@arp={0x8100, @generic={0x0, 0x0, 0x6, 0x0, 0x0, @empty, "", @broadcast, "ad0c7e8afdd053ef4fd2a822fd23f4d2"}}}})
syz_extract_tcp_res(&(0x7f0000000040), 0x101, 0x1)
syz_extract_tcp_res$synack(&(0x7f0000000080), 0x1, 0x0)


r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
mkdir(&(0x7f0000000000)='./file2\x00', 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x2, 0x2, 0x0)
fcntl$setstatus(r3, 0x4, 0x40)
shutdown(r3, 0x0)
connect$inet(r3, &(0x7f0000000000), 0x10)
r4 = getpid()
fcntl$setown(r3, 0x6, r4)
setsockopt$sock_int(r2, 0xffff, 0x1023, &(0x7f0000000040), 0x4)


mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x5c4a)
open(&(0x7f0000000080)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
select(0x40, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000340), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{0x20}, {0x1c}, {0x416}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x36, &(0x7f0000000400)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f00000001c0)=[{0x6c}, {0x44}, {0x810e}]})
syz_emit_ethernet(0x6e, &(0x7f0000000280)=ANY=[])


r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
r1 = fcntl$dupfd(r0, 0x3, 0xffffffffffffffff)
fcntl$getown(r1, 0x5)


ioctl$WSKBDIO_SETMODE(0xffffffffffffffff, 0x80045713, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
socket(0x1e, 0x3, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, 0x0, 0x1, 0x0)
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[@ANYBLOB])
msgget$private(0x0, 0x51c)
msgctl$IPC_SET(0x0, 0x1, 0x0)
pwritev(0xffffffffffffffff, &(0x7f0000000000)=[{&(0x7f0000000200)}], 0x1, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x2, 0x1, 0x0)
r2 = socket$inet(0x2, 0x3, 0x102)
dup2(r2, r1)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
dup(r3)
bind(r1, &(0x7f0000000000)=@un=@abs={0x0, 0xd}, 0x10)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x100000001})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
r1 = socket(0x18, 0x1, 0x0)
socket(0x0, 0x0, 0x0)
setsockopt(r1, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e699319296", 0x13)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
ktrace(&(0x7f0000000180)='./file0\x00', 0x4, 0x330, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
socket(0x0, 0x0, 0x0)
select(0x2, 0x0, &(0x7f0000000040), &(0x7f0000000080), &(0x7f00000000c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000280), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000440)={0x3, &(0x7f0000000240)=[{0x3}, {0x1d}, {0x6}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{0x30}, {0x80}, {0x16}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f0000000080)=ANY=[])


getpeername(0xffffffffffffff9c, &(0x7f0000000000)=@in, &(0x7f0000000040)=0xc)
syz_emit_ethernet(0xd6, &(0x7f0000000080)={@local, @remote, [], {@generic={0x7030, "03760bfefc27fcf77f301ff68831f9737e3f6688ed37f1519546bf5d20913512cbb98bc3b406028dcd67ee5f3b728679cd2f30ca0473f2dea284ee0380651c1ce7346165fe125386421f0e3fd49dfe259b53d3b843cbc6e7739d9b0bbf55c3da4d558f61e857867565ab7bfb83d55e1dc6be639222a4ab59dc13f00e11b8fa3629ec108ea11b05ccd1d2e175a0a7451c23c3f9bf6c1bed60d8e801a381049da4894cd44158a495c4449e4891d85545b4337ca6bbe6026a9f3a319ef76e979e2b54ae86d66d397944"}}})
rename(&(0x7f0000000180)='./file0\x00', &(0x7f00000001c0)='./file0\x00')
r0 = semget(0x0, 0x1, 0x620)
semctl$SETVAL(r0, 0x4, 0x8, &(0x7f0000000200)=0x9)
socketpair(0x6, 0x5, 0x4, &(0x7f0000000240)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
connect$unix(r1, &(0x7f0000000280)=@abs={0x1, 0x0, 0x0}, 0x8)
r3 = socket(0x18, 0x8000, 0x6)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x8000, 0x0)
ioctl$BIOCLOCK(r4, 0x20004276)
ioctl$TIOCSTAT(0xffffffffffffffff, 0x20007465, &(0x7f0000000300))
r5 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000340), 0x0, 0x0)
ioctl$TIOCGETA(r5, 0x402c7413, &(0x7f0000000380))
sendto(r3, 0x0, 0x0, 0x404, 0x0, 0x0)
r6 = socket$inet(0x2, 0x8000, 0x1)
r7 = socket(0x20, 0x1, 0x4)
ioctl$DIOCMAP(r5, 0xc0106477, &(0x7f0000000500)={&(0x7f00000004c0)='./file0\x00', r2, 0x2})
r8 = accept$inet(r5, &(0x7f0000000540), &(0x7f0000000580)=0xc)
recvmsg(r8, &(0x7f00000008c0)={&(0x7f00000005c0)=@in, 0xc, &(0x7f0000000840)=[{&(0x7f0000000600)=""/141, 0x8d}, {&(0x7f00000006c0)=""/116, 0x74}, {&(0x7f0000000740)=""/253, 0xfd}], 0x3, &(0x7f0000000880)=""/19, 0x13}, 0x801)
recvfrom$inet(r7, &(0x7f0000000900)=""/115, 0x73, 0x842, 0x0, 0x0)
ioctl$TIOCSWINSZ(r5, 0x80087467, &(0x7f0000000980)={0x20, 0x800, 0x7, 0x3})
semctl$GETALL(r0, 0x0, 0x6, &(0x7f00000009c0)=""/195)
getsockopt$SO_PEERCRED(r5, 0xffff, 0x1022, &(0x7f0000000ac0)={0x0, <r9=>0x0}, 0xc)
getsockopt$sock_cred(r5, 0xffff, 0x1022, &(0x7f0000000b00)={0x0, 0x0, <r10=>0x0}, &(0x7f0000000b40)=0xc)
fchown(0xffffffffffffffff, r9, r10)
bind$inet(r6, &(0x7f0000000b80)={0x2, 0x3}, 0xc)
sysctl$ddb(&(0x7f0000000bc0)={0x9, 0x2}, 0x2, &(0x7f0000000c00)="501abf22d93fda5e4d7cf899fa0c44ba962d1c92845d5e666a00671a57096188add06189f8f09193b5bfc4b9951c888add53fedda1e1876ecd895aeff4e82dffca", &(0x7f0000000c80)=0x41, &(0x7f0000000cc0)="ca9949b02c77b794930b3ad83918c9b445f5d7c45790fd95469d280f0d5baa94556ba6dc8ce874c9f0e60abfbcab8deb313176830e487ad727a2cd6730e4d003c8f1ff6413f0f69c0de0fb7c9143", 0x4e)
getsockopt$SO_PEERCRED(r8, 0xffff, 0x1022, &(0x7f0000000d40)={<r11=>0x0}, 0xc)
syz_emit_ethernet(0x44, &(0x7f0000000d80)={@remote, @empty, [{[], {0x8100, 0x7, 0x0, 0x4}}], {@arp={0x806, @generic={0x6, 0x804, 0x6, 0xe, 0x4, @random="bc054b021b93", "619e460dd2d3d1b773a0d6e7ac91", @broadcast, "690a3598bd7e4067b68ffd12d5de1dab"}}}})
getpgid(r11)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f00000000c0)="b100051300000000000000402020000000000000cea10500fef96ecf2ac72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf7f882b297be1aa0540000051e2f0ad3ebbc257699a1f139b672f335c223e7d0c032b0c8a6443a42118000000720fd38bfbb770c1f5a872c88106002ec589040000000c000000361b1257aea8c500002002fbfe0c2300008abfba0900afb7515871a3f8343712051eeab7196fcbd80407000000c011200000", 0xfd0a, 0x0, 0x0, 0x0)


r0 = syz_open_pts()
readv(r0, &(0x7f00000012c0)=[{&(0x7f0000001200)=""/1, 0x1}], 0x1)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0xffffff9a, 0x0, "b07b1f660000000000002000"})
syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000240)={0x0, 0x0, 0x3, 0x0, "0fdb00000000000000060004000000000800"})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
r1 = kqueue()
r2 = socket(0x18, 0x1, 0x0)
listen(r2, 0x0)
accept$unix(r2, 0x0, 0x0)
openat$klog(0xffffffffffffff9c, &(0x7f0000001400), 0x0, 0x0)
shutdown(r2, 0x0)
recvmmsg(r2, &(0x7f0000001380)={0x0}, 0x10, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
accept$unix(r2, &(0x7f0000000080)=@file={0x0, ""/26}, &(0x7f00000000c0)=0x1c)
kevent(r1, &(0x7f0000000640)=[{{}, 0xffffffffffffffff, 0x3f}], 0x8008, 0x0, 0x0, 0x0)
syz_open_pts()
r3 = syz_open_pts()
ioctl$TIOCSETAW(r3, 0x802c7415, &(0x7f0000000140)={0x0, 0x0, 0x0, 0x0, "ae2f00000000000000000000000011000200"})
syz_open_pts()


setrlimit(0x8, &(0x7f0000000980)={0xb})
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
mprotect(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x4)
mlockall(0x1)
munlock(&(0x7f0000ffb000/0x4000)=nil, 0x4000)
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc5005601, &(0x7f0000000000)={0x10, 0x0, [{&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ff3000/0x2000)=nil}, {&(0x7f0000538000/0x2000)=nil, &(0x7f000013e000/0x2000)=nil}, {&(0x7f00001f5000/0x4000)=nil, &(0x7f0000162000/0x4000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffb000/0x1000)=nil, &(0x7f0000ffb000/0x1000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ff3000/0xa000)=nil}, {&(0x7f0000ff2000/0x3000)=nil, &(0x7f0000ff9000/0x3000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {0x0, &(0x7f0000ffa000/0x4000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f00001f4000/0x2000)=nil}, {&(0x7f0000002000/0x1000)=nil, &(0x7f0000ff9000/0x6000)=nil}, {&(0x7f0000054000/0x4000)=nil, &(0x7f000009f000/0x4000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f0000084000/0x1000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffe000/0x2000)=nil}, {&(0x7f0000161000/0x4000)=nil, &(0x7f0000ffa000/0x3000)=nil}, {&(0x7f0000ffd000/0x1000)=nil, &(0x7f0000ffd000/0x3000)=nil}], './file0\x00'})
socket(0x0, 0x0, 0x0)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f00000000c0)={&(0x7f0000000000)='./file0\x00', 0x3, 0x0})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000080)=[{0x87}, {0x15}, {0x6}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


r0 = semget$private(0x0, 0x7, 0x3c0)
r1 = semget(0x2, 0x1, 0x400)
semop(r0, &(0x7f0000000280), 0x0)
semctl$GETPID(r0, 0x2, 0x4, &(0x7f0000000400)=""/8)
semop(r0, &(0x7f0000000080), 0x58)
r2 = semget(0x0, 0x3, 0xe0)
semctl$GETVAL(r2, 0x0, 0x5, 0x0)
semctl$GETVAL(r0, 0x1, 0x5, &(0x7f0000000240)=""/151)
semop(r0, &(0x7f00000002c0), 0x0)
semop(r1, &(0x7f0000000040)=[{0x0, 0x601, 0x800}, {0x1, 0xd76, 0x1800}, {0x2, 0x200, 0x1800}], 0x3)
r3 = semget(0x2, 0x3, 0x0)
semctl$GETALL(r3, 0x0, 0x6, &(0x7f0000000100)=""/73)
mknod(&(0x7f0000000000)='./file0\x00', 0x44bf42bca2222dfe, 0x201)
r4 = openat(0xffffffffffffffff, &(0x7f0000000300)='./file0\x00', 0x0, 0x30)
r5 = semget(0x1, 0x3, 0x2b4)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, &(0x7f0000000340)={0x0, <r6=>0x0, <r7=>0x0}, 0x3d)
semctl$IPC_SET(r5, 0x0, 0x1, &(0x7f0000000380)={{0x8, 0xffffffffffffffff, r7, r6, 0xffffffffffffffff, 0x100, 0x800}, 0x2, 0x7, 0xfffffffffffffc01})
semctl$GETVAL(r0, 0x3, 0x5, &(0x7f00000001c0)=""/47)
r8 = socket(0x2, 0x2, 0x0)
semctl$GETALL(r1, 0x0, 0x6, &(0x7f0000000440)=""/95)
r9 = dup2(r8, r8)
setsockopt$sock_int(r9, 0xffff, 0x1023, &(0x7f0000000040)=0x7, 0x4)
getsockopt$SO_PEERCRED(r4, 0xffff, 0x1022, &(0x7f0000000180)={0x0, 0x0, <r10=>0x0}, 0xc)
open(&(0x7f0000000200)='./file0\x00', 0x400, 0x40)
fchownat(r9, &(0x7f0000000080)='./file0\x00', 0x0, r10, 0x6)
r11 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x80, 0x102)
r12 = getuid()
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000015c0)={<r13=>0xffffffffffffffff})
getsockopt$sock_cred(r13, 0xffff, 0x1022, &(0x7f0000000000)={0x0, 0x0, <r14=>0x0}, &(0x7f0000000040)=0xc)
fchown(r11, r12, r14)


open$dir(&(0x7f0000000080)='./file0\x00', 0x200, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r0)
r1 = open(&(0x7f0000000bc0)='./file0\x00', 0x0, 0x0)
fcntl$lock(r1, 0x9, &(0x7f0000000440)={0x0, 0x0, 0x0, 0x10000fffffffe})


getsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000000), 0x0)
setrlimit(0x0, 0x0)
syz_open_pts()
r0 = socket(0x18, 0x3, 0x0)
socket(0x0, 0x0, 0x0)
shutdown(r0, 0x0)
syz_emit_ethernet(0x52, &(0x7f0000000080)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaabb86dd60000000001c000080000000000000000000000000000000ff020000000000000000000000000001"])


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r0 = socket(0x18, 0x3, 0x0)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r0, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x1, 0x0)
close(r1)
socket(0x18, 0x3, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
getpeername(r1, 0x0, &(0x7f0000000080))


clock_getres(0x0, &(0x7f0000000000))
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x8000000000000001})
semctl$SETALL(0x0, 0x0, 0x9, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0xb2}})
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x0, 0x0)
ioctl$BIOCSRTIMEOUT(r0, 0x8010426d, &(0x7f0000000440))
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x0, 0x0)
r1 = socket(0x18, 0x1, 0x0)
socket(0x18, 0x3, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x1}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xa, 0x0, 0x0)


socket(0x2, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
writev(0xffffffffffffffff, &(0x7f0000000380), 0x0)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r1 = geteuid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, r1, 0x0, r1, 0x0, 0xa2}})
seteuid(r1)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000440)={0x2e, &(0x7f0000000100)})
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
socketpair$unix(0x1, 0x1, 0x0, &(0x7f00000002c0)={<r3=>0xffffffffffffffff})
pwritev(0xffffffffffffffff, &(0x7f0000000200), 0x0, 0x0)
sysctl$hw(&(0x7f0000000000)={0x9, 0x6}, 0x2, 0x0, 0x0, &(0x7f00000010c0), 0x4)
getsockopt$sock_cred(r3, 0xffff, 0x1022, &(0x7f00000000c0), &(0x7f0000000040)=0xc)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
kqueue()
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x4a, 0x0)
sysctl$hw(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r5 = msgget$private(0x0, 0x0)
msgrcv(r5, &(0x7f00000007c0), 0x8, 0x3, 0x1800)


syz_emit_ethernet(0x2a, &(0x7f00000000c0)={@empty, @broadcast, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @multicast1}, @icmp=@echo}}}})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0xb, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
sendmsg$unix(r0, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
r1 = socket(0x1, 0x1, 0x0)
dup2(r0, r1)
setsockopt(r1, 0x1000000000029, 0x9, &(0x7f0000000040)="ca5e1885", 0x4)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
sendmmsg(0xffffffffffffffff, &(0x7f00000007c0)={&(0x7f0000000780)={0x0, 0x1, &(0x7f0000000440)=[{&(0x7f0000000180)="a1b6c6c1d6c2eca2950e663d39ab1bae96ef58a3c18046e41e178f37a79f00659c2ea9ac56733f7e4e4973c1e6b33ac91343ea3b3f8c5c7b93d5c20ab4211791fe30", 0x42}], 0x0, 0x0}}, 0x10, 0x0)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x80206979, &(0x7f00000001c0))


r0 = accept$unix(0xffffffffffffff9c, &(0x7f0000000080), &(0x7f0000000180)=0x28)
r1 = getpgid(0x0)
fcntl$lock(r0, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0xffffffffffff0000, r1})
sendto$unix(r0, &(0x7f0000000140)="c60467087662f692bce9b2a712082da993b75613e9adb4b419752a8609de085292d270d8c37167b5b22a7d82e7625adca93cfc8f2b5d784f7f2b6197ca49c25360fd2b14df8deaf4e97d51d9fc5d1a2fe69d34e244a9433a173621870102f1063f68a0c977cb2dabb7d39aeb557f6ce498e76eb548e5f38d98d7822f3a6cf4a5a7dccba8e76b50125347d4299c8d9df5e2dd63aab8f9d3bf10ae4a2ead87c3c6c1cf0b7328007a17b46f2bf85b4aad0c28e497cc5bee23a6939bb819a6596dbf7293e519726188c971f666d0f8451b7f8ab4794c5fba5fed51655138aaeedaea110ceb5414c513fc77dc5f3d8c8f8d33548f124a0b93a170f9", 0xf9, 0xa, &(0x7f0000000080)=@file={0x0, './file0\x00'}, 0xa)
r2 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
r3 = open(&(0x7f0000000100)='./file0\x00', 0x8, 0xf2)
fcntl$lock(r3, 0x8, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x4100030001000b})
sysctl$net_inet_divert(&(0x7f0000000000)={0x4, 0x2, 0xf0}, 0x4, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f00000fc000/0xe000)=nil, 0xe000, 0x2)
sysctl$kern(&(0x7f0000000000)={0x3}, 0x6, 0x0, 0x0, 0x0, 0xfffffffffffffedf)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x5cda)
r4 = socket(0x18, 0x2, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r5 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r5, 0xffff, 0x1023, &(0x7f0000000040)=0x3, 0x4)
select(0x7, &(0x7f00000002c0)={0xfffffffffffffffc}, 0x0, 0x0, 0x0)
open$dir(&(0x7f0000000040)='./file0\x00', 0x800, 0x0)
getgroups(0x4, &(0x7f0000000380)=[0xffffffffffffffff, 0xffffffffffffffff, <r6=>0xffffffffffffffff, 0xffffffffffffffff])
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
getgroups(0x8, &(0x7f0000000400)=[0x0, 0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, r6, 0x0])
r7 = getuid()
chown(&(0x7f0000000180)='./file0\x00', r7, 0x0)
r8 = getgid()
r9 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r9, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000401})
fcntl$dupfd(r2, 0x0, r9)
fchownat(r2, &(0x7f0000000240)='./file0\x00', r7, r8, 0x2)
r10 = semget$private(0x0, 0x2, 0x200)
semctl$SETVAL(r10, 0x0, 0x8, &(0x7f0000000280)=0x7)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000440)={0x2, &(0x7f00000000c0)=[{}, {0x1}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4f}, 0x2, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0xe, 0x0)
setsockopt$sock_linger(0xffffffffffffffff, 0xffff, 0x80, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
socket(0x0, 0x0, 0x0)
mknod(&(0x7f0000000040)='./file0\x00', 0x6000, 0xe02)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000340)={0x0, 0x0, <r0=>0x0}, &(0x7f0000000380)=0xc)
chown(&(0x7f0000000180)='./file0\x00', 0xffffffffffffffff, r0)
r1 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x40000400001803c1, 0x0)
pwritev(r1, &(0x7f0000000080)=[{&(0x7f00000003c0)="1f1d137fe265ecaee9385ff30becc172866b897ccbe0660621320a667005c376e0efc8744ca0d354f242b2d95da2f2523bfd671284a1ceabe322f148b0e098e9291cb0c301e358ea2d5e97ed4c78d22eb927464aef04e0204bcddb448baa36184cdafe0a38c7ac7400ee1b4c9626", 0x6e}], 0x1, 0x3)
syz_emit_ethernet(0x3e, &(0x7f0000000240)=ANY=[])
sysctl$kern(&(0x7f00000000c0)={0x1, 0x59}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1, 0x0, 0x37)
recvfrom(0xffffffffffffffff, &(0x7f0000000000)=""/113, 0x71, 0x0, &(0x7f0000000080)=@in={0x2, 0x0}, 0xc)
msgsnd(0xffffffffffffffff, &(0x7f0000000200)={0x3, "79ac28db834fd07243435e34ef01a0c247e4b1b34c1b3c073ead3dfa334cf541a42617e7906da8d12494d9985707a833f3d718e3ac769b677cac7f58895d730dc2d2612304ae79a8eabedfc7d5fe1fd102de297995a1c739495cbddea38df92c1784fe6b7f10a0e0421590187e73312b3e6af3581056f7dfc5057ccc486b2243d2650d5a6087d7cbb5e82c0ffdc19e4b4423bae7f7b9e09a32ad76f983153e166ee1a49102462313e2e309523e285ef5e5d0b411d70ab4962e6cbe9b074f4daebd4f8f29871565eb85efdc7487718c271fcd4621cdb20a18b61dc5342bdf0a02719e6f0dccba979942"}, 0xf1, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x2876, 0x40000802)
r0 = open(&(0x7f0000000080)='./file0\x00', 0x70e, 0x0)
readv(r0, &(0x7f0000000040)=[{&(0x7f0000000100)=""/4096, 0x1000}], 0x1)


ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x3, 0x3a)
setsockopt(r0, 0x29, 0x6c, &(0x7f0000000040), 0x4)
setsockopt$inet6_MRT6_ADD_MIF(r0, 0x29, 0x66, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x1}, 0x38)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x34}, 0x4, &(0x7f0000000140)="3998a035daa227d1ce40394f044ed95480393e74f486aff61a92312cb952b89c09f24ddb00000000008fb1463d8635bf0f8e2f68a22421d45dcf5b7f5bdf7b47", &(0x7f0000000100)=0x40, 0x0, 0x0)


r0 = open$dir(&(0x7f0000000040)='./file0\x00', 0xae828e137847f62, 0x0)
setrlimit(0x1, &(0x7f0000000000)={0xfffffffffffffffd, 0xffffffffffffffff})
ftruncate(r0, 0x20008002)
r1 = open$dir(&(0x7f0000000440)='./file0\x00', 0x201, 0x0)
ftruncate(r1, 0x40000)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000080)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
bind$unix(r1, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
setreuid(0xee00, 0xffffffffffffffff)
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000100)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000140)=0xc)
chown(&(0x7f00000000c0)='./file0\x00', 0x0, r2)
r3 = getuid()
setreuid(0xee00, r3)
r4 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r4, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)


setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x1, &(0x7f0000000000)=[{0x0, 0x0, 0xf5}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
clock_settime(0x100000000000000, &(0x7f0000000000))


r0 = socket$inet(0x2, 0x3, 0x0)
setsockopt(r0, 0x0, 0x23, &(0x7f0000000040)="3342b19c", 0x4)
syz_emit_ethernet(0x36, &(0x7f00000004c0)={@local, @local, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @broadcast, @broadcast}, @tcp={{0x0, 0x3, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000080))
r0 = syz_open_pts()
fcntl$lock(r0, 0x8, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1000300800000})
flock(r0, 0x1)
fcntl$lock(r0, 0x8, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x100000001})
syz_open_pts()
syz_open_pts()


sendmsg$unix(0xffffffffffffffff, &(0x7f0000000440)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000040)=[@cred={0x20, 0x7}], 0x20}, 0x0)
r0 = socket(0x2, 0x2, 0x0)
sendmsg$unix(r0, &(0x7f0000001a00)={&(0x7f0000000080)=@file={0x0, '\x00'}, 0x3, 0x0, 0x0, &(0x7f0000000040)=ANY=[@ANYBLOB="14"], 0x18}, 0x0)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x100000000000000}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbdf13b9fd812eaa4e713048e69931929648", 0x14)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000380)=[{0x30, 0x0, 0x80}, {0x2d}, {0x8506}]})
syz_emit_ethernet(0x2e, &(0x7f0000000280)=ANY=[])


sysctl$kern(&(0x7f0000000000)={0x1, 0x4e}, 0x6, 0x0, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000240)=[{0x14}, {0x50}, {0x6, 0xa1}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


r0 = open(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
r1 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
writev(r1, &(0x7f0000000340)=[{&(0x7f0000000000), 0x2cfea}], 0x1000000000000013)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x3, 0x10, r0, 0x0)
poll(&(0x7f0000000ac0)=[{0xffffffffffffff9c}], 0x20000000000000d7, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
r1 = kqueue()
kevent(r1, &(0x7f0000000180)=[{{r0}, 0xfffffffffffffffe, 0x1}], 0x8, 0x0, 0x0, 0x0)
kevent(r1, 0x0, 0x0, 0x0, 0xffff, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000180)=[{0x54}, {0x4}, {0xe6}]})
syz_emit_ethernet(0x4e, &(0x7f0000000140)=ANY=[])


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
r1 = dup(r0)
setsockopt(r1, 0x1000000000029, 0xd, &(0x7f0000000000)="4c0000000000000000250004000000aa0cebc400", 0x14)


open(&(0x7f0000000200)='./file0\x00', 0x80000000000206, 0x0)
r0 = socket$inet(0x2, 0x8003, 0x0)
r1 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000530, r1)
setsockopt(r0, 0x0, 0x7, &(0x7f0000000340)="15337ac0", 0x4)
syz_emit_ethernet(0x2a, &(0x7f0000000040)=ANY=[@ANYBLOB="ffff081f000000000000ffffffffffffac1400bb"])
syz_emit_ethernet(0x2a, &(0x7f00000002c0)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, @multicast2}, @icmp=@echo}}}})
recvmmsg(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
sysctl$net_mpls(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x36, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
r2 = openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000140), 0x8, 0x0)
fchownat(r2, &(0x7f00000002c0)='./file0\x00', 0x0, 0x0, 0x6)
writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
socket(0x11, 0x3, 0x0)
socket(0x11, 0x3, 0x0)
dup2(0xffffffffffffff9c, 0xffffffffffffffff)
poll(0x0, 0x0, 0x3)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x4})
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x11}, 0x4000000000000006, 0x0, 0x0, 0x0, 0x0)
r3 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000080), 0x202, 0x0)
r4 = getppid()
fcntl$setown(r3, 0x6, r4)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xfffffffffffffffe, 0x0, 0xffffffffffffffff})
r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r3 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r3, 0xc0106924, &(0x7f00000001c0))
r4 = kqueue()
kevent(r4, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r5 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r5, 0x802069c5, &(0x7f00000001c0))
close(r2)
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r6 = socket(0x2, 0x2, 0x0)
dup2(r1, r2)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
setsockopt$inet_opts(r0, 0x0, 0x1, &(0x7f0000000040)="ee08665d19ac14d5e5134876f197a7728420aef6171504b1c3d4b3830c921bf0817a0000040000006a89dbdf", 0x2c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
connect$unix(r6, &(0x7f0000000000), 0x10)


writev(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0x80206980, &(0x7f00000001c0))
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, &(0x7f0000000000))
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x80000000002)
sysctl$kern(&(0x7f0000002240), 0x2, 0x0, 0x0, 0x0, 0x0)
setitimer(0x0, &(0x7f0000000000), 0x0)


r0 = open(&(0x7f00000001c0)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0, 0x2015, r0, 0x0)
msync(&(0x7f0000ffa000/0x4000)=nil, 0x4000, 0x6)
bind$unix(0xffffffffffffffff, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
connect$unix(0xffffffffffffffff, &(0x7f0000000000)=@file={0x0, './file0\x00'}, 0xa)
sysctl$machdep(&(0x7f0000000080)={0x7, 0xf}, 0x2, 0x0, 0x0, &(0x7f0000001100), 0x2)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
connect$unix(r1, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x3a, &(0x7f0000000140)={@broadcast, @broadcast, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x0, 0x0, @empty, @multicast1, {[@timestamp={0x44, 0x4}]}}, @tcp={{0x0, 0x0, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})
syz_emit_ethernet(0x0, 0x0)
semop(0x0, &(0x7f0000000580)=[{0x4}, {0x4, 0x0, 0x800}, {0x1, 0x3f, 0x800}, {0x1, 0x4}, {0x4, 0x1000, 0x1800}, {0x0, 0xef, 0x800}, {0x2, 0x8, 0x800}, {0x2, 0x1162, 0x400}, {0x0, 0x755, 0xc00}, {0x2, 0x0, 0x800}], 0xa)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlink(&(0x7f0000000ac0)='./file0\x00', &(0x7f0000000e40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000f40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000300)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000200)='./file0\x00')
rename(&(0x7f0000000740)='./file0\x00', &(0x7f0000000780)='./file1\x00')
rename(&(0x7f00000007c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000001040)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
ioctl$WSDISPLAYIO_GETSCREEN(r0, 0xc0245755, &(0x7f0000000240)={0x8, './file0\x00', './file0aaaaaaaaa'})
mknod$loop(&(0x7f0000000440)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000c40)={0x3, &(0x7f00000001c0)=[{0x7c}, {0x2}, {0x6, 0x0, 0x0, 0xfffffffd}]})
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000080)="35b5c242413c1026089a59583cc3", 0xe}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000080)=[{0x87}, {0x34, 0x0, 0x0, 0x9}, {0x8106}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])


setreuid(0x0, 0x0)
sysctl$net_inet_ip(&(0x7f0000000040)={0x4, 0x2, 0x0, 0x5}, 0x4, 0x0, 0x0, &(0x7f0000000100), 0x0)
r0 = dup(0xffffffffffffffff)
r1 = fcntl$dupfd(r0, 0x2, 0xffffffffffffffff)
close(r1)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040))
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000240)={0x3, &(0x7f00000000c0)=[{}, {0x1, 0x0, 0x0, 0x2}, {0x6, 0x0, 0x0, 0x8002}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0xff0a, 0x0, 0x37)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000001c0)=[{0x74}, {0x6c}, {0x810e}]})
syz_emit_ethernet(0x66, &(0x7f00000002c0)=ANY=[])


open(&(0x7f0000000180)='./file0\x00', 0x80000000000206, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x104, r0)
r1 = open$dir(&(0x7f0000000440)='./file0\x00', 0x201, 0x0)
pwritev(r1, &(0x7f0000000180)=[{&(0x7f0000000000)="f2", 0x1}], 0x1, 0x10000)
r2 = fcntl$dupfd(r1, 0x0, r1)
pwritev(r2, &(0x7f0000000040)=[{&(0x7f0000000480)="8f", 0x1}], 0x1, 0x0)
ftruncate(r1, 0x40000)
fsync(r2)


r0 = socket$inet(0x2, 0x3, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000000)={0x1, &(0x7f0000000080)=[{0x1}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
setsockopt$inet_opts(r0, 0x0, 0x200000000000b, &(0x7f0000000080)='y', 0x1)


r0 = socket(0x2, 0x3, 0x0)
r1 = socket(0x2, 0x2, 0x0)
r2 = dup(r1)
dup2(r2, r0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
connect$unix(r0, &(0x7f0000000000)=@file={0x0, '\x00'}, 0x3)


r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
mkdir(&(0x7f0000000000)='./file2\x00', 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = socket(0x2, 0x2, 0x0)
fcntl$setstatus(r3, 0x4, 0x40)
connect$inet(r3, &(0x7f0000000000), 0x10)
r4 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x1023, &(0x7f0000000040), 0x4)
close(r4)


open(&(0x7f0000000040)='./file0\x00', 0x18289, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x4, 0x1310, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000000c0)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
recvmmsg(r0, &(0x7f0000000080)={&(0x7f0000000100)={&(0x7f00000005c0)=@un=@file={0x0, ""/557}, 0x223, 0x0, 0x0, 0x0}}, 0x3, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x74}, {0x30}, {0x16}]})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
syz_emit_ethernet(0x3e, &(0x7f00000001c0)=ANY=[])


r0 = syz_open_pts()
r1 = dup(r0)
ioctl$FIONBIO(r1, 0x8004667e, &(0x7f0000000000)=0xd8d)
writev(r1, &(0x7f00000024c0)=[{&(0x7f0000000040)="b3a53b3cfa1bc5f93f49c0d591a4b5b99cabb416080aa8bf30c3a6be4aed0fde23b96ede067a593daffc1f46797685823cec13b37c12bba79e46c564db72f8e552f61e7d683a885c80ae77dc65ea1b69291d8f38873a0594771e27686dc4cc799c215a6ee45f0261d5bd1ef9b87fe5eba463b63288152838bac2a775df7d40ceccf05f913fb5923b7df8228165403b4f3472d3d77e3a03bce69c867626e638a4ef1ef627b460c315d2855e41433665ee24ceb1c5e19d6a54abae0509cb28b16242fbd71b7e3c232c51c96adb40e6b723378347e5c6db385f084ac2745c8cf98201d3dac1df9be886f4a44013cf140b5cfffd9b90f22d13317ad780cbceab9bd1d0b5c92cf953e45d9dbe487ab89dbc9d90d3a77ed18d1636767df8de9bd9920dd5836073bf65a08b722fb93624fe168b33ce44dbb8b6202b830d92449ccf64a0aecd5db12f7521d7800a432987979682cf632bb95ee8cb9f48ae6bb66c19e2668684a7d1c4e95b4187c5895aa2c52a5eaa7219916c5a18bb7140bddf97155b1b242c6ba12dee782e1dd0c05394a27469f8330672e28b8ca62510a3733263e9a60ac4f907b70a2b8ae0d46248363878198f656d67f856087348f1926fae5561636efa37ecbac0dfe8e3ae51864e0bb1fca598b48452772a5b28df0927a582e9de563c87b0d339202a46036062de8fbe9660168344e718283cb33b6207d137b6b2a5b695a587da7580216ee76e8296d84e01c013d177039e822c5f1a802874f49240ab55eac0a3e2df5ea2e08653ef9a729450aed363a3d473b0d267789ab8a35d3d931479e79a545899866ee846510de4ec7e525f505878fe29ccd5f4fd6d5149280ba025d424e20ae80984fc5a22d37f113a9aafdc6da98c042e84d447b1a44e181950200cc598c8b7918637551c98980837e0e8b4e8961674e3349cc68c88c65f16b16ead6be80d559ced095e4dcd12c39afd8041bd9fa2a8083ccf0c02b2153be9d451c6fbb8dd3167eb4bee944005c7242cc001e3f899ab8a2331048fda7dec042af33ae4b3a7544a616f68e0d11d512a1405ead6f607c6cd7987491634aeb5573d38a4aa2efbc1127da53d3626db80567b7642f12f202e2778b39734f91a4ad9db910e9a30f04b973a5a67df972c1687901cc5f902ea2921173d124c719c456f128d6e4c2ac817f1e5378da514a35ad82306a6facccf301a523d93e223de99b6ab4cb334b616bd72478e91ba0ae11dd08a72b2eb5a5888e0e71fd6ed2fa80372ae5a157cf81bbbbe65a8d25d3dd71c5cf409d72cf11bd64ad62306b9bd466565e90f5dd5c01620b80cbc335c0f572a8acf0f56790a31bcc152592241b353966b6bc16a9cfe26683262df9437615d88557b41abdeb72a1eef4682604ab0653232c559ae7911166a6cdeb8d378f8d2b1f3770c7ec78bd9b8f7bd93d25187dce14b32cb0f1561d7dc2816b0c0c230c31422be368fac1e76ec54822cfa9e9a94d5b842363722da12ce80aec6be48309eb2fe5d2d0938f658d055bfdfdd50beed689d386455e62348ee8a83f5cdd0e3d1b2c9b4f9a59788dd0479f8b76f4458b959f07eabe11c7aee3e1789d4d46b31259eac87224f51b6e275d7f36f02864d4a8d72ba4a1594cab9fb69673a0f715fc3f9b14612fde9efa9ee2237ff6176bb7b6b30d5dba32b858ba244321d74139ea9c5b7c53968d6d4e9e3f6ac0a2985a63862caafa4333884f23a40bdad7bf5c0c58d301a472e13280355ed06aa9138857976d875870743a76fbca4269b9ff9e2b89c121a7942459086f99e08a4455c3e57e96361247767d4e076a5011be19f634a76decc7388aeb809df18f822b372d76cade9738432488a4fddd79f71c03ba461b9017844192fbb859df2b1b25698c61da2dcf29811bde04aa231c427c0af6e0f187da2223a4cede9156812cd0c027f9829f00159a4d3924af0811e36ee951fd910d567c19c103ca915b7cb2008cd867cfe793e95bd7f41027aaf325a4f9ab363d21d8e8043177ff4da13a67987800da5330c3fb55e28b2079ad45ac5a5751916548e377cd66ffbb6a5f481c50098f1375f7003796e1eec915c2a853ec53467c308ed3c628f8e910cd32160949aab9ec4383b8a30c4272ee4c1ba96d908ce10a1d66ae24db4f85f7db992c72d555d40471e8522784f025bb13e065b3c0154b368e2b973b89d819891a1c8ff235d95f3f9b5e2a0361086d5203c42f88c5a14d05fc2282a1f63e972a83e245a00bb71a0d6947f5b27be2a4525f17baa852a4e6b781019e9705f9d96984260c49678488b505b4a48b2389c23c9112c18d28f3cc593bbe8279106c2497f9e72ae19d58829f592520c9ee377220b2ac37e8969396b397b5ca648cdb4d71257398f0fab0d871b000a82e46667606d7f5e08744a6a52c06ee706e44ce606b680938bc909fe2f7306d2391898515e3ace2ec9553131bd90e4e79252cb240162694f9a88c4127ef436c33752f65a488d753a5c6f05f96e98767e4d8819b4d01c07f8baf74fc34a7bd2ab4685793a8301c2ebb03c41f30605ffe3bf8a4f23ec3ea7ea1184c1a88d1633915ea7f12174d2d15f767a191d5a812ad029ce4939892a0d42ec89c5df8e473837b031620b582f4d65bffaf99d293de8aff99e6d4eb03fc4fa20efe169a654dc723e60d8347d0c3d437ca536dc92022e27bed160f0a602e20a4fcb4567a8737c2e6c59d9901127573ee36f5479eae3f70a9726cd9ffdc0fddc76d42230560e166df4b805adfe79431b6150be1a1da099a32dbd30545076d5912c1576c9037bb17040aab7df31f6389fc9795e28d73f496d94d629d4fa73f1994fd222b7adbb09227c50d20d277b129baae92277755112c4437b6a764f22a01bb4e4ef139ea2a4b533acb0cbbb6bf061be606d68da9e0a09271cf574f029f643b0b0d5332a6675025d2da93bb449692d28d6b9296b95046ff3ee35832d48f432f31025b7e293bcb500eef5781e4be5a31bf458d68164b11a85642ac28811c21592155739e547c30a2748a0c8ffef451f36224495d2880e4f2adbe270c51fd53c67d93a2ad648e4cf5ece583611e244db96a9e015c76b9ba74ed0424b38504bb23e9fe0f44f7f625232555113c5ee3ca862a0228da86628ffde54569c4541d907b2da984a6a78eae2556559531e62a2ee64bc513b5dbe64d801466d015ed068e7b89e02881d6992550c784d4be025377022b80b8ef02918b06a4a04a91f7eb5a2ab56f7aa93765b94a8a9e2cae3cf81a98fff4e42d40d89aa998092b6823bff7c2ac75e9cdbe1714422c06d53afbe58c099e1e293c30f4e08552852ab9e1e9904b6ede8371da1583bc2ea487e10a28251a1f909945058120a3e19a2c69525449f9b6ab8a2525310f8a0fe9faec44bfc7252d3085e3fe42b8295766c8d07a7d956a4f8cad1ac05196cf61cfd5743977e4bb780f695ab01180e9da808e2601f2430645c886f5c00a24bd8b1db9b7b85b50bac383c0931382e5bf19fa4025289e95d98440ac8e284d86660b688d3a9838456ade9b62b4d999fa8b3b656ff55016cf1baa923faafd9edd132dad77f29b60e4c560d18ed6b14742a7bd9174a0cde02ad4445e8629c07960c6970f80323629a16f26a70144a2d198851d9fd3341b960adbe05c952be857dca55515fc4adbbdac8f589ef35dc244f061a4b9468c7a157a792bc99904fcc31ca5927357926b0b943edd9655d8830669cb72c6098a0b0be3735910ca836f40e46b6efe55d328687020008d392415c5d371495728fd7ba8ead22270633c5b4e788b03fb220d671d5022c5d223667b0750d5a2c9f2a9f38c9725cdd38d92968b618fc9320262d46c34025bc320ad30e1b28b0037364ad3d9b472004722251f44356a49168a3f198a9207fdddadc51f0d4034243274ef27fc0eb2fe8138d733168fd770cec68e19adc039a9abfeb654a803ba175260fcf75684deb3601686cce67a67fcceddd394886644d67d291c8c4067560bf0d3e44fd694cf18bb5da8c350f6eeeaa2c1b96e4a7c5690f412610225e7f11c253be9516a29267f8110d9e6f7a5b7e6897758efe117a609e4a8ab9677d9c155dd154f8dc52659ae583f9d3e4c40f459af74467215a4e3784d3e1b5c09fa8c649a668983102b2c95ea5af74b2a17ff882e9224e307a288f04baca4213bd3db002ea503e6f758bf015953fd8c0ec37f8a3aab0cd22896b6b667288323b73f5329f59b64b72e65eabdd5e855de306bc264fb137afaaafed1b2963b1077d77d9cd101e6f4bcaef4e184aae87e16a5dcb203f9a6ae671ca776c257dbe8e8c4005a67fee4d8706cb4060230a1cec089659ec7d10a19585801485284033a09a2a584624ce3f6722a51fa95830b516a12a672be992b6c1c8531735a8b702732cddc32445a9821d03d5626e8d0af000fef39159e8427c75a362f8a07fe57d22129af53596b3a35390ab55bf4800e6915073e60d0d60f5b692f345d00af9ce26ed6d15e843ce38fec8cf185400d69167338af4f9260e532373f9f83bb99482d4c3b9bcca8debb0c3a6d80de429950a9674de1664e57c1101f8b3636555731e703e5da364583c4b618c59bffc780ea87d408129e418fc8c3cd374e6667e70a0e1ba1b1b5299df89f13e57d214225d2865ee0627197f31f5e120cd1cac3a8016375778b7f7bf693aa2afe32754a5ffa72645a53d99c6a51c934a47f0fc932ddd2a0830475c5fe2bdde30cca119f74a9228e4f1ceeaafc7bfd8114325fc833481a6eaa56caa5238853581b482ff48352a34dc2a55cf10ae8b1df90670fc2d79703b8139940680f811f1ddf14e2fa1e8524b89b919c22273ecebdaf5f9bc92dac8aa98c5d4a51a4ba4f220dee4d185e58603355b5bc0155f641ca58e38289627e7b3c6b29bb74de5a369c50661f14dc733f14e1e372461027aaed42038ab2fb34e711411f473363a74ee535e4d48e84f4702344da23e5b9da46dbbda9143d059c4691ce948738a8095bd3f853e450c2ee452823a139e3bbb2eb96c67e7d7cfeca03c222bb72a04d0706456acbd31427a59d7248f705ba270375c2c1b4f8dc62e31e2993ad7dcf37df18f79a9f2ce5b188bc131c457960e9692678e1ee8cb7ca8510fa0bdbedf091f138ac75f5b6fab0a16ec03b5c5ab45bd1ef700f921a87d07c3b674e1d0d4be5d3592e8396794074a6579d1db261216218e9672f277776fd589ed75e2003d9062da0f90f99f51ec47f06ad5fff0be38d10d6d4637148c888859b2e1f880a16a977c67f207fcc6338728e5a6570c84f9c95a47ccbda6e1d6cae9468b4454cdd705550b5a29e081ab15459ee5fa1e01d42bf006e1992e5841b775346f4a36e50c949b6d3cd32f921a62c1f8f311e26e82dda308b738c0f8d98e02a70c3e05a08aec7ed4927a4c106cda83141b39909da615d16917b91113a460eb9734c8f3c997edd1c3b6eb17c89b6fab7264c31ef0d87fbac4045f10713ffbf946dd4d16f0769788d0bf60320a28a50e4016c7d73e10fe003458e30c96f0c2426d64bbad85157f5fcedb274ec7a8242e085bb27b977adaf180d9d936fac2e4746eaa183786f4d400bf63140b6fc102fe6dde44ccaf05503aeb52b5f623856eeeda1041aa43f7be078f22c8375dc2b3bc35dc36c8914ff5b4756e63042a3fa3c2a91f3b5d8c7d0bbb37381bec48c928167300a5067641c4f0300153e6725b74c0de63baa0394d791d10e5c66bb43dc7baab8fcb0a4b4570b141fb75fcc5ba011587aa8fc830532547690e18290ebf0c8051c6", 0x1000}, {&(0x7f0000001040)="a3049b52f5cb257bc4ba4b97250fadc7d71a0425c76401fa62eb08000000064e663b5b8d9d472fe82260d9c85bac37a8ffc03cf94942a51c9f234e7c81f0eb52aba551f538a63802f7c8e17b9d5abbbc0909316ccdf2db0e816256e015154e11499a66fcd41750", 0x67}, {&(0x7f00000010c0)="07c842338e6e146c6a6a29cca892124da6a63201af451d863c8edd4bdf881813129e2b9c23d5cf19db014bae25a12d9b5af290d5ecef0016b507884371b465856a3117ac0b86ef85879dafd5f70b74a51c9484464e74ae0ba22e29b0925c1d52168c5600e397d81bd3812aa0a4d3ba4bdf95de5479d80a5ae76448fa53f33c977a9ca4106d74e3c1d8a349f73b2f4ce2e7bcdeb614c2f9ad6c1426b4fa00d9a9530b951b113b6cf90ff57cd64cd0910a593192441081f2c721e6bff6bc43b2d81fd3691bbd12e302a89860cdd9494ae358ccd93e1ab9861476", 0xd9}, {&(0x7f00000011c0)="3b7faaa2cb5abb869175", 0xa}, {&(0x7f0000001200)="e36f84b7a4dc7addfd6afd6a98f0e0ea790ff229baaffce1ce2ef09eae3dc70f927701f25085a14c6b8c612467edce316eca3a3de78e0c9483f349f126dca657fbef1056082d2654286602da34d3cf4d33e5584515637009bfad3e5b026e60e5902fd60a19d9938ec6e392448661e0056076e5d0b9f0e913c7", 0x79}, {&(0x7f0000001280)="4249aeca0542351f545f1cc0f4d023b0e9e81307263720c32a41a826efd68897709611e9092c7f5715a7f8cd56d26da1bd69973647064e227bd20f8c06f83c4291cdb5e5a53013fcc429ef1d53b19c9152ff5d2910486248a84552e8bceb327d5efb10d807ac2aaafa0b6d84af9f746702839443a30d5d92944b5f6a035ca26e6edfce7d850c5b19fb8b2af3929e1fed357ad97c6fae95007b5f2812030c17c541b3f505b2de11ed8ca5121cc6a6353f04ea9954addaa6e914b15e69a717c30995d529c87bb16f56dd0adc88", 0xcc}, {&(0x7f0000001380)="9b9ccb2e9c8fa227124dd10f58c1f558dde9b636262e49fba6575ffdd70694c58e514e4aeccfbbe3eb00f3e05cd1f9720058f2cb4a2f2c1e78e207968f45c85d02eac9853da75122bd376871bbeb91f4f87f02c41553d55cc1f1c69c9bb7c5c37798864c19724d9e34bd9b112ae403def39042f135e51dfe5a9620efa4114d46b1f09c70e40e55c2701a173f7b735495346a6ed3de53b1ed3603f324e7c611640a88b9e2742001ff1ee692850929bf0ce84ac35c378d9b498cdf76321c49b97164681b4ce2a439065bf2a4df3688adaf5a592e89cef845fb669186b859a4", 0xde}, {&(0x7f0000001480)="b708d4dbc5a89b549f64c5e586e2634722079331b57ab4f033f8092a43e5327d90aa4c1dfa86ecee017fd637449b0654dac645110b1459cbefc8ae0cc2be5ff1cec9a0af362173b5565440cc06f63273cc185edd63d0ae3470a13f4ce8321edaed27233a14696a0506ee9c1a838eb984df9120812db7a82aea5ebc9921ee6b29cc4f50f7faab1a722562cf5b49f520c6e6f86bdd484858b70e502ad70e77486455704852accbedb84a8033b652cd1a89fa9f677527447517cf37d7334c96047f1d7d76f91574741777ac1a13be4fa8d4a199a3eca19f5915c5df5fdcdc9661c952e2faa33edbbdc45eef03391585fc02321e00f112b836cb84e2c132e8253e0259b6579a175b8ea3abe36f7544d6c57b95c8e0db87ef5395600ce97584fa4a65cbb64b373f120d483b93620c87e554a05c5e28d129559fe77a2b7368d564893bceb442b5bfa114d52b17dab218da83a1a4c3cf538e470eff5b687007723b35375e656d0cb709bac2e5ce0be664ac3cb3b017f09feb84c04810e377b18e622a56500d2db02354caf5fcfab67e8e7acb55df03757e41f55272d12239d6ef0e84721431e43a982c3458aaeeacfbd18078a15721ba787fca44cfc0e110797fafd0045280dd0ec74901ac7f40f2c3c4418f8481e192c9cf723566dd1447d2d982c7415beeb3153a3fd416b0d70943e0ba8af10c4417e0c03d3554e54e9314865b37ed9fa3020f47d52851e2c35e34867d59a9712c95ab4b04919297cfcb3686a9e14d34783d01dd870d3927e516123591e3942927eed8d2899eedbe6eb0abc6f84abdbca841cc0b30b1928c5962fb1585bee36958823afbba07a65be3707ef935743ba9789e94fc299cae64204ef6e9d683573ef19723876bf9eebbeff94ecc9629cc5dfc34ea25d873c1c8e61abc4d94b6041c961e39c57d20b9beaa06793cee6b9a1e80b2ab9fb4aba8c612ef3fcc2182508a730e480b4660a5fae93b942eef5b66c87b5bcfe2e9d04abe5cfb93083934af9673010ac66f74ec0a3cda14b1306a5bd3d2d98d74eae55ac8ad6f90c7f948ad39c7cbfb5e92f7e267daae17bb281fdf615496c3acadf580d51805e5e2a1e4318d06182953bcecf888b9f7aacb8bfc7727e726ab1fc01c093eb1e389852f7d83e7d864dfa1369cd31887c2f2a8965a367723ca2db3904efddcc1a7c531c3fb7ddbbd9a548542fb35744d8c4a2154881799c1f29a96895eb289ca58b554beb109048a5426834fbffcbb4d96d2f1343c4e0e8928d73595b335811dfc81342136862b86ce5e40c4bfeded3b4ef020d7cf85b85e4bdedad9534bd1985c1f54c08f0f5eedd341f3aeb406103619627a0159e0b6f880c552c509467305d09f416aa20b7db91a4654a232e12d350e89f5328f84bdc324255f906570e6c1ba688e7d854a5f49501a83c75cb77d02835f9f4b6c5dde1e02632792eba1d113d67f9833c976001ccc158ef07db561e5928495b2a637b26a15e07255696c397b7cbbec5a0f7e58b9b1f61e5527fa1d8683bc0c4c70d9719aed9f1f754d4daa21cba2ad3387667a8e048b6ae9e4334c70d62e2069b09a20ddcce229ae94ddf8d28212c87afef9442f6d3e9f271bf5815500df5e360ce681418b32ae9188e7e2d160cb64d4c86575fc62fb60d48272a331c9c37a7edef32f6c52d98ef1564b4750366476deba38dd3b994699e17fae2f42165654c8fc3988fd81d06a8f5c18275f2d0338fd5998d24d1b07304cb4c4366d549c366b370008b2a43f1ec764fac748f25c1eac37ab1adbfce9a37f4a231bed3af757fa17a4cb12f4f0cf2e6f22c96c415081219cf7d1ed670eaa8837e68b0ca8046ff39992f25becaeff5f3a3b125d799abdca623cabb474db50e74274a8138f2eec57b6e350314726e003b0f0a78d164bb554f9aaa13c954b311657b427583986cacd12e9bb1052b0395f69ba4c5156b8cf059a3da13906209f16a61c97f07d4d9dc5f125e06bda8cffbb315aa764df860edcb9f3bee6212d694b64a16ea4c40961be0a3f894029168baed25f344bf7fb8675fcb9b0cac0d81c8a26cb99d39a57b9fef654fad0d62fd0f793097988f76b1506d200c4dd23051f298c1766bd311e37744b6721fb25519ce48135e233ee88be6cf16386d711e404deb5513516391233ed31f00966bad6c2f6cb1bbb780c8fb7e70976929f53e79e83358059e2cebc51da0252ef51b2b9d4b3cfabec5bacea6f12ff174b0ca240513140687121e76fcd4c4e1fffcfd9d36cb6582935627c1eac72a1152ca14ccaed3cba2df22becb59722b2d8c9a3a0bdde1db829c8fdd8d1ba944312068826e0a0b615cb9fded6ec6a753d4da7b61979760882df9813ab6aa8ad444ade9261f8e226b54ee02b20ebd27eb62b8dac8540a2b6980fc33947713ce92585ce8dcb94ff70e21ecf0a7a176436101c967cacea86b0671f9e1ce663d2b7f83b83670f7556ecec155e7a6756a121ec5442500fd296a7106fe8c78995f200dac16484f785251f562467abf669079c5f21cfd9b19fd65b2afca16c7baff1ed260f2ca2ad54b742a5fb5dd2cf6158b4209273146fbd77fa9c5cdf86e507b9aa72d4a00b58e3058877051840f8e255a71208caf04bc008b52b08b0637e051b05f869fbfbb87d53b6d97416705ad318c4166c2721911bf95c5f839a337b6dd7341983c630b14a4516034336710247c55327356ef2362540daf22828197994b6cdb1e8011c926a60b87c2af3274298c15e91957b25b842fc92165cdcf776d640cc29576822f8b756fa6bc068fcbf113e4ed3e195203e04f4682a2e6f26c2491dff74b1569c9d4b002ccdfe101b698429c4dcd9a75ef30e30884793793d0075335b14ab3a637d781dfb497f13add0eb54fd3f64018d9a8234f77e8a705ea77cdf035510eb90b1cd2afd26c3d03cc434aee84220e002d27d4b4b4b1f83553de4682ab4e46f96198ee70312031a11a41d7c051294d0c55cf5c786bd5a3807c9b64f460a99dfdbd4509ebd06601fea76b1f24df502cfb6d27b731fd295ec23ff11ba213aa80b7a09309f2eddb86669f0cd47d98608d479e985fe14c1ef9fe25b7159c56b7342103387568143644a0f8847e104ecb1b7dbf0fe20b8e2b28d6f45ee0a6373be37c8f0a57eb6bf0988c8ad0ef8f2a5f2fa08e0d6d50e2333be40ce79a68261d969bc01debb0933ca0d46122dbf5a4c1c6870151454830c6512bb8511326e0fbb6b0856d635e6d727be9a29d3f4e986a157c0a3202fb50a0cb85a1e0cd57a820ef2cd2199f316164d94ea760bb3ef20eb8d977b377e921dc4dfb7a097eca723c587ef78296a3860aa99ebacdf05547ef7347e68b036f872fbcaa3a7961d57c77618c74b82141eab25052e71d053af68da73917bababc9baa8cc9a9a689f195d22a47c0a8abe191a3068bb8557c6dbb3adbd7a38802b3c8abc3e4b70a977baae27132d5cee0e761ada3098c5b0196ccd35638ed13b3d8189f3c8c814a34cd96ee7ad705844b5fa2df923e7435db221cf9bdfc8e4e902de395a3d0335844211766b22ac5325edd8525aa5c08893cdcdb8d0cb9fe141b9ae325ce387dac8fa71424e38fada76cdd1ad008d55534770c3038be1234a52684c43b31f357169a01d40eec45078fa1a9a757308786c5d5ba85b182f30d215021e4585735733930b28a176882ae37c644b902de0493bc95bc880ca247bfda8b1b1ccdae89a60df3a1900b95ab2f786ac7f7786a89a8ffc935dbbc904b24a7f7a92a81b84adab50d4a8bf536a255fa5a8d18c8be591cf4850e2393d2477fa56d509389e86a6a0ed827ac02344d6091f843d3fa4cde269edaf8a4e7eec70222475ccd053e2f94f14f72306ad1038de70f844e2a9dd3f7a07f142db3d9e7feccc638790191c23f9fe7feccadb15e8f98418df969fc32dd07d5ec91a4be40b32523aaec8f23c0032e2583940fbe0ff2737c2fc127c6b6ccebbcde723fa2929f8fa2faf833b6fd3435eaae3813a53d1c8c9092755cb7bcc44695c45103af7a4274d093ece33b3d7f112e0bd81c5d4300e8d1f36e953cb8684f3ee584409e69d3f38ff71b1a3e9665b6d376a84ebd37a51338e88d98b74116e55c8c1bb5879fed2263bb78b2fe1c7a76476166bae96254c3e9690e03d05fab95f3ff4944cebe65ddd37c5966c428528bcef74a7c12c9ca0658e36b4d1893285a5420072f5a1ad873f18f63809", 0xba8}], 0x8)
writev(r1, &(0x7f0000002380)=[{&(0x7f0000002040)="ae", 0x1}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000100)=[{0x20}, {0x2}, {0x6}]})
sysctl$hw(&(0x7f0000000000)={0x6, 0x11}, 0x2, 0x0, 0x0, &(0x7f0000000240), 0x0)
mprotect(&(0x7f0000ffe000/0x1000)=nil, 0x1000, 0x4)
r1 = open(&(0x7f0000000000)='./file1\x00', 0x261, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x200, 0x0)
rename(&(0x7f00000001c0)='./file0\x00', &(0x7f0000000200)='./file1\x00')
mmap(&(0x7f0000ffd000/0x1000)=nil, 0x1000, 0x0, 0x10, r1, 0x0)
close(r1)
rename(&(0x7f0000000180)='./file1\x00', &(0x7f0000000240)='./file1\x00')
r2 = open(&(0x7f0000000000)='./file0\x00', 0x200, 0x0)
mmap(&(0x7f0000ffd000/0x3000)=nil, 0x3000, 0x0, 0x10, r2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000300)={0x2, &(0x7f00000000c0)=[{}, {0x2}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x2c}, 0x2, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7a", 0x0, 0x0, 0x0)
sysctl$hw(&(0x7f0000000040)={0x6, 0x10}, 0x2, &(0x7f0000000080), 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
r3 = socket(0x2, 0x3, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f0000000000), 0x1)
setsockopt$sock_int(r3, 0xffff, 0x1001, &(0x7f0000000100)=0x20000, 0x4)
connect$unix(r3, &(0x7f0000000000), 0x10)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
r1 = dup(r0)
ioctl$BIOCSBLEN(r1, 0xc0044266, &(0x7f0000000100))
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
syz_emit_ethernet(0x138, &(0x7f0000000280)=ANY=[])
syz_emit_ethernet(0x36, &(0x7f0000000000)={@random="14f769f9b7bd", @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x28}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})
readv(r1, &(0x7f0000000000)=[{&(0x7f0000000180)=""/15, 0xf}, {&(0x7f0000000040)=""/17, 0x11}], 0x2)


open(&(0x7f00000001c0)='./file0\x00', 0x2e1, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)
writev(0xffffffffffffffff, &(0x7f0000000240), 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
socket$inet(0x2, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
msync(&(0x7f0000ffa000/0x4000)=nil, 0x4000, 0x6)


seteuid(0xffffffffffffffff)
shmget(0x1, 0x2000, 0x40, &(0x7f0000095000/0x2000)=nil)


mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
open(&(0x7f0000000480)='./file0\x00', 0x0, 0x0)
r0 = open(&(0x7f00000000c0)='./file0\x00', 0x1, 0x0)
ioctl$FIONREAD(r0, 0x8028698c, &(0x7f0000000000))


r0 = syz_open_pts()
readv(r0, &(0x7f00000012c0)=[{&(0x7f0000001200)=""/1, 0x1}], 0x1)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0xffffff9a, 0x0, "b07b1f660000000000002000"})
syz_open_pts()
ioctl$TIOCSETAF(r0, 0x802c7416, &(0x7f0000000080)={0x0, 0x0, 0x80000001, 0x0, "0fdb000000000000040600000000000000d900"})


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x1, &(0x7f00000000c0)=[{}]})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r1 = socket(0x18, 0x3, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000140)=[{0x48, 0x0, 0x0, 0x40}, {0x7c}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000540)={<r3=>0xffffffffffffffff})
getsockopt$sock_cred(r3, 0xffff, 0x1022, &(0x7f0000000100)={0x0, 0x0, <r4=>0x0}, &(0x7f0000000180)=0xc)
chown(&(0x7f0000000080)='./file0\x00', 0x0, r4)
setreuid(0x0, 0x0)
chdir(&(0x7f0000000100)='./file0\x00')
unveil(&(0x7f0000000140)='./file0\x00', &(0x7f00000001c0)='c\x00')
getsockname$inet(r1, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
r5 = socket(0x18, 0x2, 0x0)
r6 = socket(0x18, 0x2, 0x0)
syz_emit_ethernet(0x2e, &(0x7f0000000140)={@broadcast, @remote, [], {@ipv4={0x800, {{0x6, 0x4, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x1, 0x0, @remote={0xac, 0x14, 0x0}, @multicast2, {[@lsrr={0x83, 0x3}]}}, @icmp=@generic={0x9, 0x0, 0x0, "e10f46cf"}}}}})
connect$unix(r5, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
setrlimit(0x8, 0x0)
setsockopt$sock_linger(r5, 0xffff, 0x80, 0x0, 0x0)
dup2(r5, r6)
sendmsg(r6, &(0x7f0000000e00)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000140)={0x3, &(0x7f0000000100)=[{0x64}, {0xc}, {0x6, 0x0, 0x0, 0xfffffffe}]})
writev(r0, &(0x7f0000000080)=[{&(0x7f00000000c0)="d3d9bc6f7a689f455f7bc4e71ba7", 0xe}], 0x1)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x2, &(0x7f00000000c0)=[{}, {0x4, 0x0, 0x0, 0xfffffffc}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x27}, 0x4, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x50, 0x0, 0x2e)
open$dir(&(0x7f0000000000)='./file0\x00', 0x40, 0x14c)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
r1 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
r2 = getpgid(0x0)
fcntl$setown(r1, 0x6, r2)
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0xb2}, 0x0, 0x0, 0x0, 0xffffffffffffffff})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x0, 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
r3 = msgget$private(0x0, 0x0)
msgsnd(r3, &(0x7f00000000c0)=ANY=[@ANYRES32], 0x1f, 0x800)
pipe(&(0x7f00000000c0))
execve(0x0, 0x0, 0x0)
msgsnd(r3, 0x0, 0x401, 0x0)
msgsnd(0x0, 0x0, 0x401, 0x0)
open$dir(&(0x7f0000000440)='./file1\x00', 0x0, 0x0)
r4 = open(&(0x7f00000003c0)='./bus\x00', 0x0, 0x0)
r5 = shmget$private(0x0, 0x2000, 0x0, &(0x7f0000ffc000/0x2000)=nil)
setuid(0xee01)
shmctl$IPC_STAT(r5, 0x2, 0x0)
ioctl$VMM_IOC_READREGS(r4, 0xc2485607, &(0x7f0000000880))
syz_emit_ethernet(0x3e, &(0x7f0000000000)={@broadcast, @broadcast, [], {@ipv4={0x800, {{0x7, 0x4, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, @broadcast, @multicast2, {[@generic={0x88, 0x2}, @timestamp={0x44, 0x4}]}}, @tcp={{0x2, 0x2, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})
msgctl$IPC_RMID(r3, 0x0)
writev(r0, &(0x7f0000000280)=[{&(0x7f0000000000)='T5', 0x2}], 0x1)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
r6 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r6, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r6, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000280)=[{0x1c, 0x0, 0x0, 0xfffffffc}, {0x4d, 0x0, 0x0, 0x1}, {0x6}]})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000180)=[{0x24}, {0x4d}, {0x6}]})
syz_emit_ethernet(0x7e, &(0x7f00000002c0)=ANY=[])


mkdir(&(0x7f0000000000)='./file0\x00', 0xad)
setreuid(0xee00, 0x0)
r0 = getuid()
chown(&(0x7f0000000180)='./file0\x00', r0, 0x0)
r1 = getuid()
seteuid(r1)
unveil(&(0x7f0000000140)='./file0/file0\x00', &(0x7f0000000040)='x\x00')


sysctl$vm(0x0, 0x0, &(0x7f0000000040)="c06d154be3aee5f8", 0x0, 0x0, 0x0)
syz_open_pts()
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x1, 0x0)
r1 = socket(0x18, 0x2, 0x0)
close(r1)
socket(0x2, 0x7, 0x8)
connect$unix(r1, &(0x7f0000000000)=@abs={0x682eb13985c518e6, 0x7}, 0x8)
r2 = openat(0xffffffffffffff9c, &(0x7f0000000040)='.\x00', 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000695000/0x2000)=nil, &(0x7f0000159000/0x2000)=nil, 0x1}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000690000/0x4000)=nil}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ff7000/0x3000)=nil, 0xd8}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f0000ff2000/0x2000)=nil, 0x3}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000604000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000691000/0x2000)=nil, &(0x7f0000ff8000/0x4000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil, 0x9}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil}], './file0\x00'})
r3 = socket(0x800000018, 0x1, 0x0)
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff}, 0x0, 0x8000000000000000})
bind$unix(r3, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
r4 = semget$private(0x0, 0x2, 0x86)
semget$private(0x0, 0x7, 0xb)
semctl$GETALL(r4, 0x0, 0x6, &(0x7f0000001240)=""/4096)
sysctl$hw(&(0x7f0000000200)={0x6, 0x18}, 0x2, 0x0, 0x0, &(0x7f0000000140)="01000000", 0x4)
ioctl$VNDIOCSET(r2, 0xc0384600, &(0x7f00000003c0)={&(0x7f0000000340)='./bus/file0\x00', 0x5, &(0x7f0000000380)='./file0\x00', 0x8})
writev(0xffffffffffffffff, &(0x7f0000000300)=[{&(0x7f0000000140)="f005c71031c1c5f421277b09000000000000007a091a2f47be787538ec7a89ec5ed66daa731ddc384ecc690869a0aa2266affdf772d7a360ee0f15fa664f557bb45071fe9b6d9d28e6e2589000f6a64f370b9e336987d77b38f7aada5309e46a81e0e2efa087aa9f5f89934fdbd2ed96e7234b8972b273e810ca9962a8f461d3a05711a63027321ff62c", 0x8a}], 0x1)
r5 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r5, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x4e, 0x0)
r6 = openat$wsmouse(0xffffffffffffff9c, 0x0, 0x10000, 0x0)
ioctl$FIOASYNC(r6, 0x8004667d, &(0x7f0000000040))
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r7=>0xffffffffffffffff})
connect$unix(r0, &(0x7f00000002c0)=@file={0x0, './bus/file0\x00'}, 0xe)
r8 = socket$inet6(0x18, 0x3, 0x0)
getsockopt(r8, 0x29, 0x37, 0x0, 0x0)
ioctl$FIONREAD(r7, 0xc0106924, &(0x7f00000001c0))


sysctl$kern(0x0, 0x0, &(0x7f0000000100)='q', 0x0, 0x0, 0x0)
syz_emit_ethernet(0x4de, &(0x7f0000000000)=ANY=[@ANYBLOB="aaaaaaaaaaaa9cd7361987d486dd60ecea6604a80000fe8000000000000089750e6b000000aaff0200000000000000000000000000010020"])


openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x12a, &(0x7f0000000080)=ANY=[@ANYBLOB="b96d9900533a8f943f3614ef86dd60000000000b000080000000000000000000000000000000ff020000000000000000000000000001001b"])


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f0000000080)={&(0x7f0000000040)=[{}], 0x1})
ioctl$WSMOUSEIO_GETPARAMS(r0, 0x80105727, &(0x7f0000000080)={&(0x7f0000002640)})


socketpair(0x1, 0x5, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
write(r1, 0x0, 0x0)
fcntl$setstatus(r1, 0x4, 0x40)
recvmsg(r0, &(0x7f0000000280)={0x0, 0x0, 0x0}, 0x0)


writev(0xffffffffffffffff, &(0x7f00000000c0)=[{&(0x7f0000000180)="a91d572018dfc112b211c9b7f9dbdc4e9c7752845816984bb622d74a83050000000fd383c857ce942c438f2ea02b33f59d83749b711951efa88a2a6dcd049f666033a9f518c180b3eefaedee", 0x4c}], 0x1)
r0 = socket(0x11, 0x3, 0x0)
open$dir(&(0x7f0000000100)='./file0\x00', 0x1, 0x158)
read(0xffffffffffffffff, 0x0, 0x0)
sysctl$net_inet_ah(&(0x7f0000000180)={0x4, 0x2, 0x4, 0x2}, 0x4, 0x0, 0x0, 0x0, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b10005136000009f05003e0800000000331c13fecea10500fef96ecfc72fd3357a068d02bc31a3a5673039d2d236acf20b7804be38164991f7cccf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f4d335c223e7d026ba8faff0037720fd38bfbb770c1f5a872c881e2772ec5a10400000000000000361b1257aea8c5d0002012000000000000880d6633c556ae9b287948a62310", 0x9b, 0x0, 0x0, 0x0)
r1 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
linkat(r1, &(0x7f0000000040)='./file0\x00', 0xffffffffffffff9c, &(0x7f0000000080)='./file0\x00', 0x4)
writev(0xffffffffffffffff, &(0x7f0000000000)=[{&(0x7f0000000380)}], 0x1)
r2 = socket$unix(0x1, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x80206979, &(0x7f0000000000))
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x2, 0x0)
syz_emit_ethernet(0x1a, &(0x7f0000000000)=ANY=[@ANYBLOB="ffffffffffffffffffffffff8035"])


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000200)="8b8c7e5e4a790900", 0x8}], 0x1)
ioctl$TIOCSETAW(r1, 0x802c7415, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x0, "8aaf15d143e761109ea9538d53119a03261e4f5d"})
ioctl$TIOCDRAIN(r1, 0x2000745e)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000000)={0x0, 0x0, 0xffffdffc, 0xffffffbf, "ffff0900870000ff9e0b000000ff560000000014"})
close(r0)
poll(&(0x7f0000000240)=[{r1, 0x68}], 0x1, 0x0)


r0 = socket(0x18, 0x3, 0x0)
getsockopt$sock_int(r0, 0xffff, 0x100, &(0x7f0000000180), &(0x7f00000001c0)=0x4)


r0 = syz_open_pts()
readv(r0, &(0x7f0000000540)=[{&(0x7f0000000340)=""/233, 0xe9}, {&(0x7f0000000440)=""/196, 0xc4}], 0x2)
syz_open_pts()
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f00000001c0)=[{}, {0x3, 0x2, 0x0, 0xb47}, {0x1, 0xff, 0x80, 0x9}]})
sysctl$kern(0x0, 0x0, 0x0, &(0x7f0000000080), 0x0, 0x0)
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x0)
open(&(0x7f0000000080)='./bus\x00', 0x2, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
open(&(0x7f0000000580)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x200, 0x0)
r1 = open$dir(0x0, 0x0, 0xc8)
socket(0x11, 0x3, 0x0)
shmctl$IPC_SET(0x0, 0x1, 0x0)
r2 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r3 = fcntl$dupfd(r2, 0x0, r2)
ktrace(&(0x7f0000000040)='./file0\x00', 0x4, 0x6000043e, 0xffffffffffffffff)
r4 = open(&(0x7f0000000180)='./bus\x00', 0x1, 0x5a)
mknod$loop(0x0, 0x0, 0x1)
mmap(&(0x7f0000000000/0x13000)=nil, 0x13000, 0x1, 0x10, r4, 0x0)
write(r3, &(0x7f0000000140)='p', 0x1)
r5 = socket(0x18, 0x1, 0xfd)
setsockopt(r5, 0x0, 0x0, &(0x7f0000000280)="eb", 0x1)
unlinkat(r1, &(0x7f00000000c0)='./file0\x00', 0x0)
r6 = socket(0x18, 0x3, 0x0)
getsockopt$inet_opts(r6, 0x3a, 0x0, 0x0, 0x0)
socket(0x11, 0x0, 0x0)
r7 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r7, 0x80085761, &(0x7f0000000100)={0x3})
mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
mknod$loop(&(0x7f0000000000)='./file0\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
r1 = kqueue()
r2 = kqueue()
r3 = dup(r2)
kevent(0xffffffffffffffff, &(0x7f00000003c0)=[{{r3}, 0xffffffffffffffff, 0xc5}], 0x0, 0x0, 0x0, 0x0)
utimensat(0xffffffffffffffff, 0x0, &(0x7f0000000100)={{0x0, 0xfffffffffffffffe}}, 0x0)
kevent(r2, &(0x7f00000000c0), 0x138, 0x0, 0xffffffff, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000180)=[{{r1}, 0xffffffffffffffff, 0xdcd8c4bc089e638d}], 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000240)={0xffffffffffffffff, <r4=>0xffffffffffffffff})
kevent(r1, &(0x7f0000000400)=[{{r4}, 0xfffffffffffffffe, 0x1}, {{r2}, 0xffffffffffffffff, 0x21}], 0x2, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000200)=[{{}, 0xfffffffffffffff9, 0x1}], 0x0, 0x0)
r5 = kqueue()
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f00000000c0)=[{{r5}, 0xffffffffffffffff, 0x6f}], 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000080)=[{{r0}, 0xfffffffffffffffe, 0x87}], 0x0, 0x0)
kevent(r5, &(0x7f0000000080), 0xe4a, 0x0, 0xa9fa, 0x0)
kevent(r5, 0x0, 0x0, &(0x7f00000001c0), 0x9, 0x0)
openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x20, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000080)=[{0x5}, {0x2}, {0x6, 0x0, 0x0, 0x6d7}]})
writev(r0, &(0x7f0000000000)=[{&(0x7f00000001c0)="d2bc78b52324b9a50c786b26df53", 0xe}], 0x1)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f00000004c0), 0x2, 0x0)
writev(r0, &(0x7f0000002100)=[{&(0x7f0000000700)="9b9b6d4c", 0x4}, {&(0x7f0000001100)="968ce1c69d9498126527e1ad5174636898ad874ffb39b42f574f4f4cbc90acc1eb117d7e3bf3d52de5d57a7f2ec5c0d23a134ee65c5f70eee9f43f9c71342063cfdf9eb60982d3ed95722aa70920bd1c6331d3e4e1891e80699e9058b7a39ae56ffa1c545b3dfa90cd36699a984bdaedff8dbf3d11d74e26036a7fc36b1f53740b772d7c7996271e18c83078e8d21903e3b374f634d48cd37e5d788d9dc9b1a5fdc4094f0307931dc693d646727c74325a288835bf83c9029b4f9fbc275c8ed723a954b542d3ac1e03143f3b9b9dfc4ba58695c2b8fc369391f84321f6922d19ff52774d77e9fa5da31ec4180e68a9ac2a24b4788e0d54cc485b1bc332349f35a212a64747978dfee5e025493fbcfd60f1aab1f6085ab1c461eb816699c3fc078d367ab0fd6a2c1afde3f1fd1071d5e7856e8c6f726efd37d9e615dbc457767041b51b63a5af8fbfa98b1bde28dbcfa9d698abb946f831ef786761b64412992b6242449fbe6ba627d64dbe611cca8bf596032a8383c693e0fd9da49f09d66b03f266190082f44d73", 0x188}], 0x2)
writev(r0, &(0x7f0000000100)=[{&(0x7f0000000140)="f546a8", 0x3}], 0x1)
execve(0x0, 0x0, 0x0)


sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x13}, 0x4, 0x0, 0x0, &(0x7f0000000140)="53183374", 0xffffffba)
r0 = openat$pf(0xffffffffffffff9c, &(0x7f0000000080), 0x40, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x37}, 0x4, &(0x7f0000000000)="71f91e3471ac0058bc5a91501d942400b5e1a0757cb9af769c7afec37082", &(0x7f0000000080)=0x56, 0x0, 0x2e)
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f00000000c0), 0xc)
sysctl$hw(&(0x7f0000000000)={0x6, 0x12}, 0x2, &(0x7f0000000040), 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
sysctl$net_inet_ip(&(0x7f0000000300)={0x4, 0x2, 0x0, 0x25}, 0x4, &(0x7f00000013c0), 0x0, &(0x7f0000001480), 0x0)
setitimer(0x1, &(0x7f0000000280)={{0x2, 0x4}, {0x20, 0x9}}, &(0x7f00000002c0))
r1 = getuid()
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000140)={{0x0, r1, 0xffffffffffffffff, 0x0, 0xffffffffffffffff, 0x7, 0x3ff}})
r2 = msgget$private(0x0, 0x0)
msgrcv(0x0, 0x0, 0x0, 0x0, 0x0)
pipe(0x0)
ioctl$FIOASYNC(0xffffffffffffffff, 0x8004667d, 0x0)
r3 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(r3, &(0x7f0000001580)=[{0x0}], 0x1)
r4 = dup(r3)
r5 = dup2(r3, r4)
sysctl$net_inet_tcp(&(0x7f0000000100)={0x4, 0x2, 0x6, 0x12}, 0x4, &(0x7f0000000200)="2daeddd3ede9d7aadb3706aae5a410a836af01263fa075d7865d0fec53512ffd74e0b824da9ac3c89baef6c6b43da1bf126a190443766ab70aeccb2ec5c6fe3c9a96e67924087392569678b2c0301336ed240b0b", &(0x7f0000000340)=0x54, &(0x7f0000000380)="6405978227d578ae9a406d57ce8dfdb4d19da87ae6b860f9bbcdfa3f455bfdc1f3881e272185f9e5b28c6fae8b82784ccc012515b244ef78d9ed05fbe5611a85b347165cf8d13cf16e7898b7a49ac041bb3e869503b3d4a865712eca63eaddd7d262b461855e19c1cce73bc62097b6eb9c07d7a3e8", 0x75)
read(0xffffffffffffffff, 0x0, 0x0)
msgsnd(r2, &(0x7f0000001540)=ANY=[@ANYRESHEX=r5], 0x32, 0x0)
msgrcv(r2, &(0x7f00000001c0)={0x0, ""/14}, 0x16, 0x0, 0x800)
r6 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r6, 0xc0106924, &(0x7f00000001c0))
ioctl$FIONREAD(r6, 0x4004667f, &(0x7f00000000c0))
r7 = kqueue()
kevent(r7, &(0x7f0000000000)=[{{r7}, 0xffffffffffffffff, 0x8, 0x4, 0x3, 0x3}], 0x101, &(0x7f0000000040)=[{{}, 0xffffffffffffffff, 0x2d, 0x20}, {{r7}, 0xfffffffffffffff8, 0x0, 0x0, 0x0, 0xdd3}], 0x0, 0x0)
setsockopt$sock_int(r6, 0xffff, 0x10, 0x0, 0x0)


r0 = open(&(0x7f0000000000)='./file0\x00', 0x9cab835cfdc52675, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x2, 0x4001, 0x0)
r2 = dup(r1)
r3 = fcntl$dupfd(r2, 0x2, 0xffffffffffffffff)
close(r3)
r4 = socket(0x2, 0x2, 0x0)
connect$inet(r4, &(0x7f0000000000), 0x10)
setsockopt$sock_int(r3, 0xffff, 0x1023, &(0x7f0000000040), 0x4)
shutdown(r4, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0xa011, r0, 0x0)
select(0x40, &(0x7f0000000140), 0x0, &(0x7f0000000200)={0xffffffffffffffcf}, 0x0)


sysctl$vm(&(0x7f0000000380)={0x2, 0x3}, 0x2, &(0x7f0000000340)="6130c04aad66b8ba9155081015b060a3c6dba7f1a713f6a6abb0ccb9c7f3a50a848dc6f2c089e1bfcec221a0c380e3b0b7e482980eba5786fe1af216ebc387", 0x0, &(0x7f0000000240), 0x3)
open(&(0x7f0000000040)='./file0\x00', 0xfffe, 0x51)
r0 = socket(0x18, 0x0, 0x0)
shutdown(r0, 0x1)
r1 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
writev(r1, &(0x7f0000000280)=[{0x0}], 0x1)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000540)={<r2=>0xffffffffffffffff})
ioctl$VMM_IOC_RUN(0xffffffffffffffff, 0xc0205602, &(0x7f0000000300)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000040)={{}, {[], [], [], [], [], {}, {0x0, 0x0, 0x0, 0x9}}}, 0x0, 0x7f})
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x2}, 0x4, 0x0, 0x0, &(0x7f0000000280), 0x4)
getsockopt$sock_cred(r2, 0xffff, 0x1022, &(0x7f0000000100), &(0x7f0000000180)=0xc)
r3 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r3, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r3, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
r4 = socket(0x800000018, 0x1, 0x0)
ioctl$TIOCSETAF(0xffffffffffffffff, 0x802c7416, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "6aa4a24499c59ff5d619fd63d50671e2dc2042df", 0x0, 0x3})
setsockopt$sock_int(r4, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r4, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000240)=[{0x81}, {0x15}, {0x6}]})
syz_extract_tcp_res(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000040)=[{0x1c}, {0x14}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000100)=ANY=[])


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000080)='\x00\x00\x00\x00', 0x4)
r1 = socket(0x2, 0x3, 0x0)
dup2(r0, r1)
setsockopt(r1, 0x1000000029, 0x9, 0x0, 0x0)


sysctl$net_inet_ip(&(0x7f0000000280)={0x4, 0x2, 0x0, 0x19}, 0x4, 0x0, 0x0, &(0x7f00000002c0)="ef7623ba3c93204d8028df9ef5ea234abf5ea836", 0x14)


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000100)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000140)=0xc)
setregid(0x0, r1)
r2 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000424, r2)
setregid(0x0, 0x0)
ktrace(&(0x7f0000000180)='./file0\x00', 0x4, 0x20000000, r2)


mknod(&(0x7f0000000500)='./file0\x00', 0x1000, 0x0)
symlinkat(0x0, 0xffffffffffffff9c, &(0x7f0000000140)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/file0\x00')
r0 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$FIONREAD(r0, 0x8020699d, &(0x7f00000001c0))
r1 = open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0))
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x80206910, &(0x7f00000001c0))
r3 = dup2(r1, r1)
ioctl$FIONREAD(r3, 0x8020699d, &(0x7f00000001c0))


setrlimit(0x8, &(0x7f0000000400)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000880)={0x37c, 0x7f, 0x3ff, 0x1000009, "00df00003f00000000000000080000006d2b00"})
writev(r0, &(0x7f0000000100)=[{&(0x7f0000000800)="590e495b1ad2a14423c0fe6a9ba42f89606f8f5773e9ed4805627b1953e8526d359eb2d55c75c5eecce22f844fad5fcbda0e438594cd635b99159ba469291f4a807055e8cb61b875b2ff967153d9e416a79321aa4587cc1a8d8a520b57552c61a43a412d7a084aa4d72d74db60e90ff741c303bf276a00cb7754", 0x7a}, {&(0x7f00000009c0)="00681c735ebcdf1ddeb0dbde935a3cf2bafc27af3e17379e0c6f59175bbdf7db589843ec39f45c9e97fcc284b3e7f351b6095346d655708a92e51d9899c26bf2e2e9e2f53ed7c2110923ce8d6a14c8d7d3a5365a48a6d32aedba526af9decda1f4334ada2453510c65da4b3d74237650f09229a75edf77cc02b39529f32b0e968ed8c4bfc420bda1d74821ccaf18e9108568f3dbf6dd9b16cfa1828461d3d94b9d357cc6a2d548278c0ae8c2b3be444fca9e989e4ce02e161f43d4f87e09222ca614698db720e3b463d4de47f303d024413eb4b81b41036b2c596227426b434e9f31154e31b73317439b8d9240244835cc2721abe86ab0e0dd3d4c73d4c00cf68c9afc905765609fc35a380a6e9d8e4d10e4d12376994955304127d26ba79d36138474a1cc28e071c6735125c516d169017f5f3cee60f73c2d019a830b16260fcf8073dc905fcb352a92d336b71bf1a0c8d406b10a9f48ff7d061eb1ec56eb5344706936529522159916a6c934b263bccfa618797586b077bfe5e0154be5b0decca6053828b9d8c9aaece80cecd1a9693a05709047b1c547f01a5facd7ca9218b0a6f5d93b059642249ad1795e38413ac6bcf56d7596b59e61f2cb6268122b2fa16b5cd3aea17c3f511846bb9d64961224762f5d56dca3e3d78ec8810f756a809f9a4dfe133513a5b04f196192de1072d700a0a5a6a5a1205f48fe09ac940c9aa301c6d38145df76cea91f7bf7246d6bc167a93f15eb33c3fb5d6fd3afd8c6ae979055260c42fa01cae241be43be81814dba18954c12b0ac8c54fea3311d6bfecba5baa16a686842e1042e0f5e6c0035071043769cb7c9cc00a2e783fc1fb9f208e448656eeabc27af59e5b20b2948a5506b20a74e89342f85f32e01862b8ebb551293526ed2254773816a93fd3f3766e820ecdc8e98436baec88481cf58c48c521cfaaf6709c3cf6abfa7cac19fa165bee6013d800e3084fc7704ca582bd9356d11961ac1c6a31a79ac2f3f86df631bc1ca12bab2256d7ef3e64239e6acfb25ebe836f47e137d7a2bf85a7799f985f0e9937543dbaf4be34632d37b346b29ada854c6437aeecc2d2a480bb2c7f1e3d7393b9f12b4b05cfeb9a2a29e85195014802bf56160f89f9697d9a463d77ffc07ed4b4870670fad275b2c098329870d20b26209494d8029f34819e63ec879533726ed50a30b1a48457f2d7703cf6b628cd004a19adcfc578c2638ac55208a6cc9d6d908beffb83fec68d72b505aa85f5c2ac40decd02ffbfaa2d618f31758948f3bb44f81b2660e53480e0576a9234f06e65bfc7d3b5acd6efe81ff3c9dc1f88c6059ce054eb00940d689709420acf3e6d5271d53d3a223c99aa240387dbbe8a8dc868b0ca1713e620059c27b2536bd30c2c7023b738aef186bdbf32e0b9015352a5c797da6445b6e948aa531412b123596de6cb14971f2707d17ac32b376a5f06a9dc13cd92f8d2d1ff6aa74c4f3208442950e4eb330efad17ff5e40031c2c748ab0884b3d04dc7724605ab3d842009ca23a495ca67bb45d77748e9b623afae4205307afeeeea0893c462392d3d414f638ecc1d2e9eb9017ef9fa86f283dd724f47a44b6850fbf52e9960c5c2ee63804592b001500faba09cea9956f0fdb29ac17425a59ff80db874ea07a4a1183566034f656b9e91aa8f057771d64e2aa59561729d199340526ce11e505fb5b56b30071a8bf3cef0bd7b899bb3b7cbe69524452f5cf6bdc07d2a8bcc8a4c6630b773dbb70d8f9dec6b8b2e46becbfba5c9ca550afa391d3b7f69de0f05dc387cf1c6852250be0876913c52e3c5466d1e391d01c981cedbf79f5eee881e2045e8cac130101b782037c4a07da4e353153270fe24e5550c07321aee2945a3945", 0x53c}], 0x2)
writev(r1, &(0x7f00000012c0)=[{&(0x7f0000000140)="cfbb251e606bea41ad417032985e05b5725bb9a5a4201587136fda2dd727e5f62dde5a3a4482bc0b9d8726d0da46c1d908ab108ea9ec76e02493a12c1b64b1ae00f41186a7b024d2ddf2ae9d3a377c239387", 0x52}, {&(0x7f0000001700)="60bbad4238f79f3fab424ca4a0c38f34f352c7d5c7b6743ba59aca5b10b7f12be1cfa323ff58d0f57283e760788123b4a989048b3e3733dc8e3463a3713b8e03e9be10b3f7c76b830225cc80a4a30e8bf4756fae56321aa3894ab69fc4e85a1a97cbe34dd09282ac10309c3e29b703b897fcdd82d8fc7688ba2cd139ef3f333ac048fac12ed769c375952c24e6676579a90c4f13d6d4531fac3cc94239d932935ae6f55541b41f24406ca41656dd8e889a023526bff0265e626b535cb4123c4e2bd9e951b2b4d175be8134e3b76491bf204272a534386e4d2ec00bc5b7ecc8375079c2ea5526d6154677d5e2de08d01460cc71b57ac1ab20f6debbb381f3d5952ffa3c413b9c44011fe3eca5714c9e995577c26fa6f4be9cef41e86953f7a67ba4033192ec930ee4a875fd8a2d9e7945f75868255b00c1d5487217f32d2db516fd24a770974859d3e0af7c1368405afacce6876add8c4dda7d84bb1c19850919c6c474260ca663513190f2b732650031fe7abf0498f7fe749be7e9e6ac101382aa72a6a5d13564dcec299fabf7ff328c3d4d7d6bd36dc6249e363c908d6f9b04f61d174a046dd542d71c2ef30a39fbb19573b4f2e16c51520aa99f770b838d7cac545aceed9295c8cacc2be13c08f5ea75691d965e82a6a9cbe553e86d25489b4fc730f2a7712b64df3762913d0afb06179df17b755883b27600d2c8943dd88c3a7e2cdd9fbc6eec90287719b93766304ed49f5d57c3afb3dc4cba148b67797cf390bc442bb29245c2bf1b2f2a2dff528c32ad1e09cdb8a285d491613bdb9f6e567e00184a2ddeb383e6ac4f6f51c13de680b8551e67d41005c645180a9522bab67a29c0617dcbf91dca295be0a8b9fd6c8e9a3bdc81e109ecfbeb026e2391e101a29dbf5d69ec70f783476268cfc5bd0baefee4dc0512f3114fcd10e685021b4a4e0075323ff1c94a6bb7e0339bfa8f7a66cc6d7c1e115f8d8ebbf2db6553927d78c1848463196183a7e8c92e0e3c257889d633cb631b4ff59c051a216f43b532702b4b6ec7451b3ef70a3a50d29ff2a79fdb06c6fb91d8a0a8799b6b6f9d56ed0cf3322f957dc31e1a1729a622c6738e6fa4eccdc51ad158e4852c2bf585910a3726521128386e35103072791d279abe6535f07d9affc005cd85d21bf36450cc4e1d0245e0e2ff195ab6706a0cf0003ac8337adaf54ed5923f9a2e4245e6f03823c1f3f26269f3f3f26cb664a92e773178e9d0b51f1aba3a05337c5387245d009e2187cfeb658a7fe98619a1e769883a6ac7f9c01e3e35e20f7675901ee6c2e2b31f952d35d8f2a38d6236514080ce02d2b8de01801a6e4d0588d0663db5c154ee8cd913e07043ef8045ee57dc97520c3d7c597c82d7b4486c8d94d94191e7971e2ea868304007799447fd1953fb8103afdbffb934ece4527b8797a9ebd69510bee9df749c3e68f5ce9b84d5662032c9a1fed49f81e7886cbe9122ac339f72c7e93e927f628ee59d83c6c13420e0fbfb27ce84d4b8d2035488f99d97c1b87661ef58dd62a9fedef7685ec2dc16f97ceebeca935bc8925900ec234bad42982a7e67a5d33648e1defd0a585365a97535c5d78018b7a2164540ae07f81dde252208eebd15834764dc7a56345da952d9b090aebd2a54888deb5e104bc2f54155c0063a8211269ed2c21b8f5ee6c6515bcc429a093dfd0146deb9e8a56dcc73fb36492c92195ccd793738776168791f3a224fee2a695af5e95d3fdb82b312e9bd98f4aafdd9c268f3cf3790cff6649efe9d9595030aad7b24515746a52e821c6f45cf03240e3eaafd364f095bbb33a47b50fbdc2c66fe86fbcbf7b1c077e929f8e92951697de55ef19623d5ffcb9eab8b268338b8e26a2f5587c031e95917fc9e1c0af59ab18381a39ee73077d6126b26733c4b1ad311fb5ec3496f36b460153df51fd8f3829e877104ca327a6ce688e1f1f928d98bb1731715ca6d74b5279923547399511939c382368449eb3a806ceb299241f0104b56702080154578e3883edf3baf82076aaa002950500ea3a6ffadb1020b3787a7451580b5cee54190883ab55c0674746401b6bea12bad4293f0048efba066f539d1269e0a16fbeb2daf33fd47387688b43d6bf4b4f09d7c3bc07175f954c07f6946c5f4249b7b71f802bca3bdf8019dd6deae065f154a61e151b42b3040866dc7deba7df66f03ea721787e2268e58194b3cd8d9c1f9e965cf3e87b53f466fcaea4b3c9f1853807b05db27e4a206106c2bd7bde96102c3d0f0362b46853a36a12b18c9a0b83b2bf8dac247252c7138fe258c82f66d3446cbc41fff1d6abb165c776d23f6d93053ad368787b6907b1061f86f053ac2fe0ce77d10d8b5d3d52736b6bd89446aa529e636a83b70fe4a13f364d44f0db842cebbdad2e01b41e4ae61ffd309c30666498b9164c9410dca9d90879369602ef8670fc0f82e0deba5e753726e5909234aa1e2086b711d459db6ab35e7d81ebce83c1df31b6c48808f9d52020a72c99e07ca4e0de97e9bca82e2abde799287e966f03b783285cdca5ccac3b9653d94ccb17017a37b5af22832876427b0842849696a39349faaa03ef3078f51c39e4153e1330bb5be69f1103530cc09c5cef0b201111970b0d901a70af9dfa4bca6b34dff016066863936f3005f87f971bdf723d4aa71c8dee65564d66f6e4e2fe83e2a11b097c6a14b651bf1b7e253282e9adf0229f158c1ad0bef485e7a904df7c56cab5724e31b2de2ab6d87abb85a5b7174e27c3c515c1b77bc181d25eec397987deef62ed117c800f434664ce870d7d3f580d330147355c369e6564f049ea833cda2ae8fa9e34ca1a63dbf2117f5a5dd530e85224ff495035e35ae0201a608593401611fa631faa7f8029707fc0333c219acab704dbb9b80a7010989f1f3fa4856cea880c4b3e8e2d43fd12fc46f23dfc079f30407a80956938e27c0354d4f8e3e455497e9679cf2d8b57bbccdbdb75331f15e6fcc26346346d0b59913cfbaf38b2d73091b2c5497f9a8a8d0be52c205c89860e2b11bb16976796d2766b3efb36626bf1d894fc00ce4bcefbbab2608aa37137680d64e568bab8abba22d8fc846ed607e2fcd80a64f11ffb589514e3758c72f7c485a0e62b21de20fb2c481fa14aca0db56fe998247e9f41643b171b904cdc4babb4dd03533bc0b90deba0b66b103492d0ab79b2ae63e79484ebf0ad96b32da892ba082991f77ce7475dea0390f837df5bbca8a64934d722912d651b3c09b02bd3cf2874d3c8ca66496db05c6392963383cd417fca84a4492901d5a532941bede6878f2c0d387bc93439e1e79472a625bfc6f78c54ef44a395da80e6c0b777a6348b356af1c8176087ec63f87555afb3f6b594ac2fee5287b9313a556a3597c69ec3ba1fa1ef3c46c6135fbe78fb739af045d0c0ed99cfede95d7eadb381cd160f3bc34efff00ec4c417e49675c8b6b1f2c3e3f3f66c0db57c468fc7f7a48ff7aeedfa6814e5a0bdf5946f7018558c990e3ce934456b27c6a082481791de85712a334e5efe61e5863647299afe3157d5b815c9935512473ede307e8a546b32c3a85cc65a71a2f9cf4d89cb6d0451789ff6d47cd64448dff7a2cd03a11adf2ffb94618e50221ab6a9718d56dea31af92318f53bb874171f3f34c07b2d9bcbafd944cb02ada658ea094972fc68e21cbef4d884cc594671146ddaa3843fccd56af84aaf0047b2484a24c3b04b067a00dd89a097aaefea71f187e0581fa01a102056b8d26f4cb6900eeb26c860eeead7201fd2d9f2383ce5ec4f330d059dba708ab3eb6ad6662a168c3be14e226791a7d7168495b5826c8b57ba819ff359c984de9daec5273a2853675756a9422ef0ba8bc08961b333d7bf702db9dab08fdca1db9ab42fe80fdbbd020a4d0bb1335df43a8749bf3f5f1d3a30e130e8b7b43e7f78cfe32d0b324e1dbdf151b73cf2f93a7315b080573b4b819e4264526d30f987493d1597ca97f82279cb23eaeca4ebe4ece55b8e09a2deb15c2ae49898f71b7f5694e7e6089ee434c01d1ad586e63dc05e7074be8db1019dfd6ef54a10831c0fc551bed0ae5e40b3585bcbc4b71537f4a4b6b4f355598c897adb5228db77002a2cb148d90c7ea8a4e83af590b48342a053a4240a4239c16ae937fcfc7da372f6b506a761f60f70a8af108914e4aa0050a64a7ae2f73b557eba12166224f32f095e0b91b9f0a75a83ebdf96e59878af7948c553437147187aeb2088910ebc5498711a9443715523140636311999297b504cdbe084e0c5a99b9aeb57bbb974c51b0a49c30cfe2f5f2bfef509258f2d7cf5217b83c710f1ae4bd33a47d17f349779221203baf87c10fc3f93e6c3d2859676104769fedc10032fe91a5d6c027e7371560728a9dcf814b44792721e23973873550ebab1795da12b73ae5d895feb51709406dd3b18ff53fb5d3af8b0b714e484afbc262ba6f2a720ab0b18cf75d1f457e04928334377644332fc58a8f77e91f95d45b684818095b7e41cfb60be405ee289986f36b7e892bb7422aae9656fb031eb9d9b63bb4c70851689c40d54a17f7b48f0f97b3ab9739f937dd251689ef40c92fea33c99db294c1bcc27b695a288cfdff197c28027e7276611f8f97fe98384a843e4968bae4b1f63393346a753aa06042836b6eb1adc25d78c298a234b1cac319edf789f6abaa6d67094fc7f48b24b92d030baf14955159339d38a006fef1349bb73b6fec03b9119f97ea753bf376210c467520eb7cd052a36161eaf5062be089fc657f8fa2245a5887b29c26216a143382bb5e3b77b6f2cc5559a8c4915c496548734666470f24dc19d65f1a0ac2dc1b553f0c3af1510fbcee5f57461b6d14d3bd721e62238c06e2784f1a012fde89e352bbf2365b565d50ee27246fc00bd62fe46ece7b976802a697ccb7c717f85839a6e39b20bffd8e0e25e7b128c962421fde44ed4b742fe7af596add878c920cdebc7afbb42800177016cdc39d852dc64040be9fc5182c05f530e669ce2d0489b5fb5ea95fc56fa3fec5e27e0b7a450507f0b3de240899647fdfe5e7d52546aa7c358d02fe9fea6767d662d651ec1fb10e613b1f219c440362bcad23654f8602dddfef51c21e431c75b0317d0df0f843df1495817a85367e081e1df83647b7d07dbacc4874816214aaeae0a574f57381cc70f4cb782034e9974a6c4cf23c247e69a0f7fa08750b08634957ffb8826bc753bb42000c6df0e2b493ae873f7d30ce865d5a419fae68052d035a898d89642f748e6a50cc49129042298325da86c94b430396fec4bb4d3cb232a23e051061f31b9c6152c692caad3f9a1c44d06e4766d4a3137c638fa75eac3ae9e1c6a6226667470592040fa642e72722b1c98badc64d33ab3d28f1cf6f30a4c63d65d14bbd626c3612716817d83f3f9a2d96022fd5159fa45e765d02d141a4f66ed715ef7695b0ff2bb59360a729e23fbdffdee91fcb8b8a3d9e9312a522f153acbc9e9a0b412747a936731577b0a91aa6b8ae503bc74a83462f3ce2ae41a1c152a9000ad0bd7443c2f41fefc91efab2d43099aea185d7200861c97a6787cfea734be370bf36a510e4fdc186aa9f4dbe92f32fa3770dc8db2d7cdcbf9344157da48d6a5ebacbebddeae4c408c08de0a081aaf79d98b230eda6c8823cdfe59bd148b736d02f94b64afc46d3df29558891bc48c8ec7d485aa99c4417a1879c9ff1625f3e821b2347c176a0ef958ad7fc54eb10a53005b922393cee5a6cf7300f4c9171d462ddabbc0227d491f37606fc5c8e545d2a85634608", 0x100c}, {&(0x7f00000001c0)="25fd26f0c2f6f8454eb4598cefd3a544b22bac827dfb6921cd320fabb353b6abd1bdf7a6dd432ca5295f892a5056cb9908d6095b22d9c02cf7a1653f1749274f069fd0a76fa516008092282620fdb3582c7b29a74fc9a0628e26889677f0ab87054b774261de8656a080d103c0504abd02c0f742a4a5cddc2434f350c2d1e641ddfb5bd0cacc83eb73828ca34a56b3b35bc8b2610eb4eb453adb749734526c46d9b2ab6d8614761d796909a6fc66c7d08cb1527152db4272ad88493fb38f40398b5ab50934fa551a4b2630e0900d08787e89612408f5c38d3185e17475d4a49400"/240, 0xf0}, {&(0x7f00000002c0)="e041bac6e222cda5a8a83a629eb6514522c599cee99c1c36bf1a6bc1303e5e1af2c7d6ef7e7a04f1ec148d49241dd0881538a2afc2faf893f9dfa86f68f0f3f25c0bc65341263ac9ac9d46c0f4257d89bc3db24110867d5653d7bfbe294fd3c8f7d004762cd5c286b039df3ed0e2aa6f15488dfe95d5b74aefce77e0afee5ddd2876e6cf2d05000000000000007ad4273acd0f", 0x93}, {&(0x7f0000000600)="6973b3b7b5f516f850b75a28715b10f7ad5d42b6ad24befe41ebdfe071af14f8fc7b9031407b78e22b9d0814b9d792c9c83e5098efb4993f4ad8f4562dc983a42eb32fd9120e86d581ca3b88d1e1d14bf2fced5de86ab55c2a3e0199c24c232e3965832a8b339aa00261dde68a23b8d6b17ccb20b3598262b33d77dfb2f699e8003ba5e6852657ebe417b248026d5e296738d18e4508f37274f008a4fdfa9b8c2a1838de9e17b63c47d9fa63336e630736d37c3d7c65312e131b82ef9cc1b0bced06209a65ff61b2a8b14004fe487ef66b23acee047b049423f836ab87a7345585cbf92f2a4ac7e1cfe61fc4349db1e33c2da8f35920c7c73d54042f6daeca3eaf67967c50e6da9709ba6f60f11ba40091ddf33ab51f0af7d079126cc2a31c2ed60bd75314d3d4b3fb68441788ef99c0c89a954a03a54780d6b185ede26f65208dcce5c269e7cd1e035d18d1a6ab12971530f9560be23b0f79e88eaa7e2000792a8097b4ddd49daab1ef9fc945a49add61f933b61998cf8127db66386e739bf2b1f12674a63fd4c33bd7160fd5b2776725e2553e40f4d7f8bd00b660a77af3d19d56b494232e2d8003139151a8bffb808519313f751d17b8dddb913a8ff30fa7f017d701ed9dd8", 0x1c7}], 0x5)
writev(r0, &(0x7f0000000380)=[{&(0x7f0000001200)="ec6e6688290eef4d1e3caf403d1c8ec765728f141ab9100008000000000000e9ca199903fdc9ca6118d232a369ababce52c001fe64edfe80fc7c67b715015e97d64167b4cc024469e8ccacfe668e499fbe1a61794fdd72d4b72f2d2dbe26f7bab1158d052a9d215a57d3f2ba438cfaf0b979ffffff7f97a05b0000000000a41dea0dac1cfc8351b5fc", 0x89}, {&(0x7f0000000580)="6e0e59233e96f72fbe9d7537c357c1e762ffdd2941d1480727fd7e2179ded76e26da7e0a87570dceb33df4e272cf9d641dc9cacb280d539069084c386a14de14b8d6ed2b78bbb26aba3379894e573bfe95dbf8df93438d0c534134a7898dc14ca5cca20aaf4bb1443b740645be2adaf635694e4e6ad1120301", 0x79}, {&(0x7f0000000440)="06f2d803612e7c3baa2d418f22715baaa6d45f8a50f1cffc08bc399d774601dfc4f36e37320c27dd6c0f91d2a7ba63361022803132f486a8e3d4a6448eab74f80505e0f87950b4c9fa81dc2544e390117246d5a994c5781aa279fe298273fea66e7ce2b926f5acd0d1dd0b375905f26a8935eda41833b3891f1f56c1e95bed206462a8c1248fff9f06d41336ef4a", 0x8e}, {&(0x7f00000008c0)="12b1c68e4e76099b4c66a551dc6f52feeb34be35ff519fdffcc2381874f4e22146234bd7fdd653264ede74f85478f382a524978e17e1668fc8c3c27e57219888594710cb91a83fe52cb4b0a622e2c27fda34f75bc07eb331bf06e05a60b012427f8766f9a8d41134b1e4fb77f608bb25b5cf2b44ede1681033c314a01ea45a28bcd2512788ad3e876415d6b570827847e07bd29a49742f68e434af36448131c789d3e209a0a4fa3d3082d27dac39999e72a0603dc4e2dae3768ac549136b868fb642d55f", 0xc4}, {&(0x7f0000000500)="ffffdf57000000000080602c6a9b9722af847f", 0x13}, {&(0x7f0000001040)="be5f9af4744d7a7f3899a46aa1321d50719f12a311557cfa9b7d48a9359787d62f40a1c43a2e6ed68c0da7e54f0365b0054449b78550a77c6f26411f5d73f1280667f6959e0c1d3dc6187bb36431a3e2ce66eb78cff2e41cded868fe25e92711df1c4289759dc4b49d573a32da0ed8ab79c5976cc7a57d4c6db9780d5e84e90a24bdc5a0145c0f03f1800746a476ab5c153ee93eb47b12b71e22dd4890d3d330614fd54ea776df09008df6bc0ccc4fcb4a", 0xb1}, {&(0x7f0000000000)="2b51e739b678b42b3b1771e9ae7b2232322d9834436df3f53af32934cf48ad02e3190a08bcf0ceb143816231614641e031ec9dc8361149436c3a15b7173ab6748b43f9b04a86f294bfdee56e586ec21b38935380dea4f6b7fa47f58e53607b0871a0d38fce8c99dafccca523913707069ac4100987747932dd91c8ab7de1e75191b5afb60788aa28a0d25dd611c30b568304de043bc0567c735d43fc", 0x9c}], 0x7)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
openat$wsdisplay(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000400)=[{0x4d}, {0xc}, {0x812e}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000280)=[{0x1d}, {0x4}, {0x406}]})
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)


r0 = socket(0x18, 0x1, 0x0)
r1 = dup2(r0, r0)
setsockopt(r1, 0x6, 0x2, &(0x7f0000000380)="717a9e10", 0x4)


r0 = semget(0x1, 0x0, 0x0)
r1 = socket$inet(0x2, 0x2, 0x0)
socket$inet(0x2, 0x2, 0x0)
r2 = syz_open_pts()
readv(0xffffffffffffffff, &(0x7f00000012c0)=[{0x0}], 0x1)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
syz_open_pts()
ioctl$TIOCSETAF(r2, 0x802c7416, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "0fdb00000000000000060004000000000800"})
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r3 = syz_open_pts()
setrlimit(0x8, &(0x7f0000000980)={0x7, 0x51})
syz_open_pts()
syz_open_pts()
setitimer(0x2, 0x0, &(0x7f00000001c0))
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x3e, &(0x7f0000000000)=ANY=[@ANYRES16=r1])
kevent(0xffffffffffffffff, &(0x7f0000000080), 0x0, 0x0, 0x0, 0x0)
ioctl$TIOCSTAT(r3, 0x20007465, 0x0)
ioctl$TIOCSETD(r3, 0x8004741b, &(0x7f0000000040))
execve(0x0, 0x0, 0x0)
semctl$GETALL(r0, 0x0, 0x6, 0x0)
mmap(&(0x7f0000ffc000/0x1000)=nil, 0x7ffffffffff, 0x0, 0x1011, 0xffffffffffffffff, 0x0)


sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x19}, 0x4, 0x0, 0x0, &(0x7f00000000c0), 0x0)
pipe(&(0x7f0000000040)={<r0=>0xffffffffffffffff})
ioctl$FIOSETOWN(r0, 0x80047308, &(0x7f0000000000))
pipe(&(0x7f0000000040)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000900)={0x4, 0x2, 0x6, 0xd}, 0x4, &(0x7f0000000940)="0f060a80ccd2e3fb375fbd4f2268f214b8fd56dad3439465280c9c83e134564ceee58871c119da3ca711b5c3389b26311fc2a41894e02ce1a5b44777c0426a58aaa8ff3d6711645ecdfe6121a91cd880d07f05d0a7b72b73c89f000c3b5012a942b3f1f578cbcc4501cfc957658d40836e0898632b1d9ece9347fffbcfb6cdab1a0749ea3acafdaded32e732b5effadd07f604caa9893a3c924f1b19fa653b379624d018ebd45893944d34a305334e1b2a5e27dc534f64d0087efd27feb7d257572478912eac929eddcd21e7", &(0x7f0000000a40)=0xcc, &(0x7f0000000a80)="0fccee7366430ce8192228c77a771c9f4c183450a3328360f0db645d9ec98c7286bf7c994eafa0c7e55dd462e5d754c52c61d48e976b4feb3f02eb38b09a244316340a31150073f2ea03b3d5e1e240544fd290083c6de69e6d08b6d00cd6fa96ccb9f217cc9568d77cce5dcfd79b35bc197105bd3ae182cabec253f95ba981598e59382877905bb208b52fda1111197c4a1331f2d3bdb9b1cbaad69f85af2578961239fa8418225d3fab9938286954dc1de9a278d41e3a26e6e3d7282d20395f6cf19d15f7c242aa603629fb7b433c54eb8fd5cd90e1fc6cd6977c94f15d4cb35378a1e097432861d50999bbb769dee7", 0xf0)
fcntl$dupfd(r2, 0x0, r1)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETWF(r3, 0x80104277, &(0x7f0000000280)={0x3, &(0x7f00000000c0)=[{0xc}, {0x5}, {0x6, 0x0, 0x0, 0xffffffff}]})
mmap(&(0x7f0000fff000/0x1000)=nil, 0x1000, 0x2, 0x13, r3, 0x0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r4, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000000)=[{0x7c}, {0x28}, {0x6, 0x0, 0x0, 0xfffffffd}]})
writev(r4, &(0x7f0000000140)=[{&(0x7f0000000080)="35b5c242413c1026089a59583cc3", 0xe}], 0x1)
ioctl$BIOCSETWF(r4, 0x80104277, &(0x7f0000000c00)={0x4, &(0x7f0000000880)=[{0x4, 0x98, 0x1, 0x5}, {0x3, 0x6, 0x81, 0x2}, {0x0, 0x6, 0x5, 0x2}, {0x1, 0x3, 0x27, 0x4}]})
ioctl$BIOCSETWF(r3, 0x80104277, &(0x7f00000008c0)={0x9, &(0x7f0000000b80)=[{0x5, 0x3f, 0x40, 0x5}, {0x9, 0xfe, 0xff, 0x1}, {0x2, 0xf5, 0x1f, 0x5}, {0x0, 0x1, 0x2, 0x3}, {0x6, 0x1f, 0x8, 0x8000}, {0x3, 0x7, 0x1, 0x2}, {0x1, 0x5, 0x4, 0x5a}, {0xfff9, 0x9, 0x20, 0xffffffff}, {0xe6, 0x0, 0xca, 0x7ff}]})
write(r3, &(0x7f0000000140)="0000000000009cb8e7b6242a091f", 0xe)
ioctl$FIOSETOWN(r3, 0x80047308, &(0x7f0000000000))
sendto$inet(r1, &(0x7f0000000140)="4ba9da03585944a7fd4b754b0562835710ac877a3ce4792cd6b07b192cb7840c5b8ef9d1e9d128658066ad9e5b1214fc8ef9f770f8c10ab9bae312d9b6be7c98f7266919142bf4a3836ee42b8b22a5f360f31fa425651a0cec7cfb482a56a8ba93c045", 0x63, 0xb, &(0x7f0000000100)={0x2, 0x3}, 0xc)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x15}, 0x4, &(0x7f0000000080)="ea71402edf7f5db2c9063e23090000b6f2", &(0x7f00000000c0)=0x11, &(0x7f0000000200)="117c87ecb595ad6cdb31f46daaf5e7bd53b79ec395b4b1fec4e6c9389282fd41142aa2b1b16e282db268e911c8f77f25", 0x30)
recvmmsg(r1, &(0x7f0000000800)={&(0x7f0000000240)={&(0x7f00000001c0)=@in, 0xc, &(0x7f0000000680)=[{&(0x7f00000002c0)=""/212, 0xd4}, {&(0x7f00000003c0)=""/165, 0xa5}, {&(0x7f0000000480)=""/104, 0x68}, {&(0x7f0000000500)=""/219, 0xdb}, {&(0x7f0000000600)=""/89, 0x59}], 0x5, &(0x7f0000000700)=""/223, 0xdf}, 0xffffffff}, 0x10, 0x40, &(0x7f0000000840)={0x7fff, 0xfffffffffffffeff})


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x2, 0x0, 0x40}, {0x6, 0x0, 0x0, 0x85}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0x37)


r0 = open(&(0x7f0000000300)='.\x00', 0x0, 0x0)
mkdirat(r0, &(0x7f0000000340)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38/\x00', 0x0)
mkdirat(r0, &(0x7f0000000000)='./file0\x00', 0x0)
rename(&(0x7f0000000a40)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//../file0\x00', &(0x7f0000000540)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`)Y\x81F\xe6\xbe\x16nA\xad\r\xbd@T\x03<\x9f3\xbb\xda\x82$\xa2\xf3\xd7r\xe7cnH\xb3<\xbfp\x83r\xe8\xf1\xb9\x93>\xc5\x12wC\xbe\"\x06 \x9e\xf0-\xf9\xcb\xf2\xf6\xe8\x80\xd38//../file0\x00')


r0 = socket(0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
sendmsg(0xffffffffffffffff, 0x0, 0x0)
select(0x0, 0x0, 0x0, 0x0, 0x0)
connect$unix(r0, &(0x7f0000000340)=@abs={0x0, 0x0, 0x1}, 0x8)
r1 = socket(0x11, 0x3, 0x0)
sendto$unix(r1, &(0x7f00000002c0)="b10005010000009f0500070107000000331c13fecea70500fef96ecfc72fd3357ae30200004e30ffd2d236acf20bf404be01000000f7c8cf5f882b297be1aa050400ce94e2f0ad3ebbc257699a1f139b672f335c22db830c032bfa896443c32118210000720fd38bfb0000fd54c125191b1257aea8c500001602fbfe0c2300008abfba0900000808f37193f8343712cc1100b71dc000090105000000000000001300"/177, 0xb1, 0x0, 0x0, 0x18)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x8000000000000001})
semctl$SETALL(0x0, 0x0, 0x9, &(0x7f0000000040)=[0x7ff])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xd, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


mknodat(0xffffffffffffff9c, &(0x7f0000000280)='./file0\x00', 0x1000, 0x0)
r0 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r1 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
ioctl$DIOCMAP(r1, 0xc0106477, &(0x7f0000000080)={&(0x7f00000002c0)='./file0\x00', r0})
close(r1)
execve(0x0, 0x0, 0x0)


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000400), 0x889, 0x0)
pipe(&(0x7f0000000000)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
rename(0x0, &(0x7f00000000c0)='./file0\x00')
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
select(0x40, &(0x7f00000000c0), 0x0, 0x0, 0x0)
dup2(r1, r0)


writev(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe2c63a56077123a276d3ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')
mkdir(&(0x7f0000000100)='./file0\x00', 0x0)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
r2 = socket(0x2, 0x3, 0x0)
ioctl$FIONREAD(r2, 0x8020697f, &(0x7f00000001c0))


socket(0x11, 0x3, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xffffffffffffffff})
r0 = socket$inet6(0x1e, 0x3, 0x0)
writev(r0, &(0x7f0000001340)=[{&(0x7f0000000000)="08a6800310605f654af53705e3bc87172b6e29f7f989ae6d90aa992415374555e4aff9641f725b79a8474b9817f4d6bffeadff803025b3964be1d653f98834a357554dee860691bae9e40b11e1cc600d009a508b74058c840cfc6b2e205f97359c9293ec68f7e9d58ae5e631b62358edf239fb1014232a0a7b64632d755fa3250fe9144ffe8b4f45", 0x88}, {&(0x7f0000001140)="4dddfb7b05773bba5cbd3b35cd94e74546bbe514f77896e3dcea7273b729b24e7ccc831cb898b6999fd9c8ade0aba9944afe1be6c81f4d66f819b1628afea4d9e47017e12d31aae51b06de5358629db324611eef38799d8d96462e30fac4ca191aae29867b9c007291085fdb7a56f86c2f940c1197a282a52fc94d7b78dbc0499da473e0b1a58cc59de759ae44495342df95a235ac7c6d871009abff95b1693cea6b1c12e53b6d70e95914b2c2ad6c16150f1896d2c02cdce9595ac4b0a24aa066fff95682363bedd39dadcc586dddd0039b1d29c244ad2b8416305075d18542c059d99908d03fd46acaaeedc5f1ffc35b02c06063f4411e924d59a9e0a66a7b0008cc2aacfb2b5ed1649a59b9d4a88f817029e17011cf51373f7f25fbb2ad4852c6a0ad80f19adf7f6537b32b8510eb048ad0f90f529e246179aadb3c7dd54bc070f8d15edd23e145a3058468ab599b19362feb4ed76527daa710e43f1f00"/360, 0x168}, {&(0x7f0000000140)="01530959491d0791301208c3e001483cb558965c793aa5073f4a9fa10928b2c8e87f0fe505f6dbbacdeaf569dd1712113872ecc6898393f2eb40445fcab069762a2499df1cbb9cabff11465c1b6d0fc700180987", 0x12}, {&(0x7f00000001c0)="b79c8e79b21ab8421b7ead548ae1f0a248f694f8c771a593c54d094c5ac66693dab541aa6a87d0a455e74c4ad2c9df0b6d9832e66bcc20188f15013c2aee4ccce9c7c237cc5e96ab9f096d00930556eacea3e4d345a8a6e15e19ad948de7c91263ca7f8fb84c59d07190fc533a0afa274c42dccf8c9ba3e87a48d632a8fa858d6c5044ae2f7177cddec826f0035230d61ee2d7556899968b90e9b7efb8f753b312544d9d76def5c036551afddafe62785b1e0ad29979694ac44cc524cb093455fb69f94e55621f8ed6e70cb0", 0xcc}, {&(0x7f00000002c0)="dc32580ebf881bf637593697c6a13050ac35823d047454d211bb68d47b92468c93f351508a3a96d09325fd424f080914b5255a6ca2f0f54082470c56fcb881d1f13f121536c0feb3cf7b1c3dab02896221c8fb8de0da9ec49f1cf9f061a2a7b5ed9a6b6f", 0x64}, {&(0x7f00000013c0)="99b170b5f44ce422545311fa1c2e5299ec80b0c5b194cf175644b6bf52a71dfd14b9048dfba7fba31a7a15d81f4836731d0685832997a9dde55562a9a5197e7f9012c1330b5771017f5ead16652948ec48a764c825d2aead72c148c80d7fe4fc065f1225840b05fbcbc6b9fbcc49c920c348da0cb63a0b718f0a4db12d164b568a9f54805336e4a21db0df5438bb3423780d23a9bcdc05f83ade3b1770d7a1aec4bd41fb492a9f8979016ac99e3def82e0c05173e4c04d1cccef1fc78b9cdfeeaacb7eebfce00092ff183949f7d205361a249578069c992511a5e638623082f13e7d389fa3b275f227d8308ab1b640e9b07bb7b60123b0f8651ceeb2f1f6bef1b0d5d88fe6b7eb253ba7d8daafcef63edf0fdc944fd469a0be00522340784abfa9b381c9ce3901a0e30de0443805c2d53f3038b1e28689ec466370aad1e6badb07e3538fd0835e0f70c00aa45410a04f23e5fa0d7ddd20500decf6dffdd1f66805d8bd660450c0fb7a5c890bffd9dd7aa8a668802517115ce6996a9dce12f17002216187a14321d584f3d4cc41e663a426fc2f51d48e40deca69f3bc23c556d80cf355fadb65d78b86a62f7fc69f49187ba38667ec4d7dcf5f98e4411f07d6850e70aa08639db7a1d0de436d64017ad5aee02099e8d7de630b5a37431b904b6e81df715b9cd2a5cd7a0c0fdf87b892a27f14654550f3b3dacf5a303f493ad237210ab14f7da25301a59b9f2bb7654b90036c3dac0a79fd77b92ff92864e965c6d2050c1ee458dd7d56e45abec5316e8a42f0c0d7c586bad2912320f67bf90375a47621755ce410eb0d0e5efd8aab847e7b23dd44f0722b13fc0b2b79d0e2863a01939bee5a62ff75a41ee6130e4f6ae2e9b59d6efbd468173f311bdbb31dd7f234ac34642721ba2cd6fc7289e604850f7688a58a1e4a21072be79d79e5bf65f3b7e8303ba84590c03d778059e66bb19f7f71bb7bcc8a134a4dcf6e3cfeaa9b50788ec80a73f14848961893b18ae82899cee87d60436f0f47ab1d907183af580474036174cfcc7afb14ebaf70ff4fb3c37ca4882e37a2cbdfacb6247fb72866575fc10fae6ff07c2cdb3a23cf7c38bcb3f7727e960fcabe20f0c5622bc89754f55c81573a8c0b0cfd90f278f0fb6a207feb687e13bb7d7def233c1cbdee4722ac077a90648a3b79e1abc1add2adbbe3b4f15c2c23990ddd7608fcc14ff4489c355453b2c3fbdb9866bad4e5db47c621664add27ebc3c403be75f641278c590e13966a7e6ba7fc744b25207554e075f216226c5d17eab00d018f47a64370a0e08cf2ca17750e7d5a91c7358cf18a860f88d8b2f5ae18c9969dad34577e2adcd4b6773dd7c0cc8c858da6d6da6e16dc2544f6e00eee21844e2fe200b661c37c592bba2f701ea46545943b7faad257e7547f01a455360210ab446507a7d2355627c0b6d19f64930f2e5185db35ea1f0041e2fae529fcfcedc0dcc4c07b42d752beca24a27be133c76b8fff3432c72c436c03d67c1a3f116a6f1757c736938047d9a15e5cc31ae5604bf8fc331ca37581e9a2c16dbfe0573d15483bdc00f70c80f304bea3aba9c5ec0f8311a82778b53fd99fa192ffbd3df9535195b3fd49c5ad8df46b56fc0b43a14159a2cfb50658fae45004574144f161cf056f4516f04de3eb978d44e2bafcfb9c1a0fed4530eef41f5bb0cf0e08e83990569df3ae5cd410c0101c74a15010183e3abc934766cd95bfbe6c14abd39534a3c5bfc1b18d8bedce59f02b443610dcb0252b558a9c65498bcfb360ba8f69c56d707bd8f9cf92bdda0c6731dffd7b92d0e8bce6618d3ee6f5a731724d6beea6597b21f4183395bb50b970c3ef9cee453657f45871062b00eb8cb3a103be50430f16ac90a5b5778447e10738f1e90c8b668402073836e2340a5546e78bfbbdb03ff7ae20b3d3ccdbd84963d01b2fd0d46af1825eac7c2fc933eb773c39bb74840dff4874d3f00f0a353521f9cd8cc949f6e4440da4f8b4e52d785ce96ab789c0906596bf8ca44e7aa7eccb94bbcb7f6a437bc71d17c3ac3097ddf4ba677bc8da71a516d03d39788b2a73af62930ae4809f4a2b82cef623f5760aee445f641414d6b431febbd3c0dca95628eb7f53cf0980c8e5341592037e04f0c64e422fe61ddd3f6cd198fa3d46d67d9acbd5c90cc35735a508ca8356a146b3be5ddff7c712307d1d14648b69139d6ce4093319f774340052fb632e10baff479a7eb211213c741857abb93482842ba6bc24c0a82496d74a969662fd9ccb0349855c6ef4f9b7d0cc8ba9da6d8c0af4c127e54b1e0aec02c5d3e30bd2d40ebed32e8ccd181d91b02fb1fea184cfee93588df21e6d82e0130d347a3bff337c0d0cb23b38def738604eac7ba0253f8d878cd520044f18d4b98c99b2630225381d68598b74130994b37e57c71424449f355680a0632c68d75d834d3e49f379512bcc06ae1fd00437d234fe29cc93a4b0eae261ea50a205566d7983e60513cea42dadad6a3071b59f0fef0efc256375ef169134a9083e2a8338ed2db20187ef5ca2864da9d3bd029c1af42854649e9417b162275fadf00f064cec11647a322028d10a8190dcc84d9b39f3c10489ef1bde13ef72deb4c2edd1619f6de2481f7e0d54df0677b3296d910653238f66f4ba77d86b7a655aea87caa08db3ec36185381b12534745039c5646823baeb17a08d25c82e961e29bb5d53e8a5872204cc84ba7a47f991b16fb091f7bf9dd930b2847b5e1544a325456a5ebc6355e4b183594ae3cd73601bc20058cc68ad4c8630defd81813975ba45e8738536dd034444ed778bac92ba5bd8b076d6a6f8202f58fdae874cc5d33be919fa1b1642a3218079d12947cccca2d96395bc0339108a538e7590f8416935afdbf81ad60d26c0d2940dcc0a4b9c25d1189b284fbd6bec7a1319d051e9e0b3b73ea1e74677f64b88940b22a0a687c4c204e6ba7eeacc383a0fc97ef9f501e4acd2ce641e28d7968d6e1fcfda3db50d9be0cb11ce7106dc8565548beeaadc40bfecc5c6ac5bed13bc95012a97c8595c21fcb747bda11878a02cf1ee962e688e48adf964ba1f1e1a275b8d6d62ad482f4af7d26b3f5140578751b061366bb939d50588dc8d56ffd7cd7e88c4e371b3971efd3b2a480d30513d8e4e0c0ab3be7f26ae031d9f4cb81f5a3e9cd1b00d068dd7d699a237347e88133281cf189fb128deb8c4830b21332062d50bba3988feb132217a49c791e3c8610e005dff67d01cbaae1d2255b69d12b08cabdeea83b67c3f448f77729d214a0471c9634daaafc98da8761f758e065e65cc3fe6d60008b0b8ef10d6e66f438aef387eed838bf629c91872603d64efdf06df3c772c642572994be1be721a4d3b0c7c84b1048346f3371e19b83f81738ecbe108dad8987e99425c07baee00c08ba7d4476352f676496c2749a459221c4b99c9fdfb6f260b31dce4e7ed26bea90d36066e7cdf40620b1d1b5971d9229960d595a59068ad1fe3a7660bdbff1dbcf4924457f33e48cb9d1ee99dc8de354449a5be3f74417f04f8458a1727d88b6358ad8007ca67ce36c1eb2bbe3f2959394b0cceacc8c9a95020d970af8321e451e6a5dd3320ffddad431c90dedd9fab426722acf2ced06082931c127a85cfa13ccdf0ae0e2c175f3efc65b2cac55476e265377cfc75f607068779047f1d1796bd5f5b14538caca93bf2cab30b27188991c404c062c5ba502dd08d5fd575994eef436e7c7035b8959ad54e9266b7cb99db1fcf19498efda0a8170cd3476976aa6deda1e5b159c3b94b36d7e4434d31e54c481fb2f6e70ad9ba384e52e1c78f265a575a6248f7f1700bb704aa480515fe55367b56d549ba944efdebe82d28e2dffe1ec62920943b44eedfd06c2db736ec317989936feebb98a5ed9ad6305b6af6aee47596add6a3aa0d4ca63fefd147f6a68bb33aed6977b0fe81b9bd96fe906ab0c09cbd2fe33483e22526614d3dd921bb1e652da11791b275cc4157bb27ebcffc80f571b9fd818fe0a84220301ad187c1970c8c7fbe3a1eed16d2fe5501fad2fef597b84b1514a830e53f3d888a3e4bb7203567cf8d14ab5b6e1444fcd2b9fc52f2d3041d612c8b6ce87eaa822a2c3660a0d0195a5ab96f12d91add09d855ece3df91987d9639ac6936c083f2bcf77d09d3bae0cb885acc690425e8ba2abc75703b819ea07a7200038451c0b31f2c7f05613696da745b16e3a403e568bb20633a61b30007d9cc0188861c05a16ca9556dc900ce03f92cb9dd303bd7271bb8f778d84dd1f6c1e431e21214e37a8a7d864147ae73911cfdaedce9308d2c1690f004dc9122b7cdaad9bb1b9c122f702029ca8556424d979154668a8c323c4c5b96154e62bc21e0605d4f93b5de1f995d2f18a23f35e5fb7c85872533594709a6350af8aa949ace387fdfd941913d7f5b331e0bc3448115bf65c90955efc1a96f8f315cfd6887ce6ac2ee77fef2229c7efc63759fc5d3eec2af1e88fbf93051cc6804504ede4672baf86b778be4a35d4f37511a5b8e0e749e4034e33b3fa00953b5dc65e70e6c783195be34b7300fd3b44d3974fce3645acaa0d191e426364c6d1cc374dda6cb930af5ec3136699c3354fb83097afc8f047975199559636e171716430faeb128c7b278f0b5147f245901043f988b44b8009b9f6a3065f6ab0ab0d8dd9caaf66b828d0865e09479924215e5278033676c7261f9d7a704ca3a11501e4791ae77d789db7f3336f6b9ea73398c0f9fe1d1aadc79054aea6ae63a89900b148e38ec0b89a58ad22d64232a8e004dc194ad047dce978bf29996d890cde90cf4bbc9f327b698a28aef6aa32cc37c", 0xd68}], 0x6)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x10000, 0x0)
pwritev(r1, &(0x7f0000000700)=[{&(0x7f0000000340)="8636200cdc7ffe13adf368f7ea1fc2888369ba5cf0c9a131245f6ed90c1b95f6e56b1846e06af2c3c3d4ae6f50067e151ad44376f7f3c92e2d35dea4163e7a3efe5647498da824d103e83f7f03ad6c99f74546771b9cb24ca15e0853903c3ab4ccf5d7c4039bd904213686c25686a8b334dd8ab137914dadc8ee087100e845108460d85c2b4fa602379398e56054d4a15b6f415e4a04ec6e4b49cd0ebdfd50", 0x9f}, {&(0x7f0000000400)="01a5d75d4af7a5e66938363e9dec9db772fcd2b2aa21a320553be9011f0fd6a009f1bf3486886f2c42088fcd6f8d263d204599967c18812d2499c76f786e316b00ac92f63d7018e0dfbe433ed3e8a3c4c97586af779c9c9410deeb221e35b2d76983293d35d69694a7d85f611df3ce0f8819b371d5f8f83078af733a56a383993ed84737e4bf6310552c172697c8c4dfc7abe5dc54da18b9294f1dc7c68d145b378a1467e3e799ad77a20e2e1eb7be", 0xaf}, {&(0x7f00000004c0)="a644c5af640a120cc4", 0x9}, {&(0x7f0000000500)="9e5e90c348bb95d1b1030e5044454e12d124e82d44fbf4ce53525eb0434b729f111fca35077dfb96e6732e18432aaed46b08d5b93677a8211c3dec2a0a96f0e7703e26d5dcac688b62240f3cae8a22aca3f33ab09f2c12046da0fffc3e00ceabf1458fab957ae6e5476285b7371ca83cbe866dd0d1c400cbf3e1376d19838dfb67153ad64397d4b1dccccfd8c3cc9c7e2c761f0c91ab098fc79d226ab7f535b621ddf3d5927ff6a1470876a0cc30c41f59f0e2403bf40783929849a50a1ea039b64bf1a270f70c", 0xc7}, {&(0x7f0000000600)="4bdf1d9fbf668f88240f07fab23884773bc86bd05dae17278f4fa8f7fb23c91b8ed740a6d34b9d999997efef594373642ea04b99cda4edde6bad88a55773a3cc02fc2c8630933158ba818ce9ecb93020dc1b6cda3b347ee96bc99837bfb8a301c1aeb7c1618c735595c128d0ac29cbc4184457bd68ad2ab25262615b49ab0a5cbcf0d8772fe72cb6b542718ff909ea6b78a078e83feea27ab83d4b7930333bf4625582e6b302887cf7c73de227afd350d485a07d2c2c9c97e3981f78c6375e8bc698c1ed25e86aa87385db2f0620faaada8cd513676e2d2e1cf76adca3af7630d559a854e2d26e94dac587", 0xeb}], 0x5, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106978, 0x0)
open$dir(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
syz_emit_ethernet(0xe, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r2 = socket(0x2, 0x2, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x1, &(0x7f0000000080)="0315f1d89ec5a317a9", 0x9)
connect$unix(r2, &(0x7f0000000000), 0x10)
write(r2, &(0x7f00000000c0)="6bbc4044635cdfa0130442359ce30f1d6397d3e99e3a21cac54252de3f31068e94599964f0992fc4f57a21f3e43840110c5aedadf134eb754e43cfefbf30d1873b41d1b6db5ac9b567031f5f94e299e42815a09a0b895b7d71fbe32bbcc6eb773fd30096f35767d120948e67b7183f75f955cebe0ab31be9a3471867737ede7592cb85a0a3fa080000009b265a129a79ed9980eaaacbcce224abc7b30926aef1d2c9497b96374901fd3f0fa136327cedf27ab77a7bd690a931e870d6576296ea83f54541af73092ebe7575a3899854202d3ae7ed09d9cb3895d29f8722ad1fc4315f2c7a83cfba586bf6cf2b232222ba0315879fcc0c5c729cbafa39551ad6d7bf1fe58fefee90cd34bebbc4ba6faf759e1647ee8384574e91bb29d971700c1f0f2b2c27263a73328833bd4bc5577fd4521ff3ce1257081533ede709c175acf59272ef759399e20f7f3ebedcdb6485ae8b72228ef2a8172601ce45147783ee8e3186f8e0acb23c55df91e99a27c8bc1358", 0x171)


munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
sysctl$vm(&(0x7f00000000c0), 0x2, 0x0, &(0x7f0000002280), 0x0, 0x0)


r0 = socket$inet6(0x18, 0x2, 0x0)
r1 = socket(0x18, 0x1, 0x0)
shutdown(r1, 0x2)
dup2(r1, r0)
ioctl$VMM_IOC_READREGS(r0, 0xc050756a, &(0x7f0000000000))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000100)={0x3, &(0x7f0000000040)=[{0x1}, {0x25}, {0x16}]})
write(r0, &(0x7f0000000540)="76e5dead6f01f8607d2100000063", 0xe)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x8})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f00000005c0)={0x0, 0x0, 0x0, 0x0, "d8b5220d88f1155400"})
mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x412dff)
r2 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
open(0x0, 0x0, 0x0)
writev(r2, &(0x7f0000000400)=[{&(0x7f0000000080)="87", 0x1}], 0x1)
writev(r0, &(0x7f0000000080)=[{&(0x7f0000000100)="f40195903b88eb2c39", 0x9}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000240)=[{0xc0}, {0x5c}, {0x6}]})
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x0)
open$dir(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, 0x0)
syz_emit_ethernet(0x1019, &(0x7f0000000400)=ANY=[])


r0 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
ioctl$FIONBIO(r0, 0x8004667e, &(0x7f0000000040)=0xfad)
listen(r0, 0x0)
r1 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
accept(r0, 0x0, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
close(r0)
r1 = socket(0x18, 0x2, 0x0)
mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
open(0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
ioctl$FIONREAD(0xffffffffffffffff, 0x8020699d, 0x0)
close(r1)
socket(0x18, 0x3, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmsg(r0, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1400000029"], 0x3e}, 0x0)


mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
chmod(&(0x7f0000000280)='./file0\x00', 0x3a)
setreuid(0x0, 0xee01)
r0 = open(&(0x7f00000001c0)='./file0\x00', 0x0, 0x0)
fcntl$getown(r0, 0x5)


socket(0x2, 0x3, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000040), 0x4, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
utimensat(0xffffffffffffffff, 0x0, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000080)={0x4, 0x2, 0x6, 0x19}, 0x4, &(0x7f00000001c0)="2a54558c1b4577fb0d6f752d17f4752b0687d29c6a6b2a4558f1a935a0c9b45b6be68aa4ee2184035fb303261f8099378dc6d0d256131a320ffe96759f2d2266242b67aac1c8eb464e522bed5098b241589aac30b2552b6f5dde07c7f8d9eb5ebf395136f3f3a2d2c07aa388ecf314573f20b6ffb991b60da23f", &(0x7f0000000100)=0x7a, &(0x7f0000000240), 0x0)
sysctl$net_inet_divert(&(0x7f0000000100)={0x4, 0x2, 0x102, 0x1}, 0x4, 0x0, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(0xffffffffffffffff, 0x80085761, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
socket(0x6, 0x2, 0x0)
r0 = socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1023, 0x0, 0x0)
r1 = socket(0x2, 0x2, 0x0)
dup2(r0, r1)
getgroups(0x0, 0x0)
mknod(0x0, 0x0, 0x0)
r2 = openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x8981, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r2, 0x80105727, &(0x7f0000000000)={0x0})


syz_emit_ethernet(0xba, &(0x7f0000000140)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaabb86dd600000000084000080000000000000000000000000000000ff020000000000000000000000000001", @ANYRES32])
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000000)=[{0x0, 0x0, 0x1}, {0x5, 0x0, 0x3e}, {0x6}]})
sysctl$kern(&(0x7f0000000000)={0x1, 0x42}, 0x6, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, 0x0)
dup(0xffffffffffffffff)
openat$vnd(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000))
ioctl$WSDISPLAYIO_GMODE(0xffffffffffffff9c, 0x4004574b, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
r2 = fcntl$getown(r1, 0x3)
setpgid(0x0, r2)
execve(0x0, 0x0, 0x0)
r3 = socket(0x2, 0x1, 0x0)
setsockopt$sock_int(r3, 0xffff, 0x1, &(0x7f0000000240)=0x5, 0x4)
mknod(&(0x7f0000000040)='./file0\x00', 0x6000, 0xe02)
chroot(&(0x7f0000000180)='./file1\x00')
mknod(&(0x7f0000000000)='./bus\x00', 0x2000, 0x504)
open(&(0x7f0000000040)='./bus\x00', 0x10005, 0x0)
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x287e)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x200}})
r4 = socket(0x18, 0x3, 0x0)
connect$unix(r4, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r4, &(0x7f00000000c0), &(0x7f0000000180)=0xc)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
r5 = socket(0x18, 0x3, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r6 = socket(0x18, 0x2, 0x0)
dup2(r5, r6)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000980)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f0000000000)=[{0x35}, {0x16}]})
write(r0, &(0x7f0000000180)="7f23a3c23cce2575e1dd92c25683", 0xe)


open(&(0x7f0000000000)='./file0\x00', 0x8691, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000140)=[{&(0x7f0000000540)="2005666c883d54cf5e7706329e8f1309526334d94464e122c41684916a25e5ffaebb4ee93bfd907657f024bd22dd2150557e9d1ce91fdb5e592293b792bcd49b5972ac274e4a0eecae2a1a1172369f3751ae86e51f24134028c3b9de41afefd00000226652a46d76c9b2471196f8ca33fd0f591b023425fc608e8dee98d55bece13a4db5016f8171c54950520d1b661d008990f15eeeffdb2239c96a7e9110be30efa04ab933d6652d1c475f9e75df4f7317ce16a5e46e7e378c4bce33b8dcf0d979d4b2cb11e8c9cfbcb7036c2904aa0424e8ffb48558bc89b78413fd6ae44aadd997d93d8a2ed8214bb7caef41ee7907d56746a352ae2d09189dce4448deabe98f03bb6564f616d58a8cba610c8cd2b3b3d8b4e2c10e06298ab67333ea8bd0f1240ca8be79549571d3995c430995cedd3979b034d86f3dbd", 0xffffffffffff7788}], 0x1000000000000199)


r0 = socket$unix(0x1, 0x5, 0x0)
bind$unix(r0, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r0, 0x0)
r1 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
r2 = socket$unix(0x1, 0x5, 0x0)
connect$unix(r2, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)={0x3, 0x7fffffff})
r3 = kqueue()
kevent(r3, &(0x7f00000000c0), 0x30, 0x0, 0x57d, 0x0)
getgid()
setrlimit(0x0, 0x0)
r4 = syz_open_pts()
close(r4)
ioctl$TIOCSETAW(0xffffffffffffffff, 0x802c7415, 0x0)
kqueue()
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x2, 0x0)
unveil(&(0x7f0000000040)='./file0\x00', &(0x7f0000000080)='c\x00')
syz_emit_ethernet(0x36, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x28, 0x0, 0x1}, @tcp={{0x2, 0x1, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000002c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{0x1d}, {0x1d}, {0x16}]})
ioctl$WSDISPLAYIO_DELSCREEN(0xffffffffffffffff, 0x80085754, 0x0)
syz_emit_ethernet(0x6e, &(0x7f00000001c0)=ANY=[])


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
getppid()
r0 = getpid()
r1 = fcntl$getown(0xffffffffffffffff, 0x5)
r2 = getegid()
r3 = msgget$private(0x0, 0x0)
msgctl$IPC_SET(r3, 0x1, &(0x7f0000002f80)={{0x0, 0x0, r2}, 0x0, 0xff, r0, r1, 0x7fffffff, 0xa, 0x2000000100000001, 0x7})
msgrcv(r3, &(0x7f00000000c0)={0x0, ""/113}, 0x79, 0x0, 0x1000)
getppid()
openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
execve(0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0xfffffffffffffffe)
r4 = msgget$private(0x0, 0x0)
syz_open_pts()
pipe(&(0x7f0000000840))
r5 = kqueue()
r6 = syz_open_pts()
dup2(r6, r5)
select(0x40, &(0x7f0000000040)={0x6, 0x0, 0x7, 0x0, 0xfffffffefffffffd, 0x81, 0x22084473}, 0x0, &(0x7f0000000140)={0xab6, 0x1000000000000000, 0x0, 0x0, 0xb3f3, 0x6, 0x0, 0x7ff}, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
ktrace(0x0, 0x0, 0x0, 0x0)
r7 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
setreuid(0xee00, 0x0)
r8 = getuid()
setreuid(0xee00, r8)
r9 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r9, 0x8028698c, &(0x7f00000001c0))
ioctl$BIOCSETWF(r7, 0x80104277, &(0x7f0000000100)={0x1, &(0x7f0000000080)=[{0x6e2c}]})
msgctl$IPC_SET(r4, 0x1, 0x0)


sendto$unix(0xffffffffffffffff, &(0x7f00000000c0)="b100051300000000000000402020000000000000cea10500fef96ecf2ac72fd3357ae30200004e3039d2d236acf20b7804be38164991f7c8cf7f882b297be1aa0540000051e2f0ad3ebbc257699a1f139b672f335c223e7d0c032b0c8a6443a42118000000720fd38bfbb770c1f5", 0x6e, 0x0, 0x0, 0x0)
symlinkat(0x0, 0xffffffffffffff9c, &(0x7f0000000140)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/file0\x00')
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x48, &(0x7f0000000100)})
r0 = socket(0x1, 0x1, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
socket(0x18, 0x1, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
sysctl$hw(&(0x7f0000000000)={0x6, 0x10}, 0x2, &(0x7f0000000100)="bbff2eba542c0580fa35632749b009ade26bd2094189ebdb4acfdd2cecc44d53d0d82cd69aaed3e5672f35b151", 0x0, &(0x7f0000000240), 0x0)
socket$inet(0x2, 0x2, 0x0)
r1 = socket$unix(0x1, 0x2, 0x0)
semget$private(0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, 0x0)
mprotect(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x0)
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
r2 = msgget$private(0x0, 0x0)
msgrcv(r2, &(0x7f0000000b40), 0xa6, 0x0, 0x0)
mknod(&(0x7f0000000040)='./file0/file0\x00', 0x6000, 0x800)
fcntl$dupfd(0xffffffffffffffff, 0x0, r1)
msgsnd(r2, &(0x7f0000000340)=ANY=[@ANYBLOB="02"], 0xe1, 0x0)
ioctl$FIOASYNC(0xffffffffffffffff, 0x8004667d, &(0x7f0000000180)=0x2a)


r0 = openat$wsdisplay(0xffffffffffffff9c, &(0x7f00000000c0), 0x2, 0x0)
ioctl$VT_RELDISP(r0, 0x20007604, &(0x7f0000000100)=0x67d10ff0eedf750e)
r1 = kqueue()
kevent(r1, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x6, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x2, 0x1)
r2 = socket(0x18, 0x3, 0x0)
setsockopt(r2, 0x1000000029, 0x27, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
open(&(0x7f0000000000)='./file0\x00', 0x9cab835cfdc52675, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x40000538, 0x0)
r3 = openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0xe8, 0x0)
fcntl$dupfd(r3, 0x3, 0xffffffffffffffff)
r4 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r4, 0x8040691a, &(0x7f00000001c0))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x200, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x7, &(0x7f0000000080)=[{0x3681, 0x4, 0x35, 0x5}, {0x5, 0x80, 0x7, 0x9ecd}, {0x7, 0x9, 0x24, 0x8}, {0x0, 0x81, 0x0, 0x5}, {0x6, 0x0, 0x0, 0x6}, {0x0, 0xff, 0xff, 0x12d}, {0x4, 0x1, 0x2, 0x4}]})
seteuid(0x0)
r1 = open$dir(&(0x7f0000000100)='./file0\x00', 0x20000, 0x8)
mknod(&(0x7f0000000140)='./file0\x00', 0x2000, 0x80)
semget(0x3, 0x4, 0x40)
mknod$loop(&(0x7f0000000180)='./file0\x00', 0x2000, 0x0)
r2 = getuid()
select(0x40, &(0x7f00000001c0)={0x8, 0x1, 0x81, 0x101, 0x54f9d347, 0xffffffffffffffc8, 0x9, 0x84}, &(0x7f0000000200)={0x7ff, 0x5, 0x3, 0x200, 0x5, 0x4, 0xa4, 0x4}, &(0x7f0000000240)={0x0, 0x0, 0x0, 0x8, 0xffff, 0x7f, 0x9, 0x2}, &(0x7f0000000280)={0xffffffff8b9ed0c0, 0x6})
r3 = semget(0x2, 0x2, 0x180)
semctl$IPC_RMID(r3, 0x0, 0x0)
madvise(&(0x7f0000ffe000/0x2000)=nil, 0x2000, 0x0)
sysctl$hw(&(0x7f00000002c0)={0x6, 0x19}, 0x2, &(0x7f0000000300)="5e791599eae3b1b75dcafa2da056e8757cc1f34f494369a35c220890dc772a2f613aaedd7266250ed8cc99ae148f9158bdc770ced75c78e88b2b13da5b19e48c1988bd41faa8ba3d389e9209a56532fd2e73b62cb3ffe280c97bcc4b27cb402626571383c556147b87d969d996d5a2c106cb606b203f8e5e44c9f34ed8c75b652ab2ae69b4452bb1b2a8a74dbe0aff589e65b1ba73b0fac422a572fcfd09255ab8ab", &(0x7f00000003c0)=0xa2, &(0x7f0000000400)="0226a1165c58947a52316e54f1b2724a2396bb52265a7eb9b35c342ca396f9254faabb6d9001bde4bed93aeda0", 0x2d)
ioctl$BIOCGETIF(r0, 0x4020426b, &(0x7f0000000440)={""/16, @ifru_flags})
mknod(&(0x7f0000000480)='./file0\x00', 0x20, 0x2)
r4 = openat$zero(0xffffffffffffff9c, &(0x7f00000004c0), 0x2, 0x0)
getsockopt$SO_PEERCRED(r4, 0xffff, 0x1022, &(0x7f0000000500)={0x0, 0x0, <r5=>0x0}, 0xc)
fchown(r1, r2, r5)
getsockopt$sock_cred(r4, 0xffff, 0x1022, &(0x7f0000000540)={0x0, <r6=>0x0}, &(0x7f0000000580)=0xc)
seteuid(r6)
r7 = semget$private(0x0, 0x1, 0x220)
semctl$GETNCNT(r7, 0x4, 0x3, &(0x7f00000005c0)=""/32)
semctl$GETPID(0x0, 0x0, 0x4, &(0x7f0000000600)=""/233)
mprotect(&(0x7f0000ffe000/0x2000)=nil, 0x2000, 0x4)
ioctl$VT_GETACTIVE(r4, 0x40047607, &(0x7f0000000700))
ioctl$WSDISPLAYIO_SMODE(r4, 0x8004574c, &(0x7f0000000740))
semop(r3, &(0x7f0000000780)=[{0x4, 0x1, 0x400}, {0x3, 0xd5}, {0x0, 0x8, 0x800}], 0x3)
ioctl$WSDISPLAYIO_GETSCREENTYPE(r4, 0xc028575d, &(0x7f00000007c0)={0x9, 0x3, './file0\x00', 0xaeb9, 0x9, 0x6d, 0xfffffff8})


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f00000000c0)='./file0\x00', 0x63)
setreuid(0xee00, 0x0)
r0 = getuid()
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f0000000580)={0x0, 0x0, <r2=>0x0}, &(0x7f0000000140)=0xc)
chown(&(0x7f0000000200)='./file0\x00', 0x0, r2)
setreuid(0x0, r0)
truncate(&(0x7f0000000100)='./file0\x00', 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140))
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg(r1, &(0x7f0000000900)={0x0, 0x0, 0x0, 0x0, &(0x7f00000007c0)=ANY=[@ANYBLOB="04010000ffff000001"], 0x104}, 0x0)
r2 = socket(0x11, 0x3, 0x0)
sendto$unix(r1, 0x0, 0x0, 0x0, 0x0, 0x0)
dup2(r2, r0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000080))
r3 = open(&(0x7f00000001c0)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000, 0x0, 0x2015, r3, 0x0)
msync(&(0x7f0000ffa000/0x4000)=nil, 0x4000, 0x6)
bind$unix(0xffffffffffffffff, &(0x7f0000000280)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
connect$unix(0xffffffffffffffff, &(0x7f0000000000)=@file={0x0, './file0\x00'}, 0xa)
sysctl$machdep(&(0x7f0000000080)={0x7, 0xf}, 0x2, 0x0, 0x0, &(0x7f0000001100), 0x2)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r4=>0xffffffffffffffff})
connect$unix(r4, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, 0x0)
syz_emit_ethernet(0xa7, &(0x7f0000000b00)={@broadcast, @broadcast, [{[], {0x8100, 0x3, 0x1, 0xfff}}], {@generic={0x888e, "58203b37dbf3154ddf0f91791975f3955428d247da96d221fb78d7f57bd51140154fbd4409459cf75737e49cc22bfb2bdc39a095b4713f6f01bd444bce1d2d35627e8f40b26f4189660216878d2278f94a6ed10daf28a4f1e665e2eba430819ce5de5b232c3b2a9f4b6a35ed795c00919e5d0ee7d5b8c32964a4368d2c5a14907f2f4cb35bd30630a625a2b2be8b2d4b3b4c4ed83c"}}})
syz_emit_ethernet(0x0, 0x0)
semop(0x0, &(0x7f0000000580), 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000d40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlink(&(0x7f0000000ac0)='./file0\x00', &(0x7f0000000e40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000f40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
rename(&(0x7f0000000300)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000200)='./file0\x00')
rename(&(0x7f0000000740)='./file0\x00', &(0x7f0000000780)='./file1\x00')


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0xffffffffffffffff})
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
socket$inet(0x2, 0x0, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x3, 0x3a)
r2 = dup2(r1, r1)
setsockopt(r2, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


sysctl$kern(&(0x7f0000000280)={0x1, 0x47}, 0x3, &(0x7f00000003c0)="8b5ea54a413c745995d4a95b979bb64d0541e6a50849f2861cc5f3e014d9ea6bba61da747d3cd9a068b38d0bb67a985e46184f42a6c16a68078392dee63af6e601c0865da92ccdbbf8b85cb74d593a4d771ba5adb1403ae15565ef56d99f35fcc544e7a02a6c038ad8350c06a67bb9150e72e4f7e3084bf8a8cd1f65c4f707722236a4bc53e00f6e41aaea38a0c4e09508e1e439d617879713ed556c9f38b1213fe3ebb3d05a1fb9af890b38975b0a67fee19a5840f6e655d79e6d8596f328b0a7315e826f5b2d2ef536e5c9fa3e6af4a8c312e71e7da86dd5ea55f5a6a153b43941fab0217cbe2a5fbfc598f2f1bdd630558d225116d927d6d4c600418246ac0b6dde68455e73bcbe8a3d", &(0x7f00000002c0)=0x12, &(0x7f0000000300)="6675ce01f40d6aca4f5b680c7e17a4db799bb2480f1b4e922dd582704df696f66891b95981f7d920436699f59f5bcdb142bd08777d3dfee17dabe90c8f0d3defb72a65e0583485bfd0ab622d2267677a928d2d3d84731c57b234e88df06caf4fee4aa32022541c8c057f1c601f54d25fec982caee472cbce44bb86c6d5b25c6ba673915108c6f254cc12f9287a60000fbbf686386e3e", 0x96)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0xc}, {0x3}, {0x40e}]})
sysctl$machdep(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
socket(0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
shutdown(0xffffffffffffffff, 0x0)
sendto(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, 0x0)
socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
ioctl$VNDIOCCLR(0xffffffffffffff9c, 0x80384601, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
dup2(0xffffffffffffffff, 0xffffffffffffffff)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x2a, &(0x7f00000001c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000480)="7aa883c7fa66e1a18c0e5c61847cd89f23f6472d", 0x14}], 0x1)
execve(0x0, 0x0, 0x0)
kqueue()


mknodat(0xffffffffffffff9c, &(0x7f0000000400)='./file0\x00', 0x2000, 0x0)
r0 = syz_open_pts()
ioctl$TIOCCONS(r0, 0x80047462, &(0x7f0000000080)=0x7)
r1 = open(&(0x7f0000000200)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSFLAGS(r1, 0x8004745c, &(0x7f0000000000)=0x3a)
readv(r1, &(0x7f00000001c0)=[{&(0x7f0000000140)=""/5, 0x5}], 0x1)


r0 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r0, 0x80085761, &(0x7f0000000100)={0x3, 0x100})
ioctl$WSKBDIO_GETDEFAULTKEYREPEAT(r0, 0x400c570a, &(0x7f0000000000))


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000a, &(0x7f0000000000)="ea00005c00000000", 0x1)
setsockopt$inet_opts(r0, 0x0, 0xb, &(0x7f0000001500)='\t', 0x1)


r0 = socket(0x18, 0x3, 0x0)
setsockopt(r0, 0x1000000029, 0x24, &(0x7f0000000000)="5ab7776a", 0x4)
setsockopt$sock_int(r0, 0xffff, 0x800, &(0x7f0000000180)=0x2, 0x4)
recvmsg(r0, &(0x7f0000001340)={0x0, 0x0, 0x0, 0x0, &(0x7f00000002c0)=""/71, 0x47}, 0x0)
syz_emit_ethernet(0x4a, &(0x7f0000005c40)={@random="69e1629b6174", @remote, [], {@ipv6={0x86dd, {0x0, 0x6, "6b9efb", 0x14, 0x50, 0x0, @rand_addr="cb69bc83c1677a656ab420666c3e2c6f", @mcast2, {[], @tcp={{0x3, 0x2, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}}})


socket(0x18, 0x1, 0x0)
ioctl$VNDIOCSET(0xffffffffffffffff, 0x41946465, 0x0)
sysctl$net_inet_tcp(&(0x7f00000000c0), 0x4, &(0x7f0000000000), 0x0, 0x0, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x2, 0x3016, 0xffffffffffffffff, 0x0)
ioctl$FIONBIO(0xffffffffffffffff, 0x8004667e, 0x0)
semctl$IPC_SET(0xffffffffffffffff, 0x0, 0x1, &(0x7f0000000240)={{0x1, 0x0, 0x0, 0x0, 0x0, 0x1d5, 0x7fff}, 0x9, 0x0, 0xa000000000000000})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7, 0x3}, 0x8)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000001c0)={{}, 0xffffffffffffffff})
ktrace(0x0, 0x1, 0x80000400, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
setrlimit(0x8, &(0x7f0000000980)={0x7})
close(0xffffffffffffffff)
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0x8040691a, &(0x7f00000001c0))


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r0, 0x80206913, &(0x7f00000001c0))


mknod(&(0x7f0000000040)='./file0\x00', 0x1000, 0x0)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f00000000c0)={&(0x7f0000000000)='./file0\x00', 0x4, 0x0})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
bind$unix(r1, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
connect$unix(r1, &(0x7f0000000000)=@abs={0x0, 0x0, 0x1}, 0x8)


ftruncate(0xffffffffffffffff, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f00000001c0)=[{0x60}, {0x2}, {0x106}]})
syz_emit_ethernet(0x36, &(0x7f0000000200)=ANY=[])
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
recvmmsg(r0, &(0x7f0000000480)={0x0}, 0xffffffffffffffc9, 0x0, &(0x7f0000000500)={0x200ffffc, 0xa})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
r1 = semget(0x1, 0x0, 0x68)
r2 = geteuid()
r3 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000140)=[{0x35}, {0x3d}, {0x6}]})
openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
mknod(0x0, 0x0, 0x5c4a)
open(&(0x7f0000000300)='./file0\x00', 0x0, 0x0)
setrlimit(0x0, 0xfffffffffffffffe)
openat$zero(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
syz_emit_ethernet(0x4e, 0x0)
r4 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
setsockopt$inet_opts(r4, 0x0, 0xd, &(0x7f0000000240)="ea00000100000000", 0xc)
r5 = getgid()
r6 = geteuid()
r7 = getgid()
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f0000000000)={{0x4, r2, r5, r6, r7, 0x50, 0x80a}, 0x7, 0xfffffffffffffc01, 0xffff})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x2, &(0x7f0000000100)=[{0x34, 0x0, 0x0, 0x2000006}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000140)=ANY=[@ANYBLOB="6b435c90f63e3d347d2a7140d5a0e35c4bd277e820270fb34529c2f26ba7f3d2dcc9b65098c01ea51c3d0367cae691923bcdd195e8e2f8dddd6bfba8f866434eb0be40c8e6c2c278711a9d79d2ded82f5f11718eae872122d4d199600b9c29d69dafb084885d60df"])


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
socket(0x18, 0x2, 0x0)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1800000029"], 0x3e}, 0x0)
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)


socket(0x0, 0x3, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000380)=[{0x1d}, {0x1c}, {0x406}]})
syz_emit_ethernet(0x138, &(0x7f0000000040)=ANY=[])
r1 = getuid()
setreuid(0xee00, r1)
pipe2(&(0x7f0000002940), 0x0)
r2 = getpid()
geteuid()
setpgid(r2, r2)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r3 = socket(0x18, 0x2, 0x0)
ioctl$FIONREAD(r3, 0xc0106924, &(0x7f00000001c0))


syz_open_pts()
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000080)=[{0x4}, {0xc}, {0x8106}]})
syz_emit_ethernet(0x2a, &(0x7f0000000300)=ANY=[])


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000000)={0xf66c, 0x0, 0x7fffffff, 0x4777c53f, "1c192609307e7be2df67de200000d964612c3300"})
writev(r0, &(0x7f0000000580)=[{&(0x7f00000021c0)="4851872fa283958a1e2a20bd434bb69e38cd39063f209914fd0a3f59086dff13b82e546b107162fae0f3c66f2d126bc7bd4ca1271bac8d55c242698fe510b89e4743f074ff481efd4752cea7ff140d12bb1359c9589ea5e37c4e7107d6392ca8202c64e1ec2cbd3b557a0afb8c66b266cc355e0cae5414e5695243fc1ddfbdaa1a5c3757ce97c7a4650eb532308f9f83d5dcee701fc73c938c24ffedb5fab5814c4f2052230671949c78afc8809631ed7bd96ee19cc7b347ebb2bcaa33b57739d05916f918f98a78f5bd9fc893af6607c01aad487d75a9d1708cbe3af7bd74fe00e6db7245cf72b5e7373840eff128ba38e8cc981297cafcdd0f80c0cff4c9329536b21b41e178a3178be800478ceaa2ed473fa7b24bd1e259e4a0b54ef3551db6b53a0c887768aa2caed6e3844d04f43f6373b2b5d30c7ceb5239c89d68fdaa4ae33a8d4b71304c9ac115520797c986425fd6ba4aca494cf7fed0d1b8d78901a6394fe92e244c3efc5281ca69dde30ecd8eb9b854ee55d31ca31d7769ac8c9f30c63221027e75950e5399f33a730f5a357fcacf796d8d85c2be48cbf5fdf39b4f4c03dc775ec812c7fa2dcb06efa35813679ea68c140f184649d94196091830776882072913df6ffdfc73225b57f35bd670272b53076ca5bb9f3aefeaafc4b1cde5786e7e6c6028f5bc536594ed9e626a878f4a06842c96d901c8034e68a25c86f54ff6a7da643492a5287100766cf489fc122593823c7a3981fc301109f8eb5a86e4a15a021d285fb1611e0dfe102d733df921d801fb27562bb02120e7d47d5a5c6f32ec422e1fd5a4532fe763b89d8e6b62ee9a2208fc1486e6d366442511d8ca8f783ddf55677618bb141d6e76c1cfdf408e0ac83849493bab8a3869f09b3c21f9c929b7e936c7e2124a8ad57449ecd2ee4ece8fd437d778e27e03f312569d26f4ca17976bd4d8906647df0310afaea8165c7b", 0x2b5}], 0x1)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$FIOASYNC(r1, 0x80047460, &(0x7f00000000c0)=0x6)
writev(r0, &(0x7f0000000280)=[{&(0x7f0000000a00)="918db972f599c02e0565eaed008441dd285e11922f9103f3c18b5e92e496724e488417d1a4aecff3b316656215acb1ba3469e19579f44495b29b07fe40f1d77a39c53e17b28fc542501c9f02c366a9f9679e03513078c8c0bf397f4921a869eb7160b5c6561c003fd67da318f79c2127e7f3c500d169439ae30e39631480864c6bda469ea7e1ecf2e6657adb0036e6931fe3cbc836dcd271081509c32878b2da5d1ab56161436bee33e0cd772d065f1708afa86d57e24a7bea15250c3faefecb4e2b152ba92f6978d8ef7b597faa894d911cb44ae7a71d96593feb079580679d13808303d5049b8b6f11f143f3c81ca0732a03ca4916376e135557348ef5df6c2cba44a39e9d7fe27157ed537227ae5a9590c77f5ac9b9832dd57c60b937113a7ab702d20f45f76460ea7a679b4c54bfa3c005d6965256c37a4583048b5a2aab5d7a8ac18f24c92c93b8a1c764eb4586d562119f8267feddb033f5eb6593166cb966d02946ba52fe745a9eb470cdaa87d7f1629a7df698a12cb59881d8a91e201ad99b44512b810c452fbcb78d3f32f6d76f48a084a44e9941341c6aef84efcfe31104258a6e26073ee8bed10494f667aafaf2505b0722b53583520170a7ae54e0e80e191074d167f17eeba58fd2401a8845bf37d609f74bbcdeea50df8dad70ea9f7108a9611d7eb57b83615b110b4ecd122f41ffa6e0d618e4759cbfb864b3f7d95da051be0458ccb08720cedec863aa80732717ee640ed88052be9a38830269b7cdfea83ba8ebddc1a989dfe1356a7e55d19721cd233aa97687c901746d1ef5c49d028bdea5061311fb81b8312f32e5ed8e52f7432bde05960d96d19241d7148ed50739429604429b21f56fa7713fcbcbf8ffbb49ae1489d2ec834ae31cf30cefc206484ce94cb79117ad2d8a64528afb6f143995c033a84c2efda865b96cbc1587fb2f4ae79eb5e136dfd0997d576ee762349e532ee540be32df7a6e7f67c760c1486c5c46f832d89b499e91ce9648a5e9df83530eb5762be1ff26151eabf5cee46618c2fbddb137baea87c520cd53b568a7e57cd22593bf3facda0eec6868837390846b9413b6e55ba2a21ed06d639f47b4839c39ee6df1bcc7cfcca9178ec0ac1d5780663cfe53d9d2682385141e1d02b4a5c5d2012ac9c83e0a477e49eb0158a79bbc58924c9bb97b911e14e149f88fe719c34cb95c6a458977989e5cec2a902def76269d36f2e980bd7fedd668dc0e2fd1f3c6c3d9befbda2d80e2ebf7cd9d0744b2ae0fff033987d09fa2bfb312c559599f1064913b96a3085735c1cd14bcfe3902c154ec491393e9eeec8fcecdb509632d2797d2abcc9c73e70636bd3e10a9eff051a33fdf73a3ad25f6575829fa3e3f05fd72adca5a74f3bcb2e96fe3ea3a0a045f54e432e26f3f580cf51b3e6e680b675b3d12cda2aa6f769404de58dbf2160b83110e52914340d07696635bd3ce97a620ca9609e7cc4a5173b05571b9572855042a6c59974b990fe7315d4ef882274fcc231be8a4b860169470b48f26ac16c344887cae2a245015954c5b1b42574e7b927077c1377933f6d20bbba799e0a51d1c1969e48b146740fb49dd6051a81b5485fe1d89b083b84082568e35dab66b79dea4848248dabc63eb6040c864bfd468ed578586cc3bfc3dbe978351145138fea623758dbc4ed437891baf5b67b44165e1c7eaf9e0e5252bc5001ea4d5ee4cf9316932f3a13c44e426d101b53ecbf29e05da752c63be86c91803461b30438b2951b504c57887fe570e3ce4def823d0cb3807a013308ad4f9c5c80ba2399db2f305111f48ac7244ecce02ec418d794644f0c4d041310bb1bf383df624a4402add9f52a33252855e18e8bb553e503dab370a7a554e59bd61b8bbdcff41b51144232d7d5bd6d32b7e80e3e8261c370b28e9e8d847bc5a05333d7efed0cfabc7c3e28f4956d364da97036435ab025c1d7dde0c890a26ab5ae010578a09897ea92982918352f65b19a73e55a07491ea807b3d7b096d4dc153223badd7619970ff7b2cfa39f23e025e59111f089012382e1585b7038ebb1634e7729476453f89572b670218bad37a9d6413022ddc2cd4a7e113bc0a282ececebc26d01e9f9fbc837ea1ad04ddafb4335d2888cb150c748ae39c8de3f09a6880df3419dc51a1dd3126921f2451b4a61978c0889496c0ab9dcbd98ad8bdebe5205a4a238b41fdea7c6a97e730a344e4df30a8179067f163e34628504c1dfda646411001579e40795b410a8ceead37bd99166eadd61a6daac078a0603f4bfd8042a21285c240010f4d16abfbf72ad8ff9ad5a9d3e259a39e436ee3ad26523d9fae2c0bb4b9a6655a8572820979e3a172446ac741b4d8020ba5f8f5a6ad6cf6afbb303cae09309a3d0043bfc5f8b798721269b78808f2a4f0be7b0e9d72fb2ab835552b1ddab02af3dd4b319e20e819cf7e74e2bb71d797e8a4abb06620a16b5732dee7699063b6e23f20c0b7418d71098a32a88711e7035f90eb6cf8328baaebb0711cc00c1c295ead8889bf0370ade93db8694fc837b8551f97085a0a1e319acc443ec0a7386caef796fd43bdcb5e282a04811c25407fc8dd1a70715d5c07026aa949ab5eac9834ef0c98dd54119585a59e504ce63696634a277a122d02ddc29192db37b879540b5db47eb27f88f870c42f70157203cd7b5592076fcb385be4b15a0de7ca07fde4c9210d365159a5c3fdc714c60af8f7a205bd7cfd5ec73c5fd3fd26a341f68d1450c82573018340222d3c1324d42568a565e92b970cb4119da54fe8b558d89e6cb4a10b58f3455f055039b961c8dd0c4771bc58bba9479374b08fcb6dc5fb554011273d34b817fc84ff713487dd224d365e7c9bc9258e4ec42bc6df7fe9aa5703dbbde6a5eb718d0944c29125501f555873323f8d4ebf87e1d0b04ddf9408c00f80879a2014de98cfffdf476c9dd30c13900a53086beb9a2de451d59fbbc4fd02477ec8744f0c113a60933115c06b2122178b9a7cceef7a1664d9b72c9d8714c88adc469e64e1a9f73b511b6fcd7924f1d7363e566f6b6e18ca0f52fc566fed4ae5ec7a37130f1c3b1559719e4fbb6be12bf1725a534e00ec050dc96c644a7153e410496baa9684d57542aafcbeaea04e8cf12965beff0382c540c1d564d635b6bc10e422c1e5b3ab724f23ca0ffc76e1da984e31ab30e50d315bed73082e3791baf3c5d19e4ab9d8df77d18045c807fb3907cdeaa1afc7b7b43b203eb8785f4d791d429380bd00602de24ee8728e9b157ee95a58a1152ac35f70df6bd57a1233a3a4d06075688f0656b36bbeb72cf065bb31edbac27f35cbaee649d7cf54b64b3350c29495dcf4255f8dd8e686bf248eedb376fb00faf8c2ac7c533e32eac9ceaba14b9eec7bd9b7cfcd287f6455dd335f923751bd967b763c7912c2a839281c88d47afc22cd93981c4b2c773dd638ca65555ed7941a1287e45e04d04ae8f05aedc3cfc66be9d4a58a555aafa2fbaebc7a5e23766e885916685079637613bafd020ba3a9edb670c8b2365634d932518a49c380b05b1dc965068036edd10de14003e8ce9f8b50f3e2d44521f86bffd03c4e37f02498dba98dd5051b1277d3dc57c35f7acf6de1d2f5f4c85ff463211ec437a5b54e48925aa6b01598a6c010fa4fb689424d9d001a7afc19d2a848e1c284effc5f79a709dc3f95222031b90d6d018df866a6d2be04343ce26e27fa1c8a14c8cf19e723e4a120eb3e0cc290ddc2ff4bd359616d8d033d843da2a45d87423c00eb2f9a5e745da9671cadbd8825655dbaf9b34b2f56657a5683e6af96b44db827dcdce6e8bdfb78e9f1eae83c3ad87f482dcaade4a655721b1673c53b6b0a08e688409db6e6ff387e4182f736b6c43899c1fd87581880946883c046dd9b049134416212155bcf3ad80432aca3c67d3777c3fb94c07759debe771f85a93cee0c32754222ee8b3df8f09eb18643dd53b54d97a39bbb1db11fcf8002dac118226948ecc439cf71649836b59ec4cb99d8dad51bc87734fb3ecdf5d3dfa8a337f2d5e705bbed7e830e4cd5ea8cdad680727d77b5cdfdc461e2bbb766a366f9c108a6085ae207569976b86f5c20269f596a04320a639aa42445ce0239277f502cf340e9a62cfa77975062ad64a9771f70bae6e0d14ba502ed7ab35dd3da65e9788b208fa8b475cb642114609f5bb5034c008008ea7171c3dce25a05c1d871a760c8c632bf28caa7dc6801ef6e54a5af043ab6aa31272c198f9ece06a7c1e74c13ea23cbd012bb1dd38ebc0e7b46688005b78d65af3e85e0a8f3eb86047c6f83db91e28dd59b90aed2ff3d3cc3486a6d9997dcd0013cae0bc230c74e4a4d5482f199cd14700d11231434196f48e478ed7b162574ec96b2f03f3a16ce8ce977f71d23219d56cc2395fd60444e2cc1b1b58478f5beb6a5463d7265e391f7e3f8daa7bcc1b468da66d96eeeb7c0d3791a3ad618cc05832a50e9298e6a81cf518448bd1ea1aae859ab2dffcbf5e39be0e78f4b7baaca2bf3cafa92114d7c7f0cf159e2f4aae2404bf3aede2d0fd57e059472567a1819f64f8634cf995ef6cec655d18e60c85022d1945564fdcd991283694e695f149a8c219558ab19ec3f9112b22df2403aa1d9cb85a0763906ebb464490db271a51d7e1b4111834ee440f42adc1ccdbddf6942952642dc21dddd71edb8a95b5ad91058827f3603441a53b08983d578a27d64109ff2940bfbaf09d142840b462a338e12f76529a3a89c9d308fc113f20d4b67d7feab0dbf7a131b00398d3e74549ae499ea8c9beedb1fbc6db26aeea390aa6b00d894d17b6b5681437d26d52d5c0958580495848a8dbd38c3ad3a325d3f61b9c9bdf9c24dc1c42020931d1e2097f4bd725f8da76bccc1c9c343831f822163b08518724d08dee737085ae372cc5f6c60b03e0f50909ae57678e5ff557bfc8373fcfea61faa8809bb17f565af3c9392d3b4bd76b99a32ff07c091d49542aa48bac686992ca80ec750e8093222e7d8210cec7ece721b2997d9c51a4ec298d2014ed2f3e6a63297af839ba92e281d4ec6c9dbb358032437279eb6e2941972228d9939222a5c9e053389a85538880f2e4caf8b3db88232da0257cab88e98f56af503a0cd1539b860b717e39810c6cb8073faa55cdf5401ab0117976fbc68cf56e2707f29995e9b2b18e304d72004857f60aca7aee4570242b9a1ce97ff176ffa717a656a28a9b8a3fd061c3b9bb64983b44d4f7bad39fc638f510a988a3a4141354a8995f48a08b01aed8a75f8079778df1955cc56e4b3ec70de1b00348a2f8d14d53a17177e43485bb8ef931fd56e4702069d4ce7cfae1509d80c9c3e22cdde3d7a2c60ea758490169be8a8212011ec7574ae90812b3ef68a475dda62141792bb6157e02dada02aff15de5a8da43cb1ecf89d5827b640918e7e49f17bbd89e59fe99b6f09bc00f2d03a221f31fe7987bc19bace7bd5768b44c59c5a822ac84acf267b10de2ebc38c5b7bc14c640099b87741fe2df99889ca0ab42c0b5de84abeab58fcb9ebb75de897204501917c3a9673af2ff5f9ca2b57fc86c88ad98a602e4714b9a43f052b24b8be353a24542a2898372cb94cc5254412d96dd4f8dc494ea8b4cfa896cb30f7f908a97d6fe8fdc26ce351631e366286c889ff5639c9842e3dff2ea9ed150096db35c41d661e738e56cd9cf9ca10b00811e662ac57d15d001ccc3970f359073362a6c2aba5ebac19bb0dab90756414559dade6cc8a441749cfa8c20dd890a252e92a1404c2e", 0x1000}], 0x1)
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000380)={0x0, 0x0, 0xfffffefe, 0x200001ff, "ff00f888494dea16574217c8ff2c0000004000"})
writev(r0, &(0x7f0000000400)=[{&(0x7f00000009c0)='\x00', 0x1}], 0x1)


r0 = syz_open_pts()
close(r0)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r1 = syz_open_pts()
close(r1)
r2 = syz_open_pts()
ioctl$TIOCSETD(r2, 0x8004741b, &(0x7f0000000080)=0x8)
writev(r1, &(0x7f00000001c0)=[{&(0x7f0000000100)="791c965780508f54dbcb129a9b6934991cba070d2e0c2f19ce57fdf185dff047b76f5bce561cfa080860c2905c9d57ef9df88eecb44cc27bf73a964b794a1daba7ac8742bea32f4d23e71ae0658372c558d41ee20902ae", 0xff81}], 0x1)
writev(r0, &(0x7f0000000700)=[{&(0x7f0000000080)='4', 0x1}], 0x1)


r0 = syz_open_pts()
syz_open_pts()
ioctl$TIOCSTAT(r0, 0x20007465, 0x0)


msgget(0x2, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000140)=[{0x40}, {0x64, 0x0, 0x0, 0x40}, {0x836}]})
syz_emit_ethernet(0x26, &(0x7f00000001c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000c40)={0x3, &(0x7f00000001c0)=[{0x74}, {0x25}, {0x6, 0x0, 0x0, 0xfffffffd}]})
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000080)="35b5c242413c1026089a59583cc3", 0xe}], 0x1)


r0 = syz_open_pts()
syz_open_pts()
syz_open_pts()
ioctl$FIONBIO(r0, 0x8004667e, &(0x7f0000000340)=0x8)


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x100000000000000, 0xffffffffffffffff})
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={&(0x7f00000000c0), 0x1c, 0x0}, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x3, 0x0)
close(r0)
r1 = socket(0x18, 0x1, 0x0)
close(r1)
socket(0x18, 0x2, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
connect$inet(r1, &(0x7f0000000100)={0x2, 0x1}, 0xc)
sendmsg$unix(r0, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{0x80}, {0x3c}, {0x6}]})
syz_emit_ethernet(0xe, &(0x7f0000000000)=ANY=[])


pipe(&(0x7f0000000040)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
r1 = fcntl$dupfd(r0, 0x3, 0xffffffffffffffff)
write(r1, &(0x7f0000000100), 0xfffffe5d)
recvfrom$unix(0xffffffffffffffff, &(0x7f00000000c0), 0x832f1f7d, 0x0, &(0x7f0000000000)=@abs, 0x2000c600)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000980)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000380)={0x3, &(0x7f0000000140)=[{0x40}, {0x25}, {0x6}]})
syz_emit_ethernet(0x4a, &(0x7f0000000040)=ANY=[])


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x1, 0x0, "0100012d29fb000700000000098002005e00"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x4f}, 0x3, &(0x7f00000000c0)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b1068dca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d127", &(0x7f0000000080)=0x4, &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0x63)


openat$wsmouse(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
r0 = socket$inet(0x2, 0x3, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1003, &(0x7f0000000480), 0x0)
socketpair$unix(0x1, 0x0, 0x0, &(0x7f00000004c0)={<r1=>0xffffffffffffffff})
sendmsg$unix(r1, 0x0, 0x0)
mknod(0x0, 0x100000000205f, 0x2802)
writev(0xffffffffffffff9c, &(0x7f0000001300)=[{&(0x7f0000000000)="19f3b0b3b875dbbb0f7263bb2830", 0xe}], 0x1)
syz_open_pts()
r2 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000200), 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r3 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r3, 0xc0106924, &(0x7f00000001c0))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
write(r2, &(0x7f0000000100)="faee4db2a5febc10a8f78845452301dfa0ef0a070a6bd603eca5aae536b80a2cf5d40720485bea59bbc24a5e8d139bfad12afd620df8daff8c89e0f06caa2f8cd2f0b991571cdff56dadd4865e556c5d99d28b06ae98c3352eca0024b7f171d07a440082", 0x64)
execve(0x0, 0x0, 0x0)
getrlimit(0x0, 0xfffffffffffffffe)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
preadv(0xffffffffffffffff, 0x0, 0x0, 0x0)
bind(0xffffffffffffffff, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, 0x0)
socket(0x0, 0x0, 0x0)
socket$inet(0x2, 0x0, 0x0)
ktrace(&(0x7f0000000100)='./bus\x00', 0x2, 0x4000010e, 0xffffffffffffffff)
socket(0x1, 0x4001, 0x80)
getsockopt$sock_int(r1, 0xffff, 0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)


getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000040), &(0x7f0000000100)=0xc)
r0 = socket(0x800000018, 0x3, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
sysctl$net_inet_ip(&(0x7f0000000080)={0x4, 0x2, 0x0, 0x25}, 0x4, 0x0, 0x0, 0x0, 0x0)
bind$unix(r0, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
syz_emit_ethernet(0xc2, &(0x7f0000000480)=ANY=[@ANYBLOB="aaaaaaaaaaaaaaaaaaaaaaaa86dd60000000008c0000fe350e28ef0900c08cfe24be00000000ff020000000000000000000000000001"])
writev(0xffffffffffffffff, &(0x7f00000002c0)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe2c63a56077123a276d3ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
mknod(&(0x7f0000000040)='./bus\x00', 0x2000, 0x6384)
r1 = socket(0x2, 0x1, 0x0)
dup(r1)
recvmmsg(0xffffffffffffffff, &(0x7f0000000000)={&(0x7f0000000000)={0x0, 0x0, 0x0}}, 0x10, 0x0, 0x0)
chown(&(0x7f00000002c0)='./file0\x00', 0x0, 0x0)
r2 = socket(0x18, 0x1, 0x0)
setsockopt(r2, 0x1000000029, 0x1021, &(0x7f0000000000), 0x0)
geteuid()
r3 = semget$private(0x0, 0x1, 0x82)
semop(r3, &(0x7f0000000340)=[{0x0, 0x7}, {0x2, 0x8, 0x800}], 0x2)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x1000000000000000}})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbdf13b9fd812eaa4e713048e69931929648", 0x14)


r0 = socket$inet(0x2, 0x1, 0x0)
r1 = dup(r0)
setsockopt(r1, 0x0, 0x20, &(0x7f00000000c0)='\x00\x00\x00\x00', 0x4)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
writev(r0, &(0x7f0000001480)=[{&(0x7f0000000100)="cc60d3d79a1a7122a5fb9de9ea6ca0b30fb2942ef7652736f10f86d45ae419b2ecf7af93d33b3de1f2c56c0d93da7484095d0d543baf7f0161a025c9c02a561f9a76d06f1eaec7d8df99d6c28b10fa891e47d6c3bba690a611889032ac7b3581d7c92d1c546e59764f069048316871794f0615dd4d8bb1057a61fb177be649004fb56a7d46c856a20d73f050bf29d58b803a676cc3761e8a47857f51d90a4465f9c605ab2829d78ea2571900", 0xac}, {&(0x7f0000000080)="b389e5ae", 0x4}, {&(0x7f0000000200)="5f6a8de84b4c523a583f91557c748a02cda4cedf13579996073843ec5cbabaadcec85d62a8a897a78307f3d2c30eea6356105ec8aaba86930f1aed0b3d111d", 0x3f}, {&(0x7f0000000240)="2a5f4cd9b73c31d629e8d68e605e5940744ef138960b671d42c56f79fcb70549247e5504e02f85a6099eff9291731e94399a7e966e783d4073ecd5dc8e540f32190bb47050aee3907495ecf7708d1c295a0836f79ba03ea13db12836c2441989726ffbf7fd1da55bfe2caaf081a1ef55599935c0e60cb0866ee48d420b77a6e269bc30b2650349e16792252c6be8bcc6e9ce2b941299ab505e4779fa1960bb7cf924dcbc53c82e76bcd80731a694d12e8a139d8ecef6f5560939054b7842d25cd7396377f39bcfe2a2383feea17b87393cd892b90742631718b1877d8d83d5f66587e3e5b1e129433ead750143a4c51aa46e78e3b1a54a4634eea2846511719b1637b19ea8c96a95332abd69014f53e91a7319a36efb4052387dc6330aa00b5680142650e8dab5eb6b83ff7d0bbf1293338a8d3e8a6dcd7ed4916279eac230dda46e6fcdebe8a4c12d598883d9392da05791e153d905ce1930aebfc5dfc0fc22a88777c9fbc24c0b021189c3503466bf850f59e6649dd0b40d935ba155a9d7e065df6d90a500be9d7e1e77607d495898a8d6c9c48dda88533e75e760dceae91d670f97ebbe68b845c72eb698a9e0389b15cfe768cd4e524dbe939bc2d8363ae3b71a454a0a0378cd1f36565ab9d1b92263688195df65151ee9b8158c7a5280019a38f00ea05142b3cc832ece46e326e36a55d7a30f866ca97da61a3877612f0d9f23c052edf60a430d3a9acbae3d9f14f22f38a1eeac7df37ae17748a960b9e0d265bf6cdec73bd2a7b5f25035d845d936936cbfe6f013f8d7c73eba2bd9876ff6db3224e50e75c051979f4cdc41d28ea54e28f560fb0291cd6b6ba527e0f358ffa46b988f0bdbf801063d2024380071709ac00ed463e08fd1718a857b567d8b3eda143915e943d9530d25ed15743e117be375dc08e241328a53fa05b58c7c72a35d471a72706afce82b6c57eef81444269e06338bfd0af6f6ef6479dcc26aab0b10c7e58572aa507a69831d63c78c947cecda2c57bb8ae6b2ad7862d160b423de941be69928467db10ee4817536196ad0c5cc02a74ba1a1fb467e472f025f200846112b6b3efd298284d8c0cc498fb9203db18e48e34c137d1285120d809a774d56a62b3dbe8f202cb9cf18c33099f5b9651fc7ae41de53842f327fd40bcfaa601a791da1103351a64cc9815ff1f32cde6fbfe4c92f55a9aff41c055d4edce9c656ecd1becb9035bb8bd46cf47bca0dcb1848da94d05d1475c83a48c02f8f808597eaa9e88a4e4b12d0ef95458eeab115cb189fa7e368186bb68610af4651e27feab061c4ada46e8c12d6d33fe32cd40485b02120418a9aaba8f04c17ea1abdcb9e6801f5d8090c0780b3b5ae4382efbb64f62c825527b7e3d60ad9c73ba7f174ea7c7f2d155808052a0ef6ab2af85cf9a758a8c1227c85f2986fc06c5f54807968b18b6b5f9168d0b2de2728689d75f0efaedf79bd8bbbbc1d46b0f6072d46d46687bc92c0b16c4ad36c3fe4c7a2fde0cfec859052dd78d841464a6b4432342ea973bf18f1f5abd7b2fe7962faef39ff38bd88a40dbab0f8c08541e38efe924f9ec1addbd47362e349bfca42fd62cf18fef8db7d3cbf0b1733d37dcdae5b9c738b8426a1cfa205c9671870210508c614f256d199fb822613518b1a6fccfee08c48f0feae1ca4baaf0a02635282d4f630a8df115dc73e72d9f7b8feb4333b2c796f1d3f2cfb398ba1e9c81584185b8b578bac3c64d667da7d91062f0c2ccec0c9d09e0c15c62e7bc509c3204d054c22d4eac685626e48e25cff2fc382279d9cb941c2ca182b1f65b05ff05db880a37b1e7f9b3d8975558858352bbbea9213a885b7d43451230e0624403baa77839baa33ae92de771ca76319c2353e9f98ea8191fbb686aed6d08e87bcc2bb8084ae02fafbac1a0bba93f0f155fa2d7bc21bf77f116429c6a1373c34d080518b73481fcf012c0a9127e8f174695ccd4add75b026bf2935990d5cebc4e74b97ae67a414029252336880232635fce7ed7bf0b069e08e10f7e1cc4d2973dcd2ea0b63f9dc4f4c2db92e03c553afcb1060b12f6b9b4d1d799edceefdfafdae63ad797e400645c149b20f8a10af54db3289441499e122413495c7b32179ab6c274bbdf6dde48ce26f46f07ede9a314c1a73669ee8cb0d854c8a3206dcd4f532d36fa7affca1226962e20ca2c6ca0da1ab0848d23d6f198681911592815c080cead9fe6c81cf0d7ce3578978dbf1dc2f1902e51f740f95b02ebff4cf25ac8d28b8e16998f5e329e9a377a82b5bc227f77c2f1ad505286aac8618799c2363a2d07d229519370be62ef0dde6525df45a7b807759b9ba1c8557bdbecb429432c4e1a84094edda567f1245ba887686342d0a31b7dbe09bd2be75516b255d2bfad9337649e86a29b0a19e16b4059c7c45e9f81db6780af6487a11f9088ea265a99d6e95535e14fe839945f8f7da9bf9142dd12c305bd41bb392cae8eb81b28fda176d4b538f4ddaaed47913cd9149d934ca36879718bbd76a2d7ce11e6294398ea433af6cf53b951974ec96a9527178b6cbad3088a2e2dc75113fa88ede462e68b4d6b63020a45e94fbc6c3e6677d6cffee0e3bf606cd2d4b9fac89f91db8f3a1fb9f506708314249fa5c36912e3cb281acbdec3b080735ae24ebb4bca3c7900c21175435afbe5024a706e90f8ecf257c99cd8b67b5a9c2bdc2bb624201f55882349526f8faf463eecb183635db72a6aef5fa2048d97e6f6c513598f49158050df1efc6b13b8ae396cd6a905c26b94d1d50d361f10c0362a8c206c7dd553dd8b116694aa82ac029c64aa71b8a307793da12f93ce030d3c42443c37b91043687befb7968da97ffe91d45e4fd506ba4d9c5d7fe5ac7433fb6bb3ce471f59ade734d109d2093fa119827b65a360f2128e7e85ab494609b60d6e236ed8a72984f6c75652f5baa07e2e921365af2b819eef58343e65ffb45ba8580d62f5b8a9988f7176c1559f8ede3b1b92e0ff27978fc5225ed1512b605f1fd4fce46e768970b11a7b4802c93eb05a8571887cdc15f69929eadcd1f9d08ed2d6aab2997ffa2102c2d8983a78ad43779d03aa612ecbbdde634b14e980b176f04f99efad82a04001f34d6addb89e0ce629856f5ad401fed1a2c046e1fe18741b24d4253830af94a1defeecdf6f70b430e48d7b2e4ae2fb331322d96e1a361e4dcae1d0865e7ccc4aa58bcbb3ad1ce0b294437887e03088a6bb4c92c3044bb33d2a893975023ad979fb2f84d4842326cf058595398779116245c452e54989df0591238af63c5b187d18457f008f2759ae470282ee4640e92639a46915fb67f22967beb1f46736aa9c90df08f39ee481f6859f9eafdecd473bdc24ef3ad71b4c54dde360f2d550db18af7589c8107f29b0a713b65f039da10c2dc55e408ce75c77aba97c116ab078ed1467464fe4041668228316f0fff7c0e0f1a3cc47aae570182197cc3a030a4af7fe2d401b5a13d59b8fe55d48b0667b782cbf1c2e9e491167d87830bb25008aff93c4459a3ce9fd8655a542c6311d91ec6b6bd7935aba1cd01d10439f5e5a3883566c8538edb97c5d2a7c7533d415973729f52dc03134f3d777b7ad07c0f5b0d985ca48fde6cce9ec99f1223f476dcfbb5ef865a3f54459415b25e2031eeb469c83ac68fd77e59c6b6a4b9543a943c4461e47e94d038c63abf2734a3c0e99b95505e13af6cf7b66840dc60e96fb218436ea00b4a577c2effdba43e6adf97cb47c0ce606e87a7834dec04396c1e4f7df59ae5acedfd1d68c87e405fc5d788884686270cb08f0fb15fe8b11589792f9afc11152cd45f43fac6e758588cfaa88874267c3096bd689108bbb0296f3d182df7d46cf7e6b8bb923ba887443c3d2211785e364c1e55d4e9396d950e50cc11ba9a4da70a64f6acbbcd421183eb2c0521054c4f39650409e21a9d3b781725b0c38abce7b4615fa64a9cbf71a19f7e414279a7494d2e66e4e2b2d5ce7027109cfc763a9dcac37065ae80ec0cf3962deec0f9eba3bd7c514a9854ddec6542cf60a1e69cf5d1a73239633675d4ac1f3b0758e69d1d9fb8659f43f07ef6b0b2a7c9740649198b44f3272a8810d374b00c1d49b7f667ed538d89e91e5734f8d6e270aef0a406fcb4072497dd5f25b49d31cfd64f7af2d5b4df72b74c39a66f442ae61aebe1cdb96b660e3248dad3d05bfce3d8630902a565c3a7636220e0435679ce1c45367570dd08722ddfe7f1bf56c44bcab8ef2d0979eeaa569dade4ec34751833d455b31b55edcb9b64f3045725fcd3a08ce0c20b09a437133df5738092eba91430208814b4135b0a64331aff1847ca60426c91e96a029cff039b14462da6e5f9c545980b3712f7fa5f3958d92278194cf6b37ef76e91103d14db403956a7070d87afa81df227f2189926e1265a2872e9d64c64496083caff36dd3c27e961957acb86f0f9a3cbb5ddbb6bf9c62dc102d70d62eea969b1c2c5f42823f76827e918ffa77cc12ca8d31effd0b55529c496da762b6a95d43360ea4e811979ee316e143733f886a6eca5ac76746d4a302ec57b6b4af57c25631d7773243abd400d15274703154dfde2f1a63e075e4b22ed4516dd1496e3f7848bbf19e3215edda64140649d9b1a06975773d5dd0ca9c4bdfd5eb9fb6164aa659e2a8415098dd05496d0b2a20d966a4c9efefa964e007a3b731d3bad501fd21ca564c6155d893c3075c234af6378a12595d8a88ae0518350b75d57fb91b7610bfc3168f548a9a63432b49a9dbee2ee1a4ddd80255e2c655cc80d59d7e90e21fb090db6d59ef84c0becfda6bd01c5a806ce67bea77fdba62ba40e2114d31e6087ad67b28adc20d7cabe7911aa2db119cf5f43b2011bb92556e8e303a264f813764027fbec36f8248a667c766cfc12c80d96965f222d39b5f58a54b255d3b1eb4530952b6d251ff1f9a2cbc585d539704c8ea6884699ebc95d57cd1daef169da86cc10fe7300352e939c35bbe3104aea1b1c681f3e98be8fad7c91bb56724ffa794ea4ac7c4d51d4aad8e94087b4cdcab897e70558e6648ab42dfadab447735912af011fdbd9a47a4958b953b01d2e274449854cb7d4b44d88fb2db162b8dd664c7c32858c7714c69b838cb30b17e6a42ca760256c4c6da57ad5be955ca8c787262d8bd3f4a5f0170e70f92ee2ec9d227d066e41d0d4b640166b2f6937a66bc84506d102d3edac818b246954ba200a3057820da10b64ff99f016b42d90a29b43290d731ef23a72612d646f92acc05620068fd94edd12902197733cc9dbb55d95930ccc749c4a169b4b7056dba24f767da022eb01243353e1f4d0af2eb32e3feb331283ceab3e0112b37556749a701d11ada5cbe1b4c829fac46e12612679e47d4a066be939b886f0fdc2b4c5b4dd183ca025c5191ac67d7f992643333504da30e8300a0b40152671", 0xf12}], 0x4)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x10, r0, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x4)
munmap(&(0x7f0000000000/0x3000)=nil, 0x3000)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000300)={0x3, &(0x7f0000000140)=[{0x44}, {0x28}, {0x16}]})
write(r0, &(0x7f00000001c0)="d9537abde93d050cdd16b13f742a", 0xe)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000500)="940105a63feb418581b9c83fc1a1825b0138a85a80b1b0782797888fd1f838a311000000000000b13886ca3849451ae3c3051020741038f5538551f30ce390500e08fecea11ea8fef96e4fc748e93f0b780486aebdbe781e4d8f5eef9187a869a4d3a4cbba982fd825582fe2aa7923ed00f4c8b2ca3ebbc259699a1f132e27acb5d62934e4fd89070000000000000070c1f5a872c88dff7cc53c894303b2a0a85ff3faa800000000009ec7ab3a34c2900000000000008b197b00000000002d7e4a5d76cc3f9cff48d2243e56fa277603c5cc1e047326bcf6b67b75d00bf6ee330b6a80874b70559d9975ebd13da2447a78aa4b00cd0ba1870215607bb912e3d73251835c53d8974b6ca927871c81672a54ec695c5bdeb842836656f917945cc076f87dc714dfe0aa2947252df350707b22884a7730cb42110fbe9ec748188b274387e0b1dbe5695122604819b0b2294b7b20726a5d4fcb44f62d00fabb2f247a166d8d79d05b8cc370f5c11db58aedca632a83acd58f0a3dca58ccb04ace466cda735017196ff346c32717397d6ec60000000000", 0x194, 0x0, 0x0, 0x0)


r0 = syz_open_pts()
close(r0)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r1 = syz_open_pts()
close(r1)
syz_open_pts()
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000080)=0x9)
writev(r1, &(0x7f00000001c0)=[{&(0x7f0000000100)="791c965780508f54dbcb129a9b6934991cba070d2e0c2f19ce57fdf185dff047b76f5bce561cfa080860c2905c9d57ef9df88eecb44cc27bf73a964b794a1daba7ac8742bea32f4d23e71ae0658372c558d41ee20902ae", 0xff81}], 0x1)
writev(r1, &(0x7f0000000040)=[{&(0x7f0000000180)=';', 0x1}], 0x1)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{}, {0x3, 0x0, 0x0, 0x49}, {0x81, 0x0, 0x0, 0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1934, 0x0, 0x94e88e483d20a485)


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc1286944, &(0x7f0000000100))


sysctl$kern(&(0x7f0000000200)={0x0}, 0x2, 0x0, 0x0, 0x0, 0x0)
r0 = socket$inet(0x18, 0x0, 0x102)
r1 = dup(r0)
connect$unix(r1, &(0x7f0000000000)=@abs={0x0, 0x0, 0x0}, 0x8)
ioctl$WSKBDIO_SETBELL(r1, 0x80105703, &(0x7f0000000240)={0x100, 0x80000001, 0x4003, 0x1000006})
ioctl$WSKBDIO_GETDEFAULTKEYREPEAT(0xffffffffffffffff, 0x400c570a, &(0x7f0000000440))
mknod(&(0x7f0000000400)='./file0\x00', 0x2000, 0x287e)
close(0xffffffffffffffff)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd01)
r2 = open(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
utimensat(0xffffffffffffffff, 0x0, &(0x7f0000000140)={{0xfffffffffffffff7, 0xffffffff}, {0x0, 0x2}}, 0x0)
fchmodat(r2, &(0x7f0000000d00)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x297856873e19a725, 0x2)
readv(r2, &(0x7f0000000040)=[{&(0x7f0000002140)=""/4112, 0x1000}, {&(0x7f0000001140)=""/4092, 0x1000}], 0x1000000000000037)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x8000, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
dup(r3)
mknod(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x0)
mknod$loop(&(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x2000, 0x1)
link(&(0x7f0000000940)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000001380)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
link(&(0x7f0000000100)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000bc0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
mknod(0x0, 0x0, 0x205310)
rename(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', &(0x7f0000000480)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')


r0 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000100), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r0, 0x80105727, &(0x7f00000001c0)={&(0x7f0000000000)=[{0x3}], 0x1})


mkdir(&(0x7f0000000300)='./file0\x00', 0x0)
r0 = socket$unix(0x1, 0x1, 0x0)
bind$unix(r0, &(0x7f00000002c0)=@file={0xd570d0466b6018f, './file0/file0\x00'}, 0x10)
rmdir(&(0x7f0000000180)='./file0/../file0\x00')


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{0xc0}, {0x5}, {0x16}]})
write(r0, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xe)


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = getpid()
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x0, r0)
r1 = socket(0x11, 0x3, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
getpeername$unix(r1, 0x0, &(0x7f0000001140))


open(&(0x7f0000000080)='./file0\x00', 0x70e, 0x0)
r0 = open(&(0x7f0000000100)='./file0\x00', 0x0, 0x0)
fcntl$lock(r0, 0x8, &(0x7f0000000280)={0x3, 0x0, 0xfffffffffffffffd, 0x100000001})
flock(r0, 0x2)
r1 = open(&(0x7f0000000400)='./file0\x00', 0x0, 0x0)
fcntl$lock(r1, 0x9, &(0x7f0000000140)={0x1, 0x0, 0x0, 0x269000000, 0xffffffffffffffff})


r0 = syz_open_pts()
ioctl$TIOCSETAW(r0, 0x802c7415, &(0x7f0000000080)={0x0, 0x96e3, 0x0, 0xffffffc1, "48cca0f1f81a6ad70e13a0e265f8000020006100"})
ioctl$TIOCSTAT(r0, 0x20007465, 0x0)


socket(0x11, 0x3, 0x0)
sysctl$net_inet_carp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x3}, 0x4, 0x0, 0x0, &(0x7f00000010c0)="e1000000", 0x4)
sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x17}, 0x4, 0x0, 0x0, 0x0, 0x15)
sysctl$vm_swapencrypt(&(0x7f0000000040)={0x6, 0x1b, 0x3}, 0x3, 0x0, 0x0, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000001700)={0x0, 0x0, 0x0}, 0x0)
ioctl$WSKBDIO_GETDEFAULTBELL(0xffffffffffffffff, 0x40105706, &(0x7f0000000180))
sysctl$kern(&(0x7f0000000040)={0x1, 0x3f}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0xfffffffffffffda3)
setreuid(0xee00, 0x0)
r0 = getuid()
r1 = semget$private(0x0, 0x4000000009, 0x82)
semop(r1, &(0x7f0000000340), 0x0)
semop(r1, &(0x7f0000000140), 0x2aaaaaaaaaaaaddb)
mknod(0x0, 0x100, 0x6da)
r2 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r3=>0xffffffffffffffff, <r4=>0xffffffffffffffff})
r5 = dup2(r4, r3)
shutdown(r3, 0x0)
poll(&(0x7f0000000080)=[{r5, 0xab6cc3d7ffaa0897}], 0x1, 0x0)
poll(&(0x7f0000000000)=[{r3, 0x5}], 0x1, 0x0)
write(r2, 0x0, 0x0)
semctl$SETALL(r1, 0x0, 0x9, &(0x7f0000000040)=[0x7ff, 0x1000])
semop(r1, &(0x7f0000000080), 0x0)
r6 = getuid()
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f0000000240)={{0x213, 0x0, 0x0, r6, 0x0, 0x1, 0x8001}, 0xdce, 0x32f9, 0x100000000})
r7 = getgid()
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f0000000100)={{0x7b, r0, r7, 0x0, r7, 0x88, 0x4}, 0x10001, 0x1, 0x7c})
setreuid(r6, r0)
dup(0xffffffffffffffff)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x40}, {0x6, 0x0, 0x0, 0x85}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0xfffffffffffffe53)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000200)=[{0x44}, {0x1, 0x8, 0x3, 0x1002}, {0x8006, 0x0, 0x8}]})
syz_extract_tcp_res(0x0, 0x8001, 0x0)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x20, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
sysctl$net_mpls(&(0x7f00000001c0)={0x4, 0x21, 0x6}, 0x3, &(0x7f0000000400)="808ec7605085434a074f475a62ac65209731ca92e27695b883813b03a4c656709face8ff8205b74953b9d18f74c3e7c7c9fa1cc688c2c62e2454926a7719e67bc8aa1a8a304128df1a35fd66f36b7b67fcdc94b28e34be7a35c92640786e761f4d3f077cf91ea5bd166a006a24283b5c55598e178a5a0c4d958002943463f9b48a9f8cd5746d347ed2ae5e316b798bcbd816def74fd6c22e85e65a4e37b0031f8a431560bf4c966195e60238b208fd432317354ae56e1f074c5e04ba84cbe20717a94bff6b0d7654428095cee6a0024b59c264ab6e5adb69fa1319099f7281990a85485c10b575bfaebfb929767ae77b3146a2f65e885a666bb0eb5bac14", &(0x7f0000000280)=0xfffffffffffffe34, &(0x7f0000000500)="2878958569ca571885b1812bec200e0bcb9851de29f1a2f9913a83f067b0304584796955b6e398a03b6b5376dbdb682e8e9e1da51792b9c5d24dad8146f7571bdfe3d731ff7c2ddaa319f561c46621651eb8768f6d57b7a0a09caa8ae6afe1b956c7cb3be25f5c1c8d0fbd567911dcff1d72b15958e10ffc757cf49a00432ffc634354dd4f898a1194d2ba59e6e1553c2479056590cd50b5aa84beb9dc47bcedbe8698c932f268deebaf17d245c6ad10d4873d25916e2127eb7ce5134f0623692bb937d3d19d463fba43c45442ca7d860c51d0a603f0c07c3280fbea84a0d73619b1b3fac5", 0xe5)
sysctl$net_inet_ip(&(0x7f0000001640)={0x4, 0x2, 0x2}, 0x4, &(0x7f0000001680), 0x0, 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000140)=[{0x3}, {0x2d}, {0x40e}]})
munmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000)
mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x0)
r1 = openat$zero(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
r2 = openat$diskmap(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$DIOCMAP(r2, 0xc0106477, &(0x7f0000000200)={&(0x7f00000002c0)='./file0\x00', r1, 0x1})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x601, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000002c0)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x3, &(0x7f0000000000)=[{0x6c}, {0x2}, {0x6, 0x0, 0x0, 0x3fe}]})
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x5900)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
select(0x40, &(0x7f0000000140), 0x0, &(0x7f0000000200)={0xffffffffffffffcf}, 0x0)
writev(r0, &(0x7f0000002640)=[{&(0x7f0000000100)="67ad0dad3aa491e36b12738b6cf7", 0xe}], 0x1)
syz_emit_ethernet(0x2a, &(0x7f0000000100)={@random="ed6857225041", @local, [], {@arp={0x806, @ether_ipv4={0x1, 0x800, 0x6, 0x4, 0x0, @local, @multicast1, @remote, @broadcast}}}})
openat$vmm(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
syz_emit_ethernet(0xe, &(0x7f0000000100)=ANY=[])
msgget$private(0x0, 0x280)
shmget$private(0x0, 0x1000, 0x0, &(0x7f0000ffd000/0x1000)=nil)


r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x40)
writev(r0, &(0x7f0000000100)=[{&(0x7f0000000280)='#!', 0x2}], 0x1)
socket(0x18, 0x2, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000140)={0x9, &(0x7f0000000300)=[{0x35, 0x4b}, {0x4}, {0x6, 0x0, 0x0, 0xfffffffe}, {0xff00, 0x1, 0x1}, {0x2, 0x1, 0x80, 0x1ff}, {0x3, 0x7, 0x9, 0xcdf}, {0xc89, 0xff, 0x80, 0x20}, {0xfffb, 0x4, 0x7, 0x4}, {0x4, 0x4a, 0x0, 0x80000001}]})
mknod(&(0x7f0000000000)='./file0\x00', 0x6000, 0xe02)
open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x173)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x406, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r2 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r2, 0x80146940, &(0x7f00000001c0))
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000280)=""/114, 0x72}}, 0x10, 0x0, 0x0)
r3 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$FIONREAD(r3, 0x8040691a, &(0x7f00000001c0))
write(r0, &(0x7f0000000000)="24a608d334f68b0826da3fb9a1e5e89f23bf1364739a6af9efec93275e090909400000000000006745b653695b5e8e0010000000000000413fb5df308cefae50ffca562eb77b6a0a", 0x48)
sendmsg$unix(0xffffffffffffffff, &(0x7f0000000080)={&(0x7f0000000040)=@file={0x170, './file0\x00'}, 0xa, 0x0}, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f0000000000)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe2c63a56077123a276d3ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f00000000c0)=[{0x84}, {0x3d}, {0x812e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000380)=ANY=[])
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


kevent(0xffffffffffffffff, &(0x7f0000000040)=[{}, {}, {{0xffffffffffffff9c}}, {{0xffffffffffffff9c}}, {}], 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0xd01)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})


r0 = socket$inet(0x2, 0x1, 0x0)
getsockopt(r0, 0x0, 0x4, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000340)={'tap', 0x0})
r1 = dup(r0)
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000280)=[{0x3}, {0x1c}, {0x4006}]})
syz_emit_ethernet(0x3a, &(0x7f0000000240)=ANY=[])


fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000000)={0x0, 0x0, 0x7fffffffffffffff})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x1ff})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r1, 0x1000000000029, 0xa, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0206937, &(0x7f00000001c0))


r0 = open(&(0x7f0000000300)='./file0\x00', 0x8, 0x8)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000380)={0x0, &(0x7f0000000340)})
r1 = socket(0x0, 0x5, 0xfd)
sysctl$net_inet_tcp(&(0x7f0000000040)={0x4, 0x2, 0x6, 0x13}, 0x4, 0x0, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000040)={0x6, 0x1b}, 0x3, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, &(0x7f0000000400)="6aab3b9ccfe056e3f892de2b79bfd815ac5d4a52039cae4365b4dbcefeb52c2d74b77c7e70040c16c25bad60f26bcc04e8382081e6325c0808954e236f5c18d91d920b202cb148546ca64a9648b51d580b3b403684e6422d079527d08c5ae6e2582bed495c5648dbf1fa559a0dcdba51db8ce75264a7c3b5ed8b19fcd6d964671a1e9577002c58aa28618968917281542f9e42881f252837711366276edf4c628923da501235abeda701a85efe1804b4c28c17d668da60ed23268461f11b0153183cb0eba520b215f2e2230404095489f3a19be3fe7cbc2a0e76cb3b285bca6ddccec19fe9178eed4059798aa3507b2300de0000000000000000000000000000000000000000000000003142e36cd53ea0e9b9e6cc0e4bec2cb70c0fc194591aa260401005c8433af2418b4e1526b9e1f6f1", 0x0, 0x0, 0x0)
r2 = socket$inet(0x2, 0x2, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(&(0x7f00000003c0)={0x6, 0x1b}, 0x3, 0x0, 0x0, 0x0, 0x0)
r3 = socket(0x2, 0x1, 0x0)
fcntl$setstatus(r3, 0x4, 0x40)
r4 = getpgid(0x0)
fcntl$setown(r3, 0x6, r4)
listen(r1, 0x0)
shutdown(r3, 0x1)
sysctl$kern(&(0x7f0000000040)={0x1, 0x3f}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0xfffffffffffffda3)
r5 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
dup2(r5, r2)
sysctl$kern(&(0x7f00000000c0)={0x1, 0x50}, 0x2, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94", &(0x7f0000000080)=0xe, 0x0, 0x0)
setsockopt$inet_opts(r3, 0x0, 0x0, 0x0, 0xfffffffffffffdb2)
r6 = getpid()
r7 = msgget$private(0x0, 0x580)
msgctl$IPC_SET(r7, 0x1, &(0x7f0000002f80)={{}, 0x0, 0xff, r6, 0x0, 0x7fffffff, 0xa, 0x2000000100000001, 0x7})


sysctl$vfs_fuse(&(0x7f0000000640)={0xa, 0x11}, 0x3, 0x0, 0x0, 0x0, 0x0)


semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0xffffffffffffffff}})
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x1b2}})
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r1, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r1, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r2 = socket(0x800000018, 0x1, 0x0)
ioctl$PCIOCGETROM(0xffffffffffffffff, 0xc0107005, &(0x7f0000000080)={{}, 0x0, &(0x7f0000000380)})
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x800008, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)


open$dir(&(0x7f0000000b80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x200, 0x0)
r0 = open$dir(&(0x7f0000000280)='.\x00', 0x0, 0x0)
symlinkat(&(0x7f0000000300)='./file0\x00', r0, &(0x7f0000000c80)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
symlinkat(&(0x7f0000000dc0)='./file0\x00', r0, &(0x7f0000000ec0)='./file1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
r1 = openat$wsmouse(0xffffffffffffff9c, &(0x7f00000000c0), 0x8981, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r1, 0x80105728, &(0x7f0000000100)={&(0x7f0000000080)=[{0x1}, {}], 0x2})
symlinkat(&(0x7f00000000c0)='./file0\x00', r0, &(0x7f00000001c0)='./file0\x00')
open$dir(&(0x7f0000000040)='./file1\x00', 0x200, 0x0)
lstat(&(0x7f0000000140)='./file1\x00', &(0x7f0000000200))
mkdirat(r0, &(0x7f0000000600)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0)
symlinkat(&(0x7f0000000040)='./file0\x00', r0, &(0x7f00000004c0)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
open(&(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x0, 0x0)
rename(&(0x7f0000000980)='./file1\x00', &(0x7f0000000100)='./file0\x00')
r2 = socket(0x2, 0x1, 0x0)
sendmsg(r2, &(0x7f0000000380)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000180)=ANY=[@ANYBLOB="1000000000"], 0x10}, 0x401)
r3 = socket(0x1, 0x1, 0x0)
close(r3)
r4 = socket(0x11, 0x3, 0x0)
setsockopt$sock_int(r4, 0xffff, 0x40, &(0x7f0000000000), 0x63)
sendto$unix(r4, &(0x7f0000000040)="b100050400000000000008000101000000000000cea1fea7fef96ecfc73fd3357ae27caa0416fa4f376336acf00b7804be781e4991f7c8df5f882b297be1aa5b23ed00f4c8b2ca3ebb4257699a1f132e27acbdd602000d7d026ba8af63ff37282902e4fd007f720fd3873babfbb770a2f5a872c881ff7cc53c8943310b404f36a00f90006ee01bc43eaea8c500000002000000000000020208a371a3f80004000000000000000100000000000000100000", 0xb1, 0x0, 0x0, 0x0)
socket(0x18, 0x2, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105727, &(0x7f0000000040)={&(0x7f0000000000)=[{}, {0x20}], 0x2})
r5 = syz_open_pts()
syz_open_pts()
syz_open_pts()
lseek(r5, 0x0, 0x2)
setsockopt(0xffffffffffffffff, 0x29, 0xe, &(0x7f0000000000)="02000000", 0x4)
mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x881)
open$dir(&(0x7f0000000080)='./bus\x00', 0x0, 0x0)
syz_emit_ethernet(0xe, 0x0)


r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETD(r0, 0x8004741b, &(0x7f0000000100)=0x7)
munmap(&(0x7f0000001000/0x3000)=nil, 0x3000)
semop(0x0, 0x0, 0x0)
shmctl$IPC_STAT(0x0, 0x2, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r2 = shmget$private(0x0, 0x3000, 0x1dd, &(0x7f0000002000/0x3000)=nil)
shmat(r2, &(0x7f0000001000/0x3000)=nil, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r3 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r4 = kqueue()
kevent(r4, &(0x7f0000000300)=[{{r1}, 0xfffffffffffffffb, 0x1, 0x1}, {{}, 0xffffffffffffffff, 0xc, 0x1, 0x7}, {{r0}, 0xfffffffffffffffc, 0x0, 0x2, 0x8, 0x8}, {{r3}, 0xfffffffffffffffa, 0x2, 0x1, 0x0, 0xffffffffffff7fff}, {{r0}, 0xfffffffffffffff9, 0x22, 0x40, 0x1, 0x2}, {{}, 0xfffffffffffffffc, 0x22, 0xfffff, 0x86, 0x10001}, {{r3}, 0xfffffffffffffff9, 0x1, 0x2, 0x0, 0x2}], 0x8, 0x0, 0x8, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
utimensat(0xffffffffffffff9c, &(0x7f0000000100)='./file0\x00', &(0x7f0000000140)={{0x20, 0x1}, {0x7fff, 0x3}}, 0x0)
socket(0x2, 0x0, 0x0)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x9, 0x0)
kevent(0xffffffffffffffff, &(0x7f0000000000)=[{{}, 0x0, 0x0, 0x0, 0x2}], 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
shmctl$IPC_SET(0x0, 0x1, 0xfffffffffffffffe)
setreuid(0xee00, 0x0)
getuid()
setreuid(0xee00, 0x0)
socket(0x0, 0x0, 0x0)
dup(0xffffffffffffffff)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r1, 0x802069c1, &(0x7f00000001c0))
getsockopt$SO_PEERCRED(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000300), 0xfffffffffffffd7a)
semctl$SETALL(0x0, 0x0, 0x9, &(0x7f00000007c0)=[0x8, 0x24, 0x7, 0x0])
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x40000802)
r2 = open(&(0x7f00000002c0)='./file0\x00', 0x0, 0x2)
ioctl$TIOCSDTR(r2, 0x20007479)
setreuid(0xee00, 0x0)
semop(0x0, &(0x7f0000000280)=[{0x4, 0x43, 0x1800}, {0x2, 0xe6}, {0x2, 0x0, 0x3800}, {0x2}, {0x4, 0x9e, 0x1000}, {0x2, 0xfffb, 0x1000}, {0x0, 0x40, 0x1800}, {0x0, 0x6, 0x1000}], 0x8)
semctl$SETALL(0x0, 0x0, 0x9, &(0x7f0000000740)=[0x1000])
semget(0x1, 0x1, 0x230)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000200)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x182}, 0x6, 0x8000000000000000, 0x2f})
r3 = getuid()
setreuid(0xee00, r3)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000180)={0x2, &(0x7f00000000c0)=[{}, {0x5, 0x0, 0x0, 0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x2c}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0xfffffffffffffef1)


r0 = open(&(0x7f00000000c0)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x11, r0, 0x0)
ftruncate(r0, 0x8531)
writev(0xffffffffffffffff, &(0x7f00000026c0)=[{&(0x7f0000000400)="640493d78db6a9c1e335bb42b30c7b40a07b3baad98026cb156727aa65cfb18540954a46faf6cd689a437aff3f4961c4e46a834f6785f138abeced17229a790e349e6bd31df47a250b6311c17b41de694d02002d9c138fb5554471ad71a4e3b0c4a0f71fc4b1f3db02e683a852170340fa26d02f5dcb6c3772415d9b0c54258aba6ad66cd42dfd5163936af944020e200f6dad158fa90dfdd051d151c8c8cb6d711f408511a8c922ff7be9bf88fc6a18b3261c65ab46b32f89b7793b789d533f5dabd554659bcbb9e4082598016c9ffd443ad64a6c1384bebc4f0fa12ebee357f81c1bfbb7ff9c0bb5289f98184e590366ece692aac2a0f3fe55ae6072624ff0892d666934e9e7bb159ba7471e9ca862d48aa90c56e33b972e7ab5f15383b1e0bdc135ef14c4b638c9514366af346df10d2d11e3e82c7f98a731867165c536966e32790a098e86bc8c85d1d890537ee1a3b37a907cb151aa5b72801d9b213f04f59acc40bab4f2dfde876c2bc53ed02cd106d289a59310e0297a072b926369982acb409872a3a4325ed56f1d297bc8bbfb8f0a43f793ee9487a4492016350aa61cca26b86045d14a8f08e6f6d3e3be5520397612b66ebdf990efcf9ed9796836fa253dfa0389406ae25edb31abf6797596cf9b4a943972a4a19c43db1926c18bf15fc526127d1b04211fb4f4fe4c34dba511e8801a10008e54d343386c0c096641681899e65d2afea539fec10a2db4f07a06c7745c1005d0c2b1f020bd80e052df5a4969a40602d7b4350068968bae7ed03d05c9f0e7dd8940d1e37cfbf3370f5953261615197d350c60c2e3bdc186eff30d0700e608a4e08b2cac91f42275e3e6378a0747267335e017b5342a1662df7f3144a5c0e08008460631d2fb76c410c11c4dcc7f73fcab23a4794775f4284e02ad1ba71d64db4f1f4ced92b7a389fd596763283771b9faf89865c462f59e57a81cf8c3cbeffb268f00b6589ab79483f517583bc3a949c0df139721b6dcb9635dca559ac670c1b3ac3ffae886d18134df6d3b7078928ad5370c9687de2846d1f89f7455cf1f7bec56f3717cbdcab9a5fbe597f929e432ff093d92cb35d625bc8c5dcdc4df998db4b51f74775e5d6d119c505a2d0f27c9ead9e84af18c5d7e258cb6a4b57d28c5be27c3d72e277ae3a79bec39bdc88df392b2df6afcca55f79efb3fe6d0d8b50d7c8bbbc134450db20f1d5a773ce9cdc3b97b3274cb2e9c85496e9043e1eb83bda1b0960808b7dbf61fa0b420596976194a598a6ce1066867d13ed30035f8ff0ba3dcaa15df0cab8b96807cb82435a42067d4f1257de536842db0d3f7dfda891c146d79b600e6a2f994f2755cb278becfdaaefb2c7b976be36689c7a0feced48a723be73f29851f75e42e9d62c83d6aa220891c5c24634e8c7cc3eab033046727127a802dacbde8cf629c1f57d59ba0690af43ce944607c1fd9df72f74d67e7ddc2efd8dc6c459d0d1fe2ca57d14e20046f139050206dd8d203e0389aef6682cc6b861cc364184ee9708452dcb732992ce6dedbb8d57b5c5689b9836c54cdc91b4766f618d608d4bb380614d8cc2e03b3b3b5897ccb61f9fe2d16e5ced34cee9e856a6c52324c0eef64a4b7f9e8e7ed5a71d7b1fe9f94665ac75da67d114047ff5a1c3d0668d43d78c12565ea154f763418049e8dd3a1929b7fa4877c9e2cd984ab94818219a05b196b643adb3f064dbffd2b22ade017488178c5361a1c93f9c615e0e0cd28f25b7ca582d6942071cb7fae17b52eb41ead6e78914945802c19bac16c76ae14c7ed4be6e42713e8a4bd6220aadf458fa15b40777f94e223c596c7f80bab9584fcf4ff14f138adbbf7b1a7bdd686fa9249fe006aea38651e410fd4b1af0d79d7f1ee0cb2711ca81382f15804771da4a18d5f20e10ff9a7abd6ae8583d94f58769f3401526e517d963800c92485f9c24eac2d914895d4d9b866bbb769d22a00db29ce0b9a7d7112defb15d9776db55edf8fca337b1a496c7710acab8135aee0261a780ef6b39664469e33dab2398639d1becbdc74000b36c2ca5df2c0d3c5d3d3e054a2b8d91bc4656cf09300dd084cb0b625a587fba81cc6c2c3ef6f93342b65bc0e68222de6908492ac431f9f4dc1d3915a2cba79820c8c1f7c6e5c582d953b60a943eef44a6e7b244c808fb292f3944a4b1afbbadb06ed72c1d2cf9a60e02b319af032eddb475ae1947175f437262cefe05a89dc92367c8f8223e3a415b080b2bee22f084d00a289e42f5dcd0c31dc257d6bd09d214fad7aaa03d285a4ca618a5cc2bc0167ce424c40b879bfc294b9f2be0ee1c4669fe57d15c3b8fd626507ebb94d7313eda527d86a2bcaf9234a6eb4fcd2ecd218607961c7816094311a762d783ab7cef7009f103d938a5dee845b827001c87920ea3110b97b40a8525c41a57a03e389d9d864c57e10a849509135cdde81b89da8ee10540b76fe6c303a98bfa68a493ff59104b41c34c62092d3c0cc16d5c5c9abf7d0cc9206605ca6b69511091b512063985b03549573fbe60036cdfb28e77670e99b55a8f8151035ac93ef64b77f36951b0d3a31befef14741f874b313b66908f8da53a8a95255c16019876c85dd6070b2a8470f303b98d3c9ce2d203774794ecd2dbc43a69cd37c21f9c971634ff7b00af46adccaaeb1ca346bbdcad44151e38a94d91339c425554791adf2d3ff197221979625d2993ef7f4af06ec2438ab780ce737ac1bdbd873fa3b5cc0af43097b2be36bb9cbf87d39d3a7d54d5a49b176a3d74d95c06cd9b665248f84c27019f7b62232d9de01396aa0096f36c399b762913e207de7e3d24a2bbb04d879fe29b087ea262e82e4b3ca0fca62f222a592ab6ca1b1609e6a7500b8ed38db0d895c2df29604a64540e796787461ed7d1c5c562662b8f5146839cfbae18a6fb302033ad6558ce8a9d61d5de662b995ecb228535cddd02aa051321dadfd06dcd6409cf98d8a8697c7499f1695f173b427ff5f6cfdd224b66b89682d0e2978710e2bbfe7c9f2793cd2592ec7106c44e46c1d2bfe9d7cb53cac640f92f66506aefcc11c983e6c284a892dfc4b813771087baf9150eeb019ba0877afef77a66ee91b2c85ab1b95cc670ae9e80a4f20b8c8914c655828a68d6e8b509d479b5d04980a5bb17fb9ef17060f802f6e6f57e29d6587d6b8dc3438f592db639f718cc3bdaad6865d8a6aa94c47e1061cb8dfb8d7c54c168a29e8b1a78e1716ce413d429daaf09c924a7cde44eafc58fa5b3a5e3aa387a9465f024f7fe6ed9343d81dee65d106f635bbece1c99d5eb8ca0487c00c2851aaf24b2b6003e7150758f5a50943de2ba7b95710fa05f1c1e305dd7a14dba19feb94c9591d8cf724ef55aca7fb8e054763f7c80027b929666f6864db25a059859ca8831f9b7251e38eda5b00d0fc64a3b3460bd7ad733b9eac508a6a191a6465ca14729214d29cdfef5c6409a3f7e5db2044f836c049f5a14a78bea5c7a55e957a53d8d7d97203de65090319911c1788fc704d9382571d3d1bd2b35927d8d95b3f3b14930350ca34d577ff1d4ab69c7ef9f74f73590b8fd0d3574e7779e7f6564f9245c117c4272054015715a0671bcec7416d95a17da00b50e976168b9de75b673f6998119eb1c3b2bd1eebbf21aabc7e606991dc2e802058344d4854b1fe88688873db69c8ac70a9e4850960390a510231dc7159e3e89be0162258982be870d6135b0870986f66c19cf315552165fdccdd2acdff62cddeba67ca0e9578ab629d895a81f63c2262362a49ef4bd8a25dbf73fd100844496f40753d1496bdae8cf60f23db024ec56dbb594e9047ef5b005f579ff829dc1c3cf6844dd8bdcaf644481d171cec2bd25dce58a23617d5d11d7d44465214accb32a5767548fdfe3a428699ec03d02fbc2ccf1237ba07249af6f37ea83ddd8c7ec77f56ae7025c5662ecee8a8682d61823ec04bfebd6195147b016a28112821ad0f2aa32110dd31b38027f0e7fa042cce3e52ec467aaf95f998db202f819f201ee1322215018824a880755b94a2876e09e4c0cac01005ff8885e5f2f21c28b1aab38c62c33de0268521db2c198d19e7fafe69215465f6421b8503218f394d5a94c8601dd6514ff8a80f442ce07a4de65060229285b873667fa19859753c4b949ada2d3ab20afb732a4d4f0a9e5e13ef5a50c8361a465874e956464e201de1f30fa97398d3636ce88e479428b0bd8521010b92a22b4866c311593c101e3ed6169242c63334c7d6715a6dc50063e1c5658f590d0177464461a2ed8892719a770bcd687c597d51d46b89640b6610bc107a6b6d23e46052680aa18673", 0xc01}], 0x1)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x4)
munmap(&(0x7f0000000000/0x3000)=nil, 0x3000)


munmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000)
munlock(&(0x7f0000fff000/0x1000)=nil, 0x1000)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x2, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000200)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000140)={0x3, &(0x7f0000000100)=[{0xc}, {0x35}, {0x6, 0x0, 0x0, 0xfffffffe}]})
writev(r0, &(0x7f0000000080)=[{&(0x7f00000000c0)="d3d9bc6f7a689f455f7bc4e71ba7", 0xe}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x2, 0x0)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504000000000000e30b060000001a5113fecea10500fef96ecfff0f00007a89583535", 0x25, 0x0, 0x0, 0x0)
socket$inet6(0x18, 0x2, 0x0)
setsockopt(0xffffffffffffffff, 0x1000000029, 0x3b, &(0x7f0000000000), 0x0)
ioctl$VMM_IOC_READREGS(0xffffffffffffffff, 0xc050756a, &(0x7f0000000740))
openat$speaker(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, &(0x7f0000000500), &(0x7f0000000540)=0xfffffffffffffed5)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f00000000c0)={0x0, 0x0, 0x4, 0x0, "65dfdb7132fce0b568c98b35202405275b738718", 0xfffffffe})
r1 = open(&(0x7f0000001180)='./file1\x00', 0x615, 0x0)
writev(r1, &(0x7f0000001480)=[{&(0x7f0000000100)="cc", 0x1}], 0x1)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x10, r1, 0x0)
sysctl$vm_swapencrypt(&(0x7f0000000000), 0x3, 0x0, 0x0, &(0x7f0000001380)='\x00\x00\x00\x00', 0x4)
writev(0xffffffffffffffff, &(0x7f00000001c0)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0", 0x1f}], 0x1)
readv(0xffffffffffffffff, &(0x7f0000000400)=[{&(0x7f00000009c0)=""/4109, 0x100d}], 0x1)
readv(0xffffffffffffffff, &(0x7f0000000040), 0x0)
setreuid(0xee00, 0x0)
open$dir(0x0, 0x0, 0x0)
getuid()
faccessat(0xffffffffffffffff, &(0x7f0000000000)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x6, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000040)={0x9, &(0x7f00000000c0)=[{}, {}, {}]})


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000100), 0x2, 0x0)
writev(r0, &(0x7f0000001340)=[{&(0x7f0000000140)="be294b576eea0ab995d4e7e0ceeb3ecdafc4413d1492733049c1e795390f8f4027e2895d13e4d7d899f3d7dd889aef74b56ccee2ea5e47615c510f2f23c2f486c75e3f51580c2f7991b83f99b6be4edfabbabf64f8d8c967e560b7e5e2e5f110f4479d6fda2e3bd8a14407722d2ee0a0ff69daf1f760ebd1b7fa02fe91b46da21aa586f1e475dc4239abcf95b80a8c7780e41bc6505e1f3af24b23526f66156105cc11281073f7df36e33e7795866305983146325a9a5f5cd924a0463e00119d1be97cb9ed0da3c256016b57599c0b4eb986d9b5c94adf1c147b4f7c6eee626af824f812d932e6f7802b0d32e9c528526c6f1daca88e205d5cf8edfb054e95d2ce6717a479c69a8877547cd2620754f64cc2e4290f4b5776195c5cdbe93f55e1ab5b51507905398ec6564899b77e74826a53bc760a3e0193c9acb04b4873a4dc9af19aa85a4b31a624a31cf301c48048b90ed91eb94c952d9f313df7df7d7b63a3dd111c115488ddfd12f0efd67f809b61e196471d8f06dbad317bcc80758f1a56ddb3018d076fa0c69e8dd195d0a94793af5b7f4d6e", 0x196}], 0x1)
execve(0x0, 0x0, 0x0)


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000100)=[{}, {}, {0x6}]})
execve(0x0, &(0x7f00000002c0)=[&(0x7f0000000100)='tap'], 0x0)
r0 = socket(0x18, 0x3, 0x0)
ioctl$FIONREAD(r0, 0xc028698a, &(0x7f0000000100))


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000380), 0x0, 0x0)
r1 = dup(r0)
ioctl$BIOCSBLEN(r1, 0xc0044266, &(0x7f0000000100))
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSRSIG(0xffffffffffffffff, 0x80044272, 0x0)
syz_emit_ethernet(0x2e, &(0x7f0000000200)=ANY=[])
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)={0x3, 0x7fffffff})
r2 = kqueue()
kevent(r2, &(0x7f0000000040), 0x30, 0x0, 0x57f, 0x0)
kevent(r2, 0x0, 0x0, 0x0, 0x2, 0x0)
syz_emit_ethernet(0x4e, &(0x7f0000000080)=ANY=[])


r0 = socket$inet(0x2, 0x1, 0x0)
setsockopt$sock_timeval(r0, 0xffff, 0x1006, &(0x7f0000000140)={0x0, 0x6}, 0x10)
sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504600000000000000007000000331c13fecea10500fef9ed06c72fd3357ae320b37b673039d2d236073705ae04be38164991f7accf5f882b297be1aad223", 0x41, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
getsockopt$sock_timeval(r0, 0xffff, 0x1006, &(0x7f0000000000), &(0x7f0000000040)=0x10)


socket$inet(0x1e, 0x3, 0x0)
setreuid(0xee00, 0x0)
r0 = getuid()
setreuid(0x0, r0)
r1 = socket$inet6(0x18, 0x2, 0x0)
setsockopt$inet6_MRT6_ADD_MFC(r1, 0x29, 0x23, 0x0, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000280)={'tap', 0x0})
sysctl$net_inet_carp(&(0x7f0000000000), 0x8, &(0x7f0000000040), 0x0, 0x0, 0x0)
ioctl$BIOCSETF(r2, 0x80104267, 0x0)
syz_emit_ethernet(0x26, 0x0)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
r3 = kqueue()
kevent(r3, &(0x7f0000000080)=[{{}, 0x0, 0x51}], 0x0, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x1, 0x0, 0x0, 0x0)
openat$wsmuxmouse(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
accept(0xffffffffffffffff, 0x0, &(0x7f0000000180))
socket(0x18, 0x1, 0x0)
sysctl$net_mpls(&(0x7f00000000c0)={0x4, 0x22}, 0x3, &(0x7f0000000100), 0x0, 0x0, 0x0)
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f0000000080)={0x10, 0x0, [{&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000ffa000/0x4000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000da3000/0x2000)=nil}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f00007fa000/0x1000)=nil, &(0x7f0000ffd000/0x1000)=nil}, {&(0x7f0000ffb000/0x4000)=nil, &(0x7f0000b71000/0x4000)=nil}, {&(0x7f0000ffe000/0x2000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000a0e000/0x2000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f0000ffa000/0x3000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000727000/0x1000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000400000/0xc00000)=nil, &(0x7f00008aa000/0x4000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ff9000/0x1000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f00004db000/0x1000)=nil, 0x40000000102}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffa000/0x2000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000542000/0x1000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ffa000/0x2000)=nil}], './file0\x00'})
r4 = socket(0x1, 0x2, 0x0)
r5 = socket(0x18, 0x1, 0x0)
setsockopt$sock_int(r5, 0xffff, 0x1000, &(0x7f0000000000), 0x4)
ioctl$FIONREAD(r4, 0xc0106924, &(0x7f00000001c0))


connect$unix(0xffffffffffffffff, 0x0, 0x33)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
openat$null(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
mprotect(&(0x7f0000ffc000/0x4000)=nil, 0x4000, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000140)=[{0x4c}, {0x80}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000240)=ANY=[])


syz_open_pts()
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000380)=[{0x4c}, {0x14}, {0x6}]})
syz_emit_ethernet(0xe, &(0x7f00000000c0)=ANY=[])


socket(0x800000018, 0x3, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
sysctl$vm_swapencrypt(0x0, 0x0, &(0x7f0000000040), 0x0, 0x0, 0x0)
openat$vmm(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
openat$null(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
rename(&(0x7f0000000080)='./file0\x00', &(0x7f00000000c0)='./file0\x00')
flock(0xffffffffffffffff, 0x0)
syz_open_pts()
socket(0x0, 0x0, 0x0)
open(0x0, 0x800, 0x6e)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
open(&(0x7f0000000080)='./file1\x00', 0x200, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000340)={0x3, &(0x7f0000000400)=[{0x45}, {0x45}, {0x16}]})
write(r0, &(0x7f0000000140)="7f23a3c23cce2575e1dd92c25678", 0xe)


syz_emit_ethernet(0x3e, &(0x7f0000000140)=ANY=[@ANYBLOB="ffffffffffffffffffffffff86dd6060626000082c00fe830e000000000000"])
semop(0x0, &(0x7f00000000c0)=[{}, {0x0, 0x2ff}], 0x2)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x1, &(0x7f0000000000)=[{0x0, 0x6, 0xc0}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
clock_settime(0x100000000000000, &(0x7f0000000000))
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
r0 = socket(0x0, 0x0, 0x0)
setrlimit(0x0, &(0x7f00000000c0))
syz_emit_ethernet(0x22, &(0x7f0000000080)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @broadcast}}}}})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000080)={0x1, &(0x7f0000000280)=[{}]})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000000029, 0xb, &(0x7f0000000080), 0x0)
geteuid()
getsockopt$SO_PEERCRED(r1, 0xffff, 0x1022, 0x0, 0x0)
getsockopt$SO_PEERCRED(r0, 0xffff, 0x1022, &(0x7f0000000180), 0xc)
syz_emit_ethernet(0x32, &(0x7f0000000040)=ANY=[@ANYBLOB="ffffffffffff00100000000088a8300081041b00e2769fe4fd060aa80006000000000000e000000100988dfcfdc8e12eb300970fee653b7e5cb6521d1fbad834"])


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xb, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
r1 = socket(0x1, 0x1, 0x0)
dup2(r0, r1)
setsockopt(r1, 0x1000000000029, 0x9, 0x0, 0x0)


writev(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f0000000200)}], 0x1)
r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$PCIOCGETROM(r0, 0xc0107005, &(0x7f0000000100)={{}, 0x0, 0x0})


pipe(&(0x7f0000000100)={<r0=>0xffffffffffffffff})
pipe(&(0x7f00000001c0))
close(r0)
pipe(&(0x7f0000000180)={<r1=>0xffffffffffffffff, <r2=>0xffffffffffffffff})
close(r1)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000000c0)={0x7, &(0x7f0000000200)=[{}, {}, {}, {}, {}, {0x0, 0x0, 0xe3}, {0x0, 0x0, 0x8}]})
r3 = dup(r2)
poll(&(0x7f0000000080)=[{r3, 0x45}], 0x57, 0x0)


setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
socket$inet6(0x18, 0x0, 0x0)
ioctl$WSMUXIO_REMOVE_DEVICE(0xffffffffffffffff, 0x80085762, &(0x7f0000000040)={0x1})
r0 = socket(0x18, 0x2, 0x6)
setsockopt(0xffffffffffffffff, 0x29, 0x0, &(0x7f0000000040), 0x4)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000000)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmsg$unix(r1, &(0x7f0000001500)={0x0, 0x0, &(0x7f00000005c0)=[{0x0}, {&(0x7f00000000c0)="8e383bb7c060e5ec23f0317cf1813d1e5dcff503facffd99375093e1bab70b45d397c74d04829e7c37fdcda2ee58bc72764b99bd8719f6ec87e944bfc7c1f53d8a1160f80eeefb997ad54bbf860f96a36221588ac5b2dd7f334d531bc7e327dd8ccfd5c3bb8218963b165814ea70030c52faa48fd0ed1d5386e18918d67cfac5d5c35ad3dd9b8f0c2c18e7275ef89305091ecc", 0x93}, {&(0x7f00000002c0)="81f54f5d92a841c4b23b249e476278b3983ed5fdfda8b8d7e327de4468000030759166ee25", 0x25}], 0x3, &(0x7f0000001400)=ANY=[@ANYBLOB="10000000ffff000001"], 0x10}, 0x0)
r2 = socket$unix(0x1, 0x5, 0x0)
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000000)={0x1, &(0x7f00000000c0)=[{}]})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
syz_emit_ethernet(0x3e, 0x0)
bind$unix(r2, &(0x7f0000000200)=@file={0xd570d0466b6018f, './file0\x00'}, 0xa)
listen(r2, 0x0)
socket$unix(0x1, 0x5, 0x0)
ioctl$SPKRTONE(0xffffffffffffffff, 0x80085301, 0x0)
openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
ioctl$WSMOUSEIO_SRES(0xffffffffffffffff, 0x80045721, 0x0)
getsockname$inet(0xffffffffffffffff, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
close(r0)
r4 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r4, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
connect$unix(0xffffffffffffffff, &(0x7f0000000000)=@abs={0x1, 0x0, 0x2}, 0x8)


setreuid(0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000100)=[{0x40}, {0x3c, 0x4}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f00000001c0)=ANY=[])
kevent(0xffffffffffffffff, &(0x7f0000000000), 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
kqueue()
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
socketpair(0x0, 0x0, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
mknod(&(0x7f0000000080)='./bus\x00', 0x2000, 0x6d4)
mknod(&(0x7f0000000200)='./bus/file0\x00', 0xc000, 0x81)
ktrace(&(0x7f0000000280)='./bus\x00', 0x0, 0x40000200, 0xffffffffffffffff)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCPROMISC(r0, 0x20004269)
ioctl$BIOCPROMISC(r0, 0x20004269)


open$dir(0x0, 0x0, 0x0)
preadv(0xffffffffffffffff, 0x0, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
setrlimit(0x0, &(0x7f0000000180)={0x47})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f0000000040)={0x0, 0x0, 0x0, 0x1})
semctl$SETALL(0x0, 0x0, 0x9, &(0x7f0000000040)=[0x7ff])
ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000080)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
setsockopt(r0, 0x1000000029, 0xc, &(0x7f0000000040)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)


setreuid(0xee00, 0x0)
r0 = getuid()
semctl$SETALL(0x0, 0x0, 0x9, 0x0)
semop(0x0, 0x0, 0x0)
getuid()
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
getgid()
setreuid(0x0, r0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f00000000c0)=[{}, {0x0, 0x0, 0x40}, {0x6, 0x0, 0x0, 0x85}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x42}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1918, 0x0, 0xfffffffffffffe53)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000080)=[{0x28}, {0x5c}, {0x8106}]})
r1 = openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$WSMUXIO_ADD_DEVICE(r1, 0x80085761, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
syz_emit_ethernet(0x0, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$hw(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000180)=[{0x4}, {0x1d}, {0x8306}]})
syz_emit_ethernet(0x2e, &(0x7f0000000280)=ANY=[])


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x10000})
ioctl$BIOCSETIF(0xffffffffffffff9c, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r0 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0206923, &(0x7f00000001c0))
r1 = socket(0x2, 0x2, 0x0)
r2 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
r3 = dup2(r2, r2)
ioctl$WSMUXIO_INJECTEVENT(r3, 0x80185760, 0x0)
mkdirat(r3, &(0x7f0000000080)='./file0\x00', 0x1)
ioctl$FIONREAD(r1, 0x80206916, &(0x7f00000001c0))
r4 = openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x1, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(r4, 0x80105728, &(0x7f00000000c0)={&(0x7f0000000400)=[{}, {0x4}], 0x2})
r5 = syz_open_pts()
close(r5)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
writev(0xffffffffffffffff, &(0x7f0000001480)=[{&(0x7f0000000100)="cc60d3d79a1a7122a5fb9de9ea6ca0b30fb2942ef7652736f10f86d45ae419b2ecf7af93d33b3de1f2c56c0d93da7484095dd06f1eaec7d8df99d6c28b10f6891e47d6c3bba690a611889032ac7b3581d7c92d1c546e59764f069048316871794f0615dd4d8bb1057a61fb177be649004fb56a7d46c856a20d73f050bf29d58b803a676cc3761e8a47857f51d90a4465f90800ab2829d78ea2571900", 0x9c}, {&(0x7f0000001280)="00000001", 0x4}, {&(0x7f00000012c0)="5f6a8de84b4c523a583f91557c748a02cda4cedf1396073843ec5cbabaadcec85d62a8a897a78307f3d2c30eea6356105ec8aaba86930f1aed0b3d111d0000e173ccdfc68b6a39a4282c0061bfc35c0dbc2970890f50d34e85ed34183c2186", 0x5f}, {&(0x7f00000014c0)="2a5f4cd9b73c31d629e8d68e605e5940744ef138960b671d42c56f79fcb70549247e5504e02f85a6099eff9291731e94399a7e966e783d4073ecd5dc8e540f32190bb47050aee3907495ecf7708d1c295a0836f79ba03ea13db12836c2441989726ffbf7fd1da55bfe2caaf081a1ef55599935c0e60cb0866ee48d420b77a6e269bc30b2650349e16792252c6be8bcc6e9ce2b941299ab505e4779fa1960bb7cf924dcbc53c82e76bcd80731a694d12e8a139d8ecef6f5560939054b7842d25cd7396377f39bcfe2a2383feea17b87393cd892b90742631718b1877d8d83d5f66587e3e5b1e129433ead750143a4c51aa46e78e3b1a54a4634eea2846511719b1637b19ea8c96a52387dc6330aa00b5680142650e8dab5eb6b83ff7d0bbf1293338a8d3e8a6dcd7ed4916279eac230dda46e6fcdebe8a4c12d598883d9392da05791e153d905ce1930aebfc5dfc0fc22a88777c9fbc24c0b021189c3503466bf850f59e6649dd0b40d935ba155a9d7e065df6d90a500be9d7e1e77607d495898a8d6c9c48dda88533e75e760dceae91d670f97ebbe68b845c72eb698a9e0389b15cfe768cd4e524dbe939bc2d8363ae3b71a454a0a0378cd1f36565ab9d1b92263688195df65151ee9b8158c7a5280019a38f00ea05142b3cc832ece46e326e36a55d7a30f866ca97da61a3877612f0d9f23c052edf60a430d3a9acbae3d9f14f22f38a1eeac7df37ae17748a960b9e0d265bf6cdec73bd2a7b5f25035d845d936936cbfe6f013f8d7c73eba2bd9876ff6db3224e50e75c051979f4cdc41d28ea54e28f560fb0291cd6b6ba527e0f358ffa46b988f0bdbf801063d2024380071709ac00ed463e08fd1718a857b567d8b3eda143915e943d9530d25ed15743e117be375dc08e241328a53fa05b58c7c72a35d471a72706afce82b6c57eef81444269e06338bfd0af6f6ef6479dcc26aab0b10c7e58572aa507a69831d63c78c947cecda2c57bb8ae6b2ad7862d160b423de941be69928467db10ee4817536196ad0c5cc02a74ba1a1fb467e472f025f200846112b6b3efd298284d8c0cc498fb9203db18e48e34c137d1285120d809a774d56a62b3dbe8f202cb9cf18c33099f5b9651fc7ae41de53842f327fd40bcfaa601a791da1103351a64cc9815ff1f32cde6fbfe4c92f55a9aff41c055d4edce9c656ecd1becb9035bb8bd46cf47bca0dcb1848da94d05d1475c83a48c02f8f808597eaa9e88a4e4b12d0ef95458eeab115cb189fa7e368186bb68610af4651e27feab061c4ada46e8c12d6d33fe32cd40485b02120418a9aaba8f04c17ea1abdcb9e6801f5d8090c0780b3b5ae4382efbb64f62c825527b7e3d60ad9c73ba7f174ea7c7f2d155808052a0ef6ab2af85cf9a758a8c1227c85f2986fc06c5f54807968b18b6b5f9168d0b2de2728689d75f0efaedf79bd8bbbbc1d46b0f6072d46d46687bc92c0b16c4ad36c3fe4c7a2fde0cfec859052dd78d841464a6b4432342ea973bf18f1f5abd7b2fe7962faef39ff38bd88a40dbab0f8c08541e38efe924f9ec1addbd47362e349bfca42fd62cf18fef8db7d3cbf0b1733d37dcdae5b9c738b8426a1cfa205c9671870210508c614f256d199fb822613518b1a6fccfee08c48f0feae1ca4baaf0a02635282d4f630a8df115dc73e72d9f7b8feb4333b2c796f1d3f2cfb398ba1e9c81584185b8b578bac3c64d667da7d91062f0c2ccec0c9d09e0c15c62e7bc509c3204d054c22d4eac685626e48e25cff2fc382279d9cb941c2ca182b1f65b05ff05db880a37b1e7f9b3d8975558858352bbbea9213a885b7d43451230e0624403baa77839baa33ae92de771ca76319c2353e9f98ea8191fbb686aed6d08e87bcc2bb8084ae02fafbac1a0bba93f0f155fa2d7bc21bf77f116429c6a1373c34d080518b73481fcf012c0a9127e8f174695ccd4add75b026bfa935990d5cebc4e74b97ae67a414029252336880232635fce7ed7bf0b069e08e10f7e1cc4d2973dcd2ea0b63f9dc4f4c2db92e03c553afcb1060b12f6b9b4d1d799edceefdfafdae63ad797e400645c149b20f8a10af54db3289441499e122413495c7b32179ab6c274bbdf6dde48ce26f46f07ede9a314c1a73669ee8cb0d854c8a3206dcd4f532d36fa7affca1226962e20ca2c6ca0da1ab0848d23d6f198681911592815c080cead9fe6c81cf0d7ce3578978dbf1dc2f1902e51f740f95b02ebff4cf25ac8d28b8e16998f5e329e9a377a82b5bc227f77c2f1ad505286aac8618799c2363a2d07d229519370be62ef0dde6525df45a7b807759b9ba1c8557bdbecb429432c4e1a84094edda567f1245ba887686342d0a31b7dbe09bd2be75516b255d2bfad9337649e86a29b0a19e16b4059c7c45e9f81db6780af6487a11f9088ea265a99d6e95535e14fe839945f8f7da9bf9142dd12c305bd41bb392cae8eb81b28fda176d4b538f4ddaaed47913cd9149d934ca36879718bbd76a2d7ce11e6294398ea433af6cf53b951974ec96a9527178b6cbad3088a2e2dc75113fa88ede462e68b4d6b63020a45e94fbc6c3e6677d6cffee0e3bf606cd2d4b9fac89f91db8f3a1fb9f506708314249fa5c36912e3cb281acbdec3b080735ae24ebb4bca3c7900c21175435afbe5024a706e90f8ecf257c99cd8b67b5a9c2bdc2bb624201f55882349526f8faf463eecb183635db72a6aef5fa2048d97e6f6c513598f49158050df1efc6b13b8ae396cd6a905c26b94d1d50d361f10c0362a8c206c7dd553dd8b116694aa82ac029c64aa71b8a307793da12f93ce030d3c42443c37b91043687befb7968da97ffe91d45e4fd506ba4d9c5d7fe5ac7433fb6bb3ce471f59ade734d109d2093fa119827b65a360f2128e7e85ab494609b60d6e236ed8a72984f6c75652f5baa07e2e921365af2b819eef58343e65ffb45ba8580d62f5b8a9988f7176c1559f8ede3b1b92e0ff27978fc5225ed1512b605f1fd4fce46e768970b11a7b4802c93eb05a8571887cdc15f69929eadcd1f9d08ed2d6aab2997ffa2102c2d8983a78ad43779d03aa612ecbbdde634b14e980b176f04f99efad82a04001f34d6addb89e0ce629856f5ad401fed1a2c046e1fe18741b24d4253830af94a1defeecdf6f70b430e48d7b2e4ae2fb331322d96e1a361e4dcae1d0865e7ccc4aa58bcbb3ad1ce0b294437887e03088a6bb4c92c3044bb33d2a893975023ad979fb2f84d4842326cf058595398779116245c452e54989df0591238af63c5b187d18457f008f2759ae470282ee4640e92639a46915fb67f22967beb1f46736aa9c90df08f39ee481f6859f9eafdecd473bdc24ef3ad71b4c54dde360f2d550db18af7589c8107f29b0a713b65f039da10c2dc55e408ce75c77aba97c116ab078ed1467464fe4041668228316f0fff7c0e0f1a3cc47aae570182197cc3a030a4af7fe2d401b5a13d59b8fe55d48b0667b782cbf1c2e9e491167d87830bb25008aff93c4459a3ce9fd8655a542c6311d91ec6b6bd7935aba1cd01d10439f5e5a3883566c8538edb97c5d2a7d5533d415973729f52dc03134f3d777b7ad07c0f5b0d985ca48fde6cce9ec99f1223f476dcfbb5ef865a3f54459415b25e2031eeb469c83ac68fd77e59c6b6a4b9543a943c4461e47e94d038c63abf2734a3c0e99b95505e13af6cf7b66840dc60e96fb218436ea00b4a577c2effdba43e6adf97cb47c0ce606e87a7834dec04396c1e4f7df59ae5acedfd1d68c87e405fc5d788884686270cb08f0fb15fe8b11589792f9afc11152cd45f43fac6", 0xa8e}], 0x4)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x2, 0x11, 0xffffffffffffffff, 0x0)
r6 = geteuid()
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040))
fchown(0xffffffffffffffff, r6, 0x0)
sysctl$net_inet_etherip(&(0x7f0000000000)={0x4, 0x2, 0x61, 0x3}, 0x4, &(0x7f00000011c0), 0x0, 0x0, 0x0)
mkdir(0x0, 0x0)
socket(0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0206921, 0x0)
socket$inet(0x2, 0x2, 0x0)


setreuid(0xee00, 0x0)
r0 = open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
r1 = getuid()
fchown(r0, r1, 0xffffffffffffffff)
r2 = getuid()
setreuid(0xee00, r2)
open(&(0x7f00000002c0)='./file0\x00', 0x3f54c03cb53f6294, 0x0)
execve(&(0x7f00000002c0)='./file0\x00', 0x0, 0x0)


sysctl$net_inet_tcp(&(0x7f0000000040), 0x4, 0x0, 0x0, 0x0, 0x0)
r0 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r0, 0x0, 0x20, &(0x7f0000000140)="caddf7f2", 0x4)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f00000006c0)={0x0, &(0x7f0000000640)})
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000300)={0x2, &(0x7f00000002c0)=[{0x0, 0x4, 0x41, 0x3ff}, {0x3366, 0x0, 0x85, 0xa}]})
ioctl$BIOCSETWF(r1, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000700)=[{0x4, 0x0, 0x20, 0x57cb}, {0x3, 0xfe}, {0x6, 0x40, 0x2, 0xfffffffe}]})
write(r1, &(0x7f0000000740)="76e5dead6f01f8607dd154ab5b0e83bd0f1847e2df004b130821000000630fb49c097a5e1161dcb79d2875e718008521a4a826f8b07da3a0c664e0af29a67d70e14a47ff6e05ccd1f7d32fbc127ca73ce233404072674eab226837f4b01d39751b9f5e8a5b5d6dca454a73500622b962eb56f63c35a72f21f7162ccd0417c5c82e1c44c9506fad549535cab88725c92e4ea9cdbba98eeadd9a6ea51ee0d7544694e864e4372e9f53cd8fcc652d228e63c215dc9abe8c7532f70c40f9d3f39c12660b", 0xcb)


ioctl$WSMUXIO_INJECTEVENT(0xffffffffffffffff, 0x80185760, &(0x7f0000000000)={0x0, 0x0, {0x0, 0x10000000000001}})
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x0, 0x9f9d})
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x18, 0x1, 0x0)
close(r0)
r1 = socket(0x18, 0x2, 0x0)
setsockopt(r1, 0x1000000029, 0x2e, &(0x7f0000000000)="ebffcbff13b9fd812eaa4e713048e69931929648", 0x14)
connect$unix(r0, &(0x7f00000000c0)=@abs={0x0, 0x7}, 0x1c)
close(r1)


ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
sysctl$vm(&(0x7f0000000000)={0x2, 0x1}, 0x2, 0x0, 0x0, 0x0, 0x0)
sysctl$kern(0x0, 0x0, &(0x7f00000003c0)="8b5ea54a413c745995d4a95b979bb64d0541e6a50849f2861cc5f3e014d9ea6bba61da747d3cd9a068b38d0bb67a985e46184f42a6c16a68078392dee63af6e601c0865da92ccdbbf8b85cb74d593a4d771ba5adb1403ae15565ef56d99f35fcc544e7a02a6c038ad8350c06a67bb9150e72e4f7e3084bf8a8cd1f65c4f707722236a4bc53e00f6e41aaea38a0c4e09508e1e439d617879713ed556c9f38b1213fe3ebb3d05a1fb9af890b38975b0a67fee19a5840f6e655d79e6d8596f328b0a7315e826f5b2d2ef536e5c9fa3e6af4a8c312e71e7da86dd5ea55f5a6a153b43941fab0217cbe2a5fbfc598f2f1bdd630558d225116d927d6d4c600418246ac0b6dde68455e73bcbe8a3d", &(0x7f00000002c0)=0x10b, 0x0, 0x0)


open(&(0x7f0000000280)='./file0\x00', 0x615, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
r0 = open$dir(&(0x7f0000000180)='./file0\x00', 0x0, 0x0)
preadv(r0, &(0x7f00000012c0)=[{0x0}], 0x1, 0x0)


r0 = getgid()
msgctl$IPC_SET(0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, 0x0, 0x0, 0xb2}})
r1 = socket(0x18, 0x1, 0x0)
connect$unix(r1, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
getsockname$inet(r1, &(0x7f00000000c0), &(0x7f0000000000)=0xffffffffffffff35)
r2 = socket(0x18, 0x2, 0x0)
r3 = socket(0x18, 0x2, 0x0)
setsockopt(r3, 0x1000000000029, 0xa, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
dup2(r3, r2)
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, &(0x7f00000000c0)={0x0, 0x1ff}, 0x10)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmsg(r2, &(0x7f0000000ec0)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)
r4 = socket$inet(0x2, 0x1, 0x0)
setsockopt(r4, 0x0, 0x4, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
r5 = getgid()
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000340)={<r6=>0xffffffffffffffff})
getsockopt$sock_cred(r6, 0xffff, 0x1022, &(0x7f0000000100)={0x0, <r7=>0x0, <r8=>0x0}, &(0x7f0000000180)=0xc)
chown(&(0x7f0000000080)='./file0\x00', 0x0, r8)
fchown(r6, r7, r8)
r9 = getegid()
setgroups(0x4, &(0x7f0000000040)=[r0, r5, r8, r9])
r10 = semget$private(0x0, 0x4, 0x100)
semctl$IPC_STAT(r10, 0x0, 0x2, &(0x7f00000000c0)=""/55)
sysctl$net_inet_divert(&(0x7f0000000000)={0x2, 0x22}, 0x4, &(0x7f0000000240), 0x0, 0x0, 0x0)
mprotect(&(0x7f0000ffa000/0x3000)=nil, 0x3000, 0x2)


mknod(&(0x7f0000000000)='./file0\x00', 0x6000, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206979, 0x0)
getpid()
socket$inet(0x2, 0x0, 0x0)
getsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
poll(0x0, 0x0, 0x0)
openat$wsdisplay(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r0 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$VNDIOCSET(r0, 0xc0384600, &(0x7f0000000140)={&(0x7f00000000c0)='./file0\x00', 0x5, 0x0})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000340)={0x3, &(0x7f0000000200)=[{0x2}, {0x81}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000200)=ANY=[])


mkdir(0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
r0 = socket$inet(0x2, 0x3, 0x0)
setsockopt$sock_timeval(r0, 0xffff, 0x1006, &(0x7f0000000140), 0x10)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
getsockopt$sock_timeval(r0, 0xffff, 0x1006, &(0x7f0000000000), &(0x7f0000000040)=0x10)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000100)={0x0, 0x0})
mmap(&(0x7f0000ffa000/0x3000)=nil, 0x3000, 0x0, 0x11, 0xffffffffffffffff, 0x0)
ioctl$TIOCSFLAGS(0xffffffffffffffff, 0x8004745c, 0x0)
getsockopt$sock_cred(0xffffffffffffffff, 0xffff, 0x1022, 0x0, 0x0)
getsockopt$SO_PEERCRED(0xffffffffffffff9c, 0xffff, 0x1022, 0x0, 0x0)
setregid(0x0, 0x0)
mknod(0x0, 0x0, 0x0)
ioctl$TIOCSWINSZ(0xffffffffffffffff, 0x80087467, 0x0)
shmget$private(0x0, 0xc00000, 0x0, &(0x7f0000400000/0xc00000)=nil)


sysctl$vm(&(0x7f0000000180)={0x2, 0x7}, 0x2, &(0x7f00000001c0)="8373e0bd", &(0x7f0000000240)=0x4, &(0x7f0000000280)="a2d1051d", 0x4)


r0 = shmget$private(0x0, 0x2000, 0x0, &(0x7f0000ffd000/0x2000)=nil)
setgid(0xffffffffffffffff)
setgroups(0x0, 0x0)
setuid(0xee01)
shmat(r0, &(0x7f0000ffa000/0x2000)=nil, 0x0)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
writev(0xffffffffffffffff, &(0x7f00000001c0)=[{&(0x7f0000000080)="76e5eac907f9ccf7a251ceddcec7d6aa45cffe1463a52077dc0d00003ba4e9d17eb3eb5db12a3783a8e0620d357de1fe04fa9465b5bd1286e9624dec06a00c222f", 0x41}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
unveil(&(0x7f00000000c0)='./file0\x00', &(0x7f0000000300)='W\x00')
mknod(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{0x15}, {0x60}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000000)=ANY=[])


preadv(0xffffffffffffffff, 0x0, 0x4d, 0x0)
open(&(0x7f0000000100)='./file0\x00', 0x615, 0x0)
mknod(&(0x7f0000000180)='./bus\x00', 0x2000, 0xd01)
r0 = open(&(0x7f0000000000)='./bus\x00', 0x0, 0x0)
ioctl$VNDIOCGET(r0, 0x41946472, &(0x7f0000000000)={'./file0\x00'})
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
syz_open_pts()
r1 = socket$inet(0x2, 0x3, 0x0)
shutdown(r1, 0x0)
syz_emit_ethernet(0x36, &(0x7f0000000480)={@local, @local, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, @broadcast, @broadcast}, @tcp={{0x0, 0x3, 0x41424344, 0x41424344, 0x0, 0x0, 0x5}}}}}})


syz_emit_ethernet(0x0, 0x0)
setreuid(0x0, 0xee01)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r0 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
syz_extract_tcp_res(&(0x7f0000000040), 0x3ff, 0x8000)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f00000001c0))
r2 = kqueue()
kevent(r2, &(0x7f00000000c0), 0x101, &(0x7f0000000180), 0x5, 0x0)
socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0x80206919, 0x0)
ioctl$FIONREAD(r0, 0x8040691a, &(0x7f00000001c0))
syz_emit_ethernet(0x3d, &(0x7f0000000000)={@local, @empty, [{[], {0x8100, 0x0, 0x1}}], {@arp={0x806, @generic={0xf, 0x1600, 0x6, 0x7, 0x9, @local, "6abff6ce70d9a3", @empty, "abfa0b8633b5a219d91a7ef96d57c56e"}}}})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x49}, 0x6, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0xff0a, 0x0, 0x37)
r3 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r3, 0x9, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x1000300010008})
open(&(0x7f00000002c0)='./file0\x00', 0x710, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x20, 0x0)
open(&(0x7f0000000140)='./file0\x00', 0x20, 0x0)
syz_emit_ethernet(0x2a, &(0x7f0000001e00)={@broadcast, @random="2a9dafffe435", [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @remote={0xac, 0x14, 0x0}}, @udp={{0x0, 0x3, 0x8}}}}}})


mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
utimensat(0xffffffffffffffff, 0x0, &(0x7f0000002540), 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f00000000c0)=[{0x14}, {0x80}, {0x406}]})
syz_emit_ethernet(0x138, &(0x7f0000000040)=ANY=[])


open(0x0, 0x80000000000206, 0x4ebfac6bbaf7883)
open(&(0x7f00000000c0)='./file0\x00', 0x80000000000206, 0x0)
r0 = kqueue()
writev(r0, &(0x7f0000000180), 0x0)
openat$zero(0xffffffffffffff9c, &(0x7f0000000140), 0x10, 0x0)
listen(0xffffffffffffffff, 0x0)
socket(0x2, 0x1, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000380)=[{0x7}, {0x25}, {0x8006}]})
syz_emit_ethernet(0x56, &(0x7f00000003c0)=ANY=[])


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
r0 = openat$pci(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$PCIOCREAD(r0, 0xc0107002, &(0x7f0000000040))


writev(0xffffffffffffffff, &(0x7f0000000440)=[{&(0x7f0000000080)='\x00', 0xffaa}], 0x1)
pwritev(0xffffffffffffffff, &(0x7f0000000380)=[{&(0x7f0000000440)="e9", 0x1}], 0x1, 0x0)
mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x412dff)
r0 = open$dir(&(0x7f0000000080)='./file0\x00', 0x402, 0x0)
writev(r0, &(0x7f0000000340)=[{&(0x7f0000000000), 0x2cfea}], 0x1000000000000013)


socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000300)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
recvmmsg(0xffffffffffffffff, &(0x7f0000000700)={&(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000680)=""/100, 0x64}, 0x3f8d}, 0x10, 0x0, 0x0)
r2 = fcntl$dupfd(r0, 0x0, r1)
recvmsg(r2, &(0x7f0000000540)={0x0, 0x0, &(0x7f0000000280)=[{&(0x7f0000000100)=""/152, 0x98}, {&(0x7f0000000200)=""/76, 0x4c}], 0x2, 0x0}, 0x0)
sendmmsg(r1, &(0x7f0000000080)={0x0}, 0x10, 0x0)
setsockopt$sock_timeval(r1, 0xffff, 0x1005, &(0x7f0000000000)={0x0, 0x8}, 0x10)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000040)={0x3, &(0x7f0000000200)=[{}, {0x0, 0x0, 0x20}, {0x6}]})
close(r1)
socket(0x18, 0x2, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f00000002c0)=""/42, 0x2a}], 0x1)
sendmsg(0xffffffffffffffff, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1800000029"], 0x3e}, 0x0)
recvfrom$unix(r0, 0x0, 0x0, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000380)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000000)=[{0x20}, {0x30}, {0x6, 0x0, 0x0, 0xfffffffa}]})
write(r0, &(0x7f0000000740)="76e5dead6f01f8607d2100000063", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000140)=[{0x50}, {0x74}, {0x836}]})
syz_emit_ethernet(0x26, &(0x7f00000001c0)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000240)=[{0x2}, {0x50}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000280)=ANY=[])


r0 = syz_open_pts()
openat$zero(0xffffffffffffff9c, &(0x7f0000000440), 0x0, 0x0)
msgget$private(0x0, 0x1c2)
r1 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
pwritev(r1, &(0x7f0000000000)=[{&(0x7f00000000c0)='\b', 0x1}], 0x1, 0x2fffd)
writev(r1, &(0x7f0000000400), 0x1000000000000165)
open(&(0x7f00000001c0)='./file0\x00', 0x2e1, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, &(0x7f0000000040), 0x4)
pwritev(0xffffffffffffffff, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000080), 0x4000000000000003, 0x0, 0x0, 0x0, 0x0)
syz_extract_tcp_res(&(0x7f0000000000), 0x0, 0x0)
open(0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, 0x0)
mknod(0x0, 0x0, 0x0)
ioctl$TIOCSTOP(0xffffffffffffffff, 0x2000746f)
open(0x0, 0x0, 0x4)
writev(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x12, &(0x7f0000000200)=ANY=[@ANYBLOB="abaaaaaaaaaaffffffffdfff8847"])
ioctl$FIOASYNC(r0, 0x80047460, &(0x7f00000000c0))
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000140)={0x5, &(0x7f0000000100)=[{0xcc6}, {0x5}, {0x60, 0x40}, {0x1f, 0x8, 0x20, 0x3bf}, {0x0, 0x0, 0x40, 0x2}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])
ioctl$FIOASYNC(r0, 0x80047460, &(0x7f0000000200))
close(0xffffffffffffffff)


mknod(&(0x7f00000000c0)='./bus\x00', 0x2000, 0x450c)
r0 = open(&(0x7f00000002c0)='./bus\x00', 0x2, 0x0)
ioctl$WSMUXIO_INJECTEVENT(r0, 0x80185760, &(0x7f0000000140))
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
syz_open_pts()
socket(0x18, 0x2, 0x0)
select(0x7, &(0x7f00000002c0)={0xfffffffffffffffc}, 0x0, 0x0, 0x0)


setuid(0xffffffffffffffff)
clock_settime(0xffffffffffffffff, 0x0)


open(&(0x7f0000000280)='./file0\x00', 0x615, 0x0)
mmap(&(0x7f0000028000/0x4000)=nil, 0x4000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
ktrace(&(0x7f0000000200)='./file0\x00', 0x4, 0xd27d43220c7df9b, 0x0)
ktrace(&(0x7f00000006c0)='./file0\x00', 0x2, 0x0, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$FIOASYNC(r0, 0x80047466, &(0x7f0000000200)=0x4)
writev(0xffffffffffffffff, &(0x7f0000000040)=[{&(0x7f0000000000)="b8", 0x1}], 0x1)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x1)
readv(r0, &(0x7f0000000040)=[{0x0}], 0x1)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
write(r0, &(0x7f0000000400)='v', 0x1)


socket(0x18, 0x3, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000200)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
close(r0)
syz_extract_tcp_res$synack(0x0, 0x1, 0x0)
mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x412dff)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x1e56)
setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
sysctl$net_inet6_ip6(&(0x7f0000000040)={0x4, 0x18, 0x29, 0x35}, 0x4, 0x0, 0x0, &(0x7f0000000180), 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{0xffff, 0x0, 0xfe}, {0x0, 0x0, 0x0, 0x2}]})
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000140)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
getsockopt$sock_cred(r1, 0xffff, 0x1022, &(0x7f00000000c0), &(0x7f0000000240)=0x5d)
syz_emit_ethernet(0x3e, &(0x7f0000000140)=ANY=[@ANYBLOB="ffffe5ffffff00000000000086dd6073d477e407000000000000000000006b00000001ac2c0000000000000000000000000080"])
sysctl$kern(&(0x7f00000000c0)={0x1, 0x37}, 0x4, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x4d, 0x0, 0x2e)
acct(&(0x7f0000001240)='./file0\x00')
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{0x34, 0x0, 0x0, 0x20000000}, {0x1}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000140)={@local, @empty, [], {@ipv6={0x86dd, {0x0, 0x6, '\x00', 0x0, 0x0, 0x0, @rand_addr="7514bd0800000000000037481e7b3b00", @rand_addr="297530ac4b1d49265c3d1e9b53741f77"}}}})
socket$inet(0x1e, 0x1, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000000)='./file0\x00', 0x2000, 0x32e6)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000240)=[{0x44}, {0x7}, {0x6}]})
r3 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r3, 0x0, 0xc, &(0x7f0000000240)="ea00000100000000", 0xc)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000140), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000280)=[{0x74}, {0x80}, {0x6}]})
syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[])


link(&(0x7f0000001240)='./file0\x00', 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
sysctl$kern(&(0x7f0000000300)={0x1, 0x9}, 0x2, 0x0, 0x0, &(0x7f0000001440)="00000100", 0x4)


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)='\x00', 0x1}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
setsockopt$inet_opts(r0, 0x0, 0x200000000000b, &(0x7f0000000080)="02", 0x1)


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000300), 0x1, 0x0)
writev(r0, &(0x7f0000000040)=[{&(0x7f0000000000)='T5', 0x2}, {&(0x7f0000000480)='^', 0x1}], 0x2)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f00000005c0)=[{0x20}, {0x74}, {}]})
syz_emit_ethernet(0x3e, &(0x7f00000001c0)=ANY=[])
mknod(&(0x7f00000000c0)='./file0\x00', 0x2000, 0x40000802)
openat$speaker(0xffffffffffffff9c, 0x0, 0x0, 0x0)
r1 = dup(0xffffffffffffffff)
r2 = socket$inet(0x2, 0x0, 0x0)
setsockopt(r2, 0x0, 0x23, 0x0, 0x0)
pwritev(r1, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
r3 = open(0x0, 0x0, 0x0)
ioctl$WSDISPLAYIO_SVIDEO(r3, 0x80045745, &(0x7f0000000000)=0x3)
mknod(&(0x7f0000000400)='./file0\x00', 0x100, 0x5c4a)
ioctl$WSDISPLAYIO_LDFONT(0xffffffffffffffff, 0x8058574d, 0x0)
r4 = open(0x0, 0x14800, 0x0)
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$VNDIOCSET(0xffffffffffffffff, 0x81946467, &(0x7f0000000180)={0x0, 0xfffffffffffffffe, 0x0})
sysctl$kern(&(0x7f0000000280)={0x1, 0x4b}, 0x2, &(0x7f00000002c0), 0x0, 0x0, 0x0)
ktrace(0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000080)=[{0x100, 0x6, 0xca, 0x9}, {0xff, 0x80, 0x1, 0x9}, {0xffb, 0x36, 0xc5, 0x80000001}]})
ioctl$BIOCSETWF(r4, 0x80104277, 0x0)
ioctl$WSKBDIO_SETMODE(0xffffffffffffffff, 0x80045713, 0x0)
r5 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r5, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
setsockopt(r5, 0x0, 0x65, 0x0, 0x0)
getegid()
setregid(0xffffffffffffffff, 0x0)
r6 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(r6, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000200)={0xffffffffffffffff, <r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f00000001c0)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000280)=0xc)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r1}})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x50}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94100e4ac63c90dddc11f11cad5cc4", &(0x7f0000000080)=0x2, 0x0, 0x37)


syz_open_pts()
setrlimit(0x0, &(0x7f0000000980))
r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b1000501600000000000000007000000330002000000000000f96ecfc72fd3357ae320b37b673039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa5b236de351e2f0ac3ebbc257699a5f139b672f4d335d223e7d026ba8af630037282102000000720fd38bfbb770c1f5a872c881ea6e69e0bb76d907c400000000361b1257aea8c500002002fbff0c2300008abfba0900000008e371a3f8343712051eadb71d89e000040781e4b20b0001000020a254a14ce81f0cade4599523db09aef52411cf9886f289e93477356a40880349ff2bc46fa7a9abeecab40b254ccc72c07d97f045e3192f45bbd4279ca9edee5d289db8687d53c5cb5c7e8234e2c1ccfc10911ffaa33fed0b8812cce1c9dd3eeba4c145", 0xb1, 0x404, 0x0, 0x8)


symlink(0x0, &(0x7f0000001440)='./file0\x00')
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x0)
mprotect(&(0x7f0000001000/0x1000)=nil, 0x1000, 0x1)
sysctl$kern(&(0x7f0000000300)={0x1, 0x9}, 0x2, 0x0, 0x0, &(0x7f0000001440)='\x00\x00', 0x2)
mknod(&(0x7f0000000280)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
open(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000180)={0x2, &(0x7f00000001c0)=[{}, {}]})
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, &(0x7f00000001c0))
unveil(&(0x7f00000000c0)='.\x00', &(0x7f0000000180)='c\x00')
mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
open(&(0x7f0000000000)='./file0\x00', 0x0, 0x0)
r0 = socket(0x2, 0x1, 0x0)
ioctl$FIONREAD(r0, 0x8020691f, &(0x7f00000001c0))


poll(0x0, 0x0, 0x0)
socket(0x18, 0x3, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000000)={<r0=>0xffffffffffffffff})
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000140)=[{0x20, 0x1}, {0x3c, 0x0, 0xfc}, {}]})
syz_emit_ethernet(0x127, &(0x7f0000000040)=ANY=[])
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000040), &(0x7f0000000100)=0xc)
r2 = socket(0x2, 0x4001, 0x0)
dup(r2)
ktrace(&(0x7f0000000280)='./file0\x00', 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x80206916, &(0x7f00000001c0))
r4 = socket(0x2, 0x1, 0x0)
listen(r4, 0x0)
close(r2)
openat$vmm(0xffffffffffffff9c, &(0x7f0000000500), 0x0, 0x0)
sysctl$net_inet_tcp(0x0, 0x0, &(0x7f0000000100), 0x0, 0x0, 0x0)
sysctl$net_inet_tcp(&(0x7f0000000000)={0x4, 0x2, 0x6, 0x9}, 0x4, &(0x7f0000000300)="9b0209c3eb987ab7fe4189c99e805e6e84d356960798a692992117d6728436ba1bd87f42e3303eac3846528d050712f838130efce33f523ba44765f5f6915b0227390ed95bd9dc6d4dc7e149d4d6d06a3f23616e773302d9cae75e39a5a11e32e0e6ebd635450b2eba540af7f2aa5dbfbdd900a0dad2b74f50acd76b5c567049ef436dbea0d7562f52950fa5ef6e84c513252ddd8680a944d5c2bd02adc7f1fe850c00000000000000062ab475cca257352828a76e5334be562995e894238b96ca5d4d3e670feac9b4e8aa9bef19525cb6f7e8570b2a374f1400041ed45bb7ad3fe963cb9a8bd949ee0fc6dbceb7d956015947b3e88aa810f8ed7cca10ff010000000000001345daa49507756f49775275ca390b94e85d5a95b8bdacb9429c25483a9275d0da3b561c6adc3c141f26a88016dd6b436218bdbdc9ac0a623855e941dc1872fcb045e0d9df1ecc6357ee21e2b0802cb60eec6add5e94723235f06715e7eecc3e0760c70e1dd7873e27142bbae1a7e44de453a073fe3426f334b80f043ba9136d57c799353d46dd81439b111a511a288bee5dfb2e353e3bb073e3342273216b07e49ca4df0fd2dbe9a8eb377010ee678aad0bd8e9fb7d82693a096344671843a1f2082612b0ff237c6e505ff5f5ba932954d73c630fdb791f833a1da5af0704f687e196f4f7859e071fc98111cc9024f790ce16ceaa7d0104e39789d9100000010000000000050000000000", &(0x7f00000002c0)=0x210, 0x0, 0x0)


mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
recvmmsg(r0, &(0x7f0000000480)={0x0}, 0x10, 0x0, &(0x7f0000000500)={0x200ffffc, 0xa})
mknod(&(0x7f0000000040)='./file0\x00', 0x6000, 0x0)
mknod(&(0x7f0000000000)='./bus\x00', 0x3a0914c44f7b202d, 0x504)
open(&(0x7f0000000040)='./bus\x00', 0x10005, 0x0)


setrlimit(0x4, &(0x7f0000000980)={0x7, 0x100})
r0 = syz_open_pts()
close(r0)
ioctl$VMM_IOC_RESETCPU(0xffffffffffffffff, 0x82405605, &(0x7f0000000300)={0x0, 0x0, {[0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x0, 0x9, 0x80000001, 0x2, 0x0, 0x0, 0x0, 0x100006], [0x0, 0x0, 0x8000000000000001, 0x0, 0x0, 0xfffffffffffffffd, 0x0, 0x0, 0x0, 0xd35], [0xffffffffffffffff, 0x0, 0x0, 0x0, 0x10000], [0x5, 0x0, 0x800000], [{}, {}, {}, {}, {}, {}, {}, {0x0, 0x0, 0xfffffffe}]}})
setrlimit(0x8, &(0x7f0000000980)={0x8, 0x54})
r1 = syz_open_pts()
close(r1)
writev(0xffffffffffffffff, &(0x7f0000000700)=[{&(0x7f0000000080)="34eb4cd59e8456ebc0881681c60e1cd9e0bf01b618b3cb934394c5951c1db0fd943a", 0x22}], 0x1)
r2 = syz_open_pts()
r3 = socket$inet(0x2, 0x3, 0x2)
setsockopt$inet_opts(r3, 0x0, 0x64, &(0x7f0000000240)="01000000", 0x4)
setsockopt(r3, 0x0, 0x67, 0x0, 0x0)
ioctl$TIOCSETA(r2, 0x802c7414, &(0x7f0000000040)={0x7fff, 0x0, 0xa0000401, 0xffdfff8d, "1ba5d82d727c660800"})
pwritev(0xffffffffffffffff, &(0x7f00000001c0)=[{&(0x7f0000000200)="18d26cb474b5c9d53e0ffdba8c54fecc9031509b1623088cc3e85353a5586603eebda7eccfc5ced62b70a12fbffc2425f3f9e50317605792ea906ef56376aa499b9a909aff511ad2d6", 0x49}], 0x1, 0x0)
socket$inet(0x2, 0x0, 0x0)
ioctl$TIOCSCTTY(0xffffffffffffffff, 0x20007461)
r4 = getpid()
r5 = fcntl$getown(0xffffffffffffffff, 0x5)
getegid()
r6 = msgget$private(0x0, 0x0)
msgctl$IPC_SET(r6, 0x1, &(0x7f0000002f80)={{}, 0x0, 0x0, r4, r5, 0x7fffffff, 0xa, 0x2000000100000001, 0x7})


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000840), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000080)={0x3, &(0x7f0000000700)=[{0x3d}, {0x3c}, {0x1006}]})
write(r0, &(0x7f0000000740)="76e5dead6f01f8607d2100000063", 0xe)


open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f00000015c0))
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040))
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
sysctl$vm(&(0x7f0000000040), 0x2, 0x0, &(0x7f0000002f40), 0x0, 0x0)


utimensat(0xffffffffffffff9c, 0x0, &(0x7f0000000100)={{}, {0xfffffffffffffffe, 0x1000000000000006}}, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
recvmsg(0xffffffffffffffff, &(0x7f0000000100)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000880)={0x0, 0xcd, 0x1ff, 0xd2a, "90d69208f30000000000000000001e00"})
writev(r0, &(0x7f0000000180)=[{&(0x7f0000000080)="94c799e845e3728fe0395644c7c6f150860233efecf56fa2bb0f2999f4a251fe7da7cd83d68bac3f0d30ad393b4b2de3c6929edefb3add71c81743bcd8ec9a614d7e07dbacfff921bf04ef41e1e0271c41eeef3a0cd94991cb4f132dce21af098e390915c193a2439927299c3e43184e588171b900", 0x75}], 0x1)


pipe(&(0x7f0000000000)={<r0=>0xffffffffffffffff})
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
r1 = openat$wskbd(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
r2 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r2, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0x8)
syz_extract_tcp_res$synack(&(0x7f0000000040)={0x41424344, <r3=>0x41424344}, 0x1, 0x0)
syz_extract_tcp_res$synack(&(0x7f0000000040)={0x41424344, <r4=>0x41424344}, 0x1, 0x0)
syz_emit_ethernet(0x14b, &(0x7f0000000000)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x13d, 0x0, 0x1}, @tcp={{0x2, 0x1, r4, 0x41424344, 0x1, 0x0, 0x13, 0x4, 0x2, 0x0, 0x233, {[@generic={0x2, 0xd, "96c729637cae4fa49c1558"}, @sack_perm={0x4, 0x2}, @sack={0x5, 0x1a, [0x4, 0x0, 0x40000001, 0xde5, 0x2, 0xffffffff]}, @timestamp={0x8, 0xa, 0xb018, 0x8}, @generic={0x0, 0x2}]}}, {"d1c2f0bfe2d0786ca28e44289f59aba04d62ff16e6bb47f1cd981d0cf5f225560531db5a3a6c3cb3d5ac50e0eec7423f3ef5e3c4a13f81f14f843a32b529e4649b57d581159522ddf03a6cabf358af4e1ae7ab79a9aac6417859ae29d8de08ba3da1e6387381a61f166b78d7ae58ccd15a08555c8e7db3e261cbba4f565ff3567edfcacd1a43a2f80b44a3727c2f46723f3826d9842357f4d467cb2e24ed586547d107e74cfe46502dde741762fe8ad6742200cf5fd16fcdadae4fd744b730286383e0444647e948151cb63c5c12b79f75a37762e3f013f189799eb699"}}}}}})
syz_emit_ethernet(0x1377, &(0x7f0000000280)=ANY=[@ANYBLOB="000000000000aaaaaaaaaaaa81001c0086dd69591467133d03810000000000000000000000000000000100000000000000000000000000000001ff003f78640000003a010000000000000502000000010001007cb39eb7b60cf5ff4438ddf62e59f28279e7ec96edbd8981e8fedb093def3ae11b015849d65167d5f621d6b30c72282b12a36cd575c508902b494e47c1ca79e1b58221cd3e1c192dbecd115cefecebaf9216ba781967a9d607df2ae586404e218688e8672eade740a00765029c88104401dc97cbb7cf147a22a484ba6cc613ceeb60935547961bb5fa1102bf551126dee4543aea671c8db97f5f617a6123bb8be8a21e139d4d5bfb0c15fe07c4a7b66500e00d2eaa811764b184e4f9b8837d9fd3f35e3973aac596e7b98e37cfd4d66df004086bd9f02a7528d1105e750246056a2deca4133d82f7e463cebe8453e56c24824f9f01df6117e1f9c5677cefbc7a67be8b82e1a67dfb460948fc28614dbb96a185dd72209e459abe9f760a954362f92acd1945b6a9013be8b0167eabd911ca537b68ac7a70664df43b2e555da1fb23347f449750a1f6c0ae952e5279ebceaf8624c61a5d063c2e4c76c98802b9a4ae0eb76181efcc572367bff766a7cae43844d5b21f02adab06e0f95c43eca616a7bdf140b8f1170468209623d4aadb788774daf13e4cb407a421add86c12ce02c893318ca739e9cb11c4c610b39ce02d2aa25a0322cc13338b83095f4069219ae7319cf0ea2a855679a72947fc54435348b9605c381076137cf3575a5fd911dfa0e1a79ac92e7f9ea27f69704120450cc0beb25fc11add935281451f1eede0d1026bfe317c74507e0bf01d48acf136cf0b5ce82df6af0092636fa76b200a3459004148aa026527f39625dd9f58b1ac7f08ca74937a027497fb97c722edbe65091c2ed452ff9225f703e32c7452ccf7ee94625e69ab5249699713d6c9bc0aad67814e3edbd30f5d4b750b43a5237b85338b9ba4a41e0b70b556ff70fce6a088e6e5908dac0487d7a4ccdc9305cf6b17b9b914926606c181434db76858ee4e8c90faa941180d577973d4b57e9dc457c26119830b4bf45110f1ab3caa4c5001bd67b6120988b00a0cb43bf186a6e850ad23767ffc54c0ffa4a7fafe62960d10222fb3db0ea7f353c571257eb3ac6c85b7f634dacc0eb757e8fefd03facb94fcab2eafded24fac1d15eaa9508909c7d452e1b20f99a9b393d80203f0e9d5cc2a900ac269955bd7bb46e74bf2a6763ff678255e08ac219b2cdb50c5a68452a29eb717adf56e87d1fcfa58faca564c75d32a8a8c6ccdd53160a906f0c94aa8640f465fad20e53f0f294e9072df0fff2a09c54408072bb1fb7155f70914824e3a66dd7e5d59b4e95bc80cab9e0615efa7bfb2533961f9392774ed2598080be96370663aed39582ab7a8b841f1e2e5bad1d91c3b171f705c751494a8c04a7e079f7efc716fd1e58c3ac1a933586a3410f31ae6f6ac8cc4298a5eb51395344dc9928f6754e067c0b545d8030dc891223641e988aaa38dcd4cf3a85a6993d3571fbf3b88808965677348a023fac3c413ad67752ad6d00ae2f51bc051a16db2b0c972e96e3a124f0084d338e952aa2c37e62a107dd9c323c6ce6b4ecfc2dba24c065051d6180605a276501acb7dd02e17c572e7ab77d65f5530a1ae904cda40e9743956a52cf58b9e494a82deb5f60d12f69a9ade52bb954edbef10bbb2ff1a4a300a5f63c58551b12e162364ec1de7b4da00e7e6e648d1ec2eeccf5f0843652902ad0dc9cf810db3f8cb4c6bf108c47d5eb55b5efb9d4ba2047d00114f54c8aba2c57f409e8956fa436cd36009b304efa28224b1880c14750397aa76ff32c9671bb17c00cc863938c9b0620282f0283a1d34aa48206972cec676c71b50c430e91084cd798354e5a6dba46d1b2f1f11701c77819ca20395b15bc55891cf366e1063af25dce0e8d99292ff28758c93f459991a1f0ce5b90fa3c18378e0e4510cc245f64c4031b5d1cab92131c0f4418f4eb98b08470af3d21359ce3819c881caf9abc11e155a56a8af024db7983a9d634ab1488b37573c8f3451dc2285e1a5e0e3de202ba4a1bc50f1259735f706a4a59189268284c1ce32724d5bf2732992a1395678b7ff93dcb759bd2be6285ad29ab29fd6d897553b4ee3e55975525cba526de16dfcba0c1c828bb22dcb91842e64c8d6ab8ac349a5b507f6b4c1ca691e35522a0960a30fe1c0fed1cca456150648b80fda63cf3a2d80735f3e9e879b8afb119e8d9be4365ac19d856e2e090d33aaebbbe9a10891a2c4421cf03915db799e19109a73f30c73e822eb1c6e8cea396b7e047e951b886dad031df1b43c0ac1e1bdeb298174ec4d79c4e9998686a8757342032e7ff7e3bf821ebe627c9b53c799ae0df41489d1705a465cfaf232dd8c94786120ecf4e564389dcbc29e5906ed4d2dbc9ab7c64aa73c130889c6752f0edcc70def9e0467c4821f5d7466f8d2a8f1abe1dbfd9b8ac670a8c368266f4358aa67ac3d232fd5f331e7fb6bbc32039abc0eebf57b058de0d9982d68372a496acd49087b4c4e75a16a5d7bc2e97e909e7994d2350e50499a57e41e1a19ade850d2105211f046ece0cdefeaa02bad9a7b2f4a651ca4335048e1783faca990905f0759c7f9ec978281fdc61a86807d5ed6de4db03a2a3f92e79d08aeef5042c9df69409b354cfbff21e9ecba96936dbfb3a18630807f62a2c2a577b380f3372c32fbfef29571a2de5f1b3f3ab0b4d64ad95f83c7d1a7024bc9665ec22c7dabba6538b5268f91b68c6621b50bb58cc1694b9df82787fdccddbff7cb9df4372becfa46e748dca69c7f594bfd968069aac63bd121bd5a2fd0ba398f3c418e345b3a62f7aa37ea23088e5ddaca77fb81eff00e525629cb527e867ea33335b304f6cf66e46e57772dd3411c152a7550ed19cf2a4dac6a3320ed0ac69290f4b0baef22363003bb55bacf1e7b0da53f118d42408a8a28890a108423a33a8b1bd0c98580342dcf203eb4fa6e9f2bc6d1b4fe064be2cde9c7c3b3f8b3040daff3e61704acc29eb5f83bfe73e548ef94bc70baba60ff32934afbd95bddc01fbab85feda874076bb0619450b98f223505b552088ec22844998c8d7aa7fca0fca0ae68b9c20af5c41a6d68da38a5100c824efb425925587e494f9a829e2975890dd1794276fbd4caa176bda386398bc214bc523141eccdb83110ca5193e9f81d34971d0611203a7ed54f3c51138f3d574d9ebd2a8723d311059e4c73f478e8a336c5692e5f7b8586b47615bf38e2be1c6ff6d40c0be31d94a1080e3d777a7e301db43bc51d27acf15b9b083888b28de5ef045ba98d9813e212deb9f044968f24d00d6580d19bebf13766ad3ae677558b35f6d703cc1f3d4219c49c4341da4838592f09df4870182cd5641311289a1e628872dc64a8a3255771eb078c480d3d2c0eaed51ea20b330f85a53a42c53caab0095be40c8723a452d1cc05c7a001719b75b15fe298eeca810b927825fc29fa6617262ee61798e942745597a86c204218ba729f3e0b398f99197f9b9682bf136243a464e701299c5bfb21f61f4648df027695b0895d74e7ccaac7826c2ff3053857e54cf451eb80be46a6f73f9dddf59b1a791c69e5ec5c8837942f02005b9a9dafec512b97aa197dad3b74e19df8da8ab9642efff9062a05dc7dafabbdd0c57cc79e1de68c59f9cdafb5cbd9f3c241ca267e38b7e4ef8fbd1afc01c17fa2705a9bcb8e5471dfed411a02b82bc0651b89c1e8fbced23304ab9a90f16f855ef073ada91c22ae72bec4960985001cef2dae57392dcc86ded32913c6a5d6abc31be26c1f3b185e2c955b9990b6be65697635cbda24698dbb5173730f80ff36402d376d29b0652d7bbcb348cf4671d80136a959fd3e3392da369e3bb0540b8eb50fd6d42a2c599f0b6b23e31558f77342decd1ba2910d5b09954dbc8f71afae697ee5b7c89d3e4b85b9815838422a69cfefa5e7c09f0efe47af9a2baf8030e4ade978ea16bb758f3e6ba5d8d116cd2c76e4a86f282ec7276c74baf46adefa1b28baef460c9570ebc7be5b16a6cf4295b6edfa13e4a52f07c6d7ce1dec07de6830198e68e4a9bfdab700955c6670f6396746a61f05faedd0f766a1b82fc1f10e7f818a7f95f507b1f0c7a5b3a9ce69e9038e0d27e96f3a4a5b6419609e420db2a9d41db2b3e2bb649ac1e607ccb7ea6c3ae8ebefd2a00db34a1dccc146ca9c36bbf5ac2ca2ddf089cafe6a380f53c2da7e7987667609f8d546a792185ce06f0bf763be1c3661e6d6b832a889423c9c19cbe21d84aa48cf64d21bf1c81e581e331ef2e72800af1831005c661ac15712b12004f39616ab352d1507c514d05d3e53633507cc15a6b7a6e78a24f0c357ed5027c6a3eb8954c7af1ed785247467998d3fd9284cd41030f0c3c770dcea892442fb2b3184f695f2e4d39369239813ff369aee45e05fd9f71a87841e74142ba4bc5ecc3308844e8eac364038298c697051d405f59370319198e97513dd2c115fe9e8093beead94ef0ddcf5a32363548b39af8055ac45d0fc93442813ce2b7735cff373fb9beb6ac7aaf458dbe2098d368cdc9584b77e2611eda18b38ce7a728b025144b6952871b0238d7598fb297fd820caf227308399b76b930a3d9b9d5cfc5e39a6bbf74a02e8c5aae1456e2e19e86034ad4f3dc0c3a7fcfa2eb4817edcbe88a954bdc24c693cd48273d0769ac08d53df57711d477bd8b1e9c850945a4236408a0d8f040a483991dd86c5d444cee5a260fd9bce17e3f3d21b41bb9a7d6bdbdb6b0df4cadde26b3a851183ff4d9a388ec1e0e2f92135e1789e54eca165c37cce2640d6057f6ed73fca22b0cdf4450f52a5d7b64ac4faddcc18dc1909405996e6367c751ec23758fe0da3697ebb262d87a4d74f47831d80b7cb370c4af3a6ea4127aa943a5274d8c26b124500d60ae065e982dcdf45aa447eab89b44252ffc79ed283b489b16cf70853434367906c800a83dcc34b8b2f23a0eb332942c99268dcafd81911a0bde412d0ad6bdcddab0fa63356596eda0567838690e91126188622481f9d21ddcd77f21ac7f0fa4c1b13797d5681609f3df306d2ecabe0c95d9b0ccc66bee82640511f597be0ac75c94e2da3492ac666f11ff1c4850f0711e1e7b1857e824517e747c6ed0c0adaf39b9ef9ce5335f57af6136c97ec2b4556604c5892b477f9a55763f77f6368bdfea417e0042d0cecac3614bfc9ee127324e195361849c2409e8ca9fca49d018d71d9e7d6bf5ec94a2ef2281cc67d805408e06929b3d55c46dd7602534b355ba55df2dc84306c8af413498f604789865a2b7bc63f311d8b612ed3577bbfe3b340abc3509ba4c81724ba4304e17e67207079ef556914bfcb71e07a3cff968f568c9755cc185c05855fe19c50283be37c9654137b031a2ef244d9a1b05cdb6272f29e5da563b8ccd71c48eebb187e52956a6cd71d65bd34eba9d15061807c6be7d55fa27e65fef3974282deabe52a96177e09722787d35f4174c94fb7c9d309f43d21f9411b5ed4bb4309bfe342f4a28d89b6b123484d8c15825eb6ca95e06762c606e4b42bb004d2bf757d094dc0cff8c3ff34e4a1ee94311735e5c8f2458fc357410a84f634b417da23925ec53e60387ef94cb552e3b429a62c9a2dae2d4a7dcdef416e2a0a96cf7e7cbfefa0a737d6c168dac002c407720962eb885982f7567a9f3bcd6b17e8674f5c0ca06f57d8edf39a41a9871819e6d95c13421285e7e6dc97a677f94163074f8f60310836a3d949328197f3c2f03fd7d3ba5fbb3a81e352a135786586f70e37ef1d205be68fa4c5f265fc77e66c5688883ff70e5cc2ba26d6ede2a141807f76d9f4f14cb4a5aeb168c87e2e3e04015a000000006204000400000000fe8000000000000000000000000000bbfe8000000000000000000000000000aa0c14000000000000000100c204fffff29c208b472c23a1f081926fecf8ffc79d62c8a17c6d8d4d6288eb185a980854d78c785496d43928bb0a74b7f92fc16b584cd1493a2b1a984683a618a9a39d3f06c49a588fd32e3c9a01df818f74d5dfb66e0410f4d46580bac52fd1f31f4077ab5247956a7b5c3572e6b4da2806db0608440d59665fcd811869e5e16414cc852f088f053ceebd00cf2acf9daae5c6c20400000006c20400000005000000000000903800000000000001040000000005020008c20400000007010300000003d050894301a040fe9111cc8d2076757c3233162c56f6610df260f116f387dc0b31450634e0db33c377e6d4508f2c5f0e2cc808a51b3389cf71a7bd2a8dada0ccafb978fb0ad45612183e87cc992f4f9f4f09b1c22fe7d58a78be0521d239096a61a6cea207ef7429b16ed7abacc7f9e01f85dfb4d436e72c8d24e7bf1eaa966c92b8ce7a441adf2ffa03eea4ad4dee5fd2f1dc3ee0930fbb9b085a67d5e62cfd1f96b8e2674a05b24105f2df2c773efcd3f3094a22a95961e828050969f0e10aedac85e12ca69accb44c983acb47a445d80401813fd32c302c2bd9c19e1b26a4b5325bb41453b011fc10cacfd356473faabd9c9e9b3c7c4a9bd38d92ea61b448aab6f1b92d8d6b9233ca1aba26d7ee240e9fa65d5c59c9d98d269859685c81c0231f2a2ab65463c69d28a2cc739b4ba1340ccaae4360cdfe810aa22a980660c5de86733d4592a11f7473f141ac9ba17d7fdbf6f109c526f693637168550051b3f66e86dfb71bc96e4cd046077961b1d5c8263e5c6dd5499df70fb263b6480755b9fd7767b087e95fea048016d5c80c83a0a1b7328b3976bb07e07e62fc715b5a1805577273294237a80001000000000000004e224e22", @ANYRES32=r3, @ANYRES32=r4, @ANYBLOB="f00000059078063e0402131259523e40b3ec6c558f2665323bc3776800010512000000097fffffff0000000200d90b0b52c236c2809ce46282903acbe1fd552d6a5dca4f3968561a84be33945938f499fb6387604216b9587a9df54cfdb585e024d013e71d872313cf"])
ioctl$WSKBDIO_SETENCODING(r1, 0x80045710, &(0x7f0000000240)=0x240)


sysctl$net_inet_esp(&(0x7f0000000000)={0x4, 0x2, 0x11}, 0xa, &(0x7f0000000040)="82338798", &(0x7f0000000100)=0x4, 0x0, 0x0)


sysctl$net_inet_tcp(&(0x7f0000000400)={0x4, 0x2, 0x6, 0x18}, 0x4, 0x0, 0x0, &(0x7f0000000000), 0x0)


r0 = socket(0x11, 0x3, 0x0)
symlink(&(0x7f0000000100)='./file0\x00', &(0x7f0000000140)='./file0\x00')
sendto$unix(r0, &(0x7f0000000400)="b1000504600000000000000007000000331c13fecea10500fef9ed06c72fd3357ae320b37b673039d2d236073705ae04be38164991f7accf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139bb9a70e41f78eb96a05672f4d335d223e7d029d6ba8af630037282102000000720f70c1f5a472c881ea6e69e0bb76d907c400000200361b1257aea8c500002002000000000000aabfba09001d89e001e2ffffffffff7f00ff00"/186, 0xb1, 0x400, 0x0, 0xffffffffffffff3f)
read(0xffffffffffffffff, &(0x7f0000000240)=""/226, 0xe2)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r1 = socket(0x1, 0x2, 0x0)
r2 = socket(0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0xb, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
getpeername$unix(r1, &(0x7f0000000c40)=@file={0x0, ""/4089}, &(0x7f0000000200)=0xffb)
r3 = socket(0x18, 0x1, 0x0)
dup2(r2, 0xffffffffffffffff)
r4 = syz_open_pts()
r5 = syz_open_pts()
setsockopt$sock_timeval(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
r6 = socket(0x18, 0x2, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
setsockopt(r6, 0x1000000029, 0x3f, &(0x7f0000000040)="674cd6e5", 0x4)
writev(r6, &(0x7f0000000080)=[{0x0}], 0x1)
ioctl$TIOCOUTQ(r5, 0x40047473, &(0x7f0000000180)=0x6)
syz_open_pts()
fcntl$lock(r4, 0x9, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x20002fffffffa})
setsockopt(r3, 0xffff, 0x4, &(0x7f00000008c0)="fde5ec306dd4980c98b9789dd458a5a71e08d80473d8ca5533d6dce7a50e32a597f963b83dfb4e312f841b2e40b65cda6d8cbb9509e6d7bd24e1e293830eeb6fbf7accab8d85000000c029740496824a737c5e718e7e50d6bc1e3eb1ced929e4108ad2049cd200e5d0fdd7c39e72c369e43c69004c5d7e35f08c0d6258f0391d68739257d6dca392c9fe0422ace96abadf03f2bdd0fdff097da5ad16a84b7ec194b9d3377d2f74de9d312a58559fc7ac84446c34ab88680beb4340b949cc9b127ca5ea9cc73c431fcc1dea7352f7f8d50ac74f7275ce92e62585190ab88c63d807f16900d1f59e48456eca6450ef709168e39bffae6bd6add589330db5ea0d02fb2142f453177b8fd31204fa04ac0c6d2b9e311d1aa126c819ca648bd2ab17b4496ed65cf367b3fcbc54984c05b72044dba2c79e29d15725585845005d1fffadd1d826fa25addcd47615707988ba4fe4698d35d6a1386542e19f630fd8697cf70c56838c9094165cd0c04758be94ff045bcc6094fea750d2c54017c513b81c51032a3de594576465667fb453cb7718d80010da864c970df98b2834f4ad05ae507f0ad918e46e8a6d655285391130d7e80941cb79ff87cb1e7a592c46cda8301d51f873fbccc2501cb7347aebe991ba1e82a54c38c7fc17839cb516e58a114c6840283c6a6bc259e32d1481c8a2d0d5d245275f7e16fc92bd08930cc03c2d395431591f03cdb31dc58ea5cef9b7b83eee88b22bdfbbe767a7e6e09b7635450b5a32cdb278928f7e6dde2374b05c9527381659ef190b5f1fcbd5b56b8a77e2f8324fb98676b0b5c510e6333354868645708687f1fdb8637418e6688a8d60d61197d65de3b11658b014881a2a7c9aae229d9da66ea249634c3ed140b407c8ae9264706172942d6e45d5cb55c4d21bf01649f6cd3f285a0c34a98947b1fe71c7b6dae00e41a8e9d0c783e10a7c4400379906f8bb55afdc9cf7b9183bd6b3727be206e43f97989e561ac8f36d2068cde3601ef5ceab9d3ea53ccbd471e6911a2afacdf5a67614ff3c5c742141beaf5c32407c36cd4fac53c800000000b6c361af044573f24a46e71a3671caf41ed03181cc1e758a495bf48892caa340cd0ce005f8949d4b5928a3d8f427f54909704acef10c1529dc0eef35e3c1f1defdab96e44ade2100e1ed9cfdea4d1c3898bbf7a5cea2cfa24cf7edad227b", 0xffffffffffffffde)
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105727, 0x0)
r7 = socket(0x11, 0x3, 0x0)
sendto$unix(r7, &(0x7f0000000000)="b10005016000009f05000000070000007d9113fecea10500fef96ecfc72fd3357a068da3a5673039d2d236acf20b7804be38164991f7cccf5f882b297be1aa5b23edeb51e2f0ac3ebbc257699a1f139b672f45335c223e7d026ba8af630037282118000000720fd38bfbb770c1f5a872c881e2772ec5a10400000000000000361b1257aea8c5d0002012fbff0c230000880d6633c556ae9be371a3f8343712051eeab71d89000407000000800420000000", 0xb1, 0x0, 0x0, 0x0)


socket(0x0, 0x0, 0x0)
r0 = socket$inet(0x2, 0x8003, 0x0)
setsockopt(r0, 0x0, 0x7, &(0x7f0000000340)="15337ac0", 0x4)
syz_emit_ethernet(0x2a, &(0x7f00000002c0)={@broadcast, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, @multicast2}, @icmp=@echo}}}})


r0 = open(&(0x7f0000001700)='./file0\x00', 0x70e, 0x0)
truncate(&(0x7f0000000000)='./file0\x00', 0x30001)
mmap(&(0x7f0000ffb000/0x1000)=nil, 0x1000, 0x0, 0x810, r0, 0x0)
write(r0, &(0x7f0000000000)='8', 0x1)


mknod(&(0x7f0000000380)='./file1/file0\x00', 0xd000, 0x205b1a)
unveil(&(0x7f0000000200)='.\x00', &(0x7f0000000240)='c\x00')
mkdirat(0xffffffffffffff9c, &(0x7f0000000080)='./file1\x00', 0x0)
mkdir(&(0x7f0000000140)='./file1/file0\x00', 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000340)={'tap', 0x0})
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000100)={0x0, 0x0})
clock_gettime(0x2, 0xfffffffffffffffe)
open$dir(&(0x7f0000001240)='.\x00', 0x0, 0x0)
getuid()
ioctl$VMM_IOC_CREATE(0xffffffffffffffff, 0xc2585601, &(0x7f00000000c0)={0x10, 0x0, [{&(0x7f00002b5000/0x4000)=nil, &(0x7f0000ffc000/0x4000)=nil}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000159000/0x2000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000690000/0x4000)=nil, 0x5}, {&(0x7f0000692000/0x3000)=nil, &(0x7f0000ff7000/0x3000)=nil}, {&(0x7f0000ff1000/0xf000)=nil, &(0x7f0000ff1000/0x1000)=nil}, {&(0x7f00004f8000/0x2000)=nil, &(0x7f000068e000/0x12000)=nil}, {&(0x7f0000ffa000/0x4000)=nil, &(0x7f000015e000/0x1000)=nil, 0x4}, {&(0x7f0000ff9000/0x4000)=nil, &(0x7f0000159000/0x4000)=nil}, {&(0x7f00004f6000/0x4000)=nil, &(0x7f0000604000/0x3000)=nil}, {&(0x7f0000ffc000/0x1000)=nil, &(0x7f00004f6000/0x3000)=nil}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f000000e000/0x4000)=nil, &(0x7f0000ffd000/0x2000)=nil}, {&(0x7f0000691000/0x2000)=nil, &(0x7f0000ffb000/0x2000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f000015a000/0x1000)=nil, 0x4}, {&(0x7f0000ff1000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil}, {&(0x7f0000ff1000/0x1000)=nil, &(0x7f0000ff3000/0x2000)=nil}], './bus\x00'})
socket$inet(0x2, 0x0, 0x0)
sysctl$vm(&(0x7f0000002e40)={0x2, 0x7}, 0x2, &(0x7f0000002e80)="8d1ee271", 0x0, 0x0, 0x0)
setsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x1, &(0x7f00000000c0)=[{}]})
sysctl$kern(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
socket(0x0, 0x0, 0x0)
mprotect(&(0x7f0000ff3000/0x2000)=nil, 0x2000, 0x0)
writev(0xffffffffffffffff, &(0x7f0000000300)=[{&(0x7f0000000140)="f005c71031c1c5f421277b09000000000000007a091a2f47be787538ec7a89ec5ed66daa731ddc384ecc690869a0aa2266affdf772d7a360ee0f15fa664f557bb45071fe9b6d9d28e6e2589000f6a64f370b9e336987d77b38f7aada5309e46a81e0e2efa087aa9f5f89934fdbd2ed96e7234b8972b273e810ca9962a8f461d3a05711a63027321ff62c", 0x8a}], 0x1)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))


r0 = socket(0x2, 0x2, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r1 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r1, 0xc0106924, &(0x7f0000000200))
r2 = kqueue()
r3 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r3, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r3, 0x80104267, &(0x7f0000000100)={0x3, &(0x7f0000000180)=[{0x1, 0xfc, 0x5, 0x7}, {0x24, 0x9, 0x2, 0x8000000}, {0x6, 0x80, 0x0, 0x8}]})
syz_emit_ethernet(0x127, &(0x7f0000000040)=ANY=[])
openat$wskbd(0xffffffffffffff9c, 0x0, 0x80, 0x0)
kevent(r2, &(0x7f0000000100), 0x101, &(0x7f0000000180), 0x6, 0x0)
ioctl$FIONREAD(r0, 0x8040691a, &(0x7f00000001c0))
socket(0x6, 0x2, 0x4)
getpid()
openat$wsmouse(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r4 = socket(0x18, 0x2, 0x0)
setsockopt(r4, 0x1000000000029, 0xa, &(0x7f0000000040)='\x00\x00\x00\x00', 0x4)
setsockopt(r4, 0x1000000000029, 0xb, &(0x7f0000000040)="00000200", 0x4)
socket(0x6, 0x8003, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000000)={0x1, &(0x7f00000000c0)=[{}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x27}, 0x2, &(0x7f0000000100), 0x0, 0x0, 0x0)
syz_emit_ethernet(0x17a, 0x0)
open(0x0, 0x0, 0x0)
r5 = kqueue()
open$dir(&(0x7f0000000040)='./file0\x00', 0x200, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105727, 0x0)
kevent(r5, 0x0, 0x8002, 0x0, 0x5000, 0x0)
r6 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETF(r6, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f00000000c0)=[{0x45, 0x5e, 0xff}, {0x20, 0x0, 0x0, 0xcad}, {0x8006}]})


r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$VMM_IOC_CREATE(r0, 0xc2585601, &(0x7f0000000300)={0x10, 0x0, [{&(0x7f0000cb5000/0x4000)=nil, &(0x7f0000eff000/0x4000)=nil, 0x1000}, {&(0x7f0000d1b000/0x4000)=nil, &(0x7f0000f95000/0x3000)=nil, 0x100000000}, {&(0x7f0000f63000/0x3000)=nil, &(0x7f0000cb9000/0x7000)=nil}, {&(0x7f0000d03000/0x1000)=nil, &(0x7f0000dd3000/0x2000)=nil}, {&(0x7f0000fa3000/0x2000)=nil, &(0x7f0000cdf000/0x1000)=nil}, {&(0x7f0000daf000/0x2000)=nil, &(0x7f0000f8e000/0x14000)=nil}, {&(0x7f0000c85000/0x2000)=nil, &(0x7f0000ff9000/0x2000)=nil}, {&(0x7f0000c0a000/0x2000)=nil, &(0x7f0000fff000/0x1000)=nil}, {&(0x7f0000e67000/0x3000)=nil, &(0x7f0000dfc000/0x4000)=nil}, {&(0x7f0000e16000/0x1000)=nil, &(0x7f0000e71000/0x1000)=nil}, {&(0x7f0000d6c000/0x3000)=nil, &(0x7f0000d3f000/0x4000)=nil}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000f6a000/0x1000)=nil}, {&(0x7f0000c0e000/0x3000)=nil, &(0x7f0000d42000/0x1000)=nil}, {&(0x7f0000c82000/0x2000)=nil, &(0x7f0000f33000/0x2000)=nil}, {&(0x7f0000c63000/0x1000)=nil, &(0x7f0000d86000/0x1000)=nil}, {&(0x7f0000cea000/0x4000)=nil, &(0x7f0000e5b000/0x4000)=nil}], './file0\x00'})


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000000)="e000000000000000", 0x8)
close(r0)


openat$zero(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000000)=[{0x14}, {0x15}, {0x6}]})
syz_emit_ethernet(0x66, &(0x7f0000000180)=ANY=[])
sysctl$machdep(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0x9, &(0x7f0000000040)="03000000", 0x4)
setsockopt(r0, 0x29, 0xa, &(0x7f0000000000)="ebffcbff2bb9fd812eaa4e710100000000000000", 0x4)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x9})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
writev(r0, &(0x7f0000000440)=[{&(0x7f0000000380)="190d", 0x2}], 0x1)
read(r1, &(0x7f00000007c0)=""/155, 0x9b)


syz_emit_ethernet(0x2a, &(0x7f0000000000)=ANY=[@ANYBLOB="00001c00ac14"])
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x3, 0x0)
connect$unix(r0, &(0x7f0000000000), 0x10)
sendmsg$unix(r0, &(0x7f0000001800)={0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1}, 0x0)


sendmsg$unix(0xffffffffffffffff, &(0x7f0000001600)={0x0, 0x0, 0x0, 0x0, &(0x7f0000002c40)=ANY=[@ANYBLOB="10000000ffff000001"], 0x10}, 0x0)
socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
sendmmsg(r0, &(0x7f0000001440)={0x0}, 0x10, 0x0)
shutdown(r1, 0x0)


socketpair$unix(0x1, 0x5, 0x0, &(0x7f0000000040)={<r0=>0xffffffffffffffff})
getsockopt$sock_cred(r0, 0xffff, 0x1022, &(0x7f0000000140)={0x0, 0x0, <r1=>0x0}, &(0x7f0000000200)=0xc)
setreuid(0xee00, 0x0)
r2 = getuid()
setreuid(0xee00, r2)
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, r1}})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x4e}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000180)=0x66, 0x0, 0x27)


setrlimit(0x8, &(0x7f0000000980))
socket$inet(0x18, 0x3, 0x102)


openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x2, &(0x7f00000000c0)=[{}, {0x1, 0x0, 0x0, 0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x37}, 0x4, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x10, 0x0, 0x2e)


mknod(&(0x7f0000000200)='./file0\x00', 0x2008, 0x412dff)
r0 = socket(0x2, 0x1, 0x0)
r1 = dup(r0)
listen(r1, 0x0)
getpid()
getgroups(0x0, 0x0)
mknod$loop(&(0x7f0000000240)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x40, 0x1)
rename(&(0x7f0000000200)='./file0\x00', &(0x7f0000000f40)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
getsockopt$SO_PEERCRED(r1, 0xffff, 0x1022, &(0x7f0000000140), 0xc)
seteuid(0xffffffffffffffff)
r2 = getppid()
pipe(&(0x7f00000001c0)={<r3=>0xffffffffffffffff})
fcntl$setown(r3, 0x6, r2)
ioctl$WSKBDIO_GETMAP(r3, 0x80047476, &(0x7f0000000100)={0x0, 0x0})
socket$inet(0x2, 0x1, 0xff)
socketpair$unix(0x1, 0x0, 0x0, &(0x7f0000000040))
socket$inet(0x18, 0x3, 0x102)
getsockopt(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0)
kqueue()
kevent(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
socket(0x0, 0x4000, 0x0)
openat$wsmouse(0xffffffffffffff9c, 0x0, 0x8981, 0x0)
openat$tty(0xffffffffffffff9c, &(0x7f0000000040), 0x400, 0x0)
ioctl$TIOCSETVERAUTH(0xffffffffffffffff, 0x8004741c, &(0x7f0000000080)=0x2)
r4 = semget$private(0x0, 0x1, 0x8a)
semctl$SETALL(r4, 0x0, 0x9, 0x0)
semop(r4, 0x0, 0x0)
semctl$GETALL(r4, 0x0, 0x6, &(0x7f00000004c0)=""/195)
r5 = openat$vnd(0xffffffffffffff9c, &(0x7f0000000080), 0x200, 0x0)
ioctl$VNDIOCSET(r5, 0xc0384600, &(0x7f0000000000)={&(0x7f00000000c0)='./file0\x00', 0xcd, 0x0})


r0 = kqueue()
kevent(r0, &(0x7f0000000280)=[{{r0}, 0xffffffffffffffff, 0xf5}], 0x7f, 0x0, 0x0, 0x0)
r1 = open$dir(&(0x7f0000000140)='.\x00', 0x0, 0x0)
kevent(0xffffffffffffffff, 0x0, 0x0, &(0x7f00000001c0)=[{{r1}, 0xfffffffffffffffe, 0x41}], 0x0, 0x0)
kevent(0xffffffffffffff9c, 0x0, 0x0, &(0x7f0000000080)=[{{r0}, 0xffffffffffffffff, 0x88}], 0x0, 0x0)
kevent(r0, &(0x7f0000000000), 0x400, 0x0, 0xdb74, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000a, &(0x7f0000000000)="ea00005c00000000", 0x1)
setsockopt$inet_opts(r0, 0x0, 0xb, &(0x7f00000000c0), 0x0)


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
r0 = open(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
ioctl$FIONBIO(r0, 0x8004667e, &(0x7f0000000100))


open(&(0x7f0000000000)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`\x00', 0x200, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000300)={0x20000316, &(0x7f00000000c0)=[{}, {0x3}]})
sysctl$kern(&(0x7f00000000c0)={0x1, 0x3e}, 0x3, &(0x7f0000000100)="71f91e3471ac0058bc5a91501d94a34b8e5f84cf71b59c7afec37082", &(0x7f0000000080)=0x1, 0x0, 0x37)
r0 = semget$private(0x0, 0x1, 0x100)
semctl$SETALL(r0, 0x0, 0x9, &(0x7f0000000000)=[0x1, 0x4, 0x6529])
pwritev(0xffffffffffffffff, &(0x7f0000000080)=[{&(0x7f00000005c0)="dc", 0x1}], 0x1, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
r1 = open(0x0, 0x0, 0x0)
pread(0xffffffffffffffff, &(0x7f0000000040)="3cd15db7c30016", 0x50cc00, 0x0)
ioctl$WSDISPLAYIO_LSFONT(r1, 0xc058574e, &(0x7f0000000100))
sysctl$net_inet_udp(&(0x7f0000000000)={0x2, 0x4}, 0x2, 0x0, 0x0, 0x0, 0x0)
r2 = socket(0x18, 0x2, 0x0)
msgctl$IPC_STAT(0x0, 0x2, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, &(0x7f00000000c0)={0x0, 0x0, 0x83fe})
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
setsockopt(r2, 0x1000000029, 0x3e, &(0x7f0000000000)="674cd6e5", 0x4)
writev(r2, &(0x7f0000000080)=[{0x0}], 0x1)
r3 = openat$diskmap(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$DIOCMAP(r3, 0xc0106477, &(0x7f0000000080)={&(0x7f0000000040)='\x13\x13w\xc5\xfc5\xd4\x14T\xd5\xd4\x1d)\xad\x1a`\x00', r3})


ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x2, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x462, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
write(r1, &(0x7f0000000140)="7f", 0x1)


syz_emit_ethernet(0x2e, &(0x7f0000000080)=ANY=[@ANYBLOB="ed0800000089ffffff1d00000900460000200000000000019078ac1400bbe000000283030000c688ccc808009078"])
sysctl$hw(&(0x7f0000000000)={0x6, 0x11}, 0x2, &(0x7f0000000080)="51469813e77ff95e93854304d69fb025ba4e3e9c22c04c2cceed78f24181c16fe7d8b2c1d2ea86659e673d7b1f", &(0x7f0000001080)=0x2d, 0x0, 0x0)
mkdir(&(0x7f0000000040)='./file0\x00', 0x0)
chdir(&(0x7f0000000140)='./file0\x00')
unveil(&(0x7f0000000000)='./file0\x00', &(0x7f0000000080)='x\x00')
open(&(0x7f0000000100)='.\x00', 0x200, 0x0)
openat$wsmuxkbd(0xffffffffffffff9c, &(0x7f0000000440), 0x1, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
bind(0xffffffffffffffff, &(0x7f00000002c0), 0xa)
connect$unix(0xffffffffffffffff, &(0x7f0000000000)=@file={0x0, './file0\x00'}, 0xa)
mkdir(0x0, 0x0)
chmod(0x0, 0x21e)
chdir(&(0x7f0000000140)='./file0\x00')
symlink(&(0x7f0000000200)='./file2\x00', &(0x7f0000000340)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00')
open(&(0x7f0000000880)='./file0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x00', 0x80000000000206, 0x166)
r0 = semget$private(0x0, 0x7, 0x3c0)
semop(r0, 0x0, 0x0)
rename(0x0, &(0x7f0000000080)='./file0\x00')
semop(r0, &(0x7f0000000280)=[{}], 0x1)


r0 = socket(0x11, 0x3, 0x0)
sendto$unix(r0, &(0x7f0000000000)="b1000504600000000000000007000000331c13fecea10500fef9ed06c72fd3357ae320b37b673039d2d236073705ae04be38164991f7accf5f882b297be1aa5b236deb51e2f0ac3ebbc257699a5f139b672f4d335d223e7d029d6ba8cc630037282102000000720f70c1f5a472c881ea6e69e0bb76d907c400000200361b1257aea8c5000020020000000000008abf09090080fdfed8dcfad700"/177, 0xb1, 0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000000)=[{0x20}, {0x84}, {0x8106}]})
syz_emit_ethernet(0x22, &(0x7f0000000300)={@local, @empty, [], {@ipv4={0x800, {{0x5, 0x4, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, @remote={0xac, 0x14, 0x0}, @broadcast}}}}})


writev(0xffffffffffffffff, &(0x7f0000000240)=[{&(0x7f0000000140)='\x00', 0x1}], 0x1)
r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x9, &(0x7f0000000240)="ea00000100000000", 0xc)
r1 = socket$inet(0x2, 0x2, 0x0)
dup2(r0, r1)
setsockopt$inet_opts(r1, 0x0, 0xc, 0x0, 0x0)


ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f0000000400)={0x0, &(0x7f00000003c0)})
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000200)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
write(r0, &(0x7f0000000040)="ed", 0x1)
recvmmsg(r1, &(0x7f0000000880)={&(0x7f0000000840)={0x0, 0x0, &(0x7f0000000ac0)=[{&(0x7f0000000240)=""/217, 0xd9}], 0x1, 0x0}}, 0x10, 0x1060, 0x0)
shutdown(r1, 0x0)
close(r0)


setrlimit(0x8, &(0x7f0000000040)={0x7, 0x50})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETAW(r1, 0x802c7415, &(0x7f0000000000)={0x29f57365, 0x0, 0xa7c, 0xffffffff, "8b030003000100787d902b56d864d3c3a3f4d3c9"})
poll(&(0x7f0000000080)=[{r0, 0x1}], 0x1, 0x800)
writev(r0, &(0x7f0000000140)=[{&(0x7f0000000480)="5c12ec1a55e981f2e975d2276e1215c1d75d4f6968fd76f1b6711d89eb56e866d9190e76db008ff46190e213e84c0689c9762be88e3de2a2d3585c09c114ed15607bdda6e2b99a8f2a460a1706a0893af4ff6c29710336ed8396db928a10b4e8f6549862ffb4a3d3fd292b843d6d1b64", 0x70}], 0x1)


r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x4ebfac6bbaf7959)
writev(r0, &(0x7f0000000100)=[{&(0x7f0000000000)='#!', 0x2}], 0x1)
syz_emit_ethernet(0x17a, &(0x7f0000000380)=ANY=[@ANYBLOB="bce90b8d795800000000000081c70dce6a401e594e457ec4a280a2691e47ade5fad32446000288189e4410fa31ffffffff0000001f2001fff7b306000002090144e9b59cac1400ff"])
syz_extract_tcp_res(&(0x7f0000000000), 0xc0000000, 0x6)
r1 = socket(0x2, 0x2, 0x0)
connect$unix(r1, &(0x7f0000000300)=@file={0x1}, 0x2)
r2 = semget$private(0x0, 0x7, 0x3c0)
semop(r2, &(0x7f0000000180)=[{0x0, 0x43, 0x1800}, {0x4, 0xe6, 0x1800}, {0x0, 0xfd, 0x1000}, {0x1, 0x20, 0x1800}, {0x2, 0x5, 0x1800}, {0x4, 0x9e, 0x1000}, {0x2, 0xfffb, 0x1000}, {0x0, 0x40, 0x1000}, {0x3, 0x8, 0x1000}], 0x9)
getsockopt$SO_PEERCRED(r1, 0xffff, 0x1022, &(0x7f0000000200)={0x0, <r3=>0x0, <r4=>0x0}, 0xc)
semctl$IPC_SET(r2, 0x0, 0x1, &(0x7f0000000240)={{0x8001, 0xffffffffffffffff, r4, 0xffffffffffffffff, 0x0, 0x40, 0x2}, 0x0, 0x9, 0xe7})
setsockopt$sock_int(r1, 0xffff, 0x20, &(0x7f0000000080)=0xff, 0x4)
r5 = socket(0x11, 0x3, 0x0)
sendto$unix(r5, &(0x7f0000000000)="b10005040000000000000000070000001a5113fecea10500fef96ecfc72fd3357a89583535673039d2d236acf20b7804be38164991f7c8cf5f882b2900e1aa5b23edebc8ef99a8ad491726fa8251e2f0ac3ebbc2feb3fda1139b672f4d3353eb06acdb35a069d7080000000000000000008904000000000022830cf41bed66f4f365ccdcf3e4999d9d20002002c5dbfad800ff0f00"/177, 0xb1, 0x0, 0x0, 0x0)
r6 = accept$unix(r1, &(0x7f0000000a40), &(0x7f0000000140)=0x65)
accept(r6, &(0x7f0000000180)=@in6, &(0x7f00000001c0)=0xc)
r7 = geteuid()
semctl$IPC_SET(0xffffffffffffffff, 0x0, 0x1, &(0x7f00000000c0)={{0x0, 0x0, 0x0, r7}})
r8 = getegid()
semctl$IPC_SET(0x0, 0x0, 0x1, &(0x7f0000000140)={{0x3, r7, 0x0, 0x0, r8, 0x134, 0x100}, 0x0, 0x1648})
getsockopt$SO_PEERCRED(r1, 0xffff, 0x1022, &(0x7f0000000a00)={0x0, 0x0, <r9=>0x0}, 0xc)
semctl$IPC_SET(r2, 0x0, 0x1, &(0x7f0000000240)={{0x1ff, r7, 0x0, 0x0, r9, 0x90, 0x9}, 0x8, 0x8, 0x5})
chown(&(0x7f00000002c0)='./file0\x00', r3, r9)
socketpair(0x6, 0x1, 0x0, &(0x7f0000000040))
write(r1, &(0x7f0000000400)="06db92cb2bc71bc021ddc28fd02e4310164d6d6e56f0374d591d51840492ae80b6734760f8949793f5ff925e0add46df00000000000000ed2d2d53ff016fd1967aa38c840ab15e80ffed6ac4c0f97663716a21e7d96807fc320828a79b579a5759d1585d07fc4a7f7fd721a6040f186fce37121a7ff6b505fa92a82523596d8c527e2c5f34239a59a7a05dbf06b3c173ca5011f274f29841382a51065d17a62711964cdb5839dfdf821b7f75525bca0ea85058c83f41c530d6f42ea7dc8b3910a88ca185a8d8180b85f9b2c93d622e066efa03282d37a783649f764030787e5a7012df6796b02f1efbed0e01552f24f85e17be12ae9007e26ae91aa5a5e7469787f132ca0905531c300222e9d171f44d6e60cdd25f853b3a119bbb2ff949b3a2bbd4b4cc18a5f2f94fcc6bf35641a0099a464e27197b081c626bf0ea399f1fd489787c85152bb15a38cbf15238311e0848e5b9812af4c82c62d87ee884abda4f725d0f96800345dd4c069762b1436f621f482589fb0ab042ca836dc7e6e8d1de427e31161819ec257ca878ffbd4b3c86738c35b9ad49063ec8e0e0394e6b5771abc19d37064e47d972693903c7dddfcabf9ac88983fcb9af32fde20d956184fde6af1cce696f0da59bf3c9b5f37d71b1be8ea56e06af8b56a4610f0a526b914980fa95d6d2b9bcac721989e85415da2c171f14863ba291c5d9d609656f9941b2c55ed249f4eb8e5fe072e0d81b266ca69e1e9799c56a5776208ea4d5df1920da6a514f77e070a84fd1541c0a37fcc8601bf9707af463edf2f1fdd70b1d365e79101ccbb00026e57566b66291fb5db9e33309d879f48027a7bb2099ca62dced24e3dbb0e44845b5ea0a24684f16c7bcf19de0cc6687b7509ffb9e8a9cf560c426d666a91e1e929ea6425de177a52cc75a256f92383a313f1953cfa7796e8fe1b729ff11406a0bca052b32a4a133c4cfc8dbcca976a00d4b7ae19b11d55a6235399b17f8d085ce7b398754a3e71caed15234f8c99cc51f7408384418ec0f6009c42feaeed992a00833f7022116bd14de5b9992ed09c96afaf5d6c31fe600fa3cecc364fb6dc01a8213e1594c5cc039a7ea031d26118ab91c64530f19bc64543615333fa34072dd75dc70d357e2370e208fd56e7a7daf87f30dee48944d83b5563872fb61072a2381e9e000fe2c3a422ebd90ce2e7a4107094f5f805c077841f540d465d3e17e479d57a9de0a6b3c56295c85b0ad1069837fc785c6546298c96a77c651ade40c7ab1a06c6791e1de95695e6c248dc39927af011232471b17c40151d2a2f5a763eb8b78e44422e0ab8d982a9ce2813b3533382cdeaa1b284d0d144126eb622979e6ea988079fec319cac45481c1a1f3db361146bcf41b8acfee8d13d1660ee1b5b144f0b0b043d6374ce77d5165a49b2399ded113d83c6f8114868a1d37c9f35811446d5f10c7e7c4dfc4fc878ced7f6979cab411c366e2be44378d991fec8f80985fb7581cc50d3ad506f4a3d8aea9effe341a3e80ddaa4dc857a0896a444c366c3466267830e8635de26e5887819ca9bce95bbfe9656dc57cf5f41b62182265cf67eac14058782de4e7945e6cff994bd5bebee64eb3e9855c3094aed5288d8012d3501ba2d08b5f612a867137cba147f96ca29d4372af173c0e7a7a38d58dea7e9d15b774c34279d0a7345aab1be9288a9247997e0f84bc99b27b054dc7c980ea1e425147f931f009ffb122f252eae1c985e6360a16f323ddf09bbb2bdfc08679dc53a39e6cc0b79648b282639e4913f5cb98c0582ab2661903107d62a60ea6ed9f0903b8796f3451dd6156c6ad6a00a38b260870e5214af91860147f5c734de5b25108b5aa83908f976c8662bbb2aef5a097fc7109d46d439a35df91b2414af8322c1c5f969bbe2c24f13376740eb731610a29465f30e3a049a5d253f442b72cd0cab40c4626a76d66f8124174a2dc8234bafadbfcbdcc63f91ad402ac7276c1b22e913e30ebf8a5ec06022952d7157420c298b0ef5441b5999d81d23ef6c5c8e24ca39b70adf246fa9f49a9b21695f3cefd95147b3c846e107c99", 0x5c1)
read(r0, &(0x7f0000000180)=""/162, 0xa2)
write(r0, &(0x7f0000000040)='\t', 0x1)
write(r0, &(0x7f00000004c0)="09eb00000db57c60c001267f5d5e8ee581e12aaa95ab10eba007a90172c84c838b4278ad535c2a591c97413f308cbbaee481ca7f31dbd1562ef7a6540a", 0x3d)
close(r0)
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{0x4}, {0x1}, {0x8186}]})
syz_emit_ethernet(0x4e, &(0x7f0000001540)=ANY=[])


mkdir(&(0x7f0000000000)='./file0\x00', 0x0)
chmod(&(0x7f0000000180)='./file0\x00', 0x23f)
chdir(&(0x7f00000001c0)='./file0\x00')
mknod$loop(&(0x7f00000000c0)='./file2\x00', 0x6000, 0x0)
rmdir(&(0x7f0000000300)='./file2\x00')


r0 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
write(r0, &(0x7f0000000500)="5429102bb15d3d2145f713a5bb02fc8801121b8d2117cbc1f045d9385a2ad3a7b5c5a3e1fef0e412d92882d53acc5fa16cacabb889054ef0155fdd5b9f583ce3d6d3a62ebab52329fc904ba46a45626f53c72ac1a4a94b1c13edc18d71acc6aae76f77cd134d981340b488138e38a031323e3758e12321705826acc2c7889d7c44d98630db3843bc3d9cdc525d6da59e109c19b3050da712c1c43449b3b47a73ecaa31908d5e826810b8d1d94d76ef28b930e5b8b2bc691ed3ba07028c4385eb21b83164fd23bec76433eb3276fe6467077c4bd55c814d0b15bc8f412d", 0xdd)
execve(0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
preadv(0xffffffffffffffff, 0x0, 0x0, 0x0)


sysctl$net_inet_tcp(&(0x7f0000000800)={0x4, 0x2, 0x6, 0x19}, 0x4, &(0x7f0000000840), 0x0, &(0x7f00000008c0), 0x0)


setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
r0 = syz_open_pts()
close(r0)
r1 = syz_open_pts()
ioctl$TIOCSETA(r1, 0x802c7414, &(0x7f0000000240)={0x0, 0x0, 0xffffdffc, 0xfffffff7, "bfff0d000300ef01016500690200000000000400"})
writev(r0, &(0x7f0000000480)=[{&(0x7f0000000440)="ff", 0x1}, {&(0x7f00000009c0)="7208d2879d7ae4e2eb75ba85b9a88add94ebeb1b2608c200150214c90d", 0x1d}], 0x2)
readv(r1, &(0x7f0000000140)=[{&(0x7f0000000000)=""/201, 0xc9}], 0x1)


sysctl$net_inet_ah(&(0x7f0000000000)={0x4, 0x2, 0x33, 0x3}, 0x4, &(0x7f0000000040), 0x0, 0x0, 0x0)
ioctl$WSDISPLAYIO_LSFONT(0xffffffffffffffff, 0xc058574e, 0x0)
sysctl$net_inet_ah(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
msgget(0x2, 0x0)
msgsnd(0x0, 0x0, 0xcf, 0x0)
socket(0x0, 0x0, 0x0)
sendto$unix(0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0, 0x0)
getpeername(0xffffffffffffffff, 0x0, 0x0)
getppid()
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000001c0)={0x2000000000000243, &(0x7f0000000100)})
r0 = socket(0x1, 0x1, 0x0)
ioctl$FIONREAD(r0, 0xc0106924, &(0x7f00000001c0))
setsockopt$sock_int(r0, 0xffff, 0x1004, &(0x7f0000000100)=0x20000, 0x4)
write(0xffffffffffffffff, &(0x7f0000001680), 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000040)={0xffffffffffffffff, <r1=>0xffffffffffffffff})
close(r1)
r2 = socket(0x18, 0x2, 0x0)
readv(0xffffffffffffffff, &(0x7f0000000100)=[{&(0x7f0000000240)=""/61, 0x3d}], 0x1)
connect$unix(r2, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
sendmsg(r1, &(0x7f00000003c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000100)=ANY=[@ANYBLOB="1400000029"], 0x3e}, 0x0)


r0 = socket(0x18, 0x2, 0x0)
setsockopt(r0, 0x1000000000029, 0xa, &(0x7f0000000000)='\x00\x00\x00\x00', 0x4)
setsockopt(r0, 0x1000000000029, 0xa, 0x0, 0x0)


r0 = open(&(0x7f0000000480)='./file0\x00', 0x80000000000206, 0x0)
write(0xffffffffffffffff, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
ioctl$SPKRTUNE(r0, 0x20005302, &(0x7f0000000100))
ioctl$BIOCSETIF(r1, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000180)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000340)=[{0x7c}, {0x0, 0x0, 0x0, 0x81}, {0x812e}]})
syz_emit_ethernet(0x4a, &(0x7f0000000280)=ANY=[])
ioctl$BIOCSETF(r1, 0x80104267, &(0x7f0000000200)={0x3, &(0x7f0000000040)=[{0x34, 0x0, 0x0, 0x20000000}, {0x84}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000100)=ANY=[])
writev(0xffffffffffffffff, &(0x7f00000002c0)=[{0x0}, {&(0x7f0000000300)="092060000152c9f100", 0x9}], 0x2)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
r3 = socket(0x18, 0x1, 0x0)
ioctl$FIONREAD(r3, 0x8060693d, &(0x7f00000001c0))
execve(&(0x7f0000000140)='./file0\x00', 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000480), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000080)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000140)={0x3, &(0x7f0000000040)=[{0x80}, {0x4}, {0x46}]})
syz_emit_ethernet(0x3e, &(0x7f0000000180)=ANY=[])


mknod(&(0x7f0000000000)='./file0\x00', 0x6000, 0xe02)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
close(r0)


r0 = socket(0x1, 0x2, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
getsockopt$sock_int(r0, 0xffff, 0x1, &(0x7f0000000200), &(0x7f0000000000)=0x4)


r0 = open$dir(&(0x7f0000000040)='./file0\x00', 0xae828e137847f62, 0x0)
setrlimit(0x1, &(0x7f0000000000)={0xfffffffffffffffd, 0xffffffffffffffff})
ftruncate(r0, 0x40040000000000)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000440), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000000c0)={0x6, &(0x7f0000000340)=[{0x25, 0x0, 0x3}, {}, {}, {}, {0x24}, {0x6}]})
write(r0, &(0x7f0000000200)="d81ad3d20cf7eb4e9be33bbd1a30", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x1, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f00000001c0)={0x3, &(0x7f0000000080)=[{0x1d}, {0x45}, {0x6, 0x0, 0x0, 0x42}]})
write(r0, &(0x7f0000000280)="ce4aa4a25043cb02aadf8701f131", 0xe)


r0 = socket(0x11, 0x3, 0x0)
setsockopt$sock_int(r0, 0xffff, 0x1001, &(0x7f0000000b00), 0x4)
sendmsg(r0, &(0x7f00000004c0)={0x0, 0x0, 0x0, 0x0, &(0x7f0000000f80)=[{0x10}], 0x10}, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000180), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000040)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000003c0)={0x3, &(0x7f0000000140)=[{0x28}, {0x40}, {0x40e}]})
syz_emit_ethernet(0xe, &(0x7f0000000100)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000000)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000240)=[{0x14}, {0x4}, {0x6}]})
syz_emit_ethernet(0x103e, &(0x7f0000001980)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000001340)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000240)={0x3, &(0x7f0000000140)=[{0x30}, {0x60}, {0x8106}]})
syz_emit_ethernet(0x138, &(0x7f0000000300)=ANY=[])


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, 0x0)
open(0x0, 0x0, 0x0)
munmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000)
shmget$private(0x0, 0x3000, 0x0, &(0x7f0000002000/0x3000)=nil)
setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)
madvise(&(0x7f0000000000/0x3000)=nil, 0x3000, 0x6)


open$dir(&(0x7f0000000000)='./file0\x00', 0x200, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x3, 0x5012, 0xffffffffffffffff, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000140)={<r0=>0xffffffffffffffff})
recvmmsg(r0, &(0x7f0000000480)={0x0}, 0x10, 0x0, &(0x7f0000000500)={0x2007fffc, 0xa})
r1 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
r2 = open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
writev(r2, &(0x7f0000000340)=[{&(0x7f0000000000), 0x2cfea}], 0x1000000000000013)
mmap(&(0x7f0000000000/0x200000)=nil, 0x200000, 0x0, 0x10, r1, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000100), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f00000000c0)={'tap', 0x0})
ioctl$BIOCSHDRCMPLT(r0, 0x80044275, &(0x7f0000000180)=0x1)
write(r0, &(0x7f00000001c0)="d9537abde93d050cdd16b13f742a", 0xe)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x0, 0x0)
ktrace(0x0, 0x0, 0x0, 0x0)
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000240)={0x2, &(0x7f0000000180)=[{0x2d, 0x0, 0x6}, {}]})
r1 = socket(0x18, 0x1, 0x0)
setsockopt(r1, 0x1000000029, 0x31, &(0x7f00000000c0)="b2116988b272d2dd3dc90142a84231a746e337b372e93320cff6669cbe7879de45ed3fc33719ca6dd678cec8a918458b2c10a1f8c66653b276e180e9cb9b21f9982230f575295d48889c9a920796b2dd92fc8575680b37ba955d2c15e6034b7daeb2273e89771aed96271a22d7c9198ed900ab006ddfb67869b51a2216114d1ece00"/144, 0x90)
ioctl$BIOCSDIRFILT(r0, 0x8004427d, &(0x7f0000000200)=0x6)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, &(0x7f00000001c0)={'tap', 0x0})
socket(0x2, 0x2, 0x0)
socket(0x18, 0x2, 0x0)
sysctl$hw(0x0, 0x0, &(0x7f00000004c0)="001f03989dd49060e8", 0x0, 0x0, 0x0)
ioctl$WSMOUSEIO_SETPARAMS(0xffffffffffffffff, 0x80105728, &(0x7f0000000040)={&(0x7f0000000000)=[{}], 0x1})
sysctl$kern(&(0x7f0000000040)={0x1, 0x59}, 0x3, 0x0, 0x0, &(0x7f0000000080)="4f1d4c6344b80ed788b6a4515248df3aa745bb992c574ab4cdf5587145812eab4a988f7fafd7a01d99776d988908cd186b51f34f8c15ffa0c685ad4116c783959eff4278384b4000384dbb1c2aaeff10b4135529a1da6fda67c67469d954be811b25ec5521559154c586eefff122009f659cd3e27e98a3241495005f102d9101d158284c0ee3250aa7c11042330de22a299ab00894fdc9bac6042d", 0xfffffc56)
setrlimit(0x8, &(0x7f0000000980)={0x42, 0x62})
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f0000000040)={0x0, 0x0})
msgctl$IPC_SET(0x0, 0x1, &(0x7f0000000080)={{0x0, 0x0, 0x0, 0x0, 0x0, 0x30}, 0x0, 0x0, 0x0, 0x0, 0x8000000000000000})
r2 = socket(0x800000018, 0x1, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1000, &(0x7f0000000000)=0x1, 0x4)
bind$unix(r2, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
r3 = socket(0x18, 0x2, 0x0)
close(r3)
r4 = socket(0x800000018, 0x1, 0x0)
ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000080)={0x0, 0x0, 0x0, 0x0, "1a1116f0d0f700"})
setsockopt$sock_int(r4, 0xffff, 0x1000, &(0x7f0000000000)=0x7, 0x4)
bind$unix(r4, &(0x7f0000000080)=@abs={0x1f95d27d48731892, 0x7}, 0x1c)
connect$unix(r3, &(0x7f00000000c0)=@abs={0x682eb13985c518e6, 0x7}, 0x1c)
setsockopt(r1, 0x1000000029, 0x31, &(0x7f00000000c0)="b2116988b272d2dd3dc90142a84231a746e337b372e93320cff6669cbe7879de45ed3fc33719ca6dd678cec8a918458b2c10a1f8c66653b276e180e9cb9b21f9982230f575295d48889c9a920796b2dd92fc8575680b37ba955d2c15e6034b7daeb2273e89771aed96271a22d7c9198ed900ab006ddfb67869b51a2216114d1ece00"/144, 0x90)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000002880)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000680)={0x3, &(0x7f0000000080)=[{0x4}, {0x34, 0x0, 0x0, 0x3}, {0x8106}]})
syz_emit_ethernet(0x3e, &(0x7f0000000040)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000300)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000180)={0x3, &(0x7f0000000240)=[{0x2}, {0x4d}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000280)=ANY=[])


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000040), 0x462, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000240)={'tap', 0x0})
ioctl$BIOCSETWF(r0, 0x80104277, &(0x7f0000000000)={0x3, &(0x7f0000000080)=[{}, {0x64, 0x0, 0xdf}, {0x4000006, 0x0, 0x0, 0x7f}]})
mknod$loop(0x0, 0x2000, 0x1)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
sysctl$hw(0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
write(r0, &(0x7f00000002c0)="c5449bc1708e16b9805a099e20a0", 0xe)


ioctl$TIOCSETA(0xffffffffffffffff, 0x802c7414, &(0x7f0000000040)={0x0, 0x0, 0x4, 0x0, "0100012d29fb000700000000098002005a00"})
sysctl$kern(&(0x7f0000000040)={0x1, 0x45}, 0x3, &(0x7f0000000180)="3bf2ee74e747c82dad6eb2a36fa755e1a3925fe49afca7e63b52fa65ccaa74d6e6b85b6cdced70357ef201f97842b10689ca31553fa2d7031f38c03e56ad0e24dfc4f97b8b7f81499647e6e7725765d61436c85e43c15d12a78cb8c57ddde87021d7b685507fd3e0652f35e45bdaa3afd86c4fe557433e4c2b632de71c951516adff26aa2e48b45f8ce92bcefd3eceefabee7e3ebe806fdb4f6af569ae94b5d12727b1e1d0cc45c7ebd5df53fb588fd0245528fe5700a5868eaf74d373197fb657a56e99cdbddbb382ad676b756d4e8b5a81c9a624348f23ffd260bf5fd344a7a30bcf96e47800acc166910bfc34ce76252dd12fac3b10dd5719aa6e420f60e3d2cbb22f5b3a6f7fa3c909e4823cdc0cdf126bc29456035b9a44ff74d852ba5c", &(0x7f0000000080), &(0x7f0000000340)="5a67923ef0cb189971421989ebcff78831a7581e2f27caa362f1363042efb27688b2c899220fb2fe37e467d974592496856ca7b78060998608c2f952e43bc0bf11555cc5cb0fe17b2ec1be389871829bfe10dd4c4d2c8f9da2bd2868fd86791dc09dc4fa89a217458bdaed31003fdc3a7323189ba3ccbad6c8af17516e4557f61ad20180000000000000125f568ca7d3396b9057255f381855110eb3a673713716cdf010ddfa7977f92cf061ad125ca670353b45d53aae196b00271f9d3452b523b3dea22d6027625614312183724b71c7eb02083a410c1c99fa455013521f98686e472b70b560f7021f567adf4d", 0xffffff25)


setrlimit(0x8, &(0x7f0000000980)={0x7, 0x54})
r0 = syz_open_pts()
close(r0)
syz_open_pts()
ioctl$TIOCSETA(r0, 0x802c7414, &(0x7f0000000040)={0x7fff, 0x0, 0x80000401, 0xffdfff8c, "495b727c6608000000ae0c08000000001000"})
writev(r0, &(0x7f00000003c0)=[{&(0x7f00000009c0)="471e49aab0fd752532784bf2515fa242320b4a6e6543ffda060eb842b843d370b936ddaa7f71a0a0c4074da827c862a93983c361dc12dc50305653dd84a6adfc8761f897b60c4dee402807473103485b4475c657ae5428aa89543eec1819c76b9eb1e5c1848e49a2a588ed0f6ac77d2106b8ed9b8e3bf7a033cdd96085e372fde5a0d0e2fa622a7e28febd0934ab925ca1", 0x91}], 0x1)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000140)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f00000001c0)={0x3, &(0x7f0000000280)=[{0x80}, {0x4d}, {0x6}]})
syz_emit_ethernet(0x36, &(0x7f0000000200)=ANY=[])


sysctl$vm_swapencrypt(&(0x7f0000000000)={0x2, 0x5, 0x3}, 0x3, &(0x7f0000000040), 0x0, 0x0, 0x0)
r0 = openat$vmm(0xffffffffffffff9c, &(0x7f0000000040), 0x40, 0x0)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
socket(0x0, 0x0, 0x0)
setsockopt$sock_int(0xffffffffffffffff, 0xffff, 0x0, 0x0, 0x0)
ioctl$BIOCSETF(0xffffffffffffffff, 0x80104267, &(0x7f00000000c0)={0x1, &(0x7f0000000080)=[{}]})
openat$null(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x4)
rename(&(0x7f0000000080)='./file0\x00', &(0x7f00000000c0)='./file0\x00')
mkdir(0x0, 0x0)
ioctl$VMM_IOC_CREATE(r0, 0xc2585601, &(0x7f0000000080)={0x10, 0xfffffffffffffffc, [{&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ffd000/0x3000)=nil, 0x1e}, {&(0x7f0000ffb000/0x3000)=nil, &(0x7f0000fed000/0x13000)=nil, 0x80}, {&(0x7f0000ffc000/0x3000)=nil, &(0x7f0000ff2000/0x4000)=nil, 0x5}, {&(0x7f0000ff4000/0xc000)=nil, &(0x7f0000ff8000/0x4000)=nil, 0xe7b6}, {&(0x7f0000fee000/0x4000)=nil, &(0x7f0000ffa000/0x2000)=nil, 0x7}, {&(0x7f0000ffc000/0x2000)=nil, &(0x7f0000ff2000/0x2000)=nil, 0x7}, {&(0x7f0000ffb000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil, 0x1}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ffc000/0x3000)=nil}, {&(0x7f0000ffe000/0x1000)=nil, &(0x7f0000ff4000/0x2000)=nil, 0x800}, {&(0x7f0000ffd000/0x3000)=nil, &(0x7f0000ffc000/0x2000)=nil}, {&(0x7f0000ffc000/0x4000)=nil, &(0x7f0000ff0000/0x3000)=nil, 0x1}, {&(0x7f0000fee000/0x2000)=nil, &(0x7f0000ff6000/0x3000)=nil, 0x8}, {&(0x7f0000ff4000/0x3000)=nil, &(0x7f0000fef000/0x1000)=nil}, {&(0x7f0000ff3000/0x4000)=nil, &(0x7f0000ff8000/0x1000)=nil, 0x7}, {&(0x7f0000ff5000/0x3000)=nil, &(0x7f0000ff3000/0x3000)=nil, 0x2}, {&(0x7f0000ff2000/0x4000)=nil, &(0x7f0000ff9000/0x1000)=nil, 0x5}], './file0\x00', 0x1da})
syz_open_pts()
flock(0xffffffffffffffff, 0x0)
syz_open_pts()
socket(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
semctl$IPC_SET(0x0, 0x0, 0x1, 0x0)
msgctl$IPC_SET(0x0, 0x1, 0x0)
open(&(0x7f0000000080)='./file1\x00', 0x200, 0x0)


open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
poll(&(0x7f0000000180)=[{r0, 0x1}], 0x1, 0x0)
r1 = syz_open_pts()
dup2(r1, r0)


setrlimit(0x6, &(0x7f00000000c0))
mlockall(0x1)
r0 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000500)={0x3, &(0x7f00000000c0)=[{0x87}, {0x7}, {0x8106}]})
syz_emit_ethernet(0x62, &(0x7f00000008c0)=ANY=[])
munmap(&(0x7f0000ffe000/0x1000)=nil, 0x1000)
r1 = openat$speaker(0xffffffffffffff9c, &(0x7f0000000080), 0x1, 0x0)
writev(r1, &(0x7f0000000040)=[{&(0x7f00000000c0)="000076e27510c96b2a311ffdc2bcd4e4d2509b4b509d580bf1dc3e8adf057469fcc034c39d55ea56399ba343104869a9d0be351abd330a6f3aab4056b799c635e712225300536b29a100e504e4fc0cf7362e07418a8c8d302fb3ff6049f9dc1d09a00864445838889d1c87a332462e2e", 0x70}, {&(0x7f0000000140)="d6", 0x1}], 0x2)
execve(0x0, 0x0, 0x0)


r0 = openat$bpf(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
ioctl$BIOCSETIF(r0, 0x8020426c, &(0x7f0000000680)={'tap', 0x0})
ioctl$BIOCSETF(r0, 0x80104267, &(0x7f0000000080)={0x3, &(0x7f0000000280)=[{0x74}, {0x5}, {0x26}]})
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[])


r0 = socket(0x11, 0x3, 0x0)
r1 = socket(0x11, 0x3, 0x0)
socket(0x11, 0x3, 0x0)
dup2(r1, r0)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={<r2=>0xffffffffffffffff})
sysctl$vfs_nfs(&(0x7f0000000040)={0x7, 0x4, 0x3559a5c56a6d9b4d}, 0x3, 0x0, 0x0, 0x0, 0x0)
mquery(&(0x7f0000ffe000/0x2000)=nil, 0x2000, 0x0, 0x0, r2, 0x0)
r3 = kqueue()
socket$inet(0x2, 0x2, 0x0)
kevent(r3, 0x0, 0x0, 0x0, 0x0, 0x0)
select(0xffffffffffffff83, &(0x7f0000000000)={0xfffffffffffffffd}, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, &(0x7f0000000000)=ANY=[@ANYBLOB="ff02"])
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r4 = socket(0x2, 0x3, 0x0)
connect$unix(r4, &(0x7f0000000000), 0x10)
sendmsg(r4, &(0x7f0000001ec0)={0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)


r0 = socket$inet6(0x18, 0x3, 0x0)
faccessat(0xffffffffffffffff, 0x0, 0x0, 0x0)
syz_emit_ethernet(0x138, 0x0)
mmap(&(0x7f0000000000/0x400000)=nil, 0x400000, 0x0, 0x10, 0xffffffffffffffff, 0x0)
r1 = open(&(0x7f0000000040)='./file0\x00', 0x70e, 0x0)
writev(r1, &(0x7f0000001580)=[{&(0x7f00000000c0)='\x00', 0xfffffeb0}], 0x1)
r2 = open$dir(&(0x7f00000000c0)='./file0\x00', 0x2, 0x0)
pwritev(r2, &(0x7f0000000080)=[{&(0x7f00000006c0), 0xf0f75}], 0x1, 0x0)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f0000000000)=@file={0x0, '\x00'}, 0x3)
sendto$unix(0xffffffffffffffff, &(0x7f00000000c0)="b1000502000000000000000007000000330002000000000000f96ecfc72fd3357ae320b37b673039d2d236acf20b7804be38164991f7c8cf5f882b297be1aa5b236de351e2f0ac3ebbc257699a5f139b672f4d335d223e7d02", 0x59, 0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
sendmsg$unix(0xffffffffffffffff, 0x0, 0x0)
open$dir(0x0, 0x0, 0x0)
socketpair$unix(0x1, 0x0, 0x0, 0x0)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc0106924, 0x0)
setitimer(0x1, 0x0, &(0x7f00000000c0))
kqueue()
kevent(0xffffffffffffffff, &(0x7f00000000c0), 0x0, &(0x7f0000000180), 0x0, 0x0)
r3 = socket(0x2, 0x2, 0x0)
ioctl$FIONREAD(r3, 0x80206916, &(0x7f00000001c0))
getsockopt(r0, 0x29, 0x3f, 0x0, 0x0)


setsockopt$inet_opts(0xffffffffffffffff, 0x0, 0x0, &(0x7f0000000040)="fd0cc085", 0x4)
mprotect(&(0x7f0000000000/0x800000)=nil, 0x800000, 0x5)
r0 = socket(0x2, 0x4001, 0x0)
r1 = dup(r0)
r2 = fcntl$dupfd(r1, 0x2, 0xffffffffffffffff)
close(r2)
socket(0x2, 0x2, 0x0)
setsockopt$sock_int(r2, 0xffff, 0x1023, &(0x7f0000000040), 0xe0)


socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={<r0=>0xffffffffffffffff, <r1=>0xffffffffffffffff})
bind$unix(r1, &(0x7f0000000040)=@file={0xd19450564dee018c, './file0\x00'}, 0xa)
connect$unix(r1, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
socketpair$unix(0x1, 0x2, 0x0, &(0x7f0000000100)={<r2=>0xffffffffffffffff, <r3=>0xffffffffffffffff})
connect$unix(r3, &(0x7f0000000000)=@file={0xd1653077bafa0114, './file0\x00'}, 0xa)
dup2(r2, r0)


r0 = semget$private(0x0, 0x1, 0x771)
sysctl$vm(&(0x7f0000000000)={0x6, 0xe}, 0x2, 0x0, 0x0, 0x0, 0x0)
r1 = openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
r2 = socket(0x18, 0x1, 0x0)
setsockopt(r2, 0x1000000029, 0xe, &(0x7f00000000c0), 0x0)
r3 = socket(0x18, 0x8001, 0x0)
setsockopt$sock_int(r3, 0xffff, 0x200, &(0x7f0000000000)=0x5, 0x4)
listen(r3, 0x0)
pread(r1, &(0x7f0000000040), 0x0, 0x6a08)
mknod(0x0, 0x3a0914c44f7b202d, 0x0)
connect$unix(0xffffffffffffffff, &(0x7f00000003c0), 0x10)
r4 = openat$vnd(0xffffffffffffff9c, &(0x7f00000000c0), 0x0, 0x0)
write(r3, &(0x7f0000000240)="25a99fbf493e6b7ae9dc4182d1026bade187a7be89cf552946d563431143152158a12f214a6e0c20e9a3421f30604d429b39d114790337a1fa745cc813283a583683b6426b6373d5edb3e7111a619129ebedcc0c2fc0cd282cc79305be11f6e191db897b0e373a7e262086e0c0c2102679bb7443d3b8d0baba7eba74cd3c403470796bf44e57278848c3d0f96c68323fbed4a0a3e2fc53a6196d11c5f0f529df35c83e4bf5698a8f53f62df2cdda65d6508622fa03918871f87c0944", 0xbc)
chroot(&(0x7f0000000000)='./file0\x00')
r5 = semget$private(0x0, 0x4, 0x90)
semctl$SETALL(r5, 0x0, 0x9, &(0x7f0000000040)=[0x7, 0x24, 0x7, 0x4])
semop(r5, &(0x7f00000000c0)=[{0x2, 0x2, 0x800}, {0x1, 0x65c6, 0x1000}, {0x2, 0x7ad, 0x1800}, {0x0, 0xffff}, {0x1, 0x8000, 0x800}, {}, {0x3, 0x81, 0x1400}], 0x7)
ioctl$VNDIOCGET(r4, 0xc4104603, &(0x7f0000000540)={'./file0\x00'})
dup(r4)
setsockopt$sock_int(r3, 0xffff, 0x0, &(0x7f0000000180)=0x7, 0x4)
r6 = openat$diskmap(0xffffffffffffff9c, 0x0, 0x0, 0x0)
dup2(r6, 0xffffffffffffffff)
mkdir(&(0x7f0000000200)='./file0\x00', 0x0)
syz_open_pts()
semctl$GETALL(r0, 0x0, 0x6, &(0x7f00000001c0)=""/101)


getpgid(0xffffffffffffffff)
fcntl$lock(0xffffffffffffffff, 0x0, 0x0)
connect$unix(0xffffffffffffffff, 0x0, 0x0)
syz_emit_ethernet(0x17a, 0x0)
syz_emit_ethernet(0x126f, 0x0)
ioctl$BIOCSETIF(0xffffffffffffffff, 0x8020426c, 0x0)
socket(0x10, 0x0, 0x0)
socket(0x4, 0x8000, 0x80)
sendmmsg(0xffffffffffffffff, 0xffffffffffffffff, 0x4a, 0x0)
ioctl$FIONREAD(0xffffffffffffffff, 0xc1206949, 0x0)
mknod(&(0x7f0000000000)='./file0\x00', 0x2000, 0x0)
open$dir(0x0, 0x0, 0x0)
ioctl$BIOCSETWF(0xffffffffffffffff, 0x80104277, &(0x7f00000002c0)={0x0, 0x0})
sysctl$kern(0x0, 0x4000000000000087, 0x0, 0x0, 0x0, 0x0)
open$dir(&(0x7f0000000000)='./file0\x00', 0x2, 0x0)
socket(0x18, 0x0, 0x0)
r0 = socket(0x18, 0x1, 0x0)
setsockopt(r0, 0x0, 0xa, &(0x7f0000000040)="03000000", 0x4)
r1 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r1, 0x0, 0x23, &(0x7f0000000240), 0x0)
setsockopt(r0, 0x1000000000029, 0xc, 0x0, 0x0)
mknodat(0xffffffffffffff9c, &(0x7f0000000100)='./file0\x00', 0x2000, 0xfffffff9)
execve(0x0, 0x0, 0x0)
r2 = open(&(0x7f0000000380)='./file0\x00', 0x0, 0x0)
ioctl$TIOCSETA(r2, 0x802c7414, &(0x7f00000001c0)={0x0, 0x0, 0x0, 0x0, "d88c1afa8797f9bdca0997f03e850100", 0x0, 0x7})


r0 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r0, 0x0, 0x200000000000c, &(0x7f0000000240)="ecaca5cae2000140", 0x8)
mknod(0x0, 0x0, 0x0)
open(0x0, 0x0, 0x0)
writev(0xffffffffffffffff, 0x0, 0x0)
setrlimit(0x0, 0x0)
syz_open_pts()
shmget$private(0x0, 0x3000, 0x4, &(0x7f0000ffb000/0x3000)=nil)
r1 = semget$private(0x0, 0x7, 0x3c0)
semop(r1, &(0x7f0000000180)=[{0x3, 0x43, 0x1800}, {0x1, 0xfffe, 0x1800}, {0x0, 0xfd, 0x1000}, {0x1, 0x20, 0x1800}, {0x2, 0x5, 0x1800}, {0x4, 0x9e}, {0x2, 0xfffb, 0x1000}, {0x0, 0x40, 0x3800}, {0x3, 0x8}], 0x9)
semctl$SETALL(r1, 0x0, 0x9, &(0x7f00000004c0)=[0x9, 0x1001])
semctl$IPC_SET(r1, 0x0, 0x1, &(0x7f0000000240)={{0x0, 0xffffffffffffffff, 0x0, 0xffffffffffffffff, 0x0, 0x0, 0x2}, 0x0, 0x2000000009, 0xe7})
semctl$GETNCNT(r1, 0x4, 0x3, &(0x7f0000000280)=""/108)
mprotect(&(0x7f00001bc000/0x1000)=nil, 0x1000, 0x5)
openat$bpf(0xffffffffffffff9c, 0x0, 0x0, 0x0)
ioctl$BIOCVERSION(0xffffffffffffffff, 0x40044271, 0x0)
r2 = openat$bpf(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
ioctl$BIOCSETIF(r2, 0x8020426c, &(0x7f0000000100)={'tap', 0x0})
ioctl$BIOCSETF(r2, 0x80104267, &(0x7f00000000c0)={0x3, &(0x7f0000000000)=[{0x5, 0x8}, {0x28}, {0x6}]})
syz_emit_ethernet(0x3e, &(0x7f0000000180)=ANY=[])
r3 = syz_open_pts()
sysctl$hw(&(0x7f0000000100)={0x6, 0x7}, 0x2, 0x0, 0x0, 0x0, 0x0)
ioctl$FIOASYNC(r3, 0x80047460, &(0x7f0000000000)=0x20)
r4 = socket$inet(0x2, 0x2, 0x0)
setsockopt$inet_opts(r4, 0x0, 0x200000000000c, &(0x7f0000000240)="ea00000100000000", 0xc)
ioctl$WSDISPLAYIO_DELSCREEN(0xffffffffffffffff, 0x80085754, 0x0)
r5 = shmget$private(0x0, 0x3000, 0x0, &(0x7f0000ffa000/0x3000)=nil)
shmctl$SHM_UNLOCK(r5, 0x4)
sendto$unix(0xffffffffffffffff, &(0x7f0000000140)="b1000504000004000000000007000000331c13fecea10500fef96ec0c72fd3357ae30200004e3039d2d236c7c04309b00c58bc4991ffc8cf5f882b297be1aa0500000051e2f0ad3ebbc257699a1f139b672f4d335c223e7d0c032bfa896443a421020000ed710fd18bfbb670c1f5a872c881ea6e2ec5890400000000008000361b1257aea8c500002002fbfe0c2300008abfba0900000008e371a3f8343732051ed6b71d89e0000405f8fffffe13000000", 0xb1, 0x4, 0x0, 0x0)
socketpair$unix(0x1, 0x1, 0x0, &(0x7f0000000100))


sendto$unix(0xffffffffffffffff, &(0x7f0000000000)="b1000504b10004000000000003000000331c", 0x12, 0x0, 0x0, 0x0)
sysctl$kern(&(0x7f0000000000)={0x1, 0x49}, 0x6, 0x0, 0x0, 0x0, 0x0)


mknod(&(0x7f0000000280)='./file0\x00', 0x1ffa, 0x0)
execve(0x0, 0x0, 0x0)
ktrace(&(0x7f0000000000)='./file0\x00', 0x0, 0x0, 0xffffffffffffffff)
execve(0x0, 0x0, 0x0)
r0 = open(&(0x7f0000000040)='./file0\x00', 0x0, 0x0)
poll(&(0x7f0000000180)=[{r0, 0x1}], 0x1, 0x0)


r0 = open(&(0x7f0000000100)='./file0\x00', 0x615, 0x0)
r1 = open(&(0x7f00000000c0)='./file0\x00', 0x205, 0x0)
fcntl$lock(r1, 0x9, &(0x7f0000000000)={0x0, 0x0, 0x0, 0x1000300010008})
dup2(r0, r1)
r2 = open(&(0x7f00000000c0)='./file0\x00', 0x0, 0x0)
mmap(&(0x7f0000000000/0x2000)=nil, 0x2000, 0x0, 0x10, r2, 0x0)
execve(0x0, 0x0, 0x0)


r0 = socket$inet(0x2, 0x2, 0x0)
getsockopt(r0, 0x0, 0x25, 0x0, 0x0)

m_pulldown20%of 36
m_tag_copy---of 4
m_tag_copy_chain24%of 13
m_tag_delete---of 7
m_tag_delete_chain75%of 4
m_tag_find40%of 5
m_tag_first---of 1
m_tag_get40%of 5
m_tag_init---of 1
m_tag_next---of 1
m_tag_prepend100%of 1
-----------
SUMMARY29%of 64
pfi_address_add---of 22
pfi_attach_ifgroup50%of 4
pfi_attach_ifnet50%of 4
pfi_clear_flags---of 24
pfi_detach_ifgroup50%of 4
pfi_detach_ifnet50%of 4
pfi_dynaddr_copyout---of 5
pfi_dynaddr_remove---of 6
pfi_dynaddr_setup---of 33
pfi_dynaddr_update---of 6
pfi_get_ifaces---of 15
pfi_group_addmember50%of 4
pfi_group_change---of 3
pfi_group_delmember50%of 4
pfi_if_compare---of 1
pfi_ifhead_RB_FIND---of 7
pfi_ifhead_RB_INSERT---of 8
pfi_ifhead_RB_INSERT_COLOR71%of 27
pfi_ifhead_RB_MINMAX---of 4
pfi_ifhead_RB_NEXT---of 9
pfi_ifhead_RB_NFIND---of 7
pfi_ifhead_RB_PREV---of 9
pfi_ifhead_RB_REMOVE71%of 17
pfi_ifhead_RB_REMOVE_COLOR36%of 56
pfi_initialize19%of 11
pfi_instance_add---of 45
pfi_kif_alloc---of 4
pfi_kif_find78%of 9
pfi_kif_free---of 8
pfi_kif_get57%of 16
pfi_kif_match---of 11
pfi_kif_ref---of 9
pfi_kif_unref14%of 29
pfi_kif_update42%of 12
pfi_kifaddr_update60%of 5
pfi_match_addr---of 8
pfi_set_flags---of 23
pfi_skip_if---of 13
pfi_table_update---of 8
pfi_unmask---of 9
pfi_update_status16%of 26
pfi_xcommit73%of 18
-----------
SUMMARY44%of 250
uao_create37%of 19
uao_detach63%of 16
uao_dropswap50%of 4
uao_dropswap_range29%of 28
uao_find_swslot---of 7
uao_flush48%of 23
uao_get25%of 40
uao_init---of 1
uao_pagein_page---of 7
uao_reference100%of 3
uao_set_swslot20%of 21
uao_swap_off---of 38
-----------
SUMMARY36%of 154
filt_videodetach---of 1
filt_videoread---of 1
video_attach_mi---of 1
video_claim---of 3
video_intr---of 5
video_stop---of 3
video_submatch---of 1
videoactivate---of 3
videoattach---of 5
videoclose---of 3
videodetach---of 5
videoioctl---of 58
videokqfilter---of 12
videommap---of 9
videoopen25%of 8
videoprint---of 3
videoprobe---of 1
videoread---of 17
-----------
SUMMARY25%of 8
drm_fault---of 7
drm_flush---of 1
drm_gem_close_ioctl---of 3
drm_gem_create_mmap_offset---of 1
drm_gem_create_mmap_offset_size---of 1
drm_gem_dma_resv_wait---of 5
drm_gem_dumb_map_offset---of 8
drm_gem_evict---of 4
drm_gem_flink_ioctl---of 10
drm_gem_free_mmap_offset---of 1
drm_gem_get_pages---of 1
drm_gem_handle_create---of 1
drm_gem_handle_create_tail---of 10
drm_gem_handle_delete---of 4
drm_gem_init---of 3
drm_gem_init_release---of 1
drm_gem_lock_reservations---of 33
drm_gem_lru_init---of 1
drm_gem_lru_move_tail---of 4
drm_gem_lru_move_tail_locked---of 4
drm_gem_lru_remove---of 4
drm_gem_lru_scan---of 27
drm_gem_mmap---of 21
drm_gem_mmap_obj---of 10
drm_gem_object_free---of 3
drm_gem_object_handle_put_unlocked---of 10
drm_gem_object_init---of 8
drm_gem_object_lookup---of 3
drm_gem_object_release---of 10
drm_gem_object_release_handle---of 3
drm_gem_objects_lookup---of 9
drm_gem_open---of 1
drm_gem_open_ioctl---of 8
drm_gem_pin---of 3
drm_gem_print_info---of 3
drm_gem_private_object_fini---of 3
drm_gem_private_object_init---of 6
drm_gem_put_pages---of 1
drm_gem_release---of 1
drm_gem_unlock_reservations---of 6
drm_gem_unpin---of 3
drm_gem_vmap---of 4
drm_gem_vmap_unlocked---of 14
drm_gem_vunmap---of 6
drm_gem_vunmap_unlocked---of 16
drm_ref---of 1
drm_unref---of 5
udv_attach_drm17%of 12
-----------
SUMMARY17%of 12
closef60%of 10
dodup324%of 30
dupfdopen47%of 13
falloc16%of 19
fd_checkclosed67%of 3
fd_getfile100%of 4
fd_getfile_mode72%of 7
fd_iterfile56%of 9
fdalloc70%of 26
fdcloseexec---of 9
fdcopy---of 24
fdexpand---of 8
fdfree---of 15
fdinit---of 1
fdinsert50%of 8
fdrelease100%of 4
fdremove43%of 14
fdrop72%of 7
fdshare100%of 1
filedesc_init---of 1
filedescopen100%of 1
find_last_set---of 8
finishdup73%of 18
fnew67%of 3
sys_close67%of 3
sys_closefrom---of 8
sys_dup50%of 12
sys_dup2100%of 1
sys_dup3---of 4
sys_fcntl61%of 91
sys_flock100%of 12
sys_fpathconf---of 11
sys_fstat---of 12
sys_getdtablecount---of 1
-----------
SUMMARY57%of 296
VOP_ABORTOP67%of 3
VOP_ACCESS38%of 8
VOP_ADVLOCK67%of 3
VOP_BMAP43%of 7
VOP_BWRITE67%of 3
VOP_CLOSE50%of 10
VOP_CREATE43%of 7
VOP_FSYNC45%of 9
VOP_GETATTR50%of 4
VOP_INACTIVE50%of 8
VOP_IOCTL50%of 4
VOP_ISLOCKED67%of 3
VOP_KQFILTER67%of 3
VOP_LINK43%of 7
VOP_LOCK50%of 4
VOP_LOOKUP67%of 3
VOP_MKDIR43%of 7
VOP_MKNOD43%of 7
VOP_OPEN50%of 4
VOP_PATHCONF---of 12
VOP_PRINT---of 3
VOP_READ58%of 7
VOP_READDIR43%of 7
VOP_READLINK43%of 7
VOP_RECLAIM50%of 4
VOP_REMOVE46%of 11
VOP_RENAME43%of 7
VOP_REVOKE67%of 3
VOP_RMDIR34%of 12
VOP_SETATTR50%of 8
VOP_STRATEGY50%of 6
VOP_SYMLINK43%of 7
VOP_UNLOCK67%of 3
VOP_WRITE58%of 7
-----------
SUMMARY49%of 193
ifa_ifwithroute86%of 14
rcb_ref100%of 1
rcb_unref100%of 1
route_arp_conflict---of 6
route_attach40%of 5
route_cleargateway---of 5
route_ctloutput96%of 24
route_detach58%of 7
route_disconnect100%of 1
route_input84%of 36
route_output86%of 61
route_peeraddr100%of 1
route_prinit---of 1
route_rcvd84%of 6
route_send84%of 6
route_shutdown100%of 1
route_sockaddr100%of 1
rt_setsource37%of 11
rtm_80211info---of 4
rtm_addr40%of 5
rtm_getifa43%of 21
rtm_getmetrics---of 4
rtm_ifannounce50%of 4
rtm_ifchg50%of 4
rtm_miss40%of 5
rtm_msg180%of 20
rtm_msg242%of 17
rtm_output33%of 61
rtm_proposal---of 3
rtm_report63%of 24
rtm_send60%of 10
rtm_senddesync43%of 7
rtm_senddesync_timer---of 1
rtm_sendup58%of 7
rtm_setmetrics---of 6
rtm_validate_proposal50%of 32
rtm_xaddrs95%of 40
sysctl_dumpentry63%of 24
sysctl_iflist64%of 22
sysctl_ifnames73%of 11
sysctl_rtable78%of 35
sysctl_rtable_rtstat100%of 1
sysctl_source---of 9
-----------
SUMMARY67%of 526
ffs_fsync60%of 22
ffs_read71%of 24
ffs_reclaim50%of 4
ffs_write58%of 50
ffsfifo_reclaim50%of 4
-----------
SUMMARY61%of 104
fillmapentry70%of 13
ksym_upcase---of 5
wskbd_compose_value---of 14
wskbd_get_mapentry---of 23
wskbd_init_keymap100%of 4
wskbd_load_keymap67%of 36
-----------
SUMMARY70%of 53
filt_midimodify---of 1
filt_midiprocess---of 6
filt_midirdetach---of 1
filt_midiread---of 1
filt_midiwdetach---of 1
filt_midiwrite---of 1
midi_attach_mi---of 1
midi_buf_wakeup---of 3
midi_iintr---of 7
midi_ointr---of 8
midi_out_do---of 12
midi_out_start---of 3
midi_out_stop---of 3
midi_timeout---of 1
midiattach---of 7
midiclose---of 8
mididetach---of 11
midiioctl---of 3
midikqfilter---of 5
midiopen40%of 5
midiprint---of 3
midiprobe---of 3
midiread---of 11
midiwrite---of 16
-----------
SUMMARY40%of 5
-----------
SUMMARY---of 0
PHYS_TO_VM_PAGE29%of 7
uvm_objtree_RBT_COMPARE100%of 1
uvm_page_init---of 19
uvm_page_owner_locked_p---of 5
uvm_page_physdump---of 4
uvm_page_physload---of 30
uvm_page_unbusy---of 21
uvm_pageactivate72%of 14
uvm_pagealloc60%of 20
uvm_pagealloc_multi40%of 10
uvm_pagealloc_pg45%of 29
uvm_pageboot_alloc---of 1
uvm_pageclean70%of 30
uvm_pagecmp---of 1
uvm_pagecopy100%of 1
uvm_pagecount43%of 7
uvm_pagedeactivate67%of 15
uvm_pagedequeue---of 5
uvm_pagefree100%of 1
uvm_pagelookup60%of 5
uvm_pagerealloc29%of 14
uvm_pagerealloc_multi---of 15
uvm_pageunwire60%of 10
uvm_pagewait50%of 4
uvm_pagewire70%of 13
uvm_pagezero100%of 1
uvm_pglistalloc29%of 7
uvm_pglistfree100%of 1
uvm_setpagesize---of 6
uvm_shutdown---of 1
vm_physseg_find---of 8
-----------
SUMMARY56%of 190
filt_vscsidetach100%of 1
filt_vscsimodify100%of 1
filt_vscsiprocess50%of 6
filt_vscsiread100%of 1
vscsi_attach---of 1
vscsi_ccb_get---of 3
vscsi_ccb_put---of 1
vscsi_cmd---of 7
vscsi_data---of 12
vscsi_devevent---of 3
vscsi_devevent_task---of 5
vscsi_done---of 3
vscsi_free---of 3
vscsi_i2t---of 3
vscsi_match---of 1
vscsi_probe---of 3
vscsi_t2i---of 9
vscsiclose25%of 16
vscsiioctl10%of 22
vscsikqfilter75%of 4
vscsiopen80%of 5
-----------
SUMMARY34%of 56
dofilereadv86%of 21
dofilewritev77%of 26
doppoll83%of 34
dopselect94%of 58
iovec_copyin85%of 13
iovec_free100%of 3
pollout---of 4
ppollcollect54%of 28
ppollregister89%of 18
ppollregister_evts67%of 15
pselcollect60%of 10
pselregister89%of 18
selwakeup100%of 1
sys_ioctl82%of 27
sys_poll100%of 4
sys_ppoll---of 11
sys_pselect---of 11
sys_read100%of 3
sys_readv100%of 5
sys_select88%of 8
sys_utrace---of 1
sys_write100%of 3
sys_writev100%of 5
-----------
SUMMARY83%of 300
sys___getcwd---of 8
vfs_getcwd_common75%of 32
vfs_getcwd_getcache50%of 8
vfs_getcwd_scandir45%of 18
-----------
SUMMARY63%of 58
cansignal---of 23
coredump---of 21
coredump_unmap---of 1
coredump_write---of 6
cursig9%of 24
dosigsuspend---of 3
execsigs---of 9
filt_sigattach100%of 3
filt_sigdetach100%of 1
filt_signal100%of 4
initsiginfo---of 7
killpg1---of 67
pgsigio65%of 20
pgsignal25%of 8
postsig---of 24
postsig_done---of 5
proc_stop---of 6
proc_stop_sweep---of 7
psignal---of 1
ptsignal28%of 70
setsigctx---of 1
setsigvec---of 24
sigabort---of 3
sigactsfree---of 1
sigactsinit100%of 1
sigexit---of 4
siginit---of 6
sigio_copy27%of 19
sigio_del---of 6
sigio_free50%of 14
sigio_freelist71%of 17
sigio_getown100%of 3
sigio_setown77%of 26
sigio_unlink---of 8
sigismasked---of 4
signal_init---of 3
sigonstack---of 3
sigstkinit---of 1
single_thread_check100%of 1
single_thread_check_locked67%of 12
single_thread_clear42%of 12
single_thread_set41%of 22
single_thread_wait---of 4
sys___thrsigdivert---of 19
sys_kill---of 34
sys_nosys---of 1
sys_sigaction---of 31
sys_sigaltstack---of 16
sys_sigpending---of 1
sys_sigprocmask---of 6
sys_sigsuspend---of 4
sys_thrkill---of 10
trapsignal26%of 31
userret47%of 15
-----------
SUMMARY43%of 303
-----------
SUMMARY---of 0
pfsync_bulk_req_evt---of 26
pfsync_bulk_req_nstate_bulk---of 3
pfsync_bulk_req_nstate_done---of 3
pfsync_bulk_req_send---of 10
pfsync_bulk_req_tmo---of 1
pfsync_bulk_snd_sub---of 9
pfsync_bulk_snd_tmo---of 11
pfsync_clear_states---of 11
pfsync_clone_create---of 7
pfsync_clone_destroy---of 3
pfsync_defer---of 11
pfsync_defer_output---of 8
pfsync_deferrals_task---of 11
pfsync_deferrals_tmo---of 3
pfsync_deferred---of 5
pfsync_delete_state---of 15
pfsync_delete_tdb---of 13
pfsync_down---of 28
pfsync_dprintf---of 3
pfsync_in_bus---of 4
pfsync_in_clr---of 18
pfsync_in_del---of 10
pfsync_in_del_c---of 10
pfsync_in_iack---of 7
pfsync_in_ins---of 22
pfsync_in_skip---of 1
pfsync_in_tdb---of 16
pfsync_in_upd---of 12
pfsync_in_upd_c---of 21
pfsync_in_updates---of 39
pfsync_in_ureq---of 28
pfsync_init_state---of 7
pfsync_input4---of 28
pfsync_insert_state---of 12
pfsync_ioctl---of 43
pfsync_is_up---of 1
pfsync_kstat_copy---of 1
pfsync_out_del---of 1
pfsync_out_iack---of 1
pfsync_out_state---of 1
pfsync_out_upd_c---of 1
pfsync_output---of 1
pfsync_q_del---of 7
pfsync_q_ins---of 10
pfsync_slice_drop---of 22
pfsync_slice_sendq---of 9
pfsync_slice_task---of 6
pfsync_slice_tmo---of 1
pfsync_slice_write---of 18
pfsync_start---of 1
pfsync_state_in_use---of 5
pfsync_syncif_detach---of 3
pfsync_syncif_link---of 6
pfsync_sysctl100%of 4
pfsync_sysctl_pfsyncstat---of 1
pfsync_update_state---of 20
pfsync_update_tdb---of 16
pfsyncattach---of 1
-----------
SUMMARY100%of 4
_bpf_mtap79%of 14
bpf_allocbufs40%of 5
bpf_attachd---of 3
bpf_catchpacket50%of 24
bpf_d_smr---of 5
bpf_detachd59%of 17
bpf_get---of 1
bpf_getdltlist89%of 9
bpf_ifname---of 1
bpf_mbuf_copy---of 7
bpf_mbuf_ldb100%of 4
bpf_mbuf_ldh72%of 7
bpf_mbuf_ldw58%of 7
bpf_mcopy---of 5
bpf_mfilter---of 1
bpf_movein55%of 24
bpf_mtap100%of 1
bpf_mtap_af---of 1
bpf_mtap_ether50%of 4
bpf_mtap_hdr---of 3
bpf_prog_smr---of 1
bpf_put---of 3
bpf_resetd50%of 8
bpf_setdlt60%of 10
bpf_setf92%of 12
bpf_setif65%of 14
bpf_sysctl84%of 6
bpf_sysctl_locked---of 4
bpf_tap_hdr---of 5
bpf_wait_cb---of 5
bpf_wakeup56%of 9
bpf_wakeup_cb---of 6
bpfattach67%of 3
bpfclose67%of 9
bpfdetach84%of 6
bpfilter_lookup---of 5
bpfilterattach---of 1
bpfioctl77%of 89
bpfkqfilter67%of 6
bpfopen56%of 9
bpfread55%of 35
bpfsattach---of 3
bpfsdetach85%of 13
bpfwrite74%of 15
filt_bpfrdetach100%of 3
filt_bpfread75%of 4
filt_bpfreadmodify75%of 4
filt_bpfreadprocess89%of 9
-----------
SUMMARY69%of 380
chkvnlock---of 4
dead_bmap---of 4
dead_ebadf100%of 1
dead_inactive100%of 1
dead_ioctl---of 4
dead_kqfilter100%of 6
dead_lock40%of 5
dead_open---of 1
dead_print---of 1
dead_read50%of 4
dead_strategy---of 5
dead_write50%of 4
-----------
SUMMARY67%of 21
vlan_clone_create---of 1
vlan_clone_destroy---of 8
vlan_del_parent---of 4
vlan_down---of 13
vlan_enqueue---of 5
vlan_get_compat---of 3
vlan_ifdetach---of 3
vlan_iff---of 6
vlan_inject---of 3
vlan_input41%of 27
vlan_inuse---of 9
vlan_inuse_locked---of 8
vlan_ioctl---of 34
vlan_link_hook---of 5
vlan_link_state---of 3
vlan_media_get---of 3
vlan_multi_add---of 15
vlan_multi_apply---of 4
vlan_multi_del---of 16
vlan_multi_free---of 6
vlan_set_compat---of 19
vlan_set_parent---of 17
vlan_set_vnetid---of 18
vlan_setlladdr---of 7
vlan_start---of 6
vlan_strip---of 3
vlan_transmit---of 10
vlan_up---of 26
vlanattach---of 5
-----------
SUMMARY41%of 27
filt_uhidrdetach---of 1
filt_uhidread---of 1
uhid_attach---of 1
uhid_detach---of 8
uhid_do_ioctl---of 6
uhid_do_open46%of 11
uhid_do_read---of 12
uhid_do_write---of 7
uhid_intr---of 3
uhid_lookup---of 7
uhid_match---of 1
uhidclose---of 8
uhidioctl---of 14
uhidkqfilter---of 11
uhidopen100%of 1
uhidread---of 9
uhidwrite---of 15
-----------
SUMMARY50%of 12
cpu_exit---of 1
cpu_fork40%of 10
setguardpage---of 1
tcb_get---of 1
tcb_set---of 3
vmapbuf60%of 5
vunmapbuf67%of 3
-----------
SUMMARY50%of 18
alps_get_hwinfo---of 36
alps_sec_proc---of 6
elantech_get_hwinfo_v1---of 16
elantech_get_hwinfo_v2---of 27
elantech_get_hwinfo_v3---of 12
elantech_get_hwinfo_v4---of 17
elantech_knock---of 17
elantech_ps2_cmd---of 3
elantech_set_absolute_mode_v1---of 27
elantech_set_absolute_mode_v2---of 49
elantech_set_absolute_mode_v3---of 42
elantech_set_absolute_mode_v4---of 18
pms_change_state32%of 32
pms_cmd---of 3
pms_dev_disable---of 5
pms_dev_enable---of 5
pms_disable100%of 1
pms_disable_synaptics---of 7
pms_enable100%of 1
pms_enable_alps---of 47
pms_enable_elantech_v1---of 12
pms_enable_elantech_v2---of 10
pms_enable_elantech_v3---of 10
pms_enable_elantech_v4---of 11
pms_enable_intelli42%of 12
pms_enable_synaptics---of 29
pms_get_devid---of 3
pms_get_status---of 3
pms_ioctl67%of 3
pms_ioctl_alps---of 6
pms_ioctl_elantech---of 6
pms_ioctl_mouse72%of 7
pms_ioctl_synaptics---of 6
pms_proc_alps---of 12
pms_proc_elantech_v1---of 14
pms_proc_elantech_v2---of 6
pms_proc_elantech_v3---of 18
pms_proc_elantech_v4---of 19
pms_proc_mouse---of 3
pms_proc_synaptics---of 15
pms_protocol_lookup---of 6
pms_reset---of 3
pms_reset_detect---of 6
pms_reset_task---of 5
pms_reset_timo---of 4
pms_sec_disable---of 1
pms_sec_enable---of 1
pms_sec_ioctl---of 3
pms_set_rate---of 3
pms_set_resolution---of 3
pms_set_scaling---of 3
pms_spec_cmd---of 15
pms_sync_alps---of 17
pms_sync_elantech_v1---of 10
pms_sync_elantech_v2---of 16
pms_sync_elantech_v3---of 8
pms_sync_elantech_v4---of 13
pms_sync_mouse---of 7
pms_sync_synaptics---of 6
pmsactivate---of 6
pmsattach---of 6
pmsinput---of 12
pmsprobe---of 3
synaptics_get_hwinfo---of 54
synaptics_knock---of 15
synaptics_query---of 7
synaptics_sec_proc---of 3
synaptics_set_mode---of 7
-----------
SUMMARY43%of 56
cttyioctl---of 14
cttykqfilter---of 6
cttyopen50%of 4
cttyread---of 4
cttywrite---of 4
-----------
SUMMARY50%of 4
-----------
SUMMARY---of 0
copy_flow_data---of 4
copy_flow_ipfix_4_data---of 3
copy_flow_ipfix_4_to_m---of 7
copy_flow_ipfix_6_data---of 3
copy_flow_ipfix_6_to_m---of 7
copy_flow_to_m---of 7
export_pflow---of 10
export_pflow_if---of 14
pflow_calc_mtu---of 5
pflow_clone_create---of 4
pflow_clone_destroy---of 13
pflow_flush---of 4
pflow_get_mbuf---of 7
pflow_output---of 1
pflow_output_process---of 6
pflow_pack_flow---of 9
pflow_pack_flow_ipfix---of 14
pflow_sendout_ipfix---of 11
pflow_sendout_ipfix_tmpl---of 8
pflow_sendout_mbuf---of 3
pflow_sendout_v5---of 6
pflow_set---of 70
pflow_setmtu---of 7
pflow_sysctl100%of 5
pflow_timeout---of 4
pflow_timeout6---of 1
pflow_timeout_tmpl---of 1
pflowattach---of 1
pflowioctl---of 39
pflowvalidsockaddr---of 13
-----------
SUMMARY100%of 5
dopipe74%of 15
filt_pipedetach100%of 1
filt_pipeexcept84%of 6
filt_pipemodify100%of 1
filt_pipeprocess100%of 6
filt_piperead100%of 4
filt_pipewrite75%of 4
pipe_buffer_free---of 4
pipe_buffer_realloc56%of 9
pipe_close100%of 1
pipe_create---of 3
pipe_destroy87%of 15
pipe_init---of 1
pipe_ioctl100%of 11
pipe_iolock---of 4
pipe_iosleep50%of 8
pipe_iounlock---of 4
pipe_kqfilter100%of 9
pipe_pair_create50%of 4
pipe_pair_destroy---of 1
pipe_peer---of 3
pipe_read79%of 32
pipe_rundown---of 4
pipe_stat---of 1
pipe_wakeup---of 3
pipe_write72%of 52
sys_pipe100%of 1
sys_pipe2100%of 3
-----------
SUMMARY79%of 182
ufs_checkpath40%of 15
ufs_dirbad---of 3
ufs_dirbadentry---of 11
ufs_dirempty54%of 13
ufs_direnter66%of 38
ufs_dirremove72%of 14
ufs_dirrewrite50%of 4
ufs_lookup75%of 113
ufs_makedirentry67%of 3
-----------
SUMMARY68%of 200
hardclock---of 1
initclocks---of 7
startprofclock---of 4
statclock---of 17
stopprofclock---of 4
sysctl_clockrate100%of 1
tstohz89%of 9
tvtohz---of 6
-----------
SUMMARY90%of 10
msts_date_to_nano---of 7
msts_decode15%of 14
msts_scan---of 8
msts_time_to_nano---of 15
msts_timeout---of 3
mstsattach---of 1
mstsclose100%of 3
mstsinput82%of 16
mstsopen80%of 5
-----------
SUMMARY58%of 38
filt_fuse_modify100%of 1
filt_fuse_process50%of 6
filt_fuse_rdetach100%of 1
filt_fuse_read100%of 1
fuse_device_cleanup---of 18
fuse_device_queue_fbuf---of 5
fuse_device_set_fmp---of 5
fuse_lookup---of 5
fuseattach---of 1
fuseclose50%of 10
fuseioctl14%of 22
fusekqfilter72%of 7
fuseopen88%of 8
fuseread40%of 10
fusewrite24%of 21
-----------
SUMMARY41%of 87
udv_attach17%of 18
udv_detach---of 10
udv_fault---of 10
udv_flush---of 1
udv_reference---of 1
-----------
SUMMARY17%of 18
-----------
SUMMARY---of 0
bounds_check_with_label70%of 10
checkdisklabel17%of 42
disk_attach45%of 20
disk_attach_callback---of 4
disk_busy100%of 3
disk_closepart60%of 5
disk_construct---of 1
disk_detach60%of 5
disk_gone---of 11
disk_init---of 1
disk_lock100%of 1
disk_lock_nointr100%of 1
disk_lookup60%of 5
disk_map29%of 21
disk_openpart80%of 10
disk_readlabel---of 5
disk_unbusy---of 8
disk_unlock100%of 1
diskerr---of 10
dk_mountroot---of 7
dkcksum75%of 4
duid_equal---of 1
duid_format100%of 1
duid_iszero100%of 1
findblkmajor---of 11
findblkname---of 6
getdisk---of 9
gpt_chk_mbr30%of 17
gpt_get_fstype---of 11
gpt_get_hdr---of 6
gpt_get_parts---of 8
initdisklabel75%of 8
mbr_get_fstype---of 13
parsedisk---of 23
readdisksector---of 1
readdoslabel30%of 20
setdisklabel14%of 30
setroot---of 140
spooffat---of 8
spoofgpt9%of 23
spoofmbr22%of 37
-----------
SUMMARY34%of 265
uvm_io13%of 16
-----------
SUMMARY13%of 16
filt_ttyexcept80%of 5
filt_ttyrdetach100%of 1
filt_ttyread100%of 4
filt_ttywdetach100%of 1
filt_ttywrite100%of 5
nullmodem---of 7
sysctl_tty100%of 8
tputchar100%of 9
ttioctl77%of 124
ttkqfilter100%of 7
ttnread84%of 12
ttread86%of 81
ttrstrt---of 4
ttsetwater100%of 1
ttspeedtab---of 5
ttstart---of 3
ttvtimeout---of 1
ttwakeup100%of 3
ttwakeupwr100%of 4
ttwrite66%of 58
tty_init---of 1
ttychars100%of 1
ttycheckoutq---of 10
ttyclose67%of 6
ttyecho100%of 11
ttyflush100%of 11
ttyfree---of 3
ttyinfo20%of 60
ttyinput90%of 136
ttylclose80%of 5
ttymalloc50%of 4
ttymodem79%of 14
ttyopen100%of 3
ttyoutput100%of 41
ttypend---of 6
ttyretype100%of 9
ttyrub96%of 23
ttyrubo50%of 4
ttysleep100%of 3
ttysleep_nsec---of 3
ttystats_init78%of 9
ttytstamp---of 8
ttyunblock77%of 13
ttywait---of 1
ttywait_nsec65%of 17
ttywflush---of 4
-----------
SUMMARY79%of 693
wsmouse_activate---of 3
wsmouse_add_mux84%of 6
wsmouse_attach---of 4
wsmouse_btn_sync---of 7
wsmouse_buttons---of 1
wsmouse_configure---of 18
wsmouse_detach---of 21
wsmouse_do_ioctl87%of 22
wsmouse_evq_put---of 4
wsmouse_get_hw---of 1
wsmouse_get_params96%of 24
wsmouse_hysteresis---of 3
wsmouse_id_to_slot---of 9
wsmouse_input_cleanup---of 5
wsmouse_input_reset---of 5
wsmouse_input_sync---of 56
wsmouse_log_events---of 5
wsmouse_log_input---of 16
wsmouse_match---of 1
wsmouse_matching---of 53
wsmouse_motion---of 3
wsmouse_motion_sync---of 45
wsmouse_mt_convert---of 15
wsmouse_mt_init---of 10
wsmouse_mt_update---of 3
wsmouse_mtframe---of 33
wsmouse_mtstate---of 20
wsmouse_mux_close100%of 1
wsmouse_mux_open50%of 8
wsmouse_param_ioctl86%of 7
wsmouse_position---of 11
wsmouse_ptr_ctrl---of 12
wsmouse_set---of 38
wsmouse_set_mode---of 4
wsmouse_set_params94%of 29
wsmouse_touch---of 6
wsmouse_touch_sync---of 14
wsmouse_touch_update---of 13
wsmouseclose50%of 6
wsmousedevprint---of 3
wsmousedoioctl67%of 3
wsmousedoopen50%of 8
wsmouseioctl67%of 3
wsmousekqfilter100%of 3
wsmouseopen73%of 11
wsmouseread40%of 5
-----------
SUMMARY81%of 136
nd6_cache_lladdr---of 40
nd6_expire---of 21
nd6_expire_timer---of 1
nd6_expire_timer_update89%of 9
nd6_free---of 11
nd6_ifattach100%of 1
nd6_ifdetach100%of 1
nd6_init---of 1
nd6_invalidate---of 3
nd6_ioctl50%of 16
nd6_is_addr_neighbor---of 21
nd6_llinfo_settimer67%of 6
nd6_llinfo_timer---of 20
nd6_lookup---of 18
nd6_need_cache60%of 5
nd6_nud_hint---of 12
nd6_options---of 22
nd6_purge55%of 11
nd6_resolve50%of 22
nd6_rtrequest34%of 48
nd6_slowtimo---of 6
nd6_timer---of 8
-----------
SUMMARY49%of 119
_bus_space_map---of 7
_bus_space_unmap---of 8
bus_space_alloc---of 14
bus_space_free---of 1
bus_space_map---of 15
bus_space_subregion---of 1
bus_space_unmap---of 9
x86_bus_space_init---of 1
x86_bus_space_io_copy_1---of 7
x86_bus_space_io_copy_2---of 7
x86_bus_space_io_copy_4---of 7
x86_bus_space_io_mmap---of 1
x86_bus_space_io_read_1100%of 1
x86_bus_space_io_read_2---of 1
x86_bus_space_io_read_4100%of 1
x86_bus_space_io_read_multi_1---of 1
x86_bus_space_io_read_multi_2---of 1
x86_bus_space_io_read_multi_4---of 1
x86_bus_space_io_read_region_1---of 1
x86_bus_space_io_read_region_2---of 1
x86_bus_space_io_read_region_4---of 1
x86_bus_space_io_set_multi_1---of 4
x86_bus_space_io_set_multi_2---of 4
x86_bus_space_io_set_multi_4---of 4
x86_bus_space_io_set_region_1---of 4
x86_bus_space_io_set_region_2---of 4
x86_bus_space_io_set_region_4---of 4
x86_bus_space_io_vaddr---of 1
x86_bus_space_io_write_1100%of 1
x86_bus_space_io_write_2100%of 1
x86_bus_space_io_write_4---of 1
x86_bus_space_io_write_multi_1---of 1
x86_bus_space_io_write_multi_2---of 1
x86_bus_space_io_write_multi_4---of 1
x86_bus_space_io_write_region_1---of 1
x86_bus_space_io_write_region_2---of 1
x86_bus_space_io_write_region_4---of 1
x86_bus_space_mallocok---of 1
x86_bus_space_mem_copy_1---of 15
x86_bus_space_mem_copy_2---of 15
x86_bus_space_mem_copy_4---of 15
x86_bus_space_mem_copy_8---of 15
x86_bus_space_mem_mmap---of 1
x86_bus_space_mem_read_1---of 1
x86_bus_space_mem_read_2---of 1
x86_bus_space_mem_read_4---of 1
x86_bus_space_mem_read_8---of 1
x86_bus_space_mem_read_multi_1---of 1
x86_bus_space_mem_read_multi_2---of 1
x86_bus_space_mem_read_multi_4---of 1
x86_bus_space_mem_read_multi_8---of 1
x86_bus_space_mem_read_region_1---of 1
x86_bus_space_mem_read_region_2---of 1
x86_bus_space_mem_read_region_4---of 1
x86_bus_space_mem_read_region_8---of 1
x86_bus_space_mem_set_multi_1---of 8
x86_bus_space_mem_set_multi_2---of 8
x86_bus_space_mem_set_multi_4---of 8
x86_bus_space_mem_set_multi_8---of 8
x86_bus_space_mem_set_region_1---of 8
x86_bus_space_mem_set_region_2---of 8
x86_bus_space_mem_set_region_4---of 8
x86_bus_space_mem_set_region_8---of 8
x86_bus_space_mem_vaddr---of 1
x86_bus_space_mem_write_1---of 1
x86_bus_space_mem_write_2---of 1
x86_bus_space_mem_write_4---of 1
x86_bus_space_mem_write_8---of 1
x86_bus_space_mem_write_multi_1---of 1
x86_bus_space_mem_write_multi_2---of 1
x86_bus_space_mem_write_multi_4---of 1
x86_bus_space_mem_write_multi_8---of 1
x86_bus_space_mem_write_region_1---of 1
x86_bus_space_mem_write_region_2---of 1
x86_bus_space_mem_write_region_4---of 1
x86_bus_space_mem_write_region_8---of 1
x86_mem_add_mapping---of 6
-----------
SUMMARY100%of 4
icmp6_ctloutput42%of 12
icmp6_do_error55%of 51
icmp6_errcount---of 9
icmp6_error100%of 4
icmp6_fasttimo---of 1
icmp6_init---of 1
icmp6_input---of 80
icmp6_mtudisc_callback_register---of 6
icmp6_mtudisc_clone---of 11
icmp6_mtudisc_timeout---of 7
icmp6_mtudisc_update---of 19
icmp6_notify_error---of 52
icmp6_ratelimit---of 1
icmp6_redirect_diag---of 1
icmp6_redirect_input---of 44
icmp6_redirect_output---of 40
icmp6_reflect43%of 19
icmp6_sysctl100%of 6
icmp6_sysctl_icmp6stat---of 1
-----------
SUMMARY56%of 92
uvm_obj_destroy67%of 3
uvm_obj_free60%of 5
uvm_obj_init100%of 3
uvm_obj_setlock---of 5
uvm_obj_unwire---of 6
uvm_obj_wire---of 17
-----------
SUMMARY73%of 11
allocate_copybuffer---of 11
button_event---of 17
class_cmp---of 4
ctrl_event---of 16
inverse_char---of 5
inverse_region---of 4
motion_event---of 10
mouse_copy_end---of 4
mouse_copy_extend---of 7
mouse_copy_extend_after---of 10
mouse_copy_extend_char---of 32
mouse_copy_extend_line---of 32
mouse_copy_extend_word---of 54
mouse_copy_line---of 12
mouse_copy_selection---of 7
mouse_copy_start---of 11
mouse_copy_word---of 21
mouse_hide---of 3
mouse_moverel---of 10
mouse_paste---of 6
mouse_remove---of 9
mouse_zaxis---of 7
remove_selection---of 6
skip_char_left---of 4
skip_char_right---of 4
skip_spc_left---of 3
skip_spc_right---of 4
wsdisplay_activate---of 5
wsdisplay_addscreen---of 14
wsdisplay_addscreen_print---of 3
wsdisplay_brightness_cycle---of 4
wsdisplay_brightness_step---of 15
wsdisplay_brightness_zero---of 11
wsdisplay_burn---of 7
wsdisplay_burner---of 4
wsdisplay_burner_setup---of 12
wsdisplay_cfg_ioctl---of 31
wsdisplay_closescreen---of 20
wsdisplay_cnattach---of 7
wsdisplay_cnputc---of 6
wsdisplay_common_attach---of 26
wsdisplay_common_detach---of 42
wsdisplay_delscreen---of 12
wsdisplay_driver_ioctl---of 4
wsdisplay_emul_attach---of 6
wsdisplay_emul_detach---of 1
wsdisplay_emul_match---of 8
wsdisplay_emulbell---of 4
wsdisplay_emulbell_task---of 4
wsdisplay_emulinput---of 6
wsdisplay_enter_ddb---of 5
wsdisplay_get_param---of 14
wsdisplay_getactivescreen---of 3
wsdisplay_getc_dummy---of 1
wsdisplay_getscreen---of 7
wsdisplay_internal_ioctl---of 55
wsdisplay_kbdholdscr---of 3
wsdisplay_kbdholdscreen---of 5
wsdisplay_kbdinput---of 8
wsdisplay_maxscreenidx---of 1
wsdisplay_param---of 4
wsdisplay_pollc---of 6
wsdisplay_rawkbdinput---of 5
wsdisplay_reset---of 5
wsdisplay_resume---of 7
wsdisplay_resume_device---of 3
wsdisplay_screenstate---of 4
wsdisplay_screentype_pick---of 7
wsdisplay_set_cons_kbd---of 1
wsdisplay_set_console_kbd---of 3
wsdisplay_set_param---of 10
wsdisplay_suspend---of 6
wsdisplay_suspend_device---of 43
wsdisplay_switch---of 18
wsdisplay_switch1---of 9
wsdisplay_switch2---of 10
wsdisplay_switch3---of 13
wsdisplay_switchtoconsole---of 4
wsdisplay_unset_cons_kbd---of 1
wsdisplay_update_rawkbd---of 8
wsdisplayclose---of 14
wsdisplayioctl---of 14
wsdisplaykqfilter---of 5
wsdisplaymmap---of 5
wsdisplayopen15%of 14
wsdisplayparam---of 1
wsdisplayread---of 5
wsdisplaystart---of 17
wsdisplaystop---of 3
wsdisplaytty---of 4
wsdisplaywrite---of 5
wsemuldisplaydevprint---of 3
wsemuldisplaydevsubmatch---of 3
wsmoused---of 15
wsscreen_attach---of 8
wsscreen_attach_sync---of 4
wsscreen_detach---of 3
wsscreen_detach_sync---of 3
wsscreen_lookup_sync---of 3
wsscreen_switchwait---of 9
wsscrollback---of 6
-----------
SUMMARY15%of 14
mpls_do_error20%of 21
mpls_input20%of 40
mpls_input_local---of 3
mpls_ip6_adjttl---of 4
mpls_ip_adjttl---of 4
-----------
SUMMARY20%of 61
bdevvp---of 8
bgetvp54%of 13
brelvp57%of 16
buf_rb_bufs_RBT_COMPARE100%of 1
buf_replacevnode---of 14
cdevvp50%of 8
checkalias66%of 23
copy_statfs_info---of 3
fs_posix_sysctl---of 4
fs_sysctl100%of 5
getdevvp---of 8
getnewvnode48%of 17
insmntque---of 5
reassignbuf71%of 17
vaccess100%of 5
vattr_null100%of 1
vclean48%of 19
vcount90%of 10
vdevgone50%of 10
vdrop34%of 6
vfinddev86%of 7
vflush---of 5
vflush_vnode---of 16
vflushbuf---of 13
vfs_buf_print---of 1
vfs_busy100%of 1
vfs_export---of 7
vfs_export_lookup---of 7
vfs_free_addrlist---of 3
vfs_free_netcred---of 1
vfs_getnewfsid---of 9
vfs_getvfs---of 7
vfs_hang_addrlist---of 20
vfs_isbusy---of 1
vfs_mount_alloc---of 1
vfs_mount_foreach_vnode---of 5
vfs_mount_free---of 1
vfs_mount_print---of 13
vfs_mountedon90%of 10
vfs_rootmountalloc---of 3
vfs_shutdown---of 3
vfs_stall---of 13
vfs_stall_barrier67%of 3
vfs_syncwait---of 12
vfs_sysctl91%of 11
vfs_unbusy---of 1
vfs_unmountall---of 14
vfs_vnode_print---of 12
vget75%of 12
vgone100%of 1
vgonel75%of 28
vhold34%of 6
vinvalbuf58%of 38
vn_isdisk---of 1
vnoperm100%of 4
vntblinit---of 1
vprint---of 25
vput34%of 9
vputonfreelist63%of 8
vrecycle67%of 3
vref50%of 4
vrele45%of 9
vwaitforio67%of 6
vwakeup43%of 7
-----------
SUMMARY64%of 318
in6_cksum68%of 67
-----------
SUMMARY68%of 67
check_pty63%of 8
filt_ptcexcept100%of 10
filt_ptcrdetach100%of 1
filt_ptcread100%of 12
filt_ptcwdetach100%of 1
filt_ptcwrite100%of 10
ptcclose100%of 1
ptckqfilter100%of 5
ptcopen100%of 4
ptcread92%of 24
ptcwakeup---of 5
ptcwrite83%of 39
ptm_vn_open60%of 5
ptmattach---of 7
ptmclose100%of 1
ptmioctl48%of 34
ptmopen100%of 1
ptsclose100%of 1
ptsopen100%of 12
ptsread57%of 23
ptsstart100%of 4
ptsstop100%of 5
ptswrite100%of 3
pty_getfree---of 7
ptyattach---of 7
ptydevname---of 3
ptyioctl81%of 46
ptytty100%of 1
sysctl_pty100%of 1
-----------
SUMMARY80%of 252
sb_notify---of 3
sbspace---of 3
syn_cache_add---of 43
syn_cache_cleanup37%of 11
syn_cache_get---of 40
syn_cache_init---of 4
syn_cache_insert---of 39
syn_cache_lookup---of 18
syn_cache_put---of 3
syn_cache_reset---of 8
syn_cache_respond---of 37
syn_cache_rm---of 9
syn_cache_timer---of 15
syn_cache_unreach---of 9
tcp_clean_sackreport---of 1
tcp_del_sackholes---of 9
tcp_dooptions---of 44
tcp_flush_queue---of 13
tcp_hdrsz---of 1
tcp_input---of 409
tcp_mss75%of 24
tcp_mss_adv---of 9
tcp_mss_update---of 6
tcp_newreno_partialack---of 3
tcp_pulloutofband---of 5
tcp_reass---of 27
tcp_sack_option---of 33
tcp_sack_partialack---of 3
tcp_seq_subtract---of 1
tcp_update_sack_list---of 49
tcp_xmit_timer---of 6
-----------
SUMMARY63%of 35
cancel_all_itimers---of 1
clock_gettime44%of 16
inittodr---of 9
itimer_update---of 40
itimerdecr---of 14
itimerfix---of 16
perform_resettodr---of 5
periodic_resettodr---of 1
ppsratecheck60%of 10
process_reset_itimer_flag---of 6
ratecheck72%of 7
realitexpire---of 16
resettodr---of 5
setitimer93%of 28
settime46%of 11
start_periodic_resettodr---of 1
stop_periodic_resettodr---of 1
sys_adjfreq---of 10
sys_adjtime---of 19
sys_clock_getres87%of 15
sys_clock_gettime84%of 6
sys_clock_settime100%of 5
sys_getitimer100%of 3
sys_gettimeofday---of 8
sys_nanosleep84%of 18
sys_setitimer100%of 24
sys_settimeofday---of 15
todr_attach---of 4
-----------
SUMMARY80%of 143
an_match---of 5
rtable_add75%of 20
rtable_alloc---of 1
rtable_clearsource18%of 17
rtable_delete42%of 24
rtable_empty55%of 11
rtable_exists70%of 10
rtable_get---of 5
rtable_getsource50%of 8
rtable_init---of 12
rtable_init_backend---of 1
rtable_insert48%of 36
rtable_iterate67%of 3
rtable_l2100%of 3
rtable_l2set12%of 17
rtable_loindex67%of 3
rtable_lookup79%of 23
rtable_match25%of 16
rtable_mpath_capable100%of 1
rtable_mpath_insert47%of 15
rtable_mpath_reprio47%of 15
rtable_satoplen83%of 23
rtable_setsource---of 8
rtable_walk84%of 6
rtable_walk_helper67%of 6
rtentry_ref100%of 1
rtentry_unref100%of 1
rtmap_dtor100%of 1
rtmap_grow43%of 7
rtmap_init---of 6
-----------
SUMMARY54%of 267
cond_init100%of 1
cond_signal---of 1
cond_wait100%of 4
endtsleep100%of 1
msleep42%of 12
msleep_nsec75%of 4
refcnt_finalize27%of 15
refcnt_init100%of 1
refcnt_init_trace34%of 6
refcnt_read34%of 6
refcnt_rele45%of 9
refcnt_rele_wake34%of 9
refcnt_shared---of 6
refcnt_take29%of 7
rwsleep50%of 8
rwsleep_nsec75%of 4
sleep_finish58%of 28
sleep_queue_init---of 3
sleep_setup45%of 9
sleep_signal_check---of 4
sys___thrsleep---of 5
sys___thrwakeup---of 12
sys_sched_yield---of 4
thrsleep---of 32
thrsleep_unlock---of 3
tsleep56%of 9
tsleep_nsec75%of 4
unsleep43%of 7
wakeup100%of 1
wakeup_n69%of 16
wakeup_proc40%of 15
-----------
SUMMARY50%of 176
-----------
SUMMARY---of 0
check_exec53%of 23
copyargs---of 16
exec_sigcode_map---of 8
exec_timekeep_map---of 7
sys_execve2%of 108
-----------
SUMMARY11%of 131
in6_addmulti77%of 13
in6_addr2scopeid---of 13
in6_addrscope---of 6
in6_check_embed_scope---of 6
in6_clear_scope_id---of 6
in6_control100%of 4
in6_delmulti84%of 6
in6_hasmulti100%of 7
in6_ifawithscope72%of 92
in6_ifinit27%of 52
in6_ioctl100%of 17
in6_ioctl_change_ifaddr72%of 39
in6_ioctl_get75%of 28
in6_joingroup50%of 4
in6_leavegroup67%of 3
in6_mask2len87%of 22
in6_matchlen96%of 22
in6_nam2sin680%of 5
in6_prefixlen2mask82%of 11
in6_purgeaddr62%of 13
in6_sa2sin6---of 4
in6_unlink_ifa23%of 40
in6_update_ifa52%of 114
in6if_do_dad75%of 4
in6ifa_ifpforlinklocal89%of 9
in6ifa_ifpwithaddr86%of 7
-----------
SUMMARY63%of 512
buf_acquire50%of 4
buf_acquire_nomap84%of 6
buf_alloc_pages30%of 10
buf_dealloc_mem62%of 13
buf_fix_mapping---of 3
buf_free_pages42%of 12
buf_map58%of 14
buf_mem_init---of 3
buf_realloc_pages---of 20
buf_release43%of 7
buf_unmap56%of 9
-----------
SUMMARY52%of 75
srp_gc_finalize---of 1
srp_gc_init---of 1
srp_get_locked100%of 1
srp_init100%of 1
srp_startup---of 1
srp_swap_locked100%of 1
srp_update_locked100%of 5
srp_v_gc_start---of 1
srpl_rc_init---of 1
-----------
SUMMARY100%of 8
doktrace83%of 39
ktrcanset---of 8
ktrcleartrace---of 3
ktrexec---of 9
ktrgenio80%of 10
ktrinitheader---of 1
ktrinitheaderraw---of 1
ktrnamei67%of 3
ktrops86%of 14
ktrpinsyscall---of 3
ktrpledge---of 3
ktrpsig67%of 3
ktrsetchildren---of 6
ktrsettrace75%of 8
ktrstart---of 1
ktrstruct67%of 3
ktrsyscall91%of 11
ktrsysret67%of 3
ktruser---of 11
ktrwrite---of 3
ktrwrite2---of 3
ktrwriteraw27%of 15
sys_ktrace100%of 6
-----------
SUMMARY75%of 115
-----------
SUMMARY---of 0
pci_alloc_msix_table---of 3
pci_detach_devices---of 7
pci_disable_legacy_vga---of 6
pci_disable_vga---of 1
pci_enable_vga---of 1
pci_enumerate_bus---of 21
pci_find_device---of 7
pci_free_msix_table---of 3
pci_get_capability28%of 11
pci_get_ext_capability---of 9
pci_get_ht_capability---of 9
pci_get_powerstate---of 3
pci_intr_msix_count---of 4
pci_matchbyid---of 7
pci_powerdown---of 7
pci_primary_vga---of 7
pci_probe_device---of 30
pci_requester_id---of 1
pci_reserve_resources---of 49
pci_resume---of 10
pci_resume_msix---of 6
pci_route_vga---of 4
pci_set_powerstate---of 7
pci_suspend---of 8
pci_suspend_msix---of 6
pci_unroute_vga---of 4
pci_vpd_read34%of 9
pci_vpd_write---of 9
pciactivate---of 5
pciattach---of 5
pciclose100%of 1
pcidetach---of 1
pciioctl60%of 74
pcimatch---of 4
pciopen100%of 3
pciprint---of 3
pcisubmatch---of 7
-----------
SUMMARY56%of 98
vfs_byname---of 11
vfs_bytypenum100%of 11
vfsinit---of 35
-----------
SUMMARY100%of 11
isqrt---of 1
wstpad_cleanup---of 1
wstpad_click---of 7
wstpad_cmds---of 22
wstpad_compat_convert---of 10
wstpad_configure---of 38
wstpad_decelerate---of 3
wstpad_edgescroll---of 12
wstpad_f2scroll---of 44
wstpad_filter---of 14
wstpad_get_mtbtn---of 1
wstpad_get_param8%of 28
wstpad_get_sbtn---of 24
wstpad_init---of 8
wstpad_init_deceleration75%of 4
wstpad_is_stable---of 6
wstpad_is_tap---of 3
wstpad_mt_inputs---of 24
wstpad_mt_masks---of 32
wstpad_mtbtn_contacts---of 12
wstpad_process_input---of 39
wstpad_reset---of 5
wstpad_scroll---of 17
wstpad_scroll_coords---of 9
wstpad_set_direction---of 10
wstpad_set_param7%of 31
wstpad_softbuttons---of 9
wstpad_tap---of 54
wstpad_tap_button---of 3
wstpad_tap_filter---of 8
wstpad_tap_sync---of 4
wstpad_tap_timeout---of 19
wstpad_tap_touch---of 26
wstpad_touch_inputs---of 21
wstpad_track_interval---of 12
-----------
SUMMARY12%of 63
futex_get18%of 17
futex_init---of 1
futex_put50%of 6
futex_requeue38%of 8
futex_wait---of 15
futex_wake---of 1
sys_futex25%of 8
-----------
SUMMARY29%of 39
diskmapclose100%of 1
diskmapioctl71%of 17
diskmapopen100%of 1
diskmapread100%of 1
diskmapwrite100%of 1
-----------
SUMMARY77%of 21
pckbd_bell---of 3
pckbd_cnattach---of 1
pckbd_cnbell---of 3
pckbd_cngetc---of 25
pckbd_cnpollc---of 3
pckbd_enable13%of 8
pckbd_hookup_bell---of 3
pckbd_init---of 1
pckbd_input---of 33
pckbd_ioctl88%of 8
pckbd_scancode_translate---of 13
pckbd_set_leds---of 1
pckbd_set_xtscancode---of 15
pckbdactivate---of 4
pckbdattach---of 4
pckbdprobe---of 10
-----------
SUMMARY50%of 16
vio_add_rx_mbuf---of 4
vio_alloc_dmamem---of 6
vio_alloc_mem---of 25
vio_attach---of 21
vio_config_change---of 7
vio_ctrl_rx---of 12
vio_ctrl_wakeup---of 1
vio_ctrleof---of 4
vio_encap---of 6
vio_free_dmamem---of 1
vio_free_rx_mbuf---of 1
vio_get_lladdr---of 1
vio_iff16%of 19
vio_init---of 5
vio_ioctl34%of 15
vio_link_state---of 5
vio_match---of 1
vio_media_change---of 1
vio_media_status---of 8
vio_populate_rx_mbufs---of 15
vio_put_lladdr---of 1
vio_rx_drain---of 6
vio_rx_intr---of 5
vio_rx_offload---of 9
vio_rxeof---of 22
vio_rxtick---of 1
vio_set_rx_filter---of 12
vio_start34%of 24
vio_stop---of 18
vio_tx_drain---of 6
vio_tx_intr---of 1
vio_tx_offload32%of 19
vio_txeof67%of 9
vio_txtick---of 1
vio_wait_ctrl---of 5
vio_wait_ctrl_done---of 6
-----------
SUMMARY33%of 86
nmea_atoi---of 14
nmea_date_to_nano---of 9
nmea_decode_gga---of 15
nmea_degrees---of 18
nmea_gprmc---of 43
nmea_scan17%of 42
nmea_time_to_nano---of 19
nmea_timeout---of 3
nmeaattach---of 1
nmeaclose100%of 3
nmeainput100%of 12
nmeaopen80%of 5
-----------
SUMMARY42%of 62
-----------
SUMMARY---of 0
in4_cksum68%of 37
-----------
SUMMARY68%of 37
copyaddrout80%of 5
dns_portcheck---of 10
doaccept75%of 44
getsock80%of 5
recvit92%of 47
sendit75%of 43
sockargs88%of 8
sys_accept100%of 1
sys_accept4---of 3
sys_bind67%of 12
sys_connect68%of 25
sys_getpeername59%of 12
sys_getrtable---of 1
sys_getsockname59%of 12
sys_getsockopt82%of 16
sys_listen58%of 7
sys_recvfrom100%of 4
sys_recvmmsg88%of 41
sys_recvmsg94%of 15
sys_sendmmsg87%of 22
sys_sendmsg82%of 16
sys_sendto100%of 1
sys_setrtable---of 8
sys_setsockopt72%of 14
sys_shutdown84%of 6
sys_socket67%of 9
sys_socketpair78%of 27
sys_ypconnect---of 35
ypsockargs---of 7
-----------
SUMMARY79%of 392
egre_clone_create---of 1
egre_clone_destroy---of 4
egre_down---of 3
egre_input---of 12
egre_ioctl---of 26
egre_media_change---of 1
egre_media_status---of 1
egre_start---of 19
egre_tree_RBT_COMPARE---of 1
egre_up---of 6
eoip_clone_create---of 1
eoip_clone_destroy---of 3
eoip_down---of 6
eoip_ioctl---of 43
eoip_keepalive_hold---of 4
eoip_keepalive_send---of 13
eoip_start---of 17
eoip_tree_RBT_COMPARE---of 14
eoip_up---of 7
gre_clone_create---of 1
gre_clone_destroy---of 5
gre_cmp---of 18
gre_down---of 6
gre_encap_dst_ip---of 10
gre_find---of 7
gre_input---of 3
gre_input6---of 3
gre_input_key---of 62
gre_ioctl---of 29
gre_ip_output---of 4
gre_ipv4_patch---of 5
gre_ipv6_patch---of 4
gre_keepalive_hold---of 5
gre_keepalive_recv---of 15
gre_keepalive_send---of 23
gre_l3_encap_dst---of 17
gre_mpls_patch---of 4
gre_output---of 14
gre_set_tunnel---of 26
gre_start---of 10
gre_sysctl100%of 1
gre_tunnel_ioctl---of 31
greattach---of 1
mgre_clone_create---of 1
mgre_clone_destroy---of 4
mgre_down---of 3
mgre_find---of 3
mgre_ioctl---of 43
mgre_output---of 23
mgre_rtrequest---of 12
mgre_start---of 10
mgre_tree_RBT_COMPARE---of 14
mgre_up---of 9
nvgre_clone_create---of 5
nvgre_clone_destroy---of 3
nvgre_detach---of 3
nvgre_down---of 10
nvgre_eb_port_eq---of 4
nvgre_eb_port_ifname---of 1
nvgre_eb_port_rele---of 1
nvgre_eb_port_sa---of 4
nvgre_eb_port_take---of 3
nvgre_input---of 30
nvgre_ioctl---of 70
nvgre_link_change---of 1
nvgre_mcast_tree_RBT_COMPARE---of 13
nvgre_send---of 10
nvgre_set_parent---of 4
nvgre_start---of 21
nvgre_ucast_tree_RBT_COMPARE---of 10
nvgre_up---of 13
-----------
SUMMARY100%of 1
__wdstart---of 12
wd_flushcache---of 9
wd_get_params---of 7
wd_standby---of 7
wdactivate---of 14
wdattach---of 31
wdclose---of 4
wddetach---of 1
wddone---of 18
wddump---of 23
wdgetdefaultlabel---of 1
wdgetdisklabel---of 5
wdioctl---of 19
wdopen19%of 11
wdprobe---of 9
wdread---of 1
wdrestart---of 3
wdsize---of 7
wdstart---of 5
wdstrategy---of 11
wdwrite---of 1
-----------
SUMMARY19%of 11
ffs1_compat_read---of 3
ffs1_compat_write---of 3
ffs_checkrange---of 8
ffs_fhtovp---of 4
ffs_flushfiles---of 9
ffs_init---of 3
ffs_mount---of 34
ffs_mountfs---of 59
ffs_mountroot---of 10
ffs_oldfscompat---of 9
ffs_reload---of 38
ffs_reload_vnode---of 7
ffs_sbupdate---of 17
ffs_statfs---of 4
ffs_sync---of 12
ffs_sync_vnode---of 11
ffs_sysctl100%of 1
ffs_unmount---of 6
ffs_validate---of 10
ffs_vget25%of 20
ffs_vptofh---of 1
-----------
SUMMARY29%of 21
gpio_attach---of 1
gpio_detach---of 5
gpio_ioctl---of 91
gpio_match---of 1
gpio_npins---of 1
gpio_pin_caps---of 1
gpio_pin_ctl---of 1
gpio_pin_map---of 9
gpio_pin_read---of 1
gpio_pin_unmap---of 4
gpio_pin_write---of 1
gpio_pinbyname---of 5
gpio_print---of 5
gpio_search---of 3
gpio_submatch---of 3
gpiobus_print---of 3
gpioclose---of 3
gpioioctl---of 3
gpioopen50%of 4
-----------
SUMMARY50%of 4
-----------
SUMMARY---of 0
ppp_ccp---of 27
ppp_ccp_closed---of 5
ppp_clone_create---of 3
ppp_clone_destroy---of 4
ppp_dequeue---of 29
ppp_ifstart---of 1
ppp_pkt_dequeue---of 4
ppp_pkt_enqueue---of 3
ppp_pkt_list_init---of 1
ppp_pkt_mbuf---of 5
ppp_requeue---of 14
ppp_restart---of 1
pppalloc23%of 9
pppattach---of 1
pppdealloc---of 16
pppdumpm---of 11
pppintr---of 80
pppioctl---of 55
pppoutput---of 31
ppppktin---of 3
pppsioctl---of 15
-----------
SUMMARY23%of 9
nullioctl100%of 1
-----------
SUMMARY100%of 1
fd_motor_off---of 11
fd_motor_on---of 4
fd_nvtotype---of 3
fd_set_motor---of 11
fdactivate---of 5
fdattach---of 5
fdclose---of 4
fddump---of 1
fdfinish---of 7
fdformat---of 3
fdgetdisklabel---of 1
fdintr---of 88
fdioctl---of 18
fdopen15%of 14
fdprobe---of 6
fdread---of 1
fdretry---of 8
fdsize---of 1
fdstart---of 3
fdstrategy---of 16
fdtimeout---of 3
fdwrite---of 1
-----------
SUMMARY15%of 14
chkdqchg---of 11
chkdquot30%of 10
chkiqchg---of 11
dqget5%of 49
dqref---of 1
dqrele---of 7
dqsync---of 13
getinoquota34%of 9
getquota---of 12
qsync---of 4
qsync_vnode---of 9
quotaoff---of 6
quotaoff_vnode---of 9
quotaon---of 19
quotaon_vnode---of 12
setquota---of 28
setuse---of 20
ufs_quota_alloc_blocks250%of 22
ufs_quota_alloc_inode248%of 21
ufs_quota_delete24%of 13
ufs_quota_free_blocks247%of 13
ufs_quota_free_inode232%of 16
ufs_quota_init---of 1
ufs_quotactl---of 20
-----------
SUMMARY29%of 153
carp_strict_addr_chk34%of 6
in_ouraddr54%of 39
ip_deliver50%of 24
ip_dooptions70%of 42
ip_flush---of 7
ip_forward---of 36
ip_fragcheck66%of 29
ip_freef---of 9
ip_init---of 13
ip_input_if52%of 31
ip_ours72%of 7
ip_reass87%of 44
ip_savecontrol69%of 16
ip_send100%of 1
ip_send_dispatch---of 1
ip_send_do_dispatch---of 7
ip_send_raw---of 1
ip_sendraw_dispatch---of 1
ip_slowtimo---of 6
ip_srcroute---of 8
ip_stripoptions---of 3
ip_sysctl98%of 36
ip_sysctl_ipstat100%of 1
ipintr---of 8
ipv4_check74%of 23
ipv4_input67%of 3
save_rte---of 4
-----------
SUMMARY70%of 302
pow2divide---of 4
uvm_pagezero_thread---of 10
uvm_pmemrange_addr_RBT_COMPARE---of 1
uvm_pmemrange_addr_cmp---of 1
uvm_pmemrange_find---of 7
uvm_pmemrange_use_cmp---of 3
uvm_pmemrange_use_insert---of 9
uvm_pmr_addr_RBT_COMPARE100%of 1
uvm_pmr_addr_cmp---of 1
uvm_pmr_allocpmr---of 5
uvm_pmr_cache_drain---of 1
uvm_pmr_cache_get40%of 5
uvm_pmr_cache_put100%of 1
uvm_pmr_extract_range80%of 15
uvm_pmr_findnextsegment---of 10
uvm_pmr_findprevsegment---of 10
uvm_pmr_freepageq58%of 21
uvm_pmr_freepages31%of 26
uvm_pmr_get1page53%of 59
uvm_pmr_getone---of 5
uvm_pmr_getpages37%of 96
uvm_pmr_init---of 15
uvm_pmr_insert---of 3
uvm_pmr_insert_addr88%of 8
uvm_pmr_insert_size---of 3
uvm_pmr_isfree---of 11
uvm_pmr_nextsz---of 5
uvm_pmr_nfindsz---of 10
uvm_pmr_pg_to_memtype---of 1
uvm_pmr_pnaddr92%of 12
uvm_pmr_print---of 18
uvm_pmr_remove---of 3
uvm_pmr_remove_1strange25%of 49
uvm_pmr_remove_1strange_reverse---of 20
uvm_pmr_remove_addr---of 1
uvm_pmr_remove_size---of 3
uvm_pmr_rootupdate7%of 43
uvm_pmr_size_RBT_COMPARE100%of 3
uvm_pmr_size_cmp---of 3
uvm_pmr_split---of 42
uvm_pmr_use_inc---of 22
uvm_wait_pla---of 8
uvm_wakeup_pla---of 8
-----------
SUMMARY41%of 339
change_displayparam---of 5
internal_command---of 50
update_leds---of 4
update_modifier---of 9
wskbd_activate---of 3
wskbd_add_mux84%of 6
wskbd_attach---of 25
wskbd_brightness_task---of 4
wskbd_cnattach---of 3
wskbd_cnbell---of 4
wskbd_cndetach---of 3
wskbd_cngetc---of 8
wskbd_cnpollc---of 5
wskbd_debugger---of 4
wskbd_deliver_event---of 8
wskbd_detach---of 23
wskbd_displayioctl---of 1
wskbd_displayioctl_sc77%of 65
wskbd_do_ioctl67%of 3
wskbd_do_ioctl_sc77%of 13
wskbd_do_open29%of 7
wskbd_enable---of 4
wskbd_input---of 15
wskbd_kbd_backlight_task---of 6
wskbd_match---of 5
wskbd_mux_close---of 4
wskbd_mux_open25%of 8
wskbd_pickfree---of 7
wskbd_rawinput---of 3
wskbd_repeat---of 7
wskbd_set_console_display---of 3
wskbd_set_display---of 11
wskbd_set_keymap---of 1
wskbd_translate---of 92
wskbd_update_layout---of 1
wskbdclose23%of 9
wskbddevprint---of 3
wskbdioctl67%of 3
wskbdkqfilter67%of 3
wskbdopen55%of 11
wskbdread---of 5
-----------
SUMMARY65%of 128
sw_reg_iodone---of 1
sw_reg_iodone_internal---of 19
sw_reg_start---of 8
sw_reg_strategy---of 21
swap_off---of 12
swap_on---of 23
swap_print_all---of 17
swapdrum_add---of 3
swapdrum_getsdp---of 11
swaplist_find---of 11
swaplist_insert---of 15
swaplist_trim---of 9
swapmount---of 8
swstrategy---of 13
sys_swapctl---of 36
uvm_hibswap---of 11
uvm_swap_alloc---of 15
uvm_swap_allocpages---of 15
uvm_swap_finicrypt_all---of 12
uvm_swap_free---of 28
uvm_swap_freepages---of 9
uvm_swap_get---of 6
uvm_swap_init---of 7
uvm_swap_initcrypt---of 1
uvm_swap_initcrypt_all45%of 9
uvm_swap_io---of 55
uvm_swap_markbad---of 11
uvm_swap_markdecrypt---of 6
uvm_swap_needdecrypt---of 3
uvm_swap_put---of 1
uvm_swapisfilled---of 3
uvm_swapisfull---of 3
-----------
SUMMARY45%of 9
parity---of 1
stoeplitz_cache_init---of 3
stoeplitz_hash_eaddr---of 1
stoeplitz_hash_ip4---of 1
stoeplitz_hash_ip4port100%of 1
stoeplitz_hash_ip6---of 1
stoeplitz_hash_ip6port100%of 1
stoeplitz_init---of 3
stoeplitz_random_seed---of 1
stoeplitz_to_key---of 9
-----------
SUMMARY100%of 2
ffs_bufatoff56%of 9
ffs_checkoverlap---of 13
ffs_clrblock40%of 5
ffs_fragacct89%of 9
ffs_isblock40%of 5
ffs_isfreeblock40%of 5
ffs_setblock40%of 5
ffs_vinit73%of 11
-----------
SUMMARY60%of 49
uipc_abort100%of 1
uipc_accept84%of 6
uipc_attach58%of 14
uipc_bind74%of 15
uipc_connect100%of 1
uipc_connect267%of 3
uipc_detach67%of 3
uipc_dgram_send95%of 17
uipc_dgram_shutdown100%of 1
uipc_disconnect100%of 1
uipc_listen100%of 3
uipc_peeraddr84%of 6
uipc_rcvd100%of 3
uipc_send86%of 14
uipc_sense---of 3
uipc_setaddr---of 4
uipc_shutdown100%of 3
uipc_sockaddr75%of 4
uipc_sysctl100%of 12
unp_connect81%of 26
unp_connect267%of 6
unp_detach78%of 18
unp_discard---of 1
unp_disconnect80%of 10
unp_dispose75%of 12
unp_externalize74%of 38
unp_gc---of 87
unp_init---of 1
unp_internalize68%of 43
unp_nam2sun---of 10
unp_remove_gcrefs---of 12
unp_restore_gcrefs---of 11
unp_scan---of 12
unp_solock_peer72%of 7
-----------
SUMMARY78%of 267
icmp_do_error69%of 32
icmp_do_exthdr---of 10
icmp_error100%of 4
icmp_init---of 1
icmp_input---of 3
icmp_input_if---of 76
icmp_mtudisc---of 27
icmp_mtudisc_clone---of 11
icmp_mtudisc_timeout---of 8
icmp_ratelimit---of 1
icmp_reflect31%of 33
icmp_send---of 3
icmp_sysctl100%of 6
icmp_sysctl_icmpstat---of 3
iptime100%of 1
-----------
SUMMARY57%of 76
add_child_sensors---of 18
add_sdr_sensor---of 6
bmc_io_wait---of 6
bmc_read---of 3
bmc_write---of 3
bt_buildmsg---of 4
bt_probe---of 9
bt_read---of 3
bt_recvmsg---of 38
bt_reset---of 1
bt_sendmsg---of 27
bt_write---of 7
cmn_buildmsg---of 4
dumpb---of 4
get_sdr---of 17
get_sdr_partial---of 7
getbits---of 7
ipmi_activate---of 3
ipmi_attach---of 1
ipmi_attach_common---of 6
ipmi_cmd---of 3
ipmi_cmd_poll---of 8
ipmi_cmd_wait---of 4
ipmi_cmd_wait_cb---of 1
ipmi_convert---of 23
ipmi_create_thread---of 3
ipmi_get_if---of 3
ipmi_map_regs---of 7
ipmi_match---of 7
ipmi_poll_thread---of 10
ipmi_probe---of 6
ipmi_recvcmd---of 6
ipmi_refresh_sensors---of 3
ipmi_sendcmd---of 3
ipmi_sensor_name---of 21
ipmi_sensor_status---of 22
ipmi_sensor_type---of 10
ipmi_smbios_probe---of 11
ipmi_unmap_regs---of 3
ipmi_watchdog---of 5
ipmi_watchdog_set---of 5
ipmi_watchdog_tickle---of 3
ipmiclose---of 1
ipmiioctl---of 21
ipmilookup---of 1
ipmiopen100%of 1
ipow---of 14
kcs_probe---of 3
kcs_read_data---of 6
kcs_recvmsg---of 9
kcs_reset---of 1
kcs_sendmsg---of 12
kcs_wait---of 16
kcs_write_cmd---of 3
kcs_write_data---of 3
read_sensor---of 7
scan_sig---of 5
signextend---of 1
smic_probe---of 3
smic_read_data---of 9
smic_recvmsg---of 14
smic_reset---of 1
smic_sendmsg---of 8
smic_wait---of 7
smic_write_cmd_data---of 22
-----------
SUMMARY100%of 1
b_to_q87%of 23
catq75%of 8
clalloc100%of 3
clfree---of 5
clrbits---of 12
firstc80%of 5
getc88%of 8
ndflush20%of 10
ndqb---of 13
nextc70%of 10
putc89%of 9
q_to_b48%of 23
unputc88%of 8
-----------
SUMMARY71%of 107
smr_barrier_func---of 1
smr_barrier_impl38%of 8
smr_call_impl43%of 7
smr_dispatch50%of 8
smr_grace_wait---of 1
smr_idle63%of 8
smr_read_enter100%of 1
smr_read_leave67%of 3
smr_startup---of 1
smr_startup_thread---of 3
smr_thread---of 22
smr_wakeup---of 4
-----------
SUMMARY52%of 35
vioscsi_alloc_reqs---of 32
vioscsi_attach---of 8
vioscsi_match---of 1
vioscsi_req_done---of 5
vioscsi_req_get67%of 3
vioscsi_req_put100%of 1
vioscsi_scsi_cmd50%of 20
vioscsi_vq_done---of 4
-----------
SUMMARY55%of 24
audio_activate---of 40
audio_attach---of 28
audio_attach_mi---of 1
audio_blksz_bytes---of 12
audio_buf_done---of 3
audio_buf_init---of 7
audio_buf_rdiscard---of 3
audio_buf_rgetblk---of 1
audio_buf_wakeup---of 4
audio_buf_wcommit---of 1
audio_buf_wgetblk---of 1
audio_calc_sil---of 12
audio_canstart---of 9
audio_clear---of 23
audio_close---of 3
audio_detach---of 14
audio_drain---of 23
audio_event---of 7
audio_fill_sil---of 11
audio_gcd---of 4
audio_getdev---of 3
audio_ioc_getpar---of 1
audio_ioc_getstatus---of 1
audio_ioc_setpar---of 51
audio_ioc_start---of 8
audio_ioc_stop---of 4
audio_ioctl---of 22
audio_ioctl_mixer---of 19
audio_match---of 1
audio_mixer_close---of 5
audio_mixer_devinfo---of 5
audio_mixer_get---of 5
audio_mixer_open---of 4
audio_mixer_read---of 12
audio_mixer_set---of 9
audio_mixer_wakeup---of 4
audio_open---of 26
audio_pintr---of 34
audio_read---of 26
audio_rintr---of 32
audio_setpar---of 62
audio_setpar_blksz---of 34
audio_setpar_nblks---of 10
audio_start---of 1
audio_start_do---of 11
audio_stop---of 27
audio_stop_do---of 5
audio_submatch---of 1
audio_write---of 28
audioclose---of 9
audioioctl---of 11
audiokqfilter---of 7
audioopen25%of 8
audioprint---of 6
audioread---of 5
audiowrite---of 5
filt_audioctlrdetach---of 1
filt_audioctlread---of 4
filt_audiomodify---of 1
filt_audioprocess---of 6
filt_audiordetach---of 1
filt_audioread---of 4
filt_audiowdetach---of 1
filt_audiowrite---of 4
wskbd_initmute---of 8
wskbd_initvol---of 9
wskbd_mixer_cb---of 1
wskbd_mixer_init---of 10
wskbd_mixer_update---of 20
wskbd_set_mixermute---of 4
wskbd_set_mixervolume---of 6
wskbd_set_mixervolume_dev---of 12
wskbd_set_mixervolume_unit---of 6
-----------
SUMMARY25%of 8
bio_delegate_ioctl---of 1
bio_error---of 4
bio_info---of 4
bio_lookup---of 5
bio_mappings_RBT_COMPARE100%of 1
bio_register---of 4
bio_status---of 4
bio_status_init---of 1
bio_unregister---of 6
bio_validate---of 1
bio_warn---of 4
bioattach---of 1
bioclose100%of 1
bioioctl25%of 8
bioopen100%of 1
-----------
SUMMARY46%of 11
__devm_drm_dev_alloc---of 1
drm_activate---of 6
drm_attach---of 19
drm_attach_pci---of 4
drm_attach_platform---of 1
drm_dequeue_event---of 5
drm_detach---of 11
drm_dev_enter---of 1
drm_dev_exit---of 1
drm_dev_get---of 3
drm_dev_init_release---of 1
drm_dev_put---of 5
drm_dev_register---of 44
drm_dev_unplug---of 1
drm_dev_unregister---of 20
drm_dmamem_alloc---of 7
drm_dmamem_free---of 3
drm_file_cmp---of 1
drm_file_tree_SPLAY---of 12
drm_file_tree_SPLAY_INSERT---of 5
drm_file_tree_SPLAY_MINMAX---of 8
drm_file_tree_SPLAY_REMOVE---of 5
drm_find_description---of 9
drm_find_file_by_minor---of 3
drm_get_device_from_kdev50%of 4
drm_getpciinfo---of 3
drm_minor_acquire---of 4
drm_minor_alloc---of 8
drm_minor_alloc_release---of 5
drm_minor_release---of 5
drm_order---of 4
drm_pci_alloc---of 3
drm_pci_free---of 4
drm_pciprobe---of 9
drm_probe---of 5
drm_put_dev---of 5
drm_quiesce---of 4
drm_wakeup---of 1
drmclose---of 15
drmkqfilter---of 10
drmmmap---of 1
drmopen9%of 24
drmprint---of 3
drmread---of 18
drmsubmatch---of 3
filt_drmdetach---of 1
filt_drmkms---of 3
filt_drmread---of 3
filt_drmreaddetach---of 1
kasprintf---of 3
-----------
SUMMARY15%of 28
in6_pcbaddrisavail100%of 1
in6_pcbaddrisavail_lock90%of 30
in6_pcbconnect76%of 33
in6_pcbhash100%of 1
in6_pcbhash_lookup50%of 18
in6_pcblookup100%of 1
in6_pcblookup_listen50%of 12
in6_pcblookup_lock58%of 7
in6_pcbnotify---of 57
in6_pcbrtentry100%of 6
in6_peeraddr100%of 1
in6_setpeeraddr---of 1
in6_setsockaddr100%of 1
in6_sockaddr100%of 1
-----------
SUMMARY75%of 112
free55%of 24
kmeminit---of 7
kmeminit_nkmempages---of 3
malloc54%of 47
malloc_printit---of 6
mallocarray60%of 5
sysctl_malloc73%of 33
-----------
SUMMARY60%of 109
igmp_checktimer---of 11
igmp_fasttimo---of 5
igmp_init---of 1
igmp_input---of 3
igmp_input_if---of 80
igmp_joingroup78%of 9
igmp_leavegroup67%of 6
igmp_sendpkt75%of 4
igmp_slowtimo---of 7
igmp_sysctl100%of 5
igmp_sysctl_igmpstat---of 1
rti_delete80%of 5
rti_fill---of 7
rti_find---of 8
-----------
SUMMARY80%of 29
uvm_vnp_setsize100%of 4
uvm_vnp_sync45%of 18
uvm_vnp_terminate42%of 12
uvm_vnp_uncache67%of 6
uvn_attach64%of 25
uvn_cluster50%of 4
uvn_detach50%of 14
uvn_flush61%of 56
uvn_get57%of 23
uvn_init---of 1
uvn_io61%of 33
uvn_put60%of 5
uvn_reference100%of 1
-----------
SUMMARY59%of 201
ddb_sysctl50%of 12
-----------
SUMMARY50%of 12
ufs_ihash---of 1
ufs_ihashget75%of 8
ufs_ihashinit---of 1
ufs_ihashins78%of 9
ufs_ihashlookup---of 7
ufs_ihashrem60%of 5
-----------
SUMMARY73%of 22
-----------
SUMMARY---of 0
fill_file90%of 58
fill_kproc83%of 58
hw_sysctl85%of 94
kern_sysctl77%of 60
kern_sysctl_dirs89%of 61
sys_sysctl91%of 22
sysctl__string92%of 12
sysctl_audio---of 10
sysctl_bounded_arr84%of 6
sysctl_cptime2---of 12
sysctl_cpustats---of 14
sysctl_diskinit43%of 19
sysctl_doproc90%of 48
sysctl_file75%of 123
sysctl_hwbattery40%of 15
sysctl_hwchargemode---of 5
sysctl_hwchargestart---of 5
sysctl_hwchargestop---of 5
sysctl_int100%of 8
sysctl_int_bounded93%of 14
sysctl_int_lower93%of 13
sysctl_intrcnt---of 1
sysctl_proc_args70%of 36
sysctl_proc_cwd86%of 14
sysctl_proc_nobroadcastkill89%of 18
sysctl_proc_vmmap67%of 18
sysctl_quad---of 8
sysctl_rdint100%of 6
sysctl_rdquad100%of 6
sysctl_rdstring100%of 6
sysctl_rdstruct100%of 6
sysctl_securelevel_int47%of 13
sysctl_sensors79%of 14
sysctl_string100%of 8
sysctl_struct100%of 8
sysctl_sysvipc86%of 21
sysctl_tstring100%of 1
sysctl_utc_offset60%of 5
sysctl_video---of 10
-----------
SUMMARY82%of 791
ipsec_delete_policy---of 21
ipsec_get_acquire---of 7
ipsec_unref_acquire---of 1
ipsp_acquire_sa---of 16
ipsp_delete_acquire---of 3
ipsp_delete_acquire_locked---of 3
ipsp_delete_acquire_timer---of 3
ipsp_pending_acquire---of 7
ipsp_spd_inp---of 12
ipsp_spd_lookup6%of 150
ipsp_unref_acquire_locked---of 7
spd_table_add---of 10
spd_table_get---of 6
spd_table_walk38%of 8
-----------
SUMMARY7%of 158
clockintr_advance100%of 4
clockintr_bind---of 5
clockintr_cancel100%of 1
clockintr_cancel_locked34%of 9
clockintr_cpu_init---of 36
clockintr_dispatch---of 32
clockintr_hardclock---of 8
clockintr_schedule---of 1
clockintr_schedule_locked40%of 10
clockintr_stagger---of 4
clockintr_trigger---of 4
clockintr_unbind---of 5
clockqueue_init---of 3
clockqueue_intrclock_install---of 3
clockqueue_intrclock_reprogram---of 6
clockqueue_next---of 3
clockqueue_pend_delete---of 4
clockqueue_pend_insert58%of 7
clockrequest_advance---of 5
clockrequest_advance_random---of 6
db_show_all_clockintr---of 6
db_show_clockintr---of 3
db_show_clockintr_cpu---of 17
intrclock_rearm---of 1
intrclock_trigger---of 1
nsec_advance---of 4
sysctl_clockintr50%of 10
-----------
SUMMARY52%of 41
-----------
SUMMARY---of 0
ppp_pkt_free---of 4
ppp_timeout---of 9
pppasyncctlp---of 1
pppasyncrelinq---of 6
pppasyncstart---of 58
pppclose---of 4
pppdumpb---of 5
pppfcs---of 7
pppinput---of 75
ppplogchar---of 10
pppopen38%of 16
ppppkt---of 6
pppread---of 14
pppstart---of 10
pppstart_internal---of 10
ppptioctl---of 14
pppwrite---of 15
-----------
SUMMARY38%of 16
efi_adapt_error---of 10
eficlose---of 1
efiioc_get_table---of 7
efiioc_var_get---of 15
efiioc_var_next---of 12
efiioc_var_set---of 9
efiioctl---of 6
efiopen100%of 1
-----------
SUMMARY100%of 1
udf_checkexp---of 1
udf_checktag---of 3
udf_fhtovp---of 1
udf_find_partmaps---of 14
udf_get_mpartmap---of 1
udf_get_spartmap---of 10
udf_get_vpartmap---of 1
udf_init---of 1
udf_mount---of 11
udf_mountfs---of 45
udf_quotactl---of 1
udf_readlblks---of 1
udf_root---of 3
udf_start---of 1
udf_statfs---of 1
udf_sync---of 1
udf_sysctl100%of 1
udf_unmount---of 6
udf_vget---of 24
udf_vptofh---of 1
-----------
SUMMARY100%of 1
_rrw_init_flags100%of 1
_rw_init_flags100%of 1
_rw_obj_alloc_flags100%of 1
rrw_enter100%of 5
rrw_exit60%of 5
rrw_status67%of 3
rw_assert_anylock50%of 6
rw_assert_rdlock---of 5
rw_assert_unlocked50%of 4
rw_assert_wrlock40%of 5
rw_do_exit---of 4
rw_enter60%of 10
rw_enter_diag34%of 9
rw_enter_read50%of 4
rw_enter_write100%of 3
rw_exit46%of 11
rw_exit_read46%of 11
rw_exit_write46%of 11
rw_obj_free60%of 5
rw_obj_hold50%of 4
rw_obj_init---of 1
rw_status100%of 3
-----------
SUMMARY56%of 102
tcp_abort40%of 5
tcp_accept40%of 5
tcp_attach34%of 18
tcp_bind86%of 7
tcp_connect92%of 23
tcp_ctloutput90%of 39
tcp_detach60%of 5
tcp_disconnect40%of 5
tcp_dodisconnect53%of 17
tcp_fill_info91%of 11
tcp_ident67%of 33
tcp_listen90%of 10
tcp_peeraddr40%of 5
tcp_rcvd45%of 9
tcp_rcvoob39%of 13
tcp_send70%of 10
tcp_sendoob50%of 14
tcp_sense---of 5
tcp_shutdown56%of 20
tcp_sockaddr80%of 5
tcp_sysctl77%of 34
tcp_sysctl_tcpstat50%of 12
tcp_update_rcvspace---of 9
tcp_update_sndspace73%of 11
tcp_usrclosed---of 13
-----------
SUMMARY67%of 311
sd_buf_done---of 16
sd_cmd_rw10---of 1
sd_cmd_rw12---of 1
sd_cmd_rw16---of 1
sd_cmd_rw6---of 1
sd_flush---of 6
sd_get_parms---of 60
sd_interpret_sense---of 11
sd_ioctl_cache---of 15
sd_ioctl_inquiry---of 4
sd_read_cap---of 6
sd_read_cap_10---of 6
sd_read_cap_16---of 6
sd_thin_pages---of 15
sd_thin_params---of 6
sd_vpd_block_limits---of 6
sd_vpd_thin---of 4
sdactivate---of 17
sdattach---of 18
sdclose27%of 19
sddetach---of 1
sddump---of 13
sdgetdisklabel15%of 40
sdioctl31%of 39
sdmatch---of 1
sdminphys34%of 9
sdopen21%of 29
sdread100%of 1
sdsize---of 12
sdstart43%of 14
sdstrategy45%of 9
sdwrite100%of 1
viscpy---of 7
-----------
SUMMARY28%of 161
msg_copyin93%of 13
msg_copyout---of 7
msg_create---of 3
msg_dequeue---of 1
msg_enqueue100%of 1
msg_free---of 1
msg_lookup---of 5
msginit---of 1
que_create54%of 13
que_free80%of 5
que_key_lookup---of 7
que_lookup---of 6
que_wakewriters---of 6
sys_msgctl92%of 25
sys_msgget72%of 14
sys_msgrcv83%of 28
sys_msgsnd70%of 23
sysctl_sysvmsg67%of 9
-----------
SUMMARY78%of 131
filt_ugenrdetach---of 1
filt_ugenread_intr---of 1
filt_ugenread_isoc---of 4
ugen_attach---of 7
ugen_clear_iface_eps---of 24
ugen_detach---of 18
ugen_do_close---of 17
ugen_do_ioctl---of 59
ugen_do_read---of 43
ugen_do_write---of 16
ugen_get_alt_index---of 3
ugen_isoc_rintr---of 28
ugen_match---of 1
ugen_set_config---of 32
ugen_set_interface---of 11
ugenclose---of 5
ugenintr---of 5
ugenioctl---of 3
ugenkqfilter---of 10
ugenopen6%of 35
ugenread---of 3
ugenwrite---of 3
-----------
SUMMARY6%of 35
-----------
SUMMARY---of 0
in_addhost---of 1
in_addmulti84%of 12
in_broadcast85%of 13
in_canforward100%of 4
in_control100%of 4
in_delmulti84%of 6
in_hasmulti89%of 9
in_ifdetach100%of 8
in_ifinit72%of 28
in_ifscrub---of 5
in_insert_prefix---of 4
in_ioctl89%of 42
in_ioctl_change_ifaddr78%of 49
in_ioctl_get95%of 19
in_ioctl_set_ifaddr75%of 16
in_len2mask---of 10
in_mask2len---of 14
in_nam2sin80%of 5
in_prefixlen2mask100%of 1
in_purgeaddr78%of 9
in_remove_prefix---of 3
in_sa2sin---of 4
in_scrubhost---of 1
in_socktrim---of 4
-----------
SUMMARY84%of 225
filt_soexcept79%of 14
filt_sordetach100%of 1
filt_soread88%of 24
filt_sormodify100%of 7
filt_sorprocess100%of 12
filt_sowdetach100%of 1
filt_sowmodify100%of 7
filt_sowprocess100%of 12
filt_sowrite94%of 15
m_getuio88%of 16
sbsync---of 6
so_print---of 3
soabort---of 1
soaccept58%of 7
soalloc90%of 10
sobind100%of 3
sobuf_print---of 1
soclose55%of 33
soconnect80%of 10
soconnect2100%of 7
socreate90%of 10
sodisconnect---of 5
sofilt_lock---of 4
sofilt_unlock---of 4
sofree72%of 25
sogetopt93%of 39
sohasoutofband---of 1
soidle---of 3
soinit---of 1
solisten77%of 13
somove35%of 119
soo_kqfilter100%of 5
soput---of 1
soreaper---of 1
soreceive73%of 198
sorflush60%of 5
sorwakeup91%of 11
sosend90%of 76
sosetopt92%of 60
soshutdown100%of 5
sosplice83%of 41
sotask---of 3
sounsplice56%of 27
sowwakeup100%of 8
-----------
SUMMARY75%of 821
clock_secs_to_ymdhms100%of 14
clock_ymdhms_to_secs---of 17
-----------
SUMMARY100%of 14
sync_fsync---of 10
sync_inactive---of 4
sync_print---of 1
syncer_thread---of 25
vfs_allocate_syncvnode---of 10
vn_initialize_syncerd---of 1
vn_syncer_add_to_worklist67%of 6
-----------
SUMMARY67%of 6
db_show_all_pools---of 20
phtree_RBT_COMPARE100%of 1
pool_allocator_alloc---of 5
pool_allocator_free---of 1
pool_cache_cpus_info---of 1
pool_cache_info---of 1
pool_cache_init---of 1
pool_cache_pool_info---of 1
pool_chk---of 10
pool_chk_page---of 17
pool_destroy29%of 21
pool_do_get70%of 23
pool_do_put69%of 22
pool_gc_pages---of 15
pool_gc_sched---of 1
pool_get32%of 22
pool_get_done---of 1
pool_init36%of 25
pool_lock_mtx_assert_locked67%of 3
pool_lock_mtx_assert_unlocked67%of 3
pool_lock_mtx_enter100%of 1
pool_lock_mtx_enter_try---of 1
pool_lock_mtx_init100%of 1
pool_lock_mtx_leave100%of 1
pool_lock_mtx_sleep---of 1
pool_lock_rw_assert_locked100%of 1
pool_lock_rw_assert_unlocked67%of 3
pool_lock_rw_enter100%of 1
pool_lock_rw_enter_try---of 1
pool_lock_rw_init---of 1
pool_lock_rw_leave100%of 1
pool_lock_rw_sleep---of 1
pool_multi_alloc67%of 3
pool_multi_alloc_ni67%of 3
pool_multi_free67%of 3
pool_multi_free_ni---of 3
pool_p_alloc65%of 17
pool_p_free55%of 11
pool_p_insert---of 7
pool_p_remove---of 5
pool_page_alloc100%of 1
pool_page_free100%of 1
pool_prime43%of 14
pool_print1---of 33
pool_print_pagelist---of 9
pool_printit---of 1
pool_put69%of 16
pool_reclaim---of 13
pool_reclaim_all---of 4
pool_request---of 1
pool_request_init---of 1
pool_runqueue---of 17
pool_set_constraints100%of 1
pool_sethardlimit67%of 3
pool_sethiwat---of 3
pool_setlowat---of 5
pool_update_curpage---of 3
pool_wakeup---of 3
pool_walk---of 14
sysctl_dopool89%of 17
-----------
SUMMARY58%of 219
cd1400_channel_cmd---of 5
cy_attach---of 7
cy_enable_transmitter---of 1
cy_intr---of 48
cy_modem_control---of 13
cy_poll---of 28
cy_probe_common---of 9
cy_speed---of 8
cyclose---of 4
cyioctl---of 15
cyopen7%of 33
cyparam---of 34
cyread---of 1
cystart---of 4
cystop---of 4
cytty---of 1
cywrite---of 1
-----------
SUMMARY7%of 33
ast75%of 8
child_return---of 15
fault---of 1
kerntrap25%of 12
kpageflttrap45%of 18
syscall34%of 59
trap_print---of 3
upageflttrap67%of 9
usertrap30%of 24
-----------
SUMMARY39%of 130
ufsdirhash_add64%of 19
ufsdirhash_adjfree---of 10
ufsdirhash_build46%of 64
ufsdirhash_checkblock11%of 19
ufsdirhash_delslot67%of 12
ufsdirhash_dirtrunc43%of 19
ufsdirhash_enduseful50%of 8
ufsdirhash_findfree42%of 24
ufsdirhash_findslot72%of 7
ufsdirhash_free56%of 9
ufsdirhash_getprev---of 6
ufsdirhash_hash---of 1
ufsdirhash_init---of 1
ufsdirhash_lookup66%of 46
ufsdirhash_move40%of 5
ufsdirhash_newblk29%of 7
ufsdirhash_recycle---of 12
ufsdirhash_remove62%of 13
ufsdirhash_uninit---of 3
-----------
SUMMARY50%of 252
e2fs_sbcheck---of 34
e2fs_sbfill---of 12
ext2fs_cgupdate---of 8
ext2fs_fhtovp---of 8
ext2fs_flushfiles---of 3
ext2fs_init---of 1
ext2fs_mount---of 32
ext2fs_mountfs---of 18
ext2fs_mountroot---of 7
ext2fs_reload---of 7
ext2fs_reload_vnode---of 7
ext2fs_sbupdate---of 3
ext2fs_statfs---of 12
ext2fs_sync---of 11
ext2fs_sync_vnode---of 8
ext2fs_sysctl100%of 1
ext2fs_unmount---of 9
ext2fs_vget---of 19
ext2fs_vptofh---of 1
-----------
SUMMARY100%of 1
counters_alloc67%of 3
counters_alloc_ncpus---of 1
counters_free100%of 1
counters_read88%of 8
counters_zero---of 8
cpumem_first---of 1
cpumem_free---of 1
cpumem_get---of 1
cpumem_malloc---of 1
cpumem_malloc_ncpus---of 1
cpumem_next---of 1
cpumem_put---of 1
percpu_init---of 1
-----------
SUMMARY84%of 12
pcppi_attach---of 5
pcppi_bell80%of 15
pcppi_bell_stop---of 3
pcppi_kbd_bell100%of 1
pcppi_match---of 12
-----------
SUMMARY82%of 16
msi_addroute---of 5
msi_allocidtvec---of 7
msi_delroute---of 4
msi_hwmask---of 5
msi_hwunmask---of 5
msix_addroute---of 6
msix_delroute---of 6
msix_hwmask---of 6
msix_hwunmask---of 5
pci_attach_hook---of 1
pci_bus_maxdevs100%of 1
pci_conf_read29%of 7
pci_conf_size50%of 4
pci_conf_write29%of 7
pci_decompose_tag72%of 7
pci_dev_postattach---of 1
pci_init_extents---of 15
pci_intr_disestablish---of 1
pci_intr_enable_msivec---of 6
pci_intr_establish---of 1
pci_intr_establish_cpu---of 6
pci_intr_map---of 23
pci_intr_map_msi---of 4
pci_intr_map_msivec---of 5
pci_intr_map_msix---of 6
pci_intr_string---of 6
pci_lookup_segment---of 3
pci_make_tag67%of 3
pci_mcfg_init---of 3
pci_mcfg_map_bus---of 4
pci_min_powerstate---of 1
pci_msix_table_map---of 4
pci_msix_table_unmap---of 3
pci_probe_device_hook---of 1
pci_set_powerstate_md---of 1
-----------
SUMMARY49%of 29
in_baddynamic---of 5
in_init---of 1
in_losing---of 5
in_pcbaddrisavail100%of 1
in_pcbaddrisavail_lock88%of 24
in_pcballoc58%of 7
in_pcbbind100%of 1
in_pcbbind_locked79%of 37
in_pcbconnect75%of 12
in_pcbdetach100%of 9
in_pcbdisconnect67%of 3
in_pcbhash100%of 1
in_pcbhash_insert88%of 8
in_pcbhash_lookup44%of 16
in_pcbinit---of 1
in_pcblhash---of 1
in_pcblookup100%of 1
in_pcblookup_listen54%of 13
in_pcblookup_local_lock73%of 37
in_pcblookup_lock50%of 8
in_pcbnotifyall---of 14
in_pcbpickport67%of 15
in_pcbref100%of 3
in_pcbrehash100%of 5
in_pcbresize---of 11
in_pcbrtentry75%of 4
in_pcbselsrc71%of 24
in_pcbset_laddr---of 9
in_pcbset_rtableid100%of 7
in_pcbunref50%of 12
in_pcbunset_faddr---of 7
in_pcbunset_laddr86%of 7
in_peeraddr67%of 3
in_rootonly---of 6
in_rtchange---of 3
in_setpeeraddr67%of 3
in_setsockaddr100%of 3
in_sockaddr67%of 3
-----------
SUMMARY74%of 267
-----------
SUMMARY---of 0
dosendsyslog27%of 30
filt_logmodify---of 1
filt_logprocess---of 6
filt_logrdetach---of 1
filt_logread---of 3
initconsbuf---of 1
initmsgbuf---of 14
logclose---of 4
logioctl---of 15
logkqfilter---of 3
logopen67%of 3
logread---of 17
logstash_insert---of 7
logstash_remove---of 9
logstash_sendsyslog---of 5
logtick---of 9
logwakeup100%of 1
msgbuf_getlen---of 3
msgbuf_putchar58%of 7
msgbuf_putchar_locked---of 6
sys_sendsyslog50%of 8
-----------
SUMMARY39%of 49
sr_alloc_resources---of 3
sr_already_assembled---of 5
sr_attach---of 5
sr_bio_handler---of 22
sr_bio_ioctl---of 1
sr_block_get---of 1
sr_block_put---of 1
sr_boot_assembly---of 99
sr_ccb_alloc---of 6
sr_ccb_done---of 7
sr_ccb_free---of 5
sr_ccb_get---of 3
sr_ccb_put---of 1
sr_ccb_rw---of 4
sr_checksum---of 1
sr_checksum_print---of 1
sr_chunk_in_use---of 13
sr_chunks_unwind---of 7
sr_detach---of 10
sr_discipline_free---of 13
sr_discipline_init---of 9
sr_discipline_shutdown---of 24
sr_disk_attach34%of 6
sr_error---of 1
sr_find_discipline---of 5
sr_free_resources---of 5
sr_hibernate_io---of 12
sr_hotplug_register---of 5
sr_hotplug_unregister---of 7
sr_hotspare---of 33
sr_hotspare_rebuild---of 27
sr_hotspare_rebuild_callback---of 1
sr_info---of 1
sr_ioctl_createraid---of 92
sr_ioctl_deleteraid---of 8
sr_ioctl_discipline---of 8
sr_ioctl_disk---of 17
sr_ioctl_inq---of 4
sr_ioctl_installboot---of 32
sr_ioctl_setstate---of 14
sr_ioctl_vol---of 16
sr_map_root---of 27
sr_match---of 1
sr_meta_attach---of 21
sr_meta_clear---of 8
sr_meta_getdevname---of 4
sr_meta_init---of 8
sr_meta_init_complete---of 1
sr_meta_native_attach---of 21
sr_meta_native_bootprobe---of 16
sr_meta_native_probe---of 6
sr_meta_native_read---of 3
sr_meta_native_write---of 3
sr_meta_opt_handler---of 3
sr_meta_opt_load---of 9
sr_meta_probe---of 15
sr_meta_read---of 12
sr_meta_rw---of 3
sr_meta_save---of 17
sr_meta_save_callback---of 3
sr_meta_validate---of 15
sr_quiesce---of 5
sr_raid_inquiry---of 4
sr_raid_intr---of 3
sr_raid_read_cap---of 5
sr_raid_recreate_wu---of 7
sr_raid_request_sense---of 1
sr_raid_start_stop---of 1
sr_raid_startwu---of 10
sr_raid_sync---of 4
sr_raid_tur---of 4
sr_rebuild---of 33
sr_rebuild_init---of 28
sr_rebuild_percent---of 3
sr_rebuild_start---of 3
sr_roam_chunks---of 7
sr_rw---of 14
sr_schedule_wu---of 13
sr_scsi_cmd---of 37
sr_scsi_done---of 6
sr_scsi_ioctl---of 4
sr_scsi_probe---of 6
sr_scsi_wu_get---of 1
sr_scsi_wu_put---of 4
sr_sensors_create---of 4
sr_sensors_delete---of 3
sr_sensors_refresh---of 6
sr_set_chunk_state---of 4
sr_set_vol_state---of 7
sr_shutdown---of 5
sr_uuid_format---of 1
sr_uuid_generate---of 1
sr_uuid_print---of 1
sr_validate_io---of 10
sr_validate_stripsize---of 5
sr_warn---of 1
sr_wu_alloc---of 4
sr_wu_done---of 3
sr_wu_done_callback---of 27
sr_wu_enqueue_ccb---of 3
sr_wu_free---of 13
sr_wu_get---of 3
sr_wu_init---of 3
sr_wu_put---of 6
sr_wu_release_ccbs---of 4
-----------
SUMMARY34%of 6
sysctl_ucominit29%of 14
tiocm_to_ucom---of 12
ucom_attach---of 6
ucom_break---of 3
ucom_cleanup---of 15
ucom_detach---of 20
ucom_do_close---of 4
ucom_do_ioctl---of 22
ucom_do_open---of 46
ucom_dtr---of 3
ucom_hwiflow---of 1
ucom_lock---of 1
ucom_match---of 1
ucom_rts---of 3
ucom_shutdown---of 5
ucom_status_change---of 4
ucom_to_tiocm---of 1
ucom_unlock---of 1
ucomclose---of 5
ucomioctl---of 5
ucomopen29%of 7
ucomparam---of 14
ucomprint---of 5
ucomread---of 6
ucomreadcb---of 16
ucomstart---of 16
ucomstartread---of 5
ucomstop---of 1
ucomsubmatch---of 4
ucomtty---of 3
ucomwrite---of 5
ucomwritecb---of 6
-----------
SUMMARY29%of 21
_bus_dmamap_create---of 3
_bus_dmamap_destroy---of 1
_bus_dmamap_load50%of 4
_bus_dmamap_load_buffer47%of 32
_bus_dmamap_load_mbuf50%of 8
_bus_dmamap_load_raw---of 34
_bus_dmamap_load_uio---of 10
_bus_dmamap_sync100%of 1
_bus_dmamap_unload100%of 1
_bus_dmamem_alloc---of 1
_bus_dmamem_alloc_range---of 9
_bus_dmamem_free---of 7
_bus_dmamem_map---of 11
_bus_dmamem_mmap---of 8
_bus_dmamem_unmap---of 4
-----------
SUMMARY50%of 46
cpu_amd64speed100%of 1
cpu_check_vmm_cap---of 32
cpu_freq---of 1
cpu_freq_ctr---of 4
cpu_hz_update_sensor---of 3
cpu_topology---of 14
identifycpu---of 109
intelcore_update_sensor---of 12
via_nano_setup---of 20
via_update_sensor---of 1
-----------
SUMMARY100%of 1
__explicit_bzero_hook100%of 1
explicit_bzero100%of 1
-----------
SUMMARY100%of 2
pledge_ioctl_vmm_machdep---of 1
start_vmm_on_cpu34%of 12
stop_vmm_on_cpu---of 7
svm_exit_reason_decode---of 144
svm_fault_page---of 3
svm_get_guest_faulttype---of 1
svm_handle_exit---of 39
svm_handle_hlt---of 1
svm_handle_inout---of 8
svm_handle_msr---of 27
svm_handle_np_fault---of 9
svm_handle_xsetbv---of 5
svm_set_clean---of 3
svm_set_dirty---of 3
svm_setmsrbr---of 5
svm_setmsrbrw---of 5
svm_setmsrbw---of 5
vcpu_deinit---of 4
vcpu_deinit_svm---of 9
vcpu_deinit_vmx---of 9
vcpu_init50%of 4
vcpu_init_svm---of 10
vcpu_init_vmx8%of 25
vcpu_readregs_svm---of 11
vcpu_readregs_vmx42%of 36
vcpu_reload_vmcs_vmx50%of 6
vcpu_reset_regs50%of 4
vcpu_reset_regs_svm---of 6
vcpu_reset_regs_vmx27%of 61
vcpu_run_svm---of 64
vcpu_run_vmx---of 92
vcpu_state_decode---of 3
vcpu_vmx_check_cap---of 15
vcpu_vmx_compute_ctrl25%of 62
vcpu_writeregs_svm---of 11
vcpu_writeregs_vmx47%of 39
vm_impl_deinit100%of 1
vm_impl_init63%of 8
vm_intr_pending---of 4
vm_mprotect_ept58%of 21
vm_run37%of 11
vm_rwregs63%of 8
vm_rwvmparams69%of 19
vmclear_on_cpu---of 5
vmm_activate_machdep---of 9
vmm_alloc_vpid60%of 5
vmm_attach_machdep---of 16
vmm_enabled---of 4
vmm_fpurestore---of 8
vmm_fpusave---of 3
vmm_free_vpid---of 1
vmm_get_guest_cpu_cpl---of 11
vmm_get_guest_cpu_mode---of 9
vmm_get_guest_memtype50%of 6
vmm_gpa_is_valid---of 8
vmm_handle_cpuid---of 45
vmm_handle_cpuid_0xd---of 7
vmm_handle_xsetbv---of 5
vmm_init_pvclock---of 10
vmm_inject_db---of 1
vmm_inject_gp---of 1
vmm_inject_ud---of 1
vmm_pat_is_valid---of 9
vmm_quiesce_vmx---of 12
vmm_start75%of 4
vmm_stop---of 10
vmm_translate_gva---of 18
vmm_update_pvclock75%of 4
vmmioctl_machdep100%of 6
vmx_exit_reason_decode---of 3
vmx_fault_page---of 10
vmx_get_exit_info---of 3
vmx_get_exit_qualification---of 3
vmx_get_guest_faulttype---of 4
vmx_handle_cr---of 27
vmx_handle_cr0_write---of 19
vmx_handle_cr4_write---of 5
vmx_handle_exit---of 43
vmx_handle_hlt---of 6
vmx_handle_inout---of 6
vmx_handle_intr---of 3
vmx_handle_misc_enable_msr---of 1
vmx_handle_np_fault---of 9
vmx_handle_rdmsr---of 7
vmx_handle_wrmsr---of 24
vmx_handle_xsetbv---of 7
vmx_instruction_error_decode---of 22
vmx_load_pdptes---of 22
vmx_mprotect_ept45%of 20
vmx_pmap_find_pte_ept---of 6
vmx_setmsrbr---of 4
vmx_setmsrbrw---of 4
vmx_setmsrbw---of 4
-----------
SUMMARY40%of 362
filt_generic_detach---of 1
filt_generic_readwrite---of 3
vop_generic_abortop100%of 3
vop_generic_bmap---of 7
vop_generic_bwrite100%of 1
vop_generic_kqfilter---of 3
vop_generic_lookup---of 1
vop_generic_revoke17%of 18
-----------
SUMMARY32%of 22
virtio_alloc_vq---of 17
virtio_check_vq---of 6
virtio_check_vqs---of 9
virtio_dequeue63%of 8
virtio_dequeue_commit75%of 4
virtio_device_string---of 3
virtio_enqueue72%of 7
virtio_enqueue_abort---of 5
virtio_enqueue_commit78%of 9
virtio_enqueue_p100%of 3
virtio_enqueue_prep67%of 3
virtio_enqueue_reserve25%of 16
virtio_enqueue_trim80%of 10
virtio_free_vq---of 4
virtio_init_vq---of 13
virtio_nused---of 1
virtio_postpone_intr---of 1
virtio_postpone_intr_far---of 1
virtio_postpone_intr_smart---of 1
virtio_reinit_end---of 1
virtio_reinit_start---of 7
virtio_reset---of 1
virtio_start_vq_intr---of 3
virtio_stop_vq_intr67%of 3
vq_alloc_entry---of 3
vq_free_entry---of 1
-----------
SUMMARY62%of 63
com_activate---of 9
com_attach_subr---of 109
com_detach---of 7
com_enable_debugport---of 3
com_fifo_probe---of 34
com_raisedtr---of 3
com_read_reg---of 3
com_resume---of 58
com_write_reg67%of 3
comclose50%of 6
comcn_read_reg---of 3
comcn_write_reg---of 3
comcnattach---of 3
comcngetc---of 8
comcninit---of 4
comcnpollc---of 1
comcnprobe---of 15
comcnputc77%of 13
comdiag---of 1
cominit---of 5
comintr---of 45
comioctl85%of 20
comopen50%of 76
comparam53%of 53
comprobe1---of 6
compwroff33%of 34
comread100%of 1
comsoft---of 16
comspeed---of 5
comstart58%of 21
comstop100%of 3
comtty100%of 1
comwrite100%of 1
-----------
SUMMARY55%of 232
-----------
SUMMARY---of 0
component_pop---of 7
component_push---of 4
namei68%of 68
ndinitat100%of 1
vfs_lookup62%of 93
vfs_relookup31%of 26
-----------
SUMMARY60%of 188
tcp_canceltimers100%of 1
tcp_slowtimo---of 1
tcp_timer_2msl---of 14
tcp_timer_delack---of 7
tcp_timer_freesack---of 4
tcp_timer_init---of 9
tcp_timer_keep---of 15
tcp_timer_persist---of 12
tcp_timer_reaper---of 1
tcp_timer_rexmt---of 39
-----------
SUMMARY100%of 1
ipsec_adjust_mtu17%of 18
ipsec_hdrsz---of 12
ipsp_process_done---of 27
ipsp_process_packet---of 73
-----------
SUMMARY17%of 18
kstat_copy---of 1
kstat_cpu_enter---of 1
kstat_cpu_leave---of 1
kstat_create34%of 21
kstat_destroy100%of 1
kstat_id_tree_RBT_COMPARE100%of 1
kstat_init---of 3
kstat_install43%of 7
kstat_kv_init---of 1
kstat_kv_unit_init---of 3
kstat_nm_tree_RBT_COMPARE43%of 7
kstat_pv_tree_RBT_COMPARE43%of 7
kstat_read---of 1
kstat_read_nop---of 1
kstat_remove---of 3
kstat_set_cpu---of 3
kstat_set_mutex67%of 3
kstat_set_rlock---of 3
kstat_set_wlock---of 3
kstat_strcheck---of 9
kstatattach---of 1
kstatclose100%of 1
kstatioc_enter---of 5
kstatioc_find_id---of 5
kstatioc_find_nm---of 5
kstatioc_find_pv---of 5
kstatioc_leave---of 15
kstatioc_nfind_id---of 5
kstatioc_nfind_nm---of 5
kstatioc_nfind_pv---of 5
kstatioctl8%of 27
kstatopen100%of 1
-----------
SUMMARY32%of 76
pf_addr_copyout---of 5
pf_addr_setup---of 6
pf_begin_rules---of 5
pf_calc_chksum---of 5
pf_cleanup_tgetrule---of 3
pf_commit_queues---of 5
pf_commit_rules---of 19
pf_create_queues---of 28
pf_find_trans---of 7
pf_free_queues---of 4
pf_free_trans---of 6
pf_hash_rule---of 1
pf_hash_rule_addr---of 7
pf_init_tgetrule---of 1
pf_kif_setup---of 5
pf_open_trans---of 5
pf_pool_copyin---of 1
pf_qid2qname---of 4
pf_qid_unref---of 6
pf_qname2qid---of 1
pf_queue_manager---of 1
pf_remove_queues---of 7
pf_rm_rule---of 26
pf_rollback_rules---of 11
pf_rollback_trans---of 4
pf_rtlabel_add---of 4
pf_rtlabel_copyout---of 5
pf_rtlabel_remove---of 3
pf_rule_checkaf---of 13
pf_rule_copyin---of 40
pf_rule_free---of 3
pf_states_clr---of 10
pf_states_get---of 8
pf_sysctl67%of 3
pf_tag2tagname---of 4
pf_tag_ref---of 4
pf_tag_unref---of 6
pf_tagname2tag---of 1
pf_trans_set_commit---of 9
pf_validate_range---of 6
pfattach---of 6
pfclose22%of 14
pfioctl1%of 632
pfopen100%of 1
tag2tagname---of 4
tag_unref---of 6
tagname2tag---of 13
-----------
SUMMARY2%of 650
pledge_ioctl_vmm---of 12
vcpu_must_stop---of 3
vm_create55%of 11
vm_create_check_mem_ranges100%of 16
vm_find72%of 7
vm_find_vcpu50%of 6
vm_get_info54%of 15
vm_resetcpu67%of 9
vm_share_mem47%of 15
vm_teardown34%of 9
vm_terminate23%of 9
vmm_activate---of 6
vmm_attach---of 1
vmm_probe---of 1
vmmclose100%of 1
vmmioctl75%of 16
vmmopen67%of 3
-----------
SUMMARY61%of 117
ffs_indirtrunc73%of 37
ffs_truncate45%of 140
ffs_update43%of 14
-----------
SUMMARY50%of 191
carp6_proto_input---of 3
carp6_proto_input_if---of 11
carp_addr_updated---of 30
carp_carpdev_state---of 26
carp_check_dup_vhids---of 17
carp_clone_create---of 3
carp_clone_destroy---of 1
carp_del_all_timeouts---of 4
carp_destroy_vhosts---of 9
carp_enqueue---of 9
carp_ether_addmulti---of 15
carp_ether_delmulti---of 14
carp_ether_purgemulti---of 7
carp_group_demote_adj---of 23
carp_group_demote_count---of 5
carp_hmac_generate---of 1
carp_hmac_prepare---of 4
carp_hmac_prepare_ctx---of 34
carp_hmac_verify---of 3
carp_iamatch---of 1
carp_ifgattr_ioctl---of 8
carp_ifgroup_ioctl---of 7
carp_input---of 19
carp_ioctl---of 79
carp_join_multicast---of 4
carp_join_multicast6---of 7
carp_lsdrop17%of 12
carp_master_down---of 16
carp_multicast_cleanup---of 17
carp_new_vhost---of 10
carp_ourether---of 11
carp_output---of 5
carp_prepare_ad---of 3
carp_proto_input---of 3
carp_proto_input_c---of 60
carp_proto_input_if---of 17
carp_sc_ref---of 1
carp_sc_unref---of 1
carp_send_ad---of 56
carp_send_ad_all---of 15
carp_send_arp---of 6
carp_send_na---of 6
carp_set_addr---of 14
carp_set_addr6---of 15
carp_set_enaddr---of 28
carp_set_ifp---of 19
carp_set_state---of 12
carp_set_state_all---of 6
carp_set_vhe_enaddr---of 6
carp_setrun---of 27
carp_setrun_all---of 4
carp_start---of 12
carp_sysctl100%of 5
carp_sysctl_carpstat---of 1
carp_timer_ad---of 1
carp_timer_down---of 1
carp_transmit---of 8
carp_update_lsmask---of 9
carp_vh_ref---of 1
carp_vh_unref---of 3
carp_vhe_match---of 4
carp_vhe_send_ad_all---of 6
carp_vhids_ioctl---of 25
carpattach---of 1
carpdetach---of 18
-----------
SUMMARY42%of 17
addlog---of 3
db_printf---of 1
db_vprintf---of 1
kprintf28%of 208
kputchar85%of 13
log50%of 6
logpri---of 4
panic---of 5
printf67%of 3
putchar---of 1
puts---of 1
snprintf67%of 3
splassert_fail---of 6
tablefull100%of 1
tprintf---of 8
tprintf_close---of 4
tprintf_open---of 4
ttyprintf100%of 1
uprintf---of 4
vprintf---of 3
vsnprintf---of 3
-----------
SUMMARY33%of 235
etherip_clone_create---of 1
etherip_clone_destroy---of 6
etherip_del_tunnel---of 1
etherip_down---of 3
etherip_find---of 16
etherip_get_tunnel---of 5
etherip_input---of 14
etherip_ioctl---of 35
etherip_media_change---of 1
etherip_media_status---of 1
etherip_output---of 4
etherip_set_tunnel---of 24
etherip_start---of 11
etherip_sysctl100%of 5
etherip_sysctl_etheripstat---of 1
etherip_up---of 3
etheripattach---of 1
ip6_etherip_input---of 1
ip6_etherip_output---of 12
ip_etherip_input---of 1
ip_etherip_output---of 6
-----------
SUMMARY100%of 5
ulpt_attach---of 26
ulpt_detach---of 11
ulpt_do_write---of 11
ulpt_input---of 3
ulpt_load_firmware---of 3
ulpt_match---of 7
ulpt_reset---of 3
ulpt_status---of 1
ulpt_statusmsg---of 5
ulpt_ucode_loader_hp---of 9
ulptclose---of 9
ulptopen9%of 23
ulptwrite---of 5
-----------
SUMMARY9%of 23
ip_randomid50%of 6
-----------
SUMMARY50%of 6
crcopy---of 4
crdup100%of 1
crfree100%of 3
crfromxucred---of 3
crget100%of 1
crhold100%of 1
crset---of 3
dorefreshcreds75%of 4
groupmember100%of 6
proc_cansugid---of 3
suser100%of 1
suser_ucred100%of 1
sys___get_tcb---of 1
sys___set_tcb---of 3
sys_getegid100%of 1
sys_geteuid100%of 1
sys_getgid100%of 1
sys_getgroups100%of 5
sys_getlogin_r---of 1
sys_getpgid100%of 6
sys_getpgrp100%of 1
sys_getpid100%of 1
sys_getppid100%of 1
sys_getresgid---of 7
sys_getresuid---of 7
sys_getsid---of 8
sys_getthrid---of 1
sys_getthrname---of 5
sys_getuid100%of 1
sys_issetugid---of 1
sys_setegid67%of 9
sys_seteuid67%of 9
sys_setgid75%of 16
sys_setgroups72%of 7
sys_setlogin---of 4
sys_setpgid70%of 20
sys_setregid88%of 39
sys_setresgid---of 38
sys_setresuid---of 38
sys_setreuid93%of 39
sys_setsid---of 4
sys_setthrname---of 6
sys_setuid77%of 17
-----------
SUMMARY84%of 192
in6_clearscope---of 6
in6_embedscope100%of 17
in6_pcbselsrc80%of 39
in6_recoverscope100%of 8
in6_selecthlim75%of 4
in6_selectif56%of 20
in6_selectroute88%of 8
in6_selectsrc100%of 19
-----------
SUMMARY84%of 115
km_alloc50%of 28
km_free50%of 16
uvm_km_alloc1---of 12
uvm_km_free100%of 1
uvm_km_init---of 4
uvm_km_kmemalloc_pla61%of 23
uvm_km_page_init---of 1
uvm_km_page_lateinit---of 1
uvm_km_pgremove46%of 11
uvm_km_pgremove_intrsafe58%of 7
uvm_km_suballoc---of 7
-----------
SUMMARY54%of 86
binboottime---of 4
binruntime---of 8
bintime---of 8
binuptime---of 6
dummy_get_timecount---of 1
getbinruntime---of 6
getbinuptime---of 4
getmicrotime50%of 4
getmicrouptime50%of 4
getnanotime50%of 4
getnanouptime50%of 4
getnsecruntime50%of 4
getnsecuptime50%of 4
gettime100%of 1
getuptime100%of 1
inittimecounter---of 3
microboottime50%of 4
microtime50%of 4
microuptime50%of 4
nanoboottime50%of 4
nanoruntime---of 4
nanotime50%of 4
nanouptime50%of 4
nsecuptime50%of 4
ntp_update_second---of 3
sysctl_tc100%of 5
sysctl_tc_choice58%of 7
sysctl_tc_hardware72%of 7
tc_adjfreq---of 5
tc_adjtime---of 7
tc_getfrequency100%of 1
tc_getprecision100%of 1
tc_init---of 9
tc_reset_quality---of 13
tc_setclock---of 6
tc_setrealtimeclock40%of 5
tc_ticktock---of 4
tc_update_timekeep---of 5
tc_windup38%of 32
-----------
SUMMARY52%of 112
calcru---of 5
calctsru60%of 5
dogetrusage84%of 12
donice---of 11
dosetrlimit96%of 24
lim_copy---of 1
lim_cur_proc67%of 3
lim_fork67%of 3
lim_free---of 3
lim_read_enter86%of 7
lim_startup---of 1
lim_write_begin72%of 7
lim_write_commit---of 4
ruadd72%of 7
rucheck---of 5
sys_getpriority---of 22
sys_getrlimit84%of 6
sys_getrusage84%of 6
sys_setpriority---of 20
sys_setrlimit80%of 5
tuagg---of 1
tuagg_locked43%of 7
tuagg_sub---of 4
-----------
SUMMARY80%of 92
SipHash100%of 1
SipHash_End72%of 7
SipHash_Final---of 1
SipHash_Init100%of 1
SipHash_Update80%of 15
-----------
SUMMARY80%of 24
ip6_randomflowlabel100%of 1
ip6id_initid60%of 22
ip6id_pmod---of 6
ip6id_randomid80%of 15
-----------
SUMMARY69%of 38
-----------
SUMMARY---of 0
pf_add_threshold---of 3
pf_addr_compare---of 14
pf_addr_inc---of 7
pf_addr_wrap_neq---of 19
pf_addrcpy---of 4
pf_alloc_state_key---of 3
pf_anchor_stack_init---of 1
pf_anchor_stack_is_empty---of 1
pf_anchor_stack_is_full---of 1
pf_anchor_stack_pop---of 4
pf_anchor_stack_push---of 4
pf_anchor_stack_top---of 1
pf_build_tcp---of 19
pf_calc_mss---of 7
pf_calc_skip_steps---of 80
pf_change_icmp_af---of 19
pf_check_tcp_cksum---of 11
pf_check_threshold---of 1
pf_cksum_fixup---of 3
pf_cksum_fixup_a---of 6
pf_compare_state_keys---of 22
pf_counters_inc---of 25
pf_create_state---of 80
pf_delay_pkt---of 3
pf_detach_state---of 5
pf_find_divert---of 1
pf_find_state---of 51
pf_find_state_all---of 14
pf_find_state_byid---of 1
pf_find_tcpopt---of 8
pf_free_state---of 19
pf_get_divert---of 4
pf_get_mss---of 14
pf_get_src_node---of 4
pf_get_wscale---of 14
pf_icmp_mapping---of 39
pf_icmp_state_lookup---of 30
pf_init_threshold---of 1
pf_inp_link---of 9
pf_inp_lookup---of 5
pf_inp_unlink40%of 5
pf_insert_src_node---of 45
pf_log_matches---of 7
pf_match---of 11
pf_match_addr---of 9
pf_match_addr_range---of 21
pf_match_gid---of 12
pf_match_port---of 11
pf_match_rcvif---of 8
pf_match_rule---of 281
pf_match_tag---of 3
pf_match_uid---of 12
pf_mbuf_link_inpcb67%of 3
pf_mbuf_link_state_key50%of 4
pf_mbuf_unlink_inpcb100%of 3
pf_mbuf_unlink_state_key67%of 3
pf_modulate_sack---of 18
pf_ouraddr40%of 5
pf_patch_16---of 4
pf_patch_16_unaligned---of 10
pf_patch_32---of 3
pf_patch_32_unaligned---of 15
pf_patch_8---of 4
pf_pkt_addr_changed80%of 5
pf_pkt_hash---of 6
pf_pktenqueue_delayed---of 3
pf_poolmask---of 4
pf_print_flags---of 18
pf_print_host---of 42
pf_print_state---of 1
pf_print_state_parts---of 39
pf_pull_hdr---of 9
pf_purge---of 3
pf_purge_expired_src_nodes---of 18
pf_purge_expired_states---of 30
pf_purge_states---of 3
pf_purge_states_tick---of 4
pf_purge_tick---of 1
pf_remove_divert_state12%of 26
pf_remove_src_node---of 6
pf_remove_state---of 27
pf_routable---of 18
pf_route---of 31
pf_route6---of 32
pf_rtlabel_match---of 6
pf_rule_to_actions---of 17
pf_send_challenge_ack---of 5
pf_send_icmp---of 10
pf_send_tcp---of 5
pf_set_protostate---of 8
pf_setup_pdesc---of 91
pf_socket_lookup---of 19
pf_src_connlimit---of 60
pf_src_tree_RB_FIND---of 24
pf_src_tree_RB_INSERT---of 24
pf_src_tree_RB_INSERT_COLOR---of 27
pf_src_tree_RB_MINMAX---of 4
pf_src_tree_RB_NEXT---of 9
pf_src_tree_RB_NFIND---of 24
pf_src_tree_RB_PREV---of 9
pf_src_tree_RB_REMOVE---of 17
pf_src_tree_RB_REMOVE_COLOR---of 56
pf_src_tree_remove_state---of 8
pf_state_alloc_scrub_memory---of 4
pf_state_expires---of 7
pf_state_export---of 21
pf_state_import---of 76
pf_state_insert---of 22
pf_state_key_attach---of 35
pf_state_key_detach---of 10
pf_state_key_isvalid---of 3
pf_state_key_link_inpcb---of 6
pf_state_key_link_reverse---of 8
pf_state_key_ref---of 3
pf_state_key_setup---of 65
pf_state_key_unlink_inpcb---of 5
pf_state_key_unlink_reverse---of 4
pf_state_key_unref---of 8
pf_state_list_insert---of 3
pf_state_list_remove---of 1
pf_state_peer_hton---of 3
pf_state_peer_ntoh---of 4
pf_state_ref---of 3
pf_state_rm_src_node---of 6
pf_state_tree_RBT_COMPARE---of 30
pf_state_tree_id_RBT_COMPARE---of 5
pf_state_unref---of 10
pf_tag_packet---of 5
pf_tbladdr_copyout---of 6
pf_tbladdr_remove---of 4
pf_tbladdr_setup---of 3
pf_tcp_iss---of 6
pf_tcp_track_full---of 133
pf_tcp_track_sloppy---of 61
pf_test2%of 172
pf_test_rule---of 96
pf_test_state---of 131
pf_test_state_icmp---of 317
pf_translate---of 35
pf_translate_a---of 16
pf_translate_af---of 16
pf_translate_icmp---of 10
pf_translate_icmp_af---of 72
pf_update_state_timeout---of 3
pf_walk_header---of 32
pf_walk_header6---of 95
pf_walk_option---of 25
pf_walk_option6---of 37
-----------
SUMMARY10%of 226
strlcpy86%of 7
-----------
SUMMARY86%of 7
tcp6_ctlinput---of 29
tcp6_mtudisc_callback---of 1
tcp_close43%of 7
tcp_ctlinput---of 26
tcp_drop60%of 5
tcp_freeq---of 4
tcp_init---of 5
tcp_mtudisc38%of 8
tcp_mtudisc_increase---of 4
tcp_newtcpcb58%of 7
tcp_notify---of 9
tcp_respond---of 19
tcp_rscale14%of 15
tcp_set_iss_tsm100%of 1
tcp_signature---of 10
tcp_signature_apply---of 1
tcp_signature_tdb_attach---of 1
tcp_signature_tdb_init---of 4
tcp_signature_tdb_input---of 1
tcp_signature_tdb_output---of 1
tcp_signature_tdb_zeroize---of 3
tcp_template67%of 9
-----------
SUMMARY43%of 52
spec_access---of 3
spec_advlock100%of 1
spec_close73%of 18
spec_fsync25%of 8
spec_getattr67%of 3
spec_inactive100%of 1
spec_ioctl75%of 4
spec_kqfilter100%of 5
spec_open78%of 31
spec_open_clone80%of 10
spec_pathconf---of 8
spec_print---of 1
spec_read53%of 21
spec_setattr67%of 3
spec_strategy100%of 1
spec_write35%of 20
-----------
SUMMARY64%of 126
mpls_sysctl100%of 1
-----------
SUMMARY100%of 1
filt_wseventdetach100%of 1
filt_wseventread75%of 4
wsevent_fini67%of 3
wsevent_init50%of 4
wsevent_kqfilter100%of 3
wsevent_read60%of 10
-----------
SUMMARY68%of 25
chgproccnt67%of 3
db_kill_cmd---of 5
db_show_all_procs---of 33
enternewpgrp58%of 7
enterthispgrp59%of 17
fixjobc18%of 23
inferior60%of 5
killjobc---of 9
leavepgrp---of 7
pgdelete63%of 8
pgfind100%of 4
prfind100%of 5
proc_printit---of 5
procinit---of 3
tfind60%of 5
tfind_user67%of 6
uid_find43%of 7
uid_release100%of 1
zapverauth---of 1
zombiefind80%of 5
-----------
SUMMARY55%of 96
vn_close100%of 3
vn_closefile100%of 5
vn_fsizechk80%of 5
vn_ioctl77%of 13
vn_isunder100%of 1
vn_kqfilter100%of 1
vn_lock50%of 8
vn_marktext---of 1
vn_open87%of 36
vn_rdwr100%of 9
vn_read100%of 7
vn_seek100%of 9
vn_stat50%of 4
vn_statfile---of 1
vn_write90%of 10
vn_writechk40%of 10
-----------
SUMMARY82%of 121
ksymsattach---of 11
ksymsclose100%of 1
ksymsopen100%of 4
ksymsread100%of 6
-----------
SUMMARY100%of 11
ukattach---of 1
ukclose---of 3
ukdetach---of 11
ukioctl---of 3
ukmatch---of 1
ukopen50%of 4
-----------
SUMMARY50%of 4
ipe4_attach---of 1
ipe4_init---of 1
ipe4_input---of 1
ipe4_zeroize---of 1
ipip_init---of 1
ipip_input---of 6
ipip_input_if---of 38
ipip_output---of 39
ipip_sysctl100%of 5
ipip_sysctl_ipipstat---of 1
-----------
SUMMARY100%of 5
cd_buf_done---of 20
cd_cmd_rw10---of 1
cd_cmd_rw12---of 1
cd_cmd_rw6---of 1
cd_get_parms---of 6
cd_getvol---of 4
cd_interpret_sense---of 7
cd_load_toc---of 7
cd_load_unload---of 3
cd_pause---of 3
cd_play---of 3
cd_play_msf---of 3
cd_play_tracks---of 11
cd_read_subchannel---of 4
cd_read_toc---of 4
cd_reset---of 3
cd_set_pa_immed---of 7
cd_setchan---of 5
cd_setvol---of 6
cd_size---of 15
cdactivate---of 5
cdattach---of 3
cdclose---of 6
cddetach---of 1
cddump---of 1
cdgetdisklabel---of 6
cdioctl---of 103
cdmatch---of 1
cdminphys---of 8
cdopen13%of 16
cdread---of 1
cdsize---of 1
cdstart---of 11
cdstrategy---of 8
cdwrite---of 1
dvd_auth---of 22
dvd_read_bca---of 6
dvd_read_copyright---of 5
dvd_read_disckey---of 5
dvd_read_manufact---of 6
dvd_read_physical---of 6
dvd_read_struct---of 7
-----------
SUMMARY13%of 16
db_kclock---of 1
db_show_callout---of 21
db_show_callout_bucket---of 4
db_show_timeout---of 11
db_timespec---of 3
softclock---of 11
softclock_create_thread---of 3
softclock_process_kclock_timeout---of 14
softclock_process_tick_timeout---of 11
softclock_thread---of 5
timeout_abs_ts70%of 10
timeout_add56%of 9
timeout_add_msec100%of 1
timeout_add_nsec---of 1
timeout_add_sec100%of 1
timeout_add_tv100%of 1
timeout_add_usec---of 1
timeout_adjust_ticks---of 9
timeout_barrier60%of 5
timeout_barrier_timeout---of 1
timeout_bucket---of 9
timeout_del100%of 3
timeout_del_barrier100%of 5
timeout_hardclock_update---of 25
timeout_maskwheel---of 1
timeout_proc_init---of 3
timeout_run---of 3
timeout_set100%of 1
timeout_set_flags40%of 5
timeout_set_proc100%of 1
timeout_startup---of 4
timeout_sysctl100%of 1
-----------
SUMMARY73%of 43
sys_kbind---of 37
sys_madvise88%of 16
sys_mimmutable---of 9
sys_minherit56%of 9
sys_mlock64%of 11
sys_mlockall100%of 3
sys_mmap79%of 69
sys_mprotect48%of 19
sys_mquery84%of 12
sys_msync70%of 13
sys_munlock56%of 9
sys_munlockall100%of 1
sys_munmap67%of 12
sys_pinsyscalls---of 16
uvm_mmapanon67%of 6
uvm_mmapfile79%of 14
uvm_mmaplock34%of 9
-----------
SUMMARY71%of 203
art_alloc72%of 7
art_allot80%of 15
art_bindex25%of 8
art_delete29%of 14
art_gc---of 4
art_get67%of 3
art_init---of 1
art_insert57%of 16
art_lookup72%of 14
art_match80%of 10
art_put67%of 3
art_table_delete85%of 13
art_table_free---of 6
art_table_gc---of 7
art_table_get54%of 13
art_table_insert100%of 9
art_table_put20%of 10
art_table_ref---of 1
art_table_walk69%of 29
art_walk56%of 9
art_walk_apply---of 3
-----------
SUMMARY63%of 173
pctr_reload---of 13
pctr_resume---of 7
pctrattach---of 4
pctrclose100%of 1
pctrioctl6%of 38
pctropen100%of 1
-----------
SUMMARY10%of 40
amd64_pa_used---of 7
bios_getdiskinfo23%of 9
bios_sysctl59%of 24
boot---of 18
check_context---of 5
copyin32---of 3
cpu_dump---of 9
cpu_dump_mempagecnt---of 8
cpu_dumpsize---of 1
cpu_init_extents---of 7
cpu_init_idt---of 1
cpu_initclocks---of 1
cpu_reset---of 3
cpu_set_vendor---of 5
cpu_startclock---of 1
cpu_startup---of 3
cpu_sysctl83%of 17
delay_fini---of 3
delay_init---of 3
dumpconf---of 19
dumpsys---of 54
enter_shared_special_pages---of 10
getbootinfo---of 20
idt_vec_alloc---of 5
idt_vec_alloc_range---of 17
idt_vec_free---of 1
idt_vec_set---of 3
init_x86_64---of 75
initialize_thread_xstate---of 6
map_tramps---of 3
maybe_enable_user_cet---of 4
need_resched67%of 3
reset_segs---of 3
sendsig45%of 20
set_mem_segment---of 1
set_sys_segment---of 1
setgate---of 1
setregion---of 1
setregs---of 8
signotify---of 1
splassert_check60%of 5
sys_sigreturn---of 12
unsetgate---of 1
x86_64_proc0_tss_ldt_init---of 1
-----------
SUMMARY57%of 78
bktr_attach---of 11
bktr_get_info---of 4
bktr_intr---of 1
bktr_probe---of 7
bktr_set_info---of 10
bktrclose---of 5
bktrioctl---of 5
bktrmmap---of 5
bktropen25%of 8
bktrread---of 4
bktrwrite---of 1
free_bktr_mem---of 1
get_bktr_mem---of 8
-----------
SUMMARY25%of 8
vndattach---of 5
vndbdevsize---of 4
vndclear67%of 3
vndclose67%of 3
vnddump---of 1
vndencrypt---of 6
vndencryptbuf---of 6
vndgetdisklabel67%of 3
vndioctl73%of 58
vndopen58%of 7
vndread100%of 1
vndsetcred100%of 3
vndsize---of 1
vndstrategy30%of 20
vndwrite100%of 1
-----------
SUMMARY64%of 99
SHA256Final---of 5
SHA256Init---of 1
SHA256Transform---of 4
SHA256Update---of 10
SHA384Final---of 5
SHA384Init---of 1
SHA384Update---of 1
SHA512Final60%of 5
SHA512Init100%of 1
SHA512Last---of 5
SHA512Transform100%of 4
SHA512Update47%of 15
-----------
SUMMARY60%of 25
acpi_get_timecount---of 3
acpitimer_delay67%of 6
acpitimer_read---of 3
acpitimerattach---of 7
acpitimermatch---of 4
-----------
SUMMARY67%of 6
strncmp80%of 5
-----------
SUMMARY80%of 5
ether_addmulti53%of 23
ether_addr_to_e64---of 1
ether_brport_clr---of 3
ether_brport_get---of 4
ether_brport_get_locked---of 1
ether_brport_isset---of 1
ether_brport_set---of 3
ether_crc32_be---of 4
ether_crc32_be_update---of 4
ether_crc32_le---of 7
ether_crc32_le_update---of 7
ether_delmulti56%of 20
ether_e64_to_addr---of 1
ether_encap---of 5
ether_extract_headers17%of 31
ether_fakeaddr100%of 1
ether_ifattach58%of 7
ether_ifdetach34%of 6
ether_input64%of 41
ether_ioctl55%of 11
ether_multiaddr---of 10
ether_output80%of 5
ether_resolve46%of 31
ether_rtrequest80%of 5
ether_sprintf---of 1
-----------
SUMMARY50%of 181
readdisklabel45%of 9
writedisklabel---of 4
-----------
SUMMARY45%of 9
-----------
SUMMARY---of 0
m_adj37%of 19
m_align30%of 10
m_apply---of 16
m_calchdrlen75%of 4
m_cat50%of 12
m_clget62%of 18
m_clpool---of 10
m_copyback47%of 32
m_copydata54%of 13
m_copym56%of 29
m_defrag---of 15
m_devget---of 16
m_dup_pkt19%of 11
m_dup_pkthdr40%of 5
m_extfree67%of 6
m_extfree_pool100%of 1
m_extref---of 3
m_free100%of 9
m_freem100%of 4
m_get50%of 4
m_getclr50%of 4
m_gethdr50%of 4
m_getptr67%of 6
m_inithdr---of 1
m_leadingspace---of 7
m_makespace---of 39
m_microtime50%of 4
m_pool_alloc50%of 4
m_pool_free100%of 1
m_pool_init---of 1
m_pool_used100%of 1
m_prepend44%of 16
m_print---of 5
m_pullup10%of 33
m_purge100%of 5
m_removehdr67%of 3
m_resethdr67%of 3
m_split---of 19
m_trailingspace58%of 7
m_zero38%of 8
mbcpuinit---of 1
mbinit---of 10
mextfree_register---of 3
ml_dechain---of 1
ml_dequeue100%of 4
ml_enlist75%of 4
ml_enqueue100%of 1
ml_hdatalen---of 4
ml_init100%of 1
ml_purge100%of 5
mq_dechain---of 1
mq_delist---of 1
mq_dequeue50%of 4
mq_enlist---of 11
mq_enqueue80%of 5
mq_hdatalen50%of 4
mq_init100%of 1
mq_purge80%of 5
mq_push75%of 8
mq_set_maxlen---of 1
nmbclust_update---of 3
sysctl_mq100%of 7
-----------
SUMMARY53%of 325
shm_deallocate_segment100%of 1
shm_delete_mapping67%of 6
shm_find_segment_by_key---of 7
shm_find_segment_by_shmid---of 4
shm_reallocate100%of 1
shmexit---of 7
shmfork---of 8
shmget_allocate_segment43%of 21
shmget_existing---of 7
shminit---of 1
sys_shmat72%of 21
sys_shmctl100%of 16
sys_shmdt80%of 10
sys_shmget79%of 19
sysctl_sysvshm92%of 12
-----------
SUMMARY75%of 107
evcount_attach---of 1
evcount_detach---of 5
evcount_inc---of 1
evcount_init_percpu---of 6
evcount_percpu---of 4
evcount_sysctl90%of 20
-----------
SUMMARY90%of 20
acpi_filtdetach100%of 1
acpi_filtread50%of 4
acpiclose60%of 5
acpiioctl16%of 13
acpikqfilter75%of 4
acpiopen88%of 8
request_sleep---of 4
-----------
SUMMARY52%of 35
strlcat55%of 11
-----------
SUMMARY55%of 11
idgen3258%of 7
idgen32_init---of 1
-----------
SUMMARY58%of 7
endrun_atoi---of 11
endrun_date_to_nano---of 19
endrun_decode8%of 26
endrun_offset_to_nano---of 11
endrun_scan---of 8
endrun_time_to_nano---of 17
endrun_timeout---of 3
endrunattach---of 1
endrunclose100%of 3
endruninput86%of 14
endrunopen80%of 5
-----------
SUMMARY44%of 48
carp_strict_addr_chk---of 6
ip6_check_rh0hdr100%of 11
ip6_get_prevhdr31%of 13
ip6_hbhchcheck67%of 15
ip6_hopopts_input70%of 13
ip6_init---of 11
ip6_input_if49%of 77
ip6_lasthdr50%of 8
ip6_nexthdr62%of 21
ip6_ours67%of 9
ip6_process_hopopts90%of 19
ip6_pullexthdr43%of 14
ip6_savecontrol55%of 33
ip6_send100%of 1
ip6_send_dispatch---of 5
ip6_sysctl95%of 17
ip6_sysctl_ip6stat---of 1
ip6_sysctl_soiikey---of 3
ip6_unknown_opt100%of 7
ip6intr---of 8
ipv6_check89%of 62
ipv6_input67%of 3
-----------
SUMMARY67%of 323
__mtx_init100%of 1
db_mtx_enter---of 4
db_mtx_leave---of 3
mtx_enter60%of 5
mtx_enter_try---of 5
mtx_leave60%of 5
-----------
SUMMARY64%of 11
copyin43%of 7
copyinstr67%of 9
dohooks---of 9
hashfree80%of 5
hashinit54%of 13
hook_disestablish---of 4
hook_establish---of 5
uiomove68%of 28
ureadc45%of 9
-----------
SUMMARY61%of 71
task_add60%of 5
task_del75%of 4
task_set100%of 1
taskq_barrier100%of 1
taskq_barrier_task---of 3
taskq_create---of 3
taskq_create_thread---of 7
taskq_del_barrier50%of 4
taskq_destroy---of 6
taskq_do_barrier54%of 13
taskq_init---of 1
taskq_next_work---of 8
taskq_thread---of 11
-----------
SUMMARY61%of 28
-----------
SUMMARY---of 0
nfs_getset_niothreads60%of 10
nfsrv_getslp---of 9
nfsrv_init---of 12
nfsrv_slpderef---of 4
nfsrv_zapsock---of 7
nfssvc_addsock---of 14
nfssvc_iod---of 38
nfssvc_nfsd---of 65
sys_nfssvc---of 16
-----------
SUMMARY60%of 10
-----------
SUMMARY---of 0
-----------
SUMMARY---of 0
devid_alloc---of 3
devid_copy---of 1
devid_free---of 3
scsi_activate10%of 21
scsi_activate_bus---of 7
scsi_activate_link---of 3
scsi_activate_lun---of 8
scsi_activate_target---of 8
scsi_add_link---of 1
scsi_detach---of 20
scsi_detach_bus---of 7
scsi_detach_link---of 20
scsi_detach_lun---of 7
scsi_detach_target---of 8
scsi_devid---of 36
scsi_devid_pg80---of 6
scsi_devid_pg83---of 16
scsi_devid_wwn---of 5
scsi_get_link---of 7
scsi_get_target_luns---of 24
scsi_inqmatch---of 11
scsi_print_link---of 24
scsi_probe---of 15
scsi_probe_bus---of 14
scsi_probe_link---of 82
scsi_probe_lun---of 4
scsi_probe_target---of 11
scsi_remove_link---of 4
scsi_strvis---of 29
scsibusactivate---of 7
scsibusattach---of 14
scsibusbioctl---of 4
scsibusdetach---of 9
scsibusmatch---of 1
scsibussubmatch---of 7
scsibussubprint---of 3
scsiprint---of 3
-----------
SUMMARY10%of 21
pmap_activate40%of 5
pmap_alloc_level---of 10
pmap_bootstrap---of 25
pmap_clear_attrs53%of 21
pmap_clear_pml4_early---of 1
pmap_convert50%of 4
pmap_copy_page100%of 1
pmap_create28%of 11
pmap_deactivate---of 4
pmap_destroy39%of 18
pmap_do_remove75%of 63
pmap_do_remove_ept---of 10
pmap_enter43%of 71
pmap_enter_ept45%of 18
pmap_enter_pv---of 1
pmap_enter_special---of 39
pmap_extract80%of 15
pmap_find_pte_direct---of 5
pmap_find_ptp---of 5
pmap_flush_cache---of 5
pmap_free_ptp46%of 22
pmap_freepage---of 3
pmap_get_physpage---of 4
pmap_get_ptp58%of 21
pmap_growkernel---of 9
pmap_init---of 1
pmap_init_percpu---of 1
pmap_kenter_pa25%of 8
pmap_kremove60%of 5
pmap_map_ptes---of 6
pmap_page_remove42%of 43
pmap_pdes_valid---of 6
pmap_pdp_ctor25%of 8
pmap_pdp_ctor_intel---of 1
pmap_prealloc_lowmem_ptps---of 1
pmap_randomize---of 14
pmap_randomize_level---of 20
pmap_reference---of 1
pmap_remove29%of 7
pmap_remove_ept---of 6
pmap_remove_pte62%of 18
pmap_remove_ptes67%of 24
pmap_remove_pv---of 7
pmap_set_pml4_early---of 4
pmap_steal_memory---of 24
pmap_test_attrs70%of 10
pmap_tlb_shootpage---of 7
pmap_tlb_shootrange43%of 14
pmap_tlb_shoottlb---of 5
pmap_unmap_ptes---of 5
pmap_unwire29%of 7
pmap_write_protect50%of 28
pmap_zero_page100%of 1
-----------
SUMMARY52%of 443
ifiq_add_data100%of 1
ifiq_destroy60%of 5
ifiq_enqueue75%of 4
ifiq_init67%of 3
ifiq_input---of 18
ifiq_kstat_copy---of 1
ifiq_process---of 3
ifq_add_data100%of 1
ifq_attach---of 6
ifq_barrier67%of 3
ifq_barrier_task---of 1
ifq_bundle_task---of 1
ifq_deq_begin67%of 6
ifq_deq_commit50%of 4
ifq_deq_rollback---of 4
ifq_deq_sleep63%of 8
ifq_dequeue---of 7
ifq_destroy60%of 5
ifq_enqueue67%of 6
ifq_hdatalen38%of 8
ifq_init60%of 5
ifq_init_maxlen---of 1
ifq_is_serialized---of 1
ifq_kstat_copy---of 1
ifq_mfreem---of 3
ifq_mfreeml---of 3
ifq_purge67%of 3
ifq_q_enter---of 3
ifq_q_leave---of 3
ifq_restart_task---of 1
ifq_serialize38%of 8
ifq_set_oactive---of 4
ifq_start100%of 3
ifq_start_task40%of 5
net_ifiq_sysctl100%of 1
priq_alloc---of 1
priq_deq_begin30%of 10
priq_deq_commit67%of 3
priq_enq12%of 18
priq_free100%of 1
priq_idx---of 3
priq_purge100%of 1
-----------
SUMMARY50%of 112
pfkeyv2_parsemessage5%of 126
-----------
SUMMARY5%of 126
filt_tunmodify100%of 1
filt_tunprocess100%of 6
filt_tunrdetach100%of 1
filt_tunread67%of 3
filt_tunwdetach100%of 1
filt_tunwrite67%of 3
tap_clone_create100%of 1
tapclose100%of 1
tapioctl100%of 1
tapkqfilter100%of 1
tapopen100%of 1
tapread100%of 1
tapwrite100%of 1
tun_clone_create100%of 1
tun_clone_destroy70%of 13
tun_create56%of 9
tun_dev_close50%of 8
tun_dev_ioctl92%of 24
tun_dev_kqfilter72%of 7
tun_dev_open47%of 15
tun_dev_read70%of 13
tun_dev_write67%of 12
tun_enqueue67%of 6
tun_init58%of 28
tun_input34%of 6
tun_insert---of 6
tun_ioctl91%of 11
tun_link_state---of 3
tun_name_lookup---of 5
tun_output---of 4
tun_start---of 8
tun_wakeup---of 5
tunattach---of 1
tunclose100%of 1
tunioctl100%of 1
tunkqfilter100%of 1
tunopen100%of 1
tunread100%of 1
tunwrite100%of 1
-----------
SUMMARY71%of 181
-----------
SUMMARY---of 0
keycb_ref100%of 1
keycb_unref100%of 1
pfdatatopacket---of 3
pfkey_init---of 1
pfkey_sendup---of 6
pfkeyv2_acquire---of 33
pfkeyv2_attach67%of 6
pfkeyv2_detach50%of 12
pfkeyv2_disconnect100%of 1
pfkeyv2_dosend3%of 184
pfkeyv2_dump_policy---of 25
pfkeyv2_dump_walker---of 9
pfkeyv2_expire---of 14
pfkeyv2_get---of 65
pfkeyv2_get_proto_alg---of 15
pfkeyv2_output50%of 6
pfkeyv2_peeraddr100%of 1
pfkeyv2_policy---of 22
pfkeyv2_policy_flush---of 1
pfkeyv2_sa_flush---of 4
pfkeyv2_send84%of 6
pfkeyv2_sendmessage---of 51
pfkeyv2_shutdown100%of 1
pfkeyv2_sockaddr100%of 1
pfkeyv2_sysctl94%of 16
pfkeyv2_sysctl_policydumper---of 35
pfkeyv2_sysctl_walker---of 22
-----------
SUMMARY19%of 236
bcdtobin---of 1
bintobcd---of 1
clockintr---of 4
gettick---of 1
i8254_delay---of 6
i8254_get_timecount---of 3
i8254_initclocks---of 1
i8254_inittimecounter---of 1
i8254_inittimecounter_simple---of 1
i8254_simple_get_timecount---of 1
i8254_start_both_clocks---of 1
i8254_startclock---of 1
mc146818_read---of 1
mc146818_write---of 1
rtcdrain---of 5
rtcget40%of 5
rtcgettime---of 11
rtcinit---of 1
rtcintr---of 5
rtcput100%of 1
rtcsettime60%of 5
rtcstart---of 1
rtcstop---of 1
setstatclockrate---of 4
startclocks---of 1
-----------
SUMMARY55%of 11
_rs_clearseed---of 7
_rs_seed45%of 9
_rs_stir67%of 3
add_entropy_words75%of 4
arc4random67%of 6
arc4random_buf70%of 10
arc4random_ctx_buf---of 1
arc4random_ctx_free---of 1
arc4random_ctx_new100%of 1
arc4random_uniform50%of 4
chacha_encrypt_bytes93%of 14
chacha_keysetup100%of 1
dequeue_randomness67%of 3
enqueue_randomness67%of 6
extract_entropy67%of 3
filt_randomdetach100%of 1
filt_randomread100%of 1
filt_randomwrite100%of 1
random_start---of 5
randomclose100%of 1
randomioctl100%of 1
randomkqfilter100%of 4
randomopen100%of 1
randomread86%of 14
randomwrite88%of 24
resume_randomness---of 3
rnd_init---of 1
rnd_reinit---of 1
suspend_randomness---of 1
sys_getentropy---of 4
-----------
SUMMARY79%of 112
sbappend50%of 10
sbappendaddr60%of 37
sbappendcontrol52%of 35
sbappendrecord58%of 14
sbappendstream50%of 4
sbchecklowmem50%of 4
sbcheckreserve50%of 6
sbcompress68%of 31
sbcreatecontrol50%of 6
sbdrop33%of 34
sbdroprecord70%of 10
sbflush37%of 11
sblock100%of 3
sbmtxassertlocked40%of 5
sbrelease100%of 1
sbreserve75%of 8
sbunlock100%of 1
sbwait75%of 4
soassertlocked58%of 14
soassertlocked_readonly84%of 6
socantrcvmore100%of 3
socantsendmore100%of 1
soisconnected25%of 29
soisconnecting100%of 1
soisdisconnected100%of 1
soisdisconnecting100%of 1
solock100%of 4
solock_pair29%of 14
solock_persocket100%of 1
solock_shared100%of 6
sonewconn23%of 31
soqinsque---of 4
soqremque58%of 7
soreserve53%of 17
sosleep_nsec60%of 10
sounlock100%of 4
sounlock_shared100%of 6
sowakeup100%of 7
-----------
SUMMARY54%of 387
config_activate_children---of 33
config_attach---of 28
config_deactivate---of 8
config_defer---of 6
config_detach---of 49
config_detach_children---of 7
config_found_sm---of 4
config_init---of 1
config_make_softc---of 18
config_mountroot---of 6
config_pending_decr---of 4
config_pending_incr---of 1
config_process_deferred_children---of 8
config_process_deferred_mountroot---of 4
config_rootfound---of 8
config_rootsearch---of 7
config_scan---of 15
config_search---of 22
config_suspend---of 5
config_suspend_all---of 35
device_lookup67%of 6
device_mainbus---of 3
device_mpath---of 3
device_ref100%of 1
device_unref67%of 3
mapply---of 16
-----------
SUMMARY70%of 10
uvm_aio_aiodone---of 12
uvm_aio_aiodone_pages---of 28
uvm_aio_biodone---of 3
uvm_mk_pcluster52%of 33
uvm_pager_dropcluster---of 21
uvm_pager_init---of 11
uvm_pager_put20%of 20
uvm_pagermapin34%of 12
uvm_pagermapout100%of 3
uvm_pseg_get25%of 16
uvm_pseg_init---of 4
uvm_pseg_release13%of 24
-----------
SUMMARY33%of 108
nd6_dad_destroy---of 1
nd6_dad_duplicated---of 1
nd6_dad_find---of 4
nd6_dad_ns_input---of 6
nd6_dad_ns_output---of 3
nd6_dad_start50%of 12
nd6_dad_starttimer---of 1
nd6_dad_stop100%of 4
nd6_dad_stoptimer---of 1
nd6_dad_timer---of 14
nd6_ifptomac---of 7
nd6_isneighbor---of 4
nd6_na_input---of 71
nd6_na_output---of 35
nd6_ns_input---of 56
nd6_ns_output36%of 37
-----------
SUMMARY44%of 53
enc_clone_create---of 10
enc_clone_destroy---of 4
enc_getif---of 8
enc_getifa40%of 10
enc_ioctl43%of 7
enc_output---of 1
enc_setif---of 13
enc_unsetif---of 11
encattach---of 1
-----------
SUMMARY42%of 17
-----------
SUMMARY---of 0
acct_process---of 24
acct_shutdown---of 3
acct_start---of 3
acct_thread---of 8
encode_comp_t---of 5
sys_acct92%of 12
-----------
SUMMARY92%of 12
swap_decrypt---of 7
swap_encrypt---of 8
swap_encrypt_ctl100%of 8
swap_key_cleanup---of 3
swap_key_create---of 1
swap_key_delete---of 3
swap_key_prepare---of 5
-----------
SUMMARY100%of 8
tcp_chopper---of 30
tcp_if_output_tso17%of 12
tcp_output59%of 224
tcp_sack_adjust---of 8
tcp_sack_output---of 9
tcp_setpersist---of 4
-----------
SUMMARY57%of 236
nvram_csum_valid---of 3
nvram_get_byte---of 3
nvramattach---of 6
nvramclose---of 1
nvramopen100%of 1
nvramread---of 9
-----------
SUMMARY100%of 1
mem_ioctl---of 13
mem_range_attr_get---of 4
mem_range_attr_set---of 3
mmclose67%of 3
mmioctl60%of 5
mmmmap17%of 12
mmopen73%of 11
mmrw48%of 21
-----------
SUMMARY49%of 52
st_buf_done---of 14
st_check_eod---of 7
st_decide_mode---of 27
st_erase---of 3
st_interpret_sense---of 52
st_load---of 13
st_mode_select---of 15
st_mode_sense---of 4
st_mount_tape---of 20
st_read---of 5
st_read_block_limits---of 6
st_rewind---of 10
st_space---of 34
st_touch_tape---of 13
st_unmount---of 13
st_write_filemarks---of 9
stactivate---of 3
stattach---of 4
stclose---of 25
stdetach---of 6
stioctl---of 45
stmatch---of 1
stminphys---of 4
stopen13%of 16
stread---of 1
ststart---of 22
ststrategy---of 11
stwrite---of 1
-----------
SUMMARY13%of 16
fido_match---of 3
fidoioctl---of 6
fidoopen100%of 1
-----------
SUMMARY100%of 1
ffs1_balloc---of 70
ffs2_balloc38%of 77
ffs_balloc67%of 3
-----------
SUMMARY39%of 80
ah46_input---of 6
ah4_ctlinput---of 4
ah_sysctl100%of 4
ah_sysctl_ahstat---of 1
esp46_input---of 6
esp4_ctlinput---of 4
esp_sysctl100%of 4
esp_sysctl_espstat---of 1
ipcomp46_input---of 6
ipcomp_sysctl100%of 4
ipcomp_sysctl_ipcompstat---of 1
ipsec_common_ctlinput---of 11
ipsec_common_input---of 42
ipsec_common_input_cb---of 50
ipsec_forward_check---of 3
ipsec_init---of 1
ipsec_input_disabled---of 4
ipsec_local_check---of 17
ipsec_protoff---of 8
ipsec_set_mtu---of 8
ipsec_sysctl100%of 6
ipsec_sysctl_ipsecstat---of 1
udpencap_ctlinput---of 17
-----------
SUMMARY100%of 18
checkdirs---of 15
copyout_statfs---of 5
dochflagsat---of 4
dofaccessat100%of 13
dofchmodat84%of 6
dofchownat50%of 10
dofstatat70%of 10
dofutimens---of 8
dolinkat89%of 9
domkdirat84%of 6
domknodat87%of 22
doopenat66%of 32
dopathconfat---of 4
doreadlinkat100%of 4
dorenameat95%of 18
dosymlinkat100%of 6
dotruncate67%of 9
dounlinkat75%of 12
dounmount---of 19
dounmount_leaf---of 15
doutimensat---of 4
dovchflags67%of 9
dovutimens91%of 21
getvnode72%of 7
sys___realpath---of 15
sys___tmpfd---of 14
sys_access---of 1
sys_chdir100%of 5
sys_chflags100%of 3
sys_chflagsat100%of 4
sys_chmod100%of 1
sys_chown100%of 1
sys_chroot86%of 7
sys_faccessat100%of 1
sys_fchdir50%of 16
sys_fchflags63%of 8
sys_fchmod67%of 12
sys_fchmodat100%of 1
sys_fchown53%of 17
sys_fchownat100%of 1
sys_fhopen---of 37
sys_fhstat---of 7
sys_fhstatfs---of 7
sys_fstatat---of 1
sys_fstatfs---of 15
sys_fsync63%of 8
sys_ftruncate70%of 10
sys_futimens---of 15
sys_futimes---of 8
sys_getdents72%of 14
sys_getfh---of 5
sys_getfsstat---of 16
sys_lchown45%of 9
sys_link100%of 1
sys_linkat100%of 1
sys_lseek86%of 7
sys_lstat100%of 1
sys_mkdir100%of 1
sys_mkdirat100%of 1
sys_mkfifo---of 1
sys_mkfifoat---of 1
sys_mknod100%of 1
sys_mknodat100%of 1
sys_mount---of 32
sys_open100%of 1
sys_openat100%of 1
sys_pathconf---of 3
sys_pathconfat---of 4
sys_pread100%of 3
sys_preadv100%of 3
sys_pwrite100%of 3
sys_pwritev100%of 3
sys_quotactl---of 3
sys_readlink100%of 1
sys_readlinkat100%of 1
sys_rename100%of 1
sys_renameat100%of 1
sys_revoke---of 12
sys_rmdir100%of 1
sys_stat100%of 1
sys_statfs---of 7
sys_symlink100%of 1
sys_symlinkat100%of 1
sys_sync13%of 8
sys_truncate100%of 4
sys_umask---of 3
sys_unlink100%of 1
sys_unlinkat100%of 1
sys_unmount---of 7
sys_unveil98%of 34
sys_utimensat89%of 18
sys_utimes90%of 10
-----------
SUMMARY79%of 424
fifo_advlock100%of 1
fifo_close84%of 12
fifo_ebadf---of 1
fifo_inactive---of 1
fifo_ioctl100%of 8
fifo_kqfilter100%of 9
fifo_open89%of 26
fifo_pathconf---of 5
fifo_print---of 1
fifo_printinfo---of 1
fifo_read86%of 7
fifo_reclaim67%of 3
fifo_write67%of 3
filt_fifoexcept50%of 4
filt_fifordetach100%of 1
filt_fiforead67%of 6
filt_fiformodify100%of 1
filt_fiforprocess100%of 6
filt_fifowdetach100%of 1
filt_fifowmodify100%of 1
filt_fifowprocess100%of 6
filt_fifowrite67%of 6
-----------
SUMMARY87%of 101
cpu_intr_init---of 8
intr_allocate_slot---of 27
intr_allocate_slot_cpu---of 24
intr_barrier---of 1
intr_calculatemasks---of 14
intr_default_setup---of 3
intr_disestablish---of 8
intr_establish---of 29
intr_handler---of 1
intr_printconfig---of 1
softintr100%of 1
spllower100%of 3
splraise67%of 3
x86_nmi---of 1
-----------
SUMMARY86%of 7
bawrite100%of 1
bcstats_print---of 1
bdwrite100%of 3
bio_doread---of 8
biodone60%of 15
biowait63%of 8
bread100%of 7
bread_cluster64%of 22
bread_cluster_callback---of 23
breadn48%of 21
brelse66%of 26
buf_adjcnt67%of 3
buf_daemon---of 19
buf_dirty---of 6
buf_flip_dma37%of 11
buf_flip_high---of 10
buf_get56%of 27
buf_put59%of 17
buf_undirty---of 6
bufadjust60%of 5
bufbackoff---of 19
bufcache_adjust58%of 7
bufcache_getcleanbuf---of 18
bufcache_getcleanbuf_range---of 6
bufcache_getdirtybuf---of 1
bufcache_getdmacleanbuf---of 6
bufcache_gethighcleanbuf---of 3
bufcache_init---of 1
bufcache_recover_dmapages---of 29
bufcache_release48%of 21
bufcache_take54%of 13
bufinit---of 13
bwrite63%of 16
chillbufs---of 7
discard_buffer---of 5
getblk63%of 8
geteblk67%of 3
hibernate_resume_bufcache---of 1
hibernate_suspend_bufcache---of 19
incore60%of 5
-----------
SUMMARY59%of 239
GetNewKeyFromSHA---of 1
adjust_tcp_mss---of 17
ip_is_idle_packet---of 33
mppe_key_change---of 6
pipex_ccp_input---of 6
pipex_ccp_output---of 3
pipex_common_input---of 21
pipex_destroy_all_sessions20%of 10
pipex_export_session_stats---of 1
pipex_get_closed---of 11
pipex_get_stat---of 7
pipex_init---of 5
pipex_init_session---of 41
pipex_ioctl50%of 4
pipex_ip6_input---of 4
pipex_ip_input---of 19
pipex_ip_output---of 20
pipex_iterator---of 17
pipex_l2tp_input---of 23
pipex_l2tp_lookup_session---of 4
pipex_l2tp_output---of 14
pipex_l2tp_userland_lookup_session43%of 21
pipex_l2tp_userland_lookup_session_ipv4100%of 1
pipex_l2tp_userland_lookup_session_ipv6100%of 1
pipex_l2tp_userland_output---of 8
pipex_link_session---of 32
pipex_lookup_by_ip_address---of 5
pipex_lookup_by_ip_address_locked---of 4
pipex_lookup_by_session_id---of 8
pipex_lookup_by_session_id_locked---of 8
pipex_mppe_init---of 12
pipex_mppe_input---of 31
pipex_mppe_output---of 17
pipex_mppe_reduce_key---of 4
pipex_notify_close_session---of 4
pipex_ppp_input---of 30
pipex_ppp_output---of 11
pipex_ppp_proto---of 7
pipex_pppoe_input---of 4
pipex_pppoe_lookup_session---of 7
pipex_pppoe_output---of 8
pipex_pptp_input---of 28
pipex_pptp_lookup_session---of 4
pipex_pptp_output---of 14
pipex_pptp_userland_lookup_session30%of 17
pipex_pptp_userland_lookup_session_ipv4100%of 1
pipex_pptp_userland_lookup_session_ipv6---of 1
pipex_pptp_userland_output---of 10
pipex_rele_session---of 4
pipex_session_init_mppe_recv---of 1
pipex_session_init_mppe_send---of 1
pipex_session_log---of 5
pipex_sockaddr_compar_addr---of 6
pipex_sockaddr_hash_key---of 4
pipex_sysctl100%of 4
pipex_timer---of 19
pipex_timer_start---of 1
pipex_timer_stop---of 1
pipex_unlink_session---of 1
pipex_unlink_session_locked---of 20
pipexintr---of 11
-----------
SUMMARY43%of 59
inet_ntop40%of 5
inet_ntop657%of 46
sockaddr_ntop---of 9
-----------
SUMMARY55%of 51
dev_rawpart---of 4
getnulldev---of 1
iskmemdev100%of 3
iszerodev100%of 3
-----------
SUMMARY100%of 6
divert6_attach60%of 5
divert6_init---of 1
divert6_output14%of 22
divert6_packet---of 15
divert6_send100%of 1
divert6_sysctl100%of 4
divert6_sysctl_div6stat---of 1
-----------
SUMMARY35%of 32
strncpy91%of 11
-----------
SUMMARY91%of 11
add_m6fc55%of 11
add_m6if80%of 15
del_m6fc50%of 8
del_m6if82%of 11
get_mif6_cnt---of 8
get_sg6_cnt38%of 8
ip6_mdq---of 17
ip6_mforward---of 23
ip6_mrouter_detach67%of 3
ip6_mrouter_done62%of 13
ip6_mrouter_get100%of 1
ip6_mrouter_init---of 6
ip6_mrouter_set87%of 23
mf6c_add---of 9
mf6c_add_route---of 5
mf6c_expire_route---of 5
mf6c_find---of 8
mf6c_update---of 33
mrouter6_rtwalk_delete100%of 1
mrt6_iflookupbymif---of 8
mrt6_ioctl82%of 11
mrt6_mcast_add---of 12
mrt6_mcast_del---of 3
mrt6_rtwalk_mf6csysctl14%of 23
mrt6_sysctl_mfc67%of 9
mrt6_sysctl_mif84%of 12
phyint_send6---of 10
socket6_send---of 4
-----------
SUMMARY64%of 149
domaininit---of 45
net_sysctl88%of 25
pfctlinput---of 33
pffasttimo---of 31
pffinddomain---of 7
pffindproto100%of 18
pffindtype100%of 12
pfslowtimo---of 31
-----------
SUMMARY95%of 55
sysctl_wdog20%of 10
wdog_register---of 3
wdog_shutdown---of 3
wdog_tickle---of 3
-----------
SUMMARY20%of 10
dt_dev_alloc_probe---of 3
dt_dev_register_probe---of 1
dt_ioctl_get_args---of 14
dt_ioctl_get_auxbase---of 21
dt_ioctl_get_stats---of 1
dt_ioctl_list_probes---of 7
dt_ioctl_probe_disable---of 6
dt_ioctl_probe_enable---of 6
dt_ioctl_record_start---of 8
dt_ioctl_record_stop20%of 10
dt_pcb_alloc---of 4
dt_pcb_free---of 3
dt_pcb_purge---of 4
dt_pcb_ring_consume---of 4
dt_pcb_ring_copy---of 5
dt_pcb_ring_get---of 9
dtattach---of 1
dtclose67%of 9
dtioctl12%of 26
dtlookup---of 4
dtopen43%of 7
dtread19%of 16
-----------
SUMMARY25%of 68
ffs1_blkpref---of 24
ffs2_blkpref64%of 25
ffs_alloc31%of 26
ffs_alloccg52%of 31
ffs_alloccgblk34%of 18
ffs_blkfree33%of 43
ffs_cgread---of 5
ffs_clusteracct10%of 22
ffs_dirpref38%of 43
ffs_fragextend70%of 26
ffs_freefile53%of 17
ffs_hashalloc---of 9
ffs_inode_alloc28%of 36
ffs_inode_free100%of 1
ffs_mapsearch48%of 19
ffs_nodealloccg47%of 45
ffs_realloccg30%of 55
-----------
SUMMARY40%of 407
pvbus_activate---of 1
pvbus_attach---of 34
pvbus_hyperv---of 3
pvbus_hyperv_print---of 1
pvbus_identify---of 15
pvbus_init_cpu---of 19
pvbus_kvm---of 1
pvbus_match---of 1
pvbus_minor---of 16
pvbus_print---of 3
pvbus_probe---of 1
pvbus_reboot---of 1
pvbus_search---of 3
pvbus_shutdown---of 1
pvbus_xen---of 4
pvbus_xen_print---of 1
pvbusclose11%of 19
pvbusgetstr---of 5
pvbusioctl17%of 37
pvbusopen43%of 19
-----------
SUMMARY22%of 75
udp6_output90%of 39
-----------
SUMMARY90%of 39
playtone72%of 14
rest---of 3
spkrattach---of 1
spkrclose67%of 3
spkrioctl90%of 19
spkropen100%of 4
spkrprobe---of 1
spkrwrite94%of 83
-----------
SUMMARY91%of 123
udp6_ctlinput---of 22
udp_attach50%of 8
udp_bind100%of 1
udp_connect50%of 10
udp_ctlinput---of 12
udp_detach67%of 3
udp_disconnect100%of 8
udp_init---of 1
udp_input---of 110
udp_lock---of 3
udp_locked100%of 1
udp_notify---of 1
udp_output72%of 38
udp_sbappend---of 26
udp_send75%of 8
udp_shutdown100%of 1
udp_sysctl100%of 8
udp_sysctl_udpstat---of 1
udp_unlock---of 3
-----------
SUMMARY74%of 86
cpu_is_online67%of 3
cpuset_add---of 3
cpuset_add_all---of 1
cpuset_cardinality---of 15
cpuset_clear---of 1
cpuset_complement---of 4
cpuset_copy---of 1
cpuset_del---of 3
cpuset_first---of 5
cpuset_init_cpu---of 5
cpuset_intersection---of 4
cpuset_isset---of 3
cpuset_union---of 4
remrunqueue67%of 12
sched_barrier---of 1
sched_choosecpu---of 1
sched_choosecpu_fork100%of 1
sched_chooseproc50%of 10
sched_exit---of 3
sched_idle---of 24
sched_init_cpu---of 11
sched_init_runqueues---of 1
sched_kthreads_create---of 3
sched_peg_curproc---of 1
sched_proc_to_cpu_cost---of 1
sched_steal_proc---of 1
sched_toidle---of 8
setrunqueue54%of 15
sysctl_hwncpuonline20%of 15
sysctl_hwsmt75%of 4
-----------
SUMMARY50%of 60
add_mfc22%of 14
add_vif15%of 20
del_mfc30%of 10
del_vif25%of 12
get_api_config---of 4
get_api_support---of 4
get_sg_cnt23%of 9
get_version---of 1
get_vif_cnt---of 8
if_lookupbyvif---of 8
ip_mdq---of 15
ip_mforward---of 16
ip_mrouter_done54%of 13
ip_mrouter_get60%of 10
ip_mrouter_init---of 8
ip_mrouter_set60%of 25
mfc_add---of 9
mfc_add_route---of 5
mfc_expire_route---of 5
mfc_find---of 8
mrouter_rtwalk_delete100%of 1
mrt_ioctl67%of 12
mrt_mcast_del---of 3
mrt_rtwalk_mfcsysctl18%of 17
mrt_sysctl_mfc78%of 9
mrt_sysctl_vif50%of 12
rt_mcast_add---of 12
set_api_config---of 11
socket_send---of 4
update_mfc_params---of 35
vif_delete67%of 3
-----------
SUMMARY42%of 167
filt_hotplugmodify100%of 1
filt_hotplugprocess100%of 6
filt_hotplugrdetach100%of 1
filt_hotplugread100%of 1
hotplug_device_attach100%of 1
hotplug_device_detach100%of 1
hotplug_get_event---of 3
hotplug_put_event75%of 4
hotplugattach---of 1
hotplugclose63%of 8
hotplugioctl100%of 1
hotplugkqfilter100%of 3
hotplugopen100%of 5
hotplugread50%of 6
-----------
SUMMARY82%of 38
divert_attach67%of 6
divert_bind100%of 1
divert_detach67%of 3
divert_init---of 1
divert_lock---of 3
divert_locked100%of 1
divert_output20%of 15
divert_packet---of 15
divert_send100%of 1
divert_shutdown100%of 1
divert_sysctl100%of 4
divert_sysctl_divstat---of 1
divert_unlock---of 3
-----------
SUMMARY54%of 32
lpt_activate---of 13
lpt_attach_common---of 1
lpt_detach_common---of 3
lpt_not_ready---of 5
lpt_port_test---of 3
lptclose---of 5
lptintr---of 15
lptopen16%of 19
lptpushbytes---of 22
lptwakeup---of 3
lptwrite---of 5
-----------
SUMMARY16%of 19
uvm_sysctl84%of 31
uvm_total---of 12
uvmexp_print---of 1
uvmexp_read---of 1
-----------
SUMMARY84%of 31
allocpid---of 12
alloctid---of 3
fork139%of 55
fork_check_maxthread---of 4
fork_return---of 3
freepid---of 1
ispidtaken---of 9
proc_trampoline_mi---of 7
process_initialize67%of 3
process_new44%of 32
sys___tfork---of 8
sys_fork---of 1
sys_vfork---of 1
thread_fork---of 19
thread_new---of 1
-----------
SUMMARY42%of 90
rip_attach56%of 9
rip_bind88%of 8
rip_chkhdr30%of 17
rip_connect100%of 3
rip_ctloutput96%of 21
rip_detach75%of 4
rip_disconnect67%of 3
rip_init---of 1
rip_input69%of 35
rip_lock---of 3
rip_locked100%of 1
rip_output60%of 15
rip_send84%of 6
rip_shutdown100%of 1
rip_unlock---of 3
-----------
SUMMARY70%of 123
unveil_add74%of 30
unveil_add_name---of 1
unveil_add_name_unlocked67%of 3
unveil_add_vnode86%of 7
unveil_check_component78%of 18
unveil_check_final80%of 49
unveil_copy16%of 13
unveil_covered---of 7
unveil_delete_names---of 4
unveil_destroy---of 9
unveil_find_cover71%of 17
unveil_flagmatch84%of 6
unveil_lookup---of 10
unveil_namelookup---of 3
unveil_parsepermissions---of 9
unveil_removevnode---of 14
unveil_setflags---of 1
unveil_start_relative67%of 12
unvname_delete---of 1
unvname_new---of 1
unvname_rbt_RBT_COMPARE100%of 3
-----------
SUMMARY72%of 158
calibrate_tsc_freq---of 5
cpu_recalibrate_tsc---of 8
measure_tsc_freq---of 20
rdtsc_lfence---of 1
rdtscp---of 1
tsc_delay---of 3
tsc_freq_cpuid---of 16
tsc_freq_msr---of 12
tsc_get_timecount_lfence---of 1
tsc_get_timecount_rdtscp100%of 1
tsc_identify---of 32
tsc_timecounter_init---of 9
-----------
SUMMARY100%of 1
uaddr_bestfit_create---of 1
uaddr_bestfit_destroy---of 1
uaddr_bestfit_insert67%of 3
uaddr_bestfit_remove67%of 3
uaddr_bestfit_select60%of 10
uaddr_destroy100%of 1
uaddr_free_rbtree_RBT_COMPARE100%of 3
uaddr_kbootstrap_destroy---of 3
uaddr_kbootstrap_select29%of 7
uaddr_pivot_create---of 1
uaddr_pivot_destroy---of 1
uaddr_pivot_insert---of 8
uaddr_pivot_newpivot---of 15
uaddr_pivot_print---of 13
uaddr_pivot_random---of 1
uaddr_pivot_remove---of 34
uaddr_pivot_select---of 9
uaddr_rnd_create100%of 1
uaddr_rnd_destroy100%of 1
uaddr_rnd_insert100%of 1
uaddr_rnd_remove100%of 1
uaddr_rnd_select---of 24
uaddr_stack_brk_create100%of 1
uaddr_stack_brk_select---of 7
uvm_addr_align---of 1
uvm_addr_align_back---of 1
uvm_addr_destroy100%of 3
uvm_addr_entrybyspace---of 6
uvm_addr_fitspace30%of 10
uvm_addr_init---of 1
uvm_addr_invoke40%of 10
uvm_addr_linsearch---of 23
uvm_addr_print---of 4
-----------
SUMMARY57%of 55
copypktopts57%of 16
in6_delayed_cksum40%of 10
in6_proto_cksum_out56%of 47
ip6_clearpktopts58%of 33
ip6_copyexthdr---of 8
ip6_ctloutput92%of 176
ip6_fragment45%of 20
ip6_freemoptions100%of 7
ip6_freepcbopts100%of 3
ip6_getmoptions---of 8
ip6_getpcbopt77%of 26
ip6_getpmtu---of 7
ip6_initpktopts---of 1
ip6_insert_jumboopt25%of 8
ip6_insertfraghdr---of 10
ip6_mloopback50%of 18
ip6_output67%of 185
ip6_output_ipsec_lookup19%of 11
ip6_output_ipsec_pmtu_update---of 15
ip6_output_ipsec_send---of 24
ip6_pcbopt100%of 3
ip6_randomid---of 1
ip6_randomid_init---of 1
ip6_raw_ctloutput75%of 12
ip6_setmoptions92%of 80
ip6_setpktopt87%of 66
ip6_setpktopts79%of 14
ip6_splithdr60%of 5
-----------
SUMMARY75%of 740
usb_abort_task_thread---of 8
usb_activate---of 8
usb_add_task---of 7
usb_attach---of 17
usb_attach_roothub---of 4
usb_create_task_threads---of 4
usb_detach---of 6
usb_detach_roothub---of 7
usb_explore---of 12
usb_fill_udc_task---of 6
usb_fill_udf_task---of 5
usb_match---of 1
usb_needs_explore---of 4
usb_needs_reattach---of 3
usb_rem_task---of 6
usb_rem_wait_task---of 10
usb_schedsoftintr---of 5
usb_tap---of 25
usb_task_thread---of 12
usb_wait_task---of 5
usbclose---of 1
usbctlprint---of 3
usbioctl---of 46
usbopen50%of 4
-----------
SUMMARY50%of 4
wsmux_add_mux70%of 10
wsmux_attach_sc42%of 12
wsmux_create---of 3
wsmux_depth67%of 6
wsmux_detach_sc43%of 7
wsmux_detach_sc_locked50%of 6
wsmux_do_close---of 6
wsmux_do_displayioctl---of 10
wsmux_do_ioctl82%of 54
wsmux_do_open---of 8
wsmux_evsrc_set_display---of 5
wsmux_get_layout---of 1
wsmux_getmux56%of 18
wsmux_mux_close67%of 6
wsmux_mux_open23%of 9
wsmux_set_display---of 11
wsmux_set_layout67%of 3
wsmuxattach---of 1
wsmuxclose72%of 7
wsmuxioctl100%of 1
wsmuxkqfilter100%of 3
wsmuxopen58%of 14
wsmuxread67%of 3
-----------
SUMMARY65%of 159
ujoy_hid_is_collection---of 6
ujoy_match---of 3
ujoyioctl---of 8
ujoyopen100%of 3
-----------
SUMMARY100%of 3
ntfs_calccfree---of 8
ntfs_checkexp---of 3
ntfs_fhtovp---of 3
ntfs_init---of 1
ntfs_mount---of 13
ntfs_mountfs---of 52
ntfs_quotactl---of 1
ntfs_root---of 3
ntfs_start---of 1
ntfs_statfs---of 1
ntfs_sync---of 1
ntfs_sysctl100%of 1
ntfs_unmount---of 62
ntfs_vget---of 3
ntfs_vgetex---of 25
ntfs_vptofh---of 1
-----------
SUMMARY100%of 1
amap_add30%of 10
amap_adjref_anons59%of 12
amap_alloc34%of 6
amap_alloc164%of 19
amap_chunk_free---of 6
amap_chunk_get70%of 13
amap_copy54%of 50
amap_cow_now---of 18
amap_free58%of 14
amap_init---of 3
amap_lookup78%of 9
amap_lookups75%of 12
amap_populate---of 5
amap_pp_adjref82%of 32
amap_pp_establish---of 5
amap_ref67%of 3
amap_splitref30%of 10
amap_swap_off---of 20
amap_unadd59%of 17
amap_unref84%of 6
amap_wipeout58%of 19
amap_wiperange86%of 27
amap_wiperange_chunk72%of 7
-----------
SUMMARY64%of 266
_rb_check50%of 4
_rb_find100%of 7
_rb_insert92%of 46
_rb_left100%of 1
_rb_max75%of 4
_rb_min100%of 4
_rb_next100%of 9
_rb_nfind86%of 7
_rb_parent100%of 1
_rb_poison100%of 1
_rb_prev100%of 9
_rb_remove89%of 94
_rb_right100%of 1
_rb_root100%of 3
_rb_set_left---of 1
_rb_set_parent---of 1
_rb_set_right---of 1
-----------
SUMMARY91%of 191
bufq_dequeue100%of 1
bufq_destroy---of 7
bufq_done---of 7
bufq_drain---of 4
bufq_fifo_create---of 3
bufq_fifo_dequeue50%of 4
bufq_fifo_destroy---of 1
bufq_fifo_peek100%of 1
bufq_fifo_queue100%of 1
bufq_fifo_requeue---of 3
bufq_init---of 8
bufq_nscan_create---of 3
bufq_nscan_dequeue---of 16
bufq_nscan_destroy---of 1
bufq_nscan_peek---of 3
bufq_nscan_queue---of 8
bufq_nscan_requeue---of 3
bufq_nscan_resort---of 12
bufq_peek100%of 1
bufq_queue50%of 4
bufq_quiesce---of 7
bufq_requeue---of 1
bufq_restart---of 4
bufq_simple_nscan---of 11
bufq_switch---of 7
bufq_wait40%of 5
-----------
SUMMARY59%of 17
arp_rtrequest56%of 27
arpcache---of 18
arpinit---of 1
arpinput100%of 3
arpintr---of 6
arpinvalidate---of 3
arplookup---of 8
arpproxy---of 5
arppullup75%of 12
arpreply---of 1
arprequest67%of 3
arpresolve52%of 33
arptfree---of 7
arptimer---of 6
in_arpinput---of 30
in_revarpinput56%of 9
revarpinput100%of 3
revarprequest---of 3
revarpwhoami---of 1
revarpwhoarewe---of 9
-----------
SUMMARY60%of 90
sensor_attach70%of 13
sensor_detach---of 6
sensor_find100%of 10
sensor_quiesce---of 4
sensor_restart---of 1
sensor_task_register---of 7
sensor_task_tick---of 1
sensor_task_unregister---of 1
sensor_task_work---of 7
sensordev_deinstall75%of 4
sensordev_get100%of 5
sensordev_install80%of 5
-----------
SUMMARY84%of 37
sc_print_addr---of 1
scsi_cmd_rw_decode---of 10
scsi_copy_internal_data---of 3
scsi_decode_sense---of 22
scsi_default_get---of 1
scsi_default_put---of 3
scsi_delay---of 5
scsi_do_mode_sense---of 17
scsi_done---of 1
scsi_init---of 3
scsi_init_inquiry---of 1
scsi_inquire---of 10
scsi_inquire_vpd---of 4
scsi_interpret_sense---of 61
scsi_io_get---of 6
scsi_io_get_done---of 1
scsi_io_put---of 1
scsi_ioh_add---of 4
scsi_ioh_del---of 4
scsi_ioh_deq---of 3
scsi_ioh_pending---of 1
scsi_ioh_set---of 1
scsi_iopool_destroy---of 8
scsi_iopool_get---of 1
scsi_iopool_init---of 1
scsi_iopool_put---of 1
scsi_iopool_run56%of 9
scsi_link_close---of 3
scsi_link_open---of 3
scsi_link_shutdown---of 19
scsi_mode_select---of 3
scsi_mode_select_big---of 3
scsi_mode_sense---of 4
scsi_mode_sense_big---of 4
scsi_mode_sense_big_page---of 3
scsi_mode_sense_page---of 3
scsi_move---of 4
scsi_move_done---of 1
scsi_parse_blkdesc---of 16
scsi_pending_finish---of 1
scsi_pending_start---of 1
scsi_plug_detach---of 1
scsi_plug_probe---of 1
scsi_prevent---of 4
scsi_print_sense---of 21
scsi_read_cap_10---of 3
scsi_read_cap_16---of 3
scsi_report_luns---of 3
scsi_req_detach67%of 3
scsi_req_probe---of 3
scsi_start---of 3
scsi_test_unit_ready---of 3
scsi_xs_error12%of 18
scsi_xs_exec100%of 1
scsi_xs_get12%of 18
scsi_xs_get_done---of 1
scsi_xs_io50%of 4
scsi_xs_put67%of 3
scsi_xs_sync40%of 10
scsi_xs_sync_done---of 4
scsi_xsh_add50%of 4
scsi_xsh_del---of 8
scsi_xsh_ioh40%of 5
scsi_xsh_runqueue42%of 12
scsi_xsh_set---of 1
-----------
SUMMARY34%of 87
exec_script_makecmds77%of 46
-----------
SUMMARY77%of 46
fill_vmmap100%of 1
uvm_atopg---of 4
uvm_exit---of 1
uvm_init_limits---of 1
uvm_kernacc---of 1
uvm_pause67%of 3
uvm_uarea_alloc100%of 1
uvm_uarea_free---of 1
uvm_vslock100%of 3
uvm_vslock_device34%of 18
uvm_vsunlock67%of 3
uvm_vsunlock_device50%of 4
-----------
SUMMARY52%of 33
mld6_checktimer---of 10
mld6_fasttimeo---of 14
mld6_init---of 1
mld6_input---of 50
mld6_sendpkt75%of 12
mld6_start_listening100%of 4
mld6_stop_listening60%of 5
-----------
SUMMARY77%of 21
bpe_clone_create---of 5
bpe_clone_destroy---of 3
bpe_detach_hook---of 3
bpe_down---of 5
bpe_eb_port_eq---of 1
bpe_eb_port_ifname---of 1
bpe_eb_port_rele---of 1
bpe_eb_port_sa---of 1
bpe_eb_port_take---of 3
bpe_input50%of 10
bpe_ioctl---of 44
bpe_link_hook---of 5
bpe_start---of 16
bpe_tree_RBT_COMPARE---of 5
bpe_up---of 14
bpeattach---of 1
-----------
SUMMARY50%of 10
exec_process_vmcmds---of 13
exec_setup_stack---of 9
kill_vmcmds38%of 8
vmcmd_map_pagedvn---of 12
vmcmd_map_readvn---of 10
vmcmd_map_zero---of 5
vmcmd_mutable---of 3
vmcmd_randomize---of 9
vmcmdset_extend---of 5
-----------
SUMMARY38%of 8
poison_check80%of 5
poison_mem88%of 8
poison_value100%of 1
-----------
SUMMARY86%of 14
decay_aftersleep---of 5
mi_switch54%of 30
preempt100%of 1
roundrobin---of 7
schedclock---of 5
schedcpu---of 17
scheduler_start---of 6
setperf_auto---of 20
setpriority---of 3
setrunnable48%of 19
sysctl_hwperfpolicy20%of 10
sysctl_hwsetperf34%of 6
update_loadavg---of 4
yield100%of 1
-----------
SUMMARY47%of 67
canonpath---of 19
parsepledges80%of 15
pledge_adjtime---of 4
pledge_chown23%of 9
pledge_fail---of 14
pledge_fcntl50%of 4
pledge_flock50%of 4
pledge_ioctl2%of 190
pledge_kill---of 5
pledge_namei5%of 47
pledge_profil---of 3
pledge_protexec29%of 7
pledge_recvfd20%of 10
pledge_sendfd20%of 10
pledge_sendit50%of 4
pledge_socket17%of 12
pledge_sockopt4%of 60
pledge_swapctl---of 4
pledge_syscall---of 5
pledge_sysctl2%of 148
pledgereq_flags---of 4
sys_pledge74%of 23
-----------
SUMMARY10%of 543
in_delayed_cksum88%of 8
in_hdr_cksum_out50%of 8
in_ifcap_cksum---of 8
in_proto_cksum_out60%of 37
ip_ctloutput95%of 132
ip_fragment50%of 38
ip_freemoptions100%of 5
ip_getmoptions93%of 14
ip_insertoptions60%of 10
ip_mloopback---of 3
ip_multicast_if86%of 7
ip_optcopy---of 15
ip_output63%of 107
ip_output_ipsec_lookup24%of 13
ip_output_ipsec_pmtu_update---of 14
ip_output_ipsec_send---of 25
ip_pcbopts89%of 18
ip_setmoptions90%of 68
-----------
SUMMARY77%of 465
lf_advlock81%of 26
lf_alloc---of 4
lf_clearlock95%of 18
lf_deadlock36%of 17
lf_findoverlap89%of 27
lf_free50%of 6
lf_getblock---of 6
lf_getlock78%of 9
lf_init---of 1
lf_purgelocks69%of 19
lf_setlock85%of 64
lf_split88%of 8
lf_wakelock100%of 4
ls_ref---of 1
ls_rele---of 5
-----------
SUMMARY79%of 198
in_cksum52%of 29
-----------
SUMMARY52%of 29
KQREF---of 1
KQRELE50%of 12
dokqueue75%of 8
filt_badfd100%of 1
filt_dead67%of 3
filt_deaddetach100%of 1
filt_fileattach100%of 1
filt_kqdetach75%of 8
filt_kqueue---of 3
filt_kqueue_common---of 3
filt_kqueuemodify67%of 3
filt_kqueueprocess89%of 9
filt_proc25%of 12
filt_procattach55%of 11
filt_procdetach72%of 7
filt_seltrue100%of 1
filt_seltruedetach100%of 1
filt_seltruemodify100%of 1
filt_seltrueprocess100%of 4
filt_timeradd88%of 8
filt_timerattach89%of 9
filt_timerdetach100%of 1
filt_timerexpire46%of 11
filt_timermodify100%of 8
filt_timerprocess100%of 4
klist_free67%of 3
klist_init---of 1
klist_init_mutex100%of 1
klist_init_rwlock100%of 1
klist_insert60%of 5
klist_insert_locked100%of 3
klist_invalidate64%of 22
klist_mutex_assertlk67%of 3
klist_mutex_lock100%of 1
klist_mutex_unlock100%of 1
klist_remove75%of 8
klist_remove_locked84%of 6
klist_rwlock_assertlk100%of 1
klist_rwlock_lock100%of 1
klist_rwlock_unlock100%of 1
knote60%of 5
knote_acquire29%of 7
knote_activate75%of 4
knote_assign100%of 1
knote_attach43%of 7
knote_dequeue40%of 5
knote_detach75%of 8
knote_drop80%of 10
knote_enqueue56%of 9
knote_fdclose88%of 8
knote_locked90%of 10
knote_processexit---of 1
knote_release34%of 6
knote_remove58%of 26
knote_submit100%of 4
kqpoll_done40%of 5
kqpoll_exit---of 4
kqpoll_init75%of 8
kqueue_alloc---of 1
kqueue_close100%of 1
kqueue_do_check50%of 14
kqueue_init---of 1
kqueue_init_percpu---of 1
kqueue_ioctl100%of 1
kqueue_kqfilter67%of 6
kqueue_purge88%of 8
kqueue_read100%of 1
kqueue_register77%of 84
kqueue_scan76%of 61
kqueue_scan_finish43%of 7
kqueue_scan_setup100%of 1
kqueue_sleep86%of 7
kqueue_stat---of 1
kqueue_task---of 5
kqueue_terminate65%of 14
kqueue_wakeup---of 6
kqueue_write100%of 1
seltrue_kqfilter100%of 3
sys_kevent86%of 35
sys_kqueue100%of 1
sys_kqueue1---of 3
-----------
SUMMARY72%of 549
mountnfs---of 9
nfs_checkexp---of 1
nfs_decode_args---of 59
nfs_fhtovp---of 1
nfs_fsinfo---of 26
nfs_mount---of 13
nfs_mount_diskless---of 4
nfs_mountroot---of 8
nfs_quotactl---of 1
nfs_reaper---of 1
nfs_root---of 3
nfs_start---of 1
nfs_statfs---of 22
nfs_sync---of 12
nfs_sysctl80%of 10
nfs_unmount---of 7
nfs_vget---of 1
nfs_vptofh---of 1
-----------
SUMMARY80%of 10
scsi_do_ioctl16%of 13
scsi_ioc_ata_cmd---of 19
scsi_ioc_cmd---of 24
-----------
SUMMARY16%of 13
ufs_inactive53%of 17
ufs_reclaim60%of 10
-----------
SUMMARY56%of 27
-----------
SUMMARY---of 0
-----------
SUMMARY---of 0
if_addgroup65%of 17
if_addrhook_add100%of 1
if_addrhook_del100%of 1
if_addrhooks_run100%of 1
if_alloc_sadl67%of 3
if_attach100%of 1
if_attach_common67%of 15
if_attach_ifq---of 1
if_attach_iqueues---of 5
if_attach_queues---of 6
if_attachhead---of 1
if_attachsetup38%of 8
if_clone_attach---of 4
if_clone_create59%of 12
if_clone_destroy75%of 8
if_clone_list---of 7
if_clone_lookup86%of 35
if_congested---of 3
if_congestion---of 1
if_counters_alloc67%of 3
if_counters_free---of 3
if_creategroup---of 3
if_createrdomain67%of 9
if_deactivate100%of 1
if_delgroup70%of 10
if_detach34%of 39
if_detached_ioctl---of 1
if_detached_qstart---of 1
if_detachhook_add---of 3
if_detachhook_del---of 1
if_down58%of 7
if_downall---of 6
if_enqueue40%of 5
if_enqueue_ifq60%of 5
if_free_sadl---of 3
if_get84%of 6
if_getdata56%of 9
if_getgroup78%of 9
if_getgroupattribs---of 5
if_getgrouplist---of 9
if_getgroupmembers75%of 12
if_group_egress_build---of 23
if_group_routechange50%of 10
if_hooks_run58%of 7
if_idxmap_alloc45%of 18
if_idxmap_free---of 6
if_idxmap_init---of 1
if_idxmap_insert40%of 5
if_idxmap_remove34%of 6
if_input---of 1
if_input_local44%of 25
if_input_process---of 7
if_isconnected---of 13
if_link_state_change67%of 3
if_linkstate---of 5
if_linkstate_task---of 9
if_linkstatehook_add---of 3
if_linkstatehook_del---of 1
if_netisr---of 20
if_output_local100%of 3
if_output_ml100%of 4
if_output_mq---of 6
if_output_tso60%of 10
if_put100%of 3
if_qstart_compat100%of 1
if_ref---of 1
if_remove---of 3
if_rtrequest_dummy100%of 1
if_rxhprio_l2_check---of 4
if_rxhprio_l3_check---of 1
if_rxr_get---of 7
if_rxr_info_ioctl---of 5
if_rxr_init---of 1
if_rxr_ioctl---of 7
if_rxr_livelocked---of 4
if_setgroupattribs75%of 8
if_setlladdr---of 3
if_setrdomain65%of 14
if_slowtimo---of 6
if_start---of 3
if_txhprio_l2_check---of 1
if_txhprio_l3_check---of 1
if_unit---of 5
if_up67%of 9
if_vinput100%of 6
if_watchdog_task---of 7
ifa_add67%of 3
ifa_del67%of 3
ifa_ifwithaddr85%of 13
ifa_ifwithdstaddr80%of 15
ifa_print_all---of 10
ifa_update_broadaddr67%of 3
ifaof_ifpforaddr50%of 18
ifconf97%of 26
ifinit---of 6
ifioctl91%of 196
ifioctl_get80%of 40
ifnewlladdr80%of 10
ifpromisc80%of 10
ifsetlro24%of 17
net_tq67%of 3
net_tq_barriers---of 1
niq_enlist---of 4
niq_enqueue75%of 4
niq_init---of 1
p2p_bpf_mtap---of 1
p2p_input---of 5
p2p_rtrequest14%of 15
-----------
SUMMARY72%of 726
in6_get_hw_ifid35%of 23
in6_get_ifid47%of 13
in6_get_rand_ifid---of 1
in6_ifattach50%of 14
in6_ifattach_linklocal74%of 15
in6_ifattach_loopback75%of 4
in6_ifdetach79%of 14
-----------
SUMMARY56%of 83
assertwaitok45%of 9
bdevsw_lookup---of 1
blktochr---of 6
cdevsw_lookup---of 1
chrtoblk100%of 4
enodev100%of 1
enoioctl---of 1
enosys---of 1
enxio100%of 1
eopnotsupp100%of 1
nullop100%of 1
-----------
SUMMARY71%of 17
gettdb_dir---of 14
gettdbbydst---of 16
gettdbbysrc---of 16
gettdbbysrcdst_dir9%of 35
ipsec_ids_flows_RBT_COMPARE---of 1
ipsec_ids_tree_RBT_COMPARE---of 11
ipsp_address---of 4
ipsp_aux_match---of 9
ipsp_ids_free29%of 7
ipsp_ids_gc---of 9
ipsp_ids_insert---of 9
ipsp_ids_lookup---of 4
ipsp_ids_match---of 1
ipsp_init---of 1
ipsp_is_unspecified---of 4
puttdb---of 1
puttdb_locked---of 11
reserve_spi---of 17
tdb_addtimeouts---of 7
tdb_alloc---of 1
tdb_cleanspd---of 7
tdb_delete---of 12
tdb_deltimeouts---of 13
tdb_firstuse---of 6
tdb_free---of 17
tdb_hash67%of 3
tdb_hashstats---of 42
tdb_init---of 4
tdb_printit---of 13
tdb_ref---of 3
tdb_rehash---of 14
tdb_soft_firstuse---of 6
tdb_soft_timeout---of 5
tdb_timeout---of 6
tdb_unbundle---of 17
tdb_unlink---of 1
tdb_unlink_locked---of 17
tdb_unref50%of 4
tdb_walk28%of 18
-----------
SUMMARY21%of 67
cnbell---of 4
cnclose43%of 7
cngetc---of 3
cnioctl84%of 6
cnkqfilter67%of 6
cnopen50%of 6
cnpollc---of 8
cnputc75%of 4
cnread75%of 4
cnstop---of 1
cnwrite75%of 4
nullcnpollc---of 1
-----------
SUMMARY65%of 37
sema_reallocate---of 1
semexit---of 10
seminit---of 1
semu_alloc---of 6
semundo_adjust35%of 26
semundo_clear73%of 18
sys___semctl54%of 75
sys_semget80%of 29
sys_semop70%of 62
sysctl_sysvsem100%of 9
-----------
SUMMARY63%of 219
lo_bpf_mtap100%of 1
loinput---of 4
loioctl100%of 8
loop_clone_create67%of 3
loop_clone_destroy19%of 11
loopattach---of 1
looutput80%of 5
lortrequest100%of 4
-----------
SUMMARY66%of 32
rip6_attach50%of 10
rip6_bind100%of 4
rip6_connect100%of 4
rip6_ctlinput---of 12
rip6_ctloutput93%of 14
rip6_detach75%of 4
rip6_disconnect67%of 3
rip6_init---of 1
rip6_input49%of 58
rip6_lock---of 3
rip6_locked100%of 1
rip6_output87%of 29
rip6_send84%of 6
rip6_shutdown100%of 1
rip6_sysctl100%of 4
rip6_sysctl_rip6stat---of 1
rip6_unlock---of 3
-----------
SUMMARY69%of 138
uvm_map50%of 81
uvm_map_addr_RBT_AUGMENT89%of 9
uvm_map_addr_RBT_COMPARE100%of 1
uvm_map_addr_augment---of 9
uvm_map_addr_augment_get---of 5
uvm_map_advice63%of 24
uvm_map_boundary80%of 15
uvm_map_check_copyin_add---of 14
uvm_map_checkprot56%of 20
uvm_map_clean54%of 63
uvm_map_clip_end50%of 4
uvm_map_clip_start50%of 4
uvm_map_create---of 1
uvm_map_deallocate---of 9
uvm_map_entrybyaddr---of 7
uvm_map_extract26%of 35
uvm_map_fill_vmmap53%of 17
uvm_map_findspace34%of 6
uvm_map_fix_space65%of 28
uvm_map_freelist_update---of 8
uvm_map_freelist_update_clear---of 7
uvm_map_freelist_update_refill---of 4
uvm_map_hint---of 4
uvm_map_immutable---of 29
uvm_map_inentry58%of 7
uvm_map_inentry_fix31%of 13
uvm_map_inentry_recheck---of 4
uvm_map_inentry_sp67%of 3
uvm_map_inherit66%of 32
uvm_map_init---of 3
uvm_map_is_stack_remappable53%of 17
uvm_map_isavail53%of 44
uvm_map_kmem_grow---of 13
uvm_map_lock_entry100%of 5
uvm_map_lookup_entry50%of 12
uvm_map_mkentry70%of 13
uvm_map_mquery67%of 36
uvm_map_pageable58%of 47
uvm_map_pageable_all45%of 38
uvm_map_pageable_pgon86%of 7
uvm_map_pageable_wire66%of 52
uvm_map_pie---of 3
uvm_map_printit---of 9
uvm_map_protect66%of 78
uvm_map_reference---of 1
uvm_map_remap_as_stack---of 5
uvm_map_set_uaddr---of 11
uvm_map_setup45%of 9
uvm_map_setup_entries---of 1
uvm_map_setup_md---of 1
uvm_map_splitentry43%of 14
uvm_map_submap---of 22
uvm_map_teardown63%of 16
uvm_map_uaddr46%of 37
uvm_map_uaddr_e---of 1
uvm_map_unlock_entry100%of 5
uvm_map_vmspace_update---of 8
uvm_mapanon46%of 53
uvm_mapent_addr_insert55%of 11
uvm_mapent_addr_remove50%of 10
uvm_mapent_alloc47%of 13
uvm_mapent_clone63%of 8
uvm_mapent_forkcopy---of 20
uvm_mapent_forkshared---of 3
uvm_mapent_forkzero---of 6
uvm_mapent_free67%of 6
uvm_mapent_free_insert88%of 16
uvm_mapent_free_remove60%of 10
uvm_mapent_isjoinable43%of 19
uvm_mapent_merge67%of 3
uvm_mapent_mkfree60%of 15
uvm_mapent_share---of 3
uvm_mapent_tryjoin78%of 9
uvm_object_printit---of 10
uvm_page_printit---of 18
uvm_share56%of 29
uvm_unmap67%of 9
uvm_unmap_detach82%of 16
uvm_unmap_detach_intrsafe43%of 7
uvm_unmap_kill_entry---of 1
uvm_unmap_kill_entry_withlock85%of 20
uvm_unmap_remove69%of 44
uvmspace_addref67%of 3
uvmspace_alloc100%of 1
uvmspace_dused38%of 8
uvmspace_exec---of 15
uvmspace_fork---of 31
uvmspace_free75%of 4
uvmspace_init---of 4
uvmspace_share67%of 3
vm_map_assert_anylock_ln75%of 4
vm_map_assert_wrlock_ln---of 5
vm_map_busy_ln40%of 5
vm_map_lock_ln75%of 12
vm_map_lock_read_ln67%of 3
vm_map_lock_try_ln---of 11
vm_map_unbusy_ln40%of 5
vm_map_unlock_ln67%of 6
vm_map_unlock_read_ln67%of 3
-----------
SUMMARY58%of 1147
ipcperm100%of 6
-----------
SUMMARY100%of 6
fusefs_checkexp---of 1
fusefs_fhtovp---of 1
fusefs_init---of 1
fusefs_mount---of 10
fusefs_quotactl---of 1
fusefs_root---of 3
fusefs_start---of 1
fusefs_statfs---of 8
fusefs_sync---of 1
fusefs_sysctl100%of 1
fusefs_unmount---of 6
fusefs_vget---of 8
fusefs_vptofh---of 1
-----------
SUMMARY100%of 1
filt_pppac_modify100%of 1
filt_pppac_process100%of 6
filt_pppac_rdetach100%of 1
filt_pppac_read67%of 3
filt_pppac_wdetach100%of 1
filt_pppac_write100%of 1
filt_pppx_modify100%of 1
filt_pppx_process100%of 6
filt_pppx_rdetach100%of 1
filt_pppx_read67%of 3
filt_pppx_wdetach100%of 1
filt_pppx_write100%of 1
pppac_ioctl---of 9
pppac_output---of 5
pppac_qstart---of 17
pppacattach---of 1
pppacclose63%of 8
pppacioctl40%of 15
pppackqfilter67%of 9
pppacopen84%of 6
pppacread23%of 18
pppacwrite22%of 14
pppx_add_session---of 18
pppx_del_session---of 4
pppx_dev2pxd---of 4
pppx_dev_lookup---of 4
pppx_if_destroy---of 4
pppx_if_find_locked---of 3
pppx_if_ioctl---of 9
pppx_if_next_unit---of 6
pppx_if_output---of 17
pppx_if_qstart---of 4
pppx_ifs_RBT_COMPARE---of 1
pppx_set_session_descr---of 4
pppxattach---of 1
pppxclose56%of 9
pppxioctl50%of 12
pppxkqfilter86%of 7
pppxopen100%of 5
pppxread37%of 11
pppxwrite37%of 22
-----------
SUMMARY54%of 162
minphys100%of 3
physio64%of 25
-----------
SUMMARY68%of 28
virtio_pci_adjust_config_region---of 4
virtio_pci_attach---of 23
virtio_pci_attach_09---of 5
virtio_pci_attach_10---of 25
virtio_pci_config_intr---of 3
virtio_pci_detach---of 8
virtio_pci_find_cap---of 10
virtio_pci_free_irqs---of 24
virtio_pci_get_status---of 1
virtio_pci_kick67%of 3
virtio_pci_legacy_intr---of 5
virtio_pci_legacy_intr_mpsafe---of 5
virtio_pci_match---of 8
virtio_pci_msix_establish---of 4
virtio_pci_negotiate_features---of 15
virtio_pci_negotiate_features_10---of 4
virtio_pci_poll_intr---of 3
virtio_pci_queue_intr---of 1
virtio_pci_read_device_config_1---of 1
virtio_pci_read_device_config_2---of 1
virtio_pci_read_device_config_4---of 1
virtio_pci_read_device_config_8---of 1
virtio_pci_read_queue_size---of 1
virtio_pci_set_msix_config_vector---of 1
virtio_pci_set_msix_queue_vector---of 1
virtio_pci_set_status---of 7
virtio_pci_setup_msix---of 20
virtio_pci_setup_queue---of 7
virtio_pci_shared_queue_intr---of 1
virtio_pci_write_device_config_1---of 1
virtio_pci_write_device_config_2---of 1
virtio_pci_write_device_config_4---of 1
virtio_pci_write_device_config_8---of 1
-----------
SUMMARY67%of 3
mpls_getttl---of 9
mpls_output49%of 29
-----------
SUMMARY49%of 29
tcp_trace67%of 9
-----------
SUMMARY67%of 9
coredump_elf---of 15
coredump_note_elf---of 11
coredump_notes_elf---of 22
coredump_setup_elf---of 11
coredump_walk_elf---of 1
coredump_writenote_elf---of 4
elf_adjustpins---of 15
elf_check_header---of 11
elf_load_file---of 60
elf_load_psection---of 24
elf_os_pt_note---of 21
elf_os_pt_note_name---of 4
elf_read_from---of 1
elf_read_pintable---of 21
exec_elf_fixup---of 9
exec_elf_makecmds5%of 98
-----------
SUMMARY5%of 98
cache_enter68%of 25
cache_lookup70%of 26
cache_purge73%of 11
cache_purgevfs---of 13
cache_revlookup50%of 16
cache_tree_init100%of 1
cache_zap89%of 18
namecache_rb_cache_RBT_COMPARE100%of 3
nchinit---of 1
-----------
SUMMARY71%of 100
-----------
SUMMARY---of 0
sys_obreak---of 7
uvm_coredump_walk_amap---of 13
uvm_coredump_walkmap---of 73
uvm_grow40%of 5
-----------
SUMMARY40%of 5
pckbc_attach---of 54
pckbc_attach_slot---of 6
pckbc_cleanqueue---of 6
pckbc_cleanqueues---of 13
pckbc_cleanup---of 4
pckbc_cmdresponse---of 15
pckbc_cnattach---of 14
pckbc_enqueue_cmd34%of 18
pckbc_flush---of 8
pckbc_init_slotdata---of 1
pckbc_is_console---of 1
pckbc_poll---of 1
pckbc_poll_cmd25%of 4
pckbc_poll_cmd114%of 36
pckbc_poll_data---of 12
pckbc_poll_data1---of 8
pckbc_release_console---of 3
pckbc_reset---of 18
pckbc_send_cmd---of 4
pckbc_set_inputhandler---of 4
pckbc_set_poll---of 4
pckbc_slot_enable58%of 7
pckbc_start29%of 14
pckbc_stop---of 1
pckbc_submatch---of 4
pckbc_submatch_locators---of 4
pckbc_xt_translation---of 13
pckbcintr---of 1
pckbcintr_internal---of 14
pckbcprint---of 3
-----------
SUMMARY26%of 79
kthread_create75%of 4
kthread_create_deferred---of 4
kthread_exit---of 3
kthread_run_deferred_queue---of 6
-----------
SUMMARY75%of 4
ufs_bmap60%of 5
ufs_bmaparray57%of 46
ufs_getlbns65%of 17
-----------
SUMMARY59%of 68
radio_attach_mi---of 1
radioactivate---of 3
radioattach---of 1
radioclose---of 3
radiodetach---of 5
radioioctl---of 13
radioopen34%of 6
radioprint---of 3
radioprobe---of 1
-----------
SUMMARY34%of 6
uvm_analloc67%of 3
uvm_anfree_list29%of 21
uvm_anon_dropswap50%of 6
uvm_anon_init---of 1
uvm_anon_pagein---of 9
uvm_anon_release---of 14
uvm_anwait---of 1
-----------
SUMMARY37%of 30
_bpf_filter100%of 57
bpf_filter100%of 1
bpf_mem_ldb100%of 3
bpf_mem_ldh100%of 3
bpf_mem_ldw100%of 3
bpf_validate100%of 45
-----------
SUMMARY100%of 112
soo_close67%of 3
soo_ioctl100%of 16
soo_read100%of 1
soo_stat---of 8
soo_write100%of 1
-----------
SUMMARY96%of 21
filt_ufsdetach100%of 1
filt_ufsread78%of 9
filt_ufsvnode80%of 5
filt_ufswrite67%of 3
ufs_access57%of 16
ufs_advlock100%of 1
ufs_chmod62%of 13
ufs_chown54%of 41
ufs_close100%of 3
ufs_create67%of 3
ufs_getattr65%of 14
ufs_ioctl---of 1
ufs_islocked100%of 1
ufs_itimes46%of 22
ufs_kqfilter100%of 5
ufs_link34%of 15
ufs_lock100%of 1
ufs_makeinode45%of 18
ufs_mkdir25%of 16
ufs_mknod40%of 5
ufs_open75%of 4
ufs_pathconf---of 15
ufs_print---of 3
ufs_readdir80%of 10
ufs_readlink60%of 5
ufs_remove60%of 5
ufs_rename53%of 96
ufs_rmdir45%of 9
ufs_setattr57%of 75
ufs_strategy75%of 8
ufs_symlink75%of 4
ufs_unlock100%of 1
ufsfifo_close100%of 3
ufsfifo_read100%of 1
ufsfifo_write100%of 1
ufsspec_close100%of 3
ufsspec_read100%of 1
ufsspec_write100%of 1
-----------
SUMMARY57%of 419
ch_exchange---of 14
ch_get_params---of 5
ch_get_quirks---of 3
ch_getelemstatus---of 4
ch_interpret_sense---of 7
ch_move---of 9
ch_position---of 6
ch_usergetelemstatus---of 57
chattach---of 3
chclose---of 1
chioctl---of 13
chmatch---of 1
chopen29%of 7
-----------
SUMMARY29%of 7
dowait66%of 69
exit1---of 69
exit2---of 3
proc_finish_wait---of 7
proc_free---of 1
process_clear_orphan---of 4
process_reparent---of 15
process_untrace---of 5
process_zap---of 14
reaper---of 11
sys___threxit---of 4
sys_wait438%of 16
sys_waitid---of 7
-----------
SUMMARY12%of 85
gre_send70%of 10
-----------
SUMMARY70%of 10
db_print_ifa---of 17
db_print_sa---of 6
db_show_rtable---of 1
db_show_rtentry---of 11
ifafree100%of 3
ifaref100%of 1
route6_cache44%of 23
route6_mpath100%of 7
route_cache62%of 18
route_init---of 4
route_mpath100%of 3
rt_clone---of 3
rt_getll75%of 4
rt_hash58%of 14
rt_if_linkstate_change74%of 15
rt_if_track77%of 13
rt_ifa_add57%of 16
rt_ifa_addlocal78%of 9
rt_ifa_del75%of 24
rt_ifa_dellocal56%of 9
rt_ifa_purge75%of 12
rt_ifa_purge_walker100%of 1
rt_maskedcopy---of 6
rt_match100%of 5
rt_mpls_clear50%of 4
rt_mpls_set63%of 8
rt_plen2mask50%of 6
rt_plentosa---of 6
rt_putgwroute67%of 9
rt_setgate58%of 7
rt_setgwroute24%of 21
rt_timer_add---of 17
rt_timer_get_expire50%of 4
rt_timer_init---of 1
rt_timer_queue_change100%of 1
rt_timer_queue_count---of 1
rt_timer_queue_flush25%of 16
rt_timer_queue_init---of 1
rt_timer_remove_all20%of 15
rt_timer_timer---of 10
rtalloc100%of 1
rtalloc_mpath100%of 1
rtdeletemsg40%of 15
rtflushclone63%of 8
rtflushclone160%of 10
rtfree57%of 16
rtisvalid75%of 8
rtlabel_id2name---of 6
rtlabel_id2name_locked---of 5
rtlabel_id2sa67%of 6
rtlabel_name2id62%of 13
rtlabel_unref67%of 6
rtredirect---of 27
rtref100%of 1
rtrequest56%of 59
rtrequest_delete58%of 14
-----------
SUMMARY59%of 426
-----------
SUMMARY---of 0
strnlen100%of 5
-----------
SUMMARY100%of 5
uvm_fault67%of 12
uvm_fault_check51%of 65
uvm_fault_lower59%of 81
uvm_fault_lower_lookup80%of 10
uvm_fault_unwire100%of 1
uvm_fault_unwire_locked58%of 21
uvm_fault_upper29%of 42
uvm_fault_upper_lookup71%of 17
uvm_fault_wire84%of 6
uvmfault_anonget3%of 68
uvmfault_init---of 1
uvmfault_lookup39%of 26
uvmfault_relock---of 4
uvmfault_unlockall75%of 12
uvmfault_unlockmaps---of 10
uvmfault_update_stats---of 7
-----------
SUMMARY45%of 361